summaryrefslogtreecommitdiff
path: root/spec/ruby/shared/process/abort.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/shared/process/abort.rb')
-rw-r--r--spec/ruby/shared/process/abort.rb36
1 files changed, 36 insertions, 0 deletions
diff --git a/spec/ruby/shared/process/abort.rb b/spec/ruby/shared/process/abort.rb
new file mode 100644
index 0000000000..935637e1c2
--- /dev/null
+++ b/spec/ruby/shared/process/abort.rb
@@ -0,0 +1,36 @@
+describe :process_abort, shared: true do
+ before :each do
+ @stderr, $stderr = $stderr, IOStub.new
+ end
+
+ after :each do
+ $stderr = @stderr
+ end
+
+ it "raises a SystemExit exception" do
+ -> { @object.abort }.should raise_error(SystemExit)
+ end
+
+ it "sets the exception message to the given message" do
+ -> { @object.abort "message" }.should raise_error { |e| e.message.should == "message" }
+ end
+
+ it "sets the exception status code of 1" do
+ -> { @object.abort }.should raise_error { |e| e.status.should == 1 }
+ end
+
+ it "prints the specified message to STDERR" do
+ -> { @object.abort "a message" }.should raise_error(SystemExit)
+ $stderr.should =~ /a message/
+ end
+
+ it "coerces the argument with #to_str" do
+ str = mock('to_str')
+ str.should_receive(:to_str).any_number_of_times.and_return("message")
+ -> { @object.abort str }.should raise_error(SystemExit, "message")
+ end
+
+ it "raises TypeError when given a non-String object" do
+ -> { @object.abort 123 }.should raise_error(TypeError)
+ end
+end
d>19
-rw-r--r--.github/actions/slack/action.yml16
-rw-r--r--.github/auto_request_review.yml19
-rw-r--r--.github/dependabot.yml4
-rw-r--r--.github/labeler.yml6
-rw-r--r--.github/workflows/annocheck.yml12
-rw-r--r--.github/workflows/auto_request_review.yml3
-rw-r--r--.github/workflows/auto_review_pr.yml33
-rw-r--r--.github/workflows/baseruby.yml13
-rw-r--r--.github/workflows/bundled_gems.yml97
-rw-r--r--.github/workflows/check_dependencies.yml31
-rw-r--r--.github/workflows/check_misc.yml126
-rw-r--r--.github/workflows/codeql-analysis.yml23
-rw-r--r--.github/workflows/compilers.yml544
-rw-r--r--.github/workflows/cygwin.yml71
-rw-r--r--.github/workflows/default_gems_list.yml99
-rw-r--r--.github/workflows/dependabot_automerge.yml18
-rw-r--r--.github/workflows/labeler.yml12
-rw-r--r--.github/workflows/macos.yml82
-rw-r--r--.github/workflows/mingw.yml173
-rw-r--r--.github/workflows/modgc.yml176
-rw-r--r--.github/workflows/parse_y.yml100
-rw-r--r--.github/workflows/post_push.yml85
-rw-r--r--.github/workflows/pr-playground.yml2
-rw-r--r--.github/workflows/prism.yml114
-rw-r--r--.github/workflows/publish.yml107
-rw-r--r--.github/workflows/release.yml18
-rw-r--r--.github/workflows/rjit-bindgen.yml86
-rw-r--r--.github/workflows/rjit.yml114
-rw-r--r--.github/workflows/rust-warnings.yml60
-rw-r--r--.github/workflows/scorecards.yml46
-rw-r--r--.github/workflows/spec_guards.yml19
-rw-r--r--.github/workflows/sync_default_gems.yml77
-rw-r--r--.github/workflows/ubuntu.yml150
-rw-r--r--.github/workflows/wasm.yml28
-rw-r--r--.github/workflows/windows.yml209
-rw-r--r--.github/workflows/wsl.yml70
-rw-r--r--.github/workflows/yjit-macos.yml72
-rw-r--r--.github/workflows/yjit-ubuntu.yml91
-rw-r--r--.github/workflows/zjit-macos.yml214
-rw-r--r--.github/workflows/zjit-ubuntu.yml267
-rw-r--r--.gitignore13
-rw-r--r--.rdoc_options34
-rw-r--r--.travis.yml153
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--COPYING2
-rw-r--r--COPYING.ja2
-rw-r--r--Cargo.lock193
-rw-r--r--Cargo.toml60
-rw-r--r--LEGAL281
-rw-r--r--NEWS.md175
-rw-r--r--README.ja.md12
-rw-r--r--README.md5
-rw-r--r--addr2line.c526
-rw-r--r--array.c3281
-rw-r--r--array.rb321
-rw-r--r--ast.c387
-rw-r--r--ast.rb62
-rwxr-xr-xautogen.sh21
-rw-r--r--benchmark/README.md3
-rw-r--r--benchmark/app_aobench.rb4
-rw-r--r--benchmark/app_fib.rb2
-rw-r--r--benchmark/class_superclass.yml23
-rw-r--r--benchmark/file_join.yml7
-rw-r--r--benchmark/hash_new.yml16
-rw-r--r--benchmark/io_close.yml13
-rw-r--r--benchmark/io_close_contended.yml21
-rw-r--r--benchmark/lib/benchmark_driver/runner/ractor.rb2
-rw-r--r--benchmark/module_eqq.yml7
-rw-r--r--benchmark/nilclass.yml10
-rw-r--r--benchmark/object_allocate.yml1
-rw-r--r--benchmark/object_class.yml40
-rw-r--r--benchmark/object_id.yml4
-rw-r--r--benchmark/ractor_string_fstring.yml18
-rw-r--r--benchmark/scan.yaml16
-rw-r--r--benchmark/search.yaml16
-rw-r--r--benchmark/set.yml261
-rw-r--r--benchmark/string_casecmp.yml2
-rw-r--r--benchmark/string_concat.yml4
-rw-r--r--benchmark/string_fstring.yml16
-rw-r--r--benchmark/string_gsub.yml43
-rw-r--r--benchmark/struct_accessor.yml12
-rw-r--r--benchmark/time_now.yml1
-rw-r--r--benchmark/time_strftime.yml7
-rw-r--r--benchmark/time_xmlschema.yml27
-rw-r--r--benchmark/vm_ivar_get.yml67
-rw-r--r--benchmark/vm_ivar_set_on_instance.yml63
-rw-r--r--bignum.c183
-rwxr-xr-xbootstraptest/runner.rb183
-rw-r--r--bootstraptest/test_autoload.rb12
-rw-r--r--bootstraptest/test_eval.rb2
-rw-r--r--bootstraptest/test_fiber.rb5
-rw-r--r--bootstraptest/test_fork.rb27
-rw-r--r--bootstraptest/test_gc.rb2
-rw-r--r--bootstraptest/test_insns.rb60
-rw-r--r--bootstraptest/test_io.rb4
-rw-r--r--bootstraptest/test_literal.rb8
-rw-r--r--bootstraptest/test_load.rb14
-rw-r--r--bootstraptest/test_method.rb258
-rw-r--r--bootstraptest/test_ractor.rb1714
-rw-r--r--bootstraptest/test_rjit.rb58
-rw-r--r--bootstraptest/test_thread.rb13
-rw-r--r--bootstraptest/test_yjit.rb782
-rw-r--r--bootstraptest/test_yjit_rust_port.rb8
-rw-r--r--box.c1220
-rw-r--r--builtin.c24
-rw-r--r--builtin.h8
-rw-r--r--class.c1105
-rw-r--r--common.mk19898
-rw-r--r--compar.c43
-rw-r--r--compile.c1599
-rw-r--r--complex.c286
-rw-r--r--concurrent_set.c513
-rw-r--r--configure.ac620
-rw-r--r--cont.c514
-rw-r--r--coroutine/amd64/Context.S42
-rw-r--r--coroutine/amd64/Context.h2
-rw-r--r--coroutine/arm32/Context.S7
-rw-r--r--coroutine/arm32/Context.h2
-rw-r--r--coroutine/arm64/Context.S96
-rw-r--r--coroutine/arm64/Context.asm81
-rw-r--r--coroutine/arm64/Context.h26
-rw-r--r--coroutine/loongarch64/Context.S5
-rw-r--r--coroutine/loongarch64/Context.h2
-rw-r--r--coroutine/ppc/Context.S5
-rw-r--r--coroutine/ppc64/Context.S5
-rw-r--r--coroutine/ppc64le/Context.S21
-rw-r--r--coroutine/ppc64le/Context.h2
-rw-r--r--coroutine/riscv64/Context.S5
-rw-r--r--coroutine/riscv64/Context.h2
-rw-r--r--coroutine/win32/Context.h3
-rw-r--r--coroutine/win64/Context.h3
-rw-r--r--coroutine/x86/Context.S5
-rw-r--r--coroutine/x86/Context.h2
-rw-r--r--cygwin/GNUmakefile.in18
-rw-r--r--darray.h133
-rw-r--r--debug.c23
-rw-r--r--debug_counter.h10
-rw-r--r--defs/gmake.mk140
-rw-r--r--defs/id.def9
-rw-r--r--defs/jit.mk96
-rw-r--r--defs/known_errors.def206
-rw-r--r--depend20573
-rw-r--r--dir.c263
-rw-r--r--dir.rb28
-rw-r--r--dln.c97
-rw-r--r--dln.h3
-rw-r--r--dmydln.c20
-rw-r--r--doc/.document13
-rw-r--r--doc/ChangeLog/ChangeLog-1.9.32
-rw-r--r--doc/ChangeLog/ChangeLog-2.0.02
-rw-r--r--doc/ChangeLog/ChangeLog-2.1.04
-rw-r--r--doc/ChangeLog/ChangeLog-2.3.08
-rw-r--r--doc/ChangeLog/ChangeLog-2.4.04
-rw-r--r--doc/NEWS/NEWS-3.0.0.md6
-rw-r--r--doc/NEWS/NEWS-3.1.0.md4
-rw-r--r--doc/NEWS/NEWS-3.2.0.md4
-rw-r--r--doc/NEWS/NEWS-3.4.0.md962
-rw-r--r--doc/NEWS/NEWS-4.0.0.md802
-rw-r--r--doc/_regexp.rdoc104
-rw-r--r--doc/_timezones.rdoc51
-rw-r--r--doc/case_mapping.rdoc116
-rw-r--r--doc/character_selectors.rdoc97
-rw-r--r--doc/command_injection.rdoc37
-rw-r--r--doc/command_line/environment.md173
-rw-r--r--doc/contributing.md12
-rw-r--r--doc/contributing/bug_triaging.rdoc (renamed from doc/bug_triaging.rdoc)0
-rw-r--r--doc/contributing/building_ruby.md212
-rw-r--r--doc/contributing/concurrency_guide.md154
-rw-r--r--doc/contributing/contributing.md35
-rw-r--r--doc/contributing/documentation_guide.md240
-rw-r--r--doc/contributing/dtrace_probes.rdoc (renamed from doc/dtrace_probes.rdoc)0
-rw-r--r--doc/contributing/glossary.md15
-rw-r--r--doc/contributing/making_changes_to_stdlibs.md14
-rw-r--r--doc/contributing/memory_view.md (renamed from doc/memory_view.md)0
-rw-r--r--doc/contributing/reporting_issues.md37
-rw-r--r--doc/contributing/testing_ruby.md109
-rw-r--r--doc/contributing/vm_stack_and_frames.md163
-rw-r--r--doc/date/calendars.rdoc62
-rw-r--r--doc/distribution.md47
-rw-r--r--doc/distribution/distribution.md48
-rw-r--r--doc/distribution/windows.md304
-rw-r--r--doc/encodings.rdoc481
-rw-r--r--doc/examples/files.rdoc8
-rw-r--r--doc/extension.ja.rdoc2
-rw-r--r--doc/extension.rdoc4
-rw-r--r--doc/fiber.md232
-rw-r--r--doc/float.rb128
-rw-r--r--doc/format_specifications.rdoc348
-rw-r--r--doc/forwardable.rd.ja2
-rw-r--r--doc/globals.rdoc422
-rw-r--r--doc/index.md65
-rw-r--r--doc/irb/indexes.md189
-rw-r--r--doc/irb/irb-tools.rd.ja184
-rw-r--r--doc/irb/irb.rd.ja425
-rw-r--r--doc/jit/yjit.md544
-rw-r--r--doc/jit/zjit.md397
-rw-r--r--doc/language/box.md361
-rw-r--r--doc/language/bsearch.rdoc (renamed from doc/bsearch.rdoc)0
-rw-r--r--doc/language/calendars.rdoc62
-rw-r--r--doc/language/case_mapping.rdoc106
-rw-r--r--doc/language/character_selectors.rdoc100
-rw-r--r--doc/language/dig_methods.rdoc (renamed from doc/dig_methods.rdoc)0
-rw-r--r--doc/language/encodings.rdoc482
-rw-r--r--doc/language/exceptions.md521
-rw-r--r--doc/language/fiber.md290
-rw-r--r--doc/language/format_specifications.rdoc354
-rw-r--r--doc/language/globals.md610
-rw-r--r--doc/language/hash_inclusion.rdoc31
-rw-r--r--doc/language/implicit_conversion.rdoc (renamed from doc/implicit_conversion.rdoc)0
-rw-r--r--doc/language/marshal.rdoc318
-rw-r--r--doc/language/option_dump.md265
-rw-r--r--doc/language/options.md688
-rw-r--r--doc/language/packed_data.rdoc722
-rw-r--r--doc/language/ractor.md797
-rw-r--r--doc/language/regexp/methods.rdoc (renamed from doc/regexp/methods.rdoc)0
-rw-r--r--doc/language/regexp/unicode_properties.rdoc718
-rw-r--r--doc/language/signals.rdoc106
-rw-r--r--doc/language/strftime_formatting.rdoc525
-rw-r--r--doc/maintainers.md540
-rw-r--r--doc/marshal.rdoc313
-rw-r--r--doc/matchdata/begin.rdoc12
-rw-r--r--doc/matchdata/bytebegin.rdoc30
-rw-r--r--doc/matchdata/byteend.rdoc30
-rw-r--r--doc/matchdata/end.rdoc12
-rw-r--r--doc/matchdata/offset.rdoc12
-rw-r--r--doc/math/math.rdoc2
-rw-r--r--doc/optparse/argument_converters.rdoc2
-rw-r--r--doc/optparse/option_params.rdoc39
-rw-r--r--doc/optparse/ruby/matched_values.rb6
-rw-r--r--doc/optparse/tutorial.rdoc32
-rw-r--r--doc/packed_data.rdoc589
-rw-r--r--doc/ractor.md952
-rw-r--r--doc/rdoc/markup_reference.rb1287
-rw-r--r--doc/regexp/unicode_properties.rdoc678
-rw-r--r--doc/reline/face.md111
-rw-r--r--doc/rjit/rjit.md45
-rw-r--r--doc/ruby/option_dump.md297
-rw-r--r--doc/ruby/options.md723
-rw-r--r--doc/security.rdoc139
-rw-r--r--doc/security/command_injection.rdoc15
-rw-r--r--doc/security/security.rdoc127
-rw-r--r--doc/signals.rdoc106
-rw-r--r--doc/standard_library.md225
-rw-r--r--doc/standard_library.rdoc132
-rw-r--r--doc/strftime_formatting.rdoc527
-rw-r--r--doc/string.rb421
-rw-r--r--doc/string/aref.rdoc96
-rw-r--r--doc/string/aset.rdoc179
-rw-r--r--doc/string/b.rdoc2
-rw-r--r--doc/string/bytes.rdoc5
-rw-r--r--doc/string/bytesize.rdoc17
-rw-r--r--doc/string/byteslice.rdoc54
-rw-r--r--doc/string/bytesplice.rdoc66
-rw-r--r--doc/string/capitalize.rdoc26
-rw-r--r--doc/string/center.rdoc21
-rw-r--r--doc/string/chars.rdoc4
-rw-r--r--doc/string/chomp.rdoc8
-rw-r--r--doc/string/chop.rdoc7
-rw-r--r--doc/string/chr.rdoc7
-rw-r--r--doc/string/codepoints.rdoc4
-rw-r--r--doc/string/concat.rdoc11
-rw-r--r--doc/string/count.rdoc74
-rw-r--r--doc/string/delete.rdoc75
-rw-r--r--doc/string/delete_prefix.rdoc11
-rw-r--r--doc/string/delete_suffix.rdoc10
-rw-r--r--doc/string/downcase.rdoc20
-rw-r--r--doc/string/dump.rdoc89
-rw-r--r--doc/string/each_byte.rdoc22
-rw-r--r--doc/string/each_char.rdoc26
-rw-r--r--doc/string/each_codepoint.rdoc28
-rw-r--r--doc/string/each_grapheme_cluster.rdoc19
-rw-r--r--doc/string/each_line.rdoc24
-rw-r--r--doc/string/encode.rdoc5
-rw-r--r--doc/string/end_with_p.rdoc16
-rw-r--r--doc/string/eql_p.rdoc18
-rw-r--r--doc/string/force_encoding.rdoc15
-rw-r--r--doc/string/getbyte.rdoc23
-rw-r--r--doc/string/grapheme_clusters.rdoc15
-rw-r--r--doc/string/hash.rdoc19
-rw-r--r--doc/string/index.rdoc30
-rw-r--r--doc/string/insert.rdoc15
-rw-r--r--doc/string/inspect.rdoc38
-rw-r--r--doc/string/intern.rdoc8
-rw-r--r--doc/string/length.rdoc7
-rw-r--r--doc/string/ljust.rdoc15
-rw-r--r--doc/string/new.rdoc44
-rw-r--r--doc/string/ord.rdoc3
-rw-r--r--doc/string/partition.rdoc51
-rw-r--r--doc/string/rindex.rdoc51
-rw-r--r--doc/string/rjust.rdoc9
-rw-r--r--doc/string/rpartition.rdoc55
-rw-r--r--doc/string/scan.rdoc35
-rw-r--r--doc/string/scrub.rdoc27
-rw-r--r--doc/string/split.rdoc131
-rw-r--r--doc/string/squeeze.rdoc33
-rw-r--r--doc/string/start_with_p.rdoc12
-rw-r--r--doc/string/sub.rdoc33
-rw-r--r--doc/string/succ.rdoc52
-rw-r--r--doc/string/sum.rdoc5
-rw-r--r--doc/string/swapcase.rdoc31
-rw-r--r--doc/string/unicode_normalize.rdoc28
-rw-r--r--doc/string/upcase.rdoc27
-rw-r--r--doc/string/upto.rdoc38
-rw-r--r--doc/string/valid_encoding_p.rdoc8
-rw-r--r--doc/stringio/each_byte.rdoc34
-rw-r--r--doc/stringio/each_char.rdoc34
-rw-r--r--doc/stringio/each_codepoint.rdoc36
-rw-r--r--doc/stringio/each_line.md189
-rw-r--r--doc/stringio/getbyte.rdoc31
-rw-r--r--doc/stringio/getc.rdoc34
-rw-r--r--doc/stringio/gets.rdoc99
-rw-r--r--doc/stringio/pread.rdoc65
-rw-r--r--doc/stringio/putc.rdoc82
-rw-r--r--doc/stringio/read.rdoc83
-rw-r--r--doc/stringio/size.rdoc5
-rw-r--r--doc/stringio/stringio.md700
-rw-r--r--doc/strscan/helper_methods.md124
-rw-r--r--doc/strscan/link_refs.txt17
-rw-r--r--doc/strscan/methods/get_byte.md30
-rw-r--r--doc/strscan/methods/get_charpos.md19
-rw-r--r--doc/strscan/methods/get_pos.md14
-rw-r--r--doc/strscan/methods/getch.md43
-rw-r--r--doc/strscan/methods/scan.md51
-rw-r--r--doc/strscan/methods/scan_until.md52
-rw-r--r--doc/strscan/methods/set_pos.md27
-rw-r--r--doc/strscan/methods/skip.md43
-rw-r--r--doc/strscan/methods/skip_until.md49
-rw-r--r--doc/strscan/methods/terminate.md30
-rw-r--r--doc/strscan/strscan.md544
-rw-r--r--doc/syntax.rdoc5
-rw-r--r--doc/syntax/assignment.rdoc4
-rw-r--r--doc/syntax/calling_methods.rdoc97
-rw-r--r--doc/syntax/comments.rdoc2
-rw-r--r--doc/syntax/control_expressions.rdoc2
-rw-r--r--doc/syntax/exceptions.rdoc2
-rw-r--r--doc/syntax/keywords.rdoc (renamed from doc/keywords.rdoc)0
-rw-r--r--doc/syntax/layout.rdoc118
-rw-r--r--doc/syntax/literals.rdoc199
-rw-r--r--doc/syntax/methods.rdoc1
-rw-r--r--doc/syntax/pattern_matching.rdoc8
-rw-r--r--doc/syntax/refinements.rdoc5
-rw-r--r--doc/windows.md234
-rw-r--r--doc/yjit/yjit.md517
-rw-r--r--doc/yjit/yjit_hacking.md75
-rw-r--r--enc/Makefile.in5
-rw-r--r--enc/ascii.c4
-rw-r--r--enc/big5.c12
-rw-r--r--enc/cp949.c4
-rw-r--r--enc/depend73
-rw-r--r--enc/emacs_mule.c4
-rw-r--r--enc/euc_jp.c4
-rw-r--r--enc/euc_kr.c8
-rw-r--r--enc/euc_tw.c4
-rw-r--r--enc/gb18030.c4
-rw-r--r--enc/gbk.c4
-rw-r--r--enc/iso_8859_1.c6
-rw-r--r--enc/iso_8859_10.c6
-rw-r--r--enc/iso_8859_11.c4
-rw-r--r--enc/iso_8859_13.c6
-rw-r--r--enc/iso_8859_14.c6
-rw-r--r--enc/iso_8859_15.c6
-rw-r--r--enc/iso_8859_16.c6
-rw-r--r--enc/iso_8859_2.c6
-rw-r--r--enc/iso_8859_3.c6
-rw-r--r--enc/iso_8859_4.c6
-rw-r--r--enc/iso_8859_5.c6
-rw-r--r--enc/iso_8859_6.c4
-rw-r--r--enc/iso_8859_7.c6
-rw-r--r--enc/iso_8859_8.c4
-rw-r--r--enc/iso_8859_9.c6
-rw-r--r--enc/jis/props.h.blt17
-rw-r--r--enc/koi8_r.c4
-rw-r--r--enc/koi8_u.c4
-rw-r--r--enc/shift_jis.c4
-rw-r--r--enc/trans/ibm864-tbl.rb126
-rw-r--r--enc/trans/iso2022.trans148
-rw-r--r--enc/trans/single_byte.trans1
-rw-r--r--enc/unicode.c12
-rw-r--r--enc/unicode/15.0.0/casefold.h7629
-rw-r--r--enc/unicode/15.0.0/name2ctype.h45690
-rw-r--r--enc/unicode/17.0.0/casefold.h8013
-rw-r--r--enc/unicode/17.0.0/name2ctype.h49725
-rw-r--r--enc/us_ascii.c4
-rw-r--r--enc/utf_16be.c4
-rw-r--r--enc/utf_16le.c4
-rw-r--r--enc/utf_32be.c4
-rw-r--r--enc/utf_32le.c4
-rw-r--r--enc/utf_8.c4
-rw-r--r--enc/windows_1250.c6
-rw-r--r--enc/windows_1251.c6
-rw-r--r--enc/windows_1252.c6
-rw-r--r--enc/windows_1253.c6
-rw-r--r--enc/windows_1254.c6
-rw-r--r--enc/windows_1257.c6
-rw-r--r--enc/windows_31j.c4
-rw-r--r--encoding.c423
-rw-r--r--enum.c276
-rw-r--r--enumerator.c596
-rw-r--r--error.c822
-rw-r--r--eval.c439
-rw-r--r--eval_intern.h7
-rw-r--r--eval_jump.c28
-rw-r--r--ext/-test-/RUBY_ALIGNOF/depend1
-rw-r--r--ext/-test-/abi/depend3
-rw-r--r--ext/-test-/arith_seq/beg_len_step/depend1
-rw-r--r--ext/-test-/arith_seq/extract/depend1
-rw-r--r--ext/-test-/array/concat/depend1
-rw-r--r--ext/-test-/array/resize/depend1
-rw-r--r--ext/-test-/asan/asan.c24
-rw-r--r--ext/-test-/asan/extconf.rb2
-rw-r--r--ext/-test-/bignum/depend19
-rw-r--r--ext/-test-/box/yay1/extconf.rb1
-rw-r--r--ext/-test-/box/yay1/yay1.c28
-rw-r--r--ext/-test-/box/yay1/yay1.def3
-rw-r--r--ext/-test-/box/yay1/yay1.h4
-rw-r--r--ext/-test-/box/yay2/extconf.rb1
-rw-r--r--ext/-test-/box/yay2/yay2.c28
-rw-r--r--ext/-test-/box/yay2/yay2.def3
-rw-r--r--ext/-test-/box/yay2/yay2.h4
-rw-r--r--ext/-test-/bug-14834/bug-14384.c39
-rw-r--r--ext/-test-/bug-14834/bug-14834.c39
-rw-r--r--ext/-test-/bug-14834/depend321
-rw-r--r--ext/-test-/bug-3571/depend1
-rw-r--r--ext/-test-/bug-5832/depend1
-rw-r--r--ext/-test-/bug_reporter/depend1
-rw-r--r--ext/-test-/class/depend2
-rw-r--r--ext/-test-/class/init.c1
-rw-r--r--ext/-test-/cxxanyargs/cxxanyargs.cpp26
-rw-r--r--ext/-test-/debug/depend3
-rw-r--r--ext/-test-/dln/empty/depend1
-rw-r--r--ext/-test-/econv/append.c2
-rw-r--r--ext/-test-/econv/depend336
-rw-r--r--ext/-test-/ensure_and_callcc/depend163
-rw-r--r--ext/-test-/ensure_and_callcc/ensure_and_callcc.c58
-rw-r--r--ext/-test-/ensure_and_callcc/extconf.rb5
-rw-r--r--ext/-test-/enumerator_kw/depend1
-rw-r--r--ext/-test-/eval/depend162
-rw-r--r--ext/-test-/exception/depend4
-rw-r--r--ext/-test-/fatal/depend3
-rw-r--r--ext/-test-/fatal/invalid.c6
-rw-r--r--ext/-test-/file/depend4
-rw-r--r--ext/-test-/float/depend2
-rw-r--r--ext/-test-/funcall/depend1
-rw-r--r--ext/-test-/gvl/call_without_gvl/depend1
-rw-r--r--ext/-test-/hash/depend2
-rw-r--r--ext/-test-/integer/depend3
-rw-r--r--ext/-test-/integer/my_integer.c6
-rw-r--r--ext/-test-/iseq_load/depend1
-rw-r--r--ext/-test-/iter/depend3
-rw-r--r--ext/-test-/load/dot.dot/depend1
-rw-r--r--ext/-test-/load/protect/depend1
-rw-r--r--ext/-test-/load/resolve_symbol_resolver/depend163
-rw-r--r--ext/-test-/load/resolve_symbol_resolver/resolve_symbol_resolver.c7
-rw-r--r--ext/-test-/load/resolve_symbol_target/depend164
-rw-r--r--ext/-test-/load/resolve_symbol_target/resolve_symbol_target.def4
-rw-r--r--ext/-test-/load/stringify_symbols/depend164
-rw-r--r--ext/-test-/load/stringify_target/depend164
-rw-r--r--ext/-test-/load/stringify_target/stringify_target.def4
-rw-r--r--ext/-test-/marshal/compat/depend1
-rw-r--r--ext/-test-/marshal/internal_ivar/depend1
-rw-r--r--ext/-test-/marshal/internal_ivar/internal_ivar.c15
-rw-r--r--ext/-test-/marshal/usr/depend1
-rw-r--r--ext/-test-/memory_status/depend1
-rw-r--r--ext/-test-/memory_view/depend1
-rw-r--r--ext/-test-/method/depend2
-rw-r--r--ext/-test-/notimplement/depend1
-rw-r--r--ext/-test-/num2int/depend1
-rw-r--r--ext/-test-/path_to_class/depend1
-rw-r--r--ext/-test-/popen_deadlock/depend1
-rw-r--r--ext/-test-/postponed_job/depend1
-rw-r--r--ext/-test-/printf/depend1
-rw-r--r--ext/-test-/proc/depend3
-rw-r--r--ext/-test-/public_header_warnings/extconf.rb9
-rw-r--r--ext/-test-/random/depend3
-rw-r--r--ext/-test-/random/loop.c11
-rw-r--r--ext/-test-/rational/depend1
-rw-r--r--ext/-test-/rb_call_super_kw/depend1
-rw-r--r--ext/-test-/recursion/depend1
-rw-r--r--ext/-test-/regexp/depend2
-rw-r--r--ext/-test-/sanitizers/depend162
-rw-r--r--ext/-test-/sanitizers/extconf.rb2
-rw-r--r--ext/-test-/sanitizers/sanitizers.c36
-rw-r--r--ext/-test-/scan_args/depend1
-rw-r--r--ext/-test-/scheduler/extconf.rb2
-rw-r--r--ext/-test-/scheduler/scheduler.c92
-rw-r--r--ext/-test-/st/foreach/depend1
-rw-r--r--ext/-test-/st/numhash/depend1
-rw-r--r--ext/-test-/st/update/depend1
-rw-r--r--ext/-test-/stack/depend179
-rw-r--r--ext/-test-/stack/extconf.rb3
-rw-r--r--ext/-test-/stack/stack.c35
-rw-r--r--ext/-test-/string/depend20
-rw-r--r--ext/-test-/string/fstring.c6
-rw-r--r--ext/-test-/string/set_len.c8
-rw-r--r--ext/-test-/struct/depend5
-rw-r--r--ext/-test-/symbol/depend2
-rw-r--r--ext/-test-/thread/id/depend163
-rw-r--r--ext/-test-/thread/id/extconf.rb3
-rw-r--r--ext/-test-/thread/id/id.c15
-rw-r--r--ext/-test-/thread/instrumentation/depend1
-rw-r--r--ext/-test-/thread/instrumentation/instrumentation.c4
-rw-r--r--ext/-test-/thread/lock_native_thread/depend163
-rw-r--r--ext/-test-/thread_fd/depend161
-rw-r--r--ext/-test-/thread_fd/extconf.rb2
-rw-r--r--ext/-test-/thread_fd/thread_fd.c30
-rw-r--r--ext/-test-/time/depend3
-rw-r--r--ext/-test-/time/leap_second.c15
-rw-r--r--ext/-test-/tracepoint/depend2
-rw-r--r--ext/-test-/tracepoint/gc_hook.c26
-rw-r--r--ext/-test-/tracepoint/tracepoint.c10
-rw-r--r--ext/-test-/typeddata/depend1
-rw-r--r--ext/-test-/vm/depend1
-rw-r--r--ext/-test-/wait/depend1
-rw-r--r--ext/-test-/win32/dln/extconf.rb1
-rw-r--r--ext/.document3
-rw-r--r--ext/cgi/escape/depend1
-rw-r--r--ext/cgi/escape/escape.c30
-rw-r--r--ext/continuation/depend1
-rw-r--r--ext/coverage/coverage.c9
-rw-r--r--ext/coverage/depend3
-rw-r--r--ext/coverage/lib/coverage.rb5
-rw-r--r--ext/date/date.gemspec6
-rw-r--r--ext/date/date_core.c547
-rw-r--r--ext/date/date_parse.c3
-rw-r--r--ext/date/date_strptime.c6
-rw-r--r--ext/date/depend4
-rw-r--r--ext/date/extconf.rb1
-rw-r--r--ext/date/lib/date.rb2
-rw-r--r--ext/date/prereq.mk2
-rw-r--r--ext/date/zonetab.h1250
-rw-r--r--ext/date/zonetab.list7
-rw-r--r--ext/digest/bubblebabble/depend1
-rw-r--r--ext/digest/defs.h22
-rw-r--r--ext/digest/depend1
-rw-r--r--ext/digest/digest.c42
-rw-r--r--ext/digest/digest.h37
-rw-r--r--ext/digest/digest_conf.rb18
-rw-r--r--ext/digest/lib/digest/version.rb3
-rw-r--r--ext/digest/md5/depend2
-rw-r--r--ext/digest/md5/md5cc.h12
-rw-r--r--ext/digest/md5/md5init.c1
-rw-r--r--ext/digest/rmd160/depend2
-rw-r--r--ext/digest/sha1/depend2
-rw-r--r--ext/digest/sha1/sha1.c8
-rw-r--r--ext/digest/sha1/sha1cc.h8
-rw-r--r--ext/digest/sha2/depend2
-rw-r--r--ext/digest/sha2/sha2cc.h39
-rw-r--r--ext/digest/test.sh30
-rw-r--r--ext/erb/escape/escape.c41
-rw-r--r--ext/erb/escape/extconf.rb1
-rw-r--r--ext/etc/depend1
-rw-r--r--ext/etc/etc.c70
-rw-r--r--ext/etc/etc.gemspec5
-rw-r--r--ext/etc/extconf.rb48
-rwxr-xr-xext/extmk.rb61
-rw-r--r--ext/fcntl/depend1
-rw-r--r--ext/fcntl/fcntl.c48
-rw-r--r--ext/fcntl/fcntl.gemspec2
-rw-r--r--ext/fiddle/closure.c458
-rw-r--r--ext/fiddle/closure.h8
-rw-r--r--ext/fiddle/conversions.c383
-rw-r--r--ext/fiddle/conversions.h55
-rw-r--r--ext/fiddle/depend1396
-rw-r--r--ext/fiddle/extconf.rb256
-rw-r--r--ext/fiddle/fiddle.c712
-rw-r--r--ext/fiddle/fiddle.gemspec60
-rw-r--r--ext/fiddle/fiddle.h240
-rw-r--r--ext/fiddle/function.c496
-rw-r--r--ext/fiddle/function.h8
-rw-r--r--ext/fiddle/handle.c591
-rw-r--r--ext/fiddle/lib/fiddle.rb103
-rw-r--r--ext/fiddle/lib/fiddle/closure.rb74
-rw-r--r--ext/fiddle/lib/fiddle/cparser.rb278
-rw-r--r--ext/fiddle/lib/fiddle/function.rb29
-rw-r--r--ext/fiddle/lib/fiddle/import.rb322
-rw-r--r--ext/fiddle/lib/fiddle/pack.rb149
-rw-r--r--ext/fiddle/lib/fiddle/struct.rb539
-rw-r--r--ext/fiddle/lib/fiddle/types.rb73
-rw-r--r--ext/fiddle/lib/fiddle/value.rb120
-rw-r--r--ext/fiddle/lib/fiddle/version.rb3
-rw-r--r--ext/fiddle/memory_view.c321
-rw-r--r--ext/fiddle/pinned.c123
-rw-r--r--ext/fiddle/pointer.c887
-rw-r--r--ext/fiddle/win32/fficonfig.h29
-rw-r--r--ext/fiddle/win32/libffi-3.2.1-mswin.patch191
-rwxr-xr-xext/fiddle/win32/libffi-config.rb48
-rw-r--r--ext/fiddle/win32/libffi.mk.tmpl96
-rw-r--r--ext/io/console/console.c244
-rw-r--r--ext/io/console/depend4
-rw-r--r--ext/io/console/extconf.rb30
-rw-r--r--ext/io/console/io-console.gemspec3
-rw-r--r--ext/io/console/win32_vk.inc325
-rw-r--r--ext/io/console/win32_vk.list2
-rw-r--r--ext/io/nonblock/depend1
-rw-r--r--ext/io/nonblock/extconf.rb2
-rw-r--r--ext/io/nonblock/io-nonblock.gemspec4
-rw-r--r--ext/io/nonblock/nonblock.c4
-rw-r--r--ext/io/wait/depend2
-rw-r--r--ext/io/wait/extconf.rb23
-rw-r--r--ext/io/wait/io-wait.gemspec23
-rw-r--r--ext/io/wait/wait.c418
-rw-r--r--ext/json/fbuffer/fbuffer.h278
-rw-r--r--ext/json/generator/depend8
-rw-r--r--ext/json/generator/extconf.rb16
-rw-r--r--ext/json/generator/generator.c2353
-rw-r--r--ext/json/generator/generator.h177
-rw-r--r--ext/json/json.gemspec94
-rw-r--r--ext/json/json.h101
-rw-r--r--ext/json/lib/json.rb104
-rw-r--r--ext/json/lib/json/add/bigdecimal.rb4
-rw-r--r--ext/json/lib/json/add/complex.rb2
-rw-r--r--ext/json/lib/json/add/core.rb3
-rw-r--r--ext/json/lib/json/add/date.rb2
-rw-r--r--ext/json/lib/json/add/date_time.rb2
-rw-r--r--ext/json/lib/json/add/exception.rb2
-rw-r--r--ext/json/lib/json/add/ostruct.rb2
-rw-r--r--ext/json/lib/json/add/range.rb2
-rw-r--r--ext/json/lib/json/add/rational.rb2
-rw-r--r--ext/json/lib/json/add/regexp.rb2
-rw-r--r--ext/json/lib/json/add/string.rb35
-rw-r--r--ext/json/lib/json/add/struct.rb2
-rw-r--r--ext/json/lib/json/add/symbol.rb12
-rw-r--r--ext/json/lib/json/add/time.rb13
-rw-r--r--ext/json/lib/json/common.rb942
-rw-r--r--ext/json/lib/json/ext.rb40
-rw-r--r--ext/json/lib/json/ext/generator/state.rb103
-rw-r--r--ext/json/lib/json/generic_object.rb10
-rw-r--r--ext/json/lib/json/version.rb10
-rw-r--r--ext/json/parser/depend8
-rw-r--r--ext/json/parser/extconf.rb34
-rw-r--r--ext/json/parser/parser.c3377
-rw-r--r--ext/json/parser/parser.h96
-rw-r--r--ext/json/parser/parser.rl971
-rw-r--r--ext/json/parser/prereq.mk13
-rw-r--r--ext/json/simd/conf.rb24
-rw-r--r--ext/json/simd/simd.h218
-rw-r--r--ext/json/vendor/fpconv.c480
-rw-r--r--ext/json/vendor/jeaiii-ltoa.h267
-rw-r--r--ext/json/vendor/ryu.h819
-rw-r--r--ext/monitor/depend1
-rw-r--r--ext/monitor/lib/monitor.rb10
-rw-r--r--ext/monitor/monitor.c156
-rw-r--r--ext/objspace/depend13
-rw-r--r--ext/objspace/object_tracing.c47
-rw-r--r--ext/objspace/objspace.c179
-rw-r--r--ext/objspace/objspace_dump.c213
-rw-r--r--ext/openssl/History.md249
-rw-r--r--ext/openssl/depend65
-rw-r--r--ext/openssl/extconf.rb97
-rw-r--r--ext/openssl/lib/openssl.rb16
-rw-r--r--ext/openssl/lib/openssl/bn.rb2
-rw-r--r--ext/openssl/lib/openssl/buffering.rb62
-rw-r--r--ext/openssl/lib/openssl/cipher.rb2
-rw-r--r--ext/openssl/lib/openssl/digest.rb4
-rw-r--r--ext/openssl/lib/openssl/marshal.rb2
-rw-r--r--ext/openssl/lib/openssl/pkey.rb120
-rw-r--r--ext/openssl/lib/openssl/ssl.rb97
-rw-r--r--ext/openssl/lib/openssl/version.rb3
-rw-r--r--ext/openssl/lib/openssl/x509.rb21
-rw-r--r--ext/openssl/openssl.gemspec7
-rw-r--r--ext/openssl/openssl_missing.c40
-rw-r--r--ext/openssl/openssl_missing.h208
-rw-r--r--ext/openssl/ossl.c597
-rw-r--r--ext/openssl/ossl.h45
-rw-r--r--ext/openssl/ossl_asn1.c901
-rw-r--r--ext/openssl/ossl_asn1.h36
-rw-r--r--ext/openssl/ossl_bio.c8
-rw-r--r--ext/openssl/ossl_bio.h2
-rw-r--r--ext/openssl/ossl_bn.c597
-rw-r--r--ext/openssl/ossl_bn.h3
-rw-r--r--ext/openssl/ossl_cipher.c477
-rw-r--r--ext/openssl/ossl_cipher.h16
-rw-r--r--ext/openssl/ossl_config.c26
-rw-r--r--ext/openssl/ossl_config.h2
-rw-r--r--ext/openssl/ossl_digest.c143
-rw-r--r--ext/openssl/ossl_digest.h15
-rw-r--r--ext/openssl/ossl_engine.c148
-rw-r--r--ext/openssl/ossl_engine.h5
-rw-r--r--ext/openssl/ossl_hmac.c72
-rw-r--r--ext/openssl/ossl_hmac.h5
-rw-r--r--ext/openssl/ossl_kdf.c95
-rw-r--r--ext/openssl/ossl_ns_spki.c80
-rw-r--r--ext/openssl/ossl_ns_spki.h6
-rw-r--r--ext/openssl/ossl_ocsp.c471
-rw-r--r--ext/openssl/ossl_ocsp.h9
-rw-r--r--ext/openssl/ossl_pkcs12.c105
-rw-r--r--ext/openssl/ossl_pkcs12.h5
-rw-r--r--ext/openssl/ossl_pkcs7.c395
-rw-r--r--ext/openssl/ossl_pkcs7.h24
-rw-r--r--ext/openssl/ossl_pkey.c343
-rw-r--r--ext/openssl/ossl_pkey.h211
-rw-r--r--ext/openssl/ossl_pkey_dh.c101
-rw-r--r--ext/openssl/ossl_pkey_dsa.c71
-rw-r--r--ext/openssl/ossl_pkey_ec.c426
-rw-r--r--ext/openssl/ossl_pkey_rsa.c161
-rw-r--r--ext/openssl/ossl_provider.c9
-rw-r--r--ext/openssl/ossl_rand.c27
-rw-r--r--ext/openssl/ossl_rand.h5
-rw-r--r--ext/openssl/ossl_ssl.c947
-rw-r--r--ext/openssl/ossl_ssl.h18
-rw-r--r--ext/openssl/ossl_ssl_session.c190
-rw-r--r--ext/openssl/ossl_ts.c226
-rw-r--r--ext/openssl/ossl_ts.h2
-rw-r--r--ext/openssl/ossl_x509.c39
-rw-r--r--ext/openssl/ossl_x509.h21
-rw-r--r--ext/openssl/ossl_x509attr.c138
-rw-r--r--ext/openssl/ossl_x509cert.c196
-rw-r--r--ext/openssl/ossl_x509crl.c169
-rw-r--r--ext/openssl/ossl_x509ext.c117
-rw-r--r--ext/openssl/ossl_x509name.c157
-rw-r--r--ext/openssl/ossl_x509req.c119
-rw-r--r--ext/openssl/ossl_x509revoked.c72
-rw-r--r--ext/openssl/ossl_x509store.c113
-rw-r--r--ext/pathname/depend174
-rw-r--r--ext/pathname/extconf.rb3
-rw-r--r--ext/pathname/lib/pathname.rb605
-rw-r--r--ext/pathname/pathname.c1668
-rw-r--r--ext/pathname/pathname.gemspec32
-rw-r--r--ext/psych/depend5
-rw-r--r--ext/psych/extconf.rb7
-rw-r--r--ext/psych/lib/psych.rb59
-rw-r--r--ext/psych/lib/psych/class_loader.rb1
-rw-r--r--ext/psych/lib/psych/core_ext.rb21
-rw-r--r--ext/psych/lib/psych/nodes/node.rb7
-rw-r--r--ext/psych/lib/psych/scalar_scanner.rb22
-rw-r--r--ext/psych/lib/psych/versions.rb4
-rw-r--r--ext/psych/lib/psych/visitors/to_ruby.rb57
-rw-r--r--ext/psych/lib/psych/visitors/yaml_tree.rb53
-rw-r--r--ext/psych/psych.c3
-rw-r--r--ext/psych/psych.gemspec2
-rw-r--r--ext/psych/psych_emitter.c276
-rw-r--r--ext/psych/psych_parser.c525
-rw-r--r--ext/psych/psych_to_ruby.c5
-rw-r--r--ext/psych/psych_yaml_tree.c1
-rw-r--r--ext/pty/depend2
-rw-r--r--ext/pty/pty.c39
-rw-r--r--ext/rbconfig/sizeof/depend2
-rw-r--r--ext/ripper/depend12
-rw-r--r--ext/ripper/eventids2.c1
-rw-r--r--ext/ripper/lib/ripper/lexer.rb11
-rw-r--r--ext/ripper/ripper_init.c.tmpl16
-rw-r--r--ext/ripper/tools/generate.rb6
-rw-r--r--ext/socket/ancdata.c10
-rw-r--r--ext/socket/basicsocket.c6
-rw-r--r--ext/socket/depend75
-rw-r--r--ext/socket/extconf.rb1
-rw-r--r--ext/socket/getaddrinfo.c7
-rw-r--r--ext/socket/getnameinfo.c18
-rw-r--r--ext/socket/ifaddr.c2
-rw-r--r--ext/socket/init.c58
-rw-r--r--ext/socket/ipsocket.c1325
-rw-r--r--ext/socket/lib/socket.rb819
-rw-r--r--ext/socket/raddrinfo.c303
-rw-r--r--ext/socket/rubysocket.h60
-rw-r--r--ext/socket/socket.c98
-rw-r--r--ext/socket/sockssocket.c7
-rw-r--r--ext/socket/tcpserver.c2
-rw-r--r--ext/socket/tcpsocket.c47
-rw-r--r--ext/socket/udpsocket.c57
-rw-r--r--ext/socket/unixsocket.c43
-rw-r--r--ext/stringio/depend2
-rw-r--r--ext/stringio/extconf.rb2
-rw-r--r--ext/stringio/stringio.c349
-rw-r--r--ext/stringio/stringio.gemspec2
-rw-r--r--ext/strscan/depend1
-rw-r--r--ext/strscan/extconf.rb5
-rw-r--r--ext/strscan/lib/strscan/strscan.rb25
-rw-r--r--ext/strscan/strscan.c1596
-rw-r--r--ext/strscan/strscan.gemspec14
-rw-r--r--ext/win32/lib/win32/registry.rb302
-rw-r--r--ext/win32/lib/win32/resolv.rb113
-rw-r--r--ext/win32/lib/win32/sspi.rb338
-rw-r--r--ext/win32/resolv/extconf.rb6
-rw-r--r--ext/win32/resolv/resolv.c211
-rw-r--r--ext/win32/win32-registry.gemspec29
-rw-r--r--ext/win32ole/.document1
-rw-r--r--ext/win32ole/depend12
-rw-r--r--ext/win32ole/extconf.rb45
-rw-r--r--ext/win32ole/lib/win32ole.rb32
-rw-r--r--ext/win32ole/lib/win32ole/property.rb29
-rw-r--r--ext/win32ole/win32ole.c4142
-rw-r--r--ext/win32ole/win32ole.gemspec34
-rw-r--r--ext/win32ole/win32ole.h155
-rw-r--r--ext/win32ole/win32ole_error.c96
-rw-r--r--ext/win32ole/win32ole_error.h9
-rw-r--r--ext/win32ole/win32ole_event.c1279
-rw-r--r--ext/win32ole/win32ole_event.h6
-rw-r--r--ext/win32ole/win32ole_method.c954
-rw-r--r--ext/win32ole/win32ole_method.h16
-rw-r--r--ext/win32ole/win32ole_param.c440
-rw-r--r--ext/win32ole/win32ole_param.h8
-rw-r--r--ext/win32ole/win32ole_record.c608
-rw-r--r--ext/win32ole/win32ole_record.h10
-rw-r--r--ext/win32ole/win32ole_type.c922
-rw-r--r--ext/win32ole/win32ole_type.h8
-rw-r--r--ext/win32ole/win32ole_typelib.c848
-rw-r--r--ext/win32ole/win32ole_typelib.h11
-rw-r--r--ext/win32ole/win32ole_variable.c385
-rw-r--r--ext/win32ole/win32ole_variable.h8
-rw-r--r--ext/win32ole/win32ole_variant.c737
-rw-r--r--ext/win32ole/win32ole_variant.h9
-rw-r--r--ext/win32ole/win32ole_variant_m.c153
-rw-r--r--ext/win32ole/win32ole_variant_m.h7
-rw-r--r--ext/zlib/depend1
-rw-r--r--ext/zlib/zlib.c362
-rw-r--r--file.c853
-rw-r--r--gc.c13891
-rw-r--r--gc.rb717
-rw-r--r--gc/README.md37
-rw-r--r--gc/default/default.c9602
-rw-r--r--gc/default/extconf.rb5
-rw-r--r--gc/extconf_base.rb14
-rw-r--r--gc/gc.h265
-rw-r--r--gc/gc_impl.h126
-rw-r--r--gc/mmtk/.gitignore1
-rw-r--r--gc/mmtk/Cargo.lock1108
-rw-r--r--gc/mmtk/Cargo.toml42
-rw-r--r--gc/mmtk/cbindgen.toml36
-rw-r--r--gc/mmtk/depend18
-rw-r--r--gc/mmtk/extconf.rb24
-rw-r--r--gc/mmtk/mmtk.c1554
-rw-r--r--gc/mmtk/mmtk.h172
-rw-r--r--gc/mmtk/src/abi.rs336
-rw-r--r--gc/mmtk/src/active_plan.rs56
-rw-r--r--gc/mmtk/src/api.rs486
-rw-r--r--gc/mmtk/src/binding.rs129
-rw-r--r--gc/mmtk/src/collection.rs109
-rw-r--r--gc/mmtk/src/heap/mod.rs4
-rw-r--r--gc/mmtk/src/heap/ruby_heap_trigger.rs105
-rw-r--r--gc/mmtk/src/lib.rs161
-rw-r--r--gc/mmtk/src/object_model.rs124
-rw-r--r--gc/mmtk/src/pinning_registry.rs187
-rw-r--r--gc/mmtk/src/reference_glue.rs26
-rw-r--r--gc/mmtk/src/scanning.rs291
-rw-r--r--gc/mmtk/src/utils.rs161
-rw-r--r--gc/mmtk/src/weak_proc.rs318
-rw-r--r--gem_prelude.rb1
-rw-r--r--gems/bundled_gems68
-rw-r--r--gems/lib/rake/extensiontask.rb2
-rw-r--r--goruby.c10
-rw-r--r--hash.c2126
-rw-r--r--hash.rb40
-rw-r--r--id_table.c122
-rw-r--r--id_table.h15
-rw-r--r--imemo.c416
-rw-r--r--include/ruby/assert.h12
-rw-r--r--include/ruby/atomic.h452
-rw-r--r--include/ruby/backward.h6
-rw-r--r--include/ruby/backward/2/rmodule.h2
-rw-r--r--include/ruby/backward/cxxanyargs.hpp29
-rw-r--r--include/ruby/debug.h64
-rw-r--r--include/ruby/fiber/scheduler.h107
-rw-r--r--include/ruby/intern.h1
-rw-r--r--include/ruby/internal/abi.h2
-rw-r--r--include/ruby/internal/anyargs.h22
-rw-r--r--include/ruby/internal/arithmetic/int.h2
-rw-r--r--include/ruby/internal/arithmetic/intptr_t.h12
-rw-r--r--include/ruby/internal/attr/deprecated.h9
-rw-r--r--include/ruby/internal/attr/forceinline.h2
-rw-r--r--include/ruby/internal/attr/noexcept.h2
-rw-r--r--include/ruby/internal/attr/nonstring.h40
-rw-r--r--include/ruby/internal/attr/restrict.h2
-rw-r--r--include/ruby/internal/compiler_is/msvc.h13
-rw-r--r--include/ruby/internal/config.h2
-rw-r--r--include/ruby/internal/core/rarray.h4
-rw-r--r--include/ruby/internal/core/rbasic.h16
-rw-r--r--include/ruby/internal/core/rclass.h2
-rw-r--r--include/ruby/internal/core/rdata.h35
-rw-r--r--include/ruby/internal/core/robject.h40
-rw-r--r--include/ruby/internal/core/rstring.h57
-rw-r--r--include/ruby/internal/core/rstruct.h12
-rw-r--r--include/ruby/internal/core/rtypeddata.h264
-rw-r--r--include/ruby/internal/ctype.h4
-rw-r--r--include/ruby/internal/encoding/coderange.h2
-rw-r--r--include/ruby/internal/encoding/string.h6
-rw-r--r--include/ruby/internal/error.h11
-rw-r--r--include/ruby/internal/eval.h15
-rw-r--r--include/ruby/internal/fl_type.h226
-rw-r--r--include/ruby/internal/gc.h5
-rw-r--r--include/ruby/internal/globals.h2
-rw-r--r--include/ruby/internal/has/builtin.h4
-rw-r--r--include/ruby/internal/intern/array.h8
-rw-r--r--include/ruby/internal/intern/complex.h4
-rw-r--r--include/ruby/internal/intern/cont.h11
-rw-r--r--include/ruby/internal/intern/enumerator.h12
-rw-r--r--include/ruby/internal/intern/error.h20
-rw-r--r--include/ruby/internal/intern/file.h3
-rw-r--r--include/ruby/internal/intern/hash.h14
-rw-r--r--include/ruby/internal/intern/io.h2
-rw-r--r--include/ruby/internal/intern/object.h3
-rw-r--r--include/ruby/internal/intern/proc.h12
-rw-r--r--include/ruby/internal/intern/select.h2
-rw-r--r--include/ruby/internal/intern/select/win32.h4
-rw-r--r--include/ruby/internal/intern/set.h111
-rw-r--r--include/ruby/internal/intern/string.h31
-rw-r--r--include/ruby/internal/intern/thread.h8
-rw-r--r--include/ruby/internal/intern/vm.h7
-rw-r--r--include/ruby/internal/iterator.h45
-rw-r--r--include/ruby/internal/memory.h141
-rw-r--r--include/ruby/internal/newobj.h38
-rw-r--r--include/ruby/internal/scan_args.h2
-rw-r--r--include/ruby/internal/special_consts.h4
-rw-r--r--include/ruby/internal/static_assert.h5
-rw-r--r--include/ruby/internal/stdbool.h16
-rw-r--r--include/ruby/internal/symbol.h75
-rw-r--r--include/ruby/internal/value_type.h11
-rw-r--r--include/ruby/internal/warning_push.h2
-rw-r--r--include/ruby/internal/xmalloc.h104
-rw-r--r--include/ruby/io.h310
-rw-r--r--include/ruby/onigmo.h13
-rw-r--r--include/ruby/ractor.h16
-rw-r--r--include/ruby/random.h2
-rw-r--r--include/ruby/ruby.h15
-rw-r--r--include/ruby/thread.h20
-rw-r--r--include/ruby/version.h4
-rw-r--r--include/ruby/win32.h51
-rw-r--r--inits.c20
-rw-r--r--insns.def252
-rw-r--r--internal.h3
-rw-r--r--internal/array.h3
-rw-r--r--internal/basic_operators.h2
-rw-r--r--internal/bignum.h32
-rw-r--r--internal/bits.h113
-rw-r--r--internal/box.h83
-rw-r--r--internal/class.h713
-rw-r--r--internal/cmdlineopt.h7
-rw-r--r--internal/concurrent_set.h21
-rw-r--r--internal/cont.h1
-rw-r--r--internal/encoding.h5
-rw-r--r--internal/error.h42
-rw-r--r--internal/eval.h10
-rw-r--r--internal/fixnum.h1
-rw-r--r--internal/gc.h101
-rw-r--r--internal/hash.h3
-rw-r--r--internal/imemo.h138
-rw-r--r--internal/inits.h4
-rw-r--r--internal/io.h37
-rw-r--r--internal/load.h2
-rw-r--r--internal/numeric.h49
-rw-r--r--internal/object.h2
-rw-r--r--internal/parse.h20
-rw-r--r--internal/proc.h2
-rw-r--r--internal/ractor.h4
-rw-r--r--internal/range.h6
-rw-r--r--internal/re.h9
-rw-r--r--internal/sanitizers.h127
-rw-r--r--internal/set_table.h70
-rw-r--r--internal/signal.h1
-rw-r--r--internal/st.h2
-rw-r--r--internal/string.h71
-rw-r--r--internal/struct.h77
-rw-r--r--internal/symbol.h7
-rw-r--r--internal/thread.h53
-rw-r--r--internal/time.h4
-rw-r--r--internal/variable.h24
-rw-r--r--internal/vm.h17
-rw-r--r--io.c762
-rw-r--r--io_buffer.c349
-rw-r--r--iseq.c681
-rw-r--r--iseq.h24
-rw-r--r--jit.c799
-rw-r--r--jit/Cargo.toml6
-rw-r--r--jit/src/lib.rs38
-rw-r--r--jit_hook.rb12
-rw-r--r--jit_undef.rb4
-rw-r--r--kernel.rb86
-rw-r--r--lex.c.blt85
-rw-r--r--lib/English.gemspec11
-rw-r--r--lib/English.rb50
-rw-r--r--lib/benchmark.gemspec30
-rw-r--r--lib/benchmark.rb584
-rw-r--r--lib/bundled_gems.rb256
-rw-r--r--lib/bundler.rb190
-rw-r--r--lib/bundler/build_metadata.rb18
-rw-r--r--lib/bundler/bundler.gemspec10
-rw-r--r--lib/bundler/capistrano.rb20
-rw-r--r--lib/bundler/checksum.rb40
-rw-r--r--lib/bundler/cli.rb385
-rw-r--r--lib/bundler/cli/add.rb14
-rw-r--r--lib/bundler/cli/cache.rb13
-rw-r--r--lib/bundler/cli/check.rb6
-rw-r--r--lib/bundler/cli/common.rb25
-rw-r--r--lib/bundler/cli/config.rb3
-rw-r--r--lib/bundler/cli/console.rb23
-rw-r--r--lib/bundler/cli/doctor.rb178
-rw-r--r--lib/bundler/cli/doctor/diagnose.rb167
-rw-r--r--lib/bundler/cli/doctor/ssl.rb249
-rw-r--r--lib/bundler/cli/exec.rb32
-rw-r--r--lib/bundler/cli/fund.rb2
-rw-r--r--lib/bundler/cli/gem.rb158
-rw-r--r--lib/bundler/cli/info.rb12
-rw-r--r--lib/bundler/cli/inject.rb60
-rw-r--r--lib/bundler/cli/install.rb112
-rw-r--r--lib/bundler/cli/issue.rb8
-rw-r--r--lib/bundler/cli/list.rb35
-rw-r--r--lib/bundler/cli/lock.rb44
-rw-r--r--lib/bundler/cli/outdated.rb46
-rw-r--r--lib/bundler/cli/plugin.rb6
-rw-r--r--lib/bundler/cli/pristine.rb6
-rw-r--r--lib/bundler/cli/show.rb12
-rw-r--r--lib/bundler/cli/update.rb10
-rw-r--r--lib/bundler/cli/viz.rb31
-rw-r--r--lib/bundler/compact_index_client.rb9
-rw-r--r--lib/bundler/compact_index_client/cache.rb2
-rw-r--r--lib/bundler/compact_index_client/gem_parser.rb32
-rw-r--r--lib/bundler/compact_index_client/parser.rb73
-rw-r--r--lib/bundler/compact_index_client/updater.rb3
-rw-r--r--lib/bundler/current_ruby.rb72
-rw-r--r--lib/bundler/definition.rb888
-rw-r--r--lib/bundler/dependency.rb141
-rw-r--r--lib/bundler/deployment.rb65
-rw-r--r--lib/bundler/digest.rb2
-rw-r--r--lib/bundler/dsl.rb269
-rw-r--r--lib/bundler/endpoint_specification.rb33
-rw-r--r--lib/bundler/env.rb2
-rw-r--r--lib/bundler/environment_preserver.rb1
-rw-r--r--lib/bundler/errors.rb57
-rw-r--r--lib/bundler/feature_flag.rb45
-rw-r--r--lib/bundler/fetcher.rb85
-rw-r--r--lib/bundler/fetcher/compact_index.rb4
-rw-r--r--lib/bundler/fetcher/dependency.rb3
-rw-r--r--lib/bundler/fetcher/downloader.rb40
-rw-r--r--lib/bundler/fetcher/gem_remote_fetcher.rb6
-rw-r--r--lib/bundler/force_platform.rb2
-rw-r--r--lib/bundler/friendly_errors.rb9
-rw-r--r--lib/bundler/gem_helpers.rb127
-rw-r--r--lib/bundler/gem_version_promoter.rb2
-rw-r--r--lib/bundler/graph.rb152
-rw-r--r--lib/bundler/index.rb16
-rw-r--r--lib/bundler/injector.rb27
-rw-r--r--lib/bundler/inline.rb67
-rw-r--r--lib/bundler/installer.rb77
-rw-r--r--lib/bundler/installer/gem_installer.rb17
-rw-r--r--lib/bundler/installer/parallel_installer.rb5
-rw-r--r--lib/bundler/installer/standalone.rb7
-rw-r--r--lib/bundler/lazy_specification.rb197
-rw-r--r--lib/bundler/lockfile_generator.rb4
-rw-r--r--lib/bundler/lockfile_parser.rb35
-rw-r--r--lib/bundler/man/bundle-add.171
-rw-r--r--lib/bundler/man/bundle-add.1.ronn75
-rw-r--r--lib/bundler/man/bundle-binstubs.118
-rw-r--r--lib/bundler/man/bundle-binstubs.1.ronn15
-rw-r--r--lib/bundler/man/bundle-cache.126
-rw-r--r--lib/bundler/man/bundle-cache.1.ronn24
-rw-r--r--lib/bundler/man/bundle-check.113
-rw-r--r--lib/bundler/man/bundle-check.1.ronn7
-rw-r--r--lib/bundler/man/bundle-clean.16
-rw-r--r--lib/bundler/man/bundle-config.1339
-rw-r--r--lib/bundler/man/bundle-config.1.ronn230
-rw-r--r--lib/bundler/man/bundle-console.110
-rw-r--r--lib/bundler/man/bundle-console.1.ronn9
-rw-r--r--lib/bundler/man/bundle-doctor.153
-rw-r--r--lib/bundler/man/bundle-doctor.1.ronn54
-rw-r--r--lib/bundler/man/bundle-env.19
-rw-r--r--lib/bundler/man/bundle-env.1.ronn10
-rw-r--r--lib/bundler/man/bundle-exec.116
-rw-r--r--lib/bundler/man/bundle-exec.1.ronn11
-rw-r--r--lib/bundler/man/bundle-fund.122
-rw-r--r--lib/bundler/man/bundle-fund.1.ronn25
-rw-r--r--lib/bundler/man/bundle-gem.194
-rw-r--r--lib/bundler/man/bundle-gem.1.ronn47
-rw-r--r--lib/bundler/man/bundle-help.16
-rw-r--r--lib/bundler/man/bundle-info.111
-rw-r--r--lib/bundler/man/bundle-info.1.ronn8
-rw-r--r--lib/bundler/man/bundle-init.110
-rw-r--r--lib/bundler/man/bundle-init.1.ronn5
-rw-r--r--lib/bundler/man/bundle-inject.123
-rw-r--r--lib/bundler/man/bundle-inject.1.ronn24
-rw-r--r--lib/bundler/man/bundle-install.188
-rw-r--r--lib/bundler/man/bundle-install.1.ronn149
-rw-r--r--lib/bundler/man/bundle-issue.145
-rw-r--r--lib/bundler/man/bundle-issue.1.ronn37
-rw-r--r--lib/bundler/man/bundle-licenses.19
-rw-r--r--lib/bundler/man/bundle-licenses.1.ronn10
-rw-r--r--lib/bundler/man/bundle-list.111
-rw-r--r--lib/bundler/man/bundle-list.1.ronn10
-rw-r--r--lib/bundler/man/bundle-lock.131
-rw-r--r--lib/bundler/man/bundle-lock.1.ronn29
-rw-r--r--lib/bundler/man/bundle-open.18
-rw-r--r--lib/bundler/man/bundle-open.1.ronn3
-rw-r--r--lib/bundler/man/bundle-outdated.117
-rw-r--r--lib/bundler/man/bundle-outdated.1.ronn12
-rw-r--r--lib/bundler/man/bundle-platform.16
-rw-r--r--lib/bundler/man/bundle-plugin.152
-rw-r--r--lib/bundler/man/bundle-plugin.1.ronn51
-rw-r--r--lib/bundler/man/bundle-pristine.16
-rw-r--r--lib/bundler/man/bundle-pristine.1.ronn2
-rw-r--r--lib/bundler/man/bundle-remove.114
-rw-r--r--lib/bundler/man/bundle-remove.1.ronn11
-rw-r--r--lib/bundler/man/bundle-show.16
-rw-r--r--lib/bundler/man/bundle-update.128
-rw-r--r--lib/bundler/man/bundle-update.1.ronn26
-rw-r--r--lib/bundler/man/bundle-version.16
-rw-r--r--lib/bundler/man/bundle-viz.130
-rw-r--r--lib/bundler/man/bundle-viz.1.ronn32
-rw-r--r--lib/bundler/man/bundle.115
-rw-r--r--lib/bundler/man/bundle.1.ronn9
-rw-r--r--lib/bundler/man/gemfile.539
-rw-r--r--lib/bundler/man/gemfile.5.ronn34
-rw-r--r--lib/bundler/man/index.txt6
-rw-r--r--lib/bundler/match_metadata.rb13
-rw-r--r--lib/bundler/match_platform.rb43
-rw-r--r--lib/bundler/materialization.rb59
-rw-r--r--lib/bundler/plugin.rb25
-rw-r--r--lib/bundler/plugin/api/source.rb5
-rw-r--r--lib/bundler/plugin/index.rb6
-rw-r--r--lib/bundler/plugin/installer.rb12
-rw-r--r--lib/bundler/plugin/installer/path.rb8
-rw-r--r--lib/bundler/plugin/source_list.rb2
-rw-r--r--lib/bundler/process_lock.rb24
-rw-r--r--lib/bundler/remote_specification.rb7
-rw-r--r--lib/bundler/resolver.rb126
-rw-r--r--lib/bundler/resolver/base.rb17
-rw-r--r--lib/bundler/resolver/candidate.rb43
-rw-r--r--lib/bundler/resolver/package.rb24
-rw-r--r--lib/bundler/resolver/spec_group.rb49
-rw-r--r--lib/bundler/resolver/strategy.rb40
-rw-r--r--lib/bundler/retry.rb2
-rw-r--r--lib/bundler/ruby_dsl.rb20
-rw-r--r--lib/bundler/ruby_version.rb12
-rw-r--r--lib/bundler/rubygems_ext.rb417
-rw-r--r--lib/bundler/rubygems_gem_installer.rb51
-rw-r--r--lib/bundler/rubygems_integration.rb119
-rw-r--r--lib/bundler/runtime.rb75
-rw-r--r--lib/bundler/self_manager.rb64
-rw-r--r--lib/bundler/settings.rb68
-rw-r--r--lib/bundler/settings/validator.rb23
-rw-r--r--lib/bundler/setup.rb3
-rw-r--r--lib/bundler/shared_helpers.rb81
-rw-r--r--lib/bundler/similarity_detector.rb63
-rw-r--r--lib/bundler/source.rb4
-rw-r--r--lib/bundler/source/gemspec.rb5
-rw-r--r--lib/bundler/source/git.rb155
-rw-r--r--lib/bundler/source/git/git_proxy.rb37
-rw-r--r--lib/bundler/source/metadata.rb5
-rw-r--r--lib/bundler/source/path.rb44
-rw-r--r--lib/bundler/source/rubygems.rb86
-rw-r--r--lib/bundler/source/rubygems/remote.rb14
-rw-r--r--lib/bundler/source_list.rb91
-rw-r--r--lib/bundler/source_map.rb7
-rw-r--r--lib/bundler/spec_set.rb280
-rw-r--r--lib/bundler/stub_specification.rb31
-rw-r--r--lib/bundler/templates/Executable11
-rw-r--r--lib/bundler/templates/Executable.bundler109
-rw-r--r--lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt136
-rw-r--r--lib/bundler/templates/newgem/Gemfile.tt4
-rw-r--r--lib/bundler/templates/newgem/README.md.tt10
-rw-r--r--lib/bundler/templates/newgem/Rakefile.tt5
-rw-r--r--lib/bundler/templates/newgem/circleci/config.yml.tt12
-rw-r--r--lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt2
-rw-r--r--lib/bundler/templates/newgem/ext/newgem/extconf-go.rb.tt11
-rw-r--r--lib/bundler/templates/newgem/ext/newgem/go.mod.tt5
-rw-r--r--lib/bundler/templates/newgem/ext/newgem/newgem-go.c.tt2
-rw-r--r--lib/bundler/templates/newgem/ext/newgem/newgem.go.tt31
-rw-r--r--lib/bundler/templates/newgem/github/workflows/main.yml.tt38
-rw-r--r--lib/bundler/templates/newgem/gitlab-ci.yml.tt9
-rw-r--r--lib/bundler/templates/newgem/lib/newgem.rb.tt2
-rw-r--r--lib/bundler/templates/newgem/newgem.gemspec.tt22
-rw-r--r--lib/bundler/ui/shell.rb46
-rw-r--r--lib/bundler/ui/silent.rb13
-rw-r--r--lib/bundler/uri_credentials_filter.rb2
-rw-r--r--lib/bundler/vendor/connection_pool/lib/connection_pool.rb70
-rw-r--r--lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb117
-rw-r--r--lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb2
-rw-r--r--lib/bundler/vendor/fileutils/.document1
-rw-r--r--lib/bundler/vendor/fileutils/lib/fileutils.rb135
-rw-r--r--lib/bundler/vendor/net-http-persistent/.document1
-rw-r--r--lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb152
-rw-r--r--lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb3
-rw-r--r--lib/bundler/vendor/pub_grub/.document1
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/basic_package_source.rb28
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/strategy.rb42
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb28
-rw-r--r--lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb46
-rw-r--r--lib/bundler/vendor/securerandom/lib/securerandom.rb102
-rw-r--r--lib/bundler/vendor/thor/.document1
-rw-r--r--lib/bundler/vendor/thor/lib/thor.rb13
-rw-r--r--lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb56
-rw-r--r--lib/bundler/vendor/thor/lib/thor/group.rb11
-rw-r--r--lib/bundler/vendor/thor/lib/thor/parser/argument.rb5
-rw-r--r--lib/bundler/vendor/thor/lib/thor/parser/option.rb4
-rw-r--r--lib/bundler/vendor/thor/lib/thor/parser/options.rb5
-rw-r--r--lib/bundler/vendor/thor/lib/thor/runner.rb4
-rw-r--r--lib/bundler/vendor/thor/lib/thor/shell/basic.rb28
-rw-r--r--lib/bundler/vendor/thor/lib/thor/shell/html.rb2
-rw-r--r--lib/bundler/vendor/thor/lib/thor/shell/table_printer.rb26
-rw-r--r--lib/bundler/vendor/thor/lib/thor/util.rb2
-rw-r--r--lib/bundler/vendor/thor/lib/thor/version.rb2
-rw-r--r--lib/bundler/vendor/tsort/.document1
-rw-r--r--lib/bundler/vendor/uri/.document1
-rw-r--r--lib/bundler/vendor/uri/lib/uri.rb18
-rw-r--r--lib/bundler/vendor/uri/lib/uri/common.rb123
-rw-r--r--lib/bundler/vendor/uri/lib/uri/file.rb8
-rw-r--r--lib/bundler/vendor/uri/lib/uri/ftp.rb2
-rw-r--r--lib/bundler/vendor/uri/lib/uri/generic.rb114
-rw-r--r--lib/bundler/vendor/uri/lib/uri/http.rb16
-rw-r--r--lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb42
-rw-r--r--lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb29
-rw-r--r--lib/bundler/vendor/uri/lib/uri/version.rb4
-rw-r--r--lib/bundler/vendored_net_http.rb23
-rw-r--r--lib/bundler/vendored_securerandom.rb12
-rw-r--r--lib/bundler/version.rb12
-rw-r--r--lib/bundler/vlad.rb15
-rw-r--r--lib/bundler/worker.rb2
-rw-r--r--lib/bundler/yaml_serializer.rb11
-rw-r--r--lib/cgi.rb300
-rw-r--r--lib/cgi/cgi.gemspec42
-rw-r--r--lib/cgi/cookie.rb209
-rw-r--r--lib/cgi/core.rb900
-rw-r--r--lib/cgi/escape.rb232
-rw-r--r--lib/cgi/html.rb1035
-rw-r--r--lib/cgi/session.rb562
-rw-r--r--lib/cgi/session/pstore.rb88
-rw-r--r--lib/cgi/util.rb261
-rw-r--r--lib/delegate.gemspec2
-rw-r--r--lib/delegate.rb45
-rw-r--r--lib/did_you_mean.rb24
-rw-r--r--lib/did_you_mean/version.rb2
-rw-r--r--lib/erb.gemspec38
-rw-r--r--lib/erb.rb1271
-rw-r--r--lib/erb/compiler.rb25
-rw-r--r--lib/erb/def_method.rb2
-rw-r--r--lib/erb/erb.gemspec37
-rw-r--r--lib/erb/util.rb68
-rw-r--r--lib/erb/version.rb4
-rw-r--r--lib/error_highlight/base.rb428
-rw-r--r--lib/error_highlight/core_ext.rb35
-rw-r--r--lib/error_highlight/error_highlight.gemspec2
-rw-r--r--lib/error_highlight/formatter.rb63
-rw-r--r--lib/error_highlight/version.rb2
-rw-r--r--lib/fileutils.gemspec2
-rw-r--r--lib/fileutils.rb109
-rw-r--r--lib/find.rb1
-rw-r--r--lib/forwardable.rb51
-rw-r--r--lib/forwardable/forwardable.gemspec2
-rw-r--r--lib/forwardable/impl.rb17
-rw-r--r--lib/ipaddr.gemspec4
-rw-r--r--lib/ipaddr.rb60
-rw-r--r--lib/irb.rb1608
-rw-r--r--lib/irb/.document1
-rw-r--r--lib/irb/cmd/nop.rb4
-rw-r--r--lib/irb/color.rb262
-rw-r--r--lib/irb/color_printer.rb55
-rw-r--r--lib/irb/command.rb23
-rw-r--r--lib/irb/command/backtrace.rb17
-rw-r--r--lib/irb/command/base.rb62
-rw-r--r--lib/irb/command/break.rb17
-rw-r--r--lib/irb/command/catch.rb17
-rw-r--r--lib/irb/command/chws.rb40
-rw-r--r--lib/irb/command/context.rb16
-rw-r--r--lib/irb/command/continue.rb17
-rw-r--r--lib/irb/command/debug.rb71
-rw-r--r--lib/irb/command/delete.rb17
-rw-r--r--lib/irb/command/disable_irb.rb19
-rw-r--r--lib/irb/command/edit.rb63
-rw-r--r--lib/irb/command/exit.rb18
-rw-r--r--lib/irb/command/finish.rb17
-rw-r--r--lib/irb/command/force_exit.rb18
-rw-r--r--lib/irb/command/help.rb83
-rw-r--r--lib/irb/command/history.rb45
-rw-r--r--lib/irb/command/info.rb17
-rw-r--r--lib/irb/command/internal_helpers.rb27
-rw-r--r--lib/irb/command/irb_info.rb33
-rw-r--r--lib/irb/command/load.rb91
-rw-r--r--lib/irb/command/ls.rb155
-rw-r--r--lib/irb/command/measure.rb49
-rw-r--r--lib/irb/command/next.rb17
-rw-r--r--lib/irb/command/pushws.rb65
-rw-r--r--lib/irb/command/show_doc.rb51
-rw-r--r--lib/irb/command/show_source.rb74
-rw-r--r--lib/irb/command/step.rb17
-rw-r--r--lib/irb/command/subirb.rb123
-rw-r--r--lib/irb/command/whereami.rb23
-rw-r--r--lib/irb/completion.rb477
-rw-r--r--lib/irb/context.rb674
-rw-r--r--lib/irb/debug.rb130
-rw-r--r--lib/irb/debug/ui.rb103
-rw-r--r--lib/irb/default_commands.rb260
-rw-r--r--lib/irb/easter-egg.rb148
-rw-r--r--lib/irb/ext/change-ws.rb37
-rw-r--r--lib/irb/ext/eval_history.rb149
-rw-r--r--lib/irb/ext/loader.rb127
-rw-r--r--lib/irb/ext/multi-irb.rb258
-rw-r--r--lib/irb/ext/tracer.rb39
-rw-r--r--lib/irb/ext/use-loader.rb67
-rw-r--r--lib/irb/ext/workspaces.rb36
-rw-r--r--lib/irb/frame.rb80
-rw-r--r--lib/irb/help.rb28
-rw-r--r--lib/irb/helper_method.rb29
-rw-r--r--lib/irb/helper_method/base.rb16
-rw-r--r--lib/irb/helper_method/conf.rb11
-rw-r--r--lib/irb/history.rb87
-rw-r--r--lib/irb/init.rb538
-rw-r--r--lib/irb/input-method.rb513
-rw-r--r--lib/irb/inspector.rb130
-rw-r--r--lib/irb/irb.gemspec46
-rw-r--r--lib/irb/lc/error.rb52
-rw-r--r--lib/irb/lc/help-message55
-rw-r--r--lib/irb/lc/ja/error.rb53
-rw-r--r--lib/irb/lc/ja/help-message58
-rw-r--r--lib/irb/locale.rb153
-rw-r--r--lib/irb/nesting_parser.rb237
-rw-r--r--lib/irb/notifier.rb230
-rw-r--r--lib/irb/output-method.rb80
-rw-r--r--lib/irb/pager.rb91
-rw-r--r--lib/irb/ruby-lex.rb474
-rw-r--r--lib/irb/ruby_logo.aa80
-rw-r--r--lib/irb/source_finder.rb139
-rw-r--r--lib/irb/statement.rb80
-rw-r--r--lib/irb/version.rb11
-rw-r--r--lib/irb/workspace.rb189
-rw-r--r--lib/irb/ws-for-case-2.rb9
-rw-r--r--lib/irb/xmp.rb164
-rw-r--r--lib/logger.rb747
-rw-r--r--lib/logger/errors.rb9
-rw-r--r--lib/logger/formatter.rb36
-rw-r--r--lib/logger/log_device.rb207
-rw-r--r--lib/logger/logger.gemspec22
-rw-r--r--lib/logger/period.rb47
-rw-r--r--lib/logger/severity.rb38
-rw-r--r--lib/logger/version.rb5
-rw-r--r--lib/mkmf.rb56
-rw-r--r--lib/net/http.rb217
-rw-r--r--lib/net/http/backward.rb40
-rw-r--r--lib/net/http/exceptions.rb3
-rw-r--r--lib/net/http/generic_request.rb45
-rw-r--r--lib/net/http/header.rb12
-rw-r--r--lib/net/http/net-http.gemspec10
-rw-r--r--lib/net/http/requests.rb16
-rw-r--r--lib/net/http/response.rb3
-rw-r--r--lib/net/http/responses.rb72
-rw-r--r--lib/net/net-protocol.gemspec5
-rw-r--r--lib/net/protocol.rb15
-rw-r--r--lib/open-uri.rb73
-rw-r--r--lib/open3/version.rb1
-rw-r--r--lib/optparse.rb188
-rw-r--r--lib/optparse/optparse.gemspec13
-rw-r--r--lib/ostruct.gemspec24
-rw-r--r--lib/ostruct.rb489
-rw-r--r--lib/pathname.rb74
-rw-r--r--lib/pp.gemspec3
-rw-r--r--lib/pp.rb158
-rw-r--r--lib/prettyprint.rb1
-rw-r--r--lib/prism.rb40
-rw-r--r--lib/prism/desugar_compiler.rb186
-rw-r--r--lib/prism/ffi.rb188
-rw-r--r--lib/prism/lex_compat.rb108
-rw-r--r--lib/prism/lex_ripper.rb64
-rw-r--r--lib/prism/node_ext.rb100
-rw-r--r--lib/prism/pack.rb2
-rw-r--r--lib/prism/parse_result.rb241
-rw-r--r--lib/prism/parse_result/comments.rb1
-rw-r--r--lib/prism/parse_result/errors.rb66
-rw-r--r--lib/prism/parse_result/newlines.rb58
-rw-r--r--lib/prism/pattern.rb1
-rw-r--r--lib/prism/polyfill/append_as_bytes.rb15
-rw-r--r--lib/prism/polyfill/scan_byte.rb14
-rw-r--r--lib/prism/polyfill/warn.rb36
-rw-r--r--lib/prism/prism.gemspec28
-rw-r--r--lib/prism/relocation.rb505
-rw-r--r--lib/prism/string_query.rb31
-rw-r--r--lib/prism/translation.rb9
-rw-r--r--lib/prism/translation/parser.rb79
-rw-r--r--lib/prism/translation/parser/builder.rb62
-rw-r--r--lib/prism/translation/parser/compiler.rb528
-rw-r--r--lib/prism/translation/parser/lexer.rb520
-rw-r--r--lib/prism/translation/parser/rubocop.rb73
-rw-r--r--lib/prism/translation/parser33.rb12
-rw-r--r--lib/prism/translation/parser34.rb12
-rw-r--r--lib/prism/translation/parser_current.rb26
-rw-r--r--lib/prism/translation/parser_versions.rb36
-rw-r--r--lib/prism/translation/ripper.rb111
-rw-r--r--lib/prism/translation/ripper/filter.rb53
-rw-r--r--lib/prism/translation/ripper/lexer.rb128
-rw-r--r--lib/prism/translation/ripper/sexp.rb1
-rw-r--r--lib/prism/translation/ruby_parser.rb450
-rw-r--r--lib/pstore.gemspec32
-rw-r--r--lib/pstore.rb731
-rw-r--r--lib/random/formatter.rb9
-rw-r--r--lib/rdoc.rb213
-rw-r--r--lib/rdoc/.document2
-rw-r--r--lib/rdoc/alias.rb111
-rw-r--r--lib/rdoc/anon_class.rb10
-rw-r--r--lib/rdoc/any_method.rb379
-rw-r--r--lib/rdoc/attr.rb175
-rw-r--r--lib/rdoc/class_module.rb801
-rw-r--r--lib/rdoc/code_object.rb421
-rw-r--r--lib/rdoc/code_objects.rb5
-rw-r--r--lib/rdoc/comment.rb229
-rw-r--r--lib/rdoc/constant.rb186
-rw-r--r--lib/rdoc/context.rb1264
-rw-r--r--lib/rdoc/context/section.rb233
-rw-r--r--lib/rdoc/cross_reference.rb228
-rw-r--r--lib/rdoc/encoding.rb120
-rw-r--r--lib/rdoc/erb_partial.rb18
-rw-r--r--lib/rdoc/erbio.rb37
-rw-r--r--lib/rdoc/extend.rb9
-rw-r--r--lib/rdoc/generator.rb51
-rw-r--r--lib/rdoc/generator/darkfish.rb786
-rw-r--r--lib/rdoc/generator/json_index.rb300
-rw-r--r--lib/rdoc/generator/markup.rb159
-rw-r--r--lib/rdoc/generator/pot.rb99
-rw-r--r--lib/rdoc/generator/pot/message_extractor.rb68
-rw-r--r--lib/rdoc/generator/pot/po.rb84
-rw-r--r--lib/rdoc/generator/pot/po_entry.rb141
-rw-r--r--lib/rdoc/generator/ri.rb30
-rw-r--r--lib/rdoc/generator/template/darkfish/.document0
-rw-r--r--lib/rdoc/generator/template/darkfish/_footer.rhtml5
-rw-r--r--lib/rdoc/generator/template/darkfish/_head.rhtml20
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml19
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml33
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml15
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml9
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml15
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml15
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml12
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_navigation.rhtml11
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml32
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml11
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml14
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml11
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml39
-rw-r--r--lib/rdoc/generator/template/darkfish/class.rhtml180
-rw-r--r--lib/rdoc/generator/template/darkfish/css/fonts.css167
-rw-r--r--lib/rdoc/generator/template/darkfish/css/rdoc.css687
-rw-r--r--lib/rdoc/generator/template/darkfish/fonts/Lato-Light.ttfbin94668 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/fonts/Lato-LightItalic.ttfbin94196 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/fonts/Lato-Regular.ttfbin96184 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/fonts/Lato-RegularItalic.ttfbin95316 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttfbin138268 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttfbin138680 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/images/add.pngbin733 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/images/arrow_up.pngbin372 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/images/brick.pngbin452 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/images/brick_link.pngbin764 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/images/bug.pngbin774 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/images/bullet_black.pngbin211 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/images/bullet_toggle_minus.pngbin207 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/images/bullet_toggle_plus.pngbin209 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/images/date.pngbin626 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/images/delete.pngbin715 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/images/find.pngbin659 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/images/loadingAnimation.gifbin5886 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/images/macFFBgHack.pngbin207 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/images/package.pngbin853 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/images/page_green.pngbin621 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/images/page_white_text.pngbin342 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/images/page_white_width.pngbin309 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/images/plugin.pngbin591 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/images/ruby.pngbin592 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/images/tag_blue.pngbin1880 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/images/tag_green.pngbin613 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/images/transparent.pngbin97 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/images/wrench.pngbin610 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/images/wrench_orange.pngbin584 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/images/zoom.pngbin692 -> 0 bytes-rw-r--r--lib/rdoc/generator/template/darkfish/index.rhtml22
-rw-r--r--lib/rdoc/generator/template/darkfish/js/darkfish.js97
-rw-r--r--lib/rdoc/generator/template/darkfish/js/search.js110
-rw-r--r--lib/rdoc/generator/template/darkfish/page.rhtml18
-rw-r--r--lib/rdoc/generator/template/darkfish/servlet_not_found.rhtml18
-rw-r--r--lib/rdoc/generator/template/darkfish/servlet_root.rhtml62
-rw-r--r--lib/rdoc/generator/template/darkfish/table_of_contents.rhtml59
-rw-r--r--lib/rdoc/generator/template/json_index/.document1
-rw-r--r--lib/rdoc/generator/template/json_index/js/navigation.js105
-rw-r--r--lib/rdoc/generator/template/json_index/js/searcher.js229
-rw-r--r--lib/rdoc/ghost_method.rb6
-rw-r--r--lib/rdoc/i18n.rb10
-rw-r--r--lib/rdoc/i18n/locale.rb102
-rw-r--r--lib/rdoc/i18n/text.rb126
-rw-r--r--lib/rdoc/include.rb9
-rw-r--r--lib/rdoc/known_classes.rb74
-rw-r--r--lib/rdoc/markdown.rb16783
-rw-r--r--lib/rdoc/markdown/entities.rb2131
-rw-r--r--lib/rdoc/markdown/literals.rb454
-rw-r--r--lib/rdoc/markup.rb235
-rw-r--r--lib/rdoc/markup/attr_changer.rb22
-rw-r--r--lib/rdoc/markup/attr_span.rb35
-rw-r--r--lib/rdoc/markup/attribute_manager.rb405
-rw-r--r--lib/rdoc/markup/attributes.rb70
-rw-r--r--lib/rdoc/markup/blank_line.rb27
-rw-r--r--lib/rdoc/markup/block_quote.rb14
-rw-r--r--lib/rdoc/markup/document.rb164
-rw-r--r--lib/rdoc/markup/formatter.rb265
-rw-r--r--lib/rdoc/markup/hard_break.rb31
-rw-r--r--lib/rdoc/markup/heading.rb78
-rw-r--r--lib/rdoc/markup/include.rb42
-rw-r--r--lib/rdoc/markup/indented_paragraph.rb47
-rw-r--r--lib/rdoc/markup/list.rb101
-rw-r--r--lib/rdoc/markup/list_item.rb99
-rw-r--r--lib/rdoc/markup/paragraph.rb28
-rw-r--r--lib/rdoc/markup/parser.rb585
-rw-r--r--lib/rdoc/markup/pre_process.rb298
-rw-r--r--lib/rdoc/markup/raw.rb69
-rw-r--r--lib/rdoc/markup/regexp_handling.rb40
-rw-r--r--lib/rdoc/markup/rule.rb20
-rw-r--r--lib/rdoc/markup/table.rb56
-rw-r--r--lib/rdoc/markup/to_ansi.rb93
-rw-r--r--lib/rdoc/markup/to_bs.rb102
-rw-r--r--lib/rdoc/markup/to_html.rb452
-rw-r--r--lib/rdoc/markup/to_html_crossref.rb175
-rw-r--r--lib/rdoc/markup/to_html_snippet.rb287
-rw-r--r--lib/rdoc/markup/to_joined_paragraph.rb46
-rw-r--r--lib/rdoc/markup/to_label.rb74
-rw-r--r--lib/rdoc/markup/to_markdown.rb191
-rw-r--r--lib/rdoc/markup/to_rdoc.rb352
-rw-r--r--lib/rdoc/markup/to_table_of_contents.rb88
-rw-r--r--lib/rdoc/markup/to_test.rb69
-rw-r--r--lib/rdoc/markup/to_tt_only.rb120
-rw-r--r--lib/rdoc/markup/verbatim.rb83
-rw-r--r--lib/rdoc/meta_method.rb6
-rw-r--r--lib/rdoc/method_attr.rb418
-rw-r--r--lib/rdoc/mixin.rb120
-rw-r--r--lib/rdoc/normal_class.rb92
-rw-r--r--lib/rdoc/normal_module.rb73
-rw-r--r--lib/rdoc/options.rb1331
-rw-r--r--lib/rdoc/parser.rb296
-rw-r--r--lib/rdoc/parser/c.rb1236
-rw-r--r--lib/rdoc/parser/changelog.rb349
-rw-r--r--lib/rdoc/parser/markdown.rb22
-rw-r--r--lib/rdoc/parser/rd.rb22
-rw-r--r--lib/rdoc/parser/ripper_state_lex.rb600
-rw-r--r--lib/rdoc/parser/ruby.rb2372
-rw-r--r--lib/rdoc/parser/ruby_tools.rb165
-rw-r--r--lib/rdoc/parser/simple.rb61
-rw-r--r--lib/rdoc/parser/text.rb11
-rw-r--r--lib/rdoc/rd.rb99
-rw-r--r--lib/rdoc/rd/block_parser.rb1710
-rw-r--r--lib/rdoc/rd/inline.rb71
-rw-r--r--lib/rdoc/rd/inline_parser.rb1858
-rw-r--r--lib/rdoc/rdoc.gemspec237
-rw-r--r--lib/rdoc/rdoc.rb563
-rw-r--r--lib/rdoc/require.rb51
-rw-r--r--lib/rdoc/ri.rb20
-rw-r--r--lib/rdoc/ri/driver.rb1517
-rw-r--r--lib/rdoc/ri/formatter.rb6
-rw-r--r--lib/rdoc/ri/paths.rb171
-rw-r--r--lib/rdoc/ri/store.rb6
-rw-r--r--lib/rdoc/ri/task.rb71
-rw-r--r--lib/rdoc/rubygems_hook.rb248
-rw-r--r--lib/rdoc/servlet.rb451
-rw-r--r--lib/rdoc/single_class.rb30
-rw-r--r--lib/rdoc/stats.rb461
-rw-r--r--lib/rdoc/stats/normal.rb58
-rw-r--r--lib/rdoc/stats/quiet.rb59
-rw-r--r--lib/rdoc/stats/verbose.rb44
-rw-r--r--lib/rdoc/store.rb989
-rw-r--r--lib/rdoc/task.rb355
-rw-r--r--lib/rdoc/text.rb322
-rw-r--r--lib/rdoc/token_stream.rb118
-rw-r--r--lib/rdoc/tom_doc.rb263
-rw-r--r--lib/rdoc/top_level.rb291
-rw-r--r--lib/rdoc/version.rb10
-rw-r--r--lib/readline.gemspec33
-rw-r--r--lib/readline.rb7
-rw-r--r--lib/reline.rb593
-rw-r--r--lib/reline/config.rb380
-rw-r--r--lib/reline/face.rb199
-rw-r--r--lib/reline/history.rb76
-rw-r--r--lib/reline/io.rb45
-rw-r--r--lib/reline/io/ansi.rb358
-rw-r--r--lib/reline/io/dumb.rb106
-rw-r--r--lib/reline/io/windows.rb503
-rw-r--r--lib/reline/key_actor.rb7
-rw-r--r--lib/reline/key_actor/base.rb15
-rw-r--r--lib/reline/key_actor/emacs.rb517
-rw-r--r--lib/reline/key_actor/vi_command.rb518
-rw-r--r--lib/reline/key_actor/vi_insert.rb517
-rw-r--r--lib/reline/key_stroke.rb148
-rw-r--r--lib/reline/kill_ring.rb125
-rw-r--r--lib/reline/line_editor.rb2554
-rw-r--r--lib/reline/reline.gemspec30
-rw-r--r--lib/reline/terminfo.rb153
-rw-r--r--lib/reline/unicode.rb696
-rw-r--r--lib/reline/unicode/east_asian_width.rb1196
-rw-r--r--lib/reline/version.rb3
-rw-r--r--lib/resolv.gemspec6
-rw-r--r--lib/resolv.rb195
-rw-r--r--lib/ruby_vm/rjit/.document1
-rw-r--r--lib/ruby_vm/rjit/assembler.rb1140
-rw-r--r--lib/ruby_vm/rjit/block.rb11
-rw-r--r--lib/ruby_vm/rjit/branch_stub.rb24
-rw-r--r--lib/ruby_vm/rjit/c_pointer.rb394
-rw-r--r--lib/ruby_vm/rjit/c_type.rb99
-rw-r--r--lib/ruby_vm/rjit/code_block.rb91
-rw-r--r--lib/ruby_vm/rjit/compiler.rb518
-rw-r--r--lib/ruby_vm/rjit/context.rb377
-rw-r--r--lib/ruby_vm/rjit/entry_stub.rb7
-rw-r--r--lib/ruby_vm/rjit/exit_compiler.rb164
-rw-r--r--lib/ruby_vm/rjit/hooks.rb36
-rw-r--r--lib/ruby_vm/rjit/insn_compiler.rb6002
-rw-r--r--lib/ruby_vm/rjit/invariants.rb155
-rw-r--r--lib/ruby_vm/rjit/jit_state.rb65
-rw-r--r--lib/ruby_vm/rjit/stats.rb191
-rw-r--r--lib/ruby_vm/rjit/type.rb221
-rw-r--r--lib/rubygems.rb246
-rw-r--r--lib/rubygems/basic_specification.rb59
-rw-r--r--lib/rubygems/bundler_version_finder.rb43
-rw-r--r--lib/rubygems/command.rb5
-rw-r--r--lib/rubygems/command_manager.rb15
-rw-r--r--lib/rubygems/commands/build_command.rb7
-rw-r--r--lib/rubygems/commands/cert_command.rb2
-rw-r--r--lib/rubygems/commands/cleanup_command.rb16
-rw-r--r--lib/rubygems/commands/contents_command.rb27
-rw-r--r--lib/rubygems/commands/environment_command.rb5
-rw-r--r--lib/rubygems/commands/exec_command.rb29
-rw-r--r--lib/rubygems/commands/fetch_command.rb14
-rw-r--r--lib/rubygems/commands/install_command.rb10
-rw-r--r--lib/rubygems/commands/pristine_command.rb31
-rw-r--r--lib/rubygems/commands/push_command.rb37
-rw-r--r--lib/rubygems/commands/query_command.rb43
-rw-r--r--lib/rubygems/commands/rdoc_command.rb4
-rw-r--r--lib/rubygems/commands/rebuild_command.rb1
-rw-r--r--lib/rubygems/commands/setup_command.rb39
-rw-r--r--lib/rubygems/commands/sources_command.rb140
-rw-r--r--lib/rubygems/commands/uninstall_command.rb11
-rw-r--r--lib/rubygems/commands/update_command.rb10
-rw-r--r--lib/rubygems/compatibility.rb41
-rw-r--r--lib/rubygems/config_file.rb23
-rw-r--r--lib/rubygems/core_ext/kernel_require.rb7
-rw-r--r--lib/rubygems/core_ext/kernel_warn.rb8
-rw-r--r--lib/rubygems/defaults.rb4
-rw-r--r--lib/rubygems/dependency.rb12
-rw-r--r--lib/rubygems/dependency_installer.rb79
-rw-r--r--lib/rubygems/dependency_list.rb3
-rw-r--r--lib/rubygems/deprecate.rb146
-rw-r--r--lib/rubygems/doctor.rb2
-rw-r--r--lib/rubygems/errors.rb5
-rw-r--r--lib/rubygems/exceptions.rb25
-rw-r--r--lib/rubygems/ext/builder.rb50
-rw-r--r--lib/rubygems/ext/cargo_builder.rb22
-rw-r--r--lib/rubygems/ext/cmake_builder.rb106
-rw-r--r--lib/rubygems/ext/configure_builder.rb9
-rw-r--r--lib/rubygems/ext/ext_conf_builder.rb17
-rw-r--r--lib/rubygems/ext/rake_builder.rb11
-rw-r--r--lib/rubygems/gem_runner.rb10
-rw-r--r--lib/rubygems/gemcutter_utilities.rb17
-rw-r--r--lib/rubygems/gemcutter_utilities/webauthn_listener.rb13
-rw-r--r--lib/rubygems/install_default_message.rb13
-rw-r--r--lib/rubygems/install_update_options.rb17
-rw-r--r--lib/rubygems/installer.rb244
-rw-r--r--lib/rubygems/local_remote_options.rb4
-rw-r--r--lib/rubygems/name_tuple.rb8
-rw-r--r--lib/rubygems/package.rb33
-rw-r--r--lib/rubygems/package/tar_header.rb19
-rw-r--r--lib/rubygems/package/tar_reader.rb2
-rw-r--r--lib/rubygems/package/tar_reader/entry.rb6
-rw-r--r--lib/rubygems/package/tar_writer.rb9
-rw-r--r--lib/rubygems/platform.rb234
-rw-r--r--lib/rubygems/psych_tree.rb2
-rw-r--r--lib/rubygems/query_utils.rb4
-rw-r--r--lib/rubygems/rdoc.rb19
-rw-r--r--lib/rubygems/remote_fetcher.rb23
-rw-r--r--lib/rubygems/request/connection_pools.rb7
-rw-r--r--lib/rubygems/request/http_pool.rb15
-rw-r--r--lib/rubygems/request_set.rb9
-rw-r--r--lib/rubygems/request_set/gem_dependency_api.rb2
-rw-r--r--lib/rubygems/request_set/lockfile.rb2
-rw-r--r--lib/rubygems/requirement.rb23
-rw-r--r--lib/rubygems/resolver.rb11
-rw-r--r--lib/rubygems/resolver/activation_request.rb2
-rw-r--r--lib/rubygems/resolver/api_set.rb19
-rw-r--r--lib/rubygems/resolver/api_set/gem_parser.rb7
-rw-r--r--lib/rubygems/resolver/best_set.rb30
-rw-r--r--lib/rubygems/resolver/composed_set.rb6
-rw-r--r--lib/rubygems/resolver/conflict.rb2
-rw-r--r--lib/rubygems/resolver/git_set.rb1
-rw-r--r--lib/rubygems/resolver/index_set.rb4
-rw-r--r--lib/rubygems/resolver/source_set.rb2
-rw-r--r--lib/rubygems/s3_uri_signer.rb69
-rw-r--r--lib/rubygems/safe_marshal/reader.rb45
-rw-r--r--lib/rubygems/safe_marshal/visitors/to_ruby.rb45
-rw-r--r--lib/rubygems/security/policy.rb2
-rw-r--r--lib/rubygems/security/signer.rb2
-rw-r--r--lib/rubygems/shellwords.rb3
-rw-r--r--lib/rubygems/source.rb72
-rw-r--r--lib/rubygems/source/git.rb35
-rw-r--r--lib/rubygems/source/installed.rb4
-rw-r--r--lib/rubygems/source/local.rb12
-rw-r--r--lib/rubygems/source/specific_file.rb8
-rw-r--r--lib/rubygems/source_list.rb36
-rw-r--r--lib/rubygems/spec_fetcher.rb70
-rw-r--r--lib/rubygems/specification.rb222
-rw-r--r--lib/rubygems/specification_policy.rb56
-rw-r--r--lib/rubygems/specification_record.rb4
-rw-r--r--lib/rubygems/ssl_certs/rubygems.org/GlobalSign.pem (renamed from lib/rubygems/ssl_certs/rubygems.org/GlobalSignRootCA_R3.pem)0
-rw-r--r--lib/rubygems/ssl_certs/rubygems.org/GlobalSignRootCA.pem21
-rw-r--r--lib/rubygems/stub_specification.rb21
-rw-r--r--lib/rubygems/target_rbconfig.rb50
-rw-r--r--lib/rubygems/text.rb2
-rw-r--r--lib/rubygems/uninstaller.rb42
-rw-r--r--lib/rubygems/uri.rb2
-rw-r--r--lib/rubygems/uri_formatter.rb3
-rw-r--r--lib/rubygems/user_interaction.rb15
-rw-r--r--lib/rubygems/util.rb22
-rw-r--r--lib/rubygems/util/atomic_file_writer.rb76
-rw-r--r--lib/rubygems/util/licenses.rb51
-rw-r--r--lib/rubygems/util/list.rb40
-rw-r--r--lib/rubygems/validator.rb2
-rw-r--r--lib/rubygems/vendor/.document (renamed from lib/bundler/vendor/connection_pool/.document)0
-rw-r--r--lib/rubygems/vendor/molinillo/.document1
-rw-r--r--lib/rubygems/vendor/net-http/.document1
-rw-r--r--lib/rubygems/vendor/net-http/lib/net/http.rb296
-rw-r--r--lib/rubygems/vendor/net-http/lib/net/http/backward.rb40
-rw-r--r--lib/rubygems/vendor/net-http/lib/net/http/exceptions.rb3
-rw-r--r--lib/rubygems/vendor/net-http/lib/net/http/generic_request.rb45
-rw-r--r--lib/rubygems/vendor/net-http/lib/net/http/header.rb14
-rw-r--r--lib/rubygems/vendor/net-http/lib/net/http/requests.rb21
-rw-r--r--lib/rubygems/vendor/net-http/lib/net/http/response.rb3
-rw-r--r--lib/rubygems/vendor/net-http/lib/net/http/responses.rb72
-rw-r--r--lib/rubygems/vendor/net-http/lib/net/https.rb2
-rw-r--r--lib/rubygems/vendor/net-protocol/.document1
-rw-r--r--lib/rubygems/vendor/optparse/.document1
-rw-r--r--lib/rubygems/vendor/optparse/lib/optparse.rb307
-rw-r--r--lib/rubygems/vendor/optparse/lib/optparse/ac.rb16
-rw-r--r--lib/rubygems/vendor/optparse/lib/optparse/kwargs.rb11
-rw-r--r--lib/rubygems/vendor/optparse/lib/optparse/version.rb9
-rw-r--r--lib/rubygems/vendor/resolv/.document1
-rw-r--r--lib/rubygems/vendor/resolv/lib/resolv.rb159
-rw-r--r--lib/rubygems/vendor/securerandom/lib/securerandom.rb102
-rw-r--r--lib/rubygems/vendor/timeout/.document1
-rw-r--r--lib/rubygems/vendor/timeout/lib/timeout.rb22
-rw-r--r--lib/rubygems/vendor/tsort/.document1
-rw-r--r--lib/rubygems/vendor/uri/.document1
-rw-r--r--lib/rubygems/vendor/uri/lib/uri.rb18
-rw-r--r--lib/rubygems/vendor/uri/lib/uri/common.rb129
-rw-r--r--lib/rubygems/vendor/uri/lib/uri/file.rb8
-rw-r--r--lib/rubygems/vendor/uri/lib/uri/ftp.rb2
-rw-r--r--lib/rubygems/vendor/uri/lib/uri/generic.rb114
-rw-r--r--lib/rubygems/vendor/uri/lib/uri/http.rb16
-rw-r--r--lib/rubygems/vendor/uri/lib/uri/rfc2396_parser.rb42
-rw-r--r--lib/rubygems/vendor/uri/lib/uri/rfc3986_parser.rb29
-rw-r--r--lib/rubygems/vendor/uri/lib/uri/version.rb4
-rw-r--r--lib/rubygems/vendored_securerandom.rb3
-rw-r--r--lib/rubygems/version.rb63
-rw-r--r--lib/rubygems/win_platform.rb31
-rw-r--r--lib/rubygems/yaml_serializer.rb11
-rw-r--r--lib/securerandom.gemspec3
-rw-r--r--lib/securerandom.rb8
-rw-r--r--lib/set.rb852
-rw-r--r--lib/set/set.gemspec30
-rw-r--r--lib/set/sorted_set.rb6
-rw-r--r--lib/set/subclass_compatible.rb347
-rw-r--r--lib/shellwords.gemspec7
-rw-r--r--lib/shellwords.rb32
-rw-r--r--lib/singleton.rb108
-rw-r--r--lib/syntax_suggest/api.rb7
-rw-r--r--lib/syntax_suggest/capture_code_context.rb2
-rw-r--r--lib/syntax_suggest/clean_document.rb2
-rw-r--r--lib/syntax_suggest/code_frontier.rb2
-rw-r--r--lib/syntax_suggest/core_ext.rb18
-rw-r--r--lib/syntax_suggest/lex_value.rb2
-rw-r--r--lib/syntax_suggest/mini_stringio.rb30
-rw-r--r--lib/syntax_suggest/version.rb2
-rw-r--r--lib/tempfile.rb98
-rw-r--r--lib/time.gemspec1
-rw-r--r--lib/time.rb85
-rw-r--r--lib/timeout.rb257
-rw-r--r--lib/tmpdir.gemspec2
-rw-r--r--lib/tmpdir.rb34
-rw-r--r--lib/tsort.gemspec29
-rw-r--r--lib/tsort.rb455
-rw-r--r--lib/unicode_normalize/normalize.rb30
-rw-r--r--lib/unicode_normalize/tables.rb186
-rw-r--r--lib/uri/common.rb123
-rw-r--r--lib/uri/file.rb8
-rw-r--r--lib/uri/generic.rb98
-rw-r--r--lib/uri/http.rb12
-rw-r--r--lib/uri/rfc2396_parser.rb42
-rw-r--r--lib/uri/rfc3986_parser.rb29
-rw-r--r--lib/uri/uri.gemspec5
-rw-r--r--lib/uri/version.rb4
-rw-r--r--lib/weakref.gemspec2
-rw-r--r--lib/weakref.rb5
-rw-r--r--lib/yaml.rb3
-rw-r--r--lib/yaml/dbm.rb31
-rw-r--r--lib/yaml/store.rb12
-rwxr-xr-xlibexec/erb50
-rwxr-xr-xlibexec/irb9
-rwxr-xr-xlibexec/rdoc43
-rwxr-xr-xlibexec/ri12
-rwxr-xr-xlibexec/syntax_suggest2
-rw-r--r--load.c529
-rw-r--r--main.c22
-rw-r--r--man/index.txt25
-rw-r--r--man/irb.1257
-rw-r--r--man/ri.1247
-rw-r--r--man/ruby.1107
-rw-r--r--marshal.c202
-rw-r--r--math.c74
-rw-r--r--memory_view.c24
-rw-r--r--method.h29
-rw-r--r--mini_builtin.c108
-rw-r--r--miniinit.c45
-rw-r--r--misc/.vscode/settings.json8
-rwxr-xr-xmisc/expand_tabs.rb34
-rw-r--r--[-rwxr-xr-x]misc/lldb_cruby.py24
-rw-r--r--misc/lldb_rb/commands/heap_page_command.py5
-rw-r--r--misc/lldb_rb/commands/print_flags_command.py6
-rw-r--r--misc/lldb_rb/lldb_interface.py11
-rw-r--r--misc/lldb_rb/rb_heap_structs.py19
-rw-r--r--misc/lldb_rb/utils.py36
-rw-r--r--misc/ruby-style.el15
-rw-r--r--misc/tsan_suppressions.txt109
-rw-r--r--missing/dtoa.c314
-rw-r--r--nilclass.rb38
-rw-r--r--node.c19
-rw-r--r--node.h17
-rw-r--r--node_dump.c187
-rw-r--r--numeric.c1021
-rw-r--r--numeric.rb64
-rw-r--r--object.c674
-rw-r--r--pack.c176
-rw-r--r--pack.rb24
-rw-r--r--parse.y3108
-rw-r--r--parser_bits.h133
-rw-r--r--parser_st.c3
-rw-r--r--pathname.c117
-rw-r--r--pathname_builtin.rb1172
-rw-r--r--prelude.rb28
-rw-r--r--prism/config.yml1338
-rw-r--r--prism/defines.h68
-rw-r--r--prism/encoding.c239
-rw-r--r--prism/extension.c569
-rw-r--r--prism/extension.h10
-rw-r--r--prism/options.c144
-rw-r--r--prism/options.h195
-rw-r--r--prism/parser.h77
-rw-r--r--prism/prism.c7722
-rw-r--r--prism/prism.h106
-rw-r--r--prism/regexp.c279
-rw-r--r--prism/regexp.h26
-rw-r--r--prism/srcs.mk150
-rw-r--r--prism/srcs.mk.in48
-rw-r--r--prism/static_literals.c2
-rw-r--r--prism/templates/ext/prism/api_node.c.erb110
-rw-r--r--prism/templates/include/prism/ast.h.erb81
-rw-r--r--prism/templates/lib/prism/compiler.rb.erb6
-rw-r--r--prism/templates/lib/prism/dispatcher.rb.erb16
-rw-r--r--prism/templates/lib/prism/dot_visitor.rb.erb11
-rw-r--r--prism/templates/lib/prism/dsl.rb.erb126
-rw-r--r--prism/templates/lib/prism/inspect_visitor.rb.erb13
-rw-r--r--prism/templates/lib/prism/node.rb.erb302
-rw-r--r--prism/templates/lib/prism/reflection.rb.erb7
-rw-r--r--prism/templates/lib/prism/serialize.rb.erb618
-rw-r--r--prism/templates/lib/prism/visitor.rb.erb8
-rw-r--r--prism/templates/src/diagnostic.c.erb37
-rw-r--r--prism/templates/src/node.c.erb19
-rw-r--r--prism/templates/src/prettyprint.c.erb13
-rw-r--r--prism/templates/src/serialize.c.erb12
-rwxr-xr-xprism/templates/template.rb97
-rw-r--r--prism/util/pm_buffer.c40
-rw-r--r--prism/util/pm_buffer.h18
-rw-r--r--prism/util/pm_char.c2
-rw-r--r--prism/util/pm_constant_pool.c10
-rw-r--r--prism/util/pm_integer.c28
-rw-r--r--prism/util/pm_integer.h16
-rw-r--r--prism/util/pm_list.h6
-rw-r--r--prism/util/pm_newline_list.c29
-rw-r--r--prism/util/pm_newline_list.h11
-rw-r--r--prism/util/pm_string.c213
-rw-r--r--prism/util/pm_string.h46
-rw-r--r--prism/util/pm_string_list.c28
-rw-r--r--prism/util/pm_string_list.h44
-rw-r--r--prism/util/pm_strncasecmp.c14
-rw-r--r--prism/version.h6
-rw-r--r--prism_compile.c7238
-rw-r--r--prism_compile.h34
-rw-r--r--proc.c699
-rw-r--r--process.c444
-rw-r--r--ractor.c2564
-rw-r--r--ractor.rb973
-rw-r--r--ractor_core.h204
-rw-r--r--ractor_sync.c1516
-rw-r--r--random.c296
-rw-r--r--range.c506
-rw-r--r--rational.c197
-rw-r--r--re.c229
-rw-r--r--regcomp.c2423
-rw-r--r--regenc.c103
-rw-r--r--regenc.h17
-rw-r--r--regerror.c103
-rw-r--r--regexec.c3098
-rw-r--r--regint.h26
-rw-r--r--regparse.c2748
-rw-r--r--regparse.h6
-rw-r--r--rjit.c501
-rw-r--r--rjit.h101
-rw-r--r--rjit.rb41
-rw-r--r--rjit_c.c543
-rw-r--r--rjit_c.h165
-rw-r--r--rjit_c.rb1670
-rw-r--r--ruby-runner.c9
-rw-r--r--ruby.c368
-rw-r--r--ruby.rs4
-rw-r--r--ruby_atomic.h50
-rw-r--r--ruby_parser.c38
-rw-r--r--rubyparser.h193
-rw-r--r--sample/drb/README.ja.rdoc59
-rw-r--r--sample/drb/README.rdoc56
-rw-r--r--sample/drb/acl.rb15
-rw-r--r--sample/drb/darray.rb12
-rw-r--r--sample/drb/darrayc.rb47
-rw-r--r--sample/drb/dbiff.rb51
-rw-r--r--sample/drb/dcdbiff.rb43
-rw-r--r--sample/drb/dchatc.rb41
-rw-r--r--sample/drb/dchats.rb69
-rw-r--r--sample/drb/dhasen.rb41
-rw-r--r--sample/drb/dhasenc.rb14
-rw-r--r--sample/drb/dlogc.rb16
-rw-r--r--sample/drb/dlogd.rb38
-rw-r--r--sample/drb/dqin.rb13
-rw-r--r--sample/drb/dqlib.rb14
-rw-r--r--sample/drb/dqout.rb14
-rw-r--r--sample/drb/dqueue.rb11
-rw-r--r--sample/drb/drbc.rb45
-rw-r--r--sample/drb/drbch.rb48
-rw-r--r--sample/drb/drbm.rb60
-rw-r--r--sample/drb/drbmc.rb22
-rw-r--r--sample/drb/drbs-acl.rb51
-rw-r--r--sample/drb/drbs.rb64
-rw-r--r--sample/drb/drbssl_c.rb19
-rw-r--r--sample/drb/drbssl_s.rb31
-rw-r--r--sample/drb/extserv_test.rb80
-rw-r--r--sample/drb/gw_ct.rb29
-rw-r--r--sample/drb/gw_cu.rb28
-rw-r--r--sample/drb/gw_s.rb10
-rw-r--r--sample/drb/holderc.rb22
-rw-r--r--sample/drb/holders.rb63
-rw-r--r--sample/drb/http0.rb77
-rw-r--r--sample/drb/http0serv.rb120
-rw-r--r--sample/drb/name.rb117
-rw-r--r--sample/drb/namec.rb36
-rw-r--r--sample/drb/old_tuplespace.rb212
-rw-r--r--sample/drb/rinda_ts.rb7
-rw-r--r--sample/drb/rindac.rb17
-rw-r--r--sample/drb/rindas.rb18
-rw-r--r--sample/drb/ring_echo.rb29
-rw-r--r--sample/drb/ring_inspect.rb30
-rw-r--r--sample/drb/ring_place.rb25
-rw-r--r--sample/drb/simpletuple.rb89
-rw-r--r--sample/drb/speedc.rb21
-rw-r--r--sample/drb/speeds.rb31
-rw-r--r--sample/openssl/c_rehash.rb2
-rw-r--r--sample/prism/find_calls.rb105
-rw-r--r--sample/prism/find_comments.rb100
-rw-r--r--sample/prism/locate_nodes.rb84
-rw-r--r--sample/prism/make_tags.rb302
-rw-r--r--sample/prism/multiplex_constants.rb138
-rw-r--r--sample/prism/relocate_constants.rb43
-rw-r--r--sample/prism/visit_nodes.rb63
-rw-r--r--sample/trick2025/01-omoikane/authors.markdown5
-rw-r--r--sample/trick2025/01-omoikane/bf.rb81
-rw-r--r--sample/trick2025/01-omoikane/entry.rb32
-rw-r--r--sample/trick2025/01-omoikane/remarks.markdown71
-rw-r--r--sample/trick2025/01-omoikane/sample_input.txt35
-rw-r--r--sample/trick2025/01-omoikane/spoiler_rot13.txt470
-rw-r--r--sample/trick2025/02-mame/authors.markdown3
-rw-r--r--sample/trick2025/02-mame/entry.rb34
-rw-r--r--sample/trick2025/02-mame/remarks.markdown141
-rw-r--r--sample/trick2025/02-mame/sample.orig.rb8
-rw-r--r--sample/trick2025/02-mame/test.patch16
-rw-r--r--sample/trick2025/03-tompng/authors.markdown3
-rw-r--r--sample/trick2025/03-tompng/entry.rb74
-rw-r--r--sample/trick2025/03-tompng/remarks.markdown146
-rw-r--r--sample/trick2025/04-tompng/authors.markdown3
-rw-r--r--sample/trick2025/04-tompng/entry.rb36
-rw-r--r--sample/trick2025/04-tompng/remarks.markdown43
-rw-r--r--sample/trick2025/05-tompng/authors.markdown3
-rw-r--r--sample/trick2025/05-tompng/entry.rb118
-rw-r--r--sample/trick2025/05-tompng/remarks.markdown106
-rw-r--r--sample/trick2025/README.md16
-rw-r--r--sample/win32ole/excel1.rb37
-rw-r--r--sample/win32ole/excel2.rb31
-rw-r--r--sample/win32ole/excel3.rb21
-rw-r--r--sample/win32ole/ie.rb12
-rw-r--r--sample/win32ole/ieconst.rb33
-rw-r--r--sample/win32ole/ienavi.rb41
-rw-r--r--sample/win32ole/ienavi2.rb41
-rw-r--r--sample/win32ole/oledirs.rb24
-rw-r--r--sample/win32ole/olegen.rb348
-rw-r--r--sample/win32ole/xml.rb7307
-rw-r--r--scheduler.c594
-rw-r--r--set.c2293
-rw-r--r--shape.c1389
-rw-r--r--shape.h471
-rw-r--r--signal.c126
-rw-r--r--siphash.c3
-rwxr-xr-xspec/bin/bundle6
-rwxr-xr-xspec/bin/parallel_rspec7
-rwxr-xr-xspec/bin/rspec6
-rw-r--r--spec/bundled_gems.mspec10
-rw-r--r--spec/bundled_gems_spec.rb427
-rw-r--r--spec/bundler/bundler/build_metadata_spec.rb23
-rw-r--r--spec/bundler/bundler/bundler_spec.rb72
-rw-r--r--spec/bundler/bundler/cli_common_spec.rb22
-rw-r--r--spec/bundler/bundler/cli_spec.rb88
-rw-r--r--spec/bundler/bundler/compact_index_client/parser_spec.rb178
-rw-r--r--spec/bundler/bundler/compact_index_client/updater_spec.rb17
-rw-r--r--spec/bundler/bundler/current_ruby_spec.rb157
-rw-r--r--spec/bundler/bundler/definition_spec.rb70
-rw-r--r--spec/bundler/bundler/dependency_spec.rb134
-rw-r--r--spec/bundler/bundler/dsl_spec.rb45
-rw-r--r--spec/bundler/bundler/endpoint_specification_spec.rb2
-rw-r--r--spec/bundler/bundler/env_spec.rb28
-rw-r--r--spec/bundler/bundler/fetcher/dependency_spec.rb2
-rw-r--r--spec/bundler/bundler/fetcher/downloader_spec.rb85
-rw-r--r--spec/bundler/bundler/fetcher/gem_remote_fetcher_spec.rb60
-rw-r--r--spec/bundler/bundler/fetcher/index_spec.rb24
-rw-r--r--spec/bundler/bundler/friendly_errors_spec.rb31
-rw-r--r--spec/bundler/bundler/gem_helper_spec.rb40
-rw-r--r--spec/bundler/bundler/gem_version_promoter_spec.rb10
-rw-r--r--spec/bundler/bundler/installer/gem_installer_spec.rb15
-rw-r--r--spec/bundler/bundler/lockfile_parser_spec.rb8
-rw-r--r--spec/bundler/bundler/plugin/events_spec.rb12
-rw-r--r--spec/bundler/bundler/plugin/index_spec.rb10
-rw-r--r--spec/bundler/bundler/plugin/installer_spec.rb9
-rw-r--r--spec/bundler/bundler/plugin_spec.rb35
-rw-r--r--spec/bundler/bundler/resolver/candidate_spec.rb19
-rw-r--r--spec/bundler/bundler/retry_spec.rb4
-rw-r--r--spec/bundler/bundler/ruby_dsl_spec.rb50
-rw-r--r--spec/bundler/bundler/ruby_version_spec.rb10
-rw-r--r--spec/bundler/bundler/rubygems_integration_spec.rb53
-rw-r--r--spec/bundler/bundler/settings_spec.rb40
-rw-r--r--spec/bundler/bundler/shared_helpers_spec.rb51
-rw-r--r--spec/bundler/bundler/source/git/git_proxy_spec.rb135
-rw-r--r--spec/bundler/bundler/source/git_spec.rb50
-rw-r--r--spec/bundler/bundler/source/rubygems/remote_spec.rb8
-rw-r--r--spec/bundler/bundler/source/rubygems_spec.rb18
-rw-r--r--spec/bundler/bundler/source_list_spec.rb26
-rw-r--r--spec/bundler/bundler/source_spec.rb6
-rw-r--r--spec/bundler/bundler/specifications/foo.gemspec2
-rw-r--r--spec/bundler/bundler/stub_specification_spec.rb20
-rw-r--r--spec/bundler/bundler/ui/shell_spec.rb54
-rw-r--r--spec/bundler/bundler/uri_credentials_filter_spec.rb10
-rw-r--r--spec/bundler/bundler/uri_normalizer_spec.rb25
-rw-r--r--spec/bundler/bundler/yaml_serializer_spec.rb4
-rw-r--r--spec/bundler/cache/cache_path_spec.rb12
-rw-r--r--spec/bundler/cache/gems_spec.rb237
-rw-r--r--spec/bundler/cache/git_spec.rb293
-rw-r--r--spec/bundler/cache/path_spec.rb70
-rw-r--r--spec/bundler/cache/platform_spec.rb16
-rw-r--r--spec/bundler/commands/add_spec.rb190
-rw-r--r--spec/bundler/commands/binstubs_spec.rb391
-rw-r--r--spec/bundler/commands/cache_spec.rb362
-rw-r--r--spec/bundler/commands/check_spec.rb329
-rw-r--r--spec/bundler/commands/clean_spec.rb318
-rw-r--r--spec/bundler/commands/config_spec.rb59
-rw-r--r--spec/bundler/commands/console_spec.rb217
-rw-r--r--spec/bundler/commands/doctor_spec.rb78
-rw-r--r--spec/bundler/commands/exec_spec.rb568
-rw-r--r--spec/bundler/commands/fund_spec.rb50
-rw-r--r--spec/bundler/commands/help_spec.rb5
-rw-r--r--spec/bundler/commands/info_spec.rb46
-rw-r--r--spec/bundler/commands/init_spec.rb16
-rw-r--r--spec/bundler/commands/inject_spec.rb117
-rw-r--r--spec/bundler/commands/install_spec.rb1182
-rw-r--r--spec/bundler/commands/issue_spec.rb2
-rw-r--r--spec/bundler/commands/licenses_spec.rb4
-rw-r--r--spec/bundler/commands/list_spec.rb168
-rw-r--r--spec/bundler/commands/lock_spec.rb1747
-rw-r--r--spec/bundler/commands/newgem_spec.rb1784
-rw-r--r--spec/bundler/commands/open_spec.rb16
-rw-r--r--spec/bundler/commands/outdated_spec.rb247
-rw-r--r--spec/bundler/commands/platform_spec.rb415
-rw-r--r--spec/bundler/commands/post_bundle_message_spec.rb208
-rw-r--r--spec/bundler/commands/pristine_spec.rb70
-rw-r--r--spec/bundler/commands/remove_spec.rb358
-rw-r--r--spec/bundler/commands/show_spec.rb71
-rw-r--r--spec/bundler/commands/ssl_spec.rb373
-rw-r--r--spec/bundler/commands/update_spec.rb928
-rw-r--r--spec/bundler/commands/version_spec.rb50
-rw-r--r--spec/bundler/commands/viz_spec.rb144
-rw-r--r--spec/bundler/install/allow_offline_install_spec.rb34
-rw-r--r--spec/bundler/install/binstubs_spec.rb20
-rw-r--r--spec/bundler/install/bundler_spec.rb48
-rw-r--r--spec/bundler/install/deploy_spec.rb245
-rw-r--r--spec/bundler/install/failure_spec.rb4
-rw-r--r--spec/bundler/install/force_spec.rb71
-rw-r--r--spec/bundler/install/gemfile/eval_gemfile_spec.rb34
-rw-r--r--spec/bundler/install/gemfile/force_ruby_platform_spec.rb72
-rw-r--r--spec/bundler/install/gemfile/gemspec_spec.rb325
-rw-r--r--spec/bundler/install/gemfile/git_spec.rb552
-rw-r--r--spec/bundler/install/gemfile/groups_spec.rb144
-rw-r--r--spec/bundler/install/gemfile/install_if_spec.rb24
-rw-r--r--spec/bundler/install/gemfile/lockfile_spec.rb33
-rw-r--r--spec/bundler/install/gemfile/path_spec.rb259
-rw-r--r--spec/bundler/install/gemfile/platform_spec.rb481
-rw-r--r--spec/bundler/install/gemfile/ruby_spec.rb72
-rw-r--r--spec/bundler/install/gemfile/sources_spec.rb1384
-rw-r--r--spec/bundler/install/gemfile/specific_platform_spec.rb901
-rw-r--r--spec/bundler/install/gemfile_spec.rb118
-rw-r--r--spec/bundler/install/gems/compact_index_spec.rb408
-rw-r--r--spec/bundler/install/gems/dependency_api_fallback_spec.rb19
-rw-r--r--spec/bundler/install/gems/dependency_api_spec.rb287
-rw-r--r--spec/bundler/install/gems/env_spec.rb36
-rw-r--r--spec/bundler/install/gems/flex_spec.rb220
-rw-r--r--spec/bundler/install/gems/fund_spec.rb28
-rw-r--r--spec/bundler/install/gems/gemfile_source_header_spec.rb24
-rw-r--r--spec/bundler/install/gems/mirror_probe_spec.rb68
-rw-r--r--spec/bundler/install/gems/mirror_spec.rb22
-rw-r--r--spec/bundler/install/gems/native_extensions_spec.rb18
-rw-r--r--spec/bundler/install/gems/post_install_spec.rb44
-rw-r--r--spec/bundler/install/gems/resolving_spec.rb266
-rw-r--r--spec/bundler/install/gems/standalone_spec.rb168
-rw-r--r--spec/bundler/install/gems/win32_spec.rb10
-rw-r--r--spec/bundler/install/gemspecs_spec.rb50
-rw-r--r--spec/bundler/install/git_spec.rb140
-rw-r--r--spec/bundler/install/global_cache_spec.rb180
-rw-r--r--spec/bundler/install/path_spec.rb114
-rw-r--r--spec/bundler/install/prereleases_spec.rb18
-rw-r--r--spec/bundler/install/process_lock_spec.rb14
-rw-r--r--spec/bundler/install/redownload_spec.rb91
-rw-r--r--spec/bundler/install/security_policy_spec.rb8
-rw-r--r--spec/bundler/install/yanked_spec.rb153
-rw-r--r--spec/bundler/lock/git_spec.rb120
-rw-r--r--spec/bundler/lock/lockfile_spec.rb1435
-rw-r--r--spec/bundler/other/cli_dispatch_spec.rb6
-rw-r--r--spec/bundler/other/cli_man_pages_spec.rb100
-rw-r--r--spec/bundler/other/ext_spec.rb47
-rw-r--r--spec/bundler/other/major_deprecation_spec.rb588
-rw-r--r--spec/bundler/plugins/command_spec.rb10
-rw-r--r--spec/bundler/plugins/hook_spec.rb54
-rw-r--r--spec/bundler/plugins/install_spec.rb83
-rw-r--r--spec/bundler/plugins/list_spec.rb4
-rw-r--r--spec/bundler/plugins/source/example_spec.rb54
-rw-r--r--spec/bundler/plugins/source_spec.rb16
-rw-r--r--spec/bundler/plugins/uninstall_spec.rb8
-rw-r--r--spec/bundler/quality_spec.rb31
-rw-r--r--spec/bundler/realworld/dependency_api_spec.rb46
-rw-r--r--spec/bundler/realworld/edgecases_spec.rb312
-rw-r--r--spec/bundler/realworld/ffi_spec.rb4
-rw-r--r--spec/bundler/realworld/fixtures/tapioca/Gemfile5
-rw-r--r--spec/bundler/realworld/fixtures/tapioca/Gemfile.lock49
-rw-r--r--spec/bundler/realworld/fixtures/warbler/Gemfile4
-rw-r--r--spec/bundler/realworld/fixtures/warbler/Gemfile.lock35
-rw-r--r--spec/bundler/realworld/gemfile_source_header_spec.rb53
-rw-r--r--spec/bundler/realworld/mirror_probe_spec.rb131
-rw-r--r--spec/bundler/realworld/slow_perf_spec.rb111
-rw-r--r--spec/bundler/resolver/basic_spec.rb100
-rw-r--r--spec/bundler/resolver/platform_spec.rb62
-rw-r--r--spec/bundler/runtime/env_helpers_spec.rb236
-rw-r--r--spec/bundler/runtime/executable_spec.rb116
-rw-r--r--spec/bundler/runtime/gem_tasks_spec.rb80
-rw-r--r--spec/bundler/runtime/inline_spec.rb290
-rw-r--r--spec/bundler/runtime/load_spec.rb28
-rw-r--r--spec/bundler/runtime/platform_spec.rb147
-rw-r--r--spec/bundler/runtime/require_spec.rb119
-rw-r--r--spec/bundler/runtime/requiring_spec.rb8
-rw-r--r--spec/bundler/runtime/self_management_spec.rb168
-rw-r--r--spec/bundler/runtime/setup_spec.rb488
-rw-r--r--spec/bundler/runtime/with_unbundled_env_spec.rb298
-rw-r--r--spec/bundler/spec_helper.rb48
-rw-r--r--spec/bundler/support/artifice/compact_index_creds_diff_host.rb2
-rw-r--r--spec/bundler/support/artifice/compact_index_etag_match.rb2
-rw-r--r--spec/bundler/support/artifice/compact_index_mirror_down.rb21
-rw-r--r--spec/bundler/support/artifice/compact_index_no_checksums.rb16
-rw-r--r--spec/bundler/support/artifice/endpoint_500.rb2
-rw-r--r--spec/bundler/support/artifice/endpoint_creds_diff_host.rb2
-rw-r--r--spec/bundler/support/artifice/fail.rb2
-rw-r--r--spec/bundler/support/artifice/helpers/compact_index.rb13
-rw-r--r--spec/bundler/support/artifice/helpers/endpoint.rb9
-rw-r--r--spec/bundler/support/artifice/helpers/rack_request.rb2
-rw-r--r--spec/bundler/support/artifice/vcr.rb2
-rw-r--r--spec/bundler/support/artifice/windows.rb2
-rw-r--r--spec/bundler/support/build_metadata.rb14
-rw-r--r--spec/bundler/support/builders.rb213
-rwxr-xr-xspec/bundler/support/bundle6
-rw-r--r--spec/bundler/support/bundle.rb6
-rw-r--r--spec/bundler/support/checksums.rb18
-rw-r--r--spec/bundler/support/command_execution.rb3
-rw-r--r--spec/bundler/support/env.rb13
-rw-r--r--spec/bundler/support/filters.rb20
-rw-r--r--spec/bundler/support/hax.rb51
-rw-r--r--spec/bundler/support/helpers.rb405
-rw-r--r--spec/bundler/support/indexes.rb17
-rw-r--r--spec/bundler/support/matchers.rb14
-rw-r--r--spec/bundler/support/options.rb15
-rw-r--r--spec/bundler/support/path.rb147
-rw-r--r--spec/bundler/support/platforms.rb70
-rw-r--r--spec/bundler/support/rubygems_ext.rb108
-rw-r--r--spec/bundler/support/rubygems_version_manager.rb35
-rw-r--r--spec/bundler/support/setup.rb9
-rw-r--r--spec/bundler/support/silent_logger.rb10
-rw-r--r--spec/bundler/support/subprocess.rb115
-rw-r--r--spec/bundler/support/the_bundle.rb16
-rw-r--r--spec/bundler/support/vendored_net_http.rb23
-rw-r--r--spec/bundler/support/windows_tag_group.rb191
-rw-r--r--spec/bundler/update/force_spec.rb30
-rw-r--r--spec/bundler/update/gemfile_spec.rb14
-rw-r--r--spec/bundler/update/gems/fund_spec.rb4
-rw-r--r--spec/bundler/update/gems/post_install_spec.rb20
-rw-r--r--spec/bundler/update/git_spec.rb90
-rw-r--r--spec/bundler/update/path_spec.rb2
-rw-r--r--spec/bundler/update/redownload_spec.rb44
-rw-r--r--spec/default.mspec39
-rw-r--r--spec/mmtk.mspec12
-rw-r--r--[-rwxr-xr-x]spec/mspec/lib/mspec/commands/mkspec.rb2
-rw-r--r--spec/mspec/lib/mspec/commands/mspec-ci.rb5
-rw-r--r--spec/mspec/lib/mspec/commands/mspec-run.rb8
-rw-r--r--spec/mspec/lib/mspec/commands/mspec-tag.rb2
-rw-r--r--[-rwxr-xr-x]spec/mspec/lib/mspec/commands/mspec.rb2
-rw-r--r--spec/mspec/lib/mspec/guards/platform.rb24
-rw-r--r--spec/mspec/lib/mspec/helpers/numeric.rb26
-rw-r--r--spec/mspec/lib/mspec/helpers/tmp.rb15
-rw-r--r--spec/mspec/lib/mspec/runner/actions/leakchecker.rb6
-rw-r--r--spec/mspec/lib/mspec/runner/formatters/launchable.rb88
-rw-r--r--spec/mspec/lib/mspec/runner/formatters/multi.rb2
-rw-r--r--spec/mspec/lib/mspec/utils/name_map.rb13
-rw-r--r--spec/mspec/lib/mspec/utils/options.rb17
-rw-r--r--spec/mspec/lib/mspec/utils/script.rb8
-rw-r--r--spec/mspec/spec/commands/mspec_ci_spec.rb5
-rw-r--r--spec/mspec/spec/commands/mspec_run_spec.rb5
-rw-r--r--spec/mspec/spec/guards/platform_spec.rb38
-rw-r--r--spec/mspec/spec/utils/fixtures/this_file_raises.rb1
-rw-r--r--spec/mspec/spec/utils/fixtures/this_file_raises2.rb1
-rw-r--r--spec/mspec/spec/utils/name_map_spec.rb12
-rwxr-xr-x[-rw-r--r--]spec/mspec/tool/remove_old_guards.rb19
-rw-r--r--spec/mspec/tool/sync/sync-rubyspec.rb35
-rw-r--r--spec/ruby/.mspec.constants1
-rw-r--r--spec/ruby/.rubocop.yml21
-rw-r--r--spec/ruby/.rubocop_todo.yml45
-rw-r--r--spec/ruby/CONTRIBUTING.md14
-rw-r--r--spec/ruby/README.md12
-rwxr-xr-xspec/ruby/bin/rubocop12
-rwxr-xr-xspec/ruby/command_line/dash_0_spec.rb13
-rw-r--r--spec/ruby/command_line/dash_upper_u_spec.rb24
-rw-r--r--spec/ruby/command_line/dash_v_spec.rb3
-rw-r--r--spec/ruby/command_line/feature_spec.rb2
-rw-r--r--spec/ruby/command_line/fixtures/debug_info.rb1
-rw-r--r--spec/ruby/command_line/frozen_strings_spec.rb37
-rw-r--r--spec/ruby/command_line/rubyopt_spec.rb6
-rw-r--r--spec/ruby/core/array/drop_spec.rb2
-rw-r--r--spec/ruby/core/array/each_spec.rb2
-rw-r--r--spec/ruby/core/array/fetch_values_spec.rb55
-rw-r--r--spec/ruby/core/array/fixtures/classes.rb744
-rw-r--r--spec/ruby/core/array/intersect_spec.rb92
-rw-r--r--spec/ruby/core/array/pack/a_spec.rb6
-rw-r--r--spec/ruby/core/array/pack/at_spec.rb2
-rw-r--r--spec/ruby/core/array/pack/b_spec.rb2
-rw-r--r--spec/ruby/core/array/pack/buffer_spec.rb10
-rw-r--r--spec/ruby/core/array/pack/c_spec.rb2
-rw-r--r--spec/ruby/core/array/pack/comment_spec.rb2
-rw-r--r--spec/ruby/core/array/pack/h_spec.rb2
-rw-r--r--spec/ruby/core/array/pack/l_spec.rb16
-rw-r--r--spec/ruby/core/array/pack/m_spec.rb2
-rw-r--r--spec/ruby/core/array/pack/shared/basic.rb27
-rw-r--r--spec/ruby/core/array/pack/shared/float.rb2
-rw-r--r--spec/ruby/core/array/pack/shared/integer.rb6
-rw-r--r--spec/ruby/core/array/pack/shared/string.rb2
-rw-r--r--spec/ruby/core/array/pack/u_spec.rb2
-rw-r--r--spec/ruby/core/array/pack/w_spec.rb2
-rw-r--r--spec/ruby/core/array/pack/x_spec.rb2
-rw-r--r--spec/ruby/core/array/pack/z_spec.rb4
-rw-r--r--spec/ruby/core/array/plus_spec.rb2
-rw-r--r--spec/ruby/core/array/sample_spec.rb7
-rw-r--r--spec/ruby/core/array/shared/slice.rb184
-rw-r--r--spec/ruby/core/array/shared/unshift.rb2
-rw-r--r--spec/ruby/core/array/shuffle_spec.rb13
-rw-r--r--spec/ruby/core/array/to_h_spec.rb6
-rw-r--r--spec/ruby/core/basicobject/equal_spec.rb6
-rw-r--r--spec/ruby/core/basicobject/instance_eval_spec.rb19
-rw-r--r--spec/ruby/core/basicobject/instance_exec_spec.rb20
-rw-r--r--spec/ruby/core/basicobject/singleton_method_added_spec.rb2
-rw-r--r--spec/ruby/core/binding/fixtures/irb.rb3
-rw-r--r--spec/ruby/core/binding/shared/clone.rb2
-rw-r--r--spec/ruby/core/builtin_constants/builtin_constants_spec.rb102
-rw-r--r--spec/ruby/core/class/attached_object_spec.rb40
-rw-r--r--spec/ruby/core/class/dup_spec.rb2
-rw-r--r--spec/ruby/core/class/inherited_spec.rb17
-rw-r--r--spec/ruby/core/class/new_spec.rb2
-rw-r--r--spec/ruby/core/class/subclasses_spec.rb126
-rw-r--r--spec/ruby/core/comparable/clamp_spec.rb149
-rw-r--r--spec/ruby/core/comparable/fixtures/classes.rb1
-rw-r--r--spec/ruby/core/complex/equal_value_spec.rb2
-rw-r--r--spec/ruby/core/complex/polar_spec.rb24
-rw-r--r--spec/ruby/core/complex/shared/rect.rb12
-rw-r--r--spec/ruby/core/data/constants_spec.rb20
-rw-r--r--spec/ruby/core/data/deconstruct_keys_spec.rb130
-rw-r--r--spec/ruby/core/data/deconstruct_spec.rb8
-rw-r--r--spec/ruby/core/data/define_spec.rb48
-rw-r--r--spec/ruby/core/data/eql_spec.rb63
-rw-r--r--spec/ruby/core/data/equal_value_spec.rb63
-rw-r--r--spec/ruby/core/data/fixtures/classes.rb31
-rw-r--r--spec/ruby/core/data/hash_spec.rb25
-rw-r--r--spec/ruby/core/data/initialize_spec.rb145
-rw-r--r--spec/ruby/core/data/inspect_spec.rb6
-rw-r--r--spec/ruby/core/data/members_spec.rb21
-rw-r--r--spec/ruby/core/data/shared/inspect.rb62
-rw-r--r--spec/ruby/core/data/to_h_spec.rb63
-rw-r--r--spec/ruby/core/data/to_s_spec.rb6
-rw-r--r--spec/ruby/core/data/with_spec.rb66
-rw-r--r--spec/ruby/core/dir/chdir_spec.rb122
-rw-r--r--spec/ruby/core/dir/close_spec.rb42
-rw-r--r--spec/ruby/core/dir/exist_spec.rb8
-rw-r--r--spec/ruby/core/dir/fchdir_spec.rb39
-rw-r--r--spec/ruby/core/dir/fixtures/common.rb10
-rw-r--r--spec/ruby/core/dir/for_fd_spec.rb79
-rw-r--r--spec/ruby/core/dir/glob_spec.rb81
-rw-r--r--spec/ruby/core/dir/home_spec.rb46
-rw-r--r--spec/ruby/core/dir/shared/delete.rb18
-rw-r--r--spec/ruby/core/dir/shared/exist.rb1
-rw-r--r--spec/ruby/core/dir/shared/glob.rb65
-rw-r--r--spec/ruby/core/encoding/compatible_spec.rb385
-rw-r--r--spec/ruby/core/encoding/converter/convert_spec.rb2
-rw-r--r--spec/ruby/core/encoding/converter/finish_spec.rb4
-rw-r--r--spec/ruby/core/encoding/converter/last_error_spec.rb2
-rw-r--r--spec/ruby/core/encoding/converter/new_spec.rb2
-rw-r--r--spec/ruby/core/encoding/converter/primitive_convert_spec.rb2
-rw-r--r--spec/ruby/core/encoding/converter/primitive_errinfo_spec.rb2
-rw-r--r--spec/ruby/core/encoding/converter/putback_spec.rb2
-rw-r--r--spec/ruby/core/encoding/converter/search_convpath_spec.rb6
-rw-r--r--spec/ruby/core/encoding/find_spec.rb2
-rw-r--r--spec/ruby/core/encoding/fixtures/classes.rb2
-rw-r--r--spec/ruby/core/encoding/invalid_byte_sequence_error/error_bytes_spec.rb2
-rw-r--r--spec/ruby/core/encoding/invalid_byte_sequence_error/incomplete_input_spec.rb2
-rw-r--r--spec/ruby/core/encoding/invalid_byte_sequence_error/readagain_bytes_spec.rb2
-rw-r--r--spec/ruby/core/encoding/replicate_spec.rb4
-rw-r--r--spec/ruby/core/enumerable/collect_concat_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/collect_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/compact_spec.rb10
-rw-r--r--spec/ruby/core/enumerable/detect_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/each_cons_spec.rb6
-rw-r--r--spec/ruby/core/enumerable/each_slice_spec.rb6
-rw-r--r--spec/ruby/core/enumerable/entries_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/filter_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/find_all_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/find_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/fixtures/classes.rb7
-rw-r--r--spec/ruby/core/enumerable/flat_map_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/map_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/select_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/shared/inject.rb47
-rw-r--r--spec/ruby/core/enumerable/tally_spec.rb112
-rw-r--r--spec/ruby/core/enumerable/to_a_spec.rb2
-rw-r--r--spec/ruby/core/enumerable/to_h_spec.rb8
-rw-r--r--spec/ruby/core/enumerable/to_set_spec.rb33
-rw-r--r--spec/ruby/core/enumerator/each_with_index_spec.rb8
-rw-r--r--spec/ruby/core/enumerator/each_with_object_spec.rb2
-rw-r--r--spec/ruby/core/enumerator/enum_for_spec.rb2
-rw-r--r--spec/ruby/core/enumerator/fixtures/classes.rb (renamed from spec/ruby/fixtures/enumerator/classes.rb)0
-rw-r--r--spec/ruby/core/enumerator/lazy/compact_spec.rb18
-rw-r--r--spec/ruby/core/enumerator/lazy/lazy_spec.rb9
-rw-r--r--spec/ruby/core/enumerator/product/each_spec.rb108
-rw-r--r--spec/ruby/core/enumerator/product/initialize_copy_spec.rb74
-rw-r--r--spec/ruby/core/enumerator/product/initialize_spec.rb44
-rw-r--r--spec/ruby/core/enumerator/product/inspect_spec.rb28
-rw-r--r--spec/ruby/core/enumerator/product/rewind_spec.rb90
-rw-r--r--spec/ruby/core/enumerator/product/size_spec.rb102
-rw-r--r--spec/ruby/core/enumerator/product_spec.rb138
-rw-r--r--spec/ruby/core/enumerator/shared/enum_for.rb (renamed from spec/ruby/shared/enumerator/enum_for.rb)0
-rw-r--r--spec/ruby/core/enumerator/shared/with_index.rb33
-rw-r--r--spec/ruby/core/enumerator/shared/with_object.rb42
-rw-r--r--spec/ruby/core/enumerator/to_enum_spec.rb4
-rw-r--r--spec/ruby/core/enumerator/with_index_spec.rb19
-rw-r--r--spec/ruby/core/enumerator/with_object_spec.rb2
-rw-r--r--spec/ruby/core/env/clone_spec.rb10
-rw-r--r--spec/ruby/core/env/dup_spec.rb10
-rw-r--r--spec/ruby/core/env/element_reference_spec.rb2
-rw-r--r--spec/ruby/core/env/fetch_spec.rb2
-rw-r--r--spec/ruby/core/env/inspect_spec.rb2
-rw-r--r--spec/ruby/core/env/length_spec.rb2
-rw-r--r--spec/ruby/core/env/shared/update.rb10
-rw-r--r--spec/ruby/core/env/size_spec.rb2
-rw-r--r--spec/ruby/core/env/to_h_spec.rb12
-rw-r--r--spec/ruby/core/exception/detailed_message_spec.rb65
-rw-r--r--spec/ruby/core/exception/errno_spec.rb2
-rw-r--r--spec/ruby/core/exception/fixtures/common.rb3
-rw-r--r--spec/ruby/core/exception/frozen_error_spec.rb16
-rw-r--r--spec/ruby/core/exception/full_message_spec.rb96
-rw-r--r--spec/ruby/core/exception/no_method_error_spec.rb204
-rw-r--r--spec/ruby/core/exception/set_backtrace_spec.rb71
-rw-r--r--spec/ruby/core/exception/shared/set_backtrace.rb64
-rw-r--r--spec/ruby/core/exception/syntax_error_spec.rb36
-rw-r--r--spec/ruby/core/exception/system_call_error_spec.rb32
-rw-r--r--spec/ruby/core/fiber/alive_spec.rb44
-rw-r--r--spec/ruby/core/fiber/blocking_spec.rb22
-rw-r--r--spec/ruby/core/fiber/current_spec.rb50
-rw-r--r--spec/ruby/core/fiber/fixtures/classes.rb16
-rw-r--r--spec/ruby/core/fiber/fixtures/scheduler.rb35
-rw-r--r--spec/ruby/core/fiber/inspect_spec.rb1
-rw-r--r--spec/ruby/core/fiber/raise_spec.rb4
-rw-r--r--spec/ruby/core/fiber/resume_spec.rb15
-rw-r--r--spec/ruby/core/fiber/scheduler_spec.rb8
-rw-r--r--spec/ruby/core/fiber/set_scheduler_spec.rb8
-rw-r--r--spec/ruby/core/fiber/shared/resume.rb58
-rw-r--r--spec/ruby/core/fiber/shared/scheduler.rb51
-rw-r--r--spec/ruby/core/fiber/storage_spec.rb247
-rw-r--r--spec/ruby/core/fiber/transfer_spec.rb84
-rw-r--r--spec/ruby/core/file/birthtime_spec.rb62
-rw-r--r--spec/ruby/core/file/chown_spec.rb16
-rw-r--r--spec/ruby/core/file/constants/constants_spec.rb2
-rw-r--r--spec/ruby/core/file/dirname_spec.rb80
-rw-r--r--spec/ruby/core/file/empty_spec.rb6
-rw-r--r--spec/ruby/core/file/exist_spec.rb8
-rw-r--r--spec/ruby/core/file/flock_spec.rb32
-rw-r--r--spec/ruby/core/file/lchmod_spec.rb2
-rw-r--r--spec/ruby/core/file/path_spec.rb41
-rw-r--r--spec/ruby/core/file/setuid_spec.rb4
-rw-r--r--spec/ruby/core/file/shared/path.rb12
-rw-r--r--spec/ruby/core/file/shared/update_time.rb2
-rw-r--r--spec/ruby/core/file/socket_spec.rb32
-rw-r--r--spec/ruby/core/file/stat/birthtime_spec.rb34
-rw-r--r--spec/ruby/core/file/stat/rdev_major_spec.rb13
-rw-r--r--spec/ruby/core/file/stat/rdev_minor_spec.rb13
-rw-r--r--spec/ruby/core/file/zero_spec.rb6
-rw-r--r--spec/ruby/core/filetest/exist_spec.rb8
-rw-r--r--spec/ruby/core/filetest/socket_spec.rb4
-rw-r--r--spec/ruby/core/filetest/zero_spec.rb6
-rw-r--r--spec/ruby/core/float/ceil_spec.rb5
-rw-r--r--spec/ruby/core/float/comparison_spec.rb4
-rw-r--r--spec/ruby/core/float/floor_spec.rb5
-rw-r--r--spec/ruby/core/float/round_spec.rb9
-rw-r--r--spec/ruby/core/gc/config_spec.rb83
-rw-r--r--spec/ruby/core/gc/measure_total_time_spec.rb24
-rw-r--r--spec/ruby/core/gc/total_time_spec.rb18
-rw-r--r--spec/ruby/core/hash/compact_spec.rb2
-rw-r--r--spec/ruby/core/hash/constructor_spec.rb11
-rw-r--r--spec/ruby/core/hash/element_reference_spec.rb2
-rw-r--r--spec/ruby/core/hash/except_spec.rb28
-rw-r--r--spec/ruby/core/hash/hash_spec.rb10
-rw-r--r--spec/ruby/core/hash/invert_spec.rb21
-rw-r--r--spec/ruby/core/hash/merge_spec.rb23
-rw-r--r--spec/ruby/core/hash/new_spec.rb20
-rw-r--r--spec/ruby/core/hash/reject_spec.rb21
-rw-r--r--spec/ruby/core/hash/replace_spec.rb76
-rw-r--r--spec/ruby/core/hash/shared/replace.rb51
-rw-r--r--spec/ruby/core/hash/shared/select.rb21
-rw-r--r--spec/ruby/core/hash/shared/store.rb6
-rw-r--r--spec/ruby/core/hash/shared/to_s.rb52
-rw-r--r--spec/ruby/core/hash/shift_spec.rb41
-rw-r--r--spec/ruby/core/hash/slice_spec.rb21
-rw-r--r--spec/ruby/core/hash/to_h_spec.rb38
-rw-r--r--spec/ruby/core/hash/transform_keys_spec.rb45
-rw-r--r--spec/ruby/core/hash/transform_values_spec.rb21
-rw-r--r--spec/ruby/core/integer/ceil_spec.rb5
-rw-r--r--spec/ruby/core/integer/ceildiv_spec.rb26
-rw-r--r--spec/ruby/core/integer/chr_spec.rb18
-rw-r--r--spec/ruby/core/integer/constants_spec.rb36
-rw-r--r--spec/ruby/core/integer/divide_spec.rb37
-rw-r--r--spec/ruby/core/integer/floor_spec.rb12
-rw-r--r--spec/ruby/core/integer/left_shift_spec.rb6
-rw-r--r--spec/ruby/core/integer/minus_spec.rb17
-rw-r--r--spec/ruby/core/integer/plus_spec.rb17
-rw-r--r--spec/ruby/core/integer/pow_spec.rb8
-rw-r--r--spec/ruby/core/integer/remainder_spec.rb4
-rw-r--r--spec/ruby/core/integer/right_shift_spec.rb6
-rw-r--r--spec/ruby/core/integer/round_spec.rb6
-rw-r--r--spec/ruby/core/integer/shared/exponent.rb40
-rw-r--r--spec/ruby/core/integer/shared/integer_ceil_precision.rb43
-rw-r--r--spec/ruby/core/integer/shared/integer_floor_precision.rb43
-rw-r--r--spec/ruby/core/integer/shared/modulo.rb46
-rw-r--r--spec/ruby/core/integer/size_spec.rb4
-rw-r--r--spec/ruby/core/integer/try_convert_spec.rb76
-rw-r--r--spec/ruby/core/io/autoclose_spec.rb77
-rw-r--r--spec/ruby/core/io/binread_spec.rb2
-rw-r--r--spec/ruby/core/io/buffer/empty_spec.rb29
-rw-r--r--spec/ruby/core/io/buffer/external_spec.rb108
-rw-r--r--spec/ruby/core/io/buffer/free_spec.rb104
-rw-r--r--spec/ruby/core/io/buffer/initialize_spec.rb103
-rw-r--r--spec/ruby/core/io/buffer/internal_spec.rb108
-rw-r--r--spec/ruby/core/io/buffer/locked_spec.rb75
-rw-r--r--spec/ruby/core/io/buffer/mapped_spec.rb108
-rw-r--r--spec/ruby/core/io/buffer/null_spec.rb29
-rw-r--r--spec/ruby/core/io/buffer/private_spec.rb111
-rw-r--r--spec/ruby/core/io/buffer/readonly_spec.rb143
-rw-r--r--spec/ruby/core/io/buffer/resize_spec.rb155
-rw-r--r--spec/ruby/core/io/buffer/shared/null_and_empty.rb59
-rw-r--r--spec/ruby/core/io/buffer/shared_spec.rb117
-rw-r--r--spec/ruby/core/io/buffer/transfer_spec.rb118
-rw-r--r--spec/ruby/core/io/buffer/valid_spec.rb110
-rw-r--r--spec/ruby/core/io/dup_spec.rb30
-rw-r--r--spec/ruby/core/io/external_encoding_spec.rb10
-rw-r--r--spec/ruby/core/io/foreach_spec.rb46
-rw-r--r--spec/ruby/core/io/internal_encoding_spec.rb10
-rw-r--r--spec/ruby/core/io/path_spec.rb14
-rw-r--r--spec/ruby/core/io/popen_spec.rb16
-rw-r--r--spec/ruby/core/io/pread_spec.rb6
-rw-r--r--spec/ruby/core/io/puts_spec.rb2
-rw-r--r--spec/ruby/core/io/read_spec.rb112
-rw-r--r--spec/ruby/core/io/readlines_spec.rb62
-rw-r--r--spec/ruby/core/io/readpartial_spec.rb17
-rw-r--r--spec/ruby/core/io/set_encoding_by_bom_spec.rb8
-rw-r--r--spec/ruby/core/io/shared/each.rb18
-rw-r--r--spec/ruby/core/io/shared/gets_ascii.rb2
-rw-r--r--spec/ruby/core/io/shared/new.rb23
-rw-r--r--spec/ruby/core/io/sysread_spec.rb6
-rw-r--r--spec/ruby/core/io/write_nonblock_spec.rb2
-rw-r--r--spec/ruby/core/io/write_spec.rb2
-rw-r--r--spec/ruby/core/kernel/Float_spec.rb154
-rw-r--r--spec/ruby/core/kernel/Rational_spec.rb234
-rw-r--r--spec/ruby/core/kernel/autoload_spec.rb5
-rw-r--r--spec/ruby/core/kernel/block_given_spec.rb5
-rw-r--r--spec/ruby/core/kernel/caller_locations_spec.rb14
-rw-r--r--spec/ruby/core/kernel/caller_spec.rb57
-rw-r--r--spec/ruby/core/kernel/eval_spec.rb105
-rw-r--r--spec/ruby/core/kernel/extend_spec.rb12
-rw-r--r--spec/ruby/core/kernel/fixtures/classes.rb54
-rw-r--r--spec/ruby/core/kernel/format_spec.rb32
-rw-r--r--spec/ruby/core/kernel/inspect_spec.rb59
-rw-r--r--spec/ruby/core/kernel/is_a_spec.rb2
-rw-r--r--spec/ruby/core/kernel/kind_of_spec.rb2
-rw-r--r--spec/ruby/core/kernel/match_spec.rb27
-rw-r--r--spec/ruby/core/kernel/not_match_spec.rb14
-rw-r--r--spec/ruby/core/kernel/open_spec.rb96
-rw-r--r--spec/ruby/core/kernel/raise_spec.rb237
-rw-r--r--spec/ruby/core/kernel/require_spec.rb16
-rw-r--r--spec/ruby/core/kernel/select_spec.rb4
-rw-r--r--spec/ruby/core/kernel/shared/load.rb48
-rw-r--r--spec/ruby/core/kernel/shared/require.rb34
-rw-r--r--spec/ruby/core/kernel/shared/sprintf.rb36
-rw-r--r--spec/ruby/core/kernel/singleton_method_spec.rb46
-rw-r--r--spec/ruby/core/kernel/sleep_spec.rb48
-rw-r--r--spec/ruby/core/kernel/sprintf_spec.rb36
-rw-r--r--spec/ruby/core/kernel/taint_spec.rb23
-rw-r--r--spec/ruby/core/kernel/tainted_spec.rb25
-rw-r--r--spec/ruby/core/kernel/trust_spec.rb24
-rw-r--r--spec/ruby/core/kernel/untaint_spec.rb24
-rw-r--r--spec/ruby/core/kernel/untrust_spec.rb23
-rw-r--r--spec/ruby/core/kernel/untrusted_spec.rb24
-rw-r--r--spec/ruby/core/kernel/warn_spec.rb6
-rw-r--r--spec/ruby/core/main/private_spec.rb12
-rw-r--r--spec/ruby/core/main/public_spec.rb12
-rw-r--r--spec/ruby/core/main/using_spec.rb10
-rw-r--r--spec/ruby/core/marshal/dump_spec.rb282
-rw-r--r--spec/ruby/core/marshal/fixtures/marshal_data.rb75
-rw-r--r--spec/ruby/core/marshal/fixtures/marshal_multibyte_data.rb12
-rw-r--r--spec/ruby/core/marshal/shared/load.rb516
-rw-r--r--spec/ruby/core/matchdata/bytebegin_spec.rb132
-rw-r--r--spec/ruby/core/matchdata/byteend_spec.rb104
-rw-r--r--spec/ruby/core/matchdata/byteoffset_spec.rb132
-rw-r--r--spec/ruby/core/matchdata/deconstruct_keys_spec.rb86
-rw-r--r--spec/ruby/core/matchdata/deconstruct_spec.rb4
-rw-r--r--spec/ruby/core/matchdata/element_reference_spec.rb5
-rw-r--r--spec/ruby/core/matchdata/match_length_spec.rb46
-rw-r--r--spec/ruby/core/matchdata/match_spec.rb46
-rw-r--r--spec/ruby/core/matchdata/offset_spec.rb106
-rw-r--r--spec/ruby/core/math/atanh_spec.rb4
-rw-r--r--spec/ruby/core/math/expm1_spec.rb37
-rw-r--r--spec/ruby/core/math/fixtures/common.rb (renamed from spec/ruby/fixtures/math/common.rb)0
-rw-r--r--spec/ruby/core/math/lgamma_spec.rb11
-rw-r--r--spec/ruby/core/math/log1p_spec.rb49
-rw-r--r--spec/ruby/core/math/shared/atanh.rb (renamed from spec/ruby/shared/math/atanh.rb)0
-rw-r--r--spec/ruby/core/method/owner_spec.rb6
-rw-r--r--spec/ruby/core/method/parameters_spec.rb53
-rw-r--r--spec/ruby/core/method/private_spec.rb25
-rw-r--r--spec/ruby/core/method/protected_spec.rb25
-rw-r--r--spec/ruby/core/method/public_spec.rb25
-rw-r--r--spec/ruby/core/method/shared/dup.rb2
-rw-r--r--spec/ruby/core/method/source_location_spec.rb16
-rw-r--r--spec/ruby/core/method/unbind_spec.rb12
-rw-r--r--spec/ruby/core/module/ancestors_spec.rb26
-rw-r--r--spec/ruby/core/module/autoload_spec.rb161
-rw-r--r--spec/ruby/core/module/const_added_spec.rb272
-rw-r--r--spec/ruby/core/module/const_defined_spec.rb2
-rw-r--r--spec/ruby/core/module/const_get_spec.rb24
-rw-r--r--spec/ruby/core/module/const_set_spec.rb13
-rw-r--r--spec/ruby/core/module/const_source_location_spec.rb34
-rw-r--r--spec/ruby/core/module/define_method_spec.rb3
-rw-r--r--spec/ruby/core/module/deprecate_constant_spec.rb9
-rw-r--r--spec/ruby/core/module/fixtures/classes.rb2
-rw-r--r--spec/ruby/core/module/fixtures/const_added.rb4
-rw-r--r--spec/ruby/core/module/fixtures/name.rb3
-rw-r--r--spec/ruby/core/module/fixtures/set_temporary_name.rb4
-rw-r--r--spec/ruby/core/module/include_spec.rb69
-rw-r--r--spec/ruby/core/module/instance_method_spec.rb5
-rw-r--r--spec/ruby/core/module/module_function_spec.rb37
-rw-r--r--spec/ruby/core/module/name_spec.rb53
-rw-r--r--spec/ruby/core/module/new_spec.rb4
-rw-r--r--spec/ruby/core/module/prepend_spec.rb85
-rw-r--r--spec/ruby/core/module/private_spec.rb26
-rw-r--r--spec/ruby/core/module/protected_spec.rb26
-rw-r--r--spec/ruby/core/module/public_spec.rb26
-rw-r--r--spec/ruby/core/module/refine_spec.rb339
-rw-r--r--spec/ruby/core/module/refinements_spec.rb56
-rw-r--r--spec/ruby/core/module/remove_const_spec.rb2
-rw-r--r--spec/ruby/core/module/ruby2_keywords_spec.rb171
-rw-r--r--spec/ruby/core/module/set_temporary_name_spec.rb85
-rw-r--r--spec/ruby/core/module/to_s_spec.rb2
-rw-r--r--spec/ruby/core/module/undefined_instance_methods_spec.rb32
-rw-r--r--spec/ruby/core/module/used_refinements_spec.rb110
-rw-r--r--spec/ruby/core/numeric/shared/imag.rb6
-rw-r--r--spec/ruby/core/numeric/shared/rect.rb26
-rw-r--r--spec/ruby/core/objectspace/_id2ref_spec.rb87
-rw-r--r--spec/ruby/core/objectspace/add_finalizer_spec.rb5
-rw-r--r--spec/ruby/core/objectspace/call_finalizer_spec.rb5
-rw-r--r--spec/ruby/core/objectspace/define_finalizer_spec.rb55
-rw-r--r--spec/ruby/core/objectspace/finalizers_spec.rb5
-rw-r--r--spec/ruby/core/objectspace/remove_finalizer_spec.rb5
-rw-r--r--spec/ruby/core/objectspace/undefine_finalizer_spec.rb30
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/clear_spec.rb27
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/delete_spec.rb13
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/element_reference_spec.rb83
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/element_set_spec.rb59
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/fixtures/classes.rb5
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/getkey_spec.rb14
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/inspect_spec.rb4
-rw-r--r--spec/ruby/core/objectspace/weakkeymap/key_spec.rb11
-rw-r--r--spec/ruby/core/proc/clone_spec.rb15
-rw-r--r--spec/ruby/core/proc/curry_spec.rb9
-rw-r--r--spec/ruby/core/proc/dup_spec.rb15
-rw-r--r--spec/ruby/core/proc/element_reference_spec.rb2
-rw-r--r--spec/ruby/core/proc/fixtures/common.rb23
-rw-r--r--spec/ruby/core/proc/parameters_spec.rb78
-rw-r--r--spec/ruby/core/proc/ruby2_keywords_spec.rb14
-rw-r--r--spec/ruby/core/proc/shared/dup.rb10
-rw-r--r--spec/ruby/core/proc/source_location_spec.rb51
-rw-r--r--spec/ruby/core/process/_fork_spec.rb30
-rw-r--r--spec/ruby/core/process/constants_spec.rb116
-rw-r--r--spec/ruby/core/process/daemon_spec.rb3
-rw-r--r--spec/ruby/core/process/fixtures/clocks.rb2
-rw-r--r--spec/ruby/core/process/gid_spec.rb4
-rw-r--r--spec/ruby/core/process/setrlimit_spec.rb28
-rw-r--r--spec/ruby/core/process/status/bit_and_spec.rb37
-rw-r--r--spec/ruby/core/process/status/right_shift_spec.rb36
-rw-r--r--spec/ruby/core/process/tms/cstime_spec.rb17
-rw-r--r--spec/ruby/core/process/tms/cutime_spec.rb17
-rw-r--r--spec/ruby/core/process/tms/stime_spec.rb17
-rw-r--r--spec/ruby/core/process/tms/utime_spec.rb17
-rw-r--r--spec/ruby/core/queue/deq_spec.rb4
-rw-r--r--spec/ruby/core/queue/freeze_spec.rb6
-rw-r--r--spec/ruby/core/queue/initialize_spec.rb64
-rw-r--r--spec/ruby/core/queue/pop_spec.rb4
-rw-r--r--spec/ruby/core/queue/shift_spec.rb4
-rw-r--r--spec/ruby/core/random/bytes_spec.rb2
-rw-r--r--spec/ruby/core/random/default_spec.rb32
-rw-r--r--spec/ruby/core/random/new_spec.rb2
-rw-r--r--spec/ruby/core/range/case_compare_spec.rb2
-rw-r--r--spec/ruby/core/range/cover_spec.rb2
-rw-r--r--spec/ruby/core/range/each_spec.rb35
-rw-r--r--spec/ruby/core/range/include_spec.rb2
-rw-r--r--spec/ruby/core/range/last_spec.rb6
-rw-r--r--spec/ruby/core/range/max_spec.rb20
-rw-r--r--spec/ruby/core/range/member_spec.rb2
-rw-r--r--spec/ruby/core/range/overlap_spec.rb89
-rw-r--r--spec/ruby/core/range/reverse_each_spec.rb103
-rw-r--r--spec/ruby/core/range/shared/cover.rb2
-rw-r--r--spec/ruby/core/range/shared/cover_and_include.rb17
-rw-r--r--spec/ruby/core/range/shared/include.rb2
-rw-r--r--spec/ruby/core/range/size_spec.rb11
-rw-r--r--spec/ruby/core/range/step_spec.rb383
-rw-r--r--spec/ruby/core/range/to_set_spec.rb55
-rw-r--r--spec/ruby/core/rational/abs_spec.rb2
-rw-r--r--spec/ruby/core/rational/ceil_spec.rb43
-rw-r--r--spec/ruby/core/rational/comparison_spec.rb84
-rw-r--r--spec/ruby/core/rational/denominator_spec.rb12
-rw-r--r--spec/ruby/core/rational/div_spec.rb46
-rw-r--r--spec/ruby/core/rational/divide_spec.rb66
-rw-r--r--spec/ruby/core/rational/divmod_spec.rb36
-rw-r--r--spec/ruby/core/rational/equal_value_spec.rb31
-rw-r--r--spec/ruby/core/rational/exponent_spec.rb234
-rw-r--r--spec/ruby/core/rational/fdiv_spec.rb3
-rw-r--r--spec/ruby/core/rational/fixtures/rational.rb (renamed from spec/ruby/fixtures/rational.rb)0
-rw-r--r--spec/ruby/core/rational/floor_spec.rb43
-rw-r--r--spec/ruby/core/rational/hash_spec.rb7
-rw-r--r--spec/ruby/core/rational/inspect_spec.rb12
-rw-r--r--spec/ruby/core/rational/magnitude_spec.rb2
-rw-r--r--spec/ruby/core/rational/minus_spec.rb2
-rw-r--r--spec/ruby/core/rational/modulo_spec.rb41
-rw-r--r--spec/ruby/core/rational/multiply_spec.rb57
-rw-r--r--spec/ruby/core/rational/numerator_spec.rb8
-rw-r--r--spec/ruby/core/rational/plus_spec.rb43
-rw-r--r--spec/ruby/core/rational/quo_spec.rb23
-rw-r--r--spec/ruby/core/rational/remainder_spec.rb3
-rw-r--r--spec/ruby/core/rational/round_spec.rb104
-rw-r--r--spec/ruby/core/rational/shared/abs.rb11
-rw-r--r--spec/ruby/core/rational/shared/arithmetic_exception_in_coerce.rb11
-rw-r--r--spec/ruby/core/rational/to_f_spec.rb14
-rw-r--r--spec/ruby/core/rational/to_i_spec.rb10
-rw-r--r--spec/ruby/core/rational/to_r_spec.rb9
-rw-r--r--spec/ruby/core/rational/to_s_spec.rb12
-rw-r--r--spec/ruby/core/rational/truncate_spec.rb69
-rw-r--r--spec/ruby/core/refinement/append_features_spec.rb24
-rw-r--r--spec/ruby/core/refinement/extend_object_spec.rb28
-rw-r--r--spec/ruby/core/refinement/import_methods_spec.rb354
-rw-r--r--spec/ruby/core/refinement/include_spec.rb26
-rw-r--r--spec/ruby/core/refinement/prepend_features_spec.rb24
-rw-r--r--spec/ruby/core/refinement/prepend_spec.rb26
-rw-r--r--spec/ruby/core/refinement/refined_class_spec.rb29
-rw-r--r--spec/ruby/core/refinement/shared/target.rb13
-rw-r--r--spec/ruby/core/refinement/target_spec.rb8
-rw-r--r--spec/ruby/core/regexp/compile_spec.rb2
-rw-r--r--spec/ruby/core/regexp/linear_time_spec.rb42
-rw-r--r--spec/ruby/core/regexp/new_spec.rb2
-rw-r--r--spec/ruby/core/regexp/shared/new.rb426
-rw-r--r--spec/ruby/core/regexp/shared/quote.rb6
-rw-r--r--spec/ruby/core/regexp/timeout_spec.rb48
-rw-r--r--spec/ruby/core/set/add_spec.rb34
-rw-r--r--spec/ruby/core/set/append_spec.rb6
-rw-r--r--spec/ruby/core/set/case_compare_spec.rb11
-rw-r--r--spec/ruby/core/set/case_equality_spec.rb6
-rw-r--r--spec/ruby/core/set/classify_spec.rb26
-rw-r--r--spec/ruby/core/set/clear_spec.rb16
-rw-r--r--spec/ruby/core/set/collect_spec.rb6
-rw-r--r--spec/ruby/core/set/compare_by_identity_spec.rb153
-rw-r--r--spec/ruby/core/set/comparison_spec.rb26
-rw-r--r--spec/ruby/core/set/constructor_spec.rb14
-rw-r--r--spec/ruby/core/set/delete_if_spec.rb37
-rw-r--r--spec/ruby/core/set/delete_spec.rb36
-rw-r--r--spec/ruby/core/set/difference_spec.rb6
-rw-r--r--spec/ruby/core/set/disjoint_spec.rb22
-rw-r--r--spec/ruby/core/set/divide_spec.rb68
-rw-r--r--spec/ruby/core/set/each_spec.rb26
-rw-r--r--spec/ruby/core/set/empty_spec.rb9
-rw-r--r--spec/ruby/core/set/enumerable/to_set_spec.rb12
-rw-r--r--spec/ruby/core/set/eql_spec.rb14
-rw-r--r--spec/ruby/core/set/equal_value_spec.rb34
-rw-r--r--spec/ruby/core/set/exclusion_spec.rb17
-rw-r--r--spec/ruby/core/set/filter_spec.rb (renamed from spec/ruby/library/set/filter_spec.rb)0
-rw-r--r--spec/ruby/core/set/fixtures/set_like.rb30
-rw-r--r--spec/ruby/core/set/flatten_merge_spec.rb24
-rw-r--r--spec/ruby/core/set/flatten_spec.rb59
-rw-r--r--spec/ruby/core/set/hash_spec.rb19
-rw-r--r--spec/ruby/core/set/include_spec.rb6
-rw-r--r--spec/ruby/core/set/initialize_clone_spec.rb15
-rw-r--r--spec/ruby/core/set/initialize_spec.rb72
-rw-r--r--spec/ruby/core/set/inspect_spec.rb6
-rw-r--r--spec/ruby/core/set/intersect_spec.rb22
-rw-r--r--spec/ruby/core/set/intersection_spec.rb10
-rw-r--r--spec/ruby/core/set/join_spec.rb30
-rw-r--r--spec/ruby/core/set/keep_if_spec.rb37
-rw-r--r--spec/ruby/core/set/length_spec.rb6
-rw-r--r--spec/ruby/core/set/map_spec.rb6
-rw-r--r--spec/ruby/core/set/member_spec.rb6
-rw-r--r--spec/ruby/core/set/merge_spec.rb37
-rw-r--r--spec/ruby/core/set/minus_spec.rb6
-rw-r--r--spec/ruby/core/set/plus_spec.rb6
-rw-r--r--spec/ruby/core/set/pretty_print_cycle_spec.rb14
-rw-r--r--spec/ruby/core/set/proper_subset_spec.rb45
-rw-r--r--spec/ruby/core/set/proper_superset_spec.rb42
-rw-r--r--spec/ruby/core/set/reject_spec.rb41
-rw-r--r--spec/ruby/core/set/replace_spec.rb24
-rw-r--r--spec/ruby/core/set/select_spec.rb (renamed from spec/ruby/library/set/select_spec.rb)0
-rw-r--r--spec/ruby/core/set/set_spec.rb10
-rw-r--r--spec/ruby/core/set/shared/add.rb (renamed from spec/ruby/library/set/shared/add.rb)0
-rw-r--r--spec/ruby/core/set/shared/collect.rb (renamed from spec/ruby/library/set/shared/collect.rb)0
-rw-r--r--spec/ruby/core/set/shared/difference.rb (renamed from spec/ruby/library/set/shared/difference.rb)0
-rw-r--r--spec/ruby/core/set/shared/include.rb (renamed from spec/ruby/library/set/shared/include.rb)0
-rw-r--r--spec/ruby/core/set/shared/inspect.rb45
-rw-r--r--spec/ruby/core/set/shared/intersection.rb (renamed from spec/ruby/library/set/shared/intersection.rb)0
-rw-r--r--spec/ruby/core/set/shared/length.rb (renamed from spec/ruby/library/set/shared/length.rb)0
-rw-r--r--spec/ruby/core/set/shared/select.rb41
-rw-r--r--spec/ruby/core/set/shared/union.rb (renamed from spec/ruby/library/set/shared/union.rb)0
-rw-r--r--spec/ruby/core/set/size_spec.rb6
-rw-r--r--spec/ruby/core/set/sortedset/sortedset_spec.rb13
-rw-r--r--spec/ruby/core/set/subset_spec.rb45
-rw-r--r--spec/ruby/core/set/subtract_spec.rb16
-rw-r--r--spec/ruby/core/set/superset_spec.rb42
-rw-r--r--spec/ruby/core/set/to_a_spec.rb7
-rw-r--r--spec/ruby/core/set/to_s_spec.rb11
-rw-r--r--spec/ruby/core/set/union_spec.rb10
-rw-r--r--spec/ruby/core/sizedqueue/append_spec.rb4
-rw-r--r--spec/ruby/core/sizedqueue/deq_spec.rb4
-rw-r--r--spec/ruby/core/sizedqueue/enq_spec.rb4
-rw-r--r--spec/ruby/core/sizedqueue/freeze_spec.rb6
-rw-r--r--spec/ruby/core/sizedqueue/pop_spec.rb4
-rw-r--r--spec/ruby/core/sizedqueue/push_spec.rb4
-rw-r--r--spec/ruby/core/sizedqueue/shift_spec.rb4
-rw-r--r--spec/ruby/core/string/append_as_bytes_spec.rb58
-rw-r--r--spec/ruby/core/string/byteindex_spec.rb470
-rw-r--r--spec/ruby/core/string/byterindex_spec.rb568
-rw-r--r--spec/ruby/core/string/byteslice_spec.rb4
-rw-r--r--spec/ruby/core/string/bytesplice_spec.rb308
-rw-r--r--spec/ruby/core/string/chilled_string_spec.rb174
-rw-r--r--spec/ruby/core/string/codepoints_spec.rb2
-rw-r--r--spec/ruby/core/string/count_spec.rb2
-rw-r--r--spec/ruby/core/string/dedup_spec.rb4
-rw-r--r--spec/ruby/core/string/encode_spec.rb16
-rw-r--r--spec/ruby/core/string/lstrip_spec.rb14
-rw-r--r--spec/ruby/core/string/modulo_spec.rb20
-rw-r--r--spec/ruby/core/string/rindex_spec.rb4
-rw-r--r--spec/ruby/core/string/rstrip_spec.rb28
-rw-r--r--spec/ruby/core/string/scan_spec.rb20
-rw-r--r--spec/ruby/core/string/shared/codepoints.rb2
-rw-r--r--spec/ruby/core/string/shared/dedup.rb5
-rw-r--r--spec/ruby/core/string/shared/each_codepoint_without_block.rb2
-rw-r--r--spec/ruby/core/string/shared/encode.rb184
-rw-r--r--spec/ruby/core/string/shared/eql.rb2
-rw-r--r--spec/ruby/core/string/shared/slice.rb17
-rw-r--r--spec/ruby/core/string/shared/succ.rb2
-rw-r--r--spec/ruby/core/string/squeeze_spec.rb2
-rw-r--r--spec/ruby/core/string/sub_spec.rb16
-rw-r--r--spec/ruby/core/string/swapcase_spec.rb6
-rw-r--r--spec/ruby/core/string/to_c_spec.rb36
-rw-r--r--spec/ruby/core/string/to_f_spec.rb106
-rw-r--r--spec/ruby/core/string/to_i_spec.rb2
-rw-r--r--spec/ruby/core/string/to_r_spec.rb4
-rw-r--r--spec/ruby/core/string/unpack/a_spec.rb2
-rw-r--r--spec/ruby/core/string/unpack/at_spec.rb2
-rw-r--r--spec/ruby/core/string/unpack/b_spec.rb2
-rw-r--r--spec/ruby/core/string/unpack/c_spec.rb2
-rw-r--r--spec/ruby/core/string/unpack/comment_spec.rb2
-rw-r--r--spec/ruby/core/string/unpack/h_spec.rb2
-rw-r--r--spec/ruby/core/string/unpack/l_spec.rb16
-rw-r--r--spec/ruby/core/string/unpack/m_spec.rb2
-rw-r--r--spec/ruby/core/string/unpack/shared/basic.rb16
-rw-r--r--spec/ruby/core/string/unpack/shared/float.rb2
-rw-r--r--spec/ruby/core/string/unpack/shared/integer.rb2
-rw-r--r--spec/ruby/core/string/unpack/u_spec.rb2
-rw-r--r--spec/ruby/core/string/unpack/w_spec.rb2
-rw-r--r--spec/ruby/core/string/unpack/x_spec.rb2
-rw-r--r--spec/ruby/core/string/unpack/z_spec.rb2
-rw-r--r--spec/ruby/core/string/unpack1_spec.rb47
-rw-r--r--spec/ruby/core/string/unpack_spec.rb32
-rw-r--r--spec/ruby/core/string/uplus_spec.rb44
-rw-r--r--spec/ruby/core/struct/constants_spec.rb16
-rw-r--r--spec/ruby/core/struct/deconstruct_keys_spec.rb54
-rw-r--r--spec/ruby/core/struct/element_set_spec.rb7
-rw-r--r--spec/ruby/core/struct/fixtures/classes.rb2
-rw-r--r--spec/ruby/core/struct/initialize_spec.rb20
-rw-r--r--spec/ruby/core/struct/keyword_init_spec.rb61
-rw-r--r--spec/ruby/core/struct/members_spec.rb12
-rw-r--r--spec/ruby/core/struct/new_spec.rb72
-rw-r--r--spec/ruby/core/struct/struct_spec.rb7
-rw-r--r--spec/ruby/core/struct/to_h_spec.rb12
-rw-r--r--spec/ruby/core/symbol/inspect_spec.rb15
-rw-r--r--spec/ruby/core/symbol/shared/id2name.rb14
-rw-r--r--spec/ruby/core/symbol/shared/slice.rb2
-rw-r--r--spec/ruby/core/symbol/to_proc_spec.rb44
-rw-r--r--spec/ruby/core/thread/abort_on_exception_spec.rb2
-rw-r--r--spec/ruby/core/thread/backtrace/limit_spec.rb18
-rw-r--r--spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb17
-rw-r--r--spec/ruby/core/thread/each_caller_location_spec.rb70
-rw-r--r--spec/ruby/core/thread/element_reference_spec.rb11
-rw-r--r--spec/ruby/core/thread/element_set_spec.rb25
-rw-r--r--spec/ruby/core/thread/fixtures/classes.rb25
-rw-r--r--spec/ruby/core/thread/group_spec.rb15
-rw-r--r--spec/ruby/core/thread/key_spec.rb7
-rw-r--r--spec/ruby/core/thread/native_thread_id_spec.rb52
-rw-r--r--spec/ruby/core/thread/raise_spec.rb3
-rw-r--r--spec/ruby/core/thread/thread_variable_get_spec.rb39
-rw-r--r--spec/ruby/core/thread/thread_variable_set_spec.rb42
-rw-r--r--spec/ruby/core/thread/thread_variable_spec.rb43
-rw-r--r--spec/ruby/core/thread/thread_variables_spec.rb22
-rw-r--r--spec/ruby/core/time/_dump_spec.rb2
-rw-r--r--spec/ruby/core/time/_load_spec.rb2
-rw-r--r--spec/ruby/core/time/at_spec.rb36
-rw-r--r--spec/ruby/core/time/comparison_spec.rb26
-rw-r--r--spec/ruby/core/time/deconstruct_keys_spec.rb80
-rw-r--r--spec/ruby/core/time/getlocal_spec.rb39
-rw-r--r--spec/ruby/core/time/iso8601_spec.rb6
-rw-r--r--spec/ruby/core/time/localtime_spec.rb51
-rw-r--r--spec/ruby/core/time/minus_spec.rb2
-rw-r--r--spec/ruby/core/time/new_spec.rb579
-rw-r--r--spec/ruby/core/time/now_spec.rb184
-rw-r--r--spec/ruby/core/time/shared/gmtime.rb9
-rw-r--r--spec/ruby/core/time/shared/time_params.rb4
-rw-r--r--spec/ruby/core/time/shared/xmlschema.rb31
-rw-r--r--spec/ruby/core/time/strftime_spec.rb62
-rw-r--r--spec/ruby/core/time/utc_spec.rb26
-rw-r--r--spec/ruby/core/time/xmlschema_spec.rb6
-rw-r--r--spec/ruby/core/time/yday_spec.rb13
-rw-r--r--spec/ruby/core/time/zone_spec.rb22
-rw-r--r--spec/ruby/core/tracepoint/allow_reentry_spec.rb44
-rw-r--r--spec/ruby/core/tracepoint/enable_spec.rb55
-rw-r--r--spec/ruby/core/tracepoint/inspect_spec.rb13
-rw-r--r--spec/ruby/core/tracepoint/raised_exception_spec.rb18
-rw-r--r--spec/ruby/core/unboundmethod/equal_value_spec.rb39
-rw-r--r--spec/ruby/core/unboundmethod/owner_spec.rb6
-rw-r--r--spec/ruby/core/unboundmethod/private_spec.rb25
-rw-r--r--spec/ruby/core/unboundmethod/protected_spec.rb25
-rw-r--r--spec/ruby/core/unboundmethod/public_spec.rb25
-rw-r--r--spec/ruby/core/unboundmethod/shared/dup.rb2
-rw-r--r--spec/ruby/core/unboundmethod/shared/to_s.rb15
-rw-r--r--spec/ruby/core/unboundmethod/source_location_spec.rb18
-rw-r--r--spec/ruby/core/warning/categories_spec.rb12
-rw-r--r--spec/ruby/core/warning/warn_spec.rb52
-rw-r--r--spec/ruby/default.mspec5
-rw-r--r--spec/ruby/fixtures/constants.rb2
-rw-r--r--spec/ruby/fixtures/io.rb12
-rw-r--r--spec/ruby/language/assignments_spec.rb355
-rw-r--r--spec/ruby/language/block_spec.rb267
-rw-r--r--spec/ruby/language/case_spec.rb2
-rw-r--r--spec/ruby/language/class_spec.rb44
-rw-r--r--spec/ruby/language/constants_spec.rb113
-rw-r--r--spec/ruby/language/def_spec.rb55
-rw-r--r--spec/ruby/language/defined_spec.rb4
-rw-r--r--spec/ruby/language/delegation_spec.rb109
-rw-r--r--spec/ruby/language/ensure_spec.rb6
-rw-r--r--spec/ruby/language/fixtures/class_with_class_variable.rb9
-rw-r--r--spec/ruby/language/fixtures/defined.rb6
-rw-r--r--spec/ruby/language/fixtures/delegation.rb4
-rw-r--r--spec/ruby/language/fixtures/module.rb9
-rw-r--r--spec/ruby/language/fixtures/private.rb26
-rw-r--r--spec/ruby/language/fixtures/send.rb16
-rw-r--r--spec/ruby/language/for_spec.rb103
-rw-r--r--spec/ruby/language/hash_spec.rb130
-rw-r--r--spec/ruby/language/heredoc_spec.rb10
-rw-r--r--spec/ruby/language/it_parameter_spec.rb66
-rw-r--r--spec/ruby/language/keyword_arguments_spec.rb80
-rw-r--r--spec/ruby/language/lambda_spec.rb23
-rw-r--r--spec/ruby/language/magic_comment_spec.rb3
-rw-r--r--spec/ruby/language/method_spec.rb249
-rw-r--r--spec/ruby/language/module_spec.rb51
-rw-r--r--spec/ruby/language/numbered_parameters_spec.rb15
-rw-r--r--spec/ruby/language/optional_assignments_spec.rb2
-rw-r--r--spec/ruby/language/pattern_matching_spec.rb1527
-rw-r--r--spec/ruby/language/precedence_spec.rb16
-rw-r--r--spec/ruby/language/predefined_spec.rb311
-rw-r--r--spec/ruby/language/private_spec.rb2
-rw-r--r--spec/ruby/language/proc_spec.rb2
-rw-r--r--spec/ruby/language/regexp/anchors_spec.rb8
-rw-r--r--spec/ruby/language/regexp/character_classes_spec.rb13
-rw-r--r--spec/ruby/language/regexp/encoding_spec.rb8
-rw-r--r--spec/ruby/language/regexp/escapes_spec.rb2
-rw-r--r--spec/ruby/language/regexp/grouping_spec.rb2
-rw-r--r--spec/ruby/language/regexp_spec.rb4
-rw-r--r--spec/ruby/language/rescue_spec.rb26
-rw-r--r--spec/ruby/language/reserved_keywords.rb149
-rw-r--r--spec/ruby/language/send_spec.rb18
-rw-r--r--spec/ruby/language/string_spec.rb14
-rw-r--r--spec/ruby/language/super_spec.rb2
-rw-r--r--spec/ruby/language/undef_spec.rb2
-rw-r--r--spec/ruby/language/variables_spec.rb108
-rw-r--r--spec/ruby/library/bigdecimal/BigDecimal_spec.rb56
-rw-r--r--spec/ruby/library/bigdecimal/add_spec.rb8
-rw-r--r--spec/ruby/library/bigdecimal/core_spec.rb7
-rw-r--r--spec/ruby/library/bigdecimal/divmod_spec.rb80
-rw-r--r--spec/ruby/library/bigdecimal/fix_spec.rb28
-rw-r--r--spec/ruby/library/bigdecimal/mult_spec.rb8
-rw-r--r--spec/ruby/library/bigdecimal/precs_spec.rb55
-rw-r--r--spec/ruby/library/bigdecimal/remainder_spec.rb8
-rw-r--r--spec/ruby/library/bigdecimal/round_spec.rb12
-rw-r--r--spec/ruby/library/bigdecimal/shared/modulo.rb14
-rw-r--r--spec/ruby/library/bigdecimal/shared/power.rb4
-rw-r--r--spec/ruby/library/bigdecimal/shared/quo.rb1
-rw-r--r--spec/ruby/library/bigdecimal/split_spec.rb20
-rw-r--r--spec/ruby/library/bigdecimal/sqrt_spec.rb2
-rw-r--r--spec/ruby/library/bigdecimal/sub_spec.rb8
-rw-r--r--spec/ruby/library/bigdecimal/to_i_spec.rb2
-rw-r--r--spec/ruby/library/bigdecimal/truncate_spec.rb10
-rw-r--r--spec/ruby/library/cgi/cookie/domain_spec.rb33
-rw-r--r--spec/ruby/library/cgi/cookie/expires_spec.rb33
-rw-r--r--spec/ruby/library/cgi/cookie/initialize_spec.rb235
-rw-r--r--spec/ruby/library/cgi/cookie/name_spec.rb33
-rw-r--r--spec/ruby/library/cgi/cookie/parse_spec.rb41
-rw-r--r--spec/ruby/library/cgi/cookie/path_spec.rb33
-rw-r--r--spec/ruby/library/cgi/cookie/secure_spec.rb99
-rw-r--r--spec/ruby/library/cgi/cookie/to_s_spec.rb51
-rw-r--r--spec/ruby/library/cgi/cookie/value_spec.rb121
-rw-r--r--spec/ruby/library/cgi/escapeElement_spec.rb8
-rw-r--r--spec/ruby/library/cgi/escapeHTML_spec.rb6
-rw-r--r--spec/ruby/library/cgi/escapeURIComponent_spec.rb105
-rw-r--r--spec/ruby/library/cgi/escape_spec.rb6
-rw-r--r--spec/ruby/library/cgi/htmlextension/a_spec.rb73
-rw-r--r--spec/ruby/library/cgi/htmlextension/base_spec.rb47
-rw-r--r--spec/ruby/library/cgi/htmlextension/blockquote_spec.rb47
-rw-r--r--spec/ruby/library/cgi/htmlextension/br_spec.rb31
-rw-r--r--spec/ruby/library/cgi/htmlextension/caption_spec.rb47
-rw-r--r--spec/ruby/library/cgi/htmlextension/checkbox_group_spec.rb121
-rw-r--r--spec/ruby/library/cgi/htmlextension/checkbox_spec.rb113
-rw-r--r--spec/ruby/library/cgi/htmlextension/doctype_spec.rb41
-rw-r--r--spec/ruby/library/cgi/htmlextension/file_field_spec.rb105
-rw-r--r--spec/ruby/library/cgi/htmlextension/form_spec.rb85
-rw-r--r--spec/ruby/library/cgi/htmlextension/frame_spec.rb21
-rw-r--r--spec/ruby/library/cgi/htmlextension/frameset_spec.rb21
-rw-r--r--spec/ruby/library/cgi/htmlextension/hidden_spec.rb87
-rw-r--r--spec/ruby/library/cgi/htmlextension/html_spec.rb99
-rw-r--r--spec/ruby/library/cgi/htmlextension/image_button_spec.rb101
-rw-r--r--spec/ruby/library/cgi/htmlextension/img_spec.rb123
-rw-r--r--spec/ruby/library/cgi/htmlextension/multipart_form_spec.rb93
-rw-r--r--spec/ruby/library/cgi/htmlextension/password_field_spec.rb123
-rw-r--r--spec/ruby/library/cgi/htmlextension/popup_menu_spec.rb13
-rw-r--r--spec/ruby/library/cgi/htmlextension/radio_button_spec.rb113
-rw-r--r--spec/ruby/library/cgi/htmlextension/radio_group_spec.rb123
-rw-r--r--spec/ruby/library/cgi/htmlextension/reset_spec.rb83
-rw-r--r--spec/ruby/library/cgi/htmlextension/scrolling_list_spec.rb13
-rw-r--r--spec/ruby/library/cgi/htmlextension/submit_spec.rb83
-rw-r--r--spec/ruby/library/cgi/htmlextension/text_field_spec.rb123
-rw-r--r--spec/ruby/library/cgi/htmlextension/textarea_spec.rb107
-rw-r--r--spec/ruby/library/cgi/http_header_spec.rb11
-rw-r--r--spec/ruby/library/cgi/initialize_spec.rb209
-rw-r--r--spec/ruby/library/cgi/out_spec.rb97
-rw-r--r--spec/ruby/library/cgi/parse_spec.rb37
-rw-r--r--spec/ruby/library/cgi/pretty_spec.rb19
-rw-r--r--spec/ruby/library/cgi/print_spec.rb39
-rw-r--r--spec/ruby/library/cgi/queryextension/accept_charset_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/accept_encoding_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/accept_language_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/accept_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/auth_type_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/cache_control_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/content_length_spec.rb39
-rw-r--r--spec/ruby/library/cgi/queryextension/content_type_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/cookies_spec.rb15
-rw-r--r--spec/ruby/library/cgi/queryextension/element_reference_spec.rb41
-rw-r--r--spec/ruby/library/cgi/queryextension/from_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/gateway_interface_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/has_key_spec.rb11
-rw-r--r--spec/ruby/library/cgi/queryextension/host_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/include_spec.rb11
-rw-r--r--spec/ruby/library/cgi/queryextension/key_spec.rb11
-rw-r--r--spec/ruby/library/cgi/queryextension/keys_spec.rb29
-rw-r--r--spec/ruby/library/cgi/queryextension/multipart_spec.rb47
-rw-r--r--spec/ruby/library/cgi/queryextension/negotiate_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/params_spec.rb55
-rw-r--r--spec/ruby/library/cgi/queryextension/path_info_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/path_translated_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/pragma_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/query_string_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/raw_cookie2_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/raw_cookie_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/referer_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/remote_addr_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/remote_host_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/remote_ident_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/remote_user_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/request_method_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/script_name_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/server_name_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/server_port_spec.rb39
-rw-r--r--spec/ruby/library/cgi/queryextension/server_protocol_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/server_software_spec.rb33
-rw-r--r--spec/ruby/library/cgi/queryextension/user_agent_spec.rb33
-rw-r--r--spec/ruby/library/cgi/rfc1123_date_spec.rb15
-rw-r--r--spec/ruby/library/cgi/unescapeElement_spec.rb8
-rw-r--r--spec/ruby/library/cgi/unescapeHTML_spec.rb6
-rw-r--r--spec/ruby/library/cgi/unescapeURIComponent_spec.rb128
-rw-r--r--spec/ruby/library/cgi/unescape_spec.rb8
-rw-r--r--spec/ruby/library/coverage/fixtures/code_with_begin.rb3
-rw-r--r--spec/ruby/library/coverage/result_spec.rb134
-rw-r--r--spec/ruby/library/coverage/start_spec.rb128
-rw-r--r--spec/ruby/library/coverage/supported_spec.rb42
-rw-r--r--spec/ruby/library/date/accessor_spec.rb2
-rw-r--r--spec/ruby/library/date/deconstruct_keys_spec.rb74
-rw-r--r--spec/ruby/library/date/mon_spec.rb3
-rw-r--r--spec/ruby/library/date/month_spec.rb6
-rw-r--r--spec/ruby/library/date/shared/month.rb6
-rw-r--r--spec/ruby/library/date/strftime_spec.rb16
-rw-r--r--spec/ruby/library/date/yday_spec.rb3
-rw-r--r--spec/ruby/library/datetime/deconstruct_keys_spec.rb78
-rw-r--r--spec/ruby/library/datetime/strftime_spec.rb16
-rw-r--r--spec/ruby/library/datetime/time/to_datetime_spec.rb20
-rw-r--r--spec/ruby/library/datetime/to_time_spec.rb20
-rw-r--r--spec/ruby/library/datetime/yday_spec.rb7
-rw-r--r--spec/ruby/library/digest/md5/append_spec.rb2
-rw-r--r--spec/ruby/library/digest/md5/shared/constants.rb2
-rw-r--r--spec/ruby/library/digest/sha1/shared/constants.rb2
-rw-r--r--spec/ruby/library/digest/sha256/append_spec.rb2
-rw-r--r--spec/ruby/library/digest/sha256/shared/constants.rb2
-rw-r--r--spec/ruby/library/digest/sha384/append_spec.rb2
-rw-r--r--spec/ruby/library/digest/sha384/shared/constants.rb2
-rw-r--r--spec/ruby/library/digest/sha512/append_spec.rb2
-rw-r--r--spec/ruby/library/digest/sha512/shared/constants.rb2
-rw-r--r--spec/ruby/library/erb/def_class_spec.rb2
-rw-r--r--spec/ruby/library/erb/def_module_spec.rb3
-rw-r--r--spec/ruby/library/erb/defmethod/def_erb_method_spec.rb2
-rw-r--r--spec/ruby/library/erb/new_spec.rb6
-rw-r--r--spec/ruby/library/fiber/alive_spec.rb46
-rw-r--r--spec/ruby/library/fiber/current_spec.rb58
-rw-r--r--spec/ruby/library/fiber/resume_spec.rb18
-rw-r--r--spec/ruby/library/fiber/transfer_spec.rb86
-rw-r--r--spec/ruby/library/find/fixtures/common.rb14
-rw-r--r--spec/ruby/library/io-wait/fixtures/classes.rb12
-rw-r--r--spec/ruby/library/io-wait/wait_readable_spec.rb23
-rw-r--r--spec/ruby/library/io-wait/wait_spec.rb113
-rw-r--r--spec/ruby/library/io-wait/wait_writable_spec.rb25
-rw-r--r--spec/ruby/library/ipaddr/new_spec.rb46
-rw-r--r--spec/ruby/library/irb/fixtures/irb.rb3
-rw-r--r--spec/ruby/library/irb/irb_spec.rb (renamed from spec/ruby/core/binding/irb_spec.rb)0
-rw-r--r--spec/ruby/library/logger/logger/new_spec.rb28
-rw-r--r--spec/ruby/library/matrix/exponent_spec.rb18
-rw-r--r--spec/ruby/library/net-ftp/connect_spec.rb8
-rw-r--r--spec/ruby/library/net-ftp/fixtures/server.rb2
-rw-r--r--spec/ruby/library/net-ftp/shared/puttextfile.rb12
-rw-r--r--spec/ruby/library/net-http/HTTPServerException_spec.rb4
-rw-r--r--spec/ruby/library/net-http/http/post_spec.rb8
-rw-r--r--spec/ruby/library/net-http/http/send_request_spec.rb2
-rw-r--r--spec/ruby/library/net-http/httpgenericrequest/exec_spec.rb54
-rw-r--r--spec/ruby/library/objectspace/memsize_of_spec.rb2
-rw-r--r--spec/ruby/library/objectspace/trace_object_allocations_spec.rb32
-rw-r--r--spec/ruby/library/objectspace/trace_spec.rb20
-rw-r--r--spec/ruby/library/openssl/digest/initialize_spec.rb16
-rw-r--r--spec/ruby/library/openssl/kdf/pbkdf2_hmac_spec.rb20
-rw-r--r--spec/ruby/library/openssl/kdf/scrypt_spec.rb3
-rw-r--r--spec/ruby/library/openssl/shared/constants.rb2
-rw-r--r--spec/ruby/library/pathname/glob_spec.rb8
-rw-r--r--spec/ruby/library/pp/pp_spec.rb2
-rw-r--r--spec/ruby/library/random/formatter/alphanumeric_spec.rb56
-rw-r--r--spec/ruby/library/rbconfig/rbconfig_spec.rb62
-rw-r--r--spec/ruby/library/rbconfig/unicode_emoji_version_spec.rb18
-rw-r--r--spec/ruby/library/rbconfig/unicode_version_spec.rb18
-rw-r--r--spec/ruby/library/rubygems/gem/bin_path_spec.rb1
-rw-r--r--spec/ruby/library/securerandom/random_number_spec.rb34
-rw-r--r--spec/ruby/library/set/add_spec.rb27
-rw-r--r--spec/ruby/library/set/append_spec.rb7
-rw-r--r--spec/ruby/library/set/case_compare_spec.rb12
-rw-r--r--spec/ruby/library/set/case_equality_spec.rb7
-rw-r--r--spec/ruby/library/set/classify_spec.rb27
-rw-r--r--spec/ruby/library/set/clear_spec.rb17
-rw-r--r--spec/ruby/library/set/collect_spec.rb7
-rw-r--r--spec/ruby/library/set/compare_by_identity_spec.rb143
-rw-r--r--spec/ruby/library/set/comparison_spec.rb27
-rw-r--r--spec/ruby/library/set/constructor_spec.rb15
-rw-r--r--spec/ruby/library/set/delete_if_spec.rb38
-rw-r--r--spec/ruby/library/set/delete_spec.rb37
-rw-r--r--spec/ruby/library/set/difference_spec.rb7
-rw-r--r--spec/ruby/library/set/disjoint_spec.rb23
-rw-r--r--spec/ruby/library/set/divide_spec.rb59
-rw-r--r--spec/ruby/library/set/each_spec.rb27
-rw-r--r--spec/ruby/library/set/empty_spec.rb10
-rw-r--r--spec/ruby/library/set/enumerable/to_set_spec.rb13
-rw-r--r--spec/ruby/library/set/eql_spec.rb15
-rw-r--r--spec/ruby/library/set/equal_value_spec.rb33
-rw-r--r--spec/ruby/library/set/exclusion_spec.rb18
-rw-r--r--spec/ruby/library/set/fixtures/set_like.rb31
-rw-r--r--spec/ruby/library/set/flatten_merge_spec.rb23
-rw-r--r--spec/ruby/library/set/flatten_spec.rb56
-rw-r--r--spec/ruby/library/set/hash_spec.rb13
-rw-r--r--spec/ruby/library/set/include_spec.rb7
-rw-r--r--spec/ruby/library/set/initialize_clone_spec.rb16
-rw-r--r--spec/ruby/library/set/initialize_spec.rb73
-rw-r--r--spec/ruby/library/set/inspect_spec.rb7
-rw-r--r--spec/ruby/library/set/intersect_spec.rb23
-rw-r--r--spec/ruby/library/set/intersection_spec.rb11
-rw-r--r--spec/ruby/library/set/join_spec.rb29
-rw-r--r--spec/ruby/library/set/keep_if_spec.rb38
-rw-r--r--spec/ruby/library/set/length_spec.rb7
-rw-r--r--spec/ruby/library/set/map_spec.rb7
-rw-r--r--spec/ruby/library/set/member_spec.rb7
-rw-r--r--spec/ruby/library/set/merge_spec.rb19
-rw-r--r--spec/ruby/library/set/minus_spec.rb7
-rw-r--r--spec/ruby/library/set/plus_spec.rb7
-rw-r--r--spec/ruby/library/set/pretty_print_cycle_spec.rb10
-rw-r--r--spec/ruby/library/set/pretty_print_spec.rb19
-rw-r--r--spec/ruby/library/set/proper_subset_spec.rb44
-rw-r--r--spec/ruby/library/set/proper_superset_spec.rb41
-rw-r--r--spec/ruby/library/set/reject_spec.rb42
-rw-r--r--spec/ruby/library/set/replace_spec.rb17
-rw-r--r--spec/ruby/library/set/set_spec.rb12
-rw-r--r--spec/ruby/library/set/shared/inspect.rb25
-rw-r--r--spec/ruby/library/set/shared/select.rb42
-rw-r--r--spec/ruby/library/set/size_spec.rb7
-rw-r--r--spec/ruby/library/set/sortedset/sortedset_spec.rb12
-rw-r--r--spec/ruby/library/set/subset_spec.rb44
-rw-r--r--spec/ruby/library/set/subtract_spec.rb17
-rw-r--r--spec/ruby/library/set/superset_spec.rb41
-rw-r--r--spec/ruby/library/set/to_a_spec.rb8
-rw-r--r--spec/ruby/library/set/to_s_spec.rb12
-rw-r--r--spec/ruby/library/set/union_spec.rb11
-rw-r--r--spec/ruby/library/socket/addrinfo/afamily_spec.rb16
-rw-r--r--spec/ruby/library/socket/addrinfo/family_addrinfo_spec.rb48
-rw-r--r--spec/ruby/library/socket/addrinfo/getaddrinfo_spec.rb16
-rw-r--r--spec/ruby/library/socket/addrinfo/getnameinfo_spec.rb20
-rw-r--r--spec/ruby/library/socket/addrinfo/initialize_spec.rb66
-rw-r--r--spec/ruby/library/socket/addrinfo/inspect_sockaddr_spec.rb18
-rw-r--r--spec/ruby/library/socket/addrinfo/inspect_spec.rb26
-rw-r--r--spec/ruby/library/socket/addrinfo/ip_address_spec.rb14
-rw-r--r--spec/ruby/library/socket/addrinfo/ip_port_spec.rb14
-rw-r--r--spec/ruby/library/socket/addrinfo/ip_spec.rb14
-rw-r--r--spec/ruby/library/socket/addrinfo/ip_unpack_spec.rb14
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv4_loopback_spec.rb14
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv4_multicast_spec.rb14
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv4_private_spec.rb16
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv4_spec.rb14
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_loopback_spec.rb16
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_multicast_spec.rb16
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_spec.rb14
-rw-r--r--spec/ruby/library/socket/addrinfo/ipv6_to_ipv4_spec.rb2
-rw-r--r--spec/ruby/library/socket/addrinfo/marshal_dump_spec.rb56
-rw-r--r--spec/ruby/library/socket/addrinfo/marshal_load_spec.rb20
-rw-r--r--spec/ruby/library/socket/addrinfo/pfamily_spec.rb16
-rw-r--r--spec/ruby/library/socket/addrinfo/protocol_spec.rb14
-rw-r--r--spec/ruby/library/socket/addrinfo/shared/to_sockaddr.rb16
-rw-r--r--spec/ruby/library/socket/addrinfo/socktype_spec.rb14
-rw-r--r--spec/ruby/library/socket/addrinfo/udp_spec.rb6
-rw-r--r--spec/ruby/library/socket/addrinfo/unix_path_spec.rb46
-rw-r--r--spec/ruby/library/socket/addrinfo/unix_spec.rb46
-rw-r--r--spec/ruby/library/socket/ancillarydata/initialize_spec.rb2
-rw-r--r--spec/ruby/library/socket/ancillarydata/unix_rights_spec.rb2
-rw-r--r--spec/ruby/library/socket/basicsocket/connect_address_spec.rb80
-rw-r--r--spec/ruby/library/socket/basicsocket/getpeereid_spec.rb2
-rw-r--r--spec/ruby/library/socket/basicsocket/recv_nonblock_spec.rb71
-rw-r--r--spec/ruby/library/socket/basicsocket/recv_spec.rb132
-rw-r--r--spec/ruby/library/socket/basicsocket/recvmsg_nonblock_spec.rb76
-rw-r--r--spec/ruby/library/socket/basicsocket/recvmsg_spec.rb84
-rw-r--r--spec/ruby/library/socket/basicsocket/send_spec.rb84
-rw-r--r--spec/ruby/library/socket/basicsocket/setsockopt_spec.rb26
-rw-r--r--spec/ruby/library/socket/constants/constants_spec.rb2
-rw-r--r--spec/ruby/library/socket/ipsocket/getaddress_spec.rb5
-rw-r--r--spec/ruby/library/socket/ipsocket/recvfrom_spec.rb82
-rw-r--r--spec/ruby/library/socket/shared/address.rb86
-rw-r--r--spec/ruby/library/socket/shared/pack_sockaddr.rb61
-rw-r--r--spec/ruby/library/socket/socket/bind_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/connect_nonblock_spec.rb58
-rw-r--r--spec/ruby/library/socket/socket/connect_spec.rb22
-rw-r--r--spec/ruby/library/socket/socket/getaddrinfo_spec.rb20
-rw-r--r--spec/ruby/library/socket/socket/gethostbyaddr_spec.rb7
-rw-r--r--spec/ruby/library/socket/socket/gethostbyname_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/gethostname_spec.rb12
-rw-r--r--spec/ruby/library/socket/socket/getifaddrs_spec.rb2
-rw-r--r--spec/ruby/library/socket/socket/getnameinfo_spec.rb18
-rw-r--r--spec/ruby/library/socket/socket/recvfrom_nonblock_spec.rb80
-rw-r--r--spec/ruby/library/socket/socket/recvfrom_spec.rb87
-rw-r--r--spec/ruby/library/socket/socket/udp_server_loop_spec.rb4
-rw-r--r--spec/ruby/library/socket/socket/unix_server_loop_spec.rb76
-rw-r--r--spec/ruby/library/socket/socket/unix_server_socket_spec.rb56
-rw-r--r--spec/ruby/library/socket/socket/unix_spec.rb56
-rw-r--r--spec/ruby/library/socket/socket/unpack_sockaddr_in_spec.rb16
-rw-r--r--spec/ruby/library/socket/socket/unpack_sockaddr_un_spec.rb34
-rw-r--r--spec/ruby/library/socket/spec_helper.rb1
-rw-r--r--spec/ruby/library/socket/tcpsocket/gethostbyname_spec.rb4
-rw-r--r--spec/ruby/library/socket/tcpsocket/shared/new.rb48
-rw-r--r--spec/ruby/library/socket/unixserver/accept_nonblock_spec.rb114
-rw-r--r--spec/ruby/library/socket/unixserver/accept_spec.rb166
-rw-r--r--spec/ruby/library/socket/unixserver/for_fd_spec.rb28
-rw-r--r--spec/ruby/library/socket/unixserver/initialize_spec.rb36
-rw-r--r--spec/ruby/library/socket/unixserver/listen_spec.rb24
-rw-r--r--spec/ruby/library/socket/unixserver/new_spec.rb14
-rw-r--r--spec/ruby/library/socket/unixserver/open_spec.rb30
-rw-r--r--spec/ruby/library/socket/unixserver/sysaccept_spec.rb64
-rw-r--r--spec/ruby/library/socket/unixsocket/addr_spec.rb48
-rw-r--r--spec/ruby/library/socket/unixsocket/initialize_spec.rb60
-rw-r--r--spec/ruby/library/socket/unixsocket/inspect_spec.rb20
-rw-r--r--spec/ruby/library/socket/unixsocket/local_address_spec.rb132
-rw-r--r--spec/ruby/library/socket/unixsocket/new_spec.rb14
-rw-r--r--spec/ruby/library/socket/unixsocket/open_spec.rb34
-rw-r--r--spec/ruby/library/socket/unixsocket/pair_spec.rb40
-rw-r--r--spec/ruby/library/socket/unixsocket/partially_closable_spec.rb30
-rw-r--r--spec/ruby/library/socket/unixsocket/path_spec.rb34
-rw-r--r--spec/ruby/library/socket/unixsocket/peeraddr_spec.rb38
-rw-r--r--spec/ruby/library/socket/unixsocket/recv_io_spec.rb2
-rw-r--r--spec/ruby/library/socket/unixsocket/recvfrom_spec.rb152
-rw-r--r--spec/ruby/library/socket/unixsocket/remote_address_spec.rb60
-rw-r--r--spec/ruby/library/socket/unixsocket/send_io_spec.rb2
-rw-r--r--spec/ruby/library/socket/unixsocket/shared/pair.rb47
-rw-r--r--spec/ruby/library/socket/unixsocket/socketpair_spec.rb46
-rw-r--r--spec/ruby/library/stringio/each_line_spec.rb4
-rw-r--r--spec/ruby/library/stringio/each_spec.rb4
-rw-r--r--spec/ruby/library/stringio/fileno_spec.rb3
-rw-r--r--spec/ruby/library/stringio/fixtures/classes.rb4
-rw-r--r--spec/ruby/library/stringio/gets_spec.rb263
-rw-r--r--spec/ruby/library/stringio/initialize_spec.rb22
-rw-r--r--spec/ruby/library/stringio/readline_spec.rb160
-rw-r--r--spec/ruby/library/stringio/readpartial_spec.rb38
-rw-r--r--spec/ruby/library/stringio/set_encoding_by_bom_spec.rb237
-rw-r--r--spec/ruby/library/stringio/shared/each.rb78
-rw-r--r--spec/ruby/library/stringio/shared/gets.rb249
-rw-r--r--spec/ruby/library/stringio/shared/read.rb4
-rw-r--r--spec/ruby/library/stringio/shared/sysread.rb2
-rw-r--r--spec/ruby/library/stringio/shared/write.rb2
-rw-r--r--spec/ruby/library/stringio/sysread_spec.rb5
-rw-r--r--spec/ruby/library/stringscanner/captures_spec.rb36
-rw-r--r--spec/ruby/library/stringscanner/charpos_spec.rb18
-rw-r--r--spec/ruby/library/stringscanner/check_spec.rb68
-rw-r--r--spec/ruby/library/stringscanner/check_until_spec.rb122
-rw-r--r--spec/ruby/library/stringscanner/clear_spec.rb18
-rw-r--r--spec/ruby/library/stringscanner/element_reference_spec.rb9
-rw-r--r--spec/ruby/library/stringscanner/empty_spec.rb18
-rw-r--r--spec/ruby/library/stringscanner/eos_spec.rb17
-rw-r--r--spec/ruby/library/stringscanner/exist_spec.rb101
-rw-r--r--spec/ruby/library/stringscanner/fixed_anchor_spec.rb17
-rw-r--r--spec/ruby/library/stringscanner/get_byte_spec.rb81
-rw-r--r--spec/ruby/library/stringscanner/getbyte_spec.rb21
-rw-r--r--spec/ruby/library/stringscanner/getch_spec.rb56
-rw-r--r--spec/ruby/library/stringscanner/initialize_spec.rb5
-rw-r--r--spec/ruby/library/stringscanner/match_spec.rb23
-rw-r--r--spec/ruby/library/stringscanner/must_C_version_spec.rb2
-rw-r--r--spec/ruby/library/stringscanner/named_captures_spec.rb30
-rw-r--r--spec/ruby/library/stringscanner/peek_byte_spec.rb35
-rw-r--r--spec/ruby/library/stringscanner/peek_spec.rb39
-rw-r--r--spec/ruby/library/stringscanner/peep_spec.rb18
-rw-r--r--spec/ruby/library/stringscanner/rest_size_spec.rb18
-rw-r--r--spec/ruby/library/stringscanner/restsize_spec.rb18
-rw-r--r--spec/ruby/library/stringscanner/scan_byte_spec.rb98
-rw-r--r--spec/ruby/library/stringscanner/scan_full_spec.rb14
-rw-r--r--spec/ruby/library/stringscanner/scan_integer_spec.rb157
-rw-r--r--spec/ruby/library/stringscanner/scan_spec.rb14
-rw-r--r--spec/ruby/library/stringscanner/scan_until_spec.rb122
-rw-r--r--spec/ruby/library/stringscanner/search_full_spec.rb107
-rw-r--r--spec/ruby/library/stringscanner/shared/eos.rb17
-rw-r--r--spec/ruby/library/stringscanner/shared/get_byte.rb29
-rw-r--r--spec/ruby/library/stringscanner/shared/peek.rb39
-rw-r--r--spec/ruby/library/stringscanner/shared/pos.rb7
-rw-r--r--spec/ruby/library/stringscanner/shared/rest_size.rb18
-rw-r--r--spec/ruby/library/stringscanner/shared/terminate.rb8
-rw-r--r--spec/ruby/library/stringscanner/skip_spec.rb14
-rw-r--r--spec/ruby/library/stringscanner/skip_until_spec.rb118
-rw-r--r--spec/ruby/library/stringscanner/terminate_spec.rb8
-rw-r--r--spec/ruby/library/stringscanner/unscan_spec.rb6
-rw-r--r--spec/ruby/library/stringscanner/values_at_spec.rb68
-rw-r--r--spec/ruby/library/syslog/constants_spec.rb2
-rw-r--r--spec/ruby/library/syslog/log_spec.rb2
-rw-r--r--spec/ruby/library/syslog/shared/log.rb2
-rw-r--r--spec/ruby/library/tempfile/callback_spec.rb6
-rw-r--r--spec/ruby/library/tempfile/create_spec.rb176
-rw-r--r--spec/ruby/library/time/iso8601_spec.rb4
-rw-r--r--spec/ruby/library/time/shared/rfc2822.rb24
-rw-r--r--spec/ruby/library/time/shared/xmlschema.rb52
-rw-r--r--spec/ruby/library/time/xmlschema_spec.rb2
-rw-r--r--spec/ruby/library/timeout/timeout_spec.rb8
-rw-r--r--spec/ruby/library/uri/generic/host_spec.rb8
-rw-r--r--spec/ruby/library/uri/generic/to_s_spec.rb8
-rw-r--r--spec/ruby/library/uri/set_component_spec.rb40
-rw-r--r--spec/ruby/library/uri/shared/parse.rb13
-rw-r--r--spec/ruby/library/win32ole/fixtures/classes.rb17
-rw-r--r--spec/ruby/library/win32ole/win32ole/locale_spec.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole/new_spec.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_func_methods_spec.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_get_methods_spec.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_methods_spec.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_obj_help_spec.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole/ole_put_methods_spec.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole/shared/ole_method.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole_event/new_spec.rb14
-rw-r--r--spec/ruby/library/win32ole/win32ole_event/on_event_spec.rb12
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/dispid_spec.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/event_interface_spec.rb10
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/event_spec.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/helpcontext_spec.rb10
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/helpfile_spec.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/helpstring_spec.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/invkind_spec.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/invoke_kind_spec.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/name_spec.rb2
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/new_spec.rb22
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/offset_vtbl_spec.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/params_spec.rb14
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/return_type_detail_spec.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/return_type_spec.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/return_vtype_spec.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/shared/name.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/size_opt_params_spec.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/size_params_spec.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/to_s_spec.rb2
-rw-r--r--spec/ruby/library/win32ole/win32ole_method/visible_spec.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/default_spec.rb12
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/input_spec.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/name_spec.rb2
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/ole_type_detail_spec.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/ole_type_spec.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/optional_spec.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/retval_spec.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/shared/name.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole_param/to_s_spec.rb2
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/guid_spec.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/helpcontext_spec.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/helpfile_spec.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/helpstring_spec.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/major_version_spec.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/minor_version_spec.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/name_spec.rb2
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/new_spec.rb32
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/ole_classes_spec.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/ole_methods_spec.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/ole_type_spec.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/progid_spec.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/progids_spec.rb6
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/shared/name.rb2
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/src_type_spec.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/to_s_spec.rb2
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/typekind_spec.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/typelibs_spec.rb8
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/variables_spec.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole_type/visible_spec.rb4
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/ole_type_detail_spec.rb2
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/ole_type_spec.rb2
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/shared/name.rb2
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/value_spec.rb2
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/variable_kind_spec.rb2
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/varkind_spec.rb2
-rw-r--r--spec/ruby/library/win32ole/win32ole_variable/visible_spec.rb2
-rw-r--r--spec/ruby/library/yaml/dump_spec.rb6
-rw-r--r--spec/ruby/library/yaml/shared/load.rb6
-rw-r--r--spec/ruby/library/yaml/to_yaml_spec.rb2
-rw-r--r--spec/ruby/library/zlib/gzipreader/each_char_spec.rb51
-rw-r--r--spec/ruby/library/zlib/inflate/set_dictionary_spec.rb2
-rw-r--r--spec/ruby/optional/capi/array_spec.rb48
-rw-r--r--spec/ruby/optional/capi/bignum_spec.rb26
-rw-r--r--spec/ruby/optional/capi/binding_spec.rb18
-rw-r--r--spec/ruby/optional/capi/class_spec.rb2
-rw-r--r--spec/ruby/optional/capi/data_spec.rb73
-rw-r--r--spec/ruby/optional/capi/debug_spec.rb7
-rw-r--r--spec/ruby/optional/capi/digest_spec.rb103
-rw-r--r--spec/ruby/optional/capi/encoding_spec.rb24
-rw-r--r--spec/ruby/optional/capi/exception_spec.rb20
-rw-r--r--spec/ruby/optional/capi/ext/array_spec.c8
-rw-r--r--spec/ruby/optional/capi/ext/class_spec.c4
-rw-r--r--spec/ruby/optional/capi/ext/constants_spec.c6
-rw-r--r--spec/ruby/optional/capi/ext/data_spec.c4
-rw-r--r--spec/ruby/optional/capi/ext/digest_spec.c168
-rw-r--r--spec/ruby/optional/capi/ext/exception_spec.c8
-rw-r--r--spec/ruby/optional/capi/ext/fiber_spec.c5
-rw-r--r--spec/ruby/optional/capi/ext/finalizer_spec.c25
-rw-r--r--spec/ruby/optional/capi/ext/hash_spec.c19
-rw-r--r--spec/ruby/optional/capi/ext/io_spec.c61
-rw-r--r--spec/ruby/optional/capi/ext/kernel_spec.c62
-rw-r--r--spec/ruby/optional/capi/ext/mutex_spec.c23
-rw-r--r--spec/ruby/optional/capi/ext/object_spec.c49
-rw-r--r--spec/ruby/optional/capi/ext/range_spec.c48
-rw-r--r--spec/ruby/optional/capi/ext/rbasic_spec.c10
-rw-r--r--spec/ruby/optional/capi/ext/rubyspec.h37
-rw-r--r--spec/ruby/optional/capi/ext/set_spec.c65
-rw-r--r--spec/ruby/optional/capi/ext/string_spec.c26
-rw-r--r--spec/ruby/optional/capi/ext/struct_spec.c33
-rw-r--r--spec/ruby/optional/capi/ext/thread_spec.c10
-rw-r--r--spec/ruby/optional/capi/ext/typed_data_spec.c2
-rw-r--r--spec/ruby/optional/capi/fiber_spec.rb53
-rw-r--r--spec/ruby/optional/capi/finalizer_spec.rb40
-rw-r--r--spec/ruby/optional/capi/fixnum_spec.rb4
-rw-r--r--spec/ruby/optional/capi/globals_spec.rb13
-rw-r--r--spec/ruby/optional/capi/hash_spec.rb75
-rw-r--r--spec/ruby/optional/capi/integer_spec.rb2
-rw-r--r--spec/ruby/optional/capi/io_spec.rb329
-rw-r--r--spec/ruby/optional/capi/kernel_spec.rb225
-rw-r--r--spec/ruby/optional/capi/module_spec.rb6
-rw-r--r--spec/ruby/optional/capi/mutex_spec.rb13
-rw-r--r--spec/ruby/optional/capi/numeric_spec.rb8
-rw-r--r--spec/ruby/optional/capi/object_spec.rb12
-rw-r--r--spec/ruby/optional/capi/range_spec.rb144
-rw-r--r--spec/ruby/optional/capi/rbasic_spec.rb56
-rw-r--r--spec/ruby/optional/capi/regexp_spec.rb4
-rw-r--r--spec/ruby/optional/capi/set_spec.rb96
-rw-r--r--spec/ruby/optional/capi/shared/rbasic.rb1
-rw-r--r--spec/ruby/optional/capi/spec_helper.rb17
-rw-r--r--spec/ruby/optional/capi/string_spec.rb145
-rw-r--r--spec/ruby/optional/capi/struct_spec.rb105
-rw-r--r--spec/ruby/optional/capi/thread_spec.rb8
-rw-r--r--spec/ruby/optional/capi/util_spec.rb2
-rw-r--r--spec/ruby/optional/thread_safety/fixtures/classes.rb39
-rw-r--r--spec/ruby/optional/thread_safety/hash_spec.rb210
-rw-r--r--spec/ruby/security/cve_2020_10663_spec.rb64
-rw-r--r--spec/ruby/security/cve_2024_49761_spec.rb7
-rw-r--r--spec/ruby/shared/enumerator/with_index.rb33
-rw-r--r--spec/ruby/shared/enumerator/with_object.rb42
-rw-r--r--spec/ruby/shared/fiber/resume.rb58
-rw-r--r--spec/ruby/shared/file/size.rb2
-rw-r--r--spec/ruby/shared/file/socket.rb32
-rw-r--r--spec/ruby/shared/file/sticky.rb2
-rw-r--r--spec/ruby/shared/io/putc.rb2
-rw-r--r--spec/ruby/shared/kernel/raise.rb348
-rw-r--r--spec/ruby/shared/process/fork.rb10
-rw-r--r--spec/ruby/shared/queue/deque.rb118
-rw-r--r--spec/ruby/shared/queue/freeze.rb18
-rw-r--r--spec/ruby/shared/rational/Rational.rb150
-rw-r--r--spec/ruby/shared/rational/abs.rb11
-rw-r--r--spec/ruby/shared/rational/arithmetic_exception_in_coerce.rb11
-rw-r--r--spec/ruby/shared/rational/ceil.rb45
-rw-r--r--spec/ruby/shared/rational/comparison.rb95
-rw-r--r--spec/ruby/shared/rational/denominator.rb14
-rw-r--r--spec/ruby/shared/rational/div.rb54
-rw-r--r--spec/ruby/shared/rational/divide.rb71
-rw-r--r--spec/ruby/shared/rational/divmod.rb42
-rw-r--r--spec/ruby/shared/rational/equal_value.rb39
-rw-r--r--spec/ruby/shared/rational/exponent.rb196
-rw-r--r--spec/ruby/shared/rational/fdiv.rb5
-rw-r--r--spec/ruby/shared/rational/floor.rb45
-rw-r--r--spec/ruby/shared/rational/hash.rb9
-rw-r--r--spec/ruby/shared/rational/inspect.rb14
-rw-r--r--spec/ruby/shared/rational/modulo.rb43
-rw-r--r--spec/ruby/shared/rational/multiply.rb62
-rw-r--r--spec/ruby/shared/rational/numerator.rb10
-rw-r--r--spec/ruby/shared/rational/plus.rb48
-rw-r--r--spec/ruby/shared/rational/remainder.rb5
-rw-r--r--spec/ruby/shared/rational/round.rb106
-rw-r--r--spec/ruby/shared/rational/to_f.rb16
-rw-r--r--spec/ruby/shared/rational/to_i.rb12
-rw-r--r--spec/ruby/shared/rational/to_r.rb11
-rw-r--r--spec/ruby/shared/rational/to_s.rb14
-rw-r--r--spec/ruby/shared/rational/truncate.rb71
-rw-r--r--spec/ruby/shared/sizedqueue/enque.rb152
-rw-r--r--spec/ruby/shared/string/end_with.rb4
-rw-r--r--spec/ruby/shared/string/times.rb4
-rw-r--r--spec/ruby/shared/time/yday.rb18
-rw-r--r--spec/syntax_suggest/integration/syntax_suggest_spec.rb4
-rw-r--r--spec/syntax_suggest/spec_helper.rb5
-rw-r--r--spec/syntax_suggest/unit/mini_stringio_spec.rb25
-rw-r--r--sprintf.c22
-rw-r--r--st.c927
-rw-r--r--strftime.c10
-rw-r--r--string.c3107
-rw-r--r--string.rb552
-rw-r--r--struct.c155
-rw-r--r--symbol.c1018
-rw-r--r--symbol.h18
-rw-r--r--symbol.rb14
-rw-r--r--template/GNUmakefile.in3
-rw-r--r--template/Makefile.in128
-rw-r--r--template/builtin_binary.inc.tmpl30
-rw-r--r--template/builtin_binary.rbbin.tmpl35
-rw-r--r--template/configure-ext.mk.tmpl4
-rw-r--r--template/exts.mk.tmpl49
-rw-r--r--template/fake.rb.in29
-rw-r--r--template/id.c.tmpl3
-rw-r--r--template/id.h.tmpl8
-rw-r--r--template/limits.c.tmpl19
-rw-r--r--template/prelude.c.tmpl131
-rw-r--r--template/ruby-runner.h.in2
-rw-r--r--template/sizes.c.tmpl21
-rw-r--r--template/unicode_norm_gen.tmpl37
-rw-r--r--test/-ext-/box/test_load_ext.rb97
-rw-r--r--test/-ext-/bug_reporter/test_bug_reporter.rb12
-rw-r--r--test/-ext-/debug/test_debug.rb67
-rw-r--r--test/-ext-/debug/test_profile_frames.rb3
-rw-r--r--test/-ext-/gvl/test_last_thread.rb3
-rw-r--r--test/-ext-/integer/test_my_integer.rb34
-rw-r--r--test/-ext-/marshal/test_internal_ivar.rb10
-rw-r--r--test/-ext-/required.rb10
-rw-r--r--test/-ext-/scheduler/test_interrupt_with_scheduler.rb54
-rw-r--r--test/-ext-/stack/test_stack_overflow.rb55
-rw-r--r--test/-ext-/string/test_capacity.rb4
-rw-r--r--test/-ext-/string/test_interned_str.rb5
-rw-r--r--test/-ext-/string/test_set_len.rb18
-rw-r--r--test/-ext-/symbol/test_type.rb16
-rw-r--r--test/-ext-/test_abi.rb12
-rw-r--r--test/-ext-/test_ensure_and_callcc.rb40
-rw-r--r--test/-ext-/thread/test_instrumentation_api.rb6
-rw-r--r--test/-ext-/thread/test_lock_native_thread.rb4
-rw-r--r--test/-ext-/thread_fd/test_thread_fd_close.rb24
-rw-r--r--test/-ext-/tracepoint/test_tracepoint.rb20
-rw-r--r--test/.excludes-mmtk/TestArgf.rb1
-rw-r--r--test/.excludes-mmtk/TestEtc.rb1
-rw-r--r--test/.excludes-mmtk/TestGc.rb26
-rw-r--r--test/.excludes-mmtk/TestObjSpace.rb4
-rw-r--r--test/.excludes-mmtk/TestObjectSpace.rb1
-rw-r--r--test/.excludes-mmtk/TestProcess.rb4
-rw-r--r--test/.excludes-mmtk/TestTracepointObj.rb1
-rw-r--r--test/.excludes-prism/TestM17N.rb1
-rw-r--r--test/.excludes-prism/TestMixedUnicodeEscape.rb1
-rw-r--r--test/.excludes-prism/TestRubyLiteral.rb1
-rw-r--r--test/.excludes-prism/TestSyntax.rb2
-rw-r--r--test/.excludes-zjit/TestResolvDNS.rb1
-rw-r--r--test/.excludes/JSONGenericObjectTest.rb4
-rw-r--r--test/.excludes/TestPatternMatching.rb1
-rw-r--r--test/.excludes/URI/TestMailTo.rb1
-rw-r--r--test/.excludes/_appveyor/TestArray.rb7
-rw-r--r--test/benchmark/test_benchmark.rb167
-rw-r--r--test/cgi/test_cgi_cookie.rb211
-rw-r--r--test/cgi/test_cgi_core.rb307
-rw-r--r--test/cgi/test_cgi_escape.rb325
-rw-r--r--test/cgi/test_cgi_header.rb192
-rw-r--r--test/cgi/test_cgi_modruby.rb149
-rw-r--r--test/cgi/test_cgi_multipart.rb385
-rw-r--r--test/cgi/test_cgi_session.rb169
-rw-r--r--test/cgi/test_cgi_tag_helper.rb355
-rw-r--r--test/cgi/test_cgi_util.rb312
-rw-r--r--test/cgi/testdata/file1.html10
-rw-r--r--test/cgi/testdata/large.pngbin156414 -> 0 bytes-rw-r--r--test/cgi/testdata/small.pngbin82 -> 0 bytes-rw-r--r--test/coverage/test_coverage.rb53
-rw-r--r--test/date/test_date.rb4
-rw-r--r--test/date/test_date_conv.rb15
-rw-r--r--test/date/test_date_parse.rb29
-rw-r--r--test/date/test_date_ractor.rb2
-rw-r--r--test/date/test_date_strftime.rb9
-rw-r--r--test/date/test_switch_hitter.rb5
-rw-r--r--test/did_you_mean/spell_checking/test_method_name_check.rb4
-rw-r--r--test/did_you_mean/spell_checking/test_require_path_check.rb6
-rw-r--r--test/did_you_mean/test_ractor_compatibility.rb12
-rw-r--r--test/digest/test_ractor.rb6
-rw-r--r--test/dtrace/helper.rb6
-rw-r--r--test/erb/test_erb.rb80
-rw-r--r--test/error_highlight/test_error_highlight.rb458
-rw-r--r--test/etc/test_etc.rb79
-rw-r--r--test/fiber/scheduler.rb178
-rw-r--r--test/fiber/test_io.rb51
-rw-r--r--test/fiber/test_io_buffer.rb3
-rw-r--r--test/fiber/test_io_close.rb107
-rw-r--r--test/fiber/test_process.rb4
-rw-r--r--test/fiber/test_ractor.rb2
-rw-r--r--test/fiber/test_scheduler.rb201
-rw-r--r--test/fiber/test_sleep.rb4
-rw-r--r--test/fiber/test_thread.rb41
-rw-r--r--test/fiddle/helper.rb184
-rw-r--r--test/fiddle/test_c_struct_builder.rb69
-rw-r--r--test/fiddle/test_c_struct_entry.rb171
-rw-r--r--test/fiddle/test_c_union_entity.rb36
-rw-r--r--test/fiddle/test_closure.rb153
-rw-r--r--test/fiddle/test_cparser.rb414
-rw-r--r--test/fiddle/test_fiddle.rb58
-rw-r--r--test/fiddle/test_func.rb166
-rw-r--r--test/fiddle/test_function.rb239
-rw-r--r--test/fiddle/test_handle.rb218
-rw-r--r--test/fiddle/test_import.rb490
-rw-r--r--test/fiddle/test_memory_view.rb143
-rw-r--r--test/fiddle/test_pack.rb37
-rw-r--r--test/fiddle/test_pinned.rb28
-rw-r--r--test/fiddle/test_pointer.rb306
-rw-r--r--test/fileutils/test_fileutils.rb111
-rw-r--r--test/io/console/test_io_console.rb53
-rw-r--r--test/io/console/test_ractor.rb42
-rw-r--r--test/io/wait/test_io_wait.rb36
-rw-r--r--test/io/wait/test_io_wait_uncommon.rb15
-rw-r--r--test/io/wait/test_ractor.rb6
-rw-r--r--test/irb/command/test_custom_command.rb149
-rw-r--r--test/irb/command/test_force_exit.rb51
-rw-r--r--test/irb/command/test_help.rb75
-rw-r--r--test/irb/command/test_multi_irb_commands.rb50
-rw-r--r--test/irb/command/test_show_source.rb397
-rw-r--r--test/irb/helper.rb221
-rw-r--r--test/irb/test_color.rb274
-rw-r--r--test/irb/test_color_printer.rb69
-rw-r--r--test/irb/test_command.rb971
-rw-r--r--test/irb/test_completion.rb311
-rw-r--r--test/irb/test_context.rb729
-rw-r--r--test/irb/test_debugger_integration.rb496
-rw-r--r--test/irb/test_eval_history.rb69
-rw-r--r--test/irb/test_evaluation.rb44
-rw-r--r--test/irb/test_helper_method.rb134
-rw-r--r--test/irb/test_history.rb491
-rw-r--r--test/irb/test_init.rb386
-rw-r--r--test/irb/test_input_method.rb173
-rw-r--r--test/irb/test_irb.rb917
-rw-r--r--test/irb/test_locale.rb118
-rw-r--r--test/irb/test_nesting_parser.rb341
-rw-r--r--test/irb/test_option.rb13
-rw-r--r--test/irb/test_raise_exception.rb74
-rw-r--r--test/irb/test_ruby_lex.rb242
-rw-r--r--test/irb/test_tracer.rb90
-rw-r--r--test/irb/test_type_completor.rb88
-rw-r--r--test/irb/test_workspace.rb127
-rw-r--r--test/irb/yamatanooroti/test_rendering.rb517
-rw-r--r--test/json/fixtures/fail15.json (renamed from test/json/fixtures/pass15.json)0
-rw-r--r--test/json/fixtures/fail16.json (renamed from test/json/fixtures/pass16.json)0
-rw-r--r--test/json/fixtures/fail17.json (renamed from test/json/fixtures/pass17.json)0
-rw-r--r--test/json/fixtures/fail26.json (renamed from test/json/fixtures/pass26.json)0
-rw-r--r--test/json/fixtures/fail4.json1
-rw-r--r--test/json/fixtures/fail9.json1
-rw-r--r--test/json/fixtures/pass1.json2
-rw-r--r--test/json/json_addition_test.rb25
-rwxr-xr-xtest/json/json_coder_test.rb149
-rw-r--r--test/json/json_common_interface_test.rb202
-rw-r--r--test/json/json_encoding_test.rb249
-rw-r--r--test/json/json_ext_parser_test.rb79
-rw-r--r--test/json/json_fixtures_test.rb40
-rwxr-xr-xtest/json/json_generator_test.rb909
-rw-r--r--test/json/json_generic_object_test.rb35
-rw-r--r--test/json/json_parser_test.rb488
-rw-r--r--test/json/json_ryu_fallback_test.rb169
-rw-r--r--test/json/json_string_matching_test.rb2
-rw-r--r--test/json/ractor_test.rb100
-rw-r--r--test/json/test_helper.rb62
-rw-r--r--test/lib/jit_support.rb16
-rw-r--r--test/lib/parser_support.rb20
-rw-r--r--test/logger/test_formatter.rb35
-rw-r--r--test/logger/test_logdevice.rb859
-rw-r--r--test/logger/test_logger.rb393
-rw-r--r--test/logger/test_logperiod.rb80
-rw-r--r--test/logger/test_severity.rb58
-rw-r--r--test/mkmf/test_flags.rb4
-rw-r--r--test/mkmf/test_pkg_config.rb17
-rw-r--r--test/mmtk/helper.rb32
-rw-r--r--test/mmtk/test_configuration.rb93
-rw-r--r--test/net/http/test_http.rb93
-rw-r--r--test/net/http/test_http_request.rb34
-rw-r--r--test/net/http/test_https.rb137
-rw-r--r--test/net/http/test_https_proxy.rb51
-rw-r--r--test/net/http/utils.rb364
-rw-r--r--test/objspace/test_objspace.rb196
-rw-r--r--test/objspace/test_ractor.rb74
-rw-r--r--test/open-uri/test_ftp.rb216
-rw-r--r--test/open-uri/test_open-uri.rb600
-rw-r--r--test/open-uri/test_proxy.rb174
-rw-r--r--test/open-uri/test_ssl.rb435
-rw-r--r--test/open-uri/utils.rb738
-rw-r--r--test/openssl/fixtures/pkey/certificate.derbin1325 -> 0 bytes-rw-r--r--test/openssl/fixtures/pkey/dsa1024.pem12
-rw-r--r--test/openssl/fixtures/pkey/dsa256.pem8
-rw-r--r--test/openssl/fixtures/pkey/dsa512.pem8
-rw-r--r--test/openssl/fixtures/pkey/empty.der0
-rw-r--r--test/openssl/fixtures/pkey/empty.pem0
-rw-r--r--test/openssl/fixtures/pkey/fullchain.pem56
-rw-r--r--test/openssl/fixtures/pkey/garbage.txt1
-rw-r--r--test/openssl/fixtures/pkey/mldsa65-1.pem88
-rw-r--r--test/openssl/fixtures/pkey/mldsa65-2.pem88
-rw-r--r--test/openssl/fixtures/pkey/p256_too_large.pem5
-rw-r--r--test/openssl/fixtures/pkey/p384_invalid.pem6
-rw-r--r--test/openssl/fixtures/pkey/rsa1024.pem15
-rw-r--r--test/openssl/test_asn1.rb109
-rw-r--r--test/openssl/test_bn.rb54
-rw-r--r--test/openssl/test_buffering.rb2
-rw-r--r--test/openssl/test_cipher.rb115
-rw-r--r--test/openssl/test_config.rb26
-rw-r--r--test/openssl/test_digest.rb85
-rw-r--r--test/openssl/test_fips.rb9
-rw-r--r--test/openssl/test_kdf.rb3
-rw-r--r--test/openssl/test_ns_spki.rb4
-rw-r--r--test/openssl/test_ocsp.rb14
-rw-r--r--test/openssl/test_ossl.rb71
-rw-r--r--test/openssl/test_pair.rb21
-rw-r--r--test/openssl/test_pkcs12.rb75
-rw-r--r--test/openssl/test_pkcs7.rb385
-rw-r--r--test/openssl/test_pkey.rb255
-rw-r--r--test/openssl/test_pkey_dh.rb145
-rw-r--r--test/openssl/test_pkey_dsa.rb168
-rw-r--r--test/openssl/test_pkey_ec.rb119
-rw-r--r--test/openssl/test_pkey_rsa.rb467
-rw-r--r--test/openssl/test_provider.rb26
-rw-r--r--test/openssl/test_ssl.rb828
-rw-r--r--test/openssl/test_ssl_session.rb96
-rw-r--r--test/openssl/test_ts.rb48
-rw-r--r--test/openssl/test_x509attr.rb4
-rw-r--r--test/openssl/test_x509cert.rb301
-rw-r--r--test/openssl/test_x509crl.rb85
-rw-r--r--test/openssl/test_x509name.rb16
-rw-r--r--test/openssl/test_x509req.rb97
-rw-r--r--test/openssl/test_x509store.rb19
-rw-r--r--test/openssl/ut_eof.rb4
-rw-r--r--test/openssl/utils.rb70
-rw-r--r--test/optparse/test_acceptable.rb2
-rw-r--r--test/optparse/test_load.rb61
-rw-r--r--test/optparse/test_optparse.rb30
-rw-r--r--test/optparse/test_placearg.rb25
-rw-r--r--test/optparse/test_switch.rb50
-rw-r--r--test/ostruct/test_ostruct.rb434
-rw-r--r--test/pathname/test_pathname.rb48
-rw-r--r--test/pathname/test_ractor.rb12
-rw-r--r--test/prism/api/command_line_test.rb7
-rw-r--r--test/prism/api/freeze_test.rb60
-rw-r--r--test/prism/api/lex_test.rb23
-rw-r--r--test/prism/api/parse_stream_test.rb8
-rw-r--r--test/prism/api/parse_test.rb119
-rw-r--r--test/prism/encoding/encodings_test.rb18
-rw-r--r--test/prism/encoding/regular_expression_encoding_test.rb4
-rw-r--r--test/prism/errors/1_2_3.txt11
-rw-r--r--test/prism/errors/3.3-3.3/circular_parameters.txt12
-rw-r--r--test/prism/errors/3.3-3.4/leading_logical.txt34
-rw-r--r--test/prism/errors/3.3-3.4/private_endless_method.txt3
-rw-r--r--test/prism/errors/3.4/block_args_in_array_assignment.txt3
-rw-r--r--test/prism/errors/3.4/dont_allow_return_inside_sclass_body.txt3
-rw-r--r--test/prism/errors/3.4/it_with_ordinary_parameter.txt3
-rw-r--r--test/prism/errors/3.4/keyword_args_in_array_assignment.txt3
-rw-r--r--test/prism/errors/aliasing_global_variable_with_global_number_variable.txt3
-rw-r--r--test/prism/errors/aliasing_global_variable_with_non_global_variable.txt3
-rw-r--r--test/prism/errors/aliasing_non_global_variable_with_global_variable.txt3
-rw-r--r--test/prism/errors/alnum_delimiters.txt3
-rw-r--r--test/prism/errors/alnum_delimiters_2.txt3
-rw-r--r--test/prism/errors/alnum_delimiters_3.txt3
-rw-r--r--test/prism/errors/alnum_delimiters_4.txt3
-rw-r--r--test/prism/errors/alnum_delimiters_5.txt3
-rw-r--r--test/prism/errors/alnum_delimiters_6.txt3
-rw-r--r--test/prism/errors/alnum_delimiters_7.txt3
-rw-r--r--test/prism/errors/alnum_delimiters_8.txt3
-rw-r--r--test/prism/errors/alnum_delimiters_9.txt3
-rw-r--r--test/prism/errors/amperand_dot_after_endless_range.txt3
-rw-r--r--test/prism/errors/argument_after_ellipsis.txt3
-rw-r--r--test/prism/errors/argument_forwarding_only_effects_its_own_internals.txt3
-rw-r--r--test/prism/errors/argument_forwarding_when_parent_is_not_forwarding.txt3
-rw-r--r--test/prism/errors/arguments_after_block.txt17
-rw-r--r--test/prism/errors/arguments_binding_power_for_and.txt5
-rw-r--r--test/prism/errors/arguments_invalid_comma.txt4
-rw-r--r--test/prism/errors/arguments_splat_after_star_star.txt3
-rw-r--r--test/prism/errors/array_invalid_comma.txt4
-rw-r--r--test/prism/errors/array_with_double_commas.txt3
-rw-r--r--test/prism/errors/assign_to_numbered_parameter.txt11
-rw-r--r--test/prism/errors/bad_arguments.txt6
-rw-r--r--test/prism/errors/begin_at_toplevel.txt3
-rw-r--r--test/prism/errors/binary_range_with_left_unary_range.txt8
-rw-r--r--test/prism/errors/block_arg_and_block.txt3
-rw-r--r--test/prism/errors/block_args_with_endless_def.txt5
-rw-r--r--test/prism/errors/block_beginning_with_brace_and_ending_with_end.txt5
-rw-r--r--test/prism/errors/break_1.txt4
-rw-r--r--test/prism/errors/break_1_2_3.txt8
-rw-r--r--test/prism/errors/call_with_block_and_write.txt4
-rw-r--r--test/prism/errors/call_with_block_operator_write.txt4
-rw-r--r--test/prism/errors/call_with_block_or_write.txt4
-rw-r--r--test/prism/errors/cannot_assign_to_a_reserved_numbered_parameter.txt14
-rw-r--r--test/prism/errors/case_without_clauses.txt4
-rw-r--r--test/prism/errors/case_without_when_clauses_errors_on_else_clause.txt5
-rw-r--r--test/prism/errors/check_value_expression.txt20
-rw-r--r--test/prism/errors/class_definition_in_method_body.txt3
-rw-r--r--test/prism/errors/class_definition_in_method_defs.txt7
-rw-r--r--test/prism/errors/class_name.txt3
-rw-r--r--test/prism/errors/command_call_in.txt5
-rw-r--r--test/prism/errors/command_calls.txt10
-rw-r--r--test/prism/errors/command_calls_10.txt3
-rw-r--r--test/prism/errors/command_calls_11.txt3
-rw-r--r--test/prism/errors/command_calls_12.txt3
-rw-r--r--test/prism/errors/command_calls_13.txt3
-rw-r--r--test/prism/errors/command_calls_14.txt3
-rw-r--r--test/prism/errors/command_calls_15.txt3
-rw-r--r--test/prism/errors/command_calls_16.txt3
-rw-r--r--test/prism/errors/command_calls_17.txt5
-rw-r--r--test/prism/errors/command_calls_18.txt3
-rw-r--r--test/prism/errors/command_calls_19.txt3
-rw-r--r--test/prism/errors/command_calls_2.txt6
-rw-r--r--test/prism/errors/command_calls_20.txt3
-rw-r--r--test/prism/errors/command_calls_21.txt5
-rw-r--r--test/prism/errors/command_calls_22.txt3
-rw-r--r--test/prism/errors/command_calls_23.txt3
-rw-r--r--test/prism/errors/command_calls_24.txt5
-rw-r--r--test/prism/errors/command_calls_25.txt8
-rw-r--r--test/prism/errors/command_calls_26.txt3
-rw-r--r--test/prism/errors/command_calls_27.txt3
-rw-r--r--test/prism/errors/command_calls_28.txt3
-rw-r--r--test/prism/errors/command_calls_29.txt3
-rw-r--r--test/prism/errors/command_calls_3.txt3
-rw-r--r--test/prism/errors/command_calls_30.txt3
-rw-r--r--test/prism/errors/command_calls_31.txt17
-rw-r--r--test/prism/errors/command_calls_32.txt19
-rw-r--r--test/prism/errors/command_calls_33.txt6
-rw-r--r--test/prism/errors/command_calls_34.txt24
-rw-r--r--test/prism/errors/command_calls_35.txt46
-rw-r--r--test/prism/errors/command_calls_4.txt3
-rw-r--r--test/prism/errors/command_calls_5.txt3
-rw-r--r--test/prism/errors/command_calls_6.txt6
-rw-r--r--test/prism/errors/command_calls_7.txt6
-rw-r--r--test/prism/errors/command_calls_8.txt6
-rw-r--r--test/prism/errors/command_calls_9.txt6
-rw-r--r--test/prism/errors/conditional_predicate_closed.txt6
-rw-r--r--test/prism/errors/constant_assignment_in_method.txt3
-rw-r--r--test/prism/errors/constant_path_with_invalid_token_after.txt4
-rw-r--r--test/prism/errors/content_after_unterminated_heredoc.txt4
-rw-r--r--test/prism/errors/cr_without_lf_in_percent_expression.txt3
-rw-r--r--test/prism/errors/def_ivar.txt3
-rw-r--r--test/prism/errors/def_with_empty_expression_receiver.txt3
-rw-r--r--test/prism/errors/def_with_expression_receiver_and_no_identifier.txt4
-rw-r--r--test/prism/errors/def_with_multiple_statements_receiver.txt10
-rw-r--r--test/prism/errors/def_with_optional_splat.txt6
-rw-r--r--test/prism/errors/defined_empty.txt3
-rw-r--r--test/prism/errors/defining_numbered_parameter.txt3
-rw-r--r--test/prism/errors/defining_numbered_parameter_2.txt3
-rw-r--r--test/prism/errors/defs_endless_method.txt12
-rw-r--r--test/prism/errors/destroy_call_operator_write_arguments.txt11
-rw-r--r--test/prism/errors/do_not_allow_characters_other_than_0_9_a_f_and_A_F_in_u_Unicode_character_notation.txt4
-rw-r--r--test/prism/errors/do_not_allow_forward_arguments_in_blocks.txt3
-rw-r--r--test/prism/errors/do_not_allow_forward_arguments_in_lambda_literals.txt3
-rw-r--r--test/prism/errors/do_not_allow_more_than_6_hexadecimal_digits_in_u_Unicode_character_notation.txt3
-rw-r--r--test/prism/errors/do_not_allow_multiple_codepoints_in_a_single_character_literal.txt3
-rw-r--r--test/prism/errors/do_not_allow_trailing_commas_in_lambda_parameters.txt3
-rw-r--r--test/prism/errors/do_not_allow_trailing_commas_in_method_parameters.txt3
-rw-r--r--test/prism/errors/dont_allow_return_inside_class_body.txt3
-rw-r--r--test/prism/errors/dont_allow_return_inside_module_body.txt3
-rw-r--r--test/prism/errors/dont_allow_setting_to_back_and_nth_reference.txt7
-rw-r--r--test/prism/errors/double_arguments_forwarding.txt4
-rw-r--r--test/prism/errors/double_scope_numbered_parameters.txt3
-rw-r--r--test/prism/errors/double_scope_repeated_numbered_parameters.txt3
-rw-r--r--test/prism/errors/double_splat_followed_by_splat_argument.txt3
-rw-r--r--test/prism/errors/double_splat_with_double_commas.txt3
-rw-r--r--test/prism/errors/duplicate_pattern_capture.txt17
-rw-r--r--test/prism/errors/duplicate_pattern_hash_key.txt4
-rw-r--r--test/prism/errors/duplicate_pattern_hash_key_2.txt3
-rw-r--r--test/prism/errors/duplicated_parameter_names.txt3
-rw-r--r--test/prism/errors/duplicated_parameter_names_2.txt3
-rw-r--r--test/prism/errors/duplicated_parameter_names_3.txt3
-rw-r--r--test/prism/errors/duplicated_parameter_names_4.txt3
-rw-r--r--test/prism/errors/duplicated_parameter_names_5.txt3
-rw-r--r--test/prism/errors/dynamic_label_pattern.txt3
-rw-r--r--test/prism/errors/ellipsis_in_no_paren_call.txt3
-rw-r--r--test/prism/errors/endless_method_command_call.txt3
-rw-r--r--test/prism/errors/endless_method_command_call_parameters.txt27
-rw-r--r--test/prism/errors/escape_unicode_curly_whitespace.txt5
-rw-r--r--test/prism/errors/for_loop_delimiter.txt3
-rw-r--r--test/prism/errors/for_loops_index_missing.txt5
-rw-r--r--test/prism/errors/for_loops_only_end.txt6
-rw-r--r--test/prism/errors/forwarding_arg_after_keyword_rest.txt3
-rw-r--r--test/prism/errors/forwarding_arg_and_block.txt3
-rw-r--r--test/prism/errors/heredoc_percent_q_newline_delimiter.txt11
-rw-r--r--test/prism/errors/heredoc_unterminated.txt9
-rw-r--r--test/prism/errors/incomplete_instance_var_string.txt4
-rw-r--r--test/prism/errors/index_call_with_block_and_write.txt5
-rw-r--r--test/prism/errors/index_call_with_block_operator_write.txt5
-rw-r--r--test/prism/errors/index_call_with_block_or_write.txt5
-rw-r--r--test/prism/errors/infix_after_label.txt6
-rw-r--r--test/prism/errors/interpolated_regular_expression_with_unknown_regexp_options.txt3
-rw-r--r--test/prism/errors/invalid_global_variable_write.txt4
-rw-r--r--test/prism/errors/invalid_hex_escape.txt3
-rw-r--r--test/prism/errors/invalid_multi_target.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_10.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_11.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_12.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_13.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_14.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_15.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_16.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_17.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_18.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_19.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_2.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_20.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_3.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_4.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_5.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_6.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_7.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_8.txt4
-rw-r--r--test/prism/errors/invalid_multi_target_9.txt4
-rw-r--r--test/prism/errors/invalid_number_underscores.txt3
-rw-r--r--test/prism/errors/invalid_number_underscores_10.txt3
-rw-r--r--test/prism/errors/invalid_number_underscores_11.txt3
-rw-r--r--test/prism/errors/invalid_number_underscores_12.txt3
-rw-r--r--test/prism/errors/invalid_number_underscores_2.txt3
-rw-r--r--test/prism/errors/invalid_number_underscores_3.txt3
-rw-r--r--test/prism/errors/invalid_number_underscores_4.txt3
-rw-r--r--test/prism/errors/invalid_number_underscores_5.txt3
-rw-r--r--test/prism/errors/invalid_number_underscores_6.txt3
-rw-r--r--test/prism/errors/invalid_number_underscores_7.txt3
-rw-r--r--test/prism/errors/invalid_number_underscores_8.txt3
-rw-r--r--test/prism/errors/invalid_number_underscores_9.txt3
-rw-r--r--test/prism/errors/invalid_operator_write_dot.txt3
-rw-r--r--test/prism/errors/invalid_operator_write_fcall.txt3
-rw-r--r--test/prism/errors/invalid_splat.txt4
-rw-r--r--test/prism/errors/keywords_parameters_before_required_parameters.txt4
-rw-r--r--test/prism/errors/label_in_interpolated_string.txt14
-rw-r--r--test/prism/errors/label_in_parentheses.txt3
-rw-r--r--test/prism/errors/loop_conditional_is_closed.txt4
-rw-r--r--test/prism/errors/match_plus.txt7
-rw-r--r--test/prism/errors/match_predicate_after_and_with_dot_method_call.txt3
-rw-r--r--test/prism/errors/match_predicate_after_and_with_opreator.txt3
-rw-r--r--test/prism/errors/match_predicate_after_or_with_dot_method_call.txt3
-rw-r--r--test/prism/errors/match_predicate_after_or_with_opreator.txt3
-rw-r--r--test/prism/errors/match_predicate_after_rescue_with_dot_method_call.txt3
-rw-r--r--test/prism/errors/match_predicate_after_rescue_with_opreator.txt3
-rw-r--r--test/prism/errors/match_required_after_and_with_dot_method_call.txt3
-rw-r--r--test/prism/errors/match_required_after_and_with_opreator.txt3
-rw-r--r--test/prism/errors/match_required_after_or_with_dot_method_call.txt3
-rw-r--r--test/prism/errors/match_required_after_or_with_opreator.txt3
-rw-r--r--test/prism/errors/match_required_after_rescue_with_dot_method_call.txt3
-rw-r--r--test/prism/errors/match_required_after_rescue_with_opreator.txt3
-rw-r--r--test/prism/errors/method_parameters_after_arguments_forwarding.txt4
-rw-r--r--test/prism/errors/method_parameters_after_block.txt4
-rw-r--r--test/prism/errors/method_with_arguments_after_anonymous_block.txt4
-rw-r--r--test/prism/errors/missing_terminator_in_parentheses.txt3
-rw-r--r--test/prism/errors/module_definition_in_method_body.txt3
-rw-r--r--test/prism/errors/module_definition_in_method_body_within_block.txt7
-rw-r--r--test/prism/errors/module_definition_in_method_defs.txt7
-rw-r--r--test/prism/errors/module_name_recoverable.txt4
-rw-r--r--test/prism/errors/multi_target_parens.txt19
-rw-r--r--test/prism/errors/multi_target_star.txt17
-rw-r--r--test/prism/errors/multiple_error_in_parameters_order.txt5
-rw-r--r--test/prism/errors/next_1.txt4
-rw-r--r--test/prism/errors/next_1_2_3.txt8
-rw-r--r--test/prism/errors/non_assoc_equality.txt25
-rw-r--r--test/prism/errors/non_assoc_range.txt5
-rw-r--r--test/prism/errors/numbered_and_write.txt3
-rw-r--r--test/prism/errors/numbered_operator_write.txt3
-rw-r--r--test/prism/errors/numbered_or_write.txt3
-rw-r--r--test/prism/errors/numbered_parameters_in_block_arguments.txt3
-rw-r--r--test/prism/errors/optional_block_parameters_with_unary_operator.txt3
-rw-r--r--test/prism/errors/optional_block_parameters_with_unary_operator_2.txt3
-rw-r--r--test/prism/errors/optional_block_parameters_with_unary_operator_3.txt3
-rw-r--r--test/prism/errors/optional_block_parameters_with_unary_operator_4.txt3
-rw-r--r--test/prism/errors/parameter_name_ending_with_bang_or_question_mark.txt4
-rw-r--r--test/prism/errors/parameters_invalid_comma.txt4
-rw-r--r--test/prism/errors/pattern-capture-in-alt-array.txt4
-rw-r--r--test/prism/errors/pattern-capture-in-alt-hash.txt3
-rw-r--r--test/prism/errors/pattern-capture-in-alt-name.txt3
-rw-r--r--test/prism/errors/pattern-capture-in-alt-top.txt4
-rw-r--r--test/prism/errors/pattern_arithmetic_expressions.txt3
-rw-r--r--test/prism/errors/pattern_match_implicit_rest.txt3
-rw-r--r--test/prism/errors/pattern_string_key.txt8
-rw-r--r--test/prism/errors/pre_execution_context.txt4
-rw-r--r--test/prism/errors/pre_execution_missing_brace.txt3
-rw-r--r--test/prism/errors/range_and_bin_op.txt5
-rw-r--r--test/prism/errors/range_and_bin_op_2.txt5
-rw-r--r--test/prism/errors/range_and_bin_op_3.txt3
-rw-r--r--test/prism/errors/range_and_bin_op_4.txt5
-rw-r--r--test/prism/errors/range_and_bin_op_5.txt6
-rw-r--r--test/prism/errors/range_and_bin_op_6.txt3
-rw-r--r--test/prism/errors/range_and_bin_op_7.txt3
-rw-r--r--test/prism/errors/range_and_bin_op_8.txt4
-rw-r--r--test/prism/errors/range_doubled.txt3
-rw-r--r--test/prism/errors/rational_number_with_exponential_portion.txt4
-rw-r--r--test/prism/errors/regexp_unicode_too_short.txt4
-rw-r--r--test/prism/errors/regular_expression_with_unknown_regexp_options.txt3
-rw-r--r--test/prism/errors/repeated_parameter_name_in_destructured_params.txt3
-rw-r--r--test/prism/errors/rest_keywords_parameters_before_required_parameters.txt4
-rw-r--r--test/prism/errors/return_1.txt3
-rw-r--r--test/prism/errors/return_1_2_3.txt7
-rw-r--r--test/prism/errors/returning_to_optional_parameters_multiple_times.txt4
-rw-r--r--test/prism/errors/semicolon_after_inheritance_operator.txt3
-rw-r--r--test/prism/errors/setter_method_cannot_be_defined_in_an_endless_method_definition.txt6
-rw-r--r--test/prism/errors/shadow_args_in_block.txt3
-rw-r--r--test/prism/errors/shadow_args_in_lambda.txt5
-rw-r--r--test/prism/errors/singleton_class_delimiter.txt3
-rw-r--r--test/prism/errors/singleton_method_for_literals.txt39
-rw-r--r--test/prism/errors/splat_argument_after_keyword_argument.txt3
-rw-r--r--test/prism/errors/statement_at_non_statement.txt9
-rw-r--r--test/prism/errors/statement_operators.txt25
-rw-r--r--test/prism/errors/switching_to_named_arguments_twice.txt5
-rw-r--r--test/prism/errors/switching_to_optional_arguments_twice.txt5
-rw-r--r--test/prism/errors/symbol_in_hash.txt3
-rw-r--r--test/prism/errors/symbol_in_keyword_parameter.txt3
-rw-r--r--test/prism/errors/targeting_numbered_parameter.txt3
-rw-r--r--test/prism/errors/top_level_constant_starting_with_downcased_identifier.txt4
-rw-r--r--test/prism/errors/top_level_constant_with_downcased_identifier.txt4
-rw-r--r--test/prism/errors/trailing_comma_after_block.txt3
-rw-r--r--test/prism/errors/trailing_comma_in_calls.txt3
-rw-r--r--test/prism/errors/unexpected_block.txt3
-rw-r--r--test/prism/errors/unterminated_W_list.txt3
-rw-r--r--test/prism/errors/unterminated_argument_expression.txt5
-rw-r--r--test/prism/errors/unterminated_begin.txt4
-rw-r--r--test/prism/errors/unterminated_begin_upcase.txt4
-rw-r--r--test/prism/errors/unterminated_block.txt4
-rw-r--r--test/prism/errors/unterminated_block_do_end.txt4
-rw-r--r--test/prism/errors/unterminated_class.txt4
-rw-r--r--test/prism/errors/unterminated_def.txt5
-rw-r--r--test/prism/errors/unterminated_embdoc.txt3
-rw-r--r--test/prism/errors/unterminated_embdoc_2.txt3
-rw-r--r--test/prism/errors/unterminated_empty_string.txt3
-rw-r--r--test/prism/errors/unterminated_end_upcase.txt4
-rw-r--r--test/prism/errors/unterminated_for.txt5
-rw-r--r--test/prism/errors/unterminated_global_variable.txt3
-rw-r--r--test/prism/errors/unterminated_global_variable_2.txt3
-rw-r--r--test/prism/errors/unterminated_i_list.txt3
-rw-r--r--test/prism/errors/unterminated_if.txt5
-rw-r--r--test/prism/errors/unterminated_if_else.txt5
-rw-r--r--test/prism/errors/unterminated_interpolated_string.txt3
-rw-r--r--test/prism/errors/unterminated_interpolated_symbol.txt3
-rw-r--r--test/prism/errors/unterminated_lambda_brace.txt4
-rw-r--r--test/prism/errors/unterminated_method_parameters.txt3
-rw-r--r--test/prism/errors/unterminated_module.txt4
-rw-r--r--test/prism/errors/unterminated_parenthesized_expression.txt4
-rw-r--r--test/prism/errors/unterminated_pattern_bracket.txt7
-rw-r--r--test/prism/errors/unterminated_pattern_paren.txt7
-rw-r--r--test/prism/errors/unterminated_regular_expression.txt3
-rw-r--r--test/prism/errors/unterminated_regular_expression_with_heredoc.txt4
-rw-r--r--test/prism/errors/unterminated_s_symbol.txt3
-rw-r--r--test/prism/errors/unterminated_string.txt3
-rw-r--r--test/prism/errors/unterminated_unicode_brackets_should_be_a_syntax_error.txt3
-rw-r--r--test/prism/errors/unterminated_until.txt5
-rw-r--r--test/prism/errors/unterminated_xstring.txt3
-rw-r--r--test/prism/errors/void_value_expression_in_arguments.txt17
-rw-r--r--test/prism/errors/void_value_expression_in_array.txt15
-rw-r--r--test/prism/errors/void_value_expression_in_assignment.txt9
-rw-r--r--test/prism/errors/void_value_expression_in_begin_statement.txt21
-rw-r--r--test/prism/errors/void_value_expression_in_binary_call.txt11
-rw-r--r--test/prism/errors/void_value_expression_in_call.txt11
-rw-r--r--test/prism/errors/void_value_expression_in_constant_path.txt5
-rw-r--r--test/prism/errors/void_value_expression_in_def.txt10
-rw-r--r--test/prism/errors/void_value_expression_in_expression.txt19
-rw-r--r--test/prism/errors/void_value_expression_in_hash.txt9
-rw-r--r--test/prism/errors/void_value_expression_in_modifier.txt13
-rw-r--r--test/prism/errors/void_value_expression_in_statement.txt26
-rw-r--r--test/prism/errors/void_value_expression_in_unary_call.txt5
-rw-r--r--test/prism/errors/while_endless_method.txt5
-rw-r--r--test/prism/errors/writing_numbered_parameter.txt3
-rw-r--r--test/prism/errors/xstring_concat.txt5
-rw-r--r--test/prism/errors_test.rb2293
-rw-r--r--test/prism/fixtures/3.3-3.3/block_args_in_array_assignment.txt1
-rw-r--r--test/prism/fixtures/3.3-3.3/it.txt5
-rw-r--r--test/prism/fixtures/3.3-3.3/it_indirect_writes.txt23
-rw-r--r--test/prism/fixtures/3.3-3.3/it_read_and_assignment.txt1
-rw-r--r--test/prism/fixtures/3.3-3.3/it_with_ordinary_parameter.txt1
-rw-r--r--test/prism/fixtures/3.3-3.3/keyword_args_in_array_assignment.txt1
-rw-r--r--test/prism/fixtures/3.3-3.3/return_in_sclass.txt1
-rw-r--r--test/prism/fixtures/3.4/circular_parameters.txt4
-rw-r--r--test/prism/fixtures/3.4/it.txt5
-rw-r--r--test/prism/fixtures/3.4/it_indirect_writes.txt23
-rw-r--r--test/prism/fixtures/3.4/it_read_and_assignment.txt1
-rw-r--r--test/prism/fixtures/4.0/endless_methods_command_call.txt8
-rw-r--r--test/prism/fixtures/4.0/leading_logical.txt21
-rw-r--r--test/prism/fixtures/__END__.txt3
-rw-r--r--test/prism/fixtures/begin_rescue.txt6
-rw-r--r--test/prism/fixtures/break.txt8
-rw-r--r--test/prism/fixtures/case_in_hash_key.txt6
-rw-r--r--test/prism/fixtures/character_literal.txt2
-rw-r--r--test/prism/fixtures/command_method_call_2.txt3
-rw-r--r--test/prism/fixtures/command_method_call_3.txt19
-rw-r--r--test/prism/fixtures/comment_single.txt1
-rw-r--r--test/prism/fixtures/defined.txt9
-rw-r--r--test/prism/fixtures/dstring.txt13
-rw-r--r--test/prism/fixtures/dsym_str.txt3
-rw-r--r--test/prism/fixtures/encoding_binary.txt9
-rw-r--r--test/prism/fixtures/encoding_euc_jp.txt6
-rw-r--r--test/prism/fixtures/endless_method_as_default_arg.txt11
-rw-r--r--test/prism/fixtures/endless_methods.txt2
-rw-r--r--test/prism/fixtures/heredoc_percent_q_newline_delimiter.txt22
-rw-r--r--test/prism/fixtures/heredocs_with_fake_newlines.txt55
-rw-r--r--test/prism/fixtures/it_assignment.txt1
-rw-r--r--test/prism/fixtures/keyword_method_names.txt9
-rw-r--r--test/prism/fixtures/lambda.txt16
-rw-r--r--test/prism/fixtures/methods.txt7
-rw-r--r--test/prism/fixtures/next.txt4
-rw-r--r--test/prism/fixtures/patterns.txt23
-rw-r--r--test/prism/fixtures/range_beginless.txt5
-rw-r--r--test/prism/fixtures/ranges.txt2
-rw-r--r--test/prism/fixtures/regex.txt12
-rw-r--r--test/prism/fixtures/regex_escape_encoding.txt3
-rw-r--r--test/prism/fixtures/regex_with_fake_newlines.txt41
-rw-r--r--test/prism/fixtures/rescue.txt4
-rw-r--r--test/prism/fixtures/rescue_modifier.txt7
-rw-r--r--test/prism/fixtures/return.txt3
-rw-r--r--test/prism/fixtures/seattlerb/pct_Q_backslash_nl.txt2
-rw-r--r--test/prism/fixtures/string_concatination_frozen_false.txt5
-rw-r--r--test/prism/fixtures/string_concatination_frozen_true.txt5
-rw-r--r--test/prism/fixtures/strings.txt80
-rw-r--r--test/prism/fixtures/symbols.txt11
-rw-r--r--test/prism/fixtures/unary_method_calls.txt2
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/unary.txt1
-rw-r--r--test/prism/fixtures/variables.txt2
-rw-r--r--test/prism/fixtures/whitequark/LICENSE3
-rw-r--r--test/prism/fixtures/whitequark/arg_combinations.txt29
-rw-r--r--test/prism/fixtures/whitequark/block_arg_combinations.txt57
-rw-r--r--test/prism/fixtures/whitequark/block_kwarg.txt1
-rw-r--r--test/prism/fixtures/whitequark/block_kwarg_combinations.txt5
-rw-r--r--test/prism/fixtures/whitequark/emit_arg_inside_procarg0_legacy.txt1
-rw-r--r--test/prism/fixtures/whitequark/find_pattern.txt7
-rw-r--r--test/prism/fixtures/whitequark/kwarg_combinations.txt7
-rw-r--r--test/prism/fixtures/whitequark/kwarg_no_paren.txt5
-rw-r--r--test/prism/fixtures/whitequark/lvar_injecting_match.txt2
-rw-r--r--test/prism/fixtures/whitequark/marg_combinations.txt19
-rw-r--r--test/prism/fixtures/whitequark/method_definition_in_while_cond.txt7
-rw-r--r--test/prism/fixtures/whitequark/multiple_args_with_trailing_comma.txt1
-rw-r--r--test/prism/fixtures/whitequark/pattern_matching_const_pattern.txt11
-rw-r--r--test/prism/fixtures/whitequark/pattern_matching_constants.txt5
-rw-r--r--test/prism/fixtures/whitequark/pattern_matching_explicit_array_match.txt19
-rw-r--r--test/prism/fixtures/whitequark/pattern_matching_expr_in_paren.txt1
-rw-r--r--test/prism/fixtures/whitequark/pattern_matching_hash.txt48
-rw-r--r--test/prism/fixtures/whitequark/pattern_matching_if_unless_modifiers.txt3
-rw-r--r--test/prism/fixtures/whitequark/pattern_matching_implicit_array_match.txt15
-rw-r--r--test/prism/fixtures/whitequark/pattern_matching_keyword_variable.txt1
-rw-r--r--test/prism/fixtures/whitequark/pattern_matching_lambda.txt1
-rw-r--r--test/prism/fixtures/whitequark/pattern_matching_match_alt.txt1
-rw-r--r--test/prism/fixtures/whitequark/pattern_matching_match_as.txt1
-rw-r--r--test/prism/fixtures/whitequark/pattern_matching_nil_pattern.txt1
-rw-r--r--test/prism/fixtures/whitequark/pattern_matching_no_body.txt1
-rw-r--r--test/prism/fixtures/whitequark/pattern_matching_ranges.txt11
-rw-r--r--test/prism/fixtures/whitequark/pattern_matching_single_match.txt1
-rw-r--r--test/prism/fixtures/whitequark/pin_expr.txt14
-rw-r--r--test/prism/fixtures/whitequark/procarg0_legacy.txt1
-rw-r--r--test/prism/fixtures/whitequark/ruby_bug_18878.txt1
-rw-r--r--test/prism/fixtures/whitequark/ruby_bug_19281.txt7
-rw-r--r--test/prism/fixtures/whitequark/ruby_bug_19539.txt9
-rw-r--r--test/prism/fixtures/xstring.txt8
-rw-r--r--test/prism/fixtures_test.rb24
-rw-r--r--test/prism/lex_test.rb43
-rw-r--r--test/prism/locals_test.rb36
-rw-r--r--test/prism/magic_comment_test.rb10
-rw-r--r--test/prism/newline_test.rb3
-rw-r--r--test/prism/onigmo_test.rb66
-rw-r--r--test/prism/percent_delimiter_string_test.rb82
-rw-r--r--test/prism/ractor_test.rb74
-rw-r--r--test/prism/regexp_test.rb4
-rw-r--r--test/prism/result/breadth_first_search_test.rb18
-rw-r--r--test/prism/result/implicit_array_test.rb59
-rw-r--r--test/prism/result/integer_base_flags_test.rb4
-rw-r--r--test/prism/result/named_capture_test.rb29
-rw-r--r--test/prism/result/node_id_test.rb27
-rw-r--r--test/prism/result/numeric_value_test.rb11
-rw-r--r--test/prism/result/redundant_return_test.rb73
-rw-r--r--test/prism/result/source_location_test.rb12
-rw-r--r--test/prism/result/string_test.rb32
-rw-r--r--test/prism/result/warnings_test.rb186
-rw-r--r--test/prism/ruby/dispatcher_test.rb19
-rw-r--r--test/prism/ruby/location_test.rb87
-rw-r--r--test/prism/ruby/parameters_signature_test.rb7
-rw-r--r--test/prism/ruby/parser_test.rb266
-rw-r--r--test/prism/ruby/relocation_test.rb192
-rw-r--r--test/prism/ruby/ripper_test.rb110
-rw-r--r--test/prism/ruby/ruby_parser_test.rb53
-rw-r--r--test/prism/ruby/source_test.rb47
-rw-r--r--test/prism/ruby/string_query_test.rb60
-rw-r--r--test/prism/snapshots/alias.txt194
-rw-r--r--test/prism/snapshots/arithmetic.txt255
-rw-r--r--test/prism/snapshots/arrays.txt1837
-rw-r--r--test/prism/snapshots/begin_ensure.txt251
-rw-r--r--test/prism/snapshots/begin_rescue.txt699
-rw-r--r--test/prism/snapshots/blocks.txt774
-rw-r--r--test/prism/snapshots/boolean_operators.txt54
-rw-r--r--test/prism/snapshots/booleans.txt7
-rw-r--r--test/prism/snapshots/break.txt401
-rw-r--r--test/prism/snapshots/case.txt495
-rw-r--r--test/prism/snapshots/classes.txt365
-rw-r--r--test/prism/snapshots/command_method_call.txt755
-rw-r--r--test/prism/snapshots/comments.txt145
-rw-r--r--test/prism/snapshots/constants.txt1225
-rw-r--r--test/prism/snapshots/dash_heredocs.txt260
-rw-r--r--test/prism/snapshots/defined.txt88
-rw-r--r--test/prism/snapshots/dos_endings.txt110
-rw-r--r--test/prism/snapshots/dstring.txt85
-rw-r--r--test/prism/snapshots/dsym_str.txt11
-rw-r--r--test/prism/snapshots/embdoc_no_newline_at_end.txt5
-rw-r--r--test/prism/snapshots/emoji_method_calls.txt31
-rw-r--r--test/prism/snapshots/endless_methods.txt107
-rw-r--r--test/prism/snapshots/endless_range_in_conditional.txt53
-rw-r--r--test/prism/snapshots/for.txt188
-rw-r--r--test/prism/snapshots/global_variables.txt191
-rw-r--r--test/prism/snapshots/hashes.txt384
-rw-r--r--test/prism/snapshots/heredoc.txt11
-rw-r--r--test/prism/snapshots/heredoc_with_carriage_returns.txt11
-rw-r--r--test/prism/snapshots/heredoc_with_comment.txt21
-rw-r--r--test/prism/snapshots/heredoc_with_escaped_newline_at_start.txt67
-rw-r--r--test/prism/snapshots/heredoc_with_trailing_newline.txt11
-rw-r--r--test/prism/snapshots/heredocs_leading_whitespace.txt63
-rw-r--r--test/prism/snapshots/heredocs_nested.txt94
-rw-r--r--test/prism/snapshots/heredocs_with_ignored_newlines.txt70
-rw-r--r--test/prism/snapshots/heredocs_with_ignored_newlines_and_non_empty.txt11
-rw-r--r--test/prism/snapshots/if.txt531
-rw-r--r--test/prism/snapshots/indented_file_end.txt18
-rw-r--r--test/prism/snapshots/integer_operations.txt635
-rw-r--r--test/prism/snapshots/keyword_method_names.txt173
-rw-r--r--test/prism/snapshots/keywords.txt47
-rw-r--r--test/prism/snapshots/lambda.txt202
-rw-r--r--test/prism/snapshots/method_calls.txt2456
-rw-r--r--test/prism/snapshots/methods.txt2054
-rw-r--r--test/prism/snapshots/modules.txt180
-rw-r--r--test/prism/snapshots/multi_write.txt93
-rw-r--r--test/prism/snapshots/newline_terminated.txt107
-rw-r--r--test/prism/snapshots/next.txt329
-rw-r--r--test/prism/snapshots/nils.txt34
-rw-r--r--test/prism/snapshots/non_alphanumeric_methods.txt503
-rw-r--r--test/prism/snapshots/not.txt351
-rw-r--r--test/prism/snapshots/numbers.txt135
-rw-r--r--test/prism/snapshots/patterns.txt4909
-rw-r--r--test/prism/snapshots/procs.txt403
-rw-r--r--test/prism/snapshots/range_begin_open_exclusive.txt13
-rw-r--r--test/prism/snapshots/range_begin_open_inclusive.txt13
-rw-r--r--test/prism/snapshots/range_end_open_exclusive.txt13
-rw-r--r--test/prism/snapshots/range_end_open_inclusive.txt13
-rw-r--r--test/prism/snapshots/ranges.txt533
-rw-r--r--test/prism/snapshots/regex.txt510
-rw-r--r--test/prism/snapshots/regex_char_width.txt50
-rw-r--r--test/prism/snapshots/repeat_parameters.txt473
-rw-r--r--test/prism/snapshots/rescue.txt528
-rw-r--r--test/prism/snapshots/return.txt165
-rw-r--r--test/prism/snapshots/seattlerb/BEGIN.txt15
-rw-r--r--test/prism/snapshots/seattlerb/TestRubyParserShared.txt361
-rw-r--r--test/prism/snapshots/seattlerb/__ENCODING__.txt6
-rw-r--r--test/prism/snapshots/seattlerb/alias_gvar_backref.txt13
-rw-r--r--test/prism/snapshots/seattlerb/alias_resword.txt21
-rw-r--r--test/prism/snapshots/seattlerb/and_multi.txt26
-rw-r--r--test/prism/snapshots/seattlerb/aref_args_assocs.txt23
-rw-r--r--test/prism/snapshots/seattlerb/aref_args_lit_assocs.txt26
-rw-r--r--test/prism/snapshots/seattlerb/args_kw_block.txt39
-rw-r--r--test/prism/snapshots/seattlerb/array_line_breaks.txt25
-rw-r--r--test/prism/snapshots/seattlerb/array_lits_trailing_calls.txt35
-rw-r--r--test/prism/snapshots/seattlerb/assoc__bare.txt31
-rw-r--r--test/prism/snapshots/seattlerb/assoc_label.txt34
-rw-r--r--test/prism/snapshots/seattlerb/attr_asgn_colon_id.txt23
-rw-r--r--test/prism/snapshots/seattlerb/attrasgn_array_arg.txt42
-rw-r--r--test/prism/snapshots/seattlerb/attrasgn_array_lhs.txt83
-rw-r--r--test/prism/snapshots/seattlerb/attrasgn_primary_dot_constant.txt31
-rw-r--r--test/prism/snapshots/seattlerb/backticks_interpolation_line.txt38
-rw-r--r--test/prism/snapshots/seattlerb/bang_eq.txt24
-rw-r--r--test/prism/snapshots/seattlerb/bdot2.txt38
-rw-r--r--test/prism/snapshots/seattlerb/bdot3.txt38
-rw-r--r--test/prism/snapshots/seattlerb/begin_ensure_no_bodies.txt16
-rw-r--r--test/prism/snapshots/seattlerb/begin_rescue_else_ensure_bodies.txt47
-rw-r--r--test/prism/snapshots/seattlerb/begin_rescue_else_ensure_no_bodies.txt27
-rw-r--r--test/prism/snapshots/seattlerb/begin_rescue_ensure_no_bodies.txt23
-rw-r--r--test/prism/snapshots/seattlerb/block_arg__bare.txt31
-rw-r--r--test/prism/snapshots/seattlerb/block_arg_kwsplat.txt39
-rw-r--r--test/prism/snapshots/seattlerb/block_arg_opt_arg_block.txt54
-rw-r--r--test/prism/snapshots/seattlerb/block_arg_opt_splat.txt51
-rw-r--r--test/prism/snapshots/seattlerb/block_arg_opt_splat_arg_block_omfg.txt59
-rw-r--r--test/prism/snapshots/seattlerb/block_arg_optional.txt43
-rw-r--r--test/prism/snapshots/seattlerb/block_arg_scope.txt40
-rw-r--r--test/prism/snapshots/seattlerb/block_arg_scope2.txt43
-rw-r--r--test/prism/snapshots/seattlerb/block_arg_splat_arg.txt45
-rw-r--r--test/prism/snapshots/seattlerb/block_args_kwargs.txt44
-rw-r--r--test/prism/snapshots/seattlerb/block_args_no_kwargs.txt37
-rw-r--r--test/prism/snapshots/seattlerb/block_args_opt1.txt59
-rw-r--r--test/prism/snapshots/seattlerb/block_args_opt2.txt52
-rw-r--r--test/prism/snapshots/seattlerb/block_args_opt2_2.txt71
-rw-r--r--test/prism/snapshots/seattlerb/block_args_opt3.txt79
-rw-r--r--test/prism/snapshots/seattlerb/block_call_defn_call_block_call.txt80
-rw-r--r--test/prism/snapshots/seattlerb/block_call_dot_op2_brace_block.txt100
-rw-r--r--test/prism/snapshots/seattlerb/block_call_dot_op2_cmd_args_do_block.txt113
-rw-r--r--test/prism/snapshots/seattlerb/block_call_operation_colon.txt54
-rw-r--r--test/prism/snapshots/seattlerb/block_call_operation_dot.txt54
-rw-r--r--test/prism/snapshots/seattlerb/block_call_paren_call_block_call.txt60
-rw-r--r--test/prism/snapshots/seattlerb/block_command_operation_colon.txt49
-rw-r--r--test/prism/snapshots/seattlerb/block_command_operation_dot.txt49
-rw-r--r--test/prism/snapshots/seattlerb/block_decomp_anon_splat_arg.txt46
-rw-r--r--test/prism/snapshots/seattlerb/block_decomp_arg_splat.txt46
-rw-r--r--test/prism/snapshots/seattlerb/block_decomp_arg_splat_arg.txt52
-rw-r--r--test/prism/snapshots/seattlerb/block_decomp_splat.txt46
-rw-r--r--test/prism/snapshots/seattlerb/block_kw.txt42
-rw-r--r--test/prism/snapshots/seattlerb/block_kw__required.txt38
-rw-r--r--test/prism/snapshots/seattlerb/block_kwarg_lvar.txt50
-rw-r--r--test/prism/snapshots/seattlerb/block_kwarg_lvar_multiple.txt61
-rw-r--r--test/prism/snapshots/seattlerb/block_opt_arg.txt46
-rw-r--r--test/prism/snapshots/seattlerb/block_opt_splat.txt48
-rw-r--r--test/prism/snapshots/seattlerb/block_opt_splat_arg_block_omfg.txt56
-rw-r--r--test/prism/snapshots/seattlerb/block_optarg.txt46
-rw-r--r--test/prism/snapshots/seattlerb/block_paren_splat.txt49
-rw-r--r--test/prism/snapshots/seattlerb/block_reg_optarg.txt49
-rw-r--r--test/prism/snapshots/seattlerb/block_return.txt57
-rw-r--r--test/prism/snapshots/seattlerb/block_scope.txt29
-rw-r--r--test/prism/snapshots/seattlerb/block_splat_reg.txt42
-rw-r--r--test/prism/snapshots/seattlerb/bug169.txt28
-rw-r--r--test/prism/snapshots/seattlerb/bug179.txt28
-rw-r--r--test/prism/snapshots/seattlerb/bug190.txt11
-rw-r--r--test/prism/snapshots/seattlerb/bug191.txt87
-rw-r--r--test/prism/snapshots/seattlerb/bug202.txt22
-rw-r--r--test/prism/snapshots/seattlerb/bug236.txt70
-rw-r--r--test/prism/snapshots/seattlerb/bug290.txt24
-rw-r--r--test/prism/snapshots/seattlerb/bug_187.txt59
-rw-r--r--test/prism/snapshots/seattlerb/bug_215.txt14
-rw-r--r--test/prism/snapshots/seattlerb/bug_249.txt86
-rw-r--r--test/prism/snapshots/seattlerb/bug_and.txt21
-rw-r--r--test/prism/snapshots/seattlerb/bug_args__19.txt58
-rw-r--r--test/prism/snapshots/seattlerb/bug_args_masgn.txt49
-rw-r--r--test/prism/snapshots/seattlerb/bug_args_masgn2.txt58
-rw-r--r--test/prism/snapshots/seattlerb/bug_args_masgn_outer_parens__19.txt55
-rw-r--r--test/prism/snapshots/seattlerb/bug_call_arglist_parens.txt110
-rw-r--r--test/prism/snapshots/seattlerb/bug_case_when_regexp.txt28
-rw-r--r--test/prism/snapshots/seattlerb/bug_comma.txt41
-rw-r--r--test/prism/snapshots/seattlerb/bug_cond_pct.txt22
-rw-r--r--test/prism/snapshots/seattlerb/bug_hash_args.txt38
-rw-r--r--test/prism/snapshots/seattlerb/bug_hash_args_trailing_comma.txt38
-rw-r--r--test/prism/snapshots/seattlerb/bug_hash_interp_array.txt26
-rw-r--r--test/prism/snapshots/seattlerb/bug_masgn_right.txt49
-rw-r--r--test/prism/snapshots/seattlerb/bug_not_parens.txt25
-rw-r--r--test/prism/snapshots/seattlerb/bug_op_asgn_rescue.txt26
-rw-r--r--test/prism/snapshots/seattlerb/call_and.txt24
-rw-r--r--test/prism/snapshots/seattlerb/call_arg_assoc.txt34
-rw-r--r--test/prism/snapshots/seattlerb/call_arg_assoc_kwsplat.txt43
-rw-r--r--test/prism/snapshots/seattlerb/call_arg_kwsplat.txt37
-rw-r--r--test/prism/snapshots/seattlerb/call_args_assoc_quoted.txt106
-rw-r--r--test/prism/snapshots/seattlerb/call_args_assoc_trailing_comma.txt34
-rw-r--r--test/prism/snapshots/seattlerb/call_args_command.txt54
-rw-r--r--test/prism/snapshots/seattlerb/call_array_arg.txt38
-rw-r--r--test/prism/snapshots/seattlerb/call_array_block_call.txt40
-rw-r--r--test/prism/snapshots/seattlerb/call_array_lambda_block_call.txt41
-rw-r--r--test/prism/snapshots/seattlerb/call_array_lit_inline_hash.txt45
-rw-r--r--test/prism/snapshots/seattlerb/call_assoc.txt31
-rw-r--r--test/prism/snapshots/seattlerb/call_assoc_new.txt34
-rw-r--r--test/prism/snapshots/seattlerb/call_assoc_new_if_multiline.txt58
-rw-r--r--test/prism/snapshots/seattlerb/call_assoc_trailing_comma.txt31
-rw-r--r--test/prism/snapshots/seattlerb/call_bang_command_call.txt41
-rw-r--r--test/prism/snapshots/seattlerb/call_bang_squiggle.txt24
-rw-r--r--test/prism/snapshots/seattlerb/call_begin_call_block_call.txt53
-rw-r--r--test/prism/snapshots/seattlerb/call_block_arg_named.txt28
-rw-r--r--test/prism/snapshots/seattlerb/call_carat.txt24
-rw-r--r--test/prism/snapshots/seattlerb/call_colon2.txt17
-rw-r--r--test/prism/snapshots/seattlerb/call_colon_parens.txt18
-rw-r--r--test/prism/snapshots/seattlerb/call_div.txt24
-rw-r--r--test/prism/snapshots/seattlerb/call_dot_parens.txt18
-rw-r--r--test/prism/snapshots/seattlerb/call_env.txt25
-rw-r--r--test/prism/snapshots/seattlerb/call_eq3.txt24
-rw-r--r--test/prism/snapshots/seattlerb/call_gt.txt24
-rw-r--r--test/prism/snapshots/seattlerb/call_kwsplat.txt27
-rw-r--r--test/prism/snapshots/seattlerb/call_leading_dots.txt35
-rw-r--r--test/prism/snapshots/seattlerb/call_leading_dots_comment.txt35
-rw-r--r--test/prism/snapshots/seattlerb/call_lt.txt24
-rw-r--r--test/prism/snapshots/seattlerb/call_lte.txt24
-rw-r--r--test/prism/snapshots/seattlerb/call_not.txt18
-rw-r--r--test/prism/snapshots/seattlerb/call_pipe.txt24
-rw-r--r--test/prism/snapshots/seattlerb/call_rshift.txt24
-rw-r--r--test/prism/snapshots/seattlerb/call_self_brackets.txt22
-rw-r--r--test/prism/snapshots/seattlerb/call_spaceship.txt24
-rw-r--r--test/prism/snapshots/seattlerb/call_stabby_do_end_with_block.txt41
-rw-r--r--test/prism/snapshots/seattlerb/call_stabby_with_braces_block.txt41
-rw-r--r--test/prism/snapshots/seattlerb/call_star.txt24
-rw-r--r--test/prism/snapshots/seattlerb/call_star2.txt24
-rw-r--r--test/prism/snapshots/seattlerb/call_trailing_comma.txt21
-rw-r--r--test/prism/snapshots/seattlerb/call_trailing_dots.txt35
-rw-r--r--test/prism/snapshots/seattlerb/call_unary_bang.txt18
-rw-r--r--test/prism/snapshots/seattlerb/case_in.txt976
-rw-r--r--test/prism/snapshots/seattlerb/case_in_31.txt49
-rw-r--r--test/prism/snapshots/seattlerb/case_in_37.txt58
-rw-r--r--test/prism/snapshots/seattlerb/case_in_42.txt44
-rw-r--r--test/prism/snapshots/seattlerb/case_in_42_2.txt40
-rw-r--r--test/prism/snapshots/seattlerb/case_in_47.txt52
-rw-r--r--test/prism/snapshots/seattlerb/case_in_67.txt33
-rw-r--r--test/prism/snapshots/seattlerb/case_in_86.txt51
-rw-r--r--test/prism/snapshots/seattlerb/case_in_86_2.txt51
-rw-r--r--test/prism/snapshots/seattlerb/case_in_array_pat_const.txt42
-rw-r--r--test/prism/snapshots/seattlerb/case_in_array_pat_const2.txt47
-rw-r--r--test/prism/snapshots/seattlerb/case_in_array_pat_paren_assign.txt48
-rw-r--r--test/prism/snapshots/seattlerb/case_in_const.txt28
-rw-r--r--test/prism/snapshots/seattlerb/case_in_else.txt40
-rw-r--r--test/prism/snapshots/seattlerb/case_in_find.txt47
-rw-r--r--test/prism/snapshots/seattlerb/case_in_find_array.txt44
-rw-r--r--test/prism/snapshots/seattlerb/case_in_hash_pat.txt68
-rw-r--r--test/prism/snapshots/seattlerb/case_in_hash_pat_assign.txt86
-rw-r--r--test/prism/snapshots/seattlerb/case_in_hash_pat_paren_assign.txt51
-rw-r--r--test/prism/snapshots/seattlerb/case_in_hash_pat_paren_true.txt47
-rw-r--r--test/prism/snapshots/seattlerb/case_in_hash_pat_rest.txt55
-rw-r--r--test/prism/snapshots/seattlerb/case_in_hash_pat_rest_solo.txt42
-rw-r--r--test/prism/snapshots/seattlerb/case_in_if_unless_post_mod.txt67
-rw-r--r--test/prism/snapshots/seattlerb/case_in_multiple.txt57
-rw-r--r--test/prism/snapshots/seattlerb/case_in_or.txt38
-rw-r--r--test/prism/snapshots/seattlerb/class_comments.txt31
-rw-r--r--test/prism/snapshots/seattlerb/cond_unary_minus.txt15
-rw-r--r--test/prism/snapshots/seattlerb/const_2_op_asgn_or2.txt22
-rw-r--r--test/prism/snapshots/seattlerb/const_3_op_asgn_or.txt17
-rw-r--r--test/prism/snapshots/seattlerb/const_op_asgn_and1.txt18
-rw-r--r--test/prism/snapshots/seattlerb/const_op_asgn_and2.txt17
-rw-r--r--test/prism/snapshots/seattlerb/const_op_asgn_or.txt19
-rw-r--r--test/prism/snapshots/seattlerb/dasgn_icky2.txt61
-rw-r--r--test/prism/snapshots/seattlerb/defined_eh_parens.txt13
-rw-r--r--test/prism/snapshots/seattlerb/defn_arg_asplat_arg.txt37
-rw-r--r--test/prism/snapshots/seattlerb/defn_arg_forward_args.txt49
-rw-r--r--test/prism/snapshots/seattlerb/defn_args_forward_args.txt61
-rw-r--r--test/prism/snapshots/seattlerb/defn_comments.txt18
-rw-r--r--test/prism/snapshots/seattlerb/defn_endless_command.txt36
-rw-r--r--test/prism/snapshots/seattlerb/defn_endless_command_rescue.txt43
-rw-r--r--test/prism/snapshots/seattlerb/defn_forward_args.txt43
-rw-r--r--test/prism/snapshots/seattlerb/defn_forward_args__no_parens.txt43
-rw-r--r--test/prism/snapshots/seattlerb/defn_kwarg_env.txt55
-rw-r--r--test/prism/snapshots/seattlerb/defn_kwarg_kwarg.txt45
-rw-r--r--test/prism/snapshots/seattlerb/defn_kwarg_kwsplat.txt39
-rw-r--r--test/prism/snapshots/seattlerb/defn_kwarg_kwsplat_anon.txt39
-rw-r--r--test/prism/snapshots/seattlerb/defn_kwarg_lvar.txt42
-rw-r--r--test/prism/snapshots/seattlerb/defn_kwarg_no_parens.txt34
-rw-r--r--test/prism/snapshots/seattlerb/defn_kwarg_val.txt37
-rw-r--r--test/prism/snapshots/seattlerb/defn_no_kwargs.txt29
-rw-r--r--test/prism/snapshots/seattlerb/defn_oneliner.txt47
-rw-r--r--test/prism/snapshots/seattlerb/defn_oneliner_eq2.txt47
-rw-r--r--test/prism/snapshots/seattlerb/defn_oneliner_noargs.txt30
-rw-r--r--test/prism/snapshots/seattlerb/defn_oneliner_noargs_parentheses.txt30
-rw-r--r--test/prism/snapshots/seattlerb/defn_oneliner_rescue.txt158
-rw-r--r--test/prism/snapshots/seattlerb/defn_opt_last_arg.txt33
-rw-r--r--test/prism/snapshots/seattlerb/defn_opt_reg.txt36
-rw-r--r--test/prism/snapshots/seattlerb/defn_opt_splat_arg.txt43
-rw-r--r--test/prism/snapshots/seattlerb/defn_powarg.txt31
-rw-r--r--test/prism/snapshots/seattlerb/defn_reg_opt_reg.txt44
-rw-r--r--test/prism/snapshots/seattlerb/defn_splat_arg.txt34
-rw-r--r--test/prism/snapshots/seattlerb/defn_unary_not.txt21
-rw-r--r--test/prism/snapshots/seattlerb/defns_reserved.txt19
-rw-r--r--test/prism/snapshots/seattlerb/defs_as_arg_with_do_block_inside.txt60
-rw-r--r--test/prism/snapshots/seattlerb/defs_comments.txt19
-rw-r--r--test/prism/snapshots/seattlerb/defs_endless_command.txt46
-rw-r--r--test/prism/snapshots/seattlerb/defs_endless_command_rescue.txt53
-rw-r--r--test/prism/snapshots/seattlerb/defs_kwarg.txt35
-rw-r--r--test/prism/snapshots/seattlerb/defs_oneliner.txt48
-rw-r--r--test/prism/snapshots/seattlerb/defs_oneliner_eq2.txt48
-rw-r--r--test/prism/snapshots/seattlerb/defs_oneliner_rescue.txt161
-rw-r--r--test/prism/snapshots/seattlerb/difficult0_.txt73
-rw-r--r--test/prism/snapshots/seattlerb/difficult1_line_numbers.txt267
-rw-r--r--test/prism/snapshots/seattlerb/difficult1_line_numbers2.txt78
-rw-r--r--test/prism/snapshots/seattlerb/difficult2_.txt74
-rw-r--r--test/prism/snapshots/seattlerb/difficult3_.txt52
-rw-r--r--test/prism/snapshots/seattlerb/difficult3_2.txt42
-rw-r--r--test/prism/snapshots/seattlerb/difficult3_3.txt47
-rw-r--r--test/prism/snapshots/seattlerb/difficult3_4.txt38
-rw-r--r--test/prism/snapshots/seattlerb/difficult3_5.txt48
-rw-r--r--test/prism/snapshots/seattlerb/difficult3__10.txt52
-rw-r--r--test/prism/snapshots/seattlerb/difficult3__11.txt46
-rw-r--r--test/prism/snapshots/seattlerb/difficult3__12.txt49
-rw-r--r--test/prism/snapshots/seattlerb/difficult3__6.txt55
-rw-r--r--test/prism/snapshots/seattlerb/difficult3__7.txt49
-rw-r--r--test/prism/snapshots/seattlerb/difficult3__8.txt52
-rw-r--r--test/prism/snapshots/seattlerb/difficult3__9.txt49
-rw-r--r--test/prism/snapshots/seattlerb/difficult4__leading_dots.txt25
-rw-r--r--test/prism/snapshots/seattlerb/difficult4__leading_dots2.txt16
-rw-r--r--test/prism/snapshots/seattlerb/difficult6_.txt61
-rw-r--r--test/prism/snapshots/seattlerb/difficult6__7.txt55
-rw-r--r--test/prism/snapshots/seattlerb/difficult6__8.txt55
-rw-r--r--test/prism/snapshots/seattlerb/difficult7_.txt93
-rw-r--r--test/prism/snapshots/seattlerb/do_bug.txt63
-rw-r--r--test/prism/snapshots/seattlerb/do_lambda.txt17
-rw-r--r--test/prism/snapshots/seattlerb/dot2_nil__26.txt20
-rw-r--r--test/prism/snapshots/seattlerb/dot3_nil__26.txt20
-rw-r--r--test/prism/snapshots/seattlerb/dstr_evstr.txt38
-rw-r--r--test/prism/snapshots/seattlerb/dstr_evstr_empty_end.txt25
-rw-r--r--test/prism/snapshots/seattlerb/dstr_lex_state.txt35
-rw-r--r--test/prism/snapshots/seattlerb/dstr_str.txt28
-rw-r--r--test/prism/snapshots/seattlerb/dsym_esc_to_sym.txt11
-rw-r--r--test/prism/snapshots/seattlerb/dsym_to_sym.txt37
-rw-r--r--test/prism/snapshots/seattlerb/eq_begin_line_numbers.txt11
-rw-r--r--test/prism/snapshots/seattlerb/eq_begin_why_wont_people_use_their_spacebar.txt50
-rw-r--r--test/prism/snapshots/seattlerb/evstr_evstr.txt42
-rw-r--r--test/prism/snapshots/seattlerb/evstr_str.txt32
-rw-r--r--test/prism/snapshots/seattlerb/expr_not_bang.txt38
-rw-r--r--test/prism/snapshots/seattlerb/f_kw.txt34
-rw-r--r--test/prism/snapshots/seattlerb/f_kw__required.txt30
-rw-r--r--test/prism/snapshots/seattlerb/flip2_env_lvar.txt37
-rw-r--r--test/prism/snapshots/seattlerb/float_with_if_modifier.txt17
-rw-r--r--test/prism/snapshots/seattlerb/heredoc__backslash_dos_format.txt17
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_backslash_nl.txt17
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_bad_hex_escape.txt17
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_bad_oct_escape.txt17
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_comma_arg.txt27
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_lineno.txt26
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_nested.txt42
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_squiggly.txt34
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_squiggly_blank_line_plus_interpolation.txt67
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_squiggly_blank_lines.txt34
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_squiggly_empty.txt11
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_squiggly_interp.txt49
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_squiggly_no_indent.txt11
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_squiggly_tabs.txt28
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_squiggly_tabs_extra.txt28
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_squiggly_visually_blank_lines.txt34
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_trailing_slash_continued_call.txt21
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_unicode.txt11
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_with_carriage_return_escapes.txt11
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_with_carriage_return_escapes_windows.txt11
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_with_extra_carriage_horrible_mix.txt11
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_with_extra_carriage_returns.txt11
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_with_extra_carriage_returns_windows.txt11
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_with_interpolation_and_carriage_return_escapes.txt27
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_with_interpolation_and_carriage_return_escapes_windows.txt27
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_with_not_global_interpolation.txt11
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_with_only_carriage_returns.txt11
-rw-r--r--test/prism/snapshots/seattlerb/heredoc_with_only_carriage_returns_windows.txt11
-rw-r--r--test/prism/snapshots/seattlerb/if_elsif.txt25
-rw-r--r--test/prism/snapshots/seattlerb/if_symbol.txt31
-rw-r--r--test/prism/snapshots/seattlerb/in_expr_no_case.txt17
-rw-r--r--test/prism/snapshots/seattlerb/index_0.txt38
-rw-r--r--test/prism/snapshots/seattlerb/index_0_opasgn.txt36
-rw-r--r--test/prism/snapshots/seattlerb/integer_with_if_modifier.txt18
-rw-r--r--test/prism/snapshots/seattlerb/interpolated_symbol_array_line_breaks.txt25
-rw-r--r--test/prism/snapshots/seattlerb/interpolated_word_array_line_breaks.txt25
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_1.txt40
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_10_1.txt51
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_10_2.txt56
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_11_1.txt54
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_11_2.txt59
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_2__19.txt46
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_3.txt52
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_4.txt45
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_5.txt42
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_6.txt49
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_7_1.txt48
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_7_2.txt53
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_8_1.txt51
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_8_2.txt56
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_9_1.txt46
-rw-r--r--test/prism/snapshots/seattlerb/iter_args_9_2.txt51
-rw-r--r--test/prism/snapshots/seattlerb/iter_kwarg.txt42
-rw-r--r--test/prism/snapshots/seattlerb/iter_kwarg_kwsplat.txt47
-rw-r--r--test/prism/snapshots/seattlerb/label_vs_string.txt34
-rw-r--r--test/prism/snapshots/seattlerb/lambda_do_vs_brace.txt95
-rw-r--r--test/prism/snapshots/seattlerb/lasgn_arg_rescue_arg.txt21
-rw-r--r--test/prism/snapshots/seattlerb/lasgn_call_bracket_rescue_arg.txt34
-rw-r--r--test/prism/snapshots/seattlerb/lasgn_call_nobracket_rescue_arg.txt34
-rw-r--r--test/prism/snapshots/seattlerb/lasgn_command.txt37
-rw-r--r--test/prism/snapshots/seattlerb/lasgn_env.txt14
-rw-r--r--test/prism/snapshots/seattlerb/lasgn_ivar_env.txt13
-rw-r--r--test/prism/snapshots/seattlerb/lasgn_lasgn_command_call.txt33
-rw-r--r--test/prism/snapshots/seattlerb/lasgn_middle_splat.txt49
-rw-r--r--test/prism/snapshots/seattlerb/magic_encoding_comment.txt46
-rw-r--r--test/prism/snapshots/seattlerb/masgn_anon_splat_arg.txt29
-rw-r--r--test/prism/snapshots/seattlerb/masgn_arg_colon_arg.txt42
-rw-r--r--test/prism/snapshots/seattlerb/masgn_arg_ident.txt42
-rw-r--r--test/prism/snapshots/seattlerb/masgn_arg_splat_arg.txt35
-rw-r--r--test/prism/snapshots/seattlerb/masgn_colon2.txt42
-rw-r--r--test/prism/snapshots/seattlerb/masgn_colon3.txt34
-rw-r--r--test/prism/snapshots/seattlerb/masgn_command_call.txt43
-rw-r--r--test/prism/snapshots/seattlerb/masgn_double_paren.txt35
-rw-r--r--test/prism/snapshots/seattlerb/masgn_lhs_splat.txt33
-rw-r--r--test/prism/snapshots/seattlerb/masgn_paren.txt39
-rw-r--r--test/prism/snapshots/seattlerb/masgn_splat_arg.txt32
-rw-r--r--test/prism/snapshots/seattlerb/masgn_splat_arg_arg.txt35
-rw-r--r--test/prism/snapshots/seattlerb/masgn_star.txt19
-rw-r--r--test/prism/snapshots/seattlerb/masgn_var_star_var.txt32
-rw-r--r--test/prism/snapshots/seattlerb/messy_op_asgn_lineno.txt59
-rw-r--r--test/prism/snapshots/seattlerb/method_call_assoc_trailing_comma.txt41
-rw-r--r--test/prism/snapshots/seattlerb/method_call_trailing_comma.txt31
-rw-r--r--test/prism/snapshots/seattlerb/mlhs_back_anonsplat.txt35
-rw-r--r--test/prism/snapshots/seattlerb/mlhs_back_splat.txt38
-rw-r--r--test/prism/snapshots/seattlerb/mlhs_front_anonsplat.txt35
-rw-r--r--test/prism/snapshots/seattlerb/mlhs_front_splat.txt38
-rw-r--r--test/prism/snapshots/seattlerb/mlhs_keyword.txt30
-rw-r--r--test/prism/snapshots/seattlerb/mlhs_mid_anonsplat.txt44
-rw-r--r--test/prism/snapshots/seattlerb/mlhs_mid_splat.txt47
-rw-r--r--test/prism/snapshots/seattlerb/mlhs_rescue.txt36
-rw-r--r--test/prism/snapshots/seattlerb/module_comments.txt29
-rw-r--r--test/prism/snapshots/seattlerb/multiline_hash_declaration.txt95
-rw-r--r--test/prism/snapshots/seattlerb/non_interpolated_symbol_array_line_breaks.txt25
-rw-r--r--test/prism/snapshots/seattlerb/non_interpolated_word_array_line_breaks.txt25
-rw-r--r--test/prism/snapshots/seattlerb/op_asgn_command_call.txt37
-rw-r--r--test/prism/snapshots/seattlerb/op_asgn_dot_ident_command_call.txt32
-rw-r--r--test/prism/snapshots/seattlerb/op_asgn_index_command_call.txt53
-rw-r--r--test/prism/snapshots/seattlerb/op_asgn_primary_colon_const_command_call.txt40
-rw-r--r--test/prism/snapshots/seattlerb/op_asgn_primary_colon_identifier1.txt20
-rw-r--r--test/prism/snapshots/seattlerb/op_asgn_primary_colon_identifier_command_call.txt40
-rw-r--r--test/prism/snapshots/seattlerb/op_asgn_val_dot_ident_command_call.txt40
-rw-r--r--test/prism/snapshots/seattlerb/parse_def_special_name.txt18
-rw-r--r--test/prism/snapshots/seattlerb/parse_if_not_canonical.txt62
-rw-r--r--test/prism/snapshots/seattlerb/parse_if_not_noncanonical.txt62
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_block.txt30
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_block_inline_comment.txt35
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_block_inline_comment_leading_newlines.txt35
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_block_inline_multiline_comment.txt35
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_call_ivar_arg_no_parens_line_break.txt20
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_call_ivar_line_break_paren.txt20
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_call_no_args.txt61
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_defn_complex.txt67
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_defn_no_parens.txt31
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_defn_no_parens_args.txt29
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_dot2.txt51
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_dot2_open.txt38
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_dot3.txt51
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_dot3_open.txt38
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_dstr_escaped_newline.txt21
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_dstr_soft_newline.txt21
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_evstr_after_break.txt37
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_hash_lit.txt22
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_heredoc.txt43
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_heredoc_evstr.txt38
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_heredoc_hardnewline.txt22
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_heredoc_regexp_chars.txt33
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_iter_call_no_parens.txt74
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_iter_call_parens.txt74
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_multiline_str.txt14
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_multiline_str_literal_n.txt14
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_newlines.txt6
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_op_asgn.txt32
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_postexe.txt22
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_preexe.txt22
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_rescue.txt62
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_return.txt40
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_str_with_newline_escape.txt25
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_to_ary.txt39
-rw-r--r--test/prism/snapshots/seattlerb/parse_line_trailing_newlines.txt25
-rw-r--r--test/prism/snapshots/seattlerb/parse_opt_call_args_assocs_comma.txt34
-rw-r--r--test/prism/snapshots/seattlerb/parse_opt_call_args_lit_comma.txt24
-rw-r--r--test/prism/snapshots/seattlerb/parse_pattern_019.txt33
-rw-r--r--test/prism/snapshots/seattlerb/parse_pattern_044.txt38
-rw-r--r--test/prism/snapshots/seattlerb/parse_pattern_051.txt47
-rw-r--r--test/prism/snapshots/seattlerb/parse_pattern_058.txt73
-rw-r--r--test/prism/snapshots/seattlerb/parse_pattern_058_2.txt67
-rw-r--r--test/prism/snapshots/seattlerb/parse_pattern_069.txt48
-rw-r--r--test/prism/snapshots/seattlerb/parse_pattern_076.txt58
-rw-r--r--test/prism/snapshots/seattlerb/parse_until_not_canonical.txt49
-rw-r--r--test/prism/snapshots/seattlerb/parse_until_not_noncanonical.txt49
-rw-r--r--test/prism/snapshots/seattlerb/parse_while_not_canonical.txt49
-rw-r--r--test/prism/snapshots/seattlerb/parse_while_not_noncanonical.txt49
-rw-r--r--test/prism/snapshots/seattlerb/pctW_lineno.txt52
-rw-r--r--test/prism/snapshots/seattlerb/pct_Q_backslash_nl.txt11
-rw-r--r--test/prism/snapshots/seattlerb/pct_nl.txt17
-rw-r--r--test/prism/snapshots/seattlerb/pct_w_heredoc_interp_nested.txt51
-rw-r--r--test/prism/snapshots/seattlerb/pipe_semicolon.txt39
-rw-r--r--test/prism/snapshots/seattlerb/pipe_space.txt36
-rw-r--r--test/prism/snapshots/seattlerb/qWords_space.txt10
-rw-r--r--test/prism/snapshots/seattlerb/qsymbols.txt28
-rw-r--r--test/prism/snapshots/seattlerb/qsymbols_empty.txt10
-rw-r--r--test/prism/snapshots/seattlerb/qsymbols_empty_space.txt10
-rw-r--r--test/prism/snapshots/seattlerb/qsymbols_interp.txt57
-rw-r--r--test/prism/snapshots/seattlerb/quoted_symbol_hash_arg.txt35
-rw-r--r--test/prism/snapshots/seattlerb/quoted_symbol_keys.txt25
-rw-r--r--test/prism/snapshots/seattlerb/qw_escape.txt11
-rw-r--r--test/prism/snapshots/seattlerb/qw_escape_term.txt11
-rw-r--r--test/prism/snapshots/seattlerb/qwords_empty.txt10
-rw-r--r--test/prism/snapshots/seattlerb/read_escape_unicode_curlies.txt11
-rw-r--r--test/prism/snapshots/seattlerb/read_escape_unicode_h4.txt11
-rw-r--r--test/prism/snapshots/seattlerb/regexp.txt35
-rw-r--r--test/prism/snapshots/seattlerb/regexp_esc_C_slash.txt11
-rw-r--r--test/prism/snapshots/seattlerb/regexp_esc_u.txt11
-rw-r--r--test/prism/snapshots/seattlerb/regexp_escape_extended.txt11
-rw-r--r--test/prism/snapshots/seattlerb/regexp_unicode_curlies.txt17
-rw-r--r--test/prism/snapshots/seattlerb/required_kwarg_no_value.txt34
-rw-r--r--test/prism/snapshots/seattlerb/rescue_do_end_ensure_result.txt58
-rw-r--r--test/prism/snapshots/seattlerb/rescue_do_end_no_raise.txt75
-rw-r--r--test/prism/snapshots/seattlerb/rescue_do_end_raised.txt52
-rw-r--r--test/prism/snapshots/seattlerb/rescue_do_end_rescued.txt79
-rw-r--r--test/prism/snapshots/seattlerb/rescue_in_block.txt47
-rw-r--r--test/prism/snapshots/seattlerb/rescue_parens.txt48
-rw-r--r--test/prism/snapshots/seattlerb/return_call_assocs.txt218
-rw-r--r--test/prism/snapshots/seattlerb/rhs_asgn.txt15
-rw-r--r--test/prism/snapshots/seattlerb/ruby21_numbers.txt25
-rw-r--r--test/prism/snapshots/seattlerb/safe_attrasgn.txt31
-rw-r--r--test/prism/snapshots/seattlerb/safe_attrasgn_constant.txt31
-rw-r--r--test/prism/snapshots/seattlerb/safe_call.txt25
-rw-r--r--test/prism/snapshots/seattlerb/safe_call_after_newline.txt25
-rw-r--r--test/prism/snapshots/seattlerb/safe_call_dot_parens.txt25
-rw-r--r--test/prism/snapshots/seattlerb/safe_call_newline.txt25
-rw-r--r--test/prism/snapshots/seattlerb/safe_call_operator.txt31
-rw-r--r--test/prism/snapshots/seattlerb/safe_call_rhs_newline.txt31
-rw-r--r--test/prism/snapshots/seattlerb/safe_calls.txt41
-rw-r--r--test/prism/snapshots/seattlerb/safe_op_asgn.txt41
-rw-r--r--test/prism/snapshots/seattlerb/safe_op_asgn2.txt34
-rw-r--r--test/prism/snapshots/seattlerb/slashy_newlines_within_string.txt57
-rw-r--r--test/prism/snapshots/seattlerb/stabby_arg_no_paren.txt28
-rw-r--r--test/prism/snapshots/seattlerb/stabby_arg_opt_splat_arg_block_omfg.txt50
-rw-r--r--test/prism/snapshots/seattlerb/stabby_block_iter_call.txt58
-rw-r--r--test/prism/snapshots/seattlerb/stabby_block_iter_call_no_target_with_arg.txt54
-rw-r--r--test/prism/snapshots/seattlerb/stabby_block_kw.txt33
-rw-r--r--test/prism/snapshots/seattlerb/stabby_block_kw__required.txt29
-rw-r--r--test/prism/snapshots/seattlerb/stabby_proc_scope.txt31
-rw-r--r--test/prism/snapshots/seattlerb/str_backslashes.txt24
-rw-r--r--test/prism/snapshots/seattlerb/str_double_double_escaped_newline.txt34
-rw-r--r--test/prism/snapshots/seattlerb/str_double_escaped_newline.txt34
-rw-r--r--test/prism/snapshots/seattlerb/str_double_newline.txt34
-rw-r--r--test/prism/snapshots/seattlerb/str_evstr.txt32
-rw-r--r--test/prism/snapshots/seattlerb/str_evstr_escape.txt38
-rw-r--r--test/prism/snapshots/seattlerb/str_heredoc_interp.txt32
-rw-r--r--test/prism/snapshots/seattlerb/str_interp_ternary_or_label.txt105
-rw-r--r--test/prism/snapshots/seattlerb/str_lit_concat_bad_encodings.txt22
-rw-r--r--test/prism/snapshots/seattlerb/str_newline_hash_line_number.txt14
-rw-r--r--test/prism/snapshots/seattlerb/str_pct_Q_nested.txt38
-rw-r--r--test/prism/snapshots/seattlerb/str_pct_nested_nested.txt42
-rw-r--r--test/prism/snapshots/seattlerb/str_pct_q.txt11
-rw-r--r--test/prism/snapshots/seattlerb/str_single_double_escaped_newline.txt34
-rw-r--r--test/prism/snapshots/seattlerb/str_single_escaped_newline.txt34
-rw-r--r--test/prism/snapshots/seattlerb/str_single_newline.txt34
-rw-r--r--test/prism/snapshots/seattlerb/str_str.txt28
-rw-r--r--test/prism/snapshots/seattlerb/str_str_str.txt34
-rw-r--r--test/prism/snapshots/seattlerb/super_arg.txt17
-rw-r--r--test/prism/snapshots/seattlerb/symbol_empty.txt11
-rw-r--r--test/prism/snapshots/seattlerb/symbol_list.txt50
-rw-r--r--test/prism/snapshots/seattlerb/symbols.txt28
-rw-r--r--test/prism/snapshots/seattlerb/symbols_empty.txt10
-rw-r--r--test/prism/snapshots/seattlerb/symbols_empty_space.txt10
-rw-r--r--test/prism/snapshots/seattlerb/symbols_interp.txt28
-rw-r--r--test/prism/snapshots/seattlerb/thingy.txt57
-rw-r--r--test/prism/snapshots/seattlerb/uminus_float.txt7
-rw-r--r--test/prism/snapshots/seattlerb/unary_minus.txt25
-rw-r--r--test/prism/snapshots/seattlerb/unary_plus.txt25
-rw-r--r--test/prism/snapshots/seattlerb/unary_plus_on_literal.txt21
-rw-r--r--test/prism/snapshots/seattlerb/unary_tilde.txt25
-rw-r--r--test/prism/snapshots/seattlerb/utf8_bom.txt21
-rw-r--r--test/prism/snapshots/seattlerb/when_splat.txt39
-rw-r--r--test/prism/snapshots/seattlerb/words_interp.txt30
-rw-r--r--test/prism/snapshots/seattlerb/yield_arg.txt16
-rw-r--r--test/prism/snapshots/seattlerb/yield_call_assocs.txt224
-rw-r--r--test/prism/snapshots/seattlerb/yield_empty_parens.txt10
-rw-r--r--test/prism/snapshots/single_method_call_with_bang.txt15
-rw-r--r--test/prism/snapshots/single_quote_heredocs.txt11
-rw-r--r--test/prism/snapshots/spanning_heredoc.txt413
-rw-r--r--test/prism/snapshots/spanning_heredoc_newlines.txt155
-rw-r--r--test/prism/snapshots/strings.txt534
-rw-r--r--test/prism/snapshots/super.txt132
-rw-r--r--test/prism/snapshots/symbols.txt463
-rw-r--r--test/prism/snapshots/ternary_operator.txt295
-rw-r--r--test/prism/snapshots/tilde_heredocs.txt405
-rw-r--r--test/prism/snapshots/undef.txt117
-rw-r--r--test/prism/snapshots/unescaping.txt34
-rw-r--r--test/prism/snapshots/unless.txt173
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/alias.txt29
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/assignment.txt1076
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/block.txt1402
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/case.txt446
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/class.txt226
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/def.txt1204
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/defined.txt55
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/defs.txt358
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/dstr.txt353
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/empty.txt5
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/empty_begin.txt9
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/flipflop.txt237
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/for.txt171
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/hookexe.txt49
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/if.txt288
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/kwbegin.txt491
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/lambda.txt151
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/literal.txt1196
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/module.txt104
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/opasgn.txt509
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/pattern.txt446
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/pragma.txt20
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/range.txt55
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/rescue.txt103
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/send.txt2190
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/since/27.txt49
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/since/30.txt88
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/since/31.txt90
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/since/32.txt156
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/singletons.txt9
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/super.txt277
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/unary.txt248
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/undef.txt29
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/variables.txt49
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/while.txt704
-rw-r--r--test/prism/snapshots/unparser/corpus/literal/yield.txt56
-rw-r--r--test/prism/snapshots/unparser/corpus/semantic/and.txt235
-rw-r--r--test/prism/snapshots/unparser/corpus/semantic/block.txt191
-rw-r--r--test/prism/snapshots/unparser/corpus/semantic/def.txt90
-rw-r--r--test/prism/snapshots/unparser/corpus/semantic/dstr.txt598
-rw-r--r--test/prism/snapshots/unparser/corpus/semantic/kwbegin.txt259
-rw-r--r--test/prism/snapshots/unparser/corpus/semantic/literal.txt102
-rw-r--r--test/prism/snapshots/unparser/corpus/semantic/opasgn.txt69
-rw-r--r--test/prism/snapshots/unparser/corpus/semantic/send.txt163
-rw-r--r--test/prism/snapshots/unparser/corpus/semantic/undef.txt29
-rw-r--r--test/prism/snapshots/unparser/corpus/semantic/while.txt277
-rw-r--r--test/prism/snapshots/until.txt180
-rw-r--r--test/prism/snapshots/variables.txt408
-rw-r--r--test/prism/snapshots/while.txt470
-rw-r--r--test/prism/snapshots/whitequark/__ENCODING__.txt6
-rw-r--r--test/prism/snapshots/whitequark/__ENCODING___legacy_.txt6
-rw-r--r--test/prism/snapshots/whitequark/alias.txt21
-rw-r--r--test/prism/snapshots/whitequark/alias_gvar.txt21
-rw-r--r--test/prism/snapshots/whitequark/ambiuous_quoted_label_in_ternary_operator.txt60
-rw-r--r--test/prism/snapshots/whitequark/and.txt53
-rw-r--r--test/prism/snapshots/whitequark/and_asgn.txt59
-rw-r--r--test/prism/snapshots/whitequark/and_or_masgn.txt93
-rw-r--r--test/prism/snapshots/whitequark/anonymous_blockarg.txt46
-rw-r--r--test/prism/snapshots/whitequark/arg.txt56
-rw-r--r--test/prism/snapshots/whitequark/arg_duplicate_ignored.txt59
-rw-r--r--test/prism/snapshots/whitequark/arg_label.txt115
-rw-r--r--test/prism/snapshots/whitequark/arg_scope.txt34
-rw-r--r--test/prism/snapshots/whitequark/args.txt1075
-rw-r--r--test/prism/snapshots/whitequark/args_args_assocs.txt96
-rw-r--r--test/prism/snapshots/whitequark/args_args_assocs_comma.txt54
-rw-r--r--test/prism/snapshots/whitequark/args_args_comma.txt38
-rw-r--r--test/prism/snapshots/whitequark/args_args_star.txt90
-rw-r--r--test/prism/snapshots/whitequark/args_assocs.txt195
-rw-r--r--test/prism/snapshots/whitequark/args_assocs_comma.txt44
-rw-r--r--test/prism/snapshots/whitequark/args_assocs_legacy.txt195
-rw-r--r--test/prism/snapshots/whitequark/args_block_pass.txt28
-rw-r--r--test/prism/snapshots/whitequark/args_cmd.txt41
-rw-r--r--test/prism/snapshots/whitequark/args_star.txt70
-rw-r--r--test/prism/snapshots/whitequark/array_assocs.txt44
-rw-r--r--test/prism/snapshots/whitequark/array_plain.txt16
-rw-r--r--test/prism/snapshots/whitequark/array_splat.txt68
-rw-r--r--test/prism/snapshots/whitequark/array_symbols.txt22
-rw-r--r--test/prism/snapshots/whitequark/array_symbols_empty.txt15
-rw-r--r--test/prism/snapshots/whitequark/array_symbols_interp.txt67
-rw-r--r--test/prism/snapshots/whitequark/array_words.txt22
-rw-r--r--test/prism/snapshots/whitequark/array_words_empty.txt15
-rw-r--r--test/prism/snapshots/whitequark/array_words_interp.txt80
-rw-r--r--test/prism/snapshots/whitequark/asgn_cmd.txt55
-rw-r--r--test/prism/snapshots/whitequark/asgn_mrhs.txt87
-rw-r--r--test/prism/snapshots/whitequark/back_ref.txt7
-rw-r--r--test/prism/snapshots/whitequark/bang.txt25
-rw-r--r--test/prism/snapshots/whitequark/bang_cmd.txt38
-rw-r--r--test/prism/snapshots/whitequark/begin_cmdarg.txt51
-rw-r--r--test/prism/snapshots/whitequark/beginless_erange_after_newline.txt23
-rw-r--r--test/prism/snapshots/whitequark/beginless_irange_after_newline.txt23
-rw-r--r--test/prism/snapshots/whitequark/beginless_range.txt21
-rw-r--r--test/prism/snapshots/whitequark/blockarg.txt31
-rw-r--r--test/prism/snapshots/whitequark/blockargs.txt1339
-rw-r--r--test/prism/snapshots/whitequark/bug_435.txt39
-rw-r--r--test/prism/snapshots/whitequark/bug_447.txt56
-rw-r--r--test/prism/snapshots/whitequark/bug_452.txt63
-rw-r--r--test/prism/snapshots/whitequark/bug_466.txt70
-rw-r--r--test/prism/snapshots/whitequark/bug_473.txt34
-rw-r--r--test/prism/snapshots/whitequark/bug_480.txt37
-rw-r--r--test/prism/snapshots/whitequark/bug_481.txt50
-rw-r--r--test/prism/snapshots/whitequark/bug_ascii_8bit_in_literal.txt11
-rw-r--r--test/prism/snapshots/whitequark/bug_cmd_string_lookahead.txt30
-rw-r--r--test/prism/snapshots/whitequark/bug_cmdarg.txt106
-rw-r--r--test/prism/snapshots/whitequark/bug_def_no_paren_eql_begin.txt18
-rw-r--r--test/prism/snapshots/whitequark/bug_do_block_in_call_args.txt50
-rw-r--r--test/prism/snapshots/whitequark/bug_do_block_in_cmdarg.txt40
-rw-r--r--test/prism/snapshots/whitequark/bug_do_block_in_hash_brace.txt383
-rw-r--r--test/prism/snapshots/whitequark/bug_heredoc_do.txt30
-rw-r--r--test/prism/snapshots/whitequark/bug_interp_single.txt38
-rw-r--r--test/prism/snapshots/whitequark/bug_lambda_leakage.txt38
-rw-r--r--test/prism/snapshots/whitequark/bug_regex_verification.txt11
-rw-r--r--test/prism/snapshots/whitequark/bug_rescue_empty_else.txt25
-rw-r--r--test/prism/snapshots/whitequark/bug_while_not_parens_do.txt28
-rw-r--r--test/prism/snapshots/whitequark/case_cond.txt34
-rw-r--r--test/prism/snapshots/whitequark/case_cond_else.txt46
-rw-r--r--test/prism/snapshots/whitequark/case_expr.txt44
-rw-r--r--test/prism/snapshots/whitequark/case_expr_else.txt60
-rw-r--r--test/prism/snapshots/whitequark/casgn_scoped.txt19
-rw-r--r--test/prism/snapshots/whitequark/casgn_toplevel.txt17
-rw-r--r--test/prism/snapshots/whitequark/casgn_unscoped.txt13
-rw-r--r--test/prism/snapshots/whitequark/character.txt11
-rw-r--r--test/prism/snapshots/whitequark/class.txt27
-rw-r--r--test/prism/snapshots/whitequark/class_super.txt18
-rw-r--r--test/prism/snapshots/whitequark/class_super_label.txt35
-rw-r--r--test/prism/snapshots/whitequark/comments_before_leading_dot__27.txt85
-rw-r--r--test/prism/snapshots/whitequark/complex.txt26
-rw-r--r--test/prism/snapshots/whitequark/cond_begin.txt40
-rw-r--r--test/prism/snapshots/whitequark/cond_begin_masgn.txt52
-rw-r--r--test/prism/snapshots/whitequark/cond_eflipflop.txt78
-rw-r--r--test/prism/snapshots/whitequark/cond_eflipflop_with_beginless_range.txt27
-rw-r--r--test/prism/snapshots/whitequark/cond_eflipflop_with_endless_range.txt27
-rw-r--r--test/prism/snapshots/whitequark/cond_iflipflop.txt78
-rw-r--r--test/prism/snapshots/whitequark/cond_iflipflop_with_beginless_range.txt27
-rw-r--r--test/prism/snapshots/whitequark/cond_iflipflop_with_endless_range.txt27
-rw-r--r--test/prism/snapshots/whitequark/cond_match_current_line.txt34
-rw-r--r--test/prism/snapshots/whitequark/const_op_asgn.txt97
-rw-r--r--test/prism/snapshots/whitequark/const_scoped.txt12
-rw-r--r--test/prism/snapshots/whitequark/const_toplevel.txt10
-rw-r--r--test/prism/snapshots/whitequark/const_unscoped.txt7
-rw-r--r--test/prism/snapshots/whitequark/cpath.txt31
-rw-r--r--test/prism/snapshots/whitequark/cvar.txt7
-rw-r--r--test/prism/snapshots/whitequark/cvasgn.txt13
-rw-r--r--test/prism/snapshots/whitequark/dedenting_heredoc.txt496
-rw-r--r--test/prism/snapshots/whitequark/dedenting_interpolating_heredoc_fake_line_continuation.txt22
-rw-r--r--test/prism/snapshots/whitequark/dedenting_non_interpolating_heredoc_line_continuation.txt22
-rw-r--r--test/prism/snapshots/whitequark/def.txt83
-rw-r--r--test/prism/snapshots/whitequark/defined.txt42
-rw-r--r--test/prism/snapshots/whitequark/defs.txt90
-rw-r--r--test/prism/snapshots/whitequark/empty_stmt.txt5
-rw-r--r--test/prism/snapshots/whitequark/endless_comparison_method.txt221
-rw-r--r--test/prism/snapshots/whitequark/endless_method.txt151
-rw-r--r--test/prism/snapshots/whitequark/endless_method_command_syntax.txt394
-rw-r--r--test/prism/snapshots/whitequark/endless_method_forwarded_args_legacy.txt43
-rw-r--r--test/prism/snapshots/whitequark/endless_method_with_rescue_mod.txt56
-rw-r--r--test/prism/snapshots/whitequark/endless_method_without_args.txt89
-rw-r--r--test/prism/snapshots/whitequark/ensure.txt40
-rw-r--r--test/prism/snapshots/whitequark/ensure_empty.txt16
-rw-r--r--test/prism/snapshots/whitequark/false.txt6
-rw-r--r--test/prism/snapshots/whitequark/float.txt9
-rw-r--r--test/prism/snapshots/whitequark/for.txt83
-rw-r--r--test/prism/snapshots/whitequark/for_mlhs.txt56
-rw-r--r--test/prism/snapshots/whitequark/forward_arg.txt43
-rw-r--r--test/prism/snapshots/whitequark/forward_arg_with_open_args.txt404
-rw-r--r--test/prism/snapshots/whitequark/forward_args_legacy.txt99
-rw-r--r--test/prism/snapshots/whitequark/forwarded_argument_with_kwrestarg.txt58
-rw-r--r--test/prism/snapshots/whitequark/forwarded_argument_with_restarg.txt55
-rw-r--r--test/prism/snapshots/whitequark/forwarded_kwrestarg.txt52
-rw-r--r--test/prism/snapshots/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt63
-rw-r--r--test/prism/snapshots/whitequark/forwarded_restarg.txt49
-rw-r--r--test/prism/snapshots/whitequark/gvar.txt7
-rw-r--r--test/prism/snapshots/whitequark/gvasgn.txt13
-rw-r--r--test/prism/snapshots/whitequark/hash_empty.txt9
-rw-r--r--test/prism/snapshots/whitequark/hash_hashrocket.txt49
-rw-r--r--test/prism/snapshots/whitequark/hash_kwsplat.txt35
-rw-r--r--test/prism/snapshots/whitequark/hash_label.txt22
-rw-r--r--test/prism/snapshots/whitequark/hash_label_end.txt100
-rw-r--r--test/prism/snapshots/whitequark/hash_pair_value_omission.txt97
-rw-r--r--test/prism/snapshots/whitequark/heredoc.txt23
-rw-r--r--test/prism/snapshots/whitequark/if.txt63
-rw-r--r--test/prism/snapshots/whitequark/if_else.txt95
-rw-r--r--test/prism/snapshots/whitequark/if_elsif.txt65
-rw-r--r--test/prism/snapshots/whitequark/if_masgn__24.txt42
-rw-r--r--test/prism/snapshots/whitequark/if_mod.txt34
-rw-r--r--test/prism/snapshots/whitequark/if_nl_then.txt34
-rw-r--r--test/prism/snapshots/whitequark/int.txt14
-rw-r--r--test/prism/snapshots/whitequark/int___LINE__.txt6
-rw-r--r--test/prism/snapshots/whitequark/interp_digit_var.txt273
-rw-r--r--test/prism/snapshots/whitequark/ivar.txt7
-rw-r--r--test/prism/snapshots/whitequark/ivasgn.txt13
-rw-r--r--test/prism/snapshots/whitequark/keyword_argument_omission.txt65
-rw-r--r--test/prism/snapshots/whitequark/kwarg.txt30
-rw-r--r--test/prism/snapshots/whitequark/kwbegin_compstmt.txt34
-rw-r--r--test/prism/snapshots/whitequark/kwnilarg.txt84
-rw-r--r--test/prism/snapshots/whitequark/kwoptarg.txt34
-rw-r--r--test/prism/snapshots/whitequark/kwoptarg_with_kwrestarg_and_forwarded_args.txt58
-rw-r--r--test/prism/snapshots/whitequark/kwrestarg_named.txt31
-rw-r--r--test/prism/snapshots/whitequark/kwrestarg_unnamed.txt31
-rw-r--r--test/prism/snapshots/whitequark/lbrace_arg_after_command_args.txt54
-rw-r--r--test/prism/snapshots/whitequark/lparenarg_after_lvar__since_25.txt67
-rw-r--r--test/prism/snapshots/whitequark/lvar.txt15
-rw-r--r--test/prism/snapshots/whitequark/lvar_injecting_match.txt39
-rw-r--r--test/prism/snapshots/whitequark/lvasgn.txt17
-rw-r--r--test/prism/snapshots/whitequark/masgn.txt83
-rw-r--r--test/prism/snapshots/whitequark/masgn_attr.txt82
-rw-r--r--test/prism/snapshots/whitequark/masgn_cmd.txt35
-rw-r--r--test/prism/snapshots/whitequark/masgn_const.txt44
-rw-r--r--test/prism/snapshots/whitequark/masgn_nested.txt66
-rw-r--r--test/prism/snapshots/whitequark/masgn_splat.txt284
-rw-r--r--test/prism/snapshots/whitequark/module.txt14
-rw-r--r--test/prism/snapshots/whitequark/multiple_pattern_matches.txt173
-rw-r--r--test/prism/snapshots/whitequark/newline_in_hash_argument.txt163
-rw-r--r--test/prism/snapshots/whitequark/nil.txt6
-rw-r--r--test/prism/snapshots/whitequark/nil_expression.txt16
-rw-r--r--test/prism/snapshots/whitequark/non_lvar_injecting_match.txt44
-rw-r--r--test/prism/snapshots/whitequark/not.txt55
-rw-r--r--test/prism/snapshots/whitequark/not_cmd.txt38
-rw-r--r--test/prism/snapshots/whitequark/not_masgn__24.txt45
-rw-r--r--test/prism/snapshots/whitequark/nth_ref.txt7
-rw-r--r--test/prism/snapshots/whitequark/numbered_args_after_27.txt143
-rw-r--r--test/prism/snapshots/whitequark/numparam_outside_block.txt114
-rw-r--r--test/prism/snapshots/whitequark/numparam_ruby_bug_19025.txt49
-rw-r--r--test/prism/snapshots/whitequark/op_asgn.txt74
-rw-r--r--test/prism/snapshots/whitequark/op_asgn_cmd.txt177
-rw-r--r--test/prism/snapshots/whitequark/op_asgn_index.txt38
-rw-r--r--test/prism/snapshots/whitequark/op_asgn_index_cmd.txt58
-rw-r--r--test/prism/snapshots/whitequark/optarg.txt74
-rw-r--r--test/prism/snapshots/whitequark/or.txt53
-rw-r--r--test/prism/snapshots/whitequark/or_asgn.txt59
-rw-r--r--test/prism/snapshots/whitequark/parser_bug_272.txt42
-rw-r--r--test/prism/snapshots/whitequark/parser_bug_490.txt106
-rw-r--r--test/prism/snapshots/whitequark/parser_bug_507.txt36
-rw-r--r--test/prism/snapshots/whitequark/parser_bug_518.txt18
-rw-r--r--test/prism/snapshots/whitequark/parser_bug_525.txt65
-rw-r--r--test/prism/snapshots/whitequark/parser_bug_604.txt57
-rw-r--r--test/prism/snapshots/whitequark/parser_bug_640.txt22
-rw-r--r--test/prism/snapshots/whitequark/parser_bug_645.txt35
-rw-r--r--test/prism/snapshots/whitequark/parser_bug_830.txt11
-rw-r--r--test/prism/snapshots/whitequark/parser_bug_989.txt11
-rw-r--r--test/prism/snapshots/whitequark/parser_drops_truncated_parts_of_squiggly_heredoc.txt20
-rw-r--r--test/prism/snapshots/whitequark/parser_slash_slash_n_escaping_in_literals.txt139
-rw-r--r--test/prism/snapshots/whitequark/pattern_matching__FILE__LINE_literals.txt54
-rw-r--r--test/prism/snapshots/whitequark/pattern_matching_blank_else.txt31
-rw-r--r--test/prism/snapshots/whitequark/pattern_matching_else.txt36
-rw-r--r--test/prism/snapshots/whitequark/pattern_matching_single_line.txt45
-rw-r--r--test/prism/snapshots/whitequark/pattern_matching_single_line_allowed_omission_of_parentheses.txt249
-rw-r--r--test/prism/snapshots/whitequark/postexe.txt15
-rw-r--r--test/prism/snapshots/whitequark/preexe.txt15
-rw-r--r--test/prism/snapshots/whitequark/procarg0.txt78
-rw-r--r--test/prism/snapshots/whitequark/range_exclusive.txt16
-rw-r--r--test/prism/snapshots/whitequark/range_inclusive.txt16
-rw-r--r--test/prism/snapshots/whitequark/rational.txt13
-rw-r--r--test/prism/snapshots/whitequark/regex_interp.txt38
-rw-r--r--test/prism/snapshots/whitequark/regex_plain.txt11
-rw-r--r--test/prism/snapshots/whitequark/resbody_list.txt45
-rw-r--r--test/prism/snapshots/whitequark/resbody_list_mrhs.txt55
-rw-r--r--test/prism/snapshots/whitequark/resbody_list_var.txt56
-rw-r--r--test/prism/snapshots/whitequark/resbody_var.txt86
-rw-r--r--test/prism/snapshots/whitequark/rescue.txt43
-rw-r--r--test/prism/snapshots/whitequark/rescue_else.txt59
-rw-r--r--test/prism/snapshots/whitequark/rescue_else_ensure.txt75
-rw-r--r--test/prism/snapshots/whitequark/rescue_ensure.txt59
-rw-r--r--test/prism/snapshots/whitequark/rescue_in_lambda_block.txt26
-rw-r--r--test/prism/snapshots/whitequark/rescue_mod.txt29
-rw-r--r--test/prism/snapshots/whitequark/rescue_mod_asgn.txt35
-rw-r--r--test/prism/snapshots/whitequark/rescue_mod_masgn.txt44
-rw-r--r--test/prism/snapshots/whitequark/rescue_mod_op_assign.txt36
-rw-r--r--test/prism/snapshots/whitequark/rescue_without_begin_end.txt59
-rw-r--r--test/prism/snapshots/whitequark/restarg_named.txt31
-rw-r--r--test/prism/snapshots/whitequark/restarg_unnamed.txt31
-rw-r--r--test/prism/snapshots/whitequark/return.txt60
-rw-r--r--test/prism/snapshots/whitequark/return_block.txt41
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_10279.txt32
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_10653.txt173
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_11107.txt48
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_11380.txt55
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_11873.txt767
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_11873_a.txt1231
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_11873_b.txt98
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_11989.txt24
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_11990.txt35
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_12073.txt95
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_12402.txt565
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_12669.txt133
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_12686.txt39
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_13547.txt31
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_14690.txt59
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_15789.txt120
-rw-r--r--test/prism/snapshots/whitequark/ruby_bug_9669.txt59
-rw-r--r--test/prism/snapshots/whitequark/sclass.txt25
-rw-r--r--test/prism/snapshots/whitequark/self.txt6
-rw-r--r--test/prism/snapshots/whitequark/send_attr_asgn.txt105
-rw-r--r--test/prism/snapshots/whitequark/send_attr_asgn_conditional.txt31
-rw-r--r--test/prism/snapshots/whitequark/send_binary_op.txt551
-rw-r--r--test/prism/snapshots/whitequark/send_block_chain_cmd.txt325
-rw-r--r--test/prism/snapshots/whitequark/send_block_conditional.txt31
-rw-r--r--test/prism/snapshots/whitequark/send_call.txt57
-rw-r--r--test/prism/snapshots/whitequark/send_conditional.txt25
-rw-r--r--test/prism/snapshots/whitequark/send_index.txt34
-rw-r--r--test/prism/snapshots/whitequark/send_index_asgn.txt37
-rw-r--r--test/prism/snapshots/whitequark/send_index_asgn_legacy.txt37
-rw-r--r--test/prism/snapshots/whitequark/send_index_cmd.txt51
-rw-r--r--test/prism/snapshots/whitequark/send_index_legacy.txt34
-rw-r--r--test/prism/snapshots/whitequark/send_lambda.txt44
-rw-r--r--test/prism/snapshots/whitequark/send_lambda_args.txt51
-rw-r--r--test/prism/snapshots/whitequark/send_lambda_args_noparen.txt57
-rw-r--r--test/prism/snapshots/whitequark/send_lambda_args_shadow.txt34
-rw-r--r--test/prism/snapshots/whitequark/send_lambda_legacy.txt12
-rw-r--r--test/prism/snapshots/whitequark/send_op_asgn_conditional.txt27
-rw-r--r--test/prism/snapshots/whitequark/send_plain.txt65
-rw-r--r--test/prism/snapshots/whitequark/send_plain_cmd.txt104
-rw-r--r--test/prism/snapshots/whitequark/send_self.txt41
-rw-r--r--test/prism/snapshots/whitequark/send_self_block.txt75
-rw-r--r--test/prism/snapshots/whitequark/send_unary_op.txt65
-rw-r--r--test/prism/snapshots/whitequark/slash_newline_in_heredocs.txt34
-rw-r--r--test/prism/snapshots/whitequark/space_args_arg.txt27
-rw-r--r--test/prism/snapshots/whitequark/space_args_arg_block.txt109
-rw-r--r--test/prism/snapshots/whitequark/space_args_arg_call.txt37
-rw-r--r--test/prism/snapshots/whitequark/space_args_arg_newline.txt27
-rw-r--r--test/prism/snapshots/whitequark/space_args_block.txt28
-rw-r--r--test/prism/snapshots/whitequark/space_args_cmd.txt47
-rw-r--r--test/prism/snapshots/whitequark/string___FILE__.txt8
-rw-r--r--test/prism/snapshots/whitequark/string_concat.txt32
-rw-r--r--test/prism/snapshots/whitequark/string_dvar.txt37
-rw-r--r--test/prism/snapshots/whitequark/string_interp.txt38
-rw-r--r--test/prism/snapshots/whitequark/string_plain.txt17
-rw-r--r--test/prism/snapshots/whitequark/super.txt49
-rw-r--r--test/prism/snapshots/whitequark/super_block.txt48
-rw-r--r--test/prism/snapshots/whitequark/symbol_interp.txt37
-rw-r--r--test/prism/snapshots/whitequark/symbol_plain.txt17
-rw-r--r--test/prism/snapshots/whitequark/ternary.txt36
-rw-r--r--test/prism/snapshots/whitequark/ternary_ambiguous_symbol.txt50
-rw-r--r--test/prism/snapshots/whitequark/trailing_forward_arg.txt55
-rw-r--r--test/prism/snapshots/whitequark/true.txt6
-rw-r--r--test/prism/snapshots/whitequark/unary_num_pow_precedence.txt80
-rw-r--r--test/prism/snapshots/whitequark/undef.txt39
-rw-r--r--test/prism/snapshots/whitequark/unless.txt63
-rw-r--r--test/prism/snapshots/whitequark/unless_else.txt95
-rw-r--r--test/prism/snapshots/whitequark/unless_mod.txt34
-rw-r--r--test/prism/snapshots/whitequark/until.txt61
-rw-r--r--test/prism/snapshots/whitequark/until_mod.txt33
-rw-r--r--test/prism/snapshots/whitequark/until_post.txt42
-rw-r--r--test/prism/snapshots/whitequark/var_and_asgn.txt14
-rw-r--r--test/prism/snapshots/whitequark/var_op_asgn.txt57
-rw-r--r--test/prism/snapshots/whitequark/var_op_asgn_cmd.txt28
-rw-r--r--test/prism/snapshots/whitequark/var_or_asgn.txt14
-rw-r--r--test/prism/snapshots/whitequark/when_multi.txt50
-rw-r--r--test/prism/snapshots/whitequark/when_splat.txt72
-rw-r--r--test/prism/snapshots/whitequark/when_then.txt44
-rw-r--r--test/prism/snapshots/whitequark/while.txt61
-rw-r--r--test/prism/snapshots/whitequark/while_mod.txt33
-rw-r--r--test/prism/snapshots/whitequark/while_post.txt42
-rw-r--r--test/prism/snapshots/whitequark/xstring_interp.txt37
-rw-r--r--test/prism/snapshots/whitequark/xstring_plain.txt11
-rw-r--r--test/prism/snapshots/whitequark/yield.txt51
-rw-r--r--test/prism/snapshots/whitequark/zsuper.txt7
-rw-r--r--test/prism/snapshots/xstring.txt67
-rw-r--r--test/prism/snapshots/xstring_with_backslash.txt11
-rw-r--r--test/prism/snapshots/yield.txt103
-rw-r--r--test/prism/snapshots_test.rb73
-rw-r--r--test/prism/snippets_test.rb13
-rw-r--r--test/prism/test_helper.rb93
-rw-r--r--test/prism/unescape_test.rb12
-rw-r--r--test/prism/version_test.rb2
-rw-r--r--test/psych/helper.rb1
-rw-r--r--test/psych/test_data.rb94
-rw-r--r--test/psych/test_date_time.rb16
-rw-r--r--test/psych/test_exception.rb13
-rw-r--r--test/psych/test_object_references.rb5
-rw-r--r--test/psych/test_psych.rb11
-rw-r--r--test/psych/test_psych_set.rb57
-rw-r--r--test/psych/test_ractor.rb6
-rw-r--r--test/psych/test_safe_load.rb32
-rw-r--r--test/psych/test_scalar_scanner.rb19
-rw-r--r--test/psych/test_serialize_subclasses.rb18
-rw-r--r--test/psych/test_set.rb61
-rw-r--r--test/psych/test_stream.rb8
-rw-r--r--test/psych/test_string.rb10
-rw-r--r--test/psych/test_stringio.rb14
-rw-r--r--test/psych/test_yaml.rb928
-rw-r--r--test/psych/test_yaml_special_cases.rb12
-rw-r--r--test/psych/test_yamlstore.rb16
-rw-r--r--test/psych/visitors/test_to_ruby.rb6
-rw-r--r--test/psych/visitors/test_yaml_tree.rb21
-rw-r--r--test/rdoc/MarkdownTest_1.0.3/Amps and angle encoding.text21
-rw-r--r--test/rdoc/MarkdownTest_1.0.3/Auto links.text13
-rw-r--r--test/rdoc/MarkdownTest_1.0.3/Backslash escapes.text120
-rw-r--r--test/rdoc/MarkdownTest_1.0.3/Blockquotes with code blocks.text11
-rw-r--r--test/rdoc/MarkdownTest_1.0.3/Code Blocks.text14
-rw-r--r--test/rdoc/MarkdownTest_1.0.3/Code Spans.text6
-rw-r--r--test/rdoc/MarkdownTest_1.0.3/Hard-wrapped paragraphs with list-like lines.text8
-rw-r--r--test/rdoc/MarkdownTest_1.0.3/Horizontal rules.text67
-rw-r--r--test/rdoc/MarkdownTest_1.0.3/Inline HTML (Advanced).text15
-rw-r--r--test/rdoc/MarkdownTest_1.0.3/Inline HTML (Simple).text69
-rw-r--r--test/rdoc/MarkdownTest_1.0.3/Inline HTML comments.text13
-rw-r--r--test/rdoc/MarkdownTest_1.0.3/Links, inline style.text12
-rw-r--r--test/rdoc/MarkdownTest_1.0.3/Links, reference style.text71
-rw-r--r--test/rdoc/MarkdownTest_1.0.3/Links, shortcut references.text20
-rw-r--r--test/rdoc/MarkdownTest_1.0.3/Literal quotes in titles.text7
-rw-r--r--test/rdoc/MarkdownTest_1.0.3/Markdown Documentation - Basics.text306
-rw-r--r--test/rdoc/MarkdownTest_1.0.3/Markdown Documentation - Syntax.text888
-rw-r--r--test/rdoc/MarkdownTest_1.0.3/Nested blockquotes.text5
-rw-r--r--test/rdoc/MarkdownTest_1.0.3/Ordered and unordered lists.text131
-rw-r--r--test/rdoc/MarkdownTest_1.0.3/Strong and em together.text7
-rw-r--r--test/rdoc/MarkdownTest_1.0.3/Tabs.text21
-rw-r--r--test/rdoc/MarkdownTest_1.0.3/Tidyness.text5
-rw-r--r--test/rdoc/README1
-rw-r--r--test/rdoc/binary.datbin1024 -> 0 bytes-rw-r--r--test/rdoc/helper.rb5
-rw-r--r--test/rdoc/hidden.zip.txt1
-rw-r--r--test/rdoc/support/formatter_test_case.rb764
-rw-r--r--test/rdoc/support/test_case.rb217
-rw-r--r--test/rdoc/support/text_formatter_test_case.rb114
-rw-r--r--test/rdoc/test.ja.largedoc3
-rw-r--r--test/rdoc/test.ja.rdoc10
-rw-r--r--test/rdoc/test.ja.txt8
-rw-r--r--test/rdoc/test.txt1
-rw-r--r--test/rdoc/test_rdoc_alias.rb13
-rw-r--r--test/rdoc/test_rdoc_any_method.rb609
-rw-r--r--test/rdoc/test_rdoc_attr.rb190
-rw-r--r--test/rdoc/test_rdoc_class_module.rb1503
-rw-r--r--test/rdoc/test_rdoc_code_object.rb440
-rw-r--r--test/rdoc/test_rdoc_comment.rb506
-rw-r--r--test/rdoc/test_rdoc_constant.rb182
-rw-r--r--test/rdoc/test_rdoc_context.rb971
-rw-r--r--test/rdoc/test_rdoc_context_section.rb146
-rw-r--r--test/rdoc/test_rdoc_cross_reference.rb219
-rw-r--r--test/rdoc/test_rdoc_encoding.rb184
-rw-r--r--test/rdoc/test_rdoc_extend.rb94
-rw-r--r--test/rdoc/test_rdoc_generator_darkfish.rb353
-rw-r--r--test/rdoc/test_rdoc_generator_json_index.rb361
-rw-r--r--test/rdoc/test_rdoc_generator_markup.rb59
-rw-r--r--test/rdoc/test_rdoc_generator_pot.rb92
-rw-r--r--test/rdoc/test_rdoc_generator_pot_po.rb52
-rw-r--r--test/rdoc/test_rdoc_generator_pot_po_entry.rb140
-rw-r--r--test/rdoc/test_rdoc_generator_ri.rb76
-rw-r--r--test/rdoc/test_rdoc_i18n_locale.rb74
-rw-r--r--test/rdoc/test_rdoc_i18n_text.rb124
-rw-r--r--test/rdoc/test_rdoc_include.rb109
-rw-r--r--test/rdoc/test_rdoc_markdown.rb1109
-rw-r--r--test/rdoc/test_rdoc_markdown_test.rb1883
-rw-r--r--test/rdoc/test_rdoc_markup.rb95
-rw-r--r--test/rdoc/test_rdoc_markup_attribute_manager.rb395
-rw-r--r--test/rdoc/test_rdoc_markup_attributes.rb39
-rw-r--r--test/rdoc/test_rdoc_markup_document.rb207
-rw-r--r--test/rdoc/test_rdoc_markup_formatter.rb181
-rw-r--r--test/rdoc/test_rdoc_markup_hard_break.rb31
-rw-r--r--test/rdoc/test_rdoc_markup_heading.rb29
-rw-r--r--test/rdoc/test_rdoc_markup_include.rb19
-rw-r--r--test/rdoc/test_rdoc_markup_indented_paragraph.rb53
-rw-r--r--test/rdoc/test_rdoc_markup_paragraph.rb32
-rw-r--r--test/rdoc/test_rdoc_markup_parser.rb1684
-rw-r--r--test/rdoc/test_rdoc_markup_pre_process.rb467
-rw-r--r--test/rdoc/test_rdoc_markup_raw.rb22
-rw-r--r--test/rdoc/test_rdoc_markup_to_ansi.rb369
-rw-r--r--test/rdoc/test_rdoc_markup_to_bs.rb352
-rw-r--r--test/rdoc/test_rdoc_markup_to_html.rb991
-rw-r--r--test/rdoc/test_rdoc_markup_to_html_crossref.rb280
-rw-r--r--test/rdoc/test_rdoc_markup_to_html_snippet.rb709
-rw-r--r--test/rdoc/test_rdoc_markup_to_joined_paragraph.rb32
-rw-r--r--test/rdoc/test_rdoc_markup_to_label.rb112
-rw-r--r--test/rdoc/test_rdoc_markup_to_markdown.rb386
-rw-r--r--test/rdoc/test_rdoc_markup_to_rdoc.rb377
-rw-r--r--test/rdoc/test_rdoc_markup_to_table_of_contents.rb126
-rw-r--r--test/rdoc/test_rdoc_markup_to_tt_only.rb246
-rw-r--r--test/rdoc/test_rdoc_markup_verbatim.rb29
-rw-r--r--test/rdoc/test_rdoc_method_attr.rb193
-rw-r--r--test/rdoc/test_rdoc_normal_class.rb47
-rw-r--r--test/rdoc/test_rdoc_normal_module.rb42
-rw-r--r--test/rdoc/test_rdoc_options.rb931
-rw-r--r--test/rdoc/test_rdoc_parser.rb337
-rw-r--r--test/rdoc/test_rdoc_parser_c.rb2103
-rw-r--r--test/rdoc/test_rdoc_parser_changelog.rb484
-rw-r--r--test/rdoc/test_rdoc_parser_markdown.rb61
-rw-r--r--test/rdoc/test_rdoc_parser_rd.rb55
-rw-r--r--test/rdoc/test_rdoc_parser_ruby.rb4398
-rw-r--r--test/rdoc/test_rdoc_parser_simple.rb115
-rw-r--r--test/rdoc/test_rdoc_rd.rb30
-rw-r--r--test/rdoc/test_rdoc_rd_block_parser.rb557
-rw-r--r--test/rdoc/test_rdoc_rd_inline.rb63
-rw-r--r--test/rdoc/test_rdoc_rd_inline_parser.rb178
-rw-r--r--test/rdoc/test_rdoc_rdoc.rb583
-rw-r--r--test/rdoc/test_rdoc_require.rb25
-rw-r--r--test/rdoc/test_rdoc_ri_driver.rb1561
-rw-r--r--test/rdoc/test_rdoc_ri_paths.rb157
-rw-r--r--test/rdoc/test_rdoc_rubygems_hook.rb287
-rw-r--r--test/rdoc/test_rdoc_servlet.rb555
-rw-r--r--test/rdoc/test_rdoc_single_class.rb20
-rw-r--r--test/rdoc/test_rdoc_stats.rb722
-rw-r--r--test/rdoc/test_rdoc_store.rb1012
-rw-r--r--test/rdoc/test_rdoc_task.rb182
-rw-r--r--test/rdoc/test_rdoc_text.rb585
-rw-r--r--test/rdoc/test_rdoc_token_stream.rb109
-rw-r--r--test/rdoc/test_rdoc_tom_doc.rb579
-rw-r--r--test/rdoc/test_rdoc_top_level.rb290
-rw-r--r--test/rdoc/xref_data.rb163
-rw-r--r--test/rdoc/xref_test_case.rb93
-rw-r--r--test/reline/helper.rb174
-rw-r--r--test/reline/test_ansi_with_terminfo.rb112
-rw-r--r--test/reline/test_ansi_without_terminfo.rb77
-rw-r--r--test/reline/test_config.rb553
-rw-r--r--test/reline/test_face.rb257
-rw-r--r--test/reline/test_history.rb308
-rw-r--r--test/reline/test_key_actor_emacs.rb1612
-rw-r--r--test/reline/test_key_actor_vi.rb919
-rw-r--r--test/reline/test_key_stroke.rb105
-rw-r--r--test/reline/test_kill_ring.rb268
-rw-r--r--test/reline/test_line_editor.rb183
-rw-r--r--test/reline/test_macro.rb40
-rw-r--r--test/reline/test_reline.rb408
-rw-r--r--test/reline/test_reline_key.rb54
-rw-r--r--test/reline/test_string_processing.rb69
-rw-r--r--test/reline/test_terminfo.rb61
-rw-r--r--test/reline/test_unicode.rb92
-rw-r--r--test/reline/test_within_pipe.rb77
-rw-r--r--test/reline/windows/test_key_event_record.rb41
-rwxr-xr-xtest/reline/yamatanooroti/multiline_repl257
-rw-r--r--test/reline/yamatanooroti/termination_checker.rb26
-rw-r--r--test/reline/yamatanooroti/test_rendering.rb1840
-rw-r--r--test/resolv/test_dns.rb282
-rw-r--r--test/resolv/test_win32_config.rb26
-rw-r--r--test/ripper/assert_parse_files.rb1
-rw-r--r--test/ripper/test_lexer.rb223
-rw-r--r--test/ripper/test_parser_events.rb96
-rw-r--r--test/ripper/test_ripper.rb29
-rw-r--r--test/ripper/test_scanner_events.rb6
-rw-r--r--test/ruby/box/a.1_1_0.rb17
-rw-r--r--test/ruby/box/a.1_2_0.rb17
-rw-r--r--test/ruby/box/a.rb15
-rw-r--r--test/ruby/box/autoloading.rb8
-rw-r--r--test/ruby/box/blank.rb2
-rw-r--r--test/ruby/box/blank1.rb2
-rw-r--r--test/ruby/box/blank2.rb2
-rw-r--r--test/ruby/box/box.rb10
-rw-r--r--test/ruby/box/call_proc.rb5
-rw-r--r--test/ruby/box/call_toplevel.rb8
-rw-r--r--test/ruby/box/consts.rb148
-rw-r--r--test/ruby/box/define_toplevel.rb5
-rw-r--r--test/ruby/box/global_vars.rb37
-rw-r--r--test/ruby/box/instance_variables.rb21
-rw-r--r--test/ruby/box/line_splitter.rb9
-rw-r--r--test/ruby/box/load_path.rb26
-rw-r--r--test/ruby/box/open_class_with_include.rb31
-rw-r--r--test/ruby/box/proc_callee.rb14
-rw-r--r--test/ruby/box/proc_caller.rb5
-rw-r--r--test/ruby/box/procs.rb64
-rw-r--r--test/ruby/box/raise.rb3
-rw-r--r--test/ruby/box/returns_proc.rb12
-rw-r--r--test/ruby/box/singleton_methods.rb65
-rw-r--r--test/ruby/box/string_ext.rb13
-rw-r--r--test/ruby/box/string_ext_caller.rb5
-rw-r--r--test/ruby/box/string_ext_calling.rb1
-rw-r--r--test/ruby/box/string_ext_eval_caller.rb12
-rw-r--r--test/ruby/box/top_level.rb33
-rw-r--r--test/ruby/enc/test_case_comprehensive.rb61
-rw-r--r--test/ruby/enc/test_emoji_breaks.rb2
-rw-r--r--test/ruby/rjit/test_assembler.rb368
-rw-r--r--test/ruby/sentence.rb2
-rw-r--r--test/ruby/test_alias.rb49
-rw-r--r--test/ruby/test_allocation.rb440
-rw-r--r--test/ruby/test_array.rb199
-rw-r--r--test/ruby/test_assignment.rb10
-rw-r--r--test/ruby/test_ast.rb515
-rw-r--r--test/ruby/test_autoload.rb31
-rw-r--r--test/ruby/test_backtrace.rb12
-rw-r--r--test/ruby/test_bignum.rb50
-rw-r--r--test/ruby/test_box.rb874
-rw-r--r--test/ruby/test_call.rb163
-rw-r--r--test/ruby/test_case.rb9
-rw-r--r--test/ruby/test_class.rb133
-rw-r--r--test/ruby/test_compile_prism.rb162
-rw-r--r--test/ruby/test_complex.rb11
-rw-r--r--test/ruby/test_data.rb9
-rw-r--r--test/ruby/test_defined.rb55
-rw-r--r--test/ruby/test_dir.rb21
-rw-r--r--test/ruby/test_encoding.rb52
-rw-r--r--test/ruby/test_enum.rb8
-rw-r--r--test/ruby/test_enumerator.rb43
-rw-r--r--test/ruby/test_env.rb580
-rw-r--r--test/ruby/test_eval.rb46
-rw-r--r--test/ruby/test_exception.rb35
-rw-r--r--test/ruby/test_fiber.rb17
-rw-r--r--test/ruby/test_file.rb49
-rw-r--r--test/ruby/test_file_exhaustive.rb60
-rw-r--r--test/ruby/test_float.rb48
-rw-r--r--test/ruby/test_frozen.rb16
-rw-r--r--test/ruby/test_gc.rb444
-rw-r--r--test/ruby/test_gc_compact.rb89
-rw-r--r--test/ruby/test_hash.rb83
-rw-r--r--test/ruby/test_integer.rb37
-rw-r--r--test/ruby/test_io.rb297
-rw-r--r--test/ruby/test_io_buffer.rb390
-rw-r--r--test/ruby/test_io_m17n.rb41
-rw-r--r--test/ruby/test_iseq.rb212
-rw-r--r--test/ruby/test_iterator.rb16
-rw-r--r--test/ruby/test_keyword.rb76
-rw-r--r--test/ruby/test_lambda.rb14
-rw-r--r--test/ruby/test_lazy_enumerator.rb4
-rw-r--r--test/ruby/test_literal.rb31
-rw-r--r--test/ruby/test_m17n.rb205
-rw-r--r--test/ruby/test_marshal.rb50
-rw-r--r--test/ruby/test_math.rb32
-rw-r--r--test/ruby/test_memory_view.rb2
-rw-r--r--test/ruby/test_method.rb207
-rw-r--r--test/ruby/test_mixed_unicode_escapes.rb2
-rw-r--r--test/ruby/test_module.rb170
-rw-r--r--test/ruby/test_nomethod_error.rb30
-rw-r--r--test/ruby/test_numeric.rb34
-rw-r--r--test/ruby/test_object.rb127
-rw-r--r--test/ruby/test_object_id.rb303
-rw-r--r--test/ruby/test_objectspace.rb108
-rw-r--r--test/ruby/test_optimization.rb272
-rw-r--r--test/ruby/test_pack.rb23
-rw-r--r--test/ruby/test_parse.rb81
-rw-r--r--test/ruby/test_pattern_matching.rb52
-rw-r--r--test/ruby/test_proc.rb393
-rw-r--r--test/ruby/test_process.rb117
-rw-r--r--test/ruby/test_ractor.rb229
-rw-r--r--test/ruby/test_rand.rb5
-rw-r--r--test/ruby/test_random_formatter.rb5
-rw-r--r--test/ruby/test_range.rb422
-rw-r--r--test/ruby/test_rational.rb19
-rw-r--r--test/ruby/test_refinement.rb55
-rw-r--r--test/ruby/test_regexp.rb252
-rw-r--r--test/ruby/test_require.rb52
-rw-r--r--test/ruby/test_require_lib.rb4
-rw-r--r--test/ruby/test_rubyoptions.rb235
-rw-r--r--test/ruby/test_rubyvm.rb11
-rw-r--r--test/ruby/test_set.rb1052
-rw-r--r--test/ruby/test_settracefunc.rb286
-rw-r--r--test/ruby/test_shapes.rb258
-rw-r--r--test/ruby/test_signal.rb32
-rw-r--r--test/ruby/test_sleep.rb35
-rw-r--r--test/ruby/test_sprintf.rb14
-rw-r--r--test/ruby/test_string.rb420
-rw-r--r--test/ruby/test_string_memory.rb38
-rw-r--r--test/ruby/test_struct.rb10
-rw-r--r--test/ruby/test_super.rb65
-rw-r--r--test/ruby/test_symbol.rb6
-rw-r--r--test/ruby/test_syntax.rb210
-rw-r--r--test/ruby/test_thread.rb119
-rw-r--r--test/ruby/test_thread_cv.rb2
-rw-r--r--test/ruby/test_thread_queue.rb14
-rw-r--r--test/ruby/test_time.rb71
-rw-r--r--test/ruby/test_time_tz.rb1
-rw-r--r--test/ruby/test_transcode.rb108
-rw-r--r--test/ruby/test_variable.rb120
-rw-r--r--test/ruby/test_vm_dump.rb7
-rw-r--r--test/ruby/test_warning.rb32
-rw-r--r--test/ruby/test_weakkeymap.rb14
-rw-r--r--test/ruby/test_weakmap.rb36
-rw-r--r--test/ruby/test_yield.rb2
-rw-r--r--test/ruby/test_yjit.rb245
-rw-r--r--test/ruby/test_zjit.rb4542
-rw-r--r--test/rubygems/helper.rb89
-rw-r--r--test/rubygems/installer_test_case.rb25
-rw-r--r--test/rubygems/mock_gem_ui.rb4
-rw-r--r--test/rubygems/package/tar_test_case.rb38
-rw-r--r--test/rubygems/rubygems/commands/ins_command.rb7
-rw-r--r--test/rubygems/rubygems/commands/interrupt_command.rb11
-rw-r--r--test/rubygems/rubygems_plugin.rb19
-rw-r--r--test/rubygems/test_bundled_ca.rb2
-rw-r--r--test/rubygems/test_config.rb7
-rw-r--r--test/rubygems/test_gem.rb57
-rw-r--r--test/rubygems/test_gem_bundler_version_finder.rb79
-rw-r--r--test/rubygems/test_gem_command_manager.rb54
-rw-r--r--test/rubygems/test_gem_commands_build_command.rb10
-rw-r--r--test/rubygems/test_gem_commands_cert_command.rb8
-rw-r--r--test/rubygems/test_gem_commands_contents_command.rb6
-rw-r--r--test/rubygems/test_gem_commands_exec_command.rb28
-rw-r--r--test/rubygems/test_gem_commands_fetch_command.rb96
-rw-r--r--test/rubygems/test_gem_commands_help_command.rb4
-rw-r--r--test/rubygems/test_gem_commands_info_command.rb49
-rw-r--r--test/rubygems/test_gem_commands_install_command.rb148
-rw-r--r--test/rubygems/test_gem_commands_list_command.rb29
-rw-r--r--test/rubygems/test_gem_commands_lock_command.rb4
-rw-r--r--test/rubygems/test_gem_commands_owner_command.rb112
-rw-r--r--test/rubygems/test_gem_commands_pristine_command.rb70
-rw-r--r--test/rubygems/test_gem_commands_push_command.rb59
-rw-r--r--test/rubygems/test_gem_commands_query_command.rb830
-rw-r--r--test/rubygems/test_gem_commands_setup_command.rb35
-rw-r--r--test/rubygems/test_gem_commands_signin_command.rb2
-rw-r--r--test/rubygems/test_gem_commands_sources_command.rb563
-rw-r--r--test/rubygems/test_gem_commands_uninstall_command.rb55
-rw-r--r--test/rubygems/test_gem_commands_update_command.rb34
-rw-r--r--test/rubygems/test_gem_commands_yank_command.rb14
-rw-r--r--test/rubygems/test_gem_config_file.rb71
-rw-r--r--test/rubygems/test_gem_dependency.rb2
-rw-r--r--test/rubygems/test_gem_dependency_installer.rb211
-rw-r--r--test/rubygems/test_gem_ext_builder.rb70
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder.rb62
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock10
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml2
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock10
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml2
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder_link_flag_converter.rb2
-rw-r--r--test/rubygems/test_gem_ext_cmake_builder.rb97
-rw-r--r--test/rubygems/test_gem_ext_ext_conf_builder.rb33
-rw-r--r--test/rubygems/test_gem_ext_rake_builder.rb2
-rw-r--r--test/rubygems/test_gem_gem_runner.rb17
-rw-r--r--test/rubygems/test_gem_gemcutter_utilities.rb12
-rw-r--r--test/rubygems/test_gem_install_update_options.rb12
-rw-r--r--test/rubygems/test_gem_installer.rb351
-rw-r--r--test/rubygems/test_gem_name_tuple.rb37
-rw-r--r--test/rubygems/test_gem_package.rb103
-rw-r--r--test/rubygems/test_gem_package_old.rb2
-rw-r--r--test/rubygems/test_gem_package_tar_header_ractor.rb61
-rw-r--r--test/rubygems/test_gem_package_tar_writer.rb33
-rw-r--r--test/rubygems/test_gem_platform.rb360
-rw-r--r--test/rubygems/test_gem_rdoc.rb10
-rw-r--r--test/rubygems/test_gem_remote_fetcher.rb765
-rw-r--r--test/rubygems/test_gem_remote_fetcher_local_server.rb220
-rw-r--r--test/rubygems/test_gem_remote_fetcher_local_ssl_server.rb195
-rw-r--r--test/rubygems/test_gem_remote_fetcher_s3.rb437
-rw-r--r--test/rubygems/test_gem_request.rb24
-rw-r--r--test/rubygems/test_gem_request_connection_pools.rb12
-rw-r--r--test/rubygems/test_gem_request_set_gem_dependency_api.rb2
-rw-r--r--test/rubygems/test_gem_requirement.rb22
-rw-r--r--test/rubygems/test_gem_resolver.rb2
-rw-r--r--test/rubygems/test_gem_resolver_api_set.rb19
-rw-r--r--test/rubygems/test_gem_resolver_best_set.rb90
-rw-r--r--test/rubygems/test_gem_safe_marshal.rb134
-rw-r--r--test/rubygems/test_gem_security_trust_dir.rb6
-rw-r--r--test/rubygems/test_gem_source.rb2
-rw-r--r--test/rubygems/test_gem_source_git.rb4
-rw-r--r--test/rubygems/test_gem_source_installed.rb5
-rw-r--r--test/rubygems/test_gem_source_list.rb127
-rw-r--r--test/rubygems/test_gem_source_local.rb5
-rw-r--r--test/rubygems/test_gem_source_specific_file.rb4
-rw-r--r--test/rubygems/test_gem_source_subpath_problem.rb2
-rw-r--r--test/rubygems/test_gem_spec_fetcher.rb44
-rw-r--r--test/rubygems/test_gem_specification.rb283
-rw-r--r--test/rubygems/test_gem_stub_specification.rb95
-rw-r--r--test/rubygems/test_gem_uninstaller.rb2
-rw-r--r--test/rubygems/test_gem_uri.rb2
-rw-r--r--test/rubygems/test_gem_util.rb11
-rw-r--r--test/rubygems/test_gem_util_atomic_file_writer.rb12
-rw-r--r--test/rubygems/test_gem_version.rb33
-rw-r--r--test/rubygems/test_project_sanity.rb11
-rw-r--r--test/rubygems/test_require.rb56
-rw-r--r--test/rubygems/test_webauthn_listener.rb2
-rw-r--r--test/rubygems/utilities.rb24
-rw-r--r--test/set/fixtures/fake_sorted_set_gem/sorted_set.rb9
-rw-r--r--test/set/test_set.rb892
-rw-r--r--test/set/test_sorted_set.rb45
-rw-r--r--test/socket/test_addrinfo.rb6
-rw-r--r--test/socket/test_socket.rb280
-rw-r--r--test/socket/test_tcp.rb294
-rw-r--r--test/socket/test_unix.rb21
-rw-r--r--test/stringio/test_ractor.rb6
-rw-r--r--test/stringio/test_stringio.rb97
-rw-r--r--test/strscan/test_ractor.rb8
-rw-r--r--test/strscan/test_stringscanner.rb910
-rw-r--r--test/test_bundled_gems.rb48
-rw-r--r--test/test_delegate.rb41
-rw-r--r--test/test_extlibs.rb4
-rw-r--r--test/test_ipaddr.rb102
-rw-r--r--test/test_pp.rb119
-rw-r--r--test/test_pstore.rb182
-rw-r--r--test/test_pty.rb8
-rw-r--r--test/test_rbconfig.rb15
-rw-r--r--test/test_securerandom.rb20
-rw-r--r--test/test_shellwords.rb9
-rw-r--r--test/test_tempfile.rb45
-rw-r--r--test/test_time.rb2
-rw-r--r--test/test_timeout.rb193
-rw-r--r--test/test_tmpdir.rb49
-rw-r--r--test/test_tsort.rb115
-rw-r--r--test/test_unicode_normalize.rb28
-rw-r--r--test/uri/test_common.rb67
-rw-r--r--test/uri/test_ftp.rb10
-rw-r--r--test/uri/test_generic.rb92
-rw-r--r--test/uri/test_http.rb20
-rw-r--r--test/uri/test_mailto.rb72
-rw-r--r--test/uri/test_parser.rb40
-rw-r--r--test/uri/test_ws.rb16
-rw-r--r--test/uri/test_wss.rb16
-rw-r--r--test/win32/test_registry.rb229
-rw-r--r--test/win32ole/available_ole.rb41
-rw-r--r--test/win32ole/err_in_callback.rb10
-rw-r--r--test/win32ole/orig_data.csv5
-rw-r--r--test/win32ole/test_err_in_callback.rb56
-rw-r--r--test/win32ole/test_folderitem2_invokeverb.rb66
-rw-r--r--test/win32ole/test_nil2vtempty.rb37
-rw-r--r--test/win32ole/test_ole_methods.rb35
-rw-r--r--test/win32ole/test_propertyputref.rb31
-rw-r--r--test/win32ole/test_thread.rb34
-rw-r--r--test/win32ole/test_win32ole.rb541
-rw-r--r--test/win32ole/test_win32ole_event.rb411
-rw-r--r--test/win32ole/test_win32ole_method.rb138
-rw-r--r--test/win32ole/test_win32ole_method_event.rb36
-rw-r--r--test/win32ole/test_win32ole_param.rb102
-rw-r--r--test/win32ole/test_win32ole_param_event.rb30
-rw-r--r--test/win32ole/test_win32ole_record.rb215
-rw-r--r--test/win32ole/test_win32ole_type.rb203
-rw-r--r--test/win32ole/test_win32ole_type_event.rb44
-rw-r--r--test/win32ole/test_win32ole_typelib.rb121
-rw-r--r--test/win32ole/test_win32ole_variable.rb70
-rw-r--r--test/win32ole/test_win32ole_variant.rb726
-rw-r--r--test/win32ole/test_win32ole_variant_m.rb41
-rw-r--r--test/win32ole/test_win32ole_variant_outarg.rb69
-rw-r--r--test/win32ole/test_word.rb73
-rw-r--r--test/yaml/test_dbm.rb46
-rw-r--r--test/yaml/test_store.rb12
-rw-r--r--test/zlib/test_zlib.rb9
-rw-r--r--thread.c897
-rw-r--r--thread_none.c25
-rw-r--r--thread_pthread.c610
-rw-r--r--thread_pthread.h67
-rw-r--r--thread_pthread_mn.c208
-rw-r--r--thread_sync.c1172
-rw-r--r--thread_sync.rb471
-rw-r--r--thread_win32.c53
-rw-r--r--time.c362
-rw-r--r--timev.rb57
-rw-r--r--tool/annocheck/Dockerfile2
-rw-r--r--tool/annocheck/Dockerfile-copy7
-rwxr-xr-xtool/auto-style.rb284
-rwxr-xr-xtool/auto_review_pr.rb93
-rw-r--r--tool/bundler/dev_gems.rb8
-rw-r--r--tool/bundler/dev_gems.rb.lock132
-rw-r--r--tool/bundler/rubocop_gems.rb3
-rw-r--r--tool/bundler/rubocop_gems.rb.lock159
-rw-r--r--tool/bundler/standard_gems.rb3
-rw-r--r--tool/bundler/standard_gems.rb.lock179
-rw-r--r--tool/bundler/test_gems.rb14
-rw-r--r--tool/bundler/test_gems.rb.lock106
-rw-r--r--tool/bundler/vendor_gems.rb20
-rw-r--r--tool/bundler/vendor_gems.rb.lock75
-rwxr-xr-xtool/commit-email.rb372
-rw-r--r--tool/downloader.rb156
-rwxr-xr-xtool/enc-unicode.rb26
-rwxr-xr-xtool/extlibs.rb2
-rw-r--r--tool/fake.rb2
-rwxr-xr-xtool/fetch-bundled_gems.rb30
-rwxr-xr-xtool/file2lastrev.rb1
-rwxr-xr-xtool/format-release51
-rw-r--r--tool/generic_erb.rb2
-rw-r--r--tool/gperf.sed19
-rwxr-xr-xtool/ifchange6
-rwxr-xr-xtool/leaked-globals2
-rw-r--r--tool/lib/_tmpdir.rb6
-rw-r--r--tool/lib/bundle_env.rb4
-rw-r--r--tool/lib/bundled_gem.rb13
-rw-r--r--tool/lib/core_assertions.rb231
-rw-r--r--tool/lib/dump.gdb17
-rw-r--r--tool/lib/dump.lldb13
-rw-r--r--tool/lib/envutil.rb121
-rw-r--r--tool/lib/gem_env.rb1
-rw-r--r--tool/lib/launchable.rb91
-rw-r--r--tool/lib/leakchecker.rb12
-rw-r--r--tool/lib/memory_status.rb100
-rw-r--r--tool/lib/path.rb16
-rw-r--r--tool/lib/test/jobserver.rb47
-rw-r--r--tool/lib/test/unit.rb160
-rw-r--r--tool/lib/test/unit/assertions.rb34
-rw-r--r--tool/lib/test/unit/parallel.rb13
-rw-r--r--tool/lib/vcs.rb319
-rw-r--r--tool/lib/webrick.rb232
-rw-r--r--tool/lib/webrick/.document6
-rw-r--r--tool/lib/webrick/accesslog.rb157
-rw-r--r--tool/lib/webrick/cgi.rb313
-rw-r--r--tool/lib/webrick/compat.rb36
-rw-r--r--tool/lib/webrick/config.rb158
-rw-r--r--tool/lib/webrick/cookie.rb172
-rw-r--r--tool/lib/webrick/htmlutils.rb30
-rw-r--r--tool/lib/webrick/httpauth.rb96
-rw-r--r--tool/lib/webrick/httpauth/authenticator.rb117
-rw-r--r--tool/lib/webrick/httpauth/basicauth.rb116
-rw-r--r--tool/lib/webrick/httpauth/digestauth.rb395
-rw-r--r--tool/lib/webrick/httpauth/htdigest.rb132
-rw-r--r--tool/lib/webrick/httpauth/htgroup.rb97
-rw-r--r--tool/lib/webrick/httpauth/htpasswd.rb158
-rw-r--r--tool/lib/webrick/httpauth/userdb.rb53
-rw-r--r--tool/lib/webrick/httpproxy.rb354
-rw-r--r--tool/lib/webrick/httprequest.rb636
-rw-r--r--tool/lib/webrick/httpresponse.rb564
-rw-r--r--tool/lib/webrick/https.rb152
-rw-r--r--tool/lib/webrick/httpserver.rb293
-rw-r--r--tool/lib/webrick/httpservlet.rb23
-rw-r--r--tool/lib/webrick/httpservlet/abstract.rb152
-rw-r--r--tool/lib/webrick/httpservlet/cgi_runner.rb47
-rw-r--r--tool/lib/webrick/httpservlet/cgihandler.rb126
-rw-r--r--tool/lib/webrick/httpservlet/erbhandler.rb88
-rw-r--r--tool/lib/webrick/httpservlet/filehandler.rb552
-rw-r--r--tool/lib/webrick/httpservlet/prochandler.rb47
-rw-r--r--tool/lib/webrick/httpstatus.rb194
-rw-r--r--tool/lib/webrick/httputils.rb512
-rw-r--r--tool/lib/webrick/httpversion.rb76
-rw-r--r--tool/lib/webrick/log.rb156
-rw-r--r--tool/lib/webrick/server.rb381
-rw-r--r--tool/lib/webrick/ssl.rb215
-rw-r--r--tool/lib/webrick/utils.rb265
-rw-r--r--tool/lib/webrick/version.rb18
-rw-r--r--tool/lrama/NEWS.md704
-rwxr-xr-xtool/lrama/exe/lrama3
-rw-r--r--tool/lrama/lib/lrama.rb39
-rw-r--r--tool/lrama/lib/lrama/bitmap.rb26
-rw-r--r--tool/lrama/lib/lrama/command.rb145
-rw-r--r--tool/lrama/lib/lrama/context.rb60
-rw-r--r--tool/lrama/lib/lrama/counterexamples.rb336
-rw-r--r--tool/lrama/lib/lrama/counterexamples/derivation.rb31
-rw-r--r--tool/lrama/lib/lrama/counterexamples/example.rb76
-rw-r--r--tool/lrama/lib/lrama/counterexamples/node.rb30
-rw-r--r--tool/lrama/lib/lrama/counterexamples/path.rb24
-rw-r--r--tool/lrama/lib/lrama/counterexamples/production_path.rb17
-rw-r--r--tool/lrama/lib/lrama/counterexamples/start_path.rb21
-rw-r--r--tool/lrama/lib/lrama/counterexamples/state_item.rb27
-rw-r--r--tool/lrama/lib/lrama/counterexamples/transition_path.rb17
-rw-r--r--tool/lrama/lib/lrama/counterexamples/triple.rb38
-rw-r--r--tool/lrama/lib/lrama/diagram.rb77
-rw-r--r--tool/lrama/lib/lrama/digraph.rb55
-rw-r--r--tool/lrama/lib/lrama/erb.rb29
-rw-r--r--tool/lrama/lib/lrama/grammar.rb334
-rw-r--r--tool/lrama/lib/lrama/grammar/auxiliary.rb9
-rw-r--r--tool/lrama/lib/lrama/grammar/binding.rb75
-rw-r--r--tool/lrama/lib/lrama/grammar/code.rb29
-rw-r--r--tool/lrama/lib/lrama/grammar/code/destructor_code.rb13
-rw-r--r--tool/lrama/lib/lrama/grammar/code/initial_action_code.rb5
-rw-r--r--tool/lrama/lib/lrama/grammar/code/no_reference_code.rb5
-rw-r--r--tool/lrama/lib/lrama/grammar/code/printer_code.rb13
-rw-r--r--tool/lrama/lib/lrama/grammar/code/rule_action.rb27
-rw-r--r--tool/lrama/lib/lrama/grammar/counter.rb12
-rw-r--r--tool/lrama/lib/lrama/grammar/destructor.rb17
-rw-r--r--tool/lrama/lib/lrama/grammar/error_token.rb17
-rw-r--r--tool/lrama/lib/lrama/grammar/inline.rb3
-rw-r--r--tool/lrama/lib/lrama/grammar/inline/resolver.rb80
-rw-r--r--tool/lrama/lib/lrama/grammar/parameterized.rb5
-rw-r--r--tool/lrama/lib/lrama/grammar/parameterized/resolver.rb73
-rw-r--r--tool/lrama/lib/lrama/grammar/parameterized/rhs.rb45
-rw-r--r--tool/lrama/lib/lrama/grammar/parameterized/rule.rb36
-rw-r--r--tool/lrama/lib/lrama/grammar/parameterizing_rule.rb3
-rw-r--r--tool/lrama/lib/lrama/grammar/parameterizing_rule/resolver.rb56
-rw-r--r--tool/lrama/lib/lrama/grammar/parameterizing_rule/rhs.rb37
-rw-r--r--tool/lrama/lib/lrama/grammar/parameterizing_rule/rule.rb18
-rw-r--r--tool/lrama/lib/lrama/grammar/percent_code.rb15
-rw-r--r--tool/lrama/lib/lrama/grammar/precedence.rb46
-rw-r--r--tool/lrama/lib/lrama/grammar/printer.rb11
-rw-r--r--tool/lrama/lib/lrama/grammar/reference.rb15
-rw-r--r--tool/lrama/lib/lrama/grammar/rule.rb83
-rw-r--r--tool/lrama/lib/lrama/grammar/rule_builder.rb214
-rw-r--r--tool/lrama/lib/lrama/grammar/stdlib.y116
-rw-r--r--tool/lrama/lib/lrama/grammar/symbol.rb84
-rw-r--r--tool/lrama/lib/lrama/grammar/symbols.rb2
-rw-r--r--tool/lrama/lib/lrama/grammar/symbols/resolver.rb77
-rw-r--r--tool/lrama/lib/lrama/grammar/type.rb16
-rw-r--r--tool/lrama/lib/lrama/grammar/union.rb15
-rw-r--r--tool/lrama/lib/lrama/lexer.rb99
-rw-r--r--tool/lrama/lib/lrama/lexer/grammar_file.rb11
-rw-r--r--tool/lrama/lib/lrama/lexer/location.rb53
-rw-r--r--tool/lrama/lib/lrama/lexer/token.rb64
-rw-r--r--tool/lrama/lib/lrama/lexer/token/base.rb73
-rw-r--r--tool/lrama/lib/lrama/lexer/token/char.rb20
-rw-r--r--tool/lrama/lib/lrama/lexer/token/empty.rb14
-rw-r--r--tool/lrama/lib/lrama/lexer/token/ident.rb7
-rw-r--r--tool/lrama/lib/lrama/lexer/token/instantiate_rule.rb13
-rw-r--r--tool/lrama/lib/lrama/lexer/token/int.rb14
-rw-r--r--tool/lrama/lib/lrama/lexer/token/str.rb11
-rw-r--r--tool/lrama/lib/lrama/lexer/token/tag.rb10
-rw-r--r--tool/lrama/lib/lrama/lexer/token/token.rb11
-rw-r--r--tool/lrama/lib/lrama/lexer/token/user_code.rb112
-rw-r--r--tool/lrama/lib/lrama/logger.rb31
-rw-r--r--tool/lrama/lib/lrama/option_parser.rb157
-rw-r--r--tool/lrama/lib/lrama/options.rb34
-rw-r--r--tool/lrama/lib/lrama/output.rb120
-rw-r--r--tool/lrama/lib/lrama/parser.rb1743
-rw-r--r--tool/lrama/lib/lrama/report.rb2
-rw-r--r--tool/lrama/lib/lrama/report/duration.rb25
-rw-r--r--tool/lrama/lib/lrama/report/profile.rb14
-rw-r--r--tool/lrama/lib/lrama/reporter.rb39
-rw-r--r--tool/lrama/lib/lrama/reporter/conflicts.rb44
-rw-r--r--tool/lrama/lib/lrama/reporter/grammar.rb39
-rw-r--r--tool/lrama/lib/lrama/reporter/precedences.rb54
-rw-r--r--tool/lrama/lib/lrama/reporter/profile.rb4
-rw-r--r--tool/lrama/lib/lrama/reporter/profile/call_stack.rb45
-rw-r--r--tool/lrama/lib/lrama/reporter/profile/memory.rb44
-rw-r--r--tool/lrama/lib/lrama/reporter/rules.rb43
-rw-r--r--tool/lrama/lib/lrama/reporter/states.rb387
-rw-r--r--tool/lrama/lib/lrama/reporter/terms.rb44
-rw-r--r--tool/lrama/lib/lrama/state.rb452
-rw-r--r--tool/lrama/lib/lrama/state/action.rb5
-rw-r--r--tool/lrama/lib/lrama/state/action/goto.rb33
-rw-r--r--tool/lrama/lib/lrama/state/action/reduce.rb71
-rw-r--r--tool/lrama/lib/lrama/state/action/shift.rb39
-rw-r--r--tool/lrama/lib/lrama/state/inadequacy_annotation.rb140
-rw-r--r--tool/lrama/lib/lrama/state/item.rb120
-rw-r--r--tool/lrama/lib/lrama/state/reduce.rb35
-rw-r--r--tool/lrama/lib/lrama/state/reduce_reduce_conflict.rb17
-rw-r--r--tool/lrama/lib/lrama/state/resolved_conflict.rb46
-rw-r--r--tool/lrama/lib/lrama/state/shift.rb13
-rw-r--r--tool/lrama/lib/lrama/state/shift_reduce_conflict.rb17
-rw-r--r--tool/lrama/lib/lrama/states.rb651
-rw-r--r--tool/lrama/lib/lrama/states/item.rb81
-rw-r--r--tool/lrama/lib/lrama/states_reporter.rb321
-rw-r--r--tool/lrama/lib/lrama/tracer.rb51
-rw-r--r--tool/lrama/lib/lrama/tracer/actions.rb22
-rw-r--r--tool/lrama/lib/lrama/tracer/closure.rb30
-rw-r--r--tool/lrama/lib/lrama/tracer/duration.rb38
-rw-r--r--tool/lrama/lib/lrama/tracer/only_explicit_rules.rb24
-rw-r--r--tool/lrama/lib/lrama/tracer/rules.rb23
-rw-r--r--tool/lrama/lib/lrama/tracer/state.rb33
-rw-r--r--tool/lrama/lib/lrama/version.rb5
-rw-r--r--tool/lrama/lib/lrama/warning.rb25
-rw-r--r--tool/lrama/lib/lrama/warnings.rb33
-rw-r--r--tool/lrama/lib/lrama/warnings/conflicts.rb27
-rw-r--r--tool/lrama/lib/lrama/warnings/implicit_empty.rb29
-rw-r--r--tool/lrama/lib/lrama/warnings/name_conflicts.rb63
-rw-r--r--tool/lrama/lib/lrama/warnings/redefined_rules.rb23
-rw-r--r--tool/lrama/lib/lrama/warnings/required.rb23
-rw-r--r--tool/lrama/lib/lrama/warnings/useless_precedence.rb25
-rw-r--r--tool/lrama/template/bison/_yacc.h8
-rw-r--r--tool/lrama/template/bison/yacc.c43
-rw-r--r--tool/lrama/template/diagram/diagram.html102
-rw-r--r--tool/m4/ruby_append_option.m44
-rw-r--r--tool/m4/ruby_check_builtin_overflow.m428
-rw-r--r--tool/m4/ruby_check_builtin_setjmp.m42
-rw-r--r--tool/m4/ruby_defint.m43
-rw-r--r--tool/m4/ruby_modular_gc.m441
-rw-r--r--tool/m4/ruby_setjmp_type.m419
-rw-r--r--tool/m4/ruby_shared_gc.m419
-rw-r--r--tool/m4/ruby_try_cflags.m417
-rwxr-xr-xtool/make-snapshot103
-rwxr-xr-xtool/merger.rb26
-rwxr-xr-xtool/missing-baseruby.bat15
-rw-r--r--tool/mk_builtin_loader.rb58
-rwxr-xr-xtool/mk_rbbin.rb48
-rwxr-xr-xtool/mkconfig.rb12
-rwxr-xr-xtool/mkrunnable.rb5
-rw-r--r--tool/notes-github-pr.rb138
-rw-r--r--tool/notify-slack-commits.rb87
-rwxr-xr-xtool/outdate-bundled-gems.rb2
-rw-r--r--tool/prereq.status3
-rwxr-xr-xtool/rbinstall.rb232
-rw-r--r--tool/rbs_skip_tests62
-rw-r--r--tool/rbs_skip_tests_windows111
-rwxr-xr-xtool/rdoc-srcdir14
-rwxr-xr-xtool/redmine-backporter.rb25
-rwxr-xr-xtool/release.sh7
-rwxr-xr-xtool/releng/gen-mail.rb2
-rwxr-xr-xtool/releng/update-www-meta.rb25
-rwxr-xr-xtool/rjit/bindgen.rb665
-rwxr-xr-xtool/ruby-version.rb52
-rw-r--r--tool/ruby_vm/controllers/application_controller.rb1
-rw-r--r--tool/ruby_vm/helpers/c_escape.rb1
-rw-r--r--tool/ruby_vm/helpers/dumper.rb1
-rw-r--r--tool/ruby_vm/helpers/scanner.rb1
-rw-r--r--tool/ruby_vm/loaders/insns_def.rb1
-rw-r--r--tool/ruby_vm/loaders/opt_insn_unif_def.rb1
-rw-r--r--tool/ruby_vm/loaders/opt_operand_def.rb1
-rw-r--r--tool/ruby_vm/loaders/vm_opts_h.rb1
-rw-r--r--tool/ruby_vm/models/attribute.rb1
-rw-r--r--tool/ruby_vm/models/bare_instruction.rb236
-rwxr-xr-xtool/ruby_vm/models/bare_instructions.rb240
-rw-r--r--tool/ruby_vm/models/c_expr.rb1
-rw-r--r--tool/ruby_vm/models/instructions.rb19
-rw-r--r--tool/ruby_vm/models/instructions_unification.rb42
-rw-r--r--tool/ruby_vm/models/instructions_unifications.rb43
-rw-r--r--tool/ruby_vm/models/operands_unification.rb141
-rw-r--r--tool/ruby_vm/models/operands_unifications.rb142
-rw-r--r--tool/ruby_vm/models/trace_instruction.rb70
-rw-r--r--tool/ruby_vm/models/trace_instructions.rb71
-rw-r--r--tool/ruby_vm/models/typemap.rb1
-rw-r--r--tool/ruby_vm/models/zjit_instruction.rb56
-rw-r--r--tool/ruby_vm/scripts/insns2vm.rb1
-rw-r--r--tool/ruby_vm/tests/.gitkeep0
-rw-r--r--tool/ruby_vm/views/_comptime_insn_stack_increase.erb25
-rw-r--r--tool/ruby_vm/views/_insn_leaf_info.erb18
-rw-r--r--tool/ruby_vm/views/_insn_len_info.erb12
-rw-r--r--tool/ruby_vm/views/_insn_name_info.erb33
-rw-r--r--tool/ruby_vm/views/_insn_operand_info.erb32
-rw-r--r--tool/ruby_vm/views/_insn_sp_pc_dependency.erb27
-rw-r--r--tool/ruby_vm/views/_leaf_helpers.erb6
-rw-r--r--tool/ruby_vm/views/_sp_inc_helpers.erb2
-rw-r--r--tool/ruby_vm/views/_zjit_helpers.erb31
-rw-r--r--tool/ruby_vm/views/_zjit_instruction.erb12
-rw-r--r--tool/ruby_vm/views/insns.inc.erb17
-rw-r--r--tool/ruby_vm/views/insns_info.inc.erb6
-rw-r--r--tool/ruby_vm/views/lib/ruby_vm/rjit/instruction.rb.erb2
-rw-r--r--tool/ruby_vm/views/optinsn.inc.erb4
-rw-r--r--tool/ruby_vm/views/optunifs.inc.erb5
-rw-r--r--tool/ruby_vm/views/vm.inc.erb12
-rw-r--r--tool/ruby_vm/views/vmtc.inc.erb10
-rw-r--r--tool/run-gcov.rb3
-rw-r--r--tool/run-lcov.rb14
-rwxr-xr-xtool/sync_default_gems.rb1165
-rwxr-xr-xtool/test-annocheck.sh11
-rw-r--r--tool/test-bundled-gems.rb78
-rw-r--r--tool/test-coverage.rb4
-rw-r--r--tool/test/init.rb12
-rw-r--r--tool/test/test_commit_email.rb102
-rwxr-xr-xtool/test/test_sync_default_gems.rb104
-rw-r--r--tool/test/testunit/test_assertion.rb162
-rw-r--r--tool/test/testunit/test_hideskip.rb1
-rw-r--r--tool/test/testunit/test_launchable.rb3
-rw-r--r--tool/test/testunit/test_parallel.rb85
-rw-r--r--tool/test/testunit/tests_for_parallel/ptest_forth.rb8
-rw-r--r--tool/test/testunit/tests_for_parallel/test4test_hungup.rb2
-rw-r--r--tool/test/testunit/tests_for_parallel/test4test_slow_0.rb5
-rw-r--r--tool/test/testunit/tests_for_parallel/test4test_slow_1.rb5
-rw-r--r--tool/test/webrick/.htaccess1
-rw-r--r--tool/test/webrick/test_cgi.rb148
-rw-r--r--tool/test/webrick/test_config.rb17
-rw-r--r--tool/test/webrick/test_cookie.rb141
-rw-r--r--tool/test/webrick/test_do_not_reverse_lookup.rb71
-rw-r--r--tool/test/webrick/test_filehandler.rb397
-rw-r--r--tool/test/webrick/test_htgroup.rb19
-rw-r--r--tool/test/webrick/test_htmlutils.rb21
-rw-r--r--tool/test/webrick/test_httpauth.rb366
-rw-r--r--tool/test/webrick/test_httpproxy.rb467
-rw-r--r--tool/test/webrick/test_httprequest.rb488
-rw-r--r--tool/test/webrick/test_httpresponse.rb282
-rw-r--r--tool/test/webrick/test_https.rb112
-rw-r--r--tool/test/webrick/test_httpserver.rb543
-rw-r--r--tool/test/webrick/test_httpstatus.rb35
-rw-r--r--tool/test/webrick/test_httputils.rb101
-rw-r--r--tool/test/webrick/test_httpversion.rb41
-rw-r--r--tool/test/webrick/test_server.rb191
-rw-r--r--tool/test/webrick/test_ssl_server.rb67
-rw-r--r--tool/test/webrick/test_utils.rb110
-rw-r--r--tool/test/webrick/utils.rb104
-rwxr-xr-xtool/test/webrick/webrick.cgi38
-rw-r--r--tool/test/webrick/webrick.rhtml4
-rw-r--r--tool/test/webrick/webrick_long_filename.cgi36
-rw-r--r--tool/test_for_warn_bundled_gems/.gitignore1
-rw-r--r--tool/test_for_warn_bundled_gems/Gemfile0
-rw-r--r--tool/test_for_warn_bundled_gems/Gemfile.lock11
-rw-r--r--tool/test_for_warn_bundled_gems/README.md3
-rwxr-xr-xtool/test_for_warn_bundled_gems/test.sh53
-rw-r--r--tool/test_for_warn_bundled_gems/test_no_warn_dash_gem.rb8
-rw-r--r--tool/test_for_warn_bundled_gems/test_no_warn_dependency.rb10
-rw-r--r--tool/test_for_warn_bundled_gems/test_no_warn_sub_feature.rb8
-rw-r--r--tool/test_for_warn_bundled_gems/test_warn_bootsnap.rb11
-rw-r--r--tool/test_for_warn_bundled_gems/test_warn_bootsnap_rubyarchdir_gem.rb11
-rw-r--r--tool/test_for_warn_bundled_gems/test_warn_bundle_exec.rb1
-rwxr-xr-xtool/test_for_warn_bundled_gems/test_warn_bundle_exec_shebang.rb3
-rw-r--r--tool/test_for_warn_bundled_gems/test_warn_bundled_gems.rb8
-rw-r--r--tool/test_for_warn_bundled_gems/test_warn_dash_gem.rb7
-rw-r--r--tool/test_for_warn_bundled_gems/test_warn_dependency.rb8
-rw-r--r--tool/test_for_warn_bundled_gems/test_warn_sub_feature.rb7
-rw-r--r--tool/test_for_warn_bundled_gems/test_warn_zeitwerk.rb12
-rwxr-xr-xtool/update-NEWS-gemlist.rb21
-rwxr-xr-xtool/update-bundled_gems.rb9
-rwxr-xr-xtool/update-deps31
-rwxr-xr-xtool/zjit_bisect.rb158
-rw-r--r--tool/zjit_iongraph.html551
-rwxr-xr-xtool/zjit_iongraph.rb38
-rw-r--r--trace_point.rb355
-rw-r--r--transcode.c346
-rw-r--r--universal_parser.c21
-rw-r--r--util.c41
-rw-r--r--variable.c2242
-rw-r--r--variable.h28
-rw-r--r--vcpkg.json4
-rw-r--r--version.c163
-rw-r--r--vm.c822
-rw-r--r--vm_args.c295
-rw-r--r--vm_backtrace.c197
-rw-r--r--vm_callinfo.h200
-rw-r--r--vm_core.h404
-rw-r--r--vm_debug.h8
-rw-r--r--vm_dump.c365
-rw-r--r--vm_eval.c313
-rw-r--r--vm_exec.c6
-rw-r--r--vm_exec.h19
-rw-r--r--vm_insnhelper.c1365
-rw-r--r--vm_insnhelper.h17
-rw-r--r--vm_method.c882
-rw-r--r--vm_sync.c116
-rw-r--r--vm_sync.h31
-rw-r--r--vm_trace.c367
-rw-r--r--warning.rb8
-rw-r--r--wasm/README.md60
-rw-r--r--wasm/missing.c7
-rw-r--r--wasm/setjmp.c8
-rw-r--r--wasm/setjmp.h3
-rw-r--r--weakmap.c505
-rw-r--r--win32/Makefile.sub365
-rwxr-xr-xwin32/configure.bat250
-rw-r--r--win32/dir.h2
-rw-r--r--win32/file.c10
-rwxr-xr-xwin32/ifchange.bat136
-rwxr-xr-xwin32/install-buildtools.cmd14
-rwxr-xr-xwin32/install-msys-packages.cmd29
-rwxr-xr-xwin32/lastrev.bat30
-rwxr-xr-xwin32/makedirs.bat2
-rwxr-xr-xwin32/mkexports.rb21
-rwxr-xr-xwin32/rm.bat72
-rwxr-xr-xwin32/rmdirs.bat8
-rwxr-xr-xwin32/rtname.cmd1
-rw-r--r--win32/setup.mak125
-rwxr-xr-xwin32/vssetup.cmd56
-rw-r--r--win32/win32.c744
-rw-r--r--win32/winmain.c4
-rw-r--r--yjit.c857
-rw-r--r--yjit.h8
-rw-r--r--yjit.rb157
-rw-r--r--yjit/Cargo.lock8
-rw-r--r--yjit/Cargo.toml44
-rw-r--r--yjit/bindgen/Cargo.lock354
-rw-r--r--yjit/bindgen/Cargo.toml6
-rw-r--r--yjit/bindgen/src/main.rs166
-rw-r--r--yjit/not_gmake.mk2
-rw-r--r--yjit/src/asm/arm64/arg/bitmask_imm.rs2
-rw-r--r--yjit/src/asm/arm64/arg/sys_reg.rs4
-rw-r--r--yjit/src/asm/arm64/inst/atomic.rs4
-rw-r--r--yjit/src/asm/arm64/inst/branch.rs8
-rw-r--r--yjit/src/asm/arm64/inst/branch_cond.rs4
-rw-r--r--yjit/src/asm/arm64/inst/breakpoint.rs4
-rw-r--r--yjit/src/asm/arm64/inst/call.rs6
-rw-r--r--yjit/src/asm/arm64/inst/conditional.rs4
-rw-r--r--yjit/src/asm/arm64/inst/data_imm.rs12
-rw-r--r--yjit/src/asm/arm64/inst/data_reg.rs12
-rw-r--r--yjit/src/asm/arm64/inst/halfword_imm.rs14
-rw-r--r--yjit/src/asm/arm64/inst/load_literal.rs4
-rw-r--r--yjit/src/asm/arm64/inst/load_register.rs4
-rw-r--r--yjit/src/asm/arm64/inst/load_store.rs22
-rw-r--r--yjit/src/asm/arm64/inst/load_store_exclusive.rs6
-rw-r--r--yjit/src/asm/arm64/inst/logical_imm.rs14
-rw-r--r--yjit/src/asm/arm64/inst/logical_reg.rs18
-rw-r--r--yjit/src/asm/arm64/inst/madd.rs2
-rw-r--r--yjit/src/asm/arm64/inst/mov.rs6
-rw-r--r--yjit/src/asm/arm64/inst/nop.rs2
-rw-r--r--yjit/src/asm/arm64/inst/pc_rel.rs6
-rw-r--r--yjit/src/asm/arm64/inst/reg_pair.rs26
-rw-r--r--yjit/src/asm/arm64/inst/sbfm.rs6
-rw-r--r--yjit/src/asm/arm64/inst/shift_imm.rs6
-rw-r--r--yjit/src/asm/arm64/inst/smulh.rs2
-rw-r--r--yjit/src/asm/arm64/inst/sys_reg.rs6
-rw-r--r--yjit/src/asm/arm64/inst/test_bit.rs6
-rw-r--r--yjit/src/asm/arm64/mod.rs4
-rw-r--r--yjit/src/asm/mod.rs91
-rw-r--r--yjit/src/asm/x86_64/mod.rs10
-rw-r--r--yjit/src/asm/x86_64/tests.rs1
-rw-r--r--yjit/src/backend/arm64/mod.rs40
-rw-r--r--yjit/src/backend/ir.rs381
-rw-r--r--yjit/src/backend/tests.rs19
-rw-r--r--yjit/src/backend/x86_64/mod.rs42
-rw-r--r--yjit/src/codegen.rs2842
-rw-r--r--yjit/src/core.rs1826
-rw-r--r--yjit/src/cruby.rs89
-rw-r--r--yjit/src/cruby_bindings.inc.rs716
-rw-r--r--yjit/src/disasm.rs159
-rw-r--r--yjit/src/invariants.rs36
-rw-r--r--yjit/src/lib.rs14
-rw-r--r--yjit/src/log.rs179
-rw-r--r--yjit/src/options.rs121
-rw-r--r--yjit/src/stats.rs255
-rw-r--r--yjit/src/utils.rs28
-rw-r--r--yjit/src/virtualmem.rs119
-rw-r--r--yjit/src/yjit.rs72
-rw-r--r--yjit/yjit.mk93
-rw-r--r--zjit.c325
-rw-r--r--zjit.h47
-rw-r--r--zjit.rb357
-rw-r--r--zjit/.gitignore2
-rw-r--r--zjit/Cargo.lock74
-rw-r--r--zjit/Cargo.toml23
-rw-r--r--zjit/bindgen/Cargo.lock392
-rw-r--r--zjit/bindgen/Cargo.toml12
-rw-r--r--zjit/bindgen/src/main.rs454
-rw-r--r--zjit/build.rs37
-rw-r--r--zjit/src/asm/arm64/README.md16
-rw-r--r--zjit/src/asm/arm64/arg/bitmask_imm.rs255
-rw-r--r--zjit/src/asm/arm64/arg/condition.rs52
-rw-r--r--zjit/src/asm/arm64/arg/inst_offset.rs47
-rw-r--r--zjit/src/asm/arm64/arg/mod.rs18
-rw-r--r--zjit/src/asm/arm64/arg/sf.rs19
-rw-r--r--zjit/src/asm/arm64/arg/shifted_imm.rs80
-rw-r--r--zjit/src/asm/arm64/arg/sys_reg.rs6
-rw-r--r--zjit/src/asm/arm64/arg/truncate.rs66
-rw-r--r--zjit/src/asm/arm64/inst/atomic.rs86
-rw-r--r--zjit/src/asm/arm64/inst/branch.rs100
-rw-r--r--zjit/src/asm/arm64/inst/branch_cond.rs78
-rw-r--r--zjit/src/asm/arm64/inst/breakpoint.rs55
-rw-r--r--zjit/src/asm/arm64/inst/call.rs104
-rw-r--r--zjit/src/asm/arm64/inst/conditional.rs73
-rw-r--r--zjit/src/asm/arm64/inst/data_imm.rs143
-rw-r--r--zjit/src/asm/arm64/inst/data_reg.rs192
-rw-r--r--zjit/src/asm/arm64/inst/halfword_imm.rs179
-rw-r--r--zjit/src/asm/arm64/inst/load_literal.rs91
-rw-r--r--zjit/src/asm/arm64/inst/load_register.rs108
-rw-r--r--zjit/src/asm/arm64/inst/load_store.rs255
-rw-r--r--zjit/src/asm/arm64/inst/load_store_exclusive.rs109
-rw-r--r--zjit/src/asm/arm64/inst/logical_imm.rs154
-rw-r--r--zjit/src/asm/arm64/inst/logical_reg.rs207
-rw-r--r--zjit/src/asm/arm64/inst/madd.rs73
-rw-r--r--zjit/src/asm/arm64/inst/mod.rs54
-rw-r--r--zjit/src/asm/arm64/inst/mov.rs192
-rw-r--r--zjit/src/asm/arm64/inst/nop.rs44
-rw-r--r--zjit/src/asm/arm64/inst/pc_rel.rs107
-rw-r--r--zjit/src/asm/arm64/inst/reg_pair.rs212
-rw-r--r--zjit/src/asm/arm64/inst/sbfm.rs103
-rw-r--r--zjit/src/asm/arm64/inst/shift_imm.rs147
-rw-r--r--zjit/src/asm/arm64/inst/smulh.rs60
-rw-r--r--zjit/src/asm/arm64/inst/sys_reg.rs86
-rw-r--r--zjit/src/asm/arm64/inst/test_bit.rs133
-rw-r--r--zjit/src/asm/arm64/mod.rs1981
-rw-r--r--zjit/src/asm/arm64/opnd.rs270
-rw-r--r--zjit/src/asm/mod.rs453
-rw-r--r--zjit/src/asm/x86_64/mod.rs1446
-rw-r--r--zjit/src/asm/x86_64/tests.rs966
-rw-r--r--zjit/src/backend/arm64/mod.rs2780
-rw-r--r--zjit/src/backend/lir.rs2674
-rw-r--r--zjit/src/backend/mod.rs18
-rw-r--r--zjit/src/backend/tests.rs307
-rw-r--r--zjit/src/backend/x86_64/mod.rs1825
-rw-r--r--zjit/src/bitset.rs126
-rw-r--r--zjit/src/cast.rs64
-rw-r--r--zjit/src/codegen.rs2897
-rw-r--r--zjit/src/cruby.rs1411
-rw-r--r--zjit/src/cruby_bindings.inc.rs2203
-rw-r--r--zjit/src/cruby_methods.rs885
-rw-r--r--zjit/src/disasm.rs52
-rw-r--r--zjit/src/distribution.rs276
-rw-r--r--zjit/src/gc.rs211
-rw-r--r--zjit/src/hir.rs7604
-rw-r--r--zjit/src/hir/opt_tests.rs11123
-rw-r--r--zjit/src/hir/tests.rs4567
-rw-r--r--zjit/src/hir_effect/gen_hir_effect.rb119
-rw-r--r--zjit/src/hir_effect/hir_effect.inc.rs55
-rw-r--r--zjit/src/hir_effect/mod.rs420
-rw-r--r--zjit/src/hir_type/gen_hir_type.rb225
-rw-r--r--zjit/src/hir_type/hir_type.inc.rs253
-rw-r--r--zjit/src/hir_type/mod.rs1063
-rw-r--r--zjit/src/invariants.rs475
-rw-r--r--zjit/src/json.rs700
-rw-r--r--zjit/src/lib.rs34
-rw-r--r--zjit/src/options.rs523
-rw-r--r--zjit/src/payload.rs116
-rw-r--r--zjit/src/profile.rs434
-rw-r--r--zjit/src/state.rs549
-rw-r--r--zjit/src/stats.rs944
-rw-r--r--zjit/src/ttycolors.rs31
-rw-r--r--zjit/src/virtualmem.rs488
-rw-r--r--zjit/zjit.mk140
6049 files changed, 379173 insertions, 486843 deletions
diff --git a/.document b/.document
index 0665d415b9..82ca602bfb 100644
--- a/.document
+++ b/.document
@@ -15,13 +15,14 @@ array.rb
ast.rb
dir.rb
gc.rb
+hash.rb
io.rb
kernel.rb
marshal.rb
-rjit.rb
numeric.rb
nilclass.rb
pack.rb
+pathname_builtin.rb
ractor.rb
string.rb
symbol.rb
@@ -30,6 +31,7 @@ thread_sync.rb
trace_point.rb
warning.rb
yjit.rb
+zjit.rb
# Errno::*
known_errors.inc
diff --git a/.gdbinit b/.gdbinit
index 7dd3336e28..bda544c641 100644
--- a/.gdbinit
+++ b/.gdbinit
@@ -1,23 +1,7 @@
-set startup-with-shell off
-
-define hook-run
- set $color_type = 0
- set $color_highlite = 0
- set $color_end = 0
-end
-
define ruby_gdb_init
- if !$color_type
- set $color_type = "\033[31m"
- end
- if !$color_highlite
- set $color_highlite = "\033[36m"
- end
- if !$color_end
- set $color_end = "\033[m"
- end
- if ruby_dummy_gdb_enums.special_consts
- end
+ init-if-undefined $color_type = "\033[31m"
+ init-if-undefined $color_highlite = "\033[36m"
+ init-if-undefined $color_end = "\033[m"
end
# set prompt \033[36m(gdb)\033[m\040
@@ -67,7 +51,7 @@ define rp
printf "%sT_OBJECT%s: ", $color_type, $color_end
print ((struct RObject *)($arg0))->basic
if ($flags & ROBJECT_EMBED)
- print/x *((VALUE*)((struct RObject*)($arg0))->as.ary) @ (rb_shape_get_shape($arg0)->capacity)
+ print/x *((VALUE*)((struct RObject*)($arg0))->as.ary) @ (RSHAPE_CAPACITY(rb_obj_shape_id($arg0)))
else
print (((struct RObject *)($arg0))->as.heap)
if (((struct RObject*)($arg0))->as.heap.numiv) > 0
@@ -99,13 +83,11 @@ define rp
set $regsrc = ((struct RRegexp*)($arg0))->src
set $rsflags = ((struct RBasic*)$regsrc)->flags
printf "%sT_REGEXP%s: ", $color_type, $color_end
- set $len = ($rsflags & RUBY_FL_USER1) ? \
- ((struct RString*)$regsrc)->as.heap.len : \
- (($rsflags & (RUBY_FL_USER2|RUBY_FL_USER3|RUBY_FL_USER4|RUBY_FL_USER5|RUBY_FL_USER6)) >> RUBY_FL_USHIFT+2)
+ set $len = ((struct RString*)($arg0))->len
set print address off
output *(char *)(($rsflags & RUBY_FL_USER1) ? \
((struct RString*)$regsrc)->as.heap.ptr : \
- ((struct RString*)$regsrc)->as.ary) @ $len
+ ((struct RString*)$regsrc)->as.embed.ary) @ $len
set print address on
printf " len:%ld ", $len
if $flags & RUBY_FL_USER6
@@ -157,13 +139,15 @@ define rp
if ($flags & RUBY_T_MASK) == RUBY_T_HASH
printf "%sT_HASH%s: ", $color_type, $color_end,
if (((struct RHash *)($arg0))->basic.flags & RHASH_ST_TABLE_FLAG)
- printf "st len=%ld ", ((struct RHash *)($arg0))->as.st->num_entries
+ set $st = (struct st_table *)((uintptr_t)($arg0) + sizeof(struct RHash))
+ printf "st len=%ld ", $st->num_entries
+ print $st
else
printf "li len=%ld bound=%ld ", \
((((struct RHash *)($arg0))->basic.flags & RHASH_AR_TABLE_SIZE_MASK) >> RHASH_AR_TABLE_SIZE_SHIFT), \
((((struct RHash *)($arg0))->basic.flags & RHASH_AR_TABLE_BOUND_MASK) >> RHASH_AR_TABLE_BOUND_SHIFT)
+ print (struct ar_table_struct *)((uintptr_t)($arg0) + sizeof(struct RHash))
end
- print (struct RHash *)($arg0)
else
if ($flags & RUBY_T_MASK) == RUBY_T_STRUCT
set $len = (($flags & (RUBY_FL_USER1|RUBY_FL_USER2)) ? \
@@ -201,12 +185,19 @@ define rp
print (struct RBasic *)($arg0)
else
if ($flags & RUBY_T_MASK) == RUBY_T_DATA
- if ((struct RTypedData *)($arg0))->typed_flag == 1
- printf "%sT_DATA%s(%s): ", $color_type, $color_end, ((struct RTypedData *)($arg0))->type->wrap_struct_name
- print (struct RTypedData *)($arg0)
+ if ($flags & RUBY_TYPED_FL_IS_TYPED_DATA)
+ set $data = (struct RTypedData *)($arg0)
+ set $type = (const rb_data_type_t *)($data->type & ~1)
+ printf "%sT_DATA%s(%s): ", $color_type, $color_end, $type->wrap_struct_name
+ print *$type
+ if ($data->type & 1)
+ print (void *)&$data->data
+ else
+ print $data
+ end
else
printf "%sT_DATA%s: ", $color_type, $color_end
- print (struct RData *)($arg0)
+ print *(struct RData *)($arg0)
end
else
if ($flags & RUBY_T_MASK) == RUBY_T_MATCH
@@ -440,13 +431,11 @@ end
define output_string
set $flags = ((struct RBasic*)($arg0))->flags
- set $len = ($flags & RUBY_FL_USER1) ? \
- ((struct RString*)($arg0))->as.heap.len : \
- (($flags & (RUBY_FL_USER2|RUBY_FL_USER3|RUBY_FL_USER4|RUBY_FL_USER5|RUBY_FL_USER6)) >> RUBY_FL_USHIFT+2)
+ set $len = ((struct RString*)($arg0))->len
if $len > 0
output *(char *)(($flags & RUBY_FL_USER1) ? \
((struct RString*)($arg0))->as.heap.ptr : \
- ((struct RString*)($arg0))->as.ary) @ $len
+ ((struct RString*)($arg0))->as.embed.ary) @ $len
else
output ""
end
@@ -454,13 +443,11 @@ end
define print_string
set $flags = ((struct RBasic*)($arg0))->flags
- set $len = ($flags & RUBY_FL_USER1) ? \
- ((struct RString*)($arg0))->as.heap.len : \
- (($flags & (RUBY_FL_USER2|RUBY_FL_USER3|RUBY_FL_USER4|RUBY_FL_USER5|RUBY_FL_USER6)) >> RUBY_FL_USHIFT+2)
+ set $len = ((struct RString*)($arg0))->len
if $len > 0
printf "%s", *(char *)(($flags & RUBY_FL_USER1) ? \
((struct RString*)($arg0))->as.heap.ptr : \
- ((struct RString*)($arg0))->as.ary) @ $len
+ ((struct RString*)($arg0))->as.embed.ary) @ $len
end
end
@@ -543,14 +530,14 @@ document rp_bignum
end
define rp_class
+ set $class_and_classext = (struct RClass_and_rb_classext_t *)($arg0)
printf "(struct RClass *) %p", (void*)$arg0
- if RCLASS_ORIGIN((struct RClass *)($arg0)) != $arg0
- printf " -> %p", RCLASS_ORIGIN((struct RClass *)($arg0))
+ if $class_and_classext->classext->origin_ != (VALUE)$arg0
+ printf " -> %p", $class_and_classext->classext->origin_
end
printf "\n"
rb_classname $arg0
- print/x *(struct RClass *)($arg0)
- print *RCLASS_EXT((struct RClass *)($arg0))
+ print/x *$class_and_classext
end
document rp_class
Print the content of a Class/Module.
@@ -916,10 +903,10 @@ document rb_method_entry
end
define rb_classname
- # up to 128bit int
- set $rb_classname = rb_mod_name($arg0)
- if $rb_classname != RUBY_Qnil
- rp $rb_classname
+ set $rb_classname = ((struct RClass_and_rb_classext_t*)$arg0)->classext->classpath
+ if $rb_classname != RUBY_Qfalse
+ print_string $rb_classname
+ printf "\n"
else
echo anonymous class/module\n
end
@@ -1126,7 +1113,7 @@ define rb_ps_thread
set $ps_thread = (struct RTypedData*)$arg0
set $ps_thread_th = (rb_thread_t*)$ps_thread->data
printf "* #<Thread:%p rb_thread_t:%p native_thread:%p>\n", \
- $ps_thread, $ps_thread_th, $ps_thread_th->thread_id
+ $ps_thread, $ps_thread_th, $ps_thread_th->nt
set $cfp = $ps_thread_th->ec->cfp
set $cfpend = (rb_control_frame_t *)($ps_thread_th->ec->vm_stack + $ps_thread_th->ec->vm_stack_size)-1
while $cfp < $cfpend
@@ -1311,13 +1298,12 @@ define dump_node
set $flags = ((struct RBasic*)($str))->flags
printf "%s", (char *)(($flags & RUBY_FL_USER1) ? \
((struct RString*)$str)->as.heap.ptr : \
- ((struct RString*)$str)->as.ary)
+ ((struct RString*)$str)->as.embed.ary)
end
define print_flags
printf "RUBY_FL_WB_PROTECTED: %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_WB_PROTECTED ? "1" : "0"
- printf "RUBY_FL_PROMOTED0 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_PROMOTED0 ? "1" : "0"
- printf "RUBY_FL_PROMOTED1 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_PROMOTED1 ? "1" : "0"
+ printf "RUBY_FL_PROMOTED : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_PROMOTED ? "1" : "0"
printf "RUBY_FL_FINALIZE : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_FINALIZE ? "1" : "0"
printf "RUBY_FL_SHAREABLE : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_SHAREABLE ? "1" : "0"
printf "RUBY_FL_EXIVAR : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_EXIVAR ? "1" : "0"
@@ -1344,4 +1330,7 @@ define print_flags
printf "RUBY_FL_USER18 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_USER18 ? "1" : "0"
end
-source misc/gdb.py
+source -s misc/gdb.py
+
+# Moved from beginning, since it fails on older gdbs
+set startup-with-shell off
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index 1cafd3df75..d98646febf 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -6,6 +6,11 @@
# Expand tabs
5b21e94bebed90180d8ff63dad03b8b948361089
c5e9af9c9d890578182a21e7b71b50334cd5579e
+e63a2115f64433b21cb5dd67c5bf8b30f87ef293
+712ac99e4d0384a941c80a9f48f62943ba7d97c0
+d1474affa8e105bece209cc9d594bb0a989859e1
+2da92388b948821269b18d6b178a680f17e41750
+5062c0c621d887367af8a054e5e5d83d7ec57dd3
# Enable Style/StringLiterals cop for RubyGems/Bundler
d7ffd3fea402239b16833cc434404a7af82d44f3
@@ -30,3 +35,7 @@ d2c5867357ed88eccc28c2b3bd4a46e206e7ff85
# Miss-and-revived commits
a0f7de814ae5c299d6ce99bed5fb308a05d50ba0
d4e24021d39e1f80f0055b55d91f8d5f22e15084
+7a56c316418980b8a41fcbdc94067b2bda2ad112
+e90282be7ba1bc8e3119f6e1a2c80356ceb3f80a
+26a9e0b4e31f7b5a9cbd755e0a15823a8fa51bae
+2f53985da9ee593fe524d408256835667938c7d7
diff --git a/.gitattributes b/.gitattributes
index d0c2d266b4..6ac6e6fcc3 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,5 +1,6 @@
*.gemspec diff=ruby
*.rb diff=ruby
+*.inc.rs linguist-generated=true
bin svn-properties=svn:ignore=ruby
bin/* diff=ruby
tool/update-deps diff=ruby
diff --git a/.github/actions/capiext/action.yml b/.github/actions/capiext/action.yml
new file mode 100644
index 0000000000..49562725f4
--- /dev/null
+++ b/.github/actions/capiext/action.yml
@@ -0,0 +1,86 @@
+name: rubyspec C-API extensions
+
+inputs:
+ builddir:
+ required: false
+ default: '.'
+ make:
+ required: false
+ default: 'make -s'
+
+outputs:
+ key:
+ value: >-
+ ${{
+ !steps.restore.outputs.cache-hit &&
+ github.ref == 'refs/heads/master' &&
+ steps.config.outputs.key
+ }}
+
+runs:
+ using: composite
+
+ steps:
+ - id: config
+ shell: bash
+ run: |
+ eval $(grep -e '^arch *=' -e '^ruby_version *=' -e '^DLEXT *=' Makefile |
+ sed 's/ *= */=/')
+ case "${ruby_version}" in
+ *+*) key=capiexts-${arch}-${ruby_version}-${{ hashFiles('src/spec/ruby/optional/capi/ext/*.[ch]') }};;
+ *) key=;;
+ esac
+ echo version=$ruby_version >> $GITHUB_OUTPUT
+ echo key="$key" >> $GITHUB_OUTPUT
+ echo DLEXT=$DLEXT >> $GITHUB_OUTPUT
+ working-directory: ${{ inputs.builddir }}
+
+ - name: Restore previous CAPI extensions
+ uses: actions/cache/restore@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
+ id: cache
+ with:
+ path: ${{ inputs.builddir }}/spec/ruby/optional/capi/ext/
+ key: ${{ steps.config.outputs.key }}
+ if: ${{ steps.config.outputs.key }}
+
+ - name: Run test-spec with previous CAPI extension binaries
+ id: check
+ shell: bash
+ run: |
+ touch spec/ruby/optional/capi/ext/*.$DLEXT
+ [ ! -f spec/ruby/optional/capi/ext/\*.$DLEXT ]
+ ${{ inputs.make }} SPECOPTS=optional/capi test-spec
+ env:
+ DLEXT: ${{ steps.config.outputs.DLEXT }}
+ working-directory: ${{ inputs.builddir }}
+ if: ${{ steps.cache.outputs.cache-hit }}
+
+ - name: Strip CAPI extensions
+ id: strip
+ shell: bash
+ run: |
+ rm -f spec/ruby/optional/capi/ext/*.c
+ [ "$DLEXT" = bundle ] || # separated to .dSYM directories
+ strip spec/ruby/optional/capi/ext/*.$DLEXT
+ env:
+ DLEXT: ${{ steps.config.outputs.DLEXT }}
+ working-directory: ${{ inputs.builddir }}
+ if: >-
+ ${{true
+ && ! steps.cache.outputs.cache-hit
+ && github.ref_name == 'master'
+ }}
+
+ - name: Save CAPI extensions
+ uses: actions/cache/save@0400d5f644dc74513175e3cd8d07132dd4860809 # v4.2.4
+ with:
+ path: ${{ inputs.builddir }}/spec/ruby/optional/capi/ext/
+ key: ${{ steps.config.outputs.key }}
+ if: ${{ steps.strip.outcome == 'success' }}
+
+ - shell: bash
+ run: |
+ echo "::error::Change from ${prev} detected; bump up ABI version"
+ env:
+ prev: ${{ steps.config.outputs.version }}
+ if: ${{ always() && steps.check.outcome == 'failure' }}
diff --git a/.github/actions/compilers/action.yml b/.github/actions/compilers/action.yml
new file mode 100644
index 0000000000..ab5b56a889
--- /dev/null
+++ b/.github/actions/compilers/action.yml
@@ -0,0 +1,133 @@
+name: Compiles ruby in a container
+description: >-
+ Makes ruby using a dedicated container
+
+inputs:
+ tag:
+ required: false
+ default: clang-20
+ description: >-
+ container image tag to use in this run.
+
+ with_gcc:
+ required: false
+ description: >-
+ override compiler path & flags.
+
+ CFLAGS:
+ required: false
+ description: >-
+ C compiler flags to override.
+
+ CXXFLAGS:
+ required: false
+ description: >-
+ C++ compiler flags to override.
+
+ optflags:
+ required: false
+ # -O1 is faster than -O3 in our tests... Majority of time are consumed trying
+ # to optimize binaries. Also GitHub Actions run on relatively modern CPUs
+ # compared to, say, GCC 4 or Clang 3. We don't specify `-march=native`
+ # because compilers tend not understand what the CPU is.
+ default: '-O1'
+ description: >-
+ Compiler flags for optimisations.
+
+ cppflags:
+ required: false
+ description: >-
+ Additional preprocessor flags.
+
+ append_configure:
+ required: false
+ default: >-
+ --without-valgrind
+ --without-jemalloc
+ --without-gmp
+ description: >-
+ flags to append to configure.
+
+ enable_shared:
+ required: false
+ default: true
+ description: >-
+ Whether to build libruby.so.
+
+ check:
+ required: false
+ default: ''
+ description: >-
+ Whether to run `make check`
+
+ test_all:
+ required: false
+ default: ''
+ description: >-
+ Whether to run `make test-all` with options for test-all.
+
+ test_spec:
+ required: false
+ default: ''
+ description: >-
+ Whether to run `make test-spec` with options for mspec.
+
+ static_exts:
+ required: false
+ description: >-
+ whitespace separated list of extensions that need be linked statically.
+
+runs:
+ using: composite
+ steps:
+ - shell: bash
+ run: docker pull --quiet 'ghcr.io/ruby/ruby-ci-image:${{ inputs.tag }}'
+
+ - name: Enable Launchable conditionally
+ id: enable-launchable
+ run: echo "enable-launchable=true" >> $GITHUB_OUTPUT
+ shell: bash
+ if: >-
+ ${{
+ github.repository == 'ruby/ruby' ||
+ (github.repository != 'ruby/ruby' && env.LAUNCHABLE_TOKEN)
+ }}
+
+ - name: compile
+ shell: bash
+ run: >-
+ docker run
+ --rm
+ --user=root
+ --volume '${{ github.workspace }}:/github/workspace:ro'
+ --workdir=/github/workspace
+ --entrypoint=/github/workspace/.github/actions/compilers/entrypoint.sh
+ --env CI
+ --env GITHUB_ACTION
+ --env INPUT_WITH_GCC='${{ inputs.with_gcc || inputs.tag }}'
+ --env INPUT_CFLAGS='${{ inputs.CFLAGS }}'
+ --env INPUT_CXXFLAGS='${{ inputs.CXXFLAGS }}'
+ --env INPUT_OPTFLAGS='${{ inputs.OPTFLAGS }}'
+ --env INPUT_CPPFLAGS='${{ inputs.cppflags }}'
+ --env INPUT_APPEND_CONFIGURE='${{ inputs.append_configure }}'
+ --env INPUT_CHECK='${{ inputs.check }}'
+ --env INPUT_TEST_ALL='${{ inputs.test_all }}'
+ --env INPUT_TEST_SPEC='${{ inputs.test_spec }}'
+ --env INPUT_ENABLE_SHARED='${{ inputs.enable_shared }}'
+ --env INPUT_STATIC_EXTS='${{ inputs.static_exts }}'
+ --env LAUNCHABLE_ORGANIZATION='${{ github.repository_owner }}'
+ --env LAUNCHABLE_WORKSPACE='${{ github.event.repository.name }}'
+ --env LAUNCHABLE_ENABLED='${{ steps.enable-launchable.outputs.enable-launchable || false }}'
+ --env GITHUB_PR_HEAD_SHA='${{ github.event.pull_request.head.sha || github.sha }}'
+ --env GITHUB_PULL_REQUEST_URL='${{ github.event.pull_request.html_url }}'
+ --env GITHUB_REF='${{ github.ref }}'
+ --env GITHUB_ACTIONS
+ --env GITHUB_RUN_ID
+ --env GITHUB_REPOSITORY
+ --env GITHUB_WORKFLOW
+ --env GITHUB_RUN_NUMBER
+ --env GITHUB_EVENT_NAME
+ --env GITHUB_SHA
+ --env GITHUB_HEAD_REF
+ --env GITHUB_SERVER_URL
+ 'ghcr.io/ruby/ruby-ci-image:${{ inputs.tag }}'
diff --git a/.github/actions/compilers/entrypoint.sh b/.github/actions/compilers/entrypoint.sh
new file mode 100755
index 0000000000..b554151091
--- /dev/null
+++ b/.github/actions/compilers/entrypoint.sh
@@ -0,0 +1,90 @@
+#! /bin/bash
+
+# Copyright (c) 2024 Ruby developers. All rights reserved.
+#
+# This file is a part of the programming language Ruby. Permission is hereby
+# granted, to either redistribute and/or modify this file, provided that the
+# conditions mentioned in the file COPYING are met. Consult the file for
+# details.
+
+grouped()
+{
+ echo "::group::${@}"
+ "${@}"
+ echo "::endgroup::"
+}
+
+set -e
+set -u
+set -o pipefail
+
+srcdir="/github/workspace/src"
+builddir="$(mktemp -dt)"
+
+export GITHUB_WORKFLOW='Compilations'
+export CONFIGURE_TTY='never'
+export RUBY_DEBUG='ci rgengc'
+export RUBY_TESTOPTS='-q --color=always --tty=no'
+export RUBY_DEBUG_COUNTER_DISABLE='1'
+export GNUMAKEFLAGS="-j$((1 + $(nproc)))"
+
+case "x${INPUT_ENABLE_SHARED}" in
+x | xno | xfalse )
+ enable_shared='--disable-shared'
+ ;;
+*)
+ enable_shared='--enable-shared'
+ ;;
+esac
+
+pushd ${builddir}
+
+grouped git config --global --add safe.directory ${srcdir}
+
+grouped ${srcdir}/configure \
+ -C \
+ --with-gcc="${INPUT_WITH_GCC}" \
+ --enable-debug-env \
+ --disable-install-doc \
+ --with-ext=-test-/cxxanyargs,+ \
+ --without-git \
+ ${enable_shared} \
+ ${INPUT_APPEND_CONFIGURE} \
+ CFLAGS="${INPUT_CFLAGS}" \
+ CXXFLAGS="${INPUT_CXXFLAGS}" \
+ optflags="${INPUT_OPTFLAGS}" \
+ cppflags="${INPUT_CPPFLAGS}" \
+ debugflags='-ggdb3' # -g0 disables backtraces when SEGV. Do not set that.
+
+popd
+
+if [[ -n "${INPUT_STATIC_EXTS}" ]]; then
+ echo "::group::ext/Setup"
+ set -x
+ mkdir ${builddir}/ext
+ (
+ for ext in ${INPUT_STATIC_EXTS}; do
+ echo "${ext}"
+ done
+ ) >> ${builddir}/ext/Setup
+ set +x
+ echo "::endgroup::"
+fi
+
+if [ -n "$INPUT_TEST_ALL" ]; then
+ tests=" -- $INPUT_TEST_ALL"
+else
+ tests=" -- ruby -ext-"
+fi
+
+pushd ${builddir}
+
+grouped make showflags
+grouped make all
+# grouped make install
+
+# Run only `make test` by default. Run other tests if specified.
+grouped make test
+if [[ -n "$INPUT_CHECK" ]]; then grouped make test-tool; fi
+if [[ -n "$INPUT_CHECK" || -n "$INPUT_TEST_ALL" ]]; then grouped make test-all TESTS="$tests"; fi
+if [[ -n "$INPUT_CHECK" || -n "$INPUT_TEST_SPEC" ]]; then grouped env CHECK_LEAKS=true make test-spec MSPECOPT="$INPUT_TEST_SPEC"; fi
diff --git a/.github/actions/launchable/setup/action.yml b/.github/actions/launchable/setup/action.yml
index 6d50318ded..16af8fc3fd 100644
--- a/.github/actions/launchable/setup/action.yml
+++ b/.github/actions/launchable/setup/action.yml
@@ -3,11 +3,6 @@ description: >-
Install the required dependencies and execute the necessary Launchable commands for test recording
inputs:
- report-path:
- default: launchable_reports.json
- required: true
- description: The file path of the test report for uploading to Launchable
-
os:
required: true
description: The operating system that CI runs on. This value is used in Launchable flavor.
@@ -35,9 +30,42 @@ inputs:
required: false
default: ${{ github.workspace }}
description: >-
- Directory to (re-)checkout source codes. Launchable retrives the commit information
+ Directory to (re-)checkout source codes. Launchable retrieves the commit information
from the directory.
+ test-task:
+ required: false
+ default: ${{ matrix.test_task }}
+ description: >-
+ Specifies a single test task to be executed.
+ This value is used in the Launchable flavor.
+ Either 'test-task' or 'multi-test-tasks' must be configured.
+
+ test-tasks:
+ required: false
+ default: '[]'
+ description: >-
+ Specifies an array of multiple test tasks to be executed.
+ For example: '["test", "test-all"]'.
+ If you want to run a single test task, use the 'test-task' input instead.
+
+ is-yjit:
+ required: false
+ default: 'false'
+ description: >-
+ Whether this workflow is executed on YJIT.
+
+outputs:
+ stdout_report_path:
+ value: ${{ steps.global.outputs.stdout_report_path }}
+ description: >-
+ Report file path for standard output.
+
+ stderr_report_path:
+ value: ${{ steps.global.outputs.stderr_report_path }}
+ description: >-
+ Report file path for standard error.
+
runs:
using: composite
@@ -48,9 +76,14 @@ runs:
shell: bash
if: >-
${{
- (github.repository == 'ruby/ruby' ||
- (github.repository != 'ruby/ruby' && env.LAUNCHABLE_TOKEN)) &&
- (matrix.test_task == 'check' || matrix.test_task == 'test-all')
+ (github.repository == 'ruby/ruby'
+ || (github.repository != 'ruby/ruby'
+ && env.LAUNCHABLE_TOKEN))
+ && (inputs.test-task == 'check'
+ || inputs.test-task == 'test-all'
+ || inputs.test-task == 'test'
+ || contains(fromJSON(inputs.test-tasks), 'test-all')
+ || contains(fromJSON(inputs.test-tasks), 'test'))
}}
# Launchable CLI requires Python and Java.
@@ -59,13 +92,54 @@ runs:
uses: actions/setup-python@871daa956ca9ea99f3c3e30acb424b7960676734 # v5.0.0
with:
python-version: "3.x"
- if: steps.enable-launchable.outputs.enable-launchable
+ if: >-
+ ${{ steps.enable-launchable.outputs.enable-launchable
+ && !endsWith(inputs.os, 'ppc64le') && !endsWith(inputs.os, 's390x') }}
- name: Set up Java
uses: actions/setup-java@7a445ee88d4e23b52c33fdc7601e40278616c7f8 # v4.0.0
with:
distribution: 'temurin'
java-version: '17'
+ if: >-
+ ${{ steps.enable-launchable.outputs.enable-launchable
+ && !endsWith(inputs.os, 'ppc64le') && !endsWith(inputs.os, 's390x') }}
+
+ - name: Set up Java ppc64le
+ uses: actions/setup-java@7a445ee88d4e23b52c33fdc7601e40278616c7f8 # v4.0.0
+ with:
+ distribution: 'semeru'
+ architecture: 'ppc64le'
+ java-version: '17'
+ if: >-
+ ${{ steps.enable-launchable.outputs.enable-launchable
+ && endsWith(inputs.os, 'ppc64le') }}
+
+ - name: Set up Java s390x
+ uses: actions/setup-java@7a445ee88d4e23b52c33fdc7601e40278616c7f8 # v4.0.0
+ with:
+ distribution: 'semeru'
+ architecture: 's390x'
+ java-version: '17'
+ if: >-
+ ${{ steps.enable-launchable.outputs.enable-launchable
+ && endsWith(inputs.os, 's390x') }}
+
+ - name: Set global vars
+ id: global
+ shell: bash
+ run: |
+ test_all_enabled="${{ inputs.test-task == 'check' || inputs.test-task == 'test-all' || contains(fromJSON(inputs.test-tasks), 'test-all') }}"
+ btest_enabled="${{ inputs.test-task == 'check' || inputs.test-task == 'test' || contains(fromJSON(inputs.test-tasks), 'test') }}"
+ test_spec_enabled="${{ inputs.test-task == 'check' || inputs.test-task == 'test-spec' || contains(fromJSON(inputs.test-tasks), 'test-spec') }}"
+ echo test_all_enabled="${test_all_enabled}" >> $GITHUB_OUTPUT
+ echo btest_enabled="${btest_enabled}" >> $GITHUB_OUTPUT
+ echo test_spec_enabled="${test_spec_enabled}" >> $GITHUB_OUTPUT
+ echo test_all_report_file='launchable_test_all_report.json' >> $GITHUB_OUTPUT
+ echo btest_report_file='launchable_btest_report.json' >> $GITHUB_OUTPUT
+ echo test_spec_report_dir='launchable_test_spec_report' >> $GITHUB_OUTPUT
+ echo stdout_report_path="launchable_stdout.log" >> $GITHUB_OUTPUT
+ echo stderr_report_path="launchable_stderr.log" >> $GITHUB_OUTPUT
if: steps.enable-launchable.outputs.enable-launchable
- name: Set environment variables for Launchable
@@ -81,64 +155,159 @@ runs:
: # https://github.com/launchableinc/cli/blob/v1.80.1/launchable/utils/authentication.py#L71
echo "GITHUB_PR_HEAD_SHA=${{ github.event.pull_request.head.sha || github.sha }}" >> $GITHUB_ENV
echo "LAUNCHABLE_TOKEN=${{ inputs.launchable-token }}" >> $GITHUB_ENV
+ : # To prevent a slowdown in CI, disable request retries when the Launchable server is unstable.
+ echo "LAUNCHABLE_SKIP_TIMEOUT_RETRY=1" >> $GITHUB_ENV
+ echo "LAUNCHABLE_COMMIT_TIMEOUT=1" >> $GITHUB_ENV
if: steps.enable-launchable.outputs.enable-launchable
+ - name: Set up path
+ shell: bash
+ working-directory: ${{ inputs.srcdir }}
+ # Since updated PATH variable will be available in only subsequent actions, we need to add the path beforehand.
+ # https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-system-path
+ run: echo "$(python -msite --user-base)/bin" >> $GITHUB_PATH
+ if: >-
+ ${{
+ steps.enable-launchable.outputs.enable-launchable
+ && (startsWith(inputs.os, 'macos')
+ || endsWith(inputs.os, 'ppc64le')
+ || endsWith(inputs.os, 's390x'))
+ }}
+
- name: Set up Launchable
+ id: setup-launchable
shell: bash
working-directory: ${{ inputs.srcdir }}
run: |
set -x
- PATH=$PATH:$(python -msite --user-base)/bin
- echo "PATH=$PATH" >> $GITHUB_ENV
pip install --user launchable
- launchable verify || true
: # The build name cannot include a slash, so we replace the string here.
github_ref="${{ github.ref }}"
github_ref="${github_ref//\//_}"
: # With the --name option, we need to configure a unique identifier for this build.
: # To avoid setting the same build name as the CI which runs on other branches, we use the branch name here.
- : #
- : # FIXME: Need to fix `WARNING: Failed to process a change to a file`.
- : # https://github.com/launchableinc/cli/issues/786
- launchable record build --name ${github_ref}_${GITHUB_PR_HEAD_SHA}
- echo "TESTS=${TESTS} --launchable-test-reports=${{ inputs.report-path }}" >> $GITHUB_ENV
- if: steps.enable-launchable.outputs.enable-launchable
-
- - name: Variables to report Launchable
- id: variables
- shell: bash
- run: |
- set -x
- : # flavor
+ build_name="${github_ref}_${GITHUB_PR_HEAD_SHA}"
test_opts="${{ inputs.test-opts }}"
test_opts="${test_opts// /}"
test_opts="${test_opts//=/:}"
- echo test-opts="$test_opts" >> $GITHUB_OUTPUT
- : # report-path from srcdir
- if [ "${srcdir}" = "${{ github.workspace }}" ]; then
- dir=
- else
- # srcdir must be equal to or under workspace
- dir=$(echo ${srcdir:+${srcdir}/} | sed 's:[^/][^/]*/:../:g')
+ test_all_test_suite='test-all'
+ btest_test_suite='btest'
+ test_spec_test_suite='test-spec'
+ if [ "${{ inputs.is-yjit }}" = "true" ]; then
+ test_all_test_suite="yjit-${test_all_test_suite}"
+ btest_test_suite="yjit-${btest_test_suite}"
+ test_spec_test_suite="yjit-${test_spec_test_suite}"
+ fi
+ # launchable_setup target var -- refers ${target} prefixed variables
+ launchable_setup() {
+ local target=$1 session
+ eval [ "\${${target}_enabled}" = "true" ] || return
+ eval local suite=\${${target}_test_suite}
+ session=$(launchable record session \
+ --build "${build_name}" \
+ --observation \
+ --flavor os="${{ inputs.os }}" \
+ --flavor test_task="${{ inputs.test-task }}" \
+ --flavor test_opts="${test_opts}" \
+ --flavor workflow="${{ github.workflow }}" \
+ --test-suite ${suite} \
+ )
+ echo "${target}_session=${session}" >> $GITHUB_OUTPUT
+ }
+
+ launchable record build --name "${build_name}"
+ if launchable_setup test_all; then
+ echo "TESTS=${TESTS:+$TESTS }--launchable-test-reports=${test_all_report_file}" >> $GITHUB_ENV
fi
- report_path="${dir}${builddir:+${builddir}/}${report_path}"
- echo report-path="${report_path}" >> $GITHUB_OUTPUT
+ if launchable_setup btest; then
+ echo "BTESTS=${BTESTS:+$BTESTS }--launchable-test-reports=${btest_report_file}" >> $GITHUB_ENV
+ fi
+ if launchable_setup test_spec; then
+ echo "SPECOPTS=${SPECOPTS:$SPECOPTS }--launchable-test-reports=${test_spec_report_dir}" >> $GITHUB_ENV
+ echo test_spec_enabled=true >> $GITHUB_OUTPUT
+ fi
+
+ echo launchable_setup_dir=$(pwd) >> $GITHUB_OUTPUT
if: steps.enable-launchable.outputs.enable-launchable
env:
- srcdir: ${{ inputs.srcdir }}
- builddir: ${{ inputs.builddir }}
- report_path: ${{ inputs.report-path }}
+ test_all_enabled: ${{ steps.global.outputs.test_all_enabled }}
+ btest_enabled: ${{ steps.global.outputs.btest_enabled }}
+ test_spec_enabled: ${{ steps.global.outputs.test_spec_enabled }}
+ test_all_report_file: ${{ steps.global.outputs.test_all_report_file }}
+ btest_report_file: ${{ steps.global.outputs.btest_report_file }}
+ test_spec_report_dir: ${{ steps.global.outputs.test_spec_report_dir }}
+
+ - name: make test-spec report directory in build directory
+ shell: bash
+ working-directory: ${{ inputs.builddir }}
+ run: mkdir "${test_spec_report_dir}"
+ if: ${{ steps.setup-launchable.outputs.test_spec_enabled == 'true' }}
+ env:
+ test_spec_report_dir: ${{ steps.global.outputs.test_spec_report_dir }}
+
+ - name: Clean up test results in Launchable
+ uses: gacts/run-and-post-run@674528335da98a7afc80915ff2b4b860a0b3553a # v1.4.0
+ with:
+ shell: bash
+ working-directory: ${{ inputs.builddir }}
+ post: |
+ rm -f "${test_all_report_file}"
+ rm -f "${btest_report_file}"
+ rm -fr "${test_spec_report_dir}"
+ rm -f launchable_stdout.log
+ rm -f launchable_stderr.log
+ if: always() && steps.setup-launchable.outcome == 'success'
+ env:
+ test_all_report_file: ${{ steps.global.outputs.test_all_report_file }}
+ btest_report_file: ${{ steps.global.outputs.btest_report_file }}
+ test_spec_report_dir: ${{ steps.global.outputs.test_spec_report_dir }}
- name: Record test results in Launchable
uses: gacts/run-and-post-run@674528335da98a7afc80915ff2b4b860a0b3553a # v1.4.0
with:
shell: bash
- working-directory: ${{ inputs.srcdir }}
+ working-directory: ${{ inputs.builddir }}
post: |
- : # record
- launchable record tests --flavor os=${{ inputs.os }} --flavor test_task=${{ matrix.test_task }} --flavor test_opts=${test_opts} raw ${report_path}
- rm -f ${report_path}
- if: ${{ always() && steps.enable-launchable.outputs.enable-launchable }}
+ if [[ "${test_all_enabled}" = "true" ]]; then \
+ launchable record attachment \
+ --session "${test_all_session}" \
+ "${stdout_report_path}" \
+ "${stderr_report_path}"; \
+ launchable record tests \
+ --session "${test_all_session}" \
+ raw "${test_all_report_file}" || true; \
+ fi
+
+ if [[ "${btest_enabled}" = "true" ]]; then \
+ launchable record attachment \
+ --session "${btest_session}" \
+ "${stdout_report_path}" \
+ "${stderr_report_path}"; \
+ launchable record tests \
+ --session "${btest_session}" \
+ raw "${btest_report_file}" || true; \
+ fi
+
+ if [[ "${test_spec_enabled}" = "true" ]]; then \
+ launchable record attachment \
+ --session "${test_spec_session}" \
+ "${stdout_report_path}" \
+ "${stderr_report_path}"; \
+ launchable record tests \
+ --session "${test_spec_session}" \
+ raw ${test_spec_report_dir}/* || true; \
+ fi
+ if: ${{ always() && steps.setup-launchable.outcome == 'success' }}
env:
- test_opts: ${{ steps.variables.outputs.test-opts }}
- report_path: ${{ steps.variables.outputs.report-path }}
+ test_all_report_file: ${{ steps.global.outputs.test_all_report_file }}
+ btest_report_file: ${{ steps.global.outputs.btest_report_file }}
+ test_spec_report_dir: ${{ steps.global.outputs.test_spec_report_dir }}
+ test_all_enabled: ${{ steps.global.outputs.test_all_enabled }}
+ btest_enabled: ${{ steps.global.outputs.btest_enabled }}
+ test_spec_enabled: ${{ steps.global.outputs.test_spec_enabled }}
+ test_all_session: ${{ steps.setup-launchable.outputs.test_all_session }}
+ btest_session: ${{ steps.setup-launchable.outputs.btest_session }}
+ test_spec_session: ${{ steps.setup-launchable.outputs.test_spec_session }}
+ stdout_report_path: ${{ steps.global.outputs.stdout_report_path }}
+ stderr_report_path: ${{ steps.global.outputs.stderr_report_path }}
+ LAUNCHABLE_SETUP_DIR: ${{ steps.setup-launchable.outputs.launchable_setup_dir }}
diff --git a/.github/actions/setup/directories/action.yml b/.github/actions/setup/directories/action.yml
index 5264e0e969..0e8ffd59ef 100644
--- a/.github/actions/setup/directories/action.yml
+++ b/.github/actions/setup/directories/action.yml
@@ -19,6 +19,13 @@ inputs:
Where binaries and other generated contents go. This will be
created if absent.
+ make-command:
+ required: false
+ type: string
+ default: 'make'
+ description: >-
+ The command of `make`.
+
makeup:
required: false
type: boolean
@@ -76,7 +83,7 @@ runs:
shell: bash
run: |
echo "git=`command -v git`" >> "$GITHUB_OUTPUT"
- echo "sudo=`command -v sudo`" >> "$GITHUB_OUTPUT"
+ echo "sudo=`sudo true && command -v sudo`" >> "$GITHUB_OUTPUT"
echo "autoreconf=`command -v autoreconf`" >> "$GITHUB_OUTPUT"
- if: steps.which.outputs.git
@@ -88,20 +95,20 @@ runs:
git config --global init.defaultBranch garbage
- if: inputs.checkout
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
path: ${{ inputs.srcdir }}
fetch-depth: ${{ inputs.fetch-depth }}
- - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ - uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2
with:
path: ${{ inputs.srcdir }}/.downloaded-cache
- key: downloaded-cache
+ key: ${{ runner.os }}-${{ runner.arch }}-downloaded-cache
- if: steps.which.outputs.autoreconf
shell: bash
working-directory: ${{ inputs.srcdir }}
- run: ./autogen.sh
+ run: ./autogen.sh --install
# This is for MinGW.
- if: runner.os == 'Windows'
@@ -110,7 +117,7 @@ runs:
- if: runner.os == 'Linux'
shell: bash
- run: echo "GNUMAKEFLAGS=-sj$((1 + $(nproc --all)))" >> "$GITHUB_ENV"
+ run: echo "GNUMAKEFLAGS=-sj$((1 + $(nproc)))" >> "$GITHUB_ENV"
# macOS' GNU make is so old that they doesn't understand `GNUMAKEFLAGS`.
- if: runner.os == 'macOS'
@@ -121,24 +128,35 @@ runs:
shell: bash
working-directory: ${{ inputs.srcdir }}
run: |
- touch config.status
- touch .rbconfig.time
- sed -f tool/prereq.status template/Makefile.in > Makefile
- sed -f tool/prereq.status template/GNUmakefile.in > GNUmakefile
+ touch config.status .rbconfig.time
+ for mk in Makefile GNUmakefile; do
+ sed -f tool/prereq.status template/$mk.in > $mk
+ done
make up
# Cleanup, runs even on failure
- if: always() && inputs.makeup
shell: bash
working-directory: ${{ inputs.srcdir }}
- run: rm -f config.status Makefile rbconfig.rb .rbconfig.time
+ run: |
+ rm -f config.status .rbconfig.time \
+ Makefile GNUmakefile uncommon.mk enc.mk noarch-fake.rb
- if: steps.which.outputs.sudo
shell: bash
run: |
sudo chmod -R go-w /usr/share
chmod -v go-w $HOME $HOME/.config || :
- sudo bash -c 'IFS=:; for d in '"$PATH"'; do chmod -v go-w $d; done' || :
+ declare -a dirs # -A is not supported by old bash, e.g. macos
+ SAVE_IFS="$IFS" IFS=:; set $PATH
+ for d do
+ while [ -d "$d" ]; do
+ case "$IFS${dirs[*]}$IFS" in *"$IFS$d$IFS"*) ;; *) dirs+=("$d");; esac
+ d="${d%/*}"
+ done
+ done
+ IFS="$SAVE_IFS"
+ sudo chmod -v go-w "${dirs[@]}" || :
- if: inputs.dummy-files == 'true'
shell: bash
@@ -158,13 +176,13 @@ runs:
shell: bash
id: clean
run: |
- echo distclean='make -C ${{ inputs.builddir }} distclean' >> $GITHUB_OUTPUT
+ echo distclean='cd ${{ inputs.builddir }} && ${{ inputs.make-command }} distclean' >> $GITHUB_OUTPUT
echo remained-files='find ${{ inputs.builddir }} -ls' >> $GITHUB_OUTPUT
[ "${{ inputs.builddir }}" = "${{ inputs.srcdir }}" ] ||
echo final='rmdir ${{ inputs.builddir }}' >> $GITHUB_OUTPUT
- name: clean
- uses: gacts/run-and-post-run@7aec950f3b114c4fcf6012070c3709ecff0eb6f8 # v1.4.0
+ uses: gacts/run-and-post-run@81b6ce503cde93862cec047c54652e45c5dca991 # v1.4.3
with:
working-directory:
post: |
@@ -172,3 +190,5 @@ runs:
${{ steps.clean.outputs.distclean }}
${{ steps.clean.outputs.remained-files }}
${{ steps.clean.outputs.final }}
+ # rmdir randomly fails due to launchable files
+ continue-on-error: true
diff --git a/.github/actions/setup/macos/action.yml b/.github/actions/setup/macos/action.yml
index b96e959aa6..d0072ff828 100644
--- a/.github/actions/setup/macos/action.yml
+++ b/.github/actions/setup/macos/action.yml
@@ -13,16 +13,17 @@ runs:
- name: brew
shell: bash
run: |
- brew install --quiet gmp libffi openssl@1.1 zlib autoconf automake libtool
+ brew install --quiet jemalloc gmp libffi openssl@3 zlib autoconf automake libtool
- name: Set ENV
shell: bash
run: |
- for lib in gmp; do
- ruby_configure_args="${ruby_configure_args:+$ruby_configure_args }--with-${lib%@*}-dir=$(brew --prefix $lib)"
- done
- for lib in openssl@1.1; do
- CONFIGURE_ARGS="${CONFIGURE_ARGS:+$CONFIGURE_ARGS }--with-${lib%@*}-dir=$(brew --prefix $lib)"
- done
- echo ruby_configure_args="${ruby_configure_args}" >> $GITHUB_ENV
- echo CONFIGURE_ARGS="${CONFIGURE_ARGS}" >> $GITHUB_ENV
+ dir_config() {
+ local args=() lib var="$1"; shift
+ for lib in "$@"; do
+ args+=("--with-${lib%@*}-dir=$(brew --prefix $lib)")
+ done
+ echo "$var=${args[*]}" >> $GITHUB_ENV
+ }
+ dir_config ruby_configure_args gmp
+ dir_config CONFIGURE_ARGS openssl@3
diff --git a/.github/actions/slack/action.yml b/.github/actions/slack/action.yml
index f0481f5bc2..4a398da1d1 100644
--- a/.github/actions/slack/action.yml
+++ b/.github/actions/slack/action.yml
@@ -9,7 +9,7 @@ inputs:
required: true
description: >-
The URL to post the payload. This is an input because it tends
- to be stored in a secrets valut and a composite action cannot
+ to be stored in a secrets vault and a composite action cannot
look into one.
label:
@@ -18,6 +18,17 @@ inputs:
Human-readable description of the run, something like "DEBUG=1".
This need not be unique among runs.
+ event_name:
+ required: false
+ default: 'push'
+ description: >-
+ Target event to trigger notification. Notify only push by default.
+
+ extra_channel_id:
+ required: false
+ description: >-
+ Slack channel ID to notify besides #alerts and #alerts-emoji.
+
outputs: {} # Nothing?
runs:
@@ -33,7 +44,8 @@ runs:
"url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
"commit": "${{ github.sha }}",
"branch": "${{ github.ref_name }}"
+ ${{ inputs.extra_channel_id && format(', "extra_channel_id": "{0}"', inputs.extra_channel_id) }}
}
env:
SLACK_WEBHOOK_URL: ${{ inputs.SLACK_WEBHOOK_URL }}
- if: ${{github.event_name == 'push' && startsWith(github.repository, 'ruby/')}}
+ if: ${{ github.event_name == inputs.event_name && startsWith(github.repository, 'ruby/') }}
diff --git a/.github/auto_request_review.yml b/.github/auto_request_review.yml
index 8726df577d..38496d5ceb 100644
--- a/.github/auto_request_review.yml
+++ b/.github/auto_request_review.yml
@@ -1,13 +1,20 @@
files:
- 'yjit*': [team:yjit]
- 'yjit/**/*': [team:yjit]
+ 'yjit*': [team:jit]
+ 'yjit/**/*': [team:jit]
'yjit/src/cruby_bindings.inc.rs': []
- 'doc/yjit/*': [team:yjit]
- 'bootstraptest/test_yjit*': [team:yjit]
- 'test/ruby/test_yjit*': [team:yjit]
+ 'bootstraptest/test_yjit*': [team:jit]
+ 'test/ruby/test_yjit*': [team:jit]
+ 'zjit*': [team:jit]
+ 'zjit/**/*': [team:jit]
+ 'zjit/src/cruby_bindings.inc.rs': []
+ 'test/ruby/test_zjit*': [team:jit]
+ 'defs/jit.mk': [team:jit]
+ 'tool/zjit_bisect.rb': [team:jit]
+ 'doc/jit/*': [team:jit]
+ # Skip github workflow files because the team don't necessarily need to review dependabot updates for GitHub Actions. It's noisy in notifications, and they're auto-merged anyway.
options:
ignore_draft: true
# This currently doesn't work as intended. We want to skip reviews when only
# cruby_bingings.inc.rs is modified, but this skips reviews even when other
- # yjit files are modified as well. To be enabled after fixing the behavior.
+ # files are modified as well. To be enabled after fixing the behavior.
#last_files_match_only: true
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 426893be2a..2c2982d1d4 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -16,3 +16,7 @@ updates:
directory: '/yjit'
schedule:
interval: 'daily'
+ - package-ecosystem: 'vcpkg'
+ directory: '/'
+ schedule:
+ interval: 'daily'
diff --git a/.github/labeler.yml b/.github/labeler.yml
new file mode 100644
index 0000000000..e81aed8e98
--- /dev/null
+++ b/.github/labeler.yml
@@ -0,0 +1,6 @@
+Documentation:
+- changed-files:
+ - all-globs-to-all-files: doc/**
+
+Backport:
+- base-branch: 'ruby_3_\d'
diff --git a/.github/workflows/annocheck.yml b/.github/workflows/annocheck.yml
index 4d9bd18236..899d601aef 100644
--- a/.github/workflows/annocheck.yml
+++ b/.github/workflows/annocheck.yml
@@ -39,11 +39,9 @@ jobs:
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
- || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.title, 'Document')
- || contains(github.event.pull_request.labels.*.name, 'Document')
- || (github.event_name == 'push' && github.actor == 'dependabot[bot]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
)}}
env:
@@ -63,7 +61,7 @@ jobs:
- run: id
working-directory:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
sparse-checkout-cone-mode: false
sparse-checkout: /.github
@@ -74,9 +72,9 @@ jobs:
builddir: build
makeup: true
- - uses: ruby/setup-ruby@0cde4689ba33c09f1b890c1725572ad96751a3fc # v1.178.0
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0
with:
- ruby-version: '3.0'
+ ruby-version: '3.1'
bundler: none
# Minimal flags to pass the check.
diff --git a/.github/workflows/auto_request_review.yml b/.github/workflows/auto_request_review.yml
index ca27244b46..207315a084 100644
--- a/.github/workflows/auto_request_review.yml
+++ b/.github/workflows/auto_request_review.yml
@@ -2,6 +2,7 @@ name: Auto Request Review
on:
pull_request_target:
types: [opened, ready_for_review, reopened]
+ branches: [master]
permissions:
contents: read
@@ -16,4 +17,4 @@ jobs:
uses: necojackarc/auto-request-review@e89da1a8cd7c8c16d9de9c6e763290b6b0e3d424 # v0.13.0
with:
# scope: public_repo
- token: ${{ secrets.MATZBOT_GITHUB_TOKEN }}
+ token: ${{ secrets.MATZBOT_AUTO_REQUEST_REVIEW_TOKEN }}
diff --git a/.github/workflows/auto_review_pr.yml b/.github/workflows/auto_review_pr.yml
new file mode 100644
index 0000000000..ad0e63ba12
--- /dev/null
+++ b/.github/workflows/auto_review_pr.yml
@@ -0,0 +1,33 @@
+name: Auto Review PR
+on:
+ pull_request_target:
+ types: [opened, ready_for_review, reopened]
+ branches: [master]
+
+permissions:
+ contents: read
+
+jobs:
+ auto-review-pr:
+ name: Auto Review PR
+ runs-on: ubuntu-latest
+ if: ${{ github.repository == 'ruby/ruby' && github.base_ref == 'master' }}
+
+ permissions:
+ pull-requests: write
+ contents: read
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v6.0.1
+
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0
+ with:
+ ruby-version: '3.4'
+ bundler: none
+
+ - name: Auto Review PR
+ run: ruby tool/auto_review_pr.rb "$GITHUB_PR_NUMBER"
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ GITHUB_PR_NUMBER: ${{ github.event.pull_request.number }}
diff --git a/.github/workflows/baseruby.yml b/.github/workflows/baseruby.yml
index 0acc87fa29..d3e734f885 100644
--- a/.github/workflows/baseruby.yml
+++ b/.github/workflows/baseruby.yml
@@ -30,33 +30,30 @@ jobs:
baseruby:
name: BASERUBY
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
- || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.title, 'Document')
- || contains(github.event.pull_request.labels.*.name, 'Document')
- || (github.event_name == 'push' && github.actor == 'dependabot[bot]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
)}}
strategy:
matrix:
ruby:
- - ruby-3.0
- ruby-3.1
- ruby-3.2
- ruby-3.3
steps:
- - uses: ruby/setup-ruby@0cde4689ba33c09f1b890c1725572ad96751a3fc # v1.178.0
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0
with:
ruby-version: ${{ matrix.ruby }}
bundler: none
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/actions/setup/ubuntu
diff --git a/.github/workflows/bundled_gems.yml b/.github/workflows/bundled_gems.yml
index 6f06451a99..59f64e8312 100644
--- a/.github/workflows/bundled_gems.yml
+++ b/.github/workflows/bundled_gems.yml
@@ -1,5 +1,8 @@
name: bundled_gems
+env:
+ UPDATE_ENABLED: true
+
on:
push:
branches: ['master']
@@ -31,13 +34,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
- token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
+ token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_AUTO_UPDATE_TOKEN || secrets.GITHUB_TOKEN }}
- uses: ./.github/actions/setup/directories
with:
- # Skip overwriting MATZBOT_GITHUB_TOKEN
+ # Skip overwriting MATZBOT_AUTO_UPDATE_TOKEN
checkout: '' # false (ref: https://github.com/actions/runner/issues/2238)
- name: Set ENV
@@ -46,15 +49,17 @@ jobs:
- name: Download previous gems list
run: |
- data=bundled_gems.json
mkdir -p .downloaded-cache
- ln -s .downloaded-cache/$data .
- curl -O -R -z ./$data https://stdgems.org/$data
+ for data in bundled_gems.json default_gems.json; do
+ ln -s .downloaded-cache/$data .
+ curl -O -R -z ./$data https://stdgems.org/$data
+ done
- name: Update bundled gems list
id: bundled_gems
run: |
ruby -i~ tool/update-bundled_gems.rb gems/bundled_gems >> $GITHUB_OUTPUT
+ if: ${{ env.UPDATE_ENABLED == 'true' }}
- name: Update spec/bundler/support/builders.rb
run: |
@@ -62,10 +67,12 @@ jobs:
rake_version = File.read("gems/bundled_gems")[/^rake\s+(\S+)/, 1]
print ARGF.read.sub(/^ *def rake_version\s*\K".*?"/) {rake_version.dump}
shell: ruby -i~ {0} spec/bundler/support/builders.rb
+ if: ${{ env.UPDATE_ENABLED == 'true' }}
- name: Maintain updated gems list in NEWS
run: |
ruby tool/update-NEWS-gemlist.rb bundled
+ if: ${{ env.UPDATE_ENABLED == 'true' }}
- name: Check diffs
id: diff
@@ -81,6 +88,67 @@ jobs:
echo gems=$gems >> $GITHUB_OUTPUT
echo update=${news:-$gems} >> $GITHUB_OUTPUT
+ - name: Commit
+ id: commit
+ run: |
+ git pull --ff-only origin ${GITHUB_REF#refs/heads/}
+ message="Update bundled gems list"
+ if [ -z "${gems}" ]; then
+ git commit --message="[DOC] ${message} at ${GITHUB_SHA:0:30}"
+ else
+ git commit --message="${message} as of ${TODAY}"
+ fi
+ env:
+ TODAY: ${{ steps.bundled_gems.outputs.latest_date || env.TODAY }}
+ EMAIL: svn-admin@ruby-lang.org
+ GIT_AUTHOR_NAME: git
+ GIT_COMMITTER_NAME: git
+ gems: ${{ steps.diff.outputs.gems }}
+ if: ${{ steps.diff.outputs.update }}
+
+ - name: Development revision of bundled gems
+ run: |
+ #!ruby
+ file = "gems/bundled_gems"
+
+ SECONDS_IN_DAY = 86400
+ today = Time.new("#{ENV['TODAY']}Z")
+ if !(december = today.month == 12)
+ days = 30
+ elsif (days = 26 - today.day).positive?
+ days += 4
+ else
+ puts "::info:: just after released"
+ exit
+ end
+
+ since = "#{today.year-1}-12-26"
+ ref = ENV['GITHUB_REF']
+ puts "::group::\e[94mfetching \e[1m#{file}\e[22m since \e[1m#{since}\e[22m from \e[1m#{ref}\e[m"
+ system(*%W[git fetch --shallow-since=#{since} --no-tags origin #{ref}], exception: true)
+ puts "::endgroup::"
+
+ puts "\e[94mchecking development version bundled gems older than \e[1m#{days}\e[22m days\e[m"
+ limit = today.to_i - days * SECONDS_IN_DAY
+ old = 0
+ IO.popen(%W"git blame --line-porcelain -- #{file}") do |blame|
+ while head = blame.gets("\n\t") and s = blame.gets
+ next unless (gem = s.split(/\s+|#.*/)).size > 3
+ time = head[/^committer-time \K\d+/].to_i
+ next if (d = limit - time) <= 0
+ d /= SECONDS_IN_DAY
+ line = head[/\A\h+ \d+ \K\d+/].to_i
+ level = if d < days; 'warning'; else old += 1; 'error'; end
+ d += days
+ puts "::#{level} file=#{file},line=#{line},title=Older than #{d} days::#{gem[0]} #{gem[3]}"
+ end
+ end
+ abort "::error title=Too long-standing gems::The release comes soon." if december and old.nonzero?
+ shell: ruby {0}
+ env:
+ file: ${{ steps.logs.outputs.file }}
+ days: ${{ steps.logs.outputs.days }}
+
- name: Install libraries
uses: ./.github/actions/setup/ubuntu
if: ${{ steps.diff.outputs.gems }}
@@ -106,27 +174,14 @@ jobs:
TEST_BUNDLED_GEMS_ALLOW_FAILURES: ''
if: ${{ steps.diff.outputs.gems }}
- - name: Commit
+ - name: Push
run: |
- git pull --ff-only origin ${GITHUB_REF#refs/heads/}
- message="Update bundled gems list"
- if [ -z "${gems}" ]; then
- git commit --message="${message} at ${GITHUB_SHA:0:30} [ci skip]"
- else
- git commit --message="${message} as of ${TODAY}"
- fi
git push origin ${GITHUB_REF#refs/heads/}
- env:
- TODAY: ${{ steps.bundled_gems.outputs.latest_date || env.TODAY }}
- EMAIL: svn-admin@ruby-lang.org
- GIT_AUTHOR_NAME: git
- GIT_COMMITTER_NAME: git
- gems: ${{ steps.diff.outputs.gems }}
if: >-
${{
github.repository == 'ruby/ruby' &&
!startsWith(github.event_name, 'pull') &&
- steps.diff.outputs.update
+ steps.commit.outcome == 'success'
}}
- uses: ./.github/actions/slack
diff --git a/.github/workflows/check_dependencies.yml b/.github/workflows/check_dependencies.yml
index 01ed281d68..c5dec65e48 100644
--- a/.github/workflows/check_dependencies.yml
+++ b/.github/workflows/check_dependencies.yml
@@ -9,13 +9,6 @@ on:
- '**/.document'
- '.*.yml'
pull_request:
- paths-ignore:
- - 'doc/**'
- - '**/man/*'
- - '**.md'
- - '**.rdoc'
- - '**/.document'
- - '.*.yml'
merge_group:
concurrency:
@@ -27,25 +20,17 @@ permissions:
jobs:
update-deps:
+ name: Dependency checks
+
strategy:
matrix:
- os: [ubuntu-20.04]
+ os: [ubuntu-latest]
fail-fast: true
runs-on: ${{ matrix.os }}
- if: >-
- ${{!(false
- || contains(github.event.head_commit.message, '[DOC]')
- || contains(github.event.head_commit.message, 'Document')
- || contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.title, 'Document')
- || contains(github.event.pull_request.labels.*.name, 'Document')
- || (github.event_name == 'push' && github.actor == 'dependabot[bot]')
- )}}
-
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: ./.github/actions/setup/ubuntu
if: ${{ contains(matrix.os, 'ubuntu') }}
@@ -55,17 +40,15 @@ jobs:
- uses: ./.github/actions/setup/directories
- - uses: ruby/setup-ruby@0cde4689ba33c09f1b890c1725572ad96751a3fc # v1.178.0
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0
with:
- ruby-version: '3.0'
+ ruby-version: '3.1'
bundler: none
- name: Run configure
run: ./configure -C --disable-install-doc --disable-rubygems --with-gcc 'optflags=-O0' 'debugflags=-save-temps=obj -g'
- - run: make all golf
-
- - run: ruby tool/update-deps --fix
+ - run: make fix-depends
- run: git diff --no-ext-diff --ignore-submodules --exit-code
diff --git a/.github/workflows/check_misc.yml b/.github/workflows/check_misc.yml
index f26319f448..2a2bd1df53 100644
--- a/.github/workflows/check_misc.yml
+++ b/.github/workflows/check_misc.yml
@@ -18,24 +18,25 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
- token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
+ token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_AUTO_UPDATE_TOKEN || secrets.GITHUB_TOKEN }}
- uses: ./.github/actions/setup/directories
with:
makeup: true
- # Skip overwriting MATZBOT_GITHUB_TOKEN
+ # Skip overwriting MATZBOT_AUTO_UPDATE_TOKEN
checkout: '' # false (ref: https://github.com/actions/runner/issues/2238)
- - name: Check if C-sources are US-ASCII
+ - name: Check for code styles
run: |
- grep -r -n --include='*.[chyS]' --include='*.asm' $'[^\t-~]' -- . && exit 1 || :
-
- - name: Check for trailing spaces
- run: |
- git grep -I -n $'[\t ]$' -- '*.rb' '*.[chy]' '*.rs' '*.yml' && exit 1 || :
- git grep -n $'^[\t ][\t ]*$' -- '*.md' && exit 1 || :
+ set -x
+ ruby tool/auto-style.rb "$GITHUB_OLD_SHA" "$GITHUB_NEW_SHA"
+ env:
+ GITHUB_OLD_SHA: ${{ github.event.pull_request.base.sha }}
+ GITHUB_NEW_SHA: ${{ github.event.pull_request.merge_commit_sha }}
+ # Skip 'push' events because post_push.yml fixes them on push
+ if: ${{ github.repository == 'ruby/ruby' && startsWith(github.event_name, 'pull') }}
- name: Check for bash specific substitution in configure.ac
run: |
@@ -52,65 +53,74 @@ jobs:
exit $fail
working-directory: include
- - id: gems
- run: true
- if: ${{ github.ref == 'refs/heads/master' }}
-
- - name: Download previous gems list
+ - id: now
run: |
- data=default_gems.json
- mkdir -p .downloaded-cache
- ln -s .downloaded-cache/$data .
- curl -O -R -z ./$data https://stdgems.org/$data
- if: ${{ steps.gems.outcome == 'success' }}
+ date +"mon=%-m"%n"day=%-d" >> $GITHUB_OUTPUT
+ env:
+ TZ: Tokyo/Asia
- - name: Make default gems list
+ - id: deprecation
run: |
- #!ruby
- require 'rubygems'
- $:.unshift "lib"
- rgver = File.foreach("lib/rubygems.rb") do |line|
- break $1 if /^\s*VERSION\s*=\s*"([^"]+)"/ =~ line
- end
- gems = Dir.glob("{ext,lib}/**/*.gemspec").map do |f|
- spec = Gem::Specification.load(f)
- "#{spec.name} #{spec.version}"
- end.sort
- File.open("gems/default_gems", "w") do |f|
- f.puts "RubyGems #{rgver}"
- f.puts gems
- end
- shell: ruby --disable=gems {0}
- if: ${{ steps.gems.outcome == 'success' }}
-
- - name: Maintain updated gems list in NEWS
+ eval $(sed -n 's/^#define RUBY_API_VERSION_\(MAJOR\|MINOR\) /\1=/p' include/ruby/version.h)
+ if git --no-pager grep --color -o 'rb_warn_deprecated_to_remove_at('$MAJOR'\.'$MINOR',.*' -- '*.c' >&2; then
+ false
+ else
+ true
+ fi
+ continue-on-error: ${{ steps.now.outputs.mon < 12 }}
+
+ - name: Check if to generate documents
+ id: rdoc
run: |
- ruby tool/update-NEWS-gemlist.rb default
- if: ${{ steps.gems.outcome == 'success' }}
+ set -- $(sed 's/#.*//;/^rdoc /!d' gems/bundled_gems)
+ { echo version=$2; echo ref=$4; } >> $GITHUB_OUTPUT
+ echo RDOC='ruby -W0 --disable-gems tool/rdoc-srcdir -q' >> $GITHUB_ENV
- - name: Check diffs
- id: diff
+ - name: Checkout rdoc
+ uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ repository: ruby/rdoc
+ ref: ${{ steps.rdoc.outputs.ref }}
+ path: .bundle/gems/rdoc-${{ steps.rdoc.outputs.version }}
+ if: ${{ steps.rdoc.outputs.ref != '' }}
+
+ - name: Generate rdoc
+ run: |
+ set -x
+ gempath=$(ruby -e 'print Gem.user_dir, "/bin"')
+ PATH=$gempath:$PATH
+ gem install --user bundler
+ bundle config --local path vendor/bundle
+ bundle install --jobs 4
+ bundle exec rake generate
+ working-directory: .bundle/gems/rdoc-${{ steps.rdoc.outputs.version }}
+ if: ${{ steps.rdoc.outputs.ref != '' }}
+
+ - name: Core docs coverage
run: |
- git diff --color --no-ext-diff --ignore-submodules --exit-code NEWS.md ||
- echo update=true >> $GITHUB_OUTPUT
- if: ${{ steps.gems.outcome == 'success' }}
+ $RDOC -C -x ^ext -x ^lib .
- - name: Commit
+ - name: Generate docs
+ id: docs
run: |
- git pull --ff-only origin ${GITHUB_REF#refs/heads/}
- git commit --message="Update default gems list at ${GITHUB_SHA:0:30} [ci skip]" NEWS.md
- git push origin ${GITHUB_REF#refs/heads/}
- env:
- EMAIL: svn-admin@ruby-lang.org
- GIT_AUTHOR_NAME: git
- GIT_COMMITTER_NAME: git
+ $RDOC --op html .
+ echo htmlout=ruby-html-${GITHUB_SHA:0:10} >> $GITHUB_OUTPUT
+ # Generate only when document commit/PR
if: >-
- ${{
- github.repository == 'ruby/ruby' &&
- !startsWith(github.event_name, 'pull') &&
- steps.diff.outputs.update
+ ${{false
+ || contains(github.event.head_commit.message, '[ruby/rdoc]')
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
}}
+ - name: Upload docs
+ uses: actions/upload-artifact@v6.0.0
+ with:
+ path: html
+ name: ${{ steps.docs.outputs.htmlout }}
+ if: ${{ steps.docs.outcome == 'success' }}
+
- uses: ./.github/actions/slack
with:
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 7d12c1fe81..a92c93b476 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -32,7 +32,7 @@ permissions: # added using https://github.com/step-security/secure-workflows
jobs:
analyze:
name: Analyze
- runs-on: ${{ matrix.os }}
+ runs-on: ubuntu-latest
permissions:
actions: read # for github/codeql-action/init to get workflow details
contents: read # for actions/checkout to fetch code
@@ -41,11 +41,9 @@ jobs:
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
- || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.title, 'Document')
- || contains(github.event.pull_request.labels.*.name, 'Document')
- || (github.event_name == 'push' && github.actor == 'dependabot[bot]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
)}}
env:
@@ -56,14 +54,11 @@ jobs:
matrix:
include:
- language: cpp
- os: ubuntu-latest
- # ruby analysis used large memory. We need to use a larger runner.
- language: ruby
- os: ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'ubuntu-latest' }}
steps:
- name: Checkout repository
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Install libraries
if: ${{ contains(matrix.os, 'macos') }}
@@ -80,15 +75,17 @@ jobs:
run: sudo rm /usr/lib/ruby/vendor_ruby/rubygems/defaults/operating_system.rb
- name: Initialize CodeQL
- uses: github/codeql-action/init@9fdb3e49720b44c48891d036bb502feb25684276 # v3.25.6
+ uses: github/codeql-action/init@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7
with:
languages: ${{ matrix.language }}
+ trap-caching: false
+ debug: true
- name: Autobuild
- uses: github/codeql-action/autobuild@9fdb3e49720b44c48891d036bb502feb25684276 # v3.25.6
+ uses: github/codeql-action/autobuild@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@9fdb3e49720b44c48891d036bb502feb25684276 # v3.25.6
+ uses: github/codeql-action/analyze@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7
with:
category: '/language:${{ matrix.language }}'
upload: False
@@ -118,7 +115,7 @@ jobs:
continue-on-error: true
- name: Upload SARIF
- uses: github/codeql-action/upload-sarif@9fdb3e49720b44c48891d036bb502feb25684276 # v3.25.6
+ uses: github/codeql-action/upload-sarif@e296a935590eb16afc0c0108289f68c87e2a89a5 # v4.30.7
with:
sarif_file: sarif-results/${{ matrix.language }}.sarif
continue-on-error: true
diff --git a/.github/workflows/compilers.yml b/.github/workflows/compilers.yml
index 85769bd879..8c0ca54e0b 100644
--- a/.github/workflows/compilers.yml
+++ b/.github/workflows/compilers.yml
@@ -24,281 +24,311 @@ 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-18
- append_cc: ''
-
- # -O1 is faster than -O3 in our tests... Majority of time are consumed trying
- # to optimize binaries. Also GitHub Actions run on relatively modern CPUs
- # compared to, say, GCC 4 or Clang 3. We don't specify `-march=native`
- # because compilers tend not understand what the CPU is.
- optflags: '-O1'
-
- # -g0 disables backtraces when SEGV. Do not set that.
- debugflags: '-ggdb3'
-
- default_configure: >-
- --enable-debug-env
- --disable-install-doc
- --with-ext=-test-/cxxanyargs,+
- append_configure: >-
- --without-valgrind
- --without-jemalloc
- --without-gmp
-
- CONFIGURE_TTY: never
- GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
- RUBY_DEBUG: ci rgengc
- RUBY_TESTOPTS: >-
- -q
- --color=always
- --tty=no
-
permissions:
contents: read
+# Each job is split so that they roughly take 30min to run through.
jobs:
- compile:
- strategy:
- fail-fast: false
- matrix:
- env:
- - {}
- entry:
- - { name: gcc-13, env: { default_cc: gcc-13 } }
- - { name: gcc-12, env: { default_cc: gcc-12 } }
- - { name: gcc-11, env: { default_cc: gcc-11 } }
- - { name: gcc-10, env: { default_cc: gcc-10 } }
- - { name: gcc-9, env: { default_cc: gcc-9 } }
- - { name: gcc-8, env: { default_cc: gcc-8 } }
- - { name: gcc-7, env: { default_cc: gcc-7 } }
- - name: 'gcc-13 LTO'
- container: gcc-13
- env:
- default_cc: 'gcc-13 -flto=auto -ffat-lto-objects -Werror=lto-type-mismatch'
- optflags: '-O2'
- shared: disable
- # check: true
- - { name: clang-19, env: { default_cc: clang-19 } }
- - { name: clang-18, env: { default_cc: clang-18 } }
- - { name: clang-17, env: { default_cc: clang-17 } }
- - { name: clang-16, env: { default_cc: clang-16 } }
- - { name: clang-15, env: { default_cc: clang-15 } }
- - { name: clang-14, env: { default_cc: clang-14 } }
- - { name: clang-13, env: { default_cc: clang-13 } }
- - { name: clang-12, env: { default_cc: clang-12 } }
- - { name: clang-11, env: { default_cc: clang-11 } }
- - { name: clang-10, env: { default_cc: clang-10 } }
- # llvm-objcopy<=9 doesn't have --wildcard. It compiles, but leaves Rust symbols in libyjit.o.
- - { name: clang-9, env: { default_cc: clang-9, append_configure: '--disable-yjit' } }
- - { name: clang-8, env: { default_cc: clang-8, append_configure: '--disable-yjit' } }
- - { name: clang-7, env: { default_cc: clang-7, append_configure: '--disable-yjit' } }
- - { name: clang-6.0, env: { default_cc: clang-6.0, append_configure: '--disable-yjit' } }
- - name: 'clang-16 LTO'
- container: clang-16
- env:
- default_cc: 'clang-16 -flto=auto'
- optflags: '-O2'
- shared: disable
- # check: true
-
- - { name: ext/Setup, static-exts: 'etc,json/*,*/escape' }
-
-# - { name: aarch64-linux-gnu, crosshost: aarch64-linux-gnu, container: crossbuild-essential-arm64 }
-# - { name: arm-linux-gnueabi, crosshost: arm-linux-gnueabi }
-# - { name: arm-linux-gnueabihf, crosshost: arm-linux-gnueabihf }
-# - { name: i686-w64-mingw32, crosshost: i686-w64-mingw32 }
-# - { name: powerpc-linux-gnu, crosshost: powerpc-linux-gnu }
-# - { name: powerpc64le-linux-gnu, crosshost: powerpc64le-linux-gnu, container: crossbuild-essential-ppc64el }
-# - { name: s390x-linux-gnu, crosshost: s390x-linux-gnu, container: crossbuild-essential-s390x }
-# - { name: x86_64-w64-mingw32, crosshost: x86_64-w64-mingw32, container: mingw-w64 }
-
- # -Wno-strict-prototypes is necessary with current clang-15 since
- # older autoconf generate functions without prototype and -pedantic
- # now implies strict-prototypes. Disabling the error but leaving the
- # warning generates a lot of noise from use of ANYARGS in
- # rb_define_method() and friends.
- # See: https://github.com/llvm/llvm-project/commit/11da1b53d8cd3507959022cd790d5a7ad4573d94
- - { name: c99, env: { CFLAGS: '-std=c99 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } }
-# - { name: c11, env: { CFLAGS: '-std=c11 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } }
-# - { name: c17, env: { CFLAGS: '-std=c17 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } }
- - { name: c23, env: { CFLAGS: '-std=c2x -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } }
- - { name: c++98, env: { CXXFLAGS: '-std=c++98 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } }
-# - { name: c++11, env: { CXXFLAGS: '-std=c++11 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } }
-# - { name: c++14, env: { CXXFLAGS: '-std=c++14 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } }
-# - { name: c++17, env: { CXXFLAGS: '-std=c++17 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } }
-# - { name: c++20, env: { CXXFLAGS: '-std=c++20 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } }
-# - { name: c++23, env: { CXXFLAGS: '-std=c++23 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } }
- - { name: c++26, env: { CXXFLAGS: '-std=c++26 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } }
-
- - { name: '-O0', env: { optflags: '-O0 -march=x86-64 -mtune=generic' } }
-# - { name: '-O3', env: { optflags: '-O3 -march=x86-64 -mtune=generic' }, check: true }
-
- - { name: gmp, env: { append_configure: '--with-gmp' }, check: true }
- - { name: jemalloc, env: { append_configure: '--with-jemalloc' } }
- - { name: valgrind, env: { append_configure: '--with-valgrind' } }
- - { name: 'coroutine=ucontext', env: { append_configure: '--with-coroutine=ucontext' } }
- - { name: 'coroutine=pthread', env: { append_configure: '--with-coroutine=pthread' } }
- - { name: disable-jit, env: { append_configure: '--disable-yjit --disable-rjit' } }
- - { name: disable-dln, env: { append_configure: '--disable-dln' } }
- - { name: enable-mkmf-verbose, env: { append_configure: '--enable-mkmf-verbose' } }
- - { name: disable-rubygems, env: { append_configure: '--disable-rubygems' } }
- - { name: RUBY_DEVEL, env: { append_configure: '--enable-devel' } }
-
- - { name: OPT_THREADED_CODE=0, env: { cppflags: '-DOPT_THREADED_CODE=0' } }
- - { name: OPT_THREADED_CODE=1, env: { cppflags: '-DOPT_THREADED_CODE=1' } }
- - { name: OPT_THREADED_CODE=2, env: { cppflags: '-DOPT_THREADED_CODE=2' } }
-
- - { name: NDEBUG, env: { cppflags: '-DNDEBUG' } }
- - { name: RUBY_DEBUG, env: { cppflags: '-DRUBY_DEBUG' } }
-# - { name: ARRAY_DEBUG, env: { cppflags: '-DARRAY_DEBUG' } }
-# - { name: BIGNUM_DEBUG, env: { cppflags: '-DBIGNUM_DEBUG' } }
-# - { name: CCAN_LIST_DEBUG, env: { cppflags: '-DCCAN_LIST_DEBUG' } }
-# - { name: CPDEBUG=-1, env: { cppflags: '-DCPDEBUG=-1' } }
-# - { name: ENC_DEBUG, env: { cppflags: '-DENC_DEBUG' } }
-# - { name: GC_DEBUG, env: { cppflags: '-DGC_DEBUG' } }
-# - { name: HASH_DEBUG, env: { cppflags: '-DHASH_DEBUG' } }
-# - { name: ID_TABLE_DEBUG, env: { cppflags: '-DID_TABLE_DEBUG' } }
-# - { name: RGENGC_DEBUG=-1, env: { cppflags: '-DRGENGC_DEBUG=-1' } }
-# - { name: SYMBOL_DEBUG, env: { cppflags: '-DSYMBOL_DEBUG' } }
-
-# - { name: RGENGC_CHECK_MODE, env: { cppflags: '-DRGENGC_CHECK_MODE' } }
-# - { name: VM_CHECK_MODE, env: { cppflags: '-DVM_CHECK_MODE' } }
-
-# - { name: USE_EMBED_CI=0, env: { cppflags: '-DUSE_EMBED_CI=0' } }
- - name: USE_FLONUM=0
- env:
- cppflags: '-DUSE_FLONUM=0'
- # yjit requires FLONUM for the pointer tagging scheme
- append_configure: '--disable-yjit'
-# - { name: USE_GC_MALLOC_OBJ_INFO_DETAILS, env: { cppflags: '-DUSE_GC_MALLOC_OBJ_INFO_DETAILS' } }
-# - { name: USE_LAZY_LOAD, env: { cppflags: '-DUSE_LAZY_LOAD' } }
-# - { name: USE_SYMBOL_GC=0, env: { cppflags: '-DUSE_SYMBOL_GC=0' } }
-# - { name: USE_THREAD_CACHE=0, env: { cppflags: '-DUSE_THREAD_CACHE=0' } }
- - { name: USE_RUBY_DEBUG_LOG=1, env: { cppflags: '-DUSE_RUBY_DEBUG_LOG=1' } }
-# - { name: USE_DEBUG_COUNTER, env: { cppflags: '-DUSE_DEBUG_COUNTER=1', RUBY_DEBUG_COUNTER_DISABLE: '1' } }
- - { name: SHARABLE_MIDDLE_SUBSTRING, env: { cppflags: '-DSHARABLE_MIDDLE_SUBSTRING=1' } }
-
-# - { name: DEBUG_FIND_TIME_NUMGUESS, env: { cppflags: '-DDEBUG_FIND_TIME_NUMGUESS' } }
-# - { name: DEBUG_INTEGER_PACK, env: { cppflags: '-DDEBUG_INTEGER_PACK' } }
-# - { name: ENABLE_PATH_CHECK, env: { cppflags: '-DENABLE_PATH_CHECK' } }
-
-# - { name: GC_DEBUG_STRESS_TO_CLASS, env: { cppflags: '-DGC_DEBUG_STRESS_TO_CLASS' } }
-# - { name: GC_ENABLE_LAZY_SWEEP=0, env: { cppflags: '-DGC_ENABLE_LAZY_SWEEP=0' } }
-# - { name: GC_PROFILE_DETAIL_MEMOTY, env: { cppflags: '-DGC_PROFILE_DETAIL_MEMOTY' } }
-# - { name: GC_PROFILE_MORE_DETAIL, env: { cppflags: '-DGC_PROFILE_MORE_DETAIL' } }
-
-# - { name: CALC_EXACT_MALLOC_SIZE, env: { cppflags: '-DCALC_EXACT_MALLOC_SIZE' } }
-# - { name: MALLOC_ALLOCATED_SIZE_CHECK, env: { cppflags: '-DMALLOC_ALLOCATED_SIZE_CHECK' } }
-
-# - { name: IBF_ISEQ_ENABLE_LOCAL_BUFFER, env: { cppflags: '-DIBF_ISEQ_ENABLE_LOCAL_BUFFER' } }
-
-# - { name: RGENGC_ESTIMATE_OLDMALLOC, env: { cppflags: '-DRGENGC_ESTIMATE_OLDMALLOC' } }
-# - { name: RGENGC_FORCE_MAJOR_GC, env: { cppflags: '-DRGENGC_FORCE_MAJOR_GC' } }
-# - { name: RGENGC_OBJ_INFO, env: { cppflags: '-DRGENGC_OBJ_INFO' } }
-# - { name: RGENGC_PROFILE, env: { cppflags: '-DRGENGC_PROFILE' } }
-
-# - { name: VM_DEBUG_BP_CHECK, env: { cppflags: '-DVM_DEBUG_BP_CHECK' } }
-# - { name: VM_DEBUG_VERIFY_METHOD_CACHE, env: { cppflags: '-DVM_DEBUG_VERIFY_METHOD_CACHE' } }
-
- - { name: enable-yjit, env: { append_configure: '--enable-yjit --disable-rjit' } }
- - { name: enable-rjit, env: { append_configure: '--enable-rjit --disable-yjit' } }
- - { name: YJIT_FORCE_ENABLE, env: { cppflags: '-DYJIT_FORCE_ENABLE' } }
-# - { name: RJIT_FORCE_ENABLE, env: { cppflags: '-DRJIT_FORCE_ENABLE' } }
- - { name: UNIVERSAL_PARSER, env: { cppflags: '-DUNIVERSAL_PARSER' } }
-
- name: ${{ matrix.entry.name }}
-
+ compile-if:
+ name: 'omnibus compilations, trigger'
runs-on: ubuntu-latest
-
- container:
- image: ghcr.io/ruby/ruby-ci-image:${{ matrix.entry.container || matrix.entry.env.default_cc || 'clang-18' }}
- options: --user root
-
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
- || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.title, 'Document')
- || contains(github.event.pull_request.labels.*.name, 'Document')
- || (github.event_name == 'push' && github.actor == 'dependabot[bot]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
)}}
-
- env: ${{ matrix.entry.env || matrix.env }}
-
steps:
- - run: id
+ - run: true
working-directory:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- with:
- sparse-checkout-cone-mode: false
- sparse-checkout: /.github
-
- - uses: ./.github/actions/setup/directories
+ compile1:
+ name: 'omnibus compilations, #1'
+ runs-on: ubuntu-latest
+ needs: compile-if
+ if: ${{ needs.compile-if.result == 'success' }}
+ timeout-minutes: 60
+ services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } }
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
+ # Set fetch-depth: 10 so that Launchable can receive commits information.
+ - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } }
+ - name: 'clang 18 LTO'
+ uses: './.github/actions/compilers'
with:
- srcdir: src
- builddir: build
- makeup: true
- clean: true
-
- - name: Run configure
- run: >
- ../src/configure -C ${default_configure} ${append_configure}
- --${{
- matrix.entry.crosshost && 'host' || 'with-gcc'
- }}=${{
- matrix.entry.crosshost || '"${default_cc}${append_cc:+ $append_cc}"'
- }}
- --${{ matrix.entry.shared || 'enable' }}-shared
-
- - name: Add to ext/Setup
- id: ext-setup
- run: |
- mkdir ext
- cd ext
- for ext in {${{ matrix.entry.static-exts }}}; do
- echo "${ext}"
- done >> Setup
- if: ${{ (matrix.entry.static-exts || '') != '' }}
-
- - name: Clean up ext/Setup
- uses: gacts/run-and-post-run@7aec950f3b114c4fcf6012070c3709ecff0eb6f8 # v1.4.0
+ tag: clang-18
+ with_gcc: 'clang-18 -flto=auto'
+ optflags: '-O2'
+ enable_shared: false
+ timeout-minutes: 30
+ - { uses: './.github/actions/compilers', name: '-O0', with: { optflags: '-O0 -march=x86-64 -mtune=generic' }, timeout-minutes: 5 }
+ # - { uses: './.github/actions/compilers', name: '-O3', with: { optflags: '-O3 -march=x86-64 -mtune=generic', check: true } }
+
+ compile2:
+ name: 'omnibus compilations, #2'
+ runs-on: ubuntu-latest
+ needs: compile-if
+ if: ${{ needs.compile-if.result == 'success' }}
+ timeout-minutes: 60
+ services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } }
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
+ - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } }
+ - name: 'GCC 15 LTO'
+ uses: './.github/actions/compilers'
with:
- shell: bash
- working-directory: build
- post: rm ext/Setup
- if: ${{ steps.ext-setup.outcome == 'success' }}
-
- - run: make showflags
-
- - run: make
-
- - run: make test
-
- - run: make install
- if: ${{ matrix.entry.check }}
-
- - run: make test-tool
- if: ${{ matrix.entry.check }}
-
- - run: make test-all TESTS='-- ruby -ext-'
- if: ${{ matrix.entry.check }}
-
- - run: make test-spec
- env:
- CHECK_LEAKS: true
- if: ${{ matrix.entry.check }}
-
+ tag: gcc-15
+ with_gcc: 'gcc-15 -flto=auto -ffat-lto-objects -Werror=lto-type-mismatch'
+ optflags: '-O2'
+ enable_shared: false
+ timeout-minutes: 10
+ - { uses: './.github/actions/compilers', name: 'ext/Setup', with: { static_exts: 'etc json/* */escape' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GCC 15', with: { tag: 'gcc-15' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GCC 14', with: { tag: 'gcc-14' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GCC 13', with: { tag: 'gcc-13' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GCC 12', with: { tag: 'gcc-12' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GCC 11', with: { tag: 'gcc-11' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GCC 10', with: { tag: 'gcc-10' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GCC 9', with: { tag: 'gcc-9' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GCC 8', with: { tag: 'gcc-8' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GCC 7', with: { tag: 'gcc-7' }, timeout-minutes: 5 }
+
+ compile3:
+ name: 'omnibus compilations, #3'
+ runs-on: ubuntu-latest
+ needs: compile-if
+ if: ${{ needs.compile-if.result == 'success' }}
+ timeout-minutes: 60
+ services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } }
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
+ - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } }
+ - { uses: './.github/actions/compilers', name: 'clang 22', with: { tag: 'clang-22' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 21', with: { tag: 'clang-21' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 20', with: { tag: 'clang-20' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 19', with: { tag: 'clang-19' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 18', with: { tag: 'clang-18' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 17', with: { tag: 'clang-17' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 16', with: { tag: 'clang-16' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 15', with: { tag: 'clang-15' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 14', with: { tag: 'clang-14' }, timeout-minutes: 5 }
+
+ compile4:
+ name: 'omnibus compilations, #4'
+ runs-on: ubuntu-latest
+ needs: compile-if
+ if: ${{ needs.compile-if.result == 'success' }}
+ timeout-minutes: 60
+ services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } }
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
+ - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } }
+ - { uses: './.github/actions/compilers', name: 'clang 13', with: { tag: 'clang-13' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 12', with: { tag: 'clang-12' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 11', with: { tag: 'clang-11' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 10', with: { tag: 'clang-10' }, timeout-minutes: 5 }
+ # llvm-objcopy<=9 doesn't have --wildcard. It compiles, but leaves Rust symbols in libyjit.o and fail `make test-leaked-globals`.
+ - { uses: './.github/actions/compilers', name: 'clang 9', with: { tag: 'clang-9', append_configure: '--disable-yjit --disable-zjit' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 8', with: { tag: 'clang-8', append_configure: '--disable-yjit --disable-zjit' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 7', with: { tag: 'clang-7', append_configure: '--disable-yjit --disable-zjit' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'clang 6', with: { tag: 'clang-6.0', append_configure: '--disable-yjit --disable-zjit' }, timeout-minutes: 5 }
+
+ compile5:
+ name: 'omnibus compilations, #5'
+ runs-on: ubuntu-latest
+ needs: compile-if
+ if: ${{ needs.compile-if.result == 'success' }}
+ timeout-minutes: 60
+ services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } }
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
+ - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } }
+ # -Wno-strict-prototypes is necessary with current clang-15 since
+ # older autoconf generate functions without prototype and -pedantic
+ # now implies strict-prototypes. Disabling the error but leaving the
+ # warning generates a lot of noise from use of ANYARGS in
+ # rb_define_method() and friends.
+ # See: https://github.com/llvm/llvm-project/commit/11da1b53d8cd3507959022cd790d5a7ad4573d94
+ - { uses: './.github/actions/compilers', name: 'C99', with: { CFLAGS: '-std=c99 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'C11', with: { CFLAGS: '-std=c11 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'C17', with: { CFLAGS: '-std=c17 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'C23', with: { CFLAGS: '-std=c2x -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'C++98', with: { CXXFLAGS: '-std=c++98 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'C++11', with: { CXXFLAGS: '-std=c++11 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'C++14', with: { CXXFLAGS: '-std=c++14 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'C++17', with: { CXXFLAGS: '-std=c++17 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }, timeout-minutes: 5 }
+
+ compile6:
+ name: 'omnibus compilations, #6'
+ runs-on: ubuntu-latest
+ needs: compile-if
+ if: ${{ needs.compile-if.result == 'success' }}
+ timeout-minutes: 60
+ services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } }
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
+ - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } }
+ - { uses: './.github/actions/compilers', name: 'C++20', with: { CXXFLAGS: '-std=c++20 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'C++23', with: { CXXFLAGS: '-std=c++23 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'C++26', with: { CXXFLAGS: '-std=c++26 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'gmp', with: { append_configure: '--with-gmp', test_all: 'ruby/test_bignum.rb', test_spec: "/github/workspace/src/spec/ruby/core/integer" }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'jemalloc', with: { append_configure: '--with-jemalloc' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'valgrind', with: { append_configure: '--with-valgrind' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'coroutine=ucontext', with: { append_configure: '--with-coroutine=ucontext' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'coroutine=pthread', with: { append_configure: '--with-coroutine=pthread' }, timeout-minutes: 5 }
+
+ compile7:
+ name: 'omnibus compilations, #7'
+ runs-on: ubuntu-latest
+ needs: compile-if
+ if: ${{ needs.compile-if.result == 'success' }}
+ timeout-minutes: 60
+ services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } }
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
+ - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } }
+ - { uses: './.github/actions/compilers', name: 'disable-jit', with: { append_configure: '--disable-yjit --disable-zjit' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'disable-yjit', with: { append_configure: '--disable-yjit' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'disable-zjit', with: { append_configure: '--disable-zjit' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'disable-dln', with: { append_configure: '--disable-dln' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'enable-mkmf-verbose', with: { append_configure: '--enable-mkmf-verbose' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'disable-rubygems', with: { append_configure: '--disable-rubygems' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'RUBY_DEVEL', with: { append_configure: '--enable-devel' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'OPT_THREADED_CODE=0', with: { cppflags: '-DOPT_THREADED_CODE=0' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'OPT_THREADED_CODE=1', with: { cppflags: '-DOPT_THREADED_CODE=1' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'OPT_THREADED_CODE=2', with: { cppflags: '-DOPT_THREADED_CODE=2' }, timeout-minutes: 5 }
+
+ compile8:
+ name: 'omnibus compilations, #8'
+ runs-on: ubuntu-latest
+ needs: compile-if
+ if: ${{ needs.compile-if.result == 'success' }}
+ timeout-minutes: 60
+ services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } }
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
+ - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } }
+ - { uses: './.github/actions/compilers', name: 'NDEBUG', with: { cppflags: '-DNDEBUG' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'RUBY_DEBUG', with: { cppflags: '-DRUBY_DEBUG' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'ARRAY_DEBUG', with: { cppflags: '-DARRAY_DEBUG' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'BIGNUM_DEBUG', with: { cppflags: '-DBIGNUM_DEBUG' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'CCAN_LIST_DEBUG', with: { cppflags: '-DCCAN_LIST_DEBUG' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'CPDEBUG=-1', with: { cppflags: '-DCPDEBUG=-1' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'ENC_DEBUG', with: { cppflags: '-DENC_DEBUG' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GC_DEBUG', with: { cppflags: '-DGC_DEBUG' }, timeout-minutes: 5 }
+
+ compile9:
+ name: 'omnibus compilations, #9'
+ runs-on: ubuntu-latest
+ needs: compile-if
+ if: ${{ needs.compile-if.result == 'success' }}
+ timeout-minutes: 60
+ services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } }
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
+ - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } }
+ - { uses: './.github/actions/compilers', name: 'HASH_DEBUG', with: { cppflags: '-DHASH_DEBUG' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'ID_TABLE_DEBUG', with: { cppflags: '-DID_TABLE_DEBUG' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'RGENGC_DEBUG=-1', with: { cppflags: '-DRGENGC_DEBUG=-1' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'SYMBOL_DEBUG', with: { cppflags: '-DSYMBOL_DEBUG' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'RGENGC_CHECK_MODE', with: { cppflags: '-DRGENGC_CHECK_MODE' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'VM_CHECK_MODE', with: { cppflags: '-DVM_CHECK_MODE' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'USE_EMBED_CI=0', with: { cppflags: '-DUSE_EMBED_CI=0' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'USE_FLONUM=0', with: { cppflags: '-DUSE_FLONUM=0', append_configure: '--disable-yjit --disable-zjit' }, timeout-minutes: 5 }
+
+ compileX:
+ name: 'omnibus compilations, #10'
+ runs-on: ubuntu-latest
+ needs: compile-if
+ if: ${{ needs.compile-if.result == 'success' }}
+ timeout-minutes: 60
+ services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } }
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
+ - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } }
+ - { uses: './.github/actions/compilers', name: 'USE_LAZY_LOAD', with: { cppflags: '-DUSE_LAZY_LOAD' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'USE_SYMBOL_GC=0', with: { cppflags: '-DUSE_SYMBOL_GC=0' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'USE_THREAD_CACHE=0', with: { cppflags: '-DUSE_THREAD_CACHE=0' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'USE_RUBY_DEBUG_LOG=1', with: { cppflags: '-DUSE_RUBY_DEBUG_LOG=1' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'USE_DEBUG_COUNTER', with: { cppflags: '-DUSE_DEBUG_COUNTER=1' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'SHARABLE_MIDDLE_SUBSTRING', with: { cppflags: '-DSHARABLE_MIDDLE_SUBSTRING=1' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'DEBUG_FIND_TIME_NUMGUESS', with: { cppflags: '-DDEBUG_FIND_TIME_NUMGUESS' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'DEBUG_INTEGER_PACK', with: { cppflags: '-DDEBUG_INTEGER_PACK' }, timeout-minutes: 5 }
+
+ compileB:
+ name: 'omnibus compilations, #11'
+ runs-on: ubuntu-latest
+ needs: compile-if
+ if: ${{ needs.compile-if.result == 'success' }}
+ timeout-minutes: 60
+ services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } }
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
+ - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } }
+ - { uses: './.github/actions/compilers', name: 'GC_DEBUG_STRESS_TO_CLASS', with: { cppflags: '-DGC_DEBUG_STRESS_TO_CLASS' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GC_ENABLE_LAZY_SWEEP=0', with: { cppflags: '-DGC_ENABLE_LAZY_SWEEP=0' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GC_PROFILE_DETAIL_MEMORY', with: { cppflags: '-DGC_PROFILE_DETAIL_MEMORY' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'GC_PROFILE_MORE_DETAIL', with: { cppflags: '-DGC_PROFILE_MORE_DETAIL' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'MALLOC_ALLOCATED_SIZE_CHECK', with: { cppflags: '-DMALLOC_ALLOCATED_SIZE_CHECK' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'RGENGC_ESTIMATE_OLDMALLOC', with: { cppflags: '-DRGENGC_ESTIMATE_OLDMALLOC' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'RGENGC_PROFILE', with: { cppflags: '-DRGENGC_PROFILE' }, timeout-minutes: 5 }
+
+ compileC:
+ name: 'omnibus compilations, #12'
+ runs-on: ubuntu-latest
+ needs: compile-if
+ if: ${{ needs.compile-if.result == 'success' }}
+ timeout-minutes: 60
+ services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } }
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
+ - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } }
+ - { uses: './.github/actions/compilers', name: 'VM_DEBUG_BP_CHECK', with: { cppflags: '-DVM_DEBUG_BP_CHECK' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'VM_DEBUG_VERIFY_METHOD_CACHE', with: { cppflags: '-DVM_DEBUG_VERIFY_METHOD_CACHE' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'YJIT_FORCE_ENABLE', with: { cppflags: '-DYJIT_FORCE_ENABLE' }, timeout-minutes: 5 }
+ - { uses: './.github/actions/compilers', name: 'UNIVERSAL_PARSER', with: { cppflags: '-DUNIVERSAL_PARSER' }, timeout-minutes: 5 }
+
+ compilemax:
+ name: 'omnibus compilations, result'
+ runs-on: ubuntu-latest
+ if: ${{ always() }}
+ needs:
+ - 'compile1'
+ - 'compile2'
+ - 'compile3'
+ - 'compile4'
+ - 'compile5'
+ - 'compile6'
+ - 'compile7'
+ - 'compile8'
+ - 'compile9'
+ - 'compileX'
+ - 'compileB'
+ - 'compileC'
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github }
- uses: ./.github/actions/slack
with:
- label: ${{ matrix.entry.name }}
+ label: 'omnibus'
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
- if: ${{ failure() }}
+ if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
+ - run: false
+ working-directory:
+ if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
defaults:
run:
diff --git a/.github/workflows/cygwin.yml b/.github/workflows/cygwin.yml
new file mode 100644
index 0000000000..ac73991fe8
--- /dev/null
+++ b/.github/workflows/cygwin.yml
@@ -0,0 +1,71 @@
+name: Cygwin
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ make:
+ runs-on: windows-2022
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - run: git config --global core.autocrlf input
+
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+
+ - name: Setup Cygwin
+ uses: cygwin/cygwin-install-action@master
+ with:
+ packages: ruby gcc-core make autoconf libtool libssl-devel libyaml-devel libffi-devel zlib-devel rubygems
+
+ - name: configure
+ run: |
+ ./autogen.sh
+ ./configure --disable-install-doc
+ shell: C:\cygwin\bin\bash.EXE --noprofile --norc -e -o igncr -o pipefail {0}
+
+ - name: Extract bundled gems
+ run: |
+ make ruby -j5
+ make extract-gems
+ shell: C:\cygwin\bin\bash.EXE --noprofile --norc -e -o igncr -o pipefail {0}
+
+ - name: make all
+ timeout-minutes: 30
+ run: make -j4 V=1
+ shell: C:\cygwin\bin\bash.EXE --noprofile --norc -e -o igncr -o pipefail {0}
+
+ - uses: ./.github/actions/slack
+ with:
+ label: Cygwin
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
diff --git a/.github/workflows/default_gems_list.yml b/.github/workflows/default_gems_list.yml
new file mode 100644
index 0000000000..1c7e2195c8
--- /dev/null
+++ b/.github/workflows/default_gems_list.yml
@@ -0,0 +1,99 @@
+name: Update default gems list
+on: [push, pull_request, merge_group]
+
+env:
+ UPDATE_NEWS_ENABLED: true
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ update_default_gems_list:
+ name: Update default gems list
+
+ permissions:
+ contents: write # for Git to git push
+
+ runs-on: ubuntu-latest
+
+ if: ${{ github.repository == 'ruby/ruby' }}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_AUTO_UPDATE_TOKEN || secrets.GITHUB_TOKEN }}
+
+ - id: gems
+ run: true
+ if: ${{ github.ref == 'refs/heads/master' }}
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ makeup: true
+ # Skip overwriting MATZBOT_AUTO_UPDATE_TOKEN
+ checkout: '' # false (ref: https://github.com/actions/runner/issues/2238)
+ if: ${{ steps.gems.outcome == 'success' }}
+
+ - name: Download previous gems list
+ run: |
+ data=default_gems.json
+ mkdir -p .downloaded-cache
+ ln -s .downloaded-cache/$data .
+ curl -O -R -z ./$data https://stdgems.org/$data
+ if: ${{ steps.gems.outcome == 'success' }}
+
+ - name: Make default gems list
+ run: |
+ #!ruby
+ require 'rubygems'
+ $:.unshift "lib"
+ rgver = File.foreach("lib/rubygems.rb") do |line|
+ break $1 if /^\s*VERSION\s*=\s*"([^"]+)"/ =~ line
+ end
+ gems = Dir.glob("{ext,lib}/**/*.gemspec").map do |f|
+ spec = Gem::Specification.load(f)
+ "#{spec.name} #{spec.version}"
+ end.sort
+ File.open("gems/default_gems", "w") do |f|
+ f.puts "RubyGems #{rgver}"
+ f.puts gems
+ end
+ shell: ruby --disable=gems {0}
+ if: ${{ steps.gems.outcome == 'success' }}
+
+ - name: Maintain updated gems list in NEWS
+ run: |
+ ruby tool/update-NEWS-gemlist.rb default
+ if: ${{ steps.gems.outcome == 'success' && env.UPDATE_NEWS_ENABLED == 'true' }}
+
+ - name: Check diffs
+ id: diff
+ run: |
+ git diff --color --no-ext-diff --ignore-submodules --exit-code NEWS.md ||
+ echo update=true >> $GITHUB_OUTPUT
+ if: ${{ steps.gems.outcome == 'success' }}
+
+ - name: Commit
+ run: |
+ git pull --ff-only origin ${GITHUB_REF#refs/heads/}
+ git commit --message="Update default gems list at ${GITHUB_SHA:0:30} [ci skip]" NEWS.md
+ git push origin ${GITHUB_REF#refs/heads/}
+ env:
+ EMAIL: svn-admin@ruby-lang.org
+ GIT_AUTHOR_NAME: git
+ GIT_COMMITTER_NAME: git
+ if: >-
+ ${{
+ github.repository == 'ruby/ruby' &&
+ !startsWith(github.event_name, 'pull') &&
+ steps.diff.outputs.update
+ }}
+
+ - uses: ./.github/actions/slack
+ with:
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
diff --git a/.github/workflows/dependabot_automerge.yml b/.github/workflows/dependabot_automerge.yml
index 80112a0af3..a95c7005c4 100644
--- a/.github/workflows/dependabot_automerge.yml
+++ b/.github/workflows/dependabot_automerge.yml
@@ -1,23 +1,25 @@
# from https://github.com/gofiber/swagger/blob/main/.github/workflows/dependabot_automerge.yml
name: Dependabot auto-merge
on:
- pull_request_target:
+ pull_request:
+
+permissions:
+ contents: write
+ pull-requests: write
jobs:
automerge:
runs-on: ubuntu-latest
-
- if: ${{ github.actor == 'dependabot[bot]' }}
-
+ if: github.event.pull_request.user.login == 'dependabot[bot]' && github.repository == 'ruby/ruby'
steps:
- name: Dependabot metadata
- uses: dependabot/fetch-metadata@5e5f99653a5b510e8555840e80cbf1514ad4af38 # v2.1.0
+ uses: dependabot/fetch-metadata@21025c705c08248db411dc16f3619e6b5f9ea21a # v2.5.0
id: metadata
- name: Wait for status checks
- uses: lewagon/wait-on-check-action@ccfb013c15c8afb7bf2b7c028fb74dc5a068cccc # v1.3.4
+ uses: lewagon/wait-on-check-action@3603e826ee561ea102b58accb5ea55a1a7482343 # v1.4.1
with:
- repo-token: ${{ secrets.MATZBOT_GITHUB_TOKEN }}
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
ref: ${{ github.event.pull_request.head.sha || github.sha }}
check-regexp: 'make \(check, .*\)'
wait-interval: 30
@@ -27,4 +29,4 @@ jobs:
run: gh pr merge --auto --rebase "$PR_URL"
env:
PR_URL: ${{ github.event.pull_request.html_url }}
- GITHUB_TOKEN: ${{ secrets.MATZBOT_GITHUB_TOKEN }}
+ GITHUB_TOKEN: ${{ secrets.MATZBOT_DEPENDABOT_MERGE_TOKEN }}
diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml
new file mode 100644
index 0000000000..16dbac1afa
--- /dev/null
+++ b/.github/workflows/labeler.yml
@@ -0,0 +1,12 @@
+name: "Pull Request Labeler"
+on:
+- pull_request_target
+
+jobs:
+ labeler:
+ permissions:
+ contents: read
+ pull-requests: write
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/labeler@v6
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
index 3d97c092f7..29adcab39a 100644
--- a/.github/workflows/macos.yml
+++ b/.github/workflows/macos.yml
@@ -26,33 +26,42 @@ jobs:
matrix:
include:
- test_task: check
+ os: macos-14
+ - test_task: check
+ os: macos-14
+ configure_args: '--with-gcc=gcc-14'
+ - test_task: check
+ os: macos-14
+ configure_args: '--with-jemalloc --with-opt-dir=$(brew --prefix jemalloc)'
+ - test_task: check
+ os: macos-14
+ configure_args: '--with-gmp'
- test_task: test-all
test_opts: --repeat-count=2
+ os: macos-14
- test_task: test-bundler-parallel
+ os: macos-14
- test_task: test-bundled-gems
+ os: macos-14
- test_task: check
- os: macos-12
- - test_task: check
- os: macos-13
+ os: macos-15
fail-fast: false
env:
GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
- runs-on: ${{ matrix.os || (github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-14')}}
+ runs-on: ${{ matrix.os }}
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
- || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.title, 'Document')
- || contains(github.event.pull_request.labels.*.name, 'Document')
- || (github.event_name == 'push' && github.actor == 'dependabot[bot]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
)}}
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
sparse-checkout-cone-mode: false
sparse-checkout: /.github
@@ -76,14 +85,28 @@ jobs:
sudo sysctl -w kern.coredump=1
sudo chmod -R +rwx /cores/
+ - name: Delete unused SDKs
+ # To free up disk space to not run out during the run
+ run: |
+ sudo rm -rf ~/.dotnet
+ sudo rm -rf /Library/Android
+ sudo rm -rf /Library/Developer/CoreSimulator
+ continue-on-error: true
+
- name: Run configure
- run: ../src/configure -C --disable-install-doc ${ruby_configure_args}
+ run: ../src/configure -C --disable-install-doc ${ruby_configure_args} ${{ matrix.configure_args }}
- run: make prepare-gems
if: ${{ matrix.test_task == 'test-bundled-gems' }}
- run: make
+ - run: make hello
+
+ - name: runirb
+ run: |
+ echo IRB::VERSION | make runirb RUNOPT="-- -f"
+
- name: Set test options for skipped tests
run: |
set -x
@@ -92,31 +115,40 @@ jobs:
if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }}
- name: Set up Launchable
+ id: launchable
uses: ./.github/actions/launchable/setup
with:
- os: ${{ matrix.os || (github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-14')}}
+ os: ${{ matrix.os }}
test-opts: ${{ matrix.test_opts }}
launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }}
builddir: build
srcdir: src
continue-on-error: true
+ timeout-minutes: 3
- name: Set extra test options
- run: echo "TESTS=$TESTS ${{ matrix.test_opts }}" >> $GITHUB_ENV
+ run: |
+ echo "TESTS=$TESTS ${{ matrix.test_opts }}" >> $GITHUB_ENV
+ echo "RUBY_TEST_TIMEOUT_SCALE=10" >> $GITHUB_ENV # With --repeat-count=2, flaky test by timeout occurs frequently for some reason
if: matrix.test_opts
- name: make ${{ matrix.test_task }}
run: |
+ test -n "${LAUNCHABLE_STDOUT}" && exec 1> >(tee "${LAUNCHABLE_STDOUT}")
+ test -n "${LAUNCHABLE_STDERR}" && exec 2> >(tee "${LAUNCHABLE_STDERR}")
+
+ ulimit -c unlimited
make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"}
- timeout-minutes: 60
+ timeout-minutes: 90
env:
RUBY_TESTOPTS: '-q --tty=no'
TEST_BUNDLED_GEMS_ALLOW_FAILURES: ''
PRECHECK_BUNDLED_GEMS: 'no'
+ LAUNCHABLE_STDOUT: ${{ steps.launchable.outputs.stdout_report_path }}
+ LAUNCHABLE_STDERR: ${{ steps.launchable.outputs.stderr_report_path }}
- name: make skipped tests
run: |
- ulimit -c unlimited
make -s test-all TESTS="${TESTS//-n!\//-n/}"
env:
GNUMAKEFLAGS: ''
@@ -125,6 +157,14 @@ jobs:
if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }}
continue-on-error: ${{ matrix.continue-on-skipped_tests || false }}
+ - name: CAPI extensions
+ uses: ./.github/actions/capiext
+ with:
+ builddir: build
+ env:
+ RUBY_TESTOPTS: '-v --tty=no'
+ if: ${{ contains(matrix.extra_checks, 'capi') }}
+
- uses: ./.github/actions/slack
with:
label: ${{ matrix.os }} / ${{ matrix.test_task }}
@@ -147,20 +187,6 @@ jobs:
const job_name = `${context.job}${matrix ? ` (${Object.values(matrix).join(", ")})` : ""}`;
return workflow_run.jobs.find((job) => job.name === job_name).id;
- - name: upload /cores
- run: |
- ls -l /cores
- CORES_TAR_GZ="cores-${{ github.run_id }}-${{ steps.job_id.outputs.result }}.tar.gz"
- echo "test: $CORES_TAR_GZ"
- if [ -n "$(ls /cores)" ]; then
- tar czf /cores "$CORES_TAR_GZ"
- aws s3 cp "$CORES_TAR_GZ" "s3://ruby-core-files/$CORES_TAR_GZ"
- fi
- env:
- AWS_ACCESS_KEY_ID: ${{ secrets.RUBY_CORE_FILES_AWS_ACCESS_KEY_ID }}
- AWS_SECRET_ACCESS_KEY: ${{ secrets.RUBY_CORE_FILES_AWS_SECRET_ACCESS_KEY }}
- AWS_DEFAULT_REGION: ap-northeast-1
-
result:
if: ${{ always() }}
name: ${{ github.workflow }} result
diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml
index dfcd7abe08..5c639ad48b 100644
--- a/.github/workflows/mingw.yml
+++ b/.github/workflows/mingw.yml
@@ -30,16 +30,30 @@ permissions:
#
jobs:
make:
- runs-on: windows-2022
+ runs-on: windows-${{ matrix.os }}
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'
- CXXFLAGS: '-march=x86-64 -mtune=generic -O3 -pipe'
+ MSYS2_ARCH: >-
+ ${{
+ contains(matrix.msystem, 'arm64') && 'aarch64' ||
+ contains(matrix.msystem, '64') && 'x86_64' || 'i686'
+ }}
+ MINGW_PACKAGE_PREFIX: >-
+ mingw-w${{
+ endsWith(matrix.msystem, '64') && '64' || '32'
+ }}-${{
+ startsWith(matrix.msystem, 'clang') && 'clang' ||
+ startsWith(matrix.msystem, 'ucrt') && 'ucrt' ||
+ 'mingw'
+ }}-${{
+ contains(matrix.msystem, 'arm64') && 'aarch64' ||
+ endsWith(matrix.msystem, '64') && 'x86_64' || 'i686'
+ }}
+ CFLAGS: '-mtune=generic -O3 -pipe'
+ CXXFLAGS: '-mtune=generic -O3 -pipe'
CPPFLAGS: '-D_FORTIFY_SOURCE=2 -D__USE_MINGW_ANSI_STDIO=1 -DFD_SETSIZE=2048'
LDFLAGS: '-pipe'
GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
@@ -48,56 +62,111 @@ jobs:
matrix:
include:
# To mitigate flakiness of MinGW CI, we test only one runtime that newer MSYS2 uses.
+ # Ruby 3.2 is the first Windows Ruby to use OpenSSL 3.x
- msystem: 'UCRT64'
- baseruby: '3.0'
+ os: 2022
test_task: 'check'
test-all-opts: '--name=!/TestObjSpace#test_reachable_objects_during_iteration/'
+ - msystem: 'CLANGARM64'
+ os: 11-arm
+ test_task: 'check'
fail-fast: false
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
- || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.title, 'Document')
- || contains(github.event.pull_request.labels.*.name, 'Document')
- || (github.event_name == 'push' && github.actor == 'dependabot[bot]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
)}}
steps:
- - name: Set up Ruby & MSYS2
- uses: ruby/setup-ruby@0cde4689ba33c09f1b890c1725572ad96751a3fc # v1.178.0
+ - uses: msys2/setup-msys2@4f806de0a5a7294ffabaff804b38a9b435a73bda # v2.30.0
+ id: msys2
with:
- ruby-version: ${{ matrix.baseruby }}
-
- - name: where check
- run: |
- # show where
- mv /c/Windows/System32/libcrypto-1_1-x64.dll /c/Windows/System32/libcrypto-1_1-x64.dll_
- mv /c/Windows/System32/libssl-1_1-x64.dll /c/Windows/System32/libssl-1_1-x64.dll_
- result=true
- for e in gcc.exe ragel.exe make.exe libcrypto-1_1-x64.dll libssl-1_1-x64.dll; do
- echo ::group::$'\033[93m'$e$'\033[m'
- where $e || result=false
- echo ::endgroup::
- done
- $result
+ msystem: ${{ matrix.msystem }}
+ update: true
+ install: >-
+ git
+ make
+ ruby
+ autoconf
+ ${{ env.MINGW_PACKAGE_PREFIX }}-gcc
+ ${{ env.MINGW_PACKAGE_PREFIX }}-ragel
+ ${{ env.MINGW_PACKAGE_PREFIX }}-openssl
+ ${{ env.MINGW_PACKAGE_PREFIX }}-libyaml
+ ${{ env.MINGW_PACKAGE_PREFIX }}-libffi
+
+ - name: Set up env
+ id: setup-env
working-directory:
-
- - name: version check
run: |
- # show version
- result=true
- for e in gcc ragel make "openssl version"; do
- case "$e" in *" "*) ;; *) e="$e --version";; esac
- echo ::group::$'\033[93m'$e$'\033[m'
- $e || result=false
- echo ::endgroup::
- done
- $result
+ $msys2 = ${env:MSYS2_LOCATION}
+ $msystem = ${env:MSYSTEM}.ToLower()
+ echo $msys2\usr\bin $msys2\$msystem\bin |
+ Tee-Object ${env:GITHUB_PATH} -Append -Encoding utf-8
+
+ # Use the fast device for the temporary directory.
+ # %TEMP% is inconsistent with %TMP% and test-all expects they are consistent.
+ # https://github.com/actions/virtual-environments/issues/712#issuecomment-613004302
+ $tmp = ${env:RUNNER_TEMP}
+ echo HOME=$home TMP=$tmp TEMP=$tmp TMPDIR=$tmp |
+ Tee-Object ${env:GITHUB_ENV} -Append -Encoding utf-8
+ shell: pwsh # cmd.exe does not strip spaces before `|`.
+ env:
+ MSYS2_LOCATION: ${{ steps.msys2.outputs.msys2-location }}
+ MSYSTEM: ${{ matrix.msystem }}
+
+ - name: Remove Strawberry Perl pkg-config
working-directory:
+ # `pkg-config.bat` included in Strawberry Perl is written in
+ # Perl and doesn't work when another msys2 `perl` precede its
+ # own `perl`.
+ #
+ # ```
+ # Can't find C:\Strawberry\perl\bin\pkg-config.bat on PATH, '.' not in PATH.
+ # ```
+ run: |
+ Get-Command pkg-config.bat | % { ren $_.path ($_.path + "~") }
+ shell: pwsh
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - name: Misc system & package info
+ working-directory:
+ run: |
+ group() { echo ::group::$'\e[94;1m'"$*"$'\e[m'; }
+ endgroup() { echo ::endgroup::; }
+
+ group Path
+ cygpath -wa / . $(type -p cygpath bash sh)
+ endgroup
+
+ I() {
+ group $1
+ run Where type -pa $1 && { [ $# -eq 1 ] || run Version "$@"; } ||
+ failed+=($1)
+ endgroup
+ }
+ run() { local w m=$1; shift; w="$("$@")" && show "$m" && indent "$w"; }
+ indent() { [ -z "$1" ] || echo "$1" | /bin/sed '/^$/!s/^/ /'; }
+ show() { echo $'\e[96m'"$*"$'\e[m'; }
+
+ failed=()
+
+ I gcc.exe --version
+ I ragel.exe --version
+ I make.exe --version
+ I openssl.exe version
+ I libcrypto-3-x64.dll
+ I libssl-3-x64.dll
+
+ group Packages
+ pacman -Qs $MINGW_PACKAGE_PREFIX-* | /bin/sed -n "s,local/$MINGW_PACKAGE_PREFIX-,,p"
+ endgroup
+
+ [ ${#failed[@]} -eq 0 ]
+ shell: sh
+
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
sparse-checkout-cone-mode: false
sparse-checkout: /.github
@@ -107,23 +176,38 @@ jobs:
srcdir: src
builddir: build
makeup: true
+ # Set fetch-depth: 10 so that Launchable can receive commits information.
+ fetch-depth: 10
- name: configure
run: >
../src/configure --disable-install-doc --prefix=/.
--build=$CHOST --host=$CHOST --target=$CHOST
+ shell: sh
+ env:
+ CHOST: ${{ env.MSYS2_ARCH }}-w64-mingw32
- name: make all
timeout-minutes: 30
- run: make
+ run: make -j4
- name: make install
run: make DESTDIR=../install install-nodoc
+ - name: Set up Launchable
+ uses: ./.github/actions/launchable/setup
+ with:
+ os: windows-2022
+ launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }}
+ builddir: build
+ srcdir: src
+ test-tasks: '["test", "test-all", "test-spec"]'
+ continue-on-error: true
+ timeout-minutes: 3
+
- name: test
timeout-minutes: 30
- run: make test
- shell: cmd
+ run: make test test-tool
env:
GNUMAKEFLAGS: ''
RUBY_TESTOPTS: '-v --tty=no'
@@ -131,13 +215,13 @@ jobs:
- name: test-all
timeout-minutes: 45
- shell: cmd
run: |
make ${{ StartsWith(matrix.test_task, 'test/') && matrix.test_task || 'test-all' }}
env:
RUBY_TESTOPTS: >-
- --retry --job-status=normal --show-skip --timeout-scale=1.5
+ --retry --job-status=normal --show-skip --timeout-scale=1.5 -j4
${{ matrix.test-all-opts }}
+ ${{ env.TESTS }}
BUNDLER_VERSION:
if: ${{ matrix.test_task == 'check' || matrix.test_task == 'test-all' || StartsWith(matrix.test_task, 'test/') }}
@@ -145,7 +229,6 @@ jobs:
timeout-minutes: 10
run: |
make ${{ StartsWith(matrix.test_task, 'spec/') && matrix.test_task || 'test-spec' }}
- shell: cmd
if: ${{ matrix.test_task == 'check' || matrix.test_task == 'test-spec' || StartsWith(matrix.test_task, 'spec/') }}
- uses: ./src/.github/actions/slack
@@ -157,4 +240,4 @@ jobs:
defaults:
run:
working-directory: build
- shell: sh
+ shell: cmd
diff --git a/.github/workflows/modgc.yml b/.github/workflows/modgc.yml
new file mode 100644
index 0000000000..1d14934df8
--- /dev/null
+++ b/.github/workflows/modgc.yml
@@ -0,0 +1,176 @@
+name: ModGC
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ pull_request:
+ # Do not use paths-ignore for required status checks
+ # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ check:
+ strategy:
+ matrix:
+ gc:
+ - name: default
+ - name: mmtk
+ mmtk_build: release
+ os: [macos-latest, ubuntu-latest]
+ include:
+ - test_task: check
+ fail-fast: false
+
+ env:
+ GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
+ RUBY_DEBUG: ci
+
+ runs-on: ${{ matrix.os }}
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ sparse-checkout-cone-mode: false
+ sparse-checkout: /.github
+
+ - name: Install libraries (macOS)
+ uses: ./.github/actions/setup/macos
+ if: ${{ contains(matrix.os, 'macos') }}
+
+ - name: Install libraries (Ubuntu)
+ uses: ./.github/actions/setup/ubuntu
+ if: ${{ contains(matrix.os, 'ubuntu') }}
+
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0
+ with:
+ ruby-version: '3.1'
+ bundler: none
+ if: ${{ contains(matrix.os, 'ubuntu') }}
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ srcdir: src
+ builddir: build
+ makeup: true
+ clean: true
+ dummy-files: false
+ # Set fetch-depth: 10 so that Launchable can receive commits information.
+ fetch-depth: 10
+
+ - name: make sure that kern.coredump=1
+ run: |
+ sysctl -n kern.coredump
+ sudo sysctl -w kern.coredump=1
+ sudo chmod -R +rwx /cores/
+ if: ${{ contains(matrix.os, 'macos') }}
+
+ - name: Delete unused SDKs
+ # To free up disk space to not run out during the run
+ run: |
+ sudo rm -rf ~/.dotnet
+ sudo rm -rf /Library/Android
+ sudo rm -rf /Library/Developer/CoreSimulator
+ continue-on-error: true
+ if: ${{ contains(matrix.os, 'macos') }}
+
+ - name: Setup Ruby GC Directory
+ run: |
+ echo "MODULAR_GC_DIR=$HOME/ruby_gc" >> $GITHUB_ENV
+
+ - name: Run configure
+ env:
+ arch: ${{ matrix.arch }}
+ run: >-
+ $SETARCH ../src/configure -C --disable-install-doc --with-modular-gc=${{ env.MODULAR_GC_DIR }}
+ ${arch:+--target=$arch-$OSTYPE --host=$arch-$OSTYPE}
+
+ - uses: actions-rust-lang/setup-rust-toolchain@v1
+ - name: Set MMTk environment variables
+ run: |
+ echo 'EXCLUDES=../src/test/.excludes-mmtk' >> $GITHUB_ENV
+ echo 'MSPECOPT=-B../src/spec/mmtk.mspec' >> $GITHUB_ENV
+ if: ${{ matrix.gc.name == 'mmtk' }}
+
+ - run: $SETARCH make
+
+ - name: Build Modular GC
+ run: |
+ echo "RUBY_GC_LIBRARY=${{ matrix.gc.name }}" >> $GITHUB_ENV
+ make install-modular-gc MODULAR_GC=${{ matrix.gc.name }} MMTK_BUILD=${{ matrix.gc.mmtk_build }}
+ make distclean-modular-gc MODULAR_GC=${{ matrix.gc.name }}
+
+ - run: $SETARCH make hello
+
+ - name: Set test options for skipped tests
+ run: |
+ set -x
+ TESTS="$(echo "${{ matrix.skipped_tests }}" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|')"
+ echo "TESTS=${TESTS}" >> $GITHUB_ENV
+ if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }}
+
+ - name: Set up Launchable
+ id: launchable
+ uses: ./.github/actions/launchable/setup
+ with:
+ os: ${{ matrix.os || 'ubuntu-22.04' }}
+ test-opts: ${{ matrix.configure }}
+ launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }}
+ builddir: build
+ srcdir: src
+ continue-on-error: true
+ timeout-minutes: 3
+
+ - name: make ${{ matrix.test_task }}
+ run: |
+ test -n "${LAUNCHABLE_STDOUT}" && exec 1> >(tee "${LAUNCHABLE_STDOUT}")
+ test -n "${LAUNCHABLE_STDERR}" && exec 2> >(tee "${LAUNCHABLE_STDERR}")
+
+ $SETARCH make -s ${{ matrix.test_task }} \
+ ${TESTS:+TESTS="$TESTS"} \
+ ${{ !contains(matrix.test_task, 'bundle') && 'RUBYOPT=-w' || '' }}
+ timeout-minutes: ${{ matrix.gc.timeout || 40 }}
+ env:
+ RUBY_TESTOPTS: '-q --tty=no'
+ TEST_BUNDLED_GEMS_ALLOW_FAILURES: ''
+ PRECHECK_BUNDLED_GEMS: 'no'
+ LAUNCHABLE_STDOUT: ${{ steps.launchable.outputs.stdout_report_path }}
+ LAUNCHABLE_STDERR: ${{ steps.launchable.outputs.stderr_report_path }}
+
+ - name: make skipped tests
+ run: |
+ $SETARCH make -s test-all TESTS="${TESTS//-n!\//-n/}"
+ env:
+ GNUMAKEFLAGS: ''
+ RUBY_TESTOPTS: '-v --tty=no'
+ if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }}
+ continue-on-error: ${{ matrix.continue-on-skipped_tests || false }}
+
+ - uses: ./.github/actions/slack
+ with:
+ label: ${{ matrix.test_task }} ${{ matrix.configure }}${{ matrix.arch }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
+
+defaults:
+ run:
+ working-directory: build
diff --git a/.github/workflows/parse_y.yml b/.github/workflows/parse_y.yml
new file mode 100644
index 0000000000..87facc8a55
--- /dev/null
+++ b/.github/workflows/parse_y.yml
@@ -0,0 +1,100 @@
+name: parse.y
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ pull_request:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ make:
+ strategy:
+ matrix:
+ include:
+ - test_task: check
+ - test_task: test-bundler-parallel
+ - test_task: test-bundled-gems
+ fail-fast: false
+
+ env:
+ GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
+ RUBY_DEBUG: ci
+ SETARCH: ${{ matrix.arch && format('setarch {0}', matrix.arch) }}
+
+ runs-on: ubuntu-22.04
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ sparse-checkout-cone-mode: false
+ sparse-checkout: /.github
+
+ - uses: ./.github/actions/setup/ubuntu
+
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0
+ with:
+ ruby-version: '3.1'
+ bundler: none
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ srcdir: src
+ builddir: build
+ makeup: true
+ clean: true
+ dummy-files: ${{ matrix.test_task == 'check' }}
+
+ - name: Run configure
+ run: ../src/configure -C --disable-install-doc cppflags=-DRUBY_DEBUG --with-parser=parse.y
+
+ - run: make
+
+ - run: make TESTRUN_SCRIPT='-renvutil -v -e "exit EnvUtil.current_parser == %[parse.y]"' run
+ env:
+ RUNOPT0: -I$(tooldir)/lib
+
+ - name: make ${{ matrix.test_task }}
+ run: make -s ${{ matrix.test_task }} RUN_OPTS="$RUN_OPTS" SPECOPTS="$SPECOPTS"
+ env:
+ RUBY_TESTOPTS: ${{ matrix.testopts }}
+ EXCLUDES: '../src/test/.excludes-parsey'
+ RUN_OPTS: ${{ matrix.run_opts || '--parser=parse.y' }}
+ SPECOPTS: ${{ matrix.specopts || '-T --parser=parse.y' }}
+ TEST_BUNDLED_GEMS_ALLOW_FAILURES: ''
+
+ - uses: ./.github/actions/slack
+ with:
+ label: ${{ matrix.run_opts }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
+
+defaults:
+ run:
+ working-directory: build
diff --git a/.github/workflows/post_push.yml b/.github/workflows/post_push.yml
new file mode 100644
index 0000000000..318444c0a2
--- /dev/null
+++ b/.github/workflows/post_push.yml
@@ -0,0 +1,85 @@
+name: Post-push
+on:
+ push:
+ branches:
+ - master
+ - 'ruby_*_*'
+jobs:
+ hooks:
+ name: Post-push hooks
+ runs-on: ubuntu-latest
+ if: ${{ github.repository == 'ruby/ruby' }}
+ steps:
+ - name: Sync git.ruby-lang.org
+ run: |
+ mkdir -p ~/.ssh
+ (umask 066; printenv RUBY_GIT_SYNC_PRIVATE_KEY > ~/.ssh/id_ed25519)
+ ssh-keyscan -t ed25519 git.ruby-lang.org >> ~/.ssh/known_hosts
+ ssh -i ~/.ssh/id_ed25519 git-sync@git.ruby-lang.org "sudo -u git /home/git/git.ruby-lang.org/bin/update-ruby.sh $GITHUB_REF"
+ env:
+ GITHUB_REF: ${{ github.ref }}
+ RUBY_GIT_SYNC_PRIVATE_KEY: ${{ secrets.RUBY_GIT_SYNC_PRIVATE_KEY }}
+ if: ${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/ruby_') }}
+
+ - name: Fetch changesets on bugs.ruby-lang.org
+ run: |
+ curl "https://bugs.ruby-lang.org/sys/fetch_changesets?key=${REDMINE_SYS_API_KEY}" -s --fail-with-body -w '* status: %{http_code}\n'
+ env:
+ REDMINE_SYS_API_KEY: ${{ secrets.REDMINE_SYS_API_KEY }}
+ if: ${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/ruby_') }}
+
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ fetch-depth: 500 # for notify-slack-commits
+ token: ${{ secrets.MATZBOT_AUTO_UPDATE_TOKEN }}
+
+ - name: Notify commit to Slack
+ run: ruby tool/notify-slack-commits.rb "$GITHUB_OLD_SHA" "$GITHUB_NEW_SHA" refs/heads/master
+ env:
+ GITHUB_OLD_SHA: ${{ github.event.before }}
+ GITHUB_NEW_SHA: ${{ github.event.after }}
+ SLACK_WEBHOOK_URL_ALERTS: ${{ secrets.SLACK_WEBHOOK_URL_ALERTS }}
+ SLACK_WEBHOOK_URL_COMMITS: ${{ secrets.SLACK_WEBHOOK_URL_COMMITS }}
+ SLACK_WEBHOOK_URL_RUBY_JP: ${{ secrets.SLACK_WEBHOOK_URL_RUBY_JP }}
+ if: ${{ github.ref == 'refs/heads/master' }}
+
+ - name: Notify commit to ruby-cvs
+ run: |
+ SENDMAIL="ssh -i ${HOME}/.ssh/id_ed25519 git-sync@git.ruby-lang.org /usr/sbin/sendmail" \
+ ruby tool/commit-email.rb . ruby-cvs@g.ruby-lang.org \
+ "$GITHUB_OLD_SHA" "$GITHUB_NEW_SHA" "$GITHUB_REF" \
+ --viewer-uri "https://github.com/ruby/ruby/commit/" \
+ --error-to cvs-admin@ruby-lang.org
+ env:
+ GITHUB_OLD_SHA: ${{ github.event.before }}
+ GITHUB_NEW_SHA: ${{ github.event.after }}
+ GITHUB_REF: ${{ github.ref }}
+ if: ${{ github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/ruby_') }}
+
+ - name: Auto-correct code styles
+ run: |
+ set -x
+ ruby tool/auto-style.rb "$GITHUB_OLD_SHA" "$GITHUB_NEW_SHA" refs/heads/master
+ env:
+ GITHUB_OLD_SHA: ${{ github.event.before }}
+ GITHUB_NEW_SHA: ${{ github.event.after }}
+ GIT_AUTHOR_NAME: git
+ GIT_COMMITTER_NAME: git
+ EMAIL: svn-admin@ruby-lang.org
+ if: ${{ github.ref == 'refs/heads/master' }}
+
+ - name: Push PR notes to GitHub
+ run: ruby tool/notes-github-pr.rb "$(pwd)/.git" "$GITHUB_OLD_SHA" "$GITHUB_NEW_SHA" refs/heads/master
+ env:
+ GITHUB_OLD_SHA: ${{ github.event.before }}
+ GITHUB_NEW_SHA: ${{ github.event.after }}
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ GIT_AUTHOR_NAME: git
+ GIT_COMMITTER_NAME: git
+ EMAIL: svn-admin@ruby-lang.org
+ if: ${{ github.ref == 'refs/heads/master' }}
+
+ - uses: ./.github/actions/slack
+ with:
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
diff --git a/.github/workflows/pr-playground.yml b/.github/workflows/pr-playground.yml
index cc06006142..f3c0556429 100644
--- a/.github/workflows/pr-playground.yml
+++ b/.github/workflows/pr-playground.yml
@@ -25,7 +25,7 @@ jobs:
&& github.event.workflow_run.event == 'pull_request')
}}
steps:
- - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
+ - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
diff --git a/.github/workflows/prism.yml b/.github/workflows/prism.yml
deleted file mode 100644
index 56d7298193..0000000000
--- a/.github/workflows/prism.yml
+++ /dev/null
@@ -1,114 +0,0 @@
-name: Prism
-on:
- push:
- paths-ignore:
- - 'doc/**'
- - '**.md'
- - '**.rdoc'
- - '**/.document'
- - '**.[1-8]'
- - '**.ronn'
- - '.*.yml'
- pull_request:
- paths-ignore:
- - 'doc/**'
- - '**.md'
- - '**.rdoc'
- - '**/.document'
- - '**.[1-8]'
- - '**.ronn'
- - '.*.yml'
- merge_group:
-
-concurrency:
- group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
- cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
-
-permissions:
- contents: read
-
-jobs:
- make:
- strategy:
- matrix:
- # main variables included in the job name
- test_task: [check]
- run_opts: ['--parser=prism']
- arch: ['']
- fail-fast: false
-
- env:
- GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
- RUBY_DEBUG: ci
- SETARCH: ${{ matrix.arch && format('setarch {0}', matrix.arch) }}
-
- runs-on: ubuntu-22.04
-
- if: >-
- ${{!(false
- || contains(github.event.head_commit.message, '[DOC]')
- || contains(github.event.head_commit.message, 'Document')
- || contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.title, 'Document')
- || contains(github.event.pull_request.labels.*.name, 'Document')
- || (github.event_name == 'push' && github.actor == 'dependabot[bot]')
- )}}
-
- steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- with:
- sparse-checkout-cone-mode: false
- sparse-checkout: /.github
-
- - uses: ./.github/actions/setup/ubuntu
-
- - uses: ./.github/actions/setup/directories
- with:
- srcdir: src
- builddir: build
- makeup: true
-
- - name: Run configure
- env:
- arch: ${{ matrix.arch }}
- run: >-
- $SETARCH ../src/configure -C --disable-install-doc cppflags=-DRUBY_DEBUG
- ${arch:+--target=$arch-$OSTYPE --host=$arch-$OSTYPE}
-
- - run: $SETARCH make
-
- - name: make test
- run: |
- $SETARCH make -s test RUN_OPTS="$RUN_OPTS"
- timeout-minutes: 30
- env:
- GNUMAKEFLAGS: ''
- RUBY_TESTOPTS: '-v --tty=no'
- RUN_OPTS: ${{ matrix.run_opts }}
-
- - name: make test-all
- run: |
- $SETARCH make -s test-all RUN_OPTS="$RUN_OPTS"
- timeout-minutes: 40
- env:
- GNUMAKEFLAGS: ''
- RUBY_TESTOPTS: '-q --tty=no --excludes-dir="../src/test/.excludes-prism" --exclude="error_highlight/test_error_highlight.rb"'
- RUN_OPTS: ${{ matrix.run_opts }}
-
- - name: make test-spec
- run: |
- $SETARCH make -s test-spec SPECOPTS="$SPECOPTS"
- timeout-minutes: 10
- env:
- GNUMAKEFLAGS: ''
- SPECOPTS: "-T -W:no-experimental -T --parser=prism"
-
- - uses: ./.github/actions/slack
- with:
- label: ${{ matrix.run_opts }}
- SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
- if: ${{ failure() }}
-
-defaults:
- run:
- working-directory: build
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
new file mode 100644
index 0000000000..3caeee9a3b
--- /dev/null
+++ b/.github/workflows/publish.yml
@@ -0,0 +1,107 @@
+name: Publish Ruby packages
+
+on:
+ repository_dispatch:
+ types:
+ - release
+ workflow_dispatch:
+ inputs:
+ version:
+ description: 'Version of the Ruby package to release'
+ required: true
+ default: '3.3.4'
+
+jobs:
+ release:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v6.0.1
+
+ - uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: 3.3.4
+
+ - name: Store Ruby version
+ run: |
+ echo "RUBY_VERSION=${{ github.event.client_payload.version || github.event.inputs.version }}" >> $GITHUB_ENV
+
+ - name: Store ABI version
+ run: echo "ABI_VERSION=$(echo ${{ env.RUBY_VERSION }} | cut -d '.' -f 1-2)" >> $GITHUB_ENV
+
+ - name: Copy draft package `/tmp` to `/pub` directory
+ run: tool/release.sh ${{ env.RUBY_VERSION }}
+ env:
+ AWS_ACCESS_KEY_ID: ${{ secrets.FTP_R_L_O_AWS_ACCESS_KEY_ID }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.FTP_R_L_O_AWS_SECRET_ACCESS_KEY }}
+ AWS_DEFAULT_REGION: us-west-2
+
+ - name: Purge URLs of release package
+ run: |
+ curl -X POST \
+ -H "Fastly-Key: ${{ secrets.FASTLY_PURGE_TOKEN }}" \
+ https://api.fastly.com/purge/cache.ruby-lang.org/pub/ruby/${{ env.ABI_VERSION }}/ruby-${{ env.RUBY_VERSION }}.tar.gz
+ curl -X POST \
+ -H "Fastly-Key: ${{ secrets.FASTLY_PURGE_TOKEN }}" \
+ https://api.fastly.com/purge/cache.ruby-lang.org/pub/ruby/${{ env.ABI_VERSION }}/ruby-${{ env.RUBY_VERSION }}.tar.xz
+ curl -X POST \
+ -H "Fastly-Key: ${{ secrets.FASTLY_PURGE_TOKEN }}" \
+ https://api.fastly.com/purge/cache.ruby-lang.org/pub/ruby/${{ env.ABI_VERSION }}/ruby-${{ env.RUBY_VERSION }}.zip
+
+ - name: Create a release on GitHub
+ run: |
+ RELEASE_TAG=$(ruby tool/ruby-version.rb tag "${{ env.RUBY_VERSION }}")
+ echo $RELEASE_TAG
+ PREVIOUS_RELEASE_TAG=$(ruby tool/ruby-version.rb previous-tag "${{ env.RUBY_VERSION }}")
+ echo $PREVIOUS_RELEASE_TAG
+ tool/gen-github-release.rb $PREVIOUS_RELEASE_TAG $RELEASE_TAG --no-dry-run
+ env:
+ GITHUB_TOKEN: ${{ secrets.MATZBOT_AUTO_UPDATE_TOKEN }}
+
+ - name: Update versions index
+ run: |
+ curl -L -X POST \
+ -H "Authorization: Bearer ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }}" \
+ -H "Accept: application/vnd.github+json" \
+ -H "X-GitHub-Api-Version: 2022-11-28" \
+ https://api.github.com/repos/ruby/actions/dispatches \
+ -d '{"event_type": "update_index"}'
+
+ - name: Build and push Docker images
+ run: |
+ curl -L -X POST \
+ -H "Authorization: Bearer ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }}" \
+ -H "Accept: application/vnd.github+json" \
+ -H "X-GitHub-Api-Version: 2022-11-28" \
+ https://api.github.com/repos/ruby/docker-images/actions/workflows/build.yml/dispatches \
+ -d '{"ref": "master", "inputs": {"ruby_version": "${{ env.RUBY_VERSION }}"}}'
+
+ - name: Build snapcraft packages
+ run: |
+ curl -L -X POST \
+ -H "Authorization: Bearer ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }}" \
+ -H "Accept: application/vnd.github+json" \
+ -H "X-GitHub-Api-Version: 2022-11-28" \
+ https://api.github.com/repos/ruby/snap.ruby/dispatches \
+ -d '{"event_type": "build", "client_payload": {"ruby_version": "${{ env.RUBY_VERSION }}"}}'
+
+ - name: Store the latest LTS version of OpenSSL
+ run: |
+ echo "OPENSSL_VERSION=`curl -s https://api.github.com/repos/openssl/openssl/releases | jq -r '.[].tag_name | select(startswith("openssl-3.0"))' | sort -Vr | head -n1 | cut -d'-' -f2`" >> $GITHUB_ENV
+
+ - name: Update ruby-build definition
+ run: |
+ curl -L -X POST \
+ -H "Authorization: Bearer ${{ secrets.RUBY_BUILD_WORKFLOW_TOKEN }}" \
+ -H "Accept: application/vnd.github+json" \
+ -H "X-GitHub-Api-Version: 2022-11-28" \
+ https://api.github.com/repos/rbenv/ruby-build/dispatches \
+ -d '{"event_type": "update-ruby", "client_payload": {"ruby_version": "${{ env.RUBY_VERSION }}", "openssl_version": "${{ env.OPENSSL_VERSION }}"}}'
+
+ - name: Update all-ruby definition
+ run: |
+ curl -L -X POST \
+ -H "Authorization: Bearer ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }}" \
+ -H "Accept: application/vnd.github+json" \
+ -H "X-GitHub-Api-Version: 2022-11-28" \
+ https://api.github.com/repos/ruby/all-ruby/dispatches \
+ -d '{"event_type": "update"}'
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000000..5d4474d978
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,18 @@
+name: Start release workflow
+on:
+ push:
+ tags:
+ - '*'
+
+jobs:
+ notify:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Build release package
+ run: |
+ curl -L -X POST \
+ -H "Authorization: Bearer ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }}" \
+ -H "Accept: application/vnd.github+json" \
+ -H "X-GitHub-Api-Version: 2022-11-28" \
+ https://api.github.com/repos/ruby/actions/dispatches \
+ -d '{"event_type": "${{ github.ref }}"}'
diff --git a/.github/workflows/rjit-bindgen.yml b/.github/workflows/rjit-bindgen.yml
deleted file mode 100644
index 737266d17c..0000000000
--- a/.github/workflows/rjit-bindgen.yml
+++ /dev/null
@@ -1,86 +0,0 @@
-name: RJIT bindgen
-on:
- push:
- paths-ignore:
- - 'doc/**'
- - '**/man/*'
- - '**.md'
- - '**.rdoc'
- - '**/.document'
- - '.*.yml'
- pull_request:
- paths-ignore:
- - 'doc/**'
- - '**/man/*'
- - '**.md'
- - '**.rdoc'
- - '**/.document'
- - '.*.yml'
- merge_group:
-
-concurrency:
- group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
- cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
-
-permissions:
- contents: read
-
-jobs:
- make:
- strategy:
- matrix:
- include:
- - task: rjit-bindgen
- fail-fast: false
-
- runs-on: ubuntu-20.04
-
- if: >-
- ${{!(false
- || contains(github.event.head_commit.message, '[DOC]')
- || contains(github.event.head_commit.message, 'Document')
- || contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.title, 'Document')
- || contains(github.event.pull_request.labels.*.name, 'Document')
- || (github.event_name == 'push' && github.actor == 'dependabot[bot]')
- )}}
-
- steps:
- - name: Set up Ruby
- uses: ruby/setup-ruby@0cde4689ba33c09f1b890c1725572ad96751a3fc # v1.178.0
- with:
- ruby-version: '3.1'
-
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- with:
- sparse-checkout-cone-mode: false
- sparse-checkout: /.github
-
- - uses: ./.github/actions/setup/ubuntu
-
- - uses: ./.github/actions/setup/directories
- with:
- srcdir: src
- builddir: build
- makeup: true
-
- - name: Run configure
- run: ../src/configure -C --disable-install-doc --prefix=$(pwd)/install --enable-yjit=dev_nodebug
-
- - run: make
-
- - run: make install
-
- - run: make ${{ matrix.task }}
-
- - run: git diff --exit-code
- working-directory: src
-
- - uses: ./.github/actions/slack
- with:
- SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
- if: ${{ failure() }}
-
-defaults:
- run:
- working-directory: build
diff --git a/.github/workflows/rjit.yml b/.github/workflows/rjit.yml
deleted file mode 100644
index 509088db7d..0000000000
--- a/.github/workflows/rjit.yml
+++ /dev/null
@@ -1,114 +0,0 @@
-name: RJIT
-on:
- push:
- paths-ignore:
- - 'doc/**'
- - '**.md'
- - '**.rdoc'
- - '**/.document'
- - '**.[1-8]'
- - '**.ronn'
- - '.*.yml'
- pull_request:
- paths-ignore:
- - 'doc/**'
- - '**.md'
- - '**.rdoc'
- - '**/.document'
- - '**.[1-8]'
- - '**.ronn'
- - '.*.yml'
- merge_group:
-
-concurrency:
- group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
- cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
-
-permissions:
- contents: read
-
-jobs:
- make:
- strategy:
- matrix:
- # main variables included in the job name
- test_task: [check]
- run_opts: ['--rjit-call-threshold=1']
- arch: ['']
- fail-fast: false
-
- env:
- GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
- RUBY_DEBUG: ci
- SETARCH: ${{ matrix.arch && format('setarch {0}', matrix.arch) }}
-
- runs-on: ubuntu-22.04
-
- if: >-
- ${{!(false
- || contains(github.event.head_commit.message, '[DOC]')
- || contains(github.event.head_commit.message, 'Document')
- || contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.title, 'Document')
- || contains(github.event.pull_request.labels.*.name, 'Document')
- || (github.event_name == 'push' && github.actor == 'dependabot[bot]')
- )}}
-
- steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- with:
- sparse-checkout-cone-mode: false
- sparse-checkout: /.github
-
- - uses: ./.github/actions/setup/ubuntu
-
- - uses: ./.github/actions/setup/directories
- with:
- srcdir: src
- builddir: build
- makeup: true
-
- - name: Run configure
- env:
- arch: ${{ matrix.arch }}
- run: >-
- $SETARCH ../src/configure -C --disable-install-doc cppflags=-DRUBY_DEBUG
- ${arch:+--target=$arch-$OSTYPE --host=$arch-$OSTYPE}
-
- - run: $SETARCH make
-
- - name: make test
- run: |
- $SETARCH make -s test RUN_OPTS="$RUN_OPTS"
- timeout-minutes: 30
- env:
- GNUMAKEFLAGS: ''
- RUBY_TESTOPTS: '-v --tty=no'
- RUN_OPTS: ${{ matrix.run_opts }}
-
- - name: make test-all
- run: |
- $SETARCH make -s test-all RUN_OPTS="$RUN_OPTS"
- timeout-minutes: 40
- env:
- GNUMAKEFLAGS: ''
- RUBY_TESTOPTS: '-q --tty=no'
- RUN_OPTS: ${{ matrix.run_opts }}
-
- - name: make test-spec
- run: |
- $SETARCH make -s test-spec RUN_OPTS="$RUN_OPTS"
- timeout-minutes: 10
- env:
- GNUMAKEFLAGS: ''
- RUN_OPTS: ${{ matrix.run_opts }}
-
- - uses: ./.github/actions/slack
- with:
- label: ${{ matrix.run_opts }}
- SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
- if: ${{ failure() }}
-
-defaults:
- run:
- working-directory: build
diff --git a/.github/workflows/rust-warnings.yml b/.github/workflows/rust-warnings.yml
new file mode 100644
index 0000000000..a2e3208e52
--- /dev/null
+++ b/.github/workflows/rust-warnings.yml
@@ -0,0 +1,60 @@
+# Surface Rust warnings on PRs that touch any Rust code.
+# Not a required check so we never block people over new warnings
+# that might come from a new Rust version being released.
+name: Rust warnings
+on:
+ pull_request:
+ types:
+ - opened
+ - synchronize
+ - reopened
+ paths:
+ - '**.rs'
+ - '!**.inc.rs'
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ rust-warnings:
+ env:
+ GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
+
+ runs-on: ubuntu-24.04
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+
+ - name: Install Rust
+ run: rustup default beta
+
+ - name: Rust warnings
+ shell: bash
+ run: |
+ set -eu
+ cargo check --quiet --all-features --message-format=json \
+ | jq -r 'select(.message.level | IN("warning", "error")) | .message.rendered' \
+ | tee messages.txt
+ (exit "${PIPESTATUS[0]}") && ! grep --quiet '[^[:space:]]' messages.txt
+
+ - name: "📜 `rustdoc` warnings"
+ shell: bash
+ run: |
+ set -eu
+ cargo doc --document-private-items --all --no-deps --message-format=json \
+ | jq -r 'select(.message.level | IN("warning", "error")) | .message.rendered' \
+ | tee messages.txt
+ (exit "${PIPESTATUS[0]}") && ! grep --quiet '[^[:space:]]' messages.txt
diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml
index eeff61d558..c607098997 100644
--- a/.github/workflows/scorecards.yml
+++ b/.github/workflows/scorecards.yml
@@ -2,7 +2,7 @@
# by a third-party and are governed by separate terms of service, privacy
# policy, and support documentation.
-name: Scorecards supply-chain security
+name: Scorecard supply-chain security
on:
# For Branch-Protection check. Only the default branch is supported. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
@@ -10,7 +10,7 @@ on:
# To guarantee Maintained check is occasionally updated. See
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
schedule:
- - cron: '22 4 * * 2'
+ - cron: '39 3 * * 5'
# push:
# branches: [ "master" ]
@@ -19,8 +19,10 @@ permissions: read-all
jobs:
analysis:
- name: Scorecards analysis
+ name: Scorecard analysis
runs-on: ubuntu-latest
+ # `publish_results: true` only works when run from the default branch. conditional can be removed if disabled.
+ if: github.event.repository.default_branch == github.ref_name || github.event_name == 'pull_request'
permissions:
# Needed to upload the results to code-scanning dashboard.
security-events: write
@@ -31,21 +33,21 @@ jobs:
# actions: read
steps:
- - name: 'Checkout code'
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - name: "Checkout code"
+ uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
persist-credentials: false
- - name: 'Run analysis'
- uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3
+ - name: "Run analysis"
+ uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
with:
results_file: results.sarif
results_format: sarif
- # (Optional) Read-only PAT token. Uncomment the `repo_token` line below if:
+ # (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
# - you want to enable the Branch-Protection check on a *public* repository, or
- # - you are installing Scorecards on a *private* repository
- # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
- repo_token: ${{ secrets.SCORECARD_READ_TOKEN }}
+ # - you are installing Scorecard on a *private* repository
+ # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional.
+ # repo_token: ${{ secrets.SCORECARD_TOKEN }}
# Public repositories:
# - Publish results to OpenSSF REST API for easy access by consumers
@@ -56,17 +58,21 @@ jobs:
# of the value entered here.
publish_results: true
+ # (Optional) Uncomment file_mode if you have a .gitattributes with files marked export-ignore
+ # file_mode: git
+
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab.
- # - name: "Upload artifact"
- # uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
- # with:
- # name: SARIF file
- # path: results.sarif
- # retention-days: 5
+ - name: "Upload artifact"
+ uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
+ with:
+ name: SARIF file
+ path: results.sarif
+ retention-days: 5
- # Upload the results to GitHub's code scanning dashboard.
- - name: 'Upload to code-scanning'
- uses: github/codeql-action/upload-sarif@9fdb3e49720b44c48891d036bb502feb25684276 # v2.1.27
+ # Upload the results to GitHub's code scanning dashboard (optional).
+ # Commenting out will disable upload of results to your repo's Code Scanning dashboard
+ - name: "Upload to code-scanning"
+ uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: results.sarif
diff --git a/.github/workflows/spec_guards.yml b/.github/workflows/spec_guards.yml
index 64d2a5f1d0..cf4661555c 100644
--- a/.github/workflows/spec_guards.yml
+++ b/.github/workflows/spec_guards.yml
@@ -3,10 +3,12 @@ name: Rubyspec Version Guards Check
on:
push:
paths:
+ - '.github/workflows/spec_guards.yml'
- 'spec/**'
- '!spec/*.md'
pull_request:
paths:
+ - '.github/workflows/spec_guards.yml'
- 'spec/**'
- '!spec/*.md'
merge_group:
@@ -22,16 +24,14 @@ jobs:
rubyspec:
name: Rubyspec
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
- || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.title, 'Document')
- || contains(github.event.pull_request.labels.*.name, 'Document')
- || (github.event_name == 'push' && github.actor == 'dependabot[bot]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
)}}
strategy:
@@ -39,15 +39,16 @@ jobs:
# Specs from ruby/spec should still run on all supported Ruby versions.
# This also ensures the needed ruby_version_is guards are there, see spec/README.md.
ruby:
- - ruby-3.0
- - ruby-3.1
- ruby-3.2
- ruby-3.3
+ - ruby-3.4
+ - ruby-4.0
+ fail-fast: false
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- - uses: ruby/setup-ruby@0cde4689ba33c09f1b890c1725572ad96751a3fc # v1.178.0
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0
with:
ruby-version: ${{ matrix.ruby }}
bundler: none
diff --git a/.github/workflows/sync_default_gems.yml b/.github/workflows/sync_default_gems.yml
new file mode 100644
index 0000000000..9ff97d5a4e
--- /dev/null
+++ b/.github/workflows/sync_default_gems.yml
@@ -0,0 +1,77 @@
+name: Sync default gems
+
+env:
+ DEFAULT_GEM_SYNC_ENABLED: true
+
+on:
+ workflow_dispatch:
+ inputs:
+ gem:
+ required: true
+ description: 'Name of the gem to be synchronized'
+ type: string
+ before:
+ required: true
+ description: 'Gem commit SHA before sync'
+ type: string
+ after:
+ required: true
+ description: 'Gem commit SHA after sync'
+ type: string
+
+jobs:
+ sync_default_gems:
+ name: Sync default gem ${{ github.event.inputs.gem }}
+
+ permissions:
+ contents: write # for Git to git push
+
+ runs-on: ubuntu-latest
+
+ if: ${{ github.repository == 'ruby/ruby' }}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ name: Check out ruby/ruby
+ with:
+ token: ${{ github.repository == 'ruby/ruby' && secrets.MATZBOT_AUTO_UPDATE_TOKEN || secrets.GITHUB_TOKEN }}
+
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0
+ with:
+ ruby-version: '3.4'
+ bundler: none
+
+ - name: Run tool/sync_default_gems.rb
+ id: sync
+ run: |
+ ruby_before=$(git rev-parse HEAD)
+ set -x
+ ruby tool/sync_default_gems.rb "${gem_name}" "${gem_before}..${gem_after}"
+ if [[ "$(git rev-parse HEAD)" != "$ruby_before" ]]; then
+ echo update=true >> $GITHUB_OUTPUT
+ fi
+ env:
+ gem_name: ${{ github.event.inputs.gem }}
+ gem_before: ${{ github.event.inputs.before }}
+ gem_after: ${{ github.event.inputs.after }}
+ EMAIL: svn-admin@ruby-lang.org
+ GIT_AUTHOR_NAME: git
+ GIT_COMMITTER_NAME: git
+
+ - name: Push
+ run: |
+ git pull --rebase origin ${GITHUB_REF#refs/heads/}
+ git push origin ${GITHUB_REF#refs/heads/}
+ if: ${{ steps.sync.outputs.update && env.DEFAULT_GEM_SYNC_ENABLED == 'true' }}
+ env:
+ EMAIL: svn-admin@ruby-lang.org
+ GIT_AUTHOR_NAME: git
+ GIT_COMMITTER_NAME: git
+
+ - uses: ./.github/actions/slack
+ with:
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ label: "${{ github.event.inputs.gem }} (<https://github.com/${{ github.event.inputs.gem == 'rubygems' && 'rubygems' || 'ruby' }}/${{ github.event.inputs.gem }}/compare/${{ github.event.inputs.before }}...${{ github.event.inputs.after }}|diff>)"
+ event_name: workflow_dispatch
+ extra_channel_id: C05FPKAU743 # alerts-sync
+ if: ${{ failure() }}
diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml
index 747063f9cf..88c19b6fe6 100644
--- a/.github/workflows/ubuntu.yml
+++ b/.github/workflows/ubuntu.yml
@@ -24,6 +24,7 @@ jobs:
make:
strategy:
matrix:
+ # We enumerate every job in matrix.include to save build time
include:
- test_task: check
configure: 'cppflags=-DVM_CHECK_MODE'
@@ -33,15 +34,18 @@ jobs:
configure: '--disable-yjit'
- test_task: check
configure: '--enable-shared --enable-load-relative'
- - test_task: check
- configure: '--with-shared-gc'
- test_task: test-bundler-parallel
+ timeout: 50
- test_task: test-bundled-gems
- test_task: check
- os: ubuntu-20.04
+ os: ubuntu-24.04
+ extra_checks: [capi]
+ # ubuntu-24.04-arm jobs don't start on ruby/ruby as of 2025-10-29
+ #- test_task: check
+ # os: ubuntu-24.04-arm
fail-fast: false
- env:
+ env: &make-env
GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
RUBY_DEBUG: ci
@@ -50,15 +54,13 @@ jobs:
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
- || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.title, 'Document')
- || contains(github.event.pull_request.labels.*.name, 'Document')
- || (github.event_name == 'push' && github.actor == 'dependabot[bot]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
)}}
- steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ steps: &make-steps
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
sparse-checkout-cone-mode: false
sparse-checkout: /.github
@@ -67,10 +69,13 @@ jobs:
with:
arch: ${{ matrix.arch }}
- - uses: ruby/setup-ruby@0cde4689ba33c09f1b890c1725572ad96751a3fc # v1.178.0
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0
with:
- ruby-version: '3.0'
+ ruby-version: '3.1'
bundler: none
+ if: >-
+ ${{ !endsWith(matrix.os, 'arm')
+ && !endsWith(matrix.os, 'ppc64le') && !endsWith(matrix.os, 's390x') }}
- uses: ./.github/actions/setup/directories
with:
@@ -95,6 +100,12 @@ jobs:
- run: $SETARCH make
+ - run: $SETARCH make hello
+
+ - name: runirb
+ run: |
+ echo IRB::VERSION | $SETARCH make runirb RUNOPT="-- -f"
+
- name: Set test options for skipped tests
run: |
set -x
@@ -103,6 +114,7 @@ jobs:
if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }}
- name: Set up Launchable
+ id: launchable
uses: ./.github/actions/launchable/setup
with:
os: ${{ matrix.os || 'ubuntu-22.04' }}
@@ -111,17 +123,30 @@ jobs:
builddir: build
srcdir: src
continue-on-error: true
+ timeout-minutes: 3
+
+ # Avoid possible test failures with the zlib applying the following patch
+ # on s390x CPU architecture.
+ # https://github.com/madler/zlib/pull/410
+ - name: Disable DFLTCC
+ run: echo "DFLTCC=0" >> $GITHUB_ENV
+ if: ${{ endsWith(matrix.os, 's390x') }}
- name: make ${{ matrix.test_task }}
- run: >-
- $SETARCH make -s ${{ matrix.test_task }}
- ${TESTS:+TESTS="$TESTS"}
+ run: |
+ test -n "${LAUNCHABLE_STDOUT}" && exec 1> >(tee "${LAUNCHABLE_STDOUT}")
+ test -n "${LAUNCHABLE_STDERR}" && exec 2> >(tee "${LAUNCHABLE_STDERR}")
+
+ $SETARCH make -s ${{ matrix.test_task }} \
+ ${TESTS:+TESTS="$TESTS"} \
${{ !contains(matrix.test_task, 'bundle') && 'RUBYOPT=-w' || '' }}
- timeout-minutes: 40
+ timeout-minutes: ${{ matrix.timeout || 40 }}
env:
RUBY_TESTOPTS: '-q --tty=no'
TEST_BUNDLED_GEMS_ALLOW_FAILURES: ''
PRECHECK_BUNDLED_GEMS: 'no'
+ LAUNCHABLE_STDOUT: ${{ steps.launchable.outputs.stdout_report_path }}
+ LAUNCHABLE_STDERR: ${{ steps.launchable.outputs.stderr_report_path }}
- name: make skipped tests
run: |
@@ -132,9 +157,100 @@ jobs:
if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }}
continue-on-error: ${{ matrix.continue-on-skipped_tests || false }}
+ - name: test-pc
+ run: |
+ DESTDIR=${RUNNER_TEMP-${TMPDIR-/tmp}}/installed
+ $SETARCH make test-pc "DESTDIR=$DESTDIR"
+
+ - name: CAPI extensions
+ uses: ./.github/actions/capiext
+ with:
+ builddir: build
+ make: '$SETARCH make'
+ env:
+ RUBY_TESTOPTS: '-v --tty=no'
+ if: ${{ contains(matrix.extra_checks, 'capi') }}
+
+ - uses: ./.github/actions/slack
+ with:
+ label: ${{ matrix.test_task }} ${{ matrix.configure }}${{ matrix.arch }}${{ matrix.os }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
+
+ make-ibm:
+ strategy:
+ matrix:
+ include:
+ - test_task: check
+ os: ubuntu-24.04-ppc64le
+ - test_task: check
+ os: ubuntu-24.04-s390x
+ fail-fast: false
+
+ env: *make-env
+
+ runs-on: ${{ matrix.os }}
+
+ if: >-
+ ${{github.repository == 'ruby/ruby'
+ && !(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps: *make-steps
+
+ # Separated from `make` job to avoid making it a required status check
+ ruby-bench:
+ strategy:
+ matrix:
+ include:
+ # Using the same setup as ZJIT jobs
+ - bench_opts: '--warmup=1 --bench=1 --excludes=lobsters'
+
+ runs-on: ubuntu-24.04
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+
+ - uses: ./.github/actions/setup/ubuntu
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ srcdir: src
+ builddir: build
+ makeup: true
+
+ - name: Run configure
+ run: ../src/configure -C --disable-install-doc --prefix="$(pwd)/install"
+
+ - run: make install
+
+ - name: Checkout ruby-bench
+ uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ repository: ruby/ruby-bench
+ path: ruby-bench
+
+ # If you want to skip failing benchmark, consider using `--excludes`.
+ # e.g. `bench_opts: '--warmup=1 --bench=1 --excludes=railsbench,lobsters'`
+ - name: Run ruby-bench
+ run: ruby run_benchmarks.rb -e "ruby::../build/install/bin/ruby" ${{ matrix.bench_opts }}
+ working-directory: ruby-bench
+
- uses: ./.github/actions/slack
with:
- label: ${{ matrix.test_task }} ${{ matrix.configure }}${{ matrix.arch }}
+ label: ruby-bench ${{ matrix.bench_opts }} ${{ matrix.ruby_opts }}
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
if: ${{ failure() }}
diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml
index 9844dac1c8..0d2a6f0545 100644
--- a/.github/workflows/wasm.yml
+++ b/.github/workflows/wasm.yml
@@ -43,25 +43,23 @@ jobs:
env:
RUBY_TESTOPTS: '-q --tty=no'
GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
- WASI_SDK_VERSION_MAJOR: 20
+ WASI_SDK_VERSION_MAJOR: 25
WASI_SDK_VERSION_MINOR: 0
BINARYEN_VERSION: 113
WASMTIME_VERSION: v15.0.0
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
- || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.title, 'Document')
- || contains(github.event.pull_request.labels.*.name, 'Document')
- || (github.event_name == 'push' && github.actor == 'dependabot[bot]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
)}}
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
sparse-checkout-cone-mode: false
sparse-checkout: /.github
@@ -78,7 +76,7 @@ jobs:
sudo apt-get update -q || :
sudo apt-get install --no-install-recommends -q -y ruby make autoconf git wget
- wasi_sdk_deb="wasi-sdk_${WASI_SDK_VERSION_MAJOR}.${WASI_SDK_VERSION_MINOR}_amd64.deb"
+ wasi_sdk_deb="wasi-sdk-${WASI_SDK_VERSION_MAJOR}.${WASI_SDK_VERSION_MINOR}-x86_64-linux.deb"
wget "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VERSION_MAJOR}/${wasi_sdk_deb}"
sudo dpkg -i "$wasi_sdk_deb"
rm -f "$wasi_sdk_deb"
@@ -100,9 +98,9 @@ jobs:
run: |
echo "WASI_SDK_PATH=/opt/wasi-sdk" >> $GITHUB_ENV
- - uses: ruby/setup-ruby@0cde4689ba33c09f1b890c1725572ad96751a3fc # v1.178.0
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0
with:
- ruby-version: '3.0'
+ ruby-version: '3.1'
bundler: none
- name: Build baseruby
@@ -114,6 +112,12 @@ jobs:
make
make install
+ - name: Download config.guess with wasi version
+ run: |
+ rm tool/config.guess tool/config.sub
+ ruby tool/downloader.rb -d tool -e gnu config.guess config.sub
+ working-directory: src
+
- name: Run configure
run: |
../src/configure \
@@ -136,7 +140,7 @@ jobs:
- run: tar cfz ../install.tar.gz -C ../install .
- name: Upload artifacts
- uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
+ uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: ruby-wasm-install
path: ${{ github.workspace }}/install.tar.gz
@@ -164,7 +168,7 @@ jobs:
- name: Save Pull Request number
if: ${{ github.event_name == 'pull_request' }}
run: echo "${{ github.event.pull_request.number }}" >> ${{ github.workspace }}/github-pr-info.txt
- - uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
+ - uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
if: ${{ github.event_name == 'pull_request' }}
with:
name: github-pr-info
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index 8a910341de..1d44a5482c 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -9,13 +9,8 @@ on:
- '**/.document'
- '.*.yml'
pull_request:
- paths-ignore:
- - 'doc/**'
- - '**/man/*'
- - '**.md'
- - '**.rdoc'
- - '**/.document'
- - '.*.yml'
+ # Do not use paths-ignore for required status checks
+ # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks
merge_group:
concurrency:
@@ -30,126 +25,105 @@ jobs:
strategy:
matrix:
include:
- - vc: 2015
- vs: 2019
- vcvars: '10.0.14393.0 -vcvars_ver=14.0' # The oldest Windows 10 SDK w/ VC++ 2015 toolset (v140)
- - vs: 2019
- - vs: 2022
+ - os: 2022
+ vc: 2022
+ test_task: check
+ - os: 2025
+ vc: 2022
+ test_task: check
+ - os: 11-arm
+ test_task: 'btest test-basic test-tool' # check and test-spec are broken yet.
+ target: arm64
+ - os: 2025
+ vc: 2022
+ test_task: test-bundled-gems
fail-fast: false
- runs-on: windows-${{ matrix.vs < 2022 && '2019' || matrix.vs }}
+ runs-on: windows-${{ matrix.os }}
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
- || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.title, 'Document')
- || contains(github.event.pull_request.labels.*.name, 'Document')
- || (github.event_name == 'push' && github.actor == 'dependabot[bot]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
)}}
- name: VisualStudio ${{ matrix.vc || matrix.vs }}
+ name: Windows ${{ matrix.os }}/Visual C++ ${{ matrix.vc }} (${{ matrix.test_task }})
env:
GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
- OS_VER: windows-${{ matrix.vs < 2022 && '2019' || matrix.vs }}
- # FIXME: This is a workaround for the vcpkg's issue present as of openssl 3.1.1
- # where OpenSSL's default modules directory is incorrectly set to C:\vcpkg\packages\openssl_x64-windows\bin
- # cf. https://github.com/ruby/openssl/pull/635#issuecomment-1596833720
- OPENSSL_MODULES: C:\vcpkg\installed\x64-windows\bin
+ VCPKG_DEFAULT_TRIPLET: ${{ matrix.target || 'x64' }}-windows
steps:
- run: md build
working-directory:
- - name: find tools
- id: find-tools
- run: |
- ::- find needed tools
- set NEEDS=
- for %%I in (%NEEDED_TOOLS%) do if "%%~$PATH:I" == "" (
- call set NEEDS=%%NEEDS%% %%~nI
- ) else (
- echo %%I: %%~$PATH:I
- )
- echo.needs=%NEEDS%>>%GITHUB_OUTPUT%
- if "%NEEDS%" == "" (
- echo [debug] All needed tools found
- ) else (
- echo [warning^]Needs%NEEDS%
- )
- env:
- NEEDED_TOOLS: >-
- patch.exe
-
- - uses: msys2/setup-msys2@d40200dc2db4c351366b048a9565ad82919e1c24 # v2
- id: setup-msys2
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0
with:
- update: true
- install: >-
- ${{ steps.find-tools.outputs.needs }}
- if: ${{ steps.find-tools.outputs.needs != '' }}
-
- - uses: ruby/setup-ruby@0cde4689ba33c09f1b890c1725572ad96751a3fc # v1.178.0
- with:
- ruby-version: '3.0'
+ # windows-11-arm has only 3.4.1, 3.4.2, 3.4.3, head
+ ruby-version: ${{ !endsWith(matrix.os, 'arm') && '3.1' || '3.4' }}
bundler: none
windows-toolchain: none
- - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
- path: C:\vcpkg\downloads
- key: ${{ runner.os }}-vcpkg-download-${{ env.OS_VER }}-${{ github.sha }}
- restore-keys: |
- ${{ runner.os }}-vcpkg-download-${{ env.OS_VER }}-
- ${{ runner.os }}-vcpkg-download-
+ sparse-checkout-cone-mode: false
+ sparse-checkout: /.github
- - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ - uses: ./.github/actions/setup/directories
with:
- path: C:\vcpkg\installed
- key: ${{ runner.os }}-vcpkg-installed-${{ env.OS_VER }}-${{ github.sha }}
- restore-keys: |
- ${{ runner.os }}-vcpkg-installed-${{ env.OS_VER }}-
- ${{ runner.os }}-vcpkg-installed-
-
- - name: Install libraries with vcpkg
- run: |
- vcpkg --triplet x64-windows install libffi libyaml openssl readline zlib
+ srcdir: src
+ builddir: build
+ make-command: nmake
+ clean: true
- - name: Install libraries with scoop
+ - name: Install tools with scoop
run: |
- iex "& {$(irm get.scoop.sh)} -RunAsAdmin"
+ Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
+ iwr -useb get.scoop.sh | iex
Join-Path (Resolve-Path ~).Path "scoop\shims" >> $Env:GITHUB_PATH
+ scoop install vcpkg uutils-coreutils
shell: pwsh
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - name: Restore vcpkg artifact
+ id: restore-vcpkg
+ uses: actions/cache/restore@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2
with:
- sparse-checkout-cone-mode: false
- sparse-checkout: /.github
+ path: src\vcpkg_installed
+ key: windows-${{ matrix.os }}-vcpkg-${{ hashFiles('src/vcpkg.json') }}
- - uses: ./.github/actions/setup/directories
+ - name: Install libraries with vcpkg
+ run: |
+ vcpkg install --vcpkg-root=%USERPROFILE%\scoop\apps\vcpkg\current
+ working-directory: src
+ if: ${{ ! steps.restore-vcpkg.outputs.cache-hit }}
+
+ - name: Save vcpkg artifact
+ uses: actions/cache/save@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2
with:
- srcdir: src
- builddir: build
+ path: src\vcpkg_installed
+ key: windows-${{ matrix.os }}-vcpkg-${{ hashFiles('src/vcpkg.json') }}
+ if: ${{ ! steps.restore-vcpkg.outputs.cache-hit && (github.ref_name == 'master' || startsWith(github.ref_name, 'ruby_')) }}
- name: setup env
# Available Ruby versions: https://github.com/actions/runner-images/blob/main/images/windows/Windows2019-Readme.md#ruby
# %TEMP% is inconsistent with %TMP% and test-all expects they are consistent.
# https://github.com/actions/virtual-environments/issues/712#issuecomment-613004302
run: |
- set VS=${{ matrix.vs }}
- set VCVARS="C:\Program Files (x86)\Microsoft Visual Studio\%VS%\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
- if not exist %VCVARS% set VCVARS="C:\Program Files\Microsoft Visual Studio\%VS%\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
- set | C:\msys64\usr\bin\sort > old.env
- call %VCVARS% ${{ matrix.vcvars || '' }}
+ ::- Set up VC ${{ matrix.vc }}
+ set | sort > old.env
+ call ..\src\win32\vssetup.cmd ^
+ -arch=${{ matrix.target || 'amd64' }} ^
+ ${{ matrix.vcvars && '-vcvars_ver=' || '' }}${{ matrix.vcvars }}
nmake -f nul
- set TMP=%USERPROFILE%\AppData\Local\Temp
- set TEMP=%USERPROFILE%\AppData\Local\Temp
+ set TMP=%RUNNER_TEMP%
+ set TEMP=%RUNNER_TEMP%
set MAKEFLAGS=l
set /a TEST_JOBS=(15 * %NUMBER_OF_PROCESSORS% / 10) > nul
- set | C:\msys64\usr\bin\sort > new.env
- C:\msys64\usr\bin\comm -13 old.env new.env >> %GITHUB_ENV%
+ set RUBY_OPT_DIR=%GITHUB_WORKSPACE:\=/%/src/vcpkg_installed/%VCPKG_DEFAULT_TRIPLET%
+ set | sort > new.env
+ comm -13 old.env new.env >> %GITHUB_ENV%
del *.env
- name: baseruby version
@@ -158,24 +132,18 @@ jobs:
- name: compiler version
run: cl
- - name: link libraries
- run: |
- for %%I in (C:\vcpkg\installed\x64-windows\bin\*.dll) do (
- if not %%~nI == readline mklink %%~nxI %%I
- )
- # We use OpenSSL instealled by vcpkg instead
- - name: disable system OpenSSL
- run: |
- for %%I in (libcrypto-1_1-x64 libssl-1_1-x64) do (
- ren c:\Windows\System32\%%I.dll %%I.dll_
- )
- # windows-2019 image doesn't have OpenSSL as of 2023/9/14
- if: ${{ matrix.vs != 2019 }}
+ - name: volume info
+ run: Get-Volume
+ shell: pwsh
+ # TODO: We should use `../src` instead of `D:/a/ruby/ruby/src`
- name: Configure
run: >-
../src/win32/configure.bat --disable-install-doc
- --with-opt-dir=C:/vcpkg/installed/x64-windows
+ --with-opt-dir=%RUBY_OPT_DIR%
+ --with-gmp
+
+ - run: nmake prepare-vcpkg
- run: nmake incs
@@ -185,25 +153,48 @@ jobs:
# But not for this Visual Studio workflow. So here we extract gems before building.
- run: nmake extract-gems
- - run: nmake
+ # windows-11-arm runner cannot run `ruby tool/file2lastrev.rb --revision.h --output=revision.h`
+ - name: make revision.h
+ run: |
+ win32\lastrev.bat | win32\ifchange.bat --timestamp=.revision.time revision.h -
+ type revision.h
+ working-directory: src
- - run: nmake test
- timeout-minutes: 5
+ - run: nmake
- - run: nmake test-spec
- timeout-minutes: 10
+ - name: Set up Launchable
+ uses: ./.github/actions/launchable/setup
+ with:
+ os: windows-${{ matrix.os }}
+ launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }}
+ builddir: build
+ srcdir: src
+ test-task: ${{ matrix.test_task || 'check' }}
+ continue-on-error: true
+ if: ${{ matrix.test_task != 'test-bundled-gems' }}
+ timeout-minutes: 3
- - run: nmake test-all
+ - run: nmake ${{ matrix.test_task || 'check' }}
env:
- RUBY_TESTOPTS: -j${{ env.TEST_JOBS || 4 }} --job-status=normal
- timeout-minutes: 60
+ RUBY_TESTOPTS: -j${{ env.TEST_JOBS || 4 }}
+ timeout-minutes: 70
- uses: ./.github/actions/slack
with:
- label: VS${{ matrix.vc || matrix.vs }} / ${{ matrix.test_task || 'check' }}
+ label: Windows ${{ matrix.os }} / VC ${{ matrix.vc }} / ${{ matrix.test_task || 'check' }}
SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
if: ${{ failure() }}
+ result:
+ if: ${{ always() }}
+ name: ${{ github.workflow }} result
+ runs-on: windows-latest
+ needs: [make]
+ steps:
+ - run: exit 1
+ working-directory:
+ if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
+
defaults:
run:
working-directory: build
diff --git a/.github/workflows/wsl.yml b/.github/workflows/wsl.yml
new file mode 100644
index 0000000000..640f18ce42
--- /dev/null
+++ b/.github/workflows/wsl.yml
@@ -0,0 +1,70 @@
+name: Ubuntu on WSL
+
+on:
+ push:
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ pull_request:
+ # Do not use paths-ignore for required status checks
+ # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks
+ merge_group:
+
+jobs:
+ wsl:
+ runs-on: windows-2025
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - name: Install or update WSL
+ uses: Ubuntu/WSL/.github/actions/wsl-install@main
+ with:
+ distro: Ubuntu-24.04
+
+ - name: Install dependencies
+ uses: Ubuntu/WSL/.github/actions/wsl-bash@main
+ with:
+ distro: Ubuntu-24.04
+ working-dir: /tmp/github/
+ exec: |
+ DEBIAN_FRONTEND=noninteractive sudo apt update
+ DEBIAN_FRONTEND=noninteractive sudo apt install -y ruby build-essential autoconf libssl-dev libyaml-dev zlib1g-dev libgmp-dev libffi-dev
+
+ - name: Check out the repository
+ uses: Ubuntu/WSL/.github/actions/wsl-checkout@main
+ with:
+ distro: Ubuntu-24.04
+ working-dir: /tmp/github/
+ submodules: true
+
+ - name: Build
+ uses: Ubuntu/WSL/.github/actions/wsl-bash@main
+ with:
+ distro: Ubuntu-24.04
+ working-dir: /tmp/github/
+ exec: |
+ ./autogen.sh
+ ./configure --disable-install-doc
+ make ruby -j4
+ make extract-gems
+ make -j4
+
+ - name: Test
+ uses: Ubuntu/WSL/.github/actions/wsl-bash@main
+ with:
+ distro: Ubuntu-24.04
+ working-dir: /tmp/github/
+ exec: |
+ ./ruby -v
+ # make check TESTS="-j4" MSPECOPT="-j"
diff --git a/.github/workflows/yjit-macos.yml b/.github/workflows/yjit-macos.yml
index 9660572e99..a59b4d6508 100644
--- a/.github/workflows/yjit-macos.yml
+++ b/.github/workflows/yjit-macos.yml
@@ -1,6 +1,8 @@
-name: YJIT macOS Arm64
+name: YJIT macOS
on:
push:
+ branches:
+ - master
paths-ignore:
- 'doc/**'
- '**/man/*'
@@ -9,6 +11,10 @@ on:
- '**/.document'
- '.*.yml'
pull_request:
+ types:
+ - opened
+ - synchronize
+ - reopened
# Do not use paths-ignore for required status checks
# https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks
merge_group:
@@ -24,20 +30,18 @@ jobs:
cargo:
name: cargo test
- runs-on: ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-14' }}
+ runs-on: macos-14
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
- || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.title, 'Document')
- || contains(github.event.pull_request.labels.*.name, 'Document')
- || (github.event_name == 'push' && github.actor == 'dependabot[bot]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
)}}
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- run: RUST_BACKTRACE=1 cargo test
working-directory: yjit
@@ -68,20 +72,18 @@ jobs:
RUN_OPTS: ${{ matrix.yjit_opts }}
SPECOPTS: ${{ matrix.specopts }}
- runs-on: ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-14' }}
+ runs-on: macos-14
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
- || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.title, 'Document')
- || contains(github.event.pull_request.labels.*.name, 'Document')
- || (github.event_name == 'push' && github.actor == 'dependabot[bot]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
)}}
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
sparse-checkout-cone-mode: false
sparse-checkout: /.github
@@ -106,8 +108,17 @@ jobs:
- run: make
- - name: Enable YJIT through ENV
- run: echo "RUBY_YJIT_ENABLE=1" >> $GITHUB_ENV
+ - name: Verify that --yjit-dump-disasm works
+ run: |
+ ./miniruby --yjit-call-threshold=1 --yjit-dump-disasm -e0 | \
+ wc -l | \
+ ruby -ne 'raise "Disassembly seems broken in dev build (output has too few lines)" unless $_.to_i > 10'
+ if: ${{ contains(matrix.configure, 'jit=dev') }}
+
+ - name: Set ENV for YJIT
+ run: |
+ echo "RUBY_YJIT_ENABLE=1" >> $GITHUB_ENV
+ echo "RUBY_CRASH_REPORT=$(pwd)/rb_crash_%p.txt" >> $GITHUB_ENV
- name: Set test options for skipped tests
run: |
@@ -117,26 +128,35 @@ jobs:
if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }}
- name: Set up Launchable
+ id: launchable
uses: ./.github/actions/launchable/setup
with:
- os: ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-14' }}
+ os: macos-14
test-opts: ${{ matrix.configure }}
launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }}
builddir: build
srcdir: src
+ is-yjit: true
continue-on-error: true
+ timeout-minutes: 3
- name: make ${{ matrix.test_task }}
- run: >-
- make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"}
- RUN_OPTS="$RUN_OPTS"
- SPECOPTS="$SPECOPTS"
+ run: |
+ test -n "${LAUNCHABLE_STDOUT}" && exec 1> >(tee "${LAUNCHABLE_STDOUT}")
+ test -n "${LAUNCHABLE_STDERR}" && exec 2> >(tee "${LAUNCHABLE_STDERR}")
+
+ set -x
+ make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"} \
+ RUN_OPTS="$RUN_OPTS" \
+ SPECOPTS="$SPECOPTS"
timeout-minutes: 60
env:
RUBY_TESTOPTS: '-q --tty=no'
TEST_BUNDLED_GEMS_ALLOW_FAILURES: ''
SYNTAX_SUGGEST_TIMEOUT: '5'
PRECHECK_BUNDLED_GEMS: 'no'
+ LAUNCHABLE_STDOUT: ${{ steps.launchable.outputs.stdout_report_path }}
+ LAUNCHABLE_STDERR: ${{ steps.launchable.outputs.stderr_report_path }}
continue-on-error: ${{ matrix.continue-on-test_task || false }}
- name: make skipped tests
@@ -149,6 +169,13 @@ jobs:
if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }}
continue-on-error: ${{ matrix.continue-on-skipped_tests || false }}
+ - name: Dump crash logs
+ if: ${{ failure() }}
+ continue-on-error: true
+ run: |
+ tail --verbose --lines=+1 rb_crash_*.txt
+ exit 1
+
- uses: ./.github/actions/slack
with:
label: ${{ matrix.test_task }} ${{ matrix.configure }} ${{ matrix.yjit_opts }}
@@ -158,10 +185,11 @@ jobs:
result:
if: ${{ always() }}
name: ${{ github.workflow }} result
- runs-on: ${{ github.repository == 'ruby/ruby' && 'macos-arm-oss' || 'macos-14' }}
+ runs-on: macos-14
needs: [make]
steps:
- - run: exit 1
+ - name: ${{ github.workflow }} jobs have failed
+ run: exit 1
working-directory:
if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
diff --git a/.github/workflows/yjit-ubuntu.yml b/.github/workflows/yjit-ubuntu.yml
index 7b40eda16a..150f0b3275 100644
--- a/.github/workflows/yjit-ubuntu.yml
+++ b/.github/workflows/yjit-ubuntu.yml
@@ -25,18 +25,18 @@ jobs:
name: cargo test
# GitHub Action's image seems to already contain a Rust 1.58.0.
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.labels.*.name, 'Document')
- || (github.event_name == 'push' && github.actor == 'dependabot[bot]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
)}}
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
# For now we can't run cargo test --offline because it complains about the
# capstone dependency, even though the dependency is optional
@@ -57,18 +57,18 @@ jobs:
name: cargo clippy
# GitHub Action's image seems to already contain a Rust 1.58.0.
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.labels.*.name, 'Document')
- || (github.event_name == 'push' && github.actor == 'dependabot[bot]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
)}}
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
# Check that we don't have linting errors in release mode, too
- run: cargo clippy --all-targets --all-features
@@ -81,7 +81,9 @@ jobs:
include:
- test_task: 'yjit-bindgen'
hint: 'To fix: use patch in logs'
- configure: '--with-gcc=clang-12 --enable-yjit=dev'
+ # Build with YJIT+ZJIT for output that works in the most number of configurations
+ configure: '--with-gcc=clang-14 --enable-yjit=dev --enable-zjit'
+ libclang_path: '/usr/lib/llvm-14/lib/libclang.so.1'
- test_task: 'check'
# YJIT should be automatically built in release mode on x86-64 Linux with rustc present
@@ -100,43 +102,35 @@ jobs:
- test_task: 'test-bundled-gems'
configure: '--enable-yjit=dev'
- - test_task: 'yjit-bench'
- configure: '--enable-yjit=dev'
- yjit_bench_opts: '--yjit-stats'
- continue-on-test_task: true
-
env:
GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
RUN_OPTS: ${{ matrix.yjit_opts }}
YJIT_BENCH_OPTS: ${{ matrix.yjit_bench_opts }}
SPECOPTS: ${{ matrix.specopts }}
RUBY_DEBUG: ci
- BUNDLE_JOBS: 8 # for yjit-bench
RUST_BACKTRACE: 1
- runs-on: ubuntu-20.04
+ runs-on: ubuntu-22.04
if: >-
${{!(false
|| contains(github.event.head_commit.message, '[DOC]')
- || contains(github.event.head_commit.message, 'Document')
|| contains(github.event.pull_request.title, '[DOC]')
- || contains(github.event.pull_request.title, 'Document')
- || contains(github.event.pull_request.labels.*.name, 'Document')
- || (github.event_name == 'push' && github.actor == 'dependabot[bot]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
)}}
steps:
- - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with:
sparse-checkout-cone-mode: false
sparse-checkout: /.github
- uses: ./.github/actions/setup/ubuntu
- - uses: ruby/setup-ruby@0cde4689ba33c09f1b890c1725572ad96751a3fc # v1.178.0
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0
with:
- ruby-version: '3.0'
+ ruby-version: '3.1'
bundler: none
- uses: ./.github/actions/setup/directories
@@ -152,6 +146,12 @@ jobs:
if: ${{ matrix.rust_version }}
run: rustup install ${{ matrix.rust_version }} --profile minimal
+ - name: Remove cargo
+ # Since this tests a `rustc` build for release, remove `cargo` to ensure
+ # that only `rustc` is used.
+ if: ${{ contains(matrix.configure, 'rustc') }}
+ run: sudo rm $(which -a cargo | uniq)
+
- name: Run configure
run: ../src/configure -C --disable-install-doc --prefix=$(pwd)/install ${{ matrix.configure }}
@@ -162,28 +162,44 @@ jobs:
- run: make
- - name: Enable YJIT through ENV
- run: echo "RUBY_YJIT_ENABLE=1" >> $GITHUB_ENV
+ - name: Verify that --yjit-dump-disasm works
+ run: |
+ ./miniruby --yjit-call-threshold=1 --yjit-dump-disasm -e0 | \
+ wc -l | \
+ ruby -ne 'raise "Disassembly seems broken in dev build (output has too few lines)" unless $_.to_i > 10'
+ if: ${{ contains(matrix.configure, 'jit=dev') }}
+
+ - name: Set ENV for YJIT
+ run: |
+ echo "RUBY_YJIT_ENABLE=1" >> $GITHUB_ENV
+ echo "RUBY_CRASH_REPORT=$(pwd)/rb_crash_%p.txt" >> $GITHUB_ENV
# Check that the binary was built with YJIT
- name: Check YJIT enabled
run: ./miniruby --yjit -v | grep "+YJIT"
- name: Set up Launchable
+ id: launchable
uses: ./.github/actions/launchable/setup
with:
- os: ubuntu-20.04
+ os: ubuntu-22.04
test-opts: ${{ matrix.configure }}
launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }}
builddir: build
srcdir: src
+ is-yjit: true
continue-on-error: true
+ timeout-minutes: 3
- name: make ${{ matrix.test_task }}
- run: >-
- make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"}
- RUN_OPTS="$RUN_OPTS" MSPECOPT=--debug SPECOPTS="$SPECOPTS"
- YJIT_BENCH_OPTS="$YJIT_BENCH_OPTS" YJIT_BINDGEN_DIFF_OPTS="$YJIT_BINDGEN_DIFF_OPTS"
+ run: |
+ test -n "${LAUNCHABLE_STDOUT}" && exec 1> >(tee "${LAUNCHABLE_STDOUT}")
+ test -n "${LAUNCHABLE_STDERR}" && exec 2> >(tee "${LAUNCHABLE_STDERR}")
+
+ set -x
+ make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"} \
+ RUN_OPTS="$RUN_OPTS" MSPECOPT=--debug SPECOPTS="$SPECOPTS" \
+ YJIT_BENCH_OPTS="$YJIT_BENCH_OPTS" YJIT_BINDGEN_DIFF_OPTS="$YJIT_BINDGEN_DIFF_OPTS"
timeout-minutes: 90
env:
RUBY_TESTOPTS: '-q --tty=no'
@@ -191,14 +207,17 @@ jobs:
PRECHECK_BUNDLED_GEMS: 'no'
SYNTAX_SUGGEST_TIMEOUT: '5'
YJIT_BINDGEN_DIFF_OPTS: '--exit-code'
+ LIBCLANG_PATH: ${{ matrix.libclang_path }}
+ LAUNCHABLE_STDOUT: ${{ steps.launchable.outputs.stdout_report_path }}
+ LAUNCHABLE_STDERR: ${{ steps.launchable.outputs.stderr_report_path }}
continue-on-error: ${{ matrix.continue-on-test_task || false }}
- - name: Show ${{ github.event.pull_request.base.ref }} GitHub URL for yjit-bench comparison
- run: echo "https://github.com/${BASE_REPO}/commit/${BASE_SHA}"
- env:
- BASE_REPO: ${{ github.event.pull_request.base.repo.full_name }}
- BASE_SHA: ${{ github.event.pull_request.base.sha }}
- if: ${{ matrix.test_task == 'yjit-bench' && startsWith(github.event_name, 'pull') }}
+ - name: Dump crash logs
+ if: ${{ failure() }}
+ continue-on-error: true
+ run: |
+ tail --verbose --lines=+1 rb_crash_*.txt
+ exit 1
- uses: ./.github/actions/slack
with:
diff --git a/.github/workflows/zjit-macos.yml b/.github/workflows/zjit-macos.yml
new file mode 100644
index 0000000000..a638907811
--- /dev/null
+++ b/.github/workflows/zjit-macos.yml
@@ -0,0 +1,214 @@
+name: ZJIT macOS
+on:
+ push:
+ branches:
+ - master
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ pull_request:
+ types:
+ - opened
+ - synchronize
+ - reopened
+ # Do not use paths-ignore for required status checks
+ # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ make:
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - test_task: 'check'
+ run_opts: '--zjit-call-threshold=1'
+ specopts: '-T --zjit-call-threshold=1'
+ configure: '--enable-zjit=dev'
+
+ - test_task: 'check'
+ run_opts: '--zjit-disable-hir-opt --zjit-call-threshold=1'
+ specopts: '-T --zjit-disable-hir-opt -T --zjit-call-threshold=1'
+ configure: '--enable-zjit=dev'
+
+ - test_task: 'zjit-check' # zjit-test + quick feedback of test_zjit.rb
+ configure: '--enable-yjit=dev --enable-zjit'
+ rust_version: "1.85.0"
+
+ - test_task: 'ruby'
+ hint: 'combo build test'
+ configure: '--enable-yjit --enable-zjit'
+
+ env:
+ GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
+ RUN_OPTS: ${{ matrix.run_opts }}
+ SPECOPTS: ${{ matrix.specopts }}
+ TESTOPTS: ${{ matrix.testopts }}
+ ZJIT_RB_BUG: 1
+
+ runs-on: macos-14
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ sparse-checkout-cone-mode: false
+ sparse-checkout: /.github
+
+ - name: Install libraries
+ uses: ./.github/actions/setup/macos
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ srcdir: src
+ builddir: build
+ makeup: true
+ dummy-files: ${{ matrix.test_task == 'check' }}
+ # Set fetch-depth: 10 so that Launchable can receive commits information.
+ fetch-depth: 10
+
+ - name: Install Rust
+ if: ${{ matrix.rust_version }}
+ run: |
+ rustup install ${{ matrix.rust_version }} --profile minimal
+ rustup default ${{ matrix.rust_version }}
+
+ - uses: taiki-e/install-action@v2
+ with:
+ tool: nextest@0.9
+ if: ${{ matrix.test_task == 'zjit-check' }}
+
+ - name: Run configure
+ run: ../src/configure -C --disable-install-doc ${{ matrix.configure }}
+
+ - run: make
+
+ - name: Verify that --zjit-dump-disasm works
+ run: |
+ ./miniruby --zjit-call-threshold=1 --zjit-dump-disasm -e0 | \
+ wc -l | \
+ ruby -ne 'raise "Disassembly seems broken in dev build (output has too few lines)" unless $_.to_i > 10'
+ if: ${{ contains(matrix.configure, 'jit=dev') }}
+
+ - name: Set ENV for ZJIT
+ run: |
+ echo "RUBY_CRASH_REPORT=$(pwd)/rb_crash_%p.txt" >> $GITHUB_ENV
+
+ - name: make ${{ matrix.test_task }}
+ run: |
+ set -x
+ make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"} \
+ RUN_OPTS="$RUN_OPTS" \
+ SPECOPTS="$SPECOPTS" \
+ TESTOPTS="$TESTOPTS"
+ timeout-minutes: 60
+ env:
+ RUBY_TESTOPTS: '-q --tty=no'
+ EXCLUDES: '../src/test/.excludes-zjit'
+ TEST_BUNDLED_GEMS_ALLOW_FAILURES: ''
+ SYNTAX_SUGGEST_TIMEOUT: '5'
+ PRECHECK_BUNDLED_GEMS: 'no'
+ continue-on-error: ${{ matrix.continue-on-test_task || false }}
+
+ - name: Dump crash logs
+ if: ${{ failure() }}
+ continue-on-error: true
+ run: |
+ tail --verbose --lines=+1 rb_crash_*.txt
+ exit 1
+
+ - uses: ./.github/actions/slack
+ with:
+ label: ${{ matrix.test_task }} ${{ matrix.configure }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
+
+ result:
+ if: ${{ always() }}
+ name: ${{ github.workflow }} result
+ runs-on: macos-14
+ needs: [make]
+ steps:
+ - run: exit 1
+ working-directory:
+ if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
+
+ # Separated from `make` job to avoid making it a required status check for now
+ ruby-bench:
+ strategy:
+ matrix:
+ include:
+ # Test --call-threshold=2 with 2 iterations in total
+ - ruby_opts: '--zjit-call-threshold=2'
+ bench_opts: '--warmup=1 --bench=1 --excludes=lobsters'
+ configure: '--enable-zjit=dev_nodebug' # --enable-zjit=dev is too slow
+
+ runs-on: macos-14
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+
+ - uses: ./.github/actions/setup/macos
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ srcdir: src
+ builddir: build
+ makeup: true
+
+ - name: Run configure
+ run: ../src/configure -C --disable-install-doc --prefix="$(pwd)/install" ${{ matrix.configure }}
+
+ - run: make install
+
+ # setup/directories set MAKEFLAGS=-j4 for macOS, which randomly fails sqlite3.gem builds
+ - name: Unset MAKEFLAGS
+ run: echo "MAKEFLAGS=" >> "$GITHUB_ENV"
+
+ - name: Checkout ruby-bench
+ uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ repository: ruby/ruby-bench
+ path: ruby-bench
+
+ # If you want to skip failing benchmark, consider using `--excludes`.
+ # e.g. `bench_opts: '--warmup=1 --bench=1 --excludes=railsbench,lobsters'`
+ - name: Run ruby-bench
+ run: ruby run_benchmarks.rb -e "zjit::../build/install/bin/ruby ${{ matrix.ruby_opts }}" ${{ matrix.bench_opts }}
+ working-directory: ruby-bench
+
+ - uses: ./.github/actions/slack
+ with:
+ label: ruby-bench ${{ matrix.bench_opts }} ${{ matrix.ruby_opts }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
+
+defaults:
+ run:
+ working-directory: build
diff --git a/.github/workflows/zjit-ubuntu.yml b/.github/workflows/zjit-ubuntu.yml
new file mode 100644
index 0000000000..28bfec963e
--- /dev/null
+++ b/.github/workflows/zjit-ubuntu.yml
@@ -0,0 +1,267 @@
+name: ZJIT Ubuntu
+on:
+ push:
+ branches:
+ - master
+ paths-ignore:
+ - 'doc/**'
+ - '**/man/*'
+ - '**.md'
+ - '**.rdoc'
+ - '**/.document'
+ - '.*.yml'
+ pull_request:
+ types:
+ - opened
+ - synchronize
+ - reopened
+ # Do not use paths-ignore for required status checks
+ # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks
+ merge_group:
+
+concurrency:
+ group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }}
+ cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
+
+permissions:
+ contents: read
+
+jobs:
+ lint:
+ name: cargo clippy
+
+ runs-on: ubuntu-22.04
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+
+ - run: cargo clippy --all-targets --all-features
+ working-directory: zjit
+
+ make:
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - test_task: 'check'
+ run_opts: '--zjit-call-threshold=1'
+ specopts: '-T --zjit-call-threshold=1'
+ configure: '--enable-zjit=dev'
+
+ - test_task: 'check'
+ run_opts: '--zjit-disable-hir-opt --zjit-call-threshold=1'
+ specopts: '-T --zjit-disable-hir-opt -T --zjit-call-threshold=1'
+ configure: '--enable-zjit=dev'
+
+ # The optimizer benefits from at least 1 iteration of profiling. Also, many
+ # regression tests in bootstraptest/test_yjit.rb assume call-threshold=2.
+ - test_task: 'btest'
+ run_opts: '--zjit-call-threshold=2'
+ configure: '--enable-zjit=dev'
+
+ - test_task: 'zjit-check' # zjit-test + quick feedback of test_zjit.rb
+ configure: '--enable-yjit --enable-zjit=dev'
+ rust_version: '1.85.0'
+
+ - test_task: 'zjit-bindgen'
+ hint: 'To fix: use patch in logs'
+ # Build with YJIT+ZJIT for output that works in the most number of configurations
+ configure: '--enable-zjit=dev --enable-yjit --with-gcc=clang-16'
+ clang_path: '/usr/bin/clang-16'
+ runs-on: 'ubuntu-24.04' # for clang-16
+
+ - test_task: 'test-bundled-gems'
+ configure: '--enable-zjit=dev'
+ run_opts: '--zjit-call-threshold=1'
+
+ env:
+ GITPULLOPTIONS: --no-tags origin ${{ github.ref }}
+ RUN_OPTS: ${{ matrix.run_opts }}
+ YJIT_BENCH_OPTS: ${{ matrix.yjit_bench_opts }}
+ SPECOPTS: ${{ matrix.specopts }}
+ TESTOPTS: ${{ matrix.testopts }}
+ RUBY_DEBUG: ci
+ BUNDLE_JOBS: 8 # for yjit-bench
+ RUST_BACKTRACE: 1
+ ZJIT_RB_BUG: 1
+
+ runs-on: ${{ matrix.runs-on || 'ubuntu-22.04' }}
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ sparse-checkout-cone-mode: false
+ sparse-checkout: /.github
+
+ - uses: ./.github/actions/setup/ubuntu
+
+ - uses: ruby/setup-ruby@b90be12699fdfcbee4440c2bba85f6f460446bb0 # v1.279.0
+ with:
+ ruby-version: '3.1'
+ bundler: none
+
+ - uses: taiki-e/install-action@v2
+ with:
+ tool: nextest@0.9
+ if: ${{ matrix.test_task == 'zjit-check' }}
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ srcdir: src
+ builddir: build
+ makeup: true
+ dummy-files: ${{ matrix.test_task == 'check' }}
+ # Set fetch-depth: 10 so that Launchable can receive commits information.
+ fetch-depth: 10
+
+ - name: Install Rust
+ if: ${{ matrix.rust_version }}
+ run: |
+ rustup install ${{ matrix.rust_version }} --profile minimal
+ rustup default ${{ matrix.rust_version }}
+
+ - name: Install rustfmt
+ if: ${{ matrix.test_task == 'zjit-bindgen' }}
+ run: rustup component add rustfmt
+
+ - name: Run configure
+ run: ../src/configure -C --disable-install-doc --prefix=$(pwd)/install ${{ matrix.configure }}
+
+ - run: make incs
+
+ - run: make prepare-gems
+ if: ${{ matrix.test_task == 'test-bundled-gems' }}
+
+ - run: make
+
+ - name: Verify that --zjit-dump-disasm works
+ run: |
+ ./miniruby --zjit-call-threshold=1 --zjit-dump-disasm -e0 | \
+ wc -l | \
+ ruby -ne 'raise "Disassembly seems broken in dev build (output has too few lines)" unless $_.to_i > 10'
+ if: ${{ contains(matrix.configure, 'jit=dev') }}
+
+ # Check that the binary was built with ZJIT
+ - name: Check ZJIT enabled
+ run: ./miniruby --zjit -v | grep "+ZJIT"
+ if: ${{ matrix.configure != '--disable-zjit' }}
+
+ - name: Set ENV for ZJIT
+ run: |
+ echo "RUBY_CRASH_REPORT=$(pwd)/rb_crash_%p.txt" >> $GITHUB_ENV
+
+ - name: make ${{ matrix.test_task }}
+ run: |
+ set -x
+ make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"} \
+ RUN_OPTS="$RUN_OPTS" MSPECOPT=--debug SPECOPTS="$SPECOPTS" \
+ TESTOPTS="$TESTOPTS" \
+ ZJIT_BINDGEN_DIFF_OPTS="$ZJIT_BINDGEN_DIFF_OPTS"
+ timeout-minutes: 90
+ env:
+ RUBY_TESTOPTS: '-q --tty=no'
+ EXCLUDES: '../src/test/.excludes-zjit'
+ TEST_BUNDLED_GEMS_ALLOW_FAILURES: ''
+ PRECHECK_BUNDLED_GEMS: 'no'
+ SYNTAX_SUGGEST_TIMEOUT: '5'
+ ZJIT_BINDGEN_DIFF_OPTS: '--exit-code'
+ CLANG_PATH: ${{ matrix.clang_path }}
+ continue-on-error: ${{ matrix.continue-on-test_task || false }}
+
+ - name: Dump crash logs
+ if: ${{ failure() }}
+ continue-on-error: true
+ run: |
+ tail --verbose --lines=+1 rb_crash_*.txt
+ exit 1
+
+ - uses: ./.github/actions/slack
+ with:
+ label: ${{ matrix.test_task }} ${{ matrix.configure }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
+
+ result:
+ if: ${{ always() }}
+ name: ${{ github.workflow }} result
+ runs-on: ubuntu-22.04
+ needs: [make]
+ steps:
+ - name: ${{ github.workflow }} jobs have failed
+ run: exit 1
+ working-directory:
+ if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }}
+
+ # Separated from `make` job to avoid making it a required status check for now
+ ruby-bench:
+ strategy:
+ matrix:
+ include:
+ # Test --call-threshold=2 with 2 iterations in total
+ - ruby_opts: '--zjit-call-threshold=2'
+ bench_opts: '--warmup=1 --bench=1 --excludes=lobsters'
+ configure: '--enable-zjit=dev_nodebug' # --enable-zjit=dev is too slow
+
+ runs-on: ubuntu-24.04
+
+ if: >-
+ ${{!(false
+ || contains(github.event.head_commit.message, '[DOC]')
+ || contains(github.event.pull_request.title, '[DOC]')
+ || contains(github.event.pull_request.labels.*.name, 'Documentation')
+ || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]')
+ )}}
+
+ steps:
+ - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+
+ - uses: ./.github/actions/setup/ubuntu
+
+ - uses: ./.github/actions/setup/directories
+ with:
+ srcdir: src
+ builddir: build
+ makeup: true
+
+ - name: Run configure
+ run: ../src/configure -C --disable-install-doc --prefix="$(pwd)/install" ${{ matrix.configure }}
+
+ - run: make install
+
+ - name: Checkout ruby-bench
+ uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ with:
+ repository: ruby/ruby-bench
+ path: ruby-bench
+
+ # If you want to skip failing benchmark, consider using `--excludes`.
+ # e.g. `bench_opts: '--warmup=1 --bench=1 --excludes=railsbench,lobsters'`
+ - name: Run ruby-bench
+ run: ruby run_benchmarks.rb -e "zjit::../build/install/bin/ruby ${{ matrix.ruby_opts }}" ${{ matrix.bench_opts }}
+ working-directory: ruby-bench
+
+ - uses: ./.github/actions/slack
+ with:
+ label: ruby-bench ${{ matrix.bench_opts }} ${{ matrix.ruby_opts }}
+ SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot
+ if: ${{ failure() }}
+
+defaults:
+ run:
+ working-directory: build
diff --git a/.gitignore b/.gitignore
index b6beba3b3e..6cf5fb5f32 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,6 +21,7 @@
*.pch
*.pdb
*.rbinc
+*.rbbin
*.rej
*.s
*.sav
@@ -144,7 +145,6 @@ lcov*.info
/verconf.h
/verconf.mk
/web
-/yasmdata.rb
# /bin/
@@ -234,7 +234,6 @@ lcov*.info
# for `make test-bundler`
/.rspec_status
-/tool/bundler/*.lock
# /tool/
/tool/config.guess
@@ -243,17 +242,14 @@ lcov*.info
# /win32/
/win32/*.ico
-# RJIT
-/include/ruby-*/*/rb_rjit_min_header-*.h
-/lib/ruby_vm/rjit/instruction.rb
-/lib/ruby_vm/rjit/instruction.rb
-/rjit_config.h
-/rb_rjit_header.h*
# YJIT
/yjit-bench
/yjit_exit_locations.dump
+# Rust
+/target
+
# /wasm/
/wasm/tests/*.wasm
@@ -276,6 +272,7 @@ lcov*.info
/prism/prettyprint.c
/prism/serialize.c
/prism/token_type.c
+/prism/srcs.mk
# tool/update-NEWS-gemlist.rb
/bundled_gems.json
diff --git a/.rdoc_options b/.rdoc_options
index 57e03c9dd7..89265cafd4 100644
--- a/.rdoc_options
+++ b/.rdoc_options
@@ -2,6 +2,38 @@
page_dir: doc
charset: UTF-8
encoding: UTF-8
-main_page: README.md
+main_page: index.md
title: Documentation for Ruby development version
visibility: :private
+rdoc_include:
+- doc
+
+exclude:
+- \.gemspec\z
+- lib/set/subclass_compatible.rb
+
+autolink_excluded_words:
+- Box
+- Class
+- Method
+- Module
+- Process
+- RDoc
+- Ruby
+- Set
+- ZJIT
+- YJIT
+
+canonical_root: https://docs.ruby-lang.org/en/master
+
+footer_content:
+ Ruby:
+ Documentation: index.html
+ Official Website: https://www.ruby-lang.org/
+ Playground: https://ruby.github.io/play-ruby/
+ Resources:
+ GitHub: https://github.com/ruby/ruby
+ Issue Tracker: https://bugs.ruby-lang.org/projects/ruby-master/issues
+ RubyGems: https://rubygems.org/
+ Community:
+ X: https://x.com/rubylangorg
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 06de3dd493..0000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,153 +0,0 @@
-# -*- YAML -*-
-# Copyright (C) 2011 Urabe, Shyouhei. All rights reserved.
-#
-# This file is a part of the programming language Ruby. Permission is hereby
-# granted, to either redistribute or modify this file, provided that the
-# conditions mentioned in the file COPYING are met. Consult the file for
-# details.
-
-# When you see Travis CI issues, or you are interested in understanding how to
-# manage, please check the link below.
-# https://github.com/ruby/ruby/wiki/CI-Servers#travis-ci
-
-# We enable Travis on the specific branches or forked repositories here.
-if: >-
- (repo != ruby/ruby OR branch = master OR branch =~ /^ruby_\d_\d$/)
- AND (commit_message !~ /\[DOC\]/)
-
-language: c
-
-os: linux
-
-dist: jammy
-
-git:
- quiet: true
-
-env:
- global:
- - NPROC="$(nproc)"
- - JOBS="-j${NPROC}"
- # SETARCH are overridden when necessary. See below.
- - SETARCH=
- # 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"
- # -g0 disables backtraces when SEGV. Do not set that.
- - debugflags=-ggdb3
- - RUBY_TESTOPTS="$JOBS -q --tty=no"
-
-.org.ruby-lang.ci.matrix-definitions:
- - &gcc-11
- compiler: gcc-11
- before_install:
- - tool/travis_retry.sh sudo bash -c "rm -rf '${TRAVIS_ROOT}/var/lib/apt/lists/'* && exec apt-get update -yq"
- - >-
- tool/travis_retry.sh sudo -E apt-get $travis_apt_get_options install
- gcc-11
- g++-11
- libffi-dev
- libncurses-dev
- libncursesw5-dev
- libreadline-dev
- libssl-dev
- libyaml-dev
- openssl
- zlib1g-dev
- - gcc-11 --version
- - &arm64-linux
- name: arm64-linux
- arch: arm64
- <<: *gcc-11
- - &ppc64le-linux
- name: ppc64le-linux
- arch: ppc64le
- <<: *gcc-11
- - &s390x-linux
- name: s390x-linux
- arch: s390x
- <<: *gcc-11
- env:
- # Avoid possible test failures with the zlib applying the following patch
- # on s390x CPU architecture.
- # https://github.com/madler/zlib/pull/410
- - DFLTCC=0
- - &arm32-linux
- name: arm32-linux
- arch: arm64
- # https://packages.ubuntu.com/jammy/crossbuild-essential-armhf
- compiler: arm-linux-gnueabihf-gcc
- env:
- - SETARCH='setarch linux32 --verbose --32bit'
- # Still keep the -O1 for only arm32, while we want to test with the
- # default optflags -O3.
- # Because bootstraptest/test_ractor.rb fails with segfualt with the
- # default -O3.
- # https://bugs.ruby-lang.org/issues/19981
- - optflags=-O1
- 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
- crossbuild-essential-armhf
- libc6:armhf
- libstdc++-10-dev:armhf
- libffi-dev:armhf
- libncurses-dev:armhf
- libncursesw5-dev:armhf
- libreadline-dev:armhf
- libssl-dev:armhf
- libyaml-dev:armhf
- linux-libc-dev:armhf
- zlib1g-dev:armhf
-
-matrix:
- include:
- - <<: *arm64-linux
- - <<: *ppc64le-linux
- - <<: *s390x-linux
- # FIXME: lib/rubygems/util.rb:104 glob_files_in_dir -
- # <internal:dir>:411:in glob: File name too long - (Errno::ENAMETOOLONG)
- # https://github.com/rubygems/rubygems/issues/7132
- - <<: *arm32-linux
- allow_failures:
- # Allow failures for the unstable jobs.
- # - name: arm64-linux
- - name: ppc64le-linux
- - name: s390x-linux
- # The 2nd arm64 pipeline may be unstable.
- # - name: arm32-linux
- fast_finish: true
-
-before_script:
- - lscpu
- - ./autogen.sh
- - mkdir build
- - cd build
- - $SETARCH ../configure -C --disable-install-doc --prefix=$(pwd)/install
- - $SETARCH make -s $JOBS
- - make -s $JOBS install
- # Useful info to report issues to the Ruby.
- - $SETARCH $(pwd)/install/bin/ruby -v
- # Useful info To report issues to the RubyGems.
- - $SETARCH $(pwd)/install/bin/gem env
-
-script:
- - $SETARCH make -s test
- - ../tool/travis_wait.sh $SETARCH make -s test-all RUBYOPT="-w"
- - ../tool/travis_wait.sh $SETARCH make -s test-spec
-
-# We want to be notified when something happens.
-notifications:
- webhooks:
- urls:
- # ruby-lang slack: ruby/simpler-alerts-bot (travis)
- - secure: mRsoS/UbqDkKkW5p3AEqM27d4SZnV6Gsylo3bm8T/deltQzTsGzZwrm7OIBXZv0UFZdE68XmPlyHfZFLSP2V9QZ7apXMf9/vw0GtcSe1gchtnjpAPF6lYBn7nMCbVPPx9cS0dwL927fjdRM1vj7IKZ2bk4F0lAJ25R25S6teqdk=
- on_success: never
- on_failure: always
- email:
- recipients:
- - jaruga@ruby-lang.org
- on_success: never
- on_failure: always
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 13df6087ca..35e79dd3b9 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1 +1 @@
-See ["Contributing to Ruby"](https://docs.ruby-lang.org/en/master/contributing_md.html), which includes setup and build instructions.
+See ["Contributing to Ruby"](https://docs.ruby-lang.org/en/master/contributing/contributing_md.html), which includes setup and build instructions.
diff --git a/COPYING b/COPYING
index 48e5a96de7..428ce03ed7 100644
--- a/COPYING
+++ b/COPYING
@@ -1,3 +1,5 @@
+{日本語}[rdoc-ref:COPYING.ja]
+
Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.jp>.
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:
diff --git a/COPYING.ja b/COPYING.ja
index 230376bc60..5de2dbcc8f 100644
--- a/COPYING.ja
+++ b/COPYING.ja
@@ -1,3 +1,5 @@
+{English}[rdoc-ref:COPYING]
+
本プログラムはフリーソフトウェアです.2-clause BSDL
または以下に示す条件で本プログラムを再配布できます
2-clause BSDLについてはBSDLファイルを参照して下さい.
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000000..9a4b2ebbba
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,193 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "capstone"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "015ef5d5ca1743e3f94af9509ba6bd2886523cfee46e48d15c2ef5216fd4ac9a"
+dependencies = [
+ "capstone-sys",
+ "libc",
+]
+
+[[package]]
+name = "capstone-sys"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2267cb8d16a1e4197863ec4284ffd1aec26fe7e57c58af46b02590a0235809a0"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "cc"
+version = "1.2.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "525046617d8376e3db1deffb079e91cef90a89fc3ca5c185bbf8c9ecdd15cd5c"
+dependencies = [
+ "shlex",
+]
+
+[[package]]
+name = "console"
+version = "0.15.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
+dependencies = [
+ "encode_unicode",
+ "lazy_static",
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "encode_unicode"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
+
+[[package]]
+name = "insta"
+version = "1.43.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "154934ea70c58054b556dd430b99a98c2a7ff5309ac9891597e339b5c28f4371"
+dependencies = [
+ "console",
+ "once_cell",
+ "similar",
+]
+
+[[package]]
+name = "jit"
+version = "0.1.0"
+
+[[package]]
+name = "lazy_static"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+
+[[package]]
+name = "libc"
+version = "0.2.171"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
+
+[[package]]
+name = "once_cell"
+version = "1.21.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
+
+[[package]]
+name = "ruby"
+version = "0.0.0"
+dependencies = [
+ "yjit",
+ "zjit",
+]
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "similar"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32fea41aca09ee824cc9724996433064c89f7777e60762749a4170a14abbfa21"
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+
+[[package]]
+name = "yjit"
+version = "0.1.0"
+dependencies = [
+ "capstone",
+ "jit",
+]
+
+[[package]]
+name = "zjit"
+version = "0.0.1"
+dependencies = [
+ "capstone",
+ "insta",
+ "jit",
+]
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000000..521129d92d
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,60 @@
+# This is the root Cargo [workspace](https://doc.rust-lang.org/cargo/reference/workspaces.html)
+# and the root package for all the rust code that are statically linked into ruby. Rust tooling
+# limitations means all Rust code need to share a single archive library (staticlib) at the
+# integration point with non-rust code. (See rustlang/rust#44322 and #104707 for a taste of
+# the linking challenges.)
+#
+# Do not add required dependencies. This is a policy that helps downstream consumers and give
+# us tight control over what we ship. All of the optional dependencies are used exclusively
+# during development.
+#
+# Release builds avoid Cargo entirely because offline builds can fail even when none of the
+# optional dependencies are built (rust-lang/cargo#10352).
+
+[workspace]
+members = ["zjit", "yjit", "jit"]
+
+[package]
+name = "ruby"
+version = "0.0.0"
+edition = "2024"
+rust-version = "1.85.0"
+publish = false # Don't publish to crates.io
+
+[dependencies]
+yjit = { path = "yjit", optional = true }
+zjit = { path = "zjit", optional = true }
+
+[lib]
+crate-type = ["staticlib"]
+path = "ruby.rs"
+
+[features]
+disasm = ["yjit?/disasm", "zjit?/disasm"]
+runtime_checks = ["yjit?/runtime_checks", "zjit?/runtime_checks"]
+yjit = [ "dep:yjit" ]
+zjit = [ "dep:zjit" ]
+
+[profile.dev]
+opt-level = 0
+debug = true
+debug-assertions = true
+overflow-checks = true
+
+[profile.dev_nodebug]
+inherits = "dev"
+
+[profile.stats]
+inherits = "release"
+
+[profile.release]
+# NOTE: --enable-yjit and zjit builds use `rustc` without going through Cargo. You
+# might want to update the `rustc` invocation if you change this profile.
+opt-level = 3
+# The extra robustness that comes from checking for arithmetic overflow is
+# worth the performance cost for the compiler.
+overflow-checks = true
+# Generate debug info
+debug = true
+# Use ThinLTO. Much smaller output for a small amount of build time increase.
+lto = "thin"
diff --git a/LEGAL b/LEGAL
index c931291c8a..2777aa2c14 100644
--- a/LEGAL
+++ b/LEGAL
@@ -702,48 +702,22 @@ mentioned below.
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
-[ext/json/generator/generator.c]
+[ext/json/vendor/fpconv.c]
- The file contains the following copyright notice.
+ This file is under the {Boost Software License}[rdoc-ref:@Boost+Software+License+1.0].
- >>>
- Copyright 2001-2004:: Unicode, Inc.
-
- Disclaimer::
-
- This source code is provided as is by Unicode, Inc. No claims are
- made as to fitness for any particular purpose. No warranties of any
- kind are expressed or implied. The recipient agrees to determine
- applicability of information provided. If this file has been
- purchased on magnetic or optical media from Unicode, Inc., the
- sole remedy for any claim will be exchange of defective media
- within 90 days of receipt.
-
- Limitations on Rights to Redistribute This Code::
-
- Unicode, Inc. hereby grants the right to freely use the information
- supplied in this file in the creation of products supporting the
- Unicode Standard, and to make copies of this file in any form
- for internal or external distribution as long as this notice
- remains attached.
-
-[ext/nkf/nkf-utf8/config.h]
-[ext/nkf/nkf-utf8/nkf.c]
-[ext/nkf/nkf-utf8/utf8tbl.c]
-
- These files are under the following license. So to speak, it is
- copyrighted semi-public-domain software.
+[ext/json/vendor/jeaiii-ltoa.h]
>>>
- Copyright (C) 1987:: Fujitsu LTD. (Itaru ICHIKAWA)
+ Copyright (c) 2024,2025 Enrico Thierbach - https://github.com/radiospiel
+ Copyright (c) 2022 James Edward Anhalt III - https://github.com/jeaiii/itoa
- Everyone is permitted to do anything on this program
- including copying, modifying, improving,
- as long as you don't try to pretend that you wrote it.
- i.e., the above copyright notice has to appear in all copies.
- Binary distribution requires original version messages.
- You don't have to ask before copying, redistribution or publishing.
- THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE.
+ {MIT License}[rdoc-ref:@MIT+License]
+
+[ext/json/vendor/ryu.h]
+ This file is adapted from the Ryu algorithm by Ulf Adams https://github.com/ulfjack/ryu.
+ It is dual-licensed under {Apache License 2.0}[rdoc-ref:@Apache+License+2.0] OR
+ {Boost Software License 1.0}[rdoc-ref:@Boost+Software+License+1.0].
[ext/psych]
[test/psych]
@@ -1091,3 +1065,236 @@ mentioned below.
From ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change
paragraph 3 above is now null and void.
+
+== Boost Software License 1.0
+
+>>>
+ Boost Software License - Version 1.0 - August 17th, 2003
+
+ Permission is hereby granted, free of charge, to any person or organization
+ obtaining a copy of the software and accompanying documentation covered by
+ this license (the "Software") to use, reproduce, display, distribute,
+ execute, and transmit the Software, and to prepare derivative works of the
+ Software, and to permit third-parties to whom the Software is furnished to
+ do so, all subject to the following:
+
+ The copyright notices in the Software and this entire statement, including
+ the above license grant, this restriction and the following disclaimer,
+ must be included in all copies of the Software, in whole or in part, and
+ all derivative works of the Software, unless such copies or derivative
+ works are solely in the form of machine-executable object code generated by
+ a source language processor.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+ SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+ FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+== Apache License 2.0
+
+>>>
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ a. You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ b. You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ c. You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ d. If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ >>>
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/NEWS.md b/NEWS.md
index 38afa0982b..2b021e7cdd 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -1,154 +1,87 @@
-# NEWS for Ruby 3.4.0
+# NEWS for Ruby 4.1.0
This document is a list of user-visible feature changes
-since the **3.3.0** release, except for bug fixes.
+since the **4.0.0** release, except for bug fixes.
Note that each entry is kept to a minimum, see links for details.
## Language changes
-* String literals in files without a `frozen_string_literal` comment now emit a deprecation warning
- when they are mutated.
- These warnings can be enabled with `-W:deprecated` or by setting `Warning[:deprecated] = true`.
- To disable this change, you can run Ruby with the `--disable-frozen-string-literal`
- command line argument. [[Feature #20205]]
+## Core classes updates
-* `it` is added to reference a block parameter. [[Feature #18980]]
+Note: We're only listing outstanding class updates.
-* Keyword splatting `nil` when calling methods is now supported.
- `**nil` is treated similarly to `**{}`, passing no keywords,
- and not calling any conversion methods. [[Bug #20064]]
+* Method
-* Block passing is no longer allowed in index assignment
- (e.g. `a[0, &b] = 1`). [[Bug #19918]]
+ * `Method#source_location`, `Proc#source_location`, and
+ `UnboundMethod#source_location` now return extended location
+ information with 5 elements: `[path, start_line, start_column,
+ end_line, end_column]`. The previous 2-element format `[path,
+ line]` can still be obtained by calling `.take(2)` on the result.
+ [[Feature #6012]]
-* Keyword arguments are no longer allowed in index assignment
- (e.g. `a[0, kw: 1] = 2`). [[Bug #20218]]
+* Set
-## Core classes updates
+ * A deprecated behavior, `Set#to_set`, `Range#to_set`, and
+ `Enumerable#to_set` accepting arguments, was removed. [[Feature #21390]]
-Note: We're only listing outstanding class updates.
+## Stdlib updates
-* Exception
+### The following bundled gems are added.
- * Exception#set_backtrace now accepts arrays of `Thread::Backtrace::Location`.
- `Kernel#raise`, `Thread#raise` and `Fiber#raise` also accept this new format. [[Feature #13557]]
-* Range
+We only list stdlib changes that are notable feature changes.
- * Range#size now raises TypeError if the range is not iterable. [[Misc #18984]]
+Other changes are listed in the following sections. We also listed release
+history from the previous bundled version that is Ruby 3.4.0 if it has GitHub
+releases.
-## Stdlib updates
+### The following bundled gem is promoted from default gems.
-* Tempfile
-
- * The keyword argument `anonymous: true` is implemented for `Tempfile.create`.
- `Tempfile.create(anonymous: true)` removes the created temporary file immediately.
- So applications don't need to remove the file.
- [[Feature #20497]]
-
-The following default gems are updated.
-
-* RubyGems 3.6.0.dev
-* bundler 2.6.0.dev
-* erb 4.0.4
-* fiddle 1.1.3
-* io-console 0.7.2
-* irb 1.13.1
-* json 2.7.2
-* net-http 0.4.1
-* optparse 0.5.0
-* prism 0.29.0
-* rdoc 6.7.0
-* reline 0.5.8
-* resolv 0.4.0
-* stringio 3.1.1
-* strscan 3.1.1
-
-The following bundled gems are updated.
-
-* minitest 5.23.1
-* rake 13.2.1
-* test-unit 3.6.2
-* rexml 3.2.8
-* net-ftp 0.3.5
-* net-imap 0.4.12
-* net-smtp 0.5.0
-* rbs 3.4.4
-* typeprof 0.21.11
-* debug 1.9.2
-* racc 1.8.0
-
-The following bundled gems are promoted from default gems.
-
-* mutex_m 0.2.0
-* getoptlong 0.2.1
-* base64 0.2.0
-* bigdecimal 3.1.8
-* observer 0.1.2
-* abbrev 0.1.2
-* resolv-replace 0.1.1
-* rinda 0.2.0
-* drb 2.2.1
-* nkf 0.2.0
-* syslog 0.1.2
-* csv 3.3.0
-
-See GitHub releases like [GitHub Releases of Logger](https://github.com/ruby/logger/releases) or changelog for details of the default gems or bundled gems.
+* tsort 0.2.0
-## Supported platforms
+### The following default gem is added.
-## Compatibility issues
+### The following default gems are updated.
+
+* RubyGems 4.1.0.dev
+* bundler 4.1.0.dev
+* prism 1.8.0
+* stringio 3.2.1.dev
+* strscan 3.1.7.dev
-* Error messages and backtrace displays have been changed.
- * Use a single quote instead of a backtick as a opening quote. [[Feature #16495]]
- * Display a class name before a method name (only when the class has a permanent name). [[Feature #19117]]
- * `Kernel#caller`, `Thread::Backtrace::Location`'s methods, etc. are also changed accordingly.
- ```
- Old:
- test.rb:1:in `foo': undefined method `time' for an instance of Integer
- from test.rb:2:in `<main>'
+### The following bundled gems are updated.
- New:
- test.rb:1:in 'Object#foo': undefined method 'time' for an instance of Integer
- from test.rb:2:in `<main>'
- ```
+* minitest 6.0.1
+* test-unit 3.7.7
+* rss 0.3.2
+* net-imap 0.6.2
+* rbs 3.10.2
+* typeprof 0.31.1
+* debug 1.11.1
+* mutex_m 0.3.0
+* resolv-replace 0.2.0
+* rdoc 7.1.0
+
+### RubyGems and Bundler
+
+Ruby 4.0 bundled RubyGems and Bundler version 4. see the following links for details.
+
+## Supported platforms
+
+## Compatibility issues
## Stdlib compatibility issues
## C API updates
-* `rb_newobj` and `rb_newobj_of` (and corresponding macros `RB_NEWOBJ`, `RB_NEWOBJ_OF`, `NEWOBJ`, `NEWOBJ_OF`) have been removed. [[Feature #20265]]
-* Removed deprecated function `rb_gc_force_recycle`. [[Feature #18290]]
-
## Implementation improvements
-* `Array#each` is rewritten in Ruby for better performance [[Feature #20182]].
+### Ractor
+
+A lot of work has gone into making Ractors more stable, performant, and usable. These improvements bring Ractor implementation closer to leaving experimental status.
## JIT
-## Miscellaneous changes
-
-* Passing a block to a method which doesn't use the passed block will show
- a warning on verbose mode (`-w`).
- [[Feature #15554]]
-
-* Redefining some core methods that are specially optimized by the interpreter
- and JIT like `String.freeze` or `Integer#+` now emits a performance class
- warning (`-W:performance` or `Warning[:performance] = true`).
- [[Feature #20429]]
-
-[Feature #13557]: https://bugs.ruby-lang.org/issues/13557
-[Feature #15554]: https://bugs.ruby-lang.org/issues/15554
-[Feature #16495]: https://bugs.ruby-lang.org/issues/16495
-[Feature #18290]: https://bugs.ruby-lang.org/issues/18290
-[Feature #18980]: https://bugs.ruby-lang.org/issues/18980
-[Misc #18984]: https://bugs.ruby-lang.org/issues/18984
-[Feature #19117]: https://bugs.ruby-lang.org/issues/19117
-[Bug #19918]: https://bugs.ruby-lang.org/issues/19918
-[Bug #20064]: https://bugs.ruby-lang.org/issues/20064
-[Feature #20182]: https://bugs.ruby-lang.org/issues/20182
-[Feature #20205]: https://bugs.ruby-lang.org/issues/20205
-[Bug #20218]: https://bugs.ruby-lang.org/issues/20218
-[Feature #20265]: https://bugs.ruby-lang.org/issues/20265
-[Feature #20429]: https://bugs.ruby-lang.org/issues/20429
+[Feature #6012]: https://bugs.ruby-lang.org/issues/6012
+[Feature #21390]: https://bugs.ruby-lang.org/issues/21390
diff --git a/README.ja.md b/README.ja.md
index 0d2d309fb8..9bbc3a83a5 100644
--- a/README.ja.md
+++ b/README.ja.md
@@ -1,10 +1,10 @@
[![Actions Status: MinGW](https://github.com/ruby/ruby/workflows/MinGW/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"MinGW")
-[![Actions Status: RJIT](https://github.com/ruby/ruby/workflows/RJIT/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"RJIT")
[![Actions Status: Ubuntu](https://github.com/ruby/ruby/workflows/Ubuntu/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"Ubuntu")
[![Actions Status: Windows](https://github.com/ruby/ruby/workflows/Windows/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"Windows")
[![AppVeyor status](https://ci.appveyor.com/api/projects/status/0sy8rrxut4o0k960/branch/master?svg=true)](https://ci.appveyor.com/project/ruby/ruby/branch/master)
[![Travis Status](https://app.travis-ci.com/ruby/ruby.svg?branch=master)](https://app.travis-ci.com/ruby/ruby)
-[![Cirrus Status](https://api.cirrus-ci.com/github/ruby/ruby.svg)](https://cirrus-ci.com/github/ruby/ruby/master)
+
+[English](rdoc-ref:README.md)
# Rubyとは
@@ -41,11 +41,15 @@ https://www.ruby-lang.org/ja/downloads/
ミラーをGitHubに公開しています. 以下のコマンドでリポジトリを取得できます.
- $ git clone https://github.com/ruby/ruby.git
+```console
+$ git clone https://github.com/ruby/ruby.git
+```
他のブランチの一覧は次のコマンドで見られます.
- $ git ls-remote https://github.com/ruby/ruby.git
+```console
+$ git ls-remote https://github.com/ruby/ruby.git
+```
Rubyリポジトリの本来のmasterは https://git.ruby-lang.org/ruby.git にあります.
コミッタはこちらを使います.
diff --git a/README.md b/README.md
index eb24a73ee3..02435b419e 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,10 @@
[![Actions Status: MinGW](https://github.com/ruby/ruby/workflows/MinGW/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"MinGW")
-[![Actions Status: RJIT](https://github.com/ruby/ruby/workflows/RJIT/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"RJIT")
[![Actions Status: Ubuntu](https://github.com/ruby/ruby/workflows/Ubuntu/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"Ubuntu")
[![Actions Status: Windows](https://github.com/ruby/ruby/workflows/Windows/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"Windows")
[![Travis Status](https://app.travis-ci.com/ruby/ruby.svg?branch=master)](https://app.travis-ci.com/ruby/ruby)
+[日本語](rdoc-ref:README.ja.md)
+
# What is Ruby?
Ruby is an interpreted object-oriented programming language often
@@ -86,7 +87,7 @@ Bugs should be reported at https://bugs.ruby-lang.org. Read ["Reporting Issues"]
## Contributing
-See ["Contributing to Ruby"](https://docs.ruby-lang.org/en/master/contributing_md.html), which includes setup and build instructions.
+See ["Contributing to Ruby"](https://docs.ruby-lang.org/en/master/contributing/contributing_md.html), which includes setup and build instructions.
## The Author
diff --git a/addr2line.c b/addr2line.c
index 02a3e617a6..19a6a425c1 100644
--- a/addr2line.c
+++ b/addr2line.c
@@ -56,11 +56,11 @@
# ifdef _AIX
#pragma alloca
# else
-# ifndef alloca /* predefined by HP cc +Olibcalls */
+# ifndef alloca /* predefined by HP cc +Olibcalls */
void *alloca();
# endif
# endif /* AIX */
-# endif /* HAVE_ALLOCA_H */
+# endif /* HAVE_ALLOCA_H */
# ifndef UNREACHABLE
# define UNREACHABLE __builtin_unreachable()
# endif
@@ -220,13 +220,13 @@ uleb128(const char **p)
unsigned long r = 0;
int s = 0;
for (;;) {
- unsigned char b = (unsigned char)*(*p)++;
- if (b < 0x80) {
- r += (unsigned long)b << s;
- break;
- }
- r += (b & 0x7f) << s;
- s += 7;
+ unsigned char b = (unsigned char)*(*p)++;
+ if (b < 0x80) {
+ r += (unsigned long)b << s;
+ break;
+ }
+ r += (b & 0x7f) << s;
+ s += 7;
}
return r;
}
@@ -237,18 +237,18 @@ sleb128(const char **p)
long r = 0;
int s = 0;
for (;;) {
- unsigned char b = (unsigned char)*(*p)++;
- if (b < 0x80) {
- if (b & 0x40) {
- r -= (0x80 - b) << s;
- }
- else {
- r += (b & 0x3f) << s;
- }
- break;
- }
- r += (b & 0x7f) << s;
- s += 7;
+ unsigned char b = (unsigned char)*(*p)++;
+ if (b < 0x80) {
+ if (b & 0x40) {
+ r -= (0x80 - b) << s;
+ }
+ else {
+ r += (b & 0x3f) << s;
+ }
+ break;
+ }
+ r += (b & 0x7f) << s;
+ s += 7;
}
return r;
}
@@ -257,16 +257,16 @@ static const char *
get_nth_dirname(unsigned long dir, const char *p, FILE *errout)
{
if (!dir--) {
- return "";
+ return "";
}
while (dir--) {
- while (*p) p++;
- p++;
- if (!*p) {
- kprintf("Unexpected directory number %lu in %s\n",
- dir, binary_filename);
- return "";
- }
+ while (*p) p++;
+ p++;
+ if (!*p) {
+ kprintf("Unexpected directory number %lu in %s\n",
+ dir, binary_filename);
+ return "";
+ }
}
return p;
}
@@ -296,9 +296,11 @@ fill_filename(int file, uint8_t format, uint16_t version, const char *include_di
for (i = 1; i <= file; i++) {
filename = p;
if (!*p) {
+#ifndef __APPLE__
/* Need to output binary file name? */
kprintf("Unexpected file number %d in %s at %tx\n",
file, binary_filename, filenames - obj->mapped);
+#endif
return;
}
while (*p) p++;
@@ -319,19 +321,19 @@ fill_filename(int file, uint8_t format, uint16_t version, const char *include_di
static void
fill_line(int num_traces, void **traces, uintptr_t addr, int file, int line,
- uint8_t format, uint16_t version, const char *include_directories, const char *filenames,
- obj_info_t *obj, line_info_t *lines, int offset, FILE *errout)
+ uint8_t format, uint16_t version, const char *include_directories, const char *filenames,
+ obj_info_t *obj, line_info_t *lines, int offset, FILE *errout)
{
int i;
addr += obj->base_addr - obj->vmaddr;
for (i = offset; i < num_traces; i++) {
- uintptr_t a = (uintptr_t)traces[i];
- /* We assume one line code doesn't result >100 bytes of native code.
+ uintptr_t a = (uintptr_t)traces[i];
+ /* We assume one line code doesn't result >100 bytes of native code.
We may want more reliable way eventually... */
- if (addr < a && a < addr + 100) {
- fill_filename(file, format, version, include_directories, filenames, &lines[i], obj, errout);
- lines[i].line = line;
- }
+ if (addr < a && a < addr + 100) {
+ fill_filename(file, format, version, include_directories, filenames, &lines[i], obj, errout);
+ lines[i].line = line;
+ }
}
}
@@ -362,8 +364,8 @@ parse_debug_line_header(obj_info_t *obj, const char **pp, struct LineNumberProgr
header->format = 4;
if (header->unit_length == 0xffffffff) {
- header->unit_length = *(uint64_t *)p;
- p += sizeof(uint64_t);
+ header->unit_length = *(uint64_t *)p;
+ p += sizeof(uint64_t);
header->format = 8;
}
@@ -427,7 +429,7 @@ parse_debug_line_header(obj_info_t *obj, const char **pp, struct LineNumberProgr
static int
parse_debug_line_cu(int num_traces, void **traces, const char **debug_line,
- obj_info_t *obj, line_info_t *lines, int offset, FILE *errout)
+ obj_info_t *obj, line_info_t *lines, int offset, FILE *errout)
{
const char *p = (const char *)*debug_line;
struct LineNumberProgramHeader header;
@@ -448,105 +450,105 @@ parse_debug_line_cu(int num_traces, void **traces, const char **debug_line,
return -1;
is_stmt = header.default_is_stmt;
-#define FILL_LINE() \
- do { \
- fill_line(num_traces, traces, addr, file, line, \
+#define FILL_LINE() \
+ do { \
+ fill_line(num_traces, traces, addr, file, line, \
header.format, \
header.version, \
header.include_directories, \
header.filenames, \
- obj, lines, offset, errout); \
- /*basic_block = prologue_end = epilogue_begin = 0;*/ \
+ obj, lines, offset, errout); \
+ /*basic_block = prologue_end = epilogue_begin = 0;*/ \
} while (0)
while (p < header.cu_end) {
- unsigned long a;
- unsigned char op = *p++;
- switch (op) {
- case DW_LNS_copy:
- FILL_LINE();
- break;
- case DW_LNS_advance_pc:
- a = uleb128(&p) * header.minimum_instruction_length;
- addr += a;
- break;
- case DW_LNS_advance_line: {
- long a = sleb128(&p);
- line += a;
- break;
- }
- case DW_LNS_set_file:
- file = (unsigned int)uleb128(&p);
- break;
- case DW_LNS_set_column:
- /*column = (unsigned int)*/(void)uleb128(&p);
- break;
- case DW_LNS_negate_stmt:
- is_stmt = !is_stmt;
- break;
- case DW_LNS_set_basic_block:
- /*basic_block = 1; */
- break;
- case DW_LNS_const_add_pc:
- a = ((255UL - header.opcode_base) / header.line_range) *
- header.minimum_instruction_length;
- addr += a;
- break;
- case DW_LNS_fixed_advance_pc:
- a = *(uint16_t *)p;
- p += sizeof(uint16_t);
- addr += a;
- break;
- case DW_LNS_set_prologue_end:
- /* prologue_end = 1; */
- break;
- case DW_LNS_set_epilogue_begin:
- /* epilogue_begin = 1; */
- break;
- case DW_LNS_set_isa:
- /* isa = (unsigned int)*/(void)uleb128(&p);
- break;
- case 0:
- a = uleb128(&p);
- op = *p++;
- switch (op) {
- case DW_LNE_end_sequence:
- /* end_sequence = 1; */
- FILL_LINE();
- addr = 0;
- file = 1;
- line = 1;
- /* column = 0; */
- is_stmt = header.default_is_stmt;
- /* end_sequence = 0; */
- /* isa = 0; */
- break;
- case DW_LNE_set_address:
- addr = *(unsigned long *)p;
- p += sizeof(unsigned long);
- break;
- case DW_LNE_define_file:
- kprintf("Unsupported operation in %s\n",
- binary_filename);
- break;
- case DW_LNE_set_discriminator:
- /* TODO:currently ignore */
- uleb128(&p);
- break;
- default:
- kprintf("Unknown extended opcode: %d in %s\n",
- op, binary_filename);
- }
- break;
- default: {
+ unsigned long a;
+ unsigned char op = *p++;
+ switch (op) {
+ case DW_LNS_copy:
+ FILL_LINE();
+ break;
+ case DW_LNS_advance_pc:
+ a = uleb128(&p) * header.minimum_instruction_length;
+ addr += a;
+ break;
+ case DW_LNS_advance_line: {
+ long a = sleb128(&p);
+ line += a;
+ break;
+ }
+ case DW_LNS_set_file:
+ file = (unsigned int)uleb128(&p);
+ break;
+ case DW_LNS_set_column:
+ /*column = (unsigned int)*/(void)uleb128(&p);
+ break;
+ case DW_LNS_negate_stmt:
+ is_stmt = !is_stmt;
+ break;
+ case DW_LNS_set_basic_block:
+ /*basic_block = 1; */
+ break;
+ case DW_LNS_const_add_pc:
+ a = ((255UL - header.opcode_base) / header.line_range) *
+ header.minimum_instruction_length;
+ addr += a;
+ break;
+ case DW_LNS_fixed_advance_pc:
+ a = *(uint16_t *)p;
+ p += sizeof(uint16_t);
+ addr += a;
+ break;
+ case DW_LNS_set_prologue_end:
+ /* prologue_end = 1; */
+ break;
+ case DW_LNS_set_epilogue_begin:
+ /* epilogue_begin = 1; */
+ break;
+ case DW_LNS_set_isa:
+ /* isa = (unsigned int)*/(void)uleb128(&p);
+ break;
+ case 0:
+ a = uleb128(&p);
+ op = *p++;
+ switch (op) {
+ case DW_LNE_end_sequence:
+ /* end_sequence = 1; */
+ FILL_LINE();
+ addr = 0;
+ file = 1;
+ line = 1;
+ /* column = 0; */
+ is_stmt = header.default_is_stmt;
+ /* end_sequence = 0; */
+ /* isa = 0; */
+ break;
+ case DW_LNE_set_address:
+ addr = *(unsigned long *)p;
+ p += sizeof(unsigned long);
+ break;
+ case DW_LNE_define_file:
+ kprintf("Unsupported operation in %s\n",
+ binary_filename);
+ break;
+ case DW_LNE_set_discriminator:
+ /* TODO:currently ignore */
+ uleb128(&p);
+ break;
+ default:
+ kprintf("Unknown extended opcode: %d in %s\n",
+ op, binary_filename);
+ }
+ break;
+ default: {
uint8_t adjusted_opcode = op - header.opcode_base;
uint8_t operation_advance = adjusted_opcode / header.line_range;
/* NOTE: this code doesn't support VLIW */
addr += operation_advance * header.minimum_instruction_length;
line += header.line_base + (adjusted_opcode % header.line_range);
- FILL_LINE();
- }
- }
+ FILL_LINE();
+ }
+ }
}
*debug_line = (char *)p;
return 0;
@@ -554,17 +556,17 @@ parse_debug_line_cu(int num_traces, void **traces, const char **debug_line,
static int
parse_debug_line(int num_traces, void **traces,
- const char *debug_line, unsigned long size,
- obj_info_t *obj, line_info_t *lines, int offset, FILE *errout)
+ const char *debug_line, unsigned long size,
+ obj_info_t *obj, line_info_t *lines, int offset, FILE *errout)
{
const char *debug_line_end = debug_line + size;
while (debug_line < debug_line_end) {
- if (parse_debug_line_cu(num_traces, traces, &debug_line, obj, lines, offset, errout))
- return -1;
+ if (parse_debug_line_cu(num_traces, traces, &debug_line, obj, lines, offset, errout))
+ return -1;
}
if (debug_line != debug_line_end) {
- kprintf("Unexpected size of .debug_line in %s\n",
- binary_filename);
+ kprintf("Unexpected size of .debug_line in %s\n",
+ binary_filename);
}
return 0;
}
@@ -572,7 +574,7 @@ parse_debug_line(int num_traces, void **traces,
/* read file and fill lines */
static uintptr_t
fill_lines(int num_traces, void **traces, int check_debuglink,
- obj_info_t **objp, line_info_t *lines, int offset, FILE *errout);
+ obj_info_t **objp, line_info_t *lines, int offset, FILE *errout);
static void
append_obj(obj_info_t **objp)
@@ -600,7 +602,7 @@ append_obj(obj_info_t **objp)
// check the path pattern of "/usr/lib/debug/usr/bin/ruby.debug"
static void
follow_debuglink(const char *debuglink, int num_traces, void **traces,
- obj_info_t **objp, line_info_t *lines, int offset, FILE *errout)
+ obj_info_t **objp, line_info_t *lines, int offset, FILE *errout)
{
static const char global_debug_dir[] = "/usr/lib/debug";
const size_t global_debug_dir_len = sizeof(global_debug_dir) - 1;
@@ -610,13 +612,13 @@ follow_debuglink(const char *debuglink, int num_traces, void **traces,
p = strrchr(binary_filename, '/');
if (!p) {
- return;
+ return;
}
p[1] = '\0';
len = strlen(binary_filename);
if (len >= PATH_MAX - global_debug_dir_len)
- len = PATH_MAX - global_debug_dir_len - 1;
+ len = PATH_MAX - global_debug_dir_len - 1;
memmove(binary_filename + global_debug_dir_len, binary_filename, len);
memcpy(binary_filename, global_debug_dir, global_debug_dir_len);
len += global_debug_dir_len;
@@ -635,12 +637,13 @@ follow_debuglink_build_id(const char *build_id, size_t build_id_size, int num_tr
obj_info_t **objp, line_info_t *lines, int offset, FILE *errout)
{
static const char global_debug_dir[] = "/usr/lib/debug/.build-id/";
+ static const char debug_suffix[] = ".debug";
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;
+ if (PATH_MAX < global_debug_dir_len + build_id_size * 2 + sizeof(debug_suffix)) return;
memcpy(binary_filename, global_debug_dir, global_debug_dir_len);
p = binary_filename + global_debug_dir_len;
@@ -651,7 +654,7 @@ follow_debuglink_build_id(const char *build_id, size_t build_id_size, int num_tr
*p++ = tbl[n % 16];
if (i == 0) *p++ = '/';
}
- strcpy(p, ".debug");
+ memcpy(p, debug_suffix, sizeof(debug_suffix));
append_obj(objp);
o2 = *objp;
@@ -2029,14 +2032,14 @@ uncompress_debug_section(ElfW(Shdr) *shdr, char *file, char **ptr)
int ret = 0;
if (chdr->ch_type != ELFCOMPRESS_ZLIB) {
- /* unsupported compression type */
- return 0;
+ /* unsupported compression type */
+ return 0;
}
*ptr = malloc(destsize);
if (!*ptr) return 0;
ret = uncompress((Bytef *)*ptr, &destsize,
- (const Bytef*)chdr + sizeof(ElfW(Chdr)),
+ (const Bytef*)chdr + sizeof(ElfW(Chdr)),
shdr->sh_size - sizeof(ElfW(Chdr)));
if (ret != Z_OK) goto fail;
return destsize;
@@ -2051,7 +2054,7 @@ fail:
/* read file and fill lines */
static uintptr_t
fill_lines(int num_traces, void **traces, int check_debuglink,
- obj_info_t **objp, line_info_t *lines, int offset, FILE *errout)
+ obj_info_t **objp, line_info_t *lines, int offset, FILE *errout)
{
int i, j;
char *shstr;
@@ -2069,40 +2072,40 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
fd = open(binary_filename, O_RDONLY);
if (fd < 0) {
- goto fail;
+ goto fail;
}
filesize = lseek(fd, 0, SEEK_END);
if (filesize < 0) {
- int e = errno;
- close(fd);
- kprintf("lseek: %s\n", strerror(e));
- goto fail;
+ int e = errno;
+ close(fd);
+ kprintf("lseek: %s\n", strerror(e));
+ goto fail;
}
#if SIZEOF_OFF_T > SIZEOF_SIZE_T
if (filesize > (off_t)SIZE_MAX) {
- close(fd);
- kprintf("Too large file %s\n", binary_filename);
- goto fail;
+ close(fd);
+ kprintf("Too large file %s\n", binary_filename);
+ goto fail;
}
#endif
lseek(fd, 0, SEEK_SET);
/* async-signal unsafe */
file = (char *)mmap(NULL, (size_t)filesize, PROT_READ, MAP_SHARED, fd, 0);
if (file == MAP_FAILED) {
- int e = errno;
- close(fd);
- kprintf("mmap: %s\n", strerror(e));
- goto fail;
+ int e = errno;
+ close(fd);
+ kprintf("mmap: %s\n", strerror(e));
+ goto fail;
}
close(fd);
ehdr = (ElfW(Ehdr) *)file;
if (memcmp(ehdr->e_ident, "\177ELF", 4) != 0) {
- /*
- * Huh? Maybe filename was overridden by setproctitle() and
- * it match non-elf file.
- */
- goto fail;
+ /*
+ * Huh? Maybe filename was overridden by setproctitle() and
+ * it match non-elf file.
+ */
+ goto fail;
}
obj->mapped = file;
obj->mapped_size = (size_t)filesize;
@@ -2114,32 +2117,32 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
for (i = 0; i < ehdr->e_shnum; i++) {
char *section_name = shstr + shdr[i].sh_name;
- switch (shdr[i].sh_type) {
- case SHT_STRTAB:
- if (!strcmp(section_name, ".strtab")) {
- strtab_shdr = shdr + i;
- }
- else if (!strcmp(section_name, ".dynstr")) {
- dynstr_shdr = shdr + i;
- }
- break;
- case SHT_SYMTAB:
- /* if (!strcmp(section_name, ".symtab")) */
- symtab_shdr = shdr + i;
- break;
- case SHT_DYNSYM:
- /* if (!strcmp(section_name, ".dynsym")) */
- dynsym_shdr = shdr + i;
- break;
+ switch (shdr[i].sh_type) {
+ case SHT_STRTAB:
+ if (!strcmp(section_name, ".strtab")) {
+ strtab_shdr = shdr + i;
+ }
+ else if (!strcmp(section_name, ".dynstr")) {
+ dynstr_shdr = shdr + i;
+ }
+ break;
+ case SHT_SYMTAB:
+ /* if (!strcmp(section_name, ".symtab")) */
+ symtab_shdr = shdr + i;
+ break;
+ case SHT_DYNSYM:
+ /* if (!strcmp(section_name, ".dynsym")) */
+ dynsym_shdr = shdr + i;
+ break;
case SHT_NOTE:
if (!strcmp(section_name, ".note.gnu.build-id")) {
note_gnu_build_id = shdr + i;
}
break;
- case SHT_PROGBITS:
- if (!strcmp(section_name, ".gnu_debuglink")) {
- gnu_debuglink_shdr = shdr + i;
- }
+ case SHT_PROGBITS:
+ if (!strcmp(section_name, ".gnu_debuglink")) {
+ gnu_debuglink_shdr = shdr + i;
+ }
else {
const char *debug_section_names[] = {
".debug_abbrev",
@@ -2169,17 +2172,16 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
break;
}
}
- break;
- }
+ break;
+ }
}
- if (offset == -1) {
- /* main executable */
- offset = 0;
- if (dynsym_shdr && dynstr_shdr) {
- char *strtab = file + dynstr_shdr->sh_offset;
- ElfW(Sym) *symtab = (ElfW(Sym) *)(file + dynsym_shdr->sh_offset);
- int symtab_count = (int)(dynsym_shdr->sh_size / sizeof(ElfW(Sym)));
+ if (offset == 0) {
+ /* main executable */
+ if (dynsym_shdr && dynstr_shdr) {
+ char *strtab = file + dynstr_shdr->sh_offset;
+ ElfW(Sym) *symtab = (ElfW(Sym) *)(file + dynsym_shdr->sh_offset);
+ int symtab_count = (int)(dynsym_shdr->sh_size / sizeof(ElfW(Sym)));
void *handle = dlopen(NULL, RTLD_NOW|RTLD_LOCAL);
if (handle) {
for (j = 0; j < symtab_count; j++) {
@@ -2196,14 +2198,14 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
}
dlclose(handle);
}
- if (ehdr->e_type == ET_EXEC) {
- obj->base_addr = 0;
- }
- else {
- /* PIE (position-independent executable) */
- obj->base_addr = dladdr_fbase;
- }
- }
+ if (ehdr->e_type == ET_EXEC) {
+ obj->base_addr = 0;
+ }
+ else {
+ /* PIE (position-independent executable) */
+ obj->base_addr = dladdr_fbase;
+ }
+ }
}
if (obj->debug_info.ptr && obj->debug_abbrev.ptr) {
@@ -2249,21 +2251,21 @@ use_symtab:
}
if (!obj->debug_line.ptr) {
- /* This file doesn't have .debug_line section,
- let's check .gnu_debuglink section instead. */
- if (gnu_debuglink_shdr && check_debuglink) {
- follow_debuglink(file + gnu_debuglink_shdr->sh_offset,
- num_traces, traces,
- objp, lines, offset, errout);
- }
+ /* This file doesn't have .debug_line section,
+ let's check .gnu_debuglink section instead. */
+ if (gnu_debuglink_shdr && check_debuglink) {
+ follow_debuglink(file + gnu_debuglink_shdr->sh_offset,
+ num_traces, traces,
+ objp, lines, offset, errout);
+ }
if (note_gnu_build_id && check_debuglink) {
ElfW(Nhdr) *nhdr = (ElfW(Nhdr)*) (file + note_gnu_build_id->sh_offset);
const char *build_id = (char *)(nhdr + 1) + nhdr->n_namesz;
follow_debuglink_build_id(build_id, nhdr->n_descsz,
- num_traces, traces,
+ num_traces, traces,
objp, lines, offset, errout);
}
- goto finish;
+ goto finish;
}
if (parse_debug_line(num_traces, traces,
@@ -2426,7 +2428,17 @@ found_mach_header:
for (int j=0; j < DWARF_SECTION_COUNT; j++) {
struct dwarf_section *s = obj_dwarf_section_at(obj, j);
- if (strcmp(sect->sectname, debug_section_names[j]) != 0)
+ if (strcmp(sect->sectname, debug_section_names[j]) != 0
+#ifdef __APPLE__
+ /* macOS clang 16 generates DWARF5, which have Mach-O
+ * section names that are limited to 16 characters,
+ * which causes sections with long names to be truncated
+ * and not match above.
+ * See: https://wiki.dwarfstd.org/Best_Practices.md#Mach-2d-O
+ */
+ && strncmp(sect->sectname, debug_section_names[j], 16) != 0
+#endif
+ )
continue;
s->ptr = file + sect->offset;
@@ -2533,8 +2545,8 @@ main_exe_path(FILE *errout)
size_t len = PATH_MAX;
int err = sysctl(mib, 4, binary_filename, &len, NULL, 0);
if (err) {
- kprintf("Can't get the path of ruby");
- return -1;
+ kprintf("Can't get the path of ruby");
+ return -1;
}
len--; /* sysctl sets strlen+1 */
return len;
@@ -2616,79 +2628,79 @@ rb_dump_backtrace_with_lines(int num_traces, void **traces, FILE *errout)
char *main_path = NULL; /* used on printing backtrace */
ssize_t len;
if ((len = main_exe_path(errout)) > 0) {
- main_path = (char *)alloca(len + 1);
- if (main_path) {
- uintptr_t addr;
- memcpy(main_path, binary_filename, len+1);
- append_obj(&obj);
- obj->path = main_path;
- addr = fill_lines(num_traces, traces, 1, &obj, lines, -1, errout);
- if (addr != (uintptr_t)-1) {
- dladdr_fbases[0] = (void *)addr;
- }
- }
+ main_path = (char *)alloca(len + 1);
+ if (main_path) {
+ uintptr_t addr;
+ memcpy(main_path, binary_filename, len+1);
+ append_obj(&obj);
+ obj->path = main_path;
+ addr = fill_lines(num_traces, traces, 1, &obj, lines, 0, errout);
+ if (addr != (uintptr_t)-1) {
+ dladdr_fbases[0] = (void *)addr;
+ }
+ }
}
#endif
/* fill source lines by reading dwarf */
for (i = 0; i < num_traces; i++) {
- Dl_info info;
- if (lines[i].line) continue;
- if (dladdr(traces[i], &info)) {
- const char *path;
- void **p;
-
- /* skip symbols which is in already checked objects */
- /* if the binary is strip-ed, this may effect */
- for (p=dladdr_fbases; *p; p++) {
- if (*p == info.dli_fbase) {
- if (info.dli_fname) lines[i].path = info.dli_fname;
- if (info.dli_sname) lines[i].sname = info.dli_sname;
- goto next_line;
- }
- }
- *p = info.dli_fbase;
-
- append_obj(&obj);
- obj->base_addr = (uintptr_t)info.dli_fbase;
- path = info.dli_fname;
- obj->path = path;
- if (path) lines[i].path = path;
+ Dl_info info;
+ if (lines[i].line) continue;
+ if (dladdr(traces[i], &info)) {
+ const char *path;
+ void **p;
+
+ /* skip symbols which is in already checked objects */
+ /* if the binary is strip-ed, this may effect */
+ for (p=dladdr_fbases; *p; p++) {
+ if (*p == info.dli_fbase) {
+ if (info.dli_fname) lines[i].path = info.dli_fname;
+ if (info.dli_sname) lines[i].sname = info.dli_sname;
+ goto next_line;
+ }
+ }
+ *p = info.dli_fbase;
+
+ append_obj(&obj);
+ obj->base_addr = (uintptr_t)info.dli_fbase;
+ path = info.dli_fname;
+ obj->path = path;
+ if (path) lines[i].path = path;
if (info.dli_sname) {
lines[i].sname = info.dli_sname;
lines[i].saddr = (uintptr_t)info.dli_saddr;
}
- strlcpy(binary_filename, path, PATH_MAX);
- if (fill_lines(num_traces, traces, 1, &obj, lines, i, errout) == (uintptr_t)-1)
- break;
- }
+ strlcpy(binary_filename, path, PATH_MAX);
+ if (fill_lines(num_traces, traces, 1, &obj, lines, i, errout) == (uintptr_t)-1)
+ break;
+ }
next_line:
- continue;
+ continue;
}
/* output */
for (i = 0; i < num_traces; i++) {
print_line(&lines[i], traces[i], errout);
- /* FreeBSD's backtrace may show _start and so on */
- if (lines[i].sname && strcmp("main", lines[i].sname) == 0)
- break;
+ /* FreeBSD's backtrace may show _start and so on */
+ if (lines[i].sname && strcmp("main", lines[i].sname) == 0)
+ break;
}
/* free */
while (obj) {
- obj_info_t *o = obj;
+ obj_info_t *o = obj;
for (i=0; i < DWARF_SECTION_COUNT; i++) {
struct dwarf_section *s = obj_dwarf_section_at(obj, i);
if (s->flags & SHF_COMPRESSED) {
free(s->ptr);
}
}
- if (obj->mapped_size) {
- munmap(obj->mapped, obj->mapped_size);
- }
- obj = o->next;
- free(o);
+ if (obj->mapped_size) {
+ munmap(obj->mapped, obj->mapped_size);
+ }
+ obj = o->next;
+ free(o);
}
for (i = 0; i < num_traces; i++) {
line_info_t *line = lines[i].next;
diff --git a/array.c b/array.c
index dab933776f..b471823876 100644
--- a/array.c
+++ b/array.c
@@ -27,7 +27,9 @@
#include "probes.h"
#include "ruby/encoding.h"
#include "ruby/st.h"
+#include "ruby/thread.h"
#include "ruby/util.h"
+#include "ruby/ractor.h"
#include "vm_core.h"
#include "builtin.h"
@@ -38,15 +40,16 @@
#include "ruby_assert.h"
VALUE rb_cArray;
+VALUE rb_cArray_empty_frozen;
/* Flags of RArray
*
+ * 0: RARRAY_SHARED_FLAG (equal to ELTS_SHARED)
+ * The array is shared. The buffer this array points to is owned by
+ * another array (the shared root).
* 1: RARRAY_EMBED_FLAG
* The array is embedded (its contents follow the header, rather than
* being on a separately allocated buffer).
- * 2: RARRAY_SHARED_FLAG (equal to ELTS_SHARED)
- * The array is shared. The buffer this array points to is owned by
- * another array (the shared root).
* 3-9: RARRAY_EMBED_LEN
* The length of the array when RARRAY_EMBED_FLAG is set.
* 12: RARRAY_SHARED_ROOT_FLAG
@@ -105,10 +108,12 @@ should_be_T_ARRAY(VALUE ary)
} while (0)
#define FL_UNSET_SHARED(ary) FL_UNSET((ary), RARRAY_SHARED_FLAG)
+#define ARY_SET_PTR_FORCE(ary, p) \
+ (RARRAY(ary)->as.heap.ptr = (p))
#define ARY_SET_PTR(ary, p) do { \
RUBY_ASSERT(!ARY_EMBED_P(ary)); \
RUBY_ASSERT(!OBJ_FROZEN(ary)); \
- RARRAY(ary)->as.heap.ptr = (p); \
+ ARY_SET_PTR_FORCE(ary, p); \
} while (0)
#define ARY_SET_EMBED_LEN(ary, n) do { \
long tmp_n = (n); \
@@ -146,11 +151,13 @@ should_be_T_ARRAY(VALUE ary)
#define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? ary_embed_capa(ary) : \
ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : ARY_HEAP_CAPA(ary))
+#define ARY_SET_CAPA_FORCE(ary, n) \
+ RARRAY(ary)->as.heap.aux.capa = (n);
#define ARY_SET_CAPA(ary, n) do { \
RUBY_ASSERT(!ARY_EMBED_P(ary)); \
RUBY_ASSERT(!ARY_SHARED_P(ary)); \
RUBY_ASSERT(!OBJ_FROZEN(ary)); \
- RARRAY(ary)->as.heap.aux.capa = (n); \
+ ARY_SET_CAPA_FORCE(ary, n); \
} while (0)
#define ARY_SHARED_ROOT_OCCUPIED(ary) (!OBJ_FROZEN(ary) && ARY_SHARED_ROOT_REFCNT(ary) == 1)
@@ -187,7 +194,9 @@ ary_embed_capa(VALUE ary)
static size_t
ary_embed_size(long capa)
{
- return offsetof(struct RArray, as.ary) + (sizeof(VALUE) * capa);
+ size_t size = offsetof(struct RArray, as.ary) + (sizeof(VALUE) * capa);
+ if (size < sizeof(struct RArray)) size = sizeof(struct RArray);
+ return size;
}
static bool
@@ -262,12 +271,6 @@ ary_verify_(VALUE ary, const char *file, int line)
return ary;
}
-
-void
-rb_ary_verify(VALUE ary)
-{
- ary_verify(ary);
-}
#else
#define ary_verify(ary) ((void)0)
#endif
@@ -370,6 +373,7 @@ ary_heap_free(VALUE ary)
static size_t
ary_heap_realloc(VALUE ary, size_t new_capa)
{
+ RUBY_ASSERT(!OBJ_FROZEN(ary));
SIZED_REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, new_capa, ARY_HEAP_CAPA(ary));
ary_verify(ary);
@@ -441,7 +445,10 @@ ary_shrink_capa(VALUE ary)
long old_capa = ARY_HEAP_CAPA(ary);
RUBY_ASSERT(!ARY_SHARED_P(ary));
RUBY_ASSERT(old_capa >= capacity);
- if (old_capa > capacity) ary_heap_realloc(ary, capacity);
+ if (old_capa > capacity) {
+ size_t new_capa = ary_heap_realloc(ary, capacity);
+ ARY_SET_CAPA(ary, new_capa);
+ }
ary_verify(ary);
}
@@ -522,6 +529,8 @@ rb_ary_set_shared(VALUE ary, VALUE shared_root)
static inline void
rb_ary_modify_check(VALUE ary)
{
+ RUBY_ASSERT(ruby_thread_has_gvl_p());
+
rb_check_frozen(ary);
ary_verify(ary);
}
@@ -558,8 +567,8 @@ rb_ary_cancel_sharing(VALUE ary)
VALUE *ptr = ary_heap_alloc_buffer(len);
MEMCPY(ptr, ARY_HEAP_PTR(ary), VALUE, len);
rb_ary_unshare(ary);
- ARY_SET_CAPA(ary, len);
- ARY_SET_PTR(ary, ptr);
+ ARY_SET_CAPA_FORCE(ary, len);
+ ARY_SET_PTR_FORCE(ary, ptr);
}
rb_gc_writebarrier_remember(ary);
@@ -624,21 +633,32 @@ ary_ensure_room_for_push(VALUE ary, long add_len)
/*
* call-seq:
- * array.freeze -> self
+ * freeze -> self
*
- * Freezes +self+; returns +self+:
+ * Freezes +self+ (if not already frozen); returns +self+:
*
* a = []
* a.frozen? # => false
* a.freeze
* a.frozen? # => true
*
- * An attempt to modify a frozen +Array+ raises FrozenError.
+ * No further changes may be made to +self+;
+ * raises FrozenError if a change is attempted.
+ *
+ * Related: Kernel#frozen?.
*/
VALUE
rb_ary_freeze(VALUE ary)
{
+ RUBY_ASSERT(RB_TYPE_P(ary, T_ARRAY));
+
+ if (OBJ_FROZEN(ary)) return ary;
+
+ if (!ARY_EMBED_P(ary) && !ARY_SHARED_P(ary) && !ARY_SHARED_ROOT_P(ary)) {
+ ary_shrink_capa(ary);
+ }
+
return rb_obj_freeze(ary);
}
@@ -682,6 +702,11 @@ ary_alloc_heap(VALUE klass)
NEWOBJ_OF(ary, struct RArray, klass,
T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
sizeof(struct RArray), 0);
+
+ ary->as.heap.len = 0;
+ ary->as.heap.aux.capa = 0;
+ ary->as.heap.ptr = NULL;
+
return (VALUE)ary;
}
@@ -695,6 +720,8 @@ empty_ary_alloc(VALUE klass)
static VALUE
ary_new(VALUE klass, long capa)
{
+ RUBY_ASSERT(ruby_thread_has_gvl_p());
+
VALUE ary;
if (capa < 0) {
@@ -793,6 +820,11 @@ ec_ary_alloc_heap(rb_execution_context_t *ec, VALUE klass)
NEWOBJ_OF(ary, struct RArray, klass,
T_ARRAY | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0),
sizeof(struct RArray), ec);
+
+ ary->as.heap.len = 0;
+ ary->as.heap.aux.capa = 0;
+ ary->as.heap.ptr = NULL;
+
return (VALUE)ary;
}
@@ -880,17 +912,29 @@ rb_ary_free(VALUE ary)
}
}
+static VALUE fake_ary_flags;
+
+static VALUE
+init_fake_ary_flags(void)
+{
+ struct RArray fake_ary = {0};
+ fake_ary.basic.flags = T_ARRAY;
+ VALUE ary = (VALUE)&fake_ary;
+ rb_ary_freeze(ary);
+ return fake_ary.basic.flags;
+}
+
VALUE
-rb_setup_fake_ary(struct RArray *fake_ary, const VALUE *list, long len, bool freeze)
-{
- fake_ary->basic.flags = T_ARRAY;
- VALUE ary = (VALUE)fake_ary;
- RBASIC_CLEAR_CLASS(ary);
- ARY_SET_PTR(ary, list);
- ARY_SET_HEAP_LEN(ary, len);
- ARY_SET_CAPA(ary, len);
- if (freeze) OBJ_FREEZE(ary);
- return ary;
+rb_setup_fake_ary(struct RArray *fake_ary, const VALUE *list, long len)
+{
+ fake_ary->basic.flags = fake_ary_flags;
+ RBASIC_CLEAR_CLASS((VALUE)fake_ary);
+
+ // bypass frozen checks
+ fake_ary->as.heap.ptr = list;
+ fake_ary->as.heap.len = len;
+ fake_ary->as.heap.aux.capa = len;
+ return (VALUE)fake_ary;
}
size_t
@@ -916,9 +960,6 @@ ary_make_shared(VALUE ary)
return ary;
}
else if (OBJ_FROZEN(ary)) {
- if (!ARY_EMBED_P(ary)) {
- ary_shrink_capa(ary);
- }
return ary;
}
else {
@@ -1007,14 +1048,18 @@ rb_to_array(VALUE ary)
* call-seq:
* Array.try_convert(object) -> object, new_array, or nil
*
- * If +object+ is an +Array+ object, returns +object+.
+ * Attempts to return an array, based on the given +object+.
+ *
+ * If +object+ is an array, returns +object+.
*
- * Otherwise if +object+ responds to <tt>:to_ary</tt>,
- * calls <tt>object.to_ary</tt> and returns the result.
+ * Otherwise if +object+ responds to <tt>:to_ary</tt>.
+ * calls <tt>object.to_ary</tt>:
+ * if the return value is an array or +nil+, returns that value;
+ * if not, raises TypeError.
*
- * Returns +nil+ if +object+ does not respond to <tt>:to_ary</tt>
+ * Otherwise returns +nil+.
*
- * Raises an exception unless <tt>object.to_ary</tt> returns an +Array+ object.
+ * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
*/
static VALUE
@@ -1051,48 +1096,51 @@ rb_ary_s_new(int argc, VALUE *argv, VALUE klass)
* call-seq:
* Array.new -> new_empty_array
* Array.new(array) -> new_array
- * Array.new(size) -> new_array
- * Array.new(size, default_value) -> new_array
- * Array.new(size) {|index| ... } -> new_array
+ * Array.new(size, default_value = nil) -> new_array
+ * Array.new(size = 0) {|index| ... } -> new_array
*
- * Returns a new +Array+.
+ * Returns a new array.
*
- * With no block and no arguments, returns a new empty +Array+ object.
+ * With no block and no argument given, returns a new empty array:
*
- * With no block and a single +Array+ argument +array+,
- * returns a new +Array+ formed from +array+:
+ * Array.new # => []
*
- * a = Array.new([:foo, 'bar', 2])
- * a.class # => Array
- * a # => [:foo, "bar", 2]
+ * With no block and array argument given, returns a new array with the same elements:
+ *
+ * Array.new([:foo, 'bar', 2]) # => [:foo, "bar", 2]
*
- * With no block and a single Integer argument +size+,
- * returns a new +Array+ of the given size
- * whose elements are all +nil+:
+ * With no block and integer argument given, returns a new array containing
+ * that many instances of the given +default_value+:
*
- * a = Array.new(3)
- * a # => [nil, nil, nil]
+ * Array.new(0) # => []
+ * Array.new(3) # => [nil, nil, nil]
+ * Array.new(2, 3) # => [3, 3]
*
- * With no block and arguments +size+ and +default_value+,
- * returns an +Array+ of the given size;
- * each element is that same +default_value+:
+ * With a block given, returns an array of the given +size+;
+ * calls the block with each +index+ in the range <tt>(0...size)</tt>;
+ * the element at that +index+ in the returned array is the blocks return value:
*
- * a = Array.new(3, 'x')
- * a # => ['x', 'x', 'x']
+ * Array.new(3) {|index| "Element #{index}" } # => ["Element 0", "Element 1", "Element 2"]
*
- * 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 common pitfall for new Rubyists is providing an expression as +default_value+:
*
- * a = Array.new(3) {|index| "Element #{index}" }
- * a # => ["Element 0", "Element 1", "Element 2"]
+ * array = Array.new(2, {})
+ * array # => [{}, {}]
+ * array[0][:a] = 1
+ * array # => [{a: 1}, {a: 1}], as array[0] and array[1] are same object
*
- * Raises ArgumentError if +size+ is negative.
+ * If you want the elements of the array to be distinct, you should pass a block:
*
- * With a block and no argument,
- * or a single argument +0+,
- * ignores the block and returns a new empty +Array+.
+ * array = Array.new(2) { {} }
+ * array # => [{}, {}]
+ * array[0][:a] = 1
+ * array # => [{a: 1}, {}], as array[0] and array[1] are different objects
+ *
+ * Raises TypeError if the first argument is not either an array
+ * or an {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]).
+ * Raises ArgumentError if the first argument is a negative integer.
+ *
+ * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
*/
static VALUE
@@ -1150,11 +1198,13 @@ rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
}
/*
- * Returns a new array populated with the given objects.
+ * Returns a new array, populated with the given objects:
+ *
+ * Array[1, 'a', /^A/] # => [1, "a", /^A/]
+ * Array[] # => []
+ * Array.[](1, 'a', /^A/) # => [1, "a", /^A/]
*
- * Array.[]( 1, 'a', /^A/) # => [1, "a", /^A/]
- * Array[ 1, 'a', /^A/ ] # => [1, "a", /^A/]
- * [ 1, 'a', /^A/ ] # => [1, "a", /^A/]
+ * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array].
*/
static VALUE
@@ -1333,19 +1383,17 @@ ary_take_first_or_last(int argc, const VALUE *argv, VALUE ary, enum ary_take_pos
/*
* call-seq:
- * array << object -> self
+ * self << object -> self
*
- * Appends +object+ to +self+; returns +self+:
+ * Appends +object+ as the last element in +self+; returns +self+:
*
- * a = [:foo, 'bar', 2]
- * a << :baz # => [:foo, "bar", 2, :baz]
+ * [:foo, 'bar', 2] << :baz # => [:foo, "bar", 2, :baz]
*
- * Appends +object+ as one element, even if it is another +Array+:
+ * Appends +object+ as a single element, even if it is another array:
*
- * a = [:foo, 'bar', 2]
- * a1 = a << [3, 4]
- * a1 # => [:foo, "bar", 2, [3, 4]]
+ * [:foo, 'bar', 2] << [3, 4] # => [:foo, "bar", 2, [3, 4]]
*
+ * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
*/
VALUE
@@ -1373,22 +1421,20 @@ rb_ary_cat(VALUE ary, const VALUE *argv, long len)
/*
* call-seq:
- * array.push(*objects) -> self
+ * push(*objects) -> self
+ * append(*objects) -> self
*
- * Appends trailing elements.
+ * Appends each argument in +objects+ to +self+; returns +self+:
*
- * Appends each argument in +objects+ to +self+; returns +self+:
+ * a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
+ * a.push(:baz, :bat) # => [:foo, "bar", 2, :baz, :bat]
*
- * 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+:
+ * Appends each argument as a single element, even if it is another array:
*
- * a = [:foo, 'bar', 2]
- * a1 = a.push([:baz, :bat], [:bam, :bad])
- * a1 # => [:foo, "bar", 2, [:baz, :bat], [:bam, :bad]]
+ * a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
+ a.push([:baz, :bat], [:bam, :bad]) # => [:foo, "bar", 2, [:baz, :bat], [:bam, :bad]]
*
- * Related: #pop, #shift, #unshift.
+ * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
*/
static VALUE
@@ -1410,41 +1456,42 @@ rb_ary_pop(VALUE ary)
{
ary_resize_capa(ary, n * 2);
}
- --n;
- ARY_SET_LEN(ary, n);
+
+ VALUE obj = RARRAY_AREF(ary, n - 1);
+
+ ARY_SET_LEN(ary, n - 1);
ary_verify(ary);
- return RARRAY_AREF(ary, n);
+ return obj;
}
/*
* call-seq:
- * array.pop -> object or nil
- * array.pop(n) -> new_array
+ * pop -> object or nil
+ * pop(count) -> new_array
*
- * Removes and returns trailing elements.
+ * Removes and returns trailing elements of +self+.
*
- * When no argument is given and +self+ is not empty,
- * removes and returns the last element:
+ * With no argument given, removes and returns the last element, if available;
+ * otherwise returns +nil+:
*
* a = [:foo, 'bar', 2]
- * a.pop # => 2
- * a # => [:foo, "bar"]
- *
- * Returns +nil+ if the array is empty.
+ * a.pop # => 2
+ * a # => [:foo, "bar"]
+ * [].pop # => nil
*
- * When a non-negative Integer argument +n+ is given and is in range,
+ * With non-negative integer argument +count+ given,
+ * returns a new array containing the trailing +count+ elements of +self+, as available:
*
- * removes and returns the last +n+ elements in a new +Array+:
* a = [:foo, 'bar', 2]
* a.pop(2) # => ["bar", 2]
- *
- * If +n+ is positive and out of range,
- * removes and returns all elements:
+ * a # => [:foo]
*
* a = [:foo, 'bar', 2]
* a.pop(50) # => [:foo, "bar", 2]
+ * a # => []
*
- * Related: #push, #shift, #unshift.
+ * Related: Array#push;
+ * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
*/
static VALUE
@@ -1483,35 +1530,40 @@ rb_ary_shift(VALUE ary)
/*
* call-seq:
- * array.shift -> object or nil
- * array.shift(n) -> new_array
+ * shift -> object or nil
+ * shift(count) -> new_array or nil
*
- * Removes and returns leading elements.
+ * Removes and returns leading elements from +self+.
*
- * When no argument is given, removes and returns the first element:
+ * With no argument, removes and returns one element, if available,
+ * or +nil+ otherwise:
*
- * a = [:foo, 'bar', 2]
- * a.shift # => :foo
- * a # => ['bar', 2]
- *
- * Returns +nil+ if +self+ is empty.
- *
- * When positive Integer argument +n+ is given, removes the first +n+ elements;
- * returns those elements in a new +Array+:
+ * a = [0, 1, 2, 3]
+ * a.shift # => 0
+ * a # => [1, 2, 3]
+ * [].shift # => nil
*
- * a = [:foo, 'bar', 2]
- * a.shift(2) # => [:foo, 'bar']
- * a # => [2]
+ * With non-negative numeric argument +count+ given,
+ * removes and returns the first +count+ elements:
*
- * If +n+ is as large as or larger than <tt>self.length</tt>,
- * removes all elements; returns those elements in a new +Array+:
+ * a = [0, 1, 2, 3]
+ * a.shift(2) # => [0, 1]
+ * a # => [2, 3]
+ * a.shift(1.1) # => [2]
+ * a # => [3]
+ * a.shift(0) # => []
+ * a # => [3]
+ *
+ * If +count+ is large,
+ * removes and returns all elements:
*
- * a = [:foo, 'bar', 2]
- * a.shift(3) # => [:foo, 'bar', 2]
+ * a = [0, 1, 2, 3]
+ * a.shift(50) # => [0, 1, 2, 3]
+ * a # => []
*
- * If +n+ is zero, returns a new empty +Array+; +self+ is unmodified.
+ * If +self+ is empty, returns a new empty array.
*
- * Related: #push, #pop, #unshift.
+ * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
*/
static VALUE
@@ -1652,14 +1704,16 @@ ary_ensure_room_for_unshift(VALUE ary, int argc)
/*
* call-seq:
- * array.unshift(*objects) -> self
+ * unshift(*objects) -> self
+ * prepend(*objects) -> self
*
* Prepends the given +objects+ to +self+:
*
* a = [:foo, 'bar', 2]
* a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2]
*
- * Related: #push, #pop, #shift.
+ * Related: Array#shift;
+ * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
*/
VALUE
@@ -1735,35 +1789,38 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
/*
* call-seq:
- * array[index] -> object or nil
- * array[start, length] -> object or nil
- * array[range] -> object or nil
- * array[aseq] -> object or nil
- * array.slice(index) -> object or nil
- * array.slice(start, length) -> object or nil
- * array.slice(range) -> object or nil
- * array.slice(aseq) -> object or nil
+ * self[offset] -> object or nil
+ * self[offset, size] -> object or nil
+ * self[range] -> object or nil
+ * self[aseq] -> object or nil
*
* Returns elements from +self+; does not modify +self+.
*
* In brief:
*
* a = [:foo, 'bar', 2]
- * a[0] # => :foo
- * a[-1] # => 2
+ *
+ * # Single argument offset: returns one element.
+ * a[0] # => :foo # Zero-based index.
+ * a[-1] # => 2 # Negative index counts backwards from end.
+ *
+ * # Arguments offset and size: returns an array.
* a[1, 2] # => ["bar", 2]
+ * a[-2, 2] # => ["bar", 2] # Negative offset counts backwards from end.
+ *
+ * # Single argument range: returns an array.
* a[0..1] # => [:foo, "bar"]
- * a[0..-2] # => [:foo, "bar"]
- * a[-2..2] # => ["bar", 2]
+ * a[0..-2] # => [:foo, "bar"] # Negative range-begin counts backwards from end.
+ * a[-2..2] # => ["bar", 2] # Negative range-end counts backwards from end.
*
- * When a single Integer argument +index+ is given, returns the element at offset +index+:
+ * When a single integer argument +offset+ is given, returns the element at offset +offset+:
*
* a = [:foo, 'bar', 2]
* a[0] # => :foo
* a[2] # => 2
* a # => [:foo, "bar", 2]
*
- * If +index+ is negative, counts relative to the end of +self+:
+ * If +offset+ is negative, counts backwards from the end of +self+:
*
* a = [:foo, 'bar', 2]
* a[-1] # => 2
@@ -1771,35 +1828,35 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
*
* If +index+ is out of range, returns +nil+.
*
- * When two Integer arguments +start+ and +length+ are given,
- * returns a new +Array+ of size +length+ containing successive elements beginning at offset +start+:
+ * When two Integer arguments +offset+ and +size+ are given,
+ * returns a new array of size +size+ containing successive elements beginning at offset +offset+:
*
* a = [:foo, 'bar', 2]
* a[0, 2] # => [:foo, "bar"]
* a[1, 2] # => ["bar", 2]
*
- * If <tt>start + length</tt> is greater than <tt>self.length</tt>,
- * returns all elements from offset +start+ to the end:
+ * If <tt>offset + size</tt> is greater than <tt>self.size</tt>,
+ * returns all elements from offset +offset+ to the end:
*
* a = [:foo, 'bar', 2]
* a[0, 4] # => [:foo, "bar", 2]
* a[1, 3] # => ["bar", 2]
* a[2, 2] # => [2]
*
- * If <tt>start == self.size</tt> and <tt>length >= 0</tt>,
- * returns a new empty +Array+.
+ * If <tt>offset == self.size</tt> and <tt>size >= 0</tt>,
+ * returns a new empty array.
*
- * If +length+ is negative, returns +nil+.
+ * If +size+ is negative, returns +nil+.
*
* When a single Range argument +range+ is given,
- * treats <tt>range.min</tt> as +start+ above
- * and <tt>range.size</tt> as +length+ above:
+ * treats <tt>range.min</tt> as +offset+ above
+ * and <tt>range.size</tt> as +size+ above:
*
* a = [:foo, 'bar', 2]
* a[0..1] # => [:foo, "bar"]
* a[1..2] # => ["bar", 2]
*
- * Special case: If <tt>range.start == a.size</tt>, returns a new empty +Array+.
+ * Special case: If <tt>range.start == a.size</tt>, returns a new empty array.
*
* If <tt>range.end</tt> is negative, calculates the end index from the end:
*
@@ -1823,7 +1880,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
* a[4..-1] # => nil
*
* When a single Enumerator::ArithmeticSequence argument +aseq+ is given,
- * returns an +Array+ of elements corresponding to the indexes produced by
+ * returns an array of elements corresponding to the indexes produced by
* the sequence.
*
* a = ['--', 'data1', '--', 'data2', '--', 'data3']
@@ -1845,6 +1902,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e);
* # Raises TypeError (no implicit conversion of Symbol into Integer):
* a[:foo]
*
+ * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
*/
VALUE
@@ -1892,13 +1950,26 @@ rb_ary_aref1(VALUE ary, VALUE arg)
/*
* call-seq:
- * array.at(index) -> object
+ * at(index) -> object or nil
+ *
+ * Returns the element of +self+ specified by the given +index+
+ * or +nil+ if there is no such element;
+ * +index+ must be an
+ * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
+ *
+ * For non-negative +index+, returns the element of +self+ at offset +index+:
*
- * Returns the element at Integer offset +index+; does not modify +self+.
* a = [:foo, 'bar', 2]
- * a.at(0) # => :foo
- * a.at(2) # => 2
+ * a.at(0) # => :foo
+ * a.at(2) # => 2
+ * a.at(2.0) # => 2
+ *
+ * For negative +index+, counts backwards from the end of +self+:
+ *
+ * a.at(-2) # => "bar"
*
+ * Related: Array#[];
+ * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
*/
VALUE
@@ -1947,17 +2018,19 @@ rb_ary_last(int argc, const VALUE *argv, VALUE ary) // used by parse.y
/*
* call-seq:
- * array.fetch(index) -> element
- * array.fetch(index, default_value) -> element
- * array.fetch(index) {|index| ... } -> element
+ * fetch(index) -> element
+ * fetch(index, default_value) -> element or default_value
+ * fetch(index) {|index| ... } -> element or block_return_value
*
- * Returns the element at offset +index+.
+ * Returns the element of +self+ at offset +index+ if +index+ is in range; +index+ must be an
+ * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
*
- * With the single Integer argument +index+,
+ * With the single argument +index+ and no block,
* returns the element at offset +index+:
*
* a = [:foo, 'bar', 2]
- * a.fetch(1) # => "bar"
+ * a.fetch(1) # => "bar"
+ * a.fetch(1.1) # => "bar"
*
* If +index+ is negative, counts from the end of the array:
*
@@ -1965,12 +2038,12 @@ rb_ary_last(int argc, const VALUE *argv, VALUE ary) // used by parse.y
* a.fetch(-1) # => 2
* a.fetch(-2) # => "bar"
*
- * With arguments +index+ and +default_value+,
- * returns the element at offset +index+ if index is in range,
- * otherwise returns +default_value+:
+ * With arguments +index+ and +default_value+ (which may be any object) and no block,
+ * returns +default_value+ if +index+ is out-of-range:
*
* a = [:foo, 'bar', 2]
- * a.fetch(1, nil) # => "bar"
+ * a.fetch(1, nil) # => "bar"
+ * a.fetch(3, :foo) # => :foo
*
* With argument +index+ and a block,
* returns the element at offset +index+ if index is in range
@@ -1980,6 +2053,7 @@ rb_ary_last(int argc, const VALUE *argv, VALUE ary) // used by parse.y
* a.fetch(1) {|index| raise 'Cannot happen' } # => "bar"
* a.fetch(50) {|index| "Value for #{index}" } # => "Value for 50"
*
+ * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
*/
static VALUE
@@ -2011,14 +2085,106 @@ rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
}
/*
+ * 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 array;
+ * returns the first element for which the block returns a truthy value:
+ *
+ * [1, 3, 5].find {|element| element > 2} # => 3
+ *
+ * If no such element is found, calls +if_none_proc+ and returns its return value.
+ *
+ * [1, 3, 5].find(proc {-1}) {|element| element > 12} # => -1
+ *
+ * With no block given, returns an Enumerator.
+ *
+ */
+
+static VALUE
+rb_ary_find(int argc, VALUE *argv, VALUE ary)
+{
+ VALUE if_none;
+ long idx;
+
+ RETURN_ENUMERATOR(ary, argc, argv);
+ if_none = rb_check_arity(argc, 0, 1) ? argv[0] : Qnil;
+
+ for (idx = 0; idx < RARRAY_LEN(ary); idx++) {
+ VALUE elem = RARRAY_AREF(ary, idx);
+ if (RTEST(rb_yield(elem))) {
+ return elem;
+ }
+ }
+
+ if (!NIL_P(if_none)) {
+ return rb_funcallv(if_none, idCall, 0, 0);
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * rfind(if_none_proc = nil) {|element| ... } -> object or nil
+ * rfind(if_none_proc = nil) -> enumerator
+ *
+ * Returns the last element for which the block returns a truthy value.
+ *
+ * With a block given, calls the block with successive elements of the array in
+ * reverse order; returns the first element for which the block returns a truthy
+ * value:
+ *
+ * [1, 2, 3, 4, 5, 6].rfind {|element| element < 5} # => 4
+ *
+ * If no such element is found, calls +if_none_proc+ and returns its return value.
+ *
+ * [1, 2, 3, 4].rfind(proc {0}) {|element| element < -2} # => 0
+ *
+ * With no block given, returns an Enumerator.
+ *
+ */
+
+static VALUE
+rb_ary_rfind(int argc, VALUE *argv, VALUE ary)
+{
+ VALUE if_none;
+ long len, idx;
+
+ RETURN_ENUMERATOR(ary, argc, argv);
+ if_none = rb_check_arity(argc, 0, 1) ? argv[0] : Qnil;
+
+ idx = RARRAY_LEN(ary);
+ while (idx--) {
+ VALUE elem = RARRAY_AREF(ary, idx);
+ if (RTEST(rb_yield(elem))) {
+ return elem;
+ }
+
+ len = RARRAY_LEN(ary);
+ idx = (idx >= len) ? len : idx;
+ }
+
+ if (!NIL_P(if_none)) {
+ return rb_funcallv(if_none, idCall, 0, 0);
+ }
+ return Qnil;
+}
+
+/*
* call-seq:
- * array.index(object) -> integer or nil
- * array.index {|element| ... } -> integer or nil
- * array.index -> new_enumerator
+ * find_index(object) -> integer or nil
+ * find_index {|element| ... } -> integer or nil
+ * find_index -> new_enumerator
+ * index(object) -> integer or nil
+ * index {|element| ... } -> integer or nil
+ * index -> new_enumerator
*
- * Returns the index of a specified element.
+ * Returns the zero-based integer index of a specified element, or +nil+.
*
- * When argument +object+ is given but no block,
+ * With only argument +object+ given,
* returns the index of the first element +element+
* for which <tt>object == element</tt>:
*
@@ -2027,7 +2193,7 @@ rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
*
* Returns +nil+ if no such element found.
*
- * When both argument +object+ and a block are given,
+ * With only a block given,
* calls the block with each successive element;
* returns the index of the first element for which the block returns a truthy value:
*
@@ -2036,14 +2202,9 @@ rb_ary_fetch(int argc, VALUE *argv, VALUE ary)
*
* Returns +nil+ if the block never returns a truthy value.
*
- * When neither an argument nor a block is given, returns a new Enumerator:
- *
- * a = [:foo, 'bar', 2]
- * e = a.index
- * e # => #<Enumerator: [:foo, "bar", 2]:index>
- * e.each {|element| element == 'bar' } # => 1
+ * With neither an argument nor a block given, returns a new Enumerator.
*
- * Related: #rindex.
+ * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
*/
static VALUE
@@ -2076,20 +2237,20 @@ rb_ary_index(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * array.rindex(object) -> integer or nil
- * array.rindex {|element| ... } -> integer or nil
- * array.rindex -> new_enumerator
+ * rindex(object) -> integer or nil
+ * rindex {|element| ... } -> integer or nil
+ * rindex -> new_enumerator
*
* Returns the index of the last element for which <tt>object == element</tt>.
*
- * When argument +object+ is given but no block, returns the index of the last such element found:
+ * With argument +object+ given, returns the index of the last such element found:
*
* a = [:foo, 'bar', 2, 'bar']
* a.rindex('bar') # => 3
*
* Returns +nil+ if no such object found.
*
- * When a block is given but no argument, calls the block with each successive element;
+ * With a block given, calls the block with each successive element;
* returns the index of the last element for which the block returns a truthy value:
*
* a = [:foo, 'bar', 2, 'bar']
@@ -2097,14 +2258,9 @@ rb_ary_index(int argc, VALUE *argv, VALUE ary)
*
* Returns +nil+ if the block never returns a truthy value.
*
- * When neither an argument nor a block is given, returns a new Enumerator:
- *
- * a = [:foo, 'bar', 2, 'bar']
- * e = a.rindex
- * e # => #<Enumerator: [:foo, "bar", 2, "bar"]:rindex>
- * e.each {|element| element == 'bar' } # => 3
+ * When neither an argument nor a block is given, returns a new Enumerator.
*
- * Related: #index.
+ * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
*/
static VALUE
@@ -2251,7 +2407,7 @@ rb_ary_resize(VALUE ary, long len)
rb_raise(rb_eIndexError, "index %ld too big", len);
}
if (len > olen) {
- if (len >= ARY_CAPA(ary)) {
+ if (len > ARY_CAPA(ary)) {
ary_double_capa(ary, len);
}
ary_mem_clear(ary, olen, len - olen);
@@ -2301,15 +2457,16 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
/*
* call-seq:
- * array[index] = object -> object
- * array[start, length] = object -> object
- * array[range] = object -> object
+ * self[index] = object -> object
+ * self[start, length] = object -> object
+ * self[range] = object -> object
*
- * Assigns elements in +self+; returns the given +object+.
+ * Assigns elements in +self+, based on the given +object+; returns +object+.
*
* In brief:
*
* a_orig = [:foo, 'bar', 2]
+ *
* # With argument index.
* a = a_orig.dup
* a[0] = 'foo' # => "foo"
@@ -2317,6 +2474,7 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
* a = a_orig.dup
* a[7] = 'foo' # => "foo"
* a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]
+ *
* # With arguments start and length.
* a = a_orig.dup
* a[0, 2] = 'foo' # => "foo"
@@ -2324,6 +2482,7 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
* a = a_orig.dup
* a[6, 50] = 'foo' # => "foo"
* a # => [:foo, "bar", 2, nil, nil, nil, "foo"]
+ *
* # With argument range.
* a = a_orig.dup
* a[0..1] = 'foo' # => "foo"
@@ -2352,7 +2511,7 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
* a[-1] = 'two' # => "two"
* a # => [:foo, "bar", "two"]
*
- * When Integer arguments +start+ and +length+ are given and +object+ is not an +Array+,
+ * When Integer arguments +start+ and +length+ are given and +object+ is not an array,
* removes <tt>length - 1</tt> elements beginning at offset +start+,
* and assigns +object+ at offset +start+:
*
@@ -2387,7 +2546,7 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
* a[1, 5] = 'foo' # => "foo"
* a # => [:foo, "foo"]
*
- * When Range argument +range+ is given and +object+ is not an +Array+,
+ * When Range argument +range+ is given and +object+ is not an array,
* removes <tt>length - 1</tt> elements beginning at offset +start+,
* and assigns +object+ at offset +start+:
*
@@ -2437,6 +2596,7 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val)
* a[1..5] = 'foo' # => "foo"
* a # => [:foo, "foo"]
*
+ * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
*/
static VALUE
@@ -2466,38 +2626,38 @@ rb_ary_aset(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * array.insert(index, *objects) -> self
+ * insert(index, *objects) -> self
*
- * Inserts given +objects+ before or after the element at Integer index +offset+;
+ * Inserts the given +objects+ as elements of +self+;
* returns +self+.
*
- * When +index+ is non-negative, inserts all given +objects+
- * before the element at offset +index+:
+ * When +index+ is non-negative, inserts +objects+
+ * _before_ the element at offset +index+:
*
- * a = [:foo, 'bar', 2]
- * a.insert(1, :bat, :bam) # => [:foo, :bat, :bam, "bar", 2]
+ * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
+ * a.insert(1, :x, :y, :z) # => ["a", :x, :y, :z, "b", "c"]
*
* Extends the array if +index+ is beyond the array (<tt>index >= self.size</tt>):
*
- * a = [:foo, 'bar', 2]
- * a.insert(5, :bat, :bam)
- * a # => [:foo, "bar", 2, nil, nil, :bat, :bam]
+ * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
+ * a.insert(5, :x, :y, :z) # => ["a", "b", "c", nil, nil, :x, :y, :z]
*
- * Does nothing if no objects given:
+ * When +index+ is negative, inserts +objects+
+ * _after_ the element at offset <tt>index + self.size</tt>:
*
- * a = [:foo, 'bar', 2]
- * a.insert(1)
- * a.insert(50)
- * a.insert(-50)
- * a # => [:foo, "bar", 2]
+ * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
+ * a.insert(-2, :x, :y, :z) # => ["a", "b", :x, :y, :z, "c"]
*
- * When +index+ is negative, inserts all given +objects+
- * _after_ the element at offset <tt>index+self.size</tt>:
+ * With no +objects+ given, does nothing:
*
- * a = [:foo, 'bar', 2]
- * a.insert(-2, :bat, :bam)
- * a # => [:foo, "bar", :bat, :bam, 2]
+ * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
+ * a.insert(1) # => ["a", "b", "c"]
+ * a.insert(50) # => ["a", "b", "c"]
+ * a.insert(-50) # => ["a", "b", "c"]
+ *
+ * Raises IndexError if +objects+ are given and +index+ is negative and out of range.
*
+ * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
*/
static VALUE
@@ -2547,6 +2707,39 @@ ary_fetch_next(VALUE self, VALUE *index, VALUE *value)
return Qtrue;
}
+/*
+ * call-seq:
+ * each {|element| ... } -> self
+ * each -> new_enumerator
+ *
+ * With a block given, iterates over the elements of +self+,
+ * passing each element to the block;
+ * returns +self+:
+ *
+ * a = [:foo, 'bar', 2]
+ * a.each {|element| puts "#{element.class} #{element}" }
+ *
+ * Output:
+ *
+ * Symbol foo
+ * String bar
+ * Integer 2
+ *
+ * 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') }
+ *
+ * Output:
+ *
+ * foo
+ * bar
+ *
+ * With no block given, returns a new Enumerator.
+ *
+ * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
+ */
+
VALUE
rb_ary_each(VALUE ary)
{
@@ -2561,12 +2754,11 @@ rb_ary_each(VALUE ary)
/*
* call-seq:
- * array.each_index {|index| ... } -> self
- * array.each_index -> Enumerator
- *
- * Iterates over array indexes.
+ * each_index {|index| ... } -> self
+ * each_index -> new_enumerator
*
- * When a block given, passes each successive array index to the block;
+ * With a block given, iterates over the elements of +self+,
+ * passing each <i>array index</i> to the block;
* returns +self+:
*
* a = [:foo, 'bar', 2]
@@ -2582,26 +2774,16 @@ rb_ary_each(VALUE ary)
*
* a = [:foo, 'bar', 2]
* a.each_index {|index| puts index; a.clear if index > 0 }
+ * a # => []
*
* Output:
*
* 0
* 1
*
- * When no block given, returns a new Enumerator:
+ * With no block given, returns a new Enumerator.
*
- * a = [:foo, 'bar', 2]
- * e = a.each_index
- * e # => #<Enumerator: [:foo, "bar", 2]:each_index>
- * a1 = e.each {|index| puts "#{index} #{a[index]}"}
- *
- * Output:
- *
- * 0 foo
- * 1 bar
- * 2 2
- *
- * Related: #each, #reverse_each.
+ * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
*/
static VALUE
@@ -2618,47 +2800,26 @@ rb_ary_each_index(VALUE ary)
/*
* call-seq:
- * array.reverse_each {|element| ... } -> self
- * array.reverse_each -> Enumerator
+ * reverse_each {|element| ... } -> self
+ * reverse_each -> Enumerator
*
- * Iterates backwards over array elements.
- *
- * When a block given, passes, in reverse order, each element to the block;
+ * When a block given, iterates backwards over the elements of +self+,
+ * passing, in reverse order, each element to the block;
* returns +self+:
*
- * a = [:foo, 'bar', 2]
- * a.reverse_each {|element| puts "#{element.class} #{element}" }
- *
- * Output:
- *
- * Integer 2
- * String bar
- * Symbol foo
+ * a = []
+ * [0, 1, 2].reverse_each {|element| a.push(element) }
+ * a # => [2, 1, 0]
*
* Allows the array to be modified during iteration:
*
- * a = [:foo, 'bar', 2]
- * a.reverse_each {|element| puts element; a.clear if element.to_s.start_with?('b') }
- *
- * Output:
- *
- * 2
- * bar
- *
- * When no block given, returns a new Enumerator:
+ * a = ['a', 'b', 'c']
+ * a.reverse_each {|element| a.clear if element.start_with?('b') }
+ * a # => []
*
- * a = [:foo, 'bar', 2]
- * e = a.reverse_each
- * e # => #<Enumerator: [:foo, "bar", 2]:reverse_each>
- * a1 = e.each {|element| puts "#{element.class} #{element}" }
- *
- * Output:
- *
- * Integer 2
- * String bar
- * Symbol foo
+ * When no block given, returns a new Enumerator.
*
- * Related: #each, #each_index.
+ * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
*/
static VALUE
@@ -2681,9 +2842,15 @@ rb_ary_reverse_each(VALUE ary)
/*
* call-seq:
- * array.length -> an_integer
+ * length -> integer
+ * size -> integer
*
- * Returns the count of elements in +self+.
+ * Returns the count of elements in +self+:
+ *
+ * [0, 1, 2].length # => 3
+ * [].length # => 0
+ *
+ * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
*/
static VALUE
@@ -2695,10 +2862,12 @@ rb_ary_length(VALUE ary)
/*
* call-seq:
- * array.empty? -> true or false
+ * empty? -> true or false
*
* Returns +true+ if the count of elements in +self+ is zero,
* +false+ otherwise.
+ *
+ * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
*/
static VALUE
@@ -2833,23 +3002,28 @@ rb_ary_join(VALUE ary, VALUE sep)
StringValue(sep);
len += RSTRING_LEN(sep) * (RARRAY_LEN(ary) - 1);
}
- for (i=0; i<RARRAY_LEN(ary); i++) {
+ long len_memo = RARRAY_LEN(ary);
+ for (i=0; i < len_memo; i++) {
val = RARRAY_AREF(ary, i);
- tmp = rb_check_string_type(val);
-
- if (NIL_P(tmp) || tmp != val) {
- int first;
- 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());
- i = ary_join_0(ary, sep, i, result);
- first = i == 0;
- ary_join_1(ary, ary, sep, i, result, &first);
- return result;
+ if (RB_UNLIKELY(!RB_TYPE_P(val, T_STRING))) {
+ tmp = rb_check_string_type(val);
+ if (NIL_P(tmp) || tmp != val) {
+ int first;
+ 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());
+ i = ary_join_0(ary, sep, i, result);
+ first = i == 0;
+ ary_join_1(ary, ary, sep, i, result, &first);
+ return result;
+ }
+ len += RSTRING_LEN(tmp);
+ len_memo = RARRAY_LEN(ary);
+ }
+ else {
+ len += RSTRING_LEN(val);
}
-
- len += RSTRING_LEN(tmp);
}
result = rb_str_new(0, len);
@@ -2862,31 +3036,32 @@ rb_ary_join(VALUE ary, VALUE sep)
/*
* call-seq:
- * array.join ->new_string
- * array.join(separator = $,) -> new_string
+ * join(separator = $,) -> new_string
*
- * Returns the new String formed by joining the array elements after conversion.
- * For each element +element+:
+ * Returns the new string formed by joining the converted elements of +self+;
+ * for each element +element+:
*
- * - Uses <tt>element.to_s</tt> if +element+ is not a <tt>kind_of?(Array)</tt>.
- * - Uses recursive <tt>element.join(separator)</tt> if +element+ is a <tt>kind_of?(Array)</tt>.
+ * - Converts recursively using <tt>element.join(separator)</tt>
+ * if +element+ is a <tt>kind_of?(Array)</tt>.
+ * - Otherwise, converts using <tt>element.to_s</tt>.
*
- * With no argument, joins using the output field separator, <tt>$,</tt>:
+ * With no argument given, joins using the output field separator, <tt>$,</tt>:
*
* a = [:foo, 'bar', 2]
* $, # => nil
* a.join # => "foobar2"
*
- * With \string argument +separator+, joins using that separator:
+ * With string argument +separator+ given, joins using that separator:
*
* a = [:foo, 'bar', 2]
* a.join("\n") # => "foo\nbar\n2"
*
- * Joins recursively for nested Arrays:
+ * Joins recursively for nested arrays:
*
* a = [:foo, [:bar, [:baz, :bat]]]
* a.join # => "foobarbazbat"
*
+ * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
*/
static VALUE
rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
@@ -2923,14 +3098,16 @@ inspect_ary(VALUE ary, VALUE dummy, int recur)
/*
* call-seq:
- * array.inspect -> new_string
+ * inspect -> new_string
+ * to_s -> new_string
*
- * Returns the new String formed by calling method <tt>#inspect</tt>
+ * Returns the new string formed by calling method <tt>#inspect</tt>
* on each array element:
*
* a = [:foo, 'bar', 2]
* a.inspect # => "[:foo, \"bar\", 2]"
*
+ * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
*/
static VALUE
@@ -2950,21 +3127,17 @@ rb_ary_to_s(VALUE ary)
* call-seq:
* to_a -> self or new_array
*
- * When +self+ is an instance of +Array+, returns +self+:
+ * 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+:
+ * Otherwise, returns a new array containing the elements of +self+:
*
* class MyArray < Array; end
- * a = MyArray.new(['foo', 'bar', 'two'])
- * a.instance_of?(Array) # => false
- * a.kind_of?(Array) # => true
- * a1 = a.to_a
- * a1 # => ["foo", "bar", "two"]
- * a1.class # => Array # Not MyArray
+ * my_a = MyArray.new(['foo', 'bar', 'two'])
+ * a = my_a.to_a
+ * a # => ["foo", "bar", "two"]
+ * a.class # => Array # Not MyArray.
*
+ * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
*/
static VALUE
@@ -2980,27 +3153,27 @@ rb_ary_to_a(VALUE ary)
/*
* call-seq:
- * array.to_h -> new_hash
- * array.to_h {|item| ... } -> new_hash
+ * to_h -> new_hash
+ * to_h {|element| ... } -> new_hash
*
- * Returns a new Hash formed from +self+.
+ * Returns a new hash formed from +self+.
*
- * When a block is given, calls the block with each array element;
- * the block must return a 2-element +Array+ whose two elements
- * form a key-value pair in the returned Hash:
+ * With no block given, each element of +self+ must be a 2-element sub-array;
+ * forms each sub-array into a key-value pair in the new hash:
*
- * a = ['foo', :bar, 1, [2, 3], {baz: 4}]
- * h = a.to_h {|item| [item, item] }
- * h # => {"foo"=>"foo", :bar=>:bar, 1=>1, [2, 3]=>[2, 3], {:baz=>4}=>{:baz=>4}}
+ * a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
+ * a.to_h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"}
+ * [].to_h # => {}
*
- * When no block is given, +self+ must be an +Array+ of 2-element sub-arrays,
- * each sub-array is formed into a key-value pair in the new Hash:
+ * With a block given, the block must return a 2-element array;
+ * calls the block with each element of +self+;
+ * forms each returned array into a key-value pair in the returned hash:
*
- * [].to_h # => {}
- * a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
- * h = a.to_h
- * h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"}
+ * a = ['foo', :bar, 1, [2, 3], {baz: 4}]
+ * a.to_h {|element| [element, element.class] }
+ * # => {"foo"=>String, :bar=>Symbol, 1=>Integer, [2, 3]=>Array, {:baz=>4}=>Hash}
*
+ * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
*/
static VALUE
@@ -3029,7 +3202,7 @@ rb_ary_to_h(VALUE ary)
/*
* call-seq:
- * array.to_ary -> self
+ * to_ary -> self
*
* Returns +self+.
*/
@@ -3068,13 +3241,16 @@ rb_ary_reverse(VALUE ary)
/*
* call-seq:
- * array.reverse! -> self
+ * reverse! -> self
*
- * Reverses +self+ in place:
+ * Reverses the order of the elements of +self+;
+ * returns +self+:
*
- * a = ['foo', 'bar', 'two']
- * a.reverse! # => ["two", "bar", "foo"]
+ * a = [0, 1, 2]
+ * a.reverse! # => [2, 1, 0]
+ * a # => [2, 1, 0]
*
+ * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
*/
static VALUE
@@ -3085,14 +3261,13 @@ rb_ary_reverse_bang(VALUE ary)
/*
* call-seq:
- * array.reverse -> new_array
+ * reverse -> new_array
*
- * Returns a new +Array+ with the elements of +self+ in reverse order:
+ * Returns a new array containing the elements of +self+ in reverse order:
*
- * a = ['foo', 'bar', 'two']
- * a1 = a.reverse
- * a1 # => ["two", "bar", "foo"]
+ * [0, 1, 2].reverse # => [2, 1, 0]
*
+ * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
*/
static VALUE
@@ -3154,48 +3329,34 @@ rb_ary_rotate(VALUE ary, long cnt)
/*
* call-seq:
- * array.rotate! -> self
- * array.rotate!(count) -> self
+ * rotate!(count = 1) -> self
*
* Rotates +self+ in place by moving elements from one end to the other; returns +self+.
*
- * When no argument given, rotates the first element to the last position:
- *
- * a = [:foo, 'bar', 2, 'bar']
- * a.rotate! # => ["bar", 2, "bar", :foo]
- *
- * When given a non-negative Integer +count+,
+ * With non-negative numeric +count+,
* rotates +count+ elements from the beginning to the end:
*
- * a = [:foo, 'bar', 2]
- * a.rotate!(2)
- * a # => [2, :foo, "bar"]
+ * [0, 1, 2, 3].rotate!(2) # => [2, 3, 0, 1]
+ [0, 1, 2, 3].rotate!(2.1) # => [2, 3, 0, 1]
*
* If +count+ is large, uses <tt>count % array.size</tt> as the count:
*
- * a = [:foo, 'bar', 2]
- * a.rotate!(20)
- * a # => [2, :foo, "bar"]
+ * [0, 1, 2, 3].rotate!(21) # => [1, 2, 3, 0]
*
- * If +count+ is zero, returns +self+ unmodified:
+ * If +count+ is zero, rotates no elements:
*
- * a = [:foo, 'bar', 2]
- * a.rotate!(0)
- * a # => [:foo, "bar", 2]
+ * [0, 1, 2, 3].rotate!(0) # => [0, 1, 2, 3]
*
- * When given a negative Integer +count+, rotates in the opposite direction,
+ * With a negative numeric +count+, rotates in the opposite direction,
* from end to beginning:
*
- * a = [:foo, 'bar', 2]
- * a.rotate!(-2)
- * a # => ["bar", 2, :foo]
+ * [0, 1, 2, 3].rotate!(-1) # => [3, 0, 1, 2]
*
* If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
*
- * a = [:foo, 'bar', 2]
- * a.rotate!(-5)
- * a # => ["bar", 2, :foo]
+ * [0, 1, 2, 3].rotate!(-21) # => [3, 0, 1, 2]
*
+ * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
*/
static VALUE
@@ -3208,51 +3369,35 @@ rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * array.rotate -> new_array
- * array.rotate(count) -> new_array
+ * rotate(count = 1) -> new_array
*
- * Returns a new +Array+ formed from +self+ with elements
+ * Returns a new array formed from +self+ with elements
* rotated from one end to the other.
*
- * When no argument given, returns a new +Array+ that is like +self+,
- * except that the first element has been rotated to the last position:
+ * With non-negative numeric +count+,
+ * rotates elements from the beginning to the end:
*
- * 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"]
+ * [0, 1, 2, 3].rotate(2) # => [2, 3, 0, 1]
+ * [0, 1, 2, 3].rotate(2.1) # => [2, 3, 0, 1]
*
* If +count+ is large, uses <tt>count % array.size</tt> as the count:
*
- * a = [:foo, 'bar', 2]
- * a1 = a.rotate(20)
- * a1 # => [2, :foo, "bar"]
+ * [0, 1, 2, 3].rotate(22) # => [2, 3, 0, 1]
*
- * If +count+ is zero, returns a copy of +self+, unmodified:
+ * With a +count+ of zero, rotates no elements:
*
- * a = [:foo, 'bar', 2]
- * a1 = a.rotate(0)
- * a1 # => [:foo, "bar", 2]
+ * [0, 1, 2, 3].rotate(0) # => [0, 1, 2, 3]
*
- * When given a negative Integer +count+, rotates in the opposite direction,
- * from end to beginning:
+ * With negative numeric +count+, rotates in the opposite direction,
+ * from the end to the beginning:
*
- * a = [:foo, 'bar', 2]
- * a1 = a.rotate(-2)
- * a1 # => ["bar", 2, :foo]
+ * [0, 1, 2, 3].rotate(-1) # => [3, 0, 1, 2]
*
* If +count+ is small (far from zero), uses <tt>count % array.size</tt> as the count:
*
- * a = [:foo, 'bar', 2]
- * a1 = a.rotate(-5)
- * a1 # => ["bar", 2, :foo]
+ * [0, 1, 2, 3].rotate(-21) # => [3, 0, 1, 2]
*
+ * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
*/
static VALUE
@@ -3345,43 +3490,12 @@ sort_2(const void *ap, const void *bp, void *dummy)
/*
* call-seq:
- * array.sort! -> self
- * array.sort! {|a, b| ... } -> self
+ * sort! -> self
+ * sort! {|a, b| ... } -> self
*
- * Returns +self+ with its elements sorted in place.
- *
- * With no block, compares elements using operator <tt><=></tt>
- * (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"]
+ * Like Array#sort, but returns +self+ with its elements sorted in place.
*
+ * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
*/
VALUE
@@ -3434,10 +3548,9 @@ rb_ary_sort_bang(VALUE ary)
ARY_SET_CAPA(ary, ARY_HEAP_LEN(tmp));
}
/* tmp was lost ownership for the ptr */
- FL_UNSET(tmp, FL_FREEZE);
FL_SET_EMBED(tmp);
ARY_SET_EMBED_LEN(tmp, 0);
- FL_SET(tmp, FL_FREEZE);
+ OBJ_FREEZE(tmp);
}
/* tmp will be GC'ed. */
RBASIC_SET_CLASS_RAW(tmp, rb_cArray); /* rb_cArray must be marked */
@@ -3448,21 +3561,18 @@ rb_ary_sort_bang(VALUE ary)
/*
* call-seq:
- * array.sort -> new_array
- * array.sort {|a, b| ... } -> new_array
+ * sort -> new_array
+ * sort {|a, b| ... } -> new_array
*
- * Returns a new +Array+ whose elements are those from +self+, sorted.
+ * Returns a new array containing the elements of +self+, sorted.
*
- * With no block, compares elements using operator <tt><=></tt>
- * (see Comparable):
+ * With no block given, compares elements using operator <tt>#<=></tt>
+ * (see Object#<=>):
*
- * a = 'abcde'.split('').shuffle
- * a # => ["e", "b", "d", "a", "c"]
- * a1 = a.sort
- * a1 # => ["a", "b", "c", "d", "e"]
+ * [0, 2, 3, 1].sort # => [0, 1, 2, 3]
*
- * With a block, calls the block with each element pair;
- * for each element pair +a+ and +b+, the block should return an integer:
+ * With a block given, calls the block with each combination of pairs of elements from +self+;
+ * for each pair +a+ and +b+, the block should return a numeric:
*
* - Negative when +b+ is to follow +a+.
* - Zero when +a+ and +b+ are equivalent.
@@ -3470,22 +3580,17 @@ rb_ary_sort_bang(VALUE ary)
*
* Example:
*
- * a = 'abcde'.split('').shuffle
- * a # => ["e", "b", "d", "a", "c"]
- * a1 = a.sort {|a, b| a <=> b }
- * a1 # => ["a", "b", "c", "d", "e"]
- * a2 = a.sort {|a, b| b <=> a }
- * a2 # => ["e", "d", "c", "b", "a"]
+ * a = [3, 2, 0, 1]
+ * a.sort {|a, b| a <=> b } # => [0, 1, 2, 3]
+ * a.sort {|a, b| b <=> a } # => [3, 2, 1, 0]
*
* When the block returns zero, the order for +a+ and +b+ is indeterminate,
- * and may be unstable:
+ * and may be unstable.
*
- * a = 'abcde'.split('').shuffle
- * a # => ["e", "b", "d", "a", "c"]
- * a1 = a.sort {|a, b| 0 }
- * a1 # => ["c", "e", "b", "d", "a"]
+ * See an example in Numeric#nonzero? for the idiom to sort more
+ * complex structure.
*
- * Related: Enumerable#sort_by.
+ * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
*/
VALUE
@@ -3500,12 +3605,15 @@ static VALUE rb_ary_bsearch_index(VALUE ary);
/*
* call-seq:
- * array.bsearch {|element| ... } -> object
- * array.bsearch -> new_enumerator
+ * bsearch {|element| ... } -> found_element or nil
+ * bsearch -> new_enumerator
*
- * Returns an element from +self+ selected by a binary search.
+ * Returns the element from +self+ found by a binary search,
+ * or +nil+ if the search found no suitable element.
*
- * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
+ * See {Binary Searching}[rdoc-ref:language/bsearch.rdoc].
+ *
+ * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
*/
static VALUE
@@ -3521,11 +3629,15 @@ rb_ary_bsearch(VALUE ary)
/*
* call-seq:
- * array.bsearch_index {|element| ... } -> integer or nil
- * array.bsearch_index -> new_enumerator
+ * bsearch_index {|element| ... } -> integer or nil
+ * bsearch_index -> new_enumerator
+ *
+ * Returns the integer index of the element from +self+ found by a binary search,
+ * or +nil+ if the search found no suitable element.
*
- * Searches +self+ as described at method #bsearch,
- * but returns the _index_ of the found element instead of the element itself.
+ * See {Binary Searching}[rdoc-ref:language/bsearch.rdoc].
+ *
+ * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
*/
static VALUE
@@ -3584,28 +3696,24 @@ sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, dummy))
/*
* call-seq:
- * array.sort_by! {|element| ... } -> self
- * array.sort_by! -> new_enumerator
+ * sort_by! {|element| ... } -> self
+ * sort_by! -> new_enumerator
*
- * Sorts the elements of +self+ in place,
- * using an ordering determined by the block; returns self.
+ * With a block given, sorts the elements of +self+ in place;
+ * returns self.
*
* Calls the block with each successive element;
- * sorts elements based on the values returned from the block.
- *
- * For duplicates returned by the block, the ordering is indeterminate, and may be unstable.
- *
- * This example sorts strings based on their sizes:
+ * sorts elements based on the values returned from the block:
*
* a = ['aaaa', 'bbb', 'cc', 'd']
* a.sort_by! {|element| element.size }
* a # => ["d", "cc", "bbb", "aaaa"]
*
- * Returns a new Enumerator if no block given:
+ * For duplicate values returned by the block, the ordering is indeterminate, and may be unstable.
*
- * a = ['aaaa', 'bbb', 'cc', 'd']
- * a.sort_by! # => #<Enumerator: ["aaaa", "bbb", "cc", "d"]:sort_by!>
+ * With no block given, returns a new Enumerator.
*
+ * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
*/
static VALUE
@@ -3615,29 +3723,32 @@ rb_ary_sort_by_bang(VALUE ary)
RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
rb_ary_modify(ary);
- sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
- rb_ary_replace(ary, sorted);
+ if (RARRAY_LEN(ary) > 1) {
+ sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0);
+ rb_ary_replace(ary, sorted);
+ }
return ary;
}
/*
* call-seq:
- * array.map {|element| ... } -> new_array
- * array.map -> new_enumerator
+ * collect {|element| ... } -> new_array
+ * collect -> new_enumerator
+ * map {|element| ... } -> new_array
+ * map -> new_enumerator
*
- * Calls the block, if given, with each element of +self+;
- * returns a new +Array+ whose elements are the return values from the block:
+ * With a block given, calls the block with each element of +self+;
+ * returns a new array whose elements are the return values from the block:
*
* a = [:foo, 'bar', 2]
* a1 = a.map {|element| element.class }
* a1 # => [Symbol, String, Integer]
*
- * Returns a new Enumerator if no block given:
- * a = [:foo, 'bar', 2]
- * a1 = a.map
- * a1 # => #<Enumerator: [:foo, "bar", 2]:map>
+ * With no block given, returns a new Enumerator.
*
+ * Related: #collect!;
+ * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
*/
static VALUE
@@ -3657,21 +3768,22 @@ rb_ary_collect(VALUE ary)
/*
* call-seq:
- * array.map! {|element| ... } -> self
- * array.map! -> new_enumerator
+ * collect! {|element| ... } -> self
+ * collect! -> new_enumerator
+ * map! {|element| ... } -> self
+ * map! -> new_enumerator
*
- * Calls the block, if given, with each element;
- * replaces the element with the block's return value:
+ * With a block given, calls the block with each element of +self+
+ * and replaces the element with the block's return value;
+ * returns +self+:
*
* a = [:foo, 'bar', 2]
* a.map! { |element| element.class } # => [Symbol, String, Integer]
*
- * Returns a new Enumerator if no block given:
- *
- * a = [:foo, 'bar', 2]
- * a1 = a.map!
- * a1 # => #<Enumerator: [:foo, "bar", 2]:map!>
+ * With no block given, returns a new Enumerator.
*
+ * Related: #collect;
+ * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
*/
static VALUE
@@ -3743,45 +3855,108 @@ append_values_at_single(VALUE result, VALUE ary, long olen, VALUE idx)
/*
* call-seq:
- * array.values_at(*indexes) -> new_array
+ * values_at(*specifiers) -> new_array
*
- * Returns a new +Array+ whose elements are the elements
- * of +self+ at the given Integer or Range +indexes+.
+ * Returns elements from +self+ in a new array; does not modify +self+.
*
- * For each positive +index+, returns the element at offset +index+:
+ * The objects included in the returned array are the elements of +self+
+ * selected by the given +specifiers+,
+ * each of which must be a numeric index or a Range.
*
- * a = [:foo, 'bar', 2]
- * a.values_at(0, 2) # => [:foo, 2]
- * a.values_at(0..1) # => [:foo, "bar"]
+ * In brief:
+ *
+ * a = ['a', 'b', 'c', 'd']
*
- * The given +indexes+ may be in any order, and may repeat:
+ * # Index specifiers.
+ * a.values_at(2, 0, 2, 0) # => ["c", "a", "c", "a"] # May repeat.
+ * a.values_at(-4, -3, -2, -1) # => ["a", "b", "c", "d"] # Counts backwards if negative.
+ * a.values_at(-50, 50) # => [nil, nil] # Outside of self.
*
- * 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]
+ * # Range specifiers.
+ * a.values_at(1..3) # => ["b", "c", "d"] # From range.begin to range.end.
+ * a.values_at(1...3) # => ["b", "c"] # End excluded.
+ * a.values_at(3..1) # => [] # No such elements.
*
- * Assigns +nil+ for an +index+ that is too large:
+ * a.values_at(-3..3) # => ["b", "c", "d"] # Negative range.begin counts backwards.
+ * a.values_at(-50..3) # Raises RangeError.
*
- * a = [:foo, 'bar', 2]
- * a.values_at(0, 3, 1, 3) # => [:foo, nil, "bar", nil]
+ * a.values_at(1..-2) # => ["b", "c"] # Negative range.end counts backwards.
+ * a.values_at(1..-50) # => [] # No such elements.
*
- * Returns a new empty +Array+ if no arguments given.
+ * # Mixture of specifiers.
+ * a.values_at(2..3, 3, 0..1, 0) # => ["c", "d", "d", "a", "b", "a"]
*
- * For each negative +index+, counts backward from the end of the array:
+ * With no +specifiers+ given, returns a new empty array:
*
- * a = [:foo, 'bar', 2]
- * a.values_at(-1, -3) # => [2, :foo]
+ * a = ['a', 'b', 'c', 'd']
+ * a.values_at # => []
*
- * Assigns +nil+ for an +index+ that is too small:
+ * For each numeric specifier +index+, includes an element:
*
- * a = [:foo, 'bar', 2]
- * a.values_at(0, -5, 1, -6, 2) # => [:foo, nil, "bar", nil, 2]
+ * - For each non-negative numeric specifier +index+ that is in-range (less than <tt>self.size</tt>),
+ * includes the element at offset +index+:
*
- * The given +indexes+ may have a mixture of signs:
+ * a.values_at(0, 2) # => ["a", "c"]
+ * a.values_at(0.1, 2.9) # => ["a", "c"]
*
- * a = [:foo, 'bar', 2]
- * a.values_at(0, -2, 1, -1) # => [:foo, "bar", "bar", 2]
+ * - For each negative numeric +index+ that is in-range (greater than or equal to <tt>- self.size</tt>),
+ * counts backwards from the end of +self+:
+ *
+ * a.values_at(-1, -4) # => ["d", "a"]
+ *
+ * The given indexes may be in any order, and may repeat:
*
+ * a.values_at(2, 0, 1, 0, 2) # => ["c", "a", "b", "a", "c"]
+ *
+ * For each +index+ that is out-of-range, includes +nil+:
+ *
+ * a.values_at(4, -5) # => [nil, nil]
+ *
+ * For each Range specifier +range+, includes elements
+ * according to <tt>range.begin</tt> and <tt>range.end</tt>:
+ *
+ * - If both <tt>range.begin</tt> and <tt>range.end</tt>
+ * are non-negative and in-range (less than <tt>self.size</tt>),
+ * includes elements from index <tt>range.begin</tt>
+ * through <tt>range.end - 1</tt> (if <tt>range.exclude_end?</tt>),
+ * or through <tt>range.end</tt> (otherwise):
+ *
+ * a.values_at(1..2) # => ["b", "c"]
+ * a.values_at(1...2) # => ["b"]
+ *
+ * - If <tt>range.begin</tt> is negative and in-range (greater than or equal to <tt>- self.size</tt>),
+ * counts backwards from the end of +self+:
+ *
+ * a.values_at(-2..3) # => ["c", "d"]
+ *
+ * - If <tt>range.begin</tt> is negative and out-of-range, raises an exception:
+ *
+ * a.values_at(-5..3) # Raises RangeError.
+ *
+ * - If <tt>range.end</tt> is positive and out-of-range,
+ * extends the returned array with +nil+ elements:
+ *
+ * a.values_at(1..5) # => ["b", "c", "d", nil, nil]
+ *
+ * - If <tt>range.end</tt> is negative and in-range,
+ * counts backwards from the end of +self+:
+ *
+ * a.values_at(1..-2) # => ["b", "c"]
+ *
+ * - If <tt>range.end</tt> is negative and out-of-range,
+ * returns an empty array:
+ *
+ * a.values_at(1..-5) # => []
+ *
+ * The given ranges may be in any order and may repeat:
+ *
+ * a.values_at(2..3, 0..1, 2..3) # => ["c", "d", "a", "b", "c", "d"]
+ *
+ * The given specifiers may be any mixture of indexes and ranges:
+ *
+ * a.values_at(3, 1..2, 0, 2..3) # => ["d", "b", "c", "a", "c", "d"]
+ *
+ * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
*/
static VALUE
@@ -3799,22 +3974,22 @@ rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * array.select {|element| ... } -> new_array
- * array.select -> new_enumerator
+ * select {|element| ... } -> new_array
+ * select -> new_enumerator
+ * filter {|element| ... } -> new_array
+ * filter -> new_enumerator
*
- * Calls the block, if given, with each element of +self+;
- * returns a new +Array+ containing those elements of +self+
+ * With a block given, calls the block with each element of +self+;
+ * returns a new array containing those elements of +self+
* for which the block returns a truthy value:
*
* a = [:foo, 'bar', 2, :bam]
- * a1 = a.select {|element| element.to_s.start_with?('b') }
- * a1 # => ["bar", :bam]
- *
- * Returns a new Enumerator if no block given:
+ * a.select {|element| element.to_s.start_with?('b') }
+ * # => ["bar", :bam]
*
- * a = [:foo, 'bar', 2, :bam]
- * a.select # => #<Enumerator: [:foo, "bar", 2, :bam]:select>
+ * With no block given, returns a new Enumerator.
*
+ * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
*/
static VALUE
@@ -3880,10 +4055,12 @@ select_bang_ensure(VALUE a)
/*
* call-seq:
- * array.select! {|element| ... } -> self or nil
- * array.select! -> new_enumerator
+ * select! {|element| ... } -> self or nil
+ * select! -> new_enumerator
+ * filter! {|element| ... } -> self or nil
+ * filter! -> new_enumerator
*
- * Calls the block, if given with each element of +self+;
+ * With a block given, calls the block with each element of +self+;
* removes from +self+ those elements for which the block returns +false+ or +nil+.
*
* Returns +self+ if any elements were removed:
@@ -3893,11 +4070,9 @@ select_bang_ensure(VALUE a)
*
* Returns +nil+ if no elements were removed.
*
- * Returns a new Enumerator if no block given:
- *
- * a = [:foo, 'bar', 2, :bam]
- * a.select! # => #<Enumerator: [:foo, "bar", 2, :bam]:select!>
+ * With no block given, returns a new Enumerator.
*
+ * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
*/
static VALUE
@@ -3915,20 +4090,18 @@ rb_ary_select_bang(VALUE ary)
/*
* call-seq:
- * array.keep_if {|element| ... } -> self
- * array.keep_if -> new_enumeration
+ * keep_if {|element| ... } -> self
+ * keep_if -> new_enumerator
*
- * Retains those elements for which the block returns a truthy value;
- * deletes all other elements; returns +self+:
+ * With a block given, calls the block with each element of +self+;
+ * removes the element from +self+ if the block does not return a truthy value:
*
* a = [:foo, 'bar', 2, :bam]
* a.keep_if {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
*
- * Returns a new Enumerator if no block given:
- *
- * a = [:foo, 'bar', 2, :bam]
- * a.keep_if # => #<Enumerator: [:foo, "bar", 2, :bam]:keep_if>
+ * With no block given, returns a new Enumerator.
*
+ * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
*/
static VALUE
@@ -3954,38 +4127,39 @@ ary_resize_smaller(VALUE ary, long len)
/*
* call-seq:
- * array.delete(obj) -> deleted_object
- * array.delete(obj) {|nosuch| ... } -> deleted_object or block_return
+ * delete(object) -> last_removed_object
+ * delete(object) {|element| ... } -> last_removed_object or block_return
*
* Removes zero or more elements from +self+.
*
- * When no block is given,
- * removes from +self+ each element +ele+ such that <tt>ele == obj</tt>;
- * returns the last deleted element:
+ * With no block given,
+ * removes from +self+ each element +ele+ such that <tt>ele == object</tt>;
+ * returns the last removed element:
*
- * s1 = 'bar'; s2 = 'bar'
- * a = [:foo, s1, 2, s2]
- * a.delete('bar') # => "bar"
- * a # => [:foo, 2]
+ * a = [0, 1, 2, 2.0]
+ * a.delete(2) # => 2.0
+ * a # => [0, 1]
*
- * Returns +nil+ if no elements removed.
+ * Returns +nil+ if no elements removed:
*
- * When a block is given,
- * removes from +self+ each element +ele+ such that <tt>ele == obj</tt>.
+ * a.delete(2) # => nil
+ *
+ * With a block given,
+ * removes from +self+ each element +ele+ such that <tt>ele == object</tt>.
*
* If any such elements are found, ignores the block
- * and returns the last deleted element:
+ * and returns the last removed element:
*
- * s1 = 'bar'; s2 = 'bar'
- * a = [:foo, s1, 2, s2]
- * deleted_obj = a.delete('bar') {|obj| fail 'Cannot happen' }
- * a # => [:foo, 2]
+ * a = [0, 1, 2, 2.0]
+ * a.delete(2) {|element| fail 'Cannot happen' } # => 2.0
+ * a # => [0, 1]
*
- * If no such elements are found, returns the block's return value:
+ * If no such element is found, returns the block's return value:
*
- * a = [:foo, 'bar', 2]
- * a.delete(:nosuch) {|obj| "#{obj} not found" } # => "nosuch not found"
+ * a.delete(2) {|element| "Element #{element} not found." }
+ * # => "Element 2 not found."
*
+ * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
*/
VALUE
@@ -4066,9 +4240,10 @@ rb_ary_delete_at(VALUE ary, long pos)
/*
* call-seq:
- * array.delete_at(index) -> deleted_object or nil
+ * delete_at(index) -> removed_object or nil
*
- * Deletes an element from +self+, per the given Integer +index+.
+ * Removes the element of +self+ at the given +index+, which must be an
+ * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
*
* When +index+ is non-negative, deletes the element at offset +index+:
*
@@ -4076,15 +4251,19 @@ rb_ary_delete_at(VALUE ary, long pos)
* a.delete_at(1) # => "bar"
* a # => [:foo, 2]
*
- * If index is too large, returns +nil+.
- *
* When +index+ is negative, counts backward from the end of the array:
*
* a = [:foo, 'bar', 2]
* a.delete_at(-2) # => "bar"
* a # => [:foo, 2]
*
- * If +index+ is too small (far from zero), returns nil.
+ * When +index+ is out of range, returns +nil+.
+ *
+ * a = [:foo, 'bar', 2]
+ * a.delete_at(3) # => nil
+ * a.delete_at(-4) # => nil
+ *
+ * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
*/
static VALUE
@@ -4125,71 +4304,94 @@ ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len)
/*
* call-seq:
- * array.slice!(n) -> object or nil
- * array.slice!(start, length) -> new_array or nil
- * array.slice!(range) -> new_array or nil
+ * slice!(index) -> object or nil
+ * slice!(start, length) -> new_array or nil
+ * slice!(range) -> new_array or nil
*
* Removes and returns elements from +self+.
*
- * When the only argument is an Integer +n+,
- * removes and returns the _nth_ element in +self+:
+ * With numeric argument +index+ given,
+ * removes and returns the element at offset +index+:
*
- * a = [:foo, 'bar', 2]
- * a.slice!(1) # => "bar"
- * a # => [:foo, 2]
+ * a = ['a', 'b', 'c', 'd']
+ * a.slice!(2) # => "c"
+ * a # => ["a", "b", "d"]
+ * a.slice!(2.1) # => "d"
+ * a # => ["a", "b"]
*
- * If +n+ is negative, counts backwards from the end of +self+:
+ * If +index+ is negative, counts backwards from the end of +self+:
*
- * a = [:foo, 'bar', 2]
- * a.slice!(-1) # => 2
- * a # => [:foo, "bar"]
+ * a = ['a', 'b', 'c', 'd']
+ * a.slice!(-2) # => "c"
+ * a # => ["a", "b", "d"]
*
- * If +n+ is out of range, returns +nil+.
+ * If +index+ is out of range, returns +nil+.
*
- * When the only arguments are Integers +start+ and +length+,
- * removes +length+ elements from +self+ beginning at offset +start+;
- * returns the deleted objects in a new +Array+:
+ * With numeric arguments +start+ and +length+ given,
+ * removes +length+ elements from +self+ beginning at zero-based offset +start+;
+ * returns the removed objects in a new array:
*
- * a = [:foo, 'bar', 2]
- * a.slice!(0, 2) # => [:foo, "bar"]
- * a # => [2]
+ * a = ['a', 'b', 'c', 'd']
+ * a.slice!(1, 2) # => ["b", "c"]
+ * a # => ["a", "d"]
+ * a.slice!(0.1, 1.1) # => ["a"]
+ * a # => ["d"]
+ *
+ * If +start+ is negative, counts backwards from the end of +self+:
+ *
+ * a = ['a', 'b', 'c', 'd']
+ * a.slice!(-2, 1) # => ["c"]
+ * a # => ["a", "b", "d"]
+ *
+ * If +start+ is out-of-range, returns +nil+:
+ *
+ * a = ['a', 'b', 'c', 'd']
+ * a.slice!(5, 1) # => nil
+ * a.slice!(-5, 1) # => nil
*
* If <tt>start + length</tt> exceeds the array size,
* removes and returns all elements from offset +start+ to the end:
*
- * a = [:foo, 'bar', 2]
- * a.slice!(1, 50) # => ["bar", 2]
- * a # => [:foo]
+ * a = ['a', 'b', 'c', 'd']
+ * a.slice!(2, 50) # => ["c", "d"]
+ * a # => ["a", "b"]
*
* If <tt>start == a.size</tt> and +length+ is non-negative,
- * returns a new empty +Array+.
+ * returns a new empty array.
*
* If +length+ is negative, returns +nil+.
*
- * When the only argument is a Range object +range+,
- * treats <tt>range.min</tt> as +start+ above and <tt>range.size</tt> as +length+ above:
+ * With Range argument +range+ given,
+ * treats <tt>range.min</tt> as +start+ (as above)
+ * and <tt>range.size</tt> as +length+ (as above):
*
- * a = [:foo, 'bar', 2]
- * a.slice!(1..2) # => ["bar", 2]
- * a # => [:foo]
+ * a = ['a', 'b', 'c', 'd']
+ * a.slice!(1..2) # => ["b", "c"]
+ * a # => ["a", "d"]
*
- * If <tt>range.start == a.size</tt>, returns a new empty +Array+.
+ * If <tt>range.start == a.size</tt>, returns a new empty array:
*
- * If <tt>range.start</tt> is larger than the array size, returns +nil+.
+ * a = ['a', 'b', 'c', 'd']
+ * a.slice!(4..5) # => []
*
- * If <tt>range.end</tt> is negative, counts backwards from the end of the array:
+ * If <tt>range.start</tt> is larger than the array size, returns +nil+:
*
- * a = [:foo, 'bar', 2]
- * a.slice!(0..-2) # => [:foo, "bar"]
- * a # => [2]
+ * a = ['a', 'b', 'c', 'd']
+ a.slice!(5..6) # => nil
*
* If <tt>range.start</tt> is negative,
- * calculates the start index backwards from the end of the array:
+ * calculates the start index by counting backwards from the end of +self+:
*
- * a = [:foo, 'bar', 2]
- * a.slice!(-2..2) # => ["bar", 2]
- * a # => [:foo]
+ * a = ['a', 'b', 'c', 'd']
+ * a.slice!(-2..2) # => ["c"]
+ *
+ * If <tt>range.end</tt> is negative,
+ * calculates the end index by counting backwards from the end of +self+:
+ *
+ * a = ['a', 'b', 'c', 'd']
+ * a.slice!(0..-2) # => ["a", "b", "c"]
*
+ * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
*/
static VALUE
@@ -4270,10 +4472,11 @@ ary_reject_bang(VALUE ary)
/*
* call-seq:
- * array.reject! {|element| ... } -> self or nil
- * array.reject! -> new_enumerator
+ * reject! {|element| ... } -> self or nil
+ * reject! -> new_enumerator
*
- * Removes each element for which the block returns a truthy value.
+ * With a block given, calls the block with each element of +self+;
+ * removes each element for which the block returns a truthy value.
*
* Returns +self+ if any elements removed:
*
@@ -4282,11 +4485,9 @@ ary_reject_bang(VALUE ary)
*
* Returns +nil+ if no elements removed.
*
- * Returns a new Enumerator if no block given:
- *
- * a = [:foo, 'bar', 2]
- * a.reject! # => #<Enumerator: [:foo, "bar", 2]:reject!>
+ * With no block given, returns a new Enumerator.
*
+ * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
*/
static VALUE
@@ -4299,21 +4500,19 @@ rb_ary_reject_bang(VALUE ary)
/*
* call-seq:
- * array.reject {|element| ... } -> new_array
- * array.reject -> new_enumerator
+ * reject {|element| ... } -> new_array
+ * reject -> new_enumerator
*
- * Returns a new +Array+ whose elements are all those from +self+
+ * With a block given, returns a new array whose elements are all those from +self+
* for which the block returns +false+ or +nil+:
*
* a = [:foo, 'bar', 2, 'bat']
* a1 = a.reject {|element| element.to_s.start_with?('b') }
* a1 # => [:foo, 2]
*
- * Returns a new Enumerator if no block given:
- *
- * a = [:foo, 'bar', 2]
- * a.reject # => #<Enumerator: [:foo, "bar", 2]:reject>
+ * With no block given, returns a new Enumerator.
*
+ * Related: {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
*/
static VALUE
@@ -4329,20 +4528,19 @@ rb_ary_reject(VALUE ary)
/*
* call-seq:
- * array.delete_if {|element| ... } -> self
- * array.delete_if -> Enumerator
+ * delete_if {|element| ... } -> self
+ * delete_if -> new_numerator
*
- * Removes each element in +self+ for which the block returns a truthy value;
+ * With a block given, calls the block with each element of +self+;
+ * removes the element if the block returns a truthy value;
* returns +self+:
*
* a = [:foo, 'bar', 2, 'bat']
* a.delete_if {|element| element.to_s.start_with?('b') } # => [:foo, 2]
*
- * Returns a new Enumerator if no block given:
- *
- * a = [:foo, 'bar', 2]
- * a.delete_if # => #<Enumerator: [:foo, "bar", 2]:delete_if>
+ * With no block given, returns a new Enumerator.
*
+ * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
*/
static VALUE
@@ -4383,65 +4581,95 @@ take_items(VALUE obj, long n)
/*
* call-seq:
- * array.zip(*other_arrays) -> new_array
- * array.zip(*other_arrays) {|other_array| ... } -> nil
+ * zip(*other_arrays) -> new_array
+ * zip(*other_arrays) {|sub_array| ... } -> nil
+ *
+ * With no block given, combines +self+ with the collection of +other_arrays+;
+ * returns a new array of sub-arrays:
*
- * When no block given, returns a new +Array+ +new_array+ of size <tt>self.size</tt>
- * whose elements are Arrays.
+ * [0, 1].zip(['zero', 'one'], [:zero, :one])
+ * # => [[0, "zero", :zero], [1, "one", :one]]
*
- * Each nested array <tt>new_array[n]</tt> is of size <tt>other_arrays.size+1</tt>,
- * and contains:
+ * Returned:
*
- * - The _nth_ element of +self+.
- * - The _nth_ element of each of the +other_arrays+.
+ * - The outer array is of size <tt>self.size</tt>.
+ * - Each sub-array is of size <tt>other_arrays.size + 1</tt>.
+ * - The _nth_ sub-array contains (in order):
*
- * If all +other_arrays+ and +self+ are the same size:
+ * - The _nth_ element of +self+.
+ * - The _nth_ element of each of the other arrays, as available.
+ *
+ * Example:
+ *
+ * a = [0, 1]
+ * zipped = a.zip(['zero', 'one'], [:zero, :one])
+ * # => [[0, "zero", :zero], [1, "one", :one]]
+ * zipped.size # => 2 # Same size as a.
+ * zipped.first.size # => 3 # Size of other arrays plus 1.
+ *
+ * When the other arrays are all the same size as +self+,
+ * the returned sub-arrays are a rearrangement containing exactly elements of all the arrays
+ * (including +self+), with no omissions or additions:
*
* a = [:a0, :a1, :a2, :a3]
* b = [:b0, :b1, :b2, :b3]
* c = [:c0, :c1, :c2, :c3]
* d = a.zip(b, c)
- * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
+ * pp d
+ * # =>
+ * [[:a0, :b0, :c0],
+ * [:a1, :b1, :c1],
+ * [:a2, :b2, :c2],
+ * [:a3, :b3, :c3]]
*
- * If any array in +other_arrays+ is smaller than +self+,
- * fills to <tt>self.size</tt> with +nil+:
+ * When one of the other arrays is smaller than +self+,
+ * pads the corresponding sub-array with +nil+ elements:
*
* a = [:a0, :a1, :a2, :a3]
* b = [:b0, :b1, :b2]
* c = [:c0, :c1]
* d = a.zip(b, c)
- * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, nil], [:a3, nil, nil]]
+ * pp d
+ * # =>
+ * [[:a0, :b0, :c0],
+ * [:a1, :b1, :c1],
+ * [:a2, :b2, nil],
+ * [:a3, nil, nil]]
*
- * If any array in +other_arrays+ is larger than +self+,
- * its trailing elements are ignored:
+ * When one of the other arrays is larger than +self+,
+ * _ignores_ its trailing elements:
*
* a = [:a0, :a1, :a2, :a3]
* b = [:b0, :b1, :b2, :b3, :b4]
* c = [:c0, :c1, :c2, :c3, :c4, :c5]
* d = a.zip(b, c)
- * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]]
- *
- * If an argument is not an array, it extracts the values by calling #each:
- *
- * a = [:a0, :a1, :a2, :a2]
- * b = 1..4
- * c = a.zip(b)
- * c # => [[:a0, 1], [:a1, 2], [:a2, 3], [:a2, 4]]
+ * pp d
+ * # =>
+ * [[:a0, :b0, :c0],
+ * [:a1, :b1, :c1],
+ * [:a2, :b2, :c2],
+ * [:a3, :b3, :c3]]
*
- * When a block is given, calls the block with each of the sub-arrays (formed as above); returns +nil+:
+ * With a block given, calls the block with each of the other arrays;
+ * returns +nil+:
*
+ * d = []
* a = [:a0, :a1, :a2, :a3]
* b = [:b0, :b1, :b2, :b3]
* c = [:c0, :c1, :c2, :c3]
- * a.zip(b, c) {|sub_array| p sub_array} # => nil
- *
- * Output:
- *
- * [:a0, :b0, :c0]
- * [:a1, :b1, :c1]
- * [:a2, :b2, :c2]
- * [:a3, :b3, :c3]
- *
+ * a.zip(b, c) {|sub_array| d.push(sub_array.reverse) } # => nil
+ * pp d
+ * # =>
+ * [[:c0, :b0, :a0],
+ * [:c1, :b1, :a1],
+ * [:c2, :b2, :a2],
+ * [:c3, :b3, :a3]]
+ *
+ * For an *object* in *other_arrays* that is not actually an array,
+ * forms the "other array" as <tt>object.to_ary</tt>, if defined,
+ * or as <tt>object.each.to_a</tt> otherwise.
+ *
+ * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
*/
static VALUE
@@ -4504,14 +4732,17 @@ rb_ary_zip(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * array.transpose -> new_array
+ * transpose -> new_array
*
- * Transposes the rows and columns in an +Array+ of Arrays;
- * the nested Arrays must all be the same size:
+ * Returns a new array that is +self+
+ * as a {transposed matrix}[https://en.wikipedia.org/wiki/Transpose]:
*
* a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]]
* a.transpose # => [[:a0, :b0, :c0], [:a1, :b1, :c1]]
*
+ * The elements of +self+ must all be the same size.
+ *
+ * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
*/
static VALUE
@@ -4544,13 +4775,17 @@ rb_ary_transpose(VALUE ary)
/*
* call-seq:
- * array.replace(other_array) -> self
+ * initialize_copy(other_array) -> self
+ * replace(other_array) -> self
*
- * Replaces the content of +self+ with the content of +other_array+; returns +self+:
+ * Replaces the elements of +self+ with the elements of +other_array+, which must be an
+ * {array-convertible object}[rdoc-ref:implicit_conversion.rdoc@Array-Convertible+Objects];
+ * returns +self+:
*
- * a = [:foo, 'bar', 2]
- * a.replace(['foo', :bar, 3]) # => ["foo", :bar, 3]
+ * a = ['a', 'b', 'c'] # => ["a", "b", "c"]
+ * a.replace(['d', 'e']) # => ["d", "e"]
*
+ * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
*/
VALUE
@@ -4591,6 +4826,8 @@ rb_ary_replace(VALUE copy, VALUE orig)
ARY_SET_PTR(copy, ARY_HEAP_PTR(orig));
ARY_SET_LEN(copy, ARY_HEAP_LEN(orig));
rb_ary_set_shared(copy, shared_root);
+
+ RUBY_ASSERT(RB_OBJ_SHAREABLE_P(copy) ? RB_OBJ_SHAREABLE_P(shared_root) : 1);
}
ary_verify(copy);
return copy;
@@ -4598,13 +4835,14 @@ rb_ary_replace(VALUE copy, VALUE orig)
/*
* call-seq:
- * array.clear -> self
+ * clear -> self
*
- * Removes all elements from +self+:
+ * Removes all elements from +self+; returns +self+:
*
* a = [:foo, 'bar', 2]
* a.clear # => []
*
+ * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
*/
VALUE
@@ -4612,11 +4850,9 @@ rb_ary_clear(VALUE ary)
{
rb_ary_modify_check(ary);
if (ARY_SHARED_P(ary)) {
- if (!ARY_EMBED_P(ary)) {
- rb_ary_unshare(ary);
- FL_SET_EMBED(ary);
- ARY_SET_EMBED_LEN(ary, 0);
- }
+ rb_ary_unshare(ary);
+ FL_SET_EMBED(ary);
+ ARY_SET_EMBED_LEN(ary, 0);
}
else {
ARY_SET_LEN(ary, 0);
@@ -4630,198 +4866,182 @@ rb_ary_clear(VALUE ary)
/*
* call-seq:
- * array.fill(obj) -> self
- * array.fill(obj, start) -> self
- * array.fill(obj, start, length) -> self
- * array.fill(obj, range) -> self
- * array.fill {|index| ... } -> self
- * array.fill(start) {|index| ... } -> self
- * array.fill(start, length) {|index| ... } -> self
- * array.fill(range) {|index| ... } -> self
+ * fill(object, start = nil, count = nil) -> self
+ * fill(object, range) -> self
+ * fill(start = nil, count = nil) {|element| ... } -> self
+ * fill(range) {|element| ... } -> self
*
- * Replaces specified elements in +self+ with specified objects; returns +self+.
+ * Replaces selected elements in +self+;
+ * may add elements to +self+;
+ * always returns +self+ (never a new array).
*
- * With argument +obj+ and no block given, replaces all elements with that one object:
+ * In brief:
*
- * a = ['a', 'b', 'c', 'd']
- * a # => ["a", "b", "c", "d"]
- * a.fill(:X) # => [:X, :X, :X, :X]
+ * # Non-negative start.
+ * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
+ * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
*
- * With arguments +obj+ and Integer +start+, and no block given,
- * replaces elements based on the given start.
+ * # Extends with specified values if necessary.
+ * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
+ * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
*
- * If +start+ is in range (<tt>0 <= start < array.size</tt>),
- * replaces all elements from offset +start+ through the end:
+ * # Fills with nils if necessary.
+ * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
+ * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
*
- * a = ['a', 'b', 'c', 'd']
- * a.fill(:X, 2) # => ["a", "b", :X, :X]
+ * # For negative start, counts backwards from the end.
+ * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
+ * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
*
- * If +start+ is too large (<tt>start >= array.size</tt>), does nothing:
+ * # Range.
+ * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
+ * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
*
- * 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"]
+ * When arguments +start+ and +count+ are given,
+ * they select the elements of +self+ to be replaced;
+ * each must be an
+ * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
+ * (or +nil+):
*
- * If +start+ is negative, counts from the end (starting index is <tt>start + array.size</tt>):
+ * - +start+ specifies the zero-based offset of the first element to be replaced;
+ * +nil+ means zero.
+ * - +count+ is the number of consecutive elements to be replaced;
+ * +nil+ means "all the rest."
*
- * a = ['a', 'b', 'c', 'd']
- * a.fill(:X, -2) # => ["a", "b", :X, :X]
+ * With argument +object+ given,
+ * that one object is used for all replacements:
*
- * If +start+ is too small (less than and far from zero), replaces all elements:
+ * o = Object.new # => #<Object:0x0000014e7bff7600>
+ * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
+ * a.fill(o, 1, 2)
+ * # => ["a", #<Object:0x0000014e7bff7600>, #<Object:0x0000014e7bff7600>, "d"]
*
- * 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 a block given, the block is called once for each element to be replaced;
+ * the value passed to the block is the _index_ of the element to be replaced
+ * (not the element itself);
+ * the block's return value replaces the element:
*
- * With arguments +obj+, Integer +start+, and Integer +length+, and no block given,
- * replaces elements based on the given +start+ and +length+.
+ * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
+ * a.fill(1, 2) {|element| element.to_s } # => ["a", "1", "2", "d"]
*
- * If +start+ is in range, replaces +length+ elements beginning at offset +start+:
+ * For arguments +start+ and +count+:
*
- * a = ['a', 'b', 'c', 'd']
- * a.fill(:X, 1, 1) # => ["a", :X, "c", "d"]
+ * - If +start+ is non-negative,
+ * replaces +count+ elements beginning at offset +start+:
*
- * If +start+ is negative, counts from the end:
+ * ['a', 'b', 'c', 'd'].fill('-', 0, 2) # => ["-", "-", "c", "d"]
+ * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
+ * ['a', 'b', 'c', 'd'].fill('-', 2, 2) # => ["a", "b", "-", "-"]
*
- * a = ['a', 'b', 'c', 'd']
- * a.fill(:X, -2, 1) # => ["a", "b", :X, "d"]
+ * ['a', 'b', 'c', 'd'].fill(0, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
+ * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
+ * ['a', 'b', 'c', 'd'].fill(2, 2) {|e| e.to_s } # => ["a", "b", "2", "3"]
*
- * If +start+ is large (<tt>start >= array.size</tt>), extends +self+ with +nil+:
+ * Extends +self+ if necessary:
*
- * a = ['a', 'b', 'c', 'd']
- * a.fill(:X, 5, 0) # => ["a", "b", "c", "d", nil]
- * a = ['a', 'b', 'c', 'd']
- * a.fill(:X, 5, 2) # => ["a", "b", "c", "d", nil, :X, :X]
+ * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
+ * ['a', 'b', 'c', 'd'].fill('-', 4, 2) # => ["a", "b", "c", "d", "-", "-"]
*
- * If +length+ is zero or negative, replaces no elements:
+ * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
+ * ['a', 'b', 'c', 'd'].fill(4, 2) {|e| e.to_s } # => ["a", "b", "c", "d", "4", "5"]
*
- * a = ['a', 'b', 'c', 'd']
- * a.fill(:X, 1, 0) # => ["a", "b", "c", "d"]
- * a.fill(:X, 1, -1) # => ["a", "b", "c", "d"]
+ * Fills with +nil+ if necessary:
*
- * With arguments +obj+ and Range +range+, and no block given,
- * replaces elements based on the given range.
+ * ['a', 'b', 'c', 'd'].fill('-', 5, 2) # => ["a", "b", "c", "d", nil, "-", "-"]
+ * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
*
- * If the range is positive and ascending (<tt>0 < range.begin <= range.end</tt>),
- * replaces elements from <tt>range.begin</tt> to <tt>range.end</tt>:
+ * ['a', 'b', 'c', 'd'].fill(5, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, "5", "6"]
+ * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
*
- * a = ['a', 'b', 'c', 'd']
- * a.fill(:X, (1..1)) # => ["a", :X, "c", "d"]
+ * Does nothing if +count+ is non-positive:
*
- * If <tt>range.first</tt> is negative, replaces no elements:
+ * ['a', 'b', 'c', 'd'].fill('-', 2, 0) # => ["a", "b", "c", "d"]
+ * ['a', 'b', 'c', 'd'].fill('-', 2, -100) # => ["a", "b", "c", "d"]
+ * ['a', 'b', 'c', 'd'].fill('-', 6, -100) # => ["a", "b", "c", "d"]
*
- * a = ['a', 'b', 'c', 'd']
- * a.fill(:X, (-1..1)) # => ["a", "b", "c", "d"]
+ * ['a', 'b', 'c', 'd'].fill(2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
+ * ['a', 'b', 'c', 'd'].fill(2, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
+ * ['a', 'b', 'c', 'd'].fill(6, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
*
- * If <tt>range.last</tt> is negative, counts from the end:
+ * - If +start+ is negative, counts backwards from the end of +self+:
*
- * a = ['a', 'b', 'c', 'd']
- * a.fill(:X, (0..-2)) # => [:X, :X, :X, "d"]
- * a = ['a', 'b', 'c', 'd']
- * a.fill(:X, (1..-2)) # => ["a", :X, :X, "d"]
+ * ['a', 'b', 'c', 'd'].fill('-', -4, 3) # => ["-", "-", "-", "d"]
+ * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
*
- * If <tt>range.last</tt> and <tt>range.last</tt> are both negative,
- * both count from the end of the array:
+ * ['a', 'b', 'c', 'd'].fill(-4, 3) {|e| e.to_s } # => ["0", "1", "2", "d"]
+ * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
*
- * 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"]
+ * Extends +self+ if necessary:
*
- * With no arguments and a block given, calls the block with each index;
- * replaces the corresponding element with the block's return value:
+ * ['a', 'b', 'c', 'd'].fill('-', -2, 3) # => ["a", "b", "-", "-", "-"]
+ * ['a', 'b', 'c', 'd'].fill('-', -1, 3) # => ["a", "b", "c", "-", "-", "-"]
*
- * a = ['a', 'b', 'c', 'd']
- * a.fill { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
+ * ['a', 'b', 'c', 'd'].fill(-2, 3) {|e| e.to_s } # => ["a", "b", "2", "3", "4"]
+ * ['a', 'b', 'c', 'd'].fill(-1, 3) {|e| e.to_s } # => ["a", "b", "c", "3", "4", "5"]
*
- * 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.
+ * Starts at the beginning of +self+ if +start+ is negative and out-of-range:
*
- * If start is in range (<tt>0 <= start < array.size</tt>),
- * replaces from offset +start+ to the end:
+ * ['a', 'b', 'c', 'd'].fill('-', -5, 2) # => ["-", "-", "c", "d"]
+ * ['a', 'b', 'c', 'd'].fill('-', -6, 2) # => ["-", "-", "c", "d"]
*
- * a = ['a', 'b', 'c', 'd']
- * a.fill(1) { |index| "new_#{index}" } # => ["a", "new_1", "new_2", "new_3"]
+ * ['a', 'b', 'c', 'd'].fill(-5, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
+ * ['a', 'b', 'c', 'd'].fill(-6, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
*
- * If +start+ is too large(<tt>start >= array.size</tt>), does nothing:
+ * Does nothing if +count+ is non-positive:
*
- * a = ['a', 'b', 'c', 'd']
- * a.fill(4) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
- * a = ['a', 'b', 'c', 'd']
- * a.fill(4) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
+ * ['a', 'b', 'c', 'd'].fill('-', -2, 0) # => ["a", "b", "c", "d"]
+ * ['a', 'b', 'c', 'd'].fill('-', -2, -1) # => ["a", "b", "c", "d"]
*
- * If +start+ is negative, counts from the end:
+ * ['a', 'b', 'c', 'd'].fill(-2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
+ * ['a', 'b', 'c', 'd'].fill(-2, -1) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
*
- * a = ['a', 'b', 'c', 'd']
- * a.fill(-2) { |index| "new_#{index}" } # => ["a", "b", "new_2", "new_3"]
+ * When argument +range+ is given,
+ * it must be a Range object whose members are numeric;
+ * its +begin+ and +end+ values determine the elements of +self+
+ * to be replaced:
*
- * If start is too small (<tt>start <= -array.size</tt>, replaces all elements:
+ * - If both +begin+ and +end+ are positive, they specify the first and last elements
+ * to be replaced:
*
- * a = ['a', 'b', 'c', 'd']
- * a.fill(-6) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
- * a = ['a', 'b', 'c', 'd']
- * a.fill(-50) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"]
+ * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"]
+ * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
*
- * With arguments +start+ and +length+, and a block given,
- * calls the block for each index specified by start length;
- * replaces the corresponding element with the block's return value.
+ * If +end+ is smaller than +begin+, replaces no elements:
*
- * 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"]
+ * ['a', 'b', 'c', 'd'].fill('-', 2..1) # => ["a", "b", "c", "d"]
+ * ['a', 'b', 'c', 'd'].fill(2..1) {|e| e.to_s } # => ["a", "b", "c", "d"]
*
- * If start is negative, counts from the end:
+ * - If either is negative (or both are negative), counts backwards from the end of +self+:
*
- * a = ['a', 'b', 'c', 'd']
- * a.fill(-2, 1) { |index| "new_#{index}" } # => ["a", "b", "new_2", "d"]
+ * ['a', 'b', 'c', 'd'].fill('-', -3..2) # => ["a", "-", "-", "d"]
+ * ['a', 'b', 'c', 'd'].fill('-', 1..-2) # => ["a", "-", "-", "d"]
+ * ['a', 'b', 'c', 'd'].fill('-', -3..-2) # => ["a", "-", "-", "d"]
*
- * If +start+ is large (<tt>start >= array.size</tt>), extends +self+ with +nil+:
+ * ['a', 'b', 'c', 'd'].fill(-3..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
+ * ['a', 'b', 'c', 'd'].fill(1..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
+ * ['a', 'b', 'c', 'd'].fill(-3..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
*
- * a = ['a', 'b', 'c', 'd']
- * a.fill(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 the +end+ value is excluded (see Range#exclude_end?), omits the last replacement:
*
- * If +length+ is zero or less, replaces no elements:
+ * ['a', 'b', 'c', 'd'].fill('-', 1...2) # => ["a", "-", "c", "d"]
+ * ['a', 'b', 'c', 'd'].fill('-', 1...-2) # => ["a", "-", "c", "d"]
*
- * a = ['a', 'b', 'c', 'd']
- * a.fill(1, 0) { |index| "new_#{index}" } # => ["a", "b", "c", "d"]
- * a.fill(1, -1) { |index| "new_#{index}" } # => ["a", "b", "c", "d"]
+ * ['a', 'b', 'c', 'd'].fill(1...2) {|e| e.to_s } # => ["a", "1", "c", "d"]
+ * ['a', 'b', 'c', 'd'].fill(1...-2) {|e| e.to_s } # => ["a", "1", "c", "d"]
*
- * 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 endless (see {Endless Ranges}[rdoc-ref:Range@Endless+Ranges]),
+ * replaces elements to the end of +self+:
*
- * If the range is positive and ascending (<tt>range 0 < range.begin <= range.end</tt>,
- * replaces elements from <tt>range.begin</tt> to <tt>range.end</tt>:
+ * ['a', 'b', 'c', 'd'].fill('-', 1..) # => ["a", "-", "-", "-"]
+ * ['a', 'b', 'c', 'd'].fill(1..) {|e| e.to_s } # => ["a", "1", "2", "3"]
*
- * a = ['a', 'b', 'c', 'd']
- * a.fill(1..1) { |index| "new_#{index}" } # => ["a", "new_1", "c", "d"]
+ * - If the range is beginless (see {Beginless Ranges}[rdoc-ref:Range@Beginless+Ranges]),
+ * replaces elements from the beginning of +self+:
*
- * 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 <tt>range.last</tt> 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 <tt>range.first</tt> and <tt>range.last</tt> 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"]
+ * ['a', 'b', 'c', 'd'].fill('-', ..2) # => ["-", "-", "-", "d"]
+ * ['a', 'b', 'c', 'd'].fill(..2) {|e| e.to_s } # => ["0", "1", "2", "d"]
*
+ * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
*/
static VALUE
@@ -4890,15 +5110,15 @@ rb_ary_fill(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * array + other_array -> new_array
+ * self + other_array -> new_array
*
- * Returns a new +Array+ containing all elements of +array+
+ * Returns a new array containing all elements of +self+
* followed by all elements of +other_array+:
*
* a = [0, 1] + [2, 3]
* a # => [0, 1, 2, 3]
*
- * Related: #concat.
+ * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
*/
VALUE
@@ -4932,12 +5152,15 @@ ary_append(VALUE x, VALUE y)
/*
* call-seq:
- * array.concat(*other_arrays) -> self
+ * concat(*other_arrays) -> self
*
- * Adds to +array+ all elements from each +Array+ in +other_arrays+; returns +self+:
+ * Adds to +self+ all elements from each array in +other_arrays+; returns +self+:
*
* a = [0, 1]
- * a.concat([2, 3], [4, 5]) # => [0, 1, 2, 3, 4, 5]
+ * a.concat(['two', 'three'], [:four, :five], a)
+ * # => [0, 1, "two", "three", :four, :five, 0, 1]
+ *
+ * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
*/
static VALUE
@@ -4969,19 +5192,19 @@ rb_ary_concat(VALUE x, VALUE y)
/*
* call-seq:
- * array * n -> new_array
- * array * string_separator -> new_string
+ * self * n -> new_array
+ * self * string_separator -> new_string
*
- * When non-negative argument Integer +n+ is given,
- * returns a new +Array+ built by concatenating the +n+ copies of +self+:
+ * When non-negative integer argument +n+ is given,
+ * returns a new array built by concatenating +n+ copies of +self+:
*
* a = ['x', 'y']
* a * 3 # => ["x", "y", "x", "y", "x", "y"]
*
- * When String argument +string_separator+ is given,
- * equivalent to <tt>array.join(string_separator)</tt>:
+ * When string argument +string_separator+ is given,
+ * equivalent to <tt>self.join(string_separator)</tt>:
*
- * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {:foo=>0}"
+ * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {foo: 0}"
*
*/
@@ -5031,17 +5254,18 @@ rb_ary_times(VALUE ary, VALUE times)
/*
* call-seq:
- * array.assoc(obj) -> found_array or nil
+ * assoc(object) -> found_array or nil
*
- * Returns the first element in +self+ that is an +Array+
- * whose first element <tt>==</tt> +obj+:
+ * Returns the first element +ele+ in +self+ such that +ele+ is an array
+ * and <tt>ele[0] == object</tt>:
*
* a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
* a.assoc(4) # => [4, 5, 6]
*
* Returns +nil+ if no such element is found.
*
- * Related: #rassoc.
+ * Related: Array#rassoc;
+ * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
*/
VALUE
@@ -5061,17 +5285,19 @@ rb_ary_assoc(VALUE ary, VALUE key)
/*
* call-seq:
- * array.rassoc(obj) -> found_array or nil
+ * rassoc(object) -> found_array or nil
*
- * Returns the first element in +self+ that is an +Array+
- * whose second element <tt>==</tt> +obj+:
+ * Returns the first element +ele+ in +self+ such that +ele+ is an array
+ * and <tt>ele[1] == object</tt>:
*
* a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
* a.rassoc(4) # => [2, 4]
+ * a.rassoc(5) # => [4, 5, 6]
*
* Returns +nil+ if no such element is found.
*
- * Related: #assoc.
+ * Related: Array#assoc;
+ * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
*/
VALUE
@@ -5126,20 +5352,26 @@ recursive_equal(VALUE ary1, VALUE ary2, int recur)
/*
* call-seq:
- * array == other_array -> true or false
+ * self == other_array -> true or false
*
- * Returns +true+ if both <tt>array.size == other_array.size</tt>
- * and for each index +i+ in +array+, <tt>array[i] == other_array[i]</tt>:
+ * Returns whether both:
*
- * a0 = [:foo, 'bar', 2]
- * a1 = [:foo, 'bar', 2.0]
- * a1 == a0 # => true
- * [] == [] # => true
+ * - +self+ and +other_array+ are the same size.
+ * - Their corresponding elements are the same;
+ * that is, for each index +i+ in <tt>(0...self.size)</tt>,
+ * <tt>self[i] == other_array[i]</tt>.
*
- * Otherwise, returns +false+.
+ * Examples:
+ *
+ * [:foo, 'bar', 2] == [:foo, 'bar', 2] # => true
+ * [:foo, 'bar', 2] == [:foo, 'bar', 2.0] # => true
+ * [:foo, 'bar', 2] == [:foo, 'bar'] # => false # Different sizes.
+ * [:foo, 'bar', 2] == [:foo, 'bar', 3] # => false # Different elements.
*
* This method is different from method Array#eql?,
* which compares elements using <tt>Object#eql?</tt>.
+ *
+ * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
*/
static VALUE
@@ -5172,7 +5404,7 @@ recursive_eql(VALUE ary1, VALUE ary2, int recur)
/*
* call-seq:
- * array.eql?(other_array) -> true or false
+ * eql?(other_array) -> true or false
*
* Returns +true+ if +self+ and +other_array+ are the same size,
* and if, for each index +i+ in +self+, <tt>self[i].eql?(other_array[i])</tt>:
@@ -5185,6 +5417,8 @@ recursive_eql(VALUE ary1, VALUE ary2, int recur)
*
* This method is different from method Array#==,
* which compares using method <tt>Object#==</tt>.
+ *
+ * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
*/
static VALUE
@@ -5197,8 +5431,8 @@ rb_ary_eql(VALUE ary1, VALUE ary2)
return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2);
}
-VALUE
-rb_ary_hash_values(long len, const VALUE *elements)
+static VALUE
+ary_hash_values(long len, const VALUE *elements, const VALUE ary)
{
long i;
st_index_t h;
@@ -5209,39 +5443,55 @@ rb_ary_hash_values(long len, const VALUE *elements)
for (i=0; i<len; i++) {
n = rb_hash(elements[i]);
h = rb_hash_uint(h, NUM2LONG(n));
+ if (ary) {
+ len = RARRAY_LEN(ary);
+ elements = RARRAY_CONST_PTR(ary);
+ }
}
h = rb_hash_end(h);
return ST2FIX(h);
}
+VALUE
+rb_ary_hash_values(long len, const VALUE *elements)
+{
+ return ary_hash_values(len, elements, 0);
+}
+
/*
* call-seq:
- * array.hash -> integer
+ * hash -> integer
*
* Returns the integer hash value for +self+.
*
- * Two arrays with the same content will have the same hash code (and will compare using #eql?):
+ * Two arrays with the same content will have the same hash value
+ * (and will compare using eql?):
*
- * [0, 1, 2].hash == [0, 1, 2].hash # => true
- * [0, 1, 2].hash == [0, 1, 3].hash # => false
+ * ['a', 'b'].hash == ['a', 'b'].hash # => true
+ * ['a', 'b'].hash == ['a', 'c'].hash # => false
+ * ['a', 'b'].hash == ['a'].hash # => false
*
*/
static VALUE
rb_ary_hash(VALUE ary)
{
- return rb_ary_hash_values(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary));
+ RBIMPL_ASSERT_OR_ASSUME(ary);
+ return ary_hash_values(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary), ary);
}
/*
* call-seq:
- * array.include?(obj) -> true or false
+ * include?(object) -> true or false
*
- * Returns +true+ if for some index +i+ in +self+, <tt>obj == self[i]</tt>;
- * otherwise +false+:
+ * Returns whether for some element +element+ in +self+,
+ * <tt>object == element</tt>:
*
- * [0, 1, 2].include?(2) # => true
- * [0, 1, 2].include?(3) # => false
+ * [0, 1, 2].include?(2) # => true
+ * [0, 1, 2].include?(2.0) # => true
+ * [0, 1, 2].include?(2.1) # => false
+ *
+ * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
*/
VALUE
@@ -5296,33 +5546,40 @@ recursive_cmp(VALUE ary1, VALUE ary2, int recur)
/*
* call-seq:
- * array <=> other_array -> -1, 0, or 1
- *
- * Returns -1, 0, or 1 as +self+ is less than, equal to, or greater than +other_array+.
- * For each index +i+ in +self+, evaluates <tt>result = self[i] <=> other_array[i]</tt>.
+ * self <=> other_array -> -1, 0, or 1
*
- * Returns -1 if any result is -1:
+ * Returns -1, 0, or 1 as +self+ is determined
+ * to be less than, equal to, or greater than +other_array+.
*
- * [0, 1, 2] <=> [0, 1, 3] # => -1
+ * Iterates over each index +i+ in <tt>(0...self.size)</tt>:
*
- * Returns 1 if any result is 1:
+ * - Computes <tt>result[i]</tt> as <tt>self[i] <=> other_array[i]</tt>.
+ * - Immediately returns 1 if <tt>result[i]</tt> is 1:
*
- * [0, 1, 2] <=> [0, 1, 1] # => 1
+ * [0, 1, 2] <=> [0, 0, 2] # => 1
*
- * When all results are zero:
+ * - Immediately returns -1 if <tt>result[i]</tt> is -1:
*
- * - Returns -1 if +array+ is smaller than +other_array+:
+ * [0, 1, 2] <=> [0, 2, 2] # => -1
*
- * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
+ * - Continues if <tt>result[i]</tt> is 0.
*
- * - Returns 1 if +array+ is larger than +other_array+:
+ * When every +result+ is 0,
+ * returns <tt>self.size <=> other_array.size</tt>
+ * (see Integer#<=>):
*
- * [0, 1, 2] <=> [0, 1] # => 1
+ * [0, 1, 2] <=> [0, 1] # => 1
+ * [0, 1, 2] <=> [0, 1, 2] # => 0
+ * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
*
- * - Returns 0 if +array+ and +other_array+ are the same size:
+ * Note that when +other_array+ is larger than +self+,
+ * its trailing elements do not affect the result:
*
- * [0, 1, 2] <=> [0, 1, 2] # => 0
+ * [0, 1, 2] <=> [0, 1, 2, -3] # => -1
+ * [0, 1, 2] <=> [0, 1, 2, 0] # => -1
+ * [0, 1, 2] <=> [0, 1, 2, 3] # => -1
*
+ * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing].
*/
VALUE
@@ -5392,18 +5649,20 @@ ary_make_hash_by(VALUE ary)
/*
* call-seq:
- * array - other_array -> new_array
+ * self - other_array -> new_array
+ *
+ * Returns a new array containing only those elements of +self+
+ * that are not found in +other_array+;
+ * the order from +self+ is preserved:
*
- * Returns a new +Array+ containing only those elements from +array+
- * that are not found in +Array+ +other_array+;
- * items are compared using <tt>eql?</tt>;
- * the order from +array+ is preserved:
+ * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [1] # => [0, 2, 3]
+ * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [3, 2, 0, :foo] # => [1, 1, 1, 1, 1, 1]
+ * [0, 1, 2] - [:foo] # => [0, 1, 2]
*
- * [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]
+ * Element are compared using method <tt>#eql?</tt>
+ * (as defined in each element of +self+).
*
- * Related: Array#difference.
+ * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
*/
VALUE
@@ -5437,19 +5696,21 @@ rb_ary_diff(VALUE ary1, VALUE ary2)
/*
* call-seq:
- * array.difference(*other_arrays) -> new_array
+ * difference(*other_arrays = []) -> new_array
*
- * Returns a new +Array+ containing only those elements from +self+
- * that are not found in any of the Arrays +other_arrays+;
+ * Returns a new array containing only those elements from +self+
+ * that are not found in any of the given +other_arrays+;
* items are compared using <tt>eql?</tt>; order from +self+ is preserved:
*
* [0, 1, 1, 2, 1, 1, 3, 1, 1].difference([1]) # => [0, 2, 3]
- * [0, 1, 2, 3].difference([3, 0], [1, 3]) # => [2]
- * [0, 1, 2].difference([4]) # => [0, 1, 2]
+ * [0, 1, 2, 3].difference([3, 0], [1, 3]) # => [2]
+ * [0, 1, 2].difference([4]) # => [0, 1, 2]
+ * [0, 1, 2].difference # => [0, 1, 2]
*
- * Returns a copy of +self+ if no arguments given.
+ * Returns a copy of +self+ if no arguments are given.
*
- * Related: Array#-.
+ * Related: Array#-;
+ * see also {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
*/
static VALUE
@@ -5473,7 +5734,7 @@ rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary)
VALUE elt = rb_ary_elt(ary, i);
for (j = 0; j < argc; j++) {
if (is_hash[j]) {
- if (rb_hash_stlike_lookup(argv[j], RARRAY_AREF(ary, i), NULL))
+ if (rb_hash_stlike_lookup(argv[j], elt, NULL))
break;
}
else {
@@ -5491,20 +5752,25 @@ rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * array & other_array -> new_array
+ * self & other_array -> new_array
*
- * Returns a new +Array+ containing each element found in both +array+ and +Array+ +other_array+;
- * duplicates are omitted; items are compared using <tt>eql?</tt>
- * (items must also implement +hash+ correctly):
+ * Returns a new array containing the _intersection_ of +self+ and +other_array+;
+ * that is, containing those elements found in both +self+ and +other_array+:
*
* [0, 1, 2, 3] & [1, 2] # => [1, 2]
- * [0, 1, 0, 1] & [0, 1] # => [0, 1]
*
- * Preserves order from +array+:
+ * Omits duplicates:
+ *
+ * [0, 1, 1, 0] & [0, 1] # => [0, 1]
+ *
+ * Preserves order from +self+:
*
* [0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2]
*
- * Related: Array#intersection.
+ * Identifies common elements using method <tt>#eql?</tt>
+ * (as defined in each element of +self+).
+ *
+ * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
*/
@@ -5544,23 +5810,23 @@ rb_ary_and(VALUE ary1, VALUE ary2)
/*
* call-seq:
- * array.intersection(*other_arrays) -> new_array
+ * intersection(*other_arrays) -> new_array
*
- * Returns a new +Array+ containing each element found both in +self+
- * and in all of the given Arrays +other_arrays+;
- * duplicates are omitted; items are compared using <tt>eql?</tt>
- * (items must also implement +hash+ correctly):
+ * Returns a new array containing each element in +self+ that is +#eql?+
+ * to at least one element in each of the given +other_arrays+;
+ * duplicates are omitted:
*
- * [0, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
* [0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]
*
- * Preserves order from +self+:
+ * Each element must correctly implement method <tt>#hash</tt>.
+ *
+ * Order from +self+ is preserved:
*
* [0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2]
*
- * Returns a copy of +self+ if no arguments given.
+ * Returns a copy of +self+ if no arguments are given.
*
- * Related: Array#&.
+ * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
*/
static VALUE
@@ -5609,9 +5875,9 @@ rb_ary_union_hash(VALUE hash, VALUE ary2)
/*
* call-seq:
- * array | other_array -> new_array
+ * self | other_array -> new_array
*
- * Returns the union of +array+ and +Array+ +other_array+;
+ * Returns the union of +self+ and +other_array+;
* duplicates are removed; order is preserved;
* items are compared using <tt>eql?</tt>:
*
@@ -5619,7 +5885,7 @@ rb_ary_union_hash(VALUE hash, VALUE ary2)
* [0, 1, 1] | [2, 2, 3] # => [0, 1, 2, 3]
* [0, 1, 2] | [3, 2, 1, 0] # => [0, 1, 2, 3]
*
- * Related: Array#union.
+ * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
*/
static VALUE
@@ -5643,18 +5909,25 @@ rb_ary_or(VALUE ary1, VALUE ary2)
/*
* call-seq:
- * array.union(*other_arrays) -> new_array
+ * union(*other_arrays) -> new_array
*
- * Returns a new +Array+ that is the union of +self+ and all given Arrays +other_arrays+;
- * duplicates are removed; order is preserved; items are compared using <tt>eql?</tt>:
+ * Returns a new array that is the union of the elements of +self+
+ * and all given arrays +other_arrays+;
+ * items are compared using <tt>eql?</tt>:
*
* [0, 1, 2, 3].union([4, 5], [6, 7]) # => [0, 1, 2, 3, 4, 5, 6, 7]
+ *
+ * Removes duplicates (preserving the first found):
+ *
* [0, 1, 1].union([2, 1], [3, 1]) # => [0, 1, 2, 3]
- * [0, 1, 2, 3].union([3, 2], [1, 0]) # => [0, 1, 2, 3]
*
- * Returns a copy of +self+ if no arguments given.
+ * Preserves order (preserving the position of the first found):
+ *
+ * [3, 2, 1, 0].union([5, 3], [4, 2]) # => [3, 2, 1, 0, 5, 4]
*
- * Related: Array#|.
+ * With no arguments given, returns a copy of +self+.
+ *
+ * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
*/
static VALUE
@@ -5687,19 +5960,16 @@ rb_ary_union_multi(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * ary.intersect?(other_ary) -> true or false
+ * intersect?(other_array) -> true or false
+ *
+ * Returns whether +other_array+ has at least one element that is +#eql?+ to some element of +self+:
*
- * Returns +true+ if the array and +other_ary+ have at least one element in
- * common, otherwise returns +false+:
+ * [1, 2, 3].intersect?([3, 4, 5]) # => true
+ * [1, 2, 3].intersect?([4, 5, 6]) # => false
*
- * a = [ 1, 2, 3 ]
- * b = [ 3, 4, 5 ]
- * c = [ 5, 6, 7 ]
- * a.intersect?(b) #=> true
- * a.intersect?(c) #=> false
+ * Each element must correctly implement method <tt>#hash</tt>.
*
- * +Array+ elements are compared using <tt>eql?</tt>
- * (items must also implement +hash+ correctly).
+ * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
*/
static VALUE
@@ -5833,42 +6103,51 @@ ary_max_opt_string(VALUE ary, long i, VALUE vmax)
/*
* call-seq:
- * array.max -> element
- * array.max {|a, b| ... } -> element
- * array.max(n) -> new_array
- * array.max(n) {|a, b| ... } -> new_array
+ * max -> element
+ * max(count) -> new_array
+ * max {|a, b| ... } -> element
+ * max(count) {|a, b| ... } -> new_array
*
* Returns one of the following:
*
* - The maximum-valued element from +self+.
- * - A new +Array+ of maximum-valued elements selected from +self+.
+ * - A new array of maximum-valued elements from +self+.
*
- * When no block is given, each element in +self+ must respond to method <tt><=></tt>
- * with an Integer.
+ * Does not modify +self+.
+ *
+ * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
+ * with a numeric.
*
* With no argument and no block, returns the element in +self+
- * having the maximum value per method <tt><=></tt>:
+ * having the maximum value per method <tt>#<=></tt>:
*
- * [0, 1, 2].max # => 2
+ * [1, 0, 3, 2].max # => 3
*
- * With an argument Integer +n+ and no block, returns a new +Array+ with at most +n+ elements,
- * in descending order per method <tt><=></tt>:
+ * With non-negative numeric argument +count+ and no block,
+ * returns a new array with at most +count+ elements,
+ * in descending order, per method <tt>#<=></tt>:
*
- * [0, 1, 2, 3].max(3) # => [3, 2, 1]
- * [0, 1, 2, 3].max(6) # => [3, 2, 1, 0]
+ * [1, 0, 3, 2].max(3) # => [3, 2, 1]
+ * [1, 0, 3, 2].max(3.0) # => [3, 2, 1]
+ * [1, 0, 3, 2].max(9) # => [3, 2, 1, 0]
+ * [1, 0, 3, 2].max(0) # => []
*
- * When a block is given, the block must return an Integer.
+ * With a block given, the block must return a numeric.
*
- * With a block and no argument, calls the block <tt>self.size-1</tt> times to compare elements;
+ * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
* returns the element having the maximum value per the block:
*
- * ['0', '00', '000'].max {|a, b| a.size <=> b.size } # => "000"
+ * ['0', '', '000', '00'].max {|a, b| a.size <=> b.size }
+ * # => "000"
*
- * With an argument +n+ and a block, returns a new +Array+ with at most +n+ elements,
- * in descending order per the block:
+ * With non-negative numeric argument +count+ and a block,
+ * returns a new array with at most +count+ elements,
+ * in descending order, per the block:
*
- * ['0', '00', '000'].max(2) {|a, b| a.size <=> b.size } # => ["000", "00"]
+ * ['0', '', '000', '00'].max(2) {|a, b| a.size <=> b.size }
+ * # => ["000", "00"]
*
+ * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
*/
static VALUE
rb_ary_max(int argc, VALUE *argv, VALUE ary)
@@ -6001,42 +6280,51 @@ ary_min_opt_string(VALUE ary, long i, VALUE vmin)
/*
* call-seq:
- * array.min -> element
- * array.min { |a, b| ... } -> element
- * array.min(n) -> new_array
- * array.min(n) { |a, b| ... } -> new_array
+ * min -> element
+ * min(count) -> new_array
+ * min {|a, b| ... } -> element
+ * min(count) {|a, b| ... } -> new_array
*
* Returns one of the following:
*
* - The minimum-valued element from +self+.
- * - A new +Array+ of minimum-valued elements selected from +self+.
+ * - A new array of minimum-valued elements from +self+.
+ *
+ * Does not modify +self+.
*
- * When no block is given, each element in +self+ must respond to method <tt><=></tt>
- * with an Integer.
+ * With no block given, each element in +self+ must respond to method <tt>#<=></tt>
+ * with a numeric.
*
* With no argument and no block, returns the element in +self+
- * having the minimum value per method <tt><=></tt>:
+ * having the minimum value per method <tt>#<=></tt>:
*
- * [0, 1, 2].min # => 0
+ * [1, 0, 3, 2].min # => 0
*
- * With Integer argument +n+ and no block, returns a new +Array+ with at most +n+ elements,
- * in ascending order per method <tt><=></tt>:
+ * With non-negative numeric argument +count+ and no block,
+ * returns a new array with at most +count+ elements,
+ * in ascending order, per method <tt>#<=></tt>:
*
- * [0, 1, 2, 3].min(3) # => [0, 1, 2]
- * [0, 1, 2, 3].min(6) # => [0, 1, 2, 3]
+ * [1, 0, 3, 2].min(3) # => [0, 1, 2]
+ * [1, 0, 3, 2].min(3.0) # => [0, 1, 2]
+ * [1, 0, 3, 2].min(9) # => [0, 1, 2, 3]
+ * [1, 0, 3, 2].min(0) # => []
*
- * When a block is given, the block must return an Integer.
+ * With a block given, the block must return a numeric.
*
- * With a block and no argument, calls the block <tt>self.size-1</tt> times to compare elements;
+ * With a block and no argument, calls the block <tt>self.size - 1</tt> times to compare elements;
* returns the element having the minimum value per the block:
*
- * ['0', '00', '000'].min { |a, b| a.size <=> b.size } # => "0"
+ * ['0', '', '000', '00'].min {|a, b| a.size <=> b.size }
+ * # => ""
*
- * With an argument +n+ and a block, returns a new +Array+ with at most +n+ elements,
- * in ascending order per the block:
+ * With non-negative numeric argument +count+ and a block,
+ * returns a new array with at most +count+ elements,
+ * in ascending order, per the block:
*
- * ['0', '00', '000'].min(2) {|a, b| a.size <=> b.size } # => ["0", "00"]
+ * ['0', '', '000', '00'].min(2) {|a, b| a.size <=> b.size }
+ * # => ["", "0"]
*
+ * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
*/
static VALUE
rb_ary_min(int argc, VALUE *argv, VALUE ary)
@@ -6080,26 +6368,25 @@ rb_ary_min(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * array.minmax -> [min_val, max_val]
- * array.minmax {|a, b| ... } -> [min_val, max_val]
+ * minmax -> array
+ * minmax {|a, b| ... } -> array
*
- * Returns a new 2-element +Array+ containing the minimum and maximum values
- * from +self+, either per method <tt><=></tt> or per a given block:.
+ * Returns a 2-element array containing the minimum-valued and maximum-valued
+ * elements from +self+;
+ * does not modify +self+.
*
- * When no block is given, each element in +self+ must respond to method <tt><=></tt>
- * with an Integer;
- * returns a new 2-element +Array+ containing the minimum and maximum values
- * from +self+, per method <tt><=></tt>:
+ * With no block given, the minimum and maximum values are determined using method <tt>#<=></tt>:
*
- * [0, 1, 2].minmax # => [0, 2]
+ * [1, 0, 3, 2].minmax # => [0, 3]
*
- * When a block is given, the block must return an Integer;
- * the block is called <tt>self.size-1</tt> times to compare elements;
- * returns a new 2-element +Array+ containing the minimum and maximum values
- * from +self+, per the block:
+ * With a block given, the block must return a numeric;
+ * the block is called <tt>self.size - 1</tt> times to compare elements;
+ * returns the elements having the minimum and maximum values per the block:
*
- * ['0', '00', '000'].minmax {|a, b| a.size <=> b.size } # => ["0", "000"]
+ * ['0', '', '000', '00'].minmax {|a, b| a.size <=> b.size }
+ * # => ["", "000"]
*
+ * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
*/
static VALUE
rb_ary_minmax(VALUE ary)
@@ -6119,32 +6406,30 @@ push_value(st_data_t key, st_data_t val, st_data_t ary)
/*
* call-seq:
- * array.uniq! -> self or nil
- * array.uniq! {|element| ... } -> self or nil
+ * uniq! -> self or nil
+ * uniq! {|element| ... } -> self or nil
*
* Removes duplicate elements from +self+, the first occurrence always being retained;
* returns +self+ if any elements removed, +nil+ otherwise.
*
* With no block given, identifies and removes elements using method <tt>eql?</tt>
- * to compare.
- *
- * Returns +self+ if any elements removed:
+ * to compare elements:
*
* a = [0, 0, 1, 1, 2, 2]
* a.uniq! # => [0, 1, 2]
- *
- * Returns +nil+ if no elements removed.
+ * a.uniq! # => nil
*
* With a block given, calls the block for each element;
- * identifies (using method <tt>eql?</tt>) and removes
- * elements for which the block returns duplicate values.
- *
- * Returns +self+ if any elements removed:
+ * identifies and omits "duplicate" elements using method <tt>eql?</tt>
+ * to compare <i>block return values</i>;
+ * that is, an element is a duplicate if its block return value
+ * is the same as that of a previous element:
*
* a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
- * a.uniq! {|element| element.size } # => ['a', 'aa', 'aaa']
+ * a.uniq! {|element| element.size } # => ["a", "aa", "aaa"]
+ * a.uniq! {|element| element.size } # => nil
*
- * Returns +nil+ if no elements removed.
+ * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
*/
static VALUE
rb_ary_uniq_bang(VALUE ary)
@@ -6166,7 +6451,7 @@ rb_ary_uniq_bang(VALUE ary)
}
rb_ary_modify_check(ary);
ARY_SET_LEN(ary, 0);
- if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) {
+ if (ARY_SHARED_P(ary)) {
rb_ary_unshare(ary);
FL_SET_EMBED(ary);
}
@@ -6178,25 +6463,28 @@ rb_ary_uniq_bang(VALUE ary)
/*
* call-seq:
- * array.uniq -> new_array
- * array.uniq {|element| ... } -> new_array
+ * uniq -> new_array
+ * uniq {|element| ... } -> new_array
*
- * Returns a new +Array+ containing those elements from +self+ that are not duplicates,
+ * Returns a new array containing those elements from +self+ that are not duplicates,
* the first occurrence always being retained.
*
- * With no block given, identifies and omits duplicates using method <tt>eql?</tt>
- * to compare:
+ * With no block given, identifies and omits duplicate elements using method <tt>eql?</tt>
+ * to compare elements:
*
* a = [0, 0, 1, 1, 2, 2]
* a.uniq # => [0, 1, 2]
*
* With a block given, calls the block for each element;
- * identifies (using method <tt>eql?</tt>) and omits duplicate values,
- * that is, those elements for which the block returns the same value:
+ * identifies and omits "duplicate" elements using method <tt>eql?</tt>
+ * to compare <i>block return values</i>;
+ * that is, an element is a duplicate if its block return value
+ * is the same as that of a previous element:
*
* a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
* a.uniq {|element| element.size } # => ["a", "aa", "aaa"]
*
+ * Related: {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
*/
static VALUE
@@ -6222,11 +6510,18 @@ rb_ary_uniq(VALUE ary)
/*
* call-seq:
- * array.compact! -> self or nil
+ * compact! -> self or nil
*
- * Removes all +nil+ elements from +self+.
+ * Removes all +nil+ elements from +self+;
+ * Returns +self+ if any elements are removed, +nil+ otherwise:
*
- * Returns +self+ if any elements removed, otherwise +nil+.
+ * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
+ * a.compact! # => [0, false, "", [], {}]
+ * a # => [0, false, "", [], {}]
+ * a.compact! # => nil
+ *
+ * Related: Array#compact;
+ * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
*/
static VALUE
@@ -6254,12 +6549,16 @@ rb_ary_compact_bang(VALUE ary)
/*
* call-seq:
- * array.compact -> new_array
+ * compact -> new_array
+ *
+ * Returns a new array containing only the non-+nil+ elements from +self+;
+ * element order is preserved:
*
- * Returns a new +Array+ containing all non-+nil+ elements from +self+:
+ * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
+ * a.compact # => [0, false, "", [], {}]
*
- * a = [nil, 0, nil, 1, nil, 2, nil]
- * a.compact # => [0, 1, 2]
+ * Related: Array#compact!;
+ * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting].
*/
static VALUE
@@ -6272,29 +6571,29 @@ rb_ary_compact(VALUE ary)
/*
* call-seq:
- * array.count -> an_integer
- * array.count(obj) -> an_integer
- * array.count {|element| ... } -> an_integer
+ * count -> integer
+ * count(object) -> integer
+ * count {|element| ... } -> integer
*
* Returns a count of specified elements.
*
* With no argument and no block, returns the count of all elements:
*
- * [0, 1, 2].count # => 3
- * [].count # => 0
+ * [0, :one, 'two', 3, 3.0].count # => 5
*
- * With argument +obj+, returns the count of elements <tt>==</tt> to +obj+:
+ * With argument +object+ given, returns the count of elements <tt>==</tt> to +object+:
*
- * [0, 1, 2, 0.0].count(0) # => 2
- * [0, 1, 2].count(3) # => 0
+ * [0, :one, 'two', 3, 3.0].count(3) # => 2
*
* With no argument and a block given, calls the block with each element;
* returns the count of elements for which the block returns a truthy value:
*
- * [0, 1, 2, 3].count {|element| element > 1} # => 2
+ * [0, 1, 2, 3].count {|element| element > 1 } # => 2
*
- * With argument +obj+ and a block given, issues a warning, ignores the block,
- * and returns the count of elements <tt>==</tt> to +obj+.
+ * With argument +object+ and a block given, issues a warning, ignores the block,
+ * and returns the count of elements <tt>==</tt> to +object+.
+ *
+ * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
*/
static VALUE
@@ -6414,33 +6713,37 @@ flatten(VALUE ary, int level)
/*
* call-seq:
- * array.flatten! -> self or nil
- * array.flatten!(level) -> self or nil
+ * flatten!(depth = nil) -> self or nil
+ *
+ * Returns +self+ as a recursively flattening of +self+ to +depth+ levels of recursion;
+ * +depth+ must be an
+ * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
+ * or +nil+.
+ * At each level of recursion:
+ *
+ * - Each element that is an array is "flattened"
+ * (that is, replaced by its individual array elements).
+ * - Each element that is not an array is unchanged
+ * (even if the element is an object that has instance method +flatten+).
*
- * Replaces each nested +Array+ in +self+ with the elements from that +Array+;
- * returns +self+ if any changes, +nil+ otherwise.
+ * Returns +nil+ if no elements were flattened.
*
- * With non-negative Integer argument +level+, flattens recursively through +level+ levels:
+ * With non-negative integer argument +depth+, flattens recursively through +depth+ 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
+ * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
+ * a # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
+ * a.dup.flatten!(1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
+ * a.dup.flatten!(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
+ * a.dup.flatten!(2) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
+ * a.dup.flatten!(3) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
*
- * With no argument, a +nil+ argument, or with negative argument +level+, flattens all levels:
+ * With +nil+ or negative argument +depth+, 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
+ * a.dup.flatten! # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
+ * a.dup.flatten!(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
*
+ * Related: Array#flatten;
+ * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
*/
static VALUE
@@ -6458,7 +6761,7 @@ rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
if (result == ary) {
return Qnil;
}
- if (!(mod = ARY_EMBED_P(result))) rb_obj_freeze(result);
+ if (!(mod = ARY_EMBED_P(result))) rb_ary_freeze(result);
rb_ary_replace(ary, result);
if (mod) ARY_SET_EMBED_LEN(result, 0);
@@ -6467,35 +6770,37 @@ rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * array.flatten -> new_array
- * array.flatten(level) -> new_array
- *
- * Returns a new +Array+ that is a recursive flattening of +self+:
- * - Each non-Array element is unchanged.
- * - Each +Array+ is replaced by its individual elements.
- *
- * With non-negative Integer argument +level+, flattens recursively through +level+ levels:
- *
- * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
- * a.flatten(0) # => [0, [1, [2, 3], 4], 5]
- * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
- * a.flatten(1) # => [0, 1, [2, 3], 4, 5]
- * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
- * a.flatten(2) # => [0, 1, 2, 3, 4, 5]
- * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
- * a.flatten(3) # => [0, 1, 2, 3, 4, 5]
- *
- * With no argument, a +nil+ argument, or with negative argument +level+, flattens all levels:
- *
- * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
- * a.flatten # => [0, 1, 2, 3, 4, 5]
- * [0, 1, 2].flatten # => [0, 1, 2]
- * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
- * a.flatten(-1) # => [0, 1, 2, 3, 4, 5]
- * a = [ 0, [ 1, [2, 3], 4 ], 5 ]
- * a.flatten(-2) # => [0, 1, 2, 3, 4, 5]
- * [0, 1, 2].flatten(-1) # => [0, 1, 2]
+ * flatten(depth = nil) -> new_array
+ *
+ * Returns a new array that is a recursive flattening of +self+
+ * to +depth+ levels of recursion;
+ * +depth+ must be an
+ * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
+ * or +nil+.
+ * At each level of recursion:
+ *
+ * - Each element that is an array is "flattened"
+ * (that is, replaced by its individual array elements).
+ * - Each element that is not an array is unchanged
+ * (even if the element is an object that has instance method +flatten+).
+ *
+ * With non-negative integer argument +depth+, flattens recursively through +depth+ levels:
+ *
+ * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
+ * a # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
+ * a.flatten(0) # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
+ * a.flatten(1 ) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
+ * a.flatten(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
+ * a.flatten(2) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
+ * a.flatten(3) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
+ *
+ * With +nil+ or negative +depth+, flattens all levels.
+ *
+ * a.flatten # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
+ * a.flatten(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
*
+ * Related: Array#flatten!;
+ * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting].
*/
static VALUE
@@ -6527,7 +6832,7 @@ rb_ary_shuffle_bang(rb_execution_context_t *ec, VALUE ary, VALUE randgen)
rb_ary_modify(ary);
i = len = RARRAY_LEN(ary);
RARRAY_PTR_USE(ary, ptr, {
- while (i) {
+ while (i > 1) {
long j = RAND_UPTO(i);
VALUE tmp;
if (len != RARRAY_LEN(ary) || ptr != RARRAY_CONST_PTR(ary)) {
@@ -6687,6 +6992,12 @@ ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE
}
static VALUE
+ary_sized_alloc(rb_execution_context_t *ec, VALUE self)
+{
+ return rb_ary_new2(RARRAY_LEN(self));
+}
+
+static VALUE
ary_sample0(rb_execution_context_t *ec, VALUE ary)
{
return ary_sample(ec, ary, rb_cRandom, Qfalse, Qfalse);
@@ -6710,36 +7021,36 @@ rb_ary_cycle_size(VALUE self, VALUE args, VALUE eobj)
/*
* call-seq:
- * array.cycle {|element| ... } -> nil
- * array.cycle(count) {|element| ... } -> nil
- * array.cycle -> new_enumerator
- * array.cycle(count) -> new_enumerator
+ * cycle(count = nil) {|element| ... } -> nil
+ * cycle(count = nil) -> new_enumerator
+ *
+ * With a block given, may call the block, depending on the value of argument +count+;
+ * +count+ must be an
+ * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects],
+ * or +nil+.
*
- * When called with positive Integer argument +count+ and a block,
- * calls the block with each element, then does so again,
+ * When +count+ is positive,
+ * calls the block with each element, then does so repeatedly,
* until it has done so +count+ times; returns +nil+:
*
* output = []
* [0, 1].cycle(2) {|element| output.push(element) } # => nil
* output # => [0, 1, 0, 1]
*
- * If +count+ is zero or negative, does not call the block:
+ * When +count+ is zero or negative, does not call the block:
*
- * [0, 1].cycle(0) {|element| fail 'Cannot happen' } # => nil
+ * [0, 1].cycle(0) {|element| fail 'Cannot happen' } # => nil
* [0, 1].cycle(-1) {|element| fail 'Cannot happen' } # => nil
*
- * When a block is given, and argument is omitted or +nil+, cycles forever:
+ * When +count+ is +nil+, cycles forever:
*
* # Prints 0 and 1 forever.
* [0, 1].cycle {|element| puts element }
* [0, 1].cycle(nil) {|element| puts element }
*
- * When no block is given, returns a new Enumerator:
- *
- * [0, 1].cycle(2) # => #<Enumerator: [0, 1]:cycle(2)>
- * [0, 1].cycle # => # => #<Enumerator: [0, 1]:cycle>
- * [0, 1].cycle.first(5) # => [0, 1, 0, 1, 0]
+ * With no block given, returns a new Enumerator.
*
+ * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
*/
static VALUE
rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
@@ -6883,82 +7194,44 @@ rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj)
/*
* call-seq:
- * array.permutation {|element| ... } -> self
- * array.permutation(n) {|element| ... } -> self
- * array.permutation -> new_enumerator
- * array.permutation(n) -> new_enumerator
- *
- * When invoked with a block, yield all permutations of elements of +self+; returns +self+.
- * The order of permutations is indeterminate.
+ * permutation(count = self.size) {|permutation| ... } -> self
+ * permutation(count = self.size) -> new_enumerator
*
- * When a block and an in-range positive Integer argument +n+ (<tt>0 < n <= self.size</tt>)
- * are given, calls the block with all +n+-tuple permutations of +self+.
+ * Iterates over permutations of the elements of +self+;
+ * the order of permutations is indeterminate.
*
- * Example:
- *
- * a = [0, 1, 2]
- * a.permutation(2) {|permutation| p permutation }
- *
- * Output:
- *
- * [0, 1]
- * [0, 2]
- * [1, 0]
- * [1, 2]
- * [2, 0]
- * [2, 1]
- *
- * Another example:
+ * With a block and an in-range positive integer argument +count+ (<tt>0 < count <= self.size</tt>) given,
+ * calls the block with each permutation of +self+ of size +count+;
+ * returns +self+:
*
* a = [0, 1, 2]
- * a.permutation(3) {|permutation| p permutation }
+ * perms = []
+ * a.permutation(1) {|perm| perms.push(perm) }
+ * perms # => [[0], [1], [2]]
*
- * Output:
- *
- * [0, 1, 2]
- * [0, 2, 1]
- * [1, 0, 2]
- * [1, 2, 0]
- * [2, 0, 1]
- * [2, 1, 0]
+ * perms = []
+ * a.permutation(2) {|perm| perms.push(perm) }
+ * perms # => [[0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1]]
*
- * When +n+ is zero, calls the block once with a new empty +Array+:
+ * perms = []
+ * a.permutation(3) {|perm| perms.push(perm) }
+ * perms # => [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
*
- * a = [0, 1, 2]
- * a.permutation(0) {|permutation| p permutation }
+ * When +count+ is zero, calls the block once with a new empty array:
*
- * Output:
+ * perms = []
+ * a.permutation(0) {|perm| perms.push(perm) }
+ * perms # => [[]]
*
- * []
- *
- * When +n+ is out of range (negative or larger than <tt>self.size</tt>),
+ * When +count+ is out of range (negative or larger than <tt>self.size</tt>),
* 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 <tt>a.permutation(a.size)</tt>:
- *
- * 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 # => #<Enumerator: [0, 1, 2]:permutation>
- * a.permutation(2) # => #<Enumerator: [0, 1, 2]:permutation(2)>
+ * With no block given, returns a new Enumerator.
*
+ * Related: {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
*/
static VALUE
@@ -7031,56 +7304,46 @@ rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj)
/*
* call-seq:
- * array.combination(n) {|element| ... } -> self
- * array.combination(n) -> new_enumerator
- *
- * Calls the block, if given, with combinations of elements of +self+;
- * returns +self+. The order of combinations is indeterminate.
+ * combination(count) {|element| ... } -> self
+ * combination(count) -> new_enumerator
*
- * When a block and an in-range positive Integer argument +n+ (<tt>0 < n <= self.size</tt>)
- * are given, calls the block with all +n+-tuple combinations of +self+.
- *
- * Example:
+ * When a block and a positive
+ * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]
+ * argument +count+ (<tt>0 < count <= self.size</tt>)
+ * are given, calls the block with each combination of +self+ of size +count+;
+ * returns +self+:
*
- * a = [0, 1, 2]
- * a.combination(2) {|combination| p combination }
+ * a = %w[a b c] # => ["a", "b", "c"]
+ * a.combination(2) {|combination| p combination } # => ["a", "b", "c"]
*
* Output:
*
- * [0, 1]
- * [0, 2]
- * [1, 2]
- *
- * Another example:
- *
- * a = [0, 1, 2]
- * a.combination(3) {|combination| p combination }
+ * ["a", "b"]
+ * ["a", "c"]
+ * ["b", "c"]
*
- * Output:
+ * The order of the yielded combinations is not guaranteed.
*
- * [0, 1, 2]
+ * When +count+ is zero, calls the block once with a new empty array:
*
- * When +n+ is zero, calls the block once with a new empty +Array+:
- *
- * a = [0, 1, 2]
- * a1 = a.combination(0) {|combination| p combination }
+ * a.combination(0) {|combination| p combination }
+ * [].combination(0) {|combination| p combination }
*
* Output:
*
* []
+ * []
*
- * When +n+ is out of range (negative or larger than <tt>self.size</tt>),
+ * When +count+ is negative or larger than +self.size+ and +self+ is non-empty,
* does not call the block:
*
- * a = [0, 1, 2]
- * a.combination(-1) {|combination| fail 'Cannot happen' }
- * a.combination(4) {|combination| fail 'Cannot happen' }
- *
- * Returns a new Enumerator if no block given:
+ * a.combination(-1) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
+ * a.combination(4) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
*
- * a = [0, 1, 2]
- * a.combination(2) # => #<Enumerator: [0, 1, 2]:combination(2)>
+ * With no block given, returns a new Enumerator.
*
+ * Related: Array#permutation;
+ * see also {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating].
*/
static VALUE
@@ -7167,68 +7430,41 @@ rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj)
/*
* call-seq:
- * array.repeated_permutation(n) {|permutation| ... } -> self
- * array.repeated_permutation(n) -> new_enumerator
+ * repeated_permutation(size) {|permutation| ... } -> self
+ * repeated_permutation(size) -> new_enumerator
*
- * Calls the block with each repeated permutation of length +n+ of the elements of +self+;
- * each permutation is an +Array+;
+ * With a block given, calls the block with each repeated permutation of length +size+
+ * of the elements of +self+;
+ * each permutation is an array;
* returns +self+. The order of the permutations is indeterminate.
*
- * When a block and a positive Integer argument +n+ are given, calls the block with each
- * +n+-tuple repeated permutation of the elements of +self+.
- * The number of permutations is <tt>self.size**n</tt>.
+ * If a positive integer argument +size+ is given,
+ * calls the block with each +size+-tuple repeated permutation of the elements of +self+.
+ * The number of permutations is <tt>self.size**size</tt>.
*
- * +n+ = 1:
- *
- * a = [0, 1, 2]
- * a.repeated_permutation(1) {|permutation| p permutation }
- *
- * Output:
- *
- * [0]
- * [1]
- * [2]
- *
- * +n+ = 2:
- *
- * a.repeated_permutation(2) {|permutation| p permutation }
- *
- * Output:
+ * Examples:
*
- * [0, 0]
- * [0, 1]
- * [0, 2]
- * [1, 0]
- * [1, 1]
- * [1, 2]
- * [2, 0]
- * [2, 1]
- * [2, 2]
+ * - +size+ is 1:
*
- * If +n+ is zero, calls the block once with an empty +Array+.
+ * p = []
+ * [0, 1, 2].repeated_permutation(1) {|permutation| p.push(permutation) }
+ * p # => [[0], [1], [2]]
*
- * If +n+ is negative, does not call the block:
+ * - +size+ is 2:
*
- * a.repeated_permutation(-1) {|permutation| fail 'Cannot happen' }
+ * p = []
+ * [0, 1, 2].repeated_permutation(2) {|permutation| p.push(permutation) }
+ * p # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
*
- * Returns a new Enumerator if no block given:
+ * If +size+ is zero, calls the block once with an empty array.
*
- * a = [0, 1, 2]
- * a.repeated_permutation(2) # => #<Enumerator: [0, 1, 2]:permutation(2)>
+ * If +size+ is negative, does not call the block:
*
- * Using Enumerators, it's convenient to show the permutations and counts
- * for some values of +n+:
+ * [0, 1, 2].repeated_permutation(-1) {|permutation| fail 'Cannot happen' }
*
- * e = a.repeated_permutation(0)
- * e.size # => 1
- * e.to_a # => [[]]
- * e = a.repeated_permutation(1)
- * e.size # => 3
- * e.to_a # => [[0], [1], [2]]
- * e = a.repeated_permutation(2)
- * e.size # => 9
- * e.to_a # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
+ * With no block given, returns a new Enumerator.
*
+ * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
*/
static VALUE
rb_ary_repeated_permutation(VALUE ary, VALUE num)
@@ -7299,65 +7535,41 @@ rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj)
/*
* call-seq:
- * array.repeated_combination(n) {|combination| ... } -> self
- * array.repeated_combination(n) -> new_enumerator
+ * repeated_combination(size) {|combination| ... } -> self
+ * repeated_combination(size) -> new_enumerator
*
- * Calls the block with each repeated combination of length +n+ of the elements of +self+;
- * each combination is an +Array+;
+ * With a block given, calls the block with each repeated combination of length +size+
+ * of the elements of +self+;
+ * each combination is an array;
* returns +self+. The order of the combinations is indeterminate.
*
- * When a block and a positive Integer argument +n+ are given, calls the block with each
- * +n+-tuple repeated combination of the elements of +self+.
- * The number of combinations is <tt>(n+1)(n+2)/2</tt>.
+ * If a positive integer argument +size+ is given,
+ * calls the block with each +size+-tuple repeated combination of the elements of +self+.
+ * The number of combinations is <tt>(size+1)(size+2)/2</tt>.
*
- * +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:
+ * Examples:
*
- * [0, 0]
- * [0, 1]
- * [0, 2]
- * [1, 1]
- * [1, 2]
- * [2, 2]
+ * - +size+ is 1:
*
- * If +n+ is zero, calls the block once with an empty +Array+.
+ * c = []
+ * [0, 1, 2].repeated_combination(1) {|combination| c.push(combination) }
+ * c # => [[0], [1], [2]]
*
- * If +n+ is negative, does not call the block:
+ * - +size+ is 2:
*
- * a.repeated_combination(-1) {|combination| fail 'Cannot happen' }
+ * c = []
+ * [0, 1, 2].repeated_combination(2) {|combination| c.push(combination) }
+ * c # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
*
- * Returns a new Enumerator if no block given:
+ * If +size+ is zero, calls the block once with an empty array.
*
- * a = [0, 1, 2]
- * a.repeated_combination(2) # => #<Enumerator: [0, 1, 2]:combination(2)>
+ * If +size+ is negative, does not call the block:
*
- * Using Enumerators, it's convenient to show the combinations and counts
- * for some values of +n+:
+ * [0, 1, 2].repeated_combination(-1) {|combination| fail 'Cannot happen' }
*
- * e = a.repeated_combination(0)
- * e.size # => 1
- * e.to_a # => [[]]
- * e = a.repeated_combination(1)
- * e.size # => 3
- * e.to_a # => [[0], [1], [2]]
- * e = a.repeated_combination(2)
- * e.size # => 6
- * e.to_a # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
+ * With no block given, returns a new Enumerator.
*
+ * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
*/
static VALUE
@@ -7397,62 +7609,55 @@ rb_ary_repeated_combination(VALUE ary, VALUE num)
/*
* call-seq:
- * array.product(*other_arrays) -> new_array
- * array.product(*other_arrays) {|combination| ... } -> self
+ * product(*other_arrays) -> new_array
+ * product(*other_arrays) {|combination| ... } -> self
*
- * Computes and returns or yields all combinations of elements from all the Arrays,
+ * Computes all combinations of elements from all the arrays,
* including both +self+ and +other_arrays+:
*
* - The number of combinations is the product of the sizes of all the arrays,
* including both +self+ and +other_arrays+.
* - The order of the returned combinations is indeterminate.
*
- * When no block is given, returns the combinations as an +Array+ of Arrays:
+ * With no block given, returns the combinations as an array of arrays:
*
- * a = [0, 1, 2]
- * a1 = [3, 4]
- * a2 = [5, 6]
- * p = a.product(a1)
- * p.size # => 6 # a.size * a1.size
- * p # => [[0, 3], [0, 4], [1, 3], [1, 4], [2, 3], [2, 4]]
- * p = a.product(a1, a2)
- * p.size # => 12 # a.size * a1.size * a2.size
- * p # => [[0, 3, 5], [0, 3, 6], [0, 4, 5], [0, 4, 6], [1, 3, 5], [1, 3, 6], [1, 4, 5], [1, 4, 6], [2, 3, 5], [2, 3, 6], [2, 4, 5], [2, 4, 6]]
- *
- * If any argument is an empty +Array+, returns an empty +Array+.
- *
- * If no argument is given, returns an +Array+ of 1-element Arrays,
- * each containing an element of +self+:
+ * p = [0, 1].product([2, 3])
+ * # => [[0, 2], [0, 3], [1, 2], [1, 3]]
+ * p.size # => 4
+ * p = [0, 1].product([2, 3], [4, 5])
+ * # => [[0, 2, 4], [0, 2, 5], [0, 3, 4], [0, 3, 5], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3,...
+ * p.size # => 8
*
- * a.product # => [[0], [1], [2]]
+ * If +self+ or any argument is empty, returns an empty array:
*
- * When a block is given, yields each combination as an +Array+; returns +self+:
+ * [].product([2, 3], [4, 5]) # => []
+ * [0, 1].product([2, 3], []) # => []
*
- * a.product(a1) {|combination| p combination }
- *
- * Output:
+ * If no argument is given, returns an array of 1-element arrays,
+ * each containing an element of +self+:
*
- * [0, 3]
- * [0, 4]
- * [1, 3]
- * [1, 4]
- * [2, 3]
- * [2, 4]
+ * a.product # => [[0], [1], [2]]
*
- * If any argument is an empty +Array+, does not call the block:
+ * With a block given, calls the block with each combination; returns +self+:
*
- * a.product(a1, a2, []) {|combination| fail 'Cannot happen' }
+ * p = []
+ * [0, 1].product([2, 3]) {|combination| p.push(combination) }
+ * p # => [[0, 2], [0, 3], [1, 2], [1, 3]]
*
- * If no argument is given, yields each element of +self+ as a 1-element +Array+:
+ * If +self+ or any argument is empty, does not call the block:
*
- * a.product {|combination| p combination }
+ * [].product([2, 3], [4, 5]) {|combination| fail 'Cannot happen' }
+ * # => []
+ * [0, 1].product([2, 3], []) {|combination| fail 'Cannot happen' }
+ * # => [0, 1]
*
- * Output:
+ * If no argument is given, calls the block with each element of +self+ as a 1-element array:
*
- * [0]
- * [1]
- * [2]
+ * p = []
+ * [0, 1].product {|combination| p.push(combination) }
+ * p # => [[0], [1]]
*
+ * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining].
*/
static VALUE
@@ -7545,20 +7750,20 @@ done:
/*
* call-seq:
- * array.take(n) -> new_array
+ * take(count) -> new_array
*
- * Returns a new +Array+ containing the first +n+ element of +self+,
- * where +n+ is a non-negative Integer;
- * does not modify +self+.
+ * Returns a new array containing the first +count+ element of +self+
+ * (as available);
+ * +count+ must be a non-negative numeric;
+ * 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]
+ * a = ['a', 'b', 'c', 'd']
+ * a.take(2) # => ["a", "b"]
+ * a.take(2.1) # => ["a", "b"]
+ * a.take(50) # => ["a", "b", "c", "d"]
+ * a.take(0) # => []
*
+ * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
*/
static VALUE
@@ -7573,25 +7778,23 @@ rb_ary_take(VALUE obj, VALUE n)
/*
* call-seq:
- * array.take_while {|element| ... } -> new_array
- * array.take_while -> new_enumerator
- *
- * Returns a new +Array+ containing zero or more leading elements of +self+;
- * does not modify +self+.
+ * take_while {|element| ... } -> new_array
+ * take_while -> new_enumerator
*
* With a block given, calls the block with each successive element of +self+;
- * stops if the block returns +false+ or +nil+;
- * returns a new +Array+ containing those elements for which the block returned a truthy value:
+ * stops iterating if the block returns +false+ or +nil+;
+ * returns a new array containing those elements for which the block returned a truthy value:
*
* a = [0, 1, 2, 3, 4, 5]
* a.take_while {|element| element < 3 } # => [0, 1, 2]
- * a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5]
- * a # => [0, 1, 2, 3, 4, 5]
+ * a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5]
+ * a.take_while {|element| false } # => []
*
- * With no block given, returns a new Enumerator:
+ * With no block given, returns a new Enumerator.
*
- * [0, 1].take_while # => #<Enumerator: [0, 1]:take_while>
+ * Does not modify +self+.
*
+ * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
*/
static VALUE
@@ -7608,10 +7811,10 @@ rb_ary_take_while(VALUE ary)
/*
* call-seq:
- * array.drop(n) -> new_array
+ * drop(count) -> new_array
*
- * Returns a new +Array+ containing all but the first +n+ element of +self+,
- * where +n+ is a non-negative Integer;
+ * Returns a new array containing all but the first +count+ element of +self+,
+ * where +count+ is a non-negative integer;
* does not modify +self+.
*
* Examples:
@@ -7620,7 +7823,9 @@ rb_ary_take_while(VALUE ary)
* a.drop(0) # => [0, 1, 2, 3, 4, 5]
* a.drop(1) # => [1, 2, 3, 4, 5]
* a.drop(2) # => [2, 3, 4, 5]
+ * a.drop(9) # => []
*
+ * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
*/
static VALUE
@@ -7639,23 +7844,20 @@ rb_ary_drop(VALUE ary, VALUE n)
/*
* call-seq:
- * array.drop_while {|element| ... } -> new_array
- * array.drop_while -> new_enumerator
-
- * Returns a new +Array+ containing zero or more trailing elements of +self+;
- * does not modify +self+.
+ * drop_while {|element| ... } -> new_array
+ * drop_while -> new_enumerator
*
* With a block given, calls the block with each successive element of +self+;
* stops if the block returns +false+ or +nil+;
- * returns a new +Array+ _omitting_ those elements for which the block returned a truthy value:
+ * returns a new array _omitting_ those elements for which the block returned a truthy value;
+ * does not modify +self+:
*
* a = [0, 1, 2, 3, 4, 5]
* a.drop_while {|element| element < 3 } # => [3, 4, 5]
*
- * With no block given, returns a new Enumerator:
- *
- * [0, 1].drop_while # => # => #<Enumerator: [0, 1]:drop_while>
+ * With no block given, returns a new Enumerator.
*
+ * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
*/
static VALUE
@@ -7672,38 +7874,41 @@ rb_ary_drop_while(VALUE ary)
/*
* call-seq:
- * array.any? -> true or false
- * array.any? {|element| ... } -> true or false
- * array.any?(obj) -> true or false
+ * any? -> true or false
+ * any?(object) -> true or false
+ * any? {|element| ... } -> true or false
*
- * Returns +true+ if any element of +self+ meets a given criterion.
+ * Returns whether for any element of +self+, a given criterion is satisfied.
*
- * If +self+ has no element, returns +false+ and argument or block
- * are not used.
+ * With no block and no argument, returns whether any element of +self+ is truthy:
*
- * With no block given and no argument, returns +true+ if +self+ has any truthy element,
- * +false+ otherwise:
+ * [nil, false, []].any? # => true # Array object is truthy.
+ * [nil, false, {}].any? # => true # Hash object is truthy.
+ * [nil, false, ''].any? # => true # String object is truthy.
+ * [nil, false].any? # => false # Nil and false are not truthy.
*
- * [nil, 0, false].any? # => true
- * [nil, false].any? # => false
- * [].any? # => false
+ * With argument +object+ given,
+ * returns whether <tt>object === ele</tt> for any element +ele+ in +self+:
*
- * With a block given and no argument, calls the block with each element in +self+;
- * returns +true+ if the block returns any truthy value, +false+ otherwise:
+ * [nil, false, 0].any?(0) # => true
+ * [nil, false, 1].any?(0) # => false
+ * [nil, false, 'food'].any?(/foo/) # => true
+ * [nil, false, 'food'].any?(/bar/) # => false
*
- * [0, 1, 2].any? {|element| element > 1 } # => true
- * [0, 1, 2].any? {|element| element > 2 } # => false
+ * With a block given,
+ * calls the block with each element in +self+;
+ * returns whether the block returns any truthy value:
*
- * If argument +obj+ is given, returns +true+ if +obj+.<tt>===</tt> any element,
- * +false+ otherwise:
+ * [0, 1, 2].any? {|ele| ele < 1 } # => true
+ * [0, 1, 2].any? {|ele| ele < 0 } # => false
+ *
+ * With both a block and argument +object+ given,
+ * ignores the block and uses +object+ as above.
*
- * ['food', 'drink'].any?(/foo/) # => true
- * ['food', 'drink'].any?(/bar/) # => false
- * [].any?(/foo/) # => false
- * [0, 1, 2].any?(1) # => true
- * [0, 1, 2].any?(3) # => false
+ * <b>Special case</b>: returns +false+ if +self+ is empty
+ * (regardless of any given argument or block).
*
- * Related: Enumerable#any?
+ * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
*/
static VALUE
@@ -7736,37 +7941,41 @@ rb_ary_any_p(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * array.all? -> true or false
- * array.all? {|element| ... } -> true or false
- * array.all?(obj) -> true or false
+ * all? -> true or false
+ * all?(object) -> true or false
+ * all? {|element| ... } -> true or false
*
- * Returns +true+ if all elements of +self+ meet a given criterion.
+ * Returns whether for every element of +self+,
+ * a given criterion is satisfied.
*
- * If +self+ has no element, returns +true+ and argument or block
- * are not used.
+ * With no block and no argument,
+ * returns whether every element of +self+ is truthy:
*
- * With no block given and no argument, returns +true+ if +self+ contains only truthy elements,
- * +false+ otherwise:
+ * [[], {}, '', 0, 0.0, Object.new].all? # => true # All truthy objects.
+ * [[], {}, '', 0, 0.0, nil].all? # => false # nil is not truthy.
+ * [[], {}, '', 0, 0.0, false].all? # => false # false is not truthy.
+ *
+ * With argument +object+ given, returns whether <tt>object === ele</tt>
+ * for every element +ele+ in +self+:
*
- * [0, 1, :foo].all? # => true
- * [0, nil, 2].all? # => false
- * [].all? # => true
+ * [0, 0, 0].all?(0) # => true
+ * [0, 1, 2].all?(1) # => false
+ * ['food', 'fool', 'foot'].all?(/foo/) # => true
+ * ['food', 'drink'].all?(/foo/) # => false
*
- * 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:
+ * With a block given, calls the block with each element in +self+;
+ * returns whether the block returns only truthy values:
*
- * [0, 1, 2].all? { |element| element < 3 } # => true
- * [0, 1, 2].all? { |element| element < 2 } # => false
+ * [0, 1, 2].all? { |ele| ele < 3 } # => true
+ * [0, 1, 2].all? { |ele| ele < 2 } # => false
*
- * If argument +obj+ is given, returns +true+ if <tt>obj.===</tt> every element, +false+ otherwise:
+ * With both a block and argument +object+ given,
+ * ignores the block and uses +object+ as above.
*
- * ['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
+ * <b>Special case</b>: returns +true+ if +self+ is empty
+ * (regardless of any given argument or block).
*
- * Related: Enumerable#all?
+ * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
*/
static VALUE
@@ -7799,34 +8008,35 @@ rb_ary_all_p(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * array.none? -> true or false
- * array.none? {|element| ... } -> true or false
- * array.none?(obj) -> true or false
+ * none? -> true or false
+ * none?(object) -> true or false
+ * none? {|element| ... } -> true or false
*
- * Returns +true+ if no element of +self+ meet a given criterion.
+ * Returns +true+ if no element of +self+ meets a given criterion, +false+ otherwise.
*
* With no block given and no argument, returns +true+ if +self+ has no truthy elements,
* +false+ otherwise:
*
- * [nil, false].none? # => true
+ * [nil, false].none? # => true
* [nil, 0, false].none? # => false
- * [].none? # => true
+ * [].none? # => true
*
- * With a block given and no argument, calls the block with each element in +self+;
+ * With argument +object+ given, returns +false+ if for any element +element+,
+ * <tt>object === element</tt>; +true+ 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
+ *
+ * With a block given, calls the block with each element in +self+;
* returns +true+ if the block returns no truthy value, +false+ otherwise:
*
* [0, 1, 2].none? {|element| element > 3 } # => true
* [0, 1, 2].none? {|element| element > 1 } # => false
*
- * If argument +obj+ is given, returns +true+ if <tt>obj.===</tt> no element, +false+ otherwise:
- *
- * ['food', 'drink'].none?(/bar/) # => true
- * ['food', 'drink'].none?(/foo/) # => false
- * [].none?(/foo/) # => true
- * [0, 1, 2].none?(3) # => true
- * [0, 1, 2].none?(1) # => false
- *
- * Related: Enumerable#none?
+ * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
*/
static VALUE
@@ -7859,9 +8069,9 @@ rb_ary_none_p(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * array.one? -> true or false
- * array.one? {|element| ... } -> true or false
- * array.one?(obj) -> true or false
+ * one? -> true or false
+ * one? {|element| ... } -> true or false
+ * one?(object) -> true or false
*
* Returns +true+ if exactly one element of +self+ meets a given criterion.
*
@@ -7873,14 +8083,14 @@ rb_ary_none_p(int argc, VALUE *argv, VALUE ary)
* [nil, nil].one? # => false
* [].one? # => false
*
- * With a block given and no argument, calls the block with each element in +self+;
+ * With a block given, calls the block with each element in +self+;
* returns +true+ if the block a truthy value for exactly one element, +false+ otherwise:
*
* [0, 1, 2].one? {|element| element > 0 } # => false
* [0, 1, 2].one? {|element| element > 1 } # => true
* [0, 1, 2].one? {|element| element > 2 } # => false
*
- * If argument +obj+ is given, returns +true+ if <tt>obj.===</tt> exactly one element,
+ * With argument +object+ given, returns +true+ if for exactly one element +element+, <tt>object === element</tt>;
* +false+ otherwise:
*
* [0, 1, 2].one?(0) # => true
@@ -7890,7 +8100,7 @@ rb_ary_none_p(int argc, VALUE *argv, VALUE ary)
* ['food', 'drink'].one?(/foo/) # => true
* [].one?(/foo/) # => false
*
- * Related: Enumerable#one?
+ * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
*/
static VALUE
@@ -7933,11 +8143,11 @@ rb_ary_one_p(int argc, VALUE *argv, VALUE ary)
/*
* call-seq:
- * array.dig(index, *identifiers) -> object
+ * dig(index, *identifiers) -> object
*
- * Finds and returns the object in nested objects
- * that is specified by +index+ and +identifiers+.
- * The nested objects may be instances of various classes.
+ * Finds and returns the object in nested object
+ * specified by +index+ and +identifiers+;
+ * the nested objects may be instances of various classes.
* See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
*
* Examples:
@@ -7948,6 +8158,7 @@ rb_ary_one_p(int argc, VALUE *argv, VALUE ary)
* a.dig(1, 2, 0) # => :bat
* a.dig(1, 2, 3) # => nil
*
+ * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
*/
static VALUE
@@ -7976,40 +8187,41 @@ finish_exact_sum(long n, VALUE r, VALUE v, int z)
/*
* call-seq:
- * array.sum(init = 0) -> object
- * array.sum(init = 0) {|element| ... } -> object
+ * sum(init = 0) -> object
+ * sum(init = 0) {|element| ... } -> object
*
- * When no block is given, returns the object equivalent to:
+ * With no block given, returns the sum of +init+ and all elements of +self+;
+ * for array +array+ and value +init+, equivalent to:
*
* sum = init
* array.each {|element| sum += element }
* sum
*
- * For example, <tt>[e1, e2, e3].sum</tt> returns <tt>init + e1 + e2 + e3</tt>.
+ * For example, <tt>[e0, e1, e2].sum</tt> returns <tt>init + e0 + e1 + e2</tt>.
*
* Examples:
*
- * a = [0, 1, 2, 3]
- * a.sum # => 6
- * a.sum(100) # => 106
+ * [0, 1, 2, 3].sum # => 6
+ * [0, 1, 2, 3].sum(100) # => 106
+ * ['abc', 'def', 'ghi'].sum('jkl') # => "jklabcdefghi"
+ * [[:foo, :bar], ['foo', 'bar']].sum([2, 3])
+ * # => [2, 3, :foo, :bar, "foo", "bar"]
*
- * The elements need not be numeric, but must be <tt>+</tt>-compatible
- * with each other and with +init+:
+ * The +init+ value and elements need not be numeric, but must all be <tt>+</tt>-compatible:
*
- * a = ['abc', 'def', 'ghi']
- * a.sum('jkl') # => "jklabcdefghi"
+ * # Raises TypeError: Array can't be coerced into Integer.
+ * [[:foo, :bar], ['foo', 'bar']].sum(2)
*
- * When a block is given, it is called with each element
- * and the block's return value (instead of the element itself) is used as the addend:
+ * With a block given, calls the block with each element of +self+;
+ * the block's return value (instead of the element itself) is used as the addend:
*
- * a = ['zero', 1, :two]
- * s = a.sum('Coerced and concatenated: ') {|element| element.to_s }
- * s # => "Coerced and concatenated: zero1two"
+ * ['zero', 1, :two].sum('Coerced and concatenated: ') {|element| element.to_s }
+ * # => "Coerced and concatenated: zero1two"
*
* Notes:
*
* - Array#join and Array#flatten may be faster than Array#sum
- * for an +Array+ of Strings or an +Array+ of Arrays.
+ * for an array of strings or an array of arrays.
* - Array#sum method may not respect method redefinition of "+" methods such as Integer#+.
*
*/
@@ -8139,15 +8351,37 @@ rb_ary_deconstruct(VALUE ary)
}
/*
- * An +Array+ is an ordered, integer-indexed collection of objects, called _elements_.
- * Any object (even another array) may be an array element,
- * and an array can contain objects of different types.
+ * An \Array object is an ordered, integer-indexed collection of objects,
+ * called _elements_;
+ * the object represents
+ * an {array data structure}[https://en.wikipedia.org/wiki/Array_(data_structure)].
*
- * == +Array+ Indexes
+ * An element may be any object (even another array);
+ * elements may be any mixture of objects of different types.
*
- * +Array+ indexing starts at 0, as in C or Java.
+ * Important data structures that use arrays include:
*
- * A positive index is an offset from the first element:
+ * - {Coordinate vector}[https://en.wikipedia.org/wiki/Coordinate_vector].
+ * - {Matrix}[https://en.wikipedia.org/wiki/Matrix_(mathematics)].
+ * - {Heap}[https://en.wikipedia.org/wiki/Heap_(data_structure)].
+ * - {Hash table}[https://en.wikipedia.org/wiki/Hash_table].
+ * - {Deque (double-ended queue)}[https://en.wikipedia.org/wiki/Double-ended_queue].
+ * - {Queue}[https://en.wikipedia.org/wiki/Queue_(abstract_data_type)].
+ * - {Stack}[https://en.wikipedia.org/wiki/Stack_(abstract_data_type)].
+ *
+ * There are also array-like data structures:
+ *
+ * - {Associative array}[https://en.wikipedia.org/wiki/Associative_array] (see Hash).
+ * - {Directory}[https://en.wikipedia.org/wiki/Directory_(computing)] (see Dir).
+ * - {Environment}[https://en.wikipedia.org/wiki/Environment_variable] (see ENV).
+ * - {Set}[https://en.wikipedia.org/wiki/Set_(abstract_data_type)] (see Set).
+ * - {String}[https://en.wikipedia.org/wiki/String_(computer_science)] (see String).
+ *
+ * == \Array Indexes
+ *
+ * \Array indexing starts at 0, as in C or Java.
+ *
+ * A non-negative index is an offset from the first element:
*
* - Index 0 indicates the first element.
* - Index 1 indicates the second element.
@@ -8159,6 +8393,9 @@ rb_ary_deconstruct(VALUE ary)
* - Index -2 indicates the next-to-last element.
* - ...
*
+ *
+ * === In-Range and Out-of-Range Indexes
+ *
* A non-negative index is <i>in range</i> if and only if it is smaller than
* the size of the array. For a 3-element array:
*
@@ -8171,31 +8408,32 @@ rb_ary_deconstruct(VALUE ary)
* - Indexes -1 through -3 are in range.
* - Index -4 is out of range.
*
+ * === Effective Index
+ *
* Although the effective index into an array is always an integer,
- * some methods (both within and outside of class +Array+)
+ * some methods (both within class \Array and elsewhere)
* accept one or more non-integer arguments that are
* {integer-convertible objects}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
*
- *
* == Creating Arrays
*
- * You can create an +Array+ object explicitly with:
+ * You can create an \Array object explicitly with:
*
- * - An {array literal}[rdoc-ref:literals.rdoc@Array+Literals]:
+ * - An {array literal}[rdoc-ref:syntax/literals.rdoc@Array+Literals]:
*
* [1, 'one', :one, [2, 'two', :two]]
*
- * - A {%w or %W: string-array Literal}[rdoc-ref:literals.rdoc@25w+and+-25W-3A+String-Array+Literals]:
+ * - A {%w or %W string-array Literal}[rdoc-ref:syntax/literals.rdoc@25w+and+-25W-3A+String-Array+Literals]:
*
* %w[foo bar baz] # => ["foo", "bar", "baz"]
* %w[1 % *] # => ["1", "%", "*"]
*
- * - A {%i pr %I: symbol-array Literal}[rdoc-ref:literals.rdoc@25i+and+-25I-3A+Symbol-Array+Literals]:
+ * - A {%i or %I symbol-array Literal}[rdoc-ref:syntax/literals.rdoc@25i+and+-25I-3A+Symbol-Array+Literals]:
*
* %i[foo bar baz] # => [:foo, :bar, :baz]
* %i[1 % *] # => [:"1", :%, :*]
*
- * - \Method Kernel#Array:
+ * - Method Kernel#Array:
*
* Array(["a", "b"]) # => ["a", "b"]
* Array(1..5) # => [1, 2, 3, 4, 5]
@@ -8204,7 +8442,7 @@ rb_ary_deconstruct(VALUE ary)
* Array(1) # => [1]
* Array({:a => "a", :b => "b"}) # => [[:a, "a"], [:b, "b"]]
*
- * - \Method Array.new:
+ * - Method Array.new:
*
* Array.new # => []
* Array.new(3) # => [nil, nil, nil]
@@ -8259,8 +8497,8 @@ rb_ary_deconstruct(VALUE ary)
*
* == Example Usage
*
- * In addition to the methods it mixes in through the Enumerable module, the
- * +Array+ class has proprietary methods for accessing, searching and otherwise
+ * In addition to the methods it mixes in through the Enumerable module,
+ * class \Array has proprietary methods for accessing, searching and otherwise
* manipulating arrays.
*
* Some of the more common ones are illustrated below.
@@ -8308,9 +8546,9 @@ rb_ary_deconstruct(VALUE ary)
*
* arr.drop(3) #=> [4, 5, 6]
*
- * == Obtaining Information about an +Array+
+ * == Obtaining Information about an \Array
*
- * Arrays keep track of their own length at all times. To query an array
+ * An array keeps track of its own length at all times. To query an array
* about the number of elements it contains, use #length, #count or #size.
*
* browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
@@ -8325,7 +8563,7 @@ rb_ary_deconstruct(VALUE ary)
*
* browsers.include?('Konqueror') #=> false
*
- * == Adding Items to Arrays
+ * == Adding Items to an \Array
*
* Items can be added to the end of an array by using either #push or #<<
*
@@ -8346,7 +8584,7 @@ rb_ary_deconstruct(VALUE ary)
* arr.insert(3, 'orange', 'pear', 'grapefruit')
* #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]
*
- * == Removing Items from an +Array+
+ * == Removing Items from an \Array
*
* The method #pop removes the last element in an array and returns it:
*
@@ -8386,11 +8624,11 @@ rb_ary_deconstruct(VALUE ary)
* arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
* arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
*
- * == Iterating over Arrays
+ * == Iterating over an \Array
*
- * Like all classes that include the Enumerable module, +Array+ has an each
+ * Like all classes that include the Enumerable module, class \Array has an each
* method, which defines what elements should be iterated over and how. In
- * case of Array's #each, all elements in the +Array+ instance are yielded to
+ * case of Array#each, all elements in +self+ are yielded to
* the supplied block in sequence.
*
* Note that this operation leaves the array unchanged.
@@ -8417,7 +8655,7 @@ rb_ary_deconstruct(VALUE ary)
* arr #=> [1, 4, 9, 16, 25]
*
*
- * == Selecting Items from an +Array+
+ * == Selecting Items from an \Array
*
* Elements can be selected from an array according to criteria defined in a
* block. The selection can happen in a destructive or a non-destructive
@@ -8450,13 +8688,13 @@ rb_ary_deconstruct(VALUE ary)
*
* == What's Here
*
- * First, what's elsewhere. \Class +Array+:
+ * First, what's elsewhere. Class \Array:
*
* - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
* - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
* which provides dozens of additional methods.
*
- * Here, class +Array+ provides methods that are useful for:
+ * Here, class \Array provides methods that are useful for:
*
* - {Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]
* - {Querying}[rdoc-ref:Array@Methods+for+Querying]
@@ -8469,154 +8707,138 @@ rb_ary_deconstruct(VALUE ary)
* - {Converting}[rdoc-ref:Array@Methods+for+Converting]
* - {And more....}[rdoc-ref:Array@Other+Methods]
*
- * === Methods for Creating an +Array+
+ * === 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.
*
+ * See also {Creating Arrays}[rdoc-ref:Array@Creating+Arrays].
+ *
* === Methods for Querying
*
- * - #length, #size: Returns the count of elements.
- * - #include?: Returns whether any element <tt>==</tt> a given object.
- * - #empty?: Returns whether there are no elements.
* - #all?: Returns whether all elements meet a given criterion.
* - #any?: Returns whether any element meets a given criterion.
+ * - #count: Returns the count of elements that meet a given criterion.
+ * - #empty?: Returns whether there are no elements.
+ * - #find_index (aliased as #index): Returns the index of the first element that meets a given criterion.
+ * - #hash: Returns the integer hash code.
+ * - #include?: Returns whether any element <tt>==</tt> a given object.
+ * - #length (aliased as #size): Returns the count of elements.
* - #none?: Returns whether no element <tt>==</tt> a given object.
* - #one?: Returns whether exactly one element <tt>==</tt> a given object.
- * - #count: Returns the count of elements that meet a given criterion.
- * - #find_index, #index: Returns the index of the first element that meets a given criterion.
* - #rindex: Returns the index of the last element that meets a given criterion.
- * - #hash: Returns the integer hash code.
*
* === Methods for Comparing
*
- * - #<=>: Returns -1, 0, or 1 * as +self+ is less than, equal to, or
- * greater than a given object.
- * - #==: Returns whether each element in +self+ is <tt>==</tt> to the corresponding element
- * in a given object.
- * - #eql?: Returns whether each element in +self+ is <tt>eql?</tt> to the corresponding
- * element in a given object.
+ * - #<=>: Returns -1, 0, or 1, as +self+ is less than, equal to, or greater than a given object.
+ * - #==: Returns whether each element in +self+ is <tt>==</tt> to the corresponding element in a given object.
+ * - #eql?: Returns whether each element in +self+ is <tt>eql?</tt> 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 <tt><=></tt> or a given block.
- * - #min: Returns one or more minimum-valued elements,
- * as determined by <tt><=></tt> or a given block.
- * - #minmax: Returns the minimum-valued and maximum-valued elements,
- * as determined by <tt><=></tt> or a given block.
- * - #assoc: Returns the first element that is an array
- * whose first element <tt>==</tt> a given object.
- * - #rassoc: Returns the first element that is an array
- * whose second element <tt>==</tt> a given object.
+ * - #[] (aliased as #slice): Returns consecutive elements as determined by a given argument.
+ * - #assoc: Returns the first element that is an array whose first element <tt>==</tt> a given object.
* - #at: Returns the element at a given offset.
- * - #values_at: Returns the elements at given offsets.
- * - #dig: Returns the object in nested objects
- * that is specified by a given index and additional arguments.
+ * - #bsearch: Returns an element selected via a binary search as determined by a given block.
+ * - #bsearch_index: Returns the index of an element selected via a binary search as determined by a given block.
+ * - #compact: Returns an array containing all non-+nil+ elements.
+ * - #dig: Returns the object in nested objects that is specified by a given index and additional arguments.
* - #drop: Returns trailing elements as determined by a given index.
- * - #take: Returns leading elements as determined by a given index.
* - #drop_while: Returns trailing elements as determined by a given block.
- * - #take_while: Returns leading elements as determined by a given block.
- * - #slice: Returns consecutive elements as determined by a given argument.
- * - #sort: Returns all elements in an order determined by <tt><=></tt> or a given block.
+ * - #fetch: Returns the element at a given offset.
+ * - #fetch_values: Returns elements at given offsets.
+ * - #first: Returns one or more leading elements.
+ * - #last: Returns one or more trailing elements.
+ * - #max: Returns one or more maximum-valued elements, as determined by <tt>#<=></tt> or a given block.
+ * - #min: Returns one or more minimum-valued elements, as determined by <tt>#<=></tt> or a given block.
+ * - #minmax: Returns the minimum-valued and maximum-valued elements, as determined by <tt>#<=></tt> or a given block.
+ * - #rassoc: Returns the first element that is an array whose second element <tt>==</tt> a given object.
+ * - #reject: Returns an array containing elements not rejected by a given block.
* - #reverse: Returns all elements in reverse order.
- * - #compact: Returns an array containing all non-+nil+ elements.
- * - #select, #filter: Returns an array containing elements selected by a given block.
- * - #uniq: Returns an array containing non-duplicate elements.
* - #rotate: Returns all elements with some rotated from one end to the other.
- * - #bsearch: Returns an element selected via a binary search
- * as determined by a given block.
- * - #bsearch_index: Returns the index of an element selected via a binary search
- * as determined by a given block.
* - #sample: Returns one or more random elements.
+ * - #select (aliased as #filter): Returns an array containing elements selected by a given block.
* - #shuffle: Returns elements in a random order.
+ * - #sort: Returns all elements in an order determined by <tt>#<=></tt> or a given block.
+ * - #take: Returns leading elements as determined by a given index.
+ * - #take_while: Returns leading elements as determined by a given block.
+ * - #uniq: Returns an array containing non-duplicate elements.
+ * - #values_at: Returns the elements at given offsets.
*
* === Methods for Assigning
*
* These methods add, replace, or reorder elements in +self+.
*
+ * - #<<: Appends an element.
* - #[]=: Assigns specified elements with a given object.
- * - #push, #append, #<<: Appends trailing elements.
- * - #unshift, #prepend: Prepends leading elements.
- * - #insert: Inserts given objects at a given offset; does not replace elements.
* - #concat: Appends all elements from given arrays.
* - #fill: Replaces specified elements with specified objects.
- * - #replace: Replaces the content of +self+ with the content of a given array.
+ * - #flatten!: Replaces each nested array in +self+ with the elements from that array.
+ * - #initialize_copy (aliased as #replace): Replaces the content of +self+ with the content of a given array.
+ * - #insert: Inserts given objects at a given offset; does not replace elements.
+ * - #push (aliased as #append): Appends elements.
* - #reverse!: Replaces +self+ with its elements reversed.
* - #rotate!: Replaces +self+ with its elements rotated.
* - #shuffle!: Replaces +self+ with its elements in random order.
- * - #sort!: Replaces +self+ with its elements sorted,
- * as determined by <tt><=></tt> or a given block.
+ * - #sort!: Replaces +self+ with its elements sorted, as determined by <tt>#<=></tt> or a given block.
* - #sort_by!: Replaces +self+ with its elements sorted, as determined by a given block.
+ * - #unshift (aliased as #prepend): Prepends leading elements.
*
* === Methods for Deleting
*
* Each of these methods removes elements from +self+:
*
- * - #pop: Removes and returns the last element.
- * - #shift: Removes and returns the first element.
+ * - #clear: Removes all elements.
* - #compact!: Removes all +nil+ elements.
* - #delete: Removes elements equal to a given object.
* - #delete_at: Removes the element at a given offset.
* - #delete_if: Removes elements specified by a given block.
* - #keep_if: Removes elements not specified by a given block.
+ * - #pop: Removes and returns the last element.
* - #reject!: Removes elements specified by a given block.
- * - #select!, #filter!: Removes elements not specified by a given block.
+ * - #select! (aliased as #filter!): Removes elements not specified by a given block.
+ * - #shift: Removes and returns the first element.
* - #slice!: Removes and returns a sequence of elements.
* - #uniq!: Removes duplicates.
*
* === Methods for Combining
*
* - #&: Returns an array containing elements found both in +self+ and a given array.
- * - #intersection: Returns an array containing elements found both in +self+
- * and in each given array.
* - #+: Returns an array containing all elements of +self+ followed by all elements of a given array.
* - #-: Returns an array containing all elements of +self+ that are not found in a given array.
- * - #|: Returns an array containing all elements of +self+ and all elements of a given array,
- * duplicates removed.
- * - #union: Returns an array containing all elements of +self+ and all elements of given arrays,
- * duplicates removed.
- * - #difference: Returns an array containing all elements of +self+ that are not found
- * in any of the given arrays..
+ * - #|: Returns an array containing all element of +self+ and all elements of a given array, duplicates removed.
+ * - #difference: Returns an array containing all elements of +self+ that are not found in any of the given arrays..
+ * - #intersection: Returns an array containing elements found both in +self+ and in each given array.
* - #product: Returns or yields all combinations of elements from +self+ and given arrays.
+ * - #reverse: Returns an array containing all elements of +self+ in reverse order.
+ * - #union: Returns an array containing all elements of +self+ and all elements of given arrays, duplicates removed.
*
* === Methods for Iterating
*
+ * - #combination: Calls a given block with combinations of elements of +self+; a combination does not use the same element more than once.
+ * - #cycle: Calls a given block with each element, then does so again, for a specified number of times, or forever.
* - #each: Passes each element to a given block.
- * - #reverse_each: Passes each element, in reverse order, to a given block.
* - #each_index: Passes each element index to a given block.
- * - #cycle: Calls a given block with each element, then does so again,
- * for a specified number of times, or forever.
- * - #combination: Calls a given block with combinations of elements of +self+;
- * a combination does not use the same element more than once.
- * - #permutation: Calls a given block with permutations of elements of +self+;
- * a permutation does not use the same element more than once.
- * - #repeated_combination: Calls a given block with combinations of elements of +self+;
- * a combination may use the same element more than once.
- * - #repeated_permutation: Calls a given block with permutations of elements of +self+;
- * a permutation may use the same element more than once.
+ * - #permutation: Calls a given block with permutations of elements of +self+; a permutation does not use the same element more than once.
+ * - #repeated_combination: Calls a given block with combinations of elements of +self+; a combination may use the same element more than once.
+ * - #repeated_permutation: Calls a given block with permutations of elements of +self+; a permutation may use the same element more than once.
+ * - #reverse_each: Passes each element, in reverse order, to a given block.
*
* === Methods for Converting
*
- * - #map, #collect: Returns an array containing the block return-value for each element.
- * - #map!, #collect!: Replaces each element with a block return-value.
+ * - #collect (aliased as #map): Returns an array containing the block return-value for each element.
+ * - #collect! (aliased as #map!): Replaces each element with a block return-value.
* - #flatten: Returns an array that is a recursive flattening of +self+.
- * - #flatten!: Replaces each nested array in +self+ with the elements from that array.
- * - #inspect, #to_s: Returns a new String containing the elements.
- * - #join: Returns a newsString containing the elements joined by the field separator.
+ * - #inspect (aliased as #to_s): Returns a new String containing the elements.
+ * - #join: Returns a new String containing the elements joined by the field separator.
* - #to_a: Returns +self+ or a new array containing all elements.
* - #to_ary: Returns +self+.
* - #to_h: Returns a new hash formed from the elements.
* - #transpose: Transposes +self+, which must be an array of arrays.
- * - #zip: Returns a new array of arrays containing +self+ and given arrays;
- * follow the link for details.
+ * - #zip: Returns a new array of arrays containing +self+ and given arrays.
*
* === Other Methods
*
@@ -8627,7 +8849,6 @@ rb_ary_deconstruct(VALUE ary)
* - With string argument +field_separator+, a new string that is equivalent to
* <tt>join(field_separator)</tt>.
*
- * - #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 <tt>+</tt> or a given block.
*/
@@ -8635,6 +8856,8 @@ rb_ary_deconstruct(VALUE ary)
void
Init_Array(void)
{
+ fake_ary_flags = init_fake_ary_flags();
+
rb_cArray = rb_define_class("Array", rb_cObject);
rb_include_module(rb_cArray, rb_mEnumerable);
@@ -8672,11 +8895,15 @@ Init_Array(void)
rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
rb_define_alias(rb_cArray, "prepend", "unshift");
rb_define_method(rb_cArray, "insert", rb_ary_insert, -1);
+ rb_define_method(rb_cArray, "each", rb_ary_each, 0);
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_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", rb_ary_find, -1);
+ rb_define_method(rb_cArray, "detect", rb_ary_find, -1);
+ rb_define_method(rb_cArray, "rfind", rb_ary_rfind, -1);
rb_define_method(rb_cArray, "find_index", rb_ary_index, -1);
rb_define_method(rb_cArray, "index", rb_ary_index, -1);
rb_define_method(rb_cArray, "rindex", rb_ary_rindex, -1);
@@ -8754,8 +8981,12 @@ Init_Array(void)
rb_define_method(rb_cArray, "one?", rb_ary_one_p, -1);
rb_define_method(rb_cArray, "dig", rb_ary_dig, -1);
rb_define_method(rb_cArray, "sum", rb_ary_sum, -1);
+ rb_define_method(rb_cArray, "freeze", rb_ary_freeze, 0);
rb_define_method(rb_cArray, "deconstruct", rb_ary_deconstruct, 0);
+
+ rb_cArray_empty_frozen = RB_OBJ_SET_SHAREABLE(rb_ary_freeze(rb_ary_new()));
+ rb_vm_register_global_object(rb_cArray_empty_frozen);
}
#include "array.rbinc"
diff --git a/array.rb b/array.rb
index f63ff00056..81beff0b1c 100644
--- a/array.rb
+++ b/array.rb
@@ -1,119 +1,97 @@
class Array
# call-seq:
- # array.each {|element| ... } -> self
- # array.each -> Enumerator
+ # shuffle!(random: Random) -> self
#
- # Iterates over array elements.
+ # Shuffles all elements in +self+ into a random order,
+ # as selected by the object given by the keyword argument +random+.
+ # Returns +self+:
#
- # When a block given, passes each successive array element to the block;
- # returns +self+:
+ # a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+ # a.shuffle! # => [5, 3, 8, 7, 6, 1, 9, 4, 2, 0]
+ # a.shuffle! # => [9, 4, 0, 6, 2, 8, 1, 5, 3, 7]
#
- # a = [:foo, 'bar', 2]
- # a.each {|element| puts "#{element.class} #{element}" }
- #
- # Output:
- #
- # Symbol foo
- # String bar
- # Integer 2
+ # Duplicate elements are included:
#
- # Allows the array to be modified during iteration:
+ # a = [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
+ # a.shuffle! # => [1, 0, 0, 1, 1, 0, 1, 0, 0, 1]
+ # a.shuffle! # => [0, 1, 0, 1, 1, 0, 1, 0, 1, 0]
#
- # a = [:foo, 'bar', 2]
- # a.each {|element| puts element; a.clear if element.to_s.start_with?('b') }
+ # The object given with the keyword argument +random+ is used as the random number generator.
#
- # Output:
+ # Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning].
+ def shuffle!(random: Random)
+ Primitive.rb_ary_shuffle_bang(random)
+ end
+
+ # call-seq:
+ # shuffle(random: Random) -> new_array
#
- # foo
- # bar
+ # Returns a new array containing all elements from +self+ in a random order,
+ # as selected by the object given by the keyword argument +random+:
#
- # When no block given, returns a new Enumerator:
- # a = [:foo, 'bar', 2]
+ # a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+ # a.shuffle # => [0, 8, 1, 9, 6, 3, 4, 7, 2, 5]
+ # a.shuffle # => [8, 9, 0, 5, 1, 2, 6, 4, 7, 3]
#
- # e = a.each
- # e # => #<Enumerator: [:foo, "bar", 2]:each>
- # a1 = e.each {|element| puts "#{element.class} #{element}" }
+ # Duplicate elements are included:
#
- # Output:
+ # a = [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
+ # a.shuffle # => [1, 0, 1, 1, 0, 0, 1, 0, 0, 1]
+ # a.shuffle # => [1, 1, 0, 0, 0, 1, 1, 0, 0, 1]
#
- # Symbol foo
- # String bar
- # Integer 2
+ # The object given with the keyword argument +random+ is used as the random number generator.
#
- # Related: #each_index, #reverse_each.
- def each
- Primitive.attr! :inline_block
- Primitive.attr! :use_block
-
- unless defined?(yield)
- return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
- end
- _i = 0
- value = nil
- while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) })
- yield value
- end
- self
+ # Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
+ def shuffle(random: Random)
+ Primitive.rb_ary_shuffle(random)
end
# call-seq:
- # array.shuffle!(random: Random) -> array
+ # sample(random: Random) -> object
+ # sample(count, random: Random) -> new_ary
#
- # Shuffles the elements of +self+ in place.
- # a = [1, 2, 3] #=> [1, 2, 3]
- # a.shuffle! #=> [2, 3, 1]
- # a #=> [2, 3, 1]
+ # Returns random elements from +self+,
+ # as selected by the object given by the keyword argument +random+.
#
- # 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
+ # With no argument +count+ given, returns one random element from +self+:
#
- # Returns a new array with elements of +self+ shuffled.
- # a = [1, 2, 3] #=> [1, 2, 3]
- # a.shuffle #=> [2, 3, 1]
- # a #=> [1, 2, 3]
+ # a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
+ # a.sample # => 3
+ # a.sample # => 8
#
- # 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 +nil+ if +self+ is empty:
#
- # Returns random elements from +self+.
+ # [].sample # => nil
#
- # When no arguments are given, returns a random element from +self+:
- # a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
- # a.sample # => 3
- # a.sample # => 8
- # If +self+ is empty, returns +nil+.
+ # With a non-negative numeric argument +count+ given,
+ # returns a new array containing +count+ random elements from +self+:
+ #
+ # a.sample(3) # => [8, 9, 2]
+ # a.sample(6) # => [9, 6, 0, 3, 1, 4]
+ #
+ # The order of the result array is unrelated to the order of +self+.
+ #
+ # Returns a new empty array if +self+ is empty:
+ #
+ # [].sample(4) # => []
+ #
+ # May return duplicates in +self+:
+ #
+ # a = [1, 1, 1, 2, 2, 3]
+ # a.sample(a.size) # => [1, 1, 3, 2, 1, 2]
#
- # When argument +n+ is given, returns a new +Array+ containing +n+ random
- # elements from +self+:
- # a.sample(3) # => [8, 9, 2]
- # a.sample(6) # => [9, 6, 10, 3, 1, 4]
# Returns no more than <tt>a.size</tt> elements
# (because no new duplicates are introduced):
- # a.sample(a.size * 2) # => [6, 4, 1, 8, 5, 9, 10, 2, 3, 7]
- # But +self+ may contain duplicates:
- # a = [1, 1, 1, 2, 2, 3]
- # a.sample(a.size * 2) # => [1, 1, 3, 2, 1, 2]
- # The argument +n+ must be a non-negative numeric value.
- # The order of the result array is unrelated to the order of +self+.
- # Returns a new empty +Array+ if +self+ is empty.
#
- # The optional +random+ argument will be used as the random number generator:
- # a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
- # a.sample(random: Random.new(1)) #=> 6
- # a.sample(4, random: Random.new(1)) #=> [6, 10, 9, 2]
+ # a.sample(50) # => [6, 4, 1, 8, 5, 9, 0, 2, 3, 7]
+ #
+ # The object given with the keyword argument +random+ is used as the random number generator:
+ #
+ # a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ # a.sample(random: Random.new(1)) # => 6
+ # a.sample(4, random: Random.new(1)) # => [6, 10, 9, 2]
+ #
+ # Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
def sample(n = (ary = false), random: Random)
if Primitive.mandatory_only?
# Primitive.cexpr! %{ rb_ary_sample(self, rb_cRandom, Qfalse, Qfalse) }
@@ -125,12 +103,12 @@ class Array
end
# call-seq:
- # array.first -> object or nil
- # array.first(n) -> new_array
+ # first -> object or nil
+ # first(count) -> new_array
#
- # Returns elements from +self+; does not modify +self+.
+ # Returns elements from +self+, or +nil+; does not modify +self+.
#
- # When no argument is given, returns the first element:
+ # With no argument given, returns the first element (if available):
#
# a = [:foo, 'bar', 2]
# a.first # => :foo
@@ -138,23 +116,16 @@ class Array
#
# If +self+ is empty, returns +nil+.
#
- # When non-negative Integer argument +n+ is given,
- # returns the first +n+ elements in a new +Array+:
- #
- # a = [:foo, 'bar', 2]
- # a.first(2) # => [:foo, "bar"]
+ # [].first # => nil
#
- # If <tt>n >= array.size</tt>, returns all elements:
+ # With a non-negative integer argument +count+ given,
+ # returns the first +count+ elements (as available) in a new array:
#
- # a = [:foo, 'bar', 2]
+ # a.first(0) # => []
+ # a.first(2) # => [:foo, "bar"]
# a.first(50) # => [:foo, "bar", 2]
#
- # If <tt>n == 0</tt> returns an new empty +Array+:
- #
- # a = [:foo, 'bar', 2]
- # a.first(0) # []
- #
- # Related: #last.
+ # Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying].
def first n = unspecified = true
if Primitive.mandatory_only?
Primitive.attr! :leaf
@@ -169,36 +140,29 @@ class Array
end
# call-seq:
- # array.last -> object or nil
- # array.last(n) -> new_array
+ # last -> last_object or nil
+ # last(count) -> new_array
#
- # Returns elements from +self+; +self+ is not modified.
+ # Returns elements from +self+, or +nil+; +self+ is not modified.
#
- # When no argument is given, returns the last element:
+ # With no argument given, returns the last element, or +nil+ if +self+ is empty:
#
# a = [:foo, 'bar', 2]
# a.last # => 2
# a # => [:foo, "bar", 2]
+ # [].last # => nil
#
- # If +self+ is empty, returns +nil+.
- #
- # When non-negative Integer argument +n+ is given,
- # returns the last +n+ elements in a new +Array+:
- #
- # a = [:foo, 'bar', 2]
- # a.last(2) # => ["bar", 2]
#
- # If <tt>n >= array.size</tt>, returns all elements:
+ # With non-negative integer argument +count+ given,
+ # returns a new array containing the trailing +count+ elements of +self+, as available:
#
# a = [:foo, 'bar', 2]
+ # a.last(2) # => ["bar", 2]
# a.last(50) # => [:foo, "bar", 2]
+ # a.last(0) # => []
+ # [].last(3) # => []
#
- # If <tt>n == 0</tt>, returns an new empty +Array+:
- #
- # a = [:foo, 'bar', 2]
- # a.last(0) # []
- #
- # Related: #first.
+ # Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
def last n = unspecified = true
if Primitive.mandatory_only?
Primitive.attr! :leaf
@@ -211,4 +175,113 @@ class Array
end
end
end
+
+ # call-seq:
+ # fetch_values(*indexes) -> new_array
+ # fetch_values(*indexes) { |index| ... } -> new_array
+ #
+ # With no block given, returns a new array containing the elements of +self+
+ # at the offsets specified by +indexes+. Each of the +indexes+ must be an
+ # {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]:
+ #
+ # a = [:foo, :bar, :baz]
+ # a.fetch_values(2, 0) # => [:baz, :foo]
+ # a.fetch_values(2.1, 0) # => [:baz, :foo]
+ # a.fetch_values # => []
+ #
+ # For a negative index, counts backwards from the end of the array:
+ #
+ # a.fetch_values(-2, -1) # [:bar, :baz]
+ #
+ # When no block is given, raises an exception if any index is out of range.
+ #
+ # With a block given, for each index:
+ #
+ # - If the index is in range, uses an element of +self+ (as above).
+ # - Otherwise, calls the block with the index and uses the block's return value.
+ #
+ # Example:
+ #
+ # a = [:foo, :bar, :baz]
+ # a.fetch_values(1, 0, 42, 777) { |index| index.to_s }
+ # # => [:bar, :foo, "42", "777"]
+ #
+ # Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching].
+ def fetch_values(*indexes, &block)
+ indexes.map! { |i| fetch(i, &block) }
+ indexes
+ end
+
+ with_jit do
+ if Primitive.rb_builtin_basic_definition_p(:each)
+ undef :each
+
+ def each # :nodoc:
+ Primitive.attr! :inline_block, :c_trace
+
+ unless defined?(yield)
+ return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
+ end
+ _i = 0
+ value = nil
+ while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) })
+ yield value
+ end
+ self
+ end
+ end
+
+ if Primitive.rb_builtin_basic_definition_p(:map)
+ undef :map
+
+ def map # :nodoc:
+ Primitive.attr! :inline_block, :c_trace
+
+ unless defined?(yield)
+ return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
+ end
+
+ _i = 0
+ value = nil
+ result = Primitive.ary_sized_alloc
+ while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) })
+ value = yield(value)
+ Primitive.cexpr!(%q{ rb_ary_push(result, value) })
+ end
+ result
+ end
+
+ if Primitive.rb_builtin_basic_definition_p(:collect)
+ undef :collect
+ alias collect map
+ end
+ end
+
+ if Primitive.rb_builtin_basic_definition_p(:select)
+ undef :select
+
+ def select # :nodoc:
+ Primitive.attr! :inline_block, :c_trace
+
+ unless defined?(yield)
+ return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
+ end
+
+ _i = 0
+ value = nil
+ result = Primitive.ary_sized_alloc
+ while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) })
+ if yield value
+ Primitive.cexpr!(%q{ rb_ary_push(result, value) })
+ end
+ end
+ result
+ end
+
+ if Primitive.rb_builtin_basic_definition_p(:filter)
+ undef :filter
+ alias filter select
+ end
+ end
+ end
end
diff --git a/ast.c b/ast.c
index 12b3996f94..5357aa38a5 100644
--- a/ast.c
+++ b/ast.c
@@ -14,6 +14,7 @@
static VALUE rb_mAST;
static VALUE rb_cNode;
+static VALUE rb_cLocation;
struct ASTNodeData {
VALUE ast_value;
@@ -31,9 +32,13 @@ static size_t
node_memsize(const void *ptr)
{
struct ASTNodeData *data = (struct ASTNodeData *)ptr;
- rb_ast_t *ast = rb_ruby_ast_data_get(data->ast_value);
+ size_t size = sizeof(struct ASTNodeData);
+ if (data->ast_value) {
+ rb_ast_t *ast = rb_ruby_ast_data_get(data->ast_value);
+ size += rb_ast_memsize(ast);
+ }
- return sizeof(struct ASTNodeData) + rb_ast_memsize(ast);
+ return size;
}
static const rb_data_type_t rb_node_type = {
@@ -43,6 +48,32 @@ static const rb_data_type_t rb_node_type = {
RUBY_TYPED_FREE_IMMEDIATELY,
};
+struct ASTLocationData {
+ int first_lineno;
+ int first_column;
+ int last_lineno;
+ int last_column;
+};
+
+static void
+location_gc_mark(void *ptr)
+{
+}
+
+static size_t
+location_memsize(const void *ptr)
+{
+ return sizeof(struct ASTLocationData);
+}
+
+static const rb_data_type_t rb_location_type = {
+ "AST/location",
+ {location_gc_mark, RUBY_TYPED_DEFAULT_FREE, location_memsize,},
+ 0, 0,
+ RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+
static VALUE rb_ast_node_alloc(VALUE klass);
static void
@@ -89,6 +120,16 @@ ast_parse_done(VALUE ast_value)
}
static VALUE
+setup_vparser(VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
+{
+ VALUE vparser = ast_parse_new();
+ if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser);
+ if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser);
+ if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser);
+ return vparser;
+}
+
+static VALUE
ast_s_parse(rb_execution_context_t *ec, VALUE module, VALUE str, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
{
return rb_ast_parse_str(str, keep_script_lines, error_tolerant, keep_tokens);
@@ -97,13 +138,9 @@ ast_s_parse(rb_execution_context_t *ec, VALUE module, VALUE str, VALUE keep_scri
static VALUE
rb_ast_parse_str(VALUE str, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens)
{
- VALUE ast_value;
-
+ VALUE ast_value = Qnil;
StringValue(str);
- VALUE vparser = ast_parse_new();
- if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser);
- if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser);
- if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser);
+ VALUE vparser = setup_vparser(keep_script_lines, error_tolerant, keep_tokens);
ast_value = rb_parser_compile_string_path(vparser, Qnil, str, 1);
return ast_parse_done(ast_value);
}
@@ -123,10 +160,7 @@ rb_ast_parse_file(VALUE path, VALUE keep_script_lines, VALUE error_tolerant, VAL
f = rb_file_open_str(path, "r");
rb_funcall(f, rb_intern("set_encoding"), 2, rb_enc_from_encoding(enc), rb_str_new_cstr("-"));
- VALUE vparser = ast_parse_new();
- if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser);
- if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser);
- if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser);
+ VALUE vparser = setup_vparser(keep_script_lines, error_tolerant, keep_tokens);
ast_value = rb_parser_compile_file_path(vparser, Qnil, f, 1);
rb_io_close(f);
return ast_parse_done(ast_value);
@@ -138,10 +172,7 @@ rb_ast_parse_array(VALUE array, VALUE keep_script_lines, VALUE error_tolerant, V
VALUE ast_value = Qnil;
array = rb_check_array_type(array);
- VALUE vparser = ast_parse_new();
- if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser);
- if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser);
- if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser);
+ VALUE vparser = setup_vparser(keep_script_lines, error_tolerant, keep_tokens);
ast_value = rb_parser_compile_array(vparser, Qnil, array, 1);
return ast_parse_done(ast_value);
}
@@ -334,6 +365,24 @@ dump_array(VALUE ast_value, const struct RNode_LIST *node)
}
static VALUE
+dump_parser_array(VALUE ast_value, rb_parser_ary_t *p_ary)
+{
+ VALUE ary;
+
+ if (p_ary->data_type != PARSER_ARY_DATA_NODE) {
+ rb_bug("unexpected rb_parser_ary_data_type: %d", p_ary->data_type);
+ }
+
+ ary = rb_ary_new();
+
+ for (long i = 0; i < p_ary->len; i++) {
+ rb_ary_push(ary, NEW_CHILD(ast_value, p_ary->data[i]));
+ }
+
+ return ary;
+}
+
+static VALUE
var_name(ID id)
{
if (!id) return Qnil;
@@ -402,7 +451,7 @@ node_children(VALUE ast_value, const NODE *node)
case NODE_RESCUE:
return rb_ary_new_from_node_args(ast_value, 3, RNODE_RESCUE(node)->nd_head, RNODE_RESCUE(node)->nd_resq, RNODE_RESCUE(node)->nd_else);
case NODE_RESBODY:
- return rb_ary_new_from_node_args(ast_value, 3, RNODE_RESBODY(node)->nd_args, RNODE_RESBODY(node)->nd_body, RNODE_RESBODY(node)->nd_next);
+ return rb_ary_new_from_node_args(ast_value, 4, RNODE_RESBODY(node)->nd_args, RNODE_RESBODY(node)->nd_exc_var, RNODE_RESBODY(node)->nd_body, RNODE_RESBODY(node)->nd_next);
case NODE_ENSURE:
return rb_ary_new_from_node_args(ast_value, 2, RNODE_ENSURE(node)->nd_head, RNODE_ENSURE(node)->nd_ensr);
case NODE_AND:
@@ -577,7 +626,7 @@ node_children(VALUE ast_value, const NODE *node)
case NODE_VALIAS:
return rb_ary_new_from_args(2, ID2SYM(RNODE_VALIAS(node)->nd_alias), ID2SYM(RNODE_VALIAS(node)->nd_orig));
case NODE_UNDEF:
- return rb_ary_new_from_node_args(ast_value, 1, RNODE_UNDEF(node)->nd_undef);
+ return rb_ary_new_from_args(1, dump_parser_array(ast_value, RNODE_UNDEF(node)->nd_undefs));
case NODE_CLASS:
return rb_ary_new_from_node_args(ast_value, 3, RNODE_CLASS(node)->nd_cpath, RNODE_CLASS(node)->nd_super, RNODE_CLASS(node)->nd_body);
case NODE_MODULE:
@@ -702,6 +751,249 @@ ast_node_children(rb_execution_context_t *ec, VALUE self)
return node_children(data->ast_value, data->node);
}
+static int
+null_loc_p(rb_code_location_t *loc)
+{
+ return (loc->beg_pos.lineno == 0 && loc->beg_pos.column == -1 && loc->end_pos.lineno == 0 && loc->end_pos.column == -1);
+}
+
+static VALUE
+location_new(rb_code_location_t *loc)
+{
+ VALUE obj;
+ struct ASTLocationData *data;
+
+ if (null_loc_p(loc)) return Qnil;
+
+ obj = TypedData_Make_Struct(rb_cLocation, struct ASTLocationData, &rb_location_type, data);
+ data->first_lineno = loc->beg_pos.lineno;
+ data->first_column = loc->beg_pos.column;
+ data->last_lineno = loc->end_pos.lineno;
+ data->last_column = loc->end_pos.column;
+
+ return obj;
+}
+
+static VALUE
+node_locations(VALUE ast_value, const NODE *node)
+{
+ enum node_type type = nd_type(node);
+ switch (type) {
+ case NODE_ALIAS:
+ return rb_ary_new_from_args(2,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_ALIAS(node)->keyword_loc));
+ case NODE_AND:
+ return rb_ary_new_from_args(2,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_AND(node)->operator_loc));
+ case NODE_BLOCK_PASS:
+ return rb_ary_new_from_args(2,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_BLOCK_PASS(node)->operator_loc));
+ case NODE_BREAK:
+ return rb_ary_new_from_args(2,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_BREAK(node)->keyword_loc));
+ case NODE_CASE:
+ return rb_ary_new_from_args(3,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_CASE(node)->case_keyword_loc),
+ location_new(&RNODE_CASE(node)->end_keyword_loc));
+ case NODE_CASE2:
+ return rb_ary_new_from_args(3,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_CASE2(node)->case_keyword_loc),
+ location_new(&RNODE_CASE2(node)->end_keyword_loc));
+ case NODE_CASE3:
+ return rb_ary_new_from_args(3,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_CASE3(node)->case_keyword_loc),
+ location_new(&RNODE_CASE3(node)->end_keyword_loc));
+ case NODE_CLASS:
+ return rb_ary_new_from_args(4,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_CLASS(node)->class_keyword_loc),
+ location_new(&RNODE_CLASS(node)->inheritance_operator_loc),
+ location_new(&RNODE_CLASS(node)->end_keyword_loc));
+ case NODE_COLON2:
+ return rb_ary_new_from_args(3,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_COLON2(node)->delimiter_loc),
+ location_new(&RNODE_COLON2(node)->name_loc));
+ case NODE_COLON3:
+ return rb_ary_new_from_args(3,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_COLON3(node)->delimiter_loc),
+ location_new(&RNODE_COLON3(node)->name_loc));
+ case NODE_DEFINED:
+ return rb_ary_new_from_args(2,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_DEFINED(node)->keyword_loc));
+ case NODE_DOT2:
+ return rb_ary_new_from_args(2,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_DOT2(node)->operator_loc));
+ case NODE_DOT3:
+ return rb_ary_new_from_args(2,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_DOT3(node)->operator_loc));
+ case NODE_EVSTR:
+ return rb_ary_new_from_args(3,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_EVSTR(node)->opening_loc),
+ location_new(&RNODE_EVSTR(node)->closing_loc));
+ case NODE_FLIP2:
+ return rb_ary_new_from_args(2,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_FLIP2(node)->operator_loc));
+ case NODE_FLIP3:
+ return rb_ary_new_from_args(2,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_FLIP3(node)->operator_loc));
+ case NODE_FOR:
+ return rb_ary_new_from_args(5,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_FOR(node)->for_keyword_loc),
+ location_new(&RNODE_FOR(node)->in_keyword_loc),
+ location_new(&RNODE_FOR(node)->do_keyword_loc),
+ location_new(&RNODE_FOR(node)->end_keyword_loc));
+ case NODE_LAMBDA:
+ return rb_ary_new_from_args(4,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_LAMBDA(node)->operator_loc),
+ location_new(&RNODE_LAMBDA(node)->opening_loc),
+ location_new(&RNODE_LAMBDA(node)->closing_loc));
+ case NODE_IF:
+ return rb_ary_new_from_args(4,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_IF(node)->if_keyword_loc),
+ location_new(&RNODE_IF(node)->then_keyword_loc),
+ location_new(&RNODE_IF(node)->end_keyword_loc));
+ case NODE_IN:
+ return rb_ary_new_from_args(4,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_IN(node)->in_keyword_loc),
+ location_new(&RNODE_IN(node)->then_keyword_loc),
+ location_new(&RNODE_IN(node)->operator_loc));
+ case NODE_MODULE:
+ return rb_ary_new_from_args(3,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_MODULE(node)->module_keyword_loc),
+ location_new(&RNODE_MODULE(node)->end_keyword_loc));
+ case NODE_NEXT:
+ return rb_ary_new_from_args(2,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_NEXT(node)->keyword_loc));
+ case NODE_OR:
+ return rb_ary_new_from_args(2,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_OR(node)->operator_loc));
+ case NODE_OP_ASGN1:
+ return rb_ary_new_from_args(5,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_OP_ASGN1(node)->call_operator_loc),
+ location_new(&RNODE_OP_ASGN1(node)->opening_loc),
+ location_new(&RNODE_OP_ASGN1(node)->closing_loc),
+ location_new(&RNODE_OP_ASGN1(node)->binary_operator_loc));
+ case NODE_OP_ASGN2:
+ return rb_ary_new_from_args(4,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_OP_ASGN2(node)->call_operator_loc),
+ location_new(&RNODE_OP_ASGN2(node)->message_loc),
+ location_new(&RNODE_OP_ASGN2(node)->binary_operator_loc));
+ case NODE_POSTEXE:
+ return rb_ary_new_from_args(4,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_POSTEXE(node)->keyword_loc),
+ location_new(&RNODE_POSTEXE(node)->opening_loc),
+ location_new(&RNODE_POSTEXE(node)->closing_loc));
+ case NODE_REDO:
+ return rb_ary_new_from_args(2,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_REDO(node)->keyword_loc));
+ case NODE_REGX:
+ return rb_ary_new_from_args(4,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_REGX(node)->opening_loc),
+ location_new(&RNODE_REGX(node)->content_loc),
+ location_new(&RNODE_REGX(node)->closing_loc));
+ case NODE_RETURN:
+ return rb_ary_new_from_args(2,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_RETURN(node)->keyword_loc));
+
+ case NODE_SCLASS:
+ return rb_ary_new_from_args(4,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_SCLASS(node)->class_keyword_loc),
+ location_new(&RNODE_SCLASS(node)->operator_loc),
+ location_new(&RNODE_SCLASS(node)->end_keyword_loc));
+
+ case NODE_SPLAT:
+ return rb_ary_new_from_args(2,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_SPLAT(node)->operator_loc));
+ case NODE_SUPER:
+ return rb_ary_new_from_args(4,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_SUPER(node)->keyword_loc),
+ location_new(&RNODE_SUPER(node)->lparen_loc),
+ location_new(&RNODE_SUPER(node)->rparen_loc));
+ case NODE_UNDEF:
+ return rb_ary_new_from_args(2,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_UNDEF(node)->keyword_loc));
+ case NODE_UNLESS:
+ return rb_ary_new_from_args(4,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_UNLESS(node)->keyword_loc),
+ location_new(&RNODE_UNLESS(node)->then_keyword_loc),
+ location_new(&RNODE_UNLESS(node)->end_keyword_loc));
+ case NODE_VALIAS:
+ return rb_ary_new_from_args(2,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_VALIAS(node)->keyword_loc));
+ case NODE_WHEN:
+ return rb_ary_new_from_args(3,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_WHEN(node)->keyword_loc),
+ location_new(&RNODE_WHEN(node)->then_keyword_loc));
+ case NODE_WHILE:
+ return rb_ary_new_from_args(3,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_WHILE(node)->keyword_loc),
+ location_new(&RNODE_WHILE(node)->closing_loc));
+ case NODE_UNTIL:
+ return rb_ary_new_from_args(3,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_UNTIL(node)->keyword_loc),
+ location_new(&RNODE_UNTIL(node)->closing_loc));
+ case NODE_YIELD:
+ return rb_ary_new_from_args(4,
+ location_new(nd_code_loc(node)),
+ location_new(&RNODE_YIELD(node)->keyword_loc),
+ location_new(&RNODE_YIELD(node)->lparen_loc),
+ location_new(&RNODE_YIELD(node)->rparen_loc));
+ case NODE_ARGS_AUX:
+ case NODE_LAST:
+ break;
+ default:
+ return rb_ary_new_from_args(1, location_new(nd_code_loc(node)));
+ }
+
+ rb_bug("node_locations: unknown node: %s", ruby_node_name(type));
+}
+
+static VALUE
+ast_node_locations(rb_execution_context_t *ec, VALUE self)
+{
+ struct ASTNodeData *data;
+ TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data);
+
+ return node_locations(data->ast_value, data->node);
+}
+
static VALUE
ast_node_first_lineno(rb_execution_context_t *ec, VALUE self)
{
@@ -769,7 +1061,7 @@ ast_node_all_tokens(rb_execution_context_t *ec, VALUE self)
token = rb_ary_new_from_args(4, INT2FIX(parser_token->id), ID2SYM(rb_intern(parser_token->type_name)), str, loc);
rb_ary_push(all_tokens, token);
}
- rb_obj_freeze(all_tokens);
+ rb_ary_freeze(all_tokens);
return all_tokens;
}
@@ -805,6 +1097,61 @@ ast_node_script_lines(rb_execution_context_t *ec, VALUE self)
return rb_parser_build_script_lines_from(ret);
}
+static VALUE
+ast_location_first_lineno(rb_execution_context_t *ec, VALUE self)
+{
+ struct ASTLocationData *data;
+ TypedData_Get_Struct(self, struct ASTLocationData, &rb_location_type, data);
+
+ return INT2NUM(data->first_lineno);
+}
+
+static VALUE
+ast_location_first_column(rb_execution_context_t *ec, VALUE self)
+{
+ struct ASTLocationData *data;
+ TypedData_Get_Struct(self, struct ASTLocationData, &rb_location_type, data);
+
+ return INT2NUM(data->first_column);
+}
+
+static VALUE
+ast_location_last_lineno(rb_execution_context_t *ec, VALUE self)
+{
+ struct ASTLocationData *data;
+ TypedData_Get_Struct(self, struct ASTLocationData, &rb_location_type, data);
+
+ return INT2NUM(data->last_lineno);
+}
+
+static VALUE
+ast_location_last_column(rb_execution_context_t *ec, VALUE self)
+{
+ struct ASTLocationData *data;
+ TypedData_Get_Struct(self, struct ASTLocationData, &rb_location_type, data);
+
+ return INT2NUM(data->last_column);
+}
+
+static VALUE
+ast_location_inspect(rb_execution_context_t *ec, VALUE self)
+{
+ VALUE str;
+ VALUE cname;
+ struct ASTLocationData *data;
+ TypedData_Get_Struct(self, struct ASTLocationData, &rb_location_type, data);
+
+ cname = rb_class_path(rb_obj_class(self));
+ str = rb_str_new2("#<");
+
+ rb_str_append(str, cname);
+ rb_str_catf(str, ":@%d:%d-%d:%d>",
+ data->first_lineno, data->first_column,
+ data->last_lineno, data->last_column);
+
+ return str;
+}
+
#include "ast.rbinc"
void
@@ -812,5 +1159,7 @@ Init_ast(void)
{
rb_mAST = rb_define_module_under(rb_cRubyVM, "AbstractSyntaxTree");
rb_cNode = rb_define_class_under(rb_mAST, "Node", rb_cObject);
+ rb_cLocation = rb_define_class_under(rb_mAST, "Location", rb_cObject);
rb_undef_alloc_func(rb_cNode);
+ rb_undef_alloc_func(rb_cLocation);
}
diff --git a/ast.rb b/ast.rb
index 51ee5b3d59..6380621780 100644
--- a/ast.rb
+++ b/ast.rb
@@ -13,9 +13,8 @@
# access children nodes by name, etc.
#
# If you are looking for a stable API or an API working under multiple Ruby
-# implementations, consider using the _parser_ gem or Ripper. If you would
-# like to make RubyVM::AbstractSyntaxTree stable, please join the discussion
-# at https://bugs.ruby-lang.org/issues/14844.
+# implementations, consider using the _prism_ gem, which is the official
+# Ruby API to parse Ruby code.
#
module RubyVM::AbstractSyntaxTree
@@ -272,5 +271,62 @@ module RubyVM::AbstractSyntaxTree
nil
end
end
+
+ # call-seq:
+ # node.locations -> array
+ #
+ # Returns location objects associated with the AST node.
+ # The returned array contains RubyVM::AbstractSyntaxTree::Location.
+ def locations
+ Primitive.ast_node_locations
+ end
+ end
+
+ # RubyVM::AbstractSyntaxTree::Location instances are created by
+ # RubyVM::AbstractSyntaxTree::Node#locations.
+ #
+ # This class is MRI specific.
+ #
+ class Location
+
+ # call-seq:
+ # location.first_lineno -> integer
+ #
+ # The line number in the source code where this AST's text began.
+ def first_lineno
+ Primitive.ast_location_first_lineno
+ end
+
+ # call-seq:
+ # location.first_column -> integer
+ #
+ # The column number in the source code where this AST's text began.
+ def first_column
+ Primitive.ast_location_first_column
+ end
+
+ # call-seq:
+ # location.last_lineno -> integer
+ #
+ # The line number in the source code where this AST's text ended.
+ def last_lineno
+ Primitive.ast_location_last_lineno
+ end
+
+ # call-seq:
+ # location.last_column -> integer
+ #
+ # The column number in the source code where this AST's text ended.
+ def last_column
+ Primitive.ast_location_last_column
+ end
+
+ # call-seq:
+ # location.inspect -> string
+ #
+ # Returns debugging information about this location as a string.
+ def inspect
+ Primitive.ast_location_inspect
+ end
end
end
diff --git a/autogen.sh b/autogen.sh
index f8cdf3c0c1..6cbc5dddab 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -1,17 +1,22 @@
#!/bin/sh
+# Clear PWD to force commands to recompute working directory
PWD=
+
+# Figure out the source directory for this script
+# configure.ac should be in the same place
case "$0" in
-*/*) srcdir=`dirname $0`;;
-*) srcdir="";;
+ */* ) srcdir=`dirname "$0"` ;; # Called with path
+ * ) srcdir="";; # Otherwise
esac
-symlink='--install --symlink'
+# If install-only is explicitly requested, disable symlink flags
case " $* " in
- *" -i "*|*" --install "*)
- # reset to copy missing standard auxiliary files, instead of symlinks
- symlink=
- ;;
+ *" -i "* | *" --install"* ) symlink_flags="" ;;
+ * ) symlink_flags="--install --symlink" ;;
esac
-exec ${AUTORECONF:-autoreconf} ${symlink} "$@" ${srcdir:+"$srcdir"}
+exec ${AUTORECONF:-autoreconf} \
+ $symlink_flags \
+ "$@" \
+ $srcdir
diff --git a/benchmark/README.md b/benchmark/README.md
index e11381cad9..9f9192685e 100644
--- a/benchmark/README.md
+++ b/benchmark/README.md
@@ -27,6 +27,7 @@ benchmark-driver benchmark/*.yml
See also:
```console
+benchmark-driver --help
Usage: benchmark-driver [options] RUBY|YAML...
-r, --runner TYPE Specify runner type: ips, time, memory, once, block (default: ips)
-o, --output TYPE Specify output type: compare, simple, markdown, record, all (default: compare)
@@ -39,7 +40,7 @@ Usage: benchmark-driver [options] RUBY|YAML...
--filter REGEXP Filter out benchmarks with given regexp
--run-duration SECONDS Warmup estimates loop_count to run for this duration (default: 3)
--timeout SECONDS Timeout ruby command execution with timeout(1)
- -v, --verbose Verbose mode. Multiple -v options increase visilibity (max: 2)
+ -v, --verbose Verbose mode. Multiple -v options increase visibility (max: 2)
```
## make benchmark
diff --git a/benchmark/app_aobench.rb b/benchmark/app_aobench.rb
index 16296af12b..c1546e08ab 100644
--- a/benchmark/app_aobench.rb
+++ b/benchmark/app_aobench.rb
@@ -151,7 +151,7 @@ def clamp(f)
i.to_i
end
-def otherBasis(basis, n)
+def orthoBasis(basis, n)
basis[2] = Vec.new(n.x, n.y, n.z)
basis[1] = Vec.new(0.0, 0.0, 0.0)
@@ -183,7 +183,7 @@ class Scene
def ambient_occlusion(isect)
basis = Array.new
- otherBasis(basis, isect.n)
+ orthoBasis(basis, isect.n)
ntheta = NAO_SAMPLES
nphi = NAO_SAMPLES
diff --git a/benchmark/app_fib.rb b/benchmark/app_fib.rb
index 34a7b2e725..e61bc8aa32 100644
--- a/benchmark/app_fib.rb
+++ b/benchmark/app_fib.rb
@@ -1,4 +1,4 @@
-def fib n
+def fib(n)
if n < 3
1
else
diff --git a/benchmark/class_superclass.yml b/benchmark/class_superclass.yml
new file mode 100644
index 0000000000..847ff811f1
--- /dev/null
+++ b/benchmark/class_superclass.yml
@@ -0,0 +1,23 @@
+prelude: |
+ class SimpleClass; end
+ class OneModuleClass
+ 1.times { include Module.new }
+ end
+ class MediumClass
+ 10.times { include Module.new }
+ end
+ class LargeClass
+ 100.times { include Module.new }
+ end
+benchmark:
+ object_class_superclass: |
+ Object.superclass
+ simple_class_superclass: |
+ SimpleClass.superclass
+ one_module_class: |
+ OneModuleClass.superclass
+ medium_class_superclass: |
+ MediumClass.superclass
+ large_class_superclass: |
+ LargeClass.superclass
+loop_count: 20000000
diff --git a/benchmark/file_join.yml b/benchmark/file_join.yml
new file mode 100644
index 0000000000..845257cf1e
--- /dev/null
+++ b/benchmark/file_join.yml
@@ -0,0 +1,7 @@
+prelude: |
+ # frozen_string_literal: true
+benchmark:
+ two_strings: File.join(__FILE__, "path")
+ many_strings: File.join(__FILE__, "path", "a", "b", "c", "d")
+ array: File.join([__FILE__, "path", "a", "b", "c", "d"])
+ mixed: File.join(__FILE__, "path", "a", "b", ["c", "d"])
diff --git a/benchmark/hash_new.yml b/benchmark/hash_new.yml
new file mode 100644
index 0000000000..9d8e34187f
--- /dev/null
+++ b/benchmark/hash_new.yml
@@ -0,0 +1,16 @@
+prelude: |
+ has_hash_with_capa = Hash.instance_method(:initialize).parameters.include?([:key, :capacity])
+ strings_1k = 1_000.times.map { |i| -i.to_s.freeze }
+ strings_100k = 100_000.times.map { |i| -i.to_s.freeze }
+benchmark:
+ new: Hash.new
+ new_with_capa_1k: |
+ h = has_hash_with_capa ? Hash.new(capacity: strings_1k.size) : {}
+ strings_1k.each do |x|
+ h[x] = true
+ end
+ new_with_capa_100k: |
+ h = has_hash_with_capa ? Hash.new(capacity: strings_100k.size) : {}
+ strings_100k.each do |x|
+ h[x] = true
+ end
diff --git a/benchmark/io_close.yml b/benchmark/io_close.yml
new file mode 100644
index 0000000000..a552872884
--- /dev/null
+++ b/benchmark/io_close.yml
@@ -0,0 +1,13 @@
+prelude: |
+ ios = 1000.times.map do
+ 100.times.map{IO.pipe}
+ end
+benchmark:
+ # Close IO
+ io_close: |
+ # Process each batch of ios per iteration of the benchmark.
+ ios.pop.each do |r, w|
+ r.close
+ w.close
+ end
+loop_count: 100
diff --git a/benchmark/io_close_contended.yml b/benchmark/io_close_contended.yml
new file mode 100644
index 0000000000..1d9e4e0d0f
--- /dev/null
+++ b/benchmark/io_close_contended.yml
@@ -0,0 +1,21 @@
+prelude: |
+ ios = 100.times.map do
+ 10.times.map do
+ pipe = IO.pipe.tap do |r, w|
+ Thread.new do
+ r.read
+ rescue IOError
+ # Ignore
+ end
+ end
+ end
+ end
+benchmark:
+ # Close IO
+ io_close_contended: |
+ # Process each batch of ios per iteration of the benchmark.
+ ios.pop.each do |r, w|
+ r.close
+ w.close
+ end
+loop_count: 10
diff --git a/benchmark/lib/benchmark_driver/runner/ractor.rb b/benchmark/lib/benchmark_driver/runner/ractor.rb
index c730b8e4a5..fd9c2dd4db 100644
--- a/benchmark/lib/benchmark_driver/runner/ractor.rb
+++ b/benchmark/lib/benchmark_driver/runner/ractor.rb
@@ -87,7 +87,7 @@ __bmdv_ractors << Ractor.new(__bmdv_loop_after - __bmdv_loop_before) { |__bmdv_l
<% end %>
# Wait for all Ractors before executing code to write results
-__bmdv_ractors.map!(&:take)
+__bmdv_ractors.map!(&:value)
<% results.each do |result| %>
File.write(<%= result.dump %>, __bmdv_ractors.shift)
diff --git a/benchmark/module_eqq.yml b/benchmark/module_eqq.yml
index a561fb86dc..2f9c490d92 100644
--- a/benchmark/module_eqq.yml
+++ b/benchmark/module_eqq.yml
@@ -1,4 +1,5 @@
prelude: |
+ module SomeModule; end
class SimpleClass; end
class MediumClass
10.times { include Module.new }
@@ -24,4 +25,8 @@ benchmark:
SimpleClass === LargeObj
simple_class_eqq_huge_obj: |
SimpleClass === HugeObj
-loop_count: 20000000
+ simple_class_eqq_module: |
+ SimpleClass === HugeObj
+ module_eqq_module: |
+ SomeModule === HugeObj
+loop_count: 10000000
diff --git a/benchmark/nilclass.yml b/benchmark/nilclass.yml
index fba67a5f6a..66234c4cdf 100644
--- a/benchmark/nilclass.yml
+++ b/benchmark/nilclass.yml
@@ -1,6 +1,16 @@
+prelude: |
+ def a = nil
benchmark:
+ rationalize:
+ nil.rationalize
+ to_c: |
+ nil.to_c
to_i: |
nil.to_i
to_f: |
nil.to_f
+ to_r: |
+ nil.to_r
+ splat: |
+ a(*nil)
loop_count: 100000
diff --git a/benchmark/object_allocate.yml b/benchmark/object_allocate.yml
index bdbd4536db..c6269923f0 100644
--- a/benchmark/object_allocate.yml
+++ b/benchmark/object_allocate.yml
@@ -45,4 +45,5 @@ benchmark:
allocate_kwarg_params: "KWArg.new(a: 1, b: 2, c: 3, d: 4)"
allocate_mixed_params: "Mixed.new(1, 2, c: 3, d: 4)"
allocate_no_params: "Object.new"
+ allocate_allocate: "Object.allocate"
loop_count: 100000
diff --git a/benchmark/object_class.yml b/benchmark/object_class.yml
new file mode 100644
index 0000000000..1e5409d1e2
--- /dev/null
+++ b/benchmark/object_class.yml
@@ -0,0 +1,40 @@
+prelude: |
+ def get_class(obj)
+ i = 10_000
+ while i > 0
+ i -= 1
+ # 100 times per loop
+ obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class;
+ obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class;
+ obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class;
+ obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class;
+ obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class;
+ obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class;
+ obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class;
+ obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class;
+ obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class;
+ obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class;
+ obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class; obj.class;
+ end
+ end
+
+ class Obj
+ end
+ obj = Obj.new
+
+ singleton = Obj.new
+ def singleton.bar
+ end
+
+ extended = Obj.new
+ 2.times do
+ extended.extend Module.new
+ end
+
+ immediate = 1.4
+benchmark:
+ obj: get_class(obj)
+ extended: get_class(extended)
+ singleton: get_class(singleton)
+ immediate: get_class(immediate)
+loop_count: 1000
diff --git a/benchmark/object_id.yml b/benchmark/object_id.yml
new file mode 100644
index 0000000000..2bd52b923f
--- /dev/null
+++ b/benchmark/object_id.yml
@@ -0,0 +1,4 @@
+benchmark:
+ baseline: "Object.new"
+ object_id: "Object.new.object_id"
+# loop_count: 100000
diff --git a/benchmark/ractor_string_fstring.yml b/benchmark/ractor_string_fstring.yml
new file mode 100644
index 0000000000..14b92d8fd8
--- /dev/null
+++ b/benchmark/ractor_string_fstring.yml
@@ -0,0 +1,18 @@
+type: lib/benchmark_driver/runner/ractor
+benchmark:
+ ractor_fstring_random: |
+ i = 0
+ str = "same".dup
+ while i < 2000000
+ -(i.to_s.freeze)
+ i += 1
+ end
+ ractor_fstring_same: |
+ i = 0
+ str = "same".dup
+ while i < 2000000
+ -str
+ i += 1
+ end
+loop_count: 1
+ractor: 4
diff --git a/benchmark/scan.yaml b/benchmark/scan.yaml
new file mode 100644
index 0000000000..62ad1d6862
--- /dev/null
+++ b/benchmark/scan.yaml
@@ -0,0 +1,16 @@
+prelude: |
+ $LOAD_PATH.unshift(File.expand_path("lib"))
+ require "strscan"
+ str = "test string"
+ scanner = StringScanner.new(str)
+ str = "test"
+ reg = /test/
+benchmark:
+ check(reg): |
+ scanner.check(reg)
+ check(str): |
+ scanner.check(str)
+ match?(reg): |
+ scanner.match?(reg)
+ match?(str): |
+ scanner.match?(str)
diff --git a/benchmark/search.yaml b/benchmark/search.yaml
new file mode 100644
index 0000000000..42a50c90e6
--- /dev/null
+++ b/benchmark/search.yaml
@@ -0,0 +1,16 @@
+prelude: |
+ $LOAD_PATH.unshift(File.expand_path("lib"))
+ require "strscan"
+ str = "test string"
+ scanner = StringScanner.new(str)
+ str = "string"
+ reg = /string/
+benchmark:
+ check_until(reg): |
+ scanner.check_until(reg)
+ check_until(str): |
+ scanner.check_until(str)
+ exist?(reg): |
+ scanner.exist?(reg)
+ exist?(str): |
+ scanner.exist?(str)
diff --git a/benchmark/set.yml b/benchmark/set.yml
new file mode 100644
index 0000000000..061509cb1f
--- /dev/null
+++ b/benchmark/set.yml
@@ -0,0 +1,261 @@
+prelude: |
+ # First 1000 digits of pi
+ pi = <<~END.gsub(/\D/, '')
+ 31415926535897932384626433832795028841971693993751058209749445923078164062862089
+ 98628034825342117067982148086513282306647093844609550582231725359408128481117450
+ 28410270193852110555964462294895493038196442881097566593344612847564823378678316
+ 52712019091456485669234603486104543266482133936072602491412737245870066063155881
+ 74881520920962829254091715364367892590360011330530548820466521384146951941511609
+ 43305727036575959195309218611738193261179310511854807446237996274956735188575272
+ 48912279381830119491298336733624406566430860213949463952247371907021798609437027
+ 70539217176293176752384674818467669405132000568127145263560827785771342757789609
+ 17363717872146844090122495343014654958537105079227968925892354201995611212902196
+ 08640344181598136297747713099605187072113499999983729780499510597317328160963185
+ 95024459455346908302642522308253344685035261931188171010003137838752886587533208
+ 38142061717766914730359825349042875546873115956286388235378759375195778185778053
+ 21712268066130019278766111959092164201989380952572010654505906988788448549
+ END
+ array1 = 10.times.flat_map do |i|
+ pi[i...].chars.each_slice(10).map(&:join)
+ end
+ array2 = array1.map(&:reverse)
+ array1.map!(&:to_i)
+ array2.map!(&:to_i)
+ a1 = array1[...10]
+ a2 = array1[...100]
+ a3 = array1
+ oa1 = array2[...10]
+ oa2 = array2[...100]
+ oa3 = array2
+ s0 = Set.new
+ s0 = Set.new
+ s1 = Set.new(a1)
+ s2 = Set.new(a2)
+ s3 = Set.new(a3)
+ o0 = Set.new
+ o1 = Set.new(array2[...10])
+ o2 = Set.new(array2[...100])
+ o3 = Set.new(array2)
+ d0 = s0.dup
+ d1 = s1.dup
+ d2 = s2.dup
+ d3 = s3.dup
+ ss1 = s1 - a1[-1..-1]
+ ss2 = s2 - a2[-1..-1]
+ ss3 = s3 - a3[-1..-1]
+ os1 = o1 - oa1[-1..-1]
+ os2 = o2 - oa2[-1..-1]
+ os3 = o3 - oa3[-1..-1]
+ member = a1.first
+ cbi = s0.dup.compare_by_identity
+ ns = Set[s3, o3, d3]
+ set_subclass = Class.new(Set)
+
+benchmark:
+ new_0: Set.new
+ new_10: Set.new(a1)
+ new_100: Set.new(a2)
+ new_1000: Set.new(a3)
+ aref_0: Set[]
+ aref_10: Set[*a1]
+ aref_100: Set[*a2]
+ aref_1000: Set[*a3]
+ amp_0: s0 & o0
+ amp_10: s1 & o1
+ amp_100: s2 & o2
+ amp_1000: s3 & o3
+ amp_same_0: s0 & d0
+ amp_same_10: s1 & d1
+ amp_same_100: s2 & d2
+ amp_same_1000: s3 & d3
+ minus_0: s0 - o0
+ minus_10: s1 - o1
+ minus_100: s2 - o2
+ minus_1000: s3 - o3
+ minus_same_0: s0 - d0
+ minus_same_10: s1 - d1
+ minus_same_100: s2 - d2
+ minus_same_1000: s3 - d3
+ spaceship_0: s0 <=> o0
+ spaceship_diff_10: s1 <=> o1
+ spaceship_diff_100: s2 <=> o2
+ spaceship_diff_1000: s2 <=> o3
+ spaceship_sub_10: s1 <=> ss1
+ spaceship_sub_100: s2 <=> ss2
+ spaceship_sub_1000: s2 <=> ss3
+ spaceship_sup_10: ss1 <=> s1
+ spaceship_sup_100: ss2 <=> s2
+ spaceship_sup_1000: ss2 <=> s3
+ eq_0: s0 == o0
+ eq_10: s1 == o1
+ eq_100: s2 == o2
+ eq_1000: s3 == o3
+ eq_same_0: s0 == d0
+ eq_same_10: s1 == d1
+ eq_same_100: s2 == d2
+ eq_same_1000: s3 == d3
+ xor_0: s0 ^ o0
+ xor_10: s1 ^ o1
+ xor_100: s2 ^ o2
+ xor_1000: s3 ^ o3
+ xor_same_0: s0 ^ d0
+ xor_same_10: s1 ^ d1
+ xor_same_100: s2 ^ d2
+ xor_same_1000: s3 ^ d3
+ pipe_0: s0 | o0
+ pipe_10: s1 | o1
+ pipe_100: s2 | o2
+ pipe_1000: s3 | o3
+ pipe_same_0: s0 | d0
+ pipe_same_10: s1 | d1
+ pipe_same_100: s2 | d2
+ pipe_same_1000: s3 | d3
+ add: a3.each { s0.add(it) }
+ add_exist: a3.each { s3.add(it) }
+ addq: a3.each { s0.add?(it) }
+ addq_exist: a3.each { s3.add?(it) }
+ classify_0: s0.classify { it }
+ classify_10: s1.classify { it & 2 }
+ classify_100: s2.classify { it & 8 }
+ classify_1000: s3.classify { it & 32 }
+ clear: s0.clear
+ collect_0: s0.collect! { it }
+ collect_10: s1.collect! { it }
+ collect_100: s2.collect! { it }
+ collect_1000: s3.collect! { it }
+ compare_by_identity_0: s0.dup.compare_by_identity
+ compare_by_identity_10: s1.dup.compare_by_identity
+ compare_by_identity_100: s2.dup.compare_by_identity
+ compare_by_identity_1000: s3.dup.compare_by_identity
+ compare_by_identityq_false: s0.compare_by_identity?
+ compare_by_identityq_true: cbi.compare_by_identity?
+ clone_0: s0.clone
+ clone_10: s1.clone
+ clone_100: s2.clone
+ clone_1000: s3.clone
+ delete: a3.each { s3.delete(it) }
+ delete_not_exist: a3.each { o3.delete(it) }
+ deleteq: a3.each { s3.delete?(it) }
+ deleteq_not_exist: a3.each { o3.delete?(it) }
+ delete_if_0: s0.delete_if { it }
+ delete_if_10: s1.delete_if { it & 2 == 0 }
+ delete_if_100: s2.delete_if { it & 2 == 0 }
+ delete_if_1000: s3.delete_if { it & 2 == 0 }
+ disjoint_0: s0.disjoint? o0
+ disjoint_10: s1.disjoint? o1
+ disjoint_100: s2.disjoint? o2
+ disjoint_1000: s3.disjoint? o3
+ disjoint_same_0: s0.disjoint? d0
+ disjoint_same_10: s1.disjoint? d1
+ disjoint_same_100: s2.disjoint? d2
+ disjoint_same_1000: s3.disjoint? d3
+ divide_1arity_0: s0.divide { true }
+ divide_1arity_10: s1.divide { it & 2 }
+ divide_1arity_100: s2.divide { it & 8 }
+ divide_1arity_1000: s3.divide { it & 32 }
+ divide_2arity_0: s0.divide { true }
+ divide_2arity_10: s1.divide { (_1 & 2) == (_2 & 2) }
+ divide_2arity_100: s2.divide { (_1 & 8) == (_2 & 8) }
+ divide_2arity_1000: s3.divide { (_1 & 32) == (_2 & 32) }
+ dup_0: s0.dup
+ dup_10: s1.dup
+ dup_100: s2.dup
+ dup_1000: s3.dup
+ each_0: s0.each { it }
+ each_10: s1.each { it }
+ each_100: s2.each { it }
+ each_1000: s3.each { it }
+ empty_true: s0.empty?
+ empty_false: s3.empty?
+ flatten: ns.flatten
+ flattenb: ns.flatten!
+ include_true_0: s0.include? member
+ include_true_10: s1.include? member
+ include_true_100: s2.include? member
+ include_true_1000: s3.include? member
+ include_false_0: s0.include?(-1)
+ include_false_10: s1.include?(-1)
+ include_false_100: s2.include?(-1)
+ include_false_1000: s3.include?(-1)
+ intersect_0: s0.intersect? o0
+ intersect_10: s1.intersect? o1
+ intersect_100: s2.intersect? o2
+ intersect_1000: s3.intersect? o3
+ intersect_same_0: s0.intersect? d0
+ intersect_same_10: s1.intersect? d1
+ intersect_same_100: s2.intersect? d2
+ intersect_same_1000: s3.intersect? d3
+ join_0: s0.join
+ join_10: s1.join
+ join_100: s2.join
+ join_1000: s3.join
+ join_arg_0: s0.join ""
+ join_arg_10: s1.join ""
+ join_arg_100: s2.join ""
+ join_arg_1000: s3.join ""
+ keep_if_0: s0.keep_if { it }
+ keep_if_10: s1.keep_if { it & 2 == 0 }
+ keep_if_100: s2.keep_if { it & 2 == 0 }
+ keep_if_1000: s3.keep_if { it & 2 == 0 }
+ merge_set: s0.dup.merge(s3, o3)
+ merge_enum: s0.dup.merge(array1, array2)
+ proper_subset_0: s0.proper_subset? s0
+ proper_subset_10: s1.proper_subset? ss1
+ proper_subset_100: s2.proper_subset? ss2
+ proper_subset_1000: s3.proper_subset? ss3
+ proper_subset_false_10: s1.proper_subset? os1
+ proper_subset_false_100: s2.proper_subset? os2
+ proper_subset_false_1000: s3.proper_subset? os3
+ proper_superset_0: s0.proper_superset? s0
+ proper_superset_10: ss1.proper_superset? s1
+ proper_superset_100: ss2.proper_superset? s2
+ proper_superset_1000: ss3.proper_superset? s3
+ proper_superset_false_10: os1.proper_superset? s1
+ proper_superset_false_100: os2.proper_superset? s2
+ proper_superset_false_1000: os3.proper_superset? s3
+ reject_0: s0.reject! { it }
+ reject_10: s1.reject! { it & 2 == 0 }
+ reject_100: s2.reject! { it & 2 == 0 }
+ reject_1000: s3.reject! { it & 2 == 0 }
+ replace_0: s = Set.new; array1.each { s.replace(s0) }
+ replace_10: s = Set.new; array1.each { s.replace(s1) }
+ replace_100: s = Set.new; array1.each { s.replace(s2) }
+ replace_1000: s = Set.new; array1.each { s.replace(s3) }
+ reset_0: s0.reset
+ reset_10: s1.reset
+ reset_100: s2.reset
+ reset_1000: s3.reset
+ select_0: s0.select! { it }
+ select_10: s1.select! { it & 2 == 0 }
+ select_100: s2.select! { it & 2 == 0 }
+ select_1000: s3.select! { it & 2 == 0 }
+ size_0: s0.size
+ size_10: s1.size
+ size_100: s2.size
+ size_1000: s3.size
+ subtract_set: s3.dup.subtract(os3)
+ subtract_enum: s3.dup.subtract(oa3)
+ subtract_same_set: s3.dup.subtract(s3)
+ subtract_same_enum: s3.dup.subtract(a3)
+ subset_0: s0.subset? s0
+ subset_10: s1.subset? ss1
+ subset_100: s2.subset? ss2
+ subset_1000: s3.subset? ss3
+ subset_false_10: s1.subset? os1
+ subset_false_100: s2.subset? os2
+ subset_false_1000: s3.subset? os3
+ superset_0: s0.superset? s0
+ superset_10: ss1.superset? s1
+ superset_100: ss2.superset? s2
+ superset_1000: ss3.superset? s3
+ superset_false_10: os1.superset? s1
+ superset_false_100: os2.superset? s2
+ superset_false_1000: os3.superset? s3
+ to_a_0: s0.to_a
+ to_a_10: s1.to_a
+ to_a_100: s2.to_a
+ to_a_1000: s3.to_a
+ to_set_0: s0.to_set
+ to_set_10: s1.to_set
+ to_set_100: s2.to_set
+ to_set_1000: s3.to_set
diff --git a/benchmark/string_casecmp.yml b/benchmark/string_casecmp.yml
index 2354040a04..88a3555c8a 100644
--- a/benchmark/string_casecmp.yml
+++ b/benchmark/string_casecmp.yml
@@ -20,7 +20,9 @@ benchmark:
casecmp-10: lstr10.casecmp(ustr10)
casecmp-100: lstr100.casecmp(ustr100)
casecmp-1000: lstr1000.casecmp(ustr1000)
+ casecmp-1000vs10: lstr1000.casecmp(ustr10)
casecmp-nonascii1: lnonascii1.casecmp(unonascii1)
casecmp-nonascii10: lnonascii10.casecmp(unonascii10)
casecmp-nonascii100: lnonascii100.casecmp(unonascii100)
casecmp-nonascii1000: lnonascii1000.casecmp(unonascii1000)
+ casecmp-nonascii1000vs10: lnonascii1000.casecmp(unonascii10)
diff --git a/benchmark/string_concat.yml b/benchmark/string_concat.yml
index da14692f5e..f11f95ee9a 100644
--- a/benchmark/string_concat.yml
+++ b/benchmark/string_concat.yml
@@ -45,7 +45,7 @@ benchmark:
"#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \
"#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \
"#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}"
- interpolation_same_size_pool: |
+ interpolation_same_heap: |
buffer = "#{SHORT}#{SHORT}"
- interpolation_switching_size_pools: |
+ interpolation_switching_heaps: |
buffer = "#{SHORT}#{LONG}"
diff --git a/benchmark/string_fstring.yml b/benchmark/string_fstring.yml
new file mode 100644
index 0000000000..cafef1f3fe
--- /dev/null
+++ b/benchmark/string_fstring.yml
@@ -0,0 +1,16 @@
+benchmark:
+ fstring_random: |
+ i = 0
+ str = "same".dup
+ while i < 5_000_000
+ -(i.to_s.freeze)
+ i += 1
+ end
+ fstring_same: |
+ i = 0
+ str = "same".dup
+ while i < 10_000_000
+ -str
+ i += 1
+ end
+loop_count: 1
diff --git a/benchmark/string_gsub.yml b/benchmark/string_gsub.yml
new file mode 100644
index 0000000000..0f964337dd
--- /dev/null
+++ b/benchmark/string_gsub.yml
@@ -0,0 +1,43 @@
+prelude: |
+ # frozen_string_literal: true
+ STR = ((("a" * 31) + "<") * 1000).freeze
+ STR_UNICODE = ((("a" * 30) + "\u2028") * 1000).freeze
+ ESCAPED_CHARS_BINARY = {
+ "\u2028".b => '\u2028'.b,
+ "\u2029".b => '\u2029'.b,
+ ">".b => '\u003e'.b.freeze,
+ "<".b => '\u003c'.b.freeze,
+ "&".b => '\u0026'.b.freeze,
+ }
+ BINARY_PATTERN = Regexp.union(ESCAPED_CHARS_BINARY.keys)
+
+ ESCAPED_CHARS = {
+ "\u2028" => '\u2028',
+ "\u2029" => '\u2029',
+ ">" => '\u003e',
+ "<" => '\u003c',
+ "&" => '\u0026',
+ }
+ ESCAPE_PATTERN = Regexp.union(ESCAPED_CHARS.keys)
+
+
+benchmark:
+ escape: |
+ str = STR.dup
+ str.gsub!(ESCAPE_PATTERN, ESCAPED_CHARS)
+ str
+
+ escape_bin: |
+ str = STR.b
+ str.gsub!(BINARY_PATTERN, ESCAPED_CHARS_BINARY)
+ str.force_encoding(Encoding::UTF_8)
+
+ escape_utf8: |
+ str = STR_UNICODE.dup
+ str.gsub!(ESCAPE_PATTERN, ESCAPED_CHARS)
+ str
+
+ escape_utf8_bin: |
+ str = STR_UNICODE.b
+ str.gsub!(BINARY_PATTERN, ESCAPED_CHARS_BINARY)
+ str.force_encoding(Encoding::UTF_8)
diff --git a/benchmark/struct_accessor.yml b/benchmark/struct_accessor.yml
index 61176cfdd4..d95240e2dd 100644
--- a/benchmark/struct_accessor.yml
+++ b/benchmark/struct_accessor.yml
@@ -1,5 +1,12 @@
prelude: |
C = Struct.new(:x) do
+ def initialize(...)
+ super
+ @ivar = 42
+ end
+
+ attr_accessor :ivar
+
class_eval <<-END
def r
#{'x;'*256}
@@ -15,11 +22,16 @@ prelude: |
m = method(:x=)
#{'m.call(nil);'*256}
end
+ def r_ivar
+ #{'ivar;'*256}
+ end
END
end
+ C.new(nil) # ensure common shape is known
obj = C.new(nil)
benchmark:
member_reader: "obj.r"
member_writer: "obj.w"
member_reader_method: "obj.rm"
member_writer_method: "obj.wm"
+ ivar_reader: "obj.r_ivar"
diff --git a/benchmark/time_now.yml b/benchmark/time_now.yml
index f6d6a31489..9336877cd4 100644
--- a/benchmark/time_now.yml
+++ b/benchmark/time_now.yml
@@ -1,3 +1,4 @@
benchmark:
- 'Time.now'
- 'Time.now(in: "+09:00")'
+ - 'Time.now.year'
diff --git a/benchmark/time_strftime.yml b/benchmark/time_strftime.yml
new file mode 100644
index 0000000000..28f62aec87
--- /dev/null
+++ b/benchmark/time_strftime.yml
@@ -0,0 +1,7 @@
+prelude: |
+ # frozen_string_literal: true
+ time = Time.now
+benchmark:
+ - time.strftime("%FT%T") # 19B
+ - time.strftime("%FT%T.%3N") # 23B
+ - time.strftime("%FT%T.%6N") # 26B
diff --git a/benchmark/time_xmlschema.yml b/benchmark/time_xmlschema.yml
new file mode 100644
index 0000000000..654e5cfcbc
--- /dev/null
+++ b/benchmark/time_xmlschema.yml
@@ -0,0 +1,27 @@
+prelude: |
+ # frozen_string_literal
+ unless Time.method_defined?(:xmlschema)
+ class Time
+ def xmlschema(fraction_digits=0)
+ fraction_digits = fraction_digits.to_i
+ s = strftime("%FT%T")
+ if fraction_digits > 0
+ s << strftime(".%#{fraction_digits}N")
+ end
+ s << (utc? ? 'Z' : strftime("%:z"))
+ end
+ end
+ end
+ time = Time.now
+ utc_time = Time.now.utc
+ fraction_sec = Time.at(123456789.quo(9999999999)).getlocal("+09:00")
+ future_time = Time.utc(10000)
+benchmark:
+ - time.xmlschema
+ - utc_time.xmlschema
+ - time.xmlschema(6)
+ - utc_time.xmlschema(6)
+ - time.xmlschema(9)
+ - utc_time.xmlschema(9)
+ - fraction_sec.xmlschema(10)
+ - future_time.xmlschema
diff --git a/benchmark/vm_ivar_get.yml b/benchmark/vm_ivar_get.yml
index 9174af6965..1e0dad665f 100644
--- a/benchmark/vm_ivar_get.yml
+++ b/benchmark/vm_ivar_get.yml
@@ -1,17 +1,75 @@
prelude: |
class Example
def initialize
+ @levar = 1
@v0 = 1
@v1 = 2
@v3 = 3
+ end
+
+ def get_value_loop
+ sum = 0
+
+ i = 0
+ while i < 100_000
+ # 10 times to de-emphasize loop overhead
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ i += 1
+ end
+
+ return sum
+ end
+
+ @levar = 1
+ @v0 = 1
+ @v1 = 2
+ @v3 = 3
+
+ def self.get_value_loop
+ sum = 0
+
+ i = 0
+ while i < 100_000
+ # 10 times to de-emphasize loop overhead
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ sum += @levar
+ i += 1
+ end
+
+ return sum
+ end
+ end
+
+ class GenExample < Time
+ def initialize
@levar = 1
+ @v0 = 1
+ @v1 = 2
+ @v3 = 3
end
def get_value_loop
sum = 0
i = 0
- while i < 1000000
+ while i < 100_000
# 10 times to de-emphasize loop overhead
sum += @levar
sum += @levar
@@ -31,7 +89,12 @@ prelude: |
end
obj = Example.new
+ gen = GenExample.new
benchmark:
- vm_ivar_get: |
+ vm_ivar_get_on_obj: |
obj.get_value_loop
+ vm_ivar_get_on_class: |
+ Example.get_value_loop
+ vm_ivar_get_on_generic: |
+ gen.get_value_loop
loop_count: 100
diff --git a/benchmark/vm_ivar_set_on_instance.yml b/benchmark/vm_ivar_set_on_instance.yml
index 91857b7742..6ce53a86ec 100644
--- a/benchmark/vm_ivar_set_on_instance.yml
+++ b/benchmark/vm_ivar_set_on_instance.yml
@@ -1,16 +1,44 @@
prelude: |
class TheClass
def initialize
+ @levar = 1
@v0 = 1
@v1 = 2
@v3 = 3
+ end
+
+ def set_value_loop
+ # 100k
+ i = 0
+ while i < 100_000
+ # 10 times to de-emphasize loop overhead
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ i += 1
+ end
+ end
+ end
+
+ class Generic < Time
+ def initialize
@levar = 1
+ @v0 = 1
+ @v1 = 2
+ @v3 = 3
end
def set_value_loop
- # 1M
+ # 100k
i = 0
- while i < 1000000
+ while i < 100_000
# 10 times to de-emphasize loop overhead
@levar = i
@levar = i
@@ -28,8 +56,39 @@ prelude: |
end
obj = TheClass.new
+ gen_obj = Generic.new
+
+ class SomeClass
+ @levar = 1
+ @v0 = 1
+ @v1 = 2
+ @v3 = 3
+
+ def self.set_value_loop
+ # 100k
+ i = 0
+ while i < 100_000
+ # 10 times to de-emphasize loop overhead
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ @levar = i
+ i += 1
+ end
+ end
+ end
benchmark:
vm_ivar_set_on_instance: |
obj.set_value_loop
+ vm_ivar_set_on_generic: |
+ gen_obj.set_value_loop
+ vm_ivar_set_on_class: |
+ SomeClass.set_value_loop
loop_count: 100
diff --git a/bignum.c b/bignum.c
index 4b01316d22..ee2fa1ed30 100644
--- a/bignum.c
+++ b/bignum.c
@@ -30,9 +30,6 @@
# define USE_GMP 0
#endif
#endif
-#if USE_GMP
-# include <gmp.h>
-#endif
#include "id.h"
#include "internal.h"
@@ -48,6 +45,15 @@
#include "ruby/util.h"
#include "ruby_assert.h"
+#if USE_GMP
+RBIMPL_WARNING_PUSH()
+# ifdef _MSC_VER
+RBIMPL_WARNING_IGNORED(4146) /* for mpn_neg() */
+# endif
+# include <gmp.h>
+RBIMPL_WARNING_POP()
+#endif
+
static const bool debug_integer_pack = (
#ifdef DEBUG_INTEGER_PACK
DEBUG_INTEGER_PACK+0
@@ -73,7 +79,6 @@ STATIC_ASSERT(sizeof_bdigit_and_dbl, SIZEOF_BDIGIT*2 <= SIZEOF_BDIGIT_DBL);
STATIC_ASSERT(bdigit_signedness, 0 < (BDIGIT)-1);
STATIC_ASSERT(bdigit_dbl_signedness, 0 < (BDIGIT_DBL)-1);
STATIC_ASSERT(bdigit_dbl_signed_signedness, 0 > (BDIGIT_DBL_SIGNED)-1);
-STATIC_ASSERT(rbignum_embed_len_max, BIGNUM_EMBED_LEN_MAX <= (BIGNUM_EMBED_LEN_MASK >> BIGNUM_EMBED_LEN_SHIFT));
#if SIZEOF_BDIGIT < SIZEOF_LONG
STATIC_ASSERT(sizeof_long_and_sizeof_bdigit, SIZEOF_LONG % SIZEOF_BDIGIT == 0);
@@ -2693,7 +2698,7 @@ bigdivrem_restoring(BDIGIT *zds, size_t zn, BDIGIT *yds, size_t yn)
if (bds.zn > 10000 || bds.yn > 10000) {
retry:
bds.stop = Qfalse;
- rb_nogvl(bigdivrem1, &bds, rb_big_stop, &bds, RB_NOGVL_UBF_ASYNC_SAFE);
+ rb_nogvl(bigdivrem1, &bds, rb_big_stop, &bds, RB_NOGVL_UBF_ASYNC_SAFE | RB_NOGVL_OFFLOAD_SAFE);
if (bds.stop == Qtrue) {
/* execute trap handler, but exception was not raised. */
@@ -2984,25 +2989,56 @@ rb_cmpint(VALUE val, VALUE a, VALUE b)
((l) << BIGNUM_EMBED_LEN_SHIFT)) : \
(void)(RBIGNUM(b)->as.heap.len = (l)))
+static size_t
+big_embed_capa(VALUE big)
+{
+ size_t size = rb_gc_obj_slot_size(big) - offsetof(struct RBignum, as.ary);
+ RUBY_ASSERT(size % sizeof(BDIGIT) == 0);
+ size_t capa = size / sizeof(BDIGIT);
+ RUBY_ASSERT(capa <= BIGNUM_EMBED_LEN_MAX);
+ return capa;
+}
+
+static size_t
+big_embed_size(size_t capa)
+{
+ size_t size = offsetof(struct RBignum, as.ary) + (sizeof(BDIGIT) * capa);
+ if (size < sizeof(struct RBignum)) {
+ size = sizeof(struct RBignum);
+ }
+ return size;
+}
+
+static bool
+big_embeddable_p(size_t capa)
+{
+ if (capa > BIGNUM_EMBED_LEN_MAX) {
+ return false;
+ }
+ return rb_gc_size_allocatable_p(big_embed_size(capa));
+}
+
static void
rb_big_realloc(VALUE big, size_t len)
{
BDIGIT *ds;
+ size_t embed_capa = big_embed_capa(big);
+
if (BIGNUM_EMBED_P(big)) {
- if (BIGNUM_EMBED_LEN_MAX < len) {
+ if (embed_capa < len) {
ds = ALLOC_N(BDIGIT, len);
- MEMCPY(ds, RBIGNUM(big)->as.ary, BDIGIT, BIGNUM_EMBED_LEN_MAX);
+ MEMCPY(ds, RBIGNUM(big)->as.ary, BDIGIT, embed_capa);
RBIGNUM(big)->as.heap.len = BIGNUM_LEN(big);
RBIGNUM(big)->as.heap.digits = ds;
FL_UNSET_RAW(big, BIGNUM_EMBED_FLAG);
}
}
else {
- if (len <= BIGNUM_EMBED_LEN_MAX) {
+ if (len <= embed_capa) {
ds = RBIGNUM(big)->as.heap.digits;
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));
+ (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)RBIGNUM(big)->as.ary, embed_capa * sizeof(BDIGIT));
if (ds) {
MEMCPY(RBIGNUM(big)->as.ary, ds, BDIGIT, len);
xfree(ds);
@@ -3012,7 +3048,7 @@ rb_big_realloc(VALUE big, size_t len)
if (BIGNUM_LEN(big) == 0) {
RBIGNUM(big)->as.heap.digits = ALLOC_N(BDIGIT, len);
}
- else {
+ else if (BIGNUM_LEN(big) < len) {
REALLOC_N(RBIGNUM(big)->as.heap.digits, BDIGIT, len);
}
}
@@ -3029,16 +3065,24 @@ rb_big_resize(VALUE big, size_t len)
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), sizeof(struct RBignum), 0);
- VALUE bigv = (VALUE)big;
- BIGNUM_SET_SIGN(bigv, sign);
- if (len <= BIGNUM_EMBED_LEN_MAX) {
- FL_SET_RAW(bigv, BIGNUM_EMBED_FLAG);
+ VALUE bigv;
+
+ if (big_embeddable_p(len)) {
+ size_t size = big_embed_size(len);
+ RUBY_ASSERT(rb_gc_size_allocatable_p(size));
+ NEWOBJ_OF(big, struct RBignum, klass,
+ T_BIGNUM | BIGNUM_EMBED_FLAG | (RGENGC_WB_PROTECTED_BIGNUM ? FL_WB_PROTECTED : 0),
+ size, 0);
+ bigv = (VALUE)big;
+ BIGNUM_SET_SIGN(bigv, sign);
BIGNUM_SET_LEN(bigv, len);
- (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)big->as.ary, sizeof(big->as.ary));
+ (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)big->as.ary, len * sizeof(BDIGIT));
}
else {
+ NEWOBJ_OF(big, struct RBignum, klass,
+ T_BIGNUM | (RGENGC_WB_PROTECTED_BIGNUM ? FL_WB_PROTECTED : 0), sizeof(struct RBignum), 0);
+ bigv = (VALUE)big;
+ BIGNUM_SET_SIGN(bigv, sign);
big->as.heap.digits = ALLOC_N(BDIGIT, len);
big->as.heap.len = len;
}
@@ -3049,7 +3093,9 @@ bignew_1(VALUE klass, size_t len, int sign)
VALUE
rb_big_new(size_t len, int sign)
{
- return bignew(len, sign != 0);
+ VALUE obj = bignew(len, sign != 0);
+ memset(BIGNUM_DIGITS(obj), 0, len * sizeof(BDIGIT));
+ return obj;
}
VALUE
@@ -4469,7 +4515,7 @@ rb_str2big_gmp(VALUE arg, int base, int badcheck)
#if HAVE_LONG_LONG
-static VALUE
+VALUE
rb_ull2big(unsigned LONG_LONG n)
{
long i;
@@ -4491,7 +4537,7 @@ rb_ull2big(unsigned LONG_LONG n)
return big;
}
-static VALUE
+VALUE
rb_ll2big(LONG_LONG n)
{
long neg = 0;
@@ -4529,7 +4575,7 @@ rb_ll2inum(LONG_LONG n)
#endif /* HAVE_LONG_LONG */
#ifdef HAVE_INT128_T
-static VALUE
+VALUE
rb_uint128t2big(uint128_t n)
{
long i;
@@ -5908,6 +5954,8 @@ bigsq(VALUE x)
BDIGIT *xds, *zds;
xn = BIGNUM_LEN(x);
+ if (MUL_OVERFLOW_LONG_P(2, xn))
+ rb_raise(rb_eArgError, "square overflow");
zn = 2 * xn;
z = bignew(zn, 1);
@@ -5936,6 +5984,8 @@ bigmul0(VALUE x, VALUE y)
xn = BIGNUM_LEN(x);
yn = BIGNUM_LEN(y);
+ if (ADD_OVERFLOW_LONG_P(xn, yn))
+ rb_raise(rb_eArgError, "multiplication overflow");
zn = xn + yn;
z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y));
@@ -6281,8 +6331,7 @@ rb_big_pow(VALUE x, VALUE y)
y = bignorm(y);
if (FIXNUM_P(y))
goto again;
- rb_warn("in a**b, b may be too big");
- d = rb_big2dbl(y);
+ rb_raise(rb_eArgError, "exponent is too large");
}
else if (FIXNUM_P(y)) {
yy = FIX2LONG(y);
@@ -6298,13 +6347,17 @@ rb_big_pow(VALUE x, VALUE y)
VALUE z = 0;
SIGNED_VALUE mask;
const size_t xbits = rb_absint_numwords(x, 1, NULL);
- const size_t BIGLEN_LIMIT = 32*1024*1024;
+#if SIZEOF_SIZE_T == 4
+ const size_t BIGLEN_LIMIT = 1ULL << 31; // 2 GB
+#else // SIZEOF_SIZE_T == 8
+ const size_t BIGLEN_LIMIT = 1ULL << 34; // 16 GB
+#endif
if (xbits == (size_t)-1 ||
(xbits > BIGLEN_LIMIT) ||
+ MUL_OVERFLOW_LONG_P(yy, xbits) ||
(xbits * yy > BIGLEN_LIMIT)) {
- rb_warn("in a**b, b may be too big");
- d = (double)yy;
+ rb_raise(rb_eArgError, "exponent is too large");
}
else {
for (mask = FIXNUM_MAX + 1; mask; mask >>= 1) {
@@ -6333,7 +6386,7 @@ bigand_int(VALUE x, long xn, BDIGIT hibitsx, long y)
BDIGIT hibitsy;
if (y == 0) return INT2FIX(0);
- if (xn == 0) return hibitsx ? LONG2NUM(y) : 0;
+ if (xn == 0) return hibitsx ? LONG2NUM(y) : INT2FIX(0);
hibitsy = 0 <= y ? 0 : BDIGMAX;
xds = BDIGITS(x);
#if SIZEOF_BDIGIT >= SIZEOF_LONG
@@ -6745,6 +6798,73 @@ rb_big_aref(VALUE x, VALUE y)
}
VALUE
+rb_big_aref2(VALUE x, VALUE beg, VALUE len)
+{
+ BDIGIT *xds, *vds;
+ VALUE v;
+ size_t copy_begin, xn, shift;
+ ssize_t begin, length, end;
+ bool negative_add_one;
+
+ beg = rb_to_int(beg);
+ len = rb_to_int(len);
+ length = NUM2SSIZET(len);
+ begin = NUM2SSIZET(beg);
+ end = NUM2SSIZET(rb_int_plus(beg, len));
+ shift = begin < 0 ? -begin : 0;
+ xn = BIGNUM_LEN(x);
+ xds = BDIGITS(x);
+
+ if (length < 0) return rb_big_rshift(x, beg);
+ if (length == 0 || end <= 0) return INT2FIX(0);
+ if (begin < 0) begin = 0;
+
+ if ((size_t)(end - 1) / BITSPERDIG >= xn) {
+ /* end > xn * BITSPERDIG */
+ end = xn * BITSPERDIG;
+ }
+
+ if ((size_t)begin / BITSPERDIG < xn) {
+ /* begin < xn * BITSPERDIG */
+ size_t shift_bits, copy_end;
+ copy_begin = begin / BITSPERDIG;
+ shift_bits = begin % BITSPERDIG;
+ copy_end = (end - 1) / BITSPERDIG + 1;
+ v = bignew(copy_end - copy_begin, 1);
+ vds = BDIGITS(v);
+ MEMCPY(vds, xds + copy_begin, BDIGIT, copy_end - copy_begin);
+ negative_add_one = (vds[0] & ((1 << shift_bits) - 1)) == 0;
+ v = bignorm(v);
+ if (shift_bits) v = rb_int_rshift(v, SIZET2NUM(shift_bits));
+ }
+ else {
+ /* Out of range */
+ v = INT2FIX(0);
+ negative_add_one = false;
+ copy_begin = begin = end = 0;
+ }
+
+ if (BIGNUM_NEGATIVE_P(x)) {
+ size_t mask_size = length - shift;
+ VALUE mask = rb_int_minus(rb_int_lshift(INT2FIX(1), SIZET2NUM(mask_size)), INT2FIX(1));
+ v = rb_int_xor(v, mask);
+ for (size_t i = 0; negative_add_one && i < copy_begin; i++) {
+ if (xds[i]) negative_add_one = false;
+ }
+ if (negative_add_one) v = rb_int_plus(v, INT2FIX(1));
+ v = rb_int_and(v, mask);
+ }
+ else {
+ size_t mask_size = (size_t)end - begin;
+ VALUE mask = rb_int_minus(rb_int_lshift(INT2FIX(1), SIZET2NUM(mask_size)), INT2FIX(1));
+ v = rb_int_and(v, mask);
+ }
+ RB_GC_GUARD(x);
+ if (shift) v = rb_int_lshift(v, SSIZET2NUM(shift));
+ return v;
+}
+
+VALUE
rb_big_hash(VALUE x)
{
st_index_t hash;
@@ -6950,7 +7070,7 @@ int_pow_tmp3(VALUE x, VALUE y, VALUE m, int nega_flg)
zn = mn;
z = bignew(zn, 1);
bary_powm_gmp(BDIGITS(z), zn, BDIGITS(x), xn, BDIGITS(y), yn, BDIGITS(m), mn);
- if (nega_flg & BIGNUM_POSITIVE_P(z)) {
+ if (nega_flg && BIGNUM_POSITIVE_P(z) && !BIGZEROP(z)) {
z = rb_big_minus(z, m);
}
RB_GC_GUARD(x);
@@ -6978,7 +7098,7 @@ int_pow_tmp3(VALUE x, VALUE y, VALUE m, int nega_flg)
x = rb_int_modulo(x, m);
}
- if (nega_flg && rb_int_positive_p(tmp)) {
+ if (nega_flg && rb_int_positive_p(tmp) && !rb_int_zero_p(tmp)) {
tmp = rb_int_minus(tmp, m);
}
return tmp;
@@ -7090,6 +7210,11 @@ rb_int_powm(int const argc, VALUE * const argv, VALUE const num)
rb_raise(rb_eTypeError, "Integer#pow() 2nd argument not allowed unless all arguments are integers");
}
+ if (rb_int_zero_p(a) && !rb_int_zero_p(b)) {
+ /* shortcut; 0**x => 0 except for x == 0 */
+ return INT2FIX(0);
+ }
+
if (rb_int_negative_p(m)) {
m = rb_int_uminus(m);
nega_flg = 1;
diff --git a/bootstraptest/runner.rb b/bootstraptest/runner.rb
index 120b78246c..04de0c93b9 100755
--- a/bootstraptest/runner.rb
+++ b/bootstraptest/runner.rb
@@ -16,6 +16,7 @@ rescue LoadError
$:.unshift File.join(File.dirname(__FILE__), '../lib')
retry
end
+require_relative '../tool/lib/test/jobserver'
if !Dir.respond_to?(:mktmpdir)
# copied from lib/tmpdir.rb
@@ -78,6 +79,7 @@ bt = Struct.new(:ruby,
:platform,
:timeout,
:timeout_scale,
+ :launchable_test_reports
)
BT = Class.new(bt) do
def indent=(n)
@@ -109,35 +111,7 @@ BT = Class.new(bt) do
def wn=(wn)
unless wn == 1
- if /(?:\A|\s)--jobserver-(?:auth|fds)=(?:(\d+),(\d+)|fifo:((?:\\.|\S)+))/ =~ ENV.delete("MAKEFLAGS")
- begin
- if fifo = $3
- fifo.gsub!(/\\(?=.)/, '')
- r = File.open(fifo, IO::RDONLY|IO::NONBLOCK|IO::BINARY)
- w = File.open(fifo, IO::WRONLY|IO::NONBLOCK|IO::BINARY)
- else
- r = IO.for_fd($1.to_i(10), "rb", autoclose: false)
- w = IO.for_fd($2.to_i(10), "wb", autoclose: false)
- end
- rescue
- r.close if r
- else
- r.close_on_exec = true
- w.close_on_exec = true
- tokens = r.read_nonblock(wn > 0 ? wn : 1024, exception: false)
- r.close
- if String === tokens
- tokens.freeze
- auth = w
- w = nil
- at_exit {auth << tokens; auth.close}
- wn = tokens.size + 1
- else
- w.close
- wn = 1
- end
- end
- end
+ wn = Test::JobServer.max_jobs(wn > 0 ? wn : 1024, ENV.delete("MAKEFLAGS")) || wn
if wn <= 0
require 'etc'
wn = [Etc.nprocessors / 2, 1].max
@@ -162,7 +136,11 @@ def main
BT.tty = nil
BT.quiet = false
BT.timeout = 180
- BT.timeout_scale = (defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? ? 3 : 1) # for --jit-wait
+ BT.timeout_scale = 1
+ if (ts = (ENV["RUBY_TEST_TIMEOUT_SCALE"] || ENV["RUBY_TEST_SUBPROCESS_TIMEOUT_SCALE"]).to_i) > 1
+ BT.timeout_scale *= ts
+ end
+
# BT.wn = 1
dir = nil
quiet = false
@@ -225,6 +203,31 @@ End
exit true
when /\A-j/
true
+ when /--launchable-test-reports=(.*)/
+ if File.exist?($1)
+ # To protect files from overwritten, do nothing when the file exists.
+ return true
+ end
+
+ begin
+ require_relative '../tool/lib/launchable'
+ rescue LoadError
+ # The following error sometimes happens, so we're going to skip writing Launchable report files in this case.
+ #
+ # ```
+ # /tmp/tmp.bISss9CtXZ/.ext/common/json/ext.rb:15:in 'Kernel#require':
+ # /tmp/tmp.bISss9CtXZ/.ext/x86_64-linux/json/ext/parser.so:
+ # undefined symbol: ruby_abi_version - ruby_abi_version (LoadError)
+ # ```
+ #
+ return true
+ end
+ BT.launchable_test_reports = writer = Launchable::JsonStreamWriter.new($1)
+ writer.write_array('testCases')
+ at_exit {
+ writer.close
+ }
+ true
else
false
end
@@ -234,7 +237,7 @@ End
end
tests ||= ARGV
tests = Dir.glob("#{File.dirname($0)}/test_*.rb").sort if tests.empty?
- pathes = tests.map {|path| File.expand_path(path) }
+ paths = tests.map {|path| File.expand_path(path) }
BT.progress = %w[- \\ | /]
BT.progress_bs = "\b" * BT.progress[0].size
@@ -268,7 +271,7 @@ End
if defined?(RUBY_DESCRIPTION)
puts "Driver is #{RUBY_DESCRIPTION}"
elsif defined?(RUBY_PATCHLEVEL)
- puts "Driver is ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}#{RUBY_PLATFORM}) [#{RUBY_PLATFORM}]"
+ puts "Driver is ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}#{RUBY_PATCHLEVEL}) [#{RUBY_PLATFORM}]"
else
puts "Driver is ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}]"
end
@@ -278,7 +281,7 @@ End
end
in_temporary_working_directory(dir) do
- exec_test pathes
+ exec_test paths
end
end
@@ -290,8 +293,8 @@ def erase(e = true)
end
end
-def load_test pathes
- pathes.each do |path|
+def load_test paths
+ paths.each do |path|
load File.expand_path(path)
end
end
@@ -324,6 +327,7 @@ def concurrent_exec_test
begin
while BT.wn != term_wn
if r = rq.pop
+ BT_STATE.count += 1
case
when BT.quiet
when BT.tty
@@ -341,13 +345,66 @@ def concurrent_exec_test
end
end
-def exec_test(pathes)
+##
+# Module for writing a test file for uploading test results into Launchable.
+# In bootstraptest, we aggregate the test results based on file level.
+module Launchable
+ @@last_test_name = nil
+ @@failure_log = ''
+ @@duration = 0
+
+ def show_progress(message = '')
+ faildesc, t = super
+
+ if writer = BT.launchable_test_reports
+ if faildesc
+ @@failure_log += faildesc
+ end
+ repo_path = File.expand_path("#{__dir__}/../")
+ relative_path = File.join(__dir__, self.path).delete_prefix("#{repo_path}/")
+ if @@last_test_name != nil && @@last_test_name != relative_path
+ # The test path is a URL-encoded representation.
+ # https://github.com/launchableinc/cli/blob/v1.81.0/launchable/testpath.py#L18
+ test_path = "#{encode_test_path_component("file")}=#{encode_test_path_component(@@last_test_name)}"
+ if @@failure_log.size > 0
+ status = 'TEST_FAILED'
+ else
+ status = 'TEST_PASSED'
+ end
+ writer.write_object(
+ {
+ testPath: test_path,
+ status: status,
+ duration: t,
+ createdAt: Time.now.to_s,
+ stderr: @@failure_log,
+ stdout: nil,
+ data: {
+ lineNumber: self.lineno
+ }
+ }
+ )
+ @@duration = 0
+ @@failure_log = ''
+ end
+ @@last_test_name = relative_path
+ @@duration += t
+ end
+ end
+
+ private
+ def encode_test_path_component component
+ component.to_s.gsub('%', '%25').gsub('=', '%3D').gsub('#', '%23').gsub('&', '%26')
+ end
+end
+
+def exec_test(paths)
# setup
- load_test pathes
+ load_test paths
BT_STATE.count = 0
BT_STATE.error = 0
BT.columns = 0
- BT.width = pathes.map {|path| File.basename(path).size}.max + 2
+ BT.width = paths.map {|path| File.basename(path).size}.max + 2
# execute tests
if BT.wn > 1
@@ -417,6 +474,7 @@ def target_platform
end
class Assertion < Struct.new(:src, :path, :lineno, :proc)
+ prepend Launchable
@count = 0
@all = Hash.new{|h, k| h[k] = []}
@errbuf = []
@@ -491,9 +549,9 @@ class Assertion < Struct.new(:src, :path, :lineno, :proc)
$stderr.print "#{BT.progress_bs}#{BT.progress[BT_STATE.count % BT.progress.size]}"
end
- t = Time.now if BT.verbose
+ t = Time.now if BT.verbose || BT.launchable_test_reports
faildesc, errout = with_stderr {yield}
- t = Time.now - t if BT.verbose
+ t = Time.now - t if BT.verbose || BT.launchable_test_reports
if !faildesc
# success
@@ -520,6 +578,8 @@ class Assertion < Struct.new(:src, :path, :lineno, :proc)
$stderr.printf("%-*s%s", BT.width, path, BT.progress[BT_STATE.count % BT.progress.size])
end
end
+
+ [faildesc, t]
rescue Interrupt
$stderr.puts "\##{@id} #{path}:#{lineno}"
raise
@@ -538,6 +598,8 @@ class Assertion < Struct.new(:src, :path, :lineno, :proc)
end
end
+ class Timeout < StandardError; end
+
def get_result_string(opt = '', timeout: BT.timeout, **argh)
if BT.ruby
timeout = BT.apply_timeout_scale(timeout)
@@ -547,7 +609,11 @@ class Assertion < Struct.new(:src, :path, :lineno, :proc)
out = IO.popen("#{BT.ruby} -W0 #{opt} #{filename}", **kw)
pid = out.pid
th = Thread.new {out.read.tap {Process.waitpid(pid); out.close}}
- th.value if th.join(timeout)
+ if th.join(timeout)
+ th.value
+ else
+ Timeout.new("timed out after #{timeout} seconds")
+ end
ensure
raise Interrupt if $? and $?.signaled? && $?.termsig == Signal.list["INT"]
@@ -644,23 +710,19 @@ def assert_normal_exit(testsrc, *rest, timeout: BT.timeout, **opt)
timeout_signaled = false
logfile = "assert_normal_exit.#{as.path}.#{as.lineno}.log"
- begin
- err = open(logfile, "w")
- io = IO.popen("#{BT.ruby} -W0 #{filename}", err: err)
- pid = io.pid
- th = Thread.new {
- io.read
- io.close
- $?
- }
- if !th.join(timeout)
- Process.kill :KILL, pid
- timeout_signaled = true
- end
- status = th.value
- ensure
- err.close
+ io = IO.popen("#{BT.ruby} -W0 #{filename}", err: logfile)
+ pid = io.pid
+ th = Thread.new {
+ io.read
+ io.close
+ $?
+ }
+ if !th.join(timeout)
+ Process.kill :KILL, pid
+ timeout_signaled = true
end
+ status = th.value
+
if status && status.signaled?
signo = status.termsig
signame = Signal.list.invert[signo]
@@ -745,6 +807,8 @@ end
def pretty(src, desc, result)
src = src.sub(/\A\s*\n/, '')
+ lines = src.lines
+ src = lines[0..20].join + "(...snip)\n" if lines.size > 20
(/\n/ =~ src ? "\n#{adjust_indent(src)}" : src) + " #=> #{desc}"
end
@@ -806,9 +870,8 @@ def yjit_enabled?
ENV.key?('RUBY_YJIT_ENABLE') || ENV.fetch('RUN_OPTS', '').include?('yjit') || BT.ruby.include?('yjit')
end
-def rjit_enabled?
- # Don't check `RubyVM::RJIT.enabled?`. On btest-bruby, target Ruby != runner Ruby.
- ENV.fetch('RUN_OPTS', '').include?('rjit')
+def zjit_enabled?
+ ENV.key?('RUBY_ZJIT_ENABLE') || ENV.fetch('RUN_OPTS', '').include?('zjit') || BT.ruby.include?('zjit')
end
exit main
diff --git a/bootstraptest/test_autoload.rb b/bootstraptest/test_autoload.rb
index 9e0850bc52..de66f1f3ee 100644
--- a/bootstraptest/test_autoload.rb
+++ b/bootstraptest/test_autoload.rb
@@ -11,7 +11,7 @@ assert_equal 'ok', %q{
}, '[ruby-dev:43816]'
assert_equal 'ok', %q{
- open('zzz2.rb', 'w') {|f| f.puts '' }
+ File.write('zzz2.rb', '')
instance_eval do
autoload :ZZZ, './zzz2.rb'
begin
@@ -23,7 +23,7 @@ assert_equal 'ok', %q{
}, '[ruby-dev:43816]'
assert_equal 'ok', %q{
- open('zzz3.rb', 'w') {|f| f.puts 'class ZZZ; def self.ok;:ok;end;end'}
+ File.write('zzz3.rb', "class ZZZ; def self.ok;:ok;end;end\n")
instance_eval do
autoload :ZZZ, './zzz3.rb'
ZZZ.ok
@@ -31,20 +31,20 @@ assert_equal 'ok', %q{
}, '[ruby-dev:43816]'
assert_equal 'ok', %q{
- open("zzz4.rb", "w") {|f| f.puts "class ZZZ; def self.ok;:ok;end;end"}
+ File.write("zzz4.rb", "class ZZZ; def self.ok;:ok;end;end\n")
autoload :ZZZ, "./zzz4.rb"
ZZZ.ok
}
assert_equal 'ok', %q{
- open("zzz5.rb", "w") {|f| f.puts "class ZZZ; def self.ok;:ok;end;end"}
+ File.write("zzz5.rb", "class ZZZ; def self.ok;:ok;end;end\n")
autoload :ZZZ, "./zzz5.rb"
require "./zzz5.rb"
ZZZ.ok
}
assert_equal 'okok', %q{
- open("zzz6.rb", "w") {|f| f.puts "class ZZZ; def self.ok;:ok;end;end"}
+ File.write("zzz6.rb", "class ZZZ; def self.ok;:ok;end;end\n")
autoload :ZZZ, "./zzz6.rb"
t1 = Thread.new {ZZZ.ok}
t2 = Thread.new {ZZZ.ok}
@@ -60,7 +60,7 @@ assert_finish 5, %q{
}, '[ruby-core:21696]'
assert_equal 'A::C', %q{
- open("zzz7.rb", "w") {}
+ File.write("zzz7.rb", "")
class A
autoload :C, "./zzz7"
class C
diff --git a/bootstraptest/test_eval.rb b/bootstraptest/test_eval.rb
index d923a957bc..20bd9615f4 100644
--- a/bootstraptest/test_eval.rb
+++ b/bootstraptest/test_eval.rb
@@ -217,7 +217,7 @@ assert_equal %q{[10, main]}, %q{
}
%w[break next redo].each do |keyword|
- assert_match %r"Can't escape from eval with #{keyword}\b", %{
+ assert_match %r"Invalid #{keyword}\b", %{
$stderr = STDOUT
begin
eval "0 rescue #{keyword}"
diff --git a/bootstraptest/test_fiber.rb b/bootstraptest/test_fiber.rb
index 2614dd13bf..ae809a5936 100644
--- a/bootstraptest/test_fiber.rb
+++ b/bootstraptest/test_fiber.rb
@@ -37,3 +37,8 @@ assert_normal_exit %q{
assert_normal_exit %q{
Fiber.new(&Object.method(:class_eval)).resume("foo")
}, '[ruby-dev:34128]'
+
+# [Bug #21400]
+assert_normal_exit %q{
+ Thread.new { Fiber.current.kill }.join
+}
diff --git a/bootstraptest/test_fork.rb b/bootstraptest/test_fork.rb
index 83923dad97..860ef285d0 100644
--- a/bootstraptest/test_fork.rb
+++ b/bootstraptest/test_fork.rb
@@ -75,3 +75,30 @@ assert_equal '[1, 2]', %q{
end
}, '[ruby-dev:44005] [Ruby 1.9 - Bug #4950]'
+assert_equal 'ok', %q{
+ def now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+
+ Thread.new do
+ loop { sleep 0.0001 }
+ end
+
+ 10.times do
+ pid = fork{ exit!(0) }
+ deadline = now + 10
+ while true
+ _, status = Process.waitpid2(pid, Process::WNOHANG)
+ break if status
+ if now > deadline
+ Process.kill(:KILL, pid)
+ raise "failed"
+ end
+ sleep 0.001
+ end
+ unless status.success?
+ raise "child exited with status #{status}"
+ end
+ rescue NotImplementedError
+ end
+ :ok
+}, '[Bug #20670]'
+
diff --git a/bootstraptest/test_gc.rb b/bootstraptest/test_gc.rb
index 17bc497822..eb68c9845e 100644
--- a/bootstraptest/test_gc.rb
+++ b/bootstraptest/test_gc.rb
@@ -14,7 +14,7 @@ ms = "a".."k"
o.send(meth)
end
end
-}, '[ruby-dev:39453]' unless rjit_enabled? # speed up RJIT CI
+}, '[ruby-dev:39453]'
assert_normal_exit %q{
a = []
diff --git a/bootstraptest/test_insns.rb b/bootstraptest/test_insns.rb
index 06828a7f7a..9e2c4a52a7 100644
--- a/bootstraptest/test_insns.rb
+++ b/bootstraptest/test_insns.rb
@@ -214,8 +214,21 @@ tests = [
'true'.freeze
},
+ [ 'opt_duparray_send', %q{ x = :a; [:a, :b].include?(x) }, ],
+ [ 'opt_duparray_send', <<-'},', ], # {
+ class Array
+ def include?(i)
+ i == 1
+ end
+ end
+ x = 1
+ [:a, :b].include?(x)
+ },
+
[ 'opt_newarray_send', %q{ ![ ].hash.nil? }, ],
+ [ 'opt_newarray_send', %q{ v=2; [1, Object.new, 2].include?(v) }, ],
+
[ 'opt_newarray_send', %q{ [ ].max.nil? }, ],
[ 'opt_newarray_send', %q{ [1, x = 2, 3].max == 3 }, ],
[ 'opt_newarray_send', <<-'},', ], # {
@@ -236,6 +249,48 @@ tests = [
end
[3, x = 2, 1].min
},
+ [ 'opt_newarray_send', %q{ v = 1.23; [v, v*2].pack("E*").unpack("E*") == [v, v*2] }, ],
+ [ 'opt_newarray_send', %q{ v = 4.56; b = +"x"; [v, v*2].pack("E*", buffer: b); b[1..].unpack("E*") == [v, v*2] }, ],
+ [ 'opt_newarray_send', <<-'},', ], # {
+ v = 7.89;
+ b = +"x";
+ class Array
+ alias _pack pack
+ def pack(s, buffer: nil, prefix: "y")
+ buffer ||= +"b"
+ buffer << prefix
+ _pack(s, buffer: buffer)
+ end
+ end
+ tests = []
+
+ ret = [v].pack("E*", prefix: "z")
+ tests << (ret[0..1] == "bz")
+ tests << (ret[2..].unpack("E*") == [v])
+
+ ret = [v].pack("E*")
+ tests << (ret[0..1] == "by")
+ tests << (ret[2..].unpack("E*") == [v])
+
+ [v, v*2, v*3].pack("E*", buffer: b)
+ tests << (b[0..1] == "xy")
+ tests << (b[2..].unpack("E*") == [v, v*2, v*3])
+
+ class Array
+ def pack(_fmt, buffer:) = buffer
+ end
+
+ b = nil
+ tests << [v].pack("E*", buffer: b).nil?
+
+ class Array
+ def pack(_fmt, **kw) = kw.empty?
+ end
+
+ tests << [v].pack("E*") == true
+
+ tests.all? or puts tests
+ },
[ 'throw', %q{ false.tap { break true } }, ],
[ 'branchif', %q{ x = nil; x ||= true }, ],
@@ -371,11 +426,6 @@ tests = [
x&.x[true] ||= true # here
},
- [ 'opt_aref_with', %q{ { 'true' => true }['true'] }, ],
- [ 'opt_aref_with', %q{ Struct.new(:nil).new['nil'].nil? }, ],
- [ 'opt_aset_with', %q{ {}['true'] = true }, ],
- [ 'opt_aset_with', %q{ Struct.new(:true).new['true'] = true }, ],
-
[ 'opt_length', %q{ 'true' .length == 4 }, ],
[ 'opt_length', %q{ :true .length == 4 }, ],
[ 'opt_length', %q{ [ 'true' ] .length == 1 }, ],
diff --git a/bootstraptest/test_io.rb b/bootstraptest/test_io.rb
index 666e5a011b..4081769a8c 100644
--- a/bootstraptest/test_io.rb
+++ b/bootstraptest/test_io.rb
@@ -85,13 +85,13 @@ assert_normal_exit %q{
ARGF.set_encoding "foo"
}
-/freebsd/ =~ RUBY_PLATFORM or
+/(freebsd|mswin)/ =~ RUBY_PLATFORM or
10.times do
assert_normal_exit %q{
at_exit { p :foo }
megacontent = "abc" * 12345678
- #File.open("megasrc", "w") {|f| f << megacontent }
+ #File.write("megasrc", megacontent)
t0 = Thread.main
Thread.new { sleep 0.001 until t0.stop?; Process.kill(:INT, $$) }
diff --git a/bootstraptest/test_literal.rb b/bootstraptest/test_literal.rb
index a30661a796..39e6527027 100644
--- a/bootstraptest/test_literal.rb
+++ b/bootstraptest/test_literal.rb
@@ -117,16 +117,16 @@ assert_equal '1', 'a = [obj = Object.new]; a.size'
assert_equal 'true', 'a = [obj = Object.new]; a[0] == obj'
assert_equal '5', 'a = [1,2,3]; a[1] = 5; a[1]'
assert_equal 'bar', '[*:foo];:bar'
-assert_equal '[1, 2]', 'def nil.to_a; [2]; end; [1, *nil]'
-assert_equal '[1, 2]', 'def nil.to_a; [1, 2]; end; [*nil]'
-assert_equal '[0, 1, {2=>3}]', '[0, *[1], 2=>3]', "[ruby-dev:31592]"
+assert_equal '[]', 'def nil.to_a; [1, 2]; end; [*nil]'
+assert_equal '[1]', 'def nil.to_a; [2]; end; [1, *nil]'
+assert_equal '[0, 1, {2 => 3}]', '[0, *[1], 2=>3]', "[ruby-dev:31592]"
# hash
assert_equal 'Hash', '{}.class'
assert_equal '{}', '{}.inspect'
assert_equal 'Hash', '{1=>2}.class'
-assert_equal '{1=>2}', '{1=>2}.inspect'
+assert_equal '{1 => 2}', '{1=>2}.inspect'
assert_equal '2', 'h = {1 => 2}; h[1]'
assert_equal '0', 'h = {1 => 2}; h.delete(1); h.size'
assert_equal '', 'h = {1 => 2}; h.delete(1); h[1]'
diff --git a/bootstraptest/test_load.rb b/bootstraptest/test_load.rb
index 3253582a32..fa8d31c098 100644
--- a/bootstraptest/test_load.rb
+++ b/bootstraptest/test_load.rb
@@ -1,9 +1,9 @@
assert_equal 'ok', %q{
- open("require-lock-test.rb", "w") {|f|
- f.puts "sleep 0.1"
- f.puts "module M"
- f.puts "end"
- }
+ File.write("require-lock-test.rb", <<-END)
+ sleep 0.1
+ module M
+ end
+ END
$:.unshift Dir.pwd
vs = (1..2).map {|i|
Thread.start {
@@ -12,11 +12,11 @@ assert_equal 'ok', %q{
}
}.map {|t| t.value }
vs[0] == M && vs[1] == M ? :ok : :ng
-}, '[ruby-dev:32048]' unless ENV.fetch('RUN_OPTS', '').include?('rjit') # Thread seems to be switching during JIT. To be fixed later.
+}, '[ruby-dev:32048]'
assert_equal 'ok', %q{
%w[a a/foo b].each {|d| Dir.mkdir(d)}
- open("b/foo", "w") {|f| f.puts "$ok = :ok"}
+ File.write("b/foo", "$ok = :ok\n")
$:.replace(%w[a b])
begin
load "foo"
diff --git a/bootstraptest/test_method.rb b/bootstraptest/test_method.rb
index d1d1f57d55..78aab73485 100644
--- a/bootstraptest/test_method.rb
+++ b/bootstraptest/test_method.rb
@@ -1176,3 +1176,261 @@ assert_equal 'ok', %q{
foo
foo
}, '[Bug #20178]'
+
+assert_equal 'ok', %q{
+ def bar(x); x; end
+ def foo(...); bar(...); end
+ foo('ok')
+}
+
+assert_equal 'ok', %q{
+ def bar(x); x; end
+ def foo(z, ...); bar(...); end
+ foo(1, 'ok')
+}
+
+assert_equal 'ok', %q{
+ def bar(x, y); x; end
+ def foo(...); bar("ok", ...); end
+ foo(1)
+}
+
+assert_equal 'ok', %q{
+ def bar(x); x; end
+ def foo(...); 1.times { return bar(...) }; end
+ foo("ok")
+}
+
+assert_equal 'ok', %q{
+ def bar(x); x; end
+ def foo(...); x = nil; 1.times { x = bar(...) }; x; end
+ foo("ok")
+}
+
+assert_equal 'ok', %q{
+ def bar(x); yield; end
+ def foo(...); bar(...); end
+ foo(1) { "ok" }
+}
+
+assert_equal 'ok', %q{
+ def baz(x); x; end
+ def bar(...); baz(...); end
+ def foo(...); bar(...); end
+ foo("ok")
+}
+
+assert_equal '[1, 2, 3, 4]', %q{
+ def baz(a, b, c, d); [a, b, c, d]; end
+ def bar(...); baz(1, ...); end
+ def foo(...); bar(2, ...); end
+ foo(3, 4)
+}
+
+assert_equal 'ok', %q{
+ class Foo; def self.foo(x); x; end; end
+ class Bar < Foo; def self.foo(...); super; end; end
+ Bar.foo('ok')
+}
+
+assert_equal 'ok', %q{
+ class Foo; def self.foo(x); x; end; end
+ class Bar < Foo; def self.foo(...); super(...); end; end
+ Bar.foo('ok')
+}
+
+assert_equal 'ok', %q{
+ class Foo; def self.foo(x, y); x + y; end; end
+ class Bar < Foo; def self.foo(...); super("o", ...); end; end
+ Bar.foo('k')
+}
+
+assert_equal 'ok', %q{
+ def bar(a); a; end
+ def foo(...); lambda { bar(...) }; end
+ foo("ok").call
+}
+
+assert_equal 'ok', %q{
+ class Foo; def self.foo(x, y); x + y; end; end
+ class Bar < Foo; def self.y(&b); b; end; def self.foo(...); y { super("o", ...) }; end; end
+ Bar.foo('k').call
+}
+
+assert_equal 'ok', %q{
+ def baz(n); n; end
+ def foo(...); bar = baz(...); lambda { lambda { bar } }; end
+ foo("ok").call.call
+}
+
+assert_equal 'ok', %q{
+ class A; def self.foo(...); new(...); end; attr_reader :b; def initialize(a, b:"ng"); @a = a; @b = b; end end
+ A.foo(1).b
+ A.foo(1, b: "ok").b
+}
+
+assert_equal 'ok', %q{
+ class A; def initialize; @a = ["ok"]; end; def first(...); @a.first(...); end; end
+ def call x; x.first; end
+ def call1 x; x.first(1); end
+ call(A.new)
+ call1(A.new).first
+}
+
+assert_equal 'ok', %q{
+ class A; def foo; yield("o"); end; end
+ class B < A; def foo(...); super { |x| yield(x + "k") }; end; end
+ B.new.foo { |x| x }
+}
+
+assert_equal "[1, 2, 3, 4]", %q{
+ def foo(*b) = b
+
+ def forward(...)
+ splat = [1,2,3]
+ foo(*splat, ...)
+ end
+
+ forward(4)
+}
+
+assert_equal "[1, 2, 3, 4]", %q{
+class A
+ def foo(*b) = b
+end
+
+class B < A
+ def foo(...)
+ splat = [1,2,3]
+ super(*splat, ...)
+ end
+end
+
+B.new.foo(4)
+}
+
+assert_equal 'ok', %q{
+ class A; attr_reader :iv; def initialize(...) = @iv = "ok"; end
+ A.new("foo", bar: []).iv
+}
+
+assert_equal 'ok', %q{
+ def foo(a, b) = a + b
+ def bar(...) = foo(...)
+ bar(1, 2)
+ bar(1, 2)
+ begin
+ bar(1, 2, 3)
+ "ng"
+ rescue ArgumentError
+ "ok"
+ end
+}
+
+assert_equal 'ok', %q{
+ class C
+ def foo(...) = :ok
+ def bar(...) = __send__(:foo, ...)
+ end
+
+ C.new.bar
+}
+
+assert_equal 'ok', %q{
+ class C
+ def method_missing(...) = :ok
+ def foo(...) = xyzzy(...)
+ end
+
+ C.new.foo
+}
+
+assert_equal 'ok', %q{
+ class C
+ def initialize(a)
+ end
+ end
+
+ def foo(...)
+ C.new(...)
+ :ok
+ end
+
+ foo(*["bar"])
+ foo("baz")
+}
+
+assert_equal 'ok', %q{
+ class C
+ def foo(b:)
+ b
+ end
+ end
+
+ def foo(...)
+ C.new.send(...)
+ end
+
+ foo(:foo, b: :ok)
+ foo(*["foo"], b: :ok)
+}
+
+assert_equal 'ok', %q{
+ Thing = Struct.new(:value)
+
+ Obj = Thing.new("ok")
+
+ def delegate(...)
+ Obj.value(...)
+ end
+
+ def no_args
+ delegate
+ end
+
+ def splat_args(*args)
+ delegate(*args)
+ end
+
+ no_args
+ splat_args
+}
+
+assert_equal 'ok', %q{
+ class A
+ private
+ def foo = "ng"
+ end
+
+ class B
+ def initialize(o)
+ @o = o
+ end
+
+ def foo(...) = @o.foo(...)
+ def internal_foo = foo
+ end
+
+ b = B.new(A.new)
+
+ begin
+ b.internal_foo
+ rescue NoMethodError
+ "ok"
+ end
+}
+
+assert_equal 'ok', <<~RUBY
+ def test(*, kw: false)
+ "ok"
+ end
+
+ test
+RUBY
+
+assert_equal '[1, 2, 3]', %q{
+ def target(*args) = args
+ def x = [1]
+ def forwarder(...) = target(*x, 2, ...)
+ forwarder(3).inspect
+}, '[Bug #21832] post-splat args before forwarding'
diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb
index 0390d38f9c..e2a3e8dd5b 100644
--- a/bootstraptest/test_ractor.rb
+++ b/bootstraptest/test_ractor.rb
@@ -67,7 +67,7 @@ assert_equal "#<Ractor:#1 running>", %q{
# Return id, loc, and status for no-name ractor
assert_match /^#<Ractor:#([^ ]*?) .+:[0-9]+ terminated>$/, %q{
r = Ractor.new { '' }
- r.take
+ r.join
sleep 0.1 until r.inspect =~ /terminated/
r.inspect
}
@@ -75,7 +75,7 @@ assert_match /^#<Ractor:#([^ ]*?) .+:[0-9]+ terminated>$/, %q{
# Return id, name, loc, and status for named ractor
assert_match /^#<Ractor:#([^ ]*?) Test Ractor .+:[0-9]+ terminated>$/, %q{
r = Ractor.new(name: 'Test Ractor') { '' }
- r.take
+ r.join
sleep 0.1 until r.inspect =~ /terminated/
r.inspect
}
@@ -86,7 +86,7 @@ assert_equal 'ok', %q{
r = Ractor.new do
'ok'
end
- r.take
+ r.value
}
# Passed arguments to Ractor.new will be a block parameter
@@ -96,7 +96,7 @@ assert_equal 'ok', %q{
r = Ractor.new 'ok' do |msg|
msg
end
- r.take
+ r.value
}
# Pass multiple arguments to Ractor.new
@@ -105,7 +105,7 @@ assert_equal 'ok', %q{
r = Ractor.new 'ping', 'pong' do |msg, msg2|
[msg, msg2]
end
- 'ok' if r.take == ['ping', 'pong']
+ 'ok' if r.value == ['ping', 'pong']
}
# Ractor#send passes an object with copy to a Ractor
@@ -115,65 +115,23 @@ assert_equal 'ok', %q{
msg = Ractor.receive
end
r.send 'ok'
- r.take
+ r.value
}
# Ractor#receive_if can filter the message
-assert_equal '[2, 3, 1]', %q{
- r = Ractor.new Ractor.current do |main|
- main << 1
- main << 2
- main << 3
- end
- a = []
- a << Ractor.receive_if{|msg| msg == 2}
- a << Ractor.receive_if{|msg| msg == 3}
- a << Ractor.receive
-}
+assert_equal '[1, 2, 3]', %q{
+ ports = 3.times.map{Ractor::Port.new}
-# Ractor#receive_if with break
-assert_equal '[2, [1, :break], 3]', %q{
- r = Ractor.new Ractor.current do |main|
- main << 1
- main << 2
- main << 3
+ r = Ractor.new ports do |ports|
+ ports[0] << 3
+ ports[1] << 1
+ ports[2] << 2
end
-
a = []
- a << Ractor.receive_if{|msg| msg == 2}
- a << Ractor.receive_if{|msg| break [msg, :break]}
- a << Ractor.receive
-}
-
-# Ractor#receive_if can't be called recursively
-assert_equal '[[:e1, 1], [:e2, 2]]', %q{
- r = Ractor.new Ractor.current do |main|
- main << 1
- main << 2
- main << 3
- end
-
- a = []
-
- Ractor.receive_if do |msg|
- begin
- Ractor.receive
- rescue Ractor::Error
- a << [:e1, msg]
- end
- true # delete 1 from queue
- end
-
- Ractor.receive_if do |msg|
- begin
- Ractor.receive_if{}
- rescue Ractor::Error
- a << [:e2, msg]
- end
- true # delete 2 from queue
- end
-
- a #
+ a << ports[1].receive # 1
+ a << ports[2].receive # 2
+ a << ports[0].receive # 3
+ a
}
# dtoa race condition
@@ -184,73 +142,145 @@ assert_equal '[:ok, :ok, :ok]', %q{
10_000.times{ rand.to_s }
:ok
}
- }.map(&:take)
+ }.map(&:value)
}
-# Ractor.make_shareable issue for locals in proc [Bug #18023]
+assert_equal "42", %q{
+ a = 42
+ Ractor.shareable_lambda{ a }.call
+}
+
+# Ractor.shareable_proc 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] } }
+ closure = Proc.new { [v1, v2, v3, v4, v5] }
+ Ractor.shareable_proc(&closure).call
+}
- Ractor.make_shareable(closure).call
+# Ractor.shareable_proc makes a copy of given Proc
+assert_equal '[true, true]', %q{
+ pr1 = Proc.new do
+ self
+ end
+ pr2 = Ractor.shareable_proc(&pr1)
+
+ [pr1.call == self, pr2.call == nil]
}
-# 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
+# Ractor.shareable_proc keeps the original Proc intact
+assert_equal '[SyntaxError, [Object, 43, 43], Binding]', %q{
+ a = 42
+ pr1 = Proc.new do
+ [self.class, eval("a"), binding.local_variable_get(:a)]
+ end
+ a += 1
+ pr2 = Ractor.shareable_proc(&pr1)
+
+ r = []
+ begin
+ pr2.call
+ rescue SyntaxError
+ r << SyntaxError
end
- Ractor.make_shareable(closure).call
+ r << pr1.call << pr1.binding.class
}
-# 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
+# Ractor.make_shareable mutates the original Proc
+# This is the current behavior, it's currently considered safe enough
+# because in most cases it would raise anyway due to not-shared self or not-shared captured variable value
+assert_equal '[[42, 42], Binding, true, SyntaxError, "Can\'t create Binding from isolated Proc"]', %q{
+ a = 42
+ pr1 = nil.instance_exec do
+ Proc.new do
+ [eval("a"), binding.local_variable_get(:a)]
+ end
+ end
+
+ r = [pr1.call, pr1.binding.class]
+
+ pr2 = Ractor.make_shareable(pr1)
+ r << pr1.equal?(pr2)
+
+ begin
+ pr1.call
+ rescue SyntaxError
+ r << SyntaxError
+ end
+
+ begin
+ r << pr1.binding
+ rescue ArgumentError
+ r << $!.message
+ end
+
+ r
+}
+
+# Ractor::IsolationError cases
+assert_equal '3', %q{
+ ok = 0
+
+ begin
+ a = 1
+ Ractor.shareable_proc{a}
+ a = 2
+ rescue Ractor::IsolationError => e
+ ok += 1
+ end
+
+ begin
+ cond = false
+ b = 1
+ b = 2 if cond
+ Ractor.shareable_proc{b}
+ rescue Ractor::IsolationError => e
+ ok += 1
+ end
+
+ begin
+ 1.times{|i|
+ i = 2
+ Ractor.shareable_proc{i}
+ }
+ rescue Ractor::IsolationError => e
+ ok += 1
end
- r.take
}
###
###
# Ractor still has several memory corruption so skip huge number of tests
-if ENV['GITHUB_WORKFLOW'] &&
- ENV['GITHUB_WORKFLOW'] == 'Compilations'
+if ENV['GITHUB_WORKFLOW'] == 'Compilations'
# ignore the follow
else
-# Ractor.select(*ractors) receives a values from a ractors.
-# It is similar to select(2) and Go's select syntax.
-# The return value is [ch, received_value]
+# Ractor.select with a Ractor argument
assert_equal 'ok', %q{
# select 1
r1 = Ractor.new{'r1'}
- r, obj = Ractor.select(r1)
- 'ok' if r == r1 and obj == 'r1'
+ port, obj = Ractor.select(r1)
+ if port == r1 and obj == 'r1'
+ 'ok'
+ else
+ # failed
+ [port, obj].inspect
+ end
}
# Ractor.select from two ractors.
assert_equal '["r1", "r2"]', %q{
# select 2
- r1 = Ractor.new{'r1'}
- r2 = Ractor.new{'r2'}
- rs = [r1, r2]
+ p1 = Ractor::Port.new
+ p2 = Ractor::Port.new
+ r1 = Ractor.new(p1){|p1| p1 << 'r1'}
+ r2 = Ractor.new(p2){|p2| p2 << 'r2'}
+ ps = [p1, p2]
as = []
- r, obj = Ractor.select(*rs)
- rs.delete(r)
+ port, obj = Ractor.select(*ps)
+ ps.delete(port)
as << obj
- r, obj = Ractor.select(*rs)
+ port, obj = Ractor.select(*ps)
as << obj
as.sort #=> ["r1", "r2"]
}
@@ -286,7 +316,7 @@ assert_equal 30.times.map { 'ok' }.to_s, %q{
} unless (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{
+assert_match /specify at least one Ractor::Port or Ractor/, %q{
begin
Ractor.select
rescue ArgumentError => e
@@ -294,30 +324,12 @@ assert_match /specify at least one ractor/, %q{
end
}
-# Outgoing port of a ractor will be closed when the Ractor is terminated.
-assert_equal 'ok', %q{
- r = Ractor.new do
- 'finish'
- end
-
- r.take
- sleep 0.1 until r.inspect =~ /terminated/
-
- begin
- o = r.take
- rescue Ractor::ClosedError
- 'ok'
- else
- "ng: #{o}"
- end
-}
-
# Raise Ractor::ClosedError when try to send into a terminated ractor
assert_equal 'ok', %q{
r = Ractor.new do
end
- r.take # closed
+ r.join # closed
sleep 0.1 until r.inspect =~ /terminated/
begin
@@ -329,47 +341,16 @@ assert_equal 'ok', %q{
end
}
-# Raise Ractor::ClosedError when try to send into a closed actor
-assert_equal 'ok', %q{
- r = Ractor.new { Ractor.receive }
- r.close_incoming
-
- begin
- r.send(1)
- rescue Ractor::ClosedError
- 'ok'
- else
- 'ng'
- end
-}
-
-# Raise Ractor::ClosedError when try to take from closed actor
-assert_equal 'ok', %q{
- r = Ractor.new do
- Ractor.yield 1
- Ractor.receive
- end
-
- r.close_outgoing
- begin
- r.take
- rescue Ractor::ClosedError
- 'ok'
- else
- 'ng'
- end
-}
-
-# Can mix with Thread#interrupt and Ractor#take [Bug #17366]
+# Can mix with Thread#interrupt and Ractor#join [Bug #17366]
assert_equal 'err', %q{
- Ractor.new{
+ Ractor.new do
t = Thread.current
begin
Thread.new{ t.raise "err" }.join
rescue => e
e.message
end
- }.take
+ end.value
}
# Killed Ractor's thread yields nil
@@ -377,34 +358,18 @@ assert_equal 'nil', %q{
Ractor.new{
t = Thread.current
Thread.new{ t.kill }.join
- }.take.inspect #=> nil
+ }.value.inspect #=> nil
}
-# Ractor.yield raises Ractor::ClosedError when outgoing port is closed.
+# Raise Ractor::ClosedError when try to send into a ractor with closed default port
assert_equal 'ok', %q{
- r = Ractor.new Ractor.current do |main|
+ r = Ractor.new {
+ Ractor.current.close
+ Ractor.main << :ok
Ractor.receive
- main << true
- Ractor.yield 1
- end
-
- r.close_outgoing
- r << true
- Ractor.receive
-
- begin
- r.take
- rescue Ractor::ClosedError
- 'ok'
- else
- 'ng'
- end
-}
+ }
-# Raise Ractor::ClosedError when try to send into a ractor with closed incoming port
-assert_equal 'ok', %q{
- r = Ractor.new { Ractor.receive }
- r.close_incoming
+ Ractor.receive # wait for ok
begin
r.send(1)
@@ -415,154 +380,82 @@ assert_equal 'ok', %q{
end
}
-# A ractor with closed incoming port still can send messages out
-assert_equal '[1, 2]', %q{
- r = Ractor.new do
- Ractor.yield 1
- 2
- end
- r.close_incoming
-
- [r.take, r.take]
-}
-
-# Raise Ractor::ClosedError when try to take from a ractor with closed outgoing port
-assert_equal 'ok', %q{
- r = Ractor.new do
- Ractor.yield 1
- Ractor.receive
- end
-
- sleep 0.01 # wait for Ractor.yield in r
- r.close_outgoing
- begin
- r.take
- rescue Ractor::ClosedError
- 'ok'
- else
- 'ng'
- end
-}
-
-# A ractor with closed outgoing port still can receive messages from incoming port
-assert_equal 'ok', %q{
- r = Ractor.new do
- Ractor.receive
- end
-
- r.close_outgoing
- begin
- r.send(1)
- rescue Ractor::ClosedError
- 'ng'
- else
- 'ok'
- end
-}
-
# Ractor.main returns main ractor
assert_equal 'true', %q{
Ractor.new{
Ractor.main
- }.take == Ractor.current
+ }.value == Ractor.current
}
# a ractor with closed outgoing port should terminate
assert_equal 'ok', %q{
Ractor.new do
- close_outgoing
+ Ractor.current.close
end
true until Ractor.count == 1
:ok
}
-# multiple Ractors can receive (wait) from one Ractor
-assert_equal '[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]', %q{
- pipe = Ractor.new do
- loop do
- Ractor.yield Ractor.receive
- end
+# an exception in a Ractor main thread will be re-raised at Ractor#receive
+assert_equal '[RuntimeError, "ok", true]', %q{
+ r = Ractor.new do
+ raise 'ok' # exception will be transferred receiver
end
-
- RN = 10
- rs = RN.times.map{|i|
- Ractor.new pipe, i do |pipe, i|
- msg = pipe.take
- msg # ping-pong
- end
- }
- RN.times{|i|
- pipe << i
- }
- RN.times.map{
- r, n = Ractor.select(*rs)
- rs.delete r
- n
- }.sort
-} unless /mswin/ =~ RUBY_PLATFORM # randomly hangs on mswin https://github.com/ruby/ruby/actions/runs/3753871445/jobs/6377551069#step:20:131
-
-# Ractor.select also support multiple take, receive and yield
-assert_equal '[true, true, true]', %q{
- RN = 10
- CR = Ractor.current
-
- rs = (1..RN).map{
- Ractor.new do
- CR.send 'send' + CR.take #=> 'sendyield'
- 'take'
- end
- }
- received = []
- taken = []
- yielded = []
- until received.size == RN && taken.size == RN && yielded.size == RN
- r, v = Ractor.select(CR, *rs, yield_value: 'yield')
- case r
- when :receive
- received << v
- when :yield
- yielded << v
- else
- taken << v
- rs.delete r
- end
+ begin
+ r.join
+ rescue Ractor::RemoteError => e
+ [e.cause.class, #=> RuntimeError
+ e.cause.message, #=> 'ok'
+ e.ractor == r] #=> true
end
- r = [received == ['sendyield'] * RN,
- yielded == [nil] * RN,
- taken == ['take'] * RN,
- ]
-
- STDERR.puts [received, yielded, taken].inspect
- r
}
-# multiple Ractors can send to one Ractor
-assert_equal '[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]', %q{
- pipe = Ractor.new do
- loop do
- Ractor.yield Ractor.receive
- end
+# an exception in a Ractor will be re-raised at Ractor#value
+assert_equal '[RuntimeError, "ok", true]', %q{
+ r = Ractor.new do
+ raise 'ok' # exception will be transferred receiver
+ end
+ begin
+ r.value
+ rescue Ractor::RemoteError => e
+ [e.cause.class, #=> RuntimeError
+ e.cause.message, #=> 'ok'
+ e.ractor == r] #=> true
end
+}
- RN = 10
- RN.times.map{|i|
- Ractor.new pipe, i do |pipe, i|
- pipe << i
+# an exception in a Ractor non-main thread will not be re-raised at Ractor#receive
+assert_equal 'ok', %q{
+ r = Ractor.new do
+ Thread.new do
+ raise 'ng'
end
- }
- RN.times.map{
- pipe.take
- }.sort
+ sleep 0.1
+ 'ok'
+ end
+ r.value
}
-# an exception in a Ractor will be re-raised at Ractor#receive
-assert_equal '[RuntimeError, "ok", true]', %q{
- r = Ractor.new do
- raise 'ok' # exception will be transferred receiver
+# SystemExit from a Ractor is re-raised
+# [Bug #21505]
+assert_equal '[SystemExit, "exit", true]', %q{
+ r = Ractor.new { exit }
+ begin
+ r.value
+ rescue Ractor::RemoteError => e
+ [e.cause.class, #=> RuntimeError
+ e.cause.message, #=> 'ok'
+ e.ractor == r] #=> true
end
+}
+
+# SystemExit from a Thread inside a Ractor is re-raised
+# [Bug #21505]
+assert_equal '[SystemExit, "exit", true]', %q{
+ r = Ractor.new { Thread.new { exit }.join }
begin
- r.take
+ r.value
rescue Ractor::RemoteError => e
[e.cause.class, #=> RuntimeError
e.cause.message, #=> 'ok'
@@ -571,7 +464,7 @@ assert_equal '[RuntimeError, "ok", true]', %q{
}
# threads in a ractor will killed
-assert_equal '{:ok=>3}', %q{
+assert_equal '{ok: 3}', %q{
Ractor.new Ractor.current do |main|
q = Thread::Queue.new
Thread.new do
@@ -601,7 +494,7 @@ assert_equal '{:ok=>3}', %q{
end
3.times.map{Ractor.receive}.tally
-} unless yjit_enabled? # `[BUG] Bus Error at 0x000000010b7002d0` in jit_exec()
+} unless yjit_enabled? # YJIT: `[BUG] Bus Error at 0x000000010b7002d0` in jit_exec()
# unshareable object are copied
assert_equal 'false', %q{
@@ -610,7 +503,7 @@ assert_equal 'false', %q{
msg.object_id
end
- obj.object_id == r.take
+ obj.object_id == r.value
}
# To copy the object, now Marshal#dump is used
@@ -629,10 +522,11 @@ assert_equal "allocator undefined for Thread", %q{
# send shareable and unshareable objects
assert_equal "ok", <<~'RUBY', frozen_string_literal: false
- echo_ractor = Ractor.new do
+ port = Ractor::Port.new
+ echo_ractor = Ractor.new port do |port|
loop do
v = Ractor.receive
- Ractor.yield v
+ port << v
end
end
@@ -680,13 +574,13 @@ assert_equal "ok", <<~'RUBY', frozen_string_literal: false
shareable_objects.map{|o|
echo_ractor << o
- o2 = echo_ractor.take
+ o2 = port.receive
results << "#{o} is copied" unless o.object_id == o2.object_id
}
unshareable_objects.map{|o|
echo_ractor << o
- o2 = echo_ractor.take
+ o2 = port.receive
results << "#{o.inspect} is not copied" if o.object_id == o2.object_id
}
@@ -712,7 +606,7 @@ assert_equal [false, true, false].inspect, <<~'RUBY', frozen_string_literal: fal
def check obj1
obj2 = Ractor.new obj1 do |obj|
obj
- end.take
+ end.value
obj1.object_id == obj2.object_id
end
@@ -734,7 +628,7 @@ assert_equal 'hello world', <<~'RUBY', frozen_string_literal: false
str = 'hello'
r.send str, move: true
- modified = r.take
+ modified = r.value
begin
str << ' exception' # raise Ractor::MovedError
@@ -754,7 +648,7 @@ assert_equal '[0, 1]', %q{
a1 = [0]
r.send a1, move: true
- a2 = r.take
+ a2 = r.value
begin
a1 << 2 # raise Ractor::MovedError
rescue Ractor::MovedError
@@ -762,70 +656,39 @@ assert_equal '[0, 1]', %q{
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
+# unshareable frozen objects should still be frozen in new ractor after move
+assert_equal 'true', %q{
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
+ obj = receive
+ { frozen: obj.frozen? }
end
-
- Ractor.receive
+ obj = [Object.new].freeze
+ r.send(obj, move: true)
+ r.value[:frozen]
}
-# 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{
+# Access to global-variables are prohibited (read)
+assert_equal 'can not access global variable $gv from non-main Ractor', %q{
$gv = 1
r = Ractor.new do
$gv
end
begin
- r.take
+ r.join
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{
+# Access to global-variables are prohibited (write)
+assert_equal 'can not access global variable $gv from non-main Ractor', %q{
r = Ractor.new do
$gv = 1
end
begin
- r.take
+ r.join
rescue Ractor::RemoteError => e
e.cause.message
end
@@ -839,7 +702,7 @@ assert_equal 'ok', %q{
}
end
- [$stdin, $stdout, $stderr].zip(r.take){|io, (oid, fno)|
+ [$stdin, $stdout, $stderr].zip(r.value){|io, (oid, fno)|
raise "should not be different object" if io.object_id == oid
raise "fd should be same" unless io.fileno == fno
}
@@ -855,7 +718,7 @@ assert_equal 'ok', %q{
'ok'
end
- r.take
+ r.value
}
# $DEBUG, $VERBOSE are Ractor local
@@ -913,7 +776,7 @@ assert_equal 'true', %q{
h = Ractor.new do
ractor_local_globals
- end.take
+ end.value
ractor_local_globals == h #=> true
}
@@ -922,7 +785,8 @@ assert_equal 'false', %q{
r = Ractor.new do
self.object_id
end
- r.take == self.object_id #=> false
+ ret = r.value
+ ret == self.object_id
}
# self is a Ractor instance
@@ -930,7 +794,12 @@ assert_equal 'true', %q{
r = Ractor.new do
self.object_id
end
- r.object_id == r.take #=> true
+ ret = r.value
+ if r.object_id == ret #=> true
+ true
+ else
+ raise [ret, r.object_id].inspect
+ end
}
# given block Proc will be isolated, so can not access outer variables.
@@ -945,8 +814,39 @@ assert_equal 'ArgumentError', %q{
end
}
+# eval with outer locals in a Ractor raises SyntaxError
+# [Bug #21522]
+assert_equal 'SyntaxError', %q{
+ outer = 42
+ r = Ractor.new do
+ eval("outer")
+ end
+ begin
+ r.value
+ rescue Ractor::RemoteError => e
+ e.cause.class
+ end
+}
+
+# eval of an undefined name in a Ractor raises NameError
+assert_equal 'NameError', %q{
+ r = Ractor.new do
+ eval("totally_undefined_name")
+ end
+ begin
+ r.value
+ rescue Ractor::RemoteError => e
+ e.cause.class
+ end
+}
+
+# eval of a local defined inside the Ractor works
+assert_equal '99', %q{
+ Ractor.new { inner = 99; eval("inner").to_s }.value
+}
+
# 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", <<~'RUBY', frozen_string_literal: false
+assert_equal "can not get unshareable values from instance variables of classes/modules from non-main Ractors (@iv from C)", <<~'RUBY', frozen_string_literal: false
class C
@iv = 'str'
end
@@ -958,7 +858,7 @@ assert_equal "can not get unshareable values from instance variables of classes/
end
begin
- r.take
+ r.value
rescue Ractor::RemoteError => e
e.cause.message
end
@@ -974,7 +874,7 @@ assert_equal 'can not access instance variables of shareable objects from non-ma
end
begin
- r.take
+ r.value
rescue Ractor::RemoteError => e
e.cause.message
end
@@ -1000,7 +900,7 @@ assert_equal 'can not access instance variables of shareable objects from non-ma
end
begin
- r.take
+ r.value
rescue Ractor::RemoteError => e
e.cause.message
end
@@ -1021,7 +921,7 @@ assert_equal 'can not access instance variables of shareable objects from non-ma
end
begin
- r.take
+ r.value
rescue Ractor::RemoteError => e
e.cause.message
end
@@ -1035,7 +935,7 @@ assert_equal '11', %q{
Ractor.new obj do |obj|
obj.instance_variable_get('@a')
- end.take.to_s
+ end.value.to_s
}.join
}
@@ -1061,54 +961,68 @@ assert_equal '333', %q{
def self.fstr = @fstr
end
- a = Ractor.new{ C.int }.take
+ a = Ractor.new{ C.int }.value
b = Ractor.new do
C.str.to_i
rescue Ractor::IsolationError
10
- end.take
+ end.value
c = Ractor.new do
C.fstr.to_i
- end.take
+ end.value
- d = Ractor.new{ M.int }.take
+ d = Ractor.new{ M.int }.value
e = Ractor.new do
M.str.to_i
rescue Ractor::IsolationError
20
- end.take
+ end.value
f = Ractor.new do
M.fstr.to_i
- end.take
+ end.value
# 1 + 10 + 100 + 2 + 20 + 200
a + b + c + d + e + f
}
+assert_equal '["instance-variable", "instance-variable", nil]', %q{
+ class C
+ @iv1 = ""
+ @iv2 = 42
+ def self.iv1 = defined?(@iv1) # "instance-variable"
+ def self.iv2 = defined?(@iv2) # "instance-variable"
+ def self.iv3 = defined?(@iv3) # nil
+ end
+
+ Ractor.new{
+ [C.iv1, C.iv2, C.iv3]
+ }.value
+}
+
# moved objects have their shape properly set to original object's shape
assert_equal '1234', %q{
-class Obj
- attr_accessor :a, :b, :c, :d
- def initialize
- @a = 1
- @b = 2
- @c = 3
+ class Obj
+ attr_accessor :a, :b, :c, :d
+ def initialize
+ @a = 1
+ @b = 2
+ @c = 3
+ end
end
-end
-r = Ractor.new do
- obj = receive
- obj.d = 4
- [obj.a, obj.b, obj.c, obj.d]
-end
-obj = Obj.new
-r.send(obj, move: true)
-values = r.take
-values.join
+ r = Ractor.new do
+ obj = receive
+ obj.d = 4
+ [obj.a, obj.b, obj.c, obj.d]
+ end
+ obj = Obj.new
+ r.send(obj, move: true)
+ values = r.value
+ values.join
}
# cvar in shareable-objects are not allowed to access from non-main Ractor
-assert_equal 'can not access class variables from non-main Ractors', %q{
+assert_equal 'can not access class variables from non-main Ractors (@@cv from C)', %q{
class C
@@cv = 'str'
end
@@ -1120,14 +1034,14 @@ assert_equal 'can not access class variables from non-main Ractors', %q{
end
begin
- r.take
+ r.join
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{
+assert_equal 'can not access class variables from non-main Ractors (@@cv from C)', %q{
class C
@@cv = 'str'
def self.cv
@@ -1142,7 +1056,7 @@ assert_equal 'can not access class variables from non-main Ractors', %q{
end
begin
- r.take
+ r.join
rescue Ractor::RemoteError => e
e.cause.message
end
@@ -1157,19 +1071,33 @@ assert_equal 'can not access non-shareable objects in constant C::CONST by non-m
C::CONST
end
begin
- r.take
+ r.join
rescue Ractor::RemoteError => e
e.cause.message
end
RUBY
-# Constant cache should care about non-sharable constants
+# Constant cache should care about non-shareable constants
assert_equal "can not access non-shareable objects in constant Object::STR by non-main Ractor.", <<~'RUBY', frozen_string_literal: false
STR = "hello"
def str; STR; end
s = str() # fill const cache
begin
- Ractor.new{ str() }.take
+ Ractor.new{ str() }.join
+ rescue Ractor::RemoteError => e
+ e.cause.message
+ end
+RUBY
+
+# The correct constant path shall be reported
+assert_equal "can not access non-shareable objects in constant Object::STR by non-main Ractor.", <<~'RUBY', frozen_string_literal: false
+ STR = "hello"
+ module M
+ def self.str; STR; end
+ end
+
+ begin
+ Ractor.new{ M.str }.join
rescue Ractor::RemoteError => e
e.cause.message
end
@@ -1183,7 +1111,7 @@ assert_equal 'can not set constants with non-shareable objects by non-main Racto
C::CONST = 'str'
end
begin
- r.take
+ r.join
rescue Ractor::RemoteError => e
e.cause.message
end
@@ -1194,7 +1122,7 @@ assert_equal "defined with an un-shareable Proc in a different Ractor", %q{
str = "foo"
define_method(:buggy){|i| str << "#{i}"}
begin
- Ractor.new{buggy(10)}.take
+ Ractor.new{buggy(10)}.join
rescue => e
e.cause.message
end
@@ -1205,7 +1133,7 @@ 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.new{ [A.size, H.size] }.value
}
# Ractor.count
@@ -1215,15 +1143,15 @@ assert_equal '[1, 4, 3, 2, 1]', %q{
ractors = (1..3).map { Ractor.new { Ractor.receive } }
counts << Ractor.count
- ractors[0].send('End 0').take
+ ractors[0].send('End 0').join
sleep 0.1 until ractors[0].inspect =~ /terminated/
counts << Ractor.count
- ractors[1].send('End 1').take
+ ractors[1].send('End 1').join
sleep 0.1 until ractors[1].inspect =~ /terminated/
counts << Ractor.count
- ractors[2].send('End 2').take
+ ractors[2].send('End 2').join
sleep 0.1 until ractors[2].inspect =~ /terminated/
counts << Ractor.count
@@ -1236,7 +1164,7 @@ assert_equal '0', %q{
n = 0
ObjectSpace.each_object{|o| n += 1 unless Ractor.shareable?(o)}
n
- }.take
+ }.value
}
# ObjectSpace._id2ref can not handle unshareable objects with Ractors
@@ -1249,7 +1177,25 @@ assert_equal 'ok', <<~'RUBY', frozen_string_literal: false
rescue => e
:ok
end
- end.take
+ end.value
+RUBY
+
+# Inserting into the id2ref table should be Ractor-safe
+assert_equal 'ok', <<~'RUBY'
+ # Force all calls to Kernel#object_id to insert into the id2ref table
+ obj = Object.new
+ ObjectSpace._id2ref(obj.object_id) rescue nil
+
+ 10.times.map do
+ Ractor.new do
+ 10_000.times do
+ a = Object.new
+ a.object_id
+ end
+ end
+ end.map(&:value)
+
+ :ok
RUBY
# Ractor.make_shareable(obj)
@@ -1333,19 +1279,42 @@ assert_equal 'true', %q{
[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"}]
+# Ractor.make_shareable(a_proc) requires a shareable receiver
+assert_equal '[:ok, "Proc\'s self is not shareable:"]', %q{
+ pr1 = nil.instance_exec { Proc.new{} }
+ pr2 = Proc.new{}
- pr = Ractor.current.instance_eval do
- Proc.new do
- a
+ [pr1, pr2].map do |pr|
+ begin
+ Ractor.make_shareable(pr)
+ rescue Ractor::Error => e
+ e.message[/^.+?:/]
+ else
+ :ok
end
end
+}
+
+# Ractor.make_shareable(Method/UnboundMethod)
+assert_equal 'true', %q{
+ # raise because receiver is unshareable
+ begin
+ _m0 = Ractor.make_shareable(self.method(:__id__))
+ rescue => e
+ raise e unless e.message =~ /can not make shareable object/
+ else
+ raise "no error"
+ end
- Ractor.make_shareable(a) # referred value should be shareable
- Ractor.make_shareable(pr)
- Ractor.shareable?(pr)
+ # Method with shareable receiver
+ M1 = Ractor.make_shareable(Object.method(:__id__))
+
+ # UnboundMethod
+ M2 = Ractor.make_shareable(Object.instance_method(:__id__))
+
+ Ractor.new do
+ Object.__id__ == M1.call && M1.call == M2.bind_call(Object)
+ end.value
}
# Ractor.shareable?(recursive_objects)
@@ -1380,29 +1349,10 @@ assert_equal '[C, M]', %q{
assert_equal '1', %q{
class C
a = 1
- define_method "foo", Ractor.make_shareable(Proc.new{ a })
- a = 2
+ define_method "foo", Ractor.shareable_proc{ a }
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.new{ C.new.foo }.value
}
# Ractor.make_shareable(obj, copy: true) makes copied shareable object.
@@ -1427,7 +1377,7 @@ assert_equal '[6, 10]', %q{
Ractor.new{ # line 5
a = 1
b = 2
- }.take
+ }.value
c = 3 # line 9
end
rs
@@ -1437,7 +1387,7 @@ assert_equal '[6, 10]', %q{
assert_equal '[true, false]', %q{
Ractor.new([[]].freeze) { |ary|
[ary.frozen?, ary.first.frozen? ]
- }.take
+ }.value
}
# Ractor deep copies frozen objects (str)
@@ -1445,7 +1395,7 @@ 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
+ }.value
}
# Can not trap with not isolated Proc on non-main ractor
@@ -1453,15 +1403,15 @@ assert_equal '[:ok, :ok]', %q{
a = []
Ractor.new{
trap(:INT){p :ok}
- }.take
+ }.join
a << :ok
begin
Ractor.new{
s = 'str'
trap(:INT){p s}
- }.take
- rescue => Ractor::RemoteError
+ }.join
+ rescue Ractor::RemoteError
a << :ok
end
}
@@ -1490,15 +1440,48 @@ assert_equal '[nil, "b", "a"]', %q{
ans = []
Ractor.current[:key] = 'a'
r = Ractor.new{
- Ractor.yield self[:key]
+ Ractor.main << self[:key]
self[:key] = 'b'
self[:key]
}
- ans << r.take
- ans << r.take
+ ans << Ractor.receive
+ ans << r.value
ans << Ractor.current[:key]
}
+assert_equal '1', %q{
+ N = 1_000
+ Ractor.new{
+ a = []
+ 1_000.times.map{|i|
+ Thread.new(i){|i|
+ Thread.pass if i < N
+ a << Ractor.store_if_absent(:i){ i }
+ a << Ractor.current[:i]
+ }
+ }.each(&:join)
+ a.uniq.size
+ }.value
+}
+
+# Ractor-local storage
+assert_equal '2', %q{
+ Ractor.new {
+ fails = 0
+ begin
+ Ractor.main[:key] # cannot get ractor local storage from non-main ractor
+ rescue => e
+ fails += 1 if e.message =~ /Cannot get ractor local/
+ end
+ begin
+ Ractor.main[:key] = 'val'
+ rescue => e
+ fails += 1 if e.message =~ /Cannot set ractor local/
+ end
+ fails
+ }.value
+}
+
###
### Synchronization tests
###
@@ -1512,10 +1495,28 @@ assert_equal "#{N}#{N}", %Q{
Ractor.new{
N.times{|i| -(i.to_s)}
}
- }.map{|r| r.take}.join
+ }.map{|r| r.value}.join
+}
+
+assert_equal "ok", %Q{
+ N = #{N}
+ a, b = 2.times.map{
+ Ractor.new{
+ N.times.map{|i| -(i.to_s)}
+ }
+ }.map{|r| r.value}
+ N.times do |i|
+ unless a[i].equal?(b[i])
+ raise [a[i], b[i]].inspect
+ end
+ unless a[i] == i.to_s
+ raise [i, a[i], b[i]].inspect
+ end
+ end
+ :ok
}
-# Generic ivtbl
+# Generic fields_tbl
n = N/2
assert_equal "#{n}#{n}", %Q{
2.times.map{
@@ -1528,21 +1529,20 @@ assert_equal "#{n}#{n}", %Q{
obj.instance_variable_defined?("@a")
end
end
- }.map{|r| r.take}.join
+ }.map{|r| r.value}.join
}
-# NameError
-assert_equal "ok", %q{
+# Now NoMethodError is copyable
+assert_equal "NoMethodError", %q{
obj = "".freeze # NameError refers the receiver indirectly
begin
obj.bar
rescue => err
end
- begin
- Ractor.new{} << err
- rescue TypeError
- 'ok'
- end
+
+ r = Ractor.new{ Ractor.receive }
+ r << err
+ r.value.class
}
assert_equal "ok", %q{
@@ -1560,54 +1560,27 @@ assert_equal "ok", %q{
# Can yield back values while GC is sweeping [Bug #18117]
assert_equal "ok", %q{
+ port = Ractor::Port.new
workers = (0...8).map do
- Ractor.new do
+ Ractor.new port do |port|
loop do
10_000.times.map { Object.new }
- Ractor.yield Time.now
+ port << Time.now
+ Ractor.receive
end
end
end
- 1_000.times { idle_worker, tmp_reporter = Ractor.select(*workers) }
+ 100.times {
+ workers.each do
+ port.receive
+ end
+ workers.each do |w|
+ w.send(nil)
+ end
+ }
"ok"
-} unless yjit_enabled? || rjit_enabled? # flaky
-
-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
-}
+} if !yjit_enabled? && ENV['GITHUB_WORKFLOW'] != 'ModGC' # flaky
# check method cache invalidation
assert_equal "ok", %q{
@@ -1672,14 +1645,41 @@ assert_equal 'true', %q{
}
n = CS.inject(1){|r, c| r * c.foo} * LN
- rs.map{|r| r.take} == Array.new(RN){n}
+ rs.map{|r| r.value} == Array.new(RN){n}
+}
+
+# check method cache invalidation
+assert_equal 'true', %q{
+ class Foo
+ def hello = nil
+ end
+
+ r1 = Ractor.new do
+ 1000.times do
+ class Foo
+ def hello = nil
+ end
+ end
+ end
+
+ r2 = Ractor.new do
+ 1000.times do
+ o = Foo.new
+ o.hello
+ end
+ end
+
+ r1.value
+ r2.value
+
+ true
}
# check experimental warning
-assert_match /\Atest_ractor\.rb:1:\s+warning:\s+Ractor is experimental/, %q{
+assert_match /\Atest_ractor\.rb:1:\s+warning:\s+Ractor API is experimental/, %q{
Warning[:experimental] = $VERBOSE = true
STDERR.reopen(STDOUT)
- eval("Ractor.new{}.take", nil, "test_ractor.rb", 1)
+ eval("Ractor.new{}.value", nil, "test_ractor.rb", 1)
}, frozen_string_literal: false
# check moved object
@@ -1697,7 +1697,7 @@ assert_equal 'ok', %q{
end
r.send obj, move: true
- r.take
+ r.value
}
## Ractor::Selector
@@ -1773,10 +1773,11 @@ assert_equal '600', %q{
RN = 100
s = Ractor::Selector.new
+ port = Ractor::Port.new
rs = RN.times.map{
Ractor.new{
- Ractor.main << Ractor.new{ Ractor.yield :v3; :v4 }
- Ractor.main << Ractor.new{ Ractor.yield :v5; :v6 }
+ Ractor.main << Ractor.new(port){|port| port << :v3; :v4 }
+ Ractor.main << Ractor.new(port){|port| port << :v5; :v6 }
Ractor.yield :v1
:v2
}
@@ -1822,3 +1823,734 @@ assert_equal 'true', %q{
shareable = Ractor.make_shareable("chilled")
shareable == "chilled" && Ractor.shareable?(shareable)
}
+
+# require in Ractor
+assert_equal 'true', %q{
+ Module.new do
+ def require feature
+ return Ractor._require(feature) unless Ractor.main?
+ super
+ end
+ Object.prepend self
+ set_temporary_name 'Ractor#require'
+ end
+
+ Ractor.new{
+ begin
+ require 'tempfile'
+ Tempfile.new
+ rescue SystemStackError
+ # prism parser with -O0 build consumes a lot of machine stack
+ Data.define(:fileno).new(1)
+ end
+ }.value.fileno > 0
+}
+
+# require_relative in Ractor
+assert_equal 'true', %q{
+ dummyfile = File.join(__dir__, "dummy#{rand}.rb")
+ return true if File.exist?(dummyfile)
+
+ begin
+ File.write dummyfile, ''
+ rescue Exception
+ # skip on any errors
+ return true
+ end
+
+ begin
+ Ractor.new dummyfile do |f|
+ require_relative File.basename(f)
+ end.value
+ ensure
+ File.unlink dummyfile
+ end
+}
+
+# require_relative in Ractor
+assert_equal 'LoadError', %q{
+ dummyfile = File.join(__dir__, "not_existed_dummy#{rand}.rb")
+ return true if File.exist?(dummyfile)
+
+ Ractor.new dummyfile do |f|
+ begin
+ require_relative File.basename(f)
+ rescue LoadError => e
+ e.class
+ end
+ end.value
+}
+
+# autolaod in Ractor
+assert_equal 'true', %q{
+ autoload :Tempfile, 'tempfile'
+
+ r = Ractor.new do
+ begin
+ Tempfile.new
+ rescue SystemStackError
+ # prism parser with -O0 build consumes a lot of machine stack
+ Data.define(:fileno).new(1)
+ end
+ end
+ r.value.fileno > 0
+}
+
+# failed in autolaod in Ractor
+assert_equal 'LoadError', %q{
+ dummyfile = File.join(__dir__, "not_existed_dummy#{rand}.rb")
+ autoload :Tempfile, dummyfile
+
+ r = Ractor.new do
+ begin
+ Tempfile.new
+ rescue LoadError => e
+ e.class
+ end
+ end
+ r.value
+}
+
+# bind_call in Ractor [Bug #20934]
+assert_equal 'ok', %q{
+ 2.times.map do
+ Ractor.new do
+ 1000.times do
+ Object.instance_method(:itself).bind_call(self)
+ end
+ end
+ end.each(&:join)
+ GC.start
+ :ok.itself
+}
+
+# moved objects being corrupted if embeded (String)
+assert_equal 'ok', %q{
+ ractor = Ractor.new { Ractor.receive }
+ obj = "foobarbazfoobarbazfoobarbazfoobarbaz"
+ ractor.send(obj.dup, move: true)
+ roundtripped_obj = ractor.value
+ roundtripped_obj == obj ? :ok : roundtripped_obj
+}
+
+# moved objects being corrupted if embeded (Array)
+assert_equal 'ok', %q{
+ ractor = Ractor.new { Ractor.receive }
+ obj = Array.new(10, 42)
+ ractor.send(obj.dup, move: true)
+ roundtripped_obj = ractor.value
+ roundtripped_obj == obj ? :ok : roundtripped_obj
+}
+
+# moved objects being corrupted if embeded (Hash)
+assert_equal 'ok', %q{
+ ractor = Ractor.new { Ractor.receive }
+ obj = { foo: 1, bar: 2 }
+ ractor.send(obj.dup, move: true)
+ roundtripped_obj = ractor.value
+ roundtripped_obj == obj ? :ok : roundtripped_obj
+}
+
+# moved objects being corrupted if embeded (MatchData)
+assert_equal 'ok', %q{
+ ractor = Ractor.new { Ractor.receive }
+ obj = "foo".match(/o/)
+ ractor.send(obj.dup, move: true)
+ roundtripped_obj = ractor.value
+ roundtripped_obj == obj ? :ok : roundtripped_obj
+}
+
+# moved objects being corrupted if embeded (Struct)
+assert_equal 'ok', %q{
+ ractor = Ractor.new { Ractor.receive }
+ obj = Struct.new(:a, :b, :c, :d, :e, :f).new(1, 2, 3, 4, 5, 6)
+ ractor.send(obj.dup, move: true)
+ roundtripped_obj = ractor.value
+ roundtripped_obj == obj ? :ok : roundtripped_obj
+}
+
+# moved objects being corrupted if embeded (Object)
+assert_equal 'ok', %q{
+ ractor = Ractor.new { Ractor.receive }
+ class SomeObject
+ attr_reader :a, :b, :c, :d, :e, :f
+ def initialize
+ @a = @b = @c = @d = @e = @f = 1
+ end
+
+ def ==(o)
+ @a == o.a &&
+ @b == o.b &&
+ @c == o.c &&
+ @d == o.d &&
+ @e == o.e &&
+ @f == o.f
+ end
+ end
+
+ SomeObject.new # initial non-embeded
+
+ obj = SomeObject.new
+ ractor.send(obj.dup, move: true)
+ roundtripped_obj = ractor.value
+ roundtripped_obj == obj ? :ok : roundtripped_obj
+}
+
+# moved arrays can't be used
+assert_equal 'ok', %q{
+ ractor = Ractor.new { Ractor.receive }
+ obj = [1]
+ ractor.send(obj, move: true)
+ begin
+ [].concat(obj)
+ rescue TypeError
+ :ok
+ else
+ :fail
+ end
+}
+
+# moved strings can't be used
+assert_equal 'ok', %q{
+ ractor = Ractor.new { Ractor.receive }
+ obj = "hello"
+ ractor.send(obj, move: true)
+ begin
+ "".replace(obj)
+ rescue TypeError
+ :ok
+ else
+ :fail
+ end
+}
+
+# moved hashes can't be used
+assert_equal 'ok', %q{
+ ractor = Ractor.new { Ractor.receive }
+ obj = { a: 1 }
+ ractor.send(obj, move: true)
+ begin
+ {}.merge(obj)
+ rescue TypeError
+ :ok
+ else
+ :fail
+ end
+}
+
+# move objects inside frozen containers
+assert_equal 'ok', %q{
+ ractor = Ractor.new { Ractor.receive }
+ obj = Array.new(10, 42)
+ original = obj.dup
+ ractor.send([obj].freeze, move: true)
+ roundtripped_obj = ractor.value[0]
+ roundtripped_obj == original ? :ok : roundtripped_obj
+}
+
+# move object with generic ivar
+assert_equal 'ok', %q{
+ ractor = Ractor.new { Ractor.receive }
+ obj = Array.new(10, 42)
+ obj.instance_variable_set(:@array, [1])
+
+ ractor.send(obj, move: true)
+ roundtripped_obj = ractor.value
+ roundtripped_obj.instance_variable_get(:@array) == [1] ? :ok : roundtripped_obj
+}
+
+# move object with many generic ivars
+assert_equal 'ok', %q{
+ ractor = Ractor.new { Ractor.receive }
+ obj = Array.new(10, 42)
+ 0.upto(300) do |i|
+ obj.instance_variable_set(:"@array#{i}", [i])
+ end
+
+ ractor.send(obj, move: true)
+ roundtripped_obj = ractor.value
+ roundtripped_obj.instance_variable_get(:@array1) == [1] ? :ok : roundtripped_obj
+}
+
+# move object with complex generic ivars
+assert_equal 'ok', %q{
+ # Make Array too_complex
+ 30.times { |i| [].instance_variable_set(:"@complex#{i}", 1) }
+
+ ractor = Ractor.new { Ractor.receive }
+ obj = Array.new(10, 42)
+ obj.instance_variable_set(:@array1, [1])
+
+ ractor.send(obj, move: true)
+ roundtripped_obj = ractor.value
+ roundtripped_obj.instance_variable_get(:@array1) == [1] ? :ok : roundtripped_obj
+}
+
+# move object with generic ivars and existing id2ref table
+# [Bug #21664]
+assert_equal 'ok', %q{
+ obj = [1]
+ obj.instance_variable_set("@field", :ok)
+ ObjectSpace._id2ref(obj.object_id) # build id2ref table
+
+ ractor = Ractor.new { Ractor.receive }
+ ractor.send(obj, move: true)
+ obj = ractor.value
+ obj.instance_variable_get("@field")
+}
+
+# copy object with complex generic ivars
+assert_equal 'ok', %q{
+ # Make Array too_complex
+ 30.times { |i| [].instance_variable_set(:"@complex#{i}", 1) }
+
+ ractor = Ractor.new { Ractor.receive }
+ obj = Array.new(10, 42)
+ obj.instance_variable_set(:@array1, [1])
+
+ ractor.send(obj)
+ roundtripped_obj = ractor.value
+ roundtripped_obj.instance_variable_get(:@array1) == [1] ? :ok : roundtripped_obj
+}
+
+# copy object with many generic ivars
+assert_equal 'ok', %q{
+ ractor = Ractor.new { Ractor.receive }
+ obj = Array.new(10, 42)
+ 0.upto(300) do |i|
+ obj.instance_variable_set(:"@array#{i}", [i])
+ end
+
+ ractor.send(obj)
+ roundtripped_obj = ractor.value
+ roundtripped_obj.instance_variable_get(:@array1) == [1] ? :ok : roundtripped_obj
+}
+
+# moved composite types move their non-shareable parts properly
+assert_equal 'ok', %q{
+ k, v = String.new("key"), String.new("value")
+ h = { k => v }
+ h.instance_variable_set("@b", String.new("b"))
+ a = [k,v]
+ o_singleton = Object.new
+ def o_singleton.a
+ @a
+ end
+ o_singleton.instance_variable_set("@a", String.new("a"))
+ class MyObject
+ attr_reader :a
+ def initialize(a)
+ @a = a
+ end
+ end
+ struct_class = Struct.new(:a)
+ struct = struct_class.new(String.new('a'))
+ o = MyObject.new(String.new('a'))
+ port = Ractor::Port.new
+
+ r = Ractor.new port do |port|
+ loop do
+ obj = Ractor.receive
+ val = case obj
+ when Hash
+ obj['key'] == 'value' && obj.instance_variable_get("@b") == 'b'
+ when Array
+ obj[0] == 'key'
+ when Struct
+ obj.a == 'a'
+ when Object
+ obj.a == 'a'
+ end
+ port << val
+ end
+ end
+
+ objs = [h, a, o_singleton, o, struct]
+ objs.each_with_index do |obj, i|
+ klass = obj.class
+ parts_moved = {}
+ case obj
+ when Hash
+ parts_moved[klass] = [obj['key'], obj.instance_variable_get("@b")]
+ when Array
+ parts_moved[klass] = obj.dup # the contents
+ when Struct, Object
+ parts_moved[klass] = [obj.a]
+ end
+ r.send(obj, move: true)
+ val = port.receive
+ if val != true
+ raise "bad val in ractor for obj at i:#{i}"
+ end
+ begin
+ p obj
+ rescue
+ else
+ raise "should be moved"
+ end
+ parts_moved.each do |klass, parts|
+ parts.each_with_index do |part, j|
+ case part
+ when Ractor::MovedObject
+ else
+ raise "part for class #{klass} at i:#{j} should be moved"
+ end
+ end
+ end
+ end
+ 'ok'
+}
+
+# fork after creating Ractor
+assert_equal 'ok', %q{
+begin
+ Ractor.new { Ractor.receive }
+ _, status = Process.waitpid2 fork { }
+ status.success? ? "ok" : status
+rescue NotImplementedError
+ :ok
+end
+}
+
+# Ractors should be terminated after fork
+assert_equal 'ok', %q{
+begin
+ r = Ractor.new { Ractor.receive }
+ _, status = Process.waitpid2 fork {
+ begin
+ raise if r.value != nil
+ end
+ }
+ r.send(123)
+ raise unless r.value == 123
+ status.success? ? "ok" : status
+rescue NotImplementedError
+ :ok
+end
+}
+
+# Ractors should be terminated after fork
+assert_equal 'ok', %q{
+begin
+ r = Ractor.new { Ractor.receive }
+ _, status = Process.waitpid2 fork {
+ begin
+ r.send(123)
+ rescue Ractor::ClosedError
+ end
+ }
+ r.send(123)
+ raise unless r.value == 123
+ status.success? ? "ok" : status
+rescue NotImplementedError
+ :ok
+end
+}
+
+# Creating classes inside of Ractors
+# [Bug #18119]
+assert_equal 'ok', %q{
+ port = Ractor::Port.new
+ workers = (0...8).map do
+ Ractor.new port do |port|
+ loop do
+ 100.times.map { Class.new }
+ port << nil
+ end
+ end
+ end
+
+ 100.times { port.receive }
+
+ 'ok'
+}
+
+# Using Symbol#to_proc inside ractors
+# [Bug #21354]
+assert_equal 'ok', %q{
+ :inspect.to_proc
+ Ractor.new do
+ # It should not use this cached proc, it should create a new one. If it used
+ # the cached proc, we would get a ractor_confirm_belonging error here.
+ :inspect.to_proc
+ end.join
+ 'ok'
+}
+
+# take vm lock when deleting generic ivars from the global table
+assert_equal 'ok', %q{
+ Ractor.new do
+ a = [1, 2, 3]
+ a.object_id
+ a.dup # this deletes generic ivar on dupped object
+ 'ok'
+ end.value
+}
+
+## Ractor#monitor
+
+# monitor port returns `:exited` when the monitering Ractor terminated.
+assert_equal 'true', %q{
+ r = Ractor.new do
+ Ractor.main << :ok1
+ :ok2
+ end
+
+ r.monitor port = Ractor::Port.new
+ Ractor.receive # :ok1
+ port.receive == :exited
+}
+
+# monitor port returns `:exited` even if the monitoring Ractor was terminated.
+assert_equal 'true', %q{
+ r = Ractor.new do
+ :ok
+ end
+
+ r.join # wait for r's terminateion
+
+ r.monitor port = Ractor::Port.new
+ port.receive == :exited
+}
+
+# monitor returns false if the monitoring Ractor was terminated.
+assert_equal 'false', %q{
+ r = Ractor.new do
+ :ok
+ end
+
+ r.join # wait for r's terminateion
+
+ r.monitor Ractor::Port.new
+}
+
+# monitor port returns `:aborted` when the monitering Ractor is aborted.
+assert_equal 'true', %q{
+ r = Ractor.new do
+ Ractor.main << :ok1
+ raise 'ok'
+ end
+
+ r.monitor port = Ractor::Port.new
+ Ractor.receive # :ok1
+ port.receive == :aborted
+}
+
+# monitor port returns `:aborted` even if the monitoring Ractor was aborted.
+assert_equal 'true', %q{
+ r = Ractor.new do
+ raise 'ok'
+ end
+
+ begin
+ r.join # wait for r's terminateion
+ rescue Ractor::RemoteError
+ # ignore
+ end
+
+ r.monitor port = Ractor::Port.new
+ port.receive == :aborted
+}
+
+## Ractor#join
+
+# Ractor#join returns self when the Ractor is terminated.
+assert_equal 'true', %q{
+ r = Ractor.new do
+ Ractor.receive
+ end
+
+ r << :ok
+ r.join
+ r.inspect in /terminated/
+} if false # TODO
+
+# Ractor#join raises RemoteError when the remote Ractor aborted with an exception
+assert_equal 'err', %q{
+ r = Ractor.new do
+ raise 'err'
+ end
+
+ begin
+ r.join
+ rescue Ractor::RemoteError => e
+ e.cause.message
+ end
+}
+
+## Ractor#value
+
+# Ractor#value returns the last expression even if it is unshareable
+assert_equal 'true', %q{
+ r = Ractor.new do
+ obj = [1, 2]
+ obj << obj.object_id
+ end
+
+ ret = r.value
+ ret == [1, 2, ret.object_id]
+}
+
+# Only one Ractor can call Ractor#value
+assert_equal '[["Only the successor ractor can take a value", 9], ["ok", 2]]', %q{
+ r = Ractor.new do
+ 'ok'
+ end
+
+ RN = 10
+
+ rs = RN.times.map do
+ Ractor.new r do |r|
+ begin
+ Ractor.main << r.value
+ Ractor.main << r.value # this ractor can get same result
+ rescue Ractor::Error => e
+ Ractor.main << e.message
+ end
+ end
+ end
+
+ (RN+1).times.map{
+ Ractor.receive
+ }.tally.sort
+}
+
+# Cause lots of inline CC misses.
+assert_equal 'ok', <<~'RUBY'
+ class A; def test; 1 + 1; end; end
+ class B; def test; 1 + 1; end; end
+ class C; def test; 1 + 1; end; end
+ class D; def test; 1 + 1; end; end
+ class E; def test; 1 + 1; end; end
+ class F; def test; 1 + 1; end; end
+ class G; def test; 1 + 1; end; end
+
+ objs = [A.new, B.new, C.new, D.new, E.new, F.new, G.new].freeze
+
+ def call_test(obj)
+ obj.test
+ end
+
+ ractors = 7.times.map do
+ Ractor.new(objs) do |objs|
+ objs = objs.shuffle
+ 100_000.times do
+ objs.each do |o|
+ call_test(o)
+ end
+ end
+ end
+ end
+ ractors.each(&:join)
+ :ok
+RUBY
+
+# This test checks that we do not trigger a GC when we have malloc with Ractor
+# locks. We cannot trigger a GC with Ractor locks because GC requires VM lock
+# and Ractor barrier. If another Ractor is waiting on this Ractor lock, then it
+# will deadlock because the other Ractor will never join the barrier.
+#
+# Creating Ractor::Port requires locking the Ractor and inserting into an
+# st_table, which can call malloc.
+assert_equal 'ok', <<~'RUBY'
+ r = Ractor.new do
+ loop do
+ Ractor::Port.new
+ end
+ end
+
+ 10.times do
+ 10_000.times do
+ r.send(nil)
+ end
+ sleep(0.01)
+ end
+ :ok
+RUBY
+
+assert_equal 'ok', <<~'RUBY'
+ begin
+ 100.times do |i|
+ Ractor.new(i) do |j|
+ 1000.times do |i|
+ "#{j}-#{i}"
+ end
+ Ractor.receive
+ end
+ pid = fork { }
+ _, status = Process.waitpid2 pid
+ raise unless status.success?
+ end
+
+ :ok
+ rescue NotImplementedError
+ :ok
+ end
+RUBY
+
+assert_equal 'ok', <<~'RUBY'
+ begin
+ 100.times do |i|
+ Ractor.new(i) do |j|
+ 1000.times do |i|
+ "#{j}-#{i}"
+ end
+ end
+ pid = fork do
+ GC.verify_internal_consistency
+ end
+ _, status = Process.waitpid2 pid
+ raise unless status.success?
+ end
+
+ :ok
+ rescue NotImplementedError
+ :ok
+ end
+RUBY
+
+# When creating bmethods in Ractors, they should only be usable from their
+# defining ractor, even if it is GC'd
+assert_equal 'ok', <<~'RUBY'
+
+begin
+ CLASSES = 1000.times.map { Class.new }.freeze
+
+ # This would be better to run in parallel, but there's a bug with lambda
+ # creation and YJIT causing crashes in dev mode
+ ractors = CLASSES.map do |klass|
+ Ractor.new(klass) do |klass|
+ Ractor.receive
+ klass.define_method(:foo) {}
+ end
+ end
+
+ ractors.each do |ractor|
+ ractor << nil
+ ractor.join
+ end
+
+ ractors.clear
+ GC.start
+
+ any = 1000.times.map do
+ Ractor.new do
+ CLASSES.any? do |klass|
+ begin
+ klass.new.foo
+ true
+ rescue RuntimeError
+ false
+ end
+ end
+ end
+ end.map(&:value).none? && :ok
+rescue ThreadError => e
+ # ignore limited memory machine
+ if /can\'t create Thread/ =~ e.message
+ :ok
+ else
+ raise
+ end
+end
+RUBY
diff --git a/bootstraptest/test_rjit.rb b/bootstraptest/test_rjit.rb
deleted file mode 100644
index e123f35160..0000000000
--- a/bootstraptest/test_rjit.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# VM_CALL_OPT_SEND + VM_METHOD_TYPE_ATTRSET
-assert_equal '1', %q{
- class Foo
- attr_writer :foo
-
- def bar
- send(:foo=, 1)
- end
- end
-
- Foo.new.bar
-}
-
-# VM_CALL_OPT_SEND + OPTIMIZED_METHOD_TYPE_CALL
-assert_equal 'foo', %q{
- def bar(&foo)
- foo.send(:call)
- end
-
- bar { :foo }
-}
-
-# VM_CALL_OPT_SEND + OPTIMIZED_METHOD_TYPE_STRUCT_AREF
-assert_equal 'bar', %q{
- def bar(foo)
- foo.send(:bar)
- end
-
- bar(Struct.new(:bar).new(:bar))
-}
-
-# kwargs default w/ checkkeyword + locals (which shouldn't overwrite unspecified_bits)
-assert_equal '1', %q{
- def foo(bar: 1.to_s)
- _ = 1
- bar
- end
-
- def entry
- foo
- end
-
- entry
-}
-
-# Updating local type in Context
-assert_normal_exit %q{
- def foo(flag, object)
- klass = if flag
- object
- end
- klass ||= object
- return klass.new
- end
-
- foo(false, Object)
- foo(true, Object)
-}
diff --git a/bootstraptest/test_thread.rb b/bootstraptest/test_thread.rb
index a4d46e2f10..7ff5bb4a38 100644
--- a/bootstraptest/test_thread.rb
+++ b/bootstraptest/test_thread.rb
@@ -257,8 +257,7 @@ assert_equal 'true', %{
}
assert_equal 'ok', %{
- open("zzz_t1.rb", "w") do |f|
- f.puts <<-END
+ File.write("zzz_t1.rb", <<-END)
begin
Thread.new { fork { GC.start } }.join
pid, status = Process.wait2
@@ -267,7 +266,6 @@ assert_equal 'ok', %{
$result = :ok
end
END
- end
require "./zzz_t1.rb"
$result
}
@@ -303,7 +301,7 @@ assert_normal_exit %q{
}.each {|t|
t.join
}
-} unless rjit_enabled? # flaky
+}
assert_equal 'ok', %q{
def m
@@ -422,8 +420,7 @@ assert_equal 'ok', %q{
}
assert_equal 'ok', %{
- open("zzz_t2.rb", "w") do |f|
- f.puts <<-'end;' # do
+ File.write("zzz_t2.rb", <<-'end;') # do
begin
m = Thread::Mutex.new
parent = Thread.current
@@ -445,7 +442,6 @@ assert_equal 'ok', %{
$result = :ok
end
end;
- end
require "./zzz_t2.rb"
$result
}
@@ -497,7 +493,8 @@ assert_equal 'foo', %q{
[th1, th2].each {|t| t.join }
GC.start
f.call.source
-} unless rjit_enabled? # flaky
+}
+
assert_normal_exit %q{
class C
def inspect
diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb
index 76406ab601..be66395190 100644
--- a/bootstraptest/test_yjit.rb
+++ b/bootstraptest/test_yjit.rb
@@ -37,27 +37,35 @@ assert_equal "ok", %q{
}
# test discarding extra yield arguments
-assert_equal "2210150001501015", %q{
+assert_equal "22131300500015901015", %q{
def splat_kw(ary) = yield *ary, a: 1
def splat(ary) = yield *ary
- def kw = yield 1, 2, a: 0
+ def kw = yield 1, 2, a: 3
+
+ def kw_only = yield a: 0
def simple = yield 0, 1
+ def none = yield
+
def calls
[
splat([1, 1, 2]) { |x, y| x + y },
splat([1, 1, 2]) { |y, opt = raise| opt + y},
splat_kw([0, 1]) { |a:| a },
kw { |a:| a },
- kw { |a| a },
+ kw { |one| one },
+ kw { |one, a:| a },
+ kw_only { |a:| a },
+ kw_only { |a: 1| a },
simple { 5.itself },
simple { |a| a },
simple { |opt = raise| opt },
simple { |*rest| rest },
simple { |opt_kw: 5| opt_kw },
+ none { |a: 9| a },
# autosplat ineractions
[0, 1, 2].yield_self { |a, b| [a, b] },
[0, 1, 2].yield_self { |a, opt = raise| [a, opt] },
@@ -106,7 +114,7 @@ assert_equal '[:ae, :ae]', %q{
end
[test(Array.new 5), test([])]
-} unless rjit_enabled? # Not yet working on RJIT
+}
# regression test for arity check with splat and send
assert_equal '[:ae, :ae]', %q{
@@ -123,6 +131,7 @@ assert_equal '[:ae, :ae]', %q{
# regression test for GC marking stubs in invalidated code
assert_normal_exit %q{
+ skip true unless GC.respond_to?(:compact)
garbage = Array.new(10_000) { [] } # create garbage to cause iseq movement
eval(<<~RUBY)
def foo(n, garbage)
@@ -157,7 +166,7 @@ assert_equal '0', "0.abs(&nil)"
# regression test for invokeblock iseq guard
assert_equal 'ok', %q{
- return :ok unless defined?(GC.compact)
+ skip :ok unless GC.respond_to?(:compact)
def foo = yield
10.times do |i|
ret = eval("foo { #{i} }")
@@ -165,7 +174,7 @@ assert_equal 'ok', %q{
GC.compact
end
:ok
-} unless rjit_enabled? # Not yet working on RJIT
+}
# regression test for overly generous guard elision
assert_equal '[0, :sum, 0, :sum]', %q{
@@ -211,6 +220,15 @@ assert_equal 'Sub', %q{
call(Sub.new('o')).class
}
+# String#dup with generic ivars
+assert_equal '["str", "ivar"]', %q{
+ def str_dup(str) = str.dup
+ str = "str"
+ str.instance_variable_set(:@ivar, "ivar")
+ str = str_dup(str)
+ [str, str.instance_variable_get(:@ivar)]
+}
+
# test splat filling required and feeding rest
assert_equal '[0, 1, 2, [3, 4]]', %q{
public def lead_rest(a, b, *rest)
@@ -293,7 +311,7 @@ assert_equal '[:ok]', %q{
# Used to crash due to GC run in rb_ensure_iv_list_size()
# not marking the newly allocated [:ok].
RegressionTest.new.extender.itself
-} unless rjit_enabled? # Skip on RJIT since this uncovers a crash
+}
assert_equal 'true', %q{
# regression test for tracking type of locals for too long
@@ -450,91 +468,6 @@ assert_normal_exit %q{
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
@@ -592,6 +525,8 @@ assert_equal 'string', %q{
# Check that exceptions work when getting global variable
assert_equal 'rescued', %q{
+ Warning[:deprecated] = true
+
module Warning
def warn(message)
raise
@@ -1227,6 +1162,7 @@ assert_equal 'special', %q{
# Test that object references in generated code get marked and moved
assert_equal "good", %q{
+ skip :good unless GC.respond_to?(:compact)
def bar
"good"
end
@@ -1394,7 +1330,7 @@ assert_equal '[42, :default]', %q{
]
}
-# Test default value block for Hash with opt_aref_with
+# Test default value block for Hash
assert_equal "false", <<~RUBY, frozen_string_literal: false
def index_with_string(h)
h["foo"]
@@ -1794,7 +1730,7 @@ assert_equal '{}', %q{
}
# test building hash with values
-assert_equal '{:foo=>:bar}', %q{
+assert_equal '{foo: :bar}', %q{
def build_hash(val)
{ foo: val }
end
@@ -2044,7 +1980,7 @@ assert_equal '[97, :nil, 97, :nil, :raised]', %q{
getbyte("a", 0)
[getbyte("a", 0), getbyte("a", 1), getbyte("a", -1), getbyte("a", -2), getbyte("a", "a")]
-} unless rjit_enabled? # Not yet working on RJIT
+}
# Basic test for String#setbyte
assert_equal 'AoZ', %q{
@@ -2252,6 +2188,34 @@ assert_equal '7', %q{
foo(5,2)
}
+# regression test for argument registers with invalidation
+assert_equal '[0, 1, 2]', %q{
+ def test(n)
+ ret = n
+ binding
+ ret
+ end
+
+ [0, 1, 2].map do |n|
+ test(n)
+ end
+}
+
+# regression test for argument registers
+assert_equal 'true', %q{
+ class Foo
+ def ==(other)
+ other == nil
+ end
+ end
+
+ def test
+ [Foo.new].include?(Foo.new)
+ end
+
+ test
+}
+
# test pattern matching
assert_equal '[:ok, :ok]', %q{
class C
@@ -2319,6 +2283,7 @@ assert_equal '123', %q{
# Test EP == BP invalidation with moving ISEQs
assert_equal 'ok', %q{
+ skip :ok unless GC.respond_to?(:compact)
def entry
ok = proc { :ok } # set #entry as an EP-escaping ISEQ
[nil].reverse_each do # avoid exiting the JIT frame on the constant
@@ -2713,7 +2678,23 @@ assert_equal '[1, 2]', %q{
expandarray_redefined_nilclass
expandarray_redefined_nilclass
-} unless rjit_enabled?
+}
+
+assert_equal 'not_array', %q{
+ def expandarray_not_array(obj)
+ a, = obj
+ a
+ end
+
+ obj = Object.new
+ def obj.method_missing(m, *args, &block)
+ return [:not_array] if m == :to_ary
+ super
+ end
+
+ expandarray_not_array(obj)
+ expandarray_not_array(obj)
+}
assert_equal '[1, 2, nil]', %q{
def expandarray_rhs_too_small
@@ -2825,7 +2806,7 @@ assert_equal '[[:c_return, :String, :string_alias, "events_to_str"]]', %q{
events.compiled(events)
events
-} unless rjit_enabled? # RJIT calls extra Ruby methods
+}
# test enabling a TracePoint that targets a particular line in a C method call
assert_equal '[true]', %q{
@@ -2907,7 +2888,7 @@ assert_equal '[[:c_call, :itself]]', %q{
tp.enable { shouldnt_compile }
events
-} unless rjit_enabled? # RJIT calls extra Ruby methods
+}
# test enabling c_return tracing before compiling
assert_equal '[[:c_return, :itself, main]]', %q{
@@ -2922,7 +2903,7 @@ assert_equal '[[:c_return, :itself, main]]', %q{
tp.enable { shouldnt_compile }
events
-} unless rjit_enabled? # RJIT calls extra Ruby methods
+}
# test c_call invalidation
assert_equal '[[:c_call, :itself]]', %q{
@@ -2968,15 +2949,16 @@ assert_equal '[:itself]', %q{
itself
end
- tracing_ractor = Ractor.new do
+ port = Ractor::Port.new
+ tracing_ractor = Ractor.new port do |port|
# 1: start tracing
events = []
tp = TracePoint.new(:c_call) { events << _1.method_id }
tp.enable
- Ractor.yield(nil)
+ port << nil
# 3: run compiled method on tracing ractor
- Ractor.yield(nil)
+ port << nil
traced_method
events
@@ -2984,13 +2966,13 @@ assert_equal '[:itself]', %q{
tp&.disable
end
- tracing_ractor.take
+ port.receive
# 2: compile on non tracing ractor
traced_method
- tracing_ractor.take
- tracing_ractor.take
+ port.receive
+ tracing_ractor.value
}
# Try to hit a lazy branch stub while another ractor enables tracing
@@ -3004,17 +2986,18 @@ assert_equal '42', %q{
end
end
- ractor = Ractor.new do
+ port = Ractor::Port.new
+ ractor = Ractor.new port do |port|
compiled(false)
- Ractor.yield(nil)
+ port << nil
compiled(41)
end
tp = TracePoint.new(:line) { itself }
- ractor.take
+ port.receive
tp.enable
- ractor.take
+ ractor.value
}
# Test equality with changing types
@@ -3090,7 +3073,7 @@ assert_equal '42', %q{
A.foo
A.foo
- Ractor.new { A.foo }.take
+ Ractor.new { A.foo }.value
}
assert_equal '["plain", "special", "sub", "plain"]', %q{
@@ -3342,7 +3325,7 @@ assert_equal '[[1, 2, 3, 4]]', %q{
}
# cfunc kwargs
-assert_equal '{:foo=>123}', %q{
+assert_equal '{foo: 123}', %q{
def foo(bar)
bar.store(:value, foo: 123)
bar[:value]
@@ -3353,7 +3336,7 @@ assert_equal '{:foo=>123}', %q{
}
# cfunc kwargs
-assert_equal '{:foo=>123}', %q{
+assert_equal '{foo: 123}', %q{
def foo(bar)
bar.replace(foo: 123)
end
@@ -3363,7 +3346,7 @@ assert_equal '{:foo=>123}', %q{
}
# cfunc kwargs
-assert_equal '{:foo=>123, :bar=>456}', %q{
+assert_equal '{foo: 123, bar: 456}', %q{
def foo(bar)
bar.replace(foo: 123, bar: 456)
end
@@ -3373,7 +3356,7 @@ assert_equal '{:foo=>123, :bar=>456}', %q{
}
# variadic cfunc kwargs
-assert_equal '{:foo=>123}', %q{
+assert_equal '{foo: 123}', %q{
def foo(bar)
bar.merge(foo: 123)
end
@@ -3497,7 +3480,7 @@ assert_equal "true", %q{
}
# duphash
-assert_equal '{:foo=>123}', %q{
+assert_equal '{foo: 123}', %q{
def foo
{foo: 123}
end
@@ -3507,7 +3490,7 @@ assert_equal '{:foo=>123}', %q{
}
# newhash
-assert_equal '{:foo=>2}', %q{
+assert_equal '{foo: 2}', %q{
def foo
{foo: 1+1}
end
@@ -3617,6 +3600,74 @@ assert_equal 'new', %q{
test
}
+# Bug #21257 (infinite jmp)
+assert_equal 'ok', %q{
+ Good = :ok
+
+ def first
+ second
+ end
+
+ def second
+ ::Good
+ end
+
+ # Make `second` side exit on its first instruction
+ trace = TracePoint.new(:line) { }
+ trace.enable(target: method(:second))
+
+ first
+ # Recompile now that the constant cache is populated, so we get a fallthrough from `first` to `second`
+ # (this is need to reproduce with --yjit-call-threshold=1)
+ RubyVM::YJIT.code_gc if defined?(RubyVM::YJIT)
+ first
+
+ # Trigger a constant cache miss in rb_vm_opt_getconstant_path (in `second`) next time it's called
+ module InvalidateConstantCache
+ Good = nil
+ end
+
+ RubyVM::YJIT.simulate_oom! if defined?(RubyVM::YJIT)
+
+ first
+ first
+}
+
+assert_equal 'ok', %q{
+ # Multiple incoming branches into second
+ Good = :ok
+
+ def incoming_one
+ second
+ end
+
+ def incoming_two
+ second
+ end
+
+ def second
+ ::Good
+ end
+
+ # Make `second` side exit on its first instruction
+ trace = TracePoint.new(:line) { }
+ trace.enable(target: method(:second))
+
+ incoming_one
+ # Recompile now that the constant cache is populated, so we get a fallthrough from `incoming_one` to `second`
+ # (this is need to reproduce with --yjit-call-threshold=1)
+ RubyVM::YJIT.code_gc if defined?(RubyVM::YJIT)
+ incoming_one
+ incoming_two
+
+ # Trigger a constant cache miss in rb_vm_opt_getconstant_path (in `second`) next time it's called
+ module InvalidateConstantCache
+ Good = nil
+ end
+
+ incoming_one
+}
+
assert_equal 'ok', %q{
# Try to compile new method while OOM
def foo
@@ -3741,36 +3792,6 @@ assert_equal '3,12', %q{
pt_inspect(p)
}
-# Regression test for deadlock between branch_stub_hit and ractor_receive_if
-assert_equal '10', %q{
- r = Ractor.new Ractor.current do |main|
- main << 1
- main << 2
- main << 3
- main << 4
- main << 5
- main << 6
- main << 7
- main << 8
- main << 9
- main << 10
- end
-
- a = []
- a << Ractor.receive_if{|msg| msg == 10}
- a << Ractor.receive_if{|msg| msg == 9}
- a << Ractor.receive_if{|msg| msg == 8}
- a << Ractor.receive_if{|msg| msg == 7}
- a << Ractor.receive_if{|msg| msg == 6}
- a << Ractor.receive_if{|msg| msg == 5}
- a << Ractor.receive_if{|msg| msg == 4}
- a << Ractor.receive_if{|msg| msg == 3}
- a << Ractor.receive_if{|msg| msg == 2}
- a << Ractor.receive_if{|msg| msg == 1}
-
- a.length
-}
-
# checktype
assert_equal 'false', %q{
def function()
@@ -4076,6 +4097,26 @@ assert_equal '1', %q{
bar { }
}
+# unshareable bmethod call through Method#to_proc#call
+assert_equal '1000', %q{
+ define_method(:bmethod) do
+ self
+ end
+
+ Ractor.new do
+ errors = 0
+ 1000.times do
+ p = method(:bmethod).to_proc
+ begin
+ p.call
+ rescue RuntimeError
+ errors += 1
+ end
+ end
+ errors
+ end.value
+}
+
# test for return stub lifetime issue
assert_equal '1', %q{
def foo(n)
@@ -4316,7 +4357,7 @@ assert_equal "ArgumentError", %q{
# Rest with block
# Simplified code from railsbench
-assert_equal '[{"/a"=>"b", :as=>:c, :via=>:post}, [], nil]', %q{
+assert_equal '[{"/a" => "b", as: :c, via: :post}, [], nil]', %q{
def match(path, *rest, &block)
[path, rest, block]
end
@@ -4444,7 +4485,7 @@ assert_equal 'true', %q{
rescue ArgumentError
true
end
-} unless rjit_enabled? # Not yet working on RJIT
+}
# Regression test: register allocator on expandarray
assert_equal '[]', %q{
@@ -4561,6 +4602,11 @@ assert_equal '[2, 4611686018427387904]', %q{
[1.succ, 4611686018427387903.succ]
}
+# Integer pred and overflow
+assert_equal '[0, -4611686018427387905]', %q{
+ [1.pred, -4611686018427387904.pred]
+}
+
# Integer right shift
assert_equal '[0, 1, -4]', %q{
[0 >> 1, 2 >> 1, -7 >> 1]
@@ -4577,7 +4623,7 @@ assert_equal '[nil, "yield"]', %q{
}
# splat with ruby2_keywords into rest parameter
-assert_equal '[[{:a=>1}], {}]', %q{
+assert_equal '[[{a: 1}], {}]', %q{
ruby2_keywords def foo(*args) = args
def bar(*args, **kw) = [args, kw]
@@ -4618,7 +4664,7 @@ assert_normal_exit %q{
}
# a kwrest case
-assert_equal '[1, 2, {:complete=>false}]', %q{
+assert_equal '[1, 2, {complete: false}]', %q{
def rest(foo: 1, bar: 2, **kwrest)
[foo, bar, kwrest]
end
@@ -4677,7 +4723,7 @@ assert_equal '[[1, 2, 3], [0, 2, 3], [1, 2, 3], [2, 2, 3], [], [], [{}]]', %q{
}
# Class#new (arity=-1), splat, and ruby2_keywords
-assert_equal '[0, {1=>1}]', %q{
+assert_equal '[0, {1 => 1}]', %q{
class KwInit
attr_reader :init_args
def initialize(x = 0, **kw)
@@ -4693,7 +4739,7 @@ assert_equal '[0, {1=>1}]', %q{
}
# Chilled string setivar trigger warning
-assert_equal 'literal string will be frozen in the future', %q{
+assert_match(/literal string will be frozen in the future/, %q{
Warning[:deprecated] = true
$VERBOSE = true
$warning = "no-warning"
@@ -4721,7 +4767,7 @@ assert_equal 'literal string will be frozen in the future', %q{
setivar!("chilled") # Emit warning
$warning
-}
+})
# arity=-2 cfuncs
assert_equal '["", "1/2", [0, [:ok, 1]]]', %q{
@@ -4767,6 +4813,23 @@ assert_equal 'foo', %q{
entry(true)
}
+assert_equal 'ok', %q{
+ def ok
+ :ok
+ end
+
+ def delegator(...)
+ ok(...)
+ end
+
+ def caller
+ send(:delegator)
+ end
+
+ caller
+}
+
+# test inlining of simple iseqs
assert_equal '[:ok, :ok, :ok]', %q{
def identity(x) = x
def foo(x, _) = x
@@ -4783,6 +4846,59 @@ assert_equal '[:ok, :ok, :ok]', %q{
tests
}
+# test inlining of simple iseqs with kwargs
+assert_equal '[:ok, :ok, :ok, :ok, :ok]', %q{
+ def optional_unused(x, opt: :not_ok) = x
+ def optional_used(x, opt: :ok) = opt
+ def required_unused(x, req:) = x
+ def required_used(x, req:) = req
+ def unknown(x) = x
+
+ def tests
+ [
+ optional_unused(:ok),
+ optional_used(:not_ok),
+ required_unused(:ok, req: :not_ok),
+ required_used(:not_ok, req: :ok),
+ begin unknown(:not_ok, unknown_kwarg: :not_ok) rescue ArgumentError; :ok end,
+ ]
+ end
+
+ tests
+}
+
+# test simple iseqs not eligible for inlining
+assert_equal '[:ok, :ok, :ok, :ok, :ok]', %q{
+ def identity(x) = x
+ def arg_splat(x, *args) = x
+ def kwarg_splat(x, **kwargs) = x
+ def block_arg(x, &blk) = x
+ def block_iseq(x) = x
+ def call_forwarding(...) = identity(...)
+
+ def tests
+ [
+ arg_splat(:ok),
+ kwarg_splat(:ok),
+ block_arg(:ok, &proc { :not_ok }),
+ block_iseq(:ok) { :not_ok },
+ call_forwarding(:ok),
+ ]
+ end
+
+ tests
+}
+
+# regression test for splat with &proc{} when the target has rest (Bug #21266)
+assert_equal '[]', %q{
+ def foo(args) = bar(*args, &proc { _1 })
+ def bar(_, _, _, _, *rest) = yield rest
+
+ GC.stress = true
+ foo([1,2,3,4])
+ foo([1,2,3,4])
+}
+
# regression test for invalidating an empty block
assert_equal '0', %q{
def foo = (* = 1).pred
@@ -4794,7 +4910,7 @@ assert_equal '0', %q{
end
foo # try again
-} unless rjit_enabled? # doesn't work on RJIT
+}
# test integer left shift with constant rhs
assert_equal [0x80000000000, 'a+', :ok].inspect, %q{
@@ -4813,6 +4929,15 @@ assert_equal [0x80000000000, 'a+', :ok].inspect, %q{
tests
}
+# test integer left shift fusion followed by opt_getconstant_path
+assert_equal '33', %q{
+ def test(a)
+ (a << 5) | (Object; a)
+ end
+
+ test(1)
+}
+
# test String#stebyte with arguments that need conversion
assert_equal "abc", %q{
str = +"a00"
@@ -4893,7 +5018,7 @@ assert_equal '[[true, false, false], [true, true, false], [true, :error, :error]
end
results << test
-} unless rjit_enabled? # Not yet working on RJIT
+}
# test FalseClass#=== before and after redefining FalseClass#==
assert_equal '[[true, false, false], [true, false, true], [true, :error, :error]]', %q{
@@ -4928,7 +5053,7 @@ assert_equal '[[true, false, false], [true, false, true], [true, :error, :error]
end
results << test
-} unless rjit_enabled? # Not yet working on RJIT
+}
# test NilClass#=== before and after redefining NilClass#==
assert_equal '[[true, false, false], [true, false, true], [true, :error, :error]]', %q{
@@ -4963,7 +5088,7 @@ assert_equal '[[true, false, false], [true, false, true], [true, :error, :error]
end
results << test
-} unless rjit_enabled? # Not yet working on RJIT
+}
# test struct accessors fire c_call events
assert_equal '[[:c_call, :x=], [:c_call, :x]]', %q{
@@ -4992,3 +5117,346 @@ assert_equal '1', %q{
array.clear
test_body(array)
}
+
+# regression test for splatting empty array to cfunc
+assert_normal_exit %q{
+ def test_body(args) = Array(1, *args)
+
+ test_body([])
+ 0x100.times do
+ array = Array.new(100)
+ array.clear
+ test_body(array)
+ end
+}
+
+# compiling code shouldn't emit warnings as it may call into more Ruby code
+assert_equal 'ok', <<~'RUBY'
+ # [Bug #20522]
+ $VERBOSE = true
+ Warning[:performance] = true
+
+ module StrictWarnings
+ def warn(msg, **)
+ raise msg
+ end
+ end
+ Warning.singleton_class.prepend(StrictWarnings)
+
+ class A
+ def compiled_method(is_private)
+ @some_ivar = is_private
+ end
+ end
+
+ shape_max_variations = 8
+ if defined?(RubyVM::Shape::SHAPE_MAX_VARIATIONS) && RubyVM::Shape::SHAPE_MAX_VARIATIONS != shape_max_variations
+ raise "Expected SHAPE_MAX_VARIATIONS to be #{shape_max_variations}, got: #{RubyVM::Shape::SHAPE_MAX_VARIATIONS}"
+ end
+
+ 100.times do |i|
+ klass = Class.new(A)
+ (shape_max_variations - 1).times do |j|
+ obj = klass.new
+ obj.instance_variable_set("@base_#{i}", 42)
+ obj.instance_variable_set("@ivar_#{j}", 42)
+ end
+ obj = klass.new
+ obj.instance_variable_set("@base_#{i}", 42)
+ begin
+ obj.compiled_method(true)
+ rescue
+ # expected
+ end
+ end
+
+ :ok
+RUBY
+
+assert_equal 'ok', <<~'RUBY'
+ class MyRelation
+ def callee(...)
+ :ok
+ end
+
+ def uncached(...)
+ callee(...)
+ end
+
+ def takes_block(&block)
+ # push blockhandler
+ uncached(&block) # CI1
+ end
+ end
+
+ relation = MyRelation.new
+ relation.takes_block { }
+RUBY
+
+assert_equal 'ok', <<~'RUBY'
+ def _exec_scope(...)
+ instance_exec(...)
+ end
+
+ def ok args, body
+ _exec_scope(*args, &body)
+ end
+
+ ok([], -> { "ok" })
+RUBY
+
+assert_equal 'ok', <<~'RUBY'
+ def _exec_scope(...)
+ instance_exec(...)
+ end
+
+ def ok args, body
+ _exec_scope(*args, &body)
+ end
+
+ ok(["ok"], ->(x) { x })
+RUBY
+
+assert_equal 'ok', <<~'RUBY'
+def baz(a, b)
+ a + b
+end
+
+def bar(...)
+ baz(...)
+end
+
+def foo(a, ...)
+ bar(a, ...)
+end
+
+def test
+ foo("o", "k")
+end
+
+test
+RUBY
+
+# opt_newarray_send pack/buffer
+assert_equal '[true, true]', <<~'RUBY'
+ def pack
+ v = 1.23
+ [v, v*2, v*3].pack("E*").unpack("E*") == [v, v*2, v*3]
+ end
+
+ def with_buffer
+ v = 4.56
+ b = +"x"
+ [v, v*2, v*3].pack("E*", buffer: b)
+ b[1..].unpack("E*") == [v, v*2, v*3]
+ end
+
+ [pack, with_buffer]
+RUBY
+
+# String#[] / String#slice
+assert_equal 'ok', <<~'RUBY'
+ def error(klass)
+ yield
+ rescue klass
+ true
+ end
+
+ def test
+ str = "こんにちは"
+ substr = "にち"
+ failures = []
+
+ # Use many small statements to keep context for each slice call smaller than MAX_CTX_TEMPS
+
+ str[1] == "ん" && str.slice(4) == "は" || failures << :index
+ str[5].nil? && str.slice(5).nil? || failures << :index_end
+
+ str[1, 2] == "んに" && str.slice(2, 1) == "に" || failures << :beg_len
+ str[5, 1] == "" && str.slice(5, 1) == "" || failures << :beg_len_end
+
+ str[1..2] == "んに" && str.slice(2..2) == "に" || failures << :range
+
+ str[/に./] == "にち" && str.slice(/に./) == "にち" || failures << :regexp
+
+ str[/に./, 0] == "にち" && str.slice(/に./, 0) == "にち" || failures << :regexp_cap0
+
+ str[/に(.)/, 1] == "ち" && str.slice(/に(.)/, 1) == "ち" || failures << :regexp_cap1
+
+ str[substr] == substr && str.slice(substr) == substr || failures << :substr
+
+ error(TypeError) { str[Object.new] } && error(TypeError) { str.slice(Object.new, 1) } || failures << :type_error
+ error(RangeError) { str[Float::INFINITY] } && error(RangeError) { str.slice(Float::INFINITY) } || failures << :range_error
+
+ return "ok" if failures.empty?
+ {failures: failures}
+ end
+
+ test
+RUBY
+
+# opt_duparray_send :include?
+assert_equal '[true, false]', <<~'RUBY'
+ def test(x)
+ [:a, :b].include?(x)
+ end
+
+ [
+ test(:b),
+ test(:c),
+ ]
+RUBY
+
+# opt_newarray_send :include?
+assert_equal '[true, false]', <<~'RUBY'
+ def test(x)
+ [Object.new, :a, :b].include?(x.to_sym)
+ end
+
+ [
+ test("b"),
+ test("c"),
+ ]
+RUBY
+
+# YARV: swap and opt_reverse
+assert_equal '["x", "Y", "c", "A", "t", "A", "b", "C", "d"]', <<~'RUBY'
+ class Swap
+ def initialize(s)
+ @a, @b, @c, @d = s.split("")
+ end
+
+ def swap
+ a, b = @a, @b
+ b = b.upcase
+ @a, @b = a, b
+ end
+
+ def reverse_odd
+ a, b, c = @a, @b, @c
+ b = b.upcase
+ @a, @b, @c = a, b, c
+ end
+
+ def reverse_even
+ a, b, c, d = @a, @b, @c, @d
+ a = a.upcase
+ c = c.upcase
+ @a, @b, @c, @d = a, b, c, d
+ end
+ end
+
+ Swap.new("xy").swap + Swap.new("cat").reverse_odd + Swap.new("abcd").reverse_even
+RUBY
+
+assert_normal_exit %{
+ class Bug20997
+ def foo(&) = self.class.name(&)
+
+ new.foo
+ end
+}
+
+# This used to trigger a "try to mark T_NONE"
+# due to an uninitialized local in foo.
+assert_normal_exit %{
+ def foo(...)
+ _local_that_should_nil_on_call = GC.start
+ end
+
+ def test_bug21021
+ puts [], [], [], [], [], []
+ foo []
+ end
+
+ GC.stress = true
+ test_bug21021
+}
+
+assert_equal 'nil', %{
+ def foo(...)
+ _a = _b = _c = binding.local_variable_get(:_c)
+
+ _c
+ end
+
+ # [Bug #21021]
+ def test_local_fill_in_forwardable
+ puts [], [], [], [], []
+ foo []
+ end
+
+ test_local_fill_in_forwardable.inspect
+}
+
+# Test defined?(yield) and block_given? in non-method context.
+# It's good that the body of this runs at true top level and isn't wrapped in a block.
+assert_equal 'false', %{
+ RESULT = []
+ RESULT << defined?(yield)
+ RESULT << block_given?
+
+ 1.times do
+ RESULT << defined?(yield)
+ RESULT << block_given?
+ end
+
+ module ModuleContext
+ 1.times do
+ RESULT << defined?(yield)
+ RESULT << block_given?
+ end
+ end
+
+ class << self
+ RESULT << defined?(yield)
+ RESULT << block_given?
+ end
+
+ RESULT.any?
+}
+
+# throw and String#dup with GC stress
+assert_equal 'foo', %{
+ GC.stress = true
+
+ def foo
+ 1.times { return "foo".dup }
+ end
+
+ 10.times.map { foo.dup }.last
+}
+
+# regression test for [Bug #21772]
+# local variable type tracking desync
+assert_normal_exit %q{
+ def some_method = 0
+
+ def test_body(key)
+ some_method
+ key = key.to_s # setting of local relevant
+
+ key == "symbol"
+ end
+
+ def jit_caller = test_body("session_id")
+
+ jit_caller # first iteration, non-escaped environment
+ alias some_method binding # induce environment escape
+ test_body(:symbol)
+}
+
+# regression test for missing check in identity method inlining
+assert_normal_exit %q{
+ # Use dead code (if false) to create a local
+ # without initialization instructions.
+ def foo(a)
+ if false
+ x = nil
+ end
+ x
+ end
+ def test = foo(1)
+ test
+ test
+}
diff --git a/bootstraptest/test_yjit_rust_port.rb b/bootstraptest/test_yjit_rust_port.rb
index e399e0e49e..2dbcebc03a 100644
--- a/bootstraptest/test_yjit_rust_port.rb
+++ b/bootstraptest/test_yjit_rust_port.rb
@@ -374,7 +374,7 @@ assert_equal 'ok', %q{
r = Ractor.new do
'ok'
end
- r.take
+ r.value
}
# Passed arguments to Ractor.new will be a block parameter
@@ -384,7 +384,7 @@ assert_equal 'ok', %q{
r = Ractor.new 'ok' do |msg|
msg
end
- r.take
+ r.value
}
# Pass multiple arguments to Ractor.new
@@ -393,7 +393,7 @@ assert_equal 'ok', %q{
r = Ractor.new 'ping', 'pong' do |msg, msg2|
[msg, msg2]
end
- 'ok' if r.take == ['ping', 'pong']
+ 'ok' if r.value == ['ping', 'pong']
}
# Ractor#send passes an object with copy to a Ractor
@@ -403,7 +403,7 @@ assert_equal 'ok', %q{
msg = Ractor.receive
end
r.send 'ok'
- r.take
+ r.value
}
assert_equal '[1, 2, 3]', %q{
diff --git a/box.c b/box.c
new file mode 100644
index 0000000000..830172cdd5
--- /dev/null
+++ b/box.c
@@ -0,0 +1,1220 @@
+/* indent-tabs-mode: nil */
+
+#include "eval_intern.h"
+#include "internal.h"
+#include "internal/box.h"
+#include "internal/class.h"
+#include "internal/eval.h"
+#include "internal/error.h"
+#include "internal/file.h"
+#include "internal/gc.h"
+#include "internal/hash.h"
+#include "internal/io.h"
+#include "internal/load.h"
+#include "internal/st.h"
+#include "internal/variable.h"
+#include "iseq.h"
+#include "ruby/internal/globals.h"
+#include "ruby/util.h"
+#include "vm_core.h"
+#include "darray.h"
+
+#include <stdio.h>
+
+#ifdef HAVE_SYS_SENDFILE_H
+# include <sys/sendfile.h>
+#endif
+#ifdef HAVE_COPYFILE_H
+#include <copyfile.h>
+#endif
+
+VALUE rb_cBox = 0;
+VALUE rb_cBoxEntry = 0;
+VALUE rb_mBoxLoader = 0;
+
+static rb_box_t root_box[1]; /* Initialize in initialize_root_box() */
+static rb_box_t *main_box;
+static char *tmp_dir;
+static bool tmp_dir_has_dirsep;
+
+#define BOX_TMP_PREFIX "_ruby_box_"
+
+#ifndef MAXPATHLEN
+# define MAXPATHLEN 1024
+#endif
+
+#if defined(_WIN32)
+# define DIRSEP "\\"
+#else
+# define DIRSEP "/"
+#endif
+
+bool ruby_box_enabled = false; // extern
+bool ruby_box_init_done = false; // extern
+bool ruby_box_crashed = false; // extern, changed only in vm.c
+
+VALUE rb_resolve_feature_path(VALUE klass, VALUE fname);
+static VALUE rb_box_inspect(VALUE obj);
+static void cleanup_all_local_extensions(VALUE libmap);
+
+void
+rb_box_init_done(void)
+{
+ ruby_box_init_done = true;
+}
+
+const rb_box_t *
+rb_root_box(void)
+{
+ return root_box;
+}
+
+const rb_box_t *
+rb_main_box(void)
+{
+ return main_box;
+}
+
+const rb_box_t *
+rb_current_box(void)
+{
+ /*
+ * If RUBY_BOX is not set, the root box is the only available one.
+ *
+ * Until the main_box is not initialized, the root box is
+ * the only valid box.
+ * This early return is to avoid accessing EC before its setup.
+ */
+ if (!main_box)
+ return root_box;
+
+ return rb_vm_current_box(GET_EC());
+}
+
+const rb_box_t *
+rb_loading_box(void)
+{
+ if (!main_box)
+ return root_box;
+
+ return rb_vm_loading_box(GET_EC());
+}
+
+const rb_box_t *
+rb_current_box_in_crash_report(void)
+{
+ if (ruby_box_crashed)
+ return NULL;
+ return rb_current_box();
+}
+
+static long box_id_counter = 0;
+
+static long
+box_generate_id(void)
+{
+ long id;
+ RB_VM_LOCKING() {
+ id = ++box_id_counter;
+ }
+ return id;
+}
+
+static VALUE
+box_main_to_s(VALUE obj)
+{
+ return rb_str_new2("main");
+}
+
+static void
+box_entry_initialize(rb_box_t *box)
+{
+ const rb_box_t *root = rb_root_box();
+
+ // These will be updated immediately
+ box->box_object = 0;
+ box->box_id = 0;
+
+ box->top_self = rb_obj_alloc(rb_cObject);
+ rb_define_singleton_method(box->top_self, "to_s", box_main_to_s, 0);
+ rb_define_alias(rb_singleton_class(box->top_self), "inspect", "to_s");
+ box->load_path = rb_ary_dup(root->load_path);
+ box->expanded_load_path = rb_ary_dup(root->expanded_load_path);
+ box->load_path_snapshot = rb_ary_new();
+ box->load_path_check_cache = 0;
+ box->loaded_features = rb_ary_dup(root->loaded_features);
+ box->loaded_features_snapshot = rb_ary_new();
+ box->loaded_features_index = st_init_numtable();
+ box->loaded_features_realpaths = rb_hash_dup(root->loaded_features_realpaths);
+ box->loaded_features_realpath_map = rb_hash_dup(root->loaded_features_realpath_map);
+ box->loading_table = st_init_strtable();
+ box->ruby_dln_libmap = rb_hash_new_with_size(0);
+ box->gvar_tbl = rb_hash_new_with_size(0);
+ box->classext_cow_classes = st_init_numtable();
+
+ box->is_user = true;
+ box->is_optional = true;
+}
+
+void
+rb_box_gc_update_references(void *ptr)
+{
+ rb_box_t *box = (rb_box_t *)ptr;
+ if (!box) return;
+
+ if (box->box_object)
+ box->box_object = rb_gc_location(box->box_object);
+ if (box->top_self)
+ box->top_self = rb_gc_location(box->top_self);
+ box->load_path = rb_gc_location(box->load_path);
+ box->expanded_load_path = rb_gc_location(box->expanded_load_path);
+ box->load_path_snapshot = rb_gc_location(box->load_path_snapshot);
+ if (box->load_path_check_cache) {
+ box->load_path_check_cache = rb_gc_location(box->load_path_check_cache);
+ }
+ box->loaded_features = rb_gc_location(box->loaded_features);
+ box->loaded_features_snapshot = rb_gc_location(box->loaded_features_snapshot);
+ box->loaded_features_realpaths = rb_gc_location(box->loaded_features_realpaths);
+ box->loaded_features_realpath_map = rb_gc_location(box->loaded_features_realpath_map);
+ box->ruby_dln_libmap = rb_gc_location(box->ruby_dln_libmap);
+ box->gvar_tbl = rb_gc_location(box->gvar_tbl);
+}
+
+void
+rb_box_entry_mark(void *ptr)
+{
+ const rb_box_t *box = (rb_box_t *)ptr;
+ if (!box) return;
+
+ rb_gc_mark(box->box_object);
+ rb_gc_mark(box->top_self);
+ rb_gc_mark(box->load_path);
+ rb_gc_mark(box->expanded_load_path);
+ rb_gc_mark(box->load_path_snapshot);
+ rb_gc_mark(box->load_path_check_cache);
+ rb_gc_mark(box->loaded_features);
+ rb_gc_mark(box->loaded_features_snapshot);
+ rb_gc_mark(box->loaded_features_realpaths);
+ rb_gc_mark(box->loaded_features_realpath_map);
+ if (box->loading_table) {
+ rb_mark_tbl(box->loading_table);
+ }
+ rb_gc_mark(box->ruby_dln_libmap);
+ rb_gc_mark(box->gvar_tbl);
+ if (box->classext_cow_classes) {
+ rb_mark_tbl(box->classext_cow_classes);
+ }
+}
+
+static int
+free_loading_table_entry(st_data_t key, st_data_t value, st_data_t arg)
+{
+ xfree((char *)key);
+ return ST_DELETE;
+}
+
+static int
+free_loaded_feature_index_i(st_data_t key, st_data_t value, st_data_t arg)
+{
+ if (!FIXNUM_P(value)) {
+ rb_darray_free((void *)value);
+ }
+ return ST_CONTINUE;
+}
+
+static void
+box_root_free(void *ptr)
+{
+ rb_box_t *box = (rb_box_t *)ptr;
+ if (box->loading_table) {
+ st_foreach(box->loading_table, free_loading_table_entry, 0);
+ st_free_table(box->loading_table);
+ box->loading_table = 0;
+ }
+
+ if (box->loaded_features_index) {
+ st_foreach(box->loaded_features_index, free_loaded_feature_index_i, 0);
+ st_free_table(box->loaded_features_index);
+ }
+}
+
+static int
+free_classext_for_box(st_data_t _key, st_data_t obj_value, st_data_t box_arg)
+{
+ rb_classext_t *ext;
+ VALUE obj = (VALUE)obj_value;
+ const rb_box_t *box = (const rb_box_t *)box_arg;
+
+ if (RB_TYPE_P(obj, T_CLASS) || RB_TYPE_P(obj, T_MODULE)) {
+ ext = rb_class_unlink_classext(obj, box);
+ rb_class_classext_free(obj, ext, false);
+ }
+ else if (RB_TYPE_P(obj, T_ICLASS)) {
+ ext = rb_class_unlink_classext(obj, box);
+ rb_iclass_classext_free(obj, ext, false);
+ }
+ else {
+ rb_bug("Invalid type of object in classext_cow_classes: %s", rb_type_str(BUILTIN_TYPE(obj)));
+ }
+ return ST_CONTINUE;
+}
+
+static void
+box_entry_free(void *ptr)
+{
+ const rb_box_t *box = (const rb_box_t *)ptr;
+
+ if (box->classext_cow_classes) {
+ st_foreach(box->classext_cow_classes, free_classext_for_box, (st_data_t)box);
+ }
+
+ cleanup_all_local_extensions(box->ruby_dln_libmap);
+
+ box_root_free(ptr);
+ xfree(ptr);
+}
+
+static size_t
+box_entry_memsize(const void *ptr)
+{
+ size_t size = sizeof(rb_box_t);
+ const rb_box_t *box = (const rb_box_t *)ptr;
+ if (box->loaded_features_index) {
+ size += rb_st_memsize(box->loaded_features_index);
+ }
+ if (box->loading_table) {
+ size += rb_st_memsize(box->loading_table);
+ }
+ return size;
+}
+
+static const rb_data_type_t rb_box_data_type = {
+ "Ruby::Box::Entry",
+ {
+ rb_box_entry_mark,
+ box_entry_free,
+ box_entry_memsize,
+ rb_box_gc_update_references,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY // TODO: enable RUBY_TYPED_WB_PROTECTED when inserting write barriers
+};
+
+static const rb_data_type_t rb_root_box_data_type = {
+ "Ruby::Box::Root",
+ {
+ rb_box_entry_mark,
+ box_root_free,
+ box_entry_memsize,
+ rb_box_gc_update_references,
+ },
+ &rb_box_data_type, 0, RUBY_TYPED_FREE_IMMEDIATELY // TODO: enable RUBY_TYPED_WB_PROTECTED when inserting write barriers
+};
+
+VALUE
+rb_box_entry_alloc(VALUE klass)
+{
+ rb_box_t *entry;
+ VALUE obj = TypedData_Make_Struct(klass, rb_box_t, &rb_box_data_type, entry);
+ box_entry_initialize(entry);
+ return obj;
+}
+
+static rb_box_t *
+get_box_struct_internal(VALUE entry)
+{
+ rb_box_t *sval;
+ TypedData_Get_Struct(entry, rb_box_t, &rb_box_data_type, sval);
+ return sval;
+}
+
+rb_box_t *
+rb_get_box_t(VALUE box)
+{
+ VALUE entry;
+ ID id_box_entry;
+
+ VM_ASSERT(box);
+
+ if (NIL_P(box))
+ return root_box;
+
+ VM_ASSERT(BOX_OBJ_P(box));
+
+ CONST_ID(id_box_entry, "__box_entry__");
+ entry = rb_attr_get(box, id_box_entry);
+ return get_box_struct_internal(entry);
+}
+
+VALUE
+rb_get_box_object(rb_box_t *box)
+{
+ VM_ASSERT(box && box->box_object);
+ return box->box_object;
+}
+
+/*
+ * call-seq:
+ * Ruby::Box.new -> new_box
+ *
+ * Returns a new Ruby::Box object.
+ */
+static VALUE
+box_initialize(VALUE box_value)
+{
+ rb_box_t *box;
+ rb_classext_t *object_classext;
+ VALUE entry;
+ ID id_box_entry;
+ CONST_ID(id_box_entry, "__box_entry__");
+
+ if (!rb_box_available()) {
+ rb_raise(rb_eRuntimeError, "Ruby Box is disabled. Set RUBY_BOX=1 environment variable to use Ruby::Box.");
+ }
+
+ entry = rb_class_new_instance_pass_kw(0, NULL, rb_cBoxEntry);
+ box = get_box_struct_internal(entry);
+
+ box->box_object = box_value;
+ box->box_id = box_generate_id();
+ rb_define_singleton_method(box->load_path, "resolve_feature_path", rb_resolve_feature_path, 1);
+
+ // Set the Ruby::Box object unique/consistent from any boxes to have just single
+ // constant table from any view of every (including main) box.
+ // If a code in the box adds a constant, the constant will be visible even from root/main.
+ RCLASS_SET_PRIME_CLASSEXT_WRITABLE(box_value, true);
+
+ // Get a clean constant table of Object even by writable one
+ // because ns was just created, so it has not touched any constants yet.
+ object_classext = RCLASS_EXT_WRITABLE_IN_BOX(rb_cObject, box);
+ RCLASS_SET_CONST_TBL(box_value, RCLASSEXT_CONST_TBL(object_classext), true);
+
+ rb_ivar_set(box_value, id_box_entry, entry);
+
+ return box_value;
+}
+
+/*
+ * call-seq:
+ * Ruby::Box.enabled? -> true or false
+ *
+ * Returns +true+ if Ruby::Box is enabled.
+ */
+static VALUE
+rb_box_s_getenabled(VALUE recv)
+{
+ return RBOOL(rb_box_available());
+}
+
+/*
+ * call-seq:
+ * Ruby::Box.current -> box, nil or false
+ *
+ * Returns the current box.
+ * Returns +nil+ if Ruby Box is not enabled.
+ */
+static VALUE
+rb_box_s_current(VALUE recv)
+{
+ const rb_box_t *box;
+
+ if (!rb_box_available())
+ return Qnil;
+
+ box = rb_vm_current_box(GET_EC());
+ VM_ASSERT(box && box->box_object);
+ return box->box_object;
+}
+
+/*
+ * call-seq:
+ * load_path -> array
+ *
+ * Returns box local load path.
+ */
+static VALUE
+rb_box_load_path(VALUE box)
+{
+ VM_ASSERT(BOX_OBJ_P(box));
+ return rb_get_box_t(box)->load_path;
+}
+
+#ifdef _WIN32
+UINT rb_w32_system_tmpdir(WCHAR *path, UINT len);
+#endif
+
+/* Copied from mjit.c Ruby 3.0.3 */
+static char *
+system_default_tmpdir(void)
+{
+ // c.f. ext/etc/etc.c:etc_systmpdir()
+#ifdef _WIN32
+ WCHAR tmppath[_MAX_PATH];
+ UINT len = rb_w32_system_tmpdir(tmppath, numberof(tmppath));
+ if (len) {
+ int blen = WideCharToMultiByte(CP_UTF8, 0, tmppath, len, NULL, 0, NULL, NULL);
+ char *tmpdir = xmalloc(blen + 1);
+ WideCharToMultiByte(CP_UTF8, 0, tmppath, len, tmpdir, blen, NULL, NULL);
+ tmpdir[blen] = '\0';
+ return tmpdir;
+ }
+#elif defined _CS_DARWIN_USER_TEMP_DIR
+ char path[MAXPATHLEN];
+ size_t len = confstr(_CS_DARWIN_USER_TEMP_DIR, path, sizeof(path));
+ if (len > 0) {
+ char *tmpdir = xmalloc(len);
+ if (len > sizeof(path)) {
+ confstr(_CS_DARWIN_USER_TEMP_DIR, tmpdir, len);
+ }
+ else {
+ memcpy(tmpdir, path, len);
+ }
+ return tmpdir;
+ }
+#endif
+ return 0;
+}
+
+static int
+check_tmpdir(const char *dir)
+{
+ struct stat st;
+
+ if (!dir) return FALSE;
+ if (stat(dir, &st)) return FALSE;
+#ifndef S_ISDIR
+# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
+#endif
+ if (!S_ISDIR(st.st_mode)) return FALSE;
+#ifndef _WIN32
+# ifndef S_IWOTH
+# define S_IWOTH 002
+# endif
+ if (st.st_mode & S_IWOTH) {
+# ifdef S_ISVTX
+ if (!(st.st_mode & S_ISVTX)) return FALSE;
+# else
+ return FALSE;
+# endif
+ }
+ if (access(dir, W_OK)) return FALSE;
+#endif
+ return TRUE;
+}
+
+static char *
+system_tmpdir(void)
+{
+ char *tmpdir;
+# define RETURN_ENV(name) \
+ if (check_tmpdir(tmpdir = getenv(name))) return ruby_strdup(tmpdir)
+ RETURN_ENV("TMPDIR");
+ RETURN_ENV("TMP");
+ tmpdir = system_default_tmpdir();
+ if (check_tmpdir(tmpdir)) return tmpdir;
+ return ruby_strdup("/tmp");
+# undef RETURN_ENV
+}
+
+/* end of copy */
+
+static int
+sprint_ext_filename(char *str, size_t size, long box_id, const char *prefix, const char *basename)
+{
+ if (tmp_dir_has_dirsep) {
+ return snprintf(str, size, "%s%sp%"PRI_PIDT_PREFIX"u_%ld_%s", tmp_dir, prefix, getpid(), box_id, basename);
+ }
+ return snprintf(str, size, "%s%s%sp%"PRI_PIDT_PREFIX"u_%ld_%s", tmp_dir, DIRSEP, prefix, getpid(), box_id, basename);
+}
+
+enum copy_error_type {
+ COPY_ERROR_NONE,
+ COPY_ERROR_SRC_OPEN,
+ COPY_ERROR_DST_OPEN,
+ COPY_ERROR_SRC_READ,
+ COPY_ERROR_DST_WRITE,
+ COPY_ERROR_SRC_STAT,
+ COPY_ERROR_DST_CHMOD,
+ COPY_ERROR_SYSERR
+};
+
+static const char *
+copy_ext_file_error(char *message, size_t size, int copy_retvalue)
+{
+#ifdef _WIN32
+ int error = GetLastError();
+ char *p = message;
+ size_t len = snprintf(message, size, "%d: ", error);
+
+#define format_message(sublang) FormatMessage(\
+ FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, \
+ NULL, error, MAKELANGID(LANG_NEUTRAL, (sublang)), \
+ message + len, size - len, NULL)
+ if (format_message(SUBLANG_ENGLISH_US) == 0)
+ format_message(SUBLANG_DEFAULT);
+ for (p = message + len; *p; p++) {
+ if (*p == '\n' || *p == '\r')
+ *p = ' ';
+ }
+#else
+ switch (copy_retvalue) {
+ case COPY_ERROR_SRC_OPEN:
+ strlcpy(message, "can't open the extension path", size);
+ break;
+ case COPY_ERROR_DST_OPEN:
+ strlcpy(message, "can't open the file to write", size);
+ break;
+ case COPY_ERROR_SRC_READ:
+ strlcpy(message, "failed to read the extension path", size);
+ break;
+ case COPY_ERROR_DST_WRITE:
+ strlcpy(message, "failed to write the extension path", size);
+ break;
+ case COPY_ERROR_SRC_STAT:
+ strlcpy(message, "failed to stat the extension path to copy permissions", size);
+ break;
+ case COPY_ERROR_DST_CHMOD:
+ strlcpy(message, "failed to set permissions to the copied extension path", size);
+ break;
+ case COPY_ERROR_SYSERR:
+ strlcpy(message, strerror(errno), size);
+ break;
+ case COPY_ERROR_NONE: /* shouldn't be called */
+ default:
+ rb_bug("unknown return value of copy_ext_file: %d", copy_retvalue);
+ }
+#endif
+ return message;
+}
+
+#ifndef _WIN32
+static enum copy_error_type
+copy_stream(int src_fd, int dst_fd)
+{
+ char buffer[1024];
+ ssize_t rsize;
+
+ while ((rsize = read(src_fd, buffer, sizeof(buffer))) != 0) {
+ if (rsize < 0) return COPY_ERROR_SRC_READ;
+ for (size_t written = 0; written < (size_t)rsize;) {
+ ssize_t wsize = write(dst_fd, buffer+written, rsize-written);
+ if (wsize < 0) return COPY_ERROR_DST_WRITE;
+ written += (size_t)wsize;
+ }
+ }
+ return COPY_ERROR_NONE;
+}
+#endif
+
+static enum copy_error_type
+copy_ext_file(const char *src_path, const char *dst_path)
+{
+#if defined(_WIN32)
+ WCHAR *w_src = rb_w32_mbstr_to_wstr(CP_UTF8, src_path, -1, NULL);
+ WCHAR *w_dst = rb_w32_mbstr_to_wstr(CP_UTF8, dst_path, -1, NULL);
+ if (!w_src || !w_dst) {
+ free(w_src);
+ free(w_dst);
+ rb_memerror();
+ }
+
+ enum copy_error_type rvalue = CopyFileW(w_src, w_dst, TRUE) ?
+ COPY_ERROR_NONE : COPY_ERROR_SYSERR;
+ free(w_src);
+ free(w_dst);
+ return rvalue;
+#else
+# ifdef O_BINARY
+ const int bin = O_BINARY;
+# else
+ const int bin = 0;
+# endif
+# ifdef O_CLOEXEC
+ const int cloexec = O_CLOEXEC;
+# else
+ const int cloexec = 0;
+# endif
+ const int src_fd = open(src_path, O_RDONLY|cloexec|bin);
+ if (src_fd < 0) return COPY_ERROR_SRC_OPEN;
+ if (!cloexec) rb_maygvl_fd_fix_cloexec(src_fd);
+
+ struct stat src_st;
+ if (fstat(src_fd, &src_st)) {
+ close(src_fd);
+ return COPY_ERROR_SRC_STAT;
+ }
+
+ const int dst_fd = open(dst_path, O_WRONLY|O_CREAT|O_EXCL|cloexec|bin, S_IRWXU);
+ if (dst_fd < 0) {
+ close(src_fd);
+ return COPY_ERROR_DST_OPEN;
+ }
+ if (!cloexec) rb_maygvl_fd_fix_cloexec(dst_fd);
+
+ enum copy_error_type ret = COPY_ERROR_NONE;
+
+ if (fchmod(dst_fd, src_st.st_mode & 0777)) {
+ ret = COPY_ERROR_DST_CHMOD;
+ goto done;
+ }
+
+ const size_t count_max = (SIZE_MAX >> 1) + 1;
+ (void)count_max;
+
+# ifdef HAVE_COPY_FILE_RANGE
+ for (;;) {
+ ssize_t written = copy_file_range(src_fd, NULL, dst_fd, NULL, count_max, 0);
+ if (written == 0) goto done;
+ if (written < 0) break;
+ }
+# endif
+# ifdef HAVE_FCOPYFILE
+ if (fcopyfile(src_fd, dst_fd, NULL, COPYFILE_DATA) == 0) {
+ goto done;
+ }
+# endif
+# ifdef USE_SENDFILE
+ for (;;) {
+ ssize_t written = sendfile(src_fd, dst_fd, NULL count_max);
+ if (written == 0) goto done;
+ if (written < 0) break;
+ }
+# endif
+ ret = copy_stream(src_fd, dst_fd);
+
+ done:
+ close(src_fd);
+ if (dst_fd >= 0) close(dst_fd);
+ if (ret != COPY_ERROR_NONE) unlink(dst_path);
+ return ret;
+#endif
+}
+
+#if defined __CYGWIN__ || defined DOSISH
+#define isdirsep(x) ((x) == '/' || (x) == '\\')
+#else
+#define isdirsep(x) ((x) == '/')
+#endif
+
+#define IS_SOEXT(e) (strcmp((e), ".so") == 0 || strcmp((e), ".o") == 0)
+#define IS_DLEXT(e) (strcmp((e), DLEXT) == 0)
+
+static void
+fname_without_suffix(const char *fname, char *rvalue, size_t rsize)
+{
+ size_t len = strlen(fname);
+ const char *pos;
+ for (pos = fname + len; pos > fname; pos--) {
+ if (IS_SOEXT(pos) || IS_DLEXT(pos)) {
+ len = pos - fname;
+ break;
+ }
+ if (fname + len - pos > DLEXT_MAXLEN) break;
+ }
+ if (len > rsize - 1) len = rsize - 1;
+ memcpy(rvalue, fname, len);
+ rvalue[len] = '\0';
+}
+
+static void
+escaped_basename(const char *path, const char *fname, char *rvalue, size_t rsize)
+{
+ char *pos;
+ const char *leaf = path, *found;
+ // `leaf + 1` looks uncomfortable (when leaf == path), but fname must not be the top-dir itself
+ while ((found = strstr(leaf + 1, fname)) != NULL) {
+ leaf = found; // find the last occurrence for the path like /etc/my-crazy-lib-dir/etc.so
+ }
+ strlcpy(rvalue, leaf, rsize);
+ for (pos = rvalue; *pos; pos++) {
+ if (isdirsep(*pos)) {
+ *pos = '+';
+ }
+ }
+}
+
+static void
+box_ext_cleanup_mark(void *p)
+{
+ rb_gc_mark((VALUE)p);
+}
+
+static void
+box_ext_cleanup_free(void *p)
+{
+ VALUE path = (VALUE)p;
+ unlink(RSTRING_PTR(path));
+}
+
+static const rb_data_type_t box_ext_cleanup_type = {
+ "box_ext_cleanup",
+ {box_ext_cleanup_mark, box_ext_cleanup_free},
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+void
+rb_box_cleanup_local_extension(VALUE cleanup)
+{
+ void *p = DATA_PTR(cleanup);
+ DATA_PTR(cleanup) = NULL;
+#ifndef _WIN32
+ if (p) box_ext_cleanup_free(p);
+#endif
+ (void)p;
+}
+
+static int
+cleanup_local_extension_i(VALUE key, VALUE value, VALUE arg)
+{
+#if defined(_WIN32)
+ HMODULE h = (HMODULE)NUM2PTR(value);
+ WCHAR module_path[MAXPATHLEN];
+ DWORD len = GetModuleFileNameW(h, module_path, numberof(module_path));
+
+ FreeLibrary(h);
+ if (len > 0 && len < numberof(module_path)) DeleteFileW(module_path);
+#endif
+ return ST_DELETE;
+}
+
+static void
+cleanup_all_local_extensions(VALUE libmap)
+{
+ rb_hash_foreach(libmap, cleanup_local_extension_i, 0);
+}
+
+VALUE
+rb_box_local_extension(VALUE box_value, VALUE fname, VALUE path, VALUE *cleanup)
+{
+ char ext_path[MAXPATHLEN], fname2[MAXPATHLEN], basename[MAXPATHLEN];
+ int wrote;
+ const char *src_path = RSTRING_PTR(path), *fname_ptr = RSTRING_PTR(fname);
+ rb_box_t *box = rb_get_box_t(box_value);
+
+ fname_without_suffix(fname_ptr, fname2, sizeof(fname2));
+ escaped_basename(src_path, fname2, basename, sizeof(basename));
+
+ wrote = sprint_ext_filename(ext_path, sizeof(ext_path), box->box_id, BOX_TMP_PREFIX, basename);
+ if (wrote >= (int)sizeof(ext_path)) {
+ rb_bug("Extension file path in the box was too long");
+ }
+ VALUE new_path = rb_str_new_cstr(ext_path);
+ *cleanup = TypedData_Wrap_Struct(0, &box_ext_cleanup_type, NULL);
+ enum copy_error_type copy_error = copy_ext_file(src_path, ext_path);
+ if (copy_error) {
+ char message[1024];
+ copy_ext_file_error(message, sizeof(message), copy_error);
+ rb_raise(rb_eLoadError, "can't prepare the extension file for Ruby Box (%s from %"PRIsVALUE"): %s", ext_path, path, message);
+ }
+ DATA_PTR(*cleanup) = (void *)new_path;
+ return new_path;
+}
+
+static VALUE
+rb_box_load(int argc, VALUE *argv, VALUE box)
+{
+ VALUE fname, wrap;
+ rb_scan_args(argc, argv, "11", &fname, &wrap);
+
+ rb_vm_frame_flag_set_box_require(GET_EC());
+
+ VALUE args = rb_ary_new_from_args(2, fname, wrap);
+ return rb_load_entrypoint(args);
+}
+
+static VALUE
+rb_box_require(VALUE box, VALUE fname)
+{
+ rb_vm_frame_flag_set_box_require(GET_EC());
+
+ return rb_require_string(fname);
+}
+
+static VALUE
+rb_box_require_relative(VALUE box, VALUE fname)
+{
+ rb_vm_frame_flag_set_box_require(GET_EC());
+
+ return rb_require_relative_entrypoint(fname);
+}
+
+static void
+initialize_root_box(void)
+{
+ rb_vm_t *vm = GET_VM();
+ rb_box_t *root = (rb_box_t *)rb_root_box();
+
+ root->load_path = rb_ary_new();
+ root->expanded_load_path = rb_ary_hidden_new(0);
+ root->load_path_snapshot = rb_ary_hidden_new(0);
+ root->load_path_check_cache = 0;
+ rb_define_singleton_method(root->load_path, "resolve_feature_path", rb_resolve_feature_path, 1);
+
+ root->loaded_features = rb_ary_new();
+ root->loaded_features_snapshot = rb_ary_hidden_new(0);
+ root->loaded_features_index = st_init_numtable();
+ root->loaded_features_realpaths = rb_hash_new();
+ rb_obj_hide(root->loaded_features_realpaths);
+ root->loaded_features_realpath_map = rb_hash_new();
+ rb_obj_hide(root->loaded_features_realpath_map);
+
+ root->ruby_dln_libmap = rb_hash_new_with_size(0);
+ root->gvar_tbl = rb_hash_new_with_size(0);
+ root->classext_cow_classes = NULL; // classext CoW never happen on the root box
+
+ vm->root_box = root;
+
+ if (rb_box_available()) {
+ VALUE root_box, entry;
+ ID id_box_entry;
+ CONST_ID(id_box_entry, "__box_entry__");
+
+ root_box = rb_obj_alloc(rb_cBox);
+ RCLASS_SET_PRIME_CLASSEXT_WRITABLE(root_box, true);
+ RCLASS_SET_CONST_TBL(root_box, RCLASSEXT_CONST_TBL(RCLASS_EXT_PRIME(rb_cObject)), true);
+
+ root->box_id = box_generate_id();
+ root->box_object = root_box;
+
+ entry = TypedData_Wrap_Struct(rb_cBoxEntry, &rb_root_box_data_type, root);
+ rb_ivar_set(root_box, id_box_entry, entry);
+ }
+ else {
+ root->box_id = 1;
+ root->box_object = Qnil;
+ }
+}
+
+static VALUE
+rb_box_eval(VALUE box_value, VALUE str)
+{
+ const rb_iseq_t *iseq;
+ const rb_box_t *box;
+
+ StringValue(str);
+
+ iseq = rb_iseq_compile_iseq(str, rb_str_new_cstr("eval"));
+ VM_ASSERT(iseq);
+
+ box = (const rb_box_t *)rb_get_box_t(box_value);
+
+ return rb_iseq_eval(iseq, box);
+}
+
+static int box_experimental_warned = 0;
+
+RUBY_EXTERN const char ruby_api_version_name[];
+
+void
+rb_initialize_main_box(void)
+{
+ rb_box_t *box;
+ VALUE main_box_value;
+ rb_vm_t *vm = GET_VM();
+
+ VM_ASSERT(rb_box_available());
+
+ if (!box_experimental_warned) {
+ rb_category_warn(RB_WARN_CATEGORY_EXPERIMENTAL,
+ "Ruby::Box is experimental, and the behavior may change in the future!\n"
+ "See https://docs.ruby-lang.org/en/%s/Ruby/Box.html for known issues, etc.",
+ ruby_api_version_name);
+ box_experimental_warned = 1;
+ }
+
+ main_box_value = rb_class_new_instance(0, NULL, rb_cBox);
+ VM_ASSERT(BOX_OBJ_P(main_box_value));
+ box = rb_get_box_t(main_box_value);
+ box->box_object = main_box_value;
+ box->is_user = true;
+ box->is_optional = false;
+
+ rb_const_set(rb_cBox, rb_intern("MAIN"), main_box_value);
+
+ vm->main_box = main_box = box;
+
+ // create the writable classext of ::Object explicitly to finalize the set of visible top-level constants
+ RCLASS_EXT_WRITABLE_IN_BOX(rb_cObject, box);
+}
+
+static VALUE
+rb_box_inspect(VALUE obj)
+{
+ rb_box_t *box;
+ VALUE r;
+ if (obj == Qfalse) {
+ r = rb_str_new_cstr("#<Ruby::Box:root>");
+ return r;
+ }
+ box = rb_get_box_t(obj);
+ r = rb_str_new_cstr("#<Ruby::Box:");
+ rb_str_concat(r, rb_funcall(LONG2NUM(box->box_id), rb_intern("to_s"), 0));
+ if (BOX_ROOT_P(box)) {
+ rb_str_cat_cstr(r, ",root");
+ }
+ if (BOX_USER_P(box)) {
+ rb_str_cat_cstr(r, ",user");
+ }
+ if (BOX_MAIN_P(box)) {
+ rb_str_cat_cstr(r, ",main");
+ }
+ else if (BOX_OPTIONAL_P(box)) {
+ rb_str_cat_cstr(r, ",optional");
+ }
+ rb_str_cat_cstr(r, ">");
+ return r;
+}
+
+static VALUE
+rb_box_loading_func(int argc, VALUE *argv, VALUE _self)
+{
+ rb_vm_frame_flag_set_box_require(GET_EC());
+ return rb_call_super(argc, argv);
+}
+
+static void
+box_define_loader_method(const char *name)
+{
+ rb_define_private_method(rb_mBoxLoader, name, rb_box_loading_func, -1);
+ rb_define_singleton_method(rb_mBoxLoader, name, rb_box_loading_func, -1);
+}
+
+void
+Init_root_box(void)
+{
+ root_box->loading_table = st_init_strtable();
+}
+
+void
+Init_enable_box(void)
+{
+ const char *env = getenv("RUBY_BOX");
+ if (env && strlen(env) == 1 && env[0] == '1') {
+ ruby_box_enabled = true;
+ }
+ else {
+ ruby_box_init_done = true;
+ }
+}
+
+/* :nodoc: */
+static VALUE
+rb_box_s_root(VALUE recv)
+{
+ return root_box->box_object;
+}
+
+/* :nodoc: */
+static VALUE
+rb_box_s_main(VALUE recv)
+{
+ return main_box->box_object;
+}
+
+/* :nodoc: */
+static VALUE
+rb_box_root_p(VALUE box_value)
+{
+ const rb_box_t *box = (const rb_box_t *)rb_get_box_t(box_value);
+ return RBOOL(BOX_ROOT_P(box));
+}
+
+/* :nodoc: */
+static VALUE
+rb_box_main_p(VALUE box_value)
+{
+ const rb_box_t *box = (const rb_box_t *)rb_get_box_t(box_value);
+ return RBOOL(BOX_MAIN_P(box));
+}
+
+#if RUBY_DEBUG
+
+static const char *
+classname(VALUE klass)
+{
+ VALUE p;
+ if (!klass) {
+ return "Qfalse";
+ }
+ p = RCLASSEXT_CLASSPATH(RCLASS_EXT_PRIME(klass));
+ if (RTEST(p))
+ return RSTRING_PTR(p);
+ if (RB_TYPE_P(klass, T_CLASS) || RB_TYPE_P(klass, T_MODULE) || RB_TYPE_P(klass, T_ICLASS))
+ return "AnyClassValue";
+ return "NonClassValue";
+}
+
+static enum rb_id_table_iterator_result
+dump_classext_methods_i(ID mid, VALUE _val, void *data)
+{
+ VALUE ary = (VALUE)data;
+ rb_ary_push(ary, rb_id2str(mid));
+ return ID_TABLE_CONTINUE;
+}
+
+static enum rb_id_table_iterator_result
+dump_classext_constants_i(ID mid, VALUE _val, void *data)
+{
+ VALUE ary = (VALUE)data;
+ rb_ary_push(ary, rb_id2str(mid));
+ return ID_TABLE_CONTINUE;
+}
+
+static void
+dump_classext_i(rb_classext_t *ext, bool is_prime, VALUE _recv, void *data)
+{
+ char buf[4096];
+ struct rb_id_table *tbl;
+ VALUE ary, res = (VALUE)data;
+
+ snprintf(buf, 4096, "Ruby::Box %ld:%s classext %p\n",
+ RCLASSEXT_BOX(ext)->box_id, is_prime ? " prime" : "", (void *)ext);
+ rb_str_cat_cstr(res, buf);
+
+ snprintf(buf, 2048, " Super: %s\n", classname(RCLASSEXT_SUPER(ext)));
+ rb_str_cat_cstr(res, buf);
+
+ tbl = RCLASSEXT_M_TBL(ext);
+ if (tbl) {
+ ary = rb_ary_new_capa((long)rb_id_table_size(tbl));
+ rb_id_table_foreach(RCLASSEXT_M_TBL(ext), dump_classext_methods_i, (void *)ary);
+ rb_ary_sort_bang(ary);
+ snprintf(buf, 4096, " Methods(%ld): ", RARRAY_LEN(ary));
+ rb_str_cat_cstr(res, buf);
+ rb_str_concat(res, rb_ary_join(ary, rb_str_new_cstr(",")));
+ rb_str_cat_cstr(res, "\n");
+ }
+ else {
+ rb_str_cat_cstr(res, " Methods(0): .\n");
+ }
+
+ tbl = RCLASSEXT_CONST_TBL(ext);
+ if (tbl) {
+ ary = rb_ary_new_capa((long)rb_id_table_size(tbl));
+ rb_id_table_foreach(tbl, dump_classext_constants_i, (void *)ary);
+ rb_ary_sort_bang(ary);
+ snprintf(buf, 4096, " Constants(%ld): ", RARRAY_LEN(ary));
+ rb_str_cat_cstr(res, buf);
+ rb_str_concat(res, rb_ary_join(ary, rb_str_new_cstr(",")));
+ rb_str_cat_cstr(res, "\n");
+ }
+ else {
+ rb_str_cat_cstr(res, " Constants(0): .\n");
+ }
+}
+
+/* :nodoc: */
+static VALUE
+rb_f_dump_classext(VALUE recv, VALUE klass)
+{
+ /*
+ * The desired output String value is:
+ * Class: 0x88800932 (String) [singleton]
+ * Prime classext box(2,main), readable(t), writable(f)
+ * Non-prime classexts: 3
+ * Box 2: prime classext 0x88800933
+ * Super: Object
+ * Methods(43): aaaaa, bbbb, cccc, dddd, eeeee, ffff, gggg, hhhhh, ...
+ * Constants(12): FOO, Bar, ...
+ * Box 5: classext 0x88800934
+ * Super: Object
+ * Methods(43): aaaaa, bbbb, cccc, dddd, eeeee, ffff, gggg, hhhhh, ...
+ * Constants(12): FOO, Bar, ...
+ */
+ char buf[2048];
+ VALUE res;
+ const rb_classext_t *ext;
+ const rb_box_t *box;
+ st_table *classext_tbl;
+
+ if (!(RB_TYPE_P(klass, T_CLASS) || RB_TYPE_P(klass, T_MODULE))) {
+ snprintf(buf, 2048, "Non-class/module value: %p (%s)\n", (void *)klass, rb_type_str(BUILTIN_TYPE(klass)));
+ return rb_str_new_cstr(buf);
+ }
+
+ if (RB_TYPE_P(klass, T_CLASS)) {
+ snprintf(buf, 2048, "Class: %p (%s)%s\n",
+ (void *)klass, classname(klass), RCLASS_SINGLETON_P(klass) ? " [singleton]" : "");
+ }
+ else {
+ snprintf(buf, 2048, "Module: %p (%s)\n", (void *)klass, classname(klass));
+ }
+ res = rb_str_new_cstr(buf);
+
+ ext = RCLASS_EXT_PRIME(klass);
+ box = RCLASSEXT_BOX(ext);
+ snprintf(buf, 2048, "Prime classext box(%ld,%s), readable(%s), writable(%s)\n",
+ box->box_id,
+ BOX_ROOT_P(box) ? "root" : (BOX_MAIN_P(box) ? "main" : "optional"),
+ RCLASS_PRIME_CLASSEXT_READABLE_P(klass) ? "t" : "f",
+ RCLASS_PRIME_CLASSEXT_WRITABLE_P(klass) ? "t" : "f");
+ rb_str_cat_cstr(res, buf);
+
+ classext_tbl = RCLASS_CLASSEXT_TBL(klass);
+ if (!classext_tbl) {
+ rb_str_cat_cstr(res, "Non-prime classexts: 0\n");
+ }
+ else {
+ snprintf(buf, 2048, "Non-prime classexts: %zu\n", st_table_size(classext_tbl));
+ rb_str_cat_cstr(res, buf);
+ }
+
+ rb_class_classext_foreach(klass, dump_classext_i, (void *)res);
+
+ return res;
+}
+
+#endif /* RUBY_DEBUG */
+
+/*
+ * Document-class: Ruby::Box
+ *
+ * :markup: markdown
+ * :include: doc/language/box.md
+ */
+void
+Init_Box(void)
+{
+ tmp_dir = system_tmpdir();
+ tmp_dir_has_dirsep = (strcmp(tmp_dir + (strlen(tmp_dir) - strlen(DIRSEP)), DIRSEP) == 0);
+
+ VALUE mRuby = rb_define_module("Ruby");
+
+ rb_cBox = rb_define_class_under(mRuby, "Box", rb_cModule);
+ rb_define_method(rb_cBox, "initialize", box_initialize, 0);
+
+ /* :nodoc: */
+ rb_cBoxEntry = rb_define_class_under(rb_cBox, "Entry", rb_cObject);
+ rb_define_alloc_func(rb_cBoxEntry, rb_box_entry_alloc);
+
+ initialize_root_box();
+
+ /* :nodoc: */
+ rb_mBoxLoader = rb_define_module_under(rb_cBox, "Loader");
+ box_define_loader_method("require");
+ box_define_loader_method("require_relative");
+ box_define_loader_method("load");
+
+ if (rb_box_available()) {
+ rb_include_module(rb_cObject, rb_mBoxLoader);
+
+ rb_define_singleton_method(rb_cBox, "root", rb_box_s_root, 0);
+ rb_define_singleton_method(rb_cBox, "main", rb_box_s_main, 0);
+ rb_define_method(rb_cBox, "root?", rb_box_root_p, 0);
+ rb_define_method(rb_cBox, "main?", rb_box_main_p, 0);
+
+#if RUBY_DEBUG
+ rb_define_global_function("dump_classext", rb_f_dump_classext, 1);
+#endif
+ }
+
+ rb_define_singleton_method(rb_cBox, "enabled?", rb_box_s_getenabled, 0);
+ rb_define_singleton_method(rb_cBox, "current", rb_box_s_current, 0);
+
+ rb_define_method(rb_cBox, "load_path", rb_box_load_path, 0);
+ rb_define_method(rb_cBox, "load", rb_box_load, -1);
+ rb_define_method(rb_cBox, "require", rb_box_require, 1);
+ rb_define_method(rb_cBox, "require_relative", rb_box_require_relative, 1);
+ rb_define_method(rb_cBox, "eval", rb_box_eval, 1);
+
+ rb_define_method(rb_cBox, "inspect", rb_box_inspect, 0);
+}
diff --git a/builtin.c b/builtin.c
index fbc11bf1b4..6cc9790466 100644
--- a/builtin.c
+++ b/builtin.c
@@ -3,11 +3,11 @@
#include "iseq.h"
#include "builtin.h"
-#include "builtin_binary.inc"
+#include "builtin_binary.rbbin"
#ifndef BUILTIN_BINARY_SIZE
-#define INCLUDED_BY_BUILTIN_C 1
+#define BUILTIN_LOADED(feature_name, iseq) ((void)0)
#include "mini_builtin.c"
#else
@@ -32,8 +32,8 @@ builtin_lookup(const char *feature, size_t *psize)
return bin;
}
-void
-rb_load_with_builtin_functions(const char *feature_name, const struct rb_builtin_function *table)
+static void
+load_with_builtin_functions(const char *feature_name, const struct rb_builtin_function *table)
{
// search binary
size_t size;
@@ -51,7 +51,13 @@ rb_load_with_builtin_functions(const char *feature_name, const struct rb_builtin
vm->builtin_function_table = NULL;
// exec
- rb_iseq_eval(rb_iseq_check(iseq));
+ rb_iseq_eval(rb_iseq_check(iseq), rb_root_box()); // builtin functions are loaded in the root box
+}
+
+void
+rb_load_with_builtin_functions(const char *feature_name, const struct rb_builtin_function *table)
+{
+ load_with_builtin_functions(feature_name, table);
}
#endif
@@ -71,5 +77,11 @@ Init_builtin(void)
void
Init_builtin_features(void)
{
- rb_load_with_builtin_functions("gem_prelude", NULL);
+
+#ifdef BUILTIN_BINARY_SIZE
+
+ load_with_builtin_functions("gem_prelude", NULL);
+
+#endif
+
}
diff --git a/builtin.h b/builtin.h
index 24aa7c2fdb..fd1c4c307f 100644
--- a/builtin.h
+++ b/builtin.h
@@ -15,7 +15,7 @@ struct rb_builtin_function {
#define RB_BUILTIN_FUNCTION(_i, _name, _fname, _arity) {\
.name = _i < 0 ? NULL : #_name, \
- .func_ptr = (void *)_fname, \
+ .func_ptr = (void *)(uintptr_t)_fname, \
.argc = _arity, \
.index = _i, \
}
@@ -106,6 +106,12 @@ rb_vm_lvar(rb_execution_context_t *ec, int index)
#endif
}
+static inline VALUE
+rb_builtin_basic_definition_p(rb_execution_context_t *ec, VALUE klass, VALUE id_sym)
+{
+ return rb_method_basic_definition_p(klass, rb_sym2id(id_sym)) ? Qtrue : Qfalse;
+}
+
#define LOCAL_PTR(local) local ## __ptr
// dump/load
diff --git a/class.c b/class.c
index 5cce99e334..9c1bd86dc3 100644
--- a/class.c
+++ b/class.c
@@ -21,6 +21,7 @@
#include "debug_counter.h"
#include "id_table.h"
#include "internal.h"
+#include "internal/box.h"
#include "internal/class.h"
#include "internal/eval.h"
#include "internal/hash.h"
@@ -29,7 +30,9 @@
#include "internal/variable.h"
#include "ruby/st.h"
#include "vm_core.h"
+#include "ruby/ractor.h"
#include "yjit.h"
+#include "zjit.h"
/* Flags of T_CLASS
*
@@ -38,24 +41,22 @@
* This is done for classes defined from C to allow storing them in global variables.
* 1: RUBY_FL_SINGLETON
* This class is a singleton class.
- * 2: RCLASS_SUPERCLASSES_INCLUDE_SELF
- * The RCLASS_SUPERCLASSES contains the class as the last element.
- * This means that this class owns the RCLASS_SUPERCLASSES list.
- * if !SHAPE_IN_BASIC_FLAGS
- * 4-19: SHAPE_FLAG_MASK
- * Shape ID for the class.
- * endif
+ * 2: RCLASS_PRIME_CLASSEXT_PRIME_WRITABLE
+ * This class's prime classext is the only classext and writable from any boxes.
+ * If unset, the prime classext is writable only from the root box.
+ * 3: RCLASS_IS_INITIALIZED
+ * Class has been initialized.
+ * 4: RCLASS_BOXABLE
+ * Is a builtin class that may be boxed. It larger than a normal class.
*/
/* Flags of T_ICLASS
*
- * 0: RICLASS_IS_ORIGIN
- * 3: RICLASS_ORIGIN_SHARED_MTBL
- * The T_ICLASS does not own the method table.
- * if !SHAPE_IN_BASIC_FLAGS
- * 4-19: SHAPE_FLAG_MASK
- * Shape ID. This is set but not used.
- * endif
+ * 2: RCLASS_PRIME_CLASSEXT_PRIME_WRITABLE
+ * This module's prime classext is the only classext and writable from any boxes.
+ * If unset, the prime classext is writable only from the root box.
+ * 4: RCLASS_BOXABLE
+ * Is a builtin class that may be boxed. It larger than a normal class.
*/
/* Flags of T_MODULE
@@ -63,139 +64,666 @@
* 0: RCLASS_IS_ROOT
* The class has been added to the VM roots. Will always be marked and pinned.
* This is done for classes defined from C to allow storing them in global variables.
- * 1: RMODULE_ALLOCATED_BUT_NOT_INITIALIZED
- * Module has not been initialized.
- * 2: RCLASS_SUPERCLASSES_INCLUDE_SELF
- * See RCLASS_SUPERCLASSES_INCLUDE_SELF in T_CLASS.
- * 3: RMODULE_IS_REFINEMENT
+ * 1: <reserved>
+ * Ensures that RUBY_FL_SINGLETON is never set on a T_MODULE. See `rb_class_real`.
+ * 2: RCLASS_PRIME_CLASSEXT_PRIME_WRITABLE
+ * This module's prime classext is the only classext and writable from any boxes.
+ * If unset, the prime classext is writable only from the root box.
+ * 3: RCLASS_IS_INITIALIZED
+ * Module has been initialized.
+ * 4: RCLASS_BOXABLE
+ * Is a builtin class that may be boxed. It larger than a normal class.
+ * 5: RMODULE_IS_REFINEMENT
* Module is used for refinements.
- * if !SHAPE_IN_BASIC_FLAGS
- * 4-19: SHAPE_FLAG_MASK
- * Shape ID for the module.
- * endif
*/
#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 enum rb_id_table_iterator_result
+cvar_table_free_i(VALUE value, void *ctx)
+{
+ xfree((void *)value);
+ return ID_TABLE_CONTINUE;
+}
-static rb_subclass_entry_t *
-push_subclass_entry_to_list(VALUE super, VALUE klass)
+rb_classext_t *
+rb_class_unlink_classext(VALUE klass, const rb_box_t *box)
{
- rb_subclass_entry_t *entry, *head;
+ st_data_t ext;
+ st_data_t key = (st_data_t)box->box_object;
+ VALUE obj_id = rb_obj_id(klass);
+ st_delete(box->classext_cow_classes, &obj_id, 0);
+ st_delete(RCLASS_CLASSEXT_TBL(klass), &key, &ext);
+ return (rb_classext_t *)ext;
+}
- entry = ZALLOC(rb_subclass_entry_t);
- entry->klass = klass;
+void
+rb_class_classext_free(VALUE klass, rb_classext_t *ext, bool is_prime)
+{
+ struct rb_id_table *tbl;
- head = RCLASS_SUBCLASSES(super);
- if (!head) {
- head = ZALLOC(rb_subclass_entry_t);
- RCLASS_SUBCLASSES(super) = head;
+ rb_id_table_free(RCLASSEXT_M_TBL(ext));
+
+ if (!RCLASSEXT_SHARED_CONST_TBL(ext) && (tbl = RCLASSEXT_CONST_TBL(ext)) != NULL) {
+ rb_free_const_table(tbl);
+ }
+
+ if ((tbl = RCLASSEXT_CVC_TBL(ext)) != NULL) {
+ rb_id_table_foreach_values(tbl, cvar_table_free_i, NULL);
+ rb_id_table_free(tbl);
}
- entry->next = head->next;
- entry->prev = head;
- if (head->next) {
- head->next->prev = entry;
+ rb_class_classext_free_subclasses(ext, klass, false);
+
+ if (RCLASSEXT_SUPERCLASSES_WITH_SELF(ext)) {
+ RUBY_ASSERT(is_prime); // superclasses should only be used on prime
+ xfree(RCLASSEXT_SUPERCLASSES(ext));
}
- head->next = entry;
- return entry;
+ if (!is_prime) { // the prime classext will be freed with RClass
+ xfree(ext);
+ }
}
void
-rb_class_subclass_add(VALUE super, VALUE klass)
+rb_iclass_classext_free(VALUE klass, rb_classext_t *ext, bool is_prime)
{
- if (super && !UNDEF_P(super)) {
- rb_subclass_entry_t *entry = push_subclass_entry_to_list(super, klass);
- RCLASS_SUBCLASS_ENTRY(klass) = entry;
+ if (RCLASSEXT_ICLASS_IS_ORIGIN(ext) && !RCLASSEXT_ICLASS_ORIGIN_SHARED_MTBL(ext)) {
+ /* Method table is not shared for origin iclasses of classes */
+ rb_id_table_free(RCLASSEXT_M_TBL(ext));
+ }
+
+ if (RCLASSEXT_CALLABLE_M_TBL(ext) != NULL) {
+ rb_id_table_free(RCLASSEXT_CALLABLE_M_TBL(ext));
+ }
+
+ rb_class_classext_free_subclasses(ext, klass, false);
+
+ if (!is_prime) { // the prime classext will be freed with RClass
+ xfree(ext);
}
}
static void
-rb_module_add_to_subclasses_list(VALUE module, VALUE iclass)
+iclass_free_orphan_classext(VALUE klass, rb_classext_t *ext)
{
- rb_subclass_entry_t *entry = push_subclass_entry_to_list(module, iclass);
- RCLASS_MODULE_SUBCLASS_ENTRY(iclass) = entry;
+ if (RCLASSEXT_ICLASS_IS_ORIGIN(ext) && !RCLASSEXT_ICLASS_ORIGIN_SHARED_MTBL(ext)) {
+ /* Method table is not shared for origin iclasses of classes */
+ rb_id_table_free(RCLASSEXT_M_TBL(ext));
+ }
+
+ if (RCLASSEXT_CALLABLE_M_TBL(ext) != NULL) {
+ rb_id_table_free(RCLASSEXT_CALLABLE_M_TBL(ext));
+ }
+
+ rb_class_classext_free_subclasses(ext, klass, true); // replacing this classext with a newer one
+
+ xfree(ext);
}
-void
-rb_class_remove_subclass_head(VALUE klass)
+struct rb_class_set_box_classext_args {
+ VALUE obj;
+ rb_classext_t *ext;
+};
+
+static int
+set_box_classext_update(st_data_t *key_ptr, st_data_t *val_ptr, st_data_t a, int existing)
{
- rb_subclass_entry_t *head = RCLASS_SUBCLASSES(klass);
+ struct rb_class_set_box_classext_args *args = (struct rb_class_set_box_classext_args *)a;
- if (head) {
- if (head->next) {
- head->next->prev = NULL;
+ if (existing) {
+ if (LIKELY(BUILTIN_TYPE(args->obj) == T_ICLASS)) {
+ iclass_free_orphan_classext(args->obj, (rb_classext_t *)*val_ptr);
+ }
+ else {
+ rb_bug("Updating existing classext for non-iclass never happen");
}
- RCLASS_SUBCLASSES(klass) = NULL;
- xfree(head);
}
+
+ *val_ptr = (st_data_t)args->ext;
+
+ return ST_CONTINUE;
}
void
-rb_class_remove_from_super_subclasses(VALUE klass)
+rb_class_set_box_classext(VALUE obj, const rb_box_t *box, rb_classext_t *ext)
+{
+ struct rb_class_set_box_classext_args args = {
+ .obj = obj,
+ .ext = ext,
+ };
+
+ VM_ASSERT(BOX_USER_P(box));
+
+ st_update(RCLASS_CLASSEXT_TBL(obj), (st_data_t)box->box_object, set_box_classext_update, (st_data_t)&args);
+ st_insert(box->classext_cow_classes, (st_data_t)rb_obj_id(obj), obj);
+
+ // FIXME: This is done here because this is the first time the objects in
+ // the classext are exposed via this class. It's likely that if GC
+ // compaction occurred between the VALUEs being copied in and this
+ // writebarrier trigger the values will be stale.
+ rb_gc_writebarrier_remember(obj);
+}
+
+RUBY_EXTERN rb_serial_t ruby_vm_global_cvar_state;
+
+struct duplicate_id_tbl_data {
+ struct rb_id_table *tbl;
+ VALUE klass;
+};
+
+static enum rb_id_table_iterator_result
+duplicate_classext_id_table_i(ID key, VALUE value, void *data)
+{
+ struct rb_id_table *tbl = (struct rb_id_table *)data;
+ rb_id_table_insert(tbl, key, value);
+ return ID_TABLE_CONTINUE;
+}
+
+static enum rb_id_table_iterator_result
+duplicate_classext_m_tbl_i(ID key, VALUE value, void *data)
+{
+ struct duplicate_id_tbl_data *arg = (struct duplicate_id_tbl_data *)data;
+ rb_method_entry_t *me = (rb_method_entry_t *)value;
+ rb_method_table_insert0(arg->klass, arg->tbl, key, me, false);
+ return ID_TABLE_CONTINUE;
+}
+
+static struct rb_id_table *
+duplicate_classext_m_tbl(struct rb_id_table *orig, VALUE klass, bool init_missing)
+{
+ struct rb_id_table *tbl;
+ if (!orig) {
+ if (init_missing)
+ return rb_id_table_create(0);
+ else
+ return NULL;
+ }
+ tbl = rb_id_table_create(rb_id_table_size(orig));
+ struct duplicate_id_tbl_data data = {
+ .tbl = tbl,
+ .klass = klass,
+ };
+ rb_id_table_foreach(orig, duplicate_classext_m_tbl_i, &data);
+ return tbl;
+}
+
+static struct rb_id_table *
+duplicate_classext_id_table(struct rb_id_table *orig, bool init_missing)
+{
+ struct rb_id_table *tbl;
+
+ if (!orig) {
+ if (init_missing)
+ return rb_id_table_create(0);
+ else
+ return NULL;
+ }
+ tbl = rb_id_table_create(rb_id_table_size(orig));
+ rb_id_table_foreach(orig, duplicate_classext_id_table_i, tbl);
+ return tbl;
+}
+
+static rb_const_entry_t *
+duplicate_classext_const_entry(rb_const_entry_t *src, VALUE klass)
+{
+ // See also: setup_const_entry (variable.c)
+ rb_const_entry_t *dst = ZALLOC(rb_const_entry_t);
+
+ dst->flag = src->flag;
+ dst->line = src->line;
+ RB_OBJ_WRITE(klass, &dst->value, src->value);
+ RB_OBJ_WRITE(klass, &dst->file, src->file);
+
+ return dst;
+}
+
+static enum rb_id_table_iterator_result
+duplicate_classext_const_tbl_i(ID key, VALUE value, void *data)
+{
+ struct duplicate_id_tbl_data *arg = (struct duplicate_id_tbl_data *)data;
+ rb_const_entry_t *entry = duplicate_classext_const_entry((rb_const_entry_t *)value, arg->klass);
+
+ rb_id_table_insert(arg->tbl, key, (VALUE)entry);
+
+ return ID_TABLE_CONTINUE;
+}
+
+static struct rb_id_table *
+duplicate_classext_const_tbl(struct rb_id_table *src, VALUE klass)
{
- rb_subclass_entry_t *entry = RCLASS_SUBCLASS_ENTRY(klass);
+ struct rb_id_table *dst;
+
+ if (!src)
+ return NULL;
- if (entry) {
- rb_subclass_entry_t *prev = entry->prev, *next = entry->next;
+ dst = rb_id_table_create(rb_id_table_size(src));
- if (prev) {
- prev->next = next;
+ struct duplicate_id_tbl_data data = {
+ .tbl = dst,
+ .klass = klass,
+ };
+ rb_id_table_foreach(src, duplicate_classext_const_tbl_i, (void *)&data);
+
+ return dst;
+}
+
+static VALUE
+box_subclasses_tbl_key(const rb_box_t *box)
+{
+ if (!box){
+ return 0;
+ }
+ return (VALUE)box->box_id;
+}
+
+static void
+duplicate_classext_subclasses(rb_classext_t *orig, rb_classext_t *copy)
+{
+ rb_subclass_anchor_t *anchor, *orig_anchor;
+ rb_subclass_entry_t *head, *cur, *cdr, *entry, *first = NULL;
+ rb_box_subclasses_t *box_subclasses;
+ struct st_table *tbl;
+
+ if (RCLASSEXT_SUBCLASSES(orig)) {
+ orig_anchor = RCLASSEXT_SUBCLASSES(orig);
+ box_subclasses = orig_anchor->box_subclasses;
+ tbl = ((rb_box_subclasses_t *)box_subclasses)->tbl;
+
+ anchor = ZALLOC(rb_subclass_anchor_t);
+ anchor->box_subclasses = rb_box_subclasses_ref_inc(box_subclasses);
+
+ head = ZALLOC(rb_subclass_entry_t);
+ anchor->head = head;
+
+ RCLASSEXT_SUBCLASSES(copy) = anchor;
+
+ cur = head;
+ entry = orig_anchor->head;
+ RUBY_ASSERT(!entry->klass);
+ // The head entry has NULL klass always. See rb_class_foreach_subclass().
+ entry = entry->next;
+ while (entry) {
+ if (rb_objspace_garbage_object_p(entry->klass)) {
+ entry = entry->next;
+ continue;
+ }
+ cdr = ZALLOC(rb_subclass_entry_t);
+ cdr->klass = entry->klass;
+ cdr->prev = cur;
+ cur->next = cdr;
+ if (!first) {
+ VALUE box_id = box_subclasses_tbl_key(RCLASSEXT_BOX(copy));
+ first = cdr;
+ st_insert(tbl, box_id, (st_data_t)first);
+ }
+ cur = cdr;
+ entry = entry->next;
}
- if (next) {
- next->prev = prev;
+ }
+
+ if (RCLASSEXT_BOX_SUPER_SUBCLASSES(orig))
+ RCLASSEXT_BOX_SUPER_SUBCLASSES(copy) = rb_box_subclasses_ref_inc(RCLASSEXT_BOX_SUPER_SUBCLASSES(orig));
+ if (RCLASSEXT_BOX_MODULE_SUBCLASSES(orig))
+ RCLASSEXT_BOX_MODULE_SUBCLASSES(copy) = rb_box_subclasses_ref_inc(RCLASSEXT_BOX_MODULE_SUBCLASSES(orig));
+}
+
+static void
+class_duplicate_iclass_classext(VALUE iclass, rb_classext_t *mod_ext, const rb_box_t *box)
+{
+ RUBY_ASSERT(RB_TYPE_P(iclass, T_ICLASS));
+
+ rb_classext_t *src = RCLASS_EXT_PRIME(iclass);
+ rb_classext_t *ext = RCLASS_EXT_TABLE_LOOKUP_INTERNAL(iclass, box);
+ int first_set = 0;
+
+ if (ext) {
+ // iclass classext for the ns is only for cc/callable_m_tbl if it's created earlier than module's one
+ rb_invalidate_method_caches(RCLASSEXT_CALLABLE_M_TBL(ext), RCLASSEXT_CC_TBL(ext));
+ }
+
+ ext = ZALLOC(rb_classext_t);
+
+ RCLASSEXT_BOX(ext) = box;
+
+ RCLASSEXT_SUPER(ext) = RCLASSEXT_SUPER(src);
+
+ // See also: rb_include_class_new()
+ if (RCLASSEXT_ICLASS_IS_ORIGIN(src) && !RCLASSEXT_ICLASS_ORIGIN_SHARED_MTBL(src)) {
+ RCLASSEXT_M_TBL(ext) = duplicate_classext_m_tbl(RCLASSEXT_M_TBL(src), iclass, true);
+ }
+ else {
+ RCLASSEXT_M_TBL(ext) = RCLASSEXT_M_TBL(mod_ext);
+ }
+
+ RCLASSEXT_CONST_TBL(ext) = RCLASSEXT_CONST_TBL(mod_ext);
+ RCLASSEXT_CVC_TBL(ext) = RCLASSEXT_CVC_TBL(mod_ext);
+
+ // Those are cache and should be recreated when methods are called
+ // RCLASSEXT_CALLABLE_M_TBL(ext) = NULL;
+ // RCLASSEXT_CC_TBL(ext) = NULL;
+
+ // subclasses, box_super_subclasses_tbl, box_module_subclasses_tbl
+ duplicate_classext_subclasses(src, ext);
+
+ RCLASSEXT_SET_ORIGIN(ext, iclass, RCLASSEXT_ORIGIN(src));
+ RCLASSEXT_ICLASS_IS_ORIGIN(ext) = RCLASSEXT_ICLASS_IS_ORIGIN(src);
+ RCLASSEXT_ICLASS_ORIGIN_SHARED_MTBL(ext) = RCLASSEXT_ICLASS_ORIGIN_SHARED_MTBL(src);
+
+ RCLASSEXT_SET_INCLUDER(ext, iclass, RCLASSEXT_INCLUDER(src));
+
+ VM_ASSERT(FL_TEST_RAW(iclass, RCLASS_BOXABLE));
+
+ first_set = RCLASS_SET_BOX_CLASSEXT(iclass, box, ext);
+ if (first_set) {
+ RCLASS_SET_PRIME_CLASSEXT_WRITABLE(iclass, false);
+ }
+}
+
+rb_classext_t *
+rb_class_duplicate_classext(rb_classext_t *orig, VALUE klass, const rb_box_t *box)
+{
+ VM_ASSERT(RB_TYPE_P(klass, T_CLASS) || RB_TYPE_P(klass, T_MODULE) || RB_TYPE_P(klass, T_ICLASS));
+
+ rb_classext_t *ext = ZALLOC(rb_classext_t);
+ bool dup_iclass = RB_TYPE_P(klass, T_MODULE) ? true : false;
+
+ RCLASSEXT_BOX(ext) = box;
+
+ RCLASSEXT_SUPER(ext) = RCLASSEXT_SUPER(orig);
+
+ RCLASSEXT_M_TBL(ext) = duplicate_classext_m_tbl(RCLASSEXT_M_TBL(orig), klass, dup_iclass);
+ RCLASSEXT_ICLASS_IS_ORIGIN(ext) = true;
+ RCLASSEXT_ICLASS_ORIGIN_SHARED_MTBL(ext) = false;
+
+ if (orig->fields_obj) {
+ RB_OBJ_WRITE(klass, &ext->fields_obj, rb_imemo_fields_clone(orig->fields_obj));
+ }
+
+ if (RCLASSEXT_SHARED_CONST_TBL(orig)) {
+ RCLASSEXT_CONST_TBL(ext) = RCLASSEXT_CONST_TBL(orig);
+ RCLASSEXT_SHARED_CONST_TBL(ext) = true;
+ }
+ else {
+ RCLASSEXT_CONST_TBL(ext) = duplicate_classext_const_tbl(RCLASSEXT_CONST_TBL(orig), klass);
+ RCLASSEXT_SHARED_CONST_TBL(ext) = false;
+ }
+ /*
+ * callable_m_tbl is for `super` chain, and entries will be created when the super chain is called.
+ * so initially, it can be NULL and let it be created lazily.
+ * RCLASSEXT_CALLABLE_M_TBL(ext) = NULL;
+ *
+ * cc_tbl is for method inline cache, and method calls from different boxes never occur on
+ * the same code, so the copied classext should have a different cc_tbl from the prime one.
+ * RCLASSEXT_CC_TBL(copy) = NULL
+ */
+
+ RCLASSEXT_CVC_TBL(ext) = duplicate_classext_id_table(RCLASSEXT_CVC_TBL(orig), dup_iclass);
+
+ // subclasses, subclasses_index
+ duplicate_classext_subclasses(orig, ext);
+
+ RCLASSEXT_SET_ORIGIN(ext, klass, RCLASSEXT_ORIGIN(orig));
+ /*
+ * Members not copied to box's classext values
+ * * refined_class
+ * * as.class.allocator / as.singleton_class.attached_object
+ * * includer
+ * * max IV count
+ * * variation count
+ */
+ RCLASSEXT_PERMANENT_CLASSPATH(ext) = RCLASSEXT_PERMANENT_CLASSPATH(orig);
+ RCLASSEXT_CLONED(ext) = RCLASSEXT_CLONED(orig);
+ RCLASSEXT_CLASSPATH(ext) = RCLASSEXT_CLASSPATH(orig);
+
+ /* For the usual T_CLASS/T_MODULE, iclass flags are always false */
+
+ if (dup_iclass) {
+ VALUE iclass;
+ /*
+ * ICLASS has the same m_tbl/const_tbl/cvc_tbl with the included module.
+ * So the module's classext is copied, its tables should be also referred
+ * by the ICLASS's classext for the box.
+ */
+ rb_subclass_anchor_t *anchor = RCLASSEXT_SUBCLASSES(ext);
+ rb_subclass_entry_t *subclass_entry = anchor->head;
+ while (subclass_entry) {
+ if (subclass_entry->klass && RB_TYPE_P(subclass_entry->klass, T_ICLASS)) {
+ iclass = subclass_entry->klass;
+ VM_ASSERT(RB_TYPE_P(iclass, T_ICLASS));
+ if (RBASIC_CLASS(iclass) == klass) {
+ // Is the subclass an ICLASS including this module into another class
+ // If so we need to re-associate it under our box with the new ext
+ VM_ASSERT(FL_TEST_RAW(iclass, RCLASS_BOXABLE));
+ class_duplicate_iclass_classext(iclass, ext, box);
+ }
+ }
+ subclass_entry = subclass_entry->next;
}
+ }
- xfree(entry);
+ return ext;
+}
+
+void
+rb_class_ensure_writable(VALUE klass)
+{
+ VM_ASSERT(RB_TYPE_P(klass, T_CLASS) || RB_TYPE_P(klass, T_MODULE) || RB_TYPE_P(klass, T_ICLASS));
+ RCLASS_EXT_WRITABLE(klass);
+}
+
+struct class_classext_foreach_arg {
+ rb_class_classext_foreach_callback_func *func;
+ void * callback_arg;
+};
+
+static int
+class_classext_foreach_i(st_data_t key, st_data_t value, st_data_t arg)
+{
+ struct class_classext_foreach_arg *foreach_arg = (struct class_classext_foreach_arg *)arg;
+ rb_class_classext_foreach_callback_func *func = foreach_arg->func;
+ func((rb_classext_t *)value, false, (VALUE)key, foreach_arg->callback_arg);
+ return ST_CONTINUE;
+}
+
+void
+rb_class_classext_foreach(VALUE klass, rb_class_classext_foreach_callback_func *func, void *arg)
+{
+ st_table *tbl = RCLASS_CLASSEXT_TBL(klass);
+ struct class_classext_foreach_arg foreach_arg;
+ if (tbl) {
+ foreach_arg.func = func;
+ foreach_arg.callback_arg = arg;
+ rb_st_foreach(tbl, class_classext_foreach_i, (st_data_t)&foreach_arg);
+ }
+ func(RCLASS_EXT_PRIME(klass), true, (VALUE)NULL, arg);
+}
+
+VALUE
+rb_class_super_of(VALUE klass)
+{
+ return RCLASS_SUPER(klass);
+}
+
+VALUE
+rb_class_singleton_p(VALUE klass)
+{
+ return RCLASS_SINGLETON_P(klass);
+}
+
+unsigned char
+rb_class_variation_count(VALUE klass)
+{
+ return RCLASS_VARIATION_COUNT(klass);
+}
+
+static void
+push_subclass_entry_to_list(VALUE super, VALUE klass, bool is_module)
+{
+ rb_subclass_entry_t *entry, *head;
+ rb_subclass_anchor_t *anchor;
+ rb_box_subclasses_t *box_subclasses;
+ struct st_table *tbl;
+ const rb_box_t *box = rb_current_box();
+
+ entry = ZALLOC(rb_subclass_entry_t);
+ entry->klass = klass;
+
+ RB_VM_LOCKING() {
+ anchor = RCLASS_WRITABLE_SUBCLASSES(super);
+ VM_ASSERT(anchor);
+ box_subclasses = (rb_box_subclasses_t *)anchor->box_subclasses;
+ VM_ASSERT(box_subclasses);
+ tbl = box_subclasses->tbl;
+ VM_ASSERT(tbl);
+
+ head = anchor->head;
+ if (head->next) {
+ head->next->prev = entry;
+ entry->next = head->next;
+ }
+ head->next = entry;
+ entry->prev = head;
+ st_insert(tbl, box_subclasses_tbl_key(box), (st_data_t)entry);
}
- RCLASS_SUBCLASS_ENTRY(klass) = NULL;
+ if (is_module) {
+ RCLASS_WRITE_BOX_MODULE_SUBCLASSES(klass, anchor->box_subclasses);
+ }
+ else {
+ RCLASS_WRITE_BOX_SUPER_SUBCLASSES(klass, anchor->box_subclasses);
+ }
}
void
-rb_class_remove_from_module_subclasses(VALUE klass)
+rb_class_subclass_add(VALUE super, VALUE klass)
{
- rb_subclass_entry_t *entry = RCLASS_MODULE_SUBCLASS_ENTRY(klass);
+ if (super && !UNDEF_P(super)) {
+ push_subclass_entry_to_list(super, klass, false);
+ }
+}
- if (entry) {
- rb_subclass_entry_t *prev = entry->prev, *next = entry->next;
+static void
+rb_module_add_to_subclasses_list(VALUE module, VALUE iclass)
+{
+ if (module && !UNDEF_P(module)) {
+ push_subclass_entry_to_list(module, iclass, true);
+ }
+}
+
+static struct rb_subclass_entry *
+class_get_subclasses_for_ns(struct st_table *tbl, VALUE box_id)
+{
+ st_data_t value;
+ if (st_lookup(tbl, (st_data_t)box_id, &value)) {
+ return (struct rb_subclass_entry *)value;
+ }
+ return NULL;
+}
- if (prev) {
- prev->next = next;
+static int
+remove_class_from_subclasses_replace_first_entry(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
+{
+ *value = arg;
+ return ST_CONTINUE;
+}
+
+static void
+remove_class_from_subclasses(struct st_table *tbl, VALUE box_id, VALUE klass)
+{
+ rb_subclass_entry_t *entry = class_get_subclasses_for_ns(tbl, box_id);
+ bool first_entry = true;
+ while (entry) {
+ if (entry->klass == klass) {
+ rb_subclass_entry_t *prev = entry->prev, *next = entry->next;
+
+ if (prev) {
+ prev->next = next;
+ }
+ if (next) {
+ next->prev = prev;
+ }
+
+ if (first_entry) {
+ if (next) {
+ st_update(tbl, box_id, remove_class_from_subclasses_replace_first_entry, (st_data_t)next);
+ }
+ else {
+ // no subclass entries in this ns after the deletion
+ st_delete(tbl, &box_id, NULL);
+ }
+ }
+
+ xfree(entry);
+
+ break;
}
- if (next) {
- next->prev = prev;
+ else if (first_entry) {
+ first_entry = false;
}
+ entry = entry->next;
+ }
+}
+
+void
+rb_class_remove_from_super_subclasses(VALUE klass)
+{
+ rb_classext_t *ext = RCLASS_EXT_WRITABLE(klass);
+ rb_box_subclasses_t *box_subclasses = RCLASSEXT_BOX_SUPER_SUBCLASSES(ext);
+
+ if (!box_subclasses) return;
+ remove_class_from_subclasses(box_subclasses->tbl, box_subclasses_tbl_key(RCLASSEXT_BOX(ext)), klass);
+ rb_box_subclasses_ref_dec(box_subclasses);
+ RCLASSEXT_BOX_SUPER_SUBCLASSES(ext) = 0;
+}
+void
+rb_class_classext_free_subclasses(rb_classext_t *ext, VALUE klass, bool replacing)
+{
+ rb_subclass_anchor_t *anchor = RCLASSEXT_SUBCLASSES(ext);
+ struct st_table *tbl = anchor->box_subclasses->tbl;
+ VALUE box_id = box_subclasses_tbl_key(RCLASSEXT_BOX(ext));
+ rb_subclass_entry_t *next, *entry = anchor->head;
+
+ while (entry) {
+ next = entry->next;
xfree(entry);
+ entry = next;
}
+ VM_ASSERT(
+ rb_box_subclasses_ref_count(anchor->box_subclasses) > 0,
+ "box_subclasses refcount (%p) %ld", anchor->box_subclasses, rb_box_subclasses_ref_count(anchor->box_subclasses));
+ st_delete(tbl, &box_id, NULL);
+ rb_box_subclasses_ref_dec(anchor->box_subclasses);
+ xfree(anchor);
- RCLASS_MODULE_SUBCLASS_ENTRY(klass) = NULL;
+ if (RCLASSEXT_BOX_SUPER_SUBCLASSES(ext)) {
+ rb_box_subclasses_t *box_sub = RCLASSEXT_BOX_SUPER_SUBCLASSES(ext);
+ if (!replacing) remove_class_from_subclasses(box_sub->tbl, box_id, klass);
+ rb_box_subclasses_ref_dec(box_sub);
+ }
+ if (RCLASSEXT_BOX_MODULE_SUBCLASSES(ext)) {
+ rb_box_subclasses_t *box_sub = RCLASSEXT_BOX_MODULE_SUBCLASSES(ext);
+ if (!replacing) remove_class_from_subclasses(box_sub->tbl, box_id, klass);
+ rb_box_subclasses_ref_dec(box_sub);
+ }
}
void
rb_class_foreach_subclass(VALUE klass, void (*f)(VALUE, VALUE), VALUE arg)
{
- // RCLASS_SUBCLASSES should always point to our head element which has NULL klass
- rb_subclass_entry_t *cur = RCLASS_SUBCLASSES(klass);
- // if we have a subclasses list, then the head is a placeholder with no valid
- // class. So ignore it and use the next element in the list (if one exists)
- if (cur) {
- RUBY_ASSERT(!cur->klass);
- cur = cur->next;
- }
-
+ rb_subclass_entry_t *tmp;
+ rb_subclass_entry_t *cur = RCLASS_SUBCLASSES_FIRST(klass);
/* do not be tempted to simplify this loop into a for loop, the order of
operations is important here if `f` modifies the linked list */
while (cur) {
VALUE curklass = cur->klass;
- cur = cur->next;
+ tmp = cur->next;
// do not trigger GC during f, otherwise the cur will become
// a dangling pointer if the subclass is collected
f(curklass, arg);
+ cur = tmp;
}
}
@@ -205,67 +733,147 @@ class_detach_subclasses(VALUE klass, VALUE arg)
rb_class_remove_from_super_subclasses(klass);
}
-void
-rb_class_detach_subclasses(VALUE klass)
-{
- rb_class_foreach_subclass(klass, class_detach_subclasses, Qnil);
-}
-
static void
-class_detach_module_subclasses(VALUE klass, VALUE arg)
-{
- rb_class_remove_from_module_subclasses(klass);
-}
-
-void
-rb_class_detach_module_subclasses(VALUE klass)
+class_switch_superclass(VALUE super, VALUE klass)
{
- rb_class_foreach_subclass(klass, class_detach_module_subclasses, Qnil);
+ RB_VM_LOCKING() {
+ class_detach_subclasses(klass, Qnil);
+ rb_class_subclass_add(super, klass);
+ }
}
/**
- * Allocates a struct RClass for a new class.
+ * Allocates a struct RClass for a new class, iclass, or module.
*
- * @param flags initial value for basic.flags of the returned class.
- * @param klass the class of the returned class.
- * @return an uninitialized Class object.
- * @pre `klass` must refer `Class` class or an ancestor of Class.
- * @pre `(flags | T_CLASS) != 0`
- * @post the returned class can safely be `#initialize` 'd.
+ * @param type The type of the RClass (T_CLASS, T_ICLASS, or T_MODULE)
+ * @param klass value for basic.klass of the returned object.
+ * @return an uninitialized Class/IClass/Module object.
+ * @pre `klass` must refer to a class or module
*
* @note this function is not Class#allocate.
*/
static VALUE
-class_alloc(VALUE flags, VALUE klass)
+class_alloc0(enum ruby_value_type type, VALUE klass, bool boxable)
{
- size_t alloc_size = sizeof(struct RClass) + sizeof(rb_classext_t);
+ rb_box_subclasses_t *box_subclasses;
+ rb_subclass_anchor_t *anchor;
+ const rb_box_t *box = rb_current_box();
+
+ if (!ruby_box_init_done) {
+ boxable = true;
+ }
+
+ size_t alloc_size = sizeof(struct RClass_and_rb_classext_t);
+ if (boxable) {
+ alloc_size = sizeof(struct RClass_boxable);
+ }
- flags &= T_MASK;
+ // class_alloc is supposed to return a new object that is not promoted yet.
+ // So, we need to avoid GC after NEWOBJ_OF.
+ // To achieve that, we allocate subclass lists before NEWOBJ_OF.
+ //
+ // TODO: Note that this could cause memory leak.
+ // If NEWOBJ_OF fails with out of memory, these buffers will leak.
+ box_subclasses = ZALLOC(rb_box_subclasses_t);
+ box_subclasses->refcount = 1;
+ box_subclasses->tbl = st_init_numtable();
+ anchor = ZALLOC(rb_subclass_anchor_t);
+ anchor->box_subclasses = box_subclasses;
+ anchor->head = ZALLOC(rb_subclass_entry_t);
+
+ RUBY_ASSERT(type == T_CLASS || type == T_ICLASS || type == T_MODULE);
+
+ VALUE flags = type | FL_SHAREABLE;
if (RGENGC_WB_PROTECTED_CLASS) flags |= FL_WB_PROTECTED;
+ if (boxable) flags |= RCLASS_BOXABLE;
+
NEWOBJ_OF(obj, struct RClass, klass, flags, alloc_size, 0);
- memset(RCLASS_EXT(obj), 0, sizeof(rb_classext_t));
+ obj->object_id = 0;
+
+ memset(RCLASS_EXT_PRIME(obj), 0, sizeof(rb_classext_t));
/* ZALLOC
RCLASS_CONST_TBL(obj) = 0;
RCLASS_M_TBL(obj) = 0;
- RCLASS_IV_INDEX_TBL(obj) = 0;
+ RCLASS_FIELDS(obj) = 0;
RCLASS_SET_SUPER((VALUE)obj, 0);
- RCLASS_SUBCLASSES(obj) = NULL;
- RCLASS_PARENT_SUBCLASSES(obj) = NULL;
- RCLASS_MODULE_SUBCLASSES(obj) = NULL;
*/
+
+ if (boxable) {
+ ((struct RClass_boxable *)obj)->box_classext_tbl = NULL;
+ }
+
+ RCLASS_PRIME_BOX((VALUE)obj) = box;
+ // Classes/Modules defined in user boxes are
+ // writable directly because it exists only in a box.
+ RCLASS_SET_PRIME_CLASSEXT_WRITABLE((VALUE)obj, !boxable || BOX_USER_P(box));
+
RCLASS_SET_ORIGIN((VALUE)obj, (VALUE)obj);
- RB_OBJ_WRITE(obj, &RCLASS_REFINED_CLASS(obj), Qnil);
- RCLASS_SET_ALLOCATOR((VALUE)obj, 0);
+ RCLASS_SET_REFINED_CLASS((VALUE)obj, Qnil);
+
+ RCLASS_SET_SUBCLASSES((VALUE)obj, anchor);
return (VALUE)obj;
}
+static VALUE
+class_alloc(enum ruby_value_type type, VALUE klass)
+{
+ bool boxable = rb_box_available() && BOX_ROOT_P(rb_current_box());
+ return class_alloc0(type, klass, boxable);
+}
+
+static VALUE
+class_associate_super(VALUE klass, VALUE super, bool init)
+{
+ if (super && !UNDEF_P(super)) {
+ class_switch_superclass(super, klass);
+ }
+ if (init) {
+ RCLASS_SET_SUPER(klass, super);
+ }
+ else {
+ RCLASS_WRITE_SUPER(klass, super);
+ }
+ rb_class_update_superclasses(klass);
+ return super;
+}
+
+VALUE
+rb_class_set_super(VALUE klass, VALUE super)
+{
+ return class_associate_super(klass, super, false);
+}
+
static void
-RCLASS_M_TBL_INIT(VALUE c)
+class_initialize_method_table(VALUE c)
{
- RCLASS_M_TBL(c) = rb_id_table_create(0);
+ // initialize the prime classext m_tbl
+ RCLASS_SET_M_TBL(c, rb_id_table_create(0));
+}
+
+static void
+class_clear_method_table(VALUE c)
+{
+ RCLASS_WRITE_M_TBL(c, rb_id_table_create(0));
+}
+
+static VALUE
+class_boot_boxable(VALUE super, bool boxable)
+{
+ VALUE klass = class_alloc0(T_CLASS, rb_cClass, boxable);
+
+ // initialize method table prior to class_associate_super()
+ // because class_associate_super() may cause GC and promote klass
+ class_initialize_method_table(klass);
+
+ class_associate_super(klass, super, true);
+ if (super && !UNDEF_P(super)) {
+ rb_class_set_initialized(klass);
+ }
+
+ return (VALUE)klass;
}
/**
@@ -280,18 +888,13 @@ RCLASS_M_TBL_INIT(VALUE c)
VALUE
rb_class_boot(VALUE super)
{
- VALUE klass = class_alloc(T_CLASS, rb_cClass);
-
- RCLASS_SET_SUPER(klass, super);
- RCLASS_M_TBL_INIT(klass);
-
- return (VALUE)klass;
+ return class_boot_boxable(super, false);
}
static VALUE *
class_superclasses_including_self(VALUE klass)
{
- if (FL_TEST_RAW(klass, RCLASS_SUPERCLASSES_INCLUDE_SELF))
+ if (RCLASS_SUPERCLASSES_WITH_SELF_P(klass))
return RCLASS_SUPERCLASSES(klass);
size_t depth = RCLASS_SUPERCLASS_DEPTH(klass);
@@ -300,14 +903,14 @@ class_superclasses_including_self(VALUE klass)
memcpy(superclasses, RCLASS_SUPERCLASSES(klass), sizeof(VALUE) * depth);
superclasses[depth] = klass;
- RCLASS_SUPERCLASSES(klass) = superclasses;
- FL_SET_RAW(klass, RCLASS_SUPERCLASSES_INCLUDE_SELF);
return superclasses;
}
void
rb_class_update_superclasses(VALUE klass)
{
+ VALUE *superclasses;
+ size_t super_depth;
VALUE super = RCLASS_SUPER(klass);
if (!RB_TYPE_P(klass, T_CLASS)) return;
@@ -336,8 +939,17 @@ rb_class_update_superclasses(VALUE klass)
return;
}
- RCLASS_SUPERCLASSES(klass) = class_superclasses_including_self(super);
- RCLASS_SUPERCLASS_DEPTH(klass) = RCLASS_SUPERCLASS_DEPTH(super) + 1;
+ super_depth = RCLASS_SUPERCLASS_DEPTH(super);
+ if (RCLASS_SUPERCLASSES_WITH_SELF_P(super)) {
+ superclasses = RCLASS_SUPERCLASSES(super);
+ }
+ else {
+ superclasses = class_superclasses_including_self(super);
+ RCLASS_WRITE_SUPERCLASSES(super, super_depth, superclasses, true);
+ }
+
+ size_t depth = super_depth == RCLASS_MAX_SUPERCLASS_DEPTH ? super_depth : super_depth + 1;
+ RCLASS_WRITE_SUPERCLASSES(klass, depth, superclasses, false);
}
void
@@ -363,9 +975,11 @@ rb_class_new(VALUE super)
VALUE klass = rb_class_boot(super);
if (super != rb_cObject && super != rb_cBasicObject) {
- RCLASS_EXT(klass)->max_iv_count = RCLASS_EXT(super)->max_iv_count;
+ RCLASS_SET_MAX_IV_COUNT(klass, RCLASS_MAX_IV_COUNT(super));
}
+ RUBY_ASSERT(getenv("RUBY_BOX") || RCLASS_PRIME_CLASSEXT_WRITABLE_P(klass));
+
return klass;
}
@@ -379,8 +993,7 @@ static void
clone_method(VALUE old_klass, VALUE new_klass, ID mid, const rb_method_entry_t *me)
{
if (me->def->type == VM_METHOD_TYPE_ISEQ) {
- rb_cref_t *new_cref;
- rb_vm_rewrite_cref(me->def->body.iseq.cref, old_klass, new_klass, &new_cref);
+ rb_cref_t *new_cref = rb_vm_rewrite_cref(me->def->body.iseq.cref, old_klass, new_klass);
rb_add_method_iseq(new_klass, mid, me->def->body.iseq.iseqptr, new_cref, METHOD_ENTRY_VISI(me));
}
else {
@@ -430,7 +1043,7 @@ class_init_copy_check(VALUE clone, VALUE orig)
if (orig == rb_cBasicObject) {
rb_raise(rb_eTypeError, "can't copy the root class");
}
- if (RCLASS_SUPER(clone) != 0 || clone == rb_cBasicObject) {
+ if (RCLASS_INITIALIZED_P(clone)) {
rb_raise(rb_eTypeError, "already initialized class");
}
if (RCLASS_SINGLETON_P(orig)) {
@@ -468,7 +1081,7 @@ copy_tables(VALUE clone, VALUE orig)
{
if (RCLASS_CONST_TBL(clone)) {
rb_free_const_table(RCLASS_CONST_TBL(clone));
- RCLASS_CONST_TBL(clone) = 0;
+ RCLASS_WRITE_CONST_TBL(clone, 0, false);
}
if (RCLASS_CVC_TBL(orig)) {
struct rb_id_table *rb_cvc_tbl = RCLASS_CVC_TBL(orig);
@@ -478,52 +1091,38 @@ copy_tables(VALUE clone, VALUE orig)
ctx.clone = clone;
ctx.new_table = rb_cvc_tbl_dup;
rb_id_table_foreach(rb_cvc_tbl, cvc_table_copy, &ctx);
- RCLASS_CVC_TBL(clone) = rb_cvc_tbl_dup;
+ RCLASS_WRITE_CVC_TBL(clone, rb_cvc_tbl_dup);
}
rb_id_table_free(RCLASS_M_TBL(clone));
- RCLASS_M_TBL(clone) = 0;
+ RCLASS_WRITE_M_TBL(clone, 0);
if (!RB_TYPE_P(clone, T_ICLASS)) {
- st_data_t id;
-
- rb_iv_tbl_copy(clone, orig);
- CONST_ID(id, "__tmp_classpath__");
- rb_attr_delete(clone, id);
- CONST_ID(id, "__classpath__");
- rb_attr_delete(clone, id);
+ rb_fields_tbl_copy(clone, orig);
}
if (RCLASS_CONST_TBL(orig)) {
struct clone_const_arg arg;
-
- arg.tbl = RCLASS_CONST_TBL(clone) = rb_id_table_create(0);
+ struct rb_id_table *const_tbl;
+ struct rb_id_table *orig_tbl = RCLASS_CONST_TBL(orig);
+ arg.tbl = const_tbl = rb_id_table_create(rb_id_table_size(orig_tbl));
arg.klass = clone;
- rb_id_table_foreach(RCLASS_CONST_TBL(orig), clone_const_i, &arg);
+ rb_id_table_foreach(orig_tbl, clone_const_i, &arg);
+ RCLASS_WRITE_CONST_TBL(clone, const_tbl, false);
}
}
static bool ensure_origin(VALUE klass);
-/**
- * If this flag is set, that module is allocated but not initialized yet.
- */
-enum {RMODULE_ALLOCATED_BUT_NOT_INITIALIZED = RUBY_FL_USER1};
-
-static inline bool
-RMODULE_UNINITIALIZED(VALUE module)
-{
- return FL_TEST_RAW(module, RMODULE_ALLOCATED_BUT_NOT_INITIALIZED);
-}
-
void
-rb_module_set_initialized(VALUE mod)
+rb_class_set_initialized(VALUE klass)
{
- FL_UNSET_RAW(mod, RMODULE_ALLOCATED_BUT_NOT_INITIALIZED);
+ RUBY_ASSERT(RB_TYPE_P(klass, T_CLASS) || RB_TYPE_P(klass, T_MODULE));
+ FL_SET_RAW(klass, RCLASS_IS_INITIALIZED);
/* no more re-initialization */
}
void
rb_module_check_initializable(VALUE mod)
{
- if (!RMODULE_UNINITIALIZED(mod)) {
+ if (RCLASS_INITIALIZED_P(mod)) {
rb_raise(rb_eTypeError, "already initialized module");
}
}
@@ -532,9 +1131,11 @@ rb_module_check_initializable(VALUE mod)
VALUE
rb_mod_init_copy(VALUE clone, VALUE orig)
{
+ /* Only class or module is valid here, but other classes may enter here and
+ * only hit an exception on the OBJ_INIT_COPY checks
+ */
switch (BUILTIN_TYPE(clone)) {
case T_CLASS:
- case T_ICLASS:
class_init_copy_check(clone, orig);
break;
case T_MODULE:
@@ -545,28 +1146,35 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
}
if (!OBJ_INIT_COPY(clone, orig)) return clone;
+ RUBY_ASSERT(RB_TYPE_P(orig, T_CLASS) || RB_TYPE_P(orig, T_MODULE));
+ RUBY_ASSERT(BUILTIN_TYPE(clone) == BUILTIN_TYPE(orig));
+
+ rb_class_set_initialized(clone);
+
/* cloned flag is refer at constant inline cache
* see vm_get_const_key_cref() in vm_insnhelper.c
*/
- RCLASS_EXT(clone)->cloned = true;
- RCLASS_EXT(orig)->cloned = true;
+ RCLASS_SET_CLONED(clone, true);
+ RCLASS_SET_CLONED(orig, true);
if (!RCLASS_SINGLETON_P(CLASS_OF(clone))) {
RBASIC_SET_CLASS(clone, rb_singleton_class_clone(orig));
rb_singleton_class_attached(METACLASS_OF(clone), (VALUE)clone);
}
- RCLASS_SET_ALLOCATOR(clone, RCLASS_ALLOCATOR(orig));
+ if (BUILTIN_TYPE(clone) == T_CLASS) {
+ RCLASS_SET_ALLOCATOR(clone, RCLASS_ALLOCATOR(orig));
+ }
copy_tables(clone, orig);
if (RCLASS_M_TBL(orig)) {
struct clone_method_arg arg;
arg.old_klass = orig;
arg.new_klass = clone;
- RCLASS_M_TBL_INIT(clone);
+ class_initialize_method_table(clone);
rb_id_table_foreach(RCLASS_M_TBL(orig), clone_method_i, &arg);
}
if (RCLASS_ORIGIN(orig) == orig) {
- RCLASS_SET_SUPER(clone, RCLASS_SUPER(orig));
+ rb_class_set_super(clone, RCLASS_SUPER(orig));
}
else {
VALUE p = RCLASS_SUPER(orig);
@@ -586,15 +1194,11 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
if (BUILTIN_TYPE(p) != T_ICLASS) {
rb_bug("non iclass between module/class and origin");
}
- clone_p = class_alloc(RBASIC(p)->flags, METACLASS_OF(p));
- /* We should set the m_tbl right after allocation before anything
- * that can trigger GC to avoid clone_p from becoming old and
- * needing to fire write barriers. */
+ clone_p = class_alloc(T_ICLASS, METACLASS_OF(p));
RCLASS_SET_M_TBL(clone_p, RCLASS_M_TBL(p));
- RCLASS_SET_SUPER(prev_clone_p, clone_p);
+ rb_class_set_super(prev_clone_p, clone_p);
prev_clone_p = clone_p;
- RCLASS_CONST_TBL(clone_p) = RCLASS_CONST_TBL(p);
- RCLASS_SET_ALLOCATOR(clone_p, RCLASS_ALLOCATOR(p));
+ RCLASS_SET_CONST_TBL(clone_p, RCLASS_CONST_TBL(p), false);
if (RB_TYPE_P(clone, T_CLASS)) {
RCLASS_SET_INCLUDER(clone_p, clone);
}
@@ -606,8 +1210,8 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
}
else if ((origin_len = RARRAY_LEN(origin_stack)) > 1 &&
RARRAY_AREF(origin_stack, origin_len - 1) == p) {
- RCLASS_SET_ORIGIN(RARRAY_AREF(origin_stack, (origin_len -= 2)), clone_p);
- RICLASS_SET_ORIGIN_SHARED_MTBL(clone_p);
+ RCLASS_WRITE_ORIGIN(RARRAY_AREF(origin_stack, (origin_len -= 2)), clone_p);
+ RICLASS_WRITE_ORIGIN_SHARED_MTBL(clone_p);
rb_ary_resize(origin_stack, origin_len);
add_subclass = FALSE;
}
@@ -619,15 +1223,15 @@ rb_mod_init_copy(VALUE clone, VALUE orig)
if (p == orig_origin) {
if (clone_p) {
- RCLASS_SET_SUPER(clone_p, clone_origin);
- RCLASS_SET_SUPER(clone_origin, RCLASS_SUPER(orig_origin));
+ rb_class_set_super(clone_p, clone_origin);
+ rb_class_set_super(clone_origin, RCLASS_SUPER(orig_origin));
}
copy_tables(clone_origin, orig_origin);
if (RCLASS_M_TBL(orig_origin)) {
struct clone_method_arg arg;
arg.old_klass = orig;
arg.new_klass = clone;
- RCLASS_M_TBL_INIT(clone_origin);
+ class_initialize_method_table(clone_origin);
rb_id_table_foreach(RCLASS_M_TBL(orig_origin), clone_method_i, &arg);
}
}
@@ -664,7 +1268,8 @@ rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach)
else {
/* copy singleton(unnamed) class */
bool klass_of_clone_is_new;
- VALUE clone = class_alloc(RBASIC(klass)->flags, 0);
+ RUBY_ASSERT(RB_TYPE_P(klass, T_CLASS));
+ VALUE clone = class_alloc(T_CLASS, 0);
if (BUILTIN_TYPE(obj) == T_CLASS) {
klass_of_clone_is_new = true;
@@ -678,18 +1283,22 @@ rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach)
RBASIC_SET_CLASS(clone, klass_metaclass_clone);
}
- RCLASS_SET_SUPER(clone, RCLASS_SUPER(klass));
- rb_iv_tbl_copy(clone, klass);
+ // initialize method table before any GC chance
+ class_initialize_method_table(clone);
+
+ rb_class_set_super(clone, RCLASS_SUPER(klass));
+ rb_fields_tbl_copy(clone, klass);
if (RCLASS_CONST_TBL(klass)) {
struct clone_const_arg arg;
- arg.tbl = RCLASS_CONST_TBL(clone) = rb_id_table_create(0);
+ struct rb_id_table *table;
+ arg.tbl = table = rb_id_table_create(rb_id_table_size(RCLASS_CONST_TBL(klass)));
arg.klass = clone;
rb_id_table_foreach(RCLASS_CONST_TBL(klass), clone_const_i, &arg);
+ RCLASS_SET_CONST_TBL(clone, table, false);
}
if (!UNDEF_P(attach)) {
rb_singleton_class_attached(clone, attach);
}
- RCLASS_M_TBL_INIT(clone);
{
struct clone_method_arg arg;
arg.old_klass = klass;
@@ -766,7 +1375,7 @@ static inline VALUE
make_metaclass(VALUE klass)
{
VALUE super;
- VALUE metaclass = rb_class_boot(Qundef);
+ VALUE metaclass = class_boot_boxable(Qundef, FL_TEST_RAW(klass, RCLASS_BOXABLE));
FL_SET(metaclass, FL_SINGLETON);
rb_singleton_class_attached(metaclass, klass);
@@ -783,7 +1392,8 @@ make_metaclass(VALUE klass)
super = RCLASS_SUPER(klass);
while (RB_TYPE_P(super, T_ICLASS)) super = RCLASS_SUPER(super);
- RCLASS_SET_SUPER(metaclass, super ? ENSURE_EIGENCLASS(super) : rb_cClass);
+ class_associate_super(metaclass, super ? ENSURE_EIGENCLASS(super) : rb_cClass, true);
+ rb_class_set_initialized(klass);
// Full class ancestry may not have been filled until we reach here.
rb_class_update_superclasses(METACLASS_OF(metaclass));
@@ -801,12 +1411,13 @@ static inline VALUE
make_singleton_class(VALUE obj)
{
VALUE orig_class = METACLASS_OF(obj);
- VALUE klass = rb_class_boot(orig_class);
+ VALUE klass = class_boot_boxable(orig_class, FL_TEST_RAW(orig_class, RCLASS_BOXABLE));
FL_SET(klass, FL_SINGLETON);
RBASIC_SET_CLASS(obj, klass);
rb_singleton_class_attached(klass, obj);
rb_yjit_invalidate_no_singleton_class(orig_class);
+ rb_zjit_invalidate_no_singleton_class(orig_class);
SET_METACLASS_OF(klass, METACLASS_OF(rb_class_real(orig_class)));
return klass;
@@ -982,9 +1593,8 @@ VALUE
rb_define_class(const char *name, VALUE super)
{
VALUE klass;
- ID id;
+ ID id = rb_intern(name);
- id = rb_intern(name);
if (rb_const_defined(rb_cObject, id)) {
klass = rb_const_get(rb_cObject, id);
if (!RB_TYPE_P(klass, T_CLASS)) {
@@ -1061,8 +1671,7 @@ VALUE
rb_module_s_alloc(VALUE klass)
{
VALUE mod = class_alloc(T_MODULE, klass);
- RCLASS_M_TBL_INIT(mod);
- FL_SET(mod, RMODULE_ALLOCATED_BUT_NOT_INITIALIZED);
+ class_initialize_method_table(mod);
return mod;
}
@@ -1070,7 +1679,7 @@ static inline VALUE
module_new(VALUE klass)
{
VALUE mdl = class_alloc(T_MODULE, klass);
- RCLASS_M_TBL_INIT(mdl);
+ class_initialize_method_table(mdl);
return (VALUE)mdl;
}
@@ -1097,9 +1706,8 @@ VALUE
rb_define_module(const char *name)
{
VALUE module;
- ID id;
+ ID id = rb_intern(name);
- id = rb_intern(name);
if (rb_const_defined(rb_cObject, id)) {
module = rb_const_get(rb_cObject, id);
if (!RB_TYPE_P(module, T_MODULE)) {
@@ -1152,21 +1760,24 @@ rb_include_class_new(VALUE module, VALUE super)
{
VALUE klass = class_alloc(T_ICLASS, rb_cClass);
- RCLASS_SET_M_TBL(klass, RCLASS_M_TBL(module));
+ RCLASS_SET_M_TBL(klass, RCLASS_WRITABLE_M_TBL(module));
RCLASS_SET_ORIGIN(klass, klass);
if (BUILTIN_TYPE(module) == T_ICLASS) {
module = METACLASS_OF(module);
}
RUBY_ASSERT(!RB_TYPE_P(module, T_ICLASS));
- if (!RCLASS_CONST_TBL(module)) {
- RCLASS_CONST_TBL(module) = rb_id_table_create(0);
+ if (RCLASS_WRITABLE_CONST_TBL(module)) {
+ RCLASS_SET_CONST_TBL(klass, RCLASS_WRITABLE_CONST_TBL(module), true);
+ }
+ else {
+ RCLASS_WRITE_CONST_TBL(module, rb_id_table_create(0), false);
+ RCLASS_SET_CONST_TBL(klass, RCLASS_WRITABLE_CONST_TBL(module), true);
}
- RCLASS_CVC_TBL(klass) = RCLASS_CVC_TBL(module);
- RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module);
+ RCLASS_SET_CVC_TBL(klass, RCLASS_WRITABLE_CVC_TBL(module));
- RCLASS_SET_SUPER(klass, super);
+ class_associate_super(klass, super, true);
RBASIC_SET_CLASS(klass, module);
return (VALUE)klass;
@@ -1179,7 +1790,7 @@ ensure_includable(VALUE klass, VALUE module)
{
rb_class_modify_check(klass);
Check_Type(module, T_MODULE);
- rb_module_set_initialized(module);
+ rb_class_set_initialized(module);
if (!NIL_P(rb_refinement_module_get_refined_class(module))) {
rb_raise(rb_eArgError, "refinement module is not allowed");
}
@@ -1197,15 +1808,9 @@ rb_include_module(VALUE klass, VALUE module)
rb_raise(rb_eArgError, "cyclic include detected");
if (RB_TYPE_P(klass, T_MODULE)) {
- rb_subclass_entry_t *iclass = RCLASS_SUBCLASSES(klass);
- // skip the placeholder subclass entry at the head of the list
- if (iclass) {
- RUBY_ASSERT(!iclass->klass);
- iclass = iclass->next;
- }
-
- int do_include = 1;
+ rb_subclass_entry_t *iclass = RCLASS_SUBCLASSES_FIRST(klass);
while (iclass) {
+ int do_include = 1;
VALUE check_class = iclass->klass;
/* During lazy sweeping, iclass->klass could be a dead object that
* has not yet been swept. */
@@ -1272,7 +1877,7 @@ static int
do_include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super, bool check_cyclic)
{
VALUE p, iclass, origin_stack = 0;
- int method_changed = 0, add_subclass;
+ int method_changed = 0;
long origin_len;
VALUE klass_origin = RCLASS_ORIGIN(klass);
VALUE original_klass = klass;
@@ -1334,9 +1939,8 @@ do_include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super
// setup T_ICLASS for the include/prepend module
iclass = rb_include_class_new(module, super_class);
- c = RCLASS_SET_SUPER(c, iclass);
+ c = rb_class_set_super(c, iclass);
RCLASS_SET_INCLUDER(iclass, klass);
- add_subclass = TRUE;
if (module != RCLASS_ORIGIN(module)) {
if (!origin_stack) origin_stack = rb_ary_hidden_new(2);
VALUE origin[2] = {iclass, RCLASS_ORIGIN(module)};
@@ -1344,17 +1948,14 @@ do_include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super
}
else if (origin_stack && (origin_len = RARRAY_LEN(origin_stack)) > 1 &&
RARRAY_AREF(origin_stack, origin_len - 1) == module) {
- RCLASS_SET_ORIGIN(RARRAY_AREF(origin_stack, (origin_len -= 2)), iclass);
- RICLASS_SET_ORIGIN_SHARED_MTBL(iclass);
+ RCLASS_WRITE_ORIGIN(RARRAY_AREF(origin_stack, (origin_len -= 2)), iclass);
+ RICLASS_WRITE_ORIGIN_SHARED_MTBL(iclass);
rb_ary_resize(origin_stack, origin_len);
- add_subclass = FALSE;
}
- if (add_subclass) {
- VALUE m = module;
- if (BUILTIN_TYPE(m) == T_ICLASS) m = METACLASS_OF(m);
- rb_module_add_to_subclasses_list(m, iclass);
- }
+ VALUE m = module;
+ if (BUILTIN_TYPE(m) == T_ICLASS) m = METACLASS_OF(m);
+ rb_module_add_to_subclasses_list(m, iclass);
if (BUILTIN_TYPE(klass) == T_MODULE && FL_TEST(klass, RMODULE_IS_REFINEMENT)) {
VALUE refined_class =
@@ -1387,7 +1988,7 @@ move_refined_method(ID key, VALUE value, void *data)
if (me->def->type == VM_METHOD_TYPE_REFINED) {
VALUE klass = (VALUE)data;
- struct rb_id_table *tbl = RCLASS_M_TBL(klass);
+ struct rb_id_table *tbl = RCLASS_WRITABLE_M_TBL(klass);
if (me->def->body.refined.orig_me) {
const rb_method_entry_t *orig_me = me->def->body.refined.orig_me, *new_me;
@@ -1429,10 +2030,15 @@ ensure_origin(VALUE klass)
if (origin == klass) {
origin = class_alloc(T_ICLASS, klass);
RCLASS_SET_M_TBL(origin, RCLASS_M_TBL(klass));
- RCLASS_SET_SUPER(origin, RCLASS_SUPER(klass));
- RCLASS_SET_SUPER(klass, origin);
- RCLASS_SET_ORIGIN(klass, origin);
- RCLASS_M_TBL_INIT(klass);
+ rb_class_set_super(origin, RCLASS_SUPER(klass));
+ rb_class_set_super(klass, origin); // writes origin into RCLASS_SUPER(klass)
+ RCLASS_WRITE_ORIGIN(klass, origin);
+
+ // RCLASS_WRITE_ORIGIN marks origin as an origin, so this is the first
+ // point that it sees M_TBL and may mark it
+ rb_gc_writebarrier_remember(origin);
+
+ class_clear_method_table(klass);
rb_id_table_foreach(RCLASS_M_TBL(origin), cache_clear_refined_method, (void *)klass);
rb_id_table_foreach(RCLASS_M_TBL(origin), move_refined_method, (void *)klass);
return true;
@@ -1457,13 +2063,7 @@ rb_prepend_module(VALUE klass, VALUE module)
rb_vm_check_redefinition_by_prepend(klass);
}
if (RB_TYPE_P(klass, T_MODULE)) {
- rb_subclass_entry_t *iclass = RCLASS_SUBCLASSES(klass);
- // skip the placeholder subclass entry at the head of the list if it exists
- if (iclass) {
- RUBY_ASSERT(!iclass->klass);
- iclass = iclass->next;
- }
-
+ rb_subclass_entry_t *iclass = RCLASS_SUBCLASSES_FIRST(klass);
VALUE klass_origin = RCLASS_ORIGIN(klass);
struct rb_id_table *klass_m_tbl = RCLASS_M_TBL(klass);
struct rb_id_table *klass_origin_m_tbl = RCLASS_M_TBL(klass_origin);
@@ -1475,11 +2075,11 @@ rb_prepend_module(VALUE klass, VALUE module)
if (klass_had_no_origin && klass_origin_m_tbl == RCLASS_M_TBL(subclass)) {
// backfill an origin iclass to handle refinements and future prepends
rb_id_table_foreach(RCLASS_M_TBL(subclass), clear_module_cache_i, (void *)subclass);
- RCLASS_M_TBL(subclass) = klass_m_tbl;
+ RCLASS_WRITE_M_TBL(subclass, klass_m_tbl);
VALUE origin = rb_include_class_new(klass_origin, RCLASS_SUPER(subclass));
- RCLASS_SET_SUPER(subclass, origin);
+ rb_class_set_super(subclass, origin);
RCLASS_SET_INCLUDER(origin, RCLASS_INCLUDER(subclass));
- RCLASS_SET_ORIGIN(subclass, origin);
+ RCLASS_WRITE_ORIGIN(subclass, origin);
RICLASS_SET_ORIGIN_SHARED_MTBL(origin);
}
include_modules_at(subclass, subclass, module, FALSE);
@@ -1555,7 +2155,7 @@ rb_mod_include_p(VALUE mod, VALUE mod2)
Check_Type(mod2, T_MODULE);
for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) {
- if (BUILTIN_TYPE(p) == T_ICLASS && !FL_TEST(p, RICLASS_IS_ORIGIN)) {
+ if (BUILTIN_TYPE(p) == T_ICLASS && !RICLASS_IS_ORIGIN_P(p)) {
if (METACLASS_OF(p) == mod2) return Qtrue;
}
}
@@ -2226,7 +2826,7 @@ rb_special_singleton_class(VALUE obj)
* consistency of the metaclass hierarchy.
*/
static VALUE
-singleton_class_of(VALUE obj)
+singleton_class_of(VALUE obj, bool ensure_eigenclass)
{
VALUE klass;
@@ -2254,13 +2854,26 @@ singleton_class_of(VALUE obj)
}
}
- klass = METACLASS_OF(obj);
- if (!(RCLASS_SINGLETON_P(klass) &&
- RCLASS_ATTACHED_OBJECT(klass) == obj)) {
- klass = rb_make_metaclass(obj, klass);
+ bool needs_lock = rb_multi_ractor_p() && rb_ractor_shareable_p(obj);
+ unsigned int lev;
+ if (needs_lock) {
+ RB_VM_LOCK_ENTER_LEV(&lev);
+ }
+ {
+ klass = METACLASS_OF(obj);
+ if (!(RCLASS_SINGLETON_P(klass) &&
+ RCLASS_ATTACHED_OBJECT(klass) == obj)) {
+ klass = rb_make_metaclass(obj, klass);
+ }
+ RB_FL_SET_RAW(klass, RB_OBJ_FROZEN_RAW(obj));
+ if (ensure_eigenclass && RB_TYPE_P(obj, T_CLASS)) {
+ /* ensures an exposed class belongs to its own eigenclass */
+ (void)ENSURE_EIGENCLASS(klass);
+ }
+ }
+ if (needs_lock) {
+ RB_VM_LOCK_LEAVE_LEV(&lev);
}
-
- RB_FL_SET_RAW(klass, RB_OBJ_FROZEN_RAW(obj));
return klass;
}
@@ -2272,7 +2885,8 @@ rb_freeze_singleton_class(VALUE x)
if (!RCLASS_SINGLETON_P(x)) {
VALUE klass = RBASIC_CLASS(x);
if (klass && // no class when hidden from ObjectSpace
- FL_TEST(klass, (FL_SINGLETON|FL_FREEZE)) == FL_SINGLETON) {
+ FL_TEST_RAW(klass, FL_SINGLETON) &&
+ !OBJ_FROZEN_RAW(klass)) {
OBJ_FREEZE(klass);
}
}
@@ -2302,12 +2916,7 @@ rb_singleton_class_get(VALUE obj)
VALUE
rb_singleton_class(VALUE obj)
{
- VALUE klass = singleton_class_of(obj);
-
- /* ensures an exposed class belongs to its own eigenclass */
- if (RB_TYPE_P(obj, T_CLASS)) (void)ENSURE_EIGENCLASS(klass);
-
- return klass;
+ return singleton_class_of(obj, true);
}
/*!
@@ -2325,7 +2934,7 @@ rb_singleton_class(VALUE obj)
void
rb_define_singleton_method(VALUE obj, const char *name, VALUE (*func)(ANYARGS), int argc)
{
- rb_define_method(singleton_class_of(obj), name, func, argc);
+ rb_define_method(singleton_class_of(obj, false), name, func, argc);
}
#ifdef rb_define_module_function
diff --git a/common.mk b/common.mk
index bf820b228e..8891b65ed9 100644
--- a/common.mk
+++ b/common.mk
@@ -6,7 +6,7 @@ bin: $(PROGRAM) $(WPROGRAM)
lib: $(LIBRUBY)
dll: $(LIBRUBY_SO)
-.SUFFIXES: .rbinc .rb .inc .h .c .y .i .$(ASMEXT) .$(DTRACE_EXT)
+.SUFFIXES: .rbinc .rbbin .rb .inc .h .c .y .i .$(ASMEXT) .$(DTRACE_EXT)
# V=0 quiet, V=1 verbose. other values don't work.
V = 0
@@ -18,9 +18,10 @@ ECHO = @$(ECHO0)
mflags = $(MFLAGS)
gnumake_recursive =
+sequential = $(gnumake:yes=-sequential)
enable_shared = $(ENABLE_SHARED:no=)
-UNICODE_VERSION = 15.0.0
+UNICODE_VERSION = 17.0.0
UNICODE_EMOJI_VERSION_0 = $(UNICODE_VERSION)///
UNICODE_EMOJI_VERSION_1 = $(UNICODE_EMOJI_VERSION_0:.0///=)
UNICODE_EMOJI_VERSION = $(UNICODE_EMOJI_VERSION_1:///=)
@@ -43,10 +44,14 @@ RUBYLIB = $(PATH_SEPARATOR)
RUBYOPT = -
RUN_OPTS = --disable-gems
+GIT_IN_SRC = $(GIT) -C $(srcdir)
+GIT_LOG = $(GIT_IN_SRC) log --no-show-signature
+GIT_LOG_FORMAT = $(GIT_LOG) "--pretty=format:"
+
# GITPULLOPTIONS = --no-tags
PRISM_SRCDIR = $(srcdir)/prism
-INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir) -I$(srcdir) -I$(PRISM_SRCDIR) -I$(UNICODE_HDR_DIR) $(incflags)
+INCFLAGS = -I. -I$(arch_hdrdir) -I$(ext_hdrdir) -I$(hdrdir) -I$(srcdir) -I$(PRISM_SRCDIR) -I$(UNICODE_HDR_DIR) $(incflags)
GEM_HOME =
GEM_PATH =
@@ -70,7 +75,6 @@ HTMLOUT = $(EXTOUT)/html
CAPIOUT = doc/capi
INSTALL_DOC_OPTS = --rdoc-output="$(RDOCOUT)" --html-output="$(HTMLOUT)"
RDOC_GEN_OPTS = --no-force-update \
- --title "Documentation for Ruby $(RUBY_API_VERSION)" \
$(empty)
INITOBJS = dmyext.$(OBJEXT) dmyenc.$(OBJEXT)
@@ -106,19 +110,21 @@ PRISM_FILES = prism/api_node.$(OBJEXT) \
prism/util/pm_memchr.$(OBJEXT) \
prism/util/pm_newline_list.$(OBJEXT) \
prism/util/pm_string.$(OBJEXT) \
- prism/util/pm_string_list.$(OBJEXT) \
prism/util/pm_strncasecmp.$(OBJEXT) \
prism/util/pm_strpbrk.$(OBJEXT) \
prism/prism.$(OBJEXT) \
prism_init.$(OBJEXT)
-COMMONOBJS = array.$(OBJEXT) \
+COMMONOBJS = \
+ array.$(OBJEXT) \
ast.$(OBJEXT) \
bignum.$(OBJEXT) \
+ box.$(OBJEXT) \
class.$(OBJEXT) \
compar.$(OBJEXT) \
compile.$(OBJEXT) \
complex.$(OBJEXT) \
+ concurrent_set.$(OBJEXT) \
cont.$(OBJEXT) \
debug.$(OBJEXT) \
debug_counter.$(OBJEXT) \
@@ -132,8 +138,8 @@ COMMONOBJS = array.$(OBJEXT) \
file.$(OBJEXT) \
gc.$(OBJEXT) \
hash.$(OBJEXT) \
- inits.$(OBJEXT) \
imemo.$(OBJEXT) \
+ inits.$(OBJEXT) \
io.$(OBJEXT) \
io_buffer.$(OBJEXT) \
iseq.$(OBJEXT) \
@@ -141,13 +147,12 @@ COMMONOBJS = array.$(OBJEXT) \
marshal.$(OBJEXT) \
math.$(OBJEXT) \
memory_view.$(OBJEXT) \
- rjit.$(OBJEXT) \
- rjit_c.$(OBJEXT) \
node.$(OBJEXT) \
node_dump.$(OBJEXT) \
numeric.$(OBJEXT) \
object.$(OBJEXT) \
pack.$(OBJEXT) \
+ pathname.$(OBJEXT) \
parse.$(OBJEXT) \
parser_st.$(OBJEXT) \
proc.$(OBJEXT) \
@@ -166,6 +171,7 @@ COMMONOBJS = array.$(OBJEXT) \
ruby.$(OBJEXT) \
ruby_parser.$(OBJEXT) \
scheduler.$(OBJEXT) \
+ set.$(OBJEXT) \
shape.$(OBJEXT) \
signal.$(OBJEXT) \
sprintf.$(OBJEXT) \
@@ -188,7 +194,9 @@ COMMONOBJS = array.$(OBJEXT) \
weakmap.$(OBJEXT) \
$(PRISM_FILES) \
$(YJIT_OBJ) \
- $(YJIT_LIBOBJ) \
+ $(ZJIT_OBJ) \
+ $(JIT_OBJ) \
+ $(RUST_LIBOBJ) \
$(COROUTINE_OBJ) \
$(DTRACE_OBJ) \
$(BUILTIN_ENCOBJS) \
@@ -201,83 +209,6 @@ $(PRISM_BUILD_DIR)/.time $(PRISM_BUILD_DIR)/util/.time:
$(Q) $(MAKEDIRS) $(@D)
@$(NULLCMD) > $@
-main: $(srcdir)/lib/prism/compiler.rb
-srcs: $(srcdir)/lib/prism/compiler.rb
-$(srcdir)/lib/prism/compiler.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/compiler.rb.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/compiler.rb $(srcdir)/lib/prism/compiler.rb
-
-main: $(srcdir)/lib/prism/dispatcher.rb
-srcs: $(srcdir)/lib/prism/dispatcher.rb
-$(srcdir)/lib/prism/dispatcher.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/dispatcher.rb.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/dispatcher.rb $(srcdir)/lib/prism/dispatcher.rb
-
-main: $(srcdir)/lib/prism/dsl.rb
-srcs: $(srcdir)/lib/prism/dsl.rb
-$(srcdir)/lib/prism/dsl.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/dsl.rb.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/dsl.rb $(srcdir)/lib/prism/dsl.rb
-
-main: $(srcdir)/lib/prism/inspect_visitor.rb
-srcs: $(srcdir)/lib/prism/inspect_visitor.rb
-$(srcdir)/lib/prism/inspect_visitor.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/inspect_visitor.rb.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/inspect_visitor.rb $(srcdir)/lib/prism/inspect_visitor.rb
-
-main: $(srcdir)/lib/prism/mutation_compiler.rb
-srcs: $(srcdir)/lib/prism/mutation_compiler.rb
-$(srcdir)/lib/prism/mutation_compiler.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/mutation_compiler.rb.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/mutation_compiler.rb $(srcdir)/lib/prism/mutation_compiler.rb
-
-main: $(srcdir)/lib/prism/node.rb
-srcs: $(srcdir)/lib/prism/node.rb
-$(srcdir)/lib/prism/node.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/node.rb.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/node.rb $(srcdir)/lib/prism/node.rb
-
-main: $(srcdir)/lib/prism/reflection.rb
-srcs: $(srcdir)/lib/prism/reflection.rb
-$(srcdir)/lib/prism/reflection.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/reflection.rb.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/reflection.rb $(srcdir)/lib/prism/reflection.rb
-
-main: $(srcdir)/lib/prism/serialize.rb
-srcs: $(srcdir)/lib/prism/serialize.rb
-$(srcdir)/lib/prism/serialize.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/serialize.rb.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/serialize.rb $(srcdir)/lib/prism/serialize.rb
-
-main: $(srcdir)/lib/prism/visitor.rb
-srcs: $(srcdir)/lib/prism/visitor.rb
-$(srcdir)/lib/prism/visitor.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/visitor.rb.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/visitor.rb $(srcdir)/lib/prism/visitor.rb
-
-srcs: prism/api_node.c
-prism/api_node.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/ext/prism/api_node.c.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb ext/prism/api_node.c $@
-
-srcs: prism/ast.h
-prism/ast.h: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/include/prism/ast.h.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb include/prism/ast.h $@
-
-srcs: prism/diagnostic.c
-prism/diagnostic.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/src/diagnostic.c.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb src/diagnostic.c $@
-
-srcs: prism/diagnostic.h
-prism/diagnostic.h: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/include/prism/diagnostic.h.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb include/prism/diagnostic.h $@
-
-srcs: prism/node.c
-prism/node.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/src/node.c.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb src/node.c $@
-
-srcs: prism/prettyprint.c
-prism/prettyprint.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/src/prettyprint.c.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb src/prettyprint.c $@
-
-srcs: prism/serialize.c
-prism/serialize.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/src/serialize.c.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb src/serialize.c $@
-
-srcs: prism/token_type.c
-prism/token_type.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/src/token_type.c.erb
- $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb src/token_type.c $@
-
EXPORTOBJS = $(DLNOBJ) \
localeinit.$(OBJEXT) \
loadpath.$(OBJEXT) \
@@ -292,7 +223,7 @@ DEFAULT_PRELUDES = $(GEM_PRELUDE)
PRELUDE_SCRIPTS = $(DEFAULT_PRELUDES)
GEM_PRELUDE =
PRELUDES = {$(srcdir)}miniprelude.c
-GOLFPRELUDES = {$(srcdir)}golf_prelude.c
+GOLFPRELUDES = golf_prelude.rbbin
SCRIPT_ARGS = --dest-dir="$(DESTDIR)" \
--extout="$(EXTOUT)" \
@@ -337,30 +268,24 @@ MAKE_LINK = $(MINIRUBY) -rfileutils -e "include FileUtils::Verbose" \
# For release builds
YJIT_RUSTC_ARGS = --crate-name=yjit \
- --crate-type=staticlib \
+ $(JIT_RUST_FLAGS) \
+ $(RUSTC_FLAGS) \
--edition=2021 \
- -g \
- -C lto=thin \
- -C opt-level=3 \
- -C overflow-checks=on \
'--out-dir=$(CARGO_TARGET_DIR)/release/' \
- $(top_srcdir)/yjit/src/lib.rs
+ '$(top_srcdir)/yjit/src/lib.rs'
+
+ZJIT_RUSTC_ARGS = --crate-name=zjit \
+ $(JIT_RUST_FLAGS) \
+ $(RUSTC_FLAGS) \
+ --edition=2024 \
+ '--out-dir=$(CARGO_TARGET_DIR)/release/' \
+ '$(top_srcdir)/zjit/src/lib.rs'
all: $(SHOWFLAGS) main
main: $(SHOWFLAGS) exts $(ENCSTATIC:static=lib)encs
@$(NULLCMD)
-main: $(srcdir)/lib/ruby_vm/rjit/instruction.rb
-srcs: $(srcdir)/lib/ruby_vm/rjit/instruction.rb
-$(srcdir)/lib/ruby_vm/rjit/instruction.rb: $(tooldir)/insns2vm.rb $(tooldir)/ruby_vm/views/lib/ruby_vm/rjit/instruction.rb.erb $(srcdir)/insns.def
- $(ECHO) generating $@
- $(Q) $(BASERUBY) -Ku $(tooldir)/insns2vm.rb --basedir="$(srcdir)" $(INSNS2VMOPT) $@
-
-.PHONY: rjit-bindgen
-rjit-bindgen:
- $(Q) $(BASERUBY) -rrubygems -C $(srcdir)/tool/rjit bindgen.rb $(CURDIR)
-
.PHONY: showflags
exts enc trans: $(SHOWFLAGS)
showflags:
@@ -380,6 +305,7 @@ showflags:
" MFLAGS = $(MFLAGS)" \
" RUSTC = $(RUSTC)" \
" YJIT_RUSTC_ARGS = $(YJIT_RUSTC_ARGS)" \
+ " ZJIT_RUSTC_ARGS = $(ZJIT_RUSTC_ARGS)" \
$(MESSAGE_END)
-@$(CC_VERSION)
@@ -488,17 +414,19 @@ docs: srcs-doc $(DOCTARGETS)
pkgconfig-data: $(ruby_pc)
$(ruby_pc): $(srcdir)/template/ruby.pc.in config.status
+INSTALL_ALL = all
+
install-all: pre-install-all do-install-all post-install-all
pre-install-all:: all pre-install-local pre-install-ext pre-install-gem pre-install-doc
do-install-all: pre-install-all $(DOT_WAIT) docs
- $(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --install=all $(INSTALL_DOC_OPTS)
+ $(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --install=$(INSTALL_ALL) $(INSTALL_DOC_OPTS)
post-install-all:: post-install-local post-install-ext post-install-gem post-install-doc
@$(NULLCMD)
install-nodoc: pre-install-nodoc do-install-nodoc post-install-nodoc
pre-install-nodoc:: pre-install-local pre-install-ext pre-install-gem
do-install-nodoc: main pre-install-nodoc
- $(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --install=all --exclude=doc
+ $(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --install=$(INSTALL_ALL) --exclude=doc
post-install-nodoc:: post-install-local post-install-ext post-install-gem
install-local: pre-install-local do-install-local post-install-local
@@ -573,7 +501,7 @@ what-where-all: no-install-all
no-install-all: pre-no-install-all dont-install-all post-no-install-all
pre-no-install-all:: pre-no-install-local pre-no-install-ext pre-no-install-doc
dont-install-all: $(PROGRAM)
- $(INSTRUBY) -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=all $(INSTALL_DOC_OPTS)
+ $(INSTRUBY) -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=$(INSTALL_ALL) $(INSTALL_DOC_OPTS)
post-no-install-all:: post-no-install-local post-no-install-ext post-no-install-doc
@$(NULLCMD)
@@ -678,6 +606,8 @@ do-install-dbg: $(PROGRAM) pre-install-dbg
post-install-dbg::
@$(NULLCMD)
+srcs-doc: prepare-gems
+
rdoc: PHONY main srcs-doc
@echo Generating RDoc documentation
$(Q) $(RDOC) --ri --op "$(RDOCOUT)" $(RDOC_GEN_OPTS) $(RDOCFLAGS) .
@@ -686,15 +616,20 @@ html: PHONY main srcs-doc
@echo Generating RDoc HTML files
$(Q) $(RDOC) --op "$(HTMLOUT)" $(RDOC_GEN_OPTS) $(RDOCFLAGS) .
+RDOC_COVERAGE_EXCLUDES = -x ^ext/json -x ^ext/openssl -x ^ext/psych \
+ -x ^lib/bundler -x ^lib/rubygems \
+ -x ^lib/did_you_mean -x ^lib/error_highlight -x ^lib/syntax_suggest
+
rdoc-coverage: PHONY main srcs-doc
@echo Generating RDoc coverage report
- $(Q) $(RDOC) --quiet -C $(RDOCFLAGS) "$(srcdir)"
+ $(Q) $(RDOC) --quiet -C $(RDOCFLAGS) $(RDOC_COVERAGE_EXCLUDES) .
undocumented: PHONY main srcs-doc
- $(Q) $(RDOC) --quiet -C $(RDOCFLAGS) "$(srcdir)" | \
+ $(Q) $(RDOC) --quiet -C $(RDOCFLAGS) $(RDOC_COVERAGE_EXCLUDES) . | \
sed -n \
-e '/^ *# in file /{' -e 's///;N;s/\n/: /p' -e '}' \
- -e 's/^ *\(.*[^ ]\) *# in file \(.*\)/\2: \1/p'
+ -e 's/^ *\(.*[^ ]\) *# in file \(.*\)/\2: \1/p' | \
+ sort -t: -k1,1 -k2n,2
RDOCBENCHOUT=/tmp/rdocbench
@@ -723,16 +658,16 @@ install-prereq: $(CLEAR_INSTALLED_LIST) yes-fake sudo-precheck PHONY
clear-installed-list: PHONY
@> $(INSTALLED_LIST) set MAKE="$(MAKE)"
-clean: clean-ext clean-enc clean-golf clean-docs clean-extout clean-local clean-platform clean-spec
+clean: clean-ext clean-enc clean-golf clean-docs clean-extout clean-modular-gc clean-local clean-platform clean-spec
clean-local:: clean-runnable
$(Q)$(RM) $(ALLOBJS) $(LIBRUBY_A) $(LIBRUBY_SO) $(LIBRUBY) $(LIBRUBY_ALIASES)
$(Q)$(RM) $(PROGRAM) $(WPROGRAM) miniruby$(EXEEXT) dmyext.$(OBJEXT) dmyenc.$(OBJEXT) $(ARCHFILE) .*.time
$(Q)$(RM) y.tab.c y.output encdb.h transdb.h config.log rbconfig.rb $(ruby_pc) $(COROUTINE_H:/Context.h=/.time)
$(Q)$(RM) probes.h probes.$(OBJEXT) probes.stamp ruby-glommed.$(OBJEXT) ruby.imp ChangeLog $(STATIC_RUBY)$(EXEEXT)
- $(Q)$(RM) GNUmakefile.old Makefile.old $(arch)-fake.rb bisect.sh $(ENC_TRANS_D) builtin_binary.inc
+ $(Q)$(RM) GNUmakefile.old Makefile.old $(arch)-fake.rb bisect.sh $(ENC_TRANS_D) builtin_binary.rbbin
$(Q)$(RM) $(PRISM_BUILD_DIR)/.time $(PRISM_BUILD_DIR)/*/.time yjit_exit_locations.dump
- -$(Q)$(RMALL) yjit/target
- -$(Q) $(RMDIR) enc/jis enc/trans enc $(COROUTINE_H:/Context.h=) coroutine yjit \
+ -$(Q)$(RMALL) target
+ -$(Q) $(RMDIR) enc/jis enc/trans enc $(COROUTINE_H:/Context.h=) coroutine target \
$(PRISM_BUILD_DIR)/*/ $(PRISM_BUILD_DIR) tmp \
2> $(NULL) || $(NULLCMD)
@@ -757,13 +692,14 @@ clean-docs: clean-rdoc clean-html clean-capi
clean-spec: PHONY
clean-rubyspec: clean-spec
-distclean: distclean-ext distclean-enc distclean-golf distclean-docs distclean-extout distclean-local distclean-platform distclean-spec
+distclean: distclean-ext distclean-enc distclean-golf distclean-docs distclean-extout distclean-modular-gc distclean-local distclean-platform distclean-spec
distclean-local:: clean-local
- $(Q)$(RM) $(MKFILES) yasmdata.rb *.inc $(PRELUDES) *.rbinc
+ $(Q)$(RM) $(MKFILES) *.inc $(PRELUDES) *.rbinc *.rbbin
$(Q)$(RM) config.cache config.status config.status.lineno
$(Q)$(RM) *~ *.bak *.stackdump core *.core gmon.out $(PREP)
-$(Q)$(RMALL) $(srcdir)/autom4te.cache
-distclean-ext:: PHONY
+distclean-local:: distclean-srcs-local
+distclean-ext:: distclean-srcs-ext
distclean-golf: clean-golf
distclean-rdoc: clean-rdoc
distclean-html: clean-html
@@ -778,6 +714,7 @@ realclean:: realclean-ext realclean-local realclean-enc realclean-golf realclean
realclean-local:: distclean-local realclean-srcs-local
clean-srcs:: clean-srcs-local clean-srcs-ext
+distclean-srcs:: distclean-srcs-local distclean-srcs-ext
realclean-srcs:: realclean-srcs-local realclean-srcs-ext
clean-srcs-local::
@@ -785,14 +722,18 @@ clean-srcs-local::
$(Q)$(RM) id.c id.h probes.dmyh probes.h
$(Q)$(RM) encdb.h transdb.h verconf.h ruby-runner.h
-realclean-srcs-local:: clean-srcs-local
+distclean-srcs-local:: clean-srcs-local
+
+realclean-srcs-local:: distclean-srcs-local
$(Q)$(CHDIR) $(srcdir) && $(RM) \
parse.c parse.h lex.c enc/trans/newline.c $(PRELUDES) revision.h \
- id.c id.h probes.dmyh configure aclocal.m4 tool/config.guess tool/config.sub gems/*.gem \
+ id.c id.h probes.dmyh configure aclocal.m4 tool/config.guess tool/config.sub \
+ $(PRISM_SRCDIR)/srcs.mk gems/*.gem \
|| $(NULLCMD)
clean-srcs-ext::
-realclean-srcs-ext:: clean-srcs-ext
+distclean-srcs-ext:: clean-srcs-ext
+realclean-srcs-ext:: distclean-srcs-ext
realclean-ext:: PHONY
realclean-golf: distclean-golf
@@ -852,9 +793,16 @@ clean-capi distclean-capi realclean-capi:
clean-platform distclean-platform realclean-platform:
$(Q) $(RM) $(PLATFORM_D)
- -$(Q) $(RMDIR) $(PLATFORM_DIR) 2> $(NULL) || $(NULLCMD)
+ -$(Q) $(RMDIR) $(PLATFORM_DIR) $(TIMESTAMPDIR) 2> $(NULL) || $(NULLCMD)
RUBYSPEC_CAPIEXT = spec/ruby/optional/capi/ext
+RUBYSPEC_CAPIEXT_SRCDIR = $(srcdir)/$(RUBYSPEC_CAPIEXT)
+RUBYSPEC_CAPIEXT_DEPS = $(RUBYSPEC_CAPIEXT_SRCDIR)/rubyspec.h $(RUBY_H_INCLUDES) {$(VPATH)}internal/abi.h $(LIBRUBY)
+RUBYSPEC_CAPIEXT_BUILD = $(enable_shared:yes=rubyspec-capiext)
+
+rubyspec-capiext: build-ext $(DOT_WAIT)
+# make-dependent rules should be included after this and built after build-ext.
+
clean-spec: PHONY
-$(Q) $(RM) $(RUBYSPEC_CAPIEXT)/*.$(OBJEXT) $(RUBYSPEC_CAPIEXT)/*.$(DLEXT)
-$(Q) $(RMDIRS) $(RUBYSPEC_CAPIEXT) 2> $(NULL) || $(NULLCMD)
@@ -942,7 +890,7 @@ no-test-testframework: PHONY
test-tool: $(TEST_RUNNABLE)-test-tool
yes-test-tool: prog PHONY
$(ACTIONS_GROUP)
- $(gnumake_recursive)$(Q)$(exec) $(RUNRUBY) "$(TOOL_TESTSDIR)/runner.rb" --ruby="$(RUNRUBY)" $(TESTOPTS)
+ $(gnumake_recursive)$(Q)$(exec) $(RUNRUBY) "$(TOOL_TESTSDIR)/runner.rb" --ruby="$(RUNRUBY)" $(TESTOPTS) $(TESTS)
$(ACTIONS_ENDGROUP)
no-test-tool: PHONY
@@ -952,7 +900,7 @@ test: test-short
# Separate to skip updating encs and exts by `make -o test-precheck`
# for GNU make.
-test-precheck: $(ENCSTATIC:static=lib)encs exts PHONY $(DOT_WAIT)
+test-precheck: $(ENCSTATIC:static=lib)encs $(RUBYSPEC_CAPIEXT_BUILD) exts PHONY $(DOT_WAIT)
yes-test-all-precheck: programs $(DOT_WAIT) test-precheck
PRECHECK_TEST_ALL = yes-test-all-precheck
@@ -1021,10 +969,18 @@ no-test-spec:
check: $(DOT_WAIT) test-spec
RUNNABLE = $(LIBRUBY_RELATIVE:no=un)-runnable
-runnable: $(RUNNABLE) prog $(tooldir)/mkrunnable.rb PHONY
+runnable: $(RUNNABLE)
+runnable-golf: golf
+runnable $(enable_shared:yes=runnable-golf): prog $(tooldir)/mkrunnable.rb PHONY
$(Q) $(MINIRUBY) $(tooldir)/mkrunnable.rb -v $(EXTOUT)
yes-runnable: PHONY
+hello: $(TEST_RUNNABLE)-hello
+yes-hello: runnable-golf
+ ./$(enable_shared:yes=bin/)$(GORUBY) -veh
+no-hello: runnable-golf
+ $(ECHO) Run ./$(enable_shared:yes=bin/)$(GORUBY) -veh
+
encs: enc trans
libencs: libenc libtrans
encs enc trans libencs libenc libtrans: $(SHOWFLAGS) $(ENC_MK) $(LIBRUBY) $(PREP) PHONY
@@ -1049,8 +1005,11 @@ $(ENC_MK): $(srcdir)/enc/make_encmake.rb $(srcdir)/enc/Makefile.in $(srcdir)/enc
.PHONY: test install install-nodoc install-doc dist
.PHONY: loadpath golf capi rdoc install-prereq clear-installed-list
.PHONY: clean clean-ext clean-local clean-enc clean-golf clean-rdoc clean-html clean-extout
+.PHONY: clean-srcs clean-srcs-local clean-srcs-ext
.PHONY: distclean distclean-ext distclean-local distclean-enc distclean-golf distclean-extout
+.PHONY: distclean-srcs distclean-srcs-local distclean-srcs-ext
.PHONY: realclean realclean-ext realclean-local realclean-enc realclean-golf realclean-extout
+.PHONY: realclean-srcs realclean-srcs-local realclean-srcs-ext
.PHONY: exam check test test-short test-all btest btest-ruby test-basic test-knownbug
.PHONY: run runruby parse benchmark gdb gdb-ruby
.PHONY: update-mspec update-rubyspec test-rubyspec test-spec
@@ -1064,7 +1023,7 @@ PHONY:
{$(srcdir)}.y.c:
$(ECHO) generating $@
$(Q)$(BASERUBY) $(tooldir)/id2token.rb $(SRC_FILE) | \
- $(YACC) $(YFLAGS) -o$@ -H$*.h - parse.y
+ $(LRAMA) $(YFLAGS) -o$@ -H$*.h - parse.y
$(PLATFORM_D):
$(Q) $(MAKEDIRS) $(PLATFORM_DIR) $(@D)
@@ -1186,10 +1145,11 @@ $(srcs_vpath)insns_info.inc: $(tooldir)/ruby_vm/views/insns_info.inc.erb $(inc_c
$(tooldir)/ruby_vm/views/_insn_type_chars.erb $(tooldir)/ruby_vm/views/_insn_name_info.erb \
$(tooldir)/ruby_vm/views/_insn_len_info.erb $(tooldir)/ruby_vm/views/_insn_operand_info.erb \
$(tooldir)/ruby_vm/views/_attributes.erb $(tooldir)/ruby_vm/views/_comptime_insn_stack_increase.erb \
- $(tooldir)/ruby_vm/views/_insn_sp_pc_dependency.erb
+ $(tooldir)/ruby_vm/views/_zjit_helpers.erb $(tooldir)/ruby_vm/views/_insn_leaf_info.erb
$(srcs_vpath)vmtc.inc: $(tooldir)/ruby_vm/views/vmtc.inc.erb $(inc_common_headers)
$(srcs_vpath)vm.inc: $(tooldir)/ruby_vm/views/vm.inc.erb $(inc_common_headers) \
- $(tooldir)/ruby_vm/views/_insn_entry.erb $(tooldir)/ruby_vm/views/_trace_instruction.erb
+ $(tooldir)/ruby_vm/views/_insn_entry.erb $(tooldir)/ruby_vm/views/_trace_instruction.erb \
+ $(tooldir)/ruby_vm/views/_zjit_instruction.erb
BUILTIN_RB_SRCS = \
$(srcdir)/ast.rb \
@@ -1198,13 +1158,13 @@ BUILTIN_RB_SRCS = \
$(srcdir)/numeric.rb \
$(srcdir)/io.rb \
$(srcdir)/marshal.rb \
- $(srcdir)/rjit.rb \
- $(srcdir)/rjit_c.rb \
$(srcdir)/pack.rb \
$(srcdir)/trace_point.rb \
$(srcdir)/warning.rb \
$(srcdir)/array.rb \
+ $(srcdir)/hash.rb \
$(srcdir)/kernel.rb \
+ $(srcdir)/pathname_builtin.rb \
$(srcdir)/ractor.rb \
$(srcdir)/symbol.rb \
$(srcdir)/timev.rb \
@@ -1212,7 +1172,10 @@ BUILTIN_RB_SRCS = \
$(srcdir)/nilclass.rb \
$(srcdir)/prelude.rb \
$(srcdir)/gem_prelude.rb \
+ $(srcdir)/jit_hook.rb \
+ $(srcdir)/jit_undef.rb \
$(srcdir)/yjit.rb \
+ $(srcdir)/zjit.rb \
$(empty)
BUILTIN_RB_INCS = $(BUILTIN_RB_SRCS:.rb=.rbinc)
@@ -1242,7 +1205,7 @@ srcs-ext: $(EXT_SRCS)
realclean-srcs-ext::
$(Q)$(RM) $(EXT_SRCS)
-EXTRA_SRCS = $(srcdir)/ext/json/parser/parser.c \
+EXTRA_SRCS = \
$(srcdir)/ext/date/zonetab.h \
$(empty)
@@ -1258,7 +1221,7 @@ srcs-enc: $(ENC_MK)
$(ECHO) making srcs under enc
$(Q) $(MAKE) $(MAKE_ENC) srcs
-all-incs: incs {$(VPATH)}encdb.h {$(VPATH)}transdb.h
+all-incs: incs {$(VPATH)}encdb.h {$(VPATH)}transdb.h {$(VPATH)}probes.h
incs: $(INSNS) {$(VPATH)}node_name.inc {$(VPATH)}known_errors.inc \
{$(VPATH)}vm_call_iseq_optimized.inc $(srcdir)/revision.h \
$(REVISION_H) \
@@ -1304,10 +1267,7 @@ $(MINIPRELUDE_C): $(COMPILE_PRELUDE) $(BUILTIN_RB_SRCS)
$(Q) $(BASERUBY) $(tooldir)/generic_erb.rb -I$(srcdir) -o $@ \
$(srcdir)/template/prelude.c.tmpl $(BUILTIN_RB_SRCS)
-$(GOLF_PRELUDE_C): $(COMPILE_PRELUDE) {$(srcdir)}golf_prelude.rb
- $(ECHO) generating $@
- $(Q) $(BASERUBY) $(tooldir)/generic_erb.rb -I$(srcdir) -c -o $@ \
- $(srcdir)/template/prelude.c.tmpl golf_prelude.rb
+golf_prelude.rbbin: {$(srcdir)}golf_prelude.rb $(tooldir)/mk_rbbin.rb $(PREP)
MAINCPPFLAGS = $(ENABLE_DEBUG_ENV:yes=-DRUBY_DEBUG_ENV=1)
@@ -1325,18 +1285,21 @@ probes.h: {$(VPATH)}probes.$(DTRACE_EXT)
prereq: incs srcs preludes PHONY
preludes: {$(VPATH)}miniprelude.c
-preludes: {$(srcdir)}golf_prelude.c
+
+{$(srcdir)}.rb.rbbin:
+ $(ECHO) making $@
+ $(Q) $(MINIRUBY) $(tooldir)/mk_rbbin.rb $(SRC_FILE) > $(OS_DEST_FILE)
{$(srcdir)}.rb.rbinc:
$(ECHO) making $@
- $(Q) $(BASERUBY) $(tooldir)/mk_builtin_loader.rb $<
+ $(Q) $(BASERUBY) $(tooldir)/mk_builtin_loader.rb $(SRC_FILE)
-$(BUILTIN_BINARY:yes=built)in_binary.inc: $(PREP) $(BUILTIN_RB_SRCS) $(srcdir)/template/builtin_binary.inc.tmpl
+$(BUILTIN_BINARY:yes=built)in_binary.rbbin: $(PREP) $(BUILTIN_RB_SRCS) $(srcdir)/template/builtin_binary.rbbin.tmpl
$(Q) $(MINIRUBY) $(tooldir)/generic_erb.rb -o $@ \
- $(srcdir)/template/builtin_binary.inc.tmpl
+ $(srcdir)/template/builtin_binary.rbbin.tmpl
-$(Q) sha256sum $@ 2> $(NULL) || $(NULLCMD)
-$(BUILTIN_BINARY:no=builtin)_binary.inc:
+$(BUILTIN_BINARY:no=builtin)_binary.rbbin:
$(Q) echo> $@ // empty $(@F)
$(BUILTIN_RB_INCS): $(top_srcdir)/tool/mk_builtin_loader.rb
@@ -1351,9 +1314,15 @@ $(REVISION_H)$(yes_baseruby:yes=~disabled~):
# uncommon.mk: $(REVISION_H)
# $(MKFILES): $(REVISION_H)
+# $(common_mk_includes) is set by config.status or GNUmakefile
+common_mk__$(gnumake:yes=artifact)_ = uncommon.mk
+common_mk_$(gnumake)_artifact_ = $(MKFILES)
+$(common_mk__artifact_): $(srcdir)/common.mk $(common_mk_includes)
+
ripper_srcs: $(RIPPER_SRCS)
$(RIPPER_SRCS): $(srcdir)/parse.y $(srcdir)/defs/id.def
+$(RIPPER_SRCS): $(srcdir)/ext/ripper/depend $(srcdir)/ext/ripper/extconf.rb
$(RIPPER_SRCS): $(srcdir)/ext/ripper/tools/preproc.rb $(srcdir)/ext/ripper/tools/dsl.rb
$(RIPPER_SRCS): $(srcdir)/ext/ripper/ripper_init.c.tmpl $(srcdir)/ext/ripper/eventids2.c
$(ECHO) generating $@
@@ -1363,11 +1332,6 @@ $(RIPPER_SRCS): $(srcdir)/ext/ripper/ripper_init.c.tmpl $(srcdir)/ext/ripper/eve
Q=$(Q) ECHO=$(ECHO) RM="$(RM1)" top_srcdir=../.. srcdir=. VPATH=../.. \
RUBY="$(BASERUBY)" BASERUBY="$(BASERUBY)" PATH_SEPARATOR="$(PATH_SEPARATOR)" LANG=C
-$(srcdir)/ext/json/parser/parser.c: $(srcdir)/ext/json/parser/parser.rl $(srcdir)/ext/json/parser/prereq.mk
- $(ECHO) generating $@
- $(Q) $(CHDIR) $(@D) && $(exec) $(MAKE) -f prereq.mk $(mflags) \
- Q=$(Q) ECHO=$(ECHO) top_srcdir=../../.. srcdir=. VPATH=../../.. BASERUBY="$(BASERUBY)"
-
$(srcdir)/ext/date/zonetab.h: $(srcdir)/ext/date/zonetab.list $(srcdir)/ext/date/prereq.mk
$(ECHO) generating $@
$(Q) $(CHDIR) $(@D) && $(exec) $(MAKE) -f prereq.mk $(mflags) \
@@ -1409,8 +1373,8 @@ run: yes-fake miniruby$(EXEEXT) PHONY
runruby: $(PROGRAM) PHONY
RUBY_ON_BUG='gdb -x $(srcdir)/.gdbinit -p' $(RUNRUBY) $(RUNOPT0) $(TESTRUN_SCRIPT) $(RUNOPT)
-runirb: $(PROGRAM) PHONY
- RUBY_ON_BUG='gdb -x $(srcdir)/.gdbinit -p' $(RUNRUBY) $(RUNOPT0) -r irb -e 'IRB.start("make runirb")' $(RUNOPT)
+runirb: $(PROGRAM) update-default-gemspecs
+ RUBY_ON_BUG='gdb -x $(srcdir)/.gdbinit -p' $(RUNRUBY) $(RUNOPT0) -rrubygems -r irb -e 'IRB.start("make runirb")' $(RUNOPT)
parse: yes-fake miniruby$(EXEEXT) PHONY
$(BTESTRUBY) --dump=parsetree_with_comment,insns $(TESTRUN_SCRIPT)
@@ -1509,15 +1473,21 @@ update-coverage: main PHONY
--install-dir .bundle --conservative "simplecov"
refresh-gems: update-bundled_gems prepare-gems
+# can't recall exactly, but `make` somewhere (not GNU or nmake)
+# couldn't handle spaces in replacement strings; i.e.,
+# `$(HAVE_BASERUBY:yes=word word ...)` didn't work.
prepare-gems: $(HAVE_BASERUBY:yes=update-gems) $(HAVE_BASERUBY:yes=extract-gems)
-extract-gems: $(HAVE_BASERUBY:yes=update-gems)
+extract-gems: $(HAVE_BASERUBY:yes=update-gems) $(HAVE_BASERUBY:yes=outdate-bundled-gems)
+update-gems: $(HAVE_BASERUBY:yes=outdate-bundled-gems)
-update-gems$(gnumake:yes=-sequential): PHONY
+split_option = -F"\s+|$(HASH_SIGN).*"
+
+update-gems$(sequential): PHONY
$(ECHO) Downloading bundled gem files...
$(Q) $(BASERUBY) -C "$(srcdir)" \
- -I./tool -rdownloader -answ \
+ -I./tool -rdownloader $(split_option) -answ \
-e 'gem, ver = *$$F' \
- -e 'next if !ver or /^#/=~gem' \
+ -e 'next if !ver' \
-e 'old = Dir.glob("gems/#{gem}-*.gem")' \
-e 'gem = "#{gem}-#{ver}.gem"' \
-e 'Downloader::RubyGems.download(gem, "gems", nil) and' \
@@ -1526,13 +1496,13 @@ update-gems$(gnumake:yes=-sequential): PHONY
-e 'FileUtils.rm_rf(old.map{'"|n|"'n.chomp(".gem")})' \
gems/bundled_gems
-extract-gems$(gnumake:yes=-sequential): PHONY
+extract-gems$(sequential): PHONY
$(ECHO) Extracting bundled gem files...
$(Q) $(BASERUBY) -C "$(srcdir)" \
- -Itool/lib -rfileutils -rbundled_gem -answ \
+ -Itool/lib -rfileutils -rbundled_gem $(split_option) -answ \
-e 'BEGIN {d = ".bundle/gems"}' \
-e 'gem, ver, _, rev = *$$F' \
- -e 'next if !ver or /^#/=~gem' \
+ -e 'next if !ver' \
-e 'g = "#{gem}-#{ver}"' \
-e 'unless File.directory?("#{d}/#{g}")' \
-e 'if rev and File.exist?(gs = "gems/src/#{gem}/#{gem}.gemspec")' \
@@ -1542,20 +1512,9 @@ extract-gems$(gnumake:yes=-sequential): PHONY
-e 'end' \
gems/bundled_gems
-extract-gems$(gnumake:yes=-sequential): $(HAVE_GIT:yes=clone-bundled-gems-src)
-
-clone-bundled-gems-src: PHONY
- $(Q) $(BASERUBY) -C "$(srcdir)" \
- -Itool/lib -rbundled_gem -answ \
- -e 'BEGIN {git = $$git}' \
- -e 'gem, _, repo, rev = *$$F' \
- -e 'next if !rev or /^#/=~gem' \
- -e 'gemdir = "gems/src/#{gem}"' \
- -e 'BundledGem.checkout(gemdir, repo, rev, git: git)' \
- -e 'BundledGem.dummy_gemspec("#{gemdir}/#{gem}.gemspec")' \
- -- -git="$(GIT)" \
- gems/bundled_gems
+extract-gems$(sequential): $(HAVE_GIT:yes=clone-bundled-gems-src)
+flush-gems: outdate-bundled-gems
outdate-bundled-gems: PHONY
$(Q) $(BASERUBY) $(tooldir)/$@.rb --make="$(MAKE)" --mflags="$(MFLAGS)" \
--ruby-platform=$(arch) --ruby-version=$(ruby_version) \
@@ -1566,35 +1525,71 @@ update-bundled_gems: PHONY
$(tooldir)/update-bundled_gems.rb \
"$(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
+ $(GIT_IN_SRC) diff --no-ext-diff --ignore-submodules --exit-code || \
+ $(GIT_IN_SRC) commit -m "Update bundled_gems" gems/bundled_gems
-PRECHECK_BUNDLED_GEMS = test-bundled-gems-precheck
+PRECHECK_BUNDLED_GEMS = yes
test-bundled-gems-precheck: $(TEST_RUNNABLE)-test-bundled-gems-precheck
-yes-test-bundled-gems-precheck: main
+yes-test-bundled-gems-precheck: $(PRECHECK_BUNDLED_GEMS:yes=main)
no-test-bundled-gems-precheck:
+update-default-gemspecs: $(TEST_RUNNABLE)-update-default-gemspecs
+no-update-default-gemspecs:
+yes-update-default-gemspecs: $(PRECHECK_BUNDLED_GEMS:yes=main)
+ @$(MAKEDIRS) $(srcdir)/.bundle/specifications
+ @$(XRUBY) -W0 -C "$(srcdir)" -rrubygems \
+ -e "destdir = ARGV.shift" \
+ -e "ARGV.each do |basedir|" \
+ -e "Dir.glob(basedir+'/**/*.gemspec') do |g|" \
+ -e "dir, base = File.split(g)" \
+ -e "spec = Dir.chdir(dir) {Gem::Specification.load(base)} ||" \
+ -e "Gem::Specification.load(g)" \
+ -e "unless spec" \
+ -e "puts %[Ignoring #{g}]" \
+ -e "next" \
+ -e "end" \
+ -e "spec.files.clear" \
+ -e "spec.extensions.clear" \
+ -e "File.binwrite(File.join(destdir, spec.full_name+'.gemspec'), spec.to_ruby)" \
+ -e "end" \
+ -e "end" \
+ -- .bundle/specifications lib ext
+
+install-for-test-bundled-gems: $(TEST_RUNNABLE)-install-for-test-bundled-gems
+no-install-for-test-bundled-gems: no-update-default-gemspecs
+yes-install-for-test-bundled-gems: yes-update-default-gemspecs
+ $(XRUBY) -C "$(srcdir)" -r./tool/lib/gem_env.rb bin/gem \
+ install --no-document --conservative \
+ "hoe" "json-schema:5.1.0" "test-unit-rr" "simplecov" "simplecov-html" "simplecov-json" "rspec" "zeitwerk" \
+ "sinatra" "rack" "tilt" "mustermann" "base64" "compact_index" "rack-test" "logger" "kpeg" "tracer" "minitest-mock"
+
test-bundled-gems-fetch: yes-test-bundled-gems-fetch
-yes-test-bundled-gems-fetch:
- $(ACTIONS_GROUP)
- $(Q) $(BASERUBY) -C $(srcdir)/gems ../tool/fetch-bundled_gems.rb src bundled_gems
- $(ACTIONS_ENDGROUP)
+yes-test-bundled-gems-fetch: clone-bundled-gems-src
+clone-bundled-gems-src: PHONY
+ $(Q) $(BASERUBY) -C $(srcdir) tool/fetch-bundled_gems.rb BUNDLED_GEMS="$(BUNDLED_GEMS)" gems/src gems/bundled_gems
no-test-bundled-gems-fetch:
-test-bundled-gems-prepare: $(PRECHECK_BUNDLED_GEMS) test-bundled-gems-fetch
test-bundled-gems-prepare: $(TEST_RUNNABLE)-test-bundled-gems-prepare
-no-test-bundled-gems-prepare: no-test-bundled-gems-precheck
-yes-test-bundled-gems-prepare: yes-test-bundled-gems-precheck
+no-test-bundled-gems-prepare: no-test-bundled-gems-precheck no-test-bundled-gems-fetch
+Preparing-test-bundled-gems:
$(ACTIONS_GROUP)
- $(XRUBY) -C "$(srcdir)" bin/gem install --no-document \
- --install-dir .bundle --conservative "hoe" "json-schema" "test-unit-rr"
+yes-test-bundled-gems-prepare: Preparing-test-bundled-gems $(DOT_WAIT)
$(ACTIONS_ENDGROUP)
+yes-test-bundled-gems-prepare: yes-test-bundled-gems-precheck $(DOT_WAIT)
+yes-test-bundled-gems-prepare: yes-install-for-test-bundled-gems $(DOT_WAIT)
+yes-test-bundled-gems-prepare: yes-test-bundled-gems-fetch $(DOT_WAIT)
+yes-test-bundled-gems-precheck: Preparing-test-bundled-gems
+yes-install-for-test-bundled-gems: Preparing-test-bundled-gems
+yes-test-bundled-gems-fetch: Preparing-test-bundled-gems
PREPARE_BUNDLED_GEMS = test-bundled-gems-prepare
test-bundled-gems: $(TEST_RUNNABLE)-test-bundled-gems $(DOT_WAIT) $(TEST_RUNNABLE)-test-bundled-gems-spec
yes-test-bundled-gems: test-bundled-gems-run
no-test-bundled-gems:
+bundled_gems_spec-run: install-for-test-bundled-gems
+ $(XRUBY) -C $(srcdir) .bundle/bin/rspec spec/bundled_gems_spec.rb
+
# Override this to allow failure of specific gems on CI
# TEST_BUNDLED_GEMS_ALLOW_FAILURES =
@@ -1609,7 +1604,8 @@ yes-test-bundled-gems-spec: yes-test-spec-precheck $(PREPARE_BUNDLED_GEMS)
$(ACTIONS_GROUP)
$(gnumake_recursive)$(Q) \
$(RUNRUBY) -r./$(arch)-fake -r$(tooldir)/lib/_tmpdir \
- $(srcdir)/spec/mspec/bin/mspec run -B $(srcdir)/spec/bundled_gems.mspec $(MSPECOPT) $(SPECOPTS)
+ $(srcdir)/spec/mspec/bin/mspec run --env BUNDLED_GEMS=$(BUNDLED_GEMS) -B $(srcdir)/spec/bundled_gems.mspec \
+ $(MSPECOPT) $(SPECOPTS)
$(ACTIONS_ENDGROUP)
no-test-bundled-gems-spec:
@@ -1618,6 +1614,11 @@ test-syntax-suggest:
check: $(DOT_WAIT) $(PREPARE_SYNTAX_SUGGEST) test-syntax-suggest
+RAKER = $(XRUBY) -I$(srcdir)/gems/lib$(PATH_SEPARATOR)$(srcdir)/.bundle/lib \
+ -rrubygems $(srcdir)/.bundle/bin/rake
+rake:
+ $(RAKER) $(RAKE_OPTS) $(RAKE)
+
test-bundler-precheck: $(TEST_RUNNABLE)-test-bundler-precheck
no-test-bundler-precheck:
yes-test-bundler-precheck: main $(arch)-fake.rb
@@ -1627,24 +1628,19 @@ test-bundler-prepare: $(TEST_RUNNABLE)-test-bundler-prepare
no-test-bundler-prepare: no-test-bundler-precheck
yes-test-bundler-prepare: yes-test-bundler-precheck
$(ACTIONS_GROUP)
- $(XRUBY) -C $(srcdir) -Ilib \
- -e 'ENV["GEM_HOME"] = File.expand_path(".bundle")' \
- -e 'ENV["BUNDLE_APP_CONFIG"] = File.expand_path(".bundle")' \
- -e 'ENV["BUNDLE_PATH__SYSTEM"] = "true"' \
- -e 'ENV["BUNDLE_WITHOUT"] = "lint doc"' \
- -e 'load "spec/bundler/support/bundle.rb"' -- install --quiet --gemfile=tool/bundler/dev_gems.rb
+ $(XRUBY) -C $(srcdir) -Ilib -r./tool/lib/bundle_env.rb \
+ spec/bin/bundle install --quiet --gemfile=tool/bundler/dev_gems.rb
$(ACTIONS_ENDGROUP)
-RSPECOPTS =
+RSPECOPTS = -r formatter_overrides
BUNDLER_SPECS =
PREPARE_BUNDLER = $(TEST_RUNNABLE)-test-bundler-prepare
test-bundler: $(TEST_RUNNABLE)-test-bundler
yes-test-bundler: $(PREPARE_BUNDLER)
$(gnumake_recursive)$(XRUBY) \
-r./$(arch)-fake \
- -e "exec(*ARGV)" -- \
- $(XRUBY) -C $(srcdir) -Ispec/bundler:spec/lib .bundle/bin/rspec \
- --require spec_helper --require formatter_overrides $(RSPECOPTS) spec/bundler/$(BUNDLER_SPECS)
+ -C $(srcdir) -Ispec/bundler -Ispec/lib spec/bin/rspec \
+ -r spec_helper $(RSPECOPTS) spec/bundler/$(BUNDLER_SPECS)
no-test-bundler:
PARALLELRSPECOPTS = --runtime-log $(srcdir)/tmp/parallel_runtime_rspec.log
@@ -1652,22 +1648,21 @@ test-bundler-parallel: $(TEST_RUNNABLE)-test-bundler-parallel
yes-test-bundler-parallel: $(PREPARE_BUNDLER)
$(gnumake_recursive)$(XRUBY) \
-r./$(arch)-fake \
+ -I$(srcdir)/spec/bundler \
+ -e "ruby = ENV['RUBY']" \
-e "ARGV[-1] = File.expand_path(ARGV[-1])" \
- -e "exec(*ARGV)" -- \
- $(XRUBY) -I$(srcdir)/spec/bundler \
- -e "ENV['PARALLEL_TESTS_EXECUTABLE'] = ARGV.shift" \
+ -e "ENV['RSPEC_EXECUTABLE'] = ruby + ARGV.shift" \
-e "load ARGV.shift" \
- "$(XRUBY) -C $(srcdir) -Ispec/bundler:spec/lib .bundle/bin/rspec" \
- $(srcdir)/.bundle/bin/parallel_rspec \
- -o "--require spec_helper --require formatter_overrides" \
+ " -C $(srcdir) -Ispec/bundler -Ispec/lib .bundle/bin/rspec -r spec_helper" \
+ $(srcdir)/spec/bin/parallel_rspec $(RSPECOPTS) \
$(PARALLELRSPECOPTS) $(srcdir)/spec/bundler/$(BUNDLER_SPECS)
no-test-bundler-parallel:
# The annocheck supports ELF format binaries compiled for any OS and for any
# architecture. It is designed to be independent of the host OS and the
# architecture. The test-annocheck.sh requires docker or podman.
-test-annocheck: $(PROGRAM)
- $(tooldir)/test-annocheck.sh $(PROGRAM)
+test-annocheck: $(PROGRAM) $(LIBRUBY_SO)
+ $(tooldir)/test-annocheck.sh $(PROGRAM) $(LIBRUBY_SO)
GEM = up
sync-default-gems:
@@ -1680,7 +1675,7 @@ UNICODE_FILES = $(UNICODE_SRC_DATA_DIR)/UnicodeData.txt \
$(UNICODE_SRC_DATA_DIR)/SpecialCasing.txt \
$(empty)
-UNICODE_PROPERTY_FILES = \
+UNICODE_PROPERTY_FILES = \
$(UNICODE_SRC_DATA_DIR)/Blocks.txt \
$(UNICODE_SRC_DATA_DIR)/DerivedAge.txt \
$(UNICODE_SRC_DATA_DIR)/DerivedCoreProperties.txt \
@@ -1690,7 +1685,7 @@ UNICODE_PROPERTY_FILES = \
$(UNICODE_SRC_DATA_DIR)/Scripts.txt \
$(empty)
-UNICODE_AUXILIARY_FILES = \
+UNICODE_AUXILIARY_FILES = \
$(UNICODE_SRC_DATA_DIR)/auxiliary/GraphemeBreakProperty.txt \
$(UNICODE_SRC_DATA_DIR)/auxiliary/GraphemeBreakTest.txt \
$(empty)
@@ -1731,34 +1726,50 @@ UNICODE_UCD_EMOJI_DOWNLOAD = \
UNICODE_EMOJI_DOWNLOAD = \
$(UNICODE_DOWNLOADER) \
-d $(UNICODE_SRC_EMOJI_DATA_DIR) \
- -p emoji/$(UNICODE_EMOJI_VERSION)
+ -p $(UNICODE_VERSION)/emoji
-update-unicode-files: $(UNICODE_FILES) $(UNICODE_PROPERTY_FILES)
-$(UNICODE_FILES) $(UNICODE_PROPERTY_FILES):
+update-unicode-files:
$(ECHO) Downloading Unicode $(UNICODE_VERSION) data and property files...
$(Q) $(MAKEDIRS) "$(UNICODE_SRC_DATA_DIR)"
$(Q) $(UNICODE_DOWNLOAD) $(UNICODE_FILES) $(UNICODE_PROPERTY_FILES)
-update-unicode-auxiliary-files: $(UNICODE_AUXILIARY_FILES)
-$(UNICODE_AUXILIARY_FILES):
+update-unicode-auxiliary-files:
$(ECHO) Downloading Unicode $(UNICODE_VERSION) auxiliary files...
$(Q) $(MAKEDIRS) "$(UNICODE_SRC_DATA_DIR)/auxiliary"
$(Q) $(UNICODE_AUXILIARY_DOWNLOAD) $(UNICODE_AUXILIARY_FILES)
-update-unicode-ucd-emoji-files: $(UNICODE_UCD_EMOJI_FILES)
-$(UNICODE_UCD_EMOJI_FILES):
+update-unicode-ucd-emoji-files:
$(ECHO) Downloading Unicode UCD emoji $(UNICODE_EMOJI_VERSION) files...
$(Q) $(MAKEDIRS) "$(UNICODE_SRC_DATA_DIR)/emoji"
$(Q) $(UNICODE_UCD_EMOJI_DOWNLOAD) $(UNICODE_UCD_EMOJI_FILES)
-update-unicode-emoji-files: $(UNICODE_EMOJI_FILES)
-$(UNICODE_EMOJI_FILES):
+update-unicode-emoji-files:
$(ECHO) Downloading Unicode emoji $(UNICODE_EMOJI_VERSION) files...
$(Q) $(MAKEDIRS) "$(UNICODE_SRC_EMOJI_DATA_DIR)"
$(Q) $(UNICODE_EMOJI_DOWNLOAD) $(UNICODE_EMOJI_FILES)
-$(srcdir)/lib/unicode_normalize/tables.rb: \
- $(UNICODE_SRC_DATA_DIR)/$(HAVE_BASERUBY:yes=.unicode-tables.time)
+$(UNICODE_FILES) $(UNICODE_PROPERTY_FILES):
+ $(ECHO) Downloading Unicode $(UNICODE_VERSION) data and property files...
+ $(Q) $(MAKEDIRS) "$(UNICODE_SRC_DATA_DIR)"
+ $(Q) $(UNICODE_DOWNLOAD) $@
+
+$(UNICODE_AUXILIARY_FILES):
+ $(ECHO) Downloading Unicode $(UNICODE_VERSION) auxiliary files...
+ $(Q) $(MAKEDIRS) "$(UNICODE_SRC_DATA_DIR)/auxiliary"
+ $(Q) $(UNICODE_AUXILIARY_DOWNLOAD) $@
+
+$(UNICODE_UCD_EMOJI_FILES):
+ $(ECHO) Downloading Unicode UCD emoji $(UNICODE_EMOJI_VERSION) files...
+ $(Q) $(MAKEDIRS) "$(UNICODE_SRC_DATA_DIR)/emoji"
+ $(Q) $(UNICODE_UCD_EMOJI_DOWNLOAD) $@
+
+$(UNICODE_EMOJI_FILES):
+ $(ECHO) Downloading Unicode emoji $(UNICODE_EMOJI_VERSION) files...
+ $(Q) $(MAKEDIRS) "$(UNICODE_SRC_EMOJI_DATA_DIR)"
+ $(Q) $(UNICODE_EMOJI_DOWNLOAD) $@
+
+$(srcdir)/lib/unicode_normalize/$(HAVE_BASERUBY:yes=tables.rb): \
+ $(UNICODE_SRC_DATA_DIR)/.unicode-tables.time
$(UNICODE_SRC_DATA_DIR)/$(ALWAYS_UPDATE_UNICODE:yes=.unicode-tables.time): \
$(UNICODE_FILES) $(UNICODE_PROPERTY_FILES) \
@@ -1809,11 +1820,11 @@ $(UNICODE_HDR_DIR)/name2ctype.h:
$(UNICODE_SRC_DATA_DIR) $(UNICODE_SRC_EMOJI_DATA_DIR) > $@.new
$(MV) $@.new $@
-srcs-doc: $(srcdir)/doc/regexp/unicode_properties.rdoc
-$(srcdir)/doc/regexp/$(ALWAYS_UPDATE_UNICODE:yes=unicode_properties.rdoc): \
+srcs-doc: $(srcdir)/doc/language/regexp/unicode_properties.rdoc
+$(srcdir)/doc/language/regexp/$(ALWAYS_UPDATE_UNICODE:yes=unicode_properties.rdoc): \
$(UNICODE_HDR_DIR)/name2ctype.h $(UNICODE_PROPERTY_FILES)
-$(srcdir)/doc/regexp/unicode_properties.rdoc:
+$(srcdir)/doc/language/regexp/unicode_properties.rdoc:
$(Q) $(BOOTSTRAPRUBY) $(tooldir)/generic_erb.rb -c -o $@ \
$(srcdir)/template/unicode_properties.rdoc.tmpl \
$(UNICODE_SRC_DATA_DIR) $(UNICODE_HDR_DIR)/name2ctype.h || \
@@ -1850,6 +1861,9 @@ clean-gems:
CLEAN_CACHE = clean-extlibs
+prepare-package: prereq after-update
+clean-cache: $(CLEAN_CACHE)
+
info: info-program info-libruby_a info-libruby_so info-arch
info-program: PHONY
@echo PROGRAM=$(PROGRAM)
@@ -1862,6 +1876,7 @@ info-arch: PHONY
exam: check
exam: $(DOT_WAIT) test-bundler-parallel
+exam: $(DOT_WAIT) bundled_gems_spec-run
exam: $(DOT_WAIT) test-bundled-gems
love: sudo-precheck up all test exam install
@@ -1900,11 +1915,40 @@ nightly: yesterday $(DOT_WAIT) install
yesterday: rewindable
rewindable:
- $(GIT) -C $(srcdir) status --porcelain
- $(GIT) -C $(srcdir) diff --quiet
+ $(GIT_IN_SRC) status --porcelain
+ $(GIT_IN_SRC) diff --quiet
HELP_EXTRA_TASKS = ""
+gc/Makefile:
+ $(MAKEDIRS) $(@D)
+ $(MESSAGE_BEGIN) \
+ "all:" \
+ " @echo You must specify MODULAR_GC with the GC to build" \
+ " @exit 1" \
+ $(MESSAGE_END) > $@
+gc/distclean gc/realclean::
+ -$(Q) $(RM) gc/Makefile
+
+modular-gc-precheck:
+modular-gc: probes.h gc/Makefile
+ $(Q) $(RUNRUBY) $(srcdir)/ext/extmk.rb \
+ $(SCRIPT_ARGS) \
+ --make='$(MAKE)' --make-flags="V=$(V) MINIRUBY='$(MINIRUBY)'" \
+ --gnumake=$(gnumake) --extflags="$(EXTLDFLAGS)" \
+ --ext-build-dir=gc --command-output=gc/$(MODULAR_GC)/exts.mk -- \
+ configure gc/$(MODULAR_GC)
+ $(CHDIR) gc/$(MODULAR_GC) && $(exec) $(MAKE) TARGET_SO_DIR=./
+install-modular-gc: modular-gc modular-gc-precheck
+ $(Q) $(MAKEDIRS) $(modular_gc_dir)
+ $(CP) gc/$(MODULAR_GC)/librubygc.$(MODULAR_GC).$(DLEXT) $(modular_gc_dir)
+
+clean-modular-gc: gc/clean
+distclean-modular-gc: gc/distclean
+realclean-modular-gc: gc/realclean
+distclean-modular-gc realclean-modular-gc:
+ -$(Q) $(RMDIR) gc
+
help: PHONY
$(MESSAGE_BEGIN) \
" Makefile of Ruby" \
@@ -1952,19421 +1996,5 @@ help: PHONY
$(CROSS_COMPILING:yes=)builtin.$(OBJEXT): {$(VPATH)}mini_builtin.c
$(CROSS_COMPILING:yes=)builtin.$(OBJEXT): {$(VPATH)}miniprelude.c
-# 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/packed_struct.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): $(CCAN_DIR)/check_type/check_type.h
-array.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-array.$(OBJEXT): $(CCAN_DIR)/list/list.h
-array.$(OBJEXT): $(CCAN_DIR)/str/str.h
-array.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-array.$(OBJEXT): $(top_srcdir)/internal/array.h
-array.$(OBJEXT): $(top_srcdir)/internal/basic_operators.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/imemo.h
-array.$(OBJEXT): $(top_srcdir)/internal/numeric.h
-array.$(OBJEXT): $(top_srcdir)/internal/object.h
-array.$(OBJEXT): $(top_srcdir)/internal/proc.h
-array.$(OBJEXT): $(top_srcdir)/internal/rational.h
-array.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-array.$(OBJEXT): $(top_srcdir)/internal/serial.h
-array.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-array.$(OBJEXT): $(top_srcdir)/internal/variable.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)}atomic.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)}constant.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/abi.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/packed_struct.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/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/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/stdckdint.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)}method.h
-array.$(OBJEXT): {$(VPATH)}missing.h
-array.$(OBJEXT): {$(VPATH)}node.h
-array.$(OBJEXT): {$(VPATH)}onigmo.h
-array.$(OBJEXT): {$(VPATH)}oniguruma.h
-array.$(OBJEXT): {$(VPATH)}probes.dmyh
-array.$(OBJEXT): {$(VPATH)}probes.h
-array.$(OBJEXT): {$(VPATH)}ruby_assert.h
-array.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-array.$(OBJEXT): {$(VPATH)}rubyparser.h
-array.$(OBJEXT): {$(VPATH)}shape.h
-array.$(OBJEXT): {$(VPATH)}st.h
-array.$(OBJEXT): {$(VPATH)}subst.h
-array.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-array.$(OBJEXT): {$(VPATH)}thread_native.h
-array.$(OBJEXT): {$(VPATH)}util.h
-array.$(OBJEXT): {$(VPATH)}vm_core.h
-array.$(OBJEXT): {$(VPATH)}vm_opts.h
-ast.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-ast.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-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/basic_operators.h
-ast.$(OBJEXT): $(top_srcdir)/internal/bignum.h
-ast.$(OBJEXT): $(top_srcdir)/internal/bits.h
-ast.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-ast.$(OBJEXT): $(top_srcdir)/internal/complex.h
-ast.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
-ast.$(OBJEXT): $(top_srcdir)/internal/gc.h
-ast.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-ast.$(OBJEXT): $(top_srcdir)/internal/numeric.h
-ast.$(OBJEXT): $(top_srcdir)/internal/parse.h
-ast.$(OBJEXT): $(top_srcdir)/internal/rational.h
-ast.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
-ast.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-ast.$(OBJEXT): $(top_srcdir)/internal/serial.h
-ast.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-ast.$(OBJEXT): $(top_srcdir)/internal/symbol.h
-ast.$(OBJEXT): $(top_srcdir)/internal/variable.h
-ast.$(OBJEXT): $(top_srcdir)/internal/vm.h
-ast.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-ast.$(OBJEXT): $(top_srcdir)/prism/defines.h
-ast.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-ast.$(OBJEXT): $(top_srcdir)/prism/node.h
-ast.$(OBJEXT): $(top_srcdir)/prism/options.h
-ast.$(OBJEXT): $(top_srcdir)/prism/pack.h
-ast.$(OBJEXT): $(top_srcdir)/prism/parser.h
-ast.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-ast.$(OBJEXT): $(top_srcdir)/prism/prism.h
-ast.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-ast.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-ast.$(OBJEXT): {$(VPATH)}assert.h
-ast.$(OBJEXT): {$(VPATH)}ast.c
-ast.$(OBJEXT): {$(VPATH)}ast.rbinc
-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)}constant.h
-ast.$(OBJEXT): {$(VPATH)}defines.h
-ast.$(OBJEXT): {$(VPATH)}encoding.h
-ast.$(OBJEXT): {$(VPATH)}id.h
-ast.$(OBJEXT): {$(VPATH)}id_table.h
-ast.$(OBJEXT): {$(VPATH)}intern.h
-ast.$(OBJEXT): {$(VPATH)}internal.h
-ast.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/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/stdckdint.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
-ast.$(OBJEXT): {$(VPATH)}node.h
-ast.$(OBJEXT): {$(VPATH)}onigmo.h
-ast.$(OBJEXT): {$(VPATH)}oniguruma.h
-ast.$(OBJEXT): {$(VPATH)}prism/ast.h
-ast.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-ast.$(OBJEXT): {$(VPATH)}prism/version.h
-ast.$(OBJEXT): {$(VPATH)}prism_compile.h
-ast.$(OBJEXT): {$(VPATH)}ruby_assert.h
-ast.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-ast.$(OBJEXT): {$(VPATH)}rubyparser.h
-ast.$(OBJEXT): {$(VPATH)}shape.h
-ast.$(OBJEXT): {$(VPATH)}st.h
-ast.$(OBJEXT): {$(VPATH)}subst.h
-ast.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-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): $(CCAN_DIR)/check_type/check_type.h
-bignum.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-bignum.$(OBJEXT): $(CCAN_DIR)/list/list.h
-bignum.$(OBJEXT): $(CCAN_DIR)/str/str.h
-bignum.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-bignum.$(OBJEXT): $(top_srcdir)/internal/array.h
-bignum.$(OBJEXT): $(top_srcdir)/internal/basic_operators.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/imemo.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)}atomic.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)}encoding.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/abi.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/packed_struct.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/encoding/coderange.h
-bignum.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
-bignum.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
-bignum.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
-bignum.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
-bignum.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
-bignum.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
-bignum.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
-bignum.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.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/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/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/stdckdint.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)}method.h
-bignum.$(OBJEXT): {$(VPATH)}missing.h
-bignum.$(OBJEXT): {$(VPATH)}node.h
-bignum.$(OBJEXT): {$(VPATH)}onigmo.h
-bignum.$(OBJEXT): {$(VPATH)}oniguruma.h
-bignum.$(OBJEXT): {$(VPATH)}ruby_assert.h
-bignum.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-bignum.$(OBJEXT): {$(VPATH)}rubyparser.h
-bignum.$(OBJEXT): {$(VPATH)}shape.h
-bignum.$(OBJEXT): {$(VPATH)}st.h
-bignum.$(OBJEXT): {$(VPATH)}subst.h
-bignum.$(OBJEXT): {$(VPATH)}thread.h
-bignum.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-bignum.$(OBJEXT): {$(VPATH)}thread_native.h
-bignum.$(OBJEXT): {$(VPATH)}util.h
-bignum.$(OBJEXT): {$(VPATH)}vm_core.h
-bignum.$(OBJEXT): {$(VPATH)}vm_opts.h
-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/ruby.h
-builtin.$(OBJEXT): $(top_srcdir)/internal/array.h
-builtin.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-builtin.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-builtin.$(OBJEXT): $(top_srcdir)/internal/gc.h
-builtin.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-builtin.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-builtin.$(OBJEXT): $(top_srcdir)/internal/serial.h
-builtin.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-builtin.$(OBJEXT): $(top_srcdir)/internal/variable.h
-builtin.$(OBJEXT): $(top_srcdir)/internal/vm.h
-builtin.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-builtin.$(OBJEXT): $(top_srcdir)/prism/defines.h
-builtin.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-builtin.$(OBJEXT): $(top_srcdir)/prism/node.h
-builtin.$(OBJEXT): $(top_srcdir)/prism/options.h
-builtin.$(OBJEXT): $(top_srcdir)/prism/pack.h
-builtin.$(OBJEXT): $(top_srcdir)/prism/parser.h
-builtin.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-builtin.$(OBJEXT): $(top_srcdir)/prism/prism.h
-builtin.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-builtin.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-builtin.$(OBJEXT): {$(VPATH)}assert.h
-builtin.$(OBJEXT): {$(VPATH)}atomic.h
-builtin.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-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)}constant.h
-builtin.$(OBJEXT): {$(VPATH)}defines.h
-builtin.$(OBJEXT): {$(VPATH)}encoding.h
-builtin.$(OBJEXT): {$(VPATH)}id.h
-builtin.$(OBJEXT): {$(VPATH)}id_table.h
-builtin.$(OBJEXT): {$(VPATH)}intern.h
-builtin.$(OBJEXT): {$(VPATH)}internal.h
-builtin.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/encoding/coderange.h
-builtin.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
-builtin.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
-builtin.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
-builtin.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
-builtin.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
-builtin.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
-builtin.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
-builtin.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.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/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/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/stdckdint.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
-builtin.$(OBJEXT): {$(VPATH)}node.h
-builtin.$(OBJEXT): {$(VPATH)}onigmo.h
-builtin.$(OBJEXT): {$(VPATH)}oniguruma.h
-builtin.$(OBJEXT): {$(VPATH)}prism/ast.h
-builtin.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-builtin.$(OBJEXT): {$(VPATH)}prism/version.h
-builtin.$(OBJEXT): {$(VPATH)}prism_compile.h
-builtin.$(OBJEXT): {$(VPATH)}ruby_assert.h
-builtin.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-builtin.$(OBJEXT): {$(VPATH)}rubyparser.h
-builtin.$(OBJEXT): {$(VPATH)}shape.h
-builtin.$(OBJEXT): {$(VPATH)}st.h
-builtin.$(OBJEXT): {$(VPATH)}subst.h
-builtin.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-builtin.$(OBJEXT): {$(VPATH)}thread_native.h
-builtin.$(OBJEXT): {$(VPATH)}vm_core.h
-builtin.$(OBJEXT): {$(VPATH)}vm_opts.h
-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/ruby.h
-class.$(OBJEXT): $(top_srcdir)/internal/array.h
-class.$(OBJEXT): $(top_srcdir)/internal/basic_operators.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/sanitizers.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)}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/abi.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/packed_struct.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/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/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/stdckdint.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)}rubyparser.h
-class.$(OBJEXT): {$(VPATH)}shape.h
-class.$(OBJEXT): {$(VPATH)}st.h
-class.$(OBJEXT): {$(VPATH)}subst.h
-class.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-class.$(OBJEXT): {$(VPATH)}thread_native.h
-class.$(OBJEXT): {$(VPATH)}vm_core.h
-class.$(OBJEXT): {$(VPATH)}vm_debug.h
-class.$(OBJEXT): {$(VPATH)}vm_opts.h
-class.$(OBJEXT): {$(VPATH)}vm_sync.h
-class.$(OBJEXT): {$(VPATH)}yjit.h
-compar.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-compar.$(OBJEXT): $(hdrdir)/ruby/version.h
-compar.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-compar.$(OBJEXT): $(top_srcdir)/internal/compar.h
-compar.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-compar.$(OBJEXT): $(top_srcdir)/internal/error.h
-compar.$(OBJEXT): $(top_srcdir)/internal/serial.h
-compar.$(OBJEXT): $(top_srcdir)/internal/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/abi.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/packed_struct.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/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/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/stdckdint.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/ruby.h
-compile.$(OBJEXT): $(hdrdir)/ruby/version.h
-compile.$(OBJEXT): $(top_srcdir)/internal/array.h
-compile.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-compile.$(OBJEXT): $(top_srcdir)/internal/bignum.h
-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/io.h
-compile.$(OBJEXT): $(top_srcdir)/internal/numeric.h
-compile.$(OBJEXT): $(top_srcdir)/internal/object.h
-compile.$(OBJEXT): $(top_srcdir)/internal/parse.h
-compile.$(OBJEXT): $(top_srcdir)/internal/rational.h
-compile.$(OBJEXT): $(top_srcdir)/internal/re.h
-compile.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
-compile.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-compile.$(OBJEXT): $(top_srcdir)/internal/serial.h
-compile.$(OBJEXT): $(top_srcdir)/internal/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): $(top_srcdir)/prism/defines.h
-compile.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-compile.$(OBJEXT): $(top_srcdir)/prism/node.h
-compile.$(OBJEXT): $(top_srcdir)/prism/options.h
-compile.$(OBJEXT): $(top_srcdir)/prism/pack.h
-compile.$(OBJEXT): $(top_srcdir)/prism/parser.h
-compile.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-compile.$(OBJEXT): $(top_srcdir)/prism/prism.h
-compile.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-compile.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-compile.$(OBJEXT): $(top_srcdir)/prism_compile.c
-compile.$(OBJEXT): {$(VPATH)}assert.h
-compile.$(OBJEXT): {$(VPATH)}atomic.h
-compile.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-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)}debug_counter.h
-compile.$(OBJEXT): {$(VPATH)}defines.h
-compile.$(OBJEXT): {$(VPATH)}encindex.h
-compile.$(OBJEXT): {$(VPATH)}encoding.h
-compile.$(OBJEXT): {$(VPATH)}id.h
-compile.$(OBJEXT): {$(VPATH)}id_table.h
-compile.$(OBJEXT): {$(VPATH)}insns.def
-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/abi.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/packed_struct.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/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/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/stdckdint.h
-compile.$(OBJEXT): {$(VPATH)}internal/symbol.h
-compile.$(OBJEXT): {$(VPATH)}internal/value.h
-compile.$(OBJEXT): {$(VPATH)}internal/value_type.h
-compile.$(OBJEXT): {$(VPATH)}internal/variable.h
-compile.$(OBJEXT): {$(VPATH)}internal/warning_push.h
-compile.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
-compile.$(OBJEXT): {$(VPATH)}io.h
-compile.$(OBJEXT): {$(VPATH)}iseq.h
-compile.$(OBJEXT): {$(VPATH)}method.h
-compile.$(OBJEXT): {$(VPATH)}missing.h
-compile.$(OBJEXT): {$(VPATH)}node.h
-compile.$(OBJEXT): {$(VPATH)}onigmo.h
-compile.$(OBJEXT): {$(VPATH)}oniguruma.h
-compile.$(OBJEXT): {$(VPATH)}optinsn.inc
-compile.$(OBJEXT): {$(VPATH)}prism/ast.h
-compile.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-compile.$(OBJEXT): {$(VPATH)}prism/prism.h
-compile.$(OBJEXT): {$(VPATH)}prism/version.h
-compile.$(OBJEXT): {$(VPATH)}prism_compile.c
-compile.$(OBJEXT): {$(VPATH)}prism_compile.h
-compile.$(OBJEXT): {$(VPATH)}ractor.h
-compile.$(OBJEXT): {$(VPATH)}re.h
-compile.$(OBJEXT): {$(VPATH)}regex.h
-compile.$(OBJEXT): {$(VPATH)}ruby_assert.h
-compile.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-compile.$(OBJEXT): {$(VPATH)}rubyparser.h
-compile.$(OBJEXT): {$(VPATH)}shape.h
-compile.$(OBJEXT): {$(VPATH)}st.h
-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
-compile.$(OBJEXT): {$(VPATH)}vm_sync.h
-compile.$(OBJEXT): {$(VPATH)}yjit.h
-complex.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-complex.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-complex.$(OBJEXT): $(CCAN_DIR)/list/list.h
-complex.$(OBJEXT): $(CCAN_DIR)/str/str.h
-complex.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-complex.$(OBJEXT): $(top_srcdir)/internal/array.h
-complex.$(OBJEXT): $(top_srcdir)/internal/basic_operators.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/imemo.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/sanitizers.h
-complex.$(OBJEXT): $(top_srcdir)/internal/serial.h
-complex.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-complex.$(OBJEXT): $(top_srcdir)/internal/string.h
-complex.$(OBJEXT): $(top_srcdir)/internal/variable.h
-complex.$(OBJEXT): $(top_srcdir)/internal/vm.h
-complex.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-complex.$(OBJEXT): {$(VPATH)}assert.h
-complex.$(OBJEXT): {$(VPATH)}atomic.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)}constant.h
-complex.$(OBJEXT): {$(VPATH)}debug_counter.h
-complex.$(OBJEXT): {$(VPATH)}defines.h
-complex.$(OBJEXT): {$(VPATH)}encoding.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/abi.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/packed_struct.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/encoding/coderange.h
-complex.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
-complex.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
-complex.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
-complex.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
-complex.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
-complex.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
-complex.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
-complex.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.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/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/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/stdckdint.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)}method.h
-complex.$(OBJEXT): {$(VPATH)}missing.h
-complex.$(OBJEXT): {$(VPATH)}node.h
-complex.$(OBJEXT): {$(VPATH)}onigmo.h
-complex.$(OBJEXT): {$(VPATH)}oniguruma.h
-complex.$(OBJEXT): {$(VPATH)}ruby_assert.h
-complex.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-complex.$(OBJEXT): {$(VPATH)}rubyparser.h
-complex.$(OBJEXT): {$(VPATH)}shape.h
-complex.$(OBJEXT): {$(VPATH)}st.h
-complex.$(OBJEXT): {$(VPATH)}subst.h
-complex.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-complex.$(OBJEXT): {$(VPATH)}thread_native.h
-complex.$(OBJEXT): {$(VPATH)}vm_core.h
-complex.$(OBJEXT): {$(VPATH)}vm_debug.h
-complex.$(OBJEXT): {$(VPATH)}vm_opts.h
-complex.$(OBJEXT): {$(VPATH)}vm_sync.h
-cont.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-cont.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-cont.$(OBJEXT): $(CCAN_DIR)/list/list.h
-cont.$(OBJEXT): $(CCAN_DIR)/str/str.h
-cont.$(OBJEXT): $(hdrdir)/ruby.h
-cont.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-cont.$(OBJEXT): $(hdrdir)/ruby/version.h
-cont.$(OBJEXT): $(top_srcdir)/internal/array.h
-cont.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-cont.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-cont.$(OBJEXT): $(top_srcdir)/internal/cont.h
-cont.$(OBJEXT): $(top_srcdir)/internal/error.h
-cont.$(OBJEXT): $(top_srcdir)/internal/gc.h
-cont.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-cont.$(OBJEXT): $(top_srcdir)/internal/proc.h
-cont.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-cont.$(OBJEXT): $(top_srcdir)/internal/serial.h
-cont.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-cont.$(OBJEXT): $(top_srcdir)/internal/string.h
-cont.$(OBJEXT): $(top_srcdir)/internal/thread.h
-cont.$(OBJEXT): $(top_srcdir)/internal/variable.h
-cont.$(OBJEXT): $(top_srcdir)/internal/vm.h
-cont.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-cont.$(OBJEXT): $(top_srcdir)/prism/defines.h
-cont.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-cont.$(OBJEXT): $(top_srcdir)/prism/node.h
-cont.$(OBJEXT): $(top_srcdir)/prism/options.h
-cont.$(OBJEXT): $(top_srcdir)/prism/pack.h
-cont.$(OBJEXT): $(top_srcdir)/prism/parser.h
-cont.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-cont.$(OBJEXT): $(top_srcdir)/prism/prism.h
-cont.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-cont.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-cont.$(OBJEXT): {$(VPATH)}$(COROUTINE_H)
-cont.$(OBJEXT): {$(VPATH)}assert.h
-cont.$(OBJEXT): {$(VPATH)}atomic.h
-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)}constant.h
-cont.$(OBJEXT): {$(VPATH)}cont.c
-cont.$(OBJEXT): {$(VPATH)}debug_counter.h
-cont.$(OBJEXT): {$(VPATH)}defines.h
-cont.$(OBJEXT): {$(VPATH)}encoding.h
-cont.$(OBJEXT): {$(VPATH)}eval_intern.h
-cont.$(OBJEXT): {$(VPATH)}fiber/scheduler.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/abi.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/packed_struct.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/encoding/coderange.h
-cont.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
-cont.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
-cont.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
-cont.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
-cont.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
-cont.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
-cont.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
-cont.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.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/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/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/stdckdint.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)}iseq.h
-cont.$(OBJEXT): {$(VPATH)}method.h
-cont.$(OBJEXT): {$(VPATH)}missing.h
-cont.$(OBJEXT): {$(VPATH)}node.h
-cont.$(OBJEXT): {$(VPATH)}onigmo.h
-cont.$(OBJEXT): {$(VPATH)}oniguruma.h
-cont.$(OBJEXT): {$(VPATH)}prism/ast.h
-cont.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-cont.$(OBJEXT): {$(VPATH)}prism/version.h
-cont.$(OBJEXT): {$(VPATH)}prism_compile.h
-cont.$(OBJEXT): {$(VPATH)}ractor.h
-cont.$(OBJEXT): {$(VPATH)}ractor_core.h
-cont.$(OBJEXT): {$(VPATH)}rjit.h
-cont.$(OBJEXT): {$(VPATH)}ruby_assert.h
-cont.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-cont.$(OBJEXT): {$(VPATH)}rubyparser.h
-cont.$(OBJEXT): {$(VPATH)}shape.h
-cont.$(OBJEXT): {$(VPATH)}st.h
-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)}vm_sync.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/ruby.h
-debug.$(OBJEXT): $(top_srcdir)/internal/array.h
-debug.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-debug.$(OBJEXT): $(top_srcdir)/internal/class.h
-debug.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-debug.$(OBJEXT): $(top_srcdir)/internal/gc.h
-debug.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-debug.$(OBJEXT): $(top_srcdir)/internal/sanitizers.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/variable.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)}constant.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)}id.h
-debug.$(OBJEXT): {$(VPATH)}id_table.h
-debug.$(OBJEXT): {$(VPATH)}intern.h
-debug.$(OBJEXT): {$(VPATH)}internal.h
-debug.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/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/stdckdint.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)}rubyparser.h
-debug.$(OBJEXT): {$(VPATH)}shape.h
-debug.$(OBJEXT): {$(VPATH)}st.h
-debug.$(OBJEXT): {$(VPATH)}subst.h
-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.$(OBJEXT): {$(VPATH)}vm_sync.h
-debug_counter.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-debug_counter.$(OBJEXT): {$(VPATH)}assert.h
-debug_counter.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-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/abi.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/packed_struct.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/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/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/stdckdint.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
-debug_counter.$(OBJEXT): {$(VPATH)}thread_native.h
-dir.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-dir.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-dir.$(OBJEXT): $(CCAN_DIR)/list/list.h
-dir.$(OBJEXT): $(CCAN_DIR)/str/str.h
-dir.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-dir.$(OBJEXT): $(hdrdir)/ruby/version.h
-dir.$(OBJEXT): $(top_srcdir)/internal/array.h
-dir.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-dir.$(OBJEXT): $(top_srcdir)/internal/class.h
-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/imemo.h
-dir.$(OBJEXT): $(top_srcdir)/internal/io.h
-dir.$(OBJEXT): $(top_srcdir)/internal/object.h
-dir.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-dir.$(OBJEXT): $(top_srcdir)/internal/serial.h
-dir.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-dir.$(OBJEXT): $(top_srcdir)/internal/string.h
-dir.$(OBJEXT): $(top_srcdir)/internal/variable.h
-dir.$(OBJEXT): $(top_srcdir)/internal/vm.h
-dir.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-dir.$(OBJEXT): {$(VPATH)}assert.h
-dir.$(OBJEXT): {$(VPATH)}atomic.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)}constant.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/abi.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/packed_struct.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/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/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/stdckdint.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)}method.h
-dir.$(OBJEXT): {$(VPATH)}missing.h
-dir.$(OBJEXT): {$(VPATH)}node.h
-dir.$(OBJEXT): {$(VPATH)}onigmo.h
-dir.$(OBJEXT): {$(VPATH)}oniguruma.h
-dir.$(OBJEXT): {$(VPATH)}ruby_assert.h
-dir.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-dir.$(OBJEXT): {$(VPATH)}rubyparser.h
-dir.$(OBJEXT): {$(VPATH)}shape.h
-dir.$(OBJEXT): {$(VPATH)}st.h
-dir.$(OBJEXT): {$(VPATH)}subst.h
-dir.$(OBJEXT): {$(VPATH)}thread.h
-dir.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-dir.$(OBJEXT): {$(VPATH)}thread_native.h
-dir.$(OBJEXT): {$(VPATH)}util.h
-dir.$(OBJEXT): {$(VPATH)}vm_core.h
-dir.$(OBJEXT): {$(VPATH)}vm_opts.h
-dln.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-dln.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-dln.$(OBJEXT): $(top_srcdir)/internal/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/abi.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/packed_struct.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/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/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/stdckdint.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/abi.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/packed_struct.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/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/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/stdckdint.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/abi.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/packed_struct.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/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/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/stdckdint.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/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/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/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/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
-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/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/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/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/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/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/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
-enc/utf_8.$(OBJEXT): {$(VPATH)}st.h
-enc/utf_8.$(OBJEXT): {$(VPATH)}subst.h
-encoding.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-encoding.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-encoding.$(OBJEXT): $(CCAN_DIR)/list/list.h
-encoding.$(OBJEXT): $(CCAN_DIR)/str/str.h
-encoding.$(OBJEXT): $(hdrdir)/ruby.h
-encoding.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-encoding.$(OBJEXT): $(hdrdir)/ruby/version.h
-encoding.$(OBJEXT): $(top_srcdir)/internal/array.h
-encoding.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-encoding.$(OBJEXT): $(top_srcdir)/internal/class.h
-encoding.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-encoding.$(OBJEXT): $(top_srcdir)/internal/enc.h
-encoding.$(OBJEXT): $(top_srcdir)/internal/encoding.h
-encoding.$(OBJEXT): $(top_srcdir)/internal/error.h
-encoding.$(OBJEXT): $(top_srcdir)/internal/gc.h
-encoding.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-encoding.$(OBJEXT): $(top_srcdir)/internal/inits.h
-encoding.$(OBJEXT): $(top_srcdir)/internal/load.h
-encoding.$(OBJEXT): $(top_srcdir)/internal/object.h
-encoding.$(OBJEXT): $(top_srcdir)/internal/serial.h
-encoding.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-encoding.$(OBJEXT): $(top_srcdir)/internal/string.h
-encoding.$(OBJEXT): $(top_srcdir)/internal/variable.h
-encoding.$(OBJEXT): $(top_srcdir)/internal/vm.h
-encoding.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-encoding.$(OBJEXT): {$(VPATH)}assert.h
-encoding.$(OBJEXT): {$(VPATH)}atomic.h
-encoding.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-encoding.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
-encoding.$(OBJEXT): {$(VPATH)}backward/2/bool.h
-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)}constant.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.h
-encoding.$(OBJEXT): {$(VPATH)}id_table.h
-encoding.$(OBJEXT): {$(VPATH)}intern.h
-encoding.$(OBJEXT): {$(VPATH)}internal.h
-encoding.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/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/stdckdint.h
-encoding.$(OBJEXT): {$(VPATH)}internal/symbol.h
-encoding.$(OBJEXT): {$(VPATH)}internal/value.h
-encoding.$(OBJEXT): {$(VPATH)}internal/value_type.h
-encoding.$(OBJEXT): {$(VPATH)}internal/variable.h
-encoding.$(OBJEXT): {$(VPATH)}internal/warning_push.h
-encoding.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
-encoding.$(OBJEXT): {$(VPATH)}method.h
-encoding.$(OBJEXT): {$(VPATH)}missing.h
-encoding.$(OBJEXT): {$(VPATH)}node.h
-encoding.$(OBJEXT): {$(VPATH)}onigmo.h
-encoding.$(OBJEXT): {$(VPATH)}oniguruma.h
-encoding.$(OBJEXT): {$(VPATH)}regenc.h
-encoding.$(OBJEXT): {$(VPATH)}ruby_assert.h
-encoding.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-encoding.$(OBJEXT): {$(VPATH)}rubyparser.h
-encoding.$(OBJEXT): {$(VPATH)}shape.h
-encoding.$(OBJEXT): {$(VPATH)}st.h
-encoding.$(OBJEXT): {$(VPATH)}subst.h
-encoding.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-encoding.$(OBJEXT): {$(VPATH)}thread_native.h
-encoding.$(OBJEXT): {$(VPATH)}util.h
-encoding.$(OBJEXT): {$(VPATH)}vm_core.h
-encoding.$(OBJEXT): {$(VPATH)}vm_debug.h
-encoding.$(OBJEXT): {$(VPATH)}vm_opts.h
-encoding.$(OBJEXT): {$(VPATH)}vm_sync.h
-enum.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-enum.$(OBJEXT): $(top_srcdir)/internal/array.h
-enum.$(OBJEXT): $(top_srcdir)/internal/basic_operators.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/variable.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)}constant.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/abi.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/packed_struct.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/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/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/stdckdint.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)}shape.h
-enum.$(OBJEXT): {$(VPATH)}st.h
-enum.$(OBJEXT): {$(VPATH)}subst.h
-enum.$(OBJEXT): {$(VPATH)}symbol.h
-enum.$(OBJEXT): {$(VPATH)}util.h
-enumerator.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-enumerator.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-enumerator.$(OBJEXT): $(CCAN_DIR)/list/list.h
-enumerator.$(OBJEXT): $(CCAN_DIR)/str/str.h
-enumerator.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-enumerator.$(OBJEXT): $(hdrdir)/ruby/version.h
-enumerator.$(OBJEXT): $(top_srcdir)/internal/array.h
-enumerator.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-enumerator.$(OBJEXT): $(top_srcdir)/internal/bignum.h
-enumerator.$(OBJEXT): $(top_srcdir)/internal/bits.h
-enumerator.$(OBJEXT): $(top_srcdir)/internal/class.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/sanitizers.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/variable.h
-enumerator.$(OBJEXT): $(top_srcdir)/internal/vm.h
-enumerator.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-enumerator.$(OBJEXT): {$(VPATH)}assert.h
-enumerator.$(OBJEXT): {$(VPATH)}atomic.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)}constant.h
-enumerator.$(OBJEXT): {$(VPATH)}debug_counter.h
-enumerator.$(OBJEXT): {$(VPATH)}defines.h
-enumerator.$(OBJEXT): {$(VPATH)}encoding.h
-enumerator.$(OBJEXT): {$(VPATH)}enumerator.c
-enumerator.$(OBJEXT): {$(VPATH)}id.h
-enumerator.$(OBJEXT): {$(VPATH)}id_table.h
-enumerator.$(OBJEXT): {$(VPATH)}intern.h
-enumerator.$(OBJEXT): {$(VPATH)}internal.h
-enumerator.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/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/stdckdint.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)}method.h
-enumerator.$(OBJEXT): {$(VPATH)}missing.h
-enumerator.$(OBJEXT): {$(VPATH)}node.h
-enumerator.$(OBJEXT): {$(VPATH)}onigmo.h
-enumerator.$(OBJEXT): {$(VPATH)}oniguruma.h
-enumerator.$(OBJEXT): {$(VPATH)}ruby_assert.h
-enumerator.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-enumerator.$(OBJEXT): {$(VPATH)}rubyparser.h
-enumerator.$(OBJEXT): {$(VPATH)}shape.h
-enumerator.$(OBJEXT): {$(VPATH)}st.h
-enumerator.$(OBJEXT): {$(VPATH)}subst.h
-enumerator.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-enumerator.$(OBJEXT): {$(VPATH)}thread_native.h
-enumerator.$(OBJEXT): {$(VPATH)}vm_core.h
-enumerator.$(OBJEXT): {$(VPATH)}vm_debug.h
-enumerator.$(OBJEXT): {$(VPATH)}vm_opts.h
-enumerator.$(OBJEXT): {$(VPATH)}vm_sync.h
-error.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-error.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-error.$(OBJEXT): $(CCAN_DIR)/list/list.h
-error.$(OBJEXT): $(CCAN_DIR)/str/str.h
-error.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-error.$(OBJEXT): $(hdrdir)/ruby/version.h
-error.$(OBJEXT): $(top_srcdir)/internal/array.h
-error.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-error.$(OBJEXT): $(top_srcdir)/internal/class.h
-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/process.h
-error.$(OBJEXT): $(top_srcdir)/internal/sanitizers.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)}debug_counter.h
-error.$(OBJEXT): {$(VPATH)}defines.h
-error.$(OBJEXT): {$(VPATH)}encoding.h
-error.$(OBJEXT): {$(VPATH)}error.c
-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/abi.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/packed_struct.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/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/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/stdckdint.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
-error.$(OBJEXT): {$(VPATH)}node.h
-error.$(OBJEXT): {$(VPATH)}onigmo.h
-error.$(OBJEXT): {$(VPATH)}oniguruma.h
-error.$(OBJEXT): {$(VPATH)}ruby_assert.h
-error.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-error.$(OBJEXT): {$(VPATH)}rubyparser.h
-error.$(OBJEXT): {$(VPATH)}shape.h
-error.$(OBJEXT): {$(VPATH)}st.h
-error.$(OBJEXT): {$(VPATH)}subst.h
-error.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-error.$(OBJEXT): {$(VPATH)}thread_native.h
-error.$(OBJEXT): {$(VPATH)}util.h
-error.$(OBJEXT): {$(VPATH)}vm_core.h
-error.$(OBJEXT): {$(VPATH)}vm_debug.h
-error.$(OBJEXT): {$(VPATH)}vm_opts.h
-error.$(OBJEXT): {$(VPATH)}vm_sync.h
-error.$(OBJEXT): {$(VPATH)}warning.rbinc
-error.$(OBJEXT): {$(VPATH)}yjit.h
-eval.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-eval.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-eval.$(OBJEXT): $(CCAN_DIR)/list/list.h
-eval.$(OBJEXT): $(CCAN_DIR)/str/str.h
-eval.$(OBJEXT): $(hdrdir)/ruby.h
-eval.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-eval.$(OBJEXT): $(hdrdir)/ruby/version.h
-eval.$(OBJEXT): $(top_srcdir)/internal/array.h
-eval.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-eval.$(OBJEXT): $(top_srcdir)/internal/class.h
-eval.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-eval.$(OBJEXT): $(top_srcdir)/internal/cont.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/sanitizers.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): $(top_srcdir)/prism/defines.h
-eval.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-eval.$(OBJEXT): $(top_srcdir)/prism/node.h
-eval.$(OBJEXT): $(top_srcdir)/prism/options.h
-eval.$(OBJEXT): $(top_srcdir)/prism/pack.h
-eval.$(OBJEXT): $(top_srcdir)/prism/parser.h
-eval.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-eval.$(OBJEXT): $(top_srcdir)/prism/prism.h
-eval.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-eval.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-eval.$(OBJEXT): {$(VPATH)}assert.h
-eval.$(OBJEXT): {$(VPATH)}atomic.h
-eval.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-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)}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)}id.h
-eval.$(OBJEXT): {$(VPATH)}id_table.h
-eval.$(OBJEXT): {$(VPATH)}intern.h
-eval.$(OBJEXT): {$(VPATH)}internal.h
-eval.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/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/stdckdint.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)}node.h
-eval.$(OBJEXT): {$(VPATH)}onigmo.h
-eval.$(OBJEXT): {$(VPATH)}oniguruma.h
-eval.$(OBJEXT): {$(VPATH)}prism/ast.h
-eval.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-eval.$(OBJEXT): {$(VPATH)}prism/version.h
-eval.$(OBJEXT): {$(VPATH)}prism_compile.h
-eval.$(OBJEXT): {$(VPATH)}probes.dmyh
-eval.$(OBJEXT): {$(VPATH)}probes.h
-eval.$(OBJEXT): {$(VPATH)}probes_helper.h
-eval.$(OBJEXT): {$(VPATH)}ractor.h
-eval.$(OBJEXT): {$(VPATH)}ractor_core.h
-eval.$(OBJEXT): {$(VPATH)}rjit.h
-eval.$(OBJEXT): {$(VPATH)}ruby_assert.h
-eval.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-eval.$(OBJEXT): {$(VPATH)}rubyparser.h
-eval.$(OBJEXT): {$(VPATH)}shape.h
-eval.$(OBJEXT): {$(VPATH)}st.h
-eval.$(OBJEXT): {$(VPATH)}subst.h
-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)}vm_sync.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): $(CCAN_DIR)/check_type/check_type.h
-file.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-file.$(OBJEXT): $(CCAN_DIR)/list/list.h
-file.$(OBJEXT): $(CCAN_DIR)/str/str.h
-file.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-file.$(OBJEXT): $(hdrdir)/ruby/version.h
-file.$(OBJEXT): $(top_srcdir)/internal/array.h
-file.$(OBJEXT): $(top_srcdir)/internal/class.h
-file.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-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/variable.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)}constant.h
-file.$(OBJEXT): {$(VPATH)}defines.h
-file.$(OBJEXT): {$(VPATH)}dln.h
-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/abi.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/packed_struct.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/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/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/stdckdint.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
-file.$(OBJEXT): {$(VPATH)}oniguruma.h
-file.$(OBJEXT): {$(VPATH)}shape.h
-file.$(OBJEXT): {$(VPATH)}st.h
-file.$(OBJEXT): {$(VPATH)}subst.h
-file.$(OBJEXT): {$(VPATH)}thread.h
-file.$(OBJEXT): {$(VPATH)}thread_native.h
-file.$(OBJEXT): {$(VPATH)}util.h
-gc.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-gc.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-gc.$(OBJEXT): $(CCAN_DIR)/list/list.h
-gc.$(OBJEXT): $(CCAN_DIR)/str/str.h
-gc.$(OBJEXT): $(hdrdir)/ruby.h
-gc.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-gc.$(OBJEXT): $(hdrdir)/ruby/version.h
-gc.$(OBJEXT): $(top_srcdir)/internal/array.h
-gc.$(OBJEXT): $(top_srcdir)/internal/basic_operators.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/compile.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): $(top_srcdir)/prism/defines.h
-gc.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-gc.$(OBJEXT): $(top_srcdir)/prism/node.h
-gc.$(OBJEXT): $(top_srcdir)/prism/options.h
-gc.$(OBJEXT): $(top_srcdir)/prism/pack.h
-gc.$(OBJEXT): $(top_srcdir)/prism/parser.h
-gc.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-gc.$(OBJEXT): $(top_srcdir)/prism/prism.h
-gc.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-gc.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-gc.$(OBJEXT): {$(VPATH)}assert.h
-gc.$(OBJEXT): {$(VPATH)}atomic.h
-gc.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-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
-gc.$(OBJEXT): {$(VPATH)}encoding.h
-gc.$(OBJEXT): {$(VPATH)}eval_intern.h
-gc.$(OBJEXT): {$(VPATH)}gc.c
-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/abi.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/packed_struct.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/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/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/stdckdint.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)}iseq.h
-gc.$(OBJEXT): {$(VPATH)}method.h
-gc.$(OBJEXT): {$(VPATH)}missing.h
-gc.$(OBJEXT): {$(VPATH)}node.h
-gc.$(OBJEXT): {$(VPATH)}onigmo.h
-gc.$(OBJEXT): {$(VPATH)}oniguruma.h
-gc.$(OBJEXT): {$(VPATH)}prism/ast.h
-gc.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-gc.$(OBJEXT): {$(VPATH)}prism/version.h
-gc.$(OBJEXT): {$(VPATH)}prism_compile.h
-gc.$(OBJEXT): {$(VPATH)}probes.dmyh
-gc.$(OBJEXT): {$(VPATH)}probes.h
-gc.$(OBJEXT): {$(VPATH)}ractor.h
-gc.$(OBJEXT): {$(VPATH)}ractor_core.h
-gc.$(OBJEXT): {$(VPATH)}re.h
-gc.$(OBJEXT): {$(VPATH)}regenc.h
-gc.$(OBJEXT): {$(VPATH)}regex.h
-gc.$(OBJEXT): {$(VPATH)}regint.h
-gc.$(OBJEXT): {$(VPATH)}rjit.h
-gc.$(OBJEXT): {$(VPATH)}ruby_assert.h
-gc.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-gc.$(OBJEXT): {$(VPATH)}rubyparser.h
-gc.$(OBJEXT): {$(VPATH)}shape.h
-gc.$(OBJEXT): {$(VPATH)}st.h
-gc.$(OBJEXT): {$(VPATH)}subst.h
-gc.$(OBJEXT): {$(VPATH)}symbol.h
-gc.$(OBJEXT): {$(VPATH)}thread.h
-gc.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-gc.$(OBJEXT): {$(VPATH)}thread_native.h
-gc.$(OBJEXT): {$(VPATH)}util.h
-gc.$(OBJEXT): {$(VPATH)}vm_callinfo.h
-gc.$(OBJEXT): {$(VPATH)}vm_core.h
-gc.$(OBJEXT): {$(VPATH)}vm_debug.h
-gc.$(OBJEXT): {$(VPATH)}vm_opts.h
-gc.$(OBJEXT): {$(VPATH)}vm_sync.h
-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/basic_operators.h
-goruby.$(OBJEXT): $(top_srcdir)/internal/bignum.h
-goruby.$(OBJEXT): $(top_srcdir)/internal/bits.h
-goruby.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-goruby.$(OBJEXT): $(top_srcdir)/internal/complex.h
-goruby.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
-goruby.$(OBJEXT): $(top_srcdir)/internal/gc.h
-goruby.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-goruby.$(OBJEXT): $(top_srcdir)/internal/numeric.h
-goruby.$(OBJEXT): $(top_srcdir)/internal/parse.h
-goruby.$(OBJEXT): $(top_srcdir)/internal/rational.h
-goruby.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
-goruby.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-goruby.$(OBJEXT): $(top_srcdir)/internal/serial.h
-goruby.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-goruby.$(OBJEXT): $(top_srcdir)/internal/variable.h
-goruby.$(OBJEXT): $(top_srcdir)/internal/vm.h
-goruby.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-goruby.$(OBJEXT): $(top_srcdir)/prism/defines.h
-goruby.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-goruby.$(OBJEXT): $(top_srcdir)/prism/node.h
-goruby.$(OBJEXT): $(top_srcdir)/prism/options.h
-goruby.$(OBJEXT): $(top_srcdir)/prism/pack.h
-goruby.$(OBJEXT): $(top_srcdir)/prism/parser.h
-goruby.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-goruby.$(OBJEXT): $(top_srcdir)/prism/prism.h
-goruby.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-goruby.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-goruby.$(OBJEXT): {$(VPATH)}assert.h
-goruby.$(OBJEXT): {$(VPATH)}atomic.h
-goruby.$(OBJEXT): {$(VPATH)}backward.h
-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)}constant.h
-goruby.$(OBJEXT): {$(VPATH)}defines.h
-goruby.$(OBJEXT): {$(VPATH)}encoding.h
-goruby.$(OBJEXT): {$(VPATH)}golf_prelude.c
-goruby.$(OBJEXT): {$(VPATH)}goruby.c
-goruby.$(OBJEXT): {$(VPATH)}id.h
-goruby.$(OBJEXT): {$(VPATH)}id_table.h
-goruby.$(OBJEXT): {$(VPATH)}intern.h
-goruby.$(OBJEXT): {$(VPATH)}internal.h
-goruby.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/encoding/coderange.h
-goruby.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
-goruby.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
-goruby.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
-goruby.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
-goruby.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
-goruby.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
-goruby.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
-goruby.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.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/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/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/stdckdint.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)}onigmo.h
-goruby.$(OBJEXT): {$(VPATH)}oniguruma.h
-goruby.$(OBJEXT): {$(VPATH)}prism/ast.h
-goruby.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-goruby.$(OBJEXT): {$(VPATH)}prism/version.h
-goruby.$(OBJEXT): {$(VPATH)}prism_compile.h
-goruby.$(OBJEXT): {$(VPATH)}ruby_assert.h
-goruby.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-goruby.$(OBJEXT): {$(VPATH)}rubyparser.h
-goruby.$(OBJEXT): {$(VPATH)}shape.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
-goruby.$(OBJEXT): {$(VPATH)}vm_opts.h
-hash.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-hash.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-hash.$(OBJEXT): $(CCAN_DIR)/list/list.h
-hash.$(OBJEXT): $(CCAN_DIR)/str/str.h
-hash.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-hash.$(OBJEXT): $(hdrdir)/ruby/version.h
-hash.$(OBJEXT): $(top_srcdir)/internal/array.h
-hash.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-hash.$(OBJEXT): $(top_srcdir)/internal/bignum.h
-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/imemo.h
-hash.$(OBJEXT): $(top_srcdir)/internal/object.h
-hash.$(OBJEXT): $(top_srcdir)/internal/proc.h
-hash.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-hash.$(OBJEXT): $(top_srcdir)/internal/serial.h
-hash.$(OBJEXT): $(top_srcdir)/internal/st.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/thread.h
-hash.$(OBJEXT): $(top_srcdir)/internal/time.h
-hash.$(OBJEXT): $(top_srcdir)/internal/variable.h
-hash.$(OBJEXT): $(top_srcdir)/internal/vm.h
-hash.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-hash.$(OBJEXT): $(top_srcdir)/prism/defines.h
-hash.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-hash.$(OBJEXT): $(top_srcdir)/prism/node.h
-hash.$(OBJEXT): $(top_srcdir)/prism/options.h
-hash.$(OBJEXT): $(top_srcdir)/prism/pack.h
-hash.$(OBJEXT): $(top_srcdir)/prism/parser.h
-hash.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-hash.$(OBJEXT): $(top_srcdir)/prism/prism.h
-hash.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-hash.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-hash.$(OBJEXT): {$(VPATH)}assert.h
-hash.$(OBJEXT): {$(VPATH)}atomic.h
-hash.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-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)}constant.h
-hash.$(OBJEXT): {$(VPATH)}debug_counter.h
-hash.$(OBJEXT): {$(VPATH)}defines.h
-hash.$(OBJEXT): {$(VPATH)}encoding.h
-hash.$(OBJEXT): {$(VPATH)}hash.c
-hash.$(OBJEXT): {$(VPATH)}id.h
-hash.$(OBJEXT): {$(VPATH)}id_table.h
-hash.$(OBJEXT): {$(VPATH)}intern.h
-hash.$(OBJEXT): {$(VPATH)}internal.h
-hash.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/scan_args.h
-hash.$(OBJEXT): {$(VPATH)}internal/special_consts.h
-hash.$(OBJEXT): {$(VPATH)}internal/st.h
-hash.$(OBJEXT): {$(VPATH)}internal/static_assert.h
-hash.$(OBJEXT): {$(VPATH)}internal/stdalign.h
-hash.$(OBJEXT): {$(VPATH)}internal/stdbool.h
-hash.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
-hash.$(OBJEXT): {$(VPATH)}internal/symbol.h
-hash.$(OBJEXT): {$(VPATH)}internal/value.h
-hash.$(OBJEXT): {$(VPATH)}internal/value_type.h
-hash.$(OBJEXT): {$(VPATH)}internal/variable.h
-hash.$(OBJEXT): {$(VPATH)}internal/warning_push.h
-hash.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
-hash.$(OBJEXT): {$(VPATH)}iseq.h
-hash.$(OBJEXT): {$(VPATH)}method.h
-hash.$(OBJEXT): {$(VPATH)}missing.h
-hash.$(OBJEXT): {$(VPATH)}node.h
-hash.$(OBJEXT): {$(VPATH)}onigmo.h
-hash.$(OBJEXT): {$(VPATH)}oniguruma.h
-hash.$(OBJEXT): {$(VPATH)}prism/ast.h
-hash.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-hash.$(OBJEXT): {$(VPATH)}prism/version.h
-hash.$(OBJEXT): {$(VPATH)}prism_compile.h
-hash.$(OBJEXT): {$(VPATH)}probes.dmyh
-hash.$(OBJEXT): {$(VPATH)}probes.h
-hash.$(OBJEXT): {$(VPATH)}ractor.h
-hash.$(OBJEXT): {$(VPATH)}ruby_assert.h
-hash.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-hash.$(OBJEXT): {$(VPATH)}rubyparser.h
-hash.$(OBJEXT): {$(VPATH)}shape.h
-hash.$(OBJEXT): {$(VPATH)}st.h
-hash.$(OBJEXT): {$(VPATH)}subst.h
-hash.$(OBJEXT): {$(VPATH)}symbol.h
-hash.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-hash.$(OBJEXT): {$(VPATH)}thread_native.h
-hash.$(OBJEXT): {$(VPATH)}util.h
-hash.$(OBJEXT): {$(VPATH)}vm_core.h
-hash.$(OBJEXT): {$(VPATH)}vm_debug.h
-hash.$(OBJEXT): {$(VPATH)}vm_opts.h
-hash.$(OBJEXT): {$(VPATH)}vm_sync.h
-imemo.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-imemo.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-imemo.$(OBJEXT): $(CCAN_DIR)/list/list.h
-imemo.$(OBJEXT): $(CCAN_DIR)/str/str.h
-imemo.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-imemo.$(OBJEXT): $(top_srcdir)/internal/array.h
-imemo.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-imemo.$(OBJEXT): $(top_srcdir)/internal/class.h
-imemo.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-imemo.$(OBJEXT): $(top_srcdir)/internal/gc.h
-imemo.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-imemo.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-imemo.$(OBJEXT): $(top_srcdir)/internal/serial.h
-imemo.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-imemo.$(OBJEXT): $(top_srcdir)/internal/variable.h
-imemo.$(OBJEXT): $(top_srcdir)/internal/vm.h
-imemo.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-imemo.$(OBJEXT): {$(VPATH)}assert.h
-imemo.$(OBJEXT): {$(VPATH)}atomic.h
-imemo.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-imemo.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
-imemo.$(OBJEXT): {$(VPATH)}backward/2/bool.h
-imemo.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
-imemo.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
-imemo.$(OBJEXT): {$(VPATH)}backward/2/limits.h
-imemo.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
-imemo.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
-imemo.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
-imemo.$(OBJEXT): {$(VPATH)}config.h
-imemo.$(OBJEXT): {$(VPATH)}constant.h
-imemo.$(OBJEXT): {$(VPATH)}debug_counter.h
-imemo.$(OBJEXT): {$(VPATH)}defines.h
-imemo.$(OBJEXT): {$(VPATH)}encoding.h
-imemo.$(OBJEXT): {$(VPATH)}id.h
-imemo.$(OBJEXT): {$(VPATH)}id_table.h
-imemo.$(OBJEXT): {$(VPATH)}imemo.c
-imemo.$(OBJEXT): {$(VPATH)}intern.h
-imemo.$(OBJEXT): {$(VPATH)}internal.h
-imemo.$(OBJEXT): {$(VPATH)}internal/abi.h
-imemo.$(OBJEXT): {$(VPATH)}internal/anyargs.h
-imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
-imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
-imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
-imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
-imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
-imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
-imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
-imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
-imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
-imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
-imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
-imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
-imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
-imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
-imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
-imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
-imemo.$(OBJEXT): {$(VPATH)}internal/assume.h
-imemo.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
-imemo.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
-imemo.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
-imemo.$(OBJEXT): {$(VPATH)}internal/attr/const.h
-imemo.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
-imemo.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
-imemo.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
-imemo.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
-imemo.$(OBJEXT): {$(VPATH)}internal/attr/error.h
-imemo.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
-imemo.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
-imemo.$(OBJEXT): {$(VPATH)}internal/attr/format.h
-imemo.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
-imemo.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
-imemo.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
-imemo.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
-imemo.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
-imemo.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
-imemo.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
-imemo.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
-imemo.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
-imemo.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
-imemo.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
-imemo.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
-imemo.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
-imemo.$(OBJEXT): {$(VPATH)}internal/cast.h
-imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
-imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
-imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
-imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
-imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
-imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
-imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
-imemo.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
-imemo.$(OBJEXT): {$(VPATH)}internal/config.h
-imemo.$(OBJEXT): {$(VPATH)}internal/constant_p.h
-imemo.$(OBJEXT): {$(VPATH)}internal/core.h
-imemo.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
-imemo.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
-imemo.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
-imemo.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
-imemo.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
-imemo.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
-imemo.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
-imemo.$(OBJEXT): {$(VPATH)}internal/core/robject.h
-imemo.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
-imemo.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
-imemo.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
-imemo.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
-imemo.$(OBJEXT): {$(VPATH)}internal/ctype.h
-imemo.$(OBJEXT): {$(VPATH)}internal/dllexport.h
-imemo.$(OBJEXT): {$(VPATH)}internal/dosish.h
-imemo.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
-imemo.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
-imemo.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
-imemo.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
-imemo.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
-imemo.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
-imemo.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
-imemo.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
-imemo.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
-imemo.$(OBJEXT): {$(VPATH)}internal/error.h
-imemo.$(OBJEXT): {$(VPATH)}internal/eval.h
-imemo.$(OBJEXT): {$(VPATH)}internal/event.h
-imemo.$(OBJEXT): {$(VPATH)}internal/fl_type.h
-imemo.$(OBJEXT): {$(VPATH)}internal/gc.h
-imemo.$(OBJEXT): {$(VPATH)}internal/glob.h
-imemo.$(OBJEXT): {$(VPATH)}internal/globals.h
-imemo.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
-imemo.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
-imemo.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
-imemo.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
-imemo.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
-imemo.$(OBJEXT): {$(VPATH)}internal/has/extension.h
-imemo.$(OBJEXT): {$(VPATH)}internal/has/feature.h
-imemo.$(OBJEXT): {$(VPATH)}internal/has/warning.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/array.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/class.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/error.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/file.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/io.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/load.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/object.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/process.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/random.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/range.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/re.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/select.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/string.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/time.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
-imemo.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
-imemo.$(OBJEXT): {$(VPATH)}internal/interpreter.h
-imemo.$(OBJEXT): {$(VPATH)}internal/iterator.h
-imemo.$(OBJEXT): {$(VPATH)}internal/memory.h
-imemo.$(OBJEXT): {$(VPATH)}internal/method.h
-imemo.$(OBJEXT): {$(VPATH)}internal/module.h
-imemo.$(OBJEXT): {$(VPATH)}internal/newobj.h
-imemo.$(OBJEXT): {$(VPATH)}internal/scan_args.h
-imemo.$(OBJEXT): {$(VPATH)}internal/special_consts.h
-imemo.$(OBJEXT): {$(VPATH)}internal/static_assert.h
-imemo.$(OBJEXT): {$(VPATH)}internal/stdalign.h
-imemo.$(OBJEXT): {$(VPATH)}internal/stdbool.h
-imemo.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
-imemo.$(OBJEXT): {$(VPATH)}internal/symbol.h
-imemo.$(OBJEXT): {$(VPATH)}internal/value.h
-imemo.$(OBJEXT): {$(VPATH)}internal/value_type.h
-imemo.$(OBJEXT): {$(VPATH)}internal/variable.h
-imemo.$(OBJEXT): {$(VPATH)}internal/warning_push.h
-imemo.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
-imemo.$(OBJEXT): {$(VPATH)}method.h
-imemo.$(OBJEXT): {$(VPATH)}missing.h
-imemo.$(OBJEXT): {$(VPATH)}node.h
-imemo.$(OBJEXT): {$(VPATH)}onigmo.h
-imemo.$(OBJEXT): {$(VPATH)}oniguruma.h
-imemo.$(OBJEXT): {$(VPATH)}ruby_assert.h
-imemo.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-imemo.$(OBJEXT): {$(VPATH)}rubyparser.h
-imemo.$(OBJEXT): {$(VPATH)}shape.h
-imemo.$(OBJEXT): {$(VPATH)}st.h
-imemo.$(OBJEXT): {$(VPATH)}subst.h
-imemo.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-imemo.$(OBJEXT): {$(VPATH)}thread_native.h
-imemo.$(OBJEXT): {$(VPATH)}vm_callinfo.h
-imemo.$(OBJEXT): {$(VPATH)}vm_core.h
-imemo.$(OBJEXT): {$(VPATH)}vm_debug.h
-imemo.$(OBJEXT): {$(VPATH)}vm_opts.h
-imemo.$(OBJEXT): {$(VPATH)}vm_sync.h
-inits.$(OBJEXT): $(hdrdir)/ruby.h
-inits.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-inits.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-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/abi.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/packed_struct.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/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/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/stdckdint.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
-inits.$(OBJEXT): {$(VPATH)}subst.h
-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/ruby.h
-io.$(OBJEXT): $(hdrdir)/ruby/version.h
-io.$(OBJEXT): $(top_srcdir)/internal/array.h
-io.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-io.$(OBJEXT): $(top_srcdir)/internal/bignum.h
-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/sanitizers.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)}debug_counter.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/abi.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/packed_struct.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/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/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/stdckdint.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)}rubyparser.h
-io.$(OBJEXT): {$(VPATH)}shape.h
-io.$(OBJEXT): {$(VPATH)}st.h
-io.$(OBJEXT): {$(VPATH)}subst.h
-io.$(OBJEXT): {$(VPATH)}thread.h
-io.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-io.$(OBJEXT): {$(VPATH)}thread_native.h
-io.$(OBJEXT): {$(VPATH)}util.h
-io.$(OBJEXT): {$(VPATH)}vm_core.h
-io.$(OBJEXT): {$(VPATH)}vm_debug.h
-io.$(OBJEXT): {$(VPATH)}vm_opts.h
-io.$(OBJEXT): {$(VPATH)}vm_sync.h
-io_buffer.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-io_buffer.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-io_buffer.$(OBJEXT): $(CCAN_DIR)/list/list.h
-io_buffer.$(OBJEXT): $(CCAN_DIR)/str/str.h
-io_buffer.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-io_buffer.$(OBJEXT): $(hdrdir)/ruby/version.h
-io_buffer.$(OBJEXT): $(top_srcdir)/internal/array.h
-io_buffer.$(OBJEXT): $(top_srcdir)/internal/bignum.h
-io_buffer.$(OBJEXT): $(top_srcdir)/internal/bits.h
-io_buffer.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-io_buffer.$(OBJEXT): $(top_srcdir)/internal/error.h
-io_buffer.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
-io_buffer.$(OBJEXT): $(top_srcdir)/internal/numeric.h
-io_buffer.$(OBJEXT): $(top_srcdir)/internal/serial.h
-io_buffer.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-io_buffer.$(OBJEXT): $(top_srcdir)/internal/string.h
-io_buffer.$(OBJEXT): $(top_srcdir)/internal/thread.h
-io_buffer.$(OBJEXT): $(top_srcdir)/internal/vm.h
-io_buffer.$(OBJEXT): {$(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/abi.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/packed_struct.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/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/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/stdckdint.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
-io_buffer.$(OBJEXT): {$(VPATH)}thread_native.h
-iseq.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-iseq.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-iseq.$(OBJEXT): $(CCAN_DIR)/list/list.h
-iseq.$(OBJEXT): $(CCAN_DIR)/str/str.h
-iseq.$(OBJEXT): $(hdrdir)/ruby.h
-iseq.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-iseq.$(OBJEXT): $(hdrdir)/ruby/version.h
-iseq.$(OBJEXT): $(top_srcdir)/internal/array.h
-iseq.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-iseq.$(OBJEXT): $(top_srcdir)/internal/bignum.h
-iseq.$(OBJEXT): $(top_srcdir)/internal/bits.h
-iseq.$(OBJEXT): $(top_srcdir)/internal/class.h
-iseq.$(OBJEXT): $(top_srcdir)/internal/compile.h
-iseq.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-iseq.$(OBJEXT): $(top_srcdir)/internal/complex.h
-iseq.$(OBJEXT): $(top_srcdir)/internal/error.h
-iseq.$(OBJEXT): $(top_srcdir)/internal/file.h
-iseq.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
-iseq.$(OBJEXT): $(top_srcdir)/internal/gc.h
-iseq.$(OBJEXT): $(top_srcdir)/internal/hash.h
-iseq.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-iseq.$(OBJEXT): $(top_srcdir)/internal/io.h
-iseq.$(OBJEXT): $(top_srcdir)/internal/numeric.h
-iseq.$(OBJEXT): $(top_srcdir)/internal/parse.h
-iseq.$(OBJEXT): $(top_srcdir)/internal/rational.h
-iseq.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
-iseq.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-iseq.$(OBJEXT): $(top_srcdir)/internal/serial.h
-iseq.$(OBJEXT): $(top_srcdir)/internal/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): $(top_srcdir)/prism/defines.h
-iseq.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-iseq.$(OBJEXT): $(top_srcdir)/prism/node.h
-iseq.$(OBJEXT): $(top_srcdir)/prism/options.h
-iseq.$(OBJEXT): $(top_srcdir)/prism/pack.h
-iseq.$(OBJEXT): $(top_srcdir)/prism/parser.h
-iseq.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-iseq.$(OBJEXT): $(top_srcdir)/prism/prism.h
-iseq.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-iseq.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-iseq.$(OBJEXT): {$(VPATH)}assert.h
-iseq.$(OBJEXT): {$(VPATH)}atomic.h
-iseq.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-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)}debug_counter.h
-iseq.$(OBJEXT): {$(VPATH)}defines.h
-iseq.$(OBJEXT): {$(VPATH)}encoding.h
-iseq.$(OBJEXT): {$(VPATH)}eval_intern.h
-iseq.$(OBJEXT): {$(VPATH)}id.h
-iseq.$(OBJEXT): {$(VPATH)}id_table.h
-iseq.$(OBJEXT): {$(VPATH)}insns.def
-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/abi.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/packed_struct.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/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/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/stdckdint.h
-iseq.$(OBJEXT): {$(VPATH)}internal/symbol.h
-iseq.$(OBJEXT): {$(VPATH)}internal/value.h
-iseq.$(OBJEXT): {$(VPATH)}internal/value_type.h
-iseq.$(OBJEXT): {$(VPATH)}internal/variable.h
-iseq.$(OBJEXT): {$(VPATH)}internal/warning_push.h
-iseq.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
-iseq.$(OBJEXT): {$(VPATH)}io.h
-iseq.$(OBJEXT): {$(VPATH)}iseq.c
-iseq.$(OBJEXT): {$(VPATH)}iseq.h
-iseq.$(OBJEXT): {$(VPATH)}method.h
-iseq.$(OBJEXT): {$(VPATH)}missing.h
-iseq.$(OBJEXT): {$(VPATH)}node.h
-iseq.$(OBJEXT): {$(VPATH)}onigmo.h
-iseq.$(OBJEXT): {$(VPATH)}oniguruma.h
-iseq.$(OBJEXT): {$(VPATH)}prism/ast.h
-iseq.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-iseq.$(OBJEXT): {$(VPATH)}prism/prism.h
-iseq.$(OBJEXT): {$(VPATH)}prism/version.h
-iseq.$(OBJEXT): {$(VPATH)}prism_compile.h
-iseq.$(OBJEXT): {$(VPATH)}ractor.h
-iseq.$(OBJEXT): {$(VPATH)}rjit.h
-iseq.$(OBJEXT): {$(VPATH)}ruby_assert.h
-iseq.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-iseq.$(OBJEXT): {$(VPATH)}rubyparser.h
-iseq.$(OBJEXT): {$(VPATH)}shape.h
-iseq.$(OBJEXT): {$(VPATH)}st.h
-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_debug.h
-iseq.$(OBJEXT): {$(VPATH)}vm_opts.h
-iseq.$(OBJEXT): {$(VPATH)}vm_sync.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/ruby.h
-load.$(OBJEXT): $(hdrdir)/ruby/version.h
-load.$(OBJEXT): $(top_srcdir)/internal/array.h
-load.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-load.$(OBJEXT): $(top_srcdir)/internal/bignum.h
-load.$(OBJEXT): $(top_srcdir)/internal/bits.h
-load.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-load.$(OBJEXT): $(top_srcdir)/internal/complex.h
-load.$(OBJEXT): $(top_srcdir)/internal/dir.h
-load.$(OBJEXT): $(top_srcdir)/internal/error.h
-load.$(OBJEXT): $(top_srcdir)/internal/file.h
-load.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
-load.$(OBJEXT): $(top_srcdir)/internal/gc.h
-load.$(OBJEXT): $(top_srcdir)/internal/hash.h
-load.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-load.$(OBJEXT): $(top_srcdir)/internal/load.h
-load.$(OBJEXT): $(top_srcdir)/internal/numeric.h
-load.$(OBJEXT): $(top_srcdir)/internal/parse.h
-load.$(OBJEXT): $(top_srcdir)/internal/rational.h
-load.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
-load.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-load.$(OBJEXT): $(top_srcdir)/internal/serial.h
-load.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-load.$(OBJEXT): $(top_srcdir)/internal/string.h
-load.$(OBJEXT): $(top_srcdir)/internal/thread.h
-load.$(OBJEXT): $(top_srcdir)/internal/variable.h
-load.$(OBJEXT): $(top_srcdir)/internal/vm.h
-load.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-load.$(OBJEXT): $(top_srcdir)/prism/defines.h
-load.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-load.$(OBJEXT): $(top_srcdir)/prism/node.h
-load.$(OBJEXT): $(top_srcdir)/prism/options.h
-load.$(OBJEXT): $(top_srcdir)/prism/pack.h
-load.$(OBJEXT): $(top_srcdir)/prism/parser.h
-load.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-load.$(OBJEXT): $(top_srcdir)/prism/prism.h
-load.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-load.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-load.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-load.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-load.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-load.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-load.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-load.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-load.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-load.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-load.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-load.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-load.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-load.$(OBJEXT): {$(VPATH)}assert.h
-load.$(OBJEXT): {$(VPATH)}atomic.h
-load.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-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/abi.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/packed_struct.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/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/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/stdckdint.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
-load.$(OBJEXT): {$(VPATH)}missing.h
-load.$(OBJEXT): {$(VPATH)}node.h
-load.$(OBJEXT): {$(VPATH)}onigmo.h
-load.$(OBJEXT): {$(VPATH)}oniguruma.h
-load.$(OBJEXT): {$(VPATH)}prism/ast.h
-load.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-load.$(OBJEXT): {$(VPATH)}prism/version.h
-load.$(OBJEXT): {$(VPATH)}prism_compile.h
-load.$(OBJEXT): {$(VPATH)}probes.dmyh
-load.$(OBJEXT): {$(VPATH)}probes.h
-load.$(OBJEXT): {$(VPATH)}ruby_assert.h
-load.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-load.$(OBJEXT): {$(VPATH)}rubyparser.h
-load.$(OBJEXT): {$(VPATH)}shape.h
-load.$(OBJEXT): {$(VPATH)}st.h
-load.$(OBJEXT): {$(VPATH)}subst.h
-load.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-load.$(OBJEXT): {$(VPATH)}thread_native.h
-load.$(OBJEXT): {$(VPATH)}util.h
-load.$(OBJEXT): {$(VPATH)}vm_core.h
-load.$(OBJEXT): {$(VPATH)}vm_opts.h
-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/abi.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/packed_struct.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/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/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/stdckdint.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/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/abi.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/packed_struct.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/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/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/stdckdint.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
-localeinit.$(OBJEXT): {$(VPATH)}oniguruma.h
-localeinit.$(OBJEXT): {$(VPATH)}st.h
-localeinit.$(OBJEXT): {$(VPATH)}subst.h
-main.$(OBJEXT): $(hdrdir)/ruby.h
-main.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-main.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-main.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-main.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-main.$(OBJEXT): {$(VPATH)}assert.h
-main.$(OBJEXT): {$(VPATH)}backward.h
-main.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-main.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
-main.$(OBJEXT): {$(VPATH)}backward/2/bool.h
-main.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
-main.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
-main.$(OBJEXT): {$(VPATH)}backward/2/limits.h
-main.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
-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/abi.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/packed_struct.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/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/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/stdckdint.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)}st.h
-main.$(OBJEXT): {$(VPATH)}subst.h
-main.$(OBJEXT): {$(VPATH)}vm_debug.h
-marshal.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-marshal.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-marshal.$(OBJEXT): $(CCAN_DIR)/list/list.h
-marshal.$(OBJEXT): $(CCAN_DIR)/str/str.h
-marshal.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-marshal.$(OBJEXT): $(hdrdir)/ruby/version.h
-marshal.$(OBJEXT): $(top_srcdir)/internal/array.h
-marshal.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-marshal.$(OBJEXT): $(top_srcdir)/internal/bignum.h
-marshal.$(OBJEXT): $(top_srcdir)/internal/bits.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/fixnum.h
-marshal.$(OBJEXT): $(top_srcdir)/internal/gc.h
-marshal.$(OBJEXT): $(top_srcdir)/internal/hash.h
-marshal.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-marshal.$(OBJEXT): $(top_srcdir)/internal/numeric.h
-marshal.$(OBJEXT): $(top_srcdir)/internal/object.h
-marshal.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-marshal.$(OBJEXT): $(top_srcdir)/internal/serial.h
-marshal.$(OBJEXT): $(top_srcdir)/internal/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/variable.h
-marshal.$(OBJEXT): $(top_srcdir)/internal/vm.h
-marshal.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-marshal.$(OBJEXT): {$(VPATH)}assert.h
-marshal.$(OBJEXT): {$(VPATH)}atomic.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)}constant.h
-marshal.$(OBJEXT): {$(VPATH)}debug_counter.h
-marshal.$(OBJEXT): {$(VPATH)}defines.h
-marshal.$(OBJEXT): {$(VPATH)}encindex.h
-marshal.$(OBJEXT): {$(VPATH)}encoding.h
-marshal.$(OBJEXT): {$(VPATH)}id.h
-marshal.$(OBJEXT): {$(VPATH)}id_table.h
-marshal.$(OBJEXT): {$(VPATH)}intern.h
-marshal.$(OBJEXT): {$(VPATH)}internal.h
-marshal.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/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/stdckdint.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)}method.h
-marshal.$(OBJEXT): {$(VPATH)}missing.h
-marshal.$(OBJEXT): {$(VPATH)}node.h
-marshal.$(OBJEXT): {$(VPATH)}onigmo.h
-marshal.$(OBJEXT): {$(VPATH)}oniguruma.h
-marshal.$(OBJEXT): {$(VPATH)}ruby_assert.h
-marshal.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-marshal.$(OBJEXT): {$(VPATH)}rubyparser.h
-marshal.$(OBJEXT): {$(VPATH)}shape.h
-marshal.$(OBJEXT): {$(VPATH)}st.h
-marshal.$(OBJEXT): {$(VPATH)}subst.h
-marshal.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-marshal.$(OBJEXT): {$(VPATH)}thread_native.h
-marshal.$(OBJEXT): {$(VPATH)}util.h
-marshal.$(OBJEXT): {$(VPATH)}vm_core.h
-marshal.$(OBJEXT): {$(VPATH)}vm_debug.h
-marshal.$(OBJEXT): {$(VPATH)}vm_opts.h
-marshal.$(OBJEXT): {$(VPATH)}vm_sync.h
-math.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-math.$(OBJEXT): $(top_srcdir)/internal/bignum.h
-math.$(OBJEXT): $(top_srcdir)/internal/class.h
-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/variable.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)}constant.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/abi.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/packed_struct.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/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/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/stdckdint.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)}shape.h
-math.$(OBJEXT): {$(VPATH)}st.h
-math.$(OBJEXT): {$(VPATH)}subst.h
-memory_view.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-memory_view.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-memory_view.$(OBJEXT): $(CCAN_DIR)/list/list.h
-memory_view.$(OBJEXT): $(CCAN_DIR)/str/str.h
-memory_view.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-memory_view.$(OBJEXT): $(top_srcdir)/internal/array.h
-memory_view.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-memory_view.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-memory_view.$(OBJEXT): $(top_srcdir)/internal/gc.h
-memory_view.$(OBJEXT): $(top_srcdir)/internal/hash.h
-memory_view.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-memory_view.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-memory_view.$(OBJEXT): $(top_srcdir)/internal/serial.h
-memory_view.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-memory_view.$(OBJEXT): $(top_srcdir)/internal/variable.h
-memory_view.$(OBJEXT): $(top_srcdir)/internal/vm.h
-memory_view.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-memory_view.$(OBJEXT): {$(VPATH)}assert.h
-memory_view.$(OBJEXT): {$(VPATH)}atomic.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/gcc_version_since.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)}encoding.h
-memory_view.$(OBJEXT): {$(VPATH)}id.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/abi.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/packed_struct.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/encoding/coderange.h
-memory_view.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
-memory_view.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
-memory_view.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
-memory_view.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
-memory_view.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
-memory_view.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
-memory_view.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
-memory_view.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.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/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/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/stdckdint.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)}method.h
-memory_view.$(OBJEXT): {$(VPATH)}missing.h
-memory_view.$(OBJEXT): {$(VPATH)}node.h
-memory_view.$(OBJEXT): {$(VPATH)}onigmo.h
-memory_view.$(OBJEXT): {$(VPATH)}oniguruma.h
-memory_view.$(OBJEXT): {$(VPATH)}ruby_assert.h
-memory_view.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-memory_view.$(OBJEXT): {$(VPATH)}rubyparser.h
-memory_view.$(OBJEXT): {$(VPATH)}shape.h
-memory_view.$(OBJEXT): {$(VPATH)}st.h
-memory_view.$(OBJEXT): {$(VPATH)}subst.h
-memory_view.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-memory_view.$(OBJEXT): {$(VPATH)}thread_native.h
-memory_view.$(OBJEXT): {$(VPATH)}util.h
-memory_view.$(OBJEXT): {$(VPATH)}vm_core.h
-memory_view.$(OBJEXT): {$(VPATH)}vm_debug.h
-memory_view.$(OBJEXT): {$(VPATH)}vm_opts.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/ruby.h
-miniinit.$(OBJEXT): $(srcdir)/rjit_c.rb
-miniinit.$(OBJEXT): $(top_srcdir)/internal/array.h
-miniinit.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-miniinit.$(OBJEXT): $(top_srcdir)/internal/bignum.h
-miniinit.$(OBJEXT): $(top_srcdir)/internal/bits.h
-miniinit.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-miniinit.$(OBJEXT): $(top_srcdir)/internal/complex.h
-miniinit.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
-miniinit.$(OBJEXT): $(top_srcdir)/internal/gc.h
-miniinit.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-miniinit.$(OBJEXT): $(top_srcdir)/internal/numeric.h
-miniinit.$(OBJEXT): $(top_srcdir)/internal/parse.h
-miniinit.$(OBJEXT): $(top_srcdir)/internal/rational.h
-miniinit.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
-miniinit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-miniinit.$(OBJEXT): $(top_srcdir)/internal/serial.h
-miniinit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-miniinit.$(OBJEXT): $(top_srcdir)/internal/variable.h
-miniinit.$(OBJEXT): $(top_srcdir)/internal/vm.h
-miniinit.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-miniinit.$(OBJEXT): $(top_srcdir)/prism/defines.h
-miniinit.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-miniinit.$(OBJEXT): $(top_srcdir)/prism/node.h
-miniinit.$(OBJEXT): $(top_srcdir)/prism/options.h
-miniinit.$(OBJEXT): $(top_srcdir)/prism/pack.h
-miniinit.$(OBJEXT): $(top_srcdir)/prism/parser.h
-miniinit.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-miniinit.$(OBJEXT): $(top_srcdir)/prism/prism.h
-miniinit.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-miniinit.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-miniinit.$(OBJEXT): {$(VPATH)}array.rb
-miniinit.$(OBJEXT): {$(VPATH)}assert.h
-miniinit.$(OBJEXT): {$(VPATH)}ast.rb
-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)}constant.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)}id_table.h
-miniinit.$(OBJEXT): {$(VPATH)}intern.h
-miniinit.$(OBJEXT): {$(VPATH)}internal.h
-miniinit.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/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/stdckdint.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)}prism/ast.h
-miniinit.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-miniinit.$(OBJEXT): {$(VPATH)}prism/version.h
-miniinit.$(OBJEXT): {$(VPATH)}prism_compile.h
-miniinit.$(OBJEXT): {$(VPATH)}ractor.rb
-miniinit.$(OBJEXT): {$(VPATH)}rjit.rb
-miniinit.$(OBJEXT): {$(VPATH)}rjit_c.rb
-miniinit.$(OBJEXT): {$(VPATH)}ruby_assert.h
-miniinit.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-miniinit.$(OBJEXT): {$(VPATH)}rubyparser.h
-miniinit.$(OBJEXT): {$(VPATH)}shape.h
-miniinit.$(OBJEXT): {$(VPATH)}st.h
-miniinit.$(OBJEXT): {$(VPATH)}subst.h
-miniinit.$(OBJEXT): {$(VPATH)}symbol.rb
-miniinit.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-miniinit.$(OBJEXT): {$(VPATH)}thread_native.h
-miniinit.$(OBJEXT): {$(VPATH)}thread_sync.rb
-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
-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/ruby.h
-node.$(OBJEXT): $(top_srcdir)/internal/array.h
-node.$(OBJEXT): $(top_srcdir)/internal/basic_operators.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/sanitizers.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)}defines.h
-node.$(OBJEXT): {$(VPATH)}encoding.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/abi.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/packed_struct.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/encoding/coderange.h
-node.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
-node.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
-node.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
-node.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
-node.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
-node.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
-node.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
-node.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.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/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/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/stdckdint.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
-node.$(OBJEXT): {$(VPATH)}node.h
-node.$(OBJEXT): {$(VPATH)}node_name.inc
-node.$(OBJEXT): {$(VPATH)}onigmo.h
-node.$(OBJEXT): {$(VPATH)}oniguruma.h
-node.$(OBJEXT): {$(VPATH)}ruby_assert.h
-node.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-node.$(OBJEXT): {$(VPATH)}rubyparser.h
-node.$(OBJEXT): {$(VPATH)}shape.h
-node.$(OBJEXT): {$(VPATH)}st.h
-node.$(OBJEXT): {$(VPATH)}subst.h
-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
-node_dump.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-node_dump.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-node_dump.$(OBJEXT): $(CCAN_DIR)/list/list.h
-node_dump.$(OBJEXT): $(CCAN_DIR)/str/str.h
-node_dump.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-node_dump.$(OBJEXT): $(top_srcdir)/internal/array.h
-node_dump.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-node_dump.$(OBJEXT): $(top_srcdir)/internal/bignum.h
-node_dump.$(OBJEXT): $(top_srcdir)/internal/bits.h
-node_dump.$(OBJEXT): $(top_srcdir)/internal/class.h
-node_dump.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-node_dump.$(OBJEXT): $(top_srcdir)/internal/complex.h
-node_dump.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
-node_dump.$(OBJEXT): $(top_srcdir)/internal/gc.h
-node_dump.$(OBJEXT): $(top_srcdir)/internal/hash.h
-node_dump.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-node_dump.$(OBJEXT): $(top_srcdir)/internal/numeric.h
-node_dump.$(OBJEXT): $(top_srcdir)/internal/parse.h
-node_dump.$(OBJEXT): $(top_srcdir)/internal/rational.h
-node_dump.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
-node_dump.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-node_dump.$(OBJEXT): $(top_srcdir)/internal/serial.h
-node_dump.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-node_dump.$(OBJEXT): $(top_srcdir)/internal/variable.h
-node_dump.$(OBJEXT): $(top_srcdir)/internal/vm.h
-node_dump.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-node_dump.$(OBJEXT): {$(VPATH)}assert.h
-node_dump.$(OBJEXT): {$(VPATH)}atomic.h
-node_dump.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-node_dump.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
-node_dump.$(OBJEXT): {$(VPATH)}backward/2/bool.h
-node_dump.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
-node_dump.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
-node_dump.$(OBJEXT): {$(VPATH)}backward/2/limits.h
-node_dump.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
-node_dump.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
-node_dump.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
-node_dump.$(OBJEXT): {$(VPATH)}config.h
-node_dump.$(OBJEXT): {$(VPATH)}constant.h
-node_dump.$(OBJEXT): {$(VPATH)}debug_counter.h
-node_dump.$(OBJEXT): {$(VPATH)}defines.h
-node_dump.$(OBJEXT): {$(VPATH)}encoding.h
-node_dump.$(OBJEXT): {$(VPATH)}id.h
-node_dump.$(OBJEXT): {$(VPATH)}id_table.h
-node_dump.$(OBJEXT): {$(VPATH)}intern.h
-node_dump.$(OBJEXT): {$(VPATH)}internal.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/abi.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/anyargs.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/assume.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/attr/const.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/attr/error.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/attr/format.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/cast.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/config.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/constant_p.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/core.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/core/robject.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/ctype.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/dllexport.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/dosish.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/error.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/eval.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/event.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/fl_type.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/gc.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/glob.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/globals.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/has/extension.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/has/feature.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/has/warning.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/array.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/class.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/error.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/file.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/io.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/load.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/object.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/process.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/random.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/range.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/re.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/select.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/string.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/time.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/interpreter.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/iterator.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/memory.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/method.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/module.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/newobj.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/scan_args.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/special_consts.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/static_assert.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/stdalign.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/stdbool.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/symbol.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/value.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/value_type.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/variable.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/warning_push.h
-node_dump.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
-node_dump.$(OBJEXT): {$(VPATH)}method.h
-node_dump.$(OBJEXT): {$(VPATH)}missing.h
-node_dump.$(OBJEXT): {$(VPATH)}node.h
-node_dump.$(OBJEXT): {$(VPATH)}node_dump.c
-node_dump.$(OBJEXT): {$(VPATH)}onigmo.h
-node_dump.$(OBJEXT): {$(VPATH)}oniguruma.h
-node_dump.$(OBJEXT): {$(VPATH)}ruby_assert.h
-node_dump.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-node_dump.$(OBJEXT): {$(VPATH)}rubyparser.h
-node_dump.$(OBJEXT): {$(VPATH)}shape.h
-node_dump.$(OBJEXT): {$(VPATH)}st.h
-node_dump.$(OBJEXT): {$(VPATH)}subst.h
-node_dump.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-node_dump.$(OBJEXT): {$(VPATH)}thread_native.h
-node_dump.$(OBJEXT): {$(VPATH)}vm_core.h
-node_dump.$(OBJEXT): {$(VPATH)}vm_debug.h
-node_dump.$(OBJEXT): {$(VPATH)}vm_opts.h
-node_dump.$(OBJEXT): {$(VPATH)}vm_sync.h
-numeric.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-numeric.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-numeric.$(OBJEXT): $(CCAN_DIR)/list/list.h
-numeric.$(OBJEXT): $(CCAN_DIR)/str/str.h
-numeric.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-numeric.$(OBJEXT): $(top_srcdir)/internal/array.h
-numeric.$(OBJEXT): $(top_srcdir)/internal/basic_operators.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/imemo.h
-numeric.$(OBJEXT): $(top_srcdir)/internal/numeric.h
-numeric.$(OBJEXT): $(top_srcdir)/internal/object.h
-numeric.$(OBJEXT): $(top_srcdir)/internal/rational.h
-numeric.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-numeric.$(OBJEXT): $(top_srcdir)/internal/serial.h
-numeric.$(OBJEXT): $(top_srcdir)/internal/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)}atomic.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/abi.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/packed_struct.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/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/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/stdckdint.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)}method.h
-numeric.$(OBJEXT): {$(VPATH)}missing.h
-numeric.$(OBJEXT): {$(VPATH)}node.h
-numeric.$(OBJEXT): {$(VPATH)}numeric.c
-numeric.$(OBJEXT): {$(VPATH)}numeric.rbinc
-numeric.$(OBJEXT): {$(VPATH)}onigmo.h
-numeric.$(OBJEXT): {$(VPATH)}oniguruma.h
-numeric.$(OBJEXT): {$(VPATH)}ruby_assert.h
-numeric.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-numeric.$(OBJEXT): {$(VPATH)}rubyparser.h
-numeric.$(OBJEXT): {$(VPATH)}shape.h
-numeric.$(OBJEXT): {$(VPATH)}st.h
-numeric.$(OBJEXT): {$(VPATH)}subst.h
-numeric.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-numeric.$(OBJEXT): {$(VPATH)}thread_native.h
-numeric.$(OBJEXT): {$(VPATH)}util.h
-numeric.$(OBJEXT): {$(VPATH)}vm_core.h
-numeric.$(OBJEXT): {$(VPATH)}vm_opts.h
-object.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-object.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-object.$(OBJEXT): $(CCAN_DIR)/list/list.h
-object.$(OBJEXT): $(CCAN_DIR)/str/str.h
-object.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-object.$(OBJEXT): $(hdrdir)/ruby/version.h
-object.$(OBJEXT): $(top_srcdir)/internal/array.h
-object.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-object.$(OBJEXT): $(top_srcdir)/internal/bignum.h
-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/imemo.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/sanitizers.h
-object.$(OBJEXT): $(top_srcdir)/internal/serial.h
-object.$(OBJEXT): $(top_srcdir)/internal/st.h
-object.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-object.$(OBJEXT): $(top_srcdir)/internal/string.h
-object.$(OBJEXT): $(top_srcdir)/internal/struct.h
-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)}atomic.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)}debug_counter.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/abi.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/packed_struct.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/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/scan_args.h
-object.$(OBJEXT): {$(VPATH)}internal/special_consts.h
-object.$(OBJEXT): {$(VPATH)}internal/st.h
-object.$(OBJEXT): {$(VPATH)}internal/static_assert.h
-object.$(OBJEXT): {$(VPATH)}internal/stdalign.h
-object.$(OBJEXT): {$(VPATH)}internal/stdbool.h
-object.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
-object.$(OBJEXT): {$(VPATH)}internal/symbol.h
-object.$(OBJEXT): {$(VPATH)}internal/value.h
-object.$(OBJEXT): {$(VPATH)}internal/value_type.h
-object.$(OBJEXT): {$(VPATH)}internal/variable.h
-object.$(OBJEXT): {$(VPATH)}internal/warning_push.h
-object.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
-object.$(OBJEXT): {$(VPATH)}kernel.rbinc
-object.$(OBJEXT): {$(VPATH)}method.h
-object.$(OBJEXT): {$(VPATH)}missing.h
-object.$(OBJEXT): {$(VPATH)}nilclass.rbinc
-object.$(OBJEXT): {$(VPATH)}node.h
-object.$(OBJEXT): {$(VPATH)}object.c
-object.$(OBJEXT): {$(VPATH)}onigmo.h
-object.$(OBJEXT): {$(VPATH)}oniguruma.h
-object.$(OBJEXT): {$(VPATH)}probes.dmyh
-object.$(OBJEXT): {$(VPATH)}probes.h
-object.$(OBJEXT): {$(VPATH)}ruby_assert.h
-object.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-object.$(OBJEXT): {$(VPATH)}rubyparser.h
-object.$(OBJEXT): {$(VPATH)}shape.h
-object.$(OBJEXT): {$(VPATH)}st.h
-object.$(OBJEXT): {$(VPATH)}subst.h
-object.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-object.$(OBJEXT): {$(VPATH)}thread_native.h
-object.$(OBJEXT): {$(VPATH)}util.h
-object.$(OBJEXT): {$(VPATH)}variable.h
-object.$(OBJEXT): {$(VPATH)}vm_core.h
-object.$(OBJEXT): {$(VPATH)}vm_debug.h
-object.$(OBJEXT): {$(VPATH)}vm_opts.h
-object.$(OBJEXT): {$(VPATH)}vm_sync.h
-object.$(OBJEXT): {$(VPATH)}yjit.h
-pack.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-pack.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-pack.$(OBJEXT): $(CCAN_DIR)/list/list.h
-pack.$(OBJEXT): $(CCAN_DIR)/str/str.h
-pack.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-pack.$(OBJEXT): $(top_srcdir)/internal/array.h
-pack.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-pack.$(OBJEXT): $(top_srcdir)/internal/bits.h
-pack.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-pack.$(OBJEXT): $(top_srcdir)/internal/gc.h
-pack.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-pack.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-pack.$(OBJEXT): $(top_srcdir)/internal/serial.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/vm.h
-pack.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-pack.$(OBJEXT): {$(VPATH)}assert.h
-pack.$(OBJEXT): {$(VPATH)}atomic.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.h
-pack.$(OBJEXT): {$(VPATH)}id_table.h
-pack.$(OBJEXT): {$(VPATH)}intern.h
-pack.$(OBJEXT): {$(VPATH)}internal.h
-pack.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/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/stdckdint.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)}method.h
-pack.$(OBJEXT): {$(VPATH)}missing.h
-pack.$(OBJEXT): {$(VPATH)}node.h
-pack.$(OBJEXT): {$(VPATH)}onigmo.h
-pack.$(OBJEXT): {$(VPATH)}oniguruma.h
-pack.$(OBJEXT): {$(VPATH)}pack.c
-pack.$(OBJEXT): {$(VPATH)}pack.rbinc
-pack.$(OBJEXT): {$(VPATH)}ruby_assert.h
-pack.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-pack.$(OBJEXT): {$(VPATH)}rubyparser.h
-pack.$(OBJEXT): {$(VPATH)}shape.h
-pack.$(OBJEXT): {$(VPATH)}st.h
-pack.$(OBJEXT): {$(VPATH)}subst.h
-pack.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-pack.$(OBJEXT): {$(VPATH)}thread_native.h
-pack.$(OBJEXT): {$(VPATH)}util.h
-pack.$(OBJEXT): {$(VPATH)}vm_core.h
-pack.$(OBJEXT): {$(VPATH)}vm_opts.h
-parse.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-parse.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-parse.$(OBJEXT): $(CCAN_DIR)/list/list.h
-parse.$(OBJEXT): $(CCAN_DIR)/str/str.h
-parse.$(OBJEXT): $(hdrdir)/ruby.h
-parse.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-parse.$(OBJEXT): $(hdrdir)/ruby/version.h
-parse.$(OBJEXT): $(top_srcdir)/internal/array.h
-parse.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-parse.$(OBJEXT): $(top_srcdir)/internal/bignum.h
-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/encoding.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/ruby_parser.h
-parse.$(OBJEXT): $(top_srcdir)/internal/sanitizers.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)}atomic.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/abi.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/packed_struct.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/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/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/stdckdint.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)}method.h
-parse.$(OBJEXT): {$(VPATH)}missing.h
-parse.$(OBJEXT): {$(VPATH)}node.h
-parse.$(OBJEXT): {$(VPATH)}onigmo.h
-parse.$(OBJEXT): {$(VPATH)}oniguruma.h
-parse.$(OBJEXT): {$(VPATH)}parse.c
-parse.$(OBJEXT): {$(VPATH)}parse.h
-parse.$(OBJEXT): {$(VPATH)}parse.y
-parse.$(OBJEXT): {$(VPATH)}parser_node.h
-parse.$(OBJEXT): {$(VPATH)}parser_st.h
-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)}ruby_atomic.h
-parse.$(OBJEXT): {$(VPATH)}rubyparser.h
-parse.$(OBJEXT): {$(VPATH)}shape.h
-parse.$(OBJEXT): {$(VPATH)}st.h
-parse.$(OBJEXT): {$(VPATH)}subst.h
-parse.$(OBJEXT): {$(VPATH)}symbol.h
-parse.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-parse.$(OBJEXT): {$(VPATH)}thread_native.h
-parse.$(OBJEXT): {$(VPATH)}util.h
-parse.$(OBJEXT): {$(VPATH)}vm_core.h
-parse.$(OBJEXT): {$(VPATH)}vm_opts.h
-parser_st.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-parser_st.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-parser_st.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-parser_st.$(OBJEXT): {$(VPATH)}assert.h
-parser_st.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-parser_st.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
-parser_st.$(OBJEXT): {$(VPATH)}backward/2/bool.h
-parser_st.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
-parser_st.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
-parser_st.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
-parser_st.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
-parser_st.$(OBJEXT): {$(VPATH)}config.h
-parser_st.$(OBJEXT): {$(VPATH)}defines.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/assume.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/attr/const.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/attr/error.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/attr/format.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/cast.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/config.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/dllexport.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/dosish.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/has/extension.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/has/feature.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/has/warning.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/static_assert.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/stdalign.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/stdbool.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/warning_push.h
-parser_st.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
-parser_st.$(OBJEXT): {$(VPATH)}missing.h
-parser_st.$(OBJEXT): {$(VPATH)}parser_bits.h
-parser_st.$(OBJEXT): {$(VPATH)}parser_st.c
-parser_st.$(OBJEXT): {$(VPATH)}parser_st.h
-parser_st.$(OBJEXT): {$(VPATH)}parser_value.h
-parser_st.$(OBJEXT): {$(VPATH)}st.c
-prism/api_node.$(OBJEXT): $(hdrdir)/ruby.h
-prism/api_node.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/extension.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/node.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/options.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/pack.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/parser.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/prism.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-prism/api_node.$(OBJEXT): {$(VPATH)}assert.h
-prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
-prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/bool.h
-prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
-prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/limits.h
-prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
-prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
-prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
-prism/api_node.$(OBJEXT): {$(VPATH)}config.h
-prism/api_node.$(OBJEXT): {$(VPATH)}defines.h
-prism/api_node.$(OBJEXT): {$(VPATH)}encoding.h
-prism/api_node.$(OBJEXT): {$(VPATH)}intern.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/abi.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/anyargs.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/assume.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/const.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/error.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/format.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/cast.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/config.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/constant_p.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/core.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/robject.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/ctype.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/dllexport.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/dosish.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/error.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/eval.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/event.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/fl_type.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/gc.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/glob.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/globals.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/has/extension.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/has/feature.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/has/warning.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/array.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/class.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/error.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/file.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/io.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/load.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/object.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/process.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/random.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/range.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/re.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/select.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/string.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/time.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/interpreter.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/iterator.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/memory.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/method.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/module.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/newobj.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/scan_args.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/special_consts.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/static_assert.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/stdalign.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/stdbool.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/symbol.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/value.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/value_type.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/variable.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/warning_push.h
-prism/api_node.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
-prism/api_node.$(OBJEXT): {$(VPATH)}missing.h
-prism/api_node.$(OBJEXT): {$(VPATH)}onigmo.h
-prism/api_node.$(OBJEXT): {$(VPATH)}oniguruma.h
-prism/api_node.$(OBJEXT): {$(VPATH)}prism/api_node.c
-prism/api_node.$(OBJEXT): {$(VPATH)}prism/ast.h
-prism/api_node.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-prism/api_node.$(OBJEXT): {$(VPATH)}prism/version.h
-prism/api_node.$(OBJEXT): {$(VPATH)}st.h
-prism/api_node.$(OBJEXT): {$(VPATH)}subst.h
-prism/api_pack.$(OBJEXT): $(hdrdir)/ruby.h
-prism/api_pack.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/api_pack.c
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/extension.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/node.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/options.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/pack.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/parser.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/prism.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}assert.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/bool.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/limits.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}config.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}defines.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}encoding.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}intern.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/abi.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/anyargs.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/assume.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/const.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/error.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/format.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/cast.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/config.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/constant_p.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/robject.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/ctype.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/dllexport.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/dosish.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/error.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/eval.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/event.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/fl_type.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/gc.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/glob.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/globals.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/has/extension.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/has/feature.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/has/warning.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/array.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/class.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/error.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/file.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/io.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/load.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/object.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/process.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/random.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/range.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/re.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/select.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/string.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/time.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/interpreter.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/iterator.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/memory.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/method.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/module.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/newobj.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/scan_args.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/special_consts.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/static_assert.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/stdalign.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/stdbool.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/symbol.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/value.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/value_type.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/variable.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/warning_push.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}missing.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}onigmo.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}oniguruma.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}prism/ast.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}prism/version.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}st.h
-prism/api_pack.$(OBJEXT): {$(VPATH)}subst.h
-prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/diagnostic.$(OBJEXT): {$(VPATH)}prism/ast.h
-prism/diagnostic.$(OBJEXT): {$(VPATH)}prism/diagnostic.c
-prism/diagnostic.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-prism/encoding.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/encoding.$(OBJEXT): $(top_srcdir)/prism/encoding.c
-prism/encoding.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-prism/encoding.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-prism/extension.$(OBJEXT): $(hdrdir)/ruby.h
-prism/extension.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/extension.c
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/extension.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/node.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/options.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/pack.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/parser.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/prism.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-prism/extension.$(OBJEXT): {$(VPATH)}assert.h
-prism/extension.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-prism/extension.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
-prism/extension.$(OBJEXT): {$(VPATH)}backward/2/bool.h
-prism/extension.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
-prism/extension.$(OBJEXT): {$(VPATH)}backward/2/limits.h
-prism/extension.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
-prism/extension.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
-prism/extension.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
-prism/extension.$(OBJEXT): {$(VPATH)}config.h
-prism/extension.$(OBJEXT): {$(VPATH)}defines.h
-prism/extension.$(OBJEXT): {$(VPATH)}encoding.h
-prism/extension.$(OBJEXT): {$(VPATH)}intern.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/abi.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/anyargs.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/assume.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/const.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/error.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/format.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/cast.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/config.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/constant_p.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/core.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/core/robject.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/ctype.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/dllexport.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/dosish.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/error.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/eval.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/event.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/fl_type.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/gc.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/glob.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/globals.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/has/extension.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/has/feature.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/has/warning.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/array.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/class.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/error.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/file.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/io.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/load.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/object.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/process.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/random.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/range.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/re.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/select.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/string.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/time.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/interpreter.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/iterator.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/memory.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/method.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/module.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/newobj.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/scan_args.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/special_consts.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/static_assert.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/stdalign.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/stdbool.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/symbol.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/value.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/value_type.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/variable.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/warning_push.h
-prism/extension.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
-prism/extension.$(OBJEXT): {$(VPATH)}missing.h
-prism/extension.$(OBJEXT): {$(VPATH)}onigmo.h
-prism/extension.$(OBJEXT): {$(VPATH)}oniguruma.h
-prism/extension.$(OBJEXT): {$(VPATH)}prism/ast.h
-prism/extension.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-prism/extension.$(OBJEXT): {$(VPATH)}prism/version.h
-prism/extension.$(OBJEXT): {$(VPATH)}st.h
-prism/extension.$(OBJEXT): {$(VPATH)}subst.h
-prism/node.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/node.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-prism/node.$(OBJEXT): $(top_srcdir)/prism/node.h
-prism/node.$(OBJEXT): $(top_srcdir)/prism/options.h
-prism/node.$(OBJEXT): $(top_srcdir)/prism/pack.h
-prism/node.$(OBJEXT): $(top_srcdir)/prism/parser.h
-prism/node.$(OBJEXT): $(top_srcdir)/prism/prism.h
-prism/node.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-prism/node.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-prism/node.$(OBJEXT): {$(VPATH)}prism/ast.h
-prism/node.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-prism/node.$(OBJEXT): {$(VPATH)}prism/node.c
-prism/options.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/options.$(OBJEXT): $(top_srcdir)/prism/options.c
-prism/options.$(OBJEXT): $(top_srcdir)/prism/options.h
-prism/options.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/pack.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/pack.$(OBJEXT): $(top_srcdir)/prism/pack.c
-prism/pack.$(OBJEXT): $(top_srcdir)/prism/pack.h
-prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/options.h
-prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/parser.h
-prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-prism/prettyprint.$(OBJEXT): {$(VPATH)}prism/ast.h
-prism/prettyprint.$(OBJEXT): {$(VPATH)}prism/prettyprint.c
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/node.h
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/options.h
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/pack.h
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/parser.h
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/prism.c
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/prism.h
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-prism/prism.$(OBJEXT): $(top_srcdir)/prism/version.h
-prism/prism.$(OBJEXT): {$(VPATH)}prism/ast.h
-prism/prism.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-prism/prism.$(OBJEXT): {$(VPATH)}prism/version.h
-prism/regexp.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/regexp.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-prism/regexp.$(OBJEXT): $(top_srcdir)/prism/options.h
-prism/regexp.$(OBJEXT): $(top_srcdir)/prism/parser.h
-prism/regexp.$(OBJEXT): $(top_srcdir)/prism/regexp.c
-prism/regexp.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-prism/regexp.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-prism/regexp.$(OBJEXT): {$(VPATH)}prism/ast.h
-prism/serialize.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/serialize.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-prism/serialize.$(OBJEXT): $(top_srcdir)/prism/node.h
-prism/serialize.$(OBJEXT): $(top_srcdir)/prism/options.h
-prism/serialize.$(OBJEXT): $(top_srcdir)/prism/pack.h
-prism/serialize.$(OBJEXT): $(top_srcdir)/prism/parser.h
-prism/serialize.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-prism/serialize.$(OBJEXT): $(top_srcdir)/prism/prism.h
-prism/serialize.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-prism/serialize.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-prism/serialize.$(OBJEXT): {$(VPATH)}prism/ast.h
-prism/serialize.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-prism/serialize.$(OBJEXT): {$(VPATH)}prism/serialize.c
-prism/serialize.$(OBJEXT): {$(VPATH)}prism/version.h
-prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/node.h
-prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/options.h
-prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/parser.h
-prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/static_literals.c
-prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-prism/static_literals.$(OBJEXT): {$(VPATH)}prism/ast.h
-prism/token_type.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/token_type.$(OBJEXT): {$(VPATH)}prism/ast.h
-prism/token_type.$(OBJEXT): {$(VPATH)}prism/token_type.c
-prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.c
-prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/util/pm_char.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/util/pm_char.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.c
-prism/util/pm_char.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-prism/util/pm_char.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/util/pm_constant_pool.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/util/pm_constant_pool.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.c
-prism/util/pm_constant_pool.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.c
-prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/util/pm_list.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/util/pm_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.c
-prism/util/pm_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/parser.h
-prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.c
-prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-prism/util/pm_memchr.$(OBJEXT): {$(VPATH)}prism/ast.h
-prism/util/pm_newline_list.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/util/pm_newline_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.c
-prism/util/pm_newline_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/util/pm_string.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/util/pm_string.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.c
-prism/util/pm_string.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/util/pm_string_list.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/util/pm_string_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/util/pm_string_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.c
-prism/util/pm_string_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-prism/util/pm_strncasecmp.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/util/pm_strncasecmp.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.c
-prism/util/pm_strncasecmp.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/options.h
-prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/parser.h
-prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.c
-prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-prism/util/pm_strpbrk.$(OBJEXT): {$(VPATH)}prism/ast.h
-prism/util/pm_strpbrk.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-prism_init.$(OBJEXT): $(hdrdir)/ruby.h
-prism_init.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/defines.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/extension.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/node.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/options.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/pack.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/parser.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/prism.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-prism_init.$(OBJEXT): $(top_srcdir)/prism_init.c
-prism_init.$(OBJEXT): {$(VPATH)}assert.h
-prism_init.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-prism_init.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
-prism_init.$(OBJEXT): {$(VPATH)}backward/2/bool.h
-prism_init.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
-prism_init.$(OBJEXT): {$(VPATH)}backward/2/limits.h
-prism_init.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
-prism_init.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
-prism_init.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
-prism_init.$(OBJEXT): {$(VPATH)}config.h
-prism_init.$(OBJEXT): {$(VPATH)}defines.h
-prism_init.$(OBJEXT): {$(VPATH)}encoding.h
-prism_init.$(OBJEXT): {$(VPATH)}intern.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/abi.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/anyargs.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/assume.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/attr/const.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/attr/error.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/attr/format.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/cast.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/config.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/constant_p.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/core.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/core/robject.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/ctype.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/dllexport.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/dosish.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/error.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/eval.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/event.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/fl_type.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/gc.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/glob.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/globals.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/has/extension.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/has/feature.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/has/warning.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/array.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/class.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/error.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/file.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/io.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/load.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/object.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/process.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/random.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/range.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/re.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/select.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/string.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/time.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/interpreter.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/iterator.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/memory.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/method.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/module.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/newobj.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/scan_args.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/special_consts.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/static_assert.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/stdalign.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/stdbool.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/symbol.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/value.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/value_type.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/variable.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/warning_push.h
-prism_init.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
-prism_init.$(OBJEXT): {$(VPATH)}missing.h
-prism_init.$(OBJEXT): {$(VPATH)}onigmo.h
-prism_init.$(OBJEXT): {$(VPATH)}oniguruma.h
-prism_init.$(OBJEXT): {$(VPATH)}prism/ast.h
-prism_init.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-prism_init.$(OBJEXT): {$(VPATH)}prism/version.h
-prism_init.$(OBJEXT): {$(VPATH)}prism_init.c
-prism_init.$(OBJEXT): {$(VPATH)}st.h
-prism_init.$(OBJEXT): {$(VPATH)}subst.h
-proc.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-proc.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-proc.$(OBJEXT): $(CCAN_DIR)/list/list.h
-proc.$(OBJEXT): $(CCAN_DIR)/str/str.h
-proc.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-proc.$(OBJEXT): $(hdrdir)/ruby/version.h
-proc.$(OBJEXT): $(top_srcdir)/internal/array.h
-proc.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-proc.$(OBJEXT): $(top_srcdir)/internal/class.h
-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/sanitizers.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/variable.h
-proc.$(OBJEXT): $(top_srcdir)/internal/vm.h
-proc.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-proc.$(OBJEXT): $(top_srcdir)/prism/defines.h
-proc.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-proc.$(OBJEXT): $(top_srcdir)/prism/node.h
-proc.$(OBJEXT): $(top_srcdir)/prism/options.h
-proc.$(OBJEXT): $(top_srcdir)/prism/pack.h
-proc.$(OBJEXT): $(top_srcdir)/prism/parser.h
-proc.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-proc.$(OBJEXT): $(top_srcdir)/prism/prism.h
-proc.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-proc.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-proc.$(OBJEXT): {$(VPATH)}assert.h
-proc.$(OBJEXT): {$(VPATH)}atomic.h
-proc.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-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)}constant.h
-proc.$(OBJEXT): {$(VPATH)}debug_counter.h
-proc.$(OBJEXT): {$(VPATH)}defines.h
-proc.$(OBJEXT): {$(VPATH)}encoding.h
-proc.$(OBJEXT): {$(VPATH)}eval_intern.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/abi.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/packed_struct.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/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/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/stdckdint.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)}prism/ast.h
-proc.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-proc.$(OBJEXT): {$(VPATH)}prism/version.h
-proc.$(OBJEXT): {$(VPATH)}prism_compile.h
-proc.$(OBJEXT): {$(VPATH)}proc.c
-proc.$(OBJEXT): {$(VPATH)}ruby_assert.h
-proc.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-proc.$(OBJEXT): {$(VPATH)}rubyparser.h
-proc.$(OBJEXT): {$(VPATH)}shape.h
-proc.$(OBJEXT): {$(VPATH)}st.h
-proc.$(OBJEXT): {$(VPATH)}subst.h
-proc.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-proc.$(OBJEXT): {$(VPATH)}thread_native.h
-proc.$(OBJEXT): {$(VPATH)}vm_core.h
-proc.$(OBJEXT): {$(VPATH)}vm_debug.h
-proc.$(OBJEXT): {$(VPATH)}vm_opts.h
-proc.$(OBJEXT): {$(VPATH)}vm_sync.h
-proc.$(OBJEXT): {$(VPATH)}yjit.h
-process.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-process.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-process.$(OBJEXT): $(CCAN_DIR)/list/list.h
-process.$(OBJEXT): $(CCAN_DIR)/str/str.h
-process.$(OBJEXT): $(hdrdir)/ruby.h
-process.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-process.$(OBJEXT): $(hdrdir)/ruby/version.h
-process.$(OBJEXT): $(top_srcdir)/internal/array.h
-process.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-process.$(OBJEXT): $(top_srcdir)/internal/bignum.h
-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/io.h
-process.$(OBJEXT): $(top_srcdir)/internal/numeric.h
-process.$(OBJEXT): $(top_srcdir)/internal/object.h
-process.$(OBJEXT): $(top_srcdir)/internal/process.h
-process.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-process.$(OBJEXT): $(top_srcdir)/internal/serial.h
-process.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-process.$(OBJEXT): $(top_srcdir)/internal/string.h
-process.$(OBJEXT): $(top_srcdir)/internal/thread.h
-process.$(OBJEXT): $(top_srcdir)/internal/time.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)}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/abi.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/packed_struct.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/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/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/stdckdint.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)}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)}rjit.h
-process.$(OBJEXT): {$(VPATH)}ruby_assert.h
-process.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-process.$(OBJEXT): {$(VPATH)}rubyparser.h
-process.$(OBJEXT): {$(VPATH)}shape.h
-process.$(OBJEXT): {$(VPATH)}st.h
-process.$(OBJEXT): {$(VPATH)}subst.h
-process.$(OBJEXT): {$(VPATH)}thread.h
-process.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-process.$(OBJEXT): {$(VPATH)}thread_native.h
-process.$(OBJEXT): {$(VPATH)}util.h
-process.$(OBJEXT): {$(VPATH)}vm_core.h
-process.$(OBJEXT): {$(VPATH)}vm_debug.h
-process.$(OBJEXT): {$(VPATH)}vm_opts.h
-process.$(OBJEXT): {$(VPATH)}vm_sync.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.h
-ractor.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-ractor.$(OBJEXT): $(hdrdir)/ruby/version.h
-ractor.$(OBJEXT): $(top_srcdir)/internal/array.h
-ractor.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-ractor.$(OBJEXT): $(top_srcdir)/internal/bignum.h
-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/sanitizers.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/variable.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)}constant.h
-ractor.$(OBJEXT): {$(VPATH)}debug_counter.h
-ractor.$(OBJEXT): {$(VPATH)}defines.h
-ractor.$(OBJEXT): {$(VPATH)}encoding.h
-ractor.$(OBJEXT): {$(VPATH)}eval_intern.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/abi.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/packed_struct.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/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/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/stdckdint.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.rbinc
-ractor.$(OBJEXT): {$(VPATH)}ractor_core.h
-ractor.$(OBJEXT): {$(VPATH)}rjit.h
-ractor.$(OBJEXT): {$(VPATH)}ruby_assert.h
-ractor.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-ractor.$(OBJEXT): {$(VPATH)}rubyparser.h
-ractor.$(OBJEXT): {$(VPATH)}shape.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)}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): $(CCAN_DIR)/check_type/check_type.h
-random.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-random.$(OBJEXT): $(CCAN_DIR)/list/list.h
-random.$(OBJEXT): $(CCAN_DIR)/str/str.h
-random.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-random.$(OBJEXT): $(top_srcdir)/internal/array.h
-random.$(OBJEXT): $(top_srcdir)/internal/basic_operators.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/gc.h
-random.$(OBJEXT): $(top_srcdir)/internal/imemo.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)}encoding.h
-random.$(OBJEXT): {$(VPATH)}id.h
-random.$(OBJEXT): {$(VPATH)}id_table.h
-random.$(OBJEXT): {$(VPATH)}intern.h
-random.$(OBJEXT): {$(VPATH)}internal.h
-random.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/encoding/coderange.h
-random.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
-random.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
-random.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
-random.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
-random.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
-random.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
-random.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
-random.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.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/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/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/stdckdint.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)}method.h
-random.$(OBJEXT): {$(VPATH)}missing.h
-random.$(OBJEXT): {$(VPATH)}mt19937.c
-random.$(OBJEXT): {$(VPATH)}node.h
-random.$(OBJEXT): {$(VPATH)}onigmo.h
-random.$(OBJEXT): {$(VPATH)}oniguruma.h
-random.$(OBJEXT): {$(VPATH)}ractor.h
-random.$(OBJEXT): {$(VPATH)}random.c
-random.$(OBJEXT): {$(VPATH)}random.h
-random.$(OBJEXT): {$(VPATH)}ruby_assert.h
-random.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-random.$(OBJEXT): {$(VPATH)}rubyparser.h
-random.$(OBJEXT): {$(VPATH)}shape.h
-random.$(OBJEXT): {$(VPATH)}siphash.c
-random.$(OBJEXT): {$(VPATH)}siphash.h
-random.$(OBJEXT): {$(VPATH)}st.h
-random.$(OBJEXT): {$(VPATH)}subst.h
-random.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-random.$(OBJEXT): {$(VPATH)}thread_native.h
-random.$(OBJEXT): {$(VPATH)}vm_core.h
-random.$(OBJEXT): {$(VPATH)}vm_opts.h
-range.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-range.$(OBJEXT): $(hdrdir)/ruby/version.h
-range.$(OBJEXT): $(top_srcdir)/internal/array.h
-range.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-range.$(OBJEXT): $(top_srcdir)/internal/bignum.h
-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/abi.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/packed_struct.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/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/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/stdckdint.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)}shape.h
-range.$(OBJEXT): {$(VPATH)}st.h
-range.$(OBJEXT): {$(VPATH)}subst.h
-rational.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-rational.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-rational.$(OBJEXT): $(CCAN_DIR)/list/list.h
-rational.$(OBJEXT): $(CCAN_DIR)/str/str.h
-rational.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-rational.$(OBJEXT): $(top_srcdir)/internal/array.h
-rational.$(OBJEXT): $(top_srcdir)/internal/basic_operators.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/imemo.h
-rational.$(OBJEXT): $(top_srcdir)/internal/numeric.h
-rational.$(OBJEXT): $(top_srcdir)/internal/object.h
-rational.$(OBJEXT): $(top_srcdir)/internal/rational.h
-rational.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-rational.$(OBJEXT): $(top_srcdir)/internal/serial.h
-rational.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-rational.$(OBJEXT): $(top_srcdir)/internal/variable.h
-rational.$(OBJEXT): $(top_srcdir)/internal/vm.h
-rational.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-rational.$(OBJEXT): {$(VPATH)}assert.h
-rational.$(OBJEXT): {$(VPATH)}atomic.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)}constant.h
-rational.$(OBJEXT): {$(VPATH)}defines.h
-rational.$(OBJEXT): {$(VPATH)}encoding.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/abi.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/packed_struct.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/encoding/coderange.h
-rational.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
-rational.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
-rational.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
-rational.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
-rational.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
-rational.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
-rational.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
-rational.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.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/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/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/stdckdint.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)}method.h
-rational.$(OBJEXT): {$(VPATH)}missing.h
-rational.$(OBJEXT): {$(VPATH)}node.h
-rational.$(OBJEXT): {$(VPATH)}onigmo.h
-rational.$(OBJEXT): {$(VPATH)}oniguruma.h
-rational.$(OBJEXT): {$(VPATH)}rational.c
-rational.$(OBJEXT): {$(VPATH)}ruby_assert.h
-rational.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-rational.$(OBJEXT): {$(VPATH)}rubyparser.h
-rational.$(OBJEXT): {$(VPATH)}shape.h
-rational.$(OBJEXT): {$(VPATH)}st.h
-rational.$(OBJEXT): {$(VPATH)}subst.h
-rational.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-rational.$(OBJEXT): {$(VPATH)}thread_native.h
-rational.$(OBJEXT): {$(VPATH)}vm_core.h
-rational.$(OBJEXT): {$(VPATH)}vm_opts.h
-re.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-re.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-re.$(OBJEXT): $(CCAN_DIR)/list/list.h
-re.$(OBJEXT): $(CCAN_DIR)/str/str.h
-re.$(OBJEXT): $(hdrdir)/ruby.h
-re.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-re.$(OBJEXT): $(top_srcdir)/internal/array.h
-re.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-re.$(OBJEXT): $(top_srcdir)/internal/bits.h
-re.$(OBJEXT): $(top_srcdir)/internal/class.h
-re.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-re.$(OBJEXT): $(top_srcdir)/internal/encoding.h
-re.$(OBJEXT): $(top_srcdir)/internal/gc.h
-re.$(OBJEXT): $(top_srcdir)/internal/hash.h
-re.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-re.$(OBJEXT): $(top_srcdir)/internal/object.h
-re.$(OBJEXT): $(top_srcdir)/internal/ractor.h
-re.$(OBJEXT): $(top_srcdir)/internal/re.h
-re.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-re.$(OBJEXT): $(top_srcdir)/internal/serial.h
-re.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-re.$(OBJEXT): $(top_srcdir)/internal/string.h
-re.$(OBJEXT): $(top_srcdir)/internal/time.h
-re.$(OBJEXT): $(top_srcdir)/internal/variable.h
-re.$(OBJEXT): $(top_srcdir)/internal/vm.h
-re.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-re.$(OBJEXT): {$(VPATH)}assert.h
-re.$(OBJEXT): {$(VPATH)}atomic.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)}hrtime.h
-re.$(OBJEXT): {$(VPATH)}id.h
-re.$(OBJEXT): {$(VPATH)}id_table.h
-re.$(OBJEXT): {$(VPATH)}intern.h
-re.$(OBJEXT): {$(VPATH)}internal.h
-re.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/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/stdckdint.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)}method.h
-re.$(OBJEXT): {$(VPATH)}missing.h
-re.$(OBJEXT): {$(VPATH)}node.h
-re.$(OBJEXT): {$(VPATH)}onigmo.h
-re.$(OBJEXT): {$(VPATH)}oniguruma.h
-re.$(OBJEXT): {$(VPATH)}re.c
-re.$(OBJEXT): {$(VPATH)}re.h
-re.$(OBJEXT): {$(VPATH)}regenc.h
-re.$(OBJEXT): {$(VPATH)}regex.h
-re.$(OBJEXT): {$(VPATH)}regint.h
-re.$(OBJEXT): {$(VPATH)}ruby_assert.h
-re.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-re.$(OBJEXT): {$(VPATH)}rubyparser.h
-re.$(OBJEXT): {$(VPATH)}shape.h
-re.$(OBJEXT): {$(VPATH)}st.h
-re.$(OBJEXT): {$(VPATH)}subst.h
-re.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-re.$(OBJEXT): {$(VPATH)}thread_native.h
-re.$(OBJEXT): {$(VPATH)}util.h
-re.$(OBJEXT): {$(VPATH)}vm_core.h
-re.$(OBJEXT): {$(VPATH)}vm_opts.h
-regcomp.$(OBJEXT): $(hdrdir)/ruby.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/abi.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/packed_struct.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/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/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/stdckdint.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
-regcomp.$(OBJEXT): {$(VPATH)}regenc.h
-regcomp.$(OBJEXT): {$(VPATH)}regint.h
-regcomp.$(OBJEXT): {$(VPATH)}regparse.h
-regcomp.$(OBJEXT): {$(VPATH)}st.h
-regcomp.$(OBJEXT): {$(VPATH)}subst.h
-regenc.$(OBJEXT): $(hdrdir)/ruby.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/abi.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/packed_struct.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/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/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/stdckdint.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
-regenc.$(OBJEXT): {$(VPATH)}regenc.h
-regenc.$(OBJEXT): {$(VPATH)}regint.h
-regenc.$(OBJEXT): {$(VPATH)}st.h
-regenc.$(OBJEXT): {$(VPATH)}subst.h
-regerror.$(OBJEXT): $(hdrdir)/ruby.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/abi.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/packed_struct.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/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/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/stdckdint.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
-regerror.$(OBJEXT): {$(VPATH)}regerror.c
-regerror.$(OBJEXT): {$(VPATH)}regint.h
-regerror.$(OBJEXT): {$(VPATH)}st.h
-regerror.$(OBJEXT): {$(VPATH)}subst.h
-regexec.$(OBJEXT): $(hdrdir)/ruby.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/abi.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/packed_struct.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/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/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/stdckdint.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
-regexec.$(OBJEXT): {$(VPATH)}regexec.c
-regexec.$(OBJEXT): {$(VPATH)}regint.h
-regexec.$(OBJEXT): {$(VPATH)}st.h
-regexec.$(OBJEXT): {$(VPATH)}subst.h
-regparse.$(OBJEXT): $(hdrdir)/ruby.h
-regparse.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-regparse.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-regparse.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-regparse.$(OBJEXT): $(top_srcdir)/internal/warnings.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/gcc_version_since.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/abi.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/packed_struct.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/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/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/stdckdint.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
-regparse.$(OBJEXT): {$(VPATH)}regint.h
-regparse.$(OBJEXT): {$(VPATH)}regparse.c
-regparse.$(OBJEXT): {$(VPATH)}regparse.h
-regparse.$(OBJEXT): {$(VPATH)}st.h
-regparse.$(OBJEXT): {$(VPATH)}subst.h
-regsyntax.$(OBJEXT): $(hdrdir)/ruby.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/abi.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/packed_struct.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/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/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/stdckdint.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
-regsyntax.$(OBJEXT): {$(VPATH)}regint.h
-regsyntax.$(OBJEXT): {$(VPATH)}regsyntax.c
-regsyntax.$(OBJEXT): {$(VPATH)}st.h
-regsyntax.$(OBJEXT): {$(VPATH)}subst.h
-rjit.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-rjit.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-rjit.$(OBJEXT): $(CCAN_DIR)/list/list.h
-rjit.$(OBJEXT): $(CCAN_DIR)/str/str.h
-rjit.$(OBJEXT): $(hdrdir)/ruby.h
-rjit.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-rjit.$(OBJEXT): $(hdrdir)/ruby/version.h
-rjit.$(OBJEXT): $(top_srcdir)/internal/array.h
-rjit.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-rjit.$(OBJEXT): $(top_srcdir)/internal/class.h
-rjit.$(OBJEXT): $(top_srcdir)/internal/cmdlineopt.h
-rjit.$(OBJEXT): $(top_srcdir)/internal/compile.h
-rjit.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-rjit.$(OBJEXT): $(top_srcdir)/internal/cont.h
-rjit.$(OBJEXT): $(top_srcdir)/internal/file.h
-rjit.$(OBJEXT): $(top_srcdir)/internal/gc.h
-rjit.$(OBJEXT): $(top_srcdir)/internal/hash.h
-rjit.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-rjit.$(OBJEXT): $(top_srcdir)/internal/process.h
-rjit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-rjit.$(OBJEXT): $(top_srcdir)/internal/serial.h
-rjit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-rjit.$(OBJEXT): $(top_srcdir)/internal/string.h
-rjit.$(OBJEXT): $(top_srcdir)/internal/struct.h
-rjit.$(OBJEXT): $(top_srcdir)/internal/variable.h
-rjit.$(OBJEXT): $(top_srcdir)/internal/vm.h
-rjit.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-rjit.$(OBJEXT): $(top_srcdir)/prism/defines.h
-rjit.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-rjit.$(OBJEXT): $(top_srcdir)/prism/node.h
-rjit.$(OBJEXT): $(top_srcdir)/prism/options.h
-rjit.$(OBJEXT): $(top_srcdir)/prism/pack.h
-rjit.$(OBJEXT): $(top_srcdir)/prism/parser.h
-rjit.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-rjit.$(OBJEXT): $(top_srcdir)/prism/prism.h
-rjit.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-rjit.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-rjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-rjit.$(OBJEXT): {$(VPATH)}assert.h
-rjit.$(OBJEXT): {$(VPATH)}atomic.h
-rjit.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-rjit.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
-rjit.$(OBJEXT): {$(VPATH)}backward/2/bool.h
-rjit.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
-rjit.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
-rjit.$(OBJEXT): {$(VPATH)}backward/2/limits.h
-rjit.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
-rjit.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
-rjit.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
-rjit.$(OBJEXT): {$(VPATH)}builtin.h
-rjit.$(OBJEXT): {$(VPATH)}config.h
-rjit.$(OBJEXT): {$(VPATH)}constant.h
-rjit.$(OBJEXT): {$(VPATH)}debug.h
-rjit.$(OBJEXT): {$(VPATH)}debug_counter.h
-rjit.$(OBJEXT): {$(VPATH)}defines.h
-rjit.$(OBJEXT): {$(VPATH)}dln.h
-rjit.$(OBJEXT): {$(VPATH)}encoding.h
-rjit.$(OBJEXT): {$(VPATH)}id.h
-rjit.$(OBJEXT): {$(VPATH)}id_table.h
-rjit.$(OBJEXT): {$(VPATH)}insns.def
-rjit.$(OBJEXT): {$(VPATH)}insns.inc
-rjit.$(OBJEXT): {$(VPATH)}insns_info.inc
-rjit.$(OBJEXT): {$(VPATH)}intern.h
-rjit.$(OBJEXT): {$(VPATH)}internal.h
-rjit.$(OBJEXT): {$(VPATH)}internal/abi.h
-rjit.$(OBJEXT): {$(VPATH)}internal/anyargs.h
-rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
-rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
-rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
-rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
-rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
-rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
-rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
-rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
-rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
-rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
-rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
-rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
-rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
-rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
-rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
-rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
-rjit.$(OBJEXT): {$(VPATH)}internal/assume.h
-rjit.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
-rjit.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
-rjit.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
-rjit.$(OBJEXT): {$(VPATH)}internal/attr/const.h
-rjit.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
-rjit.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
-rjit.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
-rjit.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
-rjit.$(OBJEXT): {$(VPATH)}internal/attr/error.h
-rjit.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
-rjit.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
-rjit.$(OBJEXT): {$(VPATH)}internal/attr/format.h
-rjit.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
-rjit.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
-rjit.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
-rjit.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
-rjit.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
-rjit.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
-rjit.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
-rjit.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
-rjit.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
-rjit.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
-rjit.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
-rjit.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
-rjit.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
-rjit.$(OBJEXT): {$(VPATH)}internal/cast.h
-rjit.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
-rjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
-rjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
-rjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
-rjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
-rjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
-rjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
-rjit.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
-rjit.$(OBJEXT): {$(VPATH)}internal/config.h
-rjit.$(OBJEXT): {$(VPATH)}internal/constant_p.h
-rjit.$(OBJEXT): {$(VPATH)}internal/core.h
-rjit.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
-rjit.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
-rjit.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
-rjit.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
-rjit.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
-rjit.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
-rjit.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
-rjit.$(OBJEXT): {$(VPATH)}internal/core/robject.h
-rjit.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
-rjit.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
-rjit.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
-rjit.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
-rjit.$(OBJEXT): {$(VPATH)}internal/ctype.h
-rjit.$(OBJEXT): {$(VPATH)}internal/dllexport.h
-rjit.$(OBJEXT): {$(VPATH)}internal/dosish.h
-rjit.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
-rjit.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
-rjit.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
-rjit.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
-rjit.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
-rjit.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
-rjit.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
-rjit.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
-rjit.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
-rjit.$(OBJEXT): {$(VPATH)}internal/error.h
-rjit.$(OBJEXT): {$(VPATH)}internal/eval.h
-rjit.$(OBJEXT): {$(VPATH)}internal/event.h
-rjit.$(OBJEXT): {$(VPATH)}internal/fl_type.h
-rjit.$(OBJEXT): {$(VPATH)}internal/gc.h
-rjit.$(OBJEXT): {$(VPATH)}internal/glob.h
-rjit.$(OBJEXT): {$(VPATH)}internal/globals.h
-rjit.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
-rjit.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
-rjit.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
-rjit.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
-rjit.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
-rjit.$(OBJEXT): {$(VPATH)}internal/has/extension.h
-rjit.$(OBJEXT): {$(VPATH)}internal/has/feature.h
-rjit.$(OBJEXT): {$(VPATH)}internal/has/warning.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/array.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/class.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/error.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/file.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/io.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/load.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/object.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/process.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/random.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/range.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/re.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/select.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/string.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/time.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
-rjit.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
-rjit.$(OBJEXT): {$(VPATH)}internal/interpreter.h
-rjit.$(OBJEXT): {$(VPATH)}internal/iterator.h
-rjit.$(OBJEXT): {$(VPATH)}internal/memory.h
-rjit.$(OBJEXT): {$(VPATH)}internal/method.h
-rjit.$(OBJEXT): {$(VPATH)}internal/module.h
-rjit.$(OBJEXT): {$(VPATH)}internal/newobj.h
-rjit.$(OBJEXT): {$(VPATH)}internal/scan_args.h
-rjit.$(OBJEXT): {$(VPATH)}internal/special_consts.h
-rjit.$(OBJEXT): {$(VPATH)}internal/static_assert.h
-rjit.$(OBJEXT): {$(VPATH)}internal/stdalign.h
-rjit.$(OBJEXT): {$(VPATH)}internal/stdbool.h
-rjit.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
-rjit.$(OBJEXT): {$(VPATH)}internal/symbol.h
-rjit.$(OBJEXT): {$(VPATH)}internal/value.h
-rjit.$(OBJEXT): {$(VPATH)}internal/value_type.h
-rjit.$(OBJEXT): {$(VPATH)}internal/variable.h
-rjit.$(OBJEXT): {$(VPATH)}internal/warning_push.h
-rjit.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
-rjit.$(OBJEXT): {$(VPATH)}iseq.h
-rjit.$(OBJEXT): {$(VPATH)}method.h
-rjit.$(OBJEXT): {$(VPATH)}missing.h
-rjit.$(OBJEXT): {$(VPATH)}node.h
-rjit.$(OBJEXT): {$(VPATH)}onigmo.h
-rjit.$(OBJEXT): {$(VPATH)}oniguruma.h
-rjit.$(OBJEXT): {$(VPATH)}prism/ast.h
-rjit.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-rjit.$(OBJEXT): {$(VPATH)}prism/version.h
-rjit.$(OBJEXT): {$(VPATH)}prism_compile.h
-rjit.$(OBJEXT): {$(VPATH)}ractor.h
-rjit.$(OBJEXT): {$(VPATH)}ractor_core.h
-rjit.$(OBJEXT): {$(VPATH)}rjit.c
-rjit.$(OBJEXT): {$(VPATH)}rjit.h
-rjit.$(OBJEXT): {$(VPATH)}rjit.rbinc
-rjit.$(OBJEXT): {$(VPATH)}rjit_c.h
-rjit.$(OBJEXT): {$(VPATH)}ruby_assert.h
-rjit.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-rjit.$(OBJEXT): {$(VPATH)}rubyparser.h
-rjit.$(OBJEXT): {$(VPATH)}shape.h
-rjit.$(OBJEXT): {$(VPATH)}st.h
-rjit.$(OBJEXT): {$(VPATH)}subst.h
-rjit.$(OBJEXT): {$(VPATH)}thread.h
-rjit.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-rjit.$(OBJEXT): {$(VPATH)}thread_native.h
-rjit.$(OBJEXT): {$(VPATH)}util.h
-rjit.$(OBJEXT): {$(VPATH)}vm_callinfo.h
-rjit.$(OBJEXT): {$(VPATH)}vm_core.h
-rjit.$(OBJEXT): {$(VPATH)}vm_debug.h
-rjit.$(OBJEXT): {$(VPATH)}vm_opts.h
-rjit.$(OBJEXT): {$(VPATH)}vm_sync.h
-rjit.$(OBJEXT): {$(VPATH)}yjit.h
-rjit_c.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-rjit_c.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-rjit_c.$(OBJEXT): $(CCAN_DIR)/list/list.h
-rjit_c.$(OBJEXT): $(CCAN_DIR)/str/str.h
-rjit_c.$(OBJEXT): $(hdrdir)/ruby.h
-rjit_c.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-rjit_c.$(OBJEXT): $(srcdir)/rjit_c.rb
-rjit_c.$(OBJEXT): $(top_srcdir)/internal/array.h
-rjit_c.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-rjit_c.$(OBJEXT): $(top_srcdir)/internal/class.h
-rjit_c.$(OBJEXT): $(top_srcdir)/internal/compile.h
-rjit_c.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-rjit_c.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
-rjit_c.$(OBJEXT): $(top_srcdir)/internal/gc.h
-rjit_c.$(OBJEXT): $(top_srcdir)/internal/hash.h
-rjit_c.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-rjit_c.$(OBJEXT): $(top_srcdir)/internal/object.h
-rjit_c.$(OBJEXT): $(top_srcdir)/internal/proc.h
-rjit_c.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-rjit_c.$(OBJEXT): $(top_srcdir)/internal/serial.h
-rjit_c.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-rjit_c.$(OBJEXT): $(top_srcdir)/internal/string.h
-rjit_c.$(OBJEXT): $(top_srcdir)/internal/struct.h
-rjit_c.$(OBJEXT): $(top_srcdir)/internal/variable.h
-rjit_c.$(OBJEXT): $(top_srcdir)/internal/vm.h
-rjit_c.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-rjit_c.$(OBJEXT): $(top_srcdir)/prism/defines.h
-rjit_c.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-rjit_c.$(OBJEXT): $(top_srcdir)/prism/node.h
-rjit_c.$(OBJEXT): $(top_srcdir)/prism/options.h
-rjit_c.$(OBJEXT): $(top_srcdir)/prism/pack.h
-rjit_c.$(OBJEXT): $(top_srcdir)/prism/parser.h
-rjit_c.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-rjit_c.$(OBJEXT): $(top_srcdir)/prism/prism.h
-rjit_c.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-rjit_c.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-rjit_c.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-rjit_c.$(OBJEXT): {$(VPATH)}assert.h
-rjit_c.$(OBJEXT): {$(VPATH)}atomic.h
-rjit_c.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-rjit_c.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
-rjit_c.$(OBJEXT): {$(VPATH)}backward/2/bool.h
-rjit_c.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
-rjit_c.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
-rjit_c.$(OBJEXT): {$(VPATH)}backward/2/limits.h
-rjit_c.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
-rjit_c.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
-rjit_c.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
-rjit_c.$(OBJEXT): {$(VPATH)}builtin.h
-rjit_c.$(OBJEXT): {$(VPATH)}config.h
-rjit_c.$(OBJEXT): {$(VPATH)}constant.h
-rjit_c.$(OBJEXT): {$(VPATH)}debug.h
-rjit_c.$(OBJEXT): {$(VPATH)}debug_counter.h
-rjit_c.$(OBJEXT): {$(VPATH)}defines.h
-rjit_c.$(OBJEXT): {$(VPATH)}encoding.h
-rjit_c.$(OBJEXT): {$(VPATH)}id.h
-rjit_c.$(OBJEXT): {$(VPATH)}id_table.h
-rjit_c.$(OBJEXT): {$(VPATH)}insns.def
-rjit_c.$(OBJEXT): {$(VPATH)}insns.inc
-rjit_c.$(OBJEXT): {$(VPATH)}insns_info.inc
-rjit_c.$(OBJEXT): {$(VPATH)}intern.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/abi.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/anyargs.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/assume.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/const.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/error.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/format.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/cast.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/config.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/constant_p.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/core.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/core/robject.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/ctype.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/dllexport.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/dosish.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/error.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/eval.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/event.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/fl_type.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/gc.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/glob.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/globals.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/has/extension.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/has/feature.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/has/warning.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/array.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/class.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/error.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/file.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/io.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/load.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/object.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/process.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/random.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/range.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/re.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/select.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/string.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/time.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/interpreter.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/iterator.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/memory.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/method.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/module.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/newobj.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/scan_args.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/special_consts.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/static_assert.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/stdalign.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/stdbool.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/symbol.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/value.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/value_type.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/variable.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/warning_push.h
-rjit_c.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
-rjit_c.$(OBJEXT): {$(VPATH)}iseq.h
-rjit_c.$(OBJEXT): {$(VPATH)}method.h
-rjit_c.$(OBJEXT): {$(VPATH)}missing.h
-rjit_c.$(OBJEXT): {$(VPATH)}node.h
-rjit_c.$(OBJEXT): {$(VPATH)}onigmo.h
-rjit_c.$(OBJEXT): {$(VPATH)}oniguruma.h
-rjit_c.$(OBJEXT): {$(VPATH)}prism/ast.h
-rjit_c.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-rjit_c.$(OBJEXT): {$(VPATH)}prism/version.h
-rjit_c.$(OBJEXT): {$(VPATH)}prism_compile.h
-rjit_c.$(OBJEXT): {$(VPATH)}probes.dmyh
-rjit_c.$(OBJEXT): {$(VPATH)}probes.h
-rjit_c.$(OBJEXT): {$(VPATH)}probes_helper.h
-rjit_c.$(OBJEXT): {$(VPATH)}rjit.h
-rjit_c.$(OBJEXT): {$(VPATH)}rjit_c.c
-rjit_c.$(OBJEXT): {$(VPATH)}rjit_c.h
-rjit_c.$(OBJEXT): {$(VPATH)}rjit_c.rb
-rjit_c.$(OBJEXT): {$(VPATH)}rjit_c.rbinc
-rjit_c.$(OBJEXT): {$(VPATH)}ruby_assert.h
-rjit_c.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-rjit_c.$(OBJEXT): {$(VPATH)}rubyparser.h
-rjit_c.$(OBJEXT): {$(VPATH)}shape.h
-rjit_c.$(OBJEXT): {$(VPATH)}st.h
-rjit_c.$(OBJEXT): {$(VPATH)}subst.h
-rjit_c.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-rjit_c.$(OBJEXT): {$(VPATH)}thread_native.h
-rjit_c.$(OBJEXT): {$(VPATH)}vm_callinfo.h
-rjit_c.$(OBJEXT): {$(VPATH)}vm_core.h
-rjit_c.$(OBJEXT): {$(VPATH)}vm_debug.h
-rjit_c.$(OBJEXT): {$(VPATH)}vm_exec.h
-rjit_c.$(OBJEXT): {$(VPATH)}vm_insnhelper.h
-rjit_c.$(OBJEXT): {$(VPATH)}vm_opts.h
-rjit_c.$(OBJEXT): {$(VPATH)}vm_sync.h
-rjit_c.$(OBJEXT): {$(VPATH)}yjit.h
-ruby-runner.$(OBJEXT): {$(VPATH)}config.h
-ruby-runner.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
-ruby-runner.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
-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
-ruby.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-ruby.$(OBJEXT): $(CCAN_DIR)/list/list.h
-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/basic_operators.h
-ruby.$(OBJEXT): $(top_srcdir)/internal/bignum.h
-ruby.$(OBJEXT): $(top_srcdir)/internal/bits.h
-ruby.$(OBJEXT): $(top_srcdir)/internal/class.h
-ruby.$(OBJEXT): $(top_srcdir)/internal/cmdlineopt.h
-ruby.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-ruby.$(OBJEXT): $(top_srcdir)/internal/complex.h
-ruby.$(OBJEXT): $(top_srcdir)/internal/cont.h
-ruby.$(OBJEXT): $(top_srcdir)/internal/error.h
-ruby.$(OBJEXT): $(top_srcdir)/internal/file.h
-ruby.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
-ruby.$(OBJEXT): $(top_srcdir)/internal/gc.h
-ruby.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-ruby.$(OBJEXT): $(top_srcdir)/internal/inits.h
-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/numeric.h
-ruby.$(OBJEXT): $(top_srcdir)/internal/object.h
-ruby.$(OBJEXT): $(top_srcdir)/internal/parse.h
-ruby.$(OBJEXT): $(top_srcdir)/internal/rational.h
-ruby.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
-ruby.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-ruby.$(OBJEXT): $(top_srcdir)/internal/serial.h
-ruby.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-ruby.$(OBJEXT): $(top_srcdir)/internal/string.h
-ruby.$(OBJEXT): $(top_srcdir)/internal/thread.h
-ruby.$(OBJEXT): $(top_srcdir)/internal/variable.h
-ruby.$(OBJEXT): $(top_srcdir)/internal/vm.h
-ruby.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-ruby.$(OBJEXT): $(top_srcdir)/prism/defines.h
-ruby.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-ruby.$(OBJEXT): $(top_srcdir)/prism/node.h
-ruby.$(OBJEXT): $(top_srcdir)/prism/options.h
-ruby.$(OBJEXT): $(top_srcdir)/prism/pack.h
-ruby.$(OBJEXT): $(top_srcdir)/prism/parser.h
-ruby.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-ruby.$(OBJEXT): $(top_srcdir)/prism/prism.h
-ruby.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-ruby.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-ruby.$(OBJEXT): {$(VPATH)}assert.h
-ruby.$(OBJEXT): {$(VPATH)}atomic.h
-ruby.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-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)}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/abi.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/packed_struct.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/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/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/stdckdint.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)}iseq.h
-ruby.$(OBJEXT): {$(VPATH)}method.h
-ruby.$(OBJEXT): {$(VPATH)}missing.h
-ruby.$(OBJEXT): {$(VPATH)}node.h
-ruby.$(OBJEXT): {$(VPATH)}onigmo.h
-ruby.$(OBJEXT): {$(VPATH)}oniguruma.h
-ruby.$(OBJEXT): {$(VPATH)}prism/ast.h
-ruby.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-ruby.$(OBJEXT): {$(VPATH)}prism/version.h
-ruby.$(OBJEXT): {$(VPATH)}prism_compile.h
-ruby.$(OBJEXT): {$(VPATH)}rjit.h
-ruby.$(OBJEXT): {$(VPATH)}ruby.c
-ruby.$(OBJEXT): {$(VPATH)}ruby_assert.h
-ruby.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-ruby.$(OBJEXT): {$(VPATH)}rubyparser.h
-ruby.$(OBJEXT): {$(VPATH)}shape.h
-ruby.$(OBJEXT): {$(VPATH)}st.h
-ruby.$(OBJEXT): {$(VPATH)}subst.h
-ruby.$(OBJEXT): {$(VPATH)}thread.h
-ruby.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-ruby.$(OBJEXT): {$(VPATH)}thread_native.h
-ruby.$(OBJEXT): {$(VPATH)}util.h
-ruby.$(OBJEXT): {$(VPATH)}vm_core.h
-ruby.$(OBJEXT): {$(VPATH)}vm_opts.h
-ruby.$(OBJEXT): {$(VPATH)}yjit.h
-ruby_parser.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-ruby_parser.$(OBJEXT): $(top_srcdir)/internal/array.h
-ruby_parser.$(OBJEXT): $(top_srcdir)/internal/bignum.h
-ruby_parser.$(OBJEXT): $(top_srcdir)/internal/bits.h
-ruby_parser.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-ruby_parser.$(OBJEXT): $(top_srcdir)/internal/complex.h
-ruby_parser.$(OBJEXT): $(top_srcdir)/internal/error.h
-ruby_parser.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
-ruby_parser.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-ruby_parser.$(OBJEXT): $(top_srcdir)/internal/numeric.h
-ruby_parser.$(OBJEXT): $(top_srcdir)/internal/parse.h
-ruby_parser.$(OBJEXT): $(top_srcdir)/internal/rational.h
-ruby_parser.$(OBJEXT): $(top_srcdir)/internal/re.h
-ruby_parser.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
-ruby_parser.$(OBJEXT): $(top_srcdir)/internal/serial.h
-ruby_parser.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-ruby_parser.$(OBJEXT): $(top_srcdir)/internal/string.h
-ruby_parser.$(OBJEXT): $(top_srcdir)/internal/vm.h
-ruby_parser.$(OBJEXT): {$(VPATH)}assert.h
-ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
-ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/bool.h
-ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
-ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
-ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/limits.h
-ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
-ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
-ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
-ruby_parser.$(OBJEXT): {$(VPATH)}config.h
-ruby_parser.$(OBJEXT): {$(VPATH)}defines.h
-ruby_parser.$(OBJEXT): {$(VPATH)}encoding.h
-ruby_parser.$(OBJEXT): {$(VPATH)}intern.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/abi.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/anyargs.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/assume.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/const.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/error.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/format.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/cast.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/config.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/constant_p.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/core.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/robject.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/ctype.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/dllexport.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/dosish.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/error.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/eval.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/event.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/fl_type.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/gc.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/glob.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/globals.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/extension.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/feature.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/warning.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/array.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/class.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/error.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/file.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/io.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/load.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/object.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/process.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/random.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/range.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/re.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/select.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/string.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/time.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/interpreter.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/iterator.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/memory.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/method.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/module.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/newobj.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/scan_args.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/special_consts.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/static_assert.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/stdalign.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/stdbool.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/symbol.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/value.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/value_type.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/variable.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/warning_push.h
-ruby_parser.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
-ruby_parser.$(OBJEXT): {$(VPATH)}missing.h
-ruby_parser.$(OBJEXT): {$(VPATH)}node.h
-ruby_parser.$(OBJEXT): {$(VPATH)}onigmo.h
-ruby_parser.$(OBJEXT): {$(VPATH)}oniguruma.h
-ruby_parser.$(OBJEXT): {$(VPATH)}ruby_assert.h
-ruby_parser.$(OBJEXT): {$(VPATH)}ruby_parser.c
-ruby_parser.$(OBJEXT): {$(VPATH)}rubyparser.h
-ruby_parser.$(OBJEXT): {$(VPATH)}st.h
-ruby_parser.$(OBJEXT): {$(VPATH)}subst.h
-scheduler.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-scheduler.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-scheduler.$(OBJEXT): $(CCAN_DIR)/list/list.h
-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/basic_operators.h
-scheduler.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-scheduler.$(OBJEXT): $(top_srcdir)/internal/gc.h
-scheduler.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-scheduler.$(OBJEXT): $(top_srcdir)/internal/sanitizers.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/variable.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)}constant.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)}id_table.h
-scheduler.$(OBJEXT): {$(VPATH)}intern.h
-scheduler.$(OBJEXT): {$(VPATH)}internal.h
-scheduler.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/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/stdckdint.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)}rubyparser.h
-scheduler.$(OBJEXT): {$(VPATH)}scheduler.c
-scheduler.$(OBJEXT): {$(VPATH)}shape.h
-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/abi.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/packed_struct.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/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/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/stdckdint.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
-setproctitle.$(OBJEXT): {$(VPATH)}subst.h
-setproctitle.$(OBJEXT): {$(VPATH)}util.h
-shape.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-shape.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-shape.$(OBJEXT): $(CCAN_DIR)/list/list.h
-shape.$(OBJEXT): $(CCAN_DIR)/str/str.h
-shape.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-shape.$(OBJEXT): $(hdrdir)/ruby/version.h
-shape.$(OBJEXT): $(top_srcdir)/internal/array.h
-shape.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-shape.$(OBJEXT): $(top_srcdir)/internal/class.h
-shape.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-shape.$(OBJEXT): $(top_srcdir)/internal/error.h
-shape.$(OBJEXT): $(top_srcdir)/internal/gc.h
-shape.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-shape.$(OBJEXT): $(top_srcdir)/internal/object.h
-shape.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-shape.$(OBJEXT): $(top_srcdir)/internal/serial.h
-shape.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-shape.$(OBJEXT): $(top_srcdir)/internal/string.h
-shape.$(OBJEXT): $(top_srcdir)/internal/symbol.h
-shape.$(OBJEXT): $(top_srcdir)/internal/variable.h
-shape.$(OBJEXT): $(top_srcdir)/internal/vm.h
-shape.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-shape.$(OBJEXT): {$(VPATH)}assert.h
-shape.$(OBJEXT): {$(VPATH)}atomic.h
-shape.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-shape.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
-shape.$(OBJEXT): {$(VPATH)}backward/2/bool.h
-shape.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
-shape.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
-shape.$(OBJEXT): {$(VPATH)}backward/2/limits.h
-shape.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
-shape.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
-shape.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
-shape.$(OBJEXT): {$(VPATH)}config.h
-shape.$(OBJEXT): {$(VPATH)}constant.h
-shape.$(OBJEXT): {$(VPATH)}debug_counter.h
-shape.$(OBJEXT): {$(VPATH)}defines.h
-shape.$(OBJEXT): {$(VPATH)}encoding.h
-shape.$(OBJEXT): {$(VPATH)}id.h
-shape.$(OBJEXT): {$(VPATH)}id_table.h
-shape.$(OBJEXT): {$(VPATH)}intern.h
-shape.$(OBJEXT): {$(VPATH)}internal.h
-shape.$(OBJEXT): {$(VPATH)}internal/abi.h
-shape.$(OBJEXT): {$(VPATH)}internal/anyargs.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
-shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
-shape.$(OBJEXT): {$(VPATH)}internal/assume.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/const.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/error.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/format.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
-shape.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
-shape.$(OBJEXT): {$(VPATH)}internal/cast.h
-shape.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
-shape.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
-shape.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
-shape.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
-shape.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
-shape.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
-shape.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
-shape.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
-shape.$(OBJEXT): {$(VPATH)}internal/config.h
-shape.$(OBJEXT): {$(VPATH)}internal/constant_p.h
-shape.$(OBJEXT): {$(VPATH)}internal/core.h
-shape.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
-shape.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
-shape.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
-shape.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
-shape.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
-shape.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
-shape.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
-shape.$(OBJEXT): {$(VPATH)}internal/core/robject.h
-shape.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
-shape.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
-shape.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
-shape.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
-shape.$(OBJEXT): {$(VPATH)}internal/ctype.h
-shape.$(OBJEXT): {$(VPATH)}internal/dllexport.h
-shape.$(OBJEXT): {$(VPATH)}internal/dosish.h
-shape.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
-shape.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
-shape.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
-shape.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
-shape.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
-shape.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
-shape.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
-shape.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
-shape.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
-shape.$(OBJEXT): {$(VPATH)}internal/error.h
-shape.$(OBJEXT): {$(VPATH)}internal/eval.h
-shape.$(OBJEXT): {$(VPATH)}internal/event.h
-shape.$(OBJEXT): {$(VPATH)}internal/fl_type.h
-shape.$(OBJEXT): {$(VPATH)}internal/gc.h
-shape.$(OBJEXT): {$(VPATH)}internal/glob.h
-shape.$(OBJEXT): {$(VPATH)}internal/globals.h
-shape.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
-shape.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
-shape.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
-shape.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
-shape.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
-shape.$(OBJEXT): {$(VPATH)}internal/has/extension.h
-shape.$(OBJEXT): {$(VPATH)}internal/has/feature.h
-shape.$(OBJEXT): {$(VPATH)}internal/has/warning.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/array.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/class.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/error.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/file.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/io.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/load.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/object.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/process.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/random.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/range.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/re.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/select.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/string.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/time.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
-shape.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
-shape.$(OBJEXT): {$(VPATH)}internal/interpreter.h
-shape.$(OBJEXT): {$(VPATH)}internal/iterator.h
-shape.$(OBJEXT): {$(VPATH)}internal/memory.h
-shape.$(OBJEXT): {$(VPATH)}internal/method.h
-shape.$(OBJEXT): {$(VPATH)}internal/module.h
-shape.$(OBJEXT): {$(VPATH)}internal/newobj.h
-shape.$(OBJEXT): {$(VPATH)}internal/scan_args.h
-shape.$(OBJEXT): {$(VPATH)}internal/special_consts.h
-shape.$(OBJEXT): {$(VPATH)}internal/static_assert.h
-shape.$(OBJEXT): {$(VPATH)}internal/stdalign.h
-shape.$(OBJEXT): {$(VPATH)}internal/stdbool.h
-shape.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
-shape.$(OBJEXT): {$(VPATH)}internal/symbol.h
-shape.$(OBJEXT): {$(VPATH)}internal/value.h
-shape.$(OBJEXT): {$(VPATH)}internal/value_type.h
-shape.$(OBJEXT): {$(VPATH)}internal/variable.h
-shape.$(OBJEXT): {$(VPATH)}internal/warning_push.h
-shape.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
-shape.$(OBJEXT): {$(VPATH)}method.h
-shape.$(OBJEXT): {$(VPATH)}missing.h
-shape.$(OBJEXT): {$(VPATH)}node.h
-shape.$(OBJEXT): {$(VPATH)}onigmo.h
-shape.$(OBJEXT): {$(VPATH)}oniguruma.h
-shape.$(OBJEXT): {$(VPATH)}ruby_assert.h
-shape.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-shape.$(OBJEXT): {$(VPATH)}rubyparser.h
-shape.$(OBJEXT): {$(VPATH)}shape.c
-shape.$(OBJEXT): {$(VPATH)}shape.h
-shape.$(OBJEXT): {$(VPATH)}st.h
-shape.$(OBJEXT): {$(VPATH)}subst.h
-shape.$(OBJEXT): {$(VPATH)}symbol.h
-shape.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-shape.$(OBJEXT): {$(VPATH)}thread_native.h
-shape.$(OBJEXT): {$(VPATH)}variable.h
-shape.$(OBJEXT): {$(VPATH)}vm_core.h
-shape.$(OBJEXT): {$(VPATH)}vm_debug.h
-shape.$(OBJEXT): {$(VPATH)}vm_opts.h
-shape.$(OBJEXT): {$(VPATH)}vm_sync.h
-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/ruby.h
-signal.$(OBJEXT): $(hdrdir)/ruby/version.h
-signal.$(OBJEXT): $(top_srcdir)/internal/array.h
-signal.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-signal.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-signal.$(OBJEXT): $(top_srcdir)/internal/error.h
-signal.$(OBJEXT): $(top_srcdir)/internal/eval.h
-signal.$(OBJEXT): $(top_srcdir)/internal/gc.h
-signal.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-signal.$(OBJEXT): $(top_srcdir)/internal/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/variable.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)}constant.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/abi.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/packed_struct.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/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/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/stdckdint.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)}rubyparser.h
-signal.$(OBJEXT): {$(VPATH)}shape.h
-signal.$(OBJEXT): {$(VPATH)}signal.c
-signal.$(OBJEXT): {$(VPATH)}st.h
-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/ruby.h
-sprintf.$(OBJEXT): $(hdrdir)/ruby/version.h
-sprintf.$(OBJEXT): $(top_srcdir)/internal/bignum.h
-sprintf.$(OBJEXT): $(top_srcdir)/internal/bits.h
-sprintf.$(OBJEXT): $(top_srcdir)/internal/class.h
-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/variable.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)}constant.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/abi.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/packed_struct.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/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/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/stdckdint.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
-sprintf.$(OBJEXT): {$(VPATH)}re.h
-sprintf.$(OBJEXT): {$(VPATH)}regex.h
-sprintf.$(OBJEXT): {$(VPATH)}shape.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/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/st.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/abi.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/packed_struct.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/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/scan_args.h
-st.$(OBJEXT): {$(VPATH)}internal/special_consts.h
-st.$(OBJEXT): {$(VPATH)}internal/st.h
-st.$(OBJEXT): {$(VPATH)}internal/static_assert.h
-st.$(OBJEXT): {$(VPATH)}internal/stdalign.h
-st.$(OBJEXT): {$(VPATH)}internal/stdbool.h
-st.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
-st.$(OBJEXT): {$(VPATH)}internal/symbol.h
-st.$(OBJEXT): {$(VPATH)}internal/value.h
-st.$(OBJEXT): {$(VPATH)}internal/value_type.h
-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/ruby.h
-strftime.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-strftime.$(OBJEXT): $(top_srcdir)/internal/encoding.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/abi.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/packed_struct.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/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/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/stdckdint.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
-strftime.$(OBJEXT): {$(VPATH)}st.h
-strftime.$(OBJEXT): {$(VPATH)}strftime.c
-strftime.$(OBJEXT): {$(VPATH)}subst.h
-strftime.$(OBJEXT): {$(VPATH)}timev.h
-strftime.$(OBJEXT): {$(VPATH)}util.h
-string.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-string.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-string.$(OBJEXT): $(CCAN_DIR)/list/list.h
-string.$(OBJEXT): $(CCAN_DIR)/str/str.h
-string.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-string.$(OBJEXT): $(hdrdir)/ruby/version.h
-string.$(OBJEXT): $(top_srcdir)/internal/array.h
-string.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-string.$(OBJEXT): $(top_srcdir)/internal/bignum.h
-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/imemo.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/variable.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)}constant.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)}id.h
-string.$(OBJEXT): {$(VPATH)}id_table.h
-string.$(OBJEXT): {$(VPATH)}intern.h
-string.$(OBJEXT): {$(VPATH)}internal.h
-string.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/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/stdckdint.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)}method.h
-string.$(OBJEXT): {$(VPATH)}missing.h
-string.$(OBJEXT): {$(VPATH)}node.h
-string.$(OBJEXT): {$(VPATH)}onigmo.h
-string.$(OBJEXT): {$(VPATH)}oniguruma.h
-string.$(OBJEXT): {$(VPATH)}probes.dmyh
-string.$(OBJEXT): {$(VPATH)}probes.h
-string.$(OBJEXT): {$(VPATH)}re.h
-string.$(OBJEXT): {$(VPATH)}regex.h
-string.$(OBJEXT): {$(VPATH)}ruby_assert.h
-string.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-string.$(OBJEXT): {$(VPATH)}rubyparser.h
-string.$(OBJEXT): {$(VPATH)}shape.h
-string.$(OBJEXT): {$(VPATH)}st.h
-string.$(OBJEXT): {$(VPATH)}string.c
-string.$(OBJEXT): {$(VPATH)}subst.h
-string.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-string.$(OBJEXT): {$(VPATH)}thread_native.h
-string.$(OBJEXT): {$(VPATH)}util.h
-string.$(OBJEXT): {$(VPATH)}vm_core.h
-string.$(OBJEXT): {$(VPATH)}vm_debug.h
-string.$(OBJEXT): {$(VPATH)}vm_opts.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/ruby.h
-struct.$(OBJEXT): $(hdrdir)/ruby/version.h
-struct.$(OBJEXT): $(top_srcdir)/internal/array.h
-struct.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-struct.$(OBJEXT): $(top_srcdir)/internal/class.h
-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/sanitizers.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/variable.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)}constant.h
-struct.$(OBJEXT): {$(VPATH)}debug_counter.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/abi.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/packed_struct.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/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/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/stdckdint.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)}rubyparser.h
-struct.$(OBJEXT): {$(VPATH)}shape.h
-struct.$(OBJEXT): {$(VPATH)}st.h
-struct.$(OBJEXT): {$(VPATH)}struct.c
-struct.$(OBJEXT): {$(VPATH)}subst.h
-struct.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-struct.$(OBJEXT): {$(VPATH)}thread_native.h
-struct.$(OBJEXT): {$(VPATH)}vm_core.h
-struct.$(OBJEXT): {$(VPATH)}vm_debug.h
-struct.$(OBJEXT): {$(VPATH)}vm_opts.h
-struct.$(OBJEXT): {$(VPATH)}vm_sync.h
-symbol.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-symbol.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-symbol.$(OBJEXT): $(CCAN_DIR)/list/list.h
-symbol.$(OBJEXT): $(CCAN_DIR)/str/str.h
-symbol.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-symbol.$(OBJEXT): $(hdrdir)/ruby/version.h
-symbol.$(OBJEXT): $(top_srcdir)/internal/array.h
-symbol.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-symbol.$(OBJEXT): $(top_srcdir)/internal/class.h
-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/imemo.h
-symbol.$(OBJEXT): $(top_srcdir)/internal/object.h
-symbol.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-symbol.$(OBJEXT): $(top_srcdir)/internal/serial.h
-symbol.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-symbol.$(OBJEXT): $(top_srcdir)/internal/string.h
-symbol.$(OBJEXT): $(top_srcdir)/internal/symbol.h
-symbol.$(OBJEXT): $(top_srcdir)/internal/variable.h
-symbol.$(OBJEXT): $(top_srcdir)/internal/vm.h
-symbol.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-symbol.$(OBJEXT): {$(VPATH)}assert.h
-symbol.$(OBJEXT): {$(VPATH)}atomic.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)}builtin.h
-symbol.$(OBJEXT): {$(VPATH)}config.h
-symbol.$(OBJEXT): {$(VPATH)}constant.h
-symbol.$(OBJEXT): {$(VPATH)}debug_counter.h
-symbol.$(OBJEXT): {$(VPATH)}defines.h
-symbol.$(OBJEXT): {$(VPATH)}encoding.h
-symbol.$(OBJEXT): {$(VPATH)}id.c
-symbol.$(OBJEXT): {$(VPATH)}id.h
-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/abi.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/packed_struct.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/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/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/stdckdint.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)}method.h
-symbol.$(OBJEXT): {$(VPATH)}missing.h
-symbol.$(OBJEXT): {$(VPATH)}node.h
-symbol.$(OBJEXT): {$(VPATH)}onigmo.h
-symbol.$(OBJEXT): {$(VPATH)}oniguruma.h
-symbol.$(OBJEXT): {$(VPATH)}probes.dmyh
-symbol.$(OBJEXT): {$(VPATH)}probes.h
-symbol.$(OBJEXT): {$(VPATH)}ruby_assert.h
-symbol.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-symbol.$(OBJEXT): {$(VPATH)}rubyparser.h
-symbol.$(OBJEXT): {$(VPATH)}shape.h
-symbol.$(OBJEXT): {$(VPATH)}st.h
-symbol.$(OBJEXT): {$(VPATH)}subst.h
-symbol.$(OBJEXT): {$(VPATH)}symbol.c
-symbol.$(OBJEXT): {$(VPATH)}symbol.h
-symbol.$(OBJEXT): {$(VPATH)}symbol.rb
-symbol.$(OBJEXT): {$(VPATH)}symbol.rbinc
-symbol.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-symbol.$(OBJEXT): {$(VPATH)}thread_native.h
-symbol.$(OBJEXT): {$(VPATH)}vm_core.h
-symbol.$(OBJEXT): {$(VPATH)}vm_debug.h
-symbol.$(OBJEXT): {$(VPATH)}vm_opts.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): $(hdrdir)/ruby/version.h
-thread.$(OBJEXT): $(top_srcdir)/internal/array.h
-thread.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-thread.$(OBJEXT): $(top_srcdir)/internal/bits.h
-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/sanitizers.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/variable.h
-thread.$(OBJEXT): $(top_srcdir)/internal/vm.h
-thread.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-thread.$(OBJEXT): $(top_srcdir)/prism/defines.h
-thread.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-thread.$(OBJEXT): $(top_srcdir)/prism/node.h
-thread.$(OBJEXT): $(top_srcdir)/prism/options.h
-thread.$(OBJEXT): $(top_srcdir)/prism/pack.h
-thread.$(OBJEXT): $(top_srcdir)/prism/parser.h
-thread.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-thread.$(OBJEXT): $(top_srcdir)/prism/prism.h
-thread.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-thread.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-thread.$(OBJEXT): {$(VPATH)}$(COROUTINE_H)
-thread.$(OBJEXT): {$(VPATH)}assert.h
-thread.$(OBJEXT): {$(VPATH)}atomic.h
-thread.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-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)}builtin.h
-thread.$(OBJEXT): {$(VPATH)}config.h
-thread.$(OBJEXT): {$(VPATH)}constant.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)}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/abi.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/packed_struct.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/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/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/stdckdint.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
-thread.$(OBJEXT): {$(VPATH)}missing.h
-thread.$(OBJEXT): {$(VPATH)}node.h
-thread.$(OBJEXT): {$(VPATH)}onigmo.h
-thread.$(OBJEXT): {$(VPATH)}oniguruma.h
-thread.$(OBJEXT): {$(VPATH)}prism/ast.h
-thread.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-thread.$(OBJEXT): {$(VPATH)}prism/version.h
-thread.$(OBJEXT): {$(VPATH)}prism_compile.h
-thread.$(OBJEXT): {$(VPATH)}ractor.h
-thread.$(OBJEXT): {$(VPATH)}ractor_core.h
-thread.$(OBJEXT): {$(VPATH)}rjit.h
-thread.$(OBJEXT): {$(VPATH)}ruby_assert.h
-thread.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-thread.$(OBJEXT): {$(VPATH)}rubyparser.h
-thread.$(OBJEXT): {$(VPATH)}shape.h
-thread.$(OBJEXT): {$(VPATH)}st.h
-thread.$(OBJEXT): {$(VPATH)}subst.h
-thread.$(OBJEXT): {$(VPATH)}thread.c
-thread.$(OBJEXT): {$(VPATH)}thread.h
-thread.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).c
-thread.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-thread.$(OBJEXT): {$(VPATH)}thread_native.h
-thread.$(OBJEXT): {$(VPATH)}thread_pthread_mn.c
-thread.$(OBJEXT): {$(VPATH)}thread_sync.c
-thread.$(OBJEXT): {$(VPATH)}thread_sync.rbinc
-thread.$(OBJEXT): {$(VPATH)}timev.h
-thread.$(OBJEXT): {$(VPATH)}vm_core.h
-thread.$(OBJEXT): {$(VPATH)}vm_debug.h
-thread.$(OBJEXT): {$(VPATH)}vm_opts.h
-thread.$(OBJEXT): {$(VPATH)}vm_sync.h
-time.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-time.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-time.$(OBJEXT): $(CCAN_DIR)/list/list.h
-time.$(OBJEXT): $(CCAN_DIR)/str/str.h
-time.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-time.$(OBJEXT): $(top_srcdir)/internal/array.h
-time.$(OBJEXT): $(top_srcdir)/internal/basic_operators.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/hash.h
-time.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-time.$(OBJEXT): $(top_srcdir)/internal/numeric.h
-time.$(OBJEXT): $(top_srcdir)/internal/rational.h
-time.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-time.$(OBJEXT): $(top_srcdir)/internal/serial.h
-time.$(OBJEXT): $(top_srcdir)/internal/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)}atomic.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/abi.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/packed_struct.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/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/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/stdckdint.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)}method.h
-time.$(OBJEXT): {$(VPATH)}missing.h
-time.$(OBJEXT): {$(VPATH)}node.h
-time.$(OBJEXT): {$(VPATH)}onigmo.h
-time.$(OBJEXT): {$(VPATH)}oniguruma.h
-time.$(OBJEXT): {$(VPATH)}ruby_assert.h
-time.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-time.$(OBJEXT): {$(VPATH)}rubyparser.h
-time.$(OBJEXT): {$(VPATH)}shape.h
-time.$(OBJEXT): {$(VPATH)}st.h
-time.$(OBJEXT): {$(VPATH)}subst.h
-time.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-time.$(OBJEXT): {$(VPATH)}thread_native.h
-time.$(OBJEXT): {$(VPATH)}time.c
-time.$(OBJEXT): {$(VPATH)}timev.h
-time.$(OBJEXT): {$(VPATH)}timev.rbinc
-time.$(OBJEXT): {$(VPATH)}vm_core.h
-time.$(OBJEXT): {$(VPATH)}vm_opts.h
-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/variable.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)}constant.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/abi.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/packed_struct.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/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/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/stdckdint.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
-transcode.$(OBJEXT): {$(VPATH)}shape.h
-transcode.$(OBJEXT): {$(VPATH)}st.h
-transcode.$(OBJEXT): {$(VPATH)}subst.h
-transcode.$(OBJEXT): {$(VPATH)}transcode.c
-transcode.$(OBJEXT): {$(VPATH)}transcode_data.h
-util.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-util.$(OBJEXT): $(top_srcdir)/internal/array.h
-util.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-util.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-util.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-util.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-util.$(OBJEXT): $(top_srcdir)/internal/util.h
-util.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-util.$(OBJEXT): {$(VPATH)}assert.h
-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/abi.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/packed_struct.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/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/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/stdckdint.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
-util.$(OBJEXT): {$(VPATH)}util.h
-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/ruby.h
-variable.$(OBJEXT): $(hdrdir)/ruby/version.h
-variable.$(OBJEXT): $(top_srcdir)/internal/array.h
-variable.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-variable.$(OBJEXT): $(top_srcdir)/internal/class.h
-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/sanitizers.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)}debug_counter.h
-variable.$(OBJEXT): {$(VPATH)}defines.h
-variable.$(OBJEXT): {$(VPATH)}encoding.h
-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/abi.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/packed_struct.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/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/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/stdckdint.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)}rubyparser.h
-variable.$(OBJEXT): {$(VPATH)}shape.h
-variable.$(OBJEXT): {$(VPATH)}st.h
-variable.$(OBJEXT): {$(VPATH)}subst.h
-variable.$(OBJEXT): {$(VPATH)}symbol.h
-variable.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-variable.$(OBJEXT): {$(VPATH)}thread_native.h
-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
-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/basic_operators.h
-version.$(OBJEXT): $(top_srcdir)/internal/cmdlineopt.h
-version.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-version.$(OBJEXT): $(top_srcdir)/internal/gc.h
-version.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-version.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-version.$(OBJEXT): $(top_srcdir)/internal/serial.h
-version.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-version.$(OBJEXT): $(top_srcdir)/internal/variable.h
-version.$(OBJEXT): $(top_srcdir)/internal/vm.h
-version.$(OBJEXT): $(top_srcdir)/internal/warnings.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)}constant.h
-version.$(OBJEXT): {$(VPATH)}debug_counter.h
-version.$(OBJEXT): {$(VPATH)}defines.h
-version.$(OBJEXT): {$(VPATH)}encoding.h
-version.$(OBJEXT): {$(VPATH)}id.h
-version.$(OBJEXT): {$(VPATH)}id_table.h
-version.$(OBJEXT): {$(VPATH)}intern.h
-version.$(OBJEXT): {$(VPATH)}internal.h
-version.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/encoding/coderange.h
-version.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
-version.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
-version.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
-version.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
-version.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
-version.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
-version.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
-version.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.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/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/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/stdckdint.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)}node.h
-version.$(OBJEXT): {$(VPATH)}onigmo.h
-version.$(OBJEXT): {$(VPATH)}oniguruma.h
-version.$(OBJEXT): {$(VPATH)}revision.h
-version.$(OBJEXT): {$(VPATH)}rjit.h
-version.$(OBJEXT): {$(VPATH)}ruby_assert.h
-version.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-version.$(OBJEXT): {$(VPATH)}rubyparser.h
-version.$(OBJEXT): {$(VPATH)}shape.h
-version.$(OBJEXT): {$(VPATH)}st.h
-version.$(OBJEXT): {$(VPATH)}subst.h
-version.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-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): $(hdrdir)/ruby/version.h
-vm.$(OBJEXT): $(top_srcdir)/internal/array.h
-vm.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-vm.$(OBJEXT): $(top_srcdir)/internal/bignum.h
-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/complex.h
-vm.$(OBJEXT): $(top_srcdir)/internal/cont.h
-vm.$(OBJEXT): $(top_srcdir)/internal/encoding.h
-vm.$(OBJEXT): $(top_srcdir)/internal/error.h
-vm.$(OBJEXT): $(top_srcdir)/internal/eval.h
-vm.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
-vm.$(OBJEXT): $(top_srcdir)/internal/gc.h
-vm.$(OBJEXT): $(top_srcdir)/internal/hash.h
-vm.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-vm.$(OBJEXT): $(top_srcdir)/internal/inits.h
-vm.$(OBJEXT): $(top_srcdir)/internal/missing.h
-vm.$(OBJEXT): $(top_srcdir)/internal/numeric.h
-vm.$(OBJEXT): $(top_srcdir)/internal/object.h
-vm.$(OBJEXT): $(top_srcdir)/internal/parse.h
-vm.$(OBJEXT): $(top_srcdir)/internal/proc.h
-vm.$(OBJEXT): $(top_srcdir)/internal/random.h
-vm.$(OBJEXT): $(top_srcdir)/internal/rational.h
-vm.$(OBJEXT): $(top_srcdir)/internal/re.h
-vm.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
-vm.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-vm.$(OBJEXT): $(top_srcdir)/internal/serial.h
-vm.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-vm.$(OBJEXT): $(top_srcdir)/internal/string.h
-vm.$(OBJEXT): $(top_srcdir)/internal/struct.h
-vm.$(OBJEXT): $(top_srcdir)/internal/symbol.h
-vm.$(OBJEXT): $(top_srcdir)/internal/thread.h
-vm.$(OBJEXT): $(top_srcdir)/internal/transcode.h
-vm.$(OBJEXT): $(top_srcdir)/internal/variable.h
-vm.$(OBJEXT): $(top_srcdir)/internal/vm.h
-vm.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-vm.$(OBJEXT): $(top_srcdir)/prism/defines.h
-vm.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-vm.$(OBJEXT): $(top_srcdir)/prism/node.h
-vm.$(OBJEXT): $(top_srcdir)/prism/options.h
-vm.$(OBJEXT): $(top_srcdir)/prism/pack.h
-vm.$(OBJEXT): $(top_srcdir)/prism/parser.h
-vm.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-vm.$(OBJEXT): $(top_srcdir)/prism/prism.h
-vm.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-vm.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-vm.$(OBJEXT): {$(VPATH)}assert.h
-vm.$(OBJEXT): {$(VPATH)}atomic.h
-vm.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-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)}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)}id.h
-vm.$(OBJEXT): {$(VPATH)}id_table.h
-vm.$(OBJEXT): {$(VPATH)}insns.def
-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/abi.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/packed_struct.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/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/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/stdckdint.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)}node.h
-vm.$(OBJEXT): {$(VPATH)}onigmo.h
-vm.$(OBJEXT): {$(VPATH)}oniguruma.h
-vm.$(OBJEXT): {$(VPATH)}prism/ast.h
-vm.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-vm.$(OBJEXT): {$(VPATH)}prism/version.h
-vm.$(OBJEXT): {$(VPATH)}prism_compile.h
-vm.$(OBJEXT): {$(VPATH)}probes.dmyh
-vm.$(OBJEXT): {$(VPATH)}probes.h
-vm.$(OBJEXT): {$(VPATH)}probes_helper.h
-vm.$(OBJEXT): {$(VPATH)}ractor.h
-vm.$(OBJEXT): {$(VPATH)}ractor_core.h
-vm.$(OBJEXT): {$(VPATH)}rjit.h
-vm.$(OBJEXT): {$(VPATH)}ruby_assert.h
-vm.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-vm.$(OBJEXT): {$(VPATH)}rubyparser.h
-vm.$(OBJEXT): {$(VPATH)}shape.h
-vm.$(OBJEXT): {$(VPATH)}st.h
-vm.$(OBJEXT): {$(VPATH)}subst.h
-vm.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-vm.$(OBJEXT): {$(VPATH)}thread_native.h
-vm.$(OBJEXT): {$(VPATH)}variable.h
-vm.$(OBJEXT): {$(VPATH)}vm.c
-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
-vm.$(OBJEXT): {$(VPATH)}vm_exec.c
-vm.$(OBJEXT): {$(VPATH)}vm_exec.h
-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/ruby.h
-vm_backtrace.$(OBJEXT): $(hdrdir)/ruby/version.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/array.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/class.h
-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/sanitizers.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/variable.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/vm.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/defines.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/node.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/options.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/pack.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/parser.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/prism.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}assert.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}atomic.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-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)}constant.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}debug.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}debug_counter.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}defines.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}encoding.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}eval_intern.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}id.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}id_table.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}intern.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}internal.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/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/stdckdint.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
-vm_backtrace.$(OBJEXT): {$(VPATH)}node.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}onigmo.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}oniguruma.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}prism/ast.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}prism/version.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}prism_compile.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}ruby_assert.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}rubyparser.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}shape.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}st.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}subst.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-vm_backtrace.$(OBJEXT): {$(VPATH)}thread_native.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}vm_backtrace.c
-vm_backtrace.$(OBJEXT): {$(VPATH)}vm_core.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}vm_debug.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}vm_opts.h
-vm_backtrace.$(OBJEXT): {$(VPATH)}vm_sync.h
-vm_dump.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-vm_dump.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-vm_dump.$(OBJEXT): $(CCAN_DIR)/list/list.h
-vm_dump.$(OBJEXT): $(CCAN_DIR)/str/str.h
-vm_dump.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-vm_dump.$(OBJEXT): $(top_srcdir)/internal/array.h
-vm_dump.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-vm_dump.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-vm_dump.$(OBJEXT): $(top_srcdir)/internal/gc.h
-vm_dump.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-vm_dump.$(OBJEXT): $(top_srcdir)/internal/sanitizers.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): $(top_srcdir)/prism/defines.h
-vm_dump.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-vm_dump.$(OBJEXT): $(top_srcdir)/prism/node.h
-vm_dump.$(OBJEXT): $(top_srcdir)/prism/options.h
-vm_dump.$(OBJEXT): $(top_srcdir)/prism/pack.h
-vm_dump.$(OBJEXT): $(top_srcdir)/prism/parser.h
-vm_dump.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-vm_dump.$(OBJEXT): $(top_srcdir)/prism/prism.h
-vm_dump.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-vm_dump.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-vm_dump.$(OBJEXT): {$(VPATH)}addr2line.h
-vm_dump.$(OBJEXT): {$(VPATH)}assert.h
-vm_dump.$(OBJEXT): {$(VPATH)}atomic.h
-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)}defines.h
-vm_dump.$(OBJEXT): {$(VPATH)}encoding.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/abi.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/packed_struct.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/encoding/coderange.h
-vm_dump.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
-vm_dump.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
-vm_dump.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
-vm_dump.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
-vm_dump.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
-vm_dump.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
-vm_dump.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
-vm_dump.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.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/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/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/stdckdint.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)}onigmo.h
-vm_dump.$(OBJEXT): {$(VPATH)}oniguruma.h
-vm_dump.$(OBJEXT): {$(VPATH)}prism/ast.h
-vm_dump.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-vm_dump.$(OBJEXT): {$(VPATH)}prism/version.h
-vm_dump.$(OBJEXT): {$(VPATH)}prism_compile.h
-vm_dump.$(OBJEXT): {$(VPATH)}procstat_vm.c
-vm_dump.$(OBJEXT): {$(VPATH)}ractor.h
-vm_dump.$(OBJEXT): {$(VPATH)}ractor_core.h
-vm_dump.$(OBJEXT): {$(VPATH)}ruby_assert.h
-vm_dump.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-vm_dump.$(OBJEXT): {$(VPATH)}rubyparser.h
-vm_dump.$(OBJEXT): {$(VPATH)}shape.h
-vm_dump.$(OBJEXT): {$(VPATH)}st.h
-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/basic_operators.h
-vm_sync.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-vm_sync.$(OBJEXT): $(top_srcdir)/internal/gc.h
-vm_sync.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-vm_sync.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-vm_sync.$(OBJEXT): $(top_srcdir)/internal/serial.h
-vm_sync.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-vm_sync.$(OBJEXT): $(top_srcdir)/internal/thread.h
-vm_sync.$(OBJEXT): $(top_srcdir)/internal/variable.h
-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)}constant.h
-vm_sync.$(OBJEXT): {$(VPATH)}debug_counter.h
-vm_sync.$(OBJEXT): {$(VPATH)}defines.h
-vm_sync.$(OBJEXT): {$(VPATH)}encoding.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/abi.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/packed_struct.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/encoding/coderange.h
-vm_sync.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
-vm_sync.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
-vm_sync.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
-vm_sync.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
-vm_sync.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
-vm_sync.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
-vm_sync.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
-vm_sync.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.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/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/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/stdckdint.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)}onigmo.h
-vm_sync.$(OBJEXT): {$(VPATH)}oniguruma.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)}rubyparser.h
-vm_sync.$(OBJEXT): {$(VPATH)}shape.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/basic_operators.h
-vm_trace.$(OBJEXT): $(top_srcdir)/internal/bits.h
-vm_trace.$(OBJEXT): $(top_srcdir)/internal/class.h
-vm_trace.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-vm_trace.$(OBJEXT): $(top_srcdir)/internal/gc.h
-vm_trace.$(OBJEXT): $(top_srcdir)/internal/hash.h
-vm_trace.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-vm_trace.$(OBJEXT): $(top_srcdir)/internal/sanitizers.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/thread.h
-vm_trace.$(OBJEXT): $(top_srcdir)/internal/variable.h
-vm_trace.$(OBJEXT): $(top_srcdir)/internal/vm.h
-vm_trace.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-vm_trace.$(OBJEXT): $(top_srcdir)/prism/defines.h
-vm_trace.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-vm_trace.$(OBJEXT): $(top_srcdir)/prism/node.h
-vm_trace.$(OBJEXT): $(top_srcdir)/prism/options.h
-vm_trace.$(OBJEXT): $(top_srcdir)/prism/pack.h
-vm_trace.$(OBJEXT): $(top_srcdir)/prism/parser.h
-vm_trace.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-vm_trace.$(OBJEXT): $(top_srcdir)/prism/prism.h
-vm_trace.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-vm_trace.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-vm_trace.$(OBJEXT): {$(VPATH)}assert.h
-vm_trace.$(OBJEXT): {$(VPATH)}atomic.h
-vm_trace.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-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)}constant.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)}id_table.h
-vm_trace.$(OBJEXT): {$(VPATH)}intern.h
-vm_trace.$(OBJEXT): {$(VPATH)}internal.h
-vm_trace.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/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/stdckdint.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)}node.h
-vm_trace.$(OBJEXT): {$(VPATH)}onigmo.h
-vm_trace.$(OBJEXT): {$(VPATH)}oniguruma.h
-vm_trace.$(OBJEXT): {$(VPATH)}prism/ast.h
-vm_trace.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-vm_trace.$(OBJEXT): {$(VPATH)}prism/version.h
-vm_trace.$(OBJEXT): {$(VPATH)}prism_compile.h
-vm_trace.$(OBJEXT): {$(VPATH)}ractor.h
-vm_trace.$(OBJEXT): {$(VPATH)}rjit.h
-vm_trace.$(OBJEXT): {$(VPATH)}ruby_assert.h
-vm_trace.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-vm_trace.$(OBJEXT): {$(VPATH)}rubyparser.h
-vm_trace.$(OBJEXT): {$(VPATH)}shape.h
-vm_trace.$(OBJEXT): {$(VPATH)}st.h
-vm_trace.$(OBJEXT): {$(VPATH)}subst.h
-vm_trace.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-vm_trace.$(OBJEXT): {$(VPATH)}thread_native.h
-vm_trace.$(OBJEXT): {$(VPATH)}trace_point.rbinc
-vm_trace.$(OBJEXT): {$(VPATH)}vm_core.h
-vm_trace.$(OBJEXT): {$(VPATH)}vm_debug.h
-vm_trace.$(OBJEXT): {$(VPATH)}vm_opts.h
-vm_trace.$(OBJEXT): {$(VPATH)}vm_sync.h
-vm_trace.$(OBJEXT): {$(VPATH)}vm_trace.c
-vm_trace.$(OBJEXT): {$(VPATH)}yjit.h
-weakmap.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
-weakmap.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
-weakmap.$(OBJEXT): $(CCAN_DIR)/list/list.h
-weakmap.$(OBJEXT): $(CCAN_DIR)/str/str.h
-weakmap.$(OBJEXT): $(hdrdir)/ruby/ruby.h
-weakmap.$(OBJEXT): $(top_srcdir)/internal/array.h
-weakmap.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
-weakmap.$(OBJEXT): $(top_srcdir)/internal/compilers.h
-weakmap.$(OBJEXT): $(top_srcdir)/internal/gc.h
-weakmap.$(OBJEXT): $(top_srcdir)/internal/hash.h
-weakmap.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-weakmap.$(OBJEXT): $(top_srcdir)/internal/proc.h
-weakmap.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
-weakmap.$(OBJEXT): $(top_srcdir)/internal/serial.h
-weakmap.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
-weakmap.$(OBJEXT): $(top_srcdir)/internal/vm.h
-weakmap.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-weakmap.$(OBJEXT): {$(VPATH)}assert.h
-weakmap.$(OBJEXT): {$(VPATH)}atomic.h
-weakmap.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-weakmap.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
-weakmap.$(OBJEXT): {$(VPATH)}backward/2/bool.h
-weakmap.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
-weakmap.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
-weakmap.$(OBJEXT): {$(VPATH)}backward/2/limits.h
-weakmap.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
-weakmap.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
-weakmap.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
-weakmap.$(OBJEXT): {$(VPATH)}config.h
-weakmap.$(OBJEXT): {$(VPATH)}defines.h
-weakmap.$(OBJEXT): {$(VPATH)}encoding.h
-weakmap.$(OBJEXT): {$(VPATH)}id.h
-weakmap.$(OBJEXT): {$(VPATH)}intern.h
-weakmap.$(OBJEXT): {$(VPATH)}internal.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/abi.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/anyargs.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/assume.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/attr/const.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/attr/error.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/attr/format.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/cast.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/config.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/constant_p.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/core.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/core/robject.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/ctype.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/dllexport.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/dosish.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/error.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/eval.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/event.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/fl_type.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/gc.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/glob.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/globals.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/has/extension.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/has/feature.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/has/warning.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/array.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/class.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/error.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/file.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/io.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/load.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/object.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/process.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/random.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/range.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/re.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/select.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/string.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/time.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/interpreter.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/iterator.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/memory.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/method.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/module.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/newobj.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/scan_args.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/special_consts.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/static_assert.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/stdalign.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/stdbool.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/symbol.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/value.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/value_type.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/variable.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/warning_push.h
-weakmap.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
-weakmap.$(OBJEXT): {$(VPATH)}method.h
-weakmap.$(OBJEXT): {$(VPATH)}missing.h
-weakmap.$(OBJEXT): {$(VPATH)}node.h
-weakmap.$(OBJEXT): {$(VPATH)}onigmo.h
-weakmap.$(OBJEXT): {$(VPATH)}oniguruma.h
-weakmap.$(OBJEXT): {$(VPATH)}ruby_assert.h
-weakmap.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-weakmap.$(OBJEXT): {$(VPATH)}rubyparser.h
-weakmap.$(OBJEXT): {$(VPATH)}st.h
-weakmap.$(OBJEXT): {$(VPATH)}subst.h
-weakmap.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
-weakmap.$(OBJEXT): {$(VPATH)}thread_native.h
-weakmap.$(OBJEXT): {$(VPATH)}vm_core.h
-weakmap.$(OBJEXT): {$(VPATH)}vm_opts.h
-weakmap.$(OBJEXT): {$(VPATH)}weakmap.c
-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/basic_operators.h
-yjit.$(OBJEXT): $(top_srcdir)/internal/bignum.h
-yjit.$(OBJEXT): $(top_srcdir)/internal/bits.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/cont.h
-yjit.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
-yjit.$(OBJEXT): $(top_srcdir)/internal/gc.h
-yjit.$(OBJEXT): $(top_srcdir)/internal/hash.h
-yjit.$(OBJEXT): $(top_srcdir)/internal/imemo.h
-yjit.$(OBJEXT): $(top_srcdir)/internal/numeric.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/variable.h
-yjit.$(OBJEXT): $(top_srcdir)/internal/vm.h
-yjit.$(OBJEXT): $(top_srcdir)/internal/warnings.h
-yjit.$(OBJEXT): $(top_srcdir)/prism/defines.h
-yjit.$(OBJEXT): $(top_srcdir)/prism/encoding.h
-yjit.$(OBJEXT): $(top_srcdir)/prism/node.h
-yjit.$(OBJEXT): $(top_srcdir)/prism/options.h
-yjit.$(OBJEXT): $(top_srcdir)/prism/pack.h
-yjit.$(OBJEXT): $(top_srcdir)/prism/parser.h
-yjit.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
-yjit.$(OBJEXT): $(top_srcdir)/prism/prism.h
-yjit.$(OBJEXT): $(top_srcdir)/prism/regexp.h
-yjit.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
-yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
-yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
-yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
-yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
-yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
-yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
-yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
-yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
-yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string_list.h
-yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
-yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
-yjit.$(OBJEXT): {$(VPATH)}assert.h
-yjit.$(OBJEXT): {$(VPATH)}atomic.h
-yjit.$(OBJEXT): {$(VPATH)}backward/2/assume.h
-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)}debug.h
-yjit.$(OBJEXT): {$(VPATH)}debug_counter.h
-yjit.$(OBJEXT): {$(VPATH)}defines.h
-yjit.$(OBJEXT): {$(VPATH)}encoding.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/abi.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/packed_struct.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/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/numeric.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/stdckdint.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)}prism/ast.h
-yjit.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
-yjit.$(OBJEXT): {$(VPATH)}prism/version.h
-yjit.$(OBJEXT): {$(VPATH)}prism_compile.h
-yjit.$(OBJEXT): {$(VPATH)}probes.dmyh
-yjit.$(OBJEXT): {$(VPATH)}probes.h
-yjit.$(OBJEXT): {$(VPATH)}probes_helper.h
-yjit.$(OBJEXT): {$(VPATH)}ruby_assert.h
-yjit.$(OBJEXT): {$(VPATH)}ruby_atomic.h
-yjit.$(OBJEXT): {$(VPATH)}rubyparser.h
-yjit.$(OBJEXT): {$(VPATH)}shape.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_insnhelper.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.rbinc
-# AUTOGENERATED DEPENDENCIES END
+!include $(srcdir)/prism/srcs.mk
+!include $(srcdir)/depend
diff --git a/compar.c b/compar.c
index 081b4e2dea..142cb12a0c 100644
--- a/compar.c
+++ b/compar.c
@@ -95,10 +95,13 @@ cmpint(VALUE x, VALUE y)
/*
* call-seq:
- * obj > other -> true or false
+ * self > other -> true or false
*
- * Compares two objects based on the receiver's <code><=></code>
- * method, returning true if it returns a value greater than 0.
+ * Returns whether +self+ is "greater than" +other+;
+ * equivalent to <tt>(self <=> other) > 0</tt>:
+ *
+ * 'foo' > 'foo' # => false
+ * 'food' > 'foo' # => true
*/
static VALUE
@@ -109,10 +112,15 @@ cmp_gt(VALUE x, VALUE y)
/*
* call-seq:
- * obj >= other -> true or false
+ * self >= other -> true or false
+ *
+ * Returns whether +self+ is "greater than or equal to" +other+;
+ * equivalent to <tt>(self <=> other) >= 0</tt>:
+ *
+ * 'food' >= 'foo' # => true
+ * 'foo' >= 'foo' # => true
+ * 'foo' >= 'food' # => false
*
- * Compares two objects based on the receiver's <code><=></code>
- * method, returning true if it returns a value greater than or equal to 0.
*/
static VALUE
@@ -123,10 +131,14 @@ cmp_ge(VALUE x, VALUE y)
/*
* call-seq:
- * obj < other -> true or false
+ * self < other -> true or false
+ *
+ * Returns whether +self+ is "less than" +other+;
+ * equivalent to <tt>(self <=> other) < 0</tt>:
+ *
+ * 'foo' < 'foo' # => false
+ * 'foo' < 'food' # => true
*
- * Compares two objects based on the receiver's <code><=></code>
- * method, returning true if it returns a value less than 0.
*/
static VALUE
@@ -137,10 +149,15 @@ cmp_lt(VALUE x, VALUE y)
/*
* call-seq:
- * obj <= other -> true or false
+ * self <= other -> true or false
+ *
+ * Returns whether +self+ is "less than or equal to" +other+;
+ * equivalent to <tt>(self <=> other) <= 0</tt>:
+ *
+ * 'foo' <= 'foo' # => true
+ * 'foo' <= 'food' # => true
+ * 'food' <= 'foo' # => false
*
- * Compares two objects based on the receiver's <code><=></code>
- * method, returning true if it returns a value less than or equal to 0.
*/
static VALUE
@@ -293,7 +310,7 @@ cmp_clamp(int argc, VALUE *argv, VALUE x)
*
* == What's Here
*
- * \Module \Comparable provides these methods, all of which use method <tt><=></tt>:
+ * Module \Comparable provides these methods, all of which use method <tt>#<=></tt>:
*
* - #<: Returns whether +self+ is less than the given object.
* - #<=: Returns whether +self+ is less than or equal to the given object.
diff --git a/compile.c b/compile.c
index a0bbcab54b..b7d6b07090 100644
--- a/compile.c
+++ b/compile.c
@@ -49,7 +49,6 @@
#include "insns_info.inc"
#define FIXNUM_INC(n, i) ((n)+(INT2FIX(i)&~FIXNUM_FLAG))
-#define FIXNUM_OR(n, i) ((n)|INT2FIX(i))
typedef struct iseq_link_element {
enum {
@@ -214,6 +213,9 @@ const ID rb_iseq_shared_exc_local_tbl[] = {idERROR_INFO};
#define NEW_CHILD_ISEQ(node, name, type, line_no) \
new_child_iseq(iseq, (node), rb_fstring(name), iseq, (type), (line_no))
+#define NEW_CHILD_ISEQ_WITH_CALLBACK(callback_func, name, type, line_no) \
+ new_child_iseq_with_callback(iseq, (callback_func), (name), iseq, (type), (line_no))
+
/* add instructions */
#define ADD_SEQ(seq1, seq2) \
APPEND_LIST((seq1), (seq2))
@@ -436,12 +438,10 @@ do { \
#define NO_CHECK(sub) (void)(sub)
#define BEFORE_RETURN
-/* leave name uninitialized so that compiler warn if INIT_ANCHOR is
- * missing */
#define DECL_ANCHOR(name) \
- LINK_ANCHOR name[1] = {{{ISEQ_ELEMENT_ANCHOR,},}}
+ LINK_ANCHOR name[1] = {{{ISEQ_ELEMENT_ANCHOR,},&name[0].anchor}}
#define INIT_ANCHOR(name) \
- (name->last = &name->anchor)
+ ((name->last = &name->anchor)->next = NULL) /* re-initialize */
static inline VALUE
freeze_hide_obj(VALUE obj)
@@ -487,15 +487,16 @@ static int iseq_setup_insn(rb_iseq_t *iseq, LINK_ANCHOR *const anchor);
static int iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *const anchor);
static int iseq_insns_unification(rb_iseq_t *iseq, LINK_ANCHOR *const anchor);
-static int iseq_set_local_table(rb_iseq_t *iseq, const rb_ast_id_table_t *tbl);
+static int iseq_set_local_table(rb_iseq_t *iseq, const rb_ast_id_table_t *tbl, const NODE *const node_args);
static int iseq_set_exception_local_table(rb_iseq_t *iseq);
static int iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const anchor, const NODE *const node);
static int iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor);
static int iseq_set_exception_table(rb_iseq_t *iseq);
static int iseq_set_optargs_table(rb_iseq_t *iseq);
+static int iseq_set_parameters_lvar_state(const rb_iseq_t *iseq);
-static int compile_defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, VALUE needstr);
+static int compile_defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, VALUE needstr, bool ignore);
static int compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int method_call_keywords, int popped);
/*
@@ -609,15 +610,26 @@ branch_coverage_valid_p(rb_iseq_t *iseq, int first_line)
return 1;
}
-#define PTR2NUM(x) (rb_int2inum((intptr_t)(void *)(x)))
-
static VALUE
-decl_branch_base(rb_iseq_t *iseq, VALUE key, const rb_code_location_t *loc, const char *type)
+setup_branch(const rb_code_location_t *loc, const char *type, VALUE structure, VALUE key)
{
const int first_lineno = loc->beg_pos.lineno, first_column = loc->beg_pos.column;
const int last_lineno = loc->end_pos.lineno, last_column = loc->end_pos.column;
+ VALUE branch = rb_ary_hidden_new(6);
- if (!branch_coverage_valid_p(iseq, first_lineno)) return Qundef;
+ rb_hash_aset(structure, key, branch);
+ rb_ary_push(branch, ID2SYM(rb_intern(type)));
+ rb_ary_push(branch, INT2FIX(first_lineno));
+ rb_ary_push(branch, INT2FIX(first_column));
+ rb_ary_push(branch, INT2FIX(last_lineno));
+ rb_ary_push(branch, INT2FIX(last_column));
+ return branch;
+}
+
+static VALUE
+decl_branch_base(rb_iseq_t *iseq, VALUE key, const rb_code_location_t *loc, const char *type)
+{
+ if (!branch_coverage_valid_p(iseq, loc->beg_pos.lineno)) return Qundef;
/*
* if !structure[node]
@@ -632,13 +644,7 @@ decl_branch_base(rb_iseq_t *iseq, VALUE key, const rb_code_location_t *loc, cons
VALUE branches;
if (NIL_P(branch_base)) {
- branch_base = rb_ary_hidden_new(6);
- rb_hash_aset(structure, key, branch_base);
- rb_ary_push(branch_base, ID2SYM(rb_intern(type)));
- rb_ary_push(branch_base, INT2FIX(first_lineno));
- rb_ary_push(branch_base, INT2FIX(first_column));
- rb_ary_push(branch_base, INT2FIX(last_lineno));
- rb_ary_push(branch_base, INT2FIX(last_column));
+ branch_base = setup_branch(loc, type, structure, key);
branches = rb_hash_new();
rb_obj_hide(branches);
rb_ary_push(branch_base, branches);
@@ -662,10 +668,7 @@ generate_dummy_line_node(int lineno, int node_id)
static void
add_trace_branch_coverage(rb_iseq_t *iseq, LINK_ANCHOR *const seq, const rb_code_location_t *loc, int node_id, int branch_id, const char *type, VALUE branches)
{
- const int first_lineno = loc->beg_pos.lineno, first_column = loc->beg_pos.column;
- const int last_lineno = loc->end_pos.lineno, last_column = loc->end_pos.column;
-
- if (!branch_coverage_valid_p(iseq, first_lineno)) return;
+ if (!branch_coverage_valid_p(iseq, loc->beg_pos.lineno)) return;
/*
* if !branches[branch_id]
@@ -680,13 +683,7 @@ add_trace_branch_coverage(rb_iseq_t *iseq, LINK_ANCHOR *const seq, const rb_code
long counter_idx;
if (NIL_P(branch)) {
- branch = rb_ary_hidden_new(6);
- rb_hash_aset(branches, key, branch);
- rb_ary_push(branch, ID2SYM(rb_intern(type)));
- rb_ary_push(branch, INT2FIX(first_lineno));
- rb_ary_push(branch, INT2FIX(first_column));
- rb_ary_push(branch, INT2FIX(last_lineno));
- rb_ary_push(branch, INT2FIX(last_column));
+ branch = setup_branch(loc, type, branches, key);
VALUE counters = RARRAY_AREF(ISEQ_BRANCH_COVERAGE(iseq), 1);
counter_idx = RARRAY_LEN(counters);
rb_ary_push(branch, LONG2FIX(counter_idx));
@@ -697,7 +694,7 @@ add_trace_branch_coverage(rb_iseq_t *iseq, LINK_ANCHOR *const seq, const rb_code
}
ADD_TRACE_WITH_DATA(seq, RUBY_EVENT_COVERAGE_BRANCH, counter_idx);
- ADD_SYNTHETIC_INSN(seq, last_lineno, node_id, nop);
+ ADD_SYNTHETIC_INSN(seq, loc->end_pos.lineno, node_id, nop);
}
#define ISEQ_LAST_LINE(iseq) (ISEQ_COMPILE_DATA(iseq)->last_line)
@@ -839,9 +836,9 @@ get_string_value(const NODE *node)
{
switch (nd_type(node)) {
case NODE_STR:
- return rb_node_str_string_val(node);
+ return RB_OBJ_SET_SHAREABLE(rb_node_str_string_val(node));
case NODE_FILE:
- return rb_node_file_path_val(node);
+ return RB_OBJ_SET_SHAREABLE(rb_node_file_path_val(node));
default:
rb_bug("unexpected node: %s", ruby_node_name(nd_type(node)));
}
@@ -861,6 +858,8 @@ rb_iseq_compile_callback(rb_iseq_t *iseq, const struct rb_iseq_new_with_callback
return iseq_setup(iseq, ret);
}
+static bool drop_unreachable_return(LINK_ANCHOR *ret);
+
VALUE
rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node)
{
@@ -869,13 +868,14 @@ rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node)
if (node == 0) {
NO_CHECK(COMPILE(ret, "nil", node));
- iseq_set_local_table(iseq, 0);
+ iseq_set_local_table(iseq, 0, 0);
}
/* assume node is T_NODE */
else if (nd_type_p(node, NODE_SCOPE)) {
/* iseq type of top, method, class, block */
- iseq_set_local_table(iseq, RNODE_SCOPE(node)->nd_tbl);
+ iseq_set_local_table(iseq, RNODE_SCOPE(node)->nd_tbl, (NODE *)RNODE_SCOPE(node)->nd_args);
iseq_set_arguments(iseq, ret, (NODE *)RNODE_SCOPE(node)->nd_args);
+ iseq_set_parameters_lvar_state(iseq);
switch (ISEQ_BODY(iseq)->type) {
case ISEQ_TYPE_BLOCK:
@@ -960,7 +960,7 @@ rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node)
ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0);
ADD_INSN1(ret, &dummy_line_node, throw, INT2FIX(0) /* continue throw */ );
}
- else {
+ else if (!drop_unreachable_return(ret)) {
ADD_SYNTHETIC_INSN(ret, ISEQ_COMPILE_DATA(iseq)->last_line, -1, leave);
}
@@ -1290,10 +1290,15 @@ static void
APPEND_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR *const anc1, LINK_ANCHOR *const anc2)
{
if (anc2->anchor.next) {
+ /* LINK_ANCHOR must not loop */
+ RUBY_ASSERT(anc2->last != &anc2->anchor);
anc1->last->next = anc2->anchor.next;
anc2->anchor.next->prev = anc1->last;
anc1->last = anc2->last;
}
+ else {
+ RUBY_ASSERT(anc2->last == &anc2->anchor);
+ }
verify_list("append", anc1);
}
#if CPDEBUG < 0
@@ -1353,6 +1358,7 @@ new_label_body(rb_iseq_t *iseq, long line)
labelobj->set = 0;
labelobj->rescued = LABEL_RESCUE_NONE;
labelobj->unremovable = 0;
+ labelobj->position = -1;
return labelobj;
}
@@ -1369,7 +1375,7 @@ new_adjust_body(rb_iseq_t *iseq, LABEL *label, int line)
}
static void
-iseq_insn_each_markable_object(INSN *insn, void (*func)(VALUE, VALUE), VALUE data)
+iseq_insn_each_markable_object(INSN *insn, void (*func)(VALUE *, VALUE), VALUE data)
{
const char *types = insn_op_types(insn->insn_id);
for (int j = 0; types[j]; j++) {
@@ -1380,7 +1386,7 @@ iseq_insn_each_markable_object(INSN *insn, void (*func)(VALUE, VALUE), VALUE dat
case TS_VALUE:
case TS_IC: // constant path array
case TS_CALLDATA: // ci is stored.
- func(OPERAND_AT(insn, j), data);
+ func(&OPERAND_AT(insn, j), data);
break;
default:
break;
@@ -1389,9 +1395,12 @@ iseq_insn_each_markable_object(INSN *insn, void (*func)(VALUE, VALUE), VALUE dat
}
static void
-iseq_insn_each_object_write_barrier(VALUE obj, VALUE iseq)
+iseq_insn_each_object_write_barrier(VALUE * obj, VALUE iseq)
{
- RB_OBJ_WRITTEN(iseq, Qundef, obj);
+ RB_OBJ_WRITTEN(iseq, Qundef, *obj);
+ RUBY_ASSERT(SPECIAL_CONST_P(*obj) ||
+ RBASIC_CLASS(*obj) == 0 || // hidden
+ RB_OBJ_SHAREABLE_P(*obj));
}
static INSN *
@@ -1434,21 +1443,45 @@ new_insn_body(rb_iseq_t *iseq, int line_no, int node_id, enum ruby_vminsn_type i
return new_insn_core(iseq, line_no, node_id, insn_id, argc, operands);
}
+static INSN *
+insn_replace_with_operands(rb_iseq_t *iseq, INSN *iobj, enum ruby_vminsn_type insn_id, int argc, ...)
+{
+ VALUE *operands = 0;
+ va_list argv;
+ if (argc > 0) {
+ int i;
+ va_start(argv, argc);
+ operands = compile_data_alloc2(iseq, sizeof(VALUE), argc);
+ for (i = 0; i < argc; i++) {
+ VALUE v = va_arg(argv, VALUE);
+ operands[i] = v;
+ }
+ va_end(argv);
+ }
+
+ iobj->insn_id = insn_id;
+ iobj->operand_size = argc;
+ iobj->operands = operands;
+ iseq_insn_each_markable_object(iobj, iseq_insn_each_object_write_barrier, (VALUE)iseq);
+
+ return iobj;
+}
+
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)
{
VM_ASSERT(argc >= 0);
- if (!(flag & (VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_BLOCKARG | VM_CALL_KW_SPLAT)) &&
- kw_arg == NULL && !has_blockiseq) {
- flag |= VM_CALL_ARGS_SIMPLE;
- }
-
if (kw_arg) {
flag |= VM_CALL_KWARG;
argc += kw_arg->keyword_len;
}
+ if (!(flag & (VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_BLOCKARG | VM_CALL_KWARG | VM_CALL_KW_SPLAT | VM_CALL_FORWARDING))
+ && !has_blockiseq) {
+ flag |= VM_CALL_ARGS_SIMPLE;
+ }
+
ISEQ_BODY(iseq)->ci_size++;
const struct rb_callinfo *ci = vm_ci_new(mid, flag, argc, kw_arg);
RB_OBJ_WRITTEN(iseq, Qundef, ci);
@@ -1465,7 +1498,16 @@ new_insn_send(rb_iseq_t *iseq, int line_no, int node_id, ID id, VALUE argc, cons
if (blockiseq) {
RB_OBJ_WRITTEN(iseq, Qundef, blockiseq);
}
- INSN *insn = new_insn_core(iseq, line_no, node_id, BIN(send), 2, operands);
+
+ INSN *insn;
+
+ if (vm_ci_flag((struct rb_callinfo *)ci) & VM_CALL_FORWARDING) {
+ insn = new_insn_core(iseq, line_no, node_id, BIN(sendforward), 2, operands);
+ }
+ else {
+ insn = new_insn_core(iseq, line_no, node_id, BIN(send), 2, operands);
+ }
+
RB_OBJ_WRITTEN(iseq, Qundef, ci);
RB_GC_GUARD(ci);
return insn;
@@ -1676,6 +1718,7 @@ iseq_set_exception_local_table(rb_iseq_t *iseq)
{
ISEQ_BODY(iseq)->local_table_size = numberof(rb_iseq_shared_exc_local_tbl);
ISEQ_BODY(iseq)->local_table = rb_iseq_shared_exc_local_tbl;
+ ISEQ_BODY(iseq)->lvar_states = NULL; // $! is read-only, so don't need lvar_states
return COMPILE_OK;
}
@@ -1823,6 +1866,46 @@ iseq_lvar_id(const rb_iseq_t *iseq, int idx, int level)
}
static void
+update_lvar_state(const rb_iseq_t *iseq, int level, int idx)
+{
+ for (int i=0; i<level; i++) {
+ iseq = ISEQ_BODY(iseq)->parent_iseq;
+ }
+
+ enum lvar_state *states = ISEQ_BODY(iseq)->lvar_states;
+ int table_idx = ISEQ_BODY(iseq)->local_table_size - idx;
+ switch (states[table_idx]) {
+ case lvar_uninitialized:
+ states[table_idx] = lvar_initialized;
+ break;
+ case lvar_initialized:
+ states[table_idx] = lvar_reassigned;
+ break;
+ case lvar_reassigned:
+ /* nothing */
+ break;
+ default:
+ rb_bug("unreachable");
+ }
+}
+
+static int
+iseq_set_parameters_lvar_state(const rb_iseq_t *iseq)
+{
+ for (unsigned int i=0; i<ISEQ_BODY(iseq)->param.size; i++) {
+ ISEQ_BODY(iseq)->lvar_states[i] = lvar_initialized;
+ }
+
+ int lead_num = ISEQ_BODY(iseq)->param.lead_num;
+ int opt_num = ISEQ_BODY(iseq)->param.opt_num;
+ for (int i=0; i<opt_num; i++) {
+ ISEQ_BODY(iseq)->lvar_states[lead_num + i] = lvar_uninitialized;
+ }
+
+ return COMPILE_OK;
+}
+
+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)) {
@@ -1843,6 +1926,7 @@ iseq_add_setlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, const NODE *const lin
else {
ADD_INSN2(seq, line_node, setlocal, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level));
}
+ update_lvar_state(iseq, level, idx);
if (level > 0) access_outer_variables(iseq, level, iseq_lvar_id(iseq, idx, level), Qtrue);
}
@@ -1965,7 +2049,7 @@ iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs,
keyword->num = kw;
if (RNODE_DVAR(args->kw_rest_arg)->nd_vid != 0) {
- ID kw_id = iseq->body->local_table[arg_size];
+ ID kw_id = ISEQ_BODY(iseq)->local_table[arg_size];
keyword->rest_start = arg_size++;
body->param.flags.has_kwrest = TRUE;
@@ -1974,16 +2058,14 @@ iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs,
keyword->required_num = rkw;
keyword->table = &body->local_table[keyword->bits_start - keyword->num];
- {
+ if (RARRAY_LEN(default_values)) {
VALUE *dvs = ALLOC_N(VALUE, RARRAY_LEN(default_values));
for (i = 0; i < RARRAY_LEN(default_values); i++) {
VALUE dv = RARRAY_AREF(default_values, i);
if (dv == complex_mark) dv = Qundef;
- if (!SPECIAL_CONST_P(dv)) {
- RB_OBJ_WRITTEN(iseq, Qundef, dv);
- }
- dvs[i] = dv;
+ if (!SPECIAL_CONST_P(dv)) rb_ractor_make_shareable(dv);
+ RB_OBJ_WRITE(iseq, &dvs[i], dv);
}
keyword->default_values = dvs;
@@ -2000,9 +2082,9 @@ iseq_set_use_block(rb_iseq_t *iseq)
rb_vm_t *vm = GET_VM();
- if (!vm->unused_block_warning_strict) {
+ if (!rb_warning_category_enabled_p(RB_WARN_CATEGORY_STRICT_UNUSED_BLOCK)) {
st_data_t key = (st_data_t)rb_intern_str(body->location.label); // String -> ID
- st_insert(vm->unused_block_warning_table, key, 1);
+ set_insert(vm->unused_block_warning_table, key);
}
}
}
@@ -2022,7 +2104,6 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const NODE *cons
EXPECT_NODE("iseq_set_arguments", node_args, NODE_ARGS, COMPILE_NG);
- body->param.flags.ruby2_keywords = args->ruby2_keywords;
body->param.lead_num = arg_size = (int)args->pre_args_num;
if (body->param.lead_num > 0) body->param.flags.has_lead = TRUE;
debugs(" - argc: %d\n", body->param.lead_num);
@@ -2034,6 +2115,13 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const NODE *cons
}
block_id = args->block_arg;
+ bool optimized_forward = (args->forwarding && args->pre_args_num == 0 && !args->opt_args);
+
+ if (optimized_forward) {
+ rest_id = 0;
+ block_id = 0;
+ }
+
if (args->opt_args) {
const rb_node_opt_arg_t *node = args->opt_args;
LABEL *label;
@@ -2090,8 +2178,8 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const NODE *cons
if (args->kw_args) {
arg_size = iseq_set_arguments_keywords(iseq, optargs, args, arg_size);
}
- else if (args->kw_rest_arg) {
- ID kw_id = iseq->body->local_table[arg_size];
+ else if (args->kw_rest_arg && !optimized_forward) {
+ ID kw_id = ISEQ_BODY(iseq)->local_table[arg_size];
struct rb_iseq_param_keyword *keyword = ZALLOC_N(struct rb_iseq_param_keyword, 1);
keyword->rest_start = arg_size++;
body->param.keyword = keyword;
@@ -2111,6 +2199,13 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const NODE *cons
iseq_set_use_block(iseq);
}
+ // Only optimize specifically methods like this: `foo(...)`
+ if (optimized_forward) {
+ body->param.flags.use_block = 1;
+ body->param.flags.forwardable = TRUE;
+ arg_size = 1;
+ }
+
iseq_calc_param_size(iseq);
body->param.size = arg_size;
@@ -2140,14 +2235,36 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const NODE *cons
}
static int
-iseq_set_local_table(rb_iseq_t *iseq, const rb_ast_id_table_t *tbl)
+iseq_set_local_table(rb_iseq_t *iseq, const rb_ast_id_table_t *tbl, const NODE *const node_args)
{
unsigned int size = tbl ? tbl->size : 0;
+ unsigned int offset = 0;
+
+ if (node_args) {
+ struct rb_args_info *args = &RNODE_ARGS(node_args)->nd_ainfo;
+
+ // If we have a function that only has `...` as the parameter,
+ // then its local table should only be `...`
+ // FIXME: I think this should be fixed in the AST rather than special case here.
+ if (args->forwarding && args->pre_args_num == 0 && !args->opt_args) {
+ CHECK(size >= 3);
+ size -= 3;
+ offset += 3;
+ }
+ }
if (size > 0) {
- ID *ids = (ID *)ALLOC_N(ID, size);
- MEMCPY(ids, tbl->ids, ID, size);
+ ID *ids = ALLOC_N(ID, size);
+ MEMCPY(ids, tbl->ids + offset, ID, size);
ISEQ_BODY(iseq)->local_table = ids;
+
+ enum lvar_state *states = ALLOC_N(enum lvar_state, size);
+ // fprintf(stderr, "iseq:%p states:%p size:%d\n", iseq, states, (int)size);
+ for (unsigned int i=0; i<size; i++) {
+ states[i] = lvar_uninitialized;
+ // fprintf(stderr, "id:%s\n", rb_id2name(ISEQ_BODY(iseq)->local_table[i]));
+ }
+ ISEQ_BODY(iseq)->lvar_states = states;
}
ISEQ_BODY(iseq)->local_table_size = size;
@@ -2430,6 +2547,7 @@ add_adjust_info(struct iseq_insn_info_entry *insns_info, unsigned int *positions
int insns_info_index, int code_index, const ADJUST *adjust)
{
insns_info[insns_info_index].line_no = adjust->line_no;
+ insns_info[insns_info_index].node_id = -1;
insns_info[insns_info_index].events = 0;
positions[insns_info_index] = code_index;
return TRUE;
@@ -2441,7 +2559,7 @@ array_to_idlist(VALUE arr)
RUBY_ASSERT(RB_TYPE_P(arr, T_ARRAY));
long size = RARRAY_LEN(arr);
ID *ids = (ID *)ALLOC_N(ID, size + 1);
- for (int i = 0; i < size; i++) {
+ for (long i = 0; i < size; i++) {
VALUE sym = RARRAY_AREF(arr, i);
ids[i] = SYM2ID(sym);
}
@@ -2556,7 +2674,13 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
else {
body->is_entries = NULL;
}
- body->call_data = ZALLOC_N(struct rb_call_data, body->ci_size);
+
+ if (body->ci_size) {
+ body->call_data = ZALLOC_N(struct rb_call_data, body->ci_size);
+ }
+ else {
+ body->call_data = NULL;
+ }
ISEQ_COMPILE_DATA(iseq)->ci_index = 0;
// Calculate the bitmask buffer size.
@@ -2567,16 +2691,21 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
iseq_bits_t * mark_offset_bits;
int code_size = code_index;
- iseq_bits_t tmp[1] = {0};
bool needs_bitmap = false;
if (ISEQ_MBITS_BUFLEN(code_index) == 1) {
- mark_offset_bits = tmp;
+ mark_offset_bits = &ISEQ_COMPILE_DATA(iseq)->mark_bits.single;
+ ISEQ_COMPILE_DATA(iseq)->is_single_mark_bit = true;
}
else {
mark_offset_bits = ZALLOC_N(iseq_bits_t, ISEQ_MBITS_BUFLEN(code_index));
+ ISEQ_COMPILE_DATA(iseq)->mark_bits.list = mark_offset_bits;
+ ISEQ_COMPILE_DATA(iseq)->is_single_mark_bit = false;
}
+ ISEQ_COMPILE_DATA(iseq)->iseq_encoded = (void *)generated_iseq;
+ ISEQ_COMPILE_DATA(iseq)->iseq_size = code_index;
+
list = FIRST_ELEMENT(anchor);
insns_info_index = code_index = sp = 0;
@@ -2621,6 +2750,7 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
rb_hash_rehash(map);
freeze_hide_obj(map);
+ rb_ractor_make_shareable(map);
generated_iseq[code_index + 1 + j] = map;
ISEQ_MBITS_SET(mark_offset_bits, code_index + 1 + j);
RB_OBJ_WRITTEN(iseq, Qundef, map);
@@ -2787,15 +2917,16 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
body->iseq_size = code_index;
body->stack_max = stack_max;
- if (ISEQ_MBITS_BUFLEN(body->iseq_size) == 1) {
- body->mark_bits.single = mark_offset_bits[0];
+ if (ISEQ_COMPILE_DATA(iseq)->is_single_mark_bit) {
+ body->mark_bits.single = ISEQ_COMPILE_DATA(iseq)->mark_bits.single;
}
else {
if (needs_bitmap) {
body->mark_bits.list = mark_offset_bits;
}
else {
- body->mark_bits.list = 0;
+ body->mark_bits.list = NULL;
+ ISEQ_COMPILE_DATA(iseq)->mark_bits.list = NULL;
ruby_xfree(mark_offset_bits);
}
}
@@ -2844,11 +2975,16 @@ iseq_set_exception_table(rb_iseq_t *iseq)
table->size = tlen;
for (i = 0; i < table->size; i++) {
+ int pos;
ptr = RARRAY_CONST_PTR(tptr[i]);
entry = UNALIGNED_MEMBER_PTR(table, entries[i]);
entry->type = (enum rb_catch_type)(ptr[0] & 0xffff);
- entry->start = label_get_position((LABEL *)(ptr[1] & ~1));
- entry->end = label_get_position((LABEL *)(ptr[2] & ~1));
+ pos = label_get_position((LABEL *)(ptr[1] & ~1));
+ RUBY_ASSERT(pos >= 0);
+ entry->start = (unsigned int)pos;
+ pos = label_get_position((LABEL *)(ptr[2] & ~1));
+ RUBY_ASSERT(pos >= 0);
+ entry->end = (unsigned int)pos;
entry->iseq = (rb_iseq_t *)ptr[3];
RB_OBJ_WRITTEN(iseq, Qundef, entry->iseq);
@@ -2972,16 +3108,18 @@ unref_destination(INSN *iobj, int pos)
if (!lobj->refcnt) ELEM_REMOVE(&lobj->link);
}
-static void
+static bool
replace_destination(INSN *dobj, INSN *nobj)
{
VALUE n = OPERAND_AT(nobj, 0);
LABEL *dl = (LABEL *)OPERAND_AT(dobj, 0);
LABEL *nl = (LABEL *)n;
+ if (dl == nl) return false;
--dl->refcnt;
++nl->refcnt;
OPERAND_AT(dobj, 0) = n;
if (!dl->refcnt) ELEM_REMOVE(&dl->link);
+ return true;
}
static LABEL*
@@ -3014,7 +3152,6 @@ remove_unreachable_chunk(rb_iseq_t *iseq, LINK_ELEMENT *i)
break;
}
else if ((lab = find_destination((INSN *)i)) != 0) {
- if (lab->unremovable) break;
unref_counts[lab->label_no]++;
}
}
@@ -3031,8 +3168,7 @@ remove_unreachable_chunk(rb_iseq_t *iseq, LINK_ELEMENT *i)
/* do nothing */
}
else if (IS_ADJUST(i)) {
- LABEL *dest = ((ADJUST *)i)->label;
- if (dest && dest->unremovable) return 0;
+ return 0;
}
end = i;
} while ((i = i->next) != 0);
@@ -3089,6 +3225,25 @@ is_frozen_putstring(INSN *insn, VALUE *op)
}
static int
+insn_has_label_before(LINK_ELEMENT *elem)
+{
+ LINK_ELEMENT *prev = elem->prev;
+ while (prev) {
+ if (prev->type == ISEQ_ELEMENT_LABEL) {
+ LABEL *label = (LABEL *)prev;
+ if (label->refcnt > 0) {
+ return 1;
+ }
+ }
+ else if (prev->type == ISEQ_ELEMENT_INSN) {
+ break;
+ }
+ prev = prev->prev;
+ }
+ return 0;
+}
+
+static int
optimize_checktype(rb_iseq_t *iseq, INSN *iobj)
{
/*
@@ -3197,33 +3352,7 @@ ci_argc_set(const rb_iseq_t *iseq, const struct rb_callinfo *ci, int argc)
return nci;
}
-static bool
-optimize_args_splat_no_copy(rb_iseq_t *iseq, INSN *insn, LINK_ELEMENT *niobj,
- unsigned int set_flags, unsigned int unset_flags, unsigned int remove_flags)
-{
- LINK_ELEMENT *iobj = (LINK_ELEMENT *)insn;
- if ((set_flags & VM_CALL_ARGS_BLOCKARG) && (set_flags & VM_CALL_KW_SPLAT) &&
- IS_NEXT_INSN_ID(niobj, splatkw)) {
- niobj = niobj->next;
- }
- if (!IS_NEXT_INSN_ID(niobj, send) && !IS_NEXT_INSN_ID(niobj, invokesuper)) {
- return false;
- }
- niobj = niobj->next;
-
- const struct rb_callinfo *ci = (const struct rb_callinfo *)OPERAND_AT(niobj, 0);
- unsigned int flags = vm_ci_flag(ci);
- if ((flags & set_flags) == set_flags && !(flags & unset_flags)) {
- RUBY_ASSERT(flags & VM_CALL_ARGS_SPLAT_MUT);
- OPERAND_AT(iobj, 0) = Qfalse;
- const struct rb_callinfo *nci = vm_ci_new(vm_ci_mid(ci),
- flags & ~(VM_CALL_ARGS_SPLAT_MUT|remove_flags), vm_ci_argc(ci), vm_ci_kwarg(ci));
- RB_OBJ_WRITTEN(iseq, ci, nci);
- OPERAND_AT(niobj, 0) = (VALUE)nci;
- return true;
- }
- return false;
-}
+#define vm_ci_simple(ci) (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE)
static int
iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcallopt)
@@ -3263,9 +3392,10 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
* => in this case, first jump instruction should jump to
* LABEL2 directly
*/
- replace_destination(iobj, diobj);
- remove_unreachable_chunk(iseq, iobj->link.next);
- goto again;
+ if (replace_destination(iobj, diobj)) {
+ remove_unreachable_chunk(iseq, iobj->link.next);
+ goto again;
+ }
}
else if (IS_INSN_ID(diobj, leave)) {
/*
@@ -3310,8 +3440,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
*/
piobj->insn_id = (IS_INSN_ID(piobj, branchif))
? BIN(branchunless) : BIN(branchif);
- replace_destination(piobj, iobj);
- if (refcnt <= 1) {
+ if (replace_destination(piobj, iobj) && refcnt <= 1) {
ELEM_REMOVE(&iobj->link);
}
else {
@@ -3359,9 +3488,10 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
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)) {
+ is_frozen_putstring(beg, &str_beg) &&
+ !(insn_has_label_before(&beg->link) || insn_has_label_before(&end->link))) {
int excl = FIX2INT(OPERAND_AT(range, 0));
- VALUE lit_range = rb_range_new(str_beg, str_end, excl);
+ VALUE lit_range = RB_OBJ_SET_SHAREABLE(rb_range_new(str_beg, str_end, excl));
ELEM_REMOVE(&beg->link);
ELEM_REMOVE(&end->link);
@@ -3391,6 +3521,89 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
}
}
+ /*
+ * duparray [...]
+ * send <calldata!mid:freeze, argc:0, ARGS_SIMPLE>, nil
+ * =>
+ * opt_ary_freeze [...], <calldata!mid:freeze, argc:0, ARGS_SIMPLE>
+ */
+ if (IS_INSN_ID(iobj, duparray)) {
+ LINK_ELEMENT *next = iobj->link.next;
+ if (IS_INSN(next) && (IS_INSN_ID(next, send))) {
+ const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(next, 0);
+ const rb_iseq_t *blockiseq = (rb_iseq_t *)OPERAND_AT(next, 1);
+
+ if (vm_ci_simple(ci) && vm_ci_argc(ci) == 0 && blockiseq == NULL && vm_ci_mid(ci) == idFreeze) {
+ VALUE ary = iobj->operands[0];
+ rb_obj_reveal(ary, rb_cArray);
+
+ insn_replace_with_operands(iseq, iobj, BIN(opt_ary_freeze), 2, ary, (VALUE)ci);
+ ELEM_REMOVE(next);
+ }
+ }
+ }
+
+ /*
+ * duphash {...}
+ * send <calldata!mid:freeze, argc:0, ARGS_SIMPLE>, nil
+ * =>
+ * opt_hash_freeze {...}, <calldata!mid:freeze, argc:0, ARGS_SIMPLE>
+ */
+ if (IS_INSN_ID(iobj, duphash)) {
+ LINK_ELEMENT *next = iobj->link.next;
+ if (IS_INSN(next) && (IS_INSN_ID(next, send))) {
+ const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(next, 0);
+ const rb_iseq_t *blockiseq = (rb_iseq_t *)OPERAND_AT(next, 1);
+
+ if (vm_ci_simple(ci) && vm_ci_argc(ci) == 0 && blockiseq == NULL && vm_ci_mid(ci) == idFreeze) {
+ VALUE hash = iobj->operands[0];
+ rb_obj_reveal(hash, rb_cHash);
+ RB_OBJ_SET_SHAREABLE(hash);
+
+ insn_replace_with_operands(iseq, iobj, BIN(opt_hash_freeze), 2, hash, (VALUE)ci);
+ ELEM_REMOVE(next);
+ }
+ }
+ }
+
+ /*
+ * newarray 0
+ * send <calldata!mid:freeze, argc:0, ARGS_SIMPLE>, nil
+ * =>
+ * opt_ary_freeze [], <calldata!mid:freeze, argc:0, ARGS_SIMPLE>
+ */
+ if (IS_INSN_ID(iobj, newarray) && iobj->operands[0] == INT2FIX(0)) {
+ LINK_ELEMENT *next = iobj->link.next;
+ if (IS_INSN(next) && (IS_INSN_ID(next, send))) {
+ const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(next, 0);
+ const rb_iseq_t *blockiseq = (rb_iseq_t *)OPERAND_AT(next, 1);
+
+ if (vm_ci_simple(ci) && vm_ci_argc(ci) == 0 && blockiseq == NULL && vm_ci_mid(ci) == idFreeze) {
+ insn_replace_with_operands(iseq, iobj, BIN(opt_ary_freeze), 2, rb_cArray_empty_frozen, (VALUE)ci);
+ ELEM_REMOVE(next);
+ }
+ }
+ }
+
+ /*
+ * newhash 0
+ * send <calldata!mid:freeze, argc:0, ARGS_SIMPLE>, nil
+ * =>
+ * opt_hash_freeze {}, <calldata!mid:freeze, argc:0, ARGS_SIMPLE>
+ */
+ if (IS_INSN_ID(iobj, newhash) && iobj->operands[0] == INT2FIX(0)) {
+ LINK_ELEMENT *next = iobj->link.next;
+ if (IS_INSN(next) && (IS_INSN_ID(next, send))) {
+ const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(next, 0);
+ const rb_iseq_t *blockiseq = (rb_iseq_t *)OPERAND_AT(next, 1);
+
+ if (vm_ci_simple(ci) && vm_ci_argc(ci) == 0 && blockiseq == NULL && vm_ci_mid(ci) == idFreeze) {
+ insn_replace_with_operands(iseq, iobj, BIN(opt_hash_freeze), 2, rb_cHash_empty_frozen, (VALUE)ci);
+ ELEM_REMOVE(next);
+ }
+ }
+ }
+
if (IS_INSN_ID(iobj, branchif) ||
IS_INSN_ID(iobj, branchnil) ||
IS_INSN_ID(iobj, branchunless)) {
@@ -3440,7 +3653,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
for (;;) {
if (IS_INSN(&nobj->link) && IS_INSN_ID(nobj, jump)) {
- replace_destination(iobj, nobj);
+ if (!replace_destination(iobj, nobj)) break;
}
else if (prev_dup && IS_INSN_ID(nobj, dup) &&
!!(nobj = (INSN *)nobj->link.next) &&
@@ -3461,7 +3674,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
* dup
* if L2
*/
- replace_destination(iobj, nobj);
+ if (!replace_destination(iobj, nobj)) break;
}
else if (pobj) {
/*
@@ -3705,6 +3918,27 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
}
ELEM_REMOVE(&iobj->link);
}
+ if (IS_NEXT_INSN_ID(&iobj->link, toregexp)) {
+ INSN *next = (INSN *)iobj->link.next;
+ if (OPERAND_AT(next, 1) == INT2FIX(1)) {
+ VALUE src = OPERAND_AT(iobj, 0);
+ int opt = (int)FIX2LONG(OPERAND_AT(next, 0));
+ VALUE path = rb_iseq_path(iseq);
+ int line = iobj->insn_info.line_no;
+ VALUE errinfo = rb_errinfo();
+ VALUE re = rb_reg_compile(src, opt, RSTRING_PTR(path), line);
+ if (NIL_P(re)) {
+ VALUE message = rb_attr_get(rb_errinfo(), idMesg);
+ rb_set_errinfo(errinfo);
+ COMPILE_ERROR(iseq, line, "%" PRIsVALUE, message);
+ }
+ else {
+ RB_OBJ_SET_SHAREABLE(re);
+ }
+ RB_OBJ_WRITE(iseq, &OPERAND_AT(iobj, 0), re);
+ ELEM_REMOVE(iobj->link.next);
+ }
+ }
}
if (IS_INSN_ID(iobj, concatstrings)) {
@@ -3742,8 +3976,6 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
if (do_tailcallopt &&
(IS_INSN_ID(iobj, send) ||
- IS_INSN_ID(iobj, opt_aref_with) ||
- IS_INSN_ID(iobj, opt_aset_with) ||
IS_INSN_ID(iobj, invokesuper))) {
/*
* send ...
@@ -3877,8 +4109,8 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
if (IS_NEXT_INSN_ID(iobj->link.next, leave)) {
iobj->insn_id = BIN(opt_invokebuiltin_delegate_leave);
const struct rb_builtin_function *bf = (const struct rb_builtin_function *)iobj->operands[0];
- if (iobj == (INSN *)list && bf->argc == 0 && (iseq->body->builtin_attrs & BUILTIN_ATTR_LEAF)) {
- iseq->body->builtin_attrs |= BUILTIN_ATTR_SINGLE_NOARG_LEAF;
+ if (iobj == (INSN *)list && bf->argc == 0 && (ISEQ_BODY(iseq)->builtin_attrs & BUILTIN_ATTR_LEAF)) {
+ ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_SINGLE_NOARG_LEAF;
}
}
}
@@ -3897,134 +4129,63 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
}
}
- if (IS_INSN_ID(iobj, splatarray) && OPERAND_AT(iobj, 0) == Qtrue) {
+ if (IS_INSN_ID(iobj, splatarray) && OPERAND_AT(iobj, 0) == false) {
LINK_ELEMENT *niobj = &iobj->link;
-
- /*
- * Eliminate array allocation for f(1, *a)
- *
- * splatarray true
- * send ARGS_SPLAT and not KW_SPLAT|ARGS_BLOCKARG
- * =>
- * splatarray false
- * send
- */
- if (optimize_args_splat_no_copy(iseq, iobj, niobj,
- VM_CALL_ARGS_SPLAT, VM_CALL_KW_SPLAT|VM_CALL_ARGS_BLOCKARG, 0)) goto optimized_splat;
-
- if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable)) {
+ if (IS_NEXT_INSN_ID(niobj, duphash)) {
niobj = niobj->next;
+ LINK_ELEMENT *siobj;
+ unsigned int set_flags = 0, unset_flags = 0;
/*
- * Eliminate array allocation for f(1, *a, &lvar) and f(1, *a, &@iv)
+ * Eliminate hash allocation for f(*a, kw: 1)
*
- * splatarray true
- * getlocal / getinstancevariable
- * send ARGS_SPLAT|ARGS_BLOCKARG and not KW_SPLAT
- * =>
* splatarray false
- * getlocal / getinstancevariable
- * send
- */
- if (optimize_args_splat_no_copy(iseq, iobj, niobj,
- VM_CALL_ARGS_SPLAT|VM_CALL_ARGS_BLOCKARG, VM_CALL_KW_SPLAT, 0)) goto optimized_splat;
-
- /*
- * Eliminate array allocation for f(*a, **lvar) and f(*a, **@iv)
- *
- * splatarray true
- * getlocal / getinstancevariable
- * send ARGS_SPLAT|KW_SPLAT and not ARGS_BLOCKARG
+ * duphash
+ * send ARGS_SPLAT|KW_SPLAT|KW_SPLAT_MUT and not ARGS_BLOCKARG
* =>
* splatarray false
- * getlocal / getinstancevariable
- * send
+ * putobject
+ * send ARGS_SPLAT|KW_SPLAT
*/
- if (optimize_args_splat_no_copy(iseq, iobj, niobj,
- VM_CALL_ARGS_SPLAT|VM_CALL_KW_SPLAT, VM_CALL_ARGS_BLOCKARG, 0)) goto optimized_splat;
-
- if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable) ||
- IS_NEXT_INSN_ID(niobj, getblockparamproxy)) {
- niobj = niobj->next;
-
- /*
- * Eliminate array allocation for f(*a, **lvar, &{arg,lvar,@iv})
- *
- * splatarray true
- * getlocal / getinstancevariable
- * getlocal / getinstancevariable / getblockparamproxy
- * send ARGS_SPLAT|KW_SPLAT|ARGS_BLOCKARG
- * =>
- * splatarray false
- * getlocal / getinstancevariable
- * getlocal / getinstancevariable / getblockparamproxy
- * send
- */
- optimize_args_splat_no_copy(iseq, iobj, niobj,
- VM_CALL_ARGS_SPLAT|VM_CALL_KW_SPLAT|VM_CALL_ARGS_BLOCKARG, 0, 0);
- }
- } else if (IS_NEXT_INSN_ID(niobj, getblockparamproxy)) {
+ if (IS_NEXT_INSN_ID(niobj, send)) {
+ siobj = niobj->next;
+ set_flags = VM_CALL_ARGS_SPLAT|VM_CALL_KW_SPLAT|VM_CALL_KW_SPLAT_MUT;
+ unset_flags = VM_CALL_ARGS_BLOCKARG;
+ }
/*
- * Eliminate array allocation for f(1, *a, &arg)
+ * Eliminate hash allocation for f(*a, kw: 1, &{arg,lvar,@iv})
*
- * splatarray true
- * getblockparamproxy
- * send ARGS_SPLAT|ARGS_BLOCKARG and not KW_SPLAT
- * =>
* splatarray false
- * getblockparamproxy
- * send
- */
- optimize_args_splat_no_copy(iseq, iobj, niobj,
- VM_CALL_ARGS_SPLAT|VM_CALL_ARGS_BLOCKARG, VM_CALL_KW_SPLAT, 0);
- } else if (IS_NEXT_INSN_ID(niobj, duphash)) {
- niobj = niobj->next;
-
- /*
- * Eliminate array and hash allocation for f(*a, kw: 1)
- *
- * splatarray true
* duphash
- * send ARGS_SPLAT|KW_SPLAT|KW_SPLAT_MUT and not ARGS_BLOCKARG
+ * getlocal / getinstancevariable / getblockparamproxy
+ * send ARGS_SPLAT|KW_SPLAT|KW_SPLAT_MUT|ARGS_BLOCKARG
* =>
* splatarray false
* putobject
- * send ARGS_SPLAT|KW_SPLAT
+ * getlocal / getinstancevariable / getblockparamproxy
+ * send ARGS_SPLAT|KW_SPLAT|ARGS_BLOCKARG
*/
- if (optimize_args_splat_no_copy(iseq, iobj, niobj,
- VM_CALL_ARGS_SPLAT|VM_CALL_KW_SPLAT|VM_CALL_KW_SPLAT_MUT, VM_CALL_ARGS_BLOCKARG, VM_CALL_KW_SPLAT_MUT)) {
-
- ((INSN*)niobj)->insn_id = BIN(putobject);
- OPERAND_AT(niobj, 0) = rb_hash_freeze(rb_hash_resurrect(OPERAND_AT(niobj, 0)));
-
- goto optimized_splat;
+ else if ((IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable) ||
+ IS_NEXT_INSN_ID(niobj, getblockparamproxy)) && (IS_NEXT_INSN_ID(niobj->next, send))) {
+ siobj = niobj->next->next;
+ set_flags = VM_CALL_ARGS_SPLAT|VM_CALL_KW_SPLAT|VM_CALL_KW_SPLAT_MUT|VM_CALL_ARGS_BLOCKARG;
}
- if (IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable) ||
- IS_NEXT_INSN_ID(niobj, getblockparamproxy)) {
- /*
- * Eliminate array and hash allocation for f(*a, kw: 1, &{arg,lvar,@iv})
- *
- * splatarray true
- * duphash
- * getlocal / getinstancevariable / getblockparamproxy
- * send ARGS_SPLAT|KW_SPLAT|KW_SPLAT_MUT|ARGS_BLOCKARG
- * =>
- * splatarray false
- * putobject
- * getlocal / getinstancevariable / getblockparamproxy
- * send ARGS_SPLAT|KW_SPLAT|ARGS_BLOCKARG
- */
- if (optimize_args_splat_no_copy(iseq, iobj, niobj->next,
- VM_CALL_ARGS_SPLAT|VM_CALL_KW_SPLAT|VM_CALL_KW_SPLAT_MUT|VM_CALL_ARGS_BLOCKARG, 0, VM_CALL_KW_SPLAT_MUT)) {
-
+ if (set_flags) {
+ const struct rb_callinfo *ci = (const struct rb_callinfo *)OPERAND_AT(siobj, 0);
+ unsigned int flags = vm_ci_flag(ci);
+ if ((flags & set_flags) == set_flags && !(flags & unset_flags)) {
((INSN*)niobj)->insn_id = BIN(putobject);
- OPERAND_AT(niobj, 0) = rb_hash_freeze(rb_hash_resurrect(OPERAND_AT(niobj, 0)));
+ RB_OBJ_WRITE(iseq, &OPERAND_AT(niobj, 0), RB_OBJ_SET_SHAREABLE(rb_hash_freeze(rb_hash_resurrect(OPERAND_AT(niobj, 0)))));
+
+ const struct rb_callinfo *nci = vm_ci_new(vm_ci_mid(ci),
+ flags & ~VM_CALL_KW_SPLAT_MUT, vm_ci_argc(ci), vm_ci_kwarg(ci));
+ RB_OBJ_WRITTEN(iseq, ci, nci);
+ OPERAND_AT(siobj, 0) = (VALUE)nci;
}
}
}
}
- optimized_splat:
return COMPILE_OK;
}
@@ -4032,50 +4193,50 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal
static int
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 original_ci = iobj->operands[0];
- iobj->operand_size = 2;
- 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] = original_ci;
+ VALUE new_ci = (VALUE)new_callinfo(iseq, idEq, 1, 0, NULL, FALSE);
+ insn_replace_with_operands(iseq, iobj, insn_id, 2, new_ci, original_ci);
+ }
+ else {
+ 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;
return COMPILE_OK;
}
-#define vm_ci_simple(ci) (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE)
-
static int
iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
{
if (IS_INSN_ID(iobj, newarray) && iobj->link.next &&
IS_INSN(iobj->link.next)) {
/*
- * [a, b, ...].max/min -> a, b, c, opt_newarray_max/min
+ * [a, b, ...].max/min -> a, b, c, opt_newarray_send max/min
*/
INSN *niobj = (INSN *)iobj->link.next;
if (IS_INSN_ID(niobj, send)) {
const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(niobj, 0);
if (vm_ci_simple(ci) && vm_ci_argc(ci) == 0) {
+ VALUE method = INT2FIX(0);
switch (vm_ci_mid(ci)) {
case idMax:
+ method = INT2FIX(VM_OPT_NEWARRAY_SEND_MAX);
+ break;
case idMin:
+ method = INT2FIX(VM_OPT_NEWARRAY_SEND_MIN);
+ break;
case idHash:
- {
- VALUE num = iobj->operands[0];
- int operand_len = insn_len(BIN(opt_newarray_send)) - 1;
- iobj->insn_id = BIN(opt_newarray_send);
- iobj->operands = compile_data_calloc2(iseq, operand_len, sizeof(VALUE));
- iobj->operands[0] = num;
- iobj->operands[1] = rb_id2sym(vm_ci_mid(ci));
- iobj->operand_size = operand_len;
- ELEM_REMOVE(&niobj->link);
- return COMPILE_OK;
- }
+ method = INT2FIX(VM_OPT_NEWARRAY_SEND_HASH);
+ break;
+ }
+
+ if (method != INT2FIX(0)) {
+ VALUE num = iobj->operands[0];
+ insn_replace_with_operands(iseq, iobj, BIN(opt_newarray_send), 2, num, method);
+ ELEM_REMOVE(&niobj->link);
+ return COMPILE_OK;
}
}
}
@@ -4085,20 +4246,106 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT((INSN *)niobj->link.next, 0);
if (vm_ci_simple(ci) && vm_ci_argc(ci) == 1 && vm_ci_mid(ci) == idPack) {
VALUE num = iobj->operands[0];
- int operand_len = insn_len(BIN(opt_newarray_send)) - 1;
- iobj->insn_id = BIN(opt_newarray_send);
- iobj->operands = compile_data_calloc2(iseq, operand_len, sizeof(VALUE));
- iobj->operands[0] = FIXNUM_INC(num, 1);
- iobj->operands[1] = rb_id2sym(vm_ci_mid(ci));
- iobj->operand_size = operand_len;
+ insn_replace_with_operands(iseq, iobj, BIN(opt_newarray_send), 2, FIXNUM_INC(num, 1), INT2FIX(VM_OPT_NEWARRAY_SEND_PACK));
ELEM_REMOVE(&iobj->link);
ELEM_REMOVE(niobj->link.next);
ELEM_INSERT_NEXT(&niobj->link, &iobj->link);
return COMPILE_OK;
}
}
+ // newarray n, putchilledstring "E", getlocal b, send :pack with {buffer: b}
+ // -> putchilledstring "E", getlocal b, opt_newarray_send n+2, :pack, :buffer
+ else if ((IS_INSN_ID(niobj, putstring) || IS_INSN_ID(niobj, putchilledstring) ||
+ (IS_INSN_ID(niobj, putobject) && RB_TYPE_P(OPERAND_AT(niobj, 0), T_STRING))) &&
+ IS_NEXT_INSN_ID(&niobj->link, getlocal) &&
+ (niobj->link.next && IS_NEXT_INSN_ID(niobj->link.next, send))) {
+ const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT((INSN *)(niobj->link.next)->next, 0);
+ const struct rb_callinfo_kwarg *kwarg = vm_ci_kwarg(ci);
+ if (vm_ci_mid(ci) == idPack && vm_ci_argc(ci) == 2 &&
+ (kwarg && kwarg->keyword_len == 1 && kwarg->keywords[0] == rb_id2sym(idBuffer))) {
+ VALUE num = iobj->operands[0];
+ insn_replace_with_operands(iseq, iobj, BIN(opt_newarray_send), 2, FIXNUM_INC(num, 2), INT2FIX(VM_OPT_NEWARRAY_SEND_PACK_BUFFER));
+ // Remove the "send" insn.
+ ELEM_REMOVE((niobj->link.next)->next);
+ // Remove the modified insn from its original "newarray" position...
+ ELEM_REMOVE(&iobj->link);
+ // and insert it after the buffer insn.
+ ELEM_INSERT_NEXT(niobj->link.next, &iobj->link);
+ return COMPILE_OK;
+ }
+ }
+
+ // Break the "else if" chain since some prior checks abort after sub-ifs.
+ // We already found "newarray". To match `[...].include?(arg)` we look for
+ // the instruction(s) representing the argument followed by a "send".
+ if ((IS_INSN_ID(niobj, putstring) || IS_INSN_ID(niobj, putchilledstring) ||
+ IS_INSN_ID(niobj, putobject) ||
+ IS_INSN_ID(niobj, putself) ||
+ IS_INSN_ID(niobj, getlocal) ||
+ IS_INSN_ID(niobj, getinstancevariable)) &&
+ IS_NEXT_INSN_ID(&niobj->link, send)) {
+
+ LINK_ELEMENT *sendobj = &(niobj->link); // Below we call ->next;
+ const struct rb_callinfo *ci;
+ // Allow any number (0 or more) of simple method calls on the argument
+ // (as in `[...].include?(arg.method1.method2)`.
+ do {
+ sendobj = sendobj->next;
+ ci = (struct rb_callinfo *)OPERAND_AT(sendobj, 0);
+ } while (vm_ci_simple(ci) && vm_ci_argc(ci) == 0 && IS_NEXT_INSN_ID(sendobj, send));
+
+ // If this send is for .include? with one arg we can do our opt.
+ if (vm_ci_simple(ci) && vm_ci_argc(ci) == 1 && vm_ci_mid(ci) == idIncludeP) {
+ VALUE num = iobj->operands[0];
+ INSN *sendins = (INSN *)sendobj;
+ insn_replace_with_operands(iseq, sendins, BIN(opt_newarray_send), 2, FIXNUM_INC(num, 1), INT2FIX(VM_OPT_NEWARRAY_SEND_INCLUDE_P));
+ // Remove the original "newarray" insn.
+ ELEM_REMOVE(&iobj->link);
+ return COMPILE_OK;
+ }
+ }
}
+ /*
+ * duparray [...]
+ * some insn for the arg...
+ * send <calldata!mid:include?, argc:1, ARGS_SIMPLE>, nil
+ * =>
+ * arg insn...
+ * opt_duparray_send [...], :include?, 1
+ */
+ if (IS_INSN_ID(iobj, duparray) && iobj->link.next && IS_INSN(iobj->link.next)) {
+ INSN *niobj = (INSN *)iobj->link.next;
+ if ((IS_INSN_ID(niobj, getlocal) ||
+ IS_INSN_ID(niobj, getinstancevariable) ||
+ IS_INSN_ID(niobj, putself)) &&
+ IS_NEXT_INSN_ID(&niobj->link, send)) {
+
+ LINK_ELEMENT *sendobj = &(niobj->link); // Below we call ->next;
+ const struct rb_callinfo *ci;
+ // Allow any number (0 or more) of simple method calls on the argument
+ // (as in `[...].include?(arg.method1.method2)`.
+ do {
+ sendobj = sendobj->next;
+ ci = (struct rb_callinfo *)OPERAND_AT(sendobj, 0);
+ } while (vm_ci_simple(ci) && vm_ci_argc(ci) == 0 && IS_NEXT_INSN_ID(sendobj, send));
+
+ if (vm_ci_simple(ci) && vm_ci_argc(ci) == 1 && vm_ci_mid(ci) == idIncludeP) {
+ // Move the array arg from duparray to opt_duparray_send.
+ VALUE ary = iobj->operands[0];
+ rb_obj_reveal(ary, rb_cArray);
+
+ INSN *sendins = (INSN *)sendobj;
+ insn_replace_with_operands(iseq, sendins, BIN(opt_duparray_send), 3, ary, rb_id2sym(idIncludeP), INT2FIX(1));
+
+ // Remove the duparray insn.
+ ELEM_REMOVE(&iobj->link);
+ return COMPILE_OK;
+ }
+ }
+ }
+
+
if (IS_INSN_ID(iobj, send)) {
const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(iobj, 0);
const rb_iseq_t *blockiseq = (rb_iseq_t *)OPERAND_AT(iobj, 1);
@@ -4144,7 +4391,7 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj)
}
}
- if ((vm_ci_flag(ci) & VM_CALL_ARGS_BLOCKARG) == 0 && blockiseq == NULL) {
+ if ((vm_ci_flag(ci) & (VM_CALL_ARGS_BLOCKARG | VM_CALL_FORWARDING)) == 0 && blockiseq == NULL) {
iobj->insn_id = BIN(opt_send_without_block);
iobj->operand_size = insn_len(iobj->insn_id) - 1;
}
@@ -4186,9 +4433,18 @@ iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
list = FIRST_ELEMENT(anchor);
int do_block_optimization = 0;
+ LABEL * block_loop_label = NULL;
- if (ISEQ_BODY(iseq)->type == ISEQ_TYPE_BLOCK && !ISEQ_COMPILE_DATA(iseq)->catch_except_p) {
+ // If we're optimizing a block
+ if (ISEQ_BODY(iseq)->type == ISEQ_TYPE_BLOCK) {
do_block_optimization = 1;
+
+ // If the block starts with a nop and a label,
+ // record the label so we can detect if it's a jump target
+ LINK_ELEMENT * le = FIRST_ELEMENT(anchor)->next;
+ if (IS_INSN(le) && IS_INSN_ID((INSN *)le, nop) && IS_LABEL(le->next)) {
+ block_loop_label = (LABEL *)le->next;
+ }
}
while (list) {
@@ -4205,9 +4461,27 @@ iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
if (do_block_optimization) {
INSN * item = (INSN *)list;
- if (IS_INSN_ID(item, jump)) {
+ // Give up if there is a throw
+ if (IS_INSN_ID(item, throw)) {
do_block_optimization = 0;
}
+ else {
+ // If the instruction has a jump target, check if the
+ // jump target is the block loop label
+ const char *types = insn_op_types(item->insn_id);
+ for (int j = 0; types[j]; j++) {
+ if (types[j] == TS_OFFSET) {
+ // If the jump target is equal to the block loop
+ // label, then we can't do the optimization because
+ // the leading `nop` instruction fires the block
+ // entry tracepoint
+ LABEL * target = (LABEL *)OPERAND_AT(item, j);
+ if (target == block_loop_label) {
+ do_block_optimization = 0;
+ }
+ }
+ }
+ }
}
}
if (IS_LABEL(list)) {
@@ -4347,47 +4621,91 @@ all_string_result_p(const NODE *node)
}
}
+struct dstr_ctxt {
+ rb_iseq_t *const iseq;
+ LINK_ANCHOR *const ret;
+ VALUE lit;
+ const NODE *lit_node;
+ int cnt;
+ int dregx;
+};
+
static int
-compile_dstr_fragments(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int *cntp)
+append_dstr_fragment(struct dstr_ctxt *args, const NODE *const node, rb_parser_string_t *str)
{
- const struct RNode_LIST *list = RNODE_DSTR(node)->nd_next;
- VALUE lit = rb_node_dstr_string_val(node);
- LINK_ELEMENT *first_lit = 0;
- int cnt = 0;
-
- debugp_param("nd_lit", lit);
- if (!NIL_P(lit)) {
- cnt++;
- if (!RB_TYPE_P(lit, T_STRING)) {
- COMPILE_ERROR(ERROR_ARGS "dstr: must be string: %s",
- rb_builtin_type_name(TYPE(lit)));
+ VALUE s = rb_str_new_mutable_parser_string(str);
+ if (args->dregx) {
+ VALUE error = rb_reg_check_preprocess(s);
+ if (!NIL_P(error)) {
+ COMPILE_ERROR(args->iseq, nd_line(node), "%" PRIsVALUE, error);
return COMPILE_NG;
}
+ }
+ if (NIL_P(args->lit)) {
+ args->lit = s;
+ args->lit_node = node;
+ }
+ else {
+ rb_str_buf_append(args->lit, s);
+ }
+ return COMPILE_OK;
+}
+
+static void
+flush_dstr_fragment(struct dstr_ctxt *args)
+{
+ if (!NIL_P(args->lit)) {
+ rb_iseq_t *iseq = args->iseq;
+ VALUE lit = args->lit;
+ args->lit = Qnil;
lit = rb_fstring(lit);
- ADD_INSN1(ret, node, putobject, lit);
- RB_OBJ_WRITTEN(iseq, Qundef, lit);
- if (RSTRING_LEN(lit) == 0) first_lit = LAST_ELEMENT(ret);
+ ADD_INSN1(args->ret, args->lit_node, putobject, lit);
+ RB_OBJ_WRITTEN(args->iseq, Qundef, lit);
+ args->cnt++;
+ }
+}
+
+static int
+compile_dstr_fragments_0(struct dstr_ctxt *args, const NODE *const node)
+{
+ const struct RNode_LIST *list = RNODE_DSTR(node)->nd_next;
+ rb_parser_string_t *str = RNODE_DSTR(node)->string;
+
+ if (str) {
+ CHECK(append_dstr_fragment(args, node, str));
}
while (list) {
const NODE *const head = list->nd_head;
if (nd_type_p(head, NODE_STR)) {
- lit = rb_node_str_string_val(head);
- ADD_INSN1(ret, head, putobject, lit);
- RB_OBJ_WRITTEN(iseq, Qundef, lit);
- lit = Qnil;
+ CHECK(append_dstr_fragment(args, node, RNODE_STR(head)->string));
+ }
+ else if (nd_type_p(head, NODE_DSTR)) {
+ CHECK(compile_dstr_fragments_0(args, head));
}
else {
- CHECK(COMPILE(ret, "each string", head));
+ flush_dstr_fragment(args);
+ rb_iseq_t *iseq = args->iseq;
+ CHECK(COMPILE(args->ret, "each string", head));
+ args->cnt++;
}
- cnt++;
list = (struct RNode_LIST *)list->nd_next;
}
- if (NIL_P(lit) && first_lit) {
- ELEM_REMOVE(first_lit);
- --cnt;
- }
- *cntp = cnt;
+ return COMPILE_OK;
+}
+
+static int
+compile_dstr_fragments(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int *cntp, int dregx)
+{
+ struct dstr_ctxt args = {
+ .iseq = iseq, .ret = ret,
+ .lit = Qnil, .lit_node = NULL,
+ .cnt = 0, .dregx = dregx,
+ };
+ CHECK(compile_dstr_fragments_0(&args, node));
+ flush_dstr_fragment(&args);
+
+ *cntp = args.cnt;
return COMPILE_OK;
}
@@ -4413,10 +4731,11 @@ compile_dstr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node)
if (!RNODE_DSTR(node)->nd_next) {
VALUE lit = rb_node_dstr_string_val(node);
ADD_INSN1(ret, node, putstring, lit);
+ RB_OBJ_SET_SHAREABLE(lit);
RB_OBJ_WRITTEN(iseq, Qundef, lit);
}
else {
- CHECK(compile_dstr_fragments(iseq, ret, node, &cnt));
+ CHECK(compile_dstr_fragments(iseq, ret, node, &cnt, FALSE));
ADD_INSN1(ret, node, concatstrings, INT2FIX(cnt));
}
return COMPILE_OK;
@@ -4432,13 +4751,14 @@ compile_dregx(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
if (!popped) {
VALUE src = rb_node_dregx_string_val(node);
VALUE match = rb_reg_compile(src, cflag, NULL, 0);
+ RB_OBJ_SET_SHAREABLE(match);
ADD_INSN1(ret, node, putobject, match);
RB_OBJ_WRITTEN(iseq, Qundef, match);
}
return COMPILE_OK;
}
- CHECK(compile_dstr_fragments(iseq, ret, node, &cnt));
+ CHECK(compile_dstr_fragments(iseq, ret, node, &cnt, TRUE));
ADD_INSN2(ret, node, toregexp, INT2FIX(cflag), INT2FIX(cnt));
if (popped) {
@@ -4573,7 +4893,7 @@ compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *ret, const NODE *cond,
CHECK(compile_flip_flop(iseq, ret, cond, FALSE, then_label, else_label));
return COMPILE_OK;
case NODE_DEFINED:
- CHECK(compile_defined_expr(iseq, ret, cond, Qfalse));
+ CHECK(compile_defined_expr(iseq, ret, cond, Qfalse, ret == ignore));
break;
default:
{
@@ -4776,13 +5096,21 @@ static_literal_value(const NODE *node, rb_iseq_t *iseq)
{
switch (nd_type(node)) {
case NODE_INTEGER:
- return rb_node_integer_literal_val(node);
+ {
+ VALUE lit = rb_node_integer_literal_val(node);
+ if (!SPECIAL_CONST_P(lit)) RB_OBJ_SET_SHAREABLE(lit);
+ return lit;
+ }
case NODE_FLOAT:
- return rb_node_float_literal_val(node);
+ {
+ VALUE lit = rb_node_float_literal_val(node);
+ if (!SPECIAL_CONST_P(lit)) RB_OBJ_SET_SHAREABLE(lit);
+ return lit;
+ }
case NODE_RATIONAL:
- return rb_node_rational_literal_val(node);
+ return rb_ractor_make_shareable(rb_node_rational_literal_val(node));
case NODE_IMAGINARY:
- return rb_node_imaginary_literal_val(node);
+ return rb_ractor_make_shareable(rb_node_imaginary_literal_val(node));
case NODE_NIL:
return Qnil;
case NODE_TRUE:
@@ -4792,7 +5120,7 @@ static_literal_value(const NODE *node, rb_iseq_t *iseq)
case NODE_SYM:
return rb_node_sym_string_val(node);
case NODE_REGX:
- return rb_node_regx_string_val(node);
+ return RB_OBJ_SET_SHAREABLE(rb_node_regx_string_val(node));
case NODE_LINE:
return rb_node_line_lineno_val(node);
case NODE_ENCODING:
@@ -4800,10 +5128,10 @@ static_literal_value(const NODE *node, rb_iseq_t *iseq)
case NODE_FILE:
case NODE_STR:
if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) {
- VALUE debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq), INT2FIX((int)nd_line(node)));
- VALUE lit = rb_str_dup(get_string_value(node));
- rb_ivar_set(lit, id_debug_created_info, rb_obj_freeze(debug_info));
- return rb_str_freeze(lit);
+ VALUE lit = get_string_value(node);
+ VALUE str = rb_str_with_debug_created_info(lit, rb_iseq_path(iseq), (int)nd_line(node));
+ RB_OBJ_SET_SHAREABLE(str);
+ return str;
}
else {
return get_string_value(node);
@@ -4901,7 +5229,7 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop
/* Create a hidden array */
for (; count; count--, node = RNODE_LIST(node)->nd_next)
rb_ary_push(ary, static_literal_value(RNODE_LIST(node)->nd_head, iseq));
- OBJ_FREEZE(ary);
+ RB_OBJ_SET_FROZEN_SHAREABLE(ary);
/* Emit optimized code */
FLUSH_CHUNK;
@@ -4913,6 +5241,7 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop
ADD_INSN1(ret, line_node, putobject, ary);
ADD_INSN(ret, line_node, concattoarray);
}
+ RB_OBJ_SET_SHAREABLE(ary);
RB_OBJ_WRITTEN(iseq, Qundef, ary);
}
}
@@ -5039,13 +5368,14 @@ compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int meth
for (; count; count--, node = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next) {
VALUE elem[2];
elem[0] = static_literal_value(RNODE_LIST(node)->nd_head, iseq);
+ if (!RB_SPECIAL_CONST_P(elem[0])) RB_OBJ_SET_FROZEN_SHAREABLE(elem[0]);
elem[1] = static_literal_value(RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_head, iseq);
+ if (!RB_SPECIAL_CONST_P(elem[1])) RB_OBJ_SET_FROZEN_SHAREABLE(elem[1]);
rb_ary_cat(ary, elem, 2);
}
VALUE hash = rb_hash_new_with_size(RARRAY_LEN(ary) / 2);
rb_hash_bulk_insert(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary), hash);
- hash = rb_obj_hide(hash);
- OBJ_FREEZE(hash);
+ hash = RB_OBJ_SET_FROZEN_SHAREABLE(rb_obj_hide(hash));
/* Emit optimized code */
FLUSH_CHUNK();
@@ -5712,10 +6042,12 @@ collect_const_segments(rb_iseq_t *iseq, const NODE *node)
switch (nd_type(node)) {
case NODE_CONST:
rb_ary_unshift(arr, ID2SYM(RNODE_CONST(node)->nd_vid));
+ RB_OBJ_SET_SHAREABLE(arr);
return arr;
case NODE_COLON3:
rb_ary_unshift(arr, ID2SYM(RNODE_COLON3(node)->nd_mid));
rb_ary_unshift(arr, ID2SYM(idNULL));
+ RB_OBJ_SET_SHAREABLE(arr);
return arr;
case NODE_COLON2:
rb_ary_unshift(arr, ID2SYM(RNODE_COLON2(node)->nd_mid));
@@ -5790,7 +6122,7 @@ private_recv_p(const NODE *node)
static void
defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
- const NODE *const node, LABEL **lfinish, VALUE needstr);
+ const NODE *const node, LABEL **lfinish, VALUE needstr, bool ignore);
static int
compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, const enum node_type type, const NODE *const line_node, int popped, bool assume_receiver);
@@ -5821,17 +6153,22 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
expr_type = DEFINED_FALSE;
break;
+ case NODE_HASH:
case NODE_LIST:{
- const NODE *vals = node;
+ const NODE *vals = (nd_type(node) == NODE_HASH) ? RNODE_HASH(node)->nd_head : node;
- do {
- defined_expr0(iseq, ret, RNODE_LIST(vals)->nd_head, lfinish, Qfalse, false);
+ if (vals) {
+ do {
+ if (RNODE_LIST(vals)->nd_head) {
+ defined_expr0(iseq, ret, RNODE_LIST(vals)->nd_head, lfinish, Qfalse, false);
- if (!lfinish[1]) {
- lfinish[1] = NEW_LABEL(line);
- }
- ADD_INSNL(ret, line_node, branchunless, lfinish[1]);
- } while ((vals = RNODE_LIST(vals)->nd_next) != NULL);
+ if (!lfinish[1]) {
+ lfinish[1] = NEW_LABEL(line);
+ }
+ ADD_INSNL(ret, line_node, branchunless, lfinish[1]);
+ }
+ } while ((vals = RNODE_LIST(vals)->nd_next) != NULL);
+ }
}
/* fall through */
case NODE_STR:
@@ -5851,6 +6188,15 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
expr_type = DEFINED_EXPR;
break;
+ case NODE_SPLAT:
+ defined_expr0(iseq, ret, RNODE_LIST(node)->nd_head, lfinish, Qfalse, false);
+ if (!lfinish[1]) {
+ lfinish[1] = NEW_LABEL(line);
+ }
+ ADD_INSNL(ret, line_node, branchunless, lfinish[1]);
+ expr_type = DEFINED_EXPR;
+ break;
+
/* variables */
case NODE_LVAR:
case NODE_DVAR:
@@ -6017,7 +6363,7 @@ build_defined_rescue_iseq(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const void *u
static void
defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
- const NODE *const node, LABEL **lfinish, VALUE needstr)
+ const NODE *const node, LABEL **lfinish, VALUE needstr, bool ignore)
{
LINK_ELEMENT *lcur = ret->last;
defined_expr0(iseq, ret, node, lfinish, needstr, false);
@@ -6028,20 +6374,22 @@ defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
const rb_iseq_t *rescue;
struct rb_iseq_new_with_callback_callback_func *ifunc =
rb_iseq_new_with_callback_new_callback(build_defined_rescue_iseq, NULL);
- rescue = new_child_iseq_with_callback(iseq, ifunc,
+ rescue = NEW_CHILD_ISEQ_WITH_CALLBACK(ifunc,
rb_str_concat(rb_str_new2("defined guard in "),
ISEQ_BODY(iseq)->location.label),
- iseq, ISEQ_TYPE_RESCUE, 0);
+ ISEQ_TYPE_RESCUE, 0);
lstart->rescued = LABEL_RESCUE_BEG;
lend->rescued = LABEL_RESCUE_END;
APPEND_LABEL(ret, lcur, lstart);
ADD_LABEL(ret, lend);
- ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE, lstart, lend, rescue, lfinish[1]);
+ if (!ignore) {
+ ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE, lstart, lend, rescue, lfinish[1]);
+ }
}
}
static int
-compile_defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, VALUE needstr)
+compile_defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, VALUE needstr, bool ignore)
{
const int line = nd_line(node);
const NODE *line_node = node;
@@ -6055,7 +6403,7 @@ compile_defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const
lfinish[0] = NEW_LABEL(line);
lfinish[1] = 0;
lfinish[2] = 0;
- defined_expr(iseq, ret, RNODE_DEFINED(node)->nd_head, lfinish, needstr);
+ defined_expr(iseq, ret, RNODE_DEFINED(node)->nd_head, lfinish, needstr, ignore);
if (lfinish[1]) {
ELEM_INSERT_NEXT(last, &new_insn_body(iseq, nd_line(line_node), nd_node_id(line_node), BIN(putnil), 0)->link);
ADD_INSN(ret, line_node, swap);
@@ -6199,9 +6547,24 @@ keyword_node_single_splat_p(NODE *kwnode)
RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next == NULL;
}
+static void
+compile_single_keyword_splat_mutable(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
+ NODE *kwnode, unsigned int *flag_ptr)
+{
+ *flag_ptr |= VM_CALL_KW_SPLAT_MUT;
+ ADD_INSN1(args, argn, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
+ ADD_INSN1(args, argn, newhash, INT2FIX(0));
+ compile_hash(iseq, args, kwnode, TRUE, FALSE);
+ ADD_SEND(args, argn, id_core_hash_merge_kwd, INT2FIX(2));
+}
+
+#define SPLATARRAY_FALSE 0
+#define SPLATARRAY_TRUE 1
+#define DUP_SINGLE_KW_SPLAT 2
+
static int
setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
- int dup_rest, unsigned int *flag_ptr, struct rb_callinfo_kwarg **kwarg_ptr)
+ unsigned int *dup_rest, unsigned int *flag_ptr, struct rb_callinfo_kwarg **kwarg_ptr)
{
if (!argn) return 0;
@@ -6218,7 +6581,12 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
len -= 1;
}
else {
- compile_hash(iseq, args, kwnode, TRUE, FALSE);
+ if (keyword_node_single_splat_p(kwnode) && (*dup_rest & DUP_SINGLE_KW_SPLAT)) {
+ compile_single_keyword_splat_mutable(iseq, args, argn, kwnode, flag_ptr);
+ }
+ else {
+ compile_hash(iseq, args, kwnode, TRUE, FALSE);
+ }
}
}
@@ -6227,17 +6595,15 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
case NODE_SPLAT: {
// f(*a)
NO_CHECK(COMPILE(args, "args (splat)", RNODE_SPLAT(argn)->nd_head));
- ADD_INSN1(args, argn, splatarray, RBOOL(dup_rest));
- if (flag_ptr) {
- *flag_ptr |= VM_CALL_ARGS_SPLAT;
- if (dup_rest) *flag_ptr |= VM_CALL_ARGS_SPLAT_MUT;
- }
+ ADD_INSN1(args, argn, splatarray, RBOOL(*dup_rest & SPLATARRAY_TRUE));
+ if (*dup_rest & SPLATARRAY_TRUE) *dup_rest &= ~SPLATARRAY_TRUE;
+ if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
RUBY_ASSERT(flag_ptr == NULL || (*flag_ptr & VM_CALL_KW_SPLAT) == 0);
return 1;
}
case NODE_ARGSCAT: {
- if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_SPLAT_MUT;
- int argc = setup_args_core(iseq, args, RNODE_ARGSCAT(argn)->nd_head, 1, NULL, NULL);
+ if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
+ int argc = setup_args_core(iseq, args, RNODE_ARGSCAT(argn)->nd_head, dup_rest, NULL, NULL);
bool args_pushed = false;
if (nd_type_p(RNODE_ARGSCAT(argn)->nd_body, NODE_LIST)) {
@@ -6252,7 +6618,8 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
}
if (nd_type_p(RNODE_ARGSCAT(argn)->nd_head, NODE_LIST)) {
- ADD_INSN1(args, argn, splatarray, Qtrue);
+ ADD_INSN1(args, argn, splatarray, RBOOL(*dup_rest & SPLATARRAY_TRUE));
+ if (*dup_rest & SPLATARRAY_TRUE) *dup_rest &= ~SPLATARRAY_TRUE;
argc += 1;
}
else if (!args_pushed) {
@@ -6263,7 +6630,6 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
if (kwnode) {
// kwsplat
*flag_ptr |= VM_CALL_KW_SPLAT;
- *flag_ptr |= VM_CALL_KW_SPLAT_MUT;
compile_hash(iseq, args, kwnode, TRUE, FALSE);
argc += 1;
}
@@ -6271,8 +6637,8 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
return argc;
}
case NODE_ARGSPUSH: {
- if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_SPLAT_MUT;
- int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, 1, NULL, NULL);
+ if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
+ int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, dup_rest, NULL, NULL);
if (nd_type_p(RNODE_ARGSPUSH(argn)->nd_body, NODE_LIST)) {
int rest_len = compile_args(iseq, args, RNODE_ARGSPUSH(argn)->nd_body, &kwnode);
@@ -6295,8 +6661,14 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
*flag_ptr |= VM_CALL_KW_SPLAT;
if (!keyword_node_single_splat_p(kwnode)) {
*flag_ptr |= VM_CALL_KW_SPLAT_MUT;
+ compile_hash(iseq, args, kwnode, TRUE, FALSE);
+ }
+ else if (*dup_rest & DUP_SINGLE_KW_SPLAT) {
+ compile_single_keyword_splat_mutable(iseq, args, argn, kwnode, flag_ptr);
+ }
+ else {
+ compile_hash(iseq, args, kwnode, TRUE, FALSE);
}
- compile_hash(iseq, args, kwnode, TRUE, FALSE);
argc += 1;
}
@@ -6308,18 +6680,148 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
}
}
+static void
+setup_args_splat_mut(unsigned int *flag, int dup_rest, int initial_dup_rest)
+{
+ if ((*flag & VM_CALL_ARGS_SPLAT) && dup_rest != initial_dup_rest) {
+ *flag |= VM_CALL_ARGS_SPLAT_MUT;
+ }
+}
+
+static bool
+setup_args_dup_rest_p(const NODE *argn)
+{
+ switch(nd_type(argn)) {
+ case NODE_LVAR:
+ case NODE_DVAR:
+ case NODE_GVAR:
+ case NODE_IVAR:
+ case NODE_CVAR:
+ case NODE_CONST:
+ case NODE_COLON3:
+ case NODE_INTEGER:
+ case NODE_FLOAT:
+ case NODE_RATIONAL:
+ case NODE_IMAGINARY:
+ case NODE_STR:
+ case NODE_SYM:
+ case NODE_REGX:
+ case NODE_SELF:
+ case NODE_NIL:
+ case NODE_TRUE:
+ case NODE_FALSE:
+ case NODE_LAMBDA:
+ case NODE_NTH_REF:
+ case NODE_BACK_REF:
+ return false;
+ case NODE_COLON2:
+ return setup_args_dup_rest_p(RNODE_COLON2(argn)->nd_head);
+ case NODE_LIST:
+ while (argn) {
+ if (setup_args_dup_rest_p(RNODE_LIST(argn)->nd_head)) {
+ return true;
+ }
+ argn = RNODE_LIST(argn)->nd_next;
+ }
+ return false;
+ default:
+ return true;
+ }
+}
+
static VALUE
setup_args(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
unsigned int *flag, struct rb_callinfo_kwarg **keywords)
{
VALUE ret;
+ unsigned int dup_rest = SPLATARRAY_TRUE, initial_dup_rest;
+
+ if (argn) {
+ const NODE *check_arg = nd_type_p(argn, NODE_BLOCK_PASS) ?
+ RNODE_BLOCK_PASS(argn)->nd_head : argn;
+
+ if (check_arg) {
+ switch(nd_type(check_arg)) {
+ case(NODE_SPLAT):
+ // avoid caller side array allocation for f(*arg)
+ dup_rest = SPLATARRAY_FALSE;
+ break;
+ case(NODE_ARGSCAT):
+ // avoid caller side array allocation for f(1, *arg)
+ dup_rest = !nd_type_p(RNODE_ARGSCAT(check_arg)->nd_head, NODE_LIST);
+ break;
+ case(NODE_ARGSPUSH):
+ // avoid caller side array allocation for f(*arg, **hash) and f(1, *arg, **hash)
+ dup_rest = !((nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_head, NODE_SPLAT) ||
+ (nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_head, NODE_ARGSCAT) &&
+ nd_type_p(RNODE_ARGSCAT(RNODE_ARGSPUSH(check_arg)->nd_head)->nd_head, NODE_LIST))) &&
+ nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_body, NODE_HASH) &&
+ !RNODE_HASH(RNODE_ARGSPUSH(check_arg)->nd_body)->nd_brace);
+
+ if (dup_rest == SPLATARRAY_FALSE) {
+ // require allocation for keyword key/value/splat that may modify splatted argument
+ NODE *node = RNODE_HASH(RNODE_ARGSPUSH(check_arg)->nd_body)->nd_head;
+ while (node) {
+ NODE *key_node = RNODE_LIST(node)->nd_head;
+ if (key_node && setup_args_dup_rest_p(key_node)) {
+ dup_rest = SPLATARRAY_TRUE;
+ break;
+ }
+
+ node = RNODE_LIST(node)->nd_next;
+ NODE *value_node = RNODE_LIST(node)->nd_head;
+ if (setup_args_dup_rest_p(value_node)) {
+ dup_rest = SPLATARRAY_TRUE;
+ break;
+ }
+
+ node = RNODE_LIST(node)->nd_next;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (check_arg != argn && setup_args_dup_rest_p(RNODE_BLOCK_PASS(argn)->nd_body)) {
+ // for block pass that may modify splatted argument, dup rest and kwrest if given
+ dup_rest = SPLATARRAY_TRUE | DUP_SINGLE_KW_SPLAT;
+ }
+ }
+ initial_dup_rest = dup_rest;
+
if (argn && nd_type_p(argn, NODE_BLOCK_PASS)) {
- unsigned int dup_rest = 1;
DECL_ANCHOR(arg_block);
INIT_ANCHOR(arg_block);
- NO_CHECK(COMPILE(arg_block, "block", RNODE_BLOCK_PASS(argn)->nd_body));
- *flag |= VM_CALL_ARGS_BLOCKARG;
+ if (RNODE_BLOCK_PASS(argn)->forwarding && ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->param.flags.forwardable) {
+ int idx = ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->local_table_size;// - get_local_var_idx(iseq, idDot3);
+
+ RUBY_ASSERT(nd_type_p(RNODE_BLOCK_PASS(argn)->nd_head, NODE_ARGSPUSH));
+ const NODE * arg_node =
+ RNODE_ARGSPUSH(RNODE_BLOCK_PASS(argn)->nd_head)->nd_head;
+
+ int argc = 0;
+
+ // Only compile leading args:
+ // foo(x, y, ...)
+ // ^^^^
+ if (nd_type_p(arg_node, NODE_ARGSCAT)) {
+ argc += setup_args_core(iseq, args, RNODE_ARGSCAT(arg_node)->nd_head, &dup_rest, flag, keywords);
+ }
+
+ *flag |= VM_CALL_FORWARDING;
+
+ ADD_GETLOCAL(args, argn, idx, get_lvar_level(iseq));
+ setup_args_splat_mut(flag, dup_rest, initial_dup_rest);
+ return INT2FIX(argc);
+ }
+ else {
+ *flag |= VM_CALL_ARGS_BLOCKARG;
+
+ NO_CHECK(COMPILE(arg_block, "block", RNODE_BLOCK_PASS(argn)->nd_body));
+ }
if (LIST_INSN_SIZE_ONE(arg_block)) {
LINK_ELEMENT *elem = FIRST_ELEMENT(arg_block);
@@ -6328,15 +6830,15 @@ 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 = INT2FIX(setup_args_core(iseq, args, RNODE_BLOCK_PASS(argn)->nd_head, dup_rest, flag, keywords));
+ ret = INT2FIX(setup_args_core(iseq, args, RNODE_BLOCK_PASS(argn)->nd_head, &dup_rest, flag, keywords));
ADD_SEQ(args, arg_block);
}
else {
- ret = INT2FIX(setup_args_core(iseq, args, argn, 0, flag, keywords));
+ ret = INT2FIX(setup_args_core(iseq, args, argn, &dup_rest, flag, keywords));
}
+ setup_args_splat_mut(flag, dup_rest, initial_dup_rest);
return ret;
}
@@ -6351,7 +6853,7 @@ build_postexe_iseq(rb_iseq_t *iseq, LINK_ANCHOR *ret, const void *ptr)
ADD_INSN1(ret, body, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
ADD_CALL_WITH_BLOCK(ret, body, id_core_set_postexe, argc, block);
RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)block);
- iseq_set_local_table(iseq, 0);
+ iseq_set_local_table(iseq, 0, 0);
}
static void
@@ -6468,7 +6970,12 @@ compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int
else_label = NEW_LABEL(line);
end_label = 0;
- compile_branch_condition(iseq, cond_seq, RNODE_IF(node)->nd_cond, then_label, else_label);
+ NODE *cond = RNODE_IF(node)->nd_cond;
+ if (nd_type(cond) == NODE_BLOCK) {
+ cond = RNODE_BLOCK(cond)->nd_head;
+ }
+
+ CHECK(compile_branch_condition(iseq, cond_seq, cond, then_label, else_label));
ADD_SEQ(ret, cond_seq);
if (then_label->refcnt && else_label->refcnt) {
@@ -6637,6 +7144,7 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod
if (only_special_literals && ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
ADD_INSN(ret, orig_node, dup);
+ rb_obj_hide(literals);
ADD_INSN2(ret, orig_node, opt_case_dispatch, literals, elselabel);
RB_OBJ_WRITTEN(iseq, Qundef, literals);
LABEL_REF(elselabel);
@@ -7172,6 +7680,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
ADD_INSN(ret, line_node, putnil);
}
else {
+ RB_OBJ_SET_FROZEN_SHAREABLE(keys);
ADD_INSN1(ret, line_node, duparray, keys);
RB_OBJ_WRITTEN(iseq, Qundef, rb_obj_hide(keys));
}
@@ -7209,7 +7718,8 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c
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)
+ VALUE str = rb_str_freeze(rb_sprintf("key not found: %+"PRIsVALUE, key));
+ ADD_INSN1(ret, line_node, putobject, RB_OBJ_SET_SHAREABLE(str)); // (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) */));
@@ -7876,13 +8386,13 @@ compile_loop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
ADD_LABEL(ret, next_label); /* next */
if (type == NODE_WHILE) {
- compile_branch_condition(iseq, ret, RNODE_WHILE(node)->nd_cond,
- redo_label, end_label);
+ CHECK(compile_branch_condition(iseq, ret, RNODE_WHILE(node)->nd_cond,
+ redo_label, end_label));
}
else {
/* until */
- compile_branch_condition(iseq, ret, RNODE_WHILE(node)->nd_cond,
- end_label, redo_label);
+ CHECK(compile_branch_condition(iseq, ret, RNODE_WHILE(node)->nd_cond,
+ end_label, redo_label));
}
ADD_LABEL(ret, end_label);
@@ -7952,11 +8462,11 @@ compile_iter(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
// Normally, "send" instruction is at the last.
// However, qcall under branch coverage measurement adds some instructions after the "send".
//
- // Note that "invokesuper" appears instead of "send".
+ // Note that "invokesuper", "invokesuperforward" appears instead of "send".
INSN *iobj;
LINK_ELEMENT *last_elem = LAST_ELEMENT(ret);
iobj = IS_INSN(last_elem) ? (INSN*) last_elem : (INSN*) get_prev_insn((INSN*) last_elem);
- while (INSN_OF(iobj) != BIN(send) && INSN_OF(iobj) != BIN(invokesuper)) {
+ while (!IS_INSN_ID(iobj, send) && !IS_INSN_ID(iobj, invokesuper) && !IS_INSN_ID(iobj, sendforward) && !IS_INSN_ID(iobj, invokesuperforward)) {
iobj = (INSN*) get_prev_insn(iobj);
}
ELEM_INSERT_NEXT(&iobj->link, (LINK_ELEMENT*) retry_end_l);
@@ -8096,7 +8606,6 @@ compile_next(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
add_ensure_iseq(ret, iseq, 0);
ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
ADD_ADJUST_RESTORE(ret, splabel);
- splabel->unremovable = FALSE;
if (!popped) {
ADD_INSN(ret, line_node, putnil);
@@ -8320,7 +8829,11 @@ compile_resbody(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
ADD_LABEL(ret, label_hit);
ADD_TRACE(ret, RUBY_EVENT_RESCUE);
- if (nd_type(RNODE_RESBODY(resq)->nd_body) == NODE_BEGIN && RNODE_BEGIN(RNODE_RESBODY(resq)->nd_body)->nd_body == NULL) {
+ if (RNODE_RESBODY(resq)->nd_exc_var) {
+ CHECK(COMPILE_POPPED(ret, "resbody exc_var", RNODE_RESBODY(resq)->nd_exc_var));
+ }
+
+ if (nd_type(RNODE_RESBODY(resq)->nd_body) == NODE_BEGIN && RNODE_BEGIN(RNODE_RESBODY(resq)->nd_body)->nd_body == NULL && !RNODE_RESBODY(resq)->nd_exc_var) {
// empty body
ADD_SYNTHETIC_INSN(ret, nd_line(RNODE_RESBODY(resq)->nd_body), -1, putnil);
}
@@ -8446,6 +8959,27 @@ compile_return(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
return COMPILE_OK;
}
+static bool
+drop_unreachable_return(LINK_ANCHOR *ret)
+{
+ LINK_ELEMENT *i = ret->last, *last;
+ if (!i) return false;
+ if (IS_TRACE(i)) i = i->prev;
+ if (!IS_INSN(i) || !IS_INSN_ID(i, putnil)) return false;
+ last = i = i->prev;
+ if (IS_ADJUST(i)) i = i->prev;
+ if (!IS_INSN(i)) return false;
+ switch (INSN_OF(i)) {
+ case BIN(leave):
+ case BIN(jump):
+ break;
+ default:
+ return false;
+ }
+ (ret->last = last->prev)->next = NULL;
+ return true;
+}
+
static int
compile_evstr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped)
{
@@ -8526,25 +9060,6 @@ compile_call_precheck_freeze(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE
}
return TRUE;
}
- /* optimization shortcut
- * obj["literal"] -> opt_aref_with(obj, "literal")
- */
- if (get_node_call_nd_mid(node) == idAREF && !private_recv_p(node) && get_nd_args(node) &&
- nd_type_p(get_nd_args(node), NODE_LIST) && RNODE_LIST(get_nd_args(node))->as.nd_alen == 1 &&
- (nd_type_p(RNODE_LIST(get_nd_args(node))->nd_head, NODE_STR) || nd_type_p(RNODE_LIST(get_nd_args(node))->nd_head, NODE_FILE)) &&
- ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
- !frozen_string_literal_p(iseq) &&
- ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
- VALUE str = get_string_value(RNODE_LIST(get_nd_args(node))->nd_head);
- CHECK(COMPILE(ret, "recv", get_nd_recv(node)));
- ADD_INSN2(ret, line_node, opt_aref_with, str,
- new_callinfo(iseq, idAREF, 1, 0, NULL, FALSE));
- RB_OBJ_WRITTEN(iseq, Qundef, str);
- if (popped) {
- ADD_INSN(ret, line_node, pop);
- }
- return TRUE;
- }
return FALSE;
}
@@ -8688,7 +9203,7 @@ compile_builtin_attr(rb_iseq_t *iseq, const NODE *node)
if (!SYMBOL_P(symbol)) goto non_symbol_arg;
- string = rb_sym_to_s(symbol);
+ string = rb_sym2str(symbol);
if (strcmp(RSTRING_PTR(string), "leaf") == 0) {
ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_LEAF;
}
@@ -8698,6 +9213,10 @@ compile_builtin_attr(rb_iseq_t *iseq, const NODE *node)
else if (strcmp(RSTRING_PTR(string), "use_block") == 0) {
iseq_set_use_block(iseq);
}
+ else if (strcmp(RSTRING_PTR(string), "c_trace") == 0) {
+ // Let the iseq act like a C method in backtraces
+ ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_C_TRACE;
+ }
else {
goto unknown_arg;
}
@@ -8799,16 +9318,18 @@ compile_builtin_mandatory_only_method(rb_iseq_t *iseq, const NODE *node, const N
rb_node_init(RNODE(&scope_node), NODE_SCOPE);
scope_node.nd_tbl = tbl;
scope_node.nd_body = mandatory_node(iseq, node);
+ scope_node.nd_parent = NULL;
scope_node.nd_args = &args_node;
VALUE ast_value = rb_ruby_ast_new(RNODE(&scope_node));
- ISEQ_BODY(iseq)->mandatory_only_iseq =
+ const rb_iseq_t *mandatory_only_iseq =
rb_iseq_new_with_opt(ast_value, rb_iseq_base_label(iseq),
rb_iseq_path(iseq), rb_iseq_realpath(iseq),
nd_line(line_node), NULL, 0,
ISEQ_TYPE_METHOD, ISEQ_COMPILE_DATA(iseq)->option,
ISEQ_BODY(iseq)->variable.script_lines);
+ RB_OBJ_WRITE(iseq, &ISEQ_BODY(iseq)->mandatory_only_iseq, (VALUE)mandatory_only_iseq);
ALLOCV_END(idtmp);
return COMPILE_OK;
@@ -8877,7 +9398,7 @@ compile_builtin_function_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NOD
if (cconst) {
typedef VALUE(*builtin_func0)(void *, VALUE);
- VALUE const_val = (*(builtin_func0)bf->func_ptr)(NULL, Qnil);
+ VALUE const_val = (*(builtin_func0)(uintptr_t)bf->func_ptr)(NULL, Qnil);
ADD_INSN1(ret, line_node, putobject, const_val);
return COMPILE_OK;
}
@@ -8929,6 +9450,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co
INIT_ANCHOR(recv);
INIT_ANCHOR(args);
+
#if OPT_SUPPORT_JOKE
if (nd_type_p(node, NODE_VCALL)) {
ID id_bitblt;
@@ -9024,6 +9546,17 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co
}
ADD_SEQ(ret, recv);
+
+ bool inline_new = ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction &&
+ mid == rb_intern("new") &&
+ parent_block == NULL &&
+ !(flag & VM_CALL_ARGS_BLOCKARG);
+
+ if (inline_new) {
+ ADD_INSN(ret, node, putnil);
+ ADD_INSN(ret, node, swap);
+ }
+
ADD_SEQ(ret, args);
debugp_param("call args argc", argc);
@@ -9040,7 +9573,37 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co
if ((flag & VM_CALL_ARGS_BLOCKARG) && (flag & VM_CALL_KW_SPLAT) && !(flag & VM_CALL_KW_SPLAT_MUT)) {
ADD_INSN(ret, line_node, splatkw);
}
- ADD_SEND_R(ret, line_node, mid, argc, parent_block, INT2FIX(flag), keywords);
+
+ LABEL *not_basic_new = NEW_LABEL(nd_line(node));
+ LABEL *not_basic_new_finish = NEW_LABEL(nd_line(node));
+
+ if (inline_new) {
+ // Jump unless the receiver uses the "basic" implementation of "new"
+ VALUE ci;
+ if (flag & VM_CALL_FORWARDING) {
+ ci = (VALUE)new_callinfo(iseq, mid, NUM2INT(argc) + 1, flag, keywords, 0);
+ }
+ else {
+ ci = (VALUE)new_callinfo(iseq, mid, NUM2INT(argc), flag, keywords, 0);
+ }
+ ADD_INSN2(ret, node, opt_new, ci, not_basic_new);
+ LABEL_REF(not_basic_new);
+
+ // optimized path
+ ADD_SEND_R(ret, line_node, rb_intern("initialize"), argc, parent_block, INT2FIX(flag | VM_CALL_FCALL), keywords);
+ ADD_INSNL(ret, line_node, jump, not_basic_new_finish);
+
+ ADD_LABEL(ret, not_basic_new);
+ // Fall back to normal send
+ ADD_SEND_R(ret, line_node, mid, argc, parent_block, INT2FIX(flag), keywords);
+ ADD_INSN(ret, line_node, swap);
+
+ ADD_LABEL(ret, not_basic_new_finish);
+ ADD_INSN(ret, line_node, pop);
+ }
+ else {
+ ADD_SEND_R(ret, line_node, mid, argc, parent_block, INT2FIX(flag), keywords);
+ }
qcall_branch_end(iseq, ret, else_label, branches, node, line_node);
if (popped) {
@@ -9387,7 +9950,7 @@ compile_op_log(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
LABEL *lfinish[2];
lfinish[0] = lfin;
lfinish[1] = 0;
- defined_expr(iseq, ret, RNODE_OP_ASGN_OR(node)->nd_head, lfinish, Qfalse);
+ defined_expr(iseq, ret, RNODE_OP_ASGN_OR(node)->nd_head, lfinish, Qfalse, false);
lassign = lfinish[1];
if (!lassign) {
lassign = NEW_LABEL(line);
@@ -9463,6 +10026,13 @@ compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
ADD_GETLOCAL(args, node, idx, lvar_level);
}
+ /* forward ... */
+ if (local_body->param.flags.forwardable) {
+ flag |= VM_CALL_FORWARDING;
+ int idx = local_body->local_table_size - get_local_var_idx(liseq, idDot3);
+ ADD_GETLOCAL(args, node, idx, lvar_level);
+ }
+
if (local_body->param.flags.has_opt) {
/* optional arguments */
int j;
@@ -9547,9 +10117,15 @@ compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
if (type == NODE_ZSUPER) flag |= VM_CALL_ZSUPER;
ADD_INSN(ret, node, putself);
ADD_SEQ(ret, args);
- ADD_INSN2(ret, node, invokesuper,
- new_callinfo(iseq, 0, argc, flag, keywords, parent_block != NULL),
- parent_block);
+
+ const struct rb_callinfo * ci = new_callinfo(iseq, 0, argc, flag, keywords, parent_block != NULL);
+
+ if (vm_ci_flag(ci) & VM_CALL_FORWARDING) {
+ ADD_INSN2(ret, node, invokesuperforward, ci, parent_block);
+ }
+ else {
+ ADD_INSN2(ret, node, invokesuper, ci, parent_block);
+ }
if (popped) {
ADD_INSN(ret, node, pop);
@@ -9612,9 +10188,13 @@ compile_match(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
INIT_ANCHOR(val);
switch ((int)type) {
case NODE_MATCH:
- ADD_INSN1(recv, node, putobject, rb_node_regx_string_val(node));
- ADD_INSN2(val, node, getspecial, INT2FIX(0),
- INT2FIX(0));
+ {
+ VALUE re = rb_node_regx_string_val(node);
+ RB_OBJ_SET_FROZEN_SHAREABLE(re);
+ ADD_INSN1(recv, node, putobject, re);
+ ADD_INSN2(val, node, getspecial, INT2FIX(0),
+ INT2FIX(0));
+ }
break;
case NODE_MATCH2:
CHECK(COMPILE(recv, "receiver", RNODE_MATCH2(node)->nd_recv));
@@ -9691,6 +10271,7 @@ compile_colon3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node,
if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
ISEQ_BODY(iseq)->ic_size++;
VALUE segments = rb_ary_new_from_args(2, ID2SYM(idNULL), ID2SYM(RNODE_COLON3(node)->nd_mid));
+ RB_OBJ_SET_FROZEN_SHAREABLE(segments);
ADD_INSN1(ret, node, opt_getconstant_path, segments);
RB_OBJ_WRITTEN(iseq, Qundef, segments);
}
@@ -9718,6 +10299,7 @@ compile_dots(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
VALUE bv = optimized_range_item(b);
VALUE ev = optimized_range_item(e);
VALUE val = rb_range_new(bv, ev, excl);
+ rb_ractor_make_shareable(rb_obj_freeze(val));
ADD_INSN1(ret, node, putobject, val);
RB_OBJ_WRITTEN(iseq, Qundef, val);
}
@@ -9812,30 +10394,6 @@ compile_attrasgn(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
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) && RNODE_ATTRASGN(node)->nd_args &&
- nd_type_p(RNODE_ATTRASGN(node)->nd_args, NODE_LIST) && RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->as.nd_alen == 2 &&
- (nd_type_p(RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->nd_head, NODE_STR) || nd_type_p(RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->nd_head, NODE_FILE)) &&
- ISEQ_COMPILE_DATA(iseq)->current_block == NULL &&
- !frozen_string_literal_p(iseq) &&
- ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction)
- {
- VALUE str = get_string_value(RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->nd_head);
- CHECK(COMPILE(ret, "recv", RNODE_ATTRASGN(node)->nd_recv));
- CHECK(COMPILE(ret, "value", RNODE_LIST(RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->nd_next)->nd_head));
- if (!popped) {
- ADD_INSN(ret, node, swap);
- ADD_INSN1(ret, node, topn, INT2FIX(1));
- }
- ADD_INSN2(ret, node, opt_aset_with, str,
- new_callinfo(iseq, idASET, 2, 0, NULL, FALSE));
- RB_OBJ_WRITTEN(iseq, Qundef, str);
- ADD_INSN(ret, node, pop);
- return COMPILE_OK;
- }
-
INIT_ANCHOR(recv);
INIT_ANCHOR(args);
argc = setup_args(iseq, args, RNODE_ATTRASGN(node)->nd_args, &flag, NULL);
@@ -9882,7 +10440,7 @@ compile_attrasgn(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node
static int
compile_make_shareable_node(rb_iseq_t *iseq, LINK_ANCHOR *ret, LINK_ANCHOR *sub, const NODE *value, bool copy)
{
- ADD_INSN1(ret, value, putobject, rb_mRubyVMFrozenCore);
+ ADD_INSN1(ret, value, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
ADD_SEQ(ret, sub);
if (copy) {
@@ -9971,7 +10529,7 @@ compile_ensure_shareable_node(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *dest, con
*. RubyVM::FrozenCore.ensure_shareable(value, const_decl_path(dest))
*/
VALUE path = const_decl_path(dest);
- ADD_INSN1(ret, value, putobject, rb_mRubyVMFrozenCore);
+ ADD_INSN1(ret, value, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
CHECK(COMPILE(ret, "compile_ensure_shareable_node", value));
ADD_INSN1(ret, value, putobject, path);
RB_OBJ_WRITTEN(iseq, Qundef, path);
@@ -9992,7 +10550,7 @@ compile_shareable_literal_constant(rb_iseq_t *iseq, LINK_ANCHOR *ret, enum rb_pa
VALUE lit = Qnil;
DECL_ANCHOR(anchor);
- enum node_type type = nd_type(node);
+ enum node_type type = node ? nd_type(node) : NODE_NIL;
switch (type) {
case NODE_TRUE:
*value_p = Qtrue;
@@ -10112,34 +10670,36 @@ compile_shareable_literal_constant(rb_iseq_t *iseq, LINK_ANCHOR *ret, enum rb_pa
*shareable_literal_p = 0;
return COMPILE_OK;
}
+ for (NODE *n = RNODE_HASH(node)->nd_head; n; n = RNODE_LIST(RNODE_LIST(n)->nd_next)->nd_next) {
+ if (!RNODE_LIST(n)->nd_head) {
+ // If the hash node have a keyword splat, fall back to the default case.
+ goto compile_shareable;
+ }
+ }
INIT_ANCHOR(anchor);
lit = rb_hash_new();
for (NODE *n = RNODE_HASH(node)->nd_head; n; n = RNODE_LIST(RNODE_LIST(n)->nd_next)->nd_next) {
- VALUE key_val;
- VALUE value_val;
+ VALUE key_val = 0;
+ VALUE value_val = 0;
int shareable_literal_p2;
NODE *key = RNODE_LIST(n)->nd_head;
NODE *val = RNODE_LIST(RNODE_LIST(n)->nd_next)->nd_head;
- if (key) {
- CHECK(compile_shareable_literal_constant_next(key, anchor, &key_val, &shareable_literal_p2));
- if (shareable_literal_p2) {
- /* noop */
- }
- else if (RTEST(lit)) {
- rb_hash_clear(lit);
- lit = Qfalse;
- }
+ CHECK(compile_shareable_literal_constant_next(key, anchor, &key_val, &shareable_literal_p2));
+ if (shareable_literal_p2) {
+ /* noop */
}
- if (val) {
- CHECK(compile_shareable_literal_constant_next(val, anchor, &value_val, &shareable_literal_p2));
- if (shareable_literal_p2) {
- /* noop */
- }
- else if (RTEST(lit)) {
- rb_hash_clear(lit);
- lit = Qfalse;
- }
+ else if (RTEST(lit)) {
+ rb_hash_clear(lit);
+ lit = Qfalse;
+ }
+ CHECK(compile_shareable_literal_constant_next(val, anchor, &value_val, &shareable_literal_p2));
+ if (shareable_literal_p2) {
+ /* noop */
+ }
+ else if (RTEST(lit)) {
+ rb_hash_clear(lit);
+ lit = Qfalse;
}
if (RTEST(lit)) {
if (!UNDEF_P(key_val) && !UNDEF_P(value_val)) {
@@ -10155,6 +10715,8 @@ compile_shareable_literal_constant(rb_iseq_t *iseq, LINK_ANCHOR *ret, enum rb_pa
}
default:
+
+ compile_shareable:
if (shareable == rb_parser_shareable_literal &&
(SHAREABLE_BARE_EXPRESSION || level > 0)) {
CHECK(compile_ensure_shareable_node(iseq, ret, dest, node));
@@ -10168,7 +10730,7 @@ compile_shareable_literal_constant(rb_iseq_t *iseq, LINK_ANCHOR *ret, enum rb_pa
return COMPILE_OK;
}
- /* Array or Hash */
+ /* Array or Hash that does not have keyword splat */
if (!lit) {
if (nd_type(node) == NODE_LIST) {
ADD_INSN1(anchor, node, newarray, INT2FIX(RNODE_LIST(node)->as.nd_alen));
@@ -10277,7 +10839,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
if (nd_fl_newline(node)) {
int event = RUBY_EVENT_LINE;
ISEQ_COMPILE_DATA(iseq)->last_line = line;
- if (ISEQ_COVERAGE(iseq) && ISEQ_LINE_COVERAGE(iseq)) {
+ if (line > 0 && ISEQ_COVERAGE(iseq) && ISEQ_LINE_COVERAGE(iseq)) {
event |= RUBY_EVENT_COVERAGE_LINE;
}
ADD_TRACE(ret, event);
@@ -10546,6 +11108,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
body->ic_size++;
VALUE segments = rb_ary_new_from_args(1, ID2SYM(RNODE_CONST(node)->nd_vid));
+ RB_OBJ_SET_FROZEN_SHAREABLE(segments);
ADD_INSN1(ret, node, opt_getconstant_path, segments);
RB_OBJ_WRITTEN(iseq, Qundef, segments);
}
@@ -10611,6 +11174,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
}
case NODE_INTEGER:{
VALUE lit = rb_node_integer_literal_val(node);
+ if (!SPECIAL_CONST_P(lit)) RB_OBJ_SET_SHAREABLE(lit);
debugp_param("integer", lit);
if (!popped) {
ADD_INSN1(ret, node, putobject, lit);
@@ -10620,6 +11184,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
}
case NODE_FLOAT:{
VALUE lit = rb_node_float_literal_val(node);
+ if (!SPECIAL_CONST_P(lit)) RB_OBJ_SET_SHAREABLE(lit);
debugp_param("float", lit);
if (!popped) {
ADD_INSN1(ret, node, putobject, lit);
@@ -10629,6 +11194,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
}
case NODE_RATIONAL:{
VALUE lit = rb_node_rational_literal_val(node);
+ rb_ractor_make_shareable(lit);
debugp_param("rational", lit);
if (!popped) {
ADD_INSN1(ret, node, putobject, lit);
@@ -10638,6 +11204,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
}
case NODE_IMAGINARY:{
VALUE lit = rb_node_imaginary_literal_val(node);
+ rb_ractor_make_shareable(lit);
debugp_param("imaginary", lit);
if (!popped) {
ADD_INSN1(ret, node, putobject, lit);
@@ -10650,28 +11217,26 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
debugp_param("nd_lit", get_string_value(node));
if (!popped) {
VALUE lit = get_string_value(node);
- switch (ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal) {
+ const rb_compile_option_t *option = ISEQ_COMPILE_DATA(iseq)->option;
+ if ((option->debug_frozen_string_literal || RTEST(ruby_debug)) &&
+ option->frozen_string_literal != ISEQ_FROZEN_STRING_LITERAL_DISABLED) {
+ lit = rb_str_with_debug_created_info(lit, rb_iseq_path(iseq), line);
+ RB_OBJ_SET_SHAREABLE(lit);
+ }
+ switch (option->frozen_string_literal) {
case ISEQ_FROZEN_STRING_LITERAL_UNSET:
ADD_INSN1(ret, node, putchilledstring, lit);
- RB_OBJ_WRITTEN(iseq, Qundef, lit);
break;
case ISEQ_FROZEN_STRING_LITERAL_DISABLED:
ADD_INSN1(ret, node, putstring, lit);
- RB_OBJ_WRITTEN(iseq, Qundef, lit);
break;
case ISEQ_FROZEN_STRING_LITERAL_ENABLED:
- if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) {
- VALUE debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq), INT2FIX(line));
- lit = rb_str_dup(lit);
- rb_ivar_set(lit, id_debug_created_info, rb_obj_freeze(debug_info));
- lit = rb_str_freeze(lit);
- }
ADD_INSN1(ret, node, putobject, lit);
- RB_OBJ_WRITTEN(iseq, Qundef, lit);
break;
default:
rb_bug("invalid frozen_string_literal");
}
+ RB_OBJ_WRITTEN(iseq, Qundef, lit);
}
break;
}
@@ -10711,6 +11276,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
case NODE_REGX:{
if (!popped) {
VALUE lit = rb_node_regx_string_val(node);
+ RB_OBJ_SET_SHAREABLE(lit);
ADD_INSN1(ret, node, putobject, lit);
RB_OBJ_WRITTEN(iseq, Qundef, lit);
}
@@ -10844,10 +11410,18 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
break;
}
case NODE_UNDEF:{
- ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
- ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
- CHECK(COMPILE(ret, "undef arg", RNODE_UNDEF(node)->nd_undef));
- ADD_SEND(ret, node, id_core_undef_method, INT2FIX(2));
+ const rb_parser_ary_t *ary = RNODE_UNDEF(node)->nd_undefs;
+
+ for (long i = 0; i < ary->len; i++) {
+ ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
+ ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
+ CHECK(COMPILE(ret, "undef arg", ary->data[i]));
+ ADD_SEND(ret, node, id_core_undef_method, INT2FIX(2));
+
+ if (i < ary->len - 1) {
+ ADD_INSN(ret, node, pop);
+ }
+ }
if (popped) {
ADD_INSN(ret, node, pop);
@@ -10961,7 +11535,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
break;
case NODE_DEFINED:
if (!popped) {
- CHECK(compile_defined_expr(iseq, ret, node, Qtrue));
+ CHECK(compile_defined_expr(iseq, ret, node, Qtrue, false));
}
break;
case NODE_POSTEXE:{
@@ -10972,8 +11546,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
struct rb_iseq_new_with_callback_callback_func *ifunc =
rb_iseq_new_with_callback_new_callback(build_postexe_iseq, RNODE_POSTEXE(node)->nd_body);
const rb_iseq_t *once_iseq =
- new_child_iseq_with_callback(iseq, ifunc,
- rb_fstring(make_name_for_block(iseq)), iseq, ISEQ_TYPE_BLOCK, line);
+ NEW_CHILD_ISEQ_WITH_CALLBACK(ifunc, rb_fstring(make_name_for_block(iseq)), ISEQ_TYPE_BLOCK, line);
ADD_INSN2(ret, node, once, once_iseq, INT2FIX(is_index));
RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)once_iseq);
@@ -11204,7 +11777,7 @@ dump_disasm_list_with_cursor(const LINK_ELEMENT *link, const LINK_ELEMENT *curr,
}
default:
/* ignore */
- rb_raise(rb_eSyntaxError, "dump_disasm_list error: %ld\n", FIX2LONG(link->type));
+ rb_raise(rb_eSyntaxError, "dump_disasm_list error: %d\n", (int)link->type);
}
link = link->next;
}
@@ -11232,7 +11805,7 @@ rb_insns_name_array(void)
for (i = 0; i < VM_INSTRUCTION_SIZE; i++) {
rb_ary_push(ary, rb_fstring_cstr(insn_name(i)));
}
- return rb_obj_freeze(ary);
+ return rb_ary_freeze(ary);
}
static LABEL *
@@ -11567,6 +12140,7 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor,
rb_hash_aset(map, key, (VALUE)label | 1);
}
RB_GC_GUARD(op);
+ RB_OBJ_SET_SHAREABLE(rb_obj_hide(map)); // allow mutation while compiling
argv[j] = map;
RB_OBJ_WRITTEN(iseq, Qundef, map);
}
@@ -11681,7 +12255,7 @@ iseq_build_kw(rb_iseq_t *iseq, VALUE params, VALUE keywords)
rb_raise(rb_eTypeError, "keyword default has unsupported len %+"PRIsVALUE, key);
}
ids[i] = SYM2ID(sym);
- dvs[j] = default_val;
+ RB_OBJ_WRITE(iseq, &dvs[j], default_val);
}
keyword->table = ids;
@@ -11691,13 +12265,13 @@ iseq_build_kw(rb_iseq_t *iseq, VALUE params, VALUE keywords)
}
static void
-iseq_insn_each_object_mark_and_pin(VALUE obj, VALUE _)
+iseq_insn_each_object_mark_and_move(VALUE * obj, VALUE _)
{
- rb_gc_mark(obj);
+ rb_gc_mark_and_move(obj);
}
void
-rb_iseq_mark_and_pin_insn_storage(struct iseq_compile_data_storage *storage)
+rb_iseq_mark_and_move_insn_storage(struct iseq_compile_data_storage *storage)
{
INSN *iobj = 0;
size_t size = sizeof(INSN);
@@ -11722,7 +12296,7 @@ rb_iseq_mark_and_pin_insn_storage(struct iseq_compile_data_storage *storage)
iobj = (INSN *)&storage->buff[pos];
if (iobj->operands) {
- iseq_insn_each_markable_object(iobj, iseq_insn_each_object_mark_and_pin, (VALUE)0);
+ iseq_insn_each_markable_object(iobj, iseq_insn_each_object_mark_and_move, (VALUE)0);
}
pos += (int)size;
}
@@ -11913,7 +12487,7 @@ typedef uint32_t ibf_offset_t;
#define IBF_MAJOR_VERSION ISEQ_MAJOR_VERSION
#ifdef RUBY_DEVEL
-#define IBF_DEVEL_VERSION 4
+#define IBF_DEVEL_VERSION 5
#define IBF_MINOR_VERSION (ISEQ_MINOR_VERSION * 10000 + IBF_DEVEL_VERSION)
#else
#define IBF_MINOR_VERSION ISEQ_MINOR_VERSION
@@ -12072,8 +12646,13 @@ static ibf_offset_t
ibf_dump_write(struct ibf_dump *dump, const void *buff, unsigned long size)
{
ibf_offset_t pos = ibf_dump_pos(dump);
+#if SIZEOF_LONG > SIZEOF_INT
+ /* ensure the resulting dump does not exceed UINT_MAX */
+ if (size >= UINT_MAX || pos + size >= UINT_MAX) {
+ rb_raise(rb_eRuntimeError, "dump size exceeds");
+ }
+#endif
rb_str_cat(dump->current_buffer->str, (const char *)buff, size);
- /* TODO: overflow check */
return pos;
}
@@ -12403,6 +12982,9 @@ ibf_load_code(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t bytecod
struct rb_call_data *cd_entries = load_body->call_data;
int ic_index = 0;
+ load_body->iseq_encoded = code;
+ load_body->iseq_size = 0;
+
iseq_bits_t * mark_offset_bits;
iseq_bits_t tmp[1] = {0};
@@ -12446,7 +13028,7 @@ ibf_load_code(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t bytecod
v = rb_hash_dup(v); // hash dumped as frozen
RHASH_TBL_RAW(v)->type = &cdhash_type;
rb_hash_rehash(v); // hash function changed
- freeze_hide_obj(v);
+ RB_OBJ_SET_SHAREABLE(freeze_hide_obj(v));
// Overwrite the existing hash in the object list. This
// is to keep the object alive during load time.
@@ -12534,7 +13116,6 @@ ibf_load_code(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t bytecod
}
}
- load_body->iseq_encoded = code;
load_body->iseq_size = code_index;
if (ISEQ_MBITS_BUFLEN(load_body->iseq_size) == 1) {
@@ -12612,19 +13193,17 @@ ibf_load_param_keyword(const struct ibf_load *load, ibf_offset_t param_keyword_o
{
if (param_keyword_offset) {
struct rb_iseq_param_keyword *kw = IBF_R(param_keyword_offset, struct rb_iseq_param_keyword, 1);
- ID *ids = IBF_R(kw->table, ID, kw->num);
int dv_num = kw->num - kw->required_num;
- VALUE *dvs = IBF_R(kw->default_values, VALUE, dv_num);
- int i;
+ VALUE *dvs = dv_num ? IBF_R(kw->default_values, VALUE, dv_num) : NULL;
- for (i=0; i<kw->num; i++) {
- ids[i] = ibf_load_id(load, ids[i]);
- }
+ int i;
for (i=0; i<dv_num; i++) {
dvs[i] = ibf_load_object(load, dvs[i]);
}
- kw->table = ids;
+ // Will be set once the local table is loaded.
+ kw->table = NULL;
+
kw->default_values = dvs;
return kw;
}
@@ -12721,7 +13300,7 @@ ibf_dump_local_table(struct ibf_dump *dump, const rb_iseq_t *iseq)
return ibf_dump_write(dump, table, sizeof(ID) * size);
}
-static ID *
+static const ID *
ibf_load_local_table(const struct ibf_load *load, ibf_offset_t local_table_offset, int size)
{
if (size > 0) {
@@ -12731,7 +13310,14 @@ ibf_load_local_table(const struct ibf_load *load, ibf_offset_t local_table_offse
for (i=0; i<size; i++) {
table[i] = ibf_load_id(load, table[i]);
}
- return table;
+
+ if (size == 1 && table[0] == idERROR_INFO) {
+ xfree(table);
+ return rb_iseq_shared_exc_local_tbl;
+ }
+ else {
+ return table;
+ }
}
else {
return NULL;
@@ -12739,6 +13325,28 @@ ibf_load_local_table(const struct ibf_load *load, ibf_offset_t local_table_offse
}
static ibf_offset_t
+ibf_dump_lvar_states(struct ibf_dump *dump, const rb_iseq_t *iseq)
+{
+ const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
+ const int size = body->local_table_size;
+ IBF_W_ALIGN(enum lvar_state);
+ return ibf_dump_write(dump, body->lvar_states, sizeof(enum lvar_state) * (body->lvar_states ? size : 0));
+}
+
+static enum lvar_state *
+ibf_load_lvar_states(const struct ibf_load *load, ibf_offset_t lvar_states_offset, int size, const ID *local_table)
+{
+ if (local_table == rb_iseq_shared_exc_local_tbl ||
+ size <= 0) {
+ return NULL;
+ }
+ else {
+ enum lvar_state *states = IBF_R(lvar_states_offset, enum lvar_state, size);
+ return states;
+ }
+}
+
+static ibf_offset_t
ibf_dump_catch_table(struct ibf_dump *dump, const rb_iseq_t *iseq)
{
const struct iseq_catch_table *table = ISEQ_BODY(iseq)->catch_table;
@@ -12768,12 +13376,13 @@ ibf_dump_catch_table(struct ibf_dump *dump, const rb_iseq_t *iseq)
}
}
-static struct iseq_catch_table *
-ibf_load_catch_table(const struct ibf_load *load, ibf_offset_t catch_table_offset, unsigned int size)
+static void
+ibf_load_catch_table(const struct ibf_load *load, ibf_offset_t catch_table_offset, unsigned int size, const rb_iseq_t *parent_iseq)
{
if (size) {
- struct iseq_catch_table *table = ruby_xmalloc(iseq_catch_table_bytes(size));
+ struct iseq_catch_table *table = ruby_xcalloc(1, iseq_catch_table_bytes(size));
table->size = size;
+ ISEQ_BODY(parent_iseq)->catch_table = table;
ibf_offset_t reading_pos = catch_table_offset;
@@ -12786,12 +13395,12 @@ ibf_load_catch_table(const struct ibf_load *load, ibf_offset_t catch_table_offse
table->entries[i].cont = (unsigned int)ibf_load_small_value(load, &reading_pos);
table->entries[i].sp = (unsigned int)ibf_load_small_value(load, &reading_pos);
- table->entries[i].iseq = ibf_load_iseq(load, (const rb_iseq_t *)(VALUE)iseq_index);
+ rb_iseq_t *catch_iseq = (rb_iseq_t *)ibf_load_iseq(load, (const rb_iseq_t *)(VALUE)iseq_index);
+ RB_OBJ_WRITE(parent_iseq, UNALIGNED_MEMBER_PTR(&table->entries[i], iseq), catch_iseq);
}
- return table;
}
else {
- return NULL;
+ ISEQ_BODY(parent_iseq)->catch_table = NULL;
}
}
@@ -12862,6 +13471,14 @@ outer_variable_cmp(const void *a, const void *b, void *arg)
{
const struct outer_variable_pair *ap = (const struct outer_variable_pair *)a;
const struct outer_variable_pair *bp = (const struct outer_variable_pair *)b;
+
+ if (!ap->name) {
+ return -1;
+ }
+ else if (!bp->name) {
+ return 1;
+ }
+
return rb_str_cmp(ap->name, bp->name);
}
@@ -12902,6 +13519,11 @@ ibf_load_ci_entries(const struct ibf_load *load,
unsigned int ci_size,
struct rb_call_data **cd_ptr)
{
+ if (!ci_size) {
+ *cd_ptr = NULL;
+ return;
+ }
+
ibf_offset_t reading_pos = ci_entries_offset;
unsigned int i;
@@ -12997,6 +13619,7 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq)
ruby_xfree(positions);
const ibf_offset_t local_table_offset = ibf_dump_local_table(dump, iseq);
+ const ibf_offset_t lvar_states_offset = ibf_dump_lvar_states(dump, iseq);
const unsigned int catch_table_size = body->catch_table ? body->catch_table->size : 0;
const ibf_offset_t catch_table_offset = ibf_dump_catch_table(dump, iseq);
const int parent_iseq_index = ibf_dump_iseq(dump, ISEQ_BODY(iseq)->parent_iseq);
@@ -13028,7 +13651,8 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq)
(body->param.flags.ruby2_keywords << 9) |
(body->param.flags.anon_rest << 10) |
(body->param.flags.anon_kwrest << 11) |
- (body->param.flags.use_block << 12);
+ (body->param.flags.use_block << 12) |
+ (body->param.flags.forwardable << 13) ;
#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
# define IBF_BODY_OFFSET(x) (x)
@@ -13063,6 +13687,7 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq)
ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(insns_info_positions_offset));
ibf_dump_write_small_value(dump, body->insns_info.size);
ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(local_table_offset));
+ ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(lvar_states_offset));
ibf_dump_write_small_value(dump, catch_table_size);
ibf_dump_write_small_value(dump, IBF_BODY_OFFSET(catch_table_offset));
ibf_dump_write_small_value(dump, parent_iseq_index);
@@ -13174,6 +13799,7 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
const ibf_offset_t insns_info_positions_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
const unsigned int insns_info_size = (unsigned int)ibf_load_small_value(load, &reading_pos);
const ibf_offset_t local_table_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
+ const ibf_offset_t lvar_states_offset = (ibf_offset_t)IBF_BODY_OFFSET(ibf_load_small_value(load, &reading_pos));
const unsigned int catch_table_size = (unsigned int)ibf_load_small_value(load, &reading_pos);
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);
@@ -13245,6 +13871,7 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
load_body->param.flags.anon_rest = (param_flags >> 10) & 1;
load_body->param.flags.anon_kwrest = (param_flags >> 11) & 1;
load_body->param.flags.use_block = (param_flags >> 12) & 1;
+ load_body->param.flags.forwardable = (param_flags >> 13) & 1;
load_body->param.size = param_size;
load_body->param.lead_num = param_lead_num;
load_body->param.opt_num = param_opt_num;
@@ -13289,10 +13916,23 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
load_body->insns_info.body = ibf_load_insns_info_body(load, insns_info_body_offset, insns_info_size);
load_body->insns_info.positions = ibf_load_insns_info_positions(load, insns_info_positions_offset, insns_info_size);
load_body->local_table = ibf_load_local_table(load, local_table_offset, local_table_size);
- load_body->catch_table = ibf_load_catch_table(load, catch_table_offset, catch_table_size);
- load_body->parent_iseq = ibf_load_iseq(load, (const rb_iseq_t *)(VALUE)parent_iseq_index);
- load_body->local_iseq = ibf_load_iseq(load, (const rb_iseq_t *)(VALUE)local_iseq_index);
- load_body->mandatory_only_iseq = ibf_load_iseq(load, (const rb_iseq_t *)(VALUE)mandatory_only_iseq_index);
+ load_body->lvar_states = ibf_load_lvar_states(load, lvar_states_offset, local_table_size, load_body->local_table);
+ ibf_load_catch_table(load, catch_table_offset, catch_table_size, iseq);
+
+ const rb_iseq_t *parent_iseq = ibf_load_iseq(load, (const rb_iseq_t *)(VALUE)parent_iseq_index);
+ const rb_iseq_t *local_iseq = ibf_load_iseq(load, (const rb_iseq_t *)(VALUE)local_iseq_index);
+ const rb_iseq_t *mandatory_only_iseq = ibf_load_iseq(load, (const rb_iseq_t *)(VALUE)mandatory_only_iseq_index);
+
+ RB_OBJ_WRITE(iseq, &load_body->parent_iseq, parent_iseq);
+ RB_OBJ_WRITE(iseq, &load_body->local_iseq, local_iseq);
+ RB_OBJ_WRITE(iseq, &load_body->mandatory_only_iseq, mandatory_only_iseq);
+
+ // This must be done after the local table is loaded.
+ if (load_body->param.keyword != NULL) {
+ RUBY_ASSERT(load_body->local_table);
+ struct rb_iseq_param_keyword *keyword = (struct rb_iseq_param_keyword *) load_body->param.keyword;
+ keyword->table = &load_body->local_table[keyword->bits_start - keyword->num];
+ }
ibf_load_code(load, iseq, bytecode_offset, bytecode_size, iseq_size);
#if VM_INSN_INFO_TABLE_IMPL == 2
@@ -13359,8 +13999,6 @@ ibf_dump_iseq_list(struct ibf_dump *dump, struct ibf_header *header)
header->iseq_list_size = (unsigned int)size;
}
-#define IBF_OBJECT_INTERNAL FL_PROMOTED0
-
/*
* Binary format
* - ibf_object_header
@@ -13420,7 +14058,11 @@ struct ibf_object_symbol {
#define IBF_ALIGNED_OFFSET(align, offset) /* offset > 0 */ \
((((offset) - 1) / (align) + 1) * (align))
-#define IBF_OBJBODY(type, offset) (const type *)\
+/* No cast, since it's UB to create an unaligned pointer.
+ * Leave as void* for use with memcpy in those cases.
+ * We align the offset, but the buffer pointer is only VALUE aligned,
+ * so the returned pointer may be unaligned for `type` .*/
+#define IBF_OBJBODY(type, offset) \
ibf_load_check_offset(load, IBF_ALIGNED_OFFSET(RUBY_ALIGNOF(type), offset))
static const void *
@@ -13515,8 +14157,12 @@ ibf_dump_object_float(struct ibf_dump *dump, VALUE obj)
static VALUE
ibf_load_object_float(const struct ibf_load *load, const struct ibf_object_header *header, ibf_offset_t offset)
{
- const double *dblp = IBF_OBJBODY(double, offset);
- return DBL2NUM(*dblp);
+ double d;
+ /* Avoid unaligned VFP load on ARMv7; IBF payload may be unaligned (C99 6.3.2.3 p7). */
+ memcpy(&d, IBF_OBJBODY(double, offset), sizeof(d));
+ VALUE f = DBL2NUM(d);
+ if (!FLONUM_P(f)) RB_OBJ_SET_SHAREABLE(f);
+ return f;
}
static void
@@ -13587,7 +14233,7 @@ ibf_load_object_regexp(const struct ibf_load *load, const struct ibf_object_head
VALUE reg = rb_reg_compile(srcstr, (int)regexp.option, NULL, 0);
if (header->internal) rb_obj_hide(reg);
- if (header->frozen) rb_obj_freeze(reg);
+ if (header->frozen) RB_OBJ_SET_SHAREABLE(rb_obj_freeze(reg));
return reg;
}
@@ -13618,7 +14264,10 @@ ibf_load_object_array(const struct ibf_load *load, const struct ibf_object_heade
rb_ary_push(ary, ibf_load_object(load, index));
}
- if (header->frozen) rb_obj_freeze(ary);
+ if (header->frozen) {
+ rb_ary_freeze(ary);
+ rb_ractor_make_shareable(ary); // TODO: check elements
+ }
return ary;
}
@@ -13663,7 +14312,9 @@ ibf_load_object_hash(const struct ibf_load *load, const struct ibf_object_header
rb_hash_rehash(obj);
if (header->internal) rb_obj_hide(obj);
- if (header->frozen) rb_obj_freeze(obj);
+ if (header->frozen) {
+ RB_OBJ_SET_FROZEN_SHAREABLE(obj);
+ }
return obj;
}
@@ -13699,7 +14350,7 @@ ibf_load_object_struct(const struct ibf_load *load, const struct ibf_object_head
VALUE end = ibf_load_object(load, range->end);
VALUE obj = rb_range_new(beg, end, range->excl);
if (header->internal) rb_obj_hide(obj);
- if (header->frozen) rb_obj_freeze(obj);
+ if (header->frozen) RB_OBJ_SET_FROZEN_SHAREABLE(obj);
return obj;
}
@@ -13727,7 +14378,7 @@ ibf_load_object_bignum(const struct ibf_load *load, const struct ibf_object_head
big_unpack_flags |
(sign == 0 ? INTEGER_PACK_NEGATIVE : 0));
if (header->internal) rb_obj_hide(obj);
- if (header->frozen) rb_obj_freeze(obj);
+ if (header->frozen) RB_OBJ_SET_FROZEN_SHAREABLE(obj);
return obj;
}
@@ -13788,7 +14439,7 @@ ibf_load_object_complex_rational(const struct ibf_load *load, const struct ibf_o
rb_complex_new(a, b) : rb_rational_new(a, b);
if (header->internal) rb_obj_hide(obj);
- if (header->frozen) rb_obj_freeze(obj);
+ if (header->frozen) rb_ractor_make_shareable(rb_obj_freeze(obj));
return obj;
}
@@ -13901,7 +14552,7 @@ ibf_dump_object_object(struct ibf_dump *dump, VALUE obj)
else {
obj_header.internal = SPECIAL_CONST_P(obj) ? FALSE : (RBASIC_CLASS(obj) == 0) ? TRUE : FALSE;
obj_header.special_const = FALSE;
- obj_header.frozen = FL_TEST(obj, FL_FREEZE) ? TRUE : FALSE;
+ obj_header.frozen = OBJ_FROZEN(obj) ? TRUE : FALSE;
ibf_dump_object_object_header(dump, obj_header);
(*dump_object_functions[obj_header.type])(dump, obj);
}
@@ -14276,7 +14927,7 @@ ibf_load_setup(struct ibf_load *load, VALUE loader_obj, VALUE str)
str = rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str));
}
- ibf_load_setup_bytes(load, loader_obj, StringValuePtr(str), RSTRING_LEN(str));
+ ibf_load_setup_bytes(load, loader_obj, RSTRING_PTR(str), RSTRING_LEN(str));
RB_OBJ_WRITE(loader_obj, &load->str, str);
}
diff --git a/complex.c b/complex.c
index f562ed3161..85d724f273 100644
--- a/complex.c
+++ b/complex.c
@@ -799,9 +799,9 @@ rb_complex_imag(VALUE self)
/*
* call-seq:
- * -complex -> new_complex
+ * -self -> complex
*
- * Returns the negation of +self+, which is the negation of each of its parts:
+ * Returns +self+, negated, which is the negation of each of its parts:
*
* -Complex.rect(1, 2) # => (-1-2i)
* -Complex.rect(-1, -2) # => (1+2i)
@@ -816,17 +816,26 @@ rb_complex_uminus(VALUE self)
}
/*
- * call-seq:
- * complex + numeric -> new_complex
+ * call-seq:
+ * self + other -> numeric
+ *
+ * Returns the sum of +self+ and +other+:
+ *
+ * Complex(1, 2) + 0 # => (1+2i)
+ * Complex(1, 2) + 1 # => (2+2i)
+ * Complex(1, 2) + -1 # => (0+2i)
+ *
+ * Complex(1, 2) + 1.0 # => (2.0+2i)
*
- * Returns the sum of +self+ and +numeric+:
+ * Complex(1, 2) + Complex(2, 1) # => (3+3i)
+ * Complex(1, 2) + Complex(2.0, 1.0) # => (3.0+3.0i)
*
- * Complex.rect(2, 3) + Complex.rect(2, 3) # => (4+6i)
- * Complex.rect(900) + Complex.rect(1) # => (901+0i)
- * Complex.rect(-2, 9) + Complex.rect(-9, 2) # => (-11+11i)
- * Complex.rect(9, 8) + 4 # => (13+8i)
- * Complex.rect(20, 9) + 9.8 # => (29.8+9i)
+ * Complex(1, 2) + Rational(1, 1) # => ((2/1)+2i)
+ * Complex(1, 2) + Rational(1, 2) # => ((3/2)+2i)
*
+ * For a computation involving Floats, the result may be inexact (see Float#+):
+ *
+ * Complex(1, 2) + 3.14 # => (4.140000000000001+2i)
*/
VALUE
rb_complex_plus(VALUE self, VALUE other)
@@ -852,9 +861,9 @@ rb_complex_plus(VALUE self, VALUE other)
/*
* call-seq:
- * complex - numeric -> new_complex
+ * self - other -> complex
*
- * Returns the difference of +self+ and +numeric+:
+ * Returns the difference of +self+ and +other+:
*
* Complex.rect(2, 3) - Complex.rect(2, 3) # => (0+0i)
* Complex.rect(900) - Complex.rect(1) # => (899+0i)
@@ -913,15 +922,16 @@ comp_mul(VALUE areal, VALUE aimag, VALUE breal, VALUE bimag, VALUE *real, VALUE
/*
* call-seq:
- * complex * numeric -> new_complex
+ * self * other -> numeric
*
- * Returns the product of +self+ and +numeric+:
+ * Returns the numeric product of +self+ and +other+:
*
+ * Complex.rect(9, 8) * 4 # => (36+32i)
+ * Complex.rect(20, 9) * 9.8 # => (196.0+88.2i)
* Complex.rect(2, 3) * Complex.rect(2, 3) # => (-5+12i)
* Complex.rect(900) * Complex.rect(1) # => (900+0i)
* Complex.rect(-2, 9) * Complex.rect(-9, 2) # => (0-85i)
- * Complex.rect(9, 8) * 4 # => (36+32i)
- * Complex.rect(20, 9) * 9.8 # => (196.0+88.2i)
+ * Complex.rect(9, 8) * Rational(2, 3) # => ((6/1)+(16/3)*i)
*
*/
VALUE
@@ -989,9 +999,9 @@ f_divide(VALUE self, VALUE other,
/*
* call-seq:
- * complex / numeric -> new_complex
+ * self / other -> complex
*
- * Returns the quotient of +self+ and +numeric+:
+ * Returns the quotient of +self+ and +other+:
*
* Complex.rect(2, 3) / Complex.rect(2, 3) # => (1+0i)
* Complex.rect(900) / Complex.rect(1) # => (900+0i)
@@ -1065,7 +1075,8 @@ complex_pow_for_special_angle(VALUE self, VALUE other)
else if (f_eqeq_p(dat->real, f_negate(dat->imag))) {
x = dat->imag;
dir = 3;
- } else {
+ }
+ else {
dir = 0;
}
@@ -1111,9 +1122,9 @@ complex_pow_for_special_angle(VALUE self, VALUE other)
/*
* call-seq:
- * complex ** numeric -> new_complex
+ * self ** exponent -> complex
*
- * Returns +self+ raised to power +numeric+:
+ * Returns +self+ raised to the power +exponent+:
*
* Complex.rect(0, 1) ** 2 # => (-1+0i)
* Complex.rect(-8) ** Rational(1, 3) # => (1.0000000000000002+1.7320508075688772i)
@@ -1215,10 +1226,10 @@ rb_complex_pow(VALUE self, VALUE other)
/*
* call-seq:
- * complex == object -> true or false
+ * self == other -> true or false
*
- * Returns +true+ if <tt>self.real == object.real</tt>
- * and <tt>self.imag == object.imag</tt>:
+ * Returns whether both <tt>self.real == other.real</tt>
+ * and <tt>self.imag == other.imag</tt>:
*
* Complex.rect(2, 3) == Complex.rect(2.0, 3.0) # => true
*
@@ -1249,14 +1260,16 @@ nucomp_real_p(VALUE self)
/*
* call-seq:
- * complex <=> object -> -1, 0, 1, or nil
+ * self <=> other -> -1, 0, 1, or nil
+ *
+ * Compares +self+ and +other+.
*
* Returns:
*
- * - <tt>self.real <=> object.real</tt> if both of the following are true:
+ * - <tt>self.real <=> other.real</tt> if both of the following are true:
*
* - <tt>self.imag == 0</tt>.
- * - <tt>object.imag == 0</tt>. # Always true if object is numeric but not complex.
+ * - <tt>other.imag == 0</tt> (always true if +other+ is numeric but not complex).
*
* - +nil+ otherwise.
*
@@ -1269,6 +1282,8 @@ nucomp_real_p(VALUE self)
* Complex.rect(1) <=> Complex.rect(1, 1) # => nil # object.imag not zero.
* Complex.rect(1) <=> 'Foo' # => nil # object.imag not defined.
*
+ * \Class \Complex includes module Comparable,
+ * each of whose methods uses Complex#<=> for comparison.
*/
static VALUE
nucomp_cmp(VALUE self, VALUE other)
@@ -1593,16 +1608,15 @@ f_tpositive_p(VALUE x)
}
static VALUE
-f_format(VALUE self, VALUE (*func)(VALUE))
+f_format(VALUE self, VALUE s, VALUE (*func)(VALUE))
{
- VALUE s;
int impos;
get_dat1(self);
impos = f_tpositive_p(dat->imag);
- s = (*func)(dat->real);
+ rb_str_concat(s, (*func)(dat->real));
rb_str_cat2(s, !impos ? "-" : "+");
rb_str_concat(s, (*func)(f_abs(dat->imag)));
@@ -1629,7 +1643,7 @@ f_format(VALUE self, VALUE (*func)(VALUE))
static VALUE
nucomp_to_s(VALUE self)
{
- return f_format(self, rb_String);
+ return f_format(self, rb_usascii_str_new2(""), rb_String);
}
/*
@@ -1651,7 +1665,7 @@ nucomp_inspect(VALUE self)
VALUE s;
s = rb_usascii_str_new2("(");
- rb_str_concat(s, f_format(self, rb_inspect));
+ f_format(self, s, rb_inspect);
rb_str_cat2(s, ")");
return s;
@@ -1765,12 +1779,6 @@ rb_complex_new_polar(VALUE x, VALUE y)
}
VALUE
-rb_complex_polar(VALUE x, VALUE y)
-{
- return rb_complex_new_polar(x, y);
-}
-
-VALUE
rb_Complex(VALUE x, VALUE y)
{
VALUE a[2];
@@ -1795,7 +1803,7 @@ rb_dbl_complex_new(double real, double imag)
* Complex.rect(1, Rational(0, 1)).to_i # => 1
*
* Raises RangeError if <tt>self.imag</tt> is not exactly zero
- * (either <tt>Integer(0)</tt> or <tt>Rational(0, _n_)</tt>).
+ * (either <tt>Integer(0)</tt> or <tt>Rational(0, n)</tt>).
*/
static VALUE
nucomp_to_i(VALUE self)
@@ -1819,7 +1827,7 @@ nucomp_to_i(VALUE self)
* Complex.rect(1, Rational(0, 1)).to_f # => 1.0
*
* Raises RangeError if <tt>self.imag</tt> is not exactly zero
- * (either <tt>Integer(0)</tt> or <tt>Rational(0, _n_)</tt>).
+ * (either <tt>Integer(0)</tt> or <tt>Rational(0, n)</tt>).
*/
static VALUE
nucomp_to_f(VALUE self)
@@ -1844,7 +1852,7 @@ nucomp_to_f(VALUE self)
* Complex.rect(1, 0.0).to_r # => (1/1)
*
* Raises RangeError if <tt>self.imag</tt> is not exactly zero
- * (either <tt>Integer(0)</tt> or <tt>Rational(0, _n_)</tt>)
+ * (either <tt>Integer(0)</tt> or <tt>Rational(0, n)</tt>)
* and <tt>self.imag.to_r</tt> is not exactly zero.
*
* Related: Complex#rationalize.
@@ -1927,21 +1935,6 @@ nucomp_to_c(VALUE self)
/*
* call-seq:
- * to_c -> (0+0i)
- *
- * Returns zero as a Complex:
- *
- * nil.to_c # => (0+0i)
- *
- */
-static VALUE
-nilclass_to_c(VALUE self)
-{
- return rb_complex_new1(INT2FIX(0));
-}
-
-/*
- * call-seq:
* to_c -> complex
*
* Returns +self+ as a Complex object.
@@ -2244,28 +2237,156 @@ string_to_c_strict(VALUE self, int raise)
* call-seq:
* to_c -> complex
*
- * Returns +self+ interpreted as a Complex object;
- * leading whitespace and trailing garbage are ignored:
- *
- * '9'.to_c # => (9+0i)
- * '2.5'.to_c # => (2.5+0i)
- * '2.5/1'.to_c # => ((5/2)+0i)
- * '-3/2'.to_c # => ((-3/2)+0i)
- * '-i'.to_c # => (0-1i)
- * '45i'.to_c # => (0+45i)
- * '3-4i'.to_c # => (3-4i)
- * '-4e2-4e-2i'.to_c # => (-400.0-0.04i)
- * '-0.0-0.0i'.to_c # => (-0.0-0.0i)
- * '1/2+3/4i'.to_c # => ((1/2)+(3/4)*i)
- * '1.0@0'.to_c # => (1+0.0i)
+ * Returns a Complex object:
+ * parses the leading substring of +self+
+ * to extract two numeric values that become the coordinates of the complex object.
+ *
+ * The substring is interpreted as containing
+ * either rectangular coordinates (real and imaginary parts)
+ * or polar coordinates (magnitude and angle parts),
+ * depending on an included or implied "separator" character:
+ *
+ * - <tt>'+'</tt>, <tt>'-'</tt>, or no separator: rectangular coordinates.
+ * - <tt>'@'</tt>: polar coordinates.
+ *
+ * <b>In Brief</b>
+ *
+ * In these examples, we use method Complex#rect to display rectangular coordinates,
+ * and method Complex#polar to display polar coordinates.
+ *
+ * # Rectangular coordinates.
+ *
+ * # Real-only: no separator; imaginary part is zero.
+ * '9'.to_c.rect # => [9, 0] # Integer.
+ * '-9'.to_c.rect # => [-9, 0] # Integer (negative).
+ * '2.5'.to_c.rect # => [2.5, 0] # Float.
+ * '1.23e-14'.to_c.rect # => [1.23e-14, 0] # Float with exponent.
+ * '2.5/1'.to_c.rect # => [(5/2), 0] # Rational.
+ *
+ * # Some things are ignored.
+ * 'foo1'.to_c.rect # => [0, 0] # Unparsed entire substring.
+ * '1foo'.to_c.rect # => [1, 0] # Unparsed trailing substring.
+ * ' 1 '.to_c.rect # => [1, 0] # Leading and trailing whitespace.
+ * *
+ * # Imaginary only: trailing 'i' required; real part is zero.
+ * '9i'.to_c.rect # => [0, 9]
+ * '-9i'.to_c.rect # => [0, -9]
+ * '2.5i'.to_c.rect # => [0, 2.5]
+ * '1.23e-14i'.to_c.rect # => [0, 1.23e-14]
+ * '2.5/1i'.to_c.rect # => [0, (5/2)]
+ *
+ * # Real and imaginary; '+' or '-' separator; trailing 'i' required.
+ * '2+3i'.to_c.rect # => [2, 3]
+ * '-2-3i'.to_c.rect # => [-2, -3]
+ * '2.5+3i'.to_c.rect # => [2.5, 3]
+ * '2.5+3/2i'.to_c.rect # => [2.5, (3/2)]
+ *
+ * # Polar coordinates; '@' separator; magnitude required.
+ * '1.0@0'.to_c.polar # => [1.0, 0.0]
+ * '1.0@'.to_c.polar # => [1.0, 0.0]
+ * "1.0@#{Math::PI}".to_c.polar # => [1.0, 3.141592653589793]
+ * "1.0@#{Math::PI/2}".to_c.polar # => [1.0, 1.5707963267948966]
+ *
+ * <b>Parsed Values</b>
+ *
+ * The parsing may be thought of as searching for numeric literals
+ * embedded in the substring.
+ *
+ * This section shows how the method parses numeric values from leading substrings.
+ * The examples show real-only or imaginary-only parsing;
+ * the parsing is the same for each part.
+ *
+ * '1foo'.to_c # => (1+0i) # Ignores trailing unparsed characters.
+ * ' 1 '.to_c # => (1+0i) # Ignores leading and trailing whitespace.
+ * 'x1'.to_c # => (0+0i) # Finds no leading numeric.
+ *
+ * # Integer literal embedded in the substring.
+ * '1'.to_c # => (1+0i)
+ * '-1'.to_c # => (-1+0i)
+ * '1i'.to_c # => (0+1i)
+ *
+ * # Integer literals that don't work.
+ * '0b100'.to_c # => (0+0i) # Not parsed as binary.
+ * '0o100'.to_c # => (0+0i) # Not parsed as octal.
+ * '0d100'.to_c # => (0+0i) # Not parsed as decimal.
+ * '0x100'.to_c # => (0+0i) # Not parsed as hexadecimal.
+ * '010'.to_c # => (10+0i) # Not parsed as octal.
+ *
+ * # Float literals:
+ * '3.14'.to_c # => (3.14+0i)
+ * '3.14i'.to_c # => (0+3.14i)
+ * '1.23e4'.to_c # => (12300.0+0i)
+ * '1.23e+4'.to_c # => (12300.0+0i)
+ * '1.23e-4'.to_c # => (0.000123+0i)
+ *
+ * # Rational literals:
+ * '1/2'.to_c # => ((1/2)+0i)
+ * '-1/2'.to_c # => ((-1/2)+0i)
+ * '1/2r'.to_c # => ((1/2)+0i)
+ * '-1/2r'.to_c # => ((-1/2)+0i)
+ *
+ * <b>Rectangular Coordinates</b>
+ *
+ * With separator <tt>'+'</tt> or <tt>'-'</tt>,
+ * or with no separator,
+ * interprets the values as rectangular coordinates: real and imaginary.
+ *
+ * With no separator, assigns a single value to either the real or the imaginary part:
+ *
+ * ''.to_c # => (0+0i) # Defaults to zero.
+ * '1'.to_c # => (1+0i) # Real (no trailing 'i').
+ * '1i'.to_c # => (0+1i) # Imaginary (trailing 'i').
+ * 'i'.to_c # => (0+1i) # Special case (imaginary 1).
+ *
+ * With separator <tt>'+'</tt>, both parts positive (or zero):
+ *
+ * # Without trailing 'i'.
+ * '+'.to_c # => (0+0i) # No values: defaults to zero.
+ * '+1'.to_c # => (1+0i) # Value after '+': real only.
+ * '1+'.to_c # => (1+0i) # Value before '+': real only.
+ * '2+1'.to_c # => (2+0i) # Values before and after '+': real and imaginary.
+ * # With trailing 'i'.
+ * '+1i'.to_c # => (0+1i) # Value after '+': imaginary only.
+ * '2+i'.to_c # => (2+1i) # Value before '+': real and imaginary 1.
+ * '2+1i'.to_c # => (2+1i) # Values before and after '+': real and imaginary.
+ *
+ * With separator <tt>'-'</tt>, negative imaginary part:
+ *
+ * # Without trailing 'i'.
+ * '-'.to_c # => (0+0i) # No values: defaults to zero.
+ * '-1'.to_c # => (-1+0i) # Value after '-': negative real, zero imaginary.
+ * '1-'.to_c # => (1+0i) # Value before '-': positive real, zero imaginary.
+ * '2-1'.to_c # => (2+0i) # Values before and after '-': positive real, zero imaginary.
+ * # With trailing 'i'.
+ * '-1i'.to_c # => (0-1i) # Value after '-': negative real, zero imaginary.
+ * '2-i'.to_c # => (2-1i) # Value before '-': positive real, negative imaginary.
+ * '2-1i'.to_c # => (2-1i) # Values before and after '-': positive real, negative imaginary.
+ *
+ * Note that the suffixed character <tt>'i'</tt>
+ * may instead be one of <tt>'I'</tt>, <tt>'j'</tt>, or <tt>'J'</tt>,
+ * with the same effect.
+ *
+ * <b>Polar Coordinates</b>
+ *
+ * With separator <tt>'@'</tt>)
+ * interprets the values as polar coordinates: magnitude and angle.
+ *
+ * '2@'.to_c.polar # => [2, 0.0] # Value before '@': magnitude only.
+ * # Values before and after '@': magnitude and angle.
+ * '2@1'.to_c.polar # => [2.0, 1.0]
* "1.0@#{Math::PI/2}".to_c # => (0.0+1i)
* "1.0@#{Math::PI}".to_c # => (-1+0.0i)
+ * # Magnitude not given: defaults to zero.
+ * '@'.to_c.polar # => [0, 0.0]
+ * '@1'.to_c.polar # => [0, 0.0]
*
- * Returns \Complex zero if the string cannot be converted:
+ * '1.0@0'.to_c # => (1+0.0i)
*
- * 'ruby'.to_c # => (0+0i)
+ * Note that in all cases, the suffixed character <tt>'i'</tt>
+ * may instead be one of <tt>'I'</tt>, <tt>'j'</tt>, <tt>'J'</tt>,
+ * with the same effect.
*
- * See Kernel#Complex.
+ * See {Converting to Non-String}[rdoc-ref:String@Converting+to+Non--5CString].
*/
static VALUE
string_to_c(VALUE self)
@@ -2474,10 +2595,10 @@ float_arg(VALUE self)
*
* You can create a \Complex object from rectangular coordinates with:
*
- * - A {complex literal}[rdoc-ref:doc/syntax/literals.rdoc@Complex+Literals].
- * - \Method Complex.rect.
- * - \Method Kernel#Complex, either with numeric arguments or with certain string arguments.
- * - \Method String#to_c, for certain strings.
+ * - A {complex literal}[rdoc-ref:syntax/literals.rdoc@Complex+Literals].
+ * - Method Complex.rect.
+ * - Method Kernel#Complex, either with numeric arguments or with certain string arguments.
+ * - Method String#to_c, for certain strings.
*
* Note that each of the stored parts may be a an instance one of the classes
* Complex, Float, Integer, or Rational;
@@ -2503,9 +2624,9 @@ float_arg(VALUE self)
*
* You can create a \Complex object from polar coordinates with:
*
- * - \Method Complex.polar.
- * - \Method Kernel#Complex, with certain string arguments.
- * - \Method String#to_c, for certain strings.
+ * - Method Complex.polar.
+ * - Method Kernel#Complex, with certain string arguments.
+ * - Method String#to_c, for certain strings.
*
* Note that each of the stored parts may be a an instance one of the classes
* Complex, Float, Integer, or Rational;
@@ -2523,7 +2644,7 @@ float_arg(VALUE self)
*
* First, what's elsewhere:
*
- * - \Class \Complex inherits (directly or indirectly)
+ * - Class \Complex inherits (directly or indirectly)
* from classes {Numeric}[rdoc-ref:Numeric@What-27s+Here]
* and {Object}[rdoc-ref:Object@What-27s+Here].
* - Includes (indirectly) module {Comparable}[rdoc-ref:Comparable@What-27s+Here].
@@ -2589,7 +2710,7 @@ float_arg(VALUE self)
* - #as_json: Returns a serialized hash constructed from +self+.
* - #to_json: Returns a JSON string representing +self+.
*
- * These methods are provided by the {JSON gem}[https://github.com/flori/json]. To make these methods available:
+ * These methods are provided by the {JSON gem}[https://github.com/ruby/json]. To make these methods available:
*
* require 'json/add/complex'
*
@@ -2693,7 +2814,6 @@ Init_Complex(void)
rb_define_method(rb_cComplex, "to_r", nucomp_to_r, 0);
rb_define_method(rb_cComplex, "rationalize", nucomp_rationalize, -1);
rb_define_method(rb_cComplex, "to_c", nucomp_to_c, 0);
- rb_define_method(rb_cNilClass, "to_c", nilclass_to_c, 0);
rb_define_method(rb_cNumeric, "to_c", numeric_to_c, 0);
rb_define_method(rb_cString, "to_c", string_to_c, 0);
diff --git a/concurrent_set.c b/concurrent_set.c
new file mode 100644
index 0000000000..234b6408b6
--- /dev/null
+++ b/concurrent_set.c
@@ -0,0 +1,513 @@
+#include "internal.h"
+#include "internal/gc.h"
+#include "internal/concurrent_set.h"
+#include "ruby/atomic.h"
+#include "vm_sync.h"
+
+#define CONCURRENT_SET_CONTINUATION_BIT ((VALUE)1 << (sizeof(VALUE) * CHAR_BIT - 1))
+#define CONCURRENT_SET_HASH_MASK (~CONCURRENT_SET_CONTINUATION_BIT)
+
+enum concurrent_set_special_values {
+ CONCURRENT_SET_EMPTY,
+ CONCURRENT_SET_DELETED,
+ CONCURRENT_SET_MOVED,
+ CONCURRENT_SET_SPECIAL_VALUE_COUNT
+};
+
+struct concurrent_set_entry {
+ VALUE hash;
+ VALUE key;
+};
+
+struct concurrent_set {
+ rb_atomic_t size;
+ unsigned int capacity;
+ unsigned int deleted_entries;
+ const struct rb_concurrent_set_funcs *funcs;
+ struct concurrent_set_entry *entries;
+};
+
+static void
+concurrent_set_mark_continuation(struct concurrent_set_entry *entry, VALUE curr_hash_and_flags)
+{
+ if (curr_hash_and_flags & CONCURRENT_SET_CONTINUATION_BIT) return;
+
+ RUBY_ASSERT((curr_hash_and_flags & CONCURRENT_SET_HASH_MASK) != 0);
+
+ VALUE new_hash = curr_hash_and_flags | CONCURRENT_SET_CONTINUATION_BIT;
+ VALUE prev_hash = rbimpl_atomic_value_cas(&entry->hash, curr_hash_and_flags, new_hash, RBIMPL_ATOMIC_RELEASE, RBIMPL_ATOMIC_RELAXED);
+
+ // At the moment we only expect to be racing concurrently against another
+ // thread also setting the continuation bit.
+ // In the future if deletion is concurrent this will need adjusting
+ RUBY_ASSERT(prev_hash == curr_hash_and_flags || prev_hash == new_hash);
+ (void)prev_hash;
+}
+
+static VALUE
+concurrent_set_hash(const struct concurrent_set *set, VALUE key)
+{
+ VALUE hash = set->funcs->hash(key);
+ hash &= CONCURRENT_SET_HASH_MASK;
+ if (hash == 0) {
+ hash ^= CONCURRENT_SET_HASH_MASK;
+ }
+ RUBY_ASSERT(hash != 0);
+ RUBY_ASSERT(!(hash & CONCURRENT_SET_CONTINUATION_BIT));
+ return hash;
+}
+
+static void
+concurrent_set_free(void *ptr)
+{
+ struct concurrent_set *set = ptr;
+ xfree(set->entries);
+}
+
+static size_t
+concurrent_set_size(const void *ptr)
+{
+ const struct concurrent_set *set = ptr;
+ return sizeof(struct concurrent_set) +
+ (set->capacity * sizeof(struct concurrent_set_entry));
+}
+
+/* Hack: Though it would be trivial, we're intentionally avoiding WB-protecting
+ * this object. This prevents the object from aging and ensures it can always be
+ * collected in a minor GC.
+ * Longer term this deserves a better way to reclaim memory promptly.
+ */
+static void
+concurrent_set_mark(void *ptr)
+{
+ (void)ptr;
+}
+
+static const rb_data_type_t concurrent_set_type = {
+ .wrap_struct_name = "VM/concurrent_set",
+ .function = {
+ .dmark = concurrent_set_mark,
+ .dfree = concurrent_set_free,
+ .dsize = concurrent_set_size,
+ },
+ /* Hack: NOT WB_PROTECTED on purpose (see above) */
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_EMBEDDABLE
+};
+
+VALUE
+rb_concurrent_set_new(const struct rb_concurrent_set_funcs *funcs, int capacity)
+{
+ struct concurrent_set *set;
+ VALUE obj = TypedData_Make_Struct(0, struct concurrent_set, &concurrent_set_type, set);
+ set->funcs = funcs;
+ set->entries = ZALLOC_N(struct concurrent_set_entry, capacity);
+ set->capacity = capacity;
+ return obj;
+}
+
+rb_atomic_t
+rb_concurrent_set_size(VALUE set_obj)
+{
+ struct concurrent_set *set = RTYPEDDATA_GET_DATA(set_obj);
+
+ return RUBY_ATOMIC_LOAD(set->size);
+}
+
+struct concurrent_set_probe {
+ int idx;
+ int d;
+ int mask;
+};
+
+static int
+concurrent_set_probe_start(struct concurrent_set_probe *probe, struct concurrent_set *set, VALUE hash)
+{
+ RUBY_ASSERT((set->capacity & (set->capacity - 1)) == 0);
+ probe->d = 0;
+ probe->mask = set->capacity - 1;
+ probe->idx = hash & probe->mask;
+ return probe->idx;
+}
+
+static int
+concurrent_set_probe_next(struct concurrent_set_probe *probe)
+{
+ probe->d++;
+ probe->idx = (probe->idx + probe->d) & probe->mask;
+ return probe->idx;
+}
+
+static void
+concurrent_set_try_resize_without_locking(VALUE old_set_obj, VALUE *set_obj_ptr)
+{
+ // Check if another thread has already resized.
+ if (rbimpl_atomic_value_load(set_obj_ptr, RBIMPL_ATOMIC_ACQUIRE) != old_set_obj) {
+ return;
+ }
+
+ struct concurrent_set *old_set = RTYPEDDATA_GET_DATA(old_set_obj);
+
+ // This may overcount by up to the number of threads concurrently attempting to insert
+ // GC may also happen between now and the set being rebuilt
+ int expected_size = rbimpl_atomic_load(&old_set->size, RBIMPL_ATOMIC_RELAXED) - old_set->deleted_entries;
+
+ // NOTE: new capacity must make sense with load factor, don't change one without checking the other.
+ struct concurrent_set_entry *old_entries = old_set->entries;
+ int old_capacity = old_set->capacity;
+ int new_capacity = old_capacity * 2;
+ if (new_capacity > expected_size * 8) {
+ new_capacity = old_capacity / 2;
+ }
+ else if (new_capacity > expected_size * 4) {
+ new_capacity = old_capacity;
+ }
+
+ // May cause GC and therefore deletes, so must happen first.
+ VALUE new_set_obj = rb_concurrent_set_new(old_set->funcs, new_capacity);
+ struct concurrent_set *new_set = RTYPEDDATA_GET_DATA(new_set_obj);
+
+ for (int i = 0; i < old_capacity; i++) {
+ struct concurrent_set_entry *old_entry = &old_entries[i];
+ VALUE key = rbimpl_atomic_value_exchange(&old_entry->key, CONCURRENT_SET_MOVED, RBIMPL_ATOMIC_ACQUIRE);
+ RUBY_ASSERT(key != CONCURRENT_SET_MOVED);
+
+ if (key < CONCURRENT_SET_SPECIAL_VALUE_COUNT) continue;
+ if (!RB_SPECIAL_CONST_P(key) && rb_objspace_garbage_object_p(key)) continue;
+
+ VALUE hash = rbimpl_atomic_value_load(&old_entry->hash, RBIMPL_ATOMIC_RELAXED) & CONCURRENT_SET_HASH_MASK;
+ RUBY_ASSERT(hash != 0);
+ RUBY_ASSERT(hash == concurrent_set_hash(old_set, key));
+
+ // Insert key into new_set.
+ struct concurrent_set_probe probe;
+ int idx = concurrent_set_probe_start(&probe, new_set, hash);
+
+ while (true) {
+ struct concurrent_set_entry *entry = &new_set->entries[idx];
+
+ if (entry->hash == CONCURRENT_SET_EMPTY) {
+ RUBY_ASSERT(entry->key == CONCURRENT_SET_EMPTY);
+
+ new_set->size++;
+ RUBY_ASSERT(new_set->size <= new_set->capacity / 2);
+
+ entry->key = key;
+ entry->hash = hash;
+ break;
+ }
+
+ RUBY_ASSERT(entry->key >= CONCURRENT_SET_SPECIAL_VALUE_COUNT);
+ entry->hash |= CONCURRENT_SET_CONTINUATION_BIT;
+ idx = concurrent_set_probe_next(&probe);
+ }
+ }
+
+ rbimpl_atomic_value_store(set_obj_ptr, new_set_obj, RBIMPL_ATOMIC_RELEASE);
+
+ RB_GC_GUARD(old_set_obj);
+}
+
+static void
+concurrent_set_try_resize(VALUE old_set_obj, VALUE *set_obj_ptr)
+{
+ RB_VM_LOCKING() {
+ concurrent_set_try_resize_without_locking(old_set_obj, set_obj_ptr);
+ }
+}
+
+VALUE
+rb_concurrent_set_find(VALUE *set_obj_ptr, VALUE key)
+{
+ RUBY_ASSERT(key >= CONCURRENT_SET_SPECIAL_VALUE_COUNT);
+
+ VALUE set_obj;
+ VALUE hash = 0;
+ struct concurrent_set *set;
+ struct concurrent_set_probe probe;
+ int idx;
+
+ retry:
+ set_obj = rbimpl_atomic_value_load(set_obj_ptr, RBIMPL_ATOMIC_ACQUIRE);
+ RUBY_ASSERT(set_obj);
+ set = RTYPEDDATA_GET_DATA(set_obj);
+
+ if (hash == 0) {
+ // We don't need to recompute the hash on every retry because it should
+ // never change.
+ hash = concurrent_set_hash(set, key);
+ }
+ RUBY_ASSERT(hash == concurrent_set_hash(set, key));
+
+ idx = concurrent_set_probe_start(&probe, set, hash);
+
+ while (true) {
+ struct concurrent_set_entry *entry = &set->entries[idx];
+ VALUE curr_hash_and_flags = rbimpl_atomic_value_load(&entry->hash, RBIMPL_ATOMIC_ACQUIRE);
+ VALUE curr_hash = curr_hash_and_flags & CONCURRENT_SET_HASH_MASK;
+ bool continuation = curr_hash_and_flags & CONCURRENT_SET_CONTINUATION_BIT;
+
+ if (curr_hash_and_flags == CONCURRENT_SET_EMPTY) {
+ return 0;
+ }
+
+ if (curr_hash != hash) {
+ if (!continuation) {
+ return 0;
+ }
+ idx = concurrent_set_probe_next(&probe);
+ continue;
+ }
+
+ VALUE curr_key = rbimpl_atomic_value_load(&entry->key, RBIMPL_ATOMIC_ACQUIRE);
+
+ switch (curr_key) {
+ case CONCURRENT_SET_EMPTY:
+ // In-progress insert: hash written but key not yet
+ break;
+ case CONCURRENT_SET_DELETED:
+ break;
+ case CONCURRENT_SET_MOVED:
+ // Wait
+ RB_VM_LOCKING();
+
+ goto retry;
+ default: {
+ if (UNLIKELY(!RB_SPECIAL_CONST_P(curr_key) && rb_objspace_garbage_object_p(curr_key))) {
+ // This is a weakref set, so after marking but before sweeping is complete we may find a matching garbage object.
+ // Skip it and let the GC pass clean it up
+ break;
+ }
+
+ if (set->funcs->cmp(key, curr_key)) {
+ // We've found a match.
+ RB_GC_GUARD(set_obj);
+ return curr_key;
+ }
+
+ if (!continuation) {
+ return 0;
+ }
+
+ break;
+ }
+ }
+
+ idx = concurrent_set_probe_next(&probe);
+ }
+}
+
+VALUE
+rb_concurrent_set_find_or_insert(VALUE *set_obj_ptr, VALUE key, void *data)
+{
+ RUBY_ASSERT(key >= CONCURRENT_SET_SPECIAL_VALUE_COUNT);
+
+ // First attempt to find
+ {
+ VALUE result = rb_concurrent_set_find(set_obj_ptr, key);
+ if (result) return result;
+ }
+
+ // First time we need to call create, and store the hash
+ VALUE set_obj = rbimpl_atomic_value_load(set_obj_ptr, RBIMPL_ATOMIC_ACQUIRE);
+ RUBY_ASSERT(set_obj);
+
+ struct concurrent_set *set = RTYPEDDATA_GET_DATA(set_obj);
+ key = set->funcs->create(key, data);
+ VALUE hash = concurrent_set_hash(set, key);
+
+ struct concurrent_set_probe probe;
+ int idx;
+
+ goto start_search;
+
+retry:
+ // On retries we only need to load the hash object
+ set_obj = rbimpl_atomic_value_load(set_obj_ptr, RBIMPL_ATOMIC_ACQUIRE);
+ RUBY_ASSERT(set_obj);
+ set = RTYPEDDATA_GET_DATA(set_obj);
+
+ RUBY_ASSERT(hash == concurrent_set_hash(set, key));
+
+start_search:
+ idx = concurrent_set_probe_start(&probe, set, hash);
+
+ while (true) {
+ struct concurrent_set_entry *entry = &set->entries[idx];
+ VALUE curr_hash_and_flags = rbimpl_atomic_value_load(&entry->hash, RBIMPL_ATOMIC_ACQUIRE);
+ VALUE curr_hash = curr_hash_and_flags & CONCURRENT_SET_HASH_MASK;
+ bool continuation = curr_hash_and_flags & CONCURRENT_SET_CONTINUATION_BIT;
+
+ if (curr_hash_and_flags == CONCURRENT_SET_EMPTY) {
+ // Reserve this slot for our hash value
+ curr_hash_and_flags = rbimpl_atomic_value_cas(&entry->hash, CONCURRENT_SET_EMPTY, hash, RBIMPL_ATOMIC_RELEASE, RBIMPL_ATOMIC_RELAXED);
+ if (curr_hash_and_flags != CONCURRENT_SET_EMPTY) {
+ // Lost race, retry same slot to check winner's hash
+ continue;
+ }
+
+ // CAS succeeded, so these are the values stored
+ curr_hash_and_flags = hash;
+ curr_hash = hash;
+
+ // Fall through to try to claim key
+ }
+
+ if (curr_hash != hash) {
+ goto probe_next;
+ }
+
+ VALUE curr_key = rbimpl_atomic_value_load(&entry->key, RBIMPL_ATOMIC_ACQUIRE);
+
+ switch (curr_key) {
+ case CONCURRENT_SET_EMPTY: {
+ rb_atomic_t prev_size = rbimpl_atomic_fetch_add(&set->size, 1, RBIMPL_ATOMIC_RELAXED);
+
+ // Load_factor reached at 75% full. ex: prev_size: 32, capacity: 64, load_factor: 50%.
+ bool load_factor_reached = (uint64_t)(prev_size * 4) >= (uint64_t)(set->capacity * 3);
+
+ if (UNLIKELY(load_factor_reached)) {
+ concurrent_set_try_resize(set_obj, set_obj_ptr);
+ goto retry;
+ }
+
+ VALUE prev_key = rbimpl_atomic_value_cas(&entry->key, CONCURRENT_SET_EMPTY, key, RBIMPL_ATOMIC_RELEASE, RBIMPL_ATOMIC_RELAXED);
+ if (prev_key == CONCURRENT_SET_EMPTY) {
+ RUBY_ASSERT(rb_concurrent_set_find(set_obj_ptr, key) == key);
+ RB_GC_GUARD(set_obj);
+ return key;
+ }
+ else {
+ // Entry was not inserted.
+ rbimpl_atomic_sub(&set->size, 1, RBIMPL_ATOMIC_RELAXED);
+
+ // Another thread won the race, try again at the same location.
+ continue;
+ }
+ }
+ case CONCURRENT_SET_DELETED:
+ break;
+ case CONCURRENT_SET_MOVED:
+ // Wait
+ RB_VM_LOCKING();
+ goto retry;
+ default:
+ // We're never GC during our search
+ // If the continuation bit wasn't set at the start of our search,
+ // any concurrent find with the same hash value would also look at
+ // this location and try to swap curr_key
+ if (UNLIKELY(!RB_SPECIAL_CONST_P(curr_key) && rb_objspace_garbage_object_p(curr_key))) {
+ if (continuation) {
+ goto probe_next;
+ }
+ rbimpl_atomic_value_cas(&entry->key, curr_key, CONCURRENT_SET_EMPTY, RBIMPL_ATOMIC_RELEASE, RBIMPL_ATOMIC_RELAXED);
+ continue;
+ }
+
+ if (set->funcs->cmp(key, curr_key)) {
+ // We've found a live match.
+ RB_GC_GUARD(set_obj);
+
+ // We created key using set->funcs->create, but we didn't end
+ // up inserting it into the set. Free it here to prevent memory
+ // leaks.
+ if (set->funcs->free) set->funcs->free(key);
+
+ return curr_key;
+ }
+ break;
+ }
+
+ probe_next:
+ RUBY_ASSERT(curr_hash_and_flags != CONCURRENT_SET_EMPTY);
+ concurrent_set_mark_continuation(entry, curr_hash_and_flags);
+ idx = concurrent_set_probe_next(&probe);
+ }
+}
+
+static void
+concurrent_set_delete_entry_locked(struct concurrent_set *set, struct concurrent_set_entry *entry)
+{
+ ASSERT_vm_locking_with_barrier();
+
+ if (entry->hash & CONCURRENT_SET_CONTINUATION_BIT) {
+ entry->hash = CONCURRENT_SET_CONTINUATION_BIT;
+ entry->key = CONCURRENT_SET_DELETED;
+ set->deleted_entries++;
+ }
+ else {
+ entry->hash = CONCURRENT_SET_EMPTY;
+ entry->key = CONCURRENT_SET_EMPTY;
+ set->size--;
+ }
+}
+
+VALUE
+rb_concurrent_set_delete_by_identity(VALUE set_obj, VALUE key)
+{
+ ASSERT_vm_locking_with_barrier();
+
+ struct concurrent_set *set = RTYPEDDATA_GET_DATA(set_obj);
+
+ VALUE hash = concurrent_set_hash(set, key);
+
+ struct concurrent_set_probe probe;
+ int idx = concurrent_set_probe_start(&probe, set, hash);
+
+ while (true) {
+ struct concurrent_set_entry *entry = &set->entries[idx];
+ VALUE curr_key = entry->key;
+
+ switch (curr_key) {
+ case CONCURRENT_SET_EMPTY:
+ // We didn't find our entry to delete.
+ return 0;
+ case CONCURRENT_SET_DELETED:
+ break;
+ case CONCURRENT_SET_MOVED:
+ rb_bug("rb_concurrent_set_delete_by_identity: moved entry");
+ break;
+ default:
+ if (key == curr_key) {
+ RUBY_ASSERT((entry->hash & CONCURRENT_SET_HASH_MASK) == hash);
+ concurrent_set_delete_entry_locked(set, entry);
+ return curr_key;
+ }
+ break;
+ }
+
+ idx = concurrent_set_probe_next(&probe);
+ }
+}
+
+void
+rb_concurrent_set_foreach_with_replace(VALUE set_obj, int (*callback)(VALUE *key, void *data), void *data)
+{
+ ASSERT_vm_locking_with_barrier();
+
+ struct concurrent_set *set = RTYPEDDATA_GET_DATA(set_obj);
+
+ for (unsigned int i = 0; i < set->capacity; i++) {
+ struct concurrent_set_entry *entry = &set->entries[i];
+ VALUE key = entry->key;
+
+ switch (key) {
+ case CONCURRENT_SET_EMPTY:
+ case CONCURRENT_SET_DELETED:
+ continue;
+ case CONCURRENT_SET_MOVED:
+ rb_bug("rb_concurrent_set_foreach_with_replace: moved entry");
+ break;
+ default: {
+ int ret = callback(&entry->key, data);
+ switch (ret) {
+ case ST_STOP:
+ return;
+ case ST_DELETE:
+ concurrent_set_delete_entry_locked(set, entry);
+ break;
+ }
+ break;
+ }
+ }
+ }
+}
diff --git a/configure.ac b/configure.ac
index 2626c45920..4e7367804d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -20,6 +20,7 @@ RUBY_M4_INCLUDE([colorize_result.m4])dnl
RUBY_M4_INCLUDE([ruby_append_option.m4])dnl
RUBY_M4_INCLUDE([ruby_append_options.m4])dnl
RUBY_M4_INCLUDE([ruby_check_builtin_func.m4])dnl
+RUBY_M4_INCLUDE([ruby_check_builtin_overflow.m4])dnl
RUBY_M4_INCLUDE([ruby_check_builtin_setjmp.m4])dnl
RUBY_M4_INCLUDE([ruby_check_header.m4])dnl
RUBY_M4_INCLUDE([ruby_check_printf_prefix.m4])dnl
@@ -44,7 +45,7 @@ RUBY_M4_INCLUDE([ruby_replace_type.m4])dnl
RUBY_M4_INCLUDE([ruby_require_funcs.m4])dnl
RUBY_M4_INCLUDE([ruby_rm_recursive.m4])dnl
RUBY_M4_INCLUDE([ruby_setjmp_type.m4])dnl
-RUBY_M4_INCLUDE([ruby_shared_gc.m4])dnl
+RUBY_M4_INCLUDE([ruby_modular_gc.m4])dnl
RUBY_M4_INCLUDE([ruby_stack_grow_direction.m4])dnl
RUBY_M4_INCLUDE([ruby_thread.m4])dnl
RUBY_M4_INCLUDE([ruby_try_cflags.m4])dnl
@@ -68,6 +69,7 @@ dnl 93(bright yellow) is copied from .github/workflows/mingw.yml
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
+AC_ARG_VAR([rustc_flags], [additional RUSTC_FLAGS])dnl
[begin]_group "environment section" && {
HAVE_BASERUBY=yes
@@ -81,9 +83,17 @@ AC_ARG_WITH(baseruby,
],
[
AC_PATH_PROG([BASERUBY], [ruby], [false])
+ HAVE_BASERUBY=
])
-AS_IF([test "$HAVE_BASERUBY" != no], [
- RUBYOPT=- $BASERUBY --disable=gems "${tooldir}/missing-baseruby.bat" || HAVE_BASERUBY=no
+AS_IF([test "$HAVE_BASERUBY" = no], [
+ # --without-baseruby
+], [error=`RUBYOPT=- $BASERUBY --disable=gems "${tooldir}/missing-baseruby.bat" --verbose 2>&1`], [
+ HAVE_BASERUBY=yes
+], [test "$HAVE_BASERUBY" = ""], [ # no --with-baseruby option
+ AC_MSG_WARN($error) # just warn and continue
+ HAVE_BASERUBY=no
+], [ # the ruby given by --with-baseruby is too old
+ AC_MSG_ERROR($error) # bail out
])
AS_IF([test "${HAVE_BASERUBY:=no}" != no], [
AS_CASE(["$build_os"], [mingw*], [
@@ -106,10 +116,18 @@ HAVE_GIT=yes
AC_ARG_WITH(git,
AS_HELP_STRING([--without-git], [never use git]),
[AS_CASE([$withval],
- [no], [GIT=never-use HAVE_GIT=no],
+ [no], [HAVE_GIT=no],
[yes], [],
[GIT=$withval])])
-AS_IF([test x"$HAVE_GIT" = xyes], [command -v "$GIT" > /dev/null || HAVE_GIT=no])
+{
+ test x"$HAVE_GIT" = xyes &&
+ command -v "$GIT" > /dev/null &&
+ # `git -C`: 1.8.5
+ # `git log --no-show-signature`: 2.10.0
+ AS_CASE([`$GIT -C . --version 2> /dev/null | sed 's/.* //'`],
+ [0.*|1.*|2.@<:@0-9@:>@.*], [false],
+ [true])
+} || HAVE_GIT=no GIT=never-use
AC_SUBST(GIT)
AC_SUBST(HAVE_GIT)
@@ -148,6 +166,7 @@ dnl checks for alternative programs
AC_CANONICAL_BUILD
AC_CANONICAL_HOST
AC_CANONICAL_TARGET
+AC_SUBST(config_target, $target)
AS_CASE(["$target_cpu-$target_os"],
[aarch64-darwin*], [
target_cpu=arm64
@@ -206,7 +225,7 @@ AC_ARG_VAR([STRIP], [Strip command])
set rb_dummy ${CC}
rb_CC=$2
AC_DEFUN([RUBY_CHECK_PROG_FOR_CC], [
- rb_prog=`echo "${rb_CC}" | sed "$2"`
+ rb_prog=`echo "${rb_CC}" | sed ["s:$2\([^/]*\)$:$3\1:"]`
AC_CHECK_PROG([$1], [$rb_prog], [$rb_prog])
])
AS_CASE(["/${rb_CC} "],
@@ -217,17 +236,17 @@ AS_CASE(["/${rb_CC} "],
[*icc*], [
# Intel C++ has interprocedural optimizations. It tends to come with its
# own linker etc.
- RUBY_CHECK_PROG_FOR_CC([AR], [s/icc/xiar/])
- RUBY_CHECK_PROG_FOR_CC([CXX], [s/icc/icpc/])
- RUBY_CHECK_PROG_FOR_CC([LD], [s/icc/xild/])
+ RUBY_CHECK_PROG_FOR_CC([AR], [icc], [xiar])
+ RUBY_CHECK_PROG_FOR_CC([CXX], [icc], [icpc])
+ RUBY_CHECK_PROG_FOR_CC([LD], [icc], [xild])
],
[*gcc*], [
# Ditto for GCC.
- RUBY_CHECK_PROG_FOR_CC([LD], [s/gcc/ld/])
- RUBY_CHECK_PROG_FOR_CC([AR], [s/gcc/gcc-ar/])
- RUBY_CHECK_PROG_FOR_CC([CXX], [s/gcc/g++/])
- RUBY_CHECK_PROG_FOR_CC([NM], [s/gcc/gcc-nm/])
- RUBY_CHECK_PROG_FOR_CC([RANLIB], [s/gcc/gcc-ranlib/])
+ RUBY_CHECK_PROG_FOR_CC([LD], [gcc], [ld])
+ RUBY_CHECK_PROG_FOR_CC([AR], [gcc], [gcc-ar])
+ RUBY_CHECK_PROG_FOR_CC([CXX], [gcc], [g++])
+ RUBY_CHECK_PROG_FOR_CC([NM], [gcc], [gcc-nm])
+ RUBY_CHECK_PROG_FOR_CC([RANLIB], [gcc], [gcc-ranlib])
],
[*clang*], [
# Ditto for LLVM. Note however that llvm-as is a LLVM-IR to LLVM bitcode
@@ -240,15 +259,15 @@ AS_CASE(["/${rb_CC} "],
[llvm_prefix=], [llvm_prefix=llvm-])
# AC_PREPROC_IFELSE cannot be used before AC_USE_SYSTEM_EXTENSIONS
- RUBY_CHECK_PROG_FOR_CC([LD], [s/clang/ld/]) # ... maybe try lld ?
- RUBY_CHECK_PROG_FOR_CC([AR], [s/clang/${llvm_prefix}ar/])
-# RUBY_CHECK_PROG_FOR_CC([AS], [s/clang/${llvm_prefix}as/])
- RUBY_CHECK_PROG_FOR_CC([CXX], [s/clang/clang++/])
- RUBY_CHECK_PROG_FOR_CC([NM], [s/clang/${llvm_prefix}nm/])
- RUBY_CHECK_PROG_FOR_CC([OBJCOPY], [s/clang/${llvm_prefix}objcopy/])
- RUBY_CHECK_PROG_FOR_CC([OBJDUMP], [s/clang/${llvm_prefix}objdump/])
- RUBY_CHECK_PROG_FOR_CC([RANLIB], [s/clang/${llvm_prefix}ranlib/])
- RUBY_CHECK_PROG_FOR_CC([STRIP], [s/clang/${llvm_prefix}strip/])
+ RUBY_CHECK_PROG_FOR_CC([LD], [clang], [ld]) # ... maybe try lld ?
+ RUBY_CHECK_PROG_FOR_CC([AR], [clang], [${llvm_prefix}ar])
+# RUBY_CHECK_PROG_FOR_CC([AS], [clang], [${llvm_prefix}as])
+ RUBY_CHECK_PROG_FOR_CC([CXX], [clang], [clang++])
+ RUBY_CHECK_PROG_FOR_CC([NM], [clang], [${llvm_prefix}nm])
+ RUBY_CHECK_PROG_FOR_CC([OBJCOPY], [clang], [${llvm_prefix}objcopy])
+ RUBY_CHECK_PROG_FOR_CC([OBJDUMP], [clang], [${llvm_prefix}objdump])
+ RUBY_CHECK_PROG_FOR_CC([RANLIB], [clang], [${llvm_prefix}ranlib])
+ RUBY_CHECK_PROG_FOR_CC([STRIP], [clang], [${llvm_prefix}strip])
])
AS_UNSET(rb_CC)
AS_UNSET(rb_dummy)
@@ -262,6 +281,8 @@ AS_CASE(["${build_os}"],
])
AS_CASE(["${target_os}"],
[cygwin*|msys*|mingw*|darwin*], [
+ ac_ct_OBJCOPY=":"
+ ac_cv_prog_OBJCOPY=":"
ac_cv_prog_ac_ct_OBJCOPY=":"
])
@@ -284,6 +305,8 @@ AC_CHECK_TOOLS([OBJCOPY], [gobjcopy objcopy], [:])
AC_CHECK_TOOLS([OBJDUMP], [gobjdump objdump])
AC_CHECK_TOOLS([STRIP], [gstrip strip], [:])
+FIRSTMAKEFILE=""
+
# nm errors with Rust's LLVM bitcode when Rust uses a newer LLVM version than nm.
# In case we're working with llvm-nm, tell it to not worry about the bitcode.
AS_IF([${NM} --help 2>&1 | grep -q 'llvm-bc'], [NM="$NM --no-llvm-bc"])
@@ -360,7 +383,7 @@ test -z "$warnflags" ||
AS_IF([test -z "${CFLAGS+set}"], [
cflags=`echo " $cflags " | sed "$cflagspat;s/^ *//;s/ *$//"`
orig_cflags="$cflags"
- cflags="$cflags "'${optflags} ${debugflags} ${warnflags}'
+ cflags='${hardenflags} '"$cflags "'${optflags} ${debugflags} ${warnflags}'
])
dnl AS_IF([test -z "${CXXFLAGS+set}"], [
dnl cxxflags=`echo " $cxxflags " | sed "$cflagspat;s/^ *//;s/ *$//"`
@@ -458,6 +481,8 @@ AS_CASE(["$target_os"],
# so wrap clang to insert our fake wasm-opt, which does nothing, in PATH.
CC_WRAPPER=`cd -P "${tooldir}" && pwd`/wasm-clangw
CC="$CC_WRAPPER $CC"
+
+ FIRSTMAKEFILE=GNUmakefile:wasm/GNUmakefile.in
])
cc_version=
@@ -489,7 +514,6 @@ AC_CACHE_CHECK([for $AR flags], [rb_cv_arflags], [
[rb_cv_arflags=rcD], [rb_cv_arflags=rcu])
])
AC_SUBST(ARFLAGS, ["$rb_cv_arflags "])
-AC_SUBST(ASFLAGS)
AS_CASE(["$target_os"],
[cygwin*|msys*|mingw*], [
@@ -500,6 +524,8 @@ AS_CASE(["$target_os"],
target_cpu=`echo $target_cpu | sed s/i.86/i386/`
AS_CASE(["$target"], [-*], [ target="$target_cpu${target}"])
AS_CASE(["$target_alias"], [-*], [ target_alias="$target_cpu${target_alias}"])
+ # cygwin/GNUmakefile.in is not exclusively for cygwin.
+ FIRSTMAKEFILE=GNUmakefile:cygwin/GNUmakefile.in
AS_CASE(["$target_os"],
[mingw*], [
test "$rb_cv_msvcrt" = "" && unset rb_cv_msvcrt
@@ -520,7 +546,6 @@ AS_CASE(["$target_os"],
])
rb_cv_binary_elf=no
: ${enable_shared=yes}
- AS_IF([$WINDRES --version | grep LLVM > /dev/null], [USE_LLVM_WINDRES=yes], [USE_LLVM_WINDRES=no])
],
[hiuxmpp*], [AC_DEFINE(__HIUX_MPP__)]) # by TOYODA Eizi <toyoda@npd.kishou.go.jp>
@@ -602,6 +627,22 @@ AS_IF([test -f conf$$.dir/src/cdcmd], [
rm -fr conf$$.dir
AC_MSG_RESULT([$CHDIR])
AC_SUBST(CHDIR)
+
+AS_CASE(["$FIRSTMAKEFILE"], [*GNUmakefile:*], [gnumake=yes], [
+ AC_MSG_CHECKING([if ${MAKE-make} is GNU make])
+ mkdir conftest.dir
+ echo "all:; @echo yes" > conftest.dir/GNUmakefile
+ echo "all:; @echo no" > conftest.dir/Makefile
+ gnumake=`(cd conftest.dir; ${MAKE-make})`
+ rm -fr conftest.dir
+ AS_CASE(["$gnumake"],
+ [*yes*], [
+ FIRSTMAKEFILE=GNUmakefile:template/GNUmakefile.in
+ gnumake=yes],
+ [
+ gnumake=no])
+ AC_MSG_RESULT($gnumake)
+])
}
[begin]_group "compiler section" && {
@@ -663,9 +704,9 @@ RUBY_WERROR_FLAG([
[enable_rpath=$enableval], [enable_rpath="$rb_cv_binary_elf"])
AS_IF([test "$enable_rpath:${RPATHFLAG}" = yes:], [
- RPATHFLAG="${rpathflag:+ ${rpathflag}%1\$-s}"
+ RPATHFLAG="${rpathflag:+${rpathflag}%1\$-s}"
])
- AS_CASE([${RPATHFLAG}],[*'%1$'*],[: ${LIBPATHFLAG=' -L%1$-s'}],[: ${LIBPATHFLAG=' -L%s'}])
+ AS_CASE([${RPATHFLAG}],[*'%1$'*],[: ${LIBPATHFLAG='-L%1$-s'}],[: ${LIBPATHFLAG='-L%s'}])
}
RUBY_TRY_LDFLAGS(-fdeclspec, [fdeclspec=yes], [fdeclspec=no])
@@ -813,7 +854,7 @@ AS_IF([test "$GCC" = yes], [
[fortify_source=$enableval])
AS_IF([test "x$fortify_source" != xno], [
RUBY_TRY_CFLAGS([$optflags -D_FORTIFY_SOURCE=2],
- [RUBY_APPEND_OPTION(XCFLAGS, -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2)], [],
+ [RUBY_PREPEND_OPTION(hardenflags, -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2)], [],
[@%:@include <stdio.h>])
])
@@ -834,21 +875,45 @@ AS_IF([test "$GCC" = yes], [
AC_MSG_CHECKING([for -fstack-protector])
AC_MSG_RESULT(["$stack_protector"])
AS_CASE(["$stack_protector"], [-*], [
- RUBY_APPEND_OPTION(XCFLAGS, $stack_protector)
- RUBY_APPEND_OPTION(XLDFLAGS, $stack_protector)
- RUBY_APPEND_OPTION(LDFLAGS, $stack_protector)
+ RUBY_PREPEND_OPTION(hardenflags, $stack_protector)
+ RUBY_APPEND_OPTION(XLDFLAGS, $stack_protector)
+ RUBY_APPEND_OPTION(LDFLAGS, $stack_protector)
])
# aarch64 branch protection
- AS_CASE(["$target_cpu"], [aarch64], [
- AS_FOR(option, opt, [-mbranch-protection=pac-ret -msign-return-address=all], [
- RUBY_TRY_CFLAGS(option, [branch_protection=yes], [branch_protection=no])
- AS_IF([test "x$branch_protection" = xyes], [
- # C compiler and assembler must be consistent for -mbranch-protection
- # since they both check `__ARM_FEATURE_PAC_DEFAULT` definition.
- RUBY_APPEND_OPTION(XCFLAGS, option)
- RUBY_APPEND_OPTION(ASFLAGS, option)
- break
+ AS_CASE(["$target_cpu"], [aarch64|arm64], [
+ # LLVM libunwind is not actually capable of unwinding code compiled with pointer
+ # authentication unless it's built without LIBUNWIND_ENABLE_CROSS_UNWINDING (see
+ # https://github.com/llvm/llvm-project/blob/8e35c86977ce5529a9387657321ac9fefcdae5b5/libunwind/src/DwarfInstructions.hpp#L294)
+ # It seems that macOS ships LLVM compiled this way.
+ # Detect this and disable automatic insertion of pac-ret flags in that case, since we assume
+ # that reliable backtraces are more important than hardening flags.
+ AC_MSG_CHECKING([for a broken LLVM libunwind that cannot unwind code with RA signing])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+ @%:@include <libunwind.h>
+ int foo = UNW_ECROSSRASIGNING;
+ ]])],
+ # If compilation succeeds, that means we a) had libunwind, and b) it was NOT native only
+ [rb_cv_libunwind_broken_ra_signing=yes],
+ # if compilation fails, that means we either a) do not have libunwind, or b) have it in
+ # native only mode (which is good!)
+ [rb_cv_libunwind_broken_ra_signing=no]
+ )
+ AC_MSG_RESULT(["$rb_cv_libunwind_broken_ra_signing"])
+ AS_IF([test "x$rb_cv_libunwind_broken_ra_signing" = "xno"], [
+ AS_FOR(option, opt, [-mbranch-protection=pac-ret -msign-return-address=all], [
+ # Try these flags in the _prepended_ position - i.e. we want to try building a program
+ # with CFLAGS="-mbranch-protection=pac-ret $CFLAGS". If the builder has provided different
+ # branch protection flags in CFLAGS, we don't want to overwrite those. We just want to
+ # find some branch protection flags which work if none were provided.
+ RUBY_TRY_CFLAGS_PREPEND(option, [branch_protection=yes], [branch_protection=no])
+ AS_IF([test "x$branch_protection" = xyes], [
+ # _prepend_ the options to CFLAGS, so that user-provided flags will overwrite them.
+ # These CFLAGS are used during the configure script to compile further test programs;
+ # however, $harden_flags is prepended separately to CFLAGS at the end of the script.
+ RUBY_PREPEND_OPTION(hardenflags, $opt)
+ break
+ ])
])
])
])
@@ -978,9 +1043,17 @@ AC_ARG_WITH(opt-dir,
[OPT_DIR="${OPT_DIR:+$OPT_DIR$PATH_SEPARATOR}$withval"], [])
AS_IF([test "x$OPT_DIR" != x], [
+ save_IFS="$IFS" IFS="$PATH_SEPARATOR" val= PWD=
+ for dir in $OPT_DIR; do
+ test -z "$dir" && continue
+ dir=`eval $CHDIR '"$dir"' 2>/dev/null && pwd` || continue
+ val="${val:+$val$PATH_SEPARATOR}$dir"
+ done
+ IFS="$save_IFS" OPT_DIR="$val"
+ unset PWD
+ unset save_IFS
val=`IFS="$PATH_SEPARATOR"
for dir in $OPT_DIR; do
- test -z "$dir" && continue
echo x ${LIBPATHFLAG} ${RPATHFLAG} |
sed "s/^x *//;s${IFS}"'%1\\$-s'"${IFS}${dir}/lib${IFS}g;s${IFS}%s${IFS}${dir}/lib${IFS}g"
done | tr '\012' ' ' | sed 's/ *$//'`
@@ -995,6 +1068,7 @@ AC_SUBST(incflags, "$INCFLAGS")
test -z "${ac_env_CFLAGS_set}" -a -n "${cflags+set}" && eval CFLAGS="\"$cflags $ARCH_FLAG\""
test -z "${ac_env_CXXFLAGS_set}" -a -n "${cxxflags+set}" && eval CXXFLAGS="\"$cxxflags $ARCH_FLAG\""
+
AC_CACHE_CHECK([whether compiler has statement and declarations in expressions],
rb_cv_have_stmt_and_decl_in_expr,
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[ __extension__ ({ int a = 0; a; }); ]])],
@@ -1060,7 +1134,6 @@ AS_CASE(["$target_os"],
AS_IF([test $gcc_major -eq 4 -a $gcc_minor -lt 3], [
ac_cv_func___builtin_setjmp=no
])
- with_setjmp_type=sigsetjmp # to hijack SIGCHLD handler
AC_CACHE_CHECK(for broken crypt with 8bit chars, rb_cv_broken_crypt,
[AC_RUN_IFELSE([AC_LANG_SOURCE([[
#include <stdio.h>
@@ -1195,6 +1268,11 @@ main()
ac_cv_header_sys_time_h=no
ac_cv_header_sys_times_h=no
ac_cv_header_sys_socket_h=no
+ ac_cv_func_chown=yes
+ ac_cv_func_getegid=yes
+ ac_cv_func_geteuid=yes
+ ac_cv_func_getgid=yes
+ ac_cv_func_getuid=yes
ac_cv_func_execv=yes
ac_cv_func_lstat=yes
ac_cv_func_times=yes
@@ -1207,6 +1285,8 @@ main()
ac_cv_func_readlink=yes
ac_cv_func_shutdown=yes
ac_cv_func_symlink=yes
+ ac_cv_func_clock_getres=yes
+ ac_cv_func_clock_gettime=yes
ac_cv_lib_crypt_crypt=no
ac_cv_func_getpgrp_void=no
ac_cv_func_memcmp_working=yes
@@ -1217,19 +1297,18 @@ main()
ac_cv_func_gmtime_r=yes
rb_cv_large_fd_select=yes
ac_cv_type_struct_timeval=yes
- ac_cv_func_clock_gettime=yes
- ac_cv_func_clock_getres=yes
ac_cv_func_malloc_usable_size=no
ac_cv_type_off_t=yes
ac_cv_sizeof_off_t=8
AS_IF([test "$target_cpu" = x64], [
ac_cv_func___builtin_setjmp=yes
ac_cv_func_round=no
+ ac_cv_func_tgamma=no
])
- ac_cv_func_tgamma=no
AC_CHECK_TYPE([NET_LUID], [], [],
[@%:@include <winsock2.h>
- @%:@include <iphlpapi.h>])
+ @%:@include <windows.h>
+ @%:@include <iphlpapi.h>])
AS_IF([test x"$ac_cv_type_NET_LUID" = xyes], [
AC_DEFINE(HAVE_TYPE_NET_LUID, 1)
])
@@ -1259,12 +1338,8 @@ main()
# __builtin_longjmp in ppc64* Linux does not restore
# the TOC register (r2), which is problematic
# when a global exit happens from JITted .so code.
- AS_CASE(["$target_cpu"], [powerpc64*], [
- ac_cv_func___builtin_setjmp=no
- ])
- # With gcc-8's -fcf-protection, RJIT's __builtin_longjmp fails.
- AS_CASE(["$CC $CFLAGS "], [*" -fcf-protection "*], [cf_protection=yes], [cf_protection=no])
- AS_IF([test "$cf_protection" = yes], [
+ # __builtin_setjmp can have issues on arm64 linux (see [Bug #14480]).
+ AS_CASE(["$target_cpu"], [powerpc64*|arm64|aarch64], [
ac_cv_func___builtin_setjmp=no
])
],
@@ -1344,6 +1419,7 @@ AC_CHECK_HEADERS(process.h)
AC_CHECK_HEADERS(pwd.h)
AC_CHECK_HEADERS(sanitizer/asan_interface.h)
AC_CHECK_HEADERS(sanitizer/msan_interface.h)
+AC_CHECK_HEADERS(sanitizer/tsan_interface.h)
AC_CHECK_HEADERS(setjmpex.h)
AC_CHECK_HEADERS(stdalign.h)
AC_CHECK_HEADERS(stdio.h)
@@ -1374,8 +1450,9 @@ AC_CHECK_HEADERS(utime.h)
AC_CHECK_HEADERS(sys/epoll.h)
AC_CHECK_HEADERS(sys/event.h)
AC_CHECK_HEADERS(stdckdint.h)
+AC_CHECK_HEADERS(stdatomic.h)
-AS_CASE("$target_cpu", [x64|x86_64|i[3-6]86*], [
+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)
@@ -1650,21 +1727,6 @@ AS_IF([test "$rb_cv_func_weak" != x], [
AC_DEFINE(HAVE_FUNC_WEAK)
])
-AC_CACHE_CHECK([for __attribute__((__depreacted__(msg))) in C++],
- rb_cv_CentOS6_CXX_workaround,
- RUBY_WERROR_FLAG([
- AC_LANG_PUSH([C++])
- AC_COMPILE_IFELSE(
- [AC_LANG_PROGRAM(
- [],
- [__attribute__((__deprecated__("message"))) int conftest(...);])],
- [rb_cv_CentOS6_CXX_workaround=yes],
- [rb_cv_CentOS6_CXX_workaround=no])
- AC_LANG_POP()]))
-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(
@@ -1714,6 +1776,26 @@ AS_IF([test "$GCC" = yes], [
[rb_cv_gcc_atomic_builtins=no])])
AS_IF([test "$rb_cv_gcc_atomic_builtins" = yes], [
AC_DEFINE(HAVE_GCC_ATOMIC_BUILTINS)
+ for lib in "" atomic; do
+ AS_IF([test "$lib" != ""], [
+ AC_CHECK_LIB([atomic], [__atomic_fetch_add_8])
+ unset rb_cv_gcc_atomic_builtins_64
+ ])
+ AC_CACHE_CHECK([for 64bit __atomic builtins${lib:+ with -l$lib}],
+ [rb_cv_gcc_atomic_builtins_64], [
+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[@%:@include <stdint.h>
+ uint64_t atomic_var;]],
+ [[
+ __atomic_load_n(&atomic_var, __ATOMIC_RELAXED);
+ __atomic_store_n(&atomic_var, 0, __ATOMIC_RELAXED);
+ ]])],
+ [rb_cv_gcc_atomic_builtins_64=yes],
+ [rb_cv_gcc_atomic_builtins_64=no])])
+ AS_IF([test "$rb_cv_gcc_atomic_builtins_64" = yes], [
+ AC_DEFINE(HAVE_GCC_ATOMIC_BUILTINS_64)
+ break
+ ])
+ done
])
AC_CACHE_CHECK([for __sync builtins], [rb_cv_gcc_sync_builtins], [
@@ -1760,7 +1842,7 @@ AS_IF([test "$GCC" = yes], [
AC_CACHE_CHECK(for exported function attribute, rb_cv_func_exported, [
rb_cv_func_exported=no
RUBY_WERROR_FLAG([
-for mac in '__attribute__ ((__visibility__("default")))' '__declspec(dllexport)'; do
+for mac in '__declspec(dllexport)' '__attribute__ ((__visibility__("default")))'; do
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@define RUBY_FUNC_EXPORTED $mac extern
RUBY_FUNC_EXPORTED void conftest_attribute_check(void);]], [[]])],
[rb_cv_func_exported="$mac"; break])
@@ -1777,10 +1859,6 @@ 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([--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,
[AS_CASE(["$target_os"],[openbsd*],[
@@ -2055,6 +2133,7 @@ AC_CHECK_FUNCS(_longjmp) # used for AC_ARG_WITH(setjmp-type)
test x$ac_cv_func__longjmp = xno && ac_cv_func__setjmp=no
AC_CHECK_FUNCS(arc4random_buf)
AC_CHECK_FUNCS(atan2l atan2f)
+AC_CHECK_DECLS(atomic_signal_fence, [], [], [@%:@include <stdatomic.h>])
AC_CHECK_FUNCS(chmod)
AC_CHECK_FUNCS(chown)
AC_CHECK_FUNCS(chroot)
@@ -2263,10 +2342,6 @@ RUBY_CHECK_BUILTIN_FUNC(__builtin_clzl, [__builtin_clzl(0)])
RUBY_CHECK_BUILTIN_FUNC(__builtin_clzll, [__builtin_clzll(0)])
RUBY_CHECK_BUILTIN_FUNC(__builtin_ctz, [__builtin_ctz(0)])
RUBY_CHECK_BUILTIN_FUNC(__builtin_ctzll, [__builtin_ctzll(0)])
-RUBY_CHECK_BUILTIN_FUNC(__builtin_add_overflow, [int x;__builtin_add_overflow(0,0,&x)])
-RUBY_CHECK_BUILTIN_FUNC(__builtin_sub_overflow, [int x;__builtin_sub_overflow(0,0,&x)])
-RUBY_CHECK_BUILTIN_FUNC(__builtin_mul_overflow, [int x;__builtin_mul_overflow(0,0,&x)])
-RUBY_CHECK_BUILTIN_FUNC(__builtin_mul_overflow_p, [__builtin_mul_overflow_p(0,0,(int)0)])
RUBY_CHECK_BUILTIN_FUNC(__builtin_constant_p, [__builtin_constant_p(0)])
RUBY_CHECK_BUILTIN_FUNC(__builtin_choose_expr, [
[int x[__extension__(__builtin_choose_expr(1, 1, -1))]];
@@ -2282,26 +2357,9 @@ RUBY_CHECK_BUILTIN_FUNC(__builtin_types_compatible_p, [__builtin_types_compatibl
RUBY_CHECK_BUILTIN_FUNC(__builtin_trap, [__builtin_trap()])
RUBY_CHECK_BUILTIN_FUNC(__builtin_expect, [__builtin_expect(0, 0)])
-AS_IF([test "$rb_cv_builtin___builtin_mul_overflow" != no], [
- AC_CACHE_CHECK(for __builtin_mul_overflow with long long arguments, rb_cv_use___builtin_mul_overflow_long_long, [
- AC_LINK_IFELSE([AC_LANG_SOURCE([[
-#pragma clang optimize off
-
-int
-main(void)
-{
- long long x = 0, y;
- __builtin_mul_overflow(x, x, &y);
-
- return 0;
-}
-]])],
- rb_cv_use___builtin_mul_overflow_long_long=yes,
- rb_cv_use___builtin_mul_overflow_long_long=no)])
-])
-AS_IF([test "$rb_cv_use___builtin_mul_overflow_long_long" = yes], [
- AC_DEFINE(USE___BUILTIN_MUL_OVERFLOW_LONG_LONG, 1)
-])
+RUBY_CHECK_BUILTIN_OVERFLOW(add)
+RUBY_CHECK_BUILTIN_OVERFLOW(sub)
+RUBY_CHECK_BUILTIN_OVERFLOW(mul)
AS_IF([test "$ac_cv_func_qsort_r" != no], [
AC_CACHE_CHECK(whether qsort_r is GNU version, rb_cv_gnu_qsort_r,
@@ -2717,6 +2775,12 @@ AS_CASE([$coroutine_type], [yes|''], [
[aarch64-freebsd*], [
coroutine_type=arm64
],
+ [powerpc64-freebsd*], [
+ coroutine_type=ppc64le
+ ],
+ [powerpc64le-freebsd*], [
+ coroutine_type=ppc64le
+ ],
[x86_64-netbsd*], [
coroutine_type=amd64
],
@@ -2735,6 +2799,9 @@ AS_CASE([$coroutine_type], [yes|''], [
[aarch64-openbsd*], [
coroutine_type=arm64
],
+ [riscv64-openbsd*], [
+ coroutine_type=riscv64
+ ],
[*-openbsd*], [
coroutine_type=pthread
],
@@ -2833,7 +2900,7 @@ AS_IF([test "$THREAD_MODEL" = pthread], [
])
])
- AC_CACHE_CHECK([for thread-local storage sepcifier], [rb_cv_tls_specifier],
+ AC_CACHE_CHECK([for thread-local storage specifier], [rb_cv_tls_specifier],
rb_cv_tls_specifier=none
RUBY_WERROR_FLAG([
for attr in \
@@ -3344,7 +3411,6 @@ AS_IF([test x$with_valgrind != xno],
DLEXT=so])
: ${SOEXT="${DLEXT}"}
AC_SUBST(SOEXT)
-}
AS_IF([test "$rb_cv_dlopen:$load_relative" = yes:yes], [
AS_IF([test "$ac_cv_func_dladdr" = yes], [
@@ -3363,6 +3429,9 @@ AC_DEFINE_UNQUOTED(DLEXT_MAXLEN, `expr $len + 1`)
test ".$DLEXT" = "." || AC_DEFINE_UNQUOTED(DLEXT, ".$DLEXT")
AC_SUBST(DLEXT)
+AC_DEFINE_UNQUOTED(SOEXT, ".$SOEXT")
+}
+
: "strip" && {
AC_MSG_CHECKING([for $STRIP flags])
AC_LINK_IFELSE([AC_LANG_PROGRAM], [AS_IF(
@@ -3435,7 +3504,7 @@ done
BTESTRUBY='$(MINIRUBY)'
AS_IF([test x"$cross_compiling" = xyes], [
- test x"$MINIRUBY" = x && MINIRUBY="${RUBY-$BASERUBY} -I`$CHDIR .; pwd` "-r'$(arch)-fake'
+ test x"$MINIRUBY" = x && MINIRUBY="${RUBY-$BASERUBY} -I${ac_abs_builddir-.} "-r'$(arch)-fake'
XRUBY_LIBDIR=`${RUBY-$BASERUBY} -rrbconfig -e ['puts RbConfig::CONFIG["libdir"]']`
XRUBY_RUBYLIBDIR=`${RUBY-$BASERUBY} -rrbconfig -e ['puts RbConfig::CONFIG["rubylibdir"]']`
XRUBY_RUBYHDRDIR=`${RUBY-$BASERUBY} -rrbconfig -e ['puts RbConfig::CONFIG["rubyhdrdir"]']`
@@ -3473,7 +3542,6 @@ AC_SUBST(RUNRUBY)
AC_SUBST(XRUBY)
AC_SUBST(EXTOUT, [${EXTOUT=.ext}])
-FIRSTMAKEFILE=""
LIBRUBY_A='lib$(RUBY_SO_NAME)-static.a'
LIBRUBY='$(LIBRUBY_A)'
LIBRUBYARG_STATIC='-l$(RUBY_SO_NAME)-static'
@@ -3513,7 +3581,7 @@ AC_ARG_WITH(soname,
],
[mingw*], [
RUBY_SO_NAME="${rb_cv_msvcrt}"'-$(RUBY_BASE_NAME)$(MAJOR)$(MINOR)0'
- AS_IF([test x"${target_cpu}" != xi386], [
+ AS_IF([test x"${target_cpu}" != xi386 || test x"${rb_cv_msvcrt}" != xmsvcrt], [
RUBY_SO_NAME="${target_cpu}-${RUBY_SO_NAME}"
])
],
@@ -3570,6 +3638,7 @@ AS_CASE("$enable_shared", [yes], [
])
])
+ relative_libprefix="/../${multiarch+../}${libdir_basename}"
AS_CASE(["$target_os"],
[sunos4*], [
LIBRUBY_ALIASES='$(LIBRUBY_SONAME) lib$(RUBY_SO_NAME).$(SOEXT)'
@@ -3578,7 +3647,7 @@ AS_CASE("$enable_shared", [yes], [
RUBY_APPEND_OPTIONS(LIBRUBY_DLDFLAGS, ['-Wl,-soname,$(LIBRUBY_SONAME)' "$LDFLAGS_OPTDIR"])
LIBRUBY_ALIASES='$(LIBRUBY_SONAME) lib$(RUBY_SO_NAME).$(SOEXT)'
AS_IF([test "$load_relative" = yes], [
- libprefix="'\$\${ORIGIN}/../${multiarch+../../}${libdir_basename}'"
+ libprefix="'\$\${ORIGIN}${relative_libprefix}'"
LIBRUBY_RPATHFLAGS="-Wl,-rpath,${libprefix}"
LIBRUBY_RELATIVE=yes
])
@@ -3590,7 +3659,7 @@ AS_CASE("$enable_shared", [yes], [
LIBRUBY_SO="$LIBRUBY_SO.\$(TEENY)"
LIBRUBY_ALIASES=''
], [test "$load_relative" = yes], [
- libprefix="'\$\$ORIGIN/../${multiarch+../../}${libdir_basename}'"
+ libprefix="'\$\$ORIGIN${relative_libprefix}'"
LIBRUBY_RPATHFLAGS="-Wl,-rpath,${libprefix}"
LIBRUBY_RELATIVE=yes
])
@@ -3614,7 +3683,7 @@ AS_CASE("$enable_shared", [yes], [
LIBRUBY_ALIASES='$(LIBRUBY_SONAME) lib$(RUBY_SO_NAME).$(SOEXT)'
RUBY_APPEND_OPTIONS(LIBRUBY_DLDFLAGS, ["${linker_flag}-h${linker_flag:+,}"'$(@F)'])
AS_IF([test "$load_relative" = yes], [
- libprefix="'\$\$ORIGIN/../${multiarch+../../}${libdir_basename}'"
+ libprefix="'\$\$ORIGIN${relative_libprefix}'"
LIBRUBY_RPATHFLAGS="-R${libprefix}"
LIBRUBY_RELATIVE=yes
], [
@@ -3631,7 +3700,7 @@ AS_CASE("$enable_shared", [yes], [
LIBRUBY_SONAME='$(LIBRUBY_SO)'
LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).$(SOEXT)'
AS_IF([test "$load_relative" = yes], [
- libprefix="@executable_path/../${multiarch+../../}${libdir_basename}"
+ libprefix="@executable_path${relative_libprefix}"
LIBRUBY_RELATIVE=yes
])
LIBRUBY_DLDFLAGS="$LIBRUBY_DLDFLAGS -install_name ${libprefix}"'/$(LIBRUBY_SONAME)'
@@ -3639,6 +3708,7 @@ AS_CASE("$enable_shared", [yes], [
LIBRUBY_DLDFLAGS="$LIBRUBY_DLDFLAGS "'-current_version $(RUBY_PROGRAM_VERSION)'
AS_IF([test "$visibility_option" = ld], [
LIBRUBY_DLDFLAGS="$LIBRUBY_DLDFLAGS "'-Wl,-unexported_symbol,_Init_*'
+ LIBRUBY_DLDFLAGS="$LIBRUBY_DLDFLAGS "'-Wl,-unexported_symbol,_InitVM_*'
LIBRUBY_DLDFLAGS="$LIBRUBY_DLDFLAGS "'-Wl,-unexported_symbol,_ruby_static_id_*'
LIBRUBY_DLDFLAGS="$LIBRUBY_DLDFLAGS "'-Wl,-unexported_symbol,*_threadptr_*'
])
@@ -3679,16 +3749,16 @@ AS_CASE("$enable_shared", [yes], [
])
])
AS_IF([test "$enable_rpath" = yes], [
- test -z "$LIBRUBY_RPATHFLAGS" || LIBRUBY_RPATHFLAGS="$LIBRUBY_RPATHFLAGS "
- rpathflag="${RPATHFLAG}"
- AS_CASE(["${cross_compiling}${load_relative}"], [*yes*], [], [rpathflag="$RPATHFLAG$LIBPATHFLAG"])
+ AS_CASE(["${cross_compiling}${load_relative}"],
+ [*yes*], [rpathflag="${RPATHFLAG}"],
+ [rpathflag="$RPATHFLAG${LIBPATHFLAG:+${RPATHFLAG:+ }$LIBPATHFLAG}"])
rpathflag=`IFS="$PATH_SEPARATOR"
echo x "$rpathflag" |
sed "s/^x *//;s${IFS}"'%1\\$-s'"${IFS}${libprefix}${IFS}g;s${IFS}%s${IFS}${libprefix}${IFS}g"
`
- LIBRUBY_RPATHFLAGS="$LIBRUBY_RPATHFLAGS${rpathflag}"
- LIBRUBYARG_SHARED="$LIBRUBY_RPATHFLAGS $LIBRUBYARG_SHARED"
- LIBRUBYARG_STATIC="$LIBRUBY_RPATHFLAGS $LIBRUBYARG_STATIC"
+ LIBRUBY_RPATHFLAGS="${LIBRUBY_RPATHFLAGS:+$LIBRUBY_RPATHFLAGS }${rpathflag}"
+ LIBRUBYARG_SHARED="${LIBRUBY_RPATHFLAGS:+$LIBRUBY_RPATHFLAGS }$LIBRUBYARG_SHARED"
+ LIBRUBYARG_STATIC="${LIBRUBY_RPATHFLAGS:+$LIBRUBY_RPATHFLAGS }$LIBRUBYARG_STATIC"
])
AC_SUBST(LIBRUBY_RELATIVE)
@@ -3765,12 +3835,12 @@ AC_ARG_ENABLE(gcov,
AS_HELP_STRING([--enable-gcov], [enable coverage measurement by gcov]),
[gcov=yes])
AS_IF([test x"$gcov" = xyes], [
- CFLAGS="$CFLAGS -coverage"
+ CFLAGS="$CFLAGS -coverage -fprofile-update=atomic"
LDFLAGS="$LDFLAGS -coverage"
])
RUBY_SETJMP_TYPE
-RUBY_SHARED_GC
+RUBY_MODULAR_GC
}
[begin]_group "installation section" && {
@@ -3837,39 +3907,39 @@ AC_SUBST(INSTALL_STATIC_LIBRARY)
AC_CHECK_PROG(RUSTC, [rustc], [rustc], [no]) dnl no ac_tool_prefix
dnl check if rustc is recent enough to build YJIT (rustc >= 1.58.0)
-YJIT_RUSTC_OK=no
+JIT_RUSTC_OK=no
+JIT_TARGET_ARCH=
AS_IF([test "$RUSTC" != "no"],
AC_MSG_CHECKING([whether ${RUSTC} works for YJIT])
- YJIT_TARGET_ARCH=
AS_CASE(["$target_cpu"],
- [arm64|aarch64], [YJIT_TARGET_ARCH=aarch64],
- [x86_64], [YJIT_TARGET_ARCH=x86_64],
+ [arm64|aarch64], [JIT_TARGET_ARCH=aarch64],
+ [x86_64], [JIT_TARGET_ARCH=x86_64],
)
dnl Fails in case rustc target doesn't match ruby target.
dnl Can happen on Rosetta, for example.
- AS_IF([echo "#[cfg(target_arch = \"$YJIT_TARGET_ARCH\")] fn main() { let x = 1; format!(\"{x}\"); }" |
+ AS_IF([echo "#[cfg(target_arch = \"$JIT_TARGET_ARCH\")] fn main() { let x = 1; format!(\"{x}\"); }" |
$RUSTC - --emit asm=/dev/null 2>/dev/null],
- [YJIT_RUSTC_OK=yes]
+ [JIT_RUSTC_OK=yes]
)
- AC_MSG_RESULT($YJIT_RUSTC_OK)
+ AC_MSG_RESULT($JIT_RUSTC_OK)
)
-dnl check if we can build YJIT on this target platform
+dnl check if we can build YJIT/ZJIT on this target platform
dnl we can't easily cross-compile with rustc so we don't support that
-YJIT_TARGET_OK=no
+JIT_TARGET_OK=no
AS_IF([test "$cross_compiling" = no],
AS_CASE(["$target_cpu-$target_os"],
[*android*], [
- YJIT_TARGET_OK=no
+ JIT_TARGET_OK=no
],
[arm64-darwin*|aarch64-darwin*|x86_64-darwin*], [
- YJIT_TARGET_OK=yes
+ JIT_TARGET_OK=yes
],
[arm64-*linux*|aarch64-*linux*|x86_64-*linux*], [
- YJIT_TARGET_OK=yes
+ JIT_TARGET_OK=yes
],
[arm64-*bsd*|aarch64-*bsd*|x86_64-*bsd*], [
- YJIT_TARGET_OK=yes
+ JIT_TARGET_OK=yes
]
)
)
@@ -3879,7 +3949,7 @@ AC_ARG_ENABLE(yjit,
AS_HELP_STRING([--enable-yjit],
[enable in-process JIT compiler that requires Rust build tools. enabled by default on supported platforms if rustc 1.58.0+ is available]),
[YJIT_SUPPORT=$enableval],
- [AS_CASE(["$YJIT_TARGET_OK:$YJIT_RUSTC_OK"],
+ [AS_CASE(["$JIT_TARGET_OK:$JIT_RUSTC_OK"],
[yes:yes], [
YJIT_SUPPORT=yes
],
@@ -3887,9 +3957,33 @@ AC_ARG_ENABLE(yjit,
)]
)
-CARGO=
+dnl build ZJIT in release mode if rustc >= 1.85.0 is present and we are on a supported platform
+ZJIT_SUPPORT=no
+AC_ARG_ENABLE(zjit,
+ AS_HELP_STRING([--enable-zjit],
+ [enable experimental JIT compiler that requires Rust build tools. enabled by default on supported platforms if rustc 1.85.0+ is available]),
+ [ZJIT_SUPPORT=$enableval],
+ [AS_CASE(["$JIT_TARGET_OK"],
+ [yes], [
+ rb_zjit_build_possible=no
+ AC_MSG_CHECKING([prerequisites for ZJIT])dnl only checked when --enable-zjit is not specified
+ # Fails in case rustc target doesn't match ruby target. Can happen on Rosetta, for example.
+ # 1.85.0 is the first stable version that supports the 2024 edition.
+ AS_IF([test "$RUSTC" != "no" && echo "#[cfg(target_arch = \"$JIT_TARGET_ARCH\")] fn main() {}" |
+ $RUSTC - --edition=2024 --emit asm=/dev/null 2>/dev/null],
+ AS_IF([test "$gnumake" = "yes"], [
+ rb_zjit_build_possible=yes
+ ])
+ )
+ AC_MSG_RESULT($rb_zjit_build_possible)
+ ZJIT_SUPPORT=$rb_zjit_build_possible
+ ]
+ )]
+)
+
CARGO_BUILD_ARGS=
YJIT_LIBS=
+JIT_CARGO_SUPPORT=no
AS_CASE(["${YJIT_SUPPORT}"],
[yes|dev|stats|dev_nodebug], [
AS_IF([test x"$RUSTC" = "xno"],
@@ -3898,36 +3992,26 @@ AS_CASE(["${YJIT_SUPPORT}"],
AS_CASE(["${YJIT_SUPPORT}"],
[yes], [
- rb_rust_target_subdir=release
],
[dev], [
- rb_rust_target_subdir=debug
- CARGO_BUILD_ARGS='--features stats,disasm'
+ rb_cargo_features='disasm,runtime_checks'
+ JIT_CARGO_SUPPORT=dev
AC_DEFINE(RUBY_DEBUG, 1)
],
[dev_nodebug], [
- rb_rust_target_subdir=dev_nodebug
- CARGO_BUILD_ARGS='--profile dev_nodebug --features stats,disasm'
+ rb_cargo_features='disasm'
+ JIT_CARGO_SUPPORT=dev_nodebug
AC_DEFINE(YJIT_STATS, 1)
],
[stats], [
- rb_rust_target_subdir=stats
- CARGO_BUILD_ARGS='--profile stats --features stats'
+ JIT_CARGO_SUPPORT=stats
AC_DEFINE(YJIT_STATS, 1)
])
- AS_IF([test -n "${CARGO_BUILD_ARGS}"], [
- AC_CHECK_TOOL(CARGO, [cargo], [no])
- AS_IF([test x"$CARGO" = "xno"],
- AC_MSG_ERROR([cargo is required. Installation instructions available at https://www.rust-lang.org/tools/install])
- ]))
-
- YJIT_LIBS="yjit/target/${rb_rust_target_subdir}/libyjit.a"
- AS_CASE(["$target_os"],[openbsd*],[
- # Link libc++abi (which requires libpthread) for _Unwind_* functions needed by yjit
- LDFLAGS="$LDFLAGS -lpthread -lc++abi"
- ])
+ YJIT_LIBS="target/release/libyjit.a"
+ RUST_LIB='$(YJIT_LIBS)'
YJIT_OBJ='yjit.$(OBJEXT)'
+ JIT_OBJ='jit.$(OBJEXT)'
AS_IF([test x"$YJIT_SUPPORT" != "xyes" ], [
AC_DEFINE_UNQUOTED(YJIT_SUPPORT, [$YJIT_SUPPORT])
])
@@ -3936,58 +4020,118 @@ AS_CASE(["${YJIT_SUPPORT}"],
AC_DEFINE(USE_YJIT, 0)
])
-dnl These variables end up in ::RbConfig::CONFIG
-AC_SUBST(YJIT_SUPPORT)dnl what flavor of YJIT the Ruby build includes
-AC_SUBST(RUSTC)dnl Rust compiler command
-AC_SUBST(CARGO)dnl Cargo command for Rust builds
-AC_SUBST(CARGO_BUILD_ARGS)dnl for selecting Rust build profiles
-AC_SUBST(YJIT_LIBS)dnl for optionally building the Rust parts of YJIT
-AC_SUBST(YJIT_OBJ)dnl for optionally building the C parts of YJIT
-
-dnl RJIT supports only x86_64 platforms, but allows arm64/aarch64 for custom JITs.
-RJIT_TARGET_OK=no
-AS_IF([test "$cross_compiling" = no],
- AS_CASE(["$target_cpu-$target_os"],
- [*android*], [
- RJIT_TARGET_OK=no
- ],
- [arm64-darwin*|aarch64-darwin*|x86_64-darwin*], [
- RJIT_TARGET_OK=yes
- ],
- [arm64-*linux*|aarch64-*linux*|x86_64-*linux*], [
- RJIT_TARGET_OK=yes
- ],
- [arm64-*bsd*|aarch64-*bsd*|x86_64-*bsd*], [
- RJIT_TARGET_OK=yes
- ]
+ZJIT_LIBS=
+AS_CASE(["${ZJIT_SUPPORT}"],
+[yes|dev|dev_nodebug|stats], [
+ AS_IF([test x"$RUSTC" = "xno"],
+ AC_MSG_ERROR([rustc is required. Installation instructions available at https://www.rust-lang.org/tools/install])
)
-)
-
-dnl Build RJIT on supported platforms or if --enable-rjit is specified.
-AC_ARG_ENABLE(rjit,
- AS_HELP_STRING([--enable-rjit],
- [enable pure-Ruby JIT compiler. enabled by default on Unix x86_64 platforms]),
- [RJIT_SUPPORT=$enableval],
- [AS_CASE(["$RJIT_TARGET_OK"],
- [yes], [RJIT_SUPPORT=yes],
- [RJIT_SUPPORT=no]
- )]
-)
-AS_CASE(["$RJIT_SUPPORT"],
-[yes|dev], [
- AS_CASE(["$RJIT_SUPPORT"],
+ AS_CASE(["${ZJIT_SUPPORT}"],
+ [yes], [
+ ],
[dev], [
- # Link libcapstone for --rjit-dump-disasm
- AC_CHECK_LIB([capstone], [cs_disasm])
+ rb_cargo_features="$rb_cargo_features,disasm,runtime_checks"
+ JIT_CARGO_SUPPORT=dev
+ AC_DEFINE(RUBY_DEBUG, 1)
+ ],
+ [dev_nodebug], [
+ rb_cargo_features="$rb_cargo_features,disasm"
+ JIT_CARGO_SUPPORT=dev_nodebug
+ AC_DEFINE(ZJIT_STATS, 1)
+ ],
+ [stats], [
+ JIT_CARGO_SUPPORT=stats
+ AC_DEFINE(ZJIT_STATS, 1)
])
- AC_DEFINE(USE_RJIT, 1)
+ ZJIT_LIBS="target/release/libzjit.a"
+ RUST_LIB='$(ZJIT_LIBS)'
+ ZJIT_OBJ='zjit.$(OBJEXT)'
+ JIT_OBJ='jit.$(OBJEXT)'
+ AS_IF([test x"$ZJIT_SUPPORT" != "xyes" ], [
+ AC_DEFINE_UNQUOTED(ZJIT_SUPPORT, [$ZJIT_SUPPORT])
+ ])
+ AC_DEFINE(USE_ZJIT, 1)
], [
- AC_DEFINE(USE_RJIT, 0)
+ AC_DEFINE(USE_ZJIT, 0)
+])
+
+RUSTC_FLAGS='-g -C lto=thin -C opt-level=3 -C overflow-checks=on'
+AS_IF([test -n "${rustc_flags}"], [
+ RUSTC_FLAGS="${RUSTC_FLAGS} ${rustc_flags}"
+])
+
+JIT_RUST_FLAGS='--crate-type=staticlib --cfg feature=\"stats_allocator\"'
+RLIB_DIR=
+AS_CASE(["$JIT_CARGO_SUPPORT:$YJIT_SUPPORT:$ZJIT_SUPPORT"],
+[no:yes:yes], [ # release build of YJIT+ZJIT
+ YJIT_LIBS=
+ ZJIT_LIBS=
+ JIT_RUST_FLAGS="--crate-type=rlib"
+ RLIB_DIR="target/release"
+ RUST_LIB="target/release/libruby.a"
+],
+[no:*], [],
+[ # JIT_CARGO_SUPPORT not "no" -- cargo required.
+ AC_CHECK_TOOL(CARGO, [cargo], [no])
+ AS_IF([test x"$CARGO" = "xno"],
+ AC_MSG_ERROR([this build configuration requires cargo. Installation instructions available at https://www.rust-lang.org/tools/install]))
+
+ YJIT_LIBS=
+ ZJIT_LIBS=
+
+ # There's more processing below to get the feature set for the
+ # top-level crate, so capture at this point for feature set of
+ # just the zjit crate.
+ ZJIT_TEST_FEATURES="${rb_cargo_features}"
+
+ AS_IF([test x"${YJIT_SUPPORT}" != x"no"], [
+ rb_cargo_features="$rb_cargo_features,yjit"
+ ])
+ AS_IF([test x"${ZJIT_SUPPORT}" != x"no"], [
+ AC_SUBST(ZJIT_TEST_FEATURES)
+ rb_cargo_features="$rb_cargo_features,zjit"
+ ])
+ # if YJIT and ZJIT release mode
+ AS_IF([test "${YJIT_SUPPORT}:${ZJIT_SUPPORT}" = "yes:yes"], [
+ JIT_CARGO_SUPPORT=release
+ ])
+ CARGO_BUILD_ARGS="--profile ${JIT_CARGO_SUPPORT} --features ${rb_cargo_features}"
+ AS_IF([test "${JIT_CARGO_SUPPORT}" = "dev"], [
+ RUST_LIB="target/debug/libruby.a"
+ ], [
+ RUST_LIB="target/${JIT_CARGO_SUPPORT}/libruby.a"
+ ])
+])
+
+# In case either we're linking rust code
+AS_IF([test -n "$RUST_LIB"], [
+ AS_CASE(["$target_os"],[openbsd*],[
+ # Link libc++abi (which requires libpthread) for _Unwind_* functions needed by rust stdlib
+ LDFLAGS="$LDFLAGS -lpthread -lc++abi"
+ ])
+
+ # absolute path to stop the "target" dir in src dir from interfering through VPATH
+ RUST_LIB="$(pwd)/${RUST_LIB}"
])
-AC_SUBST(RJIT_SUPPORT)
+dnl These variables end up in ::RbConfig::CONFIG
+AC_SUBST(RUSTC)dnl Rust compiler command
+AC_SUBST(JIT_RUST_FLAGS)dnl the common rustc flags for JIT crates such as zjit
+AC_SUBST(RUSTC_FLAGS)dnl user-configurable rustc compiler flags
+AC_SUBST(CARGO)dnl Cargo command for Rust builds
+AC_SUBST(CARGO_BUILD_ARGS)dnl for selecting Rust build profiles
+AC_SUBST(YJIT_SUPPORT)dnl what flavor of YJIT the Ruby build includes
+AC_SUBST(YJIT_LIBS)dnl the .a library of YJIT
+AC_SUBST(YJIT_OBJ)dnl for optionally building the C parts of YJIT
+AC_SUBST(ZJIT_SUPPORT)dnl what flavor of ZJIT the Ruby build includes
+AC_SUBST(ZJIT_LIBS)dnl path to the .a library of ZJIT
+AC_SUBST(ZJIT_OBJ)dnl for optionally building the C parts of ZJIT
+AC_SUBST(JIT_OBJ)dnl for optionally building C glue code for Rust FFI
+AC_SUBST(RUST_LIB)dnl path to the rust .a library that contains either or both JITs
+AC_SUBST(RLIB_DIR)dnl subpath of build directory for .rlib files
+AC_SUBST(JIT_CARGO_SUPPORT)dnl "no" or the cargo profile of the rust code
}
[begin]_group "build section" && {
@@ -4002,7 +4146,9 @@ AC_CACHE_CHECK([for prefix of external symbols], rb_cv_symbol_prefix, [
SYMBOL_PREFIX="$rb_cv_symbol_prefix"
test "x$SYMBOL_PREFIX" = xNONE && SYMBOL_PREFIX=''
-AS_IF([test x"$enable_shared" = xyes], [
+AS_IF([test x"$SOEXT" = xdll], [
+ # DLL on Windows is managed by win32/mkexports.rb
+], [test x"$enable_shared" = xyes], [
AC_CACHE_CHECK([for default symbols in empty shared library], rb_cv_symbols_in_emptylib, [
save_CC="$CC"
eval CC=\"`printf "%s" "${DLDSHARED}" | sed ['s/\$(CC)/${CC}/']`\"
@@ -4032,7 +4178,8 @@ AS_CASE(["$target_os"],
RUBY_APPEND_OPTION(CFLAGS, -pipe)
],
[darwin*], [
- RUBY_APPEND_OPTION(CFLAGS, -pipe)
+ RUBY_TRY_CFLAGS(-pipe, [pipe_opt=yes], [pipe_opt=no])
+ AS_IF([test $pipe_opt = yes], [RUBY_APPEND_OPTION(CFLAGS, -pipe)])
AC_MSG_CHECKING([whether Security framework is needed])
AC_COMPILE_IFELSE([
AC_LANG_BOOL_COMPILE_TRY([
@@ -4085,6 +4232,7 @@ enum {
[mingw*], [
AS_IF([test x"$enable_shared" = xyes], [
LIBRUBY_SO='$(RUBY_SO_NAME)'.dll
+ LIBRUBY_SONAME=''
LIBRUBY_DLDFLAGS="${LIBRUBY_DLDFLAGS}"' $(RUBYDEF)'
])
EXPORT_PREFIX=' '
@@ -4097,7 +4245,6 @@ enum {
PLATFORM_DIR=win32
])
LIBRUBY_ALIASES=''
- FIRSTMAKEFILE=GNUmakefile:cygwin/GNUmakefile.in
AS_IF([test x"$enable_shared" = xyes], [
LIBRUBY='lib$(RUBY_SO_NAME).dll.a'
], [
@@ -4107,7 +4254,6 @@ enum {
])
],
[wasi*], [
- FIRSTMAKEFILE=GNUmakefile:wasm/GNUmakefile.in
AC_LIBOBJ([wasm/missing])
AC_LIBOBJ([wasm/runtime])
AC_LIBOBJ([wasm/fiber])
@@ -4124,21 +4270,6 @@ AC_ARG_ENABLE(debug-env,
AS_HELP_STRING([--enable-debug-env], [enable RUBY_DEBUG environment variable]),
[AC_SUBST(ENABLE_DEBUG_ENV, yes)])
-AS_CASE(["$FIRSTMAKEFILE"], [*GNUmakefile:*], [gnumake=yes], [
- AC_MSG_CHECKING([if ${MAKE-make} is GNU make])
- mkdir conftest.dir
- echo "all:; @echo yes" > conftest.dir/GNUmakefile
- echo "all:; @echo no" > conftest.dir/Makefile
- gnumake=`(cd conftest.dir; ${MAKE-make})`
- rm -fr conftest.dir
- AS_CASE(["$gnumake"],
- [*yes*], [
- FIRSTMAKEFILE=GNUmakefile:template/GNUmakefile.in
- gnumake=yes],
- [
- gnumake=no])
- AC_MSG_RESULT($gnumake)
-])
AS_IF([test "$gnumake" = yes], [ NULLCMD=: ], [
AC_MSG_CHECKING([for safe null command for ${MAKE-make}])
mkdir conftest.dir
@@ -4222,15 +4353,34 @@ AS_IF([test "${ARCH_FLAG}"], [
CXXFLAGS=`echo "$CXXFLAGS" | sed "s| *$archflagpat"'||'`
LDFLAGS=`echo "$LDFLAGS" | sed "s| *$archflagpat"'||'`
])
+AS_CASE([" $rb_cv_warnflags "], [*" -Wshorten-64-to-32 "*|*" -Werror=shorten-64-to-32 "*], [
+ voidp_ll=
+ AS_CASE([$ac_cv_sizeof_voidp],
+ [SIZEOF_LONG_LONG], [voidp_ll=true],
+ [@<:@0-9@:>@*], [
+ AS_IF([test $ac_cv_sizeof_voidp -gt $ac_cv_sizeof_long], [voidp_ll=true])
+ ])
+ AS_IF([test "$voidp_ll"], [
+ # Disable the shorten-64-to-32 warning for now, because it currently
+ # generates a lot of warnings on platforms where `sizeof(void*)` is
+ # larger than `sizeof(long)`.
+ #
+ # TODO: Replace `long` with `ptrdiff_t` or something in the all sources.
+ rb_cv_warnflags=`echo "$rb_cv_warnflags" |
+ sed -e 's/ -W\(shorten-64-to-32 \)/ -Wno-\1/' \
+ -e 's/ -Werror=\(shorten-64-to-32 \)/ -Wno-\1/'`
+ ])
+])
rb_cv_warnflags=`echo "$rb_cv_warnflags" | sed 's/^ *//;s/ *$//'`
warnflags="$rb_cv_warnflags"
AC_SUBST(cppflags)dnl
-AC_SUBST(cflags, ["${orig_cflags:+$orig_cflags }"'${optflags} ${debugflags} ${warnflags}'])dnl
+AC_SUBST(cflags, ['${hardenflags} '"${orig_cflags:+$orig_cflags }"' ${optflags} ${debugflags} ${warnflags}'])dnl
AC_SUBST(cxxflags)dnl
AC_SUBST(optflags)dnl
AC_SUBST(debugflags)dnl
AC_SUBST(warnflags)dnl
AC_SUBST(strict_warnflags)dnl
+AC_SUBST(hardenflags)dnl
AC_SUBST(XCFLAGS)dnl
AC_SUBST(XLDFLAGS)dnl
AC_SUBST(EXTLDFLAGS)dnl
@@ -4263,7 +4413,6 @@ AC_SUBST(MINIOBJS)
AC_SUBST(THREAD_MODEL)
AC_SUBST(COROUTINE_TYPE, ${coroutine_type})
AC_SUBST(PLATFORM_DIR)
-AC_SUBST(USE_LLVM_WINDRES)
firstmf=`echo $FIRSTMAKEFILE | sed 's/:.*//'`
firsttmpl=`echo $FIRSTMAKEFILE | sed 's/.*://'`
@@ -4516,6 +4665,17 @@ AS_IF([test x"$enable_rubygems" = xno], [
])
AC_SUBST(USE_RUBYGEMS)
+m4_define(available_parsers, [parse.y, prism])
+AC_ARG_WITH(parser,
+ AS_HELP_STRING([--with-parser=PARSER],
+ [specify default parser; PARSER is one of ]m4_join([, ],available_parsers)),
+ [], [with_parser=prism])
+AS_CASE([$with_parser],
+m4_foreach(parser, [available_parsers],
+ parser[,][AC_DEFINE_UNQUOTED(RB_DEFAULT_PARSER, RB_DEFAULT_PARSER_[]AS_TR_CPP(parser)),])
+ [AC_MSG_ERROR([Unknown parser: $with_parser])]
+)
+
arch_hdrdir="${EXTOUT}/include/${arch}/ruby"
AS_MKDIR_P("${arch_hdrdir}")
config_h="${arch_hdrdir}/config.h"
@@ -4602,8 +4762,12 @@ AC_CONFIG_FILES(Makefile:template/Makefile.in, [
sed '/^MISSING/s/\$U\././g;/^VCS *=/s#@VCS@#'"$VCS"'#;/^VCSUP *=/s#@VCSUP@#'"$VCSUP"'#' Makefile
echo; test x"$EXEEXT" = x || echo 'miniruby: miniruby$(EXEEXT)'
AS_IF([test "$gnumake" != yes], [
- echo ['$(MKFILES): $(srcdir)/common.mk']
- sed ['s/{\$([^(){}]*)[^{}]*}//g'] ${srcdir}/common.mk
+ # extract NMake-style include list
+ set = `sed -n 's/^!include *//p' ${srcdir}/common.mk`
+ echo common_mk_includes "@S|@*" # generate the macro assignment
+ shift
+ common_mk_includes="`echo \"@S|@*\" | sed 's|\$(srcdir)|.|g'`"
+ (PWD= cd ${srcdir} && sed -f tool/prereq.status common.mk ${common_mk_includes})
AS_IF([test "$YJIT_SUPPORT" = yes], [
cat ${srcdir}/yjit/not_gmake.mk
echo ['$(MKFILES): ${srcdir}/yjit/not_gmake.mk']
@@ -4614,20 +4778,7 @@ AC_CONFIG_FILES(Makefile:template/Makefile.in, [
echo; echo '$(srcdir)/$(CONFIGURE):RUBY_M4_INCLUDED \
$(empty)'
- } > $tmpmk && AS_IF([! grep '^ruby:' $tmpmk > /dev/null], [
- AS_IF([test "${gnumake}" = yes], [
- tmpgmk=confgmk$$.tmp
- {
- echo "include $tmpmk"
- echo "-include uncommon.mk"
- } > $tmpgmk
- ], [
- tmpgmk=$tmpmk
- ]) &&
- test -z "`${MAKE-make} -f $tmpgmk info-program | grep '^PROGRAM=ruby$'`" &&
- echo 'ruby: $(PROGRAM);' >> $tmpmk
- test "$tmpmk" = "$tmpgmk" || rm -f "$tmpgmk"
- ]) && mv -f $tmpmk Makefile],
+ } > $tmpmk && mv -f $tmpmk Makefile],
[EXEEXT='$EXEEXT' MAKE='${MAKE-make}' gnumake='$gnumake' GIT='$GIT' YJIT_SUPPORT='$YJIT_SUPPORT'])
AC_ARG_WITH([ruby-pc],
@@ -4642,6 +4793,11 @@ AC_ARG_WITH(destdir,
[DESTDIR="$withval"])
AC_SUBST(DESTDIR)
+AS_IF([test "x$load_relative:$DESTDIR" = xyes:], [
+ AS_IF([test "x$prefix" = xNONE], [DESTDIR="$ac_default_prefix"], [DESTDIR="$prefix"])
+ prefix=/.
+])
+
AC_OUTPUT
}
@@ -4680,7 +4836,7 @@ config_summary "target OS" "$target_os"
config_summary "compiler" "$CC"
config_summary "with thread" "$THREAD_MODEL"
config_summary "with coroutine" "$coroutine_type"
-config_summary "with shared GC" "$with_shared_gc"
+config_summary "with modular GC" "$modular_gc_summary"
config_summary "enable shared libs" "$ENABLE_SHARED"
config_summary "dynamic library ext" "$DLEXT"
config_summary "CFLAGS" "$cflags"
@@ -4690,10 +4846,12 @@ config_summary "DLDFLAGS" "$DLDFLAGS"
config_summary "optflags" "$optflags"
config_summary "debugflags" "$debugflags"
config_summary "warnflags" "$warnflags"
+config_summary "hardenflags" "$hardenflags"
config_summary "strip command" "$STRIP"
config_summary "install doc" "$DOCTARGETS"
config_summary "YJIT support" "$YJIT_SUPPORT"
-config_summary "RJIT support" "$RJIT_SUPPORT"
+config_summary "ZJIT support" "$ZJIT_SUPPORT"
+config_summary "RUSTC_FLAGS" "$RUSTC_FLAGS"
config_summary "man page type" "$MANTYPE"
config_summary "search path" "$search_path"
config_summary "static-linked-ext" ${EXTSTATIC:+"yes"}
diff --git a/cont.c b/cont.c
index 8f222dfef8..8af093a316 100644
--- a/cont.c
+++ b/cont.c
@@ -30,12 +30,12 @@ extern int madvise(caddr_t, size_t, int);
#include "internal/cont.h"
#include "internal/thread.h"
#include "internal/error.h"
+#include "internal/eval.h"
#include "internal/gc.h"
#include "internal/proc.h"
#include "internal/sanitizers.h"
#include "internal/warnings.h"
#include "ruby/fiber/scheduler.h"
-#include "rjit.h"
#include "yjit.h"
#include "vm_core.h"
#include "vm_sync.h"
@@ -48,7 +48,8 @@ static const int DEBUG = 0;
#define RB_PAGE_MASK (~(RB_PAGE_SIZE - 1))
static long pagesize;
-static const rb_data_type_t cont_data_type, fiber_data_type;
+static const rb_data_type_t rb_cont_data_type;
+static const rb_data_type_t rb_fiber_data_type;
static VALUE rb_cContinuation;
static VALUE rb_cFiber;
static VALUE rb_eFiberError;
@@ -226,7 +227,6 @@ typedef struct rb_context_struct {
} machine;
rb_execution_context_t saved_ec;
rb_jmpbuf_t jmpbuf;
- rb_ensure_entry_t *ensure_array;
struct rb_jit_cont *jit_cont; // Continuation contexts for JITs
} rb_context_t;
@@ -278,7 +278,12 @@ static struct fiber_pool shared_fiber_pool = {NULL, NULL, 0, 0, 0, 0};
void
rb_free_shared_fiber_pool(void)
{
- xfree(shared_fiber_pool.allocations);
+ struct fiber_pool_allocation *allocations = shared_fiber_pool.allocations;
+ while (allocations) {
+ struct fiber_pool_allocation *next = allocations->next;
+ xfree(allocations);
+ allocations = next;
+ }
}
static ID fiber_initialize_keywords[3] = {0};
@@ -476,18 +481,20 @@ fiber_pool_allocate_memory(size_t * count, size_t stride)
}
#else
errno = 0;
- void * base = mmap(NULL, (*count)*stride, PROT_READ | PROT_WRITE, FIBER_STACK_FLAGS, -1, 0);
+ size_t mmap_size = (*count)*stride;
+ void * base = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, FIBER_STACK_FLAGS, -1, 0);
if (base == MAP_FAILED) {
// If the allocation fails, count = count / 2, and try again.
*count = (*count) >> 1;
}
else {
+ ruby_annotate_mmap(base, mmap_size, "Ruby:fiber_pool_allocate_memory");
#if defined(MADV_FREE_REUSE)
// On Mac MADV_FREE_REUSE is necessary for the task_info api
// to keep the accounting accurate as possible when a page is marked as reusable
// it can possibly not occurring at first call thus re-iterating if necessary.
- while (madvise(base, (*count)*stride, MADV_FREE_REUSE) == -1 && errno == EAGAIN);
+ while (madvise(base, mmap_size, MADV_FREE_REUSE) == -1 && errno == EAGAIN);
#endif
return base;
}
@@ -504,80 +511,87 @@ fiber_pool_allocate_memory(size_t * count, size_t stride)
static struct fiber_pool_allocation *
fiber_pool_expand(struct fiber_pool * fiber_pool, size_t count)
{
- STACK_GROW_DIR_DETECTION;
+ struct fiber_pool_allocation * allocation;
+ RB_VM_LOCK_ENTER();
+ {
+ STACK_GROW_DIR_DETECTION;
- size_t size = fiber_pool->size;
- size_t stride = size + RB_PAGE_SIZE;
+ size_t size = fiber_pool->size;
+ size_t stride = size + RB_PAGE_SIZE;
- // Allocate the memory required for the stacks:
- void * base = fiber_pool_allocate_memory(&count, stride);
+ // Allocate the memory required for the stacks:
+ void * base = fiber_pool_allocate_memory(&count, stride);
- if (base == NULL) {
- rb_raise(rb_eFiberError, "can't alloc machine stack to fiber (%"PRIuSIZE" x %"PRIuSIZE" bytes): %s", count, size, ERRNOMSG);
- }
+ if (base == NULL) {
+ rb_raise(rb_eFiberError, "can't alloc machine stack to fiber (%"PRIuSIZE" x %"PRIuSIZE" bytes): %s", count, size, ERRNOMSG);
+ }
- struct fiber_pool_vacancy * vacancies = fiber_pool->vacancies;
- struct fiber_pool_allocation * allocation = RB_ALLOC(struct fiber_pool_allocation);
+ struct fiber_pool_vacancy * vacancies = fiber_pool->vacancies;
+ allocation = RB_ALLOC(struct fiber_pool_allocation);
- // Initialize fiber pool allocation:
- allocation->base = base;
- allocation->size = size;
- allocation->stride = stride;
- allocation->count = count;
+ // Initialize fiber pool allocation:
+ allocation->base = base;
+ allocation->size = size;
+ allocation->stride = stride;
+ allocation->count = count;
#ifdef FIBER_POOL_ALLOCATION_FREE
- allocation->used = 0;
+ allocation->used = 0;
#endif
- allocation->pool = fiber_pool;
-
- if (DEBUG) {
- fprintf(stderr, "fiber_pool_expand(%"PRIuSIZE"): %p, %"PRIuSIZE"/%"PRIuSIZE" x [%"PRIuSIZE":%"PRIuSIZE"]\n",
- count, (void*)fiber_pool, fiber_pool->used, fiber_pool->count, size, fiber_pool->vm_stack_size);
- }
+ allocation->pool = fiber_pool;
- // Iterate over all stacks, initializing the vacancy list:
- for (size_t i = 0; i < count; i += 1) {
- void * base = (char*)allocation->base + (stride * i);
- void * page = (char*)base + STACK_DIR_UPPER(size, 0);
+ if (DEBUG) {
+ fprintf(stderr, "fiber_pool_expand(%"PRIuSIZE"): %p, %"PRIuSIZE"/%"PRIuSIZE" x [%"PRIuSIZE":%"PRIuSIZE"]\n",
+ count, (void*)fiber_pool, fiber_pool->used, fiber_pool->count, size, fiber_pool->vm_stack_size);
+ }
+ // Iterate over all stacks, initializing the vacancy list:
+ for (size_t i = 0; i < count; i += 1) {
+ void * base = (char*)allocation->base + (stride * i);
+ void * page = (char*)base + STACK_DIR_UPPER(size, 0);
#if defined(_WIN32)
- DWORD old_protect;
+ DWORD old_protect;
- if (!VirtualProtect(page, RB_PAGE_SIZE, PAGE_READWRITE | PAGE_GUARD, &old_protect)) {
- VirtualFree(allocation->base, 0, MEM_RELEASE);
- rb_raise(rb_eFiberError, "can't set a guard page: %s", ERRNOMSG);
- }
+ if (!VirtualProtect(page, RB_PAGE_SIZE, PAGE_READWRITE | PAGE_GUARD, &old_protect)) {
+ VirtualFree(allocation->base, 0, MEM_RELEASE);
+ rb_raise(rb_eFiberError, "can't set a guard page: %s", ERRNOMSG);
+ }
+#elif defined(__wasi__)
+ // wasi-libc's mprotect emulation doesn't support PROT_NONE.
+ (void)page;
#else
- if (mprotect(page, RB_PAGE_SIZE, PROT_NONE) < 0) {
- munmap(allocation->base, count*stride);
- rb_raise(rb_eFiberError, "can't set a guard page: %s", ERRNOMSG);
- }
+ if (mprotect(page, RB_PAGE_SIZE, PROT_NONE) < 0) {
+ munmap(allocation->base, count*stride);
+ rb_raise(rb_eFiberError, "can't set a guard page: %s", ERRNOMSG);
+ }
#endif
- vacancies = fiber_pool_vacancy_initialize(
- fiber_pool, vacancies,
- (char*)base + STACK_DIR_UPPER(0, RB_PAGE_SIZE),
- size
- );
+ vacancies = fiber_pool_vacancy_initialize(
+ fiber_pool, vacancies,
+ (char*)base + STACK_DIR_UPPER(0, RB_PAGE_SIZE),
+ size
+ );
#ifdef FIBER_POOL_ALLOCATION_FREE
- vacancies->stack.allocation = allocation;
+ vacancies->stack.allocation = allocation;
#endif
- }
+ }
- // Insert the allocation into the head of the pool:
- allocation->next = fiber_pool->allocations;
+ // Insert the allocation into the head of the pool:
+ allocation->next = fiber_pool->allocations;
#ifdef FIBER_POOL_ALLOCATION_FREE
- if (allocation->next) {
- allocation->next->previous = allocation;
- }
+ if (allocation->next) {
+ allocation->next->previous = allocation;
+ }
- allocation->previous = NULL;
+ allocation->previous = NULL;
#endif
- fiber_pool->allocations = allocation;
- fiber_pool->vacancies = vacancies;
- fiber_pool->count += count;
+ fiber_pool->allocations = allocation;
+ fiber_pool->vacancies = vacancies;
+ fiber_pool->count += count;
+ }
+ RB_VM_LOCK_LEAVE();
return allocation;
}
@@ -651,41 +665,46 @@ fiber_pool_allocation_free(struct fiber_pool_allocation * allocation)
static struct fiber_pool_stack
fiber_pool_stack_acquire(struct fiber_pool * fiber_pool)
{
- struct fiber_pool_vacancy * vacancy = fiber_pool_vacancy_pop(fiber_pool);
+ struct fiber_pool_vacancy * vacancy ;
+ RB_VM_LOCK_ENTER();
+ {
+ vacancy = fiber_pool_vacancy_pop(fiber_pool);
- if (DEBUG) fprintf(stderr, "fiber_pool_stack_acquire: %p used=%"PRIuSIZE"\n", (void*)fiber_pool->vacancies, fiber_pool->used);
+ if (DEBUG) fprintf(stderr, "fiber_pool_stack_acquire: %p used=%"PRIuSIZE"\n", (void*)fiber_pool->vacancies, fiber_pool->used);
- if (!vacancy) {
- const size_t maximum = FIBER_POOL_ALLOCATION_MAXIMUM_SIZE;
- const size_t minimum = fiber_pool->initial_count;
+ if (!vacancy) {
+ const size_t maximum = FIBER_POOL_ALLOCATION_MAXIMUM_SIZE;
+ const size_t minimum = fiber_pool->initial_count;
- size_t count = fiber_pool->count;
- if (count > maximum) count = maximum;
- if (count < minimum) count = minimum;
+ size_t count = fiber_pool->count;
+ if (count > maximum) count = maximum;
+ if (count < minimum) count = minimum;
- fiber_pool_expand(fiber_pool, count);
+ fiber_pool_expand(fiber_pool, count);
- // The free list should now contain some stacks:
- VM_ASSERT(fiber_pool->vacancies);
+ // The free list should now contain some stacks:
+ VM_ASSERT(fiber_pool->vacancies);
- vacancy = fiber_pool_vacancy_pop(fiber_pool);
- }
+ vacancy = fiber_pool_vacancy_pop(fiber_pool);
+ }
- VM_ASSERT(vacancy);
- VM_ASSERT(vacancy->stack.base);
+ VM_ASSERT(vacancy);
+ VM_ASSERT(vacancy->stack.base);
#if defined(COROUTINE_SANITIZE_ADDRESS)
- __asan_unpoison_memory_region(fiber_pool_stack_poison_base(&vacancy->stack), fiber_pool_stack_poison_size(&vacancy->stack));
+ __asan_unpoison_memory_region(fiber_pool_stack_poison_base(&vacancy->stack), fiber_pool_stack_poison_size(&vacancy->stack));
#endif
- // Take the top item from the free list:
- fiber_pool->used += 1;
+ // Take the top item from the free list:
+ fiber_pool->used += 1;
#ifdef FIBER_POOL_ALLOCATION_FREE
- vacancy->stack.allocation->used += 1;
+ vacancy->stack.allocation->used += 1;
#endif
- fiber_pool_stack_reset(&vacancy->stack);
+ fiber_pool_stack_reset(&vacancy->stack);
+ }
+ RB_VM_LOCK_LEAVE();
return vacancy->stack;
}
@@ -821,6 +840,10 @@ fiber_restore_thread(rb_thread_t *th, rb_fiber_t *fiber)
VM_ASSERT(th->ec->fiber_ptr == fiber);
}
+#ifndef COROUTINE_DECL
+# define COROUTINE_DECL COROUTINE
+#endif
+NORETURN(static COROUTINE_DECL fiber_entry(struct coroutine_context * from, struct coroutine_context * to));
static COROUTINE
fiber_entry(struct coroutine_context * from, struct coroutine_context * to)
{
@@ -898,6 +921,17 @@ fiber_stack_release(rb_fiber_t * fiber)
rb_ec_clear_vm_stack(ec);
}
+static void
+fiber_stack_release_locked(rb_fiber_t *fiber)
+{
+ if (!ruby_vm_during_cleanup) {
+ // We can't try to acquire the VM lock here because MMTK calls free in its own native thread which has no ec.
+ // This assertion will fail on MMTK but we currently don't have CI for debug releases of MMTK, so we can assert for now.
+ ASSERT_vm_locking_with_barrier();
+ }
+ fiber_stack_release(fiber);
+}
+
static const char *
fiber_status_name(enum fiber_status s)
{
@@ -919,7 +953,9 @@ fiber_verify(const rb_fiber_t *fiber)
switch (fiber->status) {
case FIBER_RESUMED:
- VM_ASSERT(fiber->cont.saved_ec.vm_stack != NULL);
+ if (fiber->cont.saved_ec.thread_ptr->self == 0) {
+ VM_ASSERT(fiber->cont.saved_ec.vm_stack != NULL);
+ }
break;
case FIBER_SUSPENDED:
VM_ASSERT(fiber->cont.saved_ec.vm_stack != NULL);
@@ -949,7 +985,7 @@ cont_ptr(VALUE obj)
{
rb_context_t *cont;
- TypedData_Get_Struct(obj, rb_context_t, &cont_data_type, cont);
+ TypedData_Get_Struct(obj, rb_context_t, &rb_cont_data_type, cont);
return cont;
}
@@ -959,7 +995,7 @@ fiber_ptr(VALUE obj)
{
rb_fiber_t *fiber;
- TypedData_Get_Struct(obj, rb_fiber_t, &fiber_data_type, fiber);
+ TypedData_Get_Struct(obj, rb_fiber_t, &rb_fiber_data_type, fiber);
if (!fiber) rb_raise(rb_eFiberError, "uninitialized fiber");
return fiber;
@@ -1053,13 +1089,12 @@ cont_free(void *ptr)
if (cont->type == CONTINUATION_CONTEXT) {
ruby_xfree(cont->saved_ec.vm_stack);
- ruby_xfree(cont->ensure_array);
RUBY_FREE_UNLESS_NULL(cont->machine.stack);
}
else {
rb_fiber_t *fiber = (rb_fiber_t*)cont;
coroutine_destroy(&fiber->context);
- fiber_stack_release(fiber);
+ fiber_stack_release_locked(fiber);
}
RUBY_FREE_UNLESS_NULL(cont->saved_vm_stack.ptr);
@@ -1108,12 +1143,7 @@ rb_fiber_update_self(rb_fiber_t *fiber)
void
rb_fiber_mark_self(const rb_fiber_t *fiber)
{
- if (fiber->cont.self) {
- rb_gc_mark_movable(fiber->cont.self);
- }
- else {
- rb_execution_context_mark(&fiber->cont.saved_ec);
- }
+ rb_gc_mark_movable(fiber->cont.self);
}
static void
@@ -1179,7 +1209,7 @@ fiber_memsize(const void *ptr)
VALUE
rb_obj_is_fiber(VALUE obj)
{
- return RBOOL(rb_typeddata_is_kind_of(obj, &fiber_data_type));
+ return RBOOL(rb_typeddata_is_kind_of(obj, &rb_fiber_data_type));
}
static void
@@ -1210,9 +1240,23 @@ cont_save_machine_stack(rb_thread_t *th, rb_context_t *cont)
MEMCPY(cont->machine.stack, cont->machine.stack_src, VALUE, size);
}
-static const rb_data_type_t cont_data_type = {
+static void
+cont_handle_weak_references(void *ptr)
+{
+ rb_context_t *cont = ptr;
+
+ if (!cont) return;
+
+ if (!rb_gc_handle_weak_references_alive_p(cont->saved_ec.gen_fields_cache.obj) ||
+ !rb_gc_handle_weak_references_alive_p(cont->saved_ec.gen_fields_cache.fields_obj)) {
+ cont->saved_ec.gen_fields_cache.obj = Qundef;
+ cont->saved_ec.gen_fields_cache.fields_obj = Qundef;
+ }
+}
+
+static const rb_data_type_t rb_cont_data_type = {
"continuation",
- {cont_mark, cont_free, cont_memsize, cont_compact},
+ {cont_mark, cont_free, cont_memsize, cont_compact, cont_handle_weak_references},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};
@@ -1372,7 +1416,8 @@ cont_new(VALUE klass)
rb_thread_t *th = GET_THREAD();
THREAD_MUST_BE_RUNNING(th);
- contval = TypedData_Make_Struct(klass, rb_context_t, &cont_data_type, cont);
+ contval = TypedData_Make_Struct(klass, rb_context_t, &rb_cont_data_type, cont);
+ rb_gc_declare_weak_references(contval);
cont->self = contval;
cont_init(cont, th);
return cont;
@@ -1458,22 +1503,6 @@ cont_capture(volatile int *volatile stat)
VM_ASSERT(cont->saved_ec.cfp != NULL);
cont_save_machine_stack(th, cont);
- /* backup ensure_list to array for search in another context */
- {
- rb_ensure_list_t *p;
- int size = 0;
- rb_ensure_entry_t *entry;
- for (p=th->ec->ensure_list; p; p=p->next)
- size++;
- entry = cont->ensure_array = ALLOC_N(rb_ensure_entry_t,size+1);
- for (p=th->ec->ensure_list; p; p=p->next) {
- if (!p->entry.marker)
- p->entry.marker = rb_ary_hidden_new(0); /* dummy object */
- *entry++ = p->entry;
- }
- entry->marker = 0;
- }
-
if (ruby_setjmp(cont->jmpbuf)) {
VALUE value;
@@ -1516,6 +1545,51 @@ cont_restore_thread(rb_context_t *cont)
rb_raise(rb_eRuntimeError, "can't call across trace_func");
}
+#if defined(__wasm__) && !defined(__EMSCRIPTEN__)
+ if (th->ec->tag != sec->tag) {
+ /* find the lowest common ancestor tag of the current EC and the saved EC */
+
+ struct rb_vm_tag *lowest_common_ancestor = NULL;
+ size_t num_tags = 0;
+ size_t num_saved_tags = 0;
+ for (struct rb_vm_tag *tag = th->ec->tag; tag != NULL; tag = tag->prev) {
+ ++num_tags;
+ }
+ for (struct rb_vm_tag *tag = sec->tag; tag != NULL; tag = tag->prev) {
+ ++num_saved_tags;
+ }
+
+ size_t min_tags = num_tags <= num_saved_tags ? num_tags : num_saved_tags;
+
+ struct rb_vm_tag *tag = th->ec->tag;
+ while (num_tags > min_tags) {
+ tag = tag->prev;
+ --num_tags;
+ }
+
+ struct rb_vm_tag *saved_tag = sec->tag;
+ while (num_saved_tags > min_tags) {
+ saved_tag = saved_tag->prev;
+ --num_saved_tags;
+ }
+
+ while (min_tags > 0) {
+ if (tag == saved_tag) {
+ lowest_common_ancestor = tag;
+ break;
+ }
+ tag = tag->prev;
+ saved_tag = saved_tag->prev;
+ --min_tags;
+ }
+
+ /* free all the jump buffers between the current EC's tag and the lowest common ancestor tag */
+ for (struct rb_vm_tag *tag = th->ec->tag; tag != lowest_common_ancestor; tag = tag->prev) {
+ rb_vm_tag_jmpbuf_deinit(&tag->buf);
+ }
+ }
+#endif
+
/* copy vm stack */
#ifdef CAPTURE_JUST_VALID_VM_STACK
MEMCPY(th->ec->vm_stack,
@@ -1534,7 +1608,6 @@ cont_restore_thread(rb_context_t *cont)
th->ec->tag = sec->tag;
th->ec->root_lep = sec->root_lep;
th->ec->root_svar = sec->root_svar;
- th->ec->ensure_list = sec->ensure_list;
th->ec->errinfo = sec->errinfo;
VM_ASSERT(th->ec->vm_stack != NULL);
@@ -1603,9 +1676,9 @@ cont_restore_1(rb_context_t *cont)
cont_restore_thread(cont);
/* restore machine stack */
-#if defined(_M_AMD64) && !defined(__MINGW64__)
+#if (defined(_M_AMD64) && !defined(__MINGW64__)) || defined(_M_ARM64)
{
- /* workaround for x64 SEH */
+ /* workaround for x64 and arm64 SEH on Windows */
jmp_buf buf;
setjmp(buf);
_JUMP_BUFFER *bp = (void*)&cont->jmpbuf;
@@ -1797,80 +1870,6 @@ make_passing_arg(int argc, const VALUE *argv)
typedef VALUE e_proc(VALUE);
-/* CAUTION!! : Currently, error in rollback_func is not supported */
-/* same as rb_protect if set rollback_func to NULL */
-void
-ruby_register_rollback_func_for_ensure(e_proc *ensure_func, e_proc *rollback_func)
-{
- st_table **table_p = &GET_VM()->ensure_rollback_table;
- if (UNLIKELY(*table_p == NULL)) {
- *table_p = st_init_numtable();
- }
- st_insert(*table_p, (st_data_t)ensure_func, (st_data_t)rollback_func);
-}
-
-static inline e_proc *
-lookup_rollback_func(e_proc *ensure_func)
-{
- st_table *table = GET_VM()->ensure_rollback_table;
- st_data_t val;
- if (table && st_lookup(table, (st_data_t)ensure_func, &val))
- return (e_proc *) val;
- return (e_proc *) Qundef;
-}
-
-
-static inline void
-rollback_ensure_stack(VALUE self,rb_ensure_list_t *current,rb_ensure_entry_t *target)
-{
- rb_ensure_list_t *p;
- rb_ensure_entry_t *entry;
- size_t i, j;
- size_t cur_size;
- size_t target_size;
- size_t base_point;
- e_proc *func;
-
- cur_size = 0;
- for (p=current; p; p=p->next)
- cur_size++;
- target_size = 0;
- for (entry=target; entry->marker; entry++)
- target_size++;
-
- /* search common stack point */
- p = current;
- base_point = cur_size;
- while (base_point) {
- if (target_size >= base_point &&
- p->entry.marker == target[target_size - base_point].marker)
- break;
- base_point --;
- p = p->next;
- }
-
- /* rollback function check */
- for (i=0; i < target_size - base_point; i++) {
- if (!lookup_rollback_func(target[i].e_proc)) {
- rb_raise(rb_eRuntimeError, "continuation called from out of critical rb_ensure scope");
- }
- }
- /* pop ensure stack */
- while (cur_size > base_point) {
- /* escape from ensure block */
- (*current->entry.e_proc)(current->entry.data2);
- current = current->next;
- cur_size--;
- }
- /* push ensure stack */
- for (j = 0; j < i; j++) {
- func = lookup_rollback_func(target[i - j - 1].e_proc);
- if (!UNDEF_P((VALUE)func)) {
- (*func)(target[i - j - 1].data2);
- }
- }
-}
-
NORETURN(static VALUE rb_cont_call(int argc, VALUE *argv, VALUE contval));
/*
@@ -1902,7 +1901,6 @@ rb_cont_call(int argc, VALUE *argv, VALUE contval)
rb_raise(rb_eRuntimeError, "continuation called across fiber");
}
}
- rollback_ensure_stack(contval, th->ec->ensure_list, cont->ensure_array);
cont->argc = argc;
cont->value = make_passing_arg(argc, argv);
@@ -1979,7 +1977,7 @@ rb_cont_call(int argc, VALUE *argv, VALUE contval)
* == Non-blocking Fibers
*
* The concept of <em>non-blocking fiber</em> was introduced in Ruby 3.0.
- * A non-blocking fiber, when reaching a operation that would normally block
+ * A non-blocking fiber, when reaching an operation that would normally block
* the fiber (like <code>sleep</code>, or wait for another process or I/O)
* will yield control to other fibers and allow the <em>scheduler</em> to
* handle blocking and waking up (resuming) this fiber when it can proceed.
@@ -1998,16 +1996,38 @@ rb_cont_call(int argc, VALUE *argv, VALUE contval)
*
*/
-static const rb_data_type_t fiber_data_type = {
+static void
+fiber_handle_weak_references(void *ptr)
+{
+ rb_fiber_t *fiber = ptr;
+
+ if (!fiber) return;
+
+ if (!rb_gc_handle_weak_references_alive_p(fiber->cont.saved_ec.gen_fields_cache.obj) ||
+ !rb_gc_handle_weak_references_alive_p(fiber->cont.saved_ec.gen_fields_cache.fields_obj)) {
+ fiber->cont.saved_ec.gen_fields_cache.obj = Qundef;
+ fiber->cont.saved_ec.gen_fields_cache.fields_obj = Qundef;
+ }
+}
+
+static const rb_data_type_t rb_fiber_data_type = {
"fiber",
- {fiber_mark, fiber_free, fiber_memsize, fiber_compact,},
+ {fiber_mark, fiber_free, fiber_memsize, fiber_compact, fiber_handle_weak_references},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};
static VALUE
fiber_alloc(VALUE klass)
{
- return TypedData_Wrap_Struct(klass, &fiber_data_type, 0);
+ VALUE obj = TypedData_Wrap_Struct(klass, &rb_fiber_data_type, 0);
+ rb_gc_declare_weak_references(obj);
+ return obj;
+}
+
+static rb_serial_t
+next_ec_serial(rb_ractor_t *cr)
+{
+ return cr->next_ec_serial++;
}
static rb_fiber_t*
@@ -2029,6 +2049,7 @@ fiber_t_alloc(VALUE fiber_value, unsigned int blocking)
cont_init(&fiber->cont, th);
fiber->cont.saved_ec.fiber_ptr = fiber;
+ fiber->cont.saved_ec.serial = next_ec_serial(th->ractor);
rb_ec_clear_vm_stack(&fiber->cont.saved_ec);
fiber->prev = NULL;
@@ -2042,32 +2063,10 @@ fiber_t_alloc(VALUE fiber_value, unsigned int blocking)
return fiber;
}
-static rb_fiber_t *
-root_fiber_alloc(rb_thread_t *th)
-{
- VALUE fiber_value = fiber_alloc(rb_cFiber);
- rb_fiber_t *fiber = th->ec->fiber_ptr;
-
- VM_ASSERT(DATA_PTR(fiber_value) == NULL);
- VM_ASSERT(fiber->cont.type == FIBER_CONTEXT);
- VM_ASSERT(FIBER_RESUMED_P(fiber));
-
- th->root_fiber = fiber;
- DATA_PTR(fiber_value) = fiber;
- fiber->cont.self = fiber_value;
-
- coroutine_initialize_main(&fiber->context);
-
- return fiber;
-}
-
static inline rb_fiber_t*
fiber_current(void)
{
rb_execution_context_t *ec = GET_EC();
- if (ec->fiber_ptr->cont.self == 0) {
- root_fiber_alloc(rb_ec_thread_ptr(ec));
- }
return ec->fiber_ptr;
}
@@ -2200,14 +2199,14 @@ rb_fiber_storage_set(VALUE self, VALUE value)
* Returns the value of the fiber storage variable identified by +key+.
*
* The +key+ must be a symbol, and the value is set by Fiber#[]= or
- * Fiber#store.
+ * Fiber#storage.
*
* See also Fiber::[]=.
*/
static VALUE
rb_fiber_storage_aref(VALUE class, VALUE key)
{
- Check_Type(key, T_SYMBOL);
+ key = rb_to_symbol(key);
VALUE storage = fiber_storage_get(fiber_current(), FALSE);
if (storage == Qnil) return Qnil;
@@ -2228,7 +2227,7 @@ rb_fiber_storage_aref(VALUE class, VALUE key)
static VALUE
rb_fiber_storage_aset(VALUE class, VALUE key, VALUE value)
{
- Check_Type(key, T_SYMBOL);
+ key = rb_to_symbol(key);
VALUE storage = fiber_storage_get(fiber_current(), value != Qnil);
if (storage == Qnil) return Qnil;
@@ -2573,17 +2572,32 @@ rb_threadptr_root_fiber_setup(rb_thread_t *th)
if (!fiber) {
rb_bug("%s", strerror(errno)); /* ... is it possible to call rb_bug here? */
}
+
fiber->cont.type = FIBER_CONTEXT;
fiber->cont.saved_ec.fiber_ptr = fiber;
+ fiber->cont.saved_ec.serial = next_ec_serial(th->ractor);
fiber->cont.saved_ec.thread_ptr = th;
fiber->blocking = 1;
fiber->killed = 0;
fiber_status_set(fiber, FIBER_RESUMED); /* skip CREATED */
+
+ coroutine_initialize_main(&fiber->context);
+
th->ec = &fiber->cont.saved_ec;
+
cont_init_jit_cont(&fiber->cont);
}
void
+rb_root_fiber_obj_setup(rb_thread_t *th)
+{
+ rb_fiber_t *fiber = th->ec->fiber_ptr;
+ VALUE fiber_value = fiber_alloc(rb_cFiber);
+ DATA_PTR(fiber_value) = fiber;
+ fiber->cont.self = fiber_value;
+}
+
+void
rb_threadptr_root_fiber_release(rb_thread_t *th)
{
if (th->root_fiber) {
@@ -2653,15 +2667,7 @@ rb_fiber_current(void)
static inline void
fiber_store(rb_fiber_t *next_fiber, rb_thread_t *th)
{
- rb_fiber_t *fiber;
-
- if (th->ec->fiber_ptr != NULL) {
- fiber = th->ec->fiber_ptr;
- }
- else {
- /* create root fiber */
- fiber = root_fiber_alloc(th);
- }
+ rb_fiber_t *fiber = th->ec->fiber_ptr;
if (FIBER_CREATED_P(next_fiber)) {
fiber_prepare_stack(next_fiber);
@@ -2697,7 +2703,9 @@ fiber_switch(rb_fiber_t *fiber, int argc, const VALUE *argv, int kw_splat, rb_fi
rb_thread_t *th = GET_THREAD();
/* make sure the root_fiber object is available */
- if (th->root_fiber == NULL) root_fiber_alloc(th);
+ if (th->root_fiber == NULL) {
+ th->root_fiber = th->ec->fiber_ptr;
+ }
if (th->ec->fiber_ptr == fiber) {
/* ignore fiber context switch
@@ -2763,7 +2771,9 @@ fiber_switch(rb_fiber_t *fiber, int argc, const VALUE *argv, int kw_splat, rb_fi
// 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);
+ RB_VM_LOCKING() {
+ fiber_stack_release(fiber);
+ }
}
#endif
@@ -2903,6 +2913,7 @@ void
rb_fiber_close(rb_fiber_t *fiber)
{
fiber_status_set(fiber, FIBER_TERMINATED);
+ rb_ec_close(&fiber->cont.saved_ec);
}
static void
@@ -3241,37 +3252,46 @@ fiber_raise(rb_fiber_t *fiber, VALUE exception)
}
VALUE
-rb_fiber_raise(VALUE fiber, int argc, const VALUE *argv)
+rb_fiber_raise(VALUE fiber, int argc, VALUE *argv)
{
- VALUE exception = rb_make_exception(argc, argv);
+ VALUE exception = rb_exception_setup(argc, argv);
return fiber_raise(fiber_ptr(fiber), exception);
}
/*
* call-seq:
- * fiber.raise -> obj
- * fiber.raise(string) -> obj
- * fiber.raise(exception [, string [, array]]) -> obj
+ * raise(exception, message = exception.to_s, backtrace = nil, cause: $!)
+ * raise(message = nil, cause: $!)
*
* 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
+ * +Fiber.yield+ was called.
+ *
+ * f = Fiber.new {
+ * puts "Before the yield"
+ * Fiber.yield 1 # -- exception will be raised here
+ * puts "After the yield"
+ * }
+ *
+ * p f.resume
+ * f.raise "Gotcha"
+ *
+ * Output
+ *
+ * Before the first yield
+ * 1
+ * t.rb:8:in 'Fiber.yield': Gotcha (RuntimeError)
+ * from t.rb:8:in 'block in <main>'
+ *
+ * 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 <code>begin...end</code>
- * blocks.
- *
* Raises +FiberError+ if called on a Fiber belonging to another +Thread+.
*
- * See Kernel#raise for more information.
+ * See Kernel#raise for more information on arguments.
+ *
*/
static VALUE
rb_fiber_m_raise(int argc, VALUE *argv, VALUE self)
@@ -3366,6 +3386,8 @@ rb_fiber_atfork(rb_thread_t *th)
th->root_fiber = th->ec->fiber_ptr;
}
th->root_fiber->prev = 0;
+ th->root_fiber->blocking = 1;
+ th->blocking = 1;
}
}
#endif
@@ -3518,7 +3540,15 @@ Init_Cont(void)
rb_define_singleton_method(rb_cFiber, "schedule", rb_fiber_s_schedule, -1);
+ rb_thread_t *current_thread = rb_current_thread();
+ RUBY_ASSERT(CLASS_OF(current_thread->ec->fiber_ptr->cont.self) == 0);
+ *(VALUE *)&((struct RBasic *)current_thread->ec->fiber_ptr->cont.self)->klass = rb_cFiber;
+
#ifdef RB_EXPERIMENTAL_FIBER_POOL
+ /*
+ * Document-class: Fiber::Pool
+ * :nodoc: experimental
+ */
rb_cFiberPool = rb_define_class_under(rb_cFiber, "Pool", rb_cObject);
rb_define_alloc_func(rb_cFiberPool, fiber_pool_alloc);
rb_define_method(rb_cFiberPool, "initialize", rb_fiber_pool_initialize, -1);
diff --git a/coroutine/amd64/Context.S b/coroutine/amd64/Context.S
index 056c276a31..4b94d31f30 100644
--- a/coroutine/amd64/Context.S
+++ b/coroutine/amd64/Context.S
@@ -5,13 +5,21 @@
## Copyright, 2018, by Samuel Williams.
##
+/* Important - do _not_ include <cet.h> in this file; doing so will
+ * cause an incorrect .note.gnu.property section to be emitted. We have
+ * one at the bottom of this file */
+
#define TOKEN_PASTE(x,y) x##y
-#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name)
.text
-.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer)
-PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
+.globl PREFIXED_SYMBOL(coroutine_transfer)
+PREFIXED_SYMBOL(coroutine_transfer):
+
+#if defined(__CET__) && (__CET__ & 0x01) != 0
+ /* IBT landing pad */
+ endbr64
+#endif
# Make space on the stack for 6 registers:
subq $48, %rsp
@@ -50,3 +58,31 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
#if (defined(__linux__) || defined(__FreeBSD__)) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
#endif
+
+#if defined(__ELF__)
+
+#if defined(__CET__) && (__CET__ & 0x01) != 0
+# define IBT_FLAG 0x01
+#else
+# define IBT_FLAG 0x00
+#endif
+
+/* We do _NOT_ support CET shadow-stack. Do _not_ add the property for
+ * this to the Context.o object. If you require CET shadow-stack support,
+ * for now, consider building with --with-coroutine=ucontext */
+#define SHSTK_FLAG 0x00
+
+.pushsection .note.gnu.property, "a"
+.p2align 3
+.long 0x4 /* Name size ("GNU\0") */
+.long 0x10 /* Descriptor size */
+.long 0x5 /* Type: NT_GNU_PROPERTY_TYPE_0 */
+.asciz "GNU" /* Name */
+# Begin descriptor
+.long 0xc0000002 /* Property type: GNU_PROPERTY_X86_FEATURE_1_AND */
+.long 0x4 /* Property size */
+.long (IBT_FLAG | SHSTK_FLAG)
+.long 0x0 /* 8-byte alignment padding */
+/* End descriptor */
+.popsection
+#endif
diff --git a/coroutine/amd64/Context.h b/coroutine/amd64/Context.h
index 44daa4e01a..65aa638304 100644
--- a/coroutine/amd64/Context.h
+++ b/coroutine/amd64/Context.h
@@ -69,7 +69,7 @@ static inline void coroutine_initialize(
context->stack_pointer = (void**)((uintptr_t)top & ~0xF);
*--context->stack_pointer = NULL;
- *--context->stack_pointer = (void*)start;
+ *--context->stack_pointer = (void*)(uintptr_t)start;
context->stack_pointer -= COROUTINE_REGISTERS;
memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS);
diff --git a/coroutine/arm32/Context.S b/coroutine/arm32/Context.S
index 1850c4c408..945e4f82d5 100644
--- a/coroutine/arm32/Context.S
+++ b/coroutine/arm32/Context.S
@@ -6,16 +6,15 @@
##
#define TOKEN_PASTE(x,y) x##y
-#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name)
.file "Context.S"
.text
-.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer)
+.globl PREFIXED_SYMBOL(coroutine_transfer)
.align 2
-.type PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer),%function
+.type PREFIXED_SYMBOL(coroutine_transfer),%function
.syntax unified
-PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
+PREFIXED_SYMBOL(coroutine_transfer):
# Save caller state (8 registers + return address)
push {r4-r11,lr}
diff --git a/coroutine/arm32/Context.h b/coroutine/arm32/Context.h
index 09410eb25d..7529dd2efc 100644
--- a/coroutine/arm32/Context.h
+++ b/coroutine/arm32/Context.h
@@ -44,7 +44,7 @@ static inline void coroutine_initialize(
char * top = (char*)stack + size;
context->stack_pointer = (void**)((uintptr_t)top & ~0xF);
- *--context->stack_pointer = (void*)start;
+ *--context->stack_pointer = (void*)(uintptr_t)start;
context->stack_pointer -= COROUTINE_REGISTERS;
memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS);
diff --git a/coroutine/arm64/Context.S b/coroutine/arm64/Context.S
index 5251ab214d..ce219c0c4d 100644
--- a/coroutine/arm64/Context.S
+++ b/coroutine/arm64/Context.S
@@ -6,7 +6,6 @@
##
#define TOKEN_PASTE(x,y) x##y
-#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name)
#if defined(__APPLE__)
#define x29 fp
@@ -18,14 +17,25 @@
.align 2
#endif
+#if defined(__ARM_FEATURE_PAC_DEFAULT) && (__ARM_FEATURE_PAC_DEFAULT & 0x02) != 0
+# error "-mbranch-protection flag specified b-key but Context.S does not support this"
+#endif
+
+#if defined(_WIN32)
+## Add more space for certain TEB values on each stack
+#define TEB_OFFSET 0x20
+#else
+#define TEB_OFFSET 0x00
+#endif
+
## NOTE(PAC): Use we HINT mnemonics instead of PAC mnemonics to
## keep compatibility with those assemblers that don't support PAC.
##
## See "Providing protection for complex software" for more details about PAC/BTI
## https://developer.arm.com/architectures/learn-the-architecture/providing-protection-for-complex-software
-.global PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer)
-PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
+.global PREFIXED_SYMBOL(coroutine_transfer)
+PREFIXED_SYMBOL(coroutine_transfer):
#if defined(__ARM_FEATURE_PAC_DEFAULT) && (__ARM_FEATURE_PAC_DEFAULT != 0)
# paciasp (it also acts as BTI landing pad, so no need to insert BTI also)
@@ -36,19 +46,34 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
hint #34
#endif
# Make space on the stack for caller registers
- sub sp, sp, 0xa0
+ sub sp, sp, 0xa0 + TEB_OFFSET
# Save caller registers
- stp d8, d9, [sp, 0x00]
- stp d10, d11, [sp, 0x10]
- stp d12, d13, [sp, 0x20]
- stp d14, d15, [sp, 0x30]
- stp x19, x20, [sp, 0x40]
- stp x21, x22, [sp, 0x50]
- stp x23, x24, [sp, 0x60]
- stp x25, x26, [sp, 0x70]
- stp x27, x28, [sp, 0x80]
- stp x29, x30, [sp, 0x90]
+ stp d8, d9, [sp, 0x00 + TEB_OFFSET]
+ stp d10, d11, [sp, 0x10 + TEB_OFFSET]
+ stp d12, d13, [sp, 0x20 + TEB_OFFSET]
+ stp d14, d15, [sp, 0x30 + TEB_OFFSET]
+ stp x19, x20, [sp, 0x40 + TEB_OFFSET]
+ stp x21, x22, [sp, 0x50 + TEB_OFFSET]
+ stp x23, x24, [sp, 0x60 + TEB_OFFSET]
+ stp x25, x26, [sp, 0x70 + TEB_OFFSET]
+ stp x27, x28, [sp, 0x80 + TEB_OFFSET]
+ stp x29, x30, [sp, 0x90 + TEB_OFFSET]
+
+#if defined(_WIN32)
+ # Save certain values from Thread Environment Block (TEB)
+ # x18 points to the TEB on Windows
+ # Read TeStackBase and TeStackLimit at ksarm64.h from TEB
+ ldp x5, x6, [x18, #0x08]
+ # Save them
+ stp x5, x6, [sp, #0x00]
+ # Read TeDeallocationStack at ksarm64.h from TEB
+ ldr x5, [x18, #0x1478]
+ # Read TeFiberData at ksarm64.h from TEB
+ ldr x6, [x18, #0x20]
+ # Save current fiber data and deallocation stack
+ stp x5, x6, [sp, #0x10]
+#endif
# Save stack pointer to x0 (first argument)
mov x2, sp
@@ -58,20 +83,33 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
ldr x3, [x1, 0]
mov sp, x3
+#if defined(_WIN32)
+ # Restore stack base and limit
+ ldp x5, x6, [sp, #0x00]
+ # Write TeStackBase and TeStackLimit at ksarm64.h to TEB
+ stp x5, x6, [x18, #0x08]
+ # Restore fiber data and deallocation stack
+ ldp x5, x6, [sp, #0x10]
+ # Write TeDeallocationStack at ksarm64.h to TEB
+ str x5, [x18, #0x1478]
+ # Write TeFiberData at ksarm64.h to TEB
+ str x6, [x18, #0x20]
+#endif
+
# Restore caller registers
- ldp d8, d9, [sp, 0x00]
- ldp d10, d11, [sp, 0x10]
- ldp d12, d13, [sp, 0x20]
- ldp d14, d15, [sp, 0x30]
- ldp x19, x20, [sp, 0x40]
- ldp x21, x22, [sp, 0x50]
- ldp x23, x24, [sp, 0x60]
- ldp x25, x26, [sp, 0x70]
- ldp x27, x28, [sp, 0x80]
- ldp x29, x30, [sp, 0x90]
+ ldp d8, d9, [sp, 0x00 + TEB_OFFSET]
+ ldp d10, d11, [sp, 0x10 + TEB_OFFSET]
+ ldp d12, d13, [sp, 0x20 + TEB_OFFSET]
+ ldp d14, d15, [sp, 0x30 + TEB_OFFSET]
+ ldp x19, x20, [sp, 0x40 + TEB_OFFSET]
+ ldp x21, x22, [sp, 0x50 + TEB_OFFSET]
+ ldp x23, x24, [sp, 0x60 + TEB_OFFSET]
+ ldp x25, x26, [sp, 0x70 + TEB_OFFSET]
+ ldp x27, x28, [sp, 0x80 + TEB_OFFSET]
+ ldp x29, x30, [sp, 0x90 + TEB_OFFSET]
# Pop stack frame
- add sp, sp, 0xa0
+ add sp, sp, 0xa0 + TEB_OFFSET
#if defined(__ARM_FEATURE_PAC_DEFAULT) && (__ARM_FEATURE_PAC_DEFAULT != 0)
# autiasp: Authenticate x30 (LR) with SP and key A
@@ -85,18 +123,19 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
.section .note.GNU-stack,"",%progbits
#endif
-#if __ARM_FEATURE_BTI_DEFAULT != 0 || __ARM_FEATURE_PAC_DEFAULT != 0
+#if (defined(__ARM_FEATURE_BTI_DEFAULT) && __ARM_FEATURE_BTI_DEFAULT != 0) || (defined(__ARM_FEATURE_PAC_DEFAULT) && __ARM_FEATURE_PAC_DEFAULT != 0)
+#if defined(__ELF__)
/* See "ELF for the Arm 64-bit Architecture (AArch64)"
https://github.com/ARM-software/abi-aa/blob/2023Q3/aaelf64/aaelf64.rst#program-property */
# define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1<<0)
# define GNU_PROPERTY_AARCH64_FEATURE_1_PAC (1<<1)
-# if __ARM_FEATURE_BTI_DEFAULT != 0
+# if defined(__ARM_FEATURE_BTI_DEFAULT) && __ARM_FEATURE_BTI_DEFAULT != 0
# define BTI_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_BTI
# else
# define BTI_FLAG 0
# endif
-# if __ARM_FEATURE_PAC_DEFAULT != 0
+# if defined(__ARM_FEATURE_PAC_DEFAULT) && __ARM_FEATURE_PAC_DEFAULT != 0
# define PAC_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_PAC
# else
# define PAC_FLAG 0
@@ -118,3 +157,4 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
# End descriptor
.popsection
#endif
+#endif
diff --git a/coroutine/arm64/Context.asm b/coroutine/arm64/Context.asm
new file mode 100644
index 0000000000..866fa628e7
--- /dev/null
+++ b/coroutine/arm64/Context.asm
@@ -0,0 +1,81 @@
+ TTL coroutine/arm64/Context.asm
+
+ AREA |.drectve|, DRECTVE
+
+ EXPORT |coroutine_transfer|
+
+ AREA |.text$mn|, CODE, ARM64
+
+;; Add more space for certain TEB values on each stack
+TEB_OFFSET EQU 0x20
+
+;; Incomplete implementation
+coroutine_transfer PROC
+ ; Make space on the stack for caller registers
+ sub sp, sp, 0xa0 + TEB_OFFSET
+
+ ; Save caller registers
+ stp d8, d9, [sp, 0x00 + TEB_OFFSET]
+ stp d10, d11, [sp, 0x10 + TEB_OFFSET]
+ stp d12, d13, [sp, 0x20 + TEB_OFFSET]
+ stp d14, d15, [sp, 0x30 + TEB_OFFSET]
+ stp x19, x20, [sp, 0x40 + TEB_OFFSET]
+ stp x21, x22, [sp, 0x50 + TEB_OFFSET]
+ stp x23, x24, [sp, 0x60 + TEB_OFFSET]
+ stp x25, x26, [sp, 0x70 + TEB_OFFSET]
+ stp x27, x28, [sp, 0x80 + TEB_OFFSET]
+ stp x29, x30, [sp, 0x90 + TEB_OFFSET]
+
+ ;; Save certain values from Thread Environment Block (TEB) x18
+ ;; points to the TEB on Windows
+ ;; Read TeStackBase and TeStackLimit at ksarm64.h from TEB
+ ldp x5, x6, [x18, #0x08]
+ ;; Save them
+ stp x5, x6, [sp, #0x00]
+ ;; Read TeDeallocationStack at ksarm64.h from TEB
+ ldr x5, [x18, #0x1478]
+ ;; Read TeFiberData at ksarm64.h from TEB
+ ldr x6, [x18, #0x20]
+ ;; Save current fiber data and deallocation stack
+ stp x5, x6, [sp, #0x10]
+
+ ; Save stack pointer to x0 (first argument)
+ mov x2, sp
+ str x2, [x0, 0]
+
+ ; Load stack pointer from x1 (second argument)
+ ldr x3, [x1, 0]
+ mov sp, x3
+
+ ;; Restore stack base and limit
+ ldp x5, x6, [sp, #0x00]
+ ;; Write TeStackBase and TeStackLimit at ksarm64.h to TEB
+ stp x5, x6, [x18, #0x08]
+ ;; Restore fiber data and deallocation stack
+ ldp x5, x6, [sp, #0x10]
+ ;; Write TeDeallocationStack at ksarm64.h to TEB
+ str x5, [x18, #0x1478]
+ ;; Write TeFiberData at ksarm64.h to TEB
+ str x6, [x18, #0x20]
+
+ ; Restore caller registers
+ ldp d8, d9, [sp, 0x00 + TEB_OFFSET]
+ ldp d10, d11, [sp, 0x10 + TEB_OFFSET]
+ ldp d12, d13, [sp, 0x20 + TEB_OFFSET]
+ ldp d14, d15, [sp, 0x30 + TEB_OFFSET]
+ ldp x19, x20, [sp, 0x40 + TEB_OFFSET]
+ ldp x21, x22, [sp, 0x50 + TEB_OFFSET]
+ ldp x23, x24, [sp, 0x60 + TEB_OFFSET]
+ ldp x25, x26, [sp, 0x70 + TEB_OFFSET]
+ ldp x27, x28, [sp, 0x80 + TEB_OFFSET]
+ ldp x29, x30, [sp, 0x90 + TEB_OFFSET]
+
+ ; Pop stack frame
+ add sp, sp, 0xa0 + TEB_OFFSET
+
+ ; Jump to return address (in x30)
+ ret
+
+ endp
+
+ end
diff --git a/coroutine/arm64/Context.h b/coroutine/arm64/Context.h
index eb66fbea0f..468e4155b2 100644
--- a/coroutine/arm64/Context.h
+++ b/coroutine/arm64/Context.h
@@ -15,9 +15,21 @@
#include <stdint.h>
#include <string.h>
+#if defined __GNUC__
#define COROUTINE __attribute__((noreturn)) void
+#define COROUTINE_DECL COROUTINE
+#elif defined _MSC_VER
+#define COROUTINE __declspec(noreturn) void
+#define COROUTINE_DECL void
+#endif
-enum {COROUTINE_REGISTERS = 0xa0 / 8};
+#if defined(_WIN32)
+#define TEB_OFFSET 0x20
+#else
+#define TEB_OFFSET 0x00
+#endif
+
+enum {COROUTINE_REGISTERS = (0xa0 + TEB_OFFSET) / 8};
#if defined(__SANITIZE_ADDRESS__)
#define COROUTINE_SANITIZE_ADDRESS
@@ -44,7 +56,7 @@ struct coroutine_context
#endif
};
-typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self);
+typedef COROUTINE_DECL(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self);
static inline void coroutine_initialize_main(struct coroutine_context * context) {
context->stack_pointer = NULL;
@@ -86,7 +98,15 @@ static inline void coroutine_initialize(
context->stack_pointer -= COROUTINE_REGISTERS;
memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS);
- context->stack_pointer[0x98 / 8] = ptrauth_sign_instruction_addr((void*)start, (void*)top);
+ void *addr = (void*)(uintptr_t)start;
+ context->stack_pointer[(0x98 + TEB_OFFSET) / 8] = ptrauth_sign_instruction_addr(addr, (void*)top);
+#if defined(_WIN32)
+ // save top address of stack as base in TEB
+ context->stack_pointer[0x00 / 8] = (char*)stack + size;
+ // save botton address of stack as limit and deallocation stack in TEB
+ context->stack_pointer[0x08 / 8] = stack;
+ context->stack_pointer[0x10 / 8] = stack;
+#endif
}
struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target);
diff --git a/coroutine/loongarch64/Context.S b/coroutine/loongarch64/Context.S
index 662f5dfb6c..6e10cd032b 100644
--- a/coroutine/loongarch64/Context.S
+++ b/coroutine/loongarch64/Context.S
@@ -1,11 +1,10 @@
#define TOKEN_PASTE(x,y) x##y
-#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name)
.text
.align 2
-.global PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer)
-PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
+.global PREFIXED_SYMBOL(coroutine_transfer)
+PREFIXED_SYMBOL(coroutine_transfer):
# Make space on the stack for caller registers
addi.d $sp, $sp, -0xa0
diff --git a/coroutine/loongarch64/Context.h b/coroutine/loongarch64/Context.h
index 668c9a965e..82b85b36e9 100644
--- a/coroutine/loongarch64/Context.h
+++ b/coroutine/loongarch64/Context.h
@@ -36,7 +36,7 @@ static inline void coroutine_initialize(
context->stack_pointer -= COROUTINE_REGISTERS;
memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS);
- context->stack_pointer[0x90 / 8] = (void*)start;
+ context->stack_pointer[0x90 / 8] = (void*)(uintptr_t)start;
}
struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target);
diff --git a/coroutine/ppc/Context.S b/coroutine/ppc/Context.S
index e2431a9250..f44b2419b4 100644
--- a/coroutine/ppc/Context.S
+++ b/coroutine/ppc/Context.S
@@ -9,15 +9,14 @@
; To add support for AIX, *BSD or *Linux, please make separate implementations.
#define TOKEN_PASTE(x,y) x##y
-#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name)
.machine ppc7400 ; = G4, Rosetta
.text
-.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer)
+.globl PREFIXED_SYMBOL(coroutine_transfer)
.align 2
-PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
+PREFIXED_SYMBOL(coroutine_transfer):
; Make space on the stack for caller registers
; (Should we rather use red zone? See libphobos example.)
subi r1,r1,80
diff --git a/coroutine/ppc64/Context.S b/coroutine/ppc64/Context.S
index f8561e0e7d..20a47c61c6 100644
--- a/coroutine/ppc64/Context.S
+++ b/coroutine/ppc64/Context.S
@@ -8,15 +8,14 @@
; To add support for AIX, *BSD or *Linux, please make separate implementations.
#define TOKEN_PASTE(x,y) x##y
-#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name)
.machine ppc64 ; = G5
.text
-.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer)
+.globl PREFIXED_SYMBOL(coroutine_transfer)
.align 2
-PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
+PREFIXED_SYMBOL(coroutine_transfer):
; Make space on the stack for caller registers
; (Should we rather use red zone? See libphobos example.)
subi r1,r1,160
diff --git a/coroutine/ppc64le/Context.S b/coroutine/ppc64le/Context.S
index 61be9efcf0..f7bcae2c3a 100644
--- a/coroutine/ppc64le/Context.S
+++ b/coroutine/ppc64le/Context.S
@@ -1,14 +1,13 @@
#define TOKEN_PASTE(x,y) x##y
-#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name)
.text
.align 2
-.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer)
-.type PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer), @function
-PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
+.globl PREFIXED_SYMBOL(coroutine_transfer)
+.type PREFIXED_SYMBOL(coroutine_transfer), @function
+PREFIXED_SYMBOL(coroutine_transfer):
# Make space on the stack for caller registers
- addi 1,1,-152
+ addi 1,1,-160
# Save caller registers
std 14,0(1)
@@ -34,6 +33,10 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
mflr 0
std 0,144(1)
+ # Save caller special register
+ mfcr 0
+ std 0, 152(1)
+
# Save stack pointer to first argument
std 1,0(3)
@@ -64,8 +67,14 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
ld 0,144(1)
mtlr 0
+ # Load special registers
+ ld 0,152(1)
+ # Restore cr register cr2, cr3 and cr4 (field index 3,4,5)
+ # (field index is 1-based, field 1 = cr0) using a mask (32|16|8 = 56)
+ mtcrf 56,0
+
# Pop stack frame
- addi 1,1,152
+ addi 1,1,160
# Jump to return address
blr
diff --git a/coroutine/ppc64le/Context.h b/coroutine/ppc64le/Context.h
index fbfaa2ee63..63ea9f19ff 100644
--- a/coroutine/ppc64le/Context.h
+++ b/coroutine/ppc64le/Context.h
@@ -12,7 +12,7 @@
enum {
COROUTINE_REGISTERS =
- 19 /* 18 general purpose registers (r14-r31) and 1 return address */
+ 20 /* 18 general purpose registers (r14-r31), 1 special register (cr) and 1 return address */
+ 4 /* space for fiber_entry() to store the link register */
};
diff --git a/coroutine/riscv64/Context.S b/coroutine/riscv64/Context.S
index cc4e872f84..8e7fc74ffc 100644
--- a/coroutine/riscv64/Context.S
+++ b/coroutine/riscv64/Context.S
@@ -1,11 +1,10 @@
#define TOKEN_PASTE(x,y) x##y
-#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name)
.text
.align 2
-.global PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer)
-PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
+.global PREFIXED_SYMBOL(coroutine_transfer)
+PREFIXED_SYMBOL(coroutine_transfer):
# Make space on the stack for caller registers
addi sp, sp, -0xd0
diff --git a/coroutine/riscv64/Context.h b/coroutine/riscv64/Context.h
index 9ce1140e0b..3660fb5577 100644
--- a/coroutine/riscv64/Context.h
+++ b/coroutine/riscv64/Context.h
@@ -36,7 +36,7 @@ static inline void coroutine_initialize(
context->stack_pointer -= COROUTINE_REGISTERS;
memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS);
- context->stack_pointer[0xc0 / 8] = (void*)start;
+ context->stack_pointer[0xc0 / 8] = (void*)(uintptr_t)start;
}
struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target);
diff --git a/coroutine/win32/Context.h b/coroutine/win32/Context.h
index 902fd1246f..c1c8fbcd13 100644
--- a/coroutine/win32/Context.h
+++ b/coroutine/win32/Context.h
@@ -16,6 +16,7 @@
#include <string.h>
#define COROUTINE __declspec(noreturn) void __fastcall
+#define COROUTINE_DECL void __fastcall
#define COROUTINE_LIMITED_ADDRESS_SPACE
/* This doesn't include thread information block */
@@ -45,7 +46,7 @@ static inline void coroutine_initialize(
char * top = (char*)stack + size;
context->stack_pointer = (void**)((uintptr_t)top & ~0xF);
- *--context->stack_pointer = (void*)start;
+ *--context->stack_pointer = (void*)(uintptr_t)start;
/* Windows Thread Information Block */
*--context->stack_pointer = (void*)0xFFFFFFFF; /* fs:[0] */
diff --git a/coroutine/win64/Context.h b/coroutine/win64/Context.h
index d85ebf8e0e..23b21b5c1c 100644
--- a/coroutine/win64/Context.h
+++ b/coroutine/win64/Context.h
@@ -16,6 +16,7 @@
#include <string.h>
#define COROUTINE __declspec(noreturn) void
+#define COROUTINE_DECL void
enum {
COROUTINE_REGISTERS = 8,
@@ -53,7 +54,7 @@ static inline void coroutine_initialize(
/* Return address */
*--context->stack_pointer = 0;
- *--context->stack_pointer = (void*)start;
+ *--context->stack_pointer = (void*)(uintptr_t)start;
*--context->stack_pointer = (void*)coroutine_trampoline;
/* Windows Thread Information Block */
diff --git a/coroutine/x86/Context.S b/coroutine/x86/Context.S
index f06a417084..b04e71aa1c 100644
--- a/coroutine/x86/Context.S
+++ b/coroutine/x86/Context.S
@@ -6,12 +6,11 @@
##
#define TOKEN_PASTE(x,y) x##y
-#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name)
.text
-.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer)
-PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
+.globl PREFIXED_SYMBOL(coroutine_transfer)
+PREFIXED_SYMBOL(coroutine_transfer):
# Save caller registers
pushl %ebp
diff --git a/coroutine/x86/Context.h b/coroutine/x86/Context.h
index d98eaf6486..f33b338eab 100644
--- a/coroutine/x86/Context.h
+++ b/coroutine/x86/Context.h
@@ -45,7 +45,7 @@ static inline void coroutine_initialize(
context->stack_pointer = (void**)((uintptr_t)top & ~0xF);
*--context->stack_pointer = NULL;
- *--context->stack_pointer = (void*)start;
+ *--context->stack_pointer = (void*)(uintptr_t)start;
context->stack_pointer -= COROUTINE_REGISTERS;
memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS);
diff --git a/cygwin/GNUmakefile.in b/cygwin/GNUmakefile.in
index 192a8cc711..109baa747d 100644
--- a/cygwin/GNUmakefile.in
+++ b/cygwin/GNUmakefile.in
@@ -2,15 +2,13 @@ gnumake = yes
include Makefile
+MUNICODE_FLAG := $(if $(filter mingw%,$(target_os)),-municode)
+override EXE_LDFLAGS += $(MUNICODE_FLAG)
+
DLLWRAP = @DLLWRAP@ --target=$(target_os) --driver-name="$(CC)"
-ifeq (@USE_LLVM_WINDRES@,yes) # USE_LLVM_WINDRES
- # llvm-windres fails when preprocessor options are added
- windres-cpp :=
-else
- windres-cpp := $(CPP) -xc
- windres-cpp := --preprocessor=$(firstword $(windres-cpp)) \
- $(addprefix --preprocessor-arg=,$(wordlist 2,$(words $(windres-cpp)),$(windres-cpp)))
-endif
+windres-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@
@@ -69,7 +67,7 @@ $(PROGRAM): $(RUBY_INSTALL_NAME).res.$(OBJEXT)
$(WPROGRAM): $(RUBYW_INSTALL_NAME).res.$(OBJEXT)
@rm -f $@
$(ECHO) linking $@
- $(Q) $(PURIFY) $(CC) -mwindows -e $(SYMBOL_PREFIX)mainCRTStartup $(LDFLAGS) $(XLDFLAGS) \
+ $(Q) $(PURIFY) $(CC) $(MUNICODE_FLAG) -mwindows -e $(SYMBOL_PREFIX)mainCRTStartup $(LDFLAGS) $(XLDFLAGS) \
$(MAINOBJ) $(EXTOBJS) $(LIBRUBYARG) $(LIBS) -o $@
$(STUBPROGRAM): $(RUBY_INSTALL_NAME).res.$(OBJEXT)
@@ -96,6 +94,8 @@ yes-test-all: export MSYS2_ARG_CONV_EXCL=$(MSYS2_ARG_CONV_EXCL_PARAM)
yes-test-almost: export MSYS2_ARG_CONV_EXCL=$(MSYS2_ARG_CONV_EXCL_PARAM)
test/% spec/%/ spec/%_spec.rb: export MSYS2_ARG_CONV_EXCL=$(MSYS2_ARG_CONV_EXCL_PARAM)
+distclean-local::
+ $(RMDIR) win32
endif
$(LIBRUBY_SO): $(RUBYDEF)
diff --git a/darray.h b/darray.h
index d24e3c3eb5..10fd5e4ccc 100644
--- a/darray.h
+++ b/darray.h
@@ -4,8 +4,7 @@
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
-
-#include "internal/bits.h"
+#include "ruby/ruby.h"
// Type for a dynamic array. Use to declare a dynamic array.
// It is a pointer so it fits in st_table nicely. Designed
@@ -44,18 +43,50 @@
* void rb_darray_append(rb_darray(T) *ptr_to_ary, T element);
*/
#define rb_darray_append(ptr_to_ary, element) \
- rb_darray_append_impl(ptr_to_ary, element)
+ rb_darray_append_impl(ptr_to_ary, element, rb_darray_realloc_mul_add)
+
+#define rb_darray_append_without_gc(ptr_to_ary, element) \
+ rb_darray_append_impl(ptr_to_ary, element, rb_darray_realloc_mul_add_without_gc)
-#define rb_darray_append_impl(ptr_to_ary, element) do { \
+#define rb_darray_append_impl(ptr_to_ary, element, realloc_func) do { \
rb_darray_ensure_space((ptr_to_ary), \
sizeof(**(ptr_to_ary)), \
- sizeof((*(ptr_to_ary))->data[0])); \
+ sizeof((*(ptr_to_ary))->data[0]), \
+ realloc_func); \
rb_darray_set(*(ptr_to_ary), \
(*(ptr_to_ary))->meta.size, \
(element)); \
(*(ptr_to_ary))->meta.size++; \
} while (0)
+#define rb_darray_insert_without_gc(ptr_to_ary, idx, element) do { \
+ rb_darray_ensure_space((ptr_to_ary), \
+ sizeof(**(ptr_to_ary)), \
+ sizeof((*(ptr_to_ary))->data[0]), \
+ rb_darray_realloc_mul_add_without_gc); \
+ MEMMOVE( \
+ rb_darray_ref(*(ptr_to_ary), idx + 1), \
+ rb_darray_ref(*(ptr_to_ary), idx), \
+ (*(ptr_to_ary))->data[0], \
+ rb_darray_size(*(ptr_to_ary)) - idx); \
+ rb_darray_set(*(ptr_to_ary), idx, element); \
+ (*(ptr_to_ary))->meta.size++; \
+} while (0)
+
+/* Removes the element at idx and replaces it with the last element.
+ * ptr_to_ary and idx is evaluated multiple times.
+ * Warning: not bounds checked.
+ *
+ * void rb_darray_swap_remove(rb_darray(T) *ptr_to_ary, size_t idx);
+ */
+#define rb_darray_swap_remove(ptr_to_ary, idx) do { \
+ size_t _darray_size = rb_darray_size(*(ptr_to_ary)); \
+ if ((idx) != _darray_size - 1) { \
+ (*(ptr_to_ary))->data[idx] = (*(ptr_to_ary))->data[_darray_size - 1]; \
+ } \
+ (*(ptr_to_ary))->meta.size--; \
+} while (0)
+
// Iterate over items of the array in a for loop
//
#define rb_darray_foreach(ary, idx_name, elem_ptr_var) \
@@ -74,15 +105,21 @@
* void rb_darray_make(rb_darray(T) *ptr_to_ary, size_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]))
+ rb_darray_make_impl((ptr_to_ary), size, sizeof(**(ptr_to_ary)), \
+ sizeof((*(ptr_to_ary))->data[0]), rb_darray_calloc_mul_add)
+
+#define rb_darray_make_without_gc(ptr_to_ary, size) \
+ rb_darray_make_impl((ptr_to_ary), size, sizeof(**(ptr_to_ary)), \
+ sizeof((*(ptr_to_ary))->data[0]), rb_darray_calloc_mul_add_without_gc)
/* Resize the darray to a new capacity. The new capacity must be greater than
* or equal to the size of the darray.
*
* void rb_darray_resize_capa(rb_darray(T) *ptr_to_ary, size_t capa);
*/
-#define rb_darray_resize_capa(ptr_to_ary, capa) \
- rb_darray_resize_capa_impl((ptr_to_ary), capa, sizeof(**(ptr_to_ary)), sizeof((*(ptr_to_ary))->data[0]))
+#define rb_darray_resize_capa_without_gc(ptr_to_ary, capa) \
+ rb_darray_resize_capa_impl((ptr_to_ary), capa, sizeof(**(ptr_to_ary)), \
+ sizeof((*(ptr_to_ary))->data[0]), rb_darray_realloc_mul_add_without_gc)
#define rb_darray_data_ptr(ary) ((ary)->data)
@@ -111,6 +148,17 @@ rb_darray_size(const void *ary)
return meta ? meta->size : 0;
}
+/* Estimate of the amount of memory used by this darray.
+ * Useful for TypedData objects. */
+#define rb_darray_memsize(ary) (sizeof(*(ary)) + (rb_darray_size(ary) * sizeof((ary)->data[0])))
+
+static inline void
+rb_darray_pop(void *ary, size_t count)
+{
+ rb_darray_meta_t *meta = ary;
+ meta->size -= count;
+}
+
// Get the capacity of the dynamic array.
//
static inline size_t
@@ -127,15 +175,70 @@ rb_darray_free(void *ary)
xfree(ary);
}
+static inline void
+rb_darray_free_without_gc(void *ary)
+{
+ free(ary);
+}
+
+/* Internal function. Like rb_xcalloc_mul_add. */
+static inline void *
+rb_darray_calloc_mul_add(size_t x, size_t y, size_t z)
+{
+ size_t size = rbimpl_size_add_or_raise(rbimpl_size_mul_or_raise(x, y), z);
+
+ void *ptr = xcalloc(1, size);
+ RUBY_ASSERT(ptr != NULL);
+
+ return ptr;
+}
+
+/* Internal function. Like rb_xcalloc_mul_add but does not trigger GC. */
+static inline void *
+rb_darray_calloc_mul_add_without_gc(size_t x, size_t y, size_t z)
+{
+ size_t size = rbimpl_size_add_or_raise(rbimpl_size_mul_or_raise(x, y), z);
+
+ void *ptr = calloc(1, size);
+ if (ptr == NULL) rb_bug("rb_darray_calloc_mul_add_without_gc: failed");
+
+ return ptr;
+}
+
+/* Internal function. Like rb_xrealloc_mul_add. */
+static inline void *
+rb_darray_realloc_mul_add(void *orig_ptr, size_t x, size_t y, size_t z)
+{
+ size_t size = rbimpl_size_add_or_raise(rbimpl_size_mul_or_raise(x, y), z);
+
+ void *ptr = xrealloc(orig_ptr, size);
+ RUBY_ASSERT(ptr != NULL);
+
+ return ptr;
+}
+
+/* Internal function. Like rb_xrealloc_mul_add but does not trigger GC. */
+static inline void *
+rb_darray_realloc_mul_add_without_gc(void *orig_ptr, size_t x, size_t y, size_t z)
+{
+ size_t size = rbimpl_size_add_or_raise(rbimpl_size_mul_or_raise(x, y), z);
+
+ void *ptr = realloc(orig_ptr, size);
+ if (ptr == NULL) rb_bug("rb_darray_realloc_mul_add_without_gc: failed");
+
+ return ptr;
+}
+
/* Internal function. Resizes the capacity of a darray. The new capacity must
* be greater than or equal to the size of the darray. */
static inline void
-rb_darray_resize_capa_impl(void *ptr_to_ary, size_t new_capa, size_t header_size, size_t element_size)
+rb_darray_resize_capa_impl(void *ptr_to_ary, size_t new_capa, size_t header_size, size_t element_size,
+ void *(*realloc_mul_add_impl)(void *, size_t, size_t, size_t))
{
rb_darray_meta_t **ptr_to_ptr_to_meta = ptr_to_ary;
rb_darray_meta_t *meta = *ptr_to_ptr_to_meta;
- rb_darray_meta_t *new_ary = xrealloc(meta, new_capa * element_size + header_size);
+ rb_darray_meta_t *new_ary = realloc_mul_add_impl(meta, new_capa, element_size, header_size);
if (meta == NULL) {
/* First allocation. Initialize size. On subsequence allocations
@@ -156,7 +259,8 @@ rb_darray_resize_capa_impl(void *ptr_to_ary, size_t new_capa, size_t header_size
// Ensure there is space for one more element.
// Note: header_size can be bigger than sizeof(rb_darray_meta_t) when T is __int128_t, for example.
static inline void
-rb_darray_ensure_space(void *ptr_to_ary, size_t header_size, size_t element_size)
+rb_darray_ensure_space(void *ptr_to_ary, size_t header_size, size_t element_size,
+ void *(*realloc_mul_add_impl)(void *, size_t, size_t, size_t))
{
rb_darray_meta_t **ptr_to_ptr_to_meta = ptr_to_ary;
rb_darray_meta_t *meta = *ptr_to_ptr_to_meta;
@@ -166,11 +270,12 @@ rb_darray_ensure_space(void *ptr_to_ary, size_t header_size, size_t element_size
// Double the capacity
size_t new_capa = current_capa == 0 ? 1 : current_capa * 2;
- rb_darray_resize_capa_impl(ptr_to_ary, new_capa, header_size, element_size);
+ rb_darray_resize_capa_impl(ptr_to_ary, new_capa, header_size, element_size, realloc_mul_add_impl);
}
static inline void
-rb_darray_make_impl(void *ptr_to_ary, size_t array_size, size_t header_size, size_t element_size)
+rb_darray_make_impl(void *ptr_to_ary, size_t array_size, size_t header_size, size_t element_size,
+ void *(*calloc_mul_add_impl)(size_t, size_t, size_t))
{
rb_darray_meta_t **ptr_to_ptr_to_meta = ptr_to_ary;
if (array_size == 0) {
@@ -178,7 +283,7 @@ rb_darray_make_impl(void *ptr_to_ary, size_t array_size, size_t header_size, siz
return;
}
- rb_darray_meta_t *meta = xcalloc(array_size * element_size + header_size, 1);
+ rb_darray_meta_t *meta = calloc_mul_add_impl(array_size, element_size, header_size);
meta->size = array_size;
meta->capa = array_size;
diff --git a/debug.c b/debug.c
index 4717a0bc9c..1a2c27a5be 100644
--- a/debug.c
+++ b/debug.c
@@ -57,6 +57,7 @@ const union {
enum ruby_rstring_flags rstring_flags;
enum ruby_rarray_flags rarray_flags;
enum ruby_rarray_consts rarray_consts;
+ enum rbimpl_typeddata_flags rtypeddata_consts;
enum {
RUBY_FMODE_READABLE = FMODE_READABLE,
RUBY_FMODE_WRITABLE = FMODE_WRITABLE,
@@ -168,9 +169,7 @@ ruby_debug_breakpoint(void)
}
#if defined _WIN32
-# if RUBY_MSVCRT_VERSION >= 80
extern int ruby_w32_rtc_error;
-# endif
#endif
#if defined _WIN32 || defined __CYGWIN__
#include <windows.h>
@@ -233,9 +232,7 @@ ruby_env_debug_option(const char *str, int len, void *arg)
SET_WHEN("ci", ruby_on_ci, 1);
SET_WHEN_UINT("rgengc", &ruby_rgengc_debug, 1, ruby_rgengc_debug = 1);
#if defined _WIN32
-# if RUBY_MSVCRT_VERSION >= 80
SET_WHEN("rtc_error", ruby_w32_rtc_error, 1);
-# endif
#endif
#if defined _WIN32 || defined __CYGWIN__
SET_WHEN_UINT("codepage", ruby_w32_codepage, numberof(ruby_w32_codepage),
@@ -712,4 +709,22 @@ ruby_debug_log_dump(const char *fname, unsigned int n)
fclose(fp);
}
}
+
+#else
+
+#undef ruby_debug_log
+void
+ruby_debug_log(const char *file, int line, const char *func_name, const char *fmt, ...)
+{
+ va_list args;
+
+ fprintf(stderr, "[%s:%d] %s: ", file, line, func_name);
+
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+
+ fprintf(stderr, "\n");
+}
+
#endif // #if USE_RUBY_DEBUG_LOG
diff --git a/debug_counter.h b/debug_counter.h
index a8b95edded..c8d8ed8f11 100644
--- a/debug_counter.h
+++ b/debug_counter.h
@@ -49,7 +49,7 @@ 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_ent_invalidate) // count for invalidating cc (cc->klass = Qundef)
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
@@ -305,16 +305,18 @@ RB_DEBUG_COUNTER(obj_imemo_ment)
RB_DEBUG_COUNTER(obj_imemo_iseq)
RB_DEBUG_COUNTER(obj_imemo_env)
RB_DEBUG_COUNTER(obj_imemo_tmpbuf)
-RB_DEBUG_COUNTER(obj_imemo_ast)
RB_DEBUG_COUNTER(obj_imemo_cref)
RB_DEBUG_COUNTER(obj_imemo_svar)
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)
+RB_DEBUG_COUNTER(obj_imemo_fields)
+
+RB_DEBUG_COUNTER(opt_new_hit)
+RB_DEBUG_COUNTER(opt_new_miss)
/* ar_table */
RB_DEBUG_COUNTER(artable_hint_hit)
@@ -356,7 +358,7 @@ RB_DEBUG_COUNTER(load_path_is_not_realpath)
enum rb_debug_counter_type {
#define RB_DEBUG_COUNTER(name) RB_DEBUG_COUNTER_##name,
-#include __FILE__
+#include "debug_counter.h"
RB_DEBUG_COUNTER_MAX
#undef RB_DEBUG_COUNTER
};
diff --git a/defs/gmake.mk b/defs/gmake.mk
index b34e8420ba..f4b3d79990 100644
--- a/defs/gmake.mk
+++ b/defs/gmake.mk
@@ -2,6 +2,7 @@
reconfig config.status: export MAKE:=$(MAKE)
export BASERUBY:=$(BASERUBY)
+export GIT
override gnumake_recursive := $(if $(findstring n,$(firstword $(MFLAGS))),,+)
override mflags := $(filter-out -j%,$(MFLAGS))
MSPECOPT += $(if $(filter -j%,$(MFLAGS)),-j)
@@ -161,6 +162,10 @@ endif
config.status: $(wildcard config.cache)
+ifneq (ruby,$(PROGRAM))
+ruby: $(PROGRAM);
+endif
+
STUBPROGRAM = rubystub$(EXEEXT)
IGNOREDPATTERNS = %~ .% %.orig %.rej \#%\#
SCRIPTBINDIR := $(if $(EXEEXT),,exec/)
@@ -204,7 +209,7 @@ post-commit: $(if $(DOT_WAIT),,do-commit)
+$(Q) \
{ \
$(in-srcdir) \
- exec sed -f tool/prereq.status defs/gmake.mk template/Makefile.in common.mk; \
+ exec sed -f tool/prereq.status defs/gmake.mk template/Makefile.in common.mk depend; \
} | \
$(MAKE) $(mflags) Q=$(Q) ECHO=$(ECHO) \
top_srcdir="$(top_srcdir)" srcdir="$(srcdir)" srcs_vpath="" CHDIR="$(CHDIR)" \
@@ -216,8 +221,8 @@ post-commit: $(if $(DOT_WAIT),,do-commit)
GITHUB_RUBY_URL = https://github.com/ruby/ruby
PR =
-COMMIT_GPG_SIGN = $(shell $(GIT) -C "$(srcdir)" config commit.gpgsign)
-REMOTE_GITHUB_URL = $(shell $(GIT) -C "$(srcdir)" config remote.github.url)
+COMMIT_GPG_SIGN = $(shell $(GIT_IN_SRC) config commit.gpgsign)
+REMOTE_GITHUB_URL = $(shell $(GIT_IN_SRC) config remote.github.url)
COMMITS_NOTES = commits
.PHONY: fetch-github
@@ -232,19 +237,19 @@ define fetch-github
$(eval REMOTE_GITHUB_URL := $(REMOTE_GITHUB_URL))
$(if $(REMOTE_GITHUB_URL),,
echo adding $(GITHUB_RUBY_URL) as remote github
- $(GIT) -C "$(srcdir)" remote add github $(GITHUB_RUBY_URL)
- $(GIT) -C "$(srcdir)" config --add remote.github.fetch +refs/notes/$(COMMITS_NOTES):refs/notes/$(COMMITS_NOTES)
+ $(GIT_IN_SRC) remote add github $(GITHUB_RUBY_URL)
+ $(GIT_IN_SRC) config --add remote.github.fetch +refs/notes/$(COMMITS_NOTES):refs/notes/$(COMMITS_NOTES)
$(eval REMOTE_GITHUB_URL := $(GITHUB_RUBY_URL))
)
- $(if $(shell $(GIT) -C "$(srcdir)" rev-parse "github/pull/$(1)/head" -- 2> /dev/null),
- $(GIT) -C "$(srcdir)" branch -f "gh-$(1)" "github/pull/$(1)/head",
- $(GIT) -C "$(srcdir)" fetch -f github "pull/$(1)/head:gh-$(1)"
+ $(if $(shell $(GIT_IN_SRC) rev-parse "github/pull/$(1)/head" -- 2> /dev/null),
+ $(GIT_IN_SRC) branch -f "gh-$(1)" "github/pull/$(1)/head",
+ $(GIT_IN_SRC) fetch -f github "pull/$(1)/head:gh-$(1)"
)
endef
.PHONY: checkout-github
checkout-github: fetch-github
- $(GIT) -C "$(srcdir)" checkout "gh-$(PR)"
+ $(GIT_IN_SRC) checkout "gh-$(PR)"
.PHONY: update-github
update-github: fetch-github
@@ -257,25 +262,25 @@ update-github: fetch-github
$(eval PR_BRANCH := $(word 2,$(PULL_REQUEST_FORK_BRANCH)))
$(eval GITHUB_UPDATE_WORKTREE := $(shell mktemp -d "$(srcdir)/gh-$(PR)-XXXXXX"))
- $(GIT) -C "$(srcdir)" worktree add $(notdir $(GITHUB_UPDATE_WORKTREE)) "gh-$(PR)"
+ $(GIT_IN_SRC) worktree add $(notdir $(GITHUB_UPDATE_WORKTREE)) "gh-$(PR)"
$(GIT) -C "$(GITHUB_UPDATE_WORKTREE)" merge master --no-edit
@$(BASERUBY) -e 'print "Are you sure to push this to PR=$(PR)? [Y/n]: "; exit(gets.chomp != "n")'
- $(GIT) -C "$(srcdir)" remote add fork-$(PR) git@github.com:$(FORK_REPO).git
+ $(GIT_IN_SRC) remote add fork-$(PR) git@github.com:$(FORK_REPO).git
$(GIT) -C "$(GITHUB_UPDATE_WORKTREE)" push fork-$(PR) gh-$(PR):$(PR_BRANCH)
- $(GIT) -C "$(srcdir)" remote rm fork-$(PR)
- $(GIT) -C "$(srcdir)" worktree remove $(notdir $(GITHUB_UPDATE_WORKTREE))
- $(GIT) -C "$(srcdir)" branch -D gh-$(PR)
+ $(GIT_IN_SRC) remote rm fork-$(PR)
+ $(GIT_IN_SRC) worktree remove $(notdir $(GITHUB_UPDATE_WORKTREE))
+ $(GIT_IN_SRC) branch -D gh-$(PR)
.PHONY: pull-github
pull-github: fetch-github
$(call pull-github,$(PR))
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_BASE := $(shell $(GIT_LOG_FORMAT)%H -1)
+ $(eval GITHUB_MERGE_BRANCH := $(shell $(GIT_IN_SRC) 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_IN_SRC) worktree prune
+ $(GIT_IN_SRC) worktree add $(notdir $(GITHUB_MERGE_WORKTREE)) "gh-$(1)"
$(GIT) -C "$(GITHUB_MERGE_WORKTREE)" rebase $(GITHUB_MERGE_BRANCH)
$(eval COMMIT_GPG_SIGN := $(COMMIT_GPG_SIGN))
$(if $(filter true,$(COMMIT_GPG_SIGN)), \
@@ -290,7 +295,7 @@ fetch-github-%:
.PHONY: checkout-github-%
checkout-github-%: fetch-github-%
- $(GIT) -C "$(srcdir)" checkout "gh-$*"
+ $(GIT_IN_SRC) checkout "gh-$*"
.PHONY: pr-% pull-github-%
pr-% pull-github-%: fetch-github-%
@@ -309,7 +314,7 @@ HELP_EXTRA_TASKS = \
# 4. "gem x.y.z URL" -> "gem-x.y.z"
bundled-gems := $(shell sed \
-e 's/[ ][ ]*/ /g' \
- -e 's/^ //;/\#/d;s/ *$$//;/^$$/d' \
+ -e 's/^ //;s/\#.*//;s/ *$$//;/^$$/d' \
$(if $(filter yes,$(HAVE_GIT)), \
-e 's/^\(.*\) \(.*\) \(.*\) \(.*\)/\1|\2|\4|\3/' \
) \
@@ -365,7 +370,7 @@ $(srcdir)/.bundle/.timestamp:
define build-gem
$(srcdir)/gems/src/$(1)/.git: | $(srcdir)/gems/src
$(ECHO) Cloning $(4)
- $(Q) $(GIT) clone $(4) $$(@D)
+ $(Q) $(GIT) clone --depth=1 --no-tags $(4) $$(@D)
$(bundled-gem-revision): \
$(if $(if $(wildcard $$(@)),$(filter $(3),$(shell cat $$(@)))),,PHONY) \
@@ -429,7 +434,7 @@ ifneq ($(DOT_WAIT),)
endif
ifeq ($(HAVE_GIT),yes)
-REVISION_LATEST := $(shell $(CHDIR) $(srcdir) && $(GIT) log -1 --format=%H 2>/dev/null)
+REVISION_LATEST := $(shell $(GIT_LOG_FORMAT)%H -1 2>/dev/null)
else
REVISION_LATEST := update
endif
@@ -442,6 +447,8 @@ $(REVISION_H): PHONY
endif
include $(top_srcdir)/yjit/yjit.mk
+include $(top_srcdir)/zjit/zjit.mk
+include $(top_srcdir)/defs/jit.mk
# Query on the generated rdoc
#
@@ -489,7 +496,7 @@ endif
update-deps:
$(eval update_deps := $(shell date +update-deps-%Y%m%d))
$(eval deps_dir := $(shell mktemp -d)/$(update_deps))
- $(eval GIT_DIR := $(shell $(GIT) -C $(srcdir) rev-parse --absolute-git-dir))
+ $(eval GIT_DIR := $(shell $(GIT_IN_SRC) rev-parse --absolute-git-dir))
$(GIT) --git-dir=$(GIT_DIR) worktree add $(deps_dir)
cp $(tooldir)/config.guess $(tooldir)/config.sub $(deps_dir)/tool
[ -f config.status ] && cp config.status $(deps_dir)
@@ -503,10 +510,14 @@ update-deps:
$(GIT) --git-dir=$(GIT_DIR) merge --no-edit --ff-only $(update_deps)
$(GIT) --git-dir=$(GIT_DIR) branch --delete $(update_deps)
+fix-depends check-depends: all hello
+ $(BASERUBY) -C $(srcdir) tool/update-deps $(if $(filter fix-%,$@),--fix)
+
# 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 $@
+$(RUBYSPEC_CAPIEXT)/%.$(DLEXT): $(srcdir)/$(RUBYSPEC_CAPIEXT)/%.c $(RUBYSPEC_CAPIEXT_DEPS) \
+ | build-ext
+ $(no_silence:no=$(ECHO) building $@)
$(Q) $(MAKEDIRS) $(@D)
$(Q) $(DLDSHARED) -L. $(XDLDFLAGS) $(XLDFLAGS) $(LDFLAGS) $(INCFLAGS) $(CPPFLAGS) $(OUTFLAG)$@ $< $(LIBRUBYARG)
ifneq ($(POSTLINK),)
@@ -518,40 +529,83 @@ RUBYSPEC_CAPIEXT_SO := $(patsubst %.c,$(RUBYSPEC_CAPIEXT)/%.$(DLEXT),$(notdir $(
rubyspec-capiext: $(RUBYSPEC_CAPIEXT_SO)
@ $(NULLCMD)
-ifeq ($(ENABLE_SHARED),yes)
-ruby: $(if $(LIBRUBY_SO_UPDATE),$(RUBYSPEC_CAPIEXT_SO))
-exts: rubyspec-capiext
-endif
-
-spec/%/ spec/%_spec.rb: programs exts PHONY
+spec/%/ spec/%_spec.rb: programs exts $(RUBYSPEC_CAPIEXT_BUILD) 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))
+# `make matz`: bump up the MINOR;
+# Copying NEWS.md to doc/NEWS/, and empty the details in NEWS.md.
+#
+# `make matz NEW=x.y`: bump up to x.y.0;
+# Just update the version in the title of NEWS.md.
+
matz: up
- $(eval OLD := $(MAJOR).$(MINOR).0)
- $(eval MINOR := $(shell expr $(MINOR) + 1))
- $(eval NEW := $(MAJOR).$(MINOR).0)
- $(eval message := Development of $(NEW) started.)
- $(eval files := include/ruby/version.h include/ruby/internal/abi.h)
- $(GIT) -C $(srcdir) mv -f NEWS.md doc/NEWS/NEWS-$(OLD).md
- $(GIT) -C $(srcdir) commit -m "[DOC] Flush NEWS.md"
+matz-commit: OLD := $(MAJOR).$(MINOR).0
+ifdef NEW
+matz-commit: MAJOR := $(word 1,$(subst ., ,$(NEW)))
+matz-commit: MINOR := $(word 2,$(subst ., ,$(NEW)))
+matz-commit: $(DOT_WAIT) bump_news
+bump_news$(DOT_WAIT): up
+bump_headers$(DOT_WAIT): bump_news
+else
+matz-commit: MINOR := $(shell expr $(MINOR) + 1)
+matz-commit: $(DOT_WAIT) reset_news
+flush_news$(DOT_WAIT): up
+bump_headers$(DOT_WAIT): reset_news
+endif
+
+matz: $(DOT_WAIT) matz-commit
+matz-commit: bump_headers
+matz-commit: override NEW := $(MAJOR).$(MINOR).0
+matz-commit: files := include/ruby/version.h include/ruby/internal/abi.h
+matz-commit: message := Development of $(NEW) started.
+
+flush_news:
+ $(GIT_IN_SRC) mv -f NEWS.md doc/NEWS/NEWS-$(OLD).md
+ $(GIT_IN_SRC) commit -m "[DOC] Flush NEWS.md"
+
+.PHONY: flush_news reset_news bump_news bump_headers
+
+bump_headers:
sed -i~ \
+ -e "s/^\(#define RUBY_API_VERSION_MAJOR\) .*/\1 $(MAJOR)/" \
-e "s/^\(#define RUBY_API_VERSION_MINOR\) .*/\1 $(MINOR)/" \
-e "s/^\(#define RUBY_ABI_VERSION\) .*/\1 0/" \
$(files:%=$(srcdir)/%)
- $(GIT) -C $(srcdir) add $(files)
+
+reset_news: flush_news
$(BASERUBY) -C $(srcdir) -p -00 \
- -e 'BEGIN {old, new = ARGV.shift(2); STDOUT.reopen("NEWS.md")}' \
+ -e 'BEGIN {old, new = ARGV.shift(2); STDOUT.reopen(ARGV.shift)}' \
-e 'case $$.' \
-e 'when 1; $$_.sub!(/Ruby \K[0-9.]+/, new)' \
-e 'when 2; $$_.sub!(/\*\*\K[0-9.]+(?=\*\*)/, old)' \
-e 'end' \
-e 'next if /^[\[ *]/ =~ $$_' \
-e '$$_.sub!(/\n{2,}\z/, "\n\n")' \
- $(OLD) $(NEW) doc/NEWS/NEWS-$(OLD).md
- $(GIT) -C $(srcdir) add NEWS.md
- $(GIT) -C $(srcdir) commit -m "$(message)"
+ $(OLD) $(NEW) NEWS.md doc/NEWS/NEWS-$(OLD).md
+
+bump_news:
+ $(BASERUBY) -C $(srcdir) -p -i \
+ -e 'BEGIN {new = ARGV.shift; print gets("").sub(/Ruby \K[0-9.]+/, new)}' \
+ $(NEW) NEWS.md
+
+matz: matz-commit matz-push
+
+matz-commit:
+ $(GIT_IN_SRC) add NEWS.md $(files)
+ $(GIT_IN_SRC) commit -m "$(message)"
+
+GIT_REMOTE_ORIGIN = origin
+
+matz-push: matz-commit
+ $(eval origin_url := $(shell $(GIT_IN_SRC) remote get-url $(GIT_REMOTE_ORIGIN)))
+ $(if $(origin_url),,@false)
+ $(eval last_commit := $(shell $(GIT_IN_SRC) log -n1 --format=%H --author=matz HEAD~..HEAD))
+ $(if $(last_commit),,$(ECHO) No matz commits 1>&2; false)
+ $(if $(filter 12-25 12-26,$(shell date +%m-%d)),,$(ECHO) Not the release date 1>&2; false)
+ $(ECHO) $$'\e[31m'Pushing to $$'\e[7m'$(GIT_REMOTE_ORIGIN)$$'\e[27m'" ($(origin_url))"$$'\e[m'
+ $(GIT_IN_SRC) push $(GIT_REMOTE_ORIGIN)
tags:
$(MAKE) GIT="$(GIT)" -C "$(srcdir)" -f defs/tags.mk
diff --git a/defs/id.def b/defs/id.def
index 71baa4f968..cd3a8480a2 100644
--- a/defs/id.def
+++ b/defs/id.def
@@ -8,6 +8,7 @@ firstline, predefined = __LINE__+1, %[\
inspect
intern
object_id
+ __id__
const_added
const_missing
method_missing MethodMissing
@@ -60,6 +61,10 @@ firstline, predefined = __LINE__+1, %[\
nil
path
pack
+ buffer
+ include?
+ aborted
+ exited
_ UScore
@@ -73,6 +78,8 @@ firstline, predefined = __LINE__+1, %[\
_7 NUMPARAM_7
_8 NUMPARAM_8
_9 NUMPARAM_9
+ <it> ItImplicit
+ it It
"/*NULL*/" NULL
empty?
@@ -98,6 +105,8 @@ firstline, predefined = __LINE__+1, %[\
$_ LASTLINE
$~ BACKREF
$! ERROR_INFO
+
+ Ruby
]
# VM ID OP Parser Token
diff --git a/defs/jit.mk b/defs/jit.mk
new file mode 100644
index 0000000000..27b14e7a07
--- /dev/null
+++ b/defs/jit.mk
@@ -0,0 +1,96 @@
+# Make recipes that deal with the rust code of YJIT and ZJIT.
+#
+# $(gnumake_recursive) adds the '+' prefix to pass down GNU make's
+# jobserver resources to cargo/rustc as rust-lang.org recommends.
+# Without it, certain make version trigger a warning. It does not
+# add the prefix when `make --dry-run` so dry runs are indeed dry.
+
+ifneq ($(JIT_CARGO_SUPPORT),no)
+
+# Show Cargo progress when doing `make V=1`
+CARGO_VERBOSE_0 = -q
+CARGO_VERBOSE_1 =
+CARGO_VERBOSE = $(CARGO_VERBOSE_$(V))
+
+# Because of Cargo cache, if the actual binary is not changed from the
+# previous build, the mtime is preserved as the cached file.
+# This means the target is not updated actually, and it will need to
+# rebuild at the next build.
+RUST_LIB_TOUCH = touch $@
+
+# NOTE: MACOSX_DEPLOYMENT_TARGET to match `rustc --print deployment-target` to avoid the warning below.
+# ld: warning: object file (target/debug/libjit.a(<libcapstone object>)) was built for
+# newer macOS version (15.2) than being linked (15.0)
+# This limits us to an older set of macOS API in the rust code, but we don't use any.
+$(RUST_LIB): $(srcdir)/ruby.rs
+ $(Q)if [ '$(ZJIT_SUPPORT)' != no -a '$(YJIT_SUPPORT)' != no ]; then \
+ echo 'building YJIT and ZJIT ($(JIT_CARGO_SUPPORT:yes=release) mode)'; \
+ elif [ '$(ZJIT_SUPPORT)' != no ]; then \
+ echo 'building ZJIT ($(JIT_CARGO_SUPPORT) mode)'; \
+ elif [ '$(YJIT_SUPPORT)' != no ]; then \
+ echo 'building YJIT ($(JIT_CARGO_SUPPORT) mode)'; \
+ fi
+ $(gnumake_recursive)$(Q)CARGO_TARGET_DIR='$(CARGO_TARGET_DIR)' \
+ CARGO_TERM_PROGRESS_WHEN='never' \
+ MACOSX_DEPLOYMENT_TARGET=11.0 \
+ $(CARGO) $(CARGO_VERBOSE) build --manifest-path '$(top_srcdir)/Cargo.toml' $(CARGO_BUILD_ARGS)
+ $(RUST_LIB_TOUCH)
+else ifneq ($(strip $(RLIB_DIR)),) # combo build
+
+$(RUST_LIB): $(srcdir)/ruby.rs
+ $(ECHO) 'building $(@F)'
+ $(gnumake_recursive)$(Q) $(RUSTC) --edition=2024 \
+ $(RUSTC_FLAGS) \
+ '-L$(@D)' \
+ --extern=yjit \
+ --extern=zjit \
+ --crate-type=staticlib \
+ --cfg 'feature="yjit"' \
+ --cfg 'feature="zjit"' \
+ '--out-dir=$(@D)' \
+ '$(top_srcdir)/ruby.rs'
+
+# Absolute path to avoid VPATH ambiguity
+JIT_RLIB = $(TOP_BUILD_DIR)/$(RLIB_DIR)/libjit.rlib
+$(YJIT_RLIB): $(JIT_RLIB)
+$(ZJIT_RLIB): $(JIT_RLIB)
+$(JIT_RLIB):
+ $(ECHO) 'building $(@F)'
+ $(gnumake_recursive)$(Q) $(RUSTC) --crate-name=jit \
+ --edition=2024 \
+ $(JIT_RUST_FLAGS) \
+ $(RUSTC_FLAGS) \
+ '--out-dir=$(@D)' \
+ '$(top_srcdir)/jit/src/lib.rs'
+endif # ifneq ($(JIT_CARGO_SUPPORT),no)
+
+RUST_LIB_SYMBOLS = $(RUST_LIB:.a=).symbols
+$(RUST_LIBOBJ): $(RUST_LIB)
+ $(ECHO) 'partial linking $(RUST_LIB) into $@'
+ifneq ($(findstring darwin,$(target_os)),)
+ $(Q) $(CC) -nodefaultlibs -r -o $@ -exported_symbols_list $(RUST_LIB_SYMBOLS) $(RUST_LIB)
+else
+ $(Q) $(LD) -r -o $@ --whole-archive $(RUST_LIB)
+ -$(Q) $(OBJCOPY) --wildcard --keep-global-symbol='$(SYMBOL_PREFIX)rb_*' $(@)
+endif
+
+rust-libobj: $(RUST_LIBOBJ)
+rust-lib: $(RUST_LIB)
+
+# For Darwin only: a list of symbols that we want the glommed Rust static lib to export.
+# Unfortunately, using wildcard like '_rb_*' with -exported-symbol does not work, at least
+# not on version 820.1. Assume llvm-nm, so XCode 8.0 (from 2016) or newer.
+#
+# The -exported_symbols_list pulls out the right archive members. Symbols not listed
+# in the list are made private extern, which are in turn made local as we're using `ld -r`.
+# Note, section about -keep_private_externs in ld's man page hints at this behavior on which
+# we rely.
+ifneq ($(findstring darwin,$(target_os)),)
+$(RUST_LIB_SYMBOLS): $(RUST_LIB)
+ $(Q) $(tooldir)/darwin-ar $(NM) --defined-only --extern-only $(RUST_LIB) | \
+ sed -n -e 's/.* //' -e '/^$(SYMBOL_PREFIX)rb_/p' \
+ -e '/^$(SYMBOL_PREFIX)rust_eh_personality/p' \
+ > $@
+
+$(RUST_LIBOBJ): $(RUST_LIB_SYMBOLS)
+endif
diff --git a/defs/known_errors.def b/defs/known_errors.def
index 14b3cff265..23e9e53507 100644
--- a/defs/known_errors.def
+++ b/defs/known_errors.def
@@ -1,157 +1,157 @@
E2BIG Argument list too long
EACCES Permission denied
-EADDRINUSE Address in use
+EADDRINUSE Address already in use
EADDRNOTAVAIL Address not available
-EADV
+EADV Advertise error
EAFNOSUPPORT Address family not supported
-EAGAIN Resource unavailable, try again (may be the same value as [EWOULDBLOCK])
+EAGAIN Resource temporarily unavailable, try again (may be the same value as EWOULDBLOCK)
EALREADY Connection already in progress
-EAUTH
-EBADARCH
-EBADE
-EBADEXEC
+EAUTH Authentication error
+EBADARCH Bad CPU type in executable
+EBADE Bad exchange
+EBADEXEC Bad executable
EBADF Bad file descriptor
-EBADFD
-EBADMACHO
+EBADFD File descriptor in bad state
+EBADMACHO Malformed Macho file
EBADMSG Bad message
-EBADR
-EBADRPC
-EBADRQC
-EBADSLT
-EBFONT
+EBADR Invalid request descriptor
+EBADRPC RPC struct is bad
+EBADRQC Invalid request code
+EBADSLT Invalid slot
+EBFONT Bad font file format
EBUSY Device or resource busy
ECANCELED Operation canceled
-ECAPMODE
+ECAPMODE Not permitted in capability mode
ECHILD No child processes
-ECHRNG
-ECOMM
+ECHRNG Channel number out of range
+ECOMM Communication error on send
ECONNABORTED Connection aborted
ECONNREFUSED Connection refused
ECONNRESET Connection reset
-EDEADLK Resource deadlock would occur
-EDEADLOCK
+EDEADLK Resource deadlock avoided
+EDEADLOCK File locking deadlock error
EDESTADDRREQ Destination address required
-EDEVERR
+EDEVERR Device error; e.g., printer paper out
EDOM Mathematics argument out of domain of function
-EDOOFUS
-EDOTDOT
-EDQUOT Reserved
+EDOOFUS Improper function use
+EDOTDOT RFS specific error
+EDQUOT Disk quota exceeded
EEXIST File exists
EFAULT Bad address
EFBIG File too large
-EFTYPE
-EHOSTDOWN
+EFTYPE Invalid file type or format
+EHOSTDOWN Host is down
EHOSTUNREACH Host is unreachable
-EHWPOISON
+EHWPOISON Memory page has hardware error
EIDRM Identifier removed
-EILSEQ Illegal byte sequence
+EILSEQ Invalid or incomplete multibyte or wide character
EINPROGRESS Operation in progress
-EINTR Interrupted function
+EINTR Interrupted function call
EINVAL Invalid argument
-EIO I/O error
-EIPSEC
+EIO Input/output error
+EIPSEC IPsec processing failure
EISCONN Socket is connected
EISDIR Is a directory
-EISNAM
-EKEYEXPIRED
-EKEYREJECTED
-EKEYREVOKED
-EL2HLT
-EL2NSYNC
-EL3HLT
-EL3RST
-ELIBACC
-ELIBBAD
-ELIBEXEC
-ELIBMAX
-ELIBSCN
-ELNRNG
+EISNAM Is a named file type
+EKEYEXPIRED Key has expired
+EKEYREJECTED Key was rejected by service
+EKEYREVOKED Key has been revoked
+EL2HLT Level 2 halted
+EL2NSYNC Level 2 not synchronized
+EL3HLT Level 3 halted
+EL3RST Level 3 reset
+ELIBACC Cannot access a needed shared library
+ELIBBAD Accessing a corrupted shared library
+ELIBEXEC Cannot exec a shared library directly
+ELIBMAX Attempting to link in too many shared libraries
+ELIBSCN .lib section in a.out corrupted
+ELNRNG Link number out of range
ELOOP Too many levels of symbolic links
-EMEDIUMTYPE
-EMFILE File descriptor value too large
+EMEDIUMTYPE Wrong medium type
+EMFILE Too many open files
EMLINK Too many links
-EMSGSIZE Message too large
-EMULTIHOP Reserved
+EMSGSIZE Message too long
+EMULTIHOP Multihop attempted
ENAMETOOLONG Filename too long
-ENAVAIL
-ENEEDAUTH
+ENAVAIL No XENIX semaphores available
+ENEEDAUTH Need authenticator
ENETDOWN Network is down
ENETRESET Connection aborted by network
ENETUNREACH Network unreachable
-ENFILE Too many files open in system
-ENOANO
-ENOATTR
+ENFILE Too many open files in system
+ENOANO No anode
+ENOATTR Attribute not found
ENOBUFS No buffer space available
-ENOCSI
-ENODATA [OB XSR] [Option Start] No message is available on the STREAM head read queue [Option End]
+ENOCSI No CSI structure available
+ENODATA No data available
ENODEV No such device
ENOENT No such file or directory
-ENOEXEC Executable file format error
-ENOKEY
+ENOEXEC Exec format error
+ENOKEY Required key not available
ENOLCK No locks available
-ENOLINK Reserved
-ENOMEDIUM
-ENOMEM Not enough space
+ENOLINK Link has been severed
+ENOMEDIUM No medium found
+ENOMEM Not enough space/cannot allocate memory
ENOMSG No message of the desired type
-ENONET
-ENOPKG
-ENOPOLICY
+ENONET Machine is not on the network
+ENOPKG Package not installed
+ENOPOLICY No such policy
ENOPROTOOPT Protocol not available
ENOSPC No space left on device
-ENOSR [OB XSR] [Option Start] No STREAM resources [Option End]
-ENOSTR [OB XSR] [Option Start] Not a STREAM [Option End]
-ENOSYS Functionality not supported
-ENOTBLK
-ENOTCAPABLE
+ENOSR No STREAM resources
+ENOSTR Not a STREAM
+ENOSYS Functionality not implemented
+ENOTBLK Block device required
+ENOTCAPABLE Capabilities insufficient
ENOTCONN The socket is not connected
-ENOTDIR Not a directory or a symbolic link to a directory
+ENOTDIR Not a directory
ENOTEMPTY Directory not empty
-ENOTNAM
+ENOTNAM Not a XENIX named type file
ENOTRECOVERABLE State not recoverable
ENOTSOCK Not a socket
-ENOTSUP Not supported (may be the same value as [EOPNOTSUPP])
+ENOTSUP Operation not supported
ENOTTY Inappropriate I/O control operation
-ENOTUNIQ
+ENOTUNIQ Name not unique on network
ENXIO No such device or address
-EOPNOTSUPP Operation not supported on socket (may be the same value as [ENOTSUP])
+EOPNOTSUPP Operation not supported on socket
EOVERFLOW Value too large to be stored in data type
-EOWNERDEAD Previous owner died
+EOWNERDEAD Owner died
EPERM Operation not permitted
-EPFNOSUPPORT
+EPFNOSUPPORT Protocol family not supported
EPIPE Broken pipe
-EPROCLIM
-EPROCUNAVAIL
-EPROGMISMATCH
-EPROGUNAVAIL
+EPROCLIM Too many processes
+EPROCUNAVAIL Bad procedure for program
+EPROGMISMATCH Program version wrong
+EPROGUNAVAIL RPC program isn't available
EPROTO Protocol error
EPROTONOSUPPORT Protocol not supported
EPROTOTYPE Protocol wrong type for socket
-EPWROFF
-EQFULL
+EPWROFF Device power is off
+EQFULL Interface output queue is full
ERANGE Result too large
-EREMCHG
-EREMOTE
-EREMOTEIO
-ERESTART
-ERFKILL
+EREMCHG Remote address changed
+EREMOTE Object is remote
+EREMOTEIO Remote I/O error
+ERESTART Interrupted system call should be restarted
+ERFKILL Operation not possible due to RF-kill
EROFS Read-only file system
-ERPCMISMATCH
-ESHLIBVERS
-ESHUTDOWN
-ESOCKTNOSUPPORT
-ESPIPE Invalid seek
+ERPCMISMATCH RPC version wrong
+ESHLIBVERS Shared library version mismatch
+ESHUTDOWN Cannot send after transport endpoint shutdown
+ESOCKTNOSUPPORT Socket type not supported
+ESPIPE Illegal seek
ESRCH No such process
-ESRMNT
-ESTALE Reserved
-ESTRPIPE
-ETIME [OB XSR] [Option Start] Stream ioctl() timeout [Option End]
+ESRMNT Server mount error
+ESTALE Stale file handle
+ESTRPIPE Streams pipe error
+ETIME Timer expired
ETIMEDOUT Connection timed out
-ETOOMANYREFS
+ETOOMANYREFS Too many references: cannot splice
ETXTBSY Text file busy
-EUCLEAN
-EUNATCH
-EUSERS
-EWOULDBLOCK Operation would block (may be the same value as [EAGAIN])
-EXDEV Cross-device link
-EXFULL
-ELAST Largest errno
+EUCLEAN Structure needs cleaning
+EUNATCH Protocol driver not attached
+EUSERS Too many users
+EWOULDBLOCK Operation would block
+EXDEV Invalid cross-device link
+EXFULL Exchange full
+ELAST Largest errno value
diff --git a/depend b/depend
new file mode 100644
index 0000000000..7372902666
--- /dev/null
+++ b/depend
@@ -0,0 +1,20573 @@
+# 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/packed_struct.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): $(CCAN_DIR)/check_type/check_type.h
+array.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+array.$(OBJEXT): $(CCAN_DIR)/list/list.h
+array.$(OBJEXT): $(CCAN_DIR)/str/str.h
+array.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+array.$(OBJEXT): $(top_srcdir)/internal/array.h
+array.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+array.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+array.$(OBJEXT): $(top_srcdir)/internal/bits.h
+array.$(OBJEXT): $(top_srcdir)/internal/box.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/imemo.h
+array.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+array.$(OBJEXT): $(top_srcdir)/internal/object.h
+array.$(OBJEXT): $(top_srcdir)/internal/proc.h
+array.$(OBJEXT): $(top_srcdir)/internal/rational.h
+array.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+array.$(OBJEXT): $(top_srcdir)/internal/serial.h
+array.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+array.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+array.$(OBJEXT): $(top_srcdir)/internal/variable.h
+array.$(OBJEXT): $(top_srcdir)/internal/vm.h
+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)}atomic.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)}constant.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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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)}method.h
+array.$(OBJEXT): {$(VPATH)}missing.h
+array.$(OBJEXT): {$(VPATH)}node.h
+array.$(OBJEXT): {$(VPATH)}onigmo.h
+array.$(OBJEXT): {$(VPATH)}oniguruma.h
+array.$(OBJEXT): {$(VPATH)}probes.dmyh
+array.$(OBJEXT): {$(VPATH)}probes.h
+array.$(OBJEXT): {$(VPATH)}ractor.h
+array.$(OBJEXT): {$(VPATH)}ruby_assert.h
+array.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+array.$(OBJEXT): {$(VPATH)}rubyparser.h
+array.$(OBJEXT): {$(VPATH)}shape.h
+array.$(OBJEXT): {$(VPATH)}st.h
+array.$(OBJEXT): {$(VPATH)}subst.h
+array.$(OBJEXT): {$(VPATH)}thread.h
+array.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+array.$(OBJEXT): {$(VPATH)}thread_native.h
+array.$(OBJEXT): {$(VPATH)}util.h
+array.$(OBJEXT): {$(VPATH)}vm_core.h
+array.$(OBJEXT): {$(VPATH)}vm_opts.h
+ast.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+ast.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+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/basic_operators.h
+ast.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+ast.$(OBJEXT): $(top_srcdir)/internal/bits.h
+ast.$(OBJEXT): $(top_srcdir)/internal/box.h
+ast.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+ast.$(OBJEXT): $(top_srcdir)/internal/complex.h
+ast.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+ast.$(OBJEXT): $(top_srcdir)/internal/gc.h
+ast.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+ast.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+ast.$(OBJEXT): $(top_srcdir)/internal/parse.h
+ast.$(OBJEXT): $(top_srcdir)/internal/rational.h
+ast.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
+ast.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+ast.$(OBJEXT): $(top_srcdir)/internal/serial.h
+ast.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+ast.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+ast.$(OBJEXT): $(top_srcdir)/internal/struct.h
+ast.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+ast.$(OBJEXT): $(top_srcdir)/internal/variable.h
+ast.$(OBJEXT): $(top_srcdir)/internal/vm.h
+ast.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+ast.$(OBJEXT): $(top_srcdir)/prism/ast.h
+ast.$(OBJEXT): $(top_srcdir)/prism/defines.h
+ast.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+ast.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+ast.$(OBJEXT): $(top_srcdir)/prism/node.h
+ast.$(OBJEXT): $(top_srcdir)/prism/options.h
+ast.$(OBJEXT): $(top_srcdir)/prism/pack.h
+ast.$(OBJEXT): $(top_srcdir)/prism/parser.h
+ast.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+ast.$(OBJEXT): $(top_srcdir)/prism/prism.h
+ast.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+ast.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+ast.$(OBJEXT): $(top_srcdir)/prism/version.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)}constant.h
+ast.$(OBJEXT): {$(VPATH)}defines.h
+ast.$(OBJEXT): {$(VPATH)}encoding.h
+ast.$(OBJEXT): {$(VPATH)}id.h
+ast.$(OBJEXT): {$(VPATH)}id_table.h
+ast.$(OBJEXT): {$(VPATH)}intern.h
+ast.$(OBJEXT): {$(VPATH)}internal.h
+ast.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/set.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/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/stdckdint.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
+ast.$(OBJEXT): {$(VPATH)}node.h
+ast.$(OBJEXT): {$(VPATH)}onigmo.h
+ast.$(OBJEXT): {$(VPATH)}oniguruma.h
+ast.$(OBJEXT): {$(VPATH)}prism_compile.h
+ast.$(OBJEXT): {$(VPATH)}ruby_assert.h
+ast.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+ast.$(OBJEXT): {$(VPATH)}rubyparser.h
+ast.$(OBJEXT): {$(VPATH)}shape.h
+ast.$(OBJEXT): {$(VPATH)}st.h
+ast.$(OBJEXT): {$(VPATH)}subst.h
+ast.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+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): $(CCAN_DIR)/check_type/check_type.h
+bignum.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+bignum.$(OBJEXT): $(CCAN_DIR)/list/list.h
+bignum.$(OBJEXT): $(CCAN_DIR)/str/str.h
+bignum.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/array.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/bits.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/box.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/imemo.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/object.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/serial.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+bignum.$(OBJEXT): $(top_srcdir)/internal/struct.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)}atomic.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)}encoding.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/abi.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/packed_struct.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/encoding/coderange.h
+bignum.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+bignum.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+bignum.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+bignum.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+bignum.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+bignum.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+bignum.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+bignum.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.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/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/set.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/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/stdckdint.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)}method.h
+bignum.$(OBJEXT): {$(VPATH)}missing.h
+bignum.$(OBJEXT): {$(VPATH)}node.h
+bignum.$(OBJEXT): {$(VPATH)}onigmo.h
+bignum.$(OBJEXT): {$(VPATH)}oniguruma.h
+bignum.$(OBJEXT): {$(VPATH)}ruby_assert.h
+bignum.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+bignum.$(OBJEXT): {$(VPATH)}rubyparser.h
+bignum.$(OBJEXT): {$(VPATH)}shape.h
+bignum.$(OBJEXT): {$(VPATH)}st.h
+bignum.$(OBJEXT): {$(VPATH)}subst.h
+bignum.$(OBJEXT): {$(VPATH)}thread.h
+bignum.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+bignum.$(OBJEXT): {$(VPATH)}thread_native.h
+bignum.$(OBJEXT): {$(VPATH)}util.h
+bignum.$(OBJEXT): {$(VPATH)}vm_core.h
+bignum.$(OBJEXT): {$(VPATH)}vm_opts.h
+box.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+box.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+box.$(OBJEXT): $(CCAN_DIR)/list/list.h
+box.$(OBJEXT): $(CCAN_DIR)/str/str.h
+box.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+box.$(OBJEXT): $(top_srcdir)/internal/array.h
+box.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+box.$(OBJEXT): $(top_srcdir)/internal/box.h
+box.$(OBJEXT): $(top_srcdir)/internal/class.h
+box.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+box.$(OBJEXT): $(top_srcdir)/internal/error.h
+box.$(OBJEXT): $(top_srcdir)/internal/eval.h
+box.$(OBJEXT): $(top_srcdir)/internal/file.h
+box.$(OBJEXT): $(top_srcdir)/internal/gc.h
+box.$(OBJEXT): $(top_srcdir)/internal/hash.h
+box.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+box.$(OBJEXT): $(top_srcdir)/internal/io.h
+box.$(OBJEXT): $(top_srcdir)/internal/load.h
+box.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+box.$(OBJEXT): $(top_srcdir)/internal/serial.h
+box.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+box.$(OBJEXT): $(top_srcdir)/internal/st.h
+box.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+box.$(OBJEXT): $(top_srcdir)/internal/string.h
+box.$(OBJEXT): $(top_srcdir)/internal/struct.h
+box.$(OBJEXT): $(top_srcdir)/internal/variable.h
+box.$(OBJEXT): $(top_srcdir)/internal/vm.h
+box.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+box.$(OBJEXT): $(top_srcdir)/prism/ast.h
+box.$(OBJEXT): $(top_srcdir)/prism/defines.h
+box.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+box.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+box.$(OBJEXT): $(top_srcdir)/prism/node.h
+box.$(OBJEXT): $(top_srcdir)/prism/options.h
+box.$(OBJEXT): $(top_srcdir)/prism/pack.h
+box.$(OBJEXT): $(top_srcdir)/prism/parser.h
+box.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+box.$(OBJEXT): $(top_srcdir)/prism/prism.h
+box.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+box.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+box.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+box.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+box.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+box.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+box.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+box.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+box.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+box.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+box.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+box.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+box.$(OBJEXT): $(top_srcdir)/prism/version.h
+box.$(OBJEXT): {$(VPATH)}assert.h
+box.$(OBJEXT): {$(VPATH)}atomic.h
+box.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+box.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+box.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+box.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+box.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+box.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+box.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+box.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+box.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+box.$(OBJEXT): {$(VPATH)}box.c
+box.$(OBJEXT): {$(VPATH)}config.h
+box.$(OBJEXT): {$(VPATH)}constant.h
+box.$(OBJEXT): {$(VPATH)}darray.h
+box.$(OBJEXT): {$(VPATH)}debug_counter.h
+box.$(OBJEXT): {$(VPATH)}defines.h
+box.$(OBJEXT): {$(VPATH)}encindex.h
+box.$(OBJEXT): {$(VPATH)}encoding.h
+box.$(OBJEXT): {$(VPATH)}eval_intern.h
+box.$(OBJEXT): {$(VPATH)}id.h
+box.$(OBJEXT): {$(VPATH)}id_table.h
+box.$(OBJEXT): {$(VPATH)}intern.h
+box.$(OBJEXT): {$(VPATH)}internal.h
+box.$(OBJEXT): {$(VPATH)}internal/abi.h
+box.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+box.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+box.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+box.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+box.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+box.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+box.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+box.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+box.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+box.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+box.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+box.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+box.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+box.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+box.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+box.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+box.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+box.$(OBJEXT): {$(VPATH)}internal/assume.h
+box.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+box.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+box.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+box.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+box.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+box.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+box.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+box.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+box.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+box.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+box.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+box.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+box.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+box.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+box.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+box.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+box.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+box.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+box.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+box.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
+box.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+box.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+box.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+box.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+box.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+box.$(OBJEXT): {$(VPATH)}internal/cast.h
+box.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+box.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+box.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+box.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+box.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+box.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+box.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+box.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+box.$(OBJEXT): {$(VPATH)}internal/config.h
+box.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+box.$(OBJEXT): {$(VPATH)}internal/core.h
+box.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+box.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+box.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+box.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+box.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+box.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+box.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+box.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+box.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+box.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+box.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+box.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+box.$(OBJEXT): {$(VPATH)}internal/ctype.h
+box.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+box.$(OBJEXT): {$(VPATH)}internal/dosish.h
+box.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+box.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+box.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+box.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+box.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+box.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+box.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+box.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+box.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
+box.$(OBJEXT): {$(VPATH)}internal/error.h
+box.$(OBJEXT): {$(VPATH)}internal/eval.h
+box.$(OBJEXT): {$(VPATH)}internal/event.h
+box.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+box.$(OBJEXT): {$(VPATH)}internal/gc.h
+box.$(OBJEXT): {$(VPATH)}internal/glob.h
+box.$(OBJEXT): {$(VPATH)}internal/globals.h
+box.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+box.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+box.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+box.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+box.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+box.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+box.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+box.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/set.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+box.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+box.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+box.$(OBJEXT): {$(VPATH)}internal/iterator.h
+box.$(OBJEXT): {$(VPATH)}internal/memory.h
+box.$(OBJEXT): {$(VPATH)}internal/method.h
+box.$(OBJEXT): {$(VPATH)}internal/module.h
+box.$(OBJEXT): {$(VPATH)}internal/newobj.h
+box.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+box.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+box.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+box.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+box.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+box.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
+box.$(OBJEXT): {$(VPATH)}internal/symbol.h
+box.$(OBJEXT): {$(VPATH)}internal/value.h
+box.$(OBJEXT): {$(VPATH)}internal/value_type.h
+box.$(OBJEXT): {$(VPATH)}internal/variable.h
+box.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+box.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+box.$(OBJEXT): {$(VPATH)}io.h
+box.$(OBJEXT): {$(VPATH)}iseq.h
+box.$(OBJEXT): {$(VPATH)}method.h
+box.$(OBJEXT): {$(VPATH)}missing.h
+box.$(OBJEXT): {$(VPATH)}node.h
+box.$(OBJEXT): {$(VPATH)}onigmo.h
+box.$(OBJEXT): {$(VPATH)}oniguruma.h
+box.$(OBJEXT): {$(VPATH)}prism/ast.h
+box.$(OBJEXT): {$(VPATH)}prism/diagnostic.h
+box.$(OBJEXT): {$(VPATH)}prism/version.h
+box.$(OBJEXT): {$(VPATH)}prism_compile.h
+box.$(OBJEXT): {$(VPATH)}ruby_assert.h
+box.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+box.$(OBJEXT): {$(VPATH)}rubyparser.h
+box.$(OBJEXT): {$(VPATH)}shape.h
+box.$(OBJEXT): {$(VPATH)}st.h
+box.$(OBJEXT): {$(VPATH)}subst.h
+box.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+box.$(OBJEXT): {$(VPATH)}thread_native.h
+box.$(OBJEXT): {$(VPATH)}util.h
+box.$(OBJEXT): {$(VPATH)}vm_core.h
+box.$(OBJEXT): {$(VPATH)}vm_debug.h
+box.$(OBJEXT): {$(VPATH)}vm_opts.h
+box.$(OBJEXT): {$(VPATH)}vm_sync.h
+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/ruby.h
+builtin.$(OBJEXT): $(top_srcdir)/internal/array.h
+builtin.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+builtin.$(OBJEXT): $(top_srcdir)/internal/box.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/sanitizers.h
+builtin.$(OBJEXT): $(top_srcdir)/internal/serial.h
+builtin.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+builtin.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+builtin.$(OBJEXT): $(top_srcdir)/internal/struct.h
+builtin.$(OBJEXT): $(top_srcdir)/internal/variable.h
+builtin.$(OBJEXT): $(top_srcdir)/internal/vm.h
+builtin.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/ast.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/defines.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/node.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/options.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/pack.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/parser.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/prism.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+builtin.$(OBJEXT): $(top_srcdir)/prism/version.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.rbbin
+builtin.$(OBJEXT): {$(VPATH)}config.h
+builtin.$(OBJEXT): {$(VPATH)}constant.h
+builtin.$(OBJEXT): {$(VPATH)}defines.h
+builtin.$(OBJEXT): {$(VPATH)}encoding.h
+builtin.$(OBJEXT): {$(VPATH)}id.h
+builtin.$(OBJEXT): {$(VPATH)}id_table.h
+builtin.$(OBJEXT): {$(VPATH)}intern.h
+builtin.$(OBJEXT): {$(VPATH)}internal.h
+builtin.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/encoding/coderange.h
+builtin.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+builtin.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+builtin.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+builtin.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+builtin.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+builtin.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+builtin.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+builtin.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.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/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/set.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/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/stdckdint.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
+builtin.$(OBJEXT): {$(VPATH)}node.h
+builtin.$(OBJEXT): {$(VPATH)}onigmo.h
+builtin.$(OBJEXT): {$(VPATH)}oniguruma.h
+builtin.$(OBJEXT): {$(VPATH)}prism_compile.h
+builtin.$(OBJEXT): {$(VPATH)}ruby_assert.h
+builtin.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+builtin.$(OBJEXT): {$(VPATH)}rubyparser.h
+builtin.$(OBJEXT): {$(VPATH)}shape.h
+builtin.$(OBJEXT): {$(VPATH)}st.h
+builtin.$(OBJEXT): {$(VPATH)}subst.h
+builtin.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+builtin.$(OBJEXT): {$(VPATH)}thread_native.h
+builtin.$(OBJEXT): {$(VPATH)}vm_core.h
+builtin.$(OBJEXT): {$(VPATH)}vm_opts.h
+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/ruby.h
+class.$(OBJEXT): $(top_srcdir)/internal/array.h
+class.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+class.$(OBJEXT): $(top_srcdir)/internal/box.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/sanitizers.h
+class.$(OBJEXT): $(top_srcdir)/internal/serial.h
+class.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+class.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+class.$(OBJEXT): $(top_srcdir)/internal/string.h
+class.$(OBJEXT): $(top_srcdir)/internal/struct.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)}debug_counter.h
+class.$(OBJEXT): {$(VPATH)}defines.h
+class.$(OBJEXT): {$(VPATH)}encindex.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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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)}ractor.h
+class.$(OBJEXT): {$(VPATH)}ruby_assert.h
+class.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+class.$(OBJEXT): {$(VPATH)}rubyparser.h
+class.$(OBJEXT): {$(VPATH)}shape.h
+class.$(OBJEXT): {$(VPATH)}st.h
+class.$(OBJEXT): {$(VPATH)}subst.h
+class.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+class.$(OBJEXT): {$(VPATH)}thread_native.h
+class.$(OBJEXT): {$(VPATH)}vm_core.h
+class.$(OBJEXT): {$(VPATH)}vm_debug.h
+class.$(OBJEXT): {$(VPATH)}vm_opts.h
+class.$(OBJEXT): {$(VPATH)}vm_sync.h
+class.$(OBJEXT): {$(VPATH)}yjit.h
+class.$(OBJEXT): {$(VPATH)}zjit.h
+compar.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+compar.$(OBJEXT): $(hdrdir)/ruby/version.h
+compar.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+compar.$(OBJEXT): $(top_srcdir)/internal/compar.h
+compar.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+compar.$(OBJEXT): $(top_srcdir)/internal/error.h
+compar.$(OBJEXT): $(top_srcdir)/internal/serial.h
+compar.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+compar.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+compar.$(OBJEXT): $(top_srcdir)/internal/string.h
+compar.$(OBJEXT): $(top_srcdir)/internal/vm.h
+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)}encindex.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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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/ruby.h
+compile.$(OBJEXT): $(hdrdir)/ruby/version.h
+compile.$(OBJEXT): $(top_srcdir)/internal/array.h
+compile.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+compile.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+compile.$(OBJEXT): $(top_srcdir)/internal/bits.h
+compile.$(OBJEXT): $(top_srcdir)/internal/box.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/io.h
+compile.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+compile.$(OBJEXT): $(top_srcdir)/internal/object.h
+compile.$(OBJEXT): $(top_srcdir)/internal/parse.h
+compile.$(OBJEXT): $(top_srcdir)/internal/rational.h
+compile.$(OBJEXT): $(top_srcdir)/internal/re.h
+compile.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
+compile.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+compile.$(OBJEXT): $(top_srcdir)/internal/serial.h
+compile.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+compile.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+compile.$(OBJEXT): $(top_srcdir)/internal/string.h
+compile.$(OBJEXT): $(top_srcdir)/internal/struct.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): $(top_srcdir)/prism/ast.h
+compile.$(OBJEXT): $(top_srcdir)/prism/defines.h
+compile.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+compile.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+compile.$(OBJEXT): $(top_srcdir)/prism/node.h
+compile.$(OBJEXT): $(top_srcdir)/prism/options.h
+compile.$(OBJEXT): $(top_srcdir)/prism/pack.h
+compile.$(OBJEXT): $(top_srcdir)/prism/parser.h
+compile.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+compile.$(OBJEXT): $(top_srcdir)/prism/prism.h
+compile.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+compile.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+compile.$(OBJEXT): $(top_srcdir)/prism/version.h
+compile.$(OBJEXT): $(top_srcdir)/prism_compile.c
+compile.$(OBJEXT): {$(VPATH)}assert.h
+compile.$(OBJEXT): {$(VPATH)}atomic.h
+compile.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+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)}debug_counter.h
+compile.$(OBJEXT): {$(VPATH)}defines.h
+compile.$(OBJEXT): {$(VPATH)}encindex.h
+compile.$(OBJEXT): {$(VPATH)}encoding.h
+compile.$(OBJEXT): {$(VPATH)}id.h
+compile.$(OBJEXT): {$(VPATH)}id_table.h
+compile.$(OBJEXT): {$(VPATH)}insns.def
+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/abi.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/packed_struct.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/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/set.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/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/stdckdint.h
+compile.$(OBJEXT): {$(VPATH)}internal/symbol.h
+compile.$(OBJEXT): {$(VPATH)}internal/value.h
+compile.$(OBJEXT): {$(VPATH)}internal/value_type.h
+compile.$(OBJEXT): {$(VPATH)}internal/variable.h
+compile.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+compile.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+compile.$(OBJEXT): {$(VPATH)}io.h
+compile.$(OBJEXT): {$(VPATH)}iseq.h
+compile.$(OBJEXT): {$(VPATH)}method.h
+compile.$(OBJEXT): {$(VPATH)}missing.h
+compile.$(OBJEXT): {$(VPATH)}node.h
+compile.$(OBJEXT): {$(VPATH)}onigmo.h
+compile.$(OBJEXT): {$(VPATH)}oniguruma.h
+compile.$(OBJEXT): {$(VPATH)}optinsn.inc
+compile.$(OBJEXT): {$(VPATH)}prism_compile.c
+compile.$(OBJEXT): {$(VPATH)}prism_compile.h
+compile.$(OBJEXT): {$(VPATH)}ractor.h
+compile.$(OBJEXT): {$(VPATH)}re.h
+compile.$(OBJEXT): {$(VPATH)}regex.h
+compile.$(OBJEXT): {$(VPATH)}ruby_assert.h
+compile.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+compile.$(OBJEXT): {$(VPATH)}rubyparser.h
+compile.$(OBJEXT): {$(VPATH)}shape.h
+compile.$(OBJEXT): {$(VPATH)}st.h
+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
+compile.$(OBJEXT): {$(VPATH)}vm_sync.h
+compile.$(OBJEXT): {$(VPATH)}yjit.h
+complex.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+complex.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+complex.$(OBJEXT): $(CCAN_DIR)/list/list.h
+complex.$(OBJEXT): $(CCAN_DIR)/str/str.h
+complex.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+complex.$(OBJEXT): $(top_srcdir)/internal/array.h
+complex.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+complex.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+complex.$(OBJEXT): $(top_srcdir)/internal/bits.h
+complex.$(OBJEXT): $(top_srcdir)/internal/box.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/imemo.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/sanitizers.h
+complex.$(OBJEXT): $(top_srcdir)/internal/serial.h
+complex.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+complex.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+complex.$(OBJEXT): $(top_srcdir)/internal/string.h
+complex.$(OBJEXT): $(top_srcdir)/internal/struct.h
+complex.$(OBJEXT): $(top_srcdir)/internal/variable.h
+complex.$(OBJEXT): $(top_srcdir)/internal/vm.h
+complex.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+complex.$(OBJEXT): {$(VPATH)}assert.h
+complex.$(OBJEXT): {$(VPATH)}atomic.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)}constant.h
+complex.$(OBJEXT): {$(VPATH)}debug_counter.h
+complex.$(OBJEXT): {$(VPATH)}defines.h
+complex.$(OBJEXT): {$(VPATH)}encindex.h
+complex.$(OBJEXT): {$(VPATH)}encoding.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/abi.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/packed_struct.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/encoding/coderange.h
+complex.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+complex.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+complex.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+complex.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+complex.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+complex.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+complex.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+complex.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.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/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/set.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/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/stdckdint.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)}method.h
+complex.$(OBJEXT): {$(VPATH)}missing.h
+complex.$(OBJEXT): {$(VPATH)}node.h
+complex.$(OBJEXT): {$(VPATH)}onigmo.h
+complex.$(OBJEXT): {$(VPATH)}oniguruma.h
+complex.$(OBJEXT): {$(VPATH)}ruby_assert.h
+complex.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+complex.$(OBJEXT): {$(VPATH)}rubyparser.h
+complex.$(OBJEXT): {$(VPATH)}shape.h
+complex.$(OBJEXT): {$(VPATH)}st.h
+complex.$(OBJEXT): {$(VPATH)}subst.h
+complex.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+complex.$(OBJEXT): {$(VPATH)}thread_native.h
+complex.$(OBJEXT): {$(VPATH)}vm_core.h
+complex.$(OBJEXT): {$(VPATH)}vm_debug.h
+complex.$(OBJEXT): {$(VPATH)}vm_opts.h
+complex.$(OBJEXT): {$(VPATH)}vm_sync.h
+concurrent_set.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+concurrent_set.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+concurrent_set.$(OBJEXT): $(CCAN_DIR)/list/list.h
+concurrent_set.$(OBJEXT): $(CCAN_DIR)/str/str.h
+concurrent_set.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+concurrent_set.$(OBJEXT): $(top_srcdir)/internal/array.h
+concurrent_set.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+concurrent_set.$(OBJEXT): $(top_srcdir)/internal/box.h
+concurrent_set.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+concurrent_set.$(OBJEXT): $(top_srcdir)/internal/concurrent_set.h
+concurrent_set.$(OBJEXT): $(top_srcdir)/internal/gc.h
+concurrent_set.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+concurrent_set.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+concurrent_set.$(OBJEXT): $(top_srcdir)/internal/serial.h
+concurrent_set.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+concurrent_set.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+concurrent_set.$(OBJEXT): $(top_srcdir)/internal/vm.h
+concurrent_set.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+concurrent_set.$(OBJEXT): {$(VPATH)}assert.h
+concurrent_set.$(OBJEXT): {$(VPATH)}atomic.h
+concurrent_set.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+concurrent_set.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+concurrent_set.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+concurrent_set.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+concurrent_set.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+concurrent_set.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+concurrent_set.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+concurrent_set.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+concurrent_set.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+concurrent_set.$(OBJEXT): {$(VPATH)}concurrent_set.c
+concurrent_set.$(OBJEXT): {$(VPATH)}config.h
+concurrent_set.$(OBJEXT): {$(VPATH)}debug_counter.h
+concurrent_set.$(OBJEXT): {$(VPATH)}defines.h
+concurrent_set.$(OBJEXT): {$(VPATH)}encindex.h
+concurrent_set.$(OBJEXT): {$(VPATH)}encoding.h
+concurrent_set.$(OBJEXT): {$(VPATH)}id.h
+concurrent_set.$(OBJEXT): {$(VPATH)}id_table.h
+concurrent_set.$(OBJEXT): {$(VPATH)}intern.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/abi.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/assume.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/cast.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/config.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/core.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/ctype.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/dosish.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/error.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/eval.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/event.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/gc.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/glob.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/globals.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/set.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/iterator.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/memory.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/method.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/module.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/newobj.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/symbol.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/value.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/value_type.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/variable.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+concurrent_set.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+concurrent_set.$(OBJEXT): {$(VPATH)}method.h
+concurrent_set.$(OBJEXT): {$(VPATH)}missing.h
+concurrent_set.$(OBJEXT): {$(VPATH)}node.h
+concurrent_set.$(OBJEXT): {$(VPATH)}onigmo.h
+concurrent_set.$(OBJEXT): {$(VPATH)}oniguruma.h
+concurrent_set.$(OBJEXT): {$(VPATH)}ruby_assert.h
+concurrent_set.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+concurrent_set.$(OBJEXT): {$(VPATH)}rubyparser.h
+concurrent_set.$(OBJEXT): {$(VPATH)}st.h
+concurrent_set.$(OBJEXT): {$(VPATH)}subst.h
+concurrent_set.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+concurrent_set.$(OBJEXT): {$(VPATH)}thread_native.h
+concurrent_set.$(OBJEXT): {$(VPATH)}vm_core.h
+concurrent_set.$(OBJEXT): {$(VPATH)}vm_debug.h
+concurrent_set.$(OBJEXT): {$(VPATH)}vm_opts.h
+concurrent_set.$(OBJEXT): {$(VPATH)}vm_sync.h
+cont.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+cont.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+cont.$(OBJEXT): $(CCAN_DIR)/list/list.h
+cont.$(OBJEXT): $(CCAN_DIR)/str/str.h
+cont.$(OBJEXT): $(hdrdir)/ruby.h
+cont.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+cont.$(OBJEXT): $(hdrdir)/ruby/version.h
+cont.$(OBJEXT): $(top_srcdir)/internal/array.h
+cont.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+cont.$(OBJEXT): $(top_srcdir)/internal/box.h
+cont.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+cont.$(OBJEXT): $(top_srcdir)/internal/cont.h
+cont.$(OBJEXT): $(top_srcdir)/internal/error.h
+cont.$(OBJEXT): $(top_srcdir)/internal/eval.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/sanitizers.h
+cont.$(OBJEXT): $(top_srcdir)/internal/serial.h
+cont.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+cont.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+cont.$(OBJEXT): $(top_srcdir)/internal/string.h
+cont.$(OBJEXT): $(top_srcdir)/internal/struct.h
+cont.$(OBJEXT): $(top_srcdir)/internal/thread.h
+cont.$(OBJEXT): $(top_srcdir)/internal/variable.h
+cont.$(OBJEXT): $(top_srcdir)/internal/vm.h
+cont.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+cont.$(OBJEXT): $(top_srcdir)/prism/ast.h
+cont.$(OBJEXT): $(top_srcdir)/prism/defines.h
+cont.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+cont.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+cont.$(OBJEXT): $(top_srcdir)/prism/node.h
+cont.$(OBJEXT): $(top_srcdir)/prism/options.h
+cont.$(OBJEXT): $(top_srcdir)/prism/pack.h
+cont.$(OBJEXT): $(top_srcdir)/prism/parser.h
+cont.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+cont.$(OBJEXT): $(top_srcdir)/prism/prism.h
+cont.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+cont.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+cont.$(OBJEXT): $(top_srcdir)/prism/version.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)}constant.h
+cont.$(OBJEXT): {$(VPATH)}cont.c
+cont.$(OBJEXT): {$(VPATH)}debug_counter.h
+cont.$(OBJEXT): {$(VPATH)}defines.h
+cont.$(OBJEXT): {$(VPATH)}encindex.h
+cont.$(OBJEXT): {$(VPATH)}encoding.h
+cont.$(OBJEXT): {$(VPATH)}eval_intern.h
+cont.$(OBJEXT): {$(VPATH)}fiber/scheduler.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/abi.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/packed_struct.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/encoding/coderange.h
+cont.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+cont.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+cont.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+cont.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+cont.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+cont.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+cont.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+cont.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.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/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/set.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/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/stdckdint.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)}iseq.h
+cont.$(OBJEXT): {$(VPATH)}method.h
+cont.$(OBJEXT): {$(VPATH)}missing.h
+cont.$(OBJEXT): {$(VPATH)}node.h
+cont.$(OBJEXT): {$(VPATH)}onigmo.h
+cont.$(OBJEXT): {$(VPATH)}oniguruma.h
+cont.$(OBJEXT): {$(VPATH)}prism_compile.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)}rubyparser.h
+cont.$(OBJEXT): {$(VPATH)}shape.h
+cont.$(OBJEXT): {$(VPATH)}st.h
+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)}vm_sync.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/ruby.h
+debug.$(OBJEXT): $(top_srcdir)/internal/array.h
+debug.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+debug.$(OBJEXT): $(top_srcdir)/internal/box.h
+debug.$(OBJEXT): $(top_srcdir)/internal/class.h
+debug.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+debug.$(OBJEXT): $(top_srcdir)/internal/gc.h
+debug.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+debug.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+debug.$(OBJEXT): $(top_srcdir)/internal/serial.h
+debug.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+debug.$(OBJEXT): $(top_srcdir)/internal/signal.h
+debug.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+debug.$(OBJEXT): $(top_srcdir)/internal/struct.h
+debug.$(OBJEXT): $(top_srcdir)/internal/variable.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)}constant.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)}id.h
+debug.$(OBJEXT): {$(VPATH)}id_table.h
+debug.$(OBJEXT): {$(VPATH)}intern.h
+debug.$(OBJEXT): {$(VPATH)}internal.h
+debug.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/set.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/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/stdckdint.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)}rubyparser.h
+debug.$(OBJEXT): {$(VPATH)}shape.h
+debug.$(OBJEXT): {$(VPATH)}st.h
+debug.$(OBJEXT): {$(VPATH)}subst.h
+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.$(OBJEXT): {$(VPATH)}vm_sync.h
+debug_counter.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+debug_counter.$(OBJEXT): {$(VPATH)}assert.h
+debug_counter.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+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/abi.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/packed_struct.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/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/set.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+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/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/stdckdint.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
+debug_counter.$(OBJEXT): {$(VPATH)}thread_native.h
+dir.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+dir.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+dir.$(OBJEXT): $(CCAN_DIR)/list/list.h
+dir.$(OBJEXT): $(CCAN_DIR)/str/str.h
+dir.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+dir.$(OBJEXT): $(hdrdir)/ruby/version.h
+dir.$(OBJEXT): $(top_srcdir)/internal/array.h
+dir.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+dir.$(OBJEXT): $(top_srcdir)/internal/box.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/imemo.h
+dir.$(OBJEXT): $(top_srcdir)/internal/io.h
+dir.$(OBJEXT): $(top_srcdir)/internal/object.h
+dir.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+dir.$(OBJEXT): $(top_srcdir)/internal/serial.h
+dir.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+dir.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+dir.$(OBJEXT): $(top_srcdir)/internal/string.h
+dir.$(OBJEXT): $(top_srcdir)/internal/variable.h
+dir.$(OBJEXT): $(top_srcdir)/internal/vm.h
+dir.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+dir.$(OBJEXT): {$(VPATH)}assert.h
+dir.$(OBJEXT): {$(VPATH)}atomic.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)}constant.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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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)}method.h
+dir.$(OBJEXT): {$(VPATH)}missing.h
+dir.$(OBJEXT): {$(VPATH)}node.h
+dir.$(OBJEXT): {$(VPATH)}onigmo.h
+dir.$(OBJEXT): {$(VPATH)}oniguruma.h
+dir.$(OBJEXT): {$(VPATH)}ruby_assert.h
+dir.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+dir.$(OBJEXT): {$(VPATH)}rubyparser.h
+dir.$(OBJEXT): {$(VPATH)}shape.h
+dir.$(OBJEXT): {$(VPATH)}st.h
+dir.$(OBJEXT): {$(VPATH)}subst.h
+dir.$(OBJEXT): {$(VPATH)}thread.h
+dir.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+dir.$(OBJEXT): {$(VPATH)}thread_native.h
+dir.$(OBJEXT): {$(VPATH)}util.h
+dir.$(OBJEXT): {$(VPATH)}vm_core.h
+dir.$(OBJEXT): {$(VPATH)}vm_opts.h
+dln.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+dln.$(OBJEXT): $(top_srcdir)/internal/box.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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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/abi.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/packed_struct.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/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/set.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+dln_find.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+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/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/stdckdint.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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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/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/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/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/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
+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/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/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/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/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/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/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
+enc/utf_8.$(OBJEXT): {$(VPATH)}st.h
+enc/utf_8.$(OBJEXT): {$(VPATH)}subst.h
+encoding.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+encoding.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+encoding.$(OBJEXT): $(CCAN_DIR)/list/list.h
+encoding.$(OBJEXT): $(CCAN_DIR)/str/str.h
+encoding.$(OBJEXT): $(hdrdir)/ruby.h
+encoding.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+encoding.$(OBJEXT): $(hdrdir)/ruby/version.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/array.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/class.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/enc.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/encoding.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/error.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/gc.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/inits.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/load.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/object.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/serial.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/string.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/variable.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/vm.h
+encoding.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+encoding.$(OBJEXT): {$(VPATH)}assert.h
+encoding.$(OBJEXT): {$(VPATH)}atomic.h
+encoding.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+encoding.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+encoding.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+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)}constant.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.h
+encoding.$(OBJEXT): {$(VPATH)}id_table.h
+encoding.$(OBJEXT): {$(VPATH)}intern.h
+encoding.$(OBJEXT): {$(VPATH)}internal.h
+encoding.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/set.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/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/stdckdint.h
+encoding.$(OBJEXT): {$(VPATH)}internal/symbol.h
+encoding.$(OBJEXT): {$(VPATH)}internal/value.h
+encoding.$(OBJEXT): {$(VPATH)}internal/value_type.h
+encoding.$(OBJEXT): {$(VPATH)}internal/variable.h
+encoding.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+encoding.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+encoding.$(OBJEXT): {$(VPATH)}method.h
+encoding.$(OBJEXT): {$(VPATH)}missing.h
+encoding.$(OBJEXT): {$(VPATH)}node.h
+encoding.$(OBJEXT): {$(VPATH)}onigmo.h
+encoding.$(OBJEXT): {$(VPATH)}oniguruma.h
+encoding.$(OBJEXT): {$(VPATH)}ractor.h
+encoding.$(OBJEXT): {$(VPATH)}regenc.h
+encoding.$(OBJEXT): {$(VPATH)}ruby_assert.h
+encoding.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+encoding.$(OBJEXT): {$(VPATH)}rubyparser.h
+encoding.$(OBJEXT): {$(VPATH)}shape.h
+encoding.$(OBJEXT): {$(VPATH)}st.h
+encoding.$(OBJEXT): {$(VPATH)}subst.h
+encoding.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+encoding.$(OBJEXT): {$(VPATH)}thread_native.h
+encoding.$(OBJEXT): {$(VPATH)}util.h
+encoding.$(OBJEXT): {$(VPATH)}vm_core.h
+encoding.$(OBJEXT): {$(VPATH)}vm_debug.h
+encoding.$(OBJEXT): {$(VPATH)}vm_opts.h
+encoding.$(OBJEXT): {$(VPATH)}vm_sync.h
+enum.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+enum.$(OBJEXT): $(top_srcdir)/internal/array.h
+enum.$(OBJEXT): $(top_srcdir)/internal/basic_operators.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/set_table.h
+enum.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+enum.$(OBJEXT): $(top_srcdir)/internal/variable.h
+enum.$(OBJEXT): $(top_srcdir)/internal/vm.h
+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)}constant.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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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)}shape.h
+enum.$(OBJEXT): {$(VPATH)}st.h
+enum.$(OBJEXT): {$(VPATH)}subst.h
+enum.$(OBJEXT): {$(VPATH)}symbol.h
+enum.$(OBJEXT): {$(VPATH)}util.h
+enumerator.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+enumerator.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+enumerator.$(OBJEXT): $(CCAN_DIR)/list/list.h
+enumerator.$(OBJEXT): $(CCAN_DIR)/str/str.h
+enumerator.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+enumerator.$(OBJEXT): $(hdrdir)/ruby/version.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/array.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/bits.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/box.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/class.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/sanitizers.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/serial.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/string.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/struct.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/variable.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/vm.h
+enumerator.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+enumerator.$(OBJEXT): {$(VPATH)}assert.h
+enumerator.$(OBJEXT): {$(VPATH)}atomic.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)}constant.h
+enumerator.$(OBJEXT): {$(VPATH)}debug_counter.h
+enumerator.$(OBJEXT): {$(VPATH)}defines.h
+enumerator.$(OBJEXT): {$(VPATH)}encindex.h
+enumerator.$(OBJEXT): {$(VPATH)}encoding.h
+enumerator.$(OBJEXT): {$(VPATH)}enumerator.c
+enumerator.$(OBJEXT): {$(VPATH)}id.h
+enumerator.$(OBJEXT): {$(VPATH)}id_table.h
+enumerator.$(OBJEXT): {$(VPATH)}intern.h
+enumerator.$(OBJEXT): {$(VPATH)}internal.h
+enumerator.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/set.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/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/stdckdint.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)}method.h
+enumerator.$(OBJEXT): {$(VPATH)}missing.h
+enumerator.$(OBJEXT): {$(VPATH)}node.h
+enumerator.$(OBJEXT): {$(VPATH)}onigmo.h
+enumerator.$(OBJEXT): {$(VPATH)}oniguruma.h
+enumerator.$(OBJEXT): {$(VPATH)}ruby_assert.h
+enumerator.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+enumerator.$(OBJEXT): {$(VPATH)}rubyparser.h
+enumerator.$(OBJEXT): {$(VPATH)}shape.h
+enumerator.$(OBJEXT): {$(VPATH)}st.h
+enumerator.$(OBJEXT): {$(VPATH)}subst.h
+enumerator.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+enumerator.$(OBJEXT): {$(VPATH)}thread_native.h
+enumerator.$(OBJEXT): {$(VPATH)}vm_core.h
+enumerator.$(OBJEXT): {$(VPATH)}vm_debug.h
+enumerator.$(OBJEXT): {$(VPATH)}vm_opts.h
+enumerator.$(OBJEXT): {$(VPATH)}vm_sync.h
+error.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+error.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+error.$(OBJEXT): $(CCAN_DIR)/list/list.h
+error.$(OBJEXT): $(CCAN_DIR)/str/str.h
+error.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+error.$(OBJEXT): $(hdrdir)/ruby/version.h
+error.$(OBJEXT): $(top_srcdir)/internal/array.h
+error.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+error.$(OBJEXT): $(top_srcdir)/internal/box.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/process.h
+error.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+error.$(OBJEXT): $(top_srcdir)/internal/serial.h
+error.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+error.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+error.$(OBJEXT): $(top_srcdir)/internal/string.h
+error.$(OBJEXT): $(top_srcdir)/internal/struct.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)}debug_counter.h
+error.$(OBJEXT): {$(VPATH)}defines.h
+error.$(OBJEXT): {$(VPATH)}encindex.h
+error.$(OBJEXT): {$(VPATH)}encoding.h
+error.$(OBJEXT): {$(VPATH)}error.c
+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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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
+error.$(OBJEXT): {$(VPATH)}node.h
+error.$(OBJEXT): {$(VPATH)}onigmo.h
+error.$(OBJEXT): {$(VPATH)}oniguruma.h
+error.$(OBJEXT): {$(VPATH)}ruby_assert.h
+error.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+error.$(OBJEXT): {$(VPATH)}rubyparser.h
+error.$(OBJEXT): {$(VPATH)}shape.h
+error.$(OBJEXT): {$(VPATH)}st.h
+error.$(OBJEXT): {$(VPATH)}subst.h
+error.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+error.$(OBJEXT): {$(VPATH)}thread_native.h
+error.$(OBJEXT): {$(VPATH)}util.h
+error.$(OBJEXT): {$(VPATH)}vm_core.h
+error.$(OBJEXT): {$(VPATH)}vm_debug.h
+error.$(OBJEXT): {$(VPATH)}vm_opts.h
+error.$(OBJEXT): {$(VPATH)}vm_sync.h
+error.$(OBJEXT): {$(VPATH)}warning.rbinc
+error.$(OBJEXT): {$(VPATH)}yjit.h
+eval.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+eval.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+eval.$(OBJEXT): $(CCAN_DIR)/list/list.h
+eval.$(OBJEXT): $(CCAN_DIR)/str/str.h
+eval.$(OBJEXT): $(hdrdir)/ruby.h
+eval.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+eval.$(OBJEXT): $(hdrdir)/ruby/version.h
+eval.$(OBJEXT): $(top_srcdir)/internal/array.h
+eval.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+eval.$(OBJEXT): $(top_srcdir)/internal/box.h
+eval.$(OBJEXT): $(top_srcdir)/internal/class.h
+eval.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+eval.$(OBJEXT): $(top_srcdir)/internal/cont.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/sanitizers.h
+eval.$(OBJEXT): $(top_srcdir)/internal/serial.h
+eval.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+eval.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+eval.$(OBJEXT): $(top_srcdir)/internal/string.h
+eval.$(OBJEXT): $(top_srcdir)/internal/struct.h
+eval.$(OBJEXT): $(top_srcdir)/internal/thread.h
+eval.$(OBJEXT): $(top_srcdir)/internal/variable.h
+eval.$(OBJEXT): $(top_srcdir)/internal/vm.h
+eval.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+eval.$(OBJEXT): $(top_srcdir)/prism/ast.h
+eval.$(OBJEXT): $(top_srcdir)/prism/defines.h
+eval.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+eval.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+eval.$(OBJEXT): $(top_srcdir)/prism/node.h
+eval.$(OBJEXT): $(top_srcdir)/prism/options.h
+eval.$(OBJEXT): $(top_srcdir)/prism/pack.h
+eval.$(OBJEXT): $(top_srcdir)/prism/parser.h
+eval.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+eval.$(OBJEXT): $(top_srcdir)/prism/prism.h
+eval.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+eval.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+eval.$(OBJEXT): $(top_srcdir)/prism/version.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)}debug_counter.h
+eval.$(OBJEXT): {$(VPATH)}defines.h
+eval.$(OBJEXT): {$(VPATH)}encindex.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)}id.h
+eval.$(OBJEXT): {$(VPATH)}id_table.h
+eval.$(OBJEXT): {$(VPATH)}intern.h
+eval.$(OBJEXT): {$(VPATH)}internal.h
+eval.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/set.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/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/stdckdint.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)}node.h
+eval.$(OBJEXT): {$(VPATH)}onigmo.h
+eval.$(OBJEXT): {$(VPATH)}oniguruma.h
+eval.$(OBJEXT): {$(VPATH)}prism_compile.h
+eval.$(OBJEXT): {$(VPATH)}probes.dmyh
+eval.$(OBJEXT): {$(VPATH)}probes.h
+eval.$(OBJEXT): {$(VPATH)}probes_helper.h
+eval.$(OBJEXT): {$(VPATH)}ractor.h
+eval.$(OBJEXT): {$(VPATH)}ractor_core.h
+eval.$(OBJEXT): {$(VPATH)}ruby_assert.h
+eval.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+eval.$(OBJEXT): {$(VPATH)}rubyparser.h
+eval.$(OBJEXT): {$(VPATH)}shape.h
+eval.$(OBJEXT): {$(VPATH)}st.h
+eval.$(OBJEXT): {$(VPATH)}subst.h
+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)}vm_sync.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): $(CCAN_DIR)/check_type/check_type.h
+file.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+file.$(OBJEXT): $(CCAN_DIR)/list/list.h
+file.$(OBJEXT): $(CCAN_DIR)/str/str.h
+file.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+file.$(OBJEXT): $(hdrdir)/ruby/version.h
+file.$(OBJEXT): $(top_srcdir)/internal/array.h
+file.$(OBJEXT): $(top_srcdir)/internal/class.h
+file.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+file.$(OBJEXT): $(top_srcdir)/internal/dir.h
+file.$(OBJEXT): $(top_srcdir)/internal/encoding.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/variable.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)}constant.h
+file.$(OBJEXT): {$(VPATH)}defines.h
+file.$(OBJEXT): {$(VPATH)}dln.h
+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/abi.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/nonstring.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+file.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.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/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/set.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/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/stdckdint.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
+file.$(OBJEXT): {$(VPATH)}oniguruma.h
+file.$(OBJEXT): {$(VPATH)}shape.h
+file.$(OBJEXT): {$(VPATH)}st.h
+file.$(OBJEXT): {$(VPATH)}subst.h
+file.$(OBJEXT): {$(VPATH)}thread.h
+file.$(OBJEXT): {$(VPATH)}thread_native.h
+file.$(OBJEXT): {$(VPATH)}util.h
+gc.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+gc.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+gc.$(OBJEXT): $(CCAN_DIR)/list/list.h
+gc.$(OBJEXT): $(CCAN_DIR)/str/str.h
+gc.$(OBJEXT): $(hdrdir)/ruby.h
+gc.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+gc.$(OBJEXT): $(hdrdir)/ruby/version.h
+gc.$(OBJEXT): $(top_srcdir)/gc/default/default.c
+gc.$(OBJEXT): $(top_srcdir)/gc/gc.h
+gc.$(OBJEXT): $(top_srcdir)/gc/gc_impl.h
+gc.$(OBJEXT): $(top_srcdir)/internal/array.h
+gc.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+gc.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+gc.$(OBJEXT): $(top_srcdir)/internal/bits.h
+gc.$(OBJEXT): $(top_srcdir)/internal/box.h
+gc.$(OBJEXT): $(top_srcdir)/internal/class.h
+gc.$(OBJEXT): $(top_srcdir)/internal/compile.h
+gc.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+gc.$(OBJEXT): $(top_srcdir)/internal/complex.h
+gc.$(OBJEXT): $(top_srcdir)/internal/concurrent_set.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/set_table.h
+gc.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+gc.$(OBJEXT): $(top_srcdir)/internal/string.h
+gc.$(OBJEXT): $(top_srcdir)/internal/struct.h
+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): $(top_srcdir)/prism/ast.h
+gc.$(OBJEXT): $(top_srcdir)/prism/defines.h
+gc.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+gc.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+gc.$(OBJEXT): $(top_srcdir)/prism/node.h
+gc.$(OBJEXT): $(top_srcdir)/prism/options.h
+gc.$(OBJEXT): $(top_srcdir)/prism/pack.h
+gc.$(OBJEXT): $(top_srcdir)/prism/parser.h
+gc.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+gc.$(OBJEXT): $(top_srcdir)/prism/prism.h
+gc.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+gc.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+gc.$(OBJEXT): $(top_srcdir)/prism/version.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
+gc.$(OBJEXT): {$(VPATH)}encindex.h
+gc.$(OBJEXT): {$(VPATH)}encoding.h
+gc.$(OBJEXT): {$(VPATH)}eval_intern.h
+gc.$(OBJEXT): {$(VPATH)}gc.c
+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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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)}iseq.h
+gc.$(OBJEXT): {$(VPATH)}method.h
+gc.$(OBJEXT): {$(VPATH)}missing.h
+gc.$(OBJEXT): {$(VPATH)}node.h
+gc.$(OBJEXT): {$(VPATH)}onigmo.h
+gc.$(OBJEXT): {$(VPATH)}oniguruma.h
+gc.$(OBJEXT): {$(VPATH)}prism_compile.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
+gc.$(OBJEXT): {$(VPATH)}regint.h
+gc.$(OBJEXT): {$(VPATH)}ruby_assert.h
+gc.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+gc.$(OBJEXT): {$(VPATH)}rubyparser.h
+gc.$(OBJEXT): {$(VPATH)}shape.h
+gc.$(OBJEXT): {$(VPATH)}st.h
+gc.$(OBJEXT): {$(VPATH)}subst.h
+gc.$(OBJEXT): {$(VPATH)}symbol.h
+gc.$(OBJEXT): {$(VPATH)}thread.h
+gc.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+gc.$(OBJEXT): {$(VPATH)}thread_native.h
+gc.$(OBJEXT): {$(VPATH)}util.h
+gc.$(OBJEXT): {$(VPATH)}variable.h
+gc.$(OBJEXT): {$(VPATH)}vm.h
+gc.$(OBJEXT): {$(VPATH)}vm_callinfo.h
+gc.$(OBJEXT): {$(VPATH)}vm_core.h
+gc.$(OBJEXT): {$(VPATH)}vm_debug.h
+gc.$(OBJEXT): {$(VPATH)}vm_opts.h
+gc.$(OBJEXT): {$(VPATH)}vm_sync.h
+gc.$(OBJEXT): {$(VPATH)}yjit.h
+gc.$(OBJEXT): {$(VPATH)}zjit.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/basic_operators.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/bits.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/box.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/complex.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/gc.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/parse.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/rational.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/serial.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/variable.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/vm.h
+goruby.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/ast.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/defines.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/node.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/options.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/pack.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/parser.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/prism.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+goruby.$(OBJEXT): $(top_srcdir)/prism/version.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)}constant.h
+goruby.$(OBJEXT): {$(VPATH)}defines.h
+goruby.$(OBJEXT): {$(VPATH)}encoding.h
+goruby.$(OBJEXT): {$(VPATH)}golf_prelude.rbbin
+goruby.$(OBJEXT): {$(VPATH)}goruby.c
+goruby.$(OBJEXT): {$(VPATH)}id.h
+goruby.$(OBJEXT): {$(VPATH)}id_table.h
+goruby.$(OBJEXT): {$(VPATH)}intern.h
+goruby.$(OBJEXT): {$(VPATH)}internal.h
+goruby.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/encoding/coderange.h
+goruby.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+goruby.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+goruby.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+goruby.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+goruby.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+goruby.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+goruby.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+goruby.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.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/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/set.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/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/stdckdint.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)}onigmo.h
+goruby.$(OBJEXT): {$(VPATH)}oniguruma.h
+goruby.$(OBJEXT): {$(VPATH)}prism_compile.h
+goruby.$(OBJEXT): {$(VPATH)}ruby_assert.h
+goruby.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+goruby.$(OBJEXT): {$(VPATH)}rubyparser.h
+goruby.$(OBJEXT): {$(VPATH)}shape.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
+goruby.$(OBJEXT): {$(VPATH)}vm_opts.h
+hash.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+hash.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+hash.$(OBJEXT): $(CCAN_DIR)/list/list.h
+hash.$(OBJEXT): $(CCAN_DIR)/str/str.h
+hash.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+hash.$(OBJEXT): $(hdrdir)/ruby/version.h
+hash.$(OBJEXT): $(top_srcdir)/internal/array.h
+hash.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+hash.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+hash.$(OBJEXT): $(top_srcdir)/internal/bits.h
+hash.$(OBJEXT): $(top_srcdir)/internal/box.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/imemo.h
+hash.$(OBJEXT): $(top_srcdir)/internal/object.h
+hash.$(OBJEXT): $(top_srcdir)/internal/proc.h
+hash.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+hash.$(OBJEXT): $(top_srcdir)/internal/serial.h
+hash.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+hash.$(OBJEXT): $(top_srcdir)/internal/st.h
+hash.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+hash.$(OBJEXT): $(top_srcdir)/internal/string.h
+hash.$(OBJEXT): $(top_srcdir)/internal/struct.h
+hash.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+hash.$(OBJEXT): $(top_srcdir)/internal/thread.h
+hash.$(OBJEXT): $(top_srcdir)/internal/time.h
+hash.$(OBJEXT): $(top_srcdir)/internal/variable.h
+hash.$(OBJEXT): $(top_srcdir)/internal/vm.h
+hash.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+hash.$(OBJEXT): $(top_srcdir)/prism/ast.h
+hash.$(OBJEXT): $(top_srcdir)/prism/defines.h
+hash.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+hash.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+hash.$(OBJEXT): $(top_srcdir)/prism/node.h
+hash.$(OBJEXT): $(top_srcdir)/prism/options.h
+hash.$(OBJEXT): $(top_srcdir)/prism/pack.h
+hash.$(OBJEXT): $(top_srcdir)/prism/parser.h
+hash.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+hash.$(OBJEXT): $(top_srcdir)/prism/prism.h
+hash.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+hash.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+hash.$(OBJEXT): $(top_srcdir)/prism/version.h
+hash.$(OBJEXT): {$(VPATH)}assert.h
+hash.$(OBJEXT): {$(VPATH)}atomic.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)}builtin.h
+hash.$(OBJEXT): {$(VPATH)}config.h
+hash.$(OBJEXT): {$(VPATH)}constant.h
+hash.$(OBJEXT): {$(VPATH)}debug_counter.h
+hash.$(OBJEXT): {$(VPATH)}defines.h
+hash.$(OBJEXT): {$(VPATH)}encindex.h
+hash.$(OBJEXT): {$(VPATH)}encoding.h
+hash.$(OBJEXT): {$(VPATH)}hash.c
+hash.$(OBJEXT): {$(VPATH)}hash.rbinc
+hash.$(OBJEXT): {$(VPATH)}id.h
+hash.$(OBJEXT): {$(VPATH)}id_table.h
+hash.$(OBJEXT): {$(VPATH)}intern.h
+hash.$(OBJEXT): {$(VPATH)}internal.h
+hash.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/set.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/scan_args.h
+hash.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+hash.$(OBJEXT): {$(VPATH)}internal/st.h
+hash.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+hash.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+hash.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+hash.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
+hash.$(OBJEXT): {$(VPATH)}internal/symbol.h
+hash.$(OBJEXT): {$(VPATH)}internal/value.h
+hash.$(OBJEXT): {$(VPATH)}internal/value_type.h
+hash.$(OBJEXT): {$(VPATH)}internal/variable.h
+hash.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+hash.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+hash.$(OBJEXT): {$(VPATH)}iseq.h
+hash.$(OBJEXT): {$(VPATH)}method.h
+hash.$(OBJEXT): {$(VPATH)}missing.h
+hash.$(OBJEXT): {$(VPATH)}node.h
+hash.$(OBJEXT): {$(VPATH)}onigmo.h
+hash.$(OBJEXT): {$(VPATH)}oniguruma.h
+hash.$(OBJEXT): {$(VPATH)}prism_compile.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)}ruby_atomic.h
+hash.$(OBJEXT): {$(VPATH)}rubyparser.h
+hash.$(OBJEXT): {$(VPATH)}shape.h
+hash.$(OBJEXT): {$(VPATH)}st.h
+hash.$(OBJEXT): {$(VPATH)}subst.h
+hash.$(OBJEXT): {$(VPATH)}symbol.h
+hash.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+hash.$(OBJEXT): {$(VPATH)}thread_native.h
+hash.$(OBJEXT): {$(VPATH)}util.h
+hash.$(OBJEXT): {$(VPATH)}variable.h
+hash.$(OBJEXT): {$(VPATH)}vm_core.h
+hash.$(OBJEXT): {$(VPATH)}vm_debug.h
+hash.$(OBJEXT): {$(VPATH)}vm_opts.h
+hash.$(OBJEXT): {$(VPATH)}vm_sync.h
+imemo.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+imemo.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+imemo.$(OBJEXT): $(CCAN_DIR)/list/list.h
+imemo.$(OBJEXT): $(CCAN_DIR)/str/str.h
+imemo.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/array.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/box.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/class.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/gc.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/object.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/serial.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/st.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/struct.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/variable.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/vm.h
+imemo.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+imemo.$(OBJEXT): {$(VPATH)}assert.h
+imemo.$(OBJEXT): {$(VPATH)}atomic.h
+imemo.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+imemo.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+imemo.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+imemo.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+imemo.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+imemo.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+imemo.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+imemo.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+imemo.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+imemo.$(OBJEXT): {$(VPATH)}config.h
+imemo.$(OBJEXT): {$(VPATH)}constant.h
+imemo.$(OBJEXT): {$(VPATH)}debug_counter.h
+imemo.$(OBJEXT): {$(VPATH)}defines.h
+imemo.$(OBJEXT): {$(VPATH)}encoding.h
+imemo.$(OBJEXT): {$(VPATH)}id.h
+imemo.$(OBJEXT): {$(VPATH)}id_table.h
+imemo.$(OBJEXT): {$(VPATH)}imemo.c
+imemo.$(OBJEXT): {$(VPATH)}intern.h
+imemo.$(OBJEXT): {$(VPATH)}internal.h
+imemo.$(OBJEXT): {$(VPATH)}internal/abi.h
+imemo.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+imemo.$(OBJEXT): {$(VPATH)}internal/assume.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+imemo.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+imemo.$(OBJEXT): {$(VPATH)}internal/cast.h
+imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+imemo.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+imemo.$(OBJEXT): {$(VPATH)}internal/config.h
+imemo.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+imemo.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+imemo.$(OBJEXT): {$(VPATH)}internal/ctype.h
+imemo.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+imemo.$(OBJEXT): {$(VPATH)}internal/dosish.h
+imemo.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+imemo.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+imemo.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+imemo.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+imemo.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+imemo.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+imemo.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+imemo.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+imemo.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
+imemo.$(OBJEXT): {$(VPATH)}internal/error.h
+imemo.$(OBJEXT): {$(VPATH)}internal/eval.h
+imemo.$(OBJEXT): {$(VPATH)}internal/event.h
+imemo.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+imemo.$(OBJEXT): {$(VPATH)}internal/gc.h
+imemo.$(OBJEXT): {$(VPATH)}internal/glob.h
+imemo.$(OBJEXT): {$(VPATH)}internal/globals.h
+imemo.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+imemo.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+imemo.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+imemo.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+imemo.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+imemo.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+imemo.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+imemo.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/set.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+imemo.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+imemo.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+imemo.$(OBJEXT): {$(VPATH)}internal/iterator.h
+imemo.$(OBJEXT): {$(VPATH)}internal/memory.h
+imemo.$(OBJEXT): {$(VPATH)}internal/method.h
+imemo.$(OBJEXT): {$(VPATH)}internal/module.h
+imemo.$(OBJEXT): {$(VPATH)}internal/newobj.h
+imemo.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+imemo.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+imemo.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+imemo.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+imemo.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+imemo.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
+imemo.$(OBJEXT): {$(VPATH)}internal/symbol.h
+imemo.$(OBJEXT): {$(VPATH)}internal/value.h
+imemo.$(OBJEXT): {$(VPATH)}internal/value_type.h
+imemo.$(OBJEXT): {$(VPATH)}internal/variable.h
+imemo.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+imemo.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+imemo.$(OBJEXT): {$(VPATH)}method.h
+imemo.$(OBJEXT): {$(VPATH)}missing.h
+imemo.$(OBJEXT): {$(VPATH)}node.h
+imemo.$(OBJEXT): {$(VPATH)}onigmo.h
+imemo.$(OBJEXT): {$(VPATH)}oniguruma.h
+imemo.$(OBJEXT): {$(VPATH)}ruby_assert.h
+imemo.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+imemo.$(OBJEXT): {$(VPATH)}rubyparser.h
+imemo.$(OBJEXT): {$(VPATH)}shape.h
+imemo.$(OBJEXT): {$(VPATH)}st.h
+imemo.$(OBJEXT): {$(VPATH)}subst.h
+imemo.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+imemo.$(OBJEXT): {$(VPATH)}thread_native.h
+imemo.$(OBJEXT): {$(VPATH)}vm_callinfo.h
+imemo.$(OBJEXT): {$(VPATH)}vm_core.h
+imemo.$(OBJEXT): {$(VPATH)}vm_debug.h
+imemo.$(OBJEXT): {$(VPATH)}vm_opts.h
+imemo.$(OBJEXT): {$(VPATH)}vm_sync.h
+inits.$(OBJEXT): $(hdrdir)/ruby.h
+inits.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+inits.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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
+inits.$(OBJEXT): {$(VPATH)}subst.h
+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/ruby.h
+io.$(OBJEXT): $(hdrdir)/ruby/version.h
+io.$(OBJEXT): $(top_srcdir)/internal/array.h
+io.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+io.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+io.$(OBJEXT): $(top_srcdir)/internal/bits.h
+io.$(OBJEXT): $(top_srcdir)/internal/box.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/sanitizers.h
+io.$(OBJEXT): $(top_srcdir)/internal/serial.h
+io.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+io.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+io.$(OBJEXT): $(top_srcdir)/internal/string.h
+io.$(OBJEXT): $(top_srcdir)/internal/struct.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)}debug_counter.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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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)}rubyparser.h
+io.$(OBJEXT): {$(VPATH)}shape.h
+io.$(OBJEXT): {$(VPATH)}st.h
+io.$(OBJEXT): {$(VPATH)}subst.h
+io.$(OBJEXT): {$(VPATH)}thread.h
+io.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+io.$(OBJEXT): {$(VPATH)}thread_native.h
+io.$(OBJEXT): {$(VPATH)}util.h
+io.$(OBJEXT): {$(VPATH)}vm_core.h
+io.$(OBJEXT): {$(VPATH)}vm_debug.h
+io.$(OBJEXT): {$(VPATH)}vm_opts.h
+io.$(OBJEXT): {$(VPATH)}vm_sync.h
+io_buffer.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+io_buffer.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+io_buffer.$(OBJEXT): $(CCAN_DIR)/list/list.h
+io_buffer.$(OBJEXT): $(CCAN_DIR)/str/str.h
+io_buffer.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+io_buffer.$(OBJEXT): $(hdrdir)/ruby/version.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/array.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/bits.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/box.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/error.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/gc.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/io.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/serial.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/string.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/thread.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/vm.h
+io_buffer.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+io_buffer.$(OBJEXT): {$(VPATH)}assert.h
+io_buffer.$(OBJEXT): {$(VPATH)}atomic.h
+io_buffer.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+io_buffer.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+io_buffer.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+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)}encindex.h
+io_buffer.$(OBJEXT): {$(VPATH)}encoding.h
+io_buffer.$(OBJEXT): {$(VPATH)}fiber/scheduler.h
+io_buffer.$(OBJEXT): {$(VPATH)}id.h
+io_buffer.$(OBJEXT): {$(VPATH)}id_table.h
+io_buffer.$(OBJEXT): {$(VPATH)}intern.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/abi.h
+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/packed_struct.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/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/set.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+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/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/stdckdint.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)}method.h
+io_buffer.$(OBJEXT): {$(VPATH)}missing.h
+io_buffer.$(OBJEXT): {$(VPATH)}node.h
+io_buffer.$(OBJEXT): {$(VPATH)}onigmo.h
+io_buffer.$(OBJEXT): {$(VPATH)}oniguruma.h
+io_buffer.$(OBJEXT): {$(VPATH)}ruby_assert.h
+io_buffer.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+io_buffer.$(OBJEXT): {$(VPATH)}rubyparser.h
+io_buffer.$(OBJEXT): {$(VPATH)}st.h
+io_buffer.$(OBJEXT): {$(VPATH)}subst.h
+io_buffer.$(OBJEXT): {$(VPATH)}thread.h
+io_buffer.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+io_buffer.$(OBJEXT): {$(VPATH)}thread_native.h
+io_buffer.$(OBJEXT): {$(VPATH)}vm_core.h
+io_buffer.$(OBJEXT): {$(VPATH)}vm_opts.h
+iseq.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+iseq.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+iseq.$(OBJEXT): $(CCAN_DIR)/list/list.h
+iseq.$(OBJEXT): $(CCAN_DIR)/str/str.h
+iseq.$(OBJEXT): $(hdrdir)/ruby.h
+iseq.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+iseq.$(OBJEXT): $(hdrdir)/ruby/version.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/array.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/bits.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/box.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/class.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/compile.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/complex.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/error.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/file.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/gc.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/hash.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/io.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/parse.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/rational.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/serial.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/string.h
+iseq.$(OBJEXT): $(top_srcdir)/internal/struct.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): $(top_srcdir)/prism/ast.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/defines.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/node.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/options.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/pack.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/parser.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/prism.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+iseq.$(OBJEXT): $(top_srcdir)/prism/version.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)}debug_counter.h
+iseq.$(OBJEXT): {$(VPATH)}defines.h
+iseq.$(OBJEXT): {$(VPATH)}encindex.h
+iseq.$(OBJEXT): {$(VPATH)}encoding.h
+iseq.$(OBJEXT): {$(VPATH)}eval_intern.h
+iseq.$(OBJEXT): {$(VPATH)}id.h
+iseq.$(OBJEXT): {$(VPATH)}id_table.h
+iseq.$(OBJEXT): {$(VPATH)}insns.def
+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/abi.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/packed_struct.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/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/set.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/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/stdckdint.h
+iseq.$(OBJEXT): {$(VPATH)}internal/symbol.h
+iseq.$(OBJEXT): {$(VPATH)}internal/value.h
+iseq.$(OBJEXT): {$(VPATH)}internal/value_type.h
+iseq.$(OBJEXT): {$(VPATH)}internal/variable.h
+iseq.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+iseq.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+iseq.$(OBJEXT): {$(VPATH)}io.h
+iseq.$(OBJEXT): {$(VPATH)}iseq.c
+iseq.$(OBJEXT): {$(VPATH)}iseq.h
+iseq.$(OBJEXT): {$(VPATH)}method.h
+iseq.$(OBJEXT): {$(VPATH)}missing.h
+iseq.$(OBJEXT): {$(VPATH)}node.h
+iseq.$(OBJEXT): {$(VPATH)}onigmo.h
+iseq.$(OBJEXT): {$(VPATH)}oniguruma.h
+iseq.$(OBJEXT): {$(VPATH)}prism_compile.h
+iseq.$(OBJEXT): {$(VPATH)}ractor.h
+iseq.$(OBJEXT): {$(VPATH)}ractor_core.h
+iseq.$(OBJEXT): {$(VPATH)}ruby_assert.h
+iseq.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+iseq.$(OBJEXT): {$(VPATH)}rubyparser.h
+iseq.$(OBJEXT): {$(VPATH)}shape.h
+iseq.$(OBJEXT): {$(VPATH)}st.h
+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_debug.h
+iseq.$(OBJEXT): {$(VPATH)}vm_opts.h
+iseq.$(OBJEXT): {$(VPATH)}vm_sync.h
+iseq.$(OBJEXT): {$(VPATH)}yjit.h
+iseq.$(OBJEXT): {$(VPATH)}zjit.h
+jit.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+jit.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+jit.$(OBJEXT): $(CCAN_DIR)/list/list.h
+jit.$(OBJEXT): $(CCAN_DIR)/str/str.h
+jit.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+jit.$(OBJEXT): $(top_srcdir)/internal/array.h
+jit.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+jit.$(OBJEXT): $(top_srcdir)/internal/bits.h
+jit.$(OBJEXT): $(top_srcdir)/internal/box.h
+jit.$(OBJEXT): $(top_srcdir)/internal/class.h
+jit.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+jit.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+jit.$(OBJEXT): $(top_srcdir)/internal/gc.h
+jit.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+jit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+jit.$(OBJEXT): $(top_srcdir)/internal/serial.h
+jit.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+jit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+jit.$(OBJEXT): $(top_srcdir)/internal/string.h
+jit.$(OBJEXT): $(top_srcdir)/internal/struct.h
+jit.$(OBJEXT): $(top_srcdir)/internal/variable.h
+jit.$(OBJEXT): $(top_srcdir)/internal/vm.h
+jit.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+jit.$(OBJEXT): $(top_srcdir)/prism/ast.h
+jit.$(OBJEXT): $(top_srcdir)/prism/defines.h
+jit.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+jit.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+jit.$(OBJEXT): $(top_srcdir)/prism/node.h
+jit.$(OBJEXT): $(top_srcdir)/prism/options.h
+jit.$(OBJEXT): $(top_srcdir)/prism/pack.h
+jit.$(OBJEXT): $(top_srcdir)/prism/parser.h
+jit.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+jit.$(OBJEXT): $(top_srcdir)/prism/prism.h
+jit.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+jit.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+jit.$(OBJEXT): $(top_srcdir)/prism/version.h
+jit.$(OBJEXT): {$(VPATH)}assert.h
+jit.$(OBJEXT): {$(VPATH)}atomic.h
+jit.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+jit.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+jit.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+jit.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+jit.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+jit.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+jit.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+jit.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+jit.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+jit.$(OBJEXT): {$(VPATH)}builtin.h
+jit.$(OBJEXT): {$(VPATH)}config.h
+jit.$(OBJEXT): {$(VPATH)}constant.h
+jit.$(OBJEXT): {$(VPATH)}debug_counter.h
+jit.$(OBJEXT): {$(VPATH)}defines.h
+jit.$(OBJEXT): {$(VPATH)}encindex.h
+jit.$(OBJEXT): {$(VPATH)}encoding.h
+jit.$(OBJEXT): {$(VPATH)}id.h
+jit.$(OBJEXT): {$(VPATH)}id_table.h
+jit.$(OBJEXT): {$(VPATH)}insns.def
+jit.$(OBJEXT): {$(VPATH)}insns.inc
+jit.$(OBJEXT): {$(VPATH)}insns_info.inc
+jit.$(OBJEXT): {$(VPATH)}intern.h
+jit.$(OBJEXT): {$(VPATH)}internal.h
+jit.$(OBJEXT): {$(VPATH)}internal/abi.h
+jit.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+jit.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+jit.$(OBJEXT): {$(VPATH)}internal/assume.h
+jit.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+jit.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+jit.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+jit.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+jit.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+jit.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+jit.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+jit.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+jit.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+jit.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+jit.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+jit.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+jit.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+jit.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+jit.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+jit.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+jit.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+jit.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+jit.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+jit.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
+jit.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+jit.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+jit.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+jit.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+jit.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+jit.$(OBJEXT): {$(VPATH)}internal/cast.h
+jit.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+jit.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+jit.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+jit.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+jit.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+jit.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+jit.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+jit.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+jit.$(OBJEXT): {$(VPATH)}internal/config.h
+jit.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+jit.$(OBJEXT): {$(VPATH)}internal/core.h
+jit.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+jit.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+jit.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+jit.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+jit.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+jit.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+jit.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+jit.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+jit.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+jit.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+jit.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+jit.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+jit.$(OBJEXT): {$(VPATH)}internal/ctype.h
+jit.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+jit.$(OBJEXT): {$(VPATH)}internal/dosish.h
+jit.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+jit.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+jit.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+jit.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+jit.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+jit.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+jit.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+jit.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+jit.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
+jit.$(OBJEXT): {$(VPATH)}internal/error.h
+jit.$(OBJEXT): {$(VPATH)}internal/eval.h
+jit.$(OBJEXT): {$(VPATH)}internal/event.h
+jit.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+jit.$(OBJEXT): {$(VPATH)}internal/gc.h
+jit.$(OBJEXT): {$(VPATH)}internal/glob.h
+jit.$(OBJEXT): {$(VPATH)}internal/globals.h
+jit.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+jit.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+jit.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+jit.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+jit.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+jit.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+jit.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+jit.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/set.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+jit.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+jit.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+jit.$(OBJEXT): {$(VPATH)}internal/iterator.h
+jit.$(OBJEXT): {$(VPATH)}internal/memory.h
+jit.$(OBJEXT): {$(VPATH)}internal/method.h
+jit.$(OBJEXT): {$(VPATH)}internal/module.h
+jit.$(OBJEXT): {$(VPATH)}internal/newobj.h
+jit.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+jit.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+jit.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+jit.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+jit.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+jit.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
+jit.$(OBJEXT): {$(VPATH)}internal/symbol.h
+jit.$(OBJEXT): {$(VPATH)}internal/value.h
+jit.$(OBJEXT): {$(VPATH)}internal/value_type.h
+jit.$(OBJEXT): {$(VPATH)}internal/variable.h
+jit.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+jit.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+jit.$(OBJEXT): {$(VPATH)}iseq.h
+jit.$(OBJEXT): {$(VPATH)}jit.c
+jit.$(OBJEXT): {$(VPATH)}method.h
+jit.$(OBJEXT): {$(VPATH)}missing.h
+jit.$(OBJEXT): {$(VPATH)}node.h
+jit.$(OBJEXT): {$(VPATH)}onigmo.h
+jit.$(OBJEXT): {$(VPATH)}oniguruma.h
+jit.$(OBJEXT): {$(VPATH)}prism_compile.h
+jit.$(OBJEXT): {$(VPATH)}ruby_assert.h
+jit.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+jit.$(OBJEXT): {$(VPATH)}rubyparser.h
+jit.$(OBJEXT): {$(VPATH)}shape.h
+jit.$(OBJEXT): {$(VPATH)}st.h
+jit.$(OBJEXT): {$(VPATH)}subst.h
+jit.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+jit.$(OBJEXT): {$(VPATH)}thread_native.h
+jit.$(OBJEXT): {$(VPATH)}vm_callinfo.h
+jit.$(OBJEXT): {$(VPATH)}vm_core.h
+jit.$(OBJEXT): {$(VPATH)}vm_debug.h
+jit.$(OBJEXT): {$(VPATH)}vm_opts.h
+jit.$(OBJEXT): {$(VPATH)}vm_sync.h
+load.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+load.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+load.$(OBJEXT): $(CCAN_DIR)/list/list.h
+load.$(OBJEXT): $(CCAN_DIR)/str/str.h
+load.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+load.$(OBJEXT): $(hdrdir)/ruby/version.h
+load.$(OBJEXT): $(top_srcdir)/internal/array.h
+load.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+load.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+load.$(OBJEXT): $(top_srcdir)/internal/bits.h
+load.$(OBJEXT): $(top_srcdir)/internal/box.h
+load.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+load.$(OBJEXT): $(top_srcdir)/internal/complex.h
+load.$(OBJEXT): $(top_srcdir)/internal/dir.h
+load.$(OBJEXT): $(top_srcdir)/internal/error.h
+load.$(OBJEXT): $(top_srcdir)/internal/eval.h
+load.$(OBJEXT): $(top_srcdir)/internal/file.h
+load.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+load.$(OBJEXT): $(top_srcdir)/internal/gc.h
+load.$(OBJEXT): $(top_srcdir)/internal/hash.h
+load.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+load.$(OBJEXT): $(top_srcdir)/internal/load.h
+load.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+load.$(OBJEXT): $(top_srcdir)/internal/parse.h
+load.$(OBJEXT): $(top_srcdir)/internal/rational.h
+load.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
+load.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+load.$(OBJEXT): $(top_srcdir)/internal/serial.h
+load.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+load.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+load.$(OBJEXT): $(top_srcdir)/internal/string.h
+load.$(OBJEXT): $(top_srcdir)/internal/struct.h
+load.$(OBJEXT): $(top_srcdir)/internal/thread.h
+load.$(OBJEXT): $(top_srcdir)/internal/variable.h
+load.$(OBJEXT): $(top_srcdir)/internal/vm.h
+load.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+load.$(OBJEXT): $(top_srcdir)/prism/ast.h
+load.$(OBJEXT): $(top_srcdir)/prism/defines.h
+load.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+load.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+load.$(OBJEXT): $(top_srcdir)/prism/node.h
+load.$(OBJEXT): $(top_srcdir)/prism/options.h
+load.$(OBJEXT): $(top_srcdir)/prism/pack.h
+load.$(OBJEXT): $(top_srcdir)/prism/parser.h
+load.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+load.$(OBJEXT): $(top_srcdir)/prism/prism.h
+load.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+load.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+load.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+load.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+load.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+load.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+load.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+load.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+load.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+load.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+load.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+load.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+load.$(OBJEXT): $(top_srcdir)/prism/version.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)}encindex.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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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
+load.$(OBJEXT): {$(VPATH)}missing.h
+load.$(OBJEXT): {$(VPATH)}node.h
+load.$(OBJEXT): {$(VPATH)}onigmo.h
+load.$(OBJEXT): {$(VPATH)}oniguruma.h
+load.$(OBJEXT): {$(VPATH)}prism_compile.h
+load.$(OBJEXT): {$(VPATH)}probes.dmyh
+load.$(OBJEXT): {$(VPATH)}probes.h
+load.$(OBJEXT): {$(VPATH)}ractor.h
+load.$(OBJEXT): {$(VPATH)}ractor_core.h
+load.$(OBJEXT): {$(VPATH)}ruby_assert.h
+load.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+load.$(OBJEXT): {$(VPATH)}rubyparser.h
+load.$(OBJEXT): {$(VPATH)}shape.h
+load.$(OBJEXT): {$(VPATH)}st.h
+load.$(OBJEXT): {$(VPATH)}subst.h
+load.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+load.$(OBJEXT): {$(VPATH)}thread_native.h
+load.$(OBJEXT): {$(VPATH)}util.h
+load.$(OBJEXT): {$(VPATH)}vm_core.h
+load.$(OBJEXT): {$(VPATH)}vm_debug.h
+load.$(OBJEXT): {$(VPATH)}vm_opts.h
+loadpath.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+loadpath.$(OBJEXT): $(hdrdir)/ruby/version.h
+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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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/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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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
+localeinit.$(OBJEXT): {$(VPATH)}oniguruma.h
+localeinit.$(OBJEXT): {$(VPATH)}st.h
+localeinit.$(OBJEXT): {$(VPATH)}subst.h
+main.$(OBJEXT): $(hdrdir)/ruby.h
+main.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+main.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+main.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+main.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+main.$(OBJEXT): {$(VPATH)}assert.h
+main.$(OBJEXT): {$(VPATH)}backward.h
+main.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+main.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+main.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+main.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+main.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+main.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+main.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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)}st.h
+main.$(OBJEXT): {$(VPATH)}subst.h
+main.$(OBJEXT): {$(VPATH)}vm_debug.h
+marshal.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+marshal.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+marshal.$(OBJEXT): $(CCAN_DIR)/list/list.h
+marshal.$(OBJEXT): $(CCAN_DIR)/str/str.h
+marshal.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+marshal.$(OBJEXT): $(hdrdir)/ruby/version.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/array.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/bits.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/box.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/fixnum.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/gc.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/hash.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/object.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/serial.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/string.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/struct.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/util.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/variable.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/vm.h
+marshal.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+marshal.$(OBJEXT): {$(VPATH)}assert.h
+marshal.$(OBJEXT): {$(VPATH)}atomic.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)}constant.h
+marshal.$(OBJEXT): {$(VPATH)}debug_counter.h
+marshal.$(OBJEXT): {$(VPATH)}defines.h
+marshal.$(OBJEXT): {$(VPATH)}encindex.h
+marshal.$(OBJEXT): {$(VPATH)}encoding.h
+marshal.$(OBJEXT): {$(VPATH)}id.h
+marshal.$(OBJEXT): {$(VPATH)}id_table.h
+marshal.$(OBJEXT): {$(VPATH)}intern.h
+marshal.$(OBJEXT): {$(VPATH)}internal.h
+marshal.$(OBJEXT): {$(VPATH)}internal/abi.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/nonstring.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+marshal.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.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/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/set.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/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/stdckdint.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)}method.h
+marshal.$(OBJEXT): {$(VPATH)}missing.h
+marshal.$(OBJEXT): {$(VPATH)}node.h
+marshal.$(OBJEXT): {$(VPATH)}onigmo.h
+marshal.$(OBJEXT): {$(VPATH)}oniguruma.h
+marshal.$(OBJEXT): {$(VPATH)}ruby_assert.h
+marshal.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+marshal.$(OBJEXT): {$(VPATH)}rubyparser.h
+marshal.$(OBJEXT): {$(VPATH)}shape.h
+marshal.$(OBJEXT): {$(VPATH)}st.h
+marshal.$(OBJEXT): {$(VPATH)}subst.h
+marshal.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+marshal.$(OBJEXT): {$(VPATH)}thread_native.h
+marshal.$(OBJEXT): {$(VPATH)}util.h
+marshal.$(OBJEXT): {$(VPATH)}vm_core.h
+marshal.$(OBJEXT): {$(VPATH)}vm_debug.h
+marshal.$(OBJEXT): {$(VPATH)}vm_opts.h
+marshal.$(OBJEXT): {$(VPATH)}vm_sync.h
+math.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+math.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+math.$(OBJEXT): $(top_srcdir)/internal/class.h
+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/variable.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)}constant.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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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)}shape.h
+math.$(OBJEXT): {$(VPATH)}st.h
+math.$(OBJEXT): {$(VPATH)}subst.h
+memory_view.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+memory_view.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+memory_view.$(OBJEXT): $(CCAN_DIR)/list/list.h
+memory_view.$(OBJEXT): $(CCAN_DIR)/str/str.h
+memory_view.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+memory_view.$(OBJEXT): $(top_srcdir)/internal/array.h
+memory_view.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+memory_view.$(OBJEXT): $(top_srcdir)/internal/box.h
+memory_view.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+memory_view.$(OBJEXT): $(top_srcdir)/internal/gc.h
+memory_view.$(OBJEXT): $(top_srcdir)/internal/hash.h
+memory_view.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+memory_view.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+memory_view.$(OBJEXT): $(top_srcdir)/internal/serial.h
+memory_view.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+memory_view.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+memory_view.$(OBJEXT): $(top_srcdir)/internal/struct.h
+memory_view.$(OBJEXT): $(top_srcdir)/internal/variable.h
+memory_view.$(OBJEXT): $(top_srcdir)/internal/vm.h
+memory_view.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+memory_view.$(OBJEXT): {$(VPATH)}assert.h
+memory_view.$(OBJEXT): {$(VPATH)}atomic.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/gcc_version_since.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)}encoding.h
+memory_view.$(OBJEXT): {$(VPATH)}id.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/abi.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/packed_struct.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/encoding/coderange.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.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/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/set.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+memory_view.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+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/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/stdckdint.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)}method.h
+memory_view.$(OBJEXT): {$(VPATH)}missing.h
+memory_view.$(OBJEXT): {$(VPATH)}node.h
+memory_view.$(OBJEXT): {$(VPATH)}onigmo.h
+memory_view.$(OBJEXT): {$(VPATH)}oniguruma.h
+memory_view.$(OBJEXT): {$(VPATH)}ruby_assert.h
+memory_view.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+memory_view.$(OBJEXT): {$(VPATH)}rubyparser.h
+memory_view.$(OBJEXT): {$(VPATH)}shape.h
+memory_view.$(OBJEXT): {$(VPATH)}st.h
+memory_view.$(OBJEXT): {$(VPATH)}subst.h
+memory_view.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+memory_view.$(OBJEXT): {$(VPATH)}thread_native.h
+memory_view.$(OBJEXT): {$(VPATH)}util.h
+memory_view.$(OBJEXT): {$(VPATH)}vm_core.h
+memory_view.$(OBJEXT): {$(VPATH)}vm_debug.h
+memory_view.$(OBJEXT): {$(VPATH)}vm_opts.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/ruby.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/array.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/bits.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/box.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/complex.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/eval.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/gc.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/parse.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/rational.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/serial.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/struct.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/variable.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/vm.h
+miniinit.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/ast.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/defines.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/node.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/options.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/pack.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/parser.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/prism.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+miniinit.$(OBJEXT): $(top_srcdir)/prism/version.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)}constant.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)}id_table.h
+miniinit.$(OBJEXT): {$(VPATH)}intern.h
+miniinit.$(OBJEXT): {$(VPATH)}internal.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/abi.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/nonstring.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+miniinit.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.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/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/set.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/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/stdckdint.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)}jit_hook.rb
+miniinit.$(OBJEXT): {$(VPATH)}jit_undef.rb
+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)}pathname_builtin.rb
+miniinit.$(OBJEXT): {$(VPATH)}prelude.rb
+miniinit.$(OBJEXT): {$(VPATH)}prism_compile.h
+miniinit.$(OBJEXT): {$(VPATH)}ractor.rb
+miniinit.$(OBJEXT): {$(VPATH)}ruby_assert.h
+miniinit.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+miniinit.$(OBJEXT): {$(VPATH)}rubyparser.h
+miniinit.$(OBJEXT): {$(VPATH)}shape.h
+miniinit.$(OBJEXT): {$(VPATH)}st.h
+miniinit.$(OBJEXT): {$(VPATH)}subst.h
+miniinit.$(OBJEXT): {$(VPATH)}symbol.rb
+miniinit.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+miniinit.$(OBJEXT): {$(VPATH)}thread_native.h
+miniinit.$(OBJEXT): {$(VPATH)}thread_sync.rb
+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
+miniinit.$(OBJEXT): {$(VPATH)}zjit.rb
+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/ruby.h
+node.$(OBJEXT): $(top_srcdir)/internal/array.h
+node.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+node.$(OBJEXT): $(top_srcdir)/internal/box.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/sanitizers.h
+node.$(OBJEXT): $(top_srcdir)/internal/serial.h
+node.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+node.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+node.$(OBJEXT): $(top_srcdir)/internal/struct.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)}defines.h
+node.$(OBJEXT): {$(VPATH)}encoding.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/abi.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/packed_struct.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/encoding/coderange.h
+node.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+node.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+node.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+node.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+node.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+node.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+node.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+node.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.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/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/set.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/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/stdckdint.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
+node.$(OBJEXT): {$(VPATH)}node.h
+node.$(OBJEXT): {$(VPATH)}node_name.inc
+node.$(OBJEXT): {$(VPATH)}onigmo.h
+node.$(OBJEXT): {$(VPATH)}oniguruma.h
+node.$(OBJEXT): {$(VPATH)}ruby_assert.h
+node.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+node.$(OBJEXT): {$(VPATH)}rubyparser.h
+node.$(OBJEXT): {$(VPATH)}shape.h
+node.$(OBJEXT): {$(VPATH)}st.h
+node.$(OBJEXT): {$(VPATH)}subst.h
+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
+node_dump.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+node_dump.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+node_dump.$(OBJEXT): $(CCAN_DIR)/list/list.h
+node_dump.$(OBJEXT): $(CCAN_DIR)/str/str.h
+node_dump.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/array.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/bits.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/box.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/class.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/complex.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/gc.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/hash.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/parse.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/rational.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/serial.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/struct.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/variable.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/vm.h
+node_dump.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+node_dump.$(OBJEXT): {$(VPATH)}assert.h
+node_dump.$(OBJEXT): {$(VPATH)}atomic.h
+node_dump.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+node_dump.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+node_dump.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+node_dump.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+node_dump.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+node_dump.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+node_dump.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+node_dump.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+node_dump.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+node_dump.$(OBJEXT): {$(VPATH)}config.h
+node_dump.$(OBJEXT): {$(VPATH)}constant.h
+node_dump.$(OBJEXT): {$(VPATH)}debug_counter.h
+node_dump.$(OBJEXT): {$(VPATH)}defines.h
+node_dump.$(OBJEXT): {$(VPATH)}encoding.h
+node_dump.$(OBJEXT): {$(VPATH)}id.h
+node_dump.$(OBJEXT): {$(VPATH)}id_table.h
+node_dump.$(OBJEXT): {$(VPATH)}intern.h
+node_dump.$(OBJEXT): {$(VPATH)}internal.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/abi.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/assume.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/cast.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/config.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/ctype.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/dosish.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/error.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/eval.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/event.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/gc.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/glob.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/globals.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/set.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/iterator.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/memory.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/method.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/module.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/newobj.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/symbol.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/value.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/value_type.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/variable.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+node_dump.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+node_dump.$(OBJEXT): {$(VPATH)}method.h
+node_dump.$(OBJEXT): {$(VPATH)}missing.h
+node_dump.$(OBJEXT): {$(VPATH)}node.h
+node_dump.$(OBJEXT): {$(VPATH)}node_dump.c
+node_dump.$(OBJEXT): {$(VPATH)}onigmo.h
+node_dump.$(OBJEXT): {$(VPATH)}oniguruma.h
+node_dump.$(OBJEXT): {$(VPATH)}ruby_assert.h
+node_dump.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+node_dump.$(OBJEXT): {$(VPATH)}rubyparser.h
+node_dump.$(OBJEXT): {$(VPATH)}shape.h
+node_dump.$(OBJEXT): {$(VPATH)}st.h
+node_dump.$(OBJEXT): {$(VPATH)}subst.h
+node_dump.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+node_dump.$(OBJEXT): {$(VPATH)}thread_native.h
+node_dump.$(OBJEXT): {$(VPATH)}vm_core.h
+node_dump.$(OBJEXT): {$(VPATH)}vm_debug.h
+node_dump.$(OBJEXT): {$(VPATH)}vm_opts.h
+node_dump.$(OBJEXT): {$(VPATH)}vm_sync.h
+numeric.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+numeric.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+numeric.$(OBJEXT): $(CCAN_DIR)/list/list.h
+numeric.$(OBJEXT): $(CCAN_DIR)/str/str.h
+numeric.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/array.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/bits.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/box.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/imemo.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/object.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/rational.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/serial.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/string.h
+numeric.$(OBJEXT): $(top_srcdir)/internal/struct.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)}atomic.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)}encindex.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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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)}method.h
+numeric.$(OBJEXT): {$(VPATH)}missing.h
+numeric.$(OBJEXT): {$(VPATH)}node.h
+numeric.$(OBJEXT): {$(VPATH)}numeric.c
+numeric.$(OBJEXT): {$(VPATH)}numeric.rbinc
+numeric.$(OBJEXT): {$(VPATH)}onigmo.h
+numeric.$(OBJEXT): {$(VPATH)}oniguruma.h
+numeric.$(OBJEXT): {$(VPATH)}ruby_assert.h
+numeric.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+numeric.$(OBJEXT): {$(VPATH)}rubyparser.h
+numeric.$(OBJEXT): {$(VPATH)}shape.h
+numeric.$(OBJEXT): {$(VPATH)}st.h
+numeric.$(OBJEXT): {$(VPATH)}subst.h
+numeric.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+numeric.$(OBJEXT): {$(VPATH)}thread_native.h
+numeric.$(OBJEXT): {$(VPATH)}util.h
+numeric.$(OBJEXT): {$(VPATH)}vm_core.h
+numeric.$(OBJEXT): {$(VPATH)}vm_opts.h
+object.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+object.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+object.$(OBJEXT): $(CCAN_DIR)/list/list.h
+object.$(OBJEXT): $(CCAN_DIR)/str/str.h
+object.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+object.$(OBJEXT): $(hdrdir)/ruby/version.h
+object.$(OBJEXT): $(top_srcdir)/internal/array.h
+object.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+object.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+object.$(OBJEXT): $(top_srcdir)/internal/bits.h
+object.$(OBJEXT): $(top_srcdir)/internal/box.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/imemo.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/sanitizers.h
+object.$(OBJEXT): $(top_srcdir)/internal/serial.h
+object.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+object.$(OBJEXT): $(top_srcdir)/internal/st.h
+object.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+object.$(OBJEXT): $(top_srcdir)/internal/string.h
+object.$(OBJEXT): $(top_srcdir)/internal/struct.h
+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)}atomic.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)}debug_counter.h
+object.$(OBJEXT): {$(VPATH)}defines.h
+object.$(OBJEXT): {$(VPATH)}encindex.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/abi.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/packed_struct.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/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/set.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/scan_args.h
+object.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+object.$(OBJEXT): {$(VPATH)}internal/st.h
+object.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+object.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+object.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+object.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
+object.$(OBJEXT): {$(VPATH)}internal/symbol.h
+object.$(OBJEXT): {$(VPATH)}internal/value.h
+object.$(OBJEXT): {$(VPATH)}internal/value_type.h
+object.$(OBJEXT): {$(VPATH)}internal/variable.h
+object.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+object.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+object.$(OBJEXT): {$(VPATH)}kernel.rbinc
+object.$(OBJEXT): {$(VPATH)}method.h
+object.$(OBJEXT): {$(VPATH)}missing.h
+object.$(OBJEXT): {$(VPATH)}nilclass.rbinc
+object.$(OBJEXT): {$(VPATH)}node.h
+object.$(OBJEXT): {$(VPATH)}object.c
+object.$(OBJEXT): {$(VPATH)}onigmo.h
+object.$(OBJEXT): {$(VPATH)}oniguruma.h
+object.$(OBJEXT): {$(VPATH)}probes.dmyh
+object.$(OBJEXT): {$(VPATH)}probes.h
+object.$(OBJEXT): {$(VPATH)}ruby_assert.h
+object.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+object.$(OBJEXT): {$(VPATH)}rubyparser.h
+object.$(OBJEXT): {$(VPATH)}shape.h
+object.$(OBJEXT): {$(VPATH)}st.h
+object.$(OBJEXT): {$(VPATH)}subst.h
+object.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+object.$(OBJEXT): {$(VPATH)}thread_native.h
+object.$(OBJEXT): {$(VPATH)}util.h
+object.$(OBJEXT): {$(VPATH)}variable.h
+object.$(OBJEXT): {$(VPATH)}vm_core.h
+object.$(OBJEXT): {$(VPATH)}vm_debug.h
+object.$(OBJEXT): {$(VPATH)}vm_opts.h
+object.$(OBJEXT): {$(VPATH)}vm_sync.h
+object.$(OBJEXT): {$(VPATH)}yjit.h
+pack.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+pack.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+pack.$(OBJEXT): $(CCAN_DIR)/list/list.h
+pack.$(OBJEXT): $(CCAN_DIR)/str/str.h
+pack.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+pack.$(OBJEXT): $(top_srcdir)/internal/array.h
+pack.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+pack.$(OBJEXT): $(top_srcdir)/internal/bits.h
+pack.$(OBJEXT): $(top_srcdir)/internal/box.h
+pack.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+pack.$(OBJEXT): $(top_srcdir)/internal/gc.h
+pack.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+pack.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+pack.$(OBJEXT): $(top_srcdir)/internal/serial.h
+pack.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+pack.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+pack.$(OBJEXT): $(top_srcdir)/internal/string.h
+pack.$(OBJEXT): $(top_srcdir)/internal/struct.h
+pack.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+pack.$(OBJEXT): $(top_srcdir)/internal/variable.h
+pack.$(OBJEXT): $(top_srcdir)/internal/vm.h
+pack.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+pack.$(OBJEXT): {$(VPATH)}assert.h
+pack.$(OBJEXT): {$(VPATH)}atomic.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)}encindex.h
+pack.$(OBJEXT): {$(VPATH)}encoding.h
+pack.$(OBJEXT): {$(VPATH)}id.h
+pack.$(OBJEXT): {$(VPATH)}id_table.h
+pack.$(OBJEXT): {$(VPATH)}intern.h
+pack.$(OBJEXT): {$(VPATH)}internal.h
+pack.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/set.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/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/stdckdint.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)}method.h
+pack.$(OBJEXT): {$(VPATH)}missing.h
+pack.$(OBJEXT): {$(VPATH)}node.h
+pack.$(OBJEXT): {$(VPATH)}onigmo.h
+pack.$(OBJEXT): {$(VPATH)}oniguruma.h
+pack.$(OBJEXT): {$(VPATH)}pack.c
+pack.$(OBJEXT): {$(VPATH)}pack.rbinc
+pack.$(OBJEXT): {$(VPATH)}ruby_assert.h
+pack.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+pack.$(OBJEXT): {$(VPATH)}rubyparser.h
+pack.$(OBJEXT): {$(VPATH)}shape.h
+pack.$(OBJEXT): {$(VPATH)}st.h
+pack.$(OBJEXT): {$(VPATH)}subst.h
+pack.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+pack.$(OBJEXT): {$(VPATH)}thread_native.h
+pack.$(OBJEXT): {$(VPATH)}util.h
+pack.$(OBJEXT): {$(VPATH)}vm_core.h
+pack.$(OBJEXT): {$(VPATH)}vm_opts.h
+parse.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+parse.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+parse.$(OBJEXT): $(CCAN_DIR)/list/list.h
+parse.$(OBJEXT): $(CCAN_DIR)/str/str.h
+parse.$(OBJEXT): $(hdrdir)/ruby.h
+parse.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+parse.$(OBJEXT): $(hdrdir)/ruby/version.h
+parse.$(OBJEXT): $(top_srcdir)/internal/array.h
+parse.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+parse.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+parse.$(OBJEXT): $(top_srcdir)/internal/bits.h
+parse.$(OBJEXT): $(top_srcdir)/internal/box.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/encoding.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/ruby_parser.h
+parse.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+parse.$(OBJEXT): $(top_srcdir)/internal/serial.h
+parse.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+parse.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+parse.$(OBJEXT): $(top_srcdir)/internal/string.h
+parse.$(OBJEXT): $(top_srcdir)/internal/struct.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)}atomic.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)}encindex.h
+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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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)}method.h
+parse.$(OBJEXT): {$(VPATH)}missing.h
+parse.$(OBJEXT): {$(VPATH)}node.h
+parse.$(OBJEXT): {$(VPATH)}onigmo.h
+parse.$(OBJEXT): {$(VPATH)}oniguruma.h
+parse.$(OBJEXT): {$(VPATH)}parse.c
+parse.$(OBJEXT): {$(VPATH)}parse.h
+parse.$(OBJEXT): {$(VPATH)}parse.y
+parse.$(OBJEXT): {$(VPATH)}parser_node.h
+parse.$(OBJEXT): {$(VPATH)}parser_st.h
+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)}ruby_atomic.h
+parse.$(OBJEXT): {$(VPATH)}rubyparser.h
+parse.$(OBJEXT): {$(VPATH)}shape.h
+parse.$(OBJEXT): {$(VPATH)}st.h
+parse.$(OBJEXT): {$(VPATH)}subst.h
+parse.$(OBJEXT): {$(VPATH)}symbol.h
+parse.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+parse.$(OBJEXT): {$(VPATH)}thread_native.h
+parse.$(OBJEXT): {$(VPATH)}util.h
+parse.$(OBJEXT): {$(VPATH)}vm_core.h
+parse.$(OBJEXT): {$(VPATH)}vm_opts.h
+parser_st.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+parser_st.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+parser_st.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+parser_st.$(OBJEXT): {$(VPATH)}assert.h
+parser_st.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+parser_st.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+parser_st.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+parser_st.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+parser_st.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+parser_st.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+parser_st.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+parser_st.$(OBJEXT): {$(VPATH)}config.h
+parser_st.$(OBJEXT): {$(VPATH)}defines.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/assume.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/cast.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/config.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/dosish.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+parser_st.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+parser_st.$(OBJEXT): {$(VPATH)}missing.h
+parser_st.$(OBJEXT): {$(VPATH)}parser_bits.h
+parser_st.$(OBJEXT): {$(VPATH)}parser_st.c
+parser_st.$(OBJEXT): {$(VPATH)}parser_st.h
+parser_st.$(OBJEXT): {$(VPATH)}parser_value.h
+parser_st.$(OBJEXT): {$(VPATH)}st.c
+pathname.$(OBJEXT): $(hdrdir)/ruby.h
+pathname.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+pathname.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+pathname.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+pathname.$(OBJEXT): {$(VPATH)}assert.h
+pathname.$(OBJEXT): {$(VPATH)}backward.h
+pathname.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+pathname.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+pathname.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+pathname.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+pathname.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+pathname.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+pathname.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+pathname.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+pathname.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+pathname.$(OBJEXT): {$(VPATH)}builtin.h
+pathname.$(OBJEXT): {$(VPATH)}config.h
+pathname.$(OBJEXT): {$(VPATH)}defines.h
+pathname.$(OBJEXT): {$(VPATH)}encoding.h
+pathname.$(OBJEXT): {$(VPATH)}intern.h
+pathname.$(OBJEXT): {$(VPATH)}internal/abi.h
+pathname.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+pathname.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+pathname.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+pathname.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+pathname.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+pathname.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+pathname.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+pathname.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+pathname.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+pathname.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+pathname.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+pathname.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+pathname.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+pathname.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+pathname.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+pathname.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+pathname.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+pathname.$(OBJEXT): {$(VPATH)}internal/assume.h
+pathname.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+pathname.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+pathname.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+pathname.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+pathname.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+pathname.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+pathname.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+pathname.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+pathname.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+pathname.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+pathname.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+pathname.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+pathname.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+pathname.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+pathname.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+pathname.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+pathname.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+pathname.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+pathname.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+pathname.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
+pathname.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+pathname.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+pathname.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+pathname.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+pathname.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+pathname.$(OBJEXT): {$(VPATH)}internal/cast.h
+pathname.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+pathname.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+pathname.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+pathname.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+pathname.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+pathname.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+pathname.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+pathname.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+pathname.$(OBJEXT): {$(VPATH)}internal/config.h
+pathname.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+pathname.$(OBJEXT): {$(VPATH)}internal/core.h
+pathname.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+pathname.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+pathname.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+pathname.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+pathname.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+pathname.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+pathname.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+pathname.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+pathname.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+pathname.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+pathname.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+pathname.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+pathname.$(OBJEXT): {$(VPATH)}internal/ctype.h
+pathname.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+pathname.$(OBJEXT): {$(VPATH)}internal/dosish.h
+pathname.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+pathname.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+pathname.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+pathname.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+pathname.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+pathname.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+pathname.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+pathname.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+pathname.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
+pathname.$(OBJEXT): {$(VPATH)}internal/error.h
+pathname.$(OBJEXT): {$(VPATH)}internal/eval.h
+pathname.$(OBJEXT): {$(VPATH)}internal/event.h
+pathname.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+pathname.$(OBJEXT): {$(VPATH)}internal/gc.h
+pathname.$(OBJEXT): {$(VPATH)}internal/glob.h
+pathname.$(OBJEXT): {$(VPATH)}internal/globals.h
+pathname.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+pathname.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+pathname.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+pathname.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+pathname.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+pathname.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+pathname.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+pathname.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/set.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+pathname.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+pathname.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+pathname.$(OBJEXT): {$(VPATH)}internal/iterator.h
+pathname.$(OBJEXT): {$(VPATH)}internal/memory.h
+pathname.$(OBJEXT): {$(VPATH)}internal/method.h
+pathname.$(OBJEXT): {$(VPATH)}internal/module.h
+pathname.$(OBJEXT): {$(VPATH)}internal/newobj.h
+pathname.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+pathname.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+pathname.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+pathname.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+pathname.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+pathname.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
+pathname.$(OBJEXT): {$(VPATH)}internal/symbol.h
+pathname.$(OBJEXT): {$(VPATH)}internal/value.h
+pathname.$(OBJEXT): {$(VPATH)}internal/value_type.h
+pathname.$(OBJEXT): {$(VPATH)}internal/variable.h
+pathname.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+pathname.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+pathname.$(OBJEXT): {$(VPATH)}missing.h
+pathname.$(OBJEXT): {$(VPATH)}onigmo.h
+pathname.$(OBJEXT): {$(VPATH)}oniguruma.h
+pathname.$(OBJEXT): {$(VPATH)}pathname.c
+pathname.$(OBJEXT): {$(VPATH)}pathname_builtin.rbinc
+pathname.$(OBJEXT): {$(VPATH)}ruby.h
+pathname.$(OBJEXT): {$(VPATH)}st.h
+pathname.$(OBJEXT): {$(VPATH)}subst.h
+prism/api_node.$(OBJEXT): $(hdrdir)/ruby.h
+prism/api_node.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/api_node.c
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/ast.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/extension.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/node.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/options.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/pack.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/parser.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/prism.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+prism/api_node.$(OBJEXT): $(top_srcdir)/prism/version.h
+prism/api_node.$(OBJEXT): {$(VPATH)}assert.h
+prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+prism/api_node.$(OBJEXT): {$(VPATH)}config.h
+prism/api_node.$(OBJEXT): {$(VPATH)}defines.h
+prism/api_node.$(OBJEXT): {$(VPATH)}encoding.h
+prism/api_node.$(OBJEXT): {$(VPATH)}intern.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/abi.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/assume.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/cast.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/config.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/core.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/ctype.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/dosish.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/error.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/eval.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/event.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/gc.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/glob.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/globals.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/set.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/iterator.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/memory.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/method.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/module.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/newobj.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/symbol.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/value.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/value_type.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/variable.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+prism/api_node.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+prism/api_node.$(OBJEXT): {$(VPATH)}missing.h
+prism/api_node.$(OBJEXT): {$(VPATH)}onigmo.h
+prism/api_node.$(OBJEXT): {$(VPATH)}oniguruma.h
+prism/api_node.$(OBJEXT): {$(VPATH)}st.h
+prism/api_node.$(OBJEXT): {$(VPATH)}subst.h
+prism/api_pack.$(OBJEXT): $(hdrdir)/ruby.h
+prism/api_pack.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/api_pack.c
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/ast.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/extension.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/node.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/options.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/pack.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/parser.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/prism.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/version.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}assert.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}config.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}defines.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}encoding.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}intern.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/abi.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/assume.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/cast.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/config.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/ctype.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/dosish.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/error.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/eval.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/event.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/gc.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/glob.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/globals.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/set.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/iterator.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/memory.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/method.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/module.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/newobj.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/symbol.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/value.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/value_type.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/variable.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}missing.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}onigmo.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}oniguruma.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}st.h
+prism/api_pack.$(OBJEXT): {$(VPATH)}subst.h
+prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/ast.h
+prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/diagnostic.c
+prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+prism/encoding.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/encoding.$(OBJEXT): $(top_srcdir)/prism/encoding.c
+prism/encoding.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+prism/encoding.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+prism/extension.$(OBJEXT): $(hdrdir)/ruby.h
+prism/extension.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/ast.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/extension.c
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/extension.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/node.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/options.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/pack.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/parser.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/prism.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+prism/extension.$(OBJEXT): $(top_srcdir)/prism/version.h
+prism/extension.$(OBJEXT): {$(VPATH)}assert.h
+prism/extension.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+prism/extension.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+prism/extension.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+prism/extension.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+prism/extension.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+prism/extension.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+prism/extension.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+prism/extension.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+prism/extension.$(OBJEXT): {$(VPATH)}config.h
+prism/extension.$(OBJEXT): {$(VPATH)}defines.h
+prism/extension.$(OBJEXT): {$(VPATH)}encoding.h
+prism/extension.$(OBJEXT): {$(VPATH)}intern.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/abi.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/assume.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/cast.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/config.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/core.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/ctype.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/dosish.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/error.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/eval.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/event.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/gc.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/glob.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/globals.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/set.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/iterator.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/memory.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/method.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/module.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/newobj.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/symbol.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/value.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/value_type.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/variable.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+prism/extension.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+prism/extension.$(OBJEXT): {$(VPATH)}missing.h
+prism/extension.$(OBJEXT): {$(VPATH)}onigmo.h
+prism/extension.$(OBJEXT): {$(VPATH)}oniguruma.h
+prism/extension.$(OBJEXT): {$(VPATH)}st.h
+prism/extension.$(OBJEXT): {$(VPATH)}subst.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/ast.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/node.c
+prism/node.$(OBJEXT): $(top_srcdir)/prism/node.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/options.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/pack.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/parser.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/prism.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+prism/options.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/options.$(OBJEXT): $(top_srcdir)/prism/options.c
+prism/options.$(OBJEXT): $(top_srcdir)/prism/options.h
+prism/options.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+prism/options.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+prism/options.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+prism/pack.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/pack.$(OBJEXT): $(top_srcdir)/prism/pack.c
+prism/pack.$(OBJEXT): $(top_srcdir)/prism/pack.h
+prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/ast.h
+prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/options.h
+prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/parser.h
+prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/prettyprint.c
+prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/ast.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/node.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/options.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/pack.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/parser.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/prism.c
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/prism.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+prism/prism.$(OBJEXT): $(top_srcdir)/prism/version.h
+prism/regexp.$(OBJEXT): $(top_srcdir)/prism/ast.h
+prism/regexp.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/regexp.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+prism/regexp.$(OBJEXT): $(top_srcdir)/prism/options.h
+prism/regexp.$(OBJEXT): $(top_srcdir)/prism/parser.h
+prism/regexp.$(OBJEXT): $(top_srcdir)/prism/regexp.c
+prism/regexp.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+prism/regexp.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/ast.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/node.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/options.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/pack.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/parser.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/prism.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/serialize.c
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+prism/serialize.$(OBJEXT): $(top_srcdir)/prism/version.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/ast.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/node.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/options.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/parser.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/static_literals.c
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+prism/token_type.$(OBJEXT): $(top_srcdir)/prism/ast.h
+prism/token_type.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/token_type.$(OBJEXT): $(top_srcdir)/prism/token_type.c
+prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.c
+prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+prism/util/pm_char.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/util/pm_char.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.c
+prism/util/pm_char.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+prism/util/pm_char.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+prism/util/pm_constant_pool.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/util/pm_constant_pool.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.c
+prism/util/pm_constant_pool.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.c
+prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+prism/util/pm_list.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/util/pm_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.c
+prism/util/pm_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/ast.h
+prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/parser.h
+prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.c
+prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+prism/util/pm_newline_list.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/util/pm_newline_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.c
+prism/util/pm_newline_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+prism/util/pm_string.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/util/pm_string.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.c
+prism/util/pm_string.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+prism/util/pm_strncasecmp.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/util/pm_strncasecmp.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.c
+prism/util/pm_strncasecmp.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/ast.h
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/options.h
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/parser.h
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.c
+prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+prism_init.$(OBJEXT): $(hdrdir)/ruby.h
+prism_init.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/ast.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/defines.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/extension.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/node.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/options.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/pack.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/parser.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/prism.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism/version.h
+prism_init.$(OBJEXT): $(top_srcdir)/prism_init.c
+prism_init.$(OBJEXT): {$(VPATH)}assert.h
+prism_init.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+prism_init.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+prism_init.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+prism_init.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+prism_init.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+prism_init.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+prism_init.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+prism_init.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+prism_init.$(OBJEXT): {$(VPATH)}config.h
+prism_init.$(OBJEXT): {$(VPATH)}defines.h
+prism_init.$(OBJEXT): {$(VPATH)}encoding.h
+prism_init.$(OBJEXT): {$(VPATH)}intern.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/abi.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/assume.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/cast.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/config.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/core.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/ctype.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/dosish.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/error.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/eval.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/event.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/gc.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/glob.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/globals.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/set.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/iterator.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/memory.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/method.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/module.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/newobj.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/symbol.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/value.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/value_type.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/variable.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+prism_init.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+prism_init.$(OBJEXT): {$(VPATH)}missing.h
+prism_init.$(OBJEXT): {$(VPATH)}onigmo.h
+prism_init.$(OBJEXT): {$(VPATH)}oniguruma.h
+prism_init.$(OBJEXT): {$(VPATH)}prism_init.c
+prism_init.$(OBJEXT): {$(VPATH)}st.h
+prism_init.$(OBJEXT): {$(VPATH)}subst.h
+proc.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+proc.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+proc.$(OBJEXT): $(CCAN_DIR)/list/list.h
+proc.$(OBJEXT): $(CCAN_DIR)/str/str.h
+proc.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+proc.$(OBJEXT): $(hdrdir)/ruby/version.h
+proc.$(OBJEXT): $(top_srcdir)/internal/array.h
+proc.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+proc.$(OBJEXT): $(top_srcdir)/internal/box.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/hash.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/sanitizers.h
+proc.$(OBJEXT): $(top_srcdir)/internal/serial.h
+proc.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+proc.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+proc.$(OBJEXT): $(top_srcdir)/internal/string.h
+proc.$(OBJEXT): $(top_srcdir)/internal/struct.h
+proc.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+proc.$(OBJEXT): $(top_srcdir)/internal/variable.h
+proc.$(OBJEXT): $(top_srcdir)/internal/vm.h
+proc.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+proc.$(OBJEXT): $(top_srcdir)/prism/ast.h
+proc.$(OBJEXT): $(top_srcdir)/prism/defines.h
+proc.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+proc.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+proc.$(OBJEXT): $(top_srcdir)/prism/node.h
+proc.$(OBJEXT): $(top_srcdir)/prism/options.h
+proc.$(OBJEXT): $(top_srcdir)/prism/pack.h
+proc.$(OBJEXT): $(top_srcdir)/prism/parser.h
+proc.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+proc.$(OBJEXT): $(top_srcdir)/prism/prism.h
+proc.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+proc.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+proc.$(OBJEXT): $(top_srcdir)/prism/version.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)}constant.h
+proc.$(OBJEXT): {$(VPATH)}debug_counter.h
+proc.$(OBJEXT): {$(VPATH)}defines.h
+proc.$(OBJEXT): {$(VPATH)}encindex.h
+proc.$(OBJEXT): {$(VPATH)}encoding.h
+proc.$(OBJEXT): {$(VPATH)}eval_intern.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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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)}prism_compile.h
+proc.$(OBJEXT): {$(VPATH)}proc.c
+proc.$(OBJEXT): {$(VPATH)}ractor.h
+proc.$(OBJEXT): {$(VPATH)}ractor_core.h
+proc.$(OBJEXT): {$(VPATH)}ruby_assert.h
+proc.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+proc.$(OBJEXT): {$(VPATH)}rubyparser.h
+proc.$(OBJEXT): {$(VPATH)}shape.h
+proc.$(OBJEXT): {$(VPATH)}st.h
+proc.$(OBJEXT): {$(VPATH)}subst.h
+proc.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+proc.$(OBJEXT): {$(VPATH)}thread_native.h
+proc.$(OBJEXT): {$(VPATH)}vm_core.h
+proc.$(OBJEXT): {$(VPATH)}vm_debug.h
+proc.$(OBJEXT): {$(VPATH)}vm_opts.h
+proc.$(OBJEXT): {$(VPATH)}vm_sync.h
+proc.$(OBJEXT): {$(VPATH)}yjit.h
+process.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+process.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+process.$(OBJEXT): $(CCAN_DIR)/list/list.h
+process.$(OBJEXT): $(CCAN_DIR)/str/str.h
+process.$(OBJEXT): $(hdrdir)/ruby.h
+process.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+process.$(OBJEXT): $(hdrdir)/ruby/version.h
+process.$(OBJEXT): $(top_srcdir)/internal/array.h
+process.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+process.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+process.$(OBJEXT): $(top_srcdir)/internal/bits.h
+process.$(OBJEXT): $(top_srcdir)/internal/box.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/io.h
+process.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+process.$(OBJEXT): $(top_srcdir)/internal/object.h
+process.$(OBJEXT): $(top_srcdir)/internal/process.h
+process.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+process.$(OBJEXT): $(top_srcdir)/internal/serial.h
+process.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+process.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+process.$(OBJEXT): $(top_srcdir)/internal/string.h
+process.$(OBJEXT): $(top_srcdir)/internal/struct.h
+process.$(OBJEXT): $(top_srcdir)/internal/thread.h
+process.$(OBJEXT): $(top_srcdir)/internal/time.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)}debug_counter.h
+process.$(OBJEXT): {$(VPATH)}defines.h
+process.$(OBJEXT): {$(VPATH)}dln.h
+process.$(OBJEXT): {$(VPATH)}encindex.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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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)}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)}ractor_core.h
+process.$(OBJEXT): {$(VPATH)}ruby_assert.h
+process.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+process.$(OBJEXT): {$(VPATH)}rubyparser.h
+process.$(OBJEXT): {$(VPATH)}shape.h
+process.$(OBJEXT): {$(VPATH)}st.h
+process.$(OBJEXT): {$(VPATH)}subst.h
+process.$(OBJEXT): {$(VPATH)}thread.h
+process.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+process.$(OBJEXT): {$(VPATH)}thread_native.h
+process.$(OBJEXT): {$(VPATH)}util.h
+process.$(OBJEXT): {$(VPATH)}vm_core.h
+process.$(OBJEXT): {$(VPATH)}vm_debug.h
+process.$(OBJEXT): {$(VPATH)}vm_opts.h
+process.$(OBJEXT): {$(VPATH)}vm_sync.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.h
+ractor.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+ractor.$(OBJEXT): $(hdrdir)/ruby/version.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/array.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/bits.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/box.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/object.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/ractor.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/rational.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/serial.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/string.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/struct.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/thread.h
+ractor.$(OBJEXT): $(top_srcdir)/internal/variable.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)}constant.h
+ractor.$(OBJEXT): {$(VPATH)}debug_counter.h
+ractor.$(OBJEXT): {$(VPATH)}defines.h
+ractor.$(OBJEXT): {$(VPATH)}encindex.h
+ractor.$(OBJEXT): {$(VPATH)}encoding.h
+ractor.$(OBJEXT): {$(VPATH)}eval_intern.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/abi.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/packed_struct.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/rmatch.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/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/set.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/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/stdckdint.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.rbinc
+ractor.$(OBJEXT): {$(VPATH)}ractor_core.h
+ractor.$(OBJEXT): {$(VPATH)}ractor_sync.c
+ractor.$(OBJEXT): {$(VPATH)}re.h
+ractor.$(OBJEXT): {$(VPATH)}regex.h
+ractor.$(OBJEXT): {$(VPATH)}ruby_assert.h
+ractor.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+ractor.$(OBJEXT): {$(VPATH)}rubyparser.h
+ractor.$(OBJEXT): {$(VPATH)}shape.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)}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
+ractor.$(OBJEXT): {$(VPATH)}zjit.h
+random.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+random.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+random.$(OBJEXT): $(CCAN_DIR)/list/list.h
+random.$(OBJEXT): $(CCAN_DIR)/str/str.h
+random.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+random.$(OBJEXT): $(top_srcdir)/internal/array.h
+random.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+random.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+random.$(OBJEXT): $(top_srcdir)/internal/bits.h
+random.$(OBJEXT): $(top_srcdir)/internal/box.h
+random.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+random.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+random.$(OBJEXT): $(top_srcdir)/internal/gc.h
+random.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+random.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+random.$(OBJEXT): $(top_srcdir)/internal/random.h
+random.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+random.$(OBJEXT): $(top_srcdir)/internal/serial.h
+random.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+random.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+random.$(OBJEXT): $(top_srcdir)/internal/struct.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)}encoding.h
+random.$(OBJEXT): {$(VPATH)}id.h
+random.$(OBJEXT): {$(VPATH)}id_table.h
+random.$(OBJEXT): {$(VPATH)}intern.h
+random.$(OBJEXT): {$(VPATH)}internal.h
+random.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/encoding/coderange.h
+random.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+random.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+random.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+random.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+random.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+random.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+random.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+random.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.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/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/set.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/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/stdckdint.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)}method.h
+random.$(OBJEXT): {$(VPATH)}missing.h
+random.$(OBJEXT): {$(VPATH)}mt19937.c
+random.$(OBJEXT): {$(VPATH)}node.h
+random.$(OBJEXT): {$(VPATH)}onigmo.h
+random.$(OBJEXT): {$(VPATH)}oniguruma.h
+random.$(OBJEXT): {$(VPATH)}ractor.h
+random.$(OBJEXT): {$(VPATH)}random.c
+random.$(OBJEXT): {$(VPATH)}random.h
+random.$(OBJEXT): {$(VPATH)}ruby_assert.h
+random.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+random.$(OBJEXT): {$(VPATH)}rubyparser.h
+random.$(OBJEXT): {$(VPATH)}shape.h
+random.$(OBJEXT): {$(VPATH)}siphash.c
+random.$(OBJEXT): {$(VPATH)}siphash.h
+random.$(OBJEXT): {$(VPATH)}st.h
+random.$(OBJEXT): {$(VPATH)}subst.h
+random.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+random.$(OBJEXT): {$(VPATH)}thread_native.h
+random.$(OBJEXT): {$(VPATH)}vm_core.h
+random.$(OBJEXT): {$(VPATH)}vm_opts.h
+range.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+range.$(OBJEXT): $(hdrdir)/ruby/version.h
+range.$(OBJEXT): $(top_srcdir)/internal/array.h
+range.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+range.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+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/imemo.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)}encindex.h
+range.$(OBJEXT): {$(VPATH)}encoding.h
+range.$(OBJEXT): {$(VPATH)}id.h
+range.$(OBJEXT): {$(VPATH)}id_table.h
+range.$(OBJEXT): {$(VPATH)}intern.h
+range.$(OBJEXT): {$(VPATH)}internal.h
+range.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/set.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/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/stdckdint.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)}shape.h
+range.$(OBJEXT): {$(VPATH)}st.h
+range.$(OBJEXT): {$(VPATH)}subst.h
+rational.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+rational.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+rational.$(OBJEXT): $(CCAN_DIR)/list/list.h
+rational.$(OBJEXT): $(CCAN_DIR)/str/str.h
+rational.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+rational.$(OBJEXT): $(top_srcdir)/internal/array.h
+rational.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+rational.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+rational.$(OBJEXT): $(top_srcdir)/internal/bits.h
+rational.$(OBJEXT): $(top_srcdir)/internal/box.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/imemo.h
+rational.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+rational.$(OBJEXT): $(top_srcdir)/internal/object.h
+rational.$(OBJEXT): $(top_srcdir)/internal/rational.h
+rational.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+rational.$(OBJEXT): $(top_srcdir)/internal/serial.h
+rational.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+rational.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+rational.$(OBJEXT): $(top_srcdir)/internal/variable.h
+rational.$(OBJEXT): $(top_srcdir)/internal/vm.h
+rational.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+rational.$(OBJEXT): {$(VPATH)}assert.h
+rational.$(OBJEXT): {$(VPATH)}atomic.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)}constant.h
+rational.$(OBJEXT): {$(VPATH)}defines.h
+rational.$(OBJEXT): {$(VPATH)}encoding.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/abi.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/packed_struct.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/encoding/coderange.h
+rational.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+rational.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+rational.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+rational.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+rational.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+rational.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+rational.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+rational.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.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/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/set.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/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/stdckdint.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)}method.h
+rational.$(OBJEXT): {$(VPATH)}missing.h
+rational.$(OBJEXT): {$(VPATH)}node.h
+rational.$(OBJEXT): {$(VPATH)}onigmo.h
+rational.$(OBJEXT): {$(VPATH)}oniguruma.h
+rational.$(OBJEXT): {$(VPATH)}rational.c
+rational.$(OBJEXT): {$(VPATH)}ruby_assert.h
+rational.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+rational.$(OBJEXT): {$(VPATH)}rubyparser.h
+rational.$(OBJEXT): {$(VPATH)}shape.h
+rational.$(OBJEXT): {$(VPATH)}st.h
+rational.$(OBJEXT): {$(VPATH)}subst.h
+rational.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+rational.$(OBJEXT): {$(VPATH)}thread_native.h
+rational.$(OBJEXT): {$(VPATH)}vm_core.h
+rational.$(OBJEXT): {$(VPATH)}vm_opts.h
+re.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+re.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+re.$(OBJEXT): $(CCAN_DIR)/list/list.h
+re.$(OBJEXT): $(CCAN_DIR)/str/str.h
+re.$(OBJEXT): $(hdrdir)/ruby.h
+re.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+re.$(OBJEXT): $(top_srcdir)/internal/array.h
+re.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+re.$(OBJEXT): $(top_srcdir)/internal/bits.h
+re.$(OBJEXT): $(top_srcdir)/internal/box.h
+re.$(OBJEXT): $(top_srcdir)/internal/class.h
+re.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+re.$(OBJEXT): $(top_srcdir)/internal/encoding.h
+re.$(OBJEXT): $(top_srcdir)/internal/error.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/object.h
+re.$(OBJEXT): $(top_srcdir)/internal/ractor.h
+re.$(OBJEXT): $(top_srcdir)/internal/re.h
+re.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+re.$(OBJEXT): $(top_srcdir)/internal/serial.h
+re.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+re.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+re.$(OBJEXT): $(top_srcdir)/internal/string.h
+re.$(OBJEXT): $(top_srcdir)/internal/struct.h
+re.$(OBJEXT): $(top_srcdir)/internal/time.h
+re.$(OBJEXT): $(top_srcdir)/internal/variable.h
+re.$(OBJEXT): $(top_srcdir)/internal/vm.h
+re.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+re.$(OBJEXT): {$(VPATH)}assert.h
+re.$(OBJEXT): {$(VPATH)}atomic.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)}hrtime.h
+re.$(OBJEXT): {$(VPATH)}id.h
+re.$(OBJEXT): {$(VPATH)}id_table.h
+re.$(OBJEXT): {$(VPATH)}intern.h
+re.$(OBJEXT): {$(VPATH)}internal.h
+re.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/set.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/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/stdckdint.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)}method.h
+re.$(OBJEXT): {$(VPATH)}missing.h
+re.$(OBJEXT): {$(VPATH)}node.h
+re.$(OBJEXT): {$(VPATH)}onigmo.h
+re.$(OBJEXT): {$(VPATH)}oniguruma.h
+re.$(OBJEXT): {$(VPATH)}ractor.h
+re.$(OBJEXT): {$(VPATH)}ractor_core.h
+re.$(OBJEXT): {$(VPATH)}re.c
+re.$(OBJEXT): {$(VPATH)}re.h
+re.$(OBJEXT): {$(VPATH)}regenc.h
+re.$(OBJEXT): {$(VPATH)}regex.h
+re.$(OBJEXT): {$(VPATH)}regint.h
+re.$(OBJEXT): {$(VPATH)}ruby_assert.h
+re.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+re.$(OBJEXT): {$(VPATH)}rubyparser.h
+re.$(OBJEXT): {$(VPATH)}shape.h
+re.$(OBJEXT): {$(VPATH)}st.h
+re.$(OBJEXT): {$(VPATH)}subst.h
+re.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+re.$(OBJEXT): {$(VPATH)}thread_native.h
+re.$(OBJEXT): {$(VPATH)}util.h
+re.$(OBJEXT): {$(VPATH)}vm_core.h
+re.$(OBJEXT): {$(VPATH)}vm_debug.h
+re.$(OBJEXT): {$(VPATH)}vm_opts.h
+regcomp.$(OBJEXT): $(hdrdir)/ruby.h
+regcomp.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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
+regcomp.$(OBJEXT): {$(VPATH)}regenc.h
+regcomp.$(OBJEXT): {$(VPATH)}regint.h
+regcomp.$(OBJEXT): {$(VPATH)}regparse.h
+regcomp.$(OBJEXT): {$(VPATH)}st.h
+regcomp.$(OBJEXT): {$(VPATH)}subst.h
+regenc.$(OBJEXT): $(hdrdir)/ruby.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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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
+regenc.$(OBJEXT): {$(VPATH)}regenc.h
+regenc.$(OBJEXT): {$(VPATH)}regint.h
+regenc.$(OBJEXT): {$(VPATH)}st.h
+regenc.$(OBJEXT): {$(VPATH)}subst.h
+regerror.$(OBJEXT): $(hdrdir)/ruby.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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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
+regerror.$(OBJEXT): {$(VPATH)}regerror.c
+regerror.$(OBJEXT): {$(VPATH)}regint.h
+regerror.$(OBJEXT): {$(VPATH)}st.h
+regerror.$(OBJEXT): {$(VPATH)}subst.h
+regexec.$(OBJEXT): $(hdrdir)/ruby.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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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
+regexec.$(OBJEXT): {$(VPATH)}regexec.c
+regexec.$(OBJEXT): {$(VPATH)}regint.h
+regexec.$(OBJEXT): {$(VPATH)}st.h
+regexec.$(OBJEXT): {$(VPATH)}subst.h
+regparse.$(OBJEXT): $(hdrdir)/ruby.h
+regparse.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+regparse.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+regparse.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+regparse.$(OBJEXT): $(top_srcdir)/internal/warnings.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/gcc_version_since.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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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
+regparse.$(OBJEXT): {$(VPATH)}regint.h
+regparse.$(OBJEXT): {$(VPATH)}regparse.c
+regparse.$(OBJEXT): {$(VPATH)}regparse.h
+regparse.$(OBJEXT): {$(VPATH)}st.h
+regparse.$(OBJEXT): {$(VPATH)}subst.h
+regsyntax.$(OBJEXT): $(hdrdir)/ruby.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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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
+regsyntax.$(OBJEXT): {$(VPATH)}regint.h
+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
+ruby.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+ruby.$(OBJEXT): $(CCAN_DIR)/list/list.h
+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/basic_operators.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/bits.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/box.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/class.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/cmdlineopt.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/complex.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/cont.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/error.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/file.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/gc.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/inits.h
+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/numeric.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/object.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/parse.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/rational.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/serial.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/string.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/struct.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/thread.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/variable.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/vm.h
+ruby.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/ast.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/defines.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/node.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/options.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/pack.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/parser.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/prism.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+ruby.$(OBJEXT): $(top_srcdir)/prism/version.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)}debug_counter.h
+ruby.$(OBJEXT): {$(VPATH)}defines.h
+ruby.$(OBJEXT): {$(VPATH)}dln.h
+ruby.$(OBJEXT): {$(VPATH)}encindex.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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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)}iseq.h
+ruby.$(OBJEXT): {$(VPATH)}method.h
+ruby.$(OBJEXT): {$(VPATH)}missing.h
+ruby.$(OBJEXT): {$(VPATH)}node.h
+ruby.$(OBJEXT): {$(VPATH)}onigmo.h
+ruby.$(OBJEXT): {$(VPATH)}oniguruma.h
+ruby.$(OBJEXT): {$(VPATH)}prism_compile.h
+ruby.$(OBJEXT): {$(VPATH)}ruby.c
+ruby.$(OBJEXT): {$(VPATH)}ruby_assert.h
+ruby.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+ruby.$(OBJEXT): {$(VPATH)}rubyparser.h
+ruby.$(OBJEXT): {$(VPATH)}shape.h
+ruby.$(OBJEXT): {$(VPATH)}st.h
+ruby.$(OBJEXT): {$(VPATH)}subst.h
+ruby.$(OBJEXT): {$(VPATH)}thread.h
+ruby.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+ruby.$(OBJEXT): {$(VPATH)}thread_native.h
+ruby.$(OBJEXT): {$(VPATH)}util.h
+ruby.$(OBJEXT): {$(VPATH)}vm_core.h
+ruby.$(OBJEXT): {$(VPATH)}vm_opts.h
+ruby.$(OBJEXT): {$(VPATH)}yjit.h
+ruby_parser.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/array.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/bits.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/complex.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/error.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/parse.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/rational.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/re.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/serial.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/string.h
+ruby_parser.$(OBJEXT): $(top_srcdir)/internal/vm.h
+ruby_parser.$(OBJEXT): {$(VPATH)}assert.h
+ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+ruby_parser.$(OBJEXT): {$(VPATH)}config.h
+ruby_parser.$(OBJEXT): {$(VPATH)}defines.h
+ruby_parser.$(OBJEXT): {$(VPATH)}encindex.h
+ruby_parser.$(OBJEXT): {$(VPATH)}encoding.h
+ruby_parser.$(OBJEXT): {$(VPATH)}intern.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/abi.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/assume.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/cast.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/config.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/ctype.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/dosish.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/error.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/eval.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/event.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/gc.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/glob.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/globals.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/set.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/iterator.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/memory.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/method.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/module.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/newobj.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/symbol.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/value.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/value_type.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/variable.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+ruby_parser.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+ruby_parser.$(OBJEXT): {$(VPATH)}missing.h
+ruby_parser.$(OBJEXT): {$(VPATH)}node.h
+ruby_parser.$(OBJEXT): {$(VPATH)}onigmo.h
+ruby_parser.$(OBJEXT): {$(VPATH)}oniguruma.h
+ruby_parser.$(OBJEXT): {$(VPATH)}ruby_assert.h
+ruby_parser.$(OBJEXT): {$(VPATH)}ruby_parser.c
+ruby_parser.$(OBJEXT): {$(VPATH)}rubyparser.h
+ruby_parser.$(OBJEXT): {$(VPATH)}st.h
+ruby_parser.$(OBJEXT): {$(VPATH)}subst.h
+scheduler.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+scheduler.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+scheduler.$(OBJEXT): $(CCAN_DIR)/list/list.h
+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/basic_operators.h
+scheduler.$(OBJEXT): $(top_srcdir)/internal/box.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/sanitizers.h
+scheduler.$(OBJEXT): $(top_srcdir)/internal/serial.h
+scheduler.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+scheduler.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+scheduler.$(OBJEXT): $(top_srcdir)/internal/thread.h
+scheduler.$(OBJEXT): $(top_srcdir)/internal/variable.h
+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)}constant.h
+scheduler.$(OBJEXT): {$(VPATH)}defines.h
+scheduler.$(OBJEXT): {$(VPATH)}encoding.h
+scheduler.$(OBJEXT): {$(VPATH)}eval_intern.h
+scheduler.$(OBJEXT): {$(VPATH)}fiber/scheduler.h
+scheduler.$(OBJEXT): {$(VPATH)}id.h
+scheduler.$(OBJEXT): {$(VPATH)}id_table.h
+scheduler.$(OBJEXT): {$(VPATH)}intern.h
+scheduler.$(OBJEXT): {$(VPATH)}internal.h
+scheduler.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/set.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/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/stdckdint.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)}rubyparser.h
+scheduler.$(OBJEXT): {$(VPATH)}scheduler.c
+scheduler.$(OBJEXT): {$(VPATH)}shape.h
+scheduler.$(OBJEXT): {$(VPATH)}st.h
+scheduler.$(OBJEXT): {$(VPATH)}subst.h
+scheduler.$(OBJEXT): {$(VPATH)}thread.h
+scheduler.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+scheduler.$(OBJEXT): {$(VPATH)}thread_native.h
+scheduler.$(OBJEXT): {$(VPATH)}vm_core.h
+scheduler.$(OBJEXT): {$(VPATH)}vm_opts.h
+set.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+set.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+set.$(OBJEXT): $(CCAN_DIR)/list/list.h
+set.$(OBJEXT): $(CCAN_DIR)/str/str.h
+set.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+set.$(OBJEXT): $(top_srcdir)/internal/array.h
+set.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+set.$(OBJEXT): $(top_srcdir)/internal/bits.h
+set.$(OBJEXT): $(top_srcdir)/internal/box.h
+set.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+set.$(OBJEXT): $(top_srcdir)/internal/error.h
+set.$(OBJEXT): $(top_srcdir)/internal/gc.h
+set.$(OBJEXT): $(top_srcdir)/internal/hash.h
+set.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+set.$(OBJEXT): $(top_srcdir)/internal/proc.h
+set.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+set.$(OBJEXT): $(top_srcdir)/internal/serial.h
+set.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+set.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+set.$(OBJEXT): $(top_srcdir)/internal/string.h
+set.$(OBJEXT): $(top_srcdir)/internal/struct.h
+set.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+set.$(OBJEXT): $(top_srcdir)/internal/variable.h
+set.$(OBJEXT): $(top_srcdir)/internal/vm.h
+set.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+set.$(OBJEXT): {$(VPATH)}assert.h
+set.$(OBJEXT): {$(VPATH)}atomic.h
+set.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+set.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+set.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+set.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+set.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+set.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+set.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+set.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+set.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+set.$(OBJEXT): {$(VPATH)}config.h
+set.$(OBJEXT): {$(VPATH)}constant.h
+set.$(OBJEXT): {$(VPATH)}defines.h
+set.$(OBJEXT): {$(VPATH)}encindex.h
+set.$(OBJEXT): {$(VPATH)}encoding.h
+set.$(OBJEXT): {$(VPATH)}id.h
+set.$(OBJEXT): {$(VPATH)}id_table.h
+set.$(OBJEXT): {$(VPATH)}intern.h
+set.$(OBJEXT): {$(VPATH)}internal.h
+set.$(OBJEXT): {$(VPATH)}internal/abi.h
+set.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+set.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+set.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+set.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+set.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+set.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+set.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+set.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+set.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+set.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+set.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+set.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+set.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+set.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+set.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+set.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+set.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+set.$(OBJEXT): {$(VPATH)}internal/assume.h
+set.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+set.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+set.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+set.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+set.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+set.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+set.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+set.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+set.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+set.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+set.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+set.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+set.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+set.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+set.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+set.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+set.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+set.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+set.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+set.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
+set.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+set.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+set.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+set.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+set.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+set.$(OBJEXT): {$(VPATH)}internal/cast.h
+set.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+set.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+set.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+set.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+set.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+set.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+set.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+set.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+set.$(OBJEXT): {$(VPATH)}internal/config.h
+set.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+set.$(OBJEXT): {$(VPATH)}internal/core.h
+set.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+set.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+set.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+set.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+set.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+set.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+set.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+set.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+set.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+set.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+set.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+set.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+set.$(OBJEXT): {$(VPATH)}internal/ctype.h
+set.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+set.$(OBJEXT): {$(VPATH)}internal/dosish.h
+set.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+set.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+set.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+set.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+set.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+set.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+set.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+set.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+set.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
+set.$(OBJEXT): {$(VPATH)}internal/error.h
+set.$(OBJEXT): {$(VPATH)}internal/eval.h
+set.$(OBJEXT): {$(VPATH)}internal/event.h
+set.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+set.$(OBJEXT): {$(VPATH)}internal/gc.h
+set.$(OBJEXT): {$(VPATH)}internal/glob.h
+set.$(OBJEXT): {$(VPATH)}internal/globals.h
+set.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+set.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+set.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+set.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+set.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+set.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+set.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+set.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/set.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+set.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+set.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+set.$(OBJEXT): {$(VPATH)}internal/iterator.h
+set.$(OBJEXT): {$(VPATH)}internal/memory.h
+set.$(OBJEXT): {$(VPATH)}internal/method.h
+set.$(OBJEXT): {$(VPATH)}internal/module.h
+set.$(OBJEXT): {$(VPATH)}internal/newobj.h
+set.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+set.$(OBJEXT): {$(VPATH)}internal/set_table.h
+set.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+set.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+set.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+set.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+set.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
+set.$(OBJEXT): {$(VPATH)}internal/symbol.h
+set.$(OBJEXT): {$(VPATH)}internal/value.h
+set.$(OBJEXT): {$(VPATH)}internal/value_type.h
+set.$(OBJEXT): {$(VPATH)}internal/variable.h
+set.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+set.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+set.$(OBJEXT): {$(VPATH)}method.h
+set.$(OBJEXT): {$(VPATH)}missing.h
+set.$(OBJEXT): {$(VPATH)}node.h
+set.$(OBJEXT): {$(VPATH)}onigmo.h
+set.$(OBJEXT): {$(VPATH)}oniguruma.h
+set.$(OBJEXT): {$(VPATH)}ruby_assert.h
+set.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+set.$(OBJEXT): {$(VPATH)}rubyparser.h
+set.$(OBJEXT): {$(VPATH)}set.c
+set.$(OBJEXT): {$(VPATH)}shape.h
+set.$(OBJEXT): {$(VPATH)}st.h
+set.$(OBJEXT): {$(VPATH)}subst.h
+set.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+set.$(OBJEXT): {$(VPATH)}thread_native.h
+set.$(OBJEXT): {$(VPATH)}vm_core.h
+set.$(OBJEXT): {$(VPATH)}vm_opts.h
+setproctitle.$(OBJEXT): $(hdrdir)/ruby.h
+setproctitle.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+setproctitle.$(OBJEXT): {$(VPATH)}assert.h
+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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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
+setproctitle.$(OBJEXT): {$(VPATH)}subst.h
+setproctitle.$(OBJEXT): {$(VPATH)}util.h
+shape.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+shape.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+shape.$(OBJEXT): $(CCAN_DIR)/list/list.h
+shape.$(OBJEXT): $(CCAN_DIR)/str/str.h
+shape.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+shape.$(OBJEXT): $(hdrdir)/ruby/version.h
+shape.$(OBJEXT): $(top_srcdir)/internal/array.h
+shape.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+shape.$(OBJEXT): $(top_srcdir)/internal/box.h
+shape.$(OBJEXT): $(top_srcdir)/internal/class.h
+shape.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+shape.$(OBJEXT): $(top_srcdir)/internal/error.h
+shape.$(OBJEXT): $(top_srcdir)/internal/gc.h
+shape.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+shape.$(OBJEXT): $(top_srcdir)/internal/object.h
+shape.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+shape.$(OBJEXT): $(top_srcdir)/internal/serial.h
+shape.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+shape.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+shape.$(OBJEXT): $(top_srcdir)/internal/string.h
+shape.$(OBJEXT): $(top_srcdir)/internal/struct.h
+shape.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+shape.$(OBJEXT): $(top_srcdir)/internal/variable.h
+shape.$(OBJEXT): $(top_srcdir)/internal/vm.h
+shape.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+shape.$(OBJEXT): {$(VPATH)}assert.h
+shape.$(OBJEXT): {$(VPATH)}atomic.h
+shape.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+shape.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+shape.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+shape.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+shape.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+shape.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+shape.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+shape.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+shape.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+shape.$(OBJEXT): {$(VPATH)}config.h
+shape.$(OBJEXT): {$(VPATH)}constant.h
+shape.$(OBJEXT): {$(VPATH)}debug_counter.h
+shape.$(OBJEXT): {$(VPATH)}defines.h
+shape.$(OBJEXT): {$(VPATH)}encindex.h
+shape.$(OBJEXT): {$(VPATH)}encoding.h
+shape.$(OBJEXT): {$(VPATH)}id.h
+shape.$(OBJEXT): {$(VPATH)}id_table.h
+shape.$(OBJEXT): {$(VPATH)}intern.h
+shape.$(OBJEXT): {$(VPATH)}internal.h
+shape.$(OBJEXT): {$(VPATH)}internal/abi.h
+shape.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+shape.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+shape.$(OBJEXT): {$(VPATH)}internal/assume.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+shape.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+shape.$(OBJEXT): {$(VPATH)}internal/cast.h
+shape.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+shape.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+shape.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+shape.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+shape.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+shape.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+shape.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+shape.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+shape.$(OBJEXT): {$(VPATH)}internal/config.h
+shape.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+shape.$(OBJEXT): {$(VPATH)}internal/core.h
+shape.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+shape.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+shape.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+shape.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+shape.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+shape.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+shape.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+shape.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+shape.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+shape.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+shape.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+shape.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+shape.$(OBJEXT): {$(VPATH)}internal/ctype.h
+shape.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+shape.$(OBJEXT): {$(VPATH)}internal/dosish.h
+shape.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+shape.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+shape.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+shape.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+shape.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+shape.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+shape.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+shape.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+shape.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
+shape.$(OBJEXT): {$(VPATH)}internal/error.h
+shape.$(OBJEXT): {$(VPATH)}internal/eval.h
+shape.$(OBJEXT): {$(VPATH)}internal/event.h
+shape.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+shape.$(OBJEXT): {$(VPATH)}internal/gc.h
+shape.$(OBJEXT): {$(VPATH)}internal/glob.h
+shape.$(OBJEXT): {$(VPATH)}internal/globals.h
+shape.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+shape.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+shape.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+shape.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+shape.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+shape.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+shape.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+shape.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/set.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+shape.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+shape.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+shape.$(OBJEXT): {$(VPATH)}internal/iterator.h
+shape.$(OBJEXT): {$(VPATH)}internal/memory.h
+shape.$(OBJEXT): {$(VPATH)}internal/method.h
+shape.$(OBJEXT): {$(VPATH)}internal/module.h
+shape.$(OBJEXT): {$(VPATH)}internal/newobj.h
+shape.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+shape.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+shape.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+shape.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+shape.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+shape.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
+shape.$(OBJEXT): {$(VPATH)}internal/symbol.h
+shape.$(OBJEXT): {$(VPATH)}internal/value.h
+shape.$(OBJEXT): {$(VPATH)}internal/value_type.h
+shape.$(OBJEXT): {$(VPATH)}internal/variable.h
+shape.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+shape.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+shape.$(OBJEXT): {$(VPATH)}method.h
+shape.$(OBJEXT): {$(VPATH)}missing.h
+shape.$(OBJEXT): {$(VPATH)}node.h
+shape.$(OBJEXT): {$(VPATH)}onigmo.h
+shape.$(OBJEXT): {$(VPATH)}oniguruma.h
+shape.$(OBJEXT): {$(VPATH)}ruby_assert.h
+shape.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+shape.$(OBJEXT): {$(VPATH)}rubyparser.h
+shape.$(OBJEXT): {$(VPATH)}shape.c
+shape.$(OBJEXT): {$(VPATH)}shape.h
+shape.$(OBJEXT): {$(VPATH)}st.h
+shape.$(OBJEXT): {$(VPATH)}subst.h
+shape.$(OBJEXT): {$(VPATH)}symbol.h
+shape.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+shape.$(OBJEXT): {$(VPATH)}thread_native.h
+shape.$(OBJEXT): {$(VPATH)}variable.h
+shape.$(OBJEXT): {$(VPATH)}vm_core.h
+shape.$(OBJEXT): {$(VPATH)}vm_debug.h
+shape.$(OBJEXT): {$(VPATH)}vm_opts.h
+shape.$(OBJEXT): {$(VPATH)}vm_sync.h
+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/ruby.h
+signal.$(OBJEXT): $(hdrdir)/ruby/version.h
+signal.$(OBJEXT): $(top_srcdir)/internal/array.h
+signal.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+signal.$(OBJEXT): $(top_srcdir)/internal/box.h
+signal.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+signal.$(OBJEXT): $(top_srcdir)/internal/error.h
+signal.$(OBJEXT): $(top_srcdir)/internal/eval.h
+signal.$(OBJEXT): $(top_srcdir)/internal/gc.h
+signal.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+signal.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+signal.$(OBJEXT): $(top_srcdir)/internal/serial.h
+signal.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+signal.$(OBJEXT): $(top_srcdir)/internal/signal.h
+signal.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+signal.$(OBJEXT): $(top_srcdir)/internal/string.h
+signal.$(OBJEXT): $(top_srcdir)/internal/thread.h
+signal.$(OBJEXT): $(top_srcdir)/internal/variable.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)}constant.h
+signal.$(OBJEXT): {$(VPATH)}debug_counter.h
+signal.$(OBJEXT): {$(VPATH)}defines.h
+signal.$(OBJEXT): {$(VPATH)}encindex.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/abi.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/nonstring.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+signal.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.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/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/set.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/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/stdckdint.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)}rubyparser.h
+signal.$(OBJEXT): {$(VPATH)}shape.h
+signal.$(OBJEXT): {$(VPATH)}signal.c
+signal.$(OBJEXT): {$(VPATH)}st.h
+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/ruby.h
+sprintf.$(OBJEXT): $(hdrdir)/ruby/version.h
+sprintf.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+sprintf.$(OBJEXT): $(top_srcdir)/internal/bits.h
+sprintf.$(OBJEXT): $(top_srcdir)/internal/class.h
+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/variable.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)}constant.h
+sprintf.$(OBJEXT): {$(VPATH)}defines.h
+sprintf.$(OBJEXT): {$(VPATH)}encindex.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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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
+sprintf.$(OBJEXT): {$(VPATH)}re.h
+sprintf.$(OBJEXT): {$(VPATH)}regex.h
+sprintf.$(OBJEXT): {$(VPATH)}shape.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/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/set_table.h
+st.$(OBJEXT): $(top_srcdir)/internal/st.h
+st.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+st.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+st.$(OBJEXT): {$(VPATH)}assert.h
+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/abi.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/packed_struct.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/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/set.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/scan_args.h
+st.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+st.$(OBJEXT): {$(VPATH)}internal/st.h
+st.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+st.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+st.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+st.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
+st.$(OBJEXT): {$(VPATH)}internal/symbol.h
+st.$(OBJEXT): {$(VPATH)}internal/value.h
+st.$(OBJEXT): {$(VPATH)}internal/value_type.h
+st.$(OBJEXT): {$(VPATH)}internal/variable.h
+st.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+st.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+st.$(OBJEXT): {$(VPATH)}missing.h
+st.$(OBJEXT): {$(VPATH)}ruby_assert.h
+st.$(OBJEXT): {$(VPATH)}st.c
+st.$(OBJEXT): {$(VPATH)}st.h
+st.$(OBJEXT): {$(VPATH)}subst.h
+strftime.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+strftime.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+strftime.$(OBJEXT): $(top_srcdir)/internal/encoding.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)}encindex.h
+strftime.$(OBJEXT): {$(VPATH)}encoding.h
+strftime.$(OBJEXT): {$(VPATH)}intern.h
+strftime.$(OBJEXT): {$(VPATH)}internal.h
+strftime.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/set.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/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/stdckdint.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
+strftime.$(OBJEXT): {$(VPATH)}st.h
+strftime.$(OBJEXT): {$(VPATH)}strftime.c
+strftime.$(OBJEXT): {$(VPATH)}subst.h
+strftime.$(OBJEXT): {$(VPATH)}timev.h
+strftime.$(OBJEXT): {$(VPATH)}util.h
+string.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+string.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+string.$(OBJEXT): $(CCAN_DIR)/list/list.h
+string.$(OBJEXT): $(CCAN_DIR)/str/str.h
+string.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+string.$(OBJEXT): $(hdrdir)/ruby/version.h
+string.$(OBJEXT): $(top_srcdir)/internal/array.h
+string.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+string.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+string.$(OBJEXT): $(top_srcdir)/internal/bits.h
+string.$(OBJEXT): $(top_srcdir)/internal/box.h
+string.$(OBJEXT): $(top_srcdir)/internal/class.h
+string.$(OBJEXT): $(top_srcdir)/internal/compar.h
+string.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+string.$(OBJEXT): $(top_srcdir)/internal/concurrent_set.h
+string.$(OBJEXT): $(top_srcdir)/internal/encoding.h
+string.$(OBJEXT): $(top_srcdir)/internal/error.h
+string.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+string.$(OBJEXT): $(top_srcdir)/internal/gc.h
+string.$(OBJEXT): $(top_srcdir)/internal/hash.h
+string.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+string.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+string.$(OBJEXT): $(top_srcdir)/internal/object.h
+string.$(OBJEXT): $(top_srcdir)/internal/proc.h
+string.$(OBJEXT): $(top_srcdir)/internal/re.h
+string.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+string.$(OBJEXT): $(top_srcdir)/internal/serial.h
+string.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+string.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+string.$(OBJEXT): $(top_srcdir)/internal/string.h
+string.$(OBJEXT): $(top_srcdir)/internal/struct.h
+string.$(OBJEXT): $(top_srcdir)/internal/transcode.h
+string.$(OBJEXT): $(top_srcdir)/internal/variable.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)}constant.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)}id.h
+string.$(OBJEXT): {$(VPATH)}id_table.h
+string.$(OBJEXT): {$(VPATH)}intern.h
+string.$(OBJEXT): {$(VPATH)}internal.h
+string.$(OBJEXT): {$(VPATH)}internal/abi.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/nonstring.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+string.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.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/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/set.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/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/stdckdint.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)}method.h
+string.$(OBJEXT): {$(VPATH)}missing.h
+string.$(OBJEXT): {$(VPATH)}node.h
+string.$(OBJEXT): {$(VPATH)}onigmo.h
+string.$(OBJEXT): {$(VPATH)}oniguruma.h
+string.$(OBJEXT): {$(VPATH)}probes.dmyh
+string.$(OBJEXT): {$(VPATH)}probes.h
+string.$(OBJEXT): {$(VPATH)}ractor.h
+string.$(OBJEXT): {$(VPATH)}re.h
+string.$(OBJEXT): {$(VPATH)}regex.h
+string.$(OBJEXT): {$(VPATH)}ruby_assert.h
+string.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+string.$(OBJEXT): {$(VPATH)}rubyparser.h
+string.$(OBJEXT): {$(VPATH)}shape.h
+string.$(OBJEXT): {$(VPATH)}st.h
+string.$(OBJEXT): {$(VPATH)}string.c
+string.$(OBJEXT): {$(VPATH)}subst.h
+string.$(OBJEXT): {$(VPATH)}thread.h
+string.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+string.$(OBJEXT): {$(VPATH)}thread_native.h
+string.$(OBJEXT): {$(VPATH)}util.h
+string.$(OBJEXT): {$(VPATH)}variable.h
+string.$(OBJEXT): {$(VPATH)}vm_core.h
+string.$(OBJEXT): {$(VPATH)}vm_debug.h
+string.$(OBJEXT): {$(VPATH)}vm_opts.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/ruby.h
+struct.$(OBJEXT): $(hdrdir)/ruby/version.h
+struct.$(OBJEXT): $(top_srcdir)/internal/array.h
+struct.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+struct.$(OBJEXT): $(top_srcdir)/internal/box.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/sanitizers.h
+struct.$(OBJEXT): $(top_srcdir)/internal/serial.h
+struct.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+struct.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+struct.$(OBJEXT): $(top_srcdir)/internal/string.h
+struct.$(OBJEXT): $(top_srcdir)/internal/struct.h
+struct.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+struct.$(OBJEXT): $(top_srcdir)/internal/variable.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)}constant.h
+struct.$(OBJEXT): {$(VPATH)}debug_counter.h
+struct.$(OBJEXT): {$(VPATH)}defines.h
+struct.$(OBJEXT): {$(VPATH)}encindex.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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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)}rubyparser.h
+struct.$(OBJEXT): {$(VPATH)}shape.h
+struct.$(OBJEXT): {$(VPATH)}st.h
+struct.$(OBJEXT): {$(VPATH)}struct.c
+struct.$(OBJEXT): {$(VPATH)}subst.h
+struct.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+struct.$(OBJEXT): {$(VPATH)}thread_native.h
+struct.$(OBJEXT): {$(VPATH)}vm_core.h
+struct.$(OBJEXT): {$(VPATH)}vm_debug.h
+struct.$(OBJEXT): {$(VPATH)}vm_opts.h
+struct.$(OBJEXT): {$(VPATH)}vm_sync.h
+symbol.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+symbol.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+symbol.$(OBJEXT): $(CCAN_DIR)/list/list.h
+symbol.$(OBJEXT): $(CCAN_DIR)/str/str.h
+symbol.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+symbol.$(OBJEXT): $(hdrdir)/ruby/version.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/array.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/box.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/class.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/concurrent_set.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/imemo.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/object.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/serial.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/string.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/variable.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/vm.h
+symbol.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+symbol.$(OBJEXT): {$(VPATH)}assert.h
+symbol.$(OBJEXT): {$(VPATH)}atomic.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)}builtin.h
+symbol.$(OBJEXT): {$(VPATH)}config.h
+symbol.$(OBJEXT): {$(VPATH)}constant.h
+symbol.$(OBJEXT): {$(VPATH)}darray.h
+symbol.$(OBJEXT): {$(VPATH)}debug_counter.h
+symbol.$(OBJEXT): {$(VPATH)}defines.h
+symbol.$(OBJEXT): {$(VPATH)}encindex.h
+symbol.$(OBJEXT): {$(VPATH)}encoding.h
+symbol.$(OBJEXT): {$(VPATH)}id.c
+symbol.$(OBJEXT): {$(VPATH)}id.h
+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/abi.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/nonstring.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+symbol.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.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/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/set.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/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/stdckdint.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)}method.h
+symbol.$(OBJEXT): {$(VPATH)}missing.h
+symbol.$(OBJEXT): {$(VPATH)}node.h
+symbol.$(OBJEXT): {$(VPATH)}onigmo.h
+symbol.$(OBJEXT): {$(VPATH)}oniguruma.h
+symbol.$(OBJEXT): {$(VPATH)}probes.dmyh
+symbol.$(OBJEXT): {$(VPATH)}probes.h
+symbol.$(OBJEXT): {$(VPATH)}ractor.h
+symbol.$(OBJEXT): {$(VPATH)}ruby_assert.h
+symbol.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+symbol.$(OBJEXT): {$(VPATH)}rubyparser.h
+symbol.$(OBJEXT): {$(VPATH)}shape.h
+symbol.$(OBJEXT): {$(VPATH)}st.h
+symbol.$(OBJEXT): {$(VPATH)}subst.h
+symbol.$(OBJEXT): {$(VPATH)}symbol.c
+symbol.$(OBJEXT): {$(VPATH)}symbol.h
+symbol.$(OBJEXT): {$(VPATH)}symbol.rb
+symbol.$(OBJEXT): {$(VPATH)}symbol.rbinc
+symbol.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+symbol.$(OBJEXT): {$(VPATH)}thread_native.h
+symbol.$(OBJEXT): {$(VPATH)}vm_core.h
+symbol.$(OBJEXT): {$(VPATH)}vm_debug.h
+symbol.$(OBJEXT): {$(VPATH)}vm_opts.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): $(hdrdir)/ruby/version.h
+thread.$(OBJEXT): $(top_srcdir)/internal/array.h
+thread.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+thread.$(OBJEXT): $(top_srcdir)/internal/bits.h
+thread.$(OBJEXT): $(top_srcdir)/internal/box.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/eval.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/sanitizers.h
+thread.$(OBJEXT): $(top_srcdir)/internal/serial.h
+thread.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+thread.$(OBJEXT): $(top_srcdir)/internal/signal.h
+thread.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+thread.$(OBJEXT): $(top_srcdir)/internal/string.h
+thread.$(OBJEXT): $(top_srcdir)/internal/struct.h
+thread.$(OBJEXT): $(top_srcdir)/internal/thread.h
+thread.$(OBJEXT): $(top_srcdir)/internal/time.h
+thread.$(OBJEXT): $(top_srcdir)/internal/variable.h
+thread.$(OBJEXT): $(top_srcdir)/internal/vm.h
+thread.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+thread.$(OBJEXT): $(top_srcdir)/prism/ast.h
+thread.$(OBJEXT): $(top_srcdir)/prism/defines.h
+thread.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+thread.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+thread.$(OBJEXT): $(top_srcdir)/prism/node.h
+thread.$(OBJEXT): $(top_srcdir)/prism/options.h
+thread.$(OBJEXT): $(top_srcdir)/prism/pack.h
+thread.$(OBJEXT): $(top_srcdir)/prism/parser.h
+thread.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+thread.$(OBJEXT): $(top_srcdir)/prism/prism.h
+thread.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+thread.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+thread.$(OBJEXT): $(top_srcdir)/prism/version.h
+thread.$(OBJEXT): {$(VPATH)}$(COROUTINE_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)}builtin.h
+thread.$(OBJEXT): {$(VPATH)}config.h
+thread.$(OBJEXT): {$(VPATH)}constant.h
+thread.$(OBJEXT): {$(VPATH)}debug.h
+thread.$(OBJEXT): {$(VPATH)}debug_counter.h
+thread.$(OBJEXT): {$(VPATH)}defines.h
+thread.$(OBJEXT): {$(VPATH)}encindex.h
+thread.$(OBJEXT): {$(VPATH)}encoding.h
+thread.$(OBJEXT): {$(VPATH)}eval_intern.h
+thread.$(OBJEXT): {$(VPATH)}fiber/scheduler.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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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
+thread.$(OBJEXT): {$(VPATH)}missing.h
+thread.$(OBJEXT): {$(VPATH)}node.h
+thread.$(OBJEXT): {$(VPATH)}onigmo.h
+thread.$(OBJEXT): {$(VPATH)}oniguruma.h
+thread.$(OBJEXT): {$(VPATH)}prism_compile.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)}rubyparser.h
+thread.$(OBJEXT): {$(VPATH)}shape.h
+thread.$(OBJEXT): {$(VPATH)}st.h
+thread.$(OBJEXT): {$(VPATH)}subst.h
+thread.$(OBJEXT): {$(VPATH)}thread.c
+thread.$(OBJEXT): {$(VPATH)}thread.h
+thread.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).c
+thread.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+thread.$(OBJEXT): {$(VPATH)}thread_native.h
+thread.$(OBJEXT): {$(VPATH)}thread_pthread_mn.c
+thread.$(OBJEXT): {$(VPATH)}thread_sync.c
+thread.$(OBJEXT): {$(VPATH)}thread_sync.rbinc
+thread.$(OBJEXT): {$(VPATH)}timev.h
+thread.$(OBJEXT): {$(VPATH)}vm_core.h
+thread.$(OBJEXT): {$(VPATH)}vm_debug.h
+thread.$(OBJEXT): {$(VPATH)}vm_opts.h
+thread.$(OBJEXT): {$(VPATH)}vm_sync.h
+time.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+time.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+time.$(OBJEXT): $(CCAN_DIR)/list/list.h
+time.$(OBJEXT): $(CCAN_DIR)/str/str.h
+time.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+time.$(OBJEXT): $(top_srcdir)/internal/array.h
+time.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+time.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+time.$(OBJEXT): $(top_srcdir)/internal/bits.h
+time.$(OBJEXT): $(top_srcdir)/internal/box.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/hash.h
+time.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+time.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+time.$(OBJEXT): $(top_srcdir)/internal/rational.h
+time.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+time.$(OBJEXT): $(top_srcdir)/internal/serial.h
+time.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+time.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+time.$(OBJEXT): $(top_srcdir)/internal/string.h
+time.$(OBJEXT): $(top_srcdir)/internal/struct.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)}atomic.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)}encindex.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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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)}method.h
+time.$(OBJEXT): {$(VPATH)}missing.h
+time.$(OBJEXT): {$(VPATH)}node.h
+time.$(OBJEXT): {$(VPATH)}onigmo.h
+time.$(OBJEXT): {$(VPATH)}oniguruma.h
+time.$(OBJEXT): {$(VPATH)}ruby_assert.h
+time.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+time.$(OBJEXT): {$(VPATH)}rubyparser.h
+time.$(OBJEXT): {$(VPATH)}shape.h
+time.$(OBJEXT): {$(VPATH)}st.h
+time.$(OBJEXT): {$(VPATH)}subst.h
+time.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+time.$(OBJEXT): {$(VPATH)}thread_native.h
+time.$(OBJEXT): {$(VPATH)}time.c
+time.$(OBJEXT): {$(VPATH)}timev.h
+time.$(OBJEXT): {$(VPATH)}timev.rbinc
+time.$(OBJEXT): {$(VPATH)}util.h
+time.$(OBJEXT): {$(VPATH)}vm_core.h
+time.$(OBJEXT): {$(VPATH)}vm_opts.h
+transcode.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+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/encoding.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/variable.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)}constant.h
+transcode.$(OBJEXT): {$(VPATH)}debug_counter.h
+transcode.$(OBJEXT): {$(VPATH)}defines.h
+transcode.$(OBJEXT): {$(VPATH)}encindex.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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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
+transcode.$(OBJEXT): {$(VPATH)}shape.h
+transcode.$(OBJEXT): {$(VPATH)}st.h
+transcode.$(OBJEXT): {$(VPATH)}subst.h
+transcode.$(OBJEXT): {$(VPATH)}transcode.c
+transcode.$(OBJEXT): {$(VPATH)}transcode_data.h
+transcode.$(OBJEXT): {$(VPATH)}vm_debug.h
+transcode.$(OBJEXT): {$(VPATH)}vm_sync.h
+util.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+util.$(OBJEXT): $(top_srcdir)/internal/array.h
+util.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+util.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+util.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+util.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+util.$(OBJEXT): $(top_srcdir)/internal/util.h
+util.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+util.$(OBJEXT): {$(VPATH)}assert.h
+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)}id_table.h
+util.$(OBJEXT): {$(VPATH)}intern.h
+util.$(OBJEXT): {$(VPATH)}internal.h
+util.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/set.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/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/stdckdint.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
+util.$(OBJEXT): {$(VPATH)}util.h
+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/ruby.h
+variable.$(OBJEXT): $(hdrdir)/ruby/version.h
+variable.$(OBJEXT): $(top_srcdir)/internal/array.h
+variable.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+variable.$(OBJEXT): $(top_srcdir)/internal/box.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/sanitizers.h
+variable.$(OBJEXT): $(top_srcdir)/internal/serial.h
+variable.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+variable.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+variable.$(OBJEXT): $(top_srcdir)/internal/string.h
+variable.$(OBJEXT): $(top_srcdir)/internal/struct.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)}debug_counter.h
+variable.$(OBJEXT): {$(VPATH)}defines.h
+variable.$(OBJEXT): {$(VPATH)}encindex.h
+variable.$(OBJEXT): {$(VPATH)}encoding.h
+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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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)}rubyparser.h
+variable.$(OBJEXT): {$(VPATH)}shape.h
+variable.$(OBJEXT): {$(VPATH)}st.h
+variable.$(OBJEXT): {$(VPATH)}subst.h
+variable.$(OBJEXT): {$(VPATH)}symbol.h
+variable.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+variable.$(OBJEXT): {$(VPATH)}thread_native.h
+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
+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/basic_operators.h
+version.$(OBJEXT): $(top_srcdir)/internal/box.h
+version.$(OBJEXT): $(top_srcdir)/internal/cmdlineopt.h
+version.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+version.$(OBJEXT): $(top_srcdir)/internal/gc.h
+version.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+version.$(OBJEXT): $(top_srcdir)/internal/parse.h
+version.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+version.$(OBJEXT): $(top_srcdir)/internal/serial.h
+version.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+version.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+version.$(OBJEXT): $(top_srcdir)/internal/variable.h
+version.$(OBJEXT): $(top_srcdir)/internal/vm.h
+version.$(OBJEXT): $(top_srcdir)/internal/warnings.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)}constant.h
+version.$(OBJEXT): {$(VPATH)}debug_counter.h
+version.$(OBJEXT): {$(VPATH)}defines.h
+version.$(OBJEXT): {$(VPATH)}encoding.h
+version.$(OBJEXT): {$(VPATH)}id.h
+version.$(OBJEXT): {$(VPATH)}id_table.h
+version.$(OBJEXT): {$(VPATH)}intern.h
+version.$(OBJEXT): {$(VPATH)}internal.h
+version.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/encoding/coderange.h
+version.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+version.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+version.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+version.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+version.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+version.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+version.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+version.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.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/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/set.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/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/stdckdint.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)}node.h
+version.$(OBJEXT): {$(VPATH)}onigmo.h
+version.$(OBJEXT): {$(VPATH)}oniguruma.h
+version.$(OBJEXT): {$(VPATH)}revision.h
+version.$(OBJEXT): {$(VPATH)}ruby_assert.h
+version.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+version.$(OBJEXT): {$(VPATH)}rubyparser.h
+version.$(OBJEXT): {$(VPATH)}shape.h
+version.$(OBJEXT): {$(VPATH)}st.h
+version.$(OBJEXT): {$(VPATH)}subst.h
+version.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+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): $(hdrdir)/ruby/version.h
+vm.$(OBJEXT): $(top_srcdir)/internal/array.h
+vm.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+vm.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+vm.$(OBJEXT): $(top_srcdir)/internal/bits.h
+vm.$(OBJEXT): $(top_srcdir)/internal/box.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/complex.h
+vm.$(OBJEXT): $(top_srcdir)/internal/cont.h
+vm.$(OBJEXT): $(top_srcdir)/internal/encoding.h
+vm.$(OBJEXT): $(top_srcdir)/internal/error.h
+vm.$(OBJEXT): $(top_srcdir)/internal/eval.h
+vm.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+vm.$(OBJEXT): $(top_srcdir)/internal/gc.h
+vm.$(OBJEXT): $(top_srcdir)/internal/hash.h
+vm.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+vm.$(OBJEXT): $(top_srcdir)/internal/inits.h
+vm.$(OBJEXT): $(top_srcdir)/internal/missing.h
+vm.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+vm.$(OBJEXT): $(top_srcdir)/internal/object.h
+vm.$(OBJEXT): $(top_srcdir)/internal/parse.h
+vm.$(OBJEXT): $(top_srcdir)/internal/proc.h
+vm.$(OBJEXT): $(top_srcdir)/internal/random.h
+vm.$(OBJEXT): $(top_srcdir)/internal/rational.h
+vm.$(OBJEXT): $(top_srcdir)/internal/re.h
+vm.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h
+vm.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+vm.$(OBJEXT): $(top_srcdir)/internal/serial.h
+vm.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+vm.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+vm.$(OBJEXT): $(top_srcdir)/internal/string.h
+vm.$(OBJEXT): $(top_srcdir)/internal/struct.h
+vm.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+vm.$(OBJEXT): $(top_srcdir)/internal/thread.h
+vm.$(OBJEXT): $(top_srcdir)/internal/transcode.h
+vm.$(OBJEXT): $(top_srcdir)/internal/variable.h
+vm.$(OBJEXT): $(top_srcdir)/internal/vm.h
+vm.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+vm.$(OBJEXT): $(top_srcdir)/prism/ast.h
+vm.$(OBJEXT): $(top_srcdir)/prism/defines.h
+vm.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+vm.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+vm.$(OBJEXT): $(top_srcdir)/prism/node.h
+vm.$(OBJEXT): $(top_srcdir)/prism/options.h
+vm.$(OBJEXT): $(top_srcdir)/prism/pack.h
+vm.$(OBJEXT): $(top_srcdir)/prism/parser.h
+vm.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+vm.$(OBJEXT): $(top_srcdir)/prism/prism.h
+vm.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+vm.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+vm.$(OBJEXT): $(top_srcdir)/prism/version.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)}debug_counter.h
+vm.$(OBJEXT): {$(VPATH)}defines.h
+vm.$(OBJEXT): {$(VPATH)}defs/opt_operand.def
+vm.$(OBJEXT): {$(VPATH)}encindex.h
+vm.$(OBJEXT): {$(VPATH)}encoding.h
+vm.$(OBJEXT): {$(VPATH)}eval_intern.h
+vm.$(OBJEXT): {$(VPATH)}id.h
+vm.$(OBJEXT): {$(VPATH)}id_table.h
+vm.$(OBJEXT): {$(VPATH)}insns.def
+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/abi.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/packed_struct.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/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/set.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/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/stdckdint.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)}jit_hook.rbinc
+vm.$(OBJEXT): {$(VPATH)}jit_undef.rbinc
+vm.$(OBJEXT): {$(VPATH)}method.h
+vm.$(OBJEXT): {$(VPATH)}missing.h
+vm.$(OBJEXT): {$(VPATH)}node.h
+vm.$(OBJEXT): {$(VPATH)}onigmo.h
+vm.$(OBJEXT): {$(VPATH)}oniguruma.h
+vm.$(OBJEXT): {$(VPATH)}prism_compile.h
+vm.$(OBJEXT): {$(VPATH)}probes.dmyh
+vm.$(OBJEXT): {$(VPATH)}probes.h
+vm.$(OBJEXT): {$(VPATH)}probes_helper.h
+vm.$(OBJEXT): {$(VPATH)}ractor.h
+vm.$(OBJEXT): {$(VPATH)}ractor_core.h
+vm.$(OBJEXT): {$(VPATH)}ruby_assert.h
+vm.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+vm.$(OBJEXT): {$(VPATH)}rubyparser.h
+vm.$(OBJEXT): {$(VPATH)}shape.h
+vm.$(OBJEXT): {$(VPATH)}st.h
+vm.$(OBJEXT): {$(VPATH)}subst.h
+vm.$(OBJEXT): {$(VPATH)}symbol.h
+vm.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+vm.$(OBJEXT): {$(VPATH)}thread_native.h
+vm.$(OBJEXT): {$(VPATH)}variable.h
+vm.$(OBJEXT): {$(VPATH)}vm.c
+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
+vm.$(OBJEXT): {$(VPATH)}vm_exec.c
+vm.$(OBJEXT): {$(VPATH)}vm_exec.h
+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.$(OBJEXT): {$(VPATH)}zjit.h
+vm_backtrace.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+vm_backtrace.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+vm_backtrace.$(OBJEXT): $(CCAN_DIR)/list/list.h
+vm_backtrace.$(OBJEXT): $(CCAN_DIR)/str/str.h
+vm_backtrace.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+vm_backtrace.$(OBJEXT): $(hdrdir)/ruby/version.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/array.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/box.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/class.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/sanitizers.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/serial.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/string.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/struct.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/variable.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/vm.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/ast.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/defines.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/node.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/options.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/pack.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/parser.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/prism.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/version.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)}constant.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}debug.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}debug_counter.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}defines.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}encindex.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}encoding.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}eval_intern.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}id.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}id_table.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}intern.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/set.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+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/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/stdckdint.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
+vm_backtrace.$(OBJEXT): {$(VPATH)}node.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}onigmo.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}oniguruma.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}prism_compile.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}ruby_assert.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}rubyparser.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}shape.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}st.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}subst.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+vm_backtrace.$(OBJEXT): {$(VPATH)}thread_native.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}vm_backtrace.c
+vm_backtrace.$(OBJEXT): {$(VPATH)}vm_core.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}vm_debug.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}vm_opts.h
+vm_backtrace.$(OBJEXT): {$(VPATH)}vm_sync.h
+vm_dump.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+vm_dump.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+vm_dump.$(OBJEXT): $(CCAN_DIR)/list/list.h
+vm_dump.$(OBJEXT): $(CCAN_DIR)/str/str.h
+vm_dump.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+vm_dump.$(OBJEXT): $(top_srcdir)/internal/array.h
+vm_dump.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+vm_dump.$(OBJEXT): $(top_srcdir)/internal/box.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/sanitizers.h
+vm_dump.$(OBJEXT): $(top_srcdir)/internal/serial.h
+vm_dump.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+vm_dump.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+vm_dump.$(OBJEXT): $(top_srcdir)/internal/struct.h
+vm_dump.$(OBJEXT): $(top_srcdir)/internal/variable.h
+vm_dump.$(OBJEXT): $(top_srcdir)/internal/vm.h
+vm_dump.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/ast.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/defines.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/node.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/options.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/pack.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/parser.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/prism.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+vm_dump.$(OBJEXT): $(top_srcdir)/prism/version.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)}defines.h
+vm_dump.$(OBJEXT): {$(VPATH)}encoding.h
+vm_dump.$(OBJEXT): {$(VPATH)}fiber/scheduler.h
+vm_dump.$(OBJEXT): {$(VPATH)}id.h
+vm_dump.$(OBJEXT): {$(VPATH)}id_table.h
+vm_dump.$(OBJEXT): {$(VPATH)}intern.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/encoding/coderange.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.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/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/set.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+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/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/stdckdint.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)}onigmo.h
+vm_dump.$(OBJEXT): {$(VPATH)}oniguruma.h
+vm_dump.$(OBJEXT): {$(VPATH)}prism_compile.h
+vm_dump.$(OBJEXT): {$(VPATH)}procstat_vm.c
+vm_dump.$(OBJEXT): {$(VPATH)}ractor.h
+vm_dump.$(OBJEXT): {$(VPATH)}ractor_core.h
+vm_dump.$(OBJEXT): {$(VPATH)}ruby_assert.h
+vm_dump.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+vm_dump.$(OBJEXT): {$(VPATH)}rubyparser.h
+vm_dump.$(OBJEXT): {$(VPATH)}shape.h
+vm_dump.$(OBJEXT): {$(VPATH)}st.h
+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/basic_operators.h
+vm_sync.$(OBJEXT): $(top_srcdir)/internal/box.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/sanitizers.h
+vm_sync.$(OBJEXT): $(top_srcdir)/internal/serial.h
+vm_sync.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+vm_sync.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+vm_sync.$(OBJEXT): $(top_srcdir)/internal/thread.h
+vm_sync.$(OBJEXT): $(top_srcdir)/internal/variable.h
+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)}constant.h
+vm_sync.$(OBJEXT): {$(VPATH)}debug_counter.h
+vm_sync.$(OBJEXT): {$(VPATH)}defines.h
+vm_sync.$(OBJEXT): {$(VPATH)}encoding.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/abi.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/packed_struct.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/encoding/coderange.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.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/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/set.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+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/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/stdckdint.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)}onigmo.h
+vm_sync.$(OBJEXT): {$(VPATH)}oniguruma.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)}rubyparser.h
+vm_sync.$(OBJEXT): {$(VPATH)}shape.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/basic_operators.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/bits.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/box.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/class.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/gc.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/hash.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/serial.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/struct.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/symbol.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/thread.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/variable.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/vm.h
+vm_trace.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/ast.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/defines.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/node.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/options.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/pack.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/parser.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/prism.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+vm_trace.$(OBJEXT): $(top_srcdir)/prism/version.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)}constant.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)}id_table.h
+vm_trace.$(OBJEXT): {$(VPATH)}intern.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/abi.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/packed_struct.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/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/set.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+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/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/stdckdint.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)}node.h
+vm_trace.$(OBJEXT): {$(VPATH)}onigmo.h
+vm_trace.$(OBJEXT): {$(VPATH)}oniguruma.h
+vm_trace.$(OBJEXT): {$(VPATH)}prism_compile.h
+vm_trace.$(OBJEXT): {$(VPATH)}ractor.h
+vm_trace.$(OBJEXT): {$(VPATH)}ractor_core.h
+vm_trace.$(OBJEXT): {$(VPATH)}ruby_assert.h
+vm_trace.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+vm_trace.$(OBJEXT): {$(VPATH)}rubyparser.h
+vm_trace.$(OBJEXT): {$(VPATH)}shape.h
+vm_trace.$(OBJEXT): {$(VPATH)}st.h
+vm_trace.$(OBJEXT): {$(VPATH)}subst.h
+vm_trace.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+vm_trace.$(OBJEXT): {$(VPATH)}thread_native.h
+vm_trace.$(OBJEXT): {$(VPATH)}trace_point.rbinc
+vm_trace.$(OBJEXT): {$(VPATH)}vm_core.h
+vm_trace.$(OBJEXT): {$(VPATH)}vm_debug.h
+vm_trace.$(OBJEXT): {$(VPATH)}vm_opts.h
+vm_trace.$(OBJEXT): {$(VPATH)}vm_sync.h
+vm_trace.$(OBJEXT): {$(VPATH)}vm_trace.c
+vm_trace.$(OBJEXT): {$(VPATH)}yjit.h
+vm_trace.$(OBJEXT): {$(VPATH)}zjit.h
+weakmap.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+weakmap.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+weakmap.$(OBJEXT): $(CCAN_DIR)/list/list.h
+weakmap.$(OBJEXT): $(CCAN_DIR)/str/str.h
+weakmap.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+weakmap.$(OBJEXT): $(top_srcdir)/internal/array.h
+weakmap.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+weakmap.$(OBJEXT): $(top_srcdir)/internal/box.h
+weakmap.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+weakmap.$(OBJEXT): $(top_srcdir)/internal/gc.h
+weakmap.$(OBJEXT): $(top_srcdir)/internal/hash.h
+weakmap.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+weakmap.$(OBJEXT): $(top_srcdir)/internal/proc.h
+weakmap.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+weakmap.$(OBJEXT): $(top_srcdir)/internal/serial.h
+weakmap.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+weakmap.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+weakmap.$(OBJEXT): $(top_srcdir)/internal/vm.h
+weakmap.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+weakmap.$(OBJEXT): {$(VPATH)}assert.h
+weakmap.$(OBJEXT): {$(VPATH)}atomic.h
+weakmap.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+weakmap.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+weakmap.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+weakmap.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+weakmap.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+weakmap.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+weakmap.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+weakmap.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+weakmap.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+weakmap.$(OBJEXT): {$(VPATH)}config.h
+weakmap.$(OBJEXT): {$(VPATH)}defines.h
+weakmap.$(OBJEXT): {$(VPATH)}encoding.h
+weakmap.$(OBJEXT): {$(VPATH)}id.h
+weakmap.$(OBJEXT): {$(VPATH)}id_table.h
+weakmap.$(OBJEXT): {$(VPATH)}intern.h
+weakmap.$(OBJEXT): {$(VPATH)}internal.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/abi.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/assume.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/cast.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/config.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/core.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/ctype.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/dosish.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/error.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/eval.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/event.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/gc.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/glob.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/globals.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/set.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/iterator.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/memory.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/method.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/module.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/newobj.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/symbol.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/value.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/value_type.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/variable.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+weakmap.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+weakmap.$(OBJEXT): {$(VPATH)}method.h
+weakmap.$(OBJEXT): {$(VPATH)}missing.h
+weakmap.$(OBJEXT): {$(VPATH)}node.h
+weakmap.$(OBJEXT): {$(VPATH)}onigmo.h
+weakmap.$(OBJEXT): {$(VPATH)}oniguruma.h
+weakmap.$(OBJEXT): {$(VPATH)}ruby_assert.h
+weakmap.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+weakmap.$(OBJEXT): {$(VPATH)}rubyparser.h
+weakmap.$(OBJEXT): {$(VPATH)}st.h
+weakmap.$(OBJEXT): {$(VPATH)}subst.h
+weakmap.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+weakmap.$(OBJEXT): {$(VPATH)}thread_native.h
+weakmap.$(OBJEXT): {$(VPATH)}vm_core.h
+weakmap.$(OBJEXT): {$(VPATH)}vm_opts.h
+weakmap.$(OBJEXT): {$(VPATH)}weakmap.c
+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/basic_operators.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/bits.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/box.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/cont.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/gc.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/hash.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/serial.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/string.h
+yjit.$(OBJEXT): $(top_srcdir)/internal/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): $(top_srcdir)/prism/ast.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/defines.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/node.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/options.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/pack.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/parser.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/prism.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+yjit.$(OBJEXT): $(top_srcdir)/prism/version.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)}debug.h
+yjit.$(OBJEXT): {$(VPATH)}debug_counter.h
+yjit.$(OBJEXT): {$(VPATH)}defines.h
+yjit.$(OBJEXT): {$(VPATH)}encindex.h
+yjit.$(OBJEXT): {$(VPATH)}encoding.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/abi.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/packed_struct.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/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/set.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/numeric.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/stdckdint.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)}prism_compile.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)}rubyparser.h
+yjit.$(OBJEXT): {$(VPATH)}shape.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_insnhelper.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.rbinc
+yjit.$(OBJEXT): {$(VPATH)}zjit.h
+zjit.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h
+zjit.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h
+zjit.$(OBJEXT): $(CCAN_DIR)/list/list.h
+zjit.$(OBJEXT): $(CCAN_DIR)/str/str.h
+zjit.$(OBJEXT): $(hdrdir)/ruby/ruby.h
+zjit.$(OBJEXT): $(top_srcdir)/internal/array.h
+zjit.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h
+zjit.$(OBJEXT): $(top_srcdir)/internal/bignum.h
+zjit.$(OBJEXT): $(top_srcdir)/internal/bits.h
+zjit.$(OBJEXT): $(top_srcdir)/internal/box.h
+zjit.$(OBJEXT): $(top_srcdir)/internal/class.h
+zjit.$(OBJEXT): $(top_srcdir)/internal/compile.h
+zjit.$(OBJEXT): $(top_srcdir)/internal/compilers.h
+zjit.$(OBJEXT): $(top_srcdir)/internal/cont.h
+zjit.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
+zjit.$(OBJEXT): $(top_srcdir)/internal/gc.h
+zjit.$(OBJEXT): $(top_srcdir)/internal/hash.h
+zjit.$(OBJEXT): $(top_srcdir)/internal/imemo.h
+zjit.$(OBJEXT): $(top_srcdir)/internal/numeric.h
+zjit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h
+zjit.$(OBJEXT): $(top_srcdir)/internal/serial.h
+zjit.$(OBJEXT): $(top_srcdir)/internal/set_table.h
+zjit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
+zjit.$(OBJEXT): $(top_srcdir)/internal/string.h
+zjit.$(OBJEXT): $(top_srcdir)/internal/struct.h
+zjit.$(OBJEXT): $(top_srcdir)/internal/variable.h
+zjit.$(OBJEXT): $(top_srcdir)/internal/vm.h
+zjit.$(OBJEXT): $(top_srcdir)/internal/warnings.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/ast.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/defines.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/diagnostic.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/encoding.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/node.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/options.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/pack.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/parser.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/prism.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/regexp.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/static_literals.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h
+zjit.$(OBJEXT): $(top_srcdir)/prism/version.h
+zjit.$(OBJEXT): {$(VPATH)}assert.h
+zjit.$(OBJEXT): {$(VPATH)}atomic.h
+zjit.$(OBJEXT): {$(VPATH)}backward/2/assume.h
+zjit.$(OBJEXT): {$(VPATH)}backward/2/attributes.h
+zjit.$(OBJEXT): {$(VPATH)}backward/2/bool.h
+zjit.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h
+zjit.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h
+zjit.$(OBJEXT): {$(VPATH)}backward/2/limits.h
+zjit.$(OBJEXT): {$(VPATH)}backward/2/long_long.h
+zjit.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h
+zjit.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h
+zjit.$(OBJEXT): {$(VPATH)}builtin.h
+zjit.$(OBJEXT): {$(VPATH)}config.h
+zjit.$(OBJEXT): {$(VPATH)}constant.h
+zjit.$(OBJEXT): {$(VPATH)}debug.h
+zjit.$(OBJEXT): {$(VPATH)}debug_counter.h
+zjit.$(OBJEXT): {$(VPATH)}defines.h
+zjit.$(OBJEXT): {$(VPATH)}encindex.h
+zjit.$(OBJEXT): {$(VPATH)}encoding.h
+zjit.$(OBJEXT): {$(VPATH)}id.h
+zjit.$(OBJEXT): {$(VPATH)}id_table.h
+zjit.$(OBJEXT): {$(VPATH)}insns.def
+zjit.$(OBJEXT): {$(VPATH)}insns.inc
+zjit.$(OBJEXT): {$(VPATH)}insns_info.inc
+zjit.$(OBJEXT): {$(VPATH)}intern.h
+zjit.$(OBJEXT): {$(VPATH)}internal.h
+zjit.$(OBJEXT): {$(VPATH)}internal/abi.h
+zjit.$(OBJEXT): {$(VPATH)}internal/anyargs.h
+zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic.h
+zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h
+zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h
+zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h
+zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h
+zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h
+zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h
+zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h
+zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h
+zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h
+zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h
+zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h
+zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h
+zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h
+zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h
+zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h
+zjit.$(OBJEXT): {$(VPATH)}internal/assume.h
+zjit.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h
+zjit.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h
+zjit.$(OBJEXT): {$(VPATH)}internal/attr/cold.h
+zjit.$(OBJEXT): {$(VPATH)}internal/attr/const.h
+zjit.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h
+zjit.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h
+zjit.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h
+zjit.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h
+zjit.$(OBJEXT): {$(VPATH)}internal/attr/error.h
+zjit.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h
+zjit.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h
+zjit.$(OBJEXT): {$(VPATH)}internal/attr/format.h
+zjit.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h
+zjit.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h
+zjit.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h
+zjit.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h
+zjit.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h
+zjit.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h
+zjit.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h
+zjit.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h
+zjit.$(OBJEXT): {$(VPATH)}internal/attr/pure.h
+zjit.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h
+zjit.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h
+zjit.$(OBJEXT): {$(VPATH)}internal/attr/warning.h
+zjit.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h
+zjit.$(OBJEXT): {$(VPATH)}internal/cast.h
+zjit.$(OBJEXT): {$(VPATH)}internal/compiler_is.h
+zjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h
+zjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h
+zjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h
+zjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h
+zjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h
+zjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h
+zjit.$(OBJEXT): {$(VPATH)}internal/compiler_since.h
+zjit.$(OBJEXT): {$(VPATH)}internal/config.h
+zjit.$(OBJEXT): {$(VPATH)}internal/constant_p.h
+zjit.$(OBJEXT): {$(VPATH)}internal/core.h
+zjit.$(OBJEXT): {$(VPATH)}internal/core/rarray.h
+zjit.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h
+zjit.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h
+zjit.$(OBJEXT): {$(VPATH)}internal/core/rclass.h
+zjit.$(OBJEXT): {$(VPATH)}internal/core/rdata.h
+zjit.$(OBJEXT): {$(VPATH)}internal/core/rfile.h
+zjit.$(OBJEXT): {$(VPATH)}internal/core/rhash.h
+zjit.$(OBJEXT): {$(VPATH)}internal/core/robject.h
+zjit.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h
+zjit.$(OBJEXT): {$(VPATH)}internal/core/rstring.h
+zjit.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h
+zjit.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h
+zjit.$(OBJEXT): {$(VPATH)}internal/ctype.h
+zjit.$(OBJEXT): {$(VPATH)}internal/dllexport.h
+zjit.$(OBJEXT): {$(VPATH)}internal/dosish.h
+zjit.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h
+zjit.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h
+zjit.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h
+zjit.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h
+zjit.$(OBJEXT): {$(VPATH)}internal/encoding/re.h
+zjit.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h
+zjit.$(OBJEXT): {$(VPATH)}internal/encoding/string.h
+zjit.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h
+zjit.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h
+zjit.$(OBJEXT): {$(VPATH)}internal/error.h
+zjit.$(OBJEXT): {$(VPATH)}internal/eval.h
+zjit.$(OBJEXT): {$(VPATH)}internal/event.h
+zjit.$(OBJEXT): {$(VPATH)}internal/fl_type.h
+zjit.$(OBJEXT): {$(VPATH)}internal/gc.h
+zjit.$(OBJEXT): {$(VPATH)}internal/glob.h
+zjit.$(OBJEXT): {$(VPATH)}internal/globals.h
+zjit.$(OBJEXT): {$(VPATH)}internal/has/attribute.h
+zjit.$(OBJEXT): {$(VPATH)}internal/has/builtin.h
+zjit.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h
+zjit.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h
+zjit.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h
+zjit.$(OBJEXT): {$(VPATH)}internal/has/extension.h
+zjit.$(OBJEXT): {$(VPATH)}internal/has/feature.h
+zjit.$(OBJEXT): {$(VPATH)}internal/has/warning.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/array.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/class.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/compar.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/complex.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/cont.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/dir.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/enum.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/error.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/eval.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/file.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/hash.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/io.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/load.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/object.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/parse.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/proc.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/process.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/random.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/range.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/rational.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/re.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/select.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/set.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/signal.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/string.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/struct.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/thread.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/time.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/variable.h
+zjit.$(OBJEXT): {$(VPATH)}internal/intern/vm.h
+zjit.$(OBJEXT): {$(VPATH)}internal/interpreter.h
+zjit.$(OBJEXT): {$(VPATH)}internal/iterator.h
+zjit.$(OBJEXT): {$(VPATH)}internal/memory.h
+zjit.$(OBJEXT): {$(VPATH)}internal/method.h
+zjit.$(OBJEXT): {$(VPATH)}internal/module.h
+zjit.$(OBJEXT): {$(VPATH)}internal/newobj.h
+zjit.$(OBJEXT): {$(VPATH)}internal/numeric.h
+zjit.$(OBJEXT): {$(VPATH)}internal/scan_args.h
+zjit.$(OBJEXT): {$(VPATH)}internal/special_consts.h
+zjit.$(OBJEXT): {$(VPATH)}internal/static_assert.h
+zjit.$(OBJEXT): {$(VPATH)}internal/stdalign.h
+zjit.$(OBJEXT): {$(VPATH)}internal/stdbool.h
+zjit.$(OBJEXT): {$(VPATH)}internal/stdckdint.h
+zjit.$(OBJEXT): {$(VPATH)}internal/symbol.h
+zjit.$(OBJEXT): {$(VPATH)}internal/value.h
+zjit.$(OBJEXT): {$(VPATH)}internal/value_type.h
+zjit.$(OBJEXT): {$(VPATH)}internal/variable.h
+zjit.$(OBJEXT): {$(VPATH)}internal/warning_push.h
+zjit.$(OBJEXT): {$(VPATH)}internal/xmalloc.h
+zjit.$(OBJEXT): {$(VPATH)}iseq.h
+zjit.$(OBJEXT): {$(VPATH)}method.h
+zjit.$(OBJEXT): {$(VPATH)}missing.h
+zjit.$(OBJEXT): {$(VPATH)}node.h
+zjit.$(OBJEXT): {$(VPATH)}onigmo.h
+zjit.$(OBJEXT): {$(VPATH)}oniguruma.h
+zjit.$(OBJEXT): {$(VPATH)}prism_compile.h
+zjit.$(OBJEXT): {$(VPATH)}probes.dmyh
+zjit.$(OBJEXT): {$(VPATH)}probes.h
+zjit.$(OBJEXT): {$(VPATH)}probes_helper.h
+zjit.$(OBJEXT): {$(VPATH)}ruby_assert.h
+zjit.$(OBJEXT): {$(VPATH)}ruby_atomic.h
+zjit.$(OBJEXT): {$(VPATH)}rubyparser.h
+zjit.$(OBJEXT): {$(VPATH)}shape.h
+zjit.$(OBJEXT): {$(VPATH)}st.h
+zjit.$(OBJEXT): {$(VPATH)}subst.h
+zjit.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
+zjit.$(OBJEXT): {$(VPATH)}thread_native.h
+zjit.$(OBJEXT): {$(VPATH)}vm_callinfo.h
+zjit.$(OBJEXT): {$(VPATH)}vm_core.h
+zjit.$(OBJEXT): {$(VPATH)}vm_debug.h
+zjit.$(OBJEXT): {$(VPATH)}vm_insnhelper.h
+zjit.$(OBJEXT): {$(VPATH)}vm_opts.h
+zjit.$(OBJEXT): {$(VPATH)}vm_sync.h
+zjit.$(OBJEXT): {$(VPATH)}yjit.h
+zjit.$(OBJEXT): {$(VPATH)}zjit.c
+zjit.$(OBJEXT): {$(VPATH)}zjit.h
+zjit.$(OBJEXT): {$(VPATH)}zjit.rbinc
+# AUTOGENERATED DEPENDENCIES END
diff --git a/dir.c b/dir.c
index 0a22ad7901..25ed59c668 100644
--- a/dir.c
+++ b/dir.c
@@ -22,10 +22,6 @@
#include <unistd.h>
#endif
-#ifndef O_CLOEXEC
-# define O_CLOEXEC 0
-#endif
-
#ifndef USE_OPENDIR_AT
# if defined(HAVE_FDOPENDIR) && defined(HAVE_DIRFD) && \
defined(HAVE_OPENAT) && defined(HAVE_FSTATAT)
@@ -35,8 +31,12 @@
# endif
#endif
-#if USE_OPENDIR_AT
-# include <fcntl.h>
+#ifdef HAVE_FCNTL_H
+# include <fcntl.h>
+#endif
+
+#ifndef O_CLOEXEC
+# define O_CLOEXEC 0
#endif
#undef HAVE_DIRENT_NAMLEN
@@ -143,6 +143,50 @@ char *strchr(char*,char);
# define IS_WIN32 0
#endif
+#ifdef HAVE_GETATTRLIST
+struct getattrlist_args {
+ const char *path;
+ int fd;
+ struct attrlist *list;
+ void *buf;
+ size_t size;
+ unsigned int options;
+};
+
+# define GETATTRLIST_ARGS(list_, buf_, options_) (struct getattrlist_args) \
+ {.list = list_, .buf = buf_, .size = sizeof(buf_), .options = options_}
+
+static void *
+nogvl_getattrlist(void *args)
+{
+ struct getattrlist_args *arg = args;
+ return (void *)(VALUE)getattrlist(arg->path, arg->list, arg->buf, arg->size, arg->options);
+}
+
+static int
+gvl_getattrlist(struct getattrlist_args *args, const char *path)
+{
+ args->path = path;
+ return IO_WITHOUT_GVL_INT(nogvl_getattrlist, args);
+}
+
+# ifdef HAVE_FGETATTRLIST
+static void *
+nogvl_fgetattrlist(void *args)
+{
+ struct getattrlist_args *arg = args;
+ return (void *)(VALUE)fgetattrlist(arg->fd, arg->list, arg->buf, arg->size, arg->options);
+}
+
+static int
+gvl_fgetattrlist(struct getattrlist_args *args, int fd)
+{
+ args->fd = fd;
+ return IO_WITHOUT_GVL_INT(nogvl_fgetattrlist, args);
+}
+# endif
+#endif
+
#if NORMALIZE_UTF8PATH
# if defined HAVE_FGETATTRLIST || !defined HAVE_GETATTRLIST
# define need_normalization(dirp, path) need_normalization(dirp)
@@ -155,10 +199,11 @@ need_normalization(DIR *dirp, const char *path)
# if defined HAVE_FGETATTRLIST || defined HAVE_GETATTRLIST
u_int32_t attrbuf[SIZEUP32(fsobj_tag_t)];
struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, ATTR_CMN_OBJTAG,};
+ struct getattrlist_args args = GETATTRLIST_ARGS(&al, attrbuf, 0);
# if defined HAVE_FGETATTRLIST
- int ret = fgetattrlist(dirfd(dirp), &al, attrbuf, sizeof(attrbuf), 0);
+ int ret = gvl_fgetattrlist(&args, dirfd(dirp));
# else
- int ret = getattrlist(path, &al, attrbuf, sizeof(attrbuf), 0);
+ int ret = gvl_getattrlist(&args, path);
# endif
if (!ret) {
const fsobj_tag_t *tag = (void *)(attrbuf+1);
@@ -509,7 +554,7 @@ nogvl_opendir(void *ptr)
{
const char *path = ptr;
- return (void *)opendir(path);
+ return opendir(path);
}
static DIR *
@@ -526,6 +571,25 @@ opendir_without_gvl(const char *path)
return opendir(path);
}
+static void
+close_dir_data(struct dir_data *dp)
+{
+ if (dp->dir) {
+ if (closedir(dp->dir) < 0) {
+ dp->dir = NULL;
+ rb_sys_fail("closedir");
+ }
+ dp->dir = NULL;
+ }
+}
+
+static void
+check_closedir(DIR *dirp)
+{
+ if (closedir(dirp) < 0)
+ rb_sys_fail("closedir");
+}
+
static VALUE
dir_initialize(rb_execution_context_t *ec, VALUE dir, VALUE dirname, VALUE enc)
{
@@ -540,8 +604,7 @@ dir_initialize(rb_execution_context_t *ec, VALUE dir, VALUE dirname, VALUE enc)
dirname = rb_str_dup_frozen(dirname);
TypedData_Get_Struct(dir, struct dir_data, &dir_data_type, dp);
- if (dp->dir) closedir(dp->dir);
- dp->dir = NULL;
+ close_dir_data(dp);
RB_OBJ_WRITE(dir, &dp->path, Qnil);
dp->enc = fsenc;
path = RSTRING_PTR(dirname);
@@ -555,7 +618,8 @@ dir_initialize(rb_execution_context_t *ec, VALUE dir, VALUE dirname, VALUE enc)
else if (e == EIO) {
u_int32_t attrbuf[1];
struct attrlist al = {ATTR_BIT_MAP_COUNT, 0};
- if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW) == 0) {
+ struct getattrlist_args args = GETATTRLIST_ARGS(&al, attrbuf, FSOPT_NOFOLLOW);
+ if (gvl_getattrlist(&args, path) == 0) {
dp->dir = opendir_without_gvl(path);
}
}
@@ -588,6 +652,12 @@ dir_s_close(rb_execution_context_t *ec, VALUE klass, VALUE dir)
}
# if defined(HAVE_FDOPENDIR) && defined(HAVE_DIRFD)
+static void *
+nogvl_fdopendir(void *fd)
+{
+ return fdopendir((int)(VALUE)fd);
+}
+
/*
* call-seq:
* Dir.for_fd(fd) -> dir
@@ -614,7 +684,7 @@ dir_s_for_fd(VALUE klass, VALUE fd)
struct dir_data *dp;
VALUE dir = TypedData_Make_Struct(klass, struct dir_data, &dir_data_type, dp);
- if (!(dp->dir = fdopendir(NUM2INT(fd)))) {
+ if (!(dp->dir = IO_WITHOUT_GVL(nogvl_fdopendir, (void *)(VALUE)NUM2INT(fd)))) {
rb_sys_fail("fdopendir");
UNREACHABLE_RETURN(Qnil);
}
@@ -756,8 +826,28 @@ fundamental_encoding_p(rb_encoding *enc)
}
}
# define READDIR(dir, enc) rb_w32_readdir((dir), (enc))
+# define READDIR_NOGVL READDIR
#else
-# define READDIR(dir, enc) readdir((dir))
+NORETURN(static void *sys_failure(void *function));
+static void *
+sys_failure(void *function)
+{
+ rb_sys_fail(function);
+}
+
+static void *
+nogvl_readdir(void *dir)
+{
+ rb_errno_set(0);
+ if ((dir = readdir(dir)) == NULL) {
+ if (rb_errno())
+ rb_thread_call_with_gvl(sys_failure, (void *)"readdir");
+ }
+ return dir;
+}
+
+# define READDIR(dir, enc) IO_WITHOUT_GVL(nogvl_readdir, (void *)(dir))
+# define READDIR_NOGVL(dir, enc) nogvl_readdir((dir))
#endif
/* safe to use without GVL */
@@ -902,7 +992,8 @@ dir_tell(VALUE dir)
long pos;
GetDIR(dir, dirp);
- pos = telldir(dirp->dir);
+ if((pos = telldir(dirp->dir)) < 0)
+ rb_sys_fail("telldir");
return rb_int2inum(pos);
}
#else
@@ -1021,8 +1112,7 @@ dir_close(VALUE dir)
dirp = dir_get(dir);
if (!dirp->dir) return Qnil;
- closedir(dirp->dir);
- dirp->dir = NULL;
+ close_dir_data(dirp);
return Qnil;
}
@@ -1038,7 +1128,7 @@ nogvl_chdir(void *ptr)
static void
dir_chdir0(VALUE path)
{
- if (chdir(RSTRING_PTR(path)) < 0)
+ if (IO_WITHOUT_GVL_INT(nogvl_chdir, (void*)RSTRING_PTR(path)) < 0)
rb_sys_fail_path(path);
}
@@ -1240,7 +1330,7 @@ nogvl_fchdir(void *ptr)
static void
dir_fchdir(int fd)
{
- if (fchdir(fd) < 0)
+ if (IO_WITHOUT_GVL_INT(nogvl_fchdir, (void *)&fd) < 0)
rb_sys_fail("fchdir");
}
@@ -1390,7 +1480,7 @@ rb_dir_getwd_ospath(void)
VALUE cwd;
VALUE path_guard;
- path_guard = rb_imemo_tmpbuf_auto_free_pointer();
+ path_guard = rb_imemo_tmpbuf_new();
path = ruby_getcwd();
rb_imemo_tmpbuf_set_ptr(path_guard, path);
#ifdef __APPLE__
@@ -1460,6 +1550,12 @@ check_dirname(VALUE dir)
}
#if defined(HAVE_CHROOT)
+static void *
+nogvl_chroot(void *dirname)
+{
+ return (void *)(VALUE)chroot((const char *)dirname);
+}
+
/*
* call-seq:
* Dir.chroot(dirpath) -> 0
@@ -1476,7 +1572,7 @@ static VALUE
dir_s_chroot(VALUE dir, VALUE path)
{
path = check_dirname(path);
- if (chroot(RSTRING_PTR(path)) == -1)
+ if (IO_WITHOUT_GVL_INT(nogvl_chroot, (void *)RSTRING_PTR(path)) == -1)
rb_sys_fail_path(path);
return INT2FIX(0);
@@ -1653,11 +1749,11 @@ to_be_ignored(int e)
}
#ifdef _WIN32
-#define STAT(p, s) rb_w32_ustati128((p), (s))
-#undef lstat
-#define lstat(p, s) rb_w32_ulstati128((p), (s))
+#define STAT(args) (int)(VALUE)nogvl_stat(&(args))
+#define LSTAT(args) (int)(VALUE)nogvl_lstat(&(args))
#else
-#define STAT(p, s) stat((p), (s))
+#define STAT(args) IO_WITHOUT_GVL_INT(nogvl_stat, (void *)&(args))
+#define LSTAT(args) IO_WITHOUT_GVL_INT(nogvl_lstat, (void *)&(args))
#endif
typedef int ruby_glob_errfunc(const char*, VALUE, const void*, int);
@@ -1678,14 +1774,50 @@ at_subpath(int fd, size_t baselen, const char *path)
return *path ? path : ".";
}
+#if USE_OPENDIR_AT
+struct fstatat_args {
+ int fd;
+ int flag;
+ const char *path;
+ struct stat *pst;
+};
+
+static void *
+nogvl_fstatat(void *args)
+{
+ struct fstatat_args *arg = (struct fstatat_args *)args;
+ return (void *)(VALUE)fstatat(arg->fd, arg->path, arg->pst, arg->flag);
+}
+#else
+struct stat_args {
+ const char *path;
+ struct stat *pst;
+};
+
+static void *
+nogvl_stat(void *args)
+{
+ struct stat_args *arg = (struct stat_args *)args;
+ return (void *)(VALUE)stat(arg->path, arg->pst);
+}
+#endif
+
/* System call with warning */
static int
do_stat(int fd, size_t baselen, const char *path, struct stat *pst, int flags, rb_encoding *enc)
{
#if USE_OPENDIR_AT
- int ret = fstatat(fd, at_subpath(fd, baselen, path), pst, 0);
+ struct fstatat_args args;
+ args.fd = fd;
+ args.path = path;
+ args.pst = pst;
+ args.flag = 0;
+ int ret = IO_WITHOUT_GVL_INT(nogvl_fstatat, (void *)&args);
#else
- int ret = STAT(path, pst);
+ struct stat_args args;
+ args.path = path;
+ args.pst = pst;
+ int ret = STAT(args);
#endif
if (ret < 0 && !to_be_ignored(errno))
sys_warning(path, enc);
@@ -1694,13 +1826,30 @@ do_stat(int fd, size_t baselen, const char *path, struct stat *pst, int flags, r
}
#if defined HAVE_LSTAT || defined lstat || USE_OPENDIR_AT
+#if !USE_OPENDIR_AT
+static void *
+nogvl_lstat(void *args)
+{
+ struct stat_args *arg = (struct stat_args *)args;
+ return (void *)(VALUE)lstat(arg->path, arg->pst);
+}
+#endif
+
static int
do_lstat(int fd, size_t baselen, const char *path, struct stat *pst, int flags, rb_encoding *enc)
{
#if USE_OPENDIR_AT
- int ret = fstatat(fd, at_subpath(fd, baselen, path), pst, AT_SYMLINK_NOFOLLOW);
+ struct fstatat_args args;
+ args.fd = fd;
+ args.path = path;
+ args.pst = pst;
+ args.flag = AT_SYMLINK_NOFOLLOW;
+ int ret = IO_WITHOUT_GVL_INT(nogvl_fstatat, (void *)&args);
#else
- int ret = lstat(path, pst);
+ struct stat_args args;
+ args.path = path;
+ args.pst = pst;
+ int ret = LSTAT(args);
#endif
if (ret < 0 && !to_be_ignored(errno))
sys_warning(path, enc);
@@ -2061,14 +2210,15 @@ is_case_sensitive(DIR *dirp, const char *path)
const vol_capabilities_attr_t *const cap = attrbuf[0].cap;
const int idx = VOL_CAPABILITIES_FORMAT;
const uint32_t mask = VOL_CAP_FMT_CASE_SENSITIVE;
-
+ struct getattrlist_args args = GETATTRLIST_ARGS(&al, attrbuf, FSOPT_NOFOLLOW);
# if defined HAVE_FGETATTRLIST
- if (fgetattrlist(dirfd(dirp), &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW))
- return -1;
+ int ret = gvl_fgetattrlist(&args, dirfd(dirp));
# else
- if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW))
- return -1;
+ int ret = gvl_getattrlist(&args, path);
# endif
+ if (ret)
+ return -1;
+
if (!(cap->valid[idx] & mask))
return -1;
return (cap->capabilities[idx] & mask) != 0;
@@ -2091,7 +2241,8 @@ replace_real_basename(char *path, long base, rb_encoding *enc, int norm_p, int f
IF_NORMALIZE_UTF8PATH(VALUE utf8str = Qnil);
*type = path_noent;
- if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW)) {
+ struct getattrlist_args args = GETATTRLIST_ARGS(&al, attrbuf, FSOPT_NOFOLLOW);
+ if (gvl_getattrlist(&args, path)) {
if (!to_be_ignored(errno))
sys_warning(path, enc);
return path;
@@ -2464,7 +2615,7 @@ static void
glob_dir_finish(ruby_glob_entries_t *ent, int flags)
{
if (flags & FNM_GLOB_NOSORT) {
- closedir(ent->nosort.dirp);
+ check_closedir(ent->nosort.dirp);
ent->nosort.dirp = NULL;
}
else if (ent->sort.entries) {
@@ -2495,7 +2646,7 @@ glob_opendir(ruby_glob_entries_t *ent, DIR *dirp, int flags, rb_encoding *enc)
#ifdef _WIN32
if ((capacity = dirp->nfiles) > 0) {
if (!(newp = GLOB_ALLOC_N(rb_dirent_t, capacity))) {
- closedir(dirp);
+ check_closedir(dirp);
return NULL;
}
ent->sort.entries = newp;
@@ -2515,7 +2666,7 @@ glob_opendir(ruby_glob_entries_t *ent, DIR *dirp, int flags, rb_encoding *enc)
ent->sort.entries[count++] = rdp;
ent->sort.count = count;
}
- closedir(dirp);
+ check_closedir(dirp);
if (count < capacity) {
if (!(newp = GLOB_REALLOC_N(ent->sort.entries, count))) {
glob_dir_finish(ent, 0);
@@ -2530,7 +2681,7 @@ glob_opendir(ruby_glob_entries_t *ent, DIR *dirp, int flags, rb_encoding *enc)
nomem:
glob_dir_finish(ent, 0);
- closedir(dirp);
+ check_closedir(dirp);
return NULL;
}
@@ -2693,7 +2844,7 @@ glob_helper(
# if NORMALIZE_UTF8PATH
if (!(norm_p || magical || recursive)) {
- closedir(dirp);
+ check_closedir(dirp);
goto literally;
}
# endif
@@ -3516,7 +3667,7 @@ file_s_fnmatch(int argc, VALUE *argv, VALUE obj)
* call-seq:
* Dir.home(user_name = nil) -> dirpath
*
- * Retruns the home directory path of the user specified with +user_name+
+ * Returns the home directory path of the user specified with +user_name+
* if it is not +nil+, or the current login user:
*
* Dir.home # => "/home/me"
@@ -3585,13 +3736,13 @@ nogvl_dir_empty_p(void *ptr)
return (void *)INT2FIX(e);
}
}
- while ((dp = READDIR(dir, NULL)) != NULL) {
+ while ((dp = READDIR_NOGVL(dir, NULL)) != NULL) {
if (!to_be_skipped(dp)) {
result = Qfalse;
break;
}
}
- closedir(dir);
+ check_closedir(dir);
return (void *)result;
}
@@ -3627,12 +3778,13 @@ rb_dir_s_empty_p(VALUE obj, VALUE dirname)
{
u_int32_t attrbuf[SIZEUP32(fsobj_tag_t)];
struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, ATTR_CMN_OBJTAG,};
- if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), 0) != 0)
+ struct getattrlist_args args = GETATTRLIST_ARGS(&al, attrbuf, 0);
+ if (gvl_getattrlist(&args, path) != 0)
rb_sys_fail_path(orig);
if (*(const fsobj_tag_t *)(attrbuf+1) == VT_HFS) {
al.commonattr = 0;
al.dirattr = ATTR_DIR_ENTRYCOUNT;
- if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), 0) == 0) {
+ if (gvl_getattrlist(&args, path) == 0) {
if (attrbuf[0] >= 2 * sizeof(u_int32_t))
return RBOOL(attrbuf[1] == 0);
if (false_on_notdir) return Qfalse;
@@ -3699,26 +3851,19 @@ Init_Dir(void)
rb_define_singleton_method(rb_cFile,"fnmatch", file_s_fnmatch, -1);
rb_define_singleton_method(rb_cFile,"fnmatch?", file_s_fnmatch, -1);
- /* Document-const: FNM_NOESCAPE
- * {File::FNM_NOESCAPE}[rdoc-ref:File::Constants@File-3A-3AFNM_NOESCAPE] */
+ /* {File::FNM_NOESCAPE}[rdoc-ref:File::Constants@File-3A-3AFNM_NOESCAPE] */
rb_file_const("FNM_NOESCAPE", INT2FIX(FNM_NOESCAPE));
- /* Document-const: FNM_PATHNAME
- * {File::FNM_PATHNAME}[rdoc-ref:File::Constants@File-3A-3AFNM_PATHNAME] */
+ /* {File::FNM_PATHNAME}[rdoc-ref:File::Constants@File-3A-3AFNM_PATHNAME] */
rb_file_const("FNM_PATHNAME", INT2FIX(FNM_PATHNAME));
- /* Document-const: FNM_DOTMATCH
- * {File::FNM_DOTMATCH}[rdoc-ref:File::Constants@File-3A-3AFNM_DOTMATCH] */
+ /* {File::FNM_DOTMATCH}[rdoc-ref:File::Constants@File-3A-3AFNM_DOTMATCH] */
rb_file_const("FNM_DOTMATCH", INT2FIX(FNM_DOTMATCH));
- /* Document-const: FNM_CASEFOLD
- * {File::FNM_CASEFOLD}[rdoc-ref:File::Constants@File-3A-3AFNM_CASEFOLD] */
+ /* {File::FNM_CASEFOLD}[rdoc-ref:File::Constants@File-3A-3AFNM_CASEFOLD] */
rb_file_const("FNM_CASEFOLD", INT2FIX(FNM_CASEFOLD));
- /* Document-const: FNM_EXTGLOB
- * {File::FNM_EXTGLOB}[rdoc-ref:File::Constants@File-3A-3AFNM_EXTGLOB] */
+ /* {File::FNM_EXTGLOB}[rdoc-ref:File::Constants@File-3A-3AFNM_EXTGLOB] */
rb_file_const("FNM_EXTGLOB", INT2FIX(FNM_EXTGLOB));
- /* Document-const: FNM_SYSCASE
- * {File::FNM_SYSCASE}[rdoc-ref:File::Constants@File-3A-3AFNM_SYSCASE] */
+ /* {File::FNM_SYSCASE}[rdoc-ref:File::Constants@File-3A-3AFNM_SYSCASE] */
rb_file_const("FNM_SYSCASE", INT2FIX(FNM_SYSCASE));
- /* Document-const: FNM_SHORTNAME
- * {File::FNM_SHORTNAME}[rdoc-ref:File::Constants@File-3A-3AFNM_SHORTNAME] */
+ /* {File::FNM_SHORTNAME}[rdoc-ref:File::Constants@File-3A-3AFNM_SHORTNAME] */
rb_file_const("FNM_SHORTNAME", INT2FIX(FNM_SHORTNAME));
}
diff --git a/dir.rb b/dir.rb
index 42b475ab2c..eb1a408ee3 100644
--- a/dir.rb
+++ b/dir.rb
@@ -46,14 +46,14 @@
# The stream has a _position_, which is the index of an entry in the directory:
#
# - The initial position is zero (before the first entry).
-# - \Method #tell (aliased as #pos) returns the position.
-# - \Method #pos= sets the position (but ignores a value outside the stream),
+# - Method #tell (aliased as #pos) returns the position.
+# - Method #pos= sets the position (but ignores a value outside the stream),
# and returns the position.
-# - \Method #seek is like #pos=, but returns +self+ (convenient for chaining).
-# - \Method #read, if not at end-of-stream, reads the next entry and increments
+# - Method #seek is like #pos=, but returns +self+ (convenient for chaining).
+# - Method #read, if not at end-of-stream, reads the next entry and increments
# the position;
# if at end-of-stream, does not increment the position.
-# - \Method #rewind sets the position to zero.
+# - Method #rewind sets the position to zero.
#
# Examples (using the {simple file tree}[rdoc-ref:Dir@About+the+Examples]):
#
@@ -83,7 +83,7 @@
#
# == What's Here
#
-# First, what's elsewhere. \Class \Dir:
+# First, what's elsewhere. Class \Dir:
#
# - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
# - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
@@ -178,7 +178,7 @@ class Dir
# if +nil+ (the default), the file system's encoding is used:
#
# Dir.open('.').read.encoding # => #<Encoding:UTF-8>
- # Dir.open('.', encoding: 'US-ASCII').read.encoding # => #<Encoding:US-ASCII>
+ # Dir.open('.', encoding: Encoding::US_ASCII).read.encoding # => #<Encoding:US-ASCII>
#
def self.open(name, encoding: nil, &block)
dir = Primitive.dir_s_open(name, encoding)
@@ -206,7 +206,7 @@ class Dir
# if +nil+ (the default), the file system's encoding is used:
#
# Dir.new('.').read.encoding # => #<Encoding:UTF-8>
- # Dir.new('.', encoding: 'US-ASCII').read.encoding # => #<Encoding:US-ASCII>
+ # Dir.new('.', encoding: Encoding::US_ASCI).read.encoding # => #<Encoding:US-ASCII>
#
def initialize(name, encoding: nil)
Primitive.dir_initialize(name, encoding)
@@ -224,8 +224,8 @@ class Dir
end
# call-seq:
- # Dir.glob(*patterns, flags: 0, base: nil, sort: true) -> array
- # Dir.glob(*patterns, flags: 0, base: nil, sort: true) {|entry_name| ... } -> nil
+ # Dir.glob(patterns, flags: 0, base: nil, sort: true) -> array
+ # Dir.glob(patterns, flags: 0, base: nil, sort: true) {|entry_name| ... } -> nil
#
# Forms an array _entry_names_ of the entry names selected by the arguments.
#
@@ -319,14 +319,14 @@ class Dir
#
# Dir.glob('io.?') # => ["io.c"]
#
- # - <tt>'[_set_]'</tt>: Matches any one character in the string _set_;
+ # - <tt>'[set]'</tt>: Matches any one character in the string _set_;
# behaves like a {Regexp character class}[rdoc-ref:Regexp@Character+Classes],
# including set negation (<tt>'[^a-z]'</tt>):
#
# Dir.glob('*.[a-z][a-z]').take(3)
# # => ["CONTRIBUTING.md", "COPYING.ja", "KNOWNBUGS.rb"]
#
- # - <tt>'{_abc_,_xyz_}'</tt>:
+ # - <tt>'{abc,xyz}'</tt>:
# Matches either string _abc_ or string _xyz_;
# behaves like {Regexp alternation}[rdoc-ref:Regexp@Alternation]:
#
@@ -388,10 +388,10 @@ class Dir
#
# - File::FNM_EXTGLOB:
# enables the pattern extension
- # <tt>'{_a_,_b_}'</tt>, which matches pattern _a_ and pattern _b_;
+ # <tt>'{a,b}'</tt>, which matches pattern _a_ and pattern _b_;
# behaves like a
# {regexp union}[rdoc-ref:Regexp.union]
- # (e.g., <tt>'(?:_a_|_b_)'</tt>):
+ # (e.g., <tt>'(?:a|b)'</tt>):
#
# pattern = '{LEGAL,BSDL}'
# Dir.glob(pattern) # => ["LEGAL", "BSDL"]
diff --git a/dln.c b/dln.c
index 89f16b54f0..2549f03183 100644
--- a/dln.c
+++ b/dln.c
@@ -25,6 +25,7 @@ static void dln_loaderror(const char *format, ...);
#endif
#include "dln.h"
#include "internal.h"
+#include "internal/box.h"
#include "internal/compilers.h"
#ifdef HAVE_STDLIB_H
@@ -76,12 +77,6 @@ void *xrealloc();
# include <unistd.h>
#endif
-bool
-dln_supported_p(void)
-{
- return true;
-}
-
#ifndef dln_loaderror
static void
dln_loaderror(const char *format, ...)
@@ -200,6 +195,7 @@ dln_strerror(char *message, size_t size)
}
return message;
}
+#define dln_strerror() dln_strerror(message, sizeof message)
#elif defined USE_DLN_DLOPEN
static const char *
dln_strerror(void)
@@ -289,7 +285,7 @@ dln_incompatible_func(void *handle, const char *funcname, void *const fp, const
void *ex = dlsym(handle, funcname);
if (!ex) return false;
if (ex == fp) return false;
-# if defined(HAVE_DLADDR)
+# if defined(HAVE_DLADDR) && !defined(__CYGWIN__)
Dl_info dli;
if (dladdr(ex, &dli)) {
*libname = dli.dli_fname;
@@ -344,13 +340,16 @@ dln_disable_dlclose(void)
#endif
#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
-void *
-dln_open(const char *file, char *error, size_t size)
+static void *
+dln_open(const char *file)
{
static const char incompatible[] = "incompatible library version";
+ const char *error = NULL;
void *handle;
#if defined(_WIN32)
+ char message[1024];
+
/* Convert the file path to wide char */
WCHAR *winfile = rb_w32_mbstr_to_wstr(CP_UTF8, file, -1, NULL);
if (!winfile) {
@@ -362,15 +361,15 @@ dln_open(const char *file, char *error, size_t size)
free(winfile);
if (!handle) {
- strlcpy(error, dln_strerror(error, size), size);
- return NULL;
+ error = dln_strerror();
+ goto failed;
}
# if defined(RUBY_EXPORT)
if (!rb_w32_check_imported(handle, rb_libruby_handle())) {
FreeLibrary(handle);
- strlcpy(error, incompatible, size);
- return NULL;
+ error = incompatible;
+ goto failed;
}
# endif
@@ -385,12 +384,16 @@ dln_open(const char *file, char *error, size_t size)
# ifndef RTLD_GLOBAL
# define RTLD_GLOBAL 0
# endif
+# ifndef RTLD_LOCAL
+# define RTLD_LOCAL 0 /* TODO: 0??? some systems (including libc) use 0x00100 for RTLD_GLOBAL, 0x00000 for RTLD_LOCAL */
+# endif
/* Load file */
- handle = dlopen(file, RTLD_LAZY|RTLD_GLOBAL);
+ int mode = rb_box_available() ? RTLD_LAZY|RTLD_LOCAL : RTLD_LAZY|RTLD_GLOBAL;
+ handle = dlopen(file, mode);
if (handle == NULL) {
- strlcpy(error, dln_strerror(), size);
- return NULL;
+ error = dln_strerror();
+ goto failed;
}
# if defined(RUBY_EXPORT)
@@ -412,15 +415,11 @@ dln_open(const char *file, char *error, size_t size)
libruby_name = tmp;
}
dlclose(handle);
-
if (libruby_name) {
- snprintf(error, size, "linked to incompatible %s - %s", libruby_name, file);
+ dln_loaderror("linked to incompatible %s - %s", libruby_name, file);
}
- else {
- strlcpy(error, incompatible, size);
- }
-
- return NULL;
+ error = incompatible;
+ goto failed;
}
}
}
@@ -428,9 +427,12 @@ dln_open(const char *file, char *error, size_t size)
#endif
return handle;
+
+ failed:
+ dln_loaderror("%s - %s", error, file);
}
-void *
+static void *
dln_sym(void *handle, const char *symbol)
{
#if defined(_WIN32)
@@ -440,7 +442,7 @@ dln_sym(void *handle, const char *symbol)
#endif
}
-static void *
+static uintptr_t
dln_sym_func(void *handle, const char *symbol)
{
void *func = dln_sym(handle, symbol);
@@ -449,14 +451,14 @@ dln_sym_func(void *handle, const char *symbol)
const char *error;
#if defined(_WIN32)
char message[1024];
- error = dln_strerror(message, sizeof(message));
+ error = dln_strerror();
#elif defined(USE_DLN_DLOPEN)
const size_t errlen = strlen(error = dln_strerror()) + 1;
error = memcpy(ALLOCA_N(char, errlen), error, errlen);
#endif
dln_loaderror("%s - %s", error, symbol);
}
- return func;
+ return (uintptr_t)func;
}
#define dln_sym_callable(rettype, argtype, handle, symbol) \
@@ -500,16 +502,11 @@ abi_check_enabled_p(void)
}
#endif
-void *
-dln_load(const char *file)
+static void *
+dln_load_and_init(const char *file, const char *init_fct_name)
{
#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
- char error[1024];
- void *handle = dln_open(file, error, sizeof(error));
-
- if (handle == NULL) {
- dln_loaderror("%s - %s", error, file);
- }
+ void *handle = dln_open(file);
#ifdef RUBY_DLN_CHECK_ABI
typedef unsigned long long abi_version_number;
@@ -520,9 +517,6 @@ dln_load(const char *file)
}
#endif
- char *init_fct_name;
- init_funcname(&init_fct_name, file);
-
/* Call the init code */
dln_sym_callable(void, (void), handle, init_fct_name)();
@@ -532,6 +526,7 @@ dln_load(const char *file)
{
void (*init_fct)(void);
+ /* TODO: check - AIX's load system call will return the first/last symbol/function? */
init_fct = (void(*)(void))load((char*)file, 1, 0);
if (init_fct == NULL) {
aix_loaderror(file);
@@ -548,3 +543,29 @@ dln_load(const char *file)
return 0; /* dummy return */
}
+
+void *
+dln_load(const char *file)
+{
+#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
+ char *init_fct_name;
+ init_funcname(&init_fct_name, file);
+ return dln_load_and_init(file, init_fct_name);
+#else
+ dln_notimplement();
+ return 0;
+#endif
+}
+
+void *
+dln_load_feature(const char *file, const char *fname)
+{
+#if defined(_WIN32) || defined(USE_DLN_DLOPEN)
+ char *init_fct_name;
+ init_funcname(&init_fct_name, fname);
+ return dln_load_and_init(file, init_fct_name);
+#else
+ dln_notimplement();
+ return 0;
+#endif
+}
diff --git a/dln.h b/dln.h
index 26df5266f7..711abf592c 100644
--- a/dln.h
+++ b/dln.h
@@ -22,11 +22,10 @@ RUBY_SYMBOL_EXPORT_BEGIN
#define DLN_FIND_EXTRA_ARG_DECL
#endif
-bool dln_supported_p(void);
char *dln_find_exe_r(const char*,const char*,char*,size_t DLN_FIND_EXTRA_ARG_DECL);
char *dln_find_file_r(const char*,const char*,char*,size_t DLN_FIND_EXTRA_ARG_DECL);
void *dln_load(const char*);
-void *dln_open(const char *file, char *error, size_t size);
+void *dln_load_feature(const char*, const char*);
void *dln_symbol(void*,const char*);
RUBY_SYMBOL_EXPORT_END
diff --git a/dmydln.c b/dmydln.c
index 1f5b59022b..62a89e2da5 100644
--- a/dmydln.c
+++ b/dmydln.c
@@ -3,12 +3,6 @@
#include "ruby/ruby.h"
-bool
-dln_supported_p(void)
-{
- return false;
-}
-
NORETURN(void *dln_load(const char *));
void*
dln_load(const char *file)
@@ -18,20 +12,20 @@ dln_load(const char *file)
UNREACHABLE_RETURN(NULL);
}
-NORETURN(void *dln_symbol(void*,const char*));
+NORETURN(void *dln_load_feature(const char*,const char*));
void*
-dln_symbol(void *handle, const char *symbol)
+dln_load_feature(const char *file, const char *fname)
{
rb_loaderror("this executable file can't load extension libraries");
UNREACHABLE_RETURN(NULL);
}
+NORETURN(void *dln_symbol(void*,const char*));
void*
-dln_open(const char *library, char *error, size_t size)
+dln_symbol(void *handle, const char *symbol)
{
- static const char *error_str = "this executable file can't load extension libraries";
- strlcpy(error, error_str, size);
- return NULL;
-}
+ rb_loaderror("this executable file can't load extension libraries");
+ UNREACHABLE_RETURN(NULL);
+}
diff --git a/doc/.document b/doc/.document
index 8174394f48..3a95c9617b 100644
--- a/doc/.document
+++ b/doc/.document
@@ -1,12 +1,13 @@
-*.md
-*.rb
+[^_]*.md
+[^_]*.rb
[^_]*.rdoc
contributing
+distribution
NEWS
syntax
optparse
+date
rdoc
-regexp
-rjit
-yjit
-ruby
+jit
+security
+language
diff --git a/doc/ChangeLog/ChangeLog-1.9.3 b/doc/ChangeLog/ChangeLog-1.9.3
index 0f80eed2d5..03a7f3eabf 100644
--- a/doc/ChangeLog/ChangeLog-1.9.3
+++ b/doc/ChangeLog/ChangeLog-1.9.3
@@ -9012,7 +9012,7 @@ Thu Dec 2 01:24:39 2010 NARUSE, Yui <naruse@ruby-lang.org>
Thu Dec 2 01:02:03 2010 NARUSE, Yui <naruse@ruby-lang.org>
- * ext/json: Update github/flori/json from 1.4.2+ to
+ * ext/json: Update github/ruby/json from 1.4.2+ to
e22b2f2bdfe6a9b0. this fixes some bugs.
Thu Dec 2 00:05:44 2010 NARUSE, Yui <naruse@ruby-lang.org>
diff --git a/doc/ChangeLog/ChangeLog-2.0.0 b/doc/ChangeLog/ChangeLog-2.0.0
index 9e654db189..de47b66a69 100644
--- a/doc/ChangeLog/ChangeLog-2.0.0
+++ b/doc/ChangeLog/ChangeLog-2.0.0
@@ -14426,7 +14426,7 @@ Tue May 8 02:34:26 2012 NARUSE, Yui <naruse@ruby-lang.org>
Mon May 7 21:19:17 2012 NARUSE, Yui <naruse@ruby-lang.org>
* ext/json: Merge JSON 1.7.1.
- https://github.com/flori/json/commit/e5b9a9465c1159fae533bca320d950b772bcb4ac
+ https://github.com/ruby/json/commit/e5b9a9465c1159fae533bca320d950b772bcb4ac
Mon May 7 22:54:22 2012 Martin Bosslet <Martin.Bosslet@googlemail.com>
diff --git a/doc/ChangeLog/ChangeLog-2.1.0 b/doc/ChangeLog/ChangeLog-2.1.0
index 7964a682eb..b6977dbccd 100644
--- a/doc/ChangeLog/ChangeLog-2.1.0
+++ b/doc/ChangeLog/ChangeLog-2.1.0
@@ -2167,7 +2167,7 @@ Wed Nov 20 11:46:38 2013 NARUSE, Yui <naruse@ruby-lang.org>
* ext/json: merge JSON 1.8.1.
https://github.com/nurse/json/compare/002ac2771ce32776b32ccd2d06e5604de6c36dcd...e09ffc0d7da25d0393873936c118c188c78dbac3
* Remove Rubinius exception since transcoding should be working now.
- * Fix https://github.com/flori/json/issues/162 reported by Marc-Andre
+ * Fix https://github.com/ruby/json/issues/162 reported by Marc-Andre
Lafortune <github_rocks@marc-andre.ca>. Thanks!
* Applied patches by Yui NARUSE <naruse@airemix.jp> to suppress
warning with -Wchar-subscripts and better validate UTF-8 strings.
@@ -17913,7 +17913,7 @@ Tue Feb 12 12:02:35 2013 NARUSE, Yui <naruse@ruby-lang.org>
* ext/json: merge JSON 1.7.7.
This includes security fix. [CVE-2013-0269]
- https://github.com/flori/json/commit/d0a62f3ced7560daba2ad546d83f0479a5ae2cf2
+ https://github.com/ruby/json/commit/d0a62f3ced7560daba2ad546d83f0479a5ae2cf2
https://groups.google.com/d/topic/rubyonrails-security/4_YvCpLzL58/discussion
Mon Feb 11 23:08:48 2013 Tanaka Akira <akr@fsij.org>
diff --git a/doc/ChangeLog/ChangeLog-2.3.0 b/doc/ChangeLog/ChangeLog-2.3.0
index 94996cffd0..e616183895 100644
--- a/doc/ChangeLog/ChangeLog-2.3.0
+++ b/doc/ChangeLog/ChangeLog-2.3.0
@@ -1211,7 +1211,7 @@ Sun Dec 6 08:39:05 2015 SHIBATA Hiroshi <hsbt@ruby-lang.org>
upstream changes.
https://github.com/ruby/ruby/commit/4d059bf9f5f10f3d3088de49fc87e5555db7770d
- https://github.com/flori/json/commit/d4c99de78905d96c3f301f48b2c789943bb3f098
+ https://github.com/ruby/json/commit/d4c99de78905d96c3f301f48b2c789943bb3f098
* ext/json/lib/json/version.rb: ditto.
@@ -10989,7 +10989,7 @@ Fri Feb 13 21:16:00 2015 Yusuke Endoh <mame@tsg.ne.jp>
Fri Feb 13 14:19:06 2015 SHIBATA Hiroshi <shibata.hiroshi@gmail.com>
- * ext/json: merge upstream from flori/json
+ * ext/json: merge upstream from ruby/json
change usage of TypedData. [Feature #10739][ruby-core:67564]
Thu Feb 12 18:34:01 2015 multisnow <infinity.blick.winkel@gmail.com>
@@ -11556,7 +11556,7 @@ Tue Jan 13 21:08:22 2015 SHIBATA Hiroshi <shibata.hiroshi@gmail.com>
* ext/json, test/json: merge JSON HEAD(259dee6)
separate implementation of Typed_Data macro.
- https://github.com/flori/json/compare/v1.8.1...v1.8.2
+ https://github.com/ruby/json/compare/v1.8.1...v1.8.2
Tue Jan 13 14:16:35 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
@@ -12009,7 +12009,7 @@ Mon Dec 29 10:37:27 2014 Thiago Lewin <thiago_lewin@yahoo.com.br>
Mon Dec 29 07:27:23 2014 SHIBATA Hiroshi <shibata.hiroshi@gmail.com>
* ext/json, test/json: merge JSON HEAD(17fe8e7)
- https://github.com/flori/json/compare/v1.8.1...17fe8e7
+ https://github.com/ruby/json/compare/v1.8.1...17fe8e7
Sun Dec 28 23:49:37 2014 Michal Papis <mpapis@gmail.com>
diff --git a/doc/ChangeLog/ChangeLog-2.4.0 b/doc/ChangeLog/ChangeLog-2.4.0
index 30e9ccab3d..5e126fbd90 100644
--- a/doc/ChangeLog/ChangeLog-2.4.0
+++ b/doc/ChangeLog/ChangeLog-2.4.0
@@ -2668,8 +2668,8 @@ Wed Jul 6 07:11:27 2016 Shugo Maeda <shugo@ruby-lang.org>
Tue Jul 5 20:49:30 2016 SHIBATA Hiroshi <hsbt@ruby-lang.org>
* ext/json/*, test/json/*: Update json-2.0.1.
- Changes of 2.0.0: https://github.com/flori/json/blob/f679ebd0c69a94e3e70a897ac9a229f5779c2ee1/CHANGES.md#2015-09-11-200
- Changes of 2.0.1: https://github.com/flori/json/blob/f679ebd0c69a94e3e70a897ac9a229f5779c2ee1/CHANGES.md#2016-07-01-201
+ Changes of 2.0.0: https://github.com/ruby/json/blob/f679ebd0c69a94e3e70a897ac9a229f5779c2ee1/CHANGES.md#2015-09-11-200
+ Changes of 2.0.1: https://github.com/ruby/json/blob/f679ebd0c69a94e3e70a897ac9a229f5779c2ee1/CHANGES.md#2016-07-01-201
[Feature #12542][ruby-dev:49706][fix GH-1395]
Tue Jul 5 19:39:49 2016 Naohisa Goto <ngotogenome@gmail.com>
diff --git a/doc/NEWS/NEWS-3.0.0.md b/doc/NEWS/NEWS-3.0.0.md
index bdbd47327b..9fbaf504b4 100644
--- a/doc/NEWS/NEWS-3.0.0.md
+++ b/doc/NEWS/NEWS-3.0.0.md
@@ -367,11 +367,11 @@ Outstanding ones only.
* Fiber.blocking? tells whether the current execution context is
blocking. [[Feature #16786]]
+* Thread
+
* 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]]
@@ -741,7 +741,7 @@ end
foo(42)
```
-```
+```console
$ typeprof test.rb
# Classes
class Object
diff --git a/doc/NEWS/NEWS-3.1.0.md b/doc/NEWS/NEWS-3.1.0.md
index fe292fc414..686003894e 100644
--- a/doc/NEWS/NEWS-3.1.0.md
+++ b/doc/NEWS/NEWS-3.1.0.md
@@ -552,7 +552,7 @@ Example: `title = json[:article][:title]`
If `json` is nil, it shows:
-```
+```console
$ ruby test.rb
test.rb:2:in `<main>': undefined method `[]' for nil:NilClass (NoMethodError)
@@ -562,7 +562,7 @@ title = json[:article][:title]
If `json[:article]` returns nil, it shows:
-```
+```console
$ ruby test.rb
test.rb:2:in `<main>': undefined method `[]' for nil:NilClass (NoMethodError)
diff --git a/doc/NEWS/NEWS-3.2.0.md b/doc/NEWS/NEWS-3.2.0.md
index 33a7b85c47..3a48c1964d 100644
--- a/doc/NEWS/NEWS-3.2.0.md
+++ b/doc/NEWS/NEWS-3.2.0.md
@@ -623,13 +623,13 @@ The following deprecated methods are removed.
Psych and fiddle supported the static build with specific version of libyaml
and libffi sources. You can build psych with libyaml-0.2.5 like this.
- ```bash
+ ```console
$ ./configure --with-libyaml-source-dir=/path/to/libyaml-0.2.5
```
And you can build fiddle with libffi-3.4.4 like this.
- ```bash
+ ```console
$ ./configure --with-libffi-source-dir=/path/to/libffi-3.4.4
```
diff --git a/doc/NEWS/NEWS-3.4.0.md b/doc/NEWS/NEWS-3.4.0.md
new file mode 100644
index 0000000000..e9cc3a9569
--- /dev/null
+++ b/doc/NEWS/NEWS-3.4.0.md
@@ -0,0 +1,962 @@
+# NEWS for Ruby 3.4.0
+
+This document is a list of user-visible feature changes
+since the **3.3.0** release, except for bug fixes.
+
+Note that each entry is kept to a minimum, see links for details.
+
+## Language changes
+
+* `it` is added to reference a block parameter. [[Feature #18980]]
+
+* String literals in files without a `frozen_string_literal` comment now emit a deprecation warning
+ when they are mutated.
+ These warnings can be enabled with `-W:deprecated` or by setting `Warning[:deprecated] = true`.
+ To disable this change, you can run Ruby with the `--disable-frozen-string-literal`
+ command line argument. [[Feature #20205]]
+
+ * `String#+@` now duplicates when mutating the string would emit
+ a deprecation warning, offered as a replacement for the
+ `str.dup if str.frozen?` pattern.
+
+* Keyword splatting `nil` when calling methods is now supported.
+ `**nil` is treated similarly to `**{}`, passing no keywords,
+ and not calling any conversion methods. [[Bug #20064]]
+
+* Block passing is no longer allowed in index assignment
+ (e.g. `a[0, &b] = 1`). [[Bug #19918]]
+
+* Keyword arguments are no longer allowed in index assignment
+ (e.g. `a[0, kw: 1] = 2`). [[Bug #20218]]
+
+* The toplevel name `::Ruby` is reserved now, and the definition will be warned
+ when `Warning[:deprecated]`. [[Feature #20884]]
+
+## Core classes updates
+
+Note: We're only listing outstanding class updates.
+
+
+* Array
+
+ * `Array#fetch_values` was added. [[Feature #20702]]
+
+* Exception
+
+ * `Exception#set_backtrace` now accepts arrays of `Thread::Backtrace::Location`.
+ `Kernel#raise`, `Thread#raise` and `Fiber#raise` also accept this new format. [[Feature #13557]]
+
+* Fiber::Scheduler
+
+ * An optional `Fiber::Scheduler#blocking_operation_wait` hook allows blocking operations to be moved out of the
+ event loop in order to reduce latency and improve multi-core processor utilization. [[Feature #20876]]
+
+* GC
+
+ * `GC.config` added to allow setting configuration variables on the Garbage
+ Collector. [[Feature #20443]]
+
+ * GC configuration parameter `rgengc_allow_full_mark` introduced. When `false`
+ GC will only mark young objects. Default is `true`. [[Feature #20443]]
+
+* Hash
+
+ * `Hash.new` now accepts an optional `capacity:` argument, to preallocate the hash with a given capacity.
+ This can improve performance when building large hashes incrementally by saving on reallocation and
+ rehashing of keys. [[Feature #19236]]
+
+* IO::Buffer
+
+ * `IO::Buffer#copy` can release the GVL, allowing other threads to run while copying data. [[Feature #20902]]
+
+* Integer
+
+ * `Integer#**` used to return `Float::INFINITY` when the return value is large, but now returns an `Integer`.
+ If the return value is extremely large, it raises an exception.
+ [[Feature #20811]]
+
+* MatchData
+
+ * `MatchData#bytebegin` and `MatchData#byteend` have been added. [[Feature #20576]]
+
+* Object
+
+ * `Object#singleton_method` now returns methods in modules prepended to or included in the
+ receiver's singleton class. [[Bug #20620]]
+
+ ```rb
+ o = Object.new
+ o.extend(Module.new{def a = 1})
+ o.singleton_method(:a).call #=> 1
+ ```
+
+* Ractor
+
+ * `require` in Ractor is allowed. The requiring process will be run on
+ the main Ractor.
+ `Ractor._require(feature)` is added to run requiring process on the
+ main Ractor.
+ [[Feature #20627]]
+
+ * `Ractor.main?` is added. [[Feature #20627]]
+
+ * `Ractor.[]` and `Ractor.[]=` are added to access the ractor local storage
+ of the current Ractor. [[Feature #20715]]
+
+ * `Ractor.store_if_absent(key){ init }` is added to initialize ractor local
+ variables in thread-safety. [[Feature #20875]]
+
+* Range
+
+ * `Range#size` now raises `TypeError` if the range is not iterable. [[Misc #18984]]
+ * `Range#step` now consistently has a semantics of iterating by using `+` operator
+ for all types, not only numerics. [[Feature #18368]]
+
+ ```ruby
+ (Time.utc(2022, 2, 24)..).step(24*60*60).take(3)
+ #=> [2022-02-24 00:00:00 UTC, 2022-02-25 00:00:00 UTC, 2022-02-26 00:00:00 UTC]
+ ```
+
+* Rational
+
+ * `Rational#**` used to return `Float::INFINITY` or `Float::NAN`
+ when the numerator of the return value is large, but now returns an `Rational`.
+ If it is extremely large, it raises an exception. [[Feature #20811]]
+
+* RubyVM::AbstractSyntaxTree
+
+ * Add `RubyVM::AbstractSyntaxTree::Node#locations` method which returns location objects
+ associated with the AST node. [[Feature #20624]]
+ * Add `RubyVM::AbstractSyntaxTree::Location` class which holds location information. [[Feature #20624]]
+
+
+* String
+
+ * `String#append_as_bytes` was added to more easily and efficiently work with binary buffers and protocols.
+ It directly concatenate the arguments into the string without any encoding validation or conversion.
+ [[Feature #20594]]
+
+* Symbol
+
+ * The string returned by `Symbol#to_s` now emits a deprecation warning when mutated, and will be
+ frozen in a future version of Ruby.
+ These warnings can be enabled with `-W:deprecated` or by setting `Warning[:deprecated] = true`.
+ [[Feature #20350]]
+
+* Time
+
+ * On Windows, now `Time#zone` encodes the system timezone name in UTF-8
+ instead of the active code page, if it contains non-ASCII characters.
+ [[Bug #20929]]
+
+ * `Time#xmlschema`, and its `Time#iso8601` alias have been moved into the core Time
+ class while previously it was an extension provided by the `time` gem. [[Feature #20707]]
+
+* Warning
+
+ * Add `Warning.categories` method which returns a list of possible warning categories.
+ [[Feature #20293]]
+
+## Stdlib updates
+
+We only list stdlib changes that are notable feature changes.
+
+* RubyGems
+
+ * Add `--attestation` option to gem push. It enabled to store signature of build artifact to sigstore.dev.
+
+* Bundler
+
+ * Add a `lockfile_checksums` configuration to include checksums in fresh lockfiles.
+ * Add bundle lock `--add-checksums` to add checksums to an existing lockfile.
+
+* JSON
+
+ * Performance improvements `JSON.parse` about 1.5 times faster than json-2.7.x.
+
+* Tempfile
+
+ * The keyword argument `anonymous: true` is implemented for Tempfile.create.
+ `Tempfile.create(anonymous: true)` removes the created temporary file immediately.
+ So applications don't need to remove the file.
+ [[Feature #20497]]
+
+* win32/sspi.rb
+
+ * This library is now extracted from the Ruby repository to [ruby/net-http-sspi].
+ [[Feature #20775]]
+
+* Socket
+
+ * `Socket::ResolutionError` and `Socket::ResolutionError#error_code` was added.
+ [[Feature #20018]]
+
+* IRB
+
+ * Interactive method completion is now improved with type information by default.
+ [[Feature #20778]]
+
+Other changes are listed in the following sections. we also listed release history from the previous bundled version that is Ruby 3.3.0 if it has GitHub releases.
+
+The following default gem is added.
+
+* win32-registry 0.1.0
+
+The following default gems are updated.
+
+* RubyGems 3.6.2
+* benchmark 0.4.0
+* bundler 2.6.2
+* date 3.4.1
+* delegate 0.4.0
+* did_you_mean 2.0.0
+* digest 3.2.0
+* erb 4.0.4
+* error_highlight 0.7.0
+* etc 1.4.5
+* fcntl 1.2.0
+* fiddle 1.1.6
+* fileutils 1.7.3
+* io-console 0.8.0
+* io-nonblock 0.3.1
+* ipaddr 1.2.7
+* irb 1.14.3
+* json 2.9.1
+* logger 1.6.4
+* net-http 0.6.0
+* open-uri 0.5.0
+* openssl 3.3.0
+* optparse 0.6.0
+* ostruct 0.6.1
+* pathname 0.4.0
+* pp 0.6.2
+* prism 1.2.0
+* pstore 0.1.4
+* psych 5.2.2
+* rdoc 6.10.0
+* reline 0.6.0
+* resolv 0.6.0
+* securerandom 0.4.1
+* set 1.1.1
+* shellwords 0.2.2
+* singleton 0.3.0
+* stringio 3.1.2
+* strscan 3.1.2
+* syntax_suggest 2.0.2
+* tempfile 0.3.1
+* time 0.4.1
+* timeout 0.4.3
+* tmpdir 0.3.1
+* uri 1.0.2
+* win32ole 1.9.1
+* yaml 0.4.0
+* zlib 3.2.1
+
+ * 3.5.3 to [v3.5.4][RubyGems-v3.5.4], [v3.5.5][RubyGems-v3.5.5], [v3.5.6][RubyGems-v3.5.6], [v3.5.7][RubyGems-v3.5.7], [v3.5.8][RubyGems-v3.5.8], [v3.5.9][RubyGems-v3.5.9], [v3.5.10][RubyGems-v3.5.10], [v3.5.11][RubyGems-v3.5.11], [v3.5.12][RubyGems-v3.5.12], [v3.5.13][RubyGems-v3.5.13], [v3.5.14][RubyGems-v3.5.14], [v3.5.15][RubyGems-v3.5.15], [v3.5.16][RubyGems-v3.5.16], [v3.5.17][RubyGems-v3.5.17], [v3.5.18][RubyGems-v3.5.18], [v3.5.19][RubyGems-v3.5.19], [v3.5.20][RubyGems-v3.5.20], [v3.5.21][RubyGems-v3.5.21], [v3.5.22][RubyGems-v3.5.22], [v3.5.23][RubyGems-v3.5.23], [v3.6.0][RubyGems-v3.6.0], [v3.6.1][RubyGems-v3.6.1], [v3.6.2][RubyGems-v3.6.2]
+* [benchmark][benchmark] 0.4.0
+ * 0.3.0 to [v0.4.0][benchmark-v0.4.0]
+* [bundler][bundler] 2.6.2
+ * 2.5.3 to [v2.5.4][bundler-v2.5.4], [v2.5.5][bundler-v2.5.5], [v2.5.6][bundler-v2.5.6], [v2.5.7][bundler-v2.5.7], [v2.5.8][bundler-v2.5.8], [v2.5.9][bundler-v2.5.9], [v2.5.10][bundler-v2.5.10], [v2.5.11][bundler-v2.5.11], [v2.5.12][bundler-v2.5.12], [v2.5.13][bundler-v2.5.13], [v2.5.14][bundler-v2.5.14], [v2.5.15][bundler-v2.5.15], [v2.5.16][bundler-v2.5.16], [v2.5.17][bundler-v2.5.17], [v2.5.18][bundler-v2.5.18], [v2.5.19][bundler-v2.5.19], [v2.5.20][bundler-v2.5.20], [v2.5.21][bundler-v2.5.21], [v2.5.22][bundler-v2.5.22], [v2.5.23][bundler-v2.5.23], [v2.6.0][bundler-v2.6.0], [v2.6.1][bundler-v2.6.1], [v2.6.2][bundler-v2.6.2]
+* [date][date] 3.4.1
+ * 3.3.4 to [v3.4.0][date-v3.4.0], [v3.4.1][date-v3.4.1]
+* [delegate][delegate] 0.4.0
+ * 0.3.1 to [v0.4.0][delegate-v0.4.0]
+* [did_you_mean][did_you_mean] 2.0.0
+ * 1.6.3 to [v2.0.0][did_you_mean-v2.0.0]
+* [digest][digest] 3.2.0
+ * 3.1.1 to [v3.2.0.pre0][digest-v3.2.0.pre0], [v3.2.0][digest-v3.2.0]
+* [erb][erb] 4.0.4
+ * 4.0.3 to [v4.0.4][erb-v4.0.4]
+* [error_highlight][error_highlight] 0.7.0
+ * 0.6.0 to [v0.7.0][error_highlight-v0.7.0]
+* [etc][etc] 1.4.5
+ * 1.4.3 to [v1.4.4][etc-v1.4.4], [v1.4.5][etc-v1.4.5]
+* [fcntl][fcntl] 1.2.0
+ * 1.1.0 to [v1.2.0][fcntl-v1.2.0]
+* [fiddle][fiddle] 1.1.6
+ * 1.1.2 to [v1.1.3][fiddle-v1.1.3], [v1.1.4][fiddle-v1.1.4], [v1.1.5][fiddle-v1.1.5], [v1.1.6][fiddle-v1.1.6]
+* [fileutils][fileutils] 1.7.3
+ * 1.7.2 to [v1.7.3][fileutils-v1.7.3]
+* [io-console][io-console] 0.8.0
+ * 0.7.1 to [v0.7.2][io-console-v0.7.2], [v0.8.0.beta1][io-console-v0.8.0.beta1], [v0.8.0][io-console-v0.8.0]
+* [io-nonblock][io-nonblock] 0.3.1
+ * 0.3.0 to [v0.3.1][io-nonblock-v0.3.1]
+* [ipaddr][ipaddr] 1.2.7
+ * 1.2.6 to [v1.2.7][ipaddr-v1.2.7]
+* [irb][irb] 1.14.3
+ * 1.11.0 to [v1.11.1][irb-v1.11.1], [v1.11.2][irb-v1.11.2], [v1.12.0][irb-v1.12.0], [v1.13.0][irb-v1.13.0], [v1.13.1][irb-v1.13.1], [v1.13.2][irb-v1.13.2], [v1.14.0][irb-v1.14.0], [v1.14.1][irb-v1.14.1], [v1.14.2][irb-v1.14.2], [v1.14.3][irb-v1.14.3]
+* [json][json] 2.9.1
+ * 2.7.1 to [v2.7.2][json-v2.7.2], [v2.7.3.rc1][json-v2.7.3.rc1], [v2.7.3][json-v2.7.3], [v2.7.4][json-v2.7.4], [v2.7.5][json-v2.7.5], [v2.7.6][json-v2.7.6], [v2.8.0][json-v2.8.0], [v2.8.1][json-v2.8.1], [v2.8.2][json-v2.8.2], [v2.9.0][json-v2.9.0], [v2.9.1][json-v2.9.1]
+* [logger][logger] 1.6.4
+ * 1.6.0 to [v1.6.1][logger-v1.6.1], [v1.6.2][logger-v1.6.2], [v1.6.3][logger-v1.6.3], [v1.6.4][logger-v1.6.4]
+* [net-http][net-http] 0.6.0
+ * 0.4.0 to [v0.4.1][net-http-v0.4.1], [v0.5.0][net-http-v0.5.0], [v0.6.0][net-http-v0.6.0]
+* [open-uri][open-uri] 0.5.0
+ * 0.4.1 to [v0.5.0][open-uri-v0.5.0]
+* [optparse][optparse] 0.6.0
+ * 0.4.0 to [v0.5.0][optparse-v0.5.0], [v0.6.0][optparse-v0.6.0]
+* [ostruct][ostruct] 0.6.1
+ * 0.6.0 to [v0.6.1][ostruct-v0.6.1]
+* [pathname][pathname] 0.4.0
+ * 0.3.0 to [v0.4.0][pathname-v0.4.0]
+* [pp][pp] 0.6.2
+ * 0.5.0 to [v0.6.0][pp-v0.6.0], [v0.6.1][pp-v0.6.1], [v0.6.2][pp-v0.6.2]
+* [prism][prism] 1.2.0
+ * 0.19.0 to [v0.20.0][prism-v0.20.0], [v0.21.0][prism-v0.21.0], [v0.22.0][prism-v0.22.0], [v0.23.0][prism-v0.23.0], [v0.24.0][prism-v0.24.0], [v0.25.0][prism-v0.25.0], [v0.26.0][prism-v0.26.0], [v0.27.0][prism-v0.27.0], [v0.28.0][prism-v0.28.0], [v0.29.0][prism-v0.29.0], [v0.30.0][prism-v0.30.0], [v1.0.0][prism-v1.0.0], [v1.1.0][prism-v1.1.0], [v1.2.0][prism-v1.2.0]
+* [pstore][pstore] 0.1.4
+ * 0.1.3 to [v0.1.4][pstore-v0.1.4]
+* [psych][psych] 5.2.2
+ * 5.1.2 to [v5.2.0.beta1][psych-v5.2.0.beta1], [v5.2.0.beta2][psych-v5.2.0.beta2], [v5.2.0.beta3][psych-v5.2.0.beta3], [v5.2.0.beta4][psych-v5.2.0.beta4], [v5.2.0.beta5][psych-v5.2.0.beta5], [v5.2.0.beta6][psych-v5.2.0.beta6], [v5.2.0.beta7][psych-v5.2.0.beta7], [v5.2.0][psych-v5.2.0], [v5.2.1][psych-v5.2.1], [v5.2.2][psych-v5.2.2]
+* [rdoc][rdoc] 6.10.0
+ * 6.6.2 to [v6.7.0][rdoc-v6.7.0], [v6.8.0][rdoc-v6.8.0], [v6.8.1][rdoc-v6.8.1], [v6.9.0][rdoc-v6.9.0], [v6.9.1][rdoc-v6.9.1], [v6.10.0][rdoc-v6.10.0]
+* [reline][reline] 0.6.0
+ * 0.4.1 to [v0.4.2][reline-v0.4.2], [v0.4.3][reline-v0.4.3], [v0.5.0.pre.1][reline-v0.5.0.pre.1], [v0.5.0][reline-v0.5.0], [v0.5.1][reline-v0.5.1], [v0.5.2][reline-v0.5.2], [v0.5.3][reline-v0.5.3], [v0.5.4][reline-v0.5.4], [v0.5.5][reline-v0.5.5], [v0.5.6][reline-v0.5.6], [v0.5.7][reline-v0.5.7], [v0.5.8][reline-v0.5.8], [v0.5.9][reline-v0.5.9], [v0.5.10][reline-v0.5.10], [v0.5.11][reline-v0.5.11], [v0.5.12][reline-v0.5.12], [v0.6.0][reline-v0.6.0]
+* [resolv][resolv] 0.6.0
+ * 0.3.0 to [v0.4.0][resolv-v0.4.0], [v0.5.0][resolv-v0.5.0], [v0.6.0][resolv-v0.6.0]
+* [securerandom][securerandom] 0.4.1
+ * 0.3.1 to [v0.3.2][securerandom-v0.3.2], [v0.4.0][securerandom-v0.4.0], [v0.4.1][securerandom-v0.4.1]
+* [set][set] 1.1.1
+ * 1.1.0 to [v1.1.1][set-v1.1.1]
+* [shellwords][shellwords] 0.2.2
+ * 0.2.0 to [v0.2.1][shellwords-v0.2.1], [v0.2.2][shellwords-v0.2.2]
+* [singleton][singleton] 0.3.0
+ * 0.2.0 to [v0.3.0][singleton-v0.3.0]
+* [stringio][stringio] 3.1.2
+ * 3.1.0 to [v3.1.1][stringio-v3.1.1], [v3.1.2][stringio-v3.1.2]
+* [strscan][strscan] 3.1.2
+ * 3.0.7 to [v3.0.8][strscan-v3.0.8], [v3.0.9][strscan-v3.0.9], [v3.1.0][strscan-v3.1.0], [v3.1.1][strscan-v3.1.1], [v3.1.2][strscan-v3.1.2]
+* [syntax_suggest][syntax_suggest] 2.0.2
+ * 2.0.0 to [v2.0.1][syntax_suggest-v2.0.1], [v2.0.2][syntax_suggest-v2.0.2]
+* [tempfile][tempfile] 0.3.1
+ * 0.2.1 to [v0.3.0][tempfile-v0.3.0], [v0.3.1][tempfile-v0.3.1]
+* [time][time] 0.4.1
+ * 0.3.0 to [v0.4.0][time-v0.4.0], [v0.4.1][time-v0.4.1]
+* [timeout][timeout] 0.4.3
+ * 0.4.1 to [v0.4.2][timeout-v0.4.2], [v0.4.3][timeout-v0.4.3]
+* [tmpdir][tmpdir] 0.3.1
+ * 0.2.0 to [v0.3.0][tmpdir-v0.3.0], [v0.3.1][tmpdir-v0.3.1]
+* [uri][uri] 1.0.2
+ * 0.13.0 to [v0.13.1][uri-v0.13.1], [v1.0.0][uri-v1.0.0], [v1.0.1][uri-v1.0.1], [v1.0.2][uri-v1.0.2]
+* [win32ole][win32ole] 1.9.1
+ * 1.8.10 to [v1.9.0][win32ole-v1.9.0], [v1.9.1][win32ole-v1.9.1]
+* [yaml][yaml] 0.4.0
+ * 0.3.0 to [v0.4.0][yaml-v0.4.0]
+* [zlib][zlib] 3.2.1
+ * 3.1.0 to [v3.1.1][zlib-v3.1.1], [v3.2.0][zlib-v3.2.0], [v3.2.1][zlib-v3.2.1]
+
+The following bundled gem is added.
+
+* [repl_type_completor][repl_type_completor] 0.1.9
+
+The following bundled gems are updated.
+
+* [minitest][minitest] 5.25.4
+ * 5.20.0 to [v5.25.4][minitest-v5.25.4]
+* [power_assert][power_assert] 2.0.5
+ * 2.0.3 to [v2.0.4][power_assert-v2.0.4], [v2.0.5][power_assert-v2.0.5]
+* [rake][rake] 13.2.1
+ * 13.1.0 to [v13.2.0][rake-v13.2.0], [v13.2.1][rake-v13.2.1]
+* [test-unit][test-unit] 3.6.7
+ * 3.6.1 to [3.6.2][test-unit-3.6.2], [3.6.3][test-unit-3.6.3], [3.6.4][test-unit-3.6.4], [3.6.5][test-unit-3.6.5], [3.6.6][test-unit-3.6.6], [3.6.7][test-unit-3.6.7]
+* [rexml][rexml] 3.4.0
+ * 3.2.6 to [v3.2.7][rexml-v3.2.7], [v3.2.8][rexml-v3.2.8], [v3.2.9][rexml-v3.2.9], [v3.3.0][rexml-v3.3.0], [v3.3.1][rexml-v3.3.1], [v3.3.2][rexml-v3.3.2], [v3.3.3][rexml-v3.3.3], [v3.3.4][rexml-v3.3.4], [v3.3.5][rexml-v3.3.5], [v3.3.6][rexml-v3.3.6], [v3.3.7][rexml-v3.3.7], [v3.3.8][rexml-v3.3.8], [v3.3.9][rexml-v3.3.9], [v3.4.0][rexml-v3.4.0]
+* [rss][rss] 0.3.1
+ * 0.3.0 to [0.3.1][rss-0.3.1]
+* [net-ftp][net-ftp] 0.3.8
+ * 0.3.3 to [v0.3.4][net-ftp-v0.3.4], [v0.3.5][net-ftp-v0.3.5], [v0.3.6][net-ftp-v0.3.6], [v0.3.7][net-ftp-v0.3.7], [v0.3.8][net-ftp-v0.3.8]
+* [net-imap][net-imap] 0.5.4
+ * 0.4.9 to [v0.4.9.1][net-imap-v0.4.9.1], [v0.4.10][net-imap-v0.4.10], [v0.4.11][net-imap-v0.4.11], [v0.4.12][net-imap-v0.4.12], [v0.4.13][net-imap-v0.4.13], [v0.4.14][net-imap-v0.4.14], [v0.4.15][net-imap-v0.4.15], [v0.4.16][net-imap-v0.4.16], [v0.4.17][net-imap-v0.4.17], [v0.5.0][net-imap-v0.5.0], [v0.4.18][net-imap-v0.4.18], [v0.5.1][net-imap-v0.5.1], [v0.5.2][net-imap-v0.5.2], [v0.5.3][net-imap-v0.5.3], [v0.5.4][net-imap-v0.5.4]
+* [net-smtp][net-smtp] 0.5.0
+ * 0.4.0 to [v0.4.0.1][net-smtp-v0.4.0.1], [v0.5.0][net-smtp-v0.5.0]
+* [prime][prime] 0.1.3
+ * 0.1.2 to [v0.1.3][prime-v0.1.3]
+* [rbs][rbs] 3.8.0
+ * 3.4.0 to [v3.4.1][rbs-v3.4.1], [v3.4.2][rbs-v3.4.2], [v3.4.3][rbs-v3.4.3], [v3.4.4][rbs-v3.4.4], [v3.5.0.pre.1][rbs-v3.5.0.pre.1], [v3.5.0.pre.2][rbs-v3.5.0.pre.2], [v3.5.0][rbs-v3.5.0], [v3.5.1][rbs-v3.5.1], [v3.5.2][rbs-v3.5.2], [v3.5.3][rbs-v3.5.3], [v3.6.0.dev.1][rbs-v3.6.0.dev.1], [v3.6.0.pre.1][rbs-v3.6.0.pre.1], [v3.6.0.pre.2][rbs-v3.6.0.pre.2], [v3.6.0.pre.3][rbs-v3.6.0.pre.3], [v3.6.0][rbs-v3.6.0], [v3.6.1][rbs-v3.6.1], [v3.7.0.dev.1][rbs-v3.7.0.dev.1], [v3.7.0.pre.1][rbs-v3.7.0.pre.1], [v3.7.0][rbs-v3.7.0], [v3.8.0.pre.1][rbs-v3.8.0.pre.1] [v3.8.0][rbs-v3.8.0]
+* [typeprof][typeprof] 0.30.1
+ * 0.21.9 to [v0.30.1][typeprof-v0.30.1]
+* [debug][debug] 1.10.0
+ * 1.9.1 to [v1.9.2][debug-v1.9.2], [v1.10.0][debug-v1.10.0]
+* [racc][racc] 1.8.1
+ * 1.7.3 to [v1.8.0][racc-v1.8.0], [v1.8.1][racc-v1.8.1]
+
+The following bundled gems are promoted from default gems.
+
+* [mutex_m][mutex_m] 0.3.0
+ * 0.2.0 to [v0.3.0][mutex_m-v0.3.0]
+* [getoptlong][getoptlong] 0.2.1
+* [base64][base64] 0.2.0
+* [bigdecimal][bigdecimal] 3.1.8
+ * 3.1.5 to [v3.1.6][bigdecimal-v3.1.6], [v3.1.7][bigdecimal-v3.1.7], [v3.1.8][bigdecimal-v3.1.8]
+* [observer][observer] 0.1.2
+* [abbrev][abbrev] 0.1.2
+* [resolv-replace][resolv-replace] 0.1.1
+* [rinda][rinda] 0.2.0
+* [drb][drb] 2.2.1
+ * 2.2.0 to [v2.2.1][drb-v2.2.1]
+* [nkf][nkf] 0.2.0
+ * 0.1.3 to [v0.2.0][nkf-v0.2.0]
+* [syslog][syslog] 0.2.0
+ * 0.1.2 to [v0.2.0][syslog-v0.2.0]
+* [csv][csv] 3.3.2
+ * 3.2.8 to [v3.2.9][csv-v3.2.9], [v3.3.0][csv-v3.3.0], [v3.3.1][csv-v3.3.1], [v3.3.2][csv-v3.3.2]
+
+## Supported platforms
+
+## Compatibility issues
+
+* Error messages and backtrace displays have been changed.
+
+ * Use a single quote instead of a backtick as an opening quote. [[Feature #16495]]
+ * Display a class name before a method name (only when the class has a permanent name). [[Feature #19117]]
+ * Extra `rescue`/`ensure` frames are no longer available on the backtrace. [[Feature #20275]]
+ * `Kernel#caller`, `Thread::Backtrace::Location`’s methods, etc. are also changed accordingly.
+
+ Old:
+ ```
+ test.rb:1:in `foo': undefined method `time' for an instance of Integer
+ from test.rb:2:in `<main>'
+ ```
+
+ New:
+ ```
+ test.rb:1:in 'Object#foo': undefined method 'time' for an instance of Integer
+ from test.rb:2:in '<main>'
+ ```
+
+* `Hash#inspect` rendering have been changed. [[Bug #20433]]
+
+ * Symbol keys are displayed using the modern symbol key syntax: `"{user: 1}"`
+ * Other keys now have spaces around `=>`: `'{"user" => 1}'`, while previously they didn't: `'{"user"=>1}'`
+
+* `Kernel#Float()` now accepts a decimal string with decimal part omitted. [[Feature #20705]]
+
+ ```rb
+ Float("1.") #=> 1.0 (previously, an ArgumentError was raised)
+ Float("1.E-1") #=> 0.1 (previously, an ArgumentError was raised)
+ ```
+
+* `String#to_f` now accepts a decimal string with decimal part omitted. [[Feature #20705]]
+ Note that the result changes when an exponent is specified.
+
+ ```rb
+ "1.".to_f #=> 1.0
+ "1.E-1".to_f #=> 0.1 (previously, 1.0 was returned)
+ ```
+
+* `Refinement#refined_class` has been removed. [[Feature #19714]]
+
+## Stdlib compatibility issues
+
+* DidYouMean
+
+ * `DidYouMean::SPELL_CHECKERS[]=` and `DidYouMean::SPELL_CHECKERS.merge!` are removed.
+
+* Net::HTTP
+
+ * Removed the following deprecated constants:
+ * `Net::HTTP::ProxyMod`
+ * `Net::NetPrivate::HTTPRequest`
+ * `Net::HTTPInformationCode`
+ * `Net::HTTPSuccessCode`
+ * `Net::HTTPRedirectionCode`
+ * `Net::HTTPRetriableCode`
+ * `Net::HTTPClientErrorCode`
+ * `Net::HTTPFatalErrorCode`
+ * `Net::HTTPServerErrorCode`
+ * `Net::HTTPResponseReceiver`
+ * `Net::HTTPResponceReceiver`
+
+ These constants were deprecated from 2012.
+
+* Timeout
+
+ * Reject negative values for `Timeout.timeout`. [[Bug #20795]]
+
+* URI
+
+ * Switched default parser to RFC 3986 compliant from RFC 2396 compliant.
+ [[Bug #19266]]
+
+## C API updates
+
+* `rb_newobj` and `rb_newobj_of` (and corresponding macros `RB_NEWOBJ`, `RB_NEWOBJ_OF`, `NEWOBJ`, `NEWOBJ_OF`) have been removed. [[Feature #20265]]
+* Removed deprecated function `rb_gc_force_recycle`. [[Feature #18290]]
+
+## Implementation improvements
+
+* The default parser is now Prism.
+ To use the conventional parser, use the command-line argument `--parser=parse.y`.
+ [[Feature #20564]]
+
+* Happy Eyeballs version 2 (RFC8305), an algorithm that ensures faster and more reliable connections
+ by attempting IPv6 and IPv4 concurrently, is used in `Socket.tcp` and `TCPSocket.new`.
+ To disable it globally, set the environment variable `RUBY_TCP_NO_FAST_FALLBACK=1` or
+ call `Socket.tcp_fast_fallback=false`.
+ Or to disable it on a per-method basis, use the keyword argument `fast_fallback: false`.
+ [[Feature #20108]] [[Feature #20782]]
+
+* Alternative garbage collector (GC) implementations can be loaded dynamically
+ through the modular garbage collector feature. To enable this feature,
+ configure Ruby with `--with-modular-gc` at build time. GC libraries can be
+ loaded at runtime using the environment variable `RUBY_GC_LIBRARY`.
+ [[Feature #20351]]
+
+* Ruby's built-in garbage collector has been split into a separate file at
+ `gc/default/default.c` and interacts with Ruby using an API defined in
+ `gc/gc_impl.h`. The built-in garbage collector can now also be built as a
+ library using `make modular-gc MODULAR_GC=default` and enabled using the
+ environment variable `RUBY_GC_LIBRARY=default`. [[Feature #20470]]
+
+* An experimental GC library is provided based on [MMTk](https://www.mmtk.io/).
+ This GC library can be built using `make modular-gc MODULAR_GC=mmtk` and
+ enabled using the environment variable `RUBY_GC_LIBRARY=mmtk`. This requires
+ the Rust toolchain on the build machine. [[Feature #20860]]
+
+### YJIT
+
+#### New features
+
+* Command-line options
+ * `--yjit-mem-size` introduces a unified memory limit (default 128MiB) to track total YJIT memory usage,
+ providing a more intuitive alternative to the old `--yjit-exec-mem-size` option.
+ * `--yjit-trace-exits=COUNTER` allows tracing of counted exits and fallbacks.
+ * `--yjit-perf=codegen` allows profiling of JIT code based on YJIT's codegen functions.
+ * `--yjit-log` enables a compilation log to track what gets compiled.
+* Ruby API
+ * `RubyVM::YJIT.enable(log: true)` also enables a compilation log.
+ * `RubyVM::YJIT.log` provides access to the tail of the compilation log at run-time.
+* YJIT stats
+ * `RubyVM::YJIT.runtime_stats` now always provides additional statistics on
+ invalidation, inlining, and metadata encoding.
+ * `RubyVM::YJIT.runtime_stats[:iseq_calls]` is added to profile non-inlined Ruby method calls.
+ * `RubyVM::YJIT.runtime_stats[:cfunc_calls]` is truncated to the top 20 entries for better performance.
+
+#### New optimizations
+
+* Compressed context reduces memory needed to store YJIT metadata
+* Allocate registers for local variables and Ruby method arguments
+* When YJIT is enabled, use more Core primitives written in Ruby:
+ * `Array#each`, `Array#select`, `Array#map` rewritten in Ruby for better performance [[Feature #20182]].
+* Ability to inline small/trivial methods such as:
+ * Empty methods
+ * Methods returning a constant
+ * Methods returning `self`
+ * Methods directly returning an argument
+* Specialized codegen for many more runtime methods
+* Optimize `String#getbyte`, `String#setbyte` and other string methods
+* Optimize bitwise operations to speed up low-level bit/byte manipulation
+* Support shareable constants in multi-ractor mode
+* Various other incremental optimizations
+
+## Miscellaneous changes
+
+* Passing a block to a method which doesn't use the passed block will show
+ a warning on verbose mode (`-w`).
+ In connection with this, a new `strict_unused_block` warning category was introduced.
+ Turn them on with `-W:strict_unused_block` or `Warning[:strict_unused_block] = true`.
+ [[Feature #15554]]
+
+* Redefining some core methods that are specially optimized by the interpreter
+ and JIT like `String#freeze` or `Integer#+` now emits a performance class
+ warning (`-W:performance` or `Warning[:performance] = true`).
+ [[Feature #20429]]
+
+[Feature #13557]: https://bugs.ruby-lang.org/issues/13557
+[Feature #15554]: https://bugs.ruby-lang.org/issues/15554
+[Feature #16495]: https://bugs.ruby-lang.org/issues/16495
+[Feature #18290]: https://bugs.ruby-lang.org/issues/18290
+[Feature #18368]: https://bugs.ruby-lang.org/issues/18368
+[Feature #18980]: https://bugs.ruby-lang.org/issues/18980
+[Misc #18984]: https://bugs.ruby-lang.org/issues/18984
+[Feature #19117]: https://bugs.ruby-lang.org/issues/19117
+[Feature #19236]: https://bugs.ruby-lang.org/issues/19236
+[Bug #19266]: https://bugs.ruby-lang.org/issues/19266
+[Feature #19714]: https://bugs.ruby-lang.org/issues/19714
+[Bug #19918]: https://bugs.ruby-lang.org/issues/19918
+[Feature #20018]: https://bugs.ruby-lang.org/issues/20018
+[Bug #20064]: https://bugs.ruby-lang.org/issues/20064
+[Feature #20108]: https://bugs.ruby-lang.org/issues/20108
+[Feature #20182]: https://bugs.ruby-lang.org/issues/20182
+[Feature #20205]: https://bugs.ruby-lang.org/issues/20205
+[Bug #20218]: https://bugs.ruby-lang.org/issues/20218
+[Feature #20265]: https://bugs.ruby-lang.org/issues/20265
+[Feature #20275]: https://bugs.ruby-lang.org/issues/20275
+[Feature #20293]: https://bugs.ruby-lang.org/issues/20293
+[Feature #20350]: https://bugs.ruby-lang.org/issues/20350
+[Feature #20351]: https://bugs.ruby-lang.org/issues/20351
+[Feature #20429]: https://bugs.ruby-lang.org/issues/20429
+[Bug #20433]: https://bugs.ruby-lang.org/issues/20433
+[Feature #20443]: https://bugs.ruby-lang.org/issues/20443
+[Feature #20470]: https://bugs.ruby-lang.org/issues/20470
+[Feature #20497]: https://bugs.ruby-lang.org/issues/20497
+[Feature #20564]: https://bugs.ruby-lang.org/issues/20564
+[Feature #20576]: https://bugs.ruby-lang.org/issues/20576
+[Feature #20594]: https://bugs.ruby-lang.org/issues/20594
+[Bug #20620]: https://bugs.ruby-lang.org/issues/20620
+[Feature #20624]: https://bugs.ruby-lang.org/issues/20624
+[Feature #20627]: https://bugs.ruby-lang.org/issues/20627
+[Feature #20702]: https://bugs.ruby-lang.org/issues/20702
+[Feature #20705]: https://bugs.ruby-lang.org/issues/20705
+[Feature #20707]: https://bugs.ruby-lang.org/issues/20707
+[Feature #20715]: https://bugs.ruby-lang.org/issues/20715
+[Feature #20775]: https://bugs.ruby-lang.org/issues/20775
+[Feature #20778]: https://bugs.ruby-lang.org/issues/20778
+[Feature #20782]: https://bugs.ruby-lang.org/issues/20782
+[Bug #20795]: https://bugs.ruby-lang.org/issues/20795
+[Feature #20811]: https://bugs.ruby-lang.org/issues/20811
+[Feature #20860]: https://bugs.ruby-lang.org/issues/20860
+[Feature #20875]: https://bugs.ruby-lang.org/issues/20875
+[Feature #20876]: https://bugs.ruby-lang.org/issues/20876
+[Feature #20884]: https://bugs.ruby-lang.org/issues/20884
+[Feature #20902]: https://bugs.ruby-lang.org/issues/20902
+[Bug #20929]: https://bugs.ruby-lang.org/issues/20929
+[RubyGems-v3.5.4]: https://github.com/rubygems/rubygems/releases/tag/v3.5.4
+[RubyGems-v3.5.5]: https://github.com/rubygems/rubygems/releases/tag/v3.5.5
+[RubyGems-v3.5.6]: https://github.com/rubygems/rubygems/releases/tag/v3.5.6
+[RubyGems-v3.5.7]: https://github.com/rubygems/rubygems/releases/tag/v3.5.7
+[RubyGems-v3.5.8]: https://github.com/rubygems/rubygems/releases/tag/v3.5.8
+[RubyGems-v3.5.9]: https://github.com/rubygems/rubygems/releases/tag/v3.5.9
+[RubyGems-v3.5.10]: https://github.com/rubygems/rubygems/releases/tag/v3.5.10
+[RubyGems-v3.5.11]: https://github.com/rubygems/rubygems/releases/tag/v3.5.11
+[RubyGems-v3.5.12]: https://github.com/rubygems/rubygems/releases/tag/v3.5.12
+[RubyGems-v3.5.13]: https://github.com/rubygems/rubygems/releases/tag/v3.5.13
+[RubyGems-v3.5.14]: https://github.com/rubygems/rubygems/releases/tag/v3.5.14
+[RubyGems-v3.5.15]: https://github.com/rubygems/rubygems/releases/tag/v3.5.15
+[RubyGems-v3.5.16]: https://github.com/rubygems/rubygems/releases/tag/v3.5.16
+[RubyGems-v3.5.17]: https://github.com/rubygems/rubygems/releases/tag/v3.5.17
+[RubyGems-v3.5.18]: https://github.com/rubygems/rubygems/releases/tag/v3.5.18
+[RubyGems-v3.5.19]: https://github.com/rubygems/rubygems/releases/tag/v3.5.19
+[RubyGems-v3.5.20]: https://github.com/rubygems/rubygems/releases/tag/v3.5.20
+[RubyGems-v3.5.21]: https://github.com/rubygems/rubygems/releases/tag/v3.5.21
+[RubyGems-v3.5.22]: https://github.com/rubygems/rubygems/releases/tag/v3.5.22
+[RubyGems-v3.5.23]: https://github.com/rubygems/rubygems/releases/tag/v3.5.23
+[RubyGems-v3.6.0]: https://github.com/rubygems/rubygems/releases/tag/v3.6.0
+[RubyGems-v3.6.1]: https://github.com/rubygems/rubygems/releases/tag/v3.6.1
+[RubyGems-v3.6.2]: https://github.com/rubygems/rubygems/releases/tag/v3.6.2
+[benchmark-v0.4.0]: https://github.com/ruby/benchmark/releases/tag/v0.4.0
+[bundler-v2.5.4]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.4
+[bundler-v2.5.5]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.5
+[bundler-v2.5.6]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.6
+[bundler-v2.5.7]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.7
+[bundler-v2.5.8]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.8
+[bundler-v2.5.9]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.9
+[bundler-v2.5.10]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.10
+[bundler-v2.5.11]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.11
+[bundler-v2.5.12]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.12
+[bundler-v2.5.13]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.13
+[bundler-v2.5.14]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.14
+[bundler-v2.5.15]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.15
+[bundler-v2.5.16]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.16
+[bundler-v2.5.17]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.17
+[bundler-v2.5.18]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.18
+[bundler-v2.5.19]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.19
+[bundler-v2.5.20]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.20
+[bundler-v2.5.21]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.21
+[bundler-v2.5.22]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.22
+[bundler-v2.5.23]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.23
+[bundler-v2.6.0]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.6.0
+[bundler-v2.6.1]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.6.1
+[bundler-v2.6.2]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.6.2
+[date-v3.4.0]: https://github.com/ruby/date/releases/tag/v3.4.0
+[date-v3.4.1]: https://github.com/ruby/date/releases/tag/v3.4.1
+[delegate-v0.4.0]: https://github.com/ruby/delegate/releases/tag/v0.4.0
+[did_you_mean-v2.0.0]: https://github.com/ruby/did_you_mean/releases/tag/v2.0.0
+[digest-v3.2.0.pre0]: https://github.com/ruby/digest/releases/tag/v3.2.0.pre0
+[digest-v3.2.0]: https://github.com/ruby/digest/releases/tag/v3.2.0
+[erb-v4.0.4]: https://github.com/ruby/erb/releases/tag/v4.0.4
+[etc-v1.4.4]: https://github.com/ruby/etc/releases/tag/v1.4.4
+[etc-v1.4.5]: https://github.com/ruby/etc/releases/tag/v1.4.5
+[fcntl-v1.2.0]: https://github.com/ruby/fcntl/releases/tag/v1.2.0
+[fiddle-v1.1.3]: https://github.com/ruby/fiddle/releases/tag/v1.1.3
+[fiddle-v1.1.4]: https://github.com/ruby/fiddle/releases/tag/v1.1.4
+[fiddle-v1.1.5]: https://github.com/ruby/fiddle/releases/tag/v1.1.5
+[fiddle-v1.1.6]: https://github.com/ruby/fiddle/releases/tag/v1.1.6
+[fileutils-v1.7.3]: https://github.com/ruby/fileutils/releases/tag/v1.7.3
+[io-console-v0.7.2]: https://github.com/ruby/io-console/releases/tag/v0.7.2
+[io-console-v0.8.0.beta1]: https://github.com/ruby/io-console/releases/tag/v0.8.0.beta1
+[io-console-v0.8.0]: https://github.com/ruby/io-console/releases/tag/v0.8.0
+[io-nonblock-v0.3.1]: https://github.com/ruby/io-nonblock/releases/tag/v0.3.1
+[ipaddr-v1.2.7]: https://github.com/ruby/ipaddr/releases/tag/v1.2.7
+[irb-v1.11.1]: https://github.com/ruby/irb/releases/tag/v1.11.1
+[irb-v1.11.2]: https://github.com/ruby/irb/releases/tag/v1.11.2
+[irb-v1.12.0]: https://github.com/ruby/irb/releases/tag/v1.12.0
+[irb-v1.13.0]: https://github.com/ruby/irb/releases/tag/v1.13.0
+[irb-v1.13.1]: https://github.com/ruby/irb/releases/tag/v1.13.1
+[irb-v1.13.2]: https://github.com/ruby/irb/releases/tag/v1.13.2
+[irb-v1.14.0]: https://github.com/ruby/irb/releases/tag/v1.14.0
+[irb-v1.14.1]: https://github.com/ruby/irb/releases/tag/v1.14.1
+[irb-v1.14.2]: https://github.com/ruby/irb/releases/tag/v1.14.2
+[irb-v1.14.3]: https://github.com/ruby/irb/releases/tag/v1.14.3
+[json-v2.7.2]: https://github.com/ruby/json/releases/tag/v2.7.2
+[json-v2.7.3.rc1]: https://github.com/ruby/json/releases/tag/v2.7.3.rc1
+[json-v2.7.3]: https://github.com/ruby/json/releases/tag/v2.7.3
+[json-v2.7.4]: https://github.com/ruby/json/releases/tag/v2.7.4
+[json-v2.7.5]: https://github.com/ruby/json/releases/tag/v2.7.5
+[json-v2.7.6]: https://github.com/ruby/json/releases/tag/v2.7.6
+[json-v2.8.0]: https://github.com/ruby/json/releases/tag/v2.8.0
+[json-v2.8.1]: https://github.com/ruby/json/releases/tag/v2.8.1
+[json-v2.8.2]: https://github.com/ruby/json/releases/tag/v2.8.2
+[json-v2.9.0]: https://github.com/ruby/json/releases/tag/v2.9.0
+[json-v2.9.1]: https://github.com/ruby/json/releases/tag/v2.9.1
+[logger-v1.6.1]: https://github.com/ruby/logger/releases/tag/v1.6.1
+[logger-v1.6.2]: https://github.com/ruby/logger/releases/tag/v1.6.2
+[logger-v1.6.3]: https://github.com/ruby/logger/releases/tag/v1.6.3
+[logger-v1.6.4]: https://github.com/ruby/logger/releases/tag/v1.6.4
+[net-http-v0.4.1]: https://github.com/ruby/net-http/releases/tag/v0.4.1
+[net-http-v0.5.0]: https://github.com/ruby/net-http/releases/tag/v0.5.0
+[net-http-v0.6.0]: https://github.com/ruby/net-http/releases/tag/v0.6.0
+[open-uri-v0.5.0]: https://github.com/ruby/open-uri/releases/tag/v0.5.0
+[optparse-v0.5.0]: https://github.com/ruby/optparse/releases/tag/v0.5.0
+[optparse-v0.6.0]: https://github.com/ruby/optparse/releases/tag/v0.6.0
+[ostruct-v0.6.1]: https://github.com/ruby/ostruct/releases/tag/v0.6.1
+[pathname-v0.4.0]: https://github.com/ruby/pathname/releases/tag/v0.4.0
+[pp-v0.6.0]: https://github.com/ruby/pp/releases/tag/v0.6.0
+[pp-v0.6.1]: https://github.com/ruby/pp/releases/tag/v0.6.1
+[pp-v0.6.2]: https://github.com/ruby/pp/releases/tag/v0.6.2
+[prism-v0.20.0]: https://github.com/ruby/prism/releases/tag/v0.20.0
+[prism-v0.21.0]: https://github.com/ruby/prism/releases/tag/v0.21.0
+[prism-v0.22.0]: https://github.com/ruby/prism/releases/tag/v0.22.0
+[prism-v0.23.0]: https://github.com/ruby/prism/releases/tag/v0.23.0
+[prism-v0.24.0]: https://github.com/ruby/prism/releases/tag/v0.24.0
+[prism-v0.25.0]: https://github.com/ruby/prism/releases/tag/v0.25.0
+[prism-v0.26.0]: https://github.com/ruby/prism/releases/tag/v0.26.0
+[prism-v0.27.0]: https://github.com/ruby/prism/releases/tag/v0.27.0
+[prism-v0.28.0]: https://github.com/ruby/prism/releases/tag/v0.28.0
+[prism-v0.29.0]: https://github.com/ruby/prism/releases/tag/v0.29.0
+[prism-v0.30.0]: https://github.com/ruby/prism/releases/tag/v0.30.0
+[prism-v1.0.0]: https://github.com/ruby/prism/releases/tag/v1.0.0
+[prism-v1.1.0]: https://github.com/ruby/prism/releases/tag/v1.1.0
+[prism-v1.2.0]: https://github.com/ruby/prism/releases/tag/v1.2.0
+[pstore-v0.1.4]: https://github.com/ruby/pstore/releases/tag/v0.1.4
+[psych-v5.2.0.beta1]: https://github.com/ruby/psych/releases/tag/v5.2.0.beta1
+[psych-v5.2.0]: https://github.com/ruby/psych/releases/tag/v5.2.0
+[psych-v5.2.0.beta2]: https://github.com/ruby/psych/releases/tag/v5.2.0.beta2
+[psych-v5.2.0.beta3]: https://github.com/ruby/psych/releases/tag/v5.2.0.beta3
+[psych-v5.2.0.beta4]: https://github.com/ruby/psych/releases/tag/v5.2.0.beta4
+[psych-v5.2.0.beta5]: https://github.com/ruby/psych/releases/tag/v5.2.0.beta5
+[psych-v5.2.0.beta6]: https://github.com/ruby/psych/releases/tag/v5.2.0.beta6
+[psych-v5.2.0.beta7]: https://github.com/ruby/psych/releases/tag/v5.2.0.beta7
+[psych-v5.2.1]: https://github.com/ruby/psych/releases/tag/v5.2.1
+[psych-v5.2.2]: https://github.com/ruby/psych/releases/tag/v5.2.2
+[rdoc-v6.7.0]: https://github.com/ruby/rdoc/releases/tag/v6.7.0
+[rdoc-v6.8.0]: https://github.com/ruby/rdoc/releases/tag/v6.8.0
+[rdoc-v6.8.1]: https://github.com/ruby/rdoc/releases/tag/v6.8.1
+[rdoc-v6.9.0]: https://github.com/ruby/rdoc/releases/tag/v6.9.0
+[rdoc-v6.9.1]: https://github.com/ruby/rdoc/releases/tag/v6.9.1
+[rdoc-v6.10.0]: https://github.com/ruby/rdoc/releases/tag/v6.10.0
+[reline-v0.5.0.pre.1]: https://github.com/ruby/reline/releases/tag/v0.5.0.pre.1
+[reline-v0.4.2]: https://github.com/ruby/reline/releases/tag/v0.4.2
+[reline-v0.4.3]: https://github.com/ruby/reline/releases/tag/v0.4.3
+[reline-v0.5.0]: https://github.com/ruby/reline/releases/tag/v0.5.0
+[reline-v0.5.1]: https://github.com/ruby/reline/releases/tag/v0.5.1
+[reline-v0.5.2]: https://github.com/ruby/reline/releases/tag/v0.5.2
+[reline-v0.5.3]: https://github.com/ruby/reline/releases/tag/v0.5.3
+[reline-v0.5.4]: https://github.com/ruby/reline/releases/tag/v0.5.4
+[reline-v0.5.5]: https://github.com/ruby/reline/releases/tag/v0.5.5
+[reline-v0.5.6]: https://github.com/ruby/reline/releases/tag/v0.5.6
+[reline-v0.5.7]: https://github.com/ruby/reline/releases/tag/v0.5.7
+[reline-v0.5.8]: https://github.com/ruby/reline/releases/tag/v0.5.8
+[reline-v0.5.9]: https://github.com/ruby/reline/releases/tag/v0.5.9
+[reline-v0.5.10]: https://github.com/ruby/reline/releases/tag/v0.5.10
+[reline-v0.5.11]: https://github.com/ruby/reline/releases/tag/v0.5.11
+[reline-v0.5.12]: https://github.com/ruby/reline/releases/tag/v0.5.12
+[reline-v0.6.0]: https://github.com/ruby/reline/releases/tag/v0.6.0
+[resolv-v0.4.0]: https://github.com/ruby/resolv/releases/tag/v0.4.0
+[resolv-v0.5.0]: https://github.com/ruby/resolv/releases/tag/v0.5.0
+[resolv-v0.6.0]: https://github.com/ruby/resolv/releases/tag/v0.6.0
+[securerandom-v0.3.2]: https://github.com/ruby/securerandom/releases/tag/v0.3.2
+[securerandom-v0.4.0]: https://github.com/ruby/securerandom/releases/tag/v0.4.0
+[securerandom-v0.4.1]: https://github.com/ruby/securerandom/releases/tag/v0.4.1
+[set-v1.1.1]: https://github.com/ruby/set/releases/tag/v1.1.1
+[shellwords-v0.2.1]: https://github.com/ruby/shellwords/releases/tag/v0.2.1
+[shellwords-v0.2.2]: https://github.com/ruby/shellwords/releases/tag/v0.2.2
+[singleton-v0.3.0]: https://github.com/ruby/singleton/releases/tag/v0.3.0
+[stringio-v3.1.1]: https://github.com/ruby/stringio/releases/tag/v3.1.1
+[stringio-v3.1.2]: https://github.com/ruby/stringio/releases/tag/v3.1.2
+[strscan-v3.0.8]: https://github.com/ruby/strscan/releases/tag/v3.0.8
+[strscan-v3.0.9]: https://github.com/ruby/strscan/releases/tag/v3.0.9
+[strscan-v3.1.0]: https://github.com/ruby/strscan/releases/tag/v3.1.0
+[strscan-v3.1.1]: https://github.com/ruby/strscan/releases/tag/v3.1.1
+[strscan-v3.1.2]: https://github.com/ruby/strscan/releases/tag/v3.1.2
+[syntax_suggest-v2.0.1]: https://github.com/ruby/syntax_suggest/releases/tag/v2.0.1
+[syntax_suggest-v2.0.2]: https://github.com/ruby/syntax_suggest/releases/tag/v2.0.2
+[tempfile-v0.3.0]: https://github.com/ruby/tempfile/releases/tag/v0.3.0
+[tempfile-v0.3.1]: https://github.com/ruby/tempfile/releases/tag/v0.3.1
+[time-v0.4.0]: https://github.com/ruby/time/releases/tag/v0.4.0
+[time-v0.4.1]: https://github.com/ruby/time/releases/tag/v0.4.1
+[timeout-v0.4.2]: https://github.com/ruby/timeout/releases/tag/v0.4.2
+[timeout-v0.4.3]: https://github.com/ruby/timeout/releases/tag/v0.4.3
+[tmpdir-v0.3.0]: https://github.com/ruby/tmpdir/releases/tag/v0.3.0
+[tmpdir-v0.3.1]: https://github.com/ruby/tmpdir/releases/tag/v0.3.1
+[uri-v0.13.1]: https://github.com/ruby/uri/releases/tag/v0.13.1
+[uri-v1.0.0]: https://github.com/ruby/uri/releases/tag/v1.0.0
+[uri-v1.0.1]: https://github.com/ruby/uri/releases/tag/v1.0.1
+[uri-v1.0.2]: https://github.com/ruby/uri/releases/tag/v1.0.2
+[win32ole-v1.9.0]: https://github.com/ruby/win32ole/releases/tag/v1.9.0
+[win32ole-v1.9.1]: https://github.com/ruby/win32ole/releases/tag/v1.9.1
+[yaml-v0.4.0]: https://github.com/ruby/yaml/releases/tag/v0.4.0
+[zlib-v3.1.1]: https://github.com/ruby/zlib/releases/tag/v3.1.1
+[zlib-v3.2.0]: https://github.com/ruby/zlib/releases/tag/v3.2.0
+[zlib-v3.2.1]: https://github.com/ruby/zlib/releases/tag/v3.2.1
+[minitest-v5.25.4]: https://github.com/seattlerb/minitest/releases/tag/v5.25.4
+[power_assert-v2.0.4]: https://github.com/ruby/power_assert/releases/tag/v2.0.4
+[power_assert-v2.0.5]: https://github.com/ruby/power_assert/releases/tag/v2.0.5
+[rake-v13.2.0]: https://github.com/ruby/rake/releases/tag/v13.2.0
+[rake-v13.2.1]: https://github.com/ruby/rake/releases/tag/v13.2.1
+[test-unit-3.6.2]: https://github.com/test-unit/test-unit/releases/tag/3.6.2
+[test-unit-3.6.3]: https://github.com/test-unit/test-unit/releases/tag/3.6.3
+[test-unit-3.6.4]: https://github.com/test-unit/test-unit/releases/tag/3.6.4
+[test-unit-3.6.5]: https://github.com/test-unit/test-unit/releases/tag/3.6.5
+[test-unit-3.6.6]: https://github.com/test-unit/test-unit/releases/tag/3.6.6
+[test-unit-3.6.7]: https://github.com/test-unit/test-unit/releases/tag/3.6.7
+[rexml-v3.2.7]: https://github.com/ruby/rexml/releases/tag/v3.2.7
+[rexml-v3.2.8]: https://github.com/ruby/rexml/releases/tag/v3.2.8
+[rexml-v3.2.9]: https://github.com/ruby/rexml/releases/tag/v3.2.9
+[rexml-v3.3.0]: https://github.com/ruby/rexml/releases/tag/v3.3.0
+[rexml-v3.3.1]: https://github.com/ruby/rexml/releases/tag/v3.3.1
+[rexml-v3.3.2]: https://github.com/ruby/rexml/releases/tag/v3.3.2
+[rexml-v3.3.3]: https://github.com/ruby/rexml/releases/tag/v3.3.3
+[rexml-v3.3.4]: https://github.com/ruby/rexml/releases/tag/v3.3.4
+[rexml-v3.3.5]: https://github.com/ruby/rexml/releases/tag/v3.3.5
+[rexml-v3.3.6]: https://github.com/ruby/rexml/releases/tag/v3.3.6
+[rexml-v3.3.7]: https://github.com/ruby/rexml/releases/tag/v3.3.7
+[rexml-v3.3.8]: https://github.com/ruby/rexml/releases/tag/v3.3.8
+[rexml-v3.3.9]: https://github.com/ruby/rexml/releases/tag/v3.3.9
+[rexml-v3.4.0]: https://github.com/ruby/rexml/releases/tag/v3.4.0
+[rss-0.3.1]: https://github.com/ruby/rss/releases/tag/0.3.1
+[net-ftp-v0.3.4]: https://github.com/ruby/net-ftp/releases/tag/v0.3.4
+[net-ftp-v0.3.5]: https://github.com/ruby/net-ftp/releases/tag/v0.3.5
+[net-ftp-v0.3.6]: https://github.com/ruby/net-ftp/releases/tag/v0.3.6
+[net-ftp-v0.3.7]: https://github.com/ruby/net-ftp/releases/tag/v0.3.7
+[net-ftp-v0.3.8]: https://github.com/ruby/net-ftp/releases/tag/v0.3.8
+[net-imap-v0.4.9.1]: https://github.com/ruby/net-imap/releases/tag/v0.4.9.1
+[net-imap-v0.4.10]: https://github.com/ruby/net-imap/releases/tag/v0.4.10
+[net-imap-v0.4.11]: https://github.com/ruby/net-imap/releases/tag/v0.4.11
+[net-imap-v0.4.12]: https://github.com/ruby/net-imap/releases/tag/v0.4.12
+[net-imap-v0.4.13]: https://github.com/ruby/net-imap/releases/tag/v0.4.13
+[net-imap-v0.4.14]: https://github.com/ruby/net-imap/releases/tag/v0.4.14
+[net-imap-v0.4.15]: https://github.com/ruby/net-imap/releases/tag/v0.4.15
+[net-imap-v0.4.16]: https://github.com/ruby/net-imap/releases/tag/v0.4.16
+[net-imap-v0.4.17]: https://github.com/ruby/net-imap/releases/tag/v0.4.17
+[net-imap-v0.5.0]: https://github.com/ruby/net-imap/releases/tag/v0.5.0
+[net-imap-v0.4.18]: https://github.com/ruby/net-imap/releases/tag/v0.4.18
+[net-imap-v0.5.1]: https://github.com/ruby/net-imap/releases/tag/v0.5.1
+[net-imap-v0.5.2]: https://github.com/ruby/net-imap/releases/tag/v0.5.2
+[net-imap-v0.5.3]: https://github.com/ruby/net-imap/releases/tag/v0.5.3
+[net-imap-v0.5.4]: https://github.com/ruby/net-imap/releases/tag/v0.5.4
+[net-smtp-v0.4.0.1]: https://github.com/ruby/net-smtp/releases/tag/v0.4.0.1
+[net-smtp-v0.5.0]: https://github.com/ruby/net-smtp/releases/tag/v0.5.0
+[prime-v0.1.3]: https://github.com/ruby/prime/releases/tag/v0.1.3
+[rbs-v3.4.1]: https://github.com/ruby/rbs/releases/tag/v3.4.1
+[rbs-v3.4.2]: https://github.com/ruby/rbs/releases/tag/v3.4.2
+[rbs-v3.4.3]: https://github.com/ruby/rbs/releases/tag/v3.4.3
+[rbs-v3.4.4]: https://github.com/ruby/rbs/releases/tag/v3.4.4
+[rbs-v3.5.0.pre.1]: https://github.com/ruby/rbs/releases/tag/v3.5.0.pre.1
+[rbs-v3.5.0.pre.2]: https://github.com/ruby/rbs/releases/tag/v3.5.0.pre.2
+[rbs-v3.5.0]: https://github.com/ruby/rbs/releases/tag/v3.5.0
+[rbs-v3.5.1]: https://github.com/ruby/rbs/releases/tag/v3.5.1
+[rbs-v3.5.2]: https://github.com/ruby/rbs/releases/tag/v3.5.2
+[rbs-v3.5.3]: https://github.com/ruby/rbs/releases/tag/v3.5.3
+[rbs-v3.6.0.dev.1]: https://github.com/ruby/rbs/releases/tag/v3.6.0.dev.1
+[rbs-v3.6.0.pre.1]: https://github.com/ruby/rbs/releases/tag/v3.6.0.pre.1
+[rbs-v3.6.0.pre.2]: https://github.com/ruby/rbs/releases/tag/v3.6.0.pre.2
+[rbs-v3.6.0.pre.3]: https://github.com/ruby/rbs/releases/tag/v3.6.0.pre.3
+[rbs-v3.6.0]: https://github.com/ruby/rbs/releases/tag/v3.6.0
+[rbs-v3.6.1]: https://github.com/ruby/rbs/releases/tag/v3.6.1
+[rbs-v3.7.0.dev.1]: https://github.com/ruby/rbs/releases/tag/v3.7.0.dev.1
+[rbs-v3.7.0.pre.1]: https://github.com/ruby/rbs/releases/tag/v3.7.0.pre.1
+[rbs-v3.7.0]: https://github.com/ruby/rbs/releases/tag/v3.7.0
+[rbs-v3.8.0.pre.1]: https://github.com/ruby/rbs/releases/tag/v3.8.0.pre.1
+[rbs-v3.8.0]: https://github.com/ruby/rbs/releases/tag/v3.8.0
+[debug-v1.9.2]: https://github.com/ruby/debug/releases/tag/v1.9.2
+[debug-v1.10.0]: https://github.com/ruby/debug/releases/tag/v1.10.0
+[racc-v1.8.0]: https://github.com/ruby/racc/releases/tag/v1.8.0
+[racc-v1.8.1]: https://github.com/ruby/racc/releases/tag/v1.8.1
+[mutex_m-v0.3.0]: https://github.com/ruby/mutex_m/releases/tag/v0.3.0
+[bigdecimal-v3.1.6]: https://github.com/ruby/bigdecimal/releases/tag/v3.1.6
+[bigdecimal-v3.1.7]: https://github.com/ruby/bigdecimal/releases/tag/v3.1.7
+[bigdecimal-v3.1.8]: https://github.com/ruby/bigdecimal/releases/tag/v3.1.8
+[drb-v2.2.1]: https://github.com/ruby/drb/releases/tag/v2.2.1
+[nkf-v0.2.0]: https://github.com/ruby/nkf/releases/tag/v0.2.0
+[syslog-v0.2.0]: https://github.com/ruby/syslog/releases/tag/v0.2.0
+[csv-v3.2.9]: https://github.com/ruby/csv/releases/tag/v3.2.9
+[csv-v3.3.0]: https://github.com/ruby/csv/releases/tag/v3.3.0
+[csv-v3.3.1]: https://github.com/ruby/csv/releases/tag/v3.3.1
+[csv-v3.3.2]: https://github.com/ruby/csv/releases/tag/v3.3.2
+[ruby/net-http-sspi]: https://github.com/ruby/net-http-sspi
+[typeprof-v0.30.1]: https://github.com/ruby/typeprof/releases/tag/v0.30.1
+
+[RubyGems]: https://github.com/rubygems/rubygems
+[benchmark]: https://github.com/ruby/benchmark
+[bundler]: https://github.com/rubygems/rubygems
+[date]: https://github.com/ruby/date
+[delegate]: https://github.com/ruby/delegate
+[did_you_mean]: https://github.com/ruby/did_you_mean
+[digest]: https://github.com/ruby/digest
+[erb]: https://github.com/ruby/erb
+[error_highlight]: https://github.com/ruby/error_highlight
+[etc]: https://github.com/ruby/etc
+[fcntl]: https://github.com/ruby/fcntl
+[fiddle]: https://github.com/ruby/fiddle
+[fileutils]: https://github.com/ruby/fileutils
+[io-console]: https://github.com/ruby/io-console
+[io-nonblock]: https://github.com/ruby/io-nonblock
+[ipaddr]: https://github.com/ruby/ipaddr
+[irb]: https://github.com/ruby/irb
+[json]: https://github.com/ruby/json
+[logger]: https://github.com/ruby/logger
+[net-http]: https://github.com/ruby/net-http
+[open-uri]: https://github.com/ruby/open-uri
+[optparse]: https://github.com/ruby/optparse
+[ostruct]: https://github.com/ruby/ostruct
+[pathname]: https://github.com/ruby/pathname
+[pp]: https://github.com/ruby/pp
+[prism]: https://github.com/ruby/prism
+[pstore]: https://github.com/ruby/pstore
+[psych]: https://github.com/ruby/psych
+[rdoc]: https://github.com/ruby/rdoc
+[reline]: https://github.com/ruby/reline
+[resolv]: https://github.com/ruby/resolv
+[securerandom]: https://github.com/ruby/securerandom
+[set]: https://github.com/ruby/set
+[shellwords]: https://github.com/ruby/shellwords
+[singleton]: https://github.com/ruby/singleton
+[stringio]: https://github.com/ruby/stringio
+[strscan]: https://github.com/ruby/strscan
+[syntax_suggest]: https://github.com/ruby/syntax_suggest
+[tempfile]: https://github.com/ruby/tempfile
+[time]: https://github.com/ruby/time
+[timeout]: https://github.com/ruby/timeout
+[tmpdir]: https://github.com/ruby/tmpdir
+[uri]: https://github.com/ruby/uri
+[win32ole]: https://github.com/ruby/win32ole
+[yaml]: https://github.com/ruby/yaml
+[zlib]: https://github.com/ruby/zlib
+
+[repl_type_completor]: https://github.com/ruby/repl_type_completor
+[minitest]: https://github.com/seattlerb/minitest
+[power_assert]: https://github.com/ruby/power_assert
+[rake]: https://github.com/ruby/rake
+[test-unit]: https://github.com/test-unit/test-unit
+[rexml]: https://github.com/ruby/rexml
+[rss]: https://github.com/ruby/rss
+[net-ftp]: https://github.com/ruby/net-ftp
+[net-imap]: https://github.com/ruby/net-imap
+[net-smtp]: https://github.com/ruby/net-smtp
+[prime]: https://github.com/ruby/prime
+[rbs]: https://github.com/ruby/rbs
+[typeprof]: https://github.com/ruby/typeprof
+[debug]: https://github.com/ruby/debug
+[racc]: https://github.com/ruby/racc
+[mutex_m]: https://github.com/ruby/mutex_m
+[getoptlong]: https://github.com/ruby/getoptlong
+[base64]: https://github.com/ruby/base64
+[bigdecimal]: https://github.com/ruby/bigdecimal
+[observer]: https://github.com/ruby/observer
+[abbrev]: https://github.com/ruby/abbrev
+[resolv-replace]: https://github.com/ruby/resolv-replace
+[rinda]: https://github.com/ruby/rinda
+[drb]: https://github.com/ruby/drb
+[nkf]: https://github.com/ruby/nkf
+[syslog]: https://github.com/ruby/syslog
+[csv]: https://github.com/ruby/csv
diff --git a/doc/NEWS/NEWS-4.0.0.md b/doc/NEWS/NEWS-4.0.0.md
new file mode 100644
index 0000000000..5d932fbf5d
--- /dev/null
+++ b/doc/NEWS/NEWS-4.0.0.md
@@ -0,0 +1,802 @@
+# NEWS for Ruby 4.0.0
+
+This document is a list of user-visible feature changes
+since the **3.4.0** release, except for bug fixes.
+
+Note that each entry is kept to a minimum, see links for details.
+
+## Language changes
+
+* `*nil` no longer calls `nil.to_a`, similar to how `**nil` does
+ not call `nil.to_hash`. [[Feature #21047]]
+
+* Logical binary operators (`||`, `&&`, `and` and `or`) at the
+ beginning of a line continue the previous line, like fluent dot.
+ The following code examples are equal:
+
+ ```ruby
+ if condition1
+ && condition2
+ ...
+ end
+ ```
+
+ Previously:
+
+ ```ruby
+ if condition1 && condition2
+ ...
+ end
+ ```
+
+ ```ruby
+ if condition1 &&
+ condition2
+ ...
+ end
+ ```
+
+ [[Feature #20925]]
+
+## Core classes updates
+
+Note: We're only listing outstanding class updates.
+
+* Array
+
+ * `Array#rfind` has been added as a more efficient alternative to `array.reverse_each.find` [[Feature #21678]]
+ * `Array#find` has been added as a more efficient override of `Enumerable#find` [[Feature #21678]]
+* Binding
+
+ * `Binding#local_variables` does no longer include numbered parameters.
+ Also, `Binding#local_variable_get`, `Binding#local_variable_set`, and
+ `Binding#local_variable_defined?` reject to handle numbered parameters.
+ [[Bug #21049]]
+
+ * `Binding#implicit_parameters`, `Binding#implicit_parameter_get`, and
+ `Binding#implicit_parameter_defined?` have been added to access
+ numbered parameters and "it" parameter. [[Bug #21049]]
+
+* Enumerator
+
+ * `Enumerator.produce` now accepts an optional `size` keyword argument
+ to specify the size of the enumerator. It can be an integer,
+ `Float::INFINITY`, a callable object (such as a lambda), or `nil` to
+ indicate unknown size. When not specified, the size defaults to
+ `Float::INFINITY`.
+
+ ```ruby
+ # Infinite enumerator
+ enum = Enumerator.produce(1, size: Float::INFINITY, &:succ)
+ enum.size # => Float::INFINITY
+
+ # Finite enumerator with known/computable size
+ abs_dir = File.expand_path("./baz") # => "/foo/bar/baz"
+ traverser = Enumerator.produce(abs_dir, size: -> { abs_dir.count("/") + 1 }) {
+ raise StopIteration if it == "/"
+ File.dirname(it)
+ }
+ traverser.size # => 4
+ ```
+
+ [[Feature #21701]]
+
+* ErrorHighlight
+
+ * When an ArgumentError is raised, it now displays code snippets for
+ both the method call (caller) and the method definition (callee).
+ [[Feature #21543]]
+
+ ```
+ test.rb:1:in 'Object#add': wrong number of arguments (given 1, expected 2) (ArgumentError)
+
+ caller: test.rb:3
+ | add(1)
+ ^^^
+ callee: test.rb:1
+ | def add(x, y) = x + y
+ ^^^
+ from test.rb:3:in '<main>'
+ ```
+
+* Fiber
+
+ * Introduce support for `Fiber#raise(cause:)` argument similar to
+ `Kernel#raise`. [[Feature #21360]]
+
+* Fiber::Scheduler
+
+ * Introduce `Fiber::Scheduler#fiber_interrupt` to interrupt a fiber with a
+ given exception. The initial use case is to interrupt a fiber that is
+ waiting on a blocking IO operation when the IO operation is closed.
+ [[Feature #21166]]
+
+ * Introduce `Fiber::Scheduler#yield` to allow the fiber scheduler to
+ continue processing when signal exceptions are disabled.
+ [[Bug #21633]]
+
+ * Reintroduce the `Fiber::Scheduler#io_close` hook for asynchronous `IO#close`.
+
+ * Invoke `Fiber::Scheduler#io_write` when flushing the IO write buffer.
+ [[Bug #21789]]
+
+* File
+
+ * `File::Stat#birthtime` is now available on Linux via the statx
+ system call when supported by the kernel and filesystem.
+ [[Feature #21205]]
+
+* IO
+
+ * `IO.select` accepts `Float::INFINITY` as a timeout argument.
+ [[Feature #20610]]
+
+ * A deprecated behavior, process creation by `IO` class methods
+ with a leading `|`, was removed. [[Feature #19630]]
+
+* Kernel
+
+ * `Kernel#inspect` now checks for the existence of a `#instance_variables_to_inspect` method,
+ allowing control over which instance variables are displayed in the `#inspect` string:
+
+ ```ruby
+ class DatabaseConfig
+ def initialize(host, user, password)
+ @host = host
+ @user = user
+ @password = password
+ end
+
+ private def instance_variables_to_inspect = [:@host, :@user]
+ end
+
+ conf = DatabaseConfig.new("localhost", "root", "hunter2")
+ conf.inspect #=> #<DatabaseConfig:0x0000000104def350 @host="localhost", @user="root">
+ ```
+
+ [[Feature #21219]]
+
+ * A deprecated behavior, process creation by `Kernel#open` with a
+ leading `|`, was removed. [[Feature #19630]]
+
+* Math
+
+ * `Math.log1p` and `Math.expm1` are added. [[Feature #21527]]
+
+* Pathname
+
+ * Pathname has been promoted from a default gem to a core class of Ruby.
+ [[Feature #17473]]
+
+* Proc
+
+ * `Proc#parameters` now shows anonymous optional parameters as `[:opt]`
+ instead of `[:opt, nil]`, making the output consistent with when the
+ anonymous parameter is required. [[Bug #20974]]
+
+* Ractor
+
+ * `Ractor::Port` class was added for a new synchronization mechanism
+ to communicate between Ractors. [[Feature #21262]]
+
+ ```ruby
+ port1 = Ractor::Port.new
+ port2 = Ractor::Port.new
+ Ractor.new port1, port2 do |port1, port2|
+ port1 << 1
+ port2 << 11
+ port1 << 2
+ port2 << 12
+ end
+ 2.times{ p port1.receive } #=> 1, 2
+ 2.times{ p port2.receive } #=> 11, 12
+ ```
+
+ `Ractor::Port` provides the following methods:
+
+ * `Ractor::Port#receive`
+ * `Ractor::Port#send` (or `Ractor::Port#<<`)
+ * `Ractor::Port#close`
+ * `Ractor::Port#closed?`
+
+ As a result, `Ractor.yield` and `Ractor#take` were removed.
+
+ * `Ractor#join` and `Ractor#value` were added to wait for the
+ termination of a Ractor. These are similar to `Thread#join`
+ and `Thread#value`.
+
+ * `Ractor#monitor` and `Ractor#unmonitor` were added as low-level
+ interfaces used internally to implement `Ractor#join`.
+
+ * `Ractor.select` now only accepts Ractors and Ports. If Ractors are given,
+ it returns when a Ractor terminates.
+
+ * `Ractor#default_port` was added. Each `Ractor` has a default port,
+ which is used by `Ractor.send`, `Ractor.receive`.
+
+ * `Ractor#close_incoming` and `Ractor#close_outgoing` were removed.
+
+ * `Ractor.shareable_proc` and `Ractor.shareable_lambda` are introduced
+ to make shareable Proc or lambda.
+ [[Feature #21550]], [[Feature #21557]]
+
+* Range
+
+ * `Range#to_set` now performs size checks to prevent issues with
+ endless ranges. [[Bug #21654]]
+
+ * `Range#overlap?` now correctly handles infinite (unbounded) ranges.
+ [[Bug #21185]]
+
+ * `Range#max` behavior on beginless integer ranges has been fixed.
+ [[Bug #21174]] [[Bug #21175]]
+
+* Ruby
+
+ * A new toplevel module `Ruby` has been defined, which contains
+ Ruby-related constants. This module was reserved in Ruby 3.4
+ and is now officially defined. [[Feature #20884]]
+
+* Ruby::Box
+
+ * A new (experimental) feature to provide separation about definitions.
+ For the detail of "Ruby Box", see [doc/language/box.md](doc/language/box.md).
+ [[Feature #21311]] [[Misc #21385]]
+
+* Set
+
+ * `Set` is now a core class, instead of an autoloaded stdlib class.
+ [[Feature #21216]]
+
+ * `Set#inspect` now uses a simpler display, similar to literal arrays.
+ (e.g., `Set[1, 2, 3]` instead of `#<Set: {1, 2, 3}>`). [[Feature #21389]]
+
+ * Passing arguments to `Set#to_set` and `Enumerable#to_set` is now deprecated.
+ [[Feature #21390]]
+
+* Socket
+
+ * `Socket.tcp` & `TCPSocket.new` accepts an `open_timeout` keyword argument to specify
+ the timeout for the initial connection. [[Feature #21347]]
+ * When a user-specified timeout occurred in `TCPSocket.new`, either `Errno::ETIMEDOUT`
+ or `IO::TimeoutError` could previously be raised depending on the situation.
+ This behavior has been unified so that `IO::TimeoutError` is now consistently raised.
+ (Please note that, in `Socket.tcp`, there are still cases where `Errno::ETIMEDOUT`
+ may be raised in similar situations, and that in both cases `Errno::ETIMEDOUT` may be
+ raised when the timeout occurs at the OS level.)
+
+* String
+
+ * Update Unicode to Version 17.0.0 and Emoji Version 17.0.
+ [[Feature #19908]][[Feature #20724]][[Feature #21275]] (also applies to Regexp)
+
+ * `String#strip`, `strip!`, `lstrip`, `lstrip!`, `rstrip`, and `rstrip!`
+ are extended to accept `*selectors` arguments. [[Feature #21552]]
+
+* Thread
+
+ * Introduce support for `Thread#raise(cause:)` argument similar to
+ `Kernel#raise`. [[Feature #21360]]
+
+## Stdlib updates
+
+We only list stdlib changes that are notable feature changes.
+
+Other changes are listed in the following sections. We also listed release
+history from the previous bundled version that is Ruby 3.4.0 if it has GitHub
+releases.
+
+The following bundled gems are promoted from default gems.
+
+* ostruct 0.6.3
+ * 0.6.1 to [v0.6.2][ostruct-v0.6.2], [v0.6.3][ostruct-v0.6.3]
+* pstore 0.2.0
+ * 0.1.4 to [v0.2.0][pstore-v0.2.0]
+* benchmark 0.5.0
+ * 0.4.0 to [v0.4.1][benchmark-v0.4.1], [v0.5.0][benchmark-v0.5.0]
+* logger 1.7.0
+ * 1.6.4 to [v1.6.5][logger-v1.6.5], [v1.6.6][logger-v1.6.6], [v1.7.0][logger-v1.7.0]
+* rdoc 7.0.3
+ * 6.14.0 to [v6.14.1][rdoc-v6.14.1], [v6.14.2][rdoc-v6.14.2], [v6.15.0][rdoc-v6.15.0], [v6.15.1][rdoc-v6.15.1], [v6.16.0][rdoc-v6.16.0], [v6.16.1][rdoc-v6.16.1], [v6.17.0][rdoc-v6.17.0], [v7.0.0][rdoc-v7.0.0], [v7.0.1][rdoc-v7.0.1], [v7.0.2][rdoc-v7.0.2], [v7.0.3][rdoc-v7.0.3]
+* win32ole 1.9.2
+ * 1.9.1 to [v1.9.2][win32ole-v1.9.2]
+* irb 1.16.0
+ * 1.14.3 to [v1.15.0][irb-v1.15.0], [v1.15.1][irb-v1.15.1], [v1.15.2][irb-v1.15.2], [v1.15.3][irb-v1.15.3], [v1.16.0][irb-v1.16.0]
+* reline 0.6.3
+ * 0.6.0 to [v0.6.1][reline-v0.6.1], [v0.6.2][reline-v0.6.2], [v0.6.3][reline-v0.6.3]
+* readline 0.0.4
+* fiddle 1.1.8
+ * 1.1.6 to [v1.1.7][fiddle-v1.1.7], [v1.1.8][fiddle-v1.1.8]
+
+The following default gem is added.
+
+* win32-registry 0.1.2
+
+The following default gems are updated.
+
+* RubyGems 4.0.3
+* bundler 4.0.3
+* date 3.5.1
+ * 3.4.1 to [v3.5.0][date-v3.5.0], [v3.5.1][date-v3.5.1]
+* delegate 0.6.1
+ * 0.4.0 to [v0.5.0][delegate-v0.5.0], [v0.6.0][delegate-v0.6.0], [v0.6.1][delegate-v0.6.1]
+* digest 3.2.1
+ * 3.2.0 to [v3.2.1][digest-v3.2.1]
+* english 0.8.1
+ * 0.8.0 to [v0.8.1][english-v0.8.1]
+* erb 6.0.1
+ * 4.0.4 to [v5.1.2][erb-v5.1.2], [v5.1.3][erb-v5.1.3], [v6.0.0][erb-v6.0.0], [v6.0.1][erb-v6.0.1]
+* error_highlight 0.7.1
+* etc 1.4.6
+* fcntl 1.3.0
+ * 1.2.0 to [v1.3.0][fcntl-v1.3.0]
+* fileutils 1.8.0
+ * 1.7.3 to [v1.8.0][fileutils-v1.8.0]
+* forwardable 1.4.0
+ * 1.3.3 to [v1.4.0][forwardable-v1.4.0]
+* io-console 0.8.2
+ * 0.8.1 to [v0.8.2][io-console-v0.8.2]
+* io-nonblock 0.3.2
+* io-wait 0.4.0
+ * 0.3.2 to [v0.3.3][io-wait-v0.3.3], [v0.3.5.test1][io-wait-v0.3.5.test1], [v0.3.5][io-wait-v0.3.5], [v0.3.6][io-wait-v0.3.6], [v0.4.0][io-wait-v0.4.0]
+* ipaddr 1.2.8
+* json 2.18.0
+ * 2.9.1 to [v2.10.0][json-v2.10.0], [v2.10.1][json-v2.10.1], [v2.10.2][json-v2.10.2], [v2.11.0][json-v2.11.0], [v2.11.1][json-v2.11.1], [v2.11.2][json-v2.11.2], [v2.11.3][json-v2.11.3], [v2.12.0][json-v2.12.0], [v2.12.1][json-v2.12.1], [v2.12.2][json-v2.12.2], [v2.13.0][json-v2.13.0], [v2.13.1][json-v2.13.1], [v2.13.2][json-v2.13.2], [v2.14.0][json-v2.14.0], [v2.14.1][json-v2.14.1], [v2.15.0][json-v2.15.0], [v2.15.1][json-v2.15.1], [v2.15.2][json-v2.15.2], [v2.16.0][json-v2.16.0], [v2.17.0][json-v2.17.0], [v2.17.1][json-v2.17.1], [v2.18.0][json-v2.18.0]
+* net-http 0.9.1
+ * 0.6.0 to [v0.7.0][net-http-v0.7.0], [v0.8.0][net-http-v0.8.0], [v0.9.0][net-http-v0.9.0], [v0.9.1][net-http-v0.9.1]
+* openssl 4.0.0
+ * 3.3.1 to [v3.3.2][openssl-v3.3.2], [v4.0.0][openssl-v4.0.0]
+* optparse 0.8.1
+ * 0.6.0 to [v0.7.0][optparse-v0.7.0], [v0.8.0][optparse-v0.8.0], [v0.8.1][optparse-v0.8.1]
+* pp 0.6.3
+ * 0.6.2 to [v0.6.3][pp-v0.6.3]
+* prism 1.7.0
+ * 1.5.2 to [v1.6.0][prism-v1.6.0], [v1.7.0][prism-v1.7.0]
+* psych 5.3.1
+ * 5.2.2 to [v5.2.3][psych-v5.2.3], [v5.2.4][psych-v5.2.4], [v5.2.5][psych-v5.2.5], [v5.2.6][psych-v5.2.6], [v5.3.0][psych-v5.3.0], [v5.3.1][psych-v5.3.1]
+* resolv 0.7.0
+ * 0.6.2 to [v0.6.3][resolv-v0.6.3], [v0.7.0][resolv-v0.7.0]
+* stringio 3.2.0
+ * 3.1.2 to [v3.1.3][stringio-v3.1.3], [v3.1.4][stringio-v3.1.4], [v3.1.5][stringio-v3.1.5], [v3.1.6][stringio-v3.1.6], [v3.1.7][stringio-v3.1.7], [v3.1.8][stringio-v3.1.8], [v3.1.9][stringio-v3.1.9], [v3.2.0][stringio-v3.2.0]
+* strscan 3.1.6
+ * 3.1.2 to [v3.1.3][strscan-v3.1.3], [v3.1.4][strscan-v3.1.4], [v3.1.5][strscan-v3.1.5], [v3.1.6][strscan-v3.1.6]
+* time 0.4.2
+ * 0.4.1 to [v0.4.2][time-v0.4.2]
+* timeout 0.6.0
+ * 0.4.3 to [v0.4.4][timeout-v0.4.4], [v0.5.0][timeout-v0.5.0], [v0.6.0][timeout-v0.6.0]
+* uri 1.1.1
+ * 1.0.4 to [v1.1.0][uri-v1.1.0], [v1.1.1][uri-v1.1.1]
+* weakref 0.1.4
+ * 0.1.3 to [v0.1.4][weakref-v0.1.4]
+* zlib 3.2.2
+ * 3.2.1 to [v3.2.2][zlib-v3.2.2]
+
+The following bundled gems are updated.
+
+* minitest 6.0.0
+* power_assert 3.0.1
+ * 2.0.5 to [v3.0.0][power_assert-v3.0.0], [v3.0.1][power_assert-v3.0.1]
+* rake 13.3.1
+ * 13.2.1 to [v13.3.0][rake-v13.3.0], [v13.3.1][rake-v13.3.1]
+* test-unit 3.7.5
+ * 3.6.7 to [3.6.8][test-unit-3.6.8], [3.6.9][test-unit-3.6.9], [3.7.0][test-unit-3.7.0], [3.7.1][test-unit-3.7.1], [3.7.2][test-unit-3.7.2], [3.7.3][test-unit-3.7.3], [3.7.4][test-unit-3.7.4], [3.7.5][test-unit-3.7.5]
+* rexml 3.4.4
+* rss 0.3.2
+ * 0.3.1 to [0.3.2][rss-0.3.2]
+* net-ftp 0.3.9
+ * 0.3.8 to [v0.3.9][net-ftp-v0.3.9]
+* net-imap 0.6.2
+ * 0.5.8 to [v0.5.9][net-imap-v0.5.9], [v0.5.10][net-imap-v0.5.10], [v0.5.11][net-imap-v0.5.11], [v0.5.12][net-imap-v0.5.12], [v0.5.13][net-imap-v0.5.13], [v0.6.0][net-imap-v0.6.0], [v0.6.1][net-imap-v0.6.1], [v0.6.2][net-imap-v0.6.2]
+* net-smtp 0.5.1
+ * 0.5.0 to [v0.5.1][net-smtp-v0.5.1]
+* matrix 0.4.3
+ * 0.4.2 to [v0.4.3][matrix-v0.4.3]
+* prime 0.1.4
+ * 0.1.3 to [v0.1.4][prime-v0.1.4]
+* rbs 3.10.0
+ * 3.8.0 to [v3.8.1][rbs-v3.8.1], [v3.9.0.dev.1][rbs-v3.9.0.dev.1], [v3.9.0.pre.1][rbs-v3.9.0.pre.1], [v3.9.0.pre.2][rbs-v3.9.0.pre.2], [v3.9.0][rbs-v3.9.0], [v3.9.1][rbs-v3.9.1], [v3.9.2][rbs-v3.9.2], [v3.9.3][rbs-v3.9.3], [v3.9.4][rbs-v3.9.4], [v3.9.5][rbs-v3.9.5], [v3.10.0.pre.1][rbs-v3.10.0.pre.1], [v3.10.0.pre.2][rbs-v3.10.0.pre.2], [v3.10.0][rbs-v3.10.0]
+* typeprof 0.31.1
+* debug 1.11.1
+ * 1.11.0 to [v1.11.1][debug-v1.11.1]
+* base64 0.3.0
+ * 0.2.0 to [v0.3.0][base64-v0.3.0]
+* bigdecimal 4.0.1
+ * 3.1.8 to [v3.2.0][bigdecimal-v3.2.0], [v3.2.1][bigdecimal-v3.2.1], [v3.2.2][bigdecimal-v3.2.2], [v3.2.3][bigdecimal-v3.2.3], [v3.3.0][bigdecimal-v3.3.0], [v3.3.1][bigdecimal-v3.3.1], [v4.0.0][bigdecimal-v4.0.0], [v4.0.1][bigdecimal-v4.0.1]
+* drb 2.2.3
+ * 2.2.1 to [v2.2.3][drb-v2.2.3]
+* syslog 0.3.0
+ * 0.2.0 to [v0.3.0][syslog-v0.3.0]
+* csv 3.3.5
+ * 3.3.2 to [v3.3.3][csv-v3.3.3], [v3.3.4][csv-v3.3.4], [v3.3.5][csv-v3.3.5]
+* repl_type_completor 0.1.12
+
+### RubyGems and Bundler
+
+Ruby 4.0 bundled RubyGems and Bundler version 4. see the following links for details.
+
+* [Upgrading to RubyGems/Bundler 4 - RubyGems Blog](https://blog.rubygems.org/2025/12/03/upgrade-to-rubygems-bundler-4.html)
+* [4.0.0 Released - RubyGems Blog](https://blog.rubygems.org/2025/12/03/4.0.0-released.html)
+* [4.0.1 Released - RubyGems Blog](https://blog.rubygems.org/2025/12/09/4.0.1-released.html)
+* [4.0.2 Released - RubyGems Blog](https://blog.rubygems.org/2025/12/17/4.0.2-released.html)
+* [4.0.3 Released - RubyGems Blog](https://blog.rubygems.org/2025/12/23/4.0.3-released.html)
+
+## Supported platforms
+
+* Windows
+
+ * Dropped support for MSVC versions older than 14.0 (_MSC_VER 1900).
+ This means Visual Studio 2015 or later is now required.
+
+## Compatibility issues
+
+* The following methods were removed from Ractor due to the addition of `Ractor::Port`:
+
+ * `Ractor.yield`
+ * `Ractor#take`
+ * `Ractor#close_incoming`
+ * `Ractor#close_outgoing`
+
+ [[Feature #21262]]
+
+* `ObjectSpace._id2ref` is deprecated. [[Feature #15408]]
+
+* `Process::Status#&` and `Process::Status#>>` have been removed.
+ They were deprecated in Ruby 3.3. [[Bug #19868]]
+
+* `rb_path_check` has been removed. This function was used for
+ `$SAFE` path checking which was removed in Ruby 2.7,
+ and was already deprecated.
+ [[Feature #20971]]
+
+* A backtrace for `ArgumentError` of "wrong number of arguments" now
+ include the receiver's class or module name (e.g., in `Foo#bar`
+ instead of in `bar`). [[Bug #21698]]
+
+* Backtraces no longer display `internal` frames.
+ These methods now appear as if it is in the Ruby source file,
+ consistent with other C-implemented methods. [[Bug #20968]]
+
+ Before:
+ ```
+ ruby -e '[1].fetch_values(42)'
+ <internal:array>:211:in 'Array#fetch': index 42 outside of array bounds: -1...1 (IndexError)
+ from <internal:array>:211:in 'block in Array#fetch_values'
+ from <internal:array>:211:in 'Array#map!'
+ from <internal:array>:211:in 'Array#fetch_values'
+ from -e:1:in '<main>'
+ ```
+
+ After:
+ ```
+ $ ruby -e '[1].fetch_values(42)'
+ -e:1:in 'Array#fetch_values': index 42 outside of array bounds: -1...1 (IndexError)
+ from -e:1:in '<main>'
+ ```
+
+## Stdlib compatibility issues
+
+* CGI library is removed from the default gems. Now we only provide `cgi/escape` for
+ the following methods:
+
+ * `CGI.escape` and `CGI.unescape`
+ * `CGI.escapeHTML` and `CGI.unescapeHTML`
+ * `CGI.escapeURIComponent` and `CGI.unescapeURIComponent`
+ * `CGI.escapeElement` and `CGI.unescapeElement`
+
+ [[Feature #21258]]
+
+* With the move of `Set` from stdlib to core class, `set/sorted_set.rb` has
+ been removed, and `SortedSet` is no longer an autoloaded constant. Please
+ install the `sorted_set` gem and `require 'sorted_set'` to use `SortedSet`.
+ [[Feature #21287]]
+
+* Net::HTTP
+
+ * The default behavior of automatically setting the `Content-Type` header
+ to `application/x-www-form-urlencoded` for requests with a body
+ (e.g., `POST`, `PUT`) when the header was not explicitly set has been
+ removed. If your application relied on this automatic default, your
+ requests will now be sent without a Content-Type header, potentially
+ breaking compatibility with certain servers.
+ [[GH-net-http #205]]
+
+## C API updates
+
+* IO
+
+ * `rb_thread_fd_close` is deprecated and now a no-op. If you need to expose
+ file descriptors from C extensions to Ruby code, create an `IO` instance
+ using `RUBY_IO_MODE_EXTERNAL` and use `rb_io_close(io)` to close it (this
+ also interrupts and waits for all pending operations on the `IO`
+ instance). Directly closing file descriptors does not interrupt pending
+ operations, and may lead to undefined behaviour. In other words, if two
+ `IO` objects share the same file descriptor, closing one does not affect
+ the other. [[Feature #18455]]
+
+* GVL
+
+ * `rb_thread_call_with_gvl` now works with or without the GVL.
+ This allows gems to avoid checking `ruby_thread_has_gvl_p`.
+ Please still be diligent about the GVL. [[Feature #20750]]
+
+* Set
+
+ * A C API for `Set` has been added. The following methods are supported:
+ [[Feature #21459]]
+
+ * `rb_set_foreach`
+ * `rb_set_new`
+ * `rb_set_new_capa`
+ * `rb_set_lookup`
+ * `rb_set_add`
+ * `rb_set_clear`
+ * `rb_set_delete`
+ * `rb_set_size`
+
+## Implementation improvements
+
+* `Class#new` (ex. `Object.new`) is faster in all cases, but especially when passing keyword arguments. This has also been integrated into YJIT and ZJIT. [[Feature #21254]]
+* GC heaps of different size pools now grow independently, reducing memory usage when only some pools contain long-lived objects
+* GC sweeping is faster on pages of large objects
+* "Generic ivar" objects (String, Array, `TypedData`, etc.) now use a new internal "fields" object for faster instance variable access
+* The GC avoids maintaining an internal `id2ref` table until it is first used, making `object_id` allocation and GC sweeping faster
+* `object_id` and `hash` are faster on Class and Module objects
+* Larger bignum Integers can remain embedded using variable width allocation
+* `Random`, `Enumerator::Product`, `Enumerator::Chain`, `Addrinfo`,
+ `StringScanner`, and some internal objects are now write-barrier protected,
+ which reduces GC overhead.
+
+### Ractor
+
+A lot of work has gone into making Ractors more stable, performant, and usable. These improvements bring Ractor implementation closer to leaving experimental status.
+
+* Performance improvements
+ * Frozen strings and the symbol table internally use a lock-free hash set [[Feature #21268]]
+ * Method cache lookups avoid locking in most cases
+ * Class (and generic ivar) instance variable access is faster and avoids locking
+ * CPU cache contention is avoided in object allocation by using a per-ractor counter
+ * CPU cache contention is avoided in xmalloc/xfree by using a thread-local counter
+ * `object_id` avoids locking in most cases
+* Bug fixes and stability
+ * Fixed possible deadlocks when combining Ractors and Threads
+ * Fixed issues with require and autoload in a Ractor
+ * Fixed encoding/transcoding issues across Ractors
+ * Fixed race conditions in GC operations and method invalidation
+ * Fixed issues with processes forking after starting a Ractor
+ * GC allocation counts are now accurate under Ractors
+ * Fixed TracePoints not working after GC [[Bug #19112]]
+
+## JIT
+
+* ZJIT
+ * Introduce an [experimental method-based JIT compiler](https://docs.ruby-lang.org/en/master/jit/zjit_md.html).
+ Where available, ZJIT can be enabled at runtime with the `--zjit` option or by calling `RubyVM::ZJIT.enable`.
+ When building Ruby, Rust 1.85.0 or later is required to include ZJIT support.
+ * As of Ruby 4.0.0, ZJIT is faster than the interpreter, but not yet as fast as YJIT.
+ We encourage experimentation with ZJIT, but advise against deploying it in production for now.
+ * Our goal is to make ZJIT faster than YJIT and production-ready in Ruby 4.1.
+* YJIT
+ * `RubyVM::YJIT.runtime_stats`
+ * `ratio_in_yjit` no longer works in the default build.
+ Use `--enable-yjit=stats` on `configure` to enable it on `--yjit-stats`.
+ * Add `invalidate_everything` to default stats, which is
+ incremented when every code is invalidated by TracePoint.
+ * Add `mem_size:` and `call_threshold:` options to `RubyVM::YJIT.enable`.
+* RJIT
+ * `--rjit` is removed. We will move the implementation of the third-party JIT API
+ to the [ruby/rjit](https://github.com/ruby/rjit) repository.
+
+[Feature #15408]: https://bugs.ruby-lang.org/issues/15408
+[Feature #17473]: https://bugs.ruby-lang.org/issues/17473
+[Feature #18455]: https://bugs.ruby-lang.org/issues/18455
+[Bug #19112]: https://bugs.ruby-lang.org/issues/19112
+[Feature #19630]: https://bugs.ruby-lang.org/issues/19630
+[Bug #19868]: https://bugs.ruby-lang.org/issues/19868
+[Feature #19908]: https://bugs.ruby-lang.org/issues/19908
+[Feature #20610]: https://bugs.ruby-lang.org/issues/20610
+[Feature #20724]: https://bugs.ruby-lang.org/issues/20724
+[Feature #20750]: https://bugs.ruby-lang.org/issues/20750
+[Feature #20884]: https://bugs.ruby-lang.org/issues/20884
+[Feature #20925]: https://bugs.ruby-lang.org/issues/20925
+[Bug #20968]: https://bugs.ruby-lang.org/issues/20968
+[Feature #20971]: https://bugs.ruby-lang.org/issues/20971
+[Bug #20974]: https://bugs.ruby-lang.org/issues/20974
+[Feature #21047]: https://bugs.ruby-lang.org/issues/21047
+[Bug #21049]: https://bugs.ruby-lang.org/issues/21049
+[Feature #21166]: https://bugs.ruby-lang.org/issues/21166
+[Bug #21174]: https://bugs.ruby-lang.org/issues/21174
+[Bug #21175]: https://bugs.ruby-lang.org/issues/21175
+[Bug #21185]: https://bugs.ruby-lang.org/issues/21185
+[Feature #21205]: https://bugs.ruby-lang.org/issues/21205
+[Feature #21216]: https://bugs.ruby-lang.org/issues/21216
+[Feature #21219]: https://bugs.ruby-lang.org/issues/21219
+[Feature #21254]: https://bugs.ruby-lang.org/issues/21254
+[Feature #21258]: https://bugs.ruby-lang.org/issues/21258
+[Feature #21268]: https://bugs.ruby-lang.org/issues/21268
+[Feature #21262]: https://bugs.ruby-lang.org/issues/21262
+[Feature #21275]: https://bugs.ruby-lang.org/issues/21275
+[Feature #21287]: https://bugs.ruby-lang.org/issues/21287
+[Feature #21311]: https://bugs.ruby-lang.org/issues/21311
+[Feature #21347]: https://bugs.ruby-lang.org/issues/21347
+[Feature #21360]: https://bugs.ruby-lang.org/issues/21360
+[Misc #21385]: https://bugs.ruby-lang.org/issues/21385
+[Feature #21389]: https://bugs.ruby-lang.org/issues/21389
+[Feature #21390]: https://bugs.ruby-lang.org/issues/21390
+[Feature #21459]: https://bugs.ruby-lang.org/issues/21459
+[Feature #21527]: https://bugs.ruby-lang.org/issues/21527
+[Feature #21543]: https://bugs.ruby-lang.org/issues/21543
+[Feature #21550]: https://bugs.ruby-lang.org/issues/21550
+[Feature #21552]: https://bugs.ruby-lang.org/issues/21552
+[Feature #21557]: https://bugs.ruby-lang.org/issues/21557
+[Bug #21633]: https://bugs.ruby-lang.org/issues/21633
+[Bug #21654]: https://bugs.ruby-lang.org/issues/21654
+[Feature #21678]: https://bugs.ruby-lang.org/issues/21678
+[Bug #21698]: https://bugs.ruby-lang.org/issues/21698
+[Feature #21701]: https://bugs.ruby-lang.org/issues/21701
+[Bug #21789]: https://bugs.ruby-lang.org/issues/21789
+[GH-net-http #205]: https://github.com/ruby/net-http/issues/205
+[ostruct-v0.6.2]: https://github.com/ruby/ostruct/releases/tag/v0.6.2
+[ostruct-v0.6.3]: https://github.com/ruby/ostruct/releases/tag/v0.6.3
+[pstore-v0.2.0]: https://github.com/ruby/pstore/releases/tag/v0.2.0
+[benchmark-v0.4.1]: https://github.com/ruby/benchmark/releases/tag/v0.4.1
+[benchmark-v0.5.0]: https://github.com/ruby/benchmark/releases/tag/v0.5.0
+[logger-v1.6.5]: https://github.com/ruby/logger/releases/tag/v1.6.5
+[logger-v1.6.6]: https://github.com/ruby/logger/releases/tag/v1.6.6
+[logger-v1.7.0]: https://github.com/ruby/logger/releases/tag/v1.7.0
+[rdoc-v6.14.1]: https://github.com/ruby/rdoc/releases/tag/v6.14.1
+[rdoc-v6.14.2]: https://github.com/ruby/rdoc/releases/tag/v6.14.2
+[rdoc-v6.15.0]: https://github.com/ruby/rdoc/releases/tag/v6.15.0
+[rdoc-v6.15.1]: https://github.com/ruby/rdoc/releases/tag/v6.15.1
+[rdoc-v6.16.0]: https://github.com/ruby/rdoc/releases/tag/v6.16.0
+[rdoc-v6.16.1]: https://github.com/ruby/rdoc/releases/tag/v6.16.1
+[rdoc-v6.17.0]: https://github.com/ruby/rdoc/releases/tag/v6.17.0
+[rdoc-v7.0.0]: https://github.com/ruby/rdoc/releases/tag/v7.0.0
+[rdoc-v7.0.1]: https://github.com/ruby/rdoc/releases/tag/v7.0.1
+[rdoc-v7.0.2]: https://github.com/ruby/rdoc/releases/tag/v7.0.2
+[rdoc-v7.0.3]: https://github.com/ruby/rdoc/releases/tag/v7.0.3
+[win32ole-v1.9.2]: https://github.com/ruby/win32ole/releases/tag/v1.9.2
+[irb-v1.15.0]: https://github.com/ruby/irb/releases/tag/v1.15.0
+[irb-v1.15.1]: https://github.com/ruby/irb/releases/tag/v1.15.1
+[irb-v1.15.2]: https://github.com/ruby/irb/releases/tag/v1.15.2
+[irb-v1.15.3]: https://github.com/ruby/irb/releases/tag/v1.15.3
+[irb-v1.16.0]: https://github.com/ruby/irb/releases/tag/v1.16.0
+[reline-v0.6.1]: https://github.com/ruby/reline/releases/tag/v0.6.1
+[reline-v0.6.2]: https://github.com/ruby/reline/releases/tag/v0.6.2
+[reline-v0.6.3]: https://github.com/ruby/reline/releases/tag/v0.6.3
+[fiddle-v1.1.7]: https://github.com/ruby/fiddle/releases/tag/v1.1.7
+[fiddle-v1.1.8]: https://github.com/ruby/fiddle/releases/tag/v1.1.8
+[date-v3.5.0]: https://github.com/ruby/date/releases/tag/v3.5.0
+[date-v3.5.1]: https://github.com/ruby/date/releases/tag/v3.5.1
+[delegate-v0.5.0]: https://github.com/ruby/delegate/releases/tag/v0.5.0
+[delegate-v0.6.0]: https://github.com/ruby/delegate/releases/tag/v0.6.0
+[delegate-v0.6.1]: https://github.com/ruby/delegate/releases/tag/v0.6.1
+[digest-v3.2.1]: https://github.com/ruby/digest/releases/tag/v3.2.1
+[english-v0.8.1]: https://github.com/ruby/english/releases/tag/v0.8.1
+[erb-v5.1.2]: https://github.com/ruby/erb/releases/tag/v5.1.2
+[erb-v5.1.3]: https://github.com/ruby/erb/releases/tag/v5.1.3
+[erb-v6.0.0]: https://github.com/ruby/erb/releases/tag/v6.0.0
+[erb-v6.0.1]: https://github.com/ruby/erb/releases/tag/v6.0.1
+[fcntl-v1.3.0]: https://github.com/ruby/fcntl/releases/tag/v1.3.0
+[fileutils-v1.8.0]: https://github.com/ruby/fileutils/releases/tag/v1.8.0
+[forwardable-v1.4.0]: https://github.com/ruby/forwardable/releases/tag/v1.4.0
+[io-console-v0.8.2]: https://github.com/ruby/io-console/releases/tag/v0.8.2
+[io-wait-v0.3.3]: https://github.com/ruby/io-wait/releases/tag/v0.3.3
+[io-wait-v0.3.5.test1]: https://github.com/ruby/io-wait/releases/tag/v0.3.5.test1
+[io-wait-v0.3.5]: https://github.com/ruby/io-wait/releases/tag/v0.3.5
+[io-wait-v0.3.6]: https://github.com/ruby/io-wait/releases/tag/v0.3.6
+[io-wait-v0.4.0]: https://github.com/ruby/io-wait/releases/tag/v0.4.0
+[json-v2.10.0]: https://github.com/ruby/json/releases/tag/v2.10.0
+[json-v2.10.1]: https://github.com/ruby/json/releases/tag/v2.10.1
+[json-v2.10.2]: https://github.com/ruby/json/releases/tag/v2.10.2
+[json-v2.11.0]: https://github.com/ruby/json/releases/tag/v2.11.0
+[json-v2.11.1]: https://github.com/ruby/json/releases/tag/v2.11.1
+[json-v2.11.2]: https://github.com/ruby/json/releases/tag/v2.11.2
+[json-v2.11.3]: https://github.com/ruby/json/releases/tag/v2.11.3
+[json-v2.12.0]: https://github.com/ruby/json/releases/tag/v2.12.0
+[json-v2.12.1]: https://github.com/ruby/json/releases/tag/v2.12.1
+[json-v2.12.2]: https://github.com/ruby/json/releases/tag/v2.12.2
+[json-v2.13.0]: https://github.com/ruby/json/releases/tag/v2.13.0
+[json-v2.13.1]: https://github.com/ruby/json/releases/tag/v2.13.1
+[json-v2.13.2]: https://github.com/ruby/json/releases/tag/v2.13.2
+[json-v2.14.0]: https://github.com/ruby/json/releases/tag/v2.14.0
+[json-v2.14.1]: https://github.com/ruby/json/releases/tag/v2.14.1
+[json-v2.15.0]: https://github.com/ruby/json/releases/tag/v2.15.0
+[json-v2.15.1]: https://github.com/ruby/json/releases/tag/v2.15.1
+[json-v2.15.2]: https://github.com/ruby/json/releases/tag/v2.15.2
+[json-v2.16.0]: https://github.com/ruby/json/releases/tag/v2.16.0
+[json-v2.17.0]: https://github.com/ruby/json/releases/tag/v2.17.0
+[json-v2.17.1]: https://github.com/ruby/json/releases/tag/v2.17.1
+[json-v2.18.0]: https://github.com/ruby/json/releases/tag/v2.18.0
+[net-http-v0.7.0]: https://github.com/ruby/net-http/releases/tag/v0.7.0
+[net-http-v0.8.0]: https://github.com/ruby/net-http/releases/tag/v0.8.0
+[net-http-v0.9.0]: https://github.com/ruby/net-http/releases/tag/v0.9.0
+[net-http-v0.9.1]: https://github.com/ruby/net-http/releases/tag/v0.9.1
+[openssl-v3.3.2]: https://github.com/ruby/openssl/releases/tag/v3.3.2
+[openssl-v4.0.0]: https://github.com/ruby/openssl/releases/tag/v4.0.0
+[optparse-v0.7.0]: https://github.com/ruby/optparse/releases/tag/v0.7.0
+[optparse-v0.8.0]: https://github.com/ruby/optparse/releases/tag/v0.8.0
+[optparse-v0.8.1]: https://github.com/ruby/optparse/releases/tag/v0.8.1
+[pp-v0.6.3]: https://github.com/ruby/pp/releases/tag/v0.6.3
+[prism-v1.6.0]: https://github.com/ruby/prism/releases/tag/v1.6.0
+[prism-v1.7.0]: https://github.com/ruby/prism/releases/tag/v1.7.0
+[psych-v5.2.3]: https://github.com/ruby/psych/releases/tag/v5.2.3
+[psych-v5.2.4]: https://github.com/ruby/psych/releases/tag/v5.2.4
+[psych-v5.2.5]: https://github.com/ruby/psych/releases/tag/v5.2.5
+[psych-v5.2.6]: https://github.com/ruby/psych/releases/tag/v5.2.6
+[psych-v5.3.0]: https://github.com/ruby/psych/releases/tag/v5.3.0
+[psych-v5.3.1]: https://github.com/ruby/psych/releases/tag/v5.3.1
+[resolv-v0.6.3]: https://github.com/ruby/resolv/releases/tag/v0.6.3
+[resolv-v0.7.0]: https://github.com/ruby/resolv/releases/tag/v0.7.0
+[stringio-v3.1.3]: https://github.com/ruby/stringio/releases/tag/v3.1.3
+[stringio-v3.1.4]: https://github.com/ruby/stringio/releases/tag/v3.1.4
+[stringio-v3.1.5]: https://github.com/ruby/stringio/releases/tag/v3.1.5
+[stringio-v3.1.6]: https://github.com/ruby/stringio/releases/tag/v3.1.6
+[stringio-v3.1.7]: https://github.com/ruby/stringio/releases/tag/v3.1.7
+[stringio-v3.1.8]: https://github.com/ruby/stringio/releases/tag/v3.1.8
+[stringio-v3.1.9]: https://github.com/ruby/stringio/releases/tag/v3.1.9
+[stringio-v3.2.0]: https://github.com/ruby/stringio/releases/tag/v3.2.0
+[strscan-v3.1.3]: https://github.com/ruby/strscan/releases/tag/v3.1.3
+[strscan-v3.1.4]: https://github.com/ruby/strscan/releases/tag/v3.1.4
+[strscan-v3.1.5]: https://github.com/ruby/strscan/releases/tag/v3.1.5
+[strscan-v3.1.6]: https://github.com/ruby/strscan/releases/tag/v3.1.6
+[time-v0.4.2]: https://github.com/ruby/time/releases/tag/v0.4.2
+[timeout-v0.4.4]: https://github.com/ruby/timeout/releases/tag/v0.4.4
+[timeout-v0.5.0]: https://github.com/ruby/timeout/releases/tag/v0.5.0
+[timeout-v0.6.0]: https://github.com/ruby/timeout/releases/tag/v0.6.0
+[uri-v1.1.0]: https://github.com/ruby/uri/releases/tag/v1.1.0
+[uri-v1.1.1]: https://github.com/ruby/uri/releases/tag/v1.1.1
+[weakref-v0.1.4]: https://github.com/ruby/weakref/releases/tag/v0.1.4
+[zlib-v3.2.2]: https://github.com/ruby/zlib/releases/tag/v3.2.2
+[power_assert-v3.0.0]: https://github.com/ruby/power_assert/releases/tag/v3.0.0
+[power_assert-v3.0.1]: https://github.com/ruby/power_assert/releases/tag/v3.0.1
+[rake-v13.3.0]: https://github.com/ruby/rake/releases/tag/v13.3.0
+[rake-v13.3.1]: https://github.com/ruby/rake/releases/tag/v13.3.1
+[test-unit-3.6.8]: https://github.com/test-unit/test-unit/releases/tag/3.6.8
+[test-unit-3.6.9]: https://github.com/test-unit/test-unit/releases/tag/3.6.9
+[test-unit-3.7.0]: https://github.com/test-unit/test-unit/releases/tag/3.7.0
+[test-unit-3.7.1]: https://github.com/test-unit/test-unit/releases/tag/3.7.1
+[test-unit-3.7.2]: https://github.com/test-unit/test-unit/releases/tag/3.7.2
+[test-unit-3.7.3]: https://github.com/test-unit/test-unit/releases/tag/3.7.3
+[test-unit-3.7.4]: https://github.com/test-unit/test-unit/releases/tag/3.7.4
+[test-unit-3.7.5]: https://github.com/test-unit/test-unit/releases/tag/3.7.5
+[rss-0.3.2]: https://github.com/ruby/rss/releases/tag/0.3.2
+[net-ftp-v0.3.9]: https://github.com/ruby/net-ftp/releases/tag/v0.3.9
+[net-imap-v0.5.9]: https://github.com/ruby/net-imap/releases/tag/v0.5.9
+[net-imap-v0.5.10]: https://github.com/ruby/net-imap/releases/tag/v0.5.10
+[net-imap-v0.5.11]: https://github.com/ruby/net-imap/releases/tag/v0.5.11
+[net-imap-v0.5.12]: https://github.com/ruby/net-imap/releases/tag/v0.5.12
+[net-imap-v0.5.13]: https://github.com/ruby/net-imap/releases/tag/v0.5.13
+[net-imap-v0.6.0]: https://github.com/ruby/net-imap/releases/tag/v0.6.0
+[net-imap-v0.6.1]: https://github.com/ruby/net-imap/releases/tag/v0.6.1
+[net-imap-v0.6.2]: https://github.com/ruby/net-imap/releases/tag/v0.6.2
+[net-smtp-v0.5.1]: https://github.com/ruby/net-smtp/releases/tag/v0.5.1
+[matrix-v0.4.3]: https://github.com/ruby/matrix/releases/tag/v0.4.3
+[prime-v0.1.4]: https://github.com/ruby/prime/releases/tag/v0.1.4
+[rbs-v3.8.1]: https://github.com/ruby/rbs/releases/tag/v3.8.1
+[rbs-v3.9.0.dev.1]: https://github.com/ruby/rbs/releases/tag/v3.9.0.dev.1
+[rbs-v3.9.0.pre.1]: https://github.com/ruby/rbs/releases/tag/v3.9.0.pre.1
+[rbs-v3.9.0.pre.2]: https://github.com/ruby/rbs/releases/tag/v3.9.0.pre.2
+[rbs-v3.9.0]: https://github.com/ruby/rbs/releases/tag/v3.9.0
+[rbs-v3.9.1]: https://github.com/ruby/rbs/releases/tag/v3.9.1
+[rbs-v3.9.2]: https://github.com/ruby/rbs/releases/tag/v3.9.2
+[rbs-v3.9.3]: https://github.com/ruby/rbs/releases/tag/v3.9.3
+[rbs-v3.9.4]: https://github.com/ruby/rbs/releases/tag/v3.9.4
+[rbs-v3.9.5]: https://github.com/ruby/rbs/releases/tag/v3.9.5
+[rbs-v3.10.0.pre.1]: https://github.com/ruby/rbs/releases/tag/v3.10.0.pre.1
+[rbs-v3.10.0.pre.2]: https://github.com/ruby/rbs/releases/tag/v3.10.0.pre.2
+[rbs-v3.10.0]: https://github.com/ruby/rbs/releases/tag/v3.10.0
+[debug-v1.11.1]: https://github.com/ruby/debug/releases/tag/v1.11.1
+[base64-v0.3.0]: https://github.com/ruby/base64/releases/tag/v0.3.0
+[bigdecimal-v3.2.0]: https://github.com/ruby/bigdecimal/releases/tag/v3.2.0
+[bigdecimal-v3.2.1]: https://github.com/ruby/bigdecimal/releases/tag/v3.2.1
+[bigdecimal-v3.2.2]: https://github.com/ruby/bigdecimal/releases/tag/v3.2.2
+[bigdecimal-v3.2.3]: https://github.com/ruby/bigdecimal/releases/tag/v3.2.3
+[bigdecimal-v3.3.0]: https://github.com/ruby/bigdecimal/releases/tag/v3.3.0
+[bigdecimal-v3.3.1]: https://github.com/ruby/bigdecimal/releases/tag/v3.3.1
+[bigdecimal-v4.0.0]: https://github.com/ruby/bigdecimal/releases/tag/v4.0.0
+[bigdecimal-v4.0.1]: https://github.com/ruby/bigdecimal/releases/tag/v4.0.1
+[drb-v2.2.3]: https://github.com/ruby/drb/releases/tag/v2.2.3
+[syslog-v0.3.0]: https://github.com/ruby/syslog/releases/tag/v0.3.0
+[csv-v3.3.3]: https://github.com/ruby/csv/releases/tag/v3.3.3
+[csv-v3.3.4]: https://github.com/ruby/csv/releases/tag/v3.3.4
+[csv-v3.3.5]: https://github.com/ruby/csv/releases/tag/v3.3.5
diff --git a/doc/_regexp.rdoc b/doc/_regexp.rdoc
index 7b71eee984..aa55a7eebf 100644
--- a/doc/_regexp.rdoc
+++ b/doc/_regexp.rdoc
@@ -39,7 +39,7 @@ A regexp may be used:
most such methods accept an argument that may be either a string
or the (much more powerful) regexp.
- See {Regexp Methods}[rdoc-ref:regexp/methods.rdoc].
+ See {Regexp Methods}[rdoc-ref:language/regexp/methods.rdoc].
== \Regexp Objects
@@ -78,9 +78,9 @@ A regular expression may be created with:
%r(foo) # => /foo/
%r<foo> # => /foo/
-- \Method Regexp.new.
+- Method Regexp.new.
-== \Method <tt>match</tt>
+== Method <tt>match</tt>
Each of the methods Regexp#match, String#match, and Symbol#match
returns a MatchData object if a match was found, +nil+ otherwise;
@@ -99,7 +99,7 @@ each also sets {global variables}[rdoc-ref:Regexp@Global+Variables]:
'foo bar' =~ /bar/ # => 4
/baz/ =~ 'foo bar' # => nil
-== \Method <tt>match?</tt>
+== Method <tt>match?</tt>
Each of the methods Regexp#match?, String#match?, and Symbol#match?
returns +true+ if a match was found, +false+ otherwise;
@@ -127,6 +127,9 @@ The affected global variables are:
Note that <tt>$0</tt> is quite different;
it returns the name of the currently executing program.
+These variables, except for <tt>$~</tt>, are shorthands for methods of
+<tt>$~</tt>. See MatchData@Global+variables+equivalence.
+
Examples:
# Matched string, but no matched groups.
@@ -212,7 +215,7 @@ Method Regexp.escape returns an escaped string:
=== Source Literals
The source literal largely behaves like a double-quoted string;
-see {String Literals}[rdoc-ref:syntax/literals.rdoc@String+Literals].
+see {Double-Quoted String Literals}[rdoc-ref:syntax/literals.rdoc@Double-Quoted+String+Literals].
In particular, a source literal may contain interpolated expressions:
@@ -411,21 +414,21 @@ Each of these anchors matches a boundary:
Lookahead anchors:
-- <tt>(?=_pat_)</tt>: Positive lookahead assertion:
+- <tt>(?=pat)</tt>: Positive lookahead assertion:
ensures that the following characters match _pat_,
but doesn't include those characters in the matched substring.
-- <tt>(?!_pat_)</tt>: Negative lookahead assertion:
+- <tt>(?!pat)</tt>: Negative lookahead assertion:
ensures that the following characters <i>do not</i> match _pat_,
but doesn't include those characters in the matched substring.
Lookbehind anchors:
-- <tt>(?<=_pat_)</tt>: Positive lookbehind assertion:
+- <tt>(?<=pat)</tt>: Positive lookbehind assertion:
ensures that the preceding characters match _pat_, but
doesn't include those characters in the matched substring.
-- <tt>(?<!_pat_)</tt>: Negative lookbehind assertion:
+- <tt>(?<!pat)</tt>: Negative lookbehind assertion:
ensures that the preceding characters do not match
_pat_, but doesn't include those characters in the matched substring.
@@ -436,6 +439,10 @@ without including the tags in the match:
/(?<=<b>)\w+(?=<\/b>)/.match("Fortune favors the <b>bold</b>.")
# => #<MatchData "bold">
+The pattern in lookbehind must be fixed-width.
+But top-level alternatives can be of various lengths.
+ex. (?<=a|bc) is OK. (?<=aaa(?:b|cd)) is not allowed.
+
==== Match-Reset Anchor
- <tt>\K</tt>: Match reset:
@@ -477,7 +484,7 @@ Each alternative is a subexpression, and may be composed of other subexpressions
re.match('bar') # => #<MatchData "b" 1:"b">
re.match('ooz') # => #<MatchData "z" 1:"z">
-\Method Regexp.union provides a convenient way to construct
+Method Regexp.union provides a convenient way to construct
a regexp with alternatives.
=== Quantifiers
@@ -495,7 +502,7 @@ An added _quantifier_ specifies how many matches are required or allowed:
/\w*/.match('x')
# => #<MatchData "x">
/\w*/.match('xyz')
- # => #<MatchData "yz">
+ # => #<MatchData "xyz">
- <tt>+</tt> - Matches one or more times:
@@ -567,7 +574,7 @@ A simple regexp has (at most) one match:
re.match('1943-02-04').size # => 1
re.match('foo') # => nil
-Adding one or more pairs of parentheses, <tt>(_subexpression_)</tt>,
+Adding one or more pairs of parentheses, <tt>(subexpression)</tt>,
defines _groups_, which may result in multiple matched substrings,
called _captures_:
@@ -640,8 +647,8 @@ A regexp may contain any number of groups:
- For a large number of groups:
- - The ordinary <tt>\\_n_</tt> notation applies only for _n_ in range (1..9).
- - The <tt>MatchData[_n_]</tt> notation applies for any non-negative _n_.
+ - The ordinary <tt>\\n</tt> notation applies only for _n_ in range (1..9).
+ - The <tt>MatchData[n]</tt> notation applies for any non-negative _n_.
- <tt>\0</tt> is a special backreference, referring to the entire matched string;
it may not be used within the regexp itself,
@@ -654,7 +661,7 @@ A regexp may contain any number of groups:
As seen above, a capture can be referred to by its number.
A capture can also have a name,
-prefixed as <tt>?<_name_></tt> or <tt>?'_name_'</tt>,
+prefixed as <tt>?<name></tt> or <tt>?'name'</tt>,
and the name (symbolized) may be used as an index in <tt>MatchData[]</tt>:
md = /\$(?<dollars>\d+)\.(?'cents'\d+)/.match("$3.67")
@@ -669,7 +676,7 @@ When a regexp contains a named capture, there are no unnamed captures:
/\$(?<dollars>\d+)\.(\d+)/.match("$3.67")
# => #<MatchData "$3.67" dollars:"3">
-A named group may be backreferenced as <tt>\k<_name_></tt>:
+A named group may be backreferenced as <tt>\k<name></tt>:
/(?<vowel>[aeiou]).\k<vowel>.\k<vowel>/.match('ototomy')
# => #<MatchData "ototo" vowel:"o">
@@ -682,7 +689,7 @@ the captured substrings are assigned to local variables with corresponding names
dollars # => "3"
cents # => "67"
-\Method Regexp#named_captures returns a hash of the capture names and substrings;
+Method Regexp#named_captures returns a hash of the capture names and substrings;
method Regexp#names returns an array of the capture names.
==== Atomic Grouping
@@ -706,7 +713,7 @@ Analysis:
1. The leading subexpression <tt>"</tt> in the pattern matches the first character
<tt>"</tt> in the target string.
-2. The next subexpression <tt>.*</tt> matches the next substring <tt>Quote“</tt>
+2. The next subexpression <tt>.*</tt> matches the next substring <tt>Quote"</tt>
(including the trailing double-quote).
3. Now there is nothing left in the target string to match
the trailing subexpression <tt>"</tt> in the pattern;
@@ -725,10 +732,10 @@ see {Atomic Group}[https://www.regular-expressions.info/atomic.html].
==== Subexpression Calls
-As seen above, a backreference number (<tt>\\_n_</tt>) or name (<tt>\k<_name_></tt>)
+As seen above, a backreference number (<tt>\\n</tt>) or name (<tt>\k<name></tt>)
gives access to a captured _substring_;
the corresponding regexp _subexpression_ may also be accessed,
-via the number (<tt>\\g<i>n</i></tt>) or name (<tt>\g<_name_></tt>):
+via the number n (<tt>\\gn</tt>) or name (<tt>\g<name></tt>):
/\A(?<paren>\(\g<paren>*\))*\z/.match('(())')
# ^1
@@ -761,12 +768,12 @@ See {Subexpression calls}[https://learnbyexample.github.io/Ruby_Regexp/groupings
==== Conditionals
-The conditional construct takes the form <tt>(?(_cond_)_yes_|_no_)</tt>, where:
+The conditional construct takes the form <tt>(?(cond)yes|no)</tt>, where:
- _cond_ may be a capture number or name.
- The match to be applied is _yes_ if _cond_ is captured;
otherwise the match to be applied is _no_.
-- If not needed, <tt>|_no_</tt> may be omitted.
+- If not needed, <tt>|no</tt> may be omitted.
Examples:
@@ -795,7 +802,7 @@ The absence operator is a special group that matches anything which does _not_ m
==== Unicode Properties
-The <tt>/\p{_property_name_}/</tt> construct (with lowercase +p+)
+The <tt>/\p{property_name}/</tt> construct (with lowercase +p+)
matches characters using a Unicode property name,
much like a character class;
property +Alpha+ specifies alphabetic characters:
@@ -814,7 +821,7 @@ Or by using <tt>\P</tt> (uppercase +P+):
/\P{Alpha}/.match('1') # => #<MatchData "1">
/\P{Alpha}/.match('a') # => nil
-See {Unicode Properties}[rdoc-ref:regexp/unicode_properties.rdoc]
+See {Unicode Properties}[rdoc-ref:language/regexp/unicode_properties.rdoc]
for regexps based on the numerous properties.
Some commonly-used properties correspond to POSIX bracket expressions:
@@ -836,8 +843,9 @@ Some commonly-used properties correspond to POSIX bracket expressions:
These are also commonly used:
- <tt>/\p{Emoji}/</tt>: Unicode emoji.
-- <tt>/\p{Graph}/</tt>: Non-blank character
- (excludes spaces, control characters, and similar).
+- <tt>/\p{Graph}/</tt>: Characters excluding <tt>/\p{Cntrl}/</tt> and <tt>/\p{Space}/</tt>.
+ Note that invisible characters under the Unicode
+ {"Format"}[https://www.compart.com/en/unicode/category/Cf] category are included.
- <tt>/\p{Word}/</tt>: A member in one of these Unicode character
categories (see below) or having one of these Unicode properties:
@@ -897,7 +905,7 @@ Numbers:
- {Nl, Letter_Number}[https://www.compart.com/en/unicode/category/Nl].
- {No, Other_Number}[https://www.compart.com/en/unicode/category/No].
-Punctation:
+Punctuation:
- +P+, +Punctuation+: +Pc+, +Pd+, +Pe+, +Pf+, +Pi+, +Po+, or +Ps+.
- {Pc, Connector_Punctuation}[https://www.compart.com/en/unicode/category/Pc].
@@ -1025,23 +1033,23 @@ See also {Extended Mode}[rdoc-ref:Regexp@Extended+Mode].
Each of these modifiers sets a mode for the regexp:
-- +i+: <tt>/_pattern_/i</tt> sets
+- +i+: <tt>/pattern/i</tt> sets
{Case-Insensitive Mode}[rdoc-ref:Regexp@Case-Insensitive+Mode].
-- +m+: <tt>/_pattern_/m</tt> sets
+- +m+: <tt>/pattern/m</tt> sets
{Multiline Mode}[rdoc-ref:Regexp@Multiline+Mode].
-- +x+: <tt>/_pattern_/x</tt> sets
+- +x+: <tt>/pattern/x</tt> sets
{Extended Mode}[rdoc-ref:Regexp@Extended+Mode].
-- +o+: <tt>/_pattern_/o</tt> sets
+- +o+: <tt>/pattern/o</tt> sets
{Interpolation Mode}[rdoc-ref:Regexp@Interpolation+Mode].
Any, all, or none of these may be applied.
Modifiers +i+, +m+, and +x+ may be applied to subexpressions:
-- <tt>(?_modifier_)</tt> turns the mode "on" for ensuing subexpressions
-- <tt>(?-_modifier_)</tt> turns the mode "off" for ensuing subexpressions
-- <tt>(?_modifier_:_subexp_)</tt> turns the mode "on" for _subexp_ within the group
-- <tt>(?-_modifier_:_subexp_)</tt> turns the mode "off" for _subexp_ within the group
+- <tt>(?modifier)</tt> turns the mode "on" for ensuing subexpressions
+- <tt>(?-modifier)</tt> turns the mode "off" for ensuing subexpressions
+- <tt>(?modifier:subexp)</tt> turns the mode "on" for _subexp_ within the group
+- <tt>(?-modifier:subexp)</tt> turns the mode "off" for _subexp_ within the group
Example:
@@ -1050,13 +1058,13 @@ Example:
re.match('TEst') # => #<MatchData "TEst">
re.match('TEST') # => nil
re.match('teST') # => nil
-
+
re = /t(?i:e)st/
re.match('test') # => #<MatchData "test">
re.match('tEst') # => #<MatchData "tEst">
re.match('tEST') # => nil
-\Method Regexp#options returns an integer whose value showing
+Method Regexp#options returns an integer whose value showing
the settings for case-insensitivity mode, multiline mode, and extended mode.
=== Case-Insensitive Mode
@@ -1070,7 +1078,7 @@ Modifier +i+ enables case-insensitive mode:
/foo/i.match('FOO')
# => #<MatchData "FOO">
-\Method Regexp#casefold? returns whether the mode is case-insensitive.
+Method Regexp#casefold? returns whether the mode is case-insensitive.
=== Multiline Mode
@@ -1158,22 +1166,22 @@ A regular expression containing non-US-ASCII characters
is assumed to use the source encoding.
This can be overridden with one of the following modifiers.
-- <tt>/_pat_/n</tt>: US-ASCII if only containing US-ASCII characters,
+- <tt>/pat/n</tt>: US-ASCII if only containing US-ASCII characters,
otherwise ASCII-8BIT:
/foo/n.encoding # => #<Encoding:US-ASCII>
/foo\xff/n.encoding # => #<Encoding:ASCII-8BIT>
/foo\x7f/n.encoding # => #<Encoding:US-ASCII>
-- <tt>/_pat_/u</tt>: UTF-8
+- <tt>/pat/u</tt>: UTF-8
/foo/u.encoding # => #<Encoding:UTF-8>
-- <tt>/_pat_/e</tt>: EUC-JP
+- <tt>/pat/e</tt>: EUC-JP
/foo/e.encoding # => #<Encoding:EUC-JP>
-- <tt>/_pat_/s</tt>: Windows-31J
+- <tt>/pat/s</tt>: Windows-31J
/foo/s.encoding # => #<Encoding:Windows-31J>
@@ -1243,7 +1251,7 @@ the potential vulnerability arising from this is the {regular expression denial-
\Regexp matching can apply an optimization to prevent ReDoS attacks.
When the optimization is applied, matching time increases linearly (not polynomially or exponentially)
-in relation to the input size, and a ReDoS attach is not possible.
+in relation to the input size, and a ReDoS attack is not possible.
This optimization is applied if the pattern meets these criteria:
@@ -1264,13 +1272,13 @@ because the optimization uses memoization (which may invoke large memory consump
== References
-Read (online PDF books):
+Read:
-- {Mastering Regular Expressions}[https://ia902508.us.archive.org/10/items/allitebooks-02/Mastering%20Regular%20Expressions%2C%203rd%20Edition.pdf]
+- <i>Mastering Regular Expressions</i>
by Jeffrey E.F. Friedl.
-- {Regular Expressions Cookbook}[https://doc.lagout.org/programmation/Regular%20Expressions/Regular%20Expressions%20Cookbook_%20Detailed%20Solutions%20in%20Eight%20Programming%20Languages%20%282nd%20ed.%29%20%5BGoyvaerts%20%26%20Levithan%202012-09-06%5D.pdf]
+- <i>Regular Expressions Cookbook</i>
by Jan Goyvaerts & Steven Levithan.
-Explore, test (interactive online editor):
+Explore, test:
-- {Rubular}[https://rubular.com/].
+- {Rubular}[https://rubular.com/]: interactive online editor.
diff --git a/doc/_timezones.rdoc b/doc/_timezones.rdoc
index c5230ea67d..a2ac46584f 100644
--- a/doc/_timezones.rdoc
+++ b/doc/_timezones.rdoc
@@ -64,43 +64,50 @@ The timezone methods are:
- +local_to_utc+:
- - Called when Time.new is invoked with +tz+
- as the value of positional argument +zone+ or keyword argument +in:+.
- - Argument: a {Time-like object}[rdoc-ref:Time@Time-Like+Objects].
- - Returns: a {Time-like object}[rdoc-ref:Time@Time-Like+Objects] in the UTC timezone.
+ Called when Time.new is invoked with +tz+ as the value of positional
+ argument +zone+ or keyword argument +in:+.
+
+ Argument:: a {Time-like object}[rdoc-ref:Time@Time-Like+Objects].
+ Returns:: a {Time-like object}[rdoc-ref:Time@Time-Like+Objects] in the UTC timezone.
- +utc_to_local+:
- - Called when Time.at or Time.now is invoked with +tz+
- as the value for keyword argument +in:+,
- and when Time#getlocal or Time#localtime is called with +tz+
- as the value for positional argument +zone+.
- - Argument: a {Time-like object}[rdoc-ref:Time@Time-Like+Objects].
- - Returns: a {Time-like object}[rdoc-ref:Time@Time-Like+Objects] in the local timezone.
+ Called when Time.at or Time.now is invoked with +tz+ as the value for
+ keyword argument +in:+, and when Time#getlocal or Time#localtime is called
+ with +tz+ as the value for positional argument +zone+.
+
+ The UTC offset will be calculated as the difference between the
+ original time and the returned object as an +Integer+.
+ If the object is in fixed offset, its +utc_offset+ is also counted.
+
+ Argument:: a {Time-like object}[rdoc-ref:Time@Time-Like+Objects].
+ Returns:: a {Time-like object}[rdoc-ref:Time@Time-Like+Objects] in the local timezone.
A custom timezone class may have these instance methods,
which will be called if defined:
- +abbr+:
- - Called when Time#strftime is invoked with a format involving <tt>%Z</tt>.
- - Argument: a {Time-like object}[rdoc-ref:Time@Time-Like+Objects].
- - Returns: a string abbreviation for the timezone name.
+ Called when Time#strftime is invoked with a format involving <tt>%Z</tt>.
+
+ Argument:: a {Time-like object}[rdoc-ref:Time@Time-Like+Objects].
+ Returns:: a string abbreviation for the timezone name.
- +dst?+:
- - Called when Time.at or Time.now is invoked with +tz+
- as the value for keyword argument +in:+,
- and when Time#getlocal or Time#localtime is called with +tz+
- as the value for positional argument +zone+.
- - Argument: a {Time-like object}[rdoc-ref:Time@Time-Like+Objects].
- - Returns: whether the time is daylight saving time.
+ Called when Time.at or Time.now is invoked with +tz+ as the value for
+ keyword argument +in:+, and when Time#getlocal or Time#localtime is
+ called with +tz+ as the value for positional argument +zone+.
+
+ Argument:: a {Time-like object}[rdoc-ref:Time@Time-Like+Objects].
+ Returns:: whether the time is daylight saving time.
- +name+:
- - Called when <tt>Marshal.dump(t)</tt> is invoked
- - Argument: none.
- - Returns: the string name of the timezone.
+ Called when <tt>Marshal.dump(t)</tt> is invoked
+
+ Argument:: none.
+ Returns:: the string name of the timezone.
==== +Time+-Like Objects
diff --git a/doc/case_mapping.rdoc b/doc/case_mapping.rdoc
deleted file mode 100644
index 57c037b9d8..0000000000
--- a/doc/case_mapping.rdoc
+++ /dev/null
@@ -1,116 +0,0 @@
-= 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 {Section 3.13 (Default Case Algorithms) of the Unicode standard}[https://www.unicode.org/versions/latest/ch03.pdf].
-
-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 (Context Specification for Casing) of the Unicode standard}[https://www.unicode.org/versions/latest/ch03.pdf]
-is currently not supported.
-
-In most cases, case conversions of a string have the same number of characters.
-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, <tt>*options</tt>.
-
-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/doc/character_selectors.rdoc b/doc/character_selectors.rdoc
deleted file mode 100644
index 47cf242be7..0000000000
--- a/doc/character_selectors.rdoc
+++ /dev/null
@@ -1,97 +0,0 @@
-= Character Selectors
-
-== Character Selector
-
-A _character_ _selector_ is a string argument accepted by certain Ruby methods.
-Each of these instance methods accepts one or more character selectors:
-
-- String#tr(selector, replacements): returns a new string.
-- String#tr!(selector, replacements): returns +self+ or +nil+.
-- String#tr_s(selector, replacements): returns a new string.
-- String#tr_s!(selector, replacements): returns +self+ or +nil+.
-- String#count(*selectors): returns the count of the specified characters.
-- String#delete(*selectors): returns a new string.
-- String#delete!(*selectors): returns +self+ or +nil+.
-- String#squeeze(*selectors): returns a new string.
-- String#squeeze!(*selectors): returns +self+ or +nil+.
-
-A character selector identifies zero or more characters in +self+
-that are to be operands for the method.
-
-In this section, we illustrate using method String#delete(selector),
-which deletes the selected characters.
-
-In the simplest case, the characters selected are exactly those
-contained in the selector itself:
-
- 'abracadabra'.delete('a') # => "brcdbr"
- 'abracadabra'.delete('ab') # => "rcdr"
- 'abracadabra'.delete('abc') # => "rdr"
- '0123456789'.delete('258') # => "0134679"
- '!@#$%&*()_+'.delete('+&#') # => "!@$%*()_"
- 'тест'.delete('т') # => "ес"
- 'こんにちは'.delete('に') # => "こんちは"
-
-Note that order and repetitions do not matter:
-
- 'abracadabra'.delete('dcab') # => "rr"
- 'abracadabra'.delete('aaaa') # => "brcdbr"
-
-In a character selector, these three characters get special treatment:
-
-- A leading caret (<tt>'^'</tt>) functions as a "not" operator
- for the characters to its right:
-
- 'abracadabra'.delete('^bc') # => "bcb"
- '0123456789'.delete('^852') # => "258"
-
-- A hyphen (<tt>'-'</tt>) between two other characters
- defines a range of characters instead of a plain string of characters:
-
- 'abracadabra'.delete('a-d') # => "rr"
- '0123456789'.delete('4-7') # => "012389"
- '!@#$%&*()_+'.delete(' -/') # => "@^_"
-
- # May contain more than one range.
- 'abracadabra'.delete('a-cq-t') # => "d"
-
- # Ranges may be mixed with plain characters.
- '0123456789'.delete('67-950-23') # => "4"
-
- # Ranges may be mixed with negations.
- 'abracadabra'.delete('^a-c') # => "abacaaba"
-
-- A backslash (<tt>'\'</tt>) acts as an escape for a caret, a hyphen,
- or another backslash:
-
- 'abracadabra^'.delete('\^bc') # => "araadara"
- 'abracadabra-'.delete('a\-d') # => "brcbr"
- "hello\r\nworld".delete("\r") # => "hello\nworld"
- "hello\r\nworld".delete("\\r") # => "hello\r\nwold"
- "hello\r\nworld".delete("\\\r") # => "hello\nworld"
-
-== Multiple Character Selectors
-
-These instance methods accept multiple character selectors:
-
-- String#count(*selectors): returns the count of the specified characters.
-- String#delete(*selectors): returns a new string.
-- String#delete!(*selectors): returns +self+ or +nil+.
-- String#squeeze(*selectors): returns a new string.
-- String#squeeze!(*selectors): returns +self+ or +nil+.
-
-In effect, the given selectors are formed into a single selector
-consisting of only those characters common to _all_ of the given selectors.
-
-All forms of selectors may be used, including negations, ranges, and escapes.
-
-Each of these pairs of method calls is equivalent:
-
- s.delete('abcde', 'dcbfg')
- s.delete('bcd')
-
- s.delete('^abc', '^def')
- s.delete('^abcdef')
-
- s.delete('a-e', 'c-g')
- s.delete('cde')
diff --git a/doc/command_injection.rdoc b/doc/command_injection.rdoc
deleted file mode 100644
index ee33d4a04e..0000000000
--- a/doc/command_injection.rdoc
+++ /dev/null
@@ -1,37 +0,0 @@
-= Command Injection
-
-Some Ruby core methods accept string data
-that includes text to be executed as a system command.
-
-They should not be called with unknown or unsanitized commands.
-
-These methods include:
-
-- Kernel.exec
-- Kernel.spawn
-- Kernel.system
-- {\`command` (backtick method)}[rdoc-ref:Kernel#`]
- (also called by the expression <tt>%x[command]</tt>).
-- IO.popen (when called with other than <tt>"-"</tt>).
-
-Some methods execute a system command only if the given path name starts
-with a <tt>|</tt>:
-
-- Kernel.open(command).
-- IO.read(command).
-- IO.write(command).
-- IO.binread(command).
-- IO.binwrite(command).
-- IO.readlines(command).
-- IO.foreach(command).
-- URI.open(command).
-
-Note that some of these methods do not execute commands when called
-from subclass +File+:
-
-- File.read(path).
-- File.write(path).
-- File.binread(path).
-- File.binwrite(path).
-- File.readlines(path).
-- File.foreach(path).
diff --git a/doc/command_line/environment.md b/doc/command_line/environment.md
deleted file mode 100644
index abdfd5cfeb..0000000000
--- a/doc/command_line/environment.md
+++ /dev/null
@@ -1,173 +0,0 @@
-## Environment
-
-Certain command-line options affect the execution environment
-of the invoked Ruby program.
-
-### About the Examples
-
-The examples here use command-line option `-e`,
-which passes the Ruby code to be executed on the command line itself:
-
-```sh
-$ ruby -e 'puts "Hello, World."'
-```
-
-### Option `-C`
-
-The argument to option `-C` specifies a working directory
-for the invoked Ruby program;
-does not change the working directory for the current process:
-
-```sh
-$ basename `pwd`
-ruby
-$ ruby -C lib -e 'puts File.basename(Dir.pwd)'
-lib
-$ basename `pwd`
-ruby
-```
-
-Whitespace between the option and its argument may be omitted.
-
-### Option `-I`
-
-The argument to option `-I` specifies a directory
-to be added to the array in global variable `$LOAD_PATH`;
-the option may be given more than once:
-
-```sh
-$ pushd /tmp
-$ ruby -e 'p $LOAD_PATH.size'
-8
-$ ruby -I my_lib -I some_lib -e 'p $LOAD_PATH.size'
-10
-$ ruby -I my_lib -I some_lib -e 'p $LOAD_PATH.take(2)'
-["/tmp/my_lib", "/tmp/some_lib"]
-$ popd
-```
-
-Whitespace between the option and its argument may be omitted.
-
-### Option `-r`
-
-The argument to option `-r` specifies a library to be required
-before executing the Ruby program;
-the option may be given more than once:
-
-```sh
-$ ruby -e 'p defined?(JSON); p defined?(CSV)'
-nil
-nil
-$ ruby -r CSV -r JSON -e 'p defined?(JSON); p defined?(CSV)'
-"constant"
-"constant"
-```
-
-Whitespace between the option and its argument may be omitted.
-
-### Option `-0`
-
-Option `-0` defines the input record separator `$/`
-for the invoked Ruby program.
-
-The optional argument to the option must be octal digits,
-each in the range `0..7`;
-these digits are prefixed with digit `0` to form an octal value:
-
-- If no argument is given, the input record separator is `0x00`.
-- If the argument is `0`, the input record separator is `''`;
- see {Special Line Separator Values}[rdoc-ref:IO@Special+Line+Separator+Values].
-- If the argument is in range `(1..0377)`,
- it becomes the character value of the input record separator `$/`.
-- Otherwise, the input record separator is `nil`.
-
-Examples:
-
-```sh
-$ ruby -0 -e 'p $/'
-"\x00"
-ruby -00 -e 'p $/'
-""
-$ ruby -012 -e 'p $/'
-"\n"
-$ ruby -015 -e 'p $/'
-"\r"
-$ ruby -0377 -e 'p $/'
-"\xFF"
-$ ruby -0400 -e 'p $/'
-nil
-```
-
-The option may not be separated from its argument by whitespace.
-
-### Option `-d`
-
-Some code in (or called by) the Ruby program may include statements or blocks
-conditioned by the global variable `$DEBUG` (e.g., `if $DEBUG`);
-these commonly write to `$stdout` or `$stderr`.
-
-The default value for `$DEBUG` is `false`;
-option `-d` (or `--debug`) sets it to `true`:
-
-```sh
-$ ruby -e 'p $DEBUG'
-false
-$ ruby -d -e 'p $DEBUG'
-true
-```
-
-### Option '-w'
-
-Option `-w` (lowercase letter) is equivalent to option `-W1` (uppercase letter).
-
-### Option `-W`
-
-Any Ruby code can create a <i>warning message</i> by calling method Kernel#warn;
-methods in the Ruby core and standard libraries can also create warning messages.
-Such a message may be printed on `$stderr`
-(or not, depending on certain settings).
-
-Option `-W` helps determine whether a particular warning message
-will be written,
-by setting the initial value of global variable `$-W`:
-
-- `-W0`: Sets `$-W` to `0` (silent; no warnings).
-- `-W1`: Sets `$-W` to `1` (moderate verbosity).
-- `-W2`: Sets `$-W` to `2` (high verbosity).
-- `-W`: Same as `-W2` (high verbosity).
-- Option not given: Same as `-W1` (moderate verbosity).
-
-The value of `$-W`, in turn, determines which warning messages (if any)
-are to be printed to `$stdout` (see Kernel#warn):
-
-```sh
-$ ruby -W1 -e 'p $foo'
-nil
-$ ruby -W2 -e 'p $foo'
--e:1: warning: global variable '$foo' not initialized
-nil
-```
-
-Ruby code may also define warnings for certain categories;
-these are the default settings for the defined categories:
-
-```
-Warning[:experimental] # => true
-Warning[:deprecated] # => false
-Warning[:performance] # => false
-```
-
-They may also be set:
-```
-Warning[:experimental] = false
-Warning[:deprecated] = true
-Warning[:performance] = true
-```
-
-You can suppress a category by prefixing `no-` to the category name:
-
-```
-$ ruby -W:no-experimental -e 'p IO::Buffer.new'
-#<IO::Buffer>
-```
-
diff --git a/doc/contributing.md b/doc/contributing.md
deleted file mode 100644
index a6c63de9b2..0000000000
--- a/doc/contributing.md
+++ /dev/null
@@ -1,12 +0,0 @@
-# Contributing to Ruby
-
-This guide outlines ways to get started with contributing to Ruby:
-
-* [Reporting issues](contributing/reporting_issues.md): How to report issues, how to request features, and how backporting works
-* [Building Ruby](contributing/building_ruby.md): How to build Ruby on your local machine for development
-* [Testing Ruby](contributing/testing_ruby.md): How to test Ruby on your local machine once you've built it
-* [Making changes to Ruby](contributing/making_changes_to_ruby.md): How to submit pull requests
- to change Ruby's documentation, code, test suite, or standard libraries
-* [Making changes to Ruby standard libraries](contributing/making_changes_to_stdlibs.md): How to build, test, and contribute to Ruby standard libraries
-* [Making changes to Ruby documentation](contributing/documentation_guide.md): How to make changes to Ruby documentation
-* [Benchmarking Ruby](https://github.com/ruby/ruby/tree/master/benchmark#make-benchmark): How to benchmark Ruby
diff --git a/doc/bug_triaging.rdoc b/doc/contributing/bug_triaging.rdoc
index 83fe88cabe..83fe88cabe 100644
--- a/doc/bug_triaging.rdoc
+++ b/doc/contributing/bug_triaging.rdoc
diff --git a/doc/contributing/building_ruby.md b/doc/contributing/building_ruby.md
index 832b3687fa..286bd1f116 100644
--- a/doc/contributing/building_ruby.md
+++ b/doc/contributing/building_ruby.md
@@ -8,39 +8,61 @@
For RubyGems, you will also need:
- * OpenSSL 1.1.x or 3.0.x / LibreSSL
- * libyaml 0.1.7 or later
- * zlib
+ * [OpenSSL] 1.1.x or 3.0.x / [LibreSSL]
+ * [libyaml] 0.1.7 or later
+ * [zlib]
If you want to build from the git repository, you will also need:
- * autoconf - 2.67 or later
- * gperf - 3.1 or later
+ * [autoconf] - 2.67 or later
+ * [gperf] - 3.1 or later
* Usually unneeded; only if you edit some source files using gperf
- * ruby - 3.0 or later
+ * ruby - 3.1 or later
* We can upgrade this version to system ruby version of the latest
Ubuntu LTS.
+ * git - 2.32 or later
+ * Anterior versions may work; 2.32 or later will prevent build
+ errors in case your system `.gitconfig` uses `$HOME` paths.
2. Install optional, recommended dependencies:
- * libffi (to build fiddle)
- * gmp (if you with to accelerate Bignum operations)
- * libexecinfo (FreeBSD)
- * rustc - 1.58.0 or later, if you wish to build
- [YJIT](https://docs.ruby-lang.org/en/master/RubyVM/YJIT.html).
+ * [libffi] (to build fiddle)
+ * [gmp] (if you wish to accelerate Bignum operations)
+ * [rustc] - 1.58.0 or later, if you wish to build
+ [YJIT](rdoc-ref:RubyVM::YJIT).
- If you installed the libraries needed for extensions (openssl, readline,
- libyaml, zlib) into other than the OS default place, typically using
- Homebrew on macOS, add `--with-EXTLIB-dir` options to `CONFIGURE_ARGS`
- environment variable.
+ If you want to link the libraries (e.g., gmp) installed into other than
+ the OS default place, typically using Homebrew on macOS, pass the
+ `--with-opt-dir` (or `--with-gmp-dir` for gmp) option to `configure`.
- ``` shell
+ ```sh
+ configure --with-opt-dir=$(brew --prefix gmp):$(brew --prefix jemalloc)
+ ```
+
+ As for the libraries needed for particular extensions only and not for
+ Ruby (openssl, readline, libyaml, zlib), you can add `--with-EXTLIB-dir`
+ options to the command line or to `CONFIGURE_ARGS` environment variable.
+ The command line options will be embedded in `rbconfig.rb`, while the
+ latter environment variable is not embedded and is only used when
+ building the extension libraries.
+
+ ```sh
export CONFIGURE_ARGS=""
for ext in openssl readline libyaml zlib; do
CONFIGURE_ARGS="${CONFIGURE_ARGS} --with-$ext-dir=$(brew --prefix $ext)"
done
```
+[OpenSSL]: https://www.openssl.org
+[LibreSSL]: https://www.libressl.org
+[libyaml]: https://github.com/yaml/libyaml/
+[zlib]: https://www.zlib.net
+[autoconf]: https://www.gnu.org/software/autoconf/
+[gperf]: https://www.gnu.org/software/gperf/
+[libffi]: https://sourceware.org/libffi/
+[gmp]: https://gmplib.org
+[rustc]: https://www.rust-lang.org
+
## Quick start guide
1. Download ruby source code:
@@ -49,11 +71,10 @@
1. Build from the tarball:
- Download the latest tarball from
- [ruby-lang.org](https://www.ruby-lang.org/en/downloads/) and extract
+ Download the latest tarball from [Download Ruby] page and extract
it. Example for Ruby 3.0.2:
- ``` shell
+ ```sh
tar -xzf ruby-3.0.2.tar.gz
cd ruby-3.0.2
```
@@ -62,35 +83,35 @@
Checkout the CRuby source code:
- ``` shell
+ ```sh
git clone https://github.com/ruby/ruby.git
cd ruby
```
- Generate the configure file:
+ Run the GNU Autoconf script (which generates the `configure` script):
- ``` shell
+ ```sh
./autogen.sh
```
-2. Create a `build` directory separate from the source directory:
+2. Create a `build` directory inside the repository directory:
- ``` shell
+ ```sh
mkdir build && cd build
```
- While it's not necessary to build in a separate directory, it's good
+ While it's not necessary to build in a dedicated directory like this, it's good
practice to do so.
-3. We'll install Ruby in `~/.rubies/ruby-master`, so create the directory:
+3. We'll eventually install our new Ruby in `~/.rubies/ruby-master`, so we'll create that directory:
- ``` shell
+ ```sh
mkdir ~/.rubies
```
-4. Run configure:
+4. Run the `configure` script (which generates the `Makefile`):
- ``` shell
+ ```sh
../configure --prefix="${HOME}/.rubies/ruby-master"
```
@@ -99,15 +120,15 @@
5. Build Ruby:
- ``` shell
+ ```sh
make
```
6. [Run tests](testing_ruby.md) to confirm your build succeeded.
-7. Install Ruby:
+7. Install our newly-compiled Ruby into `~/.rubies/ruby-master`:
- ``` shell
+ ```sh
make install
```
@@ -115,6 +136,43 @@
generation with different permissions, you can use `make SUDO=sudo
install`.
+8. You can then try your new Ruby out, for example:
+
+ ```sh
+ ~/.rubies/ruby-master/bin/ruby -e "puts 'Hello, World!'"
+ ```
+
+By the end, your repo will look like this:
+
+```text
+ruby
+├── autogen.sh # Pre-existing Autoconf script, used in step 1
+├── configure # Generated in step 1, which generates the `Makefile` in step 4
+├── build # Created in step 2 and populated in step 4
+│ ├── GNUmakefile # Generated by `../configure`
+│ ├── Makefile # Generated by `../configure`
+│ ├── object.o # Compiled object file, built my `make`
+│ └── ... other compiled `.o` object files
+│
+│ # Other interesting files:
+├── include
+│ └── ruby.h # The main public header
+├── internal
+│ ├── object.h
+│ └── ... other header files used by the `.c` files in the repo root.
+├── lib
+│ └── # Default gems, like `bundler`, `erb`, `set`, `yaml`, etc.
+├── spec
+│ └── # A mirror of the Ruby specification from github.com/ruby/spec
+├── test
+│ ├── ruby
+│ └── ...
+├── object.c
+└── ... other `.c` files
+```
+
+[Download Ruby]: https://www.ruby-lang.org/en/downloads/
+
### Unexplainable Build Errors
If you are having unexplainable build errors, after saving all your work, try
@@ -125,7 +183,8 @@ cause build failures.
## Building on Windows
-The documentation for building on Windows can be found [here](../windows.md).
+The documentation for building on Windows can be found in [the separated
+file](../distribution/windows.md).
## More details
@@ -134,24 +193,21 @@ about Ruby's build to help out.
### Running make scripts in parallel
-In GNU make and BSD make implementations, to run a specific make script in
+In GNU make[^caution-gmake-3] and BSD make implementations, to run a specific make script in
parallel, pass the flag `-j<number of processes>`. For instance, to run tests
on 8 processes, use:
-``` shell
+```sh
make test-all -j8
```
-**CAUTION**: GNU make 3 is missing some features for parallel execution, we
-recommend to upgrade to GNU make 4 or later.
-
We can also set `MAKEFLAGS` to run _all_ `make` commands in parallel.
Having the right `--jobs` flag will ensure all processors are utilized when
building software projects. To do this effectively, you can set `MAKEFLAGS` in
your shell configuration/profile:
-``` shell
+```sh
# On macOS with Fish shell:
export MAKEFLAGS="--jobs "(sysctl -n hw.ncpu)
@@ -165,6 +221,9 @@ export MAKEFLAGS="--jobs "(nproc)
export MAKEFLAGS="--jobs $(nproc)"
```
+[^caution-gmake-3]: **CAUTION**: GNU make 3 is missing some features for parallel execution, we
+recommend to upgrade to GNU make 4 or later.
+
### Miniruby vs Ruby
Miniruby is a version of Ruby which has no external dependencies and lacks
@@ -172,7 +231,7 @@ certain features. It can be useful in Ruby development because it allows for
faster build times. Miniruby is built before Ruby. A functional Miniruby is
required to build Ruby. To build Miniruby:
-``` shell
+```sh
make miniruby
```
@@ -189,13 +248,37 @@ following make targets:
* `make lldb-ruby`: Runs `test.rb` using Ruby in lldb
* `make gdb-ruby`: Runs `test.rb` using Ruby in gdb
+For VS Code users, you can set up editor-based debugging experience by running:
+
+```shell
+cp -r misc/.vscode .vscode
+```
+
+This will add launch configurations for debugging Ruby itself by running `test.rb` with `lldb`.
+
+**Note**: if you build Ruby under the `./build` folder, you'll need to update `.vscode/launch.json`'s program entry accordingly to: `"${workspaceFolder}/build/ruby"`
+
### Compiling for Debugging
-You should configure Ruby without optimization and other flags that may
-interfere with debugging:
+You can compile Ruby with the `RUBY_DEBUG` macro to enable debugging on some
+features. One example is debugging object shapes in Ruby with
+`RubyVM::Shape.of(object)`.
+
+Additionally Ruby can be compiled to support the `RUBY_DEBUG` environment
+variable to enable debugging on some features. An example is using
+`RUBY_DEBUG=gc_stress` to debug GC-related issues.
+
+There is also support for the `RUBY_DEBUG_LOG` environment variable to log a
+lot of information about what the VM is doing, via the `USE_RUBY_DEBUG_LOG`
+macro.
-``` shell
-./configure --enable-debug-env optflags="-O0 -fno-omit-frame-pointer"
+You should also configure Ruby without optimization and other flags that may
+interfere with debugging by changing the optimization flags.
+
+Bringing it all together:
+
+```sh
+./configure cppflags="-DRUBY_DEBUG=1 -DUSE_RUBY_DEBUG_LOG=1" --enable-debug-env optflags="-O0 -fno-omit-frame-pointer"
```
### Building with Address Sanitizer
@@ -204,7 +287,7 @@ Using the address sanitizer (ASAN) is a great way to detect memory issues. It
can detect memory safety issues in Ruby itself, and also in any C extensions
compiled with and loaded into a Ruby compiled with ASAN.
-``` shell
+```sh
./autogen.sh
mkdir build && cd build
../configure CC=clang-18 cflags="-fsanitize=address -fno-omit-frame-pointer -DUSE_MN_THREADS=0" # and any other options you might like
@@ -218,40 +301,39 @@ two hours on my laptop); the `RUBY_TEST_TIMEOUT_SCALE` and
`SYNTAX_SUGEST_TIMEOUT` variables are required to make sure tests don't
spuriously fail with timeouts when in fact they're just slow.
-``` shell
+```sh
RUBY_TEST_TIMEOUT_SCALE=5 SYNTAX_SUGGEST_TIMEOUT=600 make check
```
Please note, however, the following caveats!
-* ASAN will not work properly on any currently released version of Ruby; the
- necessary support is currently only present on Ruby's master branch (and the
- whole test suite passes only as of commit
- [9d0a5148ae062a0481a4a18fbeb9cfd01dc10428](https://bugs.ruby-lang.org/projects/ruby-master/repository/git/revisions/9d0a5148ae062a0481a4a18fbeb9cfd01dc10428))
-* Due to [this bug](https://bugs.ruby-lang.org/issues/20243), Clang generates
- code for threadlocal variables which doesn't work with M:N threading. Thus,
- it's necessary to disable M:N threading support at build time for now (with
- the `-DUSE_MN_THREADS=0` configure argument).
-* ASAN will only work when using Clang version 18 or later - it requires [this
- bugfix](https://github.com/llvm/llvm-project/pull/75290) related to
- multithreaded `fork`.
+* Due to [Bug #20243], Clang generates code for threadlocal variables which
+ doesn't work with M:N threading. Thus, it's necessary to disable M:N
+ threading support at build time for now (with the `-DUSE_MN_THREADS=0`
+ configure argument).
+* ASAN will only work when using Clang version 18 or later - it requires
+ [llvm/llvm-project#75290] related to multithreaded `fork`.
* ASAN has only been tested so far with Clang on Linux. It may or may not work
with other compilers or on other platforms - please file an issue on
- [https://bugs.ruby-lang.org](https://bugs.ruby-lang.org) if you run into
- problems with such configurations (or, to report that they actually work
- properly!)
+ [Ruby Issue Tracking System] if you run into problems with such configurations
+ (or, to report that they actually work properly!)
* In particular, although I have not yet tried it, I have reason to believe
ASAN will _not_ work properly on macOS yet - the fix for the multithreaded
- fork issue was actually reverted for macOS (see
- [here](https://github.com/llvm/llvm-project/commit/2a03854e4ce9bb1bcd79a211063bc63c4657f92c)). Please
- open an issue on [https://bugs.ruby-lang.org](https://bugs.ruby-lang.org) if
- this is a problem for you.
+ fork issue was actually reverted for macOS (see [llvm/llvm-project#75659]).
+ Please open an issue on [Ruby Issue Tracking System] if this is a problem for
+ you.
+
+[Revision 9d0a5148]: https://bugs.ruby-lang.org/projects/ruby-master/repository/git/revisions/9d0a5148ae062a0481a4a18fbeb9cfd01dc10428
+[Bug #20243]: https://bugs.ruby-lang.org/issues/20243
+[llvm/llvm-project#75290]: https://github.com/llvm/llvm-project/pull/75290
+[llvm/llvm-project#75659]: https://github.com/llvm/llvm-project/pull/75659#issuecomment-1861584777
+[Ruby Issue Tracking System]: https://bugs.ruby-lang.org
## How to measure coverage of C and Ruby code
You need to be able to use gcc (gcov) and lcov visualizer.
-``` shell
+```sh
./autogen.sh
./configure --enable-gcov
make
diff --git a/doc/contributing/concurrency_guide.md b/doc/contributing/concurrency_guide.md
new file mode 100644
index 0000000000..1fb58f7203
--- /dev/null
+++ b/doc/contributing/concurrency_guide.md
@@ -0,0 +1,154 @@
+# Concurrency Guide
+
+This is a guide to thinking about concurrency in the cruby source code, whether that's contributing to Ruby
+by writing C or by contributing to one of the JITs. This does not touch on native extensions, only the core
+language. It will go over:
+
+* What needs synchronizing?
+* How to use the VM lock, and what you can and can't do when you've acquired this lock.
+* What you can and can't do when you've acquired other native locks.
+* The difference between the VM lock and the GVL.
+* What a VM barrier is and when to use it.
+* The lock ordering of some important locks.
+* How ruby interrupt handling works.
+* The timer thread and what it's responsible for.
+
+## What needs synchronizing?
+
+Before ractors, only one ruby thread could run at once. That didn't mean you could forget about concurrency issues, though. The timer thread
+is a native thread that interacts with other ruby threads and changes some VM internals, so if these changes can be done in parallel by both the timer
+thread and a ruby thread, they need to be synchronized.
+
+When you add ractors to the mix, it gets more complicated. However, ractors allow you to forget about synchronization for non-shareable objects because
+they aren't used across ractors. Only one ruby thread can touch the object at once. For shareable objects, they are deeply frozen so there isn't any
+mutation on the objects themselves. However, something like reading/writing constants across ractors does need to be synchronized. In this case, ruby threads need to
+see a consistent view of the VM. If publishing the update takes 2 steps or even two separate instructions, like in this case, synchronization is required.
+
+Most synchronization is to protect VM internals. These internals include structures for the thread scheduler on each ractor, the global ractor scheduler, the
+coordination between ruby threads and ractors, global tables (for `fstrings`, encodings, symbols and global vars), etc. Anything that can be mutated by a ractor
+that can also be read or mutated by another ractor at the same time requires proper synchronization.
+
+## The VM Lock
+
+There's only one VM lock and it is for critical sections that can only be entered by one ractor at a time.
+Without ractors, the VM lock is useless. It does not stop all ractors from running, as ractors can run
+without trying to acquire this lock. If you're updating global (shared) data between ractors and aren't using
+atomics, you need to use a lock and this is a convenient one to use. Unlike other locks, you can allocate ruby-managed
+memory with it held. When you take the VM lock, there are things you can and can't do during your critical section:
+
+You can (as long as no other locks are also held before the VM lock):
+
+* Create ruby objects, call `ruby_xmalloc`, etc.
+
+You can't:
+
+* Context switch to another ruby thread or ractor. This is important, as many things can cause ruby-level context switches including:
+
+ * Calling any ruby method through, for example, `rb_funcall`. If you execute ruby code, a context switch could happen.
+ This also applies to ruby methods defined in C, as they can be redefined in Ruby. Things that call ruby methods such as
+ `rb_obj_respond_to` are also disallowed.
+
+ * Calling `rb_raise`. This will call `initialize` on the new exception object. With the VM lock
+ held, nothing you call should be able to raise an exception. `NoMemoryError` is allowed, however.
+
+ * Calling `rb_nogvl` or a ruby-level mechanism that can context switch like `rb_mutex_lock`.
+
+ * Enter any blocking operation managed by ruby. This will context switch to another ruby thread using `rb_nogvl` or
+ something equivalent. A blocking operation is one that blocks the thread's progress, such as `sleep` or `IO#read`.
+
+Internally, the VM lock is the `vm->ractor.sync.lock`.
+
+You need to be on a ruby thread to take the VM lock. You also can't take it inside any functions that could be called during sweeping, as MMTK sweeps
+on another thread and you need a valid `ec` to grab the lock. For this same reason (among others), you can't take it from the timer thread either.
+
+## Other Locks
+
+All native locks that aren't the VM lock share a more strict set of rules for what's allowed during the critical section. By native locks, we mean
+anything that uses `rb_native_mutex_lock`. Some important locks include the `interrupt_lock`, the ractor scheduling lock (protects global scheduling data structures),
+the thread scheduling lock (local to each ractor, protects per-ractor scheduling data structures) and the ractor lock (local to each ractor, protects ractor data structures).
+
+When you acquire one of these locks,
+
+You can:
+
+* Allocate memory though non-ruby allocation such as raw `malloc` or the standard library. But be careful, some functions like `strdup` use
+ruby allocation through the use of macros!
+
+* Use `ccan` lists, as they don't allocate.
+
+* Do the usual things like set variables or struct fields, manipulate linked lists, signal condition variables etc.
+
+You can't:
+
+* Allocate ruby-managed memory. This includes creating ruby objects or using `ruby_xmalloc` or `st_insert`. The reason this
+is disallowed is if that allocation causes a GC, then all other ruby threads must join a VM barrier as soon as possible
+(when they next check interrupts or acquire the VM lock). This is so that no other ractors are running during GC. If a ruby thread
+is waiting (blocked) on this same native lock, it can't join the barrier and a deadlock occurs because the barrier will never finish.
+
+* Raise exceptions. You also can't use `EC_JUMP_TAG` if it jumps out of the critical section.
+
+* Context switch. See the `VM Lock` section for more info.
+
+## Difference Between VM Lock and GVL
+
+The VM Lock is a particular lock in the source code. There is only one VM Lock. The GVL, on the other hand, is more of a combination of locks.
+It is "acquired" when a ruby thread is about to run or is running. Since many ruby threads can run at the same time if they're in different ractors,
+there are many GVLs (1 per `SNT` + 1 for the main ractor). It can no longer be thought of as a "Global VM Lock" like it once was before ractors.
+
+## VM Barriers
+
+Sometimes, taking the VM Lock isn't enough and you need a guarantee that all ractors have stopped. This happens when running `GC`, for instance.
+To get a barrier, you take the VM Lock and call `rb_vm_barrier()`. For the duration that the VM lock is held, no other ractors will be running. It's not used
+often as taking a barrier slows ractor performance down considerably, but it's useful to know about and is sometimes the only solution.
+
+## Lock Orderings
+
+It's a good idea to not hold more than 2 locks at once on the same thread. Locking multiple locks can introduce deadlocks, so do it with care. When locking
+multiple locks at once, follow an ordering that is consistent across the program, otherwise you can introduce deadlocks. Here are the orderings of some important locks:
+
+* VM lock before ractor_sched_lock
+* thread_sched_lock before ractor_sched_lock
+* interrupt_lock before timer_th.waiting_lock
+* timer_th.waiting_lock before ractor_sched_lock
+
+These orderings are subject to change, so check the source if you're not sure. On top of this:
+
+* During each `ubf` (unblock) function, the VM lock can be taken around it in some circumstances. This happens during VM shutdown, for example.
+See the "Interrupt Handling" section for more details.
+
+## Ruby Interrupt Handling
+
+When the VM runs ruby code, ruby's threads intermittently check ruby-level interrupts. These software interrupts
+are for various things in ruby and they can be set by other ruby threads or the timer thread.
+
+* Ruby threads check when they should give up their timeslice. The native thread switches to another ruby thread when their time is up.
+* The timer thread sends a "trap" interrupt to the main thread if any ruby-level signal handlers are pending.
+* Ruby threads can have other ruby threads run tasks for them by sending them an interrupt. For instance, ractors send
+the main thread an interrupt when they need to `require` a file so that it's done on the main thread. They wait for the
+main thread's result.
+* During VM shutdown, a "terminate" interrupt is sent to all ractor main threads top stop them asap.
+* When calling `Thread#raise`, the caller sends an interrupt to that thread telling it which exception to raise.
+* Unlocking a mutex sends the next waiter (if any) an interrupt telling it to grab the lock.
+* Signalling or broadcasting on a condition variable tells the waiter(s) to wake up.
+
+This isn't a complete list.
+
+When sending an interrupt to a ruby thread, the ruby thread can be blocked. For example, it could be in the middle of a `TCPSocket#read` call. If so,
+the receiving thread's `ubf` (unblock function) gets called from the thread (ruby thread or timer thread) that sent the interrupt.
+Each ruby thread has a `ubf` that is set when it enters a blocking operation and is unset after returning from it. By default, this `ubf` function sends a
+`SIGVTALRM` to the receiving thread to try to unblock it from the kernel so it can check its interrupts. There are other `ubfs` that
+aren't associated with a syscall, such as when calling `Ractor#join` or `sleep`. All `ubfs` are called with the `interrupt_lock` held,
+so take that into account when using locks inside `ubfs`.
+
+Remember, `ubfs` can be called from the timer thread so you cannot assume an `ec` inside them. The `ec` (execution context) is only set on ruby threads.
+
+## The Timer Thread
+
+The timer thread has a few functions. They are:
+
+* Send interrupts to ruby threads that have run for their whole timeslice.
+* Wake up M:N ruby threads (threads in non-main ractors) blocked on IO or after a specified timeout. This
+uses `kqueue` or `epoll`, depending on the OS, to receive IO events on behalf of the threads.
+* Continue calling the `SIGVTARLM` signal if a thread is still blocked on a syscall after the first `ubf` call.
+* Signal native threads (`SNT`) waiting on a ractor if there are ractors waiting in the global run queue.
+* Create more `SNT`s if some are blocked, like on IO or on `Ractor#join`.
diff --git a/doc/contributing/contributing.md b/doc/contributing/contributing.md
new file mode 100644
index 0000000000..a2ed00ab90
--- /dev/null
+++ b/doc/contributing/contributing.md
@@ -0,0 +1,35 @@
+# Contributing to Ruby
+
+## Ruby Issues
+
+To report an issue in the Ruby core:
+
+* [Report issues](reporting_issues.md).
+
+## Ruby Core
+
+To contribute to the Ruby core functionality,
+you'll need initially to:
+
+* [Build Ruby](building_ruby.md) on your system.
+* [Test Ruby](testing_ruby.md), to make sure the build is correct.
+
+Then:
+
+* [Make changes to Ruby](making_changes_to_ruby.md).
+
+And possibly:
+
+* [Benchmark Ruby](https://github.com/ruby/ruby/tree/master/benchmark#make-benchmark).
+
+## Ruby Documentation
+
+To contribute to the Ruby core documentation, see:
+
+* [Making changes to the Ruby documentation](documentation_guide.md).
+
+## Ruby Standard Library
+
+To contribute to the Ruby Standard Library, see:
+
+* [Making changes to the Ruby Standard Library](making_changes_to_stdlibs.md).
diff --git a/doc/contributing/documentation_guide.md b/doc/contributing/documentation_guide.md
index 59953d0d52..4b1e2ac9ad 100644
--- a/doc/contributing/documentation_guide.md
+++ b/doc/contributing/documentation_guide.md
@@ -7,7 +7,7 @@ in the Ruby core and in the Ruby standard library.
## Generating documentation
Most Ruby documentation lives in the source files and is written in
-[RDoc format](rdoc-ref:RDoc::Markup).
+[RDoc format](https://ruby.github.io/rdoc/RDoc/MarkupReference.html).
Some pages live under the `doc` folder and can be written in either
`.rdoc` or `.md` format, determined by the file extension.
@@ -44,14 +44,13 @@ Use your judgment about what the user needs to know.
- Group sentences into (ideally short) paragraphs,
each covering a single topic.
- Organize material with
- [headings](rdoc-ref:RDoc::MarkupReference@Headings).
+ [headings].
- Refer to authoritative and relevant sources using
- [links](rdoc-ref:RDoc::MarkupReference@Links).
+ [links](https://ruby.github.io/rdoc/RDoc/MarkupReference.html#class-RDoc::MarkupReference-label-Links).
- Use simple verb tenses: simple present, simple past, simple future.
- Use simple sentence structure, not compound or complex structure.
- Avoid:
- - Excessive comma-separated phrases;
- consider a [list](rdoc-ref:RDoc::MarkupReference@Lists).
+ - Excessive comma-separated phrases; consider a [list].
- Idioms and culture-specific references.
- Overuse of headings.
- Using US-ASCII-incompatible characters in C source files;
@@ -62,7 +61,7 @@ Use your judgment about what the user needs to know.
Use only US-ASCII-compatible characters in a C source file.
(If you use other characters, the Ruby CI will gently let you know.)
-If want to put ASCII-incompatible characters into the documentation
+If you want to put ASCII-incompatible characters into the documentation
for a C-coded class, module, or method, there are workarounds
involving new files `doc/*.rdoc`:
@@ -75,7 +74,7 @@ involving new files `doc/*.rdoc`:
class Foo; end
```
-- Similarly, for module `Bar` (defined in file `bar.c`,
+- Similarly, for module `Bar` (defined in file `bar.c`),
create file `doc/bar.rdoc`, declare `module Bar; end`,
and place the module documentation above that declaration:
@@ -95,7 +94,7 @@ involving new files `doc/*.rdoc`:
Example:
- ```
+ ```c
/*
* call-seq:
* each_byte {|byte| ... } -> self
@@ -110,7 +109,7 @@ involving new files `doc/*.rdoc`:
Ruby is documented using RDoc.
For information on \RDoc syntax and features, see the
-[RDoc Markup Reference](rdoc-ref:RDoc::Markup@RDoc+Markup+Reference).
+[RDoc Markup Reference](https://ruby.github.io/rdoc/RDoc/MarkupReference.html).
### Output from `irb`
@@ -129,22 +128,21 @@ a #=> [2, 3, 1]
### Headings
-Organize a long discussion for a class or module with [headings](rdoc-ref:RDoc::MarkupReference@Headings).
+Organize a long discussion for a class or module with [headings].
Do not use formal headings in the documentation for a method or constant.
In the rare case where heading-like structures are needed
within the documentation for a method or constant, use
-[bold text](rdoc-ref:RDoc::MarkupReference@Bold)
+[bold text](https://ruby.github.io/rdoc/RDoc/MarkupReference.html#class-RDoc::MarkupReference-label-Bold)
as pseudo-headings.
### Blank Lines
A blank line begins a new paragraph.
-A [code block](rdoc-ref:RDoc::MarkupReference@Code+Blocks)
-or [list](rdoc-ref:RDoc::MarkupReference@Lists)
-should be preceded by and followed by a blank line.
+A [code block](https://ruby.github.io/rdoc/RDoc/MarkupReference.html#class-RDoc::MarkupReference-label-Code+Blocks)
+or [list] should be preceded by and followed by a blank line.
This is unnecessary for the HTML output, but helps in the `ri` output.
### \Method Names
@@ -164,49 +162,119 @@ For a method name in text:
Code or commands embedded in running text (i.e., not in a code block)
should marked up as
-[monofont](rdoc-ref:RDoc::MarkupReference@Monofont).
+[monofont].
Code that is a simple string should include the quote marks.
### Auto-Linking
-In general, \RDoc's auto-linking should not be suppressed.
-For example, we should write `Array`, not `\Array`.
-
-However, suppress when the word in question:
-
-- Does not refer to a Ruby entity
- (e.g., some uses of _Class_ or _English_).
-- Refers to the current document
- (e.g., _Array_ in the documentation for class `Array`);
- in that case, the word should be forced to
- [monofont](rdoc-ref:RDoc::MarkupReference@Monofont).
-
Most often, the name of a class, module, or method
-will be auto-linked:
+is auto-linked:
-- Array.
+```rdoc
+- Float.
- Enumerable.
- File.new
- File#read.
+```
+
+renders as:
+
+> - Float.
+> - Enumerable.
+> - File.new
+> - File#read.
+
+In general, \RDoc's auto-linking should not be suppressed.
+For example, we should write just plain _Float_ (which is auto-linked):
+
+```rdoc
+Returns a Float.
+```
+
+which renders as:
+
+> Returns a Float.
+
+However, _do_ suppress auto-linking when the word in question
+does not refer to a Ruby entity (e.g., some uses of _Class_ or _English_):
+
+```rdoc
+Class variables can be tricky.
+```
+
+renders as:
+
+> Class variables can be tricky.
+
+Also, _do_ suppress auto-linking when the word in question
+refers to the current document
+(e.g., _Float_ in the documentation for class Float).
+
+In this case you may consider forcing the name to
+[monofont],
+which suppresses auto-linking, and also emphasizes that the word is a class name:
+
+```rdoc
+A +Float+ object represents ....
+```
+
+renders as:
+
+> A `Float` object represents ....
+
+For a _very_ few, _very_ often-discussed classes,
+you might consider avoiding the capitalized class name altogether.
+For example, for some mentions of arrays,
+you might write simply the lowercase _array_.
+
+Instead of:
+
+```rdoc
+For an empty Array, ....
+```
+
+which renders as:
+
+> For an empty Array, ....
+
+you might write:
+
+```rdoc
+For an empty array, ....
+```
+
+which renders as:
+
+> For an empty array, ....
+
+This more casual usage avoids both auto-linking and distracting font changes,
+and is unlikely to cause confusion.
+
+This principle may be usefully applied, in particular, for:
-If not, or if you suppress autolinking, consider forcing
-[monofont](rdoc-ref:RDoc::MarkupReference@Monofont).
+- An array.
+- An integer.
+- A hash.
+- A string.
+
+However, it should be applied _only_ when referring to an _instance_ of the class,
+and _never_ when referring to the class itself.
### Explicit Links
When writing an explicit link, follow these guidelines.
-#### +rdoc-ref+ Scheme
+#### `rdoc-ref` Scheme
-Use the +rdoc-ref+ scheme for:
+Use the `rdoc-ref` scheme for:
- A link in core documentation to other core documentation.
- A link in core documentation to documentation in a standard library package.
- A link in a standard library package to other documentation in that same
standard library package.
-See section "+rdoc-ref+ Scheme" in {Links}[rdoc-ref:RDoc::MarkupReference@Links].
+See section "`rdoc-ref` Scheme" in [links].
#### URL-Based Link
@@ -216,7 +284,7 @@ Use a full URL-based link for:
- A link in standard library documentation to documentation in a different
standard library package.
-Doing so ensures that the link will valid even when the package documentation
+Doing so ensures that the link will be valid even when the package documentation
is built independently (separately from the core documentation).
The link should lead to a target in https://docs.ruby-lang.org/en/master/.
@@ -226,10 +294,10 @@ Also use a full URL-based link for a link to an off-site document.
### Variable Names
The name of a variable (as specified in its call-seq) should be marked up as
-[monofont](rdoc-ref:RDoc::MarkupReference@Monofont).
+[monofont].
Also, use monofont text for the name of a transient variable
-(i.e., one defined and used only in the discussion, such as +n+).
+(i.e., one defined and used only in the discussion, such as `n`).
### HTML Tags
@@ -244,9 +312,9 @@ In particular, avoid building tables with HTML tags
Alternatives:
-- A {verbatim text block}[rdoc-ref:RDoc::MarkupReference@Verbatim+Text+Blocks],
+- A {verbatim text block}[https://ruby.github.io/rdoc/RDoc/MarkupReference.html#class-RDoc::MarkupReference-label-Verbatim+Text+Blocks],
using spaces and punctuation to format the text;
- note that {text markup}[rdoc-ref:RDoc::MarkupReference@Text+Markup]
+ note that {text markup}[https://ruby.github.io/rdoc/RDoc/MarkupReference.html#class-RDoc::MarkupReference-label-Text+Markup]
will not be honored:
- Example {source}[https://github.com/ruby/ruby/blob/34d802f32f00df1ac0220b62f72605827c16bad8/file.c#L6570-L6596].
@@ -258,6 +326,16 @@ Alternatives:
- Example {source}[https://github.com/ruby/ruby/blob/34d802f32f00df1ac0220b62f72605827c16bad8/doc/contributing/glossary.md?plain=1].
- Corresponding {output}[https://docs.ruby-lang.org/en/master/contributing/glossary_md.html].
+### Languages in Examples
+
+For symbols and strings in documentation examples:
+
+- Prefer \English in \English documentation: <tt>'Hello'</tt>.
+- Prefer Japanese in Japanese documentation: <tt>'こんにちは'</tt>.
+- If a second language is needed (as, for example, characters with different byte-sizes),
+ prefer Japanese in \English documentation and \English in Japanese documentation.
+- Use other languages examples only as necessary: see String#capitalize.
+
## Documenting Classes and Modules
The general structure of the class or module documentation should be:
@@ -286,8 +364,7 @@ Guidelines:
- The section title is `What's Here`.
- Consider listing the parent class and any included modules; consider
- [links](rdoc-ref:RDoc::MarkupReference@Links)
- to their "What's Here" sections if those exist.
+ [links] to their "What's Here" sections if those exist.
- All methods mentioned in the left-pane table of contents
should be listed (including any methods extended from another class).
- Attributes (which are not included in the TOC) may also be listed.
@@ -299,7 +376,7 @@ Guidelines:
(and do not list the aliases separately).
- Check the rendered documentation to determine whether \RDoc has recognized
the method and linked to it; if not, manually insert a
- [link](rdoc-ref:RDoc::MarkupReference@Links).
+ [link](https://ruby.github.io/rdoc/RDoc/MarkupReference.html#class-RDoc::MarkupReference-label-Links).
- If there are numerous entries, consider grouping them into subsections with headings.
- If there are more than a few such subsections,
@@ -313,6 +390,7 @@ The general structure of the method documentation should be:
- Calling sequence (for methods written in C).
- Synopsis (short description).
+- In-brief examples (optional)
- Details and examples.
- Argument description (if necessary).
- Corner cases and exceptions.
@@ -324,17 +402,17 @@ For methods written in Ruby, \RDoc documents the calling sequence automatically.
For methods written in C, \RDoc cannot determine what arguments
the method accepts, so those need to be documented using \RDoc directive
-[`call-seq:`](rdoc-ref:RDoc::MarkupReference@Directives+for+Method+Documentation).
+[`call-seq:`](https://ruby.github.io/rdoc/RDoc/MarkupReference.html#class-RDoc::MarkupReference-label-Directives+for+Method+Documentation).
For a singleton method, use the form:
-```
+```rdoc
class_name.method_name(method_args) {|block_args| ... } -> return_type
```
Example:
-```
+```rdoc
* call-seq:
* Hash.new(default_value = nil) -> new_hash
* Hash.new {|hash, key| ... } -> new_hash
@@ -343,23 +421,32 @@ Example:
For an instance method, use the form
(omitting any prefix, just as RDoc does for a Ruby-coded method):
-```
+```rdoc
method_name(method_args) {|block_args| ... } -> return_type
```
+
For example, in Array, use:
-```
+```rdoc
* call-seq:
* count -> integer
* count(obj) -> integer
* count {|element| ... } -> integer
```
-```
-* call-seq:
+```rdoc
+* call-seq:
* <=> other -> -1, 0, 1, or nil
```
+For a binary-operator style method (e.g., Array#&),
+cite `self` in the call-seq (not, e.g., `array` or `receiver`):
+
+```rdoc
+* call-seq:
+* self & other_array -> new_array
+```
+
Arguments:
- If the method does not accept arguments, omit the parentheses.
@@ -371,15 +458,17 @@ Arguments:
or an explicit argument, use a `call-seq` with optional arguments.
For example, use:
- ```
- respond_to?(symbol, include_all = false) -> true or false
+ ```rdoc
+ * call-seq:
+ * respond_to?(symbol, include_all = false) -> true or false
```
- If the behavior is different with an omitted or an explicit argument,
use a `call-seq` with separate lines.
For example, in Enumerable, use:
- ```
+ ```rdoc
+ * call-seq:
* max -> element
* max(n) -> array
```
@@ -389,15 +478,23 @@ Block:
- If the method does not accept a block, omit the block.
- If the method accepts a block, the `call-seq` should have `{|args| ... }`,
not `{|args| block }` or `{|args| code }`.
+- If the method accepts a block, but returns an Enumerator when the block is omitted,
+ the `call-seq` should show both forms:
+
+ ```rdoc
+ * call-seq:
+ * array.select {|element| ... } -> new_array
+ * array.select -> new_enumerator
+ ```
Return types:
- If the method can return multiple different types,
separate the types with "or" and, if necessary, commas.
-- If the method can return multiple types, use +object+.
-- If the method returns the receiver, use +self+.
+- If the method can return multiple types, use `object`.
+- If the method returns the receiver, use `self`.
- If the method returns an object of the same class,
- prefix `new_` if an only if the object is not +self+;
+ prefix `new_` if and only if the object is not `self`;
example: `new_array`.
Aliases:
@@ -417,14 +514,22 @@ an entire paragraph.
For `Array#count`, the synopsis is:
-```
-Returns a count of specified elements.
-```
+> Returns a count of specified elements.
This is great as it is short and descriptive. Avoid documenting
too much in the synopsis, stick to the most important information
for the benefit of the reader.
+### In-Brief Examples
+
+For a method whose documentation is lengthy,
+consider adding an "in-brief" passage,
+showing examples that summarize the method's uses.
+
+The passage may answer some users' questions
+(without their having to read long documentation);
+see Array#[] and Array#[]=.
+
### Details and Examples
Most non-trivial methods benefit from examples, as well as details
@@ -447,6 +552,15 @@ do not add an example if it provides the same information given
in the synopsis or details. The purpose of examples is not to prove
what the details are stating.
+Many methods that can take an optional block call the block if it is given,
+but return a new Enumerator if the block is not given;
+in that case, do not provide an example,
+but do state the fact (with the auto-linking uppercase Enumerator):
+
+```rdoc
+* With no block given, returns a new Enumerator.
+```
+
### Argument Description (if necessary)
For methods that require arguments, if not obvious and not explicitly
@@ -463,7 +577,7 @@ argument passed if it is not obvious, not explicitly mentioned in the
details, and not implicitly shown in the examples.
If there is more than one argument or block argument, use a
-[labeled list](rdoc-ref:RDoc::MarkupReference@Labeled+Lists).
+[labeled list](https://ruby.github.io/rdoc/RDoc/MarkupReference.html#class-RDoc::MarkupReference-label-Labeled+Lists).
### Corner Cases and Exceptions
@@ -484,7 +598,7 @@ 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,
+ to the current method, and if you think the reader would benefit from 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.
@@ -493,7 +607,7 @@ mention `Hash#fetch` as a related method, and `Hash#merge` might mention
- Consider adding:
- A phrase suggesting how the related method is similar to,
- or different from,the current method.
+ or different from, the current method.
See an example at Time#getutc.
- Example code that illustrates the similarities and differences.
See examples at Time#ctime, Time#inspect, Time#to_s.
@@ -503,3 +617,7 @@ mention `Hash#fetch` as a related method, and `Hash#merge` might mention
For methods that accept multiple argument types, in some cases it can
be useful to document the different argument types separately. It's
best to use a separate paragraph for each case you are discussing.
+
+[headings]: https://ruby.github.io/rdoc/RDoc/MarkupReference.html#class-RDoc::MarkupReference-label-Headings
+[list]: https://ruby.github.io/rdoc/RDoc/MarkupReference.html#class-RDoc::MarkupReference-label-Lists
+[monofont]: https://ruby.github.io/rdoc/RDoc/MarkupReference.html#class-RDoc::MarkupReference-label-Monofont
diff --git a/doc/dtrace_probes.rdoc b/doc/contributing/dtrace_probes.rdoc
index 1b20597ab4..1b20597ab4 100644
--- a/doc/dtrace_probes.rdoc
+++ b/doc/contributing/dtrace_probes.rdoc
diff --git a/doc/contributing/glossary.md b/doc/contributing/glossary.md
index 86c6671fbd..3ec9796147 100644
--- a/doc/contributing/glossary.md
+++ b/doc/contributing/glossary.md
@@ -4,14 +4,17 @@ Just a list of acronyms I've run across in the Ruby source code and their meanin
| Term | Definition |
| --- | -----------|
+| `bmethod` | Method defined by `define_method() {}` (a Block that runs as a Method). |
| `BIN` | Basic Instruction Name. Used as a macro to reference the YARV instruction. Converts pop into YARVINSN_pop. |
| `bop` | Basic Operator. Relates to methods like `Integer` plus and minus which can be optimized as long as they haven't been redefined. |
| `cc` | Call Cache. An inline cache structure for the call site. Stored in the `cd` |
| `cd` | Call Data. A data structure that points at the `ci` and the `cc`. `iseq` objects points at the `cd`, and access call information and call caches via this structure |
+| CFG | Control Flow Graph. Representation of the program where all control-flow and data dependencies have been made explicit by unrolling the stack and local variables. |
| `cfp`| Control Frame Pointer. Represents a Ruby stack frame. Calling a method pushes a new frame (cfp), returning pops a frame. Points at the `pc`, `sp`, `ep`, and the corresponding `iseq`|
-| `ci` | Call Information. Refers to an `rb_callinfo` struct. Contains call information about the call site, including number of parameters to be passed, whether it they are keyword arguments or not, etc. Used in conjunction with the `cc` and `cd`. |
+| `ci` | Call Information. Refers to an `rb_callinfo` struct. Contains call information about the call site, including number of parameters to be passed, whether they are keyword arguments or not, etc. Used in conjunction with the `cc` and `cd`. |
+| `cme` | Callable Method Entry. Refers to the `rb_callable_method_entry_t` struct, the internal representation of a Ruby method that has `defined_class` and `owner` set and is ready for dispatch. |
| `cref` | Class reference. A structure pointing to the class reference where `klass_or_self`, visibility scope, and refinements are stored. It also stores a pointer to the next class in the hierarchy referenced by `rb_cref_struct * next`. The Class reference is lexically scoped. |
-| CRuby | Implementation of Ruby written in C |
+| CRuby | Reference implementation of Ruby written in C |
| `cvar` | Class Variable. Refers to a Ruby class variable like `@@foo` |
| `dvar` | Dynamic Variable. Used by the parser to refer to local variables that are defined outside of the current lexical scope. For example `def foo; bar = 1; -> { p bar }; end` the "bar" inside the block is a `dvar` |
| `ec` | Execution Context. The top level VM context, points at the current `cfp` |
@@ -25,16 +28,20 @@ Just a list of acronyms I've run across in the Ruby source code and their meanin
| `insns` | Instructions. Usually an array of YARV instructions. |
| `ivar` | Instance Variable. Refers to a Ruby instance variable like `@foo` |
| `imemo` | Internal Memo. A tagged struct whose memory is managed by Ruby's GC, but contains internal information and isn't meant to be exposed to Ruby programs. Contains various information depending on the type. See the `imemo_type` enum for different types. |
+| `IVC` | Instance Variable Cache. Cache specifically for instance variable access |
| JIT | Just In Time compiler |
| `lep` | Local Environment Pointer. An `ep` which is tagged `VM_ENV_FLAG_LOCAL`. Usually this is the `ep` of a method (rather than a block, whose `ep` isn't "local") |
| `local` | Local. Refers to a local variable. |
-| `me` | Method Entry. Refers to an `rb_method_entry_t` struct, the internal representation of a Ruby method.
+| `me` | Method Entry. Refers to an `rb_method_entry_t` struct, the internal representation of a Ruby method. |
| MRI | Matz's Ruby Implementation |
| `pc` | Program Counter. Usually the instruction that will be executed _next_ by the VM. Pointed to by the `cfp` and incremented by the VM |
+| `snt` | Shared Native Thread. OS thread on which many ruby threads can run. Ruby threads from different ractors can even run on the same SNT. Ruby threads can switch SNTs when they context switch. SNTs are used in the M:N threading model. By default, non-main ractors use this model.
+| `dnt` | Dedicated Native Thread. OS thread on which only one ruby thread can run. The ruby thread always runs on that same OS thread. DNTs are used in the 1:1 threading model. By default, the main ractor uses this model.
| `sp` | Stack Pointer. The top of the stack. The VM executes instructions in the `iseq` and instructions will push and pop values on the stack. The VM updates the `sp` on the `cfp` to point at the top of the stack|
+| ST table | ST table is the main C implementation of a hash (smaller Ruby hashes may be backed by AR tables). |
| `svar` | Special Variable. Refers to special local variables like `$~` and `$_`. See the `getspecial` instruction in `insns.def` |
| `VALUE` | VALUE is a pointer to a ruby object from the Ruby C code. |
-| VM | Virtual Machine. In MRI's case YARV (Yet Another Ruby VM)
+| VM | Virtual Machine. In MRI's case YARV (Yet Another Ruby VM)
| WB | Write Barrier. To do with GC write barriers |
| WC | Wild Card. As seen in instructions like `getlocal_WC_0`. It means this instruction takes a "wild card" for the parameter (in this case an index for a local) |
| YARV | Yet Another Ruby VM. The virtual machine that CRuby uses |
diff --git a/doc/contributing/making_changes_to_stdlibs.md b/doc/contributing/making_changes_to_stdlibs.md
index 3b33092fea..2ceb2e6075 100644
--- a/doc/contributing/making_changes_to_stdlibs.md
+++ b/doc/contributing/making_changes_to_stdlibs.md
@@ -4,7 +4,7 @@ Everything in the [lib](https://github.com/ruby/ruby/tree/master/lib) directory
If you'd like to make contributions to standard libraries, do so in the standalone repositories, and the
changes will be automatically mirrored into the Ruby repository.
-For example, CSV lives in [a separate repository](https://github.com/ruby/csv) and is mirrored into [Ruby](https://github.com/ruby/ruby/tree/master/lib/csv).
+For example, ERB lives in [a separate repository](https://github.com/ruby/erb) and is mirrored into [Ruby](https://github.com/ruby/ruby/tree/master/lib/erb).
## Maintainers
@@ -14,7 +14,7 @@ You can find the list of maintainers [here](https://docs.ruby-lang.org/en/master
First, install its dependencies using:
-```
+```shell
bundle install
```
@@ -22,7 +22,7 @@ bundle install
If the library has a `/ext` directory, it has C files that you need to compile with:
-```
+```shell
bundle exec rake compile
```
@@ -32,18 +32,18 @@ All standard libraries use [test-unit](https://github.com/test-unit/test-unit) a
To run all tests:
-```
+```shell
bundle exec rake test
```
To run a single test file:
-```
+```shell
bundle exec rake test TEST="test/test_foo.rb"
```
To run a single test case:
-```
-bundle exec rake test TEST="test/test_foo.rb" TESTOPS="--name=/test_mytest/"
+```shell
+bundle exec rake test TEST="test/test_foo.rb" TESTOPTS="--name=/test_mytest/"
```
diff --git a/doc/memory_view.md b/doc/contributing/memory_view.md
index 0b1369163d..0b1369163d 100644
--- a/doc/memory_view.md
+++ b/doc/contributing/memory_view.md
diff --git a/doc/contributing/reporting_issues.md b/doc/contributing/reporting_issues.md
index 25516ffc6b..a1a2295712 100644
--- a/doc/contributing/reporting_issues.md
+++ b/doc/contributing/reporting_issues.md
@@ -52,19 +52,30 @@ your feature it could help persuade Ruby core.
Here is a template you can use for a feature proposal:
-```
-[Abstract]
- Briefly summarize your feature
-[Background]
- Describe current behavior
-[Proposal]
- Describe your feature in detail
-[Use cases]
- Give specific example uses of your feature
-[Discussion]
- Describe why this feature is necessary and better than using existing features
-[See also]
- Link to other related resources (such as implementations in other languages)
+```markdown
+# Abstract
+
+Briefly summarize your feature
+
+# Background
+
+Describe current behavior
+
+# Proposal
+
+Describe your feature in detail
+
+# Use cases
+
+Give specific example uses of your feature
+
+# Discussion
+
+Describe why this feature is necessary and better than using existing features
+
+# See also
+
+Link to other related resources (such as implementations in other languages)
```
## Backport requests
diff --git a/doc/contributing/testing_ruby.md b/doc/contributing/testing_ruby.md
index dfb7fb3a65..4c7ce7f6a8 100644
--- a/doc/contributing/testing_ruby.md
+++ b/doc/contributing/testing_ruby.md
@@ -1,5 +1,9 @@
# Testing Ruby
+All the commands below assume that you're running them from the `build/` directory made during [Building Ruby](building_ruby.md).
+
+Most commands below should work with [GNU make](https://www.gnu.org/software/make/) (the default on Linux and macOS), [BSD make](https://man.freebsd.org/cgi/man.cgi?make(1)) and [NMAKE](https://learn.microsoft.com/en-us/cpp/build/reference/nmake-reference), except where indicated otherwise.
+
## Test suites
There are several test suites in the Ruby codebase:
@@ -8,138 +12,133 @@ We can run any of the make scripts [in parallel](building_ruby.md#label-Running+
1. [bootstraptest/](https://github.com/ruby/ruby/tree/master/bootstraptest)
- This is a small test suite that runs on Miniruby (see [building Ruby](building_ruby.md#label-Miniruby+vs+Ruby)). We can run it with:
+ This is a small test suite that runs on [Miniruby](building_ruby.md#label-Miniruby+vs+Ruby). We can run it with:
- ```
+ ```sh
make btest
```
- To run it with logs, we can use:
+ To run individual bootstrap tests, we can either specify a list of filenames or use the `--sets` flag in the variable `BTESTS`:
- ```
- make btest OPTS=-v
+ ```sh
+ make btest BTESTS="../bootstraptest/test_string.rb ../bootstraptest/test_class.rb"
+ make btest BTESTS="--sets=string,class"
```
- To run individual bootstrap tests, we can either specify a list of filenames or use the `--sets` flag in the variable `BTESTS`:
+ To run these tests with verbose logging, we can add `-v` to the `OPTS`:
- ```
- make btest BTESTS="bootstraptest/test_fork.rb bootstraptest/tes_gc.rb"
- make btest BTESTS="--sets=fork,gc"
+ ```sh
+ make btest OPTS="--sets=string,class -v"
```
If we want to run the bootstrap test suite on Ruby (not Miniruby), we can use:
- ```
+ ```sh
make test
```
- To run it with logs, we can use:
+ To run these tests with verbose logging, we can add `-v` to the `OPTS`:
- ```
+ ```sh
make test OPTS=-v
```
- To run a file or directory with GNU make, we can use:
+ (GNU make only) To run a specific file, we can use:
+ ```sh
+ make ../test/ruby/test_string.rb
```
- make test/ruby/test_foo.rb
- make test/ruby/test_foo.rb TESTOPTS="-n /test_bar/"
+
+ You can use the `-n` test option to run a specific test with a regex:
+
+ ```sh
+ make ../test/ruby/test_string.rb TESTOPTS="-n /test_.*_to_s/"
```
2. [test/](https://github.com/ruby/ruby/tree/master/test)
This is a more comprehensive test suite that runs on Ruby. We can run it with:
- ```
+ ```sh
make test-all
```
- We can run a specific test directory in this suite using the `TESTS` option, for example:
-
- ```
- make test-all TESTS=test/rubygems
- ```
-
- We can run a specific test file in this suite by also using the `TESTS` option, for example:
+ We can run a specific test file or directory in this suite using the `TESTS` option, for example:
- ```
- make test-all TESTS=test/ruby/test_array.rb
+ ```sh
+ make test-all TESTS="../test/ruby/"
+ make test-all TESTS="../test/ruby/test_string.rb"
```
We can run a specific test in this suite using the `TESTS` option, specifying
first the file name, and then the test name, prefixed with `--name`. For example:
- ```
- make test-all TESTS="../test/ruby/test_alias.rb --name=TestAlias#test_alias_with_zsuper_method"
+ ```sh
+ make test-all TESTS="../test/ruby/test_string.rb --name=TestString#test_to_s"
```
- To run these specs with logs, we can use:
+ To run these tests with verbose logging, we can add `-v` to `TESTS`:
- ```
+ ```sh
make test-all TESTS=-v
```
We can display the help of the `TESTS` option:
- ```
+ ```sh
make test-all TESTS=--help
```
- If we would like to run the `test/`, `bootstraptest/` and `spec/` test suites (the `spec/` is explained in a later section), we can run
+ We can run all the tests in `test/`, `bootstraptest/` and `spec/` (the `spec/` is explained in a later section) all together with:
- ```
+ ```sh
make check
```
3. [spec/ruby](https://github.com/ruby/ruby/tree/master/spec/ruby)
- This is a test suite that exists in [the Ruby spec repository](https://github.com/ruby/spec) and is mirrored into the `spec/ruby` directory in the Ruby repository. It tests the behavior of the Ruby programming language. We can run this using:
+ This is a test suite defined in [the Ruby spec repository](https://github.com/ruby/spec), and is periodically mirrored into the `spec/ruby` directory of this repository. It tests the behavior of the Ruby programming language. We can run this using:
- ```
+ ```sh
make test-spec
```
- To run a specific directory, we can use `SPECOPTS` to specify the directory:
-
- ```
- make test-spec SPECOPTS=spec/ruby/core/array
- ```
-
- To run a specific file, we can also use `SPECOPTS` to specify the file:
+ We can run a specific test file or directory in this suite using the `SPECOPTS` option, for example:
- ```
- make test-spec SPECOPTS=spec/ruby/core/array/any_spec.rb
+ ```sh
+ make test-spec SPECOPTS="../spec/ruby/core/string/"
+ make test-spec SPECOPTS="../spec/ruby/core/string/to_s_spec.rb"
```
To run a specific test, we can use the `--example` flag to match against the test name:
- ```
- make test-spec SPECOPTS="../spec/ruby/core/array/any_spec.rb --example='is false if the array is empty'"
+ ```sh
+ make test-spec SPECOPTS="../spec/ruby/core/string/to_s_spec.rb --example='returns self when self.class == String'"
```
- To run these specs with logs, we can use:
+ To run these specs with verbose logging, we can add `-v` to the `SPECOPTS`:
- ```
- make test-spec SPECOPTS=-Vfs
+ ```sh
+ make test-spec SPECOPTS="../spec/ruby/core/string/to_s_spec.rb -Vfs"
```
- To run a ruby-spec file or directory with GNU make, we can use
+ (GNU make only) To run a ruby-spec file or directory, we can use
- ```
- make spec/ruby/core/foo/bar_spec.rb
+ ```sh
+ make ../spec/ruby/core/string/to_s_spec.rb
```
4. [spec/bundler](https://github.com/ruby/ruby/tree/master/spec/bundler)
- The bundler test suite exists in [the RubyGems repository](https://github.com/rubygems/rubygems/tree/master/bundler/spec) and is mirrored into the `spec/bundler` directory in the Ruby repository. We can run this using:
+ The bundler test suite is defined in [the RubyGems repository](https://github.com/rubygems/rubygems/tree/master/bundler/spec), and is periodically mirrored into the `spec/ruby` directory of this repository. We can run this using:
- ```
+ ```sh
make test-bundler
```
To run a specific bundler spec file, we can use `BUNDLER_SPECS` as follows:
- ```
+ ```sh
make test-bundler BUNDLER_SPECS=commands/exec_spec.rb
```
@@ -149,7 +148,7 @@ We can run any of the make scripts [in parallel](building_ruby.md#label-Running+
If we see failing tests related to the zlib library on s390x CPU architecture, we can run the test suites with `DFLTCC=0` to pass:
-```
+```sh
DFLTCC=0 make check
```
diff --git a/doc/contributing/vm_stack_and_frames.md b/doc/contributing/vm_stack_and_frames.md
new file mode 100644
index 0000000000..c7dc59db16
--- /dev/null
+++ b/doc/contributing/vm_stack_and_frames.md
@@ -0,0 +1,163 @@
+# Ruby VM Stack and Frame Layout
+
+This document explains the Ruby VM stack architecture, including how the value
+stack (SP) and control frames (CFP) share a single contiguous memory region,
+and how individual frames are structured.
+
+## VM Stack Architecture
+
+The Ruby VM uses a single contiguous stack (`ec->vm_stack`) with two different
+regions growing toward each other. Understanding this requires distinguishing
+the overall architecture (how CFPs and values share one stack) from individual
+frame internals (how values are organized for one single frame).
+
+```text
+High addresses (ec->vm_stack + ec->vm_stack_size)
+ ↓
+ [CFP region starts here] ← RUBY_VM_END_CONTROL_FRAME(ec)
+ [CFP - 1] New frame pushed here (grows downward)
+ [CFP - 2] Another frame
+ ...
+
+ (Unused space - stack overflow when they meet)
+
+ ... Value stack grows UP toward higher addresses
+ [SP + n] Values pushed here
+ [ec->cfp->sp] Current executing frame's stack pointer
+ ↑
+Low addresses (ec->vm_stack)
+```
+
+The "unused space" represents free space available for new frames and values. When this gap closes (CFP meets SP), stack overflow occurs.
+
+### Stack Growth Directions
+
+**Control Frames (CFP):**
+
+- Start at `ec->vm_stack + ec->vm_stack_size` (high addresses)
+- Grow **downward** toward lower addresses as frames are pushed
+- Each new frame is allocated at `cfp - 1` (lower address)
+- The `rb_control_frame_t` structure itself moves downward
+
+**Value Stack (SP):**
+
+- Starts at `ec->vm_stack` (low addresses)
+- Grows **upward** toward higher addresses as values are pushed
+- Each frame's `cfp->sp` points to the top of its value stack
+
+### Stack Overflow
+
+When recursive calls push too many frames, CFP grows downward until it collides
+with SP growing upward. The VM detects this with `CHECK_VM_STACK_OVERFLOW0`,
+which computes `const rb_control_frame_struct *bound = (void *)&sp[margin];`
+and raises if `cfp <= &bound[1]`.
+
+## Understanding Individual Frame Value Stacks
+
+Each frame has its own portion of the overall VM stack, called its "VM value stack"
+or simply "value stack". This space is pre-allocated when the frame is created,
+with size determined by:
+
+- `local_size` - space for local variables
+- `stack_max` - maximum depth for temporary values during execution
+
+The frame's value stack grows upward from its base (where self/arguments/locals
+live) toward `cfp->sp` (the current top of temporary values).
+
+## Visualizing How Frames Fit in the VM Stack
+
+The left side shows the overall VM stack with CFP metadata separated from frame
+values. The right side zooms into one frame's value region, revealing its internal
+structure.
+
+```text
+Overall VM Stack (ec->vm_stack): Zooming into Frame 2's value stack:
+
+High addr (vm_stack + vm_stack_size) High addr (cfp->sp)
+ ↓ ┌
+ [CFP 1 metadata] │ [Temporaries]
+ [CFP 2 metadata] ─────────┐ │ [Env: Flags/Block/CME] ← cfp->ep
+ [CFP 3 metadata] │ │ [Locals]
+ ──────────────── │ ┌─┤ [Arguments]
+ (unused space) │ │ │ [self]
+ ──────────────── │ │ └
+ [Frame 3 values] │ │ Low addr (frame base)
+ [Frame 2 values] <────────┴───────┘
+ [Frame 1 values]
+ ↑
+Low addr (vm_stack)
+```
+
+## Examining a Single Frame's Value Stack
+
+Now let's walk through a concrete Ruby program to see how a single frame's
+value stack is structured internally:
+
+```ruby
+def foo(x, y)
+ z = x.casecmp(y)
+end
+
+foo(:one, :two)
+```
+
+First, after arguments are evaluated and right before the `send` to `foo`:
+
+```text
+ ┌────────────┐
+ putself │ :two │
+ putobject :one 0x2 ├────────────┤
+ putobject :two │ :one │
+► send <:foo, argc:2> 0x1 ├────────────┤
+ leave │ self │
+ 0x0 └────────────┘
+```
+
+The `put*` instructions have pushed 3 items onto the stack. It's now time to
+add a new control frame for `foo`. The following is the shape of the stack
+after one instruction in `foo`:
+
+```text
+ cfp->sp=0x8 at this point.
+ 0x8 ┌────────────┐◄──Stack space for temporaries
+ │ :one │ live above the environment.
+ 0x7 ├────────────┤
+ getlocal x@0 │ < flags > │ foo's rb_control_frame_t
+► getlocal y@1 0x6 ├────────────┤◄──has cfp->ep=0x6
+ send <:casecmp, argc:1> │ <no block> │
+ dup 0x5 ├────────────┤ The flags, block, and CME triple
+ setlocal z@2 │ <CME: foo> │ (VM_ENV_DATA_SIZE) form an
+ leave 0x4 ├────────────┤ environment. They can be used to
+ │ z (nil) │ figure out what local variables
+ 0x3 ├────────────┤ are below them.
+ │ :two │
+ 0x2 ├────────────┤ Notice how the arguments, now
+ │ :one │ locals, never moved. This layout
+ 0x1 ├────────────┤ allows for argument transfer
+ │ self │ without copying.
+ 0x0 └────────────┘
+```
+
+Given that locals have lower address than `cfp->ep`, it makes sense then that
+`getlocal` in `insns.def` has `val = *(vm_get_ep(GET_EP(), level) - idx);`.
+When accessing variables in the immediate scope, where `level=0`, it's
+essentially `val = cfp->ep[-idx];`.
+
+Note that this EP-relative index has a different basis than the index that comes
+after "@" in disassembly listings. The "@" index is relative to the 0th local
+(`x` in this case).
+
+### Q&A
+
+Q: It seems that the receiver is always at an offset relative to EP,
+ like locals. Couldn't we use EP to access it instead of using `cfp->self`?
+
+A: Not all calls put the `self` in the callee on the stack. Two
+ examples are `Proc#call`, where the receiver is the Proc object, but `self`
+ inside the callee is `Proc#receiver`, and `yield`, where the receiver isn't
+ pushed onto the stack before the arguments.
+
+Q: Why have `cfp->ep` when it seems that everything is below `cfp->sp`?
+
+A: In the example, `cfp->ep` points to the stack, but it can also point to the
+ GC heap. Blocks can capture and evacuate their environment to the heap.
diff --git a/doc/date/calendars.rdoc b/doc/date/calendars.rdoc
deleted file mode 100644
index b8690841b1..0000000000
--- a/doc/date/calendars.rdoc
+++ /dev/null
@@ -1,62 +0,0 @@
-== Julian and Gregorian Calendars
-
-The difference between the
-{Julian calendar}[https://en.wikipedia.org/wiki/Julian_calendar]
-and the
-{Gregorian calendar}[https://en.wikipedia.org/wiki/Gregorian_calendar]
-may matter to your program if it uses dates before the switchovers.
-
-- October 15, 1582.
-- September 14, 1752.
-
-A date will be different in the two calendars, in general.
-
-=== Different switchover dates
-
-The reasons for the difference are religious/political histories.
-
-- On October 15, 1582, several countries changed
- from the Julian calendar to the Gregorian calendar;
- these included Italy, Poland, Portugal, and Spain.
- Other contries in the Western world retained the Julian calendar.
-- On September 14, 1752, most of the British empire
- changed from the Julian calendar to the Gregorian calendar.
-
-When your code uses a date before these switchover dates,
-it will matter whether it considers the switchover date
-to be the earlier date or the later date (or neither).
-
-See also {a concrete example here}[rdoc-ref:DateTime@When+should+you+use+DateTime+and+when+should+you+use+Time-3F].
-
-=== Argument +start+
-
-Certain methods in class \Date handle differences in the
-{Julian and Gregorian calendars}[rdoc-ref:calendars.rdoc@Julian+and+Gregorian+Calendars]
-by accepting an optional argument +start+, whose value may be:
-
-- Date::ITALY (the default): the created date is Julian
- if before October 15, 1582, Gregorian otherwise:
-
- d = Date.new(1582, 10, 15)
- d.prev_day.julian? # => true
- d.julian? # => false
- d.gregorian? # => true
-
-- Date::ENGLAND: the created date is Julian if before September 14, 1752,
- Gregorian otherwise:
-
- d = Date.new(1752, 9, 14, Date::ENGLAND)
- d.prev_day.julian? # => true
- d.julian? # => false
- d.gregorian? # => true
-
-- Date::JULIAN: the created date is Julian regardless of its value:
-
- d = Date.new(1582, 10, 15, Date::JULIAN)
- d.julian? # => true
-
-- Date::GREGORIAN: the created date is Gregorian regardless of its value:
-
- d = Date.new(1752, 9, 14, Date::GREGORIAN)
- d.prev_day.gregorian? # => true
-
diff --git a/doc/distribution.md b/doc/distribution.md
deleted file mode 100644
index bc89a7500a..0000000000
--- a/doc/distribution.md
+++ /dev/null
@@ -1,47 +0,0 @@
-# Distribution
-
-This document outlines the expected way to distribute Ruby, with a specific focus on building Ruby packages.
-
-## Getting the Ruby Tarball
-
-### Official Releases
-
-The tarball for official releases is created by the release manager. The release manager uploads the tarball to the [Ruby website](https://www.ruby-lang.org/en/downloads/).
-
-Downstream distributors should use the official release tarballs as part of their build process. This ensures that the tarball is created in a consistent way, and that the tarball is crytographically verified.
-
-### Using the nightly tarball for testing
-
-See the Snapshots section of the [Ruby website](https://www.ruby-lang.org/en/downloads/).
-
-### Building a manual snapshot tarball for testing
-
-This can be useful if the nightly tarball does not have all changes yet.
-
-At Ruby source tree cloned using git:
-```sh-session
-$ ./autogen.sh
-$ ./configure -C
-$ make
-$ make dist
-```
-
-This will create several tarball in the `tmp` directory. The tarball will be named e.g. `ruby-<version>.tar.gz` (several different compression formats will be generated).
-
-## Building the Tarball
-
-See [Building Ruby](contributing/building_ruby.md).
-
-## Updating the Ruby Standard Library
-
-The Ruby standard library is a collection of Ruby files that are included with Ruby. These files are used to provide the basic functionality of Ruby. The standard library is located in the `lib` directory and is distributed as part of the Ruby tarball.
-
-Occasionally, the standard library needs to be updated, for example a security issue might be found in a default gem or standard gem. There are two main ways that Ruby would update this code.
-
-### Releasing an Updated Ruby Gem
-
-Normally, the Ruby gem maintainer will release an updated gem. This gem can be installed alongside the default gem. This allows the user to update the gem without having to update Ruby.
-
-### Releasing a New Ruby Version
-
-If the update is critical, then the Ruby maintainers may decide to release a new version of Ruby. This new version will include the updated standard library.
diff --git a/doc/distribution/distribution.md b/doc/distribution/distribution.md
new file mode 100644
index 0000000000..164e1b7109
--- /dev/null
+++ b/doc/distribution/distribution.md
@@ -0,0 +1,48 @@
+# Distribution
+
+This document outlines the expected way to distribute Ruby, with a specific focus on building Ruby packages.
+
+## Getting the Ruby Tarball
+
+### Official Releases
+
+The tarball for official releases is created by the release manager. The release manager uploads the tarball to the [Ruby website](https://www.ruby-lang.org/en/downloads/).
+
+Downstream distributors should use the official release tarballs as part of their build process. This ensures that the tarball is created in a consistent way, and that the tarball is cryptographically verified.
+
+### Using the nightly tarball for testing
+
+See the Snapshots section of the [Ruby website](https://www.ruby-lang.org/en/downloads/).
+
+### Building a manual snapshot tarball for testing
+
+This can be useful if the nightly tarball does not have all changes yet.
+
+At Ruby source tree cloned using git:
+
+```console
+$ ./autogen.sh
+$ ./configure -C
+$ make
+$ make dist
+```
+
+This will create several tarball in the `tmp` directory. The tarball will be named e.g. `ruby-<version>.tar.gz` (several different compression formats will be generated).
+
+## Building the Tarball
+
+See [Building Ruby](contributing/building_ruby.md).
+
+## Updating the Ruby Standard Library
+
+The Ruby standard library is a collection of Ruby files that are included with Ruby. These files are used to provide the basic functionality of Ruby. The standard library is located in the `lib` directory and is distributed as part of the Ruby tarball.
+
+Occasionally, the standard library needs to be updated, for example a security issue might be found in a default gem or standard gem. There are two main ways that Ruby would update this code.
+
+### Releasing an Updated Ruby Gem
+
+Normally, the Ruby gem maintainer will release an updated gem. This gem can be installed alongside the default gem. This allows the user to update the gem without having to update Ruby.
+
+### Releasing a New Ruby Version
+
+If the update is critical, then the Ruby maintainers may decide to release a new version of Ruby. This new version will include the updated standard library.
diff --git a/doc/distribution/windows.md b/doc/distribution/windows.md
new file mode 100644
index 0000000000..26a727d7ad
--- /dev/null
+++ b/doc/distribution/windows.md
@@ -0,0 +1,304 @@
+# Windows
+
+Ruby supports a few native build platforms for Windows.
+
+* mswin: Build using Microsoft Visual C++ compiler with vcruntimeXXX.dll
+* mingw-msvcrt: Build using compiler for Mingw with msvcrtXX.dll
+* mingw-ucrt: Build using compiler for Mingw with Windows Universal CRT
+
+## Building Ruby using Mingw with UCRT
+
+The easiest build environment is just a standard [RubyInstaller-Devkit]
+installation and [git-for-windows]. You might like to use [VSCode] as an
+editor.
+
+### Build examples
+
+Ruby core development can be done either in Windows `cmd` like:
+
+```batch
+ridk install
+ridk enable ucrt64
+
+pacman -S --needed %MINGW_PACKAGE_PREFIX%-openssl %MINGW_PACKAGE_PREFIX%-libyaml %MINGW_PACKAGE_PREFIX%-libffi
+
+mkdir c:\work\ruby
+cd /d c:\work\ruby
+
+git clone https://github.com/ruby/ruby src
+
+sh ./src/autogen.sh
+
+mkdir build
+cd build
+sh ../src/configure -C --disable-install-doc
+make
+```
+
+or in MSYS2 `bash` like:
+
+```bash
+ridk install
+ridk enable ucrt64
+bash
+
+pacman -S --needed $MINGW_PACKAGE_PREFIX-openssl $MINGW_PACKAGE_PREFIX-libyaml $MINGW_PACKAGE_PREFIX-libffi
+
+mkdir /c/work/ruby
+cd /c/work/ruby
+
+git clone https://github.com/ruby/ruby src
+
+./src/autogen.sh
+cd build
+../src/configure -C --disable-install-doc
+make
+```
+
+If you have other MSYS2 environment via other package manager like `scoop`, you need to specify `$MINGW_PACKAGE_PREFIX` is `mingw-w64-ucrt-x86_64`.
+And you need to add `--with-opt-dir` option to `configure` command like:
+
+```batch
+sh ../../ruby/configure -C --disable-install-doc --with-opt-dir=C:\Users\username\scoop\apps\msys2\current\ucrt64
+```
+
+[RubyInstaller-Devkit]: https://rubyinstaller.org/
+[git-for-windows]: https://gitforwindows.org/
+[VSCode]: https://code.visualstudio.com/
+
+## Building Ruby using Visual C++
+
+### Requirement
+
+1. Windows 10/Windows Server 2016 or later.
+
+2. Visual C++ 14.0 (2015) or later.
+
+ **Note** if you want to build x64 version, use native compiler for
+ x64.
+
+ The minimum requirement is here:
+ * VC++/MSVC on VS 2017/2019/2022 version build tools.
+ * Windows 10/11 SDK
+
+ You can install Visual Studio Build Tools with `winget`.
+ `win32\install-buildtools.cmd` is a batch file to install the
+ minimum requirements excluding the IDE etc.
+
+3. Please set environment variable `INCLUDE`, `LIB`, `PATH` to run
+ required commands properly from the command line. These are set
+ properly by `vsdevcmd.bat` or `vcvarall*.bat` usually. You can run
+ the following command to set them in your command line.
+
+ To native build:
+
+ ```
+ cmd /k win32\vssetup.cmd
+ ```
+
+ To cross build arm64 binary:
+
+ ```
+ cmd /k win32\vssetup.cmd -arch=arm64
+ ```
+
+ To cross build x64 binary:
+
+ ```
+ cmd /k win32\vssetup.cmd -arch=x64
+ ```
+
+ This batch file is a wrapper of `vsdevcmd.bat` and options are
+ passed to it as-is. `win32\vssetup.cmd -help` for other command
+ line options.
+
+ **Note** building ruby requires following commands.
+
+ * `nmake`
+ * `cl`
+ * `ml`
+ * `lib`
+ * `dumpbin`
+
+4. If you want to build from GIT source, following commands are required.
+ * `git`
+ * `ruby` 3.1 or later
+
+ You can use [scoop](https://scoop.sh/) to install them like:
+
+ ```batch
+ scoop install git ruby
+ ```
+
+ The windows version of `git` configured with `autocrlf` is `true`. The Ruby
+ test suite may fail with `autocrlf` set to `true`. You can set it to `false`
+ like:
+
+ ```batch
+ git config --global core.autocrlf false
+ ```
+
+5. You need to install required libraries using [vcpkg](https://vcpkg.io/) on
+ directory of ruby repository like:
+
+ ```batch
+ vcpkg --triplet x64-windows install
+ ```
+
+6. Enable Command Extension of your command line. It's the default behavior
+ of `cmd.exe`. If you want to enable it explicitly, run `cmd.exe` with
+ `/E:ON` option.
+
+### How to compile and install
+
+1. Execute `win32\configure.bat` on your build directory.
+ You can specify the target platform as an argument.
+ For example, run `configure --target=i686-mswin32`.
+ You can also specify the install directory.
+ For example, run `configure --prefix=<install_directory>`.
+ Default of the install directory is `/usr` .
+
+2. If you want to append to the executable and DLL file names,
+ specify `--program-prefix` and `--program-suffix`, like
+ `win32\configure.bat --program-suffix=-$(MAJOR)$(MINOR)`.
+
+ Also, the `--install-name` and `--so-name` options specify the
+ exact base names of the executable and DLL files, respectively,
+ like `win32\configure.bat --install-name=$(RUBY_BASE_NAME)-$(MAJOR)$(MINOR)`.
+
+ By default, the name for the executable without a console window
+ is generated from the _RUBY_INSTALL_NAME_ specified as above by
+ replacing `ruby` with `rubyw`. If you want to make it different
+ more, modify _RUBYW_INSTALL_NAME_ directly in the Makefile.
+
+3. You need specify vcpkg directory to use `--with-opt-dir`
+ option like `win32\configure.bat --with-opt-dir=C:/vcpkg_installed/x64-windows`
+
+4. Run `nmake up` if you are building from GIT source.
+
+5. Run `nmake`
+
+6. Run `nmake prepare-vcpkg` with administrator privilege if you need to
+ copy vcpkg installed libraries like `libssl-3-x64.dll` to the build directory.
+
+7. Run `nmake check`
+
+8. Run `nmake install`
+
+### Build examples
+
+* Build on the ruby source directory.
+
+ ```
+ ruby source directory: C:\ruby
+ build directory: C:\ruby
+ install directory: C:\usr\local
+ ```
+
+ ```batch
+ C:
+ cd \ruby
+ win32\configure --prefix=/usr/local
+ nmake
+ nmake check
+ nmake install
+ ```
+
+* Build on the relative directory from the ruby source directory.
+
+ ```
+ ruby source directory: C:\ruby
+ build directory: C:\ruby\mswin32
+ install directory: C:\usr\local
+ ```
+
+ ```batch
+ C:
+ cd \ruby
+ mkdir mswin32
+ cd mswin32
+ ..\win32\configure --prefix=/usr/local
+ nmake
+ nmake check
+ nmake install
+ ```
+
+* Build on the different drive.
+
+ ```
+ ruby source directory: C:\src\ruby
+ build directory: D:\build\ruby
+ install directory: C:\usr\local
+ ```
+
+ ```batch
+ D:
+ cd D:\build\ruby
+ C:\src\ruby\win32\configure --prefix=/usr/local
+ nmake
+ nmake check
+ nmake install DESTDIR=C:
+ ```
+
+* Build x64 version (requires native x64 VC++ compiler)
+
+ ```
+ ruby source directory: C:\ruby
+ build directory: C:\ruby
+ install directory: C:\usr\local
+ ```
+
+ ```batch
+ C:
+ cd \ruby
+ win32\configure --prefix=/usr/local --target=x64-mswin64
+ nmake
+ nmake check
+ nmake install
+ ```
+
+### Bugs
+
+You can **NOT** use a path name that contains any white space characters
+as the ruby source directory, this restriction comes from the behavior
+of `!INCLUDE` directives of `NMAKE`.
+
+You can build ruby in any directory including the source directory,
+except `win32` directory in the source directory.
+This is restriction originating in the path search method of `NMAKE`.
+
+### Dependency management
+
+Ruby uses [vcpkg](https://vcpkg.io/) to manage dependencies on mswin platform.
+
+You can update and install it under the build directory like:
+
+```batch
+nmake update-vcpkg # Update baseline version of vcpkg
+nmake install-vcpkg # Install vcpkg from build directory
+```
+
+
+## Icons
+
+Any icon files(`*.ico`) in the build directory, directories specified with
+_icondirs_ make variable and `win32` directory under the ruby
+source directory will be included in DLL or executable files, according
+to their base names.
+
+ $(RUBY_INSTALL_NAME).ico or ruby.ico --> $(RUBY_INSTALL_NAME).exe
+ $(RUBYW_INSTALL_NAME).ico or rubyw.ico --> $(RUBYW_INSTALL_NAME).exe
+ the others --> $(RUBY_SO_NAME).dll
+
+Although no icons are distributed with the ruby source, you can use
+anything you like. You will be able to find many images by search engines.
+For example, followings are made from [Ruby logo kit]:
+
+* Small [favicon] in the official site
+
+* [vit-ruby.ico] or [icon itself]
+
+[Ruby logo kit]: https://cache.ruby-lang.org/pub/misc/logo/ruby-logo-kit.zip
+[favicon]: https://www.ruby-lang.org/favicon.ico
+[vit-ruby.ico]: http://ruby.morphball.net/vit-ruby-ico_en.html
+[icon itself]: http://ruby.morphball.net/icon/vit-ruby.ico
diff --git a/doc/encodings.rdoc b/doc/encodings.rdoc
deleted file mode 100644
index d85099cdbc..0000000000
--- a/doc/encodings.rdoc
+++ /dev/null
@@ -1,481 +0,0 @@
-= Encodings
-
-== The Basics
-
-A {character encoding}[https://en.wikipedia.org/wiki/Character_encoding],
-often shortened to _encoding_, is a mapping between:
-
-- A sequence of 8-bit bytes (each byte in the range <tt>0..255</tt>).
-- Characters in a specific character set.
-
-Some character sets contain only 1-byte characters;
-{US-ASCII}[https://en.wikipedia.org/wiki/ASCII], for example, has 256 1-byte characters.
-This string, encoded in US-ASCII, has six characters that are stored as six bytes:
-
- s = 'Hello!'.encode('US-ASCII') # => "Hello!"
- s.encoding # => #<Encoding:US-ASCII>
- s.bytes # => [72, 101, 108, 108, 111, 33]
-
-Other encodings may involve multi-byte characters.
-{UTF-8}[https://en.wikipedia.org/wiki/UTF-8], for example,
-encodes more than one million characters, encoding each in one to four bytes.
-The lowest-valued of these characters correspond to ASCII characters,
-and so are 1-byte characters:
-
- s = 'Hello!' # => "Hello!"
- s.bytes # => [72, 101, 108, 108, 111, 33]
-
-Other characters, such as the Euro symbol, are multi-byte:
-
- s = "\u20ac" # => "€"
- s.bytes # => [226, 130, 172]
-
-== The \Encoding \Class
-
-=== \Encoding Objects
-
-Ruby encodings are defined by constants in class \Encoding.
-There can be only one instance of \Encoding for each of these constants.
-\Method Encoding.list returns an array of \Encoding objects (one for each constant):
-
- Encoding.list.size # => 103
- Encoding.list.first.class # => Encoding
- Encoding.list.take(3)
- # => [#<Encoding:ASCII-8BIT>, #<Encoding:UTF-8>, #<Encoding:US-ASCII>]
-
-=== Names and Aliases
-
-\Method Encoding#name returns the name of an \Encoding:
-
- Encoding::ASCII_8BIT.name # => "ASCII-8BIT"
- Encoding::WINDOWS_31J.name # => "Windows-31J"
-
-An \Encoding object has zero or more aliases;
-method Encoding#names returns an array containing the name and all aliases:
-
- Encoding::ASCII_8BIT.names
- # => ["ASCII-8BIT", "BINARY"]
- Encoding::WINDOWS_31J.names
- #=> ["Windows-31J", "CP932", "csWindows31J", "SJIS", "PCK"]
-
-\Method Encoding.aliases returns a hash of all alias/name pairs:
-
- Encoding.aliases.size # => 71
- Encoding.aliases.take(3)
- # => [["BINARY", "ASCII-8BIT"], ["CP437", "IBM437"], ["CP720", "IBM720"]]
-
-\Method Encoding.name_list returns an array of all the encoding names and aliases:
-
- Encoding.name_list.size # => 175
- Encoding.name_list.take(3)
- # => ["ASCII-8BIT", "UTF-8", "US-ASCII"]
-
-\Method +name_list+ returns more entries than method +list+
-because it includes both the names and their aliases.
-
-\Method Encoding.find returns the \Encoding for a given name or alias, if it exists:
-
- Encoding.find("US-ASCII") # => #<Encoding:US-ASCII>
- Encoding.find("US-ASCII").class # => Encoding
-
-=== Default Encodings
-
-\Method Encoding.find, above, also returns a default \Encoding
-for each of these special names:
-
-- +external+: the default external \Encoding:
-
- Encoding.find("external") # => #<Encoding:UTF-8>
-
-- +internal+: the default internal \Encoding (may be +nil+):
-
- Encoding.find("internal") # => nil
-
-- +locale+: the default \Encoding for a string from the environment:
-
- Encoding.find("locale") # => #<Encoding:UTF-8> # Linux
- Encoding.find("locale") # => #<Encoding:IBM437> # Windows
-
-- +filesystem+: the default \Encoding for a string from the filesystem:
-
- Encoding.find("filesystem") # => #<Encoding:UTF-8>
-
-\Method Encoding.default_external returns the default external \Encoding:
-
- Encoding.default_external # => #<Encoding:UTF-8>
-
-\Method Encoding.default_external= sets that value:
-
- Encoding.default_external = 'US-ASCII' # => "US-ASCII"
- Encoding.default_external # => #<Encoding:US-ASCII>
-
-\Method Encoding.default_internal returns the default internal \Encoding:
-
- Encoding.default_internal # => nil
-
-\Method Encoding.default_internal= sets the default internal \Encoding:
-
- Encoding.default_internal = 'US-ASCII' # => "US-ASCII"
- Encoding.default_internal # => #<Encoding:US-ASCII>
-
-=== Compatible Encodings
-
-\Method Encoding.compatible? returns whether two given objects are encoding-compatible
-(that is, whether they can be concatenated);
-returns the \Encoding of the concatenated string, or +nil+ if incompatible:
-
- rus = "\u{442 435 441 442}"
- eng = 'text'
- Encoding.compatible?(rus, eng) # => #<Encoding:UTF-8>
-
- s0 = "\xa1\xa1".force_encoding('iso-8859-1') # => "\xA1\xA1"
- s1 = "\xa1\xa1".force_encoding('euc-jp') # => "\x{A1A1}"
- Encoding.compatible?(s0, s1) # => nil
-
-== \String \Encoding
-
-A Ruby String object has an encoding that is an instance of class \Encoding.
-The encoding may be retrieved by method String#encoding.
-
-The default encoding for a string literal is the script encoding;
-see {Script Encoding}[rdoc-ref:encodings.rdoc@Script+Encoding].
-
- 's'.encoding # => #<Encoding:UTF-8>
-
-The default encoding for a string created with method String.new is:
-
-- For a \String object argument, the encoding of that string.
-- For a string literal, the script encoding;
- see {Script Encoding}[rdoc-ref:encodings.rdoc@Script+Encoding].
-
-In either case, any encoding may be specified:
-
- s = String.new(encoding: 'UTF-8') # => ""
- s.encoding # => #<Encoding:UTF-8>
- s = String.new('foo', encoding: 'ASCII-8BIT') # => "foo"
- s.encoding # => #<Encoding:ASCII-8BIT>
-
-The encoding for a string may be changed:
-
- s = "R\xC3\xA9sum\xC3\xA9" # => "Résumé"
- s.encoding # => #<Encoding:UTF-8>
- s.force_encoding('ISO-8859-1') # => "R\xC3\xA9sum\xC3\xA9"
- s.encoding # => #<Encoding:ISO-8859-1>
-
-Changing the assigned encoding does not alter the content of the string;
-it changes only the way the content is to be interpreted:
-
- s # => "R\xC3\xA9sum\xC3\xA9"
- s.force_encoding('UTF-8') # => "Résumé"
-
-The actual content of a string may also be altered;
-see {Transcoding a String}[#label-Transcoding+a+String].
-
-Here are a couple of useful query methods:
-
- s = "abc".force_encoding("UTF-8") # => "abc"
- s.ascii_only? # => true
- s = "abc\u{6666}".force_encoding("UTF-8") # => "abc晦"
- s.ascii_only? # => false
-
- s = "\xc2\xa1".force_encoding("UTF-8") # => "¡"
- s.valid_encoding? # => true
- s = "\xc2".force_encoding("UTF-8") # => "\xC2"
- s.valid_encoding? # => false
-
-== \Symbol and \Regexp Encodings
-
-The string stored in a Symbol or Regexp object also has an encoding;
-the encoding may be retrieved by method Symbol#encoding or Regexp#encoding.
-
-The default encoding for these, however, is:
-
-- US-ASCII, if all characters are US-ASCII.
-- The script encoding, otherwise;
- see (Script Encoding)[rdoc-ref:encodings.rdoc@Script+Encoding].
-
-== Filesystem \Encoding
-
-The filesystem encoding is the default \Encoding for a string from the filesystem:
-
- Encoding.find("filesystem") # => #<Encoding:UTF-8>
-
-== Locale \Encoding
-
-The locale encoding is the default encoding for a string from the environment,
-other than from the filesystem:
-
- Encoding.find('locale') # => #<Encoding:IBM437>
-
-== Stream Encodings
-
-Certain stream objects can have two encodings; these objects include instances of:
-
-- IO.
-- File.
-- ARGF.
-- StringIO.
-
-The two encodings are:
-
-- An _external_ _encoding_, which identifies the encoding of the stream.
-- An _internal_ _encoding_, which (if not +nil+) specifies the encoding
- to be used for the string constructed from the stream.
-
-=== External \Encoding
-
-The external encoding, which is an \Encoding object, specifies how bytes read
-from the stream are to be interpreted as characters.
-
-The default external encoding is:
-
-- UTF-8 for a text stream.
-- ASCII-8BIT for a binary stream.
-
-The default external encoding is returned by method Encoding.default_external,
-and may be set by:
-
-- Ruby command-line options <tt>--external_encoding</tt> or <tt>-E</tt>.
-
-You can also set the default external encoding using method Encoding.default_external=,
-but doing so may cause problems; strings created before and after the change
-may have a different encodings.
-
-For an \IO or \File object, the external encoding may be set by:
-
-- Open options +external_encoding+ or +encoding+, when the object is created;
- see {Open Options}[rdoc-ref:IO@Open+Options].
-
-For an \IO, \File, \ARGF, or \StringIO object, the external encoding may be set by:
-
-- \Methods +set_encoding+ or (except for \ARGF) +set_encoding_by_bom+.
-
-=== Internal \Encoding
-
-The internal encoding, which is an \Encoding object or +nil+,
-specifies how characters read from the stream
-are to be converted to characters in the internal encoding;
-those characters become a string whose encoding is set to the internal encoding.
-
-The default internal encoding is +nil+ (no conversion).
-It is returned by method Encoding.default_internal,
-and may be set by:
-
-- Ruby command-line options <tt>--internal_encoding</tt> or <tt>-E</tt>.
-
-You can also set the default internal encoding using method Encoding.default_internal=,
-but doing so may cause problems; strings created before and after the change
-may have a different encodings.
-
-For an \IO or \File object, the internal encoding may be set by:
-
-- Open options +internal_encoding+ or +encoding+, when the object is created;
- see {Open Options}[rdoc-ref:IO@Open+Options].
-
-For an \IO, \File, \ARGF, or \StringIO object, the internal encoding may be set by:
-
-- \Method +set_encoding+.
-
-== Script \Encoding
-
-A Ruby script has a script encoding, which may be retrieved by:
-
- __ENCODING__ # => #<Encoding:UTF-8>
-
-The default script encoding is UTF-8;
-a Ruby source file may set its script encoding with a magic comment
-on the first line of the file (or second line, if there is a shebang on the first).
-The comment must contain the word +coding+ or +encoding+,
-followed by a colon, space and the Encoding name or alias:
-
- # encoding: ISO-8859-1
- __ENCODING__ #=> #<Encoding:ISO-8859-1>
-
-== Transcoding
-
-_Transcoding_ is the process of changing a sequence of characters
-from one encoding to another.
-
-As far as possible, the characters remain the same,
-but the bytes that represent them may change.
-
-The handling for characters that cannot be represented in the destination encoding
-may be specified by @Encoding+Options.
-
-=== Transcoding a \String
-
-Each of these methods transcodes a string:
-
-- String#encode: Transcodes +self+ into a new string
- according to given encodings and options.
-- String#encode!: Like String#encode, but transcodes +self+ in place.
-- String#scrub: Transcodes +self+ into a new string
- by replacing invalid byte sequences with a given or default replacement string.
-- String#scrub!: Like String#scrub, but transcodes +self+ in place.
-- String#unicode_normalize: Transcodes +self+ into a new string
- according to Unicode normalization.
-- String#unicode_normalize!: Like String#unicode_normalize,
- but transcodes +self+ in place.
-
-== Transcoding a Stream
-
-Each of these methods may transcode a stream;
-whether it does so depends on the external and internal encodings:
-
-- IO.foreach: Yields each line of given stream to the block.
-- IO.new: Creates and returns a new \IO object for the given integer file descriptor.
-- IO.open: Creates a new \IO object.
-- IO.pipe: Creates a connected pair of reader and writer \IO objects.
-- IO.popen: Creates an \IO object to interact with a subprocess.
-- IO.read: Returns a string with all or a subset of bytes from the given stream.
-- IO.readlines: Returns an array of strings, which are the lines from the given stream.
-- IO.write: Writes a given string to the given stream.
-
-This example writes a string to a file, encoding it as ISO-8859-1,
-then reads the file into a new string, encoding it as UTF-8:
-
- s = "R\u00E9sum\u00E9"
- path = 't.tmp'
- ext_enc = 'ISO-8859-1'
- int_enc = 'UTF-8'
-
- File.write(path, s, external_encoding: ext_enc)
- raw_text = File.binread(path)
-
- transcoded_text = File.read(path, external_encoding: ext_enc, internal_encoding: int_enc)
-
- p raw_text
- p transcoded_text
-
-Output:
-
- "R\xE9sum\xE9"
- "Résumé"
-
-== \Encoding Options
-
-A number of methods in the Ruby core accept keyword arguments as encoding options.
-
-Some of the options specify or utilize a _replacement_ _string_, to be used
-in certain transcoding operations.
-A replacement string may be in any encoding that can be converted
-to the encoding of the destination string.
-
-These keyword-value pairs specify encoding options:
-
-- For an invalid byte sequence:
-
- - <tt>:invalid: nil</tt> (default): Raise exception.
- - <tt>:invalid: :replace</tt>: Replace each invalid byte sequence
- with the replacement string.
-
- Examples:
-
- s = "\x80foo\x80"
- s.encode('ISO-8859-3') # Raises Encoding::InvalidByteSequenceError.
- s.encode('ISO-8859-3', invalid: :replace) # => "?foo?"
-
-- For an undefined character:
-
- - <tt>:undef: nil</tt> (default): Raise exception.
- - <tt>:undef: :replace</tt>: Replace each undefined character
- with the replacement string.
-
- Examples:
-
- s = "\x80foo\x80"
- "\x80".encode('UTF-8', 'ASCII-8BIT') # Raises Encoding::UndefinedConversionError.
- s.encode('UTF-8', 'ASCII-8BIT', undef: :replace) # => "�foo�"
-
-
-- Replacement string:
-
- - <tt>:replace: nil</tt> (default): Set replacement string to default value:
- <tt>"\uFFFD"</tt> ("�") for a Unicode encoding, <tt>'?'</tt> otherwise.
- - <tt>:replace: _some_string_</tt>: Set replacement string to the given +some_string+;
- overrides +:fallback+.
-
- Examples:
-
- s = "\xA5foo\xA5"
- options = {:undef => :replace, :replace => 'xyzzy'}
- s.encode('UTF-8', 'ISO-8859-3', **options) # => "xyzzyfooxyzzy"
-
-- Replacement fallback:
-
- One of these may be specified:
-
- - <tt>:fallback: nil</tt> (default): No replacement fallback.
- - <tt>:fallback: _hash_like_object_</tt>: Set replacement fallback to the given
- +hash_like_object+; the replacement string is <tt>_hash_like_object_[X]</tt>.
- - <tt>:fallback: _method_</tt>: Set replacement fallback to the given
- +method+; the replacement string is <tt>_method_(X)</tt>.
- - <tt>:fallback: _proc_</tt>: Set replacement fallback to the given
- +proc+; the replacement string is <tt>_proc_[X]</tt>.
-
- Examples:
-
- s = "\u3042foo\u3043"
-
- hash = {"\u3042" => 'xyzzy'}
- hash.default = 'XYZZY'
- s.encode('ASCII', fallback: hash) # => "xyzzyfooXYZZY"
-
- def (fallback = "U+%.4X").escape(x)
- self % x.unpack("U")
- end
- "\u{3042}".encode("US-ASCII", fallback: fallback.method(:escape)) # => "U+3042"
-
- proc = Proc.new {|x| x == "\u3042" ? 'xyzzy' : 'XYZZY' }
- s.encode('ASCII', fallback: proc) # => "XYZZYfooXYZZY"
-
-- XML entities:
-
- One of these may be specified:
-
- - <tt>:xml: nil</tt> (default): No handling for XML entities.
- - <tt>:xml: :text</tt>: Treat source text as XML;
- replace each undefined character
- with its upper-case hexdecimal numeric character reference,
- except that:
-
- - <tt>&</tt> is replaced with <tt>&amp;</tt>.
- - <tt><</tt> is replaced with <tt>&lt;</tt>.
- - <tt>></tt> is replaced with <tt>&gt;</tt>.
-
- - <tt>:xml: :attr</tt>: Treat source text as XML attribute value;
- replace each undefined character
- with its upper-case hexdecimal numeric character reference,
- except that:
-
- - The replacement string <tt>r</tt> is double-quoted (<tt>"r"</tt>).
- - Each embedded double-quote is replaced with <tt>&quot;</tt>.
- - <tt>&</tt> is replaced with <tt>&amp;</tt>.
- - <tt><</tt> is replaced with <tt>&lt;</tt>.
- - <tt>></tt> is replaced with <tt>&gt;</tt>.
-
- Examples:
-
- s = 'foo"<&>"bar' + "\u3042"
- s.encode('ASCII', xml: :text) # => "foo\"&lt;&amp;&gt;\"bar&#x3042;"
- s.encode('ASCII', xml: :attr) # => "\"foo&quot;&lt;&amp;&gt;&quot;bar&#x3042;\""
-
-
-- Newlines:
-
- One of these may be specified:
-
- - <tt>:cr_newline: true</tt>: Replace each line-feed character (<tt>"\n"</tt>)
- with a carriage-return character (<tt>"\r"</tt>).
- - <tt>:crlf_newline: true</tt>: Replace each line-feed character (<tt>"\n"</tt>)
- with a carriage-return/line-feed string (<tt>"\r\n"</tt>).
- - <tt>:universal_newline: true</tt>: Replace each carriage-return
- character (<tt>"\r"</tt>) and each carriage-return/line-feed string
- (<tt>"\r\n"</tt>) with a line-feed character (<tt>"\n"</tt>).
-
- Examples:
-
- s = "\n \r \r\n" # => "\n \r \r\n"
- s.encode('ASCII', cr_newline: true) # => "\r \r \r\r"
- s.encode('ASCII', crlf_newline: true) # => "\r\n \r \r\r\n"
- s.encode('ASCII', universal_newline: true) # => "\n \n \n"
diff --git a/doc/examples/files.rdoc b/doc/examples/files.rdoc
index f736132770..cb400c81be 100644
--- a/doc/examples/files.rdoc
+++ b/doc/examples/files.rdoc
@@ -7,8 +7,8 @@ text = <<~EOT
Fifth line
EOT
-# Russian text.
-russian = "\u{442 435 441 442}" # => "тест"
+# Japanese text.
+japanese = 'こんにちは'
# Binary data.
data = "\u9990\u9991\u9992\u9993\u9994"
@@ -16,8 +16,8 @@ data = "\u9990\u9991\u9992\u9993\u9994"
# Text file.
File.write('t.txt', text)
-# File with Russian text.
-File.write('t.rus', russian)
+# File with Japanese text.
+File.write('t.ja', japanese)
# File with binary data.
f = File.new('t.dat', 'wb:UTF-16')
diff --git a/doc/extension.ja.rdoc b/doc/extension.ja.rdoc
index 2f7856f3d4..381b94a230 100644
--- a/doc/extension.ja.rdoc
+++ b/doc/extension.ja.rdoc
@@ -1,5 +1,7 @@
# extension.ja.rdoc - -*- RDoc -*- created at: Mon Aug 7 16:45:54 JST 1995
+{English}[rdoc-ref:extension.rdoc]
+
= Rubyの拡張ライブラリの作り方
Rubyの拡張ライブラリの作り方を説明します.
diff --git a/doc/extension.rdoc b/doc/extension.rdoc
index ba59d107ab..18dc5817d4 100644
--- a/doc/extension.rdoc
+++ b/doc/extension.rdoc
@@ -1,5 +1,7 @@
# extension.rdoc - -*- RDoc -*- created at: Mon Aug 7 16:45:54 JST 1995
+{日本語}[rdoc-ref:extension.ja.rdoc]
+
= Creating extension libraries for Ruby
This document explains how to make extension libraries for Ruby.
@@ -2047,7 +2049,7 @@ the <code>*_kw</code> 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)
+ #define rb_eval_cmd_kw(c, a, kw) rb_eval_cmd(c, a, 0)
#endif
== Appendix C. Functions available for use in extconf.rb
diff --git a/doc/fiber.md b/doc/fiber.md
deleted file mode 100644
index a334faf739..0000000000
--- a/doc/fiber.md
+++ /dev/null
@@ -1,232 +0,0 @@
-# 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/doc/float.rb b/doc/float.rb
new file mode 100644
index 0000000000..01668bfc6d
--- /dev/null
+++ b/doc/float.rb
@@ -0,0 +1,128 @@
+# A \Float object stores a real number
+# using the native architecture's double-precision floating-point representation.
+#
+# == \Float Imprecisions
+#
+# Some real numbers can be represented precisely as \Float objects:
+#
+# 37.5 # => 37.5
+# 98.75 # => 98.75
+# 12.3125 # => 12.3125
+#
+# Others cannot; among these are the transcendental numbers, including:
+#
+# - Pi, <i>π</i>: in mathematics, a number of infinite precision:
+# 3.1415926535897932384626433... (to 25 places);
+# in Ruby, it is of limited precision (in this case, to 16 decimal places):
+#
+# Math::PI # => 3.141592653589793
+#
+# - Euler's number, <i>e</i>: in mathematics, a number of infinite precision:
+# 2.7182818284590452353602874... (to 25 places);
+# in Ruby, it is of limited precision (in this case, to 15 decimal places):
+#
+# Math::E # => 2.718281828459045
+#
+# Some floating-point computations in Ruby give precise results:
+#
+# 1.0/2 # => 0.5
+# 100.0/8 # => 12.5
+#
+# Others do not:
+#
+# - In mathematics, 2/3 as a decimal number is an infinitely-repeating decimal:
+# 0.666... (forever);
+# in Ruby, +2.0/3+ is of limited precision (in this case, to 16 decimal places):
+#
+# 2.0/3 # => 0.6666666666666666
+#
+# - In mathematics, the square root of 2 is an irrational number of infinite precision:
+# 1.4142135623730950488016887... (to 25 decimal places);
+# in Ruby, it is of limited precision (in this case, to 16 decimal places):
+#
+# Math.sqrt(2.0) # => 1.4142135623730951
+#
+# - Even a simple computation can introduce imprecision:
+#
+# x = 0.1 + 0.2 # => 0.30000000000000004
+# y = 0.3 # => 0.3
+# x == y # => false
+#
+# See:
+#
+# - https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
+# - https://github.com/rdp/ruby_tutorials_core/wiki/Ruby-Talk-FAQ#-why-are-rubys-floats-imprecise
+# - https://en.wikipedia.org/wiki/Floating_point#Accuracy_problems
+#
+# Note that precise storage and computation of rational numbers
+# is possible using Rational objects.
+#
+# == Creating a \Float
+#
+# You can create a \Float object explicitly with:
+#
+# - A {floating-point literal}[rdoc-ref:syntax/literals.rdoc@Float+Literals].
+#
+# You can convert certain objects to Floats with:
+#
+# - Method #Float.
+#
+# == What's Here
+#
+# First, what's elsewhere. Class \Float:
+#
+# - Inherits from
+# {class Numeric}[rdoc-ref:Numeric@What-27s+Here]
+# and {class Object}[rdoc-ref:Object@What-27s+Here].
+# - Includes {module Comparable}[rdoc-ref:Comparable@What-27s+Here].
+#
+# Here, class \Float provides methods for:
+#
+# - {Querying}[rdoc-ref:Float@Querying]
+# - {Comparing}[rdoc-ref:Float@Comparing]
+# - {Converting}[rdoc-ref:Float@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
+#
+# - #<: Returns whether +self+ is less than the given value.
+# - #<=: Returns whether +self+ is less than or equal to the given value.
+# - #<=>: Returns a number indicating whether +self+ is less than, equal
+# to, or greater than the given value.
+# - #== (aliased as #=== and #eql?): Returns whether +self+ is equal to
+# the given value.
+# - #>: Returns whether +self+ is greater than the given value.
+# - #>=: 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.
+# - #**: 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.
+# - #/: 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.
+#
+
+ class Float; end
diff --git a/doc/format_specifications.rdoc b/doc/format_specifications.rdoc
deleted file mode 100644
index 1111575e74..0000000000
--- a/doc/format_specifications.rdoc
+++ /dev/null
@@ -1,348 +0,0 @@
-= Format Specifications
-
-Several Ruby core classes have instance method +printf+ or +sprintf+:
-
-- ARGF#printf
-- IO#printf
-- Kernel#printf
-- Kernel#sprintf
-
-Each of these methods takes:
-
-- Argument +format_string+, which has zero or more
- embedded _format_ _specifications_ (see below).
-- Arguments <tt>*arguments</tt>, which are zero or more objects to be formatted.
-
-Each of these methods prints or returns the string
-resulting from replacing each
-format specification embedded in +format_string+ with a string form
-of the corresponding argument among +arguments+.
-
-A simple example:
-
- sprintf('Name: %s; value: %d', 'Foo', 0) # => "Name: Foo; value: 0"
-
-A format specification has the form:
-
- %[flags][width][.precision]type
-
-It consists of:
-
-- A leading percent character.
-- Zero or more _flags_ (each is a character).
-- An optional _width_ _specifier_ (an integer).
-- An optional _precision_ _specifier_ (a period followed by a non-negative integer).
-- A _type_ _specifier_ (a character).
-
-Except for the leading percent character,
-the only required part is the type specifier, so we begin with that.
-
-== Type Specifiers
-
-This section provides a brief explanation of each type specifier.
-The links lead to the details and examples.
-
-=== \Integer Type Specifiers
-
-- +b+ or +B+: Format +argument+ as a binary integer.
- See {Specifiers b and B}[rdoc-ref:format_specifications.rdoc@Specifiers+b+and+B].
-- +d+, +i+, or +u+ (all are identical):
- Format +argument+ as a decimal integer.
- See {Specifier d}[rdoc-ref:format_specifications.rdoc@Specifier+d].
-- +o+: Format +argument+ as an octal integer.
- See {Specifier o}[rdoc-ref:format_specifications.rdoc@Specifier+o].
-- +x+ or +X+: Format +argument+ as a hexadecimal integer.
- See {Specifiers x and X}[rdoc-ref:format_specifications.rdoc@Specifiers+x+and+X].
-
-=== Floating-Point Type Specifiers
-
-- +a+ or +A+: Format +argument+ as hexadecimal floating-point number.
- See {Specifiers a and A}[rdoc-ref:format_specifications.rdoc@Specifiers+a+and+A].
-- +e+ or +E+: Format +argument+ in scientific notation.
- See {Specifiers e and E}[rdoc-ref:format_specifications.rdoc@Specifiers+e+and+E].
-- +f+: Format +argument+ as a decimal floating-point number.
- See {Specifier f}[rdoc-ref:format_specifications.rdoc@Specifier+f].
-- +g+ or +G+: Format +argument+ in a "general" format.
- See {Specifiers g and G}[rdoc-ref:format_specifications.rdoc@Specifiers+g+and+G].
-
-=== Other Type Specifiers
-
-- +c+: Format +argument+ as a character.
- See {Specifier c}[rdoc-ref:format_specifications.rdoc@Specifier+c].
-- +p+: Format +argument+ as a string via <tt>argument.inspect</tt>.
- See {Specifier p}[rdoc-ref:format_specifications.rdoc@Specifier+p].
-- +s+: Format +argument+ as a string via <tt>argument.to_s</tt>.
- See {Specifier s}[rdoc-ref:format_specifications.rdoc@Specifier+s].
-- <tt>%</tt>: Format +argument+ (<tt>'%'</tt>) as a single percent character.
- See {Specifier %}[rdoc-ref:format_specifications.rdoc@Specifier+-25].
-
-== Flags
-
-The effect of a flag may vary greatly among type specifiers.
-These remarks are general in nature.
-See {type-specific details}[rdoc-ref:format_specifications.rdoc@Type+Specifier+Details+and+Examples].
-
-Multiple flags may be given with single type specifier;
-order does not matter.
-
-=== <tt>' '</tt> Flag
-
-Insert a space before a non-negative number:
-
- sprintf('%d', 10) # => "10"
- sprintf('% d', 10) # => " 10"
-
-Insert a minus sign for negative value:
-
- sprintf('%d', -10) # => "-10"
- sprintf('% d', -10) # => "-10"
-
-=== <tt>'#'</tt> Flag
-
-Use an alternate format; varies among types:
-
- sprintf('%x', 100) # => "64"
- sprintf('%#x', 100) # => "0x64"
-
-=== <tt>'+'</tt> Flag
-
-Add a leading plus sign for a non-negative number:
-
- sprintf('%x', 100) # => "64"
- sprintf('%+x', 100) # => "+64"
-
-=== <tt>'-'</tt> Flag
-
-Left justify the value in its field:
-
- sprintf('%6d', 100) # => " 100"
- sprintf('%-6d', 100) # => "100 "
-
-=== <tt>'0'</tt> Flag
-
-Left-pad with zeros instead of spaces:
-
- sprintf('%6d', 100) # => " 100"
- sprintf('%06d', 100) # => "000100"
-
-=== <tt>'*'</tt> Flag
-
-Use the next argument as the field width:
-
- sprintf('%d', 20, 14) # => "20"
- sprintf('%*d', 20, 14) # => " 14"
-
-=== <tt>'n$'</tt> Flag
-
-Format the (1-based) <tt>n</tt>th argument into this field:
-
- sprintf("%s %s", 'world', 'hello') # => "world hello"
- sprintf("%2$s %1$s", 'world', 'hello') # => "hello world"
-
-== Width Specifier
-
-In general, a width specifier determines the minimum width (in characters)
-of the formatted field:
-
- sprintf('%10d', 100) # => " 100"
-
- # Left-justify if negative.
- sprintf('%-10d', 100) # => "100 "
-
- # Ignore if too small.
- sprintf('%1d', 100) # => "100"
-
-== Precision Specifier
-
-A precision specifier is a decimal point followed by zero or more
-decimal digits.
-
-For integer type specifiers, the precision specifies the minimum number of
-digits to be written. If the precision is shorter than the integer, the result is
-padded with leading zeros. There is no modification or truncation of the result
-if the integer is longer than the precision:
-
- sprintf('%.3d', 1) # => "001"
- sprintf('%.3d', 1000) # => "1000"
-
- # If the precision is 0 and the value is 0, nothing is written
- sprintf('%.d', 0) # => ""
- sprintf('%.0d', 0) # => ""
-
-For the +a+/+A+, +e+/+E+, +f+/+F+ specifiers, the precision specifies
-the number of digits after the decimal point to be written:
-
- sprintf('%.2f', 3.14159) # => "3.14"
- sprintf('%.10f', 3.14159) # => "3.1415900000"
-
- # With no precision specifier, defaults to 6-digit precision.
- sprintf('%f', 3.14159) # => "3.141590"
-
-For the +g+/+G+ specifiers, the precision specifies
-the number of significant digits to be written:
-
- sprintf('%.2g', 123.45) # => "1.2e+02"
- sprintf('%.3g', 123.45) # => "123"
- sprintf('%.10g', 123.45) # => "123.45"
-
- # With no precision specifier, defaults to 6 significant digits.
- sprintf('%g', 123.456789) # => "123.457"
-
-For the +s+, +p+ specifiers, the precision specifies
-the number of characters to write:
-
- sprintf('%s', Time.now) # => "2022-05-04 11:59:16 -0400"
- sprintf('%.10s', Time.now) # => "2022-05-04"
-
-== Type Specifier Details and Examples
-
-=== Specifiers +a+ and +A+
-
-Format +argument+ as hexadecimal floating-point number:
-
- sprintf('%a', 3.14159) # => "0x1.921f9f01b866ep+1"
- sprintf('%a', -3.14159) # => "-0x1.921f9f01b866ep+1"
- sprintf('%a', 4096) # => "0x1p+12"
- sprintf('%a', -4096) # => "-0x1p+12"
-
- # Capital 'A' means that alphabetical characters are printed in upper case.
- sprintf('%A', 4096) # => "0X1P+12"
- sprintf('%A', -4096) # => "-0X1P+12"
-
-=== Specifiers +b+ and +B+
-
-The two specifiers +b+ and +B+ behave identically
-except when flag <tt>'#'</tt>+ is used.
-
-Format +argument+ as a binary integer:
-
- sprintf('%b', 1) # => "1"
- sprintf('%b', 4) # => "100"
-
- # Prefix '..' for negative value.
- sprintf('%b', -4) # => "..100"
-
- # Alternate format.
- sprintf('%#b', 4) # => "0b100"
- sprintf('%#B', 4) # => "0B100"
-
-=== Specifier +c+
-
-Format +argument+ as a single character:
-
- sprintf('%c', 'A') # => "A"
- sprintf('%c', 65) # => "A"
-
-=== Specifier +d+
-
-Format +argument+ as a decimal integer:
-
- sprintf('%d', 100) # => "100"
- sprintf('%d', -100) # => "-100"
-
-Flag <tt>'#'</tt> does not apply.
-
-=== Specifiers +e+ and +E+
-
-Format +argument+ in
-{scientific notation}[https://en.wikipedia.org/wiki/Scientific_notation]:
-
- sprintf('%e', 3.14159) # => "3.141590e+00"
- sprintf('%E', -3.14159) # => "-3.141590E+00"
-
-=== Specifier +f+
-
-Format +argument+ as a floating-point number:
-
- sprintf('%f', 3.14159) # => "3.141590"
- sprintf('%f', -3.14159) # => "-3.141590"
-
-Flag <tt>'#'</tt> does not apply.
-
-=== Specifiers +g+ and +G+
-
-Format +argument+ using exponential form (+e+/+E+ specifier)
-if the exponent is less than -4 or greater than or equal to the precision.
-Otherwise format +argument+ using floating-point form (+f+ specifier):
-
- sprintf('%g', 100) # => "100"
- sprintf('%g', 100.0) # => "100"
- sprintf('%g', 3.14159) # => "3.14159"
- sprintf('%g', 100000000000) # => "1e+11"
- sprintf('%g', 0.000000000001) # => "1e-12"
-
- # Capital 'G' means use capital 'E'.
- sprintf('%G', 100000000000) # => "1E+11"
- sprintf('%G', 0.000000000001) # => "1E-12"
-
- # Alternate format.
- sprintf('%#g', 100000000000) # => "1.00000e+11"
- sprintf('%#g', 0.000000000001) # => "1.00000e-12"
- sprintf('%#G', 100000000000) # => "1.00000E+11"
- sprintf('%#G', 0.000000000001) # => "1.00000E-12"
-
-=== Specifier +o+
-
-Format +argument+ as an octal integer.
-If +argument+ is negative, it will be formatted as a two's complement
-prefixed with +..7+:
-
- sprintf('%o', 16) # => "20"
-
- # Prefix '..7' for negative value.
- sprintf('%o', -16) # => "..760"
-
- # Prefix zero for alternate format if positive.
- sprintf('%#o', 16) # => "020"
- sprintf('%#o', -16) # => "..760"
-
-=== Specifier +p+
-
-Format +argument+ as a string via <tt>argument.inspect</tt>:
-
- t = Time.now
- sprintf('%p', t) # => "2022-05-01 13:42:07.1645683 -0500"
-
-=== Specifier +s+
-
-Format +argument+ as a string via <tt>argument.to_s</tt>:
-
- t = Time.now
- sprintf('%s', t) # => "2022-05-01 13:42:07 -0500"
-
-Flag <tt>'#'</tt> does not apply.
-
-=== Specifiers +x+ and +X+
-
-Format +argument+ as a hexadecimal integer.
-If +argument+ is negative, it will be formatted as a two's complement
-prefixed with +..f+:
-
- sprintf('%x', 100) # => "64"
-
- # Prefix '..f' for negative value.
- sprintf('%x', -100) # => "..f9c"
-
- # Use alternate format.
- sprintf('%#x', 100) # => "0x64"
-
- # Alternate format for negative value.
- sprintf('%#x', -100) # => "0x..f9c"
-
-=== Specifier <tt>%</tt>
-
-Format +argument+ (<tt>'%'</tt>) as a single percent character:
-
- sprintf('%d %%', 100) # => "100 %"
-
-Flags do not apply.
-
-== Reference by Name
-
-For more complex formatting, Ruby supports a reference by name.
-%<name>s style uses format style, but %{name} style doesn't.
-
-Examples:
-
- sprintf("%<foo>d : %<bar>f", { :foo => 1, :bar => 2 }) # => 1 : 2.000000
- sprintf("%{foo}f", { :foo => 1 }) # => "1f"
diff --git a/doc/forwardable.rd.ja b/doc/forwardable.rd.ja
index 171724b2e5..53e8202513 100644
--- a/doc/forwardable.rd.ja
+++ b/doc/forwardable.rd.ja
@@ -1,4 +1,4 @@
- -- forwatable.rb
+ -- forwardable.rb
$Release Version: 1.1 $
$Revision$
diff --git a/doc/globals.rdoc b/doc/globals.rdoc
deleted file mode 100644
index 1b51bb1b36..0000000000
--- a/doc/globals.rdoc
+++ /dev/null
@@ -1,422 +0,0 @@
-= Pre-Defined Global Variables
-
-Some of the pre-defined global variables have synonyms
-that are available via module English.
-For each of those, the \English synonym is given.
-
-To use the module:
-
- require 'English'
-
-== Exceptions
-
-=== <tt>$!</tt> (\Exception)
-
-Contains the Exception object set by Kernel#raise:
-
- begin
- raise RuntimeError.new('Boo!')
- rescue RuntimeError
- p $!
- end
-
-Output:
-
- #<RuntimeError: Boo!>
-
-English - <tt>$ERROR_INFO</tt>
-
-=== <tt>$@</tt> (Backtrace)
-
-Same as <tt>$!.backtrace</tt>;
-returns an array of backtrace positions:
-
- begin
- raise RuntimeError.new('Boo!')
- rescue RuntimeError
- pp $@.take(4)
- end
-
-Output:
-
- ["(irb):338:in `<top (required)>'",
- "/snap/ruby/317/lib/ruby/3.2.0/irb/workspace.rb:119:in `eval'",
- "/snap/ruby/317/lib/ruby/3.2.0/irb/workspace.rb:119:in `evaluate'",
- "/snap/ruby/317/lib/ruby/3.2.0/irb/context.rb:502:in `evaluate'"]
-
-English - <tt>$ERROR_POSITION</tt>.
-
-== Pattern Matching
-
-These global variables store information about the most recent
-successful match in the current scope.
-
-For details and examples,
-see {Regexp Global Variables}[rdoc-ref:Regexp@Global+Variables].
-
-=== <tt>$~</tt> (\MatchData)
-
-MatchData object created from the match;
-thread-local and frame-local.
-
-English - <tt>$LAST_MATCH_INFO</tt>.
-
-=== <tt>$&</tt> (Matched Substring)
-
-The matched string.
-
-English - <tt>$MATCH</tt>.
-
-=== <tt>$`</tt> (Pre-Match Substring)
-
-The string to the left of the match.
-
-English - <tt>$PREMATCH</tt>.
-
-=== <tt>$'</tt> (Post-Match Substring)
-
-The string to the right of the match.
-
-English - <tt>$POSTMATCH</tt>.
-
-=== <tt>$+</tt> (Last Matched Group)
-
-The last group matched.
-
-English - <tt>$LAST_PAREN_MATCH</tt>.
-
-=== <tt>$1</tt>, <tt>$2</tt>, \Etc. (Matched Group)
-
-For <tt>$_n_</tt> the _nth_ group of the match.
-
-No \English.
-
-== Separators
-
-=== <tt>$/</tt> (Input Record Separator)
-
-An input record separator, initially newline.
-
-English - <tt>$INPUT_RECORD_SEPARATOR</tt>, <tt>$RS</tt>.
-
-Aliased as <tt>$-0</tt>.
-
-=== <tt>$;</tt> (Input Field Separator)
-
-An input field separator, initially +nil+.
-
-English - <tt>$FIELD_SEPARATOR</tt>, <tt>$FS</tt>.
-
-Aliased as <tt>$-F</tt>.
-
-=== <tt>$\\</tt> (Output Record Separator)
-
-An output record separator, initially +nil+.
-
-English - <tt>$OUTPUT_RECORD_SEPARATOR</tt>, <tt>$ORS</tt>.
-
-== Streams
-
-=== <tt>$stdin</tt> (Standard Input)
-
-The current standard input stream; initially:
-
- $stdin # => #<IO:<STDIN>>
-
-=== <tt>$stdout</tt> (Standard Output)
-
-The current standard output stream; initially:
-
- $stdout # => #<IO:<STDOUT>>
-
-=== <tt>$stderr</tt> (Standard Error)
-
-The current standard error stream; initially:
-
- $stderr # => #<IO:<STDERR>>
-
-=== <tt>$<</tt> (\ARGF or $stdin)
-
-Points to stream ARGF if not empty, else to stream $stdin; read-only.
-
-English - <tt>$DEFAULT_INPUT</tt>.
-
-=== <tt>$></tt> (Default Standard Output)
-
-An output stream, initially <tt>$stdout</tt>.
-
-English - <tt>$DEFAULT_OUTPUT
-
-=== <tt>$.</tt> (Input Position)
-
-The input position (line number) in the most recently read stream.
-
-English - <tt>$INPUT_LINE_NUMBER</tt>, <tt>$NR</tt>
-
-=== <tt>$_</tt> (Last Read Line)
-
-The line (string) from the most recently read stream.
-
-English - <tt>$LAST_READ_LINE</tt>.
-
-== Processes
-
-=== <tt>$0</tt>
-
-Initially, contains the name of the script being executed;
-may be reassigned.
-
-=== <tt>$*</tt> (\ARGV)
-
-Points to ARGV.
-
-English - <tt>$ARGV</tt>.
-
-=== <tt>$$</tt> (Process ID)
-
-The process ID of the current process. Same as Process.pid.
-
-English - <tt>$PROCESS_ID</tt>, <tt>$PID</tt>.
-
-=== <tt>$?</tt> (Child Status)
-
-Initially +nil+, otherwise the Process::Status object
-created for the most-recently exited child process;
-thread-local.
-
-English - <tt>$CHILD_STATUS</tt>.
-
-=== <tt>$LOAD_PATH</tt> (Load Path)
-
-Contains the array of paths to be searched
-by Kernel#load and Kernel#require.
-
-Singleton method <tt>$LOAD_PATH.resolve_feature_path(feature)</tt>
-returns:
-
-- <tt>[:rb, _path_]</tt>, where +path+ is the path to the Ruby file
- to be loaded for the given +feature+.
-- <tt>[:so+ _path_]</tt>, where +path+ is the path to the shared object file
- to be loaded for the given +feature+.
-- +nil+ if there is no such +feature+ and +path+.
-
-Examples:
-
- $LOAD_PATH.resolve_feature_path('timeout')
- # => [:rb, "/snap/ruby/317/lib/ruby/3.2.0/timeout.rb"]
- $LOAD_PATH.resolve_feature_path('date_core')
- # => [:so, "/snap/ruby/317/lib/ruby/3.2.0/x86_64-linux/date_core.so"]
- $LOAD_PATH.resolve_feature_path('foo')
- # => nil
-
-Aliased as <tt>$:</tt> and <tt>$-I</tt>.
-
-=== <tt>$LOADED_FEATURES</tt>
-
-Contains an array of the paths to the loaded files:
-
- $LOADED_FEATURES.take(10)
- # =>
- ["enumerator.so",
- "thread.rb",
- "fiber.so",
- "rational.so",
- "complex.so",
- "ruby2_keywords.rb",
- "/snap/ruby/317/lib/ruby/3.2.0/x86_64-linux/enc/encdb.so",
- "/snap/ruby/317/lib/ruby/3.2.0/x86_64-linux/enc/trans/transdb.so",
- "/snap/ruby/317/lib/ruby/3.2.0/x86_64-linux/rbconfig.rb",
- "/snap/ruby/317/lib/ruby/3.2.0/rubygems/compatibility.rb"]
-
-Aliased as <tt>$"</tt>.
-
-== Debugging
-
-=== <tt>$FILENAME</tt>
-
-The value returned by method ARGF.filename.
-
-=== <tt>$DEBUG</tt>
-
-Initially +true+ if command-line option <tt>-d</tt> or <tt>--debug</tt> is given,
-otherwise initially +false+;
-may be set to either value in the running program.
-
-When +true+, prints each raised exception to <tt>$stderr</tt>.
-
-Aliased as <tt>$-d</tt>.
-
-=== <tt>$VERBOSE</tt>
-
-Initially +true+ if command-line option <tt>-v</tt> or <tt>-w</tt> is given,
-otherwise initially +false+;
-may be set to either value, or to +nil+, in the running program.
-
-When +true+, enables Ruby warnings.
-
-When +nil+, disables warnings, including those from Kernel#warn.
-
-Aliased as <tt>$-v</tt> and <tt>$-w</tt>.
-
-== Other Variables
-
-=== <tt>$-a</tt>
-
-Whether command-line option <tt>-a</tt> was given; read-only.
-
-=== <tt>$-i</tt>
-
-Contains the extension given with command-line option <tt>-i</tt>,
-or +nil+ if none.
-
-An alias of ARGF.inplace_mode.
-
-=== <tt>$-l</tt>
-
-Whether command-line option <tt>-l</tt> was set; read-only.
-
-=== <tt>$-p</tt>
-
-Whether command-line option <tt>-p</tt> was given; read-only.
-
-== Deprecated
-
-=== <tt>$=</tt>
-
-=== <tt>$,</tt>
-
-= Pre-Defined Global Constants
-
-= Streams
-
-=== <tt>STDIN</tt>
-
-The standard input stream (the default value for <tt>$stdin</tt>):
-
- STDIN # => #<IO:<STDIN>>
-
-=== <tt>STDOUT</tt>
-
-The standard output stream (the default value for <tt>$stdout</tt>):
-
- STDOUT # => #<IO:<STDOUT>>
-
-=== <tt>STDERR</tt>
-
-The standard error stream (the default value for <tt>$stderr</tt>):
-
- STDERR # => #<IO:<STDERR>>
-
-== Environment
-
-=== ENV
-
-A hash of the contains current environment variables names and values:
-
- ENV.take(5)
- # =>
- [["COLORTERM", "truecolor"],
- ["DBUS_SESSION_BUS_ADDRESS", "unix:path=/run/user/1000/bus"],
- ["DESKTOP_SESSION", "ubuntu"],
- ["DISPLAY", ":0"],
- ["GDMSESSION", "ubuntu"]]
-
-=== ARGF
-
-The virtual concatenation of the files given on the command line, or from
-<tt>$stdin</tt> if no files were given, <tt>"-"</tt> is given, or after
-all files have been read.
-
-=== <tt>ARGV</tt>
-
-An array of the given command-line arguments.
-
-=== <tt>TOPLEVEL_BINDING</tt>
-
-The Binding of the top level scope:
-
- TOPLEVEL_BINDING # => #<Binding:0x00007f58da0da7c0>
-
-=== <tt>RUBY_VERSION</tt>
-
-The Ruby version:
-
- RUBY_VERSION # => "3.2.2"
-
-=== <tt>RUBY_RELEASE_DATE</tt>
-
-The release date string:
-
- RUBY_RELEASE_DATE # => "2023-03-30"
-
-=== <tt>RUBY_PLATFORM</tt>
-
-The platform identifier:
-
- RUBY_PLATFORM # => "x86_64-linux"
-
-=== <tt>RUBY_PATCHLEVEL</tt>
-
-The integer patch level for this Ruby:
-
- RUBY_PATCHLEVEL # => 53
-
-For a development build the patch level will be -1.
-
-=== <tt>RUBY_REVISION</tt>
-
-The git commit hash for this Ruby:
-
- RUBY_REVISION # => "e51014f9c05aa65cbf203442d37fef7c12390015"
-
-=== <tt>RUBY_COPYRIGHT</tt>
-
-The copyright string:
-
- RUBY_COPYRIGHT
- # => "ruby - Copyright (C) 1993-2023 Yukihiro Matsumoto"
-
-=== <tt>RUBY_ENGINE</tt>
-
-The name of the Ruby implementation:
-
- RUBY_ENGINE # => "ruby"
-
-=== <tt>RUBY_ENGINE_VERSION</tt>
-
-The version of the Ruby implementation:
-
- RUBY_ENGINE_VERSION # => "3.2.2"
-
-=== <tt>RUBY_DESCRIPTION</tt>
-
-The description of the Ruby implementation:
-
- RUBY_DESCRIPTION
- # => "ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-linux]"
-
-== Embedded \Data
-
-=== <tt>DATA</tt>
-
-Defined if and only if the program has this line:
-
- __END__
-
-When defined, <tt>DATA</tt> is a File object
-containing the lines following the <tt>__END__</tt>,
-positioned at the first of those lines:
-
- p DATA
- DATA.each_line { |line| p line }
- __END__
- Foo
- Bar
- Baz
-
-Output:
-
- #<File:t.rb>
- "Foo\n"
- "Bar\n"
- "Baz\n"
diff --git a/doc/index.md b/doc/index.md
new file mode 100644
index 0000000000..596825a19c
--- /dev/null
+++ b/doc/index.md
@@ -0,0 +1,65 @@
+# Ruby Documentation
+
+Welcome to the official Ruby programming language documentation.
+
+## Getting Started
+
+New to Ruby? Start with our [Getting Started Guide](https://www.ruby-lang.org/en/documentation/quickstart/).
+
+## Core Classes and Modules
+
+Explore the essential classes and modules:
+
+- [String](String.html) - Text manipulation and string utilities.
+- [Symbol](Symbol.html) - Named identifiers inside the Ruby interpreter.
+- [Array](Array.html) - Ordered collections of objects.
+- [Hash](Hash.html) - Key-value pairs for efficient data retrieval.
+- [Integer](Integer.html) - \Integer number class.
+- [Float](Float.html) - Floating-point number class.
+- [Enumerable](Enumerable.html) - Collection traversal and searching.
+- [File](File.html) - \File operations and handling.
+- [IO](IO.html) - Input/output functionality.
+- [Time](Time.html) - \Time representation.
+- [Regexp](Regexp.html) - Regular expressions for pattern matching.
+- [Range](Range.html) - Representing a range of values.
+- [Exception](Exception.html) - Base class for all exceptions.
+- [Thread](Thread.html) - Multithreading and concurrency.
+
+## Language Reference
+
+Deep dive into Ruby's syntax and features:
+
+- [Ruby Syntax](rdoc-ref:syntax.rdoc)
+- [Exceptions](rdoc-ref:exceptions.md)
+- [Implicit Conversions](rdoc-ref:implicit_conversion.rdoc)
+
+## Standard Libraries
+
+There are some standard libraries included in Ruby that are also commonly used, such as:
+
+- [Date](Date.html) - \Date representation.
+- [JSON](JSON.html) - \JSON encoding and decoding.
+- [ERB](ERB.html) - Embedded Ruby for templating.
+- [Net::HTTP](Net/HTTP.html) - HTTP client library.
+
+Use the following links to access the comprehensive set of libraries included with Ruby:
+
+- [Standard Library Documentation](rdoc-ref:standard_library.md)
+- [Maintainers](rdoc-ref:maintainers.md)
+
+## Contribute to Ruby
+
+Get involved with the Ruby community:
+
+- [Contribution Guide](rdoc-ref:contributing/contributing.md)
+- [Documentation Guide](rdoc-ref:contributing/documentation_guide.md)
+- [Reporting Issues](rdoc-ref:contributing/reporting_issues.md)
+- [Building Ruby](rdoc-ref:contributing/building_ruby.md)
+- [Testing Ruby](rdoc-ref:contributing/testing_ruby.md)
+- [Issue Tracker](https://bugs.ruby-lang.org/projects/ruby-master/issues)
+
+## Additional Resources
+
+- [Ruby Homepage](https://www.ruby-lang.org/)
+- [RubyGems](https://rubygems.org/)
+- [Ruby Community](https://www.ruby-lang.org/en/community/)
diff --git a/doc/irb/indexes.md b/doc/irb/indexes.md
deleted file mode 100644
index 24a67b9698..0000000000
--- a/doc/irb/indexes.md
+++ /dev/null
@@ -1,189 +0,0 @@
-## Indexes
-
-### Index of Command-Line Options
-
-These are the \IRB command-line options, with links to explanatory text:
-
-- `-d`: Set `$DEBUG` and {$VERBOSE}[rdoc-ref:IRB@Verbosity]
- to `true`.
-- `-E _ex_[:_in_]`: Set initial external (ex) and internal (in)
- {encodings}[rdoc-ref:IRB@Encodings] (same as `ruby -E>`).
-- `-f`: Don't initialize from {configuration file}[rdoc-ref:IRB@Configuration+File].
-- `-I _dirpath_`: Specify {$LOAD_PATH directory}[rdoc-ref:IRB@Load+Modules]
- (same as `ruby -I`).
-- `-r _load-module_`: Require {load-module}[rdoc-ref:IRB@Load+Modules]
- (same as `ruby -r`).
-- `-U`: Set external and internal {encodings}[rdoc-ref:IRB@Encodings] to UTF-8.
-- `-w`: Suppress {warnings}[rdoc-ref:IRB@Warnings] (same as `ruby -w`).
-- `-W[_level_]`: Set {warning level}[rdoc-ref:IRB@Warnings];
- 0=silence, 1=medium, 2=verbose (same as `ruby -W`).
-- `--autocomplete`: Use {auto-completion}[rdoc-ref:IRB@Automatic+Completion].
-- `--back-trace-limit _n_`: Set a {backtrace limit}[rdoc-ref:IRB@Tracer];
- display at most the top `n` and bottom `n` entries.
-- `--colorize`: Use {color-highlighting}[rdoc-ref:IRB@Color+Highlighting]
- for input and output.
-- `--context-mode _n_`: Select method to create Binding object
- for new {workspace}[rdoc-ref:IRB@Commands]; `n` in range `0..4`.
-- `--echo`: Print ({echo}[rdoc-ref:IRB@Return-Value+Printing+-28Echoing-29])
- return values.
-- `--extra-doc-dir _dirpath_`:
- Add a {documentation directory}[rdoc-ref:IRB@RI+Documentation+Directories]
- for the documentation dialog.
-- `--inf-ruby-mode`: Set prompt mode to {:INF_RUBY}[rdoc-ref:IRB@Pre-Defined+Prompts]
- (appropriate for `inf-ruby-mode` on Emacs);
- suppresses --multiline and --singleline.
-- `--inspect`: Use method `inspect` for printing ({echoing}[rdoc-ref:IRB@Return-Value+Printing+-28Echoing-29])
- return values.
-- `--multiline`: Use the multiline editor as the {input method}[rdoc-ref:IRB@Input+Method].
-- `--noautocomplete`: Don't use {auto-completion}[rdoc-ref:IRB@Automatic+Completion].
-- `--nocolorize`: Don't use {color-highlighting}[rdoc-ref:IRB@Color+Highlighting]
- for input and output.
-- `--noecho`: Don't print ({echo}[rdoc-ref:IRB@Return-Value+Printing+-28Echoing-29])
- return values.
-- `--noecho-on-assignment`: Don't print ({echo}[rdoc-ref:IRB@Return-Value+Printing+-28Echoing-29])
- result on assignment.
-- `--noinspect`: Don't se method `inspect` for printing ({echoing}[rdoc-ref:IRB@Return-Value+Printing+-28Echoing-29])
- return values.
-- `--nomultiline`: Don't use the multiline editor as the {input method}[rdoc-ref:IRB@Input+Method].
-- `--noprompt`: Don't print {prompts}[rdoc-ref:IRB@Prompt+and+Return+Formats].
-- `--noscript`: Treat the first command-line argument as a normal
- {command-line argument}[rdoc-ref:IRB@Initialization+Script],
- and include it in `ARGV`.
-- `--nosingleline`: Don't use the singleline editor as the {input method}[rdoc-ref:IRB@Input+Method].
-- `--noverbose`Don't print {verbose}[rdoc-ref:IRB@Verbosity] details.
-- `--prompt _mode_`, `--prompt-mode _mode_`:
- Set {prompt and return formats}[rdoc-ref:IRB@Prompt+and+Return+Formats];
- `mode` may be a {pre-defined prompt}[rdoc-ref:IRB@Pre-Defined+Prompts]
- or the name of a {custom prompt}[rdoc-ref:IRB@Custom+Prompts].
-- `--script`: Treat the first command-line argument as the path to an
- {initialization script}[rdoc-ref:IRB@Initialization+Script],
- and omit it from `ARGV`.
-- `--simple-prompt`, `--sample-book-mode`:
- Set prompt mode to {:SIMPLE}[rdoc-ref:IRB@Pre-Defined+Prompts].
-- `--singleline`: Use the singleline editor as the {input method}[rdoc-ref:IRB@Input+Method].
-- `--tracer`: Use {Tracer}[rdoc-ref:IRB@Tracer] to print a stack trace for each input command.
-- `--truncate-echo-on-assignment`: Print ({echo}[rdoc-ref:IRB@Return-Value+Printing+-28Echoing-29])
- truncated result on assignment.
-- `--verbose`Print {verbose}[rdoc-ref:IRB@Verbosity] details.
-- `-v`, `--version`: Print the {IRB version}[rdoc-ref:IRB@Version].
-- `-h`, `--help`: Print the {IRB help text}[rdoc-ref:IRB@Help].
-- `--`: Separate options from {arguments}[rdoc-ref:IRB@Command-Line+Arguments]
- on the command-line.
-
-### Index of \IRB.conf Entries
-
-These are the keys for hash \IRB.conf entries, with links to explanatory text;
-for each entry that is pre-defined, the initial value is given:
-
-- `:AP_NAME`: \IRB {application name}[rdoc-ref:IRB@Application+Name];
- initial value: `'irb'`.
-- `:AT_EXIT`: Array of hooks to call
- {at exit}[rdoc-ref:IRB@IRB];
- initial value: `[]`.
-- `:AUTO_INDENT`: Whether {automatic indentation}[rdoc-ref:IRB@Automatic+Indentation]
- is enabled; initial value: `true`.
-- `:BACK_TRACE_LIMIT`: Sets the {back trace limit}[rdoc-ref:IRB@Tracer];
- initial value: `16`.
-- `:COMMAND_ALIASES`: Defines input {command aliases}[rdoc-ref:IRB@Command+Aliases];
- initial value:
-
- {
- "$": :show_source,
- "@": :whereami,
- }
-
-- `:CONTEXT_MODE`: Sets the {context mode}[rdoc-ref:IRB@Context+Mode],
- the type of binding to be used when evaluating statements;
- initial value: `4`.
-- `:ECHO`: Whether to print ({echo}[rdoc-ref:IRB@Return-Value+Printing+-28Echoing-29])
- return values;
- initial value: `nil`, which would set `conf.echo` to `true`.
-- `:ECHO_ON_ASSIGNMENT`: Whether to print ({echo}[rdoc-ref:IRB@Return-Value+Printing+-28Echoing-29])
- return values on assignment;
- initial value: `nil`, which would set `conf.echo_on_assignment` to `:truncate`.
-- `:EVAL_HISTORY`: How much {evaluation history}[rdoc-ref:IRB@Evaluation+History]
- is to be stored; initial value: `nil`.
-- `:EXTRA_DOC_DIRS`: \Array of
- {RI documentation directories}[rdoc-ref:IRB@RI+Documentation+Directories]
- to be parsed for the documentation dialog;
- initial value: `[]`.
-- `:IGNORE_EOF`: Whether to ignore {end-of-file}[rdoc-ref:IRB@End-of-File];
- initial value: `false`.
-- `:IGNORE_SIGINT`: Whether to ignore {SIGINT}[rdoc-ref:IRB@SIGINT];
- initial value: `true`.
-- `:INSPECT_MODE`: Whether to use method `inspect` for printing
- ({echoing}[rdoc-ref:IRB@Return-Value+Printing+-28Echoing-29]) return values;
- initial value: `true`.
-- `:IRB_LIB_PATH`: The path to the {IRB library directory}[rdoc-ref:IRB@IRB+Library+Directory]; initial value:
-
- - `"<i>RUBY_DIR</i>/lib/ruby/gems/<i>RUBY_VER_NUM</i>/gems/irb-<i>IRB_VER_NUM</i>/lib/irb"`,
-
- where:
-
- - <i>RUBY_DIR</i> is the Ruby installation dirpath.
- - <i>RUBY_VER_NUM</i> is the Ruby version number.
- - <i>IRB_VER_NUM</i> is the \IRB version number.
-
-- `:IRB_NAME`: {IRB name}[rdoc-ref:IRB@IRB+Name];
- initial value: `'irb'`.
-- `:IRB_RC`: {Configuration monitor}[rdoc-ref:IRB@Configuration+Monitor];
- initial value: `nil`.
-- `:LC_MESSAGES`: {Locale}[rdoc-ref:IRB@Locale];
- initial value: IRB::Locale object.
-- `:LOAD_MODULES`: deprecated.
-- `:MAIN_CONTEXT`: The {context}[rdoc-ref:IRB@Session+Context] for the main \IRB session;
- initial value: IRB::Context object.
-- `:MEASURE`: Whether to
- {measure performance}[rdoc-ref:IRB@Performance+Measurement];
- initial value: `false`.
-- `:MEASURE_CALLBACKS`: Callback methods for
- {performance measurement}[rdoc-ref:IRB@Performance+Measurement];
- initial value: `[]`.
-- `:MEASURE_PROC`: Procs for
- {performance measurement}[rdoc-ref:IRB@Performance+Measurement];
- initial value:
-
- {
- :TIME=>#<Proc:0x0000556e271c6598 /var/lib/gems/3.0.0/gems/irb-1.8.3/lib/irb/init.rb:106>,
- :STACKPROF=>#<Proc:0x0000556e271c6548 /var/lib/gems/3.0.0/gems/irb-1.8.3/lib/irb/init.rb:116>
- }
-
-- `:PROMPT`: \Hash of {defined prompts}[rdoc-ref:IRB@Prompt+and+Return+Formats];
- initial value:
-
- {
- :NULL=>{:PROMPT_I=>nil, :PROMPT_S=>nil, :PROMPT_C=>nil, :RETURN=>"%s\n"},
- :DEFAULT=>{:PROMPT_I=>"%N(%m):%03n> ", :PROMPT_S=>"%N(%m):%03n%l ", :PROMPT_C=>"%N(%m):%03n* ", :RETURN=>"=> %s\n"},
- :CLASSIC=>{:PROMPT_I=>"%N(%m):%03n:%i> ", :PROMPT_S=>"%N(%m):%03n:%i%l ", :PROMPT_C=>"%N(%m):%03n:%i* ", :RETURN=>"%s\n"},
- :SIMPLE=>{:PROMPT_I=>">> ", :PROMPT_S=>"%l> ", :PROMPT_C=>"?> ", :RETURN=>"=> %s\n"},
- :INF_RUBY=>{:PROMPT_I=>"%N(%m):%03n> ", :PROMPT_S=>nil, :PROMPT_C=>nil, :RETURN=>"%s\n", :AUTO_INDENT=>true},
- :XMP=>{:PROMPT_I=>nil, :PROMPT_S=>nil, :PROMPT_C=>nil, :RETURN=>" ==>%s\n"}
- }
-
-- `:PROMPT_MODE`: Name of {current prompt}[rdoc-ref:IRB@Prompt+and+Return+Formats];
- initial value: `:DEFAULT`.
-- `:RC`: Whether a {configuration file}[rdoc-ref:IRB@Configuration+File]
- was found and interpreted;
- initial value: `true` if a configuration file was found, `false` otherwise.
-- `:SAVE_HISTORY`: Number of commands to save in
- {input command history}[rdoc-ref:IRB@Input+Command+History];
- initial value: `1000`.
-- `:SINGLE_IRB`: Whether command-line option `--single-irb` was given;
- initial value: `true` if the option was given, `false` otherwise.
- See {Single-IRB Mode}[rdoc-ref:IRB@Single-IRB+Mode].
-- `:USE_AUTOCOMPLETE`: Whether to use
- {automatic completion}[rdoc-ref:IRB@Automatic+Completion];
- initial value: `true`.
-- `:USE_COLORIZE`: Whether to use
- {color highlighting}[rdoc-ref:IRB@Color+Highlighting];
- initial value: `true`.
-- `:USE_LOADER`: Whether to use the
- {IRB loader}[rdoc-ref:IRB@IRB+Loader] for `require` and `load`;
- initial value: `false`.
-- `:USE_TRACER`: Whether to use the
- {IRB tracer}[rdoc-ref:IRB@Tracer];
- initial value: `false`.
-- `:VERBOSE`: Whether to print {verbose output}[rdoc-ref:IRB@Verbosity];
- initial value: `nil`.
-- `:__MAIN__`: The main \IRB object;
- initial value: `main`.
diff --git a/doc/irb/irb-tools.rd.ja b/doc/irb/irb-tools.rd.ja
deleted file mode 100644
index b997f0edea..0000000000
--- a/doc/irb/irb-tools.rd.ja
+++ /dev/null
@@ -1,184 +0,0 @@
-irb関連おまけコマンドとライブラリ
- $Release Version: 0.7.1 $
- $Revision$
- by Keiju ISHITSUKA(Nihon Rational Co.,Ltd.)
-
-=begin
-
-:コマンド:
-* rtags -- ruby tags command
-
-:関数ライブラリ:
-* xmp -- irb version of gotoken xmp-function
-
-:クラスライブラリ:
-* frame.rb -- frame tracer
-* completion.rb -- irb completor
-
-= rtags
-
-rtagsはemacs及びvi用の, TAGファイルをつくるコマンドです.
-
-== 使い方
-
- rtags [-vi] file....
-
-カレントディレクトリにemacs用のTAGSファイルができます. -viオプションを
-つけた時にはvi用のtagsファイルを作成します.
-
-emacsの場合, 通常のetags.elがそのまま使えます. 検索可能なのは,
-
-* クラス
-* メソッド
-* 特異メソッド
-* alias
-* attrで宣言されたアクセサ(パラメータがシンボルか文字列リテラルに限る)
-* attr_XXXで宣言されたアクセサ(パラメータがシンボルか文字列リテラルに限る)
-
-です.
-
-Cなどで使っているのと違うのは, コンプリーションに関する部分で,
-
-関数名は,
-
- 関数名(
-
-クラスは,
-
- ::クラス名::....::クラス名
-
-メソッドは,
-
- ::クラス名::....::クラス名#メソッド名
-
-特異メソッド(クラスメソッド)は
-
- ::クラス名::....::クラス名.メソッド名
-
-でコンプリーションを行なうところです.
-
-= xmp.rb
-
-ごとけんxmpの上位互換バージョンです. ただ, 非常に重いのでごとけんxmpで
-は対応できない時に, 使用すると良いでしょう.
-
-== 使い方
-
-=== 関数として使う.
-
- require "irb/xmp"
- xmp <<END
- foo = 1
- foo
- END
- ---
- foo = 1
- ==>1
- foo
- ==>1
-
-=== XMPインスタンスを用いる.
-
-この場合は, XMPがコンテキスト情報を持つので, 変数の値などを保持してい
-ます.
-
- require "irb/xmp"
- xmp = XMP.new
- xmp.puts <<END
- foo = 1
- foo
- END
- xmp.puts <<END
- foo
- END
- ===
- foo = 1
- ==>1
- foo
- ==>1
- foo
- ==>1
-
-== コンテキストに関して
-
-XMPメソッド群のコンテキストは, 呼び出す前のコンテキストで評価されます.
-明示的にコンテキストを指定するとそのコンテキストで評価します.
-
-例:
-
- xmp "foo", an_binding
-
-:注:
-マルチスレッドには対応していません.
-
-= frame.rb
-現在実行中のフレーム情報を取り扱うためのクラスです.
-
-* IRB::Frame.top(n = 0)
- 上からn番目のコンテキストを取り出します. nは0が最上位になります.
-* IRB::Frame.bottom(n = 0)
- 下からn番目のコンテキストを取り出します. nは0が最下位になります.
-* IRB::Frame.sender
- センダになっているオブジェクトを取り出します. センダとは, そのメソッ
- ドを呼び出した側のselfのことです.
-
-:注:
-set_trace_funcを用いてRubyの実行をトレースしています. マルチスレッドに
-は対応していません.
-
-= completion.rb
-irbのcompletion機能を提供するものです.
-
-== 使い方
-
- % irb -r irb/completion
-
-とするか, ~/.irbrc 中に
-
- require "irb/completion"
-
-を入れてください. irb実行中に require "irb/completion" してもよいです.
-
-irb実行中に (TAB) を押すとコンプレーションします.
-
-トップレベルで(TAB)を押すとすべての構文要素, クラス, メソッドの候補がで
-ます. 候補が唯一ならば完全に補完します.
-
- irb(main):001:0> in
- in inspect instance_eval
- include install_alias_method instance_of?
- initialize install_aliases instance_variables
- irb(main):001:0> inspect
- "main"
- irb(main):002:0> foo = Object.new
- #<Object:0x4027146c>
-
- ((|変数名.|))の後に(TAB)を押すと, そのオブジェクトのメソッド一覧がでま
- す.
-
- irb(main):003:0> foo.
- foo.== foo.frozen? foo.protected_methods
- foo.=== foo.hash foo.public_methods
- foo.=~ foo.id foo.respond_to?
- foo.__id__ foo.inspect foo.send
- foo.__send__ foo.instance_eval foo.singleton_methods
- foo.class foo.instance_of? foo.taint
- foo.clone foo.instance_variables foo.tainted?
- foo.display foo.is_a? foo.to_a
- foo.dup foo.kind_of? foo.to_s
- foo.eql? foo.method foo.type
- foo.equal? foo.methods foo.untaint
- foo.extend foo.nil?
- foo.freeze foo.private_methods
-
-=end
-
-% Begin Emacs Environment
-% Local Variables:
-% mode: text
-% comment-column: 0
-% comment-start: "%"
-% comment-end: "\n"
-% End:
-%
-
diff --git a/doc/irb/irb.rd.ja b/doc/irb/irb.rd.ja
deleted file mode 100644
index c51e0bd60d..0000000000
--- a/doc/irb/irb.rd.ja
+++ /dev/null
@@ -1,425 +0,0 @@
-irb -- interactive ruby
- $Release Version: 0.9.5 $
- $Revision$
- by Keiju ISHITSUKA(keiju@ruby-lang.org)
-=begin
-= irbとは?
-
-irbはinteractive rubyの略です. rubyの式を標準入力から簡単に入力/実行する
-ためのツールです.
-
-= 起動
-
- % irb
-
-で行ないます.
-
-= 使い方
-
-irbの使い方は, Rubyさえ知っていればいたって簡単です. 基本的には irb と
-いうコマンドを実行するだけです. irbを実行すると, 以下のようなプロンプ
-トが表れてきます. 後は, rubyの式を入れて下さい. 式が完結した時点で実行
-されます.
-
- dim% irb
- irb(main):001:0> 1+2
- 3
- irb(main):002:0> class Foo
- irb(main):003:1> def foo
- irb(main):004:2> print 1
- irb(main):005:2> end
- irb(main):006:1> end
- nil
- irb(main):007:0>
-
-また, irbはReadlineモジュールにも対応しています. Readlineモジュールが
-インストールされている時には, それを使うのが標準の動作になります.
-
-= コマンドオプション
-
- irb.rb [options] file_name opts
- options:
- -f ~/.irbrc を読み込まない.
- -d $DEBUG をtrueにする(ruby -d と同じ)
- -r load-module ruby -r と同じ.
- -I path $LOAD_PATH に path を追加する.
- -U ruby -U と同じ.
- -E enc ruby -E と同じ.
- -w ruby -w と同じ.
- -W[level=2] ruby -W と同じ.
- --context-mode n 新しいワークスペースを作成した時に関連する Binding
- オブジェクトの作成方法を 0 から 3 のいずれかに設定する.
- --echo 実行結果を表示する(デフォルト).
- --noecho 実行結果を表示しない.
- --echo-on-assignment
- 代入時に実行結果を表示する.
- --noecho-on-assignment
- 代入時に実行結果を表示しない.
- --truncate-echo-on-assignment
- 代入時に省略された実行結果を表示する(デフォルト).
- --inspect 結果出力にinspectを用いる.
- --noinspect 結果出力にinspectを用いない.
- --singleline シングルラインエディタを利用する.
- --nosingleline シングルラインエディタを利用しない. デフォルトの動
- 作は, inf-ruby-mode以外でシングルラインエディタを利
- 用しようとする.
- --colorize 色付けを利用する.
- --nocolorize 色付けを利用しない.
- --autocomplete オートコンプリートを利用する.
- --noautocomplete オートコンプリートを利用しない.
- --prompt prompt-mode
- --prompt-mode prompt-mode
- プロンプトモードを切替えます. 現在定義されているプ
- ロンプトモードは, default, simple, xmp, inf-rubyが
- 用意されています.
- --inf-ruby-mode emacsのinf-ruby-mode用のプロンプト表示を行なう. 特
- に指定がない限り, ラインエディタは使わなくなる.
- --simple-prompt
- 非常にシンプルなプロンプトを用いるモードです.
- --noprompt プロンプト表示を行なわない.
- --single-irb irb 中で self を実行して得られるオブジェクトをサ
- ブ irb と共有する.
- --tracer コマンド実行時にトレースを行なう.
- --back-trace-limit n
- バックトレース表示をバックトレースの頭から n, 後ろ
- からnだけ行なう. デフォルトは16
-
- --verbose 詳細なメッセージを出力する.
- --noverbose 詳細なメッセージを出力しない(デフォルト).
- -v, --version irbのバージョンを表示する.
- -h, --help irb のヘルプを表示する.
- -- 以降のコマンドライン引数をオプションとして扱わない.
-
-= コンフィギュレーション
-
-irb起動時に``~/.irbrc''を読み込みます. もし存在しない場合は,
-``.irbrc'', ``irb.rc'', ``_irbrc'', ``$irbrc''の順にloadを試みます.
-
-オプションを設定する代わりに, 以下のコマンドでもデフォルトの動作を設定
-できます.
-
- IRB.conf[:IRB_NAME]="irb"
- IRB.conf[:USE_TRACER]=false
- IRB.conf[:USE_LOADER]=false
- IRB.conf[:IGNORE_SIGINT]=true
- IRB.conf[:IGNORE_EOF]=false
- IRB.conf[:INSPECT_MODE]=nil
- IRB.conf[:IRB_RC] = nil
- IRB.conf[:BACK_TRACE_LIMIT]=16
- IRB.conf[:USE_LOADER] = false
- IRB.conf[:USE_SINGLELINE] = nil
- IRB.conf[:USE_TRACER] = false
- IRB.conf[:IGNORE_SIGINT] = true
- IRB.conf[:IGNORE_EOF] = false
- IRB.conf[:PROMPT_MODE] = :DEFAULT
- IRB.conf[:PROMPT] = {...}
- IRB.conf[:VERBOSE]=true
-
-== プロンプトの設定
-
-プロンプトをカスタマイズしたい時には,
-
- IRB.conf[:PROMPT]
-
-を用います. 例えば, .irbrcの中で下のような式を記述します:
-
- IRB.conf[:PROMPT][:MY_PROMPT] = { # プロンプトモードの名前
- :PROMPT_I => nil, # 通常のプロンプト
- :PROMPT_S => nil, # 文字列などの継続行のプロンプト
- :PROMPT_C => nil, # 式が継続している時のプロンプト
- :RETURN => " ==>%s\n" # リターン時のプロンプト
- }
-
-プロンプトモードを指定したい時には,
-
- irb --prompt my-prompt
-
-でそのプロンプトモードで起動されます. または, .irbrcに下式を記述しても
-OKです.
-
- IRB.conf[:PROMPT_MODE] = :MY_PROMPT
-
-PROMPT_I, PROMPT_S, PROMPT_Cは, フォーマットを指定します.
-
- %N 起動しているコマンド名が出力される.
- %m mainオブジェクト(self)がto_sで出力される.
- %M mainオブジェクト(self)がinspectされて出力される.
- %l 文字列中のタイプを表す(", ', /, ], `]'は%wの中の時)
- %NNi インデントのレベルを表す. NNは数字が入りprintfの%NNdと同じ. 省
- 略可能
- %NNn 行番号を表します.
- %% %
-
-例えば, デフォルトのプロンプトモードは:
-
- IRB.conf[:PROMPT][:DEFAULT] = {
- :PROMPT_I => "%N(%m):%03n:%i> ",
- :PROMPT_S => "%N(%m):%03n:%i%l ",
- :PROMPT_C => "%N(%m):%03n:%i* ",
- :RETURN => "=> %s\n"
- }
-
-となっています.
-
-RETURNは, 現在のところprintf形式です. 将来仕様が変わるかも知れません.
-
-== サブirbの設定
-
-コマンドラインオプションおよびIRB.confは(サブ)irb起動時のデフォルトの
-設定を決めるもので, `5. コマンド'にあるconfで個別の(サブ)irbの設定がで
-きるようになっています.
-
-IRB.conf[:IRB_RC]にprocが設定されていると, サブirbを起動する時にその
-procをirbのコンテキストを引数として呼び出します. これによって個別のサ
-ブirbごとに設定を変えることができるようになります.
-
-
-= コマンド
-
-irb拡張コマンドは, 簡単な名前と頭に`irb_'をつけた名前と両方定義されて
-います. これは, 簡単な名前がoverrideされた時のためです.
-
---- exit, quit, irb_exit
- 終了する.
- サブirbの場合, そのサブirbを終了する.
-
---- conf, irb_context
- irbの現在の設定を表示する. 設定の変更は, confにメッセージを送るこ
- とによって行なえる.
-
---- conf.eval_history = N
- 実行結果のヒストリ機能の設定.
- nnは整数かnilで nn>0 であればその数だけヒストリにためる。nn==0の時は
- 無制限に記憶する、nilだとヒストリ機能はやめる(デフォルト).
-
---- Conf.back_trace_limit
- バックトレース表示をバックトレースの頭からn, 後ろからnだけ行なう.
- デフォルトは16
-
---- conf.ignore_eof = true/false
- ^Dが入力された時の動作を設定する. trueの時は^Dを無視する, falseの
- 時はirbを終了する.
-
---- conf.ignore_sigint= true/false
- ^Cが入力された時の動作を設定する. false時は, irbを終了する. trueの
- 時の動作は以下のようになる:
- 入力中: これまで入力したものをキャンセルしトップレベルに戻る.
- 実行中: 実行を中止する.
-
---- conf.inf_ruby_mode = true/false
- inf-ruby-mode用のプロンプト表示を行なう. デフォルトはfalse. 特に指定
- がない限り, ラインエディタは使わなくなる.
-
---- conf.inspect_mode = true/false/nil
- インスペクトモードを設定する.
- true: インスペクトして表示する.
- false: 通常のprintで表示する.
- nil: 通常モードであれば, inspect modeとなり, mathモードの時は, non
- inspect modeとなる.
-
---- conf.use_loader = true/false
- load/require時にirbのfile読み込み機能を用いるモードのスイッチ(デフォ
- ルトは用いない). このモードはIRB全体に反映される.
-
---- conf.prompt_c
- ifの直後など, 行が継続している時のプロンプト.
-
---- conf.prompt_i
- 通常のプロンプト.
-
---- conf.prompt_s
- 文字列中などを表すプロンプト.
-
---- conf.rc
- ~/.irbrcを読み込んだかどうか?
-
---- conf.use_prompt = true/false
- プロンプト表示するかどうか? デフォルトではプロンプトを表示する.
-
---- conf.use_multiline = true/false/nil
- マルチラインエディタを使うかどうか?
- true: マルチラインエディタを使う.
- false: マルチラインエディタを使わない.
- nil: (デフォルト)inf-ruby-mode以外でマルチラインエディタを利用しよう
- とする.
-
---- conf.use_singleline = true/false/nil
- シングルラインエディタを使うかどうか?
- true: シングルラインエディタを使う.
- false: シングルラインエディタを使わない.
- nil: (デフォルト)inf-ruby-modeとマルチラインエディタ以外でシングルラ
- インエディタを利用しようとする.
-#
-#--- conf.verbose=T/F
-# irbからいろいろなメッセージを出力するか?
-
---- cws, chws, irb_cws, irb_chws, irb_change_workspace [obj]
- objをselfとする. objが省略されたときは, home workspace, すなわち
- irbを起動したときのmain objectをselfとする.
-
---- pushws, irb_pushws, irb_push_workspace [obj]
- UNIXシェルコマンドのpushdと同様.
-
---- popws, irb_popws, irb_pop_workspace
- UNIXシェルコマンドのpopdと同様.
-
---- irb [obj]
- サブirbを立ちあげる. objが指定された時は, そのobjをselfとする.
-
---- jobs, irb_jobs
- サブirbのリスト
-
---- fg n, irb_fg n
- 指定したサブirbにスイッチする. nは, 次のものを指定する.
-
- irb番号
- スレッド
- irbオブジェクト
- self(irb objで起動した時のobj)
-
---- kill n, irb_kill n
- サブirbをkillする. nはfgと同じ.
-
---- source, irb_source path
- UNIXシェルコマンドのsourceと似ている. 現在の環境上でpath内のスクリ
- プトを評価する.
-
---- irb_load path, prev
-
- Rubyのloadのirb版.
-
-= システム変数
-
---- _
- 前の計算の実行結果を覚えている(ローカル変数).
---- __
- 実行結果の履歴を覚えている.
- __[line_no]で、その行で実行した結果を得ることができる. line_noが負の
- 時には、最新の結果から-line_no前の結果を得ることができる.
-
-= 使用例
-
-以下のような感じです.
-
- dim% ruby irb.rb
- irb(main):001:0> irb # サブirbの立ちあげ
- irb#1(main):001:0> jobs # サブirbのリスト
- #0->irb on main (#<Thread:0x400fb7e4> : stop)
- #1->irb#1 on main (#<Thread:0x40125d64> : running)
- nil
- irb#1(main):002:0> fg 0 # jobのスイッチ
- nil
- irb(main):002:0> class Foo;end
- nil
- irb(main):003:0> irb Foo # Fooをコンテキストしてirb
- # 立ちあげ
- irb#2(Foo):001:0> def foo # Foo#fooの定義
- irb#2(Foo):002:1> print 1
- irb#2(Foo):003:1> end
- nil
- irb#2(Foo):004:0> fg 0 # jobをスイッチ
- nil
- irb(main):004:0> jobs # jobのリスト
- #0->irb on main (#<Thread:0x400fb7e4> : running)
- #1->irb#1 on main (#<Thread:0x40125d64> : stop)
- #2->irb#2 on Foo (#<Thread:0x4011d54c> : stop)
- nil
- irb(main):005:0> Foo.instance_methods # Foo#fooがちゃんと定義さ
- # れている
- ["foo"]
- irb(main):006:0> fg 2 # jobをスイッチ
- nil
- irb#2(Foo):005:0> def bar # Foo#barを定義
- irb#2(Foo):006:1> print "bar"
- irb#2(Foo):007:1> end
- nil
- irb#2(Foo):010:0> Foo.instance_methods
- ["bar", "foo"]
- irb#2(Foo):011:0> fg 0
- nil
- irb(main):007:0> f = Foo.new
- #<Foo:0x4010af3c>
- irb(main):008:0> irb f # Fooのインスタンスでirbを
- # 立ちあげる.
- irb#3(#<Foo:0x4010af3c>):001:0> jobs
- #0->irb on main (#<Thread:0x400fb7e4> : stop)
- #1->irb#1 on main (#<Thread:0x40125d64> : stop)
- #2->irb#2 on Foo (#<Thread:0x4011d54c> : stop)
- #3->irb#3 on #<Foo:0x4010af3c> (#<Thread:0x4010a1e0> : running)
- nil
- irb#3(#<Foo:0x4010af3c>):002:0> foo # f.fooの実行
- nil
- irb#3(#<Foo:0x4010af3c>):003:0> bar # f.barの実行
- barnil
- irb#3(#<Foo:0x4010af3c>):004:0> kill 1, 2, 3# jobのkill
- nil
- irb(main):009:0> jobs
- #0->irb on main (#<Thread:0x400fb7e4> : running)
- nil
- irb(main):010:0> exit # 終了
- dim%
-
-= 使用上の制限
-
-irbは, 評価できる時点(式が閉じた時点)での逐次実行を行ないます. したがっ
-て, rubyを直接使った時と, 若干異なる動作を行なう場合があります.
-
-現在明らかになっている問題点を説明します.
-
-== ローカル変数の宣言
-
-rubyでは, 以下のプログラムはエラーになります.
-
- eval "foo = 0"
- foo
- --
- -:2: undefined local variable or method `foo' for #<Object:0x40283118> (NameError)
- ---
- NameError
-
-ところが, irbを用いると
-
- >> eval "foo = 0"
- => 0
- >> foo
- => 0
-
-となり, エラーを起こしません. これは, rubyが最初にスクリプト全体をコン
-パイルしてローカル変数を決定するからです. それに対し, irbは実行可能に
-なる(式が閉じる)と自動的に評価しているからです. 上記の例では,
-
- eval "foo = 0"
-
-を行なった時点で評価を行ない, その時点で変数が定義されるため, 次式で
-変数fooは定義されているからです.
-
-このようなrubyとirbの動作の違いを解決したい場合は, begin...endで括って
-バッチ的に実行して下さい:
-
- >> begin
- ?> eval "foo = 0"
- >> foo
- >> end
- NameError: undefined local variable or method `foo' for #<Object:0x4013d0f0>
- (irb):3
- (irb_local_binding):1:in `eval'
-
-== ヒアドキュメント
-
-現在のところヒアドキュメントの実装は不完全です.
-
-== シンボル
-
-シンボルであるかどうかの判断を間違えることがあります. 具体的には式が完了
-しているのに継続行と見なすことがあります.
-
-=end
-
-% Begin Emacs Environment
-% Local Variables:
-% mode: text
-% comment-column: 0
-% comment-start: "%"
-% comment-end: "\n"
-% End:
-%
diff --git a/doc/jit/yjit.md b/doc/jit/yjit.md
new file mode 100644
index 0000000000..24aa163e60
--- /dev/null
+++ b/doc/jit/yjit.md
@@ -0,0 +1,544 @@
+<p align="center">
+ <a href="https://yjit.org/" target="_blank" rel="noopener noreferrer">
+ <img src="https://user-images.githubusercontent.com/224488/131155756-aa8fb528-a813-4dfd-99ac-8785c3d5eed7.png" width="400">
+ </a>
+</p>
+
+YJIT - Yet Another Ruby JIT
+===========================
+
+YJIT is a lightweight, minimalistic Ruby JIT built inside CRuby.
+It lazily compiles code using a Basic Block Versioning (BBV) architecture.
+YJIT is currently supported for macOS, Linux and BSD on x86-64 and arm64/aarch64 CPUs.
+This project is open source and falls under the same license as CRuby.
+
+<p align="center"><b>
+ If you're using YJIT in production, please
+ <a href="mailto:ruby@shopify.com">share your success stories with us!</a>
+</b></p>
+
+If you wish to learn more about the approach taken, here are some conference talks and publications:
+
+- MPLR 2023 talk: [Evaluating YJIT’s Performance in a Production Context: A Pragmatic Approach](https://www.youtube.com/watch?v=pVRmPZcNUhc)
+- RubyKaigi 2023 keynote: [Optimizing YJIT’s Performance, from Inception to Production](https://www.youtube.com/watch?v=X0JRhh8w_4I)
+- RubyKaigi 2023 keynote: [Fitting Rust YJIT into CRuby](https://www.youtube.com/watch?v=GI7vvAgP_Qs)
+- RubyKaigi 2022 keynote: [Stories from developing YJIT](https://www.youtube.com/watch?v=EMchdR9C8XM)
+- RubyKaigi 2022 talk: [Building a Lightweight IR and Backend for YJIT](https://www.youtube.com/watch?v=BbLGqTxTRp0)
+- RubyKaigi 2021 talk: [YJIT: Building a New JIT Compiler Inside CRuby](https://www.youtube.com/watch?v=PBVLf3yfMs8)
+- Blog post: [YJIT: Building a New JIT Compiler Inside CRuby](https://pointersgonewild.com/2021/06/02/yjit-building-a-new-jit-compiler-inside-cruby/)
+- MPLR 2023 paper: [Evaluating YJIT’s Performance in a Production Context: A Pragmatic Approach](https://dl.acm.org/doi/10.1145/3617651.3622982)
+- VMIL 2021 paper: [YJIT: A Basic Block Versioning JIT Compiler for CRuby](https://dl.acm.org/doi/10.1145/3486606.3486781)
+- MoreVMs 2021 talk: [YJIT: Building a New JIT Compiler Inside CRuby](https://www.youtube.com/watch?v=vucLAqv7qpc)
+- ECOOP 2016 talk: [Interprocedural Type Specialization of JavaScript Programs Without Type Analysis](https://www.youtube.com/watch?v=sRNBY7Ss97A)
+- 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 YJIT in your publications, please cite the MPLR 2023 paper:
+
+```BibTeX
+@inproceedings{yjit_mplr_2023,
+author = {Chevalier-Boisvert, Maxime and Kokubun, Takashi and Gibbs, Noah and Wu, Si Xing (Alan) and Patterson, Aaron and Issroff, Jemma},
+title = {Evaluating YJIT’s Performance in a Production Context: A Pragmatic Approach},
+year = {2023},
+isbn = {9798400703805},
+publisher = {Association for Computing Machinery},
+address = {New York, NY, USA},
+url = {https://doi.org/10.1145/3617651.3622982},
+doi = {10.1145/3617651.3622982},
+booktitle = {Proceedings of the 20th ACM SIGPLAN International Conference on Managed Programming Languages and Runtimes},
+pages = {20–33},
+numpages = {14},
+keywords = {dynamically typed, optimization, just-in-time, virtual machine, ruby, compiler, bytecode},
+location = {Cascais, Portugal},
+series = {MPLR 2023}
+}
+```
+
+## Current Limitations
+
+YJIT may not be suitable for certain applications. It currently only supports macOS, Linux and BSD on x86-64 and arm64/aarch64 CPUs. YJIT will use more memory than the Ruby interpreter because the JIT compiler needs to generate machine code in memory and maintain additional state information.
+You can change how much executable memory is allocated using [YJIT's command-line options](#command-line-options).
+
+## Installation
+
+### Requirements
+
+You will need to install:
+
+ - All the usual build tools for Ruby. See [Building Ruby](../contributing/building_ruby.md)
+ - The Rust compiler `rustc`
+ - The Rust version must be [>= 1.58.0](../../yjit/Cargo.toml).
+ - Optionally, only if you wish to build in dev/debug mode, Rust's `cargo`
+
+If you don't intend on making code changes to YJIT itself, we recommend
+obtaining `rustc` through your OS's package manager since that
+likely reuses the same vendor which provides the C toolchain.
+
+If you will be changing YJIT's Rust code, we suggest using the
+[first-party installation method][rust-install] for Rust. Rust also provides
+first class [support][editor-tools] for many source code editors.
+
+[rust-install]: https://www.rust-lang.org/tools/install
+[editor-tools]: https://www.rust-lang.org/tools
+
+### Building YJIT
+
+Start by cloning the `ruby/ruby` repository:
+
+```sh
+git clone https://github.com/ruby/ruby yjit
+cd yjit
+```
+
+The YJIT `ruby` binary can be built with either GCC or Clang. It can be built either in dev (debug) mode or in release mode. For maximum performance, compile YJIT in release mode with GCC. More detailed build instructions are provided in the [Ruby README](https://github.com/ruby/ruby#how-to-build).
+
+```sh
+# Configure in release mode for maximum performance, build and install
+./autogen.sh
+./configure --enable-yjit --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc
+make -j && make install
+```
+
+or
+
+```sh
+# Configure in lower-performance dev (debug) mode for development, build and install
+./autogen.sh
+./configure --enable-yjit=dev --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc
+make -j && make install
+```
+
+Dev mode includes extended YJIT statistics, but can be slow. For only statistics you can configure in stats mode:
+
+```sh
+# Configure in extended-stats mode without slow runtime checks, build and install
+./autogen.sh
+./configure --enable-yjit=stats --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc
+make -j && make install
+```
+
+On macOS, you may need to specify where to find some libraries:
+
+```sh
+# Install dependencies
+brew install openssl libyaml
+
+# Configure in dev (debug) mode for development, build and install
+./autogen.sh
+./configure --enable-yjit=dev --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc --with-opt-dir="$(brew --prefix openssl):$(brew --prefix readline):$(brew --prefix libyaml)"
+make -j && make install
+```
+
+Typically configure will choose the default C compiler. To specify the C compiler, use
+
+```sh
+# Choosing a specific c compiler
+export CC=/path/to/my/chosen/c/compiler
+```
+
+before running `./configure`.
+
+You can test that YJIT works correctly by running:
+
+```sh
+# Quick tests found in /bootstraptest
+make btest
+
+# Complete set of tests
+make -j 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:
+
+```sh
+chruby ruby-yjit
+ruby myscript.rb
+```
+
+You can dump statistics about compilation and execution by running YJIT with the `--yjit-stats` command-line option:
+
+```sh
+./miniruby --yjit-stats myscript.rb
+```
+
+You can see what YJIT has compiled by running YJIT with the `--yjit-log` command-line option:
+
+```sh
+./miniruby --yjit-log myscript.rb
+```
+
+The machine code generated for a given method can be printed by adding `puts RubyVM::YJIT.disasm(method(:method_name))` to a Ruby script. Note that no code will be generated if the method is not compiled.
+
+<h3 id="command-line-options">Command-Line Options</h3>
+
+YJIT supports all command-line options supported by upstream CRuby, but also adds a few YJIT-specific options:
+
+- `--yjit`: enable YJIT (disabled by default)
+- `--yjit-mem-size=N`: soft limit on YJIT memory usage in MiB (default: 128). Tries to limit `code_region_size + yjit_alloc_size`
+- `--yjit-exec-mem-size=N`: hard limit on executable memory block in MiB. Limits `code_region_size`
+- `--yjit-call-threshold=N`: number of calls after which YJIT begins to compile a function.
+ It defaults to 30, and it's then increased to 120 when the number of ISEQs in the process reaches 40,000.
+- `--yjit-cold-threshold=N`: number of global calls after which an ISEQ is considered cold and not
+ compiled, lower values mean less code is compiled (default 200K)
+- `--yjit-stats`: print statistics after the execution of a program (incurs a run-time cost)
+- `--yjit-stats=quiet`: gather statistics while running a program but don't print them. Stats are accessible through `RubyVM::YJIT.runtime_stats`. (incurs a run-time cost)
+- `--yjit-log[=file|dir]`: log all compilation events to the specified file or directory. If no name is supplied, the last 1024 log entries will be printed to stderr when the application exits.
+- `--yjit-log=quiet`: gather a circular buffer of recent YJIT compilations. The compilation log entries are accessible through `RubyVM::YJIT.log` and old entries will be discarded if the buffer is not drained quickly. (incurs a run-time cost)
+- `--yjit-disable`: disable YJIT despite other `--yjit*` flags for lazily enabling it with `RubyVM::YJIT.enable`
+- `--yjit-code-gc`: enable code GC (disabled by default as of Ruby 3.3).
+ It will cause all machine code to be discarded when the executable memory size limit is hit, meaning JIT compilation will then start over.
+ This can allow you to use a lower executable memory size limit, but may cause a slight drop in performance when the limit is hit.
+- `--yjit-perf`: enable frame pointers and profiling with the `perf` tool
+- `--yjit-trace-exits`: produce a Marshal dump of backtraces from all exits. Automatically enables `--yjit-stats`
+- `--yjit-trace-exits=COUNTER`: produce a Marshal dump of backtraces from a counted exit or a fallback. Automatically enables `--yjit-stats`
+- `--yjit-trace-exits-sample-rate=N`: trace exit locations only every Nth occurrence. Automatically enables `--yjit-trace-exits`
+
+Note that there is also an environment variable `RUBY_YJIT_ENABLE` which can be used to enable YJIT.
+This can be useful for some deployment scripts where specifying an extra command-line option to Ruby is not practical.
+
+You can also enable YJIT at run-time using `RubyVM::YJIT.enable`. This can allow you to enable YJIT after your application is done
+booting, which makes it possible to avoid compiling any initialization code.
+
+You can verify that YJIT is enabled using `RubyVM::YJIT.enabled?` or by checking that `ruby --yjit -v` includes the string `+YJIT`:
+
+```sh
+ruby --yjit -v
+ruby 3.3.0dev (2023-01-31T15:11:10Z master 2a0bf269c9) +YJIT dev [x86_64-darwin22]
+
+ruby --yjit -e "p RubyVM::YJIT.enabled?"
+true
+
+ruby -e "RubyVM::YJIT.enable; p RubyVM::YJIT.enabled?"
+true
+```
+
+### Benchmarking
+
+We have collected a set of benchmarks and implemented a simple benchmarking harness in the [yjit-bench](https://github.com/Shopify/yjit-bench) repository. This benchmarking harness is designed to disable CPU frequency scaling, set process affinity and disable address space randomization so that the variance between benchmarking runs will be as small as possible.
+
+## Performance Tips for Production Deployments
+
+While YJIT options default to what we think would work well for most workloads,
+they might not necessarily be the best configuration for your application.
+This section covers tips on improving YJIT performance in case YJIT does not
+speed up your application in production.
+
+### Increasing --yjit-mem-size
+
+The `--yjit-mem-size` value can be used to set the maximum amount of memory that YJIT
+is allowed to use. This corresponds to the total of `RubyVM::YJIT.runtime_stats[:code_region_size]`
+and `RubyVM::YJIT.runtime_stats[:yjit_alloc_size]`
+Increasing the `--yjit-mem-size` value means more code
+can be optimized by YJIT, at the cost of more memory usage.
+
+If you start Ruby with `--yjit-stats`, e.g. using an environment variable `RUBYOPT=--yjit-stats`,
+`RubyVM::YJIT.runtime_stats[:ratio_in_yjit]` shows the percentage of total YARV instructions
+executed by YJIT as opposed to the CRuby interpreter.
+Ideally, `ratio_in_yjit` should be as large as 99%, and increasing `--yjit-mem-size` often
+helps improving `ratio_in_yjit`.
+
+### Running workers as long as possible
+
+It's helpful to call the same code as many times as possible before a process restarts.
+If a process is killed too frequently, the time taken for compiling methods may outweigh
+the speedup obtained by compiling them.
+
+You should monitor the number of requests each process has served.
+If you're periodically killing worker processes, e.g. with `unicorn-worker-killer` or `puma_worker_killer`,
+you may want to reduce the killing frequency or increase the limit.
+
+## Reducing YJIT Memory Usage
+
+YJIT allocates memory for JIT code and metadata. Enabling YJIT generally results in more memory usage.
+This section goes over tips on minimizing YJIT memory usage in case it uses more than your capacity.
+
+### Decreasing --yjit-mem-size
+
+YJIT uses memory for compiled code and metadata. You can change the maximum amount of memory
+that YJIT can use by specifying a different `--yjit-mem-size` command-line option. The default value
+is currently `128`.
+When changing this value, you may want to monitor `RubyVM::YJIT.runtime_stats[:ratio_in_yjit]`
+as explained above.
+
+### Enabling YJIT lazily
+
+If you enable YJIT by `--yjit` options or `RUBY_YJIT_ENABLE=1`, YJIT may compile code that is
+used only during the application boot. `RubyVM::YJIT.enable` allows you to enable YJIT from Ruby code,
+and you can call this after your application is initialized, e.g. on Unicorn's `after_fork` hook.
+If you use any YJIT options (`--yjit-*`), YJIT will start at boot by default, but `--yjit-disable`
+allows you to start Ruby with the YJIT-disabled mode while passing YJIT tuning options.
+
+## Code Optimization Tips
+
+This section contains tips on writing Ruby code that will run as fast as possible on YJIT. Some of this advice is based on current limitations of YJIT, while other advice is broadly applicable. It probably won't be practical to apply these tips everywhere in your codebase. You should ideally start by profiling your application using a tool such as [stackprof](https://github.com/tmm1/stackprof) so that you can determine which methods make up most of the execution time. You can then refactor the specific methods that make up the largest fractions of the execution time. We do not recommend modifying your entire codebase based on the current limitations of YJIT.
+
+- Avoid using `OpenStruct`
+- Avoid redefining basic integer operations (i.e. +, -, <, >, etc.)
+- Avoid redefining the meaning of `nil`, equality, etc.
+- Avoid allocating objects in the hot parts of your code
+- Minimize layers of indirection
+ - Avoid writing wrapper classes if you can (e.g. a class that only wraps a Ruby hash)
+ - Avoid methods that just call another method
+- Ruby method calls are costly. Avoid things such as methods that only return a value from a hash
+- Try to write code so that the same variables and method arguments always have the same type
+- Avoid using `TracePoint` as it can cause YJIT to deoptimize code
+- Avoid using `binding` as it can cause YJIT to deoptimize code
+
+You can also use the `--yjit-stats` command-line option to see which bytecodes cause YJIT to exit, and refactor your code to avoid using these instructions in the hottest methods of your code.
+
+### Other Statistics
+
+If you run `ruby` with `--yjit-stats`, YJIT will track and return performance statistics in `RubyVM::YJIT.runtime_stats`.
+
+```rb
+$ RUBYOPT="--yjit-stats" irb
+irb(main):001:0> RubyVM::YJIT.runtime_stats
+=>
+{:inline_code_size=>340745,
+ :outlined_code_size=>297664,
+ :all_stats=>true,
+ :yjit_insns_count=>1547816,
+ :send_callsite_not_simple=>7267,
+ :send_kw_splat=>7,
+ :send_ivar_set_method=>72,
+...
+```
+
+Some of the counters include:
+
+* `:yjit_insns_count` - how many Ruby bytecode instructions have been executed
+* `:binding_allocations` - number of bindings allocated
+* `:binding_set` - number of variables set via a binding
+* `:code_gc_count` - number of garbage collections of compiled code since process start
+* `:vm_insns_count` - number of instructions executed by the Ruby interpreter
+* `:compiled_iseq_count` - number of bytecode sequences compiled
+* `:inline_code_size` - size in bytes of compiled YJIT blocks
+* `:outline_code_size` - size in bytes of YJIT error-handling compiled code
+* `:side_exit_count` - number of side exits taken at runtime
+* `:total_exit_count` - number of exits, including side exits, taken at runtime
+* `:avg_len_in_yjit` - avg. number of instructions in compiled blocks before exiting to interpreter
+
+Counters starting with "exit_" show reasons for YJIT code taking a side exit (return to the interpreter.)
+
+Performance counter names are not guaranteed to remain the same between Ruby versions. If you're curious what each counter means,
+it's usually best to search the source code for it &mdash; but it may change in a later Ruby version.
+
+The printed text after a `--yjit-stats` run includes other information that may be named differently than the information in `RubyVM::YJIT.runtime_stats`.
+
+## Contributing
+
+We welcome open source contributions. You should feel free to open new issues to report bugs or just to ask questions.
+Suggestions on how to make this readme file more helpful for new contributors are most welcome.
+
+Bug fixes and bug reports are very valuable to us. If you find a bug in YJIT, it's very possible be that nobody has reported it before,
+or that we don't have a good reproduction for it, so please open an issue and provide as much information as you can about your configuration and a description of how you encountered the problem. List the commands you used to run YJIT so that we can easily reproduce the issue on our end and investigate it. If you are able to produce a small program reproducing the error to help us track it down, that is very much appreciated as well.
+
+If you would like to contribute a large patch to YJIT, we suggest opening an issue or a discussion on the [Shopify/ruby repository](https://github.com/Shopify/ruby/issues) so that
+we can have an active discussion. A common problem is that sometimes people submit large pull requests to open source projects
+without prior communication, and we have to reject them because the work they implemented does not fit within the design of the
+project. We want to save you time and frustration, so please reach out so we can have a productive discussion as to how
+you can contribute patches we will want to merge into YJIT.
+
+### Source Code Organization
+
+The YJIT source code is divided between:
+
+- `yjit.c`: code YJIT uses to interface with the rest of CRuby
+- `yjit.h`: C definitions YJIT exposes to the rest of the CRuby
+- `yjit.rb`: `YJIT` Ruby module that is exposed to Ruby
+- `yjit/src/asm/*`: in-memory assembler we use to generate machine code
+- `yjit/src/codegen.rs`: logic for translating Ruby bytecode to machine code
+- `yjit/src/core.rb`: basic block versioning logic, core structure of YJIT
+- `yjit/src/stats.rs`: gathering of run-time statistics
+- `yjit/src/options.rs`: handling of command-line options
+- `yjit/src/cruby.rs`: C bindings manually exposed to the Rust codebase
+- `yjit/bindgen/src/main.rs`: C bindings exposed to the Rust codebase through bindgen
+
+The core of CRuby's interpreter logic is found in:
+
+- `insns.def`: defines Ruby's bytecode instructions (gets compiled into `vm.inc`)
+- `vm_insnshelper.c`: logic used by Ruby's bytecode instructions
+- `vm_exec.c`: Ruby interpreter loop
+
+### Generating C bindings with bindgen
+
+In order to expose C functions to the Rust codebase, you will need to generate C bindings:
+
+```sh
+CC=clang ./configure --enable-yjit=dev
+make -j yjit-bindgen
+```
+
+This uses the bindgen tools to generate/update `yjit/src/cruby_bindings.inc.rs` based on the
+bindings listed in `yjit/bindgen/src/main.rs`. Avoid manually editing this file
+as it could be automatically regenerated at a later time. If you need to manually add C bindings,
+add them to `yjit/cruby.rs` instead.
+
+### Coding & Debugging Protips
+
+There are multiple test suites:
+
+- `make btest` (see `/bootstraptest`)
+- `make test-all`
+- `make test-spec`
+- `make check` runs all of the above
+- `make yjit-check` runs quick checks to see that YJIT is working correctly
+
+The tests can be run in parallel like this:
+
+```sh
+make -j test-all RUN_OPTS="--yjit-call-threshold=1"
+```
+
+Or single-threaded like this, to more easily identify which specific test is failing:
+
+```sh
+make test-all TESTOPTS=--verbose RUN_OPTS="--yjit-call-threshold=1"
+```
+
+To run a single test file with `test-all`:
+
+```sh
+make test-all TESTS='test/-ext-/marshal/test_usrmarshal.rb' RUNRUBYOPT=--debugger=lldb RUN_OPTS="--yjit-call-threshold=1"
+```
+
+It's also possible to filter tests by name to run a single test:
+
+```sh
+make test-all TESTS='-n /test_float_plus/' RUN_OPTS="--yjit-call-threshold=1"
+```
+
+You can also run one specific test in `btest`:
+
+```sh
+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`:
+
+```sh
+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:
+
+```sh
+echo "settings set target.x86-disassembly-flavor intel" >> ~/.lldbinit
+```
+
+## Running x86 YJIT on Apple's Rosetta
+
+For development purposes, it is possible to run x86 YJIT on an Apple M1 via Rosetta. You can find basic
+instructions below, but there are a few caveats listed further down.
+
+First, install Rosetta:
+
+```console
+$ softwareupdate --install-rosetta
+```
+
+Now any command can be run with Rosetta via the `arch` command line tool.
+
+Then you can start your shell in an x86 environment:
+
+```console
+$ arch -x86_64 zsh
+```
+
+You can double check your current architecture via the `arch` command:
+
+```console
+$ arch -x86_64 zsh
+$ arch
+i386
+```
+
+You may need to set the default target for `rustc` to x86-64, e.g.
+
+```console
+$ rustup default stable-x86_64-apple-darwin
+```
+
+While in your i386 shell, install Cargo and Homebrew, then hack away!
+
+### Rosetta Caveats
+
+1. You must install a version of Homebrew for each architecture
+2. Cargo will install in $HOME/.cargo by default, and I don't know a good way to change architectures after install
+
+If you use Fish shell you can [read this link](https://tenderlovemaking.com/2022/01/07/homebrew-rosetta-and-ruby.html) for information on making the dev environment easier.
+
+## Profiling with Linux perf
+
+`--yjit-perf` allows you to profile JIT-ed methods along with other native functions using Linux perf.
+When you run Ruby with `perf record`, perf looks up `/tmp/perf-{pid}.map` to resolve symbols in JIT code,
+and this option lets YJIT write method symbols into that file as well as enabling frame pointers.
+
+### Call graph
+
+Here's an example way to use this option with [Firefox Profiler](https://profiler.firefox.com)
+(See also: [Profiling with Linux perf](https://profiler.firefox.com/docs/#/./guide-perf-profiling)):
+
+```bash
+# Compile the interpreter with frame pointers enabled
+./configure --enable-yjit --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc cflags=-fno-omit-frame-pointer
+make -j && make install
+
+# [Optional] Allow running perf without sudo
+echo 0 | sudo tee /proc/sys/kernel/kptr_restrict
+echo -1 | sudo tee /proc/sys/kernel/perf_event_paranoid
+
+# Profile Ruby with --yjit-perf
+cd ../yjit-bench
+PERF="record --call-graph fp" ruby --yjit-perf -Iharness-perf benchmarks/liquid-render/benchmark.rb
+
+# View results on Firefox Profiler https://profiler.firefox.com.
+# Create /tmp/test.perf as below and upload it using "Load a profile from file".
+perf script --fields +pid > /tmp/test.perf
+```
+
+### YJIT codegen
+
+You can also profile the number of cycles consumed by code generated by each YJIT function.
+
+```bash
+# Install perf
+apt-get install linux-tools-common linux-tools-generic linux-tools-`uname -r`
+
+# [Optional] Allow running perf without sudo
+echo 0 | sudo tee /proc/sys/kernel/kptr_restrict
+echo -1 | sudo tee /proc/sys/kernel/perf_event_paranoid
+
+# Profile Ruby with --yjit-perf=codegen
+cd ../yjit-bench
+PERF=record ruby --yjit-perf=codegen -Iharness-perf benchmarks/lobsters/benchmark.rb
+
+# Aggregate results
+perf script > /tmp/perf.txt
+../ruby/misc/yjit_perf.py /tmp/perf.txt
+```
+
+#### Building perf with Python support
+
+The above instructions work fine for most people, but you could also use
+a handy `perf script -s` interface if you build perf from source.
+
+```bash
+# Build perf from source for Python support
+sudo apt-get install libpython3-dev python3-pip flex libtraceevent-dev \
+ libelf-dev libunwind-dev libaudit-dev libslang2-dev libdw-dev
+git clone --depth=1 https://github.com/torvalds/linux
+cd linux/tools/perf
+make
+make install
+
+# Aggregate results
+perf script -s ../ruby/misc/yjit_perf.py
+```
diff --git a/doc/jit/zjit.md b/doc/jit/zjit.md
new file mode 100644
index 0000000000..38124cb737
--- /dev/null
+++ b/doc/jit/zjit.md
@@ -0,0 +1,397 @@
+# ZJIT: ADVANCED RUBY JIT PROTOTYPE
+
+ZJIT is a method-based just-in-time (JIT) compiler for Ruby. It uses profile
+information from the interpreter to guide optimization in the compiler.
+
+ZJIT is currently supported for macOS, Linux and BSD on x86-64 and arm64/aarch64 CPUs.
+This project is open source and falls under the same license as CRuby.
+
+## Current Limitations
+
+ZJIT may not be suitable for certain applications. It currently only supports macOS, Linux and BSD on x86-64 and arm64/aarch64 CPUs. ZJIT will use more memory than the Ruby interpreter because the JIT compiler needs to generate machine code in memory and maintain additional state information.
+You can change how much executable memory is allocated using [ZJIT's command-line options](rdoc-ref:@Command-Line+Options).
+
+## Contributing
+
+We welcome open source contributions. Feel free to open new issues to report
+bugs or just to ask questions. Suggestions on how to make this document more
+helpful for new contributors are most welcome.
+
+Bug fixes and bug reports are very valuable to us. If you find a bug in ZJIT,
+it's very possible that nobody has reported it before, or that we don't have
+a good reproduction for it, so please open a ticket on [the official Ruby bug
+tracker][rubybugs] (or, if you don't want to make an account, [on
+Shopify/ruby][shopifyruby]) 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 ZJIT 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.
+
+[rubybugs]: https://bugs.ruby-lang.org/projects/ruby-master
+[shopifyruby]: https://github.com/Shopify/ruby/issues
+
+If you would like to contribute a large patch to ZJIT, we suggest [chatting on
+Zulip][zulip] for a casual chat and then opening an issue on the [Shopify/ruby
+repository][shopifyruby] so that we can have a technical 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 so we can have a productive
+discussion as to how you can contribute patches we will want to merge into
+ZJIT.
+
+[zulip]: https://zjit.zulipchat.com/
+
+## Build Instructions
+
+Refer to [Building Ruby](rdoc-ref:contributing/building_ruby.md) for general build prerequisites.
+Additionally, ZJIT requires Rust 1.85.0 or later. Release builds need only `rustc`. Development
+builds require `cargo` and may download dependencies. GNU Make is required.
+
+### For normal use
+
+To build ZJIT on macOS:
+
+```bash
+./autogen.sh
+
+./configure \
+ --enable-zjit \
+ --prefix="$HOME"/.rubies/ruby-zjit \
+ --disable-install-doc \
+ --with-opt-dir="$(brew --prefix openssl):$(brew --prefix readline):$(brew --prefix libyaml)"
+
+make -j miniruby
+```
+
+To build ZJIT on Linux:
+
+```bash
+./autogen.sh
+
+./configure \
+ --enable-zjit \
+ --prefix="$HOME"/.rubies/ruby-zjit \
+ --disable-install-doc
+
+make -j miniruby
+```
+
+### For development
+
+To build ZJIT on macOS:
+
+```bash
+./autogen.sh
+
+./configure \
+ --enable-zjit=dev \
+ --prefix="$HOME"/.rubies/ruby-zjit \
+ --disable-install-doc \
+ --with-opt-dir="$(brew --prefix openssl):$(brew --prefix readline):$(brew --prefix libyaml)"
+
+make -j miniruby
+```
+
+To build ZJIT on Linux:
+
+```bash
+./autogen.sh
+
+./configure \
+ --enable-zjit=dev \
+ --prefix="$HOME"/.rubies/ruby-zjit \
+ --disable-install-doc
+
+make -j miniruby
+```
+
+Note that `--enable-zjit=dev` does a lot of IR validation, which will help to catch errors early but mean compilation and warmup are significantly slower.
+
+The valid values for `--enable-zjit` are, from fastest to slowest:
+* `--enable-zjit`: enable ZJIT in release mode for maximum performance
+* `--enable-zjit=stats`: enable ZJIT in extended-stats mode
+* `--enable-zjit=dev_nodebug`: enable ZJIT in development mode but without slow runtime checks
+* `--enable-zjit=dev`: enable ZJIT in debug mode for development, also enables `RUBY_DEBUG`
+
+### Regenerate bindings
+
+When modifying `zjit/bindgen/src/main.rs` you need to regenerate bindings in `zjit/src/cruby_bindings.inc.rs` with:
+
+```bash
+make zjit-bindgen
+```
+
+## Documentation
+
+### Command-Line Options
+
+See `ruby --help` for ZJIT-specific command-line options:
+
+```
+$ ruby --help
+...
+ZJIT options:
+ --zjit-mem-size=num
+ Max amount of memory that ZJIT can use in MiB (default: 128).
+ --zjit-call-threshold=num
+ Number of calls to trigger JIT (default: 30).
+ --zjit-num-profiles=num
+ Number of profiled calls before JIT (default: 5).
+ --zjit-stats[=quiet]
+ Enable collecting ZJIT statistics (=quiet to suppress output).
+ --zjit-disable Disable ZJIT for lazily enabling it with RubyVM::ZJIT.enable.
+ --zjit-perf Dump ISEQ symbols into /tmp/perf-{}.map for Linux perf.
+ --zjit-log-compiled-iseqs=path
+ Log compiled ISEQs to the file. The file will be truncated.
+ --zjit-trace-exits[=counter]
+ Record source on side-exit. `Counter` picks specific counter.
+ --zjit-trace-exits-sample-rate=num
+ Frequency at which to record side exits. Must be `usize`.
+$
+```
+
+### Source level documentation
+
+You can generate and open the source level documentation in your browser using:
+
+```bash
+cargo doc --document-private-items -p zjit --open
+```
+
+### Graph of the Type System
+
+You can generate a graph of the ZJIT type hierarchy using:
+
+```bash
+ruby zjit/src/hir_type/gen_hir_type.rb > zjit/src/hir_type/hir_type.inc.rs
+dot -O -Tpdf zjit_types.dot
+open zjit_types.dot.pdf
+```
+
+## Testing
+
+Note that tests link against CRuby, so directly calling `cargo test`, or `cargo nextest` should not build. All tests are instead accessed through `make`.
+
+### Setup
+
+First, ensure you have `cargo` installed. If you do not already have it, you can use [rustup.rs](https://rustup.rs/).
+
+Also install cargo-binstall with:
+
+```bash
+cargo install cargo-binstall
+```
+
+Make sure to add `--enable-zjit=dev` when you run `configure`, then install the following tools:
+
+```bash
+cargo binstall --secure cargo-nextest
+cargo binstall --secure cargo-insta
+```
+
+`cargo-insta` is used for updating snapshots. `cargo-nextest` runs each test in its own process, which is valuable since CRuby only supports booting once per process, and most APIs are not thread safe.
+
+### Running unit tests
+
+For testing functionality within ZJIT, use:
+
+```bash
+make zjit-test
+```
+
+You can also run a single test case by specifying the function name:
+
+```bash
+make zjit-test ZJIT_TESTS=test_putobject
+```
+
+#### Snapshot Testing
+
+ZJIT uses [insta](https://insta.rs/) for snapshot testing within unit tests. When tests fail due to snapshot mismatches, pending snapshots are created. The test command will notify you if there are pending snapshots:
+
+```
+Pending snapshots found. Accept with: make zjit-test-update
+```
+
+To update/accept all the snapshot changes:
+
+```bash
+make zjit-test-update
+```
+
+You can also review snapshot changes interactively one by one:
+
+```bash
+cd zjit && cargo insta review
+```
+
+Test changes will be reviewed alongside code changes.
+
+### Running integration tests
+
+This command runs Ruby execution tests.
+
+```bash
+make test-all TESTS="test/ruby/test_zjit.rb"
+```
+
+You can also run a single test case by matching the method name:
+
+```bash
+make test-all TESTS="test/ruby/test_zjit.rb -n TestZJIT#test_putobject"
+```
+
+### Running all tests
+
+Runs both `make zjit-test` and `test/ruby/test_zjit.rb`:
+
+```bash
+make zjit-check
+```
+
+## Statistics Collection
+
+ZJIT provides detailed statistics about JIT compilation and execution behavior.
+
+### Basic Stats
+
+Run with basic statistics printed on exit:
+
+```bash
+./miniruby --zjit-stats script.rb
+```
+
+Collect stats without printing (access via `RubyVM::ZJIT.stats` in Ruby):
+
+```bash
+./miniruby --zjit-stats=quiet script.rb
+```
+
+### Accessing Stats in Ruby
+
+```ruby
+# Check if stats are enabled
+if RubyVM::ZJIT.stats_enabled?
+ stats = RubyVM::ZJIT.stats
+ puts "Compiled ISEQs: #{stats[:compiled_iseq_count]}"
+ puts "Failed ISEQs: #{stats[:failed_iseq_count]}"
+
+ # You can also reset stats during execution
+ RubyVM::ZJIT.reset_stats!
+end
+```
+
+### Performance Ratio
+
+The `ratio_in_zjit` stat shows the percentage of Ruby instructions executed in JIT code vs interpreter.
+This metric only appears when ZJIT is built with `--enable-zjit=stats` [or more](#build-instructions) (which enables `rb_vm_insn_count` tracking) and represents a key performance indicator for ZJIT effectiveness.
+
+### Tracing side exits
+
+Through [Stackprof](https://github.com/tmm1/stackprof), detailed information about the methods that the JIT side-exits from can be displayed after some execution of a program. Optionally, you can use `--zjit-trace-exits-sample-rate=N` to sample every N-th occurrence. Enabling `--zjit-trace-exits-sample-rate=N` will automatically enable `--zjit-trace-exits`.
+
+```bash
+./miniruby --zjit-trace-exits script.rb
+```
+
+A file called `zjit_exits_{pid}.dump` will be created in the same directory as `script.rb`. Viewing the side exited methods can be done with Stackprof:
+
+```bash
+stackprof path/to/zjit_exits_{pid}.dump
+```
+
+### Viewing HIR in Iongraph
+
+Using `--zjit-dump-hir-iongraph` will dump all compiled functions into a directory named `/tmp/zjit-iongraph-{PROCESS_PID}`. Each file will be named `func_{ZJIT_FUNC_NAME}.json`. In order to use them in the Iongraph viewer, you'll need to use `jq` to collate them to a single file. An example invocation of `jq` is shown below for reference.
+
+`jq --slurp --null-input '.functions=inputs | .version=1' /tmp/zjit-iongraph-{PROCESS_PID}/func*.json > ~/Downloads/ion.json`
+
+From there, you can use https://mozilla-spidermonkey.github.io/iongraph/ to view your trace.
+
+### Printing ZJIT Errors
+
+`--zjit-debug` prints ZJIT compilation errors and other diagnostics:
+
+```bash
+./miniruby --zjit-debug script.rb
+```
+
+As you might guess from the name, this option is intended mostly for ZJIT developers.
+
+## Useful dev commands
+
+To view YARV output for code snippets:
+
+```bash
+./miniruby --dump=insns -e0
+```
+
+To run code snippets with ZJIT:
+
+```bash
+./miniruby --zjit -e0
+```
+
+You can also try https://www.rubyexplorer.xyz/ to view Ruby YARV disasm output with syntax highlighting
+in a way that can be easily shared with other team members.
+
+## Understanding Ruby Stacks
+
+Ruby execution involves three distinct stacks and understanding them will help you understand ZJIT's implementation:
+
+### 1. Native Stack
+
+- **Purpose**: Return addresses and saved registers. ZJIT also uses it for some C functions' argument arrays
+- **Management**: OS-managed, one per native thread
+- **Growth**: Downward from high addresses
+- **Constants**: `NATIVE_STACK_PTR`, `NATIVE_BASE_PTR`
+
+### 2. Ruby VM Stack
+
+The Ruby VM uses a single contiguous memory region (`ec->vm_stack`) containing two sub-stacks that grow toward each other. When they meet, stack overflow occurs.
+
+See [doc/contributing/vm_stack_and_frames.md](rdoc-ref:contributing/vm_stack_and_frames.md) for detailed architecture and frame layout.
+
+**Control Frame Stack:**
+
+- **Stores**: Frame metadata (`rb_control_frame_t` structures)
+- **Growth**: Downward from `vm_stack + size` (high addresses)
+- **Constants**: `CFP`
+
+**Value Stack:**
+
+- **Stores**: YARV bytecode operands (self, arguments, locals, temporaries)
+- **Growth**: Upward from `vm_stack` (low addresses)
+- **Constants**: `SP`
+
+## ZJIT Glossary
+
+This glossary contains terms that are helpful for understanding ZJIT.
+
+Please note that some terms may appear in CRuby internals too but with different meanings.
+
+| Term | Definition |
+| ----------------- | ------------------------------------------------------------------------------------------------------------------------------- |
+| HIR | High-level Intermediate Representation. High-level (Ruby semantics) graph representation in static single-assignment (SSA) form |
+| LIR | Low-level Intermediate Representation. Low-level IR used in the backend for assembly generation |
+| SSA | Static Single Assignment. A form where each variable is assigned exactly once |
+| `opnd` | Operand. An operand to an IR instruction (can be register, memory, immediate, etc.) |
+| `dst` | Destination. The output operand of an instruction where the result is stored |
+| VReg | Virtual Register. A virtual register that gets lowered to physical register or memory |
+| `insn_id` | Instruction ID. An index of an instruction in a function |
+| `block_id` | The index of a basic block, which effectively acts like a pointer |
+| `branch` | Control flow edge between basic blocks in the compiled code |
+| `cb` | Code Block. Memory region for generated machine code |
+| `entry` | The starting address of compiled code for an ISEQ |
+| Patch Point | Location in generated code that can be modified later in case assumptions get invalidated |
+| Frame State | Captured state of the Ruby stack frame at a specific point for deoptimization |
+| Guard | A run-time check that ensures assumptions are still valid |
+| `invariant` | An assumption that JIT code relies on, requiring invalidation if broken |
+| Deopt | Deoptimization. Process of falling back from JIT code to interpreter |
+| Side Exit | Exit from JIT code back to interpreter |
+| Type Lattice | Hierarchy of types used for type inference and optimization |
+| Constant Folding | Optimization that evaluates constant expressions at compile time |
+| RSP | x86-64 stack pointer register used for native stack operations |
+| Register Spilling | Process of moving register values to memory when running out of physical registers |
diff --git a/doc/language/box.md b/doc/language/box.md
new file mode 100644
index 0000000000..8c7fd20b20
--- /dev/null
+++ b/doc/language/box.md
@@ -0,0 +1,361 @@
+# Ruby Box - Ruby's in-process separation of Classes and Modules
+
+Ruby Box is designed to provide separated spaces in a Ruby process, to isolate application code, libraries and monkey patches.
+
+## Known issues
+
+* Experimental warning is shown when ruby starts with `RUBY_BOX=1` (specify `-W:no-experimental` option to hide it)
+* Installing native extensions may fail under `RUBY_BOX=1` because of stack level too deep in extconf.rb
+* `require 'active_support/core_ext'` may fail under `RUBY_BOX=1`
+* Defined methods in a box may not be referred by built-in methods written in Ruby
+
+## TODOs
+
+* Add the loaded box on iseq to check if another box tries running the iseq (add a field only when VM_CHECK_MODE?)
+* Assign its own TOPLEVEL_BINDING in boxes
+* Fix calling `warn` in boxes to refer `$VERBOSE` and `Warning.warn` in the box
+* Make an internal data container class `Ruby::Box::Entry` invisible
+* More test cases about `$LOAD_PATH` and `$LOADED_FEATURES`
+
+## How to use
+
+### Enabling Ruby Box
+
+First, an environment variable should be set at the ruby process bootup: `RUBY_BOX=1`.
+The only valid value is `1` to enable Ruby Box. Other values (or unset `RUBY_BOX`) means disabling Ruby Box. And setting the value after Ruby program starts doesn't work.
+
+### Using Ruby Box
+
+`Ruby::Box` class is the entrypoint of Ruby Box.
+
+```ruby
+box = Ruby::Box.new
+box.require('something') # or require_relative, load
+```
+
+The required file (either .rb or .so/.dll/.bundle) is loaded in the box (`box` here). The required/loaded files from `something` will be loaded in the box recursively.
+
+```ruby
+# something.rb
+
+X = 1
+
+class Something
+ def self.x = X
+ def x = ::X
+end
+```
+
+Classes/modules, those methods and constants defined in the box can be accessed via `box` object.
+
+```ruby
+X = 2
+p X # 2
+p ::X # 2
+p box::Something.x # 1
+p box::X # 1
+```
+
+Instance methods defined in the box also run with definitions in the box.
+
+```ruby
+s = box::Something.new
+
+p s.x # 1
+```
+
+## Specifications
+
+### Ruby Box types
+
+There are two box types:
+
+* Root box
+* User boxes
+
+There is the root box, just a single box in a Ruby process. Ruby bootstrap runs in the root box, and all builtin classes/modules are defined in the root box. (See "Builtin classes and modules".)
+
+User boxes are to run user-written programs and libraries loaded from user programs. The user's main program (specified by the `ruby` command line argument) is executed in the "main" box, which is a user box automatically created at the end of Ruby's bootstrap, copied from the root box.
+
+When `Ruby::Box.new` is called, an "optional" box (a user, non-main box) is created, copied from the root box. All user boxes are flat, copied from the root box.
+
+### Ruby Box class and instances
+
+`Ruby::Box` is a class, as a subclass of `Module`. `Ruby::Box` instances are a kind of `Module`.
+
+### Classes and modules defined in boxes
+
+The classes and modules, newly defined in a box `box`, are accessible via `box`. For example, if a class `A` is defined in `box`, it is accessible as `box::A` from outside of the box.
+
+In the box `box`, `A` can be referred to as `A` (and `::A`).
+
+### Built-in classes and modules reopened in boxes
+
+In boxes, builtin classes/modules are visible and can be reopened. Those classes/modules can be reopened using `class` or `module` clauses, and class/module definitions can be changed.
+
+The changed definitions are visible only in the box. In other boxes, builtin classes/modules and those instances work without changed definitions.
+
+```ruby
+# in foo.rb
+class String
+ BLANK_PATTERN = /\A\s*\z/
+ def blank?
+ self.match?(BLANK_PATTERN)
+ end
+end
+
+module Foo
+ def self.foo = "foo"
+
+ def self.foo_is_blank?
+ foo.blank?
+ end
+end
+
+Foo.foo.blank? #=> false
+"foo".blank? #=> false
+
+# in main.rb
+box = Ruby::Box.new
+box.require_relative('foo')
+
+box::Foo.foo_is_blank? #=> false (#blank? called in box)
+
+"foo".blank? # NoMethodError
+String::BLANK_PATTERN # NameError
+```
+
+The main box and `box` are different boxes, so monkey patches in main are also invisible in `box`.
+
+### Builtin classes and modules
+
+In the box context, "builtin" classes and modules are classes and modules:
+
+* Accessible without any `require` calls in user scripts
+* Defined before any user program start running
+* Including classes/modules loaded by `prelude.rb` (including RubyGems `Gem`, for example)
+
+Hereafter, "builtin classes and modules" will be referred to as just "builtin classes".
+
+### Builtin classes referred via box objects
+
+Builtin classes in a box `box` can be referred from other boxes. For example, `box::String` is a valid reference, and `String` and `box::String` are identical (`String == box::String`, `String.object_id == box::String.object_id`).
+
+`box::String`-like reference returns just a `String` in the current box, so its definition is `String` in the box, not in `box`.
+
+```ruby
+# foo.rb
+class String
+ def self.foo = "foo"
+end
+
+# main.rb
+box = Ruby::Box.new
+box.require_relative('foo')
+
+box::String.foo # NoMethodError
+```
+
+### Class instance variables, class variables, constants
+
+Builtin classes can have different sets of class instance variables, class variables and constants between boxes.
+
+```ruby
+# foo.rb
+class Array
+ @v = "foo"
+ @@v = "_foo_"
+ V = "FOO"
+end
+
+Array.instance_variable_get(:@v) #=> "foo"
+Array.class_variable_get(:@@v) #=> "_foo_"
+Array.const_get(:V) #=> "FOO"
+
+# main.rb
+box = Ruby::Box.new
+box.require_relative('foo')
+
+Array.instance_variable_get(:@v) #=> nil
+Array.class_variable_get(:@@v) # NameError
+Array.const_get(:V) # NameError
+```
+
+### Global variables
+
+In boxes, changes on global variables are also isolated in the boxes. Changes on global variables in a box are visible/applied only in the box.
+
+```ruby
+# foo.rb
+$foo = "foo"
+$VERBOSE = nil
+
+puts "This appears: '#{$foo}'"
+
+# main.rb
+p $foo #=> nil
+p $VERBOSE #=> false
+
+box = Ruby::Box.new
+box.require_relative('foo') # "This appears: 'foo'"
+
+p $foo #=> nil
+p $VERBOSE #=> false
+```
+
+### Top level constants
+
+Usually, top level constants are defined as constants of `Object`. In boxes, top level constants are constants of `Object` in the box. And the box object `box`'s constants are strictly equal to constants of `Object`.
+
+```ruby
+# foo.rb
+FOO = 100
+
+FOO #=> 100
+Object::FOO #=> 100
+
+# main.rb
+box = Ruby::Box.new
+box.require_relative('foo')
+
+box::FOO #=> 100
+
+FOO # NameError
+Object::FOO # NameError
+```
+
+### Top level methods
+
+Top level methods are private instance methods of `Object`, in each box.
+
+```ruby
+# foo.rb
+def yay = "foo"
+
+class Foo
+ def self.say = yay
+end
+
+Foo.say #=> "foo"
+yay #=> "foo"
+
+# main.rb
+box = Ruby::Box.new
+box.require_relative('foo')
+
+box::Foo.say #=> "foo"
+
+yay # NoMethodError
+```
+
+There is no way to expose top level methods in boxes to others.
+(See "Expose top level methods as a method of the box object" in "Discussions" section below)
+
+### Ruby Box scopes
+
+Ruby Box works in file scope. One `.rb` file runs in a single box.
+
+Once a file is loaded in a box `box`, all methods/procs defined/created in the file run in `box`.
+
+### Utility methods
+
+Several methods are available for trying/testing Ruby Box.
+
+* `Ruby::Box.current` returns the current box
+* `Ruby::Box.enabled?` returns true/false to represent `RUBY_BOX=1` is specified or not
+* `Ruby::Box.root` returns the root box
+* `Ruby::Box.main` returns the main box
+* `Ruby::Box#eval` evaluates a Ruby code (String) in the receiver box, just like calling `#load` with a file
+
+## Implementation details
+
+#### ISeq inline method/constant cache
+
+As described above in "Ruby Box scopes", an ".rb" file runs in a box. So method/constant resolution will be done in a box consistently.
+
+That means ISeq inline caches work well even with boxes. Otherwise, it's a bug.
+
+#### Method call global cache (gccct)
+
+`rb_funcall()` C function refers to the global cc cache table (gccct), and the cache key is calculated with the current box.
+
+So, `rb_funcall()` calls have a performance penalty when Ruby Box is enabled.
+
+#### Current box and loading box
+
+The current box is the box that the executing code is in. `Ruby::Box.current` returns the current box object.
+
+The loading box is an internally managed box to determine the box to load newly required/loaded files. For example, `box` is the loading box when `box.require("foo")` is called.
+
+## Discussions
+
+#### More builtin methods written in Ruby
+
+If Ruby Box is enabled by default, builtin methods can be written in Ruby because it can't be overridden by users' monkey patches. Builtin Ruby methods can be JIT-ed, and it could bring performance reward.
+
+#### Monkey patching methods called by builtin methods
+
+Builtin methods sometimes call other builtin methods. For example, `Hash#map` calls `Hash#each` to retrieve entries to be mapped. Without Ruby Box, Ruby users can overwrite `Hash#each` and expect the behavior change of `Hash#map` as a result.
+
+But with boxes, `Hash#map` runs in the root box. Ruby users can define `Hash#each` only in user boxes, so users cannot change `Hash#map`'s behavior in this case. To achieve it, users should override both`Hash#map` and `Hash#each` (or only `Hash#map`).
+
+It is a breaking change.
+
+Users can define methods using `Ruby::Box.root.eval(...)`, but it's clearly not ideal API.
+
+#### Assigning values to global variables used by builtin methods
+
+Similar to monkey patching methods, global variables assigned in a box is separated from the root box. Methods defined in the root box referring a global variable can't find the re-assigned one.
+
+#### Context of `$LOAD_PATH` and `$LOADED_FEATURES`
+
+Global variables `$LOAD_PATH` and `$LOADED_FEATURES` control `require` method behaviors. So those variables are determined by the loading box instead of the current box.
+
+This could potentially conflict with the user's expectations. We should find the solution.
+
+#### Expose top level methods as a method of the box object
+
+Currently, top level methods in boxes are not accessible from outside of the box. But there might be a use case to call other box's top level methods.
+
+#### Split root and builtin box
+
+Currently, the single "root" box is the source of classext CoW. And also, the "root" box can load additional files after starting main script evaluation by calling methods which contain lines like `require "openssl"`.
+
+That means, user boxes can have different sets of definitions according to when it is created.
+
+```
+[root]
+ |
+ |----[main]
+ |
+ |(require "openssl" called in root)
+ |
+ |----[box1] having OpenSSL
+ |
+ |(remove_const called for OpenSSL in root)
+ |
+ |----[box2] without OpenSSL
+```
+
+This could cause unexpected behavior differences between user boxes. It should NOT be a problem because user scripts which refer to `OpenSSL` should call `require "openssl"` by themselves.
+But in the worst case, a script (without `require "openssl"`) runs well in `box1`, but doesn't run in `box2`. This situation looks like a "random failure" to users.
+
+An option possible to prevent this situation is to have "root" and "builtin" boxes.
+
+* root
+ * The box for the Ruby process bootstrap, then the source of CoW
+ * After starting the main box, no code runs in this box
+* builtin
+ * The box copied from the root box at the same time with "main"
+ * Methods and procs defined in the "root" box run in this box
+ * Classes and modules required will be loaded in this box
+
+This design realizes a consistent source of box CoW.
+
+#### Separate `cc_tbl` and `callable_m_tbl`, `cvc_tbl` for less classext CoW
+
+The fields of `rb_classext_t` contains several cache(-like) data, `cc_tbl`(callcache table), `callable_m_tbl`(table of resolved complemented methods) and `cvc_tbl`(class variable cache table).
+
+The classext CoW is triggered when the contents of `rb_classext_t` are changed, including `cc_tbl`, `callable_m_tbl`, and `cvc_tbl`. But those three tables are changed by just calling methods or referring class variables. So, currently, classext CoW is triggered much more times than the original expectation.
+
+If we can move those three tables outside of `rb_classext_t`, the number of copied `rb_classext_t` will be much less than the current implementation.
diff --git a/doc/bsearch.rdoc b/doc/language/bsearch.rdoc
index 90705853d7..90705853d7 100644
--- a/doc/bsearch.rdoc
+++ b/doc/language/bsearch.rdoc
diff --git a/doc/language/calendars.rdoc b/doc/language/calendars.rdoc
new file mode 100644
index 0000000000..a2540f1c43
--- /dev/null
+++ b/doc/language/calendars.rdoc
@@ -0,0 +1,62 @@
+== Julian and Gregorian Calendars
+
+The difference between the
+{Julian calendar}[https://en.wikipedia.org/wiki/Julian_calendar]
+and the
+{Gregorian calendar}[https://en.wikipedia.org/wiki/Gregorian_calendar]
+may matter to your program if it uses dates before the switchovers.
+
+- October 15, 1582.
+- September 14, 1752.
+
+A date will be different in the two calendars, in general.
+
+=== Different switchover dates
+
+The reasons for the difference are religious/political histories.
+
+- On October 15, 1582, several countries changed
+ from the Julian calendar to the Gregorian calendar;
+ these included Italy, Poland, Portugal, and Spain.
+ Other countries in the Western world retained the Julian calendar.
+- On September 14, 1752, most of the British empire
+ changed from the Julian calendar to the Gregorian calendar.
+
+When your code uses a date before these switchover dates,
+it will matter whether it considers the switchover date
+to be the earlier date or the later date (or neither).
+
+See also {a concrete example here}[rdoc-ref:DateTime@When+should+you+use+DateTime+and+when+should+you+use+Time-3F].
+
+=== Argument +start+
+
+Certain methods in class \Date handle differences in the
+{Julian and Gregorian calendars}[rdoc-ref:@Julian+and+Gregorian+Calendars]
+by accepting an optional argument +start+, whose value may be:
+
+- Date::ITALY (the default): the created date is Julian
+ if before October 15, 1582, Gregorian otherwise:
+
+ d = Date.new(1582, 10, 15)
+ d.prev_day.julian? # => true
+ d.julian? # => false
+ d.gregorian? # => true
+
+- Date::ENGLAND: the created date is Julian if before September 14, 1752,
+ Gregorian otherwise:
+
+ d = Date.new(1752, 9, 14, Date::ENGLAND)
+ d.prev_day.julian? # => true
+ d.julian? # => false
+ d.gregorian? # => true
+
+- Date::JULIAN: the created date is Julian regardless of its value:
+
+ d = Date.new(1582, 10, 15, Date::JULIAN)
+ d.julian? # => true
+
+- Date::GREGORIAN: the created date is Gregorian regardless of its value:
+
+ d = Date.new(1752, 9, 14, Date::GREGORIAN)
+ d.prev_day.gregorian? # => true
+
diff --git a/doc/language/case_mapping.rdoc b/doc/language/case_mapping.rdoc
new file mode 100644
index 0000000000..d40155db03
--- /dev/null
+++ b/doc/language/case_mapping.rdoc
@@ -0,0 +1,106 @@
+= 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 {Section 3.13 (Default Case Algorithms) of the Unicode standard}[https://www.unicode.org/versions/latest/ch03.pdf].
+
+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 (Context Specification for Casing) of the Unicode standard}[https://www.unicode.org/versions/latest/ch03.pdf]
+is currently not supported.
+
+In most cases, the case conversion of a string has the same number of characters as before.
+There are exceptions (see also +:fold+ below):
+
+ s = "\u00DF" # => "ß"
+ 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.
+
+== Case Mappings
+
+Except for +casecmp+ and +casecmp?+,
+each of the case-mapping methods listed above
+accepts an optional argument, <tt>mapping</tt>.
+
+The argument is one of:
+
+- +: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.
+ 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.
+
+- +: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/doc/language/character_selectors.rdoc b/doc/language/character_selectors.rdoc
new file mode 100644
index 0000000000..8bfc9b719b
--- /dev/null
+++ b/doc/language/character_selectors.rdoc
@@ -0,0 +1,100 @@
+= Character Selectors
+
+== Character Selector
+
+A _character_ _selector_ is a string argument accepted by certain Ruby methods.
+Each of these instance methods accepts one or more character selectors:
+
+- String#tr(selector, replacements): returns a new string.
+- String#tr!(selector, replacements): returns +self+ or +nil+.
+- String#tr_s(selector, replacements): returns a new string.
+- String#tr_s!(selector, replacements): returns +self+ or +nil+.
+- String#count(*selectors): returns the count of the specified characters.
+- String#delete(*selectors): returns a new string.
+- String#delete!(*selectors): returns +self+ or +nil+.
+- String#squeeze(*selectors): returns a new string.
+- String#squeeze!(*selectors): returns +self+ or +nil+.
+- String#strip(*selectors): returns a new string.
+- String#strip!(*selectors): returns +self+ or +nil+.
+
+A character selector identifies zero or more characters in +self+
+that are to be operands for the method.
+
+In this section, we illustrate using method String#delete(selector),
+which deletes the selected characters.
+
+In the simplest case, the characters selected are exactly those
+contained in the selector itself:
+
+ 'abracadabra'.delete('a') # => "brcdbr"
+ 'abracadabra'.delete('ab') # => "rcdr"
+ 'abracadabra'.delete('abc') # => "rdr"
+ '0123456789'.delete('258') # => "0134679"
+ '!@#$%&*()_+'.delete('+&#') # => "!@$%*()_"
+ 'こんにちは'.delete('に') # => "こんちは"
+
+Note that order and repetitions do not matter:
+
+ 'abracadabra'.delete('dcab') # => "rr"
+ 'abracadabra'.delete('aaaa') # => "brcdbr"
+
+In a character selector, these three characters get special treatment:
+
+- A leading caret (<tt>'^'</tt>) functions as a "not" operator
+ for the characters to its right:
+
+ 'abracadabra'.delete('^bc') # => "bcb"
+ '0123456789'.delete('^852') # => "258"
+
+- A hyphen (<tt>'-'</tt>) between two other characters
+ defines a range of characters instead of a plain string of characters:
+
+ 'abracadabra'.delete('a-d') # => "rr"
+ '0123456789'.delete('4-7') # => "012389"
+ '!@#$%&*()_+'.delete(' -/') # => "@^_"
+
+ # May contain more than one range.
+ 'abracadabra'.delete('a-cq-t') # => "d"
+
+ # Ranges may be mixed with plain characters.
+ '0123456789'.delete('67-950-23') # => "4"
+
+ # Ranges may be mixed with negations.
+ 'abracadabra'.delete('^a-c') # => "abacaaba"
+
+- A backslash (<tt>'\'</tt>) acts as an escape for a caret, a hyphen,
+ or another backslash:
+
+ 'abracadabra^'.delete('\^bc') # => "araadara"
+ 'abracadabra-'.delete('a\-d') # => "brcbr"
+ "hello\r\nworld".delete("\r") # => "hello\nworld"
+ "hello\r\nworld".delete("\\r") # => "hello\r\nwold"
+ "hello\r\nworld".delete("\\\r") # => "hello\nworld"
+
+== Multiple Character Selectors
+
+These instance methods accept multiple character selectors:
+
+- String#count(*selectors): returns the count of the specified characters.
+- String#delete(*selectors): returns a new string.
+- String#delete!(*selectors): returns +self+ or +nil+.
+- String#squeeze(*selectors): returns a new string.
+- String#squeeze!(*selectors): returns +self+ or +nil+.
+- String#strip(*selectors): returns a new string.
+- String#strip!(*selectors): returns +self+ or +nil+.
+
+In effect, the given selectors are formed into a single selector
+consisting of only those characters common to _all_ of the given selectors.
+
+All forms of selectors may be used, including negations, ranges, and escapes.
+
+Each of these pairs of method calls is equivalent:
+
+ s.delete('abcde', 'dcbfg')
+ s.delete('bcd')
+
+ s.delete('^abc', '^def')
+ s.delete('^abcdef')
+
+ s.delete('a-e', 'c-g')
+ s.delete('cde')
diff --git a/doc/dig_methods.rdoc b/doc/language/dig_methods.rdoc
index 366275d451..366275d451 100644
--- a/doc/dig_methods.rdoc
+++ b/doc/language/dig_methods.rdoc
diff --git a/doc/language/encodings.rdoc b/doc/language/encodings.rdoc
new file mode 100644
index 0000000000..683842d3fb
--- /dev/null
+++ b/doc/language/encodings.rdoc
@@ -0,0 +1,482 @@
+= Encodings
+
+== The Basics
+
+A {character encoding}[https://en.wikipedia.org/wiki/Character_encoding],
+often shortened to _encoding_, is a mapping between:
+
+- A sequence of 8-bit bytes (each byte in the range <tt>0..255</tt>).
+- Characters in a specific character set.
+
+Some character sets contain only 1-byte characters;
+{US-ASCII}[https://en.wikipedia.org/wiki/ASCII], for example, has 256 1-byte characters.
+This string, encoded in US-ASCII, has six characters that are stored as six bytes:
+
+ s = 'Hello!'.encode(Encoding::US_ASCII) # => "Hello!"
+ s.encoding # => #<Encoding:US-ASCII>
+ s.bytes # => [72, 101, 108, 108, 111, 33]
+
+Other encodings may involve multi-byte characters.
+{UTF-8}[https://en.wikipedia.org/wiki/UTF-8], for example,
+encodes more than one million characters, encoding each in one to four bytes.
+The lowest-valued of these characters correspond to ASCII characters,
+and so are 1-byte characters:
+
+ s = 'Hello!' # => "Hello!"
+ s.bytes # => [72, 101, 108, 108, 111, 33]
+
+Other characters, such as the Euro symbol, are multi-byte:
+
+ s = "\u20ac" # => "€"
+ s.bytes # => [226, 130, 172]
+
+== The \Encoding Class
+
+=== \Encoding Objects
+
+Ruby encodings are defined by constants in class \Encoding.
+There can be only one instance of \Encoding for each of these constants.
+Method Encoding.list returns an array of \Encoding objects (one for each constant):
+
+ Encoding.list.size # => 103
+ Encoding.list.first.class # => Encoding
+ Encoding.list.take(3)
+ # => [#<Encoding:ASCII-8BIT>, #<Encoding:UTF-8>, #<Encoding:US-ASCII>]
+
+=== Names and Aliases
+
+Method Encoding#name returns the name of an \Encoding:
+
+ Encoding::ASCII_8BIT.name # => "ASCII-8BIT"
+ Encoding::WINDOWS_31J.name # => "Windows-31J"
+
+An \Encoding object has zero or more aliases;
+method Encoding#names returns an array containing the name and all aliases:
+
+ Encoding::ASCII_8BIT.names
+ # => ["ASCII-8BIT", "BINARY"]
+ Encoding::WINDOWS_31J.names
+ #=> ["Windows-31J", "CP932", "csWindows31J", "SJIS", "PCK"]
+
+Method Encoding.aliases returns a hash of all alias/name pairs:
+
+ Encoding.aliases.size # => 71
+ Encoding.aliases.take(3)
+ # => [["BINARY", "ASCII-8BIT"], ["CP437", "IBM437"], ["CP720", "IBM720"]]
+
+Method Encoding.name_list returns an array of all the encoding names and aliases:
+
+ Encoding.name_list.size # => 175
+ Encoding.name_list.take(3)
+ # => ["ASCII-8BIT", "UTF-8", "US-ASCII"]
+
+Method +name_list+ returns more entries than method +list+
+because it includes both the names and their aliases.
+
+Method Encoding.find returns the \Encoding for a given name or alias, if it exists:
+
+ Encoding.find("US-ASCII") # => #<Encoding:US-ASCII>
+ Encoding.find("US-ASCII").class # => Encoding
+
+=== Default Encodings
+
+Method Encoding.find, above, also returns a default \Encoding
+for each of these special names:
+
+- +external+: the default external \Encoding:
+
+ Encoding.find("external") # => #<Encoding:UTF-8>
+
+- +internal+: the default internal \Encoding (may be +nil+):
+
+ Encoding.find("internal") # => nil
+
+- +locale+: the default \Encoding for a string from the environment:
+
+ Encoding.find("locale") # => #<Encoding:UTF-8> # Linux
+ Encoding.find("locale") # => #<Encoding:IBM437> # Windows
+
+- +filesystem+: the default \Encoding for a string from the filesystem:
+
+ Encoding.find("filesystem") # => #<Encoding:UTF-8>
+
+Method Encoding.default_external returns the default external \Encoding:
+
+ Encoding.default_external # => #<Encoding:UTF-8>
+
+Method Encoding.default_external= sets that value:
+
+ Encoding.default_external = Encoding::US_ASCII # => #<Encoding:US-ASCII>
+ Encoding.default_external # => #<Encoding:US-ASCII>
+
+Method Encoding.default_internal returns the default internal \Encoding:
+
+ Encoding.default_internal # => nil
+
+Method Encoding.default_internal= sets the default internal \Encoding:
+
+ Encoding.default_internal = Encoding::US_ASCII # => #<Encoding:US-ASCII>
+ Encoding.default_internal # => #<Encoding:US-ASCII>
+
+=== Compatible Encodings
+
+Method Encoding.compatible? returns whether two given objects are encoding-compatible
+(that is, whether they can be concatenated);
+returns the \Encoding of the concatenated string, or +nil+ if incompatible:
+
+ rus = "\u{442 435 441 442}"
+ eng = 'text'
+ Encoding.compatible?(rus, eng) # => #<Encoding:UTF-8>
+
+ s0 = "\xa1\xa1".force_encoding(Encoding::ISO_8859_1) # => "\xA1\xA1"
+ s1 = "\xa1\xa1".force_encoding(Encoding::EUCJP) # => "\x{A1A1}"
+ Encoding.compatible?(s0, s1) # => nil
+
+== \String \Encoding
+
+A Ruby String object has an encoding that is an instance of class \Encoding.
+The encoding may be retrieved by method String#encoding.
+
+The default encoding for a string literal is the script encoding;
+see {Script Encoding}[rdoc-ref:@Script+Encoding].
+
+ 's'.encoding # => #<Encoding:UTF-8>
+
+The default encoding for a string created with method String.new is:
+
+- For no argument, ASCII-8BIT.
+- For a \String object argument, the encoding of that string.
+- For a string literal, the script encoding;
+ see {Script Encoding}[rdoc-ref:@Script+Encoding].
+
+In either case, any encoding may be specified:
+
+ s = String.new(encoding: Encoding::UTF_8) # => ""
+ s.encoding # => #<Encoding:UTF-8>
+ s = String.new('foo', encoding: Encoding::BINARY) # => "foo"
+ s.encoding # => #<Encoding:BINARY (ASCII-8BIT)>
+
+The encoding for a string may be changed:
+
+ s = "R\xC3\xA9sum\xC3\xA9" # => "Résumé"
+ s.encoding # => #<Encoding:UTF-8>
+ s.force_encoding(Encoding::ISO_8859_1) # => "R\xC3\xA9sum\xC3\xA9"
+ s.encoding # => #<Encoding:ISO-8859-1>
+
+Changing the assigned encoding does not alter the content of the string;
+it changes only the way the content is to be interpreted:
+
+ s # => "R\xC3\xA9sum\xC3\xA9"
+ s.force_encoding(Encoding::UTF_8) # => "Résumé"
+
+The actual content of a string may also be altered;
+see {Transcoding a String}[#label-Transcoding+a+String].
+
+Here are a couple of useful query methods:
+
+ s = "abc".force_encoding(Encoding::UTF_8) # => "abc"
+ s.ascii_only? # => true
+ s = "abc\u{6666}".force_encoding(Encoding::UTF_8) # => "abc晦"
+ s.ascii_only? # => false
+
+ s = "\xc2\xa1".force_encoding(Encoding::UTF_8) # => "¡"
+ s.valid_encoding? # => true
+ s = "\xc2".force_encoding(Encoding::UTF_8) # => "\xC2"
+ s.valid_encoding? # => false
+
+== \Symbol and \Regexp Encodings
+
+The string stored in a Symbol or Regexp object also has an encoding;
+the encoding may be retrieved by method Symbol#encoding or Regexp#encoding.
+
+The default encoding for these, however, is:
+
+- US-ASCII, if all characters are US-ASCII.
+- The script encoding, otherwise;
+ see (Script Encoding)[rdoc-ref:@Script+Encoding].
+
+== Filesystem \Encoding
+
+The filesystem encoding is the default \Encoding for a string from the filesystem:
+
+ Encoding.find("filesystem") # => #<Encoding:UTF-8>
+
+== Locale \Encoding
+
+The locale encoding is the default encoding for a string from the environment,
+other than from the filesystem:
+
+ Encoding.find('locale') # => #<Encoding:IBM437>
+
+== Stream Encodings
+
+Certain stream objects can have two encodings; these objects include instances of:
+
+- IO.
+- File.
+- ARGF.
+- StringIO.
+
+The two encodings are:
+
+- An _external_ _encoding_, which identifies the encoding of the stream.
+- An _internal_ _encoding_, which (if not +nil+) specifies the encoding
+ to be used for the string constructed from the stream.
+
+=== External \Encoding
+
+The external encoding, which is an \Encoding object, specifies how bytes read
+from the stream are to be interpreted as characters.
+
+The default external encoding is:
+
+- UTF-8 for a text stream.
+- ASCII-8BIT for a binary stream.
+
+The default external encoding is returned by method Encoding.default_external,
+and may be set by:
+
+- Ruby command-line options <tt>--external_encoding</tt> or <tt>-E</tt>.
+
+You can also set the default external encoding using method Encoding.default_external=,
+but doing so may cause problems; strings created before and after the change
+may have a different encodings.
+
+For an \IO or \File object, the external encoding may be set by:
+
+- Open options +external_encoding+ or +encoding+, when the object is created;
+ see {Open Options}[rdoc-ref:IO@Open+Options].
+
+For an \IO, \File, \ARGF, or \StringIO object, the external encoding may be set by:
+
+- Methods +set_encoding+ or (except for \ARGF) +set_encoding_by_bom+.
+
+=== Internal \Encoding
+
+The internal encoding, which is an \Encoding object or +nil+,
+specifies how characters read from the stream
+are to be converted to characters in the internal encoding;
+those characters become a string whose encoding is set to the internal encoding.
+
+The default internal encoding is +nil+ (no conversion).
+It is returned by method Encoding.default_internal,
+and may be set by:
+
+- Ruby command-line options <tt>--internal_encoding</tt> or <tt>-E</tt>.
+
+You can also set the default internal encoding using method Encoding.default_internal=,
+but doing so may cause problems; strings created before and after the change
+may have a different encodings.
+
+For an \IO or \File object, the internal encoding may be set by:
+
+- Open options +internal_encoding+ or +encoding+, when the object is created;
+ see {Open Options}[rdoc-ref:IO@Open+Options].
+
+For an \IO, \File, \ARGF, or \StringIO object, the internal encoding may be set by:
+
+- Method +set_encoding+.
+
+== Script \Encoding
+
+A Ruby script has a script encoding, which may be retrieved by:
+
+ __ENCODING__ # => #<Encoding:UTF-8>
+
+The default script encoding is UTF-8;
+a Ruby source file may set its script encoding with a magic comment
+on the first line of the file (or second line, if there is a shebang on the first).
+The comment must contain the word +coding+ or +encoding+,
+followed by a colon, space and the Encoding name or alias:
+
+ # encoding: ISO-8859-1
+ __ENCODING__ #=> #<Encoding:ISO-8859-1>
+
+== Transcoding
+
+_Transcoding_ is the process of changing a sequence of characters
+from one encoding to another.
+
+As far as possible, the characters remain the same,
+but the bytes that represent them may change.
+
+The handling for characters that cannot be represented in the destination encoding
+may be specified by @Encoding+Options.
+
+=== Transcoding a \String
+
+Each of these methods transcodes a string:
+
+- String#encode: Transcodes +self+ into a new string
+ according to given encodings and options.
+- String#encode!: Like String#encode, but transcodes +self+ in place.
+- String#scrub: Transcodes +self+ into a new string
+ by replacing invalid byte sequences with a given or default replacement string.
+- String#scrub!: Like String#scrub, but transcodes +self+ in place.
+- String#unicode_normalize: Transcodes +self+ into a new string
+ according to Unicode normalization.
+- String#unicode_normalize!: Like String#unicode_normalize,
+ but transcodes +self+ in place.
+
+== Transcoding a Stream
+
+Each of these methods may transcode a stream;
+whether it does so depends on the external and internal encodings:
+
+- IO.foreach: Yields each line of given stream to the block.
+- IO.new: Creates and returns a new \IO object for the given integer file descriptor.
+- IO.open: Creates a new \IO object.
+- IO.pipe: Creates a connected pair of reader and writer \IO objects.
+- IO.popen: Creates an \IO object to interact with a subprocess.
+- IO.read: Returns a string with all or a subset of bytes from the given stream.
+- IO.readlines: Returns an array of strings, which are the lines from the given stream.
+- IO.write: Writes a given string to the given stream.
+
+This example writes a string to a file, encoding it as ISO-8859-1,
+then reads the file into a new string, encoding it as UTF-8:
+
+ s = "R\u00E9sum\u00E9"
+ path = 't.tmp'
+ ext_enc = Encoding::ISO_8859_1
+ int_enc = Encoding::UTF_8
+
+ File.write(path, s, external_encoding: ext_enc)
+ raw_text = File.binread(path)
+
+ transcoded_text = File.read(path, external_encoding: ext_enc, internal_encoding: int_enc)
+
+ p raw_text
+ p transcoded_text
+
+Output:
+
+ "R\xE9sum\xE9"
+ "Résumé"
+
+== \Encoding Options
+
+A number of methods in the Ruby core accept keyword arguments as encoding options.
+
+Some of the options specify or utilize a _replacement_ _string_, to be used
+in certain transcoding operations.
+A replacement string may be in any encoding that can be converted
+to the encoding of the destination string.
+
+These keyword-value pairs specify encoding options:
+
+- For an invalid byte sequence:
+
+ - <tt>:invalid: nil</tt> (default): Raise exception.
+ - <tt>:invalid: :replace</tt>: Replace each invalid byte sequence
+ with the replacement string.
+
+ Examples:
+
+ s = "\x80foo\x80"
+ s.encode(Encoding::ISO_8859_3) # Raises Encoding::InvalidByteSequenceError.
+ s.encode(Encoding::ISO_8859_3, invalid: :replace) # => "?foo?"
+
+- For an undefined character:
+
+ - <tt>:undef: nil</tt> (default): Raise exception.
+ - <tt>:undef: :replace</tt>: Replace each undefined character
+ with the replacement string.
+
+ Examples:
+
+ s = "\x80foo\x80"
+ "\x80".encode(Encoding::UTF_8, Encoding::BINARY) # Raises Encoding::UndefinedConversionError.
+ s.encode(Encoding::UTF_8, Encoding::BINARY, undef: :replace) # => "�foo�"
+
+
+- Replacement string:
+
+ - <tt>:replace: nil</tt> (default): Set replacement string to default value:
+ <tt>"\uFFFD"</tt> ("�") for a Unicode encoding, <tt>'?'</tt> otherwise.
+ - <tt>:replace: some_string</tt>: Set replacement string to the given +some_string+;
+ overrides +:fallback+.
+
+ Examples:
+
+ s = "\xA5foo\xA5"
+ options = {:undef => :replace, :replace => 'xyzzy'}
+ s.encode(Encoding::UTF_8, Encoding::ISO_8859_3, **options) # => "xyzzyfooxyzzy"
+
+- Replacement fallback:
+
+ One of these may be specified:
+
+ - <tt>:fallback: nil</tt> (default): No replacement fallback.
+ - <tt>:fallback: hash_like_object</tt>: Set replacement fallback to the given
+ +hash_like_object+; the replacement string is <tt>hash_like_object[X]</tt>.
+ - <tt>:fallback: method</tt>: Set replacement fallback to the given
+ +method+; the replacement string is <tt>method(X)</tt>.
+ - <tt>:fallback: proc</tt>: Set replacement fallback to the given
+ +proc+; the replacement string is <tt>proc[X]</tt>.
+
+ Examples:
+
+ s = "\u3042foo\u3043"
+
+ hash = {"\u3042" => 'xyzzy'}
+ hash.default = 'XYZZY'
+ s.encode(Encoding::US_ASCII, fallback: hash) # => "xyzzyfooXYZZY"
+
+ def (fallback = "U+%.4X").escape(x)
+ self % x.unpack("U")
+ end
+ "\u{3042}".encode(Encoding::US_ASCII, fallback: fallback.method(:escape)) # => "U+3042"
+
+ proc = Proc.new {|x| x == "\u3042" ? 'xyzzy' : 'XYZZY' }
+ s.encode('ASCII', fallback: proc) # => "XYZZYfooXYZZY"
+
+- XML entities:
+
+ One of these may be specified:
+
+ - <tt>:xml: nil</tt> (default): No handling for XML entities.
+ - <tt>:xml: :text</tt>: Treat source text as XML;
+ replace each undefined character
+ with its upper-case hexadecimal numeric character reference,
+ except that:
+
+ - <tt>&</tt> is replaced with <tt>&amp;</tt>.
+ - <tt><</tt> is replaced with <tt>&lt;</tt>.
+ - <tt>></tt> is replaced with <tt>&gt;</tt>.
+
+ - <tt>:xml: :attr</tt>: Treat source text as XML attribute value;
+ replace each undefined character
+ with its upper-case hexadecimal numeric character reference,
+ except that:
+
+ - The replacement string <tt>r</tt> is double-quoted (<tt>"r"</tt>).
+ - Each embedded double-quote is replaced with <tt>&quot;</tt>.
+ - <tt>&</tt> is replaced with <tt>&amp;</tt>.
+ - <tt><</tt> is replaced with <tt>&lt;</tt>.
+ - <tt>></tt> is replaced with <tt>&gt;</tt>.
+
+ Examples:
+
+ s = 'foo"<&>"bar' + "\u3042"
+ s.encode(Encoding::US_ASCII, xml: :text) # => "foo\"&lt;&amp;&gt;\"bar&#x3042;"
+ s.encode(Encoding::US_ASCII, xml: :attr) # => "\"foo&quot;&lt;&amp;&gt;&quot;bar&#x3042;\""
+
+
+- Newlines:
+
+ One of these may be specified:
+
+ - <tt>:cr_newline: true</tt>: Replace each line-feed character (<tt>"\n"</tt>)
+ with a carriage-return character (<tt>"\r"</tt>).
+ - <tt>:crlf_newline: true</tt>: Replace each line-feed character (<tt>"\n"</tt>)
+ with a carriage-return/line-feed string (<tt>"\r\n"</tt>).
+ - <tt>:universal_newline: true</tt>: Replace each carriage-return
+ character (<tt>"\r"</tt>) and each carriage-return/line-feed string
+ (<tt>"\r\n"</tt>) with a line-feed character (<tt>"\n"</tt>).
+
+ Examples:
+
+ s = "\n \r \r\n" # => "\n \r \r\n"
+ s.encode(Encoding::US_ASCII, cr_newline: true) # => "\r \r \r\r"
+ s.encode(Encoding::US_ASCII, crlf_newline: true) # => "\r\n \r \r\r\n"
+ s.encode(Encoding::US_ASCII, universal_newline: true) # => "\n \n \n"
diff --git a/doc/language/exceptions.md b/doc/language/exceptions.md
new file mode 100644
index 0000000000..5f8f0ece69
--- /dev/null
+++ b/doc/language/exceptions.md
@@ -0,0 +1,521 @@
+# Exceptions
+
+Ruby code can raise exceptions.
+
+Most often, a raised exception is meant to alert the running program
+that an unusual (i.e., _exceptional_) situation has arisen,
+and may need to be handled.
+
+Code throughout the Ruby core, Ruby standard library, and Ruby gems generates exceptions
+in certain circumstances:
+
+```rb
+File.open('nope.txt') # Raises Errno::ENOENT: "No such file or directory"
+```
+
+## Raised Exceptions
+
+A raised exception transfers program execution, one way or another.
+
+### Unrescued Exceptions
+
+If an exception not _rescued_
+(see [Rescued Exceptions](#label-Rescued+Exceptions) below),
+execution transfers to code in the Ruby interpreter
+that prints a message and exits the program (or thread):
+
+```console
+$ ruby -e "raise"
+-e:1:in '<main>': unhandled exception
+```
+
+### Rescued Exceptions
+
+An <i>exception handler</i> may determine what is to happen
+when an exception is raised;
+the handler may _rescue_ an exception,
+and may prevent the program from exiting.
+
+A simple example:
+
+```rb
+begin
+ raise 'Boom!' # Raises an exception, transfers control.
+ puts 'Will not get here.'
+rescue
+ puts 'Rescued an exception.' # Control transferred to here; program does not exit.
+end
+puts 'Got here.'
+```
+
+Output:
+
+```
+Rescued an exception.
+Got here.
+```
+
+An exception handler has several elements:
+
+| Element | Use |
+|-----------------------------|------------------------------------------------------------------------------------------|
+| Begin clause. | Begins the handler and contains the code whose raised exception, if any, may be rescued. |
+| One or more rescue clauses. | Each contains "rescuing" code, which is to be executed for certain exceptions. |
+| Else clause (optional). | Contains code to be executed if no exception is raised. |
+| Ensure clause (optional). | Contains code to be executed whether or not an exception is raised, or is rescued. |
+| <tt>end</tt> statement. | Ends the handler. ` |
+
+#### Begin Clause
+
+The begin clause begins the exception handler:
+
+- May start with a `begin` statement;
+ see also [Begin-Less Exception Handlers](#label-Begin-Less+Exception+Handlers).
+- Contains code whose raised exception (if any) is covered
+ by the handler.
+- Ends with the first following `rescue` statement.
+
+#### Rescue Clauses
+
+A rescue clause:
+
+- Starts with a `rescue` statement.
+- Contains code that is to be executed for certain raised exceptions.
+- Ends with the first following `rescue`,
+ `else`, `ensure`, or `end` statement.
+
+##### Rescued Exceptions
+
+A `rescue` statement may include one or more classes
+that are to be rescued;
+if none is given, StandardError is assumed.
+
+The rescue clause rescues both the specified class
+(or StandardError if none given) or any of its subclasses;
+see [Built-In Exception Class Hierarchy](rdoc-ref:Exception@Built-In+Exception+Class+Hierarchy).
+
+```rb
+begin
+ 1 / 0 # Raises ZeroDivisionError, a subclass of StandardError.
+rescue
+ puts "Rescued #{$!.class}"
+end
+```
+
+Output:
+
+```
+Rescued ZeroDivisionError
+```
+
+If the `rescue` statement specifies an exception class,
+only that class (or one of its subclasses) is rescued;
+this example exits with a ZeroDivisionError,
+which was not rescued because it is not ArgumentError or one of its subclasses:
+
+```rb
+begin
+ 1 / 0
+rescue ArgumentError
+ puts "Rescued #{$!.class}"
+end
+```
+
+A `rescue` statement may specify multiple classes,
+which means that its code rescues an exception
+of any of the given classes (or their subclasses):
+
+```rb
+begin
+ 1 / 0
+rescue FloatDomainError, ZeroDivisionError
+ puts "Rescued #{$!.class}"
+end
+```
+
+##### Multiple Rescue Clauses
+
+An exception handler may contain multiple rescue clauses;
+in that case, the first clause that rescues the exception does so,
+and those before and after are ignored:
+
+```rb
+begin
+ Dir.open('nosuch')
+rescue Errno::ENOTDIR
+ puts "Rescued #{$!.class}"
+rescue Errno::ENOENT
+ puts "Rescued #{$!.class}"
+end
+```
+
+Output:
+
+```
+Rescued Errno::ENOENT
+```
+
+##### Capturing the Rescued \Exception
+
+A `rescue` statement may specify a variable
+whose value becomes the rescued exception
+(an instance of Exception or one of its subclasses:
+
+```rb
+begin
+ 1 / 0
+rescue => x
+ puts x.class
+ puts x.message
+end
+```
+
+Output:
+
+```
+ZeroDivisionError
+divided by 0
+```
+
+##### Global Variables
+
+Two read-only global variables always have `nil` value
+except in a rescue clause;
+they're:
+
+- `$!`: contains the rescued exception.
+- `$@`: contains its backtrace.
+
+Example:
+
+```rb
+begin
+ 1 / 0
+rescue
+ p $!
+ p $@
+end
+```
+
+Output:
+
+```
+#<ZeroDivisionError: divided by 0>
+["t.rb:2:in 'Integer#/'", "t.rb:2:in '<main>'"]
+```
+
+##### Cause
+
+In a rescue clause, the method Exception#cause returns the previous value of `$!`,
+which may be `nil`;
+elsewhere, the method returns `nil`.
+
+Example:
+
+```rb
+begin
+ raise('Boom 0')
+rescue => x0
+ puts "Exception: #{x0.inspect}; $!: #{$!.inspect}; cause: #{x0.cause.inspect}."
+ begin
+ raise('Boom 1')
+ rescue => x1
+ puts "Exception: #{x1.inspect}; $!: #{$!.inspect}; cause: #{x1.cause.inspect}."
+ begin
+ raise('Boom 2')
+ rescue => x2
+ puts "Exception: #{x2.inspect}; $!: #{$!.inspect}; cause: #{x2.cause.inspect}."
+ end
+ end
+end
+```
+
+Output:
+
+```
+Exception: #<RuntimeError: Boom 0>; $!: #<RuntimeError: Boom 0>; cause: nil.
+Exception: #<RuntimeError: Boom 1>; $!: #<RuntimeError: Boom 1>; cause: #<RuntimeError: Boom 0>.
+Exception: #<RuntimeError: Boom 2>; $!: #<RuntimeError: Boom 2>; cause: #<RuntimeError: Boom 1>.
+```
+
+#### Else Clause
+
+The `else` clause:
+
+- Starts with an `else` statement.
+- Contains code that is to be executed if no exception is raised in the begin clause.
+- Ends with the first following `ensure` or `end` statement.
+
+```rb
+begin
+ puts 'Begin.'
+rescue
+ puts 'Rescued an exception!'
+else
+ puts 'No exception raised.'
+end
+```
+
+Output:
+
+```
+Begin.
+No exception raised.
+```
+
+#### Ensure Clause
+
+The ensure clause:
+
+- Starts with an `ensure` statement.
+- Contains code that is to be executed
+ regardless of whether an exception is raised,
+ and regardless of whether a raised exception is handled.
+- Ends with the first following `end` statement.
+
+```rb
+def foo(boom: false)
+ puts 'Begin.'
+ raise 'Boom!' if boom
+rescue
+ puts 'Rescued an exception!'
+else
+ puts 'No exception raised.'
+ensure
+ puts 'Always do this.'
+end
+
+foo(boom: true)
+foo(boom: false)
+```
+
+Output:
+
+```
+Begin.
+Rescued an exception!
+Always do this.
+Begin.
+No exception raised.
+Always do this.
+```
+
+#### End Statement
+
+The `end` statement ends the handler.
+
+Code following it is reached only if any raised exception is rescued.
+
+#### Begin-Less \Exception Handlers
+
+As seen above, an exception handler may be implemented with `begin` and `end`.
+
+An exception handler may also be implemented as:
+
+- A method body:
+
+ ```rb
+ def foo(boom: false) # Serves as beginning of exception handler.
+ puts 'Begin.'
+ raise 'Boom!' if boom
+ rescue
+ puts 'Rescued an exception!'
+ else
+ puts 'No exception raised.'
+ end # Serves as end of exception handler.
+ ```
+
+- A block:
+
+ ```rb
+ Dir.chdir('.') do |dir| # Serves as beginning of exception handler.
+ raise 'Boom!'
+ rescue
+ puts 'Rescued an exception!'
+ end # Serves as end of exception handler.
+ ```
+
+#### Re-Raising an \Exception
+
+It can be useful to rescue an exception, but allow its eventual effect;
+for example, a program can rescue an exception, log data about it,
+and then "reinstate" the exception.
+
+This may be done via the `raise` method, but in a special way;
+a rescuing clause:
+
+ - Captures an exception.
+ - Does whatever is needed concerning the exception (such as logging it).
+ - Calls method `raise` with no argument,
+ which raises the rescued exception:
+
+```rb
+begin
+ 1 / 0
+rescue ZeroDivisionError
+ # Do needful things (like logging).
+ raise # Raised exception will be ZeroDivisionError, not RuntimeError.
+end
+```
+
+Output:
+
+```
+ruby t.rb
+t.rb:2:in 'Integer#/': divided by 0 (ZeroDivisionError)
+ from t.rb:2:in '<main>'
+```
+
+#### Retrying
+
+It can be useful to retry a begin clause;
+for example, if it must access a possibly-volatile resource
+(such as a web page),
+it can be useful to try the access more than once
+(in the hope that it may become available):
+
+```rb
+retries = 0
+begin
+ puts "Try ##{retries}."
+ raise 'Boom'
+rescue
+ puts "Rescued retry ##{retries}."
+ if (retries += 1) < 3
+ puts 'Retrying'
+ retry
+ else
+ puts 'Giving up.'
+ raise
+ end
+end
+```
+
+```
+Try #0.
+Rescued retry #0.
+Retrying
+Try #1.
+Rescued retry #1.
+Retrying
+Try #2.
+Rescued retry #2.
+Giving up.
+# RuntimeError ('Boom') raised.
+```
+
+Note that the retry re-executes the entire begin clause,
+not just the part after the point of failure.
+
+## Raising an \Exception
+
+Method Kernel#raise raises an exception.
+
+## Custom Exceptions
+
+To provide additional or alternate information,
+you may create custom exception classes.
+Each should be a subclass of one of the built-in exception classes
+(commonly StandardError or RuntimeError);
+see [Built-In Exception Class Hierarchy](rdoc-ref:Exception@Built-In+Exception+Class+Hierarchy).
+
+```rb
+class MyException < StandardError; end
+```
+
+## Messages
+
+Every `Exception` object has a message,
+which is a string that is set at the time the object is created;
+see Exception.new.
+
+The message cannot be changed, but you can create a similar object with a different message;
+see Exception#exception.
+
+This method returns the message as defined:
+
+- Exception#message.
+
+Two other methods return enhanced versions of the message:
+
+- Exception#detailed_message: adds exception class name, with optional highlighting.
+- Exception#full_message: adds exception class name and backtrace, with optional highlighting.
+
+Each of the two methods above accepts keyword argument `highlight`;
+if the value of keyword `highlight` is `true`,
+the returned string includes bolding and underlining ANSI codes (see below)
+to enhance the appearance of the message.
+
+Any exception class (Ruby or custom) may choose to override either of these methods,
+and may choose to interpret keyword argument <tt>highlight: true</tt>
+to mean that the returned message should contain
+[ANSI codes](https://en.wikipedia.org/wiki/ANSI_escape_code)
+that specify color, bolding, and underlining.
+
+Because the enhanced message may be written to a non-terminal device
+(e.g., into an HTML page),
+it is best to limit the ANSI codes to these widely-supported codes:
+
+- Begin font color:
+
+ | Color | ANSI Code |
+ |---------|------------------|
+ | Red | <tt>\\e[31m</tt> |
+ | Green | <tt>\\e[32m</tt> |
+ | Yellow | <tt>\\e[33m</tt> |
+ | Blue | <tt>\\e[34m</tt> |
+ | Magenta | <tt>\\e[35m</tt> |
+ | Cyan | <tt>\\e[36m</tt> |
+
+<br>
+
+- Begin font attribute:
+
+ | Attribute | ANSI Code |
+ |-----------|-----------------|
+ | Bold | <tt>\\e[1m</tt> |
+ | Underline | <tt>\\e[4m</tt> |
+
+<br>
+
+- End all of the above:
+
+ | Color | ANSI Code |
+ |-------|-----------------|
+ | Reset | <tt>\\e[0m</tt> |
+
+It's also best to craft a message that is conveniently human-readable,
+even if the ANSI codes are included "as-is"
+(rather than interpreted as font directives).
+
+## Backtraces
+
+A _backtrace_ is a record of the methods currently
+in the [call stack](https://en.wikipedia.org/wiki/Call_stack);
+each such method has been called, but has not yet returned.
+
+These methods return backtrace information:
+
+- Exception#backtrace: returns the backtrace as an array of strings or `nil`.
+- Exception#backtrace_locations: returns the backtrace as an array
+ of Thread::Backtrace::Location objects or `nil`.
+ Each Thread::Backtrace::Location object gives detailed information about a called method.
+
+By default, Ruby sets the backtrace of the exception to the location where it
+was raised.
+
+The developer might adjust this by either providing `backtrace` argument
+to Kernel#raise, or using Exception#set_backtrace.
+
+Note that:
+
+- by default, both `backtrace` and `backtrace_locations` represent the same backtrace;
+- if the developer sets the backtrace by one of the above methods to an array of
+ Thread::Backtrace::Location, they still represent the same backtrace;
+- if the developer sets the backtrace to a string or an array of strings:
+ - by Kernel#raise: `backtrace_locations` become `nil`;
+ - by Exception#set_backtrace: `backtrace_locations` preserve the original
+ value;
+- if the developer sets the backtrace to `nil` by Exception#set_backtrace,
+ `backtrace_locations` preserve the original value; but if the exception is then
+ reraised, both `backtrace` and `backtrace_locations` become the location of reraise.
diff --git a/doc/language/fiber.md b/doc/language/fiber.md
new file mode 100644
index 0000000000..d9011cce2f
--- /dev/null
+++ b/doc/language/fiber.md
@@ -0,0 +1,290 @@
+# 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.
+
+```rb
+#!/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:
+
+```rb
+Fiber.set_scheduler(MyScheduler.new)
+```
+
+When the thread exits, there is an implicit call to `set_scheduler`:
+
+```rb
+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.
+
+```rb
+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.
+
+```rb
+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:
+
+```rb
+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:
+
+```rb
+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.
+
+##### `IO#close`
+
+Closing an IO interrupts all blocking operations on that IO. When a thread calls `IO#close`, it first attempts to interrupt any threads or fibers that are blocked on that IO. The closing thread waits until all blocked threads and fibers have been properly interrupted and removed from the IO's blocking list. Each interrupted thread or fiber receives an `IOError` and is cleanly removed from the blocking operation. Only after all blocking operations have been interrupted and cleaned up will the actual file descriptor be closed, ensuring proper resource cleanup and preventing potential race conditions.
+
+For fibers managed by a scheduler, the interruption process involves calling `rb_fiber_scheduler_fiber_interrupt` on the scheduler. This allows the scheduler to handle the interruption in a way that's appropriate for its event loop implementation. The scheduler can then notify the fiber, which will receive an `IOError` and be removed from the blocking operation. This mechanism ensures that fiber-based concurrency works correctly with IO operations, even when those operations are interrupted by `IO#close`.
+
+```mermaid
+sequenceDiagram
+ participant ThreadB
+ participant ThreadA
+ participant Scheduler
+ participant IO
+ participant Fiber1
+ participant Fiber2
+
+ Note over ThreadA: Thread A has a fiber scheduler
+ activate Scheduler
+ ThreadA->>Fiber1: Schedule Fiber 1
+ activate Fiber1
+ Fiber1->>IO: IO.read
+ IO->>Scheduler: rb_thread_io_blocking_region
+ deactivate Fiber1
+
+ ThreadA->>Fiber2: Schedule Fiber 2
+ activate Fiber2
+ Fiber2->>IO: IO.read
+ IO->>Scheduler: rb_thread_io_blocking_region
+ deactivate Fiber2
+
+ Note over Fiber1,Fiber2: Both fibers blocked on same IO
+
+ Note over ThreadB: IO.close
+ activate ThreadB
+ ThreadB->>IO: thread_io_close_notify_all
+ Note over ThreadB: rb_mutex_sleep
+
+ IO->>Scheduler: rb_fiber_scheduler_fiber_interrupt(Fiber1)
+ Scheduler->>Fiber1: fiber_interrupt with IOError
+ activate Fiber1
+ Note over IO: fiber_interrupt causes removal from blocking list
+ Fiber1->>IO: rb_io_blocking_operation_exit()
+ IO-->>ThreadB: Wakeup thread
+ deactivate Fiber1
+
+ IO->>Scheduler: rb_fiber_scheduler_fiber_interrupt(Fiber2)
+ Scheduler->>Fiber2: fiber_interrupt with IOError
+ activate Fiber2
+ Note over IO: fiber_interrupt causes removal from blocking list
+ Fiber2->>IO: rb_io_blocking_operation_exit()
+ IO-->>ThreadB: Wakeup thread
+ deactivate Fiber2
+ deactivate Scheduler
+
+ Note over ThreadB: Blocking operations list empty
+ ThreadB->>IO: close(fd)
+ deactivate ThreadB
+```
+
+#### Mutex
+
+The `Mutex` class can be used in a non-blocking context and is fiber specific.
+
+#### 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/doc/language/format_specifications.rdoc b/doc/language/format_specifications.rdoc
new file mode 100644
index 0000000000..a59f210377
--- /dev/null
+++ b/doc/language/format_specifications.rdoc
@@ -0,0 +1,354 @@
+= Format Specifications
+
+Several Ruby core classes have instance method +printf+ or +sprintf+:
+
+- ARGF#printf
+- IO#printf
+- Kernel#printf
+- Kernel#sprintf
+
+Each of these methods takes:
+
+- Argument +format_string+, which has zero or more
+ embedded _format_ _specifications_ (see below).
+- Arguments <tt>*arguments</tt>, which are zero or more objects to be formatted.
+
+Each of these methods prints or returns the string
+resulting from replacing each
+format specification embedded in +format_string+ with a string form
+of the corresponding argument among +arguments+.
+
+A simple example:
+
+ sprintf('Name: %s; value: %d', 'Foo', 0) # => "Name: Foo; value: 0"
+
+A format specification has the form:
+
+ %[flags][width][.precision]type
+
+It consists of:
+
+- A leading percent character.
+- Zero or more _flags_ (each is a character).
+- An optional _width_ _specifier_ (an integer, or <tt>*</tt>).
+- An optional _precision_ _specifier_ (a period followed by a non-negative
+ integer, or <tt>*</tt>).
+- A _type_ _specifier_ (a character).
+
+Except for the leading percent character,
+the only required part is the type specifier, so we begin with that.
+
+== Type Specifiers
+
+This section provides a brief explanation of each type specifier.
+The links lead to the details and examples.
+
+=== \Integer Type Specifiers
+
+- +b+ or +B+: Format +argument+ as a binary integer.
+ See {Specifiers b and B}[rdoc-ref:@Specifiers+b+and+B].
+- +d+, +i+, or +u+ (all are identical):
+ Format +argument+ as a decimal integer.
+ See {Specifier d}[rdoc-ref:@Specifier+d].
+- +o+: Format +argument+ as an octal integer.
+ See {Specifier o}[rdoc-ref:@Specifier+o].
+- +x+ or +X+: Format +argument+ as a hexadecimal integer.
+ See {Specifiers x and X}[rdoc-ref:@Specifiers+x+and+X].
+
+=== Floating-Point Type Specifiers
+
+- +a+ or +A+: Format +argument+ as hexadecimal floating-point number.
+ See {Specifiers a and A}[rdoc-ref:@Specifiers+a+and+A].
+- +e+ or +E+: Format +argument+ in scientific notation.
+ See {Specifiers e and E}[rdoc-ref:@Specifiers+e+and+E].
+- +f+: Format +argument+ as a decimal floating-point number.
+ See {Specifier f}[rdoc-ref:@Specifier+f].
+- +g+ or +G+: Format +argument+ in a "general" format.
+ See {Specifiers g and G}[rdoc-ref:@Specifiers+g+and+G].
+
+=== Other Type Specifiers
+
+- +c+: Format +argument+ as a character.
+ See {Specifier c}[rdoc-ref:@Specifier+c].
+- +p+: Format +argument+ as a string via <tt>argument.inspect</tt>.
+ See {Specifier p}[rdoc-ref:@Specifier+p].
+- +s+: Format +argument+ as a string via <tt>argument.to_s</tt>.
+ See {Specifier s}[rdoc-ref:@Specifier+s].
+- <tt>%</tt>: Format +argument+ (<tt>'%'</tt>) as a single percent character.
+ See {Specifier %}[rdoc-ref:@Specifier+-25].
+
+== Flags
+
+The effect of a flag may vary greatly among type specifiers.
+These remarks are general in nature.
+See {type-specific details}[rdoc-ref:@Type+Specifier+Details+and+Examples].
+
+Multiple flags may be given with single type specifier;
+order does not matter.
+
+=== <tt>' '</tt> Flag
+
+Insert a space before a non-negative number:
+
+ sprintf('%d', 10) # => "10"
+ sprintf('% d', 10) # => " 10"
+
+Insert a minus sign for negative value:
+
+ sprintf('%d', -10) # => "-10"
+ sprintf('% d', -10) # => "-10"
+
+=== <tt>'#'</tt> Flag
+
+Use an alternate format; varies among types:
+
+ sprintf('%x', 100) # => "64"
+ sprintf('%#x', 100) # => "0x64"
+
+=== <tt>'+'</tt> Flag
+
+Add a leading plus sign for a non-negative number:
+
+ sprintf('%x', 100) # => "64"
+ sprintf('%+x', 100) # => "+64"
+
+=== <tt>'-'</tt> Flag
+
+Left justify the value in its field:
+
+ sprintf('%6d', 100) # => " 100"
+ sprintf('%-6d', 100) # => "100 "
+
+=== <tt>'0'</tt> Flag
+
+Left-pad with zeros instead of spaces:
+
+ sprintf('%6d', 100) # => " 100"
+ sprintf('%06d', 100) # => "000100"
+
+=== <tt>'n$'</tt> Flag
+
+Format the (1-based) <tt>n</tt>th argument into this field:
+
+ sprintf("%s %s", 'world', 'hello') # => "world hello"
+ sprintf("%2$s %1$s", 'world', 'hello') # => "hello world"
+
+== Width Specifier
+
+In general, a width specifier determines the minimum width (in characters)
+of the formatted field:
+
+ sprintf('%10d', 100) # => " 100"
+
+ # Left-justify if negative.
+ sprintf('%-10d', 100) # => "100 "
+
+ # Ignore if too small.
+ sprintf('%1d', 100) # => "100"
+
+If the width specifier is <tt>'*'</tt> instead of an integer, the actual minimum
+width is taken from the argument list:
+
+ sprintf('%*d', 20, 14) # => " 14"
+
+== Precision Specifier
+
+A precision specifier is a decimal point followed by zero or more
+decimal digits.
+
+For integer type specifiers, the precision specifies the minimum number of
+digits to be written. If the precision is shorter than the integer, the result is
+padded with leading zeros. There is no modification or truncation of the result
+if the integer is longer than the precision:
+
+ sprintf('%.3d', 1) # => "001"
+ sprintf('%.3d', 1000) # => "1000"
+
+ # If the precision is 0 and the value is 0, nothing is written
+ sprintf('%.d', 0) # => ""
+ sprintf('%.0d', 0) # => ""
+
+For the +a+/+A+, +e+/+E+, +f+/+F+ specifiers, the precision specifies
+the number of digits after the decimal point to be written:
+
+ sprintf('%.2f', 3.14159) # => "3.14"
+ sprintf('%.10f', 3.14159) # => "3.1415900000"
+
+ # With no precision specifier, defaults to 6-digit precision.
+ sprintf('%f', 3.14159) # => "3.141590"
+
+For the +g+/+G+ specifiers, the precision specifies
+the number of significant digits to be written:
+
+ sprintf('%.2g', 123.45) # => "1.2e+02"
+ sprintf('%.3g', 123.45) # => "123"
+ sprintf('%.10g', 123.45) # => "123.45"
+
+ # With no precision specifier, defaults to 6 significant digits.
+ sprintf('%g', 123.456789) # => "123.457"
+
+For the +s+, +p+ specifiers, the precision specifies
+the number of characters to write:
+
+ sprintf('%s', Time.now) # => "2022-05-04 11:59:16 -0400"
+ sprintf('%.10s', Time.now) # => "2022-05-04"
+
+If the precision specifier is <tt>'*'</tt> instead of a non-negative integer,
+the actual precision is taken from the argument list:
+
+ sprintf('%.*d', 20, 1) # => "00000000000000000001"
+
+== Type Specifier Details and Examples
+
+=== Specifiers +a+ and +A+
+
+Format +argument+ as hexadecimal floating-point number:
+
+ sprintf('%a', 3.14159) # => "0x1.921f9f01b866ep+1"
+ sprintf('%a', -3.14159) # => "-0x1.921f9f01b866ep+1"
+ sprintf('%a', 4096) # => "0x1p+12"
+ sprintf('%a', -4096) # => "-0x1p+12"
+
+ # Capital 'A' means that alphabetical characters are printed in upper case.
+ sprintf('%A', 4096) # => "0X1P+12"
+ sprintf('%A', -4096) # => "-0X1P+12"
+
+=== Specifiers +b+ and +B+
+
+The two specifiers +b+ and +B+ behave identically
+except when flag <tt>'#'</tt>+ is used.
+
+Format +argument+ as a binary integer:
+
+ sprintf('%b', 1) # => "1"
+ sprintf('%b', 4) # => "100"
+
+ # Prefix '..' for negative value.
+ sprintf('%b', -4) # => "..100"
+
+ # Alternate format.
+ sprintf('%#b', 4) # => "0b100"
+ sprintf('%#B', 4) # => "0B100"
+
+=== Specifier +c+
+
+Format +argument+ as a single character:
+
+ sprintf('%c', 'A') # => "A"
+ sprintf('%c', 65) # => "A"
+
+This behaves like String#<<, except for raising ArgumentError instead of RangeError.
+
+=== Specifier +d+
+
+Format +argument+ as a decimal integer:
+
+ sprintf('%d', 100) # => "100"
+ sprintf('%d', -100) # => "-100"
+
+Flag <tt>'#'</tt> does not apply.
+
+=== Specifiers +e+ and +E+
+
+Format +argument+ in
+{scientific notation}[https://en.wikipedia.org/wiki/Scientific_notation]:
+
+ sprintf('%e', 3.14159) # => "3.141590e+00"
+ sprintf('%E', -3.14159) # => "-3.141590E+00"
+
+=== Specifier +f+
+
+Format +argument+ as a floating-point number:
+
+ sprintf('%f', 3.14159) # => "3.141590"
+ sprintf('%f', -3.14159) # => "-3.141590"
+
+Flag <tt>'#'</tt> does not apply.
+
+=== Specifiers +g+ and +G+
+
+Format +argument+ using exponential form (+e+/+E+ specifier)
+if the exponent is less than -4 or greater than or equal to the precision.
+Otherwise format +argument+ using floating-point form (+f+ specifier):
+
+ sprintf('%g', 100) # => "100"
+ sprintf('%g', 100.0) # => "100"
+ sprintf('%g', 3.14159) # => "3.14159"
+ sprintf('%g', 100000000000) # => "1e+11"
+ sprintf('%g', 0.000000000001) # => "1e-12"
+
+ # Capital 'G' means use capital 'E'.
+ sprintf('%G', 100000000000) # => "1E+11"
+ sprintf('%G', 0.000000000001) # => "1E-12"
+
+ # Alternate format.
+ sprintf('%#g', 100000000000) # => "1.00000e+11"
+ sprintf('%#g', 0.000000000001) # => "1.00000e-12"
+ sprintf('%#G', 100000000000) # => "1.00000E+11"
+ sprintf('%#G', 0.000000000001) # => "1.00000E-12"
+
+=== Specifier +o+
+
+Format +argument+ as an octal integer.
+If +argument+ is negative, it will be formatted as a two's complement
+prefixed with +..7+:
+
+ sprintf('%o', 16) # => "20"
+
+ # Prefix '..7' for negative value.
+ sprintf('%o', -16) # => "..760"
+
+ # Prefix zero for alternate format if positive.
+ sprintf('%#o', 16) # => "020"
+ sprintf('%#o', -16) # => "..760"
+
+=== Specifier +p+
+
+Format +argument+ as a string via <tt>argument.inspect</tt>:
+
+ t = Time.now
+ sprintf('%p', t) # => "2022-05-01 13:42:07.1645683 -0500"
+
+=== Specifier +s+
+
+Format +argument+ as a string via <tt>argument.to_s</tt>:
+
+ t = Time.now
+ sprintf('%s', t) # => "2022-05-01 13:42:07 -0500"
+
+Flag <tt>'#'</tt> does not apply.
+
+=== Specifiers +x+ and +X+
+
+Format +argument+ as a hexadecimal integer.
+If +argument+ is negative, it will be formatted as a two's complement
+prefixed with +..f+:
+
+ sprintf('%x', 100) # => "64"
+
+ # Prefix '..f' for negative value.
+ sprintf('%x', -100) # => "..f9c"
+
+ # Use alternate format.
+ sprintf('%#x', 100) # => "0x64"
+
+ # Alternate format for negative value.
+ sprintf('%#x', -100) # => "0x..f9c"
+
+=== Specifier <tt>%</tt>
+
+Format +argument+ (<tt>'%'</tt>) as a single percent character:
+
+ sprintf('%d %%', 100) # => "100 %"
+
+Flags do not apply.
+
+== Reference by Name
+
+For more complex formatting, Ruby supports a reference by name.
+%<name>s style uses format style, but %{name} style doesn't.
+
+Examples:
+
+ sprintf("%<foo>d : %<bar>f", { :foo => 1, :bar => 2 }) # => 1 : 2.000000
+ sprintf("%{foo}f", { :foo => 1 }) # => "1f"
diff --git a/doc/language/globals.md b/doc/language/globals.md
new file mode 100644
index 0000000000..ece950d3d8
--- /dev/null
+++ b/doc/language/globals.md
@@ -0,0 +1,610 @@
+# Pre-Defined Global Variables
+
+Some of the pre-defined global variables have synonyms
+that are available via module English.
+For each of those, the \English synonym is given.
+
+To use the module:
+
+```ruby
+require 'English'
+```
+
+## In Brief
+
+### Exceptions
+
+| Variable | \English | Contains | Initially | Read-Only | Reset By |
+|:--------:|:-----------------:|----------------------------------------|:---------:|:---------:|--------------|
+| `$!` | `$ERROR_INFO` | \Exception object or `nil` | `nil` | Yes | Kernel#raise |
+| `$@` | `$ERROR_POSITION` | \Array of backtrace positions or `nil` | `nil` | Yes | Kernel#raise |
+
+### Matched \Data
+
+| Variable | \English | Contains | Initially | Read-Only | Reset By |
+|:---------:|:-------------------:|-----------------------------------|:---------:|:---------:|-----------------|
+| `$~` | `$LAST_MATCH_INFO` | \MatchData object or `nil` | `nil` | No | Matcher methods |
+| `$&` | `$MATCH` | Matched substring or `nil` | `nil` | No | Matcher methods |
+| `` $` `` | `$PRE_MATCH` | Substring left of match or `nil` | `nil` | No | Matcher methods |
+| `$'` | `$POST_MATCH` | Substring right of match or `nil` | `nil` | No | Matcher methods |
+| `$+` | `$LAST_PAREN_MATCH` | Last group matched or `nil` | `nil` | No | Matcher methods |
+| `$1` | | First group matched or `nil` | `nil` | Yes | Matcher methods |
+| `$2` | | Second group matched or `nil` | `nil` | Yes | Matcher methods |
+| `$n` | | <i>n</i>th group matched or `nil` | `nil` | Yes | Matcher methods |
+
+### Separators
+
+| Variable | \English | Contains | Initially | Read-Only | Reset By |
+|:-----------:|:---------------------------:|-------------------------|:---------:|:---------:|----------|
+| `$/`, `$-0` | `$INPUT_RECORD_SEPARATOR` | Input record separator | Newline | No | |
+| `$\` | `$OUTPUT_RECORD_SEPARATOR` | Output record separator | `nil` | No | |
+
+### Streams
+
+| Variable | \English | Contains | Initially | Read-Only | Reset By |
+|:---------:|:----------------------------:|---------------------------------------------|:---------:|:---------:|----------------------|
+| `$stdin` | | Standard input stream | `STDIN` | No | |
+| `$stdout` | | Standard output stream | `STDOUT` | No | |
+| `$stderr` | | Standard error stream | `STDERR` | No | |
+| `$<` | `$DEFAULT_INPUT` | Default standard input | `ARGF` | Yes | |
+| `$>` | `$DEFAULT_OUTPUT` | Default standard output | `STDOUT` | No | |
+| `$.` | `$INPUT_LINE_NUMBER`, `$NR` | Input position of most recently read stream | 0 | No | Certain read methods |
+| `$_` | `$LAST_READ_LINE` | String from most recently read stream | `nil` | No | Certain read methods |
+
+### Processes
+
+| Variable | \English | Contains | Initially | Read-Only | Reset By |
+|:-------------------------:|:----------------------:|---------------------------------|:-------------:|:---------:|----------|
+| `$0`, `$PROGRAM_NAME` | | Program name | Program name | No | |
+| `$*` | `$ARGV` | \ARGV array | `ARGV` | Yes | |
+| `$$` | `$PROCESS_ID`, `$PID` | Process id | Process PID | Yes | |
+| `$?` | `$CHILD_STATUS` | Status of recently exited child | `nil` | Yes | |
+| `$LOAD_PATH`, `$:`, `$-I` | | \Array of search paths | Ruby defaults | Yes | |
+| `$LOADED_FEATURES`, `$"` | | \Array of load paths | Ruby defaults | Yes | |
+
+### Debugging
+
+| Variable | \English | Contains | Initially | Read-Only | Reset By |
+|:-----------:|:--------:|--------------------------------------------|:----------------------------:|:---------:|----------|
+| `$FILENAME` | | Value returned by method `ARGF.filename` | Command-line argument or '-' | Yes | |
+| `$DEBUG` | | Whether option `-d` or `--debug` was given | Command-line option | No | |
+| `$VERBOSE` | | Whether option `-V` or `-W` was given | Command-line option | No | |
+
+### Other Variables
+
+| Variable | \English | Contains | Initially | Read-Only | Reset By |
+|:-----------:|:--------:|-----------------------------------------------|:---------:|:---------:|----------|
+| `$-F`, `$;` | | Separator given with command-line option `-F` | | | |
+| `$-a` | | Whether option `-a` was given | | Yes | |
+| `$-i` | | Extension given with command-line option `-i` | | No | |
+| `$-l` | | Whether option `-l` was given | | Yes | |
+| `$-p` | | Whether option `-p` was given | | Yes | |
+| `$F` | | \Array of `$_` split by `$-F` | | | |
+
+## Exceptions
+
+### `$!` (\Exception)
+
+Contains the Exception object set by Kernel#raise:
+
+```ruby
+begin
+ raise RuntimeError.new('Boo!')
+rescue RuntimeError
+ p $!
+end
+```
+
+Output:
+
+```
+#<RuntimeError: Boo!>
+```
+
+English - `$ERROR_INFO`
+
+### `$@` (Backtrace)
+
+Same as `$!.backtrace`;
+returns an array of backtrace positions:
+
+```ruby
+begin
+ raise RuntimeError.new('Boo!')
+rescue RuntimeError
+ pp $@.take(4)
+end
+```
+
+Output:
+
+```
+["(irb):338:in `<top (required)>'",
+ "/snap/ruby/317/lib/ruby/3.2.0/irb/workspace.rb:119:in `eval'",
+ "/snap/ruby/317/lib/ruby/3.2.0/irb/workspace.rb:119:in `evaluate'",
+ "/snap/ruby/317/lib/ruby/3.2.0/irb/context.rb:502:in `evaluate'"]
+```
+
+English - `$ERROR_POSITION`.
+
+## Matched \Data
+
+These global variables store information about the most recent
+successful match in the current scope.
+
+For details and examples,
+see {Regexp Global Variables}[rdoc-ref:Regexp@Global+Variables].
+
+### `$~` (\MatchData)
+
+MatchData object created from the match;
+thread-local and frame-local.
+
+English - `$LAST_MATCH_INFO`.
+
+### `$&` (Matched Substring)
+
+The matched string.
+
+English - `$MATCH`.
+
+### `` $` `` (Pre-Match Substring)
+The string to the left of the match.
+
+English - `$PREMATCH`.
+
+### `$'` (Post-Match Substring)
+
+The string to the right of the match.
+
+English - `$POSTMATCH`.
+
+### `$+` (Last Matched Group)
+
+The last group matched.
+
+English - `$LAST_PAREN_MATCH`.
+
+### `$1`, `$2`, \Etc. (Matched Group)
+
+For <tt>$n</tt> the <i>n</i>th group of the match.
+
+No \English.
+
+## Separators
+
+### `$/` (Input Record Separator)
+
+An input record separator, initially newline.
+Set by the [command-line option `-0`].
+
+Setting to non-nil value by other than the command-line option is
+deprecated.
+
+English - `$INPUT_RECORD_SEPARATOR`, `$RS`.
+
+Aliased as `$-0`.
+
+### `$\` (Output Record Separator)
+
+An output record separator, initially `nil`.
+
+Copied from `$/` when the [command-line option `-l`] is
+given.
+
+Setting to non-nil value by other than the command-line option is
+deprecated.
+
+English - `$OUTPUT_RECORD_SEPARATOR`, `$ORS`.
+
+## Streams
+
+### `$stdin` (Standard Input)
+
+The current standard input stream; initially:
+
+```ruby
+$stdin # => #<IO:<STDIN>>
+```
+
+### `$stdout` (Standard Output)
+
+The current standard output stream; initially:
+
+```ruby
+$stdout # => #<IO:<STDOUT>>
+```
+
+### `$stderr` (Standard Error)
+
+The current standard error stream; initially:
+
+```ruby
+$stderr # => #<IO:<STDERR>>
+```
+
+### `$<` (\ARGF or $stdin)
+
+Points to stream ARGF if not empty, else to stream $stdin; read-only.
+
+English - `$DEFAULT_INPUT`.
+
+### `$>` (Default Standard Output)
+
+An output stream, initially `$stdout`.
+
+English - `$DEFAULT_OUTPUT`
+
+### `$.` (Input Position)
+
+The input position (line number) in the most recently read stream.
+
+English - `$INPUT_LINE_NUMBER`, `$NR`
+
+### `$_` (Last Read Line)
+
+The line (string) from the most recently read stream.
+
+English - `$LAST_READ_LINE`.
+
+## Processes
+
+### `$0`
+
+Initially, contains the name of the script being executed;
+may be reassigned.
+
+### `$*` (\ARGV)
+
+Points to ARGV.
+
+English - `$ARGV`.
+
+### `$$` (Process ID)
+
+The process ID of the current process. Same as Process.pid.
+
+English - `$PROCESS_ID`, `$PID`.
+
+### `$?` (Child Status)
+
+Initially `nil`, otherwise the Process::Status object
+created for the most-recently exited child process;
+thread-local.
+
+English - `$CHILD_STATUS`.
+
+### `$LOAD_PATH` (Load Path)
+
+Contains the array of paths to be searched
+by Kernel#load and Kernel#require.
+
+Singleton method `$LOAD_PATH.resolve_feature_path(feature)`
+returns:
+
+- <tt>[:rb, path]</tt>, where `path` is the path to the Ruby file to be
+ loaded for the given `feature`.
+- <tt>[:so, path]</tt>, where `path` is the path to the shared object file
+ to be loaded for the given `feature`.
+- `nil` if there is no such `feature` and `path`.
+
+Examples:
+
+```ruby
+$LOAD_PATH.resolve_feature_path('timeout')
+# => [:rb, "/snap/ruby/317/lib/ruby/3.2.0/timeout.rb"]
+$LOAD_PATH.resolve_feature_path('date_core')
+# => [:so, "/snap/ruby/317/lib/ruby/3.2.0/x86_64-linux/date_core.so"]
+$LOAD_PATH.resolve_feature_path('foo')
+# => nil
+```
+
+Aliased as `$:` and `$-I`.
+
+### `$LOADED_FEATURES`
+
+Contains an array of the paths to the loaded files:
+
+```ruby
+$LOADED_FEATURES.take(10)
+# =>
+["enumerator.so",
+ "thread.rb",
+ "fiber.so",
+ "rational.so",
+ "complex.so",
+ "ruby2_keywords.rb",
+ "/snap/ruby/317/lib/ruby/3.2.0/x86_64-linux/enc/encdb.so",
+ "/snap/ruby/317/lib/ruby/3.2.0/x86_64-linux/enc/trans/transdb.so",
+ "/snap/ruby/317/lib/ruby/3.2.0/x86_64-linux/rbconfig.rb",
+ "/snap/ruby/317/lib/ruby/3.2.0/rubygems/compatibility.rb"]
+```
+
+Aliased as `$"`.
+
+## Debugging
+
+### `$FILENAME`
+
+The value returned by method ARGF.filename.
+
+### `$DEBUG`
+
+Initially `true` if [command-line option `-d`] or
+[`--debug`][command-line option `-d`] is given, otherwise initially `false`;
+may be set to either value in the running program.
+
+When `true`, prints each raised exception to `$stderr`.
+
+Aliased as `$-d`.
+
+### `$VERBOSE`
+
+Initially `true` if [command-line option `-v`] or
+[`-w`][command-line option `-w`] is given, otherwise initially `false`;
+may be set to either value, or to `nil`, in the running program.
+
+When `true`, enables Ruby warnings.
+
+When `nil`, disables warnings, including those from Kernel#warn.
+
+Aliased as `$-v` and `$-w`.
+
+## Other Variables
+
+### `$-F`
+
+The default field separator in String#split; must be a String or a
+Regexp, and can be set with [command-line option `-F`].
+
+Setting to non-nil value by other than the command-line option is
+deprecated.
+
+Aliased as `$;`.
+
+### `$-a`
+
+Whether [command-line option `-a`] was given; read-only.
+
+### `$-i`
+
+Contains the extension given with [command-line option `-i`],
+or `nil` if none.
+
+An alias of ARGF.inplace_mode.
+
+### `$-l`
+
+Whether [command-line option `-l`] was set; read-only.
+
+### `$-p`
+
+Whether [command-line option `-p`] was given; read-only.
+
+### `$F`
+
+If the [command-line option `-a`] is given, the array
+obtained by splitting `$_` by `$-F` is assigned at the start of each
+`-l`/`-p` loop.
+
+## Deprecated
+
+### `$=`
+
+### `$,`
+
+# Pre-Defined Global Constants
+
+## Summary
+
+### Streams
+
+| Constant | Contains |
+|:--------:|-------------------------|
+| `STDIN` | Standard input stream. |
+| `STDOUT` | Standard output stream. |
+| `STDERR` | Standard error stream. |
+
+### Environment
+
+| Constant | Contains |
+|-----------------------|-------------------------------------------------------------------------------|
+| `ENV` | Hash of current environment variable names and values. |
+| `ARGF` | String concatenation of files given on the command line, or `$stdin` if none. |
+| `ARGV` | Array of the given command-line arguments. |
+| `TOPLEVEL_BINDING` | Binding of the top level scope. |
+| `RUBY_VERSION` | String Ruby version. |
+| `RUBY_RELEASE_DATE` | String Ruby release date. |
+| `RUBY_PLATFORM` | String Ruby platform. |
+| `RUBY_PATCH_LEVEL` | String Ruby patch level. |
+| `RUBY_REVISION` | String Ruby revision. |
+| `RUBY_COPYRIGHT` | String Ruby copyright. |
+| `RUBY_ENGINE` | String Ruby engine. |
+| `RUBY_ENGINE_VERSION` | String Ruby engine version. |
+| `RUBY_DESCRIPTION` | String Ruby description. |
+
+### Embedded \Data
+
+| Constant | Contains |
+|:---------------------:|-------------------------------------------------------------------------------|
+| `DATA` | File containing embedded data (lines following `__END__`, if any). |
+
+## Streams
+
+### `STDIN`
+
+The standard input stream (the default value for `$stdin`):
+
+```ruby
+STDIN # => #<IO:<STDIN>>
+```
+
+### `STDOUT`
+
+The standard output stream (the default value for `$stdout`):
+
+```ruby
+STDOUT # => #<IO:<STDOUT>>
+```
+
+### `STDERR`
+
+The standard error stream (the default value for `$stderr`):
+
+```ruby
+STDERR # => #<IO:<STDERR>>
+```
+
+## Environment
+
+### `ENV`
+
+A hash of the contains current environment variables names and values:
+
+```ruby
+ENV.take(5)
+# =>
+[["COLORTERM", "truecolor"],
+ ["DBUS_SESSION_BUS_ADDRESS", "unix:path=/run/user/1000/bus"],
+ ["DESKTOP_SESSION", "ubuntu"],
+ ["DISPLAY", ":0"],
+ ["GDMSESSION", "ubuntu"]]
+```
+
+### `ARGF`
+
+The virtual concatenation of the files given on the command line, or from
+`$stdin` if no files were given, `"-"` is given, or after
+all files have been read.
+
+### `ARGV`
+
+An array of the given command-line arguments.
+
+### `TOPLEVEL_BINDING`
+
+The Binding of the top level scope:
+
+```ruby
+TOPLEVEL_BINDING # => #<Binding:0x00007f58da0da7c0>
+```
+
+### `RUBY_VERSION`
+
+The Ruby version:
+
+```ruby
+RUBY_VERSION # => "3.2.2"
+```
+
+### `RUBY_RELEASE_DATE`
+
+The release date string:
+
+```ruby
+RUBY_RELEASE_DATE # => "2023-03-30"
+```
+
+### `RUBY_PLATFORM`
+
+The platform identifier:
+
+```ruby
+RUBY_PLATFORM # => "x86_64-linux"
+```
+
+### `RUBY_PATCHLEVEL`
+
+The integer patch level for this Ruby:
+
+```ruby
+RUBY_PATCHLEVEL # => 53
+```
+
+For a development build the patch level will be -1.
+
+### `RUBY_REVISION`
+
+The git commit hash for this Ruby:
+
+```ruby
+RUBY_REVISION # => "e51014f9c05aa65cbf203442d37fef7c12390015"
+```
+
+### `RUBY_COPYRIGHT`
+
+The copyright string:
+
+```ruby
+RUBY_COPYRIGHT
+# => "ruby - Copyright (C) 1993-2023 Yukihiro Matsumoto"
+```
+
+### `RUBY_ENGINE`
+
+The name of the Ruby implementation:
+
+```ruby
+RUBY_ENGINE # => "ruby"
+```
+
+### `RUBY_ENGINE_VERSION`
+
+The version of the Ruby implementation:
+
+```ruby
+RUBY_ENGINE_VERSION # => "3.2.2"
+```
+
+### `RUBY_DESCRIPTION`
+
+The description of the Ruby implementation:
+
+```ruby
+RUBY_DESCRIPTION
+# => "ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-linux]"
+```
+
+## Embedded \Data
+
+### `DATA`
+
+Defined if and only if the program has this line:
+
+```ruby
+__END__
+```
+
+When defined, `DATA` is a File object
+containing the lines following the `__END__`,
+positioned at the first of those lines:
+
+```ruby
+p DATA
+DATA.each_line { |line| p line }
+__END__
+Foo
+Bar
+Baz
+```
+
+Output:
+
+```
+#<File:t.rb>
+"Foo\n"
+"Bar\n"
+"Baz\n"
+```
+
+
+[command-line option `-0`]: rdoc-ref:language/options.md@0-3A+Set+-24-2F+-28Input+Record+Separator-29
+[command-line option `-F`]: rdoc-ref:language/options.md@F-3A+Set+Input+Field+Separator
+[command-line option `-a`]: rdoc-ref:language/options.md@a-3A+Split+Input+Lines+into+Fields
+[command-line option `-d`]: rdoc-ref:language/options.md@d-3A+Set+-24DEBUG+to+true
+[command-line option `-i`]: rdoc-ref:language/options.md@i-3A+Set+ARGF+In-Place+Mode
+[command-line option `-l`]: rdoc-ref:language/options.md@l-3A+Set+Output+Record+Separator-3B+Chop+Lines
+[command-line option `-p`]: rdoc-ref:language/options.md@p-3A+-n-2C+with+Printing
+[command-line option `-v`]: rdoc-ref:language/options.md@v-3A+Print+Version-3B+Set+-24VERBOSE
+[command-line option `-w`]: rdoc-ref:language/options.md@w-3A+Synonym+for+-W1
+
diff --git a/doc/language/hash_inclusion.rdoc b/doc/language/hash_inclusion.rdoc
new file mode 100644
index 0000000000..05c2b0932a
--- /dev/null
+++ b/doc/language/hash_inclusion.rdoc
@@ -0,0 +1,31 @@
+== \Hash Inclusion
+
+A hash is set-like in that it cannot have duplicate entries
+(or even duplicate keys).
+\Hash inclusion can therefore based on the idea of
+{subset and superset}[https://en.wikipedia.org/wiki/Subset].
+
+Two hashes may be tested for inclusion,
+based on comparisons of their entries.
+
+An entry <tt>h0[k0]</tt> in one hash
+is equal to an entry <tt>h1[k1]</tt> in another hash
+if and only if the two keys are equal (<tt>k0 == k1</tt>)
+and their two values are equal (<tt>h0[k0] == h1[h1]</tt>).
+
+A hash may be a subset or a superset of another hash:
+
+- Subset (included in or equal to another):
+
+ - \Hash +h0+ is a _subset_ of hash +h1+ (see Hash#<=)
+ if each entry in +h0+ is equal to an entry in +h1+.
+ - Further, +h0+ is a <i>proper subset</i> of +h1+ (see Hash#<)
+ if +h1+ is larger than +h0+.
+
+- Superset (including or equal to another):
+
+ - \Hash +h0+ is a _superset_ of hash +h1+ (see Hash#>=)
+ if each entry in +h1+ is equal to an entry in +h0+.
+ - Further, +h0+ is a <i>proper superset</i> of +h1+ (see Hash#>)
+ if +h0+ is larger than +h1+.
+
diff --git a/doc/implicit_conversion.rdoc b/doc/language/implicit_conversion.rdoc
index e244096125..e244096125 100644
--- a/doc/implicit_conversion.rdoc
+++ b/doc/language/implicit_conversion.rdoc
diff --git a/doc/language/marshal.rdoc b/doc/language/marshal.rdoc
new file mode 100644
index 0000000000..740064ade6
--- /dev/null
+++ b/doc/language/marshal.rdoc
@@ -0,0 +1,318 @@
+= Marshal Format
+
+The Marshal format is used to serialize ruby objects. The format can store
+arbitrary objects through three user-defined extension mechanisms.
+
+For documentation on using Marshal to serialize and deserialize objects, see
+the Marshal module.
+
+This document calls a serialized set of objects a stream. The Ruby
+implementation can load a set of objects from a String, an IO or an object
+that implements a +getc+ method.
+
+== Stream Format
+
+The first two bytes of the stream contain the major and minor version, each as
+a single byte encoding a digit. The version implemented in Ruby is 4.8
+(stored as "\x04\x08") and is supported by ruby 1.8.0 and newer.
+
+Different major versions of the Marshal format are not compatible and cannot
+be understood by other major versions. Lesser minor versions of the format
+can be understood by newer minor versions. Format 4.7 can be loaded by a 4.8
+implementation but format 4.8 cannot be loaded by a 4.7 implementation.
+
+Following the version bytes is a stream describing the serialized object. The
+stream contains nested objects (the same as a Ruby object) but objects in the
+stream do not necessarily have a direct mapping to the Ruby object model.
+
+Each object in the stream is described by a byte indicating its type followed
+by one or more bytes describing the object. When "object" is mentioned below
+it means any of the types below that defines a Ruby object.
+
+=== true, false, nil
+
+These objects are each one byte long. "T" is represents +true+, "F"
+represents +false+ and "0" represents +nil+.
+
+=== Fixnum and long
+
+"i" represents a signed 32 bit value using a packed format. One through five
+bytes follows the type. The value loaded will always be a Fixnum. On
+32 bit platforms (where the precision of a Fixnum is less than 32 bits)
+loading large values will cause overflow on CRuby.
+
+The fixnum type is used to represent both ruby Fixnum objects and the sizes of
+marshaled arrays, hashes, instance variables and other types. In the
+following sections "long" will mean the format described below, which supports
+full 32 bit precision.
+
+The first byte has the following special values:
+
+"\x00"::
+ The value of the integer is 0. No bytes follow.
+
+"\x01"::
+ The total size of the integer is two bytes. The following byte is a
+ positive integer in the range of 0 through 255. Only values between 123
+ and 255 should be represented this way to save bytes.
+
+"\xff"::
+ The total size of the integer is two bytes. The following byte is a
+ negative integer in the range of -1 through -256.
+
+"\x02"::
+ The total size of the integer is three bytes. The following two bytes are a
+ positive little-endian integer.
+
+"\xfe"::
+ The total size of the integer is three bytes. The following two bytes are a
+ negative little-endian integer.
+
+"\x03"::
+ The total size of the integer is four bytes. The following three bytes are
+ a positive little-endian integer.
+
+"\xfd"::
+ The total size of the integer is four bytes. The following three bytes are a
+ negative little-endian integer.
+
+"\x04"::
+ The total size of the integer is five bytes. The following four bytes are a
+ positive little-endian integer. For compatibility with 32 bit ruby,
+ only Fixnums less than 1073741824 should be represented this way. For sizes
+ of stream objects full precision may be used.
+
+"\xfc"::
+ 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.
+
+Otherwise the first byte is a sign-extended eight-bit value with an offset.
+If the value is positive the value is determined by subtracting 5 from the
+value. If the value is negative the value is determined by adding 5 to the
+value.
+
+There are multiple representations for many values. CRuby always outputs the
+shortest representation possible.
+
+=== Symbols and Byte Sequence
+
+":" represents a real symbol. A real symbol contains the data needed to
+define the symbol for the rest of the stream as future occurrences in the
+stream will instead be references (a symbol link) to this one. The reference
+is a zero-indexed 32 bit value (so the first occurrence of <code>:hello</code>
+is 0).
+
+Following the type byte is byte sequence which consists of a long indicating
+the number of bytes in the sequence followed by that many bytes of data. Byte
+sequences have no encoding.
+
+For example, the following stream contains the Symbol <code>:hello</code>:
+
+ "\x04\x08:\x0ahello"
+
+";" represents a Symbol link which references a previously defined Symbol.
+Following the type byte is a long containing the index in the lookup table for
+the linked (referenced) Symbol.
+
+For example, the following stream contains <code>[:hello, :hello]</code>:
+
+ "\x04\b[\a:\nhello;\x00"
+
+When a "symbol" is referenced below it may be either a real symbol or a
+symbol link.
+
+=== Object References
+
+Separate from but similar to symbol references, the stream contains only one
+copy of each object (as determined by #object_id) for all objects except
+true, false, nil, Fixnums and Symbols (which are stored separately as
+described above) a one-indexed 32 bit value will be stored and reused when the
+object is encountered again. (The first object has an index of 1).
+
+"@" represents an object link. Following the type byte is a long giving the
+index of the object.
+
+For example, the following stream contains an Array of the same
+<code>"hello"</code> object twice:
+
+ "\004\b[\a\"\nhello@\006"
+
+=== Instance Variables
+
+"I" indicates that instance variables follow the next object. An object
+follows the type byte. Following the object is a length indicating the number
+of instance variables for the object. Following the length is a set of
+name-value pairs. The names are symbols while the values are objects. The
+symbols must be instance variable names (<code>:@name</code>).
+
+An Object ("o" type, described below) uses the same format for its instance
+variables as described here.
+
+For a String and Regexp (described below) a special instance variable
+<code>:E</code> is used to indicate the Encoding.
+
+=== Extended
+
+"e" indicates that the next object is extended by a module. An object follows
+the type byte. Following the object is a symbol that contains the name of the
+module the object is extended by.
+
+=== Array
+
+"[" represents an Array. Following the type byte is a long indicating the
+number of objects in the array. The given number of objects follow the
+length.
+
+=== Bignum
+
+"l" represents a Bignum which is composed of three parts:
+
+sign::
+ A single byte containing "+" for a positive value or "-" for a negative
+ value.
+length::
+ A long indicating the number of bytes of Bignum data follows, divided by
+ two. Multiply the length by two to determine the number of bytes of data
+ that follow.
+data::
+ Bytes of Bignum data representing the number.
+
+The following ruby code will reconstruct the Bignum value from an array of
+bytes:
+
+ result = 0
+
+ bytes.each_with_index do |byte, exp|
+ result += (byte * 2 ** (exp * 8))
+ end
+
+=== +Class+ and +Module+
+
+"c" represents a +Class+ object, "m" represents a +Module+ and "M" represents
+either a class or module (this is an old-style for compatibility). No class
+or module content is included, this type is only a reference. Following the
+type byte is a byte sequence which is used to look up an existing class or
+module, respectively.
+
+Instance variables are not allowed on a class or module.
+
+If no class or module exists an exception should be raised.
+
+For "c" and "m" types, the loaded object must be a class or module,
+respectively.
+
+=== Data
+
+"d" represents a Data object. (Data objects are wrapped pointers from ruby
+extensions.) Following the type byte is a symbol indicating the class for the
+Data object and an object that contains the state of the Data object.
+
+To dump a Data object Ruby calls _dump_data. To load a Data object Ruby calls
+_load_data with the state of the object on a newly allocated instance.
+
+=== Float
+
+"f" represents a Float object. Following the type byte is a byte sequence
+containing the float value. The following values are special:
+
+"inf"::
+ Positive infinity
+
+"-inf"::
+ Negative infinity
+
+"nan"::
+ Not a Number
+
+Otherwise the byte sequence contains a C double (loadable by strtod(3)).
+Older minor versions of Marshal also stored extra mantissa bits to ensure
+portability across platforms but 4.8 does not include these. See
+[ruby-talk:69518] for some explanation.
+
+=== Hash and Hash with Default Value
+
+"{" represents a Hash object while "}" represents a Hash with a default value
+set (<code>Hash.new 0</code>). Following the type byte is a long indicating
+the number of key-value pairs in the Hash, the size. Double the given number
+of objects follow the size.
+
+For a Hash with a default value, the default value follows all the pairs.
+
+=== Module and Old Module
+
+=== Object
+
+"o" represents an object that doesn't have any other special form (such as
+a user-defined or built-in format). Following the type byte is a symbol
+containing the class name of the object. Following the class name is a long
+indicating the number of instance variable names and values for the object.
+Double the given number of pairs of objects follow the size.
+
+The keys in the pairs must be symbols containing instance variable names.
+
+=== Regular Expression
+
+"/" represents a regular expression. Following the type byte is a byte
+sequence containing the regular expression source. Following the type byte is
+a byte containing the regular expression options (case-insensitive, etc.) as a
+signed 8-bit value.
+
+Regular expressions can have an encoding attached through instance variables
+(see above). If no encoding is attached escapes for the following regexp
+specials not present in ruby 1.8 must be removed: g-m, o-q, u, y, E, F, H-L,
+N-V, X, Y.
+
+=== String
+
+'"' represents a String. Following the type byte is a byte sequence
+containing the string content. When dumped from ruby 1.9 an encoding instance
+variable (<code>:E</code> see above) should be included unless the encoding is
+binary.
+
+=== Struct
+
+"S" represents a Struct. Following the type byte is a symbol containing the
+name of the struct. Following the name is a long indicating the number of
+members in the struct. Double the number of objects follow the member count.
+Each member is a pair containing the member's symbol and an object for the
+value of that member.
+
+If the struct name does not match a Struct subclass in the running ruby an
+exception should be raised.
+
+If there is a mismatch between the struct in the currently running ruby and
+the member count in the marshaled struct an exception should be raised.
+
+=== User Class
+
+"C" represents a subclass of a String, Regexp, Array or Hash. Following the
+type byte is a symbol containing the name of the subclass. Following the name
+is the wrapped object.
+
+=== User Defined
+
+"u" represents an object with a user-defined serialization format using the
++_dump+ instance method and +_load+ class method. Following the type byte is
+a symbol containing the class name. Following the class name is a byte
+sequence containing the user-defined representation of the object.
+
+The class method +_load+ is called on the class with a string created from the
+byte-sequence.
+
+This type is not recommended for newly created classes, because of some
+restrictions:
+
+- cannot have recursive reference
+
+=== User Marshal
+
+"U" represents an object with a user-defined serialization format using the
++marshal_dump+ and +marshal_load+ instance methods. Following the type byte
+is a symbol containing the class name. Following the class name is an object
+containing the data.
+
+Upon loading a new instance must be allocated and +marshal_load+ must be
+called on the instance with the data.
+
diff --git a/doc/language/option_dump.md b/doc/language/option_dump.md
new file mode 100644
index 0000000000..a156484bf6
--- /dev/null
+++ b/doc/language/option_dump.md
@@ -0,0 +1,265 @@
+# Option `--dump`
+
+For other argument values,
+see {Option --dump}[options_md.html#label--dump-3A+Dump+Items].
+
+For the examples here, we use this program:
+
+```console
+$ cat t.rb
+puts 'Foo'
+```
+
+The supported dump items:
+
+- `insns`: Instruction sequences:
+
+ ```sh
+ $ ruby --dump=insns t.rb
+ == disasm: #<ISeq:<main>@t.rb:1 (1,0)-(1,10)> (catch: FALSE)
+ 0000 putself ( 1)[Li]
+ 0001 putstring "Foo"
+ 0003 opt_send_without_block <calldata!mid:puts, argc:1, FCALL|ARGS_SIMPLE>
+ 0005 leave
+ ```
+
+- `parsetree`: {Abstract syntax tree}[https://en.wikipedia.org/wiki/Abstract_syntax_tree]
+ (AST):
+
+ ```console
+ $ ruby --dump=parsetree t.rb
+ ###########################################################
+ ## Do NOT use this node dump for any purpose other than ##
+ ## debug and research. Compatibility is not guaranteed. ##
+ ###########################################################
+
+ # @ NODE_SCOPE (line: 1, location: (1,0)-(1,10))
+ # +- nd_tbl: (empty)
+ # +- nd_args:
+ # | (null node)
+ # +- nd_body:
+ # @ NODE_FCALL (line: 1, location: (1,0)-(1,10))*
+ # +- nd_mid: :puts
+ # +- nd_args:
+ # @ NODE_LIST (line: 1, location: (1,5)-(1,10))
+ # +- nd_alen: 1
+ # +- nd_head:
+ # | @ NODE_STR (line: 1, location: (1,5)-(1,10))
+ # | +- nd_lit: "Foo"
+ # +- nd_next:
+ # (null node)
+ ```
+
+- `yydebug`: Debugging information from yacc parser generator:
+
+ ```
+ $ ruby --dump=yydebug t.rb
+ Starting parse
+ Entering state 0
+ Reducing stack by rule 1 (line 1295):
+ lex_state: NONE -> BEG at line 1296
+ vtable_alloc:12392: 0x0000558453df1a00
+ vtable_alloc:12393: 0x0000558453df1a60
+ cmdarg_stack(push): 0 at line 12406
+ cond_stack(push): 0 at line 12407
+ -> $$ = nterm $@1 (1.0-1.0: )
+ Stack now 0
+ Entering state 2
+ Reading a token:
+ lex_state: BEG -> CMDARG at line 9049
+ Next token is token "local variable or method" (1.0-1.4: puts)
+ Shifting token "local variable or method" (1.0-1.4: puts)
+ Entering state 35
+ Reading a token: Next token is token "string literal" (1.5-1.6: )
+ Reducing stack by rule 742 (line 5567):
+ $1 = token "local variable or method" (1.0-1.4: puts)
+ -> $$ = nterm operation (1.0-1.4: )
+ Stack now 0 2
+ Entering state 126
+ Reducing stack by rule 78 (line 1794):
+ $1 = nterm operation (1.0-1.4: )
+ -> $$ = nterm fcall (1.0-1.4: )
+ Stack now 0 2
+ Entering state 80
+ Next token is token "string literal" (1.5-1.6: )
+ Reducing stack by rule 292 (line 2723):
+ cmdarg_stack(push): 1 at line 2737
+ -> $$ = nterm $@16 (1.4-1.4: )
+ Stack now 0 2 80
+ Entering state 235
+ Next token is token "string literal" (1.5-1.6: )
+ Shifting token "string literal" (1.5-1.6: )
+ Entering state 216
+ Reducing stack by rule 607 (line 4706):
+ -> $$ = nterm string_contents (1.6-1.6: )
+ Stack now 0 2 80 235 216
+ Entering state 437
+ Reading a token: Next token is token "literal content" (1.6-1.9: "Foo")
+ Shifting token "literal content" (1.6-1.9: "Foo")
+ Entering state 503
+ Reducing stack by rule 613 (line 4802):
+ $1 = token "literal content" (1.6-1.9: "Foo")
+ -> $$ = nterm string_content (1.6-1.9: )
+ Stack now 0 2 80 235 216 437
+ Entering state 507
+ Reducing stack by rule 608 (line 4716):
+ $1 = nterm string_contents (1.6-1.6: )
+ $2 = nterm string_content (1.6-1.9: )
+ -> $$ = nterm string_contents (1.6-1.9: )
+ Stack now 0 2 80 235 216
+ Entering state 437
+ Reading a token:
+ lex_state: CMDARG -> END at line 7276
+ Next token is token "terminator" (1.9-1.10: )
+ Shifting token "terminator" (1.9-1.10: )
+ Entering state 508
+ Reducing stack by rule 590 (line 4569):
+ $1 = token "string literal" (1.5-1.6: )
+ $2 = nterm string_contents (1.6-1.9: )
+ $3 = token "terminator" (1.9-1.10: )
+ -> $$ = nterm string1 (1.5-1.10: )
+ Stack now 0 2 80 235
+ Entering state 109
+ Reducing stack by rule 588 (line 4559):
+ $1 = nterm string1 (1.5-1.10: )
+ -> $$ = nterm string (1.5-1.10: )
+ Stack now 0 2 80 235
+ Entering state 108
+ Reading a token:
+ lex_state: END -> BEG at line 9200
+ Next token is token '\n' (1.10-1.10: )
+ Reducing stack by rule 586 (line 4541):
+ $1 = nterm string (1.5-1.10: )
+ -> $$ = nterm strings (1.5-1.10: )
+ Stack now 0 2 80 235
+ Entering state 107
+ Reducing stack by rule 307 (line 2837):
+ $1 = nterm strings (1.5-1.10: )
+ -> $$ = nterm primary (1.5-1.10: )
+ Stack now 0 2 80 235
+ Entering state 90
+ Next token is token '\n' (1.10-1.10: )
+ Reducing stack by rule 261 (line 2553):
+ $1 = nterm primary (1.5-1.10: )
+ -> $$ = nterm arg (1.5-1.10: )
+ Stack now 0 2 80 235
+ Entering state 220
+ Next token is token '\n' (1.10-1.10: )
+ Reducing stack by rule 270 (line 2586):
+ $1 = nterm arg (1.5-1.10: )
+ -> $$ = nterm arg_value (1.5-1.10: )
+ Stack now 0 2 80 235
+ Entering state 221
+ Next token is token '\n' (1.10-1.10: )
+ Reducing stack by rule 297 (line 2779):
+ $1 = nterm arg_value (1.5-1.10: )
+ -> $$ = nterm args (1.5-1.10: )
+ Stack now 0 2 80 235
+ Entering state 224
+ Next token is token '\n' (1.10-1.10: )
+ Reducing stack by rule 772 (line 5626):
+ -> $$ = nterm none (1.10-1.10: )
+ Stack now 0 2 80 235 224
+ Entering state 442
+ Reducing stack by rule 296 (line 2773):
+ $1 = nterm none (1.10-1.10: )
+
+ -> $$ = nterm opt_block_arg (1.10-1.10: )
+ Stack now 0 2 80 235 224
+ Entering state 441
+ Reducing stack by rule 288 (line 2696):
+ $1 = nterm args (1.5-1.10: )
+ $2 = nterm opt_block_arg (1.10-1.10: )
+ -> $$ = nterm call_args (1.5-1.10: )
+ Stack now 0 2 80 235
+ Entering state 453
+ Reducing stack by rule 293 (line 2723):
+ $1 = nterm $@16 (1.4-1.4: )
+ $2 = nterm call_args (1.5-1.10: )
+ cmdarg_stack(pop): 0 at line 2754
+ -> $$ = nterm command_args (1.4-1.10: )
+ Stack now 0 2 80
+ Entering state 333
+ Next token is token '\n' (1.10-1.10: )
+ Reducing stack by rule 79 (line 1804):
+ $1 = nterm fcall (1.0-1.4: )
+ $2 = nterm command_args (1.4-1.10: )
+ -> $$ = nterm command (1.0-1.10: )
+ Stack now 0 2
+ Entering state 81
+ Next token is token '\n' (1.10-1.10: )
+ Reducing stack by rule 73 (line 1770):
+ $1 = nterm command (1.0-1.10: )
+ -> $$ = nterm command_call (1.0-1.10: )
+ Stack now 0 2
+ Entering state 78
+ Reducing stack by rule 51 (line 1659):
+ $1 = nterm command_call (1.0-1.10: )
+ -> $$ = nterm expr (1.0-1.10: )
+ Stack now 0 2
+ Entering state 75
+ Next token is token '\n' (1.10-1.10: )
+ Reducing stack by rule 39 (line 1578):
+ $1 = nterm expr (1.0-1.10: )
+ -> $$ = nterm stmt (1.0-1.10: )
+ Stack now 0 2
+ Entering state 73
+ Next token is token '\n' (1.10-1.10: )
+ Reducing stack by rule 8 (line 1354):
+ $1 = nterm stmt (1.0-1.10: )
+ -> $$ = nterm top_stmt (1.0-1.10: )
+ Stack now 0 2
+ Entering state 72
+ Reducing stack by rule 5 (line 1334):
+ $1 = nterm top_stmt (1.0-1.10: )
+ -> $$ = nterm top_stmts (1.0-1.10: )
+ Stack now 0 2
+ Entering state 71
+ Next token is token '\n' (1.10-1.10: )
+ Shifting token '\n' (1.10-1.10: )
+ Entering state 311
+ Reducing stack by rule 769 (line 5618):
+ $1 = token '\n' (1.10-1.10: )
+ -> $$ = nterm term (1.10-1.10: )
+ Stack now 0 2 71
+ Entering state 313
+ Reducing stack by rule 770 (line 5621):
+ $1 = nterm term (1.10-1.10: )
+ -> $$ = nterm terms (1.10-1.10: )
+ Stack now 0 2 71
+ Entering state 314
+ Reading a token: Now at end of input.
+ Reducing stack by rule 759 (line 5596):
+ $1 = nterm terms (1.10-1.10: )
+ -> $$ = nterm opt_terms (1.10-1.10: )
+ Stack now 0 2 71
+ Entering state 312
+ Reducing stack by rule 3 (line 1321):
+ $1 = nterm top_stmts (1.0-1.10: )
+ $2 = nterm opt_terms (1.10-1.10: )
+ -> $$ = nterm top_compstmt (1.0-1.10: )
+ Stack now 0 2
+ Entering state 70
+ Reducing stack by rule 2 (line 1295):
+ $1 = nterm $@1 (1.0-1.0: )
+ $2 = nterm top_compstmt (1.0-1.10: )
+ vtable_free:12426: p->lvtbl->args(0x0000558453df1a00)
+ vtable_free:12427: p->lvtbl->vars(0x0000558453df1a60)
+ cmdarg_stack(pop): 0 at line 12428
+ cond_stack(pop): 0 at line 12429
+ -> $$ = nterm program (1.0-1.10: )
+ Stack now 0
+ Entering state 1
+ Now at end of input.
+ Shifting token "end-of-input" (1.10-1.10: )
+ Entering state 3
+ Stack now 0 1 3
+ Cleanup: popping token "end-of-input" (1.10-1.10: )
+ Cleanup: popping nterm program (1.0-1.10: )
+ ```
+
+Additional flags can follow dump items.
+
+- `+comment`: Add comments to AST.
+- `+error-tolerant`: Parse in error-tolerant mode.
+- `-optimize`: Disable optimizations for instruction sequences.
diff --git a/doc/language/options.md b/doc/language/options.md
new file mode 100644
index 0000000000..3421d73f55
--- /dev/null
+++ b/doc/language/options.md
@@ -0,0 +1,688 @@
+# Ruby Command-Line Options
+
+## About the Examples
+
+Some examples here use command-line option `-e`,
+which passes the Ruby code to be executed on the command line itself:
+
+```console
+$ ruby -e 'puts "Hello, World."'
+```
+
+Some examples here assume that file `desiderata.txt` exists:
+
+```console
+$ cat desiderata.txt
+Go placidly amid the noise and the haste,
+and remember what peace there may be in silence.
+As far as possible, without surrender,
+be on good terms with all persons.
+```
+
+## Options
+
+### `-0`: Set `$/` (Input Record Separator)
+
+Option `-0` defines the input record separator `$/`
+for the invoked Ruby program.
+
+The optional argument to the option must be octal digits,
+each in the range `0..7`;
+these digits are prefixed with digit `0` to form an octal value.
+
+If no argument is given, the input record separator is `0x00`.
+
+If an argument is given, it must immediately follow the option
+(no intervening whitespace or equal-sign character `'='`);
+argument values:
+
+- `0`: the input record separator is `''`;
+ see {Special Line Separator Values}[rdoc-ref:IO@Special+Line+Separator+Values].
+- In range `(1..0377)`:
+ the input record separator `$/` is set to the character value of the argument.
+- Any other octal value: the input record separator is `nil`.
+
+Examples:
+
+```console
+$ ruby -0 -e 'p $/'
+"\x00"
+ruby -00 -e 'p $/'
+""
+$ ruby -012 -e 'p $/'
+"\n"
+$ ruby -015 -e 'p $/'
+"\r"
+$ ruby -0377 -e 'p $/'
+"\xFF"
+$ ruby -0400 -e 'p $/'
+nil
+```
+
+See also:
+
+- {Option -a}[rdoc-ref:@a-3A+Split+Input+Lines+into+Fields]:
+ Split input lines into fields.
+- {Option -F}[rdoc-ref:@F-3A+Set+Input+Field+Separator]:
+ Set input field separator.
+- {Option -l}[rdoc-ref:@l-3A+Set+Output+Record+Separator-3B+Chop+Lines]:
+ Set output record separator; chop lines.
+- {Option -n}[rdoc-ref:@n-3A+Run+Program+in+gets+Loop]:
+ Run program in `gets` loop.
+- {Option -p}[rdoc-ref:@p-3A+-n-2C+with+Printing]:
+ `-n`, with printing.
+
+### `-a`: Split Input Lines into Fields
+
+Option `-a`, when given with either of options `-n` or `-p`,
+splits the string at `$_` into an array of strings at `$F`:
+
+```console
+$ ruby -an -e 'p $F' desiderata.txt
+["Go", "placidly", "amid", "the", "noise", "and", "the", "haste,"]
+["and", "remember", "what", "peace", "there", "may", "be", "in", "silence."]
+["As", "far", "as", "possible,", "without", "surrender,"]
+["be", "on", "good", "terms", "with", "all", "persons."]
+```
+
+For the splitting,
+the default record separator is `$/`,
+and the default field separator is `$;`.
+
+See also:
+
+- {Option -0}[rdoc-ref:@0-3A+Set+-24-2F+-28Input+Record+Separator-29]:
+ Set `$/` (input record separator).
+- {Option -F}[rdoc-ref:@F-3A+Set+Input+Field+Separator]:
+ Set input field separator.
+- {Option -l}[rdoc-ref:@l-3A+Set+Output+Record+Separator-3B+Chop+Lines]:
+ Set output record separator; chop lines.
+- {Option -n}[rdoc-ref:@n-3A+Run+Program+in+gets+Loop]:
+ Run program in `gets` loop.
+- {Option -p}[rdoc-ref:@p-3A+-n-2C+with+Printing]:
+ `-n`, with printing.
+
+### `-c`: Check Syntax
+
+Option `-c` specifies that the specified Ruby program
+should be checked for syntax, but not actually executed:
+
+```console
+$ ruby -e 'puts "Foo"'
+Foo
+$ ruby -c -e 'puts "Foo"'
+Syntax OK
+```
+
+### `-C`: Set Working Directory
+
+The argument to option `-C` specifies a working directory
+for the invoked Ruby program;
+does not change the working directory for the current process:
+
+```console
+$ basename `pwd`
+ruby
+$ ruby -C lib -e 'puts File.basename(Dir.pwd)'
+lib
+$ basename `pwd`
+ruby
+```
+
+Whitespace between the option and its argument may be omitted.
+
+### `-d`: Set `$DEBUG` to `true`
+
+Some code in (or called by) the Ruby program may include statements or blocks
+conditioned by the global variable `$DEBUG` (e.g., `if $DEBUG`);
+these commonly write to `$stdout` or `$stderr`.
+
+The default value for `$DEBUG` is `false`;
+option `-d` sets it to `true`:
+
+```console
+$ ruby -e 'p $DEBUG'
+false
+$ ruby -d -e 'p $DEBUG'
+true
+```
+
+Option `--debug` is an alias for option `-d`.
+
+### `-e`: Execute Given Ruby Code
+
+Option `-e` requires an argument, which is Ruby code to be executed;
+the option may be given more than once:
+
+```console
+$ ruby -e 'puts "Foo"' -e 'puts "Bar"'
+Foo
+Bar
+```
+
+Whitespace between the option and its argument may be omitted.
+
+The command may include other options,
+but should not include arguments (which, if given, are ignored).
+
+### `-E`: Set Default Encodings
+
+Option `-E` requires an argument, which specifies either the default external encoding,
+or both the default external and internal encodings for the invoked Ruby program:
+
+```console
+# No option -E.
+$ ruby -e 'p [Encoding::default_external, Encoding::default_internal]'
+[#<Encoding:UTF-8>, nil]
+# Option -E with default external encoding.
+$ ruby -E cesu-8 -e 'p [Encoding::default_external, Encoding::default_internal]'
+[#<Encoding:CESU-8>, nil]
+# Option -E with default external and internal encodings.
+$ ruby -E utf-8:cesu-8 -e 'p [Encoding::default_external, Encoding::default_internal]'
+[#<Encoding:UTF-8>, #<Encoding:CESU-8>]
+```
+
+Whitespace between the option and its argument may be omitted.
+
+See also:
+
+- {Option --external-encoding}[options_md.html#label--external-encoding-3A+Set+Default+External+Encoding]:
+ Set default external encoding.
+- {Option --internal-encoding}[options_md.html#label--internal-encoding-3A+Set+Default+Internal+Encoding]:
+ Set default internal encoding.
+
+Option `--encoding` is an alias for option `-E`.
+
+### `-F`: Set Input Field Separator
+
+Option `-F`, when given with option `-a`,
+specifies that its argument is to be the input field separator to be used for splitting:
+
+```console
+$ ruby -an -Fs -e 'p $F' desiderata.txt
+["Go placidly amid the noi", "e and the ha", "te,\n"]
+["and remember what peace there may be in ", "ilence.\n"]
+["A", " far a", " po", "", "ible, without ", "urrender,\n"]
+["be on good term", " with all per", "on", ".\n"]
+```
+
+The argument may be a regular expression:
+
+```console
+$ ruby -an -F'[.,]\s*' -e 'p $F' desiderata.txt
+["Go placidly amid the noise and the haste"]
+["and remember what peace there may be in silence"]
+["As far as possible", "without surrender"]
+["be on good terms with all persons"]
+```
+
+The argument must immediately follow the option
+(no intervening whitespace or equal-sign character `'='`).
+
+See also:
+
+- {Option -0}[rdoc-ref:@0-3A+Set+-24-2F+-28Input+Record+Separator-29]:
+ Set `$/` (input record separator).
+- {Option -a}[rdoc-ref:@a-3A+Split+Input+Lines+into+Fields]:
+ Split input lines into fields.
+- {Option -l}[rdoc-ref:@l-3A+Set+Output+Record+Separator-3B+Chop+Lines]:
+ Set output record separator; chop lines.
+- {Option -n}[rdoc-ref:@n-3A+Run+Program+in+gets+Loop]:
+ Run program in `gets` loop.
+- {Option -p}[rdoc-ref:@p-3A+-n-2C+with+Printing]:
+ `-n`, with printing.
+
+### `-h`: Print Short Help Message
+
+Option `-h` prints a short help message
+that includes single-hyphen options (e.g. `-I`),
+and largely omits double-hyphen options (e.g., `--version`).
+
+Arguments and additional options are ignored.
+
+For a longer help message, use option `--help`.
+
+### `-i`: Set \ARGF In-Place Mode
+
+Option `-i` sets the \ARGF in-place mode for the invoked Ruby program;
+see ARGF#inplace_mode=:
+
+```console
+$ ruby -e 'p ARGF.inplace_mode'
+nil
+$ ruby -i -e 'p ARGF.inplace_mode'
+""
+$ ruby -i.bak -e 'p ARGF.inplace_mode'
+".bak"
+```
+
+### `-I`: Add to `$LOAD_PATH`
+
+The argument to option `-I` specifies a directory
+to be added to the array in global variable `$LOAD_PATH`;
+the option may be given more than once:
+
+```console
+$ pushd /tmp
+$ ruby -e 'p $LOAD_PATH.size'
+8
+$ ruby -I my_lib -I some_lib -e 'p $LOAD_PATH.size'
+10
+$ ruby -I my_lib -I some_lib -e 'p $LOAD_PATH.take(2)'
+["/tmp/my_lib", "/tmp/some_lib"]
+$ popd
+```
+
+Whitespace between the option and its argument may be omitted.
+
+### `-l`: Set Output Record Separator; Chop Lines
+
+Option `-l`, when given with option `-n` or `-p`,
+modifies line-ending processing by:
+
+- Setting global variable output record separator `$\`
+ to the current value of input record separator `$/`;
+ this affects line-oriented output (such a the output from Kernel#puts).
+- Calling String#chop! on each line read.
+
+Without option `-l` (unchopped):
+
+```console
+$ ruby -n -e 'p $_' desiderata.txt
+"Go placidly amid the noise and the haste,\n"
+"and remember what peace there may be in silence.\n"
+"As far as possible, without surrender,\n"
+"be on good terms with all persons.\n"
+```
+
+With option `-l` (chopped):
+
+```console
+$ ruby -ln -e 'p $_' desiderata.txt
+"Go placidly amid the noise and the haste,"
+"and remember what peace there may be in silence."
+"As far as possible, without surrender,"
+"be on good terms with all persons."
+```
+
+See also:
+
+- {Option -0}[rdoc-ref:@0-3A+Set+-24-2F+-28Input+Record+Separator-29]:
+ Set `$/` (input record separator).
+- {Option -a}[rdoc-ref:@a-3A+Split+Input+Lines+into+Fields]:
+ Split input lines into fields.
+- {Option -F}[rdoc-ref:@F-3A+Set+Input+Field+Separator]:
+ Set input field separator.
+- {Option -n}[rdoc-ref:@n-3A+Run+Program+in+gets+Loop]:
+ Run program in `gets` loop.
+- {Option -p}[rdoc-ref:@p-3A+-n-2C+with+Printing]:
+ `-n`, with printing.
+
+### `-n`: Run Program in `gets` Loop
+
+Option `-n` runs your program in a `Kernel#gets` loop:
+
+```ruby
+while gets
+ # Your Ruby code.
+end
+```
+
+Note that `gets` reads the next line and sets global variable `$_`
+to the last read line:
+
+```console
+$ ruby -n -e 'puts $_' desiderata.txt
+Go placidly amid the noise and the haste,
+and remember what peace there may be in silence.
+As far as possible, without surrender,
+be on good terms with all persons.
+```
+
+See also:
+
+- {Option -0}[rdoc-ref:@0-3A+Set+-24-2F+-28Input+Record+Separator-29]:
+ Set `$/` (input record separator).
+- {Option -a}[rdoc-ref:@a-3A+Split+Input+Lines+into+Fields]:
+ Split input lines into fields.
+- {Option -F}[rdoc-ref:@F-3A+Set+Input+Field+Separator]:
+ Set input field separator.
+- {Option -l}[rdoc-ref:@l-3A+Set+Output+Record+Separator-3B+Chop+Lines]:
+ Set output record separator; chop lines.
+- {Option -p}[rdoc-ref:@p-3A+-n-2C+with+Printing]:
+ `-n`, with printing.
+
+### `-p`: `-n`, with Printing
+
+Option `-p` is like option `-n`, but also prints each line:
+
+```console
+$ ruby -p -e 'puts $_.size' desiderata.txt
+42
+Go placidly amid the noise and the haste,
+49
+and remember what peace there may be in silence.
+39
+As far as possible, without surrender,
+35
+be on good terms with all persons.
+```
+
+See also:
+
+- {Option -0}[rdoc-ref:@0-3A+Set+-24-2F+-28Input+Record+Separator-29]:
+ Set `$/` (input record separator).
+- {Option -a}[rdoc-ref:@a-3A+Split+Input+Lines+into+Fields]:
+ Split input lines into fields.
+- {Option -F}[rdoc-ref:@F-3A+Set+Input+Field+Separator]:
+ Set input field separator.
+- {Option -l}[rdoc-ref:@l-3A+Set+Output+Record+Separator-3B+Chop+Lines]:
+ Set output record separator; chop lines.
+- {Option -n}[rdoc-ref:@n-3A+Run+Program+in+gets+Loop]:
+ Run program in `gets` loop.
+
+### `-r`: Require Library
+
+The argument to option `-r` specifies a library to be required
+before executing the Ruby program;
+the option may be given more than once:
+
+```console
+$ ruby -e 'p defined?(JSON); p defined?(CSV)'
+nil
+nil
+$ ruby -r CSV -r JSON -e 'p defined?(JSON); p defined?(CSV)'
+"constant"
+"constant"
+```
+
+Whitespace between the option and its argument may be omitted.
+
+### `-s`: Define Global Variable
+
+Option `-s` specifies that a "custom option" is to define a global variable
+in the invoked Ruby program:
+
+- The custom option must appear _after_ the program name.
+- The custom option must begin with single hyphen (e.g., `-foo`),
+ not two hyphens (e.g., `--foo`).
+- The name of the global variable is based on the option name:
+ global variable `$foo` for custom option`-foo`.
+- The value of the global variable is the string option argument if given,
+ `true` otherwise.
+
+More than one custom option may be given:
+
+```console
+$ cat t.rb
+p [$foo, $bar]
+$ ruby t.rb
+[nil, nil]
+$ ruby -s t.rb -foo=baz
+["baz", nil]
+$ ruby -s t.rb -foo
+[true, nil]
+$ ruby -s t.rb -foo=baz -bar=bat
+["baz", "bat"]
+```
+
+The option may not be used with
+{option -e}[rdoc-ref:@e-3A+Execute+Given+Ruby+Code]
+
+### `-S`: Search Directories in `ENV['PATH']`
+
+Option `-S` specifies that the Ruby interpreter
+is to search (if necessary) the directories whose paths are in the program's
+`PATH` environment variable;
+the program is executed in the shell's current working directory
+(not necessarily in the directory where the program is found).
+
+This example uses adds path `'tmp/'` to the `PATH` environment variable:
+
+```console
+$ export PATH=/tmp:$PATH
+$ echo "puts File.basename(Dir.pwd)" > /tmp/t.rb
+$ ruby -S t.rb
+ruby
+```
+
+### `-v`: Print Version; Set `$VERBOSE`
+
+Options `-v` prints the Ruby version and sets global variable `$VERBOSE`:
+
+```console
+$ ruby -e 'p $VERBOSE'
+false
+$ ruby -v -e 'p $VERBOSE'
+ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x64-mingw-ucrt]
+true
+```
+
+### `-w`: Synonym for `-W1`
+
+Option `-w` (lowercase letter) is equivalent to option `-W1` (uppercase letter).
+
+### `-W`: Set \Warning Policy
+
+Any Ruby code can create a <i>warning message</i> by calling method Kernel#warn;
+methods in the Ruby core and standard libraries can also create warning messages.
+Such a message may be printed on `$stderr`
+(or not, depending on certain settings).
+
+Option `-W` helps determine whether a particular warning message
+will be written,
+by setting the initial value of global variable `$-W`:
+
+- `-W0`: Sets `$-W` to `0` (silent; no warnings).
+- `-W1`: Sets `$-W` to `1` (moderate verbosity).
+- `-W2`: Sets `$-W` to `2` (high verbosity).
+- `-W`: Same as `-W2` (high verbosity).
+- Option not given: Same as `-W1` (moderate verbosity).
+
+The value of `$-W`, in turn, determines which warning messages (if any)
+are to be printed to `$stdout` (see Kernel#warn):
+
+```console
+$ ruby -W1 -e 'p $foo'
+nil
+$ ruby -W2 -e 'p $foo'
+-e:1: warning: global variable '$foo' not initialized
+nil
+```
+
+Ruby code may also define warnings for certain categories;
+these are the default settings for the defined categories:
+
+```rb
+Warning[:experimental] # => true
+Warning[:deprecated] # => false
+Warning[:performance] # => false
+```
+
+They may also be set:
+
+```rb
+Warning[:experimental] = false
+Warning[:deprecated] = true
+Warning[:performance] = true
+```
+
+You can suppress a category by prefixing `no-` to the category name:
+
+```console
+$ ruby -W:no-experimental -e 'p IO::Buffer.new'
+#<IO::Buffer>
+```
+
+### `-x`: Execute Ruby Code Found in Text
+
+Option `-x` executes a Ruby program whose code is embedded
+in other, non-code, text:
+
+The ruby code:
+
+- Begins after the first line beginning with `'#!` and containing string `'ruby'`.
+- Ends before any one of:
+
+ - End-of-file.
+ - A line consisting of `'__END__'`,
+ - Character `Ctrl-D` or `Ctrl-Z`.
+
+Example:
+
+```console
+$ cat t.txt
+Leading garbage.
+#!ruby
+puts File.basename(Dir.pwd)
+__END__
+Trailing garbage.
+
+$ ruby -x t.txt
+ruby
+```
+
+The optional argument specifies the directory where the text file
+is to be found;
+the Ruby code is executed in that directory:
+
+```console
+$ cp t.txt /tmp/
+$ ruby -x/tmp t.txt
+tmp
+$
+
+```
+
+If an argument is given, it must immediately follow the option
+(no intervening whitespace or equal-sign character `'='`).
+
+### `--backtrace-limit`: Set Backtrace Limit
+
+Option `--backtrace-limit` sets a limit on the number of entries
+to be displayed in a backtrace.
+
+See Thread::Backtrace.limit.
+
+### `--copyright`: Print Ruby Copyright
+
+Option `--copyright` prints a copyright message:
+
+```console
+$ ruby --copyright
+ruby - Copyright (C) 1993-2024 Yukihiro Matsumoto
+```
+
+### `--debug`: Alias for `-d`
+
+Option `--debug` is an alias for
+{option -d}[rdoc-ref:@d-3A+Set+-24DEBUG+to+true].
+
+### `--disable`: Disable Features
+
+Option `--disable` specifies features to be disabled;
+the argument is a comma-separated list of the features to be disabled:
+
+```sh
+ruby --disable=gems,rubyopt t.rb
+```
+
+The supported features:
+
+- `gems`: Rubygems (default: enabled).
+- `did_you_mean`: [`did_you_mean`](https://github.com/ruby/did_you_mean) (default: enabled).
+- `rubyopt`: `RUBYOPT` environment variable (default: enabled).
+- `frozen-string-literal`: Freeze all string literals (default: disabled).
+- `jit`: JIT compiler (default: disabled).
+
+See also {option --enable}[options_md.html#label--enable-3A+Enable+Features].
+
+### `--dump`: Dump Items
+
+Option `--dump` specifies items to be dumped;
+the argument is a comma-separated list of the items.
+
+Some of the argument values cause the command to behave as if a different
+option was given:
+
+- `--dump=copyright`:
+ Same as {option \-\-copyright}[options_md.html#label--copyright-3A+Print+Ruby+Copyright].
+- `--dump=help`:
+ Same as {option \-\-help}[options_md.html#label--help-3A+Print+Help+Message].
+- `--dump=syntax`:
+ Same as {option -c}[rdoc-ref:@c-3A+Check+Syntax].
+- `--dump=usage`:
+ Same as {option -h}[rdoc-ref:@h-3A+Print+Short+Help+Message].
+- `--dump=version`:
+ Same as {option \-\-version}[options_md.html#label--version-3A+Print+Ruby+Version].
+
+For other argument values and examples,
+see {Option --dump}[option_dump_md.html].
+
+### `--enable`: Enable Features
+
+Option `--enable` specifies features to be enabled;
+the argument is a comma-separated list of the features to be enabled.
+
+```sh
+ruby --enable=gems,rubyopt t.rb
+```
+
+For the features,
+see {option --disable}[options_md.html#label--disable-3A+Disable+Features].
+
+### `--encoding`: Alias for `-E`.
+
+Option `--encoding` is an alias for
+{option -E}[rdoc-ref:@E-3A+Set+Default+Encodings].
+
+### `--external-encoding`: Set Default External \Encoding
+
+Option `--external-encoding`
+sets the default external encoding for the invoked Ruby program;
+for values of `encoding`,
+see {Encoding: Names and Aliases}[rdoc-ref:encodings.rdoc@Names+and+Aliases].
+
+```console
+$ ruby -e 'puts Encoding::default_external'
+UTF-8
+$ ruby --external-encoding=cesu-8 -e 'puts Encoding::default_external'
+CESU-8
+```
+
+### `--help`: Print Help Message
+
+Option `--help` prints a long help message.
+
+Arguments and additional options are ignored.
+
+For a shorter help message, use option `-h`.
+
+### `--internal-encoding`: Set Default Internal \Encoding
+
+Option `--internal-encoding`
+sets the default internal encoding for the invoked Ruby program;
+for values of `encoding`,
+see {Encoding: Names and Aliases}[rdoc-ref:encodings.rdoc@Names+and+Aliases].
+
+```console
+$ ruby -e 'puts Encoding::default_internal.nil?'
+true
+$ ruby --internal-encoding=cesu-8 -e 'puts Encoding::default_internal'
+CESU-8
+```
+
+### `--jit`
+
+Option `--jit` is an alias for option `--yjit`, which enables YJIT;
+see additional YJIT options in the [YJIT documentation](rdoc-ref:jit/yjit.md).
+
+### `--verbose`: Set `$VERBOSE`
+
+Option `--verbose` sets global variable `$VERBOSE` to `true`
+and disables input from `$stdin`.
+
+### `--version`: Print Ruby Version
+
+Option `--version` prints the version of the Ruby interpreter, then exits.
+
diff --git a/doc/language/packed_data.rdoc b/doc/language/packed_data.rdoc
new file mode 100644
index 0000000000..597db5139f
--- /dev/null
+++ b/doc/language/packed_data.rdoc
@@ -0,0 +1,722 @@
+= Packed \Data
+
+== Quick Reference
+
+These tables summarize the directives for packing and unpacking.
+
+=== For Integers
+
+ Directive | Meaning
+ --------------|---------------------------------------------------------------
+ C | 8-bit unsigned (unsigned char)
+ S | 16-bit unsigned, native endian (uint16_t)
+ L | 32-bit unsigned, native endian (uint32_t)
+ Q | 64-bit unsigned, native endian (uint64_t)
+ J | pointer width unsigned, native endian (uintptr_t)
+
+ c | 8-bit signed (signed char)
+ s | 16-bit signed, native endian (int16_t)
+ l | 32-bit signed, native endian (int32_t)
+ q | 64-bit signed, native endian (int64_t)
+ j | pointer width signed, native endian (intptr_t)
+
+ S_ S! | unsigned short, native endian
+ I I_ I! | unsigned int, native endian
+ L_ L! | unsigned long, native endian
+ Q_ Q! | unsigned long long, native endian
+ | (raises ArgumentError if the platform has no long long type)
+ J! | uintptr_t, native endian (same with J)
+
+ s_ s! | signed short, native endian
+ i i_ i! | signed int, native endian
+ l_ l! | signed long, native endian
+ q_ q! | signed long long, native endian
+ | (raises ArgumentError if the platform has no long long type)
+ j! | intptr_t, native endian (same with j)
+
+ S> s> S!> s!> | each the same as the directive without >, but big endian
+ L> l> L!> l!> | S> is the same as n
+ I!> i!> | L> is the same as N
+ Q> q> Q!> q!> |
+ J> j> J!> j!> |
+
+ S< s< S!< s!< | each the same as the directive without <, but little endian
+ L< l< L!< l!< | S< is the same as v
+ I!< i!< | L< is the same as V
+ Q< q< Q!< q!< |
+ J< j< J!< j!< |
+
+ n | 16-bit unsigned, network (big-endian) byte order
+ N | 32-bit unsigned, network (big-endian) byte order
+ v | 16-bit unsigned, VAX (little-endian) byte order
+ V | 32-bit unsigned, VAX (little-endian) byte order
+
+ U | UTF-8 character
+ w | BER-compressed integer
+
+=== For Floats
+
+ Directive | Meaning
+ ----------|--------------------------------------------------
+ D d | double-precision, native format
+ F f | single-precision, native format
+ E | double-precision, little-endian byte order
+ e | single-precision, little-endian byte order
+ G | double-precision, network (big-endian) byte order
+ g | single-precision, network (big-endian) byte order
+
+=== For Strings
+
+ Directive | Meaning
+ ----------|-----------------------------------------------------------------
+ A | arbitrary binary string (remove trailing nulls and ASCII spaces)
+ a | arbitrary binary string
+ Z | null-terminated string
+ B | bit string (MSB first)
+ b | bit string (LSB first)
+ H | hex string (high nibble first)
+ h | hex string (low nibble first)
+ u | UU-encoded string
+ M | quoted-printable, MIME encoding (see RFC2045)
+ m | base64 encoded string (RFC 2045) (default)
+ | (base64 encoded string (RFC 4648) if followed by 0)
+ P | pointer to a structure (fixed-length string)
+ p | pointer to a null-terminated string
+
+=== Additional Directives for Packing
+
+ Directive | Meaning
+ ----------|----------------------------------------------------------------
+ @ | moves to absolute position
+ X | back up a byte
+ x | null byte
+
+=== Additional Directives for Unpacking
+
+ Directive | Meaning
+ ----------|----------------------------------------------------------------
+ @ | skip to the offset given by the length argument
+ X | skip backward one byte
+ x | skip forward one byte
+
+== Packing and Unpacking
+
+Certain Ruby core methods deal with packing and unpacking data:
+
+- Method Array#pack:
+ Formats each element in array +self+ into a binary string;
+ returns that string.
+- Method String#unpack:
+ Extracts data from string +self+,
+ forming objects that become the elements of a new array;
+ returns that array.
+- Method String#unpack1:
+ Does the same, but unpacks and returns only the first extracted object.
+
+Each of these methods accepts a string +template+,
+consisting of zero or more _directive_ characters,
+each followed by zero or more _modifier_ characters.
+
+Examples (directive <tt>'C'</tt> specifies 'unsigned character'):
+
+ [65].pack('C') # => "A" # One element, one directive.
+ [65, 66].pack('CC') # => "AB" # Two elements, two directives.
+ [65, 66].pack('C') # => "A" # Extra element is ignored.
+ [65].pack('') # => "" # No directives.
+ [65].pack('CC') # Extra directive raises ArgumentError.
+
+ 'A'.unpack('C') # => [65] # One character, one directive.
+ 'AB'.unpack('CC') # => [65, 66] # Two characters, two directives.
+ 'AB'.unpack('C') # => [65] # Extra character is ignored.
+ 'A'.unpack('CC') # => [65, nil] # Extra directive generates nil.
+ 'AB'.unpack('') # => [] # No directives.
+
+The string +template+ may contain any mixture of valid directives
+(directive <tt>'c'</tt> specifies 'signed character'):
+
+ [65, -1].pack('cC') # => "A\xFF"
+ "A\xFF".unpack('cC') # => [65, 255]
+
+The string +template+ may contain whitespace (which is ignored)
+and comments, each of which begins with character <tt>'#'</tt>
+and continues up to and including the next following newline:
+
+ [0,1].pack(" C #foo \n C ") # => "\x00\x01"
+ "\0\1".unpack(" C #foo \n C ") # => [0, 1]
+
+Any directive may be followed by either of these modifiers:
+
+- <tt>'*'</tt> - The directive is to be applied as many times as needed:
+
+ [65, 66].pack('C*') # => "AB"
+ 'AB'.unpack('C*') # => [65, 66]
+
+- \Integer +count+ - The directive is to be applied +count+ times:
+
+ [65, 66].pack('C2') # => "AB"
+ [65, 66].pack('C3') # Raises ArgumentError.
+ 'AB'.unpack('C2') # => [65, 66]
+ 'AB'.unpack('C3') # => [65, 66, nil]
+
+ Note: Directives in <tt>%w[A a Z m]</tt> use +count+ differently;
+ see {\String Directives}[rdoc-ref:@String+Directives].
+
+If elements don't fit the provided directive, only least significant bits are encoded:
+
+ [257].pack("C").unpack("C") # => [1]
+
+== Packing Method
+
+Method Array#pack accepts optional keyword argument
++buffer+ that specifies the target string (instead of a new string):
+
+ [65, 66].pack('C*', buffer: 'foo') # => "fooAB"
+
+The method can accept a block:
+
+ # Packed string is passed to the block.
+ [65, 66].pack('C*') {|s| p s } # => "AB"
+
+== Unpacking Methods
+
+Methods String#unpack and String#unpack1 each accept
+an optional keyword argument +offset+ that specifies an offset
+into the string:
+
+ 'ABC'.unpack('C*', offset: 1) # => [66, 67]
+ 'ABC'.unpack1('C*', offset: 1) # => 66
+
+Both methods can accept a block:
+
+ # Each unpacked object is passed to the block.
+ ret = []
+ "ABCD".unpack("C*") {|c| ret << c }
+ ret # => [65, 66, 67, 68]
+
+ # The single unpacked object is passed to the block.
+ 'AB'.unpack1('C*') {|ele| p ele } # => 65
+
+== \Integer Directives
+
+Each integer directive specifies the packing or unpacking
+for one element in the input or output array.
+
+=== 8-Bit \Integer Directives
+
+- <tt>'c'</tt> - 8-bit signed integer
+ (like C <tt>signed char</tt>):
+
+ [0, 1, 255].pack('c*') # => "\x00\x01\xFF"
+ s = [0, 1, -1].pack('c*') # => "\x00\x01\xFF"
+ s.unpack('c*') # => [0, 1, -1]
+
+- <tt>'C'</tt> - 8-bit unsigned integer
+ (like C <tt>unsigned char</tt>):
+
+ [0, 1, 255].pack('C*') # => "\x00\x01\xFF"
+ s = [0, 1, -1].pack('C*') # => "\x00\x01\xFF"
+ s.unpack('C*') # => [0, 1, 255]
+
+=== 16-Bit \Integer Directives
+
+- <tt>'s'</tt> - 16-bit signed integer, native-endian
+ (like C <tt>int16_t</tt>):
+
+ [513, -514].pack('s*') # => "\x01\x02\xFE\xFD"
+ s = [513, 65022].pack('s*') # => "\x01\x02\xFE\xFD"
+ s.unpack('s*') # => [513, -514]
+
+- <tt>'S'</tt> - 16-bit unsigned integer, native-endian
+ (like C <tt>uint16_t</tt>):
+
+ [513, -514].pack('S*') # => "\x01\x02\xFE\xFD"
+ s = [513, 65022].pack('S*') # => "\x01\x02\xFE\xFD"
+ s.unpack('S*') # => [513, 65022]
+
+- <tt>'n'</tt> - 16-bit network integer, big-endian:
+
+ s = [0, 1, -1, 32767, -32768, 65535].pack('n*')
+ # => "\x00\x00\x00\x01\xFF\xFF\x7F\xFF\x80\x00\xFF\xFF"
+ s.unpack('n*')
+ # => [0, 1, 65535, 32767, 32768, 65535]
+
+- <tt>'v'</tt> - 16-bit VAX integer, little-endian:
+
+ s = [0, 1, -1, 32767, -32768, 65535].pack('v*')
+ # => "\x00\x00\x01\x00\xFF\xFF\xFF\x7F\x00\x80\xFF\xFF"
+ s.unpack('v*')
+ # => [0, 1, 65535, 32767, 32768, 65535]
+
+=== 32-Bit \Integer Directives
+
+- <tt>'l'</tt> - 32-bit signed integer, native-endian
+ (like C <tt>int32_t</tt>):
+
+ s = [67305985, -50462977].pack('l*')
+ # => "\x01\x02\x03\x04\xFF\xFE\xFD\xFC"
+ s.unpack('l*')
+ # => [67305985, -50462977]
+
+- <tt>'L'</tt> - 32-bit unsigned integer, native-endian
+ (like C <tt>uint32_t</tt>):
+
+ s = [67305985, 4244504319].pack('L*')
+ # => "\x01\x02\x03\x04\xFF\xFE\xFD\xFC"
+ s.unpack('L*')
+ # => [67305985, 4244504319]
+
+- <tt>'N'</tt> - 32-bit network integer, big-endian:
+
+ s = [0,1,-1].pack('N*')
+ # => "\x00\x00\x00\x00\x00\x00\x00\x01\xFF\xFF\xFF\xFF"
+ s.unpack('N*')
+ # => [0, 1, 4294967295]
+
+- <tt>'V'</tt> - 32-bit VAX integer, little-endian:
+
+ s = [0,1,-1].pack('V*')
+ # => "\x00\x00\x00\x00\x01\x00\x00\x00\xFF\xFF\xFF\xFF"
+ s.unpack('v*')
+ # => [0, 0, 1, 0, 65535, 65535]
+
+=== 64-Bit \Integer Directives
+
+- <tt>'q'</tt> - 64-bit signed integer, native-endian
+ (like C <tt>int64_t</tt>):
+
+ s = [578437695752307201, -506097522914230529].pack('q*')
+ # => "\x01\x02\x03\x04\x05\x06\a\b\xFF\xFE\xFD\xFC\xFB\xFA\xF9\xF8"
+ s.unpack('q*')
+ # => [578437695752307201, -506097522914230529]
+
+- <tt>'Q'</tt> - 64-bit unsigned integer, native-endian
+ (like C <tt>uint64_t</tt>):
+
+ s = [578437695752307201, 17940646550795321087].pack('Q*')
+ # => "\x01\x02\x03\x04\x05\x06\a\b\xFF\xFE\xFD\xFC\xFB\xFA\xF9\xF8"
+ s.unpack('Q*')
+ # => [578437695752307201, 17940646550795321087]
+
+=== Platform-Dependent \Integer Directives
+
+- <tt>'i'</tt> - Platform-dependent width signed integer,
+ native-endian (like C <tt>int</tt>):
+
+ s = [67305985, -50462977].pack('i*')
+ # => "\x01\x02\x03\x04\xFF\xFE\xFD\xFC"
+ s.unpack('i*')
+ # => [67305985, -50462977]
+
+- <tt>'I'</tt> - Platform-dependent width unsigned integer,
+ native-endian (like C <tt>unsigned int</tt>):
+
+ s = [67305985, -50462977].pack('I*')
+ # => "\x01\x02\x03\x04\xFF\xFE\xFD\xFC"
+ s.unpack('I*')
+ # => [67305985, 4244504319]
+
+- <tt>'j'</tt> - Pointer-width signed integer, native-endian
+ (like C <tt>intptr_t</tt>):
+
+ s = [67305985, -50462977].pack('j*')
+ # => "\x01\x02\x03\x04\x00\x00\x00\x00\xFF\xFE\xFD\xFC\xFF\xFF\xFF\xFF"
+ s.unpack('j*')
+ # => [67305985, -50462977]
+
+- <tt>'J'</tt> - Pointer-width unsigned integer, native-endian
+ (like C <tt>uintptr_t</tt>):
+
+ s = [67305985, 4244504319].pack('J*')
+ # => "\x01\x02\x03\x04\x00\x00\x00\x00\xFF\xFE\xFD\xFC\x00\x00\x00\x00"
+ s.unpack('J*')
+ # => [67305985, 4244504319]
+
+=== Other \Integer Directives
+
+- <tt>'U'</tt> - UTF-8 character:
+
+ s = [4194304].pack('U*')
+ # => "\xF8\x90\x80\x80\x80"
+ s.unpack('U*')
+ # => [4194304]
+
+- <tt>'r'</tt> - Signed LEB128-encoded integer
+ (see {Signed LEB128}[https://en.wikipedia.org/wiki/LEB128#Signed_LEB128])
+
+ s = [1, 127, -128, 16383, -16384].pack("r*")
+ # => "\x01\xFF\x00\x80\x7F\xFF\xFF\x00\x80\x80\x7F"
+ s.unpack('r*')
+ # => [1, 127, -128, 16383, -16384]
+
+- <tt>'R'</tt> - Unsigned LEB128-encoded integer
+ (see {Unsigned LEB128}[https://en.wikipedia.org/wiki/LEB128#Unsigned_LEB128])
+
+ s = [1, 127, 128, 16383, 16384].pack("R*")
+ # => "\x01\x7F\x80\x01\xFF\x7F\x80\x80\x01"
+ s.unpack('R*')
+ # => [1, 127, 128, 16383, 16384]
+
+- <tt>'w'</tt> - BER-encoded integer
+ (see {BER encoding}[https://en.wikipedia.org/wiki/X.690#BER_encoding]):
+
+ s = [1073741823].pack('w*')
+ # => "\x83\xFF\xFF\xFF\x7F"
+ s.unpack('w*')
+ # => [1073741823]
+
+=== Modifiers for \Integer Directives
+
+For the following directives, <tt>'!'</tt> or <tt>'_'</tt> modifiers may be
+suffixed as underlying platform’s native size.
+
+- <tt>'i'</tt>, <tt>'I'</tt> - C <tt>int</tt>, always native size.
+- <tt>'s'</tt>, <tt>'S'</tt> - C <tt>short</tt>.
+- <tt>'l'</tt>, <tt>'L'</tt> - C <tt>long</tt>.
+- <tt>'q'</tt>, <tt>'Q'</tt> - C <tt>long long</tt>, if available.
+- <tt>'j'</tt>, <tt>'J'</tt> - C <tt>intptr_t</tt>, always native size.
+
+Native size modifiers are silently ignored for always native size directives.
+
+The endian modifiers also may be suffixed in the directives above:
+
+- <tt>'>'</tt> - Big-endian.
+- <tt>'<'</tt> - Little-endian.
+
+== \Float Directives
+
+Each float directive specifies the packing or unpacking
+for one element in the input or output array.
+
+=== Single-Precision \Float Directives
+
+- <tt>'F'</tt> or <tt>'f'</tt> - Native format:
+
+ s = [3.0].pack('F') # => "\x00\x00@@"
+ s.unpack('F') # => [3.0]
+
+- <tt>'e'</tt> - Little-endian:
+
+ s = [3.0].pack('e') # => "\x00\x00@@"
+ s.unpack('e') # => [3.0]
+
+- <tt>'g'</tt> - Big-endian:
+
+ s = [3.0].pack('g') # => "@@\x00\x00"
+ s.unpack('g') # => [3.0]
+
+=== Double-Precision \Float Directives
+
+- <tt>'D'</tt> or <tt>'d'</tt> - Native format:
+
+ s = [3.0].pack('D') # => "\x00\x00\x00\x00\x00\x00\b@"
+ s.unpack('D') # => [3.0]
+
+- <tt>'E'</tt> - Little-endian:
+
+ s = [3.0].pack('E') # => "\x00\x00\x00\x00\x00\x00\b@"
+ s.unpack('E') # => [3.0]
+
+- <tt>'G'</tt> - Big-endian:
+
+ s = [3.0].pack('G') # => "@\b\x00\x00\x00\x00\x00\x00"
+ s.unpack('G') # => [3.0]
+
+A float directive may be infinity or not-a-number:
+
+ inf = 1.0/0.0 # => Infinity
+ [inf].pack('f') # => "\x00\x00\x80\x7F"
+ "\x00\x00\x80\x7F".unpack('f') # => [Infinity]
+
+ nan = inf/inf # => NaN
+ [nan].pack('f') # => "\x00\x00\xC0\x7F"
+ "\x00\x00\xC0\x7F".unpack('f') # => [NaN]
+
+== \String Directives
+
+Each string directive specifies the packing or unpacking
+for one byte in the input or output string.
+
+=== Binary \String Directives
+
+- <tt>'A'</tt> - Arbitrary binary string (space padded; count is width);
+ +nil+ is treated as the empty string:
+
+ ['foo'].pack('A') # => "f"
+ ['foo'].pack('A*') # => "foo"
+ ['foo'].pack('A2') # => "fo"
+ ['foo'].pack('A4') # => "foo "
+ [nil].pack('A') # => " "
+ [nil].pack('A*') # => ""
+ [nil].pack('A2') # => " "
+ [nil].pack('A4') # => " "
+
+ "foo\0".unpack('A') # => ["f"]
+ "foo\0".unpack('A4') # => ["foo"]
+ "foo\0bar".unpack('A10') # => ["foo\x00bar"] # Reads past "\0".
+ "foo ".unpack('A') # => ["f"]
+ "foo ".unpack('A4') # => ["foo"]
+ "foo".unpack('A4') # => ["foo"]
+
+ japanese = 'こんにちは'
+ japanese.size # => 5
+ japanese.bytesize # => 15
+ [japanese].pack('A') # => "\xE3"
+ [japanese].pack('A*') # => "\xE3\x81\x93\xE3\x82\x93\xE3\x81\xAB\xE3\x81\xA1\xE3\x81\xAF"
+ japanese.unpack('A') # => ["\xE3"]
+ japanese.unpack('A2') # => ["\xE3\x81"]
+ japanese.unpack('A4') # => ["\xE3\x81\x93\xE3"]
+ japanese.unpack('A*') # => ["\xE3\x81\x93\xE3\x82\x93\xE3\x81\xAB\xE3\x81\xA1\xE3\x81\xAF"]
+
+- <tt>'a'</tt> - Arbitrary binary string (null padded; count is width):
+
+ ["foo"].pack('a') # => "f"
+ ["foo"].pack('a*') # => "foo"
+ ["foo"].pack('a2') # => "fo"
+ ["foo\0"].pack('a4') # => "foo\x00"
+ [nil].pack('a') # => "\x00"
+ [nil].pack('a*') # => ""
+ [nil].pack('a2') # => "\x00\x00"
+ [nil].pack('a4') # => "\x00\x00\x00\x00"
+
+ "foo\0".unpack('a') # => ["f"]
+ "foo\0".unpack('a4') # => ["foo\x00"]
+ "foo ".unpack('a4') # => ["foo "]
+ "foo".unpack('a4') # => ["foo"]
+ "foo\0bar".unpack('a4') # => ["foo\x00"] # Reads past "\0".
+
+- <tt>'Z'</tt> - Same as <tt>'a'</tt>,
+ except that null is added or ignored with <tt>'*'</tt>:
+
+ ["foo"].pack('Z*') # => "foo\x00"
+ [nil].pack('Z*') # => "\x00"
+
+ "foo\0".unpack('Z*') # => ["foo"]
+ "foo".unpack('Z*') # => ["foo"]
+ "foo\0bar".unpack('Z*') # => ["foo"] # Does not read past "\0".
+
+=== Bit \String Directives
+
+- <tt>'B'</tt> - Bit string (high byte first):
+
+ ['11111111' + '00000000'].pack('B*') # => "\xFF\x00"
+ ['10000000' + '01000000'].pack('B*') # => "\x80@"
+
+ ['1'].pack('B0') # => ""
+ ['1'].pack('B1') # => "\x80"
+ ['1'].pack('B2') # => "\x80\x00"
+ ['1'].pack('B3') # => "\x80\x00"
+ ['1'].pack('B4') # => "\x80\x00\x00"
+ ['1'].pack('B5') # => "\x80\x00\x00"
+ ['1'].pack('B6') # => "\x80\x00\x00\x00"
+
+ "\xff\x00".unpack("B*") # => ["1111111100000000"]
+ "\x01\x02".unpack("B*") # => ["0000000100000010"]
+
+ "".unpack("B0") # => [""]
+ "\x80".unpack("B1") # => ["1"]
+ "\x80".unpack("B2") # => ["10"]
+ "\x80".unpack("B3") # => ["100"]
+
+- <tt>'b'</tt> - Bit string (low byte first):
+
+ ['11111111' + '00000000'].pack('b*') # => "\xFF\x00"
+ ['10000000' + '01000000'].pack('b*') # => "\x01\x02"
+
+ ['1'].pack('b0') # => ""
+ ['1'].pack('b1') # => "\x01"
+ ['1'].pack('b2') # => "\x01\x00"
+ ['1'].pack('b3') # => "\x01\x00"
+ ['1'].pack('b4') # => "\x01\x00\x00"
+ ['1'].pack('b5') # => "\x01\x00\x00"
+ ['1'].pack('b6') # => "\x01\x00\x00\x00"
+
+ "\xff\x00".unpack("b*") # => ["1111111100000000"]
+ "\x01\x02".unpack("b*") # => ["1000000001000000"]
+
+ "".unpack("b0") # => [""]
+ "\x01".unpack("b1") # => ["1"]
+ "\x01".unpack("b2") # => ["10"]
+ "\x01".unpack("b3") # => ["100"]
+
+=== Hex \String Directives
+
+- <tt>'H'</tt> - Hex string (high nibble first):
+
+ ['10ef'].pack('H*') # => "\x10\xEF"
+ ['10ef'].pack('H0') # => ""
+ ['10ef'].pack('H3') # => "\x10\xE0"
+ ['10ef'].pack('H5') # => "\x10\xEF\x00"
+
+ ['fff'].pack('H3') # => "\xFF\xF0"
+ ['fff'].pack('H4') # => "\xFF\xF0"
+ ['fff'].pack('H5') # => "\xFF\xF0\x00"
+ ['fff'].pack('H6') # => "\xFF\xF0\x00"
+ ['fff'].pack('H7') # => "\xFF\xF0\x00\x00"
+ ['fff'].pack('H8') # => "\xFF\xF0\x00\x00"
+
+ "\x10\xef".unpack('H*') # => ["10ef"]
+ "\x10\xef".unpack('H0') # => [""]
+ "\x10\xef".unpack('H1') # => ["1"]
+ "\x10\xef".unpack('H2') # => ["10"]
+ "\x10\xef".unpack('H3') # => ["10e"]
+ "\x10\xef".unpack('H4') # => ["10ef"]
+ "\x10\xef".unpack('H5') # => ["10ef"]
+
+- <tt>'h'</tt> - Hex string (low nibble first):
+
+ ['10ef'].pack('h*') # => "\x01\xFE"
+ ['10ef'].pack('h0') # => ""
+ ['10ef'].pack('h3') # => "\x01\x0E"
+ ['10ef'].pack('h5') # => "\x01\xFE\x00"
+
+ ['fff'].pack('h3') # => "\xFF\x0F"
+ ['fff'].pack('h4') # => "\xFF\x0F"
+ ['fff'].pack('h5') # => "\xFF\x0F\x00"
+ ['fff'].pack('h6') # => "\xFF\x0F\x00"
+ ['fff'].pack('h7') # => "\xFF\x0F\x00\x00"
+ ['fff'].pack('h8') # => "\xFF\x0F\x00\x00"
+
+ "\x01\xfe".unpack('h*') # => ["10ef"]
+ "\x01\xfe".unpack('h0') # => [""]
+ "\x01\xfe".unpack('h1') # => ["1"]
+ "\x01\xfe".unpack('h2') # => ["10"]
+ "\x01\xfe".unpack('h3') # => ["10e"]
+ "\x01\xfe".unpack('h4') # => ["10ef"]
+ "\x01\xfe".unpack('h5') # => ["10ef"]
+
+=== Pointer \String Directives
+
+- <tt>'P'</tt> - Pointer to a structure (fixed-length string):
+
+ s = ['abc'].pack('P') # => "\xE0O\x7F\xE5\xA1\x01\x00\x00"
+ s.unpack('P*') # => ["abc"]
+ ".".unpack("P") # => []
+ ("\0" * 8).unpack("P") # => [nil]
+ [nil].pack("P") # => "\x00\x00\x00\x00\x00\x00\x00\x00"
+
+- <tt>'p'</tt> - Pointer to a null-terminated string:
+
+ s = ['abc'].pack('p') # => "(\xE4u\xE5\xA1\x01\x00\x00"
+ s.unpack('p*') # => ["abc"]
+ ".".unpack("p") # => []
+ ("\0" * 8).unpack("p") # => [nil]
+ [nil].pack("p") # => "\x00\x00\x00\x00\x00\x00\x00\x00"
+
+=== Other \String Directives
+
+- <tt>'M'</tt> - Quoted printable, MIME encoding;
+ text mode, but input must use LF and output LF;
+ (see {RFC 2045}[https://www.ietf.org/rfc/rfc2045.txt]):
+
+ ["a b c\td \ne"].pack('M') # => "a b c\td =\n\ne=\n"
+ ["\0"].pack('M') # => "=00=\n"
+
+ ["a"*1023].pack('M') == ("a"*73+"=\n")*14+"a=\n" # => true
+ ("a"*73+"=\na=\n").unpack('M') == ["a"*74] # => true
+ (("a"*73+"=\n")*14+"a=\n").unpack('M') == ["a"*1023] # => true
+
+ "a b c\td =\n\ne=\n".unpack('M') # => ["a b c\td \ne"]
+ "=00=\n".unpack('M') # => ["\x00"]
+
+ "pre=31=32=33after".unpack('M') # => ["pre123after"]
+ "pre=\nafter".unpack('M') # => ["preafter"]
+ "pre=\r\nafter".unpack('M') # => ["preafter"]
+ "pre=".unpack('M') # => ["pre="]
+ "pre=\r".unpack('M') # => ["pre=\r"]
+ "pre=hoge".unpack('M') # => ["pre=hoge"]
+ "pre==31after".unpack('M') # => ["pre==31after"]
+ "pre===31after".unpack('M') # => ["pre===31after"]
+
+- <tt>'m'</tt> - Base64 encoded string;
+ count specifies input bytes between each newline,
+ rounded down to nearest multiple of 3;
+ if count is zero, no newlines are added;
+ (see {RFC 4648}[https://www.ietf.org/rfc/rfc4648.txt]):
+
+ [""].pack('m') # => ""
+ ["\0"].pack('m') # => "AA==\n"
+ ["\0\0"].pack('m') # => "AAA=\n"
+ ["\0\0\0"].pack('m') # => "AAAA\n"
+ ["\377"].pack('m') # => "/w==\n"
+ ["\377\377"].pack('m') # => "//8=\n"
+ ["\377\377\377"].pack('m') # => "////\n"
+
+ "".unpack('m') # => [""]
+ "AA==\n".unpack('m') # => ["\x00"]
+ "AAA=\n".unpack('m') # => ["\x00\x00"]
+ "AAAA\n".unpack('m') # => ["\x00\x00\x00"]
+ "/w==\n".unpack('m') # => ["\xFF"]
+ "//8=\n".unpack('m') # => ["\xFF\xFF"]
+ "////\n".unpack('m') # => ["\xFF\xFF\xFF"]
+ "A\n".unpack('m') # => [""]
+ "AA\n".unpack('m') # => ["\x00"]
+ "AA=\n".unpack('m') # => ["\x00"]
+ "AAA\n".unpack('m') # => ["\x00\x00"]
+
+ [""].pack('m0') # => ""
+ ["\0"].pack('m0') # => "AA=="
+ ["\0\0"].pack('m0') # => "AAA="
+ ["\0\0\0"].pack('m0') # => "AAAA"
+ ["\377"].pack('m0') # => "/w=="
+ ["\377\377"].pack('m0') # => "//8="
+ ["\377\377\377"].pack('m0') # => "////"
+
+ "".unpack('m0') # => [""]
+ "AA==".unpack('m0') # => ["\x00"]
+ "AAA=".unpack('m0') # => ["\x00\x00"]
+ "AAAA".unpack('m0') # => ["\x00\x00\x00"]
+ "/w==".unpack('m0') # => ["\xFF"]
+ "//8=".unpack('m0') # => ["\xFF\xFF"]
+ "////".unpack('m0') # => ["\xFF\xFF\xFF"]
+
+- <tt>'u'</tt> - UU-encoded string:
+
+ [""].pack("u") # => ""
+ ["a"].pack("u") # => "!80``\n"
+ ["aaa"].pack("u") # => "#86%A\n"
+
+ "".unpack("u") # => [""]
+ "#86)C\n".unpack("u") # => ["abc"]
+
+== Offset Directives
+
+- <tt>'@'</tt> - Begin packing at the given byte offset;
+ for packing, null fill or shrink if necessary:
+
+ [1, 2].pack("C@0C") # => "\x02"
+ [1, 2].pack("C@1C") # => "\x01\x02"
+ [1, 2].pack("C@5C") # => "\x01\x00\x00\x00\x00\x02"
+ [*1..5].pack("CCCC@2C") # => "\x01\x02\x05"
+
+ For unpacking, cannot to move to outside the string:
+
+ "\x01\x00\x00\x02".unpack("C@3C") # => [1, 2]
+ "\x00".unpack("@1C") # => [nil]
+ "\x00".unpack("@2C") # Raises ArgumentError.
+
+- <tt>'X'</tt> - For packing, shrink for the given byte offset:
+
+ [0, 1, 2].pack("CCXC") # => "\x00\x02"
+ [0, 1, 2].pack("CCX2C") # => "\x02"
+
+ For unpacking; rewind unpacking position for the given byte offset:
+
+ "\x00\x02".unpack("CCXC") # => [0, 2, 2]
+
+ Cannot to move to outside the string:
+
+ [0, 1, 2].pack("CCX3C") # Raises ArgumentError.
+ "\x00\x02".unpack("CX3C") # Raises ArgumentError.
+
+- <tt>'x'</tt> - Begin packing at after the given byte offset;
+ for packing, null fill if necessary:
+
+ [].pack("x0") # => ""
+ [].pack("x") # => "\x00"
+ [].pack("x8") # => "\x00\x00\x00\x00\x00\x00\x00\x00"
+
+ For unpacking, cannot to move to outside the string:
+
+ "\x00\x00\x02".unpack("CxC") # => [0, 2]
+ "\x00\x00\x02".unpack("x3C") # => [nil]
+ "\x00\x00\x02".unpack("x4C") # Raises ArgumentError
diff --git a/doc/language/ractor.md b/doc/language/ractor.md
new file mode 100644
index 0000000000..72fbde6e5a
--- /dev/null
+++ b/doc/language/ractor.md
@@ -0,0 +1,797 @@
+# Ractor - Ruby's Actor-like concurrency abstraction
+
+Ractors are designed to provide parallel execution of Ruby code without thread-safety concerns.
+
+## Summary
+
+### Multiple Ractors in a ruby process
+
+You can create multiple Ractors which can run ruby code in parallel with each other.
+
+* `Ractor.new{ expr }` creates a new Ractor and `expr` can run in parallel with other ractors on a multi-core computer.
+* Ruby processes start with one ractor (called the *main ractor*).
+* If the main ractor terminates, all other ractors receive termination requests, similar to how threads behave.
+* Each Ractor contains one or more `Thread`s.
+ * Threads within the same ractor share a ractor-wide global lock (GVL in MRI terminology), so they can't run in parallel wich each other (without releasing the GVL explicitly in C extensions). Threads in different ractors can run in parallel.
+ * The overhead of creating a ractor is slightly above the overhead of creating a thread.
+
+### Limited sharing between Ractors
+
+Ractors don't share all objects, unlike threads which can access any object other than objects stored in another thread's thread-locals.
+
+* Most objects are *unshareable objects*. Unshareable objects can only be used by the ractor that instantiated them, so you don't need to worry about thread-safety issues resulting from using the object concurrently across ractors.
+* Some objects are *shareable objects*. Here is an incomplete list to give you an idea:
+ * `i = 123`: All `Integer`s are shareable.
+ * `s = "str".freeze`: Frozen strings are shareable if they have no instance variables that refer to unshareable objects.
+ * `a = [1, [2], 3].freeze`: `a` is not a shareable object because `a` refers to the unshareable object `[2]` (this Array is not frozen).
+ * `h = {c: Object}.freeze`: `h` is shareable because `Symbol`s and `Class`es are shareable, and the Hash is frozen.
+ * Class/Module objects are always shareable, even if they refer to unshareable objects.
+ * Special shareable objects
+ * Ractor objects themselves are shareable.
+ * And more...
+
+### Communication between Ractors with `Ractor::Port`
+
+Ractors communicate with each other and synchronize their execution by exchanging messages. The `Ractor::Port` class provides this communication mechanism.
+
+```ruby
+port = Ractor::Port.new
+
+Ractor.new port do |port|
+ # Other ractors can send to the port
+ port << 42
+end
+
+port.receive # get a message from the port. Only the ractor that created the Port can receive from it.
+#=> 42
+```
+
+All Ractors have a default port, which `Ractor#send`, `Ractor.receive` (etc) will use.
+
+### Copy & Move semantics when sending objects
+
+To send unshareable objects to another ractor, objects are either copied or moved.
+
+* Copy: deep-copies the object to the other ractor. All unshareable objects will be `Kernel#clone`ed.
+* Move: moves membership to another ractor.
+ * The sending ractor can not access the moved object after it moves.
+ * There is a guarantee that only one ractor can access an unshareable object at once.
+
+### Thread-safety
+
+Ractors help to write thread-safe, concurrent programs. They allow sharing of data only through explicit message passing for
+unshareable objects. Shareable objects are guaranteed to work correctly across ractors, even if the ractors are running in parallel.
+This guarantee, however, only applies across ractors. You still need to use `Mutex`es and other thread-safety tools within a ractor if
+you're using multiple ruby `Thread`s.
+
+ * Most objects are unshareable. You can't create data-races across ractors due to the inability to use these objects across ractors.
+ * Shareable objects are protected by locks (or otherwise don't need to be) so they can be used by more than one ractor at once.
+
+## Creation and termination
+
+### `Ractor.new`
+
+* `Ractor.new { expr }` creates a Ractor.
+
+```ruby
+# Ractor.new with a block creates a new Ractor
+r = Ractor.new do
+ # This block can run in parallel with other ractors
+end
+
+# You can name a Ractor with a `name:` argument.
+r = Ractor.new name: 'my-first-ractor' do
+end
+
+r.name #=> 'my-first-ractor'
+```
+
+### Block isolation
+
+The Ractor executes `expr` in the given block.
+The given block will be isolated from its outer scope. To prevent sharing objects between ractors, outer variables, `self` and other information is isolated from the block.
+
+This isolation occurs at Ractor creation time (when `Ractor.new` is called). If the given block is not able to be isolated because of outer variables or `self`, an error will be raised.
+
+```ruby
+begin
+ a = true
+ r = Ractor.new do
+ a #=> ArgumentError because this block accesses outer variable `a`.
+ end
+ r.join # wait for ractor to finish
+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.value == self.object_id #=> false
+```
+
+Arguments passed to `Ractor.new()` become block parameters for the given block. However, Ruby does not pass the objects themselves, but sends them as messages (see below for details).
+
+```ruby
+r = Ractor.new 'ok' do |msg|
+ msg #=> 'ok'
+end
+r.value #=> 'ok'
+```
+
+```ruby
+# similar to the last example
+r = Ractor.new do
+ msg = Ractor.receive
+ msg
+end
+r.send 'ok'
+r.value #=> 'ok'
+```
+
+### The execution result of the given block
+
+The return value of the given block becomes an outgoing message (see below for details).
+
+```ruby
+r = Ractor.new do
+ 'ok'
+end
+r.value #=> `ok`
+```
+
+An error in the given block will be propagated to the consumer of the outgoing message.
+
+```ruby
+r = Ractor.new do
+ raise 'ok' # exception will be transferred to the consumer
+end
+
+begin
+ r.value
+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:
+
+* (1) Sending and receiving messages via `Ractor::Port`
+* (2) Using shareable container objects. For example, the Ractor::TVar gem ([ko1/ractor-tvar](https://github.com/ko1/ractor-tvar))
+
+Users can control program execution timing with (1), but should not control with (2) (only perform critical sections).
+
+For sending and receiving messages, these are the fundamental APIs:
+
+* send/receive via `Ractor::Port`.
+ * `Ractor::Port#send(obj)` (`Ractor::Port#<<(obj)` is an alias) sends a message to the port. Ports are connected to an infinite size incoming queue so sending will never block the caller.
+ * `Ractor::Port#receive` dequeues a message from its own incoming queue. If the incoming queue is empty, `Ractor::Port#receive` will block the execution of the current Thread until a message is sent.
+ * `Ractor#send` and `Ractor.receive` use ports (their default port) internally, so are conceptually similar to the above.
+* You can close a `Ractor::Port` by `Ractor::Port#close`. A port can only be closed by the ractor that created it.
+ * If a port is closed, you can't `send` to it. Doing so raises an exception.
+ * When a ractor is terminated, the ractor's ports are automatically closed.
+* You can wait for a ractor's termination and receive its return value with `Ractor#value`. This is similar to `Thread#value`.
+
+There are 3 ways to send an object as a message:
+
+1) Send a reference: sending a shareable object sends only a reference to the object (fast).
+
+2) Copy an object: sending an unshareable object through copying it deeply (can be slow). Note that you can not send an object this way which does not support deep copy. Some `T_DATA` objects (objects whose class is defined in a C extension, such as `StringIO`) are not supported.
+
+3) Move an object: sending an unshareable object across ractors with a membership change. The sending Ractor can not access the moved object after moving it, otherwise an exception will be raised. Implementation note: `T_DATA` objects are not supported.
+
+You can choose between "Copy" and "Move" by the `move:` keyword, `Ractor#send(obj, move: true/false)`. The default is `false` ("Copy"). However, if the object is shareable it will automatically use `move`.
+
+### Wait for multiple Ractors with `Ractor.select`
+
+You can wait for messages on multiple ports at once.
+The return value of `Ractor.select()` is `[port, msg]` where `port` is a ready port and `msg` is the received message.
+
+To make it convenient, `Ractor.select` can also accept ractors. In this case, it waits for their termination.
+The return value of `Ractor.select()` is `[r, msg]` where `r` is a terminated Ractor and `msg` is the value of the ractor's block.
+
+Wait for a single ractor (same as `Ractor#value`):
+
+```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]
+values = []
+
+while rs.any?
+ r, obj = Ractor.select(*rs)
+ rs.delete(r)
+ values << obj
+end
+
+values.sort == ['r1', 'r2'] #=> true
+```
+
+NOTE: Using `Ractor.select()` on a very large number of ractors has the same issue as `select(2)` currently.
+
+### Closing ports
+
+* `Ractor::Port#close` closes the port (similar to `Queue#close`).
+ * `port.send(obj)` will raise an exception when the port is closed.
+ * When the queue connected to the port is empty and port is closed, `Ractor::Port#receive` raises an exception. If the queue is not empty, it dequeues an object without exceptions.
+* When a Ractor terminates, the ports are closed automatically.
+
+Example (try to get a result from closed ractor):
+
+```ruby
+r = Ractor.new do
+ 'finish'
+end
+r.join # success (wait for the termination)
+r.value # success (will return 'finish')
+
+# The ractor's termination value has already been given to another ractor
+Ractor.new r do |r|
+ r.value #=> Ractor::Error
+end.join
+```
+
+Example (try to send to closed port):
+
+```ruby
+r = Ractor.new do
+end
+
+r.join # wait for termination, closes default port
+
+begin
+ r.send(1)
+rescue Ractor::ClosedError
+ 'ok'
+end
+```
+
+### Send a message by copying
+
+`Ractor::Port#send(obj)` copies `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.value #=> false
+```
+
+Some objects do not support copying, and raise an exception.
+
+```ruby
+obj = Thread.new{}
+begin
+ Ractor.new obj do |msg|
+ msg
+ end
+rescue TypeError => e
+ e.message #=> #<TypeError: allocator undefined for Thread>
+end
+```
+
+### Send a message by moving
+
+`Ractor::Port#send(obj, move: true)` moves `obj` to the destination Ractor.
+If the source ractor uses the moved object (for example, calls a method like `obj.foo()`), it will raise an error.
+
+```ruby
+r = Ractor.new do
+ obj = Ractor.receive
+ obj << ' world'
+end
+
+str = 'hello'.dup
+r.send str, move: true
+# str is now moved, and accessing str from this ractor is prohibited
+modified = r.value #=> 'hello world'
+
+
+begin
+ # Error because it uses moved str.
+ str << ' exception' # raise Ractor::MovedError
+rescue Ractor::MovedError
+ modified #=> 'hello world'
+end
+```
+
+Some objects do not support moving, 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)
+```
+
+Once an object has been moved, the source object's class is changed to `Ractor::MovedObject`.
+
+### Shareable objects
+
+The following is an inexhaustive list of shareable objects:
+
+* `Integer`, `Float`, `Complex`, `Rational`
+* `Symbol`, frozen `String` objects that don't refer to unshareables, `true`, `false`, `nil`
+* `Regexp` objects, if they have no instance variables or their instance variables refer only to shareables
+* `Class` and `Module` objects
+* `Ractor` and other special objects which deal with synchronization
+
+To make objects shareable, `Ractor.make_shareable(obj)` is provided. It tries to make the object shareable by freezing `obj` and recursively traversing its references to freeze them all. This method accepts the `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. `Ractor.make_shareable(copy: false)` has no effect on an already shareable object. If the object cannot be made shareable, a `Ractor::Error` exception will be raised.
+
+## Language changes to limit sharing between Ractors
+
+To isolate unshareable objects across ractors, we introduced additional language semantics for multi-ractor Ruby programs.
+
+Note that when not using ractors, these additional semantics are not needed (100% compatible with Ruby 2).
+
+### Global variables
+
+Only the main Ractor can access global variables.
+
+```ruby
+$gv = 1
+r = Ractor.new do
+ $gv
+end
+
+begin
+ r.join
+rescue Ractor::RemoteError => e
+ e.cause.message #=> 'can not access global variables from non-main Ractors'
+end
+```
+
+Note that some special global variables, such as `$stdin`, `$stdout` and `$stderr` are local to each ractor. 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 accessed from non-main ractors only if their values are shareable objects.
+
+```ruby
+class C
+ @iv = 1
+end
+
+p Ractor.new do
+ class C
+ @iv
+ end
+end.value #=> 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.join
+```
+
+```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.join
+rescue Ractor::RemoteError => e
+ e.cause.message #=> can not access instance variables of shareable objects from non-main Ractors (Ractor::IsolationError)
+end
+```
+
+### 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.join
+rescue => e
+ e.class #=> Ractor::IsolationError
+end
+```
+
+### Constants
+
+Only the main Ractor can read constants which refer to an unshareable object.
+
+```ruby
+class C
+ CONST = 'str'.dup
+end
+r = Ractor.new do
+ C::CONST
+end
+begin
+ r.join
+rescue => e
+ e.class #=> Ractor::IsolationError
+end
+```
+
+Only the main Ractor can define constants which refer to an unshareable object.
+
+```ruby
+class C
+end
+r = Ractor.new do
+ C::CONST = 'str'.dup
+end
+begin
+ r.join
+rescue => e
+ e.class #=> Ractor::IsolationError
+end
+```
+
+When creating/updating a library to support ractors, constants should only refer to shareable objects if they are to be used by non-main ractors.
+
+```ruby
+TABLE = {a: 'ko1', b: 'ko2', c: 'ko3'}
+```
+
+In this case, `TABLE` refers to an unshareable Hash object. In order for other ractors to use `TABLE`, we need to make it shareable. We can use `Ractor.make_shareable()` like so:
+
+```ruby
+TABLE = Ractor.make_shareable( {a: 'ko1', b: 'ko2', c: 'ko3'} )
+```
+
+To make it easy, Ruby 3.0 introduced a new `shareable_constant_value` file 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'} )
+```
+
+The `shareable_constant_value` directive accepts the following modes (descriptions use the example: `CONST = expr`):
+
+* none: Do nothing. Same as: `CONST = expr`
+* literal:
+ * if `expr` consists of literals, replaced to `CONST = Ractor.make_shareable(expr)`.
+ * otherwise: replaced to `CONST = expr.tap{|o| raise unless Ractor.shareable?(o)}`.
+* experimental_everything: replaced to `CONST = Ractor.make_shareable(expr)`.
+* experimental_copy: replaced to `CONST = Ractor.make_shareable(expr, copy: true)`.
+
+Except for the `none` mode (default), it is guaranteed that these constants refer only to shareable objects.
+
+See [syntax/comments.rdoc](../syntax/comments.rdoc) for more details.
+
+### Shareable procs
+
+Procs and lambdas are unshareable objects, even when they are frozen. To create an unshareable Proc, you must use `Ractor.shareable_proc { expr }`. Much like during Ractor creation, the proc's block is isolated from its outer environment, so it cannot access variables from the outside scope. `self` is also changed within the Proc to be `nil` by default, although a `self:` keyword can be provided if you want to customize the value to a different shareable object.
+
+```ruby
+p = Ractor.shareable_proc { p self }
+p.call #=> nil
+```
+
+```ruby
+begin
+ a = 1
+ pr = Ractor.shareable_proc { p a }
+ pr.call # never gets here
+rescue Ractor::IsolationError
+end
+```
+
+In order to dynamically define a method with `Module#define_method` that can be used from different ractors, you must define it with a shareable proc. Alternatively, you can use `Module#class_eval` or `Module#module_eval` with a String. Even though the shareable proc's `self` is initially bound to `nil`, `define_method` will bind `self` to the correct value in the method.
+
+```ruby
+class A
+ define_method :testing, &Ractor.shareable_proc do
+ p self
+ end
+end
+Ractor.new do
+ a = A.new
+ a.testing #=> #<A:0x0000000101acfe10>
+end.join
+```
+
+This isolation must be done to prevent the method from accessing and assigning captured outer variables across ractors.
+
+### Ractor-local storage
+
+You can store any object (even unshareables) in ractor-local storage.
+
+```ruby
+r = Ractor.new do
+ values = []
+ Ractor[:threads] = []
+ 3.times do |i|
+ Ractor[:threads] << Thread.new do
+ values << [Ractor.receive, i+1] # Ractor.receive blocks the current thread in the current ractor until it receives a message
+ end
+ end
+ Ractor[:threads].each(&:join)
+ values
+end
+
+r << 1
+r << 2
+r << 3
+r.value #=> [[1,1],[2,2],[3,3]] (the order can change with each run)
+```
+
+## 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
+
+(1) One ractor has a pool
+
+```ruby
+require 'prime'
+
+N = 1000
+RN = 10
+
+# make RN workers
+workers = (1..RN).map do
+ Ractor.new do |; result_port|
+ loop do
+ n, result_port = Ractor.receive
+ result_port << [n, n.prime?, Ractor.current]
+ end
+ end
+end
+
+result_port = Ractor::Port.new
+results = []
+
+(1..N).each do |i|
+ if workers.empty?
+ # receive a result
+ n, result, w = result_port.receive
+ results << [n, result]
+ else
+ w = workers.pop
+ end
+
+ # send a task to the idle worker ractor
+ w << [i, result_port]
+end
+
+# receive a result
+while results.size != N
+ n, result, _w = result_port.receive
+ results << [n, result]
+end
+
+pp results.sort_by{|n, result| n}
+```
+
+### Pipeline
+
+```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)
+#=>
+# <Thread:0x000056262de28bd8 run> 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 <main>'
+# 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 <main>': unhandled exception
+# Traceback (most recent call last):
+# 2: from /home/ko1/src/ruby/trunk/test.rb:7:in `block (2 levels) in <main>'
+# 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 <main>': unhandled exception
+# 1: from /home/ko1/src/ruby/trunk/test.rb:21:in `<main>'
+# <internal:ractor>: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
+
+#=> <internal:ractor>: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/doc/regexp/methods.rdoc b/doc/language/regexp/methods.rdoc
index 356156ac9a..356156ac9a 100644
--- a/doc/regexp/methods.rdoc
+++ b/doc/language/regexp/methods.rdoc
diff --git a/doc/language/regexp/unicode_properties.rdoc b/doc/language/regexp/unicode_properties.rdoc
new file mode 100644
index 0000000000..94080f7199
--- /dev/null
+++ b/doc/language/regexp/unicode_properties.rdoc
@@ -0,0 +1,718 @@
+== \Regexps Based on Unicode Properties
+
+The properties shown here are those currently supported in Ruby.
+Older versions may not support all of these.
+
+=== POSIX brackets
+
+- <tt>\p{ASCII}</tt>
+- <tt>\p{Alnum}</tt>
+- <tt>\p{Alphabetic}</tt>, <tt>\p{Alpha}</tt>
+- <tt>\p{Blank}</tt>
+- <tt>\p{Cntrl}</tt>
+- <tt>\p{Digit}</tt>
+- <tt>\p{Graph}</tt>
+- <tt>\p{Lowercase}</tt>, <tt>\p{Lower}</tt>
+- <tt>\p{Print}</tt>
+- <tt>\p{Punct}</tt>
+- <tt>\p{Space}</tt>
+- <tt>\p{Uppercase}</tt>, <tt>\p{Upper}</tt>
+- <tt>\p{Word}</tt>
+- <tt>\p{XDigit}</tt>
+- <tt>\p{XPosixPunct}</tt>
+
+=== Special
+
+- <tt>\p{Any}</tt>
+- <tt>\p{Assigned}</tt>
+
+=== Major and General Categories
+
+- <tt>\p{Cased_Letter}</tt>, <tt>\p{LC}</tt>
+- <tt>\p{Close_Punctuation}</tt>, <tt>\p{Pe}</tt>
+- <tt>\p{Connector_Punctuation}</tt>, <tt>\p{Pc}</tt>
+- <tt>\p{Control}</tt>, <tt>\p{Cc}</tt>
+- <tt>\p{Currency_Symbol}</tt>, <tt>\p{Sc}</tt>
+- <tt>\p{Dash_Punctuation}</tt>, <tt>\p{Pd}</tt>
+- <tt>\p{Decimal_Number}</tt>, <tt>\p{Nd}</tt>
+- <tt>\p{Enclosing_Mark}</tt>, <tt>\p{Me}</tt>
+- <tt>\p{Final_Punctuation}</tt>, <tt>\p{Pf}</tt>
+- <tt>\p{Format}</tt>, <tt>\p{Cf}</tt>
+- <tt>\p{Initial_Punctuation}</tt>, <tt>\p{Pi}</tt>
+- <tt>\p{Letter}</tt>, <tt>\p{L}</tt>
+- <tt>\p{Letter_Number}</tt>, <tt>\p{Nl}</tt>
+- <tt>\p{Line_Separator}</tt>, <tt>\p{Zl}</tt>
+- <tt>\p{Lowercase_Letter}</tt>, <tt>\p{Ll}</tt>
+- <tt>\p{Mark}</tt>, <tt>\p{M}</tt>
+- <tt>\p{Math_Symbol}</tt>, <tt>\p{Sm}</tt>
+- <tt>\p{Modifier_Letter}</tt>, <tt>\p{Lm}</tt>
+- <tt>\p{Modifier_Symbol}</tt>, <tt>\p{Sk}</tt>
+- <tt>\p{Nonspacing_Mark}</tt>, <tt>\p{Mn}</tt>
+- <tt>\p{Number}</tt>, <tt>\p{N}</tt>
+- <tt>\p{Open_Punctuation}</tt>, <tt>\p{Ps}</tt>
+- <tt>\p{Other}</tt>, <tt>\p{C}</tt>
+- <tt>\p{Other_Letter}</tt>, <tt>\p{Lo}</tt>
+- <tt>\p{Other_Number}</tt>, <tt>\p{No}</tt>
+- <tt>\p{Other_Punctuation}</tt>, <tt>\p{Po}</tt>
+- <tt>\p{Other_Symbol}</tt>, <tt>\p{So}</tt>
+- <tt>\p{Paragraph_Separator}</tt>, <tt>\p{Zp}</tt>
+- <tt>\p{Private_Use}</tt>, <tt>\p{Co}</tt>
+- <tt>\p{Punctuation}</tt>, <tt>\p{P}</tt>
+- <tt>\p{Separator}</tt>, <tt>\p{Z}</tt>
+- <tt>\p{Space_Separator}</tt>, <tt>\p{Zs}</tt>
+- <tt>\p{Spacing_Mark}</tt>, <tt>\p{Mc}</tt>
+- <tt>\p{Surrogate}</tt>, <tt>\p{Cs}</tt>
+- <tt>\p{Symbol}</tt>, <tt>\p{S}</tt>
+- <tt>\p{Titlecase_Letter}</tt>, <tt>\p{Lt}</tt>
+- <tt>\p{Unassigned}</tt>, <tt>\p{Cn}</tt>
+- <tt>\p{Uppercase_Letter}</tt>, <tt>\p{Lu}</tt>
+
+=== Prop List
+
+- <tt>\p{ASCII_Hex_Digit}</tt>, <tt>\p{AHex}</tt>
+- <tt>\p{Bidi_Control}</tt>, <tt>\p{Bidi_C}</tt>
+- <tt>\p{Dash}</tt>
+- <tt>\p{Deprecated}</tt>, <tt>\p{Dep}</tt>
+- <tt>\p{Diacritic}</tt>, <tt>\p{Dia}</tt>
+- <tt>\p{Extender}</tt>, <tt>\p{Ext}</tt>
+- <tt>\p{Hex_Digit}</tt>, <tt>\p{Hex}</tt>
+- <tt>\p{Hyphen}</tt>
+- <tt>\p{IDS_Binary_Operator}</tt>, <tt>\p{IDSB}</tt>
+- <tt>\p{IDS_Trinary_Operator}</tt>, <tt>\p{IDST}</tt>
+- <tt>\p{IDS_Unary_Operator}</tt>, <tt>\p{IDSU}</tt>
+- <tt>\p{ID_Compat_Math_Continue}</tt>
+- <tt>\p{ID_Compat_Math_Start}</tt>
+- <tt>\p{Ideographic}</tt>, <tt>\p{Ideo}</tt>
+- <tt>\p{Join_Control}</tt>, <tt>\p{Join_C}</tt>
+- <tt>\p{Logical_Order_Exception}</tt>, <tt>\p{LOE}</tt>
+- <tt>\p{Modifier_Combining_Mark}</tt>, <tt>\p{MCM}</tt>
+- <tt>\p{Noncharacter_Code_Point}</tt>, <tt>\p{NChar}</tt>
+- <tt>\p{Other_Alphabetic}</tt>, <tt>\p{OAlpha}</tt>
+- <tt>\p{Other_Default_Ignorable_Code_Point}</tt>, <tt>\p{ODI}</tt>
+- <tt>\p{Other_Grapheme_Extend}</tt>, <tt>\p{OGr_Ext}</tt>
+- <tt>\p{Other_ID_Continue}</tt>, <tt>\p{OIDC}</tt>
+- <tt>\p{Other_ID_Start}</tt>, <tt>\p{OIDS}</tt>
+- <tt>\p{Other_Lowercase}</tt>, <tt>\p{OLower}</tt>
+- <tt>\p{Other_Math}</tt>, <tt>\p{OMath}</tt>
+- <tt>\p{Other_Uppercase}</tt>, <tt>\p{OUpper}</tt>
+- <tt>\p{Pattern_Syntax}</tt>, <tt>\p{Pat_Syn}</tt>
+- <tt>\p{Pattern_White_Space}</tt>, <tt>\p{Pat_WS}</tt>
+- <tt>\p{Prepended_Concatenation_Mark}</tt>, <tt>\p{PCM}</tt>
+- <tt>\p{Quotation_Mark}</tt>, <tt>\p{QMark}</tt>
+- <tt>\p{Radical}</tt>
+- <tt>\p{Regional_Indicator}</tt>, <tt>\p{RI}</tt>
+- <tt>\p{Sentence_Terminal}</tt>, <tt>\p{STerm}</tt>
+- <tt>\p{Soft_Dotted}</tt>, <tt>\p{SD}</tt>
+- <tt>\p{Terminal_Punctuation}</tt>, <tt>\p{Term}</tt>
+- <tt>\p{Unified_Ideograph}</tt>, <tt>\p{UIdeo}</tt>
+- <tt>\p{Variation_Selector}</tt>, <tt>\p{VS}</tt>
+- <tt>\p{White_Space}</tt>, <tt>\p{WSpace}</tt>
+
+=== Derived Core Properties
+
+- <tt>\p{Alphabetic}</tt>, <tt>\p{Alpha}</tt>
+- <tt>\p{Case_Ignorable}</tt>, <tt>\p{CI}</tt>
+- <tt>\p{Cased}</tt>
+- <tt>\p{Changes_When_Casefolded}</tt>, <tt>\p{CWCF}</tt>
+- <tt>\p{Changes_When_Casemapped}</tt>, <tt>\p{CWCM}</tt>
+- <tt>\p{Changes_When_Lowercased}</tt>, <tt>\p{CWL}</tt>
+- <tt>\p{Changes_When_Titlecased}</tt>, <tt>\p{CWT}</tt>
+- <tt>\p{Changes_When_Uppercased}</tt>, <tt>\p{CWU}</tt>
+- <tt>\p{Default_Ignorable_Code_Point}</tt>, <tt>\p{DI}</tt>
+- <tt>\p{Grapheme_Base}</tt>, <tt>\p{Gr_Base}</tt>
+- <tt>\p{Grapheme_Extend}</tt>, <tt>\p{Gr_Ext}</tt>
+- <tt>\p{Grapheme_Link}</tt>, <tt>\p{Gr_Link}</tt>
+- <tt>\p{ID_Continue}</tt>, <tt>\p{IDC}</tt>
+- <tt>\p{ID_Start}</tt>, <tt>\p{IDS}</tt>
+- <tt>\p{InCB_Consonant}</tt>
+- <tt>\p{InCB_Extend}</tt>
+- <tt>\p{InCB_Linker}</tt>
+- <tt>\p{Lowercase}</tt>, <tt>\p{Lower}</tt>
+- <tt>\p{Math}</tt>
+- <tt>\p{Uppercase}</tt>, <tt>\p{Upper}</tt>
+- <tt>\p{XID_Continue}</tt>, <tt>\p{XIDC}</tt>
+- <tt>\p{XID_Start}</tt>, <tt>\p{XIDS}</tt>
+
+=== Scripts
+
+- <tt>\p{Adlam}</tt>, <tt>\p{Adlm}</tt>
+- <tt>\p{Ahom}</tt>
+- <tt>\p{Anatolian_Hieroglyphs}</tt>, <tt>\p{Hluw}</tt>
+- <tt>\p{Arabic}</tt>, <tt>\p{Arab}</tt>
+- <tt>\p{Armenian}</tt>, <tt>\p{Armn}</tt>
+- <tt>\p{Avestan}</tt>, <tt>\p{Avst}</tt>
+- <tt>\p{Balinese}</tt>, <tt>\p{Bali}</tt>
+- <tt>\p{Bamum}</tt>, <tt>\p{Bamu}</tt>
+- <tt>\p{Bassa_Vah}</tt>, <tt>\p{Bass}</tt>
+- <tt>\p{Batak}</tt>, <tt>\p{Batk}</tt>
+- <tt>\p{Bengali}</tt>, <tt>\p{Beng}</tt>
+- <tt>\p{Beria_Erfe}</tt>, <tt>\p{Berf}</tt>
+- <tt>\p{Bhaiksuki}</tt>, <tt>\p{Bhks}</tt>
+- <tt>\p{Bopomofo}</tt>, <tt>\p{Bopo}</tt>
+- <tt>\p{Brahmi}</tt>, <tt>\p{Brah}</tt>
+- <tt>\p{Braille}</tt>, <tt>\p{Brai}</tt>
+- <tt>\p{Buginese}</tt>, <tt>\p{Bugi}</tt>
+- <tt>\p{Buhid}</tt>, <tt>\p{Buhd}</tt>
+- <tt>\p{Canadian_Aboriginal}</tt>, <tt>\p{Cans}</tt>
+- <tt>\p{Carian}</tt>, <tt>\p{Cari}</tt>
+- <tt>\p{Caucasian_Albanian}</tt>, <tt>\p{Aghb}</tt>
+- <tt>\p{Chakma}</tt>, <tt>\p{Cakm}</tt>
+- <tt>\p{Cham}</tt>
+- <tt>\p{Cherokee}</tt>, <tt>\p{Cher}</tt>
+- <tt>\p{Chorasmian}</tt>, <tt>\p{Chrs}</tt>
+- <tt>\p{Common}</tt>, <tt>\p{Zyyy}</tt>
+- <tt>\p{Coptic}</tt>, <tt>\p{Copt}</tt>
+- <tt>\p{Cuneiform}</tt>, <tt>\p{Xsux}</tt>
+- <tt>\p{Cypriot}</tt>, <tt>\p{Cprt}</tt>
+- <tt>\p{Cypro_Minoan}</tt>, <tt>\p{Cpmn}</tt>
+- <tt>\p{Cyrillic}</tt>, <tt>\p{Cyrl}</tt>
+- <tt>\p{Deseret}</tt>, <tt>\p{Dsrt}</tt>
+- <tt>\p{Devanagari}</tt>, <tt>\p{Deva}</tt>
+- <tt>\p{Dives_Akuru}</tt>, <tt>\p{Diak}</tt>
+- <tt>\p{Dogra}</tt>, <tt>\p{Dogr}</tt>
+- <tt>\p{Duployan}</tt>, <tt>\p{Dupl}</tt>
+- <tt>\p{Egyptian_Hieroglyphs}</tt>, <tt>\p{Egyp}</tt>
+- <tt>\p{Elbasan}</tt>, <tt>\p{Elba}</tt>
+- <tt>\p{Elymaic}</tt>, <tt>\p{Elym}</tt>
+- <tt>\p{Ethiopic}</tt>, <tt>\p{Ethi}</tt>
+- <tt>\p{Garay}</tt>, <tt>\p{Gara}</tt>
+- <tt>\p{Georgian}</tt>, <tt>\p{Geor}</tt>
+- <tt>\p{Glagolitic}</tt>, <tt>\p{Glag}</tt>
+- <tt>\p{Gothic}</tt>, <tt>\p{Goth}</tt>
+- <tt>\p{Grantha}</tt>, <tt>\p{Gran}</tt>
+- <tt>\p{Greek}</tt>, <tt>\p{Grek}</tt>
+- <tt>\p{Gujarati}</tt>, <tt>\p{Gujr}</tt>
+- <tt>\p{Gunjala_Gondi}</tt>, <tt>\p{Gong}</tt>
+- <tt>\p{Gurmukhi}</tt>, <tt>\p{Guru}</tt>
+- <tt>\p{Gurung_Khema}</tt>, <tt>\p{Gukh}</tt>
+- <tt>\p{Han}</tt>, <tt>\p{Hani}</tt>
+- <tt>\p{Hangul}</tt>, <tt>\p{Hang}</tt>
+- <tt>\p{Hanifi_Rohingya}</tt>, <tt>\p{Rohg}</tt>
+- <tt>\p{Hanunoo}</tt>, <tt>\p{Hano}</tt>
+- <tt>\p{Hatran}</tt>, <tt>\p{Hatr}</tt>
+- <tt>\p{Hebrew}</tt>, <tt>\p{Hebr}</tt>
+- <tt>\p{Hiragana}</tt>, <tt>\p{Hira}</tt>
+- <tt>\p{Imperial_Aramaic}</tt>, <tt>\p{Armi}</tt>
+- <tt>\p{Inherited}</tt>, <tt>\p{Zinh}</tt>
+- <tt>\p{Inscriptional_Pahlavi}</tt>, <tt>\p{Phli}</tt>
+- <tt>\p{Inscriptional_Parthian}</tt>, <tt>\p{Prti}</tt>
+- <tt>\p{Javanese}</tt>, <tt>\p{Java}</tt>
+- <tt>\p{Kaithi}</tt>, <tt>\p{Kthi}</tt>
+- <tt>\p{Kannada}</tt>, <tt>\p{Knda}</tt>
+- <tt>\p{Katakana}</tt>, <tt>\p{Kana}</tt>
+- <tt>\p{Kawi}</tt>
+- <tt>\p{Kayah_Li}</tt>, <tt>\p{Kali}</tt>
+- <tt>\p{Kharoshthi}</tt>, <tt>\p{Khar}</tt>
+- <tt>\p{Khitan_Small_Script}</tt>, <tt>\p{Kits}</tt>
+- <tt>\p{Khmer}</tt>, <tt>\p{Khmr}</tt>
+- <tt>\p{Khojki}</tt>, <tt>\p{Khoj}</tt>
+- <tt>\p{Khudawadi}</tt>, <tt>\p{Sind}</tt>
+- <tt>\p{Kirat_Rai}</tt>, <tt>\p{Krai}</tt>
+- <tt>\p{Lao}</tt>, <tt>\p{Laoo}</tt>
+- <tt>\p{Latin}</tt>, <tt>\p{Latn}</tt>
+- <tt>\p{Lepcha}</tt>, <tt>\p{Lepc}</tt>
+- <tt>\p{Limbu}</tt>, <tt>\p{Limb}</tt>
+- <tt>\p{Linear_A}</tt>, <tt>\p{Lina}</tt>
+- <tt>\p{Linear_B}</tt>, <tt>\p{Linb}</tt>
+- <tt>\p{Lisu}</tt>
+- <tt>\p{Lycian}</tt>, <tt>\p{Lyci}</tt>
+- <tt>\p{Lydian}</tt>, <tt>\p{Lydi}</tt>
+- <tt>\p{Mahajani}</tt>, <tt>\p{Mahj}</tt>
+- <tt>\p{Makasar}</tt>, <tt>\p{Maka}</tt>
+- <tt>\p{Malayalam}</tt>, <tt>\p{Mlym}</tt>
+- <tt>\p{Mandaic}</tt>, <tt>\p{Mand}</tt>
+- <tt>\p{Manichaean}</tt>, <tt>\p{Mani}</tt>
+- <tt>\p{Marchen}</tt>, <tt>\p{Marc}</tt>
+- <tt>\p{Masaram_Gondi}</tt>, <tt>\p{Gonm}</tt>
+- <tt>\p{Medefaidrin}</tt>, <tt>\p{Medf}</tt>
+- <tt>\p{Meetei_Mayek}</tt>, <tt>\p{Mtei}</tt>
+- <tt>\p{Mende_Kikakui}</tt>, <tt>\p{Mend}</tt>
+- <tt>\p{Meroitic_Cursive}</tt>, <tt>\p{Merc}</tt>
+- <tt>\p{Meroitic_Hieroglyphs}</tt>, <tt>\p{Mero}</tt>
+- <tt>\p{Miao}</tt>, <tt>\p{Plrd}</tt>
+- <tt>\p{Modi}</tt>
+- <tt>\p{Mongolian}</tt>, <tt>\p{Mong}</tt>
+- <tt>\p{Mro}</tt>, <tt>\p{Mroo}</tt>
+- <tt>\p{Multani}</tt>, <tt>\p{Mult}</tt>
+- <tt>\p{Myanmar}</tt>, <tt>\p{Mymr}</tt>
+- <tt>\p{Nabataean}</tt>, <tt>\p{Nbat}</tt>
+- <tt>\p{Nag_Mundari}</tt>, <tt>\p{Nagm}</tt>
+- <tt>\p{Nandinagari}</tt>, <tt>\p{Nand}</tt>
+- <tt>\p{New_Tai_Lue}</tt>, <tt>\p{Talu}</tt>
+- <tt>\p{Newa}</tt>
+- <tt>\p{Nko}</tt>, <tt>\p{Nkoo}</tt>
+- <tt>\p{Nushu}</tt>, <tt>\p{Nshu}</tt>
+- <tt>\p{Nyiakeng_Puachue_Hmong}</tt>, <tt>\p{Hmnp}</tt>
+- <tt>\p{Ogham}</tt>, <tt>\p{Ogam}</tt>
+- <tt>\p{Ol_Chiki}</tt>, <tt>\p{Olck}</tt>
+- <tt>\p{Ol_Onal}</tt>, <tt>\p{Onao}</tt>
+- <tt>\p{Old_Hungarian}</tt>, <tt>\p{Hung}</tt>
+- <tt>\p{Old_Italic}</tt>, <tt>\p{Ital}</tt>
+- <tt>\p{Old_North_Arabian}</tt>, <tt>\p{Narb}</tt>
+- <tt>\p{Old_Permic}</tt>, <tt>\p{Perm}</tt>
+- <tt>\p{Old_Persian}</tt>, <tt>\p{Xpeo}</tt>
+- <tt>\p{Old_Sogdian}</tt>, <tt>\p{Sogo}</tt>
+- <tt>\p{Old_South_Arabian}</tt>, <tt>\p{Sarb}</tt>
+- <tt>\p{Old_Turkic}</tt>, <tt>\p{Orkh}</tt>
+- <tt>\p{Old_Uyghur}</tt>, <tt>\p{Ougr}</tt>
+- <tt>\p{Oriya}</tt>, <tt>\p{Orya}</tt>
+- <tt>\p{Osage}</tt>, <tt>\p{Osge}</tt>
+- <tt>\p{Osmanya}</tt>, <tt>\p{Osma}</tt>
+- <tt>\p{Pahawh_Hmong}</tt>, <tt>\p{Hmng}</tt>
+- <tt>\p{Palmyrene}</tt>, <tt>\p{Palm}</tt>
+- <tt>\p{Pau_Cin_Hau}</tt>, <tt>\p{Pauc}</tt>
+- <tt>\p{Phags_Pa}</tt>, <tt>\p{Phag}</tt>
+- <tt>\p{Phoenician}</tt>, <tt>\p{Phnx}</tt>
+- <tt>\p{Psalter_Pahlavi}</tt>, <tt>\p{Phlp}</tt>
+- <tt>\p{Rejang}</tt>, <tt>\p{Rjng}</tt>
+- <tt>\p{Runic}</tt>, <tt>\p{Runr}</tt>
+- <tt>\p{Samaritan}</tt>, <tt>\p{Samr}</tt>
+- <tt>\p{Saurashtra}</tt>, <tt>\p{Saur}</tt>
+- <tt>\p{Sharada}</tt>, <tt>\p{Shrd}</tt>
+- <tt>\p{Shavian}</tt>, <tt>\p{Shaw}</tt>
+- <tt>\p{Siddham}</tt>, <tt>\p{Sidd}</tt>
+- <tt>\p{Sidetic}</tt>, <tt>\p{Sidt}</tt>
+- <tt>\p{SignWriting}</tt>, <tt>\p{Sgnw}</tt>
+- <tt>\p{Sinhala}</tt>, <tt>\p{Sinh}</tt>
+- <tt>\p{Sogdian}</tt>, <tt>\p{Sogd}</tt>
+- <tt>\p{Sora_Sompeng}</tt>, <tt>\p{Sora}</tt>
+- <tt>\p{Soyombo}</tt>, <tt>\p{Soyo}</tt>
+- <tt>\p{Sundanese}</tt>, <tt>\p{Sund}</tt>
+- <tt>\p{Sunuwar}</tt>, <tt>\p{Sunu}</tt>
+- <tt>\p{Syloti_Nagri}</tt>, <tt>\p{Sylo}</tt>
+- <tt>\p{Syriac}</tt>, <tt>\p{Syrc}</tt>
+- <tt>\p{Tagalog}</tt>, <tt>\p{Tglg}</tt>
+- <tt>\p{Tagbanwa}</tt>, <tt>\p{Tagb}</tt>
+- <tt>\p{Tai_Le}</tt>, <tt>\p{Tale}</tt>
+- <tt>\p{Tai_Tham}</tt>, <tt>\p{Lana}</tt>
+- <tt>\p{Tai_Viet}</tt>, <tt>\p{Tavt}</tt>
+- <tt>\p{Tai_Yo}</tt>, <tt>\p{Tayo}</tt>
+- <tt>\p{Takri}</tt>, <tt>\p{Takr}</tt>
+- <tt>\p{Tamil}</tt>, <tt>\p{Taml}</tt>
+- <tt>\p{Tangsa}</tt>, <tt>\p{Tnsa}</tt>
+- <tt>\p{Tangut}</tt>, <tt>\p{Tang}</tt>
+- <tt>\p{Telugu}</tt>, <tt>\p{Telu}</tt>
+- <tt>\p{Thaana}</tt>, <tt>\p{Thaa}</tt>
+- <tt>\p{Thai}</tt>
+- <tt>\p{Tibetan}</tt>, <tt>\p{Tibt}</tt>
+- <tt>\p{Tifinagh}</tt>, <tt>\p{Tfng}</tt>
+- <tt>\p{Tirhuta}</tt>, <tt>\p{Tirh}</tt>
+- <tt>\p{Todhri}</tt>, <tt>\p{Todr}</tt>
+- <tt>\p{Tolong_Siki}</tt>, <tt>\p{Tols}</tt>
+- <tt>\p{Toto}</tt>
+- <tt>\p{Tulu_Tigalari}</tt>, <tt>\p{Tutg}</tt>
+- <tt>\p{Ugaritic}</tt>, <tt>\p{Ugar}</tt>
+- <tt>\p{Unknown}</tt>, <tt>\p{Zzzz}</tt>
+- <tt>\p{Vai}</tt>, <tt>\p{Vaii}</tt>
+- <tt>\p{Vithkuqi}</tt>, <tt>\p{Vith}</tt>
+- <tt>\p{Wancho}</tt>, <tt>\p{Wcho}</tt>
+- <tt>\p{Warang_Citi}</tt>, <tt>\p{Wara}</tt>
+- <tt>\p{Yezidi}</tt>, <tt>\p{Yezi}</tt>
+- <tt>\p{Yi}</tt>, <tt>\p{Yiii}</tt>
+- <tt>\p{Zanabazar_Square}</tt>, <tt>\p{Zanb}</tt>
+
+=== Blocks
+
+- <tt>\p{In_Adlam}</tt>
+- <tt>\p{In_Aegean_Numbers}</tt>
+- <tt>\p{In_Ahom}</tt>
+- <tt>\p{In_Alchemical_Symbols}</tt>
+- <tt>\p{In_Alphabetic_Presentation_Forms}</tt>
+- <tt>\p{In_Anatolian_Hieroglyphs}</tt>
+- <tt>\p{In_Ancient_Greek_Musical_Notation}</tt>
+- <tt>\p{In_Ancient_Greek_Numbers}</tt>
+- <tt>\p{In_Ancient_Symbols}</tt>
+- <tt>\p{In_Arabic}</tt>
+- <tt>\p{In_Arabic_Extended_A}</tt>
+- <tt>\p{In_Arabic_Extended_B}</tt>
+- <tt>\p{In_Arabic_Extended_C}</tt>
+- <tt>\p{In_Arabic_Mathematical_Alphabetic_Symbols}</tt>
+- <tt>\p{In_Arabic_Presentation_Forms_A}</tt>
+- <tt>\p{In_Arabic_Presentation_Forms_B}</tt>
+- <tt>\p{In_Arabic_Supplement}</tt>
+- <tt>\p{In_Armenian}</tt>
+- <tt>\p{In_Arrows}</tt>
+- <tt>\p{In_Avestan}</tt>
+- <tt>\p{In_Balinese}</tt>
+- <tt>\p{In_Bamum}</tt>
+- <tt>\p{In_Bamum_Supplement}</tt>
+- <tt>\p{In_Basic_Latin}</tt>
+- <tt>\p{In_Bassa_Vah}</tt>
+- <tt>\p{In_Batak}</tt>
+- <tt>\p{In_Bengali}</tt>
+- <tt>\p{In_Beria_Erfe}</tt>
+- <tt>\p{In_Bhaiksuki}</tt>
+- <tt>\p{In_Block_Elements}</tt>
+- <tt>\p{In_Bopomofo}</tt>
+- <tt>\p{In_Bopomofo_Extended}</tt>
+- <tt>\p{In_Box_Drawing}</tt>
+- <tt>\p{In_Brahmi}</tt>
+- <tt>\p{In_Braille_Patterns}</tt>
+- <tt>\p{In_Buginese}</tt>
+- <tt>\p{In_Buhid}</tt>
+- <tt>\p{In_Byzantine_Musical_Symbols}</tt>
+- <tt>\p{In_CJK_Compatibility}</tt>
+- <tt>\p{In_CJK_Compatibility_Forms}</tt>
+- <tt>\p{In_CJK_Compatibility_Ideographs}</tt>
+- <tt>\p{In_CJK_Compatibility_Ideographs_Supplement}</tt>
+- <tt>\p{In_CJK_Radicals_Supplement}</tt>
+- <tt>\p{In_CJK_Strokes}</tt>
+- <tt>\p{In_CJK_Symbols_and_Punctuation}</tt>
+- <tt>\p{In_CJK_Unified_Ideographs}</tt>
+- <tt>\p{In_CJK_Unified_Ideographs_Extension_A}</tt>
+- <tt>\p{In_CJK_Unified_Ideographs_Extension_B}</tt>
+- <tt>\p{In_CJK_Unified_Ideographs_Extension_C}</tt>
+- <tt>\p{In_CJK_Unified_Ideographs_Extension_D}</tt>
+- <tt>\p{In_CJK_Unified_Ideographs_Extension_E}</tt>
+- <tt>\p{In_CJK_Unified_Ideographs_Extension_F}</tt>
+- <tt>\p{In_CJK_Unified_Ideographs_Extension_G}</tt>
+- <tt>\p{In_CJK_Unified_Ideographs_Extension_H}</tt>
+- <tt>\p{In_CJK_Unified_Ideographs_Extension_I}</tt>
+- <tt>\p{In_CJK_Unified_Ideographs_Extension_J}</tt>
+- <tt>\p{In_Carian}</tt>
+- <tt>\p{In_Caucasian_Albanian}</tt>
+- <tt>\p{In_Chakma}</tt>
+- <tt>\p{In_Cham}</tt>
+- <tt>\p{In_Cherokee}</tt>
+- <tt>\p{In_Cherokee_Supplement}</tt>
+- <tt>\p{In_Chess_Symbols}</tt>
+- <tt>\p{In_Chorasmian}</tt>
+- <tt>\p{In_Combining_Diacritical_Marks}</tt>
+- <tt>\p{In_Combining_Diacritical_Marks_Extended}</tt>
+- <tt>\p{In_Combining_Diacritical_Marks_Supplement}</tt>
+- <tt>\p{In_Combining_Diacritical_Marks_for_Symbols}</tt>
+- <tt>\p{In_Combining_Half_Marks}</tt>
+- <tt>\p{In_Common_Indic_Number_Forms}</tt>
+- <tt>\p{In_Control_Pictures}</tt>
+- <tt>\p{In_Coptic}</tt>
+- <tt>\p{In_Coptic_Epact_Numbers}</tt>
+- <tt>\p{In_Counting_Rod_Numerals}</tt>
+- <tt>\p{In_Cuneiform}</tt>
+- <tt>\p{In_Cuneiform_Numbers_and_Punctuation}</tt>
+- <tt>\p{In_Currency_Symbols}</tt>
+- <tt>\p{In_Cypriot_Syllabary}</tt>
+- <tt>\p{In_Cypro_Minoan}</tt>
+- <tt>\p{In_Cyrillic}</tt>
+- <tt>\p{In_Cyrillic_Extended_A}</tt>
+- <tt>\p{In_Cyrillic_Extended_B}</tt>
+- <tt>\p{In_Cyrillic_Extended_C}</tt>
+- <tt>\p{In_Cyrillic_Extended_D}</tt>
+- <tt>\p{In_Cyrillic_Supplement}</tt>
+- <tt>\p{In_Deseret}</tt>
+- <tt>\p{In_Devanagari}</tt>
+- <tt>\p{In_Devanagari_Extended}</tt>
+- <tt>\p{In_Devanagari_Extended_A}</tt>
+- <tt>\p{In_Dingbats}</tt>
+- <tt>\p{In_Dives_Akuru}</tt>
+- <tt>\p{In_Dogra}</tt>
+- <tt>\p{In_Domino_Tiles}</tt>
+- <tt>\p{In_Duployan}</tt>
+- <tt>\p{In_Early_Dynastic_Cuneiform}</tt>
+- <tt>\p{In_Egyptian_Hieroglyph_Format_Controls}</tt>
+- <tt>\p{In_Egyptian_Hieroglyphs}</tt>
+- <tt>\p{In_Egyptian_Hieroglyphs_Extended_A}</tt>
+- <tt>\p{In_Elbasan}</tt>
+- <tt>\p{In_Elymaic}</tt>
+- <tt>\p{In_Emoticons}</tt>
+- <tt>\p{In_Enclosed_Alphanumeric_Supplement}</tt>
+- <tt>\p{In_Enclosed_Alphanumerics}</tt>
+- <tt>\p{In_Enclosed_CJK_Letters_and_Months}</tt>
+- <tt>\p{In_Enclosed_Ideographic_Supplement}</tt>
+- <tt>\p{In_Ethiopic}</tt>
+- <tt>\p{In_Ethiopic_Extended}</tt>
+- <tt>\p{In_Ethiopic_Extended_A}</tt>
+- <tt>\p{In_Ethiopic_Extended_B}</tt>
+- <tt>\p{In_Ethiopic_Supplement}</tt>
+- <tt>\p{In_Garay}</tt>
+- <tt>\p{In_General_Punctuation}</tt>
+- <tt>\p{In_Geometric_Shapes}</tt>
+- <tt>\p{In_Geometric_Shapes_Extended}</tt>
+- <tt>\p{In_Georgian}</tt>
+- <tt>\p{In_Georgian_Extended}</tt>
+- <tt>\p{In_Georgian_Supplement}</tt>
+- <tt>\p{In_Glagolitic}</tt>
+- <tt>\p{In_Glagolitic_Supplement}</tt>
+- <tt>\p{In_Gothic}</tt>
+- <tt>\p{In_Grantha}</tt>
+- <tt>\p{In_Greek_Extended}</tt>
+- <tt>\p{In_Greek_and_Coptic}</tt>
+- <tt>\p{In_Gujarati}</tt>
+- <tt>\p{In_Gunjala_Gondi}</tt>
+- <tt>\p{In_Gurmukhi}</tt>
+- <tt>\p{In_Gurung_Khema}</tt>
+- <tt>\p{In_Halfwidth_and_Fullwidth_Forms}</tt>
+- <tt>\p{In_Hangul_Compatibility_Jamo}</tt>
+- <tt>\p{In_Hangul_Jamo}</tt>
+- <tt>\p{In_Hangul_Jamo_Extended_A}</tt>
+- <tt>\p{In_Hangul_Jamo_Extended_B}</tt>
+- <tt>\p{In_Hangul_Syllables}</tt>
+- <tt>\p{In_Hanifi_Rohingya}</tt>
+- <tt>\p{In_Hanunoo}</tt>
+- <tt>\p{In_Hatran}</tt>
+- <tt>\p{In_Hebrew}</tt>
+- <tt>\p{In_High_Private_Use_Surrogates}</tt>
+- <tt>\p{In_High_Surrogates}</tt>
+- <tt>\p{In_Hiragana}</tt>
+- <tt>\p{In_IPA_Extensions}</tt>
+- <tt>\p{In_Ideographic_Description_Characters}</tt>
+- <tt>\p{In_Ideographic_Symbols_and_Punctuation}</tt>
+- <tt>\p{In_Imperial_Aramaic}</tt>
+- <tt>\p{In_Indic_Siyaq_Numbers}</tt>
+- <tt>\p{In_Inscriptional_Pahlavi}</tt>
+- <tt>\p{In_Inscriptional_Parthian}</tt>
+- <tt>\p{In_Javanese}</tt>
+- <tt>\p{In_Kaithi}</tt>
+- <tt>\p{In_Kaktovik_Numerals}</tt>
+- <tt>\p{In_Kana_Extended_A}</tt>
+- <tt>\p{In_Kana_Extended_B}</tt>
+- <tt>\p{In_Kana_Supplement}</tt>
+- <tt>\p{In_Kanbun}</tt>
+- <tt>\p{In_Kangxi_Radicals}</tt>
+- <tt>\p{In_Kannada}</tt>
+- <tt>\p{In_Katakana}</tt>
+- <tt>\p{In_Katakana_Phonetic_Extensions}</tt>
+- <tt>\p{In_Kawi}</tt>
+- <tt>\p{In_Kayah_Li}</tt>
+- <tt>\p{In_Kharoshthi}</tt>
+- <tt>\p{In_Khitan_Small_Script}</tt>
+- <tt>\p{In_Khmer}</tt>
+- <tt>\p{In_Khmer_Symbols}</tt>
+- <tt>\p{In_Khojki}</tt>
+- <tt>\p{In_Khudawadi}</tt>
+- <tt>\p{In_Kirat_Rai}</tt>
+- <tt>\p{In_Lao}</tt>
+- <tt>\p{In_Latin_1_Supplement}</tt>
+- <tt>\p{In_Latin_Extended_A}</tt>
+- <tt>\p{In_Latin_Extended_Additional}</tt>
+- <tt>\p{In_Latin_Extended_B}</tt>
+- <tt>\p{In_Latin_Extended_C}</tt>
+- <tt>\p{In_Latin_Extended_D}</tt>
+- <tt>\p{In_Latin_Extended_E}</tt>
+- <tt>\p{In_Latin_Extended_F}</tt>
+- <tt>\p{In_Latin_Extended_G}</tt>
+- <tt>\p{In_Lepcha}</tt>
+- <tt>\p{In_Letterlike_Symbols}</tt>
+- <tt>\p{In_Limbu}</tt>
+- <tt>\p{In_Linear_A}</tt>
+- <tt>\p{In_Linear_B_Ideograms}</tt>
+- <tt>\p{In_Linear_B_Syllabary}</tt>
+- <tt>\p{In_Lisu}</tt>
+- <tt>\p{In_Lisu_Supplement}</tt>
+- <tt>\p{In_Low_Surrogates}</tt>
+- <tt>\p{In_Lycian}</tt>
+- <tt>\p{In_Lydian}</tt>
+- <tt>\p{In_Mahajani}</tt>
+- <tt>\p{In_Mahjong_Tiles}</tt>
+- <tt>\p{In_Makasar}</tt>
+- <tt>\p{In_Malayalam}</tt>
+- <tt>\p{In_Mandaic}</tt>
+- <tt>\p{In_Manichaean}</tt>
+- <tt>\p{In_Marchen}</tt>
+- <tt>\p{In_Masaram_Gondi}</tt>
+- <tt>\p{In_Mathematical_Alphanumeric_Symbols}</tt>
+- <tt>\p{In_Mathematical_Operators}</tt>
+- <tt>\p{In_Mayan_Numerals}</tt>
+- <tt>\p{In_Medefaidrin}</tt>
+- <tt>\p{In_Meetei_Mayek}</tt>
+- <tt>\p{In_Meetei_Mayek_Extensions}</tt>
+- <tt>\p{In_Mende_Kikakui}</tt>
+- <tt>\p{In_Meroitic_Cursive}</tt>
+- <tt>\p{In_Meroitic_Hieroglyphs}</tt>
+- <tt>\p{In_Miao}</tt>
+- <tt>\p{In_Miscellaneous_Mathematical_Symbols_A}</tt>
+- <tt>\p{In_Miscellaneous_Mathematical_Symbols_B}</tt>
+- <tt>\p{In_Miscellaneous_Symbols}</tt>
+- <tt>\p{In_Miscellaneous_Symbols_Supplement}</tt>
+- <tt>\p{In_Miscellaneous_Symbols_and_Arrows}</tt>
+- <tt>\p{In_Miscellaneous_Symbols_and_Pictographs}</tt>
+- <tt>\p{In_Miscellaneous_Technical}</tt>
+- <tt>\p{In_Modi}</tt>
+- <tt>\p{In_Modifier_Tone_Letters}</tt>
+- <tt>\p{In_Mongolian}</tt>
+- <tt>\p{In_Mongolian_Supplement}</tt>
+- <tt>\p{In_Mro}</tt>
+- <tt>\p{In_Multani}</tt>
+- <tt>\p{In_Musical_Symbols}</tt>
+- <tt>\p{In_Myanmar}</tt>
+- <tt>\p{In_Myanmar_Extended_A}</tt>
+- <tt>\p{In_Myanmar_Extended_B}</tt>
+- <tt>\p{In_Myanmar_Extended_C}</tt>
+- <tt>\p{In_NKo}</tt>
+- <tt>\p{In_Nabataean}</tt>
+- <tt>\p{In_Nag_Mundari}</tt>
+- <tt>\p{In_Nandinagari}</tt>
+- <tt>\p{In_New_Tai_Lue}</tt>
+- <tt>\p{In_Newa}</tt>
+- <tt>\p{In_No_Block}</tt>
+- <tt>\p{In_Number_Forms}</tt>
+- <tt>\p{In_Nushu}</tt>
+- <tt>\p{In_Nyiakeng_Puachue_Hmong}</tt>
+- <tt>\p{In_Ogham}</tt>
+- <tt>\p{In_Ol_Chiki}</tt>
+- <tt>\p{In_Ol_Onal}</tt>
+- <tt>\p{In_Old_Hungarian}</tt>
+- <tt>\p{In_Old_Italic}</tt>
+- <tt>\p{In_Old_North_Arabian}</tt>
+- <tt>\p{In_Old_Permic}</tt>
+- <tt>\p{In_Old_Persian}</tt>
+- <tt>\p{In_Old_Sogdian}</tt>
+- <tt>\p{In_Old_South_Arabian}</tt>
+- <tt>\p{In_Old_Turkic}</tt>
+- <tt>\p{In_Old_Uyghur}</tt>
+- <tt>\p{In_Optical_Character_Recognition}</tt>
+- <tt>\p{In_Oriya}</tt>
+- <tt>\p{In_Ornamental_Dingbats}</tt>
+- <tt>\p{In_Osage}</tt>
+- <tt>\p{In_Osmanya}</tt>
+- <tt>\p{In_Ottoman_Siyaq_Numbers}</tt>
+- <tt>\p{In_Pahawh_Hmong}</tt>
+- <tt>\p{In_Palmyrene}</tt>
+- <tt>\p{In_Pau_Cin_Hau}</tt>
+- <tt>\p{In_Phags_pa}</tt>
+- <tt>\p{In_Phaistos_Disc}</tt>
+- <tt>\p{In_Phoenician}</tt>
+- <tt>\p{In_Phonetic_Extensions}</tt>
+- <tt>\p{In_Phonetic_Extensions_Supplement}</tt>
+- <tt>\p{In_Playing_Cards}</tt>
+- <tt>\p{In_Private_Use_Area}</tt>
+- <tt>\p{In_Psalter_Pahlavi}</tt>
+- <tt>\p{In_Rejang}</tt>
+- <tt>\p{In_Rumi_Numeral_Symbols}</tt>
+- <tt>\p{In_Runic}</tt>
+- <tt>\p{In_Samaritan}</tt>
+- <tt>\p{In_Saurashtra}</tt>
+- <tt>\p{In_Sharada}</tt>
+- <tt>\p{In_Sharada_Supplement}</tt>
+- <tt>\p{In_Shavian}</tt>
+- <tt>\p{In_Shorthand_Format_Controls}</tt>
+- <tt>\p{In_Siddham}</tt>
+- <tt>\p{In_Sidetic}</tt>
+- <tt>\p{In_Sinhala}</tt>
+- <tt>\p{In_Sinhala_Archaic_Numbers}</tt>
+- <tt>\p{In_Small_Form_Variants}</tt>
+- <tt>\p{In_Small_Kana_Extension}</tt>
+- <tt>\p{In_Sogdian}</tt>
+- <tt>\p{In_Sora_Sompeng}</tt>
+- <tt>\p{In_Soyombo}</tt>
+- <tt>\p{In_Spacing_Modifier_Letters}</tt>
+- <tt>\p{In_Specials}</tt>
+- <tt>\p{In_Sundanese}</tt>
+- <tt>\p{In_Sundanese_Supplement}</tt>
+- <tt>\p{In_Sunuwar}</tt>
+- <tt>\p{In_Superscripts_and_Subscripts}</tt>
+- <tt>\p{In_Supplemental_Arrows_A}</tt>
+- <tt>\p{In_Supplemental_Arrows_B}</tt>
+- <tt>\p{In_Supplemental_Arrows_C}</tt>
+- <tt>\p{In_Supplemental_Mathematical_Operators}</tt>
+- <tt>\p{In_Supplemental_Punctuation}</tt>
+- <tt>\p{In_Supplemental_Symbols_and_Pictographs}</tt>
+- <tt>\p{In_Supplementary_Private_Use_Area_A}</tt>
+- <tt>\p{In_Supplementary_Private_Use_Area_B}</tt>
+- <tt>\p{In_Sutton_SignWriting}</tt>
+- <tt>\p{In_Syloti_Nagri}</tt>
+- <tt>\p{In_Symbols_and_Pictographs_Extended_A}</tt>
+- <tt>\p{In_Symbols_for_Legacy_Computing}</tt>
+- <tt>\p{In_Symbols_for_Legacy_Computing_Supplement}</tt>
+- <tt>\p{In_Syriac}</tt>
+- <tt>\p{In_Syriac_Supplement}</tt>
+- <tt>\p{In_Tagalog}</tt>
+- <tt>\p{In_Tagbanwa}</tt>
+- <tt>\p{In_Tags}</tt>
+- <tt>\p{In_Tai_Le}</tt>
+- <tt>\p{In_Tai_Tham}</tt>
+- <tt>\p{In_Tai_Viet}</tt>
+- <tt>\p{In_Tai_Xuan_Jing_Symbols}</tt>
+- <tt>\p{In_Tai_Yo}</tt>
+- <tt>\p{In_Takri}</tt>
+- <tt>\p{In_Tamil}</tt>
+- <tt>\p{In_Tamil_Supplement}</tt>
+- <tt>\p{In_Tangsa}</tt>
+- <tt>\p{In_Tangut}</tt>
+- <tt>\p{In_Tangut_Components}</tt>
+- <tt>\p{In_Tangut_Components_Supplement}</tt>
+- <tt>\p{In_Tangut_Supplement}</tt>
+- <tt>\p{In_Telugu}</tt>
+- <tt>\p{In_Thaana}</tt>
+- <tt>\p{In_Thai}</tt>
+- <tt>\p{In_Tibetan}</tt>
+- <tt>\p{In_Tifinagh}</tt>
+- <tt>\p{In_Tirhuta}</tt>
+- <tt>\p{In_Todhri}</tt>
+- <tt>\p{In_Tolong_Siki}</tt>
+- <tt>\p{In_Toto}</tt>
+- <tt>\p{In_Transport_and_Map_Symbols}</tt>
+- <tt>\p{In_Tulu_Tigalari}</tt>
+- <tt>\p{In_Ugaritic}</tt>
+- <tt>\p{In_Unified_Canadian_Aboriginal_Syllabics}</tt>
+- <tt>\p{In_Unified_Canadian_Aboriginal_Syllabics_Extended}</tt>
+- <tt>\p{In_Unified_Canadian_Aboriginal_Syllabics_Extended_A}</tt>
+- <tt>\p{In_Vai}</tt>
+- <tt>\p{In_Variation_Selectors}</tt>
+- <tt>\p{In_Variation_Selectors_Supplement}</tt>
+- <tt>\p{In_Vedic_Extensions}</tt>
+- <tt>\p{In_Vertical_Forms}</tt>
+- <tt>\p{In_Vithkuqi}</tt>
+- <tt>\p{In_Wancho}</tt>
+- <tt>\p{In_Warang_Citi}</tt>
+- <tt>\p{In_Yezidi}</tt>
+- <tt>\p{In_Yi_Radicals}</tt>
+- <tt>\p{In_Yi_Syllables}</tt>
+- <tt>\p{In_Yijing_Hexagram_Symbols}</tt>
+- <tt>\p{In_Zanabazar_Square}</tt>
+- <tt>\p{In_Znamenny_Musical_Notation}</tt>
+
+=== Emoji
+
+- <tt>\p{Emoji}</tt>
+- <tt>\p{Emoji_Component}</tt>, <tt>\p{EComp}</tt>
+- <tt>\p{Emoji_Modifier}</tt>, <tt>\p{EMod}</tt>
+- <tt>\p{Emoji_Modifier_Base}</tt>, <tt>\p{EBase}</tt>
+- <tt>\p{Emoji_Presentation}</tt>, <tt>\p{EPres}</tt>
+- <tt>\p{Extended_Pictographic}</tt>, <tt>\p{ExtPict}</tt>
+
+=== Graphemes
+
+- <tt>\p{Grapheme_Cluster_Break_CR}</tt>
+- <tt>\p{Grapheme_Cluster_Break_Control}</tt>
+- <tt>\p{Grapheme_Cluster_Break_Extend}</tt>
+- <tt>\p{Grapheme_Cluster_Break_L}</tt>
+- <tt>\p{Grapheme_Cluster_Break_LF}</tt>
+- <tt>\p{Grapheme_Cluster_Break_LV}</tt>
+- <tt>\p{Grapheme_Cluster_Break_LVT}</tt>
+- <tt>\p{Grapheme_Cluster_Break_Prepend}</tt>
+- <tt>\p{Grapheme_Cluster_Break_Regional_Indicator}</tt>
+- <tt>\p{Grapheme_Cluster_Break_SpacingMark}</tt>
+- <tt>\p{Grapheme_Cluster_Break_T}</tt>
+- <tt>\p{Grapheme_Cluster_Break_V}</tt>
+- <tt>\p{Grapheme_Cluster_Break_ZWJ}</tt>
+
+=== Derived Ages
+
+- <tt>\p{Age_10_0}</tt>
+- <tt>\p{Age_11_0}</tt>
+- <tt>\p{Age_12_0}</tt>
+- <tt>\p{Age_12_1}</tt>
+- <tt>\p{Age_13_0}</tt>
+- <tt>\p{Age_14_0}</tt>
+- <tt>\p{Age_15_0}</tt>
+- <tt>\p{Age_15_1}</tt>
+- <tt>\p{Age_16_0}</tt>
+- <tt>\p{Age_17_0}</tt>
+- <tt>\p{Age_1_1}</tt>
+- <tt>\p{Age_2_0}</tt>
+- <tt>\p{Age_2_1}</tt>
+- <tt>\p{Age_3_0}</tt>
+- <tt>\p{Age_3_1}</tt>
+- <tt>\p{Age_3_2}</tt>
+- <tt>\p{Age_4_0}</tt>
+- <tt>\p{Age_4_1}</tt>
+- <tt>\p{Age_5_0}</tt>
+- <tt>\p{Age_5_1}</tt>
+- <tt>\p{Age_5_2}</tt>
+- <tt>\p{Age_6_0}</tt>
+- <tt>\p{Age_6_1}</tt>
+- <tt>\p{Age_6_2}</tt>
+- <tt>\p{Age_6_3}</tt>
+- <tt>\p{Age_7_0}</tt>
+- <tt>\p{Age_8_0}</tt>
+- <tt>\p{Age_9_0}</tt>
diff --git a/doc/language/signals.rdoc b/doc/language/signals.rdoc
new file mode 100644
index 0000000000..a82dab81c6
--- /dev/null
+++ b/doc/language/signals.rdoc
@@ -0,0 +1,106 @@
+= Caveats for implementing Signal.trap callbacks
+
+As with implementing signal handlers in C or most other languages,
+all code passed to Signal.trap must be reentrant. If you are not
+familiar with reentrancy, you need to read up on it at
+{Wikipedia}[https://en.wikipedia.org/wiki/Reentrancy_(computing)] or
+elsewhere before reading the rest of this document.
+
+Most importantly, "thread-safety" does not guarantee reentrancy;
+and methods such as Mutex#lock and Mutex#synchronize which are
+commonly used for thread-safety even prevent reentrancy.
+
+== An implementation detail of the Ruby VM
+
+The Ruby VM defers Signal.trap callbacks from running until it is safe
+for its internal data structures, but it does not know when it is safe
+for data structures in YOUR code. Ruby implements deferred signal
+handling by registering short C functions with only
+{async-signal-safe functions}[http://man7.org/linux/man-pages/man7/signal-safety.7.html] as
+signal handlers. These short C functions only do enough to tell the VM to
+run callbacks registered via Signal.trap later in the main Ruby Thread.
+
+== Unsafe methods to call in Signal.trap blocks
+
+When in doubt, consider anything not listed as safe below as being
+unsafe.
+
+* Mutex#lock, Mutex#synchronize and any code using them are explicitly
+ unsafe. This includes Monitor in the standard library which uses
+ Mutex to provide reentrancy.
+
+* Dir.chdir with block
+
+* any IO write operations when IO#sync is false;
+ including IO#write, IO#write_nonblock, IO#puts.
+ Pipes and sockets default to `IO#sync = true', so it is safe to
+ write to them unless IO#sync was disabled.
+
+* File#flock, as the underlying flock(2) call is not specified by POSIX
+
+== Commonly safe operations inside Signal.trap blocks
+
+* Assignment and retrieval of local, instance, and class variables
+
+* Most object allocations and initializations of common types
+ including Array, Hash, String, Struct, Time.
+
+* Common Array, Hash, String, Struct operations which do not execute a block
+ are generally safe; but beware if iteration is occurring elsewhere.
+
+* Hash#[], Hash#[]= (unless Hash.new was given an unsafe block)
+
+* Thread::Queue#push and Thread::SizedQueue#push (since Ruby 2.1)
+
+* Creating a new Thread via Thread.new/Thread.start can used to get
+ around the unusability of Mutexes inside a signal handler
+
+* Signal.trap is safe to use inside blocks passed to Signal.trap
+
+* arithmetic on Integer and Float (`+', `-', '%', '*', '/')
+
+ Additionally, signal handlers do not run between two successive
+ local variable accesses, so shortcuts such as `+=' and `-=' will
+ not trigger a data race when used on Integer and Float classes in
+ signal handlers.
+
+== System call wrapper methods which are safe inside Signal.trap
+
+Since Ruby has wrappers around many
+{async-signal-safe C functions}[http://man7.org/linux/man-pages/man7/signal-safety.7.html]
+the corresponding wrappers for many IO, File, Dir, and Socket methods
+are safe.
+
+(Incomplete list)
+
+* Dir.chdir (without block arg)
+* Dir.mkdir
+* Dir.open
+* File#truncate
+* File.link
+* File.open
+* File.readlink
+* File.rename
+* File.stat
+* File.symlink
+* File.truncate
+* File.unlink
+* File.utime
+* IO#close
+* IO#dup
+* IO#fsync
+* IO#read
+* IO#read_nonblock
+* IO#stat
+* IO#sysread
+* IO#syswrite
+* IO.select
+* IO.pipe
+* Process.clock_gettime
+* Process.exit!
+* Process.fork
+* Process.kill
+* Process.pid
+* Process.ppid
+* Process.waitpid
+...
diff --git a/doc/language/strftime_formatting.rdoc b/doc/language/strftime_formatting.rdoc
new file mode 100644
index 0000000000..2bfa6b975e
--- /dev/null
+++ b/doc/language/strftime_formatting.rdoc
@@ -0,0 +1,525 @@
+= Formats for Dates and Times
+
+Several Ruby time-related classes have instance method +strftime+,
+which returns a formatted string representing all or part of a date or time:
+
+- Date#strftime.
+- DateTime#strftime.
+- Time#strftime.
+
+Each of these methods takes optional argument +format+,
+which has zero or more embedded _format_ _specifications_ (see below).
+
+Each of these methods returns the string resulting from replacing each
+format specification embedded in +format+ with a string form
+of one or more parts of the date or time.
+
+A simple example:
+
+ Time.now.strftime('%H:%M:%S') # => "14:02:07"
+
+A format specification has the form:
+
+ %[flags][width]conversion
+
+It consists of:
+
+- A leading percent character.
+- Zero or more _flags_ (each is a character).
+- An optional _width_ _specifier_ (an integer).
+- A _conversion_ _specifier_ (a character).
+
+Except for the leading percent character,
+the only required part is the conversion specifier, so we begin with that.
+
+== Conversion Specifiers
+
+=== \Date (Year, Month, Day)
+
+- <tt>%Y</tt> - Year including century, zero-padded:
+
+ Time.now.strftime('%Y') # => "2022"
+ Time.new(-1000).strftime('%Y') # => "-1000" # Before common era.
+ Time.new(10000).strftime('%Y') # => "10000" # Far future.
+ Time.new(10).strftime('%Y') # => "0010" # Zero-padded by default.
+
+- <tt>%y</tt> - Year without century, in range (0.99), zero-padded:
+
+ Time.now.strftime('%y') # => "22"
+ Time.new(1).strftime('%y') # => "01" # Zero-padded by default.
+
+- <tt>%C</tt> - Century, zero-padded:
+
+ Time.now.strftime('%C') # => "20"
+ Time.new(-1000).strftime('%C') # => "-10" # Before common era.
+ Time.new(10000).strftime('%C') # => "100" # Far future.
+ Time.new(100).strftime('%C') # => "01" # Zero-padded by default.
+
+- <tt>%m</tt> - Month of the year, in range (1..12), zero-padded:
+
+ Time.new(2022, 1).strftime('%m') # => "01" # Zero-padded by default.
+ Time.new(2022, 12).strftime('%m') # => "12"
+
+- <tt>%B</tt> - Full month name, capitalized:
+
+ Time.new(2022, 1).strftime('%B') # => "January"
+ Time.new(2022, 12).strftime('%B') # => "December"
+
+- <tt>%b</tt> - Abbreviated month name, capitalized:
+
+ Time.new(2022, 1).strftime('%b') # => "Jan"
+ Time.new(2022, 12).strftime('%h') # => "Dec"
+
+- <tt>%h</tt> - Same as <tt>%b</tt>.
+
+- <tt>%d</tt> - Day of the month, in range (1..31), zero-padded:
+
+ Time.new(2002, 1, 1).strftime('%d') # => "01"
+ Time.new(2002, 1, 31).strftime('%d') # => "31"
+
+- <tt>%e</tt> - Day of the month, in range (1..31), blank-padded:
+
+ Time.new(2002, 1, 1).strftime('%e') # => " 1"
+ Time.new(2002, 1, 31).strftime('%e') # => "31"
+
+- <tt>%j</tt> - Day of the year, in range (1..366), zero-padded:
+
+ Time.new(2002, 1, 1).strftime('%j') # => "001"
+ Time.new(2002, 12, 31).strftime('%j') # => "365"
+
+=== \Time (Hour, Minute, Second, Subsecond)
+
+- <tt>%H</tt> - Hour of the day, in range (0..23), zero-padded:
+
+ Time.new(2022, 1, 1, 1).strftime('%H') # => "01"
+ Time.new(2022, 1, 1, 13).strftime('%H') # => "13"
+
+- <tt>%k</tt> - Hour of the day, in range (0..23), blank-padded:
+
+ Time.new(2022, 1, 1, 1).strftime('%k') # => " 1"
+ Time.new(2022, 1, 1, 13).strftime('%k') # => "13"
+
+- <tt>%I</tt> - Hour of the day, in range (1..12), zero-padded:
+
+ Time.new(2022, 1, 1, 1).strftime('%I') # => "01"
+ Time.new(2022, 1, 1, 13).strftime('%I') # => "01"
+
+- <tt>%l</tt> - Hour of the day, in range (1..12), blank-padded:
+
+ Time.new(2022, 1, 1, 1).strftime('%l') # => " 1"
+ Time.new(2022, 1, 1, 13).strftime('%l') # => " 1"
+
+- <tt>%P</tt> - Meridian indicator, lowercase:
+
+ Time.new(2022, 1, 1, 1).strftime('%P') # => "am"
+ Time.new(2022, 1, 1, 13).strftime('%P') # => "pm"
+
+- <tt>%p</tt> - Meridian indicator, uppercase:
+
+ Time.new(2022, 1, 1, 1).strftime('%p') # => "AM"
+ Time.new(2022, 1, 1, 13).strftime('%p') # => "PM"
+
+- <tt>%M</tt> - Minute of the hour, in range (0..59), zero-padded:
+
+ Time.new(2022, 1, 1, 1, 0, 0).strftime('%M') # => "00"
+
+- <tt>%S</tt> - Second of the minute in range (0..59), zero-padded:
+
+ Time.new(2022, 1, 1, 1, 0, 0, 0).strftime('%S') # => "00"
+
+- <tt>%L</tt> - Millisecond of the second, in range (0..999), zero-padded:
+
+ Time.new(2022, 1, 1, 1, 0, 0, 0).strftime('%L') # => "000"
+
+- <tt>%N</tt> - Fractional seconds, default width is 9 digits (nanoseconds):
+
+ t = Time.now # => 2022-06-29 07:10:20.3230914 -0500
+ t.strftime('%N') # => "323091400" # Default.
+
+ Use {width specifiers}[rdoc-ref:@Width+Specifiers]
+ to adjust units:
+
+ t.strftime('%3N') # => "323" # Milliseconds.
+ t.strftime('%6N') # => "323091" # Microseconds.
+ t.strftime('%9N') # => "323091400" # Nanoseconds.
+ t.strftime('%12N') # => "323091400000" # Picoseconds.
+ t.strftime('%15N') # => "323091400000000" # Femptoseconds.
+ t.strftime('%18N') # => "323091400000000000" # Attoseconds.
+ t.strftime('%21N') # => "323091400000000000000" # Zeptoseconds.
+ t.strftime('%24N') # => "323091400000000000000000" # Yoctoseconds.
+
+- <tt>%s</tt> - Number of seconds since the epoch:
+
+ Time.now.strftime('%s') # => "1656505136"
+
+=== Timezone
+
+- <tt>%z</tt> - Timezone as hour and minute offset from UTC:
+
+ Time.now.strftime('%z') # => "-0500"
+
+- <tt>%Z</tt> - Timezone name (platform-dependent):
+
+ Time.now.strftime('%Z') # => "Central Daylight Time"
+
+=== Weekday
+
+- <tt>%A</tt> - Full weekday name:
+
+ Time.now.strftime('%A') # => "Wednesday"
+
+- <tt>%a</tt> - Abbreviated weekday name:
+
+ Time.now.strftime('%a') # => "Wed"
+
+- <tt>%u</tt> - Day of the week, in range (1..7), Monday is 1:
+
+ t = Time.new(2022, 6, 26) # => 2022-06-26 00:00:00 -0500
+ t.strftime('%a') # => "Sun"
+ t.strftime('%u') # => "7"
+
+- <tt>%w</tt> - Day of the week, in range (0..6), Sunday is 0:
+
+ t = Time.new(2022, 6, 26) # => 2022-06-26 00:00:00 -0500
+ t.strftime('%a') # => "Sun"
+ t.strftime('%w') # => "0"
+
+=== Week Number
+
+- <tt>%U</tt> - Week number of the year, in range (0..53), zero-padded,
+ where each week begins on a Sunday:
+
+ t = Time.new(2022, 6, 26) # => 2022-06-26 00:00:00 -0500
+ t.strftime('%a') # => "Sun"
+ t.strftime('%U') # => "26"
+
+- <tt>%W</tt> - Week number of the year, in range (0..53), zero-padded,
+ where each week begins on a Monday:
+
+ t = Time.new(2022, 6, 26) # => 2022-06-26 00:00:00 -0500
+ t.strftime('%a') # => "Sun"
+ t.strftime('%W') # => "25"
+
+=== Week Dates
+
+See {ISO 8601 week dates}[https://en.wikipedia.org/wiki/ISO_8601#Week_dates].
+
+ t0 = Time.new(2023, 1, 1) # => 2023-01-01 00:00:00 -0600
+ t1 = Time.new(2024, 1, 1) # => 2024-01-01 00:00:00 -0600
+
+- <tt>%G</tt> - Week-based year:
+
+ t0.strftime('%G') # => "2022"
+ t1.strftime('%G') # => "2024"
+
+- <tt>%g</tt> - Week-based year without century, in range (0..99), zero-padded:
+
+ t0.strftime('%g') # => "22"
+ t1.strftime('%g') # => "24"
+
+- <tt>%V</tt> - Week number of the week-based year, in range (1..53),
+ zero-padded:
+
+ t0.strftime('%V') # => "52"
+ t1.strftime('%V') # => "01"
+
+=== Literals
+
+- <tt>%n</tt> - Newline character "\n":
+
+ Time.now.strftime('%n') # => "\n"
+
+- <tt>%t</tt> - Tab character "\t":
+
+ Time.now.strftime('%t') # => "\t"
+
+- <tt>%%</tt> - Percent character '%':
+
+ Time.now.strftime('%%') # => "%"
+
+=== Shorthand Conversion Specifiers
+
+Each shorthand specifier here is shown with its corresponding
+longhand specifier.
+
+- <tt>%c</tt> - \Date and time:
+
+ Time.now.strftime('%c') # => "Wed Jun 29 08:01:41 2022"
+ Time.now.strftime('%a %b %e %T %Y') # => "Wed Jun 29 08:02:07 2022"
+
+- <tt>%D</tt> - \Date:
+
+ Time.now.strftime('%D') # => "06/29/22"
+ Time.now.strftime('%m/%d/%y') # => "06/29/22"
+
+- <tt>%F</tt> - ISO 8601 date:
+
+ Time.now.strftime('%F') # => "2022-06-29"
+ Time.now.strftime('%Y-%m-%d') # => "2022-06-29"
+
+- <tt>%v</tt> - VMS date:
+
+ Time.now.strftime('%v') # => "29-JUN-2022"
+ Time.now.strftime('%e-%^b-%4Y') # => "29-JUN-2022"
+
+- <tt>%x</tt> - Same as <tt>%D</tt>.
+
+- <tt>%X</tt> - Same as <tt>%T</tt>.
+
+- <tt>%r</tt> - 12-hour time:
+
+ Time.new(2022, 1, 1, 1).strftime('%r') # => "01:00:00 AM"
+ Time.new(2022, 1, 1, 1).strftime('%I:%M:%S %p') # => "01:00:00 AM"
+ Time.new(2022, 1, 1, 13).strftime('%r') # => "01:00:00 PM"
+ Time.new(2022, 1, 1, 13).strftime('%I:%M:%S %p') # => "01:00:00 PM"
+
+- <tt>%R</tt> - 24-hour time:
+
+ Time.new(2022, 1, 1, 1).strftime('%R') # => "01:00"
+ Time.new(2022, 1, 1, 1).strftime('%H:%M') # => "01:00"
+ Time.new(2022, 1, 1, 13).strftime('%R') # => "13:00"
+ Time.new(2022, 1, 1, 13).strftime('%H:%M') # => "13:00"
+
+- <tt>%T</tt> - 24-hour time:
+
+ Time.new(2022, 1, 1, 1).strftime('%T') # => "01:00:00"
+ Time.new(2022, 1, 1, 1).strftime('%H:%M:%S') # => "01:00:00"
+ Time.new(2022, 1, 1, 13).strftime('%T') # => "13:00:00"
+ Time.new(2022, 1, 1, 13).strftime('%H:%M:%S') # => "13:00:00"
+
+- <tt>%+</tt> (not supported in Time#strftime) - \Date and time:
+
+ DateTime.now.strftime('%+')
+ # => "Wed Jun 29 08:31:53 -05:00 2022"
+ DateTime.now.strftime('%a %b %e %H:%M:%S %Z %Y')
+ # => "Wed Jun 29 08:32:18 -05:00 2022"
+
+== Flags
+
+Flags may affect certain formatting specifications.
+
+Multiple flags may be given with a single conversion specified;
+order does not matter.
+
+=== Padding Flags
+
+- <tt>0</tt> - Pad with zeroes:
+
+ Time.new(10).strftime('%0Y') # => "0010"
+
+- <tt>_</tt> - Pad with blanks:
+
+ Time.new(10).strftime('%_Y') # => " 10"
+
+- <tt>-</tt> - Don't pad:
+
+ Time.new(10).strftime('%-Y') # => "10"
+
+=== Casing Flags
+
+- <tt>^</tt> - Upcase result:
+
+ Time.new(2022, 1).strftime('%B') # => "January" # No casing flag.
+ Time.new(2022, 1).strftime('%^B') # => "JANUARY"
+
+- <tt>#</tt> - Swapcase result:
+
+ Time.now.strftime('%p') # => "AM"
+ Time.now.strftime('%^p') # => "AM"
+ Time.now.strftime('%#p') # => "am"
+
+=== Timezone Flags
+
+- <tt>:</tt> - Put timezone as colon-separated hours and minutes:
+
+ Time.now.strftime('%:z') # => "-05:00"
+
+- <tt>::</tt> - Put timezone as colon-separated hours, minutes, and seconds:
+
+ Time.now.strftime('%::z') # => "-05:00:00"
+
+== Width Specifiers
+
+The integer width specifier gives a minimum width for the returned string:
+
+ Time.new(2002).strftime('%Y') # => "2002" # No width specifier.
+ Time.new(2002).strftime('%10Y') # => "0000002002"
+ Time.new(2002, 12).strftime('%B') # => "December" # No width specifier.
+ Time.new(2002, 12).strftime('%10B') # => " December"
+ Time.new(2002, 12).strftime('%3B') # => "December" # Ignored if too small.
+
+= Specialized Format Strings
+
+Here are a few specialized format strings,
+each based on an external standard.
+
+== HTTP Format
+
+The HTTP date format is based on
+{RFC 2616}[https://www.rfc-editor.org/rfc/rfc2616],
+and treats dates in the format <tt>'%a, %d %b %Y %T GMT'</tt>:
+
+ d = Date.new(2001, 2, 3) # => #<Date: 2001-02-03>
+ # Return HTTP-formatted string.
+ httpdate = d.httpdate # => "Sat, 03 Feb 2001 00:00:00 GMT"
+ # Return new date parsed from HTTP-formatted string.
+ Date.httpdate(httpdate) # => #<Date: 2001-02-03>
+ # Return hash parsed from HTTP-formatted string.
+ Date._httpdate(httpdate)
+ # => {:wday=>6, :mday=>3, :mon=>2, :year=>2001, :hour=>0, :min=>0, :sec=>0, :zone=>"GMT", :offset=>0}
+
+== RFC 3339 Format
+
+The RFC 3339 date format is based on
+{RFC 3339}[https://www.rfc-editor.org/rfc/rfc3339]:
+
+ d = Date.new(2001, 2, 3) # => #<Date: 2001-02-03>
+ # Return 3339-formatted string.
+ rfc3339 = d.rfc3339 # => "2001-02-03T00:00:00+00:00"
+ # Return new date parsed from 3339-formatted string.
+ Date.rfc3339(rfc3339) # => #<Date: 2001-02-03>
+ # Return hash parsed from 3339-formatted string.
+ Date._rfc3339(rfc3339)
+ # => {:year=>2001, :mon=>2, :mday=>3, :hour=>0, :min=>0, :sec=>0, :zone=>"+00:00", :offset=>0}
+
+== RFC 2822 Format
+
+The RFC 2822 date format is based on
+{RFC 2822}[https://www.rfc-editor.org/rfc/rfc2822],
+and treats dates in the format <tt>'%a, %-d %b %Y %T %z'</tt>]:
+
+ d = Date.new(2001, 2, 3) # => #<Date: 2001-02-03>
+ # Return 2822-formatted string.
+ rfc2822 = d.rfc2822 # => "Sat, 3 Feb 2001 00:00:00 +0000"
+ # Return new date parsed from 2822-formatted string.
+ Date.rfc2822(rfc2822) # => #<Date: 2001-02-03>
+ # Return hash parsed from 2822-formatted string.
+ Date._rfc2822(rfc2822)
+ # => {:wday=>6, :mday=>3, :mon=>2, :year=>2001, :hour=>0, :min=>0, :sec=>0, :zone=>"+0000", :offset=>0}
+
+== JIS X 0301 Format
+
+The JIS X 0301 format includes the
+{Japanese era name}[https://en.wikipedia.org/wiki/Japanese_era_name],
+and treats dates in the format <tt>'%Y-%m-%d'</tt>
+with the first letter of the romanized era name prefixed:
+
+ d = Date.new(2001, 2, 3) # => #<Date: 2001-02-03>
+ # Return 0301-formatted string.
+ jisx0301 = d.jisx0301 # => "H13.02.03"
+ # Return new date parsed from 0301-formatted string.
+ Date.jisx0301(jisx0301) # => #<Date: 2001-02-03>
+ # Return hash parsed from 0301-formatted string.
+ Date._jisx0301(jisx0301) # => {:year=>2001, :mon=>2, :mday=>3}
+
+== ISO 8601 Format Specifications
+
+This section shows format specifications that are compatible with
+{ISO 8601}[https://en.wikipedia.org/wiki/ISO_8601].
+Details for various formats may be seen at the links.
+
+Examples in this section assume:
+
+ t = Time.now # => 2022-06-29 16:49:25.465246 -0500
+
+=== Dates
+
+See {ISO 8601 dates}[https://en.wikipedia.org/wiki/ISO_8601#Dates].
+
+- {Years}[https://en.wikipedia.org/wiki/ISO_8601#Years]:
+
+ - Basic year (+YYYY+):
+
+ t.strftime('%Y') # => "2022"
+
+ - Expanded year (<tt>±YYYYY</tt>):
+
+ t.strftime('+%5Y') # => "+02022"
+ t.strftime('-%5Y') # => "-02022"
+
+- {Calendar dates}[https://en.wikipedia.org/wiki/ISO_8601#Calendar_dates]:
+
+ - Basic date (+YYYYMMDD+):
+
+ t.strftime('%Y%m%d') # => "20220629"
+
+ - Extended date (<tt>YYYY-MM-DD</tt>):
+
+ t.strftime('%Y-%m-%d') # => "2022-06-29"
+
+ - Reduced extended date (<tt>YYYY-MM</tt>):
+
+ t.strftime('%Y-%m') # => "2022-06"
+
+- {Week dates}[https://en.wikipedia.org/wiki/ISO_8601#Week_dates]:
+
+ - Basic date (+YYYYWww+ or +YYYYWwwD+):
+
+ t.strftime('%Y%Ww') # => "202226w"
+ t.strftime('%Y%Ww%u') # => "202226w3"
+
+ - Extended date (<tt>YYYY-Www</tt> or <tt>YYYY-Www-D<tt>):
+
+ t.strftime('%Y-%Ww') # => "2022-26w"
+ t.strftime('%Y-%Ww-%u') # => "2022-26w-3"
+
+- {Ordinal dates}[https://en.wikipedia.org/wiki/ISO_8601#Ordinal_dates]:
+
+ - Basic date (+YYYYDDD+):
+
+ t.strftime('%Y%j') # => "2022180"
+
+ - Extended date (<tt>YYYY-DDD</tt>):
+
+ t.strftime('%Y-%j') # => "2022-180"
+
+=== Times
+
+See {ISO 8601 times}[https://en.wikipedia.org/wiki/ISO_8601#Times].
+
+- Times:
+
+ - Basic time (+Thhmmss.sss+, +Thhmmss+, +Thhmm+, or +Thh+):
+
+ t.strftime('T%H%M%S.%L') # => "T164925.465"
+ t.strftime('T%H%M%S') # => "T164925"
+ t.strftime('T%H%M') # => "T1649"
+ t.strftime('T%H') # => "T16"
+
+ - Extended time (+Thh:mm:ss.sss+, +Thh:mm:ss+, or +Thh:mm+):
+
+ t.strftime('T%H:%M:%S.%L') # => "T16:49:25.465"
+ t.strftime('T%H:%M:%S') # => "T16:49:25"
+ t.strftime('T%H:%M') # => "T16:49"
+
+- {Time zone designators}[https://en.wikipedia.org/wiki/ISO_8601#Time_zone_designators]:
+
+ - Timezone (+time+ represents a valid time,
+ +hh+ represents a valid 2-digit hour,
+ and +mm+ represents a valid 2-digit minute):
+
+ - Basic timezone (<tt>time±hhmm</tt>, <tt>time±hh</tt>, or +timeZ+):
+
+ t.strftime('T%H%M%S%z') # => "T164925-0500"
+ t.strftime('T%H%M%S%z').slice(0..-3) # => "T164925-05"
+ t.strftime('T%H%M%SZ') # => "T164925Z"
+
+ - Extended timezone (<tt>time±hh:mm</tt>):
+
+ t.strftime('T%H:%M:%S%z') # => "T16:49:25-0500"
+
+ - See also:
+
+ - {Local time (unqualified)}[https://en.wikipedia.org/wiki/ISO_8601#Local_time_(unqualified)].
+ - {Coordinated Universal Time (UTC)}[https://en.wikipedia.org/wiki/ISO_8601#Coordinated_Universal_Time_(UTC)].
+ - {Time offsets from UTC}[https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC].
+
+=== Combined \Date and \Time
+
+See {ISO 8601 Combined date and time representations}[https://en.wikipedia.org/wiki/ISO_8601#Combined_date_and_time_representations].
+
+An ISO 8601 combined date and time representation may be any
+ISO 8601 date and any ISO 8601 time,
+separated by the letter +T+.
+
+For the relevant +strftime+ formats, see {Dates}[rdoc-ref:@Dates] and {Times}[rdoc-ref:@Times] above.
diff --git a/doc/maintainers.md b/doc/maintainers.md
index dabbdc0cb6..46840343ca 100644
--- a/doc/maintainers.md
+++ b/doc/maintainers.md
@@ -1,4 +1,5 @@
# Maintainers
+
This page describes the current branch, module, library, and extension maintainers of Ruby.
## Branch Maintainers
@@ -9,6 +10,7 @@ and publishing Ruby patch releases.
[The list of current branch maintainers is available in the wiki](https://github.com/ruby/ruby/wiki/Release-Engineering).
## Module Maintainers
+
A module maintainer is responsible for a certain part of Ruby.
* The maintainer fixes bugs of the part. Particularly, they should fix
@@ -26,479 +28,691 @@ 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.
+No maintainer means that there is no specific maintainer for the part now.
+The member of ruby core team can fix issues at anytime. But major changes need
+consensus on ruby-core/ruby-dev.
+
### Language core features including security
-* Yukihiro Matsumoto (matz)
+
+* Yukihiro Matsumoto ([matz])
### Evaluator
-* Koichi Sasada (ko1)
+
+* Koichi Sasada ([ko1])
### Core classes
-* Yukihiro Matsumoto (matz)
-## Standard Library Maintainers
-### Libraries
+* Yukihiro Matsumoto ([matz])
+
+### Standard Library Maintainers
+
#### lib/mkmf.rb
-* *unmaintained*
+
+* *No maintainer*
#### lib/rubygems.rb, lib/rubygems/*
-* Eric Hodel (drbrain)
-* Hiroshi SHIBATA (hsbt)
-* https://github.com/rubygems/rubygems
+
+* Hiroshi SHIBATA ([hsbt])
+* https://github.com/ruby/rubygems
#### lib/unicode_normalize.rb, lib/unicode_normalize/*
-* Martin J. Dürst
-### Extensions
+* Martin J. Dürst ([duerst])
+
+### Standard Library(Extensions) Maintainers
+
#### ext/continuation
-* Koichi Sasada (ko1)
+
+* Koichi Sasada ([ko1])
#### ext/coverage
-* Yusuke Endoh (mame)
+
+* Yusuke Endoh ([mame])
#### ext/fiber
-* Koichi Sasada (ko1)
+
+* Koichi Sasada ([ko1])
#### ext/monitor
-* Koichi Sasada (ko1)
+
+* Koichi Sasada ([ko1])
#### ext/objspace
-* *unmaintained*
+
+* *No maintainer*
#### ext/pty
-* *unmaintained*
+
+* *No maintainer*
#### ext/ripper
-* *unmaintained*
+
+* *No maintainer*
#### ext/socket
-* Tanaka Akira (akr)
+
+* Tanaka Akira ([akr])
* API change needs matz's approval
#### ext/win32
-* NAKAMURA Usaku (usa)
-## Default gems Maintainers
-### Libraries
+* NAKAMURA Usaku ([unak])
-#### lib/benchmark.rb
-* *unmaintained*
-* https://github.com/ruby/benchmark
-* https://rubygems.org/gems/benchmark
+### Default gems(Libraries) Maintainers
#### lib/bundler.rb, lib/bundler/*
-* Hiroshi SHIBATA (hsbt)
-* https://github.com/rubygems/rubygems
+
+* Hiroshi SHIBATA ([hsbt])
+* https://github.com/ruby/rubygems
* https://rubygems.org/gems/bundler
-#### lib/cgi.rb, lib/cgi/*
-* *unmaintained*
-* https://github.com/ruby/cgi
-* https://rubygems.org/gems/cgi
+#### lib/cgi/escape.rb
+
+* *No maintainer*
#### lib/English.rb
-* *unmaintained*
+
+* *No maintainer*
* https://github.com/ruby/English
* https://rubygems.org/gems/English
#### lib/delegate.rb
-* *unmaintained*
+
+* *No maintainer*
* https://github.com/ruby/delegate
* https://rubygems.org/gems/delegate
#### lib/did_you_mean.rb
-* Yuki Nishijima (yuki24)
+
+* Yuki Nishijima ([yuki24])
* https://github.com/ruby/did_you_mean
* https://rubygems.org/gems/did_you_mean
#### ext/digest, ext/digest/*
-* Akinori MUSHA (knu)
+
+* Akinori MUSHA ([knu])
* https://github.com/ruby/digest
* https://rubygems.org/gems/digest
#### lib/erb.rb
-* Masatoshi SEKI (seki)
-* Takashi Kokubun (k0kubun)
+
+* Masatoshi SEKI ([seki])
+* Takashi Kokubun ([k0kubun])
* https://github.com/ruby/erb
* https://rubygems.org/gems/erb
#### lib/error_highlight.rb, lib/error_highlight/*
-* Yusuke Endoh (mame)
+
+* Yusuke Endoh ([mame])
* https://github.com/ruby/error_highlight
* https://rubygems.org/gems/error_highlight
#### lib/fileutils.rb
-* *unmaintained*
+
+* *No maintainer*
* https://github.com/ruby/fileutils
* https://rubygems.org/gems/fileutils
#### lib/find.rb
-* Kazuki Tsujimoto (ktsj)
+
+* Kazuki Tsujimoto ([k-tsj])
* https://github.com/ruby/find
* https://rubygems.org/gems/find
#### lib/forwardable.rb
-* Keiju ISHITSUKA (keiju)
+
+* Keiju ISHITSUKA ([keiju])
* https://github.com/ruby/forwardable
* https://rubygems.org/gems/forwardable
#### lib/ipaddr.rb
-* Akinori MUSHA (knu)
+
+* Akinori MUSHA ([knu])
* https://github.com/ruby/ipaddr
* https://rubygems.org/gems/ipaddr
-#### lib/irb.rb, lib/irb/*
-* Stan Lo (st0012)
-* Tomoya Ishida (tompng)
-* Mari Imaizumi (ima1zumi)
-* Hitoshi Hasumi (hasumikin)
-* 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
+* Nobuyuki Nakada ([nobu])
+* https://github.com/ruby/optparse
+* https://rubygems.org/gems/optparse
#### lib/net/http.rb, lib/net/https.rb
-* NARUSE, Yui (naruse)
+
+* NARUSE, Yui ([nurse])
* https://github.com/ruby/net-http
* https://rubygems.org/gems/net-http
#### lib/net/protocol.rb
-* *unmaintained*
+
+* *No maintainer*
* https://github.com/ruby/net-protocol
* https://rubygems.org/gems/net-protocol
#### lib/open3.rb
-* *unmaintained*
+
+* *No maintainer*
* https://github.com/ruby/open3
* https://rubygems.org/gems/open3
#### lib/open-uri.rb
-* Tanaka Akira (akr)
-* https://github.com/ruby/open-uri
-#### lib/ostruct.rb
-* Marc-André Lafortune (marcandre)
-* https://github.com/ruby/ostruct
-* https://rubygems.org/gems/ostruct
+* Tanaka Akira ([akr])
+* https://github.com/ruby/open-uri
+* https://rubygems.org/gems/open-uri
#### lib/pp.rb
-* Tanaka Akira (akr)
+
+* Tanaka Akira ([akr])
* https://github.com/ruby/pp
* https://rubygems.org/gems/pp
#### lib/prettyprint.rb
-* Tanaka Akira (akr)
+
+* Tanaka Akira ([akr])
* https://github.com/ruby/prettyprint
* https://rubygems.org/gems/prettyprint
#### lib/prism.rb
-* Kevin Newton (kddnewton)
-* Jemma Issroff (jemmaissroff)
+
+* Kevin Newton ([kddnewton])
+* Eileen Uchitelle ([eileencodes])
+* Aaron Patterson ([tenderlove])
* https://github.com/ruby/prism
* https://rubygems.org/gems/prism
-#### lib/pstore.rb
-* *unmaintained*
-* https://github.com/ruby/pstore
-* https://rubygems.org/gems/pstore
-
-#### lib/readline.rb
-* aycabta
-* https://github.com/ruby/readline
-* https://rubygems.org/gems/readline
-
#### lib/resolv.rb
-* Tanaka Akira (akr)
+
+* Tanaka Akira ([akr])
* https://github.com/ruby/resolv
* https://rubygems.org/gems/resolv
-#### lib/rdoc.rb, lib/rdoc/*
-* Eric Hodel (drbrain)
-* Hiroshi SHIBATA (hsbt)
-* https://github.com/ruby/rdoc
-* https://rubygems.org/gems/rdoc
-
-#### lib/reline.rb, lib/reline/*
-* Tomoya Ishida (tompng)
-* Mari Imaizumi (ima1zumi)
-* Stan Lo (st0012)
-* Hitoshi Hasumi (hasumikin)
-* https://github.com/ruby/reline
-* https://rubygems.org/gems/reline
-
#### lib/securerandom.rb
-* Tanaka Akira (akr)
+
+* Tanaka Akira ([akr])
* https://github.com/ruby/securerandom
* https://rubygems.org/gems/securerandom
-#### lib/set.rb
-* Akinori MUSHA (knu)
-* https://github.com/ruby/set
-* https://rubygems.org/gems/set
-
#### lib/shellwords.rb
-* Akinori MUSHA (knu)
+
+* Akinori MUSHA ([knu])
* https://github.com/ruby/shellwords
* https://rubygems.org/gems/shellwords
#### lib/singleton.rb
-* Yukihiro Matsumoto (matz)
+
+* Yukihiro Matsumoto ([matz])
* https://github.com/ruby/singleton
* https://rubygems.org/gems/singleton
#### lib/tempfile.rb
-* *unmaintained*
+
+* *No maintainer*
* https://github.com/ruby/tempfile
* https://rubygems.org/gems/tempfile
#### lib/time.rb
-* Tanaka Akira (akr)
+
+* Tanaka Akira ([akr])
* https://github.com/ruby/time
* https://rubygems.org/gems/time
#### lib/timeout.rb
-* Yukihiro Matsumoto (matz)
+
+* Yukihiro Matsumoto ([matz])
* https://github.com/ruby/timeout
* https://rubygems.org/gems/timeout
-#### lib/thwait.rb
-* Keiju ISHITSUKA (keiju)
-* https://github.com/ruby/thwait
-* https://rubygems.org/gems/thwait
-
#### lib/tmpdir.rb
-* *unmaintained*
+
+* *No maintainer*
* 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)
+
+* WATANABE Hirofumi ([eban])
* https://github.com/ruby/un
* https://rubygems.org/gems/un
#### lib/uri.rb, lib/uri/*
-* NARUSE, Yui (naruse)
+
+* NARUSE, Yui ([nurse])
* https://github.com/ruby/uri
* https://rubygems.org/gems/uri
#### lib/yaml.rb, lib/yaml/*
-* Aaron Patterson (tenderlove)
-* Hiroshi SHIBATA (hsbt)
+
+* Aaron Patterson ([tenderlove])
+* Hiroshi SHIBATA ([hsbt])
* https://github.com/ruby/yaml
* https://rubygems.org/gems/yaml
#### lib/weakref.rb
-* *unmaintained*
+
+* *No maintainer*
* https://github.com/ruby/weakref
* https://rubygems.org/gems/weakref
-### Extensions
+### Default gems(Extensions) Maintainers
#### ext/cgi
-* Nobuyoshi Nakada (nobu)
-* https://github.com/ruby/cgi
-* https://rubygems.org/gems/cgi
+
+* Nobuyoshi Nakada ([nobu])
#### ext/date
-* *unmaintained*
+
+* *No maintainer*
* https://github.com/ruby/date
* https://rubygems.org/gems/date
#### ext/etc
-* *unmaintained*
+
+* *No maintainer*
* https://github.com/ruby/etc
* https://rubygems.org/gems/etc
#### ext/fcntl
-* *unmaintained*
+
+* *No maintainer*
* https://github.com/ruby/fcntl
* https://rubygems.org/gems/fcntl
-#### ext/fiddle
-* Aaron Patterson (tenderlove)
-* https://github.com/ruby/fiddle
-* https://rubygems.org/gems/fiddle
-
#### ext/io/console
-* Nobuyuki Nakada (nobu)
+
+* Nobuyuki Nakada ([nobu])
* https://github.com/ruby/io-console
* https://rubygems.org/gems/io-console
#### ext/io/nonblock
-* Nobuyuki Nakada (nobu)
+
+* Nobuyuki Nakada ([nobu])
* https://github.com/ruby/io-nonblock
* https://rubygems.org/gems/io-nonblock
#### ext/io/wait
-* Nobuyuki Nakada (nobu)
+
+* Nobuyuki Nakada ([nobu])
* https://github.com/ruby/io-wait
* https://rubygems.org/gems/io-wait
#### ext/json
-* NARUSE, Yui (naruse)
-* Hiroshi SHIBATA (hsbt)
-* https://github.com/flori/json
+
+* NARUSE, Yui ([nurse])
+* Hiroshi SHIBATA ([hsbt])
+* Jean Boussier ([byroot])
+* https://github.com/ruby/json
* https://rubygems.org/gems/json
#### ext/openssl
-* Kazuki Yamaguchi (rhe)
+
+* Kazuki Yamaguchi ([rhenium])
* https://github.com/ruby/openssl
* https://rubygems.org/gems/openssl
#### ext/pathname
-* Tanaka Akira (akr)
+
+* Tanaka Akira ([akr])
* https://github.com/ruby/pathname
* https://rubygems.org/gems/pathname
#### ext/psych
-* Aaron Patterson (tenderlove)
-* Hiroshi SHIBATA (hsbt)
+
+* Aaron Patterson ([tenderlove])
+* Hiroshi SHIBATA ([hsbt])
* https://github.com/ruby/psych
* https://rubygems.org/gems/psych
#### ext/stringio
-* Nobuyuki Nakada (nobu)
+
+* Nobuyuki Nakada ([nobu])
* https://github.com/ruby/stringio
* https://rubygems.org/gems/stringio
#### ext/strscan
-* Kouhei Sutou (kou)
+
+* Kouhei Sutou ([kou])
* https://github.com/ruby/strscan
* https://rubygems.org/gems/strscan
-#### ext/win32ole
-* Masaki Suketa (suke)
-* https://github.com/ruby/win32ole
-* https://rubygems.org/gems/win32ole
-
#### ext/zlib
-* NARUSE, Yui (naruse)
+
+* NARUSE, Yui ([nurse])
* https://github.com/ruby/zlib
* https://rubygems.org/gems/zlib
-## Bundled gems upstream repositories
+## Bundled gems upstream repositories and maintainers
+
+The maintanance policy of bundled gems is different from Module Maintainers above.
+Please check the policies for each repository.
+
+The ruby core team tries to maintain the repositories with no maintainers.
+It may needs to make consensus on ruby-core/ruby-dev before making major changes.
+
### minitest
+
+* Ryan Davis ([zenspider])
* https://github.com/minitest/minitest
+* https://rubygems.org/gems/minitest
### power_assert
+
+* Tsujimoto Kenta ([k-tsj])
* https://github.com/ruby/power_assert
+* https://rubygems.org/gems/power_assert
### rake
+
+* Hiroshi SHIBATA ([hsbt])
* https://github.com/ruby/rake
+* https://rubygems.org/gems/rake
### test-unit
+
+* Kouhei Sutou ([kou])
* https://github.com/test-unit/test-unit
+* https://rubygems.org/gems/test-unit
### rexml
+
+* Kouhei Sutou ([kou])
* https://github.com/ruby/rexml
+* https://rubygems.org/gems/rexml
### rss
+
+* Kouhei Sutou ([kou])
* https://github.com/ruby/rss
+* https://rubygems.org/gems/rss
### net-ftp
+
+* Shugo Maeda ([shugo])
* https://github.com/ruby/net-ftp
+* https://rubygems.org/gems/net-ftp
### net-imap
+
+* Nicholas A. Evans ([nevans])
* https://github.com/ruby/net-imap
+* https://rubygems.org/gems/net-imap
### net-pop
+
* https://github.com/ruby/net-pop
+* https://rubygems.org/gems/net-pop
### net-smtp
+
+* TOMITA Masahiro ([tmtm])
* https://github.com/ruby/net-smtp
+* https://rubygems.org/gems/net-smtp
### matrix
+
+* Marc-André Lafortune ([marcandre])
* https://github.com/ruby/matrix
+* https://rubygems.org/gems/matrix
### prime
+
* https://github.com/ruby/prime
+* https://rubygems.org/gems/prime
### rbs
+
+* Soutaro Matsumoto ([soutaro])
* https://github.com/ruby/rbs
+* https://rubygems.org/gems/rbs
### typeprof
+
+* Yusuke Endoh ([mame])
* https://github.com/ruby/typeprof
+* https://rubygems.org/gems/typeprof
### debug
+
+* Koichi Sasada ([ko1])
* https://github.com/ruby/debug
+* https://rubygems.org/gems/debug
### racc
+
+* Yuichi Kaneko ([yui-knk])
* https://github.com/ruby/racc
+* https://rubygems.org/gems/racc
#### mutex_m
+
* https://github.com/ruby/mutex_m
+* https://rubygems.org/gems/mutex_m
#### getoptlong
+
* https://github.com/ruby/getoptlong
+* https://rubygems.org/gems/getoptlong
#### base64
+
+* Yusuke Endoh ([mame])
* https://github.com/ruby/base64
+* https://rubygems.org/gems/base64
#### bigdecimal
+
+* Kenta Murata ([mrkn])
* https://github.com/ruby/bigdecimal
+* https://rubygems.org/gems/bigdecimal
#### observer
+
* https://github.com/ruby/observer
+* https://rubygems.org/gems/observer
#### abbrev
+
+* Akinori MUSHA ([knu])
* https://github.com/ruby/abbrev
+* https://rubygems.org/gems/abbrev
#### resolv-replace
+
+* Akira TANAKA ([akr])
* https://github.com/ruby/resolv-replace
+* https://rubygems.org/gems/resolv-replace
#### rinda
+
+* Masatoshi SEKI ([seki])
* https://github.com/ruby/rinda
+* https://rubygems.org/gems/rinda
#### drb
+
+* Masatoshi SEKI ([seki])
* https://github.com/ruby/drb
+* https://rubygems.org/gems/drb
#### nkf
+
+* Naruse Yusuke ([nurse])
* https://github.com/ruby/nkf
+* https://rubygems.org/gems/nkf
#### syslog
+
+* Akinori Musha ([knu])
* https://github.com/ruby/syslog
+* https://rubygems.org/gems/syslog
#### csv
+
+* Kouhei Sutou ([kou])
* https://github.com/ruby/csv
+* https://rubygems.org/gems/csv
+
+#### ostruct
+
+* Marc-André Lafortune ([marcandre])
+* https://github.com/ruby/ostruct
+* https://rubygems.org/gems/ostruct
+
+#### pstore
+
+* https://github.com/ruby/pstore
+* https://rubygems.org/gems/pstore
+
+#### benchmark
+
+* https://github.com/ruby/benchmark
+* https://rubygems.org/gems/benchmark
+
+#### logger
+
+* Naotoshi Seo ([sonots])
+* https://github.com/ruby/logger
+* https://rubygems.org/gems/logger
+
+#### rdoc
+
+* Stan Lo ([st0012])
+* Nobuyoshi Nakada ([nobu])
+* https://github.com/ruby/rdoc
+* https://rubygems.org/gems/rdoc
+
+#### win32ole
+
+* Masaki Suketa ([suketa])
+* https://github.com/ruby/win32ole
+* https://rubygems.org/gems/win32ole
+
+#### irb
+
+* Tomoya Ishida ([tompng])
+* Stan Lo ([st0012])
+* Mari Imaizumi ([ima1zumi])
+* HASUMI Hitoshi ([hasumikin])
+* https://github.com/ruby/irb
+* https://rubygems.org/gems/irb
+
+#### reline
+
+* Tomoya Ishida ([tompng])
+* Stan Lo ([st0012])
+* Mari Imaizumi ([ima1zumi])
+* HASUMI Hitoshi ([hasumikin])
+* https://github.com/ruby/reline
+* https://rubygems.org/gems/reline
+
+#### readline
+
+* https://github.com/ruby/readline
+* https://rubygems.org/gems/readline
+
+#### fiddle
+
+* Kouhei Sutou ([kou])
+* https://github.com/ruby/fiddle
+* https://rubygems.org/gems/fiddle
+
+#### repl_type_completor
+
+* Tomoya Ishida ([tompng])
+* https://github.com/ruby/repl_type_completor
+* https://rubygems.org/gems/repl_type_completor
+
+#### tsort
+
+* Tanaka Akira ([akr])
+* https://github.com/ruby/tsort
+* https://rubygems.org/gems/tsort
## Platform Maintainers
+
### mswin64 (Microsoft Windows)
-* NAKAMURA Usaku (usa)
+
+* NAKAMURA Usaku ([unak])
### mingw32 (Minimalist GNU for Windows)
-* Nobuyoshi Nakada (nobu)
+
+* Nobuyoshi Nakada ([nobu])
### AIX
-* Yutaka Kanemoto (kanemoto)
+
+* Yutaka Kanemoto ([kanemoto])
### FreeBSD
-* Akinori MUSHA (knu)
+
+* Akinori MUSHA ([knu])
### Solaris
-* Naohisa Goto (ngoto)
+
+* Naohisa Goto ([ngoto])
### RHEL, CentOS
-* KOSAKI Motohiro (kosaki)
+
+* KOSAKI Motohiro ([kosaki])
### macOS
-* Kenta Murata (mrkn)
+
+* Kenta Murata ([mrkn])
### OpenBSD
-* Jeremy Evans (jeremyevans0)
+
+* Jeremy Evans ([jeremyevans])
### cygwin, ...
-* none. (Maintainer WANTED)
+
+* **No maintainer**
### WebAssembly/WASI
-* Yuta Saito (katei)
+
+* Yuta Saito ([kateinoigakukun])
+
+[akr]: https://github.com/akr
+[byroot]: https://github.com/byroot
+[colby-swandale]: https://github.com/colby-swandale
+[drbrain]: https://github.com/drbrain
+[duerst]: https://github.com/duerst
+[eban]: https://github.com/eban
+[eileencodes]: https://github.com/eileencodes
+[hasumikin]: https://github.com/hasumikin
+[hsbt]: https://github.com/hsbt
+[ima1zumi]: https://github.com/ima1zumi
+[jeremyevans]: https://github.com/jeremyevans
+[k-tsj]: https://github.com/k-tsj
+[k0kubun]: https://github.com/k0kubun
+[kanemoto]: https://github.com/kanemoto
+[kateinoigakukun]: https://github.com/kateinoigakukun
+[kddnewton]: https://github.com/kddnewton
+[keiju]: https://github.com/keiju
+[knu]: https://github.com/knu
+[ko1]: https://github.com/ko1
+[kosaki]: https://github.com/kosaki
+[kou]: https://github.com/kou
+[mame]: https://github.com/mame
+[marcandre]: https://github.com/marcandre
+[matz]: https://github.com/matz
+[mrkn]: https://github.com/mrkn
+[ngoto]: https://github.com/ngoto
+[nobu]: https://github.com/nobu
+[nurse]: https://github.com/nurse
+[rhenium]: https://github.com/rhenium
+[seki]: https://github.com/seki
+[suketa]: https://github.com/suketa
+[sonots]: https://github.com/sonots
+[st0012]: https://github.com/st0012
+[tenderlove]: https://github.com/tenderlove
+[tompng]: https://github.com/tompng
+[unak]: https://github.com/unak
+[yuki24]: https://github.com/yuki24
+[zenspider]: https://github.com/zenspider
+[k-tsj]: https://github.com/k-tsj
+[nevans]: https://github.com/nevans
+[tmtm]: https://github.com/tmtm
+[shugo]: https://github.com/shugo
+[soutaro]: https://github.com/soutaro
+[yui-knk]: https://github.com/yui-knk
+[hasumikin]: https://github.com/hasumikin
+[suketa]: https://github.com/suketa
diff --git a/doc/marshal.rdoc b/doc/marshal.rdoc
deleted file mode 100644
index abf9467262..0000000000
--- a/doc/marshal.rdoc
+++ /dev/null
@@ -1,313 +0,0 @@
-= Marshal Format
-
-The Marshal format is used to serialize ruby objects. The format can store
-arbitrary objects through three user-defined extension mechanisms.
-
-For documentation on using Marshal to serialize and deserialize objects, see
-the Marshal module.
-
-This document calls a serialized set of objects a stream. The Ruby
-implementation can load a set of objects from a String, an IO or an object
-that implements a +getc+ method.
-
-== Stream Format
-
-The first two bytes of the stream contain the major and minor version, each as
-a single byte encoding a digit. The version implemented in Ruby is 4.8
-(stored as "\x04\x08") and is supported by ruby 1.8.0 and newer.
-
-Different major versions of the Marshal format are not compatible and cannot
-be understood by other major versions. Lesser minor versions of the format
-can be understood by newer minor versions. Format 4.7 can be loaded by a 4.8
-implementation but format 4.8 cannot be loaded by a 4.7 implementation.
-
-Following the version bytes is a stream describing the serialized object. The
-stream contains nested objects (the same as a Ruby object) but objects in the
-stream do not necessarily have a direct mapping to the Ruby object model.
-
-Each object in the stream is described by a byte indicating its type followed
-by one or more bytes describing the object. When "object" is mentioned below
-it means any of the types below that defines a Ruby object.
-
-=== true, false, nil
-
-These objects are each one byte long. "T" is represents +true+, "F"
-represents +false+ and "0" represents +nil+.
-
-=== Fixnum and long
-
-"i" represents a signed 32 bit value using a packed format. One through five
-bytes follows the type. The value loaded will always be a Fixnum. On
-32 bit platforms (where the precision of a Fixnum is less than 32 bits)
-loading large values will cause overflow on CRuby.
-
-The fixnum type is used to represent both ruby Fixnum objects and the sizes of
-marshaled arrays, hashes, instance variables and other types. In the
-following sections "long" will mean the format described below, which supports
-full 32 bit precision.
-
-The first byte has the following special values:
-
-"\x00"::
- The value of the integer is 0. No bytes follow.
-
-"\x01"::
- The total size of the integer is two bytes. The following byte is a
- positive integer in the range of 0 through 255. Only values between 123
- and 255 should be represented this way to save bytes.
-
-"\xff"::
- The total size of the integer is two bytes. The following byte is a
- negative integer in the range of -1 through -256.
-
-"\x02"::
- The total size of the integer is three bytes. The following two bytes are a
- positive little-endian integer.
-
-"\xfe"::
- The total size of the integer is three bytes. The following two bytes are a
- negative little-endian integer.
-
-"\x03"::
- The total size of the integer is four bytes. The following three bytes are
- a positive little-endian integer.
-
-"\xfd"::
- The total size of the integer is four bytes. The following three bytes are a
- negative little-endian integer.
-
-"\x04"::
- The total size of the integer is five bytes. The following four bytes are a
- positive little-endian integer. For compatibility with 32 bit ruby,
- only Fixnums less than 1073741824 should be represented this way. For sizes
- of stream objects full precision may be used.
-
-"\xfc"::
- 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.
-
-Otherwise the first byte is a sign-extended eight-bit value with an offset.
-If the value is positive the value is determined by subtracting 5 from the
-value. If the value is negative the value is determined by adding 5 to the
-value.
-
-There are multiple representations for many values. CRuby always outputs the
-shortest representation possible.
-
-=== Symbols and Byte Sequence
-
-":" represents a real symbol. A real symbol contains the data needed to
-define the symbol for the rest of the stream as future occurrences in the
-stream will instead be references (a symbol link) to this one. The reference
-is a zero-indexed 32 bit value (so the first occurrence of <code>:hello</code>
-is 0).
-
-Following the type byte is byte sequence which consists of a long indicating
-the number of bytes in the sequence followed by that many bytes of data. Byte
-sequences have no encoding.
-
-For example, the following stream contains the Symbol <code>:hello</code>:
-
- "\x04\x08:\x0ahello"
-
-";" represents a Symbol link which references a previously defined Symbol.
-Following the type byte is a long containing the index in the lookup table for
-the linked (referenced) Symbol.
-
-For example, the following stream contains <code>[:hello, :hello]</code>:
-
- "\x04\b[\a:\nhello;\x00"
-
-When a "symbol" is referenced below it may be either a real symbol or a
-symbol link.
-
-=== Object References
-
-Separate from but similar to symbol references, the stream contains only one
-copy of each object (as determined by #object_id) for all objects except
-true, false, nil, Fixnums and Symbols (which are stored separately as
-described above) a one-indexed 32 bit value will be stored and reused when the
-object is encountered again. (The first object has an index of 1).
-
-"@" represents an object link. Following the type byte is a long giving the
-index of the object.
-
-For example, the following stream contains an Array of the same
-<code>"hello"</code> object twice:
-
- "\004\b[\a\"\nhello@\006"
-
-=== Instance Variables
-
-"I" indicates that instance variables follow the next object. An object
-follows the type byte. Following the object is a length indicating the number
-of instance variables for the object. Following the length is a set of
-name-value pairs. The names are symbols while the values are objects. The
-symbols must be instance variable names (<code>:@name</code>).
-
-An Object ("o" type, described below) uses the same format for its instance
-variables as described here.
-
-For a String and Regexp (described below) a special instance variable
-<code>:E</code> is used to indicate the Encoding.
-
-=== Extended
-
-"e" indicates that the next object is extended by a module. An object follows
-the type byte. Following the object is a symbol that contains the name of the
-module the object is extended by.
-
-=== Array
-
-"[" represents an Array. Following the type byte is a long indicating the
-number of objects in the array. The given number of objects follow the
-length.
-
-=== Bignum
-
-"l" represents a Bignum which is composed of three parts:
-
-sign::
- A single byte containing "+" for a positive value or "-" for a negative
- value.
-length::
- A long indicating the number of bytes of Bignum data follows, divided by
- two. Multiply the length by two to determine the number of bytes of data
- that follow.
-data::
- Bytes of Bignum data representing the number.
-
-The following ruby code will reconstruct the Bignum value from an array of
-bytes:
-
- result = 0
-
- bytes.each_with_index do |byte, exp|
- result += (byte * 2 ** (exp * 8))
- end
-
-=== Class and Module
-
-"c" represents a Class object, "m" represents a Module and "M" represents
-either a class or module (this is an old-style for compatibility). No class
-or module content is included, this type is only a reference. Following the
-type byte is a byte sequence which is used to look up an existing class or
-module, respectively.
-
-Instance variables are not allowed on a class or module.
-
-If no class or module exists an exception should be raised.
-
-For "c" and "m" types, the loaded object must be a class or module,
-respectively.
-
-=== Data
-
-"d" represents a Data object. (Data objects are wrapped pointers from ruby
-extensions.) Following the type byte is a symbol indicating the class for the
-Data object and an object that contains the state of the Data object.
-
-To dump a Data object Ruby calls _dump_data. To load a Data object Ruby calls
-_load_data with the state of the object on a newly allocated instance.
-
-=== Float
-
-"f" represents a Float object. Following the type byte is a byte sequence
-containing the float value. The following values are special:
-
-"inf"::
- Positive infinity
-
-"-inf"::
- Negative infinity
-
-"nan"::
- Not a Number
-
-Otherwise the byte sequence contains a C double (loadable by strtod(3)).
-Older minor versions of Marshal also stored extra mantissa bits to ensure
-portability across platforms but 4.8 does not include these. See
-[ruby-talk:69518] for some explanation.
-
-=== Hash and Hash with Default Value
-
-"{" represents a Hash object while "}" represents a Hash with a default value
-set (<code>Hash.new 0</code>). Following the type byte is a long indicating
-the number of key-value pairs in the Hash, the size. Double the given number
-of objects follow the size.
-
-For a Hash with a default value, the default value follows all the pairs.
-
-=== Module and Old Module
-
-=== Object
-
-"o" represents an object that doesn't have any other special form (such as
-a user-defined or built-in format). Following the type byte is a symbol
-containing the class name of the object. Following the class name is a long
-indicating the number of instance variable names and values for the object.
-Double the given number of pairs of objects follow the size.
-
-The keys in the pairs must be symbols containing instance variable names.
-
-=== Regular Expression
-
-"/" represents a regular expression. Following the type byte is a byte
-sequence containing the regular expression source. Following the type byte is
-a byte containing the regular expression options (case-insensitive, etc.) as a
-signed 8-bit value.
-
-Regular expressions can have an encoding attached through instance variables
-(see above). If no encoding is attached escapes for the following regexp
-specials not present in ruby 1.8 must be removed: g-m, o-q, u, y, E, F, H-L,
-N-V, X, Y.
-
-=== String
-
-'"' represents a String. Following the type byte is a byte sequence
-containing the string content. When dumped from ruby 1.9 an encoding instance
-variable (<code>:E</code> see above) should be included unless the encoding is
-binary.
-
-=== Struct
-
-"S" represents a Struct. Following the type byte is a symbol containing the
-name of the struct. Following the name is a long indicating the number of
-members in the struct. Double the number of objects follow the member count.
-Each member is a pair containing the member's symbol and an object for the
-value of that member.
-
-If the struct name does not match a Struct subclass in the running ruby an
-exception should be raised.
-
-If there is a mismatch between the struct in the currently running ruby and
-the member count in the marshaled struct an exception should be raised.
-
-=== User Class
-
-"C" represents a subclass of a String, Regexp, Array or Hash. Following the
-type byte is a symbol containing the name of the subclass. Following the name
-is the wrapped object.
-
-=== User Defined
-
-"u" represents an object with a user-defined serialization format using the
-+_dump+ instance method and +_load+ class method. Following the type byte is
-a symbol containing the class name. Following the class name is a byte
-sequence containing the user-defined representation of the object.
-
-The class method +_load+ is called on the class with a string created from the
-byte-sequence.
-
-=== User Marshal
-
-"U" represents an object with a user-defined serialization format using the
-+marshal_dump+ and +marshal_load+ instance methods. Following the type byte
-is a symbol containing the class name. Following the class name is an object
-containing the data.
-
-Upon loading a new instance must be allocated and +marshal_load+ must be
-called on the instance with the data.
-
diff --git a/doc/matchdata/begin.rdoc b/doc/matchdata/begin.rdoc
index 8046dd9d55..6100617e19 100644
--- a/doc/matchdata/begin.rdoc
+++ b/doc/matchdata/begin.rdoc
@@ -10,12 +10,12 @@ returns the offset of the beginning of the <tt>n</tt>th match:
m[3] # => "113"
m.begin(3) # => 3
- m = /(т)(е)(с)/.match('тест')
- # => #<MatchData "тес" 1:"т" 2:"е" 3:"с">
- m[0] # => "тес"
- m.begin(0) # => 0
- m[3] # => "с"
- m.begin(3) # => 2
+ m = /(ん)(に)(ち)/.match('こんにちは')
+ # => #<MatchData "んにち" 1:"ん" 2:"に" 3:"ち">
+ m[0] # => "んにち"
+ m.begin(0) # => 1
+ m[3] # => "ち"
+ m.begin(3) # => 3
When string or symbol argument +name+ is given,
returns the offset of the beginning for the named match:
diff --git a/doc/matchdata/bytebegin.rdoc b/doc/matchdata/bytebegin.rdoc
new file mode 100644
index 0000000000..54e417a7fc
--- /dev/null
+++ b/doc/matchdata/bytebegin.rdoc
@@ -0,0 +1,30 @@
+Returns the offset (in bytes) of the beginning of the specified match.
+
+When non-negative integer argument +n+ is given,
+returns the offset of the beginning of the <tt>n</tt>th match:
+
+ m = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8">
+ m[0] # => "HX1138"
+ m.bytebegin(0) # => 1
+ m[3] # => "113"
+ m.bytebegin(3) # => 3
+
+ m = /(ん)(に)(ち)/.match('こんにちは')
+ # => #<MatchData "んにち" 1:"ん" 2:"に" 3:"ち">
+ m[0] # => "んにち"
+ m.bytebegin(0) # => 3
+ m[3] # => "ち"
+ m.bytebegin(3) # => 9
+
+When string or symbol argument +name+ is given,
+returns the offset of the beginning for the named match:
+
+ m = /(?<foo>.)(.)(?<bar>.)/.match("hoge")
+ # => #<MatchData "hog" foo:"h" bar:"g">
+ m[:foo] # => "h"
+ m.bytebegin('foo') # => 0
+ m[:bar] # => "g"
+ m.bytebegin(:bar) # => 2
+
+Related: MatchData#byteend, MatchData#byteoffset.
diff --git a/doc/matchdata/byteend.rdoc b/doc/matchdata/byteend.rdoc
new file mode 100644
index 0000000000..0a03f76208
--- /dev/null
+++ b/doc/matchdata/byteend.rdoc
@@ -0,0 +1,30 @@
+Returns the offset (in bytes) of the end of the specified match.
+
+When non-negative integer argument +n+ is given,
+returns the offset of the end of the <tt>n</tt>th match:
+
+ m = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ # => #<MatchData "HX1138" 1:"H" 2:"X" 3:"113" 4:"8">
+ m[0] # => "HX1138"
+ m.byteend(0) # => 7
+ m[3] # => "113"
+ m.byteend(3) # => 6
+
+ m = /(ん)(に)(ち)/.match('こんにちは')
+ # => #<MatchData "んにち" 1:"ん" 2:"に" 3:"ち">
+ m[0] # => "んにち"
+ m.byteend(0) # => 12
+ m[3] # => "ち"
+ m.byteend(3) # => 12
+
+When string or symbol argument +name+ is given,
+returns the offset of the end for the named match:
+
+ m = /(?<foo>.)(.)(?<bar>.)/.match("hoge")
+ # => #<MatchData "hog" foo:"h" bar:"g">
+ m[:foo] # => "h"
+ m.byteend('foo') # => 1
+ m[:bar] # => "g"
+ m.byteend(:bar) # => 3
+
+Related: MatchData#bytebegin, MatchData#byteoffset.
diff --git a/doc/matchdata/end.rdoc b/doc/matchdata/end.rdoc
index 0209b2d2fc..c43a5428f3 100644
--- a/doc/matchdata/end.rdoc
+++ b/doc/matchdata/end.rdoc
@@ -10,12 +10,12 @@ returns the offset of the end of the <tt>n</tt>th match:
m[3] # => "113"
m.end(3) # => 6
- m = /(т)(е)(с)/.match('тест')
- # => #<MatchData "тес" 1:"т" 2:"е" 3:"с">
- m[0] # => "тес"
- m.end(0) # => 3
- m[3] # => "с"
- m.end(3) # => 3
+ m = /(ん)(に)(ち)/.match('こんにちは')
+ # => #<MatchData "んにち" 1:"ん" 2:"に" 3:"ち">
+ m[0] # => "んにち"
+ m.end(0) # => 4
+ m[3] # => "ち"
+ m.end(3) # => 4
When string or symbol argument +name+ is given,
returns the offset of the end for the named match:
diff --git a/doc/matchdata/offset.rdoc b/doc/matchdata/offset.rdoc
index 0985316d76..4194ef7ef9 100644
--- a/doc/matchdata/offset.rdoc
+++ b/doc/matchdata/offset.rdoc
@@ -11,12 +11,12 @@ returns the starting and ending offsets of the <tt>n</tt>th match:
m[3] # => "113"
m.offset(3) # => [3, 6]
- m = /(т)(е)(с)/.match('тест')
- # => #<MatchData "тес" 1:"т" 2:"е" 3:"с">
- m[0] # => "тес"
- m.offset(0) # => [0, 3]
- m[3] # => "с"
- m.offset(3) # => [2, 3]
+ m = /(ん)(に)(ち)/.match('こんにちは')
+ # => #<MatchData "んにち" 1:"ん" 2:"に" 3:"ち">
+ m[0] # => "んにち"
+ m.offset(0) # => [1, 4]
+ m[3] # => "ち"
+ m.offset(3) # => [3, 4]
When string or symbol argument +name+ is given,
returns the starting and ending offsets for the named match:
diff --git a/doc/math/math.rdoc b/doc/math/math.rdoc
index 7a89df951c..2978375564 100644
--- a/doc/math/math.rdoc
+++ b/doc/math/math.rdoc
@@ -1,4 +1,4 @@
-\Module \Math provides methods for basic trigonometric,
+Module \Math provides methods for basic trigonometric,
logarithmic, and transcendental functions, and for extracting roots.
You can write its constants and method calls thus:
diff --git a/doc/optparse/argument_converters.rdoc b/doc/optparse/argument_converters.rdoc
index 4b4b30e8de..532729871c 100644
--- a/doc/optparse/argument_converters.rdoc
+++ b/doc/optparse/argument_converters.rdoc
@@ -377,4 +377,4 @@ Executions:
$ ruby match_converter.rb --capitalize foo
["Foo", String]
$ ruby match_converter.rb --capitalize "foo bar"
- match_converter.rb:9:in `<main>': invalid argument: --capitalize foo bar (OptionParser::InvalidArgument)
+ match_converter.rb:9:in '<main>': invalid argument: --capitalize foo bar (OptionParser::InvalidArgument)
diff --git a/doc/optparse/option_params.rdoc b/doc/optparse/option_params.rdoc
index 35db8b5a55..575ee66cdb 100644
--- a/doc/optparse/option_params.rdoc
+++ b/doc/optparse/option_params.rdoc
@@ -91,7 +91,7 @@ Executions:
Usage: short_required [options]
-xXXX Short name with required argument
$ ruby short_required.rb -x
- short_required.rb:6:in `<main>': missing argument: -x (OptionParser::MissingArgument)
+ short_required.rb:6:in '<main>': missing argument: -x (OptionParser::MissingArgument)
$ ruby short_required.rb -x FOO
["-x", "FOO"]
@@ -181,7 +181,7 @@ Executions:
Usage: long_required [options]
--xxx XXX Long name with required argument
$ ruby long_required.rb --xxx
- long_required.rb:6:in `<main>': missing argument: --xxx (OptionParser::MissingArgument)
+ long_required.rb:6:in '<main>': missing argument: --xxx (OptionParser::MissingArgument)
$ ruby long_required.rb --xxx FOO
["--xxx", "FOO"]
@@ -243,11 +243,11 @@ Usage: mixed_names [options]
$ ruby mixed_names.rb --xxx
["--xxx", true]
$ ruby mixed_names.rb -y
- mixed_names.rb:12:in `<main>': missing argument: -y (OptionParser::MissingArgument)
+ mixed_names.rb:12:in '<main>': missing argument: -y (OptionParser::MissingArgument)
$ ruby mixed_names.rb -y FOO
["--yyy", "FOO"]
$ ruby mixed_names.rb --yyy
- mixed_names.rb:12:in `<main>': missing argument: --yyy (OptionParser::MissingArgument)
+ mixed_names.rb:12:in '<main>': missing argument: --yyy (OptionParser::MissingArgument)
$ ruby mixed_names.rb --yyy BAR
["--yyy", "BAR"]
$ ruby mixed_names.rb -z
@@ -279,7 +279,7 @@ Executions:
Usage: argument_keywords [options]
-x, --xxx Required argument
$ ruby argument_styles.rb --xxx
- argument_styles.rb:6:in `<main>': missing argument: --xxx (OptionParser::MissingArgument)
+ argument_styles.rb:6:in '<main>': missing argument: --xxx (OptionParser::MissingArgument)
$ ruby argument_styles.rb --xxx FOO
["--xxx", "FOO"]
@@ -298,7 +298,7 @@ Executions:
Usage: argument_strings [options]
-x, --xxx=XXX Required argument
$ ruby argument_strings.rb --xxx
- argument_strings.rb:9:in `<main>': missing argument: --xxx (OptionParser::MissingArgument)
+ argument_strings.rb:9:in '<main>': missing argument: --xxx (OptionParser::MissingArgument)
$ ruby argument_strings.rb --xxx FOO
["--xxx", "FOO"]
@@ -331,7 +331,7 @@ Executions:
-xXXX Values for required argument
-y [YYY] Values for optional argument
$ ruby explicit_array_values.rb -x
- explicit_array_values.rb:9:in `<main>': missing argument: -x (OptionParser::MissingArgument)
+ explicit_array_values.rb:9:in '<main>': missing argument: -x (OptionParser::MissingArgument)
$ ruby explicit_array_values.rb -x foo
["-x", "foo"]
$ ruby explicit_array_values.rb -x f
@@ -339,9 +339,9 @@ Executions:
$ ruby explicit_array_values.rb -x bar
["-x", "bar"]
$ ruby explicit_array_values.rb -y ba
- explicit_array_values.rb:9:in `<main>': ambiguous argument: -y ba (OptionParser::AmbiguousArgument)
+ explicit_array_values.rb:9:in '<main>': ambiguous argument: -y ba (OptionParser::AmbiguousArgument)
$ ruby explicit_array_values.rb -x baz
- explicit_array_values.rb:9:in `<main>': invalid argument: -x baz (OptionParser::InvalidArgument)
+ explicit_array_values.rb:9:in '<main>': invalid argument: -x baz (OptionParser::InvalidArgument)
===== Explicit Values in Hash
@@ -361,7 +361,7 @@ Executions:
-xXXX Values for required argument
-y [YYY] Values for optional argument
$ ruby explicit_hash_values.rb -x
- explicit_hash_values.rb:9:in `<main>': missing argument: -x (OptionParser::MissingArgument)
+ explicit_hash_values.rb:9:in '<main>': missing argument: -x (OptionParser::MissingArgument)
$ ruby explicit_hash_values.rb -x foo
["-x", 0]
$ ruby explicit_hash_values.rb -x f
@@ -369,7 +369,7 @@ Executions:
$ ruby explicit_hash_values.rb -x bar
["-x", 1]
$ ruby explicit_hash_values.rb -x baz
- explicit_hash_values.rb:9:in `<main>': invalid argument: -x baz (OptionParser::InvalidArgument)
+ explicit_hash_values.rb:9:in '<main>': invalid argument: -x baz (OptionParser::InvalidArgument)
$ ruby explicit_hash_values.rb -y
["-y", nil]
$ ruby explicit_hash_values.rb -y baz
@@ -377,14 +377,15 @@ Executions:
$ ruby explicit_hash_values.rb -y bat
["-y", 3]
$ ruby explicit_hash_values.rb -y ba
- explicit_hash_values.rb:9:in `<main>': ambiguous argument: -y ba (OptionParser::AmbiguousArgument)
+ explicit_hash_values.rb:9:in '<main>': ambiguous argument: -y ba (OptionParser::AmbiguousArgument)
$ ruby explicit_hash_values.rb -y bam
["-y", nil]
==== Argument Value Patterns
You can restrict permissible argument values
-by specifying a Regexp that the given argument must match.
+by specifying a +Regexp+ that the given argument must match,
+or a +Range+ or +Array+ that the converted value must be included in.
File +matched_values.rb+ defines options with matched argument values.
@@ -395,12 +396,22 @@ Executions:
$ ruby matched_values.rb --help
Usage: matched_values [options]
--xxx XXX Matched values
+ --yyy YYY Check by range
+ --zzz ZZZ Check by list
$ ruby matched_values.rb --xxx foo
["--xxx", "foo"]
$ ruby matched_values.rb --xxx FOO
["--xxx", "FOO"]
$ ruby matched_values.rb --xxx bar
- matched_values.rb:6:in `<main>': invalid argument: --xxx bar (OptionParser::InvalidArgument)
+ matched_values.rb:12:in '<main>': invalid argument: --xxx bar (OptionParser::InvalidArgument)
+ $ ruby matched_values.rb --yyy 1
+ ["--yyy", 1]
+ $ ruby matched_values.rb --yyy 4
+ matched_values.rb:12:in '<main>': invalid argument: --yyy 4 (OptionParser::InvalidArgument)
+ $ ruby matched_values.rb --zzz 1
+ ["--zzz", 1]
+ $ ruby matched_values.rb --zzz 2
+ matched_values.rb:12:in '<main>': invalid argument: --zzz 2 (OptionParser::InvalidArgument)
=== Argument Converters
diff --git a/doc/optparse/ruby/matched_values.rb b/doc/optparse/ruby/matched_values.rb
index f184ca8474..a1aba140e6 100644
--- a/doc/optparse/ruby/matched_values.rb
+++ b/doc/optparse/ruby/matched_values.rb
@@ -3,4 +3,10 @@ parser = OptionParser.new
parser.on('--xxx XXX', /foo/i, 'Matched values') do |value|
p ['--xxx', value]
end
+parser.on('--yyy YYY', Integer, 'Check by range', 1..3) do |value|
+ p ['--yyy', value]
+end
+parser.on('--zzz ZZZ', Integer, 'Check by list', [1, 3, 4]) do |value|
+ p ['--zzz', value]
+end
parser.parse!
diff --git a/doc/optparse/tutorial.rdoc b/doc/optparse/tutorial.rdoc
index 6f56bbf92d..1134f94ddf 100644
--- a/doc/optparse/tutorial.rdoc
+++ b/doc/optparse/tutorial.rdoc
@@ -111,7 +111,7 @@ Executions:
["x", true]
["input_file.txt", "output_file.txt"]
$ ruby basic.rb -a
- basic.rb:16:in `<main>': invalid option: -a (OptionParser::InvalidOption)
+ basic.rb:16:in '<main>': invalid option: -a (OptionParser::InvalidOption)
=== Defining Options
@@ -232,11 +232,11 @@ Executions:
$ ruby mixed_names.rb --xxx
["--xxx", true]
$ ruby mixed_names.rb -y
- mixed_names.rb:12:in `<main>': missing argument: -y (OptionParser::MissingArgument)
+ mixed_names.rb:12:in '<main>': missing argument: -y (OptionParser::MissingArgument)
$ ruby mixed_names.rb -y FOO
["--yyy", "FOO"]
$ ruby mixed_names.rb --yyy
- mixed_names.rb:12:in `<main>': missing argument: --yyy (OptionParser::MissingArgument)
+ mixed_names.rb:12:in '<main>': missing argument: --yyy (OptionParser::MissingArgument)
$ ruby mixed_names.rb --yyy BAR
["--yyy", "BAR"]
$ ruby mixed_names.rb -z
@@ -270,9 +270,9 @@ Executions:
$ ruby name_abbrev.rb --draft
["--draft", true]
$ ruby name_abbrev.rb --d
- name_abbrev.rb:9:in `<main>': ambiguous option: --d (OptionParser::AmbiguousOption)
+ name_abbrev.rb:9:in '<main>': ambiguous option: --d (OptionParser::AmbiguousOption)
$ ruby name_abbrev.rb --dr
- name_abbrev.rb:9:in `<main>': ambiguous option: --dr (OptionParser::AmbiguousOption)
+ name_abbrev.rb:9:in '<main>': ambiguous option: --dr (OptionParser::AmbiguousOption)
$ ruby name_abbrev.rb --dry
["--dry-run", true]
$ ruby name_abbrev.rb --dra
@@ -285,7 +285,7 @@ You can disable abbreviation using method +require_exact+.
Executions:
$ ruby no_abbreviation.rb --dry-ru
- no_abbreviation.rb:10:in `<main>': invalid option: --dry-ru (OptionParser::InvalidOption)
+ no_abbreviation.rb:10:in '<main>': invalid option: --dry-ru (OptionParser::InvalidOption)
$ ruby no_abbreviation.rb --dry-run
["--dry-run", true]
@@ -323,7 +323,7 @@ Executions:
Omitting a required argument raises an error:
$ ruby required_argument.rb -x
- required_argument.rb:9:in `<main>': missing argument: -x (OptionParser::MissingArgument)
+ required_argument.rb:9:in '<main>': missing argument: -x (OptionParser::MissingArgument)
==== Option with Optional Argument
@@ -369,7 +369,7 @@ Executions:
$ ruby argument_abbreviation.rb --xxx A
["--xxx", "ABC"]
$ ruby argument_abbreviation.rb --xxx c
- argument_abbreviation.rb:9:in `<main>': invalid argument: --xxx c (OptionParser::InvalidArgument)
+ argument_abbreviation.rb:9:in '<main>': invalid argument: --xxx c (OptionParser::InvalidArgument)
$ ruby argument_abbreviation.rb --yyy a --yyy d
["--yyy", "XYZ"]
["--yyy", "FOO"]
@@ -403,7 +403,7 @@ Executions:
-xXXX Values for required argument
-y [YYY] Values for optional argument
$ ruby explicit_array_values.rb -x
- explicit_array_values.rb:9:in `<main>': missing argument: -x (OptionParser::MissingArgument)
+ explicit_array_values.rb:9:in '<main>': missing argument: -x (OptionParser::MissingArgument)
$ ruby explicit_array_values.rb -x foo
["-x", "foo"]
$ ruby explicit_array_values.rb -x f
@@ -411,9 +411,9 @@ Executions:
$ ruby explicit_array_values.rb -x bar
["-x", "bar"]
$ ruby explicit_array_values.rb -y ba
- explicit_array_values.rb:9:in `<main>': ambiguous argument: -y ba (OptionParser::AmbiguousArgument)
+ explicit_array_values.rb:9:in '<main>': ambiguous argument: -y ba (OptionParser::AmbiguousArgument)
$ ruby explicit_array_values.rb -x baz
- explicit_array_values.rb:9:in `<main>': invalid argument: -x baz (OptionParser::InvalidArgument)
+ explicit_array_values.rb:9:in '<main>': invalid argument: -x baz (OptionParser::InvalidArgument)
===== Explicit Values in Hash
@@ -433,7 +433,7 @@ Executions:
-xXXX Values for required argument
-y [YYY] Values for optional argument
$ ruby explicit_hash_values.rb -x
- explicit_hash_values.rb:9:in `<main>': missing argument: -x (OptionParser::MissingArgument)
+ explicit_hash_values.rb:9:in '<main>': missing argument: -x (OptionParser::MissingArgument)
$ ruby explicit_hash_values.rb -x foo
["-x", 0]
$ ruby explicit_hash_values.rb -x f
@@ -441,7 +441,7 @@ Executions:
$ ruby explicit_hash_values.rb -x bar
["-x", 1]
$ ruby explicit_hash_values.rb -x baz
- explicit_hash_values.rb:9:in `<main>': invalid argument: -x baz (OptionParser::InvalidArgument)
+ explicit_hash_values.rb:9:in '<main>': invalid argument: -x baz (OptionParser::InvalidArgument)
$ ruby explicit_hash_values.rb -y
["-y", nil]
$ ruby explicit_hash_values.rb -y baz
@@ -449,7 +449,7 @@ Executions:
$ ruby explicit_hash_values.rb -y bat
["-y", 3]
$ ruby explicit_hash_values.rb -y ba
- explicit_hash_values.rb:9:in `<main>': ambiguous argument: -y ba (OptionParser::AmbiguousArgument)
+ explicit_hash_values.rb:9:in '<main>': ambiguous argument: -y ba (OptionParser::AmbiguousArgument)
$ ruby explicit_hash_values.rb -y bam
["-y", nil]
@@ -472,7 +472,7 @@ Executions:
$ ruby matched_values.rb --xxx FOO
["--xxx", "FOO"]
$ ruby matched_values.rb --xxx bar
- matched_values.rb:6:in `<main>': invalid argument: --xxx bar (OptionParser::InvalidArgument)
+ matched_values.rb:6:in '<main>': invalid argument: --xxx bar (OptionParser::InvalidArgument)
=== Keyword Argument +into+
@@ -524,7 +524,7 @@ Executions:
-y, --yyyYYY Short and long, required argument
-z, --zzz [ZZZ] Short and long, optional argument
$ ruby missing_options.rb --yyy FOO
- missing_options.rb:11:in `<main>': Missing required options: [:xxx, :zzz] (RuntimeError)
+ missing_options.rb:11:in '<main>': Missing required options: [:xxx, :zzz] (RuntimeError)
==== Default Values for Options
diff --git a/doc/packed_data.rdoc b/doc/packed_data.rdoc
deleted file mode 100644
index 17bbf92023..0000000000
--- a/doc/packed_data.rdoc
+++ /dev/null
@@ -1,589 +0,0 @@
-= Packed \Data
-
-Certain Ruby core methods deal with packing and unpacking data:
-
-- \Method Array#pack:
- Formats each element in array +self+ into a binary string;
- returns that string.
-- \Method String#unpack:
- Extracts data from string +self+,
- forming objects that become the elements of a new array;
- returns that array.
-- \Method String#unpack1:
- Does the same, but unpacks and returns only the first extracted object.
-
-Each of these methods accepts a string +template+,
-consisting of zero or more _directive_ characters,
-each followed by zero or more _modifier_ characters.
-
-Examples (directive <tt>'C'</tt> specifies 'unsigned character'):
-
- [65].pack('C') # => "A" # One element, one directive.
- [65, 66].pack('CC') # => "AB" # Two elements, two directives.
- [65, 66].pack('C') # => "A" # Extra element is ignored.
- [65].pack('') # => "" # No directives.
- [65].pack('CC') # Extra directive raises ArgumentError.
-
- 'A'.unpack('C') # => [65] # One character, one directive.
- 'AB'.unpack('CC') # => [65, 66] # Two characters, two directives.
- 'AB'.unpack('C') # => [65] # Extra character is ignored.
- 'A'.unpack('CC') # => [65, nil] # Extra directive generates nil.
- 'AB'.unpack('') # => [] # No directives.
-
-The string +template+ may contain any mixture of valid directives
-(directive <tt>'c'</tt> specifies 'signed character'):
-
- [65, -1].pack('cC') # => "A\xFF"
- "A\xFF".unpack('cC') # => [65, 255]
-
-The string +template+ may contain whitespace (which is ignored)
-and comments, each of which begins with character <tt>'#'</tt>
-and continues up to and including the next following newline:
-
- [0,1].pack(" C #foo \n C ") # => "\x00\x01"
- "\0\1".unpack(" C #foo \n C ") # => [0, 1]
-
-Any directive may be followed by either of these modifiers:
-
-- <tt>'*'</tt> - The directive is to be applied as many times as needed:
-
- [65, 66].pack('C*') # => "AB"
- 'AB'.unpack('C*') # => [65, 66]
-
-- Integer +count+ - The directive is to be applied +count+ times:
-
- [65, 66].pack('C2') # => "AB"
- [65, 66].pack('C3') # Raises ArgumentError.
- 'AB'.unpack('C2') # => [65, 66]
- 'AB'.unpack('C3') # => [65, 66, nil]
-
- Note: Directives in <tt>%w[A a Z m]</tt> use +count+ differently;
- see {String Directives}[rdoc-ref:packed_data.rdoc@String+Directives].
-
-If elements don't fit the provided directive, only least significant bits are encoded:
-
- [257].pack("C").unpack("C") # => [1]
-
-== Packing \Method
-
-\Method Array#pack accepts optional keyword argument
-+buffer+ that specifies the target string (instead of a new string):
-
- [65, 66].pack('C*', buffer: 'foo') # => "fooAB"
-
-The method can accept a block:
-
- # Packed string is passed to the block.
- [65, 66].pack('C*') {|s| p s } # => "AB"
-
-== Unpacking Methods
-
-Methods String#unpack and String#unpack1 each accept
-an optional keyword argument +offset+ that specifies an offset
-into the string:
-
- 'ABC'.unpack('C*', offset: 1) # => [66, 67]
- 'ABC'.unpack1('C*', offset: 1) # => 66
-
-Both methods can accept a block:
-
- # Each unpacked object is passed to the block.
- ret = []
- "ABCD".unpack("C*") {|c| ret << c }
- ret # => [65, 66, 67, 68]
-
- # The single unpacked object is passed to the block.
- 'AB'.unpack1('C*') {|ele| p ele } # => 65
-
-== \Integer Directives
-
-Each integer directive specifies the packing or unpacking
-for one element in the input or output array.
-
-=== 8-Bit \Integer Directives
-
-- <tt>'c'</tt> - 8-bit signed integer
- (like C <tt>signed char</tt>):
-
- [0, 1, 255].pack('c*') # => "\x00\x01\xFF"
- s = [0, 1, -1].pack('c*') # => "\x00\x01\xFF"
- s.unpack('c*') # => [0, 1, -1]
-
-- <tt>'C'</tt> - 8-bit unsigned integer
- (like C <tt>unsigned char</tt>):
-
- [0, 1, 255].pack('C*') # => "\x00\x01\xFF"
- s = [0, 1, -1].pack('C*') # => "\x00\x01\xFF"
- s.unpack('C*') # => [0, 1, 255]
-
-=== 16-Bit \Integer Directives
-
-- <tt>'s'</tt> - 16-bit signed integer, native-endian
- (like C <tt>int16_t</tt>):
-
- [513, -514].pack('s*') # => "\x01\x02\xFE\xFD"
- s = [513, 65022].pack('s*') # => "\x01\x02\xFE\xFD"
- s.unpack('s*') # => [513, -514]
-
-- <tt>'S'</tt> - 16-bit unsigned integer, native-endian
- (like C <tt>uint16_t</tt>):
-
- [513, -514].pack('S*') # => "\x01\x02\xFE\xFD"
- s = [513, 65022].pack('S*') # => "\x01\x02\xFE\xFD"
- s.unpack('S*') # => [513, 65022]
-
-- <tt>'n'</tt> - 16-bit network integer, big-endian:
-
- s = [0, 1, -1, 32767, -32768, 65535].pack('n*')
- # => "\x00\x00\x00\x01\xFF\xFF\x7F\xFF\x80\x00\xFF\xFF"
- s.unpack('n*')
- # => [0, 1, 65535, 32767, 32768, 65535]
-
-- <tt>'v'</tt> - 16-bit VAX integer, little-endian:
-
- s = [0, 1, -1, 32767, -32768, 65535].pack('v*')
- # => "\x00\x00\x01\x00\xFF\xFF\xFF\x7F\x00\x80\xFF\xFF"
- s.unpack('v*')
- # => [0, 1, 65535, 32767, 32768, 65535]
-
-=== 32-Bit \Integer Directives
-
-- <tt>'l'</tt> - 32-bit signed integer, native-endian
- (like C <tt>int32_t</tt>):
-
- s = [67305985, -50462977].pack('l*')
- # => "\x01\x02\x03\x04\xFF\xFE\xFD\xFC"
- s.unpack('l*')
- # => [67305985, -50462977]
-
-- <tt>'L'</tt> - 32-bit unsigned integer, native-endian
- (like C <tt>uint32_t</tt>):
-
- s = [67305985, 4244504319].pack('L*')
- # => "\x01\x02\x03\x04\xFF\xFE\xFD\xFC"
- s.unpack('L*')
- # => [67305985, 4244504319]
-
-- <tt>'N'</tt> - 32-bit network integer, big-endian:
-
- s = [0,1,-1].pack('N*')
- # => "\x00\x00\x00\x00\x00\x00\x00\x01\xFF\xFF\xFF\xFF"
- s.unpack('N*')
- # => [0, 1, 4294967295]
-
-- <tt>'V'</tt> - 32-bit VAX integer, little-endian:
-
- s = [0,1,-1].pack('V*')
- # => "\x00\x00\x00\x00\x01\x00\x00\x00\xFF\xFF\xFF\xFF"
- s.unpack('v*')
- # => [0, 0, 1, 0, 65535, 65535]
-
-=== 64-Bit \Integer Directives
-
-- <tt>'q'</tt> - 64-bit signed integer, native-endian
- (like C <tt>int64_t</tt>):
-
- s = [578437695752307201, -506097522914230529].pack('q*')
- # => "\x01\x02\x03\x04\x05\x06\a\b\xFF\xFE\xFD\xFC\xFB\xFA\xF9\xF8"
- s.unpack('q*')
- # => [578437695752307201, -506097522914230529]
-
-- <tt>'Q'</tt> - 64-bit unsigned integer, native-endian
- (like C <tt>uint64_t</tt>):
-
- s = [578437695752307201, 17940646550795321087].pack('Q*')
- # => "\x01\x02\x03\x04\x05\x06\a\b\xFF\xFE\xFD\xFC\xFB\xFA\xF9\xF8"
- s.unpack('Q*')
- # => [578437695752307201, 17940646550795321087]
-
-=== Platform-Dependent \Integer Directives
-
-- <tt>'i'</tt> - Platform-dependent width signed integer,
- native-endian (like C <tt>int</tt>):
-
- s = [67305985, -50462977].pack('i*')
- # => "\x01\x02\x03\x04\xFF\xFE\xFD\xFC"
- s.unpack('i*')
- # => [67305985, -50462977]
-
-- <tt>'I'</tt> - Platform-dependent width unsigned integer,
- native-endian (like C <tt>unsigned int</tt>):
-
- s = [67305985, -50462977].pack('I*')
- # => "\x01\x02\x03\x04\xFF\xFE\xFD\xFC"
- s.unpack('I*')
- # => [67305985, 4244504319]
-
-- <tt>'j'</tt> - Pointer-width signed integer, native-endian
- (like C <tt>intptr_t</tt>):
-
- s = [67305985, -50462977].pack('j*')
- # => "\x01\x02\x03\x04\x00\x00\x00\x00\xFF\xFE\xFD\xFC\xFF\xFF\xFF\xFF"
- s.unpack('j*')
- # => [67305985, -50462977]
-
-- <tt>'J'</tt> - Pointer-width unsigned integer, native-endian
- (like C <tt>uintptr_t</tt>):
-
- s = [67305985, 4244504319].pack('J*')
- # => "\x01\x02\x03\x04\x00\x00\x00\x00\xFF\xFE\xFD\xFC\x00\x00\x00\x00"
- s.unpack('J*')
- # => [67305985, 4244504319]
-
-=== Other \Integer Directives
-
-- <tt>'U'</tt> - UTF-8 character:
-
- s = [4194304].pack('U*')
- # => "\xF8\x90\x80\x80\x80"
- s.unpack('U*')
- # => [4194304]
-
-- <tt>'w'</tt> - BER-encoded integer
- (see {BER encoding}[https://en.wikipedia.org/wiki/X.690#BER_encoding]):
-
- s = [1073741823].pack('w*')
- # => "\x83\xFF\xFF\xFF\x7F"
- s.unpack('w*')
- # => [1073741823]
-
-=== Modifiers for \Integer Directives
-
-For the following directives, <tt>'!'</tt> or <tt>'_'</tt> modifiers may be
-suffixed as underlying platform’s native size.
-
-- <tt>'i'</tt>, <tt>'I'</tt> - C <tt>int</tt>, always native size.
-- <tt>'s'</tt>, <tt>'S'</tt> - C <tt>short</tt>.
-- <tt>'l'</tt>, <tt>'L'</tt> - C <tt>long</tt>.
-- <tt>'q'</tt>, <tt>'Q'</tt> - C <tt>long long</tt>, if available.
-- <tt>'j'</tt>, <tt>'J'</tt> - C <tt>intptr_t</tt>, always native size.
-
-Native size modifiers are silently ignored for always native size directives.
-
-The endian modifiers also may be suffixed in the directives above:
-
-- <tt>'>'</tt> - Big-endian.
-- <tt>'<'</tt> - Little-endian.
-
-== \Float Directives
-
-Each float directive specifies the packing or unpacking
-for one element in the input or output array.
-
-=== Single-Precision \Float Directives
-
-- <tt>'F'</tt> or <tt>'f'</tt> - Native format:
-
- s = [3.0].pack('F') # => "\x00\x00@@"
- s.unpack('F') # => [3.0]
-
-- <tt>'e'</tt> - Little-endian:
-
- s = [3.0].pack('e') # => "\x00\x00@@"
- s.unpack('e') # => [3.0]
-
-- <tt>'g'</tt> - Big-endian:
-
- s = [3.0].pack('g') # => "@@\x00\x00"
- s.unpack('g') # => [3.0]
-
-=== Double-Precision \Float Directives
-
-- <tt>'D'</tt> or <tt>'d'</tt> - Native format:
-
- s = [3.0].pack('D') # => "\x00\x00\x00\x00\x00\x00\b@"
- s.unpack('D') # => [3.0]
-
-- <tt>'E'</tt> - Little-endian:
-
- s = [3.0].pack('E') # => "\x00\x00\x00\x00\x00\x00\b@"
- s.unpack('E') # => [3.0]
-
-- <tt>'G'</tt> - Big-endian:
-
- s = [3.0].pack('G') # => "@\b\x00\x00\x00\x00\x00\x00"
- s.unpack('G') # => [3.0]
-
-A float directive may be infinity or not-a-number:
-
- inf = 1.0/0.0 # => Infinity
- [inf].pack('f') # => "\x00\x00\x80\x7F"
- "\x00\x00\x80\x7F".unpack('f') # => [Infinity]
-
- nan = inf/inf # => NaN
- [nan].pack('f') # => "\x00\x00\xC0\x7F"
- "\x00\x00\xC0\x7F".unpack('f') # => [NaN]
-
-== \String Directives
-
-Each string directive specifies the packing or unpacking
-for one byte in the input or output string.
-
-=== Binary \String Directives
-
-- <tt>'A'</tt> - Arbitrary binary string (space padded; count is width);
- +nil+ is treated as the empty string:
-
- ['foo'].pack('A') # => "f"
- ['foo'].pack('A*') # => "foo"
- ['foo'].pack('A2') # => "fo"
- ['foo'].pack('A4') # => "foo "
- [nil].pack('A') # => " "
- [nil].pack('A*') # => ""
- [nil].pack('A2') # => " "
- [nil].pack('A4') # => " "
-
- "foo\0".unpack('A') # => ["f"]
- "foo\0".unpack('A4') # => ["foo"]
- "foo\0bar".unpack('A10') # => ["foo\x00bar"] # Reads past "\0".
- "foo ".unpack('A') # => ["f"]
- "foo ".unpack('A4') # => ["foo"]
- "foo".unpack('A4') # => ["foo"]
-
- russian = "\u{442 435 441 442}" # => "тест"
- russian.size # => 4
- russian.bytesize # => 8
- [russian].pack('A') # => "\xD1"
- [russian].pack('A*') # => "\xD1\x82\xD0\xB5\xD1\x81\xD1\x82"
- russian.unpack('A') # => ["\xD1"]
- russian.unpack('A2') # => ["\xD1\x82"]
- russian.unpack('A4') # => ["\xD1\x82\xD0\xB5"]
- russian.unpack('A*') # => ["\xD1\x82\xD0\xB5\xD1\x81\xD1\x82"]
-
-- <tt>'a'</tt> - Arbitrary binary string (null padded; count is width):
-
- ["foo"].pack('a') # => "f"
- ["foo"].pack('a*') # => "foo"
- ["foo"].pack('a2') # => "fo"
- ["foo\0"].pack('a4') # => "foo\x00"
- [nil].pack('a') # => "\x00"
- [nil].pack('a*') # => ""
- [nil].pack('a2') # => "\x00\x00"
- [nil].pack('a4') # => "\x00\x00\x00\x00"
-
- "foo\0".unpack('a') # => ["f"]
- "foo\0".unpack('a4') # => ["foo\x00"]
- "foo ".unpack('a4') # => ["foo "]
- "foo".unpack('a4') # => ["foo"]
- "foo\0bar".unpack('a4') # => ["foo\x00"] # Reads past "\0".
-
-- <tt>'Z'</tt> - Same as <tt>'a'</tt>,
- except that null is added or ignored with <tt>'*'</tt>:
-
- ["foo"].pack('Z*') # => "foo\x00"
- [nil].pack('Z*') # => "\x00"
-
- "foo\0".unpack('Z*') # => ["foo"]
- "foo".unpack('Z*') # => ["foo"]
- "foo\0bar".unpack('Z*') # => ["foo"] # Does not read past "\0".
-
-=== Bit \String Directives
-
-- <tt>'B'</tt> - Bit string (high byte first):
-
- ['11111111' + '00000000'].pack('B*') # => "\xFF\x00"
- ['10000000' + '01000000'].pack('B*') # => "\x80@"
-
- ['1'].pack('B0') # => ""
- ['1'].pack('B1') # => "\x80"
- ['1'].pack('B2') # => "\x80\x00"
- ['1'].pack('B3') # => "\x80\x00"
- ['1'].pack('B4') # => "\x80\x00\x00"
- ['1'].pack('B5') # => "\x80\x00\x00"
- ['1'].pack('B6') # => "\x80\x00\x00\x00"
-
- "\xff\x00".unpack("B*") # => ["1111111100000000"]
- "\x01\x02".unpack("B*") # => ["0000000100000010"]
-
- "".unpack("B0") # => [""]
- "\x80".unpack("B1") # => ["1"]
- "\x80".unpack("B2") # => ["10"]
- "\x80".unpack("B3") # => ["100"]
-
-- <tt>'b'</tt> - Bit string (low byte first):
-
- ['11111111' + '00000000'].pack('b*') # => "\xFF\x00"
- ['10000000' + '01000000'].pack('b*') # => "\x01\x02"
-
- ['1'].pack('b0') # => ""
- ['1'].pack('b1') # => "\x01"
- ['1'].pack('b2') # => "\x01\x00"
- ['1'].pack('b3') # => "\x01\x00"
- ['1'].pack('b4') # => "\x01\x00\x00"
- ['1'].pack('b5') # => "\x01\x00\x00"
- ['1'].pack('b6') # => "\x01\x00\x00\x00"
-
- "\xff\x00".unpack("b*") # => ["1111111100000000"]
- "\x01\x02".unpack("b*") # => ["1000000001000000"]
-
- "".unpack("b0") # => [""]
- "\x01".unpack("b1") # => ["1"]
- "\x01".unpack("b2") # => ["10"]
- "\x01".unpack("b3") # => ["100"]
-
-=== Hex \String Directives
-
-- <tt>'H'</tt> - Hex string (high nibble first):
-
- ['10ef'].pack('H*') # => "\x10\xEF"
- ['10ef'].pack('H0') # => ""
- ['10ef'].pack('H3') # => "\x10\xE0"
- ['10ef'].pack('H5') # => "\x10\xEF\x00"
-
- ['fff'].pack('H3') # => "\xFF\xF0"
- ['fff'].pack('H4') # => "\xFF\xF0"
- ['fff'].pack('H5') # => "\xFF\xF0\x00"
- ['fff'].pack('H6') # => "\xFF\xF0\x00"
- ['fff'].pack('H7') # => "\xFF\xF0\x00\x00"
- ['fff'].pack('H8') # => "\xFF\xF0\x00\x00"
-
- "\x10\xef".unpack('H*') # => ["10ef"]
- "\x10\xef".unpack('H0') # => [""]
- "\x10\xef".unpack('H1') # => ["1"]
- "\x10\xef".unpack('H2') # => ["10"]
- "\x10\xef".unpack('H3') # => ["10e"]
- "\x10\xef".unpack('H4') # => ["10ef"]
- "\x10\xef".unpack('H5') # => ["10ef"]
-
-- <tt>'h'</tt> - Hex string (low nibble first):
-
- ['10ef'].pack('h*') # => "\x01\xFE"
- ['10ef'].pack('h0') # => ""
- ['10ef'].pack('h3') # => "\x01\x0E"
- ['10ef'].pack('h5') # => "\x01\xFE\x00"
-
- ['fff'].pack('h3') # => "\xFF\x0F"
- ['fff'].pack('h4') # => "\xFF\x0F"
- ['fff'].pack('h5') # => "\xFF\x0F\x00"
- ['fff'].pack('h6') # => "\xFF\x0F\x00"
- ['fff'].pack('h7') # => "\xFF\x0F\x00\x00"
- ['fff'].pack('h8') # => "\xFF\x0F\x00\x00"
-
- "\x01\xfe".unpack('h*') # => ["10ef"]
- "\x01\xfe".unpack('h0') # => [""]
- "\x01\xfe".unpack('h1') # => ["1"]
- "\x01\xfe".unpack('h2') # => ["10"]
- "\x01\xfe".unpack('h3') # => ["10e"]
- "\x01\xfe".unpack('h4') # => ["10ef"]
- "\x01\xfe".unpack('h5') # => ["10ef"]
-
-=== Pointer \String Directives
-
-- <tt>'P'</tt> - Pointer to a structure (fixed-length string):
-
- s = ['abc'].pack('P') # => "\xE0O\x7F\xE5\xA1\x01\x00\x00"
- s.unpack('P*') # => ["abc"]
- ".".unpack("P") # => []
- ("\0" * 8).unpack("P") # => [nil]
- [nil].pack("P") # => "\x00\x00\x00\x00\x00\x00\x00\x00"
-
-- <tt>'p'</tt> - Pointer to a null-terminated string:
-
- s = ['abc'].pack('p') # => "(\xE4u\xE5\xA1\x01\x00\x00"
- s.unpack('p*') # => ["abc"]
- ".".unpack("p") # => []
- ("\0" * 8).unpack("p") # => [nil]
- [nil].pack("p") # => "\x00\x00\x00\x00\x00\x00\x00\x00"
-
-=== Other \String Directives
-
-- <tt>'M'</tt> - Quoted printable, MIME encoding;
- text mode, but input must use LF and output LF;
- (see {RFC 2045}[https://www.ietf.org/rfc/rfc2045.txt]):
-
- ["a b c\td \ne"].pack('M') # => "a b c\td =\n\ne=\n"
- ["\0"].pack('M') # => "=00=\n"
-
- ["a"*1023].pack('M') == ("a"*73+"=\n")*14+"a=\n" # => true
- ("a"*73+"=\na=\n").unpack('M') == ["a"*74] # => true
- (("a"*73+"=\n")*14+"a=\n").unpack('M') == ["a"*1023] # => true
-
- "a b c\td =\n\ne=\n".unpack('M') # => ["a b c\td \ne"]
- "=00=\n".unpack('M') # => ["\x00"]
-
- "pre=31=32=33after".unpack('M') # => ["pre123after"]
- "pre=\nafter".unpack('M') # => ["preafter"]
- "pre=\r\nafter".unpack('M') # => ["preafter"]
- "pre=".unpack('M') # => ["pre="]
- "pre=\r".unpack('M') # => ["pre=\r"]
- "pre=hoge".unpack('M') # => ["pre=hoge"]
- "pre==31after".unpack('M') # => ["pre==31after"]
- "pre===31after".unpack('M') # => ["pre===31after"]
-
-- <tt>'m'</tt> - Base64 encoded string;
- count specifies input bytes between each newline,
- rounded down to nearest multiple of 3;
- if count is zero, no newlines are added;
- (see {RFC 4648}[https://www.ietf.org/rfc/rfc4648.txt]):
-
- [""].pack('m') # => ""
- ["\0"].pack('m') # => "AA==\n"
- ["\0\0"].pack('m') # => "AAA=\n"
- ["\0\0\0"].pack('m') # => "AAAA\n"
- ["\377"].pack('m') # => "/w==\n"
- ["\377\377"].pack('m') # => "//8=\n"
- ["\377\377\377"].pack('m') # => "////\n"
-
- "".unpack('m') # => [""]
- "AA==\n".unpack('m') # => ["\x00"]
- "AAA=\n".unpack('m') # => ["\x00\x00"]
- "AAAA\n".unpack('m') # => ["\x00\x00\x00"]
- "/w==\n".unpack('m') # => ["\xFF"]
- "//8=\n".unpack('m') # => ["\xFF\xFF"]
- "////\n".unpack('m') # => ["\xFF\xFF\xFF"]
- "A\n".unpack('m') # => [""]
- "AA\n".unpack('m') # => ["\x00"]
- "AA=\n".unpack('m') # => ["\x00"]
- "AAA\n".unpack('m') # => ["\x00\x00"]
-
- [""].pack('m0') # => ""
- ["\0"].pack('m0') # => "AA=="
- ["\0\0"].pack('m0') # => "AAA="
- ["\0\0\0"].pack('m0') # => "AAAA"
- ["\377"].pack('m0') # => "/w=="
- ["\377\377"].pack('m0') # => "//8="
- ["\377\377\377"].pack('m0') # => "////"
-
- "".unpack('m0') # => [""]
- "AA==".unpack('m0') # => ["\x00"]
- "AAA=".unpack('m0') # => ["\x00\x00"]
- "AAAA".unpack('m0') # => ["\x00\x00\x00"]
- "/w==".unpack('m0') # => ["\xFF"]
- "//8=".unpack('m0') # => ["\xFF\xFF"]
- "////".unpack('m0') # => ["\xFF\xFF\xFF"]
-
-- <tt>'u'</tt> - UU-encoded string:
-
- [""].pack("u") # => ""
- ["a"].pack("u") # => "!80``\n"
- ["aaa"].pack("u") # => "#86%A\n"
-
- "".unpack("u") # => [""]
- "#86)C\n".unpack("u") # => ["abc"]
-
-== Offset Directives
-
-- <tt>'@'</tt> - Begin packing at the given byte offset;
- for packing, null fill if necessary:
-
- [1, 2].pack("C@0C") # => "\x02"
- [1, 2].pack("C@1C") # => "\x01\x02"
- [1, 2].pack("C@5C") # => "\x01\x00\x00\x00\x00\x02"
-
- "\x01\x00\x00\x02".unpack("C@3C") # => [1, 2]
- "\x00".unpack("@1C") # => [nil]
-
-- <tt>'X'</tt> - Back up a byte:
-
- [0, 1, 2].pack("CCXC") # => "\x00\x02"
- [0, 1, 2].pack("CCX2C") # => "\x02"
- "\x00\x02".unpack("CCXC") # => [0, 2, 2]
-
-== Null Byte Directive
-
-- <tt>'x'</tt> - Null byte:
-
- [].pack("x0") # => ""
- [].pack("x") # => "\x00"
- [].pack("x8") # => "\x00\x00\x00\x00\x00\x00\x00\x00"
- "\x00\x00\x02".unpack("CxC") # => [0, 2]
diff --git a/doc/ractor.md b/doc/ractor.md
deleted file mode 100644
index 7a69e839de..0000000000
--- a/doc/ractor.md
+++ /dev/null
@@ -1,952 +0,0 @@
-# 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 (objects whose class is defined in a C extension, such as `StringIO`) are not supported.
- * (3) Move an object: Sending an unshareable object reference with a membership. Sender Ractor can not access moved objects anymore (raise an exception) after moving it. Current implementation makes new object as a moved object for receiver Ractor and copies references of sending object to moved object. `T_DATA` objects are not supported.
- * You can choose "Copy" and "Move" by the `move:` keyword, `Ractor#send(obj, move: true/false)` and `Ractor.yield(obj, move: true/false)` (default is `false` (COPY)).
-
-### Sending/Receiving ports
-
-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 #=> #<TypeError: allocator undefined for Thread>
-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 traversable 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` consists of literals, replaced to `CONST = Ractor.make_shareable(expr)`.
- * otherwise: replaced to `CONST = expr.tap{|o| raise unless Ractor.shareable?(o)}`.
-* 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)
-#=>
-#<Thread:0x000056262de28bd8 run> 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 <main>'
- 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 <main>': unhandled exception
-Traceback (most recent call last):
- 2: from /home/ko1/src/ruby/trunk/test.rb:7:in `block (2 levels) in <main>'
- 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 <main>': unhandled exception
- 1: from /home/ko1/src/ruby/trunk/test.rb:21:in `<main>'
-<internal:ractor>: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
-
-#=> <internal:ractor>: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/doc/rdoc/markup_reference.rb b/doc/rdoc/markup_reference.rb
deleted file mode 100644
index bfc84abd5a..0000000000
--- a/doc/rdoc/markup_reference.rb
+++ /dev/null
@@ -1,1287 +0,0 @@
-require 'rdoc'
-
-# \Class \RDoc::MarkupReference exists only to provide a suitable home
-# for a reference document for \RDoc markup.
-#
-# All objects defined in this class -- classes, modules, methods, aliases,
-# attributes, and constants -- are solely for illustrating \RDoc markup,
-# and have no other legitimate use.
-#
-# == About the Examples
-#
-# - Examples in this reference are Ruby code and comments;
-# certain differences from other sources
-# (such as C code and comments) are noted.
-# - Almost all examples on this page are all RDoc-like;
-# that is, they have no explicit comment markers like Ruby <tt>#</tt>
-# or C <tt>/* ... */</tt>.
-# - An example that shows rendered HTML output
-# displays that output in a blockquote:
-#
-# >>>
-# Some stuff
-#
-# == \RDoc Sources
-#
-# The sources of \RDoc documentation vary according to the type of file:
-#
-# - <tt>.rb</tt> (Ruby code file):
-#
-# - Markup may be found in Ruby comments:
-# A comment that immediately precedes the definition
-# of a Ruby class, module, method, alias, constant, or attribute
-# becomes the documentation for that defined object.
-# - An \RDoc directive may be found in:
-#
-# - A trailing comment (on the same line as code);
-# see <tt>:nodoc:</tt>, <tt>:doc:</tt>, and <tt>:notnew:</tt>.
-# - A single-line comment;
-# see other {Directives}[rdoc-ref:RDoc::MarkupReference@Directives].
-#
-# - Documentation may be derived from the Ruby code itself;
-# see {Documentation Derived from Ruby Code}[rdoc-ref:RDoc::MarkupReference@Documentation+Derived+from+Ruby+Code].
-#
-# - <tt>.c</tt> (C code file): markup is parsed from C comments.
-# A comment that immediately precedes
-# a function that implements a Ruby method,
-# or otherwise immediately precedes the definition of a Ruby object,
-# becomes the documentation for that object.
-# - <tt>.rdoc</tt> (\RDoc markup text file) or <tt>.md</tt> (\RDoc markdown text file):
-# markup is parsed from the entire file.
-# The text is not associated with any code object,
-# but may (depending on how the documentation is built)
-# become a separate page.
-#
-# An <i>RDoc document</i>:
-#
-# - A (possibly multi-line) comment in a Ruby or C file
-# that generates \RDoc documentation (as above).
-# - The entire markup (<tt>.rdoc</tt>) file or markdown (<tt>.md</tt>) file
-# (which is usually multi-line).
-#
-# === Blocks
-#
-# It's convenient to think of an \RDoc document as a sequence of _blocks_
-# of various types (details at the links):
-#
-# - {Paragraph}[rdoc-ref:RDoc::MarkupReference@Paragraphs]:
-# an ordinary paragraph.
-# - {Verbatim text block}[rdoc-ref:RDoc::MarkupReference@Verbatim+Text+Blocks]:
-# a block of text to be rendered literally.
-# - {Code block}[rdoc-ref:RDoc::MarkupReference@Code+Blocks]:
-# a verbatim text block containing Ruby code,
-# to be rendered with code highlighting.
-# - {Block quote}[rdoc-ref:RDoc::MarkupReference@Block+Quotes]:
-# a longish quoted passage, to be rendered with indentation
-# instead of quote marks.
-# - {List}[rdoc-ref:RDoc::MarkupReference@Lists]: items for
-# a bullet list, numbered list, lettered list, or labeled list.
-# - {Heading}[rdoc-ref:RDoc::MarkupReference@Headings]:
-# a heading.
-# - {Horizontal rule}[rdoc-ref:RDoc::MarkupReference@Horizontal+Rules]:
-# a line across the rendered page.
-# - {Directive}[rdoc-ref:RDoc::MarkupReference@Directives]:
-# various special directions for the rendering.
-# - {Text Markup}[rdoc-ref:RDoc:MarkupReference@Text+Markup]:
-# text to be rendered in a special way.
-#
-# About the blocks:
-#
-# - Except for a paragraph, a block is distinguished by its indentation,
-# or by unusual initial or embedded characters.
-# - Any block may appear independently
-# (that is, not nested in another block);
-# some blocks may be nested, as detailed below.
-# - In a multi-line block,
-# \RDoc looks for the block's natural left margin,
-# which becomes the <em>base margin</em> for the block
-# and is the initial <em>current margin</em> for the block.
-#
-# ==== Paragraphs
-#
-# A paragraph consists of one or more non-empty lines of ordinary text,
-# each beginning at the current margin.
-#
-# Note: Here, <em>ordinary text</em> means text that is <em>not identified</em>
-# by indentation, or by unusual initial or embedded characters.
-# See below.
-#
-# Paragraphs are separated by one or more empty lines.
-#
-# Example input:
-#
-# \RDoc produces HTML and command-line documentation for Ruby projects.
-# \RDoc includes the rdoc and ri tools for generating and displaying
-# documentation from the command-line.
-#
-# You'll love it.
-#
-# Rendered HTML:
-# >>>
-# \RDoc produces HTML and command-line documentation for Ruby projects.
-# \RDoc includes the rdoc and ri tools for generating and displaying
-# documentation from the command-line.
-#
-# You'll love it.
-#
-# A paragraph may contain nested blocks, including:
-#
-# - {Verbatim text blocks}[rdoc-ref:RDoc::MarkupReference@Verbatim+Text+Blocks].
-# - {Code blocks}[rdoc-ref:RDoc::MarkupReference@Code+Blocks].
-# - {Block quotes}[rdoc-ref:RDoc::MarkupReference@Block+Quotes].
-# - {Lists}[rdoc-ref:RDoc::MarkupReference@Lists].
-# - {Headings}[rdoc-ref:RDoc::MarkupReference@Headings].
-# - {Horizontal rules}[rdoc-ref:RDoc::MarkupReference@Horizontal+Rules].
-# - {Text Markup}[rdoc-ref:RDoc:MarkupReference@Text+Markup].
-#
-# ==== Verbatim Text Blocks
-#
-# Text indented farther than the current margin becomes a <em>verbatim text block</em>
-# (or a code block, described next).
-# In the rendered HTML, such text:
-#
-# - Is indented.
-# - Has a contrasting background color.
-#
-# The verbatim text block ends at the first line beginning at the current margin.
-#
-# Example input:
-#
-# This is not verbatim text.
-#
-# This is verbatim text.
-# Whitespace is honored. # See?
-# Whitespace is honored. # See?
-#
-# This is still the same verbatim text block.
-#
-# This is not verbatim text.
-#
-# Rendered HTML:
-# >>>
-# This is not verbatim text.
-#
-# This is verbatim text.
-# Whitespace is honored. # See?
-# Whitespace is honored. # See?
-#
-# This is still the same verbatim text block.
-#
-# This is not verbatim text.
-#
-# A verbatim text block may not contain nested blocks of any kind
-# -- it's verbatim.
-#
-# ==== Code Blocks
-#
-# A special case of verbatim text is the <em>code block</em>,
-# which is merely verbatim text that \RDoc recognizes as Ruby code:
-#
-# In the rendered HTML, the code block:
-#
-# - Is indented.
-# - Has a contrasting background color.
-# - Has syntax highlighting.
-#
-# Example input:
-#
-# Consider this method:
-#
-# def foo(name = '', value = 0)
-# @name = name # Whitespace is still honored.
-# @value = value
-# end
-#
-#
-# Rendered HTML:
-# >>>
-# Consider this method:
-#
-# def foo(name = '', value = 0)
-# @name = name # Whitespace is still honored.
-# @value = value
-# end
-#
-# Pro tip: If your indented Ruby code does not get highlighted,
-# it may contain a syntax error.
-#
-# A code block may not contain nested blocks of any kind
-# -- it's verbatim.
-#
-# ==== Block Quotes
-#
-# You can use the characters <tt>>>></tt> (unindented),
-# followed by indented text, to treat the text
-# as a {block quote}[https://en.wikipedia.org/wiki/Block_quotation]:
-#
-# Example input:
-#
-# Here's a block quote:
-# >>>
-# Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer
-# commodo quam iaculis massa posuere, dictum fringilla justo pulvinar.
-# Quisque turpis erat, pharetra eu dui at, sollicitudin accumsan nulla.
-#
-# Aenean congue ligula eu ligula molestie, eu pellentesque purus
-# faucibus. In id leo non ligula condimentum lobortis. Duis vestibulum,
-# diam in pellentesque aliquet, mi tellus placerat sapien, id euismod
-# purus magna ut tortor.
-#
-# Rendered HTML:
-#
-# >>>
-# Here's a block quote:
-# >>>
-# Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer
-# commodo quam iaculis massa posuere, dictum fringilla justo pulvinar.
-# Quisque turpis erat, pharetra eu dui at, sollicitudin accumsan nulla.
-#
-# Aenean congue ligula eu ligula molestie, eu pellentesque purus
-# faucibus. In id leo non ligula condimentum lobortis. Duis vestibulum,
-# diam in pellentesque aliquet, mi tellus placerat sapien, id euismod
-# purus magna ut tortor.
-#
-# Note that, unlike verbatim text, single newlines are not honored,
-# but that a double newline begins a new paragraph in the block quote.
-#
-# A block quote may contain nested blocks, including:
-#
-# - Other block quotes.
-# - {Paragraphs}[rdoc-ref:RDoc::MarkupReference@Paragraphs].
-# - {Verbatim text blocks}[rdoc-ref:RDoc::MarkupReference@Verbatim+Text+Blocks].
-# - {Code blocks}[rdoc-ref:RDoc::MarkupReference@Code+Blocks].
-# - {Lists}[rdoc-ref:RDoc::MarkupReference@Lists].
-# - {Headings}[rdoc-ref:RDoc::MarkupReference@Headings].
-# - {Horizontal rules}[rdoc-ref:RDoc::MarkupReference@Horizontal+Rules].
-# - {Text Markup}[rdoc-ref:RDoc:MarkupReference@Text+Markup].
-#
-# ==== Lists
-#
-# Each type of list item is marked by a special beginning:
-#
-# - Bullet list item: Begins with a hyphen or asterisk.
-# - Numbered list item: Begins with digits and a period.
-# - Lettered list item: Begins with an alphabetic character and a period.
-# - Labeled list item: Begins with one of:
-# - Square-bracketed text.
-# - A word followed by two colons.
-#
-# A list begins with a list item and continues, even across blank lines,
-# as long as list items of the same type are found at the same indentation level.
-#
-# A new list resets the current margin inward.
-# Additional lines of text aligned at that margin
-# are part of the continuing list item.
-#
-# A list item may be continued on additional lines that are aligned
-# with the first line. See examples below.
-#
-# A list item may contain nested blocks, including:
-#
-# - Other lists of any type.
-# - {Paragraphs}[rdoc-ref:RDoc::MarkupReference@Paragraphs].
-# - {Verbatim text blocks}[rdoc-ref:RDoc::MarkupReference@Verbatim+Text+Blocks].
-# - {Code blocks}[rdoc-ref:RDoc::MarkupReference@Code+Blocks].
-# - {Block quotes}[rdoc-ref:RDoc::MarkupReference@Block+Quotes].
-# - {Headings}[rdoc-ref:RDoc::MarkupReference@Headings].
-# - {Horizontal rules}[rdoc-ref:RDoc::MarkupReference@Horizontal+Rules].
-# - {Text Markup}[rdoc-ref:RDoc:MarkupReference@Text+Markup].
-#
-# ===== Bullet Lists
-#
-# A bullet list item begins with a hyphen or asterisk.
-#
-# Example input:
-#
-# - An item.
-# - Another.
-# - An item spanning
-# multiple lines.
-#
-# * Yet another.
-# - Last one.
-#
-# Rendered HTML:
-# >>>
-# - An item.
-# - Another.
-# - An item spanning
-# multiple lines.
-#
-# * Yet another.
-# - Last one.
-#
-# ===== Numbered Lists
-#
-# A numbered list item begins with digits and a period.
-#
-# The items are automatically re-numbered.
-#
-# Example input:
-#
-# 100. An item.
-# 10. Another.
-# 1. An item spanning
-# multiple lines.
-#
-# 1. Yet another.
-# 1000. Last one.
-#
-# Rendered HTML:
-# >>>
-# 100. An item.
-# 10. Another.
-# 1. An item spanning
-# multiple lines.
-#
-# 1. Yet another.
-# 1000. Last one.
-#
-# ===== Lettered Lists
-#
-# A lettered list item begins with letters and a period.
-#
-# The items are automatically "re-lettered."
-#
-# Example input:
-#
-# z. An item.
-# y. Another.
-# x. An item spanning
-# multiple lines.
-#
-# x. Yet another.
-# a. Last one.
-#
-# Rendered HTML:
-# >>>
-# z. An item.
-# y. Another.
-#
-# x. Yet another.
-# a. Last one.
-#
-# ===== Labeled Lists
-#
-# A labeled list item begins with one of:
-#
-# - Square-bracketed text: the label and text are on two lines.
-# - A word followed by two colons: the label and text are on the same line.
-#
-# Example input:
-#
-# [foo] An item.
-# bat:: Another.
-# [bag] An item spanning
-# multiple lines.
-#
-# [bar baz] Yet another.
-# bam:: Last one.
-#
-# Rendered HTML:
-# >>>
-# [foo] An item.
-# bat:: Another.
-# [bag] An item spanning
-# multiple lines.
-#
-# [bar baz] Yet another.
-# bam:: Last one.
-#
-# ==== Headings
-#
-# A heading begins with up to six equal-signs, followed by heading text.
-# Whitespace between those and the heading text is optional.
-#
-# Examples:
-#
-# = Section 1
-# == Section 1.1
-# === Section 1.1.1
-# === Section 1.1.2
-# == Section 1.2
-# = Section 2
-# = Foo
-# == Bar
-# === Baz
-# ==== Bam
-# ===== Bat
-# ====== Bad
-# ============Still a Heading (Level 6)
-# \== Not a Heading
-#
-# A heading may contain only one type of nested block:
-#
-# - {Text Markup}[rdoc-ref:RDoc:MarkupReference@Text+Markup].
-#
-# ==== Horizontal Rules
-#
-# A horizontal rule consists of a line with three or more hyphens
-# and nothing more.
-#
-# Example input:
-#
-# ---
-# --- Not a horizontal rule.
-#
-# -- Also not a horizontal rule.
-# ---
-#
-# Rendered HTML:
-# >>>
-# ---
-# --- Not a horizontal rule.
-#
-# -- Also not a horizontal rule.
-# ---
-#
-# ==== Directives
-#
-# ===== Directives for Allowing or Suppressing Documentation
-#
-# - <tt># :stopdoc:</tt>:
-#
-# - Appears on a line by itself.
-# - Specifies that \RDoc should ignore markup
-# until next <tt>:startdoc:</tt> directive or end-of-file.
-#
-# - <tt># :startdoc:</tt>:
-#
-# - Appears on a line by itself.
-# - Specifies that \RDoc should resume parsing markup.
-#
-# - <tt># :enddoc:</tt>:
-#
-# - Appears on a line by itself.
-# - Specifies that \RDoc should ignore markup to end-of-file
-# regardless of other directives.
-#
-# - <tt># :nodoc:</tt>:
-#
-# - Appended to a line of code
-# that defines a class, module, method, alias, constant, or attribute.
-#
-# - Specifies that the defined object should not be documented.
-#
-# - For a method definition in C code, it the directive must be in the comment line
-# immediately preceding the definition:
-#
-# /* :nodoc: */
-# static VALUE
-# some_method(VALUE self)
-# {
-# return self;
-# }
-#
-# Note that this directive has <em>no effect at all</em>
-# when placed at the method declaration:
-#
-# /* :nodoc: */
-# rb_define_method(cMyClass, "do_something", something_func, 0);
-#
-# The above comment is just a comment and has nothing to do with \RDoc.
-# Therefore, +do_something+ method will be reported as "undocumented"
-# unless that method or function is documented elsewhere.
-#
-# - For a constant definition in C code, this directive <em>can not work</em>
-# because there is no "implementation" place for a constant.
-#
-# - <tt># :nodoc: all</tt>:
-#
-# - Appended to a line of code
-# that defines a class or module.
-# - Specifies that the class or module should not be documented.
-# By default, however, a nested class or module _will_ be documented.
-#
-# - <tt># :doc:</tt>:
-#
-# - Appended to a line of code
-# that defines a class, module, method, alias, constant, or attribute.
-# - Specifies the defined object should be documented, even if it otherwise
-# would not be documented.
-#
-# - <tt># :notnew:</tt> (aliased as <tt>:not_new:</tt> and <tt>:not-new:</tt>):
-#
-# - Appended to a line of code
-# that defines instance method +initialize+.
-# - Specifies that singleton method +new+ should not be documented.
-# By default, Ruby fakes a corresponding singleton method +new+,
-# which \RDoc includes in the documentation.
-# Note that instance method +initialize+ is private, and so by default
-# is not documented.
-#
-# For Ruby code, but not for other \RDoc sources,
-# there is a shorthand for <tt>:stopdoc:</tt> and <tt>:startdoc:</tt>:
-#
-# # Documented.
-# #--
-# # Not documented.
-# #++
-# # Documented.
-#
-# For C code, any of directives <tt>:startdoc:</tt>, <tt>:stopdoc:</tt>,
-# and <tt>:enddoc:</tt> may appear in a stand-alone comment:
-#
-# /* :startdoc: */
-# /* :stopdoc: */
-# /* :enddoc: */
-#
-# ===== Directive for Specifying \RDoc Source Format
-#
-# - <tt># :markup: _type_</tt>:
-#
-# - Appears on a line by itself.
-# - Specifies the format for the \RDoc input;
-# parameter +type+ is one of +markdown+, +rd+, +rdoc+, +tomdoc+.
-#
-# ===== Directives for HTML Output
-#
-# - <tt># :title: _text_</tt>:
-#
-# - Appears on a line by itself.
-# - Specifies the title for the HTML output.
-#
-# - <tt># :main: _filename_</tt>:
-# - Appears on a line by itself.
-# - Specifies the HTML file to be displayed first.
-#
-# ===== Directives for Method Documentation
-#
-# - <tt># :call-seq:</tt>:
-#
-# - Appears on a line by itself.
-# - Specifies the calling sequence to be reported in the HTML,
-# overriding the actual calling sequence in the code.
-# See method #call_seq_directive.
-#
-# Note that \RDoc can build the calling sequence for a Ruby-coded method,
-# but not for other languages.
-# You may want to override that by explicitly giving a <tt>:call-seq:</tt>
-# directive if you want to include:
-#
-# - A return type, which is not automatically inferred.
-# - Multiple calling sequences.
-#
-# For C code, the directive may appear in a stand-alone comment.
-#
-# - <tt># :args: _arg_names_</tt> (aliased as <tt>:arg:</tt>):
-#
-# - Appears on a line by itself.
-# - Specifies the arguments to be reported in the HTML,
-# overriding the actual arguments in the code.
-# See method #args_directive.
-#
-# - <tt># :yields: _arg_names_</tt> (aliased as <tt>:yield:</tt>):
-#
-# - Appears on a line by itself.
-# - Specifies the yield arguments to be reported in the HTML,
-# overriding the actual yield in the code.
-# See method #yields_directive.
-#
-# ===== Directives for Organizing Documentation
-#
-# By default, \RDoc groups:
-#
-# - Singleton methods together in alphabetical order.
-# - Instance methods and their aliases together in alphabetical order.
-# - Attributes and their aliases together in alphabetical order.
-#
-# You can use directives to modify those behaviors.
-#
-# - <tt># :section: _section_title_</tt>:
-#
-# - Appears on a line by itself.
-# - Specifies that following methods are to be grouped into the section
-# with the given <em>section_title</em>,
-# or into the default section if no title is given.
-# The directive remains in effect until another such directive is given,
-# but may be temporarily overridden by directive <tt>:category:</tt>.
-# See below.
-#
-# The comment block containing this directive:
-#
-# - Must be separated by a blank line from the documentation for the next item.
-# - May have one or more lines preceding the directive.
-# These will be removed, along with any trailing lines that match them.
-# Such lines may be visually helpful.
-# - Lines of text that are not so removed become the descriptive text
-# for the section.
-#
-# Example:
-#
-# # ----------------------------------------
-# # :section: My Section
-# # This is the section that I wrote.
-# # See it glisten in the noon-day sun.
-# # ----------------------------------------
-#
-# ##
-# # Comment for some_method
-# def some_method
-# # ...
-# end
-#
-# You can use directive <tt>:category:</tt> to temporarily
-# override the current section.
-#
-# - <tt># :category: _section_title_</tt>:
-#
-# - Appears on a line by itself.
-# - Specifies that just one following method is to be included
-# in the given section, or in the default section if no title is given.
-# Subsequent methods are to be grouped into the current section.
-#
-# ===== Directive for Including a File
-#
-# - <tt># :include: _filepath_</tt>:
-#
-# - Appears on a line by itself.
-# - Specifies that the contents of the given file
-# are to be included at this point.
-# The file content is shifted to have the same indentation as the colon
-# at the start of the directive.
-#
-# The file is searched for in the directory containing the current file,
-# and then in each of the directories given with the <tt>--include</tt>
-# command-line option.
-#
-# For C code, the directive may appear in a stand-alone comment
-#
-# ==== Text Markup
-#
-# Text markup is metatext that affects HTML rendering:
-#
-# - Typeface: italic, bold, monofont.
-# - Character conversions: copyright, trademark, certain punctuation.
-# - Links.
-# - Escapes: marking text as "not markup."
-#
-# ===== Typeface Markup
-#
-# Typeface markup can specify that text is to be rendered
-# as italic, bold, or monofont.
-#
-# Typeface markup may contain only one type of nested block:
-#
-# - More typeface markup:
-# italic, bold, monofont.
-#
-# ====== Italic
-#
-# Text may be marked as italic via HTML tag <tt><i></tt> or <tt><em></tt>.
-#
-# Example input:
-#
-# <i>Italicized words</i> in a paragraph.
-#
-# >>>
-# <i>Italicized words in a block quote</i>.
-#
-# - <i>Italicized words</i> in a list item.
-#
-# ====== <i>Italicized words</i> in a Heading
-#
-# <i>Italicized passage containing *bold* and +monofont+.</i>
-#
-# Rendered HTML:
-# >>>
-# <i>Italicized words</i> in a paragraph.
-#
-# >>>
-# <i>Italicized words in a block quote</i>.
-#
-# - <i>Italicized words</i> in a list item.
-#
-# ====== <i>Italicized words</i> in a Heading
-#
-# <i>Italicized passage containing *bold* and +monofont+.</i>
-#
-# A single word may be italicized via a shorthand:
-# prefixed and suffixed underscores.
-#
-# Example input:
-#
-# _Italic_ in a paragraph.
-#
-# >>>
-# _Italic_ in a block quote.
-#
-# - _Italic_ in a list item.
-#
-# ====== _Italic_ in a Heading
-#
-# Rendered HTML:
-# >>>
-# _Italic_ in a paragraph.
-#
-# >>>
-# _Italic_ in a block quote.
-#
-# - _Italic_ in a list item.
-#
-# ====== _Italic_ in a Heading
-#
-# ====== Bold
-#
-# Text may be marked as bold via HTML tag <tt><b></tt>.
-#
-# Example input:
-#
-# <b>Bold words</b> in a paragraph.
-#
-# >>>
-# <b>Bold words</b> in a block quote.
-#
-# - <b>Bold words</b> in a list item.
-#
-# ====== <b>Bold words</b> in a Heading
-#
-# <b>Bold passage containing _italics_ and +monofont+.</b>
-#
-# Rendered HTML:
-#
-# >>>
-# <b>Bold words</b> in a paragraph.
-#
-# >>>
-# <b>Bold words</b> in a block quote.
-#
-# - <b>Bold words</b> in a list item.
-#
-# ====== <b>Bold words</b> in a Heading
-#
-# <b>Bold passage containing _italics_ and +monofont+.</b>
-#
-# A single word may be made bold via a shorthand:
-# prefixed and suffixed asterisks.
-#
-# Example input:
-#
-# *Bold* in a paragraph.
-#
-# >>>
-# *Bold* in a block quote.
-#
-# - *Bold* in a list item.
-#
-# ===== *Bold* in a Heading
-#
-# Rendered HTML:
-#
-# >>>
-# *Bold* in a paragraph.
-#
-# >>>
-# *Bold* in a block quote.
-#
-# - *Bold* in a list item.
-#
-# ===== *Bold* in a Heading
-#
-# ====== Monofont
-#
-# Text may be marked as monofont
-# -- sometimes called 'typewriter font' --
-# via HTML tag <tt><tt></tt> or <tt><code></tt>.
-#
-# Example input:
-#
-# <tt>Monofont words</tt> in a paragraph.
-#
-# >>>
-# <tt>Monofont words</tt> in a block quote.
-#
-# - <tt>Monofont words</tt> in a list item.
-#
-# ====== <tt>Monofont words</tt> in heading
-#
-# <tt>Monofont passage containing _italics_ and *bold*.</tt>
-#
-# Rendered HTML:
-#
-# >>>
-# <tt>Monofont words</tt> in a paragraph.
-#
-# >>>
-# <tt>Monofont words</tt> in a block quote.
-#
-# - <tt>Monofont words</tt> in a list item.
-#
-# ====== <tt>Monofont words</tt> in heading
-#
-# <tt>Monofont passage containing _italics_ and *bold*.</tt>
-#
-# A single word may be made monofont by a shorthand:
-# prefixed and suffixed plus-signs.
-#
-# Example input:
-#
-# +Monofont+ in a paragraph.
-#
-# >>>
-# +Monofont+ in a block quote.
-#
-# - +Monofont+ in a list item.
-#
-# ====== +Monofont+ in a Heading
-#
-# Rendered HTML:
-#
-# >>>
-# +Monofont+ in a paragraph.
-#
-# >>>
-# +Monofont+ in a block quote.
-#
-# - +Monofont+ in a list item.
-#
-# ====== +Monofont+ in a Heading
-#
-# ==== Character Conversions
-#
-# Certain combinations of characters may be converted to special characters;
-# whether the conversion occurs depends on whether the special character
-# is available in the current encoding.
-#
-# - <tt>(c)</tt> converts to (c) (copyright character); must be lowercase.
-#
-# - <tt>(r)</tt> converts to (r) (registered trademark character); must be lowercase.
-#
-# - <tt>'foo'</tt> converts to 'foo' (smart single-quotes).
-#
-# - <tt>"foo"</tt> converts to "foo" (smart double-quotes).
-#
-# - <tt>foo ... bar</tt> converts to foo ... bar (1-character ellipsis).
-#
-# - <tt>foo -- bar</tt> converts to foo -- bar (1-character en-dash).
-#
-# - <tt>foo --- bar</tt> converts to foo --- bar (1-character em-dash).
-#
-# ==== Links
-#
-# Certain strings in \RDoc text are converted to links.
-# Any such link may be suppressed by prefixing a backslash.
-# This section shows how to link to various
-# targets.
-#
-# [Class]
-#
-# - On-page: <tt>DummyClass</tt> links to DummyClass.
-# - Off-page: <tt>RDoc::Alias</tt> links to RDoc::Alias.
-#
-# [Module]
-#
-# - On-page: <tt>DummyModule</tt> links to DummyModule.
-# - Off-page: <tt>RDoc</tt> links to RDoc.
-#
-# [Constant]
-#
-# - On-page: <tt>DUMMY_CONSTANT</tt> links to DUMMY_CONSTANT.
-# - Off-page: <tt>RDoc::Text::MARKUP_FORMAT</tt> links to RDoc::Text::MARKUP_FORMAT.
-#
-# [Singleton Method]
-#
-# - On-page: <tt>::dummy_singleton_method</tt> links to ::dummy_singleton_method.
-# - Off-page<tt>RDoc::TokenStream::to_html</tt> links to RDoc::TokenStream::to_html.
-#
-# Note: Occasionally \RDoc is not linked to a method whose name
-# has only special characters. Check whether the links you were expecting
-# are actually there. If not, you'll need to put in an explicit link;
-# see below.
-#
-# Pro tip: The link to any method is available in the alphabetical table of contents
-# at the top left of the page for the class or module.
-#
-# [Instance Method]
-#
-# - On-page: <tt>#dummy_instance_method</tt> links to #dummy_instance_method.
-# - Off-page: <tt>RDoc::Alias#html_name</tt> links to RDoc::Alias#html_name.
-#
-# See the Note and Pro Tip immediately above.
-#
-# [Attribute]
-#
-# - On-page: <tt>#dummy_attribute</tt> links to #dummy_attribute.
-# - Off-page: <tt>RDoc::Alias#name</tt> links to RDoc::Alias#name.
-#
-# [Alias]
-#
-# - On-page: <tt>#dummy_instance_alias</tt> links to #dummy_instance_alias.
-# - Off-page: <tt>RDoc::Alias#new_name</tt> links to RDoc::Alias#new_name.
-#
-# [Protocol +http+]
-#
-# - Linked: <tt>http://yahoo.com</tt> links to http://yahoo.com.
-#
-# [Protocol +https+]
-#
-# - Linked: <tt>https://github.com</tt> links to https://github.com.
-#
-# [Protocol +www+]
-#
-# - Linked: <tt>www.yahoo.com</tt> links to www.yahoo.com.
-#
-# [Protocol +ftp+]
-#
-# - Linked: <tt>ftp://nosuch.site</tt> links to ftp://nosuch.site.
-#
-# [Protocol +mailto+]
-#
-# - Linked: <tt>mailto:/foo@bar.com</tt> links to mailto://foo@bar.com.
-#
-# [Protocol +irc+]
-#
-# - link: <tt>irc://irc.freenode.net/ruby</tt> links to irc://irc.freenode.net/ruby.
-#
-# [Image Filename Extensions]
-#
-# - Link: <tt>https://www.ruby-lang.org/images/header-ruby-logo@2x.png</tt> is
-# converted to an in-line HTML +img+ tag, which displays the image in the HTML:
-#
-# https://www.ruby-lang.org/images/header-ruby-logo@2x.png
-#
-# Also works for +bmp+, +gif+, +jpeg+, and +jpg+ files.
-#
-# Note: Works only for a fully qualified URL.
-#
-# [Heading]
-#
-# - Link: <tt>RDoc::RD@LICENSE</tt> links to RDoc::RDoc::RD@LICENSE.
-#
-# Note that spaces in the actual heading are represented by <tt>+</tt> characters
-# in the linkable text.
-#
-# - Link: <tt>RDoc::Options@Saved+Options</tt>
-# links to RDoc::Options@Saved+Options.
-#
-# Punctuation and other special characters must be escaped like CGI.escape.
-#
-# Pro tip: The link to any heading is available in the alphabetical table of contents
-# at the top left of the page for the class or module.
-#
-# [Section]
-#
-# See {Directives for Organizing Documentation}[#class-RDoc::MarkupReference-label-Directives+for+Organizing+Documentation].
-#
-# - Link: <tt>RDoc::Markup::ToHtml@Visitor</tt> links to RDoc::Markup::ToHtml@Visitor.
-#
-# If a section and a heading share the same name, the link target is the section.
-#
-# [Single-Word Text Link]
-#
-# Use square brackets to create single-word text link:
-#
-# - <tt>GitHub[https://github.com]</tt> links to GitHub[https://github.com].
-#
-# [Multi-Word Text Link]
-#
-# Use square brackets and curly braces to create a multi-word text link.
-#
-# - <tt>{GitHub home page}[https://github.com]</tt> links to
-# {GitHub home page}[https://github.com].
-#
-# [<tt>rdoc-ref</tt> Scheme]
-#
-# A link with the <tt>rdoc-ref:</tt> scheme links to the referenced item,
-# if that item exists.
-# The referenced item may be a class, module, method, file, etc.
-#
-# - Class: <tt>Alias[rdoc-ref:RDoc::Alias]</tt> links to Alias[rdoc-ref:RDoc::Alias].
-# - Module: <tt>RDoc[rdoc-ref:RDoc]</tt> links to RDoc[rdoc-ref:RDoc].
-# - Method: <tt>foo[rdoc-ref:RDoc::Markup::ToHtml#handle_regexp_RDOCLINK]</tt>
-# links to foo[rdoc-ref:RDoc::Markup::ToHtml#handle_regexp_RDOCLINK].
-# - Constant: <tt>bar[rdoc-ref:RDoc::Markup::ToHtml::LIST_TYPE_TO_HTML]</tt>
-# links to bar[rdoc-ref:RDoc::Markup::ToHtml::LIST_TYPE_TO_HTML].
-# - Attribute: <tt>baz[rdoc-ref:RDoc::Markup::ToHtml#code_object]</tt>
-# links to baz[rdoc-ref:RDoc::Markup::ToHtml#code_object].
-# - Alias: <tt>bad[rdoc-ref:RDoc::MarkupReference#dummy_instance_alias]</tt> links to
-# bad[rdoc-ref:RDoc::MarkupReference#dummy_instance_alias].
-#
-# If the referenced item does not exist, no link is generated
-# and entire <tt>rdoc-ref:</tt> square-bracketed clause is removed
-# from the resulting text.
-#
-# - <tt>Nosuch[rdoc-ref:RDoc::Nosuch]</tt> is rendered as
-# Nosuch[rdoc-ref:RDoc::Nosuch].
-#
-#
-# [<tt>rdoc-label</tt> Scheme]
-#
-# [Simple]
-#
-# You can specify a link target using this form,
-# where the second part cites the id of an HTML element.
-#
-# This link refers to the constant +DUMMY_CONSTANT+ on this page:
-#
-# - <tt>{DUMMY_CONSTANT}[rdoc-label:DUMMY_CONSTANT]</tt>
-#
-# Thus:
-#
-# {DUMMY_CONSTANT}[rdoc-label:DUMMY_CONSTANT]
-#
-# [With Return]
-#
-# You can specify both a link target and a local label
-# that can be used as the target for a return link.
-# These two links refer to each other:
-#
-# - <tt>{go to addressee}[rdoc-label:addressee:sender]</tt>
-# - <tt>{return to sender}[rdoc-label:sender:addressee]</tt>
-#
-# Thus:
-#
-# {go to addressee}[rdoc-label:addressee:sender]
-#
-# Some text.
-#
-# {return to sender}[rdoc-label:sender:addressee]
-#
-# [<tt>link:</tt> Scheme]
-#
-# - <tt>link:README_rdoc.html</tt> links to link:README_rdoc.html.
-#
-# [<tt>rdoc-image</tt> Scheme]
-#
-# Use the <tt>rdoc-image</tt> scheme to display an image that is also a link:
-#
-# # {rdoc-image:path/to/image}[link_target]
-#
-# - Link: <tt>{rdoc-image:https://www.ruby-lang.org/images/header-ruby-logo@2x.png}[https://www.ruby-lang.org]</tt>
-# displays image <tt>https://www.ruby-lang.org/images/header-ruby-logo@2x.png</tt>
-# as a link to <tt>https://www.ruby-lang.org</tt>.
-#
-# {rdoc-image:https://www.ruby-lang.org/images/header-ruby-logo@2x.png}[https://www.ruby-lang.org]
-#
-# A relative path as the target also works:
-#
-# - Link: <tt>{rdoc-image:https://www.ruby-lang.org/images/header-ruby-logo@2x.png}[./Alias.html]</tt> links to <tt>./Alias.html</tt>
-#
-# {rdoc-image:https://www.ruby-lang.org/images/header-ruby-logo@2x.png}[./Alias.html]
-#
-# === Escaping Text
-#
-# Text that would otherwise be interpreted as markup
-# can be "escaped," so that it is not interpreted as markup;
-# the escape character is the backslash (<tt>'\\'</tt>).
-#
-# In a verbatim text block or a code block,
-# the escape character is always preserved:
-#
-# Example input:
-#
-# This is not verbatim text.
-#
-# This is verbatim text, with an escape character \.
-#
-# This is not a code block.
-#
-# def foo
-# 'String with an escape character.'
-# end
-#
-# Rendered HTML:
-#
-# >>>
-# This is not verbatim text.
-#
-# This is verbatim text, with an escape character \.
-#
-# This is not a code block.
-#
-# def foo
-# 'This is a code block with an escape character \.'
-# end
-#
-# In typeface markup (italic, bold, or monofont),
-# an escape character is preserved unless it is immediately
-# followed by nested typeface markup.
-#
-# Example input:
-#
-# This list is about escapes; it contains:
-#
-# - <tt>Monofont text with unescaped nested _italic_</tt>.
-# - <tt>Monofont text with escaped nested \_italic_</tt>.
-# - <tt>Monofont text with an escape character \</tt>.
-#
-# Rendered HTML:
-#
-# >>>
-# This list is about escapes; it contains:
-#
-# - <tt>Monofont text with unescaped nested _italic_</tt>.
-# - <tt>Monofont text with escaped nested \_italic_</tt>.
-# - <tt>Monofont text with an escape character \ </tt>.
-#
-# In other text-bearing blocks
-# (paragraphs, block quotes, list items, headings):
-#
-# - A single escape character immediately followed by markup
-# escapes the markup.
-# - A single escape character followed by whitespace is preserved.
-# - A single escape character anywhere else is ignored.
-# - A double escape character is rendered as a single backslash.
-#
-# Example input:
-#
-# This list is about escapes; it contains:
-#
-# - An unescaped class name, RDoc, that will become a link.
-# - An escaped class name, \RDoc, that will not become a link.
-# - An escape character followed by whitespace \ .
-# - An escape character \that is ignored.
-# - A double escape character \\ that is rendered
-# as a single backslash.
-#
-# Rendered HTML:
-#
-# >>>
-# This list is about escapes; it contains:
-#
-# - An unescaped class name, RDoc, that will become a link.
-# - An escaped class name, \RDoc, that will not become a link.
-# - An escape character followed by whitespace \ .
-# - An escape character \that is ignored.
-# - A double escape character \\ that is rendered
-# as a single backslash.
-#
-# == Documentation Derived from Ruby Code
-#
-# [Class]
-#
-# By default, \RDoc documents:
-#
-# - \Class name.
-# - Parent class.
-# - Singleton methods.
-# - Instance methods.
-# - Aliases.
-# - Constants.
-# - Attributes.
-#
-# [Module]
-#
-# By default, \RDoc documents:
-#
-# - \Module name.
-# - \Singleton methods.
-# - Instance methods.
-# - Aliases.
-# - Constants.
-# - Attributes.
-#
-# [Method]
-#
-# By default, \RDoc documents:
-#
-# - \Method name.
-# - Arguments.
-# - Yielded values.
-#
-# See #method.
-#
-# [Alias]
-#
-# By default, \RDoc documents:
-#
-# - Alias name.
-# - Aliased name.
-#
-# See #dummy_instance_alias and #dummy_instance_method.
-#
-# [Constant]
-#
-# By default, \RDoc documents:
-#
-# - \Constant name.
-#
-# See DUMMY_CONSTANT.
-#
-# [Attribute]
-#
-# By default, \RDoc documents:
-#
-# - Attribute name.
-# - Attribute type (<tt>[R]</tt>, <tt>[W]</tt>, or <tt>[RW]</tt>)
-#
-# See #dummy_attribute.
-#
-class RDoc::MarkupReference
-
- # Example class.
- class DummyClass; end
-
- # Example module.
- module DummyModule; end
-
- # Example singleton method.
- def self.dummy_singleton_method(foo, bar); end
-
- # Example instance method.
- def dummy_instance_method(foo, bar); end;
-
- alias dummy_instance_alias dummy_instance_method
-
- # Example attribute.
- attr_accessor :dummy_attribute
-
- alias dummy_attribute_alias dummy_attribute
-
- # Example constant.
- DUMMY_CONSTANT = ''
-
- # :call-seq:
- # call_seq_directive(foo, bar)
- # Can be anything -> bar
- # Also anything more -> baz or bat
- #
- # The <tt>:call-seq:</tt> directive overrides the actual calling sequence
- # found in the Ruby code.
- #
- # - It can specify anything at all.
- # - It can have multiple calling sequences.
- #
- # This one includes <tt>Can be anything -> foo</tt>, which is nonsense.
- #
- # Note that the "arrow" is two characters, hyphen and right angle-bracket,
- # which is made into a single character in the HTML.
- #
- # Click on the calling sequence to see the code.
- #
- # Here is the <tt>:call-seq:</tt> directive given for the method:
- #
- # :call-seq:
- # call_seq_directive(foo, bar)
- # Can be anything -> bar
- # Also anything more -> baz or bat
- #
- def call_seq_directive
- nil
- end
-
- # The <tt>:args:</tt> directive overrides the actual arguments found in the Ruby code.
- #
- # Click on the calling sequence to see the code.
- #
- def args_directive(foo, bar) # :args: baz
- nil
- end
-
- # The <tt>:yields:</tt> directive overrides the actual yield found in the Ruby code.
- #
- # Click on the calling sequence to see the code.
- #
- def yields_directive(foo, bar) # :yields: 'bat'
- yield 'baz'
- end
-
- # This method is documented only by \RDoc, except for these comments.
- #
- # Click on the calling sequence to see the code.
- #
- def method(foo, bar)
- yield 'baz'
- end
-
-end
diff --git a/doc/regexp/unicode_properties.rdoc b/doc/regexp/unicode_properties.rdoc
deleted file mode 100644
index a1d7ecc380..0000000000
--- a/doc/regexp/unicode_properties.rdoc
+++ /dev/null
@@ -1,678 +0,0 @@
-== \Regexps Based on Unicode Properties
-
-The properties shown here are those currently supported in Ruby.
-Older versions may not support all of these.
-
-=== POSIX brackets
-
-- <tt>\p{ASCII}</tt>
-- <tt>\p{Alnum}</tt>
-- <tt>\p{Alphabetic}</tt>, <tt>\p{Alpha}</tt>
-- <tt>\p{Blank}</tt>
-- <tt>\p{Cntrl}</tt>
-- <tt>\p{Digit}</tt>
-- <tt>\p{Graph}</tt>
-- <tt>\p{Lowercase}</tt>, <tt>\p{Lower}</tt>
-- <tt>\p{Print}</tt>
-- <tt>\p{Punct}</tt>
-- <tt>\p{Space}</tt>
-- <tt>\p{Uppercase}</tt>, <tt>\p{Upper}</tt>
-- <tt>\p{Word}</tt>
-- <tt>\p{XDigit}</tt>
-- <tt>\p{XPosixPunct}</tt>
-
-=== Special
-
-- <tt>\p{Any}</tt>
-- <tt>\p{Assigned}</tt>
-
-=== Major and General Categories
-
-- <tt>\p{Cased_Letter}</tt>, <tt>\p{LC}</tt>
-- <tt>\p{Close_Punctuation}</tt>, <tt>\p{Pe}</tt>
-- <tt>\p{Connector_Punctuation}</tt>, <tt>\p{Pc}</tt>
-- <tt>\p{Control}</tt>, <tt>\p{Cc}</tt>
-- <tt>\p{Currency_Symbol}</tt>, <tt>\p{Sc}</tt>
-- <tt>\p{Dash_Punctuation}</tt>, <tt>\p{Pd}</tt>
-- <tt>\p{Decimal_Number}</tt>, <tt>\p{Nd}</tt>
-- <tt>\p{Enclosing_Mark}</tt>, <tt>\p{Me}</tt>
-- <tt>\p{Final_Punctuation}</tt>, <tt>\p{Pf}</tt>
-- <tt>\p{Format}</tt>, <tt>\p{Cf}</tt>
-- <tt>\p{Initial_Punctuation}</tt>, <tt>\p{Pi}</tt>
-- <tt>\p{Letter}</tt>, <tt>\p{L}</tt>
-- <tt>\p{Letter_Number}</tt>, <tt>\p{Nl}</tt>
-- <tt>\p{Line_Separator}</tt>, <tt>\p{Zl}</tt>
-- <tt>\p{Lowercase_Letter}</tt>, <tt>\p{Ll}</tt>
-- <tt>\p{Mark}</tt>, <tt>\p{M}</tt>
-- <tt>\p{Math_Symbol}</tt>, <tt>\p{Sm}</tt>
-- <tt>\p{Modifier_Letter}</tt>, <tt>\p{Lm}</tt>
-- <tt>\p{Modifier_Symbol}</tt>, <tt>\p{Sk}</tt>
-- <tt>\p{Nonspacing_Mark}</tt>, <tt>\p{Mn}</tt>
-- <tt>\p{Number}</tt>, <tt>\p{N}</tt>
-- <tt>\p{Open_Punctuation}</tt>, <tt>\p{Ps}</tt>
-- <tt>\p{Other}</tt>, <tt>\p{C}</tt>
-- <tt>\p{Other_Letter}</tt>, <tt>\p{Lo}</tt>
-- <tt>\p{Other_Number}</tt>, <tt>\p{No}</tt>
-- <tt>\p{Other_Punctuation}</tt>, <tt>\p{Po}</tt>
-- <tt>\p{Other_Symbol}</tt>, <tt>\p{So}</tt>
-- <tt>\p{Paragraph_Separator}</tt>, <tt>\p{Zp}</tt>
-- <tt>\p{Private_Use}</tt>, <tt>\p{Co}</tt>
-- <tt>\p{Punctuation}</tt>, <tt>\p{P}</tt>
-- <tt>\p{Separator}</tt>, <tt>\p{Z}</tt>
-- <tt>\p{Space_Separator}</tt>, <tt>\p{Zs}</tt>
-- <tt>\p{Spacing_Mark}</tt>, <tt>\p{Mc}</tt>
-- <tt>\p{Surrogate}</tt>, <tt>\p{Cs}</tt>
-- <tt>\p{Symbol}</tt>, <tt>\p{S}</tt>
-- <tt>\p{Titlecase_Letter}</tt>, <tt>\p{Lt}</tt>
-- <tt>\p{Unassigned}</tt>, <tt>\p{Cn}</tt>
-- <tt>\p{Uppercase_Letter}</tt>, <tt>\p{Lu}</tt>
-
-=== Prop List
-
-- <tt>\p{ASCII_Hex_Digit}</tt>, <tt>\p{AHex}</tt>
-- <tt>\p{Bidi_Control}</tt>, <tt>\p{Bidi_C}</tt>
-- <tt>\p{Dash}</tt>
-- <tt>\p{Deprecated}</tt>, <tt>\p{Dep}</tt>
-- <tt>\p{Diacritic}</tt>, <tt>\p{Dia}</tt>
-- <tt>\p{Extender}</tt>, <tt>\p{Ext}</tt>
-- <tt>\p{Hex_Digit}</tt>, <tt>\p{Hex}</tt>
-- <tt>\p{Hyphen}</tt>
-- <tt>\p{IDS_Binary_Operator}</tt>, <tt>\p{IDSB}</tt>
-- <tt>\p{IDS_Trinary_Operator}</tt>, <tt>\p{IDST}</tt>
-- <tt>\p{Ideographic}</tt>, <tt>\p{Ideo}</tt>
-- <tt>\p{Join_Control}</tt>, <tt>\p{Join_C}</tt>
-- <tt>\p{Logical_Order_Exception}</tt>, <tt>\p{LOE}</tt>
-- <tt>\p{Noncharacter_Code_Point}</tt>, <tt>\p{NChar}</tt>
-- <tt>\p{Other_Alphabetic}</tt>, <tt>\p{OAlpha}</tt>
-- <tt>\p{Other_Default_Ignorable_Code_Point}</tt>, <tt>\p{ODI}</tt>
-- <tt>\p{Other_Grapheme_Extend}</tt>, <tt>\p{OGr_Ext}</tt>
-- <tt>\p{Other_ID_Continue}</tt>, <tt>\p{OIDC}</tt>
-- <tt>\p{Other_ID_Start}</tt>, <tt>\p{OIDS}</tt>
-- <tt>\p{Other_Lowercase}</tt>, <tt>\p{OLower}</tt>
-- <tt>\p{Other_Math}</tt>, <tt>\p{OMath}</tt>
-- <tt>\p{Other_Uppercase}</tt>, <tt>\p{OUpper}</tt>
-- <tt>\p{Pattern_Syntax}</tt>, <tt>\p{Pat_Syn}</tt>
-- <tt>\p{Pattern_White_Space}</tt>, <tt>\p{Pat_WS}</tt>
-- <tt>\p{Prepended_Concatenation_Mark}</tt>, <tt>\p{PCM}</tt>
-- <tt>\p{Quotation_Mark}</tt>, <tt>\p{QMark}</tt>
-- <tt>\p{Radical}</tt>
-- <tt>\p{Regional_Indicator}</tt>, <tt>\p{RI}</tt>
-- <tt>\p{Sentence_Terminal}</tt>, <tt>\p{STerm}</tt>
-- <tt>\p{Soft_Dotted}</tt>, <tt>\p{SD}</tt>
-- <tt>\p{Terminal_Punctuation}</tt>, <tt>\p{Term}</tt>
-- <tt>\p{Unified_Ideograph}</tt>, <tt>\p{UIdeo}</tt>
-- <tt>\p{Variation_Selector}</tt>, <tt>\p{VS}</tt>
-- <tt>\p{White_Space}</tt>, <tt>\p{WSpace}</tt>
-
-=== Derived Core Properties
-
-- <tt>\p{Alphabetic}</tt>, <tt>\p{Alpha}</tt>
-- <tt>\p{Case_Ignorable}</tt>, <tt>\p{CI}</tt>
-- <tt>\p{Cased}</tt>
-- <tt>\p{Changes_When_Casefolded}</tt>, <tt>\p{CWCF}</tt>
-- <tt>\p{Changes_When_Casemapped}</tt>, <tt>\p{CWCM}</tt>
-- <tt>\p{Changes_When_Lowercased}</tt>, <tt>\p{CWL}</tt>
-- <tt>\p{Changes_When_Titlecased}</tt>, <tt>\p{CWT}</tt>
-- <tt>\p{Changes_When_Uppercased}</tt>, <tt>\p{CWU}</tt>
-- <tt>\p{Default_Ignorable_Code_Point}</tt>, <tt>\p{DI}</tt>
-- <tt>\p{Grapheme_Base}</tt>, <tt>\p{Gr_Base}</tt>
-- <tt>\p{Grapheme_Extend}</tt>, <tt>\p{Gr_Ext}</tt>
-- <tt>\p{Grapheme_Link}</tt>, <tt>\p{Gr_Link}</tt>
-- <tt>\p{ID_Continue}</tt>, <tt>\p{IDC}</tt>
-- <tt>\p{ID_Start}</tt>, <tt>\p{IDS}</tt>
-- <tt>\p{Lowercase}</tt>, <tt>\p{Lower}</tt>
-- <tt>\p{Math}</tt>
-- <tt>\p{Uppercase}</tt>, <tt>\p{Upper}</tt>
-- <tt>\p{XID_Continue}</tt>, <tt>\p{XIDC}</tt>
-- <tt>\p{XID_Start}</tt>, <tt>\p{XIDS}</tt>
-
-=== Scripts
-
-- <tt>\p{Adlam}</tt>, <tt>\p{Adlm}</tt>
-- <tt>\p{Ahom}</tt>
-- <tt>\p{Anatolian_Hieroglyphs}</tt>, <tt>\p{Hluw}</tt>
-- <tt>\p{Arabic}</tt>, <tt>\p{Arab}</tt>
-- <tt>\p{Armenian}</tt>, <tt>\p{Armn}</tt>
-- <tt>\p{Avestan}</tt>, <tt>\p{Avst}</tt>
-- <tt>\p{Balinese}</tt>, <tt>\p{Bali}</tt>
-- <tt>\p{Bamum}</tt>, <tt>\p{Bamu}</tt>
-- <tt>\p{Bassa_Vah}</tt>, <tt>\p{Bass}</tt>
-- <tt>\p{Batak}</tt>, <tt>\p{Batk}</tt>
-- <tt>\p{Bengali}</tt>, <tt>\p{Beng}</tt>
-- <tt>\p{Bhaiksuki}</tt>, <tt>\p{Bhks}</tt>
-- <tt>\p{Bopomofo}</tt>, <tt>\p{Bopo}</tt>
-- <tt>\p{Brahmi}</tt>, <tt>\p{Brah}</tt>
-- <tt>\p{Braille}</tt>, <tt>\p{Brai}</tt>
-- <tt>\p{Buginese}</tt>, <tt>\p{Bugi}</tt>
-- <tt>\p{Buhid}</tt>, <tt>\p{Buhd}</tt>
-- <tt>\p{Canadian_Aboriginal}</tt>, <tt>\p{Cans}</tt>
-- <tt>\p{Carian}</tt>, <tt>\p{Cari}</tt>
-- <tt>\p{Caucasian_Albanian}</tt>, <tt>\p{Aghb}</tt>
-- <tt>\p{Chakma}</tt>, <tt>\p{Cakm}</tt>
-- <tt>\p{Cham}</tt>
-- <tt>\p{Cherokee}</tt>, <tt>\p{Cher}</tt>
-- <tt>\p{Chorasmian}</tt>, <tt>\p{Chrs}</tt>
-- <tt>\p{Common}</tt>, <tt>\p{Zyyy}</tt>
-- <tt>\p{Coptic}</tt>, <tt>\p{Copt}</tt>
-- <tt>\p{Cuneiform}</tt>, <tt>\p{Xsux}</tt>
-- <tt>\p{Cypriot}</tt>, <tt>\p{Cprt}</tt>
-- <tt>\p{Cypro_Minoan}</tt>, <tt>\p{Cpmn}</tt>
-- <tt>\p{Cyrillic}</tt>, <tt>\p{Cyrl}</tt>
-- <tt>\p{Deseret}</tt>, <tt>\p{Dsrt}</tt>
-- <tt>\p{Devanagari}</tt>, <tt>\p{Deva}</tt>
-- <tt>\p{Dives_Akuru}</tt>, <tt>\p{Diak}</tt>
-- <tt>\p{Dogra}</tt>, <tt>\p{Dogr}</tt>
-- <tt>\p{Duployan}</tt>, <tt>\p{Dupl}</tt>
-- <tt>\p{Egyptian_Hieroglyphs}</tt>, <tt>\p{Egyp}</tt>
-- <tt>\p{Elbasan}</tt>, <tt>\p{Elba}</tt>
-- <tt>\p{Elymaic}</tt>, <tt>\p{Elym}</tt>
-- <tt>\p{Ethiopic}</tt>, <tt>\p{Ethi}</tt>
-- <tt>\p{Georgian}</tt>, <tt>\p{Geor}</tt>
-- <tt>\p{Glagolitic}</tt>, <tt>\p{Glag}</tt>
-- <tt>\p{Gothic}</tt>, <tt>\p{Goth}</tt>
-- <tt>\p{Grantha}</tt>, <tt>\p{Gran}</tt>
-- <tt>\p{Greek}</tt>, <tt>\p{Grek}</tt>
-- <tt>\p{Gujarati}</tt>, <tt>\p{Gujr}</tt>
-- <tt>\p{Gunjala_Gondi}</tt>, <tt>\p{Gong}</tt>
-- <tt>\p{Gurmukhi}</tt>, <tt>\p{Guru}</tt>
-- <tt>\p{Han}</tt>, <tt>\p{Hani}</tt>
-- <tt>\p{Hangul}</tt>, <tt>\p{Hang}</tt>
-- <tt>\p{Hanifi_Rohingya}</tt>, <tt>\p{Rohg}</tt>
-- <tt>\p{Hanunoo}</tt>, <tt>\p{Hano}</tt>
-- <tt>\p{Hatran}</tt>, <tt>\p{Hatr}</tt>
-- <tt>\p{Hebrew}</tt>, <tt>\p{Hebr}</tt>
-- <tt>\p{Hiragana}</tt>, <tt>\p{Hira}</tt>
-- <tt>\p{Imperial_Aramaic}</tt>, <tt>\p{Armi}</tt>
-- <tt>\p{Inherited}</tt>, <tt>\p{Zinh}</tt>
-- <tt>\p{Inscriptional_Pahlavi}</tt>, <tt>\p{Phli}</tt>
-- <tt>\p{Inscriptional_Parthian}</tt>, <tt>\p{Prti}</tt>
-- <tt>\p{Javanese}</tt>, <tt>\p{Java}</tt>
-- <tt>\p{Kaithi}</tt>, <tt>\p{Kthi}</tt>
-- <tt>\p{Kannada}</tt>, <tt>\p{Knda}</tt>
-- <tt>\p{Katakana}</tt>, <tt>\p{Kana}</tt>
-- <tt>\p{Kawi}</tt>
-- <tt>\p{Kayah_Li}</tt>, <tt>\p{Kali}</tt>
-- <tt>\p{Kharoshthi}</tt>, <tt>\p{Khar}</tt>
-- <tt>\p{Khitan_Small_Script}</tt>, <tt>\p{Kits}</tt>
-- <tt>\p{Khmer}</tt>, <tt>\p{Khmr}</tt>
-- <tt>\p{Khojki}</tt>, <tt>\p{Khoj}</tt>
-- <tt>\p{Khudawadi}</tt>, <tt>\p{Sind}</tt>
-- <tt>\p{Lao}</tt>, <tt>\p{Laoo}</tt>
-- <tt>\p{Latin}</tt>, <tt>\p{Latn}</tt>
-- <tt>\p{Lepcha}</tt>, <tt>\p{Lepc}</tt>
-- <tt>\p{Limbu}</tt>, <tt>\p{Limb}</tt>
-- <tt>\p{Linear_A}</tt>, <tt>\p{Lina}</tt>
-- <tt>\p{Linear_B}</tt>, <tt>\p{Linb}</tt>
-- <tt>\p{Lisu}</tt>
-- <tt>\p{Lycian}</tt>, <tt>\p{Lyci}</tt>
-- <tt>\p{Lydian}</tt>, <tt>\p{Lydi}</tt>
-- <tt>\p{Mahajani}</tt>, <tt>\p{Mahj}</tt>
-- <tt>\p{Makasar}</tt>, <tt>\p{Maka}</tt>
-- <tt>\p{Malayalam}</tt>, <tt>\p{Mlym}</tt>
-- <tt>\p{Mandaic}</tt>, <tt>\p{Mand}</tt>
-- <tt>\p{Manichaean}</tt>, <tt>\p{Mani}</tt>
-- <tt>\p{Marchen}</tt>, <tt>\p{Marc}</tt>
-- <tt>\p{Masaram_Gondi}</tt>, <tt>\p{Gonm}</tt>
-- <tt>\p{Medefaidrin}</tt>, <tt>\p{Medf}</tt>
-- <tt>\p{Meetei_Mayek}</tt>, <tt>\p{Mtei}</tt>
-- <tt>\p{Mende_Kikakui}</tt>, <tt>\p{Mend}</tt>
-- <tt>\p{Meroitic_Cursive}</tt>, <tt>\p{Merc}</tt>
-- <tt>\p{Meroitic_Hieroglyphs}</tt>, <tt>\p{Mero}</tt>
-- <tt>\p{Miao}</tt>, <tt>\p{Plrd}</tt>
-- <tt>\p{Modi}</tt>
-- <tt>\p{Mongolian}</tt>, <tt>\p{Mong}</tt>
-- <tt>\p{Mro}</tt>, <tt>\p{Mroo}</tt>
-- <tt>\p{Multani}</tt>, <tt>\p{Mult}</tt>
-- <tt>\p{Myanmar}</tt>, <tt>\p{Mymr}</tt>
-- <tt>\p{Nabataean}</tt>, <tt>\p{Nbat}</tt>
-- <tt>\p{Nag_Mundari}</tt>, <tt>\p{Nagm}</tt>
-- <tt>\p{Nandinagari}</tt>, <tt>\p{Nand}</tt>
-- <tt>\p{New_Tai_Lue}</tt>, <tt>\p{Talu}</tt>
-- <tt>\p{Newa}</tt>
-- <tt>\p{Nko}</tt>, <tt>\p{Nkoo}</tt>
-- <tt>\p{Nushu}</tt>, <tt>\p{Nshu}</tt>
-- <tt>\p{Nyiakeng_Puachue_Hmong}</tt>, <tt>\p{Hmnp}</tt>
-- <tt>\p{Ogham}</tt>, <tt>\p{Ogam}</tt>
-- <tt>\p{Ol_Chiki}</tt>, <tt>\p{Olck}</tt>
-- <tt>\p{Old_Hungarian}</tt>, <tt>\p{Hung}</tt>
-- <tt>\p{Old_Italic}</tt>, <tt>\p{Ital}</tt>
-- <tt>\p{Old_North_Arabian}</tt>, <tt>\p{Narb}</tt>
-- <tt>\p{Old_Permic}</tt>, <tt>\p{Perm}</tt>
-- <tt>\p{Old_Persian}</tt>, <tt>\p{Xpeo}</tt>
-- <tt>\p{Old_Sogdian}</tt>, <tt>\p{Sogo}</tt>
-- <tt>\p{Old_South_Arabian}</tt>, <tt>\p{Sarb}</tt>
-- <tt>\p{Old_Turkic}</tt>, <tt>\p{Orkh}</tt>
-- <tt>\p{Old_Uyghur}</tt>, <tt>\p{Ougr}</tt>
-- <tt>\p{Oriya}</tt>, <tt>\p{Orya}</tt>
-- <tt>\p{Osage}</tt>, <tt>\p{Osge}</tt>
-- <tt>\p{Osmanya}</tt>, <tt>\p{Osma}</tt>
-- <tt>\p{Pahawh_Hmong}</tt>, <tt>\p{Hmng}</tt>
-- <tt>\p{Palmyrene}</tt>, <tt>\p{Palm}</tt>
-- <tt>\p{Pau_Cin_Hau}</tt>, <tt>\p{Pauc}</tt>
-- <tt>\p{Phags_Pa}</tt>, <tt>\p{Phag}</tt>
-- <tt>\p{Phoenician}</tt>, <tt>\p{Phnx}</tt>
-- <tt>\p{Psalter_Pahlavi}</tt>, <tt>\p{Phlp}</tt>
-- <tt>\p{Rejang}</tt>, <tt>\p{Rjng}</tt>
-- <tt>\p{Runic}</tt>, <tt>\p{Runr}</tt>
-- <tt>\p{Samaritan}</tt>, <tt>\p{Samr}</tt>
-- <tt>\p{Saurashtra}</tt>, <tt>\p{Saur}</tt>
-- <tt>\p{Sharada}</tt>, <tt>\p{Shrd}</tt>
-- <tt>\p{Shavian}</tt>, <tt>\p{Shaw}</tt>
-- <tt>\p{Siddham}</tt>, <tt>\p{Sidd}</tt>
-- <tt>\p{SignWriting}</tt>, <tt>\p{Sgnw}</tt>
-- <tt>\p{Sinhala}</tt>, <tt>\p{Sinh}</tt>
-- <tt>\p{Sogdian}</tt>, <tt>\p{Sogd}</tt>
-- <tt>\p{Sora_Sompeng}</tt>, <tt>\p{Sora}</tt>
-- <tt>\p{Soyombo}</tt>, <tt>\p{Soyo}</tt>
-- <tt>\p{Sundanese}</tt>, <tt>\p{Sund}</tt>
-- <tt>\p{Syloti_Nagri}</tt>, <tt>\p{Sylo}</tt>
-- <tt>\p{Syriac}</tt>, <tt>\p{Syrc}</tt>
-- <tt>\p{Tagalog}</tt>, <tt>\p{Tglg}</tt>
-- <tt>\p{Tagbanwa}</tt>, <tt>\p{Tagb}</tt>
-- <tt>\p{Tai_Le}</tt>, <tt>\p{Tale}</tt>
-- <tt>\p{Tai_Tham}</tt>, <tt>\p{Lana}</tt>
-- <tt>\p{Tai_Viet}</tt>, <tt>\p{Tavt}</tt>
-- <tt>\p{Takri}</tt>, <tt>\p{Takr}</tt>
-- <tt>\p{Tamil}</tt>, <tt>\p{Taml}</tt>
-- <tt>\p{Tangsa}</tt>, <tt>\p{Tnsa}</tt>
-- <tt>\p{Tangut}</tt>, <tt>\p{Tang}</tt>
-- <tt>\p{Telugu}</tt>, <tt>\p{Telu}</tt>
-- <tt>\p{Thaana}</tt>, <tt>\p{Thaa}</tt>
-- <tt>\p{Thai}</tt>
-- <tt>\p{Tibetan}</tt>, <tt>\p{Tibt}</tt>
-- <tt>\p{Tifinagh}</tt>, <tt>\p{Tfng}</tt>
-- <tt>\p{Tirhuta}</tt>, <tt>\p{Tirh}</tt>
-- <tt>\p{Toto}</tt>
-- <tt>\p{Ugaritic}</tt>, <tt>\p{Ugar}</tt>
-- <tt>\p{Unknown}</tt>, <tt>\p{Zzzz}</tt>
-- <tt>\p{Vai}</tt>, <tt>\p{Vaii}</tt>
-- <tt>\p{Vithkuqi}</tt>, <tt>\p{Vith}</tt>
-- <tt>\p{Wancho}</tt>, <tt>\p{Wcho}</tt>
-- <tt>\p{Warang_Citi}</tt>, <tt>\p{Wara}</tt>
-- <tt>\p{Yezidi}</tt>, <tt>\p{Yezi}</tt>
-- <tt>\p{Yi}</tt>, <tt>\p{Yiii}</tt>
-- <tt>\p{Zanabazar_Square}</tt>, <tt>\p{Zanb}</tt>
-
-=== Blocks
-
-- <tt>\p{In_Adlam}</tt>
-- <tt>\p{In_Aegean_Numbers}</tt>
-- <tt>\p{In_Ahom}</tt>
-- <tt>\p{In_Alchemical_Symbols}</tt>
-- <tt>\p{In_Alphabetic_Presentation_Forms}</tt>
-- <tt>\p{In_Anatolian_Hieroglyphs}</tt>
-- <tt>\p{In_Ancient_Greek_Musical_Notation}</tt>
-- <tt>\p{In_Ancient_Greek_Numbers}</tt>
-- <tt>\p{In_Ancient_Symbols}</tt>
-- <tt>\p{In_Arabic}</tt>
-- <tt>\p{In_Arabic_Extended_A}</tt>
-- <tt>\p{In_Arabic_Extended_B}</tt>
-- <tt>\p{In_Arabic_Extended_C}</tt>
-- <tt>\p{In_Arabic_Mathematical_Alphabetic_Symbols}</tt>
-- <tt>\p{In_Arabic_Presentation_Forms_A}</tt>
-- <tt>\p{In_Arabic_Presentation_Forms_B}</tt>
-- <tt>\p{In_Arabic_Supplement}</tt>
-- <tt>\p{In_Armenian}</tt>
-- <tt>\p{In_Arrows}</tt>
-- <tt>\p{In_Avestan}</tt>
-- <tt>\p{In_Balinese}</tt>
-- <tt>\p{In_Bamum}</tt>
-- <tt>\p{In_Bamum_Supplement}</tt>
-- <tt>\p{In_Basic_Latin}</tt>
-- <tt>\p{In_Bassa_Vah}</tt>
-- <tt>\p{In_Batak}</tt>
-- <tt>\p{In_Bengali}</tt>
-- <tt>\p{In_Bhaiksuki}</tt>
-- <tt>\p{In_Block_Elements}</tt>
-- <tt>\p{In_Bopomofo}</tt>
-- <tt>\p{In_Bopomofo_Extended}</tt>
-- <tt>\p{In_Box_Drawing}</tt>
-- <tt>\p{In_Brahmi}</tt>
-- <tt>\p{In_Braille_Patterns}</tt>
-- <tt>\p{In_Buginese}</tt>
-- <tt>\p{In_Buhid}</tt>
-- <tt>\p{In_Byzantine_Musical_Symbols}</tt>
-- <tt>\p{In_CJK_Compatibility}</tt>
-- <tt>\p{In_CJK_Compatibility_Forms}</tt>
-- <tt>\p{In_CJK_Compatibility_Ideographs}</tt>
-- <tt>\p{In_CJK_Compatibility_Ideographs_Supplement}</tt>
-- <tt>\p{In_CJK_Radicals_Supplement}</tt>
-- <tt>\p{In_CJK_Strokes}</tt>
-- <tt>\p{In_CJK_Symbols_and_Punctuation}</tt>
-- <tt>\p{In_CJK_Unified_Ideographs}</tt>
-- <tt>\p{In_CJK_Unified_Ideographs_Extension_A}</tt>
-- <tt>\p{In_CJK_Unified_Ideographs_Extension_B}</tt>
-- <tt>\p{In_CJK_Unified_Ideographs_Extension_C}</tt>
-- <tt>\p{In_CJK_Unified_Ideographs_Extension_D}</tt>
-- <tt>\p{In_CJK_Unified_Ideographs_Extension_E}</tt>
-- <tt>\p{In_CJK_Unified_Ideographs_Extension_F}</tt>
-- <tt>\p{In_CJK_Unified_Ideographs_Extension_G}</tt>
-- <tt>\p{In_CJK_Unified_Ideographs_Extension_H}</tt>
-- <tt>\p{In_Carian}</tt>
-- <tt>\p{In_Caucasian_Albanian}</tt>
-- <tt>\p{In_Chakma}</tt>
-- <tt>\p{In_Cham}</tt>
-- <tt>\p{In_Cherokee}</tt>
-- <tt>\p{In_Cherokee_Supplement}</tt>
-- <tt>\p{In_Chess_Symbols}</tt>
-- <tt>\p{In_Chorasmian}</tt>
-- <tt>\p{In_Combining_Diacritical_Marks}</tt>
-- <tt>\p{In_Combining_Diacritical_Marks_Extended}</tt>
-- <tt>\p{In_Combining_Diacritical_Marks_Supplement}</tt>
-- <tt>\p{In_Combining_Diacritical_Marks_for_Symbols}</tt>
-- <tt>\p{In_Combining_Half_Marks}</tt>
-- <tt>\p{In_Common_Indic_Number_Forms}</tt>
-- <tt>\p{In_Control_Pictures}</tt>
-- <tt>\p{In_Coptic}</tt>
-- <tt>\p{In_Coptic_Epact_Numbers}</tt>
-- <tt>\p{In_Counting_Rod_Numerals}</tt>
-- <tt>\p{In_Cuneiform}</tt>
-- <tt>\p{In_Cuneiform_Numbers_and_Punctuation}</tt>
-- <tt>\p{In_Currency_Symbols}</tt>
-- <tt>\p{In_Cypriot_Syllabary}</tt>
-- <tt>\p{In_Cypro_Minoan}</tt>
-- <tt>\p{In_Cyrillic}</tt>
-- <tt>\p{In_Cyrillic_Extended_A}</tt>
-- <tt>\p{In_Cyrillic_Extended_B}</tt>
-- <tt>\p{In_Cyrillic_Extended_C}</tt>
-- <tt>\p{In_Cyrillic_Extended_D}</tt>
-- <tt>\p{In_Cyrillic_Supplement}</tt>
-- <tt>\p{In_Deseret}</tt>
-- <tt>\p{In_Devanagari}</tt>
-- <tt>\p{In_Devanagari_Extended}</tt>
-- <tt>\p{In_Devanagari_Extended_A}</tt>
-- <tt>\p{In_Dingbats}</tt>
-- <tt>\p{In_Dives_Akuru}</tt>
-- <tt>\p{In_Dogra}</tt>
-- <tt>\p{In_Domino_Tiles}</tt>
-- <tt>\p{In_Duployan}</tt>
-- <tt>\p{In_Early_Dynastic_Cuneiform}</tt>
-- <tt>\p{In_Egyptian_Hieroglyph_Format_Controls}</tt>
-- <tt>\p{In_Egyptian_Hieroglyphs}</tt>
-- <tt>\p{In_Elbasan}</tt>
-- <tt>\p{In_Elymaic}</tt>
-- <tt>\p{In_Emoticons}</tt>
-- <tt>\p{In_Enclosed_Alphanumeric_Supplement}</tt>
-- <tt>\p{In_Enclosed_Alphanumerics}</tt>
-- <tt>\p{In_Enclosed_CJK_Letters_and_Months}</tt>
-- <tt>\p{In_Enclosed_Ideographic_Supplement}</tt>
-- <tt>\p{In_Ethiopic}</tt>
-- <tt>\p{In_Ethiopic_Extended}</tt>
-- <tt>\p{In_Ethiopic_Extended_A}</tt>
-- <tt>\p{In_Ethiopic_Extended_B}</tt>
-- <tt>\p{In_Ethiopic_Supplement}</tt>
-- <tt>\p{In_General_Punctuation}</tt>
-- <tt>\p{In_Geometric_Shapes}</tt>
-- <tt>\p{In_Geometric_Shapes_Extended}</tt>
-- <tt>\p{In_Georgian}</tt>
-- <tt>\p{In_Georgian_Extended}</tt>
-- <tt>\p{In_Georgian_Supplement}</tt>
-- <tt>\p{In_Glagolitic}</tt>
-- <tt>\p{In_Glagolitic_Supplement}</tt>
-- <tt>\p{In_Gothic}</tt>
-- <tt>\p{In_Grantha}</tt>
-- <tt>\p{In_Greek_Extended}</tt>
-- <tt>\p{In_Greek_and_Coptic}</tt>
-- <tt>\p{In_Gujarati}</tt>
-- <tt>\p{In_Gunjala_Gondi}</tt>
-- <tt>\p{In_Gurmukhi}</tt>
-- <tt>\p{In_Halfwidth_and_Fullwidth_Forms}</tt>
-- <tt>\p{In_Hangul_Compatibility_Jamo}</tt>
-- <tt>\p{In_Hangul_Jamo}</tt>
-- <tt>\p{In_Hangul_Jamo_Extended_A}</tt>
-- <tt>\p{In_Hangul_Jamo_Extended_B}</tt>
-- <tt>\p{In_Hangul_Syllables}</tt>
-- <tt>\p{In_Hanifi_Rohingya}</tt>
-- <tt>\p{In_Hanunoo}</tt>
-- <tt>\p{In_Hatran}</tt>
-- <tt>\p{In_Hebrew}</tt>
-- <tt>\p{In_High_Private_Use_Surrogates}</tt>
-- <tt>\p{In_High_Surrogates}</tt>
-- <tt>\p{In_Hiragana}</tt>
-- <tt>\p{In_IPA_Extensions}</tt>
-- <tt>\p{In_Ideographic_Description_Characters}</tt>
-- <tt>\p{In_Ideographic_Symbols_and_Punctuation}</tt>
-- <tt>\p{In_Imperial_Aramaic}</tt>
-- <tt>\p{In_Indic_Siyaq_Numbers}</tt>
-- <tt>\p{In_Inscriptional_Pahlavi}</tt>
-- <tt>\p{In_Inscriptional_Parthian}</tt>
-- <tt>\p{In_Javanese}</tt>
-- <tt>\p{In_Kaithi}</tt>
-- <tt>\p{In_Kaktovik_Numerals}</tt>
-- <tt>\p{In_Kana_Extended_A}</tt>
-- <tt>\p{In_Kana_Extended_B}</tt>
-- <tt>\p{In_Kana_Supplement}</tt>
-- <tt>\p{In_Kanbun}</tt>
-- <tt>\p{In_Kangxi_Radicals}</tt>
-- <tt>\p{In_Kannada}</tt>
-- <tt>\p{In_Katakana}</tt>
-- <tt>\p{In_Katakana_Phonetic_Extensions}</tt>
-- <tt>\p{In_Kawi}</tt>
-- <tt>\p{In_Kayah_Li}</tt>
-- <tt>\p{In_Kharoshthi}</tt>
-- <tt>\p{In_Khitan_Small_Script}</tt>
-- <tt>\p{In_Khmer}</tt>
-- <tt>\p{In_Khmer_Symbols}</tt>
-- <tt>\p{In_Khojki}</tt>
-- <tt>\p{In_Khudawadi}</tt>
-- <tt>\p{In_Lao}</tt>
-- <tt>\p{In_Latin_1_Supplement}</tt>
-- <tt>\p{In_Latin_Extended_A}</tt>
-- <tt>\p{In_Latin_Extended_Additional}</tt>
-- <tt>\p{In_Latin_Extended_B}</tt>
-- <tt>\p{In_Latin_Extended_C}</tt>
-- <tt>\p{In_Latin_Extended_D}</tt>
-- <tt>\p{In_Latin_Extended_E}</tt>
-- <tt>\p{In_Latin_Extended_F}</tt>
-- <tt>\p{In_Latin_Extended_G}</tt>
-- <tt>\p{In_Lepcha}</tt>
-- <tt>\p{In_Letterlike_Symbols}</tt>
-- <tt>\p{In_Limbu}</tt>
-- <tt>\p{In_Linear_A}</tt>
-- <tt>\p{In_Linear_B_Ideograms}</tt>
-- <tt>\p{In_Linear_B_Syllabary}</tt>
-- <tt>\p{In_Lisu}</tt>
-- <tt>\p{In_Lisu_Supplement}</tt>
-- <tt>\p{In_Low_Surrogates}</tt>
-- <tt>\p{In_Lycian}</tt>
-- <tt>\p{In_Lydian}</tt>
-- <tt>\p{In_Mahajani}</tt>
-- <tt>\p{In_Mahjong_Tiles}</tt>
-- <tt>\p{In_Makasar}</tt>
-- <tt>\p{In_Malayalam}</tt>
-- <tt>\p{In_Mandaic}</tt>
-- <tt>\p{In_Manichaean}</tt>
-- <tt>\p{In_Marchen}</tt>
-- <tt>\p{In_Masaram_Gondi}</tt>
-- <tt>\p{In_Mathematical_Alphanumeric_Symbols}</tt>
-- <tt>\p{In_Mathematical_Operators}</tt>
-- <tt>\p{In_Mayan_Numerals}</tt>
-- <tt>\p{In_Medefaidrin}</tt>
-- <tt>\p{In_Meetei_Mayek}</tt>
-- <tt>\p{In_Meetei_Mayek_Extensions}</tt>
-- <tt>\p{In_Mende_Kikakui}</tt>
-- <tt>\p{In_Meroitic_Cursive}</tt>
-- <tt>\p{In_Meroitic_Hieroglyphs}</tt>
-- <tt>\p{In_Miao}</tt>
-- <tt>\p{In_Miscellaneous_Mathematical_Symbols_A}</tt>
-- <tt>\p{In_Miscellaneous_Mathematical_Symbols_B}</tt>
-- <tt>\p{In_Miscellaneous_Symbols}</tt>
-- <tt>\p{In_Miscellaneous_Symbols_and_Arrows}</tt>
-- <tt>\p{In_Miscellaneous_Symbols_and_Pictographs}</tt>
-- <tt>\p{In_Miscellaneous_Technical}</tt>
-- <tt>\p{In_Modi}</tt>
-- <tt>\p{In_Modifier_Tone_Letters}</tt>
-- <tt>\p{In_Mongolian}</tt>
-- <tt>\p{In_Mongolian_Supplement}</tt>
-- <tt>\p{In_Mro}</tt>
-- <tt>\p{In_Multani}</tt>
-- <tt>\p{In_Musical_Symbols}</tt>
-- <tt>\p{In_Myanmar}</tt>
-- <tt>\p{In_Myanmar_Extended_A}</tt>
-- <tt>\p{In_Myanmar_Extended_B}</tt>
-- <tt>\p{In_NKo}</tt>
-- <tt>\p{In_Nabataean}</tt>
-- <tt>\p{In_Nag_Mundari}</tt>
-- <tt>\p{In_Nandinagari}</tt>
-- <tt>\p{In_New_Tai_Lue}</tt>
-- <tt>\p{In_Newa}</tt>
-- <tt>\p{In_No_Block}</tt>
-- <tt>\p{In_Number_Forms}</tt>
-- <tt>\p{In_Nushu}</tt>
-- <tt>\p{In_Nyiakeng_Puachue_Hmong}</tt>
-- <tt>\p{In_Ogham}</tt>
-- <tt>\p{In_Ol_Chiki}</tt>
-- <tt>\p{In_Old_Hungarian}</tt>
-- <tt>\p{In_Old_Italic}</tt>
-- <tt>\p{In_Old_North_Arabian}</tt>
-- <tt>\p{In_Old_Permic}</tt>
-- <tt>\p{In_Old_Persian}</tt>
-- <tt>\p{In_Old_Sogdian}</tt>
-- <tt>\p{In_Old_South_Arabian}</tt>
-- <tt>\p{In_Old_Turkic}</tt>
-- <tt>\p{In_Old_Uyghur}</tt>
-- <tt>\p{In_Optical_Character_Recognition}</tt>
-- <tt>\p{In_Oriya}</tt>
-- <tt>\p{In_Ornamental_Dingbats}</tt>
-- <tt>\p{In_Osage}</tt>
-- <tt>\p{In_Osmanya}</tt>
-- <tt>\p{In_Ottoman_Siyaq_Numbers}</tt>
-- <tt>\p{In_Pahawh_Hmong}</tt>
-- <tt>\p{In_Palmyrene}</tt>
-- <tt>\p{In_Pau_Cin_Hau}</tt>
-- <tt>\p{In_Phags_pa}</tt>
-- <tt>\p{In_Phaistos_Disc}</tt>
-- <tt>\p{In_Phoenician}</tt>
-- <tt>\p{In_Phonetic_Extensions}</tt>
-- <tt>\p{In_Phonetic_Extensions_Supplement}</tt>
-- <tt>\p{In_Playing_Cards}</tt>
-- <tt>\p{In_Private_Use_Area}</tt>
-- <tt>\p{In_Psalter_Pahlavi}</tt>
-- <tt>\p{In_Rejang}</tt>
-- <tt>\p{In_Rumi_Numeral_Symbols}</tt>
-- <tt>\p{In_Runic}</tt>
-- <tt>\p{In_Samaritan}</tt>
-- <tt>\p{In_Saurashtra}</tt>
-- <tt>\p{In_Sharada}</tt>
-- <tt>\p{In_Shavian}</tt>
-- <tt>\p{In_Shorthand_Format_Controls}</tt>
-- <tt>\p{In_Siddham}</tt>
-- <tt>\p{In_Sinhala}</tt>
-- <tt>\p{In_Sinhala_Archaic_Numbers}</tt>
-- <tt>\p{In_Small_Form_Variants}</tt>
-- <tt>\p{In_Small_Kana_Extension}</tt>
-- <tt>\p{In_Sogdian}</tt>
-- <tt>\p{In_Sora_Sompeng}</tt>
-- <tt>\p{In_Soyombo}</tt>
-- <tt>\p{In_Spacing_Modifier_Letters}</tt>
-- <tt>\p{In_Specials}</tt>
-- <tt>\p{In_Sundanese}</tt>
-- <tt>\p{In_Sundanese_Supplement}</tt>
-- <tt>\p{In_Superscripts_and_Subscripts}</tt>
-- <tt>\p{In_Supplemental_Arrows_A}</tt>
-- <tt>\p{In_Supplemental_Arrows_B}</tt>
-- <tt>\p{In_Supplemental_Arrows_C}</tt>
-- <tt>\p{In_Supplemental_Mathematical_Operators}</tt>
-- <tt>\p{In_Supplemental_Punctuation}</tt>
-- <tt>\p{In_Supplemental_Symbols_and_Pictographs}</tt>
-- <tt>\p{In_Supplementary_Private_Use_Area_A}</tt>
-- <tt>\p{In_Supplementary_Private_Use_Area_B}</tt>
-- <tt>\p{In_Sutton_SignWriting}</tt>
-- <tt>\p{In_Syloti_Nagri}</tt>
-- <tt>\p{In_Symbols_and_Pictographs_Extended_A}</tt>
-- <tt>\p{In_Symbols_for_Legacy_Computing}</tt>
-- <tt>\p{In_Syriac}</tt>
-- <tt>\p{In_Syriac_Supplement}</tt>
-- <tt>\p{In_Tagalog}</tt>
-- <tt>\p{In_Tagbanwa}</tt>
-- <tt>\p{In_Tags}</tt>
-- <tt>\p{In_Tai_Le}</tt>
-- <tt>\p{In_Tai_Tham}</tt>
-- <tt>\p{In_Tai_Viet}</tt>
-- <tt>\p{In_Tai_Xuan_Jing_Symbols}</tt>
-- <tt>\p{In_Takri}</tt>
-- <tt>\p{In_Tamil}</tt>
-- <tt>\p{In_Tamil_Supplement}</tt>
-- <tt>\p{In_Tangsa}</tt>
-- <tt>\p{In_Tangut}</tt>
-- <tt>\p{In_Tangut_Components}</tt>
-- <tt>\p{In_Tangut_Supplement}</tt>
-- <tt>\p{In_Telugu}</tt>
-- <tt>\p{In_Thaana}</tt>
-- <tt>\p{In_Thai}</tt>
-- <tt>\p{In_Tibetan}</tt>
-- <tt>\p{In_Tifinagh}</tt>
-- <tt>\p{In_Tirhuta}</tt>
-- <tt>\p{In_Toto}</tt>
-- <tt>\p{In_Transport_and_Map_Symbols}</tt>
-- <tt>\p{In_Ugaritic}</tt>
-- <tt>\p{In_Unified_Canadian_Aboriginal_Syllabics}</tt>
-- <tt>\p{In_Unified_Canadian_Aboriginal_Syllabics_Extended}</tt>
-- <tt>\p{In_Unified_Canadian_Aboriginal_Syllabics_Extended_A}</tt>
-- <tt>\p{In_Vai}</tt>
-- <tt>\p{In_Variation_Selectors}</tt>
-- <tt>\p{In_Variation_Selectors_Supplement}</tt>
-- <tt>\p{In_Vedic_Extensions}</tt>
-- <tt>\p{In_Vertical_Forms}</tt>
-- <tt>\p{In_Vithkuqi}</tt>
-- <tt>\p{In_Wancho}</tt>
-- <tt>\p{In_Warang_Citi}</tt>
-- <tt>\p{In_Yezidi}</tt>
-- <tt>\p{In_Yi_Radicals}</tt>
-- <tt>\p{In_Yi_Syllables}</tt>
-- <tt>\p{In_Yijing_Hexagram_Symbols}</tt>
-- <tt>\p{In_Zanabazar_Square}</tt>
-- <tt>\p{In_Znamenny_Musical_Notation}</tt>
-
-=== Emoji
-
-- <tt>\p{Emoji}</tt>
-- <tt>\p{Emoji_Component}</tt>, <tt>\p{EComp}</tt>
-- <tt>\p{Emoji_Modifier}</tt>, <tt>\p{EMod}</tt>
-- <tt>\p{Emoji_Modifier_Base}</tt>, <tt>\p{EBase}</tt>
-- <tt>\p{Emoji_Presentation}</tt>, <tt>\p{EPres}</tt>
-- <tt>\p{Extended_Pictographic}</tt>, <tt>\p{ExtPict}</tt>
-
-=== Graphemes
-
-- <tt>\p{Grapheme_Cluster_Break_CR}</tt>
-- <tt>\p{Grapheme_Cluster_Break_Control}</tt>
-- <tt>\p{Grapheme_Cluster_Break_Extend}</tt>
-- <tt>\p{Grapheme_Cluster_Break_L}</tt>
-- <tt>\p{Grapheme_Cluster_Break_LF}</tt>
-- <tt>\p{Grapheme_Cluster_Break_LV}</tt>
-- <tt>\p{Grapheme_Cluster_Break_LVT}</tt>
-- <tt>\p{Grapheme_Cluster_Break_Prepend}</tt>
-- <tt>\p{Grapheme_Cluster_Break_Regional_Indicator}</tt>
-- <tt>\p{Grapheme_Cluster_Break_SpacingMark}</tt>
-- <tt>\p{Grapheme_Cluster_Break_T}</tt>
-- <tt>\p{Grapheme_Cluster_Break_V}</tt>
-- <tt>\p{Grapheme_Cluster_Break_ZWJ}</tt>
-
-=== Derived Ages
-
-- <tt>\p{Age_10_0}</tt>
-- <tt>\p{Age_11_0}</tt>
-- <tt>\p{Age_12_0}</tt>
-- <tt>\p{Age_12_1}</tt>
-- <tt>\p{Age_13_0}</tt>
-- <tt>\p{Age_14_0}</tt>
-- <tt>\p{Age_15_0}</tt>
-- <tt>\p{Age_1_1}</tt>
-- <tt>\p{Age_2_0}</tt>
-- <tt>\p{Age_2_1}</tt>
-- <tt>\p{Age_3_0}</tt>
-- <tt>\p{Age_3_1}</tt>
-- <tt>\p{Age_3_2}</tt>
-- <tt>\p{Age_4_0}</tt>
-- <tt>\p{Age_4_1}</tt>
-- <tt>\p{Age_5_0}</tt>
-- <tt>\p{Age_5_1}</tt>
-- <tt>\p{Age_5_2}</tt>
-- <tt>\p{Age_6_0}</tt>
-- <tt>\p{Age_6_1}</tt>
-- <tt>\p{Age_6_2}</tt>
-- <tt>\p{Age_6_3}</tt>
-- <tt>\p{Age_7_0}</tt>
-- <tt>\p{Age_8_0}</tt>
-- <tt>\p{Age_9_0}</tt>
diff --git a/doc/reline/face.md b/doc/reline/face.md
deleted file mode 100644
index 1fa916123b..0000000000
--- a/doc/reline/face.md
+++ /dev/null
@@ -1,111 +0,0 @@
-# Face
-
-With the `Reline::Face` class, you can modify the text color and text decorations in your terminal emulator.
-This is primarily used to customize the appearance of the method completion dialog in IRB.
-
-## Usage
-
-### ex: Change the background color of the completion dialog cyan to blue
-
-```ruby
-Reline::Face.config(:completion_dialog) do |conf|
- conf.define :default, foreground: :white, background: :blue
- # ^^^^^ `:cyan` by default
- conf.define :enhanced, foreground: :white, background: :magenta
- conf.define :scrollbar, foreground: :white, background: :blue
-end
-```
-
-If you provide the above code to an IRB session in some way, you can apply the configuration.
-It's generally done by writing it in `.irbrc`.
-
-Regarding `.irbrc`, please refer to the following link: [https://docs.ruby-lang.org/en/master/IRB.html](https://docs.ruby-lang.org/en/master/IRB.html)
-
-## Available parameters
-
-`Reline::Face` internally creates SGR (Select Graphic Rendition) code according to the block parameter of `Reline::Face.config` method.
-
-| Key | Value | SGR Code (numeric part following "\e[")|
-|:------------|:------------------|-----:|
-| :foreground | :black | 30 |
-| | :red | 31 |
-| | :green | 32 |
-| | :yellow | 33 |
-| | :blue | 34 |
-| | :magenta | 35 |
-| | :cyan | 36 |
-| | :white | 37 |
-| | :bright_black | 90 |
-| | :gray | 90 |
-| | :bright_red | 91 |
-| | :bright_green | 92 |
-| | :bright_yellow | 93 |
-| | :bright_blue | 94 |
-| | :bright_magenta | 95 |
-| | :bright_cyan | 96 |
-| | :bright_white | 97 |
-| :background | :black | 40 |
-| | :red | 41 |
-| | :green | 42 |
-| | :yellow | 43 |
-| | :blue | 44 |
-| | :magenta | 45 |
-| | :cyan | 46 |
-| | :white | 47 |
-| | :bright_black | 100 |
-| | :gray | 100 |
-| | :bright_red | 101 |
-| | :bright_green | 102 |
-| | :bright_yellow | 103 |
-| | :bright_blue | 104 |
-| | :bright_magenta | 105 |
-| | :bright_cyan | 106 |
-| | :bright_white | 107 |
-| :style | :reset | 0 |
-| | :bold | 1 |
-| | :faint | 2 |
-| | :italicized | 3 |
-| | :underlined | 4 |
-| | :slowly_blinking | 5 |
-| | :blinking | 5 |
-| | :rapidly_blinking | 6 |
-| | :negative | 7 |
-| | :concealed | 8 |
-| | :crossed_out | 9 |
-
-- The value for `:style` can be both a Symbol and an Array
- ```ruby
- # Single symbol
- conf.define :default, style: :bold
- # Array
- conf.define :default, style: [:bold, :negative]
- ```
-- The availability of specific SGR codes depends on your terminal emulator
-- You can specify a hex color code to `:foreground` and `:background` color like `foreground: "#FF1020"`. Its availability also depends on your terminal emulator
-
-## Debugging
-
-You can see the current Face configuration by `Reline::Face.configs` method
-
-Example:
-
-```ruby
-irb(main):001:0> Reline::Face.configs
-=>
-{:default=>
- {:default=>{:style=>:reset, :escape_sequence=>"\e[0m"},
- :enhanced=>{:style=>:reset, :escape_sequence=>"\e[0m"},
- :scrollbar=>{:style=>:reset, :escape_sequence=>"\e[0m"}},
- :completion_dialog=>
- {:default=>{:foreground=>:white, :background=>:cyan, :escape_sequence=>"\e[0m\e[37;46m"},
- :enhanced=>{:foreground=>:white, :background=>:magenta, :escape_sequence=>"\e[0m\e[37;45m"},
- :scrollbar=>{:foreground=>:white, :background=>:cyan, :escape_sequence=>"\e[0m\e[37;46m"}}}
-```
-
-## 256-Color and TrueColor
-
-Reline will automatically detect if your terminal emulator supports truecolor with `ENV['COLORTERM] in 'truecolor' | '24bit'`. When this env is not set, Reline will fallback to 256-color.
-If your terminal emulator supports truecolor but does not set COLORTERM env, add this line to `.irbrc`.
-```ruby
-Reline::Face.force_truecolor
-```
diff --git a/doc/rjit/rjit.md b/doc/rjit/rjit.md
deleted file mode 100644
index 9e60e43ce3..0000000000
--- a/doc/rjit/rjit.md
+++ /dev/null
@@ -1,45 +0,0 @@
-# RJIT: Ruby JIT
-
-This document has some tips that might be useful when you work on RJIT.
-
-## Project purpose
-
-This project is for experimental purposes.
-For production deployment, consider using YJIT instead.
-
-## Supported platforms
-
-The following platforms are assumed to work. `linux-x86_64` is tested on CI.
-
-* OS: Linux, macOS, BSD
-* Arch: x86\_64
-
-## configure
-### --enable-rjit
-
-On supported platforms, `--enable-rjit` is set by default. You usually don't need to specify this.
-You may still manually pass `--enable-rjit` to try RJIT on unsupported platforms.
-
-### --enable-rjit=dev
-
-It enables `--rjit-dump-disasm` if libcapstone is available.
-
-## make
-### rjit-bindgen
-
-If you see an "RJIT bindgen" GitHub Actions failure, please commit the `git diff` shown on the failed job.
-
-For doing the same thing locally, run `make rjit-bindgen` after installing libclang.
-macOS seems to have libclang by default. On Ubuntu, you can install it with `apt install libclang1`.
-
-## ruby
-### --rjit-stats
-
-This prints RJIT stats at exit.
-
-### --rjit-dump-disasm
-
-This dumps all JIT code. You need to install libcapstone before configure and use `--enable-rjit=dev` on configure.
-
-* Ubuntu: `sudo apt-get install -y libcapstone-dev`
-* macOS: `brew install capstone`
diff --git a/doc/ruby/option_dump.md b/doc/ruby/option_dump.md
deleted file mode 100644
index 00d0ec77d5..0000000000
--- a/doc/ruby/option_dump.md
+++ /dev/null
@@ -1,297 +0,0 @@
-# Option `--dump`
-
-For other argument values,
-see {Option --dump}[options_md.html#label--dump-3A+Dump+Items].
-
-For the examples here, we use this program:
-
-```sh
-$ cat t.rb
-puts 'Foo'
-```
-
-The supported dump items:
-
-- `insns`: Instruction sequences:
-
- ```sh
- $ ruby --dump=insns t.rb
- == disasm: #<ISeq:<main>@t.rb:1 (1,0)-(1,10)> (catch: FALSE)
- 0000 putself ( 1)[Li]
- 0001 putstring "Foo"
- 0003 opt_send_without_block <calldata!mid:puts, argc:1, FCALL|ARGS_SIMPLE>
- 0005 leave
- ```
-
-- `parsetree`: {Abstract syntax tree}[https://en.wikipedia.org/wiki/Abstract_syntax_tree]
- (AST):
-
- ```sh
- $ ruby --dump=parsetree t.rb
- ###########################################################
- ## Do NOT use this node dump for any purpose other than ##
- ## debug and research. Compatibility is not guaranteed. ##
- ###########################################################
-
- # @ NODE_SCOPE (line: 1, location: (1,0)-(1,10))
- # +- nd_tbl: (empty)
- # +- nd_args:
- # | (null node)
- # +- nd_body:
- # @ NODE_FCALL (line: 1, location: (1,0)-(1,10))*
- # +- nd_mid: :puts
- # +- nd_args:
- # @ NODE_LIST (line: 1, location: (1,5)-(1,10))
- # +- nd_alen: 1
- # +- nd_head:
- # | @ NODE_STR (line: 1, location: (1,5)-(1,10))
- # | +- nd_lit: "Foo"
- # +- nd_next:
- # (null node)
- ```
-
-- `parsetree_with_comment`: AST with comments:
-
- ```sh
- $ ruby --dump=parsetree_with_comment t.rb
- ###########################################################
- ## Do NOT use this node dump for any purpose other than ##
- ## debug and research. Compatibility is not guaranteed. ##
- ###########################################################
-
- # @ NODE_SCOPE (line: 1, location: (1,0)-(1,10))
- # | # new scope
- # | # format: [nd_tbl]: local table, [nd_args]: arguments, [nd_body]: body
- # +- nd_tbl (local table): (empty)
- # +- nd_args (arguments):
- # | (null node)
- # +- nd_body (body):
- # @ NODE_FCALL (line: 1, location: (1,0)-(1,10))*
- # | # function call
- # | # format: [nd_mid]([nd_args])
- # | # example: foo(1)
- # +- nd_mid (method id): :puts
- # +- nd_args (arguments):
- # @ NODE_LIST (line: 1, location: (1,5)-(1,10))
- # | # list constructor
- # | # format: [ [nd_head], [nd_next].. ] (length: [nd_alen])
- # | # example: [1, 2, 3]
- # +- nd_alen (length): 1
- # +- nd_head (element):
- # | @ NODE_STR (line: 1, location: (1,5)-(1,10))
- # | | # string literal
- # | | # format: [nd_lit]
- # | | # example: 'foo'
- # | +- nd_lit (literal): "Foo"
- # +- nd_next (next element):
- # (null node)
- ```
-
-- `yydebug`: Debugging information from yacc parser generator:
-
- ```sh
- $ ruby --dump=yydebug t.rb
- Starting parse
- Entering state 0
- Reducing stack by rule 1 (line 1295):
- lex_state: NONE -> BEG at line 1296
- vtable_alloc:12392: 0x0000558453df1a00
- vtable_alloc:12393: 0x0000558453df1a60
- cmdarg_stack(push): 0 at line 12406
- cond_stack(push): 0 at line 12407
- -> $$ = nterm $@1 (1.0-1.0: )
- Stack now 0
- Entering state 2
- Reading a token:
- lex_state: BEG -> CMDARG at line 9049
- Next token is token "local variable or method" (1.0-1.4: puts)
- Shifting token "local variable or method" (1.0-1.4: puts)
- Entering state 35
- Reading a token: Next token is token "string literal" (1.5-1.6: )
- Reducing stack by rule 742 (line 5567):
- $1 = token "local variable or method" (1.0-1.4: puts)
- -> $$ = nterm operation (1.0-1.4: )
- Stack now 0 2
- Entering state 126
- Reducing stack by rule 78 (line 1794):
- $1 = nterm operation (1.0-1.4: )
- -> $$ = nterm fcall (1.0-1.4: )
- Stack now 0 2
- Entering state 80
- Next token is token "string literal" (1.5-1.6: )
- Reducing stack by rule 292 (line 2723):
- cmdarg_stack(push): 1 at line 2737
- -> $$ = nterm $@16 (1.4-1.4: )
- Stack now 0 2 80
- Entering state 235
- Next token is token "string literal" (1.5-1.6: )
- Shifting token "string literal" (1.5-1.6: )
- Entering state 216
- Reducing stack by rule 607 (line 4706):
- -> $$ = nterm string_contents (1.6-1.6: )
- Stack now 0 2 80 235 216
- Entering state 437
- Reading a token: Next token is token "literal content" (1.6-1.9: "Foo")
- Shifting token "literal content" (1.6-1.9: "Foo")
- Entering state 503
- Reducing stack by rule 613 (line 4802):
- $1 = token "literal content" (1.6-1.9: "Foo")
- -> $$ = nterm string_content (1.6-1.9: )
- Stack now 0 2 80 235 216 437
- Entering state 507
- Reducing stack by rule 608 (line 4716):
- $1 = nterm string_contents (1.6-1.6: )
- $2 = nterm string_content (1.6-1.9: )
- -> $$ = nterm string_contents (1.6-1.9: )
- Stack now 0 2 80 235 216
- Entering state 437
- Reading a token:
- lex_state: CMDARG -> END at line 7276
- Next token is token "terminator" (1.9-1.10: )
- Shifting token "terminator" (1.9-1.10: )
- Entering state 508
- Reducing stack by rule 590 (line 4569):
- $1 = token "string literal" (1.5-1.6: )
- $2 = nterm string_contents (1.6-1.9: )
- $3 = token "terminator" (1.9-1.10: )
- -> $$ = nterm string1 (1.5-1.10: )
- Stack now 0 2 80 235
- Entering state 109
- Reducing stack by rule 588 (line 4559):
- $1 = nterm string1 (1.5-1.10: )
- -> $$ = nterm string (1.5-1.10: )
- Stack now 0 2 80 235
- Entering state 108
- Reading a token:
- lex_state: END -> BEG at line 9200
- Next token is token '\n' (1.10-1.10: )
- Reducing stack by rule 586 (line 4541):
- $1 = nterm string (1.5-1.10: )
- -> $$ = nterm strings (1.5-1.10: )
- Stack now 0 2 80 235
- Entering state 107
- Reducing stack by rule 307 (line 2837):
- $1 = nterm strings (1.5-1.10: )
- -> $$ = nterm primary (1.5-1.10: )
- Stack now 0 2 80 235
- Entering state 90
- Next token is token '\n' (1.10-1.10: )
- Reducing stack by rule 261 (line 2553):
- $1 = nterm primary (1.5-1.10: )
- -> $$ = nterm arg (1.5-1.10: )
- Stack now 0 2 80 235
- Entering state 220
- Next token is token '\n' (1.10-1.10: )
- Reducing stack by rule 270 (line 2586):
- $1 = nterm arg (1.5-1.10: )
- -> $$ = nterm arg_value (1.5-1.10: )
- Stack now 0 2 80 235
- Entering state 221
- Next token is token '\n' (1.10-1.10: )
- Reducing stack by rule 297 (line 2779):
- $1 = nterm arg_value (1.5-1.10: )
- -> $$ = nterm args (1.5-1.10: )
- Stack now 0 2 80 235
- Entering state 224
- Next token is token '\n' (1.10-1.10: )
- Reducing stack by rule 772 (line 5626):
- -> $$ = nterm none (1.10-1.10: )
- Stack now 0 2 80 235 224
- Entering state 442
- Reducing stack by rule 296 (line 2773):
- $1 = nterm none (1.10-1.10: )
-
- -> $$ = nterm opt_block_arg (1.10-1.10: )
- Stack now 0 2 80 235 224
- Entering state 441
- Reducing stack by rule 288 (line 2696):
- $1 = nterm args (1.5-1.10: )
- $2 = nterm opt_block_arg (1.10-1.10: )
- -> $$ = nterm call_args (1.5-1.10: )
- Stack now 0 2 80 235
- Entering state 453
- Reducing stack by rule 293 (line 2723):
- $1 = nterm $@16 (1.4-1.4: )
- $2 = nterm call_args (1.5-1.10: )
- cmdarg_stack(pop): 0 at line 2754
- -> $$ = nterm command_args (1.4-1.10: )
- Stack now 0 2 80
- Entering state 333
- Next token is token '\n' (1.10-1.10: )
- Reducing stack by rule 79 (line 1804):
- $1 = nterm fcall (1.0-1.4: )
- $2 = nterm command_args (1.4-1.10: )
- -> $$ = nterm command (1.0-1.10: )
- Stack now 0 2
- Entering state 81
- Next token is token '\n' (1.10-1.10: )
- Reducing stack by rule 73 (line 1770):
- $1 = nterm command (1.0-1.10: )
- -> $$ = nterm command_call (1.0-1.10: )
- Stack now 0 2
- Entering state 78
- Reducing stack by rule 51 (line 1659):
- $1 = nterm command_call (1.0-1.10: )
- -> $$ = nterm expr (1.0-1.10: )
- Stack now 0 2
- Entering state 75
- Next token is token '\n' (1.10-1.10: )
- Reducing stack by rule 39 (line 1578):
- $1 = nterm expr (1.0-1.10: )
- -> $$ = nterm stmt (1.0-1.10: )
- Stack now 0 2
- Entering state 73
- Next token is token '\n' (1.10-1.10: )
- Reducing stack by rule 8 (line 1354):
- $1 = nterm stmt (1.0-1.10: )
- -> $$ = nterm top_stmt (1.0-1.10: )
- Stack now 0 2
- Entering state 72
- Reducing stack by rule 5 (line 1334):
- $1 = nterm top_stmt (1.0-1.10: )
- -> $$ = nterm top_stmts (1.0-1.10: )
- Stack now 0 2
- Entering state 71
- Next token is token '\n' (1.10-1.10: )
- Shifting token '\n' (1.10-1.10: )
- Entering state 311
- Reducing stack by rule 769 (line 5618):
- $1 = token '\n' (1.10-1.10: )
- -> $$ = nterm term (1.10-1.10: )
- Stack now 0 2 71
- Entering state 313
- Reducing stack by rule 770 (line 5621):
- $1 = nterm term (1.10-1.10: )
- -> $$ = nterm terms (1.10-1.10: )
- Stack now 0 2 71
- Entering state 314
- Reading a token: Now at end of input.
- Reducing stack by rule 759 (line 5596):
- $1 = nterm terms (1.10-1.10: )
- -> $$ = nterm opt_terms (1.10-1.10: )
- Stack now 0 2 71
- Entering state 312
- Reducing stack by rule 3 (line 1321):
- $1 = nterm top_stmts (1.0-1.10: )
- $2 = nterm opt_terms (1.10-1.10: )
- -> $$ = nterm top_compstmt (1.0-1.10: )
- Stack now 0 2
- Entering state 70
- Reducing stack by rule 2 (line 1295):
- $1 = nterm $@1 (1.0-1.0: )
- $2 = nterm top_compstmt (1.0-1.10: )
- vtable_free:12426: p->lvtbl->args(0x0000558453df1a00)
- vtable_free:12427: p->lvtbl->vars(0x0000558453df1a60)
- cmdarg_stack(pop): 0 at line 12428
- cond_stack(pop): 0 at line 12429
- -> $$ = nterm program (1.0-1.10: )
- Stack now 0
- Entering state 1
- Now at end of input.
- Shifting token "end-of-input" (1.10-1.10: )
- Entering state 3
- Stack now 0 1 3
- Cleanup: popping token "end-of-input" (1.10-1.10: )
- Cleanup: popping nterm program (1.0-1.10: )
- ```
-
diff --git a/doc/ruby/options.md b/doc/ruby/options.md
deleted file mode 100644
index 143c8925f1..0000000000
--- a/doc/ruby/options.md
+++ /dev/null
@@ -1,723 +0,0 @@
-# Ruby Command-Line Options
-
-## About the Examples
-
-Some examples here use command-line option `-e`,
-which passes the Ruby code to be executed on the command line itself:
-
-```sh
-$ ruby -e 'puts "Hello, World."'
-```
-
-Some examples here assume that file `desiderata.txt` exists:
-
-```
-$ cat desiderata.txt
-Go placidly amid the noise and the haste,
-and remember what peace there may be in silence.
-As far as possible, without surrender,
-be on good terms with all persons.
-```
-
-## Options
-
-### `-0`: \Set `$/` (Input Record Separator)
-
-Option `-0` defines the input record separator `$/`
-for the invoked Ruby program.
-
-The optional argument to the option must be octal digits,
-each in the range `0..7`;
-these digits are prefixed with digit `0` to form an octal value.
-
-If no argument is given, the input record separator is `0x00`.
-
-If an argument is given, it must immediately follow the option
-(no intervening whitespace or equal-sign character `'='`);
-argument values:
-
-- `0`: the input record separator is `''`;
- see {Special Line Separator Values}[rdoc-ref:IO@Special+Line+Separator+Values].
-- In range `(1..0377)`:
- the input record separator `$/` is set to the character value of the argument.
-- Any other octal value: the input record separator is `nil`.
-
-Examples:
-
-```sh
-$ ruby -0 -e 'p $/'
-"\x00"
-ruby -00 -e 'p $/'
-""
-$ ruby -012 -e 'p $/'
-"\n"
-$ ruby -015 -e 'p $/'
-"\r"
-$ ruby -0377 -e 'p $/'
-"\xFF"
-$ ruby -0400 -e 'p $/'
-nil
-```
-
-See also:
-
-- {Option -a}[rdoc-ref:ruby/options.md@a-3A+Split+Input+Lines+into+Fields]:
- Split input lines into fields.
-- {Option -F}[rdoc-ref:ruby/options.md@F-3A+Set+Input+Field+Separator]:
- \Set input field separator.
-- {Option -l}[rdoc-ref:ruby/options.md@l-3A+Set+Output+Record+Separator-3B+Chop+Lines]:
- \Set output record separator; chop lines.
-- {Option -n}[rdoc-ref:ruby/options.md@n-3A+Run+Program+in+gets+Loop]:
- Run program in `gets` loop.
-- {Option -p}[rdoc-ref:ruby/options.md@p-3A+-n-2C+with+Printing]:
- `-n`, with printing.
-
-### `-a`: Split Input Lines into Fields
-
-Option `-a`, when given with either of options `-n` or `-p`,
-splits the string at `$_` into an array of strings at `$F`:
-
-```sh
-$ ruby -an -e 'p $F' desiderata.txt
-["Go", "placidly", "amid", "the", "noise", "and", "the", "haste,"]
-["and", "remember", "what", "peace", "there", "may", "be", "in", "silence."]
-["As", "far", "as", "possible,", "without", "surrender,"]
-["be", "on", "good", "terms", "with", "all", "persons."]
-```
-
-For the splitting,
-the default record separator is `$/`,
-and the default field separator is `$;`.
-
-See also:
-
-- {Option -0}[rdoc-ref:ruby/options.md@0-3A+Set+-24-2F+-28Input+Record+Separator-29]:
- \Set `$/` (input record separator).
-- {Option -F}[rdoc-ref:ruby/options.md@F-3A+Set+Input+Field+Separator]:
- \Set input field separator.
-- {Option -l}[rdoc-ref:ruby/options.md@l-3A+Set+Output+Record+Separator-3B+Chop+Lines]:
- \Set output record separator; chop lines.
-- {Option -n}[rdoc-ref:ruby/options.md@n-3A+Run+Program+in+gets+Loop]:
- Run program in `gets` loop.
-- {Option -p}[rdoc-ref:ruby/options.md@p-3A+-n-2C+with+Printing]:
- `-n`, with printing.
-
-### `-c`: Check Syntax
-
-Option `-c` specifies that the specified Ruby program
-should be checked for syntax, but not actually executed:
-
-```
-$ ruby -e 'puts "Foo"'
-Foo
-$ ruby -c -e 'puts "Foo"'
-Syntax OK
-```
-
-### `-C`: \Set Working Directory
-
-The argument to option `-C` specifies a working directory
-for the invoked Ruby program;
-does not change the working directory for the current process:
-
-```sh
-$ basename `pwd`
-ruby
-$ ruby -C lib -e 'puts File.basename(Dir.pwd)'
-lib
-$ basename `pwd`
-ruby
-```
-
-Whitespace between the option and its argument may be omitted.
-
-### `-d`: \Set `$DEBUG` to `true`
-
-Some code in (or called by) the Ruby program may include statements or blocks
-conditioned by the global variable `$DEBUG` (e.g., `if $DEBUG`);
-these commonly write to `$stdout` or `$stderr`.
-
-The default value for `$DEBUG` is `false`;
-option `-d` sets it to `true`:
-
-```sh
-$ ruby -e 'p $DEBUG'
-false
-$ ruby -d -e 'p $DEBUG'
-true
-```
-
-Option `--debug` is an alias for option `-d`.
-
-### `-e`: Execute Given Ruby Code
-
-Option `-e` requires an argument, which is Ruby code to be executed;
-the option may be given more than once:
-
-```
-$ ruby -e 'puts "Foo"' -e 'puts "Bar"'
-Foo
-Bar
-```
-
-Whitespace between the option and its argument may be omitted.
-
-The command may include other options,
-but should not include arguments (which, if given, are ignored).
-
-### `-E`: \Set Default Encodings
-
-Option `-E` requires an argument, which specifies either the default external encoding,
-or both the default external and internal encodings for the invoked Ruby program:
-
-```
-# No option -E.
-$ ruby -e 'p [Encoding::default_external, Encoding::default_internal]'
-[#<Encoding:UTF-8>, nil]
-# Option -E with default external encoding.
-$ ruby -E cesu-8 -e 'p [Encoding::default_external, Encoding::default_internal]'
-[#<Encoding:CESU-8>, nil]
-# Option -E with default external and internal encodings.
-$ ruby -E utf-8:cesu-8 -e 'p [Encoding::default_external, Encoding::default_internal]'
-[#<Encoding:UTF-8>, #<Encoding:CESU-8>]
-```
-
-Whitespace between the option and its argument may be omitted.
-
-See also:
-
-- {Option --external-encoding}[options_md.html#label--external-encoding-3A+Set+Default+External+Encoding]:
- \Set default external encoding.
-- {Option --internal-encoding}[options_md.html#label--internal-encoding-3A+Set+Default+Internal+Encoding]:
- \Set default internal encoding.
-
-Option `--encoding` is an alias for option `-E`.
-
-### `-F`: \Set Input Field Separator
-
-Option `-F`, when given with option `-a`,
-specifies that its argument is to be the input field separator to be used for splitting:
-
-```sh
-$ ruby -an -Fs -e 'p $F' desiderata.txt
-["Go placidly amid the noi", "e and the ha", "te,\n"]
-["and remember what peace there may be in ", "ilence.\n"]
-["A", " far a", " po", "", "ible, without ", "urrender,\n"]
-["be on good term", " with all per", "on", ".\n"]
-```
-
-The argument may be a regular expression:
-
-```
-$ ruby -an -F'[.,]\s*' -e 'p $F' desiderata.txt
-["Go placidly amid the noise and the haste"]
-["and remember what peace there may be in silence"]
-["As far as possible", "without surrender"]
-["be on good terms with all persons"]
-```
-
-The argument must immediately follow the option
-(no intervening whitespace or equal-sign character `'='`).
-
-See also:
-
-- {Option -0}[rdoc-ref:ruby/options.md@0-3A+Set+-24-2F+-28Input+Record+Separator-29]:
- \Set `$/` (input record separator).
-- {Option -a}[rdoc-ref:ruby/options.md@a-3A+Split+Input+Lines+into+Fields]:
- Split input lines into fields.
-- {Option -l}[rdoc-ref:ruby/options.md@l-3A+Set+Output+Record+Separator-3B+Chop+Lines]:
- \Set output record separator; chop lines.
-- {Option -n}[rdoc-ref:ruby/options.md@n-3A+Run+Program+in+gets+Loop]:
- Run program in `gets` loop.
-- {Option -p}[rdoc-ref:ruby/options.md@p-3A+-n-2C+with+Printing]:
- `-n`, with printing.
-
-### `-h`: Print Short Help Message
-
-Option `-h` prints a short help message
-that includes single-hyphen options (e.g. `-I`),
-and largely omits double-hyphen options (e.g., `--version`).
-
-Arguments and additional options are ignored.
-
-For a longer help message, use option `--help`.
-
-### `-i`: \Set \ARGF In-Place Mode
-
-Option `-i` sets the \ARGF in-place mode for the invoked Ruby program;
-see ARGF#inplace_mode=:
-
-```
-$ ruby -e 'p ARGF.inplace_mode'
-nil
-$ ruby -i -e 'p ARGF.inplace_mode'
-""
-$ ruby -i.bak -e 'p ARGF.inplace_mode'
-".bak"
-```
-
-### `-I`: Add to `$LOAD_PATH`
-
-The argument to option `-I` specifies a directory
-to be added to the array in global variable `$LOAD_PATH`;
-the option may be given more than once:
-
-```sh
-$ pushd /tmp
-$ ruby -e 'p $LOAD_PATH.size'
-8
-$ ruby -I my_lib -I some_lib -e 'p $LOAD_PATH.size'
-10
-$ ruby -I my_lib -I some_lib -e 'p $LOAD_PATH.take(2)'
-["/tmp/my_lib", "/tmp/some_lib"]
-$ popd
-```
-
-Whitespace between the option and its argument may be omitted.
-
-### `-l`: \Set Output Record Separator; Chop Lines
-
-Option `-l`, when given with option `-n` or `-p`,
-modifies line-ending processing by:
-
-- Setting global variable output record separator `$\`
- to the current value of input record separator `$/`;
- this affects line-oriented output (such a the output from Kernel#puts).
-- Calling String#chop! on each line read.
-
-Without option `-l` (unchopped):
-
-```sh
-$ ruby -n -e 'p $_' desiderata.txt
-"Go placidly amid the noise and the haste,\n"
-"and remember what peace there may be in silence.\n"
-"As far as possible, without surrender,\n"
-"be on good terms with all persons.\n"
-```
-
-With option `-l' (chopped):
-
-```sh
-$ ruby -ln -e 'p $_' desiderata.txt
-"Go placidly amid the noise and the haste,"
-"and remember what peace there may be in silence."
-"As far as possible, without surrender,"
-"be on good terms with all persons."
-```
-
-See also:
-
-- {Option -0}[rdoc-ref:ruby/options.md@0-3A+Set+-24-2F+-28Input+Record+Separator-29]:
- \Set `$/` (input record separator).
-- {Option -a}[rdoc-ref:ruby/options.md@a-3A+Split+Input+Lines+into+Fields]:
- Split input lines into fields.
-- {Option -F}[rdoc-ref:ruby/options.md@F-3A+Set+Input+Field+Separator]:
- \Set input field separator.
-- {Option -n}[rdoc-ref:ruby/options.md@n-3A+Run+Program+in+gets+Loop]:
- Run program in `gets` loop.
-- {Option -p}[rdoc-ref:ruby/options.md@p-3A+-n-2C+with+Printing]:
- `-n`, with printing.
-
-### `-n`: Run Program in `gets` Loop
-
-Option `-n` runs your program in a Kernel#gets loop:
-
-```
-while gets
- # Your Ruby code.
-end
-```
-
-Note that `gets` reads the next line and sets global variable `$_`
-to the last read line:
-
-```sh
-$ ruby -n -e 'puts $_' desiderata.txt
-Go placidly amid the noise and the haste,
-and remember what peace there may be in silence.
-As far as possible, without surrender,
-be on good terms with all persons.
-```
-
-See also:
-
-- {Option -0}[rdoc-ref:ruby/options.md@0-3A+Set+-24-2F+-28Input+Record+Separator-29]:
- \Set `$/` (input record separator).
-- {Option -a}[rdoc-ref:ruby/options.md@a-3A+Split+Input+Lines+into+Fields]:
- Split input lines into fields.
-- {Option -F}[rdoc-ref:ruby/options.md@F-3A+Set+Input+Field+Separator]:
- \Set input field separator.
-- {Option -l}[rdoc-ref:ruby/options.md@l-3A+Set+Output+Record+Separator-3B+Chop+Lines]:
- \Set output record separator; chop lines.
-- {Option -p}[rdoc-ref:ruby/options.md@p-3A+-n-2C+with+Printing]:
- `-n`, with printing.
-
-### `-p`: `-n`, with Printing
-
-Option `-p` is like option `-n`, but also prints each line:
-
-```sh
-$ ruby -p -e 'puts $_.size' desiderata.txt
-42
-Go placidly amid the noise and the haste,
-49
-and remember what peace there may be in silence.
-39
-As far as possible, without surrender,
-35
-be on good terms with all persons.
-```
-
-See also:
-
-- {Option -0}[rdoc-ref:ruby/options.md@0-3A+Set+-24-2F+-28Input+Record+Separator-29]:
- \Set `$/` (input record separator).
-- {Option -a}[rdoc-ref:ruby/options.md@a-3A+Split+Input+Lines+into+Fields]:
- Split input lines into fields.
-- {Option -F}[rdoc-ref:ruby/options.md@F-3A+Set+Input+Field+Separator]:
- \Set input field separator.
-- {Option -l}[rdoc-ref:ruby/options.md@l-3A+Set+Output+Record+Separator-3B+Chop+Lines]:
- \Set output record separator; chop lines.
-- {Option -n}[rdoc-ref:ruby/options.md@n-3A+Run+Program+in+gets+Loop]:
- Run program in `gets` loop.
-
-### `-r`: Require Library
-
-The argument to option `-r` specifies a library to be required
-before executing the Ruby program;
-the option may be given more than once:
-
-```sh
-$ ruby -e 'p defined?(JSON); p defined?(CSV)'
-nil
-nil
-$ ruby -r CSV -r JSON -e 'p defined?(JSON); p defined?(CSV)'
-"constant"
-"constant"
-```
-
-Whitespace between the option and its argument may be omitted.
-
-### `-s`: Define Global Variable
-
-Option `-s` specifies that a "custom option" is to define a global variable
-in the invoked Ruby program:
-
-- The custom option must appear _after_ the program name.
-- The custom option must begin with single hyphen (e.g., `-foo`),
- not two hyphens (e.g., `--foo`).
-- The name of the global variable is based on the option name:
- global variable `$foo` for custom option`-foo`.
-- The value of the global variable is the string option argument if given,
- `true` otherwise.
-
-More than one custom option may be given:
-
-```
-$ cat t.rb
-p [$foo, $bar]
-$ ruby t.rb
-[nil, nil]
-$ ruby -s t.rb -foo=baz
-["baz", nil]
-$ ruby -s t.rb -foo
-[true, nil]
-$ ruby -s t.rb -foo=baz -bar=bat
-["baz", "bat"]
-```
-
-The option may not be used with
-{option -e}[rdoc-ref:ruby/options.md@e-3A+Execute+Given+Ruby+Code]
-
-### `-S`: Search Directories in `ENV['PATH']`
-
-Option `-S` specifies that the Ruby interpreter
-is to search (if necessary) the directories whose paths are in the program's
-`PATH` environment variable;
-the program is executed in the shell's current working directory
-(not necessarily in the directory where the program is found).
-
-This example uses adds path `'tmp/'` to the `PATH` environment variable:
-
-```sh
-$ export PATH=/tmp:$PATH
-$ echo "puts File.basename(Dir.pwd)" > /tmp/t.rb
-$ ruby -S t.rb
-ruby
-```
-
-### `-v`: Print Version; \Set `$VERBOSE`
-
-Options `-v` prints the Ruby version and sets global variable `$VERBOSE`:
-
-```
-$ ruby -e 'p $VERBOSE'
-false
-$ ruby -v -e 'p $VERBOSE'
-ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x64-mingw-ucrt]
-true
-```
-
-### `-w`: Synonym for `-W1`
-
-Option `-w` (lowercase letter) is equivalent to option `-W1` (uppercase letter).
-
-### `-W`: \Set \Warning Policy
-
-Any Ruby code can create a <i>warning message</i> by calling method Kernel#warn;
-methods in the Ruby core and standard libraries can also create warning messages.
-Such a message may be printed on `$stderr`
-(or not, depending on certain settings).
-
-Option `-W` helps determine whether a particular warning message
-will be written,
-by setting the initial value of global variable `$-W`:
-
-- `-W0`: Sets `$-W` to `0` (silent; no warnings).
-- `-W1`: Sets `$-W` to `1` (moderate verbosity).
-- `-W2`: Sets `$-W` to `2` (high verbosity).
-- `-W`: Same as `-W2` (high verbosity).
-- Option not given: Same as `-W1` (moderate verbosity).
-
-The value of `$-W`, in turn, determines which warning messages (if any)
-are to be printed to `$stdout` (see Kernel#warn):
-
-```sh
-$ ruby -W1 -e 'p $foo'
-nil
-$ ruby -W2 -e 'p $foo'
--e:1: warning: global variable '$foo' not initialized
-nil
-```
-
-Ruby code may also define warnings for certain categories;
-these are the default settings for the defined categories:
-
-```
-Warning[:experimental] # => true
-Warning[:deprecated] # => false
-Warning[:performance] # => false
-```
-
-They may also be set:
-```
-Warning[:experimental] = false
-Warning[:deprecated] = true
-Warning[:performance] = true
-```
-
-You can suppress a category by prefixing `no-` to the category name:
-
-```
-$ ruby -W:no-experimental -e 'p IO::Buffer.new'
-#<IO::Buffer>
-```
-
-### `-x`: Execute Ruby Code Found in Text
-
-Option `-x` executes a Ruby program whose code is embedded
-in other, non-code, text:
-
-The ruby code:
-
-- Begins after the first line beginning with `'#!` and containing string `'ruby'`.
-- Ends before any one of:
-
- - End-of-file.
- - A line consisting of `'__END__'`,
- - Character `Ctrl-D` or `Ctrl-Z`.
-
-Example:
-
-```sh
-$ cat t.txt
-Leading garbage.
-#!ruby
-puts File.basename(Dir.pwd)
-__END__
-Trailing garbage.
-
-$ ruby -x t.txt
-ruby
-```
-
-The optional argument specifies the directory where the text file
-is to be found;
-the Ruby code is executed in that directory:
-
-```sh
-$ cp t.txt /tmp/
-$ ruby -x/tmp t.txt
-tmp
-$
-
-```
-
-If an argument is given, it must immediately follow the option
-(no intervening whitespace or equal-sign character `'='`).
-
-### `--backtrace-limit`: \Set Backtrace Limit
-
-Option `--backtrace-limit` sets a limit on the number of entries
-to be displayed in a backtrace.
-
-See Thread::Backtrace.limit.
-
-### `--copyright`: Print Ruby Copyright
-
-Option `--copyright` prints a copyright message:
-
-```sh
-$ ruby --copyright
-ruby - Copyright (C) 1993-2024 Yukihiro Matsumoto
-```
-
-### `--debug`: Alias for `-d`
-
-Option `--debug` is an alias for
-{option -d}[rdoc-ref:ruby/options.md@d-3A+Set+-24DEBUG+to+true].
-
-### `--disable`: Disable Features
-
-Option `--disable` specifies features to be disabled;
-the argument is a comma-separated list of the features to be disabled:
-
-```sh
-ruby --disable=gems,rubyopt t.rb
-```
-
-The supported features:
-
-- `gems`: Rubygems (default: enabled).
-- `did_you_mean`: [`did_you_mean`](https://github.com/ruby/did_you_mean) (default: enabled).
-- `rubyopt`: `RUBYOPT` environment variable (default: enabled).
-- `frozen-string-literal`: Freeze all string literals (default: disabled).
-- `jit`: JIT compiler (default: disabled).
-
-See also {option --enable}[options_md.html#label--enable-3A+Enable+Features].
-
-### `--dump`: Dump Items
-
-Option `--dump` specifies items to be dumped;
-the argument is a comma-separated list of the items.
-
-Some of the argument values cause the command to behave as if a different
-option was given:
-
-- `--dump=copyright`:
- Same as {option \-\-copyright}[options_md.html#label--copyright-3A+Print+Ruby+Copyright].
-- `--dump=help`:
- Same as {option \-\-help}[options_md.html#label--help-3A+Print+Help+Message].
-- `--dump=syntax`:
- Same as {option -c}[rdoc-ref:ruby/options.md@c-3A+Check+Syntax].
-- `--dump=usage`:
- Same as {option -h}[rdoc-ref:ruby/options.md@h-3A+Print+Short+Help+Message].
-- `--dump=version`:
- Same as {option \-\-version}[options_md.html#label--version-3A+Print+Ruby+Version].
-
-For other argument values and examples,
-see {Option --dump}[option_dump_md.html].
-
-### `--enable`: Enable Features
-
-Option `--enable` specifies features to be enabled;
-the argument is a comma-separated list of the features to be enabled.
-
-```sh
-ruby --enable=gems,rubyopt t.rb
-```
-
-For the features,
-see {option --disable}[options_md.html#label--disable-3A+Disable+Features].
-
-### `--encoding`: Alias for `-E`.
-
-Option `--encoding` is an alias for
-{option -E}[rdoc-ref:ruby/options.md@E-3A+Set+Default+Encodings].
-
-### `--external-encoding`: \Set Default External \Encoding
-
-Option `--external-encoding`
-sets the default external encoding for the invoked Ruby program;
-for values of +encoding+,
-see {Encoding: Names and Aliases}[rdoc-ref:encodings.rdoc@Names+and+Aliases].
-
-```sh
-$ ruby -e 'puts Encoding::default_external'
-UTF-8
-$ ruby --external-encoding=cesu-8 -e 'puts Encoding::default_external'
-CESU-8
-```
-
-### `--help`: Print Help Message
-
-Option `--help` prints a long help message.
-
-Arguments and additional options are ignored.
-
-For a shorter help message, use option `-h`.
-
-### `--internal-encoding`: \Set Default Internal \Encoding
-
-Option `--internal-encoding`
-sets the default internal encoding for the invoked Ruby program;
-for values of +encoding+,
-see {Encoding: Names and Aliases}[rdoc-ref:encodings.rdoc@Names+and+Aliases].
-
-```sh
-$ ruby -e 'puts Encoding::default_internal.nil?'
-true
-$ ruby --internal-encoding=cesu-8 -e 'puts Encoding::default_internal'
-CESU-8
-```
-
-### `--verbose`: \Set `$VERBOSE`
-
-Option `--verbose` sets global variable `$VERBOSE` to `true`
-and disables input from `$stdin`.
-
-### `--version`: Print Ruby Version
-
-Option `--version` prints the version of the Ruby interpreter, then exits.
-
-## Experimental Options
-
-These options are experimental in the current Ruby release,
-and may be modified or withdrawn in later releases.
-
-### `--jit`
-
-Option `-jit` enables JIT compilation with the default option.
-
-#### `--jit-debug`
-
-Option `--jit-debug` enables JIT debugging (very slow);
-adds compiler flags if given.
-
-#### `--jit-max-cache=num`
-
-Option `--jit-max-cache=num` sets the maximum number of methods
-to be JIT-ed in a cache; default: 100).
-
-#### `--jit-min-calls=num`
-
-Option `jit-min-calls=num` sets the minimum number of calls to trigger JIT
-(for testing); default: 10000).
-
-#### `--jit-save-temps`
-
-Option `--jit-save-temps` saves JIT temporary files in $TMP or /tmp (for testing).
-
-#### `--jit-verbose`
-
-Option `--jit-verbose` prints JIT logs of level `num` or less
-to `$stderr`; default: 0.
-
-#### `--jit-wait`
-
-Option `--jit-wait` waits until JIT compilation finishes every time (for testing).
-
-#### `--jit-warnings`
-
-Option `--jit-warnings` enables printing of JIT warnings.
-
diff --git a/doc/security.rdoc b/doc/security.rdoc
deleted file mode 100644
index e428036cf5..0000000000
--- a/doc/security.rdoc
+++ /dev/null
@@ -1,139 +0,0 @@
-= Ruby Security
-
-The Ruby programming language is large and complex and there are many security
-pitfalls often encountered by newcomers and experienced Rubyists alike.
-
-This document aims to discuss many of these pitfalls and provide more secure
-alternatives where applicable.
-
-Please check the full list of publicly known CVEs and how to correctly report a
-security vulnerability, at: https://www.ruby-lang.org/en/security/
-Japanese version is here: https://www.ruby-lang.org/ja/security/
-
-Security vulnerabilities should be reported via an email to
-mailto:security@ruby-lang.org ({the PGP public
-key}[https://www.ruby-lang.org/security.asc]), which is a private mailing list.
-Reported problems will be published after fixes.
-
-== +Marshal.load+
-
-Ruby's +Marshal+ module provides methods for serializing and deserializing Ruby
-object trees to and from a binary data format.
-
-Never use +Marshal.load+ to deserialize untrusted or user supplied data.
-Because +Marshal+ can deserialize to almost any Ruby object and has full
-control over instance variables, it is possible to craft a malicious payload
-that executes code shortly after deserialization.
-
-If you need to deserialize untrusted data, you should use JSON as it is only
-capable of returning 'primitive' types such as strings, arrays, hashes, numbers
-and nil. If you need to deserialize other classes, you should handle this
-manually. Never deserialize to a user specified class.
-
-== YAML
-
-YAML is a popular human readable data serialization format used by many Ruby
-programs for configuration and database persistence of Ruby object trees.
-
-Similar to +Marshal+, it is able to deserialize into arbitrary Ruby classes.
-For example, the following YAML data will create an +ERB+ object when
-deserialized, using the `unsafe_load` method:
-
- !ruby/object:ERB
- src: puts `uname`
-
-Because of this, many of the security considerations applying to Marshal are
-also applicable to YAML. Do not use YAML to deserialize untrusted data.
-
-== Symbols
-
-Symbols are often seen as syntax sugar for simple strings, but they play a much
-more crucial role. The MRI Ruby implementation uses Symbols internally for
-method, variable and constant names. The reason for this is that symbols are
-simply integers with names attached to them, so they are faster to look up in
-hashtables.
-
-Starting in version 2.2, most symbols can be garbage collected; these are
-called <i>mortal</i> symbols. Most symbols you create (e.g. by calling
-+to_sym+) are mortal.
-
-<i>Immortal</i> symbols on the other hand will never be garbage collected.
-They are created when modifying code:
-* defining a method (e.g. with +define_method+),
-* setting an instance variable (e.g. with +instance_variable_set+),
-* creating a variable or constant (e.g. with +const_set+)
-C extensions that have not been updated and are still calling `SYM2ID`
-will create immortal symbols.
-Bugs in 2.2.0: +send+ and +__send__+ also created immortal symbols,
-and calling methods with keyword arguments could also create some.
-
-Don't create immortal symbols from user inputs. Otherwise, this would
-allow a user to mount a denial of service attack against your application by
-flooding it with unique strings, which will cause memory to grow indefinitely
-until the Ruby process is killed or causes the system to slow to a halt.
-
-While it might not be a good idea to call these with user inputs, methods that
-used to be vulnerable such as +to_sym+, +respond_to?+,
-+method+, +instance_variable_get+, +const_get+, etc. are no longer a threat.
-
-== Regular expressions
-
-Ruby's regular expression syntax has some minor differences when compared to
-other languages. In Ruby, the <code>^</code> and <code>$</code> anchors do not
-refer to the beginning and end of the string, rather the beginning and end of a
-*line*.
-
-This means that if you're using a regular expression like
-<code>/^[a-z]+$/</code> to restrict a string to only letters, an attacker can
-bypass this check by passing a string containing a letter, then a newline, then
-any string of their choosing.
-
-If you want to match the beginning and end of the entire string in Ruby, use
-the anchors +\A+ and +\z+.
-
-== +eval+
-
-Never pass untrusted or user controlled input to +eval+.
-
-Unless you are implementing a REPL like +irb+ or +pry+, +eval+ is almost
-certainly not what you want. Do not attempt to filter user input before passing
-it to +eval+ - this approach is fraught with danger and will most likely open
-your application up to a serious remote code execution vulnerability.
-
-== +send+
-
-'Global functions' in Ruby (+puts+, +exit+, etc.) are actually private instance
-methods on +Object+. This means it is possible to invoke these methods with
-+send+, even if the call to +send+ has an explicit receiver.
-
-For example, the following code snippet writes "Hello world" to the terminal:
-
- 1.send(:puts, "Hello world")
-
-You should never call +send+ with user supplied input as the first parameter.
-Doing so can introduce a denial of service vulnerability:
-
- foo.send(params[:bar]) # params[:bar] is "exit!"
-
-If an attacker can control the first two arguments to +send+, remote code
-execution is possible:
-
- # params is { :a => "eval", :b => "...ruby code to be executed..." }
- foo.send(params[:a], params[:b])
-
-When dispatching a method call based on user input, carefully verify that the
-method name. If possible, check it against a whitelist of safe method names.
-
-Note that the use of +public_send+ is also dangerous, as +send+ itself is
-public:
-
- 1.public_send("send", "eval", "...ruby code to be executed...")
-
-== DRb
-
-As DRb allows remote clients to invoke arbitrary methods, it is not suitable to
-expose to untrusted clients.
-
-When using DRb, try to avoid exposing it over the network if possible. If this
-isn't possible and you need to expose DRb to the world, you *must* configure an
-appropriate security policy with <code>DRb::ACL</code>.
diff --git a/doc/security/command_injection.rdoc b/doc/security/command_injection.rdoc
new file mode 100644
index 0000000000..d46e42f7be
--- /dev/null
+++ b/doc/security/command_injection.rdoc
@@ -0,0 +1,15 @@
+= Command Injection
+
+Some Ruby core methods accept string data
+that includes text to be executed as a system command.
+
+They should not be called with unknown or unsanitized commands.
+
+These methods include:
+
+- Kernel.exec
+- Kernel.spawn
+- Kernel.system
+- {\`command` (backtick method)}[rdoc-ref:Kernel#`]
+ (also called by the expression <tt>%x[command]</tt>).
+- IO.popen (when called with other than <tt>"-"</tt>).
diff --git a/doc/security/security.rdoc b/doc/security/security.rdoc
new file mode 100644
index 0000000000..af9970d336
--- /dev/null
+++ b/doc/security/security.rdoc
@@ -0,0 +1,127 @@
+= Ruby Security
+
+The Ruby programming language is large and complex and there are many security
+pitfalls often encountered by newcomers and experienced Rubyists alike.
+
+This document aims to discuss many of these pitfalls and provide more secure
+alternatives where applicable.
+
+Please check the full list of publicly known CVEs and how to correctly report a
+security vulnerability, at: https://www.ruby-lang.org/en/security/
+Japanese version is here: https://www.ruby-lang.org/ja/security/
+
+Security vulnerabilities should be reported via an email to
+mailto:security@ruby-lang.org ({the PGP public
+key}[https://www.ruby-lang.org/security.asc]), which is a private mailing list.
+Reported problems will be published after fixes.
+
+== +Marshal.load+
+
+Ruby's +Marshal+ module provides methods for serializing and deserializing Ruby
+object trees to and from a binary data format.
+
+Never use +Marshal.load+ to deserialize untrusted or user supplied data.
+Because +Marshal+ can deserialize to almost any Ruby object and has full
+control over instance variables, it is possible to craft a malicious payload
+that executes code shortly after deserialization.
+
+If you need to deserialize untrusted data, you should use JSON as it is only
+capable of returning 'primitive' types such as strings, arrays, hashes, numbers
+and nil. If you need to deserialize other classes, you should handle this
+manually. Never deserialize to a user specified class.
+
+== YAML
+
+YAML is a popular human readable data serialization format used by many Ruby
+programs for configuration and database persistence of Ruby object trees.
+
+Similar to +Marshal+, it is able to deserialize into arbitrary Ruby classes.
+For example, the following YAML data will create an +ERB+ object when
+deserialized, using the +unsafe_load+ method:
+
+ !ruby/object:ERB
+ src: puts `uname`
+
+Because of this, many of the security considerations applying to Marshal are
+also applicable to YAML. Do not use YAML to deserialize untrusted data.
+
+== Symbols
+
+Symbols are often seen as syntax sugar for simple strings, but they play a much
+more crucial role. The MRI Ruby implementation uses Symbols internally for
+method, variable and constant names. The reason for this is that symbols are
+simply integers with names attached to them, so they are faster to look up in
+hashtables.
+
+Most symbols can be garbage collected; these are called _mortal_
+symbols. Most symbols you create (e.g. by calling +to_sym+) are mortal.
+
+_Immortal_ symbols on the other hand will never be garbage collected.
+They are created when modifying code:
+* defining a method (e.g. with +define_method+),
+* setting an instance variable (e.g. with +instance_variable_set+),
+* creating a variable or constant (e.g. with +const_set+)
+C extensions that have not been updated and are still calling +SYM2ID+
+will create immortal symbols.
+
+Don't create immortal symbols from user inputs. Otherwise, this would
+allow a user to mount a denial of service attack against your application by
+flooding it with unique strings, which will cause memory to grow indefinitely
+until the Ruby process is killed or causes the system to slow to a halt.
+
+While it might not be a good idea to call these with user inputs, methods that
+used to be vulnerable such as +to_sym+, +respond_to?+,
++method+, +instance_variable_get+, +const_get+, etc. are no longer a threat.
+
+== Regular expressions
+
+Ruby's regular expression syntax has some minor differences when compared to
+other languages. In Ruby, the <code>^</code> and <code>$</code> anchors do not
+refer to the beginning and end of the string, rather the beginning and end of a
+*line*.
+
+This means that if you're using a regular expression like
+<code>/^[a-z]+$/</code> to restrict a string to only letters, an attacker can
+bypass this check by passing a string containing a letter, then a newline, then
+any string of their choosing.
+
+If you want to match the beginning and end of the entire string in Ruby, use
+the anchors +\A+ and +\z+.
+
+== +eval+
+
+Never pass untrusted or user controlled input to +eval+.
+
+Unless you are implementing a REPL like +irb+ or +pry+, +eval+ is almost
+certainly not what you want. Do not attempt to filter user input before passing
+it to +eval+ - this approach is fraught with danger and will most likely open
+your application up to a serious remote code execution vulnerability.
+
+== +send+
+
+'Global functions' in Ruby (+puts+, +exit+, etc.) are actually private instance
+methods on +Object+. This means it is possible to invoke these methods with
++send+, even if the call to +send+ has an explicit receiver.
+
+For example, the following code snippet writes "Hello world" to the terminal:
+
+ 1.send(:puts, "Hello world")
+
+You should never call +send+ with user supplied input as the first parameter.
+Doing so can introduce a denial of service vulnerability:
+
+ foo.send(params[:bar]) # params[:bar] is "exit!"
+
+If an attacker can control the first two arguments to +send+, remote code
+execution is possible:
+
+ # params is { :a => "eval", :b => "...ruby code to be executed..." }
+ foo.send(params[:a], params[:b])
+
+When dispatching a method call based on user input, carefully verify that the
+method name. If possible, check it against a whitelist of safe method names.
+
+Note that the use of +public_send+ is also dangerous, as +send+ itself is
+public:
+
+ 1.public_send("send", "eval", "...ruby code to be executed...")
diff --git a/doc/signals.rdoc b/doc/signals.rdoc
deleted file mode 100644
index 403eb66549..0000000000
--- a/doc/signals.rdoc
+++ /dev/null
@@ -1,106 +0,0 @@
-= Caveats for implementing Signal.trap callbacks
-
-As with implementing signal handlers in C or most other languages,
-all code passed to Signal.trap must be reentrant. If you are not
-familiar with reentrancy, you need to read up on it at
-{Wikipedia}[https://en.wikipedia.org/wiki/Reentrancy_(computing)] or
-elsewhere before reading the rest of this document.
-
-Most importantly, "thread-safety" does not guarantee reentrancy;
-and methods such as Mutex#lock and Mutex#synchronize which are
-commonly used for thread-safety even prevent reentrancy.
-
-== An implementation detail of the Ruby VM
-
-The Ruby VM defers Signal.trap callbacks from running until it is safe
-for its internal data structures, but it does not know when it is safe
-for data structures in YOUR code. Ruby implements deferred signal
-handling by registering short C functions with only
-{async-signal-safe functions}[http://man7.org/linux/man-pages/man7/signal-safety.7.html] as
-signal handlers. These short C functions only do enough tell the VM to
-run callbacks registered via Signal.trap later in the main Ruby Thread.
-
-== Unsafe methods to call in Signal.trap blocks
-
-When in doubt, consider anything not listed as safe below as being
-unsafe.
-
-* Mutex#lock, Mutex#synchronize and any code using them are explicitly
- unsafe. This includes Monitor in the standard library which uses
- Mutex to provide reentrancy.
-
-* Dir.chdir with block
-
-* any IO write operations when IO#sync is false;
- including IO#write, IO#write_nonblock, IO#puts.
- Pipes and sockets default to `IO#sync = true', so it is safe to
- write to them unless IO#sync was disabled.
-
-* File#flock, as the underlying flock(2) call is not specified by POSIX
-
-== Commonly safe operations inside Signal.trap blocks
-
-* Assignment and retrieval of local, instance, and class variables
-
-* Most object allocations and initializations of common types
- including Array, Hash, String, Struct, Time.
-
-* Common Array, Hash, String, Struct operations which do not execute a block
- are generally safe; but beware if iteration is occurring elsewhere.
-
-* Hash#[], Hash#[]= (unless Hash.new was given an unsafe block)
-
-* Thread::Queue#push and Thread::SizedQueue#push (since Ruby 2.1)
-
-* Creating a new Thread via Thread.new/Thread.start can used to get
- around the unusability of Mutexes inside a signal handler
-
-* Signal.trap is safe to use inside blocks passed to Signal.trap
-
-* arithmetic on Integer and Float (`+', `-', '%', '*', '/')
-
- Additionally, signal handlers do not run between two successive
- local variable accesses, so shortcuts such as `+=' and `-=' will
- not trigger a data race when used on Integer and Float classes in
- signal handlers.
-
-== System call wrapper methods which are safe inside Signal.trap
-
-Since Ruby has wrappers around many
-{async-signal-safe C functions}[http://man7.org/linux/man-pages/man7/signal-safety.7.html]
-the corresponding wrappers for many IO, File, Dir, and Socket methods
-are safe.
-
-(Incomplete list)
-
-* Dir.chdir (without block arg)
-* Dir.mkdir
-* Dir.open
-* File#truncate
-* File.link
-* File.open
-* File.readlink
-* File.rename
-* File.stat
-* File.symlink
-* File.truncate
-* File.unlink
-* File.utime
-* IO#close
-* IO#dup
-* IO#fsync
-* IO#read
-* IO#read_nonblock
-* IO#stat
-* IO#sysread
-* IO#syswrite
-* IO.select
-* IO.pipe
-* Process.clock_gettime
-* Process.exit!
-* Process.fork
-* Process.kill
-* Process.pid
-* Process.ppid
-* Process.waitpid
-...
diff --git a/doc/standard_library.md b/doc/standard_library.md
new file mode 100644
index 0000000000..7a477283a9
--- /dev/null
+++ b/doc/standard_library.md
@@ -0,0 +1,225 @@
+# Ruby Standard Library
+
+The Ruby Standard Library is a large collection of classes and modules you can
+require in your code to gain additional features.
+
+Below is an overview of the libraries and extensions, followed by a brief description
+of each.
+
+## Libraries
+
+- `MakeMakefile`: A module used to generate a Makefile for C extensions
+- `RbConfig`: Information about your Ruby configuration and build
+- `Gem`: A package management framework for Ruby
+
+## Extensions
+
+- `Coverage`: Provides coverage measurement for Ruby
+- `Monitor`: Provides a reentrant mutex
+- `objspace`: Extends the ObjectSpace module to add methods for internal statistics
+- `PTY`: Creates and manages pseudo-terminals
+- `Ripper`: Provides an interface for parsing Ruby programs into S-expressions
+- `Socket`: Accesses underlying OS socket implementations
+
+# Default gems
+
+- Default gems are shipped with Ruby releases and also available as rubygems.
+- Default gems are not uninstallable from the Ruby installation.
+- Default gems can be updated using rubygems.
+ - e.g. `gem update json`
+- Default gems can be used with bundler environments like `unbundled_env`.
+- Default gems can be used at any version in a Gemfile.
+ - e.g. `gem "json", ">= 2.6"`
+
+## Libraries
+
+- Bundler ([GitHub][bundler]): Manage your Ruby application's gem dependencies
+- Delegator ([GitHub][delegate]): Provides three abilities to delegate method calls to an object
+- DidYouMean ([GitHub][did_you_mean]): "Did you mean?" experience in Ruby
+- English ([GitHub][English]): Provides references to special global variables with less cryptic names
+- ERB ([GitHub][erb]): An easy-to-use but powerful templating system for Ruby
+- ErrorHighlight ([GitHub][error_highlight]): Highlight error locations in your code
+- FileUtils ([GitHub][fileutils]): Several file utility methods for copying, moving, removing, etc.
+- Find ([GitHub][find]): This module supports top-down traversal of a set of file paths
+- Forwardable ([GitHub][forwardable]): Provides delegation of specified methods to a designated object
+- IPAddr ([GitHub][ipaddr]): Provides methods to manipulate IPv4 and IPv6 IP addresses
+- OptionParser ([GitHub][optparse]): Ruby-oriented class for command-line option analysis
+- Net::HTTP ([GitHub][net-http]): HTTP client API for Ruby
+- Open3 ([GitHub][open3]): Provides access to stdin, stdout, and stderr when running other programs
+- OpenURI ([GitHub][open-uri]): An easy-to-use wrapper for URI::HTTP, URI::HTTPS, and URI::FTP
+- PP ([GitHub][pp]): Provides a PrettyPrinter for Ruby objects
+- PrettyPrint ([GitHub][prettyprint]): Implements a pretty printing algorithm for readable structure
+- Prism ([GitHub][prism]): A portable, error-tolerant Ruby parser
+- Resolv ([GitHub][resolv]): Thread-aware DNS resolver library in Ruby
+- SecureRandom ([GitHub][securerandom]): Interface for a secure random number generator
+- Shellwords ([GitHub][shellwords]): Manipulates strings with the word parsing rules of the UNIX Bourne shell
+- Singleton ([GitHub][singleton]): Implementation of the Singleton pattern for Ruby
+- Tempfile ([GitHub][tempfile]): A utility class for managing temporary files
+- Time ([GitHub][time]): Extends the Time class with methods for parsing and conversion
+- Timeout ([GitHub][timeout]): Auto-terminate potentially long-running operations in Ruby
+- TmpDir ([GitHub][tmpdir]): Extends the Dir class to manage the OS temporary file path
+- UN ([GitHub][un]): Utilities to replace common UNIX commands
+- URI ([GitHub][uri]): A Ruby module providing support for Uniform Resource Identifiers
+- YAML ([GitHub][yaml]): The Ruby client library for the Psych YAML implementation
+- WeakRef ([GitHub][weakref]): Allows a referenced object to be garbage-collected
+
+## Extensions
+
+- Date ([GitHub][date]): Represents dates, with a subclass for dates with time and timezones
+- Digest ([GitHub][digest]): Provides a framework for message digest libraries
+- Etc ([GitHub][etc]): Provides access to information typically stored in the UNIX /etc directory
+- Fcntl ([GitHub][fcntl]): Loads constants defined in the OS fcntl.h C header file
+- IO.console ([GitHub][io-console]): Extensions for the IO class, including `IO.console`, `IO.winsize`, etc.
+- IO#nonblock ([GitHub][io-nonblock]): Enable non-blocking mode with IO class.
+- IO#wait ([GitHub][io-wait]): Provides the feature for waiting until IO is readable or writable without blocking.
+- JSON ([GitHub][json]): Implements JavaScript Object Notation for Ruby
+- OpenSSL ([GitHub][openssl]): Provides SSL, TLS, and general-purpose cryptography for Ruby
+- Pathname ([GitHub][pathname]): Representation of the name of a file or directory on the filesystem
+- Psych ([GitHub][psych]): A YAML parser and emitter for Ruby
+- StringIO ([GitHub][stringio]): Pseudo-I/O on String objects
+- StringScanner ([GitHub][strscan]): Provides lexical scanning operations on a String
+- Zlib ([GitHub][zlib]): Ruby interface for the zlib compression/decompression library
+
+# Bundled gems
+
+- Bundled gems are shipped with Ruby releases and also available as rubygems.
+ - They are only bundled with Ruby releases.
+ - They can be uninstalled from the Ruby installation.
+ - They need to be declared in a Gemfile when used with bundler.
+
+## Libraries
+
+- [minitest]: A test library supporting TDD, BDD, mocking, and benchmarking
+- [power_assert]: Power Assert for Ruby
+- [rake][rake-doc] ([GitHub][rake]): Ruby build program with capabilities similar to make
+- [test-unit]: A compatibility layer for MiniTest
+- [rexml][rexml-doc] ([GitHub][rexml]): An XML toolkit for Ruby
+- [rss]: A family of libraries supporting various XML-based "feeds"
+- [net-ftp]: Support for the File Transfer Protocol
+- [net-imap]: Ruby client API for the Internet Message Access Protocol
+- [net-pop]: Ruby client library for POP3
+- [net-smtp]: Simple Mail Transfer Protocol client library for Ruby
+- [matrix]: Represents a mathematical matrix
+- [prime]: Prime numbers and factorization library
+- [rbs]: RBS is a language to describe the structure of Ruby programs
+- [typeprof]: A type analysis tool for Ruby code based on abstract interpretation
+- [debug]: Debugging functionality for Ruby
+- [racc][racc-doc] ([GitHub][racc]): A LALR(1) parser generator written in Ruby
+- [mutex_m]: Mixin to extend objects to be handled like a Mutex
+- [getoptlong]: Parse command line options similar to the GNU C getopt_long()
+- [base64]: Support for encoding and decoding binary data using a Base64 representation
+- [bigdecimal]: Provides arbitrary-precision floating point decimal arithmetic
+- [observer]: Provides a mechanism for the publish/subscribe pattern in Ruby
+- [abbrev]: Calculates a set of unique abbreviations for a given set of strings
+- [resolv-replace]: Replace Socket DNS with Resolv
+- [rinda]: The Linda distributed computing paradigm in Ruby
+- [drb]: Distributed object system for Ruby
+- [nkf]: Ruby extension for the Network Kanji Filter
+- [syslog]: Ruby interface for the POSIX system logging facility
+- [csv][csv-doc] ([GitHub][csv]): Provides an interface to read and write CSV files and data
+- [ostruct]: A class to build custom data structures, similar to a Hash
+- [benchmark]: Provides methods to measure and report the time used to execute code
+- [logger][logger-doc] ([GitHub][logger]): Provides a simple logging utility for outputting messages
+- [pstore]: Implements a file-based persistence mechanism based on a Hash
+- [win32ole]: Provides an interface for OLE Automation in Ruby
+- [reline][reline-doc] ([GitHub][reline]): GNU Readline and Editline in a pure Ruby implementation
+- [readline]: Wrapper for the Readline extension and Reline
+- [fiddle]: A libffi wrapper for Ruby
+- [tsort]: Topological sorting using Tarjan's algorithm
+
+## Tools
+
+- [IRB][irb-doc] ([GitHub][irb]): Interactive Ruby command-line tool for REPL (Read Eval Print Loop)
+- [RDoc][rdoc-doc] ([GitHub][rdoc]): Documentation generator for Ruby
+
+[abbrev]: https://github.com/ruby/abbrev
+[base64]: https://github.com/ruby/base64
+[benchmark]: https://github.com/ruby/benchmark
+[bigdecimal]: https://github.com/ruby/bigdecimal
+[bundler]: https://github.com/rubygems/rubygems
+[csv]: https://github.com/ruby/csv
+[date]: https://github.com/ruby/date
+[debug]: https://github.com/ruby/debug
+[delegate]: https://github.com/ruby/delegate
+[did_you_mean]: https://github.com/ruby/did_you_mean
+[digest]: https://github.com/ruby/digest
+[drb]: https://github.com/ruby/drb
+[English]: https://github.com/ruby/English
+[erb]: https://github.com/ruby/erb
+[error_highlight]: https://github.com/ruby/error_highlight
+[etc]: https://github.com/ruby/etc
+[fcntl]: https://github.com/ruby/fcntl
+[fiddle]: https://github.com/ruby/fiddle
+[fileutils]: https://github.com/ruby/fileutils
+[find]: https://github.com/ruby/find
+[forwardable]: https://github.com/ruby/forwardable
+[getoptlong]: https://github.com/ruby/getoptlong
+[io-console]: https://github.com/ruby/io-console
+[io-nonblock]: https://github.com/ruby/io-nonblock
+[io-wait]: https://github.com/ruby/io-wait
+[ipaddr]: https://github.com/ruby/ipaddr
+[irb]: https://github.com/ruby/irb
+[json]: https://github.com/ruby/json
+[logger]: https://github.com/ruby/logger
+[matrix]: https://github.com/ruby/matrix
+[minitest]: https://github.com/seattlerb/minitest
+[mutex_m]: https://github.com/ruby/mutex_m
+[net-ftp]: https://github.com/ruby/net-ftp
+[net-http]: https://github.com/ruby/net-http
+[net-imap]: https://github.com/ruby/net-imap
+[net-pop]: https://github.com/ruby/net-pop
+[net-smtp]: https://github.com/ruby/net-smtp
+[nkf]: https://github.com/ruby/nkf
+[observer]: https://github.com/ruby/observer
+[open-uri]: https://github.com/ruby/open-uri
+[open3]: https://github.com/ruby/open3
+[openssl]: https://github.com/ruby/openssl
+[optparse]: https://github.com/ruby/optparse
+[ostruct]: https://github.com/ruby/ostruct
+[pathname]: https://github.com/ruby/pathname
+[power_assert]: https://github.com/ruby/power_assert
+[pp]: https://github.com/ruby/pp
+[prettyprint]: https://github.com/ruby/prettyprint
+[prime]: https://github.com/ruby/prime
+[prism]: https://github.com/ruby/prism
+[pstore]: https://github.com/ruby/pstore
+[psych]: https://github.com/ruby/psych
+[racc]: https://github.com/ruby/racc
+[rake]: https://github.com/ruby/rake
+[rbs]: https://github.com/ruby/rbs
+[rdoc]: https://github.com/ruby/rdoc
+[readline]: https://github.com/ruby/readline
+[reline]: https://github.com/ruby/reline
+[resolv-replace]: https://github.com/ruby/resolv-replace
+[resolv]: https://github.com/ruby/resolv
+[rexml]: https://github.com/ruby/rexml
+[rinda]: https://github.com/ruby/rinda
+[rss]: https://github.com/ruby/rss
+[securerandom]: https://github.com/ruby/securerandom
+[shellwords]: https://github.com/ruby/shellwords
+[singleton]: https://github.com/ruby/singleton
+[stringio]: https://github.com/ruby/stringio
+[strscan]: https://github.com/ruby/strscan
+[syslog]: https://github.com/ruby/syslog
+[tempfile]: https://github.com/ruby/tempfile
+[test-unit]: https://github.com/test-unit/test-unit
+[time]: https://github.com/ruby/time
+[timeout]: https://github.com/ruby/timeout
+[tmpdir]: https://github.com/ruby/tmpdir
+[tsort]: https://github.com/ruby/tsort
+[typeprof]: https://github.com/ruby/typeprof
+[un]: https://github.com/ruby/un
+[uri]: https://github.com/ruby/uri
+[weakref]: https://github.com/ruby/weakref
+[win32ole]: https://github.com/ruby/win32ole
+[yaml]: https://github.com/ruby/yaml
+[zlib]: https://github.com/ruby/zlib
+
+[reline-doc]: https://ruby.github.io/reline/
+[rake-doc]: https://ruby.github.io/rake/
+[irb-doc]: https://ruby.github.io/irb/
+[rdoc-doc]: https://ruby.github.io/rdoc/
+[logger-doc]: https://ruby.github.io/logger/
+[racc-doc]: https://ruby.github.io/racc/
+[csv-doc]: https://ruby.github.io/csv/
+[rexml-doc]: https://ruby.github.io/rexml/
diff --git a/doc/standard_library.rdoc b/doc/standard_library.rdoc
deleted file mode 100644
index a9fca632f8..0000000000
--- a/doc/standard_library.rdoc
+++ /dev/null
@@ -1,132 +0,0 @@
-= Ruby Standard Library
-
-The Ruby Standard Library is a vast collection of classes and modules that you
-can require in your code for additional features.
-
-Below is an overview of libraries and extensions followed by a brief
-description.
-
-== Libraries
-
-MakeMakefile:: Module used to generate a Makefile for C extensions
-RbConfig:: Information of your configure and build of Ruby
-Gem:: Package management framework for Ruby
-
-== Extensions
-
-Coverage:: Provides coverage measurement for Ruby
-Monitor:: Provides an object or module to use safely by more than one thread
-objspace:: Extends ObjectSpace module to add methods for internal statistics
-PTY:: Creates and manages pseudo terminals
-Ripper:: Provides an interface for parsing Ruby programs into S-expressions
-Socket:: Access underlying OS socket implementations
-
-= Default gems
-
-* default gems are shipped with Ruby releases and also available as rubygems.
-* default gems are not uninstallable from Ruby installation.
-* default gems can be updated used by rubygems.
- * e.g. `gem update json`
-* default gems can be used with bundler environment like `unbundled_env`.
-* default gems can be used any version on Gemfile.
- * e.g. `gem "json", ">= 2.6"`
-
-== Libraries
-
-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
-Delegator:: Provides three abilities to delegate method calls to an object
-DidYouMean:: "Did you mean?" experience in Ruby
-English:: Provides references to special global variables with less cryptic names
-ERB:: An easy to use but powerful templating system for Ruby
-ErrorHighlight:: Highlight error location in your code
-FileUtils:: Several file utility methods for copying, moving, removing, etc
-Find:: This module supports top-down traversal of a set of file paths
-Forwardable:: Provides delegation of specified methods to a designated object
-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
-Net::HTTP:: HTTP client api for Ruby
-Open3:: Provides access to stdin, stdout and stderr when running other programs
-OpenStruct:: Class to build custom data structures, similar to a Hash
-OpenURI:: An easy-to-use wrapper for Net::HTTP, Net::HTTPS and Net::FTP
-PP:: Provides a PrettyPrinter for Ruby objects
-PrettyPrinter:: Implements a pretty printing algorithm for readable structure
-Prism:: A portable, error-tolerant Ruby parser
-PStore:: Implements a file based persistence mechanism based on a Hash
-Readline:: Wrapper for Readline extencion and Reline
-Reline:: GNU Readline and Editline by pure Ruby implementation.
-Resolv:: Thread-aware DNS resolver library in Ruby
-RDoc:: Produces HTML and command-line documentation 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
-Singleton:: Implementation of the Singleton pattern for Ruby
-Tempfile:: A utility class for managing temporary files
-Time:: Extends the Time class with methods for parsing and conversion
-Timeout:: Auto-terminate potentially long-running operations in Ruby
-tmpdir.rb:: Extends the Dir class to manage the OS temporary file path
-TSort:: Topological sorting using Tarjan's algorithm
-un.rb:: Utilities to replace common UNIX commands
-URI:: A Ruby module providing support for Uniform Resource Identifiers
-YAML:: Ruby client library for the Psych YAML implementation
-WeakRef:: Allows a referenced object to be garbage-collected
-
-== Extensions
-
-Date:: A subclass of Object includes Comparable module for handling dates
-DateTime:: Subclass of Date to handling dates, hours, minutes, seconds, offsets
-Digest:: Provides a framework for message digest libraries
-Etc:: Provides access to information typically stored in UNIX /etc directory
-Fcntl:: Loads constants defined in the OS fcntl.h C header file
-Fiddle:: A libffi wrapper for Ruby
-IO:: Extensions for Ruby IO class, including #wait, #nonblock and ::console
-JSON:: Implements Javascript Object Notation for Ruby
-OpenSSL:: Provides SSL, TLS and general purpose cryptography for Ruby
-Pathname:: Representation of the name of a file or directory on the filesystem
-Psych:: A YAML parser and emitter for Ruby
-StringIO:: Pseudo I/O on String objects
-StringScanner:: Provides lexical scanning operations on a String
-WIN32OLE:: Provides an interface for OLE Automation in Ruby
-Zlib:: Ruby interface for the zlib compression/decompression library
-
-= Bundled gems
-
-* bundled gems are shipped with Ruby releases and also available as rubygems.
-* bundled gems are same as normal gems like `rails`, `rack`.
- * They are only bundled with Ruby releases.
- * They can be uninstallable from Ruby installation.
- * They are needed to declare in Gemfile when use with bundler.
-
-== Libraries
-
-MiniTest:: A test suite with TDD, BDD, mocking and benchmarking
-PowerAssert:: Power Assert for Ruby.
-Rake:: Ruby build program with capabilities similar to make
-Test::Unit:: A compatibility layer for MiniTest
-REXML:: An XML toolkit for Ruby
-RSS:: Family of libraries that support various formats of XML "feeds"
-Net::FTP:: Support for the File Transfer Protocol
-Net::IMAP:: Ruby client api for Internet Message Access Protocol
-Net::POP3:: Ruby client library for POP3
-Net::SMTP:: Simple Mail Transfer Protocol client library for Ruby
-Matrix:: Represents a mathematical matrix.
-Prime:: Prime numbers and factorization library
-RBS:: RBS is a language to describe the structure of Ruby programs
-TypeProf:: A type analysis tool for Ruby code based on abstract interpretation
-DEBUGGER__:: Debugging functionality for Ruby
-Racc:: A LALR(1) parser generator written in Ruby.
-Mutex_m:: Mixin to extend objects to be handled like a Mutex
-GetoptLong:: Parse command line options similar to the GNU C getopt_long()
-Base64:: Support for encoding and decoding binary data using a Base64 representation
-BigDecimal:: Provides arbitrary-precision floating point decimal arithmetic
-Observable:: Provides a mechanism for publish/subscribe pattern in Ruby
-Abbrev:: Calculates a set of unique abbreviations for a given set of strings
-resolv-replace.rb:: Replace Socket DNS with Resolv
-Rinda:: The Linda distributed computing paradigm in Ruby
-DRb:: Distributed object system for Ruby
-NKF:: Ruby extension for Network Kanji Filter
-Syslog:: Ruby interface for the POSIX system logging facility
-CSV:: Provides an interface to read and write CSV files and data
diff --git a/doc/strftime_formatting.rdoc b/doc/strftime_formatting.rdoc
deleted file mode 100644
index 5c7b33155d..0000000000
--- a/doc/strftime_formatting.rdoc
+++ /dev/null
@@ -1,527 +0,0 @@
-= Formats for Dates and Times
-
-Several Ruby time-related classes have instance method +strftime+,
-which returns a formatted string representing all or part of a date or time:
-
-- Date#strftime.
-- DateTime#strftime.
-- Time#strftime.
-
-Each of these methods takes optional argument +format+,
-which has zero or more embedded _format_ _specifications_ (see below).
-
-Each of these methods returns the string resulting from replacing each
-format specification embedded in +format+ with a string form
-of one or more parts of the date or time.
-
-A simple example:
-
- Time.now.strftime('%H:%M:%S') # => "14:02:07"
-
-A format specification has the form:
-
- %[flags][width]conversion
-
-It consists of:
-
-- A leading percent character.
-- Zero or more _flags_ (each is a character).
-- An optional _width_ _specifier_ (an integer).
-- A _conversion_ _specifier_ (a character).
-
-Except for the leading percent character,
-the only required part is the conversion specifier, so we begin with that.
-
-== Conversion Specifiers
-
-=== \Date (Year, Month, Day)
-
-- <tt>%Y</tt> - Year including century, zero-padded:
-
- Time.now.strftime('%Y') # => "2022"
- Time.new(-1000).strftime('%Y') # => "-1000" # Before common era.
- Time.new(10000).strftime('%Y') # => "10000" # Far future.
- Time.new(10).strftime('%Y') # => "0010" # Zero-padded by default.
-
-- <tt>%y</tt> - Year without century, in range (0.99), zero-padded:
-
- Time.now.strftime('%y') # => "22"
- Time.new(1).strftime('%y') # => "01" # Zero-padded by default.
-
-- <tt>%C</tt> - Century, zero-padded:
-
- Time.now.strftime('%C') # => "20"
- Time.new(-1000).strftime('%C') # => "-10" # Before common era.
- Time.new(10000).strftime('%C') # => "100" # Far future.
- Time.new(100).strftime('%C') # => "01" # Zero-padded by default.
-
-- <tt>%m</tt> - Month of the year, in range (1..12), zero-padded:
-
- Time.new(2022, 1).strftime('%m') # => "01" # Zero-padded by default.
- Time.new(2022, 12).strftime('%m') # => "12"
-
-- <tt>%B</tt> - Full month name, capitalized:
-
- Time.new(2022, 1).strftime('%B') # => "January"
- Time.new(2022, 12).strftime('%B') # => "December"
-
-- <tt>%b</tt> - Abbreviated month name, capitalized:
-
- Time.new(2022, 1).strftime('%b') # => "Jan"
- Time.new(2022, 12).strftime('%h') # => "Dec"
-
-- <tt>%h</tt> - Same as <tt>%b</tt>.
-
-- <tt>%d</tt> - Day of the month, in range (1..31), zero-padded:
-
- Time.new(2002, 1, 1).strftime('%d') # => "01"
- Time.new(2002, 1, 31).strftime('%d') # => "31"
-
-- <tt>%e</tt> - Day of the month, in range (1..31), blank-padded:
-
- Time.new(2002, 1, 1).strftime('%e') # => " 1"
- Time.new(2002, 1, 31).strftime('%e') # => "31"
-
-- <tt>%j</tt> - Day of the year, in range (1..366), zero-padded:
-
- Time.new(2002, 1, 1).strftime('%j') # => "001"
- Time.new(2002, 12, 31).strftime('%j') # => "365"
-
-=== \Time (Hour, Minute, Second, Subsecond)
-
-- <tt>%H</tt> - Hour of the day, in range (0..23), zero-padded:
-
- Time.new(2022, 1, 1, 1).strftime('%H') # => "01"
- Time.new(2022, 1, 1, 13).strftime('%H') # => "13"
-
-- <tt>%k</tt> - Hour of the day, in range (0..23), blank-padded:
-
- Time.new(2022, 1, 1, 1).strftime('%k') # => " 1"
- Time.new(2022, 1, 1, 13).strftime('%k') # => "13"
-
-- <tt>%I</tt> - Hour of the day, in range (1..12), zero-padded:
-
- Time.new(2022, 1, 1, 1).strftime('%I') # => "01"
- Time.new(2022, 1, 1, 13).strftime('%I') # => "01"
-
-- <tt>%l</tt> - Hour of the day, in range (1..12), blank-padded:
-
- Time.new(2022, 1, 1, 1).strftime('%l') # => " 1"
- Time.new(2022, 1, 1, 13).strftime('%l') # => " 1"
-
-- <tt>%P</tt> - Meridian indicator, lowercase:
-
- Time.new(2022, 1, 1, 1).strftime('%P') # => "am"
- Time.new(2022, 1, 1, 13).strftime('%P') # => "pm"
-
-- <tt>%p</tt> - Meridian indicator, uppercase:
-
- Time.new(2022, 1, 1, 1).strftime('%p') # => "AM"
- Time.new(2022, 1, 1, 13).strftime('%p') # => "PM"
-
-- <tt>%M</tt> - Minute of the hour, in range (0..59), zero-padded:
-
- Time.new(2022, 1, 1, 1, 0, 0).strftime('%M') # => "00"
-
-- <tt>%S</tt> - Second of the minute in range (0..59), zero-padded:
-
- Time.new(2022, 1, 1, 1, 0, 0, 0).strftime('%S') # => "00"
-
-- <tt>%L</tt> - Millisecond of the second, in range (0..999), zero-padded:
-
- Time.new(2022, 1, 1, 1, 0, 0, 0).strftime('%L') # => "000"
-
-- <tt>%N</tt> - Fractional seconds, default width is 9 digits (nanoseconds):
-
- t = Time.now # => 2022-06-29 07:10:20.3230914 -0500
- t.strftime('%N') # => "323091400" # Default.
-
- Use {width specifiers}[rdoc-ref:strftime_formatting.rdoc@Width+Specifiers]
- to adjust units:
-
- t.strftime('%3N') # => "323" # Milliseconds.
- t.strftime('%6N') # => "323091" # Microseconds.
- t.strftime('%9N') # => "323091400" # Nanoseconds.
- t.strftime('%12N') # => "323091400000" # Picoseconds.
- t.strftime('%15N') # => "323091400000000" # Femptoseconds.
- t.strftime('%18N') # => "323091400000000000" # Attoseconds.
- t.strftime('%21N') # => "323091400000000000000" # Zeptoseconds.
- t.strftime('%24N') # => "323091400000000000000000" # Yoctoseconds.
-
-- <tt>%s</tt> - Number of seconds since the epoch:
-
- Time.now.strftime('%s') # => "1656505136"
-
-=== Timezone
-
-- <tt>%z</tt> - Timezone as hour and minute offset from UTC:
-
- Time.now.strftime('%z') # => "-0500"
-
-- <tt>%Z</tt> - Timezone name (platform-dependent):
-
- Time.now.strftime('%Z') # => "Central Daylight Time"
-
-=== Weekday
-
-- <tt>%A</tt> - Full weekday name:
-
- Time.now.strftime('%A') # => "Wednesday"
-
-- <tt>%a</tt> - Abbreviated weekday name:
-
- Time.now.strftime('%a') # => "Wed"
-
-- <tt>%u</tt> - Day of the week, in range (1..7), Monday is 1:
-
- t = Time.new(2022, 6, 26) # => 2022-06-26 00:00:00 -0500
- t.strftime('%a') # => "Sun"
- t.strftime('%u') # => "7"
-
-- <tt>%w</tt> - Day of the week, in range (0..6), Sunday is 0:
-
- t = Time.new(2022, 6, 26) # => 2022-06-26 00:00:00 -0500
- t.strftime('%a') # => "Sun"
- t.strftime('%w') # => "0"
-
-=== Week Number
-
-- <tt>%U</tt> - Week number of the year, in range (0..53), zero-padded,
- where each week begins on a Sunday:
-
- t = Time.new(2022, 6, 26) # => 2022-06-26 00:00:00 -0500
- t.strftime('%a') # => "Sun"
- t.strftime('%U') # => "26"
-
-- <tt>%W</tt> - Week number of the year, in range (0..53), zero-padded,
- where each week begins on a Monday:
-
- t = Time.new(2022, 6, 26) # => 2022-06-26 00:00:00 -0500
- t.strftime('%a') # => "Sun"
- t.strftime('%W') # => "25"
-
-=== Week Dates
-
-See {ISO 8601 week dates}[https://en.wikipedia.org/wiki/ISO_8601#Week_dates].
-
- t0 = Time.new(2023, 1, 1) # => 2023-01-01 00:00:00 -0600
- t1 = Time.new(2024, 1, 1) # => 2024-01-01 00:00:00 -0600
-
-- <tt>%G</tt> - Week-based year:
-
- t0.strftime('%G') # => "2022"
- t1.strftime('%G') # => "2024"
-
-- <tt>%g</tt> - Week-based year without century, in range (0..99), zero-padded:
-
- t0.strftime('%g') # => "22"
- t1.strftime('%g') # => "24"
-
-- <tt>%V</tt> - Week number of the week-based year, in range (1..53),
- zero-padded:
-
- t0.strftime('%V') # => "52"
- t1.strftime('%V') # => "01"
-
-=== Literals
-
-- <tt>%n</tt> - Newline character "\n":
-
- Time.now.strftime('%n') # => "\n"
-
-- <tt>%t</tt> - Tab character "\t":
-
- Time.now.strftime('%t') # => "\t"
-
-- <tt>%%</tt> - Percent character '%':
-
- Time.now.strftime('%%') # => "%"
-
-=== Shorthand Conversion Specifiers
-
-Each shorthand specifier here is shown with its corresponding
-longhand specifier.
-
-- <tt>%c</tt> - \Date and time:
-
- Time.now.strftime('%c') # => "Wed Jun 29 08:01:41 2022"
- Time.now.strftime('%a %b %e %T %Y') # => "Wed Jun 29 08:02:07 2022"
-
-- <tt>%D</tt> - \Date:
-
- Time.now.strftime('%D') # => "06/29/22"
- Time.now.strftime('%m/%d/%y') # => "06/29/22"
-
-- <tt>%F</tt> - ISO 8601 date:
-
- Time.now.strftime('%F') # => "2022-06-29"
- Time.now.strftime('%Y-%m-%d') # => "2022-06-29"
-
-- <tt>%v</tt> - VMS date:
-
- Time.now.strftime('%v') # => "29-JUN-2022"
- Time.now.strftime('%e-%^b-%4Y') # => "29-JUN-2022"
-
-- <tt>%x</tt> - Same as <tt>%D</tt>.
-
-- <tt>%X</tt> - Same as <tt>%T</tt>.
-
-- <tt>%r</tt> - 12-hour time:
-
- Time.new(2022, 1, 1, 1).strftime('%r') # => "01:00:00 AM"
- Time.new(2022, 1, 1, 1).strftime('%I:%M:%S %p') # => "01:00:00 AM"
- Time.new(2022, 1, 1, 13).strftime('%r') # => "01:00:00 PM"
- Time.new(2022, 1, 1, 13).strftime('%I:%M:%S %p') # => "01:00:00 PM"
-
-- <tt>%R</tt> - 24-hour time:
-
- Time.new(2022, 1, 1, 1).strftime('%R') # => "01:00"
- Time.new(2022, 1, 1, 1).strftime('%H:%M') # => "01:00"
- Time.new(2022, 1, 1, 13).strftime('%R') # => "13:00"
- Time.new(2022, 1, 1, 13).strftime('%H:%M') # => "13:00"
-
-- <tt>%T</tt> - 24-hour time:
-
- Time.new(2022, 1, 1, 1).strftime('%T') # => "01:00:00"
- Time.new(2022, 1, 1, 1).strftime('%H:%M:%S') # => "01:00:00"
- Time.new(2022, 1, 1, 13).strftime('%T') # => "13:00:00"
- Time.new(2022, 1, 1, 13).strftime('%H:%M:%S') # => "13:00:00"
-
-- <tt>%+</tt> (not supported in Time#strftime) - \Date and time:
-
- DateTime.now.strftime('%+')
- # => "Wed Jun 29 08:31:53 -05:00 2022"
- DateTime.now.strftime('%a %b %e %H:%M:%S %Z %Y')
- # => "Wed Jun 29 08:32:18 -05:00 2022"
-
-== Flags
-
-Flags may affect certain formatting specifications.
-
-Multiple flags may be given with a single conversion specified;
-order does not matter.
-
-=== Padding Flags
-
-- <tt>0</tt> - Pad with zeroes:
-
- Time.new(10).strftime('%0Y') # => "0010"
-
-- <tt>_</tt> - Pad with blanks:
-
- Time.new(10).strftime('%_Y') # => " 10"
-
-- <tt>-</tt> - Don't pad:
-
- Time.new(10).strftime('%-Y') # => "10"
-
-=== Casing Flags
-
-- <tt>^</tt> - Upcase result:
-
- Time.new(2022, 1).strftime('%B') # => "January" # No casing flag.
- Time.new(2022, 1).strftime('%^B') # => "JANUARY"
-
-- <tt>#</tt> - Swapcase result:
-
- Time.now.strftime('%p') # => "AM"
- Time.now.strftime('%^p') # => "AM"
- Time.now.strftime('%#p') # => "am"
-
-=== Timezone Flags
-
-- <tt>:</tt> - Put timezone as colon-separated hours and minutes:
-
- Time.now.strftime('%:z') # => "-05:00"
-
-- <tt>::</tt> - Put timezone as colon-separated hours, minutes, and seconds:
-
- Time.now.strftime('%::z') # => "-05:00:00"
-
-== Width Specifiers
-
-The integer width specifier gives a minimum width for the returned string:
-
- Time.new(2002).strftime('%Y') # => "2002" # No width specifier.
- Time.new(2002).strftime('%10Y') # => "0000002002"
- Time.new(2002, 12).strftime('%B') # => "December" # No width specifier.
- Time.new(2002, 12).strftime('%10B') # => " December"
- Time.new(2002, 12).strftime('%3B') # => "December" # Ignored if too small.
-
-= Specialized Format Strings
-
-Here are a few specialized format strings,
-each based on an external standard.
-
-== HTTP Format
-
-The HTTP date format is based on
-{RFC 2616}[https://www.rfc-editor.org/rfc/rfc2616],
-and treats dates in the format <tt>'%a, %d %b %Y %T GMT'</tt>:
-
- d = Date.new(2001, 2, 3) # => #<Date: 2001-02-03>
- # Return HTTP-formatted string.
- httpdate = d.httpdate # => "Sat, 03 Feb 2001 00:00:00 GMT"
- # Return new date parsed from HTTP-formatted string.
- Date.httpdate(httpdate) # => #<Date: 2001-02-03>
- # Return hash parsed from HTTP-formatted string.
- Date._httpdate(httpdate)
- # => {:wday=>6, :mday=>3, :mon=>2, :year=>2001, :hour=>0, :min=>0, :sec=>0, :zone=>"GMT", :offset=>0}
-
-== RFC 3339 Format
-
-The RFC 3339 date format is based on
-{RFC 3339}[https://www.rfc-editor.org/rfc/rfc3339]:
-
- d = Date.new(2001, 2, 3) # => #<Date: 2001-02-03>
- # Return 3339-formatted string.
- rfc3339 = d.rfc3339 # => "2001-02-03T00:00:00+00:00"
- # Return new date parsed from 3339-formatted string.
- Date.rfc3339(rfc3339) # => #<Date: 2001-02-03>
- # Return hash parsed from 3339-formatted string.
- Date._rfc3339(rfc3339)
- # => {:year=>2001, :mon=>2, :mday=>3, :hour=>0, :min=>0, :sec=>0, :zone=>"+00:00", :offset=>0}
-
-== RFC 2822 Format
-
-The RFC 2822 date format is based on
-{RFC 2822}[https://www.rfc-editor.org/rfc/rfc2822],
-and treats dates in the format <tt>'%a, %-d %b %Y %T %z'</tt>]:
-
- d = Date.new(2001, 2, 3) # => #<Date: 2001-02-03>
- # Return 2822-formatted string.
- rfc2822 = d.rfc2822 # => "Sat, 3 Feb 2001 00:00:00 +0000"
- # Return new date parsed from 2822-formatted string.
- Date.rfc2822(rfc2822) # => #<Date: 2001-02-03>
- # Return hash parsed from 2822-formatted string.
- Date._rfc2822(rfc2822)
- # => {:wday=>6, :mday=>3, :mon=>2, :year=>2001, :hour=>0, :min=>0, :sec=>0, :zone=>"+0000", :offset=>0}
-
-== JIS X 0301 Format
-
-The JIS X 0301 format includes the
-{Japanese era name}[https://en.wikipedia.org/wiki/Japanese_era_name],
-and treats dates in the format <tt>'%Y-%m-%d'</tt>
-with the first letter of the romanized era name prefixed:
-
- d = Date.new(2001, 2, 3) # => #<Date: 2001-02-03>
- # Return 0301-formatted string.
- jisx0301 = d.jisx0301 # => "H13.02.03"
- # Return new date parsed from 0301-formatted string.
- Date.jisx0301(jisx0301) # => #<Date: 2001-02-03>
- # Return hash parsed from 0301-formatted string.
- Date._jisx0301(jisx0301) # => {:year=>2001, :mon=>2, :mday=>3}
-
-== ISO 8601 Format Specifications
-
-This section shows format specifications that are compatible with
-{ISO 8601}[https://en.wikipedia.org/wiki/ISO_8601].
-Details for various formats may be seen at the links.
-
-Examples in this section assume:
-
- t = Time.now # => 2022-06-29 16:49:25.465246 -0500
-
-=== Dates
-
-See {ISO 8601 dates}[https://en.wikipedia.org/wiki/ISO_8601#Dates].
-
-- {Years}[https://en.wikipedia.org/wiki/ISO_8601#Years]:
-
- - Basic year (+YYYY+):
-
- t.strftime('%Y') # => "2022"
-
- - Expanded year (<tt>±YYYYY</tt>):
-
- t.strftime('+%5Y') # => "+02022"
- t.strftime('-%5Y') # => "-02022"
-
-- {Calendar dates}[https://en.wikipedia.org/wiki/ISO_8601#Calendar_dates]:
-
- - Basic date (+YYYYMMDD+):
-
- t.strftime('%Y%m%d') # => "20220629"
-
- - Extended date (<tt>YYYY-MM-DD</tt>):
-
- t.strftime('%Y-%m-%d') # => "2022-06-29"
-
- - Reduced extended date (<tt>YYYY-MM</tt>):
-
- t.strftime('%Y-%m') # => "2022-06"
-
-- {Week dates}[https://en.wikipedia.org/wiki/ISO_8601#Week_dates]:
-
- - Basic date (+YYYYWww+ or +YYYYWwwD+):
-
- t.strftime('%Y%Ww') # => "202226w"
- t.strftime('%Y%Ww%u') # => "202226w3"
-
- - Extended date (<tt>YYYY-Www</tt> or <tt>YYYY-Www-D<tt>):
-
- t.strftime('%Y-%Ww') # => "2022-26w"
- t.strftime('%Y-%Ww-%u') # => "2022-26w-3"
-
-- {Ordinal dates}[https://en.wikipedia.org/wiki/ISO_8601#Ordinal_dates]:
-
- - Basic date (+YYYYDDD+):
-
- t.strftime('%Y%j') # => "2022180"
-
- - Extended date (<tt>YYYY-DDD</tt>):
-
- t.strftime('%Y-%j') # => "2022-180"
-
-=== Times
-
-See {ISO 8601 times}[https://en.wikipedia.org/wiki/ISO_8601#Times].
-
-- Times:
-
- - Basic time (+Thhmmss.sss+, +Thhmmss+, +Thhmm+, or +Thh+):
-
- t.strftime('T%H%M%S.%L') # => "T164925.465"
- t.strftime('T%H%M%S') # => "T164925"
- t.strftime('T%H%M') # => "T1649"
- t.strftime('T%H') # => "T16"
-
- - Extended time (+Thh:mm:ss.sss+, +Thh:mm:ss+, or +Thh:mm+):
-
- t.strftime('T%H:%M:%S.%L') # => "T16:49:25.465"
- t.strftime('T%H:%M:%S') # => "T16:49:25"
- t.strftime('T%H:%M') # => "T16:49"
-
-- {Time zone designators}[https://en.wikipedia.org/wiki/ISO_8601#Time_zone_designators]:
-
- - Timezone (+time+ represents a valid time,
- +hh+ represents a valid 2-digit hour,
- and +mm+ represents a valid 2-digit minute):
-
- - Basic timezone (<tt>time±hhmm</tt>, <tt>time±hh</tt>, or +timeZ+):
-
- t.strftime('T%H%M%S%z') # => "T164925-0500"
- t.strftime('T%H%M%S%z').slice(0..-3) # => "T164925-05"
- t.strftime('T%H%M%SZ') # => "T164925Z"
-
- - Extended timezone (<tt>time±hh:mm</tt>):
-
- t.strftime('T%H:%M:%S%z') # => "T16:49:25-0500"
-
- - See also:
-
- - {Local time (unqualified)}[https://en.wikipedia.org/wiki/ISO_8601#Local_time_(unqualified)].
- - {Coordinated Universal Time (UTC)}[https://en.wikipedia.org/wiki/ISO_8601#Coordinated_Universal_Time_(UTC)].
- - {Time offsets from UTC}[https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC].
-
-=== Combined \Date and \Time
-
-See {ISO 8601 Combined date and time representations}[https://en.wikipedia.org/wiki/ISO_8601#Combined_date_and_time_representations].
-
-An ISO 8601 combined date and time representation may be any
-ISO 8601 date and any ISO 8601 time,
-separated by the letter +T+.
-
-For the relevant +strftime+ formats, see
-{Dates}[rdoc-ref:strftime_formatting.rdoc@Dates]
-and {Times}[rdoc-ref:strftime_formatting.rdoc@Times] above.
diff --git a/doc/string.rb b/doc/string.rb
new file mode 100644
index 0000000000..304ab60c29
--- /dev/null
+++ b/doc/string.rb
@@ -0,0 +1,421 @@
+# A +String+ object has an arbitrary sequence of bytes,
+# typically representing text or binary data.
+# A +String+ object may be created using String::new or as literals.
+#
+# String objects differ from Symbol objects in that Symbol objects are
+# designed to be used as identifiers, instead of text or data.
+#
+# You can create a +String+ object explicitly with:
+#
+# - A {string literal}[rdoc-ref:syntax/literals.rdoc@String+Literals].
+# - A {heredoc literal}[rdoc-ref:syntax/literals.rdoc@Here+Document+Literals].
+#
+# You can convert certain objects to Strings with:
+#
+# - Method #String.
+#
+# Some +String+ methods modify +self+.
+# Typically, a method whose name ends with <tt>!</tt> modifies +self+
+# and returns +self+;
+# often, a similarly named method (without the <tt>!</tt>)
+# returns a new string.
+#
+# In general, if both bang and non-bang versions of a method exist,
+# the bang method mutates and the non-bang method does not.
+# However, a method without a bang can also mutate, such as String#replace.
+#
+# == Substitution Methods
+#
+# These methods perform substitutions:
+#
+# - String#sub: One substitution (or none); returns a new string.
+# - String#sub!: One substitution (or none); returns +self+ if any changes,
+# +nil+ otherwise.
+# - String#gsub: Zero or more substitutions; returns a new string.
+# - String#gsub!: Zero or more substitutions; returns +self+ if any changes,
+# +nil+ otherwise.
+#
+# Each of these methods takes:
+#
+# - A first argument, +pattern+ (String or Regexp),
+# that specifies the substring(s) to be replaced.
+#
+# - Either of the following:
+#
+# - A second argument, +replacement+ (String or Hash),
+# that determines the replacing string.
+# - A block that will determine the replacing string.
+#
+# The examples in this section mostly use the String#sub and String#gsub methods;
+# the principles illustrated apply to all four substitution methods.
+#
+# <b>Argument +pattern+</b>
+#
+# 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"
+#
+# <b>+String+ +replacement+</b>
+#
+# If +replacement+ is a string, that string determines
+# the replacing string that is substituted for the matched text.
+#
+# Each of the examples above uses a simple string as the replacing string.
+#
+# +String+ +replacement+ may contain back-references to the pattern's captures:
+#
+# - <tt>\n</tt> (_n_ is a non-negative integer) refers to <tt>$n</tt>.
+# - <tt>\k<name></tt> refers to the named capture +name+.
+#
+# See Regexp for details.
+#
+# Note that within the string +replacement+, a character combination
+# such as <tt>$&</tt> is treated as ordinary text, not as
+# a special match variable.
+# However, you may refer to some special match variables using these
+# combinations:
+#
+# - <tt>\&</tt> and <tt>\0</tt> correspond to <tt>$&</tt>,
+# which contains the complete matched text.
+# - <tt>\'</tt> corresponds to <tt>$'</tt>,
+# which contains the string after the match.
+# - <tt>\`</tt> corresponds to <tt>$`</tt>,
+# which contains the string before the match.
+# - <tt>\\+</tt> corresponds to <tt>$+</tt>,
+# which contains the last capture group.
+#
+# See Regexp for details.
+#
+# Note that <tt>\\\\</tt> is interpreted as an escape, i.e., a single backslash.
+#
+# Note also that a string literal consumes backslashes.
+# See {String Literals}[rdoc-ref:syntax/literals.rdoc@String+Literals] for details about string literals.
+#
+# A back-reference is typically preceded by an additional backslash.
+# For example, if you want to write a back-reference <tt>\&</tt> in
+# +replacement+ with a double-quoted string literal, you need to write
+# <tt>"..\\\\&.."</tt>.
+#
+# If you want to write a non-back-reference string <tt>\&</tt> in
+# +replacement+, you need to first escape the backslash to prevent
+# this method from interpreting it as a back-reference, and then you
+# need to escape the backslashes again to prevent a string literal from
+# consuming them: <tt>"..\\\\\\\\&.."</tt>.
+#
+# You may want to use the block form to avoid excessive backslashes.
+#
+# <b>\Hash +replacement+</b>
+#
+# If the argument +replacement+ is a hash, and +pattern+ matches one of its keys,
+# the replacing string is the value for that key:
+#
+# h = {'foo' => 'bar', 'baz' => 'bat'}
+# 'food'.sub('foo', h) # => "bard"
+#
+# Note that a symbol key does not match:
+#
+# h = {foo: 'bar', baz: 'bat'}
+# 'food'.sub('foo', h) # => "d"
+#
+# <b>Block</b>
+#
+# 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 <tt>$1</tt>, <tt>$2</tt>, <tt>$`</tt>,
+# <tt>$&</tt>, and <tt>$'</tt> are set appropriately.
+#
+# == Whitespace in Strings
+#
+# In the class +String+, _whitespace_ is defined as a contiguous sequence of characters
+# consisting of any mixture of the following:
+#
+# - NL (null): <tt>"\x00"</tt>, <tt>"\u0000"</tt>.
+# - HT (horizontal tab): <tt>"\x09"</tt>, <tt>"\t"</tt>.
+# - LF (line feed): <tt>"\x0a"</tt>, <tt>"\n"</tt>.
+# - VT (vertical tab): <tt>"\x0b"</tt>, <tt>"\v"</tt>.
+# - FF (form feed): <tt>"\x0c"</tt>, <tt>"\f"</tt>.
+# - CR (carriage return): <tt>"\x0d"</tt>, <tt>"\r"</tt>.
+# - SP (space): <tt>"\x20"</tt>, <tt>" "</tt>.
+#
+#
+# Whitespace is relevant for the following methods:
+#
+# - #lstrip, #lstrip!: Strip leading whitespace.
+# - #rstrip, #rstrip!: Strip trailing whitespace.
+# - #strip, #strip!: Strip leading and trailing whitespace.
+#
+# == What's Here
+#
+# First, what's elsewhere. Class +String+:
+#
+# - Inherits from the {Object class}[rdoc-ref:Object@What-27s+Here].
+# - Includes the {Comparable module}[rdoc-ref:Comparable@What-27s+Here].
+#
+# Here, class +String+ provides methods that are useful for:
+#
+# - {Creating a \String}[rdoc-ref:String@Creating+a+String].
+# - {Freezing/Unfreezing a \String}[rdoc-ref:String@Freezing-2FUnfreezing].
+# - {Querying a \String}[rdoc-ref:String@Querying].
+# - {Comparing Strings}[rdoc-ref:String@Comparing].
+# - {Modifying a \String}[rdoc-ref:String@Modifying].
+# - {Converting to a new \String}[rdoc-ref:String@Converting+to+New+String].
+# - {Converting to a non-\String}[rdoc-ref:String@Converting+to+Non--5CString].
+# - {Iterating over a \String}[rdoc-ref:String@Iterating].
+#
+# === Creating a \String
+#
+# - ::new: Returns a new string.
+# - ::try_convert: Returns a new string created from a given object.
+#
+# === Freezing/Unfreezing
+#
+# - #+@: Returns a string that is not frozen: +self+ if not frozen;
+# +self.dup+ otherwise.
+# - #-@ (aliased as #dedup): Returns a string that is frozen: +self+ if already frozen;
+# +self.freeze+ otherwise.
+# - #freeze: Freezes +self+ if not already frozen; returns +self+.
+#
+# === Querying
+#
+# _Counts_
+#
+# - #bytesize: Returns the count of bytes.
+# - #count: Returns the count of substrings matching given strings.
+# - #empty?: Returns whether the length of +self+ is zero.
+# - #length (aliased as #size): Returns the count of characters (not bytes).
+#
+# _Substrings_
+#
+# - #=~: Returns the index of the first substring that matches a given
+# Regexp or other object; returns +nil+ if no match is found.
+# - #byteindex: Returns the byte index of the first occurrence of a given substring.
+# - #byterindex: Returns the byte index of the last occurrence of a given substring.
+# - #index: Returns the index of the _first_ occurrence of a given substring;
+# returns +nil+ if none found.
+# - #rindex: Returns the index of the _last_ occurrence of a given substring;
+# returns +nil+ if none found.
+# - #include?: Returns +true+ if the string contains a given substring; +false+ otherwise.
+# - #match: Returns a MatchData object if the string matches a given Regexp; +nil+ otherwise.
+# - #match?: Returns +true+ if the string matches a given Regexp; +false+ otherwise.
+# - #start_with?: Returns +true+ if the string begins with any of the given substrings.
+# - #end_with?: Returns +true+ if the string ends with any of the given substrings.
+#
+# _Encodings_
+#
+# - #encoding\: Returns the Encoding object that represents the encoding of the string.
+# - #unicode_normalized?: Returns +true+ if the string is in Unicode normalized form; +false+ otherwise.
+# - #valid_encoding?: Returns +true+ if the string contains only characters that are valid
+# for its encoding.
+# - #ascii_only?: Returns +true+ if the string has only ASCII characters; +false+ otherwise.
+#
+# _Other_
+#
+# - #sum: Returns a basic checksum for the string: the sum of each byte.
+# - #hash: Returns the integer hash code.
+#
+# === Comparing
+#
+# - #== (aliased as #===): Returns +true+ if a given other string has the same content as +self+.
+# - #eql?: Returns +true+ if the content is the same as the given other string.
+# - #<=>: Returns -1, 0, or 1 as a given other string is smaller than,
+# equal to, or larger than +self+.
+# - #casecmp: Ignoring case, returns -1, 0, or 1 as
+# +self+ is smaller than, equal to, or larger than a given other string.
+# - #casecmp?: Ignoring case, returns whether a given other string is equal to +self+.
+#
+# === Modifying
+#
+# Each of these methods modifies +self+.
+#
+# _Insertion_
+#
+# - #insert: Returns +self+ with a given string inserted at a specified offset.
+# - #<<: Returns +self+ concatenated with a given string or integer.
+# - #append_as_bytes: Returns +self+ concatenated with strings without performing any
+# encoding validation or conversion.
+# - #prepend: Prefixes to +self+ the concatenation of given other strings.
+#
+# _Substitution_
+#
+# - #bytesplice: Replaces bytes of +self+ with bytes from a given string; returns +self+.
+# - #sub!: Replaces the first substring that matches a given pattern with a given replacement string;
+# returns +self+ if any changes, +nil+ otherwise.
+# - #gsub!: Replaces each substring that matches a given pattern with a given replacement string;
+# returns +self+ if any changes, +nil+ otherwise.
+# - #succ! (aliased as #next!): Returns +self+ modified to become its own successor.
+# - #replace: Returns +self+ with its entire content replaced by a given string.
+# - #reverse!: Returns +self+ with its characters in reverse order.
+# - #setbyte: Sets the byte at a given integer offset to a given value; returns the argument.
+# - #tr!: Replaces specified characters in +self+ with specified replacement characters;
+# returns +self+ if any changes, +nil+ otherwise.
+# - #tr_s!: Replaces specified characters in +self+ with specified replacement characters,
+# removing duplicates from the substrings that were modified;
+# returns +self+ if any changes, +nil+ otherwise.
+#
+# _Casing_
+#
+# - #capitalize!: Upcases the initial character and downcases all others;
+# returns +self+ if any changes, +nil+ otherwise.
+# - #downcase!: Downcases all characters; returns +self+ if any changes, +nil+ otherwise.
+# - #upcase!: Upcases all characters; returns +self+ if any changes, +nil+ otherwise.
+# - #swapcase!: Upcases each downcase character and downcases each upcase character;
+# returns +self+ if any changes, +nil+ otherwise.
+#
+# _Encoding_
+#
+# - #encode!: Returns +self+ with all characters transcoded from one encoding to another.
+# - #unicode_normalize!: Unicode-normalizes +self+; returns +self+.
+# - #scrub!: Replaces each invalid byte with a given character; returns +self+.
+# - #force_encoding: Changes the encoding to a given encoding; returns +self+.
+#
+# _Deletion_
+#
+# - #clear: Removes all content, so that +self+ is empty; returns +self+.
+# - #slice!, #[]=: Removes a substring determined by a given index, start/length, range, regexp, or substring.
+# - #squeeze!: Removes contiguous duplicate characters; returns +self+.
+# - #delete!: Removes characters as determined by the intersection of substring arguments.
+# - #delete_prefix!: Removes leading prefix; returns +self+ if any changes, +nil+ otherwise.
+# - #delete_suffix!: Removes trailing suffix; returns +self+ if any changes, +nil+ otherwise.
+# - #lstrip!: Removes leading whitespace; returns +self+ if any changes, +nil+ otherwise.
+# - #rstrip!: Removes trailing whitespace; returns +self+ if any changes, +nil+ otherwise.
+# - #strip!: Removes leading and trailing whitespace; returns +self+ if any changes, +nil+ otherwise.
+# - #chomp!: Removes the trailing record separator, if found; returns +self+ if any changes, +nil+ otherwise.
+# - #chop!: Removes trailing newline characters if found; otherwise removes the last character;
+# returns +self+ if any changes, +nil+ otherwise.
+#
+# === Converting to New \String
+#
+# Each of these methods returns a new +String+ based on +self+,
+# often just a modified copy of +self+.
+#
+# _Extension_
+#
+# - #*: Returns the concatenation of multiple copies of +self+.
+# - #+: Returns the concatenation of +self+ and a given other string.
+# - #center: Returns a copy of +self+, centered by specified padding.
+# - #concat: Returns the concatenation of +self+ with given other strings.
+# - #ljust: Returns a copy of +self+ of a given length, right-padded with a given other string.
+# - #rjust: Returns a copy of +self+ of a given length, left-padded with a given other string.
+#
+# _Encoding_
+#
+# - #b: Returns a copy of +self+ with ASCII-8BIT encoding.
+# - #scrub: Returns a copy of +self+ with each invalid byte replaced with a given character.
+# - #unicode_normalize: Returns a copy of +self+ with each character Unicode-normalized.
+# - #encode: Returns a copy of +self+ with all characters transcoded from one encoding to another.
+#
+# _Substitution_
+#
+# - #dump: Returns a printable version of +self+, enclosed in double-quotes.
+# - #undump: Inverse of #dump; returns a copy of +self+ with changes of the kinds made by #dump "undone."
+# - #sub: Returns a copy of +self+ with the first substring matching a given pattern
+# replaced with a given replacement string.
+# - #gsub: Returns a copy of +self+ with each substring that matches a given pattern
+# replaced with a given replacement string.
+# - #succ (aliased as #next): Returns the string that is the successor to +self+.
+# - #reverse: Returns a copy of +self+ with its characters in reverse order.
+# - #tr: Returns a copy of +self+ with specified characters replaced with specified replacement characters.
+# - #tr_s: Returns a copy of +self+ with specified characters replaced with
+# specified replacement characters,
+# removing duplicates from the substrings that were modified.
+# - #%: Returns the string resulting from formatting a given object into +self+.
+#
+# _Casing_
+#
+# - #capitalize: Returns a copy of +self+ with the first character upcased
+# and all other characters downcased.
+# - #downcase: Returns a copy of +self+ with all characters downcased.
+# - #upcase: Returns a copy of +self+ with all characters upcased.
+# - #swapcase: Returns a copy of +self+ with all upcase characters downcased
+# and all downcase characters upcased.
+#
+# _Deletion_
+#
+# - #delete: Returns a copy of +self+ with characters removed.
+# - #delete_prefix: Returns a copy of +self+ with a given prefix removed.
+# - #delete_suffix: Returns a copy of +self+ with a given suffix removed.
+# - #lstrip: Returns a copy of +self+ with leading whitespace removed.
+# - #rstrip: Returns a copy of +self+ with trailing whitespace removed.
+# - #strip: Returns a copy of +self+ with leading and trailing whitespace removed.
+# - #chomp: Returns a copy of +self+ with a trailing record separator removed, if found.
+# - #chop: Returns a copy of +self+ with trailing newline characters or the last character removed.
+# - #squeeze: Returns a copy of +self+ with contiguous duplicate characters removed.
+# - #[] (aliased as #slice): Returns a substring determined by a given index, start/length, range, regexp, or string.
+# - #byteslice: Returns a substring determined by a given index, start/length, or range.
+# - #chr: Returns the first character.
+#
+# _Duplication_
+#
+# - #to_s (aliased as #to_str): If +self+ is a subclass of +String+, returns +self+ copied into a +String+;
+# otherwise, returns +self+.
+#
+# === Converting to Non-\String
+#
+# Each of these methods converts the contents of +self+ to a non-+String+.
+#
+# <em>Characters, Bytes, and Clusters</em>
+#
+# - #bytes: Returns an array of the bytes in +self+.
+# - #chars: Returns an array of the characters in +self+.
+# - #codepoints: Returns an array of the integer ordinals in +self+.
+# - #getbyte: Returns the integer byte at the given index in +self+.
+# - #grapheme_clusters: Returns an array of the grapheme clusters in +self+.
+#
+# _Splitting_
+#
+# - #lines: Returns an array of the lines in +self+, as determined by a given record separator.
+# - #partition: Returns a 3-element array determined by the first substring that matches
+# a given substring or regexp.
+# - #rpartition: Returns a 3-element array determined by the last substring that matches
+# a given substring or regexp.
+# - #split: Returns an array of substrings determined by a given delimiter -- regexp or string --
+# or, if a block is given, passes those substrings to the block.
+#
+# _Matching_
+#
+# - #scan: Returns an array of substrings matching a given regexp or string, or,
+# if a block is given, passes each matching substring to the block.
+# - #unpack: Returns an array of substrings extracted from +self+ according to a given format.
+# - #unpack1: Returns the first substring extracted from +self+ according to a given format.
+#
+# _Numerics_
+#
+# - #hex: Returns the integer value of the leading characters, interpreted as hexadecimal digits.
+# - #oct: Returns the integer value of the leading characters, interpreted as octal digits.
+# - #ord: Returns the integer ordinal of the first character in +self+.
+# - #to_c: Returns the complex value of leading characters, interpreted as a complex number.
+# - #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.
+# - #to_r: Returns the rational value of leading characters, interpreted as a rational.
+#
+# <em>Strings and Symbols</em>
+#
+# - #inspect: Returns a copy of +self+, enclosed in double quotes, with special characters escaped.
+# - #intern (aliased as #to_sym): Returns the symbol corresponding to +self+.
+#
+# === Iterating
+#
+# - #each_byte: Calls the given block with each successive byte in +self+.
+# - #each_char: Calls the given block with each successive character in +self+.
+# - #each_codepoint: Calls the given block with each successive integer codepoint in +self+.
+# - #each_grapheme_cluster: Calls the given block with each successive grapheme cluster in +self+.
+# - #each_line: Calls the given block with each successive line in +self+,
+# as determined by a given record separator.
+# - #upto: Calls the given block with each string value returned by successive calls to #succ.
+
+class String; end
diff --git a/doc/string/aref.rdoc b/doc/string/aref.rdoc
new file mode 100644
index 0000000000..a9ab8857bc
--- /dev/null
+++ b/doc/string/aref.rdoc
@@ -0,0 +1,96 @@
+Returns the substring of +self+ specified by the arguments.
+
+<b>Form <tt>self[offset]</tt></b>
+
+With non-negative integer argument +offset+ given,
+returns the 1-character substring found in self at character offset +offset+:
+
+ 'hello'[0] # => "h"
+ 'hello'[4] # => "o"
+ 'hello'[5] # => nil
+ 'こんにちは'[4] # => "は"
+
+With negative integer argument +offset+ given,
+counts backward from the end of +self+:
+
+ 'hello'[-1] # => "o"
+ 'hello'[-5] # => "h"
+ 'hello'[-6] # => nil
+
+<b>Form <tt>self[offset, size]</tt></b>
+
+With integer arguments +offset+ and +size+ given,
+returns a substring of size +size+ characters (as available)
+beginning at character offset specified by +offset+.
+
+If argument +offset+ is non-negative,
+the offset is +offset+:
+
+ 'hello'[0, 1] # => "h"
+ 'hello'[0, 5] # => "hello"
+ 'hello'[0, 6] # => "hello"
+ 'hello'[2, 3] # => "llo"
+ 'hello'[2, 0] # => ""
+ 'hello'[2, -1] # => nil
+
+If argument +offset+ is negative,
+counts backward from the end of +self+:
+
+ 'hello'[-1, 1] # => "o"
+ 'hello'[-5, 5] # => "hello"
+ 'hello'[-1, 0] # => ""
+ 'hello'[-6, 5] # => nil
+
+Special case: if +offset+ equals the size of +self+,
+returns a new empty string:
+
+ 'hello'[5, 3] # => ""
+
+<b>Form <tt>self[range]</tt></b>
+
+With Range argument +range+ given,
+forms substring <tt>self[range.start, range.size]</tt>:
+
+ 'hello'[0..2] # => "hel"
+ 'hello'[0, 3] # => "hel"
+
+ 'hello'[0...2] # => "he"
+ 'hello'[0, 2] # => "he"
+
+ 'hello'[0, 0] # => ""
+ 'hello'[0...0] # => ""
+
+<b>Form <tt>self[regexp, capture = 0]</tt></b>
+
+With Regexp argument +regexp+ given and +capture+ as zero,
+searches for a matching substring in +self+;
+updates {Regexp-related global variables}[rdoc-ref:Regexp@Global+Variables]:
+
+ 'hello'[/ell/] # => "ell"
+ 'hello'[/l+/] # => "ll"
+ 'hello'[//] # => ""
+ 'hello'[/nosuch/] # => nil
+
+With +capture+ as a positive integer +n+,
+returns the +n+th matched group:
+
+ 'hello'[/(h)(e)(l+)(o)/] # => "hello"
+ 'hello'[/(h)(e)(l+)(o)/, 1] # => "h"
+ $1 # => "h"
+ 'hello'[/(h)(e)(l+)(o)/, 2] # => "e"
+ $2 # => "e"
+ 'hello'[/(h)(e)(l+)(o)/, 3] # => "ll"
+ 'hello'[/(h)(e)(l+)(o)/, 4] # => "o"
+ 'hello'[/(h)(e)(l+)(o)/, 5] # => nil
+
+<b>Form <tt>self[substring]</tt></b>
+
+With string argument +substring+ given,
+returns the matching substring of +self+, if found:
+
+ 'hello'['ell'] # => "ell"
+ 'hello'[''] # => ""
+ 'hello'['nosuch'] # => nil
+ 'こんにちは'['んにち'] # => "んにち"
+
+Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
diff --git a/doc/string/aset.rdoc b/doc/string/aset.rdoc
new file mode 100644
index 0000000000..98c58b59cc
--- /dev/null
+++ b/doc/string/aset.rdoc
@@ -0,0 +1,179 @@
+Returns +self+ with all, a substring, or none of its contents replaced;
+returns the argument +other_string+.
+
+<b>Form <tt>self[index] = other_string</tt></b>
+
+With non-negative integer argument +index+ given,
+searches for the 1-character substring found in self at character offset index:
+
+ s = 'hello'
+ s[0] = 'foo' # => "foo"
+ s # => "fooello"
+
+ s = 'hello'
+ s[4] = 'foo' # => "foo"
+ s # => "hellfoo"
+
+ s = 'hello'
+ s[5] = 'foo' # => "foo"
+ s # => "hellofoo"
+
+ s = 'hello'
+ s[6] = 'foo' # Raises IndexError: index 6 out of string.
+
+With negative integer argument +index+ given,
+counts backward from the end of +self+:
+
+ s = 'hello'
+ s[-1] = 'foo' # => "foo"
+ s # => "hellfoo"
+
+ s = 'hello'
+ s[-5] = 'foo' # => "foo"
+ s # => "fooello"
+
+ s = 'hello'
+ s[-6] = 'foo' # Raises IndexError: index -6 out of string.
+
+<b>Form <tt>self[start, length] = other_string</tt></b>
+
+With integer arguments +start+ and +length+ given,
+searches for a substring of size +length+ characters (as available)
+beginning at character offset specified by +start+.
+
+If argument +start+ is non-negative,
+the offset is +start+:
+
+ s = 'hello'
+ s[0, 1] = 'foo' # => "foo"
+ s # => "fooello"
+
+ s = 'hello'
+ s[0, 5] = 'foo' # => "foo"
+ s # => "foo"
+
+ s = 'hello'
+ s[0, 9] = 'foo' # => "foo"
+ s # => "foo"
+
+ s = 'hello'
+ s[2, 0] = 'foo' # => "foo"
+ s # => "hefoollo"
+
+ s = 'hello'
+ s[2, -1] = 'foo' # Raises IndexError: negative length -1.
+
+If argument +start+ is negative,
+counts backward from the end of +self+:
+
+ s = 'hello'
+ s[-1, 1] = 'foo' # => "foo"
+ s # => "hellfoo"
+
+ s = 'hello'
+ s[-1, 9] = 'foo' # => "foo"
+ s # => "hellfoo"
+
+ s = 'hello'
+ s[-5, 2] = 'foo' # => "foo"
+ s # => "foollo"
+
+ s = 'hello'
+ s[-3, 0] = 'foo' # => "foo"
+ s # => "hefoollo"
+
+ s = 'hello'
+ s[-6, 2] = 'foo' # Raises IndexError: index -6 out of string.
+
+Special case: if +start+ equals the length of +self+,
+the argument is appended to +self+:
+
+ s = 'hello'
+ s[5, 3] = 'foo' # => "foo"
+ s # => "hellofoo"
+
+<b>Form <tt>self[range] = other_string</tt></b>
+
+With Range argument +range+ given,
+equivalent to <tt>self[range.start, range.size] = other_string</tt>:
+
+ s0 = 'hello'
+ s1 = 'hello'
+ s0[0..2] = 'foo' # => "foo"
+ s1[0, 3] = 'foo' # => "foo"
+ s0 # => "foolo"
+ s1 # => "foolo"
+
+ s = 'hello'
+ s[0...2] = 'foo' # => "foo"
+ s # => "foollo"
+
+ s = 'hello'
+ s[0...0] = 'foo' # => "foo"
+ s # => "foohello"
+
+ s = 'hello'
+ s[9..10] = 'foo' # Raises RangeError: 9..10 out of range
+
+<b>Form <tt>self[regexp, capture = 0] = other_string</tt></b>
+
+With Regexp argument +regexp+ given and +capture+ as zero,
+searches for a matching substring in +self+;
+updates {Regexp-related global variables}[rdoc-ref:Regexp@Global+Variables]:
+
+ s = 'hello'
+ s[/l/] = 'L' # => "L"
+ [$`, $&, $'] # => ["he", "l", "lo"]
+ s[/eLlo/] = 'owdy' # => "owdy"
+ [$`, $&, $'] # => ["h", "eLlo", ""]
+ s[/eLlo/] = 'owdy' # Raises IndexError: regexp not matched.
+ [$`, $&, $'] # => [nil, nil, nil]
+
+With +capture+ as a positive integer +n+,
+searches for the +n+th matched group:
+
+ s = 'hello'
+ s[/(h)(e)(l+)(o)/] = 'foo' # => "foo"
+ [$`, $&, $'] # => ["", "hello", ""]
+
+ s = 'hello'
+ s[/(h)(e)(l+)(o)/, 1] = 'foo' # => "foo"
+ s # => "fooello"
+ [$`, $&, $'] # => ["", "hello", ""]
+
+ s = 'hello'
+ s[/(h)(e)(l+)(o)/, 2] = 'foo' # => "foo"
+ s # => "hfoollo"
+ [$`, $&, $'] # => ["", "hello", ""]
+
+ s = 'hello'
+ s[/(h)(e)(l+)(o)/, 4] = 'foo' # => "foo"
+ s # => "hellfoo"
+ [$`, $&, $'] # => ["", "hello", ""]
+
+ s = 'hello'
+ # => "hello"
+ s[/(h)(e)(l+)(o)/, 5] = 'foo # Raises IndexError: index 5 out of regexp.
+
+ s = 'hello'
+ s[/nosuch/] = 'foo' # Raises IndexError: regexp not matched.
+
+<b>Form <tt>self[substring] = other_string</tt></b>
+
+With string argument +substring+ given:
+
+ s = 'hello'
+ s['l'] = 'foo' # => "foo"
+ s # => "hefoolo"
+
+ s = 'hello'
+ s['ll'] = 'foo' # => "foo"
+ s # => "hefooo"
+
+ s = 'こんにちは'
+ s['んにち'] = 'foo' # => "foo"
+ s # => "こfooは"
+
+ s['nosuch'] = 'foo' # Raises IndexError: string not matched.
+
+Related: see {Modifying}[rdoc-ref:String@Modifying].
diff --git a/doc/string/b.rdoc b/doc/string/b.rdoc
index f8ad2910b4..8abd6d9532 100644
--- a/doc/string/b.rdoc
+++ b/doc/string/b.rdoc
@@ -12,3 +12,5 @@ the underlying bytes are not modified:
t = s.b # => "\xE4\x82\x95"
t.encoding # => #<Encoding:ASCII-8BIT>
t.bytes # => [228, 130, 149]
+
+Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
diff --git a/doc/string/bytes.rdoc b/doc/string/bytes.rdoc
index a9e89f1cd1..6dde0a745d 100644
--- a/doc/string/bytes.rdoc
+++ b/doc/string/bytes.rdoc
@@ -1,6 +1,7 @@
Returns an array of the bytes in +self+:
- 'hello'.bytes # => [104, 101, 108, 108, 111]
- 'тест'.bytes # => [209, 130, 208, 181, 209, 129, 209, 130]
+ 'hello'.bytes # => [104, 101, 108, 108, 111]
'こんにちは'.bytes
# => [227, 129, 147, 227, 130, 147, 227, 129, 171, 227, 129, 161, 227, 129, 175]
+
+Related: see {Converting to Non-String}[rdoc-ref:String@Converting+to+Non--5CString].
diff --git a/doc/string/bytesize.rdoc b/doc/string/bytesize.rdoc
index b0567ff67b..8d12a0d454 100644
--- a/doc/string/bytesize.rdoc
+++ b/doc/string/bytesize.rdoc
@@ -1,11 +1,12 @@
-Returns the count of bytes (not characters) in +self+:
+Returns the count of bytes in +self+.
- 'foo'.bytesize # => 3
- 'тест'.bytesize # => 8
- 'こんにちは'.bytesize # => 15
+Note that the byte count may be different from the character count (returned by #size):
-Contrast with String#length:
+ s = 'foo'
+ s.bytesize # => 3
+ s.size # => 3
+ s = 'こんにちは'
+ s.bytesize # => 15
+ s.size # => 5
- 'foo'.length # => 3
- 'тест'.length # => 4
- 'こんにちは'.length # => 5
+Related: see {Querying}[rdoc-ref:String@Querying].
diff --git a/doc/string/byteslice.rdoc b/doc/string/byteslice.rdoc
new file mode 100644
index 0000000000..d70441fb2b
--- /dev/null
+++ b/doc/string/byteslice.rdoc
@@ -0,0 +1,54 @@
+Returns a substring of +self+, or +nil+ if the substring cannot be constructed.
+
+With integer arguments +offset+ and +length+ given,
+returns the substring beginning at the given +offset+
+and of the given +length+ (as available):
+
+ s = '0123456789' # => "0123456789"
+ s.byteslice(2) # => "2"
+ s.byteslice(200) # => nil
+ s.byteslice(4, 3) # => "456"
+ s.byteslice(4, 30) # => "456789"
+
+Returns +nil+ if +length+ is negative or +offset+ falls outside of +self+:
+
+ s.byteslice(4, -1) # => nil
+ s.byteslice(40, 2) # => nil
+
+Counts backwards from the end of +self+
+if +offset+ is negative:
+
+ s = '0123456789' # => "0123456789"
+ s.byteslice(-4) # => "6"
+ s.byteslice(-4, 3) # => "678"
+
+With Range argument +range+ given, returns
+<tt>byteslice(range.begin, range.size)</tt>:
+
+ s = '0123456789' # => "0123456789"
+ s.byteslice(4..6) # => "456"
+ s.byteslice(-6..-4) # => "456"
+ s.byteslice(5..2) # => "" # range.size is zero.
+ s.byteslice(40..42) # => nil
+
+The starting and ending offsets need not be on character boundaries:
+
+ s = 'こんにちは'
+ s.byteslice(0, 3) # => "こ"
+ s.byteslice(1, 3) # => "\x81\x93\xE3"
+
+The encodings of +self+ and the returned substring
+are always the same:
+
+ s.encoding # => #<Encoding:UTF-8>
+ s.byteslice(0, 3).encoding # => #<Encoding:UTF-8>
+ s.byteslice(1, 3).encoding # => #<Encoding:UTF-8>
+
+But, depending on the character boundaries,
+the encoding of the returned substring may not be valid:
+
+ s.valid_encoding? # => true
+ s.byteslice(0, 3).valid_encoding? # => true
+ s.byteslice(1, 3).valid_encoding? # => false
+
+Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
diff --git a/doc/string/bytesplice.rdoc b/doc/string/bytesplice.rdoc
new file mode 100644
index 0000000000..5689ef4a2b
--- /dev/null
+++ b/doc/string/bytesplice.rdoc
@@ -0,0 +1,66 @@
+Replaces <i>target bytes</i> in +self+ with <i>source bytes</i> from the given string +str+;
+returns +self+.
+
+In the first form, arguments +offset+ and +length+ determine the target bytes,
+and the source bytes are all of the given +str+:
+
+ '0123456789'.bytesplice(0, 3, 'abc') # => "abc3456789"
+ '0123456789'.bytesplice(3, 3, 'abc') # => "012abc6789"
+ '0123456789'.bytesplice(0, 50, 'abc') # => "abc"
+ '0123456789'.bytesplice(50, 3, 'abc') # Raises IndexError.
+
+The counts of the target bytes and source source bytes may be different:
+
+ '0123456789'.bytesplice(0, 6, 'abc') # => "abc6789" # Shorter source.
+ '0123456789'.bytesplice(0, 1, 'abc') # => "abc123456789" # Shorter target.
+
+And either count may be zero (i.e., specifying an empty string):
+
+ '0123456789'.bytesplice(0, 3, '') # => "3456789" # Empty source.
+ '0123456789'.bytesplice(0, 0, 'abc') # => "abc0123456789" # Empty target.
+
+In the second form, just as in the first,
+arugments +offset+ and +length+ determine the target bytes;
+argument +str+ _contains_ the source bytes,
+and the additional arguments +str_offset+ and +str_length+
+determine the actual source bytes:
+
+ '0123456789'.bytesplice(0, 3, 'abc', 0, 3) # => "abc3456789"
+ '0123456789'.bytesplice(0, 3, 'abc', 1, 1) # => "b3456789" # Shorter source.
+ '0123456789'.bytesplice(0, 1, 'abc', 0, 3) # => "abc123456789" # Shorter target.
+ '0123456789'.bytesplice(0, 3, 'abc', 1, 0) # => "3456789" # Empty source.
+ '0123456789'.bytesplice(0, 0, 'abc', 0, 3) # => "abc0123456789" # Empty target.
+
+In the third form, argument +range+ determines the target bytes
+and the source bytes are all of the given +str+:
+
+ '0123456789'.bytesplice(0..2, 'abc') # => "abc3456789"
+ '0123456789'.bytesplice(3..5, 'abc') # => "012abc6789"
+ '0123456789'.bytesplice(0..5, 'abc') # => "abc6789" # Shorter source.
+ '0123456789'.bytesplice(0..0, 'abc') # => "abc123456789" # Shorter target.
+ '0123456789'.bytesplice(0..2, '') # => "3456789" # Empty source.
+ '0123456789'.bytesplice(0...0, 'abc') # => "abc0123456789" # Empty target.
+
+In the fourth form, just as in the third,
+arugment +range+ determines the target bytes;
+argument +str+ _contains_ the source bytes,
+and the additional argument +str_range+
+determines the actual source bytes:
+
+ '0123456789'.bytesplice(0..2, 'abc', 0..2) # => "abc3456789"
+ '0123456789'.bytesplice(3..5, 'abc', 0..2) # => "012abc6789"
+ '0123456789'.bytesplice(0..2, 'abc', 0..1) # => "ab3456789" # Shorter source.
+ '0123456789'.bytesplice(0..1, 'abc', 0..2) # => "abc23456789" # Shorter target.
+ '0123456789'.bytesplice(0..2, 'abc', 0...0) # => "3456789" # Empty source.
+ '0123456789'.bytesplice(0...0, 'abc', 0..2) # => "abc0123456789" # Empty target.
+
+In any of the forms, the beginnings and endings of both source and target
+must be on character boundaries.
+
+In these examples, +self+ has five 3-byte characters,
+and so has character boundaries at offsets 0, 3, 6, 9, 12, and 15.
+
+ 'こんにちは'.bytesplice(0, 3, 'abc') # => "abcんにちは"
+ 'こんにちは'.bytesplice(1, 3, 'abc') # Raises IndexError.
+ 'こんにちは'.bytesplice(0, 2, 'abc') # Raises IndexError.
+
diff --git a/doc/string/capitalize.rdoc b/doc/string/capitalize.rdoc
new file mode 100644
index 0000000000..3a1a2dcb8b
--- /dev/null
+++ b/doc/string/capitalize.rdoc
@@ -0,0 +1,26 @@
+Returns a string containing the characters in +self+,
+each with possibly changed case:
+
+- The first character made uppercase.
+- All other characters are made lowercase.
+
+Examples:
+
+ 'hello'.capitalize # => "Hello"
+ 'HELLO'.capitalize # => "Hello"
+ 'straße'.capitalize # => "Straße" # Lowercase 'ß' not changed.
+ 'STRAẞE'.capitalize # => "Straße" # Uppercase 'ẞ' downcased to 'ß'.
+
+Some characters (and some character sets) do not have upcase and downcase versions;
+see {Case Mapping}[rdoc-ref:case_mapping.rdoc]:
+
+ s = '1, 2, 3, ...'
+ s.capitalize == s # => true
+ s = 'こんにちは'
+ s.capitalize == s # => true
+
+The casing is affected by the given +mapping+,
+which may be +:ascii+, +:fold+, or +:turkic+;
+see {Case Mappings}[rdoc-ref:case_mapping.rdoc@Case+Mappings].
+
+Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
diff --git a/doc/string/center.rdoc b/doc/string/center.rdoc
index d53d921ad5..b86c8b5916 100644
--- a/doc/string/center.rdoc
+++ b/doc/string/center.rdoc
@@ -2,15 +2,18 @@ Returns a centered copy of +self+.
If integer argument +size+ is greater than the size (in characters) of +self+,
returns a new string of length +size+ that is a copy of +self+,
-centered and padded on both ends with +pad_string+:
+centered and padded on one or both ends with +pad_string+:
- 'hello'.center(10) # => " hello "
- ' hello'.center(10) # => " hello "
- 'hello'.center(10, 'ab') # => "abhelloaba"
- 'тест'.center(10) # => " тест "
- 'こんにちは'.center(10) # => " こんにちは "
+ 'hello'.center(6) # => "hello " # Padded on one end.
+ 'hello'.center(10) # => " hello " # Padded on both ends.
+ 'hello'.center(20, '-|') # => "-|-|-|-hello-|-|-|-|" # Some padding repeated.
+ 'hello'.center(10, 'abcdefg') # => "abhelloabc" # Some padding not used.
+ ' hello '.center(13) # => " hello "
+ 'こんにちは'.center(10) # => " こんにちは " # Multi-byte characters.
-If +size+ is not greater than the size of +self+, returns a copy of +self+:
+If +size+ is less than or equal to the size of +self+, returns an unpadded copy of +self+:
- 'hello'.center(5) # => "hello"
- 'hello'.center(1) # => "hello"
+ 'hello'.center(5) # => "hello"
+ 'hello'.center(-10) # => "hello"
+
+Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
diff --git a/doc/string/chars.rdoc b/doc/string/chars.rdoc
index d24a1cc3a9..d4d15bf2ad 100644
--- a/doc/string/chars.rdoc
+++ b/doc/string/chars.rdoc
@@ -1,5 +1,7 @@
Returns an array of the characters in +self+:
'hello'.chars # => ["h", "e", "l", "l", "o"]
- 'тест'.chars # => ["т", "е", "с", "т"]
'こんにちは'.chars # => ["こ", "ん", "に", "ち", "は"]
+ ''.chars # => []
+
+Related: see {Converting to Non-String}[rdoc-ref:String@Converting+to+Non--5CString].
diff --git a/doc/string/chomp.rdoc b/doc/string/chomp.rdoc
index b6fb9ff38c..4efff5c291 100644
--- a/doc/string/chomp.rdoc
+++ b/doc/string/chomp.rdoc
@@ -9,7 +9,6 @@ if they are <tt>"\r"</tt>, <tt>"\n"</tt>, or <tt>"\r\n"</tt>
"abc\n".chomp # => "abc"
"abc\r\n".chomp # => "abc"
"abc\n\r".chomp # => "abc\n"
- "тест\r\n".chomp # => "тест"
"こんにちは\r\n".chomp # => "こんにちは"
When +line_sep+ is <tt>''</tt> (an empty string),
@@ -25,5 +24,8 @@ removes multiple trailing occurrences of <tt>"\n"</tt> or <tt>"\r\n"</tt>
When +line_sep+ is neither <tt>"\n"</tt> nor <tt>''</tt>,
removes a single trailing line separator if there is one:
- 'abcd'.chomp('d') # => "abc"
- 'abcdd'.chomp('d') # => "abcd"
+ 'abcd'.chomp('cd') # => "ab"
+ 'abcdcd'.chomp('cd') # => "abcd"
+ 'abcd'.chomp('xx') # => "abcd"
+
+Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
diff --git a/doc/string/chop.rdoc b/doc/string/chop.rdoc
index 8ef82f8a49..d818ba467a 100644
--- a/doc/string/chop.rdoc
+++ b/doc/string/chop.rdoc
@@ -3,14 +3,15 @@ Returns a new string copied from +self+, with trailing characters possibly remov
Removes <tt>"\r\n"</tt> if those are the last two characters.
"abc\r\n".chop # => "abc"
- "тест\r\n".chop # => "тест"
"こんにちは\r\n".chop # => "こんにちは"
Otherwise removes the last character if it exists.
'abcd'.chop # => "abc"
- 'тест'.chop # => "тес"
'こんにちは'.chop # => "こんにち"
''.chop # => ""
-If you only need to remove the newline separator at the end of the string, String#chomp is a better alternative.
+If you only need to remove the newline separator at the end of the string,
+String#chomp is a better alternative.
+
+Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
diff --git a/doc/string/chr.rdoc b/doc/string/chr.rdoc
new file mode 100644
index 0000000000..153d5d71c3
--- /dev/null
+++ b/doc/string/chr.rdoc
@@ -0,0 +1,7 @@
+Returns a string containing the first character of +self+:
+
+ 'hello'.chr # => "h"
+ 'こんにちは'.chr # => "こ"
+ ''.chr # => ""
+
+Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
diff --git a/doc/string/codepoints.rdoc b/doc/string/codepoints.rdoc
index 0c55d3f4b9..22cb22c889 100644
--- a/doc/string/codepoints.rdoc
+++ b/doc/string/codepoints.rdoc
@@ -2,5 +2,7 @@ Returns an array of the codepoints in +self+;
each codepoint is the integer value for a character:
'hello'.codepoints # => [104, 101, 108, 108, 111]
- 'тест'.codepoints # => [1090, 1077, 1089, 1090]
'こんにちは'.codepoints # => [12371, 12435, 12395, 12385, 12399]
+ ''.codepoints # => []
+
+Related: see {Converting to Non-String}[rdoc-ref:String@Converting+to+Non--5CString].
diff --git a/doc/string/concat.rdoc b/doc/string/concat.rdoc
new file mode 100644
index 0000000000..92ba664b8c
--- /dev/null
+++ b/doc/string/concat.rdoc
@@ -0,0 +1,11 @@
+Concatenates each object in +objects+ to +self+; returns +self+:
+
+ 'foo'.concat('bar', 'baz') # => "foobarbaz"
+
+For each given object +object+ that is an integer,
+the value is considered a codepoint and converted to a character before concatenation:
+
+ 'foo'.concat(32, 'bar', 32, 'baz') # => "foo bar baz" # Embeds spaces.
+ 'こん'.concat(12395, 12385, 12399) # => "こんにちは"
+
+Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
diff --git a/doc/string/count.rdoc b/doc/string/count.rdoc
new file mode 100644
index 0000000000..7a3b9f1e21
--- /dev/null
+++ b/doc/string/count.rdoc
@@ -0,0 +1,74 @@
+Returns the total number of characters in +self+ that are specified by the given selectors.
+
+For one 1-character selector,
+returns the count of instances of that character:
+
+ s = 'abracadabra'
+ s.count('a') # => 5
+ s.count('b') # => 2
+ s.count('x') # => 0
+ s.count('') # => 0
+
+ s = 'よろしくお願いします'
+ s.count('よ') # => 1
+ s.count('し') # => 2
+
+For one multi-character selector,
+returns the count of instances for all specified characters:
+
+ s = 'abracadabra'
+ s.count('ab') # => 7
+ s.count('abc') # => 8
+ s.count('abcd') # => 9
+ s.count('abcdr') # => 11
+ s.count('abcdrx') # => 11
+
+Order and repetition do not matter:
+
+ s.count('ba') == s.count('ab') # => true
+ s.count('baab') == s.count('ab') # => true
+
+For multiple selectors,
+forms a single selector that is the intersection of characters in all selectors
+and returns the count of instances for that selector:
+
+ s = 'abcdefg'
+ s.count('abcde', 'dcbfg') == s.count('bcd') # => true
+ s.count('abc', 'def') == s.count('') # => true
+
+In a character selector, three characters get special treatment:
+
+- A caret (<tt>'^'</tt>) functions as a _negation_ operator
+ for the immediately following characters:
+
+ s = 'abracadabra'
+ s.count('^bc') # => 8 # Count of all except 'b' and 'c'.
+
+- A hyphen (<tt>'-'</tt>) between two other characters defines a _range_ of characters:
+
+ s = 'abracadabra'
+ s.count('a-c') # => 8 # Count of all 'a', 'b', and 'c'.
+
+- A backslash (<tt>'\'</tt>) acts as an escape for a caret, a hyphen,
+ or another backslash:
+
+ s = 'abracadabra'
+ s.count('\^bc') # => 3 # Count of '^', 'b', and 'c'.
+ s.count('a\-c') # => 6 # Count of 'a', '-', and 'c'.
+ 'foo\bar\baz'.count('\\') # => 2 # Count of '\'.
+
+These usages may be mixed:
+
+ s = 'abracadabra'
+ s.count('a-cq-t') # => 10 # Multiple ranges.
+ s.count('ac-d') # => 7 # Range mixed with plain characters.
+ s.count('^a-c') # => 3 # Range mixed with negation.
+
+For multiple selectors, all forms may be used, including negations, ranges, and escapes.
+
+ s = 'abracadabra'
+ s.count('^abc', '^def') == s.count('^abcdef') # => true
+ s.count('a-e', 'c-g') == s.count('cde') # => true
+ s.count('^abc', 'c-g') == s.count('defg') # => true
+
+Related: see {Querying}[rdoc-ref:String@Querying].
diff --git a/doc/string/delete.rdoc b/doc/string/delete.rdoc
new file mode 100644
index 0000000000..1827f177e6
--- /dev/null
+++ b/doc/string/delete.rdoc
@@ -0,0 +1,75 @@
+Returns a new string that is a copy of +self+ with certain characters removed;
+the removed characters are all instances of those specified by the given string +selectors+.
+
+For one 1-character selector,
+removes all instances of that character:
+
+ s = 'abracadabra'
+ s.delete('a') # => "brcdbr"
+ s.delete('b') # => "aracadara"
+ s.delete('x') # => "abracadabra"
+ s.delete('') # => "abracadabra"
+
+ s = 'よろしくお願いします'
+ s.delete('よ') # => "ろしくお願いします"
+ s.delete('し') # => "よろくお願います"
+
+For one multi-character selector,
+removes all instances of the specified characters:
+
+ s = 'abracadabra'
+ s.delete('ab') # => "rcdr"
+ s.delete('abc') # => "rdr"
+ s.delete('abcd') # => "rr"
+ s.delete('abcdr') # => ""
+ s.delete('abcdrx') # => ""
+
+Order and repetition do not matter:
+
+ s.delete('ba') == s.delete('ab') # => true
+ s.delete('baab') == s.delete('ab') # => true
+
+For multiple selectors,
+forms a single selector that is the intersection of characters in all selectors
+and removes all instances of characters specified by that selector:
+
+ s = 'abcdefg'
+ s.delete('abcde', 'dcbfg') == s.delete('bcd') # => true
+ s.delete('abc', 'def') == s.delete('') # => true
+
+In a character selector, three characters get special treatment:
+
+- A caret (<tt>'^'</tt>) functions as a _negation_ operator
+ for the immediately following characters:
+
+ s = 'abracadabra'
+ s.delete('^bc') # => "bcb" # Deletes all except 'b' and 'c'.
+
+- A hyphen (<tt>'-'</tt>) between two other characters defines a _range_ of characters:
+
+ s = 'abracadabra'
+ s.delete('a-c') # => "rdr" # Deletes all 'a', 'b', and 'c'.
+
+- A backslash (<tt>'\'</tt>) acts as an escape for a caret, a hyphen,
+ or another backslash:
+
+ s = 'abracadabra'
+ s.delete('\^bc') # => "araadara" # Deletes all '^', 'b', and 'c'.
+ s.delete('a\-c') # => "brdbr" # Deletes all 'a', '-', and 'c'.
+ 'foo\bar\baz'.delete('\\') # => "foobarbaz" # Deletes all '\'.
+
+These usages may be mixed:
+
+ s = 'abracadabra'
+ s.delete('a-cq-t') # => "d" # Multiple ranges.
+ s.delete('ac-d') # => "brbr" # Range mixed with plain characters.
+ s.delete('^a-c') # => "abacaaba" # Range mixed with negation.
+
+For multiple selectors, all forms may be used, including negations, ranges, and escapes.
+
+ s = 'abracadabra'
+ s.delete('^abc', '^def') == s.delete('^abcdef') # => true
+ s.delete('a-e', 'c-g') == s.delete('cde') # => true
+ s.delete('^abc', 'c-g') == s.delete('defg') # => true
+
+Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
diff --git a/doc/string/delete_prefix.rdoc b/doc/string/delete_prefix.rdoc
index fa9d8abd38..6255e300e3 100644
--- a/doc/string/delete_prefix.rdoc
+++ b/doc/string/delete_prefix.rdoc
@@ -1,8 +1,9 @@
-Returns a copy of +self+ with leading substring <tt>prefix</tt> removed:
+Returns a copy of +self+ with leading substring +prefix+ removed:
- 'hello'.delete_prefix('hel') # => "lo"
- 'hello'.delete_prefix('llo') # => "hello"
- 'тест'.delete_prefix('те') # => "ст"
+ 'oof'.delete_prefix('o') # => "of"
+ 'oof'.delete_prefix('oo') # => "f"
+ 'oof'.delete_prefix('oof') # => ""
+ 'oof'.delete_prefix('x') # => "oof"
'こんにちは'.delete_prefix('こん') # => "にちは"
-Related: String#delete_prefix!, String#delete_suffix.
+Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
diff --git a/doc/string/delete_suffix.rdoc b/doc/string/delete_suffix.rdoc
index 4862b725cf..a4d9a80f85 100644
--- a/doc/string/delete_suffix.rdoc
+++ b/doc/string/delete_suffix.rdoc
@@ -1,8 +1,10 @@
Returns a copy of +self+ with trailing substring <tt>suffix</tt> removed:
- 'hello'.delete_suffix('llo') # => "he"
- 'hello'.delete_suffix('hel') # => "hello"
- 'тест'.delete_suffix('ст') # => "те"
+ 'foo'.delete_suffix('o') # => "fo"
+ 'foo'.delete_suffix('oo') # => "f"
+ 'foo'.delete_suffix('foo') # => ""
+ 'foo'.delete_suffix('f') # => "foo"
+ 'foo'.delete_suffix('x') # => "foo"
'こんにちは'.delete_suffix('ちは') # => "こんに"
-Related: String#delete_suffix!, String#delete_prefix.
+Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
diff --git a/doc/string/downcase.rdoc b/doc/string/downcase.rdoc
new file mode 100644
index 0000000000..d5fffa037b
--- /dev/null
+++ b/doc/string/downcase.rdoc
@@ -0,0 +1,20 @@
+Returns a new string containing the downcased characters in +self+:
+
+ 'HELLO'.downcase # => "hello"
+ 'STRAẞE'.downcase # => "straße"
+ 'ПРИВЕТ'.downcase # => "привет"
+ 'RubyGems.org'.downcase # => "rubygems.org"
+
+Some characters (and some character sets) do not have upcase and downcase versions;
+see {Case Mapping}[rdoc-ref:case_mapping.rdoc]:
+
+ s = '1, 2, 3, ...'
+ s.downcase == s # => true
+ s = 'こんにちは'
+ s.downcase == s # => true
+
+The casing is affected by the given +mapping+,
+which may be +:ascii+, +:fold+, or +:turkic+;
+see {Case Mappings}[rdoc-ref:case_mapping.rdoc@Case+Mappings].
+
+Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
diff --git a/doc/string/dump.rdoc b/doc/string/dump.rdoc
new file mode 100644
index 0000000000..add3c35662
--- /dev/null
+++ b/doc/string/dump.rdoc
@@ -0,0 +1,89 @@
+For an ordinary string, this method, +String#dump+,
+returns a printable ASCII-only version of +self+, enclosed in double-quotes.
+
+For a dumped string, method String#undump is the inverse of +String#dump+;
+it returns a "restored" version of +self+,
+where all the dumping changes have been undone.
+
+In the simplest case, the dumped string contains the original string,
+enclosed in double-quotes;
+this example is done in +irb+ (interactive Ruby), which uses method `inspect` to render the results:
+
+ s = 'hello' # => "hello"
+ s.dump # => "\"hello\""
+ s.dump.undump # => "hello"
+
+Keep in mind that in the second line above:
+
+- The outer double-quotes are put on by +inspect+,
+ and _are_ _not_ part of the output of #dump.
+- The inner double-quotes _are_ part of the output of +dump+,
+ and are escaped by +inspect+ because they are within the outer double-quotes.
+
+To avoid confusion, we'll use this helper method to omit the outer double-quotes:
+
+ def dump(s)
+ print "String: ", s, "\n"
+ print "Dumped: ", s.dump, "\n"
+ print "Undumped: ", s.dump.undump, "\n"
+ end
+
+So that for string <tt>'hello'</tt>, we'll see:
+
+ String: hello
+ Dumped: "hello"
+ Undumped: hello
+
+In a dump, certain special characters are escaped:
+
+ String: "
+ Dumped: "\""
+ Undumped: "
+
+ String: \
+ Dumped: "\\"
+ Undumped: \
+
+In a dump, unprintable characters are replaced by printable ones;
+the unprintable characters are the whitespace characters (other than space itself);
+here we see the ordinals for those characers, together with explanatory text:
+
+ h = {
+ 7 => 'Alert (BEL)',
+ 8 => 'Backspace (BS)',
+ 9 => 'Horizontal tab (HT)',
+ 10 => 'Linefeed (LF)',
+ 11 => 'Vertical tab (VT)',
+ 12 => 'Formfeed (FF)',
+ 13 => 'Carriage return (CR)'
+ }
+
+In this example, the dumped output is printed by method #inspect,
+and so contains both outer double-quotes and escaped inner double-quotes:
+
+ s = ''
+ h.keys.each {|i| s << i } # => [7, 8, 9, 10, 11, 12, 13]
+ s # => "\a\b\t\n\v\f\r"
+ s.dump # => "\"\\a\\b\\t\\n\\v\\f\\r\""
+
+If +self+ is encoded in UTF-8 and contains Unicode characters,
+each Unicode character is dumped as a Unicode escape sequence:
+
+ String: こんにちは
+ Dumped: "\u3053\u3093\u306B\u3061\u306F"
+ Undumped: こんにちは
+
+If the encoding of +self+ is not ASCII-compatible
+(i.e., if <tt>self.encoding.ascii_compatible?</tt> returns +false+),
+each ASCII-compatible byte is dumped as an ASCII character,
+and all other bytes are dumped as hexadecimal;
+also appends <tt>.dup.force_encoding(\"encoding\")</tt>,
+where <tt><encoding></tt> is <tt>self.encoding.name</tt>:
+
+ String: hello
+ Dumped: "\xFE\xFF\x00h\x00e\x00l\x00l\x00o".dup.force_encoding("UTF-16")
+ Undumped: hello
+
+ String: こんにちは
+ Dumped: "\xFE\xFF0S0\x930k0a0o".dup.force_encoding("UTF-16")
+ Undumped: こんにちは
diff --git a/doc/string/each_byte.rdoc b/doc/string/each_byte.rdoc
index 643118fea3..642d71e84b 100644
--- a/doc/string/each_byte.rdoc
+++ b/doc/string/each_byte.rdoc
@@ -1,17 +1,15 @@
-Calls the given block with each successive byte from +self+;
+With a block given, calls the block with each successive byte from +self+;
returns +self+:
- 'hello'.each_byte {|byte| print byte, ' ' }
- print "\n"
- 'тест'.each_byte {|byte| print byte, ' ' }
- print "\n"
- 'こんにちは'.each_byte {|byte| print byte, ' ' }
- print "\n"
+ a = []
+ 'hello'.each_byte {|byte| a.push(byte) } # Five 1-byte characters.
+ a # => [104, 101, 108, 108, 111]
+ a = []
+ 'こんにちは'.each_byte {|byte| a.push(byte) } # Five 3-byte characters.
+ a # => [227, 129, 147, 227, 130, 147, 227, 129, 171, 227, 129, 161, 227, 129, 175]
-Output:
+With no block given, returns an enumerator.
+
+Related: see {Iterating}[rdoc-ref:String@Iterating].
- 104 101 108 108 111
- 209 130 208 181 209 129 209 130
- 227 129 147 227 130 147 227 129 171 227 129 161 227 129 175
-Returns an enumerator if no block is given.
diff --git a/doc/string/each_char.rdoc b/doc/string/each_char.rdoc
index e5ae5a1812..2dd56711d3 100644
--- a/doc/string/each_char.rdoc
+++ b/doc/string/each_char.rdoc
@@ -1,17 +1,17 @@
-Calls the given block with each successive character from +self+;
+With a block given, calls the block with each successive character from +self+;
returns +self+:
- 'hello'.each_char {|char| print char, ' ' }
- print "\n"
- 'тест'.each_char {|char| print char, ' ' }
- print "\n"
- 'こんにちは'.each_char {|char| print char, ' ' }
- print "\n"
+ a = []
+ 'hello'.each_char do |char|
+ a.push(char)
+ end
+ a # => ["h", "e", "l", "l", "o"]
+ a = []
+ 'こんにちは'.each_char do |char|
+ a.push(char)
+ end
+ a # => ["こ", "ん", "に", "ち", "は"]
-Output:
+With no block given, returns an enumerator.
- h e l l o
- т е с т
- こ ん に ち は
-
-Returns an enumerator if no block is given.
+Related: see {Iterating}[rdoc-ref:String@Iterating].
diff --git a/doc/string/each_codepoint.rdoc b/doc/string/each_codepoint.rdoc
index 88bfcbd1c0..8e4e7545e6 100644
--- a/doc/string/each_codepoint.rdoc
+++ b/doc/string/each_codepoint.rdoc
@@ -1,18 +1,18 @@
-Calls the given block with each successive codepoint from +self+;
-each codepoint is the integer value for a character;
+With a block given, calls the block with each successive codepoint from +self+;
+each {codepoint}[https://en.wikipedia.org/wiki/Code_point] is the integer value for a character;
returns +self+:
- 'hello'.each_codepoint {|codepoint| print codepoint, ' ' }
- print "\n"
- 'тест'.each_codepoint {|codepoint| print codepoint, ' ' }
- print "\n"
- 'こんにちは'.each_codepoint {|codepoint| print codepoint, ' ' }
- print "\n"
+ a = []
+ 'hello'.each_codepoint do |codepoint|
+ a.push(codepoint)
+ end
+ a # => [104, 101, 108, 108, 111]
+ a = []
+ 'こんにちは'.each_codepoint do |codepoint|
+ a.push(codepoint)
+ end
+ a # => [12371, 12435, 12395, 12385, 12399]
-Output:
+With no block given, returns an enumerator.
- 104 101 108 108 111
- 1090 1077 1089 1090
- 12371 12435 12395 12385 12399
-
-Returns an enumerator if no block is given.
+Related: see {Iterating}[rdoc-ref:String@Iterating].
diff --git a/doc/string/each_grapheme_cluster.rdoc b/doc/string/each_grapheme_cluster.rdoc
index 40be95fcac..384cd6967d 100644
--- a/doc/string/each_grapheme_cluster.rdoc
+++ b/doc/string/each_grapheme_cluster.rdoc
@@ -1,12 +1,19 @@
-Calls the given block with each successive grapheme cluster from +self+
+With a block given, calls the given block with each successive grapheme cluster from +self+
(see {Unicode Grapheme Cluster Boundaries}[https://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries]);
returns +self+:
- s = "\u0061\u0308-pqr-\u0062\u0308-xyz-\u0063\u0308" # => "ä-pqr-b̈-xyz-c̈"
- s.each_grapheme_cluster {|gc| print gc, ' ' }
+ a = []
+ 'hello'.each_grapheme_cluster do |grapheme_cluster|
+ a.push(grapheme_cluster)
+ end
+ a # => ["h", "e", "l", "l", "o"]
-Output:
+ a = []
+ 'こんにちは'.each_grapheme_cluster do |grapheme_cluster|
+ a.push(grapheme_cluster)
+ end
+ a # => ["こ", "ん", "に", "ち", "は"]
- ä - p q r - b̈ - x y z - c̈
+With no block given, returns an enumerator.
-Returns an enumerator if no block is given.
+Related: see {Iterating}[rdoc-ref:String@Iterating].
diff --git a/doc/string/each_line.rdoc b/doc/string/each_line.rdoc
index e254c22d40..217c188e35 100644
--- a/doc/string/each_line.rdoc
+++ b/doc/string/each_line.rdoc
@@ -1,9 +1,12 @@
-With a block given, forms the substrings ("lines")
+With a block given, forms the substrings (lines)
that are the result of splitting +self+
-at each occurrence of the given line separator +line_sep+;
+at each occurrence of the given +record_separator+;
passes each line to the block;
-returns +self+:
+returns +self+.
+With the default +record_separator+:
+
+ $/ # => "\n"
s = <<~EOT
This is the first line.
This is line two.
@@ -11,7 +14,6 @@ returns +self+:
This is line four.
This is line five.
EOT
-
s.each_line {|line| p line }
Output:
@@ -22,9 +24,10 @@ Output:
"This is line four.\n"
"This is line five.\n"
-With a different +line_sep+:
+With a different +record_separator+:
- s.each_line(' is ') {|line| p line }
+ record_separator = ' is '
+ s.each_line(record_separator) {|line| p line }
Output:
@@ -34,7 +37,7 @@ Output:
"line four.\nThis is "
"line five.\n"
-With +chomp+ as +true+, removes the trailing +line_sep+ from each line:
+With +chomp+ as +true+, removes the trailing +record_separator+ from each line:
s.each_line(chomp: true) {|line| p line }
@@ -46,11 +49,12 @@ Output:
"This is line four."
"This is line five."
-With an empty string as +line_sep+,
+With an empty string as +record_separator+,
forms and passes "paragraphs" by splitting at each occurrence
of two or more newlines:
- s.each_line('') {|line| p line }
+ record_separator = ''
+ s.each_line(record_separator) {|line| p line }
Output:
@@ -58,3 +62,5 @@ Output:
"This is line four.\nThis is line five.\n"
With no block given, returns an enumerator.
+
+Related: see {Iterating}[rdoc-ref:String@Iterating].
diff --git a/doc/string/encode.rdoc b/doc/string/encode.rdoc
index 65872fdfd4..14b959ffff 100644
--- a/doc/string/encode.rdoc
+++ b/doc/string/encode.rdoc
@@ -1,4 +1,6 @@
-Returns a copy of +self+ transcoded as determined by +dst_encoding+.
+Returns a copy of +self+ transcoded as determined by +dst_encoding+;
+see {Encodings}[rdoc-ref:encodings.rdoc].
+
By default, raises an exception if +self+
contains an invalid byte or a character not defined in +dst_encoding+;
that behavior may be modified by encoding options; see below.
@@ -45,3 +47,4 @@ given, conversion from an encoding +enc+ to the same encoding +enc+
no-op, i.e. the string is simply copied without any changes, and no
exceptions are raised, even if there are invalid bytes.
+Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
diff --git a/doc/string/end_with_p.rdoc b/doc/string/end_with_p.rdoc
index f959cf7aaa..9a95d74fde 100644
--- a/doc/string/end_with_p.rdoc
+++ b/doc/string/end_with_p.rdoc
@@ -1,11 +1,9 @@
-Returns whether +self+ ends with any of the given +strings+.
+Returns whether +self+ ends with any of the given +strings+:
-Returns +true+ if any given string matches the end, +false+ otherwise:
+ 'foo'.end_with?('oo') # => true
+ 'foo'.end_with?('bar', 'oo') # => true
+ 'foo'.end_with?('bar', 'baz') # => false
+ 'foo'.end_with?('') # => true
+ 'こんにちは'.end_with?('は') # => true
- 'hello'.end_with?('ello') #=> true
- 'hello'.end_with?('heaven', 'ello') #=> true
- 'hello'.end_with?('heaven', 'paradise') #=> false
- 'тест'.end_with?('т') # => true
- 'こんにちは'.end_with?('は') # => true
-
-Related: String#start_with?.
+Related: see {Querying}[rdoc-ref:String@Querying].
diff --git a/doc/string/eql_p.rdoc b/doc/string/eql_p.rdoc
new file mode 100644
index 0000000000..85409c5ed6
--- /dev/null
+++ b/doc/string/eql_p.rdoc
@@ -0,0 +1,18 @@
+Returns whether +self+ and +object+ have the same length and content:
+
+ s = 'foo'
+ s.eql?('foo') # => true
+ s.eql?('food') # => false
+ s.eql?('FOO') # => false
+
+Returns +false+ if the two strings' encodings are not compatible:
+
+ s0 = "äöü" # => "äöü"
+ s1 = s0.encode(Encoding::ISO_8859_1) # => "\xE4\xF6\xFC"
+ s0.encoding # => #<Encoding:UTF-8>
+ s1.encoding # => #<Encoding:ISO-8859-1>
+ s0.eql?(s1) # => false
+
+See {Encodings}[rdoc-ref:encodings.rdoc].
+
+Related: see {Querying}[rdoc-ref:String@Querying].
diff --git a/doc/string/force_encoding.rdoc b/doc/string/force_encoding.rdoc
index fd9615caaa..a509e67f80 100644
--- a/doc/string/force_encoding.rdoc
+++ b/doc/string/force_encoding.rdoc
@@ -1,5 +1,6 @@
-Changes the encoding of +self+ to +encoding+,
+Changes the encoding of +self+ to the given +encoding+,
which may be a string encoding name or an Encoding object;
+does not change the underlying bytes;
returns self:
s = 'łał'
@@ -7,14 +8,14 @@ returns self:
s.encoding # => #<Encoding:UTF-8>
s.force_encoding('ascii') # => "\xC5\x82a\xC5\x82"
s.encoding # => #<Encoding:US-ASCII>
-
-Does not change the underlying bytes:
-
+ s.valid_encoding? # => true
s.bytes # => [197, 130, 97, 197, 130]
Makes the change even if the given +encoding+ is invalid
for +self+ (as is the change above):
- s.valid_encoding? # => false
- s.force_encoding(Encoding::UTF_8) # => "łał"
- s.valid_encoding? # => true
+ s.valid_encoding? # => false
+
+See {Encodings}[rdoc-ref:encodings.rdoc].
+
+Related: see {Modifying}[rdoc-ref:String@Modifying].
diff --git a/doc/string/getbyte.rdoc b/doc/string/getbyte.rdoc
new file mode 100644
index 0000000000..1d0ed2a5a4
--- /dev/null
+++ b/doc/string/getbyte.rdoc
@@ -0,0 +1,23 @@
+Returns the byte at zero-based +index+ as an integer:
+
+ s = 'foo'
+ s.getbyte(0) # => 102
+ s.getbyte(1) # => 111
+ s.getbyte(2) # => 111
+
+Counts backward from the end if +index+ is negative:
+
+ s.getbyte(-3) # => 102
+
+Returns +nil+ if +index+ is out of range:
+
+ s.getbyte(3) # => nil
+ s.getbyte(-4) # => nil
+
+More examples:
+
+ s = 'こんにちは'
+ s.bytes # => [227, 129, 147, 227, 130, 147, 227, 129, 171, 227, 129, 161, 227, 129, 175]
+ s.getbyte(2) # => 147
+
+Related: see {Converting to Non-String}[rdoc-ref:String@Converting+to+Non--5CString].
diff --git a/doc/string/grapheme_clusters.rdoc b/doc/string/grapheme_clusters.rdoc
index 8c7f5a7259..07ea1e318b 100644
--- a/doc/string/grapheme_clusters.rdoc
+++ b/doc/string/grapheme_clusters.rdoc
@@ -1,6 +1,19 @@
Returns an array of the grapheme clusters in +self+
(see {Unicode Grapheme Cluster Boundaries}[https://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries]):
- s = "\u0061\u0308-pqr-\u0062\u0308-xyz-\u0063\u0308" # => "ä-pqr-b̈-xyz-c̈"
+ s = "ä-pqr-b̈-xyz-c̈"
+ s.size # => 16
+ s.bytesize # => 19
+ s.grapheme_clusters.size # => 13
s.grapheme_clusters
# => ["ä", "-", "p", "q", "r", "-", "b̈", "-", "x", "y", "z", "-", "c̈"]
+
+Details:
+
+ s = "ä"
+ s.grapheme_clusters # => ["ä"] # One grapheme cluster.
+ s.bytes # => [97, 204, 136] # Three bytes.
+ s.chars # => ["a", "̈"] # Two characters.
+ s.chars.map {|char| char.ord } # => [97, 776] # Their values.
+
+Related: see {Converting to Non-String}[rdoc-ref:String@Converting+to+Non--5CString].
diff --git a/doc/string/hash.rdoc b/doc/string/hash.rdoc
new file mode 100644
index 0000000000..fe94770ed9
--- /dev/null
+++ b/doc/string/hash.rdoc
@@ -0,0 +1,19 @@
+Returns the integer hash value for +self+.
+
+Two \String objects that have identical content and compatible encodings
+also have the same hash value;
+see Object#hash and {Encodings}[rdoc-ref:encodings.rdoc]:
+
+ s = 'foo'
+ h = s.hash # => -569050784
+ h == 'foo'.hash # => true
+ h == 'food'.hash # => false
+ h == 'FOO'.hash # => false
+
+ s0 = "äöü"
+ s1 = s0.encode(Encoding::ISO_8859_1)
+ s0.encoding # => #<Encoding:UTF-8>
+ s1.encoding # => #<Encoding:ISO-8859-1>
+ s0.hash == s1.hash # => false
+
+Related: see {Querying}[rdoc-ref:String@Querying].
diff --git a/doc/string/index.rdoc b/doc/string/index.rdoc
index ce09a37bdf..c3cff24dac 100644
--- a/doc/string/index.rdoc
+++ b/doc/string/index.rdoc
@@ -1,31 +1,31 @@
-Returns the integer index of the first match for the given argument,
-or +nil+ if none found;
-the search of +self+ is forward, and begins at position +offset+ (in characters).
+Returns the integer position of the first substring that matches the given argument +pattern+,
+or +nil+ if none found.
-With string argument +substring+,
+When +pattern+ is a string,
returns the index of the first matching substring in +self+:
'foo'.index('f') # => 0
'foo'.index('o') # => 1
'foo'.index('oo') # => 1
'foo'.index('ooo') # => nil
- 'тест'.index('с') # => 2
- 'こんにちは'.index('ち') # => 3
+ 'こんにちは'.index('ち') # => 3
-With Regexp argument +regexp+, returns the index of the first match in +self+:
+When +pattern+ is a Regexp, returns the index of the first match in +self+:
'foo'.index(/o./) # => 1
'foo'.index(/.o/) # => 0
-With positive integer +offset+, begins the search at position +offset+:
+When +offset+ is non-negative, begins the search at position +offset+;
+the returned index is relative to the beginning of +self+:
- 'foo'.index('o', 1) # => 1
- 'foo'.index('o', 2) # => 2
- 'foo'.index('o', 3) # => nil
- 'тест'.index('с', 1) # => 2
- 'こんにちは'.index('ち', 2) # => 3
+ 'bar'.index('r', 0) # => 2
+ 'bar'.index('r', 1) # => 2
+ 'bar'.index('r', 2) # => 2
+ 'bar'.index('r', 3) # => nil
+ 'bar'.index(/[r-z]/, 0) # => 2
+ 'こんにちは'.index('ち', 2) # => 3
-With negative integer +offset+, selects the search position by counting backward
+With negative integer argument +offset+, selects the search position by counting backward
from the end of +self+:
'foo'.index('o', -1) # => 2
@@ -35,4 +35,4 @@ from the end of +self+:
'foo'.index(/o./, -2) # => 1
'foo'.index(/.o/, -2) # => 1
-Related: String#rindex.
+Related: see {Querying}[rdoc-ref:String@Querying].
diff --git a/doc/string/insert.rdoc b/doc/string/insert.rdoc
new file mode 100644
index 0000000000..73205f2069
--- /dev/null
+++ b/doc/string/insert.rdoc
@@ -0,0 +1,15 @@
+Inserts the given +other_string+ into +self+; returns +self+.
+
+If the given +index+ is non-negative, inserts +other_string+ at offset +index+:
+
+ 'foo'.insert(0, 'bar') # => "barfoo"
+ 'foo'.insert(1, 'bar') # => "fbaroo"
+ 'foo'.insert(3, 'bar') # => "foobar"
+ 'こんにちは'.insert(2, 'bar') # => "こんbarにちは"
+
+If the +index+ is negative, counts backward from the end of +self+
+and inserts +other_string+ _after_ the offset:
+
+ 'foo'.insert(-2, 'bar') # => "fobaro"
+
+Related: see {Modifying}[rdoc-ref:String@Modifying].
diff --git a/doc/string/inspect.rdoc b/doc/string/inspect.rdoc
new file mode 100644
index 0000000000..907828c2af
--- /dev/null
+++ b/doc/string/inspect.rdoc
@@ -0,0 +1,38 @@
+Returns a printable version of +self+, enclosed in double-quotes.
+
+Most printable characters are rendered simply as themselves:
+
+ 'abc'.inspect # => "\"abc\""
+ '012'.inspect # => "\"012\""
+ ''.inspect # => "\"\""
+ "\u000012".inspect # => "\"\\u000012\""
+ 'こんにちは'.inspect # => "\"こんにちは\""
+
+But printable characters double-quote (<tt>'"'</tt>) and backslash and (<tt>'\\'</tt>) are escaped:
+
+ '"'.inspect # => "\"\\\"\""
+ '\\'.inspect # => "\"\\\\\""
+
+Unprintable characters are the {ASCII characters}[https://en.wikipedia.org/wiki/ASCII]
+whose values are in range <tt>0..31</tt>,
+along with the character whose value is +127+.
+
+Most of these characters are rendered thus:
+
+ 0.chr.inspect # => "\"\\x00\""
+ 1.chr.inspect # => "\"\\x01\""
+ 2.chr.inspect # => "\"\\x02\""
+ # ...
+
+A few, however, have special renderings:
+
+ 7.chr.inspect # => "\"\\a\"" # BEL
+ 8.chr.inspect # => "\"\\b\"" # BS
+ 9.chr.inspect # => "\"\\t\"" # TAB
+ 10.chr.inspect # => "\"\\n\"" # LF
+ 11.chr.inspect # => "\"\\v\"" # VT
+ 12.chr.inspect # => "\"\\f\"" # FF
+ 13.chr.inspect # => "\"\\r\"" # CR
+ 27.chr.inspect # => "\"\\e\"" # ESC
+
+Related: see {Converting to Non-String}[rdoc-ref:String@Converting+to+Non--5CString].
diff --git a/doc/string/intern.rdoc b/doc/string/intern.rdoc
new file mode 100644
index 0000000000..eded6ac3d7
--- /dev/null
+++ b/doc/string/intern.rdoc
@@ -0,0 +1,8 @@
+Returns the Symbol object derived from +self+,
+creating it if it did not already exist:
+
+ 'foo'.intern # => :foo
+ 'こんにちは'.intern # => :こんにちは
+
+Related: see {Converting to Non-String}[rdoc-ref:String@Converting+to+Non--5CString].
+
diff --git a/doc/string/length.rdoc b/doc/string/length.rdoc
index 544bca269f..eb68edb10c 100644
--- a/doc/string/length.rdoc
+++ b/doc/string/length.rdoc
@@ -1,12 +1,11 @@
Returns the count of characters (not bytes) in +self+:
'foo'.length # => 3
- 'тест'.length # => 4
- 'こんにちは'.length # => 5
+ 'こんにちは'.length # => 5
Contrast with String#bytesize:
'foo'.bytesize # => 3
- 'тест'.bytesize # => 8
- 'こんにちは'.bytesize # => 15
+ 'こんにちは'.bytesize # => 15
+Related: see {Querying}[rdoc-ref:String@Querying].
diff --git a/doc/string/ljust.rdoc b/doc/string/ljust.rdoc
index 8e23c1fc8f..a8ca62ee76 100644
--- a/doc/string/ljust.rdoc
+++ b/doc/string/ljust.rdoc
@@ -1,16 +1,13 @@
-Returns a left-justified copy of +self+.
-
-If integer argument +size+ is greater than the size (in characters) of +self+,
-returns a new string of length +size+ that is a copy of +self+,
-left justified and padded on the right with +pad_string+:
+Returns a copy of +self+, left-justified and, if necessary, right-padded with the +pad_string+:
'hello'.ljust(10) # => "hello "
' hello'.ljust(10) # => " hello "
'hello'.ljust(10, 'ab') # => "helloababa"
- 'тест'.ljust(10) # => "тест "
- 'こんにちは'.ljust(10) # => "こんにちは "
+ 'こんにちは'.ljust(10) # => "こんにちは "
-If +size+ is not greater than the size of +self+, returns a copy of +self+:
+If <tt>width <= self.length</tt>, returns a copy of +self+:
'hello'.ljust(5) # => "hello"
- 'hello'.ljust(1) # => "hello"
+ 'hello'.ljust(1) # => "hello" # Does not truncate to width.
+
+Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
diff --git a/doc/string/new.rdoc b/doc/string/new.rdoc
index d955e61c87..e2752d6e1f 100644
--- a/doc/string/new.rdoc
+++ b/doc/string/new.rdoc
@@ -1,34 +1,38 @@
-Returns a new \String that is a copy of +string+.
+Returns a new \String object containing the given +string+.
-With no arguments, returns the empty string with the Encoding <tt>ASCII-8BIT</tt>:
+The +options+ are optional keyword options (see below).
- s = String.new
- s # => ""
- s.encoding # => #<Encoding:ASCII-8BIT>
+With no argument given and keyword +encoding+ also not given,
+returns an empty string with the Encoding <tt>ASCII-8BIT</tt>:
-With optional argument +string+ and no keyword arguments,
-returns a copy of +string+ with the same encoding:
+ s = String.new # => ""
+ s.encoding # => #<Encoding:ASCII-8BIT>
- String.new('foo') # => "foo"
- String.new('тест') # => "тест"
- String.new('こんにちは') # => "こんにちは"
+With argument +string+ given and keyword option +encoding+ not given,
+returns a new string with the same encoding as +string+:
+
+ s0 = 'foo'.encode(Encoding::UTF_16)
+ s1 = String.new(s0)
+ s1.encoding # => #<Encoding:UTF-16 (dummy)>
(Unlike \String.new,
a {string literal}[rdoc-ref:syntax/literals.rdoc@String+Literals] like <tt>''</tt> or a
{here document literal}[rdoc-ref:syntax/literals.rdoc@Here+Document+Literals]
always has {script encoding}[rdoc-ref:encodings.rdoc@Script+Encoding].)
-With optional keyword argument +encoding+, returns a copy of +string+
-with the specified encoding;
+With keyword option +encoding+ given,
+returns a string with the specified encoding;
the +encoding+ may be an Encoding object, an encoding name,
or an encoding name alias:
+ String.new(encoding: Encoding::US_ASCII).encoding # => #<Encoding:US-ASCII>
+ String.new('', encoding: Encoding::US_ASCII).encoding # => #<Encoding:US-ASCII>
String.new('foo', encoding: Encoding::US_ASCII).encoding # => #<Encoding:US-ASCII>
String.new('foo', encoding: 'US-ASCII').encoding # => #<Encoding:US-ASCII>
String.new('foo', encoding: 'ASCII').encoding # => #<Encoding:US-ASCII>
The given encoding need not be valid for the string's content,
-and that validity is not checked:
+and its validity is not checked:
s = String.new('こんにちは', encoding: 'ascii')
s.valid_encoding? # => false
@@ -37,15 +41,11 @@ But the given +encoding+ itself is checked:
String.new('foo', encoding: 'bar') # Raises ArgumentError.
-With optional keyword argument +capacity+, returns a copy of +string+
-(or an empty string, if +string+ is not given);
-the given +capacity+ is advisory only,
+With keyword option +capacity+ given,
+the given value is advisory only,
and may or may not set the size of the internal buffer,
which may in turn affect performance:
- String.new(capacity: 1)
- String.new('foo', capacity: 4096)
-
-The +string+, +encoding+, and +capacity+ arguments may all be used together:
-
- String.new('hello', encoding: 'UTF-8', capacity: 25)
+ String.new('foo', capacity: 1) # Buffer size is at least 4 (includes terminal null byte).
+ String.new('foo', capacity: 4096) # Buffer size is at least 4;
+ # may be equal to, greater than, or less than 4096.
diff --git a/doc/string/ord.rdoc b/doc/string/ord.rdoc
index d586363d44..87b469db02 100644
--- a/doc/string/ord.rdoc
+++ b/doc/string/ord.rdoc
@@ -2,5 +2,6 @@ Returns the integer ordinal of the first character of +self+:
'h'.ord # => 104
'hello'.ord # => 104
- 'тест'.ord # => 1090
'こんにちは'.ord # => 12371
+
+Related: see {Converting to Non-String}[rdoc-ref:String@Converting+to+Non--5CString].
diff --git a/doc/string/partition.rdoc b/doc/string/partition.rdoc
index ebe575e8eb..614ad029d4 100644
--- a/doc/string/partition.rdoc
+++ b/doc/string/partition.rdoc
@@ -1,24 +1,43 @@
Returns a 3-element array of substrings of +self+.
-Matches a pattern against +self+, scanning from the beginning.
-The pattern is:
+If +pattern+ is matched, returns the array:
-- +string_or_regexp+ itself, if it is a Regexp.
-- <tt>Regexp.quote(string_or_regexp)</tt>, if +string_or_regexp+ is a string.
+ [pre_match, first_match, post_match]
-If the pattern is matched, returns pre-match, first-match, post-match:
+where:
- 'hello'.partition('l') # => ["he", "l", "lo"]
- 'hello'.partition('ll') # => ["he", "ll", "o"]
- 'hello'.partition('h') # => ["", "h", "ello"]
- 'hello'.partition('o') # => ["hell", "o", ""]
- 'hello'.partition(/l+/) #=> ["he", "ll", "o"]
- 'hello'.partition('') # => ["", "", "hello"]
- 'тест'.partition('т') # => ["", "т", "ест"]
- 'こんにちは'.partition('に') # => ["こん", "に", "ちは"]
+- +first_match+ is the first-found matching substring.
+- +pre_match+ and +post_match+ are the preceding and following substrings.
-If the pattern is not matched, returns a copy of +self+ and two empty strings:
+If +pattern+ is not matched, returns the array:
- 'hello'.partition('x') # => ["hello", "", ""]
+ [self.dup, "", ""]
-Related: String#rpartition, String#split.
+Note that in the examples below, a returned string <tt>'hello'</tt>
+is a copy of +self+, not +self+.
+
+If +pattern+ is a Regexp, performs the equivalent of <tt>self.match(pattern)</tt>
+(also setting {matched-data variables}[rdoc-ref:language/globals.md@Matched+Data]):
+
+ 'hello'.partition(/h/) # => ["", "h", "ello"]
+ 'hello'.partition(/l/) # => ["he", "l", "lo"]
+ 'hello'.partition(/l+/) # => ["he", "ll", "o"]
+ 'hello'.partition(/o/) # => ["hell", "o", ""]
+ 'hello'.partition(/^/) # => ["", "", "hello"]
+ 'hello'.partition(//) # => ["", "", "hello"]
+ 'hello'.partition(/$/) # => ["hello", "", ""]
+ 'hello'.partition(/x/) # => ["hello", "", ""]
+
+If +pattern+ is not a Regexp, converts it to a string (if it is not already one),
+then performs the equivalent of <tt>self.index(pattern)</tt>
+(and does _not_ set {matched-data global variables}[rdoc-ref:language/globals.md@Matched+Data]):
+
+ 'hello'.partition('h') # => ["", "h", "ello"]
+ 'hello'.partition('l') # => ["he", "l", "lo"]
+ 'hello'.partition('ll') # => ["he", "ll", "o"]
+ 'hello'.partition('o') # => ["hell", "o", ""]
+ 'hello'.partition('') # => ["", "", "hello"]
+ 'hello'.partition('x') # => ["hello", "", ""]
+ 'こんにちは'.partition('に') # => ["こん", "に", "ちは"]
+
+Related: see {Converting to Non-String}[rdoc-ref:String@Converting+to+Non--5CString].
diff --git a/doc/string/rindex.rdoc b/doc/string/rindex.rdoc
new file mode 100644
index 0000000000..2b81c3716d
--- /dev/null
+++ b/doc/string/rindex.rdoc
@@ -0,0 +1,51 @@
+Returns the integer position of the _last_ substring that matches the given argument +pattern+,
+or +nil+ if none found.
+
+When +pattern+ is a string, returns the index of the last matching substring in self:
+
+ 'foo'.rindex('f') # => 0
+ 'foo'.rindex('o') # => 2
+ 'foo'.rindex('oo' # => 1
+ 'foo'.rindex('ooo') # => nil
+ 'こんにちは'.rindex('ち') # => 3
+
+When +pattern+ is a Regexp, returns the index of the last match in self:
+
+ 'foo'.rindex(/f/) # => 0
+ 'foo'.rindex(/o/) # => 2
+ 'foo'.rindex(/oo/) # => 1
+ 'foo'.rindex(/ooo/) # => nil
+
+When +offset+ is non-negative, it 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
+
+With negative integer argument +offset+,
+selects the search position by counting backward from the end of +self+:
+
+ 'foo'.rindex('o', -1) # => 2
+ 'foo'.rindex('o', -2) # => 1
+ 'foo'.rindex('o', -3) # => nil
+ 'foo'.rindex('o', -4) # => nil
+
+The last match means starting at the possible last position, not
+the last of longest matches:
+
+ 'foo'.rindex(/o+/) # => 2
+ $~ # => #<MatchData "o">
+
+To get the last longest match, combine with negative lookbehind:
+
+ 'foo'.rindex(/(?<!o)o+/) # => 1
+ $~ # => #<MatchData "oo">
+
+Or String#index with negative lookforward.
+
+ 'foo'.index(/o+(?!.*o)/) # => 1
+ $~ # => #<MatchData "oo">
+
+Related: see {Querying}[rdoc-ref:String@Querying].
diff --git a/doc/string/rjust.rdoc b/doc/string/rjust.rdoc
index 24e7bf3159..acd3f198d4 100644
--- a/doc/string/rjust.rdoc
+++ b/doc/string/rjust.rdoc
@@ -1,16 +1,17 @@
Returns a right-justified copy of +self+.
-If integer argument +size+ is greater than the size (in characters) of +self+,
-returns a new string of length +size+ that is a copy of +self+,
+If integer argument +width+ is greater than the size (in characters) of +self+,
+returns a new string of length +width+ that is a copy of +self+,
right justified and padded on the left with +pad_string+:
'hello'.rjust(10) # => " hello"
'hello '.rjust(10) # => " hello "
'hello'.rjust(10, 'ab') # => "ababahello"
- 'тест'.rjust(10) # => " тест"
'こんにちは'.rjust(10) # => " こんにちは"
-If +size+ is not greater than the size of +self+, returns a copy of +self+:
+If <tt>width <= self.size</tt>, returns a copy of +self+:
'hello'.rjust(5, 'ab') # => "hello"
'hello'.rjust(1, 'ab') # => "hello"
+
+Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
diff --git a/doc/string/rpartition.rdoc b/doc/string/rpartition.rdoc
index d24106fb9f..eed03949a5 100644
--- a/doc/string/rpartition.rdoc
+++ b/doc/string/rpartition.rdoc
@@ -1,24 +1,47 @@
Returns a 3-element array of substrings of +self+.
-Matches a pattern against +self+, scanning backwards from the end.
-The pattern is:
+Searches +self+ for a match of +pattern+, seeking the _last_ match.
-- +string_or_regexp+ itself, if it is a Regexp.
-- <tt>Regexp.quote(string_or_regexp)</tt>, if +string_or_regexp+ is a string.
+If +pattern+ is not matched, returns the array:
-If the pattern is matched, returns pre-match, last-match, post-match:
+ ["", "", self.dup]
- 'hello'.rpartition('l') # => ["hel", "l", "o"]
- 'hello'.rpartition('ll') # => ["he", "ll", "o"]
- 'hello'.rpartition('h') # => ["", "h", "ello"]
- 'hello'.rpartition('o') # => ["hell", "o", ""]
- 'hello'.rpartition(/l+/) # => ["hel", "l", "o"]
- 'hello'.rpartition('') # => ["hello", "", ""]
- 'тест'.rpartition('т') # => ["тес", "т", ""]
- 'こんにちは'.rpartition('に') # => ["こん", "に", "ちは"]
+If +pattern+ is matched, returns the array:
-If the pattern is not matched, returns two empty strings and a copy of +self+:
+ [pre_match, last_match, post_match]
- 'hello'.rpartition('x') # => ["", "", "hello"]
+where:
-Related: String#partition, String#split.
+- +last_match+ is the last-found matching substring.
+- +pre_match+ and +post_match+ are the preceding and following substrings.
+
+The pattern used is:
+
+- +pattern+ itself, if it is a Regexp.
+- <tt>Regexp.quote(pattern)</tt>, if +pattern+ is a string.
+
+Note that in the examples below, a returned string <tt>'hello'</tt> is a copy of +self+, not +self+.
+
+If +pattern+ is a Regexp, searches for the last matching substring
+(also setting {matched-data global variables}[rdoc-ref:language/globals.md@Matched+Data]):
+
+ 'hello'.rpartition(/l/) # => ["hel", "l", "o"]
+ 'hello'.rpartition(/ll/) # => ["he", "ll", "o"]
+ 'hello'.rpartition(/h/) # => ["", "h", "ello"]
+ 'hello'.rpartition(/o/) # => ["hell", "o", ""]
+ 'hello'.rpartition(//) # => ["hello", "", ""]
+ 'hello'.rpartition(/x/) # => ["", "", "hello"]
+ 'こんにちは'.rpartition(/に/) # => ["こん", "に", "ちは"]
+
+If +pattern+ is not a Regexp, converts it to a string (if it is not already one),
+then searches for the last matching substring
+(and does _not_ set {matched-data global variables}[rdoc-ref:language/globals.md@Matched+Data]):
+
+ 'hello'.rpartition('l') # => ["hel", "l", "o"]
+ 'hello'.rpartition('ll') # => ["he", "ll", "o"]
+ 'hello'.rpartition('h') # => ["", "h", "ello"]
+ 'hello'.rpartition('o') # => ["hell", "o", ""]
+ 'hello'.rpartition('') # => ["hello", "", ""]
+ 'こんにちは'.rpartition('に') # => ["こん", "に", "ちは"]
+
+Related: see {Converting to Non-String}[rdoc-ref:String@Converting+to+Non--5CString].
diff --git a/doc/string/scan.rdoc b/doc/string/scan.rdoc
new file mode 100644
index 0000000000..04a2b02ff4
--- /dev/null
+++ b/doc/string/scan.rdoc
@@ -0,0 +1,35 @@
+Matches a pattern against +self+:
+
+- If +pattern+ is a Regexp, the pattern used is +pattern+ itself.
+- If +pattern+ is a string, the pattern used is <tt>Regexp.quote(pattern)</tt>.
+
+Generates a collection of matching results
+and updates {regexp-related global variables}[rdoc-ref:Regexp@Global+Variables]:
+
+- If the pattern contains no groups, each result is a matched substring.
+- If the pattern contains groups, each result is an array
+ containing a matched substring for each group.
+
+With no block given, returns an array of the results:
+
+ 'cruel world'.scan(/\w+/) # => ["cruel", "world"]
+ 'cruel world'.scan(/.../) # => ["cru", "el ", "wor"]
+ 'cruel world'.scan(/(...)/) # => [["cru"], ["el "], ["wor"]]
+ 'cruel world'.scan(/(..)(..)/) # => [["cr", "ue"], ["l ", "wo"]]
+ 'こんにちは'.scan(/../) # => ["こん", "にち"]
+ 'abracadabra'.scan('ab') # => ["ab", "ab"]
+ 'abracadabra'.scan('nosuch') # => []
+
+With a block given, calls the block with each result; returns +self+:
+
+ 'cruel world'.scan(/\w+/) {|w| p w }
+ # => "cruel"
+ # => "world"
+ 'cruel world'.scan(/(.)(.)/) {|x, y| p [x, y] }
+ # => ["c", "r"]
+ # => ["u", "e"]
+ # => ["l", " "]
+ # => ["w", "o"]
+ # => ["r", "l"]
+
+Related: see {Converting to Non-String}[rdoc-ref:String@Converting+to+Non--5CString].
diff --git a/doc/string/scrub.rdoc b/doc/string/scrub.rdoc
index 1a5b1c79d0..5ace376cdb 100644
--- a/doc/string/scrub.rdoc
+++ b/doc/string/scrub.rdoc
@@ -1,25 +1,22 @@
Returns a copy of +self+ with each invalid byte sequence replaced
by the given +replacement_string+.
-With no block given and no argument, replaces each invalid sequence
-with the default replacement string
-(<tt>"�"</tt> for a Unicode encoding, <tt>'?'</tt> otherwise):
+With no block given, replaces each invalid sequence
+with the given +default_replacement_string+
+(by default, <tt>"�"</tt> for a Unicode encoding, <tt>'?'</tt> otherwise):
- s = "foo\x81\x81bar"
- s.scrub # => "foo��bar"
+ "foo\x81\x81bar"scrub # => "foo��bar"
+ "foo\x81\x81bar".force_encoding('US-ASCII').scrub # => "foo??bar"
+ "foo\x81\x81bar".scrub('xyzzy') # => "fooxyzzyxyzzybar"
-With no block given and argument +replacement_string+ given,
-replaces each invalid sequence with that string:
+With a block given, calls the block with each invalid sequence,
+and replaces that sequence with the return value of the block:
- "foo\x81\x81bar".scrub('xyzzy') # => "fooxyzzyxyzzybar"
+ "foo\x81\x81bar".scrub {|sequence| p sequence; 'XYZZY' } # => "fooXYZZYXYZZYbar"
-With a block given, replaces each invalid sequence with the value
-of the block:
-
- "foo\x81\x81bar".scrub {|bytes| p bytes; 'XYZZY' }
- # => "fooXYZZYXYZZYbar"
-
-Output:
+Output :
"\x81"
"\x81"
+
+Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
diff --git a/doc/string/split.rdoc b/doc/string/split.rdoc
index 5ab065093b..1aee1de0a4 100644
--- a/doc/string/split.rdoc
+++ b/doc/string/split.rdoc
@@ -1,86 +1,101 @@
-Returns an array of substrings of +self+
-that are the result of splitting +self+
+Creates an array of substrings by splitting +self+
at each occurrence of the given field separator +field_sep+.
-When +field_sep+ is <tt>$;</tt>:
+With no arguments given,
+splits using the field separator <tt>$;</tt>,
+whose default value is +nil+.
-- If <tt>$;</tt> is +nil+ (its default value),
- the split occurs just as if +field_sep+ were given as a space character
- (see below).
+With no block given, returns the array of substrings:
-- If <tt>$;</tt> is a string,
- the split occurs just as if +field_sep+ were given as that string
- (see below).
+ 'abracadabra'.split('a') # => ["", "br", "c", "d", "br"]
-When +field_sep+ is <tt>' '</tt> and +limit+ is +nil+,
-the split occurs at each sequence of whitespace:
+When +field_sep+ is +nil+ or <tt>' '</tt> (a single space),
+splits at each sequence of whitespace:
- 'abc def ghi'.split(' ') => ["abc", "def", "ghi"]
- "abc \n\tdef\t\n ghi".split(' ') # => ["abc", "def", "ghi"]
- 'abc def ghi'.split(' ') => ["abc", "def", "ghi"]
- ''.split(' ') => []
+ 'foo bar baz'.split(nil) # => ["foo", "bar", "baz"]
+ 'foo bar baz'.split(' ') # => ["foo", "bar", "baz"]
+ "foo \n\tbar\t\n baz".split(' ') # => ["foo", "bar", "baz"]
+ 'foo bar baz'.split(' ') # => ["foo", "bar", "baz"]
+ ''.split(' ') # => []
-When +field_sep+ is a string different from <tt>' '</tt>
-and +limit+ is +nil+,
-the split occurs at each occurrence of +field_sep+;
-trailing empty substrings are not returned:
+When +field_sep+ is an empty string,
+splits at every character:
- 'abracadabra'.split('ab') => ["", "racad", "ra"]
- 'aaabcdaaa'.split('a') => ["", "", "", "bcd"]
- ''.split('a') => []
- '3.14159'.split('1') => ["3.", "4", "59"]
- '!@#$%^$&*($)_+'.split('$') # => ["!@#", "%^", "&*(", ")_+"]
- 'тест'.split('т') => ["", "ес"]
- 'こんにちは'.split('に') => ["こん", "ちは"]
+ 'abracadabra'.split('') # => ["a", "b", "r", "a", "c", "a", "d", "a", "b", "r", "a"]
+ ''.split('') # => []
+ 'こんにちは'.split('') # => ["こ", "ん", "に", "ち", "は"]
-When +field_sep+ is a Regexp and +limit+ is +nil+,
-the split occurs at each occurrence of a match;
-trailing empty substrings are not returned:
+When +field_sep+ is a non-empty string and different from <tt>' '</tt> (a single space),
+uses that string as the separator:
+
+ 'abracadabra'.split('a') # => ["", "br", "c", "d", "br"]
+ 'abracadabra'.split('ab') # => ["", "racad", "ra"]
+ ''.split('a') # => []
+ 'こんにちは'.split('に') # => ["こん", "ちは"]
+
+When +field_sep+ is a Regexp,
+splits at each occurrence of a matching substring:
'abracadabra'.split(/ab/) # => ["", "racad", "ra"]
- 'aaabcdaaa'.split(/a/) => ["", "", "", "bcd"]
- 'aaabcdaaa'.split(//) => ["a", "a", "a", "b", "c", "d", "a", "a", "a"]
'1 + 1 == 2'.split(/\W+/) # => ["1", "1", "2"]
+ 'abracadabra'.split(//) # => ["a", "b", "r", "a", "c", "a", "d", "a", "b", "r", "a"]
-If the \Regexp contains groups, their matches are also included
+If the \Regexp contains groups, their matches are included
in the returned array:
'1:2:3'.split(/(:)()()/, 2) # => ["1", ":", "", "", "2:3"]
-As seen above, if +limit+ is +nil+,
-trailing empty substrings are not returned;
-the same is true if +limit+ is zero:
+Argument +limit+ sets a limit on the size of the returned array;
+it also determines whether trailing empty strings are included in the returned array.
+
+When +limit+ is zero,
+there is no limit on the size of the array,
+but trailing empty strings are omitted:
+
+ 'abracadabra'.split('', 0) # => ["a", "b", "r", "a", "c", "a", "d", "a", "b", "r", "a"]
+ 'abracadabra'.split('a', 0) # => ["", "br", "c", "d", "br"] # Empty string after last 'a' omitted.
+
+When +limit+ is a positive integer,
+there is a limit on the size of the array (no more than <tt>n - 1</tt> splits occur),
+and trailing empty strings are included:
+
+ 'abracadabra'.split('', 3) # => ["a", "b", "racadabra"]
+ 'abracadabra'.split('a', 3) # => ["", "br", "cadabra"]
+ 'abracadabra'.split('', 30) # => ["a", "b", "r", "a", "c", "a", "d", "a", "b", "r", "a", ""]
+ 'abracadabra'.split('a', 30) # => ["", "br", "c", "d", "br", ""]
+ 'abracadabra'.split('', 1) # => ["abracadabra"]
+ 'abracadabra'.split('a', 1) # => ["abracadabra"]
+
+When +limit+ is negative,
+there is no limit on the size of the array,
+and trailing empty strings are omitted:
+
+ 'abracadabra'.split('', -1) # => ["a", "b", "r", "a", "c", "a", "d", "a", "b", "r", "a", ""]
+ 'abracadabra'.split('a', -1) # => ["", "br", "c", "d", "br", ""]
- 'aaabcdaaa'.split('a') => ["", "", "", "bcd"]
- 'aaabcdaaa'.split('a', 0) # => ["", "", "", "bcd"]
+If a block is given, it is called with each substring and returns +self+:
-If +limit+ is positive integer +n+, no more than <tt>n - 1-</tt>
-splits occur, so that at most +n+ substrings are returned,
-and trailing empty substrings are included:
+ 'foo bar baz'.split(' ') {|substring| p substring }
- 'aaabcdaaa'.split('a', 1) # => ["aaabcdaaa"]
- 'aaabcdaaa'.split('a', 2) # => ["", "aabcdaaa"]
- 'aaabcdaaa'.split('a', 5) # => ["", "", "", "bcd", "aa"]
- 'aaabcdaaa'.split('a', 7) # => ["", "", "", "bcd", "", "", ""]
- 'aaabcdaaa'.split('a', 8) # => ["", "", "", "bcd", "", "", ""]
+Output :
-Note that if +field_sep+ is a \Regexp containing groups,
-their matches are in the returned array, but do not count toward the limit.
+ "foo"
+ "bar"
+ "baz"
-If +limit+ is negative, it behaves the same as if +limit+ was +nil+,
-meaning that there is no limit,
-and trailing empty substrings are included:
+Note that the above example is functionally equivalent to:
- 'aaabcdaaa'.split('a', -1) # => ["", "", "", "bcd", "", "", ""]
+ 'foo bar baz'.split(' ').each {|substring| p substring }
-If a block is given, it is called with each substring:
+Output :
- 'abc def ghi'.split(' ') {|substring| p substring }
+ "foo"
+ "bar"
+ "baz"
-Output:
+But the latter:
- "abc"
- "def"
- "ghi"
+- Has poorer performance because it creates an intermediate array.
+- Returns an array (instead of +self+).
-Related: String#partition, String#rpartition.
+Related: see {Converting to Non-String}[rdoc-ref:String@Converting+to+Non--5CString].
diff --git a/doc/string/squeeze.rdoc b/doc/string/squeeze.rdoc
new file mode 100644
index 0000000000..1a38c08b32
--- /dev/null
+++ b/doc/string/squeeze.rdoc
@@ -0,0 +1,33 @@
+Returns a copy of +self+ with each tuple (doubling, tripling, etc.) of specified characters
+"squeezed" down to a single character.
+
+The tuples to be squeezed are specified by arguments +selectors+,
+each of which is a string;
+see {Character Selectors}[rdoc-ref:character_selectors.rdoc@Character+Selectors].
+
+A single argument may be a single character:
+
+ 'Noooooo!'.squeeze('o') # => "No!"
+ 'foo bar baz'.squeeze(' ') # => "foo bar baz"
+ 'Mississippi'.squeeze('s') # => "Misisippi"
+ 'Mississippi'.squeeze('p') # => "Mississipi"
+ 'Mississippi'.squeeze('x') # => "Mississippi" # Unused selector character is ignored.
+ 'бессонница'.squeeze('с') # => "бесонница"
+ 'бессонница'.squeeze('н') # => "бессоница"
+
+A single argument may be a string of characters:
+
+ 'Mississippi'.squeeze('sp') # => "Misisipi"
+ 'Mississippi'.squeeze('ps') # => "Misisipi" # Order doesn't matter.
+ 'Mississippi'.squeeze('nonsense') # => "Misisippi" # Unused selector characters are ignored.
+
+A single argument may be a range of characters:
+
+ 'Mississippi'.squeeze('a-p') # => "Mississipi"
+ 'Mississippi'.squeeze('q-z') # => "Misisippi"
+ 'Mississippi'.squeeze('a-z') # => "Misisipi"
+
+Multiple arguments are allowed;
+see {Multiple Character Selectors}[rdoc-ref:character_selectors.rdoc@Multiple+Character+Selectors].
+
+Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
diff --git a/doc/string/start_with_p.rdoc b/doc/string/start_with_p.rdoc
index 5d1f9f9543..f78edc7fa3 100644
--- a/doc/string/start_with_p.rdoc
+++ b/doc/string/start_with_p.rdoc
@@ -1,10 +1,9 @@
-Returns whether +self+ starts with any of the given +string_or_regexp+.
+Returns whether +self+ starts with any of the given +patterns+.
-Matches patterns against the beginning of +self+.
-For each given +string_or_regexp+, the pattern is:
+For each argument, the pattern used is:
-- +string_or_regexp+ itself, if it is a Regexp.
-- <tt>Regexp.quote(string_or_regexp)</tt>, if +string_or_regexp+ is a string.
+- The pattern itself, if it is a Regexp.
+- <tt>Regexp.quote(pattern)</tt>, if it is a string.
Returns +true+ if any pattern matches the beginning, +false+ otherwise:
@@ -12,7 +11,6 @@ Returns +true+ if any pattern matches the beginning, +false+ otherwise:
'hello'.start_with?(/H/i) # => true
'hello'.start_with?('heaven', 'hell') # => true
'hello'.start_with?('heaven', 'paradise') # => false
- 'тест'.start_with?('т') # => true
'こんにちは'.start_with?('こ') # => true
-Related: String#end_with?.
+Related: see {Querying}[rdoc-ref:String@Querying].
diff --git a/doc/string/sub.rdoc b/doc/string/sub.rdoc
new file mode 100644
index 0000000000..ff051ea177
--- /dev/null
+++ b/doc/string/sub.rdoc
@@ -0,0 +1,33 @@
+Returns a copy of self, possibly with a substring replaced.
+
+Argument +pattern+ may be a string or a Regexp;
+argument +replacement+ may be a string or a Hash.
+
+Varying types for the argument values makes this method very versatile.
+
+Below are some simple examples; for many more examples,
+see {Substitution Methods}[rdoc-ref:String@Substitution+Methods].
+
+With arguments +pattern+ and string +replacement+ given,
+replaces the first matching substring with the given replacement string:
+
+ s = 'abracadabra' # => "abracadabra"
+ s.sub('bra', 'xyzzy') # => "axyzzycadabra"
+ s.sub(/bra/, 'xyzzy') # => "axyzzycadabra"
+ s.sub('nope', 'xyzzy') # => "abracadabra"
+
+With arguments +pattern+ and hash +replacement+ given,
+replaces the first matching substring with a value from the given replacement hash, or removes it:
+
+ h = {'a' => 'A', 'b' => 'B', 'c' => 'C'}
+ s.sub('b', h) # => "aBracadabra"
+ s.sub(/b/, h) # => "aBracadabra"
+ s.sub(/d/, h) # => "abracaabra" # 'd' removed.
+
+With argument +pattern+ and a block given,
+calls the block with each matching substring;
+replaces that substring with the block’s return value:
+
+ s.sub('b') {|match| match.upcase } # => "aBracadabra"
+
+Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
diff --git a/doc/string/succ.rdoc b/doc/string/succ.rdoc
new file mode 100644
index 0000000000..1b4b936a8e
--- /dev/null
+++ b/doc/string/succ.rdoc
@@ -0,0 +1,52 @@
+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"
+ '<<koala>>'.succ # => "<<koalb>>"
+ '***'.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"
+
+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:
+
+ '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:
+
+ s = 0.chr * 3 # => "\x00\x00\x00"
+ s.succ # => "\x00\x00\x01"
+ s = 255.chr * 3 # => "\xFF\xFF\xFF"
+ s.succ # => "\x01\x00\x00\x00"
+
+Carrying can occur between and among mixtures of alphanumeric characters:
+
+ s = 'zz99zz99' # => "zz99zz99"
+ s.succ # => "aaa00aa00"
+ s = '99zz99zz' # => "99zz99zz"
+ s.succ # => "100aa00aa"
+
+The successor to an empty +String+ is a new empty +String+:
+
+ ''.succ # => ""
+
+Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
diff --git a/doc/string/sum.rdoc b/doc/string/sum.rdoc
index 5de24e6402..22045e5f4d 100644
--- a/doc/string/sum.rdoc
+++ b/doc/string/sum.rdoc
@@ -1,11 +1,12 @@
-Returns a basic +n+-bit checksum of the characters in +self+;
+Returns a basic +n+-bit {checksum}[https://en.wikipedia.org/wiki/Checksum] of the characters in +self+;
the checksum is the sum of the binary value of each byte in +self+,
modulo <tt>2**n - 1</tt>:
'hello'.sum # => 532
'hello'.sum(4) # => 4
'hello'.sum(64) # => 532
- 'тест'.sum # => 1405
'こんにちは'.sum # => 2582
This is not a particularly strong checksum.
+
+Related: see {Querying}[rdoc-ref:String@Querying].
diff --git a/doc/string/swapcase.rdoc b/doc/string/swapcase.rdoc
new file mode 100644
index 0000000000..4353c8528a
--- /dev/null
+++ b/doc/string/swapcase.rdoc
@@ -0,0 +1,31 @@
+Returns a string containing the characters in +self+, with cases reversed:
+
+- Each uppercase character is downcased.
+- Each lowercase character is upcased.
+
+Examples:
+
+ 'Hello'.swapcase # => "hELLO"
+ 'Straße'.swapcase # => "sTRASSE"
+ 'RubyGems.org'.swapcase # => "rUBYgEMS.ORG"
+
+The sizes of +self+ and the upcased result may differ:
+
+ s = 'Straße'
+ s.size # => 6
+ s.swapcase # => "sTRASSE"
+ s.swapcase.size # => 7
+
+Some characters (and some character sets) do not have upcase and downcase versions;
+see {Case Mapping}[rdoc-ref:case_mapping.rdoc]:
+
+ s = '1, 2, 3, ...'
+ s.swapcase == s # => true
+ s = 'こんにちは'
+ s.swapcase == s # => true
+
+The casing is affected by the given +mapping+,
+which may be +:ascii+, +:fold+, or +:turkic+;
+see {Case Mappings}[rdoc-ref:case_mapping.rdoc@Case+Mappings].
+
+Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
diff --git a/doc/string/unicode_normalize.rdoc b/doc/string/unicode_normalize.rdoc
new file mode 100644
index 0000000000..5f733c0fb8
--- /dev/null
+++ b/doc/string/unicode_normalize.rdoc
@@ -0,0 +1,28 @@
+Returns a copy of +self+ with
+{Unicode normalization}[https://unicode.org/reports/tr15] applied.
+
+Argument +form+ must be one of the following symbols
+(see {Unicode normalization forms}[https://unicode.org/reports/tr15/#Norm_Forms]):
+
+- +:nfc+: Canonical decomposition, followed by canonical composition.
+- +:nfd+: Canonical decomposition.
+- +:nfkc+: Compatibility decomposition, followed by canonical composition.
+- +:nfkd+: Compatibility decomposition.
+
+The encoding of +self+ must be one of:
+
+- <tt>Encoding::UTF_8</tt>.
+- <tt>Encoding::UTF_16BE</tt>.
+- <tt>Encoding::UTF_16LE</tt>.
+- <tt>Encoding::UTF_32BE</tt>.
+- <tt>Encoding::UTF_32LE</tt>.
+- <tt>Encoding::GB18030</tt>.
+- <tt>Encoding::UCS_2BE</tt>.
+- <tt>Encoding::UCS_4BE</tt>.
+
+Examples:
+
+ "a\u0300".unicode_normalize # => "à" # Lowercase 'a' with grave accens.
+ "a\u0300".unicode_normalize(:nfd) # => "à" # Same.
+
+Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
diff --git a/doc/string/upcase.rdoc b/doc/string/upcase.rdoc
new file mode 100644
index 0000000000..ad859e8973
--- /dev/null
+++ b/doc/string/upcase.rdoc
@@ -0,0 +1,27 @@
+Returns a new string containing the upcased characters in +self+:
+
+ 'hello'.upcase # => "HELLO"
+ 'straße'.upcase # => "STRASSE"
+ 'привет'.upcase # => "ПРИВЕТ"
+ 'RubyGems.org'.upcase # => "RUBYGEMS.ORG"
+
+The sizes of +self+ and the upcased result may differ:
+
+ s = 'Straße'
+ s.size # => 6
+ s.upcase # => "STRASSE"
+ s.upcase.size # => 7
+
+Some characters (and some character sets) do not have upcase and downcase versions;
+see {Case Mapping}[rdoc-ref:case_mapping.rdoc]:
+
+ s = '1, 2, 3, ...'
+ s.upcase == s # => true
+ s = 'こんにちは'
+ s.upcase == s # => true
+
+The casing is affected by the given +mapping+,
+which may be +:ascii+, +:fold+, or +:turkic+;
+see {Case Mappings}[rdoc-ref:case_mapping.rdoc@Case+Mappings].
+
+Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
diff --git a/doc/string/upto.rdoc b/doc/string/upto.rdoc
new file mode 100644
index 0000000000..f860fe84fe
--- /dev/null
+++ b/doc/string/upto.rdoc
@@ -0,0 +1,38 @@
+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 <tt>self.succ</tt>, and so on;
+the sequence terminates when value +other_string+ is reached;
+returns +self+:
+
+ a = []
+ 'a'.upto('f') {|c| a.push(c) }
+ a # => ["a", "b", "c", "d", "e", "f"]
+
+ a = []
+ 'Ж'.upto('П') {|c| a.push(c) }
+ a # => ["Ж", "З", "И", "Й", "К", "Л", "М", "Н", "О", "П"]
+
+ a = []
+ 'よ'.upto('ろ') {|c| a.push(c) }
+ a # => ["よ", "ら", "り", "る", "れ", "ろ"]
+
+ a = []
+ 'a8'.upto('b6') {|c| a.push(c) }
+ a # => ["a8", "a9", "b0", "b1", "b2", "b3", "b4", "b5", "b6"]
+
+If argument +exclusive+ is given as a truthy object, the last value is omitted:
+
+ a = []
+ 'a'.upto('f', true) {|c| a.push(c) }
+ a # => ["a", "b", "c", "d", "e"]
+
+If +other_string+ would not be reached, does not call the block:
+
+ '25'.upto('5') {|s| fail s }
+ 'aa'.upto('a') {|s| fail s }
+
+With no block given, returns a new Enumerator:
+
+ 'a8'.upto('b6') # => #<Enumerator: "a8":upto("b6")>
+
+Related: see {Iterating}[rdoc-ref:String@Iterating].
diff --git a/doc/string/valid_encoding_p.rdoc b/doc/string/valid_encoding_p.rdoc
new file mode 100644
index 0000000000..e1db55174a
--- /dev/null
+++ b/doc/string/valid_encoding_p.rdoc
@@ -0,0 +1,8 @@
+Returns whether +self+ is encoded correctly:
+
+ s = 'Straße'
+ s.valid_encoding? # => true
+ s.encoding # => #<Encoding:UTF-8>
+ s.force_encoding(Encoding::ASCII).valid_encoding? # => false
+
+Related: see {Querying}[rdoc-ref:String@Querying].
diff --git a/doc/stringio/each_byte.rdoc b/doc/stringio/each_byte.rdoc
new file mode 100644
index 0000000000..65e81c53a7
--- /dev/null
+++ b/doc/stringio/each_byte.rdoc
@@ -0,0 +1,34 @@
+With a block given, calls the block with each remaining byte in the stream;
+positions the stream at end-of-file;
+returns +self+:
+
+ bytes = []
+ strio = StringIO.new('hello') # Five 1-byte characters.
+ strio.each_byte {|byte| bytes.push(byte) }
+ strio.eof? # => true
+ bytes # => [104, 101, 108, 108, 111]
+ bytes = []
+ strio = StringIO.new('тест') # Four 2-byte characters.
+ strio.each_byte {|byte| bytes.push(byte) }
+ bytes # => [209, 130, 208, 181, 209, 129, 209, 130]
+ bytes = []
+ strio = StringIO.new('こんにちは') # Five 3-byte characters.
+ strio.each_byte {|byte| bytes.push(byte) }
+ bytes # => [227, 129, 147, 227, 130, 147, 227, 129, 171, 227, 129, 161, 227, 129, 175]
+
+The position in the stream matters:
+
+ bytes = []
+ strio = StringIO.new('こんにちは')
+ strio.getc # => "こ"
+ strio.pos # => 3 # 3-byte character was read.
+ strio.each_byte {|byte| bytes.push(byte) }
+ bytes # => [227, 130, 147, 227, 129, 171, 227, 129, 161, 227, 129, 175]
+
+If at end-of-file, does not call the block:
+
+ strio.eof? # => true
+ strio.each_byte {|byte| fail 'Boo!' }
+ strio.eof? # => true
+
+With no block given, returns a new {Enumerator}[rdoc-ref:Enumerator].
diff --git a/doc/stringio/each_char.rdoc b/doc/stringio/each_char.rdoc
new file mode 100644
index 0000000000..d0b5e4082c
--- /dev/null
+++ b/doc/stringio/each_char.rdoc
@@ -0,0 +1,34 @@
+With a block given, calls the block with each remaining character in the stream;
+positions the stream at end-of-file;
+returns +self+:
+
+ chars = []
+ strio = StringIO.new('hello')
+ strio.each_char {|char| chars.push(char) }
+ strio.eof? # => true
+ chars # => ["h", "e", "l", "l", "o"]
+ chars = []
+ strio = StringIO.new('тест')
+ strio.each_char {|char| chars.push(char) }
+ chars # => ["т", "е", "с", "т"]
+ chars = []
+ strio = StringIO.new('こんにちは')
+ strio.each_char {|char| chars.push(char) }
+ chars # => ["こ", "ん", "に", "ち", "は"]
+
+Stream position matters:
+
+ chars = []
+ strio = StringIO.new('こんにちは')
+ strio.getc # => "こ"
+ strio.pos # => 3 # 3-byte character was read.
+ strio.each_char {|char| chars.push(char) }
+ chars # => ["ん", "に", "ち", "は"]
+
+When at end-of-stream does not call the block:
+
+ strio.eof? # => true
+ strio.each_char {|char| fail 'Boo!' }
+ strio.eof? # => true
+
+With no block given, returns a new {Enumerator}[rdoc-ref:Enumerator].
diff --git a/doc/stringio/each_codepoint.rdoc b/doc/stringio/each_codepoint.rdoc
new file mode 100644
index 0000000000..ede16de599
--- /dev/null
+++ b/doc/stringio/each_codepoint.rdoc
@@ -0,0 +1,36 @@
+With a block given, calls the block with each successive codepoint from self;
+sets the position to end-of-stream;
+returns +self+.
+
+Each codepoint is the integer value for a character; returns self:
+
+ codepoints = []
+ strio = StringIO.new('hello')
+ strio.each_codepoint {|codepoint| codepoints.push(codepoint) }
+ strio.eof? # => true
+ codepoints # => [104, 101, 108, 108, 111]
+ codepoints = []
+ strio = StringIO.new('тест')
+ strio.each_codepoint {|codepoint| codepoints.push(codepoint) }
+ codepoints # => [1090, 1077, 1089, 1090]
+ codepoints = []
+ strio = StringIO.new('こんにちは')
+ strio.each_codepoint {|codepoint| codepoints.push(codepoint) }
+ codepoints # => [12371, 12435, 12395, 12385, 12399]
+
+Position in the stream matters:
+
+ codepoints = []
+ strio = StringIO.new('こんにちは')
+ strio.getc # => "こ"
+ strio.pos # => 3
+ strio.each_codepoint {|codepoint| codepoints.push(codepoint) }
+ codepoints # => [12435, 12395, 12385, 12399]
+
+When at end-of-stream, the block is not called:
+
+ strio.eof? # => true
+ strio.each_codepoint {|codepoint| fail 'Boo!' }
+ strio.eof? # => true
+
+With no block given, returns a new {Enumerator}[rdoc-ref:Enumerator].
diff --git a/doc/stringio/each_line.md b/doc/stringio/each_line.md
new file mode 100644
index 0000000000..e29640a12a
--- /dev/null
+++ b/doc/stringio/each_line.md
@@ -0,0 +1,189 @@
+With a block given calls the block with each remaining line (see "Position" below) in the stream;
+returns `self`.
+
+Leaves stream position at end-of-stream.
+
+**No Arguments**
+
+With no arguments given,
+reads lines using the default record separator
+(global variable `$/`, whose initial value is `"\n"`).
+
+```ruby
+strio = StringIO.new(TEXT)
+strio.each_line {|line| p line }
+strio.eof? # => true
+```
+
+Output:
+
+```
+"First line\n"
+"Second line\n"
+"\n"
+"Fourth line\n"
+"Fifth line\n"
+```
+
+**Argument `sep`**
+
+With only string argument `sep` given,
+reads lines using that string as the record separator:
+
+```ruby
+strio = StringIO.new(TEXT)
+strio.each_line(' ') {|line| p line }
+```
+
+Output:
+
+```
+"First "
+"line\nSecond "
+"line\n\nFourth "
+"line\nFifth "
+"line\n"
+```
+
+**Argument `limit`**
+
+With only integer argument `limit` given,
+reads lines using the default record separator;
+also limits the size (in characters) of each line to the given limit:
+
+```ruby
+strio = StringIO.new(TEXT)
+strio.each_line(10) {|line| p line }
+```
+
+Output:
+
+```
+"First line"
+"\n"
+"Second lin"
+"e\n"
+"\n"
+"Fourth lin"
+"e\n"
+"Fifth line"
+"\n"
+```
+
+**Arguments `sep` and `limit`**
+
+With arguments `sep` and `limit` both given,
+honors both:
+
+```ruby
+strio = StringIO.new(TEXT)
+strio.each_line(' ', 10) {|line| p line }
+```
+
+Output:
+
+```
+"First "
+"line\nSecon"
+"d "
+"line\n\nFour"
+"th "
+"line\nFifth"
+" "
+"line\n"
+```
+
+**Position**
+
+As stated above, method `each` _remaining_ line in the stream.
+
+In the examples above each `strio` object starts with its position at beginning-of-stream;
+but in other cases the position may be anywhere (see StringIO#pos):
+
+```ruby
+strio = StringIO.new(TEXT)
+strio.pos = 30 # Set stream position to character 30.
+strio.each_line {|line| p line }
+```
+
+Output:
+
+```
+" line\n"
+"Fifth line\n"
+```
+
+In all the examples above, the stream position is at the beginning of a character;
+in other cases, that need not be so:
+
+```ruby
+s = 'こんにちは' # Five 3-byte characters.
+strio = StringIO.new(s)
+strio.pos = 3 # At beginning of second character.
+strio.each_line {|line| p line }
+strio.pos = 4 # At second byte of second character.
+strio.each_line {|line| p line }
+strio.pos = 5 # At third byte of second character.
+strio.each_line {|line| p line }
+```
+
+Output:
+
+```
+"んにちは"
+"\x82\x93にちは"
+"\x93にちは"
+```
+
+**Special Record Separators**
+
+Like some methods in class `IO`, StringIO.each honors two special record separators;
+see {Special Line Separators}[https://docs.ruby-lang.org/en/master/IO.html#class-IO-label-Special+Line+Separator+Values].
+
+```ruby
+strio = StringIO.new(TEXT)
+strio.each_line('') {|line| p line } # Read as paragraphs (separated by blank lines).
+```
+
+Output:
+
+```
+"First line\nSecond line\n\n"
+"Fourth line\nFifth line\n"
+```
+
+```ruby
+strio = StringIO.new(TEXT)
+strio.each_line(nil) {|line| p line } # "Slurp"; read it all.
+```
+
+Output:
+
+```
+"First line\nSecond line\n\nFourth line\nFifth line\n"
+```
+
+**Keyword Argument `chomp`**
+
+With keyword argument `chomp` given as `true` (the default is `false`),
+removes trailing newline (if any) from each line:
+
+```ruby
+strio = StringIO.new(TEXT)
+strio.each_line(chomp: true) {|line| p line }
+```
+
+Output:
+
+```
+"First line"
+"Second line"
+""
+"Fourth line"
+"Fifth line"
+```
+
+With no block given, returns a new {Enumerator}[https://docs.ruby-lang.org/en/master/Enumerator.html].
+
+
+Related: StringIO.each_byte, StringIO.each_char, StringIO.each_codepoint.
diff --git a/doc/stringio/getbyte.rdoc b/doc/stringio/getbyte.rdoc
new file mode 100644
index 0000000000..5e524941bc
--- /dev/null
+++ b/doc/stringio/getbyte.rdoc
@@ -0,0 +1,31 @@
+Reads and returns the next integer byte (not character) from the stream:
+
+ s = 'foo'
+ s.bytes # => [102, 111, 111]
+ strio = StringIO.new(s)
+ strio.getbyte # => 102
+ strio.getbyte # => 111
+ strio.getbyte # => 111
+
+Returns +nil+ if at end-of-stream:
+
+ strio.eof? # => true
+ strio.getbyte # => nil
+
+Returns a byte, not a character:
+
+ s = 'Привет'
+ s.bytes
+ # => [208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130]
+ strio = StringIO.new(s)
+ strio.getbyte # => 208
+ strio.getbyte # => 159
+
+ s = 'こんにちは'
+ s.bytes
+ # => [227, 129, 147, 227, 130, 147, 227, 129, 171, 227, 129, 161, 227, 129, 175]
+ strio = StringIO.new(s)
+ strio.getbyte # => 227
+ strio.getbyte # => 129
+
+Related: #each_byte, #ungetbyte, #getc.
diff --git a/doc/stringio/getc.rdoc b/doc/stringio/getc.rdoc
new file mode 100644
index 0000000000..b2ab46843c
--- /dev/null
+++ b/doc/stringio/getc.rdoc
@@ -0,0 +1,34 @@
+Reads and returns the next character (or byte; see below) from the stream:
+
+ strio = StringIO.new('foo')
+ strio.getc # => "f"
+ strio.getc # => "o"
+ strio.getc # => "o"
+
+Returns +nil+ if at end-of-stream:
+
+ strio.eof? # => true
+ strio.getc # => nil
+
+Returns characters, not bytes:
+
+ strio = StringIO.new('Привет')
+ strio.getc # => "П"
+ strio.getc # => "р"
+
+ strio = StringIO.new('こんにちは')
+ strio.getc # => "こ"
+ strio.getc # => "ん"
+
+In each of the examples above, the stream is positioned at the beginning of a character;
+in other cases that need not be true:
+
+ strio = StringIO.new('こんにちは') # Five 3-byte characters.
+ strio.pos = 3 # => 3 # At beginning of second character; returns character.
+ strio.getc # => "ん"
+ strio.pos = 4 # => 4 # At second byte of second character; returns byte.
+ strio.getc # => "\x82"
+ strio.pos = 5 # => 5 # At third byte of second character; returns byte.
+ strio.getc # => "\x93"
+
+Related: #getbyte, #putc, #ungetc.
diff --git a/doc/stringio/gets.rdoc b/doc/stringio/gets.rdoc
new file mode 100644
index 0000000000..bbefeb008a
--- /dev/null
+++ b/doc/stringio/gets.rdoc
@@ -0,0 +1,99 @@
+Reads and returns a line from the stream;
+returns +nil+ if at end-of-stream.
+
+Side effects:
+
+- Increments stream position by the number of bytes read.
+- Assigns the return value to global variable <tt>$_</tt>.
+
+With no arguments given, reads a line using the default record separator
+(global variable <tt>$/</tt>,* whose initial value is <tt>"\n"</tt>):
+
+ strio = StringIO.new(TEXT)
+ strio.pos # => 0
+ strio.gets # => "First line\n"
+ strio.pos # => 11
+ $_ # => "First line\n"
+ strio.gets # => "Second line\n"
+ strio.read # => "\nFourth line\nFifth line\n"
+ strio.eof? # => true
+ strio.gets # => nil
+
+ strio = StringIO.new('Привет') # Six 2-byte characters
+ strio.pos # => 0
+ strio.gets # => "Привет"
+ strio.pos # => 12
+
+<b>Argument +sep+</b>
+
+With only string argument +sep+ given, reads a line using that string as the record separator:
+
+ strio = StringIO.new(TEXT)
+ strio.gets(' ') # => "First "
+ strio.gets(' ') # => "line\nSecond "
+ strio.gets(' ') # => "line\n\nFourth "
+
+<b>Argument +limit+</b>
+
+With only integer argument +limit+ given,
+reads a line using the default record separator;
+limits the size (in characters) of each line to the given limit:
+
+ strio = StringIO.new(TEXT)
+ strio.gets(10) # => "First line"
+ strio.gets(10) # => "\n"
+ strio.gets(10) # => "Second lin"
+ strio.gets(10) # => "e\n"
+
+<b>Arguments +sep+ and +limit+</b>
+
+With arguments +sep+ and +limit+ both given, honors both:
+
+ strio = StringIO.new(TEXT)
+ strio.gets(' ', 10) # => "First "
+ strio.gets(' ', 10) # => "line\nSecon"
+ strio.gets(' ', 10) # => "d "
+
+<b>Position</b>
+
+As stated above, method +gets+ reads and returns the next line in the stream.
+
+In the examples above each +strio+ object starts with its position at beginning-of-stream;
+but in other cases the position may be anywhere:
+
+ strio = StringIO.new(TEXT)
+ strio.pos = 12
+ strio.gets # => "econd line\n"
+
+The position need not be at a character boundary:
+
+ strio = StringIO.new('Привет') # Six 2-byte characters.
+ strio.pos = 2 # At beginning of second character.
+ strio.gets # => "ривет"
+ strio.pos = 3 # In middle of second character.
+ strio.gets # => "\x80ивет"
+
+<b>Special Record Separators</b>
+
+Like some methods in class IO, method +gets+ honors two special record separators;
+see {Special Line Separators}[https://docs.ruby-lang.org/en/master/IO.html#class-IO-label-Special+Line+Separator+Values]:
+
+ strio = StringIO.new(TEXT)
+ strio.gets('') # Read "paragraph" (up to empty line).
+ # => "First line\nSecond line\n\n"
+
+ strio = StringIO.new(TEXT)
+ strio.gets(nil) # "Slurp": read all.
+ # => "First line\nSecond line\n\nFourth line\nFifth line\n"
+
+<b>Keyword Argument +chomp+</b>
+
+With keyword argument +chomp+ given as +true+ (the default is +false+),
+removes the trailing newline (if any) from the returned line:
+
+ strio = StringIO.new(TEXT)
+ strio.gets # => "First line\n"
+ strio.gets(chomp: true) # => "Second line"
+
+Related: #each_line, #readlines,
+{Kernel#puts}[rdoc-ref:Kernel#puts].
diff --git a/doc/stringio/pread.rdoc b/doc/stringio/pread.rdoc
new file mode 100644
index 0000000000..2dcbc18ad8
--- /dev/null
+++ b/doc/stringio/pread.rdoc
@@ -0,0 +1,65 @@
+**Note**: \Method +pread+ is different from other reading methods
+in that it does not modify +self+ in any way;
+thus, multiple threads may read safely from the same stream.
+
+Reads up to +maxlen+ bytes from the stream,
+beginning at 0-based byte offset +offset+;
+returns a string containing the read bytes.
+
+The returned string:
+
+- Contains +maxlen+ bytes from the stream, if available;
+ otherwise contains all available bytes.
+- Has encoding +Encoding::ASCII_8BIT+.
+
+With only arguments +maxlen+ and +offset+ given,
+returns a new string:
+
+ english = 'Hello' # Five 1-byte characters.
+ strio = StringIO.new(english)
+ strio.pread(3, 0) # => "Hel"
+ strio.pread(3, 2) # => "llo"
+ strio.pread(0, 0) # => ""
+ strio.pread(50, 0) # => "Hello"
+ strio.pread(50, 2) # => "llo"
+ strio.pread(50, 4) # => "o"
+ strio.pread(0, 0).encoding
+ # => #<Encoding:BINARY (ASCII-8BIT)>
+
+ russian = 'Привет' # Six 2-byte characters.
+ strio = StringIO.new(russian)
+ strio.pread(50, 0) # All 12 bytes.
+ # => "\xD0\x9F\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD1\x82"
+ strio.pread(3, 0) # => "\xD0\x9F\xD1"
+ strio.pread(3, 3) # => "\x80\xD0\xB8"
+ strio.pread(0, 0).encoding
+ # => #<Encoding:BINARY (ASCII-8BIT)>
+
+ japanese = 'こんにちは' # Five 3-byte characters.
+ strio = StringIO.new(japanese)
+ strio.pread(50, 0) # All 15 bytes.
+ # => "\xE3\x81\x93\xE3\x82\x93\xE3\x81\xAB\xE3\x81\xA1\xE3\x81\xAF"
+ strio.pread(6, 0) # => "\xE3\x81\x93\xE3\x82\x93"
+ strio.pread(1, 2) # => "\x93"
+ strio.pread(0, 0).encoding
+ # => #<Encoding:BINARY (ASCII-8BIT)>
+
+Raises an exception if +offset+ is out-of-range:
+
+ strio = StringIO.new(english)
+ strio.pread(5, 50) # Raises EOFError: end of file reached
+
+With string argument +out_string+ given:
+
+- Reads as above.
+- Overwrites the content of +out_string+ with the read bytes.
+
+Examples:
+
+ out_string = 'Will be overwritten'
+ out_string.encoding # => #<Encoding:UTF-8>
+ result = StringIO.new(english).pread(50, 0, out_string)
+ result.__id__ == out_string.__id__ # => true
+ out_string # => "Hello"
+ out_string.encoding # => #<Encoding:BINARY (ASCII-8BIT)>
+
diff --git a/doc/stringio/putc.rdoc b/doc/stringio/putc.rdoc
new file mode 100644
index 0000000000..4636ffa0db
--- /dev/null
+++ b/doc/stringio/putc.rdoc
@@ -0,0 +1,82 @@
+Replaces one or more bytes at position +pos+
+with bytes of the given argument;
+advances the position by the count of bytes written;
+returns the argument.
+
+\StringIO object for 1-byte characters.
+
+ strio = StringIO.new('foo')
+ strio.pos # => 0
+
+With 1-byte argument, replaces one byte:
+
+ strio.putc('b')
+ strio.string # => "boo"
+ strio.pos # => 1
+ strio.putc('a') # => "a"
+ strio.string # => "bao"
+ strio.pos # => 2
+ strio.putc('r') # => "r"
+ strio.string # => "bar"
+ strio.pos # => 3
+ strio.putc('n') # => "n"
+ strio.string # => "barn"
+ strio.pos # => 4
+
+Fills with null characters if necessary:
+
+ strio.pos = 6
+ strio.putc('x') # => "x"
+ strio.string # => "barn\u0000\u0000x"
+ strio.pos # => 7
+
+With integer argument, replaces one byte with the low-order byte of the integer:
+
+ strio = StringIO.new('foo')
+ strio.putc(70)
+ strio.string # => "Foo"
+ strio.putc(79)
+ strio.string # => "FOo"
+ strio.putc(79 + 1024)
+ strio.string # => "FOO"
+
+\StringIO object for Multi-byte characters:
+
+ greek = 'αβγδε' # Five 2-byte characters.
+ strio = StringIO.new(greek)
+ strio.string# => "αβγδε"
+ strio.string.b # => "\xCE\xB1\xCE\xB2\xCE\xB3\xCE\xB4\xCE\xB5"
+ strio.string.bytesize # => 10
+ strio.string.chars # => ["α", "β", "γ", "δ", "ε"]
+ strio.string.size # => 5
+
+With 1-byte argument, replaces one byte of the string:
+
+ strio.putc(' ') # 1-byte ascii space.
+ strio.pos # => 1
+ strio.string # => " \xB1βγδε"
+ strio.string.b # => " \xB1\xCE\xB2\xCE\xB3\xCE\xB4\xCE\xB5"
+ strio.string.bytesize # => 10
+ strio.string.chars # => [" ", "\xB1", "β", "γ", "δ", "ε"]
+ strio.string.size # => 6
+
+ strio.putc(' ')
+ strio.pos # => 2
+ strio.string # => " βγδε"
+ strio.string.b # => " \xCE\xB2\xCE\xB3\xCE\xB4\xCE\xB5"
+ strio.string.bytesize # => 10
+ strio.string.chars # => [" ", " ", "β", "γ", "δ", "ε"]
+ strio.string.size # => 6
+
+With 2-byte argument, replaces two bytes of the string:
+
+ strio.rewind
+ strio.putc('α')
+ strio.pos # => 2
+ strio.string # => "αβγδε"
+ strio.string.b # => "\xCE\xB1\xCE\xB2\xCE\xB3\xCE\xB4\xCE\xB5"
+ strio.string.bytesize # => 10
+ strio.string.chars # => ["α", "β", "γ", "δ", "ε"]
+ strio.string.size # => 5
+
+Related: #getc, #ungetc.
diff --git a/doc/stringio/read.rdoc b/doc/stringio/read.rdoc
new file mode 100644
index 0000000000..46b9fa349f
--- /dev/null
+++ b/doc/stringio/read.rdoc
@@ -0,0 +1,83 @@
+Reads and returns a string containing bytes read from the stream,
+beginning at the current position;
+advances the position by the count of bytes read.
+
+With no arguments given,
+reads all remaining bytes in the stream;
+returns a new string containing bytes read:
+
+ strio = StringIO.new('Hello') # Five 1-byte characters.
+ strio.read # => "Hello"
+ strio.pos # => 5
+ strio.read # => ""
+ StringIO.new('').read # => ""
+
+With non-negative argument +maxlen+ given,
+reads +maxlen+ bytes as available;
+returns a new string containing the bytes read, or +nil+ if none:
+
+ strio.rewind
+ strio.read(3) # => "Hel"
+ strio.read(3) # => "lo"
+ strio.read(3) # => nil
+
+ russian = 'Привет' # Six 2-byte characters.
+ russian.b
+ # => "\xD0\x9F\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD1\x82"
+ strio = StringIO.new(russian)
+ strio.read(6) # => "\xD0\x9F\xD1\x80\xD0\xB8"
+ strio.read(6) # => "\xD0\xB2\xD0\xB5\xD1\x82"
+ strio.read(6) # => nil
+
+ japanese = 'こんにちは'
+ japanese.b
+ # => "\xE3\x81\x93\xE3\x82\x93\xE3\x81\xAB\xE3\x81\xA1\xE3\x81\xAF"
+ strio = StringIO.new(japanese)
+ strio.read(9) # => "\xE3\x81\x93\xE3\x82\x93\xE3\x81\xAB"
+ strio.read(9) # => "\xE3\x81\xA1\xE3\x81\xAF"
+ strio.read(9) # => nil
+
+With argument +max_len+ as +nil+ and string argument +out_string+ given,
+reads the remaining bytes in the stream;
+clears +out_string+ and writes the bytes into it;
+returns +out_string+:
+
+ out_string = 'Will be overwritten'
+ strio = StringIO.new('Hello')
+ strio.read(nil, out_string) # => "Hello"
+ strio.read(nil, out_string) # => ""
+
+With non-negative argument +maxlen+ and string argument +out_string+ given,
+reads the +maxlen bytes from the stream, as availble;
+clears +out_string+ and writes the bytes into it;
+returns +out_string+ if any bytes were read, or +nil+ if none:
+
+ out_string = 'Will be overwritten'
+ strio = StringIO.new('Hello')
+ strio.read(3, out_string) # => "Hel"
+ strio.read(3, out_string) # => "lo"
+ strio.read(3, out_string) # => nil
+
+ out_string = 'Will be overwritten'
+ strio = StringIO.new(russian)
+ strio.read(6, out_string) # => "При"
+ strio.read(6, out_string) # => "вет"
+ strio.read(6, out_string) # => nil
+ strio.rewind
+ russian.b
+ # => "\xD0\x9F\xD1\x80\xD0\xB8\xD0\xB2\xD0\xB5\xD1\x82"
+ strio.read(3) # => "\xD0\x9F\xD1"
+ strio.read(3) # => "\x80\xD0\xB8"
+
+ out_string = 'Will be overwritten'
+ strio = StringIO.new(japanese)
+ strio.read(9, out_string) # => "こんに"
+ strio.read(9, out_string) # => "ちは"
+ strio.read(9, out_string) # => nil
+ strio.rewind
+ japanese.b
+ # => "\xE3\x81\x93\xE3\x82\x93\xE3\x81\xAB\xE3\x81\xA1\xE3\x81\xAF"
+ strio.read(4) # => "\xE3\x81\x93\xE3"
+ strio.read(4) # => "\x82\x93\xE3\x81"
+
+Related: #gets, #readlines.
diff --git a/doc/stringio/size.rdoc b/doc/stringio/size.rdoc
new file mode 100644
index 0000000000..9323adf8c3
--- /dev/null
+++ b/doc/stringio/size.rdoc
@@ -0,0 +1,5 @@
+Returns the number of bytes in the string in +self+:
+
+ StringIO.new('hello').size # => 5 # Five 1-byte characters.
+ StringIO.new('тест').size # => 8 # Four 2-byte characters.
+ StringIO.new('こんにちは').size # => 15 # Five 3-byte characters.
diff --git a/doc/stringio/stringio.md b/doc/stringio/stringio.md
new file mode 100644
index 0000000000..8931d1c30c
--- /dev/null
+++ b/doc/stringio/stringio.md
@@ -0,0 +1,700 @@
+\Class \StringIO supports accessing a string as a stream,
+similar in some ways to [class IO][io class].
+
+You can create a \StringIO instance using:
+
+- StringIO.new: returns a new \StringIO object containing the given string.
+- StringIO.open: passes a new \StringIO object to the given block.
+
+Like an \IO stream, a \StringIO stream has certain properties:
+
+- **Read/write mode**: whether the stream may be read, written, appended to, etc.;
+ see [Read/Write Mode][read/write mode].
+- **Data mode**: text-only or binary;
+ see [Data Mode][data mode].
+- **Encodings**: internal and external encodings;
+ see [Encodings][encodings].
+- **Position**: where in the stream the next read or write is to occur;
+ see [Position][position].
+- **Line number**: a special, line-oriented, "position" (different from the position mentioned above);
+ see [Line Number][line number].
+- **Open/closed**: whether the stream is open or closed, for reading or writing.
+ see [Open/Closed Streams][open/closed streams].
+- **BOM**: byte mark order;
+ see [Byte Order Mark][bom (byte order mark)].
+
+## About the Examples
+
+Examples on this page assume that \StringIO has been required:
+
+```ruby
+require 'stringio'
+```
+
+And that this constant has been defined:
+
+```ruby
+TEXT = <<EOT
+First line
+Second line
+
+Fourth line
+Fifth line
+EOT
+```
+
+## Stream Properties
+
+### Read/Write Mode
+
+#### Summary
+
+| Mode | Initial Clear? | Read | Write |
+|:--------------------------:|:--------------:|:--------:|:--------:|
+| <tt>'r'</tt>: read-only | No | Anywhere | Error |
+| <tt>'w'</tt>: write-only | Yes | Error | Anywhere |
+| <tt>'a'</tt>: append-only | No | Error | End only |
+| <tt>'r+'</tt>: read/write | No | Anywhere | Anywhere |
+| <tt>'w+'</tt>: read-write | Yes | Anywhere | Anywhere |
+| <tt>'a+'</tt>: read/append | No | Anywhere | End only |
+
+Each section below describes a read/write mode.
+
+Any of the modes may be given as a string or as file constants;
+example:
+
+```ruby
+strio = StringIO.new('foo', 'a')
+strio = StringIO.new('foo', File::WRONLY | File::APPEND)
+```
+
+#### `'r'`: Read-Only
+
+Mode specified as one of:
+
+- String: `'r'`.
+- Constant: `File::RDONLY`.
+
+Initial state:
+
+```ruby
+strio = StringIO.new('foobarbaz', 'r')
+strio.pos # => 0 # Beginning-of-stream.
+strio.string # => "foobarbaz" # Not cleared.
+```
+
+May be read anywhere:
+
+```ruby
+strio.gets(3) # => "foo"
+strio.gets(3) # => "bar"
+strio.pos = 9
+strio.gets(3) # => nil
+```
+
+May not be written:
+
+```ruby
+strio.write('foo') # Raises IOError: not opened for writing
+```
+
+#### `'w'`: Write-Only
+
+Mode specified as one of:
+
+- String: `'w'`.
+- Constant: `File::WRONLY`.
+
+Initial state:
+
+```ruby
+strio = StringIO.new('foo', 'w')
+strio.pos # => 0 # Beginning of stream.
+strio.string # => "" # Initially cleared.
+```
+
+May be written anywhere (even past end-of-stream):
+
+```ruby
+strio.write('foobar')
+strio.string # => "foobar"
+strio.rewind
+strio.write('FOO')
+strio.string # => "FOObar"
+strio.pos = 3
+strio.write('BAR')
+strio.string # => "FOOBAR"
+strio.pos = 9
+strio.write('baz')
+strio.string # => "FOOBAR\u0000\u0000\u0000baz" # Null-padded.
+```
+
+May not be read:
+
+```ruby
+strio.read # Raises IOError: not opened for reading
+```
+
+#### `'a'`: Append-Only
+
+Mode specified as one of:
+
+- String: `'a'`.
+- Constant: `File::WRONLY | File::APPEND`.
+
+Initial state:
+
+```ruby
+strio = StringIO.new('foo', 'a')
+strio.pos # => 0 # Beginning-of-stream.
+strio.string # => "foo" # Not cleared.
+```
+
+May be written only at the end; position does not affect writing:
+
+```ruby
+strio.write('bar')
+strio.string # => "foobar"
+strio.write('baz')
+strio.string # => "foobarbaz"
+strio.pos = 400
+strio.write('bat')
+strio.string # => "foobarbazbat"
+```
+
+May not be read:
+
+```ruby
+strio.gets # Raises IOError: not opened for reading
+```
+
+#### `'r+'`: Read/Write
+
+Mode specified as one of:
+
+- String: `'r+'`.
+- Constant: `File::RDRW`.
+
+Initial state:
+
+```ruby
+strio = StringIO.new('foobar', 'r+')
+strio.pos # => 0 # Beginning-of-stream.
+strio.string # => "foobar" # Not cleared.
+```
+
+May be written anywhere (even past end-of-stream):
+
+```ruby
+strio.write('FOO')
+strio.string # => "FOObar"
+strio.write('BAR')
+strio.string # => "FOOBAR"
+strio.write('BAZ')
+strio.string # => "FOOBARBAZ"
+strio.pos = 12
+strio.write('BAT')
+strio.string # => "FOOBARBAZ\u0000\u0000\u0000BAT" # Null padded.
+```
+
+May be read anywhere:
+
+```ruby
+strio.pos = 0
+strio.gets(3) # => "FOO"
+strio.pos = 6
+strio.gets(3) # => "BAZ"
+strio.pos = 400
+strio.gets(3) # => nil
+```
+
+#### `'w+'`: Read/Write (Initially Clear)
+
+Mode specified as one of:
+
+- String: `'w+'`.
+- Constant: `File::RDWR | File::TRUNC`.
+
+Initial state:
+
+```ruby
+strio = StringIO.new('foo', 'w+')
+strio.pos # => 0 # Beginning-of-stream.
+strio.string # => "" # Truncated.
+```
+
+May be written anywhere (even past end-of-stream):
+
+```ruby
+strio.write('foobar')
+strio.string # => "foobar"
+strio.rewind
+strio.write('FOO')
+strio.string # => "FOObar"
+strio.write('BAR')
+strio.string # => "FOOBAR"
+strio.write('BAZ')
+strio.string # => "FOOBARBAZ"
+strio.pos = 12
+strio.write('BAT')
+strio.string # => "FOOBARBAZ\u0000\u0000\u0000BAT" # Null-padded.
+```
+
+May be read anywhere:
+
+```ruby
+strio.rewind
+strio.gets(3) # => "FOO"
+strio.gets(3) # => "BAR"
+strio.pos = 12
+strio.gets(3) # => "BAT"
+strio.pos = 400
+strio.gets(3) # => nil
+```
+
+#### `'a+'`: Read/Append
+
+Mode specified as one of:
+
+- String: `'a+'`.
+- Constant: `File::RDWR | File::APPEND`.
+
+Initial state:
+
+```ruby
+strio = StringIO.new('foo', 'a+')
+strio.pos # => 0 # Beginning-of-stream.
+strio.string # => "foo" # Not cleared.
+```
+
+May be written only at the end; #rewind; position does not affect writing:
+
+```ruby
+strio.write('bar')
+strio.string # => "foobar"
+strio.write('baz')
+strio.string # => "foobarbaz"
+strio.pos = 400
+strio.write('bat')
+strio.string # => "foobarbazbat"
+```
+
+May be read anywhere:
+
+```ruby
+strio.rewind
+strio.gets(3) # => "foo"
+strio.gets(3) # => "bar"
+strio.pos = 9
+strio.gets(3) # => "bat"
+strio.pos = 400
+strio.gets(3) # => nil
+```
+
+### Data Mode
+
+To specify whether the stream is to be treated as text or as binary data,
+either of the following may be suffixed to any of the string read/write modes above:
+
+- `'t'`: Text;
+ initializes the encoding as Encoding::UTF_8.
+- `'b'`: Binary;
+ initializes the encoding as Encoding::ASCII_8BIT.
+
+If neither is given, the stream defaults to text data.
+
+Examples:
+
+```ruby
+strio = StringIO.new('foo', 'rt')
+strio.external_encoding # => #<Encoding:UTF-8>
+data = "\u9990\u9991\u9992\u9993\u9994"
+strio = StringIO.new(data, 'rb')
+strio.external_encoding # => #<Encoding:BINARY (ASCII-8BIT)>
+```
+
+When the data mode is specified, the read/write mode may not be omitted:
+
+```ruby
+StringIO.new(data, 'b') # Raises ArgumentError: invalid access mode b
+```
+
+A text stream may be changed to binary by calling instance method #binmode;
+a binary stream may not be changed to text.
+
+### Encodings
+
+A stream has an encoding; see [Encodings][encodings document].
+
+The initial encoding for a new or re-opened stream depends on its [data mode][data mode]:
+
+- Text: `Encoding::UTF_8`.
+- Binary: `Encoding::ASCII_8BIT`.
+
+These instance methods are relevant:
+
+- #external_encoding: returns the current encoding of the stream as an `Encoding` object.
+- #internal_encoding: returns +nil+; a stream does not have an internal encoding.
+- #set_encoding: sets the encoding for the stream.
+- #set_encoding_by_bom: sets the encoding for the stream to the stream's BOM (byte order mark).
+
+Examples:
+
+```ruby
+strio = StringIO.new('foo', 'rt') # Text mode.
+strio.external_encoding # => #<Encoding:UTF-8>
+data = "\u9990\u9991\u9992\u9993\u9994"
+strio = StringIO.new(data, 'rb') # Binary mode.
+strio.external_encoding # => #<Encoding:BINARY (ASCII-8BIT)>
+strio = StringIO.new('foo')
+strio.external_encoding # => #<Encoding:UTF-8>
+strio.set_encoding('US-ASCII')
+strio.external_encoding # => #<Encoding:US-ASCII>
+```
+
+### Position
+
+A stream has a _position_, and integer offset (in bytes) into the stream.
+The initial position of a stream is zero.
+
+#### Getting and Setting the Position
+
+Each of these methods initializes (to zero) the position of a new or re-opened stream:
+
+- ::new: returns a new stream.
+- ::open: passes a new stream to the block.
+- #reopen: re-initializes the stream.
+
+Each of these methods queries, gets, or sets the position, without otherwise changing the stream:
+
+- #eof?: returns whether the position is at end-of-stream.
+- #pos: returns the position.
+- #pos=: sets the position.
+- #rewind: sets the position to zero.
+- #seek: sets the position.
+
+Examples:
+
+```ruby
+strio = StringIO.new('foobar')
+strio.pos # => 0
+strio.pos = 3
+strio.pos # => 3
+strio.eof? # => false
+strio.rewind
+strio.pos # => 0
+strio.seek(0, IO::SEEK_END)
+strio.pos # => 6
+strio.eof? # => true
+```
+
+#### Position Before and After Reading
+
+Except for #pread, a stream reading method (see [Basic Reading][basic reading])
+begins reading at the current position.
+
+Except for #pread, a read method advances the position past the read substring.
+
+Examples:
+
+```ruby
+strio = StringIO.new(TEXT)
+strio.string # => "First line\nSecond line\n\nFourth line\nFifth line\n"
+strio.pos # => 0
+strio.getc # => "F"
+strio.pos # => 1
+strio.gets # => "irst line\n"
+strio.pos # => 11
+strio.pos = 24
+strio.gets # => "Fourth line\n"
+strio.pos # => 36
+
+strio = StringIO.new('тест') # Four 2-byte characters.
+strio.pos = 0 # At first byte of first character.
+strio.read # => "тест"
+strio.pos = 1 # At second byte of first character.
+strio.read # => "\x82ест"
+strio.pos = 2 # At first of second character.
+strio.read # => "ест"
+
+strio = StringIO.new(TEXT)
+strio.pos = 15
+a = []
+strio.each_line {|line| a.push(line) }
+a # => ["nd line\n", "\n", "Fourth line\n", "Fifth line\n"]
+strio.pos # => 47 ## End-of-stream.
+```
+
+#### Position Before and After Writing
+
+Each of these methods begins writing at the current position,
+and advances the position to the end of the written substring:
+
+- #putc: writes the given character.
+- #write: writes the given objects as strings.
+- [Kernel#puts][kernel#puts]: writes given objects as strings, each followed by newline.
+
+Examples:
+
+```ruby
+strio = StringIO.new('foo')
+strio.pos # => 0
+strio.putc('b')
+strio.string # => "boo"
+strio.pos # => 1
+strio.write('r')
+strio.string # => "bro"
+strio.pos # => 2
+strio.puts('ew')
+strio.string # => "brew\n"
+strio.pos # => 5
+strio.pos = 8
+strio.write('foo')
+strio.string # => "brew\n\u0000\u0000\u0000foo"
+strio.pos # => 11
+```
+
+Each of these methods writes _before_ the current position, and decrements the position
+so that the written data is next to be read:
+
+- #ungetbyte: unshifts the given byte.
+- #ungetc: unshifts the given character.
+
+Examples:
+
+```ruby
+strio = StringIO.new('foo')
+strio.pos = 2
+strio.ungetc('x')
+strio.pos # => 1
+strio.string # => "fxo"
+strio.ungetc('x')
+strio.pos # => 0
+strio.string # => "xxo"
+```
+
+This method does not affect the position:
+
+- #truncate: truncates the stream's string to the given size.
+
+Examples:
+
+```ruby
+strio = StringIO.new('foobar')
+strio.pos # => 0
+strio.truncate(3)
+strio.string # => "foo"
+strio.pos # => 0
+strio.pos = 500
+strio.truncate(0)
+strio.string # => ""
+strio.pos # => 500
+```
+
+### Line Number
+
+A stream has a line number, which initially is zero:
+
+- Method #lineno returns the line number.
+- Method #lineno= sets the line number.
+
+The line number can be affected by reading (but never by writing);
+in general, the line number is incremented each time the record separator (default: `"\n"`) is read.
+
+Examples:
+
+```ruby
+strio = StringIO.new(TEXT)
+strio.string # => "First line\nSecond line\n\nFourth line\nFifth line\n"
+strio.lineno # => 0
+strio.gets # => "First line\n"
+strio.lineno # => 1
+strio.getc # => "S"
+strio.lineno # => 1
+strio.gets # => "econd line\n"
+strio.lineno # => 2
+strio.gets # => "\n"
+strio.lineno # => 3
+strio.gets # => "Fourth line\n"
+strio.lineno # => 4
+```
+
+Setting the position does not affect the line number:
+
+```ruby
+strio.pos = 0
+strio.lineno # => 4
+strio.gets # => "First line\n"
+strio.pos # => 11
+strio.lineno # => 5
+```
+
+And setting the line number does not affect the position:
+
+```ruby
+strio.lineno = 10
+strio.pos # => 11
+strio.gets # => "Second line\n"
+strio.lineno # => 11
+strio.pos # => 23
+```
+
+### Open/Closed Streams
+
+A new stream is open for either reading or writing, and may be open for both;
+see [Read/Write Mode][read/write mode].
+
+Each of these methods initializes the read/write mode for a new or re-opened stream:
+
+- ::new: returns a new stream.
+- ::open: passes a new stream to the block.
+- #reopen: re-initializes the stream.
+
+Other relevant methods:
+
+- #close: closes the stream for both reading and writing.
+- #close_read: closes the stream for reading.
+- #close_write: closes the stream for writing.
+- #closed?: returns whether the stream is closed for both reading and writing.
+- #closed_read?: returns whether the stream is closed for reading.
+- #closed_write?: returns whether the stream is closed for writing.
+
+### BOM (Byte Order Mark)
+
+The string provided for ::new, ::open, or #reopen
+may contain an optional [BOM][bom] (byte order mark) at the beginning of the string;
+the BOM can affect the stream's encoding.
+
+The BOM (if provided):
+
+- Is stored as part of the stream's string.
+- Does _not_ immediately affect the encoding.
+- Is _initially_ considered part of the stream.
+
+```ruby
+utf8_bom = "\xEF\xBB\xBF"
+string = utf8_bom + 'foo'
+string.bytes # => [239, 187, 191, 102, 111, 111]
+strio.string.bytes.take(3) # => [239, 187, 191] # The BOM.
+strio = StringIO.new(string, 'rb')
+strio.string.bytes # => [239, 187, 191, 102, 111, 111] # BOM is part of the stored string.
+strio.external_encoding # => #<Encoding:BINARY (ASCII-8BIT)> # Default for a binary stream.
+strio.gets # => "\xEF\xBB\xBFfoo" # BOM is part of the stream.
+```
+
+You can call instance method #set_encoding_by_bom to "activate" the stored BOM;
+after doing so the BOM:
+
+- Is _still_ stored as part of the stream's string.
+- _Determines_ (and may have changed) the stream's encoding.
+- Is _no longer_ considered part of the stream.
+
+```ruby
+strio.set_encoding_by_bom
+strio.string.bytes # => [239, 187, 191, 102, 111, 111] # BOM is still part of the stored string.
+strio.external_encoding # => #<Encoding:UTF-8> # The new encoding.
+strio.rewind # => 0
+strio.gets # => "foo" # BOM is not part of the stream.
+```
+
+## Basic Stream \IO
+
+### Basic Reading
+
+You can read from the stream using these instance methods:
+
+- #getbyte: reads and returns the next byte.
+- #getc: reads and returns the next character.
+- #gets: reads and returns all or part of the next line.
+- #read: reads and returns all or part of the remaining data in the stream.
+- #readlines: reads the remaining data the stream and returns an array of its lines.
+- [Kernel#readline][kernel#readline]: like #gets, but raises an exception if at end-of-stream.
+
+You can iterate over the stream using these instance methods:
+
+- #each_byte: reads each remaining byte, passing it to the block.
+- #each_char: reads each remaining character, passing it to the block.
+- #each_codepoint: reads each remaining codepoint, passing it to the block.
+- #each_line: reads all or part of each remaining line, passing the read string to the block
+
+This instance method is useful in a multi-threaded application:
+
+- #pread: reads and returns all or part of the stream.
+
+### Basic Writing
+
+You can write to the stream, advancing the position, using these instance methods:
+
+- #putc: writes a given character.
+- #write: writes the given objects as strings.
+- [Kernel#puts][kernel#puts] writes given objects as strings, each followed by newline.
+
+You can "unshift" to the stream using these instance methods;
+each writes _before_ the current position, and decrements the position
+so that the written data is next to be read.
+
+- #ungetbyte: unshifts the given byte.
+- #ungetc: unshifts the given character.
+
+One more writing method:
+
+- #truncate: truncates the stream's string to the given size.
+
+## Line \IO
+
+Reading:
+
+- #gets: reads and returns the next line.
+- [Kernel#readline][kernel#readline]: like #gets, but raises an exception if at end-of-stream.
+- #readlines: reads the remaining data the stream and returns an array of its lines.
+- #each_line: reads each remaining line, passing it to the block
+
+Writing:
+
+- [Kernel#puts][kernel#puts]: writes given objects, each followed by newline.
+
+## Character \IO
+
+Reading:
+
+- #each_char: reads each remaining character, passing it to the block.
+- #getc: reads and returns the next character.
+
+Writing:
+
+- #putc: writes the given character.
+- #ungetc.: unshifts the given character.
+
+## Byte \IO
+
+Reading:
+
+- #each_byte: reads each remaining byte, passing it to the block.
+- #getbyte: reads and returns the next byte.
+
+Writing:
+
+- #ungetbyte: unshifts the given byte.
+
+## Codepoint \IO
+
+Reading:
+
+- #each_codepoint: reads each remaining codepoint, passing it to the block.
+
+[bom]: https://en.wikipedia.org/wiki/Byte_order_mark
+[encodings document]: https://docs.ruby-lang.org/en/master/language/encodings_rdoc.html
+[io class]: https://docs.ruby-lang.org/en/master/IO.html
+[kernel#puts]: https://docs.ruby-lang.org/en/master/Kernel.html#method-i-puts
+[kernel#readline]: https://docs.ruby-lang.org/en/master/Kernel.html#method-i-readline
+
+[basic reading]: rdoc-ref:StringIO@Basic+Reading
+[basic writing]: rdoc-ref:StringIO@Basic+Writing
+[bom (byte order mark)]: rdoc-ref:StringIO@BOM+-28Byte+Order+Mark-29
+[data mode]: rdoc-ref:StringIO@Data+Mode
+[encodings]: rdoc-ref:StringIO@Encodings
+[end-of-stream]: rdoc-ref:StringIO@End-of-Stream
+[line number]: rdoc-ref:StringIO@Line+Number
+[open/closed streams]: rdoc-ref:StringIO@Open-2FClosed+Streams
+[position]: rdoc-ref:StringIO@Position
+[read/write mode]: rdoc-ref:StringIO@Read-2FWrite+Mode
diff --git a/doc/strscan/helper_methods.md b/doc/strscan/helper_methods.md
new file mode 100644
index 0000000000..9fb1d79bba
--- /dev/null
+++ b/doc/strscan/helper_methods.md
@@ -0,0 +1,124 @@
+## Helper Methods
+
+These helper methods display values returned by scanner's methods.
+
+### `put_situation(scanner)`
+
+Display scanner's situation:
+
+- Byte position (`#pos`).
+- Character position (`#charpos`)
+- Target string (`#rest`) and size (`#rest_size`).
+
+```rb
+scanner = StringScanner.new('foobarbaz')
+scanner.scan(/foo/)
+put_situation(scanner)
+# Situation:
+# pos: 3
+# charpos: 3
+# rest: "barbaz"
+# rest_size: 6
+```
+
+### `put_match_values(scanner)`
+
+Display the scanner's match values:
+
+```rb
+scanner = StringScanner.new('Fri Dec 12 1975 14:39')
+pattern = /(?<wday>\w+) (?<month>\w+) (?<day>\d+) /
+scanner.match?(pattern)
+put_match_values(scanner)
+# Basic match values:
+# matched?: true
+# matched_size: 11
+# pre_match: ""
+# matched : "Fri Dec 12 "
+# post_match: "1975 14:39"
+# Captured match values:
+# size: 4
+# captures: ["Fri", "Dec", "12"]
+# named_captures: {"wday"=>"Fri", "month"=>"Dec", "day"=>"12"}
+# values_at: ["Fri Dec 12 ", "Fri", "Dec", "12", nil]
+# []:
+# [0]: "Fri Dec 12 "
+# [1]: "Fri"
+# [2]: "Dec"
+# [3]: "12"
+# [4]: nil
+```
+
+### `match_values_cleared?(scanner)`
+
+Returns whether the scanner's match values are all properly cleared:
+
+```rb
+scanner = StringScanner.new('foobarbaz')
+match_values_cleared?(scanner) # => true
+put_match_values(scanner)
+# Basic match values:
+# matched?: false
+# matched_size: nil
+# pre_match: nil
+# matched : nil
+# post_match: nil
+# Captured match values:
+# size: nil
+# captures: nil
+# named_captures: {}
+# values_at: nil
+# [0]: nil
+scanner.scan(/foo/)
+match_values_cleared?(scanner) # => false
+```
+
+## The Code
+
+```rb
+def put_situation(scanner)
+ puts '# Situation:'
+ puts "# pos: #{scanner.pos}"
+ puts "# charpos: #{scanner.charpos}"
+ puts "# rest: #{scanner.rest.inspect}"
+ puts "# rest_size: #{scanner.rest_size}"
+end
+
+def put_match_values(scanner)
+ puts '# Basic match values:'
+ puts "# matched?: #{scanner.matched?}"
+ value = scanner.matched_size || 'nil'
+ puts "# matched_size: #{value}"
+ puts "# pre_match: #{scanner.pre_match.inspect}"
+ puts "# matched : #{scanner.matched.inspect}"
+ puts "# post_match: #{scanner.post_match.inspect}"
+ puts '# Captured match values:'
+ puts "# size: #{scanner.size}"
+ puts "# captures: #{scanner.captures}"
+ puts "# named_captures: #{scanner.named_captures}"
+ if scanner.size.nil?
+ puts "# values_at: #{scanner.values_at(0)}"
+ puts "# [0]: #{scanner[0]}"
+ else
+ puts "# values_at: #{scanner.values_at(*(0..scanner.size))}"
+ puts "# []:"
+ scanner.size.times do |i|
+ puts "# [#{i}]: #{scanner[i].inspect}"
+ end
+ end
+end
+
+def match_values_cleared?(scanner)
+ scanner.matched? == false &&
+ scanner.matched_size.nil? &&
+ scanner.matched.nil? &&
+ scanner.pre_match.nil? &&
+ scanner.post_match.nil? &&
+ scanner.size.nil? &&
+ scanner[0].nil? &&
+ scanner.captures.nil? &&
+ scanner.values_at(0..1).nil? &&
+ scanner.named_captures == {}
+end
+```
+
diff --git a/doc/strscan/link_refs.txt b/doc/strscan/link_refs.txt
new file mode 100644
index 0000000000..19f6f7ce5c
--- /dev/null
+++ b/doc/strscan/link_refs.txt
@@ -0,0 +1,17 @@
+[1]: rdoc-ref:StringScanner@Stored+String
+[2]: rdoc-ref:StringScanner@Byte+Position+-28Position-29
+[3]: rdoc-ref:StringScanner@Target+Substring
+[4]: rdoc-ref:StringScanner@Setting+the+Target+Substring
+[5]: rdoc-ref:StringScanner@Traversing+the+Target+Substring
+[6]: https://docs.ruby-lang.org/en/master/Regexp.html
+[7]: rdoc-ref:StringScanner@Character+Position
+[8]: https://docs.ruby-lang.org/en/master/String.html#method-i-5B-5D
+[9]: rdoc-ref:StringScanner@Match+Values
+[10]: rdoc-ref:StringScanner@Fixed-Anchor+Property
+[11]: rdoc-ref:StringScanner@Positions
+[13]: rdoc-ref:StringScanner@Captured+Match+Values
+[14]: rdoc-ref:StringScanner@Querying+the+Target+Substring
+[15]: rdoc-ref:StringScanner@Searching+the+Target+Substring
+[16]: https://docs.ruby-lang.org/en/master/Regexp.html#class-Regexp-label-Groups+and+Captures
+[17]: rdoc-ref:StringScanner@Matching
+[18]: rdoc-ref:StringScanner@Basic+Match+Values
diff --git a/doc/strscan/methods/get_byte.md b/doc/strscan/methods/get_byte.md
new file mode 100644
index 0000000000..3208d77158
--- /dev/null
+++ b/doc/strscan/methods/get_byte.md
@@ -0,0 +1,30 @@
+call-seq:
+ get_byte -> byte_as_character or nil
+
+Returns the next byte, if available:
+
+- If the [position][2]
+ is not at the end of the [stored string][1]:
+
+ - Returns the next byte.
+ - Increments the [byte position][2].
+ - Adjusts the [character position][7].
+
+ ```rb
+ scanner = StringScanner.new(HIRAGANA_TEXT)
+ # => #<StringScanner 0/15 @ "\xE3\x81\x93\xE3\x82...">
+ scanner.string # => "こんにちは"
+ [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\xE3", 1, 1]
+ [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\x81", 2, 2]
+ [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\x93", 3, 1]
+ [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\xE3", 4, 2]
+ [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\x82", 5, 3]
+ [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\x93", 6, 2]
+ ```
+
+- Otherwise, returns `nil`, and does not change the positions.
+
+ ```rb
+ scanner.terminate
+ [scanner.get_byte, scanner.pos, scanner.charpos] # => [nil, 15, 5]
+ ```
diff --git a/doc/strscan/methods/get_charpos.md b/doc/strscan/methods/get_charpos.md
new file mode 100644
index 0000000000..954fcf5b44
--- /dev/null
+++ b/doc/strscan/methods/get_charpos.md
@@ -0,0 +1,19 @@
+call-seq:
+ charpos -> character_position
+
+Returns the [character position][7] (initially zero),
+which may be different from the [byte position][2]
+given by method #pos:
+
+```rb
+scanner = StringScanner.new(HIRAGANA_TEXT)
+scanner.string # => "こんにちは"
+scanner.getch # => "こ" # 3-byte character.
+scanner.getch # => "ん" # 3-byte character.
+put_situation(scanner)
+# Situation:
+# pos: 6
+# charpos: 2
+# rest: "にちは"
+# rest_size: 9
+```
diff --git a/doc/strscan/methods/get_pos.md b/doc/strscan/methods/get_pos.md
new file mode 100644
index 0000000000..81bbb2345e
--- /dev/null
+++ b/doc/strscan/methods/get_pos.md
@@ -0,0 +1,14 @@
+call-seq:
+ pos -> byte_position
+
+Returns the integer [byte position][2],
+which may be different from the [character position][7]:
+
+```rb
+scanner = StringScanner.new(HIRAGANA_TEXT)
+scanner.string # => "こんにちは"
+scanner.pos # => 0
+scanner.getch # => "こ" # 3-byte character.
+scanner.charpos # => 1
+scanner.pos # => 3
+```
diff --git a/doc/strscan/methods/getch.md b/doc/strscan/methods/getch.md
new file mode 100644
index 0000000000..3dd70e4c5b
--- /dev/null
+++ b/doc/strscan/methods/getch.md
@@ -0,0 +1,43 @@
+call-seq:
+ getch -> character or nil
+
+Returns the next (possibly multibyte) character,
+if available:
+
+- If the [position][2]
+ is at the beginning of a character:
+
+ - Returns the character.
+ - Increments the [character position][7] by 1.
+ - Increments the [byte position][2]
+ by the size (in bytes) of the character.
+
+ ```rb
+ scanner = StringScanner.new(HIRAGANA_TEXT)
+ scanner.string # => "こんにちは"
+ [scanner.getch, scanner.pos, scanner.charpos] # => ["こ", 3, 1]
+ [scanner.getch, scanner.pos, scanner.charpos] # => ["ん", 6, 2]
+ [scanner.getch, scanner.pos, scanner.charpos] # => ["に", 9, 3]
+ [scanner.getch, scanner.pos, scanner.charpos] # => ["ち", 12, 4]
+ [scanner.getch, scanner.pos, scanner.charpos] # => ["は", 15, 5]
+ [scanner.getch, scanner.pos, scanner.charpos] # => [nil, 15, 5]
+ ```
+
+- If the [position][2] is within a multi-byte character
+ (that is, not at its beginning),
+ behaves like #get_byte (returns a 1-byte character):
+
+ ```rb
+ scanner.pos = 1
+ [scanner.getch, scanner.pos, scanner.charpos] # => ["\x81", 2, 2]
+ [scanner.getch, scanner.pos, scanner.charpos] # => ["\x93", 3, 1]
+ [scanner.getch, scanner.pos, scanner.charpos] # => ["ん", 6, 2]
+ ```
+
+- If the [position][2] is at the end of the [stored string][1],
+ returns `nil` and does not modify the positions:
+
+ ```rb
+ scanner.terminate
+ [scanner.getch, scanner.pos, scanner.charpos] # => [nil, 15, 5]
+ ```
diff --git a/doc/strscan/methods/scan.md b/doc/strscan/methods/scan.md
new file mode 100644
index 0000000000..22ddd368b6
--- /dev/null
+++ b/doc/strscan/methods/scan.md
@@ -0,0 +1,51 @@
+call-seq:
+ scan(pattern) -> substring or nil
+
+Attempts to [match][17] the given `pattern`
+at the beginning of the [target substring][3].
+
+If the match succeeds:
+
+- Returns the matched substring.
+- Increments the [byte position][2] by <tt>substring.bytesize</tt>,
+ and may increment the [character position][7].
+- Sets [match values][9].
+
+```rb
+scanner = StringScanner.new(HIRAGANA_TEXT)
+scanner.string # => "こんにちは"
+scanner.pos = 6
+scanner.scan(/に/) # => "に"
+put_match_values(scanner)
+# Basic match values:
+# matched?: true
+# matched_size: 3
+# pre_match: "こん"
+# matched : "に"
+# post_match: "ちは"
+# Captured match values:
+# size: 1
+# captures: []
+# named_captures: {}
+# values_at: ["に", nil]
+# []:
+# [0]: "に"
+# [1]: nil
+put_situation(scanner)
+# Situation:
+# pos: 9
+# charpos: 3
+# rest: "ちは"
+# rest_size: 6
+```
+
+If the match fails:
+
+- Returns `nil`.
+- Does not increment byte and character positions.
+- Clears match values.
+
+```rb
+scanner.scan(/nope/) # => nil
+match_values_cleared?(scanner) # => true
+```
diff --git a/doc/strscan/methods/scan_until.md b/doc/strscan/methods/scan_until.md
new file mode 100644
index 0000000000..9a8c7c02f6
--- /dev/null
+++ b/doc/strscan/methods/scan_until.md
@@ -0,0 +1,52 @@
+call-seq:
+ scan_until(pattern) -> substring or nil
+
+Attempts to [match][17] the given `pattern`
+anywhere (at any [position][2]) in the [target substring][3].
+
+If the match attempt succeeds:
+
+- Sets [match values][9].
+- Sets the [byte position][2] to the end of the matched substring;
+ may adjust the [character position][7].
+- Returns the matched substring.
+
+
+```rb
+scanner = StringScanner.new(HIRAGANA_TEXT)
+scanner.string # => "こんにちは"
+scanner.pos = 6
+scanner.scan_until(/ち/) # => "にち"
+put_match_values(scanner)
+# Basic match values:
+# matched?: true
+# matched_size: 3
+# pre_match: "こんに"
+# matched : "ち"
+# post_match: "は"
+# Captured match values:
+# size: 1
+# captures: []
+# named_captures: {}
+# values_at: ["ち", nil]
+# []:
+# [0]: "ち"
+# [1]: nil
+put_situation(scanner)
+# Situation:
+# pos: 12
+# charpos: 4
+# rest: "は"
+# rest_size: 3
+```
+
+If the match attempt fails:
+
+- Clears match data.
+- Returns `nil`.
+- Does not update positions.
+
+```rb
+scanner.scan_until(/nope/) # => nil
+match_values_cleared?(scanner) # => true
+```
diff --git a/doc/strscan/methods/set_pos.md b/doc/strscan/methods/set_pos.md
new file mode 100644
index 0000000000..3b7abe65e3
--- /dev/null
+++ b/doc/strscan/methods/set_pos.md
@@ -0,0 +1,27 @@
+call-seq:
+ pos = n -> n
+ pointer = n -> n
+
+Sets the [byte position][2] and the [character position][11];
+returns `n`.
+
+Does not affect [match values][9].
+
+For non-negative `n`, sets the position to `n`:
+
+```rb
+scanner = StringScanner.new(HIRAGANA_TEXT)
+scanner.string # => "こんにちは"
+scanner.pos = 3 # => 3
+scanner.rest # => "んにちは"
+scanner.charpos # => 1
+```
+
+For negative `n`, counts from the end of the [stored string][1]:
+
+```rb
+scanner.pos = -9 # => -9
+scanner.pos # => 6
+scanner.rest # => "にちは"
+scanner.charpos # => 2
+```
diff --git a/doc/strscan/methods/skip.md b/doc/strscan/methods/skip.md
new file mode 100644
index 0000000000..10a329e0e4
--- /dev/null
+++ b/doc/strscan/methods/skip.md
@@ -0,0 +1,43 @@
+call-seq:
+ skip(pattern) match_size or nil
+
+Attempts to [match][17] the given `pattern`
+at the beginning of the [target substring][3];
+
+If the match succeeds:
+
+- Increments the [byte position][2] by substring.bytesize,
+ and may increment the [character position][7].
+- Sets [match values][9].
+- Returns the size (bytes) of the matched substring.
+
+```rb
+scanner = StringScanner.new(HIRAGANA_TEXT)
+scanner.string # => "こんにちは"
+scanner.pos = 6
+scanner.skip(/に/) # => 3
+put_match_values(scanner)
+# Basic match values:
+# matched?: true
+# matched_size: 3
+# pre_match: "こん"
+# matched : "に"
+# post_match: "ちは"
+# Captured match values:
+# size: 1
+# captures: []
+# named_captures: {}
+# values_at: ["に", nil]
+# []:
+# [0]: "に"
+# [1]: nil
+put_situation(scanner)
+# Situation:
+# pos: 9
+# charpos: 3
+# rest: "ちは"
+# rest_size: 6
+
+scanner.skip(/nope/) # => nil
+match_values_cleared?(scanner) # => true
+```
diff --git a/doc/strscan/methods/skip_until.md b/doc/strscan/methods/skip_until.md
new file mode 100644
index 0000000000..b7dacf6da1
--- /dev/null
+++ b/doc/strscan/methods/skip_until.md
@@ -0,0 +1,49 @@
+call-seq:
+ skip_until(pattern) -> matched_substring_size or nil
+
+Attempts to [match][17] the given `pattern`
+anywhere (at any [position][2]) in the [target substring][3];
+does not modify the positions.
+
+If the match attempt succeeds:
+
+- Sets [match values][9].
+- Returns the size of the matched substring.
+
+```rb
+scanner = StringScanner.new(HIRAGANA_TEXT)
+scanner.string # => "こんにちは"
+scanner.pos = 6
+scanner.skip_until(/ち/) # => 6
+put_match_values(scanner)
+# Basic match values:
+# matched?: true
+# matched_size: 3
+# pre_match: "こんに"
+# matched : "ち"
+# post_match: "は"
+# Captured match values:
+# size: 1
+# captures: []
+# named_captures: {}
+# values_at: ["ち", nil]
+# []:
+# [0]: "ち"
+# [1]: nil
+put_situation(scanner)
+# Situation:
+# pos: 12
+# charpos: 4
+# rest: "は"
+# rest_size: 3
+```
+
+If the match attempt fails:
+
+- Clears match values.
+- Returns `nil`.
+
+```rb
+scanner.skip_until(/nope/) # => nil
+match_values_cleared?(scanner) # => true
+```
diff --git a/doc/strscan/methods/terminate.md b/doc/strscan/methods/terminate.md
new file mode 100644
index 0000000000..b03b37d2a2
--- /dev/null
+++ b/doc/strscan/methods/terminate.md
@@ -0,0 +1,30 @@
+call-seq:
+ terminate -> self
+
+Sets the scanner to end-of-string;
+returns +self+:
+
+- Sets both [positions][11] to end-of-stream.
+- Clears [match values][9].
+
+```rb
+scanner = StringScanner.new(HIRAGANA_TEXT)
+scanner.string # => "こんにちは"
+scanner.scan_until(/に/)
+put_situation(scanner)
+# Situation:
+# pos: 9
+# charpos: 3
+# rest: "ちは"
+# rest_size: 6
+match_values_cleared?(scanner) # => false
+
+scanner.terminate # => #<StringScanner fin>
+put_situation(scanner)
+# Situation:
+# pos: 15
+# charpos: 5
+# rest: ""
+# rest_size: 0
+match_values_cleared?(scanner) # => true
+```
diff --git a/doc/strscan/strscan.md b/doc/strscan/strscan.md
new file mode 100644
index 0000000000..385e92f84e
--- /dev/null
+++ b/doc/strscan/strscan.md
@@ -0,0 +1,544 @@
+\Class `StringScanner` supports processing a stored string as a stream;
+this code creates a new `StringScanner` object with string `'foobarbaz'`:
+
+```rb
+require 'strscan'
+scanner = StringScanner.new('foobarbaz')
+```
+
+## About the Examples
+
+All examples here assume that `StringScanner` has been required:
+
+```rb
+require 'strscan'
+```
+
+Some examples here assume that these constants are defined:
+
+```rb
+MULTILINE_TEXT = <<~EOT
+Go placidly amid the noise and haste,
+and remember what peace there may be in silence.
+EOT
+
+HIRAGANA_TEXT = 'こんにちは'
+
+ENGLISH_TEXT = 'Hello'
+```
+
+Some examples here assume that certain helper methods are defined:
+
+- `put_situation(scanner)`:
+ Displays the values of the scanner's
+ methods #pos, #charpos, #rest, and #rest_size.
+- `put_match_values(scanner)`:
+ Displays the scanner's [match values][9].
+- `match_values_cleared?(scanner)`:
+ Returns whether the scanner's [match values][9] are cleared.
+
+See examples at [helper methods](helper_methods.md).
+
+## The `StringScanner` \Object
+
+This code creates a `StringScanner` object
+(we'll call it simply a _scanner_),
+and shows some of its basic properties:
+
+```rb
+scanner = StringScanner.new('foobarbaz')
+scanner.string # => "foobarbaz"
+put_situation(scanner)
+# Situation:
+# pos: 0
+# charpos: 0
+# rest: "foobarbaz"
+# rest_size: 9
+```
+
+The scanner has:
+
+* A <i>stored string</i>, which is:
+
+ * Initially set by StringScanner.new(string) to the given `string`
+ (`'foobarbaz'` in the example above).
+ * Modifiable by methods #string=(new_string) and #concat(more_string).
+ * Returned by method #string.
+
+ More at [Stored String][1] below.
+
+* A _position_;
+ a zero-based index into the bytes of the stored string (_not_ into its characters):
+
+ * Initially set by StringScanner.new to `0`.
+ * Returned by method #pos.
+ * Modifiable explicitly by methods #reset, #terminate, and #pos=(new_pos).
+ * Modifiable implicitly (various traversing methods, among others).
+
+ More at [Byte Position][2] below.
+
+* A <i>target substring</i>,
+ which is a trailing substring of the stored string;
+ it extends from the current position to the end of the stored string:
+
+ * Initially set by StringScanner.new(string) to the given `string`
+ (`'foobarbaz'` in the example above).
+ * Returned by method #rest.
+ * Modified by any modification to either the stored string or the position.
+
+ <b>Most importantly</b>:
+ the searching and traversing methods operate on the target substring,
+ which may be (and often is) less than the entire stored string.
+
+ More at [Target Substring][3] below.
+
+## Stored \String
+
+The <i>stored string</i> is the string stored in the `StringScanner` object.
+
+Each of these methods sets, modifies, or returns the stored string:
+
+| Method | Effect |
+|----------------------|-------------------------------------------------|
+| ::new(string) | Creates a new scanner for the given string. |
+| #string=(new_string) | Replaces the existing stored string. |
+| #concat(more_string) | Appends a string to the existing stored string. |
+| #string | Returns the stored string. |
+
+## Positions
+
+A `StringScanner` object maintains a zero-based <i>byte position</i>
+and a zero-based <i>character position</i>.
+
+Each of these methods explicitly sets positions:
+
+| Method | Effect |
+|--------------------------|-----------------------------------------------------------|
+| #reset | Sets both positions to zero (beginning of stored string). |
+| #terminate | Sets both positions to the end of the stored string. |
+| #pos=(new_byte_position) | Sets byte position; adjusts character position. |
+
+### Byte Position (Position)
+
+The byte position (or simply _position_)
+is a zero-based index into the bytes in the scanner's stored string;
+for a new `StringScanner` object, the byte position is zero.
+
+When the byte position is:
+
+* Zero (at the beginning), the target substring is the entire stored string.
+* Equal to the size of the stored string (at the end),
+ the target substring is the empty string `''`.
+
+To get or set the byte position:
+
+* \#pos: returns the byte position.
+* \#pos=(new_pos): sets the byte position.
+
+Many methods use the byte position as the basis for finding matches;
+many others set, increment, or decrement the byte position:
+
+```rb
+scanner = StringScanner.new('foobar')
+scanner.pos # => 0
+scanner.scan(/foo/) # => "foo" # Match found.
+scanner.pos # => 3 # Byte position incremented.
+scanner.scan(/foo/) # => nil # Match not found.
+scanner.pos # => 3 # Byte position not changed.
+```
+
+Some methods implicitly modify the byte position;
+see:
+
+* [Setting the Target Substring][4].
+* [Traversing the Target Substring][5].
+
+The values of these methods are derived directly from the values of #pos and #string:
+
+- \#charpos: the [character position][7].
+- \#rest: the [target substring][3].
+- \#rest_size: `rest.size`.
+
+### Character Position
+
+The character position is a zero-based index into the _characters_
+in the stored string;
+for a new `StringScanner` object, the character position is zero.
+
+\Method #charpos returns the character position;
+its value may not be reset explicitly.
+
+Some methods change (increment or reset) the character position;
+see:
+
+* [Setting the Target Substring][4].
+* [Traversing the Target Substring][5].
+
+Example (string includes multi-byte characters):
+
+```rb
+scanner = StringScanner.new(ENGLISH_TEXT) # Five 1-byte characters.
+scanner.concat(HIRAGANA_TEXT) # Five 3-byte characters
+scanner.string # => "Helloこんにちは" # Twenty bytes in all.
+put_situation(scanner)
+# Situation:
+# pos: 0
+# charpos: 0
+# rest: "Helloこんにちは"
+# rest_size: 20
+scanner.scan(/Hello/) # => "Hello" # Five 1-byte characters.
+put_situation(scanner)
+# Situation:
+# pos: 5
+# charpos: 5
+# rest: "こんにちは"
+# rest_size: 15
+scanner.getch # => "こ" # One 3-byte character.
+put_situation(scanner)
+# Situation:
+# pos: 8
+# charpos: 6
+# rest: "んにちは"
+# rest_size: 12
+```
+
+## Target Substring
+
+The target substring is the part of the [stored string][1]
+that extends from the current [byte position][2] to the end of the stored string;
+it is always either:
+
+- The entire stored string (byte position is zero).
+- A trailing substring of the stored string (byte position positive).
+
+The target substring is returned by method #rest,
+and its size is returned by method #rest_size.
+
+Examples:
+
+```rb
+scanner = StringScanner.new('foobarbaz')
+put_situation(scanner)
+# Situation:
+# pos: 0
+# charpos: 0
+# rest: "foobarbaz"
+# rest_size: 9
+scanner.pos = 3
+put_situation(scanner)
+# Situation:
+# pos: 3
+# charpos: 3
+# rest: "barbaz"
+# rest_size: 6
+scanner.pos = 9
+put_situation(scanner)
+# Situation:
+# pos: 9
+# charpos: 9
+# rest: ""
+# rest_size: 0
+```
+
+### Setting the Target Substring
+
+The target substring is set whenever:
+
+* The [stored string][1] is set (position reset to zero; target substring set to stored string).
+* The [byte position][2] is set (target substring adjusted accordingly).
+
+### Querying the Target Substring
+
+This table summarizes (details and examples at the links):
+
+| Method | Returns |
+|------------|-----------------------------------|
+| #rest | Target substring. |
+| #rest_size | Size (bytes) of target substring. |
+
+### Searching the Target Substring
+
+A _search_ method examines the target substring,
+but does not advance the [positions][11]
+or (by implication) shorten the target substring.
+
+This table summarizes (details and examples at the links):
+
+| Method | Returns | Sets Match Values? |
+|-----------------------|-----------------------------------------------|--------------------|
+| #check(pattern) | Matched leading substring or +nil+. | Yes. |
+| #check_until(pattern) | Matched substring (anywhere) or +nil+. | Yes. |
+| #exist?(pattern) | Matched substring (anywhere) end index. | Yes. |
+| #match?(pattern) | Size of matched leading substring or +nil+. | Yes. |
+| #peek(size) | Leading substring of given length (bytes). | No. |
+| #peek_byte | Integer leading byte or +nil+. | No. |
+| #rest | Target substring (from byte position to end). | No. |
+
+### Traversing the Target Substring
+
+A _traversal_ method examines the target substring,
+and, if successful:
+
+- Advances the [positions][11].
+- Shortens the target substring.
+
+
+This table summarizes (details and examples at links):
+
+| Method | Returns | Sets Match Values? |
+|----------------------|------------------------------------------------------|--------------------|
+| #get_byte | Leading byte or +nil+. | No. |
+| #getch | Leading character or +nil+. | No. |
+| #scan(pattern) | Matched leading substring or +nil+. | Yes. |
+| #scan_byte | Integer leading byte or +nil+. | No. |
+| #scan_until(pattern) | Matched substring (anywhere) or +nil+. | Yes. |
+| #skip(pattern) | Matched leading substring size or +nil+. | Yes. |
+| #skip_until(pattern) | Position delta to end-of-matched-substring or +nil+. | Yes. |
+| #unscan | +self+. | No. |
+
+## Querying the Scanner
+
+Each of these methods queries the scanner object
+without modifying it (details and examples at links)
+
+| Method | Returns |
+|---------------------|----------------------------------|
+| #beginning_of_line? | +true+ or +false+. |
+| #charpos | Character position. |
+| #eos? | +true+ or +false+. |
+| #fixed_anchor? | +true+ or +false+. |
+| #inspect | String representation of +self+. |
+| #pos | Byte position. |
+| #rest | Target substring. |
+| #rest_size | Size of target substring. |
+| #string | Stored string. |
+
+## Matching
+
+`StringScanner` implements pattern matching via Ruby class [Regexp][6],
+and its matching behaviors are the same as Ruby's
+except for the [fixed-anchor property][10].
+
+### Matcher Methods
+
+Each <i>matcher method</i> takes a single argument `pattern`,
+and attempts to find a matching substring in the [target substring][3].
+
+| Method | Pattern Type | Matches Target Substring | Success Return | May Update Positions? |
+|--------------|-------------------|--------------------------|--------------------|-----------------------|
+| #check | Regexp or String. | At beginning. | Matched substring. | No. |
+| #check_until | Regexp or String. | Anywhere. | Substring. | No. |
+| #match? | Regexp or String. | At beginning. | Match size. | No. |
+| #exist? | Regexp or String. | Anywhere. | Substring size. | No. |
+| #scan | Regexp or String. | At beginning. | Matched substring. | Yes. |
+| #scan_until | Regexp or String. | Anywhere. | Substring. | Yes. |
+| #skip | Regexp or String. | At beginning. | Match size. | Yes. |
+| #skip_until | Regexp or String. | Anywhere. | Substring size. | Yes. |
+
+<br>
+
+Which matcher you choose will depend on:
+
+- Where you want to find a match:
+
+ - Only at the beginning of the target substring:
+ #check, #match?, #scan, #skip.
+ - Anywhere in the target substring:
+ #check_until, #exist?, #scan_until, #skip_until.
+
+- Whether you want to:
+
+ - Traverse, by advancing the positions:
+ #scan, #scan_until, #skip, #skip_until.
+ - Keep the positions unchanged:
+ #check, #check_until, #match?, #exist?.
+
+- What you want for the return value:
+
+ - The matched substring: #check, #scan.
+ - The substring: #check_until, #scan_until.
+ - The match size: #match?, #skip.
+ - The substring size: #exist?, #skip_until.
+
+### Match Values
+
+The <i>match values</i> in a `StringScanner` object
+generally contain the results of the most recent attempted match.
+
+Each match value may be thought of as:
+
+* _Clear_: Initially, or after an unsuccessful match attempt:
+ usually, `false`, `nil`, or `{}`.
+* _Set_: After a successful match attempt:
+ `true`, string, array, or hash.
+
+Each of these methods clears match values:
+
+- ::new(string).
+- \#reset.
+- \#terminate.
+
+Each of these methods attempts a match based on a pattern,
+and either sets match values (if successful) or clears them (if not);
+
+- \#check(pattern)
+- \#check_until(pattern)
+- \#exist?(pattern)
+- \#match?(pattern)
+- \#scan(pattern)
+- \#scan_until(pattern)
+- \#skip(pattern)
+- \#skip_until(pattern)
+
+#### Basic Match Values
+
+Basic match values are those not related to captures.
+
+Each of these methods returns a basic match value:
+
+| Method | Return After Match | Return After No Match |
+|-----------------|----------------------------------------|-----------------------|
+| #matched? | +true+. | +false+. |
+| #matched_size | Size of matched substring. | +nil+. |
+| #matched | Matched substring. | +nil+. |
+| #pre_match | Substring preceding matched substring. | +nil+. |
+| #post_match | Substring following matched substring. | +nil+. |
+
+<br>
+
+See examples below.
+
+#### Captured Match Values
+
+Captured match values are those related to [captures][16].
+
+Each of these methods returns a captured match value:
+
+| Method | Return After Match | Return After No Match |
+|-----------------|-----------------------------------------|-----------------------|
+| #size | Count of captured substrings. | +nil+. |
+| #\[\](n) | <tt>n</tt>th captured substring. | +nil+. |
+| #captures | Array of all captured substrings. | +nil+. |
+| #values_at(*n) | Array of specified captured substrings. | +nil+. |
+| #named_captures | Hash of named captures. | <tt>{}</tt>. |
+
+<br>
+
+See examples below.
+
+#### Match Values Examples
+
+Successful basic match attempt (no captures):
+
+```rb
+scanner = StringScanner.new('foobarbaz')
+scanner.exist?(/bar/)
+put_match_values(scanner)
+# Basic match values:
+# matched?: true
+# matched_size: 3
+# pre_match: "foo"
+# matched : "bar"
+# post_match: "baz"
+# Captured match values:
+# size: 1
+# captures: []
+# named_captures: {}
+# values_at: ["bar", nil]
+# []:
+# [0]: "bar"
+# [1]: nil
+```
+
+Failed basic match attempt (no captures);
+
+```rb
+scanner = StringScanner.new('foobarbaz')
+scanner.exist?(/nope/)
+match_values_cleared?(scanner) # => true
+```
+
+Successful unnamed capture match attempt:
+
+```rb
+scanner = StringScanner.new('foobarbazbatbam')
+scanner.exist?(/(foo)bar(baz)bat(bam)/)
+put_match_values(scanner)
+# Basic match values:
+# matched?: true
+# matched_size: 15
+# pre_match: ""
+# matched : "foobarbazbatbam"
+# post_match: ""
+# Captured match values:
+# size: 4
+# captures: ["foo", "baz", "bam"]
+# named_captures: {}
+# values_at: ["foobarbazbatbam", "foo", "baz", "bam", nil]
+# []:
+# [0]: "foobarbazbatbam"
+# [1]: "foo"
+# [2]: "baz"
+# [3]: "bam"
+# [4]: nil
+```
+
+Successful named capture match attempt;
+same as unnamed above, except for #named_captures:
+
+```rb
+scanner = StringScanner.new('foobarbazbatbam')
+scanner.exist?(/(?<x>foo)bar(?<y>baz)bat(?<z>bam)/)
+scanner.named_captures # => {"x"=>"foo", "y"=>"baz", "z"=>"bam"}
+```
+
+Failed unnamed capture match attempt:
+
+```rb
+scanner = StringScanner.new('somestring')
+scanner.exist?(/(foo)bar(baz)bat(bam)/)
+match_values_cleared?(scanner) # => true
+```
+
+Failed named capture match attempt;
+same as unnamed above, except for #named_captures:
+
+```rb
+scanner = StringScanner.new('somestring')
+scanner.exist?(/(?<x>foo)bar(?<y>baz)bat(?<z>bam)/)
+match_values_cleared?(scanner) # => false
+scanner.named_captures # => {"x"=>nil, "y"=>nil, "z"=>nil}
+```
+
+## Fixed-Anchor Property
+
+Pattern matching in `StringScanner` is the same as in Ruby's,
+except for its fixed-anchor property,
+which determines the meaning of `'\A'`:
+
+* `false` (the default): matches the current byte position.
+
+ ```rb
+ scanner = StringScanner.new('foobar')
+ scanner.scan(/\A./) # => "f"
+ scanner.scan(/\A./) # => "o"
+ scanner.scan(/\A./) # => "o"
+ scanner.scan(/\A./) # => "b"
+ ```
+
+* `true`: matches the beginning of the target substring;
+ never matches unless the byte position is zero:
+
+ ```rb
+ scanner = StringScanner.new('foobar', fixed_anchor: true)
+ scanner.scan(/\A./) # => "f"
+ scanner.scan(/\A./) # => nil
+ scanner.reset
+ scanner.scan(/\A./) # => "f"
+ ```
+
+The fixed-anchor property is set when the `StringScanner` object is created,
+and may not be modified
+(see StringScanner.new);
+method #fixed_anchor? returns the setting.
+
diff --git a/doc/syntax.rdoc b/doc/syntax.rdoc
index 6ca5843512..a48c83ff15 100644
--- a/doc/syntax.rdoc
+++ b/doc/syntax.rdoc
@@ -2,6 +2,9 @@
The Ruby syntax is large and is split up into the following sections:
+{Code Layout}[rdoc-ref:syntax/layout.rdoc] ::
+ Breaking code in lines
+
Literals[rdoc-ref:syntax/literals.rdoc] ::
Numbers, Strings, Arrays, Hashes, etc.
@@ -12,7 +15,7 @@ Assignment[rdoc-ref:syntax/assignment.rdoc] ::
+if+, +unless+, +while+, +until+, +for+, +break+, +next+, +redo+
{Pattern matching}[rdoc-ref:syntax/pattern_matching.rdoc] ::
- Experimental structural pattern matching and variable binding syntax
+ Structural pattern matching and variable binding syntax
Methods[rdoc-ref:syntax/methods.rdoc] ::
Method and method argument syntax
diff --git a/doc/syntax/assignment.rdoc b/doc/syntax/assignment.rdoc
index f45f5bc0ea..3988f82e5f 100644
--- a/doc/syntax/assignment.rdoc
+++ b/doc/syntax/assignment.rdoc
@@ -9,7 +9,7 @@ Assignment creates a local variable if the variable was not previously
referenced.
An assignment expression result is always the assigned value, including
-{assignment methods}[rdoc-ref:syntax/assignment.rdoc@Assignment+Methods].
+{assignment methods}[rdoc-ref:@Assignment+Methods].
== Local Variable Names
@@ -279,7 +279,7 @@ An uninitialized global variable has a value of +nil+.
Ruby has some special globals that behave differently depending on context
such as the regular expression match variables or that have a side-effect when
-assigned to. See the {global variables documentation}[rdoc-ref:globals.rdoc]
+assigned to. See the {global variables documentation}[rdoc-ref:language/globals.md]
for details.
== Assignment Methods
diff --git a/doc/syntax/calling_methods.rdoc b/doc/syntax/calling_methods.rdoc
index c2c6c61a10..76babcc3dc 100644
--- a/doc/syntax/calling_methods.rdoc
+++ b/doc/syntax/calling_methods.rdoc
@@ -30,7 +30,7 @@ NoMethodError.
You may also use <code>::</code> to designate a receiver, but this is rarely
used due to the potential for confusion with <code>::</code> for namespaces.
-=== Chaining \Method Calls
+=== Chaining Method Calls
You can "chain" method calls by immediately following one method call with another.
@@ -291,16 +291,16 @@ override local arguments outside the block in the caller's scope:
This prints:
hello main this is block
- place is world
+ place is: world
So the +place+ variable in the block is not the same +place+ variable as
outside the block. Removing <code>; place</code> from the block arguments
gives this result:
hello main this is block
- place is block
+ place is: block
-=== Array to Arguments Conversion
+=== Unpacking Positional Arguments
Given the following method:
@@ -322,6 +322,59 @@ Both are equivalent to:
my_method(1, 2, 3)
+The <code>*</code> unpacking operator can be applied to any object, not only
+arrays. If the object responds to a <code>#to_a</code> method, this method
+is called, and is expected to return an Array, and elements of this array are passed
+as separate positional arguments:
+
+ class Name
+ def initialize(name)
+ @name = name
+ end
+
+ def to_a = @name.split(' ')
+ end
+
+ name = Name.new('Jane Doe')
+ p(*name)
+ # prints separate values:
+ # Jane
+ # Doe
+
+If the object doesn't have a <code>#to_a</code> method, the object itself is passed
+as one argument:
+
+ class Name
+ def initialize(name)
+ @name = name
+ end
+ end
+
+ name = Name.new('Jane Doe')
+ p(*name)
+ # Prints the object itself:
+ # #<Name:0x00007f9d07bca650 @name="Jane Doe">
+
+This allows to handle one or many arguments polymorphically. Note also that <tt>*nil</tt>
+is unpacked to an empty list of arguments, so conditional unpacking is possible:
+
+ my_method(*(some_arguments if some_condition?))
+
+If <code>#to_a</code> method exists and does not return an Array, it would be an
+error on unpacking:
+
+ class Name
+ def initialize(name)
+ @name = name
+ end
+
+ def to_a = @name
+ end
+
+ name = Name.new('Jane Doe')
+ p(*name)
+ # can't convert Name to Array (Name#to_a gives String) (TypeError)
+
You may also use the <code>**</code> (described next) to convert a Hash into
keyword arguments.
@@ -329,12 +382,13 @@ If the number of objects in the Array do not match the number of arguments for
the method, an ArgumentError will be raised.
If the splat operator comes first in the call, parentheses must be used to
-avoid a warning:
+avoid an ambiguity of interpretation as an unpacking operator or multiplication
+operator. In this case, Ruby issues a warning in verbose mode:
- my_method *arguments # warning
+ my_method *arguments # warning: '*' interpreted as argument prefix
my_method(*arguments) # no warning
-=== Hash to Keyword Arguments Conversion
+=== Unpacking Keyword Arguments
Given the following method:
@@ -356,6 +410,35 @@ Both are equivalent to:
my_method(first: 3, second: 4, third: 5)
+The <code>**</code> unpacking operator can be applied to any object, not only
+hashes. If the object responds to a <code>#to_hash</code> method, this method
+is called, and is expected to return an Hash, and elements of this hash are passed
+as keyword arguments:
+
+ class Name
+ def initialize(name)
+ @name = name
+ end
+
+ def to_hash = {first: @name.split(' ').first, last: @name.split(' ').last}
+ end
+
+ name = Name.new('Jane Doe')
+ p(**name)
+ # Prints: {name: "Jane", last: "Doe"}
+
+Unlike <code>*</code> operator, <code>**</code> raises an error when used on an
+object that doesn't respond to <code>#to_hash</code>. The one exception is
++nil+, which doesn't explicitly define this method, but is still allowed to
+be used in <code>**</code> unpacking, not adding any keyword arguments.
+
+Again, this allows for conditional unpacking:
+
+ my_method(some: params, **(some_extra_params if pass_extra_params?))
+
+Like <code>*</code> operator, <code>**</code> raises an error when the object responds
+to <code>#to_hash</code>, but it doesn't return a Hash.
+
If the method definition uses the keyword splat operator to
gather arbitrary keyword arguments, they will not be gathered
by <code>*</code>:
diff --git a/doc/syntax/comments.rdoc b/doc/syntax/comments.rdoc
index 00d19d588a..cb6829a984 100644
--- a/doc/syntax/comments.rdoc
+++ b/doc/syntax/comments.rdoc
@@ -170,7 +170,7 @@ 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(...)
+ # same as FOO = Ractor.make_shareable(...)
# OR same as `FOO = Set[1, 2, {foo: [].freeze}.freeze].freeze`
var = [{foo: []}]
diff --git a/doc/syntax/control_expressions.rdoc b/doc/syntax/control_expressions.rdoc
index 9126289389..3de6cd293f 100644
--- a/doc/syntax/control_expressions.rdoc
+++ b/doc/syntax/control_expressions.rdoc
@@ -255,7 +255,7 @@ Again, the +then+ and +else+ are optional.
The result value of a +case+ expression is the last value executed in the
expression.
-Since Ruby 2.7, +case+ expressions also provide a more powerful experimental
+Since Ruby 2.7, +case+ expressions also provide a more powerful
pattern matching feature via the +in+ keyword:
case {a: 1, b: 2, c: 3}
diff --git a/doc/syntax/exceptions.rdoc b/doc/syntax/exceptions.rdoc
index ac5ff78a95..cdf9d367a7 100644
--- a/doc/syntax/exceptions.rdoc
+++ b/doc/syntax/exceptions.rdoc
@@ -103,4 +103,4 @@ You may also run some code when an exception is not raised:
# It will not return implicitly.
end
-NB : Without explicit +return+ in the +ensure+ block, +begin+/+end+ block will return the last evaluated statement before entering in the `ensure` block.
+NB : Without explicit +return+ in the +ensure+ block, +begin+/+end+ block will return the last evaluated statement before entering in the +ensure+ block.
diff --git a/doc/keywords.rdoc b/doc/syntax/keywords.rdoc
index 7c368205ef..7c368205ef 100644
--- a/doc/keywords.rdoc
+++ b/doc/syntax/keywords.rdoc
diff --git a/doc/syntax/layout.rdoc b/doc/syntax/layout.rdoc
new file mode 100644
index 0000000000..f07447587b
--- /dev/null
+++ b/doc/syntax/layout.rdoc
@@ -0,0 +1,118 @@
+= Code Layout
+
+Expressions in Ruby are separated by line breaks:
+
+ x = 1
+ y = 2
+ z = x + y
+
+Line breaks also used as logical separators of the headers of some of control structures from their bodies:
+
+ if z > 3 # line break ends the condition and starts the body
+ puts "more"
+ end
+
+ while x < 3 # line break ends the condition and starts the body
+ x += 1
+ end
+
+<tt>;</tt> can be used as an expressions separator instead of a line break:
+
+ x = 1; y = 2; z = x + y
+ if z > 3; puts "more"; end
+
+Traditionally, expressions separated by <tt>;</tt> is used only in short scripts and experiments.
+
+In some control structures, there is an optional keyword that can be used instead of a line break to separate their elements:
+
+ # if, elsif, until and case ... when: 'then' is an optional separator:
+
+ if z > 3 then puts "more" end
+
+ case x
+ when Numeric then "number"
+ when String then "string"
+ else "object"
+ end
+
+ # while and until: 'do' is an optional separator
+ while x < 3 do x +=1 end
+
+Also, line breaks can be skipped in some places where it doesn't create any ambiguity. Note in the example above: no line break needed before +end+, just as no line break needed after +else+.
+
+== Breaking expressions in lines
+
+One expression might be split into several lines when each line can be unambiguously identified as "incomplete" without the next one.
+
+These works:
+
+ x = # incomplete without something after =
+ 1 + # incomplete without something after +
+ 2
+
+ File.read "test.txt", # incomplete without something after ,
+ enconding: "utf-8"
+
+These would not:
+
+ # unintended interpretation:
+ x = 1 # already complete expression
+ + 2 # interpreted as a separate +2
+
+ # syntax error:
+ File.read "test.txt" # already complete expression
+ , encoding: "utf-8" # attempt to parse as a new expression, SyntaxError
+
+The exceptions to the rule are lines starting with <tt>.</tt> ("leading dot" style of method calls) or logical operators <tt>&&</tt>/<tt>||</tt> and <tt>and</tt>/<tt>or</tt>:
+
+ # OK, interpreted as a chain of calls
+ File.read('test.txt')
+ .strip("\n")
+ .split("\t")
+ .sort
+
+ # OK, interpreted as a chain of logical operators:
+ File.empty?('test.txt')
+ || File.size('test.txt') < 10
+ || File.read('test.txt').strip.empty?
+
+If the expressions is broken into multiple lines in any of the ways described above, comments between separate lines are allowed:
+
+ sum = base_salary +
+ # see "yearly bonuses section"
+ yearly_bonus(year) +
+ # per-employee coefficient is described
+ # in another module
+ personal_coeff(employee)
+
+ # We want to short-circuit on empty files
+ File.empty?('test.txt')
+ # Or almost empty ones
+ || File.size('test.txt') < 10
+ # Otherwise we check if it is full of spaces
+ || File.read('test.txt').strip.empty?
+
+Finally, the code can explicitly tell Ruby that the expression is continued on the next line with <tt>\\</tt>:
+
+ # Unusual, but works
+ File.read "test.txt" \
+ , encoding: "utf-8"
+
+ # More regular usage (joins the strings on parsing instead
+ # of concatenating them in runtime, as + would do):
+ TEXT = "One pretty long line" \
+ "one more long line" \
+ "one other line of the text"
+
+The <tt>\\</tt> works as a parse time line break escape, so with it, comments can not be inserted between the lines:
+
+ TEXT = "line 1" \
+ # here would be line 2:
+ "line 2"
+
+ # This is interpreted as if there was no line break where \ is,
+ # i.e. the same as
+ TEXT = "line 1" # here would be line 2:
+ "line 2"
+
+ puts TEXT #=> "line 1"
diff --git a/doc/syntax/literals.rdoc b/doc/syntax/literals.rdoc
index 0c1e4a434b..87a891bf2d 100644
--- a/doc/syntax/literals.rdoc
+++ b/doc/syntax/literals.rdoc
@@ -3,7 +3,7 @@
Literals create objects you can use in your program. Literals include:
* {Boolean and Nil Literals}[#label-Boolean+and+Nil+Literals]
-* {Number Literals}[#label-Number+Literals]
+* {Numeric Literals}[#label-Numeric+Literals]
* {Integer Literals}[#label-Integer+Literals]
* {Float Literals}[#label-Float+Literals]
@@ -36,7 +36,7 @@ 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.
-== Number Literals
+== \Numeric Literals
=== \Integer Literals
@@ -136,9 +136,9 @@ Also \Rational numbers may be imaginary numbers.
12.3ir #=> Syntax error
-== Strings
+== \String Literals
-=== \String Literals
+=== Double-Quoted \String Literals
The most common way of writing strings is using <tt>"</tt>:
@@ -150,35 +150,14 @@ Any internal <tt>"</tt> must be escaped:
"This string has a quote: \". As you can see, it is escaped"
-Double-quote strings allow escaped characters such as <tt>\n</tt> for
-newline, <tt>\t</tt> for tab, etc. The full list of supported escape
-sequences are as follows:
+Double-quoted strings allow escape sequences described in
+{Escape Sequences}[#label-Escape+Sequences].
- \a bell, ASCII 07h (BEL)
- \b backspace, ASCII 08h (BS)
- \t horizontal tab, ASCII 09h (TAB)
- \n newline (line feed), ASCII 0Ah (LF)
- \v vertical tab, ASCII 0Bh (VT)
- \f form feed, ASCII 0Ch (FF)
- \r carriage return, ASCII 0Dh (CR)
- \e escape, ASCII 1Bh (ESC)
- \s space, ASCII 20h (SPC)
- \\ backslash, \
- \nnn octal bit pattern, where nnn is 1-3 octal digits ([0-7])
- \xnn hexadecimal bit pattern, where nn is 1-2 hexadecimal digits ([0-9a-fA-F])
- \unnnn Unicode character, where nnnn is exactly 4 hexadecimal digits ([0-9a-fA-F])
- \u{nnnn ...} Unicode character(s), where each nnnn is 1-6 hexadecimal digits ([0-9a-fA-F])
- \cx or \C-x control character, where x is an ASCII printable character
- \M-x meta character, where x is an ASCII printable character
- \M-\C-x meta control character, where x is an ASCII printable character
- \M-\cx same as above
- \c\M-x same as above
- \c? or \C-? delete, ASCII 7Fh (DEL)
-
-Any other character following a backslash is interpreted as the
+In a double-quoted string,
+any other character following a backslash is interpreted as the
character itself.
-Double-quote strings allow interpolation of other values using
+Double-quoted strings allow interpolation of other values using
<tt>#{...}</tt>:
"One plus one is two: #{1 + 1}"
@@ -190,8 +169,14 @@ You can also use <tt>#@foo</tt>, <tt>#@@foo</tt> and <tt>#$foo</tt> as a
shorthand for, respectively, <tt>#{ @foo }</tt>, <tt>#{ @@foo }</tt> and
<tt>#{ $foo }</tt>.
+See also:
+
+* {% and %Q: Interpolable String Literals}[#label-25+and+-25Q-3A+Interpolable+String+Literals]
+
+=== Single-Quoted \String Literals
+
Interpolation may be disabled by escaping the "#" character or using
-single-quote strings:
+single-quoted strings:
'#{1 + 1}' #=> "\#{1 + 1}"
@@ -199,6 +184,16 @@ In addition to disabling interpolation, single-quoted strings also disable all
escape sequences except for the single-quote (<tt>\'</tt>) and backslash
(<tt>\\\\</tt>).
+In a single-quoted string,
+any other character following a backslash is interpreted as is:
+a backslash and the character itself.
+
+See also:
+
+* {%q: Non-Interpolable String Literals}[#label-25q-3A+Non-Interpolable+String+Literals]
+
+=== Literal String Concatenation
+
Adjacent string literals are automatically concatenated by the interpreter:
"con" "cat" "en" "at" "ion" #=> "concatenation"
@@ -209,12 +204,14 @@ Any combination of adjacent single-quote, double-quote, percent strings will
be concatenated as long as a percent-string is not last.
%q{a} 'b' "c" #=> "abc"
- "a" 'b' %q{c} #=> NameError: uninitialized constant q
+ "a" 'b' %q{c} #=> NoMethodError: undefined method 'q' for main
+
+=== Character Literal
There is also a character literal notation to represent single
character strings, which syntax is a question mark (<tt>?</tt>)
-followed by a single character or escape sequence that corresponds to
-a single codepoint in the script encoding:
+followed by a single character or escape sequence (except continuation line)
+that corresponds to a single codepoint in the script encoding:
?a #=> "a"
?abc #=> SyntaxError
@@ -228,10 +225,45 @@ a single codepoint in the script encoding:
?\C-\M-a #=> "\x81", same as above
?あ #=> "あ"
-See also:
+=== Escape Sequences
-* {%q: Non-Interpolable String Literals}[#label-25q-3A+Non-Interpolable+String+Literals]
-* {% and %Q: Interpolable String Literals}[#label-25+and+-25Q-3A+Interpolable+String+Literals]
+Some characters can be represented as escape sequences in
+double-quoted strings,
+character literals,
+here document literals (non-quoted, double-quoted, and with backticks),
+double-quoted symbols,
+double-quoted symbol keys in Hash literals,
+Regexp literals, and
+several percent literals (<tt>%</tt>, <tt>%Q</tt>, <tt>%W</tt>, <tt>%I</tt>, <tt>%r</tt>, <tt>%x</tt>).
+
+They allow escape sequences such as <tt>\n</tt> for
+newline, <tt>\t</tt> for tab, etc. The full list of supported escape
+sequences are as follows:
+
+ \a bell, ASCII 07h (BEL)
+ \b backspace, ASCII 08h (BS)
+ \t horizontal tab, ASCII 09h (TAB)
+ \n newline (line feed), ASCII 0Ah (LF)
+ \v vertical tab, ASCII 0Bh (VT)
+ \f form feed, ASCII 0Ch (FF)
+ \r carriage return, ASCII 0Dh (CR)
+ \e escape, ASCII 1Bh (ESC)
+ \s space, ASCII 20h (SPC)
+ \\ backslash, \
+ \nnn octal bit pattern, where nnn is 1-3 octal digits ([0-7])
+ \xnn hexadecimal bit pattern, where nn is 1-2 hexadecimal digits ([0-9a-fA-F])
+ \unnnn Unicode character, where nnnn is exactly 4 hexadecimal digits ([0-9a-fA-F])
+ \u{nnnn ...} Unicode character(s), where each nnnn is 1-6 hexadecimal digits ([0-9a-fA-F])
+ \cx or \C-x control character, where x is an ASCII printable character
+ \M-x meta character, where x is an ASCII printable character
+ \M-\C-x meta control character, where x is an ASCII printable character
+ \M-\cx same as above
+ \c\M-x same as above
+ \c? or \C-? delete, ASCII 7Fh (DEL)
+ \<newline> continuation line (empty string)
+
+The last one, <tt>\<newline></tt>, represents an empty string instead of a character.
+It is used to fold a line in a string.
=== Here Document Literals
@@ -283,9 +315,10 @@ its end is a multiple of eight. The amount to be removed is counted in terms
of the number of spaces. If the boundary appears in the middle of a tab, that
tab is not removed.
-A heredoc allows interpolation and escaped characters. You may disable
-interpolation and escaping by surrounding the opening identifier with single
-quotes:
+A heredoc allows interpolation and the escape sequences described in
+{Escape Sequences}[#label-Escape+Sequences].
+You may disable interpolation and the escaping by surrounding the opening
+identifier with single quotes:
expected_result = <<-'EXPECTED'
One plus one is #{1 + 1}
@@ -326,12 +359,15 @@ details on what symbols are and when ruby creates them internally.
You may reference a symbol using a colon: <tt>:my_symbol</tt>.
-You may also create symbols by interpolation:
+You may also create symbols by interpolation and escape sequences described in
+{Escape Sequences}[#label-Escape+Sequences] with double-quotes:
:"my_symbol1"
:"my_symbol#{1 + 1}"
+ :"foo\sbar"
-Like strings, a single-quote may be used to disable interpolation:
+Like strings, a single-quote may be used to disable interpolation and
+escape sequences:
:'my_symbol#{1 + 1}' #=> :"my_symbol\#{1 + 1}"
@@ -451,7 +487,12 @@ may use these paired delimiters:
* <tt>(</tt> and <tt>)</tt>.
* <tt>{</tt> and <tt>}</tt>.
* <tt><</tt> and <tt>></tt>.
-* Any other character, as both beginning and ending delimiters.
+* Non-alphanumeric ASCII character except above, as both beginning and ending delimiters.
+
+The delimiters can be escaped with a backslash.
+However, the first four pairs (brackets, parenthesis, braces, and
+angle brackets) are allowed without backslash as far as they are correctly
+paired.
These are demonstrated in the next section.
@@ -460,13 +501,20 @@ These are demonstrated in the next section.
You can write a non-interpolable string with <tt>%q</tt>.
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> # => "foo bar baz" # Using <>.
- %|foo bar baz| # => "foo bar baz" # Using two |.
- %:foo bar baz: # => "foo bar baz" # Using two :.
+ %q[foo bar baz] # => "foo bar baz" # Using [].
+ %q(foo bar baz) # => "foo bar baz" # Using ().
+ %q{foo bar baz} # => "foo bar baz" # Using {}.
+ %q<foo bar baz> # => "foo bar baz" # Using <>.
+ %q|foo bar baz| # => "foo bar baz" # Using two |.
+ %q:foo bar baz: # => "foo bar baz" # Using two :.
%q(1 + 1 is #{1 + 1}) # => "1 + 1 is \#{1 + 1}" # No interpolation.
+ %q[foo[bar]baz] # => "foo[bar]baz" # brackets can be nested.
+ %q(foo(bar)baz) # => "foo(bar)baz" # parenthesis can be nested.
+ %q{foo{bar}baz} # => "foo{bar}baz" # braces can be nested.
+ %q<foo<bar>baz> # => "foo<bar>baz" # angle brackets can be nested.
+
+This is similar to single-quoted string but only backslashes and
+the specified delimiters can be escaped with a backslash.
=== <tt>% and %Q</tt>: Interpolable String Literals
@@ -476,30 +524,63 @@ or with its alias <tt>%</tt>:
%[foo bar baz] # => "foo bar baz"
%(1 + 1 is #{1 + 1}) # => "1 + 1 is 2" # Interpolation.
+This is similar to double-quoted string.
+It allow escape sequences described in
+{Escape Sequences}[#label-Escape+Sequences].
+Other escaped characters (a backslash followed by a character) are
+interpreted as the character.
+
=== <tt>%w and %W</tt>: String-Array Literals
-You can write an array of strings with <tt>%w</tt> (non-interpolable)
-or <tt>%W</tt> (interpolable):
+You can write an array of strings as whitespace-separated words
+with <tt>%w</tt> (non-interpolable) or <tt>%W</tt> (interpolable):
%w[foo bar baz] # => ["foo", "bar", "baz"]
%w[1 % *] # => ["1", "%", "*"]
# Use backslash to embed spaces in the strings.
%w[foo\ bar baz\ bat] # => ["foo bar", "baz bat"]
+ %W[foo\ bar baz\ bat] # => ["foo bar", "baz bat"]
%w(#{1 + 1}) # => ["\#{1", "+", "1}"]
%W(#{1 + 1}) # => ["2"]
+ # The nested delimiters evaluated to a flat array of strings
+ # (not nested array).
+ %w[foo[bar baz]qux] # => ["foo[bar", "baz]qux"]
+
+The following characters are considered as white spaces to separate words:
+
+* space, ASCII 20h (SPC)
+* form feed, ASCII 0Ch (FF)
+* newline (line feed), ASCII 0Ah (LF)
+* carriage return, ASCII 0Dh (CR)
+* horizontal tab, ASCII 09h (TAB)
+* vertical tab, ASCII 0Bh (VT)
+
+The white space characters can be escaped with a backslash to make them
+part of a word.
+
+<tt>%W</tt> allow escape sequences described in
+{Escape Sequences}[#label-Escape+Sequences].
+However the continuation line <tt>\<newline></tt> is not usable because
+it is interpreted as the escaped newline described above.
+
=== <tt>%i and %I</tt>: Symbol-Array Literals
-You can write an array of symbols with <tt>%i</tt> (non-interpolable)
-or <tt>%I</tt> (interpolable):
+You can write an array of symbols as whitespace-separated words
+with <tt>%i</tt> (non-interpolable) or <tt>%I</tt> (interpolable):
%i[foo bar baz] # => [:foo, :bar, :baz]
%i[1 % *] # => [:"1", :%, :*]
# Use backslash to embed spaces in the symbols.
%i[foo\ bar baz\ bat] # => [:"foo bar", :"baz bat"]
+ %I[foo\ bar baz\ bat] # => [:"foo bar", :"baz bat"]
%i(#{1 + 1}) # => [:"\#{1", :+, :"1}"]
%I(#{1 + 1}) # => [:"2"]
+The white space characters and its escapes are interpreted as the same as
+string-array literals described in
+{%w and %W: String-Array Literals}[#label-25w+and+-25W-3A+String-Array+Literals].
+
=== <tt>%s</tt>: Symbol Literals
You can write a symbol with <tt>%s</tt>:
@@ -507,6 +588,10 @@ You can write a symbol with <tt>%s</tt>:
%s[foo] # => :foo
%s[foo bar] # => :"foo bar"
+This is non-interpolable.
+No interpolation allowed.
+Only backslashes and the specified delimiters can be escaped with a backslash.
+
=== <tt>%r</tt>: Regexp Literals
You can write a regular expression with <tt>%r</tt>;
@@ -531,4 +616,10 @@ See {Regexp modes}[rdoc-ref:Regexp@Modes] for details.
You can write and execute a shell command with <tt>%x</tt>:
- %x(echo 1) # => "1\n"
+ %x(echo 1) # => "1\n"
+ %x[echo #{1 + 2}] # => "3\n"
+ %x[echo \u0030] # => "0\n"
+
+This is interpolable.
+<tt>%x</tt> allow escape sequences described in
+{Escape Sequences}[#label-Escape+Sequences].
diff --git a/doc/syntax/methods.rdoc b/doc/syntax/methods.rdoc
index 8dafa6bb0c..14810a188f 100644
--- a/doc/syntax/methods.rdoc
+++ b/doc/syntax/methods.rdoc
@@ -100,6 +100,7 @@ operators.
<code>/</code> :: divide
<code>%</code> :: modulus division, String#%
<code>&</code> :: AND
+<code>|</code> :: OR
<code>^</code> :: XOR (exclusive OR)
<code>>></code> :: right-shift
<code><<</code> :: left-shift, append
diff --git a/doc/syntax/pattern_matching.rdoc b/doc/syntax/pattern_matching.rdoc
index 6a30380f46..06aae26d49 100644
--- a/doc/syntax/pattern_matching.rdoc
+++ b/doc/syntax/pattern_matching.rdoc
@@ -221,7 +221,7 @@ For hash patterns, even a simpler form exists: key-only specification (without a
end
#=> "matched: 1"
-Binding works for nested patterns as well:
+\Binding works for nested patterns as well:
case {name: 'John', friends: [{name: 'Jane'}, {name: 'Rajesh'}]}
in name:, friends: [{name: first_friend}, *]
@@ -247,17 +247,17 @@ The "rest" part of a pattern also can be bound to a variable:
else
"not matched"
end
- #=> "matched: 1, {:b=>2, :c=>3}"
+ #=> "matched: 1, {b: 2, c: 3}"
-Binding to variables currently does NOT work for alternative patterns joined with <code>|</code>:
+\Binding to variables currently does NOT work for alternative patterns joined with <code>|</code>:
case {a: 1, b: 2}
in {a: } | Array
+ # ^ SyntaxError (variable capture in alternative pattern)
"matched: #{a}"
else
"not matched"
end
- # SyntaxError (illegal variable in alternative pattern (a))
Variables that start with <code>_</code> are the only exclusions from this rule:
diff --git a/doc/syntax/refinements.rdoc b/doc/syntax/refinements.rdoc
index 17d5e67c21..4095977284 100644
--- a/doc/syntax/refinements.rdoc
+++ b/doc/syntax/refinements.rdoc
@@ -212,10 +212,7 @@ all refinements from the same module are active when a refined method
When looking up a method for an instance of class +C+ Ruby checks:
-* If refinements are active for +C+, in the reverse order they were activated:
- * The prepended modules from the refinement for +C+
- * The refinement for +C+
- * The included modules from the refinement for +C+
+* The refinements of +C+, in reverse order of activation
* The prepended modules of +C+
* +C+
* The included modules of +C+
diff --git a/doc/windows.md b/doc/windows.md
deleted file mode 100644
index 2020eec9cf..0000000000
--- a/doc/windows.md
+++ /dev/null
@@ -1,234 +0,0 @@
-# Windows
-
-Ruby supports a few native build platforms for Windows.
-
-* mswin: Build using Microsoft Visual C++ compiler with vcruntimeXXX.dll
-* mingw-msvcrt: Build using compiler for Mingw with msvcrtXX.dll
-* mingw-ucrt: Build using compiler for Mingw with Windows Universal CRT
-
-## Building Ruby using Mingw with UCRT
-
-The easiest build environment is just a standard [RubyInstaller-Devkit]
-installation and [git-for-windows]. You might like to use [VSCode] as an
-editor.
-
-### Build examples
-
-Ruby core development can be done either in Windows `cmd` like:
-
-```
-ridk enable ucrt64
-
-pacman -S --needed %MINGW_PACKAGE_PREFIX%-openssl %MINGW_PACKAGE_PREFIX%-libyaml %MINGW_PACKAGE_PREFIX%-libffi
-
-cd c:\
-mkdir work
-cd work
-git clone https://github.com/ruby/ruby
-
-cd c:\work\ruby
-sh autogen.sh
-sh configure -C --disable-install-doc
-make
-```
-
-or in MSYS2 `bash` like:
-
-```
-ridk enable ucrt64
-bash
-
-pacman -S --needed $MINGW_PACKAGE_PREFIX-openssl $MINGW_PACKAGE_PREFIX-libyaml $MINGW_PACKAGE_PREFIX-libffi
-
-cd /c/
-mkdir work
-cd work
-git clone https://github.com/ruby/ruby
-cd ruby
-
-./autogen.sh
-./configure -C --disable-install-doc
-make
-```
-
-[RubyInstaller-Devkit]: https://rubyinstaller.org/
-[git-for-windows]: https://gitforwindows.org/
-[VSCode]: https://code.visualstudio.com/
-
-## Building Ruby using Visual C++
-
-### Requirement
-
-1. Windows 10/Windows Server 2016 or later.
-
-2. Visual C++ 14.0 (2015) or later.
-
- **Note** if you want to build x64 version, use native compiler for
- x64.
-
-3. Please set environment variable `INCLUDE`, `LIB`, `PATH`
- to run required commands properly from the command line.
-
- **Note** building ruby requires following commands.
-
- * nmake
- * cl
- * ml
- * lib
- * dumpbin
-
-4. If you want to build from GIT source, following commands are required.
- * patch
- * sed
- * ruby 3.0 or later
-
- You can use [scoop](https://scoop.sh/) to install them like:
-
- ```
- scoop install git ruby sed patch
- ```
-
-5. You need to install required libraries using [vcpkg](https://vcpkg.io/) on
- directory of ruby repository like:
-
- ```
- vcpkg --triplet x64-windows install
- ```
-
-6. Enable Command Extension of your command line. It's the default behavior
- of `cmd.exe`. If you want to enable it explicitly, run `cmd.exe` with
- `/E:ON` option.
-
-### How to compile and install
-
-1. Execute `win32\configure.bat` on your build directory.
- You can specify the target platform as an argument.
- For example, run `configure --target=i686-mswin32`
- You can also specify the install directory.
- For example, run `configure --prefix=<install_directory>`
- Default of the install directory is `/usr` .
- The default _PLATFORM_ is `i386-mswin32_`_MSRTVERSION_ on 32-bit
- platforms, or `x64-mswin64_`_MSRTVERSION_ on x64 platforms.
- _MSRTVERSION_ is the 2- or 3-digits version of the Microsoft
- Runtime Library.
-
-2. Change _RUBY_INSTALL_NAME_ and _RUBY_SO_NAME_ in `Makefile`
- if you want to change the name of the executable files.
- And add _RUBYW_INSTALL_NAME_ to change the name of the
- executable without console window if also you want.
-
-3. You need specify vcpkg directory to use `--with-opt-dir`
- option like `win32\configure.bat --with-opt-dir=vcpkg_installed\x64-windows`
-
-4. Run `nmake up` if you are building from GIT source.
-
-5. Run `nmake`
-
-6. Run `nmake check`
-
-7. Run `nmake install`
-
-### Build examples
-
-* Build on the ruby source directory.
-
- ```
- ruby source directory: C:\ruby
- build directory: C:\ruby
- install directory: C:\usr\local
- ```
-
- ```
- C:
- cd \ruby
- win32\configure --prefix=/usr/local
- nmake
- nmake check
- nmake install
- ```
-
-* Build on the relative directory from the ruby source directory.
-
- ```
- ruby source directory: C:\ruby
- build directory: C:\ruby\mswin32
- install directory: C:\usr\local
- ```
-
- ```
- C:
- cd \ruby
- mkdir mswin32
- cd mswin32
- ..\win32\configure --prefix=/usr/local
- nmake
- nmake check
- nmake install
- ```
-
-* Build on the different drive.
-
- ```
- ruby source directory: C:\src\ruby
- build directory: D:\build\ruby
- install directory: C:\usr\local
- ```
-
- ```
- D:
- cd D:\build\ruby
- C:\src\ruby\win32\configure --prefix=/usr/local
- nmake
- nmake check
- nmake install DESTDIR=C:
- ```
-
-* Build x64 version (requires native x64 VC++ compiler)
-
- ```
- ruby source directory: C:\ruby
- build directory: C:\ruby
- install directory: C:\usr\local
- ```
-
- ```
- C:
- cd \ruby
- win32\configure --prefix=/usr/local --target=x64-mswin64
- nmake
- nmake check
- nmake install
- ```
-
-### Bugs
-
-You can **NOT** use a path name that contains any white space characters
-as the ruby source directory, this restriction comes from the behavior
-of `!INCLUDE` directives of `NMAKE`.
-
-You can build ruby in any directory including the source directory,
-except `win32` directory in the source directory.
-This is restriction originating in the path search method of `NMAKE`.
-
-## Icons
-
-Any icon files(`*.ico`) in the build directory, directories specified with
-_icondirs_ make variable and `win32` directory under the ruby
-source directory will be included in DLL or executable files, according
-to their base names.
- $(RUBY_INSTALL_NAME).ico or ruby.ico --> $(RUBY_INSTALL_NAME).exe
- $(RUBYW_INSTALL_NAME).ico or rubyw.ico --> $(RUBYW_INSTALL_NAME).exe
- the others --> $(RUBY_SO_NAME).dll
-
-Although no icons are distributed with the ruby source, you can use
-anything you like. You will be able to find many images by search engines.
-For example, followings are made from [Ruby logo kit]:
-
-* Small [favicon] in the official site
-
-* [vit-ruby.ico] or [icon itself]
-
-[Ruby logo kit]: https://cache.ruby-lang.org/pub/misc/logo/ruby-logo-kit.zip
-[favicon]: https://www.ruby-lang.org/favicon.ico
-[vit-ruby.ico]: http://ruby.morphball.net/vit-ruby-ico_en.html
-[icon itself]: http://ruby.morphball.net/icon/vit-ruby.ico
diff --git a/doc/yjit/yjit.md b/doc/yjit/yjit.md
deleted file mode 100644
index 8ea3409e48..0000000000
--- a/doc/yjit/yjit.md
+++ /dev/null
@@ -1,517 +0,0 @@
-<p align="center">
- <a href="https://yjit.org/" target="_blank" rel="noopener noreferrer">
- <img src="https://user-images.githubusercontent.com/224488/131155756-aa8fb528-a813-4dfd-99ac-8785c3d5eed7.png" width="400">
- </a>
-</p>
-
-YJIT - Yet Another Ruby JIT
-===========================
-
-YJIT is a lightweight, minimalistic Ruby JIT built inside CRuby.
-It lazily compiles code using a Basic Block Versioning (BBV) architecture.
-YJIT is currently supported for macOS, Linux and BSD on x86-64 and arm64/aarch64 CPUs.
-This project is open source and falls under the same license as CRuby.
-
-<p align="center"><b>
- If you're using YJIT in production, please
- <a href="mailto:maxime.chevalierboisvert@shopify.com">share your success stories with us!</a>
-</b></p>
-
-If you wish to learn more about the approach taken, here are some conference talks and publications:
-- RubyKaigi 2023 keynote: [Optimizing YJIT’s Performance, from Inception to Production](https://www.youtube.com/watch?v=X0JRhh8w_4I)
-- RubyKaigi 2023 keynote: [Fitting Rust YJIT into CRuby](https://www.youtube.com/watch?v=GI7vvAgP_Qs)
-- RubyKaigi 2022 keynote: [Stories from developing YJIT](https://www.youtube.com/watch?v=EMchdR9C8XM)
-- RubyKaigi 2022 talk: [Building a Lightweight IR and Backend for YJIT](https://www.youtube.com/watch?v=BbLGqTxTRp0)
-- RubyKaigi 2021 talk: [YJIT: Building a New JIT Compiler Inside CRuby](https://www.youtube.com/watch?v=PBVLf3yfMs8)
-- Blog post: [YJIT: Building a New JIT Compiler Inside CRuby](https://pointersgonewild.com/2021/06/02/yjit-building-a-new-jit-compiler-inside-cruby/)
-- MPLR 2023 paper: [Evaluating YJIT’s Performance in a Production Context: A Pragmatic Approach](https://dl.acm.org/doi/10.1145/3617651.3622982)
-- VMIL 2021 paper: [YJIT: A Basic Block Versioning JIT Compiler for CRuby](https://dl.acm.org/doi/10.1145/3486606.3486781)
-- MoreVMs 2021 talk: [YJIT: Building a New JIT Compiler Inside CRuby](https://www.youtube.com/watch?v=vucLAqv7qpc)
-- ECOOP 2016 talk: [Interprocedural Type Specialization of JavaScript Programs Without Type Analysis](https://www.youtube.com/watch?v=sRNBY7Ss97A)
-- 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 YJIT in your publications, please cite the MPLR 2023 paper:
-
-```
-@inproceedings{yjit_mplr_2023,
-author = {Chevalier-Boisvert, Maxime and Kokubun, Takashi and Gibbs, Noah and Wu, Si Xing (Alan) and Patterson, Aaron and Issroff, Jemma},
-title = {Evaluating YJIT’s Performance in a Production Context: A Pragmatic Approach},
-year = {2023},
-isbn = {9798400703805},
-publisher = {Association for Computing Machinery},
-address = {New York, NY, USA},
-url = {https://doi.org/10.1145/3617651.3622982},
-doi = {10.1145/3617651.3622982},
-booktitle = {Proceedings of the 20th ACM SIGPLAN International Conference on Managed Programming Languages and Runtimes},
-pages = {20–33},
-numpages = {14},
-keywords = {dynamically typed, optimization, just-in-time, virtual machine, ruby, compiler, bytecode},
-location = {Cascais, Portugal},
-series = {MPLR 2023}
-}
-```
-
-## Current Limitations
-
-YJIT may not be suitable for certain applications. It currently only supports macOS, Linux and BSD on x86-64 and arm64/aarch64 CPUs. YJIT will use more memory than the Ruby interpreter because the JIT compiler needs to generate machine code in memory and maintain additional state information.
-You can change how much executable memory is allocated using [YJIT's command-line options](#command-line-options).
-
-## Installation
-
-### Requirements
-
-You will need to install:
-- A C compiler such as GCC or Clang
-- GNU Make and Autoconf
-- The Rust compiler `rustc` and Cargo (if you want to build in dev/debug mode)
- - The Rust version must be [>= 1.58.0](../../yjit/Cargo.toml).
-
-To install the Rust build toolchain, we suggest following the [recommended installation method][rust-install]. Rust also provides first class [support][editor-tools] for many source code editors.
-
-[rust-install]: https://www.rust-lang.org/tools/install
-[editor-tools]: https://www.rust-lang.org/tools
-
-### Building YJIT
-
-Start by cloning the `ruby/ruby` repository:
-
-```sh
-git clone https://github.com/ruby/ruby yjit
-cd yjit
-```
-
-The YJIT `ruby` binary can be built with either GCC or Clang. It can be built either in dev (debug) mode or in release mode. For maximum performance, compile YJIT in release mode with GCC. More detailed build instructions are provided in the [Ruby README](https://github.com/ruby/ruby#how-to-build).
-
-```sh
-# Configure in release mode for maximum performance, build and install
-./autogen.sh
-./configure --enable-yjit --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc
-make -j && make install
-```
-
-or
-
-```sh
-# Configure in lower-performance dev (debug) mode for development, build and install
-./autogen.sh
-./configure --enable-yjit=dev --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc
-make -j && make install
-```
-
-Dev mode includes extended YJIT statistics, but can be slow. For only statistics you can configure in stats mode:
-
-```sh
-# Configure in extended-stats mode without slow runtime checks, build and install
-./autogen.sh
-./configure --enable-yjit=stats --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc
-make -j && make install
-```
-
-On macOS, you may need to specify where to find some libraries:
-
-```sh
-# Install dependencies
-brew install openssl libyaml
-
-# Configure in dev (debug) mode for development, build and install
-./autogen.sh
-./configure --enable-yjit=dev --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc --with-opt-dir="$(brew --prefix openssl):$(brew --prefix readline):$(brew --prefix libyaml)"
-make -j && make install
-```
-
-Typically configure will choose the default C compiler. To specify the C compiler, use
-
-```sh
-# Choosing a specific c compiler
-export CC=/path/to/my/chosen/c/compiler
-```
-
-before running `./configure`.
-
-You can test that YJIT works correctly by running:
-
-```sh
-# Quick tests found in /bootstraptest
-make btest
-
-# Complete set of tests
-make -j 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:
-
-```sh
-chruby ruby-yjit
-ruby myscript.rb
-```
-
-You can dump statistics about compilation and execution by running YJIT with the `--yjit-stats` command-line option:
-
-```sh
-./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:
-
-- `--yjit`: enable YJIT (disabled by default)
-- `--yjit-exec-mem-size=N`: size of the executable memory block to allocate, in MiB (default 48 MiB)
-- `--yjit-call-threshold=N`: number of calls after which YJIT begins to compile a function.
- It defaults to 30, and it's then increased to 120 when the number of ISEQs in the process reaches 40,000.
-- `--yjit-cold-threshold=N`: number of global calls after which an ISEQ is considered cold and not
- compiled, lower values mean less code is compiled (default 200K)
-- `--yjit-stats`: print statistics after the execution of a program (incurs a run-time cost)
-- `--yjit-stats=quiet`: gather statistics while running a program but don't print them. Stats are accessible through `RubyVM::YJIT.runtime_stats`. (incurs a run-time cost)
-- `--yjit-disable`: disable YJIT despite other `--yjit*` flags for lazily enabling it with `RubyVM::YJIT.enable`
-- `--yjit-code-gc`: enable code GC (disabled by default as of Ruby 3.3).
- It will cause all machine code to be discarded when the executable memory size limit is hit, meaning JIT compilation will then start over.
- This can allow you to use a lower executable memory size limit, but may cause a slight drop in performance when the limit is hit.
-- `--yjit-perf`: enable frame pointers and profiling with the `perf` tool
-- `--yjit-trace-exits`: produce a Marshal dump of backtraces from all exits. Automatically enables `--yjit-stats`
-- `--yjit-trace-exits=COUNTER`: produce a Marshal dump of backtraces from specified exits. Automatically enables `--yjit-stats`
-- `--yjit-trace-exits-sample-rate=N`: trace exit locations only every Nth occurrence. Automatically enables `--yjit-trace-exits`
-
-Note that there is also an environment variable `RUBY_YJIT_ENABLE` which can be used to enable YJIT.
-This can be useful for some deployment scripts where specifying an extra command-line option to Ruby is not practical.
-
-You can also enable YJIT at run-time using `RubyVM::YJIT.enable`. This can allow you to enable YJIT after your application is done
-booting, which makes it possible to avoid compiling any initialization code.
-
-You can verify that YJIT is enabled using `RubyVM::YJIT.enabled?` or by checking that `ruby --yjit -v` includes the string `+YJIT`:
-
-```sh
-ruby --yjit -v
-ruby 3.3.0dev (2023-01-31T15:11:10Z master 2a0bf269c9) +YJIT dev [x86_64-darwin22]
-
-ruby --yjit -e "p RubyVM::YJIT.enabled?"
-true
-
-ruby -e "RubyVM::YJIT.enable; p RubyVM::YJIT.enabled?"
-true
-```
-
-### Benchmarking
-
-We have collected a set of benchmarks and implemented a simple benchmarking harness in the [yjit-bench](https://github.com/Shopify/yjit-bench) repository. This benchmarking harness is designed to disable CPU frequency scaling, set process affinity and disable address space randomization so that the variance between benchmarking runs will be as small as possible.
-
-## Performance Tips for Production Deployments
-
-While YJIT options default to what we think would work well for most workloads,
-they might not necessarily be the best configuration for your application.
-This section covers tips on improving YJIT performance in case YJIT does not
-speed up your application in production.
-
-### Increasing --yjit-exec-mem-size
-
-When JIT code size (`RubyVM::YJIT.runtime_stats[:code_region_size]`) reaches this value,
-YJIT stops compiling new code. Increasing the executable memory size means more code
-can be optimized by YJIT, at the cost of more memory usage.
-
-If you start Ruby with `--yjit-stats`, e.g. using an environment variable `RUBYOPT=--yjit-stats`,
-`RubyVM::YJIT.runtime_stats[:ratio_in_yjit]` shows the ratio of YJIT-executed instructions in %.
-Ideally, `ratio_in_yjit` should be as large as 99%, and increasing `--yjit-exec-mem-size` often
-helps improving `ratio_in_yjit`.
-
-### Running workers as long as possible
-
-It's helpful to call the same code as many times as possible before a process restarts.
-If a process is killed too frequently, the time taken for compiling methods may outweigh
-the speedup obtained by compiling them.
-
-You should monitor the number of requests each process has served.
-If you're periodically killing worker processes, e.g. with `unicorn-worker-killer` or `puma_worker_killer`,
-you may want to reduce the killing frequency or increase the limit.
-
-## Reducing YJIT Memory Usage
-
-YJIT allocates memory for JIT code and metadata. Enabling YJIT generally results in more memory usage.
-This section goes over tips on minimizing YJIT memory usage in case it uses more than your capacity.
-
-### Decreasing --yjit-exec-mem-size
-
-The `--yjit-exec-mem-size` option specifies the JIT code size, but YJIT also uses memory for its metadata,
-which often consumes more memory than JIT code. Generally, YJIT adds memory overhead by roughly
-3-4x of `--yjit-exec-mem-size` in production as of Ruby 3.3. You should multiply that by the number
-of worker processes to estimate the worst case memory overhead.
-
-`--yjit-exec-mem-size=48` is the default since Ruby 3.3.1,
-but smaller values like 32 MiB might make sense for your application.
-While doing so, you may want to monitor `RubyVM::YJIT.runtime_stats[:ratio_in_yjit]` as explained above.
-
-### Enabling YJIT lazily
-
-If you enable YJIT by `--yjit` options or `RUBY_YJIT_ENABLE=1`, YJIT may compile code that is
-used only during the application boot. `RubyVM::YJIT.enable` allows you to enable YJIT from Ruby code,
-and you can call this after your application is initialized, e.g. on Unicorn's `after_fork` hook.
-If you use any YJIT options (`--yjit-*`), YJIT will start at boot by default, but `--yjit-disable`
-allows you to start Ruby with the YJIT-disabled mode while passing YJIT tuning options.
-
-## Code Optimization Tips
-
-This section contains tips on writing Ruby code that will run as fast as possible on YJIT. Some of this advice is based on current limitations of YJIT, while other advice is broadly applicable. It probably won't be practical to apply these tips everywhere in your codebase. You should ideally start by profiling your application using a tool such as [stackprof](https://github.com/tmm1/stackprof) so that you can determine which methods make up most of the execution time. You can then refactor the specific methods that make up the largest fractions of the execution time. We do not recommend modifying your entire codebase based on the current limitations of YJIT.
-
-- Avoid using `OpenStruct`
-- Avoid redefining basic integer operations (i.e. +, -, <, >, etc.)
-- Avoid redefining the meaning of `nil`, equality, etc.
-- Avoid allocating objects in the hot parts of your code
-- Minimize layers of indirection
- - Avoid writing wrapper classes if you can (e.g. a class that only wraps a Ruby hash)
- - Avoid methods that just call another method
-- Ruby method calls are costly. Avoid things such as methods that only return a value from a hash
-- Try to write code so that the same variables and method arguments always have the same type
-- Avoid using `TracePoint` as it can cause YJIT to deoptimize code
-- Avoid using `Binding` as it can cause YJIT to deoptimize code
-
-You can also use the `--yjit-stats` command-line option to see which bytecodes cause YJIT to exit, and refactor your code to avoid using these instructions in the hottest methods of your code.
-
-### Other Statistics
-
-If you run `ruby` with `--yjit-stats`, YJIT will track and return performance statistics in `RubyVM::YJIT.runtime_stats`.
-
-```rb
-$ RUBYOPT="--yjit-stats" irb
-irb(main):001:0> RubyVM::YJIT.runtime_stats
-=>
-{:inline_code_size=>340745,
- :outlined_code_size=>297664,
- :all_stats=>true,
- :yjit_insns_count=>1547816,
- :send_callsite_not_simple=>7267,
- :send_kw_splat=>7,
- :send_ivar_set_method=>72,
-...
-```
-
-Some of the counters include:
-
-* :yjit_insns_count - how many Ruby bytecode instructions have been executed
-* :binding_allocations - number of bindings allocated
-* :binding_set - number of variables set via a binding
-* :code_gc_count - number of garbage collections of compiled code since process start
-* :vm_insns_count - number of instructions executed by the Ruby interpreter
-* :compiled_iseq_count - number of bytecode sequences compiled
-* :inline_code_size - size in bytes of compiled YJIT blocks
-* :outline_code_size - size in bytes of YJIT error-handling compiled code
-* :side_exit_count - number of side exits taken at runtime
-* :total_exit_count - number of exits, including side exits, taken at runtime
-* :avg_len_in_yjit - avg. number of instructions in compiled blocks before exiting to interpreter
-
-Counters starting with "exit_" show reasons for YJIT code taking a side exit (return to the interpreter.)
-
-Performance counter names are not guaranteed to remain the same between Ruby versions. If you're curious what each counter means,
-it's usually best to search the source code for it &mdash; but it may change in a later Ruby version.
-
-The printed text after a `--yjit-stats` run includes other information that may be named differently than the information in `RubyVM::YJIT.runtime_stats`.
-
-## Contributing
-
-We welcome open source contributions. You should feel free to open new issues to report bugs or just to ask questions.
-Suggestions on how to make this readme file more helpful for new contributors are most welcome.
-
-Bug fixes and bug reports are very valuable to us. If you find a bug in YJIT, it's very possible be that nobody has reported it before,
-or that we don't have a good reproduction for it, so please open an issue and provide as much information as you can about your configuration and a description of how you encountered the problem. List the commands you used to run YJIT so that we can easily reproduce the issue on our end and investigate it. If you are able to produce a small program reproducing the error to help us track it down, that is very much appreciated as well.
-
-If you would like to contribute a large patch to YJIT, we suggest opening an issue or a discussion on the [Shopify/ruby repository](https://github.com/Shopify/ruby/issues) so that
-we can have an active discussion. A common problem is that sometimes people submit large pull requests to open source projects
-without prior communication, and we have to reject them because the work they implemented does not fit within the design of the
-project. We want to save you time and frustration, so please reach out so we can have a productive discussion as to how
-you can contribute patches we will want to merge into YJIT.
-
-### Source Code Organization
-
-The YJIT source code is divided between:
-- `yjit.c`: code YJIT uses to interface with the rest of CRuby
-- `yjit.h`: C definitions YJIT exposes to the rest of the CRuby
-- `yjit.rb`: `YJIT` Ruby module that is exposed to Ruby
-- `yjit/src/asm/*`: in-memory assembler we use to generate machine code
-- `yjit/src/codegen.rs`: logic for translating Ruby bytecode to machine code
-- `yjit/src/core.rb`: basic block versioning logic, core structure of YJIT
-- `yjit/src/stats.rs`: gathering of run-time statistics
-- `yjit/src/options.rs`: handling of command-line options
-- `yjit/src/cruby.rs`: C bindings manually exposed to the Rust codebase
-- `yjit/bindgen/src/main.rs`: C bindings exposed to the Rust codebase through bindgen
-
-The core of CRuby's interpreter logic is found in:
-- `insns.def`: defines Ruby's bytecode instructions (gets compiled into `vm.inc`)
-- `vm_insnshelper.c`: logic used by Ruby's bytecode instructions
-- `vm_exec.c`: Ruby interpreter loop
-
-### Generating C bindings with bindgen
-
-In order to expose C functions to the Rust codebase, you will need to generate C bindings:
-
-```sh
-CC=clang ./configure --enable-yjit=dev
-make -j yjit-bindgen
-```
-
-This uses the bindgen tools to generate/update `yjit/src/cruby_bindings.inc.rs` based on the
-bindings listed in `yjit/bindgen/src/main.rs`. Avoid manually editing this file
-as it could be automatically regenerated at a later time. If you need to manually add C bindings,
-add them to `yjit/cruby.rs` instead.
-
-### Coding & Debugging Protips
-
-There are multiple test suites:
-- `make btest` (see `/bootstraptest`)
-- `make test-all`
-- `make test-spec`
-- `make check` runs all of the above
-- `make yjit-smoke-test` runs quick checks to see that YJIT is working correctly
-
-The tests can be run in parallel like this:
-
-```sh
-make -j test-all RUN_OPTS="--yjit-call-threshold=1"
-```
-
-Or single-threaded like this, to more easily identify which specific test is failing:
-
-```sh
-make test-all TESTOPTS=--verbose RUN_OPTS="--yjit-call-threshold=1"
-```
-
-To debug a single test in `test-all`:
-
-```sh
-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`:
-
-```sh
-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`:
-
-```sh
-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:
-
-```sh
-echo "settings set target.x86-disassembly-flavor intel" >> ~/.lldbinit
-```
-
-## Running x86 YJIT on Apple's Rosetta
-
-For development purposes, it is possible to run x86 YJIT on an Apple M1 via Rosetta. You can find basic
-instructions below, but there are a few caveats listed further down.
-
-First, install Rosetta:
-
-```sh
-$ softwareupdate --install-rosetta
-```
-
-Now any command can be run with Rosetta via the `arch` command line tool.
-
-Then you can start your shell in an x86 environment:
-
-```sh
-$ arch -x86_64 zsh
-```
-
-You can double check your current architecture via the `arch` command:
-
-```sh
-$ arch -x86_64 zsh
-$ arch
-i386
-```
-
-You may need to set the default target for `rustc` to x86-64, e.g.
-
-```sh
-$ rustup default stable-x86_64-apple-darwin
-```
-
-While in your i386 shell, install Cargo and Homebrew, then hack away!
-
-### Rosetta Caveats
-
-1. You must install a version of Homebrew for each architecture
-2. Cargo will install in $HOME/.cargo by default, and I don't know a good way to change architectures after install
-
-If you use Fish shell you can [read this link](https://tenderlovemaking.com/2022/01/07/homebrew-rosetta-and-ruby.html) for information on making the dev environment easier.
-
-## Profiling with Linux perf
-
-`--yjit-perf` allows you to profile JIT-ed methods along with other native functions using Linux perf.
-When you run Ruby with `perf record`, perf looks up `/tmp/perf-{pid}.map` to resolve symbols in JIT code,
-and this option lets YJIT write method symbols into that file as well as enabling frame pointers.
-
-### Call graph
-
-Here's an example way to use this option with [Firefox Profiler](https://profiler.firefox.com)
-(See also: [Profiling with Linux perf](https://profiler.firefox.com/docs/#/./guide-perf-profiling)):
-
-```bash
-# Compile the interpreter with frame pointers enabled
-./configure --enable-yjit --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc cflags=-fno-omit-frame-pointer
-make -j && make install
-
-# [Optional] Allow running perf without sudo
-echo 0 | sudo tee /proc/sys/kernel/kptr_restrict
-echo -1 | sudo tee /proc/sys/kernel/perf_event_paranoid
-
-# Profile Ruby with --yjit-perf
-cd ../yjit-bench
-PERF="record --call-graph fp" ruby --yjit-perf -Iharness-perf benchmarks/liquid-render/benchmark.rb
-
-# View results on Firefox Profiler https://profiler.firefox.com.
-# Create /tmp/test.perf as below and upload it using "Load a profile from file".
-perf script --fields +pid > /tmp/test.perf
-```
-
-### YJIT codegen
-
-You can also profile the number of cycles consumed by code generated by each YJIT function.
-
-```bash
-# Install perf
-apt-get install linux-tools-common linux-tools-generic linux-tools-`uname -r`
-
-# [Optional] Allow running perf without sudo
-echo 0 | sudo tee /proc/sys/kernel/kptr_restrict
-echo -1 | sudo tee /proc/sys/kernel/perf_event_paranoid
-
-# Profile Ruby with --yjit-perf=codegen
-cd ../yjit-bench
-PERF=record ruby --yjit-perf=codegen -Iharness-perf benchmarks/lobsters/benchmark.rb
-
-# Aggregate results
-perf script > /tmp/perf.txt
-../ruby/misc/yjit_perf.py /tmp/perf.txt
-```
-
-#### Building perf with Python support
-
-The above instructions work fine for most people, but you could also use
-a handy `perf script -s` interface if you build perf from source.
-
-```bash
-# Build perf from source for Python support
-sudo apt-get install libpython3-dev python3-pip flex libtraceevent-dev \
- libelf-dev libunwind-dev libaudit-dev libslang2-dev libdw-dev
-git clone --depth=1 https://github.com/torvalds/linux
-cd linux/tools/perf
-make
-make install
-
-# Aggregate results
-perf script -s ../ruby/misc/yjit_perf.py
-```
diff --git a/doc/yjit/yjit_hacking.md b/doc/yjit/yjit_hacking.md
deleted file mode 100644
index 4c4d742b73..0000000000
--- a/doc/yjit/yjit_hacking.md
+++ /dev/null
@@ -1,75 +0,0 @@
-# YJIT Hacking
-
-## Code Generation and Assembly Language
-
-YJIT’s basic purpose is to take ISEQs and generate machine code.
-
-Documentation on each Ruby bytecode can be found in insns.def.
-
-YJIT uses those bytecodes as the “Basic Blocks” in Lazy Basic Block Versioning (LBBV.) For more deep details of LBBV, see yjit.md in this directory.
-
-Current YJIT has a simple assembler as a backend. Each method that generates code does it by emitting machine code:
-
-```
-# Excerpt of yjit_gen_exit() from yjit_codegen.c, Sept 2021
-// Generate an exit to return to the interpreter
-static uint32_t
-yjit_gen_exit(VALUE *exit_pc, ctx_t *ctx, codeblock_t *cb)
-{
- const uint32_t code_pos = cb->write_pos;
-
- ADD_COMMENT(cb, "exit to interpreter");
-
- // Generate the code to exit to the interpreters
- // Write the adjusted SP back into the CFP
- if (ctx->sp_offset != 0) {
- x86opnd_t stack_pointer = ctx_sp_opnd(ctx, 0);
- lea(cb, REG_SP, stack_pointer);
- mov(cb, member_opnd(REG_CFP, rb_control_frame_t, sp), REG_SP);
- }
-
- // Update CFP->PC
- mov(cb, RAX, const_ptr_opnd(exit_pc));
- mov(cb, member_opnd(REG_CFP, rb_control_frame_t, pc), RAX);
-```
-
-Later there will be a more complex backend.
-
-## Code Generation vs Code Execution
-
-When you see lea() call above (“load effective address,”) it’s not running the LEA x86 instruction. It’s generating an LEA instruction to the codeblock pointer in the first argument. It will execute that instruction later, when the codeblock gets executed.
-
-This is subtle because YJIT will often wait to compile the method until you’re about to run it -- that’s when it knows the most about what types of arguments the method will receive. So it’s a compile-time instruction, but often it will defer compile-time until just barely before runtime.
-
-The ctx structure tracks what is known at compile time about the arguments being passed into the Ruby bytecode. Often YJIT will “peek” at an expected type before it generates machine code.
-
-## Inlined and Outlined Code
-
-When YJIT is generating code, it needs a code pointer. In many cases it needs two, usually called “cb” (codeblock) and “ocb” (out-of-line codeblock.)
-
-cb is for “inlined” normal code and ocb is for “outline” code such as exits. Inlined code is normal generated code for Ruby operations, while outlined code is for unusual and error conditions, such as encountering an unexpected parameter type and exiting to the interpreter.
-
-The purpose of the outlined code block is to keep things we believe are going to be infrequent somewhere else. That way we can keep the code in the inline block more linear and compact. Linear code, with as few branches as possible, is more easily predicted by the CPU. An exception or unsupported operation will cause YJIT to generate outlined code to handle it.
-
-If you search for ocb in yjit_codegen.c, you can see some places where out-of-line code is generated.
-
-YJIT statistics are only gathered when RUBY_DEBUG or YJIT_STATS is true. In some cases the code to increment YJIT statistics will be generated out-of-line, especially if those statistics are gathered when a side exit happens.
-
-## Statistics and Comments
-
-When RUBY_DEBUG is defined to a true value, YJIT will emit comments into the generated machine code. This can make disassemblies a lot more readable. When RUBY_DEBUG or YJIT_STATS is defined and stats are active (--yjit-stats or export YJIT_STATS=1), code will be generated to collect statistics during the run, and a report will be printed when the process exits.
-
-## Entering and Exiting the Interpreter
-
-YJIT won’t generate machine code for an ISEQ until it’s been run a certain number of times (10 by default.) Then, the next time the interpreter would call that ISEQ, it will call the generated machine code version instead. If YJIT hits an unexpected or unsupported operation, it will return to the normal interpreter.
-
-If YJIT returns to the interpreter, the behaviour will be correct but slower. YJIT only optimises part of some operations - for instance, YJIT will not optimise a BMETHOD call yet.
-
-When the interpreter calls to a YJIT-optimised method again, control will return to YJIT’s generated machine code. The more time that’s spent in YJIT-generated code (“ratio in YJIT,”) the more CPU time YJIT can save with its optimisations.
-
-## Side Exits
-
-When YJIT has compiled an ISEQ and is running it later, sometimes it will hit an unexpected condition. It might see a parameter of a different type than before, or square-brackets might be used on a hash when they were first used on an array. In those cases, the generated code will contain a call to return to the interpreter at runtime, called a “side exit.”
-
-Side exits are generated as out-of-line code.
-
diff --git a/enc/Makefile.in b/enc/Makefile.in
index ce93fdd22d..2a3c45169f 100644
--- a/enc/Makefile.in
+++ b/enc/Makefile.in
@@ -24,13 +24,14 @@ OBJEXT = @OBJEXT@
LIBEXT = @LIBEXT@
EXEEXT = @EXEEXT@
TIMESTAMPDIR = $(EXTOUT)/.timestamp
-ENC_TRANS_D = $(TIMESTAMPDIR)/.enc-trans.time
-ENC_TRANS_SO_D = $(TIMESTAMPDIR)/.enc-trans.so.time
+ENC_TRANS_D = $(TIMESTAMPDIR)/enc-trans.time
+ENC_TRANS_SO_D = $(TIMESTAMPDIR)/enc-trans-$(arch).time
BUILTIN_ENCS = enc/ascii.c enc/us_ascii.c\
enc/unicode.c enc/utf_8.c
BUILTIN_TRANSES = enc/trans/newline.trans
+BUILTIN_TRANS_CSRCS = $(BUILTIN_TRANSES:.trans=.c)
RUBY_SO_NAME = @RUBY_SO_NAME@
LIBRUBY = @LIBRUBY@
diff --git a/enc/ascii.c b/enc/ascii.c
index ae7db97f25..4ba93f4feb 100644
--- a/enc/ascii.c
+++ b/enc/ascii.c
@@ -54,7 +54,11 @@ OnigEncodingDefine(ascii, ASCII) = {
onigenc_not_support_get_ctype_code_range,
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
onigenc_single_byte_ascii_only_case_map,
+#else
+ NULL,
+#endif
ENCINDEX_ASCII_8BIT,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/big5.c b/enc/big5.c
index ab4fb69819..e141ebdbe3 100644
--- a/enc/big5.c
+++ b/enc/big5.c
@@ -300,7 +300,11 @@ OnigEncodingDefine(big5, BIG5) = {
onigenc_not_support_get_ctype_code_range,
big5_left_adjust_char_head,
big5_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
onigenc_ascii_only_case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
@@ -335,7 +339,11 @@ OnigEncodingDefine(big5_hkscs, BIG5_HKSCS) = {
onigenc_not_support_get_ctype_code_range,
big5_left_adjust_char_head,
big5_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
onigenc_ascii_only_case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
@@ -370,7 +378,11 @@ OnigEncodingDefine(big5_uao, BIG5_UAO) = {
onigenc_not_support_get_ctype_code_range,
big5_left_adjust_char_head,
big5_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
onigenc_ascii_only_case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/cp949.c b/enc/cp949.c
index 1600d0cd5b..77e961a7cd 100644
--- a/enc/cp949.c
+++ b/enc/cp949.c
@@ -211,7 +211,11 @@ OnigEncodingDefine(cp949, CP949) = {
onigenc_not_support_get_ctype_code_range,
cp949_left_adjust_char_head,
cp949_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
onigenc_ascii_only_case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/depend b/enc/depend
index 2918a90a05..4bf97dc880 100644
--- a/enc/depend
+++ b/enc/depend
@@ -157,15 +157,15 @@ clean:
% end
% 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)$(RM) enc/trans/newline.c enc/jis/props.h
+ -$(Q)$(RMDIR) enc/trnas enc/unicode<%=ignore_error%>
% end
% workdirs.reverse_each do|d|
-$(Q)$(RMDIR) <%=pathrep[d]%><%=ignore_error%>
% end
clean-srcs:
- $(Q)$(RM) <%=pathrep['$(TRANSCSRCS)']%>
+ $(Q)$(RM) <%=pathrep['$(TRANSCSRCS)']%> <%=pathrep['$(BUILTIN_TRANS_CSRCS)']%>
-$(Q)$(RMDIR) <%=pathrep['enc/trans']%><%=ignore_error%>
$(Q)$(RM) enc/unicode/*/casefold.h enc/unicode/*/name2ctype.h
$(Q)$(RM) enc/jis/props.h
@@ -317,6 +317,7 @@ enc/ascii.$(OBJEXT): internal/intern/re.h
enc/ascii.$(OBJEXT): internal/intern/ruby.h
enc/ascii.$(OBJEXT): internal/intern/select.h
enc/ascii.$(OBJEXT): internal/intern/select/largesize.h
+enc/ascii.$(OBJEXT): internal/intern/set.h
enc/ascii.$(OBJEXT): internal/intern/signal.h
enc/ascii.$(OBJEXT): internal/intern/sprintf.h
enc/ascii.$(OBJEXT): internal/intern/string.h
@@ -479,6 +480,7 @@ enc/big5.$(OBJEXT): internal/intern/re.h
enc/big5.$(OBJEXT): internal/intern/ruby.h
enc/big5.$(OBJEXT): internal/intern/select.h
enc/big5.$(OBJEXT): internal/intern/select/largesize.h
+enc/big5.$(OBJEXT): internal/intern/set.h
enc/big5.$(OBJEXT): internal/intern/signal.h
enc/big5.$(OBJEXT): internal/intern/sprintf.h
enc/big5.$(OBJEXT): internal/intern/string.h
@@ -651,6 +653,7 @@ enc/cesu_8.$(OBJEXT): internal/intern/re.h
enc/cesu_8.$(OBJEXT): internal/intern/ruby.h
enc/cesu_8.$(OBJEXT): internal/intern/select.h
enc/cesu_8.$(OBJEXT): internal/intern/select/largesize.h
+enc/cesu_8.$(OBJEXT): internal/intern/set.h
enc/cesu_8.$(OBJEXT): internal/intern/signal.h
enc/cesu_8.$(OBJEXT): internal/intern/sprintf.h
enc/cesu_8.$(OBJEXT): internal/intern/string.h
@@ -813,6 +816,7 @@ enc/cp949.$(OBJEXT): internal/intern/re.h
enc/cp949.$(OBJEXT): internal/intern/ruby.h
enc/cp949.$(OBJEXT): internal/intern/select.h
enc/cp949.$(OBJEXT): internal/intern/select/largesize.h
+enc/cp949.$(OBJEXT): internal/intern/set.h
enc/cp949.$(OBJEXT): internal/intern/signal.h
enc/cp949.$(OBJEXT): internal/intern/sprintf.h
enc/cp949.$(OBJEXT): internal/intern/string.h
@@ -974,6 +978,7 @@ enc/emacs_mule.$(OBJEXT): internal/intern/re.h
enc/emacs_mule.$(OBJEXT): internal/intern/ruby.h
enc/emacs_mule.$(OBJEXT): internal/intern/select.h
enc/emacs_mule.$(OBJEXT): internal/intern/select/largesize.h
+enc/emacs_mule.$(OBJEXT): internal/intern/set.h
enc/emacs_mule.$(OBJEXT): internal/intern/signal.h
enc/emacs_mule.$(OBJEXT): internal/intern/sprintf.h
enc/emacs_mule.$(OBJEXT): internal/intern/string.h
@@ -1145,6 +1150,7 @@ enc/encdb.$(OBJEXT): internal/intern/re.h
enc/encdb.$(OBJEXT): internal/intern/ruby.h
enc/encdb.$(OBJEXT): internal/intern/select.h
enc/encdb.$(OBJEXT): internal/intern/select/largesize.h
+enc/encdb.$(OBJEXT): internal/intern/set.h
enc/encdb.$(OBJEXT): internal/intern/signal.h
enc/encdb.$(OBJEXT): internal/intern/sprintf.h
enc/encdb.$(OBJEXT): internal/intern/string.h
@@ -1309,6 +1315,7 @@ enc/euc_jp.$(OBJEXT): internal/intern/re.h
enc/euc_jp.$(OBJEXT): internal/intern/ruby.h
enc/euc_jp.$(OBJEXT): internal/intern/select.h
enc/euc_jp.$(OBJEXT): internal/intern/select/largesize.h
+enc/euc_jp.$(OBJEXT): internal/intern/set.h
enc/euc_jp.$(OBJEXT): internal/intern/signal.h
enc/euc_jp.$(OBJEXT): internal/intern/sprintf.h
enc/euc_jp.$(OBJEXT): internal/intern/string.h
@@ -1470,6 +1477,7 @@ enc/euc_kr.$(OBJEXT): internal/intern/re.h
enc/euc_kr.$(OBJEXT): internal/intern/ruby.h
enc/euc_kr.$(OBJEXT): internal/intern/select.h
enc/euc_kr.$(OBJEXT): internal/intern/select/largesize.h
+enc/euc_kr.$(OBJEXT): internal/intern/set.h
enc/euc_kr.$(OBJEXT): internal/intern/signal.h
enc/euc_kr.$(OBJEXT): internal/intern/sprintf.h
enc/euc_kr.$(OBJEXT): internal/intern/string.h
@@ -1631,6 +1639,7 @@ enc/euc_tw.$(OBJEXT): internal/intern/re.h
enc/euc_tw.$(OBJEXT): internal/intern/ruby.h
enc/euc_tw.$(OBJEXT): internal/intern/select.h
enc/euc_tw.$(OBJEXT): internal/intern/select/largesize.h
+enc/euc_tw.$(OBJEXT): internal/intern/set.h
enc/euc_tw.$(OBJEXT): internal/intern/signal.h
enc/euc_tw.$(OBJEXT): internal/intern/sprintf.h
enc/euc_tw.$(OBJEXT): internal/intern/string.h
@@ -1792,6 +1801,7 @@ enc/gb18030.$(OBJEXT): internal/intern/re.h
enc/gb18030.$(OBJEXT): internal/intern/ruby.h
enc/gb18030.$(OBJEXT): internal/intern/select.h
enc/gb18030.$(OBJEXT): internal/intern/select/largesize.h
+enc/gb18030.$(OBJEXT): internal/intern/set.h
enc/gb18030.$(OBJEXT): internal/intern/signal.h
enc/gb18030.$(OBJEXT): internal/intern/sprintf.h
enc/gb18030.$(OBJEXT): internal/intern/string.h
@@ -1953,6 +1963,7 @@ enc/gb2312.$(OBJEXT): internal/intern/re.h
enc/gb2312.$(OBJEXT): internal/intern/ruby.h
enc/gb2312.$(OBJEXT): internal/intern/select.h
enc/gb2312.$(OBJEXT): internal/intern/select/largesize.h
+enc/gb2312.$(OBJEXT): internal/intern/set.h
enc/gb2312.$(OBJEXT): internal/intern/signal.h
enc/gb2312.$(OBJEXT): internal/intern/sprintf.h
enc/gb2312.$(OBJEXT): internal/intern/string.h
@@ -2114,6 +2125,7 @@ enc/gbk.$(OBJEXT): internal/intern/re.h
enc/gbk.$(OBJEXT): internal/intern/ruby.h
enc/gbk.$(OBJEXT): internal/intern/select.h
enc/gbk.$(OBJEXT): internal/intern/select/largesize.h
+enc/gbk.$(OBJEXT): internal/intern/set.h
enc/gbk.$(OBJEXT): internal/intern/signal.h
enc/gbk.$(OBJEXT): internal/intern/sprintf.h
enc/gbk.$(OBJEXT): internal/intern/string.h
@@ -2276,6 +2288,7 @@ enc/iso_8859_1.$(OBJEXT): internal/intern/re.h
enc/iso_8859_1.$(OBJEXT): internal/intern/ruby.h
enc/iso_8859_1.$(OBJEXT): internal/intern/select.h
enc/iso_8859_1.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_1.$(OBJEXT): internal/intern/set.h
enc/iso_8859_1.$(OBJEXT): internal/intern/signal.h
enc/iso_8859_1.$(OBJEXT): internal/intern/sprintf.h
enc/iso_8859_1.$(OBJEXT): internal/intern/string.h
@@ -2438,6 +2451,7 @@ enc/iso_8859_10.$(OBJEXT): internal/intern/re.h
enc/iso_8859_10.$(OBJEXT): internal/intern/ruby.h
enc/iso_8859_10.$(OBJEXT): internal/intern/select.h
enc/iso_8859_10.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_10.$(OBJEXT): internal/intern/set.h
enc/iso_8859_10.$(OBJEXT): internal/intern/signal.h
enc/iso_8859_10.$(OBJEXT): internal/intern/sprintf.h
enc/iso_8859_10.$(OBJEXT): internal/intern/string.h
@@ -2599,6 +2613,7 @@ enc/iso_8859_11.$(OBJEXT): internal/intern/re.h
enc/iso_8859_11.$(OBJEXT): internal/intern/ruby.h
enc/iso_8859_11.$(OBJEXT): internal/intern/select.h
enc/iso_8859_11.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_11.$(OBJEXT): internal/intern/set.h
enc/iso_8859_11.$(OBJEXT): internal/intern/signal.h
enc/iso_8859_11.$(OBJEXT): internal/intern/sprintf.h
enc/iso_8859_11.$(OBJEXT): internal/intern/string.h
@@ -2761,6 +2776,7 @@ enc/iso_8859_13.$(OBJEXT): internal/intern/re.h
enc/iso_8859_13.$(OBJEXT): internal/intern/ruby.h
enc/iso_8859_13.$(OBJEXT): internal/intern/select.h
enc/iso_8859_13.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_13.$(OBJEXT): internal/intern/set.h
enc/iso_8859_13.$(OBJEXT): internal/intern/signal.h
enc/iso_8859_13.$(OBJEXT): internal/intern/sprintf.h
enc/iso_8859_13.$(OBJEXT): internal/intern/string.h
@@ -2923,6 +2939,7 @@ enc/iso_8859_14.$(OBJEXT): internal/intern/re.h
enc/iso_8859_14.$(OBJEXT): internal/intern/ruby.h
enc/iso_8859_14.$(OBJEXT): internal/intern/select.h
enc/iso_8859_14.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_14.$(OBJEXT): internal/intern/set.h
enc/iso_8859_14.$(OBJEXT): internal/intern/signal.h
enc/iso_8859_14.$(OBJEXT): internal/intern/sprintf.h
enc/iso_8859_14.$(OBJEXT): internal/intern/string.h
@@ -3085,6 +3102,7 @@ enc/iso_8859_15.$(OBJEXT): internal/intern/re.h
enc/iso_8859_15.$(OBJEXT): internal/intern/ruby.h
enc/iso_8859_15.$(OBJEXT): internal/intern/select.h
enc/iso_8859_15.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_15.$(OBJEXT): internal/intern/set.h
enc/iso_8859_15.$(OBJEXT): internal/intern/signal.h
enc/iso_8859_15.$(OBJEXT): internal/intern/sprintf.h
enc/iso_8859_15.$(OBJEXT): internal/intern/string.h
@@ -3247,6 +3265,7 @@ enc/iso_8859_16.$(OBJEXT): internal/intern/re.h
enc/iso_8859_16.$(OBJEXT): internal/intern/ruby.h
enc/iso_8859_16.$(OBJEXT): internal/intern/select.h
enc/iso_8859_16.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_16.$(OBJEXT): internal/intern/set.h
enc/iso_8859_16.$(OBJEXT): internal/intern/signal.h
enc/iso_8859_16.$(OBJEXT): internal/intern/sprintf.h
enc/iso_8859_16.$(OBJEXT): internal/intern/string.h
@@ -3409,6 +3428,7 @@ enc/iso_8859_2.$(OBJEXT): internal/intern/re.h
enc/iso_8859_2.$(OBJEXT): internal/intern/ruby.h
enc/iso_8859_2.$(OBJEXT): internal/intern/select.h
enc/iso_8859_2.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_2.$(OBJEXT): internal/intern/set.h
enc/iso_8859_2.$(OBJEXT): internal/intern/signal.h
enc/iso_8859_2.$(OBJEXT): internal/intern/sprintf.h
enc/iso_8859_2.$(OBJEXT): internal/intern/string.h
@@ -3571,6 +3591,7 @@ enc/iso_8859_3.$(OBJEXT): internal/intern/re.h
enc/iso_8859_3.$(OBJEXT): internal/intern/ruby.h
enc/iso_8859_3.$(OBJEXT): internal/intern/select.h
enc/iso_8859_3.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_3.$(OBJEXT): internal/intern/set.h
enc/iso_8859_3.$(OBJEXT): internal/intern/signal.h
enc/iso_8859_3.$(OBJEXT): internal/intern/sprintf.h
enc/iso_8859_3.$(OBJEXT): internal/intern/string.h
@@ -3733,6 +3754,7 @@ enc/iso_8859_4.$(OBJEXT): internal/intern/re.h
enc/iso_8859_4.$(OBJEXT): internal/intern/ruby.h
enc/iso_8859_4.$(OBJEXT): internal/intern/select.h
enc/iso_8859_4.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_4.$(OBJEXT): internal/intern/set.h
enc/iso_8859_4.$(OBJEXT): internal/intern/signal.h
enc/iso_8859_4.$(OBJEXT): internal/intern/sprintf.h
enc/iso_8859_4.$(OBJEXT): internal/intern/string.h
@@ -3894,6 +3916,7 @@ enc/iso_8859_5.$(OBJEXT): internal/intern/re.h
enc/iso_8859_5.$(OBJEXT): internal/intern/ruby.h
enc/iso_8859_5.$(OBJEXT): internal/intern/select.h
enc/iso_8859_5.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_5.$(OBJEXT): internal/intern/set.h
enc/iso_8859_5.$(OBJEXT): internal/intern/signal.h
enc/iso_8859_5.$(OBJEXT): internal/intern/sprintf.h
enc/iso_8859_5.$(OBJEXT): internal/intern/string.h
@@ -4055,6 +4078,7 @@ enc/iso_8859_6.$(OBJEXT): internal/intern/re.h
enc/iso_8859_6.$(OBJEXT): internal/intern/ruby.h
enc/iso_8859_6.$(OBJEXT): internal/intern/select.h
enc/iso_8859_6.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_6.$(OBJEXT): internal/intern/set.h
enc/iso_8859_6.$(OBJEXT): internal/intern/signal.h
enc/iso_8859_6.$(OBJEXT): internal/intern/sprintf.h
enc/iso_8859_6.$(OBJEXT): internal/intern/string.h
@@ -4216,6 +4240,7 @@ enc/iso_8859_7.$(OBJEXT): internal/intern/re.h
enc/iso_8859_7.$(OBJEXT): internal/intern/ruby.h
enc/iso_8859_7.$(OBJEXT): internal/intern/select.h
enc/iso_8859_7.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_7.$(OBJEXT): internal/intern/set.h
enc/iso_8859_7.$(OBJEXT): internal/intern/signal.h
enc/iso_8859_7.$(OBJEXT): internal/intern/sprintf.h
enc/iso_8859_7.$(OBJEXT): internal/intern/string.h
@@ -4377,6 +4402,7 @@ enc/iso_8859_8.$(OBJEXT): internal/intern/re.h
enc/iso_8859_8.$(OBJEXT): internal/intern/ruby.h
enc/iso_8859_8.$(OBJEXT): internal/intern/select.h
enc/iso_8859_8.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_8.$(OBJEXT): internal/intern/set.h
enc/iso_8859_8.$(OBJEXT): internal/intern/signal.h
enc/iso_8859_8.$(OBJEXT): internal/intern/sprintf.h
enc/iso_8859_8.$(OBJEXT): internal/intern/string.h
@@ -4539,6 +4565,7 @@ enc/iso_8859_9.$(OBJEXT): internal/intern/re.h
enc/iso_8859_9.$(OBJEXT): internal/intern/ruby.h
enc/iso_8859_9.$(OBJEXT): internal/intern/select.h
enc/iso_8859_9.$(OBJEXT): internal/intern/select/largesize.h
+enc/iso_8859_9.$(OBJEXT): internal/intern/set.h
enc/iso_8859_9.$(OBJEXT): internal/intern/signal.h
enc/iso_8859_9.$(OBJEXT): internal/intern/sprintf.h
enc/iso_8859_9.$(OBJEXT): internal/intern/string.h
@@ -4700,6 +4727,7 @@ enc/koi8_r.$(OBJEXT): internal/intern/re.h
enc/koi8_r.$(OBJEXT): internal/intern/ruby.h
enc/koi8_r.$(OBJEXT): internal/intern/select.h
enc/koi8_r.$(OBJEXT): internal/intern/select/largesize.h
+enc/koi8_r.$(OBJEXT): internal/intern/set.h
enc/koi8_r.$(OBJEXT): internal/intern/signal.h
enc/koi8_r.$(OBJEXT): internal/intern/sprintf.h
enc/koi8_r.$(OBJEXT): internal/intern/string.h
@@ -4861,6 +4889,7 @@ enc/koi8_u.$(OBJEXT): internal/intern/re.h
enc/koi8_u.$(OBJEXT): internal/intern/ruby.h
enc/koi8_u.$(OBJEXT): internal/intern/select.h
enc/koi8_u.$(OBJEXT): internal/intern/select/largesize.h
+enc/koi8_u.$(OBJEXT): internal/intern/set.h
enc/koi8_u.$(OBJEXT): internal/intern/signal.h
enc/koi8_u.$(OBJEXT): internal/intern/sprintf.h
enc/koi8_u.$(OBJEXT): internal/intern/string.h
@@ -5025,6 +5054,7 @@ enc/shift_jis.$(OBJEXT): internal/intern/re.h
enc/shift_jis.$(OBJEXT): internal/intern/ruby.h
enc/shift_jis.$(OBJEXT): internal/intern/select.h
enc/shift_jis.$(OBJEXT): internal/intern/select/largesize.h
+enc/shift_jis.$(OBJEXT): internal/intern/set.h
enc/shift_jis.$(OBJEXT): internal/intern/signal.h
enc/shift_jis.$(OBJEXT): internal/intern/sprintf.h
enc/shift_jis.$(OBJEXT): internal/intern/string.h
@@ -5185,6 +5215,7 @@ enc/trans/big5.$(OBJEXT): internal/intern/re.h
enc/trans/big5.$(OBJEXT): internal/intern/ruby.h
enc/trans/big5.$(OBJEXT): internal/intern/select.h
enc/trans/big5.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/big5.$(OBJEXT): internal/intern/set.h
enc/trans/big5.$(OBJEXT): internal/intern/signal.h
enc/trans/big5.$(OBJEXT): internal/intern/sprintf.h
enc/trans/big5.$(OBJEXT): internal/intern/string.h
@@ -5344,6 +5375,7 @@ enc/trans/cesu_8.$(OBJEXT): internal/intern/re.h
enc/trans/cesu_8.$(OBJEXT): internal/intern/ruby.h
enc/trans/cesu_8.$(OBJEXT): internal/intern/select.h
enc/trans/cesu_8.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/cesu_8.$(OBJEXT): internal/intern/set.h
enc/trans/cesu_8.$(OBJEXT): internal/intern/signal.h
enc/trans/cesu_8.$(OBJEXT): internal/intern/sprintf.h
enc/trans/cesu_8.$(OBJEXT): internal/intern/string.h
@@ -5503,6 +5535,7 @@ enc/trans/chinese.$(OBJEXT): internal/intern/re.h
enc/trans/chinese.$(OBJEXT): internal/intern/ruby.h
enc/trans/chinese.$(OBJEXT): internal/intern/select.h
enc/trans/chinese.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/chinese.$(OBJEXT): internal/intern/set.h
enc/trans/chinese.$(OBJEXT): internal/intern/signal.h
enc/trans/chinese.$(OBJEXT): internal/intern/sprintf.h
enc/trans/chinese.$(OBJEXT): internal/intern/string.h
@@ -5662,6 +5695,7 @@ enc/trans/ebcdic.$(OBJEXT): internal/intern/re.h
enc/trans/ebcdic.$(OBJEXT): internal/intern/ruby.h
enc/trans/ebcdic.$(OBJEXT): internal/intern/select.h
enc/trans/ebcdic.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/ebcdic.$(OBJEXT): internal/intern/set.h
enc/trans/ebcdic.$(OBJEXT): internal/intern/signal.h
enc/trans/ebcdic.$(OBJEXT): internal/intern/sprintf.h
enc/trans/ebcdic.$(OBJEXT): internal/intern/string.h
@@ -5821,6 +5855,7 @@ enc/trans/emoji.$(OBJEXT): internal/intern/re.h
enc/trans/emoji.$(OBJEXT): internal/intern/ruby.h
enc/trans/emoji.$(OBJEXT): internal/intern/select.h
enc/trans/emoji.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/emoji.$(OBJEXT): internal/intern/set.h
enc/trans/emoji.$(OBJEXT): internal/intern/signal.h
enc/trans/emoji.$(OBJEXT): internal/intern/sprintf.h
enc/trans/emoji.$(OBJEXT): internal/intern/string.h
@@ -5980,6 +6015,7 @@ enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/re.h
enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/ruby.h
enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/select.h
enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/set.h
enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/signal.h
enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/sprintf.h
enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/string.h
@@ -6139,6 +6175,7 @@ enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/re.h
enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/ruby.h
enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/select.h
enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/set.h
enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/signal.h
enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/sprintf.h
enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/string.h
@@ -6298,6 +6335,7 @@ enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/re.h
enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/ruby.h
enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/select.h
enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/set.h
enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/signal.h
enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/sprintf.h
enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/string.h
@@ -6457,6 +6495,7 @@ enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/re.h
enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/ruby.h
enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/select.h
enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/set.h
enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/signal.h
enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/sprintf.h
enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/string.h
@@ -6616,6 +6655,7 @@ enc/trans/escape.$(OBJEXT): internal/intern/re.h
enc/trans/escape.$(OBJEXT): internal/intern/ruby.h
enc/trans/escape.$(OBJEXT): internal/intern/select.h
enc/trans/escape.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/escape.$(OBJEXT): internal/intern/set.h
enc/trans/escape.$(OBJEXT): internal/intern/signal.h
enc/trans/escape.$(OBJEXT): internal/intern/sprintf.h
enc/trans/escape.$(OBJEXT): internal/intern/string.h
@@ -6775,6 +6815,7 @@ enc/trans/gb18030.$(OBJEXT): internal/intern/re.h
enc/trans/gb18030.$(OBJEXT): internal/intern/ruby.h
enc/trans/gb18030.$(OBJEXT): internal/intern/select.h
enc/trans/gb18030.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/gb18030.$(OBJEXT): internal/intern/set.h
enc/trans/gb18030.$(OBJEXT): internal/intern/signal.h
enc/trans/gb18030.$(OBJEXT): internal/intern/sprintf.h
enc/trans/gb18030.$(OBJEXT): internal/intern/string.h
@@ -6934,6 +6975,7 @@ enc/trans/gbk.$(OBJEXT): internal/intern/re.h
enc/trans/gbk.$(OBJEXT): internal/intern/ruby.h
enc/trans/gbk.$(OBJEXT): internal/intern/select.h
enc/trans/gbk.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/gbk.$(OBJEXT): internal/intern/set.h
enc/trans/gbk.$(OBJEXT): internal/intern/signal.h
enc/trans/gbk.$(OBJEXT): internal/intern/sprintf.h
enc/trans/gbk.$(OBJEXT): internal/intern/string.h
@@ -7016,6 +7058,7 @@ enc/trans/iso2022.$(OBJEXT): internal/attr/nodiscard.h
enc/trans/iso2022.$(OBJEXT): internal/attr/noexcept.h
enc/trans/iso2022.$(OBJEXT): internal/attr/noinline.h
enc/trans/iso2022.$(OBJEXT): internal/attr/nonnull.h
+enc/trans/iso2022.$(OBJEXT): internal/attr/nonstring.h
enc/trans/iso2022.$(OBJEXT): internal/attr/noreturn.h
enc/trans/iso2022.$(OBJEXT): internal/attr/packed_struct.h
enc/trans/iso2022.$(OBJEXT): internal/attr/pure.h
@@ -7093,6 +7136,7 @@ enc/trans/iso2022.$(OBJEXT): internal/intern/re.h
enc/trans/iso2022.$(OBJEXT): internal/intern/ruby.h
enc/trans/iso2022.$(OBJEXT): internal/intern/select.h
enc/trans/iso2022.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/iso2022.$(OBJEXT): internal/intern/set.h
enc/trans/iso2022.$(OBJEXT): internal/intern/signal.h
enc/trans/iso2022.$(OBJEXT): internal/intern/sprintf.h
enc/trans/iso2022.$(OBJEXT): internal/intern/string.h
@@ -7252,6 +7296,7 @@ enc/trans/japanese.$(OBJEXT): internal/intern/re.h
enc/trans/japanese.$(OBJEXT): internal/intern/ruby.h
enc/trans/japanese.$(OBJEXT): internal/intern/select.h
enc/trans/japanese.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/japanese.$(OBJEXT): internal/intern/set.h
enc/trans/japanese.$(OBJEXT): internal/intern/signal.h
enc/trans/japanese.$(OBJEXT): internal/intern/sprintf.h
enc/trans/japanese.$(OBJEXT): internal/intern/string.h
@@ -7411,6 +7456,7 @@ enc/trans/japanese_euc.$(OBJEXT): internal/intern/re.h
enc/trans/japanese_euc.$(OBJEXT): internal/intern/ruby.h
enc/trans/japanese_euc.$(OBJEXT): internal/intern/select.h
enc/trans/japanese_euc.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/japanese_euc.$(OBJEXT): internal/intern/set.h
enc/trans/japanese_euc.$(OBJEXT): internal/intern/signal.h
enc/trans/japanese_euc.$(OBJEXT): internal/intern/sprintf.h
enc/trans/japanese_euc.$(OBJEXT): internal/intern/string.h
@@ -7570,6 +7616,7 @@ enc/trans/japanese_sjis.$(OBJEXT): internal/intern/re.h
enc/trans/japanese_sjis.$(OBJEXT): internal/intern/ruby.h
enc/trans/japanese_sjis.$(OBJEXT): internal/intern/select.h
enc/trans/japanese_sjis.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/japanese_sjis.$(OBJEXT): internal/intern/set.h
enc/trans/japanese_sjis.$(OBJEXT): internal/intern/signal.h
enc/trans/japanese_sjis.$(OBJEXT): internal/intern/sprintf.h
enc/trans/japanese_sjis.$(OBJEXT): internal/intern/string.h
@@ -7729,6 +7776,7 @@ enc/trans/korean.$(OBJEXT): internal/intern/re.h
enc/trans/korean.$(OBJEXT): internal/intern/ruby.h
enc/trans/korean.$(OBJEXT): internal/intern/select.h
enc/trans/korean.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/korean.$(OBJEXT): internal/intern/set.h
enc/trans/korean.$(OBJEXT): internal/intern/signal.h
enc/trans/korean.$(OBJEXT): internal/intern/sprintf.h
enc/trans/korean.$(OBJEXT): internal/intern/string.h
@@ -7887,6 +7935,7 @@ enc/trans/newline.$(OBJEXT): internal/intern/re.h
enc/trans/newline.$(OBJEXT): internal/intern/ruby.h
enc/trans/newline.$(OBJEXT): internal/intern/select.h
enc/trans/newline.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/newline.$(OBJEXT): internal/intern/set.h
enc/trans/newline.$(OBJEXT): internal/intern/signal.h
enc/trans/newline.$(OBJEXT): internal/intern/sprintf.h
enc/trans/newline.$(OBJEXT): internal/intern/string.h
@@ -8046,6 +8095,7 @@ enc/trans/single_byte.$(OBJEXT): internal/intern/re.h
enc/trans/single_byte.$(OBJEXT): internal/intern/ruby.h
enc/trans/single_byte.$(OBJEXT): internal/intern/select.h
enc/trans/single_byte.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/single_byte.$(OBJEXT): internal/intern/set.h
enc/trans/single_byte.$(OBJEXT): internal/intern/signal.h
enc/trans/single_byte.$(OBJEXT): internal/intern/sprintf.h
enc/trans/single_byte.$(OBJEXT): internal/intern/string.h
@@ -8205,6 +8255,7 @@ enc/trans/transdb.$(OBJEXT): internal/intern/re.h
enc/trans/transdb.$(OBJEXT): internal/intern/ruby.h
enc/trans/transdb.$(OBJEXT): internal/intern/select.h
enc/trans/transdb.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/transdb.$(OBJEXT): internal/intern/set.h
enc/trans/transdb.$(OBJEXT): internal/intern/signal.h
enc/trans/transdb.$(OBJEXT): internal/intern/sprintf.h
enc/trans/transdb.$(OBJEXT): internal/intern/string.h
@@ -8365,6 +8416,7 @@ enc/trans/utf8_mac.$(OBJEXT): internal/intern/re.h
enc/trans/utf8_mac.$(OBJEXT): internal/intern/ruby.h
enc/trans/utf8_mac.$(OBJEXT): internal/intern/select.h
enc/trans/utf8_mac.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/utf8_mac.$(OBJEXT): internal/intern/set.h
enc/trans/utf8_mac.$(OBJEXT): internal/intern/signal.h
enc/trans/utf8_mac.$(OBJEXT): internal/intern/sprintf.h
enc/trans/utf8_mac.$(OBJEXT): internal/intern/string.h
@@ -8524,6 +8576,7 @@ enc/trans/utf_16_32.$(OBJEXT): internal/intern/re.h
enc/trans/utf_16_32.$(OBJEXT): internal/intern/ruby.h
enc/trans/utf_16_32.$(OBJEXT): internal/intern/select.h
enc/trans/utf_16_32.$(OBJEXT): internal/intern/select/largesize.h
+enc/trans/utf_16_32.$(OBJEXT): internal/intern/set.h
enc/trans/utf_16_32.$(OBJEXT): internal/intern/signal.h
enc/trans/utf_16_32.$(OBJEXT): internal/intern/sprintf.h
enc/trans/utf_16_32.$(OBJEXT): internal/intern/string.h
@@ -8686,6 +8739,7 @@ enc/unicode.$(OBJEXT): internal/intern/re.h
enc/unicode.$(OBJEXT): internal/intern/ruby.h
enc/unicode.$(OBJEXT): internal/intern/select.h
enc/unicode.$(OBJEXT): internal/intern/select/largesize.h
+enc/unicode.$(OBJEXT): internal/intern/set.h
enc/unicode.$(OBJEXT): internal/intern/signal.h
enc/unicode.$(OBJEXT): internal/intern/sprintf.h
enc/unicode.$(OBJEXT): internal/intern/string.h
@@ -8857,6 +8911,7 @@ enc/us_ascii.$(OBJEXT): internal/intern/re.h
enc/us_ascii.$(OBJEXT): internal/intern/ruby.h
enc/us_ascii.$(OBJEXT): internal/intern/select.h
enc/us_ascii.$(OBJEXT): internal/intern/select/largesize.h
+enc/us_ascii.$(OBJEXT): internal/intern/set.h
enc/us_ascii.$(OBJEXT): internal/intern/signal.h
enc/us_ascii.$(OBJEXT): internal/intern/sprintf.h
enc/us_ascii.$(OBJEXT): internal/intern/string.h
@@ -9020,6 +9075,7 @@ enc/utf_16be.$(OBJEXT): internal/intern/re.h
enc/utf_16be.$(OBJEXT): internal/intern/ruby.h
enc/utf_16be.$(OBJEXT): internal/intern/select.h
enc/utf_16be.$(OBJEXT): internal/intern/select/largesize.h
+enc/utf_16be.$(OBJEXT): internal/intern/set.h
enc/utf_16be.$(OBJEXT): internal/intern/signal.h
enc/utf_16be.$(OBJEXT): internal/intern/sprintf.h
enc/utf_16be.$(OBJEXT): internal/intern/string.h
@@ -9182,6 +9238,7 @@ enc/utf_16le.$(OBJEXT): internal/intern/re.h
enc/utf_16le.$(OBJEXT): internal/intern/ruby.h
enc/utf_16le.$(OBJEXT): internal/intern/select.h
enc/utf_16le.$(OBJEXT): internal/intern/select/largesize.h
+enc/utf_16le.$(OBJEXT): internal/intern/set.h
enc/utf_16le.$(OBJEXT): internal/intern/signal.h
enc/utf_16le.$(OBJEXT): internal/intern/sprintf.h
enc/utf_16le.$(OBJEXT): internal/intern/string.h
@@ -9344,6 +9401,7 @@ enc/utf_32be.$(OBJEXT): internal/intern/re.h
enc/utf_32be.$(OBJEXT): internal/intern/ruby.h
enc/utf_32be.$(OBJEXT): internal/intern/select.h
enc/utf_32be.$(OBJEXT): internal/intern/select/largesize.h
+enc/utf_32be.$(OBJEXT): internal/intern/set.h
enc/utf_32be.$(OBJEXT): internal/intern/signal.h
enc/utf_32be.$(OBJEXT): internal/intern/sprintf.h
enc/utf_32be.$(OBJEXT): internal/intern/string.h
@@ -9506,6 +9564,7 @@ enc/utf_32le.$(OBJEXT): internal/intern/re.h
enc/utf_32le.$(OBJEXT): internal/intern/ruby.h
enc/utf_32le.$(OBJEXT): internal/intern/select.h
enc/utf_32le.$(OBJEXT): internal/intern/select/largesize.h
+enc/utf_32le.$(OBJEXT): internal/intern/set.h
enc/utf_32le.$(OBJEXT): internal/intern/signal.h
enc/utf_32le.$(OBJEXT): internal/intern/sprintf.h
enc/utf_32le.$(OBJEXT): internal/intern/string.h
@@ -9677,6 +9736,7 @@ enc/utf_8.$(OBJEXT): internal/intern/re.h
enc/utf_8.$(OBJEXT): internal/intern/ruby.h
enc/utf_8.$(OBJEXT): internal/intern/select.h
enc/utf_8.$(OBJEXT): internal/intern/select/largesize.h
+enc/utf_8.$(OBJEXT): internal/intern/set.h
enc/utf_8.$(OBJEXT): internal/intern/signal.h
enc/utf_8.$(OBJEXT): internal/intern/sprintf.h
enc/utf_8.$(OBJEXT): internal/intern/string.h
@@ -9840,6 +9900,7 @@ enc/windows_1250.$(OBJEXT): internal/intern/re.h
enc/windows_1250.$(OBJEXT): internal/intern/ruby.h
enc/windows_1250.$(OBJEXT): internal/intern/select.h
enc/windows_1250.$(OBJEXT): internal/intern/select/largesize.h
+enc/windows_1250.$(OBJEXT): internal/intern/set.h
enc/windows_1250.$(OBJEXT): internal/intern/signal.h
enc/windows_1250.$(OBJEXT): internal/intern/sprintf.h
enc/windows_1250.$(OBJEXT): internal/intern/string.h
@@ -10001,6 +10062,7 @@ enc/windows_1251.$(OBJEXT): internal/intern/re.h
enc/windows_1251.$(OBJEXT): internal/intern/ruby.h
enc/windows_1251.$(OBJEXT): internal/intern/select.h
enc/windows_1251.$(OBJEXT): internal/intern/select/largesize.h
+enc/windows_1251.$(OBJEXT): internal/intern/set.h
enc/windows_1251.$(OBJEXT): internal/intern/signal.h
enc/windows_1251.$(OBJEXT): internal/intern/sprintf.h
enc/windows_1251.$(OBJEXT): internal/intern/string.h
@@ -10163,6 +10225,7 @@ enc/windows_1252.$(OBJEXT): internal/intern/re.h
enc/windows_1252.$(OBJEXT): internal/intern/ruby.h
enc/windows_1252.$(OBJEXT): internal/intern/select.h
enc/windows_1252.$(OBJEXT): internal/intern/select/largesize.h
+enc/windows_1252.$(OBJEXT): internal/intern/set.h
enc/windows_1252.$(OBJEXT): internal/intern/signal.h
enc/windows_1252.$(OBJEXT): internal/intern/sprintf.h
enc/windows_1252.$(OBJEXT): internal/intern/string.h
@@ -10324,6 +10387,7 @@ enc/windows_1253.$(OBJEXT): internal/intern/re.h
enc/windows_1253.$(OBJEXT): internal/intern/ruby.h
enc/windows_1253.$(OBJEXT): internal/intern/select.h
enc/windows_1253.$(OBJEXT): internal/intern/select/largesize.h
+enc/windows_1253.$(OBJEXT): internal/intern/set.h
enc/windows_1253.$(OBJEXT): internal/intern/signal.h
enc/windows_1253.$(OBJEXT): internal/intern/sprintf.h
enc/windows_1253.$(OBJEXT): internal/intern/string.h
@@ -10486,6 +10550,7 @@ enc/windows_1254.$(OBJEXT): internal/intern/re.h
enc/windows_1254.$(OBJEXT): internal/intern/ruby.h
enc/windows_1254.$(OBJEXT): internal/intern/select.h
enc/windows_1254.$(OBJEXT): internal/intern/select/largesize.h
+enc/windows_1254.$(OBJEXT): internal/intern/set.h
enc/windows_1254.$(OBJEXT): internal/intern/signal.h
enc/windows_1254.$(OBJEXT): internal/intern/sprintf.h
enc/windows_1254.$(OBJEXT): internal/intern/string.h
@@ -10648,6 +10713,7 @@ enc/windows_1257.$(OBJEXT): internal/intern/re.h
enc/windows_1257.$(OBJEXT): internal/intern/ruby.h
enc/windows_1257.$(OBJEXT): internal/intern/select.h
enc/windows_1257.$(OBJEXT): internal/intern/select/largesize.h
+enc/windows_1257.$(OBJEXT): internal/intern/set.h
enc/windows_1257.$(OBJEXT): internal/intern/signal.h
enc/windows_1257.$(OBJEXT): internal/intern/sprintf.h
enc/windows_1257.$(OBJEXT): internal/intern/string.h
@@ -10812,6 +10878,7 @@ enc/windows_31j.$(OBJEXT): internal/intern/re.h
enc/windows_31j.$(OBJEXT): internal/intern/ruby.h
enc/windows_31j.$(OBJEXT): internal/intern/select.h
enc/windows_31j.$(OBJEXT): internal/intern/select/largesize.h
+enc/windows_31j.$(OBJEXT): internal/intern/set.h
enc/windows_31j.$(OBJEXT): internal/intern/signal.h
enc/windows_31j.$(OBJEXT): internal/intern/sprintf.h
enc/windows_31j.$(OBJEXT): internal/intern/string.h
diff --git a/enc/emacs_mule.c b/enc/emacs_mule.c
index f92eb183cf..abd986a187 100644
--- a/enc/emacs_mule.c
+++ b/enc/emacs_mule.c
@@ -334,7 +334,11 @@ OnigEncodingDefine(emacs_mule, Emacs_Mule) = {
onigenc_not_support_get_ctype_code_range,
left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
onigenc_ascii_only_case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/euc_jp.c b/enc/euc_jp.c
index d283bf4ebb..678d011668 100644
--- a/enc/euc_jp.c
+++ b/enc/euc_jp.c
@@ -576,7 +576,11 @@ OnigEncodingDefine(euc_jp, EUC_JP) = {
get_ctype_code_range,
left_adjust_char_head,
is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
onigenc_ascii_only_case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/euc_kr.c b/enc/euc_kr.c
index 21d6ab4e1c..4079a0ece0 100644
--- a/enc/euc_kr.c
+++ b/enc/euc_kr.c
@@ -188,7 +188,11 @@ OnigEncodingDefine(euc_kr, EUC_KR) = {
onigenc_not_support_get_ctype_code_range,
euckr_left_adjust_char_head,
euckr_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
onigenc_ascii_only_case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
@@ -213,7 +217,11 @@ OnigEncodingDefine(euc_cn, EUC_CN) = {
onigenc_not_support_get_ctype_code_range,
euckr_left_adjust_char_head,
euckr_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
onigenc_ascii_only_case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/euc_tw.c b/enc/euc_tw.c
index 1c5659cb1d..722e29a9da 100644
--- a/enc/euc_tw.c
+++ b/enc/euc_tw.c
@@ -221,7 +221,11 @@ OnigEncodingDefine(euc_tw, EUC_TW) = {
onigenc_not_support_get_ctype_code_range,
euctw_left_adjust_char_head,
euctw_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
onigenc_ascii_only_case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/gb18030.c b/enc/gb18030.c
index 63d2e633ec..316737db11 100644
--- a/enc/gb18030.c
+++ b/enc/gb18030.c
@@ -597,7 +597,11 @@ OnigEncodingDefine(gb18030, GB18030) = {
onigenc_not_support_get_ctype_code_range,
gb18030_left_adjust_char_head,
gb18030_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
onigenc_ascii_only_case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/gbk.c b/enc/gbk.c
index 31032553bf..3df4e4b6d6 100644
--- a/enc/gbk.c
+++ b/enc/gbk.c
@@ -211,7 +211,11 @@ OnigEncodingDefine(gbk, GBK) = {
onigenc_not_support_get_ctype_code_range,
gbk_left_adjust_char_head,
gbk_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
onigenc_ascii_only_case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/iso_8859_1.c b/enc/iso_8859_1.c
index 7af0888c3e..78ea1fba60 100644
--- a/enc/iso_8859_1.c
+++ b/enc/iso_8859_1.c
@@ -255,6 +255,7 @@ is_code_ctype(OnigCodePoint code, unsigned int ctype, OnigEncoding enc ARG_UNUSE
return FALSE;
}
+#ifdef USE_CASE_MAP_API
static int
case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
const OnigUChar* end, OnigUChar* to, OnigUChar* to_end,
@@ -297,6 +298,7 @@ case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
*flagP = flags;
return (int )(to - to_start);
}
+#endif
OnigEncodingDefine(iso_8859_1, ISO_8859_1) = {
onigenc_single_byte_mbc_enc_len,
@@ -315,7 +317,11 @@ OnigEncodingDefine(iso_8859_1, ISO_8859_1) = {
onigenc_not_support_get_ctype_code_range,
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/iso_8859_10.c b/enc/iso_8859_10.c
index cae4be2db0..bf1c884cb2 100644
--- a/enc/iso_8859_10.c
+++ b/enc/iso_8859_10.c
@@ -224,6 +224,7 @@ get_case_fold_codes_by_str(OnigCaseFoldType flag,
flag, p, end, items);
}
+#ifdef USE_CASE_MAP_API
static int
case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
const OnigUChar* end, OnigUChar* to, OnigUChar* to_end,
@@ -269,6 +270,7 @@ case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
*flagP = flags;
return (int )(to - to_start);
}
+#endif
OnigEncodingDefine(iso_8859_10, ISO_8859_10) = {
onigenc_single_byte_mbc_enc_len,
@@ -287,7 +289,11 @@ OnigEncodingDefine(iso_8859_10, ISO_8859_10) = {
onigenc_not_support_get_ctype_code_range,
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/iso_8859_11.c b/enc/iso_8859_11.c
index b9c6119fd9..403ae6499e 100644
--- a/enc/iso_8859_11.c
+++ b/enc/iso_8859_11.c
@@ -93,7 +93,11 @@ OnigEncodingDefine(iso_8859_11, ISO_8859_11) = {
onigenc_not_support_get_ctype_code_range,
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
onigenc_single_byte_ascii_only_case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/iso_8859_13.c b/enc/iso_8859_13.c
index fe1ddd7065..8c6e758b80 100644
--- a/enc/iso_8859_13.c
+++ b/enc/iso_8859_13.c
@@ -217,6 +217,7 @@ get_case_fold_codes_by_str(OnigCaseFoldType flag,
flag, p, end, items);
}
+#ifdef USE_CASE_MAP_API
static int
case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
const OnigUChar* end, OnigUChar* to, OnigUChar* to_end,
@@ -264,6 +265,7 @@ case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
*flagP = flags;
return (int )(to - to_start);
}
+#endif
OnigEncodingDefine(iso_8859_13, ISO_8859_13) = {
onigenc_single_byte_mbc_enc_len,
@@ -282,7 +284,11 @@ OnigEncodingDefine(iso_8859_13, ISO_8859_13) = {
onigenc_not_support_get_ctype_code_range,
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/iso_8859_14.c b/enc/iso_8859_14.c
index 647514a016..21dffea76f 100644
--- a/enc/iso_8859_14.c
+++ b/enc/iso_8859_14.c
@@ -226,6 +226,7 @@ get_case_fold_codes_by_str(OnigCaseFoldType flag,
flag, p, end, items);
}
+#ifdef USE_CASE_MAP_API
static int
case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
const OnigUChar* end, OnigUChar* to, OnigUChar* to_end,
@@ -280,6 +281,7 @@ case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
*flagP = flags;
return (int )(to - to_start);
}
+#endif
OnigEncodingDefine(iso_8859_14, ISO_8859_14) = {
onigenc_single_byte_mbc_enc_len,
@@ -298,7 +300,11 @@ OnigEncodingDefine(iso_8859_14, ISO_8859_14) = {
onigenc_not_support_get_ctype_code_range,
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/iso_8859_15.c b/enc/iso_8859_15.c
index 377a3afc7b..dd6c29a643 100644
--- a/enc/iso_8859_15.c
+++ b/enc/iso_8859_15.c
@@ -220,6 +220,7 @@ get_case_fold_codes_by_str(OnigCaseFoldType flag,
flag, p, end, items);
}
+#ifdef USE_CASE_MAP_API
static int
case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
const OnigUChar* end, OnigUChar* to, OnigUChar* to_end,
@@ -271,6 +272,7 @@ case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
*flagP = flags;
return (int )(to - to_start);
}
+#endif
OnigEncodingDefine(iso_8859_15, ISO_8859_15) = {
onigenc_single_byte_mbc_enc_len,
@@ -289,7 +291,11 @@ OnigEncodingDefine(iso_8859_15, ISO_8859_15) = {
onigenc_not_support_get_ctype_code_range,
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/iso_8859_16.c b/enc/iso_8859_16.c
index 135630eb73..aa7ce99fba 100644
--- a/enc/iso_8859_16.c
+++ b/enc/iso_8859_16.c
@@ -222,6 +222,7 @@ get_case_fold_codes_by_str(OnigCaseFoldType flag,
flag, p, end, items);
}
+#ifdef USE_CASE_MAP_API
static int
case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
const OnigUChar* end, OnigUChar* to, OnigUChar* to_end,
@@ -275,6 +276,7 @@ case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
*flagP = flags;
return (int )(to - to_start);
}
+#endif
OnigEncodingDefine(iso_8859_16, ISO_8859_16) = {
onigenc_single_byte_mbc_enc_len,
@@ -293,7 +295,11 @@ OnigEncodingDefine(iso_8859_16, ISO_8859_16) = {
onigenc_not_support_get_ctype_code_range,
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/iso_8859_2.c b/enc/iso_8859_2.c
index 3a05c6320d..859073fd14 100644
--- a/enc/iso_8859_2.c
+++ b/enc/iso_8859_2.c
@@ -220,6 +220,7 @@ is_code_ctype(OnigCodePoint code, unsigned int ctype, OnigEncoding enc ARG_UNUSE
return FALSE;
}
+#ifdef USE_CASE_MAP_API
static int
case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
const OnigUChar* end, OnigUChar* to, OnigUChar* to_end,
@@ -266,6 +267,7 @@ case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
*flagP = flags;
return (int )(to - to_start);
}
+#endif
OnigEncodingDefine(iso_8859_2, ISO_8859_2) = {
onigenc_single_byte_mbc_enc_len,
@@ -284,7 +286,11 @@ OnigEncodingDefine(iso_8859_2, ISO_8859_2) = {
onigenc_not_support_get_ctype_code_range,
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/iso_8859_3.c b/enc/iso_8859_3.c
index 2a343eac63..d8199d5125 100644
--- a/enc/iso_8859_3.c
+++ b/enc/iso_8859_3.c
@@ -220,6 +220,7 @@ get_case_fold_codes_by_str(OnigCaseFoldType flag,
flag, p, end, items);
}
+#ifdef USE_CASE_MAP_API
#define DOTLESS_i (0xB9)
#define I_WITH_DOT_ABOVE (0xA9)
static int
@@ -276,6 +277,7 @@ case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
*flagP = flags;
return (int )(to - to_start);
}
+#endif
OnigEncodingDefine(iso_8859_3, ISO_8859_3) = {
onigenc_single_byte_mbc_enc_len,
@@ -294,7 +296,11 @@ OnigEncodingDefine(iso_8859_3, ISO_8859_3) = {
onigenc_not_support_get_ctype_code_range,
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/iso_8859_4.c b/enc/iso_8859_4.c
index e2134e8c0b..5f01f01575 100644
--- a/enc/iso_8859_4.c
+++ b/enc/iso_8859_4.c
@@ -223,6 +223,7 @@ get_case_fold_codes_by_str(OnigCaseFoldType flag,
flag, p, end, items);
}
+#ifdef USE_CASE_MAP_API
static int
case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
const OnigUChar* end, OnigUChar* to, OnigUChar* to_end,
@@ -272,6 +273,7 @@ case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
*flagP = flags;
return (int )(to - to_start);
}
+#endif
OnigEncodingDefine(iso_8859_4, ISO_8859_4) = {
onigenc_single_byte_mbc_enc_len,
@@ -290,7 +292,11 @@ OnigEncodingDefine(iso_8859_4, ISO_8859_4) = {
onigenc_not_support_get_ctype_code_range,
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/iso_8859_5.c b/enc/iso_8859_5.c
index 6fafc35823..8223fc0ec7 100644
--- a/enc/iso_8859_5.c
+++ b/enc/iso_8859_5.c
@@ -209,6 +209,7 @@ get_case_fold_codes_by_str(OnigCaseFoldType flag,
flag, p, end, items);
}
+#ifdef USE_CASE_MAP_API
static int
case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
const OnigUChar* end, OnigUChar* to, OnigUChar* to_end,
@@ -240,6 +241,7 @@ case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
*flagP = flags;
return (int )(to - to_start);
}
+#endif
OnigEncodingDefine(iso_8859_5, ISO_8859_5) = {
onigenc_single_byte_mbc_enc_len,
@@ -258,7 +260,11 @@ OnigEncodingDefine(iso_8859_5, ISO_8859_5) = {
onigenc_not_support_get_ctype_code_range,
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/iso_8859_6.c b/enc/iso_8859_6.c
index cdb74054d1..78543ea307 100644
--- a/enc/iso_8859_6.c
+++ b/enc/iso_8859_6.c
@@ -93,7 +93,11 @@ OnigEncodingDefine(iso_8859_6, ISO_8859_6) = {
onigenc_not_support_get_ctype_code_range,
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
onigenc_single_byte_ascii_only_case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/iso_8859_7.c b/enc/iso_8859_7.c
index ac973f74ba..e84f5c3460 100644
--- a/enc/iso_8859_7.c
+++ b/enc/iso_8859_7.c
@@ -205,6 +205,7 @@ get_case_fold_codes_by_str(OnigCaseFoldType flag,
flag, p, end, items);
}
+#ifdef USE_CASE_MAP_API
static int
case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
const OnigUChar* end, OnigUChar* to, OnigUChar* to_end,
@@ -259,6 +260,7 @@ case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
*flagP = flags;
return (int )(to - to_start);
}
+#endif
OnigEncodingDefine(iso_8859_7, ISO_8859_7) = {
onigenc_single_byte_mbc_enc_len,
@@ -277,7 +279,11 @@ OnigEncodingDefine(iso_8859_7, ISO_8859_7) = {
onigenc_not_support_get_ctype_code_range,
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/iso_8859_8.c b/enc/iso_8859_8.c
index e256855f21..b757a283de 100644
--- a/enc/iso_8859_8.c
+++ b/enc/iso_8859_8.c
@@ -93,7 +93,11 @@ OnigEncodingDefine(iso_8859_8, ISO_8859_8) = {
onigenc_not_support_get_ctype_code_range,
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
onigenc_single_byte_ascii_only_case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/iso_8859_9.c b/enc/iso_8859_9.c
index 004eec310f..f15953963b 100644
--- a/enc/iso_8859_9.c
+++ b/enc/iso_8859_9.c
@@ -213,6 +213,7 @@ get_case_fold_codes_by_str(OnigCaseFoldType flag,
flag, p, end, items);
}
+#ifdef USE_CASE_MAP_API
#define DOTLESS_i (0xFD)
#define I_WITH_DOT_ABOVE (0xDD)
static int
@@ -265,6 +266,7 @@ case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
*flagP = flags;
return (int )(to - to_start);
}
+#endif
OnigEncodingDefine(iso_8859_9, ISO_8859_9) = {
onigenc_single_byte_mbc_enc_len,
@@ -283,7 +285,11 @@ OnigEncodingDefine(iso_8859_9, ISO_8859_9) = {
onigenc_not_support_get_ctype_code_range,
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/jis/props.h.blt b/enc/jis/props.h.blt
index 508a084449..865ae6b651 100644
--- a/enc/jis/props.h.blt
+++ b/enc/jis/props.h.blt
@@ -1,5 +1,5 @@
/* ANSI-C code produced by gperf version 3.1 */
-/* Command-line: gperf -k1,3 -7 -c -j1 -i1 -t -C -P -t --ignore-case -H onig_jis_property_hash -Q onig_jis_property_pool -N onig_jis_property enc/jis/props.kwd */
+/* Command-line: gperf -L ANSI-C -k1,3 -7 -c -j1 -i1 -t -C -P -t --ignore-case -H onig_jis_property_hash -Q onig_jis_property_pool -N onig_jis_property enc/jis/props.kwd */
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
&& ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
@@ -28,7 +28,6 @@
#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gperf@gnu.org>."
#endif
-#define gperf_offsetof(s, n) (short)offsetof(struct s##_t, s##_str##n)
#line 1 "enc/jis/props.kwd"
/* -*- c -*- */
#define GPERF_DOWNCASE 1
@@ -82,7 +81,7 @@ struct enc_property;
#ifndef GPERF_DOWNCASE
#define GPERF_DOWNCASE 1
-static const unsigned char gperf_downcase[256] =
+static unsigned char gperf_downcase[256] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
@@ -180,19 +179,19 @@ onig_jis_property (register const char *str, register size_t len)
{
{-1}, {-1}, {-1}, {-1}, {-1},
#line 48 "enc/jis/props.kwd"
- {gperf_offsetof(onig_jis_property_pool, 5), onigenc_jis_han},
+ {(int)(size_t)&((struct onig_jis_property_pool_t *)0)->onig_jis_property_pool_str5, onigenc_jis_han},
{-1},
#line 49 "enc/jis/props.kwd"
- {gperf_offsetof(onig_jis_property_pool, 7), onigenc_jis_latin},
+ {(int)(size_t)&((struct onig_jis_property_pool_t *)0)->onig_jis_property_pool_str7, onigenc_jis_latin},
#line 50 "enc/jis/props.kwd"
- {gperf_offsetof(onig_jis_property_pool, 8), onigenc_jis_greek},
+ {(int)(size_t)&((struct onig_jis_property_pool_t *)0)->onig_jis_property_pool_str8, onigenc_jis_greek},
{-1},
#line 46 "enc/jis/props.kwd"
- {gperf_offsetof(onig_jis_property_pool, 10), onigenc_jis_hiragana},
+ {(int)(size_t)&((struct onig_jis_property_pool_t *)0)->onig_jis_property_pool_str10, onigenc_jis_hiragana},
#line 47 "enc/jis/props.kwd"
- {gperf_offsetof(onig_jis_property_pool, 11), onigenc_jis_katakana},
+ {(int)(size_t)&((struct onig_jis_property_pool_t *)0)->onig_jis_property_pool_str11, onigenc_jis_katakana},
#line 51 "enc/jis/props.kwd"
- {gperf_offsetof(onig_jis_property_pool, 12), onigenc_jis_cyrillic}
+ {(int)(size_t)&((struct onig_jis_property_pool_t *)0)->onig_jis_property_pool_str12, onigenc_jis_cyrillic}
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
diff --git a/enc/koi8_r.c b/enc/koi8_r.c
index a520975774..39f2482465 100644
--- a/enc/koi8_r.c
+++ b/enc/koi8_r.c
@@ -214,7 +214,11 @@ OnigEncodingDefine(koi8_r, KOI8_R) = {
onigenc_not_support_get_ctype_code_range,
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
onigenc_single_byte_ascii_only_case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/koi8_u.c b/enc/koi8_u.c
index 50bb78bd04..8cd890dd16 100644
--- a/enc/koi8_u.c
+++ b/enc/koi8_u.c
@@ -218,7 +218,11 @@ OnigEncodingDefine(koi8_u, KOI8_U) = {
onigenc_not_support_get_ctype_code_range,
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
onigenc_single_byte_ascii_only_case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/shift_jis.c b/enc/shift_jis.c
index f1355d2d95..48f648868a 100644
--- a/enc/shift_jis.c
+++ b/enc/shift_jis.c
@@ -47,7 +47,11 @@ OnigEncodingDefine(shift_jis, Shift_JIS) = {
get_ctype_code_range,
left_adjust_char_head,
is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
onigenc_ascii_only_case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/trans/ibm864-tbl.rb b/enc/trans/ibm864-tbl.rb
new file mode 100644
index 0000000000..13f8a27f1d
--- /dev/null
+++ b/enc/trans/ibm864-tbl.rb
@@ -0,0 +1,126 @@
+IBM864_TO_UCS_TBL = [
+ ["80",0x00B0],
+ ["81",0x00B7],
+ ["82",0x2219],
+ ["83",0x221A],
+ ["84",0x2592],
+ ["85",0x2500],
+ ["86",0x2502],
+ ["87",0x253C],
+ ["88",0x2524],
+ ["89",0x252C],
+ ["8A",0x251C],
+ ["8B",0x2534],
+ ["8C",0x2510],
+ ["8D",0x250C],
+ ["8E",0x2514],
+ ["8F",0x2518],
+ ["90",0x03B2],
+ ["91",0x221E],
+ ["92",0x03C6],
+ ["93",0x00B1],
+ ["94",0x00BD],
+ ["95",0x00BC],
+ ["96",0x2248],
+ ["97",0x00AB],
+ ["98",0x00BB],
+ ["99",0xFEF7],
+ ["9A",0xFEF8],
+ ["9D",0xFEFB],
+ ["9E",0xFEFC],
+ ["9F",0xFE73],
+ ["A0",0x00A0],
+ ["A1",0x00AD],
+ ["A2",0xFE82],
+ ["A3",0x00A3],
+ ["A4",0x00A4],
+ ["A5",0xFE84],
+ ["A7",0x20AC], # Euro sign from CCSID 864
+ ["A8",0xFE8E],
+ ["A9",0xFE8F],
+ ["AA",0xFE95],
+ ["AB",0xFE99],
+ ["AC",0x060C],
+ ["AD",0xFE9D],
+ ["AE",0xFEA1],
+ ["AF",0xFEA5],
+ ["B0",0x0660],
+ ["B1",0x0661],
+ ["B2",0x0662],
+ ["B3",0x0663],
+ ["B4",0x0664],
+ ["B5",0x0665],
+ ["B6",0x0666],
+ ["B7",0x0667],
+ ["B8",0x0668],
+ ["B9",0x0669],
+ ["BA",0xFED1],
+ ["BB",0x061B],
+ ["BC",0xFEB1],
+ ["BD",0xFEB5],
+ ["BE",0xFEB9],
+ ["BF",0x061F],
+ ["C0",0x00A2],
+ ["C1",0xFE80],
+ ["C2",0xFE81],
+ ["C3",0xFE83],
+ ["C4",0xFE85],
+ ["C5",0xFECA],
+ ["C6",0xFE8B],
+ ["C7",0xFE8D],
+ ["C8",0xFE91],
+ ["C9",0xFE93],
+ ["CA",0xFE97],
+ ["CB",0xFE9B],
+ ["CC",0xFE9F],
+ ["CD",0xFEA3],
+ ["CE",0xFEA7],
+ ["CF",0xFEA9],
+ ["D0",0xFEAB],
+ ["D1",0xFEAD],
+ ["D2",0xFEAF],
+ ["D3",0xFEB3],
+ ["D4",0xFEB7],
+ ["D5",0xFEBB],
+ ["D6",0xFEBF],
+ ["D7",0xFEC1],
+ ["D8",0xFEC5],
+ ["D9",0xFECB],
+ ["DA",0xFECF],
+ ["DB",0x00A6],
+ ["DC",0x00AC],
+ ["DD",0x00F7],
+ ["DE",0x00D7],
+ ["DF",0xFEC9],
+ ["E0",0x0640],
+ ["E1",0xFED3],
+ ["E2",0xFED7],
+ ["E3",0xFEDB],
+ ["E4",0xFEDF],
+ ["E5",0xFEE3],
+ ["E6",0xFEE7],
+ ["E7",0xFEEB],
+ ["E8",0xFEED],
+ ["E9",0xFEEF],
+ ["EA",0xFEF3],
+ ["EB",0xFEBD],
+ ["EC",0xFECC],
+ ["ED",0xFECE],
+ ["EE",0xFECD],
+ ["EF",0xFEE1],
+ ["F0",0xFE7D],
+ ["F1",0x0651],
+ ["F2",0xFEE5],
+ ["F3",0xFEE9],
+ ["F4",0xFEEC],
+ ["F5",0xFEF0],
+ ["F6",0xFEF2],
+ ["F7",0xFED0],
+ ["F8",0xFED5],
+ ["F9",0xFEF5],
+ ["FA",0xFEF6],
+ ["FB",0xFEDD],
+ ["FC",0xFED9],
+ ["FD",0xFEF1],
+ ["FE",0x25A0]
+]
diff --git a/enc/trans/iso2022.trans b/enc/trans/iso2022.trans
index a441f1596d..bc42bbc19c 100644
--- a/enc/trans/iso2022.trans
+++ b/enc/trans/iso2022.trans
@@ -1,4 +1,5 @@
#include "transcode_data.h"
+#include "ruby/internal/attr/nonstring.h"
<%
map = {
@@ -79,6 +80,34 @@ iso2022jp_init(void *statep)
return 0;
}
+static unsigned char *
+iso2022jp_put_state(unsigned char *sp, unsigned char *o, int oldstate, int newstate)
+{
+ if (oldstate != newstate) {
+ *o++ = 0x1b;
+ switch (newstate) {
+ case G0_ASCII:
+ *o++ = '(';
+ *o++ = 'B';
+ break;
+ case G0_JISX0201_KATAKANA:
+ *o++ = '(';
+ *o++ = 'I';
+ break;
+ case G0_JISX0208_1978:
+ *o++ = '$';
+ *o++ = '@';
+ break;
+ default:
+ *o++ = '$';
+ *o++ = 'B';
+ break;
+ }
+ *sp = newstate;
+ }
+ return o;
+}
+
static VALUE
fun_si_iso2022jp_decoder(void *statep, const unsigned char *s, size_t l)
{
@@ -154,24 +183,7 @@ fun_so_iso2022jp_encoder(void *statep, const unsigned char *s, size_t l, unsigne
else
newstate = G0_JISX0208_1983;
- if (*sp != newstate) {
- if (newstate == G0_ASCII) {
- *o++ = 0x1b;
- *o++ = '(';
- *o++ = 'B';
- }
- else if (newstate == G0_JISX0208_1978) {
- *o++ = 0x1b;
- *o++ = '$';
- *o++ = '@';
- }
- else {
- *o++ = 0x1b;
- *o++ = '$';
- *o++ = 'B';
- }
- *sp = newstate;
- }
+ o = iso2022jp_put_state(sp, o, *sp, newstate);
if (l == 1) {
*o++ = s[0] & 0x7f;
@@ -202,10 +214,7 @@ finish_iso2022jp_encoder(void *statep, unsigned char *o, size_t osize)
if (*sp == G0_ASCII)
return 0;
- *o++ = 0x1b;
- *o++ = '(';
- *o++ = 'B';
- *sp = G0_ASCII;
+ o = iso2022jp_put_state(sp, o, *sp, G0_ASCII);
return o - output0;
}
@@ -399,24 +408,7 @@ fun_so_cp5022x_encoder(void *statep, const unsigned char *s, size_t l,
else
newstate = G0_JISX0208_1983;
- if (*sp != newstate) {
- if (newstate == G0_ASCII) {
- *o++ = 0x1b;
- *o++ = '(';
- *o++ = 'B';
- }
- else if (newstate == G0_JISX0201_KATAKANA) {
- *o++ = 0x1b;
- *o++ = '(';
- *o++ = 'I';
- }
- else {
- *o++ = 0x1b;
- *o++ = '$';
- *o++ = 'B';
- }
- *sp = newstate;
- }
+ o = iso2022jp_put_state(sp, o, sp[0], newstate);
if (l == 1) {
*o++ = s[0] & 0x7f;
@@ -443,15 +435,26 @@ rb_cp50221_encoder = {
iso2022jp_encoder_reset_sequence_size, finish_iso2022jp_encoder
};
-static const char *tbl0208 =
- "\x21\x23\x21\x56\x21\x57\x21\x22\x21\x26\x25\x72\x25\x21\x25\x23" \
- "\x25\x25\x25\x27\x25\x29\x25\x63\x25\x65\x25\x67\x25\x43\x21\x3C" \
- "\x25\x22\x25\x24\x25\x26\x25\x28\x25\x2A\x25\x2B\x25\x2D\x25\x2F" \
- "\x25\x31\x25\x33\x25\x35\x25\x37\x25\x39\x25\x3B\x25\x3D\x25\x3F" \
- "\x25\x41\x25\x44\x25\x46\x25\x48\x25\x4A\x25\x4B\x25\x4C\x25\x4D" \
- "\x25\x4E\x25\x4F\x25\x52\x25\x55\x25\x58\x25\x5B\x25\x5E\x25\x5F" \
- "\x25\x60\x25\x61\x25\x62\x25\x64\x25\x66\x25\x68\x25\x69\x25\x6A" \
- "\x25\x6B\x25\x6C\x25\x6D\x25\x6F\x25\x73\x21\x2B\x21\x2C";
+/* JIS0201 to JIS0208 conversion table */
+enum {tbl0208_num = 0xDF - 0xA1 + 1};
+RBIMPL_ATTR_NONSTRING_ARRAY() static const char tbl0208[tbl0208_num][2] = {
+ "\x21\x23", "\x21\x56", "\x21\x57", "\x21\x22",
+ "\x21\x26", "\x25\x72", "\x25\x21", "\x25\x23",
+ "\x25\x25", "\x25\x27", "\x25\x29", "\x25\x63",
+ "\x25\x65", "\x25\x67", "\x25\x43", "\x21\x3C",
+ "\x25\x22", "\x25\x24", "\x25\x26", "\x25\x28",
+ "\x25\x2A", "\x25\x2B", "\x25\x2D", "\x25\x2F",
+ "\x25\x31", "\x25\x33", "\x25\x35", "\x25\x37",
+ "\x25\x39", "\x25\x3B", "\x25\x3D", "\x25\x3F",
+ "\x25\x41", "\x25\x44", "\x25\x46", "\x25\x48",
+ "\x25\x4A", "\x25\x4B", "\x25\x4C", "\x25\x4D",
+ "\x25\x4E", "\x25\x4F", "\x25\x52", "\x25\x55",
+ "\x25\x58", "\x25\x5B", "\x25\x5E", "\x25\x5F",
+ "\x25\x60", "\x25\x61", "\x25\x62", "\x25\x64",
+ "\x25\x66", "\x25\x68", "\x25\x69", "\x25\x6A",
+ "\x25\x6B", "\x25\x6C", "\x25\x6D", "\x25\x6F",
+ "\x25\x73", "\x21\x2B", "\x21\x2C"
+};
static ssize_t
fun_so_cp50220_encoder(void *statep, const unsigned char *s, size_t l,
@@ -460,22 +463,21 @@ fun_so_cp50220_encoder(void *statep, const unsigned char *s, size_t l,
unsigned char *output0 = o;
unsigned char *sp = statep;
- if (sp[0] == G0_JISX0201_KATAKANA) {
+ if (sp[0] == G0_JISX0201_KATAKANA && sp[2]) {
int c = sp[2] & 0x7F;
- const char *p = tbl0208 + (c - 0x21) * 2;
- if (sp[1] != G0_JISX0208_1983) {
- *o++ = 0x1b;
- *o++ = '$';
- *o++ = 'B';
- }
+ const char *p = tbl0208[c - 0x21];
+ sp[2] = 0;
+ o = iso2022jp_put_state(sp, o, sp[1], G0_JISX0208_1983);
sp[0] = G0_JISX0208_1983;
*o++ = *p++;
if (l == 2 && s[0] == 0x8E) {
if (s[1] == 0xDE) {
+ /* VOICED SOUND MARK */
*o++ = *p + 1;
return o - output0;
}
else if (s[1] == 0xDF && (0x4A <= c && c <= 0x4E)) {
+ /* SEMI-VOICED SOUND MARK */
*o++ = *p + 2;
return o - output0;
}
@@ -484,21 +486,25 @@ fun_so_cp50220_encoder(void *statep, const unsigned char *s, size_t l,
}
if (l == 2 && s[0] == 0x8E) {
- const char *p = tbl0208 + (s[1] - 0xA1) * 2;
if ((0xA1 <= s[1] && s[1] <= 0xB5) ||
(0xC5 <= s[1] && s[1] <= 0xC9) ||
(0xCF <= s[1] && s[1] <= 0xDF)) {
- if (*sp != G0_JISX0208_1983) {
- *o++ = 0x1b;
- *o++ = '$';
- *o++ = 'B';
- *sp = G0_JISX0208_1983;
- }
+ /* May not be followed by a sound mark */
+ const char *p = tbl0208[s[1] - 0xA1];
+ o = iso2022jp_put_state(sp, o, *sp, G0_JISX0208_1983);
*o++ = *p++;
*o++ = *p;
return o - output0;
}
+ if (s[1] > 0xDF) { /* undef */
+ o = iso2022jp_put_state(sp, o, *sp, G0_JISX0201_KATAKANA);
+ *o++ = s[1] & 0x7F;
+ sp[2] = 0;
+ return o - output0;
+ }
+
+ /* Katakana that may be followed by a sound mark */
sp[2] = s[1];
sp[1] = sp[0];
sp[0] = G0_JISX0201_KATAKANA;
@@ -518,23 +524,16 @@ finish_cp50220_encoder(void *statep, unsigned char *o, size_t osize)
if (*sp == G0_ASCII)
return 0;
- if (sp[0] == G0_JISX0201_KATAKANA) {
+ if (sp[0] == G0_JISX0201_KATAKANA && sp[2]) {
int c = sp[2] & 0x7F;
- const char *p = tbl0208 + (c - 0x21) * 2;
- if (sp[1] != G0_JISX0208_1983) {
- *o++ = 0x1b;
- *o++ = '$';
- *o++ = 'B';
- }
+ const char *p = tbl0208[c - 0x21];
+ o = iso2022jp_put_state(sp, o, sp[1], G0_JISX0208_1983);
sp[0] = G0_JISX0208_1983;
*o++ = *p++;
*o++ = *p;
}
- *o++ = 0x1b;
- *o++ = '(';
- *o++ = 'B';
- *sp = G0_ASCII;
+ o = iso2022jp_put_state(sp, o, sp[0], G0_ASCII);
return o - output0;
}
@@ -564,4 +563,3 @@ TRANS_INIT(iso2022)
rb_register_transcoder(&rb_cp50220_encoder);
rb_register_transcoder(&rb_cp50221_encoder);
}
-
diff --git a/enc/trans/single_byte.trans b/enc/trans/single_byte.trans
index 0d5407b918..c326cbebea 100644
--- a/enc/trans/single_byte.trans
+++ b/enc/trans/single_byte.trans
@@ -61,6 +61,7 @@
transcode_tblgen_singlebyte "IBM861"
transcode_tblgen_singlebyte "IBM862"
transcode_tblgen_singlebyte "IBM863"
+ transcode_tblgen_singlebyte "IBM864"
transcode_tblgen_singlebyte "IBM865"
transcode_tblgen_singlebyte "IBM866"
transcode_tblgen_singlebyte "IBM869"
diff --git a/enc/unicode.c b/enc/unicode.c
index 18fba02476..5bc806863e 100644
--- a/enc/unicode.c
+++ b/enc/unicode.c
@@ -655,6 +655,7 @@ onigenc_unicode_get_case_fold_codes_by_str(OnigEncoding enc,
return n;
}
+#ifdef USE_CASE_MAP_API
/* length in bytes for three characters in UTF-32; e.g. needed for ffi (U+FB03) */
#define CASE_MAPPING_SLACK 12
#define MODIFIED (flags |= ONIGENC_CASE_MODIFIED)
@@ -682,15 +683,13 @@ onigenc_unicode_case_map(OnigCaseFoldType* flagP,
*pp += codepoint_length;
if (code <= 'z') { /* ASCII comes first */
- if (code >= 'a' && code <= 'z') {
+ if (code >= 'a' /*&& code <= 'z'*/) {
if (flags & ONIGENC_CASE_UPCASE) {
MODIFIED;
if (flags & ONIGENC_CASE_FOLD_TURKISH_AZERI && code == 'i')
code = I_WITH_DOT_ABOVE;
- else {
- code -= 'a';
- code += 'A';
- }
+ else
+ code -= 'a' - 'A';
}
}
else if (code >= 'A' && code <= 'Z') {
@@ -800,8 +799,8 @@ SpecialsCopy:
*flagP = flags;
return (int )(to - to_start);
}
+#endif
-#if 0
const char onigenc_unicode_version_string[] =
#ifdef ONIG_UNICODE_VERSION_STRING
ONIG_UNICODE_VERSION_STRING
@@ -817,4 +816,3 @@ const int onigenc_unicode_version_number[3] = {
0
#endif
};
-#endif
diff --git a/enc/unicode/15.0.0/casefold.h b/enc/unicode/15.0.0/casefold.h
deleted file mode 100644
index 51120d867d..0000000000
--- a/enc/unicode/15.0.0/casefold.h
+++ /dev/null
@@ -1,7629 +0,0 @@
-/* DO NOT EDIT THIS FILE. */
-/* Generated by enc-case-folding.rb */
-
-#if defined ONIG_UNICODE_VERSION_STRING && !( \
- ONIG_UNICODE_VERSION_MAJOR == 15 && \
- ONIG_UNICODE_VERSION_MINOR == 0 && \
- ONIG_UNICODE_VERSION_TEENY == 0 && \
- 1)
-# error ONIG_UNICODE_VERSION_STRING mismatch
-#endif
-#define ONIG_UNICODE_VERSION_STRING "15.0.0"
-#define ONIG_UNICODE_VERSION_MAJOR 15
-#define ONIG_UNICODE_VERSION_MINOR 0
-#define ONIG_UNICODE_VERSION_TEENY 0
-
-static const CaseFold_11_Type CaseFold_11_Table[] = {
-#define CaseFold (*(CaseFold_11_Type (*)[1528])(CaseFold_11_Table+0))
- {0x0041, {1|F|D, {0x0061}}},
- {0x0042, {1|F|D, {0x0062}}},
- {0x0043, {1|F|D, {0x0063}}},
- {0x0044, {1|F|D, {0x0064}}},
- {0x0045, {1|F|D, {0x0065}}},
- {0x0046, {1|F|D, {0x0066}}},
- {0x0047, {1|F|D, {0x0067}}},
- {0x0048, {1|F|D, {0x0068}}},
- {0x004a, {1|F|D, {0x006a}}},
- {0x004b, {1|F|D, {0x006b}}},
- {0x004c, {1|F|D, {0x006c}}},
- {0x004d, {1|F|D, {0x006d}}},
- {0x004e, {1|F|D, {0x006e}}},
- {0x004f, {1|F|D, {0x006f}}},
- {0x0050, {1|F|D, {0x0070}}},
- {0x0051, {1|F|D, {0x0071}}},
- {0x0052, {1|F|D, {0x0072}}},
- {0x0053, {1|F|D, {0x0073}}},
- {0x0054, {1|F|D, {0x0074}}},
- {0x0055, {1|F|D, {0x0075}}},
- {0x0056, {1|F|D, {0x0076}}},
- {0x0057, {1|F|D, {0x0077}}},
- {0x0058, {1|F|D, {0x0078}}},
- {0x0059, {1|F|D, {0x0079}}},
- {0x005a, {1|F|D, {0x007a}}},
- {0x00b5, {1|F|SU|I(0), {0x03bc}}},
- {0x00c0, {1|F|D, {0x00e0}}},
- {0x00c1, {1|F|D, {0x00e1}}},
- {0x00c2, {1|F|D, {0x00e2}}},
- {0x00c3, {1|F|D, {0x00e3}}},
- {0x00c4, {1|F|D, {0x00e4}}},
- {0x00c5, {1|F|D, {0x00e5}}},
- {0x00c6, {1|F|D, {0x00e6}}},
- {0x00c7, {1|F|D, {0x00e7}}},
- {0x00c8, {1|F|D, {0x00e8}}},
- {0x00c9, {1|F|D, {0x00e9}}},
- {0x00ca, {1|F|D, {0x00ea}}},
- {0x00cb, {1|F|D, {0x00eb}}},
- {0x00cc, {1|F|D, {0x00ec}}},
- {0x00cd, {1|F|D, {0x00ed}}},
- {0x00ce, {1|F|D, {0x00ee}}},
- {0x00cf, {1|F|D, {0x00ef}}},
- {0x00d0, {1|F|D, {0x00f0}}},
- {0x00d1, {1|F|D, {0x00f1}}},
- {0x00d2, {1|F|D, {0x00f2}}},
- {0x00d3, {1|F|D, {0x00f3}}},
- {0x00d4, {1|F|D, {0x00f4}}},
- {0x00d5, {1|F|D, {0x00f5}}},
- {0x00d6, {1|F|D, {0x00f6}}},
- {0x00d8, {1|F|D, {0x00f8}}},
- {0x00d9, {1|F|D, {0x00f9}}},
- {0x00da, {1|F|D, {0x00fa}}},
- {0x00db, {1|F|D, {0x00fb}}},
- {0x00dc, {1|F|D, {0x00fc}}},
- {0x00dd, {1|F|D, {0x00fd}}},
- {0x00de, {1|F|D, {0x00fe}}},
- {0x00df, {2|F|ST|SU|I(1), {0x0073, 0x0073}}},
- {0x0100, {1|F|D, {0x0101}}},
- {0x0102, {1|F|D, {0x0103}}},
- {0x0104, {1|F|D, {0x0105}}},
- {0x0106, {1|F|D, {0x0107}}},
- {0x0108, {1|F|D, {0x0109}}},
- {0x010a, {1|F|D, {0x010b}}},
- {0x010c, {1|F|D, {0x010d}}},
- {0x010e, {1|F|D, {0x010f}}},
- {0x0110, {1|F|D, {0x0111}}},
- {0x0112, {1|F|D, {0x0113}}},
- {0x0114, {1|F|D, {0x0115}}},
- {0x0116, {1|F|D, {0x0117}}},
- {0x0118, {1|F|D, {0x0119}}},
- {0x011a, {1|F|D, {0x011b}}},
- {0x011c, {1|F|D, {0x011d}}},
- {0x011e, {1|F|D, {0x011f}}},
- {0x0120, {1|F|D, {0x0121}}},
- {0x0122, {1|F|D, {0x0123}}},
- {0x0124, {1|F|D, {0x0125}}},
- {0x0126, {1|F|D, {0x0127}}},
- {0x0128, {1|F|D, {0x0129}}},
- {0x012a, {1|F|D, {0x012b}}},
- {0x012c, {1|F|D, {0x012d}}},
- {0x012e, {1|F|D, {0x012f}}},
- {0x0132, {1|F|D, {0x0133}}},
- {0x0134, {1|F|D, {0x0135}}},
- {0x0136, {1|F|D, {0x0137}}},
- {0x0139, {1|F|D, {0x013a}}},
- {0x013b, {1|F|D, {0x013c}}},
- {0x013d, {1|F|D, {0x013e}}},
- {0x013f, {1|F|D, {0x0140}}},
- {0x0141, {1|F|D, {0x0142}}},
- {0x0143, {1|F|D, {0x0144}}},
- {0x0145, {1|F|D, {0x0146}}},
- {0x0147, {1|F|D, {0x0148}}},
- {0x0149, {2|F|SU|I(5), {0x02bc, 0x006e}}},
- {0x014a, {1|F|D, {0x014b}}},
- {0x014c, {1|F|D, {0x014d}}},
- {0x014e, {1|F|D, {0x014f}}},
- {0x0150, {1|F|D, {0x0151}}},
- {0x0152, {1|F|D, {0x0153}}},
- {0x0154, {1|F|D, {0x0155}}},
- {0x0156, {1|F|D, {0x0157}}},
- {0x0158, {1|F|D, {0x0159}}},
- {0x015a, {1|F|D, {0x015b}}},
- {0x015c, {1|F|D, {0x015d}}},
- {0x015e, {1|F|D, {0x015f}}},
- {0x0160, {1|F|D, {0x0161}}},
- {0x0162, {1|F|D, {0x0163}}},
- {0x0164, {1|F|D, {0x0165}}},
- {0x0166, {1|F|D, {0x0167}}},
- {0x0168, {1|F|D, {0x0169}}},
- {0x016a, {1|F|D, {0x016b}}},
- {0x016c, {1|F|D, {0x016d}}},
- {0x016e, {1|F|D, {0x016f}}},
- {0x0170, {1|F|D, {0x0171}}},
- {0x0172, {1|F|D, {0x0173}}},
- {0x0174, {1|F|D, {0x0175}}},
- {0x0176, {1|F|D, {0x0177}}},
- {0x0178, {1|F|D, {0x00ff}}},
- {0x0179, {1|F|D, {0x017a}}},
- {0x017b, {1|F|D, {0x017c}}},
- {0x017d, {1|F|D, {0x017e}}},
- {0x017f, {1|F|SU|I(7), {0x0073}}},
- {0x0181, {1|F|D, {0x0253}}},
- {0x0182, {1|F|D, {0x0183}}},
- {0x0184, {1|F|D, {0x0185}}},
- {0x0186, {1|F|D, {0x0254}}},
- {0x0187, {1|F|D, {0x0188}}},
- {0x0189, {1|F|D, {0x0256}}},
- {0x018a, {1|F|D, {0x0257}}},
- {0x018b, {1|F|D, {0x018c}}},
- {0x018e, {1|F|D, {0x01dd}}},
- {0x018f, {1|F|D, {0x0259}}},
- {0x0190, {1|F|D, {0x025b}}},
- {0x0191, {1|F|D, {0x0192}}},
- {0x0193, {1|F|D, {0x0260}}},
- {0x0194, {1|F|D, {0x0263}}},
- {0x0196, {1|F|D, {0x0269}}},
- {0x0197, {1|F|D, {0x0268}}},
- {0x0198, {1|F|D, {0x0199}}},
- {0x019c, {1|F|D, {0x026f}}},
- {0x019d, {1|F|D, {0x0272}}},
- {0x019f, {1|F|D, {0x0275}}},
- {0x01a0, {1|F|D, {0x01a1}}},
- {0x01a2, {1|F|D, {0x01a3}}},
- {0x01a4, {1|F|D, {0x01a5}}},
- {0x01a6, {1|F|D, {0x0280}}},
- {0x01a7, {1|F|D, {0x01a8}}},
- {0x01a9, {1|F|D, {0x0283}}},
- {0x01ac, {1|F|D, {0x01ad}}},
- {0x01ae, {1|F|D, {0x0288}}},
- {0x01af, {1|F|D, {0x01b0}}},
- {0x01b1, {1|F|D, {0x028a}}},
- {0x01b2, {1|F|D, {0x028b}}},
- {0x01b3, {1|F|D, {0x01b4}}},
- {0x01b5, {1|F|D, {0x01b6}}},
- {0x01b7, {1|F|D, {0x0292}}},
- {0x01b8, {1|F|D, {0x01b9}}},
- {0x01bc, {1|F|D, {0x01bd}}},
- {0x01c4, {1|F|D|ST|I(8), {0x01c6}}},
- {0x01c5, {1|F|D|IT|SU|I(9), {0x01c6}}},
- {0x01c7, {1|F|D|ST|I(12), {0x01c9}}},
- {0x01c8, {1|F|D|IT|SU|I(13), {0x01c9}}},
- {0x01ca, {1|F|D|ST|I(16), {0x01cc}}},
- {0x01cb, {1|F|D|IT|SU|I(17), {0x01cc}}},
- {0x01cd, {1|F|D, {0x01ce}}},
- {0x01cf, {1|F|D, {0x01d0}}},
- {0x01d1, {1|F|D, {0x01d2}}},
- {0x01d3, {1|F|D, {0x01d4}}},
- {0x01d5, {1|F|D, {0x01d6}}},
- {0x01d7, {1|F|D, {0x01d8}}},
- {0x01d9, {1|F|D, {0x01da}}},
- {0x01db, {1|F|D, {0x01dc}}},
- {0x01de, {1|F|D, {0x01df}}},
- {0x01e0, {1|F|D, {0x01e1}}},
- {0x01e2, {1|F|D, {0x01e3}}},
- {0x01e4, {1|F|D, {0x01e5}}},
- {0x01e6, {1|F|D, {0x01e7}}},
- {0x01e8, {1|F|D, {0x01e9}}},
- {0x01ea, {1|F|D, {0x01eb}}},
- {0x01ec, {1|F|D, {0x01ed}}},
- {0x01ee, {1|F|D, {0x01ef}}},
- {0x01f0, {2|F|SU|I(20), {0x006a, 0x030c}}},
- {0x01f1, {1|F|D|ST|I(22), {0x01f3}}},
- {0x01f2, {1|F|D|IT|SU|I(23), {0x01f3}}},
- {0x01f4, {1|F|D, {0x01f5}}},
- {0x01f6, {1|F|D, {0x0195}}},
- {0x01f7, {1|F|D, {0x01bf}}},
- {0x01f8, {1|F|D, {0x01f9}}},
- {0x01fa, {1|F|D, {0x01fb}}},
- {0x01fc, {1|F|D, {0x01fd}}},
- {0x01fe, {1|F|D, {0x01ff}}},
- {0x0200, {1|F|D, {0x0201}}},
- {0x0202, {1|F|D, {0x0203}}},
- {0x0204, {1|F|D, {0x0205}}},
- {0x0206, {1|F|D, {0x0207}}},
- {0x0208, {1|F|D, {0x0209}}},
- {0x020a, {1|F|D, {0x020b}}},
- {0x020c, {1|F|D, {0x020d}}},
- {0x020e, {1|F|D, {0x020f}}},
- {0x0210, {1|F|D, {0x0211}}},
- {0x0212, {1|F|D, {0x0213}}},
- {0x0214, {1|F|D, {0x0215}}},
- {0x0216, {1|F|D, {0x0217}}},
- {0x0218, {1|F|D, {0x0219}}},
- {0x021a, {1|F|D, {0x021b}}},
- {0x021c, {1|F|D, {0x021d}}},
- {0x021e, {1|F|D, {0x021f}}},
- {0x0220, {1|F|D, {0x019e}}},
- {0x0222, {1|F|D, {0x0223}}},
- {0x0224, {1|F|D, {0x0225}}},
- {0x0226, {1|F|D, {0x0227}}},
- {0x0228, {1|F|D, {0x0229}}},
- {0x022a, {1|F|D, {0x022b}}},
- {0x022c, {1|F|D, {0x022d}}},
- {0x022e, {1|F|D, {0x022f}}},
- {0x0230, {1|F|D, {0x0231}}},
- {0x0232, {1|F|D, {0x0233}}},
- {0x023a, {1|F|D, {0x2c65}}},
- {0x023b, {1|F|D, {0x023c}}},
- {0x023d, {1|F|D, {0x019a}}},
- {0x023e, {1|F|D, {0x2c66}}},
- {0x0241, {1|F|D, {0x0242}}},
- {0x0243, {1|F|D, {0x0180}}},
- {0x0244, {1|F|D, {0x0289}}},
- {0x0245, {1|F|D, {0x028c}}},
- {0x0246, {1|F|D, {0x0247}}},
- {0x0248, {1|F|D, {0x0249}}},
- {0x024a, {1|F|D, {0x024b}}},
- {0x024c, {1|F|D, {0x024d}}},
- {0x024e, {1|F|D, {0x024f}}},
- {0x0345, {1|F|SU|I(26), {0x03b9}}},
- {0x0370, {1|F|D, {0x0371}}},
- {0x0372, {1|F|D, {0x0373}}},
- {0x0376, {1|F|D, {0x0377}}},
- {0x037f, {1|F|D, {0x03f3}}},
- {0x0386, {1|F|D, {0x03ac}}},
- {0x0388, {1|F|D, {0x03ad}}},
- {0x0389, {1|F|D, {0x03ae}}},
- {0x038a, {1|F|D, {0x03af}}},
- {0x038c, {1|F|D, {0x03cc}}},
- {0x038e, {1|F|D, {0x03cd}}},
- {0x038f, {1|F|D, {0x03ce}}},
- {0x0390, {3|F|SU|I(27), {0x03b9, 0x0308, 0x0301}}},
- {0x0391, {1|F|D, {0x03b1}}},
- {0x0392, {1|F|D, {0x03b2}}},
- {0x0393, {1|F|D, {0x03b3}}},
- {0x0394, {1|F|D, {0x03b4}}},
- {0x0395, {1|F|D, {0x03b5}}},
- {0x0396, {1|F|D, {0x03b6}}},
- {0x0397, {1|F|D, {0x03b7}}},
- {0x0398, {1|F|D, {0x03b8}}},
- {0x0399, {1|F|D, {0x03b9}}},
- {0x039a, {1|F|D, {0x03ba}}},
- {0x039b, {1|F|D, {0x03bb}}},
- {0x039c, {1|F|D, {0x03bc}}},
- {0x039d, {1|F|D, {0x03bd}}},
- {0x039e, {1|F|D, {0x03be}}},
- {0x039f, {1|F|D, {0x03bf}}},
- {0x03a0, {1|F|D, {0x03c0}}},
- {0x03a1, {1|F|D, {0x03c1}}},
- {0x03a3, {1|F|D, {0x03c3}}},
- {0x03a4, {1|F|D, {0x03c4}}},
- {0x03a5, {1|F|D, {0x03c5}}},
- {0x03a6, {1|F|D, {0x03c6}}},
- {0x03a7, {1|F|D, {0x03c7}}},
- {0x03a8, {1|F|D, {0x03c8}}},
- {0x03a9, {1|F|D, {0x03c9}}},
- {0x03aa, {1|F|D, {0x03ca}}},
- {0x03ab, {1|F|D, {0x03cb}}},
- {0x03b0, {3|F|SU|I(30), {0x03c5, 0x0308, 0x0301}}},
- {0x03c2, {1|F|SU|I(33), {0x03c3}}},
- {0x03cf, {1|F|D, {0x03d7}}},
- {0x03d0, {1|F|SU|I(34), {0x03b2}}},
- {0x03d1, {1|F|SU|I(35), {0x03b8}}},
- {0x03d5, {1|F|SU|I(36), {0x03c6}}},
- {0x03d6, {1|F|SU|I(37), {0x03c0}}},
- {0x03d8, {1|F|D, {0x03d9}}},
- {0x03da, {1|F|D, {0x03db}}},
- {0x03dc, {1|F|D, {0x03dd}}},
- {0x03de, {1|F|D, {0x03df}}},
- {0x03e0, {1|F|D, {0x03e1}}},
- {0x03e2, {1|F|D, {0x03e3}}},
- {0x03e4, {1|F|D, {0x03e5}}},
- {0x03e6, {1|F|D, {0x03e7}}},
- {0x03e8, {1|F|D, {0x03e9}}},
- {0x03ea, {1|F|D, {0x03eb}}},
- {0x03ec, {1|F|D, {0x03ed}}},
- {0x03ee, {1|F|D, {0x03ef}}},
- {0x03f0, {1|F|SU|I(38), {0x03ba}}},
- {0x03f1, {1|F|SU|I(39), {0x03c1}}},
- {0x03f4, {1|F|D, {0x03b8}}},
- {0x03f5, {1|F|SU|I(40), {0x03b5}}},
- {0x03f7, {1|F|D, {0x03f8}}},
- {0x03f9, {1|F|D, {0x03f2}}},
- {0x03fa, {1|F|D, {0x03fb}}},
- {0x03fd, {1|F|D, {0x037b}}},
- {0x03fe, {1|F|D, {0x037c}}},
- {0x03ff, {1|F|D, {0x037d}}},
- {0x0400, {1|F|D, {0x0450}}},
- {0x0401, {1|F|D, {0x0451}}},
- {0x0402, {1|F|D, {0x0452}}},
- {0x0403, {1|F|D, {0x0453}}},
- {0x0404, {1|F|D, {0x0454}}},
- {0x0405, {1|F|D, {0x0455}}},
- {0x0406, {1|F|D, {0x0456}}},
- {0x0407, {1|F|D, {0x0457}}},
- {0x0408, {1|F|D, {0x0458}}},
- {0x0409, {1|F|D, {0x0459}}},
- {0x040a, {1|F|D, {0x045a}}},
- {0x040b, {1|F|D, {0x045b}}},
- {0x040c, {1|F|D, {0x045c}}},
- {0x040d, {1|F|D, {0x045d}}},
- {0x040e, {1|F|D, {0x045e}}},
- {0x040f, {1|F|D, {0x045f}}},
- {0x0410, {1|F|D, {0x0430}}},
- {0x0411, {1|F|D, {0x0431}}},
- {0x0412, {1|F|D, {0x0432}}},
- {0x0413, {1|F|D, {0x0433}}},
- {0x0414, {1|F|D, {0x0434}}},
- {0x0415, {1|F|D, {0x0435}}},
- {0x0416, {1|F|D, {0x0436}}},
- {0x0417, {1|F|D, {0x0437}}},
- {0x0418, {1|F|D, {0x0438}}},
- {0x0419, {1|F|D, {0x0439}}},
- {0x041a, {1|F|D, {0x043a}}},
- {0x041b, {1|F|D, {0x043b}}},
- {0x041c, {1|F|D, {0x043c}}},
- {0x041d, {1|F|D, {0x043d}}},
- {0x041e, {1|F|D, {0x043e}}},
- {0x041f, {1|F|D, {0x043f}}},
- {0x0420, {1|F|D, {0x0440}}},
- {0x0421, {1|F|D, {0x0441}}},
- {0x0422, {1|F|D, {0x0442}}},
- {0x0423, {1|F|D, {0x0443}}},
- {0x0424, {1|F|D, {0x0444}}},
- {0x0425, {1|F|D, {0x0445}}},
- {0x0426, {1|F|D, {0x0446}}},
- {0x0427, {1|F|D, {0x0447}}},
- {0x0428, {1|F|D, {0x0448}}},
- {0x0429, {1|F|D, {0x0449}}},
- {0x042a, {1|F|D, {0x044a}}},
- {0x042b, {1|F|D, {0x044b}}},
- {0x042c, {1|F|D, {0x044c}}},
- {0x042d, {1|F|D, {0x044d}}},
- {0x042e, {1|F|D, {0x044e}}},
- {0x042f, {1|F|D, {0x044f}}},
- {0x0460, {1|F|D, {0x0461}}},
- {0x0462, {1|F|D, {0x0463}}},
- {0x0464, {1|F|D, {0x0465}}},
- {0x0466, {1|F|D, {0x0467}}},
- {0x0468, {1|F|D, {0x0469}}},
- {0x046a, {1|F|D, {0x046b}}},
- {0x046c, {1|F|D, {0x046d}}},
- {0x046e, {1|F|D, {0x046f}}},
- {0x0470, {1|F|D, {0x0471}}},
- {0x0472, {1|F|D, {0x0473}}},
- {0x0474, {1|F|D, {0x0475}}},
- {0x0476, {1|F|D, {0x0477}}},
- {0x0478, {1|F|D, {0x0479}}},
- {0x047a, {1|F|D, {0x047b}}},
- {0x047c, {1|F|D, {0x047d}}},
- {0x047e, {1|F|D, {0x047f}}},
- {0x0480, {1|F|D, {0x0481}}},
- {0x048a, {1|F|D, {0x048b}}},
- {0x048c, {1|F|D, {0x048d}}},
- {0x048e, {1|F|D, {0x048f}}},
- {0x0490, {1|F|D, {0x0491}}},
- {0x0492, {1|F|D, {0x0493}}},
- {0x0494, {1|F|D, {0x0495}}},
- {0x0496, {1|F|D, {0x0497}}},
- {0x0498, {1|F|D, {0x0499}}},
- {0x049a, {1|F|D, {0x049b}}},
- {0x049c, {1|F|D, {0x049d}}},
- {0x049e, {1|F|D, {0x049f}}},
- {0x04a0, {1|F|D, {0x04a1}}},
- {0x04a2, {1|F|D, {0x04a3}}},
- {0x04a4, {1|F|D, {0x04a5}}},
- {0x04a6, {1|F|D, {0x04a7}}},
- {0x04a8, {1|F|D, {0x04a9}}},
- {0x04aa, {1|F|D, {0x04ab}}},
- {0x04ac, {1|F|D, {0x04ad}}},
- {0x04ae, {1|F|D, {0x04af}}},
- {0x04b0, {1|F|D, {0x04b1}}},
- {0x04b2, {1|F|D, {0x04b3}}},
- {0x04b4, {1|F|D, {0x04b5}}},
- {0x04b6, {1|F|D, {0x04b7}}},
- {0x04b8, {1|F|D, {0x04b9}}},
- {0x04ba, {1|F|D, {0x04bb}}},
- {0x04bc, {1|F|D, {0x04bd}}},
- {0x04be, {1|F|D, {0x04bf}}},
- {0x04c0, {1|F|D, {0x04cf}}},
- {0x04c1, {1|F|D, {0x04c2}}},
- {0x04c3, {1|F|D, {0x04c4}}},
- {0x04c5, {1|F|D, {0x04c6}}},
- {0x04c7, {1|F|D, {0x04c8}}},
- {0x04c9, {1|F|D, {0x04ca}}},
- {0x04cb, {1|F|D, {0x04cc}}},
- {0x04cd, {1|F|D, {0x04ce}}},
- {0x04d0, {1|F|D, {0x04d1}}},
- {0x04d2, {1|F|D, {0x04d3}}},
- {0x04d4, {1|F|D, {0x04d5}}},
- {0x04d6, {1|F|D, {0x04d7}}},
- {0x04d8, {1|F|D, {0x04d9}}},
- {0x04da, {1|F|D, {0x04db}}},
- {0x04dc, {1|F|D, {0x04dd}}},
- {0x04de, {1|F|D, {0x04df}}},
- {0x04e0, {1|F|D, {0x04e1}}},
- {0x04e2, {1|F|D, {0x04e3}}},
- {0x04e4, {1|F|D, {0x04e5}}},
- {0x04e6, {1|F|D, {0x04e7}}},
- {0x04e8, {1|F|D, {0x04e9}}},
- {0x04ea, {1|F|D, {0x04eb}}},
- {0x04ec, {1|F|D, {0x04ed}}},
- {0x04ee, {1|F|D, {0x04ef}}},
- {0x04f0, {1|F|D, {0x04f1}}},
- {0x04f2, {1|F|D, {0x04f3}}},
- {0x04f4, {1|F|D, {0x04f5}}},
- {0x04f6, {1|F|D, {0x04f7}}},
- {0x04f8, {1|F|D, {0x04f9}}},
- {0x04fa, {1|F|D, {0x04fb}}},
- {0x04fc, {1|F|D, {0x04fd}}},
- {0x04fe, {1|F|D, {0x04ff}}},
- {0x0500, {1|F|D, {0x0501}}},
- {0x0502, {1|F|D, {0x0503}}},
- {0x0504, {1|F|D, {0x0505}}},
- {0x0506, {1|F|D, {0x0507}}},
- {0x0508, {1|F|D, {0x0509}}},
- {0x050a, {1|F|D, {0x050b}}},
- {0x050c, {1|F|D, {0x050d}}},
- {0x050e, {1|F|D, {0x050f}}},
- {0x0510, {1|F|D, {0x0511}}},
- {0x0512, {1|F|D, {0x0513}}},
- {0x0514, {1|F|D, {0x0515}}},
- {0x0516, {1|F|D, {0x0517}}},
- {0x0518, {1|F|D, {0x0519}}},
- {0x051a, {1|F|D, {0x051b}}},
- {0x051c, {1|F|D, {0x051d}}},
- {0x051e, {1|F|D, {0x051f}}},
- {0x0520, {1|F|D, {0x0521}}},
- {0x0522, {1|F|D, {0x0523}}},
- {0x0524, {1|F|D, {0x0525}}},
- {0x0526, {1|F|D, {0x0527}}},
- {0x0528, {1|F|D, {0x0529}}},
- {0x052a, {1|F|D, {0x052b}}},
- {0x052c, {1|F|D, {0x052d}}},
- {0x052e, {1|F|D, {0x052f}}},
- {0x0531, {1|F|D, {0x0561}}},
- {0x0532, {1|F|D, {0x0562}}},
- {0x0533, {1|F|D, {0x0563}}},
- {0x0534, {1|F|D, {0x0564}}},
- {0x0535, {1|F|D, {0x0565}}},
- {0x0536, {1|F|D, {0x0566}}},
- {0x0537, {1|F|D, {0x0567}}},
- {0x0538, {1|F|D, {0x0568}}},
- {0x0539, {1|F|D, {0x0569}}},
- {0x053a, {1|F|D, {0x056a}}},
- {0x053b, {1|F|D, {0x056b}}},
- {0x053c, {1|F|D, {0x056c}}},
- {0x053d, {1|F|D, {0x056d}}},
- {0x053e, {1|F|D, {0x056e}}},
- {0x053f, {1|F|D, {0x056f}}},
- {0x0540, {1|F|D, {0x0570}}},
- {0x0541, {1|F|D, {0x0571}}},
- {0x0542, {1|F|D, {0x0572}}},
- {0x0543, {1|F|D, {0x0573}}},
- {0x0544, {1|F|D, {0x0574}}},
- {0x0545, {1|F|D, {0x0575}}},
- {0x0546, {1|F|D, {0x0576}}},
- {0x0547, {1|F|D, {0x0577}}},
- {0x0548, {1|F|D, {0x0578}}},
- {0x0549, {1|F|D, {0x0579}}},
- {0x054a, {1|F|D, {0x057a}}},
- {0x054b, {1|F|D, {0x057b}}},
- {0x054c, {1|F|D, {0x057c}}},
- {0x054d, {1|F|D, {0x057d}}},
- {0x054e, {1|F|D, {0x057e}}},
- {0x054f, {1|F|D, {0x057f}}},
- {0x0550, {1|F|D, {0x0580}}},
- {0x0551, {1|F|D, {0x0581}}},
- {0x0552, {1|F|D, {0x0582}}},
- {0x0553, {1|F|D, {0x0583}}},
- {0x0554, {1|F|D, {0x0584}}},
- {0x0555, {1|F|D, {0x0585}}},
- {0x0556, {1|F|D, {0x0586}}},
- {0x0587, {2|F|ST|SU|I(41), {0x0565, 0x0582}}},
- {0x10a0, {1|F|D, {0x2d00}}},
- {0x10a1, {1|F|D, {0x2d01}}},
- {0x10a2, {1|F|D, {0x2d02}}},
- {0x10a3, {1|F|D, {0x2d03}}},
- {0x10a4, {1|F|D, {0x2d04}}},
- {0x10a5, {1|F|D, {0x2d05}}},
- {0x10a6, {1|F|D, {0x2d06}}},
- {0x10a7, {1|F|D, {0x2d07}}},
- {0x10a8, {1|F|D, {0x2d08}}},
- {0x10a9, {1|F|D, {0x2d09}}},
- {0x10aa, {1|F|D, {0x2d0a}}},
- {0x10ab, {1|F|D, {0x2d0b}}},
- {0x10ac, {1|F|D, {0x2d0c}}},
- {0x10ad, {1|F|D, {0x2d0d}}},
- {0x10ae, {1|F|D, {0x2d0e}}},
- {0x10af, {1|F|D, {0x2d0f}}},
- {0x10b0, {1|F|D, {0x2d10}}},
- {0x10b1, {1|F|D, {0x2d11}}},
- {0x10b2, {1|F|D, {0x2d12}}},
- {0x10b3, {1|F|D, {0x2d13}}},
- {0x10b4, {1|F|D, {0x2d14}}},
- {0x10b5, {1|F|D, {0x2d15}}},
- {0x10b6, {1|F|D, {0x2d16}}},
- {0x10b7, {1|F|D, {0x2d17}}},
- {0x10b8, {1|F|D, {0x2d18}}},
- {0x10b9, {1|F|D, {0x2d19}}},
- {0x10ba, {1|F|D, {0x2d1a}}},
- {0x10bb, {1|F|D, {0x2d1b}}},
- {0x10bc, {1|F|D, {0x2d1c}}},
- {0x10bd, {1|F|D, {0x2d1d}}},
- {0x10be, {1|F|D, {0x2d1e}}},
- {0x10bf, {1|F|D, {0x2d1f}}},
- {0x10c0, {1|F|D, {0x2d20}}},
- {0x10c1, {1|F|D, {0x2d21}}},
- {0x10c2, {1|F|D, {0x2d22}}},
- {0x10c3, {1|F|D, {0x2d23}}},
- {0x10c4, {1|F|D, {0x2d24}}},
- {0x10c5, {1|F|D, {0x2d25}}},
- {0x10c7, {1|F|D, {0x2d27}}},
- {0x10cd, {1|F|D, {0x2d2d}}},
- {0x13f8, {1|F|U, {0x13f0}}},
- {0x13f9, {1|F|U, {0x13f1}}},
- {0x13fa, {1|F|U, {0x13f2}}},
- {0x13fb, {1|F|U, {0x13f3}}},
- {0x13fc, {1|F|U, {0x13f4}}},
- {0x13fd, {1|F|U, {0x13f5}}},
- {0x1c80, {1|F|SU|I(45), {0x0432}}},
- {0x1c81, {1|F|SU|I(46), {0x0434}}},
- {0x1c82, {1|F|SU|I(47), {0x043e}}},
- {0x1c83, {1|F|SU|I(48), {0x0441}}},
- {0x1c84, {1|F|SU|I(49), {0x0442}}},
- {0x1c85, {1|F|SU|I(50), {0x0442}}},
- {0x1c86, {1|F|SU|I(51), {0x044a}}},
- {0x1c87, {1|F|SU|I(52), {0x0463}}},
- {0x1c88, {1|F|SU|I(53), {0xa64b}}},
- {0x1c90, {1|F|D, {0x10d0}}},
- {0x1c91, {1|F|D, {0x10d1}}},
- {0x1c92, {1|F|D, {0x10d2}}},
- {0x1c93, {1|F|D, {0x10d3}}},
- {0x1c94, {1|F|D, {0x10d4}}},
- {0x1c95, {1|F|D, {0x10d5}}},
- {0x1c96, {1|F|D, {0x10d6}}},
- {0x1c97, {1|F|D, {0x10d7}}},
- {0x1c98, {1|F|D, {0x10d8}}},
- {0x1c99, {1|F|D, {0x10d9}}},
- {0x1c9a, {1|F|D, {0x10da}}},
- {0x1c9b, {1|F|D, {0x10db}}},
- {0x1c9c, {1|F|D, {0x10dc}}},
- {0x1c9d, {1|F|D, {0x10dd}}},
- {0x1c9e, {1|F|D, {0x10de}}},
- {0x1c9f, {1|F|D, {0x10df}}},
- {0x1ca0, {1|F|D, {0x10e0}}},
- {0x1ca1, {1|F|D, {0x10e1}}},
- {0x1ca2, {1|F|D, {0x10e2}}},
- {0x1ca3, {1|F|D, {0x10e3}}},
- {0x1ca4, {1|F|D, {0x10e4}}},
- {0x1ca5, {1|F|D, {0x10e5}}},
- {0x1ca6, {1|F|D, {0x10e6}}},
- {0x1ca7, {1|F|D, {0x10e7}}},
- {0x1ca8, {1|F|D, {0x10e8}}},
- {0x1ca9, {1|F|D, {0x10e9}}},
- {0x1caa, {1|F|D, {0x10ea}}},
- {0x1cab, {1|F|D, {0x10eb}}},
- {0x1cac, {1|F|D, {0x10ec}}},
- {0x1cad, {1|F|D, {0x10ed}}},
- {0x1cae, {1|F|D, {0x10ee}}},
- {0x1caf, {1|F|D, {0x10ef}}},
- {0x1cb0, {1|F|D, {0x10f0}}},
- {0x1cb1, {1|F|D, {0x10f1}}},
- {0x1cb2, {1|F|D, {0x10f2}}},
- {0x1cb3, {1|F|D, {0x10f3}}},
- {0x1cb4, {1|F|D, {0x10f4}}},
- {0x1cb5, {1|F|D, {0x10f5}}},
- {0x1cb6, {1|F|D, {0x10f6}}},
- {0x1cb7, {1|F|D, {0x10f7}}},
- {0x1cb8, {1|F|D, {0x10f8}}},
- {0x1cb9, {1|F|D, {0x10f9}}},
- {0x1cba, {1|F|D, {0x10fa}}},
- {0x1cbd, {1|F|D, {0x10fd}}},
- {0x1cbe, {1|F|D, {0x10fe}}},
- {0x1cbf, {1|F|D, {0x10ff}}},
- {0x1e00, {1|F|D, {0x1e01}}},
- {0x1e02, {1|F|D, {0x1e03}}},
- {0x1e04, {1|F|D, {0x1e05}}},
- {0x1e06, {1|F|D, {0x1e07}}},
- {0x1e08, {1|F|D, {0x1e09}}},
- {0x1e0a, {1|F|D, {0x1e0b}}},
- {0x1e0c, {1|F|D, {0x1e0d}}},
- {0x1e0e, {1|F|D, {0x1e0f}}},
- {0x1e10, {1|F|D, {0x1e11}}},
- {0x1e12, {1|F|D, {0x1e13}}},
- {0x1e14, {1|F|D, {0x1e15}}},
- {0x1e16, {1|F|D, {0x1e17}}},
- {0x1e18, {1|F|D, {0x1e19}}},
- {0x1e1a, {1|F|D, {0x1e1b}}},
- {0x1e1c, {1|F|D, {0x1e1d}}},
- {0x1e1e, {1|F|D, {0x1e1f}}},
- {0x1e20, {1|F|D, {0x1e21}}},
- {0x1e22, {1|F|D, {0x1e23}}},
- {0x1e24, {1|F|D, {0x1e25}}},
- {0x1e26, {1|F|D, {0x1e27}}},
- {0x1e28, {1|F|D, {0x1e29}}},
- {0x1e2a, {1|F|D, {0x1e2b}}},
- {0x1e2c, {1|F|D, {0x1e2d}}},
- {0x1e2e, {1|F|D, {0x1e2f}}},
- {0x1e30, {1|F|D, {0x1e31}}},
- {0x1e32, {1|F|D, {0x1e33}}},
- {0x1e34, {1|F|D, {0x1e35}}},
- {0x1e36, {1|F|D, {0x1e37}}},
- {0x1e38, {1|F|D, {0x1e39}}},
- {0x1e3a, {1|F|D, {0x1e3b}}},
- {0x1e3c, {1|F|D, {0x1e3d}}},
- {0x1e3e, {1|F|D, {0x1e3f}}},
- {0x1e40, {1|F|D, {0x1e41}}},
- {0x1e42, {1|F|D, {0x1e43}}},
- {0x1e44, {1|F|D, {0x1e45}}},
- {0x1e46, {1|F|D, {0x1e47}}},
- {0x1e48, {1|F|D, {0x1e49}}},
- {0x1e4a, {1|F|D, {0x1e4b}}},
- {0x1e4c, {1|F|D, {0x1e4d}}},
- {0x1e4e, {1|F|D, {0x1e4f}}},
- {0x1e50, {1|F|D, {0x1e51}}},
- {0x1e52, {1|F|D, {0x1e53}}},
- {0x1e54, {1|F|D, {0x1e55}}},
- {0x1e56, {1|F|D, {0x1e57}}},
- {0x1e58, {1|F|D, {0x1e59}}},
- {0x1e5a, {1|F|D, {0x1e5b}}},
- {0x1e5c, {1|F|D, {0x1e5d}}},
- {0x1e5e, {1|F|D, {0x1e5f}}},
- {0x1e60, {1|F|D, {0x1e61}}},
- {0x1e62, {1|F|D, {0x1e63}}},
- {0x1e64, {1|F|D, {0x1e65}}},
- {0x1e66, {1|F|D, {0x1e67}}},
- {0x1e68, {1|F|D, {0x1e69}}},
- {0x1e6a, {1|F|D, {0x1e6b}}},
- {0x1e6c, {1|F|D, {0x1e6d}}},
- {0x1e6e, {1|F|D, {0x1e6f}}},
- {0x1e70, {1|F|D, {0x1e71}}},
- {0x1e72, {1|F|D, {0x1e73}}},
- {0x1e74, {1|F|D, {0x1e75}}},
- {0x1e76, {1|F|D, {0x1e77}}},
- {0x1e78, {1|F|D, {0x1e79}}},
- {0x1e7a, {1|F|D, {0x1e7b}}},
- {0x1e7c, {1|F|D, {0x1e7d}}},
- {0x1e7e, {1|F|D, {0x1e7f}}},
- {0x1e80, {1|F|D, {0x1e81}}},
- {0x1e82, {1|F|D, {0x1e83}}},
- {0x1e84, {1|F|D, {0x1e85}}},
- {0x1e86, {1|F|D, {0x1e87}}},
- {0x1e88, {1|F|D, {0x1e89}}},
- {0x1e8a, {1|F|D, {0x1e8b}}},
- {0x1e8c, {1|F|D, {0x1e8d}}},
- {0x1e8e, {1|F|D, {0x1e8f}}},
- {0x1e90, {1|F|D, {0x1e91}}},
- {0x1e92, {1|F|D, {0x1e93}}},
- {0x1e94, {1|F|D, {0x1e95}}},
- {0x1e96, {2|F|SU|I(54), {0x0068, 0x0331}}},
- {0x1e97, {2|F|SU|I(56), {0x0074, 0x0308}}},
- {0x1e98, {2|F|SU|I(58), {0x0077, 0x030a}}},
- {0x1e99, {2|F|SU|I(60), {0x0079, 0x030a}}},
- {0x1e9a, {2|F|SU|I(62), {0x0061, 0x02be}}},
- {0x1e9b, {1|F|SU|I(64), {0x1e61}}},
- {0x1e9e, {2|F|SL|I(65), {0x0073, 0x0073}}},
- {0x1ea0, {1|F|D, {0x1ea1}}},
- {0x1ea2, {1|F|D, {0x1ea3}}},
- {0x1ea4, {1|F|D, {0x1ea5}}},
- {0x1ea6, {1|F|D, {0x1ea7}}},
- {0x1ea8, {1|F|D, {0x1ea9}}},
- {0x1eaa, {1|F|D, {0x1eab}}},
- {0x1eac, {1|F|D, {0x1ead}}},
- {0x1eae, {1|F|D, {0x1eaf}}},
- {0x1eb0, {1|F|D, {0x1eb1}}},
- {0x1eb2, {1|F|D, {0x1eb3}}},
- {0x1eb4, {1|F|D, {0x1eb5}}},
- {0x1eb6, {1|F|D, {0x1eb7}}},
- {0x1eb8, {1|F|D, {0x1eb9}}},
- {0x1eba, {1|F|D, {0x1ebb}}},
- {0x1ebc, {1|F|D, {0x1ebd}}},
- {0x1ebe, {1|F|D, {0x1ebf}}},
- {0x1ec0, {1|F|D, {0x1ec1}}},
- {0x1ec2, {1|F|D, {0x1ec3}}},
- {0x1ec4, {1|F|D, {0x1ec5}}},
- {0x1ec6, {1|F|D, {0x1ec7}}},
- {0x1ec8, {1|F|D, {0x1ec9}}},
- {0x1eca, {1|F|D, {0x1ecb}}},
- {0x1ecc, {1|F|D, {0x1ecd}}},
- {0x1ece, {1|F|D, {0x1ecf}}},
- {0x1ed0, {1|F|D, {0x1ed1}}},
- {0x1ed2, {1|F|D, {0x1ed3}}},
- {0x1ed4, {1|F|D, {0x1ed5}}},
- {0x1ed6, {1|F|D, {0x1ed7}}},
- {0x1ed8, {1|F|D, {0x1ed9}}},
- {0x1eda, {1|F|D, {0x1edb}}},
- {0x1edc, {1|F|D, {0x1edd}}},
- {0x1ede, {1|F|D, {0x1edf}}},
- {0x1ee0, {1|F|D, {0x1ee1}}},
- {0x1ee2, {1|F|D, {0x1ee3}}},
- {0x1ee4, {1|F|D, {0x1ee5}}},
- {0x1ee6, {1|F|D, {0x1ee7}}},
- {0x1ee8, {1|F|D, {0x1ee9}}},
- {0x1eea, {1|F|D, {0x1eeb}}},
- {0x1eec, {1|F|D, {0x1eed}}},
- {0x1eee, {1|F|D, {0x1eef}}},
- {0x1ef0, {1|F|D, {0x1ef1}}},
- {0x1ef2, {1|F|D, {0x1ef3}}},
- {0x1ef4, {1|F|D, {0x1ef5}}},
- {0x1ef6, {1|F|D, {0x1ef7}}},
- {0x1ef8, {1|F|D, {0x1ef9}}},
- {0x1efa, {1|F|D, {0x1efb}}},
- {0x1efc, {1|F|D, {0x1efd}}},
- {0x1efe, {1|F|D, {0x1eff}}},
- {0x1f08, {1|F|D, {0x1f00}}},
- {0x1f09, {1|F|D, {0x1f01}}},
- {0x1f0a, {1|F|D, {0x1f02}}},
- {0x1f0b, {1|F|D, {0x1f03}}},
- {0x1f0c, {1|F|D, {0x1f04}}},
- {0x1f0d, {1|F|D, {0x1f05}}},
- {0x1f0e, {1|F|D, {0x1f06}}},
- {0x1f0f, {1|F|D, {0x1f07}}},
- {0x1f18, {1|F|D, {0x1f10}}},
- {0x1f19, {1|F|D, {0x1f11}}},
- {0x1f1a, {1|F|D, {0x1f12}}},
- {0x1f1b, {1|F|D, {0x1f13}}},
- {0x1f1c, {1|F|D, {0x1f14}}},
- {0x1f1d, {1|F|D, {0x1f15}}},
- {0x1f28, {1|F|D, {0x1f20}}},
- {0x1f29, {1|F|D, {0x1f21}}},
- {0x1f2a, {1|F|D, {0x1f22}}},
- {0x1f2b, {1|F|D, {0x1f23}}},
- {0x1f2c, {1|F|D, {0x1f24}}},
- {0x1f2d, {1|F|D, {0x1f25}}},
- {0x1f2e, {1|F|D, {0x1f26}}},
- {0x1f2f, {1|F|D, {0x1f27}}},
- {0x1f38, {1|F|D, {0x1f30}}},
- {0x1f39, {1|F|D, {0x1f31}}},
- {0x1f3a, {1|F|D, {0x1f32}}},
- {0x1f3b, {1|F|D, {0x1f33}}},
- {0x1f3c, {1|F|D, {0x1f34}}},
- {0x1f3d, {1|F|D, {0x1f35}}},
- {0x1f3e, {1|F|D, {0x1f36}}},
- {0x1f3f, {1|F|D, {0x1f37}}},
- {0x1f48, {1|F|D, {0x1f40}}},
- {0x1f49, {1|F|D, {0x1f41}}},
- {0x1f4a, {1|F|D, {0x1f42}}},
- {0x1f4b, {1|F|D, {0x1f43}}},
- {0x1f4c, {1|F|D, {0x1f44}}},
- {0x1f4d, {1|F|D, {0x1f45}}},
- {0x1f50, {2|F|SU|I(66), {0x03c5, 0x0313}}},
- {0x1f52, {3|F|SU|I(68), {0x03c5, 0x0313, 0x0300}}},
- {0x1f54, {3|F|SU|I(71), {0x03c5, 0x0313, 0x0301}}},
- {0x1f56, {3|F|SU|I(74), {0x03c5, 0x0313, 0x0342}}},
- {0x1f59, {1|F|D, {0x1f51}}},
- {0x1f5b, {1|F|D, {0x1f53}}},
- {0x1f5d, {1|F|D, {0x1f55}}},
- {0x1f5f, {1|F|D, {0x1f57}}},
- {0x1f68, {1|F|D, {0x1f60}}},
- {0x1f69, {1|F|D, {0x1f61}}},
- {0x1f6a, {1|F|D, {0x1f62}}},
- {0x1f6b, {1|F|D, {0x1f63}}},
- {0x1f6c, {1|F|D, {0x1f64}}},
- {0x1f6d, {1|F|D, {0x1f65}}},
- {0x1f6e, {1|F|D, {0x1f66}}},
- {0x1f6f, {1|F|D, {0x1f67}}},
- {0x1f80, {2|F|ST|SU|I(77), {0x1f00, 0x03b9}}},
- {0x1f81, {2|F|ST|SU|I(80), {0x1f01, 0x03b9}}},
- {0x1f82, {2|F|ST|SU|I(83), {0x1f02, 0x03b9}}},
- {0x1f83, {2|F|ST|SU|I(86), {0x1f03, 0x03b9}}},
- {0x1f84, {2|F|ST|SU|I(89), {0x1f04, 0x03b9}}},
- {0x1f85, {2|F|ST|SU|I(92), {0x1f05, 0x03b9}}},
- {0x1f86, {2|F|ST|SU|I(95), {0x1f06, 0x03b9}}},
- {0x1f87, {2|F|ST|SU|I(98), {0x1f07, 0x03b9}}},
- {0x1f88, {2|F|IT|SL|SU|I(101), {0x1f00, 0x03b9}}},
- {0x1f89, {2|F|IT|SL|SU|I(106), {0x1f01, 0x03b9}}},
- {0x1f8a, {2|F|IT|SL|SU|I(111), {0x1f02, 0x03b9}}},
- {0x1f8b, {2|F|IT|SL|SU|I(116), {0x1f03, 0x03b9}}},
- {0x1f8c, {2|F|IT|SL|SU|I(121), {0x1f04, 0x03b9}}},
- {0x1f8d, {2|F|IT|SL|SU|I(126), {0x1f05, 0x03b9}}},
- {0x1f8e, {2|F|IT|SL|SU|I(131), {0x1f06, 0x03b9}}},
- {0x1f8f, {2|F|IT|SL|SU|I(136), {0x1f07, 0x03b9}}},
- {0x1f90, {2|F|ST|SU|I(141), {0x1f20, 0x03b9}}},
- {0x1f91, {2|F|ST|SU|I(144), {0x1f21, 0x03b9}}},
- {0x1f92, {2|F|ST|SU|I(147), {0x1f22, 0x03b9}}},
- {0x1f93, {2|F|ST|SU|I(150), {0x1f23, 0x03b9}}},
- {0x1f94, {2|F|ST|SU|I(153), {0x1f24, 0x03b9}}},
- {0x1f95, {2|F|ST|SU|I(156), {0x1f25, 0x03b9}}},
- {0x1f96, {2|F|ST|SU|I(159), {0x1f26, 0x03b9}}},
- {0x1f97, {2|F|ST|SU|I(162), {0x1f27, 0x03b9}}},
- {0x1f98, {2|F|IT|SL|SU|I(165), {0x1f20, 0x03b9}}},
- {0x1f99, {2|F|IT|SL|SU|I(170), {0x1f21, 0x03b9}}},
- {0x1f9a, {2|F|IT|SL|SU|I(175), {0x1f22, 0x03b9}}},
- {0x1f9b, {2|F|IT|SL|SU|I(180), {0x1f23, 0x03b9}}},
- {0x1f9c, {2|F|IT|SL|SU|I(185), {0x1f24, 0x03b9}}},
- {0x1f9d, {2|F|IT|SL|SU|I(190), {0x1f25, 0x03b9}}},
- {0x1f9e, {2|F|IT|SL|SU|I(195), {0x1f26, 0x03b9}}},
- {0x1f9f, {2|F|IT|SL|SU|I(200), {0x1f27, 0x03b9}}},
- {0x1fa0, {2|F|ST|SU|I(205), {0x1f60, 0x03b9}}},
- {0x1fa1, {2|F|ST|SU|I(208), {0x1f61, 0x03b9}}},
- {0x1fa2, {2|F|ST|SU|I(211), {0x1f62, 0x03b9}}},
- {0x1fa3, {2|F|ST|SU|I(214), {0x1f63, 0x03b9}}},
- {0x1fa4, {2|F|ST|SU|I(217), {0x1f64, 0x03b9}}},
- {0x1fa5, {2|F|ST|SU|I(220), {0x1f65, 0x03b9}}},
- {0x1fa6, {2|F|ST|SU|I(223), {0x1f66, 0x03b9}}},
- {0x1fa7, {2|F|ST|SU|I(226), {0x1f67, 0x03b9}}},
- {0x1fa8, {2|F|IT|SL|SU|I(229), {0x1f60, 0x03b9}}},
- {0x1fa9, {2|F|IT|SL|SU|I(234), {0x1f61, 0x03b9}}},
- {0x1faa, {2|F|IT|SL|SU|I(239), {0x1f62, 0x03b9}}},
- {0x1fab, {2|F|IT|SL|SU|I(244), {0x1f63, 0x03b9}}},
- {0x1fac, {2|F|IT|SL|SU|I(249), {0x1f64, 0x03b9}}},
- {0x1fad, {2|F|IT|SL|SU|I(254), {0x1f65, 0x03b9}}},
- {0x1fae, {2|F|IT|SL|SU|I(259), {0x1f66, 0x03b9}}},
- {0x1faf, {2|F|IT|SL|SU|I(264), {0x1f67, 0x03b9}}},
- {0x1fb2, {2|F|ST|SU|I(269), {0x1f70, 0x03b9}}},
- {0x1fb3, {2|F|ST|SU|I(273), {0x03b1, 0x03b9}}},
- {0x1fb4, {2|F|ST|SU|I(276), {0x03ac, 0x03b9}}},
- {0x1fb6, {2|F|SU|I(280), {0x03b1, 0x0342}}},
- {0x1fb7, {3|F|ST|SU|I(282), {0x03b1, 0x0342, 0x03b9}}},
- {0x1fb8, {1|F|D, {0x1fb0}}},
- {0x1fb9, {1|F|D, {0x1fb1}}},
- {0x1fba, {1|F|D, {0x1f70}}},
- {0x1fbb, {1|F|D, {0x1f71}}},
- {0x1fbc, {2|F|IT|SL|SU|I(288), {0x03b1, 0x03b9}}},
- {0x1fbe, {1|F|SU|I(293), {0x03b9}}},
- {0x1fc2, {2|F|ST|SU|I(294), {0x1f74, 0x03b9}}},
- {0x1fc3, {2|F|ST|SU|I(298), {0x03b7, 0x03b9}}},
- {0x1fc4, {2|F|ST|SU|I(301), {0x03ae, 0x03b9}}},
- {0x1fc6, {2|F|SU|I(305), {0x03b7, 0x0342}}},
- {0x1fc7, {3|F|ST|SU|I(307), {0x03b7, 0x0342, 0x03b9}}},
- {0x1fc8, {1|F|D, {0x1f72}}},
- {0x1fc9, {1|F|D, {0x1f73}}},
- {0x1fca, {1|F|D, {0x1f74}}},
- {0x1fcb, {1|F|D, {0x1f75}}},
- {0x1fcc, {2|F|IT|SL|SU|I(313), {0x03b7, 0x03b9}}},
- {0x1fd2, {3|F|SU|I(318), {0x03b9, 0x0308, 0x0300}}},
- {0x1fd3, {3|F|SU|I(321), {0x03b9, 0x0308, 0x0301}}},
- {0x1fd6, {2|F|SU|I(324), {0x03b9, 0x0342}}},
- {0x1fd7, {3|F|SU|I(326), {0x03b9, 0x0308, 0x0342}}},
- {0x1fd8, {1|F|D, {0x1fd0}}},
- {0x1fd9, {1|F|D, {0x1fd1}}},
- {0x1fda, {1|F|D, {0x1f76}}},
- {0x1fdb, {1|F|D, {0x1f77}}},
- {0x1fe2, {3|F|SU|I(329), {0x03c5, 0x0308, 0x0300}}},
- {0x1fe3, {3|F|SU|I(332), {0x03c5, 0x0308, 0x0301}}},
- {0x1fe4, {2|F|SU|I(335), {0x03c1, 0x0313}}},
- {0x1fe6, {2|F|SU|I(337), {0x03c5, 0x0342}}},
- {0x1fe7, {3|F|SU|I(339), {0x03c5, 0x0308, 0x0342}}},
- {0x1fe8, {1|F|D, {0x1fe0}}},
- {0x1fe9, {1|F|D, {0x1fe1}}},
- {0x1fea, {1|F|D, {0x1f7a}}},
- {0x1feb, {1|F|D, {0x1f7b}}},
- {0x1fec, {1|F|D, {0x1fe5}}},
- {0x1ff2, {2|F|ST|SU|I(342), {0x1f7c, 0x03b9}}},
- {0x1ff3, {2|F|ST|SU|I(346), {0x03c9, 0x03b9}}},
- {0x1ff4, {2|F|ST|SU|I(349), {0x03ce, 0x03b9}}},
- {0x1ff6, {2|F|SU|I(353), {0x03c9, 0x0342}}},
- {0x1ff7, {3|F|ST|SU|I(355), {0x03c9, 0x0342, 0x03b9}}},
- {0x1ff8, {1|F|D, {0x1f78}}},
- {0x1ff9, {1|F|D, {0x1f79}}},
- {0x1ffa, {1|F|D, {0x1f7c}}},
- {0x1ffb, {1|F|D, {0x1f7d}}},
- {0x1ffc, {2|F|IT|SL|SU|I(361), {0x03c9, 0x03b9}}},
- {0x2126, {1|F|D, {0x03c9}}},
- {0x212a, {1|F|D, {0x006b}}},
- {0x212b, {1|F|D, {0x00e5}}},
- {0x2132, {1|F|D, {0x214e}}},
- {0x2160, {1|F|D, {0x2170}}},
- {0x2161, {1|F|D, {0x2171}}},
- {0x2162, {1|F|D, {0x2172}}},
- {0x2163, {1|F|D, {0x2173}}},
- {0x2164, {1|F|D, {0x2174}}},
- {0x2165, {1|F|D, {0x2175}}},
- {0x2166, {1|F|D, {0x2176}}},
- {0x2167, {1|F|D, {0x2177}}},
- {0x2168, {1|F|D, {0x2178}}},
- {0x2169, {1|F|D, {0x2179}}},
- {0x216a, {1|F|D, {0x217a}}},
- {0x216b, {1|F|D, {0x217b}}},
- {0x216c, {1|F|D, {0x217c}}},
- {0x216d, {1|F|D, {0x217d}}},
- {0x216e, {1|F|D, {0x217e}}},
- {0x216f, {1|F|D, {0x217f}}},
- {0x2183, {1|F|D, {0x2184}}},
- {0x24b6, {1|F|D, {0x24d0}}},
- {0x24b7, {1|F|D, {0x24d1}}},
- {0x24b8, {1|F|D, {0x24d2}}},
- {0x24b9, {1|F|D, {0x24d3}}},
- {0x24ba, {1|F|D, {0x24d4}}},
- {0x24bb, {1|F|D, {0x24d5}}},
- {0x24bc, {1|F|D, {0x24d6}}},
- {0x24bd, {1|F|D, {0x24d7}}},
- {0x24be, {1|F|D, {0x24d8}}},
- {0x24bf, {1|F|D, {0x24d9}}},
- {0x24c0, {1|F|D, {0x24da}}},
- {0x24c1, {1|F|D, {0x24db}}},
- {0x24c2, {1|F|D, {0x24dc}}},
- {0x24c3, {1|F|D, {0x24dd}}},
- {0x24c4, {1|F|D, {0x24de}}},
- {0x24c5, {1|F|D, {0x24df}}},
- {0x24c6, {1|F|D, {0x24e0}}},
- {0x24c7, {1|F|D, {0x24e1}}},
- {0x24c8, {1|F|D, {0x24e2}}},
- {0x24c9, {1|F|D, {0x24e3}}},
- {0x24ca, {1|F|D, {0x24e4}}},
- {0x24cb, {1|F|D, {0x24e5}}},
- {0x24cc, {1|F|D, {0x24e6}}},
- {0x24cd, {1|F|D, {0x24e7}}},
- {0x24ce, {1|F|D, {0x24e8}}},
- {0x24cf, {1|F|D, {0x24e9}}},
- {0x2c00, {1|F|D, {0x2c30}}},
- {0x2c01, {1|F|D, {0x2c31}}},
- {0x2c02, {1|F|D, {0x2c32}}},
- {0x2c03, {1|F|D, {0x2c33}}},
- {0x2c04, {1|F|D, {0x2c34}}},
- {0x2c05, {1|F|D, {0x2c35}}},
- {0x2c06, {1|F|D, {0x2c36}}},
- {0x2c07, {1|F|D, {0x2c37}}},
- {0x2c08, {1|F|D, {0x2c38}}},
- {0x2c09, {1|F|D, {0x2c39}}},
- {0x2c0a, {1|F|D, {0x2c3a}}},
- {0x2c0b, {1|F|D, {0x2c3b}}},
- {0x2c0c, {1|F|D, {0x2c3c}}},
- {0x2c0d, {1|F|D, {0x2c3d}}},
- {0x2c0e, {1|F|D, {0x2c3e}}},
- {0x2c0f, {1|F|D, {0x2c3f}}},
- {0x2c10, {1|F|D, {0x2c40}}},
- {0x2c11, {1|F|D, {0x2c41}}},
- {0x2c12, {1|F|D, {0x2c42}}},
- {0x2c13, {1|F|D, {0x2c43}}},
- {0x2c14, {1|F|D, {0x2c44}}},
- {0x2c15, {1|F|D, {0x2c45}}},
- {0x2c16, {1|F|D, {0x2c46}}},
- {0x2c17, {1|F|D, {0x2c47}}},
- {0x2c18, {1|F|D, {0x2c48}}},
- {0x2c19, {1|F|D, {0x2c49}}},
- {0x2c1a, {1|F|D, {0x2c4a}}},
- {0x2c1b, {1|F|D, {0x2c4b}}},
- {0x2c1c, {1|F|D, {0x2c4c}}},
- {0x2c1d, {1|F|D, {0x2c4d}}},
- {0x2c1e, {1|F|D, {0x2c4e}}},
- {0x2c1f, {1|F|D, {0x2c4f}}},
- {0x2c20, {1|F|D, {0x2c50}}},
- {0x2c21, {1|F|D, {0x2c51}}},
- {0x2c22, {1|F|D, {0x2c52}}},
- {0x2c23, {1|F|D, {0x2c53}}},
- {0x2c24, {1|F|D, {0x2c54}}},
- {0x2c25, {1|F|D, {0x2c55}}},
- {0x2c26, {1|F|D, {0x2c56}}},
- {0x2c27, {1|F|D, {0x2c57}}},
- {0x2c28, {1|F|D, {0x2c58}}},
- {0x2c29, {1|F|D, {0x2c59}}},
- {0x2c2a, {1|F|D, {0x2c5a}}},
- {0x2c2b, {1|F|D, {0x2c5b}}},
- {0x2c2c, {1|F|D, {0x2c5c}}},
- {0x2c2d, {1|F|D, {0x2c5d}}},
- {0x2c2e, {1|F|D, {0x2c5e}}},
- {0x2c2f, {1|F|D, {0x2c5f}}},
- {0x2c60, {1|F|D, {0x2c61}}},
- {0x2c62, {1|F|D, {0x026b}}},
- {0x2c63, {1|F|D, {0x1d7d}}},
- {0x2c64, {1|F|D, {0x027d}}},
- {0x2c67, {1|F|D, {0x2c68}}},
- {0x2c69, {1|F|D, {0x2c6a}}},
- {0x2c6b, {1|F|D, {0x2c6c}}},
- {0x2c6d, {1|F|D, {0x0251}}},
- {0x2c6e, {1|F|D, {0x0271}}},
- {0x2c6f, {1|F|D, {0x0250}}},
- {0x2c70, {1|F|D, {0x0252}}},
- {0x2c72, {1|F|D, {0x2c73}}},
- {0x2c75, {1|F|D, {0x2c76}}},
- {0x2c7e, {1|F|D, {0x023f}}},
- {0x2c7f, {1|F|D, {0x0240}}},
- {0x2c80, {1|F|D, {0x2c81}}},
- {0x2c82, {1|F|D, {0x2c83}}},
- {0x2c84, {1|F|D, {0x2c85}}},
- {0x2c86, {1|F|D, {0x2c87}}},
- {0x2c88, {1|F|D, {0x2c89}}},
- {0x2c8a, {1|F|D, {0x2c8b}}},
- {0x2c8c, {1|F|D, {0x2c8d}}},
- {0x2c8e, {1|F|D, {0x2c8f}}},
- {0x2c90, {1|F|D, {0x2c91}}},
- {0x2c92, {1|F|D, {0x2c93}}},
- {0x2c94, {1|F|D, {0x2c95}}},
- {0x2c96, {1|F|D, {0x2c97}}},
- {0x2c98, {1|F|D, {0x2c99}}},
- {0x2c9a, {1|F|D, {0x2c9b}}},
- {0x2c9c, {1|F|D, {0x2c9d}}},
- {0x2c9e, {1|F|D, {0x2c9f}}},
- {0x2ca0, {1|F|D, {0x2ca1}}},
- {0x2ca2, {1|F|D, {0x2ca3}}},
- {0x2ca4, {1|F|D, {0x2ca5}}},
- {0x2ca6, {1|F|D, {0x2ca7}}},
- {0x2ca8, {1|F|D, {0x2ca9}}},
- {0x2caa, {1|F|D, {0x2cab}}},
- {0x2cac, {1|F|D, {0x2cad}}},
- {0x2cae, {1|F|D, {0x2caf}}},
- {0x2cb0, {1|F|D, {0x2cb1}}},
- {0x2cb2, {1|F|D, {0x2cb3}}},
- {0x2cb4, {1|F|D, {0x2cb5}}},
- {0x2cb6, {1|F|D, {0x2cb7}}},
- {0x2cb8, {1|F|D, {0x2cb9}}},
- {0x2cba, {1|F|D, {0x2cbb}}},
- {0x2cbc, {1|F|D, {0x2cbd}}},
- {0x2cbe, {1|F|D, {0x2cbf}}},
- {0x2cc0, {1|F|D, {0x2cc1}}},
- {0x2cc2, {1|F|D, {0x2cc3}}},
- {0x2cc4, {1|F|D, {0x2cc5}}},
- {0x2cc6, {1|F|D, {0x2cc7}}},
- {0x2cc8, {1|F|D, {0x2cc9}}},
- {0x2cca, {1|F|D, {0x2ccb}}},
- {0x2ccc, {1|F|D, {0x2ccd}}},
- {0x2cce, {1|F|D, {0x2ccf}}},
- {0x2cd0, {1|F|D, {0x2cd1}}},
- {0x2cd2, {1|F|D, {0x2cd3}}},
- {0x2cd4, {1|F|D, {0x2cd5}}},
- {0x2cd6, {1|F|D, {0x2cd7}}},
- {0x2cd8, {1|F|D, {0x2cd9}}},
- {0x2cda, {1|F|D, {0x2cdb}}},
- {0x2cdc, {1|F|D, {0x2cdd}}},
- {0x2cde, {1|F|D, {0x2cdf}}},
- {0x2ce0, {1|F|D, {0x2ce1}}},
- {0x2ce2, {1|F|D, {0x2ce3}}},
- {0x2ceb, {1|F|D, {0x2cec}}},
- {0x2ced, {1|F|D, {0x2cee}}},
- {0x2cf2, {1|F|D, {0x2cf3}}},
- {0xa640, {1|F|D, {0xa641}}},
- {0xa642, {1|F|D, {0xa643}}},
- {0xa644, {1|F|D, {0xa645}}},
- {0xa646, {1|F|D, {0xa647}}},
- {0xa648, {1|F|D, {0xa649}}},
- {0xa64a, {1|F|D, {0xa64b}}},
- {0xa64c, {1|F|D, {0xa64d}}},
- {0xa64e, {1|F|D, {0xa64f}}},
- {0xa650, {1|F|D, {0xa651}}},
- {0xa652, {1|F|D, {0xa653}}},
- {0xa654, {1|F|D, {0xa655}}},
- {0xa656, {1|F|D, {0xa657}}},
- {0xa658, {1|F|D, {0xa659}}},
- {0xa65a, {1|F|D, {0xa65b}}},
- {0xa65c, {1|F|D, {0xa65d}}},
- {0xa65e, {1|F|D, {0xa65f}}},
- {0xa660, {1|F|D, {0xa661}}},
- {0xa662, {1|F|D, {0xa663}}},
- {0xa664, {1|F|D, {0xa665}}},
- {0xa666, {1|F|D, {0xa667}}},
- {0xa668, {1|F|D, {0xa669}}},
- {0xa66a, {1|F|D, {0xa66b}}},
- {0xa66c, {1|F|D, {0xa66d}}},
- {0xa680, {1|F|D, {0xa681}}},
- {0xa682, {1|F|D, {0xa683}}},
- {0xa684, {1|F|D, {0xa685}}},
- {0xa686, {1|F|D, {0xa687}}},
- {0xa688, {1|F|D, {0xa689}}},
- {0xa68a, {1|F|D, {0xa68b}}},
- {0xa68c, {1|F|D, {0xa68d}}},
- {0xa68e, {1|F|D, {0xa68f}}},
- {0xa690, {1|F|D, {0xa691}}},
- {0xa692, {1|F|D, {0xa693}}},
- {0xa694, {1|F|D, {0xa695}}},
- {0xa696, {1|F|D, {0xa697}}},
- {0xa698, {1|F|D, {0xa699}}},
- {0xa69a, {1|F|D, {0xa69b}}},
- {0xa722, {1|F|D, {0xa723}}},
- {0xa724, {1|F|D, {0xa725}}},
- {0xa726, {1|F|D, {0xa727}}},
- {0xa728, {1|F|D, {0xa729}}},
- {0xa72a, {1|F|D, {0xa72b}}},
- {0xa72c, {1|F|D, {0xa72d}}},
- {0xa72e, {1|F|D, {0xa72f}}},
- {0xa732, {1|F|D, {0xa733}}},
- {0xa734, {1|F|D, {0xa735}}},
- {0xa736, {1|F|D, {0xa737}}},
- {0xa738, {1|F|D, {0xa739}}},
- {0xa73a, {1|F|D, {0xa73b}}},
- {0xa73c, {1|F|D, {0xa73d}}},
- {0xa73e, {1|F|D, {0xa73f}}},
- {0xa740, {1|F|D, {0xa741}}},
- {0xa742, {1|F|D, {0xa743}}},
- {0xa744, {1|F|D, {0xa745}}},
- {0xa746, {1|F|D, {0xa747}}},
- {0xa748, {1|F|D, {0xa749}}},
- {0xa74a, {1|F|D, {0xa74b}}},
- {0xa74c, {1|F|D, {0xa74d}}},
- {0xa74e, {1|F|D, {0xa74f}}},
- {0xa750, {1|F|D, {0xa751}}},
- {0xa752, {1|F|D, {0xa753}}},
- {0xa754, {1|F|D, {0xa755}}},
- {0xa756, {1|F|D, {0xa757}}},
- {0xa758, {1|F|D, {0xa759}}},
- {0xa75a, {1|F|D, {0xa75b}}},
- {0xa75c, {1|F|D, {0xa75d}}},
- {0xa75e, {1|F|D, {0xa75f}}},
- {0xa760, {1|F|D, {0xa761}}},
- {0xa762, {1|F|D, {0xa763}}},
- {0xa764, {1|F|D, {0xa765}}},
- {0xa766, {1|F|D, {0xa767}}},
- {0xa768, {1|F|D, {0xa769}}},
- {0xa76a, {1|F|D, {0xa76b}}},
- {0xa76c, {1|F|D, {0xa76d}}},
- {0xa76e, {1|F|D, {0xa76f}}},
- {0xa779, {1|F|D, {0xa77a}}},
- {0xa77b, {1|F|D, {0xa77c}}},
- {0xa77d, {1|F|D, {0x1d79}}},
- {0xa77e, {1|F|D, {0xa77f}}},
- {0xa780, {1|F|D, {0xa781}}},
- {0xa782, {1|F|D, {0xa783}}},
- {0xa784, {1|F|D, {0xa785}}},
- {0xa786, {1|F|D, {0xa787}}},
- {0xa78b, {1|F|D, {0xa78c}}},
- {0xa78d, {1|F|D, {0x0265}}},
- {0xa790, {1|F|D, {0xa791}}},
- {0xa792, {1|F|D, {0xa793}}},
- {0xa796, {1|F|D, {0xa797}}},
- {0xa798, {1|F|D, {0xa799}}},
- {0xa79a, {1|F|D, {0xa79b}}},
- {0xa79c, {1|F|D, {0xa79d}}},
- {0xa79e, {1|F|D, {0xa79f}}},
- {0xa7a0, {1|F|D, {0xa7a1}}},
- {0xa7a2, {1|F|D, {0xa7a3}}},
- {0xa7a4, {1|F|D, {0xa7a5}}},
- {0xa7a6, {1|F|D, {0xa7a7}}},
- {0xa7a8, {1|F|D, {0xa7a9}}},
- {0xa7aa, {1|F|D, {0x0266}}},
- {0xa7ab, {1|F|D, {0x025c}}},
- {0xa7ac, {1|F|D, {0x0261}}},
- {0xa7ad, {1|F|D, {0x026c}}},
- {0xa7ae, {1|F|D, {0x026a}}},
- {0xa7b0, {1|F|D, {0x029e}}},
- {0xa7b1, {1|F|D, {0x0287}}},
- {0xa7b2, {1|F|D, {0x029d}}},
- {0xa7b3, {1|F|D, {0xab53}}},
- {0xa7b4, {1|F|D, {0xa7b5}}},
- {0xa7b6, {1|F|D, {0xa7b7}}},
- {0xa7b8, {1|F|D, {0xa7b9}}},
- {0xa7ba, {1|F|D, {0xa7bb}}},
- {0xa7bc, {1|F|D, {0xa7bd}}},
- {0xa7be, {1|F|D, {0xa7bf}}},
- {0xa7c0, {1|F|D, {0xa7c1}}},
- {0xa7c2, {1|F|D, {0xa7c3}}},
- {0xa7c4, {1|F|D, {0xa794}}},
- {0xa7c5, {1|F|D, {0x0282}}},
- {0xa7c6, {1|F|D, {0x1d8e}}},
- {0xa7c7, {1|F|D, {0xa7c8}}},
- {0xa7c9, {1|F|D, {0xa7ca}}},
- {0xa7d0, {1|F|D, {0xa7d1}}},
- {0xa7d6, {1|F|D, {0xa7d7}}},
- {0xa7d8, {1|F|D, {0xa7d9}}},
- {0xa7f5, {1|F|D, {0xa7f6}}},
- {0xab70, {1|F|U, {0x13a0}}},
- {0xab71, {1|F|U, {0x13a1}}},
- {0xab72, {1|F|U, {0x13a2}}},
- {0xab73, {1|F|U, {0x13a3}}},
- {0xab74, {1|F|U, {0x13a4}}},
- {0xab75, {1|F|U, {0x13a5}}},
- {0xab76, {1|F|U, {0x13a6}}},
- {0xab77, {1|F|U, {0x13a7}}},
- {0xab78, {1|F|U, {0x13a8}}},
- {0xab79, {1|F|U, {0x13a9}}},
- {0xab7a, {1|F|U, {0x13aa}}},
- {0xab7b, {1|F|U, {0x13ab}}},
- {0xab7c, {1|F|U, {0x13ac}}},
- {0xab7d, {1|F|U, {0x13ad}}},
- {0xab7e, {1|F|U, {0x13ae}}},
- {0xab7f, {1|F|U, {0x13af}}},
- {0xab80, {1|F|U, {0x13b0}}},
- {0xab81, {1|F|U, {0x13b1}}},
- {0xab82, {1|F|U, {0x13b2}}},
- {0xab83, {1|F|U, {0x13b3}}},
- {0xab84, {1|F|U, {0x13b4}}},
- {0xab85, {1|F|U, {0x13b5}}},
- {0xab86, {1|F|U, {0x13b6}}},
- {0xab87, {1|F|U, {0x13b7}}},
- {0xab88, {1|F|U, {0x13b8}}},
- {0xab89, {1|F|U, {0x13b9}}},
- {0xab8a, {1|F|U, {0x13ba}}},
- {0xab8b, {1|F|U, {0x13bb}}},
- {0xab8c, {1|F|U, {0x13bc}}},
- {0xab8d, {1|F|U, {0x13bd}}},
- {0xab8e, {1|F|U, {0x13be}}},
- {0xab8f, {1|F|U, {0x13bf}}},
- {0xab90, {1|F|U, {0x13c0}}},
- {0xab91, {1|F|U, {0x13c1}}},
- {0xab92, {1|F|U, {0x13c2}}},
- {0xab93, {1|F|U, {0x13c3}}},
- {0xab94, {1|F|U, {0x13c4}}},
- {0xab95, {1|F|U, {0x13c5}}},
- {0xab96, {1|F|U, {0x13c6}}},
- {0xab97, {1|F|U, {0x13c7}}},
- {0xab98, {1|F|U, {0x13c8}}},
- {0xab99, {1|F|U, {0x13c9}}},
- {0xab9a, {1|F|U, {0x13ca}}},
- {0xab9b, {1|F|U, {0x13cb}}},
- {0xab9c, {1|F|U, {0x13cc}}},
- {0xab9d, {1|F|U, {0x13cd}}},
- {0xab9e, {1|F|U, {0x13ce}}},
- {0xab9f, {1|F|U, {0x13cf}}},
- {0xaba0, {1|F|U, {0x13d0}}},
- {0xaba1, {1|F|U, {0x13d1}}},
- {0xaba2, {1|F|U, {0x13d2}}},
- {0xaba3, {1|F|U, {0x13d3}}},
- {0xaba4, {1|F|U, {0x13d4}}},
- {0xaba5, {1|F|U, {0x13d5}}},
- {0xaba6, {1|F|U, {0x13d6}}},
- {0xaba7, {1|F|U, {0x13d7}}},
- {0xaba8, {1|F|U, {0x13d8}}},
- {0xaba9, {1|F|U, {0x13d9}}},
- {0xabaa, {1|F|U, {0x13da}}},
- {0xabab, {1|F|U, {0x13db}}},
- {0xabac, {1|F|U, {0x13dc}}},
- {0xabad, {1|F|U, {0x13dd}}},
- {0xabae, {1|F|U, {0x13de}}},
- {0xabaf, {1|F|U, {0x13df}}},
- {0xabb0, {1|F|U, {0x13e0}}},
- {0xabb1, {1|F|U, {0x13e1}}},
- {0xabb2, {1|F|U, {0x13e2}}},
- {0xabb3, {1|F|U, {0x13e3}}},
- {0xabb4, {1|F|U, {0x13e4}}},
- {0xabb5, {1|F|U, {0x13e5}}},
- {0xabb6, {1|F|U, {0x13e6}}},
- {0xabb7, {1|F|U, {0x13e7}}},
- {0xabb8, {1|F|U, {0x13e8}}},
- {0xabb9, {1|F|U, {0x13e9}}},
- {0xabba, {1|F|U, {0x13ea}}},
- {0xabbb, {1|F|U, {0x13eb}}},
- {0xabbc, {1|F|U, {0x13ec}}},
- {0xabbd, {1|F|U, {0x13ed}}},
- {0xabbe, {1|F|U, {0x13ee}}},
- {0xabbf, {1|F|U, {0x13ef}}},
- {0xfb00, {2|F|ST|SU|I(366), {0x0066, 0x0066}}},
- {0xfb01, {2|F|ST|SU|I(370), {0x0066, 0x0069}}},
- {0xfb02, {2|F|ST|SU|I(374), {0x0066, 0x006c}}},
- {0xfb03, {3|F|ST|SU|I(378), {0x0066, 0x0066, 0x0069}}},
- {0xfb04, {3|F|ST|SU|I(384), {0x0066, 0x0066, 0x006c}}},
- {0xfb05, {2|F|ST|SU|I(390), {0x0073, 0x0074}}},
- {0xfb06, {2|F|ST|SU|I(394), {0x0073, 0x0074}}},
- {0xfb13, {2|F|ST|SU|I(398), {0x0574, 0x0576}}},
- {0xfb14, {2|F|ST|SU|I(402), {0x0574, 0x0565}}},
- {0xfb15, {2|F|ST|SU|I(406), {0x0574, 0x056b}}},
- {0xfb16, {2|F|ST|SU|I(410), {0x057e, 0x0576}}},
- {0xfb17, {2|F|ST|SU|I(414), {0x0574, 0x056d}}},
- {0xff21, {1|F|D, {0xff41}}},
- {0xff22, {1|F|D, {0xff42}}},
- {0xff23, {1|F|D, {0xff43}}},
- {0xff24, {1|F|D, {0xff44}}},
- {0xff25, {1|F|D, {0xff45}}},
- {0xff26, {1|F|D, {0xff46}}},
- {0xff27, {1|F|D, {0xff47}}},
- {0xff28, {1|F|D, {0xff48}}},
- {0xff29, {1|F|D, {0xff49}}},
- {0xff2a, {1|F|D, {0xff4a}}},
- {0xff2b, {1|F|D, {0xff4b}}},
- {0xff2c, {1|F|D, {0xff4c}}},
- {0xff2d, {1|F|D, {0xff4d}}},
- {0xff2e, {1|F|D, {0xff4e}}},
- {0xff2f, {1|F|D, {0xff4f}}},
- {0xff30, {1|F|D, {0xff50}}},
- {0xff31, {1|F|D, {0xff51}}},
- {0xff32, {1|F|D, {0xff52}}},
- {0xff33, {1|F|D, {0xff53}}},
- {0xff34, {1|F|D, {0xff54}}},
- {0xff35, {1|F|D, {0xff55}}},
- {0xff36, {1|F|D, {0xff56}}},
- {0xff37, {1|F|D, {0xff57}}},
- {0xff38, {1|F|D, {0xff58}}},
- {0xff39, {1|F|D, {0xff59}}},
- {0xff3a, {1|F|D, {0xff5a}}},
- {0x10400, {1|F|D, {0x10428}}},
- {0x10401, {1|F|D, {0x10429}}},
- {0x10402, {1|F|D, {0x1042a}}},
- {0x10403, {1|F|D, {0x1042b}}},
- {0x10404, {1|F|D, {0x1042c}}},
- {0x10405, {1|F|D, {0x1042d}}},
- {0x10406, {1|F|D, {0x1042e}}},
- {0x10407, {1|F|D, {0x1042f}}},
- {0x10408, {1|F|D, {0x10430}}},
- {0x10409, {1|F|D, {0x10431}}},
- {0x1040a, {1|F|D, {0x10432}}},
- {0x1040b, {1|F|D, {0x10433}}},
- {0x1040c, {1|F|D, {0x10434}}},
- {0x1040d, {1|F|D, {0x10435}}},
- {0x1040e, {1|F|D, {0x10436}}},
- {0x1040f, {1|F|D, {0x10437}}},
- {0x10410, {1|F|D, {0x10438}}},
- {0x10411, {1|F|D, {0x10439}}},
- {0x10412, {1|F|D, {0x1043a}}},
- {0x10413, {1|F|D, {0x1043b}}},
- {0x10414, {1|F|D, {0x1043c}}},
- {0x10415, {1|F|D, {0x1043d}}},
- {0x10416, {1|F|D, {0x1043e}}},
- {0x10417, {1|F|D, {0x1043f}}},
- {0x10418, {1|F|D, {0x10440}}},
- {0x10419, {1|F|D, {0x10441}}},
- {0x1041a, {1|F|D, {0x10442}}},
- {0x1041b, {1|F|D, {0x10443}}},
- {0x1041c, {1|F|D, {0x10444}}},
- {0x1041d, {1|F|D, {0x10445}}},
- {0x1041e, {1|F|D, {0x10446}}},
- {0x1041f, {1|F|D, {0x10447}}},
- {0x10420, {1|F|D, {0x10448}}},
- {0x10421, {1|F|D, {0x10449}}},
- {0x10422, {1|F|D, {0x1044a}}},
- {0x10423, {1|F|D, {0x1044b}}},
- {0x10424, {1|F|D, {0x1044c}}},
- {0x10425, {1|F|D, {0x1044d}}},
- {0x10426, {1|F|D, {0x1044e}}},
- {0x10427, {1|F|D, {0x1044f}}},
- {0x104b0, {1|F|D, {0x104d8}}},
- {0x104b1, {1|F|D, {0x104d9}}},
- {0x104b2, {1|F|D, {0x104da}}},
- {0x104b3, {1|F|D, {0x104db}}},
- {0x104b4, {1|F|D, {0x104dc}}},
- {0x104b5, {1|F|D, {0x104dd}}},
- {0x104b6, {1|F|D, {0x104de}}},
- {0x104b7, {1|F|D, {0x104df}}},
- {0x104b8, {1|F|D, {0x104e0}}},
- {0x104b9, {1|F|D, {0x104e1}}},
- {0x104ba, {1|F|D, {0x104e2}}},
- {0x104bb, {1|F|D, {0x104e3}}},
- {0x104bc, {1|F|D, {0x104e4}}},
- {0x104bd, {1|F|D, {0x104e5}}},
- {0x104be, {1|F|D, {0x104e6}}},
- {0x104bf, {1|F|D, {0x104e7}}},
- {0x104c0, {1|F|D, {0x104e8}}},
- {0x104c1, {1|F|D, {0x104e9}}},
- {0x104c2, {1|F|D, {0x104ea}}},
- {0x104c3, {1|F|D, {0x104eb}}},
- {0x104c4, {1|F|D, {0x104ec}}},
- {0x104c5, {1|F|D, {0x104ed}}},
- {0x104c6, {1|F|D, {0x104ee}}},
- {0x104c7, {1|F|D, {0x104ef}}},
- {0x104c8, {1|F|D, {0x104f0}}},
- {0x104c9, {1|F|D, {0x104f1}}},
- {0x104ca, {1|F|D, {0x104f2}}},
- {0x104cb, {1|F|D, {0x104f3}}},
- {0x104cc, {1|F|D, {0x104f4}}},
- {0x104cd, {1|F|D, {0x104f5}}},
- {0x104ce, {1|F|D, {0x104f6}}},
- {0x104cf, {1|F|D, {0x104f7}}},
- {0x104d0, {1|F|D, {0x104f8}}},
- {0x104d1, {1|F|D, {0x104f9}}},
- {0x104d2, {1|F|D, {0x104fa}}},
- {0x104d3, {1|F|D, {0x104fb}}},
- {0x10570, {1|F|D, {0x10597}}},
- {0x10571, {1|F|D, {0x10598}}},
- {0x10572, {1|F|D, {0x10599}}},
- {0x10573, {1|F|D, {0x1059a}}},
- {0x10574, {1|F|D, {0x1059b}}},
- {0x10575, {1|F|D, {0x1059c}}},
- {0x10576, {1|F|D, {0x1059d}}},
- {0x10577, {1|F|D, {0x1059e}}},
- {0x10578, {1|F|D, {0x1059f}}},
- {0x10579, {1|F|D, {0x105a0}}},
- {0x1057a, {1|F|D, {0x105a1}}},
- {0x1057c, {1|F|D, {0x105a3}}},
- {0x1057d, {1|F|D, {0x105a4}}},
- {0x1057e, {1|F|D, {0x105a5}}},
- {0x1057f, {1|F|D, {0x105a6}}},
- {0x10580, {1|F|D, {0x105a7}}},
- {0x10581, {1|F|D, {0x105a8}}},
- {0x10582, {1|F|D, {0x105a9}}},
- {0x10583, {1|F|D, {0x105aa}}},
- {0x10584, {1|F|D, {0x105ab}}},
- {0x10585, {1|F|D, {0x105ac}}},
- {0x10586, {1|F|D, {0x105ad}}},
- {0x10587, {1|F|D, {0x105ae}}},
- {0x10588, {1|F|D, {0x105af}}},
- {0x10589, {1|F|D, {0x105b0}}},
- {0x1058a, {1|F|D, {0x105b1}}},
- {0x1058c, {1|F|D, {0x105b3}}},
- {0x1058d, {1|F|D, {0x105b4}}},
- {0x1058e, {1|F|D, {0x105b5}}},
- {0x1058f, {1|F|D, {0x105b6}}},
- {0x10590, {1|F|D, {0x105b7}}},
- {0x10591, {1|F|D, {0x105b8}}},
- {0x10592, {1|F|D, {0x105b9}}},
- {0x10594, {1|F|D, {0x105bb}}},
- {0x10595, {1|F|D, {0x105bc}}},
- {0x10c80, {1|F|D, {0x10cc0}}},
- {0x10c81, {1|F|D, {0x10cc1}}},
- {0x10c82, {1|F|D, {0x10cc2}}},
- {0x10c83, {1|F|D, {0x10cc3}}},
- {0x10c84, {1|F|D, {0x10cc4}}},
- {0x10c85, {1|F|D, {0x10cc5}}},
- {0x10c86, {1|F|D, {0x10cc6}}},
- {0x10c87, {1|F|D, {0x10cc7}}},
- {0x10c88, {1|F|D, {0x10cc8}}},
- {0x10c89, {1|F|D, {0x10cc9}}},
- {0x10c8a, {1|F|D, {0x10cca}}},
- {0x10c8b, {1|F|D, {0x10ccb}}},
- {0x10c8c, {1|F|D, {0x10ccc}}},
- {0x10c8d, {1|F|D, {0x10ccd}}},
- {0x10c8e, {1|F|D, {0x10cce}}},
- {0x10c8f, {1|F|D, {0x10ccf}}},
- {0x10c90, {1|F|D, {0x10cd0}}},
- {0x10c91, {1|F|D, {0x10cd1}}},
- {0x10c92, {1|F|D, {0x10cd2}}},
- {0x10c93, {1|F|D, {0x10cd3}}},
- {0x10c94, {1|F|D, {0x10cd4}}},
- {0x10c95, {1|F|D, {0x10cd5}}},
- {0x10c96, {1|F|D, {0x10cd6}}},
- {0x10c97, {1|F|D, {0x10cd7}}},
- {0x10c98, {1|F|D, {0x10cd8}}},
- {0x10c99, {1|F|D, {0x10cd9}}},
- {0x10c9a, {1|F|D, {0x10cda}}},
- {0x10c9b, {1|F|D, {0x10cdb}}},
- {0x10c9c, {1|F|D, {0x10cdc}}},
- {0x10c9d, {1|F|D, {0x10cdd}}},
- {0x10c9e, {1|F|D, {0x10cde}}},
- {0x10c9f, {1|F|D, {0x10cdf}}},
- {0x10ca0, {1|F|D, {0x10ce0}}},
- {0x10ca1, {1|F|D, {0x10ce1}}},
- {0x10ca2, {1|F|D, {0x10ce2}}},
- {0x10ca3, {1|F|D, {0x10ce3}}},
- {0x10ca4, {1|F|D, {0x10ce4}}},
- {0x10ca5, {1|F|D, {0x10ce5}}},
- {0x10ca6, {1|F|D, {0x10ce6}}},
- {0x10ca7, {1|F|D, {0x10ce7}}},
- {0x10ca8, {1|F|D, {0x10ce8}}},
- {0x10ca9, {1|F|D, {0x10ce9}}},
- {0x10caa, {1|F|D, {0x10cea}}},
- {0x10cab, {1|F|D, {0x10ceb}}},
- {0x10cac, {1|F|D, {0x10cec}}},
- {0x10cad, {1|F|D, {0x10ced}}},
- {0x10cae, {1|F|D, {0x10cee}}},
- {0x10caf, {1|F|D, {0x10cef}}},
- {0x10cb0, {1|F|D, {0x10cf0}}},
- {0x10cb1, {1|F|D, {0x10cf1}}},
- {0x10cb2, {1|F|D, {0x10cf2}}},
- {0x118a0, {1|F|D, {0x118c0}}},
- {0x118a1, {1|F|D, {0x118c1}}},
- {0x118a2, {1|F|D, {0x118c2}}},
- {0x118a3, {1|F|D, {0x118c3}}},
- {0x118a4, {1|F|D, {0x118c4}}},
- {0x118a5, {1|F|D, {0x118c5}}},
- {0x118a6, {1|F|D, {0x118c6}}},
- {0x118a7, {1|F|D, {0x118c7}}},
- {0x118a8, {1|F|D, {0x118c8}}},
- {0x118a9, {1|F|D, {0x118c9}}},
- {0x118aa, {1|F|D, {0x118ca}}},
- {0x118ab, {1|F|D, {0x118cb}}},
- {0x118ac, {1|F|D, {0x118cc}}},
- {0x118ad, {1|F|D, {0x118cd}}},
- {0x118ae, {1|F|D, {0x118ce}}},
- {0x118af, {1|F|D, {0x118cf}}},
- {0x118b0, {1|F|D, {0x118d0}}},
- {0x118b1, {1|F|D, {0x118d1}}},
- {0x118b2, {1|F|D, {0x118d2}}},
- {0x118b3, {1|F|D, {0x118d3}}},
- {0x118b4, {1|F|D, {0x118d4}}},
- {0x118b5, {1|F|D, {0x118d5}}},
- {0x118b6, {1|F|D, {0x118d6}}},
- {0x118b7, {1|F|D, {0x118d7}}},
- {0x118b8, {1|F|D, {0x118d8}}},
- {0x118b9, {1|F|D, {0x118d9}}},
- {0x118ba, {1|F|D, {0x118da}}},
- {0x118bb, {1|F|D, {0x118db}}},
- {0x118bc, {1|F|D, {0x118dc}}},
- {0x118bd, {1|F|D, {0x118dd}}},
- {0x118be, {1|F|D, {0x118de}}},
- {0x118bf, {1|F|D, {0x118df}}},
- {0x16e40, {1|F|D, {0x16e60}}},
- {0x16e41, {1|F|D, {0x16e61}}},
- {0x16e42, {1|F|D, {0x16e62}}},
- {0x16e43, {1|F|D, {0x16e63}}},
- {0x16e44, {1|F|D, {0x16e64}}},
- {0x16e45, {1|F|D, {0x16e65}}},
- {0x16e46, {1|F|D, {0x16e66}}},
- {0x16e47, {1|F|D, {0x16e67}}},
- {0x16e48, {1|F|D, {0x16e68}}},
- {0x16e49, {1|F|D, {0x16e69}}},
- {0x16e4a, {1|F|D, {0x16e6a}}},
- {0x16e4b, {1|F|D, {0x16e6b}}},
- {0x16e4c, {1|F|D, {0x16e6c}}},
- {0x16e4d, {1|F|D, {0x16e6d}}},
- {0x16e4e, {1|F|D, {0x16e6e}}},
- {0x16e4f, {1|F|D, {0x16e6f}}},
- {0x16e50, {1|F|D, {0x16e70}}},
- {0x16e51, {1|F|D, {0x16e71}}},
- {0x16e52, {1|F|D, {0x16e72}}},
- {0x16e53, {1|F|D, {0x16e73}}},
- {0x16e54, {1|F|D, {0x16e74}}},
- {0x16e55, {1|F|D, {0x16e75}}},
- {0x16e56, {1|F|D, {0x16e76}}},
- {0x16e57, {1|F|D, {0x16e77}}},
- {0x16e58, {1|F|D, {0x16e78}}},
- {0x16e59, {1|F|D, {0x16e79}}},
- {0x16e5a, {1|F|D, {0x16e7a}}},
- {0x16e5b, {1|F|D, {0x16e7b}}},
- {0x16e5c, {1|F|D, {0x16e7c}}},
- {0x16e5d, {1|F|D, {0x16e7d}}},
- {0x16e5e, {1|F|D, {0x16e7e}}},
- {0x16e5f, {1|F|D, {0x16e7f}}},
- {0x1e900, {1|F|D, {0x1e922}}},
- {0x1e901, {1|F|D, {0x1e923}}},
- {0x1e902, {1|F|D, {0x1e924}}},
- {0x1e903, {1|F|D, {0x1e925}}},
- {0x1e904, {1|F|D, {0x1e926}}},
- {0x1e905, {1|F|D, {0x1e927}}},
- {0x1e906, {1|F|D, {0x1e928}}},
- {0x1e907, {1|F|D, {0x1e929}}},
- {0x1e908, {1|F|D, {0x1e92a}}},
- {0x1e909, {1|F|D, {0x1e92b}}},
- {0x1e90a, {1|F|D, {0x1e92c}}},
- {0x1e90b, {1|F|D, {0x1e92d}}},
- {0x1e90c, {1|F|D, {0x1e92e}}},
- {0x1e90d, {1|F|D, {0x1e92f}}},
- {0x1e90e, {1|F|D, {0x1e930}}},
- {0x1e90f, {1|F|D, {0x1e931}}},
- {0x1e910, {1|F|D, {0x1e932}}},
- {0x1e911, {1|F|D, {0x1e933}}},
- {0x1e912, {1|F|D, {0x1e934}}},
- {0x1e913, {1|F|D, {0x1e935}}},
- {0x1e914, {1|F|D, {0x1e936}}},
- {0x1e915, {1|F|D, {0x1e937}}},
- {0x1e916, {1|F|D, {0x1e938}}},
- {0x1e917, {1|F|D, {0x1e939}}},
- {0x1e918, {1|F|D, {0x1e93a}}},
- {0x1e919, {1|F|D, {0x1e93b}}},
- {0x1e91a, {1|F|D, {0x1e93c}}},
- {0x1e91b, {1|F|D, {0x1e93d}}},
- {0x1e91c, {1|F|D, {0x1e93e}}},
- {0x1e91d, {1|F|D, {0x1e93f}}},
- {0x1e91e, {1|F|D, {0x1e940}}},
- {0x1e91f, {1|F|D, {0x1e941}}},
- {0x1e920, {1|F|D, {0x1e942}}},
- {0x1e921, {1|F|D, {0x1e943}}},
-#define CaseFold_Locale (*(CaseFold_11_Type (*)[2])(CaseFold_11_Table+1528))
- {0x0049, {1|F|D, {0x0069}}},
- {0x0130, {2|F|D, {0x0069, 0x0307}}},
-};
-
-/* ANSI-C code produced by gperf version 3.1 */
-/* Command-line: gperf -7 -k1,2,3 -F,-1 -c -j1 -i1 -t -T -E -C -H onigenc_unicode_CaseFold_11_hash -N onigenc_unicode_CaseFold_11_lookup -n */
-
-/* maximum key range = 3080, duplicates = 0 */
-
-#ifdef __GNUC__
-__inline
-#else
-#ifdef __cplusplus
-inline
-#endif
-#endif
-/*ARGSUSED*/
-static unsigned int
-onigenc_unicode_CaseFold_11_hash(const OnigCodePoint code)
-{
- static const unsigned short asso_values[] =
- {
- 1, 3085, 2, 20, 3, 307, 200, 8, 31, 159,
- 2, 253, 33, 967, 3085, 3085, 3085, 3085, 3085, 3085,
- 3085, 3085, 3085, 3085, 3085, 3085, 3085, 30, 3085, 3085,
- 3085, 3085, 3085, 3085, 3085, 352, 3085, 3085, 3085, 3085,
- 3085, 93, 3085, 3085, 3085, 3085, 3085, 3085, 3085, 3085,
- 3085, 407, 3085, 3085, 3085, 3085, 3085, 3085, 3085, 201,
- 3085, 3085, 14, 13, 373, 1, 3085, 3085, 503, 19,
- 3085, 3085, 3085, 3085, 3085, 325, 3085, 3085, 290, 1064,
- 484, 28, 1906, 447, 272, 414, 2002, 79, 905, 5,
- 11, 22, 2024, 623, 761, 617, 1893, 45, 1874, 113,
- 1856, 255, 1823, 96, 1463, 62, 1841, 130, 1798, 331,
- 1771, 238, 1977, 147, 1387, 464, 1691, 187, 1639, 181,
- 366, 580, 1331, 508, 1287, 547, 1583, 541, 400, 783,
- 1944, 657, 1850, 932, 1785, 858, 1645, 681, 1412, 722,
- 1622, 972, 1306, 807, 1942, 1282, 283, 1218, 1557, 1055,
- 1406, 1258, 1401, 1168, 1327, 864, 893, 1123, 1714, 1195,
- 1885, 1083, 2016, 1232, 823, 678, 1420, 1017, 155, 1261,
- 86, 1351, 794, 1929, 51, 1525, 50, 221, 4, 1383,
- 196, 325, 1, 1562, 102, 1441, 3, 1356, 226, 1304,
- 271, 1516, 68, 1752, 37, 1469, 51, 1920, 143, 2059,
- 198, 2095, 370, 2069, 137, 718, 407, 1926, 136
- };
- return asso_values[bits_of(code, 2)+81] + asso_values[bits_of(code, 1)+2] + asso_values[bits_of(code, 0)];
-}
-
-static const CodePointList3 *
-onigenc_unicode_CaseFold_11_lookup(const OnigCodePoint code)
-{
- enum
- {
- MIN_CODE_VALUE = 0x41,
- MAX_CODE_VALUE = 0x1e921,
- TOTAL_KEYWORDS = 1530,
- MIN_WORD_LENGTH = 3,
- MAX_WORD_LENGTH = 3,
- MIN_HASH_VALUE = 5,
- MAX_HASH_VALUE = 3084
- };
-
- static const short wordlist[] =
- {
- -1, -1, -1, -1, -1,
- /*0x1fe9*/ 850,
- -1,
- /*0x1f88*/ 775,
- /*0x0408*/ 305,
- /*0x0108*/ 61,
- /*0x10408*/ 1276,
- -1,
- /*0xab88*/ 1174,
- /*0x1f89*/ 776,
- /*0x0409*/ 306,
- /*0x2c69*/ 964,
- /*0x10409*/ 1277,
- /*0x2c08*/ 919,
- /*0xab89*/ 1175,
- /*0x1e88*/ 653,
- /*0x1e08*/ 589,
- -1, -1,
- /*0x2c09*/ 920,
- /*0x1f8a*/ 777,
- /*0x040a*/ 307,
- /*0x010a*/ 62,
- /*0x1040a*/ 1278,
- /*0x2c88*/ 978,
- /*0xab8a*/ 1176,
- /*0x1f80*/ 767,
- /*0x0400*/ 297,
- /*0x0100*/ 57,
- /*0x10400*/ 1268,
- /*0x2c0a*/ 921,
- /*0xab80*/ 1166,
- /*0x1e8a*/ 654,
- /*0x1e0a*/ 590,
- /*0x10c88*/ 1387,
- /*0x0508*/ 425,
- /*0x2c00*/ 911,
- -1,
- /*0x1e80*/ 649,
- /*0x1e00*/ 585,
- /*0x10c89*/ 1388,
- /*0x2c8a*/ 979,
- -1,
- /*0x1f90*/ 783,
- /*0x0410*/ 313,
- /*0x0110*/ 65,
- /*0x10410*/ 1284,
- /*0x2c80*/ 974,
- /*0xab90*/ 1182,
- /*0x1ff3*/ 855,
- -1,
- /*0x10c8a*/ 1389,
- /*0x050a*/ 426,
- /*0x2c10*/ 927,
- /*0xa780*/ 1106,
- /*0x1e90*/ 657,
- /*0x1e10*/ 593,
- /*0x10c80*/ 1379,
- /*0x0500*/ 421,
- -1,
- /*0x1f98*/ 791,
- /*0x0418*/ 321,
- /*0x0118*/ 69,
- /*0x10418*/ 1292,
- /*0x2c90*/ 982,
- /*0xab98*/ 1190,
- -1,
- /*0x00df*/ 56,
- /*0x00dd*/ 54,
- /*0x10571*/ 1345,
- /*0x2c18*/ 935,
- /*0xa790*/ 1112,
- /*0x1e98*/ 662,
- /*0x1e18*/ 597,
- /*0x10c90*/ 1395,
- /*0x0510*/ 429,
- /*0x2c6f*/ 968,
- /*0x1f86*/ 773,
- /*0x0406*/ 303,
- /*0x0106*/ 60,
- /*0x10406*/ 1274,
- /*0x2c98*/ 986,
- /*0xab86*/ 1172,
- /*0x10573*/ 1347,
- /*0x1fd9*/ 841,
- /*0x0059*/ 23,
- -1,
- /*0x2c06*/ 917,
- /*0xa798*/ 1115,
- /*0x1e86*/ 652,
- /*0x1e06*/ 588,
- /*0x10c98*/ 1403,
- /*0x0518*/ 433,
- -1,
- /*0x1f96*/ 789,
- /*0x0416*/ 319,
- /*0x0116*/ 68,
- /*0x10416*/ 1290,
- /*0x2c86*/ 977,
- /*0xab96*/ 1188,
- /*0x1fe7*/ 848,
- -1, -1,
- /*0x00d9*/ 50,
- /*0x2c16*/ 933,
- /*0xa786*/ 1109,
- /*0x1e96*/ 660,
- /*0x1e16*/ 596,
- /*0x10c86*/ 1385,
- /*0x0506*/ 424,
- /*0x2c67*/ 963,
- /*0x1f92*/ 785,
- /*0x0412*/ 315,
- /*0x0112*/ 66,
- /*0x10412*/ 1286,
- /*0x2c96*/ 985,
- /*0xab92*/ 1184,
- -1, -1, -1, -1,
- /*0x2c12*/ 929,
- /*0xa796*/ 1114,
- /*0x1e92*/ 658,
- /*0x1e12*/ 594,
- /*0x10c96*/ 1401,
- /*0x0516*/ 432,
- -1,
- /*0x1f9a*/ 793,
- /*0x041a*/ 323,
- /*0x011a*/ 70,
- /*0x1041a*/ 1294,
- /*0x2c92*/ 983,
- /*0xab9a*/ 1192,
- -1,
- /*0x1ffb*/ 862,
- /*0x017f*/ 120,
- /*0x017b*/ 118,
- /*0x2c1a*/ 937,
- /*0xa792*/ 1113,
- /*0x1e9a*/ 664,
- /*0x1e1a*/ 598,
- /*0x10c92*/ 1397,
- /*0x0512*/ 430,
- /*0x2c7f*/ 973,
- /*0x1fa0*/ 799,
- /*0x0420*/ 329,
- /*0x0120*/ 73,
- /*0x10420*/ 1300,
- /*0x2c9a*/ 987,
- /*0xaba0*/ 1198,
- /*0x2c75*/ 971,
- -1,
- /*0x1fd7*/ 839,
- /*0x0057*/ 21,
- /*0x2c20*/ 943,
- /*0xa79a*/ 1116,
- /*0x1ea0*/ 667,
- /*0x1e20*/ 601,
- /*0x10c9a*/ 1405,
- /*0x051a*/ 434,
- /*0x0388*/ 235,
- -1, -1,
- /*0x037f*/ 233,
- -1,
- /*0x2ca0*/ 990,
- /*0x0389*/ 236,
- /*0x1057f*/ 1358,
- /*0xa7f5*/ 1149,
- -1, -1, -1,
- /*0xa7a0*/ 1119,
- -1,
- /*0x10575*/ 1349,
- /*0x10ca0*/ 1411,
- /*0x0520*/ 437,
- /*0x038a*/ 237,
- /*0x1fa6*/ 805,
- /*0x0426*/ 335,
- /*0x0126*/ 76,
- /*0x10426*/ 1306,
- -1,
- /*0xaba6*/ 1204,
- /*0x1fa4*/ 803,
- /*0x0424*/ 333,
- /*0x0124*/ 75,
- /*0x10424*/ 1304,
- /*0x2c26*/ 949,
- /*0xaba4*/ 1202,
- /*0x1ea6*/ 670,
- /*0x1e26*/ 604,
- /*0x03f1*/ 288,
- /*0x1fe3*/ 845,
- /*0x2c24*/ 947,
- /*0x1ff7*/ 858,
- /*0x1ea4*/ 669,
- /*0x1e24*/ 603,
- -1,
- /*0x2ca6*/ 993,
- /*0x0390*/ 241,
- /*0x0208*/ 194,
- /*0x1c88*/ 538,
- /*0x2c63*/ 961,
- -1,
- /*0x2ca4*/ 992,
- /*0xa7a6*/ 1122,
- -1, -1,
- /*0x10ca6*/ 1417,
- /*0x0526*/ 440,
- -1,
- /*0xa7a4*/ 1121,
- -1, -1,
- /*0x10ca4*/ 1415,
- /*0x0524*/ 439,
- /*0x0398*/ 249,
- /*0x020a*/ 195,
- /*0x0460*/ 345,
- /*0x0160*/ 104,
- -1, -1,
- /*0x1feb*/ 852,
- /*0x0200*/ 190,
- /*0x1c80*/ 530,
- /*0x13fb*/ 527,
- -1,
- /*0x2c60*/ 959,
- /*0x10577*/ 1351,
- /*0x1ee0*/ 699,
- /*0x1e60*/ 633,
- -1,
- /*0x2c6b*/ 965,
- /*0x0386*/ 234,
- /*0x1f9e*/ 797,
- /*0x041e*/ 327,
- /*0x011e*/ 72,
- /*0x1041e*/ 1298,
- /*0x2ce0*/ 1022,
- /*0xab9e*/ 1196,
- /*0x0210*/ 198,
- /*0x1c90*/ 539,
- -1,
- /*0x2ceb*/ 1024,
- /*0x2c1e*/ 941,
- -1,
- /*0x1e9e*/ 666,
- /*0x1e1e*/ 600,
- -1, -1,
- /*0x0396*/ 247,
- /*0x1f94*/ 787,
- /*0x0414*/ 317,
- /*0x0114*/ 67,
- /*0x10414*/ 1288,
- /*0x2c9e*/ 989,
- /*0xab94*/ 1186,
- /*0x0218*/ 202,
- /*0x1c98*/ 547,
- -1, -1,
- /*0x2c14*/ 931,
- /*0xa79e*/ 1118,
- /*0x1e94*/ 659,
- /*0x1e14*/ 595,
- /*0x10c9e*/ 1409,
- /*0x051e*/ 436,
- /*0x0392*/ 243,
- /*0x1f83*/ 770,
- /*0x0403*/ 300,
- /*0x048a*/ 362,
- /*0x10403*/ 1271,
- /*0x2c94*/ 984,
- /*0xab83*/ 1169,
- /*0x0206*/ 193,
- /*0x1c86*/ 536,
- /*0x0480*/ 361,
- /*0x2c6d*/ 966,
- /*0x2c03*/ 914,
- /*0x1e908*/ 1502,
- /*0x0041*/ 0,
- /*0x0141*/ 88,
- /*0x10c94*/ 1399,
- /*0x0514*/ 431,
- /*0x039a*/ 251,
- /*0x1e909*/ 1503,
- /*0x2183*/ 884,
- -1,
- /*0x2ced*/ 1025,
- -1,
- /*0x03ff*/ 296,
- /*0x0216*/ 201,
- /*0x1c96*/ 545,
- /*0x0490*/ 365,
- -1, -1,
- /*0x1e90a*/ 1504,
- /*0x03f5*/ 290,
- /*0x00c1*/ 27,
- /*0x10c83*/ 1382,
- -1,
- /*0x03a0*/ 257,
- /*0x1e900*/ 1494,
- -1, -1, -1, -1, -1,
- /*0x0212*/ 199,
- /*0x1c92*/ 541,
- /*0x0498*/ 369,
- /*0x0541*/ 461,
- -1,
- /*0x0189*/ 126,
- -1, -1, -1, -1, -1,
- /*0x1e910*/ 1510,
- -1,
- /*0x1fe4*/ 846,
- /*0x0464*/ 347,
- /*0x0164*/ 106,
- /*0x018a*/ 127,
- /*0x021a*/ 203,
- /*0x1c9a*/ 549,
- /*0x1f9c*/ 795,
- /*0x041c*/ 325,
- /*0x011c*/ 71,
- /*0x1041c*/ 1296,
- /*0x2c64*/ 962,
- /*0xab9c*/ 1194,
- /*0x1ee4*/ 701,
- /*0x1e64*/ 635,
- /*0x03a6*/ 262,
- /*0x1e918*/ 1518,
- /*0x2c1c*/ 939,
- -1,
- /*0x01f1*/ 181,
- /*0x1e1c*/ 599,
- /*0x03a4*/ 260,
- /*0x0220*/ 206,
- /*0x1ca0*/ 555,
- /*0x0496*/ 368,
- -1, -1,
- /*0x0190*/ 131,
- /*0x2c9c*/ 988,
- -1, -1, -1,
- /*0x03f7*/ 291,
- /*0x1e906*/ 1500,
- -1,
- /*0xa79c*/ 1117,
- -1, -1,
- /*0x10c9c*/ 1407,
- /*0x051c*/ 435,
- -1,
- /*0x0492*/ 366,
- /*0x1fa7*/ 806,
- /*0x0427*/ 336,
- /*0x0198*/ 137,
- /*0x10427*/ 1307,
- /*0x1ff9*/ 860,
- /*0xaba7*/ 1205,
- /*0x0179*/ 117,
- -1,
- /*0x1e916*/ 1516,
- /*0x1f69*/ 760,
- /*0x2c27*/ 950,
- /*0x1f08*/ 715,
- -1,
- /*0x03e0*/ 279,
- /*0x0226*/ 209,
- /*0x1ca6*/ 561,
- /*0x049a*/ 370,
- /*0x1f09*/ 716,
- -1,
- /*0x0186*/ 124,
- /*0x0224*/ 208,
- /*0x1ca4*/ 559,
- -1, -1, -1,
- /*0x1e912*/ 1512,
- /*0x01d9*/ 169,
- -1,
- /*0x1f0a*/ 717,
- -1,
- /*0x039e*/ 255,
- /*0x10ca7*/ 1418,
- -1,
- /*0x04a0*/ 373,
- /*0x1faf*/ 814,
- /*0x042f*/ 344,
- /*0x0196*/ 135,
- -1,
- /*0x10579*/ 1353,
- /*0xabaf*/ 1213,
- -1, -1,
- /*0x1e91a*/ 1520,
- /*0x017d*/ 119,
- /*0x2c2f*/ 958,
- -1,
- /*0xfb00*/ 1230,
- /*0x0394*/ 245,
- /*0x1f84*/ 771,
- /*0x0404*/ 301,
- /*0x0104*/ 59,
- /*0x10404*/ 1272,
- -1,
- /*0xab84*/ 1170,
- -1, -1,
- /*0x1f5f*/ 758,
- /*0x1f5d*/ 757,
- /*0x2c04*/ 915,
- /*0x1e920*/ 1526,
- /*0x1e84*/ 651,
- /*0x1e04*/ 587,
- -1, -1, -1,
- /*0x10caf*/ 1426,
- -1,
- /*0x04a6*/ 376,
- /*0x1f18*/ 723,
- /*0x2c84*/ 976,
- -1,
- /*0x021e*/ 205,
- /*0x1c9e*/ 553,
- /*0x04a4*/ 375,
- /*0x1f6f*/ 766,
- /*0x1057d*/ 1356,
- /*0xa784*/ 1108,
- -1, -1,
- /*0x10c84*/ 1383,
- /*0x0504*/ 423,
- /*0x1f82*/ 769,
- /*0x0402*/ 299,
- /*0x0102*/ 58,
- /*0x10402*/ 1270,
- -1,
- /*0xab82*/ 1168,
- /*0x01a0*/ 141,
- /*0x0214*/ 200,
- /*0x1c94*/ 543,
- -1,
- /*0x2c02*/ 913,
- /*0x1f59*/ 755,
- /*0x1e82*/ 650,
- /*0x1e02*/ 586,
- /*0x01d7*/ 168,
- /*0x13f9*/ 525,
- /*0xfb06*/ 1236,
- /*0x1fa2*/ 801,
- /*0x0422*/ 331,
- /*0x0122*/ 74,
- /*0x10422*/ 1302,
- /*0x2c82*/ 975,
- /*0xaba2*/ 1200,
- -1, -1,
- /*0x1c83*/ 533,
- /*0x04e0*/ 405,
- /*0x2c22*/ 945,
- /*0xa782*/ 1107,
- /*0x1ea2*/ 668,
- /*0x1e22*/ 602,
- /*0x10c82*/ 1381,
- /*0x0502*/ 422,
- /*0xfb16*/ 1240,
- -1,
- /*0x0241*/ 220,
- /*0x03e4*/ 281,
- -1,
- /*0x2ca2*/ 991,
- -1,
- /*0x01a6*/ 144,
- -1,
- /*0x039c*/ 253,
- /*0x049e*/ 372,
- -1,
- /*0xa7a2*/ 1120,
- /*0x01a4*/ 143,
- -1,
- /*0x10ca2*/ 1413,
- /*0x0522*/ 438,
- -1,
- /*0x10a0*/ 484,
- /*0x13fd*/ 529,
- -1, -1,
- /*0x1f1a*/ 725,
- /*0x2165*/ 873,
- /*0x01f7*/ 185,
- /*0x2169*/ 877,
- /*0x2161*/ 869,
- /*0x0494*/ 367,
- /*0x1faa*/ 809,
- /*0x042a*/ 339,
- /*0x012a*/ 78,
- /*0xa660*/ 1043,
- -1,
- /*0xabaa*/ 1208,
- -1, -1,
- /*0x1e91e*/ 1524,
- -1,
- /*0x2c2a*/ 953,
- -1,
- /*0x1eaa*/ 672,
- /*0x1e2a*/ 606,
- -1, -1,
- /*0x03a7*/ 263,
- -1, -1,
- /*0x01e0*/ 172,
- /*0x03f9*/ 292,
- /*0x2caa*/ 995,
- /*0x021c*/ 204,
- /*0x1c9c*/ 551,
- /*0x10a6*/ 490,
- /*0x1e914*/ 1514,
- -1,
- /*0x04c1*/ 390,
- /*0xa7aa*/ 1124,
- /*0x104c1*/ 1325,
- /*0x10a4*/ 488,
- /*0x10caa*/ 1421,
- /*0x052a*/ 442,
- /*0x1fae*/ 813,
- /*0x042e*/ 343,
- /*0x012e*/ 80,
- -1, -1,
- /*0xabae*/ 1212,
- /*0x1fac*/ 811,
- /*0x042c*/ 341,
- /*0x012c*/ 79,
- /*0x1e903*/ 1497,
- /*0x2c2e*/ 957,
- /*0xabac*/ 1210,
- /*0x1eae*/ 674,
- /*0x1e2e*/ 608,
- /*0x118a0*/ 1430,
- -1,
- /*0x2c2c*/ 955,
- -1,
- /*0x1eac*/ 673,
- /*0x1e2c*/ 607,
- /*0x0194*/ 134,
- /*0x2cae*/ 997,
- -1, -1,
- /*0x03fd*/ 294,
- /*0x1ca7*/ 562,
- -1,
- /*0x2cac*/ 996,
- /*0xa7ae*/ 1128,
- /*0x216f*/ 883,
- -1,
- /*0x10cae*/ 1425,
- /*0x052e*/ 444,
- -1,
- /*0xa7ac*/ 1126,
- -1,
- /*0x04e4*/ 407,
- /*0x10cac*/ 1423,
- /*0x052c*/ 443,
- /*0x1fa8*/ 807,
- /*0x0428*/ 337,
- /*0x0128*/ 77,
- /*0x049c*/ 371,
- -1,
- /*0xaba8*/ 1206,
- -1, -1, -1,
- /*0x118a6*/ 1436,
- /*0x2c28*/ 951,
- -1,
- /*0x1ea8*/ 671,
- /*0x1e28*/ 605,
- -1,
- /*0x118a4*/ 1434,
- -1, -1,
- /*0x1f6b*/ 762,
- /*0xff26*/ 1247,
- /*0x1caf*/ 570,
- /*0x2ca8*/ 994,
- -1, -1,
- /*0x2167*/ 875,
- /*0xff24*/ 1245,
- -1,
- /*0x24c1*/ 896,
- /*0xa7a8*/ 1123,
- /*0x1e91c*/ 1522,
- -1,
- /*0x10ca8*/ 1419,
- /*0x0528*/ 441,
- /*0x0204*/ 192,
- /*0x1c84*/ 534,
- /*0xa664*/ 1045,
- -1,
- /*0x1f8e*/ 781,
- /*0x040e*/ 311,
- /*0x010e*/ 64,
- /*0x1040e*/ 1282,
- /*0xa77b*/ 1103,
- /*0xab8e*/ 1180,
- /*0x1f8c*/ 779,
- /*0x040c*/ 309,
- /*0x010c*/ 63,
- /*0x1040c*/ 1280,
- /*0x2c0e*/ 925,
- /*0xab8c*/ 1178,
- /*0x1e8e*/ 656,
- /*0x1e0e*/ 592,
- /*0x01e4*/ 174,
- -1,
- /*0x2c0c*/ 923,
- /*0x10c1*/ 517,
- /*0x1e8c*/ 655,
- /*0x1e0c*/ 591,
- /*0x019c*/ 138,
- /*0x2c8e*/ 981,
- /*0xfb14*/ 1238,
- -1, -1, -1,
- /*0x1f6d*/ 764,
- /*0x2c8c*/ 980,
- -1,
- /*0x0202*/ 191,
- /*0x1c82*/ 532,
- /*0x10c8e*/ 1393,
- /*0x050e*/ 428,
- -1, -1, -1, -1,
- /*0x10c8c*/ 1391,
- /*0x050c*/ 427,
- /*0xfb03*/ 1233,
- /*0x1fb2*/ 815,
- -1,
- /*0x0132*/ 81,
- -1, -1,
- /*0xabb2*/ 1216,
- /*0x0222*/ 207,
- /*0x1ca2*/ 557,
- /*0xa726*/ 1066,
- /*0x03aa*/ 266,
- -1, -1,
- /*0x1eb2*/ 676,
- /*0x1e32*/ 610,
- /*0xa724*/ 1065,
- /*0x01a7*/ 145,
- -1, -1, -1, -1, -1,
- /*0x2cb2*/ 999,
- /*0x0054*/ 18,
- /*0x0154*/ 98,
- /*0x1fb8*/ 820,
- -1,
- /*0x2126*/ 864,
- -1,
- /*0xa7b2*/ 1131,
- /*0xabb8*/ 1222,
- -1,
- /*0x10cb2*/ 1429,
- /*0x0532*/ 446,
- /*0x1ed4*/ 693,
- /*0x1e54*/ 627,
- /*0x1e904*/ 1498,
- /*0x1eb8*/ 679,
- /*0x1e38*/ 613,
- -1, -1,
- /*0x00d4*/ 46,
- /*0x2163*/ 871,
- /*0x2cd4*/ 1016,
- -1, -1,
- /*0x2cb8*/ 1002,
- /*0x1f1c*/ 727,
- -1,
- /*0xa760*/ 1094,
- /*0x01af*/ 149,
- /*0x022a*/ 211,
- /*0x1caa*/ 565,
- /*0xa7b8*/ 1135,
- /*0x0554*/ 480,
- -1, -1,
- /*0x0538*/ 452,
- -1, -1,
- /*0x04a2*/ 374,
- /*0x10a7*/ 491,
- /*0x1ffc*/ 863,
- /*0x047c*/ 359,
- /*0x0184*/ 123,
- -1,
- /*0x1fba*/ 822,
- /*0x2160*/ 868,
- -1,
- /*0x1e902*/ 1496,
- -1,
- /*0xabba*/ 1224,
- /*0x216b*/ 879,
- -1,
- /*0x1efc*/ 713,
- /*0x1e7c*/ 647,
- -1, -1,
- /*0x1eba*/ 680,
- /*0x1e3a*/ 614,
- -1, -1,
- /*0x03a8*/ 264,
- -1,
- /*0x022e*/ 213,
- /*0x1cae*/ 569,
- -1,
- /*0x2cba*/ 1003,
- -1, -1,
- /*0x022c*/ 212,
- /*0x1cac*/ 567,
- -1, -1,
- /*0xa7ba*/ 1136,
- /*0x10af*/ 499,
- /*0x1057c*/ 1355,
- /*0x0182*/ 122,
- /*0x053a*/ 454,
- -1, -1, -1, -1, -1,
- /*0x04aa*/ 378,
- /*0x1f8d*/ 780,
- /*0x040d*/ 310,
- -1,
- /*0x1040d*/ 1281,
- -1,
- /*0xab8d*/ 1179,
- -1, -1, -1,
- /*0x01a2*/ 142,
- /*0x2c0d*/ 924,
- /*0x1f2f*/ 736,
- /*0x216d*/ 881,
- /*0x118a7*/ 1437,
- /*0x038e*/ 239,
- -1, -1, -1,
- /*0x0228*/ 210,
- /*0x1ca8*/ 563,
- /*0x038c*/ 238,
- -1, -1,
- /*0xff27*/ 1248,
- /*0x0130*/ 1529,
- -1, -1,
- /*0xabb0*/ 1214,
- /*0xa78d*/ 1111,
- -1, -1,
- /*0x10c8d*/ 1392,
- /*0x04ae*/ 380,
- /*0x1fdb*/ 843,
- /*0x1eb0*/ 675,
- /*0x1e30*/ 609,
- -1,
- /*0xfb04*/ 1234,
- /*0x04ac*/ 379,
- -1, -1, -1, -1,
- /*0x2cb0*/ 998,
- -1, -1,
- /*0x1fbe*/ 825,
- /*0x118af*/ 1445,
- /*0xa764*/ 1096,
- /*0x13fc*/ 528,
- /*0xa7b0*/ 1129,
- /*0xabbe*/ 1228,
- /*0x00db*/ 52,
- /*0x10cb0*/ 1427,
- /*0x10a2*/ 486,
- /*0x020e*/ 197,
- -1,
- /*0xff2f*/ 1256,
- /*0x1ebe*/ 682,
- /*0x1e3e*/ 616,
- -1,
- /*0x020c*/ 196,
- /*0x1fd3*/ 837,
- /*0x0053*/ 17,
- -1, -1,
- /*0x2164*/ 872,
- /*0x2cbe*/ 1005,
- -1, -1,
- /*0xfb02*/ 1232,
- /*0x04a8*/ 377,
- -1, -1,
- /*0xa7be*/ 1138,
- -1, -1, -1,
- /*0x053e*/ 458,
- -1, -1,
- /*0x00d3*/ 45,
- -1, -1, -1, -1,
- /*0x01ae*/ 148,
- -1, -1, -1, -1, -1,
- /*0x01ac*/ 147,
- /*0xa779*/ 1102,
- /*0x0553*/ 479,
- /*0x0232*/ 215,
- /*0x1cb2*/ 573,
- /*0x1fb6*/ 818,
- /*0x10aa*/ 494,
- /*0x0136*/ 83,
- -1, -1,
- /*0xabb6*/ 1220,
- /*0x1fca*/ 833,
- /*0x004a*/ 8,
- /*0x014a*/ 93,
- -1, -1,
- /*0x048e*/ 364,
- /*0x1eb6*/ 678,
- /*0x1e36*/ 612,
- /*0x118a2*/ 1432,
- -1, -1,
- /*0x048c*/ 363,
- /*0x1eca*/ 688,
- /*0x1e4a*/ 622,
- -1,
- /*0x2cb6*/ 1001,
- /*0x1f2a*/ 731,
- /*0x1cb8*/ 579,
- /*0xff22*/ 1243,
- /*0x00ca*/ 36,
- -1,
- /*0x2cca*/ 1011,
- /*0xa7b6*/ 1134,
- -1, -1, -1,
- /*0x0536*/ 450,
- /*0xa77d*/ 1104,
- /*0x10ae*/ 498,
- /*0x1fcb*/ 834,
- /*0x004b*/ 9,
- /*0x1e90e*/ 1508,
- /*0x054a*/ 470,
- -1,
- /*0x10ac*/ 496,
- -1, -1,
- /*0x1e90c*/ 1506,
- -1, -1, -1,
- /*0x1f87*/ 774,
- /*0x0407*/ 304,
- -1,
- /*0x10407*/ 1275,
- /*0x04b2*/ 382,
- /*0xab87*/ 1173,
- /*0x104b2*/ 1310,
- /*0x00cb*/ 37,
- /*0x1f2e*/ 735,
- -1,
- /*0x2c07*/ 918,
- /*0x118aa*/ 1440,
- -1, -1,
- /*0x1f2c*/ 733,
- -1,
- /*0x023a*/ 216,
- /*0x1cba*/ 581,
- /*0x018e*/ 129,
- -1,
- /*0x054b*/ 471,
- /*0xff2a*/ 1251,
- -1, -1, -1,
- /*0x04d4*/ 399,
- /*0x10a8*/ 492,
- /*0x1fb4*/ 817,
- /*0x04b8*/ 385,
- /*0x0134*/ 82,
- /*0x104b8*/ 1316,
- /*0x10c87*/ 1386,
- /*0xabb4*/ 1218,
- -1, -1, -1,
- /*0x03b0*/ 268,
- /*0xab71*/ 1151,
- -1,
- /*0x1eb4*/ 677,
- /*0x1e34*/ 611,
- -1, -1,
- /*0xa722*/ 1064,
- /*0x118ae*/ 1444,
- -1, -1,
- /*0x1f28*/ 729,
- /*0x2cb4*/ 1000,
- -1,
- /*0x118ac*/ 1442,
- /*0xab73*/ 1153,
- -1, -1,
- /*0xff2e*/ 1255,
- /*0xa7b4*/ 1133,
- -1, -1,
- /*0x01b2*/ 151,
- /*0x0534*/ 448,
- /*0xff2c*/ 1253,
- -1, -1,
- /*0xa654*/ 1037,
- -1,
- /*0x04fc*/ 419,
- -1,
- /*0x1fbc*/ 824,
- /*0x10588*/ 1367,
- /*0x04ba*/ 386,
- -1,
- /*0x104ba*/ 1318,
- /*0xabbc*/ 1226,
- -1,
- /*0x10589*/ 1368,
- -1, -1,
- /*0x0230*/ 214,
- /*0x1cb0*/ 571,
- /*0x1ebc*/ 681,
- /*0x1e3c*/ 615,
- -1,
- /*0x01b8*/ 155,
- /*0x118a8*/ 1438,
- /*0x1f0e*/ 721,
- /*0x1058a*/ 1369,
- -1,
- /*0xa72a*/ 1068,
- /*0x2cbc*/ 1004,
- -1,
- /*0x1f0c*/ 719,
- /*0x10580*/ 1359,
- -1,
- /*0xff28*/ 1249,
- -1,
- /*0xa7bc*/ 1137,
- -1, -1, -1,
- /*0x053c*/ 456,
- /*0x24b8*/ 887,
- /*0x023e*/ 219,
- /*0x1cbe*/ 583,
- /*0x10b2*/ 502,
- -1,
- /*0x212a*/ 865,
- -1, -1,
- /*0x10590*/ 1374,
- -1, -1, -1,
- /*0x1fd6*/ 838,
- /*0x0056*/ 20,
- /*0x0156*/ 99,
- -1, -1, -1, -1,
- /*0x01fc*/ 188,
- /*0xa72e*/ 1070,
- -1, -1, -1,
- /*0x1ed6*/ 694,
- /*0x1e56*/ 628,
- /*0xa72c*/ 1069,
- /*0x10b8*/ 508,
- -1, -1,
- /*0x04b0*/ 381,
- /*0x00d6*/ 48,
- /*0x104b0*/ 1308,
- /*0x2cd6*/ 1017,
- /*0x1e90d*/ 1507,
- -1,
- /*0xab7f*/ 1165,
- /*0xab7b*/ 1161,
- -1, -1,
- /*0xa7d6*/ 1147,
- /*0x24ba*/ 889,
- /*0x10586*/ 1365,
- /*0xab75*/ 1155,
- /*0x0556*/ 482,
- /*0x1f54*/ 753,
- -1, -1,
- /*0x1f38*/ 737,
- -1,
- /*0x1fc4*/ 828,
- /*0x0044*/ 3,
- -1,
- /*0x1cb6*/ 577,
- /*0x04be*/ 388,
- -1,
- /*0x104be*/ 1322,
- -1,
- /*0x024a*/ 226,
- /*0xa728*/ 1067,
- /*0x118b2*/ 1448,
- -1,
- /*0x1ec4*/ 685,
- /*0x1e44*/ 619,
- /*0xa688*/ 1054,
- -1, -1, -1,
- /*0x10ba*/ 510,
- /*0x00c4*/ 30,
- /*0xff32*/ 1259,
- /*0x2cc4*/ 1008,
- /*0x104d3*/ 1343,
- -1, -1, -1,
- /*0x10592*/ 1376,
- -1,
- /*0xa7c4*/ 1141,
- /*0x0050*/ 14,
- /*0x0150*/ 96,
- /*0xa68a*/ 1055,
- /*0x0544*/ 464,
- -1,
- /*0x118b8*/ 1454,
- -1, -1,
- /*0xa680*/ 1050,
- -1,
- /*0x1f3a*/ 739,
- /*0x1ed0*/ 691,
- /*0x1e50*/ 625,
- -1, -1,
- /*0xff38*/ 1265,
- /*0x01db*/ 170,
- -1,
- /*0x00d0*/ 42,
- /*0xab77*/ 1157,
- /*0x2cd0*/ 1014,
- /*0x1c87*/ 537,
- -1, -1, -1,
- /*0xa690*/ 1058,
- /*0x04b6*/ 384,
- /*0xa7d0*/ 1146,
- /*0x104b6*/ 1314,
- -1, -1,
- /*0x0550*/ 476,
- /*0x16e5f*/ 1493,
- /*0x16e5d*/ 1491,
- /*0x104ca*/ 1334,
- -1, -1, -1, -1,
- /*0x1fcc*/ 835,
- /*0x004c*/ 10,
- /*0x014c*/ 94,
- /*0xa698*/ 1062,
- -1, -1,
- /*0x01d3*/ 166,
- /*0x118ba*/ 1456,
- /*0x24be*/ 893,
- /*0x1cb4*/ 575,
- /*0x1f0d*/ 720,
- /*0x10b0*/ 500,
- /*0x1ecc*/ 689,
- /*0x1e4c*/ 623,
- -1, -1, -1,
- /*0xff3a*/ 1267,
- /*0xa732*/ 1071,
- /*0x00cc*/ 38,
- /*0xa686*/ 1053,
- /*0x2ccc*/ 1012,
- /*0x04cb*/ 395,
- -1,
- /*0x104cb*/ 1335,
- -1, -1, -1, -1,
- /*0x16e59*/ 1487,
- -1,
- /*0xa64a*/ 1032,
- /*0x054c*/ 472,
- -1, -1,
- /*0x10be*/ 514,
- /*0x2132*/ 867,
- /*0xa696*/ 1061,
- -1,
- /*0xa754*/ 1088,
- -1, -1,
- /*0xa738*/ 1074,
- /*0x1f5b*/ 756,
- -1,
- /*0x1fc8*/ 831,
- /*0x0048*/ 7,
- /*0x01ca*/ 161,
- -1, -1, -1, -1,
- /*0x03d6*/ 274,
- -1,
- /*0xa692*/ 1059,
- -1,
- /*0x1f3e*/ 743,
- /*0x1ec8*/ 687,
- /*0x1e48*/ 621,
- /*0x24b6*/ 885,
- /*0x1e907*/ 1501,
- /*0x04b4*/ 383,
- -1,
- /*0x104b4*/ 1312,
- /*0x00c8*/ 34,
- /*0x24ca*/ 905,
- /*0x2cc8*/ 1010,
- -1,
- /*0x118b0*/ 1446,
- -1, -1,
- /*0xa69a*/ 1063,
- -1,
- /*0x004e*/ 12,
- /*0x014e*/ 95,
- -1,
- /*0x01cb*/ 162,
- /*0x0548*/ 468,
- /*0xff30*/ 1257,
- -1, -1, -1, -1,
- /*0xa73a*/ 1075,
- /*0x1ece*/ 690,
- /*0x1e4e*/ 624,
- /*0x10b6*/ 506,
- -1,
- /*0x0187*/ 125,
- -1, -1,
- /*0x00ce*/ 40,
- /*0x118be*/ 1460,
- /*0x2cce*/ 1013,
- /*0x24cb*/ 906,
- /*0x1fc2*/ 826,
- /*0x0042*/ 1,
- -1,
- /*0x16e57*/ 1485,
- -1,
- /*0x10594*/ 1377,
- /*0x04bc*/ 387,
- -1,
- /*0x104bc*/ 1320,
- /*0x054e*/ 474,
- -1, -1,
- /*0x1ec2*/ 684,
- /*0x1e42*/ 618,
- /*0x1fd2*/ 836,
- /*0x0052*/ 16,
- /*0x0152*/ 97,
- -1,
- /*0x1f4a*/ 747,
- /*0x00c2*/ 28,
- -1,
- /*0x2cc2*/ 1007,
- /*0x10583*/ 1362,
- /*0x03d0*/ 271,
- -1, -1,
- /*0x1ed2*/ 692,
- /*0x1e52*/ 626,
- /*0xa7c2*/ 1140,
- -1, -1, -1,
- /*0x0542*/ 462,
- /*0x00d2*/ 44,
- -1,
- /*0x2cd2*/ 1015,
- /*0x0244*/ 222,
- -1, -1, -1,
- /*0x1fc6*/ 829,
- /*0x0046*/ 5,
- -1,
- /*0x1fd8*/ 840,
- /*0x0058*/ 22,
- /*0x0158*/ 100,
- /*0x0552*/ 478,
- /*0x1f4b*/ 748,
- /*0x118b6*/ 1452,
- -1, -1,
- /*0x04d6*/ 400,
- /*0x1ec6*/ 686,
- /*0x1e46*/ 620,
- -1,
- /*0x1ed8*/ 695,
- /*0x1e58*/ 629,
- /*0xab79*/ 1159,
- /*0xff36*/ 1263,
- /*0x00c6*/ 32,
- /*0x01bc*/ 156,
- /*0x2cc6*/ 1009,
- /*0x00d8*/ 49,
- -1,
- /*0x2cd8*/ 1018,
- /*0x10b4*/ 504,
- -1, -1,
- /*0xa7c6*/ 1143,
- /*0x1fab*/ 810,
- /*0x042b*/ 340,
- /*0xa7d8*/ 1148,
- /*0x0546*/ 466,
- /*0xa73e*/ 1077,
- /*0xabab*/ 1209,
- -1,
- /*0x1ec0*/ 683,
- /*0x1e40*/ 617,
- /*0x24bc*/ 891,
- /*0x2c2b*/ 954,
- -1, -1, -1,
- /*0x00c0*/ 26,
- -1,
- /*0x2cc0*/ 1006,
- /*0x1fec*/ 853,
- /*0x046c*/ 351,
- /*0x016c*/ 110,
- /*0xa656*/ 1038,
- /*0x013d*/ 86,
- /*0x104c4*/ 1328,
- /*0xa7c0*/ 1139,
- /*0xabbd*/ 1227,
- /*0xab7d*/ 1163,
- -1,
- /*0x0540*/ 460,
- /*0xa7ab*/ 1125,
- /*0x1eec*/ 705,
- /*0x1e6c*/ 639,
- /*0x10cab*/ 1422,
- /*0xa694*/ 1060,
- -1, -1,
- /*0x024c*/ 227,
- /*0x10bc*/ 512,
- -1, -1, -1,
- /*0x1fc9*/ 832,
- /*0x0049*/ 1528,
- /*0x0149*/ 92,
- -1,
- /*0x1fa9*/ 808,
- /*0x0429*/ 338,
- -1, -1,
- /*0x04d0*/ 397,
- /*0xaba9*/ 1207,
- /*0x104d0*/ 1340,
- /*0x053d*/ 457,
- -1,
- /*0x118b4*/ 1450,
- /*0x2c29*/ 952,
- /*0xa736*/ 1073,
- -1,
- /*0x1f3c*/ 741,
- /*0xa644*/ 1029,
- /*0x00c9*/ 35,
- -1,
- /*0xa74a*/ 1083,
- /*0x16e41*/ 1463,
- /*0xff34*/ 1261,
- /*0x1fda*/ 842,
- /*0x005a*/ 24,
- /*0x015a*/ 101,
- -1,
- /*0xa7c9*/ 1145,
- /*0x1fea*/ 851,
- /*0x046a*/ 350,
- /*0x016a*/ 109,
- /*0x0549*/ 469,
- -1,
- /*0x01c4*/ 157,
- /*0x10ca9*/ 1420,
- /*0x1eda*/ 696,
- /*0x1e5a*/ 630,
- -1, -1,
- /*0x0248*/ 225,
- /*0x1eea*/ 704,
- /*0x1e6a*/ 638,
- /*0x00da*/ 51,
- -1,
- /*0x2cda*/ 1019,
- /*0xa650*/ 1035,
- -1, -1,
- /*0x03c2*/ 269,
- /*0x104cc*/ 1336,
- -1,
- /*0x24c4*/ 899,
- /*0x118bc*/ 1458,
- -1,
- /*0x10584*/ 1363,
- /*0x1fe2*/ 844,
- /*0x0462*/ 346,
- /*0x0162*/ 105,
- -1,
- /*0x1fa1*/ 800,
- /*0x0421*/ 330,
- /*0x1f56*/ 754,
- /*0x10421*/ 1301,
- -1,
- /*0xaba1*/ 1199,
- /*0x2c62*/ 960,
- /*0x024e*/ 228,
- /*0x1ee2*/ 700,
- /*0x1e62*/ 634,
- /*0x2c21*/ 944,
- -1, -1, -1,
- /*0x1fc7*/ 830,
- /*0x0047*/ 6,
- /*0x0147*/ 91,
- /*0x2ce2*/ 1023,
- -1,
- /*0x10c4*/ 520,
- /*0x0045*/ 4,
- /*0x0145*/ 90,
- -1, -1, -1,
- /*0x1fb9*/ 821,
- /*0xa64c*/ 1033,
- /*0x0139*/ 84,
- /*0x10582*/ 1361,
- /*0xa734*/ 1072,
- /*0xabb9*/ 1223,
- /*0x10ca1*/ 1412,
- /*0x03d8*/ 275,
- /*0x00c7*/ 33,
- /*0x0055*/ 19,
- /*0x104c8*/ 1332,
- -1, -1,
- /*0x00c5*/ 31,
- -1, -1, -1,
- /*0xa7c7*/ 1144,
- -1, -1, -1,
- /*0x0547*/ 467,
- /*0xa7c5*/ 1142,
- -1,
- /*0x0345*/ 229,
- -1,
- /*0x0545*/ 465,
- /*0x00d5*/ 47,
- -1,
- /*0x1fe8*/ 849,
- /*0x0468*/ 349,
- /*0x0168*/ 108,
- /*0x0539*/ 453,
- /*0x03ab*/ 267,
- -1,
- /*0x24cc*/ 907,
- -1,
- /*0x104ce*/ 1338,
- -1, -1,
- /*0x0555*/ 481,
- /*0x1ee8*/ 703,
- /*0x1e68*/ 637,
- /*0x1f50*/ 751,
- /*0xa73c*/ 1076,
- /*0x0246*/ 224,
- /*0xa648*/ 1031,
- -1, -1, -1,
- /*0x03ec*/ 285,
- /*0x1f97*/ 790,
- /*0x0417*/ 320,
- -1,
- /*0x10417*/ 1291,
- -1,
- /*0xab97*/ 1189,
- /*0x1ff2*/ 854,
- /*0x0472*/ 354,
- /*0x0172*/ 113,
- /*0x104c2*/ 1326,
- /*0x2c17*/ 934,
- /*0x01c8*/ 160,
- /*0x1e97*/ 661,
- -1, -1,
- /*0xa684*/ 1052,
- /*0x2c72*/ 970,
- -1,
- /*0x1ef2*/ 708,
- /*0x1e72*/ 642,
- -1,
- /*0x04d2*/ 398,
- /*0xa64e*/ 1034,
- /*0x104d2*/ 1342,
- /*0x1cab*/ 566,
- -1,
- /*0x03a9*/ 265,
- /*0x2cf2*/ 1026,
- -1,
- /*0x24c8*/ 903,
- -1,
- /*0x10c97*/ 1402,
- /*0x1f4c*/ 749,
- -1, -1, -1,
- /*0x0372*/ 231,
- -1,
- /*0xa756*/ 1089,
- -1,
- /*0x10572*/ 1346,
- -1,
- /*0x023d*/ 218,
- /*0x1cbd*/ 582,
- -1,
- /*0xa642*/ 1028,
- /*0x03da*/ 276,
- -1,
- /*0xa682*/ 1051,
- /*0x104c6*/ 1330,
- /*0x04d8*/ 401,
- /*0x03ea*/ 284,
- -1, -1,
- /*0x046e*/ 352,
- /*0x016e*/ 111,
- /*0x24ce*/ 909,
- -1, -1,
- /*0xa652*/ 1036,
- -1, -1, -1,
- /*0x2c6e*/ 967,
- /*0x015e*/ 103,
- /*0x1eee*/ 706,
- /*0x1e6e*/ 640,
- -1,
- /*0x1ca9*/ 564,
- -1, -1,
- /*0x04c0*/ 389,
- -1,
- /*0x104c0*/ 1324,
- /*0x1ede*/ 698,
- /*0x1e5e*/ 632,
- /*0xa744*/ 1080,
- /*0x1f48*/ 745,
- /*0x03e2*/ 280,
- /*0x24c2*/ 897,
- -1,
- /*0x00de*/ 55,
- /*0x03a1*/ 258,
- /*0x2cde*/ 1021,
- -1,
- /*0xa646*/ 1030,
- -1, -1,
- /*0xa658*/ 1039,
- -1, -1, -1, -1,
- /*0x04ec*/ 411,
- /*0x1fc3*/ 827,
- /*0x0043*/ 2,
- /*0x0143*/ 89,
- /*0x104bd*/ 1321,
- -1,
- /*0x1fe6*/ 847,
- /*0x0466*/ 348,
- /*0x0166*/ 107,
- -1, -1,
- /*0xa750*/ 1086,
- -1,
- /*0x10c2*/ 518,
- -1, -1,
- /*0xa640*/ 1027,
- -1,
- /*0x1ee6*/ 702,
- /*0x1e66*/ 636,
- /*0x00c3*/ 29,
- -1,
- /*0x03d5*/ 273,
- /*0x04c9*/ 394,
- -1,
- /*0x104c9*/ 1333,
- /*0x24c6*/ 901,
- /*0x1fad*/ 812,
- /*0x042d*/ 342,
- /*0x1058e*/ 1372,
- -1,
- /*0x1ca1*/ 556,
- /*0xabad*/ 1211,
- /*0x0543*/ 463,
- -1,
- /*0x1058c*/ 1370,
- -1,
- /*0x2c2d*/ 956,
- /*0xa66c*/ 1049,
- -1, -1, -1, -1,
- /*0x03e8*/ 283,
- -1, -1, -1,
- /*0x04da*/ 402,
- /*0x1f52*/ 752,
- /*0x0245*/ 223,
- /*0x24c0*/ 895,
- /*0xa74c*/ 1084,
- /*0x04ea*/ 410,
- -1,
- /*0x01ec*/ 178,
- /*0xa7ad*/ 1127,
- /*0x1cb9*/ 580,
- -1,
- /*0x10cad*/ 1424,
- -1, -1, -1, -1, -1, -1,
- /*0x0397*/ 248,
- /*0x1fbb*/ 823,
- /*0xab7c*/ 1162,
- /*0x013b*/ 85,
- -1, -1,
- /*0xabbb*/ 1225,
- -1, -1,
- /*0x24bd*/ 892,
- -1, -1,
- /*0x10c0*/ 516,
- -1,
- /*0x04e2*/ 406,
- -1,
- /*0x01a9*/ 146,
- /*0x10ab*/ 495,
- /*0x1fa5*/ 804,
- /*0x0425*/ 334,
- /*0xa65a*/ 1040,
- /*0x10425*/ 1305,
- -1,
- /*0xaba5*/ 1203,
- /*0x1fb7*/ 819,
- /*0xa66a*/ 1048,
- -1, -1,
- /*0x2c25*/ 948,
- /*0xabb7*/ 1221,
- /*0x24c9*/ 904,
- /*0xa748*/ 1082,
- /*0x04c7*/ 393,
- /*0x053b*/ 455,
- /*0x104c7*/ 1331,
- -1,
- /*0x10bd*/ 513,
- /*0x04c5*/ 392,
- /*0x1f2b*/ 732,
- /*0x104c5*/ 1329,
- -1,
- /*0x01ea*/ 177,
- /*0x1c97*/ 546,
- -1,
- /*0x1e921*/ 1527,
- /*0x104b9*/ 1317,
- -1, -1, -1,
- /*0x10ca5*/ 1416,
- -1, -1,
- /*0xa662*/ 1044,
- /*0x03ee*/ 286,
- -1,
- /*0x1f6c*/ 763,
- /*0x0537*/ 451,
- /*0x1f3d*/ 742,
- /*0xa74e*/ 1085,
- -1,
- /*0xa68e*/ 1057,
- /*0x10a9*/ 493,
- /*0x03de*/ 278,
- -1, -1, -1,
- /*0xa68c*/ 1056,
- -1,
- /*0x01e2*/ 173,
- -1,
- /*0x1fa3*/ 802,
- /*0x0423*/ 332,
- /*0x04e8*/ 409,
- /*0x10423*/ 1303,
- /*0x118ab*/ 1441,
- /*0xaba3*/ 1201,
- -1, -1,
- /*0x1f49*/ 746,
- -1,
- /*0x2c23*/ 946,
- /*0xa742*/ 1079,
- /*0x1f29*/ 730,
- -1,
- /*0xff2b*/ 1252,
- -1,
- /*0x01c7*/ 159,
- -1, -1, -1, -1,
- /*0x01c5*/ 158,
- -1,
- /*0x118bd*/ 1459,
- /*0x004d*/ 11,
- /*0xa752*/ 1087,
- -1, -1, -1,
- /*0x03e6*/ 282,
- /*0x04f2*/ 414,
- /*0x10ca3*/ 1414,
- -1, -1,
- /*0x24c7*/ 902,
- /*0x01d5*/ 167,
- -1,
- /*0x1f6a*/ 761,
- /*0x1058d*/ 1371,
- /*0x24c5*/ 900,
- /*0xa668*/ 1047,
- -1,
- /*0x00cd*/ 39,
- -1, -1,
- /*0x24b9*/ 888,
- -1,
- /*0x10a1*/ 485,
- /*0x118a9*/ 1439,
- -1,
- /*0x1e917*/ 1517,
- /*0xa746*/ 1081,
- -1,
- /*0x16e54*/ 1482,
- /*0xa758*/ 1090,
- /*0x054d*/ 473,
- /*0x01e8*/ 176,
- -1,
- /*0xff29*/ 1250,
- -1, -1,
- /*0x10c7*/ 522,
- /*0x0470*/ 353,
- /*0x0170*/ 112,
- -1,
- /*0x0243*/ 221,
- /*0x10c5*/ 521,
- -1, -1, -1, -1,
- /*0x2c70*/ 969,
- /*0x10b9*/ 509,
- /*0x1ef0*/ 707,
- /*0x1e70*/ 641,
- /*0xa740*/ 1078,
- -1,
- /*0x04ee*/ 412,
- /*0x0197*/ 136,
- -1,
- /*0x1f9d*/ 796,
- /*0x041d*/ 326,
- -1,
- /*0x1041d*/ 1297,
- /*0x01f2*/ 182,
- /*0xab9d*/ 1195,
- /*0x04de*/ 404,
- -1, -1, -1,
- /*0x2c1d*/ 940,
- /*0x0370*/ 230,
- /*0x1cad*/ 568,
- /*0x1f39*/ 738,
- -1,
- /*0x10570*/ 1344,
- -1,
- /*0xa76c*/ 1100,
- /*0x212b*/ 866,
- /*0xabb5*/ 1219,
- -1, -1, -1, -1,
- /*0x118a1*/ 1431,
- -1,
- /*0x03a5*/ 261,
- /*0x1f9b*/ 794,
- /*0x041b*/ 324,
- -1,
- /*0x1041b*/ 1295,
- /*0x10c9d*/ 1408,
- /*0xab9b*/ 1193,
- /*0x00b5*/ 25,
- /*0xff21*/ 1242,
- /*0x216c*/ 880,
- -1,
- /*0x2c1b*/ 938,
- /*0x04c3*/ 391,
- /*0x1e9b*/ 665,
- /*0x104c3*/ 1327,
- -1,
- /*0x1f68*/ 759,
- /*0x04e6*/ 408,
- /*0xa65e*/ 1042,
- -1,
- /*0x0535*/ 449,
- -1, -1,
- /*0x118b9*/ 1455,
- /*0x023b*/ 217,
- /*0x01ee*/ 179,
- /*0x1f95*/ 788,
- /*0x0415*/ 318,
- -1,
- /*0x10415*/ 1289,
- -1,
- /*0xab95*/ 1187,
- /*0x10c9b*/ 1406,
- /*0xff39*/ 1266,
- /*0x01de*/ 171,
- -1,
- /*0x2c15*/ 932,
- -1,
- /*0xa75a*/ 1091,
- -1, -1, -1,
- /*0x1ca5*/ 560,
- /*0xa76a*/ 1099,
- /*0x1f99*/ 792,
- /*0x0419*/ 322,
- -1,
- /*0x10419*/ 1293,
- /*0x1cb7*/ 578,
- /*0xab99*/ 1191,
- /*0xfb17*/ 1241,
- -1,
- /*0x03a3*/ 259,
- /*0x1fb3*/ 816,
- /*0x2c19*/ 936,
- /*0xa666*/ 1046,
- /*0x1e99*/ 663,
- /*0x10c95*/ 1400,
- /*0xabb3*/ 1217,
- /*0x1f93*/ 786,
- /*0x0413*/ 316,
- /*0x216a*/ 878,
- /*0x10413*/ 1287,
- /*0x16e5b*/ 1489,
- /*0xab93*/ 1185,
- -1, -1, -1, -1,
- /*0x2c13*/ 930,
- /*0xa762*/ 1095,
- /*0x01e6*/ 175,
- -1, -1,
- /*0x0587*/ 483,
- /*0x10c99*/ 1404,
- /*0x10587*/ 1366,
- /*0x1f91*/ 784,
- /*0x0411*/ 314,
- /*0x104bb*/ 1319,
- /*0x10411*/ 1285,
- /*0xa7b3*/ 1132,
- /*0xab91*/ 1183,
- -1,
- /*0x24c3*/ 898,
- /*0x0533*/ 447,
- -1,
- /*0x2c11*/ 928,
- /*0x2162*/ 870,
- /*0x004f*/ 13,
- /*0x10c93*/ 1398,
- /*0x1f6e*/ 765,
- /*0x16e53*/ 1481,
- -1,
- /*0x1ca3*/ 558,
- -1,
- /*0x1f8f*/ 782,
- /*0x040f*/ 312,
- -1,
- /*0x1040f*/ 1283,
- -1,
- /*0xab8f*/ 1181,
- /*0x104b7*/ 1315,
- -1, -1, -1,
- /*0x2c0f*/ 926,
- /*0x00cf*/ 41,
- /*0x10c91*/ 1396,
- /*0x1f81*/ 768,
- /*0x0401*/ 298,
- /*0x10c3*/ 519,
- /*0x10401*/ 1269,
- /*0x03f0*/ 287,
- /*0xab81*/ 1167,
- -1, -1, -1, -1,
- /*0x2c01*/ 912,
- /*0x054f*/ 475,
- -1, -1,
- /*0x1ff4*/ 856,
- /*0x0474*/ 355,
- /*0x0174*/ 114,
- -1,
- /*0x10c8f*/ 1394,
- /*0xa768*/ 1098,
- -1,
- /*0x047e*/ 360,
- -1,
- /*0x039d*/ 254,
- /*0x16e4a*/ 1472,
- /*0x015c*/ 102,
- /*0x1ef4*/ 709,
- /*0x1e74*/ 643,
- /*0x10ad*/ 497,
- -1,
- /*0x2c7e*/ 972,
- /*0x10c81*/ 1380,
- /*0x1efe*/ 714,
- /*0x1e7e*/ 648,
- -1,
- /*0x1edc*/ 697,
- /*0x1e5c*/ 631,
- /*0x2168*/ 876,
- /*0x013f*/ 87,
- -1,
- /*0x24bb*/ 890,
- /*0xabbf*/ 1229,
- /*0x00dc*/ 53,
- /*0xabb1*/ 1215,
- /*0x2cdc*/ 1020,
- /*0x01b7*/ 154,
- -1, -1,
- /*0x10574*/ 1348,
- /*0x1f2d*/ 734,
- /*0x039b*/ 252,
- -1, -1,
- /*0x16e4b*/ 1473,
- /*0x1057e*/ 1357,
- -1, -1, -1, -1, -1,
- /*0x04cd*/ 396,
- -1,
- /*0x104cd*/ 1337,
- /*0x24b7*/ 886,
- -1,
- /*0x1c9d*/ 552,
- /*0xa7b1*/ 1130,
- /*0x10bb*/ 511,
- /*0x053f*/ 459,
- /*0x10cb1*/ 1428,
- /*0x0531*/ 445,
- /*0x1f9f*/ 798,
- /*0x041f*/ 328,
- -1,
- /*0x1041f*/ 1299,
- /*0x0395*/ 246,
- /*0xab9f*/ 1197,
- -1, -1,
- /*0x1cb5*/ 576,
- -1,
- /*0x2c1f*/ 942,
- -1, -1,
- /*0x10a5*/ 489,
- /*0x118ad*/ 1443,
- -1, -1,
- /*0x1f3b*/ 740,
- -1,
- /*0x10b7*/ 507,
- -1,
- /*0x1c9b*/ 550,
- /*0x0399*/ 250,
- /*0xa76e*/ 1101,
- /*0xff2d*/ 1254,
- /*0x1f85*/ 772,
- /*0x0405*/ 302,
- /*0x04f0*/ 413,
- /*0x10405*/ 1273,
- -1,
- /*0xab85*/ 1171,
- /*0x10c9f*/ 1410,
- /*0xa75e*/ 1093,
- -1, -1,
- /*0x2c05*/ 916,
- -1,
- /*0x0393*/ 244,
- -1, -1,
- /*0x0051*/ 15,
- /*0x216e*/ 882,
- -1,
- /*0x01cd*/ 163,
- -1, -1,
- /*0x1c95*/ 544,
- /*0x1f8b*/ 778,
- /*0x040b*/ 308,
- -1,
- /*0x1040b*/ 1279,
- -1,
- /*0xab8b*/ 1177,
- /*0x118bb*/ 1457,
- -1,
- /*0x0391*/ 242,
- /*0x10c85*/ 1384,
- /*0x2c0b*/ 922,
- /*0x00d1*/ 43,
- -1, -1,
- /*0x24cd*/ 908,
- /*0x104b5*/ 1313,
- -1,
- /*0x1c99*/ 548,
- /*0x10a3*/ 487,
- /*0x03cf*/ 270,
- -1, -1,
- /*0xa766*/ 1097,
- /*0x118a5*/ 1435,
- /*0x0551*/ 477,
- /*0x1e91d*/ 1523,
- /*0x1cb3*/ 574,
- /*0x038f*/ 240,
- /*0xa78b*/ 1110,
- /*0x118b7*/ 1453,
- -1,
- /*0x10c8b*/ 1390,
- /*0x1c93*/ 542,
- /*0xff25*/ 1246,
- /*0x01f0*/ 180,
- /*0x1ff6*/ 857,
- /*0x0476*/ 356,
- /*0x0176*/ 115,
- -1,
- /*0xff37*/ 1264,
- /*0x2166*/ 874,
- /*0x10cd*/ 523,
- -1, -1, -1,
- /*0x1ffa*/ 861,
- /*0x047a*/ 358,
- /*0x1ef6*/ 710,
- /*0x1e76*/ 644,
- -1,
- /*0x1c91*/ 540,
- -1,
- /*0x1e91b*/ 1521,
- /*0x019d*/ 139,
- /*0x03f4*/ 289,
- -1, -1,
- /*0x1efa*/ 712,
- /*0x1e7a*/ 646,
- /*0x16e56*/ 1484,
- /*0x03fe*/ 295,
- -1,
- /*0x1f4d*/ 750,
- /*0x03dc*/ 277,
- -1,
- /*0x0376*/ 232,
- -1,
- /*0x01b5*/ 153,
- -1,
- /*0x10576*/ 1350,
- -1,
- /*0x1ff8*/ 859,
- /*0x0478*/ 357,
- /*0x0178*/ 116,
- -1,
- /*0x118a3*/ 1433,
- -1,
- /*0x1e915*/ 1515,
- -1,
- /*0x1057a*/ 1354,
- /*0x104b3*/ 1311,
- -1,
- /*0x1c81*/ 531,
- /*0x1ef8*/ 711,
- /*0x1e78*/ 645,
- /*0xff23*/ 1244,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1,
- /*0x1e919*/ 1519,
- -1,
- /*0x16e44*/ 1466,
- -1, -1, -1, -1, -1, -1,
- -1,
- /*0x10578*/ 1352,
- -1, -1, -1, -1,
- /*0x1e913*/ 1513,
- /*0x039f*/ 256,
- /*0x10b5*/ 505,
- -1, -1,
- /*0x104cf*/ 1339,
- -1, -1,
- /*0x1cbf*/ 584,
- /*0x1f1d*/ 728,
- /*0x1cb1*/ 572,
- -1, -1, -1, -1,
- /*0x16e50*/ 1478,
- -1, -1,
- /*0x1e911*/ 1511,
- -1, -1, -1,
- /*0x01b3*/ 152,
- -1, -1, -1, -1,
- /*0x13fa*/ 526,
- /*0x0193*/ 133,
- -1, -1, -1, -1, -1, -1,
- -1,
- /*0x1f1b*/ 726,
- /*0x1e90f*/ 1509,
- /*0x04f4*/ 415,
- -1,
- /*0x03d1*/ 272,
- -1, -1,
- /*0x1c9f*/ 554,
- /*0x04fe*/ 420,
- -1,
- /*0x0191*/ 132,
- /*0x04dc*/ 403,
- -1, -1,
- /*0x1e901*/ 1495,
- -1, -1,
- /*0x13f8*/ 524,
- -1,
- /*0x16e4c*/ 1474,
- -1,
- /*0x01cf*/ 164,
- -1,
- /*0x118b5*/ 1451,
- -1, -1,
- /*0x104bf*/ 1323,
- -1,
- /*0x104b1*/ 1309,
- /*0x018f*/ 130,
- -1,
- /*0x10b3*/ 503,
- /*0x1c85*/ 535,
- /*0xff35*/ 1262,
- -1, -1, -1,
- /*0xfb15*/ 1239,
- -1,
- /*0x24cf*/ 910,
- -1, -1,
- /*0x0181*/ 121,
- /*0x1f19*/ 724,
- -1, -1, -1, -1, -1,
- /*0xa65c*/ 1041,
- -1, -1, -1, -1, -1, -1,
- /*0x01f4*/ 183,
- /*0x03fa*/ 293,
- -1, -1, -1, -1,
- /*0x01fe*/ 189,
- -1,
- /*0x16e48*/ 1470,
- -1, -1, -1, -1, -1,
- /*0xfb13*/ 1237,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1,
- /*0x01b1*/ 150,
- -1, -1, -1, -1,
- /*0x1e91f*/ 1525,
- -1, -1,
- /*0x118b3*/ 1449,
- -1, -1,
- /*0x16e4e*/ 1476,
- -1, -1, -1,
- /*0x1f0f*/ 722,
- /*0x24bf*/ 894,
- -1,
- /*0xff33*/ 1260,
- -1,
- /*0x104d1*/ 1341,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1,
- /*0x1e905*/ 1499,
- -1, -1,
- /*0x019f*/ 140,
- /*0x16e42*/ 1464,
- -1, -1, -1, -1, -1,
- /*0xfb01*/ 1231,
- -1, -1,
- /*0x10bf*/ 515,
- -1,
- /*0x10b1*/ 501,
- -1, -1,
- /*0x16e52*/ 1480,
- -1, -1, -1,
- /*0x1e90b*/ 1505,
- -1, -1, -1, -1, -1, -1,
- -1, -1,
- /*0x04f6*/ 416,
- -1, -1,
- /*0x1f3f*/ 744,
- -1, -1, -1, -1, -1, -1,
- /*0x04fa*/ 418,
- /*0x01d1*/ 165,
- -1,
- /*0x16e46*/ 1468,
- -1, -1,
- /*0x16e58*/ 1486,
- -1, -1,
- /*0x018b*/ 128,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1,
- /*0x04f8*/ 417,
- /*0x16e40*/ 1462,
- -1,
- /*0x118bf*/ 1461,
- -1,
- /*0x118b1*/ 1447,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1,
- /*0xff31*/ 1258,
- -1, -1,
- /*0x01f6*/ 184,
- -1, -1, -1, -1, -1, -1,
- -1, -1,
- /*0xab72*/ 1152,
- /*0x01fa*/ 187,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1,
- /*0xfb05*/ 1235,
- -1, -1, -1, -1, -1, -1,
- /*0x16e49*/ 1471,
- -1, -1,
- /*0x1f0b*/ 718,
- -1, -1, -1, -1,
- /*0x01f8*/ 186,
- -1, -1, -1, -1, -1, -1,
- -1, -1,
- /*0xa77e*/ 1105,
- -1, -1,
- /*0xa75c*/ 1092,
- -1, -1, -1,
- /*0x16e5a*/ 1488,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1,
- /*0x16e47*/ 1469,
- -1, -1, -1, -1,
- /*0x16e45*/ 1467,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1,
- /*0x16e55*/ 1483,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1,
- /*0x16e5e*/ 1492,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1,
- /*0x16e43*/ 1465,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1,
- /*0xab70*/ 1150,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1,
- /*0x16e4d*/ 1475,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1,
- /*0x10595*/ 1378,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1,
- /*0xab74*/ 1154,
- -1, -1, -1, -1, -1,
- /*0xab7e*/ 1164,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1,
- /*0x10591*/ 1375,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- /*0x1058f*/ 1373,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- /*0x10581*/ 1360,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1,
- /*0x16e4f*/ 1477,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- /*0xab76*/ 1156,
- -1, -1, -1, -1, -1,
- /*0x10585*/ 1364,
- -1, -1, -1,
- /*0xab7a*/ 1160,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1,
- /*0x16e5c*/ 1490,
- -1, -1, -1, -1,
- /*0xab78*/ 1158,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1,
- /*0x16e51*/ 1479
- };
-
- if (code <= MAX_CODE_VALUE && code >= MIN_CODE_VALUE)
- {
- register unsigned int key = onigenc_unicode_CaseFold_11_hash(code);
-
- if (key <= MAX_HASH_VALUE)
- {
- register short s = wordlist[key];
-
- if (s >= 0 && code1_equal(code, CaseFold_11_Table[s].from))
- return &CaseFold_11_Table[s].to;
- }
- }
- return 0;
-}
-
-static const CaseUnfold_11_Type CaseUnfold_11_Table[] = {
-#define CaseUnfold_11 (*(CaseUnfold_11_Type (*)[1395])(CaseUnfold_11_Table+0))
- {0x0061, {1|U, {0x0041}}},
- {0x0062, {1|U, {0x0042}}},
- {0x0063, {1|U, {0x0043}}},
- {0x0064, {1|U, {0x0044}}},
- {0x0065, {1|U, {0x0045}}},
- {0x0066, {1|U, {0x0046}}},
- {0x0067, {1|U, {0x0047}}},
- {0x0068, {1|U, {0x0048}}},
- {0x006a, {1|U, {0x004a}}},
- {0x006b, {2|U, {0x004b, 0x212a}}},
- {0x006c, {1|U, {0x004c}}},
- {0x006d, {1|U, {0x004d}}},
- {0x006e, {1|U, {0x004e}}},
- {0x006f, {1|U, {0x004f}}},
- {0x0070, {1|U, {0x0050}}},
- {0x0071, {1|U, {0x0051}}},
- {0x0072, {1|U, {0x0052}}},
- {0x0073, {2|U, {0x0053, 0x017f}}},
- {0x0074, {1|U, {0x0054}}},
- {0x0075, {1|U, {0x0055}}},
- {0x0076, {1|U, {0x0056}}},
- {0x0077, {1|U, {0x0057}}},
- {0x0078, {1|U, {0x0058}}},
- {0x0079, {1|U, {0x0059}}},
- {0x007a, {1|U, {0x005a}}},
- {0x00e0, {1|U, {0x00c0}}},
- {0x00e1, {1|U, {0x00c1}}},
- {0x00e2, {1|U, {0x00c2}}},
- {0x00e3, {1|U, {0x00c3}}},
- {0x00e4, {1|U, {0x00c4}}},
- {0x00e5, {2|U, {0x00c5, 0x212b}}},
- {0x00e6, {1|U, {0x00c6}}},
- {0x00e7, {1|U, {0x00c7}}},
- {0x00e8, {1|U, {0x00c8}}},
- {0x00e9, {1|U, {0x00c9}}},
- {0x00ea, {1|U, {0x00ca}}},
- {0x00eb, {1|U, {0x00cb}}},
- {0x00ec, {1|U, {0x00cc}}},
- {0x00ed, {1|U, {0x00cd}}},
- {0x00ee, {1|U, {0x00ce}}},
- {0x00ef, {1|U, {0x00cf}}},
- {0x00f0, {1|U, {0x00d0}}},
- {0x00f1, {1|U, {0x00d1}}},
- {0x00f2, {1|U, {0x00d2}}},
- {0x00f3, {1|U, {0x00d3}}},
- {0x00f4, {1|U, {0x00d4}}},
- {0x00f5, {1|U, {0x00d5}}},
- {0x00f6, {1|U, {0x00d6}}},
- {0x00f8, {1|U, {0x00d8}}},
- {0x00f9, {1|U, {0x00d9}}},
- {0x00fa, {1|U, {0x00da}}},
- {0x00fb, {1|U, {0x00db}}},
- {0x00fc, {1|U, {0x00dc}}},
- {0x00fd, {1|U, {0x00dd}}},
- {0x00fe, {1|U, {0x00de}}},
- {0x00ff, {1|U, {0x0178}}},
- {0x0101, {1|U, {0x0100}}},
- {0x0103, {1|U, {0x0102}}},
- {0x0105, {1|U, {0x0104}}},
- {0x0107, {1|U, {0x0106}}},
- {0x0109, {1|U, {0x0108}}},
- {0x010b, {1|U, {0x010a}}},
- {0x010d, {1|U, {0x010c}}},
- {0x010f, {1|U, {0x010e}}},
- {0x0111, {1|U, {0x0110}}},
- {0x0113, {1|U, {0x0112}}},
- {0x0115, {1|U, {0x0114}}},
- {0x0117, {1|U, {0x0116}}},
- {0x0119, {1|U, {0x0118}}},
- {0x011b, {1|U, {0x011a}}},
- {0x011d, {1|U, {0x011c}}},
- {0x011f, {1|U, {0x011e}}},
- {0x0121, {1|U, {0x0120}}},
- {0x0123, {1|U, {0x0122}}},
- {0x0125, {1|U, {0x0124}}},
- {0x0127, {1|U, {0x0126}}},
- {0x0129, {1|U, {0x0128}}},
- {0x012b, {1|U, {0x012a}}},
- {0x012d, {1|U, {0x012c}}},
- {0x012f, {1|U, {0x012e}}},
- {0x0133, {1|U, {0x0132}}},
- {0x0135, {1|U, {0x0134}}},
- {0x0137, {1|U, {0x0136}}},
- {0x013a, {1|U, {0x0139}}},
- {0x013c, {1|U, {0x013b}}},
- {0x013e, {1|U, {0x013d}}},
- {0x0140, {1|U, {0x013f}}},
- {0x0142, {1|U, {0x0141}}},
- {0x0144, {1|U, {0x0143}}},
- {0x0146, {1|U, {0x0145}}},
- {0x0148, {1|U, {0x0147}}},
- {0x014b, {1|U, {0x014a}}},
- {0x014d, {1|U, {0x014c}}},
- {0x014f, {1|U, {0x014e}}},
- {0x0151, {1|U, {0x0150}}},
- {0x0153, {1|U, {0x0152}}},
- {0x0155, {1|U, {0x0154}}},
- {0x0157, {1|U, {0x0156}}},
- {0x0159, {1|U, {0x0158}}},
- {0x015b, {1|U, {0x015a}}},
- {0x015d, {1|U, {0x015c}}},
- {0x015f, {1|U, {0x015e}}},
- {0x0161, {1|U, {0x0160}}},
- {0x0163, {1|U, {0x0162}}},
- {0x0165, {1|U, {0x0164}}},
- {0x0167, {1|U, {0x0166}}},
- {0x0169, {1|U, {0x0168}}},
- {0x016b, {1|U, {0x016a}}},
- {0x016d, {1|U, {0x016c}}},
- {0x016f, {1|U, {0x016e}}},
- {0x0171, {1|U, {0x0170}}},
- {0x0173, {1|U, {0x0172}}},
- {0x0175, {1|U, {0x0174}}},
- {0x0177, {1|U, {0x0176}}},
- {0x017a, {1|U, {0x0179}}},
- {0x017c, {1|U, {0x017b}}},
- {0x017e, {1|U, {0x017d}}},
- {0x0180, {1|U, {0x0243}}},
- {0x0183, {1|U, {0x0182}}},
- {0x0185, {1|U, {0x0184}}},
- {0x0188, {1|U, {0x0187}}},
- {0x018c, {1|U, {0x018b}}},
- {0x0192, {1|U, {0x0191}}},
- {0x0195, {1|U, {0x01f6}}},
- {0x0199, {1|U, {0x0198}}},
- {0x019a, {1|U, {0x023d}}},
- {0x019e, {1|U, {0x0220}}},
- {0x01a1, {1|U, {0x01a0}}},
- {0x01a3, {1|U, {0x01a2}}},
- {0x01a5, {1|U, {0x01a4}}},
- {0x01a8, {1|U, {0x01a7}}},
- {0x01ad, {1|U, {0x01ac}}},
- {0x01b0, {1|U, {0x01af}}},
- {0x01b4, {1|U, {0x01b3}}},
- {0x01b6, {1|U, {0x01b5}}},
- {0x01b9, {1|U, {0x01b8}}},
- {0x01bd, {1|U, {0x01bc}}},
- {0x01bf, {1|U, {0x01f7}}},
- {0x01c6, {2|U|ST, {0x01c4, 0x01c5}}},
- {0x01c9, {2|U|ST, {0x01c7, 0x01c8}}},
- {0x01cc, {2|U|ST, {0x01ca, 0x01cb}}},
- {0x01ce, {1|U, {0x01cd}}},
- {0x01d0, {1|U, {0x01cf}}},
- {0x01d2, {1|U, {0x01d1}}},
- {0x01d4, {1|U, {0x01d3}}},
- {0x01d6, {1|U, {0x01d5}}},
- {0x01d8, {1|U, {0x01d7}}},
- {0x01da, {1|U, {0x01d9}}},
- {0x01dc, {1|U, {0x01db}}},
- {0x01dd, {1|U, {0x018e}}},
- {0x01df, {1|U, {0x01de}}},
- {0x01e1, {1|U, {0x01e0}}},
- {0x01e3, {1|U, {0x01e2}}},
- {0x01e5, {1|U, {0x01e4}}},
- {0x01e7, {1|U, {0x01e6}}},
- {0x01e9, {1|U, {0x01e8}}},
- {0x01eb, {1|U, {0x01ea}}},
- {0x01ed, {1|U, {0x01ec}}},
- {0x01ef, {1|U, {0x01ee}}},
- {0x01f3, {2|U|ST, {0x01f1, 0x01f2}}},
- {0x01f5, {1|U, {0x01f4}}},
- {0x01f9, {1|U, {0x01f8}}},
- {0x01fb, {1|U, {0x01fa}}},
- {0x01fd, {1|U, {0x01fc}}},
- {0x01ff, {1|U, {0x01fe}}},
- {0x0201, {1|U, {0x0200}}},
- {0x0203, {1|U, {0x0202}}},
- {0x0205, {1|U, {0x0204}}},
- {0x0207, {1|U, {0x0206}}},
- {0x0209, {1|U, {0x0208}}},
- {0x020b, {1|U, {0x020a}}},
- {0x020d, {1|U, {0x020c}}},
- {0x020f, {1|U, {0x020e}}},
- {0x0211, {1|U, {0x0210}}},
- {0x0213, {1|U, {0x0212}}},
- {0x0215, {1|U, {0x0214}}},
- {0x0217, {1|U, {0x0216}}},
- {0x0219, {1|U, {0x0218}}},
- {0x021b, {1|U, {0x021a}}},
- {0x021d, {1|U, {0x021c}}},
- {0x021f, {1|U, {0x021e}}},
- {0x0223, {1|U, {0x0222}}},
- {0x0225, {1|U, {0x0224}}},
- {0x0227, {1|U, {0x0226}}},
- {0x0229, {1|U, {0x0228}}},
- {0x022b, {1|U, {0x022a}}},
- {0x022d, {1|U, {0x022c}}},
- {0x022f, {1|U, {0x022e}}},
- {0x0231, {1|U, {0x0230}}},
- {0x0233, {1|U, {0x0232}}},
- {0x023c, {1|U, {0x023b}}},
- {0x023f, {1|U, {0x2c7e}}},
- {0x0240, {1|U, {0x2c7f}}},
- {0x0242, {1|U, {0x0241}}},
- {0x0247, {1|U, {0x0246}}},
- {0x0249, {1|U, {0x0248}}},
- {0x024b, {1|U, {0x024a}}},
- {0x024d, {1|U, {0x024c}}},
- {0x024f, {1|U, {0x024e}}},
- {0x0250, {1|U, {0x2c6f}}},
- {0x0251, {1|U, {0x2c6d}}},
- {0x0252, {1|U, {0x2c70}}},
- {0x0253, {1|U, {0x0181}}},
- {0x0254, {1|U, {0x0186}}},
- {0x0256, {1|U, {0x0189}}},
- {0x0257, {1|U, {0x018a}}},
- {0x0259, {1|U, {0x018f}}},
- {0x025b, {1|U, {0x0190}}},
- {0x025c, {1|U, {0xa7ab}}},
- {0x0260, {1|U, {0x0193}}},
- {0x0261, {1|U, {0xa7ac}}},
- {0x0263, {1|U, {0x0194}}},
- {0x0265, {1|U, {0xa78d}}},
- {0x0266, {1|U, {0xa7aa}}},
- {0x0268, {1|U, {0x0197}}},
- {0x0269, {1|U, {0x0196}}},
- {0x026a, {1|U, {0xa7ae}}},
- {0x026b, {1|U, {0x2c62}}},
- {0x026c, {1|U, {0xa7ad}}},
- {0x026f, {1|U, {0x019c}}},
- {0x0271, {1|U, {0x2c6e}}},
- {0x0272, {1|U, {0x019d}}},
- {0x0275, {1|U, {0x019f}}},
- {0x027d, {1|U, {0x2c64}}},
- {0x0280, {1|U, {0x01a6}}},
- {0x0282, {1|U, {0xa7c5}}},
- {0x0283, {1|U, {0x01a9}}},
- {0x0287, {1|U, {0xa7b1}}},
- {0x0288, {1|U, {0x01ae}}},
- {0x0289, {1|U, {0x0244}}},
- {0x028a, {1|U, {0x01b1}}},
- {0x028b, {1|U, {0x01b2}}},
- {0x028c, {1|U, {0x0245}}},
- {0x0292, {1|U, {0x01b7}}},
- {0x029d, {1|U, {0xa7b2}}},
- {0x029e, {1|U, {0xa7b0}}},
- {0x0371, {1|U, {0x0370}}},
- {0x0373, {1|U, {0x0372}}},
- {0x0377, {1|U, {0x0376}}},
- {0x037b, {1|U, {0x03fd}}},
- {0x037c, {1|U, {0x03fe}}},
- {0x037d, {1|U, {0x03ff}}},
- {0x03ac, {1|U, {0x0386}}},
- {0x03ad, {1|U, {0x0388}}},
- {0x03ae, {1|U, {0x0389}}},
- {0x03af, {1|U, {0x038a}}},
- {0x03b1, {1|U, {0x0391}}},
- {0x03b2, {2|U, {0x0392, 0x03d0}}},
- {0x03b3, {1|U, {0x0393}}},
- {0x03b4, {1|U, {0x0394}}},
- {0x03b5, {2|U, {0x0395, 0x03f5}}},
- {0x03b6, {1|U, {0x0396}}},
- {0x03b7, {1|U, {0x0397}}},
- {0x03b8, {3|U, {0x0398, 0x03d1, 0x03f4}}},
- {0x03b9, {3|U, {0x0399, 0x0345, 0x1fbe}}},
- {0x03ba, {2|U, {0x039a, 0x03f0}}},
- {0x03bb, {1|U, {0x039b}}},
- {0x03bc, {2|U, {0x039c, 0x00b5}}},
- {0x03bd, {1|U, {0x039d}}},
- {0x03be, {1|U, {0x039e}}},
- {0x03bf, {1|U, {0x039f}}},
- {0x03c0, {2|U, {0x03a0, 0x03d6}}},
- {0x03c1, {2|U, {0x03a1, 0x03f1}}},
- {0x03c3, {2|U, {0x03a3, 0x03c2}}},
- {0x03c4, {1|U, {0x03a4}}},
- {0x03c5, {1|U, {0x03a5}}},
- {0x03c6, {2|U, {0x03a6, 0x03d5}}},
- {0x03c7, {1|U, {0x03a7}}},
- {0x03c8, {1|U, {0x03a8}}},
- {0x03c9, {2|U, {0x03a9, 0x2126}}},
- {0x03ca, {1|U, {0x03aa}}},
- {0x03cb, {1|U, {0x03ab}}},
- {0x03cc, {1|U, {0x038c}}},
- {0x03cd, {1|U, {0x038e}}},
- {0x03ce, {1|U, {0x038f}}},
- {0x03d7, {1|U, {0x03cf}}},
- {0x03d9, {1|U, {0x03d8}}},
- {0x03db, {1|U, {0x03da}}},
- {0x03dd, {1|U, {0x03dc}}},
- {0x03df, {1|U, {0x03de}}},
- {0x03e1, {1|U, {0x03e0}}},
- {0x03e3, {1|U, {0x03e2}}},
- {0x03e5, {1|U, {0x03e4}}},
- {0x03e7, {1|U, {0x03e6}}},
- {0x03e9, {1|U, {0x03e8}}},
- {0x03eb, {1|U, {0x03ea}}},
- {0x03ed, {1|U, {0x03ec}}},
- {0x03ef, {1|U, {0x03ee}}},
- {0x03f2, {1|U, {0x03f9}}},
- {0x03f3, {1|U, {0x037f}}},
- {0x03f8, {1|U, {0x03f7}}},
- {0x03fb, {1|U, {0x03fa}}},
- {0x0430, {1|U, {0x0410}}},
- {0x0431, {1|U, {0x0411}}},
- {0x0432, {2|U, {0x0412, 0x1c80}}},
- {0x0433, {1|U, {0x0413}}},
- {0x0434, {2|U, {0x0414, 0x1c81}}},
- {0x0435, {1|U, {0x0415}}},
- {0x0436, {1|U, {0x0416}}},
- {0x0437, {1|U, {0x0417}}},
- {0x0438, {1|U, {0x0418}}},
- {0x0439, {1|U, {0x0419}}},
- {0x043a, {1|U, {0x041a}}},
- {0x043b, {1|U, {0x041b}}},
- {0x043c, {1|U, {0x041c}}},
- {0x043d, {1|U, {0x041d}}},
- {0x043e, {2|U, {0x041e, 0x1c82}}},
- {0x043f, {1|U, {0x041f}}},
- {0x0440, {1|U, {0x0420}}},
- {0x0441, {2|U, {0x0421, 0x1c83}}},
- {0x0442, {3|U, {0x0422, 0x1c84, 0x1c85}}},
- {0x0443, {1|U, {0x0423}}},
- {0x0444, {1|U, {0x0424}}},
- {0x0445, {1|U, {0x0425}}},
- {0x0446, {1|U, {0x0426}}},
- {0x0447, {1|U, {0x0427}}},
- {0x0448, {1|U, {0x0428}}},
- {0x0449, {1|U, {0x0429}}},
- {0x044a, {2|U, {0x042a, 0x1c86}}},
- {0x044b, {1|U, {0x042b}}},
- {0x044c, {1|U, {0x042c}}},
- {0x044d, {1|U, {0x042d}}},
- {0x044e, {1|U, {0x042e}}},
- {0x044f, {1|U, {0x042f}}},
- {0x0450, {1|U, {0x0400}}},
- {0x0451, {1|U, {0x0401}}},
- {0x0452, {1|U, {0x0402}}},
- {0x0453, {1|U, {0x0403}}},
- {0x0454, {1|U, {0x0404}}},
- {0x0455, {1|U, {0x0405}}},
- {0x0456, {1|U, {0x0406}}},
- {0x0457, {1|U, {0x0407}}},
- {0x0458, {1|U, {0x0408}}},
- {0x0459, {1|U, {0x0409}}},
- {0x045a, {1|U, {0x040a}}},
- {0x045b, {1|U, {0x040b}}},
- {0x045c, {1|U, {0x040c}}},
- {0x045d, {1|U, {0x040d}}},
- {0x045e, {1|U, {0x040e}}},
- {0x045f, {1|U, {0x040f}}},
- {0x0461, {1|U, {0x0460}}},
- {0x0463, {2|U, {0x0462, 0x1c87}}},
- {0x0465, {1|U, {0x0464}}},
- {0x0467, {1|U, {0x0466}}},
- {0x0469, {1|U, {0x0468}}},
- {0x046b, {1|U, {0x046a}}},
- {0x046d, {1|U, {0x046c}}},
- {0x046f, {1|U, {0x046e}}},
- {0x0471, {1|U, {0x0470}}},
- {0x0473, {1|U, {0x0472}}},
- {0x0475, {1|U, {0x0474}}},
- {0x0477, {1|U, {0x0476}}},
- {0x0479, {1|U, {0x0478}}},
- {0x047b, {1|U, {0x047a}}},
- {0x047d, {1|U, {0x047c}}},
- {0x047f, {1|U, {0x047e}}},
- {0x0481, {1|U, {0x0480}}},
- {0x048b, {1|U, {0x048a}}},
- {0x048d, {1|U, {0x048c}}},
- {0x048f, {1|U, {0x048e}}},
- {0x0491, {1|U, {0x0490}}},
- {0x0493, {1|U, {0x0492}}},
- {0x0495, {1|U, {0x0494}}},
- {0x0497, {1|U, {0x0496}}},
- {0x0499, {1|U, {0x0498}}},
- {0x049b, {1|U, {0x049a}}},
- {0x049d, {1|U, {0x049c}}},
- {0x049f, {1|U, {0x049e}}},
- {0x04a1, {1|U, {0x04a0}}},
- {0x04a3, {1|U, {0x04a2}}},
- {0x04a5, {1|U, {0x04a4}}},
- {0x04a7, {1|U, {0x04a6}}},
- {0x04a9, {1|U, {0x04a8}}},
- {0x04ab, {1|U, {0x04aa}}},
- {0x04ad, {1|U, {0x04ac}}},
- {0x04af, {1|U, {0x04ae}}},
- {0x04b1, {1|U, {0x04b0}}},
- {0x04b3, {1|U, {0x04b2}}},
- {0x04b5, {1|U, {0x04b4}}},
- {0x04b7, {1|U, {0x04b6}}},
- {0x04b9, {1|U, {0x04b8}}},
- {0x04bb, {1|U, {0x04ba}}},
- {0x04bd, {1|U, {0x04bc}}},
- {0x04bf, {1|U, {0x04be}}},
- {0x04c2, {1|U, {0x04c1}}},
- {0x04c4, {1|U, {0x04c3}}},
- {0x04c6, {1|U, {0x04c5}}},
- {0x04c8, {1|U, {0x04c7}}},
- {0x04ca, {1|U, {0x04c9}}},
- {0x04cc, {1|U, {0x04cb}}},
- {0x04ce, {1|U, {0x04cd}}},
- {0x04cf, {1|U, {0x04c0}}},
- {0x04d1, {1|U, {0x04d0}}},
- {0x04d3, {1|U, {0x04d2}}},
- {0x04d5, {1|U, {0x04d4}}},
- {0x04d7, {1|U, {0x04d6}}},
- {0x04d9, {1|U, {0x04d8}}},
- {0x04db, {1|U, {0x04da}}},
- {0x04dd, {1|U, {0x04dc}}},
- {0x04df, {1|U, {0x04de}}},
- {0x04e1, {1|U, {0x04e0}}},
- {0x04e3, {1|U, {0x04e2}}},
- {0x04e5, {1|U, {0x04e4}}},
- {0x04e7, {1|U, {0x04e6}}},
- {0x04e9, {1|U, {0x04e8}}},
- {0x04eb, {1|U, {0x04ea}}},
- {0x04ed, {1|U, {0x04ec}}},
- {0x04ef, {1|U, {0x04ee}}},
- {0x04f1, {1|U, {0x04f0}}},
- {0x04f3, {1|U, {0x04f2}}},
- {0x04f5, {1|U, {0x04f4}}},
- {0x04f7, {1|U, {0x04f6}}},
- {0x04f9, {1|U, {0x04f8}}},
- {0x04fb, {1|U, {0x04fa}}},
- {0x04fd, {1|U, {0x04fc}}},
- {0x04ff, {1|U, {0x04fe}}},
- {0x0501, {1|U, {0x0500}}},
- {0x0503, {1|U, {0x0502}}},
- {0x0505, {1|U, {0x0504}}},
- {0x0507, {1|U, {0x0506}}},
- {0x0509, {1|U, {0x0508}}},
- {0x050b, {1|U, {0x050a}}},
- {0x050d, {1|U, {0x050c}}},
- {0x050f, {1|U, {0x050e}}},
- {0x0511, {1|U, {0x0510}}},
- {0x0513, {1|U, {0x0512}}},
- {0x0515, {1|U, {0x0514}}},
- {0x0517, {1|U, {0x0516}}},
- {0x0519, {1|U, {0x0518}}},
- {0x051b, {1|U, {0x051a}}},
- {0x051d, {1|U, {0x051c}}},
- {0x051f, {1|U, {0x051e}}},
- {0x0521, {1|U, {0x0520}}},
- {0x0523, {1|U, {0x0522}}},
- {0x0525, {1|U, {0x0524}}},
- {0x0527, {1|U, {0x0526}}},
- {0x0529, {1|U, {0x0528}}},
- {0x052b, {1|U, {0x052a}}},
- {0x052d, {1|U, {0x052c}}},
- {0x052f, {1|U, {0x052e}}},
- {0x0561, {1|U, {0x0531}}},
- {0x0562, {1|U, {0x0532}}},
- {0x0563, {1|U, {0x0533}}},
- {0x0564, {1|U, {0x0534}}},
- {0x0565, {1|U, {0x0535}}},
- {0x0566, {1|U, {0x0536}}},
- {0x0567, {1|U, {0x0537}}},
- {0x0568, {1|U, {0x0538}}},
- {0x0569, {1|U, {0x0539}}},
- {0x056a, {1|U, {0x053a}}},
- {0x056b, {1|U, {0x053b}}},
- {0x056c, {1|U, {0x053c}}},
- {0x056d, {1|U, {0x053d}}},
- {0x056e, {1|U, {0x053e}}},
- {0x056f, {1|U, {0x053f}}},
- {0x0570, {1|U, {0x0540}}},
- {0x0571, {1|U, {0x0541}}},
- {0x0572, {1|U, {0x0542}}},
- {0x0573, {1|U, {0x0543}}},
- {0x0574, {1|U, {0x0544}}},
- {0x0575, {1|U, {0x0545}}},
- {0x0576, {1|U, {0x0546}}},
- {0x0577, {1|U, {0x0547}}},
- {0x0578, {1|U, {0x0548}}},
- {0x0579, {1|U, {0x0549}}},
- {0x057a, {1|U, {0x054a}}},
- {0x057b, {1|U, {0x054b}}},
- {0x057c, {1|U, {0x054c}}},
- {0x057d, {1|U, {0x054d}}},
- {0x057e, {1|U, {0x054e}}},
- {0x057f, {1|U, {0x054f}}},
- {0x0580, {1|U, {0x0550}}},
- {0x0581, {1|U, {0x0551}}},
- {0x0582, {1|U, {0x0552}}},
- {0x0583, {1|U, {0x0553}}},
- {0x0584, {1|U, {0x0554}}},
- {0x0585, {1|U, {0x0555}}},
- {0x0586, {1|U, {0x0556}}},
- {0x10d0, {1|U|IT, {0x1c90}}},
- {0x10d1, {1|U|IT, {0x1c91}}},
- {0x10d2, {1|U|IT, {0x1c92}}},
- {0x10d3, {1|U|IT, {0x1c93}}},
- {0x10d4, {1|U|IT, {0x1c94}}},
- {0x10d5, {1|U|IT, {0x1c95}}},
- {0x10d6, {1|U|IT, {0x1c96}}},
- {0x10d7, {1|U|IT, {0x1c97}}},
- {0x10d8, {1|U|IT, {0x1c98}}},
- {0x10d9, {1|U|IT, {0x1c99}}},
- {0x10da, {1|U|IT, {0x1c9a}}},
- {0x10db, {1|U|IT, {0x1c9b}}},
- {0x10dc, {1|U|IT, {0x1c9c}}},
- {0x10dd, {1|U|IT, {0x1c9d}}},
- {0x10de, {1|U|IT, {0x1c9e}}},
- {0x10df, {1|U|IT, {0x1c9f}}},
- {0x10e0, {1|U|IT, {0x1ca0}}},
- {0x10e1, {1|U|IT, {0x1ca1}}},
- {0x10e2, {1|U|IT, {0x1ca2}}},
- {0x10e3, {1|U|IT, {0x1ca3}}},
- {0x10e4, {1|U|IT, {0x1ca4}}},
- {0x10e5, {1|U|IT, {0x1ca5}}},
- {0x10e6, {1|U|IT, {0x1ca6}}},
- {0x10e7, {1|U|IT, {0x1ca7}}},
- {0x10e8, {1|U|IT, {0x1ca8}}},
- {0x10e9, {1|U|IT, {0x1ca9}}},
- {0x10ea, {1|U|IT, {0x1caa}}},
- {0x10eb, {1|U|IT, {0x1cab}}},
- {0x10ec, {1|U|IT, {0x1cac}}},
- {0x10ed, {1|U|IT, {0x1cad}}},
- {0x10ee, {1|U|IT, {0x1cae}}},
- {0x10ef, {1|U|IT, {0x1caf}}},
- {0x10f0, {1|U|IT, {0x1cb0}}},
- {0x10f1, {1|U|IT, {0x1cb1}}},
- {0x10f2, {1|U|IT, {0x1cb2}}},
- {0x10f3, {1|U|IT, {0x1cb3}}},
- {0x10f4, {1|U|IT, {0x1cb4}}},
- {0x10f5, {1|U|IT, {0x1cb5}}},
- {0x10f6, {1|U|IT, {0x1cb6}}},
- {0x10f7, {1|U|IT, {0x1cb7}}},
- {0x10f8, {1|U|IT, {0x1cb8}}},
- {0x10f9, {1|U|IT, {0x1cb9}}},
- {0x10fa, {1|U|IT, {0x1cba}}},
- {0x10fd, {1|U|IT, {0x1cbd}}},
- {0x10fe, {1|U|IT, {0x1cbe}}},
- {0x10ff, {1|U|IT, {0x1cbf}}},
- {0x13a0, {1|D, {0xab70}}},
- {0x13a1, {1|D, {0xab71}}},
- {0x13a2, {1|D, {0xab72}}},
- {0x13a3, {1|D, {0xab73}}},
- {0x13a4, {1|D, {0xab74}}},
- {0x13a5, {1|D, {0xab75}}},
- {0x13a6, {1|D, {0xab76}}},
- {0x13a7, {1|D, {0xab77}}},
- {0x13a8, {1|D, {0xab78}}},
- {0x13a9, {1|D, {0xab79}}},
- {0x13aa, {1|D, {0xab7a}}},
- {0x13ab, {1|D, {0xab7b}}},
- {0x13ac, {1|D, {0xab7c}}},
- {0x13ad, {1|D, {0xab7d}}},
- {0x13ae, {1|D, {0xab7e}}},
- {0x13af, {1|D, {0xab7f}}},
- {0x13b0, {1|D, {0xab80}}},
- {0x13b1, {1|D, {0xab81}}},
- {0x13b2, {1|D, {0xab82}}},
- {0x13b3, {1|D, {0xab83}}},
- {0x13b4, {1|D, {0xab84}}},
- {0x13b5, {1|D, {0xab85}}},
- {0x13b6, {1|D, {0xab86}}},
- {0x13b7, {1|D, {0xab87}}},
- {0x13b8, {1|D, {0xab88}}},
- {0x13b9, {1|D, {0xab89}}},
- {0x13ba, {1|D, {0xab8a}}},
- {0x13bb, {1|D, {0xab8b}}},
- {0x13bc, {1|D, {0xab8c}}},
- {0x13bd, {1|D, {0xab8d}}},
- {0x13be, {1|D, {0xab8e}}},
- {0x13bf, {1|D, {0xab8f}}},
- {0x13c0, {1|D, {0xab90}}},
- {0x13c1, {1|D, {0xab91}}},
- {0x13c2, {1|D, {0xab92}}},
- {0x13c3, {1|D, {0xab93}}},
- {0x13c4, {1|D, {0xab94}}},
- {0x13c5, {1|D, {0xab95}}},
- {0x13c6, {1|D, {0xab96}}},
- {0x13c7, {1|D, {0xab97}}},
- {0x13c8, {1|D, {0xab98}}},
- {0x13c9, {1|D, {0xab99}}},
- {0x13ca, {1|D, {0xab9a}}},
- {0x13cb, {1|D, {0xab9b}}},
- {0x13cc, {1|D, {0xab9c}}},
- {0x13cd, {1|D, {0xab9d}}},
- {0x13ce, {1|D, {0xab9e}}},
- {0x13cf, {1|D, {0xab9f}}},
- {0x13d0, {1|D, {0xaba0}}},
- {0x13d1, {1|D, {0xaba1}}},
- {0x13d2, {1|D, {0xaba2}}},
- {0x13d3, {1|D, {0xaba3}}},
- {0x13d4, {1|D, {0xaba4}}},
- {0x13d5, {1|D, {0xaba5}}},
- {0x13d6, {1|D, {0xaba6}}},
- {0x13d7, {1|D, {0xaba7}}},
- {0x13d8, {1|D, {0xaba8}}},
- {0x13d9, {1|D, {0xaba9}}},
- {0x13da, {1|D, {0xabaa}}},
- {0x13db, {1|D, {0xabab}}},
- {0x13dc, {1|D, {0xabac}}},
- {0x13dd, {1|D, {0xabad}}},
- {0x13de, {1|D, {0xabae}}},
- {0x13df, {1|D, {0xabaf}}},
- {0x13e0, {1|D, {0xabb0}}},
- {0x13e1, {1|D, {0xabb1}}},
- {0x13e2, {1|D, {0xabb2}}},
- {0x13e3, {1|D, {0xabb3}}},
- {0x13e4, {1|D, {0xabb4}}},
- {0x13e5, {1|D, {0xabb5}}},
- {0x13e6, {1|D, {0xabb6}}},
- {0x13e7, {1|D, {0xabb7}}},
- {0x13e8, {1|D, {0xabb8}}},
- {0x13e9, {1|D, {0xabb9}}},
- {0x13ea, {1|D, {0xabba}}},
- {0x13eb, {1|D, {0xabbb}}},
- {0x13ec, {1|D, {0xabbc}}},
- {0x13ed, {1|D, {0xabbd}}},
- {0x13ee, {1|D, {0xabbe}}},
- {0x13ef, {1|D, {0xabbf}}},
- {0x13f0, {1|D, {0x13f8}}},
- {0x13f1, {1|D, {0x13f9}}},
- {0x13f2, {1|D, {0x13fa}}},
- {0x13f3, {1|D, {0x13fb}}},
- {0x13f4, {1|D, {0x13fc}}},
- {0x13f5, {1|D, {0x13fd}}},
- {0x1d79, {1|U, {0xa77d}}},
- {0x1d7d, {1|U, {0x2c63}}},
- {0x1d8e, {1|U, {0xa7c6}}},
- {0x1e01, {1|U, {0x1e00}}},
- {0x1e03, {1|U, {0x1e02}}},
- {0x1e05, {1|U, {0x1e04}}},
- {0x1e07, {1|U, {0x1e06}}},
- {0x1e09, {1|U, {0x1e08}}},
- {0x1e0b, {1|U, {0x1e0a}}},
- {0x1e0d, {1|U, {0x1e0c}}},
- {0x1e0f, {1|U, {0x1e0e}}},
- {0x1e11, {1|U, {0x1e10}}},
- {0x1e13, {1|U, {0x1e12}}},
- {0x1e15, {1|U, {0x1e14}}},
- {0x1e17, {1|U, {0x1e16}}},
- {0x1e19, {1|U, {0x1e18}}},
- {0x1e1b, {1|U, {0x1e1a}}},
- {0x1e1d, {1|U, {0x1e1c}}},
- {0x1e1f, {1|U, {0x1e1e}}},
- {0x1e21, {1|U, {0x1e20}}},
- {0x1e23, {1|U, {0x1e22}}},
- {0x1e25, {1|U, {0x1e24}}},
- {0x1e27, {1|U, {0x1e26}}},
- {0x1e29, {1|U, {0x1e28}}},
- {0x1e2b, {1|U, {0x1e2a}}},
- {0x1e2d, {1|U, {0x1e2c}}},
- {0x1e2f, {1|U, {0x1e2e}}},
- {0x1e31, {1|U, {0x1e30}}},
- {0x1e33, {1|U, {0x1e32}}},
- {0x1e35, {1|U, {0x1e34}}},
- {0x1e37, {1|U, {0x1e36}}},
- {0x1e39, {1|U, {0x1e38}}},
- {0x1e3b, {1|U, {0x1e3a}}},
- {0x1e3d, {1|U, {0x1e3c}}},
- {0x1e3f, {1|U, {0x1e3e}}},
- {0x1e41, {1|U, {0x1e40}}},
- {0x1e43, {1|U, {0x1e42}}},
- {0x1e45, {1|U, {0x1e44}}},
- {0x1e47, {1|U, {0x1e46}}},
- {0x1e49, {1|U, {0x1e48}}},
- {0x1e4b, {1|U, {0x1e4a}}},
- {0x1e4d, {1|U, {0x1e4c}}},
- {0x1e4f, {1|U, {0x1e4e}}},
- {0x1e51, {1|U, {0x1e50}}},
- {0x1e53, {1|U, {0x1e52}}},
- {0x1e55, {1|U, {0x1e54}}},
- {0x1e57, {1|U, {0x1e56}}},
- {0x1e59, {1|U, {0x1e58}}},
- {0x1e5b, {1|U, {0x1e5a}}},
- {0x1e5d, {1|U, {0x1e5c}}},
- {0x1e5f, {1|U, {0x1e5e}}},
- {0x1e61, {2|U, {0x1e60, 0x1e9b}}},
- {0x1e63, {1|U, {0x1e62}}},
- {0x1e65, {1|U, {0x1e64}}},
- {0x1e67, {1|U, {0x1e66}}},
- {0x1e69, {1|U, {0x1e68}}},
- {0x1e6b, {1|U, {0x1e6a}}},
- {0x1e6d, {1|U, {0x1e6c}}},
- {0x1e6f, {1|U, {0x1e6e}}},
- {0x1e71, {1|U, {0x1e70}}},
- {0x1e73, {1|U, {0x1e72}}},
- {0x1e75, {1|U, {0x1e74}}},
- {0x1e77, {1|U, {0x1e76}}},
- {0x1e79, {1|U, {0x1e78}}},
- {0x1e7b, {1|U, {0x1e7a}}},
- {0x1e7d, {1|U, {0x1e7c}}},
- {0x1e7f, {1|U, {0x1e7e}}},
- {0x1e81, {1|U, {0x1e80}}},
- {0x1e83, {1|U, {0x1e82}}},
- {0x1e85, {1|U, {0x1e84}}},
- {0x1e87, {1|U, {0x1e86}}},
- {0x1e89, {1|U, {0x1e88}}},
- {0x1e8b, {1|U, {0x1e8a}}},
- {0x1e8d, {1|U, {0x1e8c}}},
- {0x1e8f, {1|U, {0x1e8e}}},
- {0x1e91, {1|U, {0x1e90}}},
- {0x1e93, {1|U, {0x1e92}}},
- {0x1e95, {1|U, {0x1e94}}},
- {0x1ea1, {1|U, {0x1ea0}}},
- {0x1ea3, {1|U, {0x1ea2}}},
- {0x1ea5, {1|U, {0x1ea4}}},
- {0x1ea7, {1|U, {0x1ea6}}},
- {0x1ea9, {1|U, {0x1ea8}}},
- {0x1eab, {1|U, {0x1eaa}}},
- {0x1ead, {1|U, {0x1eac}}},
- {0x1eaf, {1|U, {0x1eae}}},
- {0x1eb1, {1|U, {0x1eb0}}},
- {0x1eb3, {1|U, {0x1eb2}}},
- {0x1eb5, {1|U, {0x1eb4}}},
- {0x1eb7, {1|U, {0x1eb6}}},
- {0x1eb9, {1|U, {0x1eb8}}},
- {0x1ebb, {1|U, {0x1eba}}},
- {0x1ebd, {1|U, {0x1ebc}}},
- {0x1ebf, {1|U, {0x1ebe}}},
- {0x1ec1, {1|U, {0x1ec0}}},
- {0x1ec3, {1|U, {0x1ec2}}},
- {0x1ec5, {1|U, {0x1ec4}}},
- {0x1ec7, {1|U, {0x1ec6}}},
- {0x1ec9, {1|U, {0x1ec8}}},
- {0x1ecb, {1|U, {0x1eca}}},
- {0x1ecd, {1|U, {0x1ecc}}},
- {0x1ecf, {1|U, {0x1ece}}},
- {0x1ed1, {1|U, {0x1ed0}}},
- {0x1ed3, {1|U, {0x1ed2}}},
- {0x1ed5, {1|U, {0x1ed4}}},
- {0x1ed7, {1|U, {0x1ed6}}},
- {0x1ed9, {1|U, {0x1ed8}}},
- {0x1edb, {1|U, {0x1eda}}},
- {0x1edd, {1|U, {0x1edc}}},
- {0x1edf, {1|U, {0x1ede}}},
- {0x1ee1, {1|U, {0x1ee0}}},
- {0x1ee3, {1|U, {0x1ee2}}},
- {0x1ee5, {1|U, {0x1ee4}}},
- {0x1ee7, {1|U, {0x1ee6}}},
- {0x1ee9, {1|U, {0x1ee8}}},
- {0x1eeb, {1|U, {0x1eea}}},
- {0x1eed, {1|U, {0x1eec}}},
- {0x1eef, {1|U, {0x1eee}}},
- {0x1ef1, {1|U, {0x1ef0}}},
- {0x1ef3, {1|U, {0x1ef2}}},
- {0x1ef5, {1|U, {0x1ef4}}},
- {0x1ef7, {1|U, {0x1ef6}}},
- {0x1ef9, {1|U, {0x1ef8}}},
- {0x1efb, {1|U, {0x1efa}}},
- {0x1efd, {1|U, {0x1efc}}},
- {0x1eff, {1|U, {0x1efe}}},
- {0x1f00, {1|U, {0x1f08}}},
- {0x1f01, {1|U, {0x1f09}}},
- {0x1f02, {1|U, {0x1f0a}}},
- {0x1f03, {1|U, {0x1f0b}}},
- {0x1f04, {1|U, {0x1f0c}}},
- {0x1f05, {1|U, {0x1f0d}}},
- {0x1f06, {1|U, {0x1f0e}}},
- {0x1f07, {1|U, {0x1f0f}}},
- {0x1f10, {1|U, {0x1f18}}},
- {0x1f11, {1|U, {0x1f19}}},
- {0x1f12, {1|U, {0x1f1a}}},
- {0x1f13, {1|U, {0x1f1b}}},
- {0x1f14, {1|U, {0x1f1c}}},
- {0x1f15, {1|U, {0x1f1d}}},
- {0x1f20, {1|U, {0x1f28}}},
- {0x1f21, {1|U, {0x1f29}}},
- {0x1f22, {1|U, {0x1f2a}}},
- {0x1f23, {1|U, {0x1f2b}}},
- {0x1f24, {1|U, {0x1f2c}}},
- {0x1f25, {1|U, {0x1f2d}}},
- {0x1f26, {1|U, {0x1f2e}}},
- {0x1f27, {1|U, {0x1f2f}}},
- {0x1f30, {1|U, {0x1f38}}},
- {0x1f31, {1|U, {0x1f39}}},
- {0x1f32, {1|U, {0x1f3a}}},
- {0x1f33, {1|U, {0x1f3b}}},
- {0x1f34, {1|U, {0x1f3c}}},
- {0x1f35, {1|U, {0x1f3d}}},
- {0x1f36, {1|U, {0x1f3e}}},
- {0x1f37, {1|U, {0x1f3f}}},
- {0x1f40, {1|U, {0x1f48}}},
- {0x1f41, {1|U, {0x1f49}}},
- {0x1f42, {1|U, {0x1f4a}}},
- {0x1f43, {1|U, {0x1f4b}}},
- {0x1f44, {1|U, {0x1f4c}}},
- {0x1f45, {1|U, {0x1f4d}}},
- {0x1f51, {1|U, {0x1f59}}},
- {0x1f53, {1|U, {0x1f5b}}},
- {0x1f55, {1|U, {0x1f5d}}},
- {0x1f57, {1|U, {0x1f5f}}},
- {0x1f60, {1|U, {0x1f68}}},
- {0x1f61, {1|U, {0x1f69}}},
- {0x1f62, {1|U, {0x1f6a}}},
- {0x1f63, {1|U, {0x1f6b}}},
- {0x1f64, {1|U, {0x1f6c}}},
- {0x1f65, {1|U, {0x1f6d}}},
- {0x1f66, {1|U, {0x1f6e}}},
- {0x1f67, {1|U, {0x1f6f}}},
- {0x1f70, {1|U, {0x1fba}}},
- {0x1f71, {1|U, {0x1fbb}}},
- {0x1f72, {1|U, {0x1fc8}}},
- {0x1f73, {1|U, {0x1fc9}}},
- {0x1f74, {1|U, {0x1fca}}},
- {0x1f75, {1|U, {0x1fcb}}},
- {0x1f76, {1|U, {0x1fda}}},
- {0x1f77, {1|U, {0x1fdb}}},
- {0x1f78, {1|U, {0x1ff8}}},
- {0x1f79, {1|U, {0x1ff9}}},
- {0x1f7a, {1|U, {0x1fea}}},
- {0x1f7b, {1|U, {0x1feb}}},
- {0x1f7c, {1|U, {0x1ffa}}},
- {0x1f7d, {1|U, {0x1ffb}}},
- {0x1fb0, {1|U, {0x1fb8}}},
- {0x1fb1, {1|U, {0x1fb9}}},
- {0x1fd0, {1|U, {0x1fd8}}},
- {0x1fd1, {1|U, {0x1fd9}}},
- {0x1fe0, {1|U, {0x1fe8}}},
- {0x1fe1, {1|U, {0x1fe9}}},
- {0x1fe5, {1|U, {0x1fec}}},
- {0x214e, {1|U, {0x2132}}},
- {0x2170, {1|U, {0x2160}}},
- {0x2171, {1|U, {0x2161}}},
- {0x2172, {1|U, {0x2162}}},
- {0x2173, {1|U, {0x2163}}},
- {0x2174, {1|U, {0x2164}}},
- {0x2175, {1|U, {0x2165}}},
- {0x2176, {1|U, {0x2166}}},
- {0x2177, {1|U, {0x2167}}},
- {0x2178, {1|U, {0x2168}}},
- {0x2179, {1|U, {0x2169}}},
- {0x217a, {1|U, {0x216a}}},
- {0x217b, {1|U, {0x216b}}},
- {0x217c, {1|U, {0x216c}}},
- {0x217d, {1|U, {0x216d}}},
- {0x217e, {1|U, {0x216e}}},
- {0x217f, {1|U, {0x216f}}},
- {0x2184, {1|U, {0x2183}}},
- {0x24d0, {1|U, {0x24b6}}},
- {0x24d1, {1|U, {0x24b7}}},
- {0x24d2, {1|U, {0x24b8}}},
- {0x24d3, {1|U, {0x24b9}}},
- {0x24d4, {1|U, {0x24ba}}},
- {0x24d5, {1|U, {0x24bb}}},
- {0x24d6, {1|U, {0x24bc}}},
- {0x24d7, {1|U, {0x24bd}}},
- {0x24d8, {1|U, {0x24be}}},
- {0x24d9, {1|U, {0x24bf}}},
- {0x24da, {1|U, {0x24c0}}},
- {0x24db, {1|U, {0x24c1}}},
- {0x24dc, {1|U, {0x24c2}}},
- {0x24dd, {1|U, {0x24c3}}},
- {0x24de, {1|U, {0x24c4}}},
- {0x24df, {1|U, {0x24c5}}},
- {0x24e0, {1|U, {0x24c6}}},
- {0x24e1, {1|U, {0x24c7}}},
- {0x24e2, {1|U, {0x24c8}}},
- {0x24e3, {1|U, {0x24c9}}},
- {0x24e4, {1|U, {0x24ca}}},
- {0x24e5, {1|U, {0x24cb}}},
- {0x24e6, {1|U, {0x24cc}}},
- {0x24e7, {1|U, {0x24cd}}},
- {0x24e8, {1|U, {0x24ce}}},
- {0x24e9, {1|U, {0x24cf}}},
- {0x2c30, {1|U, {0x2c00}}},
- {0x2c31, {1|U, {0x2c01}}},
- {0x2c32, {1|U, {0x2c02}}},
- {0x2c33, {1|U, {0x2c03}}},
- {0x2c34, {1|U, {0x2c04}}},
- {0x2c35, {1|U, {0x2c05}}},
- {0x2c36, {1|U, {0x2c06}}},
- {0x2c37, {1|U, {0x2c07}}},
- {0x2c38, {1|U, {0x2c08}}},
- {0x2c39, {1|U, {0x2c09}}},
- {0x2c3a, {1|U, {0x2c0a}}},
- {0x2c3b, {1|U, {0x2c0b}}},
- {0x2c3c, {1|U, {0x2c0c}}},
- {0x2c3d, {1|U, {0x2c0d}}},
- {0x2c3e, {1|U, {0x2c0e}}},
- {0x2c3f, {1|U, {0x2c0f}}},
- {0x2c40, {1|U, {0x2c10}}},
- {0x2c41, {1|U, {0x2c11}}},
- {0x2c42, {1|U, {0x2c12}}},
- {0x2c43, {1|U, {0x2c13}}},
- {0x2c44, {1|U, {0x2c14}}},
- {0x2c45, {1|U, {0x2c15}}},
- {0x2c46, {1|U, {0x2c16}}},
- {0x2c47, {1|U, {0x2c17}}},
- {0x2c48, {1|U, {0x2c18}}},
- {0x2c49, {1|U, {0x2c19}}},
- {0x2c4a, {1|U, {0x2c1a}}},
- {0x2c4b, {1|U, {0x2c1b}}},
- {0x2c4c, {1|U, {0x2c1c}}},
- {0x2c4d, {1|U, {0x2c1d}}},
- {0x2c4e, {1|U, {0x2c1e}}},
- {0x2c4f, {1|U, {0x2c1f}}},
- {0x2c50, {1|U, {0x2c20}}},
- {0x2c51, {1|U, {0x2c21}}},
- {0x2c52, {1|U, {0x2c22}}},
- {0x2c53, {1|U, {0x2c23}}},
- {0x2c54, {1|U, {0x2c24}}},
- {0x2c55, {1|U, {0x2c25}}},
- {0x2c56, {1|U, {0x2c26}}},
- {0x2c57, {1|U, {0x2c27}}},
- {0x2c58, {1|U, {0x2c28}}},
- {0x2c59, {1|U, {0x2c29}}},
- {0x2c5a, {1|U, {0x2c2a}}},
- {0x2c5b, {1|U, {0x2c2b}}},
- {0x2c5c, {1|U, {0x2c2c}}},
- {0x2c5d, {1|U, {0x2c2d}}},
- {0x2c5e, {1|U, {0x2c2e}}},
- {0x2c5f, {1|U, {0x2c2f}}},
- {0x2c61, {1|U, {0x2c60}}},
- {0x2c65, {1|U, {0x023a}}},
- {0x2c66, {1|U, {0x023e}}},
- {0x2c68, {1|U, {0x2c67}}},
- {0x2c6a, {1|U, {0x2c69}}},
- {0x2c6c, {1|U, {0x2c6b}}},
- {0x2c73, {1|U, {0x2c72}}},
- {0x2c76, {1|U, {0x2c75}}},
- {0x2c81, {1|U, {0x2c80}}},
- {0x2c83, {1|U, {0x2c82}}},
- {0x2c85, {1|U, {0x2c84}}},
- {0x2c87, {1|U, {0x2c86}}},
- {0x2c89, {1|U, {0x2c88}}},
- {0x2c8b, {1|U, {0x2c8a}}},
- {0x2c8d, {1|U, {0x2c8c}}},
- {0x2c8f, {1|U, {0x2c8e}}},
- {0x2c91, {1|U, {0x2c90}}},
- {0x2c93, {1|U, {0x2c92}}},
- {0x2c95, {1|U, {0x2c94}}},
- {0x2c97, {1|U, {0x2c96}}},
- {0x2c99, {1|U, {0x2c98}}},
- {0x2c9b, {1|U, {0x2c9a}}},
- {0x2c9d, {1|U, {0x2c9c}}},
- {0x2c9f, {1|U, {0x2c9e}}},
- {0x2ca1, {1|U, {0x2ca0}}},
- {0x2ca3, {1|U, {0x2ca2}}},
- {0x2ca5, {1|U, {0x2ca4}}},
- {0x2ca7, {1|U, {0x2ca6}}},
- {0x2ca9, {1|U, {0x2ca8}}},
- {0x2cab, {1|U, {0x2caa}}},
- {0x2cad, {1|U, {0x2cac}}},
- {0x2caf, {1|U, {0x2cae}}},
- {0x2cb1, {1|U, {0x2cb0}}},
- {0x2cb3, {1|U, {0x2cb2}}},
- {0x2cb5, {1|U, {0x2cb4}}},
- {0x2cb7, {1|U, {0x2cb6}}},
- {0x2cb9, {1|U, {0x2cb8}}},
- {0x2cbb, {1|U, {0x2cba}}},
- {0x2cbd, {1|U, {0x2cbc}}},
- {0x2cbf, {1|U, {0x2cbe}}},
- {0x2cc1, {1|U, {0x2cc0}}},
- {0x2cc3, {1|U, {0x2cc2}}},
- {0x2cc5, {1|U, {0x2cc4}}},
- {0x2cc7, {1|U, {0x2cc6}}},
- {0x2cc9, {1|U, {0x2cc8}}},
- {0x2ccb, {1|U, {0x2cca}}},
- {0x2ccd, {1|U, {0x2ccc}}},
- {0x2ccf, {1|U, {0x2cce}}},
- {0x2cd1, {1|U, {0x2cd0}}},
- {0x2cd3, {1|U, {0x2cd2}}},
- {0x2cd5, {1|U, {0x2cd4}}},
- {0x2cd7, {1|U, {0x2cd6}}},
- {0x2cd9, {1|U, {0x2cd8}}},
- {0x2cdb, {1|U, {0x2cda}}},
- {0x2cdd, {1|U, {0x2cdc}}},
- {0x2cdf, {1|U, {0x2cde}}},
- {0x2ce1, {1|U, {0x2ce0}}},
- {0x2ce3, {1|U, {0x2ce2}}},
- {0x2cec, {1|U, {0x2ceb}}},
- {0x2cee, {1|U, {0x2ced}}},
- {0x2cf3, {1|U, {0x2cf2}}},
- {0x2d00, {1|U, {0x10a0}}},
- {0x2d01, {1|U, {0x10a1}}},
- {0x2d02, {1|U, {0x10a2}}},
- {0x2d03, {1|U, {0x10a3}}},
- {0x2d04, {1|U, {0x10a4}}},
- {0x2d05, {1|U, {0x10a5}}},
- {0x2d06, {1|U, {0x10a6}}},
- {0x2d07, {1|U, {0x10a7}}},
- {0x2d08, {1|U, {0x10a8}}},
- {0x2d09, {1|U, {0x10a9}}},
- {0x2d0a, {1|U, {0x10aa}}},
- {0x2d0b, {1|U, {0x10ab}}},
- {0x2d0c, {1|U, {0x10ac}}},
- {0x2d0d, {1|U, {0x10ad}}},
- {0x2d0e, {1|U, {0x10ae}}},
- {0x2d0f, {1|U, {0x10af}}},
- {0x2d10, {1|U, {0x10b0}}},
- {0x2d11, {1|U, {0x10b1}}},
- {0x2d12, {1|U, {0x10b2}}},
- {0x2d13, {1|U, {0x10b3}}},
- {0x2d14, {1|U, {0x10b4}}},
- {0x2d15, {1|U, {0x10b5}}},
- {0x2d16, {1|U, {0x10b6}}},
- {0x2d17, {1|U, {0x10b7}}},
- {0x2d18, {1|U, {0x10b8}}},
- {0x2d19, {1|U, {0x10b9}}},
- {0x2d1a, {1|U, {0x10ba}}},
- {0x2d1b, {1|U, {0x10bb}}},
- {0x2d1c, {1|U, {0x10bc}}},
- {0x2d1d, {1|U, {0x10bd}}},
- {0x2d1e, {1|U, {0x10be}}},
- {0x2d1f, {1|U, {0x10bf}}},
- {0x2d20, {1|U, {0x10c0}}},
- {0x2d21, {1|U, {0x10c1}}},
- {0x2d22, {1|U, {0x10c2}}},
- {0x2d23, {1|U, {0x10c3}}},
- {0x2d24, {1|U, {0x10c4}}},
- {0x2d25, {1|U, {0x10c5}}},
- {0x2d27, {1|U, {0x10c7}}},
- {0x2d2d, {1|U, {0x10cd}}},
- {0xa641, {1|U, {0xa640}}},
- {0xa643, {1|U, {0xa642}}},
- {0xa645, {1|U, {0xa644}}},
- {0xa647, {1|U, {0xa646}}},
- {0xa649, {1|U, {0xa648}}},
- {0xa64b, {2|U, {0xa64a, 0x1c88}}},
- {0xa64d, {1|U, {0xa64c}}},
- {0xa64f, {1|U, {0xa64e}}},
- {0xa651, {1|U, {0xa650}}},
- {0xa653, {1|U, {0xa652}}},
- {0xa655, {1|U, {0xa654}}},
- {0xa657, {1|U, {0xa656}}},
- {0xa659, {1|U, {0xa658}}},
- {0xa65b, {1|U, {0xa65a}}},
- {0xa65d, {1|U, {0xa65c}}},
- {0xa65f, {1|U, {0xa65e}}},
- {0xa661, {1|U, {0xa660}}},
- {0xa663, {1|U, {0xa662}}},
- {0xa665, {1|U, {0xa664}}},
- {0xa667, {1|U, {0xa666}}},
- {0xa669, {1|U, {0xa668}}},
- {0xa66b, {1|U, {0xa66a}}},
- {0xa66d, {1|U, {0xa66c}}},
- {0xa681, {1|U, {0xa680}}},
- {0xa683, {1|U, {0xa682}}},
- {0xa685, {1|U, {0xa684}}},
- {0xa687, {1|U, {0xa686}}},
- {0xa689, {1|U, {0xa688}}},
- {0xa68b, {1|U, {0xa68a}}},
- {0xa68d, {1|U, {0xa68c}}},
- {0xa68f, {1|U, {0xa68e}}},
- {0xa691, {1|U, {0xa690}}},
- {0xa693, {1|U, {0xa692}}},
- {0xa695, {1|U, {0xa694}}},
- {0xa697, {1|U, {0xa696}}},
- {0xa699, {1|U, {0xa698}}},
- {0xa69b, {1|U, {0xa69a}}},
- {0xa723, {1|U, {0xa722}}},
- {0xa725, {1|U, {0xa724}}},
- {0xa727, {1|U, {0xa726}}},
- {0xa729, {1|U, {0xa728}}},
- {0xa72b, {1|U, {0xa72a}}},
- {0xa72d, {1|U, {0xa72c}}},
- {0xa72f, {1|U, {0xa72e}}},
- {0xa733, {1|U, {0xa732}}},
- {0xa735, {1|U, {0xa734}}},
- {0xa737, {1|U, {0xa736}}},
- {0xa739, {1|U, {0xa738}}},
- {0xa73b, {1|U, {0xa73a}}},
- {0xa73d, {1|U, {0xa73c}}},
- {0xa73f, {1|U, {0xa73e}}},
- {0xa741, {1|U, {0xa740}}},
- {0xa743, {1|U, {0xa742}}},
- {0xa745, {1|U, {0xa744}}},
- {0xa747, {1|U, {0xa746}}},
- {0xa749, {1|U, {0xa748}}},
- {0xa74b, {1|U, {0xa74a}}},
- {0xa74d, {1|U, {0xa74c}}},
- {0xa74f, {1|U, {0xa74e}}},
- {0xa751, {1|U, {0xa750}}},
- {0xa753, {1|U, {0xa752}}},
- {0xa755, {1|U, {0xa754}}},
- {0xa757, {1|U, {0xa756}}},
- {0xa759, {1|U, {0xa758}}},
- {0xa75b, {1|U, {0xa75a}}},
- {0xa75d, {1|U, {0xa75c}}},
- {0xa75f, {1|U, {0xa75e}}},
- {0xa761, {1|U, {0xa760}}},
- {0xa763, {1|U, {0xa762}}},
- {0xa765, {1|U, {0xa764}}},
- {0xa767, {1|U, {0xa766}}},
- {0xa769, {1|U, {0xa768}}},
- {0xa76b, {1|U, {0xa76a}}},
- {0xa76d, {1|U, {0xa76c}}},
- {0xa76f, {1|U, {0xa76e}}},
- {0xa77a, {1|U, {0xa779}}},
- {0xa77c, {1|U, {0xa77b}}},
- {0xa77f, {1|U, {0xa77e}}},
- {0xa781, {1|U, {0xa780}}},
- {0xa783, {1|U, {0xa782}}},
- {0xa785, {1|U, {0xa784}}},
- {0xa787, {1|U, {0xa786}}},
- {0xa78c, {1|U, {0xa78b}}},
- {0xa791, {1|U, {0xa790}}},
- {0xa793, {1|U, {0xa792}}},
- {0xa794, {1|U, {0xa7c4}}},
- {0xa797, {1|U, {0xa796}}},
- {0xa799, {1|U, {0xa798}}},
- {0xa79b, {1|U, {0xa79a}}},
- {0xa79d, {1|U, {0xa79c}}},
- {0xa79f, {1|U, {0xa79e}}},
- {0xa7a1, {1|U, {0xa7a0}}},
- {0xa7a3, {1|U, {0xa7a2}}},
- {0xa7a5, {1|U, {0xa7a4}}},
- {0xa7a7, {1|U, {0xa7a6}}},
- {0xa7a9, {1|U, {0xa7a8}}},
- {0xa7b5, {1|U, {0xa7b4}}},
- {0xa7b7, {1|U, {0xa7b6}}},
- {0xa7b9, {1|U, {0xa7b8}}},
- {0xa7bb, {1|U, {0xa7ba}}},
- {0xa7bd, {1|U, {0xa7bc}}},
- {0xa7bf, {1|U, {0xa7be}}},
- {0xa7c1, {1|U, {0xa7c0}}},
- {0xa7c3, {1|U, {0xa7c2}}},
- {0xa7c8, {1|U, {0xa7c7}}},
- {0xa7ca, {1|U, {0xa7c9}}},
- {0xa7d1, {1|U, {0xa7d0}}},
- {0xa7d7, {1|U, {0xa7d6}}},
- {0xa7d9, {1|U, {0xa7d8}}},
- {0xa7f6, {1|U, {0xa7f5}}},
- {0xab53, {1|U, {0xa7b3}}},
- {0xff41, {1|U, {0xff21}}},
- {0xff42, {1|U, {0xff22}}},
- {0xff43, {1|U, {0xff23}}},
- {0xff44, {1|U, {0xff24}}},
- {0xff45, {1|U, {0xff25}}},
- {0xff46, {1|U, {0xff26}}},
- {0xff47, {1|U, {0xff27}}},
- {0xff48, {1|U, {0xff28}}},
- {0xff49, {1|U, {0xff29}}},
- {0xff4a, {1|U, {0xff2a}}},
- {0xff4b, {1|U, {0xff2b}}},
- {0xff4c, {1|U, {0xff2c}}},
- {0xff4d, {1|U, {0xff2d}}},
- {0xff4e, {1|U, {0xff2e}}},
- {0xff4f, {1|U, {0xff2f}}},
- {0xff50, {1|U, {0xff30}}},
- {0xff51, {1|U, {0xff31}}},
- {0xff52, {1|U, {0xff32}}},
- {0xff53, {1|U, {0xff33}}},
- {0xff54, {1|U, {0xff34}}},
- {0xff55, {1|U, {0xff35}}},
- {0xff56, {1|U, {0xff36}}},
- {0xff57, {1|U, {0xff37}}},
- {0xff58, {1|U, {0xff38}}},
- {0xff59, {1|U, {0xff39}}},
- {0xff5a, {1|U, {0xff3a}}},
- {0x10428, {1|U, {0x10400}}},
- {0x10429, {1|U, {0x10401}}},
- {0x1042a, {1|U, {0x10402}}},
- {0x1042b, {1|U, {0x10403}}},
- {0x1042c, {1|U, {0x10404}}},
- {0x1042d, {1|U, {0x10405}}},
- {0x1042e, {1|U, {0x10406}}},
- {0x1042f, {1|U, {0x10407}}},
- {0x10430, {1|U, {0x10408}}},
- {0x10431, {1|U, {0x10409}}},
- {0x10432, {1|U, {0x1040a}}},
- {0x10433, {1|U, {0x1040b}}},
- {0x10434, {1|U, {0x1040c}}},
- {0x10435, {1|U, {0x1040d}}},
- {0x10436, {1|U, {0x1040e}}},
- {0x10437, {1|U, {0x1040f}}},
- {0x10438, {1|U, {0x10410}}},
- {0x10439, {1|U, {0x10411}}},
- {0x1043a, {1|U, {0x10412}}},
- {0x1043b, {1|U, {0x10413}}},
- {0x1043c, {1|U, {0x10414}}},
- {0x1043d, {1|U, {0x10415}}},
- {0x1043e, {1|U, {0x10416}}},
- {0x1043f, {1|U, {0x10417}}},
- {0x10440, {1|U, {0x10418}}},
- {0x10441, {1|U, {0x10419}}},
- {0x10442, {1|U, {0x1041a}}},
- {0x10443, {1|U, {0x1041b}}},
- {0x10444, {1|U, {0x1041c}}},
- {0x10445, {1|U, {0x1041d}}},
- {0x10446, {1|U, {0x1041e}}},
- {0x10447, {1|U, {0x1041f}}},
- {0x10448, {1|U, {0x10420}}},
- {0x10449, {1|U, {0x10421}}},
- {0x1044a, {1|U, {0x10422}}},
- {0x1044b, {1|U, {0x10423}}},
- {0x1044c, {1|U, {0x10424}}},
- {0x1044d, {1|U, {0x10425}}},
- {0x1044e, {1|U, {0x10426}}},
- {0x1044f, {1|U, {0x10427}}},
- {0x104d8, {1|U, {0x104b0}}},
- {0x104d9, {1|U, {0x104b1}}},
- {0x104da, {1|U, {0x104b2}}},
- {0x104db, {1|U, {0x104b3}}},
- {0x104dc, {1|U, {0x104b4}}},
- {0x104dd, {1|U, {0x104b5}}},
- {0x104de, {1|U, {0x104b6}}},
- {0x104df, {1|U, {0x104b7}}},
- {0x104e0, {1|U, {0x104b8}}},
- {0x104e1, {1|U, {0x104b9}}},
- {0x104e2, {1|U, {0x104ba}}},
- {0x104e3, {1|U, {0x104bb}}},
- {0x104e4, {1|U, {0x104bc}}},
- {0x104e5, {1|U, {0x104bd}}},
- {0x104e6, {1|U, {0x104be}}},
- {0x104e7, {1|U, {0x104bf}}},
- {0x104e8, {1|U, {0x104c0}}},
- {0x104e9, {1|U, {0x104c1}}},
- {0x104ea, {1|U, {0x104c2}}},
- {0x104eb, {1|U, {0x104c3}}},
- {0x104ec, {1|U, {0x104c4}}},
- {0x104ed, {1|U, {0x104c5}}},
- {0x104ee, {1|U, {0x104c6}}},
- {0x104ef, {1|U, {0x104c7}}},
- {0x104f0, {1|U, {0x104c8}}},
- {0x104f1, {1|U, {0x104c9}}},
- {0x104f2, {1|U, {0x104ca}}},
- {0x104f3, {1|U, {0x104cb}}},
- {0x104f4, {1|U, {0x104cc}}},
- {0x104f5, {1|U, {0x104cd}}},
- {0x104f6, {1|U, {0x104ce}}},
- {0x104f7, {1|U, {0x104cf}}},
- {0x104f8, {1|U, {0x104d0}}},
- {0x104f9, {1|U, {0x104d1}}},
- {0x104fa, {1|U, {0x104d2}}},
- {0x104fb, {1|U, {0x104d3}}},
- {0x10597, {1|U, {0x10570}}},
- {0x10598, {1|U, {0x10571}}},
- {0x10599, {1|U, {0x10572}}},
- {0x1059a, {1|U, {0x10573}}},
- {0x1059b, {1|U, {0x10574}}},
- {0x1059c, {1|U, {0x10575}}},
- {0x1059d, {1|U, {0x10576}}},
- {0x1059e, {1|U, {0x10577}}},
- {0x1059f, {1|U, {0x10578}}},
- {0x105a0, {1|U, {0x10579}}},
- {0x105a1, {1|U, {0x1057a}}},
- {0x105a3, {1|U, {0x1057c}}},
- {0x105a4, {1|U, {0x1057d}}},
- {0x105a5, {1|U, {0x1057e}}},
- {0x105a6, {1|U, {0x1057f}}},
- {0x105a7, {1|U, {0x10580}}},
- {0x105a8, {1|U, {0x10581}}},
- {0x105a9, {1|U, {0x10582}}},
- {0x105aa, {1|U, {0x10583}}},
- {0x105ab, {1|U, {0x10584}}},
- {0x105ac, {1|U, {0x10585}}},
- {0x105ad, {1|U, {0x10586}}},
- {0x105ae, {1|U, {0x10587}}},
- {0x105af, {1|U, {0x10588}}},
- {0x105b0, {1|U, {0x10589}}},
- {0x105b1, {1|U, {0x1058a}}},
- {0x105b3, {1|U, {0x1058c}}},
- {0x105b4, {1|U, {0x1058d}}},
- {0x105b5, {1|U, {0x1058e}}},
- {0x105b6, {1|U, {0x1058f}}},
- {0x105b7, {1|U, {0x10590}}},
- {0x105b8, {1|U, {0x10591}}},
- {0x105b9, {1|U, {0x10592}}},
- {0x105bb, {1|U, {0x10594}}},
- {0x105bc, {1|U, {0x10595}}},
- {0x10cc0, {1|U, {0x10c80}}},
- {0x10cc1, {1|U, {0x10c81}}},
- {0x10cc2, {1|U, {0x10c82}}},
- {0x10cc3, {1|U, {0x10c83}}},
- {0x10cc4, {1|U, {0x10c84}}},
- {0x10cc5, {1|U, {0x10c85}}},
- {0x10cc6, {1|U, {0x10c86}}},
- {0x10cc7, {1|U, {0x10c87}}},
- {0x10cc8, {1|U, {0x10c88}}},
- {0x10cc9, {1|U, {0x10c89}}},
- {0x10cca, {1|U, {0x10c8a}}},
- {0x10ccb, {1|U, {0x10c8b}}},
- {0x10ccc, {1|U, {0x10c8c}}},
- {0x10ccd, {1|U, {0x10c8d}}},
- {0x10cce, {1|U, {0x10c8e}}},
- {0x10ccf, {1|U, {0x10c8f}}},
- {0x10cd0, {1|U, {0x10c90}}},
- {0x10cd1, {1|U, {0x10c91}}},
- {0x10cd2, {1|U, {0x10c92}}},
- {0x10cd3, {1|U, {0x10c93}}},
- {0x10cd4, {1|U, {0x10c94}}},
- {0x10cd5, {1|U, {0x10c95}}},
- {0x10cd6, {1|U, {0x10c96}}},
- {0x10cd7, {1|U, {0x10c97}}},
- {0x10cd8, {1|U, {0x10c98}}},
- {0x10cd9, {1|U, {0x10c99}}},
- {0x10cda, {1|U, {0x10c9a}}},
- {0x10cdb, {1|U, {0x10c9b}}},
- {0x10cdc, {1|U, {0x10c9c}}},
- {0x10cdd, {1|U, {0x10c9d}}},
- {0x10cde, {1|U, {0x10c9e}}},
- {0x10cdf, {1|U, {0x10c9f}}},
- {0x10ce0, {1|U, {0x10ca0}}},
- {0x10ce1, {1|U, {0x10ca1}}},
- {0x10ce2, {1|U, {0x10ca2}}},
- {0x10ce3, {1|U, {0x10ca3}}},
- {0x10ce4, {1|U, {0x10ca4}}},
- {0x10ce5, {1|U, {0x10ca5}}},
- {0x10ce6, {1|U, {0x10ca6}}},
- {0x10ce7, {1|U, {0x10ca7}}},
- {0x10ce8, {1|U, {0x10ca8}}},
- {0x10ce9, {1|U, {0x10ca9}}},
- {0x10cea, {1|U, {0x10caa}}},
- {0x10ceb, {1|U, {0x10cab}}},
- {0x10cec, {1|U, {0x10cac}}},
- {0x10ced, {1|U, {0x10cad}}},
- {0x10cee, {1|U, {0x10cae}}},
- {0x10cef, {1|U, {0x10caf}}},
- {0x10cf0, {1|U, {0x10cb0}}},
- {0x10cf1, {1|U, {0x10cb1}}},
- {0x10cf2, {1|U, {0x10cb2}}},
- {0x118c0, {1|U, {0x118a0}}},
- {0x118c1, {1|U, {0x118a1}}},
- {0x118c2, {1|U, {0x118a2}}},
- {0x118c3, {1|U, {0x118a3}}},
- {0x118c4, {1|U, {0x118a4}}},
- {0x118c5, {1|U, {0x118a5}}},
- {0x118c6, {1|U, {0x118a6}}},
- {0x118c7, {1|U, {0x118a7}}},
- {0x118c8, {1|U, {0x118a8}}},
- {0x118c9, {1|U, {0x118a9}}},
- {0x118ca, {1|U, {0x118aa}}},
- {0x118cb, {1|U, {0x118ab}}},
- {0x118cc, {1|U, {0x118ac}}},
- {0x118cd, {1|U, {0x118ad}}},
- {0x118ce, {1|U, {0x118ae}}},
- {0x118cf, {1|U, {0x118af}}},
- {0x118d0, {1|U, {0x118b0}}},
- {0x118d1, {1|U, {0x118b1}}},
- {0x118d2, {1|U, {0x118b2}}},
- {0x118d3, {1|U, {0x118b3}}},
- {0x118d4, {1|U, {0x118b4}}},
- {0x118d5, {1|U, {0x118b5}}},
- {0x118d6, {1|U, {0x118b6}}},
- {0x118d7, {1|U, {0x118b7}}},
- {0x118d8, {1|U, {0x118b8}}},
- {0x118d9, {1|U, {0x118b9}}},
- {0x118da, {1|U, {0x118ba}}},
- {0x118db, {1|U, {0x118bb}}},
- {0x118dc, {1|U, {0x118bc}}},
- {0x118dd, {1|U, {0x118bd}}},
- {0x118de, {1|U, {0x118be}}},
- {0x118df, {1|U, {0x118bf}}},
- {0x16e60, {1|U, {0x16e40}}},
- {0x16e61, {1|U, {0x16e41}}},
- {0x16e62, {1|U, {0x16e42}}},
- {0x16e63, {1|U, {0x16e43}}},
- {0x16e64, {1|U, {0x16e44}}},
- {0x16e65, {1|U, {0x16e45}}},
- {0x16e66, {1|U, {0x16e46}}},
- {0x16e67, {1|U, {0x16e47}}},
- {0x16e68, {1|U, {0x16e48}}},
- {0x16e69, {1|U, {0x16e49}}},
- {0x16e6a, {1|U, {0x16e4a}}},
- {0x16e6b, {1|U, {0x16e4b}}},
- {0x16e6c, {1|U, {0x16e4c}}},
- {0x16e6d, {1|U, {0x16e4d}}},
- {0x16e6e, {1|U, {0x16e4e}}},
- {0x16e6f, {1|U, {0x16e4f}}},
- {0x16e70, {1|U, {0x16e50}}},
- {0x16e71, {1|U, {0x16e51}}},
- {0x16e72, {1|U, {0x16e52}}},
- {0x16e73, {1|U, {0x16e53}}},
- {0x16e74, {1|U, {0x16e54}}},
- {0x16e75, {1|U, {0x16e55}}},
- {0x16e76, {1|U, {0x16e56}}},
- {0x16e77, {1|U, {0x16e57}}},
- {0x16e78, {1|U, {0x16e58}}},
- {0x16e79, {1|U, {0x16e59}}},
- {0x16e7a, {1|U, {0x16e5a}}},
- {0x16e7b, {1|U, {0x16e5b}}},
- {0x16e7c, {1|U, {0x16e5c}}},
- {0x16e7d, {1|U, {0x16e5d}}},
- {0x16e7e, {1|U, {0x16e5e}}},
- {0x16e7f, {1|U, {0x16e5f}}},
- {0x1e922, {1|U, {0x1e900}}},
- {0x1e923, {1|U, {0x1e901}}},
- {0x1e924, {1|U, {0x1e902}}},
- {0x1e925, {1|U, {0x1e903}}},
- {0x1e926, {1|U, {0x1e904}}},
- {0x1e927, {1|U, {0x1e905}}},
- {0x1e928, {1|U, {0x1e906}}},
- {0x1e929, {1|U, {0x1e907}}},
- {0x1e92a, {1|U, {0x1e908}}},
- {0x1e92b, {1|U, {0x1e909}}},
- {0x1e92c, {1|U, {0x1e90a}}},
- {0x1e92d, {1|U, {0x1e90b}}},
- {0x1e92e, {1|U, {0x1e90c}}},
- {0x1e92f, {1|U, {0x1e90d}}},
- {0x1e930, {1|U, {0x1e90e}}},
- {0x1e931, {1|U, {0x1e90f}}},
- {0x1e932, {1|U, {0x1e910}}},
- {0x1e933, {1|U, {0x1e911}}},
- {0x1e934, {1|U, {0x1e912}}},
- {0x1e935, {1|U, {0x1e913}}},
- {0x1e936, {1|U, {0x1e914}}},
- {0x1e937, {1|U, {0x1e915}}},
- {0x1e938, {1|U, {0x1e916}}},
- {0x1e939, {1|U, {0x1e917}}},
- {0x1e93a, {1|U, {0x1e918}}},
- {0x1e93b, {1|U, {0x1e919}}},
- {0x1e93c, {1|U, {0x1e91a}}},
- {0x1e93d, {1|U, {0x1e91b}}},
- {0x1e93e, {1|U, {0x1e91c}}},
- {0x1e93f, {1|U, {0x1e91d}}},
- {0x1e940, {1|U, {0x1e91e}}},
- {0x1e941, {1|U, {0x1e91f}}},
- {0x1e942, {1|U, {0x1e920}}},
- {0x1e943, {1|U, {0x1e921}}},
-#define CaseUnfold_11_Locale (*(CaseUnfold_11_Type (*)[1])(CaseUnfold_11_Table+1395))
- {0x0069, {1|U, {0x0049}}},
-};
-
-/* ANSI-C code produced by gperf version 3.1 */
-/* Command-line: gperf -7 -k1,2,3 -F,-1 -c -j1 -i1 -t -T -E -C -H onigenc_unicode_CaseUnfold_11_hash -N onigenc_unicode_CaseUnfold_11_lookup -n */
-
-/* maximum key range = 2771, duplicates = 0 */
-
-#ifdef __GNUC__
-__inline
-#else
-#ifdef __cplusplus
-inline
-#endif
-#endif
-/*ARGSUSED*/
-static unsigned int
-onigenc_unicode_CaseUnfold_11_hash(const OnigCodePoint code)
-{
- static const unsigned short asso_values[] =
- {
- 1, 2774, 2, 2, 4, 421, 9, 371, 231, 463,
- 37, 20, 2, 3, 419, 408, 2774, 2774, 2774, 2774,
- 2774, 2774, 2774, 2774, 2774, 2774, 2774, 2774, 2774, 112,
- 2774, 2774, 2774, 2774, 2774, 2774, 2774, 120, 2774, 2774,
- 2774, 2774, 2774, 1, 2774, 2774, 2774, 2774, 2774, 2774,
- 2774, 2774, 2774, 355, 2774, 2774, 2774, 2774, 2774, 2774,
- 2774, 2774, 10, 9, 7, 8, 244, 689, 226, 993,
- 561, 710, 104, 1429, 36, 1190, 28, 15, 114, 1768,
- 241, 1003, 87, 285, 26, 1399, 78, 1360, 7, 1455,
- 90, 1076, 113, 10, 724, 1460, 167, 1727, 155, 1040,
- 67, 754, 66, 705, 246, 886, 331, 1140, 430, 1251,
- 864, 768, 643, 1064, 1591, 865, 834, 720, 1700, 671,
- 1581, 657, 1794, 842, 1782, 1050, 1537, 1024, 1760, 814,
- 975, 440, 1187, 407, 1440, 951, 1384, 909, 1320, 555,
- 1567, 541, 1723, 525, 383, 501, 1179, 250, 1596, 342,
- 1575, 352, 1501, 194, 1559, 70, 1512, 85, 1509, 129,
- 467, 100, 1413, 1, 1485, 25, 1351, 35, 1088, 55,
- 1262, 45, 1277, 160, 1245, 317, 118, 220, 1300, 596,
- 1100, 373, 1632, 617, 1337, 1236, 1500, 1152, 148, 793,
- 1538, 979, 385, 1228
- };
- return asso_values[bits_of(code, 2)+66] + asso_values[bits_of(code, 1)+4] + asso_values[bits_of(code, 0)];
-}
-
-static const CodePointList3 *
-onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code)
-{
- enum
- {
- MIN_CODE_VALUE = 0x61,
- MAX_CODE_VALUE = 0x1e943,
- TOTAL_KEYWORDS = 1396,
- MIN_WORD_LENGTH = 3,
- MAX_WORD_LENGTH = 3,
- MIN_HASH_VALUE = 3,
- MAX_HASH_VALUE = 2773
- };
-
- static const short wordlist[] =
- {
- -1, -1, -1,
- /*0x13e1*/ 589,
- /*0x0461*/ 340,
- /*0x04e1*/ 400,
- /*0x0061*/ 0,
- -1,
- /*0x104e1*/ 1184,
- /*0x1e61*/ 661,
- /*0x1ee1*/ 720,
- /*0x0161*/ 102,
- /*0x2ce1*/ 953,
- -1,
- /*0x049b*/ 365,
- -1, -1,
- /*0x24e1*/ 840,
- /*0x1e1b*/ 626,
- /*0x048b*/ 357,
- /*0x011b*/ 69,
- /*0x2c9b*/ 918,
- /*0x03e1*/ 280,
- /*0x1e0b*/ 618,
- /*0x1e8b*/ 682,
- /*0x010b*/ 61,
- /*0x2c8b*/ 910,
- /*0x13e3*/ 591,
- /*0x0463*/ 341,
- /*0x04e3*/ 401,
- /*0x0063*/ 2,
- -1,
- /*0x104e3*/ 1186,
- /*0x1e63*/ 662,
- /*0x1ee3*/ 721,
- /*0x0163*/ 103,
- /*0x2ce3*/ 954,
- /*0x13e5*/ 593,
- /*0x0465*/ 342,
- /*0x04e5*/ 402,
- /*0x0065*/ 4,
- /*0x24e3*/ 842,
- /*0x104e5*/ 1188,
- /*0x1e65*/ 663,
- /*0x1ee5*/ 722,
- /*0x0165*/ 104,
- /*0x03e3*/ 281,
- /*0x13e9*/ 597,
- /*0x0469*/ 344,
- /*0x04e9*/ 404,
- /*0x0069*/ 1395,
- /*0x24e5*/ 844,
- /*0x104e9*/ 1192,
- /*0x1e69*/ 665,
- /*0x1ee9*/ 724,
- /*0x0169*/ 106,
- /*0x03e5*/ 282,
- /*0x13e7*/ 595,
- /*0x0467*/ 343,
- /*0x04e7*/ 403,
- /*0x0067*/ 6,
- /*0x24e9*/ 848,
- /*0x104e7*/ 1190,
- /*0x1e67*/ 664,
- /*0x1ee7*/ 723,
- /*0x0167*/ 105,
- /*0x03e9*/ 284,
- -1,
- /*0x13a4*/ 528,
- /*0x13a2*/ 526,
- -1,
- /*0x24e7*/ 846,
- /*0x13d9*/ 581,
- /*0x0459*/ 333,
- /*0x04d9*/ 396,
- -1,
- /*0x03e7*/ 283,
- /*0x104d9*/ 1176,
- /*0x1e59*/ 657,
- /*0x1ed9*/ 716,
- /*0x0159*/ 98,
- /*0x2cd9*/ 949,
- -1, -1, -1, -1,
- /*0x24d9*/ 832,
- /*0x13db*/ 583,
- /*0x045b*/ 335,
- /*0x04db*/ 397,
- /*0xa761*/ 1065,
- /*0x03d9*/ 276,
- /*0x104db*/ 1178,
- /*0x1e5b*/ 658,
- /*0x1edb*/ 717,
- /*0x015b*/ 99,
- /*0x2cdb*/ 950,
- -1, -1, -1, -1,
- /*0x24db*/ 834,
- /*0x13df*/ 587,
- /*0x045f*/ 339,
- /*0x04df*/ 399,
- -1,
- /*0x03db*/ 277,
- /*0x104df*/ 1182,
- /*0x1e5f*/ 660,
- /*0x1edf*/ 719,
- /*0x015f*/ 101,
- /*0x2cdf*/ 952,
- -1, -1,
- /*0xa763*/ 1066,
- /*0x2c61*/ 897,
- /*0x24df*/ 838,
- /*0x10ce1*/ 1279,
- -1, -1,
- /*0x13ee*/ 602,
- /*0x03df*/ 279,
- /*0x10e1*/ 495,
- /*0x006e*/ 12,
- /*0xa765*/ 1067,
- /*0x104ee*/ 1197,
- -1, -1, -1,
- /*0x2cee*/ 956,
- -1,
- /*0x13dd*/ 585,
- /*0x045d*/ 337,
- /*0x04dd*/ 398,
- /*0xa769*/ 1069,
- -1,
- /*0x104dd*/ 1180,
- /*0x1e5d*/ 659,
- /*0x1edd*/ 718,
- /*0x015d*/ 100,
- /*0x2cdd*/ 951,
- /*0x10ce3*/ 1281,
- -1, -1,
- /*0xa767*/ 1068,
- /*0x24dd*/ 836,
- /*0x10e3*/ 497,
- -1, -1,
- /*0x2c65*/ 898,
- /*0x03dd*/ 278,
- /*0x10ce5*/ 1283,
- -1,
- /*0x007a*/ 24,
- -1,
- /*0x104fa*/ 1209,
- /*0x10e5*/ 499,
- /*0x13a0*/ 524,
- /*0x017a*/ 114,
- /*0xa759*/ 1061,
- -1,
- /*0x10ce9*/ 1287,
- /*0x13eb*/ 599,
- /*0x046b*/ 345,
- /*0x04eb*/ 405,
- /*0x006b*/ 9,
- /*0x10e9*/ 503,
- /*0x104eb*/ 1194,
- /*0x1e6b*/ 666,
- /*0x1eeb*/ 725,
- /*0x016b*/ 107,
- /*0x10ce7*/ 1285,
- -1, -1,
- /*0xa75b*/ 1062,
- -1,
- /*0x10e7*/ 501,
- -1, -1, -1, -1,
- /*0x03eb*/ 285,
- -1, -1,
- /*0x2c59*/ 890,
- -1,
- /*0x10cd9*/ 1271,
- -1, -1,
- /*0xa75f*/ 1064,
- -1,
- /*0x10d9*/ 487,
- -1, -1, -1, -1,
- /*0x13d7*/ 579,
- /*0x0457*/ 331,
- /*0x04d7*/ 395,
- /*0x2c5b*/ 892,
- -1,
- /*0x10cdb*/ 1273,
- /*0x1e57*/ 656,
- /*0x1ed7*/ 715,
- /*0x0157*/ 97,
- /*0x2cd7*/ 948,
- /*0x10db*/ 489,
- -1, -1, -1,
- /*0x24d7*/ 830,
- -1, -1, -1,
- /*0x2c5f*/ 896,
- /*0x03d7*/ 275,
- /*0x10cdf*/ 1277,
- -1,
- /*0xa75d*/ 1063,
- -1, -1,
- /*0x10df*/ 493,
- /*0x13ef*/ 603,
- /*0x046f*/ 347,
- /*0x04ef*/ 407,
- /*0x006f*/ 13,
- -1,
- /*0x104ef*/ 1198,
- /*0x1e6f*/ 668,
- /*0x1eef*/ 727,
- /*0x016f*/ 109,
- -1, -1,
- /*0x0261*/ 210,
- /*0x10cee*/ 1292,
- -1, -1,
- /*0xa77a*/ 1073,
- -1,
- /*0x10ee*/ 508,
- -1,
- /*0x03ef*/ 287,
- /*0x021b*/ 178,
- /*0x2c5d*/ 894,
- /*0xa661*/ 1014,
- /*0x10cdd*/ 1275,
- /*0x1f61*/ 777,
- /*0x020b*/ 170,
- /*0x13a6*/ 530,
- /*0xa76b*/ 1070,
- /*0x10dd*/ 491,
- /*0x1d8e*/ 612,
- /*0x13d1*/ 573,
- /*0x0451*/ 325,
- /*0x04d1*/ 392,
- -1, -1,
- /*0x0263*/ 211,
- /*0x1e51*/ 653,
- /*0x1ed1*/ 712,
- /*0x0151*/ 94,
- /*0x2cd1*/ 945,
- -1, -1, -1, -1,
- /*0x24d1*/ 824,
- /*0x0265*/ 212,
- /*0xa663*/ 1015,
- /*0x10fa*/ 520,
- /*0x1f63*/ 779,
- /*0x1f12*/ 746,
- -1, -1, -1, -1,
- /*0x10ceb*/ 1289,
- /*0x0269*/ 215,
- /*0xa665*/ 1016,
- -1,
- /*0x1f65*/ 781,
- /*0x10eb*/ 505,
- -1,
- /*0xa757*/ 1060,
- -1, -1, -1, -1,
- /*0xa669*/ 1018,
- /*0x0491*/ 360,
- -1, -1, -1,
- /*0x1e11*/ 621,
- /*0x1e91*/ 685,
- /*0x0111*/ 64,
- /*0x2c91*/ 913,
- /*0xa79b*/ 1086,
- /*0xa667*/ 1017,
- -1,
- /*0x1f67*/ 783,
- -1,
- /*0x0259*/ 206,
- -1, -1, -1, -1, -1,
- /*0x2c57*/ 888,
- /*0xa76f*/ 1072,
- /*0x10cd7*/ 1269,
- /*0x1f24*/ 754,
- /*0x1f22*/ 752,
- /*0xa659*/ 1010,
- -1,
- /*0x10d7*/ 485,
- -1,
- /*0x025b*/ 207,
- -1,
- /*0x13ed*/ 601,
- /*0x046d*/ 346,
- /*0x04ed*/ 406,
- /*0x006d*/ 11,
- /*0x1f14*/ 748,
- /*0x104ed*/ 1196,
- /*0x1e6d*/ 667,
- /*0x1eed*/ 726,
- /*0x016d*/ 108,
- /*0xa65b*/ 1011,
- -1, -1, -1,
- /*0x1f10*/ 744,
- /*0x13a8*/ 532,
- -1, -1,
- /*0x10cef*/ 1293,
- /*0x10428*/ 1135,
- /*0x03ed*/ 286,
- /*0xa751*/ 1057,
- -1,
- /*0x10ef*/ 509,
- -1,
- /*0xa65f*/ 1013,
- /*0x13d3*/ 575,
- /*0x0453*/ 327,
- /*0x04d3*/ 393,
- -1, -1,
- /*0x1f06*/ 742,
- /*0x1e53*/ 654,
- /*0x1ed3*/ 713,
- /*0x0153*/ 95,
- /*0x2cd3*/ 946,
- /*0x13d5*/ 577,
- /*0x0455*/ 329,
- /*0x04d5*/ 394,
- /*0xa7d9*/ 1106,
- /*0x24d3*/ 826,
- -1,
- /*0x1e55*/ 655,
- /*0x1ed5*/ 714,
- /*0x0155*/ 96,
- /*0x2cd5*/ 947,
- /*0x2c51*/ 882,
- /*0xa794*/ 1083,
- /*0x10cd1*/ 1263,
- -1,
- /*0x24d5*/ 828,
- -1, -1,
- /*0x10d1*/ 479,
- /*0xa65d*/ 1012,
- /*0x01e1*/ 151,
- -1,
- /*0x13f3*/ 607,
- /*0x0473*/ 349,
- /*0x04f3*/ 409,
- /*0x0073*/ 17,
- -1,
- /*0x104f3*/ 1202,
- /*0x1e73*/ 670,
- /*0x1ef3*/ 729,
- /*0x0173*/ 111,
- /*0x2cf3*/ 957,
- /*0x13ce*/ 570,
- /*0x044e*/ 322,
- /*0x04ce*/ 390,
- -1,
- /*0x1044e*/ 1173,
- -1, -1,
- /*0x026b*/ 217,
- /*0x1f7a*/ 794,
- /*0x03f3*/ 289,
- /*0x017e*/ 116,
- -1,
- /*0x01e3*/ 152,
- /*0x0192*/ 122,
- -1,
- /*0x1f20*/ 750,
- /*0xa78c*/ 1080,
- -1,
- /*0xa66b*/ 1019,
- /*0x03ce*/ 274,
- -1,
- /*0xa76d*/ 1071,
- /*0x01e5*/ 153,
- /*0x0188*/ 120,
- /*0x13c3*/ 559,
- /*0x0443*/ 311,
- /*0x0373*/ 237,
- -1,
- /*0x10443*/ 1162,
- -1,
- /*0x1e43*/ 646,
- /*0x1ec3*/ 705,
- /*0x01e9*/ 155,
- /*0x2cc3*/ 938,
- -1, -1,
- /*0x0561*/ 440,
- /*0x1059b*/ 1215,
- /*0x00e1*/ 26,
- -1, -1,
- /*0x0257*/ 205,
- /*0x01e7*/ 154,
- /*0x03c3*/ 263,
- /*0x118d9*/ 1322,
- /*0x051b*/ 429,
- /*0xa753*/ 1058,
- /*0x13aa*/ 534,
- /*0x10ced*/ 1291,
- /*0xab53*/ 1108,
- /*0x050b*/ 421,
- /*0x1042a*/ 1137,
- /*0xa657*/ 1009,
- /*0x10ed*/ 507,
- /*0x1f57*/ 775,
- -1,
- /*0xa755*/ 1059,
- /*0x13c1*/ 557,
- /*0x0441*/ 309,
- /*0x118db*/ 1324,
- /*0x0563*/ 442,
- /*0x10441*/ 1160,
- /*0x00e3*/ 28,
- /*0x1e41*/ 645,
- /*0x1ec1*/ 704,
- -1,
- /*0x2cc1*/ 937,
- /*0x026f*/ 219,
- -1, -1,
- /*0x0565*/ 444,
- /*0x2c53*/ 884,
- /*0x00e5*/ 30,
- /*0x10cd3*/ 1265,
- /*0x118df*/ 1328,
- -1,
- /*0x03c1*/ 262,
- -1,
- /*0x10d3*/ 481,
- -1,
- /*0x0569*/ 448,
- /*0x2c55*/ 886,
- /*0x00e9*/ 34,
- /*0x10cd5*/ 1267,
- /*0x13de*/ 586,
- /*0x045e*/ 338,
- /*0x1f02*/ 738,
- /*0x01df*/ 150,
- /*0x10d5*/ 483,
- /*0x104de*/ 1181,
- /*0x0567*/ 446,
- -1,
- /*0x00e7*/ 32,
- /*0x105a4*/ 1223,
- /*0x028b*/ 231,
- -1,
- /*0xa7d7*/ 1105,
- /*0x0251*/ 200,
- /*0x24de*/ 837,
- -1,
- /*0x019a*/ 125,
- /*0x018c*/ 121,
- /*0x2c73*/ 903,
- /*0x118dd*/ 1326,
- /*0x1f00*/ 736,
- /*0x0292*/ 233,
- /*0x1f26*/ 756,
- /*0x028a*/ 230,
- /*0xa651*/ 1006,
- /*0x10f3*/ 513,
- /*0x1f51*/ 772,
- /*0xa743*/ 1050,
- /*0x2c4e*/ 879,
- -1,
- /*0x10cce*/ 1260,
- /*0x0288*/ 228,
- /*0x01dd*/ 149,
- /*0x10598*/ 1212,
- /*0x13cf*/ 571,
- /*0x044f*/ 323,
- /*0x04cf*/ 391,
- /*0x10fe*/ 522,
- /*0x1044f*/ 1174,
- -1,
- /*0x1e4f*/ 652,
- /*0x1ecf*/ 711,
- /*0x014f*/ 93,
- /*0x2ccf*/ 944,
- /*0x0586*/ 477,
- -1,
- /*0x1e924*/ 1363,
- /*0x1e922*/ 1361,
- /*0x0211*/ 173,
- -1, -1, -1,
- /*0x2c43*/ 868,
- -1,
- /*0x10cc3*/ 1249,
- -1,
- /*0x1059a*/ 1214,
- -1,
- /*0x13cd*/ 569,
- /*0x044d*/ 321,
- /*0xa741*/ 1049,
- /*0x1f11*/ 745,
- /*0x1044d*/ 1172,
- /*0x01eb*/ 156,
- /*0x1e4d*/ 651,
- /*0x1ecd*/ 710,
- /*0x014d*/ 92,
- /*0x2ccd*/ 943,
- /*0xa7d1*/ 1104,
- /*0x056e*/ 453,
- /*0x019e*/ 126,
- /*0x00ee*/ 39,
- -1, -1,
- /*0x13cb*/ 567,
- /*0x044b*/ 319,
- -1,
- /*0x03cd*/ 273,
- /*0x1044b*/ 1170,
- -1,
- /*0x1e4b*/ 650,
- /*0x1ecb*/ 709,
- /*0x014b*/ 91,
- /*0x2ccb*/ 942,
- /*0x118d7*/ 1320,
- /*0x2c41*/ 866,
- -1,
- /*0x10cc1*/ 1247,
- /*0x13c9*/ 565,
- /*0x0449*/ 317,
- -1,
- /*0xa66d*/ 1020,
- /*0x10449*/ 1168,
- /*0x03cb*/ 271,
- /*0x1e49*/ 649,
- /*0x1ec9*/ 708,
- -1,
- /*0x2cc9*/ 941,
- /*0x105a0*/ 1220,
- /*0x057a*/ 465,
- -1,
- /*0x00fa*/ 50,
- -1,
- /*0xa791*/ 1081,
- -1,
- /*0x0253*/ 202,
- -1,
- /*0x03c9*/ 269,
- -1,
- /*0x028c*/ 232,
- /*0x1059e*/ 1218,
- /*0x056b*/ 450,
- /*0x2c5e*/ 895,
- /*0x00eb*/ 36,
- /*0x10cde*/ 1276,
- -1,
- /*0xa653*/ 1007,
- -1,
- /*0x1f53*/ 773,
- /*0x10de*/ 492,
- /*0x16e61*/ 1330,
- /*0xa74f*/ 1056,
- -1,
- /*0x01ef*/ 158,
- -1, -1,
- /*0xa655*/ 1008,
- -1,
- /*0x1f55*/ 774,
- /*0x13f1*/ 605,
- /*0x0471*/ 348,
- /*0x04f1*/ 408,
- /*0x0071*/ 15,
- -1,
- /*0x104f1*/ 1200,
- /*0x1e71*/ 669,
- /*0x1ef1*/ 728,
- /*0x0171*/ 110,
- -1, -1,
- /*0x118d1*/ 1314,
- -1, -1, -1,
- /*0x16e63*/ 1332,
- /*0xa74d*/ 1055,
- /*0x2c4f*/ 880,
- /*0x0180*/ 117,
- /*0x10ccf*/ 1261,
- /*0x1f73*/ 787,
- /*0x13f5*/ 609,
- /*0x0475*/ 350,
- /*0x04f5*/ 410,
- /*0x0075*/ 19,
- /*0x16e65*/ 1334,
- /*0x104f5*/ 1204,
- /*0x1e75*/ 671,
- /*0x1ef5*/ 730,
- /*0x0175*/ 112,
- -1, -1,
- /*0xa74b*/ 1054,
- /*0x029e*/ 235,
- -1,
- /*0x16e69*/ 1338,
- /*0x0371*/ 236,
- /*0x0582*/ 473,
- -1, -1, -1,
- /*0x2c4d*/ 878,
- /*0x056f*/ 454,
- /*0x10ccd*/ 1259,
- /*0x00ef*/ 40,
- /*0x16e67*/ 1336,
- /*0xa749*/ 1053,
- /*0x13ae*/ 538,
- -1, -1, -1,
- /*0x1042e*/ 1141,
- /*0xa643*/ 999,
- -1,
- /*0x1f43*/ 769,
- /*0x0580*/ 471,
- -1,
- /*0x2c4b*/ 876,
- -1,
- /*0x10ccb*/ 1257,
- /*0x105a6*/ 1225,
- /*0x13b7*/ 547,
- /*0x0437*/ 299,
- /*0x04b7*/ 379,
- -1,
- /*0x10437*/ 1150,
- /*0x03ae*/ 244,
- /*0x1e37*/ 640,
- /*0x1eb7*/ 699,
- /*0x0137*/ 82,
- /*0x2cb7*/ 932,
- /*0x2c49*/ 874,
- -1,
- /*0x10cc9*/ 1255,
- -1,
- /*0x13b5*/ 545,
- /*0x0435*/ 297,
- /*0x04b5*/ 378,
- -1,
- /*0x10435*/ 1148,
- /*0x03b7*/ 252,
- /*0x1e35*/ 639,
- /*0x1eb5*/ 698,
- /*0x0135*/ 81,
- /*0x2cb5*/ 931,
- /*0xa641*/ 998,
- -1,
- /*0x1f41*/ 767,
- -1, -1, -1,
- /*0x01ed*/ 157,
- /*0x0282*/ 225,
- /*0x1fe1*/ 803,
- /*0x03b5*/ 250,
- /*0x0481*/ 356,
- /*0xa7c3*/ 1101,
- /*0x1e926*/ 1365,
- -1,
- /*0x1e01*/ 613,
- /*0x1e81*/ 677,
- /*0x0101*/ 56,
- /*0x2c81*/ 905,
- /*0x118d3*/ 1316,
- -1,
- /*0x01a8*/ 130,
- -1,
- /*0x0511*/ 424,
- /*0x16e6e*/ 1343,
- /*0x13a5*/ 529,
- /*0x0280*/ 224,
- /*0x04a5*/ 370,
- /*0x217a*/ 816,
- /*0x118d5*/ 1318,
- /*0x10cf1*/ 1295,
- /*0x1e25*/ 631,
- /*0x1ea5*/ 690,
- /*0x0125*/ 74,
- /*0x2ca5*/ 923,
- /*0x10f1*/ 511,
- /*0x1e05*/ 615,
- /*0x1e85*/ 679,
- /*0x0105*/ 58,
- /*0x2c85*/ 907,
- /*0x13b3*/ 543,
- /*0x0433*/ 295,
- /*0x04b3*/ 377,
- /*0x1fe5*/ 804,
- /*0x10433*/ 1146,
- /*0xa7c1*/ 1100,
- /*0x1e33*/ 638,
- /*0x1eb3*/ 697,
- /*0x0133*/ 80,
- /*0x2cb3*/ 930,
- /*0x2d16*/ 980,
- /*0x024f*/ 198,
- -1,
- /*0x2d1b*/ 985,
- /*0x16e7a*/ 1355,
- /*0x056d*/ 452,
- /*0x10f5*/ 515,
- /*0x00ed*/ 38,
- /*0x2d0b*/ 969,
- /*0x03b3*/ 248,
- /*0x118ce*/ 1311,
- /*0x105a8*/ 1227,
- /*0xa64f*/ 1005,
- /*0x01f3*/ 159,
- /*0xa737*/ 1044,
- -1,
- /*0x16e6b*/ 1340,
- -1, -1,
- /*0x2d12*/ 976,
- -1,
- /*0x2d0a*/ 968,
- -1,
- /*0x01ce*/ 141,
- /*0x13a3*/ 527,
- /*0x024d*/ 197,
- /*0x04a3*/ 369,
- -1,
- /*0xa735*/ 1043,
- /*0x2d08*/ 966,
- /*0x1e23*/ 630,
- /*0x1ea3*/ 689,
- /*0x0123*/ 73,
- /*0x2ca3*/ 922,
- /*0x118c3*/ 1300,
- -1,
- /*0xa64d*/ 1004,
- -1,
- /*0x13ad*/ 537,
- /*0x2c37*/ 856,
- /*0x04ad*/ 374,
- /*0x024b*/ 196,
- /*0x1042d*/ 1140,
- -1,
- /*0x1e2d*/ 635,
- /*0x1ead*/ 694,
- /*0x012d*/ 78,
- /*0x2cad*/ 927,
- /*0x1e928*/ 1367,
- -1, -1, -1,
- /*0xa64b*/ 1003,
- /*0x2c35*/ 854,
- -1,
- /*0x0249*/ 195,
- -1,
- /*0x03ad*/ 243,
- -1,
- /*0x2d24*/ 994,
- /*0x2d22*/ 992,
- /*0x0573*/ 458,
- /*0xa725*/ 1036,
- /*0x00f3*/ 44,
- /*0x047b*/ 353,
- /*0x04fb*/ 413,
- /*0xa649*/ 1002,
- /*0x118c1*/ 1298,
- /*0x104fb*/ 1210,
- /*0x1e7b*/ 674,
- /*0x1efb*/ 733,
- /*0x2d14*/ 978,
- -1,
- /*0x057e*/ 469,
- /*0x1f04*/ 740,
- /*0x00fe*/ 54,
- /*0x16e6f*/ 1344,
- /*0xa733*/ 1042,
- -1, -1,
- /*0x2d10*/ 974,
- -1,
- /*0x03fb*/ 291,
- /*0x2d18*/ 982,
- /*0x13bf*/ 555,
- /*0x043f*/ 307,
- /*0x04bf*/ 383,
- -1,
- /*0x1043f*/ 1158,
- -1,
- /*0x1e3f*/ 644,
- /*0x1ebf*/ 703,
- -1,
- /*0x2cbf*/ 936,
- /*0x118de*/ 1327,
- -1,
- /*0x0271*/ 220,
- /*0x2d06*/ 964,
- -1,
- /*0x037b*/ 239,
- -1, -1,
- /*0x2c33*/ 852,
- /*0x03bf*/ 260,
- /*0x13b2*/ 542,
- /*0x0432*/ 294,
- /*0x2d1a*/ 984,
- /*0x2d0c*/ 970,
- /*0x10432*/ 1145,
- /*0x1f71*/ 785,
- /*0x105aa*/ 1229,
- /*0xa723*/ 1035,
- /*0x13b9*/ 549,
- /*0x0439*/ 301,
- /*0x04b9*/ 380,
- -1,
- /*0x10439*/ 1152,
- /*0x0275*/ 222,
- /*0x1e39*/ 641,
- /*0x1eb9*/ 700,
- -1,
- /*0x2cb9*/ 933,
- -1,
- /*0x03b2*/ 247,
- /*0x1e943*/ 1394,
- /*0xa72d*/ 1040,
- -1, -1,
- /*0x118cf*/ 1312,
- -1,
- /*0x1f75*/ 789,
- /*0x03b9*/ 254,
- -1, -1,
- /*0x13ac*/ 536,
- /*0x13b1*/ 541,
- /*0x0431*/ 293,
- /*0x04b1*/ 376,
- /*0x1042c*/ 1139,
- /*0x10431*/ 1144,
- -1,
- /*0x1e31*/ 637,
- /*0x1eb1*/ 696,
- -1,
- /*0x2cb1*/ 929,
- -1, -1,
- /*0x1e92a*/ 1369,
- /*0x2d20*/ 990,
- -1, -1, -1,
- /*0x118cd*/ 1310,
- /*0x03ac*/ 242,
- /*0x03b1*/ 246,
- -1,
- /*0x13a7*/ 531,
- /*0x1e941*/ 1392,
- /*0x04a7*/ 371,
- -1,
- /*0x2d1e*/ 988,
- -1,
- /*0x1e27*/ 632,
- /*0x1ea7*/ 691,
- /*0x0127*/ 75,
- /*0x2ca7*/ 924,
- -1, -1,
- /*0x118cb*/ 1308,
- -1,
- /*0x1f37*/ 765,
- /*0xa73f*/ 1048,
- -1,
- /*0x16e6d*/ 1342,
- -1, -1, -1, -1, -1,
- /*0x13c7*/ 563,
- /*0x0447*/ 315,
- -1,
- /*0x118c9*/ 1306,
- /*0x10447*/ 1166,
- /*0x1f35*/ 763,
- /*0x1e47*/ 648,
- /*0x1ec7*/ 707,
- -1,
- /*0x2cc7*/ 940,
- /*0x0201*/ 165,
- -1, -1, -1, -1, -1,
- /*0x01c9*/ 139,
- /*0x2c3f*/ 864,
- -1,
- /*0x03c7*/ 267,
- /*0xa739*/ 1045,
- -1, -1,
- /*0x1f01*/ 737,
- /*0x2173*/ 809,
- -1,
- /*0x0225*/ 182,
- -1, -1,
- /*0x1fd1*/ 801,
- -1,
- /*0x0205*/ 167,
- -1,
- /*0xa7b7*/ 1095,
- /*0x214e*/ 805,
- -1,
- /*0x217e*/ 820,
- /*0x2c32*/ 851,
- -1,
- /*0x1f25*/ 755,
- /*0x2d02*/ 960,
- /*0x0233*/ 189,
- /*0x13c5*/ 561,
- /*0x0445*/ 313,
- /*0x1f05*/ 741,
- /*0x2c39*/ 858,
- /*0x10445*/ 1164,
- /*0xa7b5*/ 1094,
- /*0x1e45*/ 647,
- /*0x1ec5*/ 706,
- /*0x16e73*/ 1348,
- /*0x2cc5*/ 939,
- -1, -1,
- /*0x1f33*/ 761,
- /*0x2d0e*/ 972,
- -1, -1,
- /*0x2d00*/ 958,
- /*0x0584*/ 475,
- -1,
- /*0x03c5*/ 265,
- /*0x16e7e*/ 1359,
- -1,
- /*0xa727*/ 1037,
- /*0xa781*/ 1076,
- /*0x13c0*/ 556,
- /*0x0440*/ 308,
- /*0x2c31*/ 850,
- -1,
- /*0x10440*/ 1159,
- /*0x047d*/ 354,
- /*0x04fd*/ 414,
- -1,
- /*0x0140*/ 86,
- /*0x0223*/ 181,
- /*0x1e7d*/ 675,
- /*0x1efd*/ 734,
- /*0x01f5*/ 160,
- /*0x1d7d*/ 611,
- -1,
- /*0xa7a5*/ 1091,
- -1, -1, -1,
- /*0x03c0*/ 261,
- /*0xa785*/ 1078,
- /*0xa747*/ 1052,
- /*0x1f23*/ 753,
- /*0x022d*/ 186,
- /*0x1e03*/ 614,
- /*0x1e83*/ 678,
- /*0x0103*/ 57,
- /*0x2c83*/ 906,
- -1, -1,
- /*0x048f*/ 359,
- -1, -1,
- /*0x2d11*/ 975,
- /*0x1e0f*/ 620,
- /*0x1e8f*/ 684,
- /*0x010f*/ 63,
- /*0x2c8f*/ 912,
- /*0xa69b*/ 1034,
- /*0x0571*/ 456,
- /*0x037d*/ 241,
- /*0x00f1*/ 42,
- -1,
- /*0xa68b*/ 1026,
- -1, -1,
- /*0x2c47*/ 872,
- -1,
- /*0x10cc7*/ 1253,
- /*0x13bd*/ 553,
- /*0x043d*/ 305,
- /*0x04bd*/ 382,
- -1,
- /*0x1043d*/ 1156,
- -1,
- /*0x1e3d*/ 643,
- /*0x1ebd*/ 702,
- -1,
- /*0x2cbd*/ 935,
- -1,
- /*0x0575*/ 460,
- /*0x1f7b*/ 795,
- /*0x00f5*/ 46,
- /*0xa745*/ 1051,
- /*0xa7a3*/ 1090,
- /*0x13a1*/ 525,
- -1,
- /*0x04a1*/ 368,
- /*0x03bd*/ 258,
- /*0x023f*/ 191,
- /*0xff59*/ 1133,
- /*0x1e21*/ 629,
- /*0x1ea1*/ 688,
- /*0x0121*/ 72,
- /*0x2ca1*/ 921,
- /*0x13bb*/ 551,
- /*0x043b*/ 303,
- /*0x04bb*/ 381,
- /*0x105ae*/ 1233,
- /*0x1043b*/ 1154,
- -1,
- /*0x1e3b*/ 642,
- /*0x1ebb*/ 701,
- -1,
- /*0x2cbb*/ 934,
- -1, -1, -1,
- /*0x2c45*/ 870,
- /*0x13af*/ 539,
- /*0x10cc5*/ 1251,
- /*0x04af*/ 375,
- /*0x105b7*/ 1241,
- /*0x1042f*/ 1142,
- /*0x03bb*/ 256,
- /*0x1e2f*/ 636,
- /*0x1eaf*/ 695,
- /*0x012f*/ 79,
- /*0x2caf*/ 928,
- -1,
- /*0x01a5*/ 129,
- -1,
- /*0x1f32*/ 760,
- /*0x0499*/ 364,
- -1,
- /*0x0185*/ 119,
- /*0x105b5*/ 1239,
- /*0x1e19*/ 625,
- /*0x03af*/ 245,
- /*0x0119*/ 68,
- /*0x2c99*/ 917,
- -1,
- /*0x2c40*/ 865,
- /*0x13e6*/ 594,
- /*0x10cc0*/ 1246,
- /*0x1e92e*/ 1373,
- /*0x0066*/ 5,
- -1,
- /*0x104e6*/ 1189,
- -1,
- /*0x0231*/ 188,
- /*0x0581*/ 472,
- -1,
- /*0x10fd*/ 521,
- /*0xa7bf*/ 1099,
- /*0x13f2*/ 606,
- -1,
- /*0x24e6*/ 845,
- /*0x0072*/ 16,
- /*0x1e937*/ 1382,
- /*0x104f2*/ 1201,
- -1,
- /*0x0501*/ 416,
- /*0x1f31*/ 759,
- -1, -1,
- /*0xa73d*/ 1047,
- -1, -1, -1,
- /*0x105a5*/ 1224,
- /*0x0227*/ 183,
- /*0x0585*/ 476,
- /*0x1e935*/ 1380,
- /*0x03f2*/ 288,
- -1, -1, -1,
- /*0x0525*/ 434,
- /*0x01a3*/ 128,
- -1, -1,
- /*0xa7b9*/ 1096,
- /*0x0505*/ 418,
- /*0x1f27*/ 757,
- /*0x105b3*/ 1237,
- -1, -1, -1,
- /*0x1059c*/ 1216,
- -1,
- /*0x2c3d*/ 862,
- /*0xa73b*/ 1046,
- /*0x01ad*/ 131,
- /*0x0247*/ 194,
- /*0x13a9*/ 533,
- -1,
- /*0x04a9*/ 372,
- -1,
- /*0x10429*/ 1136,
- -1,
- /*0x1e29*/ 633,
- /*0x1ea9*/ 692,
- /*0x0129*/ 76,
- /*0x2ca9*/ 925,
- /*0xa647*/ 1001,
- /*0xa72f*/ 1041,
- /*0x1e925*/ 1364,
- /*0x0479*/ 352,
- /*0x04f9*/ 412,
- /*0x0079*/ 23,
- /*0x2171*/ 807,
- /*0x104f9*/ 1208,
- /*0x1e79*/ 673,
- /*0x1ef9*/ 732,
- -1,
- /*0x1d79*/ 610,
- /*0x2c3b*/ 860,
- /*0x01fb*/ 162,
- /*0x105a3*/ 1222,
- -1, -1,
- /*0x1e933*/ 1378,
- -1,
- /*0xff57*/ 1131,
- -1,
- /*0xa7a7*/ 1092,
- /*0x0523*/ 433,
- -1, -1, -1, -1,
- /*0x2175*/ 811,
- /*0x105ad*/ 1232,
- /*0x13d0*/ 572,
- /*0x0450*/ 324,
- -1,
- /*0x16e71*/ 1346,
- -1,
- /*0x01bf*/ 137,
- -1,
- /*0x052d*/ 438,
- /*0x13c2*/ 558,
- /*0x0442*/ 310,
- /*0x04c2*/ 384,
- -1,
- /*0x10442*/ 1161,
- /*0xa645*/ 1000,
- /*0x24d0*/ 823,
- /*0x1f45*/ 771,
- /*0x0142*/ 87,
- /*0x1e09*/ 617,
- /*0x1e89*/ 681,
- /*0x0109*/ 60,
- /*0x2c89*/ 909,
- /*0x2c66*/ 899,
- /*0x1e923*/ 1362,
- /*0x10ce6*/ 1284,
- /*0x16e75*/ 1350,
- -1,
- /*0x0240*/ 192,
- -1,
- /*0x10e6*/ 500,
- -1,
- /*0x027d*/ 223,
- -1,
- /*0x057b*/ 466,
- /*0x01b9*/ 135,
- /*0x00fb*/ 51,
- /*0x10cf2*/ 1296,
- /*0x1e92d*/ 1372,
- -1, -1,
- /*0x1f40*/ 766,
- /*0x10f2*/ 512,
- -1, -1,
- /*0x1f7d*/ 797,
- /*0x0203*/ 166,
- -1,
- /*0xff51*/ 1125,
- -1,
- /*0xa729*/ 1038,
- -1,
- /*0x047f*/ 355,
- /*0x04ff*/ 415,
- -1, -1,
- /*0x020f*/ 172,
- /*0x1e7f*/ 676,
- /*0x1eff*/ 735,
- /*0x1f03*/ 739,
- /*0x0477*/ 351,
- /*0x04f7*/ 411,
- /*0x0077*/ 21,
- -1,
- /*0x104f7*/ 1206,
- /*0x1e77*/ 672,
- /*0x1ef7*/ 731,
- /*0x0177*/ 113,
- /*0x13ec*/ 600,
- -1, -1,
- /*0x006c*/ 10,
- -1,
- /*0x104ec*/ 1195,
- /*0x13ab*/ 535,
- /*0x105b9*/ 1243,
- /*0x04ab*/ 373,
- /*0x2cec*/ 955,
- /*0x1042b*/ 1138,
- -1,
- /*0x1e2b*/ 634,
- /*0x1eab*/ 693,
- /*0x012b*/ 77,
- /*0x2cab*/ 926,
- /*0x1e93f*/ 1390,
- /*0x13e8*/ 596,
- -1, -1,
- /*0x0068*/ 7,
- /*0x118c7*/ 1304,
- /*0x104e8*/ 1191,
- -1, -1,
- /*0x2184*/ 822,
- /*0x10f9*/ 519,
- /*0x0377*/ 238,
- -1,
- /*0x105ac*/ 1231,
- /*0x105b1*/ 1236,
- /*0x24e8*/ 847,
- /*0x13ea*/ 598,
- /*0xa783*/ 1077,
- -1,
- /*0x006a*/ 8,
- /*0x1e932*/ 1377,
- /*0x104ea*/ 1193,
- /*0x1f21*/ 751,
- /*0x2d04*/ 962,
- -1, -1, -1,
- /*0xa691*/ 1029,
- /*0x1e939*/ 1384,
- -1,
- /*0x2c50*/ 881,
- -1,
- /*0x10cd0*/ 1262,
- /*0x022f*/ 187,
- -1,
- /*0x105a7*/ 1226,
- -1,
- /*0x10d0*/ 478,
- /*0x2c42*/ 867,
- /*0x13f0*/ 604,
- /*0x10cc2*/ 1248,
- -1,
- /*0x0070*/ 14,
- /*0x0527*/ 435,
- /*0x104f0*/ 1199,
- /*0x0219*/ 177,
- -1,
- /*0x118c5*/ 1302,
- /*0xa7bd*/ 1098,
- -1,
- /*0x1e92c*/ 1371,
- /*0x1e931*/ 1376,
- -1, -1,
- /*0xa77f*/ 1075,
- -1,
- /*0xff53*/ 1127,
- /*0x0266*/ 213,
- -1,
- /*0x13c8*/ 564,
- /*0x0448*/ 316,
- /*0x04c8*/ 387,
- -1,
- /*0x10448*/ 1167,
- /*0xa7a1*/ 1089,
- -1,
- /*0xff55*/ 1129,
- /*0x0148*/ 90,
- -1,
- /*0x0272*/ 221,
- /*0x1f66*/ 782,
- /*0x118c0*/ 1297,
- /*0x1e927*/ 1366,
- -1,
- /*0xa7bb*/ 1097,
- -1, -1,
- /*0xa72b*/ 1039,
- /*0x03c8*/ 268,
- /*0x0076*/ 20,
- -1,
- /*0x104f6*/ 1205,
- /*0x1f72*/ 786,
- -1, -1, -1,
- /*0x10ff*/ 523,
- -1,
- /*0x01fd*/ 163,
- -1,
- /*0x13e4*/ 592,
- -1,
- /*0x217b*/ 817,
- /*0x0064*/ 3,
- /*0x10f7*/ 517,
- /*0x104e4*/ 1187,
- /*0x2c6c*/ 902,
- /*0xff4e*/ 1122,
- /*0x10cec*/ 1290,
- -1,
- /*0xa799*/ 1085,
- /*0x0495*/ 362,
- /*0x0183*/ 118,
- /*0x10ec*/ 506,
- /*0x24e4*/ 843,
- /*0x1e15*/ 623,
- /*0x1e95*/ 687,
- /*0x0115*/ 66,
- /*0x2c95*/ 915,
- /*0x0229*/ 184,
- -1, -1, -1,
- /*0x2c68*/ 900,
- -1,
- /*0x10ce8*/ 1286,
- -1, -1,
- /*0x16e7b*/ 1356,
- -1,
- /*0x10e8*/ 502,
- /*0xff43*/ 1111,
- -1,
- /*0x13c6*/ 562,
- /*0x0446*/ 314,
- /*0x04c6*/ 386,
- -1,
- /*0x10446*/ 1165,
- /*0x2c6a*/ 901,
- -1,
- /*0x10cea*/ 1288,
- /*0x0146*/ 89,
- -1,
- /*0x01bd*/ 136,
- /*0x1f79*/ 793,
- /*0x10ea*/ 504,
- /*0x057d*/ 468,
- -1,
- /*0x00fd*/ 53,
- /*0x0583*/ 474,
- /*0x0493*/ 361,
- -1,
- /*0x03c6*/ 266,
- -1,
- /*0x1e13*/ 622,
- /*0x1e93*/ 686,
- /*0x0113*/ 65,
- /*0x2c93*/ 914,
- /*0x0250*/ 199,
- /*0x01a1*/ 127,
- /*0x0503*/ 417,
- /*0x2d01*/ 959,
- /*0x13e0*/ 588,
- /*0x10cf0*/ 1294,
- /*0xff41*/ 1109,
- -1,
- /*0x0242*/ 193,
- /*0x104e0*/ 1183,
- /*0x10f0*/ 510,
- /*0x0209*/ 169,
- /*0x050f*/ 423,
- /*0x1e940*/ 1391,
- -1, -1,
- /*0xa7a9*/ 1093,
- -1,
- /*0x24e0*/ 839,
- /*0x2d25*/ 995,
- -1,
- /*0x1f42*/ 768,
- -1,
- /*0x2c48*/ 873,
- /*0x2d05*/ 963,
- /*0x10cc8*/ 1254,
- /*0x1e07*/ 616,
- /*0x1e87*/ 680,
- /*0x0107*/ 59,
- /*0x2c87*/ 908,
- -1,
- /*0x13c4*/ 560,
- /*0x0444*/ 312,
- /*0x04c4*/ 385,
- -1,
- /*0x10444*/ 1163,
- -1,
- /*0x0199*/ 124,
- /*0x2d1c*/ 986,
- /*0x0144*/ 88,
- /*0x2c76*/ 904,
- /*0x105a1*/ 1221,
- -1, -1, -1, -1,
- /*0x0283*/ 226,
- /*0x10f6*/ 516,
- /*0x0497*/ 363,
- /*0x0521*/ 432,
- /*0x03c4*/ 264,
- /*0x105bb*/ 1244,
- /*0x1e17*/ 624,
- /*0x049d*/ 366,
- /*0x0117*/ 67,
- /*0x2c97*/ 916,
- /*0x10ce4*/ 1282,
- /*0x1e1d*/ 627,
- -1,
- /*0x011d*/ 70,
- /*0x2c9d*/ 919,
- /*0x10e4*/ 498,
- /*0x1e93d*/ 1388,
- -1, -1,
- /*0x105af*/ 1234,
- /*0x026c*/ 218,
- /*0xff4f*/ 1123,
- /*0x2d23*/ 993,
- -1,
- /*0x1f77*/ 791,
- -1,
- /*0x022b*/ 185,
- /*0x052f*/ 439,
- -1, -1,
- /*0x13e2*/ 590,
- /*0x10599*/ 1213,
- -1,
- /*0x0062*/ 1,
- -1,
- /*0x104e2*/ 1185,
- /*0x2d2d*/ 997,
- /*0x0268*/ 214,
- -1,
- /*0x0519*/ 428,
- -1,
- /*0x2c46*/ 871,
- /*0x1e93b*/ 1386,
- /*0x10cc6*/ 1252,
- /*0x24e2*/ 841,
- /*0xff4d*/ 1121,
- /*0x13d6*/ 578,
- /*0x0456*/ 330,
- /*0x0078*/ 22,
- -1,
- /*0x104f8*/ 1207,
- /*0x0566*/ 445,
- /*0x026a*/ 216,
- /*0x00e6*/ 31,
- /*0x13dc*/ 584,
- /*0x045c*/ 336,
- /*0x1e92f*/ 1374,
- /*0x13da*/ 582,
- /*0x045a*/ 334,
- /*0x104dc*/ 1179,
- /*0x24d6*/ 829,
- /*0xff4b*/ 1119,
- /*0x104da*/ 1177,
- /*0x0572*/ 457,
- /*0x03f8*/ 290,
- /*0x00f2*/ 43,
- -1,
- /*0x01f9*/ 161,
- /*0x24dc*/ 835,
- -1, -1,
- /*0x24da*/ 833,
- /*0x10ce0*/ 1278,
- -1, -1,
- /*0xff49*/ 1117,
- -1,
- /*0x10e0*/ 494,
- -1, -1, -1,
- /*0x118d0*/ 1313,
- /*0x13bc*/ 552,
- /*0x043c*/ 304,
- /*0x217d*/ 819,
- -1,
- /*0x1043c*/ 1155,
- -1,
- /*0x1f70*/ 784,
- /*0x118c2*/ 1299,
- /*0x013c*/ 84,
- /*0x017c*/ 115,
- -1, -1,
- /*0x01d0*/ 142,
- /*0x105a9*/ 1228,
- -1,
- /*0x2c44*/ 869,
- /*0x1fb1*/ 799,
- /*0x10cc4*/ 1250,
- -1,
- /*0x03bc*/ 257,
- -1,
- /*0x0529*/ 436,
- /*0x13d8*/ 580,
- /*0x0458*/ 332,
- -1, -1, -1,
- /*0x104d8*/ 1175,
- /*0x16e7d*/ 1358,
- -1,
- /*0x13ca*/ 566,
- /*0x044a*/ 318,
- /*0x04ca*/ 388,
- /*0x0579*/ 464,
- /*0x1044a*/ 1169,
- /*0x00f9*/ 49,
- /*0x24d8*/ 831,
- /*0x037c*/ 240,
- /*0x13d4*/ 576,
- /*0x0454*/ 328,
- -1, -1, -1,
- /*0x1f76*/ 790,
- /*0x13b6*/ 546,
- /*0x0436*/ 298,
- -1, -1,
- /*0x10436*/ 1149,
- /*0x03ca*/ 270,
- /*0x1e929*/ 1368,
- -1,
- /*0x24d4*/ 827,
- /*0x0215*/ 175,
- /*0x13b0*/ 540,
- /*0x0430*/ 292,
- -1,
- /*0x1f64*/ 780,
- /*0x10430*/ 1143,
- /*0x13d2*/ 574,
- /*0x0452*/ 326,
- /*0x01ff*/ 164,
- /*0x10ce2*/ 1280,
- /*0x03b6*/ 251,
- -1, -1,
- /*0x1f15*/ 749,
- /*0x10e2*/ 496,
- /*0xa7c8*/ 1102,
- -1, -1,
- /*0x0509*/ 420,
- /*0x2d27*/ 996,
- /*0x24d2*/ 825,
- -1, -1,
- /*0x2c56*/ 887,
- -1,
- /*0x10cd6*/ 1268,
- -1, -1, -1,
- /*0x10f8*/ 518,
- /*0x10d6*/ 484,
- /*0x2c5c*/ 893,
- /*0xa7f6*/ 1107,
- /*0x10cdc*/ 1274,
- /*0x2c5a*/ 891,
- /*0xa77c*/ 1074,
- /*0x10cda*/ 1272,
- -1,
- /*0x10dc*/ 490,
- /*0x0213*/ 174,
- -1,
- /*0x10da*/ 488,
- /*0x13f4*/ 608,
- -1,
- /*0x1e942*/ 1393,
- /*0x0074*/ 18,
- -1,
- /*0x104f4*/ 1203,
- -1, -1, -1, -1,
- /*0x1f13*/ 747,
- /*0x0260*/ 209,
- -1, -1,
- /*0x057f*/ 470,
- -1,
- /*0x00ff*/ 55,
- /*0x2c3c*/ 861,
- -1, -1,
- /*0x0289*/ 229,
- -1,
- /*0x0577*/ 462,
- -1,
- /*0x1f60*/ 776,
- -1, -1,
- /*0x0207*/ 168,
- /*0x2172*/ 808,
- /*0x105ab*/ 1230,
- -1,
- /*0x056c*/ 451,
- -1,
- /*0x00ec*/ 37,
- -1, -1, -1,
- /*0x052b*/ 437,
- -1,
- /*0x2c58*/ 889,
- /*0x1f07*/ 743,
- /*0x10cd8*/ 1270,
- /*0x16e66*/ 1335,
- -1, -1,
- /*0x118c8*/ 1305,
- /*0x10d8*/ 486,
- /*0x2c4a*/ 875,
- /*0x0568*/ 447,
- /*0x10cca*/ 1256,
- /*0x00e8*/ 33,
- /*0x1f44*/ 770,
- /*0xa793*/ 1082,
- /*0x0217*/ 176,
- /*0x16e72*/ 1347,
- /*0x2c54*/ 885,
- -1,
- /*0x10cd4*/ 1266,
- /*0x021d*/ 179,
- -1,
- /*0xa681*/ 1021,
- /*0x2c36*/ 855,
- /*0x10d4*/ 482,
- /*0x056a*/ 449,
- -1,
- /*0x00ea*/ 35,
- /*0x1e92b*/ 1370,
- -1,
- /*0x13b4*/ 544,
- /*0x0434*/ 296,
- -1,
- /*0x2c30*/ 849,
- /*0x10434*/ 1147,
- -1, -1, -1,
- /*0x2c52*/ 883,
- -1,
- /*0x10cd2*/ 1264,
- -1,
- /*0x2179*/ 815,
- /*0xa685*/ 1023,
- /*0xa787*/ 1079,
- /*0x10d2*/ 480,
- /*0x2d03*/ 961,
- -1,
- /*0x0570*/ 455,
- /*0x03b4*/ 249,
- /*0x00f0*/ 41,
- -1, -1,
- /*0x13cc*/ 568,
- /*0x044c*/ 320,
- /*0x04cc*/ 389,
- /*0x2d0f*/ 973,
- /*0x1044c*/ 1171,
- /*0x1f62*/ 778,
- /*0x049f*/ 367,
- /*0x0195*/ 123,
- /*0x0256*/ 204,
- -1,
- /*0x1e1f*/ 628,
- -1,
- /*0x011f*/ 71,
- /*0x2c9f*/ 920,
- -1,
- /*0x16e79*/ 1354,
- /*0x025c*/ 208,
- /*0xa797*/ 1084,
- /*0x118c6*/ 1303,
- /*0x03cc*/ 272,
- /*0x1f78*/ 792,
- -1,
- /*0xa79d*/ 1087,
- -1, -1, -1, -1, -1,
- /*0x10f4*/ 514,
- -1, -1,
- /*0x01c6*/ 138,
- /*0x0576*/ 461,
- -1,
- /*0x00f6*/ 47,
- -1, -1,
- /*0x13be*/ 554,
- /*0x043e*/ 306,
- -1,
- /*0x2d21*/ 991,
- /*0x1043e*/ 1157,
- -1, -1,
- /*0x023c*/ 190,
- /*0x013e*/ 85,
- /*0x0564*/ 443,
- /*0x048d*/ 358,
- /*0x00e4*/ 29,
- -1, -1,
- /*0x1e0d*/ 619,
- /*0x1e8d*/ 683,
- /*0x010d*/ 62,
- /*0x2c8d*/ 911,
- /*0x0515*/ 426,
- /*0x03be*/ 259,
- -1,
- /*0x1f7c*/ 796,
- /*0x13ba*/ 550,
- /*0x043a*/ 302,
- -1, -1,
- /*0x1043a*/ 1153,
- -1,
- /*0x217f*/ 821,
- -1,
- /*0x013a*/ 83,
- -1, -1, -1,
- /*0x13b8*/ 548,
- /*0x0438*/ 300,
- /*0x2177*/ 813,
- /*0x118c4*/ 1301,
- /*0x10438*/ 1151,
- /*0x2d19*/ 983,
- -1,
- /*0x03ba*/ 255,
- -1, -1, -1,
- /*0x0254*/ 203,
- -1, -1, -1, -1, -1, -1,
- /*0x2c34*/ 853,
- /*0x03b8*/ 253,
- /*0x16e7f*/ 1360,
- -1, -1,
- /*0x0513*/ 425,
- -1, -1, -1, -1,
- /*0x16e77*/ 1352,
- -1,
- /*0x1f36*/ 764,
- -1,
- /*0x0252*/ 201,
- -1, -1, -1, -1,
- /*0x16e6c*/ 1341,
- -1,
- /*0x00e0*/ 25,
- /*0x1f30*/ 758,
- /*0x2c4c*/ 877,
- -1,
- /*0x10ccc*/ 1258,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1,
- /*0x0507*/ 419,
- /*0x16e68*/ 1337,
- -1, -1, -1,
- /*0xa7ca*/ 1103,
- -1, -1, -1, -1, -1,
- /*0x118d6*/ 1319,
- -1,
- /*0x2170*/ 806,
- -1, -1,
- /*0x16e6a*/ 1339,
- -1,
- /*0x10597*/ 1211,
- /*0x118dc*/ 1325,
- /*0x1fd0*/ 800,
- -1,
- /*0x118da*/ 1323,
- /*0x1059d*/ 1217,
- /*0x01d6*/ 145,
- /*0x2c3e*/ 863,
- /*0x0517*/ 427,
- -1,
- /*0x1f74*/ 788,
- -1, -1,
- /*0x051d*/ 430,
- /*0x01dc*/ 148,
- -1, -1,
- /*0x01da*/ 147,
- -1,
- /*0xff47*/ 1115,
- -1,
- /*0x16e70*/ 1345,
- -1, -1, -1, -1,
- /*0x0287*/ 227,
- -1, -1,
- /*0x2c3a*/ 859,
- -1, -1,
- /*0x2176*/ 812,
- -1, -1, -1, -1, -1,
- /*0x0562*/ 441,
- -1,
- /*0x00e2*/ 27,
- /*0x2c38*/ 857,
- -1, -1, -1, -1, -1, -1,
- /*0x2d09*/ 967,
- -1, -1,
- /*0x118d8*/ 1321,
- -1,
- /*0x0578*/ 463,
- -1,
- /*0x00f8*/ 48,
- -1,
- /*0x029d*/ 234,
- /*0x16e76*/ 1351,
- /*0x118ca*/ 1307,
- -1,
- /*0xff45*/ 1113,
- -1, -1,
- /*0x01d8*/ 146,
- -1, -1,
- /*0x118d4*/ 1317,
- -1, -1, -1, -1,
- /*0x16e64*/ 1333,
- -1, -1, -1, -1, -1,
- /*0x1f34*/ 762,
- -1,
- /*0x01d4*/ 144,
- -1,
- /*0x105bc*/ 1245,
- -1, -1, -1,
- /*0x01b6*/ 134,
- -1,
- /*0x118d2*/ 1315,
- -1, -1,
- /*0x057c*/ 467,
- /*0x021f*/ 180,
- /*0x00fc*/ 52,
- -1, -1,
- /*0x01b0*/ 132,
- -1, -1, -1, -1,
- /*0x01d2*/ 143,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1,
- /*0x1e93c*/ 1387,
- -1, -1, -1, -1, -1, -1,
- /*0x105b6*/ 1240,
- -1, -1, -1, -1,
- /*0xa683*/ 1022,
- -1,
- /*0x020d*/ 171,
- /*0x16e60*/ 1329,
- -1,
- /*0x105b0*/ 1235,
- -1, -1, -1, -1,
- /*0xa68f*/ 1028,
- -1, -1, -1, -1, -1,
- /*0xa79f*/ 1088,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1,
- /*0x1e936*/ 1381,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1,
- /*0x1e930*/ 1375,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1,
- /*0x0574*/ 459,
- -1,
- /*0x00f4*/ 45,
- -1, -1, -1, -1, -1, -1,
- -1,
- /*0x2178*/ 814,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1,
- /*0x01b4*/ 133,
- /*0x16e62*/ 1331,
- -1, -1, -1, -1, -1, -1,
- -1,
- /*0xa699*/ 1033,
- /*0x118cc*/ 1309,
- -1, -1,
- /*0x2d15*/ 979,
- -1, -1,
- /*0x16e78*/ 1353,
- -1, -1, -1, -1, -1, -1,
- /*0x01cc*/ 140,
- -1, -1, -1, -1,
- /*0x217c*/ 818,
- -1, -1,
- /*0x1fe0*/ 802,
- -1, -1, -1, -1, -1, -1,
- -1, -1,
- /*0x105b4*/ 1238,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1,
- /*0x2d13*/ 977,
- -1,
- /*0x16e7c*/ 1357,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- /*0x1059f*/ 1219,
- -1, -1, -1, -1, -1, -1,
- -1,
- /*0x051f*/ 431,
- -1,
- /*0x1e934*/ 1379,
- -1, -1, -1, -1,
- /*0x2d07*/ 965,
- -1,
- /*0xff50*/ 1124,
- -1, -1, -1, -1, -1, -1,
- -1,
- /*0xff42*/ 1110,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1,
- /*0x2d17*/ 981,
- -1, -1, -1, -1,
- /*0x2d1d*/ 987,
- -1, -1,
- /*0x050d*/ 422,
- -1, -1, -1, -1, -1,
- /*0x2174*/ 810,
- /*0xa689*/ 1025,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1,
- /*0x105b8*/ 1242,
- -1, -1,
- /*0x1e93e*/ 1389,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1,
- /*0x16e74*/ 1349,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1,
- /*0x1e93a*/ 1385,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1,
- /*0x1e938*/ 1383,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1,
- /*0x1fb0*/ 798,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1,
- /*0xff48*/ 1116,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1,
- /*0xff46*/ 1114,
- -1, -1, -1,
- /*0xa695*/ 1031,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1,
- /*0xa693*/ 1030,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- /*0xff44*/ 1112,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1,
- /*0xa687*/ 1024,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1,
- /*0x2d1f*/ 989,
- -1, -1, -1, -1, -1, -1,
- -1,
- /*0xa697*/ 1032,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1,
- /*0xff56*/ 1130,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1,
- /*0xff5a*/ 1134,
- -1, -1, -1,
- /*0x2d0d*/ 971,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- /*0xff58*/ 1132,
- -1, -1, -1, -1, -1, -1,
- -1,
- /*0xff4a*/ 1118,
- -1, -1, -1, -1, -1, -1,
- -1,
- /*0xff54*/ 1128,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1,
- /*0xff52*/ 1126,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- /*0xff4c*/ 1120,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- /*0xa68d*/ 1027
- };
-
- if (code <= MAX_CODE_VALUE && code >= MIN_CODE_VALUE)
- {
- register unsigned int key = onigenc_unicode_CaseUnfold_11_hash(code);
-
- if (key <= MAX_HASH_VALUE)
- {
- register short s = wordlist[key];
-
- if (s >= 0 && code1_equal(code, CaseUnfold_11_Table[s].from))
- return &CaseUnfold_11_Table[s].to;
- }
- }
- return 0;
-}
-
-static const CaseUnfold_12_Type CaseUnfold_12_Table[] = {
-#define CaseUnfold_12 (*(CaseUnfold_12_Type (*)[58])(CaseUnfold_12_Table+0))
- {{0x0061, 0x02be}, {1, {0x1e9a}}},
- {{0x0066, 0x0066}, {1, {0xfb00}}},
- {{0x0066, 0x0069}, {1, {0xfb01}}},
- {{0x0066, 0x006c}, {1, {0xfb02}}},
- {{0x0068, 0x0331}, {1, {0x1e96}}},
- {{0x006a, 0x030c}, {1, {0x01f0}}},
- {{0x0073, 0x0073}, {2, {0x00df, 0x1e9e}}},
- {{0x0073, 0x0074}, {2, {0xfb05, 0xfb06}}},
- {{0x0074, 0x0308}, {1, {0x1e97}}},
- {{0x0077, 0x030a}, {1, {0x1e98}}},
- {{0x0079, 0x030a}, {1, {0x1e99}}},
- {{0x02bc, 0x006e}, {1, {0x0149}}},
- {{0x03ac, 0x03b9}, {1, {0x1fb4}}},
- {{0x03ae, 0x03b9}, {1, {0x1fc4}}},
- {{0x03b1, 0x0342}, {1, {0x1fb6}}},
- {{0x03b1, 0x03b9}, {2, {0x1fb3, 0x1fbc}}},
- {{0x03b7, 0x0342}, {1, {0x1fc6}}},
- {{0x03b7, 0x03b9}, {2, {0x1fc3, 0x1fcc}}},
- {{0x03b9, 0x0342}, {1, {0x1fd6}}},
- {{0x03c1, 0x0313}, {1, {0x1fe4}}},
- {{0x03c5, 0x0313}, {1, {0x1f50}}},
- {{0x03c5, 0x0342}, {1, {0x1fe6}}},
- {{0x03c9, 0x0342}, {1, {0x1ff6}}},
- {{0x03c9, 0x03b9}, {2, {0x1ff3, 0x1ffc}}},
- {{0x03ce, 0x03b9}, {1, {0x1ff4}}},
- {{0x0565, 0x0582}, {1, {0x0587}}},
- {{0x0574, 0x0565}, {1, {0xfb14}}},
- {{0x0574, 0x056b}, {1, {0xfb15}}},
- {{0x0574, 0x056d}, {1, {0xfb17}}},
- {{0x0574, 0x0576}, {1, {0xfb13}}},
- {{0x057e, 0x0576}, {1, {0xfb16}}},
- {{0x1f00, 0x03b9}, {2, {0x1f80, 0x1f88}}},
- {{0x1f01, 0x03b9}, {2, {0x1f81, 0x1f89}}},
- {{0x1f02, 0x03b9}, {2, {0x1f82, 0x1f8a}}},
- {{0x1f03, 0x03b9}, {2, {0x1f83, 0x1f8b}}},
- {{0x1f04, 0x03b9}, {2, {0x1f84, 0x1f8c}}},
- {{0x1f05, 0x03b9}, {2, {0x1f85, 0x1f8d}}},
- {{0x1f06, 0x03b9}, {2, {0x1f86, 0x1f8e}}},
- {{0x1f07, 0x03b9}, {2, {0x1f87, 0x1f8f}}},
- {{0x1f20, 0x03b9}, {2, {0x1f90, 0x1f98}}},
- {{0x1f21, 0x03b9}, {2, {0x1f91, 0x1f99}}},
- {{0x1f22, 0x03b9}, {2, {0x1f92, 0x1f9a}}},
- {{0x1f23, 0x03b9}, {2, {0x1f93, 0x1f9b}}},
- {{0x1f24, 0x03b9}, {2, {0x1f94, 0x1f9c}}},
- {{0x1f25, 0x03b9}, {2, {0x1f95, 0x1f9d}}},
- {{0x1f26, 0x03b9}, {2, {0x1f96, 0x1f9e}}},
- {{0x1f27, 0x03b9}, {2, {0x1f97, 0x1f9f}}},
- {{0x1f60, 0x03b9}, {2, {0x1fa0, 0x1fa8}}},
- {{0x1f61, 0x03b9}, {2, {0x1fa1, 0x1fa9}}},
- {{0x1f62, 0x03b9}, {2, {0x1fa2, 0x1faa}}},
- {{0x1f63, 0x03b9}, {2, {0x1fa3, 0x1fab}}},
- {{0x1f64, 0x03b9}, {2, {0x1fa4, 0x1fac}}},
- {{0x1f65, 0x03b9}, {2, {0x1fa5, 0x1fad}}},
- {{0x1f66, 0x03b9}, {2, {0x1fa6, 0x1fae}}},
- {{0x1f67, 0x03b9}, {2, {0x1fa7, 0x1faf}}},
- {{0x1f70, 0x03b9}, {1, {0x1fb2}}},
- {{0x1f74, 0x03b9}, {1, {0x1fc2}}},
- {{0x1f7c, 0x03b9}, {1, {0x1ff2}}},
-#define CaseUnfold_12_Locale (*(CaseUnfold_12_Type (*)[1])(CaseUnfold_12_Table+58))
- {{0x0069, 0x0307}, {1, {0x0130}}},
-};
-
-/* ANSI-C code produced by gperf version 3.1 */
-/* Command-line: gperf -7 -k1,2,3,4,5,6 -F,-1 -c -j1 -i1 -t -T -E -C -H onigenc_unicode_CaseUnfold_12_hash -N onigenc_unicode_CaseUnfold_12_lookup -n */
-
-/* maximum key range = 71, duplicates = 0 */
-
-#ifdef __GNUC__
-__inline
-#else
-#ifdef __cplusplus
-inline
-#endif
-#endif
-/*ARGSUSED*/
-static unsigned int
-onigenc_unicode_CaseUnfold_12_hash(const OnigCodePoint *codes)
-{
- static const unsigned char asso_values[] =
- {
- 3, 58, 54, 57, 56, 16, 8, 2, 43, 82,
- 3, 1, 23, 82, 82, 82, 82, 82, 82, 4,
- 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
- 82, 82, 52, 51, 50, 49, 48, 47, 46, 45,
- 82, 82, 82, 82, 43, 82, 42, 82, 82, 13,
- 82, 82, 82, 82, 82, 11, 82, 1, 82, 82,
- 14, 82, 1, 82, 82, 31, 3, 82, 82, 30,
- 82, 82, 82, 10, 82, 82, 82, 82, 37, 82,
- 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
- 82, 82, 82, 82, 82, 82, 37, 15, 36, 35,
- 34, 17, 1, 33, 12, 4, 23, 23, 26, 21,
- 13, 82, 27, 82, 82, 2, 5, 82, 11, 16,
- 82, 15, 82, 82, 23, 82, 8, 82
- };
- return asso_values[bits_at(codes, 5)] + asso_values[bits_at(codes, 4)] + asso_values[bits_at(codes, 3)] + asso_values[bits_at(codes, 2)] + asso_values[bits_at(codes, 1)] + asso_values[bits_at(codes, 0)];
-}
-
-static const CodePointList2 *
-onigenc_unicode_CaseUnfold_12_lookup(const OnigCodePoint *codes)
-{
- enum
- {
- MIN_CODE_VALUE = 0x61,
- MAX_CODE_VALUE = 0x1f7c,
- TOTAL_KEYWORDS = 59,
- MIN_WORD_LENGTH = 6,
- MAX_WORD_LENGTH = 6,
- MIN_HASH_VALUE = 11,
- MAX_HASH_VALUE = 81
- };
-
- static const short wordlist[] =
- {
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1,
- /*0x1f66,0x03b9*/ 53,
- /*0x1f07,0x03b9*/ 38,
- /*0x1f00,0x03b9*/ 31,
- /*0x0066,0x0066*/ 1,
- /*0x1f74,0x03b9*/ 56,
- /*0x0073,0x0073*/ 6,
- /*0x0066,0x0069*/ 2,
- /*0x1f06,0x03b9*/ 37,
- /*0x0073,0x0074*/ 7,
- /*0x03b9,0x0342*/ 18,
- /*0x03c9,0x03b9*/ 23,
- /*0x03b7,0x03b9*/ 17,
- /*0x0069,0x0307*/ 58,
- /*0x03b1,0x03b9*/ 15,
- /*0x1f61,0x03b9*/ 48,
- /*0x1f05,0x03b9*/ 36,
- /*0x1f65,0x03b9*/ 52,
- /*0x0574,0x0576*/ 29,
- /*0x03c9,0x0342*/ 22,
- /*0x03b7,0x0342*/ 16,
- /*0x057e,0x0576*/ 30,
- /*0x03b1,0x0342*/ 14,
- /*0x1f7c,0x03b9*/ 57,
- /*0x0574,0x0565*/ 26,
- /*0x0079,0x030a*/ 10,
- /*0x0077,0x030a*/ 9,
- /*0x1f70,0x03b9*/ 55,
- /*0x0574,0x056d*/ 28,
- /*0x0066,0x006c*/ 3,
- /*0x0574,0x056b*/ 27,
- /*0x0061,0x02be*/ 0,
- /*0x0068,0x0331*/ 4,
- /*0x1f67,0x03b9*/ 54,
- /*0x1f64,0x03b9*/ 51,
- /*0x1f63,0x03b9*/ 50,
- /*0x1f62,0x03b9*/ 49,
- /*0x1f60,0x03b9*/ 47,
- /*0x03ce,0x03b9*/ 24,
- /*0x03c5,0x0342*/ 21,
- /*0x03c5,0x0313*/ 20,
- /*0x03c1,0x0313*/ 19,
- /*0x02bc,0x006e*/ 11,
- /*0x03ae,0x03b9*/ 13,
- /*0x03ac,0x03b9*/ 12,
- /*0x1f27,0x03b9*/ 46,
- /*0x1f26,0x03b9*/ 45,
- /*0x1f25,0x03b9*/ 44,
- /*0x1f24,0x03b9*/ 43,
- /*0x1f23,0x03b9*/ 42,
- /*0x1f22,0x03b9*/ 41,
- /*0x1f21,0x03b9*/ 40,
- /*0x1f20,0x03b9*/ 39,
- /*0x006a,0x030c*/ 5,
- /*0x1f02,0x03b9*/ 33,
- /*0x0074,0x0308*/ 8,
- /*0x1f04,0x03b9*/ 35,
- /*0x1f03,0x03b9*/ 34,
- /*0x1f01,0x03b9*/ 32,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- /*0x0565,0x0582*/ 25
- };
-
- if (codes[0] <= MAX_CODE_VALUE && codes[0] >= MIN_CODE_VALUE &&
- codes[1] <= MAX_CODE_VALUE && codes[1] >= MIN_CODE_VALUE)
- {
- register unsigned int key = onigenc_unicode_CaseUnfold_12_hash(codes);
-
- if (key <= MAX_HASH_VALUE)
- {
- register short s = wordlist[key];
-
- if (s >= 0 && code2_equal(codes, CaseUnfold_12_Table[s].from))
- return &CaseUnfold_12_Table[s].to;
- }
- }
- return 0;
-}
-
-static const CaseUnfold_13_Type CaseUnfold_13_Table[] = {
-#define CaseUnfold_13 (*(CaseUnfold_13_Type (*)[14])(CaseUnfold_13_Table+0))
- {{0x0066, 0x0066, 0x0069}, {1, {0xfb03}}},
- {{0x0066, 0x0066, 0x006c}, {1, {0xfb04}}},
- {{0x03b1, 0x0342, 0x03b9}, {1, {0x1fb7}}},
- {{0x03b7, 0x0342, 0x03b9}, {1, {0x1fc7}}},
- {{0x03b9, 0x0308, 0x0300}, {1, {0x1fd2}}},
- {{0x03b9, 0x0308, 0x0301}, {2, {0x0390, 0x1fd3}}},
- {{0x03b9, 0x0308, 0x0342}, {1, {0x1fd7}}},
- {{0x03c5, 0x0308, 0x0300}, {1, {0x1fe2}}},
- {{0x03c5, 0x0308, 0x0301}, {2, {0x03b0, 0x1fe3}}},
- {{0x03c5, 0x0308, 0x0342}, {1, {0x1fe7}}},
- {{0x03c5, 0x0313, 0x0300}, {1, {0x1f52}}},
- {{0x03c5, 0x0313, 0x0301}, {1, {0x1f54}}},
- {{0x03c5, 0x0313, 0x0342}, {1, {0x1f56}}},
- {{0x03c9, 0x0342, 0x03b9}, {1, {0x1ff7}}},
-};
-
-/* ANSI-C code produced by gperf version 3.1 */
-/* Command-line: gperf -7 -k1,2,3,4,5,6,7,8,9 -F,-1 -c -j1 -i1 -t -T -E -C -H onigenc_unicode_CaseUnfold_13_hash -N onigenc_unicode_CaseUnfold_13_lookup -n */
-
-/* maximum key range = 20, duplicates = 0 */
-
-#ifdef __GNUC__
-__inline
-#else
-#ifdef __cplusplus
-inline
-#endif
-#endif
-/*ARGSUSED*/
-static unsigned int
-onigenc_unicode_CaseUnfold_13_hash(const OnigCodePoint *codes)
-{
- static const unsigned char asso_values[] =
- {
- 7, 4, 47, 47, 47, 47, 1, 1, 2, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 1,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 11,
- 47, 47, 47, 47, 47, 10, 47, 2, 47, 47,
- 47, 47, 47, 47, 47, 47, 1, 47, 47, 1,
- 47, 47, 47, 9, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 1, 47, 47, 2, 47, 47, 1, 47,
- 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, 47
- };
- return asso_values[bits_at(codes, 8)] + asso_values[bits_at(codes, 7)] + asso_values[bits_at(codes, 6)] + asso_values[bits_at(codes, 5)] + asso_values[bits_at(codes, 4)] + asso_values[bits_at(codes, 3)] + asso_values[bits_at(codes, 2)] + asso_values[bits_at(codes, 1)] + asso_values[bits_at(codes, 0)];
-}
-
-static const CodePointList2 *
-onigenc_unicode_CaseUnfold_13_lookup(const OnigCodePoint *codes)
-{
- enum
- {
- MIN_CODE_VALUE = 0x66,
- MAX_CODE_VALUE = 0x3c9,
- TOTAL_KEYWORDS = 14,
- MIN_WORD_LENGTH = 9,
- MAX_WORD_LENGTH = 9,
- MIN_HASH_VALUE = 27,
- MAX_HASH_VALUE = 46
- };
-
- static const short wordlist[] =
- {
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1,
- -1, -1, -1,
- /*0x03c5,0x0313,0x0342*/ 12,
- /*0x03c5,0x0308,0x0342*/ 9,
- /*0x03b9,0x0308,0x0342*/ 6,
- /*0x03c5,0x0313,0x0301*/ 11,
- /*0x03c5,0x0308,0x0301*/ 8,
- /*0x03b9,0x0308,0x0301*/ 5,
- /*0x03c5,0x0313,0x0300*/ 10,
- /*0x03c5,0x0308,0x0300*/ 7,
- /*0x03b9,0x0308,0x0300*/ 4,
- /*0x03c9,0x0342,0x03b9*/ 13,
- /*0x03b7,0x0342,0x03b9*/ 3,
- /*0x03b1,0x0342,0x03b9*/ 2,
- -1, -1, -1, -1, -1, -1,
- /*0x0066,0x0066,0x006c*/ 1,
- /*0x0066,0x0066,0x0069*/ 0
- };
-
- if (codes[0] <= MAX_CODE_VALUE && codes[0] >= MIN_CODE_VALUE &&
- codes[1] <= MAX_CODE_VALUE && codes[1] >= MIN_CODE_VALUE &&
- codes[2] <= MAX_CODE_VALUE && codes[2] >= MIN_CODE_VALUE)
- {
- register unsigned int key = onigenc_unicode_CaseUnfold_13_hash(codes);
-
- if (key <= MAX_HASH_VALUE)
- {
- register short s = wordlist[key];
-
- if (s >= 0 && code3_equal(codes, CaseUnfold_13_Table[s].from))
- return &CaseUnfold_13_Table[s].to;
- }
- }
- return 0;
-}
-
-static const OnigCodePoint CaseMappingSpecials[] = {
- L(1)|0x039C,
- L(2)|0x0053, 0x0073, L(2)|0x0053, 0x0053,
- L(2)|0x02BC, 0x004E,
- L(1)|0x0053,
- L(1)|0x01C5,
- L(2)|0x0064, 0x017D, L(1)|0x01C4,
- L(1)|0x01C8,
- L(2)|0x006C, 0x004A, L(1)|0x01C7,
- L(1)|0x01CB,
- L(2)|0x006E, 0x004A, L(1)|0x01CA,
- L(2)|0x004A, 0x030C,
- L(1)|0x01F2,
- L(2)|0x0064, 0x005A, L(1)|0x01F1,
- L(1)|0x0399,
- L(3)|0x0399, 0x0308, 0x0301,
- L(3)|0x03A5, 0x0308, 0x0301,
- L(1)|0x03A3,
- L(1)|0x0392,
- L(1)|0x0398,
- L(1)|0x03A6,
- L(1)|0x03A0,
- L(1)|0x039A,
- L(1)|0x03A1,
- L(1)|0x0395,
- L(2)|0x0535, 0x0582, L(2)|0x0535, 0x0552,
- L(1)|0x0412,
- L(1)|0x0414,
- L(1)|0x041E,
- L(1)|0x0421,
- L(1)|0x0422,
- L(1)|0x0422,
- L(1)|0x042A,
- L(1)|0x0462,
- L(1)|0xA64A,
- L(2)|0x0048, 0x0331,
- L(2)|0x0054, 0x0308,
- L(2)|0x0057, 0x030A,
- L(2)|0x0059, 0x030A,
- L(2)|0x0041, 0x02BE,
- L(1)|0x1E60,
- L(1)|0x00DF,
- L(2)|0x03A5, 0x0313,
- L(3)|0x03A5, 0x0313, 0x0300,
- L(3)|0x03A5, 0x0313, 0x0301,
- L(3)|0x03A5, 0x0313, 0x0342,
- L(1)|0x1F88, L(2)|0x1F08, 0x0399,
- L(1)|0x1F89, L(2)|0x1F09, 0x0399,
- L(1)|0x1F8A, L(2)|0x1F0A, 0x0399,
- L(1)|0x1F8B, L(2)|0x1F0B, 0x0399,
- L(1)|0x1F8C, L(2)|0x1F0C, 0x0399,
- L(1)|0x1F8D, L(2)|0x1F0D, 0x0399,
- L(1)|0x1F8E, L(2)|0x1F0E, 0x0399,
- L(1)|0x1F8F, L(2)|0x1F0F, 0x0399,
- L(2)|0x1F00, 0x0399, L(1)|0x1F80, L(2)|0x1F08, 0x0399,
- L(2)|0x1F01, 0x0399, L(1)|0x1F81, L(2)|0x1F09, 0x0399,
- L(2)|0x1F02, 0x0399, L(1)|0x1F82, L(2)|0x1F0A, 0x0399,
- L(2)|0x1F03, 0x0399, L(1)|0x1F83, L(2)|0x1F0B, 0x0399,
- L(2)|0x1F04, 0x0399, L(1)|0x1F84, L(2)|0x1F0C, 0x0399,
- L(2)|0x1F05, 0x0399, L(1)|0x1F85, L(2)|0x1F0D, 0x0399,
- L(2)|0x1F06, 0x0399, L(1)|0x1F86, L(2)|0x1F0E, 0x0399,
- L(2)|0x1F07, 0x0399, L(1)|0x1F87, L(2)|0x1F0F, 0x0399,
- L(1)|0x1F98, L(2)|0x1F28, 0x0399,
- L(1)|0x1F99, L(2)|0x1F29, 0x0399,
- L(1)|0x1F9A, L(2)|0x1F2A, 0x0399,
- L(1)|0x1F9B, L(2)|0x1F2B, 0x0399,
- L(1)|0x1F9C, L(2)|0x1F2C, 0x0399,
- L(1)|0x1F9D, L(2)|0x1F2D, 0x0399,
- L(1)|0x1F9E, L(2)|0x1F2E, 0x0399,
- L(1)|0x1F9F, L(2)|0x1F2F, 0x0399,
- L(2)|0x1F20, 0x0399, L(1)|0x1F90, L(2)|0x1F28, 0x0399,
- L(2)|0x1F21, 0x0399, L(1)|0x1F91, L(2)|0x1F29, 0x0399,
- L(2)|0x1F22, 0x0399, L(1)|0x1F92, L(2)|0x1F2A, 0x0399,
- L(2)|0x1F23, 0x0399, L(1)|0x1F93, L(2)|0x1F2B, 0x0399,
- L(2)|0x1F24, 0x0399, L(1)|0x1F94, L(2)|0x1F2C, 0x0399,
- L(2)|0x1F25, 0x0399, L(1)|0x1F95, L(2)|0x1F2D, 0x0399,
- L(2)|0x1F26, 0x0399, L(1)|0x1F96, L(2)|0x1F2E, 0x0399,
- L(2)|0x1F27, 0x0399, L(1)|0x1F97, L(2)|0x1F2F, 0x0399,
- L(1)|0x1FA8, L(2)|0x1F68, 0x0399,
- L(1)|0x1FA9, L(2)|0x1F69, 0x0399,
- L(1)|0x1FAA, L(2)|0x1F6A, 0x0399,
- L(1)|0x1FAB, L(2)|0x1F6B, 0x0399,
- L(1)|0x1FAC, L(2)|0x1F6C, 0x0399,
- L(1)|0x1FAD, L(2)|0x1F6D, 0x0399,
- L(1)|0x1FAE, L(2)|0x1F6E, 0x0399,
- L(1)|0x1FAF, L(2)|0x1F6F, 0x0399,
- L(2)|0x1F60, 0x0399, L(1)|0x1FA0, L(2)|0x1F68, 0x0399,
- L(2)|0x1F61, 0x0399, L(1)|0x1FA1, L(2)|0x1F69, 0x0399,
- L(2)|0x1F62, 0x0399, L(1)|0x1FA2, L(2)|0x1F6A, 0x0399,
- L(2)|0x1F63, 0x0399, L(1)|0x1FA3, L(2)|0x1F6B, 0x0399,
- L(2)|0x1F64, 0x0399, L(1)|0x1FA4, L(2)|0x1F6C, 0x0399,
- L(2)|0x1F65, 0x0399, L(1)|0x1FA5, L(2)|0x1F6D, 0x0399,
- L(2)|0x1F66, 0x0399, L(1)|0x1FA6, L(2)|0x1F6E, 0x0399,
- L(2)|0x1F67, 0x0399, L(1)|0x1FA7, L(2)|0x1F6F, 0x0399,
- L(2)|0x1FBA, 0x0345, L(2)|0x1FBA, 0x0399,
- L(1)|0x1FBC, L(2)|0x0391, 0x0399,
- L(2)|0x0386, 0x0345, L(2)|0x0386, 0x0399,
- L(2)|0x0391, 0x0342,
- L(3)|0x0391, 0x0342, 0x0345, L(3)|0x0391, 0x0342, 0x0399,
- L(2)|0x03B1, 0x0399, L(1)|0x1FB3, L(2)|0x0391, 0x0399,
- L(1)|0x0399,
- L(2)|0x1FCA, 0x0345, L(2)|0x1FCA, 0x0399,
- L(1)|0x1FCC, L(2)|0x0397, 0x0399,
- L(2)|0x0389, 0x0345, L(2)|0x0389, 0x0399,
- L(2)|0x0397, 0x0342,
- L(3)|0x0397, 0x0342, 0x0345, L(3)|0x0397, 0x0342, 0x0399,
- L(2)|0x03B7, 0x0399, L(1)|0x1FC3, L(2)|0x0397, 0x0399,
- L(3)|0x0399, 0x0308, 0x0300,
- L(3)|0x0399, 0x0308, 0x0301,
- L(2)|0x0399, 0x0342,
- L(3)|0x0399, 0x0308, 0x0342,
- L(3)|0x03A5, 0x0308, 0x0300,
- L(3)|0x03A5, 0x0308, 0x0301,
- L(2)|0x03A1, 0x0313,
- L(2)|0x03A5, 0x0342,
- L(3)|0x03A5, 0x0308, 0x0342,
- L(2)|0x1FFA, 0x0345, L(2)|0x1FFA, 0x0399,
- L(1)|0x1FFC, L(2)|0x03A9, 0x0399,
- L(2)|0x038F, 0x0345, L(2)|0x038F, 0x0399,
- L(2)|0x03A9, 0x0342,
- L(3)|0x03A9, 0x0342, 0x0345, L(3)|0x03A9, 0x0342, 0x0399,
- L(2)|0x03C9, 0x0399, L(1)|0x1FF3, L(2)|0x03A9, 0x0399,
- L(2)|0x0046, 0x0066, L(2)|0x0046, 0x0046,
- L(2)|0x0046, 0x0069, L(2)|0x0046, 0x0049,
- L(2)|0x0046, 0x006C, L(2)|0x0046, 0x004C,
- L(3)|0x0046, 0x0066, 0x0069, L(3)|0x0046, 0x0046, 0x0049,
- L(3)|0x0046, 0x0066, 0x006C, L(3)|0x0046, 0x0046, 0x004C,
- L(2)|0x0053, 0x0074, L(2)|0x0053, 0x0054,
- L(2)|0x0053, 0x0074, L(2)|0x0053, 0x0054,
- L(2)|0x0544, 0x0576, L(2)|0x0544, 0x0546,
- L(2)|0x0544, 0x0565, L(2)|0x0544, 0x0535,
- L(2)|0x0544, 0x056B, L(2)|0x0544, 0x053B,
- L(2)|0x054E, 0x0576, L(2)|0x054E, 0x0546,
- L(2)|0x0544, 0x056D, L(2)|0x0544, 0x053D,
-};
diff --git a/enc/unicode/15.0.0/name2ctype.h b/enc/unicode/15.0.0/name2ctype.h
deleted file mode 100644
index 6bbbb3512f..0000000000
--- a/enc/unicode/15.0.0/name2ctype.h
+++ /dev/null
@@ -1,45690 +0,0 @@
-/* ANSI-C code produced by gperf version 3.1 */
-/* Command-line: gperf -7 -c -j1 -i1 -t -C -P -T -H uniname2ctype_hash -Q uniname2ctype_pool -N uniname2ctype_p */
-#ifndef USE_UNICODE_PROPERTIES
-/* Computed positions: -k'1,3' */
-#else /* USE_UNICODE_PROPERTIES */
-/* Computed positions: -k'1-3,5-6,12,16,$' */
-#endif /* USE_UNICODE_PROPERTIES */
-
-#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
- && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
- && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
- && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
- && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
- && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
- && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
- && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
- && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
- && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
- && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
- && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
- && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
- && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
- && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
- && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
- && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
- && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
- && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
- && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
- && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
- && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
- && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
-/* The character set is not based on ISO-646. */
-#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gperf@gnu.org>."
-#endif
-
-
-
-/* 'NEWLINE': [[:NEWLINE:]] */
-static const OnigCodePoint CR_NEWLINE[] = {
- 1,
- 0x000a, 0x000a,
-}; /* CR_NEWLINE */
-
-/* 'Alpha': [[:Alpha:]] */
-static const OnigCodePoint CR_Alpha[] = {
- 732,
- 0x0041, 0x005a,
- 0x0061, 0x007a,
- 0x00aa, 0x00aa,
- 0x00b5, 0x00b5,
- 0x00ba, 0x00ba,
- 0x00c0, 0x00d6,
- 0x00d8, 0x00f6,
- 0x00f8, 0x02c1,
- 0x02c6, 0x02d1,
- 0x02e0, 0x02e4,
- 0x02ec, 0x02ec,
- 0x02ee, 0x02ee,
- 0x0345, 0x0345,
- 0x0370, 0x0374,
- 0x0376, 0x0377,
- 0x037a, 0x037d,
- 0x037f, 0x037f,
- 0x0386, 0x0386,
- 0x0388, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03f5,
- 0x03f7, 0x0481,
- 0x048a, 0x052f,
- 0x0531, 0x0556,
- 0x0559, 0x0559,
- 0x0560, 0x0588,
- 0x05b0, 0x05bd,
- 0x05bf, 0x05bf,
- 0x05c1, 0x05c2,
- 0x05c4, 0x05c5,
- 0x05c7, 0x05c7,
- 0x05d0, 0x05ea,
- 0x05ef, 0x05f2,
- 0x0610, 0x061a,
- 0x0620, 0x0657,
- 0x0659, 0x065f,
- 0x066e, 0x06d3,
- 0x06d5, 0x06dc,
- 0x06e1, 0x06e8,
- 0x06ed, 0x06ef,
- 0x06fa, 0x06fc,
- 0x06ff, 0x06ff,
- 0x0710, 0x073f,
- 0x074d, 0x07b1,
- 0x07ca, 0x07ea,
- 0x07f4, 0x07f5,
- 0x07fa, 0x07fa,
- 0x0800, 0x0817,
- 0x081a, 0x082c,
- 0x0840, 0x0858,
- 0x0860, 0x086a,
- 0x0870, 0x0887,
- 0x0889, 0x088e,
- 0x08a0, 0x08c9,
- 0x08d4, 0x08df,
- 0x08e3, 0x08e9,
- 0x08f0, 0x093b,
- 0x093d, 0x094c,
- 0x094e, 0x0950,
- 0x0955, 0x0963,
- 0x0971, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bd, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09cc,
- 0x09ce, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09f0, 0x09f1,
- 0x09fc, 0x09fc,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4c,
- 0x0a51, 0x0a51,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a70, 0x0a75,
- 0x0a81, 0x0a83,
- 0x0a85, 0x0a8d,
- 0x0a8f, 0x0a91,
- 0x0a93, 0x0aa8,
- 0x0aaa, 0x0ab0,
- 0x0ab2, 0x0ab3,
- 0x0ab5, 0x0ab9,
- 0x0abd, 0x0ac5,
- 0x0ac7, 0x0ac9,
- 0x0acb, 0x0acc,
- 0x0ad0, 0x0ad0,
- 0x0ae0, 0x0ae3,
- 0x0af9, 0x0afc,
- 0x0b01, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b35, 0x0b39,
- 0x0b3d, 0x0b44,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4c,
- 0x0b56, 0x0b57,
- 0x0b5c, 0x0b5d,
- 0x0b5f, 0x0b63,
- 0x0b71, 0x0b71,
- 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, 0x0bcc,
- 0x0bd0, 0x0bd0,
- 0x0bd7, 0x0bd7,
- 0x0c00, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c39,
- 0x0c3d, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4c,
- 0x0c55, 0x0c56,
- 0x0c58, 0x0c5a,
- 0x0c5d, 0x0c5d,
- 0x0c60, 0x0c63,
- 0x0c80, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbd, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccc,
- 0x0cd5, 0x0cd6,
- 0x0cdd, 0x0cde,
- 0x0ce0, 0x0ce3,
- 0x0cf1, 0x0cf3,
- 0x0d00, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d3a,
- 0x0d3d, 0x0d44,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4c,
- 0x0d4e, 0x0d4e,
- 0x0d54, 0x0d57,
- 0x0d5f, 0x0d63,
- 0x0d7a, 0x0d7f,
- 0x0d81, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0df2, 0x0df3,
- 0x0e01, 0x0e3a,
- 0x0e40, 0x0e46,
- 0x0e4d, 0x0e4d,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e86, 0x0e8a,
- 0x0e8c, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ecd, 0x0ecd,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f00,
- 0x0f40, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f71, 0x0f83,
- 0x0f88, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x1000, 0x1036,
- 0x1038, 0x1038,
- 0x103b, 0x103f,
- 0x1050, 0x108f,
- 0x109a, 0x109d,
- 0x10a0, 0x10c5,
- 0x10c7, 0x10c7,
- 0x10cd, 0x10cd,
- 0x10d0, 0x10fa,
- 0x10fc, 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,
- 0x1380, 0x138f,
- 0x13a0, 0x13f5,
- 0x13f8, 0x13fd,
- 0x1401, 0x166c,
- 0x166f, 0x167f,
- 0x1681, 0x169a,
- 0x16a0, 0x16ea,
- 0x16ee, 0x16f8,
- 0x1700, 0x1713,
- 0x171f, 0x1733,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17b3,
- 0x17b6, 0x17c8,
- 0x17d7, 0x17d7,
- 0x17dc, 0x17dc,
- 0x1820, 0x1878,
- 0x1880, 0x18aa,
- 0x18b0, 0x18f5,
- 0x1900, 0x191e,
- 0x1920, 0x192b,
- 0x1930, 0x1938,
- 0x1950, 0x196d,
- 0x1970, 0x1974,
- 0x1980, 0x19ab,
- 0x19b0, 0x19c9,
- 0x1a00, 0x1a1b,
- 0x1a20, 0x1a5e,
- 0x1a61, 0x1a74,
- 0x1aa7, 0x1aa7,
- 0x1abf, 0x1ac0,
- 0x1acc, 0x1ace,
- 0x1b00, 0x1b33,
- 0x1b35, 0x1b43,
- 0x1b45, 0x1b4c,
- 0x1b80, 0x1ba9,
- 0x1bac, 0x1baf,
- 0x1bba, 0x1be5,
- 0x1be7, 0x1bf1,
- 0x1c00, 0x1c36,
- 0x1c4d, 0x1c4f,
- 0x1c5a, 0x1c7d,
- 0x1c80, 0x1c88,
- 0x1c90, 0x1cba,
- 0x1cbd, 0x1cbf,
- 0x1ce9, 0x1cec,
- 0x1cee, 0x1cf3,
- 0x1cf5, 0x1cf6,
- 0x1cfa, 0x1cfa,
- 0x1d00, 0x1dbf,
- 0x1de7, 0x1df4,
- 0x1e00, 0x1f15,
- 0x1f18, 0x1f1d,
- 0x1f20, 0x1f45,
- 0x1f48, 0x1f4d,
- 0x1f50, 0x1f57,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f7d,
- 0x1f80, 0x1fb4,
- 0x1fb6, 0x1fbc,
- 0x1fbe, 0x1fbe,
- 0x1fc2, 0x1fc4,
- 0x1fc6, 0x1fcc,
- 0x1fd0, 0x1fd3,
- 0x1fd6, 0x1fdb,
- 0x1fe0, 0x1fec,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ffc,
- 0x2071, 0x2071,
- 0x207f, 0x207f,
- 0x2090, 0x209c,
- 0x2102, 0x2102,
- 0x2107, 0x2107,
- 0x210a, 0x2113,
- 0x2115, 0x2115,
- 0x2119, 0x211d,
- 0x2124, 0x2124,
- 0x2126, 0x2126,
- 0x2128, 0x2128,
- 0x212a, 0x212d,
- 0x212f, 0x2139,
- 0x213c, 0x213f,
- 0x2145, 0x2149,
- 0x214e, 0x214e,
- 0x2160, 0x2188,
- 0x24b6, 0x24e9,
- 0x2c00, 0x2ce4,
- 0x2ceb, 0x2cee,
- 0x2cf2, 0x2cf3,
- 0x2d00, 0x2d25,
- 0x2d27, 0x2d27,
- 0x2d2d, 0x2d2d,
- 0x2d30, 0x2d67,
- 0x2d6f, 0x2d6f,
- 0x2d80, 0x2d96,
- 0x2da0, 0x2da6,
- 0x2da8, 0x2dae,
- 0x2db0, 0x2db6,
- 0x2db8, 0x2dbe,
- 0x2dc0, 0x2dc6,
- 0x2dc8, 0x2dce,
- 0x2dd0, 0x2dd6,
- 0x2dd8, 0x2dde,
- 0x2de0, 0x2dff,
- 0x2e2f, 0x2e2f,
- 0x3005, 0x3007,
- 0x3021, 0x3029,
- 0x3031, 0x3035,
- 0x3038, 0x303c,
- 0x3041, 0x3096,
- 0x309d, 0x309f,
- 0x30a1, 0x30fa,
- 0x30fc, 0x30ff,
- 0x3105, 0x312f,
- 0x3131, 0x318e,
- 0x31a0, 0x31bf,
- 0x31f0, 0x31ff,
- 0x3400, 0x4dbf,
- 0x4e00, 0xa48c,
- 0xa4d0, 0xa4fd,
- 0xa500, 0xa60c,
- 0xa610, 0xa61f,
- 0xa62a, 0xa62b,
- 0xa640, 0xa66e,
- 0xa674, 0xa67b,
- 0xa67f, 0xa6ef,
- 0xa717, 0xa71f,
- 0xa722, 0xa788,
- 0xa78b, 0xa7ca,
- 0xa7d0, 0xa7d1,
- 0xa7d3, 0xa7d3,
- 0xa7d5, 0xa7d9,
- 0xa7f2, 0xa805,
- 0xa807, 0xa827,
- 0xa840, 0xa873,
- 0xa880, 0xa8c3,
- 0xa8c5, 0xa8c5,
- 0xa8f2, 0xa8f7,
- 0xa8fb, 0xa8fb,
- 0xa8fd, 0xa8ff,
- 0xa90a, 0xa92a,
- 0xa930, 0xa952,
- 0xa960, 0xa97c,
- 0xa980, 0xa9b2,
- 0xa9b4, 0xa9bf,
- 0xa9cf, 0xa9cf,
- 0xa9e0, 0xa9ef,
- 0xa9fa, 0xa9fe,
- 0xaa00, 0xaa36,
- 0xaa40, 0xaa4d,
- 0xaa60, 0xaa76,
- 0xaa7a, 0xaabe,
- 0xaac0, 0xaac0,
- 0xaac2, 0xaac2,
- 0xaadb, 0xaadd,
- 0xaae0, 0xaaef,
- 0xaaf2, 0xaaf5,
- 0xab01, 0xab06,
- 0xab09, 0xab0e,
- 0xab11, 0xab16,
- 0xab20, 0xab26,
- 0xab28, 0xab2e,
- 0xab30, 0xab5a,
- 0xab5c, 0xab69,
- 0xab70, 0xabea,
- 0xac00, 0xd7a3,
- 0xd7b0, 0xd7c6,
- 0xd7cb, 0xd7fb,
- 0xf900, 0xfa6d,
- 0xfa70, 0xfad9,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1d, 0xfb28,
- 0xfb2a, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbb1,
- 0xfbd3, 0xfd3d,
- 0xfd50, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdf0, 0xfdfb,
- 0xfe70, 0xfe74,
- 0xfe76, 0xfefc,
- 0xff21, 0xff3a,
- 0xff41, 0xff5a,
- 0xff66, 0xffbe,
- 0xffc2, 0xffc7,
- 0xffca, 0xffcf,
- 0xffd2, 0xffd7,
- 0xffda, 0xffdc,
- 0x10000, 0x1000b,
- 0x1000d, 0x10026,
- 0x10028, 0x1003a,
- 0x1003c, 0x1003d,
- 0x1003f, 0x1004d,
- 0x10050, 0x1005d,
- 0x10080, 0x100fa,
- 0x10140, 0x10174,
- 0x10280, 0x1029c,
- 0x102a0, 0x102d0,
- 0x10300, 0x1031f,
- 0x1032d, 0x1034a,
- 0x10350, 0x1037a,
- 0x10380, 0x1039d,
- 0x103a0, 0x103c3,
- 0x103c8, 0x103cf,
- 0x103d1, 0x103d5,
- 0x10400, 0x1049d,
- 0x104b0, 0x104d3,
- 0x104d8, 0x104fb,
- 0x10500, 0x10527,
- 0x10530, 0x10563,
- 0x10570, 0x1057a,
- 0x1057c, 0x1058a,
- 0x1058c, 0x10592,
- 0x10594, 0x10595,
- 0x10597, 0x105a1,
- 0x105a3, 0x105b1,
- 0x105b3, 0x105b9,
- 0x105bb, 0x105bc,
- 0x10600, 0x10736,
- 0x10740, 0x10755,
- 0x10760, 0x10767,
- 0x10780, 0x10785,
- 0x10787, 0x107b0,
- 0x107b2, 0x107ba,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x10855,
- 0x10860, 0x10876,
- 0x10880, 0x1089e,
- 0x108e0, 0x108f2,
- 0x108f4, 0x108f5,
- 0x10900, 0x10915,
- 0x10920, 0x10939,
- 0x10980, 0x109b7,
- 0x109be, 0x109bf,
- 0x10a00, 0x10a03,
- 0x10a05, 0x10a06,
- 0x10a0c, 0x10a13,
- 0x10a15, 0x10a17,
- 0x10a19, 0x10a35,
- 0x10a60, 0x10a7c,
- 0x10a80, 0x10a9c,
- 0x10ac0, 0x10ac7,
- 0x10ac9, 0x10ae4,
- 0x10b00, 0x10b35,
- 0x10b40, 0x10b55,
- 0x10b60, 0x10b72,
- 0x10b80, 0x10b91,
- 0x10c00, 0x10c48,
- 0x10c80, 0x10cb2,
- 0x10cc0, 0x10cf2,
- 0x10d00, 0x10d27,
- 0x10e80, 0x10ea9,
- 0x10eab, 0x10eac,
- 0x10eb0, 0x10eb1,
- 0x10f00, 0x10f1c,
- 0x10f27, 0x10f27,
- 0x10f30, 0x10f45,
- 0x10f70, 0x10f81,
- 0x10fb0, 0x10fc4,
- 0x10fe0, 0x10ff6,
- 0x11000, 0x11045,
- 0x11071, 0x11075,
- 0x11080, 0x110b8,
- 0x110c2, 0x110c2,
- 0x110d0, 0x110e8,
- 0x11100, 0x11132,
- 0x11144, 0x11147,
- 0x11150, 0x11172,
- 0x11176, 0x11176,
- 0x11180, 0x111bf,
- 0x111c1, 0x111c4,
- 0x111ce, 0x111cf,
- 0x111da, 0x111da,
- 0x111dc, 0x111dc,
- 0x11200, 0x11211,
- 0x11213, 0x11234,
- 0x11237, 0x11237,
- 0x1123e, 0x11241,
- 0x11280, 0x11286,
- 0x11288, 0x11288,
- 0x1128a, 0x1128d,
- 0x1128f, 0x1129d,
- 0x1129f, 0x112a8,
- 0x112b0, 0x112e8,
- 0x11300, 0x11303,
- 0x11305, 0x1130c,
- 0x1130f, 0x11310,
- 0x11313, 0x11328,
- 0x1132a, 0x11330,
- 0x11332, 0x11333,
- 0x11335, 0x11339,
- 0x1133d, 0x11344,
- 0x11347, 0x11348,
- 0x1134b, 0x1134c,
- 0x11350, 0x11350,
- 0x11357, 0x11357,
- 0x1135d, 0x11363,
- 0x11400, 0x11441,
- 0x11443, 0x11445,
- 0x11447, 0x1144a,
- 0x1145f, 0x11461,
- 0x11480, 0x114c1,
- 0x114c4, 0x114c5,
- 0x114c7, 0x114c7,
- 0x11580, 0x115b5,
- 0x115b8, 0x115be,
- 0x115d8, 0x115dd,
- 0x11600, 0x1163e,
- 0x11640, 0x11640,
- 0x11644, 0x11644,
- 0x11680, 0x116b5,
- 0x116b8, 0x116b8,
- 0x11700, 0x1171a,
- 0x1171d, 0x1172a,
- 0x11740, 0x11746,
- 0x11800, 0x11838,
- 0x118a0, 0x118df,
- 0x118ff, 0x11906,
- 0x11909, 0x11909,
- 0x1190c, 0x11913,
- 0x11915, 0x11916,
- 0x11918, 0x11935,
- 0x11937, 0x11938,
- 0x1193b, 0x1193c,
- 0x1193f, 0x11942,
- 0x119a0, 0x119a7,
- 0x119aa, 0x119d7,
- 0x119da, 0x119df,
- 0x119e1, 0x119e1,
- 0x119e3, 0x119e4,
- 0x11a00, 0x11a32,
- 0x11a35, 0x11a3e,
- 0x11a50, 0x11a97,
- 0x11a9d, 0x11a9d,
- 0x11ab0, 0x11af8,
- 0x11c00, 0x11c08,
- 0x11c0a, 0x11c36,
- 0x11c38, 0x11c3e,
- 0x11c40, 0x11c40,
- 0x11c72, 0x11c8f,
- 0x11c92, 0x11ca7,
- 0x11ca9, 0x11cb6,
- 0x11d00, 0x11d06,
- 0x11d08, 0x11d09,
- 0x11d0b, 0x11d36,
- 0x11d3a, 0x11d3a,
- 0x11d3c, 0x11d3d,
- 0x11d3f, 0x11d41,
- 0x11d43, 0x11d43,
- 0x11d46, 0x11d47,
- 0x11d60, 0x11d65,
- 0x11d67, 0x11d68,
- 0x11d6a, 0x11d8e,
- 0x11d90, 0x11d91,
- 0x11d93, 0x11d96,
- 0x11d98, 0x11d98,
- 0x11ee0, 0x11ef6,
- 0x11f00, 0x11f10,
- 0x11f12, 0x11f3a,
- 0x11f3e, 0x11f40,
- 0x11fb0, 0x11fb0,
- 0x12000, 0x12399,
- 0x12400, 0x1246e,
- 0x12480, 0x12543,
- 0x12f90, 0x12ff0,
- 0x13000, 0x1342f,
- 0x13441, 0x13446,
- 0x14400, 0x14646,
- 0x16800, 0x16a38,
- 0x16a40, 0x16a5e,
- 0x16a70, 0x16abe,
- 0x16ad0, 0x16aed,
- 0x16b00, 0x16b2f,
- 0x16b40, 0x16b43,
- 0x16b63, 0x16b77,
- 0x16b7d, 0x16b8f,
- 0x16e40, 0x16e7f,
- 0x16f00, 0x16f4a,
- 0x16f4f, 0x16f87,
- 0x16f8f, 0x16f9f,
- 0x16fe0, 0x16fe1,
- 0x16fe3, 0x16fe3,
- 0x16ff0, 0x16ff1,
- 0x17000, 0x187f7,
- 0x18800, 0x18cd5,
- 0x18d00, 0x18d08,
- 0x1aff0, 0x1aff3,
- 0x1aff5, 0x1affb,
- 0x1affd, 0x1affe,
- 0x1b000, 0x1b122,
- 0x1b132, 0x1b132,
- 0x1b150, 0x1b152,
- 0x1b155, 0x1b155,
- 0x1b164, 0x1b167,
- 0x1b170, 0x1b2fb,
- 0x1bc00, 0x1bc6a,
- 0x1bc70, 0x1bc7c,
- 0x1bc80, 0x1bc88,
- 0x1bc90, 0x1bc99,
- 0x1bc9e, 0x1bc9e,
- 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, 0x1d6c0,
- 0x1d6c2, 0x1d6da,
- 0x1d6dc, 0x1d6fa,
- 0x1d6fc, 0x1d714,
- 0x1d716, 0x1d734,
- 0x1d736, 0x1d74e,
- 0x1d750, 0x1d76e,
- 0x1d770, 0x1d788,
- 0x1d78a, 0x1d7a8,
- 0x1d7aa, 0x1d7c2,
- 0x1d7c4, 0x1d7cb,
- 0x1df00, 0x1df1e,
- 0x1df25, 0x1df2a,
- 0x1e000, 0x1e006,
- 0x1e008, 0x1e018,
- 0x1e01b, 0x1e021,
- 0x1e023, 0x1e024,
- 0x1e026, 0x1e02a,
- 0x1e030, 0x1e06d,
- 0x1e08f, 0x1e08f,
- 0x1e100, 0x1e12c,
- 0x1e137, 0x1e13d,
- 0x1e14e, 0x1e14e,
- 0x1e290, 0x1e2ad,
- 0x1e2c0, 0x1e2eb,
- 0x1e4d0, 0x1e4eb,
- 0x1e7e0, 0x1e7e6,
- 0x1e7e8, 0x1e7eb,
- 0x1e7ed, 0x1e7ee,
- 0x1e7f0, 0x1e7fe,
- 0x1e800, 0x1e8c4,
- 0x1e900, 0x1e943,
- 0x1e947, 0x1e947,
- 0x1e94b, 0x1e94b,
- 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,
- 0x1f130, 0x1f149,
- 0x1f150, 0x1f169,
- 0x1f170, 0x1f189,
- 0x20000, 0x2a6df,
- 0x2a700, 0x2b739,
- 0x2b740, 0x2b81d,
- 0x2b820, 0x2cea1,
- 0x2ceb0, 0x2ebe0,
- 0x2f800, 0x2fa1d,
- 0x30000, 0x3134a,
- 0x31350, 0x323af,
-}; /* CR_Alpha */
-
-/* 'Blank': [[:Blank:]] */
-static const OnigCodePoint CR_Blank[] = {
- 8,
- 0x0009, 0x0009,
- 0x0020, 0x0020,
- 0x00a0, 0x00a0,
- 0x1680, 0x1680,
- 0x2000, 0x200a,
- 0x202f, 0x202f,
- 0x205f, 0x205f,
- 0x3000, 0x3000,
-}; /* CR_Blank */
-
-/* 'Cntrl': [[:Cntrl:]] */
-static const OnigCodePoint CR_Cntrl[] = {
- 2,
- 0x0000, 0x001f,
- 0x007f, 0x009f,
-}; /* CR_Cntrl */
-
-/* 'Digit': [[:Digit:]] */
-static const OnigCodePoint CR_Digit[] = {
- 64,
- 0x0030, 0x0039,
- 0x0660, 0x0669,
- 0x06f0, 0x06f9,
- 0x07c0, 0x07c9,
- 0x0966, 0x096f,
- 0x09e6, 0x09ef,
- 0x0a66, 0x0a6f,
- 0x0ae6, 0x0aef,
- 0x0b66, 0x0b6f,
- 0x0be6, 0x0bef,
- 0x0c66, 0x0c6f,
- 0x0ce6, 0x0cef,
- 0x0d66, 0x0d6f,
- 0x0de6, 0x0def,
- 0x0e50, 0x0e59,
- 0x0ed0, 0x0ed9,
- 0x0f20, 0x0f29,
- 0x1040, 0x1049,
- 0x1090, 0x1099,
- 0x17e0, 0x17e9,
- 0x1810, 0x1819,
- 0x1946, 0x194f,
- 0x19d0, 0x19d9,
- 0x1a80, 0x1a89,
- 0x1a90, 0x1a99,
- 0x1b50, 0x1b59,
- 0x1bb0, 0x1bb9,
- 0x1c40, 0x1c49,
- 0x1c50, 0x1c59,
- 0xa620, 0xa629,
- 0xa8d0, 0xa8d9,
- 0xa900, 0xa909,
- 0xa9d0, 0xa9d9,
- 0xa9f0, 0xa9f9,
- 0xaa50, 0xaa59,
- 0xabf0, 0xabf9,
- 0xff10, 0xff19,
- 0x104a0, 0x104a9,
- 0x10d30, 0x10d39,
- 0x11066, 0x1106f,
- 0x110f0, 0x110f9,
- 0x11136, 0x1113f,
- 0x111d0, 0x111d9,
- 0x112f0, 0x112f9,
- 0x11450, 0x11459,
- 0x114d0, 0x114d9,
- 0x11650, 0x11659,
- 0x116c0, 0x116c9,
- 0x11730, 0x11739,
- 0x118e0, 0x118e9,
- 0x11950, 0x11959,
- 0x11c50, 0x11c59,
- 0x11d50, 0x11d59,
- 0x11da0, 0x11da9,
- 0x11f50, 0x11f59,
- 0x16a60, 0x16a69,
- 0x16ac0, 0x16ac9,
- 0x16b50, 0x16b59,
- 0x1d7ce, 0x1d7ff,
- 0x1e140, 0x1e149,
- 0x1e2f0, 0x1e2f9,
- 0x1e4f0, 0x1e4f9,
- 0x1e950, 0x1e959,
- 0x1fbf0, 0x1fbf9,
-}; /* CR_Digit */
-
-/* 'Graph': [[:Graph:]] */
-static const OnigCodePoint CR_Graph[] = {
- 712,
- 0x0021, 0x007e,
- 0x00a1, 0x0377,
- 0x037a, 0x037f,
- 0x0384, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x052f,
- 0x0531, 0x0556,
- 0x0559, 0x058a,
- 0x058d, 0x058f,
- 0x0591, 0x05c7,
- 0x05d0, 0x05ea,
- 0x05ef, 0x05f4,
- 0x0600, 0x070d,
- 0x070f, 0x074a,
- 0x074d, 0x07b1,
- 0x07c0, 0x07fa,
- 0x07fd, 0x082d,
- 0x0830, 0x083e,
- 0x0840, 0x085b,
- 0x085e, 0x085e,
- 0x0860, 0x086a,
- 0x0870, 0x088e,
- 0x0890, 0x0891,
- 0x0898, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fe,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a51, 0x0a51,
- 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,
- 0x0be6, 0x0bfa,
- 0x0c00, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c39,
- 0x0c3c, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c58, 0x0c5a,
- 0x0c5d, 0x0c5d,
- 0x0c60, 0x0c63,
- 0x0c66, 0x0c6f,
- 0x0c77, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cdd, 0x0cde,
- 0x0ce0, 0x0ce3,
- 0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf3,
- 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, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 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, 0x0ece,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f71, 0x0f97,
- 0x0f99, 0x0fbc,
- 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, 0x167f,
- 0x1681, 0x169c,
- 0x16a0, 0x16f8,
- 0x1700, 0x1715,
- 0x171f, 0x1736,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17dd,
- 0x17e0, 0x17e9,
- 0x17f0, 0x17f9,
- 0x1800, 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, 0x1ace,
- 0x1b00, 0x1b4c,
- 0x1b50, 0x1b7e,
- 0x1b80, 0x1bf3,
- 0x1bfc, 0x1c37,
- 0x1c3b, 0x1c49,
- 0x1c4d, 0x1c88,
- 0x1c90, 0x1cba,
- 0x1cbd, 0x1cc7,
- 0x1cd0, 0x1cfa,
- 0x1d00, 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,
- 0x200b, 0x2027,
- 0x202a, 0x202e,
- 0x2030, 0x205e,
- 0x2060, 0x2064,
- 0x2066, 0x2071,
- 0x2074, 0x208e,
- 0x2090, 0x209c,
- 0x20a0, 0x20c0,
- 0x20d0, 0x20f0,
- 0x2100, 0x218b,
- 0x2190, 0x2426,
- 0x2440, 0x244a,
- 0x2460, 0x2b73,
- 0x2b76, 0x2b95,
- 0x2b97, 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, 0x2e5d,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3001, 0x303f,
- 0x3041, 0x3096,
- 0x3099, 0x30ff,
- 0x3105, 0x312f,
- 0x3131, 0x318e,
- 0x3190, 0x31e3,
- 0x31f0, 0x321e,
- 0x3220, 0xa48c,
- 0xa490, 0xa4c6,
- 0xa4d0, 0xa62b,
- 0xa640, 0xa6f7,
- 0xa700, 0xa7ca,
- 0xa7d0, 0xa7d1,
- 0xa7d3, 0xa7d3,
- 0xa7d5, 0xa7d9,
- 0xa7f2, 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,
- 0xe000, 0xfa6d,
- 0xfa70, 0xfad9,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1d, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbc2,
- 0xfbd3, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdcf, 0xfdcf,
- 0xfdf0, 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, 0xfffd,
- 0x10000, 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, 0x1057a,
- 0x1057c, 0x1058a,
- 0x1058c, 0x10592,
- 0x10594, 0x10595,
- 0x10597, 0x105a1,
- 0x105a3, 0x105b1,
- 0x105b3, 0x105b9,
- 0x105bb, 0x105bc,
- 0x10600, 0x10736,
- 0x10740, 0x10755,
- 0x10760, 0x10767,
- 0x10780, 0x10785,
- 0x10787, 0x107b0,
- 0x107b2, 0x107ba,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 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,
- 0x10efd, 0x10f27,
- 0x10f30, 0x10f59,
- 0x10f70, 0x10f89,
- 0x10fb0, 0x10fcb,
- 0x10fe0, 0x10ff6,
- 0x11000, 0x1104d,
- 0x11052, 0x11075,
- 0x1107f, 0x110c2,
- 0x110cd, 0x110cd,
- 0x110d0, 0x110e8,
- 0x110f0, 0x110f9,
- 0x11100, 0x11134,
- 0x11136, 0x11147,
- 0x11150, 0x11176,
- 0x11180, 0x111df,
- 0x111e1, 0x111f4,
- 0x11200, 0x11211,
- 0x11213, 0x11241,
- 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, 0x116b9,
- 0x116c0, 0x116c9,
- 0x11700, 0x1171a,
- 0x1171d, 0x1172b,
- 0x11730, 0x11746,
- 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,
- 0x11ab0, 0x11af8,
- 0x11b00, 0x11b09,
- 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,
- 0x11f00, 0x11f10,
- 0x11f12, 0x11f3a,
- 0x11f3e, 0x11f59,
- 0x11fb0, 0x11fb0,
- 0x11fc0, 0x11ff1,
- 0x11fff, 0x12399,
- 0x12400, 0x1246e,
- 0x12470, 0x12474,
- 0x12480, 0x12543,
- 0x12f90, 0x12ff2,
- 0x13000, 0x13455,
- 0x14400, 0x14646,
- 0x16800, 0x16a38,
- 0x16a40, 0x16a5e,
- 0x16a60, 0x16a69,
- 0x16a6e, 0x16abe,
- 0x16ac0, 0x16ac9,
- 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,
- 0x1aff0, 0x1aff3,
- 0x1aff5, 0x1affb,
- 0x1affd, 0x1affe,
- 0x1b000, 0x1b122,
- 0x1b132, 0x1b132,
- 0x1b150, 0x1b152,
- 0x1b155, 0x1b155,
- 0x1b164, 0x1b167,
- 0x1b170, 0x1b2fb,
- 0x1bc00, 0x1bc6a,
- 0x1bc70, 0x1bc7c,
- 0x1bc80, 0x1bc88,
- 0x1bc90, 0x1bc99,
- 0x1bc9c, 0x1bca3,
- 0x1cf00, 0x1cf2d,
- 0x1cf30, 0x1cf46,
- 0x1cf50, 0x1cfc3,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d129, 0x1d1ea,
- 0x1d200, 0x1d245,
- 0x1d2c0, 0x1d2d3,
- 0x1d2e0, 0x1d2f3,
- 0x1d300, 0x1d356,
- 0x1d360, 0x1d378,
- 0x1d400, 0x1d454,
- 0x1d456, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 0x1d4a2, 0x1d4a2,
- 0x1d4a5, 0x1d4a6,
- 0x1d4a9, 0x1d4ac,
- 0x1d4ae, 0x1d4b9,
- 0x1d4bb, 0x1d4bb,
- 0x1d4bd, 0x1d4c3,
- 0x1d4c5, 0x1d505,
- 0x1d507, 0x1d50a,
- 0x1d50d, 0x1d514,
- 0x1d516, 0x1d51c,
- 0x1d51e, 0x1d539,
- 0x1d53b, 0x1d53e,
- 0x1d540, 0x1d544,
- 0x1d546, 0x1d546,
- 0x1d54a, 0x1d550,
- 0x1d552, 0x1d6a5,
- 0x1d6a8, 0x1d7cb,
- 0x1d7ce, 0x1da8b,
- 0x1da9b, 0x1da9f,
- 0x1daa1, 0x1daaf,
- 0x1df00, 0x1df1e,
- 0x1df25, 0x1df2a,
- 0x1e000, 0x1e006,
- 0x1e008, 0x1e018,
- 0x1e01b, 0x1e021,
- 0x1e023, 0x1e024,
- 0x1e026, 0x1e02a,
- 0x1e030, 0x1e06d,
- 0x1e08f, 0x1e08f,
- 0x1e100, 0x1e12c,
- 0x1e130, 0x1e13d,
- 0x1e140, 0x1e149,
- 0x1e14e, 0x1e14f,
- 0x1e290, 0x1e2ae,
- 0x1e2c0, 0x1e2f9,
- 0x1e2ff, 0x1e2ff,
- 0x1e4d0, 0x1e4f9,
- 0x1e7e0, 0x1e7e6,
- 0x1e7e8, 0x1e7eb,
- 0x1e7ed, 0x1e7ee,
- 0x1e7f0, 0x1e7fe,
- 0x1e800, 0x1e8c4,
- 0x1e8c7, 0x1e8d6,
- 0x1e900, 0x1e94b,
- 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,
- 0x1f6dc, 0x1f6ec,
- 0x1f6f0, 0x1f6fc,
- 0x1f700, 0x1f776,
- 0x1f77b, 0x1f7d9,
- 0x1f7e0, 0x1f7eb,
- 0x1f7f0, 0x1f7f0,
- 0x1f800, 0x1f80b,
- 0x1f810, 0x1f847,
- 0x1f850, 0x1f859,
- 0x1f860, 0x1f887,
- 0x1f890, 0x1f8ad,
- 0x1f8b0, 0x1f8b1,
- 0x1f900, 0x1fa53,
- 0x1fa60, 0x1fa6d,
- 0x1fa70, 0x1fa7c,
- 0x1fa80, 0x1fa88,
- 0x1fa90, 0x1fabd,
- 0x1fabf, 0x1fac5,
- 0x1face, 0x1fadb,
- 0x1fae0, 0x1fae8,
- 0x1faf0, 0x1faf8,
- 0x1fb00, 0x1fb92,
- 0x1fb94, 0x1fbca,
- 0x1fbf0, 0x1fbf9,
- 0x20000, 0x2a6df,
- 0x2a700, 0x2b739,
- 0x2b740, 0x2b81d,
- 0x2b820, 0x2cea1,
- 0x2ceb0, 0x2ebe0,
- 0x2f800, 0x2fa1d,
- 0x30000, 0x3134a,
- 0x31350, 0x323af,
- 0xe0001, 0xe0001,
- 0xe0020, 0xe007f,
- 0xe0100, 0xe01ef,
- 0xf0000, 0xffffd,
- 0x100000, 0x10fffd,
-}; /* CR_Graph */
-
-/* 'Lower': [[:Lower:]] */
-static const OnigCodePoint CR_Lower[] = {
- 671,
- 0x0061, 0x007a,
- 0x00aa, 0x00aa,
- 0x00b5, 0x00b5,
- 0x00ba, 0x00ba,
- 0x00df, 0x00f6,
- 0x00f8, 0x00ff,
- 0x0101, 0x0101,
- 0x0103, 0x0103,
- 0x0105, 0x0105,
- 0x0107, 0x0107,
- 0x0109, 0x0109,
- 0x010b, 0x010b,
- 0x010d, 0x010d,
- 0x010f, 0x010f,
- 0x0111, 0x0111,
- 0x0113, 0x0113,
- 0x0115, 0x0115,
- 0x0117, 0x0117,
- 0x0119, 0x0119,
- 0x011b, 0x011b,
- 0x011d, 0x011d,
- 0x011f, 0x011f,
- 0x0121, 0x0121,
- 0x0123, 0x0123,
- 0x0125, 0x0125,
- 0x0127, 0x0127,
- 0x0129, 0x0129,
- 0x012b, 0x012b,
- 0x012d, 0x012d,
- 0x012f, 0x012f,
- 0x0131, 0x0131,
- 0x0133, 0x0133,
- 0x0135, 0x0135,
- 0x0137, 0x0138,
- 0x013a, 0x013a,
- 0x013c, 0x013c,
- 0x013e, 0x013e,
- 0x0140, 0x0140,
- 0x0142, 0x0142,
- 0x0144, 0x0144,
- 0x0146, 0x0146,
- 0x0148, 0x0149,
- 0x014b, 0x014b,
- 0x014d, 0x014d,
- 0x014f, 0x014f,
- 0x0151, 0x0151,
- 0x0153, 0x0153,
- 0x0155, 0x0155,
- 0x0157, 0x0157,
- 0x0159, 0x0159,
- 0x015b, 0x015b,
- 0x015d, 0x015d,
- 0x015f, 0x015f,
- 0x0161, 0x0161,
- 0x0163, 0x0163,
- 0x0165, 0x0165,
- 0x0167, 0x0167,
- 0x0169, 0x0169,
- 0x016b, 0x016b,
- 0x016d, 0x016d,
- 0x016f, 0x016f,
- 0x0171, 0x0171,
- 0x0173, 0x0173,
- 0x0175, 0x0175,
- 0x0177, 0x0177,
- 0x017a, 0x017a,
- 0x017c, 0x017c,
- 0x017e, 0x0180,
- 0x0183, 0x0183,
- 0x0185, 0x0185,
- 0x0188, 0x0188,
- 0x018c, 0x018d,
- 0x0192, 0x0192,
- 0x0195, 0x0195,
- 0x0199, 0x019b,
- 0x019e, 0x019e,
- 0x01a1, 0x01a1,
- 0x01a3, 0x01a3,
- 0x01a5, 0x01a5,
- 0x01a8, 0x01a8,
- 0x01aa, 0x01ab,
- 0x01ad, 0x01ad,
- 0x01b0, 0x01b0,
- 0x01b4, 0x01b4,
- 0x01b6, 0x01b6,
- 0x01b9, 0x01ba,
- 0x01bd, 0x01bf,
- 0x01c6, 0x01c6,
- 0x01c9, 0x01c9,
- 0x01cc, 0x01cc,
- 0x01ce, 0x01ce,
- 0x01d0, 0x01d0,
- 0x01d2, 0x01d2,
- 0x01d4, 0x01d4,
- 0x01d6, 0x01d6,
- 0x01d8, 0x01d8,
- 0x01da, 0x01da,
- 0x01dc, 0x01dd,
- 0x01df, 0x01df,
- 0x01e1, 0x01e1,
- 0x01e3, 0x01e3,
- 0x01e5, 0x01e5,
- 0x01e7, 0x01e7,
- 0x01e9, 0x01e9,
- 0x01eb, 0x01eb,
- 0x01ed, 0x01ed,
- 0x01ef, 0x01f0,
- 0x01f3, 0x01f3,
- 0x01f5, 0x01f5,
- 0x01f9, 0x01f9,
- 0x01fb, 0x01fb,
- 0x01fd, 0x01fd,
- 0x01ff, 0x01ff,
- 0x0201, 0x0201,
- 0x0203, 0x0203,
- 0x0205, 0x0205,
- 0x0207, 0x0207,
- 0x0209, 0x0209,
- 0x020b, 0x020b,
- 0x020d, 0x020d,
- 0x020f, 0x020f,
- 0x0211, 0x0211,
- 0x0213, 0x0213,
- 0x0215, 0x0215,
- 0x0217, 0x0217,
- 0x0219, 0x0219,
- 0x021b, 0x021b,
- 0x021d, 0x021d,
- 0x021f, 0x021f,
- 0x0221, 0x0221,
- 0x0223, 0x0223,
- 0x0225, 0x0225,
- 0x0227, 0x0227,
- 0x0229, 0x0229,
- 0x022b, 0x022b,
- 0x022d, 0x022d,
- 0x022f, 0x022f,
- 0x0231, 0x0231,
- 0x0233, 0x0239,
- 0x023c, 0x023c,
- 0x023f, 0x0240,
- 0x0242, 0x0242,
- 0x0247, 0x0247,
- 0x0249, 0x0249,
- 0x024b, 0x024b,
- 0x024d, 0x024d,
- 0x024f, 0x0293,
- 0x0295, 0x02b8,
- 0x02c0, 0x02c1,
- 0x02e0, 0x02e4,
- 0x0345, 0x0345,
- 0x0371, 0x0371,
- 0x0373, 0x0373,
- 0x0377, 0x0377,
- 0x037a, 0x037d,
- 0x0390, 0x0390,
- 0x03ac, 0x03ce,
- 0x03d0, 0x03d1,
- 0x03d5, 0x03d7,
- 0x03d9, 0x03d9,
- 0x03db, 0x03db,
- 0x03dd, 0x03dd,
- 0x03df, 0x03df,
- 0x03e1, 0x03e1,
- 0x03e3, 0x03e3,
- 0x03e5, 0x03e5,
- 0x03e7, 0x03e7,
- 0x03e9, 0x03e9,
- 0x03eb, 0x03eb,
- 0x03ed, 0x03ed,
- 0x03ef, 0x03f3,
- 0x03f5, 0x03f5,
- 0x03f8, 0x03f8,
- 0x03fb, 0x03fc,
- 0x0430, 0x045f,
- 0x0461, 0x0461,
- 0x0463, 0x0463,
- 0x0465, 0x0465,
- 0x0467, 0x0467,
- 0x0469, 0x0469,
- 0x046b, 0x046b,
- 0x046d, 0x046d,
- 0x046f, 0x046f,
- 0x0471, 0x0471,
- 0x0473, 0x0473,
- 0x0475, 0x0475,
- 0x0477, 0x0477,
- 0x0479, 0x0479,
- 0x047b, 0x047b,
- 0x047d, 0x047d,
- 0x047f, 0x047f,
- 0x0481, 0x0481,
- 0x048b, 0x048b,
- 0x048d, 0x048d,
- 0x048f, 0x048f,
- 0x0491, 0x0491,
- 0x0493, 0x0493,
- 0x0495, 0x0495,
- 0x0497, 0x0497,
- 0x0499, 0x0499,
- 0x049b, 0x049b,
- 0x049d, 0x049d,
- 0x049f, 0x049f,
- 0x04a1, 0x04a1,
- 0x04a3, 0x04a3,
- 0x04a5, 0x04a5,
- 0x04a7, 0x04a7,
- 0x04a9, 0x04a9,
- 0x04ab, 0x04ab,
- 0x04ad, 0x04ad,
- 0x04af, 0x04af,
- 0x04b1, 0x04b1,
- 0x04b3, 0x04b3,
- 0x04b5, 0x04b5,
- 0x04b7, 0x04b7,
- 0x04b9, 0x04b9,
- 0x04bb, 0x04bb,
- 0x04bd, 0x04bd,
- 0x04bf, 0x04bf,
- 0x04c2, 0x04c2,
- 0x04c4, 0x04c4,
- 0x04c6, 0x04c6,
- 0x04c8, 0x04c8,
- 0x04ca, 0x04ca,
- 0x04cc, 0x04cc,
- 0x04ce, 0x04cf,
- 0x04d1, 0x04d1,
- 0x04d3, 0x04d3,
- 0x04d5, 0x04d5,
- 0x04d7, 0x04d7,
- 0x04d9, 0x04d9,
- 0x04db, 0x04db,
- 0x04dd, 0x04dd,
- 0x04df, 0x04df,
- 0x04e1, 0x04e1,
- 0x04e3, 0x04e3,
- 0x04e5, 0x04e5,
- 0x04e7, 0x04e7,
- 0x04e9, 0x04e9,
- 0x04eb, 0x04eb,
- 0x04ed, 0x04ed,
- 0x04ef, 0x04ef,
- 0x04f1, 0x04f1,
- 0x04f3, 0x04f3,
- 0x04f5, 0x04f5,
- 0x04f7, 0x04f7,
- 0x04f9, 0x04f9,
- 0x04fb, 0x04fb,
- 0x04fd, 0x04fd,
- 0x04ff, 0x04ff,
- 0x0501, 0x0501,
- 0x0503, 0x0503,
- 0x0505, 0x0505,
- 0x0507, 0x0507,
- 0x0509, 0x0509,
- 0x050b, 0x050b,
- 0x050d, 0x050d,
- 0x050f, 0x050f,
- 0x0511, 0x0511,
- 0x0513, 0x0513,
- 0x0515, 0x0515,
- 0x0517, 0x0517,
- 0x0519, 0x0519,
- 0x051b, 0x051b,
- 0x051d, 0x051d,
- 0x051f, 0x051f,
- 0x0521, 0x0521,
- 0x0523, 0x0523,
- 0x0525, 0x0525,
- 0x0527, 0x0527,
- 0x0529, 0x0529,
- 0x052b, 0x052b,
- 0x052d, 0x052d,
- 0x052f, 0x052f,
- 0x0560, 0x0588,
- 0x10d0, 0x10fa,
- 0x10fc, 0x10ff,
- 0x13f8, 0x13fd,
- 0x1c80, 0x1c88,
- 0x1d00, 0x1dbf,
- 0x1e01, 0x1e01,
- 0x1e03, 0x1e03,
- 0x1e05, 0x1e05,
- 0x1e07, 0x1e07,
- 0x1e09, 0x1e09,
- 0x1e0b, 0x1e0b,
- 0x1e0d, 0x1e0d,
- 0x1e0f, 0x1e0f,
- 0x1e11, 0x1e11,
- 0x1e13, 0x1e13,
- 0x1e15, 0x1e15,
- 0x1e17, 0x1e17,
- 0x1e19, 0x1e19,
- 0x1e1b, 0x1e1b,
- 0x1e1d, 0x1e1d,
- 0x1e1f, 0x1e1f,
- 0x1e21, 0x1e21,
- 0x1e23, 0x1e23,
- 0x1e25, 0x1e25,
- 0x1e27, 0x1e27,
- 0x1e29, 0x1e29,
- 0x1e2b, 0x1e2b,
- 0x1e2d, 0x1e2d,
- 0x1e2f, 0x1e2f,
- 0x1e31, 0x1e31,
- 0x1e33, 0x1e33,
- 0x1e35, 0x1e35,
- 0x1e37, 0x1e37,
- 0x1e39, 0x1e39,
- 0x1e3b, 0x1e3b,
- 0x1e3d, 0x1e3d,
- 0x1e3f, 0x1e3f,
- 0x1e41, 0x1e41,
- 0x1e43, 0x1e43,
- 0x1e45, 0x1e45,
- 0x1e47, 0x1e47,
- 0x1e49, 0x1e49,
- 0x1e4b, 0x1e4b,
- 0x1e4d, 0x1e4d,
- 0x1e4f, 0x1e4f,
- 0x1e51, 0x1e51,
- 0x1e53, 0x1e53,
- 0x1e55, 0x1e55,
- 0x1e57, 0x1e57,
- 0x1e59, 0x1e59,
- 0x1e5b, 0x1e5b,
- 0x1e5d, 0x1e5d,
- 0x1e5f, 0x1e5f,
- 0x1e61, 0x1e61,
- 0x1e63, 0x1e63,
- 0x1e65, 0x1e65,
- 0x1e67, 0x1e67,
- 0x1e69, 0x1e69,
- 0x1e6b, 0x1e6b,
- 0x1e6d, 0x1e6d,
- 0x1e6f, 0x1e6f,
- 0x1e71, 0x1e71,
- 0x1e73, 0x1e73,
- 0x1e75, 0x1e75,
- 0x1e77, 0x1e77,
- 0x1e79, 0x1e79,
- 0x1e7b, 0x1e7b,
- 0x1e7d, 0x1e7d,
- 0x1e7f, 0x1e7f,
- 0x1e81, 0x1e81,
- 0x1e83, 0x1e83,
- 0x1e85, 0x1e85,
- 0x1e87, 0x1e87,
- 0x1e89, 0x1e89,
- 0x1e8b, 0x1e8b,
- 0x1e8d, 0x1e8d,
- 0x1e8f, 0x1e8f,
- 0x1e91, 0x1e91,
- 0x1e93, 0x1e93,
- 0x1e95, 0x1e9d,
- 0x1e9f, 0x1e9f,
- 0x1ea1, 0x1ea1,
- 0x1ea3, 0x1ea3,
- 0x1ea5, 0x1ea5,
- 0x1ea7, 0x1ea7,
- 0x1ea9, 0x1ea9,
- 0x1eab, 0x1eab,
- 0x1ead, 0x1ead,
- 0x1eaf, 0x1eaf,
- 0x1eb1, 0x1eb1,
- 0x1eb3, 0x1eb3,
- 0x1eb5, 0x1eb5,
- 0x1eb7, 0x1eb7,
- 0x1eb9, 0x1eb9,
- 0x1ebb, 0x1ebb,
- 0x1ebd, 0x1ebd,
- 0x1ebf, 0x1ebf,
- 0x1ec1, 0x1ec1,
- 0x1ec3, 0x1ec3,
- 0x1ec5, 0x1ec5,
- 0x1ec7, 0x1ec7,
- 0x1ec9, 0x1ec9,
- 0x1ecb, 0x1ecb,
- 0x1ecd, 0x1ecd,
- 0x1ecf, 0x1ecf,
- 0x1ed1, 0x1ed1,
- 0x1ed3, 0x1ed3,
- 0x1ed5, 0x1ed5,
- 0x1ed7, 0x1ed7,
- 0x1ed9, 0x1ed9,
- 0x1edb, 0x1edb,
- 0x1edd, 0x1edd,
- 0x1edf, 0x1edf,
- 0x1ee1, 0x1ee1,
- 0x1ee3, 0x1ee3,
- 0x1ee5, 0x1ee5,
- 0x1ee7, 0x1ee7,
- 0x1ee9, 0x1ee9,
- 0x1eeb, 0x1eeb,
- 0x1eed, 0x1eed,
- 0x1eef, 0x1eef,
- 0x1ef1, 0x1ef1,
- 0x1ef3, 0x1ef3,
- 0x1ef5, 0x1ef5,
- 0x1ef7, 0x1ef7,
- 0x1ef9, 0x1ef9,
- 0x1efb, 0x1efb,
- 0x1efd, 0x1efd,
- 0x1eff, 0x1f07,
- 0x1f10, 0x1f15,
- 0x1f20, 0x1f27,
- 0x1f30, 0x1f37,
- 0x1f40, 0x1f45,
- 0x1f50, 0x1f57,
- 0x1f60, 0x1f67,
- 0x1f70, 0x1f7d,
- 0x1f80, 0x1f87,
- 0x1f90, 0x1f97,
- 0x1fa0, 0x1fa7,
- 0x1fb0, 0x1fb4,
- 0x1fb6, 0x1fb7,
- 0x1fbe, 0x1fbe,
- 0x1fc2, 0x1fc4,
- 0x1fc6, 0x1fc7,
- 0x1fd0, 0x1fd3,
- 0x1fd6, 0x1fd7,
- 0x1fe0, 0x1fe7,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ff7,
- 0x2071, 0x2071,
- 0x207f, 0x207f,
- 0x2090, 0x209c,
- 0x210a, 0x210a,
- 0x210e, 0x210f,
- 0x2113, 0x2113,
- 0x212f, 0x212f,
- 0x2134, 0x2134,
- 0x2139, 0x2139,
- 0x213c, 0x213d,
- 0x2146, 0x2149,
- 0x214e, 0x214e,
- 0x2170, 0x217f,
- 0x2184, 0x2184,
- 0x24d0, 0x24e9,
- 0x2c30, 0x2c5f,
- 0x2c61, 0x2c61,
- 0x2c65, 0x2c66,
- 0x2c68, 0x2c68,
- 0x2c6a, 0x2c6a,
- 0x2c6c, 0x2c6c,
- 0x2c71, 0x2c71,
- 0x2c73, 0x2c74,
- 0x2c76, 0x2c7d,
- 0x2c81, 0x2c81,
- 0x2c83, 0x2c83,
- 0x2c85, 0x2c85,
- 0x2c87, 0x2c87,
- 0x2c89, 0x2c89,
- 0x2c8b, 0x2c8b,
- 0x2c8d, 0x2c8d,
- 0x2c8f, 0x2c8f,
- 0x2c91, 0x2c91,
- 0x2c93, 0x2c93,
- 0x2c95, 0x2c95,
- 0x2c97, 0x2c97,
- 0x2c99, 0x2c99,
- 0x2c9b, 0x2c9b,
- 0x2c9d, 0x2c9d,
- 0x2c9f, 0x2c9f,
- 0x2ca1, 0x2ca1,
- 0x2ca3, 0x2ca3,
- 0x2ca5, 0x2ca5,
- 0x2ca7, 0x2ca7,
- 0x2ca9, 0x2ca9,
- 0x2cab, 0x2cab,
- 0x2cad, 0x2cad,
- 0x2caf, 0x2caf,
- 0x2cb1, 0x2cb1,
- 0x2cb3, 0x2cb3,
- 0x2cb5, 0x2cb5,
- 0x2cb7, 0x2cb7,
- 0x2cb9, 0x2cb9,
- 0x2cbb, 0x2cbb,
- 0x2cbd, 0x2cbd,
- 0x2cbf, 0x2cbf,
- 0x2cc1, 0x2cc1,
- 0x2cc3, 0x2cc3,
- 0x2cc5, 0x2cc5,
- 0x2cc7, 0x2cc7,
- 0x2cc9, 0x2cc9,
- 0x2ccb, 0x2ccb,
- 0x2ccd, 0x2ccd,
- 0x2ccf, 0x2ccf,
- 0x2cd1, 0x2cd1,
- 0x2cd3, 0x2cd3,
- 0x2cd5, 0x2cd5,
- 0x2cd7, 0x2cd7,
- 0x2cd9, 0x2cd9,
- 0x2cdb, 0x2cdb,
- 0x2cdd, 0x2cdd,
- 0x2cdf, 0x2cdf,
- 0x2ce1, 0x2ce1,
- 0x2ce3, 0x2ce4,
- 0x2cec, 0x2cec,
- 0x2cee, 0x2cee,
- 0x2cf3, 0x2cf3,
- 0x2d00, 0x2d25,
- 0x2d27, 0x2d27,
- 0x2d2d, 0x2d2d,
- 0xa641, 0xa641,
- 0xa643, 0xa643,
- 0xa645, 0xa645,
- 0xa647, 0xa647,
- 0xa649, 0xa649,
- 0xa64b, 0xa64b,
- 0xa64d, 0xa64d,
- 0xa64f, 0xa64f,
- 0xa651, 0xa651,
- 0xa653, 0xa653,
- 0xa655, 0xa655,
- 0xa657, 0xa657,
- 0xa659, 0xa659,
- 0xa65b, 0xa65b,
- 0xa65d, 0xa65d,
- 0xa65f, 0xa65f,
- 0xa661, 0xa661,
- 0xa663, 0xa663,
- 0xa665, 0xa665,
- 0xa667, 0xa667,
- 0xa669, 0xa669,
- 0xa66b, 0xa66b,
- 0xa66d, 0xa66d,
- 0xa681, 0xa681,
- 0xa683, 0xa683,
- 0xa685, 0xa685,
- 0xa687, 0xa687,
- 0xa689, 0xa689,
- 0xa68b, 0xa68b,
- 0xa68d, 0xa68d,
- 0xa68f, 0xa68f,
- 0xa691, 0xa691,
- 0xa693, 0xa693,
- 0xa695, 0xa695,
- 0xa697, 0xa697,
- 0xa699, 0xa699,
- 0xa69b, 0xa69d,
- 0xa723, 0xa723,
- 0xa725, 0xa725,
- 0xa727, 0xa727,
- 0xa729, 0xa729,
- 0xa72b, 0xa72b,
- 0xa72d, 0xa72d,
- 0xa72f, 0xa731,
- 0xa733, 0xa733,
- 0xa735, 0xa735,
- 0xa737, 0xa737,
- 0xa739, 0xa739,
- 0xa73b, 0xa73b,
- 0xa73d, 0xa73d,
- 0xa73f, 0xa73f,
- 0xa741, 0xa741,
- 0xa743, 0xa743,
- 0xa745, 0xa745,
- 0xa747, 0xa747,
- 0xa749, 0xa749,
- 0xa74b, 0xa74b,
- 0xa74d, 0xa74d,
- 0xa74f, 0xa74f,
- 0xa751, 0xa751,
- 0xa753, 0xa753,
- 0xa755, 0xa755,
- 0xa757, 0xa757,
- 0xa759, 0xa759,
- 0xa75b, 0xa75b,
- 0xa75d, 0xa75d,
- 0xa75f, 0xa75f,
- 0xa761, 0xa761,
- 0xa763, 0xa763,
- 0xa765, 0xa765,
- 0xa767, 0xa767,
- 0xa769, 0xa769,
- 0xa76b, 0xa76b,
- 0xa76d, 0xa76d,
- 0xa76f, 0xa778,
- 0xa77a, 0xa77a,
- 0xa77c, 0xa77c,
- 0xa77f, 0xa77f,
- 0xa781, 0xa781,
- 0xa783, 0xa783,
- 0xa785, 0xa785,
- 0xa787, 0xa787,
- 0xa78c, 0xa78c,
- 0xa78e, 0xa78e,
- 0xa791, 0xa791,
- 0xa793, 0xa795,
- 0xa797, 0xa797,
- 0xa799, 0xa799,
- 0xa79b, 0xa79b,
- 0xa79d, 0xa79d,
- 0xa79f, 0xa79f,
- 0xa7a1, 0xa7a1,
- 0xa7a3, 0xa7a3,
- 0xa7a5, 0xa7a5,
- 0xa7a7, 0xa7a7,
- 0xa7a9, 0xa7a9,
- 0xa7af, 0xa7af,
- 0xa7b5, 0xa7b5,
- 0xa7b7, 0xa7b7,
- 0xa7b9, 0xa7b9,
- 0xa7bb, 0xa7bb,
- 0xa7bd, 0xa7bd,
- 0xa7bf, 0xa7bf,
- 0xa7c1, 0xa7c1,
- 0xa7c3, 0xa7c3,
- 0xa7c8, 0xa7c8,
- 0xa7ca, 0xa7ca,
- 0xa7d1, 0xa7d1,
- 0xa7d3, 0xa7d3,
- 0xa7d5, 0xa7d5,
- 0xa7d7, 0xa7d7,
- 0xa7d9, 0xa7d9,
- 0xa7f2, 0xa7f4,
- 0xa7f6, 0xa7f6,
- 0xa7f8, 0xa7fa,
- 0xab30, 0xab5a,
- 0xab5c, 0xab69,
- 0xab70, 0xabbf,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xff41, 0xff5a,
- 0x10428, 0x1044f,
- 0x104d8, 0x104fb,
- 0x10597, 0x105a1,
- 0x105a3, 0x105b1,
- 0x105b3, 0x105b9,
- 0x105bb, 0x105bc,
- 0x10780, 0x10780,
- 0x10783, 0x10785,
- 0x10787, 0x107b0,
- 0x107b2, 0x107ba,
- 0x10cc0, 0x10cf2,
- 0x118c0, 0x118df,
- 0x16e60, 0x16e7f,
- 0x1d41a, 0x1d433,
- 0x1d44e, 0x1d454,
- 0x1d456, 0x1d467,
- 0x1d482, 0x1d49b,
- 0x1d4b6, 0x1d4b9,
- 0x1d4bb, 0x1d4bb,
- 0x1d4bd, 0x1d4c3,
- 0x1d4c5, 0x1d4cf,
- 0x1d4ea, 0x1d503,
- 0x1d51e, 0x1d537,
- 0x1d552, 0x1d56b,
- 0x1d586, 0x1d59f,
- 0x1d5ba, 0x1d5d3,
- 0x1d5ee, 0x1d607,
- 0x1d622, 0x1d63b,
- 0x1d656, 0x1d66f,
- 0x1d68a, 0x1d6a5,
- 0x1d6c2, 0x1d6da,
- 0x1d6dc, 0x1d6e1,
- 0x1d6fc, 0x1d714,
- 0x1d716, 0x1d71b,
- 0x1d736, 0x1d74e,
- 0x1d750, 0x1d755,
- 0x1d770, 0x1d788,
- 0x1d78a, 0x1d78f,
- 0x1d7aa, 0x1d7c2,
- 0x1d7c4, 0x1d7c9,
- 0x1d7cb, 0x1d7cb,
- 0x1df00, 0x1df09,
- 0x1df0b, 0x1df1e,
- 0x1df25, 0x1df2a,
- 0x1e030, 0x1e06d,
- 0x1e922, 0x1e943,
-}; /* CR_Lower */
-
-/* 'Print': [[:Print:]] */
-static const OnigCodePoint CR_Print[] = {
- 709,
- 0x0020, 0x007e,
- 0x00a0, 0x0377,
- 0x037a, 0x037f,
- 0x0384, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x052f,
- 0x0531, 0x0556,
- 0x0559, 0x058a,
- 0x058d, 0x058f,
- 0x0591, 0x05c7,
- 0x05d0, 0x05ea,
- 0x05ef, 0x05f4,
- 0x0600, 0x070d,
- 0x070f, 0x074a,
- 0x074d, 0x07b1,
- 0x07c0, 0x07fa,
- 0x07fd, 0x082d,
- 0x0830, 0x083e,
- 0x0840, 0x085b,
- 0x085e, 0x085e,
- 0x0860, 0x086a,
- 0x0870, 0x088e,
- 0x0890, 0x0891,
- 0x0898, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fe,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a51, 0x0a51,
- 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,
- 0x0be6, 0x0bfa,
- 0x0c00, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c39,
- 0x0c3c, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c58, 0x0c5a,
- 0x0c5d, 0x0c5d,
- 0x0c60, 0x0c63,
- 0x0c66, 0x0c6f,
- 0x0c77, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cdd, 0x0cde,
- 0x0ce0, 0x0ce3,
- 0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf3,
- 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, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 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, 0x0ece,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f71, 0x0f97,
- 0x0f99, 0x0fbc,
- 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, 0x1715,
- 0x171f, 0x1736,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17dd,
- 0x17e0, 0x17e9,
- 0x17f0, 0x17f9,
- 0x1800, 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, 0x1ace,
- 0x1b00, 0x1b4c,
- 0x1b50, 0x1b7e,
- 0x1b80, 0x1bf3,
- 0x1bfc, 0x1c37,
- 0x1c3b, 0x1c49,
- 0x1c4d, 0x1c88,
- 0x1c90, 0x1cba,
- 0x1cbd, 0x1cc7,
- 0x1cd0, 0x1cfa,
- 0x1d00, 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, 0x2027,
- 0x202a, 0x2064,
- 0x2066, 0x2071,
- 0x2074, 0x208e,
- 0x2090, 0x209c,
- 0x20a0, 0x20c0,
- 0x20d0, 0x20f0,
- 0x2100, 0x218b,
- 0x2190, 0x2426,
- 0x2440, 0x244a,
- 0x2460, 0x2b73,
- 0x2b76, 0x2b95,
- 0x2b97, 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, 0x2e5d,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x303f,
- 0x3041, 0x3096,
- 0x3099, 0x30ff,
- 0x3105, 0x312f,
- 0x3131, 0x318e,
- 0x3190, 0x31e3,
- 0x31f0, 0x321e,
- 0x3220, 0xa48c,
- 0xa490, 0xa4c6,
- 0xa4d0, 0xa62b,
- 0xa640, 0xa6f7,
- 0xa700, 0xa7ca,
- 0xa7d0, 0xa7d1,
- 0xa7d3, 0xa7d3,
- 0xa7d5, 0xa7d9,
- 0xa7f2, 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,
- 0xe000, 0xfa6d,
- 0xfa70, 0xfad9,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1d, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbc2,
- 0xfbd3, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdcf, 0xfdcf,
- 0xfdf0, 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, 0xfffd,
- 0x10000, 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, 0x1057a,
- 0x1057c, 0x1058a,
- 0x1058c, 0x10592,
- 0x10594, 0x10595,
- 0x10597, 0x105a1,
- 0x105a3, 0x105b1,
- 0x105b3, 0x105b9,
- 0x105bb, 0x105bc,
- 0x10600, 0x10736,
- 0x10740, 0x10755,
- 0x10760, 0x10767,
- 0x10780, 0x10785,
- 0x10787, 0x107b0,
- 0x107b2, 0x107ba,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 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,
- 0x10efd, 0x10f27,
- 0x10f30, 0x10f59,
- 0x10f70, 0x10f89,
- 0x10fb0, 0x10fcb,
- 0x10fe0, 0x10ff6,
- 0x11000, 0x1104d,
- 0x11052, 0x11075,
- 0x1107f, 0x110c2,
- 0x110cd, 0x110cd,
- 0x110d0, 0x110e8,
- 0x110f0, 0x110f9,
- 0x11100, 0x11134,
- 0x11136, 0x11147,
- 0x11150, 0x11176,
- 0x11180, 0x111df,
- 0x111e1, 0x111f4,
- 0x11200, 0x11211,
- 0x11213, 0x11241,
- 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, 0x116b9,
- 0x116c0, 0x116c9,
- 0x11700, 0x1171a,
- 0x1171d, 0x1172b,
- 0x11730, 0x11746,
- 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,
- 0x11ab0, 0x11af8,
- 0x11b00, 0x11b09,
- 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,
- 0x11f00, 0x11f10,
- 0x11f12, 0x11f3a,
- 0x11f3e, 0x11f59,
- 0x11fb0, 0x11fb0,
- 0x11fc0, 0x11ff1,
- 0x11fff, 0x12399,
- 0x12400, 0x1246e,
- 0x12470, 0x12474,
- 0x12480, 0x12543,
- 0x12f90, 0x12ff2,
- 0x13000, 0x13455,
- 0x14400, 0x14646,
- 0x16800, 0x16a38,
- 0x16a40, 0x16a5e,
- 0x16a60, 0x16a69,
- 0x16a6e, 0x16abe,
- 0x16ac0, 0x16ac9,
- 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,
- 0x1aff0, 0x1aff3,
- 0x1aff5, 0x1affb,
- 0x1affd, 0x1affe,
- 0x1b000, 0x1b122,
- 0x1b132, 0x1b132,
- 0x1b150, 0x1b152,
- 0x1b155, 0x1b155,
- 0x1b164, 0x1b167,
- 0x1b170, 0x1b2fb,
- 0x1bc00, 0x1bc6a,
- 0x1bc70, 0x1bc7c,
- 0x1bc80, 0x1bc88,
- 0x1bc90, 0x1bc99,
- 0x1bc9c, 0x1bca3,
- 0x1cf00, 0x1cf2d,
- 0x1cf30, 0x1cf46,
- 0x1cf50, 0x1cfc3,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d129, 0x1d1ea,
- 0x1d200, 0x1d245,
- 0x1d2c0, 0x1d2d3,
- 0x1d2e0, 0x1d2f3,
- 0x1d300, 0x1d356,
- 0x1d360, 0x1d378,
- 0x1d400, 0x1d454,
- 0x1d456, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 0x1d4a2, 0x1d4a2,
- 0x1d4a5, 0x1d4a6,
- 0x1d4a9, 0x1d4ac,
- 0x1d4ae, 0x1d4b9,
- 0x1d4bb, 0x1d4bb,
- 0x1d4bd, 0x1d4c3,
- 0x1d4c5, 0x1d505,
- 0x1d507, 0x1d50a,
- 0x1d50d, 0x1d514,
- 0x1d516, 0x1d51c,
- 0x1d51e, 0x1d539,
- 0x1d53b, 0x1d53e,
- 0x1d540, 0x1d544,
- 0x1d546, 0x1d546,
- 0x1d54a, 0x1d550,
- 0x1d552, 0x1d6a5,
- 0x1d6a8, 0x1d7cb,
- 0x1d7ce, 0x1da8b,
- 0x1da9b, 0x1da9f,
- 0x1daa1, 0x1daaf,
- 0x1df00, 0x1df1e,
- 0x1df25, 0x1df2a,
- 0x1e000, 0x1e006,
- 0x1e008, 0x1e018,
- 0x1e01b, 0x1e021,
- 0x1e023, 0x1e024,
- 0x1e026, 0x1e02a,
- 0x1e030, 0x1e06d,
- 0x1e08f, 0x1e08f,
- 0x1e100, 0x1e12c,
- 0x1e130, 0x1e13d,
- 0x1e140, 0x1e149,
- 0x1e14e, 0x1e14f,
- 0x1e290, 0x1e2ae,
- 0x1e2c0, 0x1e2f9,
- 0x1e2ff, 0x1e2ff,
- 0x1e4d0, 0x1e4f9,
- 0x1e7e0, 0x1e7e6,
- 0x1e7e8, 0x1e7eb,
- 0x1e7ed, 0x1e7ee,
- 0x1e7f0, 0x1e7fe,
- 0x1e800, 0x1e8c4,
- 0x1e8c7, 0x1e8d6,
- 0x1e900, 0x1e94b,
- 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,
- 0x1f6dc, 0x1f6ec,
- 0x1f6f0, 0x1f6fc,
- 0x1f700, 0x1f776,
- 0x1f77b, 0x1f7d9,
- 0x1f7e0, 0x1f7eb,
- 0x1f7f0, 0x1f7f0,
- 0x1f800, 0x1f80b,
- 0x1f810, 0x1f847,
- 0x1f850, 0x1f859,
- 0x1f860, 0x1f887,
- 0x1f890, 0x1f8ad,
- 0x1f8b0, 0x1f8b1,
- 0x1f900, 0x1fa53,
- 0x1fa60, 0x1fa6d,
- 0x1fa70, 0x1fa7c,
- 0x1fa80, 0x1fa88,
- 0x1fa90, 0x1fabd,
- 0x1fabf, 0x1fac5,
- 0x1face, 0x1fadb,
- 0x1fae0, 0x1fae8,
- 0x1faf0, 0x1faf8,
- 0x1fb00, 0x1fb92,
- 0x1fb94, 0x1fbca,
- 0x1fbf0, 0x1fbf9,
- 0x20000, 0x2a6df,
- 0x2a700, 0x2b739,
- 0x2b740, 0x2b81d,
- 0x2b820, 0x2cea1,
- 0x2ceb0, 0x2ebe0,
- 0x2f800, 0x2fa1d,
- 0x30000, 0x3134a,
- 0x31350, 0x323af,
- 0xe0001, 0xe0001,
- 0xe0020, 0xe007f,
- 0xe0100, 0xe01ef,
- 0xf0000, 0xffffd,
- 0x100000, 0x10fffd,
-}; /* CR_Print */
-
-/* 'XPosixPunct': [[:Punct:]] */
-static const OnigCodePoint CR_XPosixPunct[] = {
- 186,
- 0x0021, 0x002f,
- 0x003a, 0x0040,
- 0x005b, 0x0060,
- 0x007b, 0x007e,
- 0x00a1, 0x00a1,
- 0x00a7, 0x00a7,
- 0x00ab, 0x00ab,
- 0x00b6, 0x00b7,
- 0x00bb, 0x00bb,
- 0x00bf, 0x00bf,
- 0x037e, 0x037e,
- 0x0387, 0x0387,
- 0x055a, 0x055f,
- 0x0589, 0x058a,
- 0x05be, 0x05be,
- 0x05c0, 0x05c0,
- 0x05c3, 0x05c3,
- 0x05c6, 0x05c6,
- 0x05f3, 0x05f4,
- 0x0609, 0x060a,
- 0x060c, 0x060d,
- 0x061b, 0x061b,
- 0x061d, 0x061f,
- 0x066a, 0x066d,
- 0x06d4, 0x06d4,
- 0x0700, 0x070d,
- 0x07f7, 0x07f9,
- 0x0830, 0x083e,
- 0x085e, 0x085e,
- 0x0964, 0x0965,
- 0x0970, 0x0970,
- 0x09fd, 0x09fd,
- 0x0a76, 0x0a76,
- 0x0af0, 0x0af0,
- 0x0c77, 0x0c77,
- 0x0c84, 0x0c84,
- 0x0df4, 0x0df4,
- 0x0e4f, 0x0e4f,
- 0x0e5a, 0x0e5b,
- 0x0f04, 0x0f12,
- 0x0f14, 0x0f14,
- 0x0f3a, 0x0f3d,
- 0x0f85, 0x0f85,
- 0x0fd0, 0x0fd4,
- 0x0fd9, 0x0fda,
- 0x104a, 0x104f,
- 0x10fb, 0x10fb,
- 0x1360, 0x1368,
- 0x1400, 0x1400,
- 0x166e, 0x166e,
- 0x169b, 0x169c,
- 0x16eb, 0x16ed,
- 0x1735, 0x1736,
- 0x17d4, 0x17d6,
- 0x17d8, 0x17da,
- 0x1800, 0x180a,
- 0x1944, 0x1945,
- 0x1a1e, 0x1a1f,
- 0x1aa0, 0x1aa6,
- 0x1aa8, 0x1aad,
- 0x1b5a, 0x1b60,
- 0x1b7d, 0x1b7e,
- 0x1bfc, 0x1bff,
- 0x1c3b, 0x1c3f,
- 0x1c7e, 0x1c7f,
- 0x1cc0, 0x1cc7,
- 0x1cd3, 0x1cd3,
- 0x2010, 0x2027,
- 0x2030, 0x2043,
- 0x2045, 0x2051,
- 0x2053, 0x205e,
- 0x207d, 0x207e,
- 0x208d, 0x208e,
- 0x2308, 0x230b,
- 0x2329, 0x232a,
- 0x2768, 0x2775,
- 0x27c5, 0x27c6,
- 0x27e6, 0x27ef,
- 0x2983, 0x2998,
- 0x29d8, 0x29db,
- 0x29fc, 0x29fd,
- 0x2cf9, 0x2cfc,
- 0x2cfe, 0x2cff,
- 0x2d70, 0x2d70,
- 0x2e00, 0x2e2e,
- 0x2e30, 0x2e4f,
- 0x2e52, 0x2e5d,
- 0x3001, 0x3003,
- 0x3008, 0x3011,
- 0x3014, 0x301f,
- 0x3030, 0x3030,
- 0x303d, 0x303d,
- 0x30a0, 0x30a0,
- 0x30fb, 0x30fb,
- 0xa4fe, 0xa4ff,
- 0xa60d, 0xa60f,
- 0xa673, 0xa673,
- 0xa67e, 0xa67e,
- 0xa6f2, 0xa6f7,
- 0xa874, 0xa877,
- 0xa8ce, 0xa8cf,
- 0xa8f8, 0xa8fa,
- 0xa8fc, 0xa8fc,
- 0xa92e, 0xa92f,
- 0xa95f, 0xa95f,
- 0xa9c1, 0xa9cd,
- 0xa9de, 0xa9df,
- 0xaa5c, 0xaa5f,
- 0xaade, 0xaadf,
- 0xaaf0, 0xaaf1,
- 0xabeb, 0xabeb,
- 0xfd3e, 0xfd3f,
- 0xfe10, 0xfe19,
- 0xfe30, 0xfe52,
- 0xfe54, 0xfe61,
- 0xfe63, 0xfe63,
- 0xfe68, 0xfe68,
- 0xfe6a, 0xfe6b,
- 0xff01, 0xff03,
- 0xff05, 0xff0a,
- 0xff0c, 0xff0f,
- 0xff1a, 0xff1b,
- 0xff1f, 0xff20,
- 0xff3b, 0xff3d,
- 0xff3f, 0xff3f,
- 0xff5b, 0xff5b,
- 0xff5d, 0xff5d,
- 0xff5f, 0xff65,
- 0x10100, 0x10102,
- 0x1039f, 0x1039f,
- 0x103d0, 0x103d0,
- 0x1056f, 0x1056f,
- 0x10857, 0x10857,
- 0x1091f, 0x1091f,
- 0x1093f, 0x1093f,
- 0x10a50, 0x10a58,
- 0x10a7f, 0x10a7f,
- 0x10af0, 0x10af6,
- 0x10b39, 0x10b3f,
- 0x10b99, 0x10b9c,
- 0x10ead, 0x10ead,
- 0x10f55, 0x10f59,
- 0x10f86, 0x10f89,
- 0x11047, 0x1104d,
- 0x110bb, 0x110bc,
- 0x110be, 0x110c1,
- 0x11140, 0x11143,
- 0x11174, 0x11175,
- 0x111c5, 0x111c8,
- 0x111cd, 0x111cd,
- 0x111db, 0x111db,
- 0x111dd, 0x111df,
- 0x11238, 0x1123d,
- 0x112a9, 0x112a9,
- 0x1144b, 0x1144f,
- 0x1145a, 0x1145b,
- 0x1145d, 0x1145d,
- 0x114c6, 0x114c6,
- 0x115c1, 0x115d7,
- 0x11641, 0x11643,
- 0x11660, 0x1166c,
- 0x116b9, 0x116b9,
- 0x1173c, 0x1173e,
- 0x1183b, 0x1183b,
- 0x11944, 0x11946,
- 0x119e2, 0x119e2,
- 0x11a3f, 0x11a46,
- 0x11a9a, 0x11a9c,
- 0x11a9e, 0x11aa2,
- 0x11b00, 0x11b09,
- 0x11c41, 0x11c45,
- 0x11c70, 0x11c71,
- 0x11ef7, 0x11ef8,
- 0x11f43, 0x11f4f,
- 0x11fff, 0x11fff,
- 0x12470, 0x12474,
- 0x12ff1, 0x12ff2,
- 0x16a6e, 0x16a6f,
- 0x16af5, 0x16af5,
- 0x16b37, 0x16b3b,
- 0x16b44, 0x16b44,
- 0x16e97, 0x16e9a,
- 0x16fe2, 0x16fe2,
- 0x1bc9f, 0x1bc9f,
- 0x1da87, 0x1da8b,
- 0x1e95e, 0x1e95f,
-}; /* CR_XPosixPunct */
-
-/* 'Space': [[:Space:]] */
-static const OnigCodePoint CR_Space[] = {
- 10,
- 0x0009, 0x000d,
- 0x0020, 0x0020,
- 0x0085, 0x0085,
- 0x00a0, 0x00a0,
- 0x1680, 0x1680,
- 0x2000, 0x200a,
- 0x2028, 0x2029,
- 0x202f, 0x202f,
- 0x205f, 0x205f,
- 0x3000, 0x3000,
-}; /* CR_Space */
-
-/* 'Upper': [[:Upper:]] */
-static const OnigCodePoint CR_Upper[] = {
- 651,
- 0x0041, 0x005a,
- 0x00c0, 0x00d6,
- 0x00d8, 0x00de,
- 0x0100, 0x0100,
- 0x0102, 0x0102,
- 0x0104, 0x0104,
- 0x0106, 0x0106,
- 0x0108, 0x0108,
- 0x010a, 0x010a,
- 0x010c, 0x010c,
- 0x010e, 0x010e,
- 0x0110, 0x0110,
- 0x0112, 0x0112,
- 0x0114, 0x0114,
- 0x0116, 0x0116,
- 0x0118, 0x0118,
- 0x011a, 0x011a,
- 0x011c, 0x011c,
- 0x011e, 0x011e,
- 0x0120, 0x0120,
- 0x0122, 0x0122,
- 0x0124, 0x0124,
- 0x0126, 0x0126,
- 0x0128, 0x0128,
- 0x012a, 0x012a,
- 0x012c, 0x012c,
- 0x012e, 0x012e,
- 0x0130, 0x0130,
- 0x0132, 0x0132,
- 0x0134, 0x0134,
- 0x0136, 0x0136,
- 0x0139, 0x0139,
- 0x013b, 0x013b,
- 0x013d, 0x013d,
- 0x013f, 0x013f,
- 0x0141, 0x0141,
- 0x0143, 0x0143,
- 0x0145, 0x0145,
- 0x0147, 0x0147,
- 0x014a, 0x014a,
- 0x014c, 0x014c,
- 0x014e, 0x014e,
- 0x0150, 0x0150,
- 0x0152, 0x0152,
- 0x0154, 0x0154,
- 0x0156, 0x0156,
- 0x0158, 0x0158,
- 0x015a, 0x015a,
- 0x015c, 0x015c,
- 0x015e, 0x015e,
- 0x0160, 0x0160,
- 0x0162, 0x0162,
- 0x0164, 0x0164,
- 0x0166, 0x0166,
- 0x0168, 0x0168,
- 0x016a, 0x016a,
- 0x016c, 0x016c,
- 0x016e, 0x016e,
- 0x0170, 0x0170,
- 0x0172, 0x0172,
- 0x0174, 0x0174,
- 0x0176, 0x0176,
- 0x0178, 0x0179,
- 0x017b, 0x017b,
- 0x017d, 0x017d,
- 0x0181, 0x0182,
- 0x0184, 0x0184,
- 0x0186, 0x0187,
- 0x0189, 0x018b,
- 0x018e, 0x0191,
- 0x0193, 0x0194,
- 0x0196, 0x0198,
- 0x019c, 0x019d,
- 0x019f, 0x01a0,
- 0x01a2, 0x01a2,
- 0x01a4, 0x01a4,
- 0x01a6, 0x01a7,
- 0x01a9, 0x01a9,
- 0x01ac, 0x01ac,
- 0x01ae, 0x01af,
- 0x01b1, 0x01b3,
- 0x01b5, 0x01b5,
- 0x01b7, 0x01b8,
- 0x01bc, 0x01bc,
- 0x01c4, 0x01c4,
- 0x01c7, 0x01c7,
- 0x01ca, 0x01ca,
- 0x01cd, 0x01cd,
- 0x01cf, 0x01cf,
- 0x01d1, 0x01d1,
- 0x01d3, 0x01d3,
- 0x01d5, 0x01d5,
- 0x01d7, 0x01d7,
- 0x01d9, 0x01d9,
- 0x01db, 0x01db,
- 0x01de, 0x01de,
- 0x01e0, 0x01e0,
- 0x01e2, 0x01e2,
- 0x01e4, 0x01e4,
- 0x01e6, 0x01e6,
- 0x01e8, 0x01e8,
- 0x01ea, 0x01ea,
- 0x01ec, 0x01ec,
- 0x01ee, 0x01ee,
- 0x01f1, 0x01f1,
- 0x01f4, 0x01f4,
- 0x01f6, 0x01f8,
- 0x01fa, 0x01fa,
- 0x01fc, 0x01fc,
- 0x01fe, 0x01fe,
- 0x0200, 0x0200,
- 0x0202, 0x0202,
- 0x0204, 0x0204,
- 0x0206, 0x0206,
- 0x0208, 0x0208,
- 0x020a, 0x020a,
- 0x020c, 0x020c,
- 0x020e, 0x020e,
- 0x0210, 0x0210,
- 0x0212, 0x0212,
- 0x0214, 0x0214,
- 0x0216, 0x0216,
- 0x0218, 0x0218,
- 0x021a, 0x021a,
- 0x021c, 0x021c,
- 0x021e, 0x021e,
- 0x0220, 0x0220,
- 0x0222, 0x0222,
- 0x0224, 0x0224,
- 0x0226, 0x0226,
- 0x0228, 0x0228,
- 0x022a, 0x022a,
- 0x022c, 0x022c,
- 0x022e, 0x022e,
- 0x0230, 0x0230,
- 0x0232, 0x0232,
- 0x023a, 0x023b,
- 0x023d, 0x023e,
- 0x0241, 0x0241,
- 0x0243, 0x0246,
- 0x0248, 0x0248,
- 0x024a, 0x024a,
- 0x024c, 0x024c,
- 0x024e, 0x024e,
- 0x0370, 0x0370,
- 0x0372, 0x0372,
- 0x0376, 0x0376,
- 0x037f, 0x037f,
- 0x0386, 0x0386,
- 0x0388, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x038f,
- 0x0391, 0x03a1,
- 0x03a3, 0x03ab,
- 0x03cf, 0x03cf,
- 0x03d2, 0x03d4,
- 0x03d8, 0x03d8,
- 0x03da, 0x03da,
- 0x03dc, 0x03dc,
- 0x03de, 0x03de,
- 0x03e0, 0x03e0,
- 0x03e2, 0x03e2,
- 0x03e4, 0x03e4,
- 0x03e6, 0x03e6,
- 0x03e8, 0x03e8,
- 0x03ea, 0x03ea,
- 0x03ec, 0x03ec,
- 0x03ee, 0x03ee,
- 0x03f4, 0x03f4,
- 0x03f7, 0x03f7,
- 0x03f9, 0x03fa,
- 0x03fd, 0x042f,
- 0x0460, 0x0460,
- 0x0462, 0x0462,
- 0x0464, 0x0464,
- 0x0466, 0x0466,
- 0x0468, 0x0468,
- 0x046a, 0x046a,
- 0x046c, 0x046c,
- 0x046e, 0x046e,
- 0x0470, 0x0470,
- 0x0472, 0x0472,
- 0x0474, 0x0474,
- 0x0476, 0x0476,
- 0x0478, 0x0478,
- 0x047a, 0x047a,
- 0x047c, 0x047c,
- 0x047e, 0x047e,
- 0x0480, 0x0480,
- 0x048a, 0x048a,
- 0x048c, 0x048c,
- 0x048e, 0x048e,
- 0x0490, 0x0490,
- 0x0492, 0x0492,
- 0x0494, 0x0494,
- 0x0496, 0x0496,
- 0x0498, 0x0498,
- 0x049a, 0x049a,
- 0x049c, 0x049c,
- 0x049e, 0x049e,
- 0x04a0, 0x04a0,
- 0x04a2, 0x04a2,
- 0x04a4, 0x04a4,
- 0x04a6, 0x04a6,
- 0x04a8, 0x04a8,
- 0x04aa, 0x04aa,
- 0x04ac, 0x04ac,
- 0x04ae, 0x04ae,
- 0x04b0, 0x04b0,
- 0x04b2, 0x04b2,
- 0x04b4, 0x04b4,
- 0x04b6, 0x04b6,
- 0x04b8, 0x04b8,
- 0x04ba, 0x04ba,
- 0x04bc, 0x04bc,
- 0x04be, 0x04be,
- 0x04c0, 0x04c1,
- 0x04c3, 0x04c3,
- 0x04c5, 0x04c5,
- 0x04c7, 0x04c7,
- 0x04c9, 0x04c9,
- 0x04cb, 0x04cb,
- 0x04cd, 0x04cd,
- 0x04d0, 0x04d0,
- 0x04d2, 0x04d2,
- 0x04d4, 0x04d4,
- 0x04d6, 0x04d6,
- 0x04d8, 0x04d8,
- 0x04da, 0x04da,
- 0x04dc, 0x04dc,
- 0x04de, 0x04de,
- 0x04e0, 0x04e0,
- 0x04e2, 0x04e2,
- 0x04e4, 0x04e4,
- 0x04e6, 0x04e6,
- 0x04e8, 0x04e8,
- 0x04ea, 0x04ea,
- 0x04ec, 0x04ec,
- 0x04ee, 0x04ee,
- 0x04f0, 0x04f0,
- 0x04f2, 0x04f2,
- 0x04f4, 0x04f4,
- 0x04f6, 0x04f6,
- 0x04f8, 0x04f8,
- 0x04fa, 0x04fa,
- 0x04fc, 0x04fc,
- 0x04fe, 0x04fe,
- 0x0500, 0x0500,
- 0x0502, 0x0502,
- 0x0504, 0x0504,
- 0x0506, 0x0506,
- 0x0508, 0x0508,
- 0x050a, 0x050a,
- 0x050c, 0x050c,
- 0x050e, 0x050e,
- 0x0510, 0x0510,
- 0x0512, 0x0512,
- 0x0514, 0x0514,
- 0x0516, 0x0516,
- 0x0518, 0x0518,
- 0x051a, 0x051a,
- 0x051c, 0x051c,
- 0x051e, 0x051e,
- 0x0520, 0x0520,
- 0x0522, 0x0522,
- 0x0524, 0x0524,
- 0x0526, 0x0526,
- 0x0528, 0x0528,
- 0x052a, 0x052a,
- 0x052c, 0x052c,
- 0x052e, 0x052e,
- 0x0531, 0x0556,
- 0x10a0, 0x10c5,
- 0x10c7, 0x10c7,
- 0x10cd, 0x10cd,
- 0x13a0, 0x13f5,
- 0x1c90, 0x1cba,
- 0x1cbd, 0x1cbf,
- 0x1e00, 0x1e00,
- 0x1e02, 0x1e02,
- 0x1e04, 0x1e04,
- 0x1e06, 0x1e06,
- 0x1e08, 0x1e08,
- 0x1e0a, 0x1e0a,
- 0x1e0c, 0x1e0c,
- 0x1e0e, 0x1e0e,
- 0x1e10, 0x1e10,
- 0x1e12, 0x1e12,
- 0x1e14, 0x1e14,
- 0x1e16, 0x1e16,
- 0x1e18, 0x1e18,
- 0x1e1a, 0x1e1a,
- 0x1e1c, 0x1e1c,
- 0x1e1e, 0x1e1e,
- 0x1e20, 0x1e20,
- 0x1e22, 0x1e22,
- 0x1e24, 0x1e24,
- 0x1e26, 0x1e26,
- 0x1e28, 0x1e28,
- 0x1e2a, 0x1e2a,
- 0x1e2c, 0x1e2c,
- 0x1e2e, 0x1e2e,
- 0x1e30, 0x1e30,
- 0x1e32, 0x1e32,
- 0x1e34, 0x1e34,
- 0x1e36, 0x1e36,
- 0x1e38, 0x1e38,
- 0x1e3a, 0x1e3a,
- 0x1e3c, 0x1e3c,
- 0x1e3e, 0x1e3e,
- 0x1e40, 0x1e40,
- 0x1e42, 0x1e42,
- 0x1e44, 0x1e44,
- 0x1e46, 0x1e46,
- 0x1e48, 0x1e48,
- 0x1e4a, 0x1e4a,
- 0x1e4c, 0x1e4c,
- 0x1e4e, 0x1e4e,
- 0x1e50, 0x1e50,
- 0x1e52, 0x1e52,
- 0x1e54, 0x1e54,
- 0x1e56, 0x1e56,
- 0x1e58, 0x1e58,
- 0x1e5a, 0x1e5a,
- 0x1e5c, 0x1e5c,
- 0x1e5e, 0x1e5e,
- 0x1e60, 0x1e60,
- 0x1e62, 0x1e62,
- 0x1e64, 0x1e64,
- 0x1e66, 0x1e66,
- 0x1e68, 0x1e68,
- 0x1e6a, 0x1e6a,
- 0x1e6c, 0x1e6c,
- 0x1e6e, 0x1e6e,
- 0x1e70, 0x1e70,
- 0x1e72, 0x1e72,
- 0x1e74, 0x1e74,
- 0x1e76, 0x1e76,
- 0x1e78, 0x1e78,
- 0x1e7a, 0x1e7a,
- 0x1e7c, 0x1e7c,
- 0x1e7e, 0x1e7e,
- 0x1e80, 0x1e80,
- 0x1e82, 0x1e82,
- 0x1e84, 0x1e84,
- 0x1e86, 0x1e86,
- 0x1e88, 0x1e88,
- 0x1e8a, 0x1e8a,
- 0x1e8c, 0x1e8c,
- 0x1e8e, 0x1e8e,
- 0x1e90, 0x1e90,
- 0x1e92, 0x1e92,
- 0x1e94, 0x1e94,
- 0x1e9e, 0x1e9e,
- 0x1ea0, 0x1ea0,
- 0x1ea2, 0x1ea2,
- 0x1ea4, 0x1ea4,
- 0x1ea6, 0x1ea6,
- 0x1ea8, 0x1ea8,
- 0x1eaa, 0x1eaa,
- 0x1eac, 0x1eac,
- 0x1eae, 0x1eae,
- 0x1eb0, 0x1eb0,
- 0x1eb2, 0x1eb2,
- 0x1eb4, 0x1eb4,
- 0x1eb6, 0x1eb6,
- 0x1eb8, 0x1eb8,
- 0x1eba, 0x1eba,
- 0x1ebc, 0x1ebc,
- 0x1ebe, 0x1ebe,
- 0x1ec0, 0x1ec0,
- 0x1ec2, 0x1ec2,
- 0x1ec4, 0x1ec4,
- 0x1ec6, 0x1ec6,
- 0x1ec8, 0x1ec8,
- 0x1eca, 0x1eca,
- 0x1ecc, 0x1ecc,
- 0x1ece, 0x1ece,
- 0x1ed0, 0x1ed0,
- 0x1ed2, 0x1ed2,
- 0x1ed4, 0x1ed4,
- 0x1ed6, 0x1ed6,
- 0x1ed8, 0x1ed8,
- 0x1eda, 0x1eda,
- 0x1edc, 0x1edc,
- 0x1ede, 0x1ede,
- 0x1ee0, 0x1ee0,
- 0x1ee2, 0x1ee2,
- 0x1ee4, 0x1ee4,
- 0x1ee6, 0x1ee6,
- 0x1ee8, 0x1ee8,
- 0x1eea, 0x1eea,
- 0x1eec, 0x1eec,
- 0x1eee, 0x1eee,
- 0x1ef0, 0x1ef0,
- 0x1ef2, 0x1ef2,
- 0x1ef4, 0x1ef4,
- 0x1ef6, 0x1ef6,
- 0x1ef8, 0x1ef8,
- 0x1efa, 0x1efa,
- 0x1efc, 0x1efc,
- 0x1efe, 0x1efe,
- 0x1f08, 0x1f0f,
- 0x1f18, 0x1f1d,
- 0x1f28, 0x1f2f,
- 0x1f38, 0x1f3f,
- 0x1f48, 0x1f4d,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f5f,
- 0x1f68, 0x1f6f,
- 0x1fb8, 0x1fbb,
- 0x1fc8, 0x1fcb,
- 0x1fd8, 0x1fdb,
- 0x1fe8, 0x1fec,
- 0x1ff8, 0x1ffb,
- 0x2102, 0x2102,
- 0x2107, 0x2107,
- 0x210b, 0x210d,
- 0x2110, 0x2112,
- 0x2115, 0x2115,
- 0x2119, 0x211d,
- 0x2124, 0x2124,
- 0x2126, 0x2126,
- 0x2128, 0x2128,
- 0x212a, 0x212d,
- 0x2130, 0x2133,
- 0x213e, 0x213f,
- 0x2145, 0x2145,
- 0x2160, 0x216f,
- 0x2183, 0x2183,
- 0x24b6, 0x24cf,
- 0x2c00, 0x2c2f,
- 0x2c60, 0x2c60,
- 0x2c62, 0x2c64,
- 0x2c67, 0x2c67,
- 0x2c69, 0x2c69,
- 0x2c6b, 0x2c6b,
- 0x2c6d, 0x2c70,
- 0x2c72, 0x2c72,
- 0x2c75, 0x2c75,
- 0x2c7e, 0x2c80,
- 0x2c82, 0x2c82,
- 0x2c84, 0x2c84,
- 0x2c86, 0x2c86,
- 0x2c88, 0x2c88,
- 0x2c8a, 0x2c8a,
- 0x2c8c, 0x2c8c,
- 0x2c8e, 0x2c8e,
- 0x2c90, 0x2c90,
- 0x2c92, 0x2c92,
- 0x2c94, 0x2c94,
- 0x2c96, 0x2c96,
- 0x2c98, 0x2c98,
- 0x2c9a, 0x2c9a,
- 0x2c9c, 0x2c9c,
- 0x2c9e, 0x2c9e,
- 0x2ca0, 0x2ca0,
- 0x2ca2, 0x2ca2,
- 0x2ca4, 0x2ca4,
- 0x2ca6, 0x2ca6,
- 0x2ca8, 0x2ca8,
- 0x2caa, 0x2caa,
- 0x2cac, 0x2cac,
- 0x2cae, 0x2cae,
- 0x2cb0, 0x2cb0,
- 0x2cb2, 0x2cb2,
- 0x2cb4, 0x2cb4,
- 0x2cb6, 0x2cb6,
- 0x2cb8, 0x2cb8,
- 0x2cba, 0x2cba,
- 0x2cbc, 0x2cbc,
- 0x2cbe, 0x2cbe,
- 0x2cc0, 0x2cc0,
- 0x2cc2, 0x2cc2,
- 0x2cc4, 0x2cc4,
- 0x2cc6, 0x2cc6,
- 0x2cc8, 0x2cc8,
- 0x2cca, 0x2cca,
- 0x2ccc, 0x2ccc,
- 0x2cce, 0x2cce,
- 0x2cd0, 0x2cd0,
- 0x2cd2, 0x2cd2,
- 0x2cd4, 0x2cd4,
- 0x2cd6, 0x2cd6,
- 0x2cd8, 0x2cd8,
- 0x2cda, 0x2cda,
- 0x2cdc, 0x2cdc,
- 0x2cde, 0x2cde,
- 0x2ce0, 0x2ce0,
- 0x2ce2, 0x2ce2,
- 0x2ceb, 0x2ceb,
- 0x2ced, 0x2ced,
- 0x2cf2, 0x2cf2,
- 0xa640, 0xa640,
- 0xa642, 0xa642,
- 0xa644, 0xa644,
- 0xa646, 0xa646,
- 0xa648, 0xa648,
- 0xa64a, 0xa64a,
- 0xa64c, 0xa64c,
- 0xa64e, 0xa64e,
- 0xa650, 0xa650,
- 0xa652, 0xa652,
- 0xa654, 0xa654,
- 0xa656, 0xa656,
- 0xa658, 0xa658,
- 0xa65a, 0xa65a,
- 0xa65c, 0xa65c,
- 0xa65e, 0xa65e,
- 0xa660, 0xa660,
- 0xa662, 0xa662,
- 0xa664, 0xa664,
- 0xa666, 0xa666,
- 0xa668, 0xa668,
- 0xa66a, 0xa66a,
- 0xa66c, 0xa66c,
- 0xa680, 0xa680,
- 0xa682, 0xa682,
- 0xa684, 0xa684,
- 0xa686, 0xa686,
- 0xa688, 0xa688,
- 0xa68a, 0xa68a,
- 0xa68c, 0xa68c,
- 0xa68e, 0xa68e,
- 0xa690, 0xa690,
- 0xa692, 0xa692,
- 0xa694, 0xa694,
- 0xa696, 0xa696,
- 0xa698, 0xa698,
- 0xa69a, 0xa69a,
- 0xa722, 0xa722,
- 0xa724, 0xa724,
- 0xa726, 0xa726,
- 0xa728, 0xa728,
- 0xa72a, 0xa72a,
- 0xa72c, 0xa72c,
- 0xa72e, 0xa72e,
- 0xa732, 0xa732,
- 0xa734, 0xa734,
- 0xa736, 0xa736,
- 0xa738, 0xa738,
- 0xa73a, 0xa73a,
- 0xa73c, 0xa73c,
- 0xa73e, 0xa73e,
- 0xa740, 0xa740,
- 0xa742, 0xa742,
- 0xa744, 0xa744,
- 0xa746, 0xa746,
- 0xa748, 0xa748,
- 0xa74a, 0xa74a,
- 0xa74c, 0xa74c,
- 0xa74e, 0xa74e,
- 0xa750, 0xa750,
- 0xa752, 0xa752,
- 0xa754, 0xa754,
- 0xa756, 0xa756,
- 0xa758, 0xa758,
- 0xa75a, 0xa75a,
- 0xa75c, 0xa75c,
- 0xa75e, 0xa75e,
- 0xa760, 0xa760,
- 0xa762, 0xa762,
- 0xa764, 0xa764,
- 0xa766, 0xa766,
- 0xa768, 0xa768,
- 0xa76a, 0xa76a,
- 0xa76c, 0xa76c,
- 0xa76e, 0xa76e,
- 0xa779, 0xa779,
- 0xa77b, 0xa77b,
- 0xa77d, 0xa77e,
- 0xa780, 0xa780,
- 0xa782, 0xa782,
- 0xa784, 0xa784,
- 0xa786, 0xa786,
- 0xa78b, 0xa78b,
- 0xa78d, 0xa78d,
- 0xa790, 0xa790,
- 0xa792, 0xa792,
- 0xa796, 0xa796,
- 0xa798, 0xa798,
- 0xa79a, 0xa79a,
- 0xa79c, 0xa79c,
- 0xa79e, 0xa79e,
- 0xa7a0, 0xa7a0,
- 0xa7a2, 0xa7a2,
- 0xa7a4, 0xa7a4,
- 0xa7a6, 0xa7a6,
- 0xa7a8, 0xa7a8,
- 0xa7aa, 0xa7ae,
- 0xa7b0, 0xa7b4,
- 0xa7b6, 0xa7b6,
- 0xa7b8, 0xa7b8,
- 0xa7ba, 0xa7ba,
- 0xa7bc, 0xa7bc,
- 0xa7be, 0xa7be,
- 0xa7c0, 0xa7c0,
- 0xa7c2, 0xa7c2,
- 0xa7c4, 0xa7c7,
- 0xa7c9, 0xa7c9,
- 0xa7d0, 0xa7d0,
- 0xa7d6, 0xa7d6,
- 0xa7d8, 0xa7d8,
- 0xa7f5, 0xa7f5,
- 0xff21, 0xff3a,
- 0x10400, 0x10427,
- 0x104b0, 0x104d3,
- 0x10570, 0x1057a,
- 0x1057c, 0x1058a,
- 0x1058c, 0x10592,
- 0x10594, 0x10595,
- 0x10c80, 0x10cb2,
- 0x118a0, 0x118bf,
- 0x16e40, 0x16e5f,
- 0x1d400, 0x1d419,
- 0x1d434, 0x1d44d,
- 0x1d468, 0x1d481,
- 0x1d49c, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 0x1d4a2, 0x1d4a2,
- 0x1d4a5, 0x1d4a6,
- 0x1d4a9, 0x1d4ac,
- 0x1d4ae, 0x1d4b5,
- 0x1d4d0, 0x1d4e9,
- 0x1d504, 0x1d505,
- 0x1d507, 0x1d50a,
- 0x1d50d, 0x1d514,
- 0x1d516, 0x1d51c,
- 0x1d538, 0x1d539,
- 0x1d53b, 0x1d53e,
- 0x1d540, 0x1d544,
- 0x1d546, 0x1d546,
- 0x1d54a, 0x1d550,
- 0x1d56c, 0x1d585,
- 0x1d5a0, 0x1d5b9,
- 0x1d5d4, 0x1d5ed,
- 0x1d608, 0x1d621,
- 0x1d63c, 0x1d655,
- 0x1d670, 0x1d689,
- 0x1d6a8, 0x1d6c0,
- 0x1d6e2, 0x1d6fa,
- 0x1d71c, 0x1d734,
- 0x1d756, 0x1d76e,
- 0x1d790, 0x1d7a8,
- 0x1d7ca, 0x1d7ca,
- 0x1e900, 0x1e921,
- 0x1f130, 0x1f149,
- 0x1f150, 0x1f169,
- 0x1f170, 0x1f189,
-}; /* CR_Upper */
-
-/* 'XDigit': [[:XDigit:]] */
-static const OnigCodePoint CR_XDigit[] = {
- 3,
- 0x0030, 0x0039,
- 0x0041, 0x0046,
- 0x0061, 0x0066,
-}; /* CR_XDigit */
-
-/* 'Word': [[:Word:]] */
-static const OnigCodePoint CR_Word[] = {
- 770,
- 0x0030, 0x0039,
- 0x0041, 0x005a,
- 0x005f, 0x005f,
- 0x0061, 0x007a,
- 0x00aa, 0x00aa,
- 0x00b5, 0x00b5,
- 0x00ba, 0x00ba,
- 0x00c0, 0x00d6,
- 0x00d8, 0x00f6,
- 0x00f8, 0x02c1,
- 0x02c6, 0x02d1,
- 0x02e0, 0x02e4,
- 0x02ec, 0x02ec,
- 0x02ee, 0x02ee,
- 0x0300, 0x0374,
- 0x0376, 0x0377,
- 0x037a, 0x037d,
- 0x037f, 0x037f,
- 0x0386, 0x0386,
- 0x0388, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03f5,
- 0x03f7, 0x0481,
- 0x0483, 0x052f,
- 0x0531, 0x0556,
- 0x0559, 0x0559,
- 0x0560, 0x0588,
- 0x0591, 0x05bd,
- 0x05bf, 0x05bf,
- 0x05c1, 0x05c2,
- 0x05c4, 0x05c5,
- 0x05c7, 0x05c7,
- 0x05d0, 0x05ea,
- 0x05ef, 0x05f2,
- 0x0610, 0x061a,
- 0x0620, 0x0669,
- 0x066e, 0x06d3,
- 0x06d5, 0x06dc,
- 0x06df, 0x06e8,
- 0x06ea, 0x06fc,
- 0x06ff, 0x06ff,
- 0x0710, 0x074a,
- 0x074d, 0x07b1,
- 0x07c0, 0x07f5,
- 0x07fa, 0x07fa,
- 0x07fd, 0x07fd,
- 0x0800, 0x082d,
- 0x0840, 0x085b,
- 0x0860, 0x086a,
- 0x0870, 0x0887,
- 0x0889, 0x088e,
- 0x0898, 0x08e1,
- 0x08e3, 0x0963,
- 0x0966, 0x096f,
- 0x0971, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09f1,
- 0x09fc, 0x09fc,
- 0x09fe, 0x09fe,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a51, 0x0a51,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a75,
- 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, 0x0aef,
- 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, 0x0b6f,
- 0x0b71, 0x0b71,
- 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,
- 0x0be6, 0x0bef,
- 0x0c00, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c39,
- 0x0c3c, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c58, 0x0c5a,
- 0x0c5d, 0x0c5d,
- 0x0c60, 0x0c63,
- 0x0c66, 0x0c6f,
- 0x0c80, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cdd, 0x0cde,
- 0x0ce0, 0x0ce3,
- 0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf3,
- 0x0d00, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d44,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4e,
- 0x0d54, 0x0d57,
- 0x0d5f, 0x0d63,
- 0x0d66, 0x0d6f,
- 0x0d7a, 0x0d7f,
- 0x0d81, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0de6, 0x0def,
- 0x0df2, 0x0df3,
- 0x0e01, 0x0e3a,
- 0x0e40, 0x0e4e,
- 0x0e50, 0x0e59,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e86, 0x0e8a,
- 0x0e8c, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ece,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f00,
- 0x0f18, 0x0f19,
- 0x0f20, 0x0f29,
- 0x0f35, 0x0f35,
- 0x0f37, 0x0f37,
- 0x0f39, 0x0f39,
- 0x0f3e, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f71, 0x0f84,
- 0x0f86, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x0fc6, 0x0fc6,
- 0x1000, 0x1049,
- 0x1050, 0x109d,
- 0x10a0, 0x10c5,
- 0x10c7, 0x10c7,
- 0x10cd, 0x10cd,
- 0x10d0, 0x10fa,
- 0x10fc, 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, 0x135f,
- 0x1380, 0x138f,
- 0x13a0, 0x13f5,
- 0x13f8, 0x13fd,
- 0x1401, 0x166c,
- 0x166f, 0x167f,
- 0x1681, 0x169a,
- 0x16a0, 0x16ea,
- 0x16ee, 0x16f8,
- 0x1700, 0x1715,
- 0x171f, 0x1734,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17d3,
- 0x17d7, 0x17d7,
- 0x17dc, 0x17dd,
- 0x17e0, 0x17e9,
- 0x180b, 0x180d,
- 0x180f, 0x1819,
- 0x1820, 0x1878,
- 0x1880, 0x18aa,
- 0x18b0, 0x18f5,
- 0x1900, 0x191e,
- 0x1920, 0x192b,
- 0x1930, 0x193b,
- 0x1946, 0x196d,
- 0x1970, 0x1974,
- 0x1980, 0x19ab,
- 0x19b0, 0x19c9,
- 0x19d0, 0x19d9,
- 0x1a00, 0x1a1b,
- 0x1a20, 0x1a5e,
- 0x1a60, 0x1a7c,
- 0x1a7f, 0x1a89,
- 0x1a90, 0x1a99,
- 0x1aa7, 0x1aa7,
- 0x1ab0, 0x1ace,
- 0x1b00, 0x1b4c,
- 0x1b50, 0x1b59,
- 0x1b6b, 0x1b73,
- 0x1b80, 0x1bf3,
- 0x1c00, 0x1c37,
- 0x1c40, 0x1c49,
- 0x1c4d, 0x1c7d,
- 0x1c80, 0x1c88,
- 0x1c90, 0x1cba,
- 0x1cbd, 0x1cbf,
- 0x1cd0, 0x1cd2,
- 0x1cd4, 0x1cfa,
- 0x1d00, 0x1f15,
- 0x1f18, 0x1f1d,
- 0x1f20, 0x1f45,
- 0x1f48, 0x1f4d,
- 0x1f50, 0x1f57,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f7d,
- 0x1f80, 0x1fb4,
- 0x1fb6, 0x1fbc,
- 0x1fbe, 0x1fbe,
- 0x1fc2, 0x1fc4,
- 0x1fc6, 0x1fcc,
- 0x1fd0, 0x1fd3,
- 0x1fd6, 0x1fdb,
- 0x1fe0, 0x1fec,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ffc,
- 0x203f, 0x2040,
- 0x2054, 0x2054,
- 0x2071, 0x2071,
- 0x207f, 0x207f,
- 0x2090, 0x209c,
- 0x20d0, 0x20f0,
- 0x2102, 0x2102,
- 0x2107, 0x2107,
- 0x210a, 0x2113,
- 0x2115, 0x2115,
- 0x2119, 0x211d,
- 0x2124, 0x2124,
- 0x2126, 0x2126,
- 0x2128, 0x2128,
- 0x212a, 0x212d,
- 0x212f, 0x2139,
- 0x213c, 0x213f,
- 0x2145, 0x2149,
- 0x214e, 0x214e,
- 0x2160, 0x2188,
- 0x24b6, 0x24e9,
- 0x2c00, 0x2ce4,
- 0x2ceb, 0x2cf3,
- 0x2d00, 0x2d25,
- 0x2d27, 0x2d27,
- 0x2d2d, 0x2d2d,
- 0x2d30, 0x2d67,
- 0x2d6f, 0x2d6f,
- 0x2d7f, 0x2d96,
- 0x2da0, 0x2da6,
- 0x2da8, 0x2dae,
- 0x2db0, 0x2db6,
- 0x2db8, 0x2dbe,
- 0x2dc0, 0x2dc6,
- 0x2dc8, 0x2dce,
- 0x2dd0, 0x2dd6,
- 0x2dd8, 0x2dde,
- 0x2de0, 0x2dff,
- 0x2e2f, 0x2e2f,
- 0x3005, 0x3007,
- 0x3021, 0x302f,
- 0x3031, 0x3035,
- 0x3038, 0x303c,
- 0x3041, 0x3096,
- 0x3099, 0x309a,
- 0x309d, 0x309f,
- 0x30a1, 0x30fa,
- 0x30fc, 0x30ff,
- 0x3105, 0x312f,
- 0x3131, 0x318e,
- 0x31a0, 0x31bf,
- 0x31f0, 0x31ff,
- 0x3400, 0x4dbf,
- 0x4e00, 0xa48c,
- 0xa4d0, 0xa4fd,
- 0xa500, 0xa60c,
- 0xa610, 0xa62b,
- 0xa640, 0xa672,
- 0xa674, 0xa67d,
- 0xa67f, 0xa6f1,
- 0xa717, 0xa71f,
- 0xa722, 0xa788,
- 0xa78b, 0xa7ca,
- 0xa7d0, 0xa7d1,
- 0xa7d3, 0xa7d3,
- 0xa7d5, 0xa7d9,
- 0xa7f2, 0xa827,
- 0xa82c, 0xa82c,
- 0xa840, 0xa873,
- 0xa880, 0xa8c5,
- 0xa8d0, 0xa8d9,
- 0xa8e0, 0xa8f7,
- 0xa8fb, 0xa8fb,
- 0xa8fd, 0xa92d,
- 0xa930, 0xa953,
- 0xa960, 0xa97c,
- 0xa980, 0xa9c0,
- 0xa9cf, 0xa9d9,
- 0xa9e0, 0xa9fe,
- 0xaa00, 0xaa36,
- 0xaa40, 0xaa4d,
- 0xaa50, 0xaa59,
- 0xaa60, 0xaa76,
- 0xaa7a, 0xaac2,
- 0xaadb, 0xaadd,
- 0xaae0, 0xaaef,
- 0xaaf2, 0xaaf6,
- 0xab01, 0xab06,
- 0xab09, 0xab0e,
- 0xab11, 0xab16,
- 0xab20, 0xab26,
- 0xab28, 0xab2e,
- 0xab30, 0xab5a,
- 0xab5c, 0xab69,
- 0xab70, 0xabea,
- 0xabec, 0xabed,
- 0xabf0, 0xabf9,
- 0xac00, 0xd7a3,
- 0xd7b0, 0xd7c6,
- 0xd7cb, 0xd7fb,
- 0xf900, 0xfa6d,
- 0xfa70, 0xfad9,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1d, 0xfb28,
- 0xfb2a, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbb1,
- 0xfbd3, 0xfd3d,
- 0xfd50, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdf0, 0xfdfb,
- 0xfe00, 0xfe0f,
- 0xfe20, 0xfe2f,
- 0xfe33, 0xfe34,
- 0xfe4d, 0xfe4f,
- 0xfe70, 0xfe74,
- 0xfe76, 0xfefc,
- 0xff10, 0xff19,
- 0xff21, 0xff3a,
- 0xff3f, 0xff3f,
- 0xff41, 0xff5a,
- 0xff66, 0xffbe,
- 0xffc2, 0xffc7,
- 0xffca, 0xffcf,
- 0xffd2, 0xffd7,
- 0xffda, 0xffdc,
- 0x10000, 0x1000b,
- 0x1000d, 0x10026,
- 0x10028, 0x1003a,
- 0x1003c, 0x1003d,
- 0x1003f, 0x1004d,
- 0x10050, 0x1005d,
- 0x10080, 0x100fa,
- 0x10140, 0x10174,
- 0x101fd, 0x101fd,
- 0x10280, 0x1029c,
- 0x102a0, 0x102d0,
- 0x102e0, 0x102e0,
- 0x10300, 0x1031f,
- 0x1032d, 0x1034a,
- 0x10350, 0x1037a,
- 0x10380, 0x1039d,
- 0x103a0, 0x103c3,
- 0x103c8, 0x103cf,
- 0x103d1, 0x103d5,
- 0x10400, 0x1049d,
- 0x104a0, 0x104a9,
- 0x104b0, 0x104d3,
- 0x104d8, 0x104fb,
- 0x10500, 0x10527,
- 0x10530, 0x10563,
- 0x10570, 0x1057a,
- 0x1057c, 0x1058a,
- 0x1058c, 0x10592,
- 0x10594, 0x10595,
- 0x10597, 0x105a1,
- 0x105a3, 0x105b1,
- 0x105b3, 0x105b9,
- 0x105bb, 0x105bc,
- 0x10600, 0x10736,
- 0x10740, 0x10755,
- 0x10760, 0x10767,
- 0x10780, 0x10785,
- 0x10787, 0x107b0,
- 0x107b2, 0x107ba,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x10855,
- 0x10860, 0x10876,
- 0x10880, 0x1089e,
- 0x108e0, 0x108f2,
- 0x108f4, 0x108f5,
- 0x10900, 0x10915,
- 0x10920, 0x10939,
- 0x10980, 0x109b7,
- 0x109be, 0x109bf,
- 0x10a00, 0x10a03,
- 0x10a05, 0x10a06,
- 0x10a0c, 0x10a13,
- 0x10a15, 0x10a17,
- 0x10a19, 0x10a35,
- 0x10a38, 0x10a3a,
- 0x10a3f, 0x10a3f,
- 0x10a60, 0x10a7c,
- 0x10a80, 0x10a9c,
- 0x10ac0, 0x10ac7,
- 0x10ac9, 0x10ae6,
- 0x10b00, 0x10b35,
- 0x10b40, 0x10b55,
- 0x10b60, 0x10b72,
- 0x10b80, 0x10b91,
- 0x10c00, 0x10c48,
- 0x10c80, 0x10cb2,
- 0x10cc0, 0x10cf2,
- 0x10d00, 0x10d27,
- 0x10d30, 0x10d39,
- 0x10e80, 0x10ea9,
- 0x10eab, 0x10eac,
- 0x10eb0, 0x10eb1,
- 0x10efd, 0x10f1c,
- 0x10f27, 0x10f27,
- 0x10f30, 0x10f50,
- 0x10f70, 0x10f85,
- 0x10fb0, 0x10fc4,
- 0x10fe0, 0x10ff6,
- 0x11000, 0x11046,
- 0x11066, 0x11075,
- 0x1107f, 0x110ba,
- 0x110c2, 0x110c2,
- 0x110d0, 0x110e8,
- 0x110f0, 0x110f9,
- 0x11100, 0x11134,
- 0x11136, 0x1113f,
- 0x11144, 0x11147,
- 0x11150, 0x11173,
- 0x11176, 0x11176,
- 0x11180, 0x111c4,
- 0x111c9, 0x111cc,
- 0x111ce, 0x111da,
- 0x111dc, 0x111dc,
- 0x11200, 0x11211,
- 0x11213, 0x11237,
- 0x1123e, 0x11241,
- 0x11280, 0x11286,
- 0x11288, 0x11288,
- 0x1128a, 0x1128d,
- 0x1128f, 0x1129d,
- 0x1129f, 0x112a8,
- 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, 0x1144a,
- 0x11450, 0x11459,
- 0x1145e, 0x11461,
- 0x11480, 0x114c5,
- 0x114c7, 0x114c7,
- 0x114d0, 0x114d9,
- 0x11580, 0x115b5,
- 0x115b8, 0x115c0,
- 0x115d8, 0x115dd,
- 0x11600, 0x11640,
- 0x11644, 0x11644,
- 0x11650, 0x11659,
- 0x11680, 0x116b8,
- 0x116c0, 0x116c9,
- 0x11700, 0x1171a,
- 0x1171d, 0x1172b,
- 0x11730, 0x11739,
- 0x11740, 0x11746,
- 0x11800, 0x1183a,
- 0x118a0, 0x118e9,
- 0x118ff, 0x11906,
- 0x11909, 0x11909,
- 0x1190c, 0x11913,
- 0x11915, 0x11916,
- 0x11918, 0x11935,
- 0x11937, 0x11938,
- 0x1193b, 0x11943,
- 0x11950, 0x11959,
- 0x119a0, 0x119a7,
- 0x119aa, 0x119d7,
- 0x119da, 0x119e1,
- 0x119e3, 0x119e4,
- 0x11a00, 0x11a3e,
- 0x11a47, 0x11a47,
- 0x11a50, 0x11a99,
- 0x11a9d, 0x11a9d,
- 0x11ab0, 0x11af8,
- 0x11c00, 0x11c08,
- 0x11c0a, 0x11c36,
- 0x11c38, 0x11c40,
- 0x11c50, 0x11c59,
- 0x11c72, 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, 0x11ef6,
- 0x11f00, 0x11f10,
- 0x11f12, 0x11f3a,
- 0x11f3e, 0x11f42,
- 0x11f50, 0x11f59,
- 0x11fb0, 0x11fb0,
- 0x12000, 0x12399,
- 0x12400, 0x1246e,
- 0x12480, 0x12543,
- 0x12f90, 0x12ff0,
- 0x13000, 0x1342f,
- 0x13440, 0x13455,
- 0x14400, 0x14646,
- 0x16800, 0x16a38,
- 0x16a40, 0x16a5e,
- 0x16a60, 0x16a69,
- 0x16a70, 0x16abe,
- 0x16ac0, 0x16ac9,
- 0x16ad0, 0x16aed,
- 0x16af0, 0x16af4,
- 0x16b00, 0x16b36,
- 0x16b40, 0x16b43,
- 0x16b50, 0x16b59,
- 0x16b63, 0x16b77,
- 0x16b7d, 0x16b8f,
- 0x16e40, 0x16e7f,
- 0x16f00, 0x16f4a,
- 0x16f4f, 0x16f87,
- 0x16f8f, 0x16f9f,
- 0x16fe0, 0x16fe1,
- 0x16fe3, 0x16fe4,
- 0x16ff0, 0x16ff1,
- 0x17000, 0x187f7,
- 0x18800, 0x18cd5,
- 0x18d00, 0x18d08,
- 0x1aff0, 0x1aff3,
- 0x1aff5, 0x1affb,
- 0x1affd, 0x1affe,
- 0x1b000, 0x1b122,
- 0x1b132, 0x1b132,
- 0x1b150, 0x1b152,
- 0x1b155, 0x1b155,
- 0x1b164, 0x1b167,
- 0x1b170, 0x1b2fb,
- 0x1bc00, 0x1bc6a,
- 0x1bc70, 0x1bc7c,
- 0x1bc80, 0x1bc88,
- 0x1bc90, 0x1bc99,
- 0x1bc9d, 0x1bc9e,
- 0x1cf00, 0x1cf2d,
- 0x1cf30, 0x1cf46,
- 0x1d165, 0x1d169,
- 0x1d16d, 0x1d172,
- 0x1d17b, 0x1d182,
- 0x1d185, 0x1d18b,
- 0x1d1aa, 0x1d1ad,
- 0x1d242, 0x1d244,
- 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, 0x1d6c0,
- 0x1d6c2, 0x1d6da,
- 0x1d6dc, 0x1d6fa,
- 0x1d6fc, 0x1d714,
- 0x1d716, 0x1d734,
- 0x1d736, 0x1d74e,
- 0x1d750, 0x1d76e,
- 0x1d770, 0x1d788,
- 0x1d78a, 0x1d7a8,
- 0x1d7aa, 0x1d7c2,
- 0x1d7c4, 0x1d7cb,
- 0x1d7ce, 0x1d7ff,
- 0x1da00, 0x1da36,
- 0x1da3b, 0x1da6c,
- 0x1da75, 0x1da75,
- 0x1da84, 0x1da84,
- 0x1da9b, 0x1da9f,
- 0x1daa1, 0x1daaf,
- 0x1df00, 0x1df1e,
- 0x1df25, 0x1df2a,
- 0x1e000, 0x1e006,
- 0x1e008, 0x1e018,
- 0x1e01b, 0x1e021,
- 0x1e023, 0x1e024,
- 0x1e026, 0x1e02a,
- 0x1e030, 0x1e06d,
- 0x1e08f, 0x1e08f,
- 0x1e100, 0x1e12c,
- 0x1e130, 0x1e13d,
- 0x1e140, 0x1e149,
- 0x1e14e, 0x1e14e,
- 0x1e290, 0x1e2ae,
- 0x1e2c0, 0x1e2f9,
- 0x1e4d0, 0x1e4f9,
- 0x1e7e0, 0x1e7e6,
- 0x1e7e8, 0x1e7eb,
- 0x1e7ed, 0x1e7ee,
- 0x1e7f0, 0x1e7fe,
- 0x1e800, 0x1e8c4,
- 0x1e8d0, 0x1e8d6,
- 0x1e900, 0x1e94b,
- 0x1e950, 0x1e959,
- 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,
- 0x1f130, 0x1f149,
- 0x1f150, 0x1f169,
- 0x1f170, 0x1f189,
- 0x1fbf0, 0x1fbf9,
- 0x20000, 0x2a6df,
- 0x2a700, 0x2b739,
- 0x2b740, 0x2b81d,
- 0x2b820, 0x2cea1,
- 0x2ceb0, 0x2ebe0,
- 0x2f800, 0x2fa1d,
- 0x30000, 0x3134a,
- 0x31350, 0x323af,
- 0xe0100, 0xe01ef,
-}; /* CR_Word */
-
-/* 'Alnum': [[:Alnum:]] */
-static const OnigCodePoint CR_Alnum[] = {
- 772,
- 0x0030, 0x0039,
- 0x0041, 0x005a,
- 0x0061, 0x007a,
- 0x00aa, 0x00aa,
- 0x00b5, 0x00b5,
- 0x00ba, 0x00ba,
- 0x00c0, 0x00d6,
- 0x00d8, 0x00f6,
- 0x00f8, 0x02c1,
- 0x02c6, 0x02d1,
- 0x02e0, 0x02e4,
- 0x02ec, 0x02ec,
- 0x02ee, 0x02ee,
- 0x0345, 0x0345,
- 0x0370, 0x0374,
- 0x0376, 0x0377,
- 0x037a, 0x037d,
- 0x037f, 0x037f,
- 0x0386, 0x0386,
- 0x0388, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03f5,
- 0x03f7, 0x0481,
- 0x048a, 0x052f,
- 0x0531, 0x0556,
- 0x0559, 0x0559,
- 0x0560, 0x0588,
- 0x05b0, 0x05bd,
- 0x05bf, 0x05bf,
- 0x05c1, 0x05c2,
- 0x05c4, 0x05c5,
- 0x05c7, 0x05c7,
- 0x05d0, 0x05ea,
- 0x05ef, 0x05f2,
- 0x0610, 0x061a,
- 0x0620, 0x0657,
- 0x0659, 0x0669,
- 0x066e, 0x06d3,
- 0x06d5, 0x06dc,
- 0x06e1, 0x06e8,
- 0x06ed, 0x06fc,
- 0x06ff, 0x06ff,
- 0x0710, 0x073f,
- 0x074d, 0x07b1,
- 0x07c0, 0x07ea,
- 0x07f4, 0x07f5,
- 0x07fa, 0x07fa,
- 0x0800, 0x0817,
- 0x081a, 0x082c,
- 0x0840, 0x0858,
- 0x0860, 0x086a,
- 0x0870, 0x0887,
- 0x0889, 0x088e,
- 0x08a0, 0x08c9,
- 0x08d4, 0x08df,
- 0x08e3, 0x08e9,
- 0x08f0, 0x093b,
- 0x093d, 0x094c,
- 0x094e, 0x0950,
- 0x0955, 0x0963,
- 0x0966, 0x096f,
- 0x0971, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bd, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09cc,
- 0x09ce, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09f1,
- 0x09fc, 0x09fc,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4c,
- 0x0a51, 0x0a51,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a75,
- 0x0a81, 0x0a83,
- 0x0a85, 0x0a8d,
- 0x0a8f, 0x0a91,
- 0x0a93, 0x0aa8,
- 0x0aaa, 0x0ab0,
- 0x0ab2, 0x0ab3,
- 0x0ab5, 0x0ab9,
- 0x0abd, 0x0ac5,
- 0x0ac7, 0x0ac9,
- 0x0acb, 0x0acc,
- 0x0ad0, 0x0ad0,
- 0x0ae0, 0x0ae3,
- 0x0ae6, 0x0aef,
- 0x0af9, 0x0afc,
- 0x0b01, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b35, 0x0b39,
- 0x0b3d, 0x0b44,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4c,
- 0x0b56, 0x0b57,
- 0x0b5c, 0x0b5d,
- 0x0b5f, 0x0b63,
- 0x0b66, 0x0b6f,
- 0x0b71, 0x0b71,
- 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, 0x0bcc,
- 0x0bd0, 0x0bd0,
- 0x0bd7, 0x0bd7,
- 0x0be6, 0x0bef,
- 0x0c00, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c39,
- 0x0c3d, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4c,
- 0x0c55, 0x0c56,
- 0x0c58, 0x0c5a,
- 0x0c5d, 0x0c5d,
- 0x0c60, 0x0c63,
- 0x0c66, 0x0c6f,
- 0x0c80, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbd, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccc,
- 0x0cd5, 0x0cd6,
- 0x0cdd, 0x0cde,
- 0x0ce0, 0x0ce3,
- 0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf3,
- 0x0d00, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d3a,
- 0x0d3d, 0x0d44,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4c,
- 0x0d4e, 0x0d4e,
- 0x0d54, 0x0d57,
- 0x0d5f, 0x0d63,
- 0x0d66, 0x0d6f,
- 0x0d7a, 0x0d7f,
- 0x0d81, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0de6, 0x0def,
- 0x0df2, 0x0df3,
- 0x0e01, 0x0e3a,
- 0x0e40, 0x0e46,
- 0x0e4d, 0x0e4d,
- 0x0e50, 0x0e59,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e86, 0x0e8a,
- 0x0e8c, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ecd, 0x0ecd,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f00,
- 0x0f20, 0x0f29,
- 0x0f40, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f71, 0x0f83,
- 0x0f88, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x1000, 0x1036,
- 0x1038, 0x1038,
- 0x103b, 0x1049,
- 0x1050, 0x109d,
- 0x10a0, 0x10c5,
- 0x10c7, 0x10c7,
- 0x10cd, 0x10cd,
- 0x10d0, 0x10fa,
- 0x10fc, 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,
- 0x1380, 0x138f,
- 0x13a0, 0x13f5,
- 0x13f8, 0x13fd,
- 0x1401, 0x166c,
- 0x166f, 0x167f,
- 0x1681, 0x169a,
- 0x16a0, 0x16ea,
- 0x16ee, 0x16f8,
- 0x1700, 0x1713,
- 0x171f, 0x1733,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17b3,
- 0x17b6, 0x17c8,
- 0x17d7, 0x17d7,
- 0x17dc, 0x17dc,
- 0x17e0, 0x17e9,
- 0x1810, 0x1819,
- 0x1820, 0x1878,
- 0x1880, 0x18aa,
- 0x18b0, 0x18f5,
- 0x1900, 0x191e,
- 0x1920, 0x192b,
- 0x1930, 0x1938,
- 0x1946, 0x196d,
- 0x1970, 0x1974,
- 0x1980, 0x19ab,
- 0x19b0, 0x19c9,
- 0x19d0, 0x19d9,
- 0x1a00, 0x1a1b,
- 0x1a20, 0x1a5e,
- 0x1a61, 0x1a74,
- 0x1a80, 0x1a89,
- 0x1a90, 0x1a99,
- 0x1aa7, 0x1aa7,
- 0x1abf, 0x1ac0,
- 0x1acc, 0x1ace,
- 0x1b00, 0x1b33,
- 0x1b35, 0x1b43,
- 0x1b45, 0x1b4c,
- 0x1b50, 0x1b59,
- 0x1b80, 0x1ba9,
- 0x1bac, 0x1be5,
- 0x1be7, 0x1bf1,
- 0x1c00, 0x1c36,
- 0x1c40, 0x1c49,
- 0x1c4d, 0x1c7d,
- 0x1c80, 0x1c88,
- 0x1c90, 0x1cba,
- 0x1cbd, 0x1cbf,
- 0x1ce9, 0x1cec,
- 0x1cee, 0x1cf3,
- 0x1cf5, 0x1cf6,
- 0x1cfa, 0x1cfa,
- 0x1d00, 0x1dbf,
- 0x1de7, 0x1df4,
- 0x1e00, 0x1f15,
- 0x1f18, 0x1f1d,
- 0x1f20, 0x1f45,
- 0x1f48, 0x1f4d,
- 0x1f50, 0x1f57,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f7d,
- 0x1f80, 0x1fb4,
- 0x1fb6, 0x1fbc,
- 0x1fbe, 0x1fbe,
- 0x1fc2, 0x1fc4,
- 0x1fc6, 0x1fcc,
- 0x1fd0, 0x1fd3,
- 0x1fd6, 0x1fdb,
- 0x1fe0, 0x1fec,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ffc,
- 0x2071, 0x2071,
- 0x207f, 0x207f,
- 0x2090, 0x209c,
- 0x2102, 0x2102,
- 0x2107, 0x2107,
- 0x210a, 0x2113,
- 0x2115, 0x2115,
- 0x2119, 0x211d,
- 0x2124, 0x2124,
- 0x2126, 0x2126,
- 0x2128, 0x2128,
- 0x212a, 0x212d,
- 0x212f, 0x2139,
- 0x213c, 0x213f,
- 0x2145, 0x2149,
- 0x214e, 0x214e,
- 0x2160, 0x2188,
- 0x24b6, 0x24e9,
- 0x2c00, 0x2ce4,
- 0x2ceb, 0x2cee,
- 0x2cf2, 0x2cf3,
- 0x2d00, 0x2d25,
- 0x2d27, 0x2d27,
- 0x2d2d, 0x2d2d,
- 0x2d30, 0x2d67,
- 0x2d6f, 0x2d6f,
- 0x2d80, 0x2d96,
- 0x2da0, 0x2da6,
- 0x2da8, 0x2dae,
- 0x2db0, 0x2db6,
- 0x2db8, 0x2dbe,
- 0x2dc0, 0x2dc6,
- 0x2dc8, 0x2dce,
- 0x2dd0, 0x2dd6,
- 0x2dd8, 0x2dde,
- 0x2de0, 0x2dff,
- 0x2e2f, 0x2e2f,
- 0x3005, 0x3007,
- 0x3021, 0x3029,
- 0x3031, 0x3035,
- 0x3038, 0x303c,
- 0x3041, 0x3096,
- 0x309d, 0x309f,
- 0x30a1, 0x30fa,
- 0x30fc, 0x30ff,
- 0x3105, 0x312f,
- 0x3131, 0x318e,
- 0x31a0, 0x31bf,
- 0x31f0, 0x31ff,
- 0x3400, 0x4dbf,
- 0x4e00, 0xa48c,
- 0xa4d0, 0xa4fd,
- 0xa500, 0xa60c,
- 0xa610, 0xa62b,
- 0xa640, 0xa66e,
- 0xa674, 0xa67b,
- 0xa67f, 0xa6ef,
- 0xa717, 0xa71f,
- 0xa722, 0xa788,
- 0xa78b, 0xa7ca,
- 0xa7d0, 0xa7d1,
- 0xa7d3, 0xa7d3,
- 0xa7d5, 0xa7d9,
- 0xa7f2, 0xa805,
- 0xa807, 0xa827,
- 0xa840, 0xa873,
- 0xa880, 0xa8c3,
- 0xa8c5, 0xa8c5,
- 0xa8d0, 0xa8d9,
- 0xa8f2, 0xa8f7,
- 0xa8fb, 0xa8fb,
- 0xa8fd, 0xa92a,
- 0xa930, 0xa952,
- 0xa960, 0xa97c,
- 0xa980, 0xa9b2,
- 0xa9b4, 0xa9bf,
- 0xa9cf, 0xa9d9,
- 0xa9e0, 0xa9fe,
- 0xaa00, 0xaa36,
- 0xaa40, 0xaa4d,
- 0xaa50, 0xaa59,
- 0xaa60, 0xaa76,
- 0xaa7a, 0xaabe,
- 0xaac0, 0xaac0,
- 0xaac2, 0xaac2,
- 0xaadb, 0xaadd,
- 0xaae0, 0xaaef,
- 0xaaf2, 0xaaf5,
- 0xab01, 0xab06,
- 0xab09, 0xab0e,
- 0xab11, 0xab16,
- 0xab20, 0xab26,
- 0xab28, 0xab2e,
- 0xab30, 0xab5a,
- 0xab5c, 0xab69,
- 0xab70, 0xabea,
- 0xabf0, 0xabf9,
- 0xac00, 0xd7a3,
- 0xd7b0, 0xd7c6,
- 0xd7cb, 0xd7fb,
- 0xf900, 0xfa6d,
- 0xfa70, 0xfad9,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1d, 0xfb28,
- 0xfb2a, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbb1,
- 0xfbd3, 0xfd3d,
- 0xfd50, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdf0, 0xfdfb,
- 0xfe70, 0xfe74,
- 0xfe76, 0xfefc,
- 0xff10, 0xff19,
- 0xff21, 0xff3a,
- 0xff41, 0xff5a,
- 0xff66, 0xffbe,
- 0xffc2, 0xffc7,
- 0xffca, 0xffcf,
- 0xffd2, 0xffd7,
- 0xffda, 0xffdc,
- 0x10000, 0x1000b,
- 0x1000d, 0x10026,
- 0x10028, 0x1003a,
- 0x1003c, 0x1003d,
- 0x1003f, 0x1004d,
- 0x10050, 0x1005d,
- 0x10080, 0x100fa,
- 0x10140, 0x10174,
- 0x10280, 0x1029c,
- 0x102a0, 0x102d0,
- 0x10300, 0x1031f,
- 0x1032d, 0x1034a,
- 0x10350, 0x1037a,
- 0x10380, 0x1039d,
- 0x103a0, 0x103c3,
- 0x103c8, 0x103cf,
- 0x103d1, 0x103d5,
- 0x10400, 0x1049d,
- 0x104a0, 0x104a9,
- 0x104b0, 0x104d3,
- 0x104d8, 0x104fb,
- 0x10500, 0x10527,
- 0x10530, 0x10563,
- 0x10570, 0x1057a,
- 0x1057c, 0x1058a,
- 0x1058c, 0x10592,
- 0x10594, 0x10595,
- 0x10597, 0x105a1,
- 0x105a3, 0x105b1,
- 0x105b3, 0x105b9,
- 0x105bb, 0x105bc,
- 0x10600, 0x10736,
- 0x10740, 0x10755,
- 0x10760, 0x10767,
- 0x10780, 0x10785,
- 0x10787, 0x107b0,
- 0x107b2, 0x107ba,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x10855,
- 0x10860, 0x10876,
- 0x10880, 0x1089e,
- 0x108e0, 0x108f2,
- 0x108f4, 0x108f5,
- 0x10900, 0x10915,
- 0x10920, 0x10939,
- 0x10980, 0x109b7,
- 0x109be, 0x109bf,
- 0x10a00, 0x10a03,
- 0x10a05, 0x10a06,
- 0x10a0c, 0x10a13,
- 0x10a15, 0x10a17,
- 0x10a19, 0x10a35,
- 0x10a60, 0x10a7c,
- 0x10a80, 0x10a9c,
- 0x10ac0, 0x10ac7,
- 0x10ac9, 0x10ae4,
- 0x10b00, 0x10b35,
- 0x10b40, 0x10b55,
- 0x10b60, 0x10b72,
- 0x10b80, 0x10b91,
- 0x10c00, 0x10c48,
- 0x10c80, 0x10cb2,
- 0x10cc0, 0x10cf2,
- 0x10d00, 0x10d27,
- 0x10d30, 0x10d39,
- 0x10e80, 0x10ea9,
- 0x10eab, 0x10eac,
- 0x10eb0, 0x10eb1,
- 0x10f00, 0x10f1c,
- 0x10f27, 0x10f27,
- 0x10f30, 0x10f45,
- 0x10f70, 0x10f81,
- 0x10fb0, 0x10fc4,
- 0x10fe0, 0x10ff6,
- 0x11000, 0x11045,
- 0x11066, 0x1106f,
- 0x11071, 0x11075,
- 0x11080, 0x110b8,
- 0x110c2, 0x110c2,
- 0x110d0, 0x110e8,
- 0x110f0, 0x110f9,
- 0x11100, 0x11132,
- 0x11136, 0x1113f,
- 0x11144, 0x11147,
- 0x11150, 0x11172,
- 0x11176, 0x11176,
- 0x11180, 0x111bf,
- 0x111c1, 0x111c4,
- 0x111ce, 0x111da,
- 0x111dc, 0x111dc,
- 0x11200, 0x11211,
- 0x11213, 0x11234,
- 0x11237, 0x11237,
- 0x1123e, 0x11241,
- 0x11280, 0x11286,
- 0x11288, 0x11288,
- 0x1128a, 0x1128d,
- 0x1128f, 0x1129d,
- 0x1129f, 0x112a8,
- 0x112b0, 0x112e8,
- 0x112f0, 0x112f9,
- 0x11300, 0x11303,
- 0x11305, 0x1130c,
- 0x1130f, 0x11310,
- 0x11313, 0x11328,
- 0x1132a, 0x11330,
- 0x11332, 0x11333,
- 0x11335, 0x11339,
- 0x1133d, 0x11344,
- 0x11347, 0x11348,
- 0x1134b, 0x1134c,
- 0x11350, 0x11350,
- 0x11357, 0x11357,
- 0x1135d, 0x11363,
- 0x11400, 0x11441,
- 0x11443, 0x11445,
- 0x11447, 0x1144a,
- 0x11450, 0x11459,
- 0x1145f, 0x11461,
- 0x11480, 0x114c1,
- 0x114c4, 0x114c5,
- 0x114c7, 0x114c7,
- 0x114d0, 0x114d9,
- 0x11580, 0x115b5,
- 0x115b8, 0x115be,
- 0x115d8, 0x115dd,
- 0x11600, 0x1163e,
- 0x11640, 0x11640,
- 0x11644, 0x11644,
- 0x11650, 0x11659,
- 0x11680, 0x116b5,
- 0x116b8, 0x116b8,
- 0x116c0, 0x116c9,
- 0x11700, 0x1171a,
- 0x1171d, 0x1172a,
- 0x11730, 0x11739,
- 0x11740, 0x11746,
- 0x11800, 0x11838,
- 0x118a0, 0x118e9,
- 0x118ff, 0x11906,
- 0x11909, 0x11909,
- 0x1190c, 0x11913,
- 0x11915, 0x11916,
- 0x11918, 0x11935,
- 0x11937, 0x11938,
- 0x1193b, 0x1193c,
- 0x1193f, 0x11942,
- 0x11950, 0x11959,
- 0x119a0, 0x119a7,
- 0x119aa, 0x119d7,
- 0x119da, 0x119df,
- 0x119e1, 0x119e1,
- 0x119e3, 0x119e4,
- 0x11a00, 0x11a32,
- 0x11a35, 0x11a3e,
- 0x11a50, 0x11a97,
- 0x11a9d, 0x11a9d,
- 0x11ab0, 0x11af8,
- 0x11c00, 0x11c08,
- 0x11c0a, 0x11c36,
- 0x11c38, 0x11c3e,
- 0x11c40, 0x11c40,
- 0x11c50, 0x11c59,
- 0x11c72, 0x11c8f,
- 0x11c92, 0x11ca7,
- 0x11ca9, 0x11cb6,
- 0x11d00, 0x11d06,
- 0x11d08, 0x11d09,
- 0x11d0b, 0x11d36,
- 0x11d3a, 0x11d3a,
- 0x11d3c, 0x11d3d,
- 0x11d3f, 0x11d41,
- 0x11d43, 0x11d43,
- 0x11d46, 0x11d47,
- 0x11d50, 0x11d59,
- 0x11d60, 0x11d65,
- 0x11d67, 0x11d68,
- 0x11d6a, 0x11d8e,
- 0x11d90, 0x11d91,
- 0x11d93, 0x11d96,
- 0x11d98, 0x11d98,
- 0x11da0, 0x11da9,
- 0x11ee0, 0x11ef6,
- 0x11f00, 0x11f10,
- 0x11f12, 0x11f3a,
- 0x11f3e, 0x11f40,
- 0x11f50, 0x11f59,
- 0x11fb0, 0x11fb0,
- 0x12000, 0x12399,
- 0x12400, 0x1246e,
- 0x12480, 0x12543,
- 0x12f90, 0x12ff0,
- 0x13000, 0x1342f,
- 0x13441, 0x13446,
- 0x14400, 0x14646,
- 0x16800, 0x16a38,
- 0x16a40, 0x16a5e,
- 0x16a60, 0x16a69,
- 0x16a70, 0x16abe,
- 0x16ac0, 0x16ac9,
- 0x16ad0, 0x16aed,
- 0x16b00, 0x16b2f,
- 0x16b40, 0x16b43,
- 0x16b50, 0x16b59,
- 0x16b63, 0x16b77,
- 0x16b7d, 0x16b8f,
- 0x16e40, 0x16e7f,
- 0x16f00, 0x16f4a,
- 0x16f4f, 0x16f87,
- 0x16f8f, 0x16f9f,
- 0x16fe0, 0x16fe1,
- 0x16fe3, 0x16fe3,
- 0x16ff0, 0x16ff1,
- 0x17000, 0x187f7,
- 0x18800, 0x18cd5,
- 0x18d00, 0x18d08,
- 0x1aff0, 0x1aff3,
- 0x1aff5, 0x1affb,
- 0x1affd, 0x1affe,
- 0x1b000, 0x1b122,
- 0x1b132, 0x1b132,
- 0x1b150, 0x1b152,
- 0x1b155, 0x1b155,
- 0x1b164, 0x1b167,
- 0x1b170, 0x1b2fb,
- 0x1bc00, 0x1bc6a,
- 0x1bc70, 0x1bc7c,
- 0x1bc80, 0x1bc88,
- 0x1bc90, 0x1bc99,
- 0x1bc9e, 0x1bc9e,
- 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, 0x1d6c0,
- 0x1d6c2, 0x1d6da,
- 0x1d6dc, 0x1d6fa,
- 0x1d6fc, 0x1d714,
- 0x1d716, 0x1d734,
- 0x1d736, 0x1d74e,
- 0x1d750, 0x1d76e,
- 0x1d770, 0x1d788,
- 0x1d78a, 0x1d7a8,
- 0x1d7aa, 0x1d7c2,
- 0x1d7c4, 0x1d7cb,
- 0x1d7ce, 0x1d7ff,
- 0x1df00, 0x1df1e,
- 0x1df25, 0x1df2a,
- 0x1e000, 0x1e006,
- 0x1e008, 0x1e018,
- 0x1e01b, 0x1e021,
- 0x1e023, 0x1e024,
- 0x1e026, 0x1e02a,
- 0x1e030, 0x1e06d,
- 0x1e08f, 0x1e08f,
- 0x1e100, 0x1e12c,
- 0x1e137, 0x1e13d,
- 0x1e140, 0x1e149,
- 0x1e14e, 0x1e14e,
- 0x1e290, 0x1e2ad,
- 0x1e2c0, 0x1e2eb,
- 0x1e2f0, 0x1e2f9,
- 0x1e4d0, 0x1e4eb,
- 0x1e4f0, 0x1e4f9,
- 0x1e7e0, 0x1e7e6,
- 0x1e7e8, 0x1e7eb,
- 0x1e7ed, 0x1e7ee,
- 0x1e7f0, 0x1e7fe,
- 0x1e800, 0x1e8c4,
- 0x1e900, 0x1e943,
- 0x1e947, 0x1e947,
- 0x1e94b, 0x1e94b,
- 0x1e950, 0x1e959,
- 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,
- 0x1f130, 0x1f149,
- 0x1f150, 0x1f169,
- 0x1f170, 0x1f189,
- 0x1fbf0, 0x1fbf9,
- 0x20000, 0x2a6df,
- 0x2a700, 0x2b739,
- 0x2b740, 0x2b81d,
- 0x2b820, 0x2cea1,
- 0x2ceb0, 0x2ebe0,
- 0x2f800, 0x2fa1d,
- 0x30000, 0x3134a,
- 0x31350, 0x323af,
-}; /* CR_Alnum */
-
-/* 'ASCII': [[:ASCII:]] */
-static const OnigCodePoint CR_ASCII[] = {
- 1,
- 0x0000, 0x007f,
-}; /* CR_ASCII */
-
-/* 'Punct': [[:Punct:]] */
-static const OnigCodePoint CR_Punct[] = {
- 191,
- 0x0021, 0x0023,
- 0x0025, 0x002a,
- 0x002c, 0x002f,
- 0x003a, 0x003b,
- 0x003f, 0x0040,
- 0x005b, 0x005d,
- 0x005f, 0x005f,
- 0x007b, 0x007b,
- 0x007d, 0x007d,
- 0x00a1, 0x00a1,
- 0x00a7, 0x00a7,
- 0x00ab, 0x00ab,
- 0x00b6, 0x00b7,
- 0x00bb, 0x00bb,
- 0x00bf, 0x00bf,
- 0x037e, 0x037e,
- 0x0387, 0x0387,
- 0x055a, 0x055f,
- 0x0589, 0x058a,
- 0x05be, 0x05be,
- 0x05c0, 0x05c0,
- 0x05c3, 0x05c3,
- 0x05c6, 0x05c6,
- 0x05f3, 0x05f4,
- 0x0609, 0x060a,
- 0x060c, 0x060d,
- 0x061b, 0x061b,
- 0x061d, 0x061f,
- 0x066a, 0x066d,
- 0x06d4, 0x06d4,
- 0x0700, 0x070d,
- 0x07f7, 0x07f9,
- 0x0830, 0x083e,
- 0x085e, 0x085e,
- 0x0964, 0x0965,
- 0x0970, 0x0970,
- 0x09fd, 0x09fd,
- 0x0a76, 0x0a76,
- 0x0af0, 0x0af0,
- 0x0c77, 0x0c77,
- 0x0c84, 0x0c84,
- 0x0df4, 0x0df4,
- 0x0e4f, 0x0e4f,
- 0x0e5a, 0x0e5b,
- 0x0f04, 0x0f12,
- 0x0f14, 0x0f14,
- 0x0f3a, 0x0f3d,
- 0x0f85, 0x0f85,
- 0x0fd0, 0x0fd4,
- 0x0fd9, 0x0fda,
- 0x104a, 0x104f,
- 0x10fb, 0x10fb,
- 0x1360, 0x1368,
- 0x1400, 0x1400,
- 0x166e, 0x166e,
- 0x169b, 0x169c,
- 0x16eb, 0x16ed,
- 0x1735, 0x1736,
- 0x17d4, 0x17d6,
- 0x17d8, 0x17da,
- 0x1800, 0x180a,
- 0x1944, 0x1945,
- 0x1a1e, 0x1a1f,
- 0x1aa0, 0x1aa6,
- 0x1aa8, 0x1aad,
- 0x1b5a, 0x1b60,
- 0x1b7d, 0x1b7e,
- 0x1bfc, 0x1bff,
- 0x1c3b, 0x1c3f,
- 0x1c7e, 0x1c7f,
- 0x1cc0, 0x1cc7,
- 0x1cd3, 0x1cd3,
- 0x2010, 0x2027,
- 0x2030, 0x2043,
- 0x2045, 0x2051,
- 0x2053, 0x205e,
- 0x207d, 0x207e,
- 0x208d, 0x208e,
- 0x2308, 0x230b,
- 0x2329, 0x232a,
- 0x2768, 0x2775,
- 0x27c5, 0x27c6,
- 0x27e6, 0x27ef,
- 0x2983, 0x2998,
- 0x29d8, 0x29db,
- 0x29fc, 0x29fd,
- 0x2cf9, 0x2cfc,
- 0x2cfe, 0x2cff,
- 0x2d70, 0x2d70,
- 0x2e00, 0x2e2e,
- 0x2e30, 0x2e4f,
- 0x2e52, 0x2e5d,
- 0x3001, 0x3003,
- 0x3008, 0x3011,
- 0x3014, 0x301f,
- 0x3030, 0x3030,
- 0x303d, 0x303d,
- 0x30a0, 0x30a0,
- 0x30fb, 0x30fb,
- 0xa4fe, 0xa4ff,
- 0xa60d, 0xa60f,
- 0xa673, 0xa673,
- 0xa67e, 0xa67e,
- 0xa6f2, 0xa6f7,
- 0xa874, 0xa877,
- 0xa8ce, 0xa8cf,
- 0xa8f8, 0xa8fa,
- 0xa8fc, 0xa8fc,
- 0xa92e, 0xa92f,
- 0xa95f, 0xa95f,
- 0xa9c1, 0xa9cd,
- 0xa9de, 0xa9df,
- 0xaa5c, 0xaa5f,
- 0xaade, 0xaadf,
- 0xaaf0, 0xaaf1,
- 0xabeb, 0xabeb,
- 0xfd3e, 0xfd3f,
- 0xfe10, 0xfe19,
- 0xfe30, 0xfe52,
- 0xfe54, 0xfe61,
- 0xfe63, 0xfe63,
- 0xfe68, 0xfe68,
- 0xfe6a, 0xfe6b,
- 0xff01, 0xff03,
- 0xff05, 0xff0a,
- 0xff0c, 0xff0f,
- 0xff1a, 0xff1b,
- 0xff1f, 0xff20,
- 0xff3b, 0xff3d,
- 0xff3f, 0xff3f,
- 0xff5b, 0xff5b,
- 0xff5d, 0xff5d,
- 0xff5f, 0xff65,
- 0x10100, 0x10102,
- 0x1039f, 0x1039f,
- 0x103d0, 0x103d0,
- 0x1056f, 0x1056f,
- 0x10857, 0x10857,
- 0x1091f, 0x1091f,
- 0x1093f, 0x1093f,
- 0x10a50, 0x10a58,
- 0x10a7f, 0x10a7f,
- 0x10af0, 0x10af6,
- 0x10b39, 0x10b3f,
- 0x10b99, 0x10b9c,
- 0x10ead, 0x10ead,
- 0x10f55, 0x10f59,
- 0x10f86, 0x10f89,
- 0x11047, 0x1104d,
- 0x110bb, 0x110bc,
- 0x110be, 0x110c1,
- 0x11140, 0x11143,
- 0x11174, 0x11175,
- 0x111c5, 0x111c8,
- 0x111cd, 0x111cd,
- 0x111db, 0x111db,
- 0x111dd, 0x111df,
- 0x11238, 0x1123d,
- 0x112a9, 0x112a9,
- 0x1144b, 0x1144f,
- 0x1145a, 0x1145b,
- 0x1145d, 0x1145d,
- 0x114c6, 0x114c6,
- 0x115c1, 0x115d7,
- 0x11641, 0x11643,
- 0x11660, 0x1166c,
- 0x116b9, 0x116b9,
- 0x1173c, 0x1173e,
- 0x1183b, 0x1183b,
- 0x11944, 0x11946,
- 0x119e2, 0x119e2,
- 0x11a3f, 0x11a46,
- 0x11a9a, 0x11a9c,
- 0x11a9e, 0x11aa2,
- 0x11b00, 0x11b09,
- 0x11c41, 0x11c45,
- 0x11c70, 0x11c71,
- 0x11ef7, 0x11ef8,
- 0x11f43, 0x11f4f,
- 0x11fff, 0x11fff,
- 0x12470, 0x12474,
- 0x12ff1, 0x12ff2,
- 0x16a6e, 0x16a6f,
- 0x16af5, 0x16af5,
- 0x16b37, 0x16b3b,
- 0x16b44, 0x16b44,
- 0x16e97, 0x16e9a,
- 0x16fe2, 0x16fe2,
- 0x1bc9f, 0x1bc9f,
- 0x1da87, 0x1da8b,
- 0x1e95e, 0x1e95f,
-}; /* CR_Punct */
-
-#ifdef USE_UNICODE_PROPERTIES
-/* 'Any': - */
-static const OnigCodePoint CR_Any[] = {
- 1,
- 0x0000, 0x10ffff,
-}; /* CR_Any */
-
-/* 'Assigned': - */
-static const OnigCodePoint CR_Assigned[] = {
- 707,
- 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, 0x070d,
- 0x070f, 0x074a,
- 0x074d, 0x07b1,
- 0x07c0, 0x07fa,
- 0x07fd, 0x082d,
- 0x0830, 0x083e,
- 0x0840, 0x085b,
- 0x085e, 0x085e,
- 0x0860, 0x086a,
- 0x0870, 0x088e,
- 0x0890, 0x0891,
- 0x0898, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fe,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a51, 0x0a51,
- 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,
- 0x0be6, 0x0bfa,
- 0x0c00, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c39,
- 0x0c3c, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c58, 0x0c5a,
- 0x0c5d, 0x0c5d,
- 0x0c60, 0x0c63,
- 0x0c66, 0x0c6f,
- 0x0c77, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cdd, 0x0cde,
- 0x0ce0, 0x0ce3,
- 0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf3,
- 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, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 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, 0x0ece,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f71, 0x0f97,
- 0x0f99, 0x0fbc,
- 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, 0x1715,
- 0x171f, 0x1736,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17dd,
- 0x17e0, 0x17e9,
- 0x17f0, 0x17f9,
- 0x1800, 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, 0x1ace,
- 0x1b00, 0x1b4c,
- 0x1b50, 0x1b7e,
- 0x1b80, 0x1bf3,
- 0x1bfc, 0x1c37,
- 0x1c3b, 0x1c49,
- 0x1c4d, 0x1c88,
- 0x1c90, 0x1cba,
- 0x1cbd, 0x1cc7,
- 0x1cd0, 0x1cfa,
- 0x1d00, 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, 0x20c0,
- 0x20d0, 0x20f0,
- 0x2100, 0x218b,
- 0x2190, 0x2426,
- 0x2440, 0x244a,
- 0x2460, 0x2b73,
- 0x2b76, 0x2b95,
- 0x2b97, 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, 0x2e5d,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x303f,
- 0x3041, 0x3096,
- 0x3099, 0x30ff,
- 0x3105, 0x312f,
- 0x3131, 0x318e,
- 0x3190, 0x31e3,
- 0x31f0, 0x321e,
- 0x3220, 0xa48c,
- 0xa490, 0xa4c6,
- 0xa4d0, 0xa62b,
- 0xa640, 0xa6f7,
- 0xa700, 0xa7ca,
- 0xa7d0, 0xa7d1,
- 0xa7d3, 0xa7d3,
- 0xa7d5, 0xa7d9,
- 0xa7f2, 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, 0xfbc2,
- 0xfbd3, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdcf, 0xfdcf,
- 0xfdf0, 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, 0xfffd,
- 0x10000, 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, 0x1057a,
- 0x1057c, 0x1058a,
- 0x1058c, 0x10592,
- 0x10594, 0x10595,
- 0x10597, 0x105a1,
- 0x105a3, 0x105b1,
- 0x105b3, 0x105b9,
- 0x105bb, 0x105bc,
- 0x10600, 0x10736,
- 0x10740, 0x10755,
- 0x10760, 0x10767,
- 0x10780, 0x10785,
- 0x10787, 0x107b0,
- 0x107b2, 0x107ba,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 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,
- 0x10efd, 0x10f27,
- 0x10f30, 0x10f59,
- 0x10f70, 0x10f89,
- 0x10fb0, 0x10fcb,
- 0x10fe0, 0x10ff6,
- 0x11000, 0x1104d,
- 0x11052, 0x11075,
- 0x1107f, 0x110c2,
- 0x110cd, 0x110cd,
- 0x110d0, 0x110e8,
- 0x110f0, 0x110f9,
- 0x11100, 0x11134,
- 0x11136, 0x11147,
- 0x11150, 0x11176,
- 0x11180, 0x111df,
- 0x111e1, 0x111f4,
- 0x11200, 0x11211,
- 0x11213, 0x11241,
- 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, 0x116b9,
- 0x116c0, 0x116c9,
- 0x11700, 0x1171a,
- 0x1171d, 0x1172b,
- 0x11730, 0x11746,
- 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,
- 0x11ab0, 0x11af8,
- 0x11b00, 0x11b09,
- 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,
- 0x11f00, 0x11f10,
- 0x11f12, 0x11f3a,
- 0x11f3e, 0x11f59,
- 0x11fb0, 0x11fb0,
- 0x11fc0, 0x11ff1,
- 0x11fff, 0x12399,
- 0x12400, 0x1246e,
- 0x12470, 0x12474,
- 0x12480, 0x12543,
- 0x12f90, 0x12ff2,
- 0x13000, 0x13455,
- 0x14400, 0x14646,
- 0x16800, 0x16a38,
- 0x16a40, 0x16a5e,
- 0x16a60, 0x16a69,
- 0x16a6e, 0x16abe,
- 0x16ac0, 0x16ac9,
- 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,
- 0x1aff0, 0x1aff3,
- 0x1aff5, 0x1affb,
- 0x1affd, 0x1affe,
- 0x1b000, 0x1b122,
- 0x1b132, 0x1b132,
- 0x1b150, 0x1b152,
- 0x1b155, 0x1b155,
- 0x1b164, 0x1b167,
- 0x1b170, 0x1b2fb,
- 0x1bc00, 0x1bc6a,
- 0x1bc70, 0x1bc7c,
- 0x1bc80, 0x1bc88,
- 0x1bc90, 0x1bc99,
- 0x1bc9c, 0x1bca3,
- 0x1cf00, 0x1cf2d,
- 0x1cf30, 0x1cf46,
- 0x1cf50, 0x1cfc3,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d129, 0x1d1ea,
- 0x1d200, 0x1d245,
- 0x1d2c0, 0x1d2d3,
- 0x1d2e0, 0x1d2f3,
- 0x1d300, 0x1d356,
- 0x1d360, 0x1d378,
- 0x1d400, 0x1d454,
- 0x1d456, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 0x1d4a2, 0x1d4a2,
- 0x1d4a5, 0x1d4a6,
- 0x1d4a9, 0x1d4ac,
- 0x1d4ae, 0x1d4b9,
- 0x1d4bb, 0x1d4bb,
- 0x1d4bd, 0x1d4c3,
- 0x1d4c5, 0x1d505,
- 0x1d507, 0x1d50a,
- 0x1d50d, 0x1d514,
- 0x1d516, 0x1d51c,
- 0x1d51e, 0x1d539,
- 0x1d53b, 0x1d53e,
- 0x1d540, 0x1d544,
- 0x1d546, 0x1d546,
- 0x1d54a, 0x1d550,
- 0x1d552, 0x1d6a5,
- 0x1d6a8, 0x1d7cb,
- 0x1d7ce, 0x1da8b,
- 0x1da9b, 0x1da9f,
- 0x1daa1, 0x1daaf,
- 0x1df00, 0x1df1e,
- 0x1df25, 0x1df2a,
- 0x1e000, 0x1e006,
- 0x1e008, 0x1e018,
- 0x1e01b, 0x1e021,
- 0x1e023, 0x1e024,
- 0x1e026, 0x1e02a,
- 0x1e030, 0x1e06d,
- 0x1e08f, 0x1e08f,
- 0x1e100, 0x1e12c,
- 0x1e130, 0x1e13d,
- 0x1e140, 0x1e149,
- 0x1e14e, 0x1e14f,
- 0x1e290, 0x1e2ae,
- 0x1e2c0, 0x1e2f9,
- 0x1e2ff, 0x1e2ff,
- 0x1e4d0, 0x1e4f9,
- 0x1e7e0, 0x1e7e6,
- 0x1e7e8, 0x1e7eb,
- 0x1e7ed, 0x1e7ee,
- 0x1e7f0, 0x1e7fe,
- 0x1e800, 0x1e8c4,
- 0x1e8c7, 0x1e8d6,
- 0x1e900, 0x1e94b,
- 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,
- 0x1f6dc, 0x1f6ec,
- 0x1f6f0, 0x1f6fc,
- 0x1f700, 0x1f776,
- 0x1f77b, 0x1f7d9,
- 0x1f7e0, 0x1f7eb,
- 0x1f7f0, 0x1f7f0,
- 0x1f800, 0x1f80b,
- 0x1f810, 0x1f847,
- 0x1f850, 0x1f859,
- 0x1f860, 0x1f887,
- 0x1f890, 0x1f8ad,
- 0x1f8b0, 0x1f8b1,
- 0x1f900, 0x1fa53,
- 0x1fa60, 0x1fa6d,
- 0x1fa70, 0x1fa7c,
- 0x1fa80, 0x1fa88,
- 0x1fa90, 0x1fabd,
- 0x1fabf, 0x1fac5,
- 0x1face, 0x1fadb,
- 0x1fae0, 0x1fae8,
- 0x1faf0, 0x1faf8,
- 0x1fb00, 0x1fb92,
- 0x1fb94, 0x1fbca,
- 0x1fbf0, 0x1fbf9,
- 0x20000, 0x2a6df,
- 0x2a700, 0x2b739,
- 0x2b740, 0x2b81d,
- 0x2b820, 0x2cea1,
- 0x2ceb0, 0x2ebe0,
- 0x2f800, 0x2fa1d,
- 0x30000, 0x3134a,
- 0x31350, 0x323af,
- 0xe0001, 0xe0001,
- 0xe0020, 0xe007f,
- 0xe0100, 0xe01ef,
- 0xf0000, 0xffffd,
- 0x100000, 0x10fffd,
-}; /* CR_Assigned */
-
-/* 'C': Major Category */
-static const OnigCodePoint CR_C[] = {
- 712,
- 0x0000, 0x001f,
- 0x007f, 0x009f,
- 0x00ad, 0x00ad,
- 0x0378, 0x0379,
- 0x0380, 0x0383,
- 0x038b, 0x038b,
- 0x038d, 0x038d,
- 0x03a2, 0x03a2,
- 0x0530, 0x0530,
- 0x0557, 0x0558,
- 0x058b, 0x058c,
- 0x0590, 0x0590,
- 0x05c8, 0x05cf,
- 0x05eb, 0x05ee,
- 0x05f5, 0x0605,
- 0x061c, 0x061c,
- 0x06dd, 0x06dd,
- 0x070e, 0x070f,
- 0x074b, 0x074c,
- 0x07b2, 0x07bf,
- 0x07fb, 0x07fc,
- 0x082e, 0x082f,
- 0x083f, 0x083f,
- 0x085c, 0x085d,
- 0x085f, 0x085f,
- 0x086b, 0x086f,
- 0x088f, 0x0897,
- 0x08e2, 0x08e2,
- 0x0984, 0x0984,
- 0x098d, 0x098e,
- 0x0991, 0x0992,
- 0x09a9, 0x09a9,
- 0x09b1, 0x09b1,
- 0x09b3, 0x09b5,
- 0x09ba, 0x09bb,
- 0x09c5, 0x09c6,
- 0x09c9, 0x09ca,
- 0x09cf, 0x09d6,
- 0x09d8, 0x09db,
- 0x09de, 0x09de,
- 0x09e4, 0x09e5,
- 0x09ff, 0x0a00,
- 0x0a04, 0x0a04,
- 0x0a0b, 0x0a0e,
- 0x0a11, 0x0a12,
- 0x0a29, 0x0a29,
- 0x0a31, 0x0a31,
- 0x0a34, 0x0a34,
- 0x0a37, 0x0a37,
- 0x0a3a, 0x0a3b,
- 0x0a3d, 0x0a3d,
- 0x0a43, 0x0a46,
- 0x0a49, 0x0a4a,
- 0x0a4e, 0x0a50,
- 0x0a52, 0x0a58,
- 0x0a5d, 0x0a5d,
- 0x0a5f, 0x0a65,
- 0x0a77, 0x0a80,
- 0x0a84, 0x0a84,
- 0x0a8e, 0x0a8e,
- 0x0a92, 0x0a92,
- 0x0aa9, 0x0aa9,
- 0x0ab1, 0x0ab1,
- 0x0ab4, 0x0ab4,
- 0x0aba, 0x0abb,
- 0x0ac6, 0x0ac6,
- 0x0aca, 0x0aca,
- 0x0ace, 0x0acf,
- 0x0ad1, 0x0adf,
- 0x0ae4, 0x0ae5,
- 0x0af2, 0x0af8,
- 0x0b00, 0x0b00,
- 0x0b04, 0x0b04,
- 0x0b0d, 0x0b0e,
- 0x0b11, 0x0b12,
- 0x0b29, 0x0b29,
- 0x0b31, 0x0b31,
- 0x0b34, 0x0b34,
- 0x0b3a, 0x0b3b,
- 0x0b45, 0x0b46,
- 0x0b49, 0x0b4a,
- 0x0b4e, 0x0b54,
- 0x0b58, 0x0b5b,
- 0x0b5e, 0x0b5e,
- 0x0b64, 0x0b65,
- 0x0b78, 0x0b81,
- 0x0b84, 0x0b84,
- 0x0b8b, 0x0b8d,
- 0x0b91, 0x0b91,
- 0x0b96, 0x0b98,
- 0x0b9b, 0x0b9b,
- 0x0b9d, 0x0b9d,
- 0x0ba0, 0x0ba2,
- 0x0ba5, 0x0ba7,
- 0x0bab, 0x0bad,
- 0x0bba, 0x0bbd,
- 0x0bc3, 0x0bc5,
- 0x0bc9, 0x0bc9,
- 0x0bce, 0x0bcf,
- 0x0bd1, 0x0bd6,
- 0x0bd8, 0x0be5,
- 0x0bfb, 0x0bff,
- 0x0c0d, 0x0c0d,
- 0x0c11, 0x0c11,
- 0x0c29, 0x0c29,
- 0x0c3a, 0x0c3b,
- 0x0c45, 0x0c45,
- 0x0c49, 0x0c49,
- 0x0c4e, 0x0c54,
- 0x0c57, 0x0c57,
- 0x0c5b, 0x0c5c,
- 0x0c5e, 0x0c5f,
- 0x0c64, 0x0c65,
- 0x0c70, 0x0c76,
- 0x0c8d, 0x0c8d,
- 0x0c91, 0x0c91,
- 0x0ca9, 0x0ca9,
- 0x0cb4, 0x0cb4,
- 0x0cba, 0x0cbb,
- 0x0cc5, 0x0cc5,
- 0x0cc9, 0x0cc9,
- 0x0cce, 0x0cd4,
- 0x0cd7, 0x0cdc,
- 0x0cdf, 0x0cdf,
- 0x0ce4, 0x0ce5,
- 0x0cf0, 0x0cf0,
- 0x0cf4, 0x0cff,
- 0x0d0d, 0x0d0d,
- 0x0d11, 0x0d11,
- 0x0d45, 0x0d45,
- 0x0d49, 0x0d49,
- 0x0d50, 0x0d53,
- 0x0d64, 0x0d65,
- 0x0d80, 0x0d80,
- 0x0d84, 0x0d84,
- 0x0d97, 0x0d99,
- 0x0db2, 0x0db2,
- 0x0dbc, 0x0dbc,
- 0x0dbe, 0x0dbf,
- 0x0dc7, 0x0dc9,
- 0x0dcb, 0x0dce,
- 0x0dd5, 0x0dd5,
- 0x0dd7, 0x0dd7,
- 0x0de0, 0x0de5,
- 0x0df0, 0x0df1,
- 0x0df5, 0x0e00,
- 0x0e3b, 0x0e3e,
- 0x0e5c, 0x0e80,
- 0x0e83, 0x0e83,
- 0x0e85, 0x0e85,
- 0x0e8b, 0x0e8b,
- 0x0ea4, 0x0ea4,
- 0x0ea6, 0x0ea6,
- 0x0ebe, 0x0ebf,
- 0x0ec5, 0x0ec5,
- 0x0ec7, 0x0ec7,
- 0x0ecf, 0x0ecf,
- 0x0eda, 0x0edb,
- 0x0ee0, 0x0eff,
- 0x0f48, 0x0f48,
- 0x0f6d, 0x0f70,
- 0x0f98, 0x0f98,
- 0x0fbd, 0x0fbd,
- 0x0fcd, 0x0fcd,
- 0x0fdb, 0x0fff,
- 0x10c6, 0x10c6,
- 0x10c8, 0x10cc,
- 0x10ce, 0x10cf,
- 0x1249, 0x1249,
- 0x124e, 0x124f,
- 0x1257, 0x1257,
- 0x1259, 0x1259,
- 0x125e, 0x125f,
- 0x1289, 0x1289,
- 0x128e, 0x128f,
- 0x12b1, 0x12b1,
- 0x12b6, 0x12b7,
- 0x12bf, 0x12bf,
- 0x12c1, 0x12c1,
- 0x12c6, 0x12c7,
- 0x12d7, 0x12d7,
- 0x1311, 0x1311,
- 0x1316, 0x1317,
- 0x135b, 0x135c,
- 0x137d, 0x137f,
- 0x139a, 0x139f,
- 0x13f6, 0x13f7,
- 0x13fe, 0x13ff,
- 0x169d, 0x169f,
- 0x16f9, 0x16ff,
- 0x1716, 0x171e,
- 0x1737, 0x173f,
- 0x1754, 0x175f,
- 0x176d, 0x176d,
- 0x1771, 0x1771,
- 0x1774, 0x177f,
- 0x17de, 0x17df,
- 0x17ea, 0x17ef,
- 0x17fa, 0x17ff,
- 0x180e, 0x180e,
- 0x181a, 0x181f,
- 0x1879, 0x187f,
- 0x18ab, 0x18af,
- 0x18f6, 0x18ff,
- 0x191f, 0x191f,
- 0x192c, 0x192f,
- 0x193c, 0x193f,
- 0x1941, 0x1943,
- 0x196e, 0x196f,
- 0x1975, 0x197f,
- 0x19ac, 0x19af,
- 0x19ca, 0x19cf,
- 0x19db, 0x19dd,
- 0x1a1c, 0x1a1d,
- 0x1a5f, 0x1a5f,
- 0x1a7d, 0x1a7e,
- 0x1a8a, 0x1a8f,
- 0x1a9a, 0x1a9f,
- 0x1aae, 0x1aaf,
- 0x1acf, 0x1aff,
- 0x1b4d, 0x1b4f,
- 0x1b7f, 0x1b7f,
- 0x1bf4, 0x1bfb,
- 0x1c38, 0x1c3a,
- 0x1c4a, 0x1c4c,
- 0x1c89, 0x1c8f,
- 0x1cbb, 0x1cbc,
- 0x1cc8, 0x1ccf,
- 0x1cfb, 0x1cff,
- 0x1f16, 0x1f17,
- 0x1f1e, 0x1f1f,
- 0x1f46, 0x1f47,
- 0x1f4e, 0x1f4f,
- 0x1f58, 0x1f58,
- 0x1f5a, 0x1f5a,
- 0x1f5c, 0x1f5c,
- 0x1f5e, 0x1f5e,
- 0x1f7e, 0x1f7f,
- 0x1fb5, 0x1fb5,
- 0x1fc5, 0x1fc5,
- 0x1fd4, 0x1fd5,
- 0x1fdc, 0x1fdc,
- 0x1ff0, 0x1ff1,
- 0x1ff5, 0x1ff5,
- 0x1fff, 0x1fff,
- 0x200b, 0x200f,
- 0x202a, 0x202e,
- 0x2060, 0x206f,
- 0x2072, 0x2073,
- 0x208f, 0x208f,
- 0x209d, 0x209f,
- 0x20c1, 0x20cf,
- 0x20f1, 0x20ff,
- 0x218c, 0x218f,
- 0x2427, 0x243f,
- 0x244b, 0x245f,
- 0x2b74, 0x2b75,
- 0x2b96, 0x2b96,
- 0x2cf4, 0x2cf8,
- 0x2d26, 0x2d26,
- 0x2d28, 0x2d2c,
- 0x2d2e, 0x2d2f,
- 0x2d68, 0x2d6e,
- 0x2d71, 0x2d7e,
- 0x2d97, 0x2d9f,
- 0x2da7, 0x2da7,
- 0x2daf, 0x2daf,
- 0x2db7, 0x2db7,
- 0x2dbf, 0x2dbf,
- 0x2dc7, 0x2dc7,
- 0x2dcf, 0x2dcf,
- 0x2dd7, 0x2dd7,
- 0x2ddf, 0x2ddf,
- 0x2e5e, 0x2e7f,
- 0x2e9a, 0x2e9a,
- 0x2ef4, 0x2eff,
- 0x2fd6, 0x2fef,
- 0x2ffc, 0x2fff,
- 0x3040, 0x3040,
- 0x3097, 0x3098,
- 0x3100, 0x3104,
- 0x3130, 0x3130,
- 0x318f, 0x318f,
- 0x31e4, 0x31ef,
- 0x321f, 0x321f,
- 0xa48d, 0xa48f,
- 0xa4c7, 0xa4cf,
- 0xa62c, 0xa63f,
- 0xa6f8, 0xa6ff,
- 0xa7cb, 0xa7cf,
- 0xa7d2, 0xa7d2,
- 0xa7d4, 0xa7d4,
- 0xa7da, 0xa7f1,
- 0xa82d, 0xa82f,
- 0xa83a, 0xa83f,
- 0xa878, 0xa87f,
- 0xa8c6, 0xa8cd,
- 0xa8da, 0xa8df,
- 0xa954, 0xa95e,
- 0xa97d, 0xa97f,
- 0xa9ce, 0xa9ce,
- 0xa9da, 0xa9dd,
- 0xa9ff, 0xa9ff,
- 0xaa37, 0xaa3f,
- 0xaa4e, 0xaa4f,
- 0xaa5a, 0xaa5b,
- 0xaac3, 0xaada,
- 0xaaf7, 0xab00,
- 0xab07, 0xab08,
- 0xab0f, 0xab10,
- 0xab17, 0xab1f,
- 0xab27, 0xab27,
- 0xab2f, 0xab2f,
- 0xab6c, 0xab6f,
- 0xabee, 0xabef,
- 0xabfa, 0xabff,
- 0xd7a4, 0xd7af,
- 0xd7c7, 0xd7ca,
- 0xd7fc, 0xf8ff,
- 0xfa6e, 0xfa6f,
- 0xfada, 0xfaff,
- 0xfb07, 0xfb12,
- 0xfb18, 0xfb1c,
- 0xfb37, 0xfb37,
- 0xfb3d, 0xfb3d,
- 0xfb3f, 0xfb3f,
- 0xfb42, 0xfb42,
- 0xfb45, 0xfb45,
- 0xfbc3, 0xfbd2,
- 0xfd90, 0xfd91,
- 0xfdc8, 0xfdce,
- 0xfdd0, 0xfdef,
- 0xfe1a, 0xfe1f,
- 0xfe53, 0xfe53,
- 0xfe67, 0xfe67,
- 0xfe6c, 0xfe6f,
- 0xfe75, 0xfe75,
- 0xfefd, 0xff00,
- 0xffbf, 0xffc1,
- 0xffc8, 0xffc9,
- 0xffd0, 0xffd1,
- 0xffd8, 0xffd9,
- 0xffdd, 0xffdf,
- 0xffe7, 0xffe7,
- 0xffef, 0xfffb,
- 0xfffe, 0xffff,
- 0x1000c, 0x1000c,
- 0x10027, 0x10027,
- 0x1003b, 0x1003b,
- 0x1003e, 0x1003e,
- 0x1004e, 0x1004f,
- 0x1005e, 0x1007f,
- 0x100fb, 0x100ff,
- 0x10103, 0x10106,
- 0x10134, 0x10136,
- 0x1018f, 0x1018f,
- 0x1019d, 0x1019f,
- 0x101a1, 0x101cf,
- 0x101fe, 0x1027f,
- 0x1029d, 0x1029f,
- 0x102d1, 0x102df,
- 0x102fc, 0x102ff,
- 0x10324, 0x1032c,
- 0x1034b, 0x1034f,
- 0x1037b, 0x1037f,
- 0x1039e, 0x1039e,
- 0x103c4, 0x103c7,
- 0x103d6, 0x103ff,
- 0x1049e, 0x1049f,
- 0x104aa, 0x104af,
- 0x104d4, 0x104d7,
- 0x104fc, 0x104ff,
- 0x10528, 0x1052f,
- 0x10564, 0x1056e,
- 0x1057b, 0x1057b,
- 0x1058b, 0x1058b,
- 0x10593, 0x10593,
- 0x10596, 0x10596,
- 0x105a2, 0x105a2,
- 0x105b2, 0x105b2,
- 0x105ba, 0x105ba,
- 0x105bd, 0x105ff,
- 0x10737, 0x1073f,
- 0x10756, 0x1075f,
- 0x10768, 0x1077f,
- 0x10786, 0x10786,
- 0x107b1, 0x107b1,
- 0x107bb, 0x107ff,
- 0x10806, 0x10807,
- 0x10809, 0x10809,
- 0x10836, 0x10836,
- 0x10839, 0x1083b,
- 0x1083d, 0x1083e,
- 0x10856, 0x10856,
- 0x1089f, 0x108a6,
- 0x108b0, 0x108df,
- 0x108f3, 0x108f3,
- 0x108f6, 0x108fa,
- 0x1091c, 0x1091e,
- 0x1093a, 0x1093e,
- 0x10940, 0x1097f,
- 0x109b8, 0x109bb,
- 0x109d0, 0x109d1,
- 0x10a04, 0x10a04,
- 0x10a07, 0x10a0b,
- 0x10a14, 0x10a14,
- 0x10a18, 0x10a18,
- 0x10a36, 0x10a37,
- 0x10a3b, 0x10a3e,
- 0x10a49, 0x10a4f,
- 0x10a59, 0x10a5f,
- 0x10aa0, 0x10abf,
- 0x10ae7, 0x10aea,
- 0x10af7, 0x10aff,
- 0x10b36, 0x10b38,
- 0x10b56, 0x10b57,
- 0x10b73, 0x10b77,
- 0x10b92, 0x10b98,
- 0x10b9d, 0x10ba8,
- 0x10bb0, 0x10bff,
- 0x10c49, 0x10c7f,
- 0x10cb3, 0x10cbf,
- 0x10cf3, 0x10cf9,
- 0x10d28, 0x10d2f,
- 0x10d3a, 0x10e5f,
- 0x10e7f, 0x10e7f,
- 0x10eaa, 0x10eaa,
- 0x10eae, 0x10eaf,
- 0x10eb2, 0x10efc,
- 0x10f28, 0x10f2f,
- 0x10f5a, 0x10f6f,
- 0x10f8a, 0x10faf,
- 0x10fcc, 0x10fdf,
- 0x10ff7, 0x10fff,
- 0x1104e, 0x11051,
- 0x11076, 0x1107e,
- 0x110bd, 0x110bd,
- 0x110c3, 0x110cf,
- 0x110e9, 0x110ef,
- 0x110fa, 0x110ff,
- 0x11135, 0x11135,
- 0x11148, 0x1114f,
- 0x11177, 0x1117f,
- 0x111e0, 0x111e0,
- 0x111f5, 0x111ff,
- 0x11212, 0x11212,
- 0x11242, 0x1127f,
- 0x11287, 0x11287,
- 0x11289, 0x11289,
- 0x1128e, 0x1128e,
- 0x1129e, 0x1129e,
- 0x112aa, 0x112af,
- 0x112eb, 0x112ef,
- 0x112fa, 0x112ff,
- 0x11304, 0x11304,
- 0x1130d, 0x1130e,
- 0x11311, 0x11312,
- 0x11329, 0x11329,
- 0x11331, 0x11331,
- 0x11334, 0x11334,
- 0x1133a, 0x1133a,
- 0x11345, 0x11346,
- 0x11349, 0x1134a,
- 0x1134e, 0x1134f,
- 0x11351, 0x11356,
- 0x11358, 0x1135c,
- 0x11364, 0x11365,
- 0x1136d, 0x1136f,
- 0x11375, 0x113ff,
- 0x1145c, 0x1145c,
- 0x11462, 0x1147f,
- 0x114c8, 0x114cf,
- 0x114da, 0x1157f,
- 0x115b6, 0x115b7,
- 0x115de, 0x115ff,
- 0x11645, 0x1164f,
- 0x1165a, 0x1165f,
- 0x1166d, 0x1167f,
- 0x116ba, 0x116bf,
- 0x116ca, 0x116ff,
- 0x1171b, 0x1171c,
- 0x1172c, 0x1172f,
- 0x11747, 0x117ff,
- 0x1183c, 0x1189f,
- 0x118f3, 0x118fe,
- 0x11907, 0x11908,
- 0x1190a, 0x1190b,
- 0x11914, 0x11914,
- 0x11917, 0x11917,
- 0x11936, 0x11936,
- 0x11939, 0x1193a,
- 0x11947, 0x1194f,
- 0x1195a, 0x1199f,
- 0x119a8, 0x119a9,
- 0x119d8, 0x119d9,
- 0x119e5, 0x119ff,
- 0x11a48, 0x11a4f,
- 0x11aa3, 0x11aaf,
- 0x11af9, 0x11aff,
- 0x11b0a, 0x11bff,
- 0x11c09, 0x11c09,
- 0x11c37, 0x11c37,
- 0x11c46, 0x11c4f,
- 0x11c6d, 0x11c6f,
- 0x11c90, 0x11c91,
- 0x11ca8, 0x11ca8,
- 0x11cb7, 0x11cff,
- 0x11d07, 0x11d07,
- 0x11d0a, 0x11d0a,
- 0x11d37, 0x11d39,
- 0x11d3b, 0x11d3b,
- 0x11d3e, 0x11d3e,
- 0x11d48, 0x11d4f,
- 0x11d5a, 0x11d5f,
- 0x11d66, 0x11d66,
- 0x11d69, 0x11d69,
- 0x11d8f, 0x11d8f,
- 0x11d92, 0x11d92,
- 0x11d99, 0x11d9f,
- 0x11daa, 0x11edf,
- 0x11ef9, 0x11eff,
- 0x11f11, 0x11f11,
- 0x11f3b, 0x11f3d,
- 0x11f5a, 0x11faf,
- 0x11fb1, 0x11fbf,
- 0x11ff2, 0x11ffe,
- 0x1239a, 0x123ff,
- 0x1246f, 0x1246f,
- 0x12475, 0x1247f,
- 0x12544, 0x12f8f,
- 0x12ff3, 0x12fff,
- 0x13430, 0x1343f,
- 0x13456, 0x143ff,
- 0x14647, 0x167ff,
- 0x16a39, 0x16a3f,
- 0x16a5f, 0x16a5f,
- 0x16a6a, 0x16a6d,
- 0x16abf, 0x16abf,
- 0x16aca, 0x16acf,
- 0x16aee, 0x16aef,
- 0x16af6, 0x16aff,
- 0x16b46, 0x16b4f,
- 0x16b5a, 0x16b5a,
- 0x16b62, 0x16b62,
- 0x16b78, 0x16b7c,
- 0x16b90, 0x16e3f,
- 0x16e9b, 0x16eff,
- 0x16f4b, 0x16f4e,
- 0x16f88, 0x16f8e,
- 0x16fa0, 0x16fdf,
- 0x16fe5, 0x16fef,
- 0x16ff2, 0x16fff,
- 0x187f8, 0x187ff,
- 0x18cd6, 0x18cff,
- 0x18d09, 0x1afef,
- 0x1aff4, 0x1aff4,
- 0x1affc, 0x1affc,
- 0x1afff, 0x1afff,
- 0x1b123, 0x1b131,
- 0x1b133, 0x1b14f,
- 0x1b153, 0x1b154,
- 0x1b156, 0x1b163,
- 0x1b168, 0x1b16f,
- 0x1b2fc, 0x1bbff,
- 0x1bc6b, 0x1bc6f,
- 0x1bc7d, 0x1bc7f,
- 0x1bc89, 0x1bc8f,
- 0x1bc9a, 0x1bc9b,
- 0x1bca0, 0x1ceff,
- 0x1cf2e, 0x1cf2f,
- 0x1cf47, 0x1cf4f,
- 0x1cfc4, 0x1cfff,
- 0x1d0f6, 0x1d0ff,
- 0x1d127, 0x1d128,
- 0x1d173, 0x1d17a,
- 0x1d1eb, 0x1d1ff,
- 0x1d246, 0x1d2bf,
- 0x1d2d4, 0x1d2df,
- 0x1d2f4, 0x1d2ff,
- 0x1d357, 0x1d35f,
- 0x1d379, 0x1d3ff,
- 0x1d455, 0x1d455,
- 0x1d49d, 0x1d49d,
- 0x1d4a0, 0x1d4a1,
- 0x1d4a3, 0x1d4a4,
- 0x1d4a7, 0x1d4a8,
- 0x1d4ad, 0x1d4ad,
- 0x1d4ba, 0x1d4ba,
- 0x1d4bc, 0x1d4bc,
- 0x1d4c4, 0x1d4c4,
- 0x1d506, 0x1d506,
- 0x1d50b, 0x1d50c,
- 0x1d515, 0x1d515,
- 0x1d51d, 0x1d51d,
- 0x1d53a, 0x1d53a,
- 0x1d53f, 0x1d53f,
- 0x1d545, 0x1d545,
- 0x1d547, 0x1d549,
- 0x1d551, 0x1d551,
- 0x1d6a6, 0x1d6a7,
- 0x1d7cc, 0x1d7cd,
- 0x1da8c, 0x1da9a,
- 0x1daa0, 0x1daa0,
- 0x1dab0, 0x1deff,
- 0x1df1f, 0x1df24,
- 0x1df2b, 0x1dfff,
- 0x1e007, 0x1e007,
- 0x1e019, 0x1e01a,
- 0x1e022, 0x1e022,
- 0x1e025, 0x1e025,
- 0x1e02b, 0x1e02f,
- 0x1e06e, 0x1e08e,
- 0x1e090, 0x1e0ff,
- 0x1e12d, 0x1e12f,
- 0x1e13e, 0x1e13f,
- 0x1e14a, 0x1e14d,
- 0x1e150, 0x1e28f,
- 0x1e2af, 0x1e2bf,
- 0x1e2fa, 0x1e2fe,
- 0x1e300, 0x1e4cf,
- 0x1e4fa, 0x1e7df,
- 0x1e7e7, 0x1e7e7,
- 0x1e7ec, 0x1e7ec,
- 0x1e7ef, 0x1e7ef,
- 0x1e7ff, 0x1e7ff,
- 0x1e8c5, 0x1e8c6,
- 0x1e8d7, 0x1e8ff,
- 0x1e94c, 0x1e94f,
- 0x1e95a, 0x1e95d,
- 0x1e960, 0x1ec70,
- 0x1ecb5, 0x1ed00,
- 0x1ed3e, 0x1edff,
- 0x1ee04, 0x1ee04,
- 0x1ee20, 0x1ee20,
- 0x1ee23, 0x1ee23,
- 0x1ee25, 0x1ee26,
- 0x1ee28, 0x1ee28,
- 0x1ee33, 0x1ee33,
- 0x1ee38, 0x1ee38,
- 0x1ee3a, 0x1ee3a,
- 0x1ee3c, 0x1ee41,
- 0x1ee43, 0x1ee46,
- 0x1ee48, 0x1ee48,
- 0x1ee4a, 0x1ee4a,
- 0x1ee4c, 0x1ee4c,
- 0x1ee50, 0x1ee50,
- 0x1ee53, 0x1ee53,
- 0x1ee55, 0x1ee56,
- 0x1ee58, 0x1ee58,
- 0x1ee5a, 0x1ee5a,
- 0x1ee5c, 0x1ee5c,
- 0x1ee5e, 0x1ee5e,
- 0x1ee60, 0x1ee60,
- 0x1ee63, 0x1ee63,
- 0x1ee65, 0x1ee66,
- 0x1ee6b, 0x1ee6b,
- 0x1ee73, 0x1ee73,
- 0x1ee78, 0x1ee78,
- 0x1ee7d, 0x1ee7d,
- 0x1ee7f, 0x1ee7f,
- 0x1ee8a, 0x1ee8a,
- 0x1ee9c, 0x1eea0,
- 0x1eea4, 0x1eea4,
- 0x1eeaa, 0x1eeaa,
- 0x1eebc, 0x1eeef,
- 0x1eef2, 0x1efff,
- 0x1f02c, 0x1f02f,
- 0x1f094, 0x1f09f,
- 0x1f0af, 0x1f0b0,
- 0x1f0c0, 0x1f0c0,
- 0x1f0d0, 0x1f0d0,
- 0x1f0f6, 0x1f0ff,
- 0x1f1ae, 0x1f1e5,
- 0x1f203, 0x1f20f,
- 0x1f23c, 0x1f23f,
- 0x1f249, 0x1f24f,
- 0x1f252, 0x1f25f,
- 0x1f266, 0x1f2ff,
- 0x1f6d8, 0x1f6db,
- 0x1f6ed, 0x1f6ef,
- 0x1f6fd, 0x1f6ff,
- 0x1f777, 0x1f77a,
- 0x1f7da, 0x1f7df,
- 0x1f7ec, 0x1f7ef,
- 0x1f7f1, 0x1f7ff,
- 0x1f80c, 0x1f80f,
- 0x1f848, 0x1f84f,
- 0x1f85a, 0x1f85f,
- 0x1f888, 0x1f88f,
- 0x1f8ae, 0x1f8af,
- 0x1f8b2, 0x1f8ff,
- 0x1fa54, 0x1fa5f,
- 0x1fa6e, 0x1fa6f,
- 0x1fa7d, 0x1fa7f,
- 0x1fa89, 0x1fa8f,
- 0x1fabe, 0x1fabe,
- 0x1fac6, 0x1facd,
- 0x1fadc, 0x1fadf,
- 0x1fae9, 0x1faef,
- 0x1faf9, 0x1faff,
- 0x1fb93, 0x1fb93,
- 0x1fbcb, 0x1fbef,
- 0x1fbfa, 0x1ffff,
- 0x2a6e0, 0x2a6ff,
- 0x2b73a, 0x2b73f,
- 0x2b81e, 0x2b81f,
- 0x2cea2, 0x2ceaf,
- 0x2ebe1, 0x2f7ff,
- 0x2fa1e, 0x2ffff,
- 0x3134b, 0x3134f,
- 0x323b0, 0xe00ff,
- 0xe01f0, 0x10ffff,
-}; /* CR_C */
-
-/* 'Cc': General Category */
-#define CR_Cc CR_Cntrl
-
-/* 'Cf': General Category */
-static const OnigCodePoint CR_Cf[] = {
- 21,
- 0x00ad, 0x00ad,
- 0x0600, 0x0605,
- 0x061c, 0x061c,
- 0x06dd, 0x06dd,
- 0x070f, 0x070f,
- 0x0890, 0x0891,
- 0x08e2, 0x08e2,
- 0x180e, 0x180e,
- 0x200b, 0x200f,
- 0x202a, 0x202e,
- 0x2060, 0x2064,
- 0x2066, 0x206f,
- 0xfeff, 0xfeff,
- 0xfff9, 0xfffb,
- 0x110bd, 0x110bd,
- 0x110cd, 0x110cd,
- 0x13430, 0x1343f,
- 0x1bca0, 0x1bca3,
- 0x1d173, 0x1d17a,
- 0xe0001, 0xe0001,
- 0xe0020, 0xe007f,
-}; /* CR_Cf */
-
-/* 'Cn': General Category */
-static const OnigCodePoint CR_Cn[] = {
- 707,
- 0x0378, 0x0379,
- 0x0380, 0x0383,
- 0x038b, 0x038b,
- 0x038d, 0x038d,
- 0x03a2, 0x03a2,
- 0x0530, 0x0530,
- 0x0557, 0x0558,
- 0x058b, 0x058c,
- 0x0590, 0x0590,
- 0x05c8, 0x05cf,
- 0x05eb, 0x05ee,
- 0x05f5, 0x05ff,
- 0x070e, 0x070e,
- 0x074b, 0x074c,
- 0x07b2, 0x07bf,
- 0x07fb, 0x07fc,
- 0x082e, 0x082f,
- 0x083f, 0x083f,
- 0x085c, 0x085d,
- 0x085f, 0x085f,
- 0x086b, 0x086f,
- 0x088f, 0x088f,
- 0x0892, 0x0897,
- 0x0984, 0x0984,
- 0x098d, 0x098e,
- 0x0991, 0x0992,
- 0x09a9, 0x09a9,
- 0x09b1, 0x09b1,
- 0x09b3, 0x09b5,
- 0x09ba, 0x09bb,
- 0x09c5, 0x09c6,
- 0x09c9, 0x09ca,
- 0x09cf, 0x09d6,
- 0x09d8, 0x09db,
- 0x09de, 0x09de,
- 0x09e4, 0x09e5,
- 0x09ff, 0x0a00,
- 0x0a04, 0x0a04,
- 0x0a0b, 0x0a0e,
- 0x0a11, 0x0a12,
- 0x0a29, 0x0a29,
- 0x0a31, 0x0a31,
- 0x0a34, 0x0a34,
- 0x0a37, 0x0a37,
- 0x0a3a, 0x0a3b,
- 0x0a3d, 0x0a3d,
- 0x0a43, 0x0a46,
- 0x0a49, 0x0a4a,
- 0x0a4e, 0x0a50,
- 0x0a52, 0x0a58,
- 0x0a5d, 0x0a5d,
- 0x0a5f, 0x0a65,
- 0x0a77, 0x0a80,
- 0x0a84, 0x0a84,
- 0x0a8e, 0x0a8e,
- 0x0a92, 0x0a92,
- 0x0aa9, 0x0aa9,
- 0x0ab1, 0x0ab1,
- 0x0ab4, 0x0ab4,
- 0x0aba, 0x0abb,
- 0x0ac6, 0x0ac6,
- 0x0aca, 0x0aca,
- 0x0ace, 0x0acf,
- 0x0ad1, 0x0adf,
- 0x0ae4, 0x0ae5,
- 0x0af2, 0x0af8,
- 0x0b00, 0x0b00,
- 0x0b04, 0x0b04,
- 0x0b0d, 0x0b0e,
- 0x0b11, 0x0b12,
- 0x0b29, 0x0b29,
- 0x0b31, 0x0b31,
- 0x0b34, 0x0b34,
- 0x0b3a, 0x0b3b,
- 0x0b45, 0x0b46,
- 0x0b49, 0x0b4a,
- 0x0b4e, 0x0b54,
- 0x0b58, 0x0b5b,
- 0x0b5e, 0x0b5e,
- 0x0b64, 0x0b65,
- 0x0b78, 0x0b81,
- 0x0b84, 0x0b84,
- 0x0b8b, 0x0b8d,
- 0x0b91, 0x0b91,
- 0x0b96, 0x0b98,
- 0x0b9b, 0x0b9b,
- 0x0b9d, 0x0b9d,
- 0x0ba0, 0x0ba2,
- 0x0ba5, 0x0ba7,
- 0x0bab, 0x0bad,
- 0x0bba, 0x0bbd,
- 0x0bc3, 0x0bc5,
- 0x0bc9, 0x0bc9,
- 0x0bce, 0x0bcf,
- 0x0bd1, 0x0bd6,
- 0x0bd8, 0x0be5,
- 0x0bfb, 0x0bff,
- 0x0c0d, 0x0c0d,
- 0x0c11, 0x0c11,
- 0x0c29, 0x0c29,
- 0x0c3a, 0x0c3b,
- 0x0c45, 0x0c45,
- 0x0c49, 0x0c49,
- 0x0c4e, 0x0c54,
- 0x0c57, 0x0c57,
- 0x0c5b, 0x0c5c,
- 0x0c5e, 0x0c5f,
- 0x0c64, 0x0c65,
- 0x0c70, 0x0c76,
- 0x0c8d, 0x0c8d,
- 0x0c91, 0x0c91,
- 0x0ca9, 0x0ca9,
- 0x0cb4, 0x0cb4,
- 0x0cba, 0x0cbb,
- 0x0cc5, 0x0cc5,
- 0x0cc9, 0x0cc9,
- 0x0cce, 0x0cd4,
- 0x0cd7, 0x0cdc,
- 0x0cdf, 0x0cdf,
- 0x0ce4, 0x0ce5,
- 0x0cf0, 0x0cf0,
- 0x0cf4, 0x0cff,
- 0x0d0d, 0x0d0d,
- 0x0d11, 0x0d11,
- 0x0d45, 0x0d45,
- 0x0d49, 0x0d49,
- 0x0d50, 0x0d53,
- 0x0d64, 0x0d65,
- 0x0d80, 0x0d80,
- 0x0d84, 0x0d84,
- 0x0d97, 0x0d99,
- 0x0db2, 0x0db2,
- 0x0dbc, 0x0dbc,
- 0x0dbe, 0x0dbf,
- 0x0dc7, 0x0dc9,
- 0x0dcb, 0x0dce,
- 0x0dd5, 0x0dd5,
- 0x0dd7, 0x0dd7,
- 0x0de0, 0x0de5,
- 0x0df0, 0x0df1,
- 0x0df5, 0x0e00,
- 0x0e3b, 0x0e3e,
- 0x0e5c, 0x0e80,
- 0x0e83, 0x0e83,
- 0x0e85, 0x0e85,
- 0x0e8b, 0x0e8b,
- 0x0ea4, 0x0ea4,
- 0x0ea6, 0x0ea6,
- 0x0ebe, 0x0ebf,
- 0x0ec5, 0x0ec5,
- 0x0ec7, 0x0ec7,
- 0x0ecf, 0x0ecf,
- 0x0eda, 0x0edb,
- 0x0ee0, 0x0eff,
- 0x0f48, 0x0f48,
- 0x0f6d, 0x0f70,
- 0x0f98, 0x0f98,
- 0x0fbd, 0x0fbd,
- 0x0fcd, 0x0fcd,
- 0x0fdb, 0x0fff,
- 0x10c6, 0x10c6,
- 0x10c8, 0x10cc,
- 0x10ce, 0x10cf,
- 0x1249, 0x1249,
- 0x124e, 0x124f,
- 0x1257, 0x1257,
- 0x1259, 0x1259,
- 0x125e, 0x125f,
- 0x1289, 0x1289,
- 0x128e, 0x128f,
- 0x12b1, 0x12b1,
- 0x12b6, 0x12b7,
- 0x12bf, 0x12bf,
- 0x12c1, 0x12c1,
- 0x12c6, 0x12c7,
- 0x12d7, 0x12d7,
- 0x1311, 0x1311,
- 0x1316, 0x1317,
- 0x135b, 0x135c,
- 0x137d, 0x137f,
- 0x139a, 0x139f,
- 0x13f6, 0x13f7,
- 0x13fe, 0x13ff,
- 0x169d, 0x169f,
- 0x16f9, 0x16ff,
- 0x1716, 0x171e,
- 0x1737, 0x173f,
- 0x1754, 0x175f,
- 0x176d, 0x176d,
- 0x1771, 0x1771,
- 0x1774, 0x177f,
- 0x17de, 0x17df,
- 0x17ea, 0x17ef,
- 0x17fa, 0x17ff,
- 0x181a, 0x181f,
- 0x1879, 0x187f,
- 0x18ab, 0x18af,
- 0x18f6, 0x18ff,
- 0x191f, 0x191f,
- 0x192c, 0x192f,
- 0x193c, 0x193f,
- 0x1941, 0x1943,
- 0x196e, 0x196f,
- 0x1975, 0x197f,
- 0x19ac, 0x19af,
- 0x19ca, 0x19cf,
- 0x19db, 0x19dd,
- 0x1a1c, 0x1a1d,
- 0x1a5f, 0x1a5f,
- 0x1a7d, 0x1a7e,
- 0x1a8a, 0x1a8f,
- 0x1a9a, 0x1a9f,
- 0x1aae, 0x1aaf,
- 0x1acf, 0x1aff,
- 0x1b4d, 0x1b4f,
- 0x1b7f, 0x1b7f,
- 0x1bf4, 0x1bfb,
- 0x1c38, 0x1c3a,
- 0x1c4a, 0x1c4c,
- 0x1c89, 0x1c8f,
- 0x1cbb, 0x1cbc,
- 0x1cc8, 0x1ccf,
- 0x1cfb, 0x1cff,
- 0x1f16, 0x1f17,
- 0x1f1e, 0x1f1f,
- 0x1f46, 0x1f47,
- 0x1f4e, 0x1f4f,
- 0x1f58, 0x1f58,
- 0x1f5a, 0x1f5a,
- 0x1f5c, 0x1f5c,
- 0x1f5e, 0x1f5e,
- 0x1f7e, 0x1f7f,
- 0x1fb5, 0x1fb5,
- 0x1fc5, 0x1fc5,
- 0x1fd4, 0x1fd5,
- 0x1fdc, 0x1fdc,
- 0x1ff0, 0x1ff1,
- 0x1ff5, 0x1ff5,
- 0x1fff, 0x1fff,
- 0x2065, 0x2065,
- 0x2072, 0x2073,
- 0x208f, 0x208f,
- 0x209d, 0x209f,
- 0x20c1, 0x20cf,
- 0x20f1, 0x20ff,
- 0x218c, 0x218f,
- 0x2427, 0x243f,
- 0x244b, 0x245f,
- 0x2b74, 0x2b75,
- 0x2b96, 0x2b96,
- 0x2cf4, 0x2cf8,
- 0x2d26, 0x2d26,
- 0x2d28, 0x2d2c,
- 0x2d2e, 0x2d2f,
- 0x2d68, 0x2d6e,
- 0x2d71, 0x2d7e,
- 0x2d97, 0x2d9f,
- 0x2da7, 0x2da7,
- 0x2daf, 0x2daf,
- 0x2db7, 0x2db7,
- 0x2dbf, 0x2dbf,
- 0x2dc7, 0x2dc7,
- 0x2dcf, 0x2dcf,
- 0x2dd7, 0x2dd7,
- 0x2ddf, 0x2ddf,
- 0x2e5e, 0x2e7f,
- 0x2e9a, 0x2e9a,
- 0x2ef4, 0x2eff,
- 0x2fd6, 0x2fef,
- 0x2ffc, 0x2fff,
- 0x3040, 0x3040,
- 0x3097, 0x3098,
- 0x3100, 0x3104,
- 0x3130, 0x3130,
- 0x318f, 0x318f,
- 0x31e4, 0x31ef,
- 0x321f, 0x321f,
- 0xa48d, 0xa48f,
- 0xa4c7, 0xa4cf,
- 0xa62c, 0xa63f,
- 0xa6f8, 0xa6ff,
- 0xa7cb, 0xa7cf,
- 0xa7d2, 0xa7d2,
- 0xa7d4, 0xa7d4,
- 0xa7da, 0xa7f1,
- 0xa82d, 0xa82f,
- 0xa83a, 0xa83f,
- 0xa878, 0xa87f,
- 0xa8c6, 0xa8cd,
- 0xa8da, 0xa8df,
- 0xa954, 0xa95e,
- 0xa97d, 0xa97f,
- 0xa9ce, 0xa9ce,
- 0xa9da, 0xa9dd,
- 0xa9ff, 0xa9ff,
- 0xaa37, 0xaa3f,
- 0xaa4e, 0xaa4f,
- 0xaa5a, 0xaa5b,
- 0xaac3, 0xaada,
- 0xaaf7, 0xab00,
- 0xab07, 0xab08,
- 0xab0f, 0xab10,
- 0xab17, 0xab1f,
- 0xab27, 0xab27,
- 0xab2f, 0xab2f,
- 0xab6c, 0xab6f,
- 0xabee, 0xabef,
- 0xabfa, 0xabff,
- 0xd7a4, 0xd7af,
- 0xd7c7, 0xd7ca,
- 0xd7fc, 0xd7ff,
- 0xfa6e, 0xfa6f,
- 0xfada, 0xfaff,
- 0xfb07, 0xfb12,
- 0xfb18, 0xfb1c,
- 0xfb37, 0xfb37,
- 0xfb3d, 0xfb3d,
- 0xfb3f, 0xfb3f,
- 0xfb42, 0xfb42,
- 0xfb45, 0xfb45,
- 0xfbc3, 0xfbd2,
- 0xfd90, 0xfd91,
- 0xfdc8, 0xfdce,
- 0xfdd0, 0xfdef,
- 0xfe1a, 0xfe1f,
- 0xfe53, 0xfe53,
- 0xfe67, 0xfe67,
- 0xfe6c, 0xfe6f,
- 0xfe75, 0xfe75,
- 0xfefd, 0xfefe,
- 0xff00, 0xff00,
- 0xffbf, 0xffc1,
- 0xffc8, 0xffc9,
- 0xffd0, 0xffd1,
- 0xffd8, 0xffd9,
- 0xffdd, 0xffdf,
- 0xffe7, 0xffe7,
- 0xffef, 0xfff8,
- 0xfffe, 0xffff,
- 0x1000c, 0x1000c,
- 0x10027, 0x10027,
- 0x1003b, 0x1003b,
- 0x1003e, 0x1003e,
- 0x1004e, 0x1004f,
- 0x1005e, 0x1007f,
- 0x100fb, 0x100ff,
- 0x10103, 0x10106,
- 0x10134, 0x10136,
- 0x1018f, 0x1018f,
- 0x1019d, 0x1019f,
- 0x101a1, 0x101cf,
- 0x101fe, 0x1027f,
- 0x1029d, 0x1029f,
- 0x102d1, 0x102df,
- 0x102fc, 0x102ff,
- 0x10324, 0x1032c,
- 0x1034b, 0x1034f,
- 0x1037b, 0x1037f,
- 0x1039e, 0x1039e,
- 0x103c4, 0x103c7,
- 0x103d6, 0x103ff,
- 0x1049e, 0x1049f,
- 0x104aa, 0x104af,
- 0x104d4, 0x104d7,
- 0x104fc, 0x104ff,
- 0x10528, 0x1052f,
- 0x10564, 0x1056e,
- 0x1057b, 0x1057b,
- 0x1058b, 0x1058b,
- 0x10593, 0x10593,
- 0x10596, 0x10596,
- 0x105a2, 0x105a2,
- 0x105b2, 0x105b2,
- 0x105ba, 0x105ba,
- 0x105bd, 0x105ff,
- 0x10737, 0x1073f,
- 0x10756, 0x1075f,
- 0x10768, 0x1077f,
- 0x10786, 0x10786,
- 0x107b1, 0x107b1,
- 0x107bb, 0x107ff,
- 0x10806, 0x10807,
- 0x10809, 0x10809,
- 0x10836, 0x10836,
- 0x10839, 0x1083b,
- 0x1083d, 0x1083e,
- 0x10856, 0x10856,
- 0x1089f, 0x108a6,
- 0x108b0, 0x108df,
- 0x108f3, 0x108f3,
- 0x108f6, 0x108fa,
- 0x1091c, 0x1091e,
- 0x1093a, 0x1093e,
- 0x10940, 0x1097f,
- 0x109b8, 0x109bb,
- 0x109d0, 0x109d1,
- 0x10a04, 0x10a04,
- 0x10a07, 0x10a0b,
- 0x10a14, 0x10a14,
- 0x10a18, 0x10a18,
- 0x10a36, 0x10a37,
- 0x10a3b, 0x10a3e,
- 0x10a49, 0x10a4f,
- 0x10a59, 0x10a5f,
- 0x10aa0, 0x10abf,
- 0x10ae7, 0x10aea,
- 0x10af7, 0x10aff,
- 0x10b36, 0x10b38,
- 0x10b56, 0x10b57,
- 0x10b73, 0x10b77,
- 0x10b92, 0x10b98,
- 0x10b9d, 0x10ba8,
- 0x10bb0, 0x10bff,
- 0x10c49, 0x10c7f,
- 0x10cb3, 0x10cbf,
- 0x10cf3, 0x10cf9,
- 0x10d28, 0x10d2f,
- 0x10d3a, 0x10e5f,
- 0x10e7f, 0x10e7f,
- 0x10eaa, 0x10eaa,
- 0x10eae, 0x10eaf,
- 0x10eb2, 0x10efc,
- 0x10f28, 0x10f2f,
- 0x10f5a, 0x10f6f,
- 0x10f8a, 0x10faf,
- 0x10fcc, 0x10fdf,
- 0x10ff7, 0x10fff,
- 0x1104e, 0x11051,
- 0x11076, 0x1107e,
- 0x110c3, 0x110cc,
- 0x110ce, 0x110cf,
- 0x110e9, 0x110ef,
- 0x110fa, 0x110ff,
- 0x11135, 0x11135,
- 0x11148, 0x1114f,
- 0x11177, 0x1117f,
- 0x111e0, 0x111e0,
- 0x111f5, 0x111ff,
- 0x11212, 0x11212,
- 0x11242, 0x1127f,
- 0x11287, 0x11287,
- 0x11289, 0x11289,
- 0x1128e, 0x1128e,
- 0x1129e, 0x1129e,
- 0x112aa, 0x112af,
- 0x112eb, 0x112ef,
- 0x112fa, 0x112ff,
- 0x11304, 0x11304,
- 0x1130d, 0x1130e,
- 0x11311, 0x11312,
- 0x11329, 0x11329,
- 0x11331, 0x11331,
- 0x11334, 0x11334,
- 0x1133a, 0x1133a,
- 0x11345, 0x11346,
- 0x11349, 0x1134a,
- 0x1134e, 0x1134f,
- 0x11351, 0x11356,
- 0x11358, 0x1135c,
- 0x11364, 0x11365,
- 0x1136d, 0x1136f,
- 0x11375, 0x113ff,
- 0x1145c, 0x1145c,
- 0x11462, 0x1147f,
- 0x114c8, 0x114cf,
- 0x114da, 0x1157f,
- 0x115b6, 0x115b7,
- 0x115de, 0x115ff,
- 0x11645, 0x1164f,
- 0x1165a, 0x1165f,
- 0x1166d, 0x1167f,
- 0x116ba, 0x116bf,
- 0x116ca, 0x116ff,
- 0x1171b, 0x1171c,
- 0x1172c, 0x1172f,
- 0x11747, 0x117ff,
- 0x1183c, 0x1189f,
- 0x118f3, 0x118fe,
- 0x11907, 0x11908,
- 0x1190a, 0x1190b,
- 0x11914, 0x11914,
- 0x11917, 0x11917,
- 0x11936, 0x11936,
- 0x11939, 0x1193a,
- 0x11947, 0x1194f,
- 0x1195a, 0x1199f,
- 0x119a8, 0x119a9,
- 0x119d8, 0x119d9,
- 0x119e5, 0x119ff,
- 0x11a48, 0x11a4f,
- 0x11aa3, 0x11aaf,
- 0x11af9, 0x11aff,
- 0x11b0a, 0x11bff,
- 0x11c09, 0x11c09,
- 0x11c37, 0x11c37,
- 0x11c46, 0x11c4f,
- 0x11c6d, 0x11c6f,
- 0x11c90, 0x11c91,
- 0x11ca8, 0x11ca8,
- 0x11cb7, 0x11cff,
- 0x11d07, 0x11d07,
- 0x11d0a, 0x11d0a,
- 0x11d37, 0x11d39,
- 0x11d3b, 0x11d3b,
- 0x11d3e, 0x11d3e,
- 0x11d48, 0x11d4f,
- 0x11d5a, 0x11d5f,
- 0x11d66, 0x11d66,
- 0x11d69, 0x11d69,
- 0x11d8f, 0x11d8f,
- 0x11d92, 0x11d92,
- 0x11d99, 0x11d9f,
- 0x11daa, 0x11edf,
- 0x11ef9, 0x11eff,
- 0x11f11, 0x11f11,
- 0x11f3b, 0x11f3d,
- 0x11f5a, 0x11faf,
- 0x11fb1, 0x11fbf,
- 0x11ff2, 0x11ffe,
- 0x1239a, 0x123ff,
- 0x1246f, 0x1246f,
- 0x12475, 0x1247f,
- 0x12544, 0x12f8f,
- 0x12ff3, 0x12fff,
- 0x13456, 0x143ff,
- 0x14647, 0x167ff,
- 0x16a39, 0x16a3f,
- 0x16a5f, 0x16a5f,
- 0x16a6a, 0x16a6d,
- 0x16abf, 0x16abf,
- 0x16aca, 0x16acf,
- 0x16aee, 0x16aef,
- 0x16af6, 0x16aff,
- 0x16b46, 0x16b4f,
- 0x16b5a, 0x16b5a,
- 0x16b62, 0x16b62,
- 0x16b78, 0x16b7c,
- 0x16b90, 0x16e3f,
- 0x16e9b, 0x16eff,
- 0x16f4b, 0x16f4e,
- 0x16f88, 0x16f8e,
- 0x16fa0, 0x16fdf,
- 0x16fe5, 0x16fef,
- 0x16ff2, 0x16fff,
- 0x187f8, 0x187ff,
- 0x18cd6, 0x18cff,
- 0x18d09, 0x1afef,
- 0x1aff4, 0x1aff4,
- 0x1affc, 0x1affc,
- 0x1afff, 0x1afff,
- 0x1b123, 0x1b131,
- 0x1b133, 0x1b14f,
- 0x1b153, 0x1b154,
- 0x1b156, 0x1b163,
- 0x1b168, 0x1b16f,
- 0x1b2fc, 0x1bbff,
- 0x1bc6b, 0x1bc6f,
- 0x1bc7d, 0x1bc7f,
- 0x1bc89, 0x1bc8f,
- 0x1bc9a, 0x1bc9b,
- 0x1bca4, 0x1ceff,
- 0x1cf2e, 0x1cf2f,
- 0x1cf47, 0x1cf4f,
- 0x1cfc4, 0x1cfff,
- 0x1d0f6, 0x1d0ff,
- 0x1d127, 0x1d128,
- 0x1d1eb, 0x1d1ff,
- 0x1d246, 0x1d2bf,
- 0x1d2d4, 0x1d2df,
- 0x1d2f4, 0x1d2ff,
- 0x1d357, 0x1d35f,
- 0x1d379, 0x1d3ff,
- 0x1d455, 0x1d455,
- 0x1d49d, 0x1d49d,
- 0x1d4a0, 0x1d4a1,
- 0x1d4a3, 0x1d4a4,
- 0x1d4a7, 0x1d4a8,
- 0x1d4ad, 0x1d4ad,
- 0x1d4ba, 0x1d4ba,
- 0x1d4bc, 0x1d4bc,
- 0x1d4c4, 0x1d4c4,
- 0x1d506, 0x1d506,
- 0x1d50b, 0x1d50c,
- 0x1d515, 0x1d515,
- 0x1d51d, 0x1d51d,
- 0x1d53a, 0x1d53a,
- 0x1d53f, 0x1d53f,
- 0x1d545, 0x1d545,
- 0x1d547, 0x1d549,
- 0x1d551, 0x1d551,
- 0x1d6a6, 0x1d6a7,
- 0x1d7cc, 0x1d7cd,
- 0x1da8c, 0x1da9a,
- 0x1daa0, 0x1daa0,
- 0x1dab0, 0x1deff,
- 0x1df1f, 0x1df24,
- 0x1df2b, 0x1dfff,
- 0x1e007, 0x1e007,
- 0x1e019, 0x1e01a,
- 0x1e022, 0x1e022,
- 0x1e025, 0x1e025,
- 0x1e02b, 0x1e02f,
- 0x1e06e, 0x1e08e,
- 0x1e090, 0x1e0ff,
- 0x1e12d, 0x1e12f,
- 0x1e13e, 0x1e13f,
- 0x1e14a, 0x1e14d,
- 0x1e150, 0x1e28f,
- 0x1e2af, 0x1e2bf,
- 0x1e2fa, 0x1e2fe,
- 0x1e300, 0x1e4cf,
- 0x1e4fa, 0x1e7df,
- 0x1e7e7, 0x1e7e7,
- 0x1e7ec, 0x1e7ec,
- 0x1e7ef, 0x1e7ef,
- 0x1e7ff, 0x1e7ff,
- 0x1e8c5, 0x1e8c6,
- 0x1e8d7, 0x1e8ff,
- 0x1e94c, 0x1e94f,
- 0x1e95a, 0x1e95d,
- 0x1e960, 0x1ec70,
- 0x1ecb5, 0x1ed00,
- 0x1ed3e, 0x1edff,
- 0x1ee04, 0x1ee04,
- 0x1ee20, 0x1ee20,
- 0x1ee23, 0x1ee23,
- 0x1ee25, 0x1ee26,
- 0x1ee28, 0x1ee28,
- 0x1ee33, 0x1ee33,
- 0x1ee38, 0x1ee38,
- 0x1ee3a, 0x1ee3a,
- 0x1ee3c, 0x1ee41,
- 0x1ee43, 0x1ee46,
- 0x1ee48, 0x1ee48,
- 0x1ee4a, 0x1ee4a,
- 0x1ee4c, 0x1ee4c,
- 0x1ee50, 0x1ee50,
- 0x1ee53, 0x1ee53,
- 0x1ee55, 0x1ee56,
- 0x1ee58, 0x1ee58,
- 0x1ee5a, 0x1ee5a,
- 0x1ee5c, 0x1ee5c,
- 0x1ee5e, 0x1ee5e,
- 0x1ee60, 0x1ee60,
- 0x1ee63, 0x1ee63,
- 0x1ee65, 0x1ee66,
- 0x1ee6b, 0x1ee6b,
- 0x1ee73, 0x1ee73,
- 0x1ee78, 0x1ee78,
- 0x1ee7d, 0x1ee7d,
- 0x1ee7f, 0x1ee7f,
- 0x1ee8a, 0x1ee8a,
- 0x1ee9c, 0x1eea0,
- 0x1eea4, 0x1eea4,
- 0x1eeaa, 0x1eeaa,
- 0x1eebc, 0x1eeef,
- 0x1eef2, 0x1efff,
- 0x1f02c, 0x1f02f,
- 0x1f094, 0x1f09f,
- 0x1f0af, 0x1f0b0,
- 0x1f0c0, 0x1f0c0,
- 0x1f0d0, 0x1f0d0,
- 0x1f0f6, 0x1f0ff,
- 0x1f1ae, 0x1f1e5,
- 0x1f203, 0x1f20f,
- 0x1f23c, 0x1f23f,
- 0x1f249, 0x1f24f,
- 0x1f252, 0x1f25f,
- 0x1f266, 0x1f2ff,
- 0x1f6d8, 0x1f6db,
- 0x1f6ed, 0x1f6ef,
- 0x1f6fd, 0x1f6ff,
- 0x1f777, 0x1f77a,
- 0x1f7da, 0x1f7df,
- 0x1f7ec, 0x1f7ef,
- 0x1f7f1, 0x1f7ff,
- 0x1f80c, 0x1f80f,
- 0x1f848, 0x1f84f,
- 0x1f85a, 0x1f85f,
- 0x1f888, 0x1f88f,
- 0x1f8ae, 0x1f8af,
- 0x1f8b2, 0x1f8ff,
- 0x1fa54, 0x1fa5f,
- 0x1fa6e, 0x1fa6f,
- 0x1fa7d, 0x1fa7f,
- 0x1fa89, 0x1fa8f,
- 0x1fabe, 0x1fabe,
- 0x1fac6, 0x1facd,
- 0x1fadc, 0x1fadf,
- 0x1fae9, 0x1faef,
- 0x1faf9, 0x1faff,
- 0x1fb93, 0x1fb93,
- 0x1fbcb, 0x1fbef,
- 0x1fbfa, 0x1ffff,
- 0x2a6e0, 0x2a6ff,
- 0x2b73a, 0x2b73f,
- 0x2b81e, 0x2b81f,
- 0x2cea2, 0x2ceaf,
- 0x2ebe1, 0x2f7ff,
- 0x2fa1e, 0x2ffff,
- 0x3134b, 0x3134f,
- 0x323b0, 0xe0000,
- 0xe0002, 0xe001f,
- 0xe0080, 0xe00ff,
- 0xe01f0, 0xeffff,
- 0xffffe, 0xfffff,
- 0x10fffe, 0x10ffff,
-}; /* CR_Cn */
-
-/* 'Co': General Category */
-static const OnigCodePoint CR_Co[] = {
- 3,
- 0xe000, 0xf8ff,
- 0xf0000, 0xffffd,
- 0x100000, 0x10fffd,
-}; /* CR_Co */
-
-/* 'Cs': General Category */
-static const OnigCodePoint CR_Cs[] = {
- 1,
- 0xd800, 0xdfff,
-}; /* CR_Cs */
-
-/* 'L': Major Category */
-static const OnigCodePoint CR_L[] = {
- 659,
- 0x0041, 0x005a,
- 0x0061, 0x007a,
- 0x00aa, 0x00aa,
- 0x00b5, 0x00b5,
- 0x00ba, 0x00ba,
- 0x00c0, 0x00d6,
- 0x00d8, 0x00f6,
- 0x00f8, 0x02c1,
- 0x02c6, 0x02d1,
- 0x02e0, 0x02e4,
- 0x02ec, 0x02ec,
- 0x02ee, 0x02ee,
- 0x0370, 0x0374,
- 0x0376, 0x0377,
- 0x037a, 0x037d,
- 0x037f, 0x037f,
- 0x0386, 0x0386,
- 0x0388, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03f5,
- 0x03f7, 0x0481,
- 0x048a, 0x052f,
- 0x0531, 0x0556,
- 0x0559, 0x0559,
- 0x0560, 0x0588,
- 0x05d0, 0x05ea,
- 0x05ef, 0x05f2,
- 0x0620, 0x064a,
- 0x066e, 0x066f,
- 0x0671, 0x06d3,
- 0x06d5, 0x06d5,
- 0x06e5, 0x06e6,
- 0x06ee, 0x06ef,
- 0x06fa, 0x06fc,
- 0x06ff, 0x06ff,
- 0x0710, 0x0710,
- 0x0712, 0x072f,
- 0x074d, 0x07a5,
- 0x07b1, 0x07b1,
- 0x07ca, 0x07ea,
- 0x07f4, 0x07f5,
- 0x07fa, 0x07fa,
- 0x0800, 0x0815,
- 0x081a, 0x081a,
- 0x0824, 0x0824,
- 0x0828, 0x0828,
- 0x0840, 0x0858,
- 0x0860, 0x086a,
- 0x0870, 0x0887,
- 0x0889, 0x088e,
- 0x08a0, 0x08c9,
- 0x0904, 0x0939,
- 0x093d, 0x093d,
- 0x0950, 0x0950,
- 0x0958, 0x0961,
- 0x0971, 0x0980,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bd, 0x09bd,
- 0x09ce, 0x09ce,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e1,
- 0x09f0, 0x09f1,
- 0x09fc, 0x09fc,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a72, 0x0a74,
- 0x0a85, 0x0a8d,
- 0x0a8f, 0x0a91,
- 0x0a93, 0x0aa8,
- 0x0aaa, 0x0ab0,
- 0x0ab2, 0x0ab3,
- 0x0ab5, 0x0ab9,
- 0x0abd, 0x0abd,
- 0x0ad0, 0x0ad0,
- 0x0ae0, 0x0ae1,
- 0x0af9, 0x0af9,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b35, 0x0b39,
- 0x0b3d, 0x0b3d,
- 0x0b5c, 0x0b5d,
- 0x0b5f, 0x0b61,
- 0x0b71, 0x0b71,
- 0x0b83, 0x0b83,
- 0x0b85, 0x0b8a,
- 0x0b8e, 0x0b90,
- 0x0b92, 0x0b95,
- 0x0b99, 0x0b9a,
- 0x0b9c, 0x0b9c,
- 0x0b9e, 0x0b9f,
- 0x0ba3, 0x0ba4,
- 0x0ba8, 0x0baa,
- 0x0bae, 0x0bb9,
- 0x0bd0, 0x0bd0,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c39,
- 0x0c3d, 0x0c3d,
- 0x0c58, 0x0c5a,
- 0x0c5d, 0x0c5d,
- 0x0c60, 0x0c61,
- 0x0c80, 0x0c80,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbd, 0x0cbd,
- 0x0cdd, 0x0cde,
- 0x0ce0, 0x0ce1,
- 0x0cf1, 0x0cf2,
- 0x0d04, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d3a,
- 0x0d3d, 0x0d3d,
- 0x0d4e, 0x0d4e,
- 0x0d54, 0x0d56,
- 0x0d5f, 0x0d61,
- 0x0d7a, 0x0d7f,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0e01, 0x0e30,
- 0x0e32, 0x0e33,
- 0x0e40, 0x0e46,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e86, 0x0e8a,
- 0x0e8c, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0eb0,
- 0x0eb2, 0x0eb3,
- 0x0ebd, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f00,
- 0x0f40, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f88, 0x0f8c,
- 0x1000, 0x102a,
- 0x103f, 0x103f,
- 0x1050, 0x1055,
- 0x105a, 0x105d,
- 0x1061, 0x1061,
- 0x1065, 0x1066,
- 0x106e, 0x1070,
- 0x1075, 0x1081,
- 0x108e, 0x108e,
- 0x10a0, 0x10c5,
- 0x10c7, 0x10c7,
- 0x10cd, 0x10cd,
- 0x10d0, 0x10fa,
- 0x10fc, 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,
- 0x1380, 0x138f,
- 0x13a0, 0x13f5,
- 0x13f8, 0x13fd,
- 0x1401, 0x166c,
- 0x166f, 0x167f,
- 0x1681, 0x169a,
- 0x16a0, 0x16ea,
- 0x16f1, 0x16f8,
- 0x1700, 0x1711,
- 0x171f, 0x1731,
- 0x1740, 0x1751,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1780, 0x17b3,
- 0x17d7, 0x17d7,
- 0x17dc, 0x17dc,
- 0x1820, 0x1878,
- 0x1880, 0x1884,
- 0x1887, 0x18a8,
- 0x18aa, 0x18aa,
- 0x18b0, 0x18f5,
- 0x1900, 0x191e,
- 0x1950, 0x196d,
- 0x1970, 0x1974,
- 0x1980, 0x19ab,
- 0x19b0, 0x19c9,
- 0x1a00, 0x1a16,
- 0x1a20, 0x1a54,
- 0x1aa7, 0x1aa7,
- 0x1b05, 0x1b33,
- 0x1b45, 0x1b4c,
- 0x1b83, 0x1ba0,
- 0x1bae, 0x1baf,
- 0x1bba, 0x1be5,
- 0x1c00, 0x1c23,
- 0x1c4d, 0x1c4f,
- 0x1c5a, 0x1c7d,
- 0x1c80, 0x1c88,
- 0x1c90, 0x1cba,
- 0x1cbd, 0x1cbf,
- 0x1ce9, 0x1cec,
- 0x1cee, 0x1cf3,
- 0x1cf5, 0x1cf6,
- 0x1cfa, 0x1cfa,
- 0x1d00, 0x1dbf,
- 0x1e00, 0x1f15,
- 0x1f18, 0x1f1d,
- 0x1f20, 0x1f45,
- 0x1f48, 0x1f4d,
- 0x1f50, 0x1f57,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f7d,
- 0x1f80, 0x1fb4,
- 0x1fb6, 0x1fbc,
- 0x1fbe, 0x1fbe,
- 0x1fc2, 0x1fc4,
- 0x1fc6, 0x1fcc,
- 0x1fd0, 0x1fd3,
- 0x1fd6, 0x1fdb,
- 0x1fe0, 0x1fec,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ffc,
- 0x2071, 0x2071,
- 0x207f, 0x207f,
- 0x2090, 0x209c,
- 0x2102, 0x2102,
- 0x2107, 0x2107,
- 0x210a, 0x2113,
- 0x2115, 0x2115,
- 0x2119, 0x211d,
- 0x2124, 0x2124,
- 0x2126, 0x2126,
- 0x2128, 0x2128,
- 0x212a, 0x212d,
- 0x212f, 0x2139,
- 0x213c, 0x213f,
- 0x2145, 0x2149,
- 0x214e, 0x214e,
- 0x2183, 0x2184,
- 0x2c00, 0x2ce4,
- 0x2ceb, 0x2cee,
- 0x2cf2, 0x2cf3,
- 0x2d00, 0x2d25,
- 0x2d27, 0x2d27,
- 0x2d2d, 0x2d2d,
- 0x2d30, 0x2d67,
- 0x2d6f, 0x2d6f,
- 0x2d80, 0x2d96,
- 0x2da0, 0x2da6,
- 0x2da8, 0x2dae,
- 0x2db0, 0x2db6,
- 0x2db8, 0x2dbe,
- 0x2dc0, 0x2dc6,
- 0x2dc8, 0x2dce,
- 0x2dd0, 0x2dd6,
- 0x2dd8, 0x2dde,
- 0x2e2f, 0x2e2f,
- 0x3005, 0x3006,
- 0x3031, 0x3035,
- 0x303b, 0x303c,
- 0x3041, 0x3096,
- 0x309d, 0x309f,
- 0x30a1, 0x30fa,
- 0x30fc, 0x30ff,
- 0x3105, 0x312f,
- 0x3131, 0x318e,
- 0x31a0, 0x31bf,
- 0x31f0, 0x31ff,
- 0x3400, 0x4dbf,
- 0x4e00, 0xa48c,
- 0xa4d0, 0xa4fd,
- 0xa500, 0xa60c,
- 0xa610, 0xa61f,
- 0xa62a, 0xa62b,
- 0xa640, 0xa66e,
- 0xa67f, 0xa69d,
- 0xa6a0, 0xa6e5,
- 0xa717, 0xa71f,
- 0xa722, 0xa788,
- 0xa78b, 0xa7ca,
- 0xa7d0, 0xa7d1,
- 0xa7d3, 0xa7d3,
- 0xa7d5, 0xa7d9,
- 0xa7f2, 0xa801,
- 0xa803, 0xa805,
- 0xa807, 0xa80a,
- 0xa80c, 0xa822,
- 0xa840, 0xa873,
- 0xa882, 0xa8b3,
- 0xa8f2, 0xa8f7,
- 0xa8fb, 0xa8fb,
- 0xa8fd, 0xa8fe,
- 0xa90a, 0xa925,
- 0xa930, 0xa946,
- 0xa960, 0xa97c,
- 0xa984, 0xa9b2,
- 0xa9cf, 0xa9cf,
- 0xa9e0, 0xa9e4,
- 0xa9e6, 0xa9ef,
- 0xa9fa, 0xa9fe,
- 0xaa00, 0xaa28,
- 0xaa40, 0xaa42,
- 0xaa44, 0xaa4b,
- 0xaa60, 0xaa76,
- 0xaa7a, 0xaa7a,
- 0xaa7e, 0xaaaf,
- 0xaab1, 0xaab1,
- 0xaab5, 0xaab6,
- 0xaab9, 0xaabd,
- 0xaac0, 0xaac0,
- 0xaac2, 0xaac2,
- 0xaadb, 0xaadd,
- 0xaae0, 0xaaea,
- 0xaaf2, 0xaaf4,
- 0xab01, 0xab06,
- 0xab09, 0xab0e,
- 0xab11, 0xab16,
- 0xab20, 0xab26,
- 0xab28, 0xab2e,
- 0xab30, 0xab5a,
- 0xab5c, 0xab69,
- 0xab70, 0xabe2,
- 0xac00, 0xd7a3,
- 0xd7b0, 0xd7c6,
- 0xd7cb, 0xd7fb,
- 0xf900, 0xfa6d,
- 0xfa70, 0xfad9,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1d, 0xfb1d,
- 0xfb1f, 0xfb28,
- 0xfb2a, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbb1,
- 0xfbd3, 0xfd3d,
- 0xfd50, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdf0, 0xfdfb,
- 0xfe70, 0xfe74,
- 0xfe76, 0xfefc,
- 0xff21, 0xff3a,
- 0xff41, 0xff5a,
- 0xff66, 0xffbe,
- 0xffc2, 0xffc7,
- 0xffca, 0xffcf,
- 0xffd2, 0xffd7,
- 0xffda, 0xffdc,
- 0x10000, 0x1000b,
- 0x1000d, 0x10026,
- 0x10028, 0x1003a,
- 0x1003c, 0x1003d,
- 0x1003f, 0x1004d,
- 0x10050, 0x1005d,
- 0x10080, 0x100fa,
- 0x10280, 0x1029c,
- 0x102a0, 0x102d0,
- 0x10300, 0x1031f,
- 0x1032d, 0x10340,
- 0x10342, 0x10349,
- 0x10350, 0x10375,
- 0x10380, 0x1039d,
- 0x103a0, 0x103c3,
- 0x103c8, 0x103cf,
- 0x10400, 0x1049d,
- 0x104b0, 0x104d3,
- 0x104d8, 0x104fb,
- 0x10500, 0x10527,
- 0x10530, 0x10563,
- 0x10570, 0x1057a,
- 0x1057c, 0x1058a,
- 0x1058c, 0x10592,
- 0x10594, 0x10595,
- 0x10597, 0x105a1,
- 0x105a3, 0x105b1,
- 0x105b3, 0x105b9,
- 0x105bb, 0x105bc,
- 0x10600, 0x10736,
- 0x10740, 0x10755,
- 0x10760, 0x10767,
- 0x10780, 0x10785,
- 0x10787, 0x107b0,
- 0x107b2, 0x107ba,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x10855,
- 0x10860, 0x10876,
- 0x10880, 0x1089e,
- 0x108e0, 0x108f2,
- 0x108f4, 0x108f5,
- 0x10900, 0x10915,
- 0x10920, 0x10939,
- 0x10980, 0x109b7,
- 0x109be, 0x109bf,
- 0x10a00, 0x10a00,
- 0x10a10, 0x10a13,
- 0x10a15, 0x10a17,
- 0x10a19, 0x10a35,
- 0x10a60, 0x10a7c,
- 0x10a80, 0x10a9c,
- 0x10ac0, 0x10ac7,
- 0x10ac9, 0x10ae4,
- 0x10b00, 0x10b35,
- 0x10b40, 0x10b55,
- 0x10b60, 0x10b72,
- 0x10b80, 0x10b91,
- 0x10c00, 0x10c48,
- 0x10c80, 0x10cb2,
- 0x10cc0, 0x10cf2,
- 0x10d00, 0x10d23,
- 0x10e80, 0x10ea9,
- 0x10eb0, 0x10eb1,
- 0x10f00, 0x10f1c,
- 0x10f27, 0x10f27,
- 0x10f30, 0x10f45,
- 0x10f70, 0x10f81,
- 0x10fb0, 0x10fc4,
- 0x10fe0, 0x10ff6,
- 0x11003, 0x11037,
- 0x11071, 0x11072,
- 0x11075, 0x11075,
- 0x11083, 0x110af,
- 0x110d0, 0x110e8,
- 0x11103, 0x11126,
- 0x11144, 0x11144,
- 0x11147, 0x11147,
- 0x11150, 0x11172,
- 0x11176, 0x11176,
- 0x11183, 0x111b2,
- 0x111c1, 0x111c4,
- 0x111da, 0x111da,
- 0x111dc, 0x111dc,
- 0x11200, 0x11211,
- 0x11213, 0x1122b,
- 0x1123f, 0x11240,
- 0x11280, 0x11286,
- 0x11288, 0x11288,
- 0x1128a, 0x1128d,
- 0x1128f, 0x1129d,
- 0x1129f, 0x112a8,
- 0x112b0, 0x112de,
- 0x11305, 0x1130c,
- 0x1130f, 0x11310,
- 0x11313, 0x11328,
- 0x1132a, 0x11330,
- 0x11332, 0x11333,
- 0x11335, 0x11339,
- 0x1133d, 0x1133d,
- 0x11350, 0x11350,
- 0x1135d, 0x11361,
- 0x11400, 0x11434,
- 0x11447, 0x1144a,
- 0x1145f, 0x11461,
- 0x11480, 0x114af,
- 0x114c4, 0x114c5,
- 0x114c7, 0x114c7,
- 0x11580, 0x115ae,
- 0x115d8, 0x115db,
- 0x11600, 0x1162f,
- 0x11644, 0x11644,
- 0x11680, 0x116aa,
- 0x116b8, 0x116b8,
- 0x11700, 0x1171a,
- 0x11740, 0x11746,
- 0x11800, 0x1182b,
- 0x118a0, 0x118df,
- 0x118ff, 0x11906,
- 0x11909, 0x11909,
- 0x1190c, 0x11913,
- 0x11915, 0x11916,
- 0x11918, 0x1192f,
- 0x1193f, 0x1193f,
- 0x11941, 0x11941,
- 0x119a0, 0x119a7,
- 0x119aa, 0x119d0,
- 0x119e1, 0x119e1,
- 0x119e3, 0x119e3,
- 0x11a00, 0x11a00,
- 0x11a0b, 0x11a32,
- 0x11a3a, 0x11a3a,
- 0x11a50, 0x11a50,
- 0x11a5c, 0x11a89,
- 0x11a9d, 0x11a9d,
- 0x11ab0, 0x11af8,
- 0x11c00, 0x11c08,
- 0x11c0a, 0x11c2e,
- 0x11c40, 0x11c40,
- 0x11c72, 0x11c8f,
- 0x11d00, 0x11d06,
- 0x11d08, 0x11d09,
- 0x11d0b, 0x11d30,
- 0x11d46, 0x11d46,
- 0x11d60, 0x11d65,
- 0x11d67, 0x11d68,
- 0x11d6a, 0x11d89,
- 0x11d98, 0x11d98,
- 0x11ee0, 0x11ef2,
- 0x11f02, 0x11f02,
- 0x11f04, 0x11f10,
- 0x11f12, 0x11f33,
- 0x11fb0, 0x11fb0,
- 0x12000, 0x12399,
- 0x12480, 0x12543,
- 0x12f90, 0x12ff0,
- 0x13000, 0x1342f,
- 0x13441, 0x13446,
- 0x14400, 0x14646,
- 0x16800, 0x16a38,
- 0x16a40, 0x16a5e,
- 0x16a70, 0x16abe,
- 0x16ad0, 0x16aed,
- 0x16b00, 0x16b2f,
- 0x16b40, 0x16b43,
- 0x16b63, 0x16b77,
- 0x16b7d, 0x16b8f,
- 0x16e40, 0x16e7f,
- 0x16f00, 0x16f4a,
- 0x16f50, 0x16f50,
- 0x16f93, 0x16f9f,
- 0x16fe0, 0x16fe1,
- 0x16fe3, 0x16fe3,
- 0x17000, 0x187f7,
- 0x18800, 0x18cd5,
- 0x18d00, 0x18d08,
- 0x1aff0, 0x1aff3,
- 0x1aff5, 0x1affb,
- 0x1affd, 0x1affe,
- 0x1b000, 0x1b122,
- 0x1b132, 0x1b132,
- 0x1b150, 0x1b152,
- 0x1b155, 0x1b155,
- 0x1b164, 0x1b167,
- 0x1b170, 0x1b2fb,
- 0x1bc00, 0x1bc6a,
- 0x1bc70, 0x1bc7c,
- 0x1bc80, 0x1bc88,
- 0x1bc90, 0x1bc99,
- 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, 0x1d6c0,
- 0x1d6c2, 0x1d6da,
- 0x1d6dc, 0x1d6fa,
- 0x1d6fc, 0x1d714,
- 0x1d716, 0x1d734,
- 0x1d736, 0x1d74e,
- 0x1d750, 0x1d76e,
- 0x1d770, 0x1d788,
- 0x1d78a, 0x1d7a8,
- 0x1d7aa, 0x1d7c2,
- 0x1d7c4, 0x1d7cb,
- 0x1df00, 0x1df1e,
- 0x1df25, 0x1df2a,
- 0x1e030, 0x1e06d,
- 0x1e100, 0x1e12c,
- 0x1e137, 0x1e13d,
- 0x1e14e, 0x1e14e,
- 0x1e290, 0x1e2ad,
- 0x1e2c0, 0x1e2eb,
- 0x1e4d0, 0x1e4eb,
- 0x1e7e0, 0x1e7e6,
- 0x1e7e8, 0x1e7eb,
- 0x1e7ed, 0x1e7ee,
- 0x1e7f0, 0x1e7fe,
- 0x1e800, 0x1e8c4,
- 0x1e900, 0x1e943,
- 0x1e94b, 0x1e94b,
- 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,
- 0x20000, 0x2a6df,
- 0x2a700, 0x2b739,
- 0x2b740, 0x2b81d,
- 0x2b820, 0x2cea1,
- 0x2ceb0, 0x2ebe0,
- 0x2f800, 0x2fa1d,
- 0x30000, 0x3134a,
- 0x31350, 0x323af,
-}; /* CR_L */
-
-/* 'LC': General Category */
-static const OnigCodePoint CR_LC[] = {
- 143,
- 0x0041, 0x005a,
- 0x0061, 0x007a,
- 0x00b5, 0x00b5,
- 0x00c0, 0x00d6,
- 0x00d8, 0x00f6,
- 0x00f8, 0x01ba,
- 0x01bc, 0x01bf,
- 0x01c4, 0x0293,
- 0x0295, 0x02af,
- 0x0370, 0x0373,
- 0x0376, 0x0377,
- 0x037b, 0x037d,
- 0x037f, 0x037f,
- 0x0386, 0x0386,
- 0x0388, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03f5,
- 0x03f7, 0x0481,
- 0x048a, 0x052f,
- 0x0531, 0x0556,
- 0x0560, 0x0588,
- 0x10a0, 0x10c5,
- 0x10c7, 0x10c7,
- 0x10cd, 0x10cd,
- 0x10d0, 0x10fa,
- 0x10fd, 0x10ff,
- 0x13a0, 0x13f5,
- 0x13f8, 0x13fd,
- 0x1c80, 0x1c88,
- 0x1c90, 0x1cba,
- 0x1cbd, 0x1cbf,
- 0x1d00, 0x1d2b,
- 0x1d6b, 0x1d77,
- 0x1d79, 0x1d9a,
- 0x1e00, 0x1f15,
- 0x1f18, 0x1f1d,
- 0x1f20, 0x1f45,
- 0x1f48, 0x1f4d,
- 0x1f50, 0x1f57,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f7d,
- 0x1f80, 0x1fb4,
- 0x1fb6, 0x1fbc,
- 0x1fbe, 0x1fbe,
- 0x1fc2, 0x1fc4,
- 0x1fc6, 0x1fcc,
- 0x1fd0, 0x1fd3,
- 0x1fd6, 0x1fdb,
- 0x1fe0, 0x1fec,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ffc,
- 0x2102, 0x2102,
- 0x2107, 0x2107,
- 0x210a, 0x2113,
- 0x2115, 0x2115,
- 0x2119, 0x211d,
- 0x2124, 0x2124,
- 0x2126, 0x2126,
- 0x2128, 0x2128,
- 0x212a, 0x212d,
- 0x212f, 0x2134,
- 0x2139, 0x2139,
- 0x213c, 0x213f,
- 0x2145, 0x2149,
- 0x214e, 0x214e,
- 0x2183, 0x2184,
- 0x2c00, 0x2c7b,
- 0x2c7e, 0x2ce4,
- 0x2ceb, 0x2cee,
- 0x2cf2, 0x2cf3,
- 0x2d00, 0x2d25,
- 0x2d27, 0x2d27,
- 0x2d2d, 0x2d2d,
- 0xa640, 0xa66d,
- 0xa680, 0xa69b,
- 0xa722, 0xa76f,
- 0xa771, 0xa787,
- 0xa78b, 0xa78e,
- 0xa790, 0xa7ca,
- 0xa7d0, 0xa7d1,
- 0xa7d3, 0xa7d3,
- 0xa7d5, 0xa7d9,
- 0xa7f5, 0xa7f6,
- 0xa7fa, 0xa7fa,
- 0xab30, 0xab5a,
- 0xab60, 0xab68,
- 0xab70, 0xabbf,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xff21, 0xff3a,
- 0xff41, 0xff5a,
- 0x10400, 0x1044f,
- 0x104b0, 0x104d3,
- 0x104d8, 0x104fb,
- 0x10570, 0x1057a,
- 0x1057c, 0x1058a,
- 0x1058c, 0x10592,
- 0x10594, 0x10595,
- 0x10597, 0x105a1,
- 0x105a3, 0x105b1,
- 0x105b3, 0x105b9,
- 0x105bb, 0x105bc,
- 0x10c80, 0x10cb2,
- 0x10cc0, 0x10cf2,
- 0x118a0, 0x118df,
- 0x16e40, 0x16e7f,
- 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, 0x1d6c0,
- 0x1d6c2, 0x1d6da,
- 0x1d6dc, 0x1d6fa,
- 0x1d6fc, 0x1d714,
- 0x1d716, 0x1d734,
- 0x1d736, 0x1d74e,
- 0x1d750, 0x1d76e,
- 0x1d770, 0x1d788,
- 0x1d78a, 0x1d7a8,
- 0x1d7aa, 0x1d7c2,
- 0x1d7c4, 0x1d7cb,
- 0x1df00, 0x1df09,
- 0x1df0b, 0x1df1e,
- 0x1df25, 0x1df2a,
- 0x1e900, 0x1e943,
-}; /* CR_LC */
-
-/* 'Ll': General Category */
-static const OnigCodePoint CR_Ll[] = {
- 658,
- 0x0061, 0x007a,
- 0x00b5, 0x00b5,
- 0x00df, 0x00f6,
- 0x00f8, 0x00ff,
- 0x0101, 0x0101,
- 0x0103, 0x0103,
- 0x0105, 0x0105,
- 0x0107, 0x0107,
- 0x0109, 0x0109,
- 0x010b, 0x010b,
- 0x010d, 0x010d,
- 0x010f, 0x010f,
- 0x0111, 0x0111,
- 0x0113, 0x0113,
- 0x0115, 0x0115,
- 0x0117, 0x0117,
- 0x0119, 0x0119,
- 0x011b, 0x011b,
- 0x011d, 0x011d,
- 0x011f, 0x011f,
- 0x0121, 0x0121,
- 0x0123, 0x0123,
- 0x0125, 0x0125,
- 0x0127, 0x0127,
- 0x0129, 0x0129,
- 0x012b, 0x012b,
- 0x012d, 0x012d,
- 0x012f, 0x012f,
- 0x0131, 0x0131,
- 0x0133, 0x0133,
- 0x0135, 0x0135,
- 0x0137, 0x0138,
- 0x013a, 0x013a,
- 0x013c, 0x013c,
- 0x013e, 0x013e,
- 0x0140, 0x0140,
- 0x0142, 0x0142,
- 0x0144, 0x0144,
- 0x0146, 0x0146,
- 0x0148, 0x0149,
- 0x014b, 0x014b,
- 0x014d, 0x014d,
- 0x014f, 0x014f,
- 0x0151, 0x0151,
- 0x0153, 0x0153,
- 0x0155, 0x0155,
- 0x0157, 0x0157,
- 0x0159, 0x0159,
- 0x015b, 0x015b,
- 0x015d, 0x015d,
- 0x015f, 0x015f,
- 0x0161, 0x0161,
- 0x0163, 0x0163,
- 0x0165, 0x0165,
- 0x0167, 0x0167,
- 0x0169, 0x0169,
- 0x016b, 0x016b,
- 0x016d, 0x016d,
- 0x016f, 0x016f,
- 0x0171, 0x0171,
- 0x0173, 0x0173,
- 0x0175, 0x0175,
- 0x0177, 0x0177,
- 0x017a, 0x017a,
- 0x017c, 0x017c,
- 0x017e, 0x0180,
- 0x0183, 0x0183,
- 0x0185, 0x0185,
- 0x0188, 0x0188,
- 0x018c, 0x018d,
- 0x0192, 0x0192,
- 0x0195, 0x0195,
- 0x0199, 0x019b,
- 0x019e, 0x019e,
- 0x01a1, 0x01a1,
- 0x01a3, 0x01a3,
- 0x01a5, 0x01a5,
- 0x01a8, 0x01a8,
- 0x01aa, 0x01ab,
- 0x01ad, 0x01ad,
- 0x01b0, 0x01b0,
- 0x01b4, 0x01b4,
- 0x01b6, 0x01b6,
- 0x01b9, 0x01ba,
- 0x01bd, 0x01bf,
- 0x01c6, 0x01c6,
- 0x01c9, 0x01c9,
- 0x01cc, 0x01cc,
- 0x01ce, 0x01ce,
- 0x01d0, 0x01d0,
- 0x01d2, 0x01d2,
- 0x01d4, 0x01d4,
- 0x01d6, 0x01d6,
- 0x01d8, 0x01d8,
- 0x01da, 0x01da,
- 0x01dc, 0x01dd,
- 0x01df, 0x01df,
- 0x01e1, 0x01e1,
- 0x01e3, 0x01e3,
- 0x01e5, 0x01e5,
- 0x01e7, 0x01e7,
- 0x01e9, 0x01e9,
- 0x01eb, 0x01eb,
- 0x01ed, 0x01ed,
- 0x01ef, 0x01f0,
- 0x01f3, 0x01f3,
- 0x01f5, 0x01f5,
- 0x01f9, 0x01f9,
- 0x01fb, 0x01fb,
- 0x01fd, 0x01fd,
- 0x01ff, 0x01ff,
- 0x0201, 0x0201,
- 0x0203, 0x0203,
- 0x0205, 0x0205,
- 0x0207, 0x0207,
- 0x0209, 0x0209,
- 0x020b, 0x020b,
- 0x020d, 0x020d,
- 0x020f, 0x020f,
- 0x0211, 0x0211,
- 0x0213, 0x0213,
- 0x0215, 0x0215,
- 0x0217, 0x0217,
- 0x0219, 0x0219,
- 0x021b, 0x021b,
- 0x021d, 0x021d,
- 0x021f, 0x021f,
- 0x0221, 0x0221,
- 0x0223, 0x0223,
- 0x0225, 0x0225,
- 0x0227, 0x0227,
- 0x0229, 0x0229,
- 0x022b, 0x022b,
- 0x022d, 0x022d,
- 0x022f, 0x022f,
- 0x0231, 0x0231,
- 0x0233, 0x0239,
- 0x023c, 0x023c,
- 0x023f, 0x0240,
- 0x0242, 0x0242,
- 0x0247, 0x0247,
- 0x0249, 0x0249,
- 0x024b, 0x024b,
- 0x024d, 0x024d,
- 0x024f, 0x0293,
- 0x0295, 0x02af,
- 0x0371, 0x0371,
- 0x0373, 0x0373,
- 0x0377, 0x0377,
- 0x037b, 0x037d,
- 0x0390, 0x0390,
- 0x03ac, 0x03ce,
- 0x03d0, 0x03d1,
- 0x03d5, 0x03d7,
- 0x03d9, 0x03d9,
- 0x03db, 0x03db,
- 0x03dd, 0x03dd,
- 0x03df, 0x03df,
- 0x03e1, 0x03e1,
- 0x03e3, 0x03e3,
- 0x03e5, 0x03e5,
- 0x03e7, 0x03e7,
- 0x03e9, 0x03e9,
- 0x03eb, 0x03eb,
- 0x03ed, 0x03ed,
- 0x03ef, 0x03f3,
- 0x03f5, 0x03f5,
- 0x03f8, 0x03f8,
- 0x03fb, 0x03fc,
- 0x0430, 0x045f,
- 0x0461, 0x0461,
- 0x0463, 0x0463,
- 0x0465, 0x0465,
- 0x0467, 0x0467,
- 0x0469, 0x0469,
- 0x046b, 0x046b,
- 0x046d, 0x046d,
- 0x046f, 0x046f,
- 0x0471, 0x0471,
- 0x0473, 0x0473,
- 0x0475, 0x0475,
- 0x0477, 0x0477,
- 0x0479, 0x0479,
- 0x047b, 0x047b,
- 0x047d, 0x047d,
- 0x047f, 0x047f,
- 0x0481, 0x0481,
- 0x048b, 0x048b,
- 0x048d, 0x048d,
- 0x048f, 0x048f,
- 0x0491, 0x0491,
- 0x0493, 0x0493,
- 0x0495, 0x0495,
- 0x0497, 0x0497,
- 0x0499, 0x0499,
- 0x049b, 0x049b,
- 0x049d, 0x049d,
- 0x049f, 0x049f,
- 0x04a1, 0x04a1,
- 0x04a3, 0x04a3,
- 0x04a5, 0x04a5,
- 0x04a7, 0x04a7,
- 0x04a9, 0x04a9,
- 0x04ab, 0x04ab,
- 0x04ad, 0x04ad,
- 0x04af, 0x04af,
- 0x04b1, 0x04b1,
- 0x04b3, 0x04b3,
- 0x04b5, 0x04b5,
- 0x04b7, 0x04b7,
- 0x04b9, 0x04b9,
- 0x04bb, 0x04bb,
- 0x04bd, 0x04bd,
- 0x04bf, 0x04bf,
- 0x04c2, 0x04c2,
- 0x04c4, 0x04c4,
- 0x04c6, 0x04c6,
- 0x04c8, 0x04c8,
- 0x04ca, 0x04ca,
- 0x04cc, 0x04cc,
- 0x04ce, 0x04cf,
- 0x04d1, 0x04d1,
- 0x04d3, 0x04d3,
- 0x04d5, 0x04d5,
- 0x04d7, 0x04d7,
- 0x04d9, 0x04d9,
- 0x04db, 0x04db,
- 0x04dd, 0x04dd,
- 0x04df, 0x04df,
- 0x04e1, 0x04e1,
- 0x04e3, 0x04e3,
- 0x04e5, 0x04e5,
- 0x04e7, 0x04e7,
- 0x04e9, 0x04e9,
- 0x04eb, 0x04eb,
- 0x04ed, 0x04ed,
- 0x04ef, 0x04ef,
- 0x04f1, 0x04f1,
- 0x04f3, 0x04f3,
- 0x04f5, 0x04f5,
- 0x04f7, 0x04f7,
- 0x04f9, 0x04f9,
- 0x04fb, 0x04fb,
- 0x04fd, 0x04fd,
- 0x04ff, 0x04ff,
- 0x0501, 0x0501,
- 0x0503, 0x0503,
- 0x0505, 0x0505,
- 0x0507, 0x0507,
- 0x0509, 0x0509,
- 0x050b, 0x050b,
- 0x050d, 0x050d,
- 0x050f, 0x050f,
- 0x0511, 0x0511,
- 0x0513, 0x0513,
- 0x0515, 0x0515,
- 0x0517, 0x0517,
- 0x0519, 0x0519,
- 0x051b, 0x051b,
- 0x051d, 0x051d,
- 0x051f, 0x051f,
- 0x0521, 0x0521,
- 0x0523, 0x0523,
- 0x0525, 0x0525,
- 0x0527, 0x0527,
- 0x0529, 0x0529,
- 0x052b, 0x052b,
- 0x052d, 0x052d,
- 0x052f, 0x052f,
- 0x0560, 0x0588,
- 0x10d0, 0x10fa,
- 0x10fd, 0x10ff,
- 0x13f8, 0x13fd,
- 0x1c80, 0x1c88,
- 0x1d00, 0x1d2b,
- 0x1d6b, 0x1d77,
- 0x1d79, 0x1d9a,
- 0x1e01, 0x1e01,
- 0x1e03, 0x1e03,
- 0x1e05, 0x1e05,
- 0x1e07, 0x1e07,
- 0x1e09, 0x1e09,
- 0x1e0b, 0x1e0b,
- 0x1e0d, 0x1e0d,
- 0x1e0f, 0x1e0f,
- 0x1e11, 0x1e11,
- 0x1e13, 0x1e13,
- 0x1e15, 0x1e15,
- 0x1e17, 0x1e17,
- 0x1e19, 0x1e19,
- 0x1e1b, 0x1e1b,
- 0x1e1d, 0x1e1d,
- 0x1e1f, 0x1e1f,
- 0x1e21, 0x1e21,
- 0x1e23, 0x1e23,
- 0x1e25, 0x1e25,
- 0x1e27, 0x1e27,
- 0x1e29, 0x1e29,
- 0x1e2b, 0x1e2b,
- 0x1e2d, 0x1e2d,
- 0x1e2f, 0x1e2f,
- 0x1e31, 0x1e31,
- 0x1e33, 0x1e33,
- 0x1e35, 0x1e35,
- 0x1e37, 0x1e37,
- 0x1e39, 0x1e39,
- 0x1e3b, 0x1e3b,
- 0x1e3d, 0x1e3d,
- 0x1e3f, 0x1e3f,
- 0x1e41, 0x1e41,
- 0x1e43, 0x1e43,
- 0x1e45, 0x1e45,
- 0x1e47, 0x1e47,
- 0x1e49, 0x1e49,
- 0x1e4b, 0x1e4b,
- 0x1e4d, 0x1e4d,
- 0x1e4f, 0x1e4f,
- 0x1e51, 0x1e51,
- 0x1e53, 0x1e53,
- 0x1e55, 0x1e55,
- 0x1e57, 0x1e57,
- 0x1e59, 0x1e59,
- 0x1e5b, 0x1e5b,
- 0x1e5d, 0x1e5d,
- 0x1e5f, 0x1e5f,
- 0x1e61, 0x1e61,
- 0x1e63, 0x1e63,
- 0x1e65, 0x1e65,
- 0x1e67, 0x1e67,
- 0x1e69, 0x1e69,
- 0x1e6b, 0x1e6b,
- 0x1e6d, 0x1e6d,
- 0x1e6f, 0x1e6f,
- 0x1e71, 0x1e71,
- 0x1e73, 0x1e73,
- 0x1e75, 0x1e75,
- 0x1e77, 0x1e77,
- 0x1e79, 0x1e79,
- 0x1e7b, 0x1e7b,
- 0x1e7d, 0x1e7d,
- 0x1e7f, 0x1e7f,
- 0x1e81, 0x1e81,
- 0x1e83, 0x1e83,
- 0x1e85, 0x1e85,
- 0x1e87, 0x1e87,
- 0x1e89, 0x1e89,
- 0x1e8b, 0x1e8b,
- 0x1e8d, 0x1e8d,
- 0x1e8f, 0x1e8f,
- 0x1e91, 0x1e91,
- 0x1e93, 0x1e93,
- 0x1e95, 0x1e9d,
- 0x1e9f, 0x1e9f,
- 0x1ea1, 0x1ea1,
- 0x1ea3, 0x1ea3,
- 0x1ea5, 0x1ea5,
- 0x1ea7, 0x1ea7,
- 0x1ea9, 0x1ea9,
- 0x1eab, 0x1eab,
- 0x1ead, 0x1ead,
- 0x1eaf, 0x1eaf,
- 0x1eb1, 0x1eb1,
- 0x1eb3, 0x1eb3,
- 0x1eb5, 0x1eb5,
- 0x1eb7, 0x1eb7,
- 0x1eb9, 0x1eb9,
- 0x1ebb, 0x1ebb,
- 0x1ebd, 0x1ebd,
- 0x1ebf, 0x1ebf,
- 0x1ec1, 0x1ec1,
- 0x1ec3, 0x1ec3,
- 0x1ec5, 0x1ec5,
- 0x1ec7, 0x1ec7,
- 0x1ec9, 0x1ec9,
- 0x1ecb, 0x1ecb,
- 0x1ecd, 0x1ecd,
- 0x1ecf, 0x1ecf,
- 0x1ed1, 0x1ed1,
- 0x1ed3, 0x1ed3,
- 0x1ed5, 0x1ed5,
- 0x1ed7, 0x1ed7,
- 0x1ed9, 0x1ed9,
- 0x1edb, 0x1edb,
- 0x1edd, 0x1edd,
- 0x1edf, 0x1edf,
- 0x1ee1, 0x1ee1,
- 0x1ee3, 0x1ee3,
- 0x1ee5, 0x1ee5,
- 0x1ee7, 0x1ee7,
- 0x1ee9, 0x1ee9,
- 0x1eeb, 0x1eeb,
- 0x1eed, 0x1eed,
- 0x1eef, 0x1eef,
- 0x1ef1, 0x1ef1,
- 0x1ef3, 0x1ef3,
- 0x1ef5, 0x1ef5,
- 0x1ef7, 0x1ef7,
- 0x1ef9, 0x1ef9,
- 0x1efb, 0x1efb,
- 0x1efd, 0x1efd,
- 0x1eff, 0x1f07,
- 0x1f10, 0x1f15,
- 0x1f20, 0x1f27,
- 0x1f30, 0x1f37,
- 0x1f40, 0x1f45,
- 0x1f50, 0x1f57,
- 0x1f60, 0x1f67,
- 0x1f70, 0x1f7d,
- 0x1f80, 0x1f87,
- 0x1f90, 0x1f97,
- 0x1fa0, 0x1fa7,
- 0x1fb0, 0x1fb4,
- 0x1fb6, 0x1fb7,
- 0x1fbe, 0x1fbe,
- 0x1fc2, 0x1fc4,
- 0x1fc6, 0x1fc7,
- 0x1fd0, 0x1fd3,
- 0x1fd6, 0x1fd7,
- 0x1fe0, 0x1fe7,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ff7,
- 0x210a, 0x210a,
- 0x210e, 0x210f,
- 0x2113, 0x2113,
- 0x212f, 0x212f,
- 0x2134, 0x2134,
- 0x2139, 0x2139,
- 0x213c, 0x213d,
- 0x2146, 0x2149,
- 0x214e, 0x214e,
- 0x2184, 0x2184,
- 0x2c30, 0x2c5f,
- 0x2c61, 0x2c61,
- 0x2c65, 0x2c66,
- 0x2c68, 0x2c68,
- 0x2c6a, 0x2c6a,
- 0x2c6c, 0x2c6c,
- 0x2c71, 0x2c71,
- 0x2c73, 0x2c74,
- 0x2c76, 0x2c7b,
- 0x2c81, 0x2c81,
- 0x2c83, 0x2c83,
- 0x2c85, 0x2c85,
- 0x2c87, 0x2c87,
- 0x2c89, 0x2c89,
- 0x2c8b, 0x2c8b,
- 0x2c8d, 0x2c8d,
- 0x2c8f, 0x2c8f,
- 0x2c91, 0x2c91,
- 0x2c93, 0x2c93,
- 0x2c95, 0x2c95,
- 0x2c97, 0x2c97,
- 0x2c99, 0x2c99,
- 0x2c9b, 0x2c9b,
- 0x2c9d, 0x2c9d,
- 0x2c9f, 0x2c9f,
- 0x2ca1, 0x2ca1,
- 0x2ca3, 0x2ca3,
- 0x2ca5, 0x2ca5,
- 0x2ca7, 0x2ca7,
- 0x2ca9, 0x2ca9,
- 0x2cab, 0x2cab,
- 0x2cad, 0x2cad,
- 0x2caf, 0x2caf,
- 0x2cb1, 0x2cb1,
- 0x2cb3, 0x2cb3,
- 0x2cb5, 0x2cb5,
- 0x2cb7, 0x2cb7,
- 0x2cb9, 0x2cb9,
- 0x2cbb, 0x2cbb,
- 0x2cbd, 0x2cbd,
- 0x2cbf, 0x2cbf,
- 0x2cc1, 0x2cc1,
- 0x2cc3, 0x2cc3,
- 0x2cc5, 0x2cc5,
- 0x2cc7, 0x2cc7,
- 0x2cc9, 0x2cc9,
- 0x2ccb, 0x2ccb,
- 0x2ccd, 0x2ccd,
- 0x2ccf, 0x2ccf,
- 0x2cd1, 0x2cd1,
- 0x2cd3, 0x2cd3,
- 0x2cd5, 0x2cd5,
- 0x2cd7, 0x2cd7,
- 0x2cd9, 0x2cd9,
- 0x2cdb, 0x2cdb,
- 0x2cdd, 0x2cdd,
- 0x2cdf, 0x2cdf,
- 0x2ce1, 0x2ce1,
- 0x2ce3, 0x2ce4,
- 0x2cec, 0x2cec,
- 0x2cee, 0x2cee,
- 0x2cf3, 0x2cf3,
- 0x2d00, 0x2d25,
- 0x2d27, 0x2d27,
- 0x2d2d, 0x2d2d,
- 0xa641, 0xa641,
- 0xa643, 0xa643,
- 0xa645, 0xa645,
- 0xa647, 0xa647,
- 0xa649, 0xa649,
- 0xa64b, 0xa64b,
- 0xa64d, 0xa64d,
- 0xa64f, 0xa64f,
- 0xa651, 0xa651,
- 0xa653, 0xa653,
- 0xa655, 0xa655,
- 0xa657, 0xa657,
- 0xa659, 0xa659,
- 0xa65b, 0xa65b,
- 0xa65d, 0xa65d,
- 0xa65f, 0xa65f,
- 0xa661, 0xa661,
- 0xa663, 0xa663,
- 0xa665, 0xa665,
- 0xa667, 0xa667,
- 0xa669, 0xa669,
- 0xa66b, 0xa66b,
- 0xa66d, 0xa66d,
- 0xa681, 0xa681,
- 0xa683, 0xa683,
- 0xa685, 0xa685,
- 0xa687, 0xa687,
- 0xa689, 0xa689,
- 0xa68b, 0xa68b,
- 0xa68d, 0xa68d,
- 0xa68f, 0xa68f,
- 0xa691, 0xa691,
- 0xa693, 0xa693,
- 0xa695, 0xa695,
- 0xa697, 0xa697,
- 0xa699, 0xa699,
- 0xa69b, 0xa69b,
- 0xa723, 0xa723,
- 0xa725, 0xa725,
- 0xa727, 0xa727,
- 0xa729, 0xa729,
- 0xa72b, 0xa72b,
- 0xa72d, 0xa72d,
- 0xa72f, 0xa731,
- 0xa733, 0xa733,
- 0xa735, 0xa735,
- 0xa737, 0xa737,
- 0xa739, 0xa739,
- 0xa73b, 0xa73b,
- 0xa73d, 0xa73d,
- 0xa73f, 0xa73f,
- 0xa741, 0xa741,
- 0xa743, 0xa743,
- 0xa745, 0xa745,
- 0xa747, 0xa747,
- 0xa749, 0xa749,
- 0xa74b, 0xa74b,
- 0xa74d, 0xa74d,
- 0xa74f, 0xa74f,
- 0xa751, 0xa751,
- 0xa753, 0xa753,
- 0xa755, 0xa755,
- 0xa757, 0xa757,
- 0xa759, 0xa759,
- 0xa75b, 0xa75b,
- 0xa75d, 0xa75d,
- 0xa75f, 0xa75f,
- 0xa761, 0xa761,
- 0xa763, 0xa763,
- 0xa765, 0xa765,
- 0xa767, 0xa767,
- 0xa769, 0xa769,
- 0xa76b, 0xa76b,
- 0xa76d, 0xa76d,
- 0xa76f, 0xa76f,
- 0xa771, 0xa778,
- 0xa77a, 0xa77a,
- 0xa77c, 0xa77c,
- 0xa77f, 0xa77f,
- 0xa781, 0xa781,
- 0xa783, 0xa783,
- 0xa785, 0xa785,
- 0xa787, 0xa787,
- 0xa78c, 0xa78c,
- 0xa78e, 0xa78e,
- 0xa791, 0xa791,
- 0xa793, 0xa795,
- 0xa797, 0xa797,
- 0xa799, 0xa799,
- 0xa79b, 0xa79b,
- 0xa79d, 0xa79d,
- 0xa79f, 0xa79f,
- 0xa7a1, 0xa7a1,
- 0xa7a3, 0xa7a3,
- 0xa7a5, 0xa7a5,
- 0xa7a7, 0xa7a7,
- 0xa7a9, 0xa7a9,
- 0xa7af, 0xa7af,
- 0xa7b5, 0xa7b5,
- 0xa7b7, 0xa7b7,
- 0xa7b9, 0xa7b9,
- 0xa7bb, 0xa7bb,
- 0xa7bd, 0xa7bd,
- 0xa7bf, 0xa7bf,
- 0xa7c1, 0xa7c1,
- 0xa7c3, 0xa7c3,
- 0xa7c8, 0xa7c8,
- 0xa7ca, 0xa7ca,
- 0xa7d1, 0xa7d1,
- 0xa7d3, 0xa7d3,
- 0xa7d5, 0xa7d5,
- 0xa7d7, 0xa7d7,
- 0xa7d9, 0xa7d9,
- 0xa7f6, 0xa7f6,
- 0xa7fa, 0xa7fa,
- 0xab30, 0xab5a,
- 0xab60, 0xab68,
- 0xab70, 0xabbf,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xff41, 0xff5a,
- 0x10428, 0x1044f,
- 0x104d8, 0x104fb,
- 0x10597, 0x105a1,
- 0x105a3, 0x105b1,
- 0x105b3, 0x105b9,
- 0x105bb, 0x105bc,
- 0x10cc0, 0x10cf2,
- 0x118c0, 0x118df,
- 0x16e60, 0x16e7f,
- 0x1d41a, 0x1d433,
- 0x1d44e, 0x1d454,
- 0x1d456, 0x1d467,
- 0x1d482, 0x1d49b,
- 0x1d4b6, 0x1d4b9,
- 0x1d4bb, 0x1d4bb,
- 0x1d4bd, 0x1d4c3,
- 0x1d4c5, 0x1d4cf,
- 0x1d4ea, 0x1d503,
- 0x1d51e, 0x1d537,
- 0x1d552, 0x1d56b,
- 0x1d586, 0x1d59f,
- 0x1d5ba, 0x1d5d3,
- 0x1d5ee, 0x1d607,
- 0x1d622, 0x1d63b,
- 0x1d656, 0x1d66f,
- 0x1d68a, 0x1d6a5,
- 0x1d6c2, 0x1d6da,
- 0x1d6dc, 0x1d6e1,
- 0x1d6fc, 0x1d714,
- 0x1d716, 0x1d71b,
- 0x1d736, 0x1d74e,
- 0x1d750, 0x1d755,
- 0x1d770, 0x1d788,
- 0x1d78a, 0x1d78f,
- 0x1d7aa, 0x1d7c2,
- 0x1d7c4, 0x1d7c9,
- 0x1d7cb, 0x1d7cb,
- 0x1df00, 0x1df09,
- 0x1df0b, 0x1df1e,
- 0x1df25, 0x1df2a,
- 0x1e922, 0x1e943,
-}; /* CR_Ll */
-
-/* 'Lm': General Category */
-static const OnigCodePoint CR_Lm[] = {
- 71,
- 0x02b0, 0x02c1,
- 0x02c6, 0x02d1,
- 0x02e0, 0x02e4,
- 0x02ec, 0x02ec,
- 0x02ee, 0x02ee,
- 0x0374, 0x0374,
- 0x037a, 0x037a,
- 0x0559, 0x0559,
- 0x0640, 0x0640,
- 0x06e5, 0x06e6,
- 0x07f4, 0x07f5,
- 0x07fa, 0x07fa,
- 0x081a, 0x081a,
- 0x0824, 0x0824,
- 0x0828, 0x0828,
- 0x08c9, 0x08c9,
- 0x0971, 0x0971,
- 0x0e46, 0x0e46,
- 0x0ec6, 0x0ec6,
- 0x10fc, 0x10fc,
- 0x17d7, 0x17d7,
- 0x1843, 0x1843,
- 0x1aa7, 0x1aa7,
- 0x1c78, 0x1c7d,
- 0x1d2c, 0x1d6a,
- 0x1d78, 0x1d78,
- 0x1d9b, 0x1dbf,
- 0x2071, 0x2071,
- 0x207f, 0x207f,
- 0x2090, 0x209c,
- 0x2c7c, 0x2c7d,
- 0x2d6f, 0x2d6f,
- 0x2e2f, 0x2e2f,
- 0x3005, 0x3005,
- 0x3031, 0x3035,
- 0x303b, 0x303b,
- 0x309d, 0x309e,
- 0x30fc, 0x30fe,
- 0xa015, 0xa015,
- 0xa4f8, 0xa4fd,
- 0xa60c, 0xa60c,
- 0xa67f, 0xa67f,
- 0xa69c, 0xa69d,
- 0xa717, 0xa71f,
- 0xa770, 0xa770,
- 0xa788, 0xa788,
- 0xa7f2, 0xa7f4,
- 0xa7f8, 0xa7f9,
- 0xa9cf, 0xa9cf,
- 0xa9e6, 0xa9e6,
- 0xaa70, 0xaa70,
- 0xaadd, 0xaadd,
- 0xaaf3, 0xaaf4,
- 0xab5c, 0xab5f,
- 0xab69, 0xab69,
- 0xff70, 0xff70,
- 0xff9e, 0xff9f,
- 0x10780, 0x10785,
- 0x10787, 0x107b0,
- 0x107b2, 0x107ba,
- 0x16b40, 0x16b43,
- 0x16f93, 0x16f9f,
- 0x16fe0, 0x16fe1,
- 0x16fe3, 0x16fe3,
- 0x1aff0, 0x1aff3,
- 0x1aff5, 0x1affb,
- 0x1affd, 0x1affe,
- 0x1e030, 0x1e06d,
- 0x1e137, 0x1e13d,
- 0x1e4eb, 0x1e4eb,
- 0x1e94b, 0x1e94b,
-}; /* CR_Lm */
-
-/* 'Lo': General Category */
-static const OnigCodePoint CR_Lo[] = {
- 510,
- 0x00aa, 0x00aa,
- 0x00ba, 0x00ba,
- 0x01bb, 0x01bb,
- 0x01c0, 0x01c3,
- 0x0294, 0x0294,
- 0x05d0, 0x05ea,
- 0x05ef, 0x05f2,
- 0x0620, 0x063f,
- 0x0641, 0x064a,
- 0x066e, 0x066f,
- 0x0671, 0x06d3,
- 0x06d5, 0x06d5,
- 0x06ee, 0x06ef,
- 0x06fa, 0x06fc,
- 0x06ff, 0x06ff,
- 0x0710, 0x0710,
- 0x0712, 0x072f,
- 0x074d, 0x07a5,
- 0x07b1, 0x07b1,
- 0x07ca, 0x07ea,
- 0x0800, 0x0815,
- 0x0840, 0x0858,
- 0x0860, 0x086a,
- 0x0870, 0x0887,
- 0x0889, 0x088e,
- 0x08a0, 0x08c8,
- 0x0904, 0x0939,
- 0x093d, 0x093d,
- 0x0950, 0x0950,
- 0x0958, 0x0961,
- 0x0972, 0x0980,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bd, 0x09bd,
- 0x09ce, 0x09ce,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e1,
- 0x09f0, 0x09f1,
- 0x09fc, 0x09fc,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a72, 0x0a74,
- 0x0a85, 0x0a8d,
- 0x0a8f, 0x0a91,
- 0x0a93, 0x0aa8,
- 0x0aaa, 0x0ab0,
- 0x0ab2, 0x0ab3,
- 0x0ab5, 0x0ab9,
- 0x0abd, 0x0abd,
- 0x0ad0, 0x0ad0,
- 0x0ae0, 0x0ae1,
- 0x0af9, 0x0af9,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b35, 0x0b39,
- 0x0b3d, 0x0b3d,
- 0x0b5c, 0x0b5d,
- 0x0b5f, 0x0b61,
- 0x0b71, 0x0b71,
- 0x0b83, 0x0b83,
- 0x0b85, 0x0b8a,
- 0x0b8e, 0x0b90,
- 0x0b92, 0x0b95,
- 0x0b99, 0x0b9a,
- 0x0b9c, 0x0b9c,
- 0x0b9e, 0x0b9f,
- 0x0ba3, 0x0ba4,
- 0x0ba8, 0x0baa,
- 0x0bae, 0x0bb9,
- 0x0bd0, 0x0bd0,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c39,
- 0x0c3d, 0x0c3d,
- 0x0c58, 0x0c5a,
- 0x0c5d, 0x0c5d,
- 0x0c60, 0x0c61,
- 0x0c80, 0x0c80,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbd, 0x0cbd,
- 0x0cdd, 0x0cde,
- 0x0ce0, 0x0ce1,
- 0x0cf1, 0x0cf2,
- 0x0d04, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d3a,
- 0x0d3d, 0x0d3d,
- 0x0d4e, 0x0d4e,
- 0x0d54, 0x0d56,
- 0x0d5f, 0x0d61,
- 0x0d7a, 0x0d7f,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0e01, 0x0e30,
- 0x0e32, 0x0e33,
- 0x0e40, 0x0e45,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e86, 0x0e8a,
- 0x0e8c, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0eb0,
- 0x0eb2, 0x0eb3,
- 0x0ebd, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f00,
- 0x0f40, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f88, 0x0f8c,
- 0x1000, 0x102a,
- 0x103f, 0x103f,
- 0x1050, 0x1055,
- 0x105a, 0x105d,
- 0x1061, 0x1061,
- 0x1065, 0x1066,
- 0x106e, 0x1070,
- 0x1075, 0x1081,
- 0x108e, 0x108e,
- 0x1100, 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,
- 0x1380, 0x138f,
- 0x1401, 0x166c,
- 0x166f, 0x167f,
- 0x1681, 0x169a,
- 0x16a0, 0x16ea,
- 0x16f1, 0x16f8,
- 0x1700, 0x1711,
- 0x171f, 0x1731,
- 0x1740, 0x1751,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1780, 0x17b3,
- 0x17dc, 0x17dc,
- 0x1820, 0x1842,
- 0x1844, 0x1878,
- 0x1880, 0x1884,
- 0x1887, 0x18a8,
- 0x18aa, 0x18aa,
- 0x18b0, 0x18f5,
- 0x1900, 0x191e,
- 0x1950, 0x196d,
- 0x1970, 0x1974,
- 0x1980, 0x19ab,
- 0x19b0, 0x19c9,
- 0x1a00, 0x1a16,
- 0x1a20, 0x1a54,
- 0x1b05, 0x1b33,
- 0x1b45, 0x1b4c,
- 0x1b83, 0x1ba0,
- 0x1bae, 0x1baf,
- 0x1bba, 0x1be5,
- 0x1c00, 0x1c23,
- 0x1c4d, 0x1c4f,
- 0x1c5a, 0x1c77,
- 0x1ce9, 0x1cec,
- 0x1cee, 0x1cf3,
- 0x1cf5, 0x1cf6,
- 0x1cfa, 0x1cfa,
- 0x2135, 0x2138,
- 0x2d30, 0x2d67,
- 0x2d80, 0x2d96,
- 0x2da0, 0x2da6,
- 0x2da8, 0x2dae,
- 0x2db0, 0x2db6,
- 0x2db8, 0x2dbe,
- 0x2dc0, 0x2dc6,
- 0x2dc8, 0x2dce,
- 0x2dd0, 0x2dd6,
- 0x2dd8, 0x2dde,
- 0x3006, 0x3006,
- 0x303c, 0x303c,
- 0x3041, 0x3096,
- 0x309f, 0x309f,
- 0x30a1, 0x30fa,
- 0x30ff, 0x30ff,
- 0x3105, 0x312f,
- 0x3131, 0x318e,
- 0x31a0, 0x31bf,
- 0x31f0, 0x31ff,
- 0x3400, 0x4dbf,
- 0x4e00, 0xa014,
- 0xa016, 0xa48c,
- 0xa4d0, 0xa4f7,
- 0xa500, 0xa60b,
- 0xa610, 0xa61f,
- 0xa62a, 0xa62b,
- 0xa66e, 0xa66e,
- 0xa6a0, 0xa6e5,
- 0xa78f, 0xa78f,
- 0xa7f7, 0xa7f7,
- 0xa7fb, 0xa801,
- 0xa803, 0xa805,
- 0xa807, 0xa80a,
- 0xa80c, 0xa822,
- 0xa840, 0xa873,
- 0xa882, 0xa8b3,
- 0xa8f2, 0xa8f7,
- 0xa8fb, 0xa8fb,
- 0xa8fd, 0xa8fe,
- 0xa90a, 0xa925,
- 0xa930, 0xa946,
- 0xa960, 0xa97c,
- 0xa984, 0xa9b2,
- 0xa9e0, 0xa9e4,
- 0xa9e7, 0xa9ef,
- 0xa9fa, 0xa9fe,
- 0xaa00, 0xaa28,
- 0xaa40, 0xaa42,
- 0xaa44, 0xaa4b,
- 0xaa60, 0xaa6f,
- 0xaa71, 0xaa76,
- 0xaa7a, 0xaa7a,
- 0xaa7e, 0xaaaf,
- 0xaab1, 0xaab1,
- 0xaab5, 0xaab6,
- 0xaab9, 0xaabd,
- 0xaac0, 0xaac0,
- 0xaac2, 0xaac2,
- 0xaadb, 0xaadc,
- 0xaae0, 0xaaea,
- 0xaaf2, 0xaaf2,
- 0xab01, 0xab06,
- 0xab09, 0xab0e,
- 0xab11, 0xab16,
- 0xab20, 0xab26,
- 0xab28, 0xab2e,
- 0xabc0, 0xabe2,
- 0xac00, 0xd7a3,
- 0xd7b0, 0xd7c6,
- 0xd7cb, 0xd7fb,
- 0xf900, 0xfa6d,
- 0xfa70, 0xfad9,
- 0xfb1d, 0xfb1d,
- 0xfb1f, 0xfb28,
- 0xfb2a, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbb1,
- 0xfbd3, 0xfd3d,
- 0xfd50, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdf0, 0xfdfb,
- 0xfe70, 0xfe74,
- 0xfe76, 0xfefc,
- 0xff66, 0xff6f,
- 0xff71, 0xff9d,
- 0xffa0, 0xffbe,
- 0xffc2, 0xffc7,
- 0xffca, 0xffcf,
- 0xffd2, 0xffd7,
- 0xffda, 0xffdc,
- 0x10000, 0x1000b,
- 0x1000d, 0x10026,
- 0x10028, 0x1003a,
- 0x1003c, 0x1003d,
- 0x1003f, 0x1004d,
- 0x10050, 0x1005d,
- 0x10080, 0x100fa,
- 0x10280, 0x1029c,
- 0x102a0, 0x102d0,
- 0x10300, 0x1031f,
- 0x1032d, 0x10340,
- 0x10342, 0x10349,
- 0x10350, 0x10375,
- 0x10380, 0x1039d,
- 0x103a0, 0x103c3,
- 0x103c8, 0x103cf,
- 0x10450, 0x1049d,
- 0x10500, 0x10527,
- 0x10530, 0x10563,
- 0x10600, 0x10736,
- 0x10740, 0x10755,
- 0x10760, 0x10767,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x10855,
- 0x10860, 0x10876,
- 0x10880, 0x1089e,
- 0x108e0, 0x108f2,
- 0x108f4, 0x108f5,
- 0x10900, 0x10915,
- 0x10920, 0x10939,
- 0x10980, 0x109b7,
- 0x109be, 0x109bf,
- 0x10a00, 0x10a00,
- 0x10a10, 0x10a13,
- 0x10a15, 0x10a17,
- 0x10a19, 0x10a35,
- 0x10a60, 0x10a7c,
- 0x10a80, 0x10a9c,
- 0x10ac0, 0x10ac7,
- 0x10ac9, 0x10ae4,
- 0x10b00, 0x10b35,
- 0x10b40, 0x10b55,
- 0x10b60, 0x10b72,
- 0x10b80, 0x10b91,
- 0x10c00, 0x10c48,
- 0x10d00, 0x10d23,
- 0x10e80, 0x10ea9,
- 0x10eb0, 0x10eb1,
- 0x10f00, 0x10f1c,
- 0x10f27, 0x10f27,
- 0x10f30, 0x10f45,
- 0x10f70, 0x10f81,
- 0x10fb0, 0x10fc4,
- 0x10fe0, 0x10ff6,
- 0x11003, 0x11037,
- 0x11071, 0x11072,
- 0x11075, 0x11075,
- 0x11083, 0x110af,
- 0x110d0, 0x110e8,
- 0x11103, 0x11126,
- 0x11144, 0x11144,
- 0x11147, 0x11147,
- 0x11150, 0x11172,
- 0x11176, 0x11176,
- 0x11183, 0x111b2,
- 0x111c1, 0x111c4,
- 0x111da, 0x111da,
- 0x111dc, 0x111dc,
- 0x11200, 0x11211,
- 0x11213, 0x1122b,
- 0x1123f, 0x11240,
- 0x11280, 0x11286,
- 0x11288, 0x11288,
- 0x1128a, 0x1128d,
- 0x1128f, 0x1129d,
- 0x1129f, 0x112a8,
- 0x112b0, 0x112de,
- 0x11305, 0x1130c,
- 0x1130f, 0x11310,
- 0x11313, 0x11328,
- 0x1132a, 0x11330,
- 0x11332, 0x11333,
- 0x11335, 0x11339,
- 0x1133d, 0x1133d,
- 0x11350, 0x11350,
- 0x1135d, 0x11361,
- 0x11400, 0x11434,
- 0x11447, 0x1144a,
- 0x1145f, 0x11461,
- 0x11480, 0x114af,
- 0x114c4, 0x114c5,
- 0x114c7, 0x114c7,
- 0x11580, 0x115ae,
- 0x115d8, 0x115db,
- 0x11600, 0x1162f,
- 0x11644, 0x11644,
- 0x11680, 0x116aa,
- 0x116b8, 0x116b8,
- 0x11700, 0x1171a,
- 0x11740, 0x11746,
- 0x11800, 0x1182b,
- 0x118ff, 0x11906,
- 0x11909, 0x11909,
- 0x1190c, 0x11913,
- 0x11915, 0x11916,
- 0x11918, 0x1192f,
- 0x1193f, 0x1193f,
- 0x11941, 0x11941,
- 0x119a0, 0x119a7,
- 0x119aa, 0x119d0,
- 0x119e1, 0x119e1,
- 0x119e3, 0x119e3,
- 0x11a00, 0x11a00,
- 0x11a0b, 0x11a32,
- 0x11a3a, 0x11a3a,
- 0x11a50, 0x11a50,
- 0x11a5c, 0x11a89,
- 0x11a9d, 0x11a9d,
- 0x11ab0, 0x11af8,
- 0x11c00, 0x11c08,
- 0x11c0a, 0x11c2e,
- 0x11c40, 0x11c40,
- 0x11c72, 0x11c8f,
- 0x11d00, 0x11d06,
- 0x11d08, 0x11d09,
- 0x11d0b, 0x11d30,
- 0x11d46, 0x11d46,
- 0x11d60, 0x11d65,
- 0x11d67, 0x11d68,
- 0x11d6a, 0x11d89,
- 0x11d98, 0x11d98,
- 0x11ee0, 0x11ef2,
- 0x11f02, 0x11f02,
- 0x11f04, 0x11f10,
- 0x11f12, 0x11f33,
- 0x11fb0, 0x11fb0,
- 0x12000, 0x12399,
- 0x12480, 0x12543,
- 0x12f90, 0x12ff0,
- 0x13000, 0x1342f,
- 0x13441, 0x13446,
- 0x14400, 0x14646,
- 0x16800, 0x16a38,
- 0x16a40, 0x16a5e,
- 0x16a70, 0x16abe,
- 0x16ad0, 0x16aed,
- 0x16b00, 0x16b2f,
- 0x16b63, 0x16b77,
- 0x16b7d, 0x16b8f,
- 0x16f00, 0x16f4a,
- 0x16f50, 0x16f50,
- 0x17000, 0x187f7,
- 0x18800, 0x18cd5,
- 0x18d00, 0x18d08,
- 0x1b000, 0x1b122,
- 0x1b132, 0x1b132,
- 0x1b150, 0x1b152,
- 0x1b155, 0x1b155,
- 0x1b164, 0x1b167,
- 0x1b170, 0x1b2fb,
- 0x1bc00, 0x1bc6a,
- 0x1bc70, 0x1bc7c,
- 0x1bc80, 0x1bc88,
- 0x1bc90, 0x1bc99,
- 0x1df0a, 0x1df0a,
- 0x1e100, 0x1e12c,
- 0x1e14e, 0x1e14e,
- 0x1e290, 0x1e2ad,
- 0x1e2c0, 0x1e2eb,
- 0x1e4d0, 0x1e4ea,
- 0x1e7e0, 0x1e7e6,
- 0x1e7e8, 0x1e7eb,
- 0x1e7ed, 0x1e7ee,
- 0x1e7f0, 0x1e7fe,
- 0x1e800, 0x1e8c4,
- 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,
- 0x20000, 0x2a6df,
- 0x2a700, 0x2b739,
- 0x2b740, 0x2b81d,
- 0x2b820, 0x2cea1,
- 0x2ceb0, 0x2ebe0,
- 0x2f800, 0x2fa1d,
- 0x30000, 0x3134a,
- 0x31350, 0x323af,
-}; /* CR_Lo */
-
-/* 'Lt': General Category */
-static const OnigCodePoint CR_Lt[] = {
- 10,
- 0x01c5, 0x01c5,
- 0x01c8, 0x01c8,
- 0x01cb, 0x01cb,
- 0x01f2, 0x01f2,
- 0x1f88, 0x1f8f,
- 0x1f98, 0x1f9f,
- 0x1fa8, 0x1faf,
- 0x1fbc, 0x1fbc,
- 0x1fcc, 0x1fcc,
- 0x1ffc, 0x1ffc,
-}; /* CR_Lt */
-
-/* 'Lu': General Category */
-static const OnigCodePoint CR_Lu[] = {
- 646,
- 0x0041, 0x005a,
- 0x00c0, 0x00d6,
- 0x00d8, 0x00de,
- 0x0100, 0x0100,
- 0x0102, 0x0102,
- 0x0104, 0x0104,
- 0x0106, 0x0106,
- 0x0108, 0x0108,
- 0x010a, 0x010a,
- 0x010c, 0x010c,
- 0x010e, 0x010e,
- 0x0110, 0x0110,
- 0x0112, 0x0112,
- 0x0114, 0x0114,
- 0x0116, 0x0116,
- 0x0118, 0x0118,
- 0x011a, 0x011a,
- 0x011c, 0x011c,
- 0x011e, 0x011e,
- 0x0120, 0x0120,
- 0x0122, 0x0122,
- 0x0124, 0x0124,
- 0x0126, 0x0126,
- 0x0128, 0x0128,
- 0x012a, 0x012a,
- 0x012c, 0x012c,
- 0x012e, 0x012e,
- 0x0130, 0x0130,
- 0x0132, 0x0132,
- 0x0134, 0x0134,
- 0x0136, 0x0136,
- 0x0139, 0x0139,
- 0x013b, 0x013b,
- 0x013d, 0x013d,
- 0x013f, 0x013f,
- 0x0141, 0x0141,
- 0x0143, 0x0143,
- 0x0145, 0x0145,
- 0x0147, 0x0147,
- 0x014a, 0x014a,
- 0x014c, 0x014c,
- 0x014e, 0x014e,
- 0x0150, 0x0150,
- 0x0152, 0x0152,
- 0x0154, 0x0154,
- 0x0156, 0x0156,
- 0x0158, 0x0158,
- 0x015a, 0x015a,
- 0x015c, 0x015c,
- 0x015e, 0x015e,
- 0x0160, 0x0160,
- 0x0162, 0x0162,
- 0x0164, 0x0164,
- 0x0166, 0x0166,
- 0x0168, 0x0168,
- 0x016a, 0x016a,
- 0x016c, 0x016c,
- 0x016e, 0x016e,
- 0x0170, 0x0170,
- 0x0172, 0x0172,
- 0x0174, 0x0174,
- 0x0176, 0x0176,
- 0x0178, 0x0179,
- 0x017b, 0x017b,
- 0x017d, 0x017d,
- 0x0181, 0x0182,
- 0x0184, 0x0184,
- 0x0186, 0x0187,
- 0x0189, 0x018b,
- 0x018e, 0x0191,
- 0x0193, 0x0194,
- 0x0196, 0x0198,
- 0x019c, 0x019d,
- 0x019f, 0x01a0,
- 0x01a2, 0x01a2,
- 0x01a4, 0x01a4,
- 0x01a6, 0x01a7,
- 0x01a9, 0x01a9,
- 0x01ac, 0x01ac,
- 0x01ae, 0x01af,
- 0x01b1, 0x01b3,
- 0x01b5, 0x01b5,
- 0x01b7, 0x01b8,
- 0x01bc, 0x01bc,
- 0x01c4, 0x01c4,
- 0x01c7, 0x01c7,
- 0x01ca, 0x01ca,
- 0x01cd, 0x01cd,
- 0x01cf, 0x01cf,
- 0x01d1, 0x01d1,
- 0x01d3, 0x01d3,
- 0x01d5, 0x01d5,
- 0x01d7, 0x01d7,
- 0x01d9, 0x01d9,
- 0x01db, 0x01db,
- 0x01de, 0x01de,
- 0x01e0, 0x01e0,
- 0x01e2, 0x01e2,
- 0x01e4, 0x01e4,
- 0x01e6, 0x01e6,
- 0x01e8, 0x01e8,
- 0x01ea, 0x01ea,
- 0x01ec, 0x01ec,
- 0x01ee, 0x01ee,
- 0x01f1, 0x01f1,
- 0x01f4, 0x01f4,
- 0x01f6, 0x01f8,
- 0x01fa, 0x01fa,
- 0x01fc, 0x01fc,
- 0x01fe, 0x01fe,
- 0x0200, 0x0200,
- 0x0202, 0x0202,
- 0x0204, 0x0204,
- 0x0206, 0x0206,
- 0x0208, 0x0208,
- 0x020a, 0x020a,
- 0x020c, 0x020c,
- 0x020e, 0x020e,
- 0x0210, 0x0210,
- 0x0212, 0x0212,
- 0x0214, 0x0214,
- 0x0216, 0x0216,
- 0x0218, 0x0218,
- 0x021a, 0x021a,
- 0x021c, 0x021c,
- 0x021e, 0x021e,
- 0x0220, 0x0220,
- 0x0222, 0x0222,
- 0x0224, 0x0224,
- 0x0226, 0x0226,
- 0x0228, 0x0228,
- 0x022a, 0x022a,
- 0x022c, 0x022c,
- 0x022e, 0x022e,
- 0x0230, 0x0230,
- 0x0232, 0x0232,
- 0x023a, 0x023b,
- 0x023d, 0x023e,
- 0x0241, 0x0241,
- 0x0243, 0x0246,
- 0x0248, 0x0248,
- 0x024a, 0x024a,
- 0x024c, 0x024c,
- 0x024e, 0x024e,
- 0x0370, 0x0370,
- 0x0372, 0x0372,
- 0x0376, 0x0376,
- 0x037f, 0x037f,
- 0x0386, 0x0386,
- 0x0388, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x038f,
- 0x0391, 0x03a1,
- 0x03a3, 0x03ab,
- 0x03cf, 0x03cf,
- 0x03d2, 0x03d4,
- 0x03d8, 0x03d8,
- 0x03da, 0x03da,
- 0x03dc, 0x03dc,
- 0x03de, 0x03de,
- 0x03e0, 0x03e0,
- 0x03e2, 0x03e2,
- 0x03e4, 0x03e4,
- 0x03e6, 0x03e6,
- 0x03e8, 0x03e8,
- 0x03ea, 0x03ea,
- 0x03ec, 0x03ec,
- 0x03ee, 0x03ee,
- 0x03f4, 0x03f4,
- 0x03f7, 0x03f7,
- 0x03f9, 0x03fa,
- 0x03fd, 0x042f,
- 0x0460, 0x0460,
- 0x0462, 0x0462,
- 0x0464, 0x0464,
- 0x0466, 0x0466,
- 0x0468, 0x0468,
- 0x046a, 0x046a,
- 0x046c, 0x046c,
- 0x046e, 0x046e,
- 0x0470, 0x0470,
- 0x0472, 0x0472,
- 0x0474, 0x0474,
- 0x0476, 0x0476,
- 0x0478, 0x0478,
- 0x047a, 0x047a,
- 0x047c, 0x047c,
- 0x047e, 0x047e,
- 0x0480, 0x0480,
- 0x048a, 0x048a,
- 0x048c, 0x048c,
- 0x048e, 0x048e,
- 0x0490, 0x0490,
- 0x0492, 0x0492,
- 0x0494, 0x0494,
- 0x0496, 0x0496,
- 0x0498, 0x0498,
- 0x049a, 0x049a,
- 0x049c, 0x049c,
- 0x049e, 0x049e,
- 0x04a0, 0x04a0,
- 0x04a2, 0x04a2,
- 0x04a4, 0x04a4,
- 0x04a6, 0x04a6,
- 0x04a8, 0x04a8,
- 0x04aa, 0x04aa,
- 0x04ac, 0x04ac,
- 0x04ae, 0x04ae,
- 0x04b0, 0x04b0,
- 0x04b2, 0x04b2,
- 0x04b4, 0x04b4,
- 0x04b6, 0x04b6,
- 0x04b8, 0x04b8,
- 0x04ba, 0x04ba,
- 0x04bc, 0x04bc,
- 0x04be, 0x04be,
- 0x04c0, 0x04c1,
- 0x04c3, 0x04c3,
- 0x04c5, 0x04c5,
- 0x04c7, 0x04c7,
- 0x04c9, 0x04c9,
- 0x04cb, 0x04cb,
- 0x04cd, 0x04cd,
- 0x04d0, 0x04d0,
- 0x04d2, 0x04d2,
- 0x04d4, 0x04d4,
- 0x04d6, 0x04d6,
- 0x04d8, 0x04d8,
- 0x04da, 0x04da,
- 0x04dc, 0x04dc,
- 0x04de, 0x04de,
- 0x04e0, 0x04e0,
- 0x04e2, 0x04e2,
- 0x04e4, 0x04e4,
- 0x04e6, 0x04e6,
- 0x04e8, 0x04e8,
- 0x04ea, 0x04ea,
- 0x04ec, 0x04ec,
- 0x04ee, 0x04ee,
- 0x04f0, 0x04f0,
- 0x04f2, 0x04f2,
- 0x04f4, 0x04f4,
- 0x04f6, 0x04f6,
- 0x04f8, 0x04f8,
- 0x04fa, 0x04fa,
- 0x04fc, 0x04fc,
- 0x04fe, 0x04fe,
- 0x0500, 0x0500,
- 0x0502, 0x0502,
- 0x0504, 0x0504,
- 0x0506, 0x0506,
- 0x0508, 0x0508,
- 0x050a, 0x050a,
- 0x050c, 0x050c,
- 0x050e, 0x050e,
- 0x0510, 0x0510,
- 0x0512, 0x0512,
- 0x0514, 0x0514,
- 0x0516, 0x0516,
- 0x0518, 0x0518,
- 0x051a, 0x051a,
- 0x051c, 0x051c,
- 0x051e, 0x051e,
- 0x0520, 0x0520,
- 0x0522, 0x0522,
- 0x0524, 0x0524,
- 0x0526, 0x0526,
- 0x0528, 0x0528,
- 0x052a, 0x052a,
- 0x052c, 0x052c,
- 0x052e, 0x052e,
- 0x0531, 0x0556,
- 0x10a0, 0x10c5,
- 0x10c7, 0x10c7,
- 0x10cd, 0x10cd,
- 0x13a0, 0x13f5,
- 0x1c90, 0x1cba,
- 0x1cbd, 0x1cbf,
- 0x1e00, 0x1e00,
- 0x1e02, 0x1e02,
- 0x1e04, 0x1e04,
- 0x1e06, 0x1e06,
- 0x1e08, 0x1e08,
- 0x1e0a, 0x1e0a,
- 0x1e0c, 0x1e0c,
- 0x1e0e, 0x1e0e,
- 0x1e10, 0x1e10,
- 0x1e12, 0x1e12,
- 0x1e14, 0x1e14,
- 0x1e16, 0x1e16,
- 0x1e18, 0x1e18,
- 0x1e1a, 0x1e1a,
- 0x1e1c, 0x1e1c,
- 0x1e1e, 0x1e1e,
- 0x1e20, 0x1e20,
- 0x1e22, 0x1e22,
- 0x1e24, 0x1e24,
- 0x1e26, 0x1e26,
- 0x1e28, 0x1e28,
- 0x1e2a, 0x1e2a,
- 0x1e2c, 0x1e2c,
- 0x1e2e, 0x1e2e,
- 0x1e30, 0x1e30,
- 0x1e32, 0x1e32,
- 0x1e34, 0x1e34,
- 0x1e36, 0x1e36,
- 0x1e38, 0x1e38,
- 0x1e3a, 0x1e3a,
- 0x1e3c, 0x1e3c,
- 0x1e3e, 0x1e3e,
- 0x1e40, 0x1e40,
- 0x1e42, 0x1e42,
- 0x1e44, 0x1e44,
- 0x1e46, 0x1e46,
- 0x1e48, 0x1e48,
- 0x1e4a, 0x1e4a,
- 0x1e4c, 0x1e4c,
- 0x1e4e, 0x1e4e,
- 0x1e50, 0x1e50,
- 0x1e52, 0x1e52,
- 0x1e54, 0x1e54,
- 0x1e56, 0x1e56,
- 0x1e58, 0x1e58,
- 0x1e5a, 0x1e5a,
- 0x1e5c, 0x1e5c,
- 0x1e5e, 0x1e5e,
- 0x1e60, 0x1e60,
- 0x1e62, 0x1e62,
- 0x1e64, 0x1e64,
- 0x1e66, 0x1e66,
- 0x1e68, 0x1e68,
- 0x1e6a, 0x1e6a,
- 0x1e6c, 0x1e6c,
- 0x1e6e, 0x1e6e,
- 0x1e70, 0x1e70,
- 0x1e72, 0x1e72,
- 0x1e74, 0x1e74,
- 0x1e76, 0x1e76,
- 0x1e78, 0x1e78,
- 0x1e7a, 0x1e7a,
- 0x1e7c, 0x1e7c,
- 0x1e7e, 0x1e7e,
- 0x1e80, 0x1e80,
- 0x1e82, 0x1e82,
- 0x1e84, 0x1e84,
- 0x1e86, 0x1e86,
- 0x1e88, 0x1e88,
- 0x1e8a, 0x1e8a,
- 0x1e8c, 0x1e8c,
- 0x1e8e, 0x1e8e,
- 0x1e90, 0x1e90,
- 0x1e92, 0x1e92,
- 0x1e94, 0x1e94,
- 0x1e9e, 0x1e9e,
- 0x1ea0, 0x1ea0,
- 0x1ea2, 0x1ea2,
- 0x1ea4, 0x1ea4,
- 0x1ea6, 0x1ea6,
- 0x1ea8, 0x1ea8,
- 0x1eaa, 0x1eaa,
- 0x1eac, 0x1eac,
- 0x1eae, 0x1eae,
- 0x1eb0, 0x1eb0,
- 0x1eb2, 0x1eb2,
- 0x1eb4, 0x1eb4,
- 0x1eb6, 0x1eb6,
- 0x1eb8, 0x1eb8,
- 0x1eba, 0x1eba,
- 0x1ebc, 0x1ebc,
- 0x1ebe, 0x1ebe,
- 0x1ec0, 0x1ec0,
- 0x1ec2, 0x1ec2,
- 0x1ec4, 0x1ec4,
- 0x1ec6, 0x1ec6,
- 0x1ec8, 0x1ec8,
- 0x1eca, 0x1eca,
- 0x1ecc, 0x1ecc,
- 0x1ece, 0x1ece,
- 0x1ed0, 0x1ed0,
- 0x1ed2, 0x1ed2,
- 0x1ed4, 0x1ed4,
- 0x1ed6, 0x1ed6,
- 0x1ed8, 0x1ed8,
- 0x1eda, 0x1eda,
- 0x1edc, 0x1edc,
- 0x1ede, 0x1ede,
- 0x1ee0, 0x1ee0,
- 0x1ee2, 0x1ee2,
- 0x1ee4, 0x1ee4,
- 0x1ee6, 0x1ee6,
- 0x1ee8, 0x1ee8,
- 0x1eea, 0x1eea,
- 0x1eec, 0x1eec,
- 0x1eee, 0x1eee,
- 0x1ef0, 0x1ef0,
- 0x1ef2, 0x1ef2,
- 0x1ef4, 0x1ef4,
- 0x1ef6, 0x1ef6,
- 0x1ef8, 0x1ef8,
- 0x1efa, 0x1efa,
- 0x1efc, 0x1efc,
- 0x1efe, 0x1efe,
- 0x1f08, 0x1f0f,
- 0x1f18, 0x1f1d,
- 0x1f28, 0x1f2f,
- 0x1f38, 0x1f3f,
- 0x1f48, 0x1f4d,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f5f,
- 0x1f68, 0x1f6f,
- 0x1fb8, 0x1fbb,
- 0x1fc8, 0x1fcb,
- 0x1fd8, 0x1fdb,
- 0x1fe8, 0x1fec,
- 0x1ff8, 0x1ffb,
- 0x2102, 0x2102,
- 0x2107, 0x2107,
- 0x210b, 0x210d,
- 0x2110, 0x2112,
- 0x2115, 0x2115,
- 0x2119, 0x211d,
- 0x2124, 0x2124,
- 0x2126, 0x2126,
- 0x2128, 0x2128,
- 0x212a, 0x212d,
- 0x2130, 0x2133,
- 0x213e, 0x213f,
- 0x2145, 0x2145,
- 0x2183, 0x2183,
- 0x2c00, 0x2c2f,
- 0x2c60, 0x2c60,
- 0x2c62, 0x2c64,
- 0x2c67, 0x2c67,
- 0x2c69, 0x2c69,
- 0x2c6b, 0x2c6b,
- 0x2c6d, 0x2c70,
- 0x2c72, 0x2c72,
- 0x2c75, 0x2c75,
- 0x2c7e, 0x2c80,
- 0x2c82, 0x2c82,
- 0x2c84, 0x2c84,
- 0x2c86, 0x2c86,
- 0x2c88, 0x2c88,
- 0x2c8a, 0x2c8a,
- 0x2c8c, 0x2c8c,
- 0x2c8e, 0x2c8e,
- 0x2c90, 0x2c90,
- 0x2c92, 0x2c92,
- 0x2c94, 0x2c94,
- 0x2c96, 0x2c96,
- 0x2c98, 0x2c98,
- 0x2c9a, 0x2c9a,
- 0x2c9c, 0x2c9c,
- 0x2c9e, 0x2c9e,
- 0x2ca0, 0x2ca0,
- 0x2ca2, 0x2ca2,
- 0x2ca4, 0x2ca4,
- 0x2ca6, 0x2ca6,
- 0x2ca8, 0x2ca8,
- 0x2caa, 0x2caa,
- 0x2cac, 0x2cac,
- 0x2cae, 0x2cae,
- 0x2cb0, 0x2cb0,
- 0x2cb2, 0x2cb2,
- 0x2cb4, 0x2cb4,
- 0x2cb6, 0x2cb6,
- 0x2cb8, 0x2cb8,
- 0x2cba, 0x2cba,
- 0x2cbc, 0x2cbc,
- 0x2cbe, 0x2cbe,
- 0x2cc0, 0x2cc0,
- 0x2cc2, 0x2cc2,
- 0x2cc4, 0x2cc4,
- 0x2cc6, 0x2cc6,
- 0x2cc8, 0x2cc8,
- 0x2cca, 0x2cca,
- 0x2ccc, 0x2ccc,
- 0x2cce, 0x2cce,
- 0x2cd0, 0x2cd0,
- 0x2cd2, 0x2cd2,
- 0x2cd4, 0x2cd4,
- 0x2cd6, 0x2cd6,
- 0x2cd8, 0x2cd8,
- 0x2cda, 0x2cda,
- 0x2cdc, 0x2cdc,
- 0x2cde, 0x2cde,
- 0x2ce0, 0x2ce0,
- 0x2ce2, 0x2ce2,
- 0x2ceb, 0x2ceb,
- 0x2ced, 0x2ced,
- 0x2cf2, 0x2cf2,
- 0xa640, 0xa640,
- 0xa642, 0xa642,
- 0xa644, 0xa644,
- 0xa646, 0xa646,
- 0xa648, 0xa648,
- 0xa64a, 0xa64a,
- 0xa64c, 0xa64c,
- 0xa64e, 0xa64e,
- 0xa650, 0xa650,
- 0xa652, 0xa652,
- 0xa654, 0xa654,
- 0xa656, 0xa656,
- 0xa658, 0xa658,
- 0xa65a, 0xa65a,
- 0xa65c, 0xa65c,
- 0xa65e, 0xa65e,
- 0xa660, 0xa660,
- 0xa662, 0xa662,
- 0xa664, 0xa664,
- 0xa666, 0xa666,
- 0xa668, 0xa668,
- 0xa66a, 0xa66a,
- 0xa66c, 0xa66c,
- 0xa680, 0xa680,
- 0xa682, 0xa682,
- 0xa684, 0xa684,
- 0xa686, 0xa686,
- 0xa688, 0xa688,
- 0xa68a, 0xa68a,
- 0xa68c, 0xa68c,
- 0xa68e, 0xa68e,
- 0xa690, 0xa690,
- 0xa692, 0xa692,
- 0xa694, 0xa694,
- 0xa696, 0xa696,
- 0xa698, 0xa698,
- 0xa69a, 0xa69a,
- 0xa722, 0xa722,
- 0xa724, 0xa724,
- 0xa726, 0xa726,
- 0xa728, 0xa728,
- 0xa72a, 0xa72a,
- 0xa72c, 0xa72c,
- 0xa72e, 0xa72e,
- 0xa732, 0xa732,
- 0xa734, 0xa734,
- 0xa736, 0xa736,
- 0xa738, 0xa738,
- 0xa73a, 0xa73a,
- 0xa73c, 0xa73c,
- 0xa73e, 0xa73e,
- 0xa740, 0xa740,
- 0xa742, 0xa742,
- 0xa744, 0xa744,
- 0xa746, 0xa746,
- 0xa748, 0xa748,
- 0xa74a, 0xa74a,
- 0xa74c, 0xa74c,
- 0xa74e, 0xa74e,
- 0xa750, 0xa750,
- 0xa752, 0xa752,
- 0xa754, 0xa754,
- 0xa756, 0xa756,
- 0xa758, 0xa758,
- 0xa75a, 0xa75a,
- 0xa75c, 0xa75c,
- 0xa75e, 0xa75e,
- 0xa760, 0xa760,
- 0xa762, 0xa762,
- 0xa764, 0xa764,
- 0xa766, 0xa766,
- 0xa768, 0xa768,
- 0xa76a, 0xa76a,
- 0xa76c, 0xa76c,
- 0xa76e, 0xa76e,
- 0xa779, 0xa779,
- 0xa77b, 0xa77b,
- 0xa77d, 0xa77e,
- 0xa780, 0xa780,
- 0xa782, 0xa782,
- 0xa784, 0xa784,
- 0xa786, 0xa786,
- 0xa78b, 0xa78b,
- 0xa78d, 0xa78d,
- 0xa790, 0xa790,
- 0xa792, 0xa792,
- 0xa796, 0xa796,
- 0xa798, 0xa798,
- 0xa79a, 0xa79a,
- 0xa79c, 0xa79c,
- 0xa79e, 0xa79e,
- 0xa7a0, 0xa7a0,
- 0xa7a2, 0xa7a2,
- 0xa7a4, 0xa7a4,
- 0xa7a6, 0xa7a6,
- 0xa7a8, 0xa7a8,
- 0xa7aa, 0xa7ae,
- 0xa7b0, 0xa7b4,
- 0xa7b6, 0xa7b6,
- 0xa7b8, 0xa7b8,
- 0xa7ba, 0xa7ba,
- 0xa7bc, 0xa7bc,
- 0xa7be, 0xa7be,
- 0xa7c0, 0xa7c0,
- 0xa7c2, 0xa7c2,
- 0xa7c4, 0xa7c7,
- 0xa7c9, 0xa7c9,
- 0xa7d0, 0xa7d0,
- 0xa7d6, 0xa7d6,
- 0xa7d8, 0xa7d8,
- 0xa7f5, 0xa7f5,
- 0xff21, 0xff3a,
- 0x10400, 0x10427,
- 0x104b0, 0x104d3,
- 0x10570, 0x1057a,
- 0x1057c, 0x1058a,
- 0x1058c, 0x10592,
- 0x10594, 0x10595,
- 0x10c80, 0x10cb2,
- 0x118a0, 0x118bf,
- 0x16e40, 0x16e5f,
- 0x1d400, 0x1d419,
- 0x1d434, 0x1d44d,
- 0x1d468, 0x1d481,
- 0x1d49c, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 0x1d4a2, 0x1d4a2,
- 0x1d4a5, 0x1d4a6,
- 0x1d4a9, 0x1d4ac,
- 0x1d4ae, 0x1d4b5,
- 0x1d4d0, 0x1d4e9,
- 0x1d504, 0x1d505,
- 0x1d507, 0x1d50a,
- 0x1d50d, 0x1d514,
- 0x1d516, 0x1d51c,
- 0x1d538, 0x1d539,
- 0x1d53b, 0x1d53e,
- 0x1d540, 0x1d544,
- 0x1d546, 0x1d546,
- 0x1d54a, 0x1d550,
- 0x1d56c, 0x1d585,
- 0x1d5a0, 0x1d5b9,
- 0x1d5d4, 0x1d5ed,
- 0x1d608, 0x1d621,
- 0x1d63c, 0x1d655,
- 0x1d670, 0x1d689,
- 0x1d6a8, 0x1d6c0,
- 0x1d6e2, 0x1d6fa,
- 0x1d71c, 0x1d734,
- 0x1d756, 0x1d76e,
- 0x1d790, 0x1d7a8,
- 0x1d7ca, 0x1d7ca,
- 0x1e900, 0x1e921,
-}; /* CR_Lu */
-
-/* 'M': Major Category */
-static const OnigCodePoint CR_M[] = {
- 310,
- 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,
- 0x0898, 0x089f,
- 0x08ca, 0x08e1,
- 0x08e3, 0x0903,
- 0x093a, 0x093c,
- 0x093e, 0x094f,
- 0x0951, 0x0957,
- 0x0962, 0x0963,
- 0x0981, 0x0983,
- 0x09bc, 0x09bc,
- 0x09be, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09cd,
- 0x09d7, 0x09d7,
- 0x09e2, 0x09e3,
- 0x09fe, 0x09fe,
- 0x0a01, 0x0a03,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a51, 0x0a51,
- 0x0a70, 0x0a71,
- 0x0a75, 0x0a75,
- 0x0a81, 0x0a83,
- 0x0abc, 0x0abc,
- 0x0abe, 0x0ac5,
- 0x0ac7, 0x0ac9,
- 0x0acb, 0x0acd,
- 0x0ae2, 0x0ae3,
- 0x0afa, 0x0aff,
- 0x0b01, 0x0b03,
- 0x0b3c, 0x0b3c,
- 0x0b3e, 0x0b44,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4d,
- 0x0b55, 0x0b57,
- 0x0b62, 0x0b63,
- 0x0b82, 0x0b82,
- 0x0bbe, 0x0bc2,
- 0x0bc6, 0x0bc8,
- 0x0bca, 0x0bcd,
- 0x0bd7, 0x0bd7,
- 0x0c00, 0x0c04,
- 0x0c3c, 0x0c3c,
- 0x0c3e, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c62, 0x0c63,
- 0x0c81, 0x0c83,
- 0x0cbc, 0x0cbc,
- 0x0cbe, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0ce2, 0x0ce3,
- 0x0cf3, 0x0cf3,
- 0x0d00, 0x0d03,
- 0x0d3b, 0x0d3c,
- 0x0d3e, 0x0d44,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4d,
- 0x0d57, 0x0d57,
- 0x0d62, 0x0d63,
- 0x0d81, 0x0d83,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0df2, 0x0df3,
- 0x0e31, 0x0e31,
- 0x0e34, 0x0e3a,
- 0x0e47, 0x0e4e,
- 0x0eb1, 0x0eb1,
- 0x0eb4, 0x0ebc,
- 0x0ec8, 0x0ece,
- 0x0f18, 0x0f19,
- 0x0f35, 0x0f35,
- 0x0f37, 0x0f37,
- 0x0f39, 0x0f39,
- 0x0f3e, 0x0f3f,
- 0x0f71, 0x0f84,
- 0x0f86, 0x0f87,
- 0x0f8d, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x0fc6, 0x0fc6,
- 0x102b, 0x103e,
- 0x1056, 0x1059,
- 0x105e, 0x1060,
- 0x1062, 0x1064,
- 0x1067, 0x106d,
- 0x1071, 0x1074,
- 0x1082, 0x108d,
- 0x108f, 0x108f,
- 0x109a, 0x109d,
- 0x135d, 0x135f,
- 0x1712, 0x1715,
- 0x1732, 0x1734,
- 0x1752, 0x1753,
- 0x1772, 0x1773,
- 0x17b4, 0x17d3,
- 0x17dd, 0x17dd,
- 0x180b, 0x180d,
- 0x180f, 0x180f,
- 0x1885, 0x1886,
- 0x18a9, 0x18a9,
- 0x1920, 0x192b,
- 0x1930, 0x193b,
- 0x1a17, 0x1a1b,
- 0x1a55, 0x1a5e,
- 0x1a60, 0x1a7c,
- 0x1a7f, 0x1a7f,
- 0x1ab0, 0x1ace,
- 0x1b00, 0x1b04,
- 0x1b34, 0x1b44,
- 0x1b6b, 0x1b73,
- 0x1b80, 0x1b82,
- 0x1ba1, 0x1bad,
- 0x1be6, 0x1bf3,
- 0x1c24, 0x1c37,
- 0x1cd0, 0x1cd2,
- 0x1cd4, 0x1ce8,
- 0x1ced, 0x1ced,
- 0x1cf4, 0x1cf4,
- 0x1cf7, 0x1cf9,
- 0x1dc0, 0x1dff,
- 0x20d0, 0x20f0,
- 0x2cef, 0x2cf1,
- 0x2d7f, 0x2d7f,
- 0x2de0, 0x2dff,
- 0x302a, 0x302f,
- 0x3099, 0x309a,
- 0xa66f, 0xa672,
- 0xa674, 0xa67d,
- 0xa69e, 0xa69f,
- 0xa6f0, 0xa6f1,
- 0xa802, 0xa802,
- 0xa806, 0xa806,
- 0xa80b, 0xa80b,
- 0xa823, 0xa827,
- 0xa82c, 0xa82c,
- 0xa880, 0xa881,
- 0xa8b4, 0xa8c5,
- 0xa8e0, 0xa8f1,
- 0xa8ff, 0xa8ff,
- 0xa926, 0xa92d,
- 0xa947, 0xa953,
- 0xa980, 0xa983,
- 0xa9b3, 0xa9c0,
- 0xa9e5, 0xa9e5,
- 0xaa29, 0xaa36,
- 0xaa43, 0xaa43,
- 0xaa4c, 0xaa4d,
- 0xaa7b, 0xaa7d,
- 0xaab0, 0xaab0,
- 0xaab2, 0xaab4,
- 0xaab7, 0xaab8,
- 0xaabe, 0xaabf,
- 0xaac1, 0xaac1,
- 0xaaeb, 0xaaef,
- 0xaaf5, 0xaaf6,
- 0xabe3, 0xabea,
- 0xabec, 0xabed,
- 0xfb1e, 0xfb1e,
- 0xfe00, 0xfe0f,
- 0xfe20, 0xfe2f,
- 0x101fd, 0x101fd,
- 0x102e0, 0x102e0,
- 0x10376, 0x1037a,
- 0x10a01, 0x10a03,
- 0x10a05, 0x10a06,
- 0x10a0c, 0x10a0f,
- 0x10a38, 0x10a3a,
- 0x10a3f, 0x10a3f,
- 0x10ae5, 0x10ae6,
- 0x10d24, 0x10d27,
- 0x10eab, 0x10eac,
- 0x10efd, 0x10eff,
- 0x10f46, 0x10f50,
- 0x10f82, 0x10f85,
- 0x11000, 0x11002,
- 0x11038, 0x11046,
- 0x11070, 0x11070,
- 0x11073, 0x11074,
- 0x1107f, 0x11082,
- 0x110b0, 0x110ba,
- 0x110c2, 0x110c2,
- 0x11100, 0x11102,
- 0x11127, 0x11134,
- 0x11145, 0x11146,
- 0x11173, 0x11173,
- 0x11180, 0x11182,
- 0x111b3, 0x111c0,
- 0x111c9, 0x111cc,
- 0x111ce, 0x111cf,
- 0x1122c, 0x11237,
- 0x1123e, 0x1123e,
- 0x11241, 0x11241,
- 0x112df, 0x112ea,
- 0x11300, 0x11303,
- 0x1133b, 0x1133c,
- 0x1133e, 0x11344,
- 0x11347, 0x11348,
- 0x1134b, 0x1134d,
- 0x11357, 0x11357,
- 0x11362, 0x11363,
- 0x11366, 0x1136c,
- 0x11370, 0x11374,
- 0x11435, 0x11446,
- 0x1145e, 0x1145e,
- 0x114b0, 0x114c3,
- 0x115af, 0x115b5,
- 0x115b8, 0x115c0,
- 0x115dc, 0x115dd,
- 0x11630, 0x11640,
- 0x116ab, 0x116b7,
- 0x1171d, 0x1172b,
- 0x1182c, 0x1183a,
- 0x11930, 0x11935,
- 0x11937, 0x11938,
- 0x1193b, 0x1193e,
- 0x11940, 0x11940,
- 0x11942, 0x11943,
- 0x119d1, 0x119d7,
- 0x119da, 0x119e0,
- 0x119e4, 0x119e4,
- 0x11a01, 0x11a0a,
- 0x11a33, 0x11a39,
- 0x11a3b, 0x11a3e,
- 0x11a47, 0x11a47,
- 0x11a51, 0x11a5b,
- 0x11a8a, 0x11a99,
- 0x11c2f, 0x11c36,
- 0x11c38, 0x11c3f,
- 0x11c92, 0x11ca7,
- 0x11ca9, 0x11cb6,
- 0x11d31, 0x11d36,
- 0x11d3a, 0x11d3a,
- 0x11d3c, 0x11d3d,
- 0x11d3f, 0x11d45,
- 0x11d47, 0x11d47,
- 0x11d8a, 0x11d8e,
- 0x11d90, 0x11d91,
- 0x11d93, 0x11d97,
- 0x11ef3, 0x11ef6,
- 0x11f00, 0x11f01,
- 0x11f03, 0x11f03,
- 0x11f34, 0x11f3a,
- 0x11f3e, 0x11f42,
- 0x13440, 0x13440,
- 0x13447, 0x13455,
- 0x16af0, 0x16af4,
- 0x16b30, 0x16b36,
- 0x16f4f, 0x16f4f,
- 0x16f51, 0x16f87,
- 0x16f8f, 0x16f92,
- 0x16fe4, 0x16fe4,
- 0x16ff0, 0x16ff1,
- 0x1bc9d, 0x1bc9e,
- 0x1cf00, 0x1cf2d,
- 0x1cf30, 0x1cf46,
- 0x1d165, 0x1d169,
- 0x1d16d, 0x1d172,
- 0x1d17b, 0x1d182,
- 0x1d185, 0x1d18b,
- 0x1d1aa, 0x1d1ad,
- 0x1d242, 0x1d244,
- 0x1da00, 0x1da36,
- 0x1da3b, 0x1da6c,
- 0x1da75, 0x1da75,
- 0x1da84, 0x1da84,
- 0x1da9b, 0x1da9f,
- 0x1daa1, 0x1daaf,
- 0x1e000, 0x1e006,
- 0x1e008, 0x1e018,
- 0x1e01b, 0x1e021,
- 0x1e023, 0x1e024,
- 0x1e026, 0x1e02a,
- 0x1e08f, 0x1e08f,
- 0x1e130, 0x1e136,
- 0x1e2ae, 0x1e2ae,
- 0x1e2ec, 0x1e2ef,
- 0x1e4ec, 0x1e4ef,
- 0x1e8d0, 0x1e8d6,
- 0x1e944, 0x1e94a,
- 0xe0100, 0xe01ef,
-}; /* CR_M */
-
-/* 'Mc': General Category */
-static const OnigCodePoint CR_Mc[] = {
- 182,
- 0x0903, 0x0903,
- 0x093b, 0x093b,
- 0x093e, 0x0940,
- 0x0949, 0x094c,
- 0x094e, 0x094f,
- 0x0982, 0x0983,
- 0x09be, 0x09c0,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09cc,
- 0x09d7, 0x09d7,
- 0x0a03, 0x0a03,
- 0x0a3e, 0x0a40,
- 0x0a83, 0x0a83,
- 0x0abe, 0x0ac0,
- 0x0ac9, 0x0ac9,
- 0x0acb, 0x0acc,
- 0x0b02, 0x0b03,
- 0x0b3e, 0x0b3e,
- 0x0b40, 0x0b40,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4c,
- 0x0b57, 0x0b57,
- 0x0bbe, 0x0bbf,
- 0x0bc1, 0x0bc2,
- 0x0bc6, 0x0bc8,
- 0x0bca, 0x0bcc,
- 0x0bd7, 0x0bd7,
- 0x0c01, 0x0c03,
- 0x0c41, 0x0c44,
- 0x0c82, 0x0c83,
- 0x0cbe, 0x0cbe,
- 0x0cc0, 0x0cc4,
- 0x0cc7, 0x0cc8,
- 0x0cca, 0x0ccb,
- 0x0cd5, 0x0cd6,
- 0x0cf3, 0x0cf3,
- 0x0d02, 0x0d03,
- 0x0d3e, 0x0d40,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4c,
- 0x0d57, 0x0d57,
- 0x0d82, 0x0d83,
- 0x0dcf, 0x0dd1,
- 0x0dd8, 0x0ddf,
- 0x0df2, 0x0df3,
- 0x0f3e, 0x0f3f,
- 0x0f7f, 0x0f7f,
- 0x102b, 0x102c,
- 0x1031, 0x1031,
- 0x1038, 0x1038,
- 0x103b, 0x103c,
- 0x1056, 0x1057,
- 0x1062, 0x1064,
- 0x1067, 0x106d,
- 0x1083, 0x1084,
- 0x1087, 0x108c,
- 0x108f, 0x108f,
- 0x109a, 0x109c,
- 0x1715, 0x1715,
- 0x1734, 0x1734,
- 0x17b6, 0x17b6,
- 0x17be, 0x17c5,
- 0x17c7, 0x17c8,
- 0x1923, 0x1926,
- 0x1929, 0x192b,
- 0x1930, 0x1931,
- 0x1933, 0x1938,
- 0x1a19, 0x1a1a,
- 0x1a55, 0x1a55,
- 0x1a57, 0x1a57,
- 0x1a61, 0x1a61,
- 0x1a63, 0x1a64,
- 0x1a6d, 0x1a72,
- 0x1b04, 0x1b04,
- 0x1b35, 0x1b35,
- 0x1b3b, 0x1b3b,
- 0x1b3d, 0x1b41,
- 0x1b43, 0x1b44,
- 0x1b82, 0x1b82,
- 0x1ba1, 0x1ba1,
- 0x1ba6, 0x1ba7,
- 0x1baa, 0x1baa,
- 0x1be7, 0x1be7,
- 0x1bea, 0x1bec,
- 0x1bee, 0x1bee,
- 0x1bf2, 0x1bf3,
- 0x1c24, 0x1c2b,
- 0x1c34, 0x1c35,
- 0x1ce1, 0x1ce1,
- 0x1cf7, 0x1cf7,
- 0x302e, 0x302f,
- 0xa823, 0xa824,
- 0xa827, 0xa827,
- 0xa880, 0xa881,
- 0xa8b4, 0xa8c3,
- 0xa952, 0xa953,
- 0xa983, 0xa983,
- 0xa9b4, 0xa9b5,
- 0xa9ba, 0xa9bb,
- 0xa9be, 0xa9c0,
- 0xaa2f, 0xaa30,
- 0xaa33, 0xaa34,
- 0xaa4d, 0xaa4d,
- 0xaa7b, 0xaa7b,
- 0xaa7d, 0xaa7d,
- 0xaaeb, 0xaaeb,
- 0xaaee, 0xaaef,
- 0xaaf5, 0xaaf5,
- 0xabe3, 0xabe4,
- 0xabe6, 0xabe7,
- 0xabe9, 0xabea,
- 0xabec, 0xabec,
- 0x11000, 0x11000,
- 0x11002, 0x11002,
- 0x11082, 0x11082,
- 0x110b0, 0x110b2,
- 0x110b7, 0x110b8,
- 0x1112c, 0x1112c,
- 0x11145, 0x11146,
- 0x11182, 0x11182,
- 0x111b3, 0x111b5,
- 0x111bf, 0x111c0,
- 0x111ce, 0x111ce,
- 0x1122c, 0x1122e,
- 0x11232, 0x11233,
- 0x11235, 0x11235,
- 0x112e0, 0x112e2,
- 0x11302, 0x11303,
- 0x1133e, 0x1133f,
- 0x11341, 0x11344,
- 0x11347, 0x11348,
- 0x1134b, 0x1134d,
- 0x11357, 0x11357,
- 0x11362, 0x11363,
- 0x11435, 0x11437,
- 0x11440, 0x11441,
- 0x11445, 0x11445,
- 0x114b0, 0x114b2,
- 0x114b9, 0x114b9,
- 0x114bb, 0x114be,
- 0x114c1, 0x114c1,
- 0x115af, 0x115b1,
- 0x115b8, 0x115bb,
- 0x115be, 0x115be,
- 0x11630, 0x11632,
- 0x1163b, 0x1163c,
- 0x1163e, 0x1163e,
- 0x116ac, 0x116ac,
- 0x116ae, 0x116af,
- 0x116b6, 0x116b6,
- 0x11720, 0x11721,
- 0x11726, 0x11726,
- 0x1182c, 0x1182e,
- 0x11838, 0x11838,
- 0x11930, 0x11935,
- 0x11937, 0x11938,
- 0x1193d, 0x1193d,
- 0x11940, 0x11940,
- 0x11942, 0x11942,
- 0x119d1, 0x119d3,
- 0x119dc, 0x119df,
- 0x119e4, 0x119e4,
- 0x11a39, 0x11a39,
- 0x11a57, 0x11a58,
- 0x11a97, 0x11a97,
- 0x11c2f, 0x11c2f,
- 0x11c3e, 0x11c3e,
- 0x11ca9, 0x11ca9,
- 0x11cb1, 0x11cb1,
- 0x11cb4, 0x11cb4,
- 0x11d8a, 0x11d8e,
- 0x11d93, 0x11d94,
- 0x11d96, 0x11d96,
- 0x11ef5, 0x11ef6,
- 0x11f03, 0x11f03,
- 0x11f34, 0x11f35,
- 0x11f3e, 0x11f3f,
- 0x11f41, 0x11f41,
- 0x16f51, 0x16f87,
- 0x16ff0, 0x16ff1,
- 0x1d165, 0x1d166,
- 0x1d16d, 0x1d172,
-}; /* CR_Mc */
-
-/* 'Me': General Category */
-static const OnigCodePoint CR_Me[] = {
- 5,
- 0x0488, 0x0489,
- 0x1abe, 0x1abe,
- 0x20dd, 0x20e0,
- 0x20e2, 0x20e4,
- 0xa670, 0xa672,
-}; /* CR_Me */
-
-/* 'Mn': General Category */
-static const OnigCodePoint CR_Mn[] = {
- 346,
- 0x0300, 0x036f,
- 0x0483, 0x0487,
- 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,
- 0x0898, 0x089f,
- 0x08ca, 0x08e1,
- 0x08e3, 0x0902,
- 0x093a, 0x093a,
- 0x093c, 0x093c,
- 0x0941, 0x0948,
- 0x094d, 0x094d,
- 0x0951, 0x0957,
- 0x0962, 0x0963,
- 0x0981, 0x0981,
- 0x09bc, 0x09bc,
- 0x09c1, 0x09c4,
- 0x09cd, 0x09cd,
- 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,
- 0x0b3f, 0x0b3f,
- 0x0b41, 0x0b44,
- 0x0b4d, 0x0b4d,
- 0x0b55, 0x0b56,
- 0x0b62, 0x0b63,
- 0x0b82, 0x0b82,
- 0x0bc0, 0x0bc0,
- 0x0bcd, 0x0bcd,
- 0x0c00, 0x0c00,
- 0x0c04, 0x0c04,
- 0x0c3c, 0x0c3c,
- 0x0c3e, 0x0c40,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c62, 0x0c63,
- 0x0c81, 0x0c81,
- 0x0cbc, 0x0cbc,
- 0x0cbf, 0x0cbf,
- 0x0cc6, 0x0cc6,
- 0x0ccc, 0x0ccd,
- 0x0ce2, 0x0ce3,
- 0x0d00, 0x0d01,
- 0x0d3b, 0x0d3c,
- 0x0d41, 0x0d44,
- 0x0d4d, 0x0d4d,
- 0x0d62, 0x0d63,
- 0x0d81, 0x0d81,
- 0x0dca, 0x0dca,
- 0x0dd2, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0e31, 0x0e31,
- 0x0e34, 0x0e3a,
- 0x0e47, 0x0e4e,
- 0x0eb1, 0x0eb1,
- 0x0eb4, 0x0ebc,
- 0x0ec8, 0x0ece,
- 0x0f18, 0x0f19,
- 0x0f35, 0x0f35,
- 0x0f37, 0x0f37,
- 0x0f39, 0x0f39,
- 0x0f71, 0x0f7e,
- 0x0f80, 0x0f84,
- 0x0f86, 0x0f87,
- 0x0f8d, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x0fc6, 0x0fc6,
- 0x102d, 0x1030,
- 0x1032, 0x1037,
- 0x1039, 0x103a,
- 0x103d, 0x103e,
- 0x1058, 0x1059,
- 0x105e, 0x1060,
- 0x1071, 0x1074,
- 0x1082, 0x1082,
- 0x1085, 0x1086,
- 0x108d, 0x108d,
- 0x109d, 0x109d,
- 0x135d, 0x135f,
- 0x1712, 0x1714,
- 0x1732, 0x1733,
- 0x1752, 0x1753,
- 0x1772, 0x1773,
- 0x17b4, 0x17b5,
- 0x17b7, 0x17bd,
- 0x17c6, 0x17c6,
- 0x17c9, 0x17d3,
- 0x17dd, 0x17dd,
- 0x180b, 0x180d,
- 0x180f, 0x180f,
- 0x1885, 0x1886,
- 0x18a9, 0x18a9,
- 0x1920, 0x1922,
- 0x1927, 0x1928,
- 0x1932, 0x1932,
- 0x1939, 0x193b,
- 0x1a17, 0x1a18,
- 0x1a1b, 0x1a1b,
- 0x1a56, 0x1a56,
- 0x1a58, 0x1a5e,
- 0x1a60, 0x1a60,
- 0x1a62, 0x1a62,
- 0x1a65, 0x1a6c,
- 0x1a73, 0x1a7c,
- 0x1a7f, 0x1a7f,
- 0x1ab0, 0x1abd,
- 0x1abf, 0x1ace,
- 0x1b00, 0x1b03,
- 0x1b34, 0x1b34,
- 0x1b36, 0x1b3a,
- 0x1b3c, 0x1b3c,
- 0x1b42, 0x1b42,
- 0x1b6b, 0x1b73,
- 0x1b80, 0x1b81,
- 0x1ba2, 0x1ba5,
- 0x1ba8, 0x1ba9,
- 0x1bab, 0x1bad,
- 0x1be6, 0x1be6,
- 0x1be8, 0x1be9,
- 0x1bed, 0x1bed,
- 0x1bef, 0x1bf1,
- 0x1c2c, 0x1c33,
- 0x1c36, 0x1c37,
- 0x1cd0, 0x1cd2,
- 0x1cd4, 0x1ce0,
- 0x1ce2, 0x1ce8,
- 0x1ced, 0x1ced,
- 0x1cf4, 0x1cf4,
- 0x1cf8, 0x1cf9,
- 0x1dc0, 0x1dff,
- 0x20d0, 0x20dc,
- 0x20e1, 0x20e1,
- 0x20e5, 0x20f0,
- 0x2cef, 0x2cf1,
- 0x2d7f, 0x2d7f,
- 0x2de0, 0x2dff,
- 0x302a, 0x302d,
- 0x3099, 0x309a,
- 0xa66f, 0xa66f,
- 0xa674, 0xa67d,
- 0xa69e, 0xa69f,
- 0xa6f0, 0xa6f1,
- 0xa802, 0xa802,
- 0xa806, 0xa806,
- 0xa80b, 0xa80b,
- 0xa825, 0xa826,
- 0xa82c, 0xa82c,
- 0xa8c4, 0xa8c5,
- 0xa8e0, 0xa8f1,
- 0xa8ff, 0xa8ff,
- 0xa926, 0xa92d,
- 0xa947, 0xa951,
- 0xa980, 0xa982,
- 0xa9b3, 0xa9b3,
- 0xa9b6, 0xa9b9,
- 0xa9bc, 0xa9bd,
- 0xa9e5, 0xa9e5,
- 0xaa29, 0xaa2e,
- 0xaa31, 0xaa32,
- 0xaa35, 0xaa36,
- 0xaa43, 0xaa43,
- 0xaa4c, 0xaa4c,
- 0xaa7c, 0xaa7c,
- 0xaab0, 0xaab0,
- 0xaab2, 0xaab4,
- 0xaab7, 0xaab8,
- 0xaabe, 0xaabf,
- 0xaac1, 0xaac1,
- 0xaaec, 0xaaed,
- 0xaaf6, 0xaaf6,
- 0xabe5, 0xabe5,
- 0xabe8, 0xabe8,
- 0xabed, 0xabed,
- 0xfb1e, 0xfb1e,
- 0xfe00, 0xfe0f,
- 0xfe20, 0xfe2f,
- 0x101fd, 0x101fd,
- 0x102e0, 0x102e0,
- 0x10376, 0x1037a,
- 0x10a01, 0x10a03,
- 0x10a05, 0x10a06,
- 0x10a0c, 0x10a0f,
- 0x10a38, 0x10a3a,
- 0x10a3f, 0x10a3f,
- 0x10ae5, 0x10ae6,
- 0x10d24, 0x10d27,
- 0x10eab, 0x10eac,
- 0x10efd, 0x10eff,
- 0x10f46, 0x10f50,
- 0x10f82, 0x10f85,
- 0x11001, 0x11001,
- 0x11038, 0x11046,
- 0x11070, 0x11070,
- 0x11073, 0x11074,
- 0x1107f, 0x11081,
- 0x110b3, 0x110b6,
- 0x110b9, 0x110ba,
- 0x110c2, 0x110c2,
- 0x11100, 0x11102,
- 0x11127, 0x1112b,
- 0x1112d, 0x11134,
- 0x11173, 0x11173,
- 0x11180, 0x11181,
- 0x111b6, 0x111be,
- 0x111c9, 0x111cc,
- 0x111cf, 0x111cf,
- 0x1122f, 0x11231,
- 0x11234, 0x11234,
- 0x11236, 0x11237,
- 0x1123e, 0x1123e,
- 0x11241, 0x11241,
- 0x112df, 0x112df,
- 0x112e3, 0x112ea,
- 0x11300, 0x11301,
- 0x1133b, 0x1133c,
- 0x11340, 0x11340,
- 0x11366, 0x1136c,
- 0x11370, 0x11374,
- 0x11438, 0x1143f,
- 0x11442, 0x11444,
- 0x11446, 0x11446,
- 0x1145e, 0x1145e,
- 0x114b3, 0x114b8,
- 0x114ba, 0x114ba,
- 0x114bf, 0x114c0,
- 0x114c2, 0x114c3,
- 0x115b2, 0x115b5,
- 0x115bc, 0x115bd,
- 0x115bf, 0x115c0,
- 0x115dc, 0x115dd,
- 0x11633, 0x1163a,
- 0x1163d, 0x1163d,
- 0x1163f, 0x11640,
- 0x116ab, 0x116ab,
- 0x116ad, 0x116ad,
- 0x116b0, 0x116b5,
- 0x116b7, 0x116b7,
- 0x1171d, 0x1171f,
- 0x11722, 0x11725,
- 0x11727, 0x1172b,
- 0x1182f, 0x11837,
- 0x11839, 0x1183a,
- 0x1193b, 0x1193c,
- 0x1193e, 0x1193e,
- 0x11943, 0x11943,
- 0x119d4, 0x119d7,
- 0x119da, 0x119db,
- 0x119e0, 0x119e0,
- 0x11a01, 0x11a0a,
- 0x11a33, 0x11a38,
- 0x11a3b, 0x11a3e,
- 0x11a47, 0x11a47,
- 0x11a51, 0x11a56,
- 0x11a59, 0x11a5b,
- 0x11a8a, 0x11a96,
- 0x11a98, 0x11a99,
- 0x11c30, 0x11c36,
- 0x11c38, 0x11c3d,
- 0x11c3f, 0x11c3f,
- 0x11c92, 0x11ca7,
- 0x11caa, 0x11cb0,
- 0x11cb2, 0x11cb3,
- 0x11cb5, 0x11cb6,
- 0x11d31, 0x11d36,
- 0x11d3a, 0x11d3a,
- 0x11d3c, 0x11d3d,
- 0x11d3f, 0x11d45,
- 0x11d47, 0x11d47,
- 0x11d90, 0x11d91,
- 0x11d95, 0x11d95,
- 0x11d97, 0x11d97,
- 0x11ef3, 0x11ef4,
- 0x11f00, 0x11f01,
- 0x11f36, 0x11f3a,
- 0x11f40, 0x11f40,
- 0x11f42, 0x11f42,
- 0x13440, 0x13440,
- 0x13447, 0x13455,
- 0x16af0, 0x16af4,
- 0x16b30, 0x16b36,
- 0x16f4f, 0x16f4f,
- 0x16f8f, 0x16f92,
- 0x16fe4, 0x16fe4,
- 0x1bc9d, 0x1bc9e,
- 0x1cf00, 0x1cf2d,
- 0x1cf30, 0x1cf46,
- 0x1d167, 0x1d169,
- 0x1d17b, 0x1d182,
- 0x1d185, 0x1d18b,
- 0x1d1aa, 0x1d1ad,
- 0x1d242, 0x1d244,
- 0x1da00, 0x1da36,
- 0x1da3b, 0x1da6c,
- 0x1da75, 0x1da75,
- 0x1da84, 0x1da84,
- 0x1da9b, 0x1da9f,
- 0x1daa1, 0x1daaf,
- 0x1e000, 0x1e006,
- 0x1e008, 0x1e018,
- 0x1e01b, 0x1e021,
- 0x1e023, 0x1e024,
- 0x1e026, 0x1e02a,
- 0x1e08f, 0x1e08f,
- 0x1e130, 0x1e136,
- 0x1e2ae, 0x1e2ae,
- 0x1e2ec, 0x1e2ef,
- 0x1e4ec, 0x1e4ef,
- 0x1e8d0, 0x1e8d6,
- 0x1e944, 0x1e94a,
- 0xe0100, 0xe01ef,
-}; /* CR_Mn */
-
-/* 'N': Major Category */
-static const OnigCodePoint CR_N[] = {
- 137,
- 0x0030, 0x0039,
- 0x00b2, 0x00b3,
- 0x00b9, 0x00b9,
- 0x00bc, 0x00be,
- 0x0660, 0x0669,
- 0x06f0, 0x06f9,
- 0x07c0, 0x07c9,
- 0x0966, 0x096f,
- 0x09e6, 0x09ef,
- 0x09f4, 0x09f9,
- 0x0a66, 0x0a6f,
- 0x0ae6, 0x0aef,
- 0x0b66, 0x0b6f,
- 0x0b72, 0x0b77,
- 0x0be6, 0x0bf2,
- 0x0c66, 0x0c6f,
- 0x0c78, 0x0c7e,
- 0x0ce6, 0x0cef,
- 0x0d58, 0x0d5e,
- 0x0d66, 0x0d78,
- 0x0de6, 0x0def,
- 0x0e50, 0x0e59,
- 0x0ed0, 0x0ed9,
- 0x0f20, 0x0f33,
- 0x1040, 0x1049,
- 0x1090, 0x1099,
- 0x1369, 0x137c,
- 0x16ee, 0x16f0,
- 0x17e0, 0x17e9,
- 0x17f0, 0x17f9,
- 0x1810, 0x1819,
- 0x1946, 0x194f,
- 0x19d0, 0x19da,
- 0x1a80, 0x1a89,
- 0x1a90, 0x1a99,
- 0x1b50, 0x1b59,
- 0x1bb0, 0x1bb9,
- 0x1c40, 0x1c49,
- 0x1c50, 0x1c59,
- 0x2070, 0x2070,
- 0x2074, 0x2079,
- 0x2080, 0x2089,
- 0x2150, 0x2182,
- 0x2185, 0x2189,
- 0x2460, 0x249b,
- 0x24ea, 0x24ff,
- 0x2776, 0x2793,
- 0x2cfd, 0x2cfd,
- 0x3007, 0x3007,
- 0x3021, 0x3029,
- 0x3038, 0x303a,
- 0x3192, 0x3195,
- 0x3220, 0x3229,
- 0x3248, 0x324f,
- 0x3251, 0x325f,
- 0x3280, 0x3289,
- 0x32b1, 0x32bf,
- 0xa620, 0xa629,
- 0xa6e6, 0xa6ef,
- 0xa830, 0xa835,
- 0xa8d0, 0xa8d9,
- 0xa900, 0xa909,
- 0xa9d0, 0xa9d9,
- 0xa9f0, 0xa9f9,
- 0xaa50, 0xaa59,
- 0xabf0, 0xabf9,
- 0xff10, 0xff19,
- 0x10107, 0x10133,
- 0x10140, 0x10178,
- 0x1018a, 0x1018b,
- 0x102e1, 0x102fb,
- 0x10320, 0x10323,
- 0x10341, 0x10341,
- 0x1034a, 0x1034a,
- 0x103d1, 0x103d5,
- 0x104a0, 0x104a9,
- 0x10858, 0x1085f,
- 0x10879, 0x1087f,
- 0x108a7, 0x108af,
- 0x108fb, 0x108ff,
- 0x10916, 0x1091b,
- 0x109bc, 0x109bd,
- 0x109c0, 0x109cf,
- 0x109d2, 0x109ff,
- 0x10a40, 0x10a48,
- 0x10a7d, 0x10a7e,
- 0x10a9d, 0x10a9f,
- 0x10aeb, 0x10aef,
- 0x10b58, 0x10b5f,
- 0x10b78, 0x10b7f,
- 0x10ba9, 0x10baf,
- 0x10cfa, 0x10cff,
- 0x10d30, 0x10d39,
- 0x10e60, 0x10e7e,
- 0x10f1d, 0x10f26,
- 0x10f51, 0x10f54,
- 0x10fc5, 0x10fcb,
- 0x11052, 0x1106f,
- 0x110f0, 0x110f9,
- 0x11136, 0x1113f,
- 0x111d0, 0x111d9,
- 0x111e1, 0x111f4,
- 0x112f0, 0x112f9,
- 0x11450, 0x11459,
- 0x114d0, 0x114d9,
- 0x11650, 0x11659,
- 0x116c0, 0x116c9,
- 0x11730, 0x1173b,
- 0x118e0, 0x118f2,
- 0x11950, 0x11959,
- 0x11c50, 0x11c6c,
- 0x11d50, 0x11d59,
- 0x11da0, 0x11da9,
- 0x11f50, 0x11f59,
- 0x11fc0, 0x11fd4,
- 0x12400, 0x1246e,
- 0x16a60, 0x16a69,
- 0x16ac0, 0x16ac9,
- 0x16b50, 0x16b59,
- 0x16b5b, 0x16b61,
- 0x16e80, 0x16e96,
- 0x1d2c0, 0x1d2d3,
- 0x1d2e0, 0x1d2f3,
- 0x1d360, 0x1d378,
- 0x1d7ce, 0x1d7ff,
- 0x1e140, 0x1e149,
- 0x1e2f0, 0x1e2f9,
- 0x1e4f0, 0x1e4f9,
- 0x1e8c7, 0x1e8cf,
- 0x1e950, 0x1e959,
- 0x1ec71, 0x1ecab,
- 0x1ecad, 0x1ecaf,
- 0x1ecb1, 0x1ecb4,
- 0x1ed01, 0x1ed2d,
- 0x1ed2f, 0x1ed3d,
- 0x1f100, 0x1f10c,
- 0x1fbf0, 0x1fbf9,
-}; /* CR_N */
-
-/* 'Nd': General Category */
-#define CR_Nd CR_Digit
-
-/* 'Nl': General Category */
-static const OnigCodePoint CR_Nl[] = {
- 12,
- 0x16ee, 0x16f0,
- 0x2160, 0x2182,
- 0x2185, 0x2188,
- 0x3007, 0x3007,
- 0x3021, 0x3029,
- 0x3038, 0x303a,
- 0xa6e6, 0xa6ef,
- 0x10140, 0x10174,
- 0x10341, 0x10341,
- 0x1034a, 0x1034a,
- 0x103d1, 0x103d5,
- 0x12400, 0x1246e,
-}; /* CR_Nl */
-
-/* 'No': General Category */
-static const OnigCodePoint CR_No[] = {
- 72,
- 0x00b2, 0x00b3,
- 0x00b9, 0x00b9,
- 0x00bc, 0x00be,
- 0x09f4, 0x09f9,
- 0x0b72, 0x0b77,
- 0x0bf0, 0x0bf2,
- 0x0c78, 0x0c7e,
- 0x0d58, 0x0d5e,
- 0x0d70, 0x0d78,
- 0x0f2a, 0x0f33,
- 0x1369, 0x137c,
- 0x17f0, 0x17f9,
- 0x19da, 0x19da,
- 0x2070, 0x2070,
- 0x2074, 0x2079,
- 0x2080, 0x2089,
- 0x2150, 0x215f,
- 0x2189, 0x2189,
- 0x2460, 0x249b,
- 0x24ea, 0x24ff,
- 0x2776, 0x2793,
- 0x2cfd, 0x2cfd,
- 0x3192, 0x3195,
- 0x3220, 0x3229,
- 0x3248, 0x324f,
- 0x3251, 0x325f,
- 0x3280, 0x3289,
- 0x32b1, 0x32bf,
- 0xa830, 0xa835,
- 0x10107, 0x10133,
- 0x10175, 0x10178,
- 0x1018a, 0x1018b,
- 0x102e1, 0x102fb,
- 0x10320, 0x10323,
- 0x10858, 0x1085f,
- 0x10879, 0x1087f,
- 0x108a7, 0x108af,
- 0x108fb, 0x108ff,
- 0x10916, 0x1091b,
- 0x109bc, 0x109bd,
- 0x109c0, 0x109cf,
- 0x109d2, 0x109ff,
- 0x10a40, 0x10a48,
- 0x10a7d, 0x10a7e,
- 0x10a9d, 0x10a9f,
- 0x10aeb, 0x10aef,
- 0x10b58, 0x10b5f,
- 0x10b78, 0x10b7f,
- 0x10ba9, 0x10baf,
- 0x10cfa, 0x10cff,
- 0x10e60, 0x10e7e,
- 0x10f1d, 0x10f26,
- 0x10f51, 0x10f54,
- 0x10fc5, 0x10fcb,
- 0x11052, 0x11065,
- 0x111e1, 0x111f4,
- 0x1173a, 0x1173b,
- 0x118ea, 0x118f2,
- 0x11c5a, 0x11c6c,
- 0x11fc0, 0x11fd4,
- 0x16b5b, 0x16b61,
- 0x16e80, 0x16e96,
- 0x1d2c0, 0x1d2d3,
- 0x1d2e0, 0x1d2f3,
- 0x1d360, 0x1d378,
- 0x1e8c7, 0x1e8cf,
- 0x1ec71, 0x1ecab,
- 0x1ecad, 0x1ecaf,
- 0x1ecb1, 0x1ecb4,
- 0x1ed01, 0x1ed2d,
- 0x1ed2f, 0x1ed3d,
- 0x1f100, 0x1f10c,
-}; /* CR_No */
-
-/* 'P': Major Category */
-#define CR_P CR_Punct
-
-/* 'Pc': General Category */
-static const OnigCodePoint CR_Pc[] = {
- 6,
- 0x005f, 0x005f,
- 0x203f, 0x2040,
- 0x2054, 0x2054,
- 0xfe33, 0xfe34,
- 0xfe4d, 0xfe4f,
- 0xff3f, 0xff3f,
-}; /* CR_Pc */
-
-/* 'Pd': General Category */
-static const OnigCodePoint CR_Pd[] = {
- 19,
- 0x002d, 0x002d,
- 0x058a, 0x058a,
- 0x05be, 0x05be,
- 0x1400, 0x1400,
- 0x1806, 0x1806,
- 0x2010, 0x2015,
- 0x2e17, 0x2e17,
- 0x2e1a, 0x2e1a,
- 0x2e3a, 0x2e3b,
- 0x2e40, 0x2e40,
- 0x2e5d, 0x2e5d,
- 0x301c, 0x301c,
- 0x3030, 0x3030,
- 0x30a0, 0x30a0,
- 0xfe31, 0xfe32,
- 0xfe58, 0xfe58,
- 0xfe63, 0xfe63,
- 0xff0d, 0xff0d,
- 0x10ead, 0x10ead,
-}; /* CR_Pd */
-
-/* 'Pe': General Category */
-static const OnigCodePoint CR_Pe[] = {
- 76,
- 0x0029, 0x0029,
- 0x005d, 0x005d,
- 0x007d, 0x007d,
- 0x0f3b, 0x0f3b,
- 0x0f3d, 0x0f3d,
- 0x169c, 0x169c,
- 0x2046, 0x2046,
- 0x207e, 0x207e,
- 0x208e, 0x208e,
- 0x2309, 0x2309,
- 0x230b, 0x230b,
- 0x232a, 0x232a,
- 0x2769, 0x2769,
- 0x276b, 0x276b,
- 0x276d, 0x276d,
- 0x276f, 0x276f,
- 0x2771, 0x2771,
- 0x2773, 0x2773,
- 0x2775, 0x2775,
- 0x27c6, 0x27c6,
- 0x27e7, 0x27e7,
- 0x27e9, 0x27e9,
- 0x27eb, 0x27eb,
- 0x27ed, 0x27ed,
- 0x27ef, 0x27ef,
- 0x2984, 0x2984,
- 0x2986, 0x2986,
- 0x2988, 0x2988,
- 0x298a, 0x298a,
- 0x298c, 0x298c,
- 0x298e, 0x298e,
- 0x2990, 0x2990,
- 0x2992, 0x2992,
- 0x2994, 0x2994,
- 0x2996, 0x2996,
- 0x2998, 0x2998,
- 0x29d9, 0x29d9,
- 0x29db, 0x29db,
- 0x29fd, 0x29fd,
- 0x2e23, 0x2e23,
- 0x2e25, 0x2e25,
- 0x2e27, 0x2e27,
- 0x2e29, 0x2e29,
- 0x2e56, 0x2e56,
- 0x2e58, 0x2e58,
- 0x2e5a, 0x2e5a,
- 0x2e5c, 0x2e5c,
- 0x3009, 0x3009,
- 0x300b, 0x300b,
- 0x300d, 0x300d,
- 0x300f, 0x300f,
- 0x3011, 0x3011,
- 0x3015, 0x3015,
- 0x3017, 0x3017,
- 0x3019, 0x3019,
- 0x301b, 0x301b,
- 0x301e, 0x301f,
- 0xfd3e, 0xfd3e,
- 0xfe18, 0xfe18,
- 0xfe36, 0xfe36,
- 0xfe38, 0xfe38,
- 0xfe3a, 0xfe3a,
- 0xfe3c, 0xfe3c,
- 0xfe3e, 0xfe3e,
- 0xfe40, 0xfe40,
- 0xfe42, 0xfe42,
- 0xfe44, 0xfe44,
- 0xfe48, 0xfe48,
- 0xfe5a, 0xfe5a,
- 0xfe5c, 0xfe5c,
- 0xfe5e, 0xfe5e,
- 0xff09, 0xff09,
- 0xff3d, 0xff3d,
- 0xff5d, 0xff5d,
- 0xff60, 0xff60,
- 0xff63, 0xff63,
-}; /* CR_Pe */
-
-/* 'Pf': General Category */
-static const OnigCodePoint CR_Pf[] = {
- 10,
- 0x00bb, 0x00bb,
- 0x2019, 0x2019,
- 0x201d, 0x201d,
- 0x203a, 0x203a,
- 0x2e03, 0x2e03,
- 0x2e05, 0x2e05,
- 0x2e0a, 0x2e0a,
- 0x2e0d, 0x2e0d,
- 0x2e1d, 0x2e1d,
- 0x2e21, 0x2e21,
-}; /* CR_Pf */
-
-/* 'Pi': General Category */
-static const OnigCodePoint CR_Pi[] = {
- 11,
- 0x00ab, 0x00ab,
- 0x2018, 0x2018,
- 0x201b, 0x201c,
- 0x201f, 0x201f,
- 0x2039, 0x2039,
- 0x2e02, 0x2e02,
- 0x2e04, 0x2e04,
- 0x2e09, 0x2e09,
- 0x2e0c, 0x2e0c,
- 0x2e1c, 0x2e1c,
- 0x2e20, 0x2e20,
-}; /* CR_Pi */
-
-/* 'Po': General Category */
-static const OnigCodePoint CR_Po[] = {
- 187,
- 0x0021, 0x0023,
- 0x0025, 0x0027,
- 0x002a, 0x002a,
- 0x002c, 0x002c,
- 0x002e, 0x002f,
- 0x003a, 0x003b,
- 0x003f, 0x0040,
- 0x005c, 0x005c,
- 0x00a1, 0x00a1,
- 0x00a7, 0x00a7,
- 0x00b6, 0x00b7,
- 0x00bf, 0x00bf,
- 0x037e, 0x037e,
- 0x0387, 0x0387,
- 0x055a, 0x055f,
- 0x0589, 0x0589,
- 0x05c0, 0x05c0,
- 0x05c3, 0x05c3,
- 0x05c6, 0x05c6,
- 0x05f3, 0x05f4,
- 0x0609, 0x060a,
- 0x060c, 0x060d,
- 0x061b, 0x061b,
- 0x061d, 0x061f,
- 0x066a, 0x066d,
- 0x06d4, 0x06d4,
- 0x0700, 0x070d,
- 0x07f7, 0x07f9,
- 0x0830, 0x083e,
- 0x085e, 0x085e,
- 0x0964, 0x0965,
- 0x0970, 0x0970,
- 0x09fd, 0x09fd,
- 0x0a76, 0x0a76,
- 0x0af0, 0x0af0,
- 0x0c77, 0x0c77,
- 0x0c84, 0x0c84,
- 0x0df4, 0x0df4,
- 0x0e4f, 0x0e4f,
- 0x0e5a, 0x0e5b,
- 0x0f04, 0x0f12,
- 0x0f14, 0x0f14,
- 0x0f85, 0x0f85,
- 0x0fd0, 0x0fd4,
- 0x0fd9, 0x0fda,
- 0x104a, 0x104f,
- 0x10fb, 0x10fb,
- 0x1360, 0x1368,
- 0x166e, 0x166e,
- 0x16eb, 0x16ed,
- 0x1735, 0x1736,
- 0x17d4, 0x17d6,
- 0x17d8, 0x17da,
- 0x1800, 0x1805,
- 0x1807, 0x180a,
- 0x1944, 0x1945,
- 0x1a1e, 0x1a1f,
- 0x1aa0, 0x1aa6,
- 0x1aa8, 0x1aad,
- 0x1b5a, 0x1b60,
- 0x1b7d, 0x1b7e,
- 0x1bfc, 0x1bff,
- 0x1c3b, 0x1c3f,
- 0x1c7e, 0x1c7f,
- 0x1cc0, 0x1cc7,
- 0x1cd3, 0x1cd3,
- 0x2016, 0x2017,
- 0x2020, 0x2027,
- 0x2030, 0x2038,
- 0x203b, 0x203e,
- 0x2041, 0x2043,
- 0x2047, 0x2051,
- 0x2053, 0x2053,
- 0x2055, 0x205e,
- 0x2cf9, 0x2cfc,
- 0x2cfe, 0x2cff,
- 0x2d70, 0x2d70,
- 0x2e00, 0x2e01,
- 0x2e06, 0x2e08,
- 0x2e0b, 0x2e0b,
- 0x2e0e, 0x2e16,
- 0x2e18, 0x2e19,
- 0x2e1b, 0x2e1b,
- 0x2e1e, 0x2e1f,
- 0x2e2a, 0x2e2e,
- 0x2e30, 0x2e39,
- 0x2e3c, 0x2e3f,
- 0x2e41, 0x2e41,
- 0x2e43, 0x2e4f,
- 0x2e52, 0x2e54,
- 0x3001, 0x3003,
- 0x303d, 0x303d,
- 0x30fb, 0x30fb,
- 0xa4fe, 0xa4ff,
- 0xa60d, 0xa60f,
- 0xa673, 0xa673,
- 0xa67e, 0xa67e,
- 0xa6f2, 0xa6f7,
- 0xa874, 0xa877,
- 0xa8ce, 0xa8cf,
- 0xa8f8, 0xa8fa,
- 0xa8fc, 0xa8fc,
- 0xa92e, 0xa92f,
- 0xa95f, 0xa95f,
- 0xa9c1, 0xa9cd,
- 0xa9de, 0xa9df,
- 0xaa5c, 0xaa5f,
- 0xaade, 0xaadf,
- 0xaaf0, 0xaaf1,
- 0xabeb, 0xabeb,
- 0xfe10, 0xfe16,
- 0xfe19, 0xfe19,
- 0xfe30, 0xfe30,
- 0xfe45, 0xfe46,
- 0xfe49, 0xfe4c,
- 0xfe50, 0xfe52,
- 0xfe54, 0xfe57,
- 0xfe5f, 0xfe61,
- 0xfe68, 0xfe68,
- 0xfe6a, 0xfe6b,
- 0xff01, 0xff03,
- 0xff05, 0xff07,
- 0xff0a, 0xff0a,
- 0xff0c, 0xff0c,
- 0xff0e, 0xff0f,
- 0xff1a, 0xff1b,
- 0xff1f, 0xff20,
- 0xff3c, 0xff3c,
- 0xff61, 0xff61,
- 0xff64, 0xff65,
- 0x10100, 0x10102,
- 0x1039f, 0x1039f,
- 0x103d0, 0x103d0,
- 0x1056f, 0x1056f,
- 0x10857, 0x10857,
- 0x1091f, 0x1091f,
- 0x1093f, 0x1093f,
- 0x10a50, 0x10a58,
- 0x10a7f, 0x10a7f,
- 0x10af0, 0x10af6,
- 0x10b39, 0x10b3f,
- 0x10b99, 0x10b9c,
- 0x10f55, 0x10f59,
- 0x10f86, 0x10f89,
- 0x11047, 0x1104d,
- 0x110bb, 0x110bc,
- 0x110be, 0x110c1,
- 0x11140, 0x11143,
- 0x11174, 0x11175,
- 0x111c5, 0x111c8,
- 0x111cd, 0x111cd,
- 0x111db, 0x111db,
- 0x111dd, 0x111df,
- 0x11238, 0x1123d,
- 0x112a9, 0x112a9,
- 0x1144b, 0x1144f,
- 0x1145a, 0x1145b,
- 0x1145d, 0x1145d,
- 0x114c6, 0x114c6,
- 0x115c1, 0x115d7,
- 0x11641, 0x11643,
- 0x11660, 0x1166c,
- 0x116b9, 0x116b9,
- 0x1173c, 0x1173e,
- 0x1183b, 0x1183b,
- 0x11944, 0x11946,
- 0x119e2, 0x119e2,
- 0x11a3f, 0x11a46,
- 0x11a9a, 0x11a9c,
- 0x11a9e, 0x11aa2,
- 0x11b00, 0x11b09,
- 0x11c41, 0x11c45,
- 0x11c70, 0x11c71,
- 0x11ef7, 0x11ef8,
- 0x11f43, 0x11f4f,
- 0x11fff, 0x11fff,
- 0x12470, 0x12474,
- 0x12ff1, 0x12ff2,
- 0x16a6e, 0x16a6f,
- 0x16af5, 0x16af5,
- 0x16b37, 0x16b3b,
- 0x16b44, 0x16b44,
- 0x16e97, 0x16e9a,
- 0x16fe2, 0x16fe2,
- 0x1bc9f, 0x1bc9f,
- 0x1da87, 0x1da8b,
- 0x1e95e, 0x1e95f,
-}; /* CR_Po */
-
-/* 'Ps': General Category */
-static const OnigCodePoint CR_Ps[] = {
- 79,
- 0x0028, 0x0028,
- 0x005b, 0x005b,
- 0x007b, 0x007b,
- 0x0f3a, 0x0f3a,
- 0x0f3c, 0x0f3c,
- 0x169b, 0x169b,
- 0x201a, 0x201a,
- 0x201e, 0x201e,
- 0x2045, 0x2045,
- 0x207d, 0x207d,
- 0x208d, 0x208d,
- 0x2308, 0x2308,
- 0x230a, 0x230a,
- 0x2329, 0x2329,
- 0x2768, 0x2768,
- 0x276a, 0x276a,
- 0x276c, 0x276c,
- 0x276e, 0x276e,
- 0x2770, 0x2770,
- 0x2772, 0x2772,
- 0x2774, 0x2774,
- 0x27c5, 0x27c5,
- 0x27e6, 0x27e6,
- 0x27e8, 0x27e8,
- 0x27ea, 0x27ea,
- 0x27ec, 0x27ec,
- 0x27ee, 0x27ee,
- 0x2983, 0x2983,
- 0x2985, 0x2985,
- 0x2987, 0x2987,
- 0x2989, 0x2989,
- 0x298b, 0x298b,
- 0x298d, 0x298d,
- 0x298f, 0x298f,
- 0x2991, 0x2991,
- 0x2993, 0x2993,
- 0x2995, 0x2995,
- 0x2997, 0x2997,
- 0x29d8, 0x29d8,
- 0x29da, 0x29da,
- 0x29fc, 0x29fc,
- 0x2e22, 0x2e22,
- 0x2e24, 0x2e24,
- 0x2e26, 0x2e26,
- 0x2e28, 0x2e28,
- 0x2e42, 0x2e42,
- 0x2e55, 0x2e55,
- 0x2e57, 0x2e57,
- 0x2e59, 0x2e59,
- 0x2e5b, 0x2e5b,
- 0x3008, 0x3008,
- 0x300a, 0x300a,
- 0x300c, 0x300c,
- 0x300e, 0x300e,
- 0x3010, 0x3010,
- 0x3014, 0x3014,
- 0x3016, 0x3016,
- 0x3018, 0x3018,
- 0x301a, 0x301a,
- 0x301d, 0x301d,
- 0xfd3f, 0xfd3f,
- 0xfe17, 0xfe17,
- 0xfe35, 0xfe35,
- 0xfe37, 0xfe37,
- 0xfe39, 0xfe39,
- 0xfe3b, 0xfe3b,
- 0xfe3d, 0xfe3d,
- 0xfe3f, 0xfe3f,
- 0xfe41, 0xfe41,
- 0xfe43, 0xfe43,
- 0xfe47, 0xfe47,
- 0xfe59, 0xfe59,
- 0xfe5b, 0xfe5b,
- 0xfe5d, 0xfe5d,
- 0xff08, 0xff08,
- 0xff3b, 0xff3b,
- 0xff5b, 0xff5b,
- 0xff5f, 0xff5f,
- 0xff62, 0xff62,
-}; /* CR_Ps */
-
-/* 'S': Major Category */
-static const OnigCodePoint CR_S[] = {
- 232,
- 0x0024, 0x0024,
- 0x002b, 0x002b,
- 0x003c, 0x003e,
- 0x005e, 0x005e,
- 0x0060, 0x0060,
- 0x007c, 0x007c,
- 0x007e, 0x007e,
- 0x00a2, 0x00a6,
- 0x00a8, 0x00a9,
- 0x00ac, 0x00ac,
- 0x00ae, 0x00b1,
- 0x00b4, 0x00b4,
- 0x00b8, 0x00b8,
- 0x00d7, 0x00d7,
- 0x00f7, 0x00f7,
- 0x02c2, 0x02c5,
- 0x02d2, 0x02df,
- 0x02e5, 0x02eb,
- 0x02ed, 0x02ed,
- 0x02ef, 0x02ff,
- 0x0375, 0x0375,
- 0x0384, 0x0385,
- 0x03f6, 0x03f6,
- 0x0482, 0x0482,
- 0x058d, 0x058f,
- 0x0606, 0x0608,
- 0x060b, 0x060b,
- 0x060e, 0x060f,
- 0x06de, 0x06de,
- 0x06e9, 0x06e9,
- 0x06fd, 0x06fe,
- 0x07f6, 0x07f6,
- 0x07fe, 0x07ff,
- 0x0888, 0x0888,
- 0x09f2, 0x09f3,
- 0x09fa, 0x09fb,
- 0x0af1, 0x0af1,
- 0x0b70, 0x0b70,
- 0x0bf3, 0x0bfa,
- 0x0c7f, 0x0c7f,
- 0x0d4f, 0x0d4f,
- 0x0d79, 0x0d79,
- 0x0e3f, 0x0e3f,
- 0x0f01, 0x0f03,
- 0x0f13, 0x0f13,
- 0x0f15, 0x0f17,
- 0x0f1a, 0x0f1f,
- 0x0f34, 0x0f34,
- 0x0f36, 0x0f36,
- 0x0f38, 0x0f38,
- 0x0fbe, 0x0fc5,
- 0x0fc7, 0x0fcc,
- 0x0fce, 0x0fcf,
- 0x0fd5, 0x0fd8,
- 0x109e, 0x109f,
- 0x1390, 0x1399,
- 0x166d, 0x166d,
- 0x17db, 0x17db,
- 0x1940, 0x1940,
- 0x19de, 0x19ff,
- 0x1b61, 0x1b6a,
- 0x1b74, 0x1b7c,
- 0x1fbd, 0x1fbd,
- 0x1fbf, 0x1fc1,
- 0x1fcd, 0x1fcf,
- 0x1fdd, 0x1fdf,
- 0x1fed, 0x1fef,
- 0x1ffd, 0x1ffe,
- 0x2044, 0x2044,
- 0x2052, 0x2052,
- 0x207a, 0x207c,
- 0x208a, 0x208c,
- 0x20a0, 0x20c0,
- 0x2100, 0x2101,
- 0x2103, 0x2106,
- 0x2108, 0x2109,
- 0x2114, 0x2114,
- 0x2116, 0x2118,
- 0x211e, 0x2123,
- 0x2125, 0x2125,
- 0x2127, 0x2127,
- 0x2129, 0x2129,
- 0x212e, 0x212e,
- 0x213a, 0x213b,
- 0x2140, 0x2144,
- 0x214a, 0x214d,
- 0x214f, 0x214f,
- 0x218a, 0x218b,
- 0x2190, 0x2307,
- 0x230c, 0x2328,
- 0x232b, 0x2426,
- 0x2440, 0x244a,
- 0x249c, 0x24e9,
- 0x2500, 0x2767,
- 0x2794, 0x27c4,
- 0x27c7, 0x27e5,
- 0x27f0, 0x2982,
- 0x2999, 0x29d7,
- 0x29dc, 0x29fb,
- 0x29fe, 0x2b73,
- 0x2b76, 0x2b95,
- 0x2b97, 0x2bff,
- 0x2ce5, 0x2cea,
- 0x2e50, 0x2e51,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3004, 0x3004,
- 0x3012, 0x3013,
- 0x3020, 0x3020,
- 0x3036, 0x3037,
- 0x303e, 0x303f,
- 0x309b, 0x309c,
- 0x3190, 0x3191,
- 0x3196, 0x319f,
- 0x31c0, 0x31e3,
- 0x3200, 0x321e,
- 0x322a, 0x3247,
- 0x3250, 0x3250,
- 0x3260, 0x327f,
- 0x328a, 0x32b0,
- 0x32c0, 0x33ff,
- 0x4dc0, 0x4dff,
- 0xa490, 0xa4c6,
- 0xa700, 0xa716,
- 0xa720, 0xa721,
- 0xa789, 0xa78a,
- 0xa828, 0xa82b,
- 0xa836, 0xa839,
- 0xaa77, 0xaa79,
- 0xab5b, 0xab5b,
- 0xab6a, 0xab6b,
- 0xfb29, 0xfb29,
- 0xfbb2, 0xfbc2,
- 0xfd40, 0xfd4f,
- 0xfdcf, 0xfdcf,
- 0xfdfc, 0xfdff,
- 0xfe62, 0xfe62,
- 0xfe64, 0xfe66,
- 0xfe69, 0xfe69,
- 0xff04, 0xff04,
- 0xff0b, 0xff0b,
- 0xff1c, 0xff1e,
- 0xff3e, 0xff3e,
- 0xff40, 0xff40,
- 0xff5c, 0xff5c,
- 0xff5e, 0xff5e,
- 0xffe0, 0xffe6,
- 0xffe8, 0xffee,
- 0xfffc, 0xfffd,
- 0x10137, 0x1013f,
- 0x10179, 0x10189,
- 0x1018c, 0x1018e,
- 0x10190, 0x1019c,
- 0x101a0, 0x101a0,
- 0x101d0, 0x101fc,
- 0x10877, 0x10878,
- 0x10ac8, 0x10ac8,
- 0x1173f, 0x1173f,
- 0x11fd5, 0x11ff1,
- 0x16b3c, 0x16b3f,
- 0x16b45, 0x16b45,
- 0x1bc9c, 0x1bc9c,
- 0x1cf50, 0x1cfc3,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d129, 0x1d164,
- 0x1d16a, 0x1d16c,
- 0x1d183, 0x1d184,
- 0x1d18c, 0x1d1a9,
- 0x1d1ae, 0x1d1ea,
- 0x1d200, 0x1d241,
- 0x1d245, 0x1d245,
- 0x1d300, 0x1d356,
- 0x1d6c1, 0x1d6c1,
- 0x1d6db, 0x1d6db,
- 0x1d6fb, 0x1d6fb,
- 0x1d715, 0x1d715,
- 0x1d735, 0x1d735,
- 0x1d74f, 0x1d74f,
- 0x1d76f, 0x1d76f,
- 0x1d789, 0x1d789,
- 0x1d7a9, 0x1d7a9,
- 0x1d7c3, 0x1d7c3,
- 0x1d800, 0x1d9ff,
- 0x1da37, 0x1da3a,
- 0x1da6d, 0x1da74,
- 0x1da76, 0x1da83,
- 0x1da85, 0x1da86,
- 0x1e14f, 0x1e14f,
- 0x1e2ff, 0x1e2ff,
- 0x1ecac, 0x1ecac,
- 0x1ecb0, 0x1ecb0,
- 0x1ed2e, 0x1ed2e,
- 0x1eef0, 0x1eef1,
- 0x1f000, 0x1f02b,
- 0x1f030, 0x1f093,
- 0x1f0a0, 0x1f0ae,
- 0x1f0b1, 0x1f0bf,
- 0x1f0c1, 0x1f0cf,
- 0x1f0d1, 0x1f0f5,
- 0x1f10d, 0x1f1ad,
- 0x1f1e6, 0x1f202,
- 0x1f210, 0x1f23b,
- 0x1f240, 0x1f248,
- 0x1f250, 0x1f251,
- 0x1f260, 0x1f265,
- 0x1f300, 0x1f6d7,
- 0x1f6dc, 0x1f6ec,
- 0x1f6f0, 0x1f6fc,
- 0x1f700, 0x1f776,
- 0x1f77b, 0x1f7d9,
- 0x1f7e0, 0x1f7eb,
- 0x1f7f0, 0x1f7f0,
- 0x1f800, 0x1f80b,
- 0x1f810, 0x1f847,
- 0x1f850, 0x1f859,
- 0x1f860, 0x1f887,
- 0x1f890, 0x1f8ad,
- 0x1f8b0, 0x1f8b1,
- 0x1f900, 0x1fa53,
- 0x1fa60, 0x1fa6d,
- 0x1fa70, 0x1fa7c,
- 0x1fa80, 0x1fa88,
- 0x1fa90, 0x1fabd,
- 0x1fabf, 0x1fac5,
- 0x1face, 0x1fadb,
- 0x1fae0, 0x1fae8,
- 0x1faf0, 0x1faf8,
- 0x1fb00, 0x1fb92,
- 0x1fb94, 0x1fbca,
-}; /* CR_S */
-
-/* 'Sc': General Category */
-static const OnigCodePoint CR_Sc[] = {
- 21,
- 0x0024, 0x0024,
- 0x00a2, 0x00a5,
- 0x058f, 0x058f,
- 0x060b, 0x060b,
- 0x07fe, 0x07ff,
- 0x09f2, 0x09f3,
- 0x09fb, 0x09fb,
- 0x0af1, 0x0af1,
- 0x0bf9, 0x0bf9,
- 0x0e3f, 0x0e3f,
- 0x17db, 0x17db,
- 0x20a0, 0x20c0,
- 0xa838, 0xa838,
- 0xfdfc, 0xfdfc,
- 0xfe69, 0xfe69,
- 0xff04, 0xff04,
- 0xffe0, 0xffe1,
- 0xffe5, 0xffe6,
- 0x11fdd, 0x11fe0,
- 0x1e2ff, 0x1e2ff,
- 0x1ecb0, 0x1ecb0,
-}; /* CR_Sc */
-
-/* 'Sk': General Category */
-static const OnigCodePoint CR_Sk[] = {
- 31,
- 0x005e, 0x005e,
- 0x0060, 0x0060,
- 0x00a8, 0x00a8,
- 0x00af, 0x00af,
- 0x00b4, 0x00b4,
- 0x00b8, 0x00b8,
- 0x02c2, 0x02c5,
- 0x02d2, 0x02df,
- 0x02e5, 0x02eb,
- 0x02ed, 0x02ed,
- 0x02ef, 0x02ff,
- 0x0375, 0x0375,
- 0x0384, 0x0385,
- 0x0888, 0x0888,
- 0x1fbd, 0x1fbd,
- 0x1fbf, 0x1fc1,
- 0x1fcd, 0x1fcf,
- 0x1fdd, 0x1fdf,
- 0x1fed, 0x1fef,
- 0x1ffd, 0x1ffe,
- 0x309b, 0x309c,
- 0xa700, 0xa716,
- 0xa720, 0xa721,
- 0xa789, 0xa78a,
- 0xab5b, 0xab5b,
- 0xab6a, 0xab6b,
- 0xfbb2, 0xfbc2,
- 0xff3e, 0xff3e,
- 0xff40, 0xff40,
- 0xffe3, 0xffe3,
- 0x1f3fb, 0x1f3ff,
-}; /* CR_Sk */
-
-/* 'Sm': General Category */
-static const OnigCodePoint CR_Sm[] = {
- 64,
- 0x002b, 0x002b,
- 0x003c, 0x003e,
- 0x007c, 0x007c,
- 0x007e, 0x007e,
- 0x00ac, 0x00ac,
- 0x00b1, 0x00b1,
- 0x00d7, 0x00d7,
- 0x00f7, 0x00f7,
- 0x03f6, 0x03f6,
- 0x0606, 0x0608,
- 0x2044, 0x2044,
- 0x2052, 0x2052,
- 0x207a, 0x207c,
- 0x208a, 0x208c,
- 0x2118, 0x2118,
- 0x2140, 0x2144,
- 0x214b, 0x214b,
- 0x2190, 0x2194,
- 0x219a, 0x219b,
- 0x21a0, 0x21a0,
- 0x21a3, 0x21a3,
- 0x21a6, 0x21a6,
- 0x21ae, 0x21ae,
- 0x21ce, 0x21cf,
- 0x21d2, 0x21d2,
- 0x21d4, 0x21d4,
- 0x21f4, 0x22ff,
- 0x2320, 0x2321,
- 0x237c, 0x237c,
- 0x239b, 0x23b3,
- 0x23dc, 0x23e1,
- 0x25b7, 0x25b7,
- 0x25c1, 0x25c1,
- 0x25f8, 0x25ff,
- 0x266f, 0x266f,
- 0x27c0, 0x27c4,
- 0x27c7, 0x27e5,
- 0x27f0, 0x27ff,
- 0x2900, 0x2982,
- 0x2999, 0x29d7,
- 0x29dc, 0x29fb,
- 0x29fe, 0x2aff,
- 0x2b30, 0x2b44,
- 0x2b47, 0x2b4c,
- 0xfb29, 0xfb29,
- 0xfe62, 0xfe62,
- 0xfe64, 0xfe66,
- 0xff0b, 0xff0b,
- 0xff1c, 0xff1e,
- 0xff5c, 0xff5c,
- 0xff5e, 0xff5e,
- 0xffe2, 0xffe2,
- 0xffe9, 0xffec,
- 0x1d6c1, 0x1d6c1,
- 0x1d6db, 0x1d6db,
- 0x1d6fb, 0x1d6fb,
- 0x1d715, 0x1d715,
- 0x1d735, 0x1d735,
- 0x1d74f, 0x1d74f,
- 0x1d76f, 0x1d76f,
- 0x1d789, 0x1d789,
- 0x1d7a9, 0x1d7a9,
- 0x1d7c3, 0x1d7c3,
- 0x1eef0, 0x1eef1,
-}; /* CR_Sm */
-
-/* 'So': General Category */
-static const OnigCodePoint CR_So[] = {
- 184,
- 0x00a6, 0x00a6,
- 0x00a9, 0x00a9,
- 0x00ae, 0x00ae,
- 0x00b0, 0x00b0,
- 0x0482, 0x0482,
- 0x058d, 0x058e,
- 0x060e, 0x060f,
- 0x06de, 0x06de,
- 0x06e9, 0x06e9,
- 0x06fd, 0x06fe,
- 0x07f6, 0x07f6,
- 0x09fa, 0x09fa,
- 0x0b70, 0x0b70,
- 0x0bf3, 0x0bf8,
- 0x0bfa, 0x0bfa,
- 0x0c7f, 0x0c7f,
- 0x0d4f, 0x0d4f,
- 0x0d79, 0x0d79,
- 0x0f01, 0x0f03,
- 0x0f13, 0x0f13,
- 0x0f15, 0x0f17,
- 0x0f1a, 0x0f1f,
- 0x0f34, 0x0f34,
- 0x0f36, 0x0f36,
- 0x0f38, 0x0f38,
- 0x0fbe, 0x0fc5,
- 0x0fc7, 0x0fcc,
- 0x0fce, 0x0fcf,
- 0x0fd5, 0x0fd8,
- 0x109e, 0x109f,
- 0x1390, 0x1399,
- 0x166d, 0x166d,
- 0x1940, 0x1940,
- 0x19de, 0x19ff,
- 0x1b61, 0x1b6a,
- 0x1b74, 0x1b7c,
- 0x2100, 0x2101,
- 0x2103, 0x2106,
- 0x2108, 0x2109,
- 0x2114, 0x2114,
- 0x2116, 0x2117,
- 0x211e, 0x2123,
- 0x2125, 0x2125,
- 0x2127, 0x2127,
- 0x2129, 0x2129,
- 0x212e, 0x212e,
- 0x213a, 0x213b,
- 0x214a, 0x214a,
- 0x214c, 0x214d,
- 0x214f, 0x214f,
- 0x218a, 0x218b,
- 0x2195, 0x2199,
- 0x219c, 0x219f,
- 0x21a1, 0x21a2,
- 0x21a4, 0x21a5,
- 0x21a7, 0x21ad,
- 0x21af, 0x21cd,
- 0x21d0, 0x21d1,
- 0x21d3, 0x21d3,
- 0x21d5, 0x21f3,
- 0x2300, 0x2307,
- 0x230c, 0x231f,
- 0x2322, 0x2328,
- 0x232b, 0x237b,
- 0x237d, 0x239a,
- 0x23b4, 0x23db,
- 0x23e2, 0x2426,
- 0x2440, 0x244a,
- 0x249c, 0x24e9,
- 0x2500, 0x25b6,
- 0x25b8, 0x25c0,
- 0x25c2, 0x25f7,
- 0x2600, 0x266e,
- 0x2670, 0x2767,
- 0x2794, 0x27bf,
- 0x2800, 0x28ff,
- 0x2b00, 0x2b2f,
- 0x2b45, 0x2b46,
- 0x2b4d, 0x2b73,
- 0x2b76, 0x2b95,
- 0x2b97, 0x2bff,
- 0x2ce5, 0x2cea,
- 0x2e50, 0x2e51,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3004, 0x3004,
- 0x3012, 0x3013,
- 0x3020, 0x3020,
- 0x3036, 0x3037,
- 0x303e, 0x303f,
- 0x3190, 0x3191,
- 0x3196, 0x319f,
- 0x31c0, 0x31e3,
- 0x3200, 0x321e,
- 0x322a, 0x3247,
- 0x3250, 0x3250,
- 0x3260, 0x327f,
- 0x328a, 0x32b0,
- 0x32c0, 0x33ff,
- 0x4dc0, 0x4dff,
- 0xa490, 0xa4c6,
- 0xa828, 0xa82b,
- 0xa836, 0xa837,
- 0xa839, 0xa839,
- 0xaa77, 0xaa79,
- 0xfd40, 0xfd4f,
- 0xfdcf, 0xfdcf,
- 0xfdfd, 0xfdff,
- 0xffe4, 0xffe4,
- 0xffe8, 0xffe8,
- 0xffed, 0xffee,
- 0xfffc, 0xfffd,
- 0x10137, 0x1013f,
- 0x10179, 0x10189,
- 0x1018c, 0x1018e,
- 0x10190, 0x1019c,
- 0x101a0, 0x101a0,
- 0x101d0, 0x101fc,
- 0x10877, 0x10878,
- 0x10ac8, 0x10ac8,
- 0x1173f, 0x1173f,
- 0x11fd5, 0x11fdc,
- 0x11fe1, 0x11ff1,
- 0x16b3c, 0x16b3f,
- 0x16b45, 0x16b45,
- 0x1bc9c, 0x1bc9c,
- 0x1cf50, 0x1cfc3,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d129, 0x1d164,
- 0x1d16a, 0x1d16c,
- 0x1d183, 0x1d184,
- 0x1d18c, 0x1d1a9,
- 0x1d1ae, 0x1d1ea,
- 0x1d200, 0x1d241,
- 0x1d245, 0x1d245,
- 0x1d300, 0x1d356,
- 0x1d800, 0x1d9ff,
- 0x1da37, 0x1da3a,
- 0x1da6d, 0x1da74,
- 0x1da76, 0x1da83,
- 0x1da85, 0x1da86,
- 0x1e14f, 0x1e14f,
- 0x1ecac, 0x1ecac,
- 0x1ed2e, 0x1ed2e,
- 0x1f000, 0x1f02b,
- 0x1f030, 0x1f093,
- 0x1f0a0, 0x1f0ae,
- 0x1f0b1, 0x1f0bf,
- 0x1f0c1, 0x1f0cf,
- 0x1f0d1, 0x1f0f5,
- 0x1f10d, 0x1f1ad,
- 0x1f1e6, 0x1f202,
- 0x1f210, 0x1f23b,
- 0x1f240, 0x1f248,
- 0x1f250, 0x1f251,
- 0x1f260, 0x1f265,
- 0x1f300, 0x1f3fa,
- 0x1f400, 0x1f6d7,
- 0x1f6dc, 0x1f6ec,
- 0x1f6f0, 0x1f6fc,
- 0x1f700, 0x1f776,
- 0x1f77b, 0x1f7d9,
- 0x1f7e0, 0x1f7eb,
- 0x1f7f0, 0x1f7f0,
- 0x1f800, 0x1f80b,
- 0x1f810, 0x1f847,
- 0x1f850, 0x1f859,
- 0x1f860, 0x1f887,
- 0x1f890, 0x1f8ad,
- 0x1f8b0, 0x1f8b1,
- 0x1f900, 0x1fa53,
- 0x1fa60, 0x1fa6d,
- 0x1fa70, 0x1fa7c,
- 0x1fa80, 0x1fa88,
- 0x1fa90, 0x1fabd,
- 0x1fabf, 0x1fac5,
- 0x1face, 0x1fadb,
- 0x1fae0, 0x1fae8,
- 0x1faf0, 0x1faf8,
- 0x1fb00, 0x1fb92,
- 0x1fb94, 0x1fbca,
-}; /* CR_So */
-
-/* 'Z': Major Category */
-static const OnigCodePoint CR_Z[] = {
- 8,
- 0x0020, 0x0020,
- 0x00a0, 0x00a0,
- 0x1680, 0x1680,
- 0x2000, 0x200a,
- 0x2028, 0x2029,
- 0x202f, 0x202f,
- 0x205f, 0x205f,
- 0x3000, 0x3000,
-}; /* CR_Z */
-
-/* 'Zl': General Category */
-static const OnigCodePoint CR_Zl[] = {
- 1,
- 0x2028, 0x2028,
-}; /* CR_Zl */
-
-/* 'Zp': General Category */
-static const OnigCodePoint CR_Zp[] = {
- 1,
- 0x2029, 0x2029,
-}; /* CR_Zp */
-
-/* 'Zs': General Category */
-static const OnigCodePoint CR_Zs[] = {
- 7,
- 0x0020, 0x0020,
- 0x00a0, 0x00a0,
- 0x1680, 0x1680,
- 0x2000, 0x200a,
- 0x202f, 0x202f,
- 0x205f, 0x205f,
- 0x3000, 0x3000,
-}; /* CR_Zs */
-
-/* 'Math': Derived Property */
-static const OnigCodePoint CR_Math[] = {
- 138,
- 0x002b, 0x002b,
- 0x003c, 0x003e,
- 0x005e, 0x005e,
- 0x007c, 0x007c,
- 0x007e, 0x007e,
- 0x00ac, 0x00ac,
- 0x00b1, 0x00b1,
- 0x00d7, 0x00d7,
- 0x00f7, 0x00f7,
- 0x03d0, 0x03d2,
- 0x03d5, 0x03d5,
- 0x03f0, 0x03f1,
- 0x03f4, 0x03f6,
- 0x0606, 0x0608,
- 0x2016, 0x2016,
- 0x2032, 0x2034,
- 0x2040, 0x2040,
- 0x2044, 0x2044,
- 0x2052, 0x2052,
- 0x2061, 0x2064,
- 0x207a, 0x207e,
- 0x208a, 0x208e,
- 0x20d0, 0x20dc,
- 0x20e1, 0x20e1,
- 0x20e5, 0x20e6,
- 0x20eb, 0x20ef,
- 0x2102, 0x2102,
- 0x2107, 0x2107,
- 0x210a, 0x2113,
- 0x2115, 0x2115,
- 0x2118, 0x211d,
- 0x2124, 0x2124,
- 0x2128, 0x2129,
- 0x212c, 0x212d,
- 0x212f, 0x2131,
- 0x2133, 0x2138,
- 0x213c, 0x2149,
- 0x214b, 0x214b,
- 0x2190, 0x21a7,
- 0x21a9, 0x21ae,
- 0x21b0, 0x21b1,
- 0x21b6, 0x21b7,
- 0x21bc, 0x21db,
- 0x21dd, 0x21dd,
- 0x21e4, 0x21e5,
- 0x21f4, 0x22ff,
- 0x2308, 0x230b,
- 0x2320, 0x2321,
- 0x237c, 0x237c,
- 0x239b, 0x23b5,
- 0x23b7, 0x23b7,
- 0x23d0, 0x23d0,
- 0x23dc, 0x23e2,
- 0x25a0, 0x25a1,
- 0x25ae, 0x25b7,
- 0x25bc, 0x25c1,
- 0x25c6, 0x25c7,
- 0x25ca, 0x25cb,
- 0x25cf, 0x25d3,
- 0x25e2, 0x25e2,
- 0x25e4, 0x25e4,
- 0x25e7, 0x25ec,
- 0x25f8, 0x25ff,
- 0x2605, 0x2606,
- 0x2640, 0x2640,
- 0x2642, 0x2642,
- 0x2660, 0x2663,
- 0x266d, 0x266f,
- 0x27c0, 0x27ff,
- 0x2900, 0x2aff,
- 0x2b30, 0x2b44,
- 0x2b47, 0x2b4c,
- 0xfb29, 0xfb29,
- 0xfe61, 0xfe66,
- 0xfe68, 0xfe68,
- 0xff0b, 0xff0b,
- 0xff1c, 0xff1e,
- 0xff3c, 0xff3c,
- 0xff3e, 0xff3e,
- 0xff5c, 0xff5c,
- 0xff5e, 0xff5e,
- 0xffe2, 0xffe2,
- 0xffe9, 0xffec,
- 0x1d400, 0x1d454,
- 0x1d456, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 0x1d4a2, 0x1d4a2,
- 0x1d4a5, 0x1d4a6,
- 0x1d4a9, 0x1d4ac,
- 0x1d4ae, 0x1d4b9,
- 0x1d4bb, 0x1d4bb,
- 0x1d4bd, 0x1d4c3,
- 0x1d4c5, 0x1d505,
- 0x1d507, 0x1d50a,
- 0x1d50d, 0x1d514,
- 0x1d516, 0x1d51c,
- 0x1d51e, 0x1d539,
- 0x1d53b, 0x1d53e,
- 0x1d540, 0x1d544,
- 0x1d546, 0x1d546,
- 0x1d54a, 0x1d550,
- 0x1d552, 0x1d6a5,
- 0x1d6a8, 0x1d7cb,
- 0x1d7ce, 0x1d7ff,
- 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,
-}; /* CR_Math */
-
-/* 'Alphabetic': Derived Property */
-#define CR_Alphabetic CR_Alpha
-
-/* 'Lowercase': Derived Property */
-#define CR_Lowercase CR_Lower
-
-/* 'Uppercase': Derived Property */
-#define CR_Uppercase CR_Upper
-
-/* 'Cased': Derived Property */
-static const OnigCodePoint CR_Cased[] = {
- 157,
- 0x0041, 0x005a,
- 0x0061, 0x007a,
- 0x00aa, 0x00aa,
- 0x00b5, 0x00b5,
- 0x00ba, 0x00ba,
- 0x00c0, 0x00d6,
- 0x00d8, 0x00f6,
- 0x00f8, 0x01ba,
- 0x01bc, 0x01bf,
- 0x01c4, 0x0293,
- 0x0295, 0x02b8,
- 0x02c0, 0x02c1,
- 0x02e0, 0x02e4,
- 0x0345, 0x0345,
- 0x0370, 0x0373,
- 0x0376, 0x0377,
- 0x037a, 0x037d,
- 0x037f, 0x037f,
- 0x0386, 0x0386,
- 0x0388, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03f5,
- 0x03f7, 0x0481,
- 0x048a, 0x052f,
- 0x0531, 0x0556,
- 0x0560, 0x0588,
- 0x10a0, 0x10c5,
- 0x10c7, 0x10c7,
- 0x10cd, 0x10cd,
- 0x10d0, 0x10fa,
- 0x10fc, 0x10ff,
- 0x13a0, 0x13f5,
- 0x13f8, 0x13fd,
- 0x1c80, 0x1c88,
- 0x1c90, 0x1cba,
- 0x1cbd, 0x1cbf,
- 0x1d00, 0x1dbf,
- 0x1e00, 0x1f15,
- 0x1f18, 0x1f1d,
- 0x1f20, 0x1f45,
- 0x1f48, 0x1f4d,
- 0x1f50, 0x1f57,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f7d,
- 0x1f80, 0x1fb4,
- 0x1fb6, 0x1fbc,
- 0x1fbe, 0x1fbe,
- 0x1fc2, 0x1fc4,
- 0x1fc6, 0x1fcc,
- 0x1fd0, 0x1fd3,
- 0x1fd6, 0x1fdb,
- 0x1fe0, 0x1fec,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ffc,
- 0x2071, 0x2071,
- 0x207f, 0x207f,
- 0x2090, 0x209c,
- 0x2102, 0x2102,
- 0x2107, 0x2107,
- 0x210a, 0x2113,
- 0x2115, 0x2115,
- 0x2119, 0x211d,
- 0x2124, 0x2124,
- 0x2126, 0x2126,
- 0x2128, 0x2128,
- 0x212a, 0x212d,
- 0x212f, 0x2134,
- 0x2139, 0x2139,
- 0x213c, 0x213f,
- 0x2145, 0x2149,
- 0x214e, 0x214e,
- 0x2160, 0x217f,
- 0x2183, 0x2184,
- 0x24b6, 0x24e9,
- 0x2c00, 0x2ce4,
- 0x2ceb, 0x2cee,
- 0x2cf2, 0x2cf3,
- 0x2d00, 0x2d25,
- 0x2d27, 0x2d27,
- 0x2d2d, 0x2d2d,
- 0xa640, 0xa66d,
- 0xa680, 0xa69d,
- 0xa722, 0xa787,
- 0xa78b, 0xa78e,
- 0xa790, 0xa7ca,
- 0xa7d0, 0xa7d1,
- 0xa7d3, 0xa7d3,
- 0xa7d5, 0xa7d9,
- 0xa7f2, 0xa7f6,
- 0xa7f8, 0xa7fa,
- 0xab30, 0xab5a,
- 0xab5c, 0xab69,
- 0xab70, 0xabbf,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xff21, 0xff3a,
- 0xff41, 0xff5a,
- 0x10400, 0x1044f,
- 0x104b0, 0x104d3,
- 0x104d8, 0x104fb,
- 0x10570, 0x1057a,
- 0x1057c, 0x1058a,
- 0x1058c, 0x10592,
- 0x10594, 0x10595,
- 0x10597, 0x105a1,
- 0x105a3, 0x105b1,
- 0x105b3, 0x105b9,
- 0x105bb, 0x105bc,
- 0x10780, 0x10780,
- 0x10783, 0x10785,
- 0x10787, 0x107b0,
- 0x107b2, 0x107ba,
- 0x10c80, 0x10cb2,
- 0x10cc0, 0x10cf2,
- 0x118a0, 0x118df,
- 0x16e40, 0x16e7f,
- 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, 0x1d6c0,
- 0x1d6c2, 0x1d6da,
- 0x1d6dc, 0x1d6fa,
- 0x1d6fc, 0x1d714,
- 0x1d716, 0x1d734,
- 0x1d736, 0x1d74e,
- 0x1d750, 0x1d76e,
- 0x1d770, 0x1d788,
- 0x1d78a, 0x1d7a8,
- 0x1d7aa, 0x1d7c2,
- 0x1d7c4, 0x1d7cb,
- 0x1df00, 0x1df09,
- 0x1df0b, 0x1df1e,
- 0x1df25, 0x1df2a,
- 0x1e030, 0x1e06d,
- 0x1e900, 0x1e943,
- 0x1f130, 0x1f149,
- 0x1f150, 0x1f169,
- 0x1f170, 0x1f189,
-}; /* CR_Cased */
-
-/* 'Case_Ignorable': Derived Property */
-static const OnigCodePoint CR_Case_Ignorable[] = {
- 437,
- 0x0027, 0x0027,
- 0x002e, 0x002e,
- 0x003a, 0x003a,
- 0x005e, 0x005e,
- 0x0060, 0x0060,
- 0x00a8, 0x00a8,
- 0x00ad, 0x00ad,
- 0x00af, 0x00af,
- 0x00b4, 0x00b4,
- 0x00b7, 0x00b8,
- 0x02b0, 0x036f,
- 0x0374, 0x0375,
- 0x037a, 0x037a,
- 0x0384, 0x0385,
- 0x0387, 0x0387,
- 0x0483, 0x0489,
- 0x0559, 0x0559,
- 0x055f, 0x055f,
- 0x0591, 0x05bd,
- 0x05bf, 0x05bf,
- 0x05c1, 0x05c2,
- 0x05c4, 0x05c5,
- 0x05c7, 0x05c7,
- 0x05f4, 0x05f4,
- 0x0600, 0x0605,
- 0x0610, 0x061a,
- 0x061c, 0x061c,
- 0x0640, 0x0640,
- 0x064b, 0x065f,
- 0x0670, 0x0670,
- 0x06d6, 0x06dd,
- 0x06df, 0x06e8,
- 0x06ea, 0x06ed,
- 0x070f, 0x070f,
- 0x0711, 0x0711,
- 0x0730, 0x074a,
- 0x07a6, 0x07b0,
- 0x07eb, 0x07f5,
- 0x07fa, 0x07fa,
- 0x07fd, 0x07fd,
- 0x0816, 0x082d,
- 0x0859, 0x085b,
- 0x0888, 0x0888,
- 0x0890, 0x0891,
- 0x0898, 0x089f,
- 0x08c9, 0x0902,
- 0x093a, 0x093a,
- 0x093c, 0x093c,
- 0x0941, 0x0948,
- 0x094d, 0x094d,
- 0x0951, 0x0957,
- 0x0962, 0x0963,
- 0x0971, 0x0971,
- 0x0981, 0x0981,
- 0x09bc, 0x09bc,
- 0x09c1, 0x09c4,
- 0x09cd, 0x09cd,
- 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,
- 0x0b3f, 0x0b3f,
- 0x0b41, 0x0b44,
- 0x0b4d, 0x0b4d,
- 0x0b55, 0x0b56,
- 0x0b62, 0x0b63,
- 0x0b82, 0x0b82,
- 0x0bc0, 0x0bc0,
- 0x0bcd, 0x0bcd,
- 0x0c00, 0x0c00,
- 0x0c04, 0x0c04,
- 0x0c3c, 0x0c3c,
- 0x0c3e, 0x0c40,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c62, 0x0c63,
- 0x0c81, 0x0c81,
- 0x0cbc, 0x0cbc,
- 0x0cbf, 0x0cbf,
- 0x0cc6, 0x0cc6,
- 0x0ccc, 0x0ccd,
- 0x0ce2, 0x0ce3,
- 0x0d00, 0x0d01,
- 0x0d3b, 0x0d3c,
- 0x0d41, 0x0d44,
- 0x0d4d, 0x0d4d,
- 0x0d62, 0x0d63,
- 0x0d81, 0x0d81,
- 0x0dca, 0x0dca,
- 0x0dd2, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0e31, 0x0e31,
- 0x0e34, 0x0e3a,
- 0x0e46, 0x0e4e,
- 0x0eb1, 0x0eb1,
- 0x0eb4, 0x0ebc,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ece,
- 0x0f18, 0x0f19,
- 0x0f35, 0x0f35,
- 0x0f37, 0x0f37,
- 0x0f39, 0x0f39,
- 0x0f71, 0x0f7e,
- 0x0f80, 0x0f84,
- 0x0f86, 0x0f87,
- 0x0f8d, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x0fc6, 0x0fc6,
- 0x102d, 0x1030,
- 0x1032, 0x1037,
- 0x1039, 0x103a,
- 0x103d, 0x103e,
- 0x1058, 0x1059,
- 0x105e, 0x1060,
- 0x1071, 0x1074,
- 0x1082, 0x1082,
- 0x1085, 0x1086,
- 0x108d, 0x108d,
- 0x109d, 0x109d,
- 0x10fc, 0x10fc,
- 0x135d, 0x135f,
- 0x1712, 0x1714,
- 0x1732, 0x1733,
- 0x1752, 0x1753,
- 0x1772, 0x1773,
- 0x17b4, 0x17b5,
- 0x17b7, 0x17bd,
- 0x17c6, 0x17c6,
- 0x17c9, 0x17d3,
- 0x17d7, 0x17d7,
- 0x17dd, 0x17dd,
- 0x180b, 0x180f,
- 0x1843, 0x1843,
- 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,
- 0x1aa7, 0x1aa7,
- 0x1ab0, 0x1ace,
- 0x1b00, 0x1b03,
- 0x1b34, 0x1b34,
- 0x1b36, 0x1b3a,
- 0x1b3c, 0x1b3c,
- 0x1b42, 0x1b42,
- 0x1b6b, 0x1b73,
- 0x1b80, 0x1b81,
- 0x1ba2, 0x1ba5,
- 0x1ba8, 0x1ba9,
- 0x1bab, 0x1bad,
- 0x1be6, 0x1be6,
- 0x1be8, 0x1be9,
- 0x1bed, 0x1bed,
- 0x1bef, 0x1bf1,
- 0x1c2c, 0x1c33,
- 0x1c36, 0x1c37,
- 0x1c78, 0x1c7d,
- 0x1cd0, 0x1cd2,
- 0x1cd4, 0x1ce0,
- 0x1ce2, 0x1ce8,
- 0x1ced, 0x1ced,
- 0x1cf4, 0x1cf4,
- 0x1cf8, 0x1cf9,
- 0x1d2c, 0x1d6a,
- 0x1d78, 0x1d78,
- 0x1d9b, 0x1dff,
- 0x1fbd, 0x1fbd,
- 0x1fbf, 0x1fc1,
- 0x1fcd, 0x1fcf,
- 0x1fdd, 0x1fdf,
- 0x1fed, 0x1fef,
- 0x1ffd, 0x1ffe,
- 0x200b, 0x200f,
- 0x2018, 0x2019,
- 0x2024, 0x2024,
- 0x2027, 0x2027,
- 0x202a, 0x202e,
- 0x2060, 0x2064,
- 0x2066, 0x206f,
- 0x2071, 0x2071,
- 0x207f, 0x207f,
- 0x2090, 0x209c,
- 0x20d0, 0x20f0,
- 0x2c7c, 0x2c7d,
- 0x2cef, 0x2cf1,
- 0x2d6f, 0x2d6f,
- 0x2d7f, 0x2d7f,
- 0x2de0, 0x2dff,
- 0x2e2f, 0x2e2f,
- 0x3005, 0x3005,
- 0x302a, 0x302d,
- 0x3031, 0x3035,
- 0x303b, 0x303b,
- 0x3099, 0x309e,
- 0x30fc, 0x30fe,
- 0xa015, 0xa015,
- 0xa4f8, 0xa4fd,
- 0xa60c, 0xa60c,
- 0xa66f, 0xa672,
- 0xa674, 0xa67d,
- 0xa67f, 0xa67f,
- 0xa69c, 0xa69f,
- 0xa6f0, 0xa6f1,
- 0xa700, 0xa721,
- 0xa770, 0xa770,
- 0xa788, 0xa78a,
- 0xa7f2, 0xa7f4,
- 0xa7f8, 0xa7f9,
- 0xa802, 0xa802,
- 0xa806, 0xa806,
- 0xa80b, 0xa80b,
- 0xa825, 0xa826,
- 0xa82c, 0xa82c,
- 0xa8c4, 0xa8c5,
- 0xa8e0, 0xa8f1,
- 0xa8ff, 0xa8ff,
- 0xa926, 0xa92d,
- 0xa947, 0xa951,
- 0xa980, 0xa982,
- 0xa9b3, 0xa9b3,
- 0xa9b6, 0xa9b9,
- 0xa9bc, 0xa9bd,
- 0xa9cf, 0xa9cf,
- 0xa9e5, 0xa9e6,
- 0xaa29, 0xaa2e,
- 0xaa31, 0xaa32,
- 0xaa35, 0xaa36,
- 0xaa43, 0xaa43,
- 0xaa4c, 0xaa4c,
- 0xaa70, 0xaa70,
- 0xaa7c, 0xaa7c,
- 0xaab0, 0xaab0,
- 0xaab2, 0xaab4,
- 0xaab7, 0xaab8,
- 0xaabe, 0xaabf,
- 0xaac1, 0xaac1,
- 0xaadd, 0xaadd,
- 0xaaec, 0xaaed,
- 0xaaf3, 0xaaf4,
- 0xaaf6, 0xaaf6,
- 0xab5b, 0xab5f,
- 0xab69, 0xab6b,
- 0xabe5, 0xabe5,
- 0xabe8, 0xabe8,
- 0xabed, 0xabed,
- 0xfb1e, 0xfb1e,
- 0xfbb2, 0xfbc2,
- 0xfe00, 0xfe0f,
- 0xfe13, 0xfe13,
- 0xfe20, 0xfe2f,
- 0xfe52, 0xfe52,
- 0xfe55, 0xfe55,
- 0xfeff, 0xfeff,
- 0xff07, 0xff07,
- 0xff0e, 0xff0e,
- 0xff1a, 0xff1a,
- 0xff3e, 0xff3e,
- 0xff40, 0xff40,
- 0xff70, 0xff70,
- 0xff9e, 0xff9f,
- 0xffe3, 0xffe3,
- 0xfff9, 0xfffb,
- 0x101fd, 0x101fd,
- 0x102e0, 0x102e0,
- 0x10376, 0x1037a,
- 0x10780, 0x10785,
- 0x10787, 0x107b0,
- 0x107b2, 0x107ba,
- 0x10a01, 0x10a03,
- 0x10a05, 0x10a06,
- 0x10a0c, 0x10a0f,
- 0x10a38, 0x10a3a,
- 0x10a3f, 0x10a3f,
- 0x10ae5, 0x10ae6,
- 0x10d24, 0x10d27,
- 0x10eab, 0x10eac,
- 0x10efd, 0x10eff,
- 0x10f46, 0x10f50,
- 0x10f82, 0x10f85,
- 0x11001, 0x11001,
- 0x11038, 0x11046,
- 0x11070, 0x11070,
- 0x11073, 0x11074,
- 0x1107f, 0x11081,
- 0x110b3, 0x110b6,
- 0x110b9, 0x110ba,
- 0x110bd, 0x110bd,
- 0x110c2, 0x110c2,
- 0x110cd, 0x110cd,
- 0x11100, 0x11102,
- 0x11127, 0x1112b,
- 0x1112d, 0x11134,
- 0x11173, 0x11173,
- 0x11180, 0x11181,
- 0x111b6, 0x111be,
- 0x111c9, 0x111cc,
- 0x111cf, 0x111cf,
- 0x1122f, 0x11231,
- 0x11234, 0x11234,
- 0x11236, 0x11237,
- 0x1123e, 0x1123e,
- 0x11241, 0x11241,
- 0x112df, 0x112df,
- 0x112e3, 0x112ea,
- 0x11300, 0x11301,
- 0x1133b, 0x1133c,
- 0x11340, 0x11340,
- 0x11366, 0x1136c,
- 0x11370, 0x11374,
- 0x11438, 0x1143f,
- 0x11442, 0x11444,
- 0x11446, 0x11446,
- 0x1145e, 0x1145e,
- 0x114b3, 0x114b8,
- 0x114ba, 0x114ba,
- 0x114bf, 0x114c0,
- 0x114c2, 0x114c3,
- 0x115b2, 0x115b5,
- 0x115bc, 0x115bd,
- 0x115bf, 0x115c0,
- 0x115dc, 0x115dd,
- 0x11633, 0x1163a,
- 0x1163d, 0x1163d,
- 0x1163f, 0x11640,
- 0x116ab, 0x116ab,
- 0x116ad, 0x116ad,
- 0x116b0, 0x116b5,
- 0x116b7, 0x116b7,
- 0x1171d, 0x1171f,
- 0x11722, 0x11725,
- 0x11727, 0x1172b,
- 0x1182f, 0x11837,
- 0x11839, 0x1183a,
- 0x1193b, 0x1193c,
- 0x1193e, 0x1193e,
- 0x11943, 0x11943,
- 0x119d4, 0x119d7,
- 0x119da, 0x119db,
- 0x119e0, 0x119e0,
- 0x11a01, 0x11a0a,
- 0x11a33, 0x11a38,
- 0x11a3b, 0x11a3e,
- 0x11a47, 0x11a47,
- 0x11a51, 0x11a56,
- 0x11a59, 0x11a5b,
- 0x11a8a, 0x11a96,
- 0x11a98, 0x11a99,
- 0x11c30, 0x11c36,
- 0x11c38, 0x11c3d,
- 0x11c3f, 0x11c3f,
- 0x11c92, 0x11ca7,
- 0x11caa, 0x11cb0,
- 0x11cb2, 0x11cb3,
- 0x11cb5, 0x11cb6,
- 0x11d31, 0x11d36,
- 0x11d3a, 0x11d3a,
- 0x11d3c, 0x11d3d,
- 0x11d3f, 0x11d45,
- 0x11d47, 0x11d47,
- 0x11d90, 0x11d91,
- 0x11d95, 0x11d95,
- 0x11d97, 0x11d97,
- 0x11ef3, 0x11ef4,
- 0x11f00, 0x11f01,
- 0x11f36, 0x11f3a,
- 0x11f40, 0x11f40,
- 0x11f42, 0x11f42,
- 0x13430, 0x13440,
- 0x13447, 0x13455,
- 0x16af0, 0x16af4,
- 0x16b30, 0x16b36,
- 0x16b40, 0x16b43,
- 0x16f4f, 0x16f4f,
- 0x16f8f, 0x16f9f,
- 0x16fe0, 0x16fe1,
- 0x16fe3, 0x16fe4,
- 0x1aff0, 0x1aff3,
- 0x1aff5, 0x1affb,
- 0x1affd, 0x1affe,
- 0x1bc9d, 0x1bc9e,
- 0x1bca0, 0x1bca3,
- 0x1cf00, 0x1cf2d,
- 0x1cf30, 0x1cf46,
- 0x1d167, 0x1d169,
- 0x1d173, 0x1d182,
- 0x1d185, 0x1d18b,
- 0x1d1aa, 0x1d1ad,
- 0x1d242, 0x1d244,
- 0x1da00, 0x1da36,
- 0x1da3b, 0x1da6c,
- 0x1da75, 0x1da75,
- 0x1da84, 0x1da84,
- 0x1da9b, 0x1da9f,
- 0x1daa1, 0x1daaf,
- 0x1e000, 0x1e006,
- 0x1e008, 0x1e018,
- 0x1e01b, 0x1e021,
- 0x1e023, 0x1e024,
- 0x1e026, 0x1e02a,
- 0x1e030, 0x1e06d,
- 0x1e08f, 0x1e08f,
- 0x1e130, 0x1e13d,
- 0x1e2ae, 0x1e2ae,
- 0x1e2ec, 0x1e2ef,
- 0x1e4eb, 0x1e4ef,
- 0x1e8d0, 0x1e8d6,
- 0x1e944, 0x1e94b,
- 0x1f3fb, 0x1f3ff,
- 0xe0001, 0xe0001,
- 0xe0020, 0xe007f,
- 0xe0100, 0xe01ef,
-}; /* CR_Case_Ignorable */
-
-/* 'Changes_When_Lowercased': Derived Property */
-static const OnigCodePoint CR_Changes_When_Lowercased[] = {
- 609,
- 0x0041, 0x005a,
- 0x00c0, 0x00d6,
- 0x00d8, 0x00de,
- 0x0100, 0x0100,
- 0x0102, 0x0102,
- 0x0104, 0x0104,
- 0x0106, 0x0106,
- 0x0108, 0x0108,
- 0x010a, 0x010a,
- 0x010c, 0x010c,
- 0x010e, 0x010e,
- 0x0110, 0x0110,
- 0x0112, 0x0112,
- 0x0114, 0x0114,
- 0x0116, 0x0116,
- 0x0118, 0x0118,
- 0x011a, 0x011a,
- 0x011c, 0x011c,
- 0x011e, 0x011e,
- 0x0120, 0x0120,
- 0x0122, 0x0122,
- 0x0124, 0x0124,
- 0x0126, 0x0126,
- 0x0128, 0x0128,
- 0x012a, 0x012a,
- 0x012c, 0x012c,
- 0x012e, 0x012e,
- 0x0130, 0x0130,
- 0x0132, 0x0132,
- 0x0134, 0x0134,
- 0x0136, 0x0136,
- 0x0139, 0x0139,
- 0x013b, 0x013b,
- 0x013d, 0x013d,
- 0x013f, 0x013f,
- 0x0141, 0x0141,
- 0x0143, 0x0143,
- 0x0145, 0x0145,
- 0x0147, 0x0147,
- 0x014a, 0x014a,
- 0x014c, 0x014c,
- 0x014e, 0x014e,
- 0x0150, 0x0150,
- 0x0152, 0x0152,
- 0x0154, 0x0154,
- 0x0156, 0x0156,
- 0x0158, 0x0158,
- 0x015a, 0x015a,
- 0x015c, 0x015c,
- 0x015e, 0x015e,
- 0x0160, 0x0160,
- 0x0162, 0x0162,
- 0x0164, 0x0164,
- 0x0166, 0x0166,
- 0x0168, 0x0168,
- 0x016a, 0x016a,
- 0x016c, 0x016c,
- 0x016e, 0x016e,
- 0x0170, 0x0170,
- 0x0172, 0x0172,
- 0x0174, 0x0174,
- 0x0176, 0x0176,
- 0x0178, 0x0179,
- 0x017b, 0x017b,
- 0x017d, 0x017d,
- 0x0181, 0x0182,
- 0x0184, 0x0184,
- 0x0186, 0x0187,
- 0x0189, 0x018b,
- 0x018e, 0x0191,
- 0x0193, 0x0194,
- 0x0196, 0x0198,
- 0x019c, 0x019d,
- 0x019f, 0x01a0,
- 0x01a2, 0x01a2,
- 0x01a4, 0x01a4,
- 0x01a6, 0x01a7,
- 0x01a9, 0x01a9,
- 0x01ac, 0x01ac,
- 0x01ae, 0x01af,
- 0x01b1, 0x01b3,
- 0x01b5, 0x01b5,
- 0x01b7, 0x01b8,
- 0x01bc, 0x01bc,
- 0x01c4, 0x01c5,
- 0x01c7, 0x01c8,
- 0x01ca, 0x01cb,
- 0x01cd, 0x01cd,
- 0x01cf, 0x01cf,
- 0x01d1, 0x01d1,
- 0x01d3, 0x01d3,
- 0x01d5, 0x01d5,
- 0x01d7, 0x01d7,
- 0x01d9, 0x01d9,
- 0x01db, 0x01db,
- 0x01de, 0x01de,
- 0x01e0, 0x01e0,
- 0x01e2, 0x01e2,
- 0x01e4, 0x01e4,
- 0x01e6, 0x01e6,
- 0x01e8, 0x01e8,
- 0x01ea, 0x01ea,
- 0x01ec, 0x01ec,
- 0x01ee, 0x01ee,
- 0x01f1, 0x01f2,
- 0x01f4, 0x01f4,
- 0x01f6, 0x01f8,
- 0x01fa, 0x01fa,
- 0x01fc, 0x01fc,
- 0x01fe, 0x01fe,
- 0x0200, 0x0200,
- 0x0202, 0x0202,
- 0x0204, 0x0204,
- 0x0206, 0x0206,
- 0x0208, 0x0208,
- 0x020a, 0x020a,
- 0x020c, 0x020c,
- 0x020e, 0x020e,
- 0x0210, 0x0210,
- 0x0212, 0x0212,
- 0x0214, 0x0214,
- 0x0216, 0x0216,
- 0x0218, 0x0218,
- 0x021a, 0x021a,
- 0x021c, 0x021c,
- 0x021e, 0x021e,
- 0x0220, 0x0220,
- 0x0222, 0x0222,
- 0x0224, 0x0224,
- 0x0226, 0x0226,
- 0x0228, 0x0228,
- 0x022a, 0x022a,
- 0x022c, 0x022c,
- 0x022e, 0x022e,
- 0x0230, 0x0230,
- 0x0232, 0x0232,
- 0x023a, 0x023b,
- 0x023d, 0x023e,
- 0x0241, 0x0241,
- 0x0243, 0x0246,
- 0x0248, 0x0248,
- 0x024a, 0x024a,
- 0x024c, 0x024c,
- 0x024e, 0x024e,
- 0x0370, 0x0370,
- 0x0372, 0x0372,
- 0x0376, 0x0376,
- 0x037f, 0x037f,
- 0x0386, 0x0386,
- 0x0388, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x038f,
- 0x0391, 0x03a1,
- 0x03a3, 0x03ab,
- 0x03cf, 0x03cf,
- 0x03d8, 0x03d8,
- 0x03da, 0x03da,
- 0x03dc, 0x03dc,
- 0x03de, 0x03de,
- 0x03e0, 0x03e0,
- 0x03e2, 0x03e2,
- 0x03e4, 0x03e4,
- 0x03e6, 0x03e6,
- 0x03e8, 0x03e8,
- 0x03ea, 0x03ea,
- 0x03ec, 0x03ec,
- 0x03ee, 0x03ee,
- 0x03f4, 0x03f4,
- 0x03f7, 0x03f7,
- 0x03f9, 0x03fa,
- 0x03fd, 0x042f,
- 0x0460, 0x0460,
- 0x0462, 0x0462,
- 0x0464, 0x0464,
- 0x0466, 0x0466,
- 0x0468, 0x0468,
- 0x046a, 0x046a,
- 0x046c, 0x046c,
- 0x046e, 0x046e,
- 0x0470, 0x0470,
- 0x0472, 0x0472,
- 0x0474, 0x0474,
- 0x0476, 0x0476,
- 0x0478, 0x0478,
- 0x047a, 0x047a,
- 0x047c, 0x047c,
- 0x047e, 0x047e,
- 0x0480, 0x0480,
- 0x048a, 0x048a,
- 0x048c, 0x048c,
- 0x048e, 0x048e,
- 0x0490, 0x0490,
- 0x0492, 0x0492,
- 0x0494, 0x0494,
- 0x0496, 0x0496,
- 0x0498, 0x0498,
- 0x049a, 0x049a,
- 0x049c, 0x049c,
- 0x049e, 0x049e,
- 0x04a0, 0x04a0,
- 0x04a2, 0x04a2,
- 0x04a4, 0x04a4,
- 0x04a6, 0x04a6,
- 0x04a8, 0x04a8,
- 0x04aa, 0x04aa,
- 0x04ac, 0x04ac,
- 0x04ae, 0x04ae,
- 0x04b0, 0x04b0,
- 0x04b2, 0x04b2,
- 0x04b4, 0x04b4,
- 0x04b6, 0x04b6,
- 0x04b8, 0x04b8,
- 0x04ba, 0x04ba,
- 0x04bc, 0x04bc,
- 0x04be, 0x04be,
- 0x04c0, 0x04c1,
- 0x04c3, 0x04c3,
- 0x04c5, 0x04c5,
- 0x04c7, 0x04c7,
- 0x04c9, 0x04c9,
- 0x04cb, 0x04cb,
- 0x04cd, 0x04cd,
- 0x04d0, 0x04d0,
- 0x04d2, 0x04d2,
- 0x04d4, 0x04d4,
- 0x04d6, 0x04d6,
- 0x04d8, 0x04d8,
- 0x04da, 0x04da,
- 0x04dc, 0x04dc,
- 0x04de, 0x04de,
- 0x04e0, 0x04e0,
- 0x04e2, 0x04e2,
- 0x04e4, 0x04e4,
- 0x04e6, 0x04e6,
- 0x04e8, 0x04e8,
- 0x04ea, 0x04ea,
- 0x04ec, 0x04ec,
- 0x04ee, 0x04ee,
- 0x04f0, 0x04f0,
- 0x04f2, 0x04f2,
- 0x04f4, 0x04f4,
- 0x04f6, 0x04f6,
- 0x04f8, 0x04f8,
- 0x04fa, 0x04fa,
- 0x04fc, 0x04fc,
- 0x04fe, 0x04fe,
- 0x0500, 0x0500,
- 0x0502, 0x0502,
- 0x0504, 0x0504,
- 0x0506, 0x0506,
- 0x0508, 0x0508,
- 0x050a, 0x050a,
- 0x050c, 0x050c,
- 0x050e, 0x050e,
- 0x0510, 0x0510,
- 0x0512, 0x0512,
- 0x0514, 0x0514,
- 0x0516, 0x0516,
- 0x0518, 0x0518,
- 0x051a, 0x051a,
- 0x051c, 0x051c,
- 0x051e, 0x051e,
- 0x0520, 0x0520,
- 0x0522, 0x0522,
- 0x0524, 0x0524,
- 0x0526, 0x0526,
- 0x0528, 0x0528,
- 0x052a, 0x052a,
- 0x052c, 0x052c,
- 0x052e, 0x052e,
- 0x0531, 0x0556,
- 0x10a0, 0x10c5,
- 0x10c7, 0x10c7,
- 0x10cd, 0x10cd,
- 0x13a0, 0x13f5,
- 0x1c90, 0x1cba,
- 0x1cbd, 0x1cbf,
- 0x1e00, 0x1e00,
- 0x1e02, 0x1e02,
- 0x1e04, 0x1e04,
- 0x1e06, 0x1e06,
- 0x1e08, 0x1e08,
- 0x1e0a, 0x1e0a,
- 0x1e0c, 0x1e0c,
- 0x1e0e, 0x1e0e,
- 0x1e10, 0x1e10,
- 0x1e12, 0x1e12,
- 0x1e14, 0x1e14,
- 0x1e16, 0x1e16,
- 0x1e18, 0x1e18,
- 0x1e1a, 0x1e1a,
- 0x1e1c, 0x1e1c,
- 0x1e1e, 0x1e1e,
- 0x1e20, 0x1e20,
- 0x1e22, 0x1e22,
- 0x1e24, 0x1e24,
- 0x1e26, 0x1e26,
- 0x1e28, 0x1e28,
- 0x1e2a, 0x1e2a,
- 0x1e2c, 0x1e2c,
- 0x1e2e, 0x1e2e,
- 0x1e30, 0x1e30,
- 0x1e32, 0x1e32,
- 0x1e34, 0x1e34,
- 0x1e36, 0x1e36,
- 0x1e38, 0x1e38,
- 0x1e3a, 0x1e3a,
- 0x1e3c, 0x1e3c,
- 0x1e3e, 0x1e3e,
- 0x1e40, 0x1e40,
- 0x1e42, 0x1e42,
- 0x1e44, 0x1e44,
- 0x1e46, 0x1e46,
- 0x1e48, 0x1e48,
- 0x1e4a, 0x1e4a,
- 0x1e4c, 0x1e4c,
- 0x1e4e, 0x1e4e,
- 0x1e50, 0x1e50,
- 0x1e52, 0x1e52,
- 0x1e54, 0x1e54,
- 0x1e56, 0x1e56,
- 0x1e58, 0x1e58,
- 0x1e5a, 0x1e5a,
- 0x1e5c, 0x1e5c,
- 0x1e5e, 0x1e5e,
- 0x1e60, 0x1e60,
- 0x1e62, 0x1e62,
- 0x1e64, 0x1e64,
- 0x1e66, 0x1e66,
- 0x1e68, 0x1e68,
- 0x1e6a, 0x1e6a,
- 0x1e6c, 0x1e6c,
- 0x1e6e, 0x1e6e,
- 0x1e70, 0x1e70,
- 0x1e72, 0x1e72,
- 0x1e74, 0x1e74,
- 0x1e76, 0x1e76,
- 0x1e78, 0x1e78,
- 0x1e7a, 0x1e7a,
- 0x1e7c, 0x1e7c,
- 0x1e7e, 0x1e7e,
- 0x1e80, 0x1e80,
- 0x1e82, 0x1e82,
- 0x1e84, 0x1e84,
- 0x1e86, 0x1e86,
- 0x1e88, 0x1e88,
- 0x1e8a, 0x1e8a,
- 0x1e8c, 0x1e8c,
- 0x1e8e, 0x1e8e,
- 0x1e90, 0x1e90,
- 0x1e92, 0x1e92,
- 0x1e94, 0x1e94,
- 0x1e9e, 0x1e9e,
- 0x1ea0, 0x1ea0,
- 0x1ea2, 0x1ea2,
- 0x1ea4, 0x1ea4,
- 0x1ea6, 0x1ea6,
- 0x1ea8, 0x1ea8,
- 0x1eaa, 0x1eaa,
- 0x1eac, 0x1eac,
- 0x1eae, 0x1eae,
- 0x1eb0, 0x1eb0,
- 0x1eb2, 0x1eb2,
- 0x1eb4, 0x1eb4,
- 0x1eb6, 0x1eb6,
- 0x1eb8, 0x1eb8,
- 0x1eba, 0x1eba,
- 0x1ebc, 0x1ebc,
- 0x1ebe, 0x1ebe,
- 0x1ec0, 0x1ec0,
- 0x1ec2, 0x1ec2,
- 0x1ec4, 0x1ec4,
- 0x1ec6, 0x1ec6,
- 0x1ec8, 0x1ec8,
- 0x1eca, 0x1eca,
- 0x1ecc, 0x1ecc,
- 0x1ece, 0x1ece,
- 0x1ed0, 0x1ed0,
- 0x1ed2, 0x1ed2,
- 0x1ed4, 0x1ed4,
- 0x1ed6, 0x1ed6,
- 0x1ed8, 0x1ed8,
- 0x1eda, 0x1eda,
- 0x1edc, 0x1edc,
- 0x1ede, 0x1ede,
- 0x1ee0, 0x1ee0,
- 0x1ee2, 0x1ee2,
- 0x1ee4, 0x1ee4,
- 0x1ee6, 0x1ee6,
- 0x1ee8, 0x1ee8,
- 0x1eea, 0x1eea,
- 0x1eec, 0x1eec,
- 0x1eee, 0x1eee,
- 0x1ef0, 0x1ef0,
- 0x1ef2, 0x1ef2,
- 0x1ef4, 0x1ef4,
- 0x1ef6, 0x1ef6,
- 0x1ef8, 0x1ef8,
- 0x1efa, 0x1efa,
- 0x1efc, 0x1efc,
- 0x1efe, 0x1efe,
- 0x1f08, 0x1f0f,
- 0x1f18, 0x1f1d,
- 0x1f28, 0x1f2f,
- 0x1f38, 0x1f3f,
- 0x1f48, 0x1f4d,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f5f,
- 0x1f68, 0x1f6f,
- 0x1f88, 0x1f8f,
- 0x1f98, 0x1f9f,
- 0x1fa8, 0x1faf,
- 0x1fb8, 0x1fbc,
- 0x1fc8, 0x1fcc,
- 0x1fd8, 0x1fdb,
- 0x1fe8, 0x1fec,
- 0x1ff8, 0x1ffc,
- 0x2126, 0x2126,
- 0x212a, 0x212b,
- 0x2132, 0x2132,
- 0x2160, 0x216f,
- 0x2183, 0x2183,
- 0x24b6, 0x24cf,
- 0x2c00, 0x2c2f,
- 0x2c60, 0x2c60,
- 0x2c62, 0x2c64,
- 0x2c67, 0x2c67,
- 0x2c69, 0x2c69,
- 0x2c6b, 0x2c6b,
- 0x2c6d, 0x2c70,
- 0x2c72, 0x2c72,
- 0x2c75, 0x2c75,
- 0x2c7e, 0x2c80,
- 0x2c82, 0x2c82,
- 0x2c84, 0x2c84,
- 0x2c86, 0x2c86,
- 0x2c88, 0x2c88,
- 0x2c8a, 0x2c8a,
- 0x2c8c, 0x2c8c,
- 0x2c8e, 0x2c8e,
- 0x2c90, 0x2c90,
- 0x2c92, 0x2c92,
- 0x2c94, 0x2c94,
- 0x2c96, 0x2c96,
- 0x2c98, 0x2c98,
- 0x2c9a, 0x2c9a,
- 0x2c9c, 0x2c9c,
- 0x2c9e, 0x2c9e,
- 0x2ca0, 0x2ca0,
- 0x2ca2, 0x2ca2,
- 0x2ca4, 0x2ca4,
- 0x2ca6, 0x2ca6,
- 0x2ca8, 0x2ca8,
- 0x2caa, 0x2caa,
- 0x2cac, 0x2cac,
- 0x2cae, 0x2cae,
- 0x2cb0, 0x2cb0,
- 0x2cb2, 0x2cb2,
- 0x2cb4, 0x2cb4,
- 0x2cb6, 0x2cb6,
- 0x2cb8, 0x2cb8,
- 0x2cba, 0x2cba,
- 0x2cbc, 0x2cbc,
- 0x2cbe, 0x2cbe,
- 0x2cc0, 0x2cc0,
- 0x2cc2, 0x2cc2,
- 0x2cc4, 0x2cc4,
- 0x2cc6, 0x2cc6,
- 0x2cc8, 0x2cc8,
- 0x2cca, 0x2cca,
- 0x2ccc, 0x2ccc,
- 0x2cce, 0x2cce,
- 0x2cd0, 0x2cd0,
- 0x2cd2, 0x2cd2,
- 0x2cd4, 0x2cd4,
- 0x2cd6, 0x2cd6,
- 0x2cd8, 0x2cd8,
- 0x2cda, 0x2cda,
- 0x2cdc, 0x2cdc,
- 0x2cde, 0x2cde,
- 0x2ce0, 0x2ce0,
- 0x2ce2, 0x2ce2,
- 0x2ceb, 0x2ceb,
- 0x2ced, 0x2ced,
- 0x2cf2, 0x2cf2,
- 0xa640, 0xa640,
- 0xa642, 0xa642,
- 0xa644, 0xa644,
- 0xa646, 0xa646,
- 0xa648, 0xa648,
- 0xa64a, 0xa64a,
- 0xa64c, 0xa64c,
- 0xa64e, 0xa64e,
- 0xa650, 0xa650,
- 0xa652, 0xa652,
- 0xa654, 0xa654,
- 0xa656, 0xa656,
- 0xa658, 0xa658,
- 0xa65a, 0xa65a,
- 0xa65c, 0xa65c,
- 0xa65e, 0xa65e,
- 0xa660, 0xa660,
- 0xa662, 0xa662,
- 0xa664, 0xa664,
- 0xa666, 0xa666,
- 0xa668, 0xa668,
- 0xa66a, 0xa66a,
- 0xa66c, 0xa66c,
- 0xa680, 0xa680,
- 0xa682, 0xa682,
- 0xa684, 0xa684,
- 0xa686, 0xa686,
- 0xa688, 0xa688,
- 0xa68a, 0xa68a,
- 0xa68c, 0xa68c,
- 0xa68e, 0xa68e,
- 0xa690, 0xa690,
- 0xa692, 0xa692,
- 0xa694, 0xa694,
- 0xa696, 0xa696,
- 0xa698, 0xa698,
- 0xa69a, 0xa69a,
- 0xa722, 0xa722,
- 0xa724, 0xa724,
- 0xa726, 0xa726,
- 0xa728, 0xa728,
- 0xa72a, 0xa72a,
- 0xa72c, 0xa72c,
- 0xa72e, 0xa72e,
- 0xa732, 0xa732,
- 0xa734, 0xa734,
- 0xa736, 0xa736,
- 0xa738, 0xa738,
- 0xa73a, 0xa73a,
- 0xa73c, 0xa73c,
- 0xa73e, 0xa73e,
- 0xa740, 0xa740,
- 0xa742, 0xa742,
- 0xa744, 0xa744,
- 0xa746, 0xa746,
- 0xa748, 0xa748,
- 0xa74a, 0xa74a,
- 0xa74c, 0xa74c,
- 0xa74e, 0xa74e,
- 0xa750, 0xa750,
- 0xa752, 0xa752,
- 0xa754, 0xa754,
- 0xa756, 0xa756,
- 0xa758, 0xa758,
- 0xa75a, 0xa75a,
- 0xa75c, 0xa75c,
- 0xa75e, 0xa75e,
- 0xa760, 0xa760,
- 0xa762, 0xa762,
- 0xa764, 0xa764,
- 0xa766, 0xa766,
- 0xa768, 0xa768,
- 0xa76a, 0xa76a,
- 0xa76c, 0xa76c,
- 0xa76e, 0xa76e,
- 0xa779, 0xa779,
- 0xa77b, 0xa77b,
- 0xa77d, 0xa77e,
- 0xa780, 0xa780,
- 0xa782, 0xa782,
- 0xa784, 0xa784,
- 0xa786, 0xa786,
- 0xa78b, 0xa78b,
- 0xa78d, 0xa78d,
- 0xa790, 0xa790,
- 0xa792, 0xa792,
- 0xa796, 0xa796,
- 0xa798, 0xa798,
- 0xa79a, 0xa79a,
- 0xa79c, 0xa79c,
- 0xa79e, 0xa79e,
- 0xa7a0, 0xa7a0,
- 0xa7a2, 0xa7a2,
- 0xa7a4, 0xa7a4,
- 0xa7a6, 0xa7a6,
- 0xa7a8, 0xa7a8,
- 0xa7aa, 0xa7ae,
- 0xa7b0, 0xa7b4,
- 0xa7b6, 0xa7b6,
- 0xa7b8, 0xa7b8,
- 0xa7ba, 0xa7ba,
- 0xa7bc, 0xa7bc,
- 0xa7be, 0xa7be,
- 0xa7c0, 0xa7c0,
- 0xa7c2, 0xa7c2,
- 0xa7c4, 0xa7c7,
- 0xa7c9, 0xa7c9,
- 0xa7d0, 0xa7d0,
- 0xa7d6, 0xa7d6,
- 0xa7d8, 0xa7d8,
- 0xa7f5, 0xa7f5,
- 0xff21, 0xff3a,
- 0x10400, 0x10427,
- 0x104b0, 0x104d3,
- 0x10570, 0x1057a,
- 0x1057c, 0x1058a,
- 0x1058c, 0x10592,
- 0x10594, 0x10595,
- 0x10c80, 0x10cb2,
- 0x118a0, 0x118bf,
- 0x16e40, 0x16e5f,
- 0x1e900, 0x1e921,
-}; /* CR_Changes_When_Lowercased */
-
-/* 'Changes_When_Uppercased': Derived Property */
-static const OnigCodePoint CR_Changes_When_Uppercased[] = {
- 627,
- 0x0061, 0x007a,
- 0x00b5, 0x00b5,
- 0x00df, 0x00f6,
- 0x00f8, 0x00ff,
- 0x0101, 0x0101,
- 0x0103, 0x0103,
- 0x0105, 0x0105,
- 0x0107, 0x0107,
- 0x0109, 0x0109,
- 0x010b, 0x010b,
- 0x010d, 0x010d,
- 0x010f, 0x010f,
- 0x0111, 0x0111,
- 0x0113, 0x0113,
- 0x0115, 0x0115,
- 0x0117, 0x0117,
- 0x0119, 0x0119,
- 0x011b, 0x011b,
- 0x011d, 0x011d,
- 0x011f, 0x011f,
- 0x0121, 0x0121,
- 0x0123, 0x0123,
- 0x0125, 0x0125,
- 0x0127, 0x0127,
- 0x0129, 0x0129,
- 0x012b, 0x012b,
- 0x012d, 0x012d,
- 0x012f, 0x012f,
- 0x0131, 0x0131,
- 0x0133, 0x0133,
- 0x0135, 0x0135,
- 0x0137, 0x0137,
- 0x013a, 0x013a,
- 0x013c, 0x013c,
- 0x013e, 0x013e,
- 0x0140, 0x0140,
- 0x0142, 0x0142,
- 0x0144, 0x0144,
- 0x0146, 0x0146,
- 0x0148, 0x0149,
- 0x014b, 0x014b,
- 0x014d, 0x014d,
- 0x014f, 0x014f,
- 0x0151, 0x0151,
- 0x0153, 0x0153,
- 0x0155, 0x0155,
- 0x0157, 0x0157,
- 0x0159, 0x0159,
- 0x015b, 0x015b,
- 0x015d, 0x015d,
- 0x015f, 0x015f,
- 0x0161, 0x0161,
- 0x0163, 0x0163,
- 0x0165, 0x0165,
- 0x0167, 0x0167,
- 0x0169, 0x0169,
- 0x016b, 0x016b,
- 0x016d, 0x016d,
- 0x016f, 0x016f,
- 0x0171, 0x0171,
- 0x0173, 0x0173,
- 0x0175, 0x0175,
- 0x0177, 0x0177,
- 0x017a, 0x017a,
- 0x017c, 0x017c,
- 0x017e, 0x0180,
- 0x0183, 0x0183,
- 0x0185, 0x0185,
- 0x0188, 0x0188,
- 0x018c, 0x018c,
- 0x0192, 0x0192,
- 0x0195, 0x0195,
- 0x0199, 0x019a,
- 0x019e, 0x019e,
- 0x01a1, 0x01a1,
- 0x01a3, 0x01a3,
- 0x01a5, 0x01a5,
- 0x01a8, 0x01a8,
- 0x01ad, 0x01ad,
- 0x01b0, 0x01b0,
- 0x01b4, 0x01b4,
- 0x01b6, 0x01b6,
- 0x01b9, 0x01b9,
- 0x01bd, 0x01bd,
- 0x01bf, 0x01bf,
- 0x01c5, 0x01c6,
- 0x01c8, 0x01c9,
- 0x01cb, 0x01cc,
- 0x01ce, 0x01ce,
- 0x01d0, 0x01d0,
- 0x01d2, 0x01d2,
- 0x01d4, 0x01d4,
- 0x01d6, 0x01d6,
- 0x01d8, 0x01d8,
- 0x01da, 0x01da,
- 0x01dc, 0x01dd,
- 0x01df, 0x01df,
- 0x01e1, 0x01e1,
- 0x01e3, 0x01e3,
- 0x01e5, 0x01e5,
- 0x01e7, 0x01e7,
- 0x01e9, 0x01e9,
- 0x01eb, 0x01eb,
- 0x01ed, 0x01ed,
- 0x01ef, 0x01f0,
- 0x01f2, 0x01f3,
- 0x01f5, 0x01f5,
- 0x01f9, 0x01f9,
- 0x01fb, 0x01fb,
- 0x01fd, 0x01fd,
- 0x01ff, 0x01ff,
- 0x0201, 0x0201,
- 0x0203, 0x0203,
- 0x0205, 0x0205,
- 0x0207, 0x0207,
- 0x0209, 0x0209,
- 0x020b, 0x020b,
- 0x020d, 0x020d,
- 0x020f, 0x020f,
- 0x0211, 0x0211,
- 0x0213, 0x0213,
- 0x0215, 0x0215,
- 0x0217, 0x0217,
- 0x0219, 0x0219,
- 0x021b, 0x021b,
- 0x021d, 0x021d,
- 0x021f, 0x021f,
- 0x0223, 0x0223,
- 0x0225, 0x0225,
- 0x0227, 0x0227,
- 0x0229, 0x0229,
- 0x022b, 0x022b,
- 0x022d, 0x022d,
- 0x022f, 0x022f,
- 0x0231, 0x0231,
- 0x0233, 0x0233,
- 0x023c, 0x023c,
- 0x023f, 0x0240,
- 0x0242, 0x0242,
- 0x0247, 0x0247,
- 0x0249, 0x0249,
- 0x024b, 0x024b,
- 0x024d, 0x024d,
- 0x024f, 0x0254,
- 0x0256, 0x0257,
- 0x0259, 0x0259,
- 0x025b, 0x025c,
- 0x0260, 0x0261,
- 0x0263, 0x0263,
- 0x0265, 0x0266,
- 0x0268, 0x026c,
- 0x026f, 0x026f,
- 0x0271, 0x0272,
- 0x0275, 0x0275,
- 0x027d, 0x027d,
- 0x0280, 0x0280,
- 0x0282, 0x0283,
- 0x0287, 0x028c,
- 0x0292, 0x0292,
- 0x029d, 0x029e,
- 0x0345, 0x0345,
- 0x0371, 0x0371,
- 0x0373, 0x0373,
- 0x0377, 0x0377,
- 0x037b, 0x037d,
- 0x0390, 0x0390,
- 0x03ac, 0x03ce,
- 0x03d0, 0x03d1,
- 0x03d5, 0x03d7,
- 0x03d9, 0x03d9,
- 0x03db, 0x03db,
- 0x03dd, 0x03dd,
- 0x03df, 0x03df,
- 0x03e1, 0x03e1,
- 0x03e3, 0x03e3,
- 0x03e5, 0x03e5,
- 0x03e7, 0x03e7,
- 0x03e9, 0x03e9,
- 0x03eb, 0x03eb,
- 0x03ed, 0x03ed,
- 0x03ef, 0x03f3,
- 0x03f5, 0x03f5,
- 0x03f8, 0x03f8,
- 0x03fb, 0x03fb,
- 0x0430, 0x045f,
- 0x0461, 0x0461,
- 0x0463, 0x0463,
- 0x0465, 0x0465,
- 0x0467, 0x0467,
- 0x0469, 0x0469,
- 0x046b, 0x046b,
- 0x046d, 0x046d,
- 0x046f, 0x046f,
- 0x0471, 0x0471,
- 0x0473, 0x0473,
- 0x0475, 0x0475,
- 0x0477, 0x0477,
- 0x0479, 0x0479,
- 0x047b, 0x047b,
- 0x047d, 0x047d,
- 0x047f, 0x047f,
- 0x0481, 0x0481,
- 0x048b, 0x048b,
- 0x048d, 0x048d,
- 0x048f, 0x048f,
- 0x0491, 0x0491,
- 0x0493, 0x0493,
- 0x0495, 0x0495,
- 0x0497, 0x0497,
- 0x0499, 0x0499,
- 0x049b, 0x049b,
- 0x049d, 0x049d,
- 0x049f, 0x049f,
- 0x04a1, 0x04a1,
- 0x04a3, 0x04a3,
- 0x04a5, 0x04a5,
- 0x04a7, 0x04a7,
- 0x04a9, 0x04a9,
- 0x04ab, 0x04ab,
- 0x04ad, 0x04ad,
- 0x04af, 0x04af,
- 0x04b1, 0x04b1,
- 0x04b3, 0x04b3,
- 0x04b5, 0x04b5,
- 0x04b7, 0x04b7,
- 0x04b9, 0x04b9,
- 0x04bb, 0x04bb,
- 0x04bd, 0x04bd,
- 0x04bf, 0x04bf,
- 0x04c2, 0x04c2,
- 0x04c4, 0x04c4,
- 0x04c6, 0x04c6,
- 0x04c8, 0x04c8,
- 0x04ca, 0x04ca,
- 0x04cc, 0x04cc,
- 0x04ce, 0x04cf,
- 0x04d1, 0x04d1,
- 0x04d3, 0x04d3,
- 0x04d5, 0x04d5,
- 0x04d7, 0x04d7,
- 0x04d9, 0x04d9,
- 0x04db, 0x04db,
- 0x04dd, 0x04dd,
- 0x04df, 0x04df,
- 0x04e1, 0x04e1,
- 0x04e3, 0x04e3,
- 0x04e5, 0x04e5,
- 0x04e7, 0x04e7,
- 0x04e9, 0x04e9,
- 0x04eb, 0x04eb,
- 0x04ed, 0x04ed,
- 0x04ef, 0x04ef,
- 0x04f1, 0x04f1,
- 0x04f3, 0x04f3,
- 0x04f5, 0x04f5,
- 0x04f7, 0x04f7,
- 0x04f9, 0x04f9,
- 0x04fb, 0x04fb,
- 0x04fd, 0x04fd,
- 0x04ff, 0x04ff,
- 0x0501, 0x0501,
- 0x0503, 0x0503,
- 0x0505, 0x0505,
- 0x0507, 0x0507,
- 0x0509, 0x0509,
- 0x050b, 0x050b,
- 0x050d, 0x050d,
- 0x050f, 0x050f,
- 0x0511, 0x0511,
- 0x0513, 0x0513,
- 0x0515, 0x0515,
- 0x0517, 0x0517,
- 0x0519, 0x0519,
- 0x051b, 0x051b,
- 0x051d, 0x051d,
- 0x051f, 0x051f,
- 0x0521, 0x0521,
- 0x0523, 0x0523,
- 0x0525, 0x0525,
- 0x0527, 0x0527,
- 0x0529, 0x0529,
- 0x052b, 0x052b,
- 0x052d, 0x052d,
- 0x052f, 0x052f,
- 0x0561, 0x0587,
- 0x10d0, 0x10fa,
- 0x10fd, 0x10ff,
- 0x13f8, 0x13fd,
- 0x1c80, 0x1c88,
- 0x1d79, 0x1d79,
- 0x1d7d, 0x1d7d,
- 0x1d8e, 0x1d8e,
- 0x1e01, 0x1e01,
- 0x1e03, 0x1e03,
- 0x1e05, 0x1e05,
- 0x1e07, 0x1e07,
- 0x1e09, 0x1e09,
- 0x1e0b, 0x1e0b,
- 0x1e0d, 0x1e0d,
- 0x1e0f, 0x1e0f,
- 0x1e11, 0x1e11,
- 0x1e13, 0x1e13,
- 0x1e15, 0x1e15,
- 0x1e17, 0x1e17,
- 0x1e19, 0x1e19,
- 0x1e1b, 0x1e1b,
- 0x1e1d, 0x1e1d,
- 0x1e1f, 0x1e1f,
- 0x1e21, 0x1e21,
- 0x1e23, 0x1e23,
- 0x1e25, 0x1e25,
- 0x1e27, 0x1e27,
- 0x1e29, 0x1e29,
- 0x1e2b, 0x1e2b,
- 0x1e2d, 0x1e2d,
- 0x1e2f, 0x1e2f,
- 0x1e31, 0x1e31,
- 0x1e33, 0x1e33,
- 0x1e35, 0x1e35,
- 0x1e37, 0x1e37,
- 0x1e39, 0x1e39,
- 0x1e3b, 0x1e3b,
- 0x1e3d, 0x1e3d,
- 0x1e3f, 0x1e3f,
- 0x1e41, 0x1e41,
- 0x1e43, 0x1e43,
- 0x1e45, 0x1e45,
- 0x1e47, 0x1e47,
- 0x1e49, 0x1e49,
- 0x1e4b, 0x1e4b,
- 0x1e4d, 0x1e4d,
- 0x1e4f, 0x1e4f,
- 0x1e51, 0x1e51,
- 0x1e53, 0x1e53,
- 0x1e55, 0x1e55,
- 0x1e57, 0x1e57,
- 0x1e59, 0x1e59,
- 0x1e5b, 0x1e5b,
- 0x1e5d, 0x1e5d,
- 0x1e5f, 0x1e5f,
- 0x1e61, 0x1e61,
- 0x1e63, 0x1e63,
- 0x1e65, 0x1e65,
- 0x1e67, 0x1e67,
- 0x1e69, 0x1e69,
- 0x1e6b, 0x1e6b,
- 0x1e6d, 0x1e6d,
- 0x1e6f, 0x1e6f,
- 0x1e71, 0x1e71,
- 0x1e73, 0x1e73,
- 0x1e75, 0x1e75,
- 0x1e77, 0x1e77,
- 0x1e79, 0x1e79,
- 0x1e7b, 0x1e7b,
- 0x1e7d, 0x1e7d,
- 0x1e7f, 0x1e7f,
- 0x1e81, 0x1e81,
- 0x1e83, 0x1e83,
- 0x1e85, 0x1e85,
- 0x1e87, 0x1e87,
- 0x1e89, 0x1e89,
- 0x1e8b, 0x1e8b,
- 0x1e8d, 0x1e8d,
- 0x1e8f, 0x1e8f,
- 0x1e91, 0x1e91,
- 0x1e93, 0x1e93,
- 0x1e95, 0x1e9b,
- 0x1ea1, 0x1ea1,
- 0x1ea3, 0x1ea3,
- 0x1ea5, 0x1ea5,
- 0x1ea7, 0x1ea7,
- 0x1ea9, 0x1ea9,
- 0x1eab, 0x1eab,
- 0x1ead, 0x1ead,
- 0x1eaf, 0x1eaf,
- 0x1eb1, 0x1eb1,
- 0x1eb3, 0x1eb3,
- 0x1eb5, 0x1eb5,
- 0x1eb7, 0x1eb7,
- 0x1eb9, 0x1eb9,
- 0x1ebb, 0x1ebb,
- 0x1ebd, 0x1ebd,
- 0x1ebf, 0x1ebf,
- 0x1ec1, 0x1ec1,
- 0x1ec3, 0x1ec3,
- 0x1ec5, 0x1ec5,
- 0x1ec7, 0x1ec7,
- 0x1ec9, 0x1ec9,
- 0x1ecb, 0x1ecb,
- 0x1ecd, 0x1ecd,
- 0x1ecf, 0x1ecf,
- 0x1ed1, 0x1ed1,
- 0x1ed3, 0x1ed3,
- 0x1ed5, 0x1ed5,
- 0x1ed7, 0x1ed7,
- 0x1ed9, 0x1ed9,
- 0x1edb, 0x1edb,
- 0x1edd, 0x1edd,
- 0x1edf, 0x1edf,
- 0x1ee1, 0x1ee1,
- 0x1ee3, 0x1ee3,
- 0x1ee5, 0x1ee5,
- 0x1ee7, 0x1ee7,
- 0x1ee9, 0x1ee9,
- 0x1eeb, 0x1eeb,
- 0x1eed, 0x1eed,
- 0x1eef, 0x1eef,
- 0x1ef1, 0x1ef1,
- 0x1ef3, 0x1ef3,
- 0x1ef5, 0x1ef5,
- 0x1ef7, 0x1ef7,
- 0x1ef9, 0x1ef9,
- 0x1efb, 0x1efb,
- 0x1efd, 0x1efd,
- 0x1eff, 0x1f07,
- 0x1f10, 0x1f15,
- 0x1f20, 0x1f27,
- 0x1f30, 0x1f37,
- 0x1f40, 0x1f45,
- 0x1f50, 0x1f57,
- 0x1f60, 0x1f67,
- 0x1f70, 0x1f7d,
- 0x1f80, 0x1fb4,
- 0x1fb6, 0x1fb7,
- 0x1fbc, 0x1fbc,
- 0x1fbe, 0x1fbe,
- 0x1fc2, 0x1fc4,
- 0x1fc6, 0x1fc7,
- 0x1fcc, 0x1fcc,
- 0x1fd0, 0x1fd3,
- 0x1fd6, 0x1fd7,
- 0x1fe0, 0x1fe7,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ff7,
- 0x1ffc, 0x1ffc,
- 0x214e, 0x214e,
- 0x2170, 0x217f,
- 0x2184, 0x2184,
- 0x24d0, 0x24e9,
- 0x2c30, 0x2c5f,
- 0x2c61, 0x2c61,
- 0x2c65, 0x2c66,
- 0x2c68, 0x2c68,
- 0x2c6a, 0x2c6a,
- 0x2c6c, 0x2c6c,
- 0x2c73, 0x2c73,
- 0x2c76, 0x2c76,
- 0x2c81, 0x2c81,
- 0x2c83, 0x2c83,
- 0x2c85, 0x2c85,
- 0x2c87, 0x2c87,
- 0x2c89, 0x2c89,
- 0x2c8b, 0x2c8b,
- 0x2c8d, 0x2c8d,
- 0x2c8f, 0x2c8f,
- 0x2c91, 0x2c91,
- 0x2c93, 0x2c93,
- 0x2c95, 0x2c95,
- 0x2c97, 0x2c97,
- 0x2c99, 0x2c99,
- 0x2c9b, 0x2c9b,
- 0x2c9d, 0x2c9d,
- 0x2c9f, 0x2c9f,
- 0x2ca1, 0x2ca1,
- 0x2ca3, 0x2ca3,
- 0x2ca5, 0x2ca5,
- 0x2ca7, 0x2ca7,
- 0x2ca9, 0x2ca9,
- 0x2cab, 0x2cab,
- 0x2cad, 0x2cad,
- 0x2caf, 0x2caf,
- 0x2cb1, 0x2cb1,
- 0x2cb3, 0x2cb3,
- 0x2cb5, 0x2cb5,
- 0x2cb7, 0x2cb7,
- 0x2cb9, 0x2cb9,
- 0x2cbb, 0x2cbb,
- 0x2cbd, 0x2cbd,
- 0x2cbf, 0x2cbf,
- 0x2cc1, 0x2cc1,
- 0x2cc3, 0x2cc3,
- 0x2cc5, 0x2cc5,
- 0x2cc7, 0x2cc7,
- 0x2cc9, 0x2cc9,
- 0x2ccb, 0x2ccb,
- 0x2ccd, 0x2ccd,
- 0x2ccf, 0x2ccf,
- 0x2cd1, 0x2cd1,
- 0x2cd3, 0x2cd3,
- 0x2cd5, 0x2cd5,
- 0x2cd7, 0x2cd7,
- 0x2cd9, 0x2cd9,
- 0x2cdb, 0x2cdb,
- 0x2cdd, 0x2cdd,
- 0x2cdf, 0x2cdf,
- 0x2ce1, 0x2ce1,
- 0x2ce3, 0x2ce3,
- 0x2cec, 0x2cec,
- 0x2cee, 0x2cee,
- 0x2cf3, 0x2cf3,
- 0x2d00, 0x2d25,
- 0x2d27, 0x2d27,
- 0x2d2d, 0x2d2d,
- 0xa641, 0xa641,
- 0xa643, 0xa643,
- 0xa645, 0xa645,
- 0xa647, 0xa647,
- 0xa649, 0xa649,
- 0xa64b, 0xa64b,
- 0xa64d, 0xa64d,
- 0xa64f, 0xa64f,
- 0xa651, 0xa651,
- 0xa653, 0xa653,
- 0xa655, 0xa655,
- 0xa657, 0xa657,
- 0xa659, 0xa659,
- 0xa65b, 0xa65b,
- 0xa65d, 0xa65d,
- 0xa65f, 0xa65f,
- 0xa661, 0xa661,
- 0xa663, 0xa663,
- 0xa665, 0xa665,
- 0xa667, 0xa667,
- 0xa669, 0xa669,
- 0xa66b, 0xa66b,
- 0xa66d, 0xa66d,
- 0xa681, 0xa681,
- 0xa683, 0xa683,
- 0xa685, 0xa685,
- 0xa687, 0xa687,
- 0xa689, 0xa689,
- 0xa68b, 0xa68b,
- 0xa68d, 0xa68d,
- 0xa68f, 0xa68f,
- 0xa691, 0xa691,
- 0xa693, 0xa693,
- 0xa695, 0xa695,
- 0xa697, 0xa697,
- 0xa699, 0xa699,
- 0xa69b, 0xa69b,
- 0xa723, 0xa723,
- 0xa725, 0xa725,
- 0xa727, 0xa727,
- 0xa729, 0xa729,
- 0xa72b, 0xa72b,
- 0xa72d, 0xa72d,
- 0xa72f, 0xa72f,
- 0xa733, 0xa733,
- 0xa735, 0xa735,
- 0xa737, 0xa737,
- 0xa739, 0xa739,
- 0xa73b, 0xa73b,
- 0xa73d, 0xa73d,
- 0xa73f, 0xa73f,
- 0xa741, 0xa741,
- 0xa743, 0xa743,
- 0xa745, 0xa745,
- 0xa747, 0xa747,
- 0xa749, 0xa749,
- 0xa74b, 0xa74b,
- 0xa74d, 0xa74d,
- 0xa74f, 0xa74f,
- 0xa751, 0xa751,
- 0xa753, 0xa753,
- 0xa755, 0xa755,
- 0xa757, 0xa757,
- 0xa759, 0xa759,
- 0xa75b, 0xa75b,
- 0xa75d, 0xa75d,
- 0xa75f, 0xa75f,
- 0xa761, 0xa761,
- 0xa763, 0xa763,
- 0xa765, 0xa765,
- 0xa767, 0xa767,
- 0xa769, 0xa769,
- 0xa76b, 0xa76b,
- 0xa76d, 0xa76d,
- 0xa76f, 0xa76f,
- 0xa77a, 0xa77a,
- 0xa77c, 0xa77c,
- 0xa77f, 0xa77f,
- 0xa781, 0xa781,
- 0xa783, 0xa783,
- 0xa785, 0xa785,
- 0xa787, 0xa787,
- 0xa78c, 0xa78c,
- 0xa791, 0xa791,
- 0xa793, 0xa794,
- 0xa797, 0xa797,
- 0xa799, 0xa799,
- 0xa79b, 0xa79b,
- 0xa79d, 0xa79d,
- 0xa79f, 0xa79f,
- 0xa7a1, 0xa7a1,
- 0xa7a3, 0xa7a3,
- 0xa7a5, 0xa7a5,
- 0xa7a7, 0xa7a7,
- 0xa7a9, 0xa7a9,
- 0xa7b5, 0xa7b5,
- 0xa7b7, 0xa7b7,
- 0xa7b9, 0xa7b9,
- 0xa7bb, 0xa7bb,
- 0xa7bd, 0xa7bd,
- 0xa7bf, 0xa7bf,
- 0xa7c1, 0xa7c1,
- 0xa7c3, 0xa7c3,
- 0xa7c8, 0xa7c8,
- 0xa7ca, 0xa7ca,
- 0xa7d1, 0xa7d1,
- 0xa7d7, 0xa7d7,
- 0xa7d9, 0xa7d9,
- 0xa7f6, 0xa7f6,
- 0xab53, 0xab53,
- 0xab70, 0xabbf,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xff41, 0xff5a,
- 0x10428, 0x1044f,
- 0x104d8, 0x104fb,
- 0x10597, 0x105a1,
- 0x105a3, 0x105b1,
- 0x105b3, 0x105b9,
- 0x105bb, 0x105bc,
- 0x10cc0, 0x10cf2,
- 0x118c0, 0x118df,
- 0x16e60, 0x16e7f,
- 0x1e922, 0x1e943,
-}; /* CR_Changes_When_Uppercased */
-
-/* 'Changes_When_Titlecased': Derived Property */
-static const OnigCodePoint CR_Changes_When_Titlecased[] = {
- 626,
- 0x0061, 0x007a,
- 0x00b5, 0x00b5,
- 0x00df, 0x00f6,
- 0x00f8, 0x00ff,
- 0x0101, 0x0101,
- 0x0103, 0x0103,
- 0x0105, 0x0105,
- 0x0107, 0x0107,
- 0x0109, 0x0109,
- 0x010b, 0x010b,
- 0x010d, 0x010d,
- 0x010f, 0x010f,
- 0x0111, 0x0111,
- 0x0113, 0x0113,
- 0x0115, 0x0115,
- 0x0117, 0x0117,
- 0x0119, 0x0119,
- 0x011b, 0x011b,
- 0x011d, 0x011d,
- 0x011f, 0x011f,
- 0x0121, 0x0121,
- 0x0123, 0x0123,
- 0x0125, 0x0125,
- 0x0127, 0x0127,
- 0x0129, 0x0129,
- 0x012b, 0x012b,
- 0x012d, 0x012d,
- 0x012f, 0x012f,
- 0x0131, 0x0131,
- 0x0133, 0x0133,
- 0x0135, 0x0135,
- 0x0137, 0x0137,
- 0x013a, 0x013a,
- 0x013c, 0x013c,
- 0x013e, 0x013e,
- 0x0140, 0x0140,
- 0x0142, 0x0142,
- 0x0144, 0x0144,
- 0x0146, 0x0146,
- 0x0148, 0x0149,
- 0x014b, 0x014b,
- 0x014d, 0x014d,
- 0x014f, 0x014f,
- 0x0151, 0x0151,
- 0x0153, 0x0153,
- 0x0155, 0x0155,
- 0x0157, 0x0157,
- 0x0159, 0x0159,
- 0x015b, 0x015b,
- 0x015d, 0x015d,
- 0x015f, 0x015f,
- 0x0161, 0x0161,
- 0x0163, 0x0163,
- 0x0165, 0x0165,
- 0x0167, 0x0167,
- 0x0169, 0x0169,
- 0x016b, 0x016b,
- 0x016d, 0x016d,
- 0x016f, 0x016f,
- 0x0171, 0x0171,
- 0x0173, 0x0173,
- 0x0175, 0x0175,
- 0x0177, 0x0177,
- 0x017a, 0x017a,
- 0x017c, 0x017c,
- 0x017e, 0x0180,
- 0x0183, 0x0183,
- 0x0185, 0x0185,
- 0x0188, 0x0188,
- 0x018c, 0x018c,
- 0x0192, 0x0192,
- 0x0195, 0x0195,
- 0x0199, 0x019a,
- 0x019e, 0x019e,
- 0x01a1, 0x01a1,
- 0x01a3, 0x01a3,
- 0x01a5, 0x01a5,
- 0x01a8, 0x01a8,
- 0x01ad, 0x01ad,
- 0x01b0, 0x01b0,
- 0x01b4, 0x01b4,
- 0x01b6, 0x01b6,
- 0x01b9, 0x01b9,
- 0x01bd, 0x01bd,
- 0x01bf, 0x01bf,
- 0x01c4, 0x01c4,
- 0x01c6, 0x01c7,
- 0x01c9, 0x01ca,
- 0x01cc, 0x01cc,
- 0x01ce, 0x01ce,
- 0x01d0, 0x01d0,
- 0x01d2, 0x01d2,
- 0x01d4, 0x01d4,
- 0x01d6, 0x01d6,
- 0x01d8, 0x01d8,
- 0x01da, 0x01da,
- 0x01dc, 0x01dd,
- 0x01df, 0x01df,
- 0x01e1, 0x01e1,
- 0x01e3, 0x01e3,
- 0x01e5, 0x01e5,
- 0x01e7, 0x01e7,
- 0x01e9, 0x01e9,
- 0x01eb, 0x01eb,
- 0x01ed, 0x01ed,
- 0x01ef, 0x01f1,
- 0x01f3, 0x01f3,
- 0x01f5, 0x01f5,
- 0x01f9, 0x01f9,
- 0x01fb, 0x01fb,
- 0x01fd, 0x01fd,
- 0x01ff, 0x01ff,
- 0x0201, 0x0201,
- 0x0203, 0x0203,
- 0x0205, 0x0205,
- 0x0207, 0x0207,
- 0x0209, 0x0209,
- 0x020b, 0x020b,
- 0x020d, 0x020d,
- 0x020f, 0x020f,
- 0x0211, 0x0211,
- 0x0213, 0x0213,
- 0x0215, 0x0215,
- 0x0217, 0x0217,
- 0x0219, 0x0219,
- 0x021b, 0x021b,
- 0x021d, 0x021d,
- 0x021f, 0x021f,
- 0x0223, 0x0223,
- 0x0225, 0x0225,
- 0x0227, 0x0227,
- 0x0229, 0x0229,
- 0x022b, 0x022b,
- 0x022d, 0x022d,
- 0x022f, 0x022f,
- 0x0231, 0x0231,
- 0x0233, 0x0233,
- 0x023c, 0x023c,
- 0x023f, 0x0240,
- 0x0242, 0x0242,
- 0x0247, 0x0247,
- 0x0249, 0x0249,
- 0x024b, 0x024b,
- 0x024d, 0x024d,
- 0x024f, 0x0254,
- 0x0256, 0x0257,
- 0x0259, 0x0259,
- 0x025b, 0x025c,
- 0x0260, 0x0261,
- 0x0263, 0x0263,
- 0x0265, 0x0266,
- 0x0268, 0x026c,
- 0x026f, 0x026f,
- 0x0271, 0x0272,
- 0x0275, 0x0275,
- 0x027d, 0x027d,
- 0x0280, 0x0280,
- 0x0282, 0x0283,
- 0x0287, 0x028c,
- 0x0292, 0x0292,
- 0x029d, 0x029e,
- 0x0345, 0x0345,
- 0x0371, 0x0371,
- 0x0373, 0x0373,
- 0x0377, 0x0377,
- 0x037b, 0x037d,
- 0x0390, 0x0390,
- 0x03ac, 0x03ce,
- 0x03d0, 0x03d1,
- 0x03d5, 0x03d7,
- 0x03d9, 0x03d9,
- 0x03db, 0x03db,
- 0x03dd, 0x03dd,
- 0x03df, 0x03df,
- 0x03e1, 0x03e1,
- 0x03e3, 0x03e3,
- 0x03e5, 0x03e5,
- 0x03e7, 0x03e7,
- 0x03e9, 0x03e9,
- 0x03eb, 0x03eb,
- 0x03ed, 0x03ed,
- 0x03ef, 0x03f3,
- 0x03f5, 0x03f5,
- 0x03f8, 0x03f8,
- 0x03fb, 0x03fb,
- 0x0430, 0x045f,
- 0x0461, 0x0461,
- 0x0463, 0x0463,
- 0x0465, 0x0465,
- 0x0467, 0x0467,
- 0x0469, 0x0469,
- 0x046b, 0x046b,
- 0x046d, 0x046d,
- 0x046f, 0x046f,
- 0x0471, 0x0471,
- 0x0473, 0x0473,
- 0x0475, 0x0475,
- 0x0477, 0x0477,
- 0x0479, 0x0479,
- 0x047b, 0x047b,
- 0x047d, 0x047d,
- 0x047f, 0x047f,
- 0x0481, 0x0481,
- 0x048b, 0x048b,
- 0x048d, 0x048d,
- 0x048f, 0x048f,
- 0x0491, 0x0491,
- 0x0493, 0x0493,
- 0x0495, 0x0495,
- 0x0497, 0x0497,
- 0x0499, 0x0499,
- 0x049b, 0x049b,
- 0x049d, 0x049d,
- 0x049f, 0x049f,
- 0x04a1, 0x04a1,
- 0x04a3, 0x04a3,
- 0x04a5, 0x04a5,
- 0x04a7, 0x04a7,
- 0x04a9, 0x04a9,
- 0x04ab, 0x04ab,
- 0x04ad, 0x04ad,
- 0x04af, 0x04af,
- 0x04b1, 0x04b1,
- 0x04b3, 0x04b3,
- 0x04b5, 0x04b5,
- 0x04b7, 0x04b7,
- 0x04b9, 0x04b9,
- 0x04bb, 0x04bb,
- 0x04bd, 0x04bd,
- 0x04bf, 0x04bf,
- 0x04c2, 0x04c2,
- 0x04c4, 0x04c4,
- 0x04c6, 0x04c6,
- 0x04c8, 0x04c8,
- 0x04ca, 0x04ca,
- 0x04cc, 0x04cc,
- 0x04ce, 0x04cf,
- 0x04d1, 0x04d1,
- 0x04d3, 0x04d3,
- 0x04d5, 0x04d5,
- 0x04d7, 0x04d7,
- 0x04d9, 0x04d9,
- 0x04db, 0x04db,
- 0x04dd, 0x04dd,
- 0x04df, 0x04df,
- 0x04e1, 0x04e1,
- 0x04e3, 0x04e3,
- 0x04e5, 0x04e5,
- 0x04e7, 0x04e7,
- 0x04e9, 0x04e9,
- 0x04eb, 0x04eb,
- 0x04ed, 0x04ed,
- 0x04ef, 0x04ef,
- 0x04f1, 0x04f1,
- 0x04f3, 0x04f3,
- 0x04f5, 0x04f5,
- 0x04f7, 0x04f7,
- 0x04f9, 0x04f9,
- 0x04fb, 0x04fb,
- 0x04fd, 0x04fd,
- 0x04ff, 0x04ff,
- 0x0501, 0x0501,
- 0x0503, 0x0503,
- 0x0505, 0x0505,
- 0x0507, 0x0507,
- 0x0509, 0x0509,
- 0x050b, 0x050b,
- 0x050d, 0x050d,
- 0x050f, 0x050f,
- 0x0511, 0x0511,
- 0x0513, 0x0513,
- 0x0515, 0x0515,
- 0x0517, 0x0517,
- 0x0519, 0x0519,
- 0x051b, 0x051b,
- 0x051d, 0x051d,
- 0x051f, 0x051f,
- 0x0521, 0x0521,
- 0x0523, 0x0523,
- 0x0525, 0x0525,
- 0x0527, 0x0527,
- 0x0529, 0x0529,
- 0x052b, 0x052b,
- 0x052d, 0x052d,
- 0x052f, 0x052f,
- 0x0561, 0x0587,
- 0x13f8, 0x13fd,
- 0x1c80, 0x1c88,
- 0x1d79, 0x1d79,
- 0x1d7d, 0x1d7d,
- 0x1d8e, 0x1d8e,
- 0x1e01, 0x1e01,
- 0x1e03, 0x1e03,
- 0x1e05, 0x1e05,
- 0x1e07, 0x1e07,
- 0x1e09, 0x1e09,
- 0x1e0b, 0x1e0b,
- 0x1e0d, 0x1e0d,
- 0x1e0f, 0x1e0f,
- 0x1e11, 0x1e11,
- 0x1e13, 0x1e13,
- 0x1e15, 0x1e15,
- 0x1e17, 0x1e17,
- 0x1e19, 0x1e19,
- 0x1e1b, 0x1e1b,
- 0x1e1d, 0x1e1d,
- 0x1e1f, 0x1e1f,
- 0x1e21, 0x1e21,
- 0x1e23, 0x1e23,
- 0x1e25, 0x1e25,
- 0x1e27, 0x1e27,
- 0x1e29, 0x1e29,
- 0x1e2b, 0x1e2b,
- 0x1e2d, 0x1e2d,
- 0x1e2f, 0x1e2f,
- 0x1e31, 0x1e31,
- 0x1e33, 0x1e33,
- 0x1e35, 0x1e35,
- 0x1e37, 0x1e37,
- 0x1e39, 0x1e39,
- 0x1e3b, 0x1e3b,
- 0x1e3d, 0x1e3d,
- 0x1e3f, 0x1e3f,
- 0x1e41, 0x1e41,
- 0x1e43, 0x1e43,
- 0x1e45, 0x1e45,
- 0x1e47, 0x1e47,
- 0x1e49, 0x1e49,
- 0x1e4b, 0x1e4b,
- 0x1e4d, 0x1e4d,
- 0x1e4f, 0x1e4f,
- 0x1e51, 0x1e51,
- 0x1e53, 0x1e53,
- 0x1e55, 0x1e55,
- 0x1e57, 0x1e57,
- 0x1e59, 0x1e59,
- 0x1e5b, 0x1e5b,
- 0x1e5d, 0x1e5d,
- 0x1e5f, 0x1e5f,
- 0x1e61, 0x1e61,
- 0x1e63, 0x1e63,
- 0x1e65, 0x1e65,
- 0x1e67, 0x1e67,
- 0x1e69, 0x1e69,
- 0x1e6b, 0x1e6b,
- 0x1e6d, 0x1e6d,
- 0x1e6f, 0x1e6f,
- 0x1e71, 0x1e71,
- 0x1e73, 0x1e73,
- 0x1e75, 0x1e75,
- 0x1e77, 0x1e77,
- 0x1e79, 0x1e79,
- 0x1e7b, 0x1e7b,
- 0x1e7d, 0x1e7d,
- 0x1e7f, 0x1e7f,
- 0x1e81, 0x1e81,
- 0x1e83, 0x1e83,
- 0x1e85, 0x1e85,
- 0x1e87, 0x1e87,
- 0x1e89, 0x1e89,
- 0x1e8b, 0x1e8b,
- 0x1e8d, 0x1e8d,
- 0x1e8f, 0x1e8f,
- 0x1e91, 0x1e91,
- 0x1e93, 0x1e93,
- 0x1e95, 0x1e9b,
- 0x1ea1, 0x1ea1,
- 0x1ea3, 0x1ea3,
- 0x1ea5, 0x1ea5,
- 0x1ea7, 0x1ea7,
- 0x1ea9, 0x1ea9,
- 0x1eab, 0x1eab,
- 0x1ead, 0x1ead,
- 0x1eaf, 0x1eaf,
- 0x1eb1, 0x1eb1,
- 0x1eb3, 0x1eb3,
- 0x1eb5, 0x1eb5,
- 0x1eb7, 0x1eb7,
- 0x1eb9, 0x1eb9,
- 0x1ebb, 0x1ebb,
- 0x1ebd, 0x1ebd,
- 0x1ebf, 0x1ebf,
- 0x1ec1, 0x1ec1,
- 0x1ec3, 0x1ec3,
- 0x1ec5, 0x1ec5,
- 0x1ec7, 0x1ec7,
- 0x1ec9, 0x1ec9,
- 0x1ecb, 0x1ecb,
- 0x1ecd, 0x1ecd,
- 0x1ecf, 0x1ecf,
- 0x1ed1, 0x1ed1,
- 0x1ed3, 0x1ed3,
- 0x1ed5, 0x1ed5,
- 0x1ed7, 0x1ed7,
- 0x1ed9, 0x1ed9,
- 0x1edb, 0x1edb,
- 0x1edd, 0x1edd,
- 0x1edf, 0x1edf,
- 0x1ee1, 0x1ee1,
- 0x1ee3, 0x1ee3,
- 0x1ee5, 0x1ee5,
- 0x1ee7, 0x1ee7,
- 0x1ee9, 0x1ee9,
- 0x1eeb, 0x1eeb,
- 0x1eed, 0x1eed,
- 0x1eef, 0x1eef,
- 0x1ef1, 0x1ef1,
- 0x1ef3, 0x1ef3,
- 0x1ef5, 0x1ef5,
- 0x1ef7, 0x1ef7,
- 0x1ef9, 0x1ef9,
- 0x1efb, 0x1efb,
- 0x1efd, 0x1efd,
- 0x1eff, 0x1f07,
- 0x1f10, 0x1f15,
- 0x1f20, 0x1f27,
- 0x1f30, 0x1f37,
- 0x1f40, 0x1f45,
- 0x1f50, 0x1f57,
- 0x1f60, 0x1f67,
- 0x1f70, 0x1f7d,
- 0x1f80, 0x1f87,
- 0x1f90, 0x1f97,
- 0x1fa0, 0x1fa7,
- 0x1fb0, 0x1fb4,
- 0x1fb6, 0x1fb7,
- 0x1fbe, 0x1fbe,
- 0x1fc2, 0x1fc4,
- 0x1fc6, 0x1fc7,
- 0x1fd0, 0x1fd3,
- 0x1fd6, 0x1fd7,
- 0x1fe0, 0x1fe7,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ff7,
- 0x214e, 0x214e,
- 0x2170, 0x217f,
- 0x2184, 0x2184,
- 0x24d0, 0x24e9,
- 0x2c30, 0x2c5f,
- 0x2c61, 0x2c61,
- 0x2c65, 0x2c66,
- 0x2c68, 0x2c68,
- 0x2c6a, 0x2c6a,
- 0x2c6c, 0x2c6c,
- 0x2c73, 0x2c73,
- 0x2c76, 0x2c76,
- 0x2c81, 0x2c81,
- 0x2c83, 0x2c83,
- 0x2c85, 0x2c85,
- 0x2c87, 0x2c87,
- 0x2c89, 0x2c89,
- 0x2c8b, 0x2c8b,
- 0x2c8d, 0x2c8d,
- 0x2c8f, 0x2c8f,
- 0x2c91, 0x2c91,
- 0x2c93, 0x2c93,
- 0x2c95, 0x2c95,
- 0x2c97, 0x2c97,
- 0x2c99, 0x2c99,
- 0x2c9b, 0x2c9b,
- 0x2c9d, 0x2c9d,
- 0x2c9f, 0x2c9f,
- 0x2ca1, 0x2ca1,
- 0x2ca3, 0x2ca3,
- 0x2ca5, 0x2ca5,
- 0x2ca7, 0x2ca7,
- 0x2ca9, 0x2ca9,
- 0x2cab, 0x2cab,
- 0x2cad, 0x2cad,
- 0x2caf, 0x2caf,
- 0x2cb1, 0x2cb1,
- 0x2cb3, 0x2cb3,
- 0x2cb5, 0x2cb5,
- 0x2cb7, 0x2cb7,
- 0x2cb9, 0x2cb9,
- 0x2cbb, 0x2cbb,
- 0x2cbd, 0x2cbd,
- 0x2cbf, 0x2cbf,
- 0x2cc1, 0x2cc1,
- 0x2cc3, 0x2cc3,
- 0x2cc5, 0x2cc5,
- 0x2cc7, 0x2cc7,
- 0x2cc9, 0x2cc9,
- 0x2ccb, 0x2ccb,
- 0x2ccd, 0x2ccd,
- 0x2ccf, 0x2ccf,
- 0x2cd1, 0x2cd1,
- 0x2cd3, 0x2cd3,
- 0x2cd5, 0x2cd5,
- 0x2cd7, 0x2cd7,
- 0x2cd9, 0x2cd9,
- 0x2cdb, 0x2cdb,
- 0x2cdd, 0x2cdd,
- 0x2cdf, 0x2cdf,
- 0x2ce1, 0x2ce1,
- 0x2ce3, 0x2ce3,
- 0x2cec, 0x2cec,
- 0x2cee, 0x2cee,
- 0x2cf3, 0x2cf3,
- 0x2d00, 0x2d25,
- 0x2d27, 0x2d27,
- 0x2d2d, 0x2d2d,
- 0xa641, 0xa641,
- 0xa643, 0xa643,
- 0xa645, 0xa645,
- 0xa647, 0xa647,
- 0xa649, 0xa649,
- 0xa64b, 0xa64b,
- 0xa64d, 0xa64d,
- 0xa64f, 0xa64f,
- 0xa651, 0xa651,
- 0xa653, 0xa653,
- 0xa655, 0xa655,
- 0xa657, 0xa657,
- 0xa659, 0xa659,
- 0xa65b, 0xa65b,
- 0xa65d, 0xa65d,
- 0xa65f, 0xa65f,
- 0xa661, 0xa661,
- 0xa663, 0xa663,
- 0xa665, 0xa665,
- 0xa667, 0xa667,
- 0xa669, 0xa669,
- 0xa66b, 0xa66b,
- 0xa66d, 0xa66d,
- 0xa681, 0xa681,
- 0xa683, 0xa683,
- 0xa685, 0xa685,
- 0xa687, 0xa687,
- 0xa689, 0xa689,
- 0xa68b, 0xa68b,
- 0xa68d, 0xa68d,
- 0xa68f, 0xa68f,
- 0xa691, 0xa691,
- 0xa693, 0xa693,
- 0xa695, 0xa695,
- 0xa697, 0xa697,
- 0xa699, 0xa699,
- 0xa69b, 0xa69b,
- 0xa723, 0xa723,
- 0xa725, 0xa725,
- 0xa727, 0xa727,
- 0xa729, 0xa729,
- 0xa72b, 0xa72b,
- 0xa72d, 0xa72d,
- 0xa72f, 0xa72f,
- 0xa733, 0xa733,
- 0xa735, 0xa735,
- 0xa737, 0xa737,
- 0xa739, 0xa739,
- 0xa73b, 0xa73b,
- 0xa73d, 0xa73d,
- 0xa73f, 0xa73f,
- 0xa741, 0xa741,
- 0xa743, 0xa743,
- 0xa745, 0xa745,
- 0xa747, 0xa747,
- 0xa749, 0xa749,
- 0xa74b, 0xa74b,
- 0xa74d, 0xa74d,
- 0xa74f, 0xa74f,
- 0xa751, 0xa751,
- 0xa753, 0xa753,
- 0xa755, 0xa755,
- 0xa757, 0xa757,
- 0xa759, 0xa759,
- 0xa75b, 0xa75b,
- 0xa75d, 0xa75d,
- 0xa75f, 0xa75f,
- 0xa761, 0xa761,
- 0xa763, 0xa763,
- 0xa765, 0xa765,
- 0xa767, 0xa767,
- 0xa769, 0xa769,
- 0xa76b, 0xa76b,
- 0xa76d, 0xa76d,
- 0xa76f, 0xa76f,
- 0xa77a, 0xa77a,
- 0xa77c, 0xa77c,
- 0xa77f, 0xa77f,
- 0xa781, 0xa781,
- 0xa783, 0xa783,
- 0xa785, 0xa785,
- 0xa787, 0xa787,
- 0xa78c, 0xa78c,
- 0xa791, 0xa791,
- 0xa793, 0xa794,
- 0xa797, 0xa797,
- 0xa799, 0xa799,
- 0xa79b, 0xa79b,
- 0xa79d, 0xa79d,
- 0xa79f, 0xa79f,
- 0xa7a1, 0xa7a1,
- 0xa7a3, 0xa7a3,
- 0xa7a5, 0xa7a5,
- 0xa7a7, 0xa7a7,
- 0xa7a9, 0xa7a9,
- 0xa7b5, 0xa7b5,
- 0xa7b7, 0xa7b7,
- 0xa7b9, 0xa7b9,
- 0xa7bb, 0xa7bb,
- 0xa7bd, 0xa7bd,
- 0xa7bf, 0xa7bf,
- 0xa7c1, 0xa7c1,
- 0xa7c3, 0xa7c3,
- 0xa7c8, 0xa7c8,
- 0xa7ca, 0xa7ca,
- 0xa7d1, 0xa7d1,
- 0xa7d7, 0xa7d7,
- 0xa7d9, 0xa7d9,
- 0xa7f6, 0xa7f6,
- 0xab53, 0xab53,
- 0xab70, 0xabbf,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xff41, 0xff5a,
- 0x10428, 0x1044f,
- 0x104d8, 0x104fb,
- 0x10597, 0x105a1,
- 0x105a3, 0x105b1,
- 0x105b3, 0x105b9,
- 0x105bb, 0x105bc,
- 0x10cc0, 0x10cf2,
- 0x118c0, 0x118df,
- 0x16e60, 0x16e7f,
- 0x1e922, 0x1e943,
-}; /* CR_Changes_When_Titlecased */
-
-/* 'Changes_When_Casefolded': Derived Property */
-static const OnigCodePoint CR_Changes_When_Casefolded[] = {
- 622,
- 0x0041, 0x005a,
- 0x00b5, 0x00b5,
- 0x00c0, 0x00d6,
- 0x00d8, 0x00df,
- 0x0100, 0x0100,
- 0x0102, 0x0102,
- 0x0104, 0x0104,
- 0x0106, 0x0106,
- 0x0108, 0x0108,
- 0x010a, 0x010a,
- 0x010c, 0x010c,
- 0x010e, 0x010e,
- 0x0110, 0x0110,
- 0x0112, 0x0112,
- 0x0114, 0x0114,
- 0x0116, 0x0116,
- 0x0118, 0x0118,
- 0x011a, 0x011a,
- 0x011c, 0x011c,
- 0x011e, 0x011e,
- 0x0120, 0x0120,
- 0x0122, 0x0122,
- 0x0124, 0x0124,
- 0x0126, 0x0126,
- 0x0128, 0x0128,
- 0x012a, 0x012a,
- 0x012c, 0x012c,
- 0x012e, 0x012e,
- 0x0130, 0x0130,
- 0x0132, 0x0132,
- 0x0134, 0x0134,
- 0x0136, 0x0136,
- 0x0139, 0x0139,
- 0x013b, 0x013b,
- 0x013d, 0x013d,
- 0x013f, 0x013f,
- 0x0141, 0x0141,
- 0x0143, 0x0143,
- 0x0145, 0x0145,
- 0x0147, 0x0147,
- 0x0149, 0x014a,
- 0x014c, 0x014c,
- 0x014e, 0x014e,
- 0x0150, 0x0150,
- 0x0152, 0x0152,
- 0x0154, 0x0154,
- 0x0156, 0x0156,
- 0x0158, 0x0158,
- 0x015a, 0x015a,
- 0x015c, 0x015c,
- 0x015e, 0x015e,
- 0x0160, 0x0160,
- 0x0162, 0x0162,
- 0x0164, 0x0164,
- 0x0166, 0x0166,
- 0x0168, 0x0168,
- 0x016a, 0x016a,
- 0x016c, 0x016c,
- 0x016e, 0x016e,
- 0x0170, 0x0170,
- 0x0172, 0x0172,
- 0x0174, 0x0174,
- 0x0176, 0x0176,
- 0x0178, 0x0179,
- 0x017b, 0x017b,
- 0x017d, 0x017d,
- 0x017f, 0x017f,
- 0x0181, 0x0182,
- 0x0184, 0x0184,
- 0x0186, 0x0187,
- 0x0189, 0x018b,
- 0x018e, 0x0191,
- 0x0193, 0x0194,
- 0x0196, 0x0198,
- 0x019c, 0x019d,
- 0x019f, 0x01a0,
- 0x01a2, 0x01a2,
- 0x01a4, 0x01a4,
- 0x01a6, 0x01a7,
- 0x01a9, 0x01a9,
- 0x01ac, 0x01ac,
- 0x01ae, 0x01af,
- 0x01b1, 0x01b3,
- 0x01b5, 0x01b5,
- 0x01b7, 0x01b8,
- 0x01bc, 0x01bc,
- 0x01c4, 0x01c5,
- 0x01c7, 0x01c8,
- 0x01ca, 0x01cb,
- 0x01cd, 0x01cd,
- 0x01cf, 0x01cf,
- 0x01d1, 0x01d1,
- 0x01d3, 0x01d3,
- 0x01d5, 0x01d5,
- 0x01d7, 0x01d7,
- 0x01d9, 0x01d9,
- 0x01db, 0x01db,
- 0x01de, 0x01de,
- 0x01e0, 0x01e0,
- 0x01e2, 0x01e2,
- 0x01e4, 0x01e4,
- 0x01e6, 0x01e6,
- 0x01e8, 0x01e8,
- 0x01ea, 0x01ea,
- 0x01ec, 0x01ec,
- 0x01ee, 0x01ee,
- 0x01f1, 0x01f2,
- 0x01f4, 0x01f4,
- 0x01f6, 0x01f8,
- 0x01fa, 0x01fa,
- 0x01fc, 0x01fc,
- 0x01fe, 0x01fe,
- 0x0200, 0x0200,
- 0x0202, 0x0202,
- 0x0204, 0x0204,
- 0x0206, 0x0206,
- 0x0208, 0x0208,
- 0x020a, 0x020a,
- 0x020c, 0x020c,
- 0x020e, 0x020e,
- 0x0210, 0x0210,
- 0x0212, 0x0212,
- 0x0214, 0x0214,
- 0x0216, 0x0216,
- 0x0218, 0x0218,
- 0x021a, 0x021a,
- 0x021c, 0x021c,
- 0x021e, 0x021e,
- 0x0220, 0x0220,
- 0x0222, 0x0222,
- 0x0224, 0x0224,
- 0x0226, 0x0226,
- 0x0228, 0x0228,
- 0x022a, 0x022a,
- 0x022c, 0x022c,
- 0x022e, 0x022e,
- 0x0230, 0x0230,
- 0x0232, 0x0232,
- 0x023a, 0x023b,
- 0x023d, 0x023e,
- 0x0241, 0x0241,
- 0x0243, 0x0246,
- 0x0248, 0x0248,
- 0x024a, 0x024a,
- 0x024c, 0x024c,
- 0x024e, 0x024e,
- 0x0345, 0x0345,
- 0x0370, 0x0370,
- 0x0372, 0x0372,
- 0x0376, 0x0376,
- 0x037f, 0x037f,
- 0x0386, 0x0386,
- 0x0388, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x038f,
- 0x0391, 0x03a1,
- 0x03a3, 0x03ab,
- 0x03c2, 0x03c2,
- 0x03cf, 0x03d1,
- 0x03d5, 0x03d6,
- 0x03d8, 0x03d8,
- 0x03da, 0x03da,
- 0x03dc, 0x03dc,
- 0x03de, 0x03de,
- 0x03e0, 0x03e0,
- 0x03e2, 0x03e2,
- 0x03e4, 0x03e4,
- 0x03e6, 0x03e6,
- 0x03e8, 0x03e8,
- 0x03ea, 0x03ea,
- 0x03ec, 0x03ec,
- 0x03ee, 0x03ee,
- 0x03f0, 0x03f1,
- 0x03f4, 0x03f5,
- 0x03f7, 0x03f7,
- 0x03f9, 0x03fa,
- 0x03fd, 0x042f,
- 0x0460, 0x0460,
- 0x0462, 0x0462,
- 0x0464, 0x0464,
- 0x0466, 0x0466,
- 0x0468, 0x0468,
- 0x046a, 0x046a,
- 0x046c, 0x046c,
- 0x046e, 0x046e,
- 0x0470, 0x0470,
- 0x0472, 0x0472,
- 0x0474, 0x0474,
- 0x0476, 0x0476,
- 0x0478, 0x0478,
- 0x047a, 0x047a,
- 0x047c, 0x047c,
- 0x047e, 0x047e,
- 0x0480, 0x0480,
- 0x048a, 0x048a,
- 0x048c, 0x048c,
- 0x048e, 0x048e,
- 0x0490, 0x0490,
- 0x0492, 0x0492,
- 0x0494, 0x0494,
- 0x0496, 0x0496,
- 0x0498, 0x0498,
- 0x049a, 0x049a,
- 0x049c, 0x049c,
- 0x049e, 0x049e,
- 0x04a0, 0x04a0,
- 0x04a2, 0x04a2,
- 0x04a4, 0x04a4,
- 0x04a6, 0x04a6,
- 0x04a8, 0x04a8,
- 0x04aa, 0x04aa,
- 0x04ac, 0x04ac,
- 0x04ae, 0x04ae,
- 0x04b0, 0x04b0,
- 0x04b2, 0x04b2,
- 0x04b4, 0x04b4,
- 0x04b6, 0x04b6,
- 0x04b8, 0x04b8,
- 0x04ba, 0x04ba,
- 0x04bc, 0x04bc,
- 0x04be, 0x04be,
- 0x04c0, 0x04c1,
- 0x04c3, 0x04c3,
- 0x04c5, 0x04c5,
- 0x04c7, 0x04c7,
- 0x04c9, 0x04c9,
- 0x04cb, 0x04cb,
- 0x04cd, 0x04cd,
- 0x04d0, 0x04d0,
- 0x04d2, 0x04d2,
- 0x04d4, 0x04d4,
- 0x04d6, 0x04d6,
- 0x04d8, 0x04d8,
- 0x04da, 0x04da,
- 0x04dc, 0x04dc,
- 0x04de, 0x04de,
- 0x04e0, 0x04e0,
- 0x04e2, 0x04e2,
- 0x04e4, 0x04e4,
- 0x04e6, 0x04e6,
- 0x04e8, 0x04e8,
- 0x04ea, 0x04ea,
- 0x04ec, 0x04ec,
- 0x04ee, 0x04ee,
- 0x04f0, 0x04f0,
- 0x04f2, 0x04f2,
- 0x04f4, 0x04f4,
- 0x04f6, 0x04f6,
- 0x04f8, 0x04f8,
- 0x04fa, 0x04fa,
- 0x04fc, 0x04fc,
- 0x04fe, 0x04fe,
- 0x0500, 0x0500,
- 0x0502, 0x0502,
- 0x0504, 0x0504,
- 0x0506, 0x0506,
- 0x0508, 0x0508,
- 0x050a, 0x050a,
- 0x050c, 0x050c,
- 0x050e, 0x050e,
- 0x0510, 0x0510,
- 0x0512, 0x0512,
- 0x0514, 0x0514,
- 0x0516, 0x0516,
- 0x0518, 0x0518,
- 0x051a, 0x051a,
- 0x051c, 0x051c,
- 0x051e, 0x051e,
- 0x0520, 0x0520,
- 0x0522, 0x0522,
- 0x0524, 0x0524,
- 0x0526, 0x0526,
- 0x0528, 0x0528,
- 0x052a, 0x052a,
- 0x052c, 0x052c,
- 0x052e, 0x052e,
- 0x0531, 0x0556,
- 0x0587, 0x0587,
- 0x10a0, 0x10c5,
- 0x10c7, 0x10c7,
- 0x10cd, 0x10cd,
- 0x13f8, 0x13fd,
- 0x1c80, 0x1c88,
- 0x1c90, 0x1cba,
- 0x1cbd, 0x1cbf,
- 0x1e00, 0x1e00,
- 0x1e02, 0x1e02,
- 0x1e04, 0x1e04,
- 0x1e06, 0x1e06,
- 0x1e08, 0x1e08,
- 0x1e0a, 0x1e0a,
- 0x1e0c, 0x1e0c,
- 0x1e0e, 0x1e0e,
- 0x1e10, 0x1e10,
- 0x1e12, 0x1e12,
- 0x1e14, 0x1e14,
- 0x1e16, 0x1e16,
- 0x1e18, 0x1e18,
- 0x1e1a, 0x1e1a,
- 0x1e1c, 0x1e1c,
- 0x1e1e, 0x1e1e,
- 0x1e20, 0x1e20,
- 0x1e22, 0x1e22,
- 0x1e24, 0x1e24,
- 0x1e26, 0x1e26,
- 0x1e28, 0x1e28,
- 0x1e2a, 0x1e2a,
- 0x1e2c, 0x1e2c,
- 0x1e2e, 0x1e2e,
- 0x1e30, 0x1e30,
- 0x1e32, 0x1e32,
- 0x1e34, 0x1e34,
- 0x1e36, 0x1e36,
- 0x1e38, 0x1e38,
- 0x1e3a, 0x1e3a,
- 0x1e3c, 0x1e3c,
- 0x1e3e, 0x1e3e,
- 0x1e40, 0x1e40,
- 0x1e42, 0x1e42,
- 0x1e44, 0x1e44,
- 0x1e46, 0x1e46,
- 0x1e48, 0x1e48,
- 0x1e4a, 0x1e4a,
- 0x1e4c, 0x1e4c,
- 0x1e4e, 0x1e4e,
- 0x1e50, 0x1e50,
- 0x1e52, 0x1e52,
- 0x1e54, 0x1e54,
- 0x1e56, 0x1e56,
- 0x1e58, 0x1e58,
- 0x1e5a, 0x1e5a,
- 0x1e5c, 0x1e5c,
- 0x1e5e, 0x1e5e,
- 0x1e60, 0x1e60,
- 0x1e62, 0x1e62,
- 0x1e64, 0x1e64,
- 0x1e66, 0x1e66,
- 0x1e68, 0x1e68,
- 0x1e6a, 0x1e6a,
- 0x1e6c, 0x1e6c,
- 0x1e6e, 0x1e6e,
- 0x1e70, 0x1e70,
- 0x1e72, 0x1e72,
- 0x1e74, 0x1e74,
- 0x1e76, 0x1e76,
- 0x1e78, 0x1e78,
- 0x1e7a, 0x1e7a,
- 0x1e7c, 0x1e7c,
- 0x1e7e, 0x1e7e,
- 0x1e80, 0x1e80,
- 0x1e82, 0x1e82,
- 0x1e84, 0x1e84,
- 0x1e86, 0x1e86,
- 0x1e88, 0x1e88,
- 0x1e8a, 0x1e8a,
- 0x1e8c, 0x1e8c,
- 0x1e8e, 0x1e8e,
- 0x1e90, 0x1e90,
- 0x1e92, 0x1e92,
- 0x1e94, 0x1e94,
- 0x1e9a, 0x1e9b,
- 0x1e9e, 0x1e9e,
- 0x1ea0, 0x1ea0,
- 0x1ea2, 0x1ea2,
- 0x1ea4, 0x1ea4,
- 0x1ea6, 0x1ea6,
- 0x1ea8, 0x1ea8,
- 0x1eaa, 0x1eaa,
- 0x1eac, 0x1eac,
- 0x1eae, 0x1eae,
- 0x1eb0, 0x1eb0,
- 0x1eb2, 0x1eb2,
- 0x1eb4, 0x1eb4,
- 0x1eb6, 0x1eb6,
- 0x1eb8, 0x1eb8,
- 0x1eba, 0x1eba,
- 0x1ebc, 0x1ebc,
- 0x1ebe, 0x1ebe,
- 0x1ec0, 0x1ec0,
- 0x1ec2, 0x1ec2,
- 0x1ec4, 0x1ec4,
- 0x1ec6, 0x1ec6,
- 0x1ec8, 0x1ec8,
- 0x1eca, 0x1eca,
- 0x1ecc, 0x1ecc,
- 0x1ece, 0x1ece,
- 0x1ed0, 0x1ed0,
- 0x1ed2, 0x1ed2,
- 0x1ed4, 0x1ed4,
- 0x1ed6, 0x1ed6,
- 0x1ed8, 0x1ed8,
- 0x1eda, 0x1eda,
- 0x1edc, 0x1edc,
- 0x1ede, 0x1ede,
- 0x1ee0, 0x1ee0,
- 0x1ee2, 0x1ee2,
- 0x1ee4, 0x1ee4,
- 0x1ee6, 0x1ee6,
- 0x1ee8, 0x1ee8,
- 0x1eea, 0x1eea,
- 0x1eec, 0x1eec,
- 0x1eee, 0x1eee,
- 0x1ef0, 0x1ef0,
- 0x1ef2, 0x1ef2,
- 0x1ef4, 0x1ef4,
- 0x1ef6, 0x1ef6,
- 0x1ef8, 0x1ef8,
- 0x1efa, 0x1efa,
- 0x1efc, 0x1efc,
- 0x1efe, 0x1efe,
- 0x1f08, 0x1f0f,
- 0x1f18, 0x1f1d,
- 0x1f28, 0x1f2f,
- 0x1f38, 0x1f3f,
- 0x1f48, 0x1f4d,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f5f,
- 0x1f68, 0x1f6f,
- 0x1f80, 0x1faf,
- 0x1fb2, 0x1fb4,
- 0x1fb7, 0x1fbc,
- 0x1fc2, 0x1fc4,
- 0x1fc7, 0x1fcc,
- 0x1fd8, 0x1fdb,
- 0x1fe8, 0x1fec,
- 0x1ff2, 0x1ff4,
- 0x1ff7, 0x1ffc,
- 0x2126, 0x2126,
- 0x212a, 0x212b,
- 0x2132, 0x2132,
- 0x2160, 0x216f,
- 0x2183, 0x2183,
- 0x24b6, 0x24cf,
- 0x2c00, 0x2c2f,
- 0x2c60, 0x2c60,
- 0x2c62, 0x2c64,
- 0x2c67, 0x2c67,
- 0x2c69, 0x2c69,
- 0x2c6b, 0x2c6b,
- 0x2c6d, 0x2c70,
- 0x2c72, 0x2c72,
- 0x2c75, 0x2c75,
- 0x2c7e, 0x2c80,
- 0x2c82, 0x2c82,
- 0x2c84, 0x2c84,
- 0x2c86, 0x2c86,
- 0x2c88, 0x2c88,
- 0x2c8a, 0x2c8a,
- 0x2c8c, 0x2c8c,
- 0x2c8e, 0x2c8e,
- 0x2c90, 0x2c90,
- 0x2c92, 0x2c92,
- 0x2c94, 0x2c94,
- 0x2c96, 0x2c96,
- 0x2c98, 0x2c98,
- 0x2c9a, 0x2c9a,
- 0x2c9c, 0x2c9c,
- 0x2c9e, 0x2c9e,
- 0x2ca0, 0x2ca0,
- 0x2ca2, 0x2ca2,
- 0x2ca4, 0x2ca4,
- 0x2ca6, 0x2ca6,
- 0x2ca8, 0x2ca8,
- 0x2caa, 0x2caa,
- 0x2cac, 0x2cac,
- 0x2cae, 0x2cae,
- 0x2cb0, 0x2cb0,
- 0x2cb2, 0x2cb2,
- 0x2cb4, 0x2cb4,
- 0x2cb6, 0x2cb6,
- 0x2cb8, 0x2cb8,
- 0x2cba, 0x2cba,
- 0x2cbc, 0x2cbc,
- 0x2cbe, 0x2cbe,
- 0x2cc0, 0x2cc0,
- 0x2cc2, 0x2cc2,
- 0x2cc4, 0x2cc4,
- 0x2cc6, 0x2cc6,
- 0x2cc8, 0x2cc8,
- 0x2cca, 0x2cca,
- 0x2ccc, 0x2ccc,
- 0x2cce, 0x2cce,
- 0x2cd0, 0x2cd0,
- 0x2cd2, 0x2cd2,
- 0x2cd4, 0x2cd4,
- 0x2cd6, 0x2cd6,
- 0x2cd8, 0x2cd8,
- 0x2cda, 0x2cda,
- 0x2cdc, 0x2cdc,
- 0x2cde, 0x2cde,
- 0x2ce0, 0x2ce0,
- 0x2ce2, 0x2ce2,
- 0x2ceb, 0x2ceb,
- 0x2ced, 0x2ced,
- 0x2cf2, 0x2cf2,
- 0xa640, 0xa640,
- 0xa642, 0xa642,
- 0xa644, 0xa644,
- 0xa646, 0xa646,
- 0xa648, 0xa648,
- 0xa64a, 0xa64a,
- 0xa64c, 0xa64c,
- 0xa64e, 0xa64e,
- 0xa650, 0xa650,
- 0xa652, 0xa652,
- 0xa654, 0xa654,
- 0xa656, 0xa656,
- 0xa658, 0xa658,
- 0xa65a, 0xa65a,
- 0xa65c, 0xa65c,
- 0xa65e, 0xa65e,
- 0xa660, 0xa660,
- 0xa662, 0xa662,
- 0xa664, 0xa664,
- 0xa666, 0xa666,
- 0xa668, 0xa668,
- 0xa66a, 0xa66a,
- 0xa66c, 0xa66c,
- 0xa680, 0xa680,
- 0xa682, 0xa682,
- 0xa684, 0xa684,
- 0xa686, 0xa686,
- 0xa688, 0xa688,
- 0xa68a, 0xa68a,
- 0xa68c, 0xa68c,
- 0xa68e, 0xa68e,
- 0xa690, 0xa690,
- 0xa692, 0xa692,
- 0xa694, 0xa694,
- 0xa696, 0xa696,
- 0xa698, 0xa698,
- 0xa69a, 0xa69a,
- 0xa722, 0xa722,
- 0xa724, 0xa724,
- 0xa726, 0xa726,
- 0xa728, 0xa728,
- 0xa72a, 0xa72a,
- 0xa72c, 0xa72c,
- 0xa72e, 0xa72e,
- 0xa732, 0xa732,
- 0xa734, 0xa734,
- 0xa736, 0xa736,
- 0xa738, 0xa738,
- 0xa73a, 0xa73a,
- 0xa73c, 0xa73c,
- 0xa73e, 0xa73e,
- 0xa740, 0xa740,
- 0xa742, 0xa742,
- 0xa744, 0xa744,
- 0xa746, 0xa746,
- 0xa748, 0xa748,
- 0xa74a, 0xa74a,
- 0xa74c, 0xa74c,
- 0xa74e, 0xa74e,
- 0xa750, 0xa750,
- 0xa752, 0xa752,
- 0xa754, 0xa754,
- 0xa756, 0xa756,
- 0xa758, 0xa758,
- 0xa75a, 0xa75a,
- 0xa75c, 0xa75c,
- 0xa75e, 0xa75e,
- 0xa760, 0xa760,
- 0xa762, 0xa762,
- 0xa764, 0xa764,
- 0xa766, 0xa766,
- 0xa768, 0xa768,
- 0xa76a, 0xa76a,
- 0xa76c, 0xa76c,
- 0xa76e, 0xa76e,
- 0xa779, 0xa779,
- 0xa77b, 0xa77b,
- 0xa77d, 0xa77e,
- 0xa780, 0xa780,
- 0xa782, 0xa782,
- 0xa784, 0xa784,
- 0xa786, 0xa786,
- 0xa78b, 0xa78b,
- 0xa78d, 0xa78d,
- 0xa790, 0xa790,
- 0xa792, 0xa792,
- 0xa796, 0xa796,
- 0xa798, 0xa798,
- 0xa79a, 0xa79a,
- 0xa79c, 0xa79c,
- 0xa79e, 0xa79e,
- 0xa7a0, 0xa7a0,
- 0xa7a2, 0xa7a2,
- 0xa7a4, 0xa7a4,
- 0xa7a6, 0xa7a6,
- 0xa7a8, 0xa7a8,
- 0xa7aa, 0xa7ae,
- 0xa7b0, 0xa7b4,
- 0xa7b6, 0xa7b6,
- 0xa7b8, 0xa7b8,
- 0xa7ba, 0xa7ba,
- 0xa7bc, 0xa7bc,
- 0xa7be, 0xa7be,
- 0xa7c0, 0xa7c0,
- 0xa7c2, 0xa7c2,
- 0xa7c4, 0xa7c7,
- 0xa7c9, 0xa7c9,
- 0xa7d0, 0xa7d0,
- 0xa7d6, 0xa7d6,
- 0xa7d8, 0xa7d8,
- 0xa7f5, 0xa7f5,
- 0xab70, 0xabbf,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xff21, 0xff3a,
- 0x10400, 0x10427,
- 0x104b0, 0x104d3,
- 0x10570, 0x1057a,
- 0x1057c, 0x1058a,
- 0x1058c, 0x10592,
- 0x10594, 0x10595,
- 0x10c80, 0x10cb2,
- 0x118a0, 0x118bf,
- 0x16e40, 0x16e5f,
- 0x1e900, 0x1e921,
-}; /* CR_Changes_When_Casefolded */
-
-/* 'Changes_When_Casemapped': Derived Property */
-static const OnigCodePoint CR_Changes_When_Casemapped[] = {
- 131,
- 0x0041, 0x005a,
- 0x0061, 0x007a,
- 0x00b5, 0x00b5,
- 0x00c0, 0x00d6,
- 0x00d8, 0x00f6,
- 0x00f8, 0x0137,
- 0x0139, 0x018c,
- 0x018e, 0x019a,
- 0x019c, 0x01a9,
- 0x01ac, 0x01b9,
- 0x01bc, 0x01bd,
- 0x01bf, 0x01bf,
- 0x01c4, 0x0220,
- 0x0222, 0x0233,
- 0x023a, 0x0254,
- 0x0256, 0x0257,
- 0x0259, 0x0259,
- 0x025b, 0x025c,
- 0x0260, 0x0261,
- 0x0263, 0x0263,
- 0x0265, 0x0266,
- 0x0268, 0x026c,
- 0x026f, 0x026f,
- 0x0271, 0x0272,
- 0x0275, 0x0275,
- 0x027d, 0x027d,
- 0x0280, 0x0280,
- 0x0282, 0x0283,
- 0x0287, 0x028c,
- 0x0292, 0x0292,
- 0x029d, 0x029e,
- 0x0345, 0x0345,
- 0x0370, 0x0373,
- 0x0376, 0x0377,
- 0x037b, 0x037d,
- 0x037f, 0x037f,
- 0x0386, 0x0386,
- 0x0388, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03d1,
- 0x03d5, 0x03f5,
- 0x03f7, 0x03fb,
- 0x03fd, 0x0481,
- 0x048a, 0x052f,
- 0x0531, 0x0556,
- 0x0561, 0x0587,
- 0x10a0, 0x10c5,
- 0x10c7, 0x10c7,
- 0x10cd, 0x10cd,
- 0x10d0, 0x10fa,
- 0x10fd, 0x10ff,
- 0x13a0, 0x13f5,
- 0x13f8, 0x13fd,
- 0x1c80, 0x1c88,
- 0x1c90, 0x1cba,
- 0x1cbd, 0x1cbf,
- 0x1d79, 0x1d79,
- 0x1d7d, 0x1d7d,
- 0x1d8e, 0x1d8e,
- 0x1e00, 0x1e9b,
- 0x1e9e, 0x1e9e,
- 0x1ea0, 0x1f15,
- 0x1f18, 0x1f1d,
- 0x1f20, 0x1f45,
- 0x1f48, 0x1f4d,
- 0x1f50, 0x1f57,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f7d,
- 0x1f80, 0x1fb4,
- 0x1fb6, 0x1fbc,
- 0x1fbe, 0x1fbe,
- 0x1fc2, 0x1fc4,
- 0x1fc6, 0x1fcc,
- 0x1fd0, 0x1fd3,
- 0x1fd6, 0x1fdb,
- 0x1fe0, 0x1fec,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ffc,
- 0x2126, 0x2126,
- 0x212a, 0x212b,
- 0x2132, 0x2132,
- 0x214e, 0x214e,
- 0x2160, 0x217f,
- 0x2183, 0x2184,
- 0x24b6, 0x24e9,
- 0x2c00, 0x2c70,
- 0x2c72, 0x2c73,
- 0x2c75, 0x2c76,
- 0x2c7e, 0x2ce3,
- 0x2ceb, 0x2cee,
- 0x2cf2, 0x2cf3,
- 0x2d00, 0x2d25,
- 0x2d27, 0x2d27,
- 0x2d2d, 0x2d2d,
- 0xa640, 0xa66d,
- 0xa680, 0xa69b,
- 0xa722, 0xa72f,
- 0xa732, 0xa76f,
- 0xa779, 0xa787,
- 0xa78b, 0xa78d,
- 0xa790, 0xa794,
- 0xa796, 0xa7ae,
- 0xa7b0, 0xa7ca,
- 0xa7d0, 0xa7d1,
- 0xa7d6, 0xa7d9,
- 0xa7f5, 0xa7f6,
- 0xab53, 0xab53,
- 0xab70, 0xabbf,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xff21, 0xff3a,
- 0xff41, 0xff5a,
- 0x10400, 0x1044f,
- 0x104b0, 0x104d3,
- 0x104d8, 0x104fb,
- 0x10570, 0x1057a,
- 0x1057c, 0x1058a,
- 0x1058c, 0x10592,
- 0x10594, 0x10595,
- 0x10597, 0x105a1,
- 0x105a3, 0x105b1,
- 0x105b3, 0x105b9,
- 0x105bb, 0x105bc,
- 0x10c80, 0x10cb2,
- 0x10cc0, 0x10cf2,
- 0x118a0, 0x118df,
- 0x16e40, 0x16e7f,
- 0x1e900, 0x1e943,
-}; /* CR_Changes_When_Casemapped */
-
-/* 'ID_Start': Derived Property */
-static const OnigCodePoint CR_ID_Start[] = {
- 659,
- 0x0041, 0x005a,
- 0x0061, 0x007a,
- 0x00aa, 0x00aa,
- 0x00b5, 0x00b5,
- 0x00ba, 0x00ba,
- 0x00c0, 0x00d6,
- 0x00d8, 0x00f6,
- 0x00f8, 0x02c1,
- 0x02c6, 0x02d1,
- 0x02e0, 0x02e4,
- 0x02ec, 0x02ec,
- 0x02ee, 0x02ee,
- 0x0370, 0x0374,
- 0x0376, 0x0377,
- 0x037a, 0x037d,
- 0x037f, 0x037f,
- 0x0386, 0x0386,
- 0x0388, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03f5,
- 0x03f7, 0x0481,
- 0x048a, 0x052f,
- 0x0531, 0x0556,
- 0x0559, 0x0559,
- 0x0560, 0x0588,
- 0x05d0, 0x05ea,
- 0x05ef, 0x05f2,
- 0x0620, 0x064a,
- 0x066e, 0x066f,
- 0x0671, 0x06d3,
- 0x06d5, 0x06d5,
- 0x06e5, 0x06e6,
- 0x06ee, 0x06ef,
- 0x06fa, 0x06fc,
- 0x06ff, 0x06ff,
- 0x0710, 0x0710,
- 0x0712, 0x072f,
- 0x074d, 0x07a5,
- 0x07b1, 0x07b1,
- 0x07ca, 0x07ea,
- 0x07f4, 0x07f5,
- 0x07fa, 0x07fa,
- 0x0800, 0x0815,
- 0x081a, 0x081a,
- 0x0824, 0x0824,
- 0x0828, 0x0828,
- 0x0840, 0x0858,
- 0x0860, 0x086a,
- 0x0870, 0x0887,
- 0x0889, 0x088e,
- 0x08a0, 0x08c9,
- 0x0904, 0x0939,
- 0x093d, 0x093d,
- 0x0950, 0x0950,
- 0x0958, 0x0961,
- 0x0971, 0x0980,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bd, 0x09bd,
- 0x09ce, 0x09ce,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e1,
- 0x09f0, 0x09f1,
- 0x09fc, 0x09fc,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a72, 0x0a74,
- 0x0a85, 0x0a8d,
- 0x0a8f, 0x0a91,
- 0x0a93, 0x0aa8,
- 0x0aaa, 0x0ab0,
- 0x0ab2, 0x0ab3,
- 0x0ab5, 0x0ab9,
- 0x0abd, 0x0abd,
- 0x0ad0, 0x0ad0,
- 0x0ae0, 0x0ae1,
- 0x0af9, 0x0af9,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b35, 0x0b39,
- 0x0b3d, 0x0b3d,
- 0x0b5c, 0x0b5d,
- 0x0b5f, 0x0b61,
- 0x0b71, 0x0b71,
- 0x0b83, 0x0b83,
- 0x0b85, 0x0b8a,
- 0x0b8e, 0x0b90,
- 0x0b92, 0x0b95,
- 0x0b99, 0x0b9a,
- 0x0b9c, 0x0b9c,
- 0x0b9e, 0x0b9f,
- 0x0ba3, 0x0ba4,
- 0x0ba8, 0x0baa,
- 0x0bae, 0x0bb9,
- 0x0bd0, 0x0bd0,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c39,
- 0x0c3d, 0x0c3d,
- 0x0c58, 0x0c5a,
- 0x0c5d, 0x0c5d,
- 0x0c60, 0x0c61,
- 0x0c80, 0x0c80,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbd, 0x0cbd,
- 0x0cdd, 0x0cde,
- 0x0ce0, 0x0ce1,
- 0x0cf1, 0x0cf2,
- 0x0d04, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d3a,
- 0x0d3d, 0x0d3d,
- 0x0d4e, 0x0d4e,
- 0x0d54, 0x0d56,
- 0x0d5f, 0x0d61,
- 0x0d7a, 0x0d7f,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0e01, 0x0e30,
- 0x0e32, 0x0e33,
- 0x0e40, 0x0e46,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e86, 0x0e8a,
- 0x0e8c, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0eb0,
- 0x0eb2, 0x0eb3,
- 0x0ebd, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f00,
- 0x0f40, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f88, 0x0f8c,
- 0x1000, 0x102a,
- 0x103f, 0x103f,
- 0x1050, 0x1055,
- 0x105a, 0x105d,
- 0x1061, 0x1061,
- 0x1065, 0x1066,
- 0x106e, 0x1070,
- 0x1075, 0x1081,
- 0x108e, 0x108e,
- 0x10a0, 0x10c5,
- 0x10c7, 0x10c7,
- 0x10cd, 0x10cd,
- 0x10d0, 0x10fa,
- 0x10fc, 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,
- 0x1380, 0x138f,
- 0x13a0, 0x13f5,
- 0x13f8, 0x13fd,
- 0x1401, 0x166c,
- 0x166f, 0x167f,
- 0x1681, 0x169a,
- 0x16a0, 0x16ea,
- 0x16ee, 0x16f8,
- 0x1700, 0x1711,
- 0x171f, 0x1731,
- 0x1740, 0x1751,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1780, 0x17b3,
- 0x17d7, 0x17d7,
- 0x17dc, 0x17dc,
- 0x1820, 0x1878,
- 0x1880, 0x18a8,
- 0x18aa, 0x18aa,
- 0x18b0, 0x18f5,
- 0x1900, 0x191e,
- 0x1950, 0x196d,
- 0x1970, 0x1974,
- 0x1980, 0x19ab,
- 0x19b0, 0x19c9,
- 0x1a00, 0x1a16,
- 0x1a20, 0x1a54,
- 0x1aa7, 0x1aa7,
- 0x1b05, 0x1b33,
- 0x1b45, 0x1b4c,
- 0x1b83, 0x1ba0,
- 0x1bae, 0x1baf,
- 0x1bba, 0x1be5,
- 0x1c00, 0x1c23,
- 0x1c4d, 0x1c4f,
- 0x1c5a, 0x1c7d,
- 0x1c80, 0x1c88,
- 0x1c90, 0x1cba,
- 0x1cbd, 0x1cbf,
- 0x1ce9, 0x1cec,
- 0x1cee, 0x1cf3,
- 0x1cf5, 0x1cf6,
- 0x1cfa, 0x1cfa,
- 0x1d00, 0x1dbf,
- 0x1e00, 0x1f15,
- 0x1f18, 0x1f1d,
- 0x1f20, 0x1f45,
- 0x1f48, 0x1f4d,
- 0x1f50, 0x1f57,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f7d,
- 0x1f80, 0x1fb4,
- 0x1fb6, 0x1fbc,
- 0x1fbe, 0x1fbe,
- 0x1fc2, 0x1fc4,
- 0x1fc6, 0x1fcc,
- 0x1fd0, 0x1fd3,
- 0x1fd6, 0x1fdb,
- 0x1fe0, 0x1fec,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ffc,
- 0x2071, 0x2071,
- 0x207f, 0x207f,
- 0x2090, 0x209c,
- 0x2102, 0x2102,
- 0x2107, 0x2107,
- 0x210a, 0x2113,
- 0x2115, 0x2115,
- 0x2118, 0x211d,
- 0x2124, 0x2124,
- 0x2126, 0x2126,
- 0x2128, 0x2128,
- 0x212a, 0x2139,
- 0x213c, 0x213f,
- 0x2145, 0x2149,
- 0x214e, 0x214e,
- 0x2160, 0x2188,
- 0x2c00, 0x2ce4,
- 0x2ceb, 0x2cee,
- 0x2cf2, 0x2cf3,
- 0x2d00, 0x2d25,
- 0x2d27, 0x2d27,
- 0x2d2d, 0x2d2d,
- 0x2d30, 0x2d67,
- 0x2d6f, 0x2d6f,
- 0x2d80, 0x2d96,
- 0x2da0, 0x2da6,
- 0x2da8, 0x2dae,
- 0x2db0, 0x2db6,
- 0x2db8, 0x2dbe,
- 0x2dc0, 0x2dc6,
- 0x2dc8, 0x2dce,
- 0x2dd0, 0x2dd6,
- 0x2dd8, 0x2dde,
- 0x3005, 0x3007,
- 0x3021, 0x3029,
- 0x3031, 0x3035,
- 0x3038, 0x303c,
- 0x3041, 0x3096,
- 0x309b, 0x309f,
- 0x30a1, 0x30fa,
- 0x30fc, 0x30ff,
- 0x3105, 0x312f,
- 0x3131, 0x318e,
- 0x31a0, 0x31bf,
- 0x31f0, 0x31ff,
- 0x3400, 0x4dbf,
- 0x4e00, 0xa48c,
- 0xa4d0, 0xa4fd,
- 0xa500, 0xa60c,
- 0xa610, 0xa61f,
- 0xa62a, 0xa62b,
- 0xa640, 0xa66e,
- 0xa67f, 0xa69d,
- 0xa6a0, 0xa6ef,
- 0xa717, 0xa71f,
- 0xa722, 0xa788,
- 0xa78b, 0xa7ca,
- 0xa7d0, 0xa7d1,
- 0xa7d3, 0xa7d3,
- 0xa7d5, 0xa7d9,
- 0xa7f2, 0xa801,
- 0xa803, 0xa805,
- 0xa807, 0xa80a,
- 0xa80c, 0xa822,
- 0xa840, 0xa873,
- 0xa882, 0xa8b3,
- 0xa8f2, 0xa8f7,
- 0xa8fb, 0xa8fb,
- 0xa8fd, 0xa8fe,
- 0xa90a, 0xa925,
- 0xa930, 0xa946,
- 0xa960, 0xa97c,
- 0xa984, 0xa9b2,
- 0xa9cf, 0xa9cf,
- 0xa9e0, 0xa9e4,
- 0xa9e6, 0xa9ef,
- 0xa9fa, 0xa9fe,
- 0xaa00, 0xaa28,
- 0xaa40, 0xaa42,
- 0xaa44, 0xaa4b,
- 0xaa60, 0xaa76,
- 0xaa7a, 0xaa7a,
- 0xaa7e, 0xaaaf,
- 0xaab1, 0xaab1,
- 0xaab5, 0xaab6,
- 0xaab9, 0xaabd,
- 0xaac0, 0xaac0,
- 0xaac2, 0xaac2,
- 0xaadb, 0xaadd,
- 0xaae0, 0xaaea,
- 0xaaf2, 0xaaf4,
- 0xab01, 0xab06,
- 0xab09, 0xab0e,
- 0xab11, 0xab16,
- 0xab20, 0xab26,
- 0xab28, 0xab2e,
- 0xab30, 0xab5a,
- 0xab5c, 0xab69,
- 0xab70, 0xabe2,
- 0xac00, 0xd7a3,
- 0xd7b0, 0xd7c6,
- 0xd7cb, 0xd7fb,
- 0xf900, 0xfa6d,
- 0xfa70, 0xfad9,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1d, 0xfb1d,
- 0xfb1f, 0xfb28,
- 0xfb2a, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbb1,
- 0xfbd3, 0xfd3d,
- 0xfd50, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdf0, 0xfdfb,
- 0xfe70, 0xfe74,
- 0xfe76, 0xfefc,
- 0xff21, 0xff3a,
- 0xff41, 0xff5a,
- 0xff66, 0xffbe,
- 0xffc2, 0xffc7,
- 0xffca, 0xffcf,
- 0xffd2, 0xffd7,
- 0xffda, 0xffdc,
- 0x10000, 0x1000b,
- 0x1000d, 0x10026,
- 0x10028, 0x1003a,
- 0x1003c, 0x1003d,
- 0x1003f, 0x1004d,
- 0x10050, 0x1005d,
- 0x10080, 0x100fa,
- 0x10140, 0x10174,
- 0x10280, 0x1029c,
- 0x102a0, 0x102d0,
- 0x10300, 0x1031f,
- 0x1032d, 0x1034a,
- 0x10350, 0x10375,
- 0x10380, 0x1039d,
- 0x103a0, 0x103c3,
- 0x103c8, 0x103cf,
- 0x103d1, 0x103d5,
- 0x10400, 0x1049d,
- 0x104b0, 0x104d3,
- 0x104d8, 0x104fb,
- 0x10500, 0x10527,
- 0x10530, 0x10563,
- 0x10570, 0x1057a,
- 0x1057c, 0x1058a,
- 0x1058c, 0x10592,
- 0x10594, 0x10595,
- 0x10597, 0x105a1,
- 0x105a3, 0x105b1,
- 0x105b3, 0x105b9,
- 0x105bb, 0x105bc,
- 0x10600, 0x10736,
- 0x10740, 0x10755,
- 0x10760, 0x10767,
- 0x10780, 0x10785,
- 0x10787, 0x107b0,
- 0x107b2, 0x107ba,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x10855,
- 0x10860, 0x10876,
- 0x10880, 0x1089e,
- 0x108e0, 0x108f2,
- 0x108f4, 0x108f5,
- 0x10900, 0x10915,
- 0x10920, 0x10939,
- 0x10980, 0x109b7,
- 0x109be, 0x109bf,
- 0x10a00, 0x10a00,
- 0x10a10, 0x10a13,
- 0x10a15, 0x10a17,
- 0x10a19, 0x10a35,
- 0x10a60, 0x10a7c,
- 0x10a80, 0x10a9c,
- 0x10ac0, 0x10ac7,
- 0x10ac9, 0x10ae4,
- 0x10b00, 0x10b35,
- 0x10b40, 0x10b55,
- 0x10b60, 0x10b72,
- 0x10b80, 0x10b91,
- 0x10c00, 0x10c48,
- 0x10c80, 0x10cb2,
- 0x10cc0, 0x10cf2,
- 0x10d00, 0x10d23,
- 0x10e80, 0x10ea9,
- 0x10eb0, 0x10eb1,
- 0x10f00, 0x10f1c,
- 0x10f27, 0x10f27,
- 0x10f30, 0x10f45,
- 0x10f70, 0x10f81,
- 0x10fb0, 0x10fc4,
- 0x10fe0, 0x10ff6,
- 0x11003, 0x11037,
- 0x11071, 0x11072,
- 0x11075, 0x11075,
- 0x11083, 0x110af,
- 0x110d0, 0x110e8,
- 0x11103, 0x11126,
- 0x11144, 0x11144,
- 0x11147, 0x11147,
- 0x11150, 0x11172,
- 0x11176, 0x11176,
- 0x11183, 0x111b2,
- 0x111c1, 0x111c4,
- 0x111da, 0x111da,
- 0x111dc, 0x111dc,
- 0x11200, 0x11211,
- 0x11213, 0x1122b,
- 0x1123f, 0x11240,
- 0x11280, 0x11286,
- 0x11288, 0x11288,
- 0x1128a, 0x1128d,
- 0x1128f, 0x1129d,
- 0x1129f, 0x112a8,
- 0x112b0, 0x112de,
- 0x11305, 0x1130c,
- 0x1130f, 0x11310,
- 0x11313, 0x11328,
- 0x1132a, 0x11330,
- 0x11332, 0x11333,
- 0x11335, 0x11339,
- 0x1133d, 0x1133d,
- 0x11350, 0x11350,
- 0x1135d, 0x11361,
- 0x11400, 0x11434,
- 0x11447, 0x1144a,
- 0x1145f, 0x11461,
- 0x11480, 0x114af,
- 0x114c4, 0x114c5,
- 0x114c7, 0x114c7,
- 0x11580, 0x115ae,
- 0x115d8, 0x115db,
- 0x11600, 0x1162f,
- 0x11644, 0x11644,
- 0x11680, 0x116aa,
- 0x116b8, 0x116b8,
- 0x11700, 0x1171a,
- 0x11740, 0x11746,
- 0x11800, 0x1182b,
- 0x118a0, 0x118df,
- 0x118ff, 0x11906,
- 0x11909, 0x11909,
- 0x1190c, 0x11913,
- 0x11915, 0x11916,
- 0x11918, 0x1192f,
- 0x1193f, 0x1193f,
- 0x11941, 0x11941,
- 0x119a0, 0x119a7,
- 0x119aa, 0x119d0,
- 0x119e1, 0x119e1,
- 0x119e3, 0x119e3,
- 0x11a00, 0x11a00,
- 0x11a0b, 0x11a32,
- 0x11a3a, 0x11a3a,
- 0x11a50, 0x11a50,
- 0x11a5c, 0x11a89,
- 0x11a9d, 0x11a9d,
- 0x11ab0, 0x11af8,
- 0x11c00, 0x11c08,
- 0x11c0a, 0x11c2e,
- 0x11c40, 0x11c40,
- 0x11c72, 0x11c8f,
- 0x11d00, 0x11d06,
- 0x11d08, 0x11d09,
- 0x11d0b, 0x11d30,
- 0x11d46, 0x11d46,
- 0x11d60, 0x11d65,
- 0x11d67, 0x11d68,
- 0x11d6a, 0x11d89,
- 0x11d98, 0x11d98,
- 0x11ee0, 0x11ef2,
- 0x11f02, 0x11f02,
- 0x11f04, 0x11f10,
- 0x11f12, 0x11f33,
- 0x11fb0, 0x11fb0,
- 0x12000, 0x12399,
- 0x12400, 0x1246e,
- 0x12480, 0x12543,
- 0x12f90, 0x12ff0,
- 0x13000, 0x1342f,
- 0x13441, 0x13446,
- 0x14400, 0x14646,
- 0x16800, 0x16a38,
- 0x16a40, 0x16a5e,
- 0x16a70, 0x16abe,
- 0x16ad0, 0x16aed,
- 0x16b00, 0x16b2f,
- 0x16b40, 0x16b43,
- 0x16b63, 0x16b77,
- 0x16b7d, 0x16b8f,
- 0x16e40, 0x16e7f,
- 0x16f00, 0x16f4a,
- 0x16f50, 0x16f50,
- 0x16f93, 0x16f9f,
- 0x16fe0, 0x16fe1,
- 0x16fe3, 0x16fe3,
- 0x17000, 0x187f7,
- 0x18800, 0x18cd5,
- 0x18d00, 0x18d08,
- 0x1aff0, 0x1aff3,
- 0x1aff5, 0x1affb,
- 0x1affd, 0x1affe,
- 0x1b000, 0x1b122,
- 0x1b132, 0x1b132,
- 0x1b150, 0x1b152,
- 0x1b155, 0x1b155,
- 0x1b164, 0x1b167,
- 0x1b170, 0x1b2fb,
- 0x1bc00, 0x1bc6a,
- 0x1bc70, 0x1bc7c,
- 0x1bc80, 0x1bc88,
- 0x1bc90, 0x1bc99,
- 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, 0x1d6c0,
- 0x1d6c2, 0x1d6da,
- 0x1d6dc, 0x1d6fa,
- 0x1d6fc, 0x1d714,
- 0x1d716, 0x1d734,
- 0x1d736, 0x1d74e,
- 0x1d750, 0x1d76e,
- 0x1d770, 0x1d788,
- 0x1d78a, 0x1d7a8,
- 0x1d7aa, 0x1d7c2,
- 0x1d7c4, 0x1d7cb,
- 0x1df00, 0x1df1e,
- 0x1df25, 0x1df2a,
- 0x1e030, 0x1e06d,
- 0x1e100, 0x1e12c,
- 0x1e137, 0x1e13d,
- 0x1e14e, 0x1e14e,
- 0x1e290, 0x1e2ad,
- 0x1e2c0, 0x1e2eb,
- 0x1e4d0, 0x1e4eb,
- 0x1e7e0, 0x1e7e6,
- 0x1e7e8, 0x1e7eb,
- 0x1e7ed, 0x1e7ee,
- 0x1e7f0, 0x1e7fe,
- 0x1e800, 0x1e8c4,
- 0x1e900, 0x1e943,
- 0x1e94b, 0x1e94b,
- 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,
- 0x20000, 0x2a6df,
- 0x2a700, 0x2b739,
- 0x2b740, 0x2b81d,
- 0x2b820, 0x2cea1,
- 0x2ceb0, 0x2ebe0,
- 0x2f800, 0x2fa1d,
- 0x30000, 0x3134a,
- 0x31350, 0x323af,
-}; /* CR_ID_Start */
-
-/* 'ID_Continue': Derived Property */
-static const OnigCodePoint CR_ID_Continue[] = {
- 768,
- 0x0030, 0x0039,
- 0x0041, 0x005a,
- 0x005f, 0x005f,
- 0x0061, 0x007a,
- 0x00aa, 0x00aa,
- 0x00b5, 0x00b5,
- 0x00b7, 0x00b7,
- 0x00ba, 0x00ba,
- 0x00c0, 0x00d6,
- 0x00d8, 0x00f6,
- 0x00f8, 0x02c1,
- 0x02c6, 0x02d1,
- 0x02e0, 0x02e4,
- 0x02ec, 0x02ec,
- 0x02ee, 0x02ee,
- 0x0300, 0x0374,
- 0x0376, 0x0377,
- 0x037a, 0x037d,
- 0x037f, 0x037f,
- 0x0386, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03f5,
- 0x03f7, 0x0481,
- 0x0483, 0x0487,
- 0x048a, 0x052f,
- 0x0531, 0x0556,
- 0x0559, 0x0559,
- 0x0560, 0x0588,
- 0x0591, 0x05bd,
- 0x05bf, 0x05bf,
- 0x05c1, 0x05c2,
- 0x05c4, 0x05c5,
- 0x05c7, 0x05c7,
- 0x05d0, 0x05ea,
- 0x05ef, 0x05f2,
- 0x0610, 0x061a,
- 0x0620, 0x0669,
- 0x066e, 0x06d3,
- 0x06d5, 0x06dc,
- 0x06df, 0x06e8,
- 0x06ea, 0x06fc,
- 0x06ff, 0x06ff,
- 0x0710, 0x074a,
- 0x074d, 0x07b1,
- 0x07c0, 0x07f5,
- 0x07fa, 0x07fa,
- 0x07fd, 0x07fd,
- 0x0800, 0x082d,
- 0x0840, 0x085b,
- 0x0860, 0x086a,
- 0x0870, 0x0887,
- 0x0889, 0x088e,
- 0x0898, 0x08e1,
- 0x08e3, 0x0963,
- 0x0966, 0x096f,
- 0x0971, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09f1,
- 0x09fc, 0x09fc,
- 0x09fe, 0x09fe,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a51, 0x0a51,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a75,
- 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, 0x0aef,
- 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, 0x0b6f,
- 0x0b71, 0x0b71,
- 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,
- 0x0be6, 0x0bef,
- 0x0c00, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c39,
- 0x0c3c, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c58, 0x0c5a,
- 0x0c5d, 0x0c5d,
- 0x0c60, 0x0c63,
- 0x0c66, 0x0c6f,
- 0x0c80, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cdd, 0x0cde,
- 0x0ce0, 0x0ce3,
- 0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf3,
- 0x0d00, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d44,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4e,
- 0x0d54, 0x0d57,
- 0x0d5f, 0x0d63,
- 0x0d66, 0x0d6f,
- 0x0d7a, 0x0d7f,
- 0x0d81, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0de6, 0x0def,
- 0x0df2, 0x0df3,
- 0x0e01, 0x0e3a,
- 0x0e40, 0x0e4e,
- 0x0e50, 0x0e59,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e86, 0x0e8a,
- 0x0e8c, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ece,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f00,
- 0x0f18, 0x0f19,
- 0x0f20, 0x0f29,
- 0x0f35, 0x0f35,
- 0x0f37, 0x0f37,
- 0x0f39, 0x0f39,
- 0x0f3e, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f71, 0x0f84,
- 0x0f86, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x0fc6, 0x0fc6,
- 0x1000, 0x1049,
- 0x1050, 0x109d,
- 0x10a0, 0x10c5,
- 0x10c7, 0x10c7,
- 0x10cd, 0x10cd,
- 0x10d0, 0x10fa,
- 0x10fc, 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, 0x135f,
- 0x1369, 0x1371,
- 0x1380, 0x138f,
- 0x13a0, 0x13f5,
- 0x13f8, 0x13fd,
- 0x1401, 0x166c,
- 0x166f, 0x167f,
- 0x1681, 0x169a,
- 0x16a0, 0x16ea,
- 0x16ee, 0x16f8,
- 0x1700, 0x1715,
- 0x171f, 0x1734,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17d3,
- 0x17d7, 0x17d7,
- 0x17dc, 0x17dd,
- 0x17e0, 0x17e9,
- 0x180b, 0x180d,
- 0x180f, 0x1819,
- 0x1820, 0x1878,
- 0x1880, 0x18aa,
- 0x18b0, 0x18f5,
- 0x1900, 0x191e,
- 0x1920, 0x192b,
- 0x1930, 0x193b,
- 0x1946, 0x196d,
- 0x1970, 0x1974,
- 0x1980, 0x19ab,
- 0x19b0, 0x19c9,
- 0x19d0, 0x19da,
- 0x1a00, 0x1a1b,
- 0x1a20, 0x1a5e,
- 0x1a60, 0x1a7c,
- 0x1a7f, 0x1a89,
- 0x1a90, 0x1a99,
- 0x1aa7, 0x1aa7,
- 0x1ab0, 0x1abd,
- 0x1abf, 0x1ace,
- 0x1b00, 0x1b4c,
- 0x1b50, 0x1b59,
- 0x1b6b, 0x1b73,
- 0x1b80, 0x1bf3,
- 0x1c00, 0x1c37,
- 0x1c40, 0x1c49,
- 0x1c4d, 0x1c7d,
- 0x1c80, 0x1c88,
- 0x1c90, 0x1cba,
- 0x1cbd, 0x1cbf,
- 0x1cd0, 0x1cd2,
- 0x1cd4, 0x1cfa,
- 0x1d00, 0x1f15,
- 0x1f18, 0x1f1d,
- 0x1f20, 0x1f45,
- 0x1f48, 0x1f4d,
- 0x1f50, 0x1f57,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f7d,
- 0x1f80, 0x1fb4,
- 0x1fb6, 0x1fbc,
- 0x1fbe, 0x1fbe,
- 0x1fc2, 0x1fc4,
- 0x1fc6, 0x1fcc,
- 0x1fd0, 0x1fd3,
- 0x1fd6, 0x1fdb,
- 0x1fe0, 0x1fec,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ffc,
- 0x203f, 0x2040,
- 0x2054, 0x2054,
- 0x2071, 0x2071,
- 0x207f, 0x207f,
- 0x2090, 0x209c,
- 0x20d0, 0x20dc,
- 0x20e1, 0x20e1,
- 0x20e5, 0x20f0,
- 0x2102, 0x2102,
- 0x2107, 0x2107,
- 0x210a, 0x2113,
- 0x2115, 0x2115,
- 0x2118, 0x211d,
- 0x2124, 0x2124,
- 0x2126, 0x2126,
- 0x2128, 0x2128,
- 0x212a, 0x2139,
- 0x213c, 0x213f,
- 0x2145, 0x2149,
- 0x214e, 0x214e,
- 0x2160, 0x2188,
- 0x2c00, 0x2ce4,
- 0x2ceb, 0x2cf3,
- 0x2d00, 0x2d25,
- 0x2d27, 0x2d27,
- 0x2d2d, 0x2d2d,
- 0x2d30, 0x2d67,
- 0x2d6f, 0x2d6f,
- 0x2d7f, 0x2d96,
- 0x2da0, 0x2da6,
- 0x2da8, 0x2dae,
- 0x2db0, 0x2db6,
- 0x2db8, 0x2dbe,
- 0x2dc0, 0x2dc6,
- 0x2dc8, 0x2dce,
- 0x2dd0, 0x2dd6,
- 0x2dd8, 0x2dde,
- 0x2de0, 0x2dff,
- 0x3005, 0x3007,
- 0x3021, 0x302f,
- 0x3031, 0x3035,
- 0x3038, 0x303c,
- 0x3041, 0x3096,
- 0x3099, 0x309f,
- 0x30a1, 0x30fa,
- 0x30fc, 0x30ff,
- 0x3105, 0x312f,
- 0x3131, 0x318e,
- 0x31a0, 0x31bf,
- 0x31f0, 0x31ff,
- 0x3400, 0x4dbf,
- 0x4e00, 0xa48c,
- 0xa4d0, 0xa4fd,
- 0xa500, 0xa60c,
- 0xa610, 0xa62b,
- 0xa640, 0xa66f,
- 0xa674, 0xa67d,
- 0xa67f, 0xa6f1,
- 0xa717, 0xa71f,
- 0xa722, 0xa788,
- 0xa78b, 0xa7ca,
- 0xa7d0, 0xa7d1,
- 0xa7d3, 0xa7d3,
- 0xa7d5, 0xa7d9,
- 0xa7f2, 0xa827,
- 0xa82c, 0xa82c,
- 0xa840, 0xa873,
- 0xa880, 0xa8c5,
- 0xa8d0, 0xa8d9,
- 0xa8e0, 0xa8f7,
- 0xa8fb, 0xa8fb,
- 0xa8fd, 0xa92d,
- 0xa930, 0xa953,
- 0xa960, 0xa97c,
- 0xa980, 0xa9c0,
- 0xa9cf, 0xa9d9,
- 0xa9e0, 0xa9fe,
- 0xaa00, 0xaa36,
- 0xaa40, 0xaa4d,
- 0xaa50, 0xaa59,
- 0xaa60, 0xaa76,
- 0xaa7a, 0xaac2,
- 0xaadb, 0xaadd,
- 0xaae0, 0xaaef,
- 0xaaf2, 0xaaf6,
- 0xab01, 0xab06,
- 0xab09, 0xab0e,
- 0xab11, 0xab16,
- 0xab20, 0xab26,
- 0xab28, 0xab2e,
- 0xab30, 0xab5a,
- 0xab5c, 0xab69,
- 0xab70, 0xabea,
- 0xabec, 0xabed,
- 0xabf0, 0xabf9,
- 0xac00, 0xd7a3,
- 0xd7b0, 0xd7c6,
- 0xd7cb, 0xd7fb,
- 0xf900, 0xfa6d,
- 0xfa70, 0xfad9,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1d, 0xfb28,
- 0xfb2a, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbb1,
- 0xfbd3, 0xfd3d,
- 0xfd50, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdf0, 0xfdfb,
- 0xfe00, 0xfe0f,
- 0xfe20, 0xfe2f,
- 0xfe33, 0xfe34,
- 0xfe4d, 0xfe4f,
- 0xfe70, 0xfe74,
- 0xfe76, 0xfefc,
- 0xff10, 0xff19,
- 0xff21, 0xff3a,
- 0xff3f, 0xff3f,
- 0xff41, 0xff5a,
- 0xff66, 0xffbe,
- 0xffc2, 0xffc7,
- 0xffca, 0xffcf,
- 0xffd2, 0xffd7,
- 0xffda, 0xffdc,
- 0x10000, 0x1000b,
- 0x1000d, 0x10026,
- 0x10028, 0x1003a,
- 0x1003c, 0x1003d,
- 0x1003f, 0x1004d,
- 0x10050, 0x1005d,
- 0x10080, 0x100fa,
- 0x10140, 0x10174,
- 0x101fd, 0x101fd,
- 0x10280, 0x1029c,
- 0x102a0, 0x102d0,
- 0x102e0, 0x102e0,
- 0x10300, 0x1031f,
- 0x1032d, 0x1034a,
- 0x10350, 0x1037a,
- 0x10380, 0x1039d,
- 0x103a0, 0x103c3,
- 0x103c8, 0x103cf,
- 0x103d1, 0x103d5,
- 0x10400, 0x1049d,
- 0x104a0, 0x104a9,
- 0x104b0, 0x104d3,
- 0x104d8, 0x104fb,
- 0x10500, 0x10527,
- 0x10530, 0x10563,
- 0x10570, 0x1057a,
- 0x1057c, 0x1058a,
- 0x1058c, 0x10592,
- 0x10594, 0x10595,
- 0x10597, 0x105a1,
- 0x105a3, 0x105b1,
- 0x105b3, 0x105b9,
- 0x105bb, 0x105bc,
- 0x10600, 0x10736,
- 0x10740, 0x10755,
- 0x10760, 0x10767,
- 0x10780, 0x10785,
- 0x10787, 0x107b0,
- 0x107b2, 0x107ba,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x10855,
- 0x10860, 0x10876,
- 0x10880, 0x1089e,
- 0x108e0, 0x108f2,
- 0x108f4, 0x108f5,
- 0x10900, 0x10915,
- 0x10920, 0x10939,
- 0x10980, 0x109b7,
- 0x109be, 0x109bf,
- 0x10a00, 0x10a03,
- 0x10a05, 0x10a06,
- 0x10a0c, 0x10a13,
- 0x10a15, 0x10a17,
- 0x10a19, 0x10a35,
- 0x10a38, 0x10a3a,
- 0x10a3f, 0x10a3f,
- 0x10a60, 0x10a7c,
- 0x10a80, 0x10a9c,
- 0x10ac0, 0x10ac7,
- 0x10ac9, 0x10ae6,
- 0x10b00, 0x10b35,
- 0x10b40, 0x10b55,
- 0x10b60, 0x10b72,
- 0x10b80, 0x10b91,
- 0x10c00, 0x10c48,
- 0x10c80, 0x10cb2,
- 0x10cc0, 0x10cf2,
- 0x10d00, 0x10d27,
- 0x10d30, 0x10d39,
- 0x10e80, 0x10ea9,
- 0x10eab, 0x10eac,
- 0x10eb0, 0x10eb1,
- 0x10efd, 0x10f1c,
- 0x10f27, 0x10f27,
- 0x10f30, 0x10f50,
- 0x10f70, 0x10f85,
- 0x10fb0, 0x10fc4,
- 0x10fe0, 0x10ff6,
- 0x11000, 0x11046,
- 0x11066, 0x11075,
- 0x1107f, 0x110ba,
- 0x110c2, 0x110c2,
- 0x110d0, 0x110e8,
- 0x110f0, 0x110f9,
- 0x11100, 0x11134,
- 0x11136, 0x1113f,
- 0x11144, 0x11147,
- 0x11150, 0x11173,
- 0x11176, 0x11176,
- 0x11180, 0x111c4,
- 0x111c9, 0x111cc,
- 0x111ce, 0x111da,
- 0x111dc, 0x111dc,
- 0x11200, 0x11211,
- 0x11213, 0x11237,
- 0x1123e, 0x11241,
- 0x11280, 0x11286,
- 0x11288, 0x11288,
- 0x1128a, 0x1128d,
- 0x1128f, 0x1129d,
- 0x1129f, 0x112a8,
- 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, 0x1144a,
- 0x11450, 0x11459,
- 0x1145e, 0x11461,
- 0x11480, 0x114c5,
- 0x114c7, 0x114c7,
- 0x114d0, 0x114d9,
- 0x11580, 0x115b5,
- 0x115b8, 0x115c0,
- 0x115d8, 0x115dd,
- 0x11600, 0x11640,
- 0x11644, 0x11644,
- 0x11650, 0x11659,
- 0x11680, 0x116b8,
- 0x116c0, 0x116c9,
- 0x11700, 0x1171a,
- 0x1171d, 0x1172b,
- 0x11730, 0x11739,
- 0x11740, 0x11746,
- 0x11800, 0x1183a,
- 0x118a0, 0x118e9,
- 0x118ff, 0x11906,
- 0x11909, 0x11909,
- 0x1190c, 0x11913,
- 0x11915, 0x11916,
- 0x11918, 0x11935,
- 0x11937, 0x11938,
- 0x1193b, 0x11943,
- 0x11950, 0x11959,
- 0x119a0, 0x119a7,
- 0x119aa, 0x119d7,
- 0x119da, 0x119e1,
- 0x119e3, 0x119e4,
- 0x11a00, 0x11a3e,
- 0x11a47, 0x11a47,
- 0x11a50, 0x11a99,
- 0x11a9d, 0x11a9d,
- 0x11ab0, 0x11af8,
- 0x11c00, 0x11c08,
- 0x11c0a, 0x11c36,
- 0x11c38, 0x11c40,
- 0x11c50, 0x11c59,
- 0x11c72, 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, 0x11ef6,
- 0x11f00, 0x11f10,
- 0x11f12, 0x11f3a,
- 0x11f3e, 0x11f42,
- 0x11f50, 0x11f59,
- 0x11fb0, 0x11fb0,
- 0x12000, 0x12399,
- 0x12400, 0x1246e,
- 0x12480, 0x12543,
- 0x12f90, 0x12ff0,
- 0x13000, 0x1342f,
- 0x13440, 0x13455,
- 0x14400, 0x14646,
- 0x16800, 0x16a38,
- 0x16a40, 0x16a5e,
- 0x16a60, 0x16a69,
- 0x16a70, 0x16abe,
- 0x16ac0, 0x16ac9,
- 0x16ad0, 0x16aed,
- 0x16af0, 0x16af4,
- 0x16b00, 0x16b36,
- 0x16b40, 0x16b43,
- 0x16b50, 0x16b59,
- 0x16b63, 0x16b77,
- 0x16b7d, 0x16b8f,
- 0x16e40, 0x16e7f,
- 0x16f00, 0x16f4a,
- 0x16f4f, 0x16f87,
- 0x16f8f, 0x16f9f,
- 0x16fe0, 0x16fe1,
- 0x16fe3, 0x16fe4,
- 0x16ff0, 0x16ff1,
- 0x17000, 0x187f7,
- 0x18800, 0x18cd5,
- 0x18d00, 0x18d08,
- 0x1aff0, 0x1aff3,
- 0x1aff5, 0x1affb,
- 0x1affd, 0x1affe,
- 0x1b000, 0x1b122,
- 0x1b132, 0x1b132,
- 0x1b150, 0x1b152,
- 0x1b155, 0x1b155,
- 0x1b164, 0x1b167,
- 0x1b170, 0x1b2fb,
- 0x1bc00, 0x1bc6a,
- 0x1bc70, 0x1bc7c,
- 0x1bc80, 0x1bc88,
- 0x1bc90, 0x1bc99,
- 0x1bc9d, 0x1bc9e,
- 0x1cf00, 0x1cf2d,
- 0x1cf30, 0x1cf46,
- 0x1d165, 0x1d169,
- 0x1d16d, 0x1d172,
- 0x1d17b, 0x1d182,
- 0x1d185, 0x1d18b,
- 0x1d1aa, 0x1d1ad,
- 0x1d242, 0x1d244,
- 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, 0x1d6c0,
- 0x1d6c2, 0x1d6da,
- 0x1d6dc, 0x1d6fa,
- 0x1d6fc, 0x1d714,
- 0x1d716, 0x1d734,
- 0x1d736, 0x1d74e,
- 0x1d750, 0x1d76e,
- 0x1d770, 0x1d788,
- 0x1d78a, 0x1d7a8,
- 0x1d7aa, 0x1d7c2,
- 0x1d7c4, 0x1d7cb,
- 0x1d7ce, 0x1d7ff,
- 0x1da00, 0x1da36,
- 0x1da3b, 0x1da6c,
- 0x1da75, 0x1da75,
- 0x1da84, 0x1da84,
- 0x1da9b, 0x1da9f,
- 0x1daa1, 0x1daaf,
- 0x1df00, 0x1df1e,
- 0x1df25, 0x1df2a,
- 0x1e000, 0x1e006,
- 0x1e008, 0x1e018,
- 0x1e01b, 0x1e021,
- 0x1e023, 0x1e024,
- 0x1e026, 0x1e02a,
- 0x1e030, 0x1e06d,
- 0x1e08f, 0x1e08f,
- 0x1e100, 0x1e12c,
- 0x1e130, 0x1e13d,
- 0x1e140, 0x1e149,
- 0x1e14e, 0x1e14e,
- 0x1e290, 0x1e2ae,
- 0x1e2c0, 0x1e2f9,
- 0x1e4d0, 0x1e4f9,
- 0x1e7e0, 0x1e7e6,
- 0x1e7e8, 0x1e7eb,
- 0x1e7ed, 0x1e7ee,
- 0x1e7f0, 0x1e7fe,
- 0x1e800, 0x1e8c4,
- 0x1e8d0, 0x1e8d6,
- 0x1e900, 0x1e94b,
- 0x1e950, 0x1e959,
- 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,
- 0x1fbf0, 0x1fbf9,
- 0x20000, 0x2a6df,
- 0x2a700, 0x2b739,
- 0x2b740, 0x2b81d,
- 0x2b820, 0x2cea1,
- 0x2ceb0, 0x2ebe0,
- 0x2f800, 0x2fa1d,
- 0x30000, 0x3134a,
- 0x31350, 0x323af,
- 0xe0100, 0xe01ef,
-}; /* CR_ID_Continue */
-
-/* 'XID_Start': Derived Property */
-static const OnigCodePoint CR_XID_Start[] = {
- 666,
- 0x0041, 0x005a,
- 0x0061, 0x007a,
- 0x00aa, 0x00aa,
- 0x00b5, 0x00b5,
- 0x00ba, 0x00ba,
- 0x00c0, 0x00d6,
- 0x00d8, 0x00f6,
- 0x00f8, 0x02c1,
- 0x02c6, 0x02d1,
- 0x02e0, 0x02e4,
- 0x02ec, 0x02ec,
- 0x02ee, 0x02ee,
- 0x0370, 0x0374,
- 0x0376, 0x0377,
- 0x037b, 0x037d,
- 0x037f, 0x037f,
- 0x0386, 0x0386,
- 0x0388, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03f5,
- 0x03f7, 0x0481,
- 0x048a, 0x052f,
- 0x0531, 0x0556,
- 0x0559, 0x0559,
- 0x0560, 0x0588,
- 0x05d0, 0x05ea,
- 0x05ef, 0x05f2,
- 0x0620, 0x064a,
- 0x066e, 0x066f,
- 0x0671, 0x06d3,
- 0x06d5, 0x06d5,
- 0x06e5, 0x06e6,
- 0x06ee, 0x06ef,
- 0x06fa, 0x06fc,
- 0x06ff, 0x06ff,
- 0x0710, 0x0710,
- 0x0712, 0x072f,
- 0x074d, 0x07a5,
- 0x07b1, 0x07b1,
- 0x07ca, 0x07ea,
- 0x07f4, 0x07f5,
- 0x07fa, 0x07fa,
- 0x0800, 0x0815,
- 0x081a, 0x081a,
- 0x0824, 0x0824,
- 0x0828, 0x0828,
- 0x0840, 0x0858,
- 0x0860, 0x086a,
- 0x0870, 0x0887,
- 0x0889, 0x088e,
- 0x08a0, 0x08c9,
- 0x0904, 0x0939,
- 0x093d, 0x093d,
- 0x0950, 0x0950,
- 0x0958, 0x0961,
- 0x0971, 0x0980,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bd, 0x09bd,
- 0x09ce, 0x09ce,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e1,
- 0x09f0, 0x09f1,
- 0x09fc, 0x09fc,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a72, 0x0a74,
- 0x0a85, 0x0a8d,
- 0x0a8f, 0x0a91,
- 0x0a93, 0x0aa8,
- 0x0aaa, 0x0ab0,
- 0x0ab2, 0x0ab3,
- 0x0ab5, 0x0ab9,
- 0x0abd, 0x0abd,
- 0x0ad0, 0x0ad0,
- 0x0ae0, 0x0ae1,
- 0x0af9, 0x0af9,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b35, 0x0b39,
- 0x0b3d, 0x0b3d,
- 0x0b5c, 0x0b5d,
- 0x0b5f, 0x0b61,
- 0x0b71, 0x0b71,
- 0x0b83, 0x0b83,
- 0x0b85, 0x0b8a,
- 0x0b8e, 0x0b90,
- 0x0b92, 0x0b95,
- 0x0b99, 0x0b9a,
- 0x0b9c, 0x0b9c,
- 0x0b9e, 0x0b9f,
- 0x0ba3, 0x0ba4,
- 0x0ba8, 0x0baa,
- 0x0bae, 0x0bb9,
- 0x0bd0, 0x0bd0,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c39,
- 0x0c3d, 0x0c3d,
- 0x0c58, 0x0c5a,
- 0x0c5d, 0x0c5d,
- 0x0c60, 0x0c61,
- 0x0c80, 0x0c80,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbd, 0x0cbd,
- 0x0cdd, 0x0cde,
- 0x0ce0, 0x0ce1,
- 0x0cf1, 0x0cf2,
- 0x0d04, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d3a,
- 0x0d3d, 0x0d3d,
- 0x0d4e, 0x0d4e,
- 0x0d54, 0x0d56,
- 0x0d5f, 0x0d61,
- 0x0d7a, 0x0d7f,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0e01, 0x0e30,
- 0x0e32, 0x0e32,
- 0x0e40, 0x0e46,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e86, 0x0e8a,
- 0x0e8c, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0eb0,
- 0x0eb2, 0x0eb2,
- 0x0ebd, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f00,
- 0x0f40, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f88, 0x0f8c,
- 0x1000, 0x102a,
- 0x103f, 0x103f,
- 0x1050, 0x1055,
- 0x105a, 0x105d,
- 0x1061, 0x1061,
- 0x1065, 0x1066,
- 0x106e, 0x1070,
- 0x1075, 0x1081,
- 0x108e, 0x108e,
- 0x10a0, 0x10c5,
- 0x10c7, 0x10c7,
- 0x10cd, 0x10cd,
- 0x10d0, 0x10fa,
- 0x10fc, 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,
- 0x1380, 0x138f,
- 0x13a0, 0x13f5,
- 0x13f8, 0x13fd,
- 0x1401, 0x166c,
- 0x166f, 0x167f,
- 0x1681, 0x169a,
- 0x16a0, 0x16ea,
- 0x16ee, 0x16f8,
- 0x1700, 0x1711,
- 0x171f, 0x1731,
- 0x1740, 0x1751,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1780, 0x17b3,
- 0x17d7, 0x17d7,
- 0x17dc, 0x17dc,
- 0x1820, 0x1878,
- 0x1880, 0x18a8,
- 0x18aa, 0x18aa,
- 0x18b0, 0x18f5,
- 0x1900, 0x191e,
- 0x1950, 0x196d,
- 0x1970, 0x1974,
- 0x1980, 0x19ab,
- 0x19b0, 0x19c9,
- 0x1a00, 0x1a16,
- 0x1a20, 0x1a54,
- 0x1aa7, 0x1aa7,
- 0x1b05, 0x1b33,
- 0x1b45, 0x1b4c,
- 0x1b83, 0x1ba0,
- 0x1bae, 0x1baf,
- 0x1bba, 0x1be5,
- 0x1c00, 0x1c23,
- 0x1c4d, 0x1c4f,
- 0x1c5a, 0x1c7d,
- 0x1c80, 0x1c88,
- 0x1c90, 0x1cba,
- 0x1cbd, 0x1cbf,
- 0x1ce9, 0x1cec,
- 0x1cee, 0x1cf3,
- 0x1cf5, 0x1cf6,
- 0x1cfa, 0x1cfa,
- 0x1d00, 0x1dbf,
- 0x1e00, 0x1f15,
- 0x1f18, 0x1f1d,
- 0x1f20, 0x1f45,
- 0x1f48, 0x1f4d,
- 0x1f50, 0x1f57,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f7d,
- 0x1f80, 0x1fb4,
- 0x1fb6, 0x1fbc,
- 0x1fbe, 0x1fbe,
- 0x1fc2, 0x1fc4,
- 0x1fc6, 0x1fcc,
- 0x1fd0, 0x1fd3,
- 0x1fd6, 0x1fdb,
- 0x1fe0, 0x1fec,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ffc,
- 0x2071, 0x2071,
- 0x207f, 0x207f,
- 0x2090, 0x209c,
- 0x2102, 0x2102,
- 0x2107, 0x2107,
- 0x210a, 0x2113,
- 0x2115, 0x2115,
- 0x2118, 0x211d,
- 0x2124, 0x2124,
- 0x2126, 0x2126,
- 0x2128, 0x2128,
- 0x212a, 0x2139,
- 0x213c, 0x213f,
- 0x2145, 0x2149,
- 0x214e, 0x214e,
- 0x2160, 0x2188,
- 0x2c00, 0x2ce4,
- 0x2ceb, 0x2cee,
- 0x2cf2, 0x2cf3,
- 0x2d00, 0x2d25,
- 0x2d27, 0x2d27,
- 0x2d2d, 0x2d2d,
- 0x2d30, 0x2d67,
- 0x2d6f, 0x2d6f,
- 0x2d80, 0x2d96,
- 0x2da0, 0x2da6,
- 0x2da8, 0x2dae,
- 0x2db0, 0x2db6,
- 0x2db8, 0x2dbe,
- 0x2dc0, 0x2dc6,
- 0x2dc8, 0x2dce,
- 0x2dd0, 0x2dd6,
- 0x2dd8, 0x2dde,
- 0x3005, 0x3007,
- 0x3021, 0x3029,
- 0x3031, 0x3035,
- 0x3038, 0x303c,
- 0x3041, 0x3096,
- 0x309d, 0x309f,
- 0x30a1, 0x30fa,
- 0x30fc, 0x30ff,
- 0x3105, 0x312f,
- 0x3131, 0x318e,
- 0x31a0, 0x31bf,
- 0x31f0, 0x31ff,
- 0x3400, 0x4dbf,
- 0x4e00, 0xa48c,
- 0xa4d0, 0xa4fd,
- 0xa500, 0xa60c,
- 0xa610, 0xa61f,
- 0xa62a, 0xa62b,
- 0xa640, 0xa66e,
- 0xa67f, 0xa69d,
- 0xa6a0, 0xa6ef,
- 0xa717, 0xa71f,
- 0xa722, 0xa788,
- 0xa78b, 0xa7ca,
- 0xa7d0, 0xa7d1,
- 0xa7d3, 0xa7d3,
- 0xa7d5, 0xa7d9,
- 0xa7f2, 0xa801,
- 0xa803, 0xa805,
- 0xa807, 0xa80a,
- 0xa80c, 0xa822,
- 0xa840, 0xa873,
- 0xa882, 0xa8b3,
- 0xa8f2, 0xa8f7,
- 0xa8fb, 0xa8fb,
- 0xa8fd, 0xa8fe,
- 0xa90a, 0xa925,
- 0xa930, 0xa946,
- 0xa960, 0xa97c,
- 0xa984, 0xa9b2,
- 0xa9cf, 0xa9cf,
- 0xa9e0, 0xa9e4,
- 0xa9e6, 0xa9ef,
- 0xa9fa, 0xa9fe,
- 0xaa00, 0xaa28,
- 0xaa40, 0xaa42,
- 0xaa44, 0xaa4b,
- 0xaa60, 0xaa76,
- 0xaa7a, 0xaa7a,
- 0xaa7e, 0xaaaf,
- 0xaab1, 0xaab1,
- 0xaab5, 0xaab6,
- 0xaab9, 0xaabd,
- 0xaac0, 0xaac0,
- 0xaac2, 0xaac2,
- 0xaadb, 0xaadd,
- 0xaae0, 0xaaea,
- 0xaaf2, 0xaaf4,
- 0xab01, 0xab06,
- 0xab09, 0xab0e,
- 0xab11, 0xab16,
- 0xab20, 0xab26,
- 0xab28, 0xab2e,
- 0xab30, 0xab5a,
- 0xab5c, 0xab69,
- 0xab70, 0xabe2,
- 0xac00, 0xd7a3,
- 0xd7b0, 0xd7c6,
- 0xd7cb, 0xd7fb,
- 0xf900, 0xfa6d,
- 0xfa70, 0xfad9,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1d, 0xfb1d,
- 0xfb1f, 0xfb28,
- 0xfb2a, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbb1,
- 0xfbd3, 0xfc5d,
- 0xfc64, 0xfd3d,
- 0xfd50, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdf0, 0xfdf9,
- 0xfe71, 0xfe71,
- 0xfe73, 0xfe73,
- 0xfe77, 0xfe77,
- 0xfe79, 0xfe79,
- 0xfe7b, 0xfe7b,
- 0xfe7d, 0xfe7d,
- 0xfe7f, 0xfefc,
- 0xff21, 0xff3a,
- 0xff41, 0xff5a,
- 0xff66, 0xff9d,
- 0xffa0, 0xffbe,
- 0xffc2, 0xffc7,
- 0xffca, 0xffcf,
- 0xffd2, 0xffd7,
- 0xffda, 0xffdc,
- 0x10000, 0x1000b,
- 0x1000d, 0x10026,
- 0x10028, 0x1003a,
- 0x1003c, 0x1003d,
- 0x1003f, 0x1004d,
- 0x10050, 0x1005d,
- 0x10080, 0x100fa,
- 0x10140, 0x10174,
- 0x10280, 0x1029c,
- 0x102a0, 0x102d0,
- 0x10300, 0x1031f,
- 0x1032d, 0x1034a,
- 0x10350, 0x10375,
- 0x10380, 0x1039d,
- 0x103a0, 0x103c3,
- 0x103c8, 0x103cf,
- 0x103d1, 0x103d5,
- 0x10400, 0x1049d,
- 0x104b0, 0x104d3,
- 0x104d8, 0x104fb,
- 0x10500, 0x10527,
- 0x10530, 0x10563,
- 0x10570, 0x1057a,
- 0x1057c, 0x1058a,
- 0x1058c, 0x10592,
- 0x10594, 0x10595,
- 0x10597, 0x105a1,
- 0x105a3, 0x105b1,
- 0x105b3, 0x105b9,
- 0x105bb, 0x105bc,
- 0x10600, 0x10736,
- 0x10740, 0x10755,
- 0x10760, 0x10767,
- 0x10780, 0x10785,
- 0x10787, 0x107b0,
- 0x107b2, 0x107ba,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x10855,
- 0x10860, 0x10876,
- 0x10880, 0x1089e,
- 0x108e0, 0x108f2,
- 0x108f4, 0x108f5,
- 0x10900, 0x10915,
- 0x10920, 0x10939,
- 0x10980, 0x109b7,
- 0x109be, 0x109bf,
- 0x10a00, 0x10a00,
- 0x10a10, 0x10a13,
- 0x10a15, 0x10a17,
- 0x10a19, 0x10a35,
- 0x10a60, 0x10a7c,
- 0x10a80, 0x10a9c,
- 0x10ac0, 0x10ac7,
- 0x10ac9, 0x10ae4,
- 0x10b00, 0x10b35,
- 0x10b40, 0x10b55,
- 0x10b60, 0x10b72,
- 0x10b80, 0x10b91,
- 0x10c00, 0x10c48,
- 0x10c80, 0x10cb2,
- 0x10cc0, 0x10cf2,
- 0x10d00, 0x10d23,
- 0x10e80, 0x10ea9,
- 0x10eb0, 0x10eb1,
- 0x10f00, 0x10f1c,
- 0x10f27, 0x10f27,
- 0x10f30, 0x10f45,
- 0x10f70, 0x10f81,
- 0x10fb0, 0x10fc4,
- 0x10fe0, 0x10ff6,
- 0x11003, 0x11037,
- 0x11071, 0x11072,
- 0x11075, 0x11075,
- 0x11083, 0x110af,
- 0x110d0, 0x110e8,
- 0x11103, 0x11126,
- 0x11144, 0x11144,
- 0x11147, 0x11147,
- 0x11150, 0x11172,
- 0x11176, 0x11176,
- 0x11183, 0x111b2,
- 0x111c1, 0x111c4,
- 0x111da, 0x111da,
- 0x111dc, 0x111dc,
- 0x11200, 0x11211,
- 0x11213, 0x1122b,
- 0x1123f, 0x11240,
- 0x11280, 0x11286,
- 0x11288, 0x11288,
- 0x1128a, 0x1128d,
- 0x1128f, 0x1129d,
- 0x1129f, 0x112a8,
- 0x112b0, 0x112de,
- 0x11305, 0x1130c,
- 0x1130f, 0x11310,
- 0x11313, 0x11328,
- 0x1132a, 0x11330,
- 0x11332, 0x11333,
- 0x11335, 0x11339,
- 0x1133d, 0x1133d,
- 0x11350, 0x11350,
- 0x1135d, 0x11361,
- 0x11400, 0x11434,
- 0x11447, 0x1144a,
- 0x1145f, 0x11461,
- 0x11480, 0x114af,
- 0x114c4, 0x114c5,
- 0x114c7, 0x114c7,
- 0x11580, 0x115ae,
- 0x115d8, 0x115db,
- 0x11600, 0x1162f,
- 0x11644, 0x11644,
- 0x11680, 0x116aa,
- 0x116b8, 0x116b8,
- 0x11700, 0x1171a,
- 0x11740, 0x11746,
- 0x11800, 0x1182b,
- 0x118a0, 0x118df,
- 0x118ff, 0x11906,
- 0x11909, 0x11909,
- 0x1190c, 0x11913,
- 0x11915, 0x11916,
- 0x11918, 0x1192f,
- 0x1193f, 0x1193f,
- 0x11941, 0x11941,
- 0x119a0, 0x119a7,
- 0x119aa, 0x119d0,
- 0x119e1, 0x119e1,
- 0x119e3, 0x119e3,
- 0x11a00, 0x11a00,
- 0x11a0b, 0x11a32,
- 0x11a3a, 0x11a3a,
- 0x11a50, 0x11a50,
- 0x11a5c, 0x11a89,
- 0x11a9d, 0x11a9d,
- 0x11ab0, 0x11af8,
- 0x11c00, 0x11c08,
- 0x11c0a, 0x11c2e,
- 0x11c40, 0x11c40,
- 0x11c72, 0x11c8f,
- 0x11d00, 0x11d06,
- 0x11d08, 0x11d09,
- 0x11d0b, 0x11d30,
- 0x11d46, 0x11d46,
- 0x11d60, 0x11d65,
- 0x11d67, 0x11d68,
- 0x11d6a, 0x11d89,
- 0x11d98, 0x11d98,
- 0x11ee0, 0x11ef2,
- 0x11f02, 0x11f02,
- 0x11f04, 0x11f10,
- 0x11f12, 0x11f33,
- 0x11fb0, 0x11fb0,
- 0x12000, 0x12399,
- 0x12400, 0x1246e,
- 0x12480, 0x12543,
- 0x12f90, 0x12ff0,
- 0x13000, 0x1342f,
- 0x13441, 0x13446,
- 0x14400, 0x14646,
- 0x16800, 0x16a38,
- 0x16a40, 0x16a5e,
- 0x16a70, 0x16abe,
- 0x16ad0, 0x16aed,
- 0x16b00, 0x16b2f,
- 0x16b40, 0x16b43,
- 0x16b63, 0x16b77,
- 0x16b7d, 0x16b8f,
- 0x16e40, 0x16e7f,
- 0x16f00, 0x16f4a,
- 0x16f50, 0x16f50,
- 0x16f93, 0x16f9f,
- 0x16fe0, 0x16fe1,
- 0x16fe3, 0x16fe3,
- 0x17000, 0x187f7,
- 0x18800, 0x18cd5,
- 0x18d00, 0x18d08,
- 0x1aff0, 0x1aff3,
- 0x1aff5, 0x1affb,
- 0x1affd, 0x1affe,
- 0x1b000, 0x1b122,
- 0x1b132, 0x1b132,
- 0x1b150, 0x1b152,
- 0x1b155, 0x1b155,
- 0x1b164, 0x1b167,
- 0x1b170, 0x1b2fb,
- 0x1bc00, 0x1bc6a,
- 0x1bc70, 0x1bc7c,
- 0x1bc80, 0x1bc88,
- 0x1bc90, 0x1bc99,
- 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, 0x1d6c0,
- 0x1d6c2, 0x1d6da,
- 0x1d6dc, 0x1d6fa,
- 0x1d6fc, 0x1d714,
- 0x1d716, 0x1d734,
- 0x1d736, 0x1d74e,
- 0x1d750, 0x1d76e,
- 0x1d770, 0x1d788,
- 0x1d78a, 0x1d7a8,
- 0x1d7aa, 0x1d7c2,
- 0x1d7c4, 0x1d7cb,
- 0x1df00, 0x1df1e,
- 0x1df25, 0x1df2a,
- 0x1e030, 0x1e06d,
- 0x1e100, 0x1e12c,
- 0x1e137, 0x1e13d,
- 0x1e14e, 0x1e14e,
- 0x1e290, 0x1e2ad,
- 0x1e2c0, 0x1e2eb,
- 0x1e4d0, 0x1e4eb,
- 0x1e7e0, 0x1e7e6,
- 0x1e7e8, 0x1e7eb,
- 0x1e7ed, 0x1e7ee,
- 0x1e7f0, 0x1e7fe,
- 0x1e800, 0x1e8c4,
- 0x1e900, 0x1e943,
- 0x1e94b, 0x1e94b,
- 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,
- 0x20000, 0x2a6df,
- 0x2a700, 0x2b739,
- 0x2b740, 0x2b81d,
- 0x2b820, 0x2cea1,
- 0x2ceb0, 0x2ebe0,
- 0x2f800, 0x2fa1d,
- 0x30000, 0x3134a,
- 0x31350, 0x323af,
-}; /* CR_XID_Start */
-
-/* 'XID_Continue': Derived Property */
-static const OnigCodePoint CR_XID_Continue[] = {
- 775,
- 0x0030, 0x0039,
- 0x0041, 0x005a,
- 0x005f, 0x005f,
- 0x0061, 0x007a,
- 0x00aa, 0x00aa,
- 0x00b5, 0x00b5,
- 0x00b7, 0x00b7,
- 0x00ba, 0x00ba,
- 0x00c0, 0x00d6,
- 0x00d8, 0x00f6,
- 0x00f8, 0x02c1,
- 0x02c6, 0x02d1,
- 0x02e0, 0x02e4,
- 0x02ec, 0x02ec,
- 0x02ee, 0x02ee,
- 0x0300, 0x0374,
- 0x0376, 0x0377,
- 0x037b, 0x037d,
- 0x037f, 0x037f,
- 0x0386, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03f5,
- 0x03f7, 0x0481,
- 0x0483, 0x0487,
- 0x048a, 0x052f,
- 0x0531, 0x0556,
- 0x0559, 0x0559,
- 0x0560, 0x0588,
- 0x0591, 0x05bd,
- 0x05bf, 0x05bf,
- 0x05c1, 0x05c2,
- 0x05c4, 0x05c5,
- 0x05c7, 0x05c7,
- 0x05d0, 0x05ea,
- 0x05ef, 0x05f2,
- 0x0610, 0x061a,
- 0x0620, 0x0669,
- 0x066e, 0x06d3,
- 0x06d5, 0x06dc,
- 0x06df, 0x06e8,
- 0x06ea, 0x06fc,
- 0x06ff, 0x06ff,
- 0x0710, 0x074a,
- 0x074d, 0x07b1,
- 0x07c0, 0x07f5,
- 0x07fa, 0x07fa,
- 0x07fd, 0x07fd,
- 0x0800, 0x082d,
- 0x0840, 0x085b,
- 0x0860, 0x086a,
- 0x0870, 0x0887,
- 0x0889, 0x088e,
- 0x0898, 0x08e1,
- 0x08e3, 0x0963,
- 0x0966, 0x096f,
- 0x0971, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09f1,
- 0x09fc, 0x09fc,
- 0x09fe, 0x09fe,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a51, 0x0a51,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a75,
- 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, 0x0aef,
- 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, 0x0b6f,
- 0x0b71, 0x0b71,
- 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,
- 0x0be6, 0x0bef,
- 0x0c00, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c39,
- 0x0c3c, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c58, 0x0c5a,
- 0x0c5d, 0x0c5d,
- 0x0c60, 0x0c63,
- 0x0c66, 0x0c6f,
- 0x0c80, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cdd, 0x0cde,
- 0x0ce0, 0x0ce3,
- 0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf3,
- 0x0d00, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d44,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4e,
- 0x0d54, 0x0d57,
- 0x0d5f, 0x0d63,
- 0x0d66, 0x0d6f,
- 0x0d7a, 0x0d7f,
- 0x0d81, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0de6, 0x0def,
- 0x0df2, 0x0df3,
- 0x0e01, 0x0e3a,
- 0x0e40, 0x0e4e,
- 0x0e50, 0x0e59,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e86, 0x0e8a,
- 0x0e8c, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ece,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f00,
- 0x0f18, 0x0f19,
- 0x0f20, 0x0f29,
- 0x0f35, 0x0f35,
- 0x0f37, 0x0f37,
- 0x0f39, 0x0f39,
- 0x0f3e, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f71, 0x0f84,
- 0x0f86, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x0fc6, 0x0fc6,
- 0x1000, 0x1049,
- 0x1050, 0x109d,
- 0x10a0, 0x10c5,
- 0x10c7, 0x10c7,
- 0x10cd, 0x10cd,
- 0x10d0, 0x10fa,
- 0x10fc, 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, 0x135f,
- 0x1369, 0x1371,
- 0x1380, 0x138f,
- 0x13a0, 0x13f5,
- 0x13f8, 0x13fd,
- 0x1401, 0x166c,
- 0x166f, 0x167f,
- 0x1681, 0x169a,
- 0x16a0, 0x16ea,
- 0x16ee, 0x16f8,
- 0x1700, 0x1715,
- 0x171f, 0x1734,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17d3,
- 0x17d7, 0x17d7,
- 0x17dc, 0x17dd,
- 0x17e0, 0x17e9,
- 0x180b, 0x180d,
- 0x180f, 0x1819,
- 0x1820, 0x1878,
- 0x1880, 0x18aa,
- 0x18b0, 0x18f5,
- 0x1900, 0x191e,
- 0x1920, 0x192b,
- 0x1930, 0x193b,
- 0x1946, 0x196d,
- 0x1970, 0x1974,
- 0x1980, 0x19ab,
- 0x19b0, 0x19c9,
- 0x19d0, 0x19da,
- 0x1a00, 0x1a1b,
- 0x1a20, 0x1a5e,
- 0x1a60, 0x1a7c,
- 0x1a7f, 0x1a89,
- 0x1a90, 0x1a99,
- 0x1aa7, 0x1aa7,
- 0x1ab0, 0x1abd,
- 0x1abf, 0x1ace,
- 0x1b00, 0x1b4c,
- 0x1b50, 0x1b59,
- 0x1b6b, 0x1b73,
- 0x1b80, 0x1bf3,
- 0x1c00, 0x1c37,
- 0x1c40, 0x1c49,
- 0x1c4d, 0x1c7d,
- 0x1c80, 0x1c88,
- 0x1c90, 0x1cba,
- 0x1cbd, 0x1cbf,
- 0x1cd0, 0x1cd2,
- 0x1cd4, 0x1cfa,
- 0x1d00, 0x1f15,
- 0x1f18, 0x1f1d,
- 0x1f20, 0x1f45,
- 0x1f48, 0x1f4d,
- 0x1f50, 0x1f57,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f7d,
- 0x1f80, 0x1fb4,
- 0x1fb6, 0x1fbc,
- 0x1fbe, 0x1fbe,
- 0x1fc2, 0x1fc4,
- 0x1fc6, 0x1fcc,
- 0x1fd0, 0x1fd3,
- 0x1fd6, 0x1fdb,
- 0x1fe0, 0x1fec,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ffc,
- 0x203f, 0x2040,
- 0x2054, 0x2054,
- 0x2071, 0x2071,
- 0x207f, 0x207f,
- 0x2090, 0x209c,
- 0x20d0, 0x20dc,
- 0x20e1, 0x20e1,
- 0x20e5, 0x20f0,
- 0x2102, 0x2102,
- 0x2107, 0x2107,
- 0x210a, 0x2113,
- 0x2115, 0x2115,
- 0x2118, 0x211d,
- 0x2124, 0x2124,
- 0x2126, 0x2126,
- 0x2128, 0x2128,
- 0x212a, 0x2139,
- 0x213c, 0x213f,
- 0x2145, 0x2149,
- 0x214e, 0x214e,
- 0x2160, 0x2188,
- 0x2c00, 0x2ce4,
- 0x2ceb, 0x2cf3,
- 0x2d00, 0x2d25,
- 0x2d27, 0x2d27,
- 0x2d2d, 0x2d2d,
- 0x2d30, 0x2d67,
- 0x2d6f, 0x2d6f,
- 0x2d7f, 0x2d96,
- 0x2da0, 0x2da6,
- 0x2da8, 0x2dae,
- 0x2db0, 0x2db6,
- 0x2db8, 0x2dbe,
- 0x2dc0, 0x2dc6,
- 0x2dc8, 0x2dce,
- 0x2dd0, 0x2dd6,
- 0x2dd8, 0x2dde,
- 0x2de0, 0x2dff,
- 0x3005, 0x3007,
- 0x3021, 0x302f,
- 0x3031, 0x3035,
- 0x3038, 0x303c,
- 0x3041, 0x3096,
- 0x3099, 0x309a,
- 0x309d, 0x309f,
- 0x30a1, 0x30fa,
- 0x30fc, 0x30ff,
- 0x3105, 0x312f,
- 0x3131, 0x318e,
- 0x31a0, 0x31bf,
- 0x31f0, 0x31ff,
- 0x3400, 0x4dbf,
- 0x4e00, 0xa48c,
- 0xa4d0, 0xa4fd,
- 0xa500, 0xa60c,
- 0xa610, 0xa62b,
- 0xa640, 0xa66f,
- 0xa674, 0xa67d,
- 0xa67f, 0xa6f1,
- 0xa717, 0xa71f,
- 0xa722, 0xa788,
- 0xa78b, 0xa7ca,
- 0xa7d0, 0xa7d1,
- 0xa7d3, 0xa7d3,
- 0xa7d5, 0xa7d9,
- 0xa7f2, 0xa827,
- 0xa82c, 0xa82c,
- 0xa840, 0xa873,
- 0xa880, 0xa8c5,
- 0xa8d0, 0xa8d9,
- 0xa8e0, 0xa8f7,
- 0xa8fb, 0xa8fb,
- 0xa8fd, 0xa92d,
- 0xa930, 0xa953,
- 0xa960, 0xa97c,
- 0xa980, 0xa9c0,
- 0xa9cf, 0xa9d9,
- 0xa9e0, 0xa9fe,
- 0xaa00, 0xaa36,
- 0xaa40, 0xaa4d,
- 0xaa50, 0xaa59,
- 0xaa60, 0xaa76,
- 0xaa7a, 0xaac2,
- 0xaadb, 0xaadd,
- 0xaae0, 0xaaef,
- 0xaaf2, 0xaaf6,
- 0xab01, 0xab06,
- 0xab09, 0xab0e,
- 0xab11, 0xab16,
- 0xab20, 0xab26,
- 0xab28, 0xab2e,
- 0xab30, 0xab5a,
- 0xab5c, 0xab69,
- 0xab70, 0xabea,
- 0xabec, 0xabed,
- 0xabf0, 0xabf9,
- 0xac00, 0xd7a3,
- 0xd7b0, 0xd7c6,
- 0xd7cb, 0xd7fb,
- 0xf900, 0xfa6d,
- 0xfa70, 0xfad9,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1d, 0xfb28,
- 0xfb2a, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbb1,
- 0xfbd3, 0xfc5d,
- 0xfc64, 0xfd3d,
- 0xfd50, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdf0, 0xfdf9,
- 0xfe00, 0xfe0f,
- 0xfe20, 0xfe2f,
- 0xfe33, 0xfe34,
- 0xfe4d, 0xfe4f,
- 0xfe71, 0xfe71,
- 0xfe73, 0xfe73,
- 0xfe77, 0xfe77,
- 0xfe79, 0xfe79,
- 0xfe7b, 0xfe7b,
- 0xfe7d, 0xfe7d,
- 0xfe7f, 0xfefc,
- 0xff10, 0xff19,
- 0xff21, 0xff3a,
- 0xff3f, 0xff3f,
- 0xff41, 0xff5a,
- 0xff66, 0xffbe,
- 0xffc2, 0xffc7,
- 0xffca, 0xffcf,
- 0xffd2, 0xffd7,
- 0xffda, 0xffdc,
- 0x10000, 0x1000b,
- 0x1000d, 0x10026,
- 0x10028, 0x1003a,
- 0x1003c, 0x1003d,
- 0x1003f, 0x1004d,
- 0x10050, 0x1005d,
- 0x10080, 0x100fa,
- 0x10140, 0x10174,
- 0x101fd, 0x101fd,
- 0x10280, 0x1029c,
- 0x102a0, 0x102d0,
- 0x102e0, 0x102e0,
- 0x10300, 0x1031f,
- 0x1032d, 0x1034a,
- 0x10350, 0x1037a,
- 0x10380, 0x1039d,
- 0x103a0, 0x103c3,
- 0x103c8, 0x103cf,
- 0x103d1, 0x103d5,
- 0x10400, 0x1049d,
- 0x104a0, 0x104a9,
- 0x104b0, 0x104d3,
- 0x104d8, 0x104fb,
- 0x10500, 0x10527,
- 0x10530, 0x10563,
- 0x10570, 0x1057a,
- 0x1057c, 0x1058a,
- 0x1058c, 0x10592,
- 0x10594, 0x10595,
- 0x10597, 0x105a1,
- 0x105a3, 0x105b1,
- 0x105b3, 0x105b9,
- 0x105bb, 0x105bc,
- 0x10600, 0x10736,
- 0x10740, 0x10755,
- 0x10760, 0x10767,
- 0x10780, 0x10785,
- 0x10787, 0x107b0,
- 0x107b2, 0x107ba,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x10855,
- 0x10860, 0x10876,
- 0x10880, 0x1089e,
- 0x108e0, 0x108f2,
- 0x108f4, 0x108f5,
- 0x10900, 0x10915,
- 0x10920, 0x10939,
- 0x10980, 0x109b7,
- 0x109be, 0x109bf,
- 0x10a00, 0x10a03,
- 0x10a05, 0x10a06,
- 0x10a0c, 0x10a13,
- 0x10a15, 0x10a17,
- 0x10a19, 0x10a35,
- 0x10a38, 0x10a3a,
- 0x10a3f, 0x10a3f,
- 0x10a60, 0x10a7c,
- 0x10a80, 0x10a9c,
- 0x10ac0, 0x10ac7,
- 0x10ac9, 0x10ae6,
- 0x10b00, 0x10b35,
- 0x10b40, 0x10b55,
- 0x10b60, 0x10b72,
- 0x10b80, 0x10b91,
- 0x10c00, 0x10c48,
- 0x10c80, 0x10cb2,
- 0x10cc0, 0x10cf2,
- 0x10d00, 0x10d27,
- 0x10d30, 0x10d39,
- 0x10e80, 0x10ea9,
- 0x10eab, 0x10eac,
- 0x10eb0, 0x10eb1,
- 0x10efd, 0x10f1c,
- 0x10f27, 0x10f27,
- 0x10f30, 0x10f50,
- 0x10f70, 0x10f85,
- 0x10fb0, 0x10fc4,
- 0x10fe0, 0x10ff6,
- 0x11000, 0x11046,
- 0x11066, 0x11075,
- 0x1107f, 0x110ba,
- 0x110c2, 0x110c2,
- 0x110d0, 0x110e8,
- 0x110f0, 0x110f9,
- 0x11100, 0x11134,
- 0x11136, 0x1113f,
- 0x11144, 0x11147,
- 0x11150, 0x11173,
- 0x11176, 0x11176,
- 0x11180, 0x111c4,
- 0x111c9, 0x111cc,
- 0x111ce, 0x111da,
- 0x111dc, 0x111dc,
- 0x11200, 0x11211,
- 0x11213, 0x11237,
- 0x1123e, 0x11241,
- 0x11280, 0x11286,
- 0x11288, 0x11288,
- 0x1128a, 0x1128d,
- 0x1128f, 0x1129d,
- 0x1129f, 0x112a8,
- 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, 0x1144a,
- 0x11450, 0x11459,
- 0x1145e, 0x11461,
- 0x11480, 0x114c5,
- 0x114c7, 0x114c7,
- 0x114d0, 0x114d9,
- 0x11580, 0x115b5,
- 0x115b8, 0x115c0,
- 0x115d8, 0x115dd,
- 0x11600, 0x11640,
- 0x11644, 0x11644,
- 0x11650, 0x11659,
- 0x11680, 0x116b8,
- 0x116c0, 0x116c9,
- 0x11700, 0x1171a,
- 0x1171d, 0x1172b,
- 0x11730, 0x11739,
- 0x11740, 0x11746,
- 0x11800, 0x1183a,
- 0x118a0, 0x118e9,
- 0x118ff, 0x11906,
- 0x11909, 0x11909,
- 0x1190c, 0x11913,
- 0x11915, 0x11916,
- 0x11918, 0x11935,
- 0x11937, 0x11938,
- 0x1193b, 0x11943,
- 0x11950, 0x11959,
- 0x119a0, 0x119a7,
- 0x119aa, 0x119d7,
- 0x119da, 0x119e1,
- 0x119e3, 0x119e4,
- 0x11a00, 0x11a3e,
- 0x11a47, 0x11a47,
- 0x11a50, 0x11a99,
- 0x11a9d, 0x11a9d,
- 0x11ab0, 0x11af8,
- 0x11c00, 0x11c08,
- 0x11c0a, 0x11c36,
- 0x11c38, 0x11c40,
- 0x11c50, 0x11c59,
- 0x11c72, 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, 0x11ef6,
- 0x11f00, 0x11f10,
- 0x11f12, 0x11f3a,
- 0x11f3e, 0x11f42,
- 0x11f50, 0x11f59,
- 0x11fb0, 0x11fb0,
- 0x12000, 0x12399,
- 0x12400, 0x1246e,
- 0x12480, 0x12543,
- 0x12f90, 0x12ff0,
- 0x13000, 0x1342f,
- 0x13440, 0x13455,
- 0x14400, 0x14646,
- 0x16800, 0x16a38,
- 0x16a40, 0x16a5e,
- 0x16a60, 0x16a69,
- 0x16a70, 0x16abe,
- 0x16ac0, 0x16ac9,
- 0x16ad0, 0x16aed,
- 0x16af0, 0x16af4,
- 0x16b00, 0x16b36,
- 0x16b40, 0x16b43,
- 0x16b50, 0x16b59,
- 0x16b63, 0x16b77,
- 0x16b7d, 0x16b8f,
- 0x16e40, 0x16e7f,
- 0x16f00, 0x16f4a,
- 0x16f4f, 0x16f87,
- 0x16f8f, 0x16f9f,
- 0x16fe0, 0x16fe1,
- 0x16fe3, 0x16fe4,
- 0x16ff0, 0x16ff1,
- 0x17000, 0x187f7,
- 0x18800, 0x18cd5,
- 0x18d00, 0x18d08,
- 0x1aff0, 0x1aff3,
- 0x1aff5, 0x1affb,
- 0x1affd, 0x1affe,
- 0x1b000, 0x1b122,
- 0x1b132, 0x1b132,
- 0x1b150, 0x1b152,
- 0x1b155, 0x1b155,
- 0x1b164, 0x1b167,
- 0x1b170, 0x1b2fb,
- 0x1bc00, 0x1bc6a,
- 0x1bc70, 0x1bc7c,
- 0x1bc80, 0x1bc88,
- 0x1bc90, 0x1bc99,
- 0x1bc9d, 0x1bc9e,
- 0x1cf00, 0x1cf2d,
- 0x1cf30, 0x1cf46,
- 0x1d165, 0x1d169,
- 0x1d16d, 0x1d172,
- 0x1d17b, 0x1d182,
- 0x1d185, 0x1d18b,
- 0x1d1aa, 0x1d1ad,
- 0x1d242, 0x1d244,
- 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, 0x1d6c0,
- 0x1d6c2, 0x1d6da,
- 0x1d6dc, 0x1d6fa,
- 0x1d6fc, 0x1d714,
- 0x1d716, 0x1d734,
- 0x1d736, 0x1d74e,
- 0x1d750, 0x1d76e,
- 0x1d770, 0x1d788,
- 0x1d78a, 0x1d7a8,
- 0x1d7aa, 0x1d7c2,
- 0x1d7c4, 0x1d7cb,
- 0x1d7ce, 0x1d7ff,
- 0x1da00, 0x1da36,
- 0x1da3b, 0x1da6c,
- 0x1da75, 0x1da75,
- 0x1da84, 0x1da84,
- 0x1da9b, 0x1da9f,
- 0x1daa1, 0x1daaf,
- 0x1df00, 0x1df1e,
- 0x1df25, 0x1df2a,
- 0x1e000, 0x1e006,
- 0x1e008, 0x1e018,
- 0x1e01b, 0x1e021,
- 0x1e023, 0x1e024,
- 0x1e026, 0x1e02a,
- 0x1e030, 0x1e06d,
- 0x1e08f, 0x1e08f,
- 0x1e100, 0x1e12c,
- 0x1e130, 0x1e13d,
- 0x1e140, 0x1e149,
- 0x1e14e, 0x1e14e,
- 0x1e290, 0x1e2ae,
- 0x1e2c0, 0x1e2f9,
- 0x1e4d0, 0x1e4f9,
- 0x1e7e0, 0x1e7e6,
- 0x1e7e8, 0x1e7eb,
- 0x1e7ed, 0x1e7ee,
- 0x1e7f0, 0x1e7fe,
- 0x1e800, 0x1e8c4,
- 0x1e8d0, 0x1e8d6,
- 0x1e900, 0x1e94b,
- 0x1e950, 0x1e959,
- 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,
- 0x1fbf0, 0x1fbf9,
- 0x20000, 0x2a6df,
- 0x2a700, 0x2b739,
- 0x2b740, 0x2b81d,
- 0x2b820, 0x2cea1,
- 0x2ceb0, 0x2ebe0,
- 0x2f800, 0x2fa1d,
- 0x30000, 0x3134a,
- 0x31350, 0x323af,
- 0xe0100, 0xe01ef,
-}; /* CR_XID_Continue */
-
-/* 'Default_Ignorable_Code_Point': Derived Property */
-static const OnigCodePoint CR_Default_Ignorable_Code_Point[] = {
- 17,
- 0x00ad, 0x00ad,
- 0x034f, 0x034f,
- 0x061c, 0x061c,
- 0x115f, 0x1160,
- 0x17b4, 0x17b5,
- 0x180b, 0x180f,
- 0x200b, 0x200f,
- 0x202a, 0x202e,
- 0x2060, 0x206f,
- 0x3164, 0x3164,
- 0xfe00, 0xfe0f,
- 0xfeff, 0xfeff,
- 0xffa0, 0xffa0,
- 0xfff0, 0xfff8,
- 0x1bca0, 0x1bca3,
- 0x1d173, 0x1d17a,
- 0xe0000, 0xe0fff,
-}; /* CR_Default_Ignorable_Code_Point */
-
-/* 'Grapheme_Extend': Derived Property */
-static const OnigCodePoint CR_Grapheme_Extend[] = {
- 363,
- 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,
- 0x0898, 0x089f,
- 0x08ca, 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,
- 0x0c3c, 0x0c3c,
- 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, 0x0ece,
- 0x0f18, 0x0f19,
- 0x0f35, 0x0f35,
- 0x0f37, 0x0f37,
- 0x0f39, 0x0f39,
- 0x0f71, 0x0f7e,
- 0x0f80, 0x0f84,
- 0x0f86, 0x0f87,
- 0x0f8d, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x0fc6, 0x0fc6,
- 0x102d, 0x1030,
- 0x1032, 0x1037,
- 0x1039, 0x103a,
- 0x103d, 0x103e,
- 0x1058, 0x1059,
- 0x105e, 0x1060,
- 0x1071, 0x1074,
- 0x1082, 0x1082,
- 0x1085, 0x1086,
- 0x108d, 0x108d,
- 0x109d, 0x109d,
- 0x135d, 0x135f,
- 0x1712, 0x1714,
- 0x1732, 0x1733,
- 0x1752, 0x1753,
- 0x1772, 0x1773,
- 0x17b4, 0x17b5,
- 0x17b7, 0x17bd,
- 0x17c6, 0x17c6,
- 0x17c9, 0x17d3,
- 0x17dd, 0x17dd,
- 0x180b, 0x180d,
- 0x180f, 0x180f,
- 0x1885, 0x1886,
- 0x18a9, 0x18a9,
- 0x1920, 0x1922,
- 0x1927, 0x1928,
- 0x1932, 0x1932,
- 0x1939, 0x193b,
- 0x1a17, 0x1a18,
- 0x1a1b, 0x1a1b,
- 0x1a56, 0x1a56,
- 0x1a58, 0x1a5e,
- 0x1a60, 0x1a60,
- 0x1a62, 0x1a62,
- 0x1a65, 0x1a6c,
- 0x1a73, 0x1a7c,
- 0x1a7f, 0x1a7f,
- 0x1ab0, 0x1ace,
- 0x1b00, 0x1b03,
- 0x1b34, 0x1b3a,
- 0x1b3c, 0x1b3c,
- 0x1b42, 0x1b42,
- 0x1b6b, 0x1b73,
- 0x1b80, 0x1b81,
- 0x1ba2, 0x1ba5,
- 0x1ba8, 0x1ba9,
- 0x1bab, 0x1bad,
- 0x1be6, 0x1be6,
- 0x1be8, 0x1be9,
- 0x1bed, 0x1bed,
- 0x1bef, 0x1bf1,
- 0x1c2c, 0x1c33,
- 0x1c36, 0x1c37,
- 0x1cd0, 0x1cd2,
- 0x1cd4, 0x1ce0,
- 0x1ce2, 0x1ce8,
- 0x1ced, 0x1ced,
- 0x1cf4, 0x1cf4,
- 0x1cf8, 0x1cf9,
- 0x1dc0, 0x1dff,
- 0x200c, 0x200c,
- 0x20d0, 0x20f0,
- 0x2cef, 0x2cf1,
- 0x2d7f, 0x2d7f,
- 0x2de0, 0x2dff,
- 0x302a, 0x302f,
- 0x3099, 0x309a,
- 0xa66f, 0xa672,
- 0xa674, 0xa67d,
- 0xa69e, 0xa69f,
- 0xa6f0, 0xa6f1,
- 0xa802, 0xa802,
- 0xa806, 0xa806,
- 0xa80b, 0xa80b,
- 0xa825, 0xa826,
- 0xa82c, 0xa82c,
- 0xa8c4, 0xa8c5,
- 0xa8e0, 0xa8f1,
- 0xa8ff, 0xa8ff,
- 0xa926, 0xa92d,
- 0xa947, 0xa951,
- 0xa980, 0xa982,
- 0xa9b3, 0xa9b3,
- 0xa9b6, 0xa9b9,
- 0xa9bc, 0xa9bd,
- 0xa9e5, 0xa9e5,
- 0xaa29, 0xaa2e,
- 0xaa31, 0xaa32,
- 0xaa35, 0xaa36,
- 0xaa43, 0xaa43,
- 0xaa4c, 0xaa4c,
- 0xaa7c, 0xaa7c,
- 0xaab0, 0xaab0,
- 0xaab2, 0xaab4,
- 0xaab7, 0xaab8,
- 0xaabe, 0xaabf,
- 0xaac1, 0xaac1,
- 0xaaec, 0xaaed,
- 0xaaf6, 0xaaf6,
- 0xabe5, 0xabe5,
- 0xabe8, 0xabe8,
- 0xabed, 0xabed,
- 0xfb1e, 0xfb1e,
- 0xfe00, 0xfe0f,
- 0xfe20, 0xfe2f,
- 0xff9e, 0xff9f,
- 0x101fd, 0x101fd,
- 0x102e0, 0x102e0,
- 0x10376, 0x1037a,
- 0x10a01, 0x10a03,
- 0x10a05, 0x10a06,
- 0x10a0c, 0x10a0f,
- 0x10a38, 0x10a3a,
- 0x10a3f, 0x10a3f,
- 0x10ae5, 0x10ae6,
- 0x10d24, 0x10d27,
- 0x10eab, 0x10eac,
- 0x10efd, 0x10eff,
- 0x10f46, 0x10f50,
- 0x10f82, 0x10f85,
- 0x11001, 0x11001,
- 0x11038, 0x11046,
- 0x11070, 0x11070,
- 0x11073, 0x11074,
- 0x1107f, 0x11081,
- 0x110b3, 0x110b6,
- 0x110b9, 0x110ba,
- 0x110c2, 0x110c2,
- 0x11100, 0x11102,
- 0x11127, 0x1112b,
- 0x1112d, 0x11134,
- 0x11173, 0x11173,
- 0x11180, 0x11181,
- 0x111b6, 0x111be,
- 0x111c9, 0x111cc,
- 0x111cf, 0x111cf,
- 0x1122f, 0x11231,
- 0x11234, 0x11234,
- 0x11236, 0x11237,
- 0x1123e, 0x1123e,
- 0x11241, 0x11241,
- 0x112df, 0x112df,
- 0x112e3, 0x112ea,
- 0x11300, 0x11301,
- 0x1133b, 0x1133c,
- 0x1133e, 0x1133e,
- 0x11340, 0x11340,
- 0x11357, 0x11357,
- 0x11366, 0x1136c,
- 0x11370, 0x11374,
- 0x11438, 0x1143f,
- 0x11442, 0x11444,
- 0x11446, 0x11446,
- 0x1145e, 0x1145e,
- 0x114b0, 0x114b0,
- 0x114b3, 0x114b8,
- 0x114ba, 0x114ba,
- 0x114bd, 0x114bd,
- 0x114bf, 0x114c0,
- 0x114c2, 0x114c3,
- 0x115af, 0x115af,
- 0x115b2, 0x115b5,
- 0x115bc, 0x115bd,
- 0x115bf, 0x115c0,
- 0x115dc, 0x115dd,
- 0x11633, 0x1163a,
- 0x1163d, 0x1163d,
- 0x1163f, 0x11640,
- 0x116ab, 0x116ab,
- 0x116ad, 0x116ad,
- 0x116b0, 0x116b5,
- 0x116b7, 0x116b7,
- 0x1171d, 0x1171f,
- 0x11722, 0x11725,
- 0x11727, 0x1172b,
- 0x1182f, 0x11837,
- 0x11839, 0x1183a,
- 0x11930, 0x11930,
- 0x1193b, 0x1193c,
- 0x1193e, 0x1193e,
- 0x11943, 0x11943,
- 0x119d4, 0x119d7,
- 0x119da, 0x119db,
- 0x119e0, 0x119e0,
- 0x11a01, 0x11a0a,
- 0x11a33, 0x11a38,
- 0x11a3b, 0x11a3e,
- 0x11a47, 0x11a47,
- 0x11a51, 0x11a56,
- 0x11a59, 0x11a5b,
- 0x11a8a, 0x11a96,
- 0x11a98, 0x11a99,
- 0x11c30, 0x11c36,
- 0x11c38, 0x11c3d,
- 0x11c3f, 0x11c3f,
- 0x11c92, 0x11ca7,
- 0x11caa, 0x11cb0,
- 0x11cb2, 0x11cb3,
- 0x11cb5, 0x11cb6,
- 0x11d31, 0x11d36,
- 0x11d3a, 0x11d3a,
- 0x11d3c, 0x11d3d,
- 0x11d3f, 0x11d45,
- 0x11d47, 0x11d47,
- 0x11d90, 0x11d91,
- 0x11d95, 0x11d95,
- 0x11d97, 0x11d97,
- 0x11ef3, 0x11ef4,
- 0x11f00, 0x11f01,
- 0x11f36, 0x11f3a,
- 0x11f40, 0x11f40,
- 0x11f42, 0x11f42,
- 0x13440, 0x13440,
- 0x13447, 0x13455,
- 0x16af0, 0x16af4,
- 0x16b30, 0x16b36,
- 0x16f4f, 0x16f4f,
- 0x16f8f, 0x16f92,
- 0x16fe4, 0x16fe4,
- 0x1bc9d, 0x1bc9e,
- 0x1cf00, 0x1cf2d,
- 0x1cf30, 0x1cf46,
- 0x1d165, 0x1d165,
- 0x1d167, 0x1d169,
- 0x1d16e, 0x1d172,
- 0x1d17b, 0x1d182,
- 0x1d185, 0x1d18b,
- 0x1d1aa, 0x1d1ad,
- 0x1d242, 0x1d244,
- 0x1da00, 0x1da36,
- 0x1da3b, 0x1da6c,
- 0x1da75, 0x1da75,
- 0x1da84, 0x1da84,
- 0x1da9b, 0x1da9f,
- 0x1daa1, 0x1daaf,
- 0x1e000, 0x1e006,
- 0x1e008, 0x1e018,
- 0x1e01b, 0x1e021,
- 0x1e023, 0x1e024,
- 0x1e026, 0x1e02a,
- 0x1e08f, 0x1e08f,
- 0x1e130, 0x1e136,
- 0x1e2ae, 0x1e2ae,
- 0x1e2ec, 0x1e2ef,
- 0x1e4ec, 0x1e4ef,
- 0x1e8d0, 0x1e8d6,
- 0x1e944, 0x1e94a,
- 0xe0020, 0xe007f,
- 0xe0100, 0xe01ef,
-}; /* CR_Grapheme_Extend */
-
-/* 'Grapheme_Base': Derived Property */
-static const OnigCodePoint CR_Grapheme_Base[] = {
- 875,
- 0x0020, 0x007e,
- 0x00a0, 0x00ac,
- 0x00ae, 0x02ff,
- 0x0370, 0x0377,
- 0x037a, 0x037f,
- 0x0384, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x0482,
- 0x048a, 0x052f,
- 0x0531, 0x0556,
- 0x0559, 0x058a,
- 0x058d, 0x058f,
- 0x05be, 0x05be,
- 0x05c0, 0x05c0,
- 0x05c3, 0x05c3,
- 0x05c6, 0x05c6,
- 0x05d0, 0x05ea,
- 0x05ef, 0x05f4,
- 0x0606, 0x060f,
- 0x061b, 0x061b,
- 0x061d, 0x064a,
- 0x0660, 0x066f,
- 0x0671, 0x06d5,
- 0x06de, 0x06de,
- 0x06e5, 0x06e6,
- 0x06e9, 0x06e9,
- 0x06ee, 0x070d,
- 0x0710, 0x0710,
- 0x0712, 0x072f,
- 0x074d, 0x07a5,
- 0x07b1, 0x07b1,
- 0x07c0, 0x07ea,
- 0x07f4, 0x07fa,
- 0x07fe, 0x0815,
- 0x081a, 0x081a,
- 0x0824, 0x0824,
- 0x0828, 0x0828,
- 0x0830, 0x083e,
- 0x0840, 0x0858,
- 0x085e, 0x085e,
- 0x0860, 0x086a,
- 0x0870, 0x088e,
- 0x08a0, 0x08c9,
- 0x0903, 0x0939,
- 0x093b, 0x093b,
- 0x093d, 0x0940,
- 0x0949, 0x094c,
- 0x094e, 0x0950,
- 0x0958, 0x0961,
- 0x0964, 0x0980,
- 0x0982, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bd, 0x09bd,
- 0x09bf, 0x09c0,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09cc,
- 0x09ce, 0x09ce,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e1,
- 0x09e6, 0x09fd,
- 0x0a03, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3e, 0x0a40,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a6f,
- 0x0a72, 0x0a74,
- 0x0a76, 0x0a76,
- 0x0a83, 0x0a83,
- 0x0a85, 0x0a8d,
- 0x0a8f, 0x0a91,
- 0x0a93, 0x0aa8,
- 0x0aaa, 0x0ab0,
- 0x0ab2, 0x0ab3,
- 0x0ab5, 0x0ab9,
- 0x0abd, 0x0ac0,
- 0x0ac9, 0x0ac9,
- 0x0acb, 0x0acc,
- 0x0ad0, 0x0ad0,
- 0x0ae0, 0x0ae1,
- 0x0ae6, 0x0af1,
- 0x0af9, 0x0af9,
- 0x0b02, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b35, 0x0b39,
- 0x0b3d, 0x0b3d,
- 0x0b40, 0x0b40,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4c,
- 0x0b5c, 0x0b5d,
- 0x0b5f, 0x0b61,
- 0x0b66, 0x0b77,
- 0x0b83, 0x0b83,
- 0x0b85, 0x0b8a,
- 0x0b8e, 0x0b90,
- 0x0b92, 0x0b95,
- 0x0b99, 0x0b9a,
- 0x0b9c, 0x0b9c,
- 0x0b9e, 0x0b9f,
- 0x0ba3, 0x0ba4,
- 0x0ba8, 0x0baa,
- 0x0bae, 0x0bb9,
- 0x0bbf, 0x0bbf,
- 0x0bc1, 0x0bc2,
- 0x0bc6, 0x0bc8,
- 0x0bca, 0x0bcc,
- 0x0bd0, 0x0bd0,
- 0x0be6, 0x0bfa,
- 0x0c01, 0x0c03,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c39,
- 0x0c3d, 0x0c3d,
- 0x0c41, 0x0c44,
- 0x0c58, 0x0c5a,
- 0x0c5d, 0x0c5d,
- 0x0c60, 0x0c61,
- 0x0c66, 0x0c6f,
- 0x0c77, 0x0c80,
- 0x0c82, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbd, 0x0cbe,
- 0x0cc0, 0x0cc1,
- 0x0cc3, 0x0cc4,
- 0x0cc7, 0x0cc8,
- 0x0cca, 0x0ccb,
- 0x0cdd, 0x0cde,
- 0x0ce0, 0x0ce1,
- 0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf3,
- 0x0d02, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d3a,
- 0x0d3d, 0x0d3d,
- 0x0d3f, 0x0d40,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4c,
- 0x0d4e, 0x0d4f,
- 0x0d54, 0x0d56,
- 0x0d58, 0x0d61,
- 0x0d66, 0x0d7f,
- 0x0d82, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dd0, 0x0dd1,
- 0x0dd8, 0x0dde,
- 0x0de6, 0x0def,
- 0x0df2, 0x0df4,
- 0x0e01, 0x0e30,
- 0x0e32, 0x0e33,
- 0x0e3f, 0x0e46,
- 0x0e4f, 0x0e5b,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e86, 0x0e8a,
- 0x0e8c, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0eb0,
- 0x0eb2, 0x0eb3,
- 0x0ebd, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f17,
- 0x0f1a, 0x0f34,
- 0x0f36, 0x0f36,
- 0x0f38, 0x0f38,
- 0x0f3a, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f7f, 0x0f7f,
- 0x0f85, 0x0f85,
- 0x0f88, 0x0f8c,
- 0x0fbe, 0x0fc5,
- 0x0fc7, 0x0fcc,
- 0x0fce, 0x0fda,
- 0x1000, 0x102c,
- 0x1031, 0x1031,
- 0x1038, 0x1038,
- 0x103b, 0x103c,
- 0x103f, 0x1057,
- 0x105a, 0x105d,
- 0x1061, 0x1070,
- 0x1075, 0x1081,
- 0x1083, 0x1084,
- 0x1087, 0x108c,
- 0x108e, 0x109c,
- 0x109e, 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,
- 0x1360, 0x137c,
- 0x1380, 0x1399,
- 0x13a0, 0x13f5,
- 0x13f8, 0x13fd,
- 0x1400, 0x169c,
- 0x16a0, 0x16f8,
- 0x1700, 0x1711,
- 0x1715, 0x1715,
- 0x171f, 0x1731,
- 0x1734, 0x1736,
- 0x1740, 0x1751,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1780, 0x17b3,
- 0x17b6, 0x17b6,
- 0x17be, 0x17c5,
- 0x17c7, 0x17c8,
- 0x17d4, 0x17dc,
- 0x17e0, 0x17e9,
- 0x17f0, 0x17f9,
- 0x1800, 0x180a,
- 0x1810, 0x1819,
- 0x1820, 0x1878,
- 0x1880, 0x1884,
- 0x1887, 0x18a8,
- 0x18aa, 0x18aa,
- 0x18b0, 0x18f5,
- 0x1900, 0x191e,
- 0x1923, 0x1926,
- 0x1929, 0x192b,
- 0x1930, 0x1931,
- 0x1933, 0x1938,
- 0x1940, 0x1940,
- 0x1944, 0x196d,
- 0x1970, 0x1974,
- 0x1980, 0x19ab,
- 0x19b0, 0x19c9,
- 0x19d0, 0x19da,
- 0x19de, 0x1a16,
- 0x1a19, 0x1a1a,
- 0x1a1e, 0x1a55,
- 0x1a57, 0x1a57,
- 0x1a61, 0x1a61,
- 0x1a63, 0x1a64,
- 0x1a6d, 0x1a72,
- 0x1a80, 0x1a89,
- 0x1a90, 0x1a99,
- 0x1aa0, 0x1aad,
- 0x1b04, 0x1b33,
- 0x1b3b, 0x1b3b,
- 0x1b3d, 0x1b41,
- 0x1b43, 0x1b4c,
- 0x1b50, 0x1b6a,
- 0x1b74, 0x1b7e,
- 0x1b82, 0x1ba1,
- 0x1ba6, 0x1ba7,
- 0x1baa, 0x1baa,
- 0x1bae, 0x1be5,
- 0x1be7, 0x1be7,
- 0x1bea, 0x1bec,
- 0x1bee, 0x1bee,
- 0x1bf2, 0x1bf3,
- 0x1bfc, 0x1c2b,
- 0x1c34, 0x1c35,
- 0x1c3b, 0x1c49,
- 0x1c4d, 0x1c88,
- 0x1c90, 0x1cba,
- 0x1cbd, 0x1cc7,
- 0x1cd3, 0x1cd3,
- 0x1ce1, 0x1ce1,
- 0x1ce9, 0x1cec,
- 0x1cee, 0x1cf3,
- 0x1cf5, 0x1cf7,
- 0x1cfa, 0x1cfa,
- 0x1d00, 0x1dbf,
- 0x1e00, 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, 0x200a,
- 0x2010, 0x2027,
- 0x202f, 0x205f,
- 0x2070, 0x2071,
- 0x2074, 0x208e,
- 0x2090, 0x209c,
- 0x20a0, 0x20c0,
- 0x2100, 0x218b,
- 0x2190, 0x2426,
- 0x2440, 0x244a,
- 0x2460, 0x2b73,
- 0x2b76, 0x2b95,
- 0x2b97, 0x2cee,
- 0x2cf2, 0x2cf3,
- 0x2cf9, 0x2d25,
- 0x2d27, 0x2d27,
- 0x2d2d, 0x2d2d,
- 0x2d30, 0x2d67,
- 0x2d6f, 0x2d70,
- 0x2d80, 0x2d96,
- 0x2da0, 0x2da6,
- 0x2da8, 0x2dae,
- 0x2db0, 0x2db6,
- 0x2db8, 0x2dbe,
- 0x2dc0, 0x2dc6,
- 0x2dc8, 0x2dce,
- 0x2dd0, 0x2dd6,
- 0x2dd8, 0x2dde,
- 0x2e00, 0x2e5d,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x3029,
- 0x3030, 0x303f,
- 0x3041, 0x3096,
- 0x309b, 0x30ff,
- 0x3105, 0x312f,
- 0x3131, 0x318e,
- 0x3190, 0x31e3,
- 0x31f0, 0x321e,
- 0x3220, 0xa48c,
- 0xa490, 0xa4c6,
- 0xa4d0, 0xa62b,
- 0xa640, 0xa66e,
- 0xa673, 0xa673,
- 0xa67e, 0xa69d,
- 0xa6a0, 0xa6ef,
- 0xa6f2, 0xa6f7,
- 0xa700, 0xa7ca,
- 0xa7d0, 0xa7d1,
- 0xa7d3, 0xa7d3,
- 0xa7d5, 0xa7d9,
- 0xa7f2, 0xa801,
- 0xa803, 0xa805,
- 0xa807, 0xa80a,
- 0xa80c, 0xa824,
- 0xa827, 0xa82b,
- 0xa830, 0xa839,
- 0xa840, 0xa877,
- 0xa880, 0xa8c3,
- 0xa8ce, 0xa8d9,
- 0xa8f2, 0xa8fe,
- 0xa900, 0xa925,
- 0xa92e, 0xa946,
- 0xa952, 0xa953,
- 0xa95f, 0xa97c,
- 0xa983, 0xa9b2,
- 0xa9b4, 0xa9b5,
- 0xa9ba, 0xa9bb,
- 0xa9be, 0xa9cd,
- 0xa9cf, 0xa9d9,
- 0xa9de, 0xa9e4,
- 0xa9e6, 0xa9fe,
- 0xaa00, 0xaa28,
- 0xaa2f, 0xaa30,
- 0xaa33, 0xaa34,
- 0xaa40, 0xaa42,
- 0xaa44, 0xaa4b,
- 0xaa4d, 0xaa4d,
- 0xaa50, 0xaa59,
- 0xaa5c, 0xaa7b,
- 0xaa7d, 0xaaaf,
- 0xaab1, 0xaab1,
- 0xaab5, 0xaab6,
- 0xaab9, 0xaabd,
- 0xaac0, 0xaac0,
- 0xaac2, 0xaac2,
- 0xaadb, 0xaaeb,
- 0xaaee, 0xaaf5,
- 0xab01, 0xab06,
- 0xab09, 0xab0e,
- 0xab11, 0xab16,
- 0xab20, 0xab26,
- 0xab28, 0xab2e,
- 0xab30, 0xab6b,
- 0xab70, 0xabe4,
- 0xabe6, 0xabe7,
- 0xabe9, 0xabec,
- 0xabf0, 0xabf9,
- 0xac00, 0xd7a3,
- 0xd7b0, 0xd7c6,
- 0xd7cb, 0xd7fb,
- 0xf900, 0xfa6d,
- 0xfa70, 0xfad9,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1d, 0xfb1d,
- 0xfb1f, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbc2,
- 0xfbd3, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdcf, 0xfdcf,
- 0xfdf0, 0xfdff,
- 0xfe10, 0xfe19,
- 0xfe30, 0xfe52,
- 0xfe54, 0xfe66,
- 0xfe68, 0xfe6b,
- 0xfe70, 0xfe74,
- 0xfe76, 0xfefc,
- 0xff01, 0xff9d,
- 0xffa0, 0xffbe,
- 0xffc2, 0xffc7,
- 0xffca, 0xffcf,
- 0xffd2, 0xffd7,
- 0xffda, 0xffdc,
- 0xffe0, 0xffe6,
- 0xffe8, 0xffee,
- 0xfffc, 0xfffd,
- 0x10000, 0x1000b,
- 0x1000d, 0x10026,
- 0x10028, 0x1003a,
- 0x1003c, 0x1003d,
- 0x1003f, 0x1004d,
- 0x10050, 0x1005d,
- 0x10080, 0x100fa,
- 0x10100, 0x10102,
- 0x10107, 0x10133,
- 0x10137, 0x1018e,
- 0x10190, 0x1019c,
- 0x101a0, 0x101a0,
- 0x101d0, 0x101fc,
- 0x10280, 0x1029c,
- 0x102a0, 0x102d0,
- 0x102e1, 0x102fb,
- 0x10300, 0x10323,
- 0x1032d, 0x1034a,
- 0x10350, 0x10375,
- 0x10380, 0x1039d,
- 0x1039f, 0x103c3,
- 0x103c8, 0x103d5,
- 0x10400, 0x1049d,
- 0x104a0, 0x104a9,
- 0x104b0, 0x104d3,
- 0x104d8, 0x104fb,
- 0x10500, 0x10527,
- 0x10530, 0x10563,
- 0x1056f, 0x1057a,
- 0x1057c, 0x1058a,
- 0x1058c, 0x10592,
- 0x10594, 0x10595,
- 0x10597, 0x105a1,
- 0x105a3, 0x105b1,
- 0x105b3, 0x105b9,
- 0x105bb, 0x105bc,
- 0x10600, 0x10736,
- 0x10740, 0x10755,
- 0x10760, 0x10767,
- 0x10780, 0x10785,
- 0x10787, 0x107b0,
- 0x107b2, 0x107ba,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 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, 0x10a00,
- 0x10a10, 0x10a13,
- 0x10a15, 0x10a17,
- 0x10a19, 0x10a35,
- 0x10a40, 0x10a48,
- 0x10a50, 0x10a58,
- 0x10a60, 0x10a9f,
- 0x10ac0, 0x10ae4,
- 0x10aeb, 0x10af6,
- 0x10b00, 0x10b35,
- 0x10b39, 0x10b55,
- 0x10b58, 0x10b72,
- 0x10b78, 0x10b91,
- 0x10b99, 0x10b9c,
- 0x10ba9, 0x10baf,
- 0x10c00, 0x10c48,
- 0x10c80, 0x10cb2,
- 0x10cc0, 0x10cf2,
- 0x10cfa, 0x10d23,
- 0x10d30, 0x10d39,
- 0x10e60, 0x10e7e,
- 0x10e80, 0x10ea9,
- 0x10ead, 0x10ead,
- 0x10eb0, 0x10eb1,
- 0x10f00, 0x10f27,
- 0x10f30, 0x10f45,
- 0x10f51, 0x10f59,
- 0x10f70, 0x10f81,
- 0x10f86, 0x10f89,
- 0x10fb0, 0x10fcb,
- 0x10fe0, 0x10ff6,
- 0x11000, 0x11000,
- 0x11002, 0x11037,
- 0x11047, 0x1104d,
- 0x11052, 0x1106f,
- 0x11071, 0x11072,
- 0x11075, 0x11075,
- 0x11082, 0x110b2,
- 0x110b7, 0x110b8,
- 0x110bb, 0x110bc,
- 0x110be, 0x110c1,
- 0x110d0, 0x110e8,
- 0x110f0, 0x110f9,
- 0x11103, 0x11126,
- 0x1112c, 0x1112c,
- 0x11136, 0x11147,
- 0x11150, 0x11172,
- 0x11174, 0x11176,
- 0x11182, 0x111b5,
- 0x111bf, 0x111c8,
- 0x111cd, 0x111ce,
- 0x111d0, 0x111df,
- 0x111e1, 0x111f4,
- 0x11200, 0x11211,
- 0x11213, 0x1122e,
- 0x11232, 0x11233,
- 0x11235, 0x11235,
- 0x11238, 0x1123d,
- 0x1123f, 0x11240,
- 0x11280, 0x11286,
- 0x11288, 0x11288,
- 0x1128a, 0x1128d,
- 0x1128f, 0x1129d,
- 0x1129f, 0x112a9,
- 0x112b0, 0x112de,
- 0x112e0, 0x112e2,
- 0x112f0, 0x112f9,
- 0x11302, 0x11303,
- 0x11305, 0x1130c,
- 0x1130f, 0x11310,
- 0x11313, 0x11328,
- 0x1132a, 0x11330,
- 0x11332, 0x11333,
- 0x11335, 0x11339,
- 0x1133d, 0x1133d,
- 0x1133f, 0x1133f,
- 0x11341, 0x11344,
- 0x11347, 0x11348,
- 0x1134b, 0x1134d,
- 0x11350, 0x11350,
- 0x1135d, 0x11363,
- 0x11400, 0x11437,
- 0x11440, 0x11441,
- 0x11445, 0x11445,
- 0x11447, 0x1145b,
- 0x1145d, 0x1145d,
- 0x1145f, 0x11461,
- 0x11480, 0x114af,
- 0x114b1, 0x114b2,
- 0x114b9, 0x114b9,
- 0x114bb, 0x114bc,
- 0x114be, 0x114be,
- 0x114c1, 0x114c1,
- 0x114c4, 0x114c7,
- 0x114d0, 0x114d9,
- 0x11580, 0x115ae,
- 0x115b0, 0x115b1,
- 0x115b8, 0x115bb,
- 0x115be, 0x115be,
- 0x115c1, 0x115db,
- 0x11600, 0x11632,
- 0x1163b, 0x1163c,
- 0x1163e, 0x1163e,
- 0x11641, 0x11644,
- 0x11650, 0x11659,
- 0x11660, 0x1166c,
- 0x11680, 0x116aa,
- 0x116ac, 0x116ac,
- 0x116ae, 0x116af,
- 0x116b6, 0x116b6,
- 0x116b8, 0x116b9,
- 0x116c0, 0x116c9,
- 0x11700, 0x1171a,
- 0x11720, 0x11721,
- 0x11726, 0x11726,
- 0x11730, 0x11746,
- 0x11800, 0x1182e,
- 0x11838, 0x11838,
- 0x1183b, 0x1183b,
- 0x118a0, 0x118f2,
- 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,
- 0x119e1, 0x119e4,
- 0x11a00, 0x11a00,
- 0x11a0b, 0x11a32,
- 0x11a39, 0x11a3a,
- 0x11a3f, 0x11a46,
- 0x11a50, 0x11a50,
- 0x11a57, 0x11a58,
- 0x11a5c, 0x11a89,
- 0x11a97, 0x11a97,
- 0x11a9a, 0x11aa2,
- 0x11ab0, 0x11af8,
- 0x11b00, 0x11b09,
- 0x11c00, 0x11c08,
- 0x11c0a, 0x11c2f,
- 0x11c3e, 0x11c3e,
- 0x11c40, 0x11c45,
- 0x11c50, 0x11c6c,
- 0x11c70, 0x11c8f,
- 0x11ca9, 0x11ca9,
- 0x11cb1, 0x11cb1,
- 0x11cb4, 0x11cb4,
- 0x11d00, 0x11d06,
- 0x11d08, 0x11d09,
- 0x11d0b, 0x11d30,
- 0x11d46, 0x11d46,
- 0x11d50, 0x11d59,
- 0x11d60, 0x11d65,
- 0x11d67, 0x11d68,
- 0x11d6a, 0x11d8e,
- 0x11d93, 0x11d94,
- 0x11d96, 0x11d96,
- 0x11d98, 0x11d98,
- 0x11da0, 0x11da9,
- 0x11ee0, 0x11ef2,
- 0x11ef5, 0x11ef8,
- 0x11f02, 0x11f10,
- 0x11f12, 0x11f35,
- 0x11f3e, 0x11f3f,
- 0x11f41, 0x11f41,
- 0x11f43, 0x11f59,
- 0x11fb0, 0x11fb0,
- 0x11fc0, 0x11ff1,
- 0x11fff, 0x12399,
- 0x12400, 0x1246e,
- 0x12470, 0x12474,
- 0x12480, 0x12543,
- 0x12f90, 0x12ff2,
- 0x13000, 0x1342f,
- 0x13441, 0x13446,
- 0x14400, 0x14646,
- 0x16800, 0x16a38,
- 0x16a40, 0x16a5e,
- 0x16a60, 0x16a69,
- 0x16a6e, 0x16abe,
- 0x16ac0, 0x16ac9,
- 0x16ad0, 0x16aed,
- 0x16af5, 0x16af5,
- 0x16b00, 0x16b2f,
- 0x16b37, 0x16b45,
- 0x16b50, 0x16b59,
- 0x16b5b, 0x16b61,
- 0x16b63, 0x16b77,
- 0x16b7d, 0x16b8f,
- 0x16e40, 0x16e9a,
- 0x16f00, 0x16f4a,
- 0x16f50, 0x16f87,
- 0x16f93, 0x16f9f,
- 0x16fe0, 0x16fe3,
- 0x16ff0, 0x16ff1,
- 0x17000, 0x187f7,
- 0x18800, 0x18cd5,
- 0x18d00, 0x18d08,
- 0x1aff0, 0x1aff3,
- 0x1aff5, 0x1affb,
- 0x1affd, 0x1affe,
- 0x1b000, 0x1b122,
- 0x1b132, 0x1b132,
- 0x1b150, 0x1b152,
- 0x1b155, 0x1b155,
- 0x1b164, 0x1b167,
- 0x1b170, 0x1b2fb,
- 0x1bc00, 0x1bc6a,
- 0x1bc70, 0x1bc7c,
- 0x1bc80, 0x1bc88,
- 0x1bc90, 0x1bc99,
- 0x1bc9c, 0x1bc9c,
- 0x1bc9f, 0x1bc9f,
- 0x1cf50, 0x1cfc3,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d129, 0x1d164,
- 0x1d166, 0x1d166,
- 0x1d16a, 0x1d16d,
- 0x1d183, 0x1d184,
- 0x1d18c, 0x1d1a9,
- 0x1d1ae, 0x1d1ea,
- 0x1d200, 0x1d241,
- 0x1d245, 0x1d245,
- 0x1d2c0, 0x1d2d3,
- 0x1d2e0, 0x1d2f3,
- 0x1d300, 0x1d356,
- 0x1d360, 0x1d378,
- 0x1d400, 0x1d454,
- 0x1d456, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 0x1d4a2, 0x1d4a2,
- 0x1d4a5, 0x1d4a6,
- 0x1d4a9, 0x1d4ac,
- 0x1d4ae, 0x1d4b9,
- 0x1d4bb, 0x1d4bb,
- 0x1d4bd, 0x1d4c3,
- 0x1d4c5, 0x1d505,
- 0x1d507, 0x1d50a,
- 0x1d50d, 0x1d514,
- 0x1d516, 0x1d51c,
- 0x1d51e, 0x1d539,
- 0x1d53b, 0x1d53e,
- 0x1d540, 0x1d544,
- 0x1d546, 0x1d546,
- 0x1d54a, 0x1d550,
- 0x1d552, 0x1d6a5,
- 0x1d6a8, 0x1d7cb,
- 0x1d7ce, 0x1d9ff,
- 0x1da37, 0x1da3a,
- 0x1da6d, 0x1da74,
- 0x1da76, 0x1da83,
- 0x1da85, 0x1da8b,
- 0x1df00, 0x1df1e,
- 0x1df25, 0x1df2a,
- 0x1e030, 0x1e06d,
- 0x1e100, 0x1e12c,
- 0x1e137, 0x1e13d,
- 0x1e140, 0x1e149,
- 0x1e14e, 0x1e14f,
- 0x1e290, 0x1e2ad,
- 0x1e2c0, 0x1e2eb,
- 0x1e2f0, 0x1e2f9,
- 0x1e2ff, 0x1e2ff,
- 0x1e4d0, 0x1e4eb,
- 0x1e4f0, 0x1e4f9,
- 0x1e7e0, 0x1e7e6,
- 0x1e7e8, 0x1e7eb,
- 0x1e7ed, 0x1e7ee,
- 0x1e7f0, 0x1e7fe,
- 0x1e800, 0x1e8c4,
- 0x1e8c7, 0x1e8cf,
- 0x1e900, 0x1e943,
- 0x1e94b, 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,
- 0x1f6dc, 0x1f6ec,
- 0x1f6f0, 0x1f6fc,
- 0x1f700, 0x1f776,
- 0x1f77b, 0x1f7d9,
- 0x1f7e0, 0x1f7eb,
- 0x1f7f0, 0x1f7f0,
- 0x1f800, 0x1f80b,
- 0x1f810, 0x1f847,
- 0x1f850, 0x1f859,
- 0x1f860, 0x1f887,
- 0x1f890, 0x1f8ad,
- 0x1f8b0, 0x1f8b1,
- 0x1f900, 0x1fa53,
- 0x1fa60, 0x1fa6d,
- 0x1fa70, 0x1fa7c,
- 0x1fa80, 0x1fa88,
- 0x1fa90, 0x1fabd,
- 0x1fabf, 0x1fac5,
- 0x1face, 0x1fadb,
- 0x1fae0, 0x1fae8,
- 0x1faf0, 0x1faf8,
- 0x1fb00, 0x1fb92,
- 0x1fb94, 0x1fbca,
- 0x1fbf0, 0x1fbf9,
- 0x20000, 0x2a6df,
- 0x2a700, 0x2b739,
- 0x2b740, 0x2b81d,
- 0x2b820, 0x2cea1,
- 0x2ceb0, 0x2ebe0,
- 0x2f800, 0x2fa1d,
- 0x30000, 0x3134a,
- 0x31350, 0x323af,
-}; /* CR_Grapheme_Base */
-
-/* 'Grapheme_Link': Derived Property */
-static const OnigCodePoint CR_Grapheme_Link[] = {
- 56,
- 0x094d, 0x094d,
- 0x09cd, 0x09cd,
- 0x0a4d, 0x0a4d,
- 0x0acd, 0x0acd,
- 0x0b4d, 0x0b4d,
- 0x0bcd, 0x0bcd,
- 0x0c4d, 0x0c4d,
- 0x0ccd, 0x0ccd,
- 0x0d3b, 0x0d3c,
- 0x0d4d, 0x0d4d,
- 0x0dca, 0x0dca,
- 0x0e3a, 0x0e3a,
- 0x0eba, 0x0eba,
- 0x0f84, 0x0f84,
- 0x1039, 0x103a,
- 0x1714, 0x1715,
- 0x1734, 0x1734,
- 0x17d2, 0x17d2,
- 0x1a60, 0x1a60,
- 0x1b44, 0x1b44,
- 0x1baa, 0x1bab,
- 0x1bf2, 0x1bf3,
- 0x2d7f, 0x2d7f,
- 0xa806, 0xa806,
- 0xa82c, 0xa82c,
- 0xa8c4, 0xa8c4,
- 0xa953, 0xa953,
- 0xa9c0, 0xa9c0,
- 0xaaf6, 0xaaf6,
- 0xabed, 0xabed,
- 0x10a3f, 0x10a3f,
- 0x11046, 0x11046,
- 0x11070, 0x11070,
- 0x1107f, 0x1107f,
- 0x110b9, 0x110b9,
- 0x11133, 0x11134,
- 0x111c0, 0x111c0,
- 0x11235, 0x11235,
- 0x112ea, 0x112ea,
- 0x1134d, 0x1134d,
- 0x11442, 0x11442,
- 0x114c2, 0x114c2,
- 0x115bf, 0x115bf,
- 0x1163f, 0x1163f,
- 0x116b6, 0x116b6,
- 0x1172b, 0x1172b,
- 0x11839, 0x11839,
- 0x1193d, 0x1193e,
- 0x119e0, 0x119e0,
- 0x11a34, 0x11a34,
- 0x11a47, 0x11a47,
- 0x11a99, 0x11a99,
- 0x11c3f, 0x11c3f,
- 0x11d44, 0x11d45,
- 0x11d97, 0x11d97,
- 0x11f41, 0x11f42,
-}; /* CR_Grapheme_Link */
-
-/* 'Common': Script */
-static const OnigCodePoint CR_Common[] = {
- 173,
- 0x0000, 0x0040,
- 0x005b, 0x0060,
- 0x007b, 0x00a9,
- 0x00ab, 0x00b9,
- 0x00bb, 0x00bf,
- 0x00d7, 0x00d7,
- 0x00f7, 0x00f7,
- 0x02b9, 0x02df,
- 0x02e5, 0x02e9,
- 0x02ec, 0x02ff,
- 0x0374, 0x0374,
- 0x037e, 0x037e,
- 0x0385, 0x0385,
- 0x0387, 0x0387,
- 0x0605, 0x0605,
- 0x060c, 0x060c,
- 0x061b, 0x061b,
- 0x061f, 0x061f,
- 0x0640, 0x0640,
- 0x06dd, 0x06dd,
- 0x08e2, 0x08e2,
- 0x0964, 0x0965,
- 0x0e3f, 0x0e3f,
- 0x0fd5, 0x0fd8,
- 0x10fb, 0x10fb,
- 0x16eb, 0x16ed,
- 0x1735, 0x1736,
- 0x1802, 0x1803,
- 0x1805, 0x1805,
- 0x1cd3, 0x1cd3,
- 0x1ce1, 0x1ce1,
- 0x1ce9, 0x1cec,
- 0x1cee, 0x1cf3,
- 0x1cf5, 0x1cf7,
- 0x1cfa, 0x1cfa,
- 0x2000, 0x200b,
- 0x200e, 0x2064,
- 0x2066, 0x2070,
- 0x2074, 0x207e,
- 0x2080, 0x208e,
- 0x20a0, 0x20c0,
- 0x2100, 0x2125,
- 0x2127, 0x2129,
- 0x212c, 0x2131,
- 0x2133, 0x214d,
- 0x214f, 0x215f,
- 0x2189, 0x218b,
- 0x2190, 0x2426,
- 0x2440, 0x244a,
- 0x2460, 0x27ff,
- 0x2900, 0x2b73,
- 0x2b76, 0x2b95,
- 0x2b97, 0x2bff,
- 0x2e00, 0x2e5d,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x3004,
- 0x3006, 0x3006,
- 0x3008, 0x3020,
- 0x3030, 0x3037,
- 0x303c, 0x303f,
- 0x309b, 0x309c,
- 0x30a0, 0x30a0,
- 0x30fb, 0x30fc,
- 0x3190, 0x319f,
- 0x31c0, 0x31e3,
- 0x3220, 0x325f,
- 0x327f, 0x32cf,
- 0x32ff, 0x32ff,
- 0x3358, 0x33ff,
- 0x4dc0, 0x4dff,
- 0xa700, 0xa721,
- 0xa788, 0xa78a,
- 0xa830, 0xa839,
- 0xa92e, 0xa92e,
- 0xa9cf, 0xa9cf,
- 0xab5b, 0xab5b,
- 0xab6a, 0xab6b,
- 0xfd3e, 0xfd3f,
- 0xfe10, 0xfe19,
- 0xfe30, 0xfe52,
- 0xfe54, 0xfe66,
- 0xfe68, 0xfe6b,
- 0xfeff, 0xfeff,
- 0xff01, 0xff20,
- 0xff3b, 0xff40,
- 0xff5b, 0xff65,
- 0xff70, 0xff70,
- 0xff9e, 0xff9f,
- 0xffe0, 0xffe6,
- 0xffe8, 0xffee,
- 0xfff9, 0xfffd,
- 0x10100, 0x10102,
- 0x10107, 0x10133,
- 0x10137, 0x1013f,
- 0x10190, 0x1019c,
- 0x101d0, 0x101fc,
- 0x102e1, 0x102fb,
- 0x1bca0, 0x1bca3,
- 0x1cf50, 0x1cfc3,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d129, 0x1d166,
- 0x1d16a, 0x1d17a,
- 0x1d183, 0x1d184,
- 0x1d18c, 0x1d1a9,
- 0x1d1ae, 0x1d1ea,
- 0x1d2c0, 0x1d2d3,
- 0x1d2e0, 0x1d2f3,
- 0x1d300, 0x1d356,
- 0x1d360, 0x1d378,
- 0x1d400, 0x1d454,
- 0x1d456, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 0x1d4a2, 0x1d4a2,
- 0x1d4a5, 0x1d4a6,
- 0x1d4a9, 0x1d4ac,
- 0x1d4ae, 0x1d4b9,
- 0x1d4bb, 0x1d4bb,
- 0x1d4bd, 0x1d4c3,
- 0x1d4c5, 0x1d505,
- 0x1d507, 0x1d50a,
- 0x1d50d, 0x1d514,
- 0x1d516, 0x1d51c,
- 0x1d51e, 0x1d539,
- 0x1d53b, 0x1d53e,
- 0x1d540, 0x1d544,
- 0x1d546, 0x1d546,
- 0x1d54a, 0x1d550,
- 0x1d552, 0x1d6a5,
- 0x1d6a8, 0x1d7cb,
- 0x1d7ce, 0x1d7ff,
- 0x1ec71, 0x1ecb4,
- 0x1ed01, 0x1ed3d,
- 0x1f000, 0x1f02b,
- 0x1f030, 0x1f093,
- 0x1f0a0, 0x1f0ae,
- 0x1f0b1, 0x1f0bf,
- 0x1f0c1, 0x1f0cf,
- 0x1f0d1, 0x1f0f5,
- 0x1f100, 0x1f1ad,
- 0x1f1e6, 0x1f1ff,
- 0x1f201, 0x1f202,
- 0x1f210, 0x1f23b,
- 0x1f240, 0x1f248,
- 0x1f250, 0x1f251,
- 0x1f260, 0x1f265,
- 0x1f300, 0x1f6d7,
- 0x1f6dc, 0x1f6ec,
- 0x1f6f0, 0x1f6fc,
- 0x1f700, 0x1f776,
- 0x1f77b, 0x1f7d9,
- 0x1f7e0, 0x1f7eb,
- 0x1f7f0, 0x1f7f0,
- 0x1f800, 0x1f80b,
- 0x1f810, 0x1f847,
- 0x1f850, 0x1f859,
- 0x1f860, 0x1f887,
- 0x1f890, 0x1f8ad,
- 0x1f8b0, 0x1f8b1,
- 0x1f900, 0x1fa53,
- 0x1fa60, 0x1fa6d,
- 0x1fa70, 0x1fa7c,
- 0x1fa80, 0x1fa88,
- 0x1fa90, 0x1fabd,
- 0x1fabf, 0x1fac5,
- 0x1face, 0x1fadb,
- 0x1fae0, 0x1fae8,
- 0x1faf0, 0x1faf8,
- 0x1fb00, 0x1fb92,
- 0x1fb94, 0x1fbca,
- 0x1fbf0, 0x1fbf9,
- 0xe0001, 0xe0001,
- 0xe0020, 0xe007f,
-}; /* CR_Common */
-
-/* 'Latin': Script */
-static const OnigCodePoint CR_Latin[] = {
- 39,
- 0x0041, 0x005a,
- 0x0061, 0x007a,
- 0x00aa, 0x00aa,
- 0x00ba, 0x00ba,
- 0x00c0, 0x00d6,
- 0x00d8, 0x00f6,
- 0x00f8, 0x02b8,
- 0x02e0, 0x02e4,
- 0x1d00, 0x1d25,
- 0x1d2c, 0x1d5c,
- 0x1d62, 0x1d65,
- 0x1d6b, 0x1d77,
- 0x1d79, 0x1dbe,
- 0x1e00, 0x1eff,
- 0x2071, 0x2071,
- 0x207f, 0x207f,
- 0x2090, 0x209c,
- 0x212a, 0x212b,
- 0x2132, 0x2132,
- 0x214e, 0x214e,
- 0x2160, 0x2188,
- 0x2c60, 0x2c7f,
- 0xa722, 0xa787,
- 0xa78b, 0xa7ca,
- 0xa7d0, 0xa7d1,
- 0xa7d3, 0xa7d3,
- 0xa7d5, 0xa7d9,
- 0xa7f2, 0xa7ff,
- 0xab30, 0xab5a,
- 0xab5c, 0xab64,
- 0xab66, 0xab69,
- 0xfb00, 0xfb06,
- 0xff21, 0xff3a,
- 0xff41, 0xff5a,
- 0x10780, 0x10785,
- 0x10787, 0x107b0,
- 0x107b2, 0x107ba,
- 0x1df00, 0x1df1e,
- 0x1df25, 0x1df2a,
-}; /* CR_Latin */
-
-/* 'Greek': Script */
-static const OnigCodePoint CR_Greek[] = {
- 36,
- 0x0370, 0x0373,
- 0x0375, 0x0377,
- 0x037a, 0x037d,
- 0x037f, 0x037f,
- 0x0384, 0x0384,
- 0x0386, 0x0386,
- 0x0388, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03e1,
- 0x03f0, 0x03ff,
- 0x1d26, 0x1d2a,
- 0x1d5d, 0x1d61,
- 0x1d66, 0x1d6a,
- 0x1dbf, 0x1dbf,
- 0x1f00, 0x1f15,
- 0x1f18, 0x1f1d,
- 0x1f20, 0x1f45,
- 0x1f48, 0x1f4d,
- 0x1f50, 0x1f57,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f7d,
- 0x1f80, 0x1fb4,
- 0x1fb6, 0x1fc4,
- 0x1fc6, 0x1fd3,
- 0x1fd6, 0x1fdb,
- 0x1fdd, 0x1fef,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ffe,
- 0x2126, 0x2126,
- 0xab65, 0xab65,
- 0x10140, 0x1018e,
- 0x101a0, 0x101a0,
- 0x1d200, 0x1d245,
-}; /* CR_Greek */
-
-/* 'Cyrillic': Script */
-static const OnigCodePoint CR_Cyrillic[] = {
- 10,
- 0x0400, 0x0484,
- 0x0487, 0x052f,
- 0x1c80, 0x1c88,
- 0x1d2b, 0x1d2b,
- 0x1d78, 0x1d78,
- 0x2de0, 0x2dff,
- 0xa640, 0xa69f,
- 0xfe2e, 0xfe2f,
- 0x1e030, 0x1e06d,
- 0x1e08f, 0x1e08f,
-}; /* CR_Cyrillic */
-
-/* 'Armenian': Script */
-static const OnigCodePoint CR_Armenian[] = {
- 4,
- 0x0531, 0x0556,
- 0x0559, 0x058a,
- 0x058d, 0x058f,
- 0xfb13, 0xfb17,
-}; /* CR_Armenian */
-
-/* 'Hebrew': Script */
-static const OnigCodePoint CR_Hebrew[] = {
- 9,
- 0x0591, 0x05c7,
- 0x05d0, 0x05ea,
- 0x05ef, 0x05f4,
- 0xfb1d, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfb4f,
-}; /* CR_Hebrew */
-
-/* 'Arabic': Script */
-static const OnigCodePoint CR_Arabic[] = {
- 58,
- 0x0600, 0x0604,
- 0x0606, 0x060b,
- 0x060d, 0x061a,
- 0x061c, 0x061e,
- 0x0620, 0x063f,
- 0x0641, 0x064a,
- 0x0656, 0x066f,
- 0x0671, 0x06dc,
- 0x06de, 0x06ff,
- 0x0750, 0x077f,
- 0x0870, 0x088e,
- 0x0890, 0x0891,
- 0x0898, 0x08e1,
- 0x08e3, 0x08ff,
- 0xfb50, 0xfbc2,
- 0xfbd3, 0xfd3d,
- 0xfd40, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdcf, 0xfdcf,
- 0xfdf0, 0xfdff,
- 0xfe70, 0xfe74,
- 0xfe76, 0xfefc,
- 0x10e60, 0x10e7e,
- 0x10efd, 0x10eff,
- 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,
-}; /* CR_Arabic */
-
-/* 'Syriac': Script */
-static const OnigCodePoint CR_Syriac[] = {
- 4,
- 0x0700, 0x070d,
- 0x070f, 0x074a,
- 0x074d, 0x074f,
- 0x0860, 0x086a,
-}; /* CR_Syriac */
-
-/* 'Thaana': Script */
-static const OnigCodePoint CR_Thaana[] = {
- 1,
- 0x0780, 0x07b1,
-}; /* CR_Thaana */
-
-/* 'Devanagari': Script */
-static const OnigCodePoint CR_Devanagari[] = {
- 5,
- 0x0900, 0x0950,
- 0x0955, 0x0963,
- 0x0966, 0x097f,
- 0xa8e0, 0xa8ff,
- 0x11b00, 0x11b09,
-}; /* CR_Devanagari */
-
-/* 'Bengali': Script */
-static const OnigCodePoint CR_Bengali[] = {
- 14,
- 0x0980, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fe,
-}; /* CR_Bengali */
-
-/* 'Gurmukhi': Script */
-static const OnigCodePoint CR_Gurmukhi[] = {
- 16,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a51, 0x0a51,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a76,
-}; /* CR_Gurmukhi */
-
-/* 'Gujarati': Script */
-static const OnigCodePoint CR_Gujarati[] = {
- 14,
- 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,
-}; /* CR_Gujarati */
-
-/* 'Oriya': Script */
-static const OnigCodePoint CR_Oriya[] = {
- 14,
- 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,
-}; /* CR_Oriya */
-
-/* 'Tamil': Script */
-static const OnigCodePoint CR_Tamil[] = {
- 18,
- 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,
- 0x0be6, 0x0bfa,
- 0x11fc0, 0x11ff1,
- 0x11fff, 0x11fff,
-}; /* CR_Tamil */
-
-/* 'Telugu': Script */
-static const OnigCodePoint CR_Telugu[] = {
- 13,
- 0x0c00, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c39,
- 0x0c3c, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c58, 0x0c5a,
- 0x0c5d, 0x0c5d,
- 0x0c60, 0x0c63,
- 0x0c66, 0x0c6f,
- 0x0c77, 0x0c7f,
-}; /* CR_Telugu */
-
-/* 'Kannada': Script */
-static const OnigCodePoint CR_Kannada[] = {
- 13,
- 0x0c80, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cdd, 0x0cde,
- 0x0ce0, 0x0ce3,
- 0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf3,
-}; /* CR_Kannada */
-
-/* 'Malayalam': Script */
-static const OnigCodePoint CR_Malayalam[] = {
- 7,
- 0x0d00, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d44,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4f,
- 0x0d54, 0x0d63,
- 0x0d66, 0x0d7f,
-}; /* CR_Malayalam */
-
-/* 'Sinhala': Script */
-static const OnigCodePoint CR_Sinhala[] = {
- 13,
- 0x0d81, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0de6, 0x0def,
- 0x0df2, 0x0df4,
- 0x111e1, 0x111f4,
-}; /* CR_Sinhala */
-
-/* 'Thai': Script */
-static const OnigCodePoint CR_Thai[] = {
- 2,
- 0x0e01, 0x0e3a,
- 0x0e40, 0x0e5b,
-}; /* CR_Thai */
-
-/* 'Lao': Script */
-static const OnigCodePoint CR_Lao[] = {
- 11,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e86, 0x0e8a,
- 0x0e8c, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ece,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edf,
-}; /* CR_Lao */
-
-/* 'Tibetan': Script */
-static const OnigCodePoint CR_Tibetan[] = {
- 7,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f71, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x0fbe, 0x0fcc,
- 0x0fce, 0x0fd4,
- 0x0fd9, 0x0fda,
-}; /* CR_Tibetan */
-
-/* 'Myanmar': Script */
-static const OnigCodePoint CR_Myanmar[] = {
- 3,
- 0x1000, 0x109f,
- 0xa9e0, 0xa9fe,
- 0xaa60, 0xaa7f,
-}; /* CR_Myanmar */
-
-/* 'Georgian': Script */
-static const OnigCodePoint CR_Georgian[] = {
- 10,
- 0x10a0, 0x10c5,
- 0x10c7, 0x10c7,
- 0x10cd, 0x10cd,
- 0x10d0, 0x10fa,
- 0x10fc, 0x10ff,
- 0x1c90, 0x1cba,
- 0x1cbd, 0x1cbf,
- 0x2d00, 0x2d25,
- 0x2d27, 0x2d27,
- 0x2d2d, 0x2d2d,
-}; /* CR_Georgian */
-
-/* 'Hangul': Script */
-static const OnigCodePoint CR_Hangul[] = {
- 14,
- 0x1100, 0x11ff,
- 0x302e, 0x302f,
- 0x3131, 0x318e,
- 0x3200, 0x321e,
- 0x3260, 0x327e,
- 0xa960, 0xa97c,
- 0xac00, 0xd7a3,
- 0xd7b0, 0xd7c6,
- 0xd7cb, 0xd7fb,
- 0xffa0, 0xffbe,
- 0xffc2, 0xffc7,
- 0xffca, 0xffcf,
- 0xffd2, 0xffd7,
- 0xffda, 0xffdc,
-}; /* CR_Hangul */
-
-/* 'Ethiopic': Script */
-static const OnigCodePoint CR_Ethiopic[] = {
- 36,
- 0x1200, 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,
- 0x2d80, 0x2d96,
- 0x2da0, 0x2da6,
- 0x2da8, 0x2dae,
- 0x2db0, 0x2db6,
- 0x2db8, 0x2dbe,
- 0x2dc0, 0x2dc6,
- 0x2dc8, 0x2dce,
- 0x2dd0, 0x2dd6,
- 0x2dd8, 0x2dde,
- 0xab01, 0xab06,
- 0xab09, 0xab0e,
- 0xab11, 0xab16,
- 0xab20, 0xab26,
- 0xab28, 0xab2e,
- 0x1e7e0, 0x1e7e6,
- 0x1e7e8, 0x1e7eb,
- 0x1e7ed, 0x1e7ee,
- 0x1e7f0, 0x1e7fe,
-}; /* CR_Ethiopic */
-
-/* 'Cherokee': Script */
-static const OnigCodePoint CR_Cherokee[] = {
- 3,
- 0x13a0, 0x13f5,
- 0x13f8, 0x13fd,
- 0xab70, 0xabbf,
-}; /* CR_Cherokee */
-
-/* 'Canadian_Aboriginal': Script */
-static const OnigCodePoint CR_Canadian_Aboriginal[] = {
- 3,
- 0x1400, 0x167f,
- 0x18b0, 0x18f5,
- 0x11ab0, 0x11abf,
-}; /* CR_Canadian_Aboriginal */
-
-/* 'Ogham': Script */
-static const OnigCodePoint CR_Ogham[] = {
- 1,
- 0x1680, 0x169c,
-}; /* CR_Ogham */
-
-/* 'Runic': Script */
-static const OnigCodePoint CR_Runic[] = {
- 2,
- 0x16a0, 0x16ea,
- 0x16ee, 0x16f8,
-}; /* CR_Runic */
-
-/* 'Khmer': Script */
-static const OnigCodePoint CR_Khmer[] = {
- 4,
- 0x1780, 0x17dd,
- 0x17e0, 0x17e9,
- 0x17f0, 0x17f9,
- 0x19e0, 0x19ff,
-}; /* CR_Khmer */
-
-/* 'Mongolian': Script */
-static const OnigCodePoint CR_Mongolian[] = {
- 6,
- 0x1800, 0x1801,
- 0x1804, 0x1804,
- 0x1806, 0x1819,
- 0x1820, 0x1878,
- 0x1880, 0x18aa,
- 0x11660, 0x1166c,
-}; /* CR_Mongolian */
-
-/* 'Hiragana': Script */
-static const OnigCodePoint CR_Hiragana[] = {
- 6,
- 0x3041, 0x3096,
- 0x309d, 0x309f,
- 0x1b001, 0x1b11f,
- 0x1b132, 0x1b132,
- 0x1b150, 0x1b152,
- 0x1f200, 0x1f200,
-}; /* CR_Hiragana */
-
-/* 'Katakana': Script */
-static const OnigCodePoint CR_Katakana[] = {
- 14,
- 0x30a1, 0x30fa,
- 0x30fd, 0x30ff,
- 0x31f0, 0x31ff,
- 0x32d0, 0x32fe,
- 0x3300, 0x3357,
- 0xff66, 0xff6f,
- 0xff71, 0xff9d,
- 0x1aff0, 0x1aff3,
- 0x1aff5, 0x1affb,
- 0x1affd, 0x1affe,
- 0x1b000, 0x1b000,
- 0x1b120, 0x1b122,
- 0x1b155, 0x1b155,
- 0x1b164, 0x1b167,
-}; /* CR_Katakana */
-
-/* 'Bopomofo': Script */
-static const OnigCodePoint CR_Bopomofo[] = {
- 3,
- 0x02ea, 0x02eb,
- 0x3105, 0x312f,
- 0x31a0, 0x31bf,
-}; /* CR_Bopomofo */
-
-/* 'Han': Script */
-static const OnigCodePoint CR_Han[] = {
- 21,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x3005, 0x3005,
- 0x3007, 0x3007,
- 0x3021, 0x3029,
- 0x3038, 0x303b,
- 0x3400, 0x4dbf,
- 0x4e00, 0x9fff,
- 0xf900, 0xfa6d,
- 0xfa70, 0xfad9,
- 0x16fe2, 0x16fe3,
- 0x16ff0, 0x16ff1,
- 0x20000, 0x2a6df,
- 0x2a700, 0x2b739,
- 0x2b740, 0x2b81d,
- 0x2b820, 0x2cea1,
- 0x2ceb0, 0x2ebe0,
- 0x2f800, 0x2fa1d,
- 0x30000, 0x3134a,
- 0x31350, 0x323af,
-}; /* CR_Han */
-
-/* 'Yi': Script */
-static const OnigCodePoint CR_Yi[] = {
- 2,
- 0xa000, 0xa48c,
- 0xa490, 0xa4c6,
-}; /* CR_Yi */
-
-/* 'Old_Italic': Script */
-static const OnigCodePoint CR_Old_Italic[] = {
- 2,
- 0x10300, 0x10323,
- 0x1032d, 0x1032f,
-}; /* CR_Old_Italic */
-
-/* 'Gothic': Script */
-static const OnigCodePoint CR_Gothic[] = {
- 1,
- 0x10330, 0x1034a,
-}; /* CR_Gothic */
-
-/* 'Deseret': Script */
-static const OnigCodePoint CR_Deseret[] = {
- 1,
- 0x10400, 0x1044f,
-}; /* CR_Deseret */
-
-/* 'Inherited': Script */
-static const OnigCodePoint CR_Inherited[] = {
- 29,
- 0x0300, 0x036f,
- 0x0485, 0x0486,
- 0x064b, 0x0655,
- 0x0670, 0x0670,
- 0x0951, 0x0954,
- 0x1ab0, 0x1ace,
- 0x1cd0, 0x1cd2,
- 0x1cd4, 0x1ce0,
- 0x1ce2, 0x1ce8,
- 0x1ced, 0x1ced,
- 0x1cf4, 0x1cf4,
- 0x1cf8, 0x1cf9,
- 0x1dc0, 0x1dff,
- 0x200c, 0x200d,
- 0x20d0, 0x20f0,
- 0x302a, 0x302d,
- 0x3099, 0x309a,
- 0xfe00, 0xfe0f,
- 0xfe20, 0xfe2d,
- 0x101fd, 0x101fd,
- 0x102e0, 0x102e0,
- 0x1133b, 0x1133b,
- 0x1cf00, 0x1cf2d,
- 0x1cf30, 0x1cf46,
- 0x1d167, 0x1d169,
- 0x1d17b, 0x1d182,
- 0x1d185, 0x1d18b,
- 0x1d1aa, 0x1d1ad,
- 0xe0100, 0xe01ef,
-}; /* CR_Inherited */
-
-/* 'Tagalog': Script */
-static const OnigCodePoint CR_Tagalog[] = {
- 2,
- 0x1700, 0x1715,
- 0x171f, 0x171f,
-}; /* CR_Tagalog */
-
-/* 'Hanunoo': Script */
-static const OnigCodePoint CR_Hanunoo[] = {
- 1,
- 0x1720, 0x1734,
-}; /* CR_Hanunoo */
-
-/* 'Buhid': Script */
-static const OnigCodePoint CR_Buhid[] = {
- 1,
- 0x1740, 0x1753,
-}; /* CR_Buhid */
-
-/* 'Tagbanwa': Script */
-static const OnigCodePoint CR_Tagbanwa[] = {
- 3,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
-}; /* CR_Tagbanwa */
-
-/* 'Limbu': Script */
-static const OnigCodePoint CR_Limbu[] = {
- 5,
- 0x1900, 0x191e,
- 0x1920, 0x192b,
- 0x1930, 0x193b,
- 0x1940, 0x1940,
- 0x1944, 0x194f,
-}; /* CR_Limbu */
-
-/* 'Tai_Le': Script */
-static const OnigCodePoint CR_Tai_Le[] = {
- 2,
- 0x1950, 0x196d,
- 0x1970, 0x1974,
-}; /* CR_Tai_Le */
-
-/* 'Linear_B': Script */
-static const OnigCodePoint CR_Linear_B[] = {
- 7,
- 0x10000, 0x1000b,
- 0x1000d, 0x10026,
- 0x10028, 0x1003a,
- 0x1003c, 0x1003d,
- 0x1003f, 0x1004d,
- 0x10050, 0x1005d,
- 0x10080, 0x100fa,
-}; /* CR_Linear_B */
-
-/* 'Ugaritic': Script */
-static const OnigCodePoint CR_Ugaritic[] = {
- 2,
- 0x10380, 0x1039d,
- 0x1039f, 0x1039f,
-}; /* CR_Ugaritic */
-
-/* 'Shavian': Script */
-static const OnigCodePoint CR_Shavian[] = {
- 1,
- 0x10450, 0x1047f,
-}; /* CR_Shavian */
-
-/* 'Osmanya': Script */
-static const OnigCodePoint CR_Osmanya[] = {
- 2,
- 0x10480, 0x1049d,
- 0x104a0, 0x104a9,
-}; /* CR_Osmanya */
-
-/* 'Cypriot': Script */
-static const OnigCodePoint CR_Cypriot[] = {
- 6,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x1083f,
-}; /* CR_Cypriot */
-
-/* 'Braille': Script */
-static const OnigCodePoint CR_Braille[] = {
- 1,
- 0x2800, 0x28ff,
-}; /* CR_Braille */
-
-/* 'Buginese': Script */
-static const OnigCodePoint CR_Buginese[] = {
- 2,
- 0x1a00, 0x1a1b,
- 0x1a1e, 0x1a1f,
-}; /* CR_Buginese */
-
-/* 'Coptic': Script */
-static const OnigCodePoint CR_Coptic[] = {
- 3,
- 0x03e2, 0x03ef,
- 0x2c80, 0x2cf3,
- 0x2cf9, 0x2cff,
-}; /* CR_Coptic */
-
-/* 'New_Tai_Lue': Script */
-static const OnigCodePoint CR_New_Tai_Lue[] = {
- 4,
- 0x1980, 0x19ab,
- 0x19b0, 0x19c9,
- 0x19d0, 0x19da,
- 0x19de, 0x19df,
-}; /* CR_New_Tai_Lue */
-
-/* 'Glagolitic': Script */
-static const OnigCodePoint CR_Glagolitic[] = {
- 6,
- 0x2c00, 0x2c5f,
- 0x1e000, 0x1e006,
- 0x1e008, 0x1e018,
- 0x1e01b, 0x1e021,
- 0x1e023, 0x1e024,
- 0x1e026, 0x1e02a,
-}; /* CR_Glagolitic */
-
-/* 'Tifinagh': Script */
-static const OnigCodePoint CR_Tifinagh[] = {
- 3,
- 0x2d30, 0x2d67,
- 0x2d6f, 0x2d70,
- 0x2d7f, 0x2d7f,
-}; /* CR_Tifinagh */
-
-/* 'Syloti_Nagri': Script */
-static const OnigCodePoint CR_Syloti_Nagri[] = {
- 1,
- 0xa800, 0xa82c,
-}; /* CR_Syloti_Nagri */
-
-/* 'Old_Persian': Script */
-static const OnigCodePoint CR_Old_Persian[] = {
- 2,
- 0x103a0, 0x103c3,
- 0x103c8, 0x103d5,
-}; /* CR_Old_Persian */
-
-/* 'Kharoshthi': Script */
-static const OnigCodePoint CR_Kharoshthi[] = {
- 8,
- 0x10a00, 0x10a03,
- 0x10a05, 0x10a06,
- 0x10a0c, 0x10a13,
- 0x10a15, 0x10a17,
- 0x10a19, 0x10a35,
- 0x10a38, 0x10a3a,
- 0x10a3f, 0x10a48,
- 0x10a50, 0x10a58,
-}; /* CR_Kharoshthi */
-
-/* 'Balinese': Script */
-static const OnigCodePoint CR_Balinese[] = {
- 2,
- 0x1b00, 0x1b4c,
- 0x1b50, 0x1b7e,
-}; /* CR_Balinese */
-
-/* 'Cuneiform': Script */
-static const OnigCodePoint CR_Cuneiform[] = {
- 4,
- 0x12000, 0x12399,
- 0x12400, 0x1246e,
- 0x12470, 0x12474,
- 0x12480, 0x12543,
-}; /* CR_Cuneiform */
-
-/* 'Phoenician': Script */
-static const OnigCodePoint CR_Phoenician[] = {
- 2,
- 0x10900, 0x1091b,
- 0x1091f, 0x1091f,
-}; /* CR_Phoenician */
-
-/* 'Phags_Pa': Script */
-static const OnigCodePoint CR_Phags_Pa[] = {
- 1,
- 0xa840, 0xa877,
-}; /* CR_Phags_Pa */
-
-/* 'Nko': Script */
-static const OnigCodePoint CR_Nko[] = {
- 2,
- 0x07c0, 0x07fa,
- 0x07fd, 0x07ff,
-}; /* CR_Nko */
-
-/* 'Sundanese': Script */
-static const OnigCodePoint CR_Sundanese[] = {
- 2,
- 0x1b80, 0x1bbf,
- 0x1cc0, 0x1cc7,
-}; /* CR_Sundanese */
-
-/* 'Lepcha': Script */
-static const OnigCodePoint CR_Lepcha[] = {
- 3,
- 0x1c00, 0x1c37,
- 0x1c3b, 0x1c49,
- 0x1c4d, 0x1c4f,
-}; /* CR_Lepcha */
-
-/* 'Ol_Chiki': Script */
-static const OnigCodePoint CR_Ol_Chiki[] = {
- 1,
- 0x1c50, 0x1c7f,
-}; /* CR_Ol_Chiki */
-
-/* 'Vai': Script */
-static const OnigCodePoint CR_Vai[] = {
- 1,
- 0xa500, 0xa62b,
-}; /* CR_Vai */
-
-/* 'Saurashtra': Script */
-static const OnigCodePoint CR_Saurashtra[] = {
- 2,
- 0xa880, 0xa8c5,
- 0xa8ce, 0xa8d9,
-}; /* CR_Saurashtra */
-
-/* 'Kayah_Li': Script */
-static const OnigCodePoint CR_Kayah_Li[] = {
- 2,
- 0xa900, 0xa92d,
- 0xa92f, 0xa92f,
-}; /* CR_Kayah_Li */
-
-/* 'Rejang': Script */
-static const OnigCodePoint CR_Rejang[] = {
- 2,
- 0xa930, 0xa953,
- 0xa95f, 0xa95f,
-}; /* CR_Rejang */
-
-/* 'Lycian': Script */
-static const OnigCodePoint CR_Lycian[] = {
- 1,
- 0x10280, 0x1029c,
-}; /* CR_Lycian */
-
-/* 'Carian': Script */
-static const OnigCodePoint CR_Carian[] = {
- 1,
- 0x102a0, 0x102d0,
-}; /* CR_Carian */
-
-/* 'Lydian': Script */
-static const OnigCodePoint CR_Lydian[] = {
- 2,
- 0x10920, 0x10939,
- 0x1093f, 0x1093f,
-}; /* CR_Lydian */
-
-/* 'Cham': Script */
-static const OnigCodePoint CR_Cham[] = {
- 4,
- 0xaa00, 0xaa36,
- 0xaa40, 0xaa4d,
- 0xaa50, 0xaa59,
- 0xaa5c, 0xaa5f,
-}; /* CR_Cham */
-
-/* 'Tai_Tham': Script */
-static const OnigCodePoint CR_Tai_Tham[] = {
- 5,
- 0x1a20, 0x1a5e,
- 0x1a60, 0x1a7c,
- 0x1a7f, 0x1a89,
- 0x1a90, 0x1a99,
- 0x1aa0, 0x1aad,
-}; /* CR_Tai_Tham */
-
-/* 'Tai_Viet': Script */
-static const OnigCodePoint CR_Tai_Viet[] = {
- 2,
- 0xaa80, 0xaac2,
- 0xaadb, 0xaadf,
-}; /* CR_Tai_Viet */
-
-/* 'Avestan': Script */
-static const OnigCodePoint CR_Avestan[] = {
- 2,
- 0x10b00, 0x10b35,
- 0x10b39, 0x10b3f,
-}; /* CR_Avestan */
-
-/* 'Egyptian_Hieroglyphs': Script */
-static const OnigCodePoint CR_Egyptian_Hieroglyphs[] = {
- 1,
- 0x13000, 0x13455,
-}; /* CR_Egyptian_Hieroglyphs */
-
-/* 'Samaritan': Script */
-static const OnigCodePoint CR_Samaritan[] = {
- 2,
- 0x0800, 0x082d,
- 0x0830, 0x083e,
-}; /* CR_Samaritan */
-
-/* 'Lisu': Script */
-static const OnigCodePoint CR_Lisu[] = {
- 2,
- 0xa4d0, 0xa4ff,
- 0x11fb0, 0x11fb0,
-}; /* CR_Lisu */
-
-/* 'Bamum': Script */
-static const OnigCodePoint CR_Bamum[] = {
- 2,
- 0xa6a0, 0xa6f7,
- 0x16800, 0x16a38,
-}; /* CR_Bamum */
-
-/* 'Javanese': Script */
-static const OnigCodePoint CR_Javanese[] = {
- 3,
- 0xa980, 0xa9cd,
- 0xa9d0, 0xa9d9,
- 0xa9de, 0xa9df,
-}; /* CR_Javanese */
-
-/* 'Meetei_Mayek': Script */
-static const OnigCodePoint CR_Meetei_Mayek[] = {
- 3,
- 0xaae0, 0xaaf6,
- 0xabc0, 0xabed,
- 0xabf0, 0xabf9,
-}; /* CR_Meetei_Mayek */
-
-/* 'Imperial_Aramaic': Script */
-static const OnigCodePoint CR_Imperial_Aramaic[] = {
- 2,
- 0x10840, 0x10855,
- 0x10857, 0x1085f,
-}; /* CR_Imperial_Aramaic */
-
-/* 'Old_South_Arabian': Script */
-static const OnigCodePoint CR_Old_South_Arabian[] = {
- 1,
- 0x10a60, 0x10a7f,
-}; /* CR_Old_South_Arabian */
-
-/* 'Inscriptional_Parthian': Script */
-static const OnigCodePoint CR_Inscriptional_Parthian[] = {
- 2,
- 0x10b40, 0x10b55,
- 0x10b58, 0x10b5f,
-}; /* CR_Inscriptional_Parthian */
-
-/* 'Inscriptional_Pahlavi': Script */
-static const OnigCodePoint CR_Inscriptional_Pahlavi[] = {
- 2,
- 0x10b60, 0x10b72,
- 0x10b78, 0x10b7f,
-}; /* CR_Inscriptional_Pahlavi */
-
-/* 'Old_Turkic': Script */
-static const OnigCodePoint CR_Old_Turkic[] = {
- 1,
- 0x10c00, 0x10c48,
-}; /* CR_Old_Turkic */
-
-/* 'Kaithi': Script */
-static const OnigCodePoint CR_Kaithi[] = {
- 2,
- 0x11080, 0x110c2,
- 0x110cd, 0x110cd,
-}; /* CR_Kaithi */
-
-/* 'Batak': Script */
-static const OnigCodePoint CR_Batak[] = {
- 2,
- 0x1bc0, 0x1bf3,
- 0x1bfc, 0x1bff,
-}; /* CR_Batak */
-
-/* 'Brahmi': Script */
-static const OnigCodePoint CR_Brahmi[] = {
- 3,
- 0x11000, 0x1104d,
- 0x11052, 0x11075,
- 0x1107f, 0x1107f,
-}; /* CR_Brahmi */
-
-/* 'Mandaic': Script */
-static const OnigCodePoint CR_Mandaic[] = {
- 2,
- 0x0840, 0x085b,
- 0x085e, 0x085e,
-}; /* CR_Mandaic */
-
-/* 'Chakma': Script */
-static const OnigCodePoint CR_Chakma[] = {
- 2,
- 0x11100, 0x11134,
- 0x11136, 0x11147,
-}; /* CR_Chakma */
-
-/* 'Meroitic_Cursive': Script */
-static const OnigCodePoint CR_Meroitic_Cursive[] = {
- 3,
- 0x109a0, 0x109b7,
- 0x109bc, 0x109cf,
- 0x109d2, 0x109ff,
-}; /* CR_Meroitic_Cursive */
-
-/* 'Meroitic_Hieroglyphs': Script */
-static const OnigCodePoint CR_Meroitic_Hieroglyphs[] = {
- 1,
- 0x10980, 0x1099f,
-}; /* CR_Meroitic_Hieroglyphs */
-
-/* 'Miao': Script */
-static const OnigCodePoint CR_Miao[] = {
- 3,
- 0x16f00, 0x16f4a,
- 0x16f4f, 0x16f87,
- 0x16f8f, 0x16f9f,
-}; /* CR_Miao */
-
-/* 'Sharada': Script */
-static const OnigCodePoint CR_Sharada[] = {
- 1,
- 0x11180, 0x111df,
-}; /* CR_Sharada */
-
-/* 'Sora_Sompeng': Script */
-static const OnigCodePoint CR_Sora_Sompeng[] = {
- 2,
- 0x110d0, 0x110e8,
- 0x110f0, 0x110f9,
-}; /* CR_Sora_Sompeng */
-
-/* 'Takri': Script */
-static const OnigCodePoint CR_Takri[] = {
- 2,
- 0x11680, 0x116b9,
- 0x116c0, 0x116c9,
-}; /* CR_Takri */
-
-/* 'Caucasian_Albanian': Script */
-static const OnigCodePoint CR_Caucasian_Albanian[] = {
- 2,
- 0x10530, 0x10563,
- 0x1056f, 0x1056f,
-}; /* CR_Caucasian_Albanian */
-
-/* 'Bassa_Vah': Script */
-static const OnigCodePoint CR_Bassa_Vah[] = {
- 2,
- 0x16ad0, 0x16aed,
- 0x16af0, 0x16af5,
-}; /* CR_Bassa_Vah */
-
-/* 'Duployan': Script */
-static const OnigCodePoint CR_Duployan[] = {
- 5,
- 0x1bc00, 0x1bc6a,
- 0x1bc70, 0x1bc7c,
- 0x1bc80, 0x1bc88,
- 0x1bc90, 0x1bc99,
- 0x1bc9c, 0x1bc9f,
-}; /* CR_Duployan */
-
-/* 'Elbasan': Script */
-static const OnigCodePoint CR_Elbasan[] = {
- 1,
- 0x10500, 0x10527,
-}; /* CR_Elbasan */
-
-/* 'Grantha': Script */
-static const OnigCodePoint CR_Grantha[] = {
- 15,
- 0x11300, 0x11303,
- 0x11305, 0x1130c,
- 0x1130f, 0x11310,
- 0x11313, 0x11328,
- 0x1132a, 0x11330,
- 0x11332, 0x11333,
- 0x11335, 0x11339,
- 0x1133c, 0x11344,
- 0x11347, 0x11348,
- 0x1134b, 0x1134d,
- 0x11350, 0x11350,
- 0x11357, 0x11357,
- 0x1135d, 0x11363,
- 0x11366, 0x1136c,
- 0x11370, 0x11374,
-}; /* CR_Grantha */
-
-/* 'Pahawh_Hmong': Script */
-static const OnigCodePoint CR_Pahawh_Hmong[] = {
- 5,
- 0x16b00, 0x16b45,
- 0x16b50, 0x16b59,
- 0x16b5b, 0x16b61,
- 0x16b63, 0x16b77,
- 0x16b7d, 0x16b8f,
-}; /* CR_Pahawh_Hmong */
-
-/* 'Khojki': Script */
-static const OnigCodePoint CR_Khojki[] = {
- 2,
- 0x11200, 0x11211,
- 0x11213, 0x11241,
-}; /* CR_Khojki */
-
-/* 'Linear_A': Script */
-static const OnigCodePoint CR_Linear_A[] = {
- 3,
- 0x10600, 0x10736,
- 0x10740, 0x10755,
- 0x10760, 0x10767,
-}; /* CR_Linear_A */
-
-/* 'Mahajani': Script */
-static const OnigCodePoint CR_Mahajani[] = {
- 1,
- 0x11150, 0x11176,
-}; /* CR_Mahajani */
-
-/* 'Manichaean': Script */
-static const OnigCodePoint CR_Manichaean[] = {
- 2,
- 0x10ac0, 0x10ae6,
- 0x10aeb, 0x10af6,
-}; /* CR_Manichaean */
-
-/* 'Mende_Kikakui': Script */
-static const OnigCodePoint CR_Mende_Kikakui[] = {
- 2,
- 0x1e800, 0x1e8c4,
- 0x1e8c7, 0x1e8d6,
-}; /* CR_Mende_Kikakui */
-
-/* 'Modi': Script */
-static const OnigCodePoint CR_Modi[] = {
- 2,
- 0x11600, 0x11644,
- 0x11650, 0x11659,
-}; /* CR_Modi */
-
-/* 'Mro': Script */
-static const OnigCodePoint CR_Mro[] = {
- 3,
- 0x16a40, 0x16a5e,
- 0x16a60, 0x16a69,
- 0x16a6e, 0x16a6f,
-}; /* CR_Mro */
-
-/* 'Old_North_Arabian': Script */
-static const OnigCodePoint CR_Old_North_Arabian[] = {
- 1,
- 0x10a80, 0x10a9f,
-}; /* CR_Old_North_Arabian */
-
-/* 'Nabataean': Script */
-static const OnigCodePoint CR_Nabataean[] = {
- 2,
- 0x10880, 0x1089e,
- 0x108a7, 0x108af,
-}; /* CR_Nabataean */
-
-/* 'Palmyrene': Script */
-static const OnigCodePoint CR_Palmyrene[] = {
- 1,
- 0x10860, 0x1087f,
-}; /* CR_Palmyrene */
-
-/* 'Pau_Cin_Hau': Script */
-static const OnigCodePoint CR_Pau_Cin_Hau[] = {
- 1,
- 0x11ac0, 0x11af8,
-}; /* CR_Pau_Cin_Hau */
-
-/* 'Old_Permic': Script */
-static const OnigCodePoint CR_Old_Permic[] = {
- 1,
- 0x10350, 0x1037a,
-}; /* CR_Old_Permic */
-
-/* 'Psalter_Pahlavi': Script */
-static const OnigCodePoint CR_Psalter_Pahlavi[] = {
- 3,
- 0x10b80, 0x10b91,
- 0x10b99, 0x10b9c,
- 0x10ba9, 0x10baf,
-}; /* CR_Psalter_Pahlavi */
-
-/* 'Siddham': Script */
-static const OnigCodePoint CR_Siddham[] = {
- 2,
- 0x11580, 0x115b5,
- 0x115b8, 0x115dd,
-}; /* CR_Siddham */
-
-/* 'Khudawadi': Script */
-static const OnigCodePoint CR_Khudawadi[] = {
- 2,
- 0x112b0, 0x112ea,
- 0x112f0, 0x112f9,
-}; /* CR_Khudawadi */
-
-/* 'Tirhuta': Script */
-static const OnigCodePoint CR_Tirhuta[] = {
- 2,
- 0x11480, 0x114c7,
- 0x114d0, 0x114d9,
-}; /* CR_Tirhuta */
-
-/* 'Warang_Citi': Script */
-static const OnigCodePoint CR_Warang_Citi[] = {
- 2,
- 0x118a0, 0x118f2,
- 0x118ff, 0x118ff,
-}; /* CR_Warang_Citi */
-
-/* 'Ahom': Script */
-static const OnigCodePoint CR_Ahom[] = {
- 3,
- 0x11700, 0x1171a,
- 0x1171d, 0x1172b,
- 0x11730, 0x11746,
-}; /* CR_Ahom */
-
-/* 'Anatolian_Hieroglyphs': Script */
-static const OnigCodePoint CR_Anatolian_Hieroglyphs[] = {
- 1,
- 0x14400, 0x14646,
-}; /* CR_Anatolian_Hieroglyphs */
-
-/* 'Hatran': Script */
-static const OnigCodePoint CR_Hatran[] = {
- 3,
- 0x108e0, 0x108f2,
- 0x108f4, 0x108f5,
- 0x108fb, 0x108ff,
-}; /* CR_Hatran */
-
-/* 'Multani': Script */
-static const OnigCodePoint CR_Multani[] = {
- 5,
- 0x11280, 0x11286,
- 0x11288, 0x11288,
- 0x1128a, 0x1128d,
- 0x1128f, 0x1129d,
- 0x1129f, 0x112a9,
-}; /* CR_Multani */
-
-/* 'Old_Hungarian': Script */
-static const OnigCodePoint CR_Old_Hungarian[] = {
- 3,
- 0x10c80, 0x10cb2,
- 0x10cc0, 0x10cf2,
- 0x10cfa, 0x10cff,
-}; /* CR_Old_Hungarian */
-
-/* 'SignWriting': Script */
-static const OnigCodePoint CR_SignWriting[] = {
- 3,
- 0x1d800, 0x1da8b,
- 0x1da9b, 0x1da9f,
- 0x1daa1, 0x1daaf,
-}; /* CR_SignWriting */
-
-/* 'Adlam': Script */
-static const OnigCodePoint CR_Adlam[] = {
- 3,
- 0x1e900, 0x1e94b,
- 0x1e950, 0x1e959,
- 0x1e95e, 0x1e95f,
-}; /* CR_Adlam */
-
-/* 'Bhaiksuki': Script */
-static const OnigCodePoint CR_Bhaiksuki[] = {
- 4,
- 0x11c00, 0x11c08,
- 0x11c0a, 0x11c36,
- 0x11c38, 0x11c45,
- 0x11c50, 0x11c6c,
-}; /* CR_Bhaiksuki */
-
-/* 'Marchen': Script */
-static const OnigCodePoint CR_Marchen[] = {
- 3,
- 0x11c70, 0x11c8f,
- 0x11c92, 0x11ca7,
- 0x11ca9, 0x11cb6,
-}; /* CR_Marchen */
-
-/* 'Newa': Script */
-static const OnigCodePoint CR_Newa[] = {
- 2,
- 0x11400, 0x1145b,
- 0x1145d, 0x11461,
-}; /* CR_Newa */
-
-/* 'Osage': Script */
-static const OnigCodePoint CR_Osage[] = {
- 2,
- 0x104b0, 0x104d3,
- 0x104d8, 0x104fb,
-}; /* CR_Osage */
-
-/* 'Tangut': Script */
-static const OnigCodePoint CR_Tangut[] = {
- 4,
- 0x16fe0, 0x16fe0,
- 0x17000, 0x187f7,
- 0x18800, 0x18aff,
- 0x18d00, 0x18d08,
-}; /* CR_Tangut */
-
-/* 'Masaram_Gondi': Script */
-static const OnigCodePoint CR_Masaram_Gondi[] = {
- 7,
- 0x11d00, 0x11d06,
- 0x11d08, 0x11d09,
- 0x11d0b, 0x11d36,
- 0x11d3a, 0x11d3a,
- 0x11d3c, 0x11d3d,
- 0x11d3f, 0x11d47,
- 0x11d50, 0x11d59,
-}; /* CR_Masaram_Gondi */
-
-/* 'Nushu': Script */
-static const OnigCodePoint CR_Nushu[] = {
- 2,
- 0x16fe1, 0x16fe1,
- 0x1b170, 0x1b2fb,
-}; /* CR_Nushu */
-
-/* 'Soyombo': Script */
-static const OnigCodePoint CR_Soyombo[] = {
- 1,
- 0x11a50, 0x11aa2,
-}; /* CR_Soyombo */
-
-/* 'Zanabazar_Square': Script */
-static const OnigCodePoint CR_Zanabazar_Square[] = {
- 1,
- 0x11a00, 0x11a47,
-}; /* CR_Zanabazar_Square */
-
-/* 'Dogra': Script */
-static const OnigCodePoint CR_Dogra[] = {
- 1,
- 0x11800, 0x1183b,
-}; /* CR_Dogra */
-
-/* 'Gunjala_Gondi': Script */
-static const OnigCodePoint CR_Gunjala_Gondi[] = {
- 6,
- 0x11d60, 0x11d65,
- 0x11d67, 0x11d68,
- 0x11d6a, 0x11d8e,
- 0x11d90, 0x11d91,
- 0x11d93, 0x11d98,
- 0x11da0, 0x11da9,
-}; /* CR_Gunjala_Gondi */
-
-/* 'Makasar': Script */
-static const OnigCodePoint CR_Makasar[] = {
- 1,
- 0x11ee0, 0x11ef8,
-}; /* CR_Makasar */
-
-/* 'Medefaidrin': Script */
-static const OnigCodePoint CR_Medefaidrin[] = {
- 1,
- 0x16e40, 0x16e9a,
-}; /* CR_Medefaidrin */
-
-/* 'Hanifi_Rohingya': Script */
-static const OnigCodePoint CR_Hanifi_Rohingya[] = {
- 2,
- 0x10d00, 0x10d27,
- 0x10d30, 0x10d39,
-}; /* CR_Hanifi_Rohingya */
-
-/* 'Sogdian': Script */
-static const OnigCodePoint CR_Sogdian[] = {
- 1,
- 0x10f30, 0x10f59,
-}; /* CR_Sogdian */
-
-/* 'Old_Sogdian': Script */
-static const OnigCodePoint CR_Old_Sogdian[] = {
- 1,
- 0x10f00, 0x10f27,
-}; /* CR_Old_Sogdian */
-
-/* 'Elymaic': Script */
-static const OnigCodePoint CR_Elymaic[] = {
- 1,
- 0x10fe0, 0x10ff6,
-}; /* CR_Elymaic */
-
-/* 'Nandinagari': Script */
-static const OnigCodePoint CR_Nandinagari[] = {
- 3,
- 0x119a0, 0x119a7,
- 0x119aa, 0x119d7,
- 0x119da, 0x119e4,
-}; /* CR_Nandinagari */
-
-/* 'Nyiakeng_Puachue_Hmong': Script */
-static const OnigCodePoint CR_Nyiakeng_Puachue_Hmong[] = {
- 4,
- 0x1e100, 0x1e12c,
- 0x1e130, 0x1e13d,
- 0x1e140, 0x1e149,
- 0x1e14e, 0x1e14f,
-}; /* CR_Nyiakeng_Puachue_Hmong */
-
-/* 'Wancho': Script */
-static const OnigCodePoint CR_Wancho[] = {
- 2,
- 0x1e2c0, 0x1e2f9,
- 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 */
-
-/* 'Cypro_Minoan': Script */
-static const OnigCodePoint CR_Cypro_Minoan[] = {
- 1,
- 0x12f90, 0x12ff2,
-}; /* CR_Cypro_Minoan */
-
-/* 'Old_Uyghur': Script */
-static const OnigCodePoint CR_Old_Uyghur[] = {
- 1,
- 0x10f70, 0x10f89,
-}; /* CR_Old_Uyghur */
-
-/* 'Tangsa': Script */
-static const OnigCodePoint CR_Tangsa[] = {
- 2,
- 0x16a70, 0x16abe,
- 0x16ac0, 0x16ac9,
-}; /* CR_Tangsa */
-
-/* 'Toto': Script */
-static const OnigCodePoint CR_Toto[] = {
- 1,
- 0x1e290, 0x1e2ae,
-}; /* CR_Toto */
-
-/* 'Vithkuqi': Script */
-static const OnigCodePoint CR_Vithkuqi[] = {
- 8,
- 0x10570, 0x1057a,
- 0x1057c, 0x1058a,
- 0x1058c, 0x10592,
- 0x10594, 0x10595,
- 0x10597, 0x105a1,
- 0x105a3, 0x105b1,
- 0x105b3, 0x105b9,
- 0x105bb, 0x105bc,
-}; /* CR_Vithkuqi */
-
-/* 'Kawi': Script */
-static const OnigCodePoint CR_Kawi[] = {
- 3,
- 0x11f00, 0x11f10,
- 0x11f12, 0x11f3a,
- 0x11f3e, 0x11f59,
-}; /* CR_Kawi */
-
-/* 'Nag_Mundari': Script */
-static const OnigCodePoint CR_Nag_Mundari[] = {
- 1,
- 0x1e4d0, 0x1e4f9,
-}; /* CR_Nag_Mundari */
-
-/* 'White_Space': Binary Property */
-#define CR_White_Space CR_Space
-
-/* 'Bidi_Control': Binary Property */
-static const OnigCodePoint CR_Bidi_Control[] = {
- 4,
- 0x061c, 0x061c,
- 0x200e, 0x200f,
- 0x202a, 0x202e,
- 0x2066, 0x2069,
-}; /* CR_Bidi_Control */
-
-/* 'Join_Control': Binary Property */
-static const OnigCodePoint CR_Join_Control[] = {
- 1,
- 0x200c, 0x200d,
-}; /* CR_Join_Control */
-
-/* 'Dash': Binary Property */
-static const OnigCodePoint CR_Dash[] = {
- 23,
- 0x002d, 0x002d,
- 0x058a, 0x058a,
- 0x05be, 0x05be,
- 0x1400, 0x1400,
- 0x1806, 0x1806,
- 0x2010, 0x2015,
- 0x2053, 0x2053,
- 0x207b, 0x207b,
- 0x208b, 0x208b,
- 0x2212, 0x2212,
- 0x2e17, 0x2e17,
- 0x2e1a, 0x2e1a,
- 0x2e3a, 0x2e3b,
- 0x2e40, 0x2e40,
- 0x2e5d, 0x2e5d,
- 0x301c, 0x301c,
- 0x3030, 0x3030,
- 0x30a0, 0x30a0,
- 0xfe31, 0xfe32,
- 0xfe58, 0xfe58,
- 0xfe63, 0xfe63,
- 0xff0d, 0xff0d,
- 0x10ead, 0x10ead,
-}; /* CR_Dash */
-
-/* 'Hyphen': Binary Property */
-static const OnigCodePoint CR_Hyphen[] = {
- 10,
- 0x002d, 0x002d,
- 0x00ad, 0x00ad,
- 0x058a, 0x058a,
- 0x1806, 0x1806,
- 0x2010, 0x2011,
- 0x2e17, 0x2e17,
- 0x30fb, 0x30fb,
- 0xfe63, 0xfe63,
- 0xff0d, 0xff0d,
- 0xff65, 0xff65,
-}; /* CR_Hyphen */
-
-/* 'Quotation_Mark': Binary Property */
-static const OnigCodePoint CR_Quotation_Mark[] = {
- 13,
- 0x0022, 0x0022,
- 0x0027, 0x0027,
- 0x00ab, 0x00ab,
- 0x00bb, 0x00bb,
- 0x2018, 0x201f,
- 0x2039, 0x203a,
- 0x2e42, 0x2e42,
- 0x300c, 0x300f,
- 0x301d, 0x301f,
- 0xfe41, 0xfe44,
- 0xff02, 0xff02,
- 0xff07, 0xff07,
- 0xff62, 0xff63,
-}; /* CR_Quotation_Mark */
-
-/* 'Terminal_Punctuation': Binary Property */
-static const OnigCodePoint CR_Terminal_Punctuation[] = {
- 108,
- 0x0021, 0x0021,
- 0x002c, 0x002c,
- 0x002e, 0x002e,
- 0x003a, 0x003b,
- 0x003f, 0x003f,
- 0x037e, 0x037e,
- 0x0387, 0x0387,
- 0x0589, 0x0589,
- 0x05c3, 0x05c3,
- 0x060c, 0x060c,
- 0x061b, 0x061b,
- 0x061d, 0x061f,
- 0x06d4, 0x06d4,
- 0x0700, 0x070a,
- 0x070c, 0x070c,
- 0x07f8, 0x07f9,
- 0x0830, 0x083e,
- 0x085e, 0x085e,
- 0x0964, 0x0965,
- 0x0e5a, 0x0e5b,
- 0x0f08, 0x0f08,
- 0x0f0d, 0x0f12,
- 0x104a, 0x104b,
- 0x1361, 0x1368,
- 0x166e, 0x166e,
- 0x16eb, 0x16ed,
- 0x1735, 0x1736,
- 0x17d4, 0x17d6,
- 0x17da, 0x17da,
- 0x1802, 0x1805,
- 0x1808, 0x1809,
- 0x1944, 0x1945,
- 0x1aa8, 0x1aab,
- 0x1b5a, 0x1b5b,
- 0x1b5d, 0x1b5f,
- 0x1b7d, 0x1b7e,
- 0x1c3b, 0x1c3f,
- 0x1c7e, 0x1c7f,
- 0x203c, 0x203d,
- 0x2047, 0x2049,
- 0x2e2e, 0x2e2e,
- 0x2e3c, 0x2e3c,
- 0x2e41, 0x2e41,
- 0x2e4c, 0x2e4c,
- 0x2e4e, 0x2e4f,
- 0x2e53, 0x2e54,
- 0x3001, 0x3002,
- 0xa4fe, 0xa4ff,
- 0xa60d, 0xa60f,
- 0xa6f3, 0xa6f7,
- 0xa876, 0xa877,
- 0xa8ce, 0xa8cf,
- 0xa92f, 0xa92f,
- 0xa9c7, 0xa9c9,
- 0xaa5d, 0xaa5f,
- 0xaadf, 0xaadf,
- 0xaaf0, 0xaaf1,
- 0xabeb, 0xabeb,
- 0xfe50, 0xfe52,
- 0xfe54, 0xfe57,
- 0xff01, 0xff01,
- 0xff0c, 0xff0c,
- 0xff0e, 0xff0e,
- 0xff1a, 0xff1b,
- 0xff1f, 0xff1f,
- 0xff61, 0xff61,
- 0xff64, 0xff64,
- 0x1039f, 0x1039f,
- 0x103d0, 0x103d0,
- 0x10857, 0x10857,
- 0x1091f, 0x1091f,
- 0x10a56, 0x10a57,
- 0x10af0, 0x10af5,
- 0x10b3a, 0x10b3f,
- 0x10b99, 0x10b9c,
- 0x10f55, 0x10f59,
- 0x10f86, 0x10f89,
- 0x11047, 0x1104d,
- 0x110be, 0x110c1,
- 0x11141, 0x11143,
- 0x111c5, 0x111c6,
- 0x111cd, 0x111cd,
- 0x111de, 0x111df,
- 0x11238, 0x1123c,
- 0x112a9, 0x112a9,
- 0x1144b, 0x1144d,
- 0x1145a, 0x1145b,
- 0x115c2, 0x115c5,
- 0x115c9, 0x115d7,
- 0x11641, 0x11642,
- 0x1173c, 0x1173e,
- 0x11944, 0x11944,
- 0x11946, 0x11946,
- 0x11a42, 0x11a43,
- 0x11a9b, 0x11a9c,
- 0x11aa1, 0x11aa2,
- 0x11c41, 0x11c43,
- 0x11c71, 0x11c71,
- 0x11ef7, 0x11ef8,
- 0x11f43, 0x11f44,
- 0x12470, 0x12474,
- 0x16a6e, 0x16a6f,
- 0x16af5, 0x16af5,
- 0x16b37, 0x16b39,
- 0x16b44, 0x16b44,
- 0x16e97, 0x16e98,
- 0x1bc9f, 0x1bc9f,
- 0x1da87, 0x1da8a,
-}; /* CR_Terminal_Punctuation */
-
-/* 'Other_Math': Binary Property */
-static const OnigCodePoint CR_Other_Math[] = {
- 134,
- 0x005e, 0x005e,
- 0x03d0, 0x03d2,
- 0x03d5, 0x03d5,
- 0x03f0, 0x03f1,
- 0x03f4, 0x03f5,
- 0x2016, 0x2016,
- 0x2032, 0x2034,
- 0x2040, 0x2040,
- 0x2061, 0x2064,
- 0x207d, 0x207e,
- 0x208d, 0x208e,
- 0x20d0, 0x20dc,
- 0x20e1, 0x20e1,
- 0x20e5, 0x20e6,
- 0x20eb, 0x20ef,
- 0x2102, 0x2102,
- 0x2107, 0x2107,
- 0x210a, 0x2113,
- 0x2115, 0x2115,
- 0x2119, 0x211d,
- 0x2124, 0x2124,
- 0x2128, 0x2129,
- 0x212c, 0x212d,
- 0x212f, 0x2131,
- 0x2133, 0x2138,
- 0x213c, 0x213f,
- 0x2145, 0x2149,
- 0x2195, 0x2199,
- 0x219c, 0x219f,
- 0x21a1, 0x21a2,
- 0x21a4, 0x21a5,
- 0x21a7, 0x21a7,
- 0x21a9, 0x21ad,
- 0x21b0, 0x21b1,
- 0x21b6, 0x21b7,
- 0x21bc, 0x21cd,
- 0x21d0, 0x21d1,
- 0x21d3, 0x21d3,
- 0x21d5, 0x21db,
- 0x21dd, 0x21dd,
- 0x21e4, 0x21e5,
- 0x2308, 0x230b,
- 0x23b4, 0x23b5,
- 0x23b7, 0x23b7,
- 0x23d0, 0x23d0,
- 0x23e2, 0x23e2,
- 0x25a0, 0x25a1,
- 0x25ae, 0x25b6,
- 0x25bc, 0x25c0,
- 0x25c6, 0x25c7,
- 0x25ca, 0x25cb,
- 0x25cf, 0x25d3,
- 0x25e2, 0x25e2,
- 0x25e4, 0x25e4,
- 0x25e7, 0x25ec,
- 0x2605, 0x2606,
- 0x2640, 0x2640,
- 0x2642, 0x2642,
- 0x2660, 0x2663,
- 0x266d, 0x266e,
- 0x27c5, 0x27c6,
- 0x27e6, 0x27ef,
- 0x2983, 0x2998,
- 0x29d8, 0x29db,
- 0x29fc, 0x29fd,
- 0xfe61, 0xfe61,
- 0xfe63, 0xfe63,
- 0xfe68, 0xfe68,
- 0xff3c, 0xff3c,
- 0xff3e, 0xff3e,
- 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, 0x1d6c0,
- 0x1d6c2, 0x1d6da,
- 0x1d6dc, 0x1d6fa,
- 0x1d6fc, 0x1d714,
- 0x1d716, 0x1d734,
- 0x1d736, 0x1d74e,
- 0x1d750, 0x1d76e,
- 0x1d770, 0x1d788,
- 0x1d78a, 0x1d7a8,
- 0x1d7aa, 0x1d7c2,
- 0x1d7c4, 0x1d7cb,
- 0x1d7ce, 0x1d7ff,
- 0x1ee00, 0x1ee03,
- 0x1ee05, 0x1ee1f,
- 0x1ee21, 0x1ee22,
- 0x1ee24, 0x1ee24,
- 0x1ee27, 0x1ee27,
- 0x1ee29, 0x1ee32,
- 0x1ee34, 0x1ee37,
- 0x1ee39, 0x1ee39,
- 0x1ee3b, 0x1ee3b,
- 0x1ee42, 0x1ee42,
- 0x1ee47, 0x1ee47,
- 0x1ee49, 0x1ee49,
- 0x1ee4b, 0x1ee4b,
- 0x1ee4d, 0x1ee4f,
- 0x1ee51, 0x1ee52,
- 0x1ee54, 0x1ee54,
- 0x1ee57, 0x1ee57,
- 0x1ee59, 0x1ee59,
- 0x1ee5b, 0x1ee5b,
- 0x1ee5d, 0x1ee5d,
- 0x1ee5f, 0x1ee5f,
- 0x1ee61, 0x1ee62,
- 0x1ee64, 0x1ee64,
- 0x1ee67, 0x1ee6a,
- 0x1ee6c, 0x1ee72,
- 0x1ee74, 0x1ee77,
- 0x1ee79, 0x1ee7c,
- 0x1ee7e, 0x1ee7e,
- 0x1ee80, 0x1ee89,
- 0x1ee8b, 0x1ee9b,
- 0x1eea1, 0x1eea3,
- 0x1eea5, 0x1eea9,
- 0x1eeab, 0x1eebb,
-}; /* CR_Other_Math */
-
-/* 'Hex_Digit': Binary Property */
-static const OnigCodePoint CR_Hex_Digit[] = {
- 6,
- 0x0030, 0x0039,
- 0x0041, 0x0046,
- 0x0061, 0x0066,
- 0xff10, 0xff19,
- 0xff21, 0xff26,
- 0xff41, 0xff46,
-}; /* CR_Hex_Digit */
-
-/* 'ASCII_Hex_Digit': Binary Property */
-#define CR_ASCII_Hex_Digit CR_XDigit
-
-/* 'Other_Alphabetic': Binary Property */
-static const OnigCodePoint CR_Other_Alphabetic[] = {
- 240,
- 0x0345, 0x0345,
- 0x05b0, 0x05bd,
- 0x05bf, 0x05bf,
- 0x05c1, 0x05c2,
- 0x05c4, 0x05c5,
- 0x05c7, 0x05c7,
- 0x0610, 0x061a,
- 0x064b, 0x0657,
- 0x0659, 0x065f,
- 0x0670, 0x0670,
- 0x06d6, 0x06dc,
- 0x06e1, 0x06e4,
- 0x06e7, 0x06e8,
- 0x06ed, 0x06ed,
- 0x0711, 0x0711,
- 0x0730, 0x073f,
- 0x07a6, 0x07b0,
- 0x0816, 0x0817,
- 0x081b, 0x0823,
- 0x0825, 0x0827,
- 0x0829, 0x082c,
- 0x08d4, 0x08df,
- 0x08e3, 0x08e9,
- 0x08f0, 0x0903,
- 0x093a, 0x093b,
- 0x093e, 0x094c,
- 0x094e, 0x094f,
- 0x0955, 0x0957,
- 0x0962, 0x0963,
- 0x0981, 0x0983,
- 0x09be, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09cc,
- 0x09d7, 0x09d7,
- 0x09e2, 0x09e3,
- 0x0a01, 0x0a03,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4c,
- 0x0a51, 0x0a51,
- 0x0a70, 0x0a71,
- 0x0a75, 0x0a75,
- 0x0a81, 0x0a83,
- 0x0abe, 0x0ac5,
- 0x0ac7, 0x0ac9,
- 0x0acb, 0x0acc,
- 0x0ae2, 0x0ae3,
- 0x0afa, 0x0afc,
- 0x0b01, 0x0b03,
- 0x0b3e, 0x0b44,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4c,
- 0x0b56, 0x0b57,
- 0x0b62, 0x0b63,
- 0x0b82, 0x0b82,
- 0x0bbe, 0x0bc2,
- 0x0bc6, 0x0bc8,
- 0x0bca, 0x0bcc,
- 0x0bd7, 0x0bd7,
- 0x0c00, 0x0c04,
- 0x0c3e, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4c,
- 0x0c55, 0x0c56,
- 0x0c62, 0x0c63,
- 0x0c81, 0x0c83,
- 0x0cbe, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccc,
- 0x0cd5, 0x0cd6,
- 0x0ce2, 0x0ce3,
- 0x0cf3, 0x0cf3,
- 0x0d00, 0x0d03,
- 0x0d3e, 0x0d44,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4c,
- 0x0d57, 0x0d57,
- 0x0d62, 0x0d63,
- 0x0d81, 0x0d83,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0df2, 0x0df3,
- 0x0e31, 0x0e31,
- 0x0e34, 0x0e3a,
- 0x0e4d, 0x0e4d,
- 0x0eb1, 0x0eb1,
- 0x0eb4, 0x0eb9,
- 0x0ebb, 0x0ebc,
- 0x0ecd, 0x0ecd,
- 0x0f71, 0x0f83,
- 0x0f8d, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x102b, 0x1036,
- 0x1038, 0x1038,
- 0x103b, 0x103e,
- 0x1056, 0x1059,
- 0x105e, 0x1060,
- 0x1062, 0x1064,
- 0x1067, 0x106d,
- 0x1071, 0x1074,
- 0x1082, 0x108d,
- 0x108f, 0x108f,
- 0x109a, 0x109d,
- 0x1712, 0x1713,
- 0x1732, 0x1733,
- 0x1752, 0x1753,
- 0x1772, 0x1773,
- 0x17b6, 0x17c8,
- 0x1885, 0x1886,
- 0x18a9, 0x18a9,
- 0x1920, 0x192b,
- 0x1930, 0x1938,
- 0x1a17, 0x1a1b,
- 0x1a55, 0x1a5e,
- 0x1a61, 0x1a74,
- 0x1abf, 0x1ac0,
- 0x1acc, 0x1ace,
- 0x1b00, 0x1b04,
- 0x1b35, 0x1b43,
- 0x1b80, 0x1b82,
- 0x1ba1, 0x1ba9,
- 0x1bac, 0x1bad,
- 0x1be7, 0x1bf1,
- 0x1c24, 0x1c36,
- 0x1de7, 0x1df4,
- 0x24b6, 0x24e9,
- 0x2de0, 0x2dff,
- 0xa674, 0xa67b,
- 0xa69e, 0xa69f,
- 0xa802, 0xa802,
- 0xa80b, 0xa80b,
- 0xa823, 0xa827,
- 0xa880, 0xa881,
- 0xa8b4, 0xa8c3,
- 0xa8c5, 0xa8c5,
- 0xa8ff, 0xa8ff,
- 0xa926, 0xa92a,
- 0xa947, 0xa952,
- 0xa980, 0xa983,
- 0xa9b4, 0xa9bf,
- 0xa9e5, 0xa9e5,
- 0xaa29, 0xaa36,
- 0xaa43, 0xaa43,
- 0xaa4c, 0xaa4d,
- 0xaa7b, 0xaa7d,
- 0xaab0, 0xaab0,
- 0xaab2, 0xaab4,
- 0xaab7, 0xaab8,
- 0xaabe, 0xaabe,
- 0xaaeb, 0xaaef,
- 0xaaf5, 0xaaf5,
- 0xabe3, 0xabea,
- 0xfb1e, 0xfb1e,
- 0x10376, 0x1037a,
- 0x10a01, 0x10a03,
- 0x10a05, 0x10a06,
- 0x10a0c, 0x10a0f,
- 0x10d24, 0x10d27,
- 0x10eab, 0x10eac,
- 0x11000, 0x11002,
- 0x11038, 0x11045,
- 0x11073, 0x11074,
- 0x11080, 0x11082,
- 0x110b0, 0x110b8,
- 0x110c2, 0x110c2,
- 0x11100, 0x11102,
- 0x11127, 0x11132,
- 0x11145, 0x11146,
- 0x11180, 0x11182,
- 0x111b3, 0x111bf,
- 0x111ce, 0x111cf,
- 0x1122c, 0x11234,
- 0x11237, 0x11237,
- 0x1123e, 0x1123e,
- 0x11241, 0x11241,
- 0x112df, 0x112e8,
- 0x11300, 0x11303,
- 0x1133e, 0x11344,
- 0x11347, 0x11348,
- 0x1134b, 0x1134c,
- 0x11357, 0x11357,
- 0x11362, 0x11363,
- 0x11435, 0x11441,
- 0x11443, 0x11445,
- 0x114b0, 0x114c1,
- 0x115af, 0x115b5,
- 0x115b8, 0x115be,
- 0x115dc, 0x115dd,
- 0x11630, 0x1163e,
- 0x11640, 0x11640,
- 0x116ab, 0x116b5,
- 0x1171d, 0x1172a,
- 0x1182c, 0x11838,
- 0x11930, 0x11935,
- 0x11937, 0x11938,
- 0x1193b, 0x1193c,
- 0x11940, 0x11940,
- 0x11942, 0x11942,
- 0x119d1, 0x119d7,
- 0x119da, 0x119df,
- 0x119e4, 0x119e4,
- 0x11a01, 0x11a0a,
- 0x11a35, 0x11a39,
- 0x11a3b, 0x11a3e,
- 0x11a51, 0x11a5b,
- 0x11a8a, 0x11a97,
- 0x11c2f, 0x11c36,
- 0x11c38, 0x11c3e,
- 0x11c92, 0x11ca7,
- 0x11ca9, 0x11cb6,
- 0x11d31, 0x11d36,
- 0x11d3a, 0x11d3a,
- 0x11d3c, 0x11d3d,
- 0x11d3f, 0x11d41,
- 0x11d43, 0x11d43,
- 0x11d47, 0x11d47,
- 0x11d8a, 0x11d8e,
- 0x11d90, 0x11d91,
- 0x11d93, 0x11d96,
- 0x11ef3, 0x11ef6,
- 0x11f00, 0x11f01,
- 0x11f03, 0x11f03,
- 0x11f34, 0x11f3a,
- 0x11f3e, 0x11f40,
- 0x16f4f, 0x16f4f,
- 0x16f51, 0x16f87,
- 0x16f8f, 0x16f92,
- 0x16ff0, 0x16ff1,
- 0x1bc9e, 0x1bc9e,
- 0x1e000, 0x1e006,
- 0x1e008, 0x1e018,
- 0x1e01b, 0x1e021,
- 0x1e023, 0x1e024,
- 0x1e026, 0x1e02a,
- 0x1e08f, 0x1e08f,
- 0x1e947, 0x1e947,
- 0x1f130, 0x1f149,
- 0x1f150, 0x1f169,
- 0x1f170, 0x1f189,
-}; /* CR_Other_Alphabetic */
-
-/* 'Ideographic': Binary Property */
-static const OnigCodePoint CR_Ideographic[] = {
- 20,
- 0x3006, 0x3007,
- 0x3021, 0x3029,
- 0x3038, 0x303a,
- 0x3400, 0x4dbf,
- 0x4e00, 0x9fff,
- 0xf900, 0xfa6d,
- 0xfa70, 0xfad9,
- 0x16fe4, 0x16fe4,
- 0x17000, 0x187f7,
- 0x18800, 0x18cd5,
- 0x18d00, 0x18d08,
- 0x1b170, 0x1b2fb,
- 0x20000, 0x2a6df,
- 0x2a700, 0x2b739,
- 0x2b740, 0x2b81d,
- 0x2b820, 0x2cea1,
- 0x2ceb0, 0x2ebe0,
- 0x2f800, 0x2fa1d,
- 0x30000, 0x3134a,
- 0x31350, 0x323af,
-}; /* CR_Ideographic */
-
-/* 'Diacritic': Binary Property */
-static const OnigCodePoint CR_Diacritic[] = {
- 195,
- 0x005e, 0x005e,
- 0x0060, 0x0060,
- 0x00a8, 0x00a8,
- 0x00af, 0x00af,
- 0x00b4, 0x00b4,
- 0x00b7, 0x00b8,
- 0x02b0, 0x034e,
- 0x0350, 0x0357,
- 0x035d, 0x0362,
- 0x0374, 0x0375,
- 0x037a, 0x037a,
- 0x0384, 0x0385,
- 0x0483, 0x0487,
- 0x0559, 0x0559,
- 0x0591, 0x05a1,
- 0x05a3, 0x05bd,
- 0x05bf, 0x05bf,
- 0x05c1, 0x05c2,
- 0x05c4, 0x05c4,
- 0x064b, 0x0652,
- 0x0657, 0x0658,
- 0x06df, 0x06e0,
- 0x06e5, 0x06e6,
- 0x06ea, 0x06ec,
- 0x0730, 0x074a,
- 0x07a6, 0x07b0,
- 0x07eb, 0x07f5,
- 0x0818, 0x0819,
- 0x0898, 0x089f,
- 0x08c9, 0x08d2,
- 0x08e3, 0x08fe,
- 0x093c, 0x093c,
- 0x094d, 0x094d,
- 0x0951, 0x0954,
- 0x0971, 0x0971,
- 0x09bc, 0x09bc,
- 0x09cd, 0x09cd,
- 0x0a3c, 0x0a3c,
- 0x0a4d, 0x0a4d,
- 0x0abc, 0x0abc,
- 0x0acd, 0x0acd,
- 0x0afd, 0x0aff,
- 0x0b3c, 0x0b3c,
- 0x0b4d, 0x0b4d,
- 0x0b55, 0x0b55,
- 0x0bcd, 0x0bcd,
- 0x0c3c, 0x0c3c,
- 0x0c4d, 0x0c4d,
- 0x0cbc, 0x0cbc,
- 0x0ccd, 0x0ccd,
- 0x0d3b, 0x0d3c,
- 0x0d4d, 0x0d4d,
- 0x0dca, 0x0dca,
- 0x0e47, 0x0e4c,
- 0x0e4e, 0x0e4e,
- 0x0eba, 0x0eba,
- 0x0ec8, 0x0ecc,
- 0x0f18, 0x0f19,
- 0x0f35, 0x0f35,
- 0x0f37, 0x0f37,
- 0x0f39, 0x0f39,
- 0x0f3e, 0x0f3f,
- 0x0f82, 0x0f84,
- 0x0f86, 0x0f87,
- 0x0fc6, 0x0fc6,
- 0x1037, 0x1037,
- 0x1039, 0x103a,
- 0x1063, 0x1064,
- 0x1069, 0x106d,
- 0x1087, 0x108d,
- 0x108f, 0x108f,
- 0x109a, 0x109b,
- 0x135d, 0x135f,
- 0x1714, 0x1715,
- 0x17c9, 0x17d3,
- 0x17dd, 0x17dd,
- 0x1939, 0x193b,
- 0x1a75, 0x1a7c,
- 0x1a7f, 0x1a7f,
- 0x1ab0, 0x1abe,
- 0x1ac1, 0x1acb,
- 0x1b34, 0x1b34,
- 0x1b44, 0x1b44,
- 0x1b6b, 0x1b73,
- 0x1baa, 0x1bab,
- 0x1c36, 0x1c37,
- 0x1c78, 0x1c7d,
- 0x1cd0, 0x1ce8,
- 0x1ced, 0x1ced,
- 0x1cf4, 0x1cf4,
- 0x1cf7, 0x1cf9,
- 0x1d2c, 0x1d6a,
- 0x1dc4, 0x1dcf,
- 0x1df5, 0x1dff,
- 0x1fbd, 0x1fbd,
- 0x1fbf, 0x1fc1,
- 0x1fcd, 0x1fcf,
- 0x1fdd, 0x1fdf,
- 0x1fed, 0x1fef,
- 0x1ffd, 0x1ffe,
- 0x2cef, 0x2cf1,
- 0x2e2f, 0x2e2f,
- 0x302a, 0x302f,
- 0x3099, 0x309c,
- 0x30fc, 0x30fc,
- 0xa66f, 0xa66f,
- 0xa67c, 0xa67d,
- 0xa67f, 0xa67f,
- 0xa69c, 0xa69d,
- 0xa6f0, 0xa6f1,
- 0xa700, 0xa721,
- 0xa788, 0xa78a,
- 0xa7f8, 0xa7f9,
- 0xa8c4, 0xa8c4,
- 0xa8e0, 0xa8f1,
- 0xa92b, 0xa92e,
- 0xa953, 0xa953,
- 0xa9b3, 0xa9b3,
- 0xa9c0, 0xa9c0,
- 0xa9e5, 0xa9e5,
- 0xaa7b, 0xaa7d,
- 0xaabf, 0xaac2,
- 0xaaf6, 0xaaf6,
- 0xab5b, 0xab5f,
- 0xab69, 0xab6b,
- 0xabec, 0xabed,
- 0xfb1e, 0xfb1e,
- 0xfe20, 0xfe2f,
- 0xff3e, 0xff3e,
- 0xff40, 0xff40,
- 0xff70, 0xff70,
- 0xff9e, 0xff9f,
- 0xffe3, 0xffe3,
- 0x102e0, 0x102e0,
- 0x10780, 0x10785,
- 0x10787, 0x107b0,
- 0x107b2, 0x107ba,
- 0x10ae5, 0x10ae6,
- 0x10d22, 0x10d27,
- 0x10efd, 0x10eff,
- 0x10f46, 0x10f50,
- 0x10f82, 0x10f85,
- 0x11046, 0x11046,
- 0x11070, 0x11070,
- 0x110b9, 0x110ba,
- 0x11133, 0x11134,
- 0x11173, 0x11173,
- 0x111c0, 0x111c0,
- 0x111ca, 0x111cc,
- 0x11235, 0x11236,
- 0x112e9, 0x112ea,
- 0x1133c, 0x1133c,
- 0x1134d, 0x1134d,
- 0x11366, 0x1136c,
- 0x11370, 0x11374,
- 0x11442, 0x11442,
- 0x11446, 0x11446,
- 0x114c2, 0x114c3,
- 0x115bf, 0x115c0,
- 0x1163f, 0x1163f,
- 0x116b6, 0x116b7,
- 0x1172b, 0x1172b,
- 0x11839, 0x1183a,
- 0x1193d, 0x1193e,
- 0x11943, 0x11943,
- 0x119e0, 0x119e0,
- 0x11a34, 0x11a34,
- 0x11a47, 0x11a47,
- 0x11a99, 0x11a99,
- 0x11c3f, 0x11c3f,
- 0x11d42, 0x11d42,
- 0x11d44, 0x11d45,
- 0x11d97, 0x11d97,
- 0x13447, 0x13455,
- 0x16af0, 0x16af4,
- 0x16b30, 0x16b36,
- 0x16f8f, 0x16f9f,
- 0x16ff0, 0x16ff1,
- 0x1aff0, 0x1aff3,
- 0x1aff5, 0x1affb,
- 0x1affd, 0x1affe,
- 0x1cf00, 0x1cf2d,
- 0x1cf30, 0x1cf46,
- 0x1d167, 0x1d169,
- 0x1d16d, 0x1d172,
- 0x1d17b, 0x1d182,
- 0x1d185, 0x1d18b,
- 0x1d1aa, 0x1d1ad,
- 0x1e030, 0x1e06d,
- 0x1e130, 0x1e136,
- 0x1e2ae, 0x1e2ae,
- 0x1e2ec, 0x1e2ef,
- 0x1e8d0, 0x1e8d6,
- 0x1e944, 0x1e946,
- 0x1e948, 0x1e94a,
-}; /* CR_Diacritic */
-
-/* 'Extender': Binary Property */
-static const OnigCodePoint CR_Extender[] = {
- 33,
- 0x00b7, 0x00b7,
- 0x02d0, 0x02d1,
- 0x0640, 0x0640,
- 0x07fa, 0x07fa,
- 0x0b55, 0x0b55,
- 0x0e46, 0x0e46,
- 0x0ec6, 0x0ec6,
- 0x180a, 0x180a,
- 0x1843, 0x1843,
- 0x1aa7, 0x1aa7,
- 0x1c36, 0x1c36,
- 0x1c7b, 0x1c7b,
- 0x3005, 0x3005,
- 0x3031, 0x3035,
- 0x309d, 0x309e,
- 0x30fc, 0x30fe,
- 0xa015, 0xa015,
- 0xa60c, 0xa60c,
- 0xa9cf, 0xa9cf,
- 0xa9e6, 0xa9e6,
- 0xaa70, 0xaa70,
- 0xaadd, 0xaadd,
- 0xaaf3, 0xaaf4,
- 0xff70, 0xff70,
- 0x10781, 0x10782,
- 0x1135d, 0x1135d,
- 0x115c6, 0x115c8,
- 0x11a98, 0x11a98,
- 0x16b42, 0x16b43,
- 0x16fe0, 0x16fe1,
- 0x16fe3, 0x16fe3,
- 0x1e13c, 0x1e13d,
- 0x1e944, 0x1e946,
-}; /* CR_Extender */
-
-/* 'Other_Lowercase': Binary Property */
-static const OnigCodePoint CR_Other_Lowercase[] = {
- 28,
- 0x00aa, 0x00aa,
- 0x00ba, 0x00ba,
- 0x02b0, 0x02b8,
- 0x02c0, 0x02c1,
- 0x02e0, 0x02e4,
- 0x0345, 0x0345,
- 0x037a, 0x037a,
- 0x10fc, 0x10fc,
- 0x1d2c, 0x1d6a,
- 0x1d78, 0x1d78,
- 0x1d9b, 0x1dbf,
- 0x2071, 0x2071,
- 0x207f, 0x207f,
- 0x2090, 0x209c,
- 0x2170, 0x217f,
- 0x24d0, 0x24e9,
- 0x2c7c, 0x2c7d,
- 0xa69c, 0xa69d,
- 0xa770, 0xa770,
- 0xa7f2, 0xa7f4,
- 0xa7f8, 0xa7f9,
- 0xab5c, 0xab5f,
- 0xab69, 0xab69,
- 0x10780, 0x10780,
- 0x10783, 0x10785,
- 0x10787, 0x107b0,
- 0x107b2, 0x107ba,
- 0x1e030, 0x1e06d,
-}; /* CR_Other_Lowercase */
-
-/* 'Other_Uppercase': Binary Property */
-static const OnigCodePoint CR_Other_Uppercase[] = {
- 5,
- 0x2160, 0x216f,
- 0x24b6, 0x24cf,
- 0x1f130, 0x1f149,
- 0x1f150, 0x1f169,
- 0x1f170, 0x1f189,
-}; /* CR_Other_Uppercase */
-
-/* 'Noncharacter_Code_Point': Binary Property */
-static const OnigCodePoint CR_Noncharacter_Code_Point[] = {
- 18,
- 0xfdd0, 0xfdef,
- 0xfffe, 0xffff,
- 0x1fffe, 0x1ffff,
- 0x2fffe, 0x2ffff,
- 0x3fffe, 0x3ffff,
- 0x4fffe, 0x4ffff,
- 0x5fffe, 0x5ffff,
- 0x6fffe, 0x6ffff,
- 0x7fffe, 0x7ffff,
- 0x8fffe, 0x8ffff,
- 0x9fffe, 0x9ffff,
- 0xafffe, 0xaffff,
- 0xbfffe, 0xbffff,
- 0xcfffe, 0xcffff,
- 0xdfffe, 0xdffff,
- 0xefffe, 0xeffff,
- 0xffffe, 0xfffff,
- 0x10fffe, 0x10ffff,
-}; /* CR_Noncharacter_Code_Point */
-
-/* 'Other_Grapheme_Extend': Binary Property */
-static const OnigCodePoint CR_Other_Grapheme_Extend[] = {
- 25,
- 0x09be, 0x09be,
- 0x09d7, 0x09d7,
- 0x0b3e, 0x0b3e,
- 0x0b57, 0x0b57,
- 0x0bbe, 0x0bbe,
- 0x0bd7, 0x0bd7,
- 0x0cc2, 0x0cc2,
- 0x0cd5, 0x0cd6,
- 0x0d3e, 0x0d3e,
- 0x0d57, 0x0d57,
- 0x0dcf, 0x0dcf,
- 0x0ddf, 0x0ddf,
- 0x1b35, 0x1b35,
- 0x200c, 0x200c,
- 0x302e, 0x302f,
- 0xff9e, 0xff9f,
- 0x1133e, 0x1133e,
- 0x11357, 0x11357,
- 0x114b0, 0x114b0,
- 0x114bd, 0x114bd,
- 0x115af, 0x115af,
- 0x11930, 0x11930,
- 0x1d165, 0x1d165,
- 0x1d16e, 0x1d172,
- 0xe0020, 0xe007f,
-}; /* CR_Other_Grapheme_Extend */
-
-/* 'IDS_Binary_Operator': Binary Property */
-static const OnigCodePoint CR_IDS_Binary_Operator[] = {
- 2,
- 0x2ff0, 0x2ff1,
- 0x2ff4, 0x2ffb,
-}; /* CR_IDS_Binary_Operator */
-
-/* 'IDS_Trinary_Operator': Binary Property */
-static const OnigCodePoint CR_IDS_Trinary_Operator[] = {
- 1,
- 0x2ff2, 0x2ff3,
-}; /* CR_IDS_Trinary_Operator */
-
-/* 'Radical': Binary Property */
-static const OnigCodePoint CR_Radical[] = {
- 3,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
-}; /* CR_Radical */
-
-/* 'Unified_Ideograph': Binary Property */
-static const OnigCodePoint CR_Unified_Ideograph[] = {
- 16,
- 0x3400, 0x4dbf,
- 0x4e00, 0x9fff,
- 0xfa0e, 0xfa0f,
- 0xfa11, 0xfa11,
- 0xfa13, 0xfa14,
- 0xfa1f, 0xfa1f,
- 0xfa21, 0xfa21,
- 0xfa23, 0xfa24,
- 0xfa27, 0xfa29,
- 0x20000, 0x2a6df,
- 0x2a700, 0x2b739,
- 0x2b740, 0x2b81d,
- 0x2b820, 0x2cea1,
- 0x2ceb0, 0x2ebe0,
- 0x30000, 0x3134a,
- 0x31350, 0x323af,
-}; /* CR_Unified_Ideograph */
-
-/* 'Other_Default_Ignorable_Code_Point': Binary Property */
-static const OnigCodePoint CR_Other_Default_Ignorable_Code_Point[] = {
- 11,
- 0x034f, 0x034f,
- 0x115f, 0x1160,
- 0x17b4, 0x17b5,
- 0x2065, 0x2065,
- 0x3164, 0x3164,
- 0xffa0, 0xffa0,
- 0xfff0, 0xfff8,
- 0xe0000, 0xe0000,
- 0xe0002, 0xe001f,
- 0xe0080, 0xe00ff,
- 0xe01f0, 0xe0fff,
-}; /* CR_Other_Default_Ignorable_Code_Point */
-
-/* 'Deprecated': Binary Property */
-static const OnigCodePoint CR_Deprecated[] = {
- 8,
- 0x0149, 0x0149,
- 0x0673, 0x0673,
- 0x0f77, 0x0f77,
- 0x0f79, 0x0f79,
- 0x17a3, 0x17a4,
- 0x206a, 0x206f,
- 0x2329, 0x232a,
- 0xe0001, 0xe0001,
-}; /* CR_Deprecated */
-
-/* 'Soft_Dotted': Binary Property */
-static const OnigCodePoint CR_Soft_Dotted[] = {
- 34,
- 0x0069, 0x006a,
- 0x012f, 0x012f,
- 0x0249, 0x0249,
- 0x0268, 0x0268,
- 0x029d, 0x029d,
- 0x02b2, 0x02b2,
- 0x03f3, 0x03f3,
- 0x0456, 0x0456,
- 0x0458, 0x0458,
- 0x1d62, 0x1d62,
- 0x1d96, 0x1d96,
- 0x1da4, 0x1da4,
- 0x1da8, 0x1da8,
- 0x1e2d, 0x1e2d,
- 0x1ecb, 0x1ecb,
- 0x2071, 0x2071,
- 0x2148, 0x2149,
- 0x2c7c, 0x2c7c,
- 0x1d422, 0x1d423,
- 0x1d456, 0x1d457,
- 0x1d48a, 0x1d48b,
- 0x1d4be, 0x1d4bf,
- 0x1d4f2, 0x1d4f3,
- 0x1d526, 0x1d527,
- 0x1d55a, 0x1d55b,
- 0x1d58e, 0x1d58f,
- 0x1d5c2, 0x1d5c3,
- 0x1d5f6, 0x1d5f7,
- 0x1d62a, 0x1d62b,
- 0x1d65e, 0x1d65f,
- 0x1d692, 0x1d693,
- 0x1df1a, 0x1df1a,
- 0x1e04c, 0x1e04d,
- 0x1e068, 0x1e068,
-}; /* CR_Soft_Dotted */
-
-/* 'Logical_Order_Exception': Binary Property */
-static const OnigCodePoint CR_Logical_Order_Exception[] = {
- 7,
- 0x0e40, 0x0e44,
- 0x0ec0, 0x0ec4,
- 0x19b5, 0x19b7,
- 0x19ba, 0x19ba,
- 0xaab5, 0xaab6,
- 0xaab9, 0xaab9,
- 0xaabb, 0xaabc,
-}; /* CR_Logical_Order_Exception */
-
-/* 'Other_ID_Start': Binary Property */
-static const OnigCodePoint CR_Other_ID_Start[] = {
- 4,
- 0x1885, 0x1886,
- 0x2118, 0x2118,
- 0x212e, 0x212e,
- 0x309b, 0x309c,
-}; /* CR_Other_ID_Start */
-
-/* 'Other_ID_Continue': Binary Property */
-static const OnigCodePoint CR_Other_ID_Continue[] = {
- 4,
- 0x00b7, 0x00b7,
- 0x0387, 0x0387,
- 0x1369, 0x1371,
- 0x19da, 0x19da,
-}; /* CR_Other_ID_Continue */
-
-/* 'Sentence_Terminal': Binary Property */
-static const OnigCodePoint CR_Sentence_Terminal[] = {
- 80,
- 0x0021, 0x0021,
- 0x002e, 0x002e,
- 0x003f, 0x003f,
- 0x0589, 0x0589,
- 0x061d, 0x061f,
- 0x06d4, 0x06d4,
- 0x0700, 0x0702,
- 0x07f9, 0x07f9,
- 0x0837, 0x0837,
- 0x0839, 0x0839,
- 0x083d, 0x083e,
- 0x0964, 0x0965,
- 0x104a, 0x104b,
- 0x1362, 0x1362,
- 0x1367, 0x1368,
- 0x166e, 0x166e,
- 0x1735, 0x1736,
- 0x1803, 0x1803,
- 0x1809, 0x1809,
- 0x1944, 0x1945,
- 0x1aa8, 0x1aab,
- 0x1b5a, 0x1b5b,
- 0x1b5e, 0x1b5f,
- 0x1b7d, 0x1b7e,
- 0x1c3b, 0x1c3c,
- 0x1c7e, 0x1c7f,
- 0x203c, 0x203d,
- 0x2047, 0x2049,
- 0x2e2e, 0x2e2e,
- 0x2e3c, 0x2e3c,
- 0x2e53, 0x2e54,
- 0x3002, 0x3002,
- 0xa4ff, 0xa4ff,
- 0xa60e, 0xa60f,
- 0xa6f3, 0xa6f3,
- 0xa6f7, 0xa6f7,
- 0xa876, 0xa877,
- 0xa8ce, 0xa8cf,
- 0xa92f, 0xa92f,
- 0xa9c8, 0xa9c9,
- 0xaa5d, 0xaa5f,
- 0xaaf0, 0xaaf1,
- 0xabeb, 0xabeb,
- 0xfe52, 0xfe52,
- 0xfe56, 0xfe57,
- 0xff01, 0xff01,
- 0xff0e, 0xff0e,
- 0xff1f, 0xff1f,
- 0xff61, 0xff61,
- 0x10a56, 0x10a57,
- 0x10f55, 0x10f59,
- 0x10f86, 0x10f89,
- 0x11047, 0x11048,
- 0x110be, 0x110c1,
- 0x11141, 0x11143,
- 0x111c5, 0x111c6,
- 0x111cd, 0x111cd,
- 0x111de, 0x111df,
- 0x11238, 0x11239,
- 0x1123b, 0x1123c,
- 0x112a9, 0x112a9,
- 0x1144b, 0x1144c,
- 0x115c2, 0x115c3,
- 0x115c9, 0x115d7,
- 0x11641, 0x11642,
- 0x1173c, 0x1173e,
- 0x11944, 0x11944,
- 0x11946, 0x11946,
- 0x11a42, 0x11a43,
- 0x11a9b, 0x11a9c,
- 0x11c41, 0x11c42,
- 0x11ef7, 0x11ef8,
- 0x11f43, 0x11f44,
- 0x16a6e, 0x16a6f,
- 0x16af5, 0x16af5,
- 0x16b37, 0x16b38,
- 0x16b44, 0x16b44,
- 0x16e98, 0x16e98,
- 0x1bc9f, 0x1bc9f,
- 0x1da88, 0x1da88,
-}; /* CR_Sentence_Terminal */
-
-/* 'Variation_Selector': Binary Property */
-static const OnigCodePoint CR_Variation_Selector[] = {
- 4,
- 0x180b, 0x180d,
- 0x180f, 0x180f,
- 0xfe00, 0xfe0f,
- 0xe0100, 0xe01ef,
-}; /* CR_Variation_Selector */
-
-/* 'Pattern_White_Space': Binary Property */
-static const OnigCodePoint CR_Pattern_White_Space[] = {
- 5,
- 0x0009, 0x000d,
- 0x0020, 0x0020,
- 0x0085, 0x0085,
- 0x200e, 0x200f,
- 0x2028, 0x2029,
-}; /* CR_Pattern_White_Space */
-
-/* 'Pattern_Syntax': Binary Property */
-static const OnigCodePoint CR_Pattern_Syntax[] = {
- 28,
- 0x0021, 0x002f,
- 0x003a, 0x0040,
- 0x005b, 0x005e,
- 0x0060, 0x0060,
- 0x007b, 0x007e,
- 0x00a1, 0x00a7,
- 0x00a9, 0x00a9,
- 0x00ab, 0x00ac,
- 0x00ae, 0x00ae,
- 0x00b0, 0x00b1,
- 0x00b6, 0x00b6,
- 0x00bb, 0x00bb,
- 0x00bf, 0x00bf,
- 0x00d7, 0x00d7,
- 0x00f7, 0x00f7,
- 0x2010, 0x2027,
- 0x2030, 0x203e,
- 0x2041, 0x2053,
- 0x2055, 0x205e,
- 0x2190, 0x245f,
- 0x2500, 0x2775,
- 0x2794, 0x2bff,
- 0x2e00, 0x2e7f,
- 0x3001, 0x3003,
- 0x3008, 0x3020,
- 0x3030, 0x3030,
- 0xfd3e, 0xfd3f,
- 0xfe45, 0xfe46,
-}; /* CR_Pattern_Syntax */
-
-/* 'Prepended_Concatenation_Mark': Binary Property */
-static const OnigCodePoint CR_Prepended_Concatenation_Mark[] = {
- 7,
- 0x0600, 0x0605,
- 0x06dd, 0x06dd,
- 0x070f, 0x070f,
- 0x0890, 0x0891,
- 0x08e2, 0x08e2,
- 0x110bd, 0x110bd,
- 0x110cd, 0x110cd,
-}; /* CR_Prepended_Concatenation_Mark */
-
-/* 'Regional_Indicator': Binary Property */
-static const OnigCodePoint CR_Regional_Indicator[] = {
- 1,
- 0x1f1e6, 0x1f1ff,
-}; /* CR_Regional_Indicator */
-
-/* 'Emoji': Emoji */
-static const OnigCodePoint CR_Emoji[] = {
- 151,
- 0x0023, 0x0023,
- 0x002a, 0x002a,
- 0x0030, 0x0039,
- 0x00a9, 0x00a9,
- 0x00ae, 0x00ae,
- 0x203c, 0x203c,
- 0x2049, 0x2049,
- 0x2122, 0x2122,
- 0x2139, 0x2139,
- 0x2194, 0x2199,
- 0x21a9, 0x21aa,
- 0x231a, 0x231b,
- 0x2328, 0x2328,
- 0x23cf, 0x23cf,
- 0x23e9, 0x23f3,
- 0x23f8, 0x23fa,
- 0x24c2, 0x24c2,
- 0x25aa, 0x25ab,
- 0x25b6, 0x25b6,
- 0x25c0, 0x25c0,
- 0x25fb, 0x25fe,
- 0x2600, 0x2604,
- 0x260e, 0x260e,
- 0x2611, 0x2611,
- 0x2614, 0x2615,
- 0x2618, 0x2618,
- 0x261d, 0x261d,
- 0x2620, 0x2620,
- 0x2622, 0x2623,
- 0x2626, 0x2626,
- 0x262a, 0x262a,
- 0x262e, 0x262f,
- 0x2638, 0x263a,
- 0x2640, 0x2640,
- 0x2642, 0x2642,
- 0x2648, 0x2653,
- 0x265f, 0x2660,
- 0x2663, 0x2663,
- 0x2665, 0x2666,
- 0x2668, 0x2668,
- 0x267b, 0x267b,
- 0x267e, 0x267f,
- 0x2692, 0x2697,
- 0x2699, 0x2699,
- 0x269b, 0x269c,
- 0x26a0, 0x26a1,
- 0x26a7, 0x26a7,
- 0x26aa, 0x26ab,
- 0x26b0, 0x26b1,
- 0x26bd, 0x26be,
- 0x26c4, 0x26c5,
- 0x26c8, 0x26c8,
- 0x26ce, 0x26cf,
- 0x26d1, 0x26d1,
- 0x26d3, 0x26d4,
- 0x26e9, 0x26ea,
- 0x26f0, 0x26f5,
- 0x26f7, 0x26fa,
- 0x26fd, 0x26fd,
- 0x2702, 0x2702,
- 0x2705, 0x2705,
- 0x2708, 0x270d,
- 0x270f, 0x270f,
- 0x2712, 0x2712,
- 0x2714, 0x2714,
- 0x2716, 0x2716,
- 0x271d, 0x271d,
- 0x2721, 0x2721,
- 0x2728, 0x2728,
- 0x2733, 0x2734,
- 0x2744, 0x2744,
- 0x2747, 0x2747,
- 0x274c, 0x274c,
- 0x274e, 0x274e,
- 0x2753, 0x2755,
- 0x2757, 0x2757,
- 0x2763, 0x2764,
- 0x2795, 0x2797,
- 0x27a1, 0x27a1,
- 0x27b0, 0x27b0,
- 0x27bf, 0x27bf,
- 0x2934, 0x2935,
- 0x2b05, 0x2b07,
- 0x2b1b, 0x2b1c,
- 0x2b50, 0x2b50,
- 0x2b55, 0x2b55,
- 0x3030, 0x3030,
- 0x303d, 0x303d,
- 0x3297, 0x3297,
- 0x3299, 0x3299,
- 0x1f004, 0x1f004,
- 0x1f0cf, 0x1f0cf,
- 0x1f170, 0x1f171,
- 0x1f17e, 0x1f17f,
- 0x1f18e, 0x1f18e,
- 0x1f191, 0x1f19a,
- 0x1f1e6, 0x1f1ff,
- 0x1f201, 0x1f202,
- 0x1f21a, 0x1f21a,
- 0x1f22f, 0x1f22f,
- 0x1f232, 0x1f23a,
- 0x1f250, 0x1f251,
- 0x1f300, 0x1f321,
- 0x1f324, 0x1f393,
- 0x1f396, 0x1f397,
- 0x1f399, 0x1f39b,
- 0x1f39e, 0x1f3f0,
- 0x1f3f3, 0x1f3f5,
- 0x1f3f7, 0x1f4fd,
- 0x1f4ff, 0x1f53d,
- 0x1f549, 0x1f54e,
- 0x1f550, 0x1f567,
- 0x1f56f, 0x1f570,
- 0x1f573, 0x1f57a,
- 0x1f587, 0x1f587,
- 0x1f58a, 0x1f58d,
- 0x1f590, 0x1f590,
- 0x1f595, 0x1f596,
- 0x1f5a4, 0x1f5a5,
- 0x1f5a8, 0x1f5a8,
- 0x1f5b1, 0x1f5b2,
- 0x1f5bc, 0x1f5bc,
- 0x1f5c2, 0x1f5c4,
- 0x1f5d1, 0x1f5d3,
- 0x1f5dc, 0x1f5de,
- 0x1f5e1, 0x1f5e1,
- 0x1f5e3, 0x1f5e3,
- 0x1f5e8, 0x1f5e8,
- 0x1f5ef, 0x1f5ef,
- 0x1f5f3, 0x1f5f3,
- 0x1f5fa, 0x1f64f,
- 0x1f680, 0x1f6c5,
- 0x1f6cb, 0x1f6d2,
- 0x1f6d5, 0x1f6d7,
- 0x1f6dc, 0x1f6e5,
- 0x1f6e9, 0x1f6e9,
- 0x1f6eb, 0x1f6ec,
- 0x1f6f0, 0x1f6f0,
- 0x1f6f3, 0x1f6fc,
- 0x1f7e0, 0x1f7eb,
- 0x1f7f0, 0x1f7f0,
- 0x1f90c, 0x1f93a,
- 0x1f93c, 0x1f945,
- 0x1f947, 0x1f9ff,
- 0x1fa70, 0x1fa7c,
- 0x1fa80, 0x1fa88,
- 0x1fa90, 0x1fabd,
- 0x1fabf, 0x1fac5,
- 0x1face, 0x1fadb,
- 0x1fae0, 0x1fae8,
- 0x1faf0, 0x1faf8,
-}; /* CR_Emoji */
-
-/* 'Emoji_Presentation': Emoji */
-static const OnigCodePoint CR_Emoji_Presentation[] = {
- 81,
- 0x231a, 0x231b,
- 0x23e9, 0x23ec,
- 0x23f0, 0x23f0,
- 0x23f3, 0x23f3,
- 0x25fd, 0x25fe,
- 0x2614, 0x2615,
- 0x2648, 0x2653,
- 0x267f, 0x267f,
- 0x2693, 0x2693,
- 0x26a1, 0x26a1,
- 0x26aa, 0x26ab,
- 0x26bd, 0x26be,
- 0x26c4, 0x26c5,
- 0x26ce, 0x26ce,
- 0x26d4, 0x26d4,
- 0x26ea, 0x26ea,
- 0x26f2, 0x26f3,
- 0x26f5, 0x26f5,
- 0x26fa, 0x26fa,
- 0x26fd, 0x26fd,
- 0x2705, 0x2705,
- 0x270a, 0x270b,
- 0x2728, 0x2728,
- 0x274c, 0x274c,
- 0x274e, 0x274e,
- 0x2753, 0x2755,
- 0x2757, 0x2757,
- 0x2795, 0x2797,
- 0x27b0, 0x27b0,
- 0x27bf, 0x27bf,
- 0x2b1b, 0x2b1c,
- 0x2b50, 0x2b50,
- 0x2b55, 0x2b55,
- 0x1f004, 0x1f004,
- 0x1f0cf, 0x1f0cf,
- 0x1f18e, 0x1f18e,
- 0x1f191, 0x1f19a,
- 0x1f1e6, 0x1f1ff,
- 0x1f201, 0x1f201,
- 0x1f21a, 0x1f21a,
- 0x1f22f, 0x1f22f,
- 0x1f232, 0x1f236,
- 0x1f238, 0x1f23a,
- 0x1f250, 0x1f251,
- 0x1f300, 0x1f320,
- 0x1f32d, 0x1f335,
- 0x1f337, 0x1f37c,
- 0x1f37e, 0x1f393,
- 0x1f3a0, 0x1f3ca,
- 0x1f3cf, 0x1f3d3,
- 0x1f3e0, 0x1f3f0,
- 0x1f3f4, 0x1f3f4,
- 0x1f3f8, 0x1f43e,
- 0x1f440, 0x1f440,
- 0x1f442, 0x1f4fc,
- 0x1f4ff, 0x1f53d,
- 0x1f54b, 0x1f54e,
- 0x1f550, 0x1f567,
- 0x1f57a, 0x1f57a,
- 0x1f595, 0x1f596,
- 0x1f5a4, 0x1f5a4,
- 0x1f5fb, 0x1f64f,
- 0x1f680, 0x1f6c5,
- 0x1f6cc, 0x1f6cc,
- 0x1f6d0, 0x1f6d2,
- 0x1f6d5, 0x1f6d7,
- 0x1f6dc, 0x1f6df,
- 0x1f6eb, 0x1f6ec,
- 0x1f6f4, 0x1f6fc,
- 0x1f7e0, 0x1f7eb,
- 0x1f7f0, 0x1f7f0,
- 0x1f90c, 0x1f93a,
- 0x1f93c, 0x1f945,
- 0x1f947, 0x1f9ff,
- 0x1fa70, 0x1fa7c,
- 0x1fa80, 0x1fa88,
- 0x1fa90, 0x1fabd,
- 0x1fabf, 0x1fac5,
- 0x1face, 0x1fadb,
- 0x1fae0, 0x1fae8,
- 0x1faf0, 0x1faf8,
-}; /* CR_Emoji_Presentation */
-
-/* 'Emoji_Modifier': Emoji */
-static const OnigCodePoint CR_Emoji_Modifier[] = {
- 1,
- 0x1f3fb, 0x1f3ff,
-}; /* CR_Emoji_Modifier */
-
-/* 'Emoji_Modifier_Base': Emoji */
-static const OnigCodePoint CR_Emoji_Modifier_Base[] = {
- 40,
- 0x261d, 0x261d,
- 0x26f9, 0x26f9,
- 0x270a, 0x270d,
- 0x1f385, 0x1f385,
- 0x1f3c2, 0x1f3c4,
- 0x1f3c7, 0x1f3c7,
- 0x1f3ca, 0x1f3cc,
- 0x1f442, 0x1f443,
- 0x1f446, 0x1f450,
- 0x1f466, 0x1f478,
- 0x1f47c, 0x1f47c,
- 0x1f481, 0x1f483,
- 0x1f485, 0x1f487,
- 0x1f48f, 0x1f48f,
- 0x1f491, 0x1f491,
- 0x1f4aa, 0x1f4aa,
- 0x1f574, 0x1f575,
- 0x1f57a, 0x1f57a,
- 0x1f590, 0x1f590,
- 0x1f595, 0x1f596,
- 0x1f645, 0x1f647,
- 0x1f64b, 0x1f64f,
- 0x1f6a3, 0x1f6a3,
- 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,
- 0x1f9cd, 0x1f9cf,
- 0x1f9d1, 0x1f9dd,
- 0x1fac3, 0x1fac5,
- 0x1faf0, 0x1faf8,
-}; /* CR_Emoji_Modifier_Base */
-
-/* 'Emoji_Component': Emoji */
-static const OnigCodePoint CR_Emoji_Component[] = {
- 10,
- 0x0023, 0x0023,
- 0x002a, 0x002a,
- 0x0030, 0x0039,
- 0x200d, 0x200d,
- 0x20e3, 0x20e3,
- 0xfe0f, 0xfe0f,
- 0x1f1e6, 0x1f1ff,
- 0x1f3fb, 0x1f3ff,
- 0x1f9b0, 0x1f9b3,
- 0xe0020, 0xe007f,
-}; /* CR_Emoji_Component */
-
-/* 'Extended_Pictographic': Emoji */
-static const OnigCodePoint CR_Extended_Pictographic[] = {
- 78,
- 0x00a9, 0x00a9,
- 0x00ae, 0x00ae,
- 0x203c, 0x203c,
- 0x2049, 0x2049,
- 0x2122, 0x2122,
- 0x2139, 0x2139,
- 0x2194, 0x2199,
- 0x21a9, 0x21aa,
- 0x231a, 0x231b,
- 0x2328, 0x2328,
- 0x2388, 0x2388,
- 0x23cf, 0x23cf,
- 0x23e9, 0x23f3,
- 0x23f8, 0x23fa,
- 0x24c2, 0x24c2,
- 0x25aa, 0x25ab,
- 0x25b6, 0x25b6,
- 0x25c0, 0x25c0,
- 0x25fb, 0x25fe,
- 0x2600, 0x2605,
- 0x2607, 0x2612,
- 0x2614, 0x2685,
- 0x2690, 0x2705,
- 0x2708, 0x2712,
- 0x2714, 0x2714,
- 0x2716, 0x2716,
- 0x271d, 0x271d,
- 0x2721, 0x2721,
- 0x2728, 0x2728,
- 0x2733, 0x2734,
- 0x2744, 0x2744,
- 0x2747, 0x2747,
- 0x274c, 0x274c,
- 0x274e, 0x274e,
- 0x2753, 0x2755,
- 0x2757, 0x2757,
- 0x2763, 0x2767,
- 0x2795, 0x2797,
- 0x27a1, 0x27a1,
- 0x27b0, 0x27b0,
- 0x27bf, 0x27bf,
- 0x2934, 0x2935,
- 0x2b05, 0x2b07,
- 0x2b1b, 0x2b1c,
- 0x2b50, 0x2b50,
- 0x2b55, 0x2b55,
- 0x3030, 0x3030,
- 0x303d, 0x303d,
- 0x3297, 0x3297,
- 0x3299, 0x3299,
- 0x1f000, 0x1f0ff,
- 0x1f10d, 0x1f10f,
- 0x1f12f, 0x1f12f,
- 0x1f16c, 0x1f171,
- 0x1f17e, 0x1f17f,
- 0x1f18e, 0x1f18e,
- 0x1f191, 0x1f19a,
- 0x1f1ad, 0x1f1e5,
- 0x1f201, 0x1f20f,
- 0x1f21a, 0x1f21a,
- 0x1f22f, 0x1f22f,
- 0x1f232, 0x1f23a,
- 0x1f23c, 0x1f23f,
- 0x1f249, 0x1f3fa,
- 0x1f400, 0x1f53d,
- 0x1f546, 0x1f64f,
- 0x1f680, 0x1f6ff,
- 0x1f774, 0x1f77f,
- 0x1f7d5, 0x1f7ff,
- 0x1f80c, 0x1f80f,
- 0x1f848, 0x1f84f,
- 0x1f85a, 0x1f85f,
- 0x1f888, 0x1f88f,
- 0x1f8ae, 0x1f8ff,
- 0x1f90c, 0x1f93a,
- 0x1f93c, 0x1f945,
- 0x1f947, 0x1faff,
- 0x1fc00, 0x1fffd,
-}; /* CR_Extended_Pictographic */
-
-/* 'Unknown': Script */
-static const OnigCodePoint CR_Unknown[] = {
- 705,
- 0x0378, 0x0379,
- 0x0380, 0x0383,
- 0x038b, 0x038b,
- 0x038d, 0x038d,
- 0x03a2, 0x03a2,
- 0x0530, 0x0530,
- 0x0557, 0x0558,
- 0x058b, 0x058c,
- 0x0590, 0x0590,
- 0x05c8, 0x05cf,
- 0x05eb, 0x05ee,
- 0x05f5, 0x05ff,
- 0x070e, 0x070e,
- 0x074b, 0x074c,
- 0x07b2, 0x07bf,
- 0x07fb, 0x07fc,
- 0x082e, 0x082f,
- 0x083f, 0x083f,
- 0x085c, 0x085d,
- 0x085f, 0x085f,
- 0x086b, 0x086f,
- 0x088f, 0x088f,
- 0x0892, 0x0897,
- 0x0984, 0x0984,
- 0x098d, 0x098e,
- 0x0991, 0x0992,
- 0x09a9, 0x09a9,
- 0x09b1, 0x09b1,
- 0x09b3, 0x09b5,
- 0x09ba, 0x09bb,
- 0x09c5, 0x09c6,
- 0x09c9, 0x09ca,
- 0x09cf, 0x09d6,
- 0x09d8, 0x09db,
- 0x09de, 0x09de,
- 0x09e4, 0x09e5,
- 0x09ff, 0x0a00,
- 0x0a04, 0x0a04,
- 0x0a0b, 0x0a0e,
- 0x0a11, 0x0a12,
- 0x0a29, 0x0a29,
- 0x0a31, 0x0a31,
- 0x0a34, 0x0a34,
- 0x0a37, 0x0a37,
- 0x0a3a, 0x0a3b,
- 0x0a3d, 0x0a3d,
- 0x0a43, 0x0a46,
- 0x0a49, 0x0a4a,
- 0x0a4e, 0x0a50,
- 0x0a52, 0x0a58,
- 0x0a5d, 0x0a5d,
- 0x0a5f, 0x0a65,
- 0x0a77, 0x0a80,
- 0x0a84, 0x0a84,
- 0x0a8e, 0x0a8e,
- 0x0a92, 0x0a92,
- 0x0aa9, 0x0aa9,
- 0x0ab1, 0x0ab1,
- 0x0ab4, 0x0ab4,
- 0x0aba, 0x0abb,
- 0x0ac6, 0x0ac6,
- 0x0aca, 0x0aca,
- 0x0ace, 0x0acf,
- 0x0ad1, 0x0adf,
- 0x0ae4, 0x0ae5,
- 0x0af2, 0x0af8,
- 0x0b00, 0x0b00,
- 0x0b04, 0x0b04,
- 0x0b0d, 0x0b0e,
- 0x0b11, 0x0b12,
- 0x0b29, 0x0b29,
- 0x0b31, 0x0b31,
- 0x0b34, 0x0b34,
- 0x0b3a, 0x0b3b,
- 0x0b45, 0x0b46,
- 0x0b49, 0x0b4a,
- 0x0b4e, 0x0b54,
- 0x0b58, 0x0b5b,
- 0x0b5e, 0x0b5e,
- 0x0b64, 0x0b65,
- 0x0b78, 0x0b81,
- 0x0b84, 0x0b84,
- 0x0b8b, 0x0b8d,
- 0x0b91, 0x0b91,
- 0x0b96, 0x0b98,
- 0x0b9b, 0x0b9b,
- 0x0b9d, 0x0b9d,
- 0x0ba0, 0x0ba2,
- 0x0ba5, 0x0ba7,
- 0x0bab, 0x0bad,
- 0x0bba, 0x0bbd,
- 0x0bc3, 0x0bc5,
- 0x0bc9, 0x0bc9,
- 0x0bce, 0x0bcf,
- 0x0bd1, 0x0bd6,
- 0x0bd8, 0x0be5,
- 0x0bfb, 0x0bff,
- 0x0c0d, 0x0c0d,
- 0x0c11, 0x0c11,
- 0x0c29, 0x0c29,
- 0x0c3a, 0x0c3b,
- 0x0c45, 0x0c45,
- 0x0c49, 0x0c49,
- 0x0c4e, 0x0c54,
- 0x0c57, 0x0c57,
- 0x0c5b, 0x0c5c,
- 0x0c5e, 0x0c5f,
- 0x0c64, 0x0c65,
- 0x0c70, 0x0c76,
- 0x0c8d, 0x0c8d,
- 0x0c91, 0x0c91,
- 0x0ca9, 0x0ca9,
- 0x0cb4, 0x0cb4,
- 0x0cba, 0x0cbb,
- 0x0cc5, 0x0cc5,
- 0x0cc9, 0x0cc9,
- 0x0cce, 0x0cd4,
- 0x0cd7, 0x0cdc,
- 0x0cdf, 0x0cdf,
- 0x0ce4, 0x0ce5,
- 0x0cf0, 0x0cf0,
- 0x0cf4, 0x0cff,
- 0x0d0d, 0x0d0d,
- 0x0d11, 0x0d11,
- 0x0d45, 0x0d45,
- 0x0d49, 0x0d49,
- 0x0d50, 0x0d53,
- 0x0d64, 0x0d65,
- 0x0d80, 0x0d80,
- 0x0d84, 0x0d84,
- 0x0d97, 0x0d99,
- 0x0db2, 0x0db2,
- 0x0dbc, 0x0dbc,
- 0x0dbe, 0x0dbf,
- 0x0dc7, 0x0dc9,
- 0x0dcb, 0x0dce,
- 0x0dd5, 0x0dd5,
- 0x0dd7, 0x0dd7,
- 0x0de0, 0x0de5,
- 0x0df0, 0x0df1,
- 0x0df5, 0x0e00,
- 0x0e3b, 0x0e3e,
- 0x0e5c, 0x0e80,
- 0x0e83, 0x0e83,
- 0x0e85, 0x0e85,
- 0x0e8b, 0x0e8b,
- 0x0ea4, 0x0ea4,
- 0x0ea6, 0x0ea6,
- 0x0ebe, 0x0ebf,
- 0x0ec5, 0x0ec5,
- 0x0ec7, 0x0ec7,
- 0x0ecf, 0x0ecf,
- 0x0eda, 0x0edb,
- 0x0ee0, 0x0eff,
- 0x0f48, 0x0f48,
- 0x0f6d, 0x0f70,
- 0x0f98, 0x0f98,
- 0x0fbd, 0x0fbd,
- 0x0fcd, 0x0fcd,
- 0x0fdb, 0x0fff,
- 0x10c6, 0x10c6,
- 0x10c8, 0x10cc,
- 0x10ce, 0x10cf,
- 0x1249, 0x1249,
- 0x124e, 0x124f,
- 0x1257, 0x1257,
- 0x1259, 0x1259,
- 0x125e, 0x125f,
- 0x1289, 0x1289,
- 0x128e, 0x128f,
- 0x12b1, 0x12b1,
- 0x12b6, 0x12b7,
- 0x12bf, 0x12bf,
- 0x12c1, 0x12c1,
- 0x12c6, 0x12c7,
- 0x12d7, 0x12d7,
- 0x1311, 0x1311,
- 0x1316, 0x1317,
- 0x135b, 0x135c,
- 0x137d, 0x137f,
- 0x139a, 0x139f,
- 0x13f6, 0x13f7,
- 0x13fe, 0x13ff,
- 0x169d, 0x169f,
- 0x16f9, 0x16ff,
- 0x1716, 0x171e,
- 0x1737, 0x173f,
- 0x1754, 0x175f,
- 0x176d, 0x176d,
- 0x1771, 0x1771,
- 0x1774, 0x177f,
- 0x17de, 0x17df,
- 0x17ea, 0x17ef,
- 0x17fa, 0x17ff,
- 0x181a, 0x181f,
- 0x1879, 0x187f,
- 0x18ab, 0x18af,
- 0x18f6, 0x18ff,
- 0x191f, 0x191f,
- 0x192c, 0x192f,
- 0x193c, 0x193f,
- 0x1941, 0x1943,
- 0x196e, 0x196f,
- 0x1975, 0x197f,
- 0x19ac, 0x19af,
- 0x19ca, 0x19cf,
- 0x19db, 0x19dd,
- 0x1a1c, 0x1a1d,
- 0x1a5f, 0x1a5f,
- 0x1a7d, 0x1a7e,
- 0x1a8a, 0x1a8f,
- 0x1a9a, 0x1a9f,
- 0x1aae, 0x1aaf,
- 0x1acf, 0x1aff,
- 0x1b4d, 0x1b4f,
- 0x1b7f, 0x1b7f,
- 0x1bf4, 0x1bfb,
- 0x1c38, 0x1c3a,
- 0x1c4a, 0x1c4c,
- 0x1c89, 0x1c8f,
- 0x1cbb, 0x1cbc,
- 0x1cc8, 0x1ccf,
- 0x1cfb, 0x1cff,
- 0x1f16, 0x1f17,
- 0x1f1e, 0x1f1f,
- 0x1f46, 0x1f47,
- 0x1f4e, 0x1f4f,
- 0x1f58, 0x1f58,
- 0x1f5a, 0x1f5a,
- 0x1f5c, 0x1f5c,
- 0x1f5e, 0x1f5e,
- 0x1f7e, 0x1f7f,
- 0x1fb5, 0x1fb5,
- 0x1fc5, 0x1fc5,
- 0x1fd4, 0x1fd5,
- 0x1fdc, 0x1fdc,
- 0x1ff0, 0x1ff1,
- 0x1ff5, 0x1ff5,
- 0x1fff, 0x1fff,
- 0x2065, 0x2065,
- 0x2072, 0x2073,
- 0x208f, 0x208f,
- 0x209d, 0x209f,
- 0x20c1, 0x20cf,
- 0x20f1, 0x20ff,
- 0x218c, 0x218f,
- 0x2427, 0x243f,
- 0x244b, 0x245f,
- 0x2b74, 0x2b75,
- 0x2b96, 0x2b96,
- 0x2cf4, 0x2cf8,
- 0x2d26, 0x2d26,
- 0x2d28, 0x2d2c,
- 0x2d2e, 0x2d2f,
- 0x2d68, 0x2d6e,
- 0x2d71, 0x2d7e,
- 0x2d97, 0x2d9f,
- 0x2da7, 0x2da7,
- 0x2daf, 0x2daf,
- 0x2db7, 0x2db7,
- 0x2dbf, 0x2dbf,
- 0x2dc7, 0x2dc7,
- 0x2dcf, 0x2dcf,
- 0x2dd7, 0x2dd7,
- 0x2ddf, 0x2ddf,
- 0x2e5e, 0x2e7f,
- 0x2e9a, 0x2e9a,
- 0x2ef4, 0x2eff,
- 0x2fd6, 0x2fef,
- 0x2ffc, 0x2fff,
- 0x3040, 0x3040,
- 0x3097, 0x3098,
- 0x3100, 0x3104,
- 0x3130, 0x3130,
- 0x318f, 0x318f,
- 0x31e4, 0x31ef,
- 0x321f, 0x321f,
- 0xa48d, 0xa48f,
- 0xa4c7, 0xa4cf,
- 0xa62c, 0xa63f,
- 0xa6f8, 0xa6ff,
- 0xa7cb, 0xa7cf,
- 0xa7d2, 0xa7d2,
- 0xa7d4, 0xa7d4,
- 0xa7da, 0xa7f1,
- 0xa82d, 0xa82f,
- 0xa83a, 0xa83f,
- 0xa878, 0xa87f,
- 0xa8c6, 0xa8cd,
- 0xa8da, 0xa8df,
- 0xa954, 0xa95e,
- 0xa97d, 0xa97f,
- 0xa9ce, 0xa9ce,
- 0xa9da, 0xa9dd,
- 0xa9ff, 0xa9ff,
- 0xaa37, 0xaa3f,
- 0xaa4e, 0xaa4f,
- 0xaa5a, 0xaa5b,
- 0xaac3, 0xaada,
- 0xaaf7, 0xab00,
- 0xab07, 0xab08,
- 0xab0f, 0xab10,
- 0xab17, 0xab1f,
- 0xab27, 0xab27,
- 0xab2f, 0xab2f,
- 0xab6c, 0xab6f,
- 0xabee, 0xabef,
- 0xabfa, 0xabff,
- 0xd7a4, 0xd7af,
- 0xd7c7, 0xd7ca,
- 0xd7fc, 0xf8ff,
- 0xfa6e, 0xfa6f,
- 0xfada, 0xfaff,
- 0xfb07, 0xfb12,
- 0xfb18, 0xfb1c,
- 0xfb37, 0xfb37,
- 0xfb3d, 0xfb3d,
- 0xfb3f, 0xfb3f,
- 0xfb42, 0xfb42,
- 0xfb45, 0xfb45,
- 0xfbc3, 0xfbd2,
- 0xfd90, 0xfd91,
- 0xfdc8, 0xfdce,
- 0xfdd0, 0xfdef,
- 0xfe1a, 0xfe1f,
- 0xfe53, 0xfe53,
- 0xfe67, 0xfe67,
- 0xfe6c, 0xfe6f,
- 0xfe75, 0xfe75,
- 0xfefd, 0xfefe,
- 0xff00, 0xff00,
- 0xffbf, 0xffc1,
- 0xffc8, 0xffc9,
- 0xffd0, 0xffd1,
- 0xffd8, 0xffd9,
- 0xffdd, 0xffdf,
- 0xffe7, 0xffe7,
- 0xffef, 0xfff8,
- 0xfffe, 0xffff,
- 0x1000c, 0x1000c,
- 0x10027, 0x10027,
- 0x1003b, 0x1003b,
- 0x1003e, 0x1003e,
- 0x1004e, 0x1004f,
- 0x1005e, 0x1007f,
- 0x100fb, 0x100ff,
- 0x10103, 0x10106,
- 0x10134, 0x10136,
- 0x1018f, 0x1018f,
- 0x1019d, 0x1019f,
- 0x101a1, 0x101cf,
- 0x101fe, 0x1027f,
- 0x1029d, 0x1029f,
- 0x102d1, 0x102df,
- 0x102fc, 0x102ff,
- 0x10324, 0x1032c,
- 0x1034b, 0x1034f,
- 0x1037b, 0x1037f,
- 0x1039e, 0x1039e,
- 0x103c4, 0x103c7,
- 0x103d6, 0x103ff,
- 0x1049e, 0x1049f,
- 0x104aa, 0x104af,
- 0x104d4, 0x104d7,
- 0x104fc, 0x104ff,
- 0x10528, 0x1052f,
- 0x10564, 0x1056e,
- 0x1057b, 0x1057b,
- 0x1058b, 0x1058b,
- 0x10593, 0x10593,
- 0x10596, 0x10596,
- 0x105a2, 0x105a2,
- 0x105b2, 0x105b2,
- 0x105ba, 0x105ba,
- 0x105bd, 0x105ff,
- 0x10737, 0x1073f,
- 0x10756, 0x1075f,
- 0x10768, 0x1077f,
- 0x10786, 0x10786,
- 0x107b1, 0x107b1,
- 0x107bb, 0x107ff,
- 0x10806, 0x10807,
- 0x10809, 0x10809,
- 0x10836, 0x10836,
- 0x10839, 0x1083b,
- 0x1083d, 0x1083e,
- 0x10856, 0x10856,
- 0x1089f, 0x108a6,
- 0x108b0, 0x108df,
- 0x108f3, 0x108f3,
- 0x108f6, 0x108fa,
- 0x1091c, 0x1091e,
- 0x1093a, 0x1093e,
- 0x10940, 0x1097f,
- 0x109b8, 0x109bb,
- 0x109d0, 0x109d1,
- 0x10a04, 0x10a04,
- 0x10a07, 0x10a0b,
- 0x10a14, 0x10a14,
- 0x10a18, 0x10a18,
- 0x10a36, 0x10a37,
- 0x10a3b, 0x10a3e,
- 0x10a49, 0x10a4f,
- 0x10a59, 0x10a5f,
- 0x10aa0, 0x10abf,
- 0x10ae7, 0x10aea,
- 0x10af7, 0x10aff,
- 0x10b36, 0x10b38,
- 0x10b56, 0x10b57,
- 0x10b73, 0x10b77,
- 0x10b92, 0x10b98,
- 0x10b9d, 0x10ba8,
- 0x10bb0, 0x10bff,
- 0x10c49, 0x10c7f,
- 0x10cb3, 0x10cbf,
- 0x10cf3, 0x10cf9,
- 0x10d28, 0x10d2f,
- 0x10d3a, 0x10e5f,
- 0x10e7f, 0x10e7f,
- 0x10eaa, 0x10eaa,
- 0x10eae, 0x10eaf,
- 0x10eb2, 0x10efc,
- 0x10f28, 0x10f2f,
- 0x10f5a, 0x10f6f,
- 0x10f8a, 0x10faf,
- 0x10fcc, 0x10fdf,
- 0x10ff7, 0x10fff,
- 0x1104e, 0x11051,
- 0x11076, 0x1107e,
- 0x110c3, 0x110cc,
- 0x110ce, 0x110cf,
- 0x110e9, 0x110ef,
- 0x110fa, 0x110ff,
- 0x11135, 0x11135,
- 0x11148, 0x1114f,
- 0x11177, 0x1117f,
- 0x111e0, 0x111e0,
- 0x111f5, 0x111ff,
- 0x11212, 0x11212,
- 0x11242, 0x1127f,
- 0x11287, 0x11287,
- 0x11289, 0x11289,
- 0x1128e, 0x1128e,
- 0x1129e, 0x1129e,
- 0x112aa, 0x112af,
- 0x112eb, 0x112ef,
- 0x112fa, 0x112ff,
- 0x11304, 0x11304,
- 0x1130d, 0x1130e,
- 0x11311, 0x11312,
- 0x11329, 0x11329,
- 0x11331, 0x11331,
- 0x11334, 0x11334,
- 0x1133a, 0x1133a,
- 0x11345, 0x11346,
- 0x11349, 0x1134a,
- 0x1134e, 0x1134f,
- 0x11351, 0x11356,
- 0x11358, 0x1135c,
- 0x11364, 0x11365,
- 0x1136d, 0x1136f,
- 0x11375, 0x113ff,
- 0x1145c, 0x1145c,
- 0x11462, 0x1147f,
- 0x114c8, 0x114cf,
- 0x114da, 0x1157f,
- 0x115b6, 0x115b7,
- 0x115de, 0x115ff,
- 0x11645, 0x1164f,
- 0x1165a, 0x1165f,
- 0x1166d, 0x1167f,
- 0x116ba, 0x116bf,
- 0x116ca, 0x116ff,
- 0x1171b, 0x1171c,
- 0x1172c, 0x1172f,
- 0x11747, 0x117ff,
- 0x1183c, 0x1189f,
- 0x118f3, 0x118fe,
- 0x11907, 0x11908,
- 0x1190a, 0x1190b,
- 0x11914, 0x11914,
- 0x11917, 0x11917,
- 0x11936, 0x11936,
- 0x11939, 0x1193a,
- 0x11947, 0x1194f,
- 0x1195a, 0x1199f,
- 0x119a8, 0x119a9,
- 0x119d8, 0x119d9,
- 0x119e5, 0x119ff,
- 0x11a48, 0x11a4f,
- 0x11aa3, 0x11aaf,
- 0x11af9, 0x11aff,
- 0x11b0a, 0x11bff,
- 0x11c09, 0x11c09,
- 0x11c37, 0x11c37,
- 0x11c46, 0x11c4f,
- 0x11c6d, 0x11c6f,
- 0x11c90, 0x11c91,
- 0x11ca8, 0x11ca8,
- 0x11cb7, 0x11cff,
- 0x11d07, 0x11d07,
- 0x11d0a, 0x11d0a,
- 0x11d37, 0x11d39,
- 0x11d3b, 0x11d3b,
- 0x11d3e, 0x11d3e,
- 0x11d48, 0x11d4f,
- 0x11d5a, 0x11d5f,
- 0x11d66, 0x11d66,
- 0x11d69, 0x11d69,
- 0x11d8f, 0x11d8f,
- 0x11d92, 0x11d92,
- 0x11d99, 0x11d9f,
- 0x11daa, 0x11edf,
- 0x11ef9, 0x11eff,
- 0x11f11, 0x11f11,
- 0x11f3b, 0x11f3d,
- 0x11f5a, 0x11faf,
- 0x11fb1, 0x11fbf,
- 0x11ff2, 0x11ffe,
- 0x1239a, 0x123ff,
- 0x1246f, 0x1246f,
- 0x12475, 0x1247f,
- 0x12544, 0x12f8f,
- 0x12ff3, 0x12fff,
- 0x13456, 0x143ff,
- 0x14647, 0x167ff,
- 0x16a39, 0x16a3f,
- 0x16a5f, 0x16a5f,
- 0x16a6a, 0x16a6d,
- 0x16abf, 0x16abf,
- 0x16aca, 0x16acf,
- 0x16aee, 0x16aef,
- 0x16af6, 0x16aff,
- 0x16b46, 0x16b4f,
- 0x16b5a, 0x16b5a,
- 0x16b62, 0x16b62,
- 0x16b78, 0x16b7c,
- 0x16b90, 0x16e3f,
- 0x16e9b, 0x16eff,
- 0x16f4b, 0x16f4e,
- 0x16f88, 0x16f8e,
- 0x16fa0, 0x16fdf,
- 0x16fe5, 0x16fef,
- 0x16ff2, 0x16fff,
- 0x187f8, 0x187ff,
- 0x18cd6, 0x18cff,
- 0x18d09, 0x1afef,
- 0x1aff4, 0x1aff4,
- 0x1affc, 0x1affc,
- 0x1afff, 0x1afff,
- 0x1b123, 0x1b131,
- 0x1b133, 0x1b14f,
- 0x1b153, 0x1b154,
- 0x1b156, 0x1b163,
- 0x1b168, 0x1b16f,
- 0x1b2fc, 0x1bbff,
- 0x1bc6b, 0x1bc6f,
- 0x1bc7d, 0x1bc7f,
- 0x1bc89, 0x1bc8f,
- 0x1bc9a, 0x1bc9b,
- 0x1bca4, 0x1ceff,
- 0x1cf2e, 0x1cf2f,
- 0x1cf47, 0x1cf4f,
- 0x1cfc4, 0x1cfff,
- 0x1d0f6, 0x1d0ff,
- 0x1d127, 0x1d128,
- 0x1d1eb, 0x1d1ff,
- 0x1d246, 0x1d2bf,
- 0x1d2d4, 0x1d2df,
- 0x1d2f4, 0x1d2ff,
- 0x1d357, 0x1d35f,
- 0x1d379, 0x1d3ff,
- 0x1d455, 0x1d455,
- 0x1d49d, 0x1d49d,
- 0x1d4a0, 0x1d4a1,
- 0x1d4a3, 0x1d4a4,
- 0x1d4a7, 0x1d4a8,
- 0x1d4ad, 0x1d4ad,
- 0x1d4ba, 0x1d4ba,
- 0x1d4bc, 0x1d4bc,
- 0x1d4c4, 0x1d4c4,
- 0x1d506, 0x1d506,
- 0x1d50b, 0x1d50c,
- 0x1d515, 0x1d515,
- 0x1d51d, 0x1d51d,
- 0x1d53a, 0x1d53a,
- 0x1d53f, 0x1d53f,
- 0x1d545, 0x1d545,
- 0x1d547, 0x1d549,
- 0x1d551, 0x1d551,
- 0x1d6a6, 0x1d6a7,
- 0x1d7cc, 0x1d7cd,
- 0x1da8c, 0x1da9a,
- 0x1daa0, 0x1daa0,
- 0x1dab0, 0x1deff,
- 0x1df1f, 0x1df24,
- 0x1df2b, 0x1dfff,
- 0x1e007, 0x1e007,
- 0x1e019, 0x1e01a,
- 0x1e022, 0x1e022,
- 0x1e025, 0x1e025,
- 0x1e02b, 0x1e02f,
- 0x1e06e, 0x1e08e,
- 0x1e090, 0x1e0ff,
- 0x1e12d, 0x1e12f,
- 0x1e13e, 0x1e13f,
- 0x1e14a, 0x1e14d,
- 0x1e150, 0x1e28f,
- 0x1e2af, 0x1e2bf,
- 0x1e2fa, 0x1e2fe,
- 0x1e300, 0x1e4cf,
- 0x1e4fa, 0x1e7df,
- 0x1e7e7, 0x1e7e7,
- 0x1e7ec, 0x1e7ec,
- 0x1e7ef, 0x1e7ef,
- 0x1e7ff, 0x1e7ff,
- 0x1e8c5, 0x1e8c6,
- 0x1e8d7, 0x1e8ff,
- 0x1e94c, 0x1e94f,
- 0x1e95a, 0x1e95d,
- 0x1e960, 0x1ec70,
- 0x1ecb5, 0x1ed00,
- 0x1ed3e, 0x1edff,
- 0x1ee04, 0x1ee04,
- 0x1ee20, 0x1ee20,
- 0x1ee23, 0x1ee23,
- 0x1ee25, 0x1ee26,
- 0x1ee28, 0x1ee28,
- 0x1ee33, 0x1ee33,
- 0x1ee38, 0x1ee38,
- 0x1ee3a, 0x1ee3a,
- 0x1ee3c, 0x1ee41,
- 0x1ee43, 0x1ee46,
- 0x1ee48, 0x1ee48,
- 0x1ee4a, 0x1ee4a,
- 0x1ee4c, 0x1ee4c,
- 0x1ee50, 0x1ee50,
- 0x1ee53, 0x1ee53,
- 0x1ee55, 0x1ee56,
- 0x1ee58, 0x1ee58,
- 0x1ee5a, 0x1ee5a,
- 0x1ee5c, 0x1ee5c,
- 0x1ee5e, 0x1ee5e,
- 0x1ee60, 0x1ee60,
- 0x1ee63, 0x1ee63,
- 0x1ee65, 0x1ee66,
- 0x1ee6b, 0x1ee6b,
- 0x1ee73, 0x1ee73,
- 0x1ee78, 0x1ee78,
- 0x1ee7d, 0x1ee7d,
- 0x1ee7f, 0x1ee7f,
- 0x1ee8a, 0x1ee8a,
- 0x1ee9c, 0x1eea0,
- 0x1eea4, 0x1eea4,
- 0x1eeaa, 0x1eeaa,
- 0x1eebc, 0x1eeef,
- 0x1eef2, 0x1efff,
- 0x1f02c, 0x1f02f,
- 0x1f094, 0x1f09f,
- 0x1f0af, 0x1f0b0,
- 0x1f0c0, 0x1f0c0,
- 0x1f0d0, 0x1f0d0,
- 0x1f0f6, 0x1f0ff,
- 0x1f1ae, 0x1f1e5,
- 0x1f203, 0x1f20f,
- 0x1f23c, 0x1f23f,
- 0x1f249, 0x1f24f,
- 0x1f252, 0x1f25f,
- 0x1f266, 0x1f2ff,
- 0x1f6d8, 0x1f6db,
- 0x1f6ed, 0x1f6ef,
- 0x1f6fd, 0x1f6ff,
- 0x1f777, 0x1f77a,
- 0x1f7da, 0x1f7df,
- 0x1f7ec, 0x1f7ef,
- 0x1f7f1, 0x1f7ff,
- 0x1f80c, 0x1f80f,
- 0x1f848, 0x1f84f,
- 0x1f85a, 0x1f85f,
- 0x1f888, 0x1f88f,
- 0x1f8ae, 0x1f8af,
- 0x1f8b2, 0x1f8ff,
- 0x1fa54, 0x1fa5f,
- 0x1fa6e, 0x1fa6f,
- 0x1fa7d, 0x1fa7f,
- 0x1fa89, 0x1fa8f,
- 0x1fabe, 0x1fabe,
- 0x1fac6, 0x1facd,
- 0x1fadc, 0x1fadf,
- 0x1fae9, 0x1faef,
- 0x1faf9, 0x1faff,
- 0x1fb93, 0x1fb93,
- 0x1fbcb, 0x1fbef,
- 0x1fbfa, 0x1ffff,
- 0x2a6e0, 0x2a6ff,
- 0x2b73a, 0x2b73f,
- 0x2b81e, 0x2b81f,
- 0x2cea2, 0x2ceaf,
- 0x2ebe1, 0x2f7ff,
- 0x2fa1e, 0x2ffff,
- 0x3134b, 0x3134f,
- 0x323b0, 0xe0000,
- 0xe0002, 0xe001f,
- 0xe0080, 0xe00ff,
- 0xe01f0, 0x10ffff,
-}; /* CR_Unknown */
-
-#ifdef USE_UNICODE_AGE_PROPERTIES
-/* 'Age_1_1': Derived Age 1.1 */
-static const OnigCodePoint CR_Age_1_1[] = {
- 288,
- 0x0000, 0x01f5,
- 0x01fa, 0x0217,
- 0x0250, 0x02a8,
- 0x02b0, 0x02de,
- 0x02e0, 0x02e9,
- 0x0300, 0x0345,
- 0x0360, 0x0361,
- 0x0374, 0x0375,
- 0x037a, 0x037a,
- 0x037e, 0x037e,
- 0x0384, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03ce,
- 0x03d0, 0x03d6,
- 0x03da, 0x03da,
- 0x03dc, 0x03dc,
- 0x03de, 0x03de,
- 0x03e0, 0x03e0,
- 0x03e2, 0x03f3,
- 0x0401, 0x040c,
- 0x040e, 0x044f,
- 0x0451, 0x045c,
- 0x045e, 0x0486,
- 0x0490, 0x04c4,
- 0x04c7, 0x04c8,
- 0x04cb, 0x04cc,
- 0x04d0, 0x04eb,
- 0x04ee, 0x04f5,
- 0x04f8, 0x04f9,
- 0x0531, 0x0556,
- 0x0559, 0x055f,
- 0x0561, 0x0587,
- 0x0589, 0x0589,
- 0x05b0, 0x05b9,
- 0x05bb, 0x05c3,
- 0x05d0, 0x05ea,
- 0x05f0, 0x05f4,
- 0x060c, 0x060c,
- 0x061b, 0x061b,
- 0x061f, 0x061f,
- 0x0621, 0x063a,
- 0x0640, 0x0652,
- 0x0660, 0x066d,
- 0x0670, 0x06b7,
- 0x06ba, 0x06be,
- 0x06c0, 0x06ce,
- 0x06d0, 0x06ed,
- 0x06f0, 0x06f9,
- 0x0901, 0x0903,
- 0x0905, 0x0939,
- 0x093c, 0x094d,
- 0x0950, 0x0954,
- 0x0958, 0x0970,
- 0x0981, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09bc,
- 0x09be, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09cd,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fa,
- 0x0a02, 0x0a02,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a74,
- 0x0a81, 0x0a83,
- 0x0a85, 0x0a8b,
- 0x0a8d, 0x0a8d,
- 0x0a8f, 0x0a91,
- 0x0a93, 0x0aa8,
- 0x0aaa, 0x0ab0,
- 0x0ab2, 0x0ab3,
- 0x0ab5, 0x0ab9,
- 0x0abc, 0x0ac5,
- 0x0ac7, 0x0ac9,
- 0x0acb, 0x0acd,
- 0x0ad0, 0x0ad0,
- 0x0ae0, 0x0ae0,
- 0x0ae6, 0x0aef,
- 0x0b01, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b36, 0x0b39,
- 0x0b3c, 0x0b43,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4d,
- 0x0b56, 0x0b57,
- 0x0b5c, 0x0b5d,
- 0x0b5f, 0x0b61,
- 0x0b66, 0x0b70,
- 0x0b82, 0x0b83,
- 0x0b85, 0x0b8a,
- 0x0b8e, 0x0b90,
- 0x0b92, 0x0b95,
- 0x0b99, 0x0b9a,
- 0x0b9c, 0x0b9c,
- 0x0b9e, 0x0b9f,
- 0x0ba3, 0x0ba4,
- 0x0ba8, 0x0baa,
- 0x0bae, 0x0bb5,
- 0x0bb7, 0x0bb9,
- 0x0bbe, 0x0bc2,
- 0x0bc6, 0x0bc8,
- 0x0bca, 0x0bcd,
- 0x0bd7, 0x0bd7,
- 0x0be7, 0x0bf2,
- 0x0c01, 0x0c03,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c33,
- 0x0c35, 0x0c39,
- 0x0c3e, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c60, 0x0c61,
- 0x0c66, 0x0c6f,
- 0x0c82, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbe, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce1,
- 0x0ce6, 0x0cef,
- 0x0d02, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d28,
- 0x0d2a, 0x0d39,
- 0x0d3e, 0x0d43,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4d,
- 0x0d57, 0x0d57,
- 0x0d60, 0x0d61,
- 0x0d66, 0x0d6f,
- 0x0e01, 0x0e3a,
- 0x0e3f, 0x0e5b,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e87, 0x0e88,
- 0x0e8a, 0x0e8a,
- 0x0e8d, 0x0e8d,
- 0x0e94, 0x0e97,
- 0x0e99, 0x0e9f,
- 0x0ea1, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ea7,
- 0x0eaa, 0x0eab,
- 0x0ead, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edd,
- 0x10a0, 0x10c5,
- 0x10d0, 0x10f6,
- 0x10fb, 0x10fb,
- 0x1100, 0x1159,
- 0x115f, 0x11a2,
- 0x11a8, 0x11f9,
- 0x1e00, 0x1e9a,
- 0x1ea0, 0x1ef9,
- 0x1f00, 0x1f15,
- 0x1f18, 0x1f1d,
- 0x1f20, 0x1f45,
- 0x1f48, 0x1f4d,
- 0x1f50, 0x1f57,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f7d,
- 0x1f80, 0x1fb4,
- 0x1fb6, 0x1fc4,
- 0x1fc6, 0x1fd3,
- 0x1fd6, 0x1fdb,
- 0x1fdd, 0x1fef,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ffe,
- 0x2000, 0x202e,
- 0x2030, 0x2046,
- 0x206a, 0x2070,
- 0x2074, 0x208e,
- 0x20a0, 0x20aa,
- 0x20d0, 0x20e1,
- 0x2100, 0x2138,
- 0x2153, 0x2182,
- 0x2190, 0x21ea,
- 0x2200, 0x22f1,
- 0x2300, 0x2300,
- 0x2302, 0x237a,
- 0x2400, 0x2424,
- 0x2440, 0x244a,
- 0x2460, 0x24ea,
- 0x2500, 0x2595,
- 0x25a0, 0x25ef,
- 0x2600, 0x2613,
- 0x261a, 0x266f,
- 0x2701, 0x2704,
- 0x2706, 0x2709,
- 0x270c, 0x2727,
- 0x2729, 0x274b,
- 0x274d, 0x274d,
- 0x274f, 0x2752,
- 0x2756, 0x2756,
- 0x2758, 0x275e,
- 0x2761, 0x2767,
- 0x2776, 0x2794,
- 0x2798, 0x27af,
- 0x27b1, 0x27be,
- 0x3000, 0x3037,
- 0x303f, 0x303f,
- 0x3041, 0x3094,
- 0x3099, 0x309e,
- 0x30a1, 0x30fe,
- 0x3105, 0x312c,
- 0x3131, 0x318e,
- 0x3190, 0x319f,
- 0x3200, 0x321c,
- 0x3220, 0x3243,
- 0x3260, 0x327b,
- 0x327f, 0x32b0,
- 0x32c0, 0x32cb,
- 0x32d0, 0x32fe,
- 0x3300, 0x3376,
- 0x337b, 0x33dd,
- 0x33e0, 0x33fe,
- 0x4e00, 0x9fa5,
- 0xe000, 0xfa2d,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1e, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbb1,
- 0xfbd3, 0xfd3f,
- 0xfd50, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdf0, 0xfdfb,
- 0xfe20, 0xfe23,
- 0xfe30, 0xfe44,
- 0xfe49, 0xfe52,
- 0xfe54, 0xfe66,
- 0xfe68, 0xfe6b,
- 0xfe70, 0xfe72,
- 0xfe74, 0xfe74,
- 0xfe76, 0xfefc,
- 0xfeff, 0xfeff,
- 0xff01, 0xff5e,
- 0xff61, 0xffbe,
- 0xffc2, 0xffc7,
- 0xffca, 0xffcf,
- 0xffd2, 0xffd7,
- 0xffda, 0xffdc,
- 0xffe0, 0xffe6,
- 0xffe8, 0xffee,
- 0xfffd, 0xffff,
-}; /* CR_Age_1_1 */
-
-/* 'Age_2_0': Derived Age 2.0 */
-static const OnigCodePoint CR_Age_2_0[] = {
- 312,
- 0x0000, 0x01f5,
- 0x01fa, 0x0217,
- 0x0250, 0x02a8,
- 0x02b0, 0x02de,
- 0x02e0, 0x02e9,
- 0x0300, 0x0345,
- 0x0360, 0x0361,
- 0x0374, 0x0375,
- 0x037a, 0x037a,
- 0x037e, 0x037e,
- 0x0384, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03ce,
- 0x03d0, 0x03d6,
- 0x03da, 0x03da,
- 0x03dc, 0x03dc,
- 0x03de, 0x03de,
- 0x03e0, 0x03e0,
- 0x03e2, 0x03f3,
- 0x0401, 0x040c,
- 0x040e, 0x044f,
- 0x0451, 0x045c,
- 0x045e, 0x0486,
- 0x0490, 0x04c4,
- 0x04c7, 0x04c8,
- 0x04cb, 0x04cc,
- 0x04d0, 0x04eb,
- 0x04ee, 0x04f5,
- 0x04f8, 0x04f9,
- 0x0531, 0x0556,
- 0x0559, 0x055f,
- 0x0561, 0x0587,
- 0x0589, 0x0589,
- 0x0591, 0x05a1,
- 0x05a3, 0x05b9,
- 0x05bb, 0x05c4,
- 0x05d0, 0x05ea,
- 0x05f0, 0x05f4,
- 0x060c, 0x060c,
- 0x061b, 0x061b,
- 0x061f, 0x061f,
- 0x0621, 0x063a,
- 0x0640, 0x0652,
- 0x0660, 0x066d,
- 0x0670, 0x06b7,
- 0x06ba, 0x06be,
- 0x06c0, 0x06ce,
- 0x06d0, 0x06ed,
- 0x06f0, 0x06f9,
- 0x0901, 0x0903,
- 0x0905, 0x0939,
- 0x093c, 0x094d,
- 0x0950, 0x0954,
- 0x0958, 0x0970,
- 0x0981, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09bc,
- 0x09be, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09cd,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fa,
- 0x0a02, 0x0a02,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a74,
- 0x0a81, 0x0a83,
- 0x0a85, 0x0a8b,
- 0x0a8d, 0x0a8d,
- 0x0a8f, 0x0a91,
- 0x0a93, 0x0aa8,
- 0x0aaa, 0x0ab0,
- 0x0ab2, 0x0ab3,
- 0x0ab5, 0x0ab9,
- 0x0abc, 0x0ac5,
- 0x0ac7, 0x0ac9,
- 0x0acb, 0x0acd,
- 0x0ad0, 0x0ad0,
- 0x0ae0, 0x0ae0,
- 0x0ae6, 0x0aef,
- 0x0b01, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b36, 0x0b39,
- 0x0b3c, 0x0b43,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4d,
- 0x0b56, 0x0b57,
- 0x0b5c, 0x0b5d,
- 0x0b5f, 0x0b61,
- 0x0b66, 0x0b70,
- 0x0b82, 0x0b83,
- 0x0b85, 0x0b8a,
- 0x0b8e, 0x0b90,
- 0x0b92, 0x0b95,
- 0x0b99, 0x0b9a,
- 0x0b9c, 0x0b9c,
- 0x0b9e, 0x0b9f,
- 0x0ba3, 0x0ba4,
- 0x0ba8, 0x0baa,
- 0x0bae, 0x0bb5,
- 0x0bb7, 0x0bb9,
- 0x0bbe, 0x0bc2,
- 0x0bc6, 0x0bc8,
- 0x0bca, 0x0bcd,
- 0x0bd7, 0x0bd7,
- 0x0be7, 0x0bf2,
- 0x0c01, 0x0c03,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c33,
- 0x0c35, 0x0c39,
- 0x0c3e, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c60, 0x0c61,
- 0x0c66, 0x0c6f,
- 0x0c82, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbe, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce1,
- 0x0ce6, 0x0cef,
- 0x0d02, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d28,
- 0x0d2a, 0x0d39,
- 0x0d3e, 0x0d43,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4d,
- 0x0d57, 0x0d57,
- 0x0d60, 0x0d61,
- 0x0d66, 0x0d6f,
- 0x0e01, 0x0e3a,
- 0x0e3f, 0x0e5b,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e87, 0x0e88,
- 0x0e8a, 0x0e8a,
- 0x0e8d, 0x0e8d,
- 0x0e94, 0x0e97,
- 0x0e99, 0x0e9f,
- 0x0ea1, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ea7,
- 0x0eaa, 0x0eab,
- 0x0ead, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edd,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f69,
- 0x0f71, 0x0f8b,
- 0x0f90, 0x0f95,
- 0x0f97, 0x0f97,
- 0x0f99, 0x0fad,
- 0x0fb1, 0x0fb7,
- 0x0fb9, 0x0fb9,
- 0x10a0, 0x10c5,
- 0x10d0, 0x10f6,
- 0x10fb, 0x10fb,
- 0x1100, 0x1159,
- 0x115f, 0x11a2,
- 0x11a8, 0x11f9,
- 0x1e00, 0x1e9b,
- 0x1ea0, 0x1ef9,
- 0x1f00, 0x1f15,
- 0x1f18, 0x1f1d,
- 0x1f20, 0x1f45,
- 0x1f48, 0x1f4d,
- 0x1f50, 0x1f57,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f7d,
- 0x1f80, 0x1fb4,
- 0x1fb6, 0x1fc4,
- 0x1fc6, 0x1fd3,
- 0x1fd6, 0x1fdb,
- 0x1fdd, 0x1fef,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ffe,
- 0x2000, 0x202e,
- 0x2030, 0x2046,
- 0x206a, 0x2070,
- 0x2074, 0x208e,
- 0x20a0, 0x20ab,
- 0x20d0, 0x20e1,
- 0x2100, 0x2138,
- 0x2153, 0x2182,
- 0x2190, 0x21ea,
- 0x2200, 0x22f1,
- 0x2300, 0x2300,
- 0x2302, 0x237a,
- 0x2400, 0x2424,
- 0x2440, 0x244a,
- 0x2460, 0x24ea,
- 0x2500, 0x2595,
- 0x25a0, 0x25ef,
- 0x2600, 0x2613,
- 0x261a, 0x266f,
- 0x2701, 0x2704,
- 0x2706, 0x2709,
- 0x270c, 0x2727,
- 0x2729, 0x274b,
- 0x274d, 0x274d,
- 0x274f, 0x2752,
- 0x2756, 0x2756,
- 0x2758, 0x275e,
- 0x2761, 0x2767,
- 0x2776, 0x2794,
- 0x2798, 0x27af,
- 0x27b1, 0x27be,
- 0x3000, 0x3037,
- 0x303f, 0x303f,
- 0x3041, 0x3094,
- 0x3099, 0x309e,
- 0x30a1, 0x30fe,
- 0x3105, 0x312c,
- 0x3131, 0x318e,
- 0x3190, 0x319f,
- 0x3200, 0x321c,
- 0x3220, 0x3243,
- 0x3260, 0x327b,
- 0x327f, 0x32b0,
- 0x32c0, 0x32cb,
- 0x32d0, 0x32fe,
- 0x3300, 0x3376,
- 0x337b, 0x33dd,
- 0x33e0, 0x33fe,
- 0x4e00, 0x9fa5,
- 0xac00, 0xd7a3,
- 0xd800, 0xfa2d,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1e, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbb1,
- 0xfbd3, 0xfd3f,
- 0xfd50, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdf0, 0xfdfb,
- 0xfe20, 0xfe23,
- 0xfe30, 0xfe44,
- 0xfe49, 0xfe52,
- 0xfe54, 0xfe66,
- 0xfe68, 0xfe6b,
- 0xfe70, 0xfe72,
- 0xfe74, 0xfe74,
- 0xfe76, 0xfefc,
- 0xfeff, 0xfeff,
- 0xff01, 0xff5e,
- 0xff61, 0xffbe,
- 0xffc2, 0xffc7,
- 0xffca, 0xffcf,
- 0xffd2, 0xffd7,
- 0xffda, 0xffdc,
- 0xffe0, 0xffe6,
- 0xffe8, 0xffee,
- 0xfffd, 0xffff,
- 0x1fffe, 0x1ffff,
- 0x2fffe, 0x2ffff,
- 0x3fffe, 0x3ffff,
- 0x4fffe, 0x4ffff,
- 0x5fffe, 0x5ffff,
- 0x6fffe, 0x6ffff,
- 0x7fffe, 0x7ffff,
- 0x8fffe, 0x8ffff,
- 0x9fffe, 0x9ffff,
- 0xafffe, 0xaffff,
- 0xbfffe, 0xbffff,
- 0xcfffe, 0xcffff,
- 0xdfffe, 0xdffff,
- 0xefffe, 0x10ffff,
-}; /* CR_Age_2_0 */
-
-/* 'Age_2_1': Derived Age 2.1 */
-static const OnigCodePoint CR_Age_2_1[] = {
- 312,
- 0x0000, 0x01f5,
- 0x01fa, 0x0217,
- 0x0250, 0x02a8,
- 0x02b0, 0x02de,
- 0x02e0, 0x02e9,
- 0x0300, 0x0345,
- 0x0360, 0x0361,
- 0x0374, 0x0375,
- 0x037a, 0x037a,
- 0x037e, 0x037e,
- 0x0384, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03ce,
- 0x03d0, 0x03d6,
- 0x03da, 0x03da,
- 0x03dc, 0x03dc,
- 0x03de, 0x03de,
- 0x03e0, 0x03e0,
- 0x03e2, 0x03f3,
- 0x0401, 0x040c,
- 0x040e, 0x044f,
- 0x0451, 0x045c,
- 0x045e, 0x0486,
- 0x0490, 0x04c4,
- 0x04c7, 0x04c8,
- 0x04cb, 0x04cc,
- 0x04d0, 0x04eb,
- 0x04ee, 0x04f5,
- 0x04f8, 0x04f9,
- 0x0531, 0x0556,
- 0x0559, 0x055f,
- 0x0561, 0x0587,
- 0x0589, 0x0589,
- 0x0591, 0x05a1,
- 0x05a3, 0x05b9,
- 0x05bb, 0x05c4,
- 0x05d0, 0x05ea,
- 0x05f0, 0x05f4,
- 0x060c, 0x060c,
- 0x061b, 0x061b,
- 0x061f, 0x061f,
- 0x0621, 0x063a,
- 0x0640, 0x0652,
- 0x0660, 0x066d,
- 0x0670, 0x06b7,
- 0x06ba, 0x06be,
- 0x06c0, 0x06ce,
- 0x06d0, 0x06ed,
- 0x06f0, 0x06f9,
- 0x0901, 0x0903,
- 0x0905, 0x0939,
- 0x093c, 0x094d,
- 0x0950, 0x0954,
- 0x0958, 0x0970,
- 0x0981, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09bc,
- 0x09be, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09cd,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fa,
- 0x0a02, 0x0a02,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a74,
- 0x0a81, 0x0a83,
- 0x0a85, 0x0a8b,
- 0x0a8d, 0x0a8d,
- 0x0a8f, 0x0a91,
- 0x0a93, 0x0aa8,
- 0x0aaa, 0x0ab0,
- 0x0ab2, 0x0ab3,
- 0x0ab5, 0x0ab9,
- 0x0abc, 0x0ac5,
- 0x0ac7, 0x0ac9,
- 0x0acb, 0x0acd,
- 0x0ad0, 0x0ad0,
- 0x0ae0, 0x0ae0,
- 0x0ae6, 0x0aef,
- 0x0b01, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b36, 0x0b39,
- 0x0b3c, 0x0b43,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4d,
- 0x0b56, 0x0b57,
- 0x0b5c, 0x0b5d,
- 0x0b5f, 0x0b61,
- 0x0b66, 0x0b70,
- 0x0b82, 0x0b83,
- 0x0b85, 0x0b8a,
- 0x0b8e, 0x0b90,
- 0x0b92, 0x0b95,
- 0x0b99, 0x0b9a,
- 0x0b9c, 0x0b9c,
- 0x0b9e, 0x0b9f,
- 0x0ba3, 0x0ba4,
- 0x0ba8, 0x0baa,
- 0x0bae, 0x0bb5,
- 0x0bb7, 0x0bb9,
- 0x0bbe, 0x0bc2,
- 0x0bc6, 0x0bc8,
- 0x0bca, 0x0bcd,
- 0x0bd7, 0x0bd7,
- 0x0be7, 0x0bf2,
- 0x0c01, 0x0c03,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c33,
- 0x0c35, 0x0c39,
- 0x0c3e, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c60, 0x0c61,
- 0x0c66, 0x0c6f,
- 0x0c82, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbe, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce1,
- 0x0ce6, 0x0cef,
- 0x0d02, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d28,
- 0x0d2a, 0x0d39,
- 0x0d3e, 0x0d43,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4d,
- 0x0d57, 0x0d57,
- 0x0d60, 0x0d61,
- 0x0d66, 0x0d6f,
- 0x0e01, 0x0e3a,
- 0x0e3f, 0x0e5b,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e87, 0x0e88,
- 0x0e8a, 0x0e8a,
- 0x0e8d, 0x0e8d,
- 0x0e94, 0x0e97,
- 0x0e99, 0x0e9f,
- 0x0ea1, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ea7,
- 0x0eaa, 0x0eab,
- 0x0ead, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edd,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f69,
- 0x0f71, 0x0f8b,
- 0x0f90, 0x0f95,
- 0x0f97, 0x0f97,
- 0x0f99, 0x0fad,
- 0x0fb1, 0x0fb7,
- 0x0fb9, 0x0fb9,
- 0x10a0, 0x10c5,
- 0x10d0, 0x10f6,
- 0x10fb, 0x10fb,
- 0x1100, 0x1159,
- 0x115f, 0x11a2,
- 0x11a8, 0x11f9,
- 0x1e00, 0x1e9b,
- 0x1ea0, 0x1ef9,
- 0x1f00, 0x1f15,
- 0x1f18, 0x1f1d,
- 0x1f20, 0x1f45,
- 0x1f48, 0x1f4d,
- 0x1f50, 0x1f57,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f7d,
- 0x1f80, 0x1fb4,
- 0x1fb6, 0x1fc4,
- 0x1fc6, 0x1fd3,
- 0x1fd6, 0x1fdb,
- 0x1fdd, 0x1fef,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ffe,
- 0x2000, 0x202e,
- 0x2030, 0x2046,
- 0x206a, 0x2070,
- 0x2074, 0x208e,
- 0x20a0, 0x20ac,
- 0x20d0, 0x20e1,
- 0x2100, 0x2138,
- 0x2153, 0x2182,
- 0x2190, 0x21ea,
- 0x2200, 0x22f1,
- 0x2300, 0x2300,
- 0x2302, 0x237a,
- 0x2400, 0x2424,
- 0x2440, 0x244a,
- 0x2460, 0x24ea,
- 0x2500, 0x2595,
- 0x25a0, 0x25ef,
- 0x2600, 0x2613,
- 0x261a, 0x266f,
- 0x2701, 0x2704,
- 0x2706, 0x2709,
- 0x270c, 0x2727,
- 0x2729, 0x274b,
- 0x274d, 0x274d,
- 0x274f, 0x2752,
- 0x2756, 0x2756,
- 0x2758, 0x275e,
- 0x2761, 0x2767,
- 0x2776, 0x2794,
- 0x2798, 0x27af,
- 0x27b1, 0x27be,
- 0x3000, 0x3037,
- 0x303f, 0x303f,
- 0x3041, 0x3094,
- 0x3099, 0x309e,
- 0x30a1, 0x30fe,
- 0x3105, 0x312c,
- 0x3131, 0x318e,
- 0x3190, 0x319f,
- 0x3200, 0x321c,
- 0x3220, 0x3243,
- 0x3260, 0x327b,
- 0x327f, 0x32b0,
- 0x32c0, 0x32cb,
- 0x32d0, 0x32fe,
- 0x3300, 0x3376,
- 0x337b, 0x33dd,
- 0x33e0, 0x33fe,
- 0x4e00, 0x9fa5,
- 0xac00, 0xd7a3,
- 0xd800, 0xfa2d,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1e, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbb1,
- 0xfbd3, 0xfd3f,
- 0xfd50, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdf0, 0xfdfb,
- 0xfe20, 0xfe23,
- 0xfe30, 0xfe44,
- 0xfe49, 0xfe52,
- 0xfe54, 0xfe66,
- 0xfe68, 0xfe6b,
- 0xfe70, 0xfe72,
- 0xfe74, 0xfe74,
- 0xfe76, 0xfefc,
- 0xfeff, 0xfeff,
- 0xff01, 0xff5e,
- 0xff61, 0xffbe,
- 0xffc2, 0xffc7,
- 0xffca, 0xffcf,
- 0xffd2, 0xffd7,
- 0xffda, 0xffdc,
- 0xffe0, 0xffe6,
- 0xffe8, 0xffee,
- 0xfffc, 0xffff,
- 0x1fffe, 0x1ffff,
- 0x2fffe, 0x2ffff,
- 0x3fffe, 0x3ffff,
- 0x4fffe, 0x4ffff,
- 0x5fffe, 0x5ffff,
- 0x6fffe, 0x6ffff,
- 0x7fffe, 0x7ffff,
- 0x8fffe, 0x8ffff,
- 0x9fffe, 0x9ffff,
- 0xafffe, 0xaffff,
- 0xbfffe, 0xbffff,
- 0xcfffe, 0xcffff,
- 0xdfffe, 0xdffff,
- 0xefffe, 0x10ffff,
-}; /* CR_Age_2_1 */
-
-/* 'Age_3_0': Derived Age 3.0 */
-static const OnigCodePoint CR_Age_3_0[] = {
- 369,
- 0x0000, 0x021f,
- 0x0222, 0x0233,
- 0x0250, 0x02ad,
- 0x02b0, 0x02ee,
- 0x0300, 0x034e,
- 0x0360, 0x0362,
- 0x0374, 0x0375,
- 0x037a, 0x037a,
- 0x037e, 0x037e,
- 0x0384, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03ce,
- 0x03d0, 0x03d7,
- 0x03da, 0x03f3,
- 0x0400, 0x0486,
- 0x0488, 0x0489,
- 0x048c, 0x04c4,
- 0x04c7, 0x04c8,
- 0x04cb, 0x04cc,
- 0x04d0, 0x04f5,
- 0x04f8, 0x04f9,
- 0x0531, 0x0556,
- 0x0559, 0x055f,
- 0x0561, 0x0587,
- 0x0589, 0x058a,
- 0x0591, 0x05a1,
- 0x05a3, 0x05b9,
- 0x05bb, 0x05c4,
- 0x05d0, 0x05ea,
- 0x05f0, 0x05f4,
- 0x060c, 0x060c,
- 0x061b, 0x061b,
- 0x061f, 0x061f,
- 0x0621, 0x063a,
- 0x0640, 0x0655,
- 0x0660, 0x066d,
- 0x0670, 0x06ed,
- 0x06f0, 0x06fe,
- 0x0700, 0x070d,
- 0x070f, 0x072c,
- 0x0730, 0x074a,
- 0x0780, 0x07b0,
- 0x0901, 0x0903,
- 0x0905, 0x0939,
- 0x093c, 0x094d,
- 0x0950, 0x0954,
- 0x0958, 0x0970,
- 0x0981, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09bc,
- 0x09be, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09cd,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fa,
- 0x0a02, 0x0a02,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a74,
- 0x0a81, 0x0a83,
- 0x0a85, 0x0a8b,
- 0x0a8d, 0x0a8d,
- 0x0a8f, 0x0a91,
- 0x0a93, 0x0aa8,
- 0x0aaa, 0x0ab0,
- 0x0ab2, 0x0ab3,
- 0x0ab5, 0x0ab9,
- 0x0abc, 0x0ac5,
- 0x0ac7, 0x0ac9,
- 0x0acb, 0x0acd,
- 0x0ad0, 0x0ad0,
- 0x0ae0, 0x0ae0,
- 0x0ae6, 0x0aef,
- 0x0b01, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b36, 0x0b39,
- 0x0b3c, 0x0b43,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4d,
- 0x0b56, 0x0b57,
- 0x0b5c, 0x0b5d,
- 0x0b5f, 0x0b61,
- 0x0b66, 0x0b70,
- 0x0b82, 0x0b83,
- 0x0b85, 0x0b8a,
- 0x0b8e, 0x0b90,
- 0x0b92, 0x0b95,
- 0x0b99, 0x0b9a,
- 0x0b9c, 0x0b9c,
- 0x0b9e, 0x0b9f,
- 0x0ba3, 0x0ba4,
- 0x0ba8, 0x0baa,
- 0x0bae, 0x0bb5,
- 0x0bb7, 0x0bb9,
- 0x0bbe, 0x0bc2,
- 0x0bc6, 0x0bc8,
- 0x0bca, 0x0bcd,
- 0x0bd7, 0x0bd7,
- 0x0be7, 0x0bf2,
- 0x0c01, 0x0c03,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c33,
- 0x0c35, 0x0c39,
- 0x0c3e, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c60, 0x0c61,
- 0x0c66, 0x0c6f,
- 0x0c82, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbe, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce1,
- 0x0ce6, 0x0cef,
- 0x0d02, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d28,
- 0x0d2a, 0x0d39,
- 0x0d3e, 0x0d43,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4d,
- 0x0d57, 0x0d57,
- 0x0d60, 0x0d61,
- 0x0d66, 0x0d6f,
- 0x0d82, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0df2, 0x0df4,
- 0x0e01, 0x0e3a,
- 0x0e3f, 0x0e5b,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e87, 0x0e88,
- 0x0e8a, 0x0e8a,
- 0x0e8d, 0x0e8d,
- 0x0e94, 0x0e97,
- 0x0e99, 0x0e9f,
- 0x0ea1, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ea7,
- 0x0eaa, 0x0eab,
- 0x0ead, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edd,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6a,
- 0x0f71, 0x0f8b,
- 0x0f90, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x0fbe, 0x0fcc,
- 0x0fcf, 0x0fcf,
- 0x1000, 0x1021,
- 0x1023, 0x1027,
- 0x1029, 0x102a,
- 0x102c, 0x1032,
- 0x1036, 0x1039,
- 0x1040, 0x1059,
- 0x10a0, 0x10c5,
- 0x10d0, 0x10f6,
- 0x10fb, 0x10fb,
- 0x1100, 0x1159,
- 0x115f, 0x11a2,
- 0x11a8, 0x11f9,
- 0x1200, 0x1206,
- 0x1208, 0x1246,
- 0x1248, 0x1248,
- 0x124a, 0x124d,
- 0x1250, 0x1256,
- 0x1258, 0x1258,
- 0x125a, 0x125d,
- 0x1260, 0x1286,
- 0x1288, 0x1288,
- 0x128a, 0x128d,
- 0x1290, 0x12ae,
- 0x12b0, 0x12b0,
- 0x12b2, 0x12b5,
- 0x12b8, 0x12be,
- 0x12c0, 0x12c0,
- 0x12c2, 0x12c5,
- 0x12c8, 0x12ce,
- 0x12d0, 0x12d6,
- 0x12d8, 0x12ee,
- 0x12f0, 0x130e,
- 0x1310, 0x1310,
- 0x1312, 0x1315,
- 0x1318, 0x131e,
- 0x1320, 0x1346,
- 0x1348, 0x135a,
- 0x1361, 0x137c,
- 0x13a0, 0x13f4,
- 0x1401, 0x1676,
- 0x1680, 0x169c,
- 0x16a0, 0x16f0,
- 0x1780, 0x17dc,
- 0x17e0, 0x17e9,
- 0x1800, 0x180e,
- 0x1810, 0x1819,
- 0x1820, 0x1877,
- 0x1880, 0x18a9,
- 0x1e00, 0x1e9b,
- 0x1ea0, 0x1ef9,
- 0x1f00, 0x1f15,
- 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, 0x2046,
- 0x2048, 0x204d,
- 0x206a, 0x2070,
- 0x2074, 0x208e,
- 0x20a0, 0x20af,
- 0x20d0, 0x20e3,
- 0x2100, 0x213a,
- 0x2153, 0x2183,
- 0x2190, 0x21f3,
- 0x2200, 0x22f1,
- 0x2300, 0x237b,
- 0x237d, 0x239a,
- 0x2400, 0x2426,
- 0x2440, 0x244a,
- 0x2460, 0x24ea,
- 0x2500, 0x2595,
- 0x25a0, 0x25f7,
- 0x2600, 0x2613,
- 0x2619, 0x2671,
- 0x2701, 0x2704,
- 0x2706, 0x2709,
- 0x270c, 0x2727,
- 0x2729, 0x274b,
- 0x274d, 0x274d,
- 0x274f, 0x2752,
- 0x2756, 0x2756,
- 0x2758, 0x275e,
- 0x2761, 0x2767,
- 0x2776, 0x2794,
- 0x2798, 0x27af,
- 0x27b1, 0x27be,
- 0x2800, 0x28ff,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x303a,
- 0x303e, 0x303f,
- 0x3041, 0x3094,
- 0x3099, 0x309e,
- 0x30a1, 0x30fe,
- 0x3105, 0x312c,
- 0x3131, 0x318e,
- 0x3190, 0x31b7,
- 0x3200, 0x321c,
- 0x3220, 0x3243,
- 0x3260, 0x327b,
- 0x327f, 0x32b0,
- 0x32c0, 0x32cb,
- 0x32d0, 0x32fe,
- 0x3300, 0x3376,
- 0x337b, 0x33dd,
- 0x33e0, 0x33fe,
- 0x3400, 0x4db5,
- 0x4e00, 0x9fa5,
- 0xa000, 0xa48c,
- 0xa490, 0xa4a1,
- 0xa4a4, 0xa4b3,
- 0xa4b5, 0xa4c0,
- 0xa4c2, 0xa4c4,
- 0xa4c6, 0xa4c6,
- 0xac00, 0xd7a3,
- 0xd800, 0xfa2d,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1d, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbb1,
- 0xfbd3, 0xfd3f,
- 0xfd50, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdf0, 0xfdfb,
- 0xfe20, 0xfe23,
- 0xfe30, 0xfe44,
- 0xfe49, 0xfe52,
- 0xfe54, 0xfe66,
- 0xfe68, 0xfe6b,
- 0xfe70, 0xfe72,
- 0xfe74, 0xfe74,
- 0xfe76, 0xfefc,
- 0xfeff, 0xfeff,
- 0xff01, 0xff5e,
- 0xff61, 0xffbe,
- 0xffc2, 0xffc7,
- 0xffca, 0xffcf,
- 0xffd2, 0xffd7,
- 0xffda, 0xffdc,
- 0xffe0, 0xffe6,
- 0xffe8, 0xffee,
- 0xfff9, 0xffff,
- 0x1fffe, 0x1ffff,
- 0x2fffe, 0x2ffff,
- 0x3fffe, 0x3ffff,
- 0x4fffe, 0x4ffff,
- 0x5fffe, 0x5ffff,
- 0x6fffe, 0x6ffff,
- 0x7fffe, 0x7ffff,
- 0x8fffe, 0x8ffff,
- 0x9fffe, 0x9ffff,
- 0xafffe, 0xaffff,
- 0xbfffe, 0xbffff,
- 0xcfffe, 0xcffff,
- 0xdfffe, 0xdffff,
- 0xefffe, 0x10ffff,
-}; /* CR_Age_3_0 */
-
-/* 'Age_3_1': Derived Age 3.1 */
-static const OnigCodePoint CR_Age_3_1[] = {
- 402,
- 0x0000, 0x021f,
- 0x0222, 0x0233,
- 0x0250, 0x02ad,
- 0x02b0, 0x02ee,
- 0x0300, 0x034e,
- 0x0360, 0x0362,
- 0x0374, 0x0375,
- 0x037a, 0x037a,
- 0x037e, 0x037e,
- 0x0384, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03ce,
- 0x03d0, 0x03d7,
- 0x03da, 0x03f5,
- 0x0400, 0x0486,
- 0x0488, 0x0489,
- 0x048c, 0x04c4,
- 0x04c7, 0x04c8,
- 0x04cb, 0x04cc,
- 0x04d0, 0x04f5,
- 0x04f8, 0x04f9,
- 0x0531, 0x0556,
- 0x0559, 0x055f,
- 0x0561, 0x0587,
- 0x0589, 0x058a,
- 0x0591, 0x05a1,
- 0x05a3, 0x05b9,
- 0x05bb, 0x05c4,
- 0x05d0, 0x05ea,
- 0x05f0, 0x05f4,
- 0x060c, 0x060c,
- 0x061b, 0x061b,
- 0x061f, 0x061f,
- 0x0621, 0x063a,
- 0x0640, 0x0655,
- 0x0660, 0x066d,
- 0x0670, 0x06ed,
- 0x06f0, 0x06fe,
- 0x0700, 0x070d,
- 0x070f, 0x072c,
- 0x0730, 0x074a,
- 0x0780, 0x07b0,
- 0x0901, 0x0903,
- 0x0905, 0x0939,
- 0x093c, 0x094d,
- 0x0950, 0x0954,
- 0x0958, 0x0970,
- 0x0981, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09bc,
- 0x09be, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09cd,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fa,
- 0x0a02, 0x0a02,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a74,
- 0x0a81, 0x0a83,
- 0x0a85, 0x0a8b,
- 0x0a8d, 0x0a8d,
- 0x0a8f, 0x0a91,
- 0x0a93, 0x0aa8,
- 0x0aaa, 0x0ab0,
- 0x0ab2, 0x0ab3,
- 0x0ab5, 0x0ab9,
- 0x0abc, 0x0ac5,
- 0x0ac7, 0x0ac9,
- 0x0acb, 0x0acd,
- 0x0ad0, 0x0ad0,
- 0x0ae0, 0x0ae0,
- 0x0ae6, 0x0aef,
- 0x0b01, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b36, 0x0b39,
- 0x0b3c, 0x0b43,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4d,
- 0x0b56, 0x0b57,
- 0x0b5c, 0x0b5d,
- 0x0b5f, 0x0b61,
- 0x0b66, 0x0b70,
- 0x0b82, 0x0b83,
- 0x0b85, 0x0b8a,
- 0x0b8e, 0x0b90,
- 0x0b92, 0x0b95,
- 0x0b99, 0x0b9a,
- 0x0b9c, 0x0b9c,
- 0x0b9e, 0x0b9f,
- 0x0ba3, 0x0ba4,
- 0x0ba8, 0x0baa,
- 0x0bae, 0x0bb5,
- 0x0bb7, 0x0bb9,
- 0x0bbe, 0x0bc2,
- 0x0bc6, 0x0bc8,
- 0x0bca, 0x0bcd,
- 0x0bd7, 0x0bd7,
- 0x0be7, 0x0bf2,
- 0x0c01, 0x0c03,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c33,
- 0x0c35, 0x0c39,
- 0x0c3e, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c60, 0x0c61,
- 0x0c66, 0x0c6f,
- 0x0c82, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbe, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce1,
- 0x0ce6, 0x0cef,
- 0x0d02, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d28,
- 0x0d2a, 0x0d39,
- 0x0d3e, 0x0d43,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4d,
- 0x0d57, 0x0d57,
- 0x0d60, 0x0d61,
- 0x0d66, 0x0d6f,
- 0x0d82, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0df2, 0x0df4,
- 0x0e01, 0x0e3a,
- 0x0e3f, 0x0e5b,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e87, 0x0e88,
- 0x0e8a, 0x0e8a,
- 0x0e8d, 0x0e8d,
- 0x0e94, 0x0e97,
- 0x0e99, 0x0e9f,
- 0x0ea1, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ea7,
- 0x0eaa, 0x0eab,
- 0x0ead, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edd,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6a,
- 0x0f71, 0x0f8b,
- 0x0f90, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x0fbe, 0x0fcc,
- 0x0fcf, 0x0fcf,
- 0x1000, 0x1021,
- 0x1023, 0x1027,
- 0x1029, 0x102a,
- 0x102c, 0x1032,
- 0x1036, 0x1039,
- 0x1040, 0x1059,
- 0x10a0, 0x10c5,
- 0x10d0, 0x10f6,
- 0x10fb, 0x10fb,
- 0x1100, 0x1159,
- 0x115f, 0x11a2,
- 0x11a8, 0x11f9,
- 0x1200, 0x1206,
- 0x1208, 0x1246,
- 0x1248, 0x1248,
- 0x124a, 0x124d,
- 0x1250, 0x1256,
- 0x1258, 0x1258,
- 0x125a, 0x125d,
- 0x1260, 0x1286,
- 0x1288, 0x1288,
- 0x128a, 0x128d,
- 0x1290, 0x12ae,
- 0x12b0, 0x12b0,
- 0x12b2, 0x12b5,
- 0x12b8, 0x12be,
- 0x12c0, 0x12c0,
- 0x12c2, 0x12c5,
- 0x12c8, 0x12ce,
- 0x12d0, 0x12d6,
- 0x12d8, 0x12ee,
- 0x12f0, 0x130e,
- 0x1310, 0x1310,
- 0x1312, 0x1315,
- 0x1318, 0x131e,
- 0x1320, 0x1346,
- 0x1348, 0x135a,
- 0x1361, 0x137c,
- 0x13a0, 0x13f4,
- 0x1401, 0x1676,
- 0x1680, 0x169c,
- 0x16a0, 0x16f0,
- 0x1780, 0x17dc,
- 0x17e0, 0x17e9,
- 0x1800, 0x180e,
- 0x1810, 0x1819,
- 0x1820, 0x1877,
- 0x1880, 0x18a9,
- 0x1e00, 0x1e9b,
- 0x1ea0, 0x1ef9,
- 0x1f00, 0x1f15,
- 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, 0x2046,
- 0x2048, 0x204d,
- 0x206a, 0x2070,
- 0x2074, 0x208e,
- 0x20a0, 0x20af,
- 0x20d0, 0x20e3,
- 0x2100, 0x213a,
- 0x2153, 0x2183,
- 0x2190, 0x21f3,
- 0x2200, 0x22f1,
- 0x2300, 0x237b,
- 0x237d, 0x239a,
- 0x2400, 0x2426,
- 0x2440, 0x244a,
- 0x2460, 0x24ea,
- 0x2500, 0x2595,
- 0x25a0, 0x25f7,
- 0x2600, 0x2613,
- 0x2619, 0x2671,
- 0x2701, 0x2704,
- 0x2706, 0x2709,
- 0x270c, 0x2727,
- 0x2729, 0x274b,
- 0x274d, 0x274d,
- 0x274f, 0x2752,
- 0x2756, 0x2756,
- 0x2758, 0x275e,
- 0x2761, 0x2767,
- 0x2776, 0x2794,
- 0x2798, 0x27af,
- 0x27b1, 0x27be,
- 0x2800, 0x28ff,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x303a,
- 0x303e, 0x303f,
- 0x3041, 0x3094,
- 0x3099, 0x309e,
- 0x30a1, 0x30fe,
- 0x3105, 0x312c,
- 0x3131, 0x318e,
- 0x3190, 0x31b7,
- 0x3200, 0x321c,
- 0x3220, 0x3243,
- 0x3260, 0x327b,
- 0x327f, 0x32b0,
- 0x32c0, 0x32cb,
- 0x32d0, 0x32fe,
- 0x3300, 0x3376,
- 0x337b, 0x33dd,
- 0x33e0, 0x33fe,
- 0x3400, 0x4db5,
- 0x4e00, 0x9fa5,
- 0xa000, 0xa48c,
- 0xa490, 0xa4a1,
- 0xa4a4, 0xa4b3,
- 0xa4b5, 0xa4c0,
- 0xa4c2, 0xa4c4,
- 0xa4c6, 0xa4c6,
- 0xac00, 0xd7a3,
- 0xd800, 0xfa2d,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1d, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbb1,
- 0xfbd3, 0xfd3f,
- 0xfd50, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdd0, 0xfdfb,
- 0xfe20, 0xfe23,
- 0xfe30, 0xfe44,
- 0xfe49, 0xfe52,
- 0xfe54, 0xfe66,
- 0xfe68, 0xfe6b,
- 0xfe70, 0xfe72,
- 0xfe74, 0xfe74,
- 0xfe76, 0xfefc,
- 0xfeff, 0xfeff,
- 0xff01, 0xff5e,
- 0xff61, 0xffbe,
- 0xffc2, 0xffc7,
- 0xffca, 0xffcf,
- 0xffd2, 0xffd7,
- 0xffda, 0xffdc,
- 0xffe0, 0xffe6,
- 0xffe8, 0xffee,
- 0xfff9, 0xffff,
- 0x10300, 0x1031e,
- 0x10320, 0x10323,
- 0x10330, 0x1034a,
- 0x10400, 0x10425,
- 0x10428, 0x1044d,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d12a, 0x1d1dd,
- 0x1d400, 0x1d454,
- 0x1d456, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 0x1d4a2, 0x1d4a2,
- 0x1d4a5, 0x1d4a6,
- 0x1d4a9, 0x1d4ac,
- 0x1d4ae, 0x1d4b9,
- 0x1d4bb, 0x1d4bb,
- 0x1d4bd, 0x1d4c0,
- 0x1d4c2, 0x1d4c3,
- 0x1d4c5, 0x1d505,
- 0x1d507, 0x1d50a,
- 0x1d50d, 0x1d514,
- 0x1d516, 0x1d51c,
- 0x1d51e, 0x1d539,
- 0x1d53b, 0x1d53e,
- 0x1d540, 0x1d544,
- 0x1d546, 0x1d546,
- 0x1d54a, 0x1d550,
- 0x1d552, 0x1d6a3,
- 0x1d6a8, 0x1d7c9,
- 0x1d7ce, 0x1d7ff,
- 0x1fffe, 0x2a6d6,
- 0x2f800, 0x2fa1d,
- 0x2fffe, 0x2ffff,
- 0x3fffe, 0x3ffff,
- 0x4fffe, 0x4ffff,
- 0x5fffe, 0x5ffff,
- 0x6fffe, 0x6ffff,
- 0x7fffe, 0x7ffff,
- 0x8fffe, 0x8ffff,
- 0x9fffe, 0x9ffff,
- 0xafffe, 0xaffff,
- 0xbfffe, 0xbffff,
- 0xcfffe, 0xcffff,
- 0xdfffe, 0xdffff,
- 0xe0001, 0xe0001,
- 0xe0020, 0xe007f,
- 0xefffe, 0x10ffff,
-}; /* CR_Age_3_1 */
-
-/* 'Age_3_2': Derived Age 3.2 */
-static const OnigCodePoint CR_Age_3_2[] = {
- 397,
- 0x0000, 0x0220,
- 0x0222, 0x0233,
- 0x0250, 0x02ad,
- 0x02b0, 0x02ee,
- 0x0300, 0x034f,
- 0x0360, 0x036f,
- 0x0374, 0x0375,
- 0x037a, 0x037a,
- 0x037e, 0x037e,
- 0x0384, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03ce,
- 0x03d0, 0x03f6,
- 0x0400, 0x0486,
- 0x0488, 0x04ce,
- 0x04d0, 0x04f5,
- 0x04f8, 0x04f9,
- 0x0500, 0x050f,
- 0x0531, 0x0556,
- 0x0559, 0x055f,
- 0x0561, 0x0587,
- 0x0589, 0x058a,
- 0x0591, 0x05a1,
- 0x05a3, 0x05b9,
- 0x05bb, 0x05c4,
- 0x05d0, 0x05ea,
- 0x05f0, 0x05f4,
- 0x060c, 0x060c,
- 0x061b, 0x061b,
- 0x061f, 0x061f,
- 0x0621, 0x063a,
- 0x0640, 0x0655,
- 0x0660, 0x06ed,
- 0x06f0, 0x06fe,
- 0x0700, 0x070d,
- 0x070f, 0x072c,
- 0x0730, 0x074a,
- 0x0780, 0x07b1,
- 0x0901, 0x0903,
- 0x0905, 0x0939,
- 0x093c, 0x094d,
- 0x0950, 0x0954,
- 0x0958, 0x0970,
- 0x0981, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09bc,
- 0x09be, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09cd,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fa,
- 0x0a02, 0x0a02,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a74,
- 0x0a81, 0x0a83,
- 0x0a85, 0x0a8b,
- 0x0a8d, 0x0a8d,
- 0x0a8f, 0x0a91,
- 0x0a93, 0x0aa8,
- 0x0aaa, 0x0ab0,
- 0x0ab2, 0x0ab3,
- 0x0ab5, 0x0ab9,
- 0x0abc, 0x0ac5,
- 0x0ac7, 0x0ac9,
- 0x0acb, 0x0acd,
- 0x0ad0, 0x0ad0,
- 0x0ae0, 0x0ae0,
- 0x0ae6, 0x0aef,
- 0x0b01, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b36, 0x0b39,
- 0x0b3c, 0x0b43,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4d,
- 0x0b56, 0x0b57,
- 0x0b5c, 0x0b5d,
- 0x0b5f, 0x0b61,
- 0x0b66, 0x0b70,
- 0x0b82, 0x0b83,
- 0x0b85, 0x0b8a,
- 0x0b8e, 0x0b90,
- 0x0b92, 0x0b95,
- 0x0b99, 0x0b9a,
- 0x0b9c, 0x0b9c,
- 0x0b9e, 0x0b9f,
- 0x0ba3, 0x0ba4,
- 0x0ba8, 0x0baa,
- 0x0bae, 0x0bb5,
- 0x0bb7, 0x0bb9,
- 0x0bbe, 0x0bc2,
- 0x0bc6, 0x0bc8,
- 0x0bca, 0x0bcd,
- 0x0bd7, 0x0bd7,
- 0x0be7, 0x0bf2,
- 0x0c01, 0x0c03,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c33,
- 0x0c35, 0x0c39,
- 0x0c3e, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c60, 0x0c61,
- 0x0c66, 0x0c6f,
- 0x0c82, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbe, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce1,
- 0x0ce6, 0x0cef,
- 0x0d02, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d28,
- 0x0d2a, 0x0d39,
- 0x0d3e, 0x0d43,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4d,
- 0x0d57, 0x0d57,
- 0x0d60, 0x0d61,
- 0x0d66, 0x0d6f,
- 0x0d82, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0df2, 0x0df4,
- 0x0e01, 0x0e3a,
- 0x0e3f, 0x0e5b,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e87, 0x0e88,
- 0x0e8a, 0x0e8a,
- 0x0e8d, 0x0e8d,
- 0x0e94, 0x0e97,
- 0x0e99, 0x0e9f,
- 0x0ea1, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ea7,
- 0x0eaa, 0x0eab,
- 0x0ead, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edd,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6a,
- 0x0f71, 0x0f8b,
- 0x0f90, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x0fbe, 0x0fcc,
- 0x0fcf, 0x0fcf,
- 0x1000, 0x1021,
- 0x1023, 0x1027,
- 0x1029, 0x102a,
- 0x102c, 0x1032,
- 0x1036, 0x1039,
- 0x1040, 0x1059,
- 0x10a0, 0x10c5,
- 0x10d0, 0x10f8,
- 0x10fb, 0x10fb,
- 0x1100, 0x1159,
- 0x115f, 0x11a2,
- 0x11a8, 0x11f9,
- 0x1200, 0x1206,
- 0x1208, 0x1246,
- 0x1248, 0x1248,
- 0x124a, 0x124d,
- 0x1250, 0x1256,
- 0x1258, 0x1258,
- 0x125a, 0x125d,
- 0x1260, 0x1286,
- 0x1288, 0x1288,
- 0x128a, 0x128d,
- 0x1290, 0x12ae,
- 0x12b0, 0x12b0,
- 0x12b2, 0x12b5,
- 0x12b8, 0x12be,
- 0x12c0, 0x12c0,
- 0x12c2, 0x12c5,
- 0x12c8, 0x12ce,
- 0x12d0, 0x12d6,
- 0x12d8, 0x12ee,
- 0x12f0, 0x130e,
- 0x1310, 0x1310,
- 0x1312, 0x1315,
- 0x1318, 0x131e,
- 0x1320, 0x1346,
- 0x1348, 0x135a,
- 0x1361, 0x137c,
- 0x13a0, 0x13f4,
- 0x1401, 0x1676,
- 0x1680, 0x169c,
- 0x16a0, 0x16f0,
- 0x1700, 0x170c,
- 0x170e, 0x1714,
- 0x1720, 0x1736,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17dc,
- 0x17e0, 0x17e9,
- 0x1800, 0x180e,
- 0x1810, 0x1819,
- 0x1820, 0x1877,
- 0x1880, 0x18a9,
- 0x1e00, 0x1e9b,
- 0x1ea0, 0x1ef9,
- 0x1f00, 0x1f15,
- 0x1f18, 0x1f1d,
- 0x1f20, 0x1f45,
- 0x1f48, 0x1f4d,
- 0x1f50, 0x1f57,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f7d,
- 0x1f80, 0x1fb4,
- 0x1fb6, 0x1fc4,
- 0x1fc6, 0x1fd3,
- 0x1fd6, 0x1fdb,
- 0x1fdd, 0x1fef,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ffe,
- 0x2000, 0x2052,
- 0x2057, 0x2057,
- 0x205f, 0x2063,
- 0x206a, 0x2071,
- 0x2074, 0x208e,
- 0x20a0, 0x20b1,
- 0x20d0, 0x20ea,
- 0x2100, 0x213a,
- 0x213d, 0x214b,
- 0x2153, 0x2183,
- 0x2190, 0x23ce,
- 0x2400, 0x2426,
- 0x2440, 0x244a,
- 0x2460, 0x24fe,
- 0x2500, 0x2613,
- 0x2616, 0x2617,
- 0x2619, 0x267d,
- 0x2680, 0x2689,
- 0x2701, 0x2704,
- 0x2706, 0x2709,
- 0x270c, 0x2727,
- 0x2729, 0x274b,
- 0x274d, 0x274d,
- 0x274f, 0x2752,
- 0x2756, 0x2756,
- 0x2758, 0x275e,
- 0x2761, 0x2794,
- 0x2798, 0x27af,
- 0x27b1, 0x27be,
- 0x27d0, 0x27eb,
- 0x27f0, 0x2aff,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x303f,
- 0x3041, 0x3096,
- 0x3099, 0x30ff,
- 0x3105, 0x312c,
- 0x3131, 0x318e,
- 0x3190, 0x31b7,
- 0x31f0, 0x321c,
- 0x3220, 0x3243,
- 0x3251, 0x327b,
- 0x327f, 0x32cb,
- 0x32d0, 0x32fe,
- 0x3300, 0x3376,
- 0x337b, 0x33dd,
- 0x33e0, 0x33fe,
- 0x3400, 0x4db5,
- 0x4e00, 0x9fa5,
- 0xa000, 0xa48c,
- 0xa490, 0xa4c6,
- 0xac00, 0xd7a3,
- 0xd800, 0xfa2d,
- 0xfa30, 0xfa6a,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1d, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbb1,
- 0xfbd3, 0xfd3f,
- 0xfd50, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdd0, 0xfdfc,
- 0xfe00, 0xfe0f,
- 0xfe20, 0xfe23,
- 0xfe30, 0xfe46,
- 0xfe49, 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, 0xffff,
- 0x10300, 0x1031e,
- 0x10320, 0x10323,
- 0x10330, 0x1034a,
- 0x10400, 0x10425,
- 0x10428, 0x1044d,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d12a, 0x1d1dd,
- 0x1d400, 0x1d454,
- 0x1d456, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 0x1d4a2, 0x1d4a2,
- 0x1d4a5, 0x1d4a6,
- 0x1d4a9, 0x1d4ac,
- 0x1d4ae, 0x1d4b9,
- 0x1d4bb, 0x1d4bb,
- 0x1d4bd, 0x1d4c0,
- 0x1d4c2, 0x1d4c3,
- 0x1d4c5, 0x1d505,
- 0x1d507, 0x1d50a,
- 0x1d50d, 0x1d514,
- 0x1d516, 0x1d51c,
- 0x1d51e, 0x1d539,
- 0x1d53b, 0x1d53e,
- 0x1d540, 0x1d544,
- 0x1d546, 0x1d546,
- 0x1d54a, 0x1d550,
- 0x1d552, 0x1d6a3,
- 0x1d6a8, 0x1d7c9,
- 0x1d7ce, 0x1d7ff,
- 0x1fffe, 0x2a6d6,
- 0x2f800, 0x2fa1d,
- 0x2fffe, 0x2ffff,
- 0x3fffe, 0x3ffff,
- 0x4fffe, 0x4ffff,
- 0x5fffe, 0x5ffff,
- 0x6fffe, 0x6ffff,
- 0x7fffe, 0x7ffff,
- 0x8fffe, 0x8ffff,
- 0x9fffe, 0x9ffff,
- 0xafffe, 0xaffff,
- 0xbfffe, 0xbffff,
- 0xcfffe, 0xcffff,
- 0xdfffe, 0xdffff,
- 0xe0001, 0xe0001,
- 0xe0020, 0xe007f,
- 0xefffe, 0x10ffff,
-}; /* CR_Age_3_2 */
-
-/* 'Age_4_0': Derived Age 4.0 */
-static const OnigCodePoint CR_Age_4_0[] = {
- 412,
- 0x0000, 0x0236,
- 0x0250, 0x0357,
- 0x035d, 0x036f,
- 0x0374, 0x0375,
- 0x037a, 0x037a,
- 0x037e, 0x037e,
- 0x0384, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03ce,
- 0x03d0, 0x03fb,
- 0x0400, 0x0486,
- 0x0488, 0x04ce,
- 0x04d0, 0x04f5,
- 0x04f8, 0x04f9,
- 0x0500, 0x050f,
- 0x0531, 0x0556,
- 0x0559, 0x055f,
- 0x0561, 0x0587,
- 0x0589, 0x058a,
- 0x0591, 0x05a1,
- 0x05a3, 0x05b9,
- 0x05bb, 0x05c4,
- 0x05d0, 0x05ea,
- 0x05f0, 0x05f4,
- 0x0600, 0x0603,
- 0x060c, 0x0615,
- 0x061b, 0x061b,
- 0x061f, 0x061f,
- 0x0621, 0x063a,
- 0x0640, 0x0658,
- 0x0660, 0x070d,
- 0x070f, 0x074a,
- 0x074d, 0x074f,
- 0x0780, 0x07b1,
- 0x0901, 0x0939,
- 0x093c, 0x094d,
- 0x0950, 0x0954,
- 0x0958, 0x0970,
- 0x0981, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09cd,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fa,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a74,
- 0x0a81, 0x0a83,
- 0x0a85, 0x0a8d,
- 0x0a8f, 0x0a91,
- 0x0a93, 0x0aa8,
- 0x0aaa, 0x0ab0,
- 0x0ab2, 0x0ab3,
- 0x0ab5, 0x0ab9,
- 0x0abc, 0x0ac5,
- 0x0ac7, 0x0ac9,
- 0x0acb, 0x0acd,
- 0x0ad0, 0x0ad0,
- 0x0ae0, 0x0ae3,
- 0x0ae6, 0x0aef,
- 0x0af1, 0x0af1,
- 0x0b01, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b35, 0x0b39,
- 0x0b3c, 0x0b43,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4d,
- 0x0b56, 0x0b57,
- 0x0b5c, 0x0b5d,
- 0x0b5f, 0x0b61,
- 0x0b66, 0x0b71,
- 0x0b82, 0x0b83,
- 0x0b85, 0x0b8a,
- 0x0b8e, 0x0b90,
- 0x0b92, 0x0b95,
- 0x0b99, 0x0b9a,
- 0x0b9c, 0x0b9c,
- 0x0b9e, 0x0b9f,
- 0x0ba3, 0x0ba4,
- 0x0ba8, 0x0baa,
- 0x0bae, 0x0bb5,
- 0x0bb7, 0x0bb9,
- 0x0bbe, 0x0bc2,
- 0x0bc6, 0x0bc8,
- 0x0bca, 0x0bcd,
- 0x0bd7, 0x0bd7,
- 0x0be7, 0x0bfa,
- 0x0c01, 0x0c03,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c33,
- 0x0c35, 0x0c39,
- 0x0c3e, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c60, 0x0c61,
- 0x0c66, 0x0c6f,
- 0x0c82, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce1,
- 0x0ce6, 0x0cef,
- 0x0d02, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d28,
- 0x0d2a, 0x0d39,
- 0x0d3e, 0x0d43,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4d,
- 0x0d57, 0x0d57,
- 0x0d60, 0x0d61,
- 0x0d66, 0x0d6f,
- 0x0d82, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0df2, 0x0df4,
- 0x0e01, 0x0e3a,
- 0x0e3f, 0x0e5b,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e87, 0x0e88,
- 0x0e8a, 0x0e8a,
- 0x0e8d, 0x0e8d,
- 0x0e94, 0x0e97,
- 0x0e99, 0x0e9f,
- 0x0ea1, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ea7,
- 0x0eaa, 0x0eab,
- 0x0ead, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edd,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6a,
- 0x0f71, 0x0f8b,
- 0x0f90, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x0fbe, 0x0fcc,
- 0x0fcf, 0x0fcf,
- 0x1000, 0x1021,
- 0x1023, 0x1027,
- 0x1029, 0x102a,
- 0x102c, 0x1032,
- 0x1036, 0x1039,
- 0x1040, 0x1059,
- 0x10a0, 0x10c5,
- 0x10d0, 0x10f8,
- 0x10fb, 0x10fb,
- 0x1100, 0x1159,
- 0x115f, 0x11a2,
- 0x11a8, 0x11f9,
- 0x1200, 0x1206,
- 0x1208, 0x1246,
- 0x1248, 0x1248,
- 0x124a, 0x124d,
- 0x1250, 0x1256,
- 0x1258, 0x1258,
- 0x125a, 0x125d,
- 0x1260, 0x1286,
- 0x1288, 0x1288,
- 0x128a, 0x128d,
- 0x1290, 0x12ae,
- 0x12b0, 0x12b0,
- 0x12b2, 0x12b5,
- 0x12b8, 0x12be,
- 0x12c0, 0x12c0,
- 0x12c2, 0x12c5,
- 0x12c8, 0x12ce,
- 0x12d0, 0x12d6,
- 0x12d8, 0x12ee,
- 0x12f0, 0x130e,
- 0x1310, 0x1310,
- 0x1312, 0x1315,
- 0x1318, 0x131e,
- 0x1320, 0x1346,
- 0x1348, 0x135a,
- 0x1361, 0x137c,
- 0x13a0, 0x13f4,
- 0x1401, 0x1676,
- 0x1680, 0x169c,
- 0x16a0, 0x16f0,
- 0x1700, 0x170c,
- 0x170e, 0x1714,
- 0x1720, 0x1736,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17dd,
- 0x17e0, 0x17e9,
- 0x17f0, 0x17f9,
- 0x1800, 0x180e,
- 0x1810, 0x1819,
- 0x1820, 0x1877,
- 0x1880, 0x18a9,
- 0x1900, 0x191c,
- 0x1920, 0x192b,
- 0x1930, 0x193b,
- 0x1940, 0x1940,
- 0x1944, 0x196d,
- 0x1970, 0x1974,
- 0x19e0, 0x19ff,
- 0x1d00, 0x1d6b,
- 0x1e00, 0x1e9b,
- 0x1ea0, 0x1ef9,
- 0x1f00, 0x1f15,
- 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, 0x2054,
- 0x2057, 0x2057,
- 0x205f, 0x2063,
- 0x206a, 0x2071,
- 0x2074, 0x208e,
- 0x20a0, 0x20b1,
- 0x20d0, 0x20ea,
- 0x2100, 0x213b,
- 0x213d, 0x214b,
- 0x2153, 0x2183,
- 0x2190, 0x23d0,
- 0x2400, 0x2426,
- 0x2440, 0x244a,
- 0x2460, 0x2617,
- 0x2619, 0x267d,
- 0x2680, 0x2691,
- 0x26a0, 0x26a1,
- 0x2701, 0x2704,
- 0x2706, 0x2709,
- 0x270c, 0x2727,
- 0x2729, 0x274b,
- 0x274d, 0x274d,
- 0x274f, 0x2752,
- 0x2756, 0x2756,
- 0x2758, 0x275e,
- 0x2761, 0x2794,
- 0x2798, 0x27af,
- 0x27b1, 0x27be,
- 0x27d0, 0x27eb,
- 0x27f0, 0x2b0d,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x303f,
- 0x3041, 0x3096,
- 0x3099, 0x30ff,
- 0x3105, 0x312c,
- 0x3131, 0x318e,
- 0x3190, 0x31b7,
- 0x31f0, 0x321e,
- 0x3220, 0x3243,
- 0x3250, 0x327d,
- 0x327f, 0x32fe,
- 0x3300, 0x4db5,
- 0x4dc0, 0x9fa5,
- 0xa000, 0xa48c,
- 0xa490, 0xa4c6,
- 0xac00, 0xd7a3,
- 0xd800, 0xfa2d,
- 0xfa30, 0xfa6a,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1d, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbb1,
- 0xfbd3, 0xfd3f,
- 0xfd50, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdd0, 0xfdfd,
- 0xfe00, 0xfe0f,
- 0xfe20, 0xfe23,
- 0xfe30, 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, 0x1013f,
- 0x10300, 0x1031e,
- 0x10320, 0x10323,
- 0x10330, 0x1034a,
- 0x10380, 0x1039d,
- 0x1039f, 0x1039f,
- 0x10400, 0x1049d,
- 0x104a0, 0x104a9,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x1083f,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d12a, 0x1d1dd,
- 0x1d300, 0x1d356,
- 0x1d400, 0x1d454,
- 0x1d456, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 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, 0x1d6a3,
- 0x1d6a8, 0x1d7c9,
- 0x1d7ce, 0x1d7ff,
- 0x1fffe, 0x2a6d6,
- 0x2f800, 0x2fa1d,
- 0x2fffe, 0x2ffff,
- 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_4_0 */
-
-/* 'Age_4_1': Derived Age 4.1 */
-static const OnigCodePoint CR_Age_4_1[] = {
- 430,
- 0x0000, 0x0241,
- 0x0250, 0x036f,
- 0x0374, 0x0375,
- 0x037a, 0x037a,
- 0x037e, 0x037e,
- 0x0384, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03ce,
- 0x03d0, 0x0486,
- 0x0488, 0x04ce,
- 0x04d0, 0x04f9,
- 0x0500, 0x050f,
- 0x0531, 0x0556,
- 0x0559, 0x055f,
- 0x0561, 0x0587,
- 0x0589, 0x058a,
- 0x0591, 0x05b9,
- 0x05bb, 0x05c7,
- 0x05d0, 0x05ea,
- 0x05f0, 0x05f4,
- 0x0600, 0x0603,
- 0x060b, 0x0615,
- 0x061b, 0x061b,
- 0x061e, 0x061f,
- 0x0621, 0x063a,
- 0x0640, 0x065e,
- 0x0660, 0x070d,
- 0x070f, 0x074a,
- 0x074d, 0x076d,
- 0x0780, 0x07b1,
- 0x0901, 0x0939,
- 0x093c, 0x094d,
- 0x0950, 0x0954,
- 0x0958, 0x0970,
- 0x097d, 0x097d,
- 0x0981, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fa,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a74,
- 0x0a81, 0x0a83,
- 0x0a85, 0x0a8d,
- 0x0a8f, 0x0a91,
- 0x0a93, 0x0aa8,
- 0x0aaa, 0x0ab0,
- 0x0ab2, 0x0ab3,
- 0x0ab5, 0x0ab9,
- 0x0abc, 0x0ac5,
- 0x0ac7, 0x0ac9,
- 0x0acb, 0x0acd,
- 0x0ad0, 0x0ad0,
- 0x0ae0, 0x0ae3,
- 0x0ae6, 0x0aef,
- 0x0af1, 0x0af1,
- 0x0b01, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b35, 0x0b39,
- 0x0b3c, 0x0b43,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4d,
- 0x0b56, 0x0b57,
- 0x0b5c, 0x0b5d,
- 0x0b5f, 0x0b61,
- 0x0b66, 0x0b71,
- 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,
- 0x0bd7, 0x0bd7,
- 0x0be6, 0x0bfa,
- 0x0c01, 0x0c03,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c33,
- 0x0c35, 0x0c39,
- 0x0c3e, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c60, 0x0c61,
- 0x0c66, 0x0c6f,
- 0x0c82, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce1,
- 0x0ce6, 0x0cef,
- 0x0d02, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d28,
- 0x0d2a, 0x0d39,
- 0x0d3e, 0x0d43,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4d,
- 0x0d57, 0x0d57,
- 0x0d60, 0x0d61,
- 0x0d66, 0x0d6f,
- 0x0d82, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0df2, 0x0df4,
- 0x0e01, 0x0e3a,
- 0x0e3f, 0x0e5b,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e87, 0x0e88,
- 0x0e8a, 0x0e8a,
- 0x0e8d, 0x0e8d,
- 0x0e94, 0x0e97,
- 0x0e99, 0x0e9f,
- 0x0ea1, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ea7,
- 0x0eaa, 0x0eab,
- 0x0ead, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edd,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6a,
- 0x0f71, 0x0f8b,
- 0x0f90, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x0fbe, 0x0fcc,
- 0x0fcf, 0x0fd1,
- 0x1000, 0x1021,
- 0x1023, 0x1027,
- 0x1029, 0x102a,
- 0x102c, 0x1032,
- 0x1036, 0x1039,
- 0x1040, 0x1059,
- 0x10a0, 0x10c5,
- 0x10d0, 0x10fc,
- 0x1100, 0x1159,
- 0x115f, 0x11a2,
- 0x11a8, 0x11f9,
- 0x1200, 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,
- 0x135f, 0x137c,
- 0x1380, 0x1399,
- 0x13a0, 0x13f4,
- 0x1401, 0x1676,
- 0x1680, 0x169c,
- 0x16a0, 0x16f0,
- 0x1700, 0x170c,
- 0x170e, 0x1714,
- 0x1720, 0x1736,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17dd,
- 0x17e0, 0x17e9,
- 0x17f0, 0x17f9,
- 0x1800, 0x180e,
- 0x1810, 0x1819,
- 0x1820, 0x1877,
- 0x1880, 0x18a9,
- 0x1900, 0x191c,
- 0x1920, 0x192b,
- 0x1930, 0x193b,
- 0x1940, 0x1940,
- 0x1944, 0x196d,
- 0x1970, 0x1974,
- 0x1980, 0x19a9,
- 0x19b0, 0x19c9,
- 0x19d0, 0x19d9,
- 0x19de, 0x1a1b,
- 0x1a1e, 0x1a1f,
- 0x1d00, 0x1dc3,
- 0x1e00, 0x1e9b,
- 0x1ea0, 0x1ef9,
- 0x1f00, 0x1f15,
- 0x1f18, 0x1f1d,
- 0x1f20, 0x1f45,
- 0x1f48, 0x1f4d,
- 0x1f50, 0x1f57,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f7d,
- 0x1f80, 0x1fb4,
- 0x1fb6, 0x1fc4,
- 0x1fc6, 0x1fd3,
- 0x1fd6, 0x1fdb,
- 0x1fdd, 0x1fef,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ffe,
- 0x2000, 0x2063,
- 0x206a, 0x2071,
- 0x2074, 0x208e,
- 0x2090, 0x2094,
- 0x20a0, 0x20b5,
- 0x20d0, 0x20eb,
- 0x2100, 0x214c,
- 0x2153, 0x2183,
- 0x2190, 0x23db,
- 0x2400, 0x2426,
- 0x2440, 0x244a,
- 0x2460, 0x269c,
- 0x26a0, 0x26b1,
- 0x2701, 0x2704,
- 0x2706, 0x2709,
- 0x270c, 0x2727,
- 0x2729, 0x274b,
- 0x274d, 0x274d,
- 0x274f, 0x2752,
- 0x2756, 0x2756,
- 0x2758, 0x275e,
- 0x2761, 0x2794,
- 0x2798, 0x27af,
- 0x27b1, 0x27be,
- 0x27c0, 0x27c6,
- 0x27d0, 0x27eb,
- 0x27f0, 0x2b13,
- 0x2c00, 0x2c2e,
- 0x2c30, 0x2c5e,
- 0x2c80, 0x2cea,
- 0x2cf9, 0x2d25,
- 0x2d30, 0x2d65,
- 0x2d6f, 0x2d6f,
- 0x2d80, 0x2d96,
- 0x2da0, 0x2da6,
- 0x2da8, 0x2dae,
- 0x2db0, 0x2db6,
- 0x2db8, 0x2dbe,
- 0x2dc0, 0x2dc6,
- 0x2dc8, 0x2dce,
- 0x2dd0, 0x2dd6,
- 0x2dd8, 0x2dde,
- 0x2e00, 0x2e17,
- 0x2e1c, 0x2e1d,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x303f,
- 0x3041, 0x3096,
- 0x3099, 0x30ff,
- 0x3105, 0x312c,
- 0x3131, 0x318e,
- 0x3190, 0x31b7,
- 0x31c0, 0x31cf,
- 0x31f0, 0x321e,
- 0x3220, 0x3243,
- 0x3250, 0x32fe,
- 0x3300, 0x4db5,
- 0x4dc0, 0x9fbb,
- 0xa000, 0xa48c,
- 0xa490, 0xa4c6,
- 0xa700, 0xa716,
- 0xa800, 0xa82b,
- 0xac00, 0xd7a3,
- 0xd800, 0xfa2d,
- 0xfa30, 0xfa6a,
- 0xfa70, 0xfad9,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1d, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbb1,
- 0xfbd3, 0xfd3f,
- 0xfd50, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdd0, 0xfdfd,
- 0xfe00, 0xfe19,
- 0xfe20, 0xfe23,
- 0xfe30, 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, 0x1018a,
- 0x10300, 0x1031e,
- 0x10320, 0x10323,
- 0x10330, 0x1034a,
- 0x10380, 0x1039d,
- 0x1039f, 0x103c3,
- 0x103c8, 0x103d5,
- 0x10400, 0x1049d,
- 0x104a0, 0x104a9,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x1083f,
- 0x10a00, 0x10a03,
- 0x10a05, 0x10a06,
- 0x10a0c, 0x10a13,
- 0x10a15, 0x10a17,
- 0x10a19, 0x10a33,
- 0x10a38, 0x10a3a,
- 0x10a3f, 0x10a47,
- 0x10a50, 0x10a58,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d12a, 0x1d1dd,
- 0x1d200, 0x1d245,
- 0x1d300, 0x1d356,
- 0x1d400, 0x1d454,
- 0x1d456, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 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, 0x1d7c9,
- 0x1d7ce, 0x1d7ff,
- 0x1fffe, 0x2a6d6,
- 0x2f800, 0x2fa1d,
- 0x2fffe, 0x2ffff,
- 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_4_1 */
-
-/* 'Age_5_0': Derived Age 5.0 */
-static const OnigCodePoint CR_Age_5_0[] = {
- 440,
- 0x0000, 0x036f,
- 0x0374, 0x0375,
- 0x037a, 0x037e,
- 0x0384, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x03ce,
- 0x03d0, 0x0486,
- 0x0488, 0x0513,
- 0x0531, 0x0556,
- 0x0559, 0x055f,
- 0x0561, 0x0587,
- 0x0589, 0x058a,
- 0x0591, 0x05c7,
- 0x05d0, 0x05ea,
- 0x05f0, 0x05f4,
- 0x0600, 0x0603,
- 0x060b, 0x0615,
- 0x061b, 0x061b,
- 0x061e, 0x061f,
- 0x0621, 0x063a,
- 0x0640, 0x065e,
- 0x0660, 0x070d,
- 0x070f, 0x074a,
- 0x074d, 0x076d,
- 0x0780, 0x07b1,
- 0x07c0, 0x07fa,
- 0x0901, 0x0939,
- 0x093c, 0x094d,
- 0x0950, 0x0954,
- 0x0958, 0x0970,
- 0x097b, 0x097f,
- 0x0981, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fa,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a74,
- 0x0a81, 0x0a83,
- 0x0a85, 0x0a8d,
- 0x0a8f, 0x0a91,
- 0x0a93, 0x0aa8,
- 0x0aaa, 0x0ab0,
- 0x0ab2, 0x0ab3,
- 0x0ab5, 0x0ab9,
- 0x0abc, 0x0ac5,
- 0x0ac7, 0x0ac9,
- 0x0acb, 0x0acd,
- 0x0ad0, 0x0ad0,
- 0x0ae0, 0x0ae3,
- 0x0ae6, 0x0aef,
- 0x0af1, 0x0af1,
- 0x0b01, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b35, 0x0b39,
- 0x0b3c, 0x0b43,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4d,
- 0x0b56, 0x0b57,
- 0x0b5c, 0x0b5d,
- 0x0b5f, 0x0b61,
- 0x0b66, 0x0b71,
- 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,
- 0x0bd7, 0x0bd7,
- 0x0be6, 0x0bfa,
- 0x0c01, 0x0c03,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c33,
- 0x0c35, 0x0c39,
- 0x0c3e, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c60, 0x0c61,
- 0x0c66, 0x0c6f,
- 0x0c82, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce3,
- 0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
- 0x0d02, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d28,
- 0x0d2a, 0x0d39,
- 0x0d3e, 0x0d43,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4d,
- 0x0d57, 0x0d57,
- 0x0d60, 0x0d61,
- 0x0d66, 0x0d6f,
- 0x0d82, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0df2, 0x0df4,
- 0x0e01, 0x0e3a,
- 0x0e3f, 0x0e5b,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e87, 0x0e88,
- 0x0e8a, 0x0e8a,
- 0x0e8d, 0x0e8d,
- 0x0e94, 0x0e97,
- 0x0e99, 0x0e9f,
- 0x0ea1, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ea7,
- 0x0eaa, 0x0eab,
- 0x0ead, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edd,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6a,
- 0x0f71, 0x0f8b,
- 0x0f90, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x0fbe, 0x0fcc,
- 0x0fcf, 0x0fd1,
- 0x1000, 0x1021,
- 0x1023, 0x1027,
- 0x1029, 0x102a,
- 0x102c, 0x1032,
- 0x1036, 0x1039,
- 0x1040, 0x1059,
- 0x10a0, 0x10c5,
- 0x10d0, 0x10fc,
- 0x1100, 0x1159,
- 0x115f, 0x11a2,
- 0x11a8, 0x11f9,
- 0x1200, 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,
- 0x135f, 0x137c,
- 0x1380, 0x1399,
- 0x13a0, 0x13f4,
- 0x1401, 0x1676,
- 0x1680, 0x169c,
- 0x16a0, 0x16f0,
- 0x1700, 0x170c,
- 0x170e, 0x1714,
- 0x1720, 0x1736,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17dd,
- 0x17e0, 0x17e9,
- 0x17f0, 0x17f9,
- 0x1800, 0x180e,
- 0x1810, 0x1819,
- 0x1820, 0x1877,
- 0x1880, 0x18a9,
- 0x1900, 0x191c,
- 0x1920, 0x192b,
- 0x1930, 0x193b,
- 0x1940, 0x1940,
- 0x1944, 0x196d,
- 0x1970, 0x1974,
- 0x1980, 0x19a9,
- 0x19b0, 0x19c9,
- 0x19d0, 0x19d9,
- 0x19de, 0x1a1b,
- 0x1a1e, 0x1a1f,
- 0x1b00, 0x1b4b,
- 0x1b50, 0x1b7c,
- 0x1d00, 0x1dca,
- 0x1dfe, 0x1e9b,
- 0x1ea0, 0x1ef9,
- 0x1f00, 0x1f15,
- 0x1f18, 0x1f1d,
- 0x1f20, 0x1f45,
- 0x1f48, 0x1f4d,
- 0x1f50, 0x1f57,
- 0x1f59, 0x1f59,
- 0x1f5b, 0x1f5b,
- 0x1f5d, 0x1f5d,
- 0x1f5f, 0x1f7d,
- 0x1f80, 0x1fb4,
- 0x1fb6, 0x1fc4,
- 0x1fc6, 0x1fd3,
- 0x1fd6, 0x1fdb,
- 0x1fdd, 0x1fef,
- 0x1ff2, 0x1ff4,
- 0x1ff6, 0x1ffe,
- 0x2000, 0x2063,
- 0x206a, 0x2071,
- 0x2074, 0x208e,
- 0x2090, 0x2094,
- 0x20a0, 0x20b5,
- 0x20d0, 0x20ef,
- 0x2100, 0x214e,
- 0x2153, 0x2184,
- 0x2190, 0x23e7,
- 0x2400, 0x2426,
- 0x2440, 0x244a,
- 0x2460, 0x269c,
- 0x26a0, 0x26b2,
- 0x2701, 0x2704,
- 0x2706, 0x2709,
- 0x270c, 0x2727,
- 0x2729, 0x274b,
- 0x274d, 0x274d,
- 0x274f, 0x2752,
- 0x2756, 0x2756,
- 0x2758, 0x275e,
- 0x2761, 0x2794,
- 0x2798, 0x27af,
- 0x27b1, 0x27be,
- 0x27c0, 0x27ca,
- 0x27d0, 0x27eb,
- 0x27f0, 0x2b1a,
- 0x2b20, 0x2b23,
- 0x2c00, 0x2c2e,
- 0x2c30, 0x2c5e,
- 0x2c60, 0x2c6c,
- 0x2c74, 0x2c77,
- 0x2c80, 0x2cea,
- 0x2cf9, 0x2d25,
- 0x2d30, 0x2d65,
- 0x2d6f, 0x2d6f,
- 0x2d80, 0x2d96,
- 0x2da0, 0x2da6,
- 0x2da8, 0x2dae,
- 0x2db0, 0x2db6,
- 0x2db8, 0x2dbe,
- 0x2dc0, 0x2dc6,
- 0x2dc8, 0x2dce,
- 0x2dd0, 0x2dd6,
- 0x2dd8, 0x2dde,
- 0x2e00, 0x2e17,
- 0x2e1c, 0x2e1d,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x303f,
- 0x3041, 0x3096,
- 0x3099, 0x30ff,
- 0x3105, 0x312c,
- 0x3131, 0x318e,
- 0x3190, 0x31b7,
- 0x31c0, 0x31cf,
- 0x31f0, 0x321e,
- 0x3220, 0x3243,
- 0x3250, 0x32fe,
- 0x3300, 0x4db5,
- 0x4dc0, 0x9fbb,
- 0xa000, 0xa48c,
- 0xa490, 0xa4c6,
- 0xa700, 0xa71a,
- 0xa720, 0xa721,
- 0xa800, 0xa82b,
- 0xa840, 0xa877,
- 0xac00, 0xd7a3,
- 0xd800, 0xfa2d,
- 0xfa30, 0xfa6a,
- 0xfa70, 0xfad9,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1d, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbb1,
- 0xfbd3, 0xfd3f,
- 0xfd50, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdd0, 0xfdfd,
- 0xfe00, 0xfe19,
- 0xfe20, 0xfe23,
- 0xfe30, 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, 0x1018a,
- 0x10300, 0x1031e,
- 0x10320, 0x10323,
- 0x10330, 0x1034a,
- 0x10380, 0x1039d,
- 0x1039f, 0x103c3,
- 0x103c8, 0x103d5,
- 0x10400, 0x1049d,
- 0x104a0, 0x104a9,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x1083f,
- 0x10900, 0x10919,
- 0x1091f, 0x1091f,
- 0x10a00, 0x10a03,
- 0x10a05, 0x10a06,
- 0x10a0c, 0x10a13,
- 0x10a15, 0x10a17,
- 0x10a19, 0x10a33,
- 0x10a38, 0x10a3a,
- 0x10a3f, 0x10a47,
- 0x10a50, 0x10a58,
- 0x12000, 0x1236e,
- 0x12400, 0x12462,
- 0x12470, 0x12473,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d12a, 0x1d1dd,
- 0x1d200, 0x1d245,
- 0x1d300, 0x1d356,
- 0x1d360, 0x1d371,
- 0x1d400, 0x1d454,
- 0x1d456, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 0x1d4a2, 0x1d4a2,
- 0x1d4a5, 0x1d4a6,
- 0x1d4a9, 0x1d4ac,
- 0x1d4ae, 0x1d4b9,
- 0x1d4bb, 0x1d4bb,
- 0x1d4bd, 0x1d4c3,
- 0x1d4c5, 0x1d505,
- 0x1d507, 0x1d50a,
- 0x1d50d, 0x1d514,
- 0x1d516, 0x1d51c,
- 0x1d51e, 0x1d539,
- 0x1d53b, 0x1d53e,
- 0x1d540, 0x1d544,
- 0x1d546, 0x1d546,
- 0x1d54a, 0x1d550,
- 0x1d552, 0x1d6a5,
- 0x1d6a8, 0x1d7cb,
- 0x1d7ce, 0x1d7ff,
- 0x1fffe, 0x2a6d6,
- 0x2f800, 0x2fa1d,
- 0x2fffe, 0x2ffff,
- 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_5_0 */
-
-/* 'Age_5_1': Derived Age 5.1 */
-static const OnigCodePoint CR_Age_5_1[] = {
- 455,
- 0x0000, 0x0377,
- 0x037a, 0x037e,
- 0x0384, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x0523,
- 0x0531, 0x0556,
- 0x0559, 0x055f,
- 0x0561, 0x0587,
- 0x0589, 0x058a,
- 0x0591, 0x05c7,
- 0x05d0, 0x05ea,
- 0x05f0, 0x05f4,
- 0x0600, 0x0603,
- 0x0606, 0x061b,
- 0x061e, 0x061f,
- 0x0621, 0x065e,
- 0x0660, 0x070d,
- 0x070f, 0x074a,
- 0x074d, 0x07b1,
- 0x07c0, 0x07fa,
- 0x0901, 0x0939,
- 0x093c, 0x094d,
- 0x0950, 0x0954,
- 0x0958, 0x0972,
- 0x097b, 0x097f,
- 0x0981, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fa,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a51, 0x0a51,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a75,
- 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, 0x0aef,
- 0x0af1, 0x0af1,
- 0x0b01, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b35, 0x0b39,
- 0x0b3c, 0x0b44,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4d,
- 0x0b56, 0x0b57,
- 0x0b5c, 0x0b5d,
- 0x0b5f, 0x0b63,
- 0x0b66, 0x0b71,
- 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,
- 0x0be6, 0x0bfa,
- 0x0c01, 0x0c03,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c33,
- 0x0c35, 0x0c39,
- 0x0c3d, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c58, 0x0c59,
- 0x0c60, 0x0c63,
- 0x0c66, 0x0c6f,
- 0x0c78, 0x0c7f,
- 0x0c82, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce3,
- 0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
- 0x0d02, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d28,
- 0x0d2a, 0x0d39,
- 0x0d3d, 0x0d44,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4d,
- 0x0d57, 0x0d57,
- 0x0d60, 0x0d63,
- 0x0d66, 0x0d75,
- 0x0d79, 0x0d7f,
- 0x0d82, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0df2, 0x0df4,
- 0x0e01, 0x0e3a,
- 0x0e3f, 0x0e5b,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e87, 0x0e88,
- 0x0e8a, 0x0e8a,
- 0x0e8d, 0x0e8d,
- 0x0e94, 0x0e97,
- 0x0e99, 0x0e9f,
- 0x0ea1, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ea7,
- 0x0eaa, 0x0eab,
- 0x0ead, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edd,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f71, 0x0f8b,
- 0x0f90, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x0fbe, 0x0fcc,
- 0x0fce, 0x0fd4,
- 0x1000, 0x1099,
- 0x109e, 0x10c5,
- 0x10d0, 0x10fc,
- 0x1100, 0x1159,
- 0x115f, 0x11a2,
- 0x11a8, 0x11f9,
- 0x1200, 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,
- 0x135f, 0x137c,
- 0x1380, 0x1399,
- 0x13a0, 0x13f4,
- 0x1401, 0x1676,
- 0x1680, 0x169c,
- 0x16a0, 0x16f0,
- 0x1700, 0x170c,
- 0x170e, 0x1714,
- 0x1720, 0x1736,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17dd,
- 0x17e0, 0x17e9,
- 0x17f0, 0x17f9,
- 0x1800, 0x180e,
- 0x1810, 0x1819,
- 0x1820, 0x1877,
- 0x1880, 0x18aa,
- 0x1900, 0x191c,
- 0x1920, 0x192b,
- 0x1930, 0x193b,
- 0x1940, 0x1940,
- 0x1944, 0x196d,
- 0x1970, 0x1974,
- 0x1980, 0x19a9,
- 0x19b0, 0x19c9,
- 0x19d0, 0x19d9,
- 0x19de, 0x1a1b,
- 0x1a1e, 0x1a1f,
- 0x1b00, 0x1b4b,
- 0x1b50, 0x1b7c,
- 0x1b80, 0x1baa,
- 0x1bae, 0x1bb9,
- 0x1c00, 0x1c37,
- 0x1c3b, 0x1c49,
- 0x1c4d, 0x1c7f,
- 0x1d00, 0x1de6,
- 0x1dfe, 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,
- 0x206a, 0x2071,
- 0x2074, 0x208e,
- 0x2090, 0x2094,
- 0x20a0, 0x20b5,
- 0x20d0, 0x20f0,
- 0x2100, 0x214f,
- 0x2153, 0x2188,
- 0x2190, 0x23e7,
- 0x2400, 0x2426,
- 0x2440, 0x244a,
- 0x2460, 0x269d,
- 0x26a0, 0x26bc,
- 0x26c0, 0x26c3,
- 0x2701, 0x2704,
- 0x2706, 0x2709,
- 0x270c, 0x2727,
- 0x2729, 0x274b,
- 0x274d, 0x274d,
- 0x274f, 0x2752,
- 0x2756, 0x2756,
- 0x2758, 0x275e,
- 0x2761, 0x2794,
- 0x2798, 0x27af,
- 0x27b1, 0x27be,
- 0x27c0, 0x27ca,
- 0x27cc, 0x27cc,
- 0x27d0, 0x2b4c,
- 0x2b50, 0x2b54,
- 0x2c00, 0x2c2e,
- 0x2c30, 0x2c5e,
- 0x2c60, 0x2c6f,
- 0x2c71, 0x2c7d,
- 0x2c80, 0x2cea,
- 0x2cf9, 0x2d25,
- 0x2d30, 0x2d65,
- 0x2d6f, 0x2d6f,
- 0x2d80, 0x2d96,
- 0x2da0, 0x2da6,
- 0x2da8, 0x2dae,
- 0x2db0, 0x2db6,
- 0x2db8, 0x2dbe,
- 0x2dc0, 0x2dc6,
- 0x2dc8, 0x2dce,
- 0x2dd0, 0x2dd6,
- 0x2dd8, 0x2dde,
- 0x2de0, 0x2e30,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x303f,
- 0x3041, 0x3096,
- 0x3099, 0x30ff,
- 0x3105, 0x312d,
- 0x3131, 0x318e,
- 0x3190, 0x31b7,
- 0x31c0, 0x31e3,
- 0x31f0, 0x321e,
- 0x3220, 0x3243,
- 0x3250, 0x32fe,
- 0x3300, 0x4db5,
- 0x4dc0, 0x9fc3,
- 0xa000, 0xa48c,
- 0xa490, 0xa4c6,
- 0xa500, 0xa62b,
- 0xa640, 0xa65f,
- 0xa662, 0xa673,
- 0xa67c, 0xa697,
- 0xa700, 0xa78c,
- 0xa7fb, 0xa82b,
- 0xa840, 0xa877,
- 0xa880, 0xa8c4,
- 0xa8ce, 0xa8d9,
- 0xa900, 0xa953,
- 0xa95f, 0xa95f,
- 0xaa00, 0xaa36,
- 0xaa40, 0xaa4d,
- 0xaa50, 0xaa59,
- 0xaa5c, 0xaa5f,
- 0xac00, 0xd7a3,
- 0xd800, 0xfa2d,
- 0xfa30, 0xfa6a,
- 0xfa70, 0xfad9,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1d, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbb1,
- 0xfbd3, 0xfd3f,
- 0xfd50, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdd0, 0xfdfd,
- 0xfe00, 0xfe19,
- 0xfe20, 0xfe26,
- 0xfe30, 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, 0x1018a,
- 0x10190, 0x1019b,
- 0x101d0, 0x101fd,
- 0x10280, 0x1029c,
- 0x102a0, 0x102d0,
- 0x10300, 0x1031e,
- 0x10320, 0x10323,
- 0x10330, 0x1034a,
- 0x10380, 0x1039d,
- 0x1039f, 0x103c3,
- 0x103c8, 0x103d5,
- 0x10400, 0x1049d,
- 0x104a0, 0x104a9,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x1083f,
- 0x10900, 0x10919,
- 0x1091f, 0x10939,
- 0x1093f, 0x1093f,
- 0x10a00, 0x10a03,
- 0x10a05, 0x10a06,
- 0x10a0c, 0x10a13,
- 0x10a15, 0x10a17,
- 0x10a19, 0x10a33,
- 0x10a38, 0x10a3a,
- 0x10a3f, 0x10a47,
- 0x10a50, 0x10a58,
- 0x12000, 0x1236e,
- 0x12400, 0x12462,
- 0x12470, 0x12473,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d129, 0x1d1dd,
- 0x1d200, 0x1d245,
- 0x1d300, 0x1d356,
- 0x1d360, 0x1d371,
- 0x1d400, 0x1d454,
- 0x1d456, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 0x1d4a2, 0x1d4a2,
- 0x1d4a5, 0x1d4a6,
- 0x1d4a9, 0x1d4ac,
- 0x1d4ae, 0x1d4b9,
- 0x1d4bb, 0x1d4bb,
- 0x1d4bd, 0x1d4c3,
- 0x1d4c5, 0x1d505,
- 0x1d507, 0x1d50a,
- 0x1d50d, 0x1d514,
- 0x1d516, 0x1d51c,
- 0x1d51e, 0x1d539,
- 0x1d53b, 0x1d53e,
- 0x1d540, 0x1d544,
- 0x1d546, 0x1d546,
- 0x1d54a, 0x1d550,
- 0x1d552, 0x1d6a5,
- 0x1d6a8, 0x1d7cb,
- 0x1d7ce, 0x1d7ff,
- 0x1f000, 0x1f02b,
- 0x1f030, 0x1f093,
- 0x1fffe, 0x2a6d6,
- 0x2f800, 0x2fa1d,
- 0x2fffe, 0x2ffff,
- 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_5_1 */
-
-/* 'Age_5_2': Derived Age 5.2 */
-static const OnigCodePoint CR_Age_5_2[] = {
- 495,
- 0x0000, 0x0377,
- 0x037a, 0x037e,
- 0x0384, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x0525,
- 0x0531, 0x0556,
- 0x0559, 0x055f,
- 0x0561, 0x0587,
- 0x0589, 0x058a,
- 0x0591, 0x05c7,
- 0x05d0, 0x05ea,
- 0x05f0, 0x05f4,
- 0x0600, 0x0603,
- 0x0606, 0x061b,
- 0x061e, 0x061f,
- 0x0621, 0x065e,
- 0x0660, 0x070d,
- 0x070f, 0x074a,
- 0x074d, 0x07b1,
- 0x07c0, 0x07fa,
- 0x0800, 0x082d,
- 0x0830, 0x083e,
- 0x0900, 0x0939,
- 0x093c, 0x094e,
- 0x0950, 0x0955,
- 0x0958, 0x0972,
- 0x0979, 0x097f,
- 0x0981, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fb,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a51, 0x0a51,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a75,
- 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, 0x0aef,
- 0x0af1, 0x0af1,
- 0x0b01, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b35, 0x0b39,
- 0x0b3c, 0x0b44,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4d,
- 0x0b56, 0x0b57,
- 0x0b5c, 0x0b5d,
- 0x0b5f, 0x0b63,
- 0x0b66, 0x0b71,
- 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,
- 0x0be6, 0x0bfa,
- 0x0c01, 0x0c03,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c33,
- 0x0c35, 0x0c39,
- 0x0c3d, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c58, 0x0c59,
- 0x0c60, 0x0c63,
- 0x0c66, 0x0c6f,
- 0x0c78, 0x0c7f,
- 0x0c82, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce3,
- 0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
- 0x0d02, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d28,
- 0x0d2a, 0x0d39,
- 0x0d3d, 0x0d44,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4d,
- 0x0d57, 0x0d57,
- 0x0d60, 0x0d63,
- 0x0d66, 0x0d75,
- 0x0d79, 0x0d7f,
- 0x0d82, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0df2, 0x0df4,
- 0x0e01, 0x0e3a,
- 0x0e3f, 0x0e5b,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e87, 0x0e88,
- 0x0e8a, 0x0e8a,
- 0x0e8d, 0x0e8d,
- 0x0e94, 0x0e97,
- 0x0e99, 0x0e9f,
- 0x0ea1, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ea7,
- 0x0eaa, 0x0eab,
- 0x0ead, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edd,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f71, 0x0f8b,
- 0x0f90, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x0fbe, 0x0fcc,
- 0x0fce, 0x0fd8,
- 0x1000, 0x10c5,
- 0x10d0, 0x10fc,
- 0x1100, 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,
- 0x135f, 0x137c,
- 0x1380, 0x1399,
- 0x13a0, 0x13f4,
- 0x1400, 0x169c,
- 0x16a0, 0x16f0,
- 0x1700, 0x170c,
- 0x170e, 0x1714,
- 0x1720, 0x1736,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17dd,
- 0x17e0, 0x17e9,
- 0x17f0, 0x17f9,
- 0x1800, 0x180e,
- 0x1810, 0x1819,
- 0x1820, 0x1877,
- 0x1880, 0x18aa,
- 0x18b0, 0x18f5,
- 0x1900, 0x191c,
- 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,
- 0x1b00, 0x1b4b,
- 0x1b50, 0x1b7c,
- 0x1b80, 0x1baa,
- 0x1bae, 0x1bb9,
- 0x1c00, 0x1c37,
- 0x1c3b, 0x1c49,
- 0x1c4d, 0x1c7f,
- 0x1cd0, 0x1cf2,
- 0x1d00, 0x1de6,
- 0x1dfd, 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,
- 0x206a, 0x2071,
- 0x2074, 0x208e,
- 0x2090, 0x2094,
- 0x20a0, 0x20b8,
- 0x20d0, 0x20f0,
- 0x2100, 0x2189,
- 0x2190, 0x23e8,
- 0x2400, 0x2426,
- 0x2440, 0x244a,
- 0x2460, 0x26cd,
- 0x26cf, 0x26e1,
- 0x26e3, 0x26e3,
- 0x26e8, 0x26ff,
- 0x2701, 0x2704,
- 0x2706, 0x2709,
- 0x270c, 0x2727,
- 0x2729, 0x274b,
- 0x274d, 0x274d,
- 0x274f, 0x2752,
- 0x2756, 0x275e,
- 0x2761, 0x2794,
- 0x2798, 0x27af,
- 0x27b1, 0x27be,
- 0x27c0, 0x27ca,
- 0x27cc, 0x27cc,
- 0x27d0, 0x2b4c,
- 0x2b50, 0x2b59,
- 0x2c00, 0x2c2e,
- 0x2c30, 0x2c5e,
- 0x2c60, 0x2cf1,
- 0x2cf9, 0x2d25,
- 0x2d30, 0x2d65,
- 0x2d6f, 0x2d6f,
- 0x2d80, 0x2d96,
- 0x2da0, 0x2da6,
- 0x2da8, 0x2dae,
- 0x2db0, 0x2db6,
- 0x2db8, 0x2dbe,
- 0x2dc0, 0x2dc6,
- 0x2dc8, 0x2dce,
- 0x2dd0, 0x2dd6,
- 0x2dd8, 0x2dde,
- 0x2de0, 0x2e31,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x303f,
- 0x3041, 0x3096,
- 0x3099, 0x30ff,
- 0x3105, 0x312d,
- 0x3131, 0x318e,
- 0x3190, 0x31b7,
- 0x31c0, 0x31e3,
- 0x31f0, 0x321e,
- 0x3220, 0x32fe,
- 0x3300, 0x4db5,
- 0x4dc0, 0x9fcb,
- 0xa000, 0xa48c,
- 0xa490, 0xa4c6,
- 0xa4d0, 0xa62b,
- 0xa640, 0xa65f,
- 0xa662, 0xa673,
- 0xa67c, 0xa697,
- 0xa6a0, 0xa6f7,
- 0xa700, 0xa78c,
- 0xa7fb, 0xa82b,
- 0xa830, 0xa839,
- 0xa840, 0xa877,
- 0xa880, 0xa8c4,
- 0xa8ce, 0xa8d9,
- 0xa8e0, 0xa8fb,
- 0xa900, 0xa953,
- 0xa95f, 0xa97c,
- 0xa980, 0xa9cd,
- 0xa9cf, 0xa9d9,
- 0xa9de, 0xa9df,
- 0xaa00, 0xaa36,
- 0xaa40, 0xaa4d,
- 0xaa50, 0xaa59,
- 0xaa5c, 0xaa7b,
- 0xaa80, 0xaac2,
- 0xaadb, 0xaadf,
- 0xabc0, 0xabed,
- 0xabf0, 0xabf9,
- 0xac00, 0xd7a3,
- 0xd7b0, 0xd7c6,
- 0xd7cb, 0xd7fb,
- 0xd800, 0xfa2d,
- 0xfa30, 0xfa6d,
- 0xfa70, 0xfad9,
- 0xfb00, 0xfb06,
- 0xfb13, 0xfb17,
- 0xfb1d, 0xfb36,
- 0xfb38, 0xfb3c,
- 0xfb3e, 0xfb3e,
- 0xfb40, 0xfb41,
- 0xfb43, 0xfb44,
- 0xfb46, 0xfbb1,
- 0xfbd3, 0xfd3f,
- 0xfd50, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdd0, 0xfdfd,
- 0xfe00, 0xfe19,
- 0xfe20, 0xfe26,
- 0xfe30, 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, 0x1018a,
- 0x10190, 0x1019b,
- 0x101d0, 0x101fd,
- 0x10280, 0x1029c,
- 0x102a0, 0x102d0,
- 0x10300, 0x1031e,
- 0x10320, 0x10323,
- 0x10330, 0x1034a,
- 0x10380, 0x1039d,
- 0x1039f, 0x103c3,
- 0x103c8, 0x103d5,
- 0x10400, 0x1049d,
- 0x104a0, 0x104a9,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x10855,
- 0x10857, 0x1085f,
- 0x10900, 0x1091b,
- 0x1091f, 0x10939,
- 0x1093f, 0x1093f,
- 0x10a00, 0x10a03,
- 0x10a05, 0x10a06,
- 0x10a0c, 0x10a13,
- 0x10a15, 0x10a17,
- 0x10a19, 0x10a33,
- 0x10a38, 0x10a3a,
- 0x10a3f, 0x10a47,
- 0x10a50, 0x10a58,
- 0x10a60, 0x10a7f,
- 0x10b00, 0x10b35,
- 0x10b39, 0x10b55,
- 0x10b58, 0x10b72,
- 0x10b78, 0x10b7f,
- 0x10c00, 0x10c48,
- 0x10e60, 0x10e7e,
- 0x11080, 0x110c1,
- 0x12000, 0x1236e,
- 0x12400, 0x12462,
- 0x12470, 0x12473,
- 0x13000, 0x1342e,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d129, 0x1d1dd,
- 0x1d200, 0x1d245,
- 0x1d300, 0x1d356,
- 0x1d360, 0x1d371,
- 0x1d400, 0x1d454,
- 0x1d456, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 0x1d4a2, 0x1d4a2,
- 0x1d4a5, 0x1d4a6,
- 0x1d4a9, 0x1d4ac,
- 0x1d4ae, 0x1d4b9,
- 0x1d4bb, 0x1d4bb,
- 0x1d4bd, 0x1d4c3,
- 0x1d4c5, 0x1d505,
- 0x1d507, 0x1d50a,
- 0x1d50d, 0x1d514,
- 0x1d516, 0x1d51c,
- 0x1d51e, 0x1d539,
- 0x1d53b, 0x1d53e,
- 0x1d540, 0x1d544,
- 0x1d546, 0x1d546,
- 0x1d54a, 0x1d550,
- 0x1d552, 0x1d6a5,
- 0x1d6a8, 0x1d7cb,
- 0x1d7ce, 0x1d7ff,
- 0x1f000, 0x1f02b,
- 0x1f030, 0x1f093,
- 0x1f100, 0x1f10a,
- 0x1f110, 0x1f12e,
- 0x1f131, 0x1f131,
- 0x1f13d, 0x1f13d,
- 0x1f13f, 0x1f13f,
- 0x1f142, 0x1f142,
- 0x1f146, 0x1f146,
- 0x1f14a, 0x1f14e,
- 0x1f157, 0x1f157,
- 0x1f15f, 0x1f15f,
- 0x1f179, 0x1f179,
- 0x1f17b, 0x1f17c,
- 0x1f17f, 0x1f17f,
- 0x1f18a, 0x1f18d,
- 0x1f190, 0x1f190,
- 0x1f200, 0x1f200,
- 0x1f210, 0x1f231,
- 0x1f240, 0x1f248,
- 0x1fffe, 0x2a6d6,
- 0x2a700, 0x2b734,
- 0x2f800, 0x2fa1d,
- 0x2fffe, 0x2ffff,
- 0x3fffe, 0x3ffff,
- 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_5_2 */
-
-/* 'Age_6_0': Derived Age 6.0 */
-static const OnigCodePoint CR_Age_6_0[] = {
- 511,
- 0x0000, 0x0377,
- 0x037a, 0x037e,
- 0x0384, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x0527,
- 0x0531, 0x0556,
- 0x0559, 0x055f,
- 0x0561, 0x0587,
- 0x0589, 0x058a,
- 0x0591, 0x05c7,
- 0x05d0, 0x05ea,
- 0x05f0, 0x05f4,
- 0x0600, 0x0603,
- 0x0606, 0x061b,
- 0x061e, 0x070d,
- 0x070f, 0x074a,
- 0x074d, 0x07b1,
- 0x07c0, 0x07fa,
- 0x0800, 0x082d,
- 0x0830, 0x083e,
- 0x0840, 0x085b,
- 0x085e, 0x085e,
- 0x0900, 0x0977,
- 0x0979, 0x097f,
- 0x0981, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fb,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a51, 0x0a51,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a75,
- 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, 0x0aef,
- 0x0af1, 0x0af1,
- 0x0b01, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b35, 0x0b39,
- 0x0b3c, 0x0b44,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4d,
- 0x0b56, 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,
- 0x0be6, 0x0bfa,
- 0x0c01, 0x0c03,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c33,
- 0x0c35, 0x0c39,
- 0x0c3d, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c58, 0x0c59,
- 0x0c60, 0x0c63,
- 0x0c66, 0x0c6f,
- 0x0c78, 0x0c7f,
- 0x0c82, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce3,
- 0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
- 0x0d02, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d3a,
- 0x0d3d, 0x0d44,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4e,
- 0x0d57, 0x0d57,
- 0x0d60, 0x0d63,
- 0x0d66, 0x0d75,
- 0x0d79, 0x0d7f,
- 0x0d82, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0df2, 0x0df4,
- 0x0e01, 0x0e3a,
- 0x0e3f, 0x0e5b,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e87, 0x0e88,
- 0x0e8a, 0x0e8a,
- 0x0e8d, 0x0e8d,
- 0x0e94, 0x0e97,
- 0x0e99, 0x0e9f,
- 0x0ea1, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ea7,
- 0x0eaa, 0x0eab,
- 0x0ead, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edd,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f71, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x0fbe, 0x0fcc,
- 0x0fce, 0x0fda,
- 0x1000, 0x10c5,
- 0x10d0, 0x10fc,
- 0x1100, 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, 0x13f4,
- 0x1400, 0x169c,
- 0x16a0, 0x16f0,
- 0x1700, 0x170c,
- 0x170e, 0x1714,
- 0x1720, 0x1736,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17dd,
- 0x17e0, 0x17e9,
- 0x17f0, 0x17f9,
- 0x1800, 0x180e,
- 0x1810, 0x1819,
- 0x1820, 0x1877,
- 0x1880, 0x18aa,
- 0x18b0, 0x18f5,
- 0x1900, 0x191c,
- 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,
- 0x1b00, 0x1b4b,
- 0x1b50, 0x1b7c,
- 0x1b80, 0x1baa,
- 0x1bae, 0x1bb9,
- 0x1bc0, 0x1bf3,
- 0x1bfc, 0x1c37,
- 0x1c3b, 0x1c49,
- 0x1c4d, 0x1c7f,
- 0x1cd0, 0x1cf2,
- 0x1d00, 0x1de6,
- 0x1dfc, 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,
- 0x206a, 0x2071,
- 0x2074, 0x208e,
- 0x2090, 0x209c,
- 0x20a0, 0x20b9,
- 0x20d0, 0x20f0,
- 0x2100, 0x2189,
- 0x2190, 0x23f3,
- 0x2400, 0x2426,
- 0x2440, 0x244a,
- 0x2460, 0x26ff,
- 0x2701, 0x27ca,
- 0x27cc, 0x27cc,
- 0x27ce, 0x2b4c,
- 0x2b50, 0x2b59,
- 0x2c00, 0x2c2e,
- 0x2c30, 0x2c5e,
- 0x2c60, 0x2cf1,
- 0x2cf9, 0x2d25,
- 0x2d30, 0x2d65,
- 0x2d6f, 0x2d70,
- 0x2d7f, 0x2d96,
- 0x2da0, 0x2da6,
- 0x2da8, 0x2dae,
- 0x2db0, 0x2db6,
- 0x2db8, 0x2dbe,
- 0x2dc0, 0x2dc6,
- 0x2dc8, 0x2dce,
- 0x2dd0, 0x2dd6,
- 0x2dd8, 0x2dde,
- 0x2de0, 0x2e31,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x303f,
- 0x3041, 0x3096,
- 0x3099, 0x30ff,
- 0x3105, 0x312d,
- 0x3131, 0x318e,
- 0x3190, 0x31ba,
- 0x31c0, 0x31e3,
- 0x31f0, 0x321e,
- 0x3220, 0x32fe,
- 0x3300, 0x4db5,
- 0x4dc0, 0x9fcb,
- 0xa000, 0xa48c,
- 0xa490, 0xa4c6,
- 0xa4d0, 0xa62b,
- 0xa640, 0xa673,
- 0xa67c, 0xa697,
- 0xa6a0, 0xa6f7,
- 0xa700, 0xa78e,
- 0xa790, 0xa791,
- 0xa7a0, 0xa7a9,
- 0xa7fa, 0xa82b,
- 0xa830, 0xa839,
- 0xa840, 0xa877,
- 0xa880, 0xa8c4,
- 0xa8ce, 0xa8d9,
- 0xa8e0, 0xa8fb,
- 0xa900, 0xa953,
- 0xa95f, 0xa97c,
- 0xa980, 0xa9cd,
- 0xa9cf, 0xa9d9,
- 0xa9de, 0xa9df,
- 0xaa00, 0xaa36,
- 0xaa40, 0xaa4d,
- 0xaa50, 0xaa59,
- 0xaa5c, 0xaa7b,
- 0xaa80, 0xaac2,
- 0xaadb, 0xaadf,
- 0xab01, 0xab06,
- 0xab09, 0xab0e,
- 0xab11, 0xab16,
- 0xab20, 0xab26,
- 0xab28, 0xab2e,
- 0xabc0, 0xabed,
- 0xabf0, 0xabf9,
- 0xac00, 0xd7a3,
- 0xd7b0, 0xd7c6,
- 0xd7cb, 0xd7fb,
- 0xd800, 0xfa2d,
- 0xfa30, 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, 0xfe26,
- 0xfe30, 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, 0x1018a,
- 0x10190, 0x1019b,
- 0x101d0, 0x101fd,
- 0x10280, 0x1029c,
- 0x102a0, 0x102d0,
- 0x10300, 0x1031e,
- 0x10320, 0x10323,
- 0x10330, 0x1034a,
- 0x10380, 0x1039d,
- 0x1039f, 0x103c3,
- 0x103c8, 0x103d5,
- 0x10400, 0x1049d,
- 0x104a0, 0x104a9,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x10855,
- 0x10857, 0x1085f,
- 0x10900, 0x1091b,
- 0x1091f, 0x10939,
- 0x1093f, 0x1093f,
- 0x10a00, 0x10a03,
- 0x10a05, 0x10a06,
- 0x10a0c, 0x10a13,
- 0x10a15, 0x10a17,
- 0x10a19, 0x10a33,
- 0x10a38, 0x10a3a,
- 0x10a3f, 0x10a47,
- 0x10a50, 0x10a58,
- 0x10a60, 0x10a7f,
- 0x10b00, 0x10b35,
- 0x10b39, 0x10b55,
- 0x10b58, 0x10b72,
- 0x10b78, 0x10b7f,
- 0x10c00, 0x10c48,
- 0x10e60, 0x10e7e,
- 0x11000, 0x1104d,
- 0x11052, 0x1106f,
- 0x11080, 0x110c1,
- 0x12000, 0x1236e,
- 0x12400, 0x12462,
- 0x12470, 0x12473,
- 0x13000, 0x1342e,
- 0x16800, 0x16a38,
- 0x1b000, 0x1b001,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d129, 0x1d1dd,
- 0x1d200, 0x1d245,
- 0x1d300, 0x1d356,
- 0x1d360, 0x1d371,
- 0x1d400, 0x1d454,
- 0x1d456, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 0x1d4a2, 0x1d4a2,
- 0x1d4a5, 0x1d4a6,
- 0x1d4a9, 0x1d4ac,
- 0x1d4ae, 0x1d4b9,
- 0x1d4bb, 0x1d4bb,
- 0x1d4bd, 0x1d4c3,
- 0x1d4c5, 0x1d505,
- 0x1d507, 0x1d50a,
- 0x1d50d, 0x1d514,
- 0x1d516, 0x1d51c,
- 0x1d51e, 0x1d539,
- 0x1d53b, 0x1d53e,
- 0x1d540, 0x1d544,
- 0x1d546, 0x1d546,
- 0x1d54a, 0x1d550,
- 0x1d552, 0x1d6a5,
- 0x1d6a8, 0x1d7cb,
- 0x1d7ce, 0x1d7ff,
- 0x1f000, 0x1f02b,
- 0x1f030, 0x1f093,
- 0x1f0a0, 0x1f0ae,
- 0x1f0b1, 0x1f0be,
- 0x1f0c1, 0x1f0cf,
- 0x1f0d1, 0x1f0df,
- 0x1f100, 0x1f10a,
- 0x1f110, 0x1f12e,
- 0x1f130, 0x1f169,
- 0x1f170, 0x1f19a,
- 0x1f1e6, 0x1f202,
- 0x1f210, 0x1f23a,
- 0x1f240, 0x1f248,
- 0x1f250, 0x1f251,
- 0x1f300, 0x1f320,
- 0x1f330, 0x1f335,
- 0x1f337, 0x1f37c,
- 0x1f380, 0x1f393,
- 0x1f3a0, 0x1f3c4,
- 0x1f3c6, 0x1f3ca,
- 0x1f3e0, 0x1f3f0,
- 0x1f400, 0x1f43e,
- 0x1f440, 0x1f440,
- 0x1f442, 0x1f4f7,
- 0x1f4f9, 0x1f4fc,
- 0x1f500, 0x1f53d,
- 0x1f550, 0x1f567,
- 0x1f5fb, 0x1f5ff,
- 0x1f601, 0x1f610,
- 0x1f612, 0x1f614,
- 0x1f616, 0x1f616,
- 0x1f618, 0x1f618,
- 0x1f61a, 0x1f61a,
- 0x1f61c, 0x1f61e,
- 0x1f620, 0x1f625,
- 0x1f628, 0x1f62b,
- 0x1f62d, 0x1f62d,
- 0x1f630, 0x1f633,
- 0x1f635, 0x1f640,
- 0x1f645, 0x1f64f,
- 0x1f680, 0x1f6c5,
- 0x1f700, 0x1f773,
- 0x1fffe, 0x2a6d6,
- 0x2a700, 0x2b734,
- 0x2b740, 0x2b81d,
- 0x2f800, 0x2fa1d,
- 0x2fffe, 0x2ffff,
- 0x3fffe, 0x3ffff,
- 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_6_0 */
-
-/* 'Age_6_1': Derived Age 6.1 */
-static const OnigCodePoint CR_Age_6_1[] = {
- 549,
- 0x0000, 0x0377,
- 0x037a, 0x037e,
- 0x0384, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x0527,
- 0x0531, 0x0556,
- 0x0559, 0x055f,
- 0x0561, 0x0587,
- 0x0589, 0x058a,
- 0x058f, 0x058f,
- 0x0591, 0x05c7,
- 0x05d0, 0x05ea,
- 0x05f0, 0x05f4,
- 0x0600, 0x0604,
- 0x0606, 0x061b,
- 0x061e, 0x070d,
- 0x070f, 0x074a,
- 0x074d, 0x07b1,
- 0x07c0, 0x07fa,
- 0x0800, 0x082d,
- 0x0830, 0x083e,
- 0x0840, 0x085b,
- 0x085e, 0x085e,
- 0x08a0, 0x08a0,
- 0x08a2, 0x08ac,
- 0x08e4, 0x08fe,
- 0x0900, 0x0977,
- 0x0979, 0x097f,
- 0x0981, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fb,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a51, 0x0a51,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a75,
- 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,
- 0x0b01, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b35, 0x0b39,
- 0x0b3c, 0x0b44,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4d,
- 0x0b56, 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,
- 0x0be6, 0x0bfa,
- 0x0c01, 0x0c03,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c33,
- 0x0c35, 0x0c39,
- 0x0c3d, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c58, 0x0c59,
- 0x0c60, 0x0c63,
- 0x0c66, 0x0c6f,
- 0x0c78, 0x0c7f,
- 0x0c82, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce3,
- 0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
- 0x0d02, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d3a,
- 0x0d3d, 0x0d44,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4e,
- 0x0d57, 0x0d57,
- 0x0d60, 0x0d63,
- 0x0d66, 0x0d75,
- 0x0d79, 0x0d7f,
- 0x0d82, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0df2, 0x0df4,
- 0x0e01, 0x0e3a,
- 0x0e3f, 0x0e5b,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e87, 0x0e88,
- 0x0e8a, 0x0e8a,
- 0x0e8d, 0x0e8d,
- 0x0e94, 0x0e97,
- 0x0e99, 0x0e9f,
- 0x0ea1, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ea7,
- 0x0eaa, 0x0eab,
- 0x0ead, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f71, 0x0f97,
- 0x0f99, 0x0fbc,
- 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, 0x13f4,
- 0x1400, 0x169c,
- 0x16a0, 0x16f0,
- 0x1700, 0x170c,
- 0x170e, 0x1714,
- 0x1720, 0x1736,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17dd,
- 0x17e0, 0x17e9,
- 0x17f0, 0x17f9,
- 0x1800, 0x180e,
- 0x1810, 0x1819,
- 0x1820, 0x1877,
- 0x1880, 0x18aa,
- 0x18b0, 0x18f5,
- 0x1900, 0x191c,
- 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,
- 0x1b00, 0x1b4b,
- 0x1b50, 0x1b7c,
- 0x1b80, 0x1bf3,
- 0x1bfc, 0x1c37,
- 0x1c3b, 0x1c49,
- 0x1c4d, 0x1c7f,
- 0x1cc0, 0x1cc7,
- 0x1cd0, 0x1cf6,
- 0x1d00, 0x1de6,
- 0x1dfc, 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,
- 0x206a, 0x2071,
- 0x2074, 0x208e,
- 0x2090, 0x209c,
- 0x20a0, 0x20b9,
- 0x20d0, 0x20f0,
- 0x2100, 0x2189,
- 0x2190, 0x23f3,
- 0x2400, 0x2426,
- 0x2440, 0x244a,
- 0x2460, 0x26ff,
- 0x2701, 0x2b4c,
- 0x2b50, 0x2b59,
- 0x2c00, 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, 0x2e3b,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x303f,
- 0x3041, 0x3096,
- 0x3099, 0x30ff,
- 0x3105, 0x312d,
- 0x3131, 0x318e,
- 0x3190, 0x31ba,
- 0x31c0, 0x31e3,
- 0x31f0, 0x321e,
- 0x3220, 0x32fe,
- 0x3300, 0x4db5,
- 0x4dc0, 0x9fcc,
- 0xa000, 0xa48c,
- 0xa490, 0xa4c6,
- 0xa4d0, 0xa62b,
- 0xa640, 0xa697,
- 0xa69f, 0xa6f7,
- 0xa700, 0xa78e,
- 0xa790, 0xa793,
- 0xa7a0, 0xa7aa,
- 0xa7f8, 0xa82b,
- 0xa830, 0xa839,
- 0xa840, 0xa877,
- 0xa880, 0xa8c4,
- 0xa8ce, 0xa8d9,
- 0xa8e0, 0xa8fb,
- 0xa900, 0xa953,
- 0xa95f, 0xa97c,
- 0xa980, 0xa9cd,
- 0xa9cf, 0xa9d9,
- 0xa9de, 0xa9df,
- 0xaa00, 0xaa36,
- 0xaa40, 0xaa4d,
- 0xaa50, 0xaa59,
- 0xaa5c, 0xaa7b,
- 0xaa80, 0xaac2,
- 0xaadb, 0xaaf6,
- 0xab01, 0xab06,
- 0xab09, 0xab0e,
- 0xab11, 0xab16,
- 0xab20, 0xab26,
- 0xab28, 0xab2e,
- 0xabc0, 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, 0xfe26,
- 0xfe30, 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, 0x1018a,
- 0x10190, 0x1019b,
- 0x101d0, 0x101fd,
- 0x10280, 0x1029c,
- 0x102a0, 0x102d0,
- 0x10300, 0x1031e,
- 0x10320, 0x10323,
- 0x10330, 0x1034a,
- 0x10380, 0x1039d,
- 0x1039f, 0x103c3,
- 0x103c8, 0x103d5,
- 0x10400, 0x1049d,
- 0x104a0, 0x104a9,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x10855,
- 0x10857, 0x1085f,
- 0x10900, 0x1091b,
- 0x1091f, 0x10939,
- 0x1093f, 0x1093f,
- 0x10980, 0x109b7,
- 0x109be, 0x109bf,
- 0x10a00, 0x10a03,
- 0x10a05, 0x10a06,
- 0x10a0c, 0x10a13,
- 0x10a15, 0x10a17,
- 0x10a19, 0x10a33,
- 0x10a38, 0x10a3a,
- 0x10a3f, 0x10a47,
- 0x10a50, 0x10a58,
- 0x10a60, 0x10a7f,
- 0x10b00, 0x10b35,
- 0x10b39, 0x10b55,
- 0x10b58, 0x10b72,
- 0x10b78, 0x10b7f,
- 0x10c00, 0x10c48,
- 0x10e60, 0x10e7e,
- 0x11000, 0x1104d,
- 0x11052, 0x1106f,
- 0x11080, 0x110c1,
- 0x110d0, 0x110e8,
- 0x110f0, 0x110f9,
- 0x11100, 0x11134,
- 0x11136, 0x11143,
- 0x11180, 0x111c8,
- 0x111d0, 0x111d9,
- 0x11680, 0x116b7,
- 0x116c0, 0x116c9,
- 0x12000, 0x1236e,
- 0x12400, 0x12462,
- 0x12470, 0x12473,
- 0x13000, 0x1342e,
- 0x16800, 0x16a38,
- 0x16f00, 0x16f44,
- 0x16f50, 0x16f7e,
- 0x16f8f, 0x16f9f,
- 0x1b000, 0x1b001,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d129, 0x1d1dd,
- 0x1d200, 0x1d245,
- 0x1d300, 0x1d356,
- 0x1d360, 0x1d371,
- 0x1d400, 0x1d454,
- 0x1d456, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 0x1d4a2, 0x1d4a2,
- 0x1d4a5, 0x1d4a6,
- 0x1d4a9, 0x1d4ac,
- 0x1d4ae, 0x1d4b9,
- 0x1d4bb, 0x1d4bb,
- 0x1d4bd, 0x1d4c3,
- 0x1d4c5, 0x1d505,
- 0x1d507, 0x1d50a,
- 0x1d50d, 0x1d514,
- 0x1d516, 0x1d51c,
- 0x1d51e, 0x1d539,
- 0x1d53b, 0x1d53e,
- 0x1d540, 0x1d544,
- 0x1d546, 0x1d546,
- 0x1d54a, 0x1d550,
- 0x1d552, 0x1d6a5,
- 0x1d6a8, 0x1d7cb,
- 0x1d7ce, 0x1d7ff,
- 0x1ee00, 0x1ee03,
- 0x1ee05, 0x1ee1f,
- 0x1ee21, 0x1ee22,
- 0x1ee24, 0x1ee24,
- 0x1ee27, 0x1ee27,
- 0x1ee29, 0x1ee32,
- 0x1ee34, 0x1ee37,
- 0x1ee39, 0x1ee39,
- 0x1ee3b, 0x1ee3b,
- 0x1ee42, 0x1ee42,
- 0x1ee47, 0x1ee47,
- 0x1ee49, 0x1ee49,
- 0x1ee4b, 0x1ee4b,
- 0x1ee4d, 0x1ee4f,
- 0x1ee51, 0x1ee52,
- 0x1ee54, 0x1ee54,
- 0x1ee57, 0x1ee57,
- 0x1ee59, 0x1ee59,
- 0x1ee5b, 0x1ee5b,
- 0x1ee5d, 0x1ee5d,
- 0x1ee5f, 0x1ee5f,
- 0x1ee61, 0x1ee62,
- 0x1ee64, 0x1ee64,
- 0x1ee67, 0x1ee6a,
- 0x1ee6c, 0x1ee72,
- 0x1ee74, 0x1ee77,
- 0x1ee79, 0x1ee7c,
- 0x1ee7e, 0x1ee7e,
- 0x1ee80, 0x1ee89,
- 0x1ee8b, 0x1ee9b,
- 0x1eea1, 0x1eea3,
- 0x1eea5, 0x1eea9,
- 0x1eeab, 0x1eebb,
- 0x1eef0, 0x1eef1,
- 0x1f000, 0x1f02b,
- 0x1f030, 0x1f093,
- 0x1f0a0, 0x1f0ae,
- 0x1f0b1, 0x1f0be,
- 0x1f0c1, 0x1f0cf,
- 0x1f0d1, 0x1f0df,
- 0x1f100, 0x1f10a,
- 0x1f110, 0x1f12e,
- 0x1f130, 0x1f16b,
- 0x1f170, 0x1f19a,
- 0x1f1e6, 0x1f202,
- 0x1f210, 0x1f23a,
- 0x1f240, 0x1f248,
- 0x1f250, 0x1f251,
- 0x1f300, 0x1f320,
- 0x1f330, 0x1f335,
- 0x1f337, 0x1f37c,
- 0x1f380, 0x1f393,
- 0x1f3a0, 0x1f3c4,
- 0x1f3c6, 0x1f3ca,
- 0x1f3e0, 0x1f3f0,
- 0x1f400, 0x1f43e,
- 0x1f440, 0x1f440,
- 0x1f442, 0x1f4f7,
- 0x1f4f9, 0x1f4fc,
- 0x1f500, 0x1f53d,
- 0x1f540, 0x1f543,
- 0x1f550, 0x1f567,
- 0x1f5fb, 0x1f640,
- 0x1f645, 0x1f64f,
- 0x1f680, 0x1f6c5,
- 0x1f700, 0x1f773,
- 0x1fffe, 0x2a6d6,
- 0x2a700, 0x2b734,
- 0x2b740, 0x2b81d,
- 0x2f800, 0x2fa1d,
- 0x2fffe, 0x2ffff,
- 0x3fffe, 0x3ffff,
- 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_6_1 */
-
-/* 'Age_6_2': Derived Age 6.2 */
-static const OnigCodePoint CR_Age_6_2[] = {
- 549,
- 0x0000, 0x0377,
- 0x037a, 0x037e,
- 0x0384, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x0527,
- 0x0531, 0x0556,
- 0x0559, 0x055f,
- 0x0561, 0x0587,
- 0x0589, 0x058a,
- 0x058f, 0x058f,
- 0x0591, 0x05c7,
- 0x05d0, 0x05ea,
- 0x05f0, 0x05f4,
- 0x0600, 0x0604,
- 0x0606, 0x061b,
- 0x061e, 0x070d,
- 0x070f, 0x074a,
- 0x074d, 0x07b1,
- 0x07c0, 0x07fa,
- 0x0800, 0x082d,
- 0x0830, 0x083e,
- 0x0840, 0x085b,
- 0x085e, 0x085e,
- 0x08a0, 0x08a0,
- 0x08a2, 0x08ac,
- 0x08e4, 0x08fe,
- 0x0900, 0x0977,
- 0x0979, 0x097f,
- 0x0981, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fb,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a51, 0x0a51,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a75,
- 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,
- 0x0b01, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b35, 0x0b39,
- 0x0b3c, 0x0b44,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4d,
- 0x0b56, 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,
- 0x0be6, 0x0bfa,
- 0x0c01, 0x0c03,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c33,
- 0x0c35, 0x0c39,
- 0x0c3d, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c58, 0x0c59,
- 0x0c60, 0x0c63,
- 0x0c66, 0x0c6f,
- 0x0c78, 0x0c7f,
- 0x0c82, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce3,
- 0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
- 0x0d02, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d3a,
- 0x0d3d, 0x0d44,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4e,
- 0x0d57, 0x0d57,
- 0x0d60, 0x0d63,
- 0x0d66, 0x0d75,
- 0x0d79, 0x0d7f,
- 0x0d82, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0df2, 0x0df4,
- 0x0e01, 0x0e3a,
- 0x0e3f, 0x0e5b,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e87, 0x0e88,
- 0x0e8a, 0x0e8a,
- 0x0e8d, 0x0e8d,
- 0x0e94, 0x0e97,
- 0x0e99, 0x0e9f,
- 0x0ea1, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ea7,
- 0x0eaa, 0x0eab,
- 0x0ead, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f71, 0x0f97,
- 0x0f99, 0x0fbc,
- 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, 0x13f4,
- 0x1400, 0x169c,
- 0x16a0, 0x16f0,
- 0x1700, 0x170c,
- 0x170e, 0x1714,
- 0x1720, 0x1736,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17dd,
- 0x17e0, 0x17e9,
- 0x17f0, 0x17f9,
- 0x1800, 0x180e,
- 0x1810, 0x1819,
- 0x1820, 0x1877,
- 0x1880, 0x18aa,
- 0x18b0, 0x18f5,
- 0x1900, 0x191c,
- 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,
- 0x1b00, 0x1b4b,
- 0x1b50, 0x1b7c,
- 0x1b80, 0x1bf3,
- 0x1bfc, 0x1c37,
- 0x1c3b, 0x1c49,
- 0x1c4d, 0x1c7f,
- 0x1cc0, 0x1cc7,
- 0x1cd0, 0x1cf6,
- 0x1d00, 0x1de6,
- 0x1dfc, 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,
- 0x206a, 0x2071,
- 0x2074, 0x208e,
- 0x2090, 0x209c,
- 0x20a0, 0x20ba,
- 0x20d0, 0x20f0,
- 0x2100, 0x2189,
- 0x2190, 0x23f3,
- 0x2400, 0x2426,
- 0x2440, 0x244a,
- 0x2460, 0x26ff,
- 0x2701, 0x2b4c,
- 0x2b50, 0x2b59,
- 0x2c00, 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, 0x2e3b,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x303f,
- 0x3041, 0x3096,
- 0x3099, 0x30ff,
- 0x3105, 0x312d,
- 0x3131, 0x318e,
- 0x3190, 0x31ba,
- 0x31c0, 0x31e3,
- 0x31f0, 0x321e,
- 0x3220, 0x32fe,
- 0x3300, 0x4db5,
- 0x4dc0, 0x9fcc,
- 0xa000, 0xa48c,
- 0xa490, 0xa4c6,
- 0xa4d0, 0xa62b,
- 0xa640, 0xa697,
- 0xa69f, 0xa6f7,
- 0xa700, 0xa78e,
- 0xa790, 0xa793,
- 0xa7a0, 0xa7aa,
- 0xa7f8, 0xa82b,
- 0xa830, 0xa839,
- 0xa840, 0xa877,
- 0xa880, 0xa8c4,
- 0xa8ce, 0xa8d9,
- 0xa8e0, 0xa8fb,
- 0xa900, 0xa953,
- 0xa95f, 0xa97c,
- 0xa980, 0xa9cd,
- 0xa9cf, 0xa9d9,
- 0xa9de, 0xa9df,
- 0xaa00, 0xaa36,
- 0xaa40, 0xaa4d,
- 0xaa50, 0xaa59,
- 0xaa5c, 0xaa7b,
- 0xaa80, 0xaac2,
- 0xaadb, 0xaaf6,
- 0xab01, 0xab06,
- 0xab09, 0xab0e,
- 0xab11, 0xab16,
- 0xab20, 0xab26,
- 0xab28, 0xab2e,
- 0xabc0, 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, 0xfe26,
- 0xfe30, 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, 0x1018a,
- 0x10190, 0x1019b,
- 0x101d0, 0x101fd,
- 0x10280, 0x1029c,
- 0x102a0, 0x102d0,
- 0x10300, 0x1031e,
- 0x10320, 0x10323,
- 0x10330, 0x1034a,
- 0x10380, 0x1039d,
- 0x1039f, 0x103c3,
- 0x103c8, 0x103d5,
- 0x10400, 0x1049d,
- 0x104a0, 0x104a9,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x10855,
- 0x10857, 0x1085f,
- 0x10900, 0x1091b,
- 0x1091f, 0x10939,
- 0x1093f, 0x1093f,
- 0x10980, 0x109b7,
- 0x109be, 0x109bf,
- 0x10a00, 0x10a03,
- 0x10a05, 0x10a06,
- 0x10a0c, 0x10a13,
- 0x10a15, 0x10a17,
- 0x10a19, 0x10a33,
- 0x10a38, 0x10a3a,
- 0x10a3f, 0x10a47,
- 0x10a50, 0x10a58,
- 0x10a60, 0x10a7f,
- 0x10b00, 0x10b35,
- 0x10b39, 0x10b55,
- 0x10b58, 0x10b72,
- 0x10b78, 0x10b7f,
- 0x10c00, 0x10c48,
- 0x10e60, 0x10e7e,
- 0x11000, 0x1104d,
- 0x11052, 0x1106f,
- 0x11080, 0x110c1,
- 0x110d0, 0x110e8,
- 0x110f0, 0x110f9,
- 0x11100, 0x11134,
- 0x11136, 0x11143,
- 0x11180, 0x111c8,
- 0x111d0, 0x111d9,
- 0x11680, 0x116b7,
- 0x116c0, 0x116c9,
- 0x12000, 0x1236e,
- 0x12400, 0x12462,
- 0x12470, 0x12473,
- 0x13000, 0x1342e,
- 0x16800, 0x16a38,
- 0x16f00, 0x16f44,
- 0x16f50, 0x16f7e,
- 0x16f8f, 0x16f9f,
- 0x1b000, 0x1b001,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d129, 0x1d1dd,
- 0x1d200, 0x1d245,
- 0x1d300, 0x1d356,
- 0x1d360, 0x1d371,
- 0x1d400, 0x1d454,
- 0x1d456, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 0x1d4a2, 0x1d4a2,
- 0x1d4a5, 0x1d4a6,
- 0x1d4a9, 0x1d4ac,
- 0x1d4ae, 0x1d4b9,
- 0x1d4bb, 0x1d4bb,
- 0x1d4bd, 0x1d4c3,
- 0x1d4c5, 0x1d505,
- 0x1d507, 0x1d50a,
- 0x1d50d, 0x1d514,
- 0x1d516, 0x1d51c,
- 0x1d51e, 0x1d539,
- 0x1d53b, 0x1d53e,
- 0x1d540, 0x1d544,
- 0x1d546, 0x1d546,
- 0x1d54a, 0x1d550,
- 0x1d552, 0x1d6a5,
- 0x1d6a8, 0x1d7cb,
- 0x1d7ce, 0x1d7ff,
- 0x1ee00, 0x1ee03,
- 0x1ee05, 0x1ee1f,
- 0x1ee21, 0x1ee22,
- 0x1ee24, 0x1ee24,
- 0x1ee27, 0x1ee27,
- 0x1ee29, 0x1ee32,
- 0x1ee34, 0x1ee37,
- 0x1ee39, 0x1ee39,
- 0x1ee3b, 0x1ee3b,
- 0x1ee42, 0x1ee42,
- 0x1ee47, 0x1ee47,
- 0x1ee49, 0x1ee49,
- 0x1ee4b, 0x1ee4b,
- 0x1ee4d, 0x1ee4f,
- 0x1ee51, 0x1ee52,
- 0x1ee54, 0x1ee54,
- 0x1ee57, 0x1ee57,
- 0x1ee59, 0x1ee59,
- 0x1ee5b, 0x1ee5b,
- 0x1ee5d, 0x1ee5d,
- 0x1ee5f, 0x1ee5f,
- 0x1ee61, 0x1ee62,
- 0x1ee64, 0x1ee64,
- 0x1ee67, 0x1ee6a,
- 0x1ee6c, 0x1ee72,
- 0x1ee74, 0x1ee77,
- 0x1ee79, 0x1ee7c,
- 0x1ee7e, 0x1ee7e,
- 0x1ee80, 0x1ee89,
- 0x1ee8b, 0x1ee9b,
- 0x1eea1, 0x1eea3,
- 0x1eea5, 0x1eea9,
- 0x1eeab, 0x1eebb,
- 0x1eef0, 0x1eef1,
- 0x1f000, 0x1f02b,
- 0x1f030, 0x1f093,
- 0x1f0a0, 0x1f0ae,
- 0x1f0b1, 0x1f0be,
- 0x1f0c1, 0x1f0cf,
- 0x1f0d1, 0x1f0df,
- 0x1f100, 0x1f10a,
- 0x1f110, 0x1f12e,
- 0x1f130, 0x1f16b,
- 0x1f170, 0x1f19a,
- 0x1f1e6, 0x1f202,
- 0x1f210, 0x1f23a,
- 0x1f240, 0x1f248,
- 0x1f250, 0x1f251,
- 0x1f300, 0x1f320,
- 0x1f330, 0x1f335,
- 0x1f337, 0x1f37c,
- 0x1f380, 0x1f393,
- 0x1f3a0, 0x1f3c4,
- 0x1f3c6, 0x1f3ca,
- 0x1f3e0, 0x1f3f0,
- 0x1f400, 0x1f43e,
- 0x1f440, 0x1f440,
- 0x1f442, 0x1f4f7,
- 0x1f4f9, 0x1f4fc,
- 0x1f500, 0x1f53d,
- 0x1f540, 0x1f543,
- 0x1f550, 0x1f567,
- 0x1f5fb, 0x1f640,
- 0x1f645, 0x1f64f,
- 0x1f680, 0x1f6c5,
- 0x1f700, 0x1f773,
- 0x1fffe, 0x2a6d6,
- 0x2a700, 0x2b734,
- 0x2b740, 0x2b81d,
- 0x2f800, 0x2fa1d,
- 0x2fffe, 0x2ffff,
- 0x3fffe, 0x3ffff,
- 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_6_2 */
-
-/* 'Age_6_3': Derived Age 6.3 */
-static const OnigCodePoint CR_Age_6_3[] = {
- 549,
- 0x0000, 0x0377,
- 0x037a, 0x037e,
- 0x0384, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x0527,
- 0x0531, 0x0556,
- 0x0559, 0x055f,
- 0x0561, 0x0587,
- 0x0589, 0x058a,
- 0x058f, 0x058f,
- 0x0591, 0x05c7,
- 0x05d0, 0x05ea,
- 0x05f0, 0x05f4,
- 0x0600, 0x0604,
- 0x0606, 0x061c,
- 0x061e, 0x070d,
- 0x070f, 0x074a,
- 0x074d, 0x07b1,
- 0x07c0, 0x07fa,
- 0x0800, 0x082d,
- 0x0830, 0x083e,
- 0x0840, 0x085b,
- 0x085e, 0x085e,
- 0x08a0, 0x08a0,
- 0x08a2, 0x08ac,
- 0x08e4, 0x08fe,
- 0x0900, 0x0977,
- 0x0979, 0x097f,
- 0x0981, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fb,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a51, 0x0a51,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a75,
- 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,
- 0x0b01, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b35, 0x0b39,
- 0x0b3c, 0x0b44,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4d,
- 0x0b56, 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,
- 0x0be6, 0x0bfa,
- 0x0c01, 0x0c03,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c33,
- 0x0c35, 0x0c39,
- 0x0c3d, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c58, 0x0c59,
- 0x0c60, 0x0c63,
- 0x0c66, 0x0c6f,
- 0x0c78, 0x0c7f,
- 0x0c82, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce3,
- 0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
- 0x0d02, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d3a,
- 0x0d3d, 0x0d44,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4e,
- 0x0d57, 0x0d57,
- 0x0d60, 0x0d63,
- 0x0d66, 0x0d75,
- 0x0d79, 0x0d7f,
- 0x0d82, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0df2, 0x0df4,
- 0x0e01, 0x0e3a,
- 0x0e3f, 0x0e5b,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e87, 0x0e88,
- 0x0e8a, 0x0e8a,
- 0x0e8d, 0x0e8d,
- 0x0e94, 0x0e97,
- 0x0e99, 0x0e9f,
- 0x0ea1, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ea7,
- 0x0eaa, 0x0eab,
- 0x0ead, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f71, 0x0f97,
- 0x0f99, 0x0fbc,
- 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, 0x13f4,
- 0x1400, 0x169c,
- 0x16a0, 0x16f0,
- 0x1700, 0x170c,
- 0x170e, 0x1714,
- 0x1720, 0x1736,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17dd,
- 0x17e0, 0x17e9,
- 0x17f0, 0x17f9,
- 0x1800, 0x180e,
- 0x1810, 0x1819,
- 0x1820, 0x1877,
- 0x1880, 0x18aa,
- 0x18b0, 0x18f5,
- 0x1900, 0x191c,
- 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,
- 0x1b00, 0x1b4b,
- 0x1b50, 0x1b7c,
- 0x1b80, 0x1bf3,
- 0x1bfc, 0x1c37,
- 0x1c3b, 0x1c49,
- 0x1c4d, 0x1c7f,
- 0x1cc0, 0x1cc7,
- 0x1cd0, 0x1cf6,
- 0x1d00, 0x1de6,
- 0x1dfc, 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, 0x20ba,
- 0x20d0, 0x20f0,
- 0x2100, 0x2189,
- 0x2190, 0x23f3,
- 0x2400, 0x2426,
- 0x2440, 0x244a,
- 0x2460, 0x26ff,
- 0x2701, 0x2b4c,
- 0x2b50, 0x2b59,
- 0x2c00, 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, 0x2e3b,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x303f,
- 0x3041, 0x3096,
- 0x3099, 0x30ff,
- 0x3105, 0x312d,
- 0x3131, 0x318e,
- 0x3190, 0x31ba,
- 0x31c0, 0x31e3,
- 0x31f0, 0x321e,
- 0x3220, 0x32fe,
- 0x3300, 0x4db5,
- 0x4dc0, 0x9fcc,
- 0xa000, 0xa48c,
- 0xa490, 0xa4c6,
- 0xa4d0, 0xa62b,
- 0xa640, 0xa697,
- 0xa69f, 0xa6f7,
- 0xa700, 0xa78e,
- 0xa790, 0xa793,
- 0xa7a0, 0xa7aa,
- 0xa7f8, 0xa82b,
- 0xa830, 0xa839,
- 0xa840, 0xa877,
- 0xa880, 0xa8c4,
- 0xa8ce, 0xa8d9,
- 0xa8e0, 0xa8fb,
- 0xa900, 0xa953,
- 0xa95f, 0xa97c,
- 0xa980, 0xa9cd,
- 0xa9cf, 0xa9d9,
- 0xa9de, 0xa9df,
- 0xaa00, 0xaa36,
- 0xaa40, 0xaa4d,
- 0xaa50, 0xaa59,
- 0xaa5c, 0xaa7b,
- 0xaa80, 0xaac2,
- 0xaadb, 0xaaf6,
- 0xab01, 0xab06,
- 0xab09, 0xab0e,
- 0xab11, 0xab16,
- 0xab20, 0xab26,
- 0xab28, 0xab2e,
- 0xabc0, 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, 0xfe26,
- 0xfe30, 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, 0x1018a,
- 0x10190, 0x1019b,
- 0x101d0, 0x101fd,
- 0x10280, 0x1029c,
- 0x102a0, 0x102d0,
- 0x10300, 0x1031e,
- 0x10320, 0x10323,
- 0x10330, 0x1034a,
- 0x10380, 0x1039d,
- 0x1039f, 0x103c3,
- 0x103c8, 0x103d5,
- 0x10400, 0x1049d,
- 0x104a0, 0x104a9,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x10855,
- 0x10857, 0x1085f,
- 0x10900, 0x1091b,
- 0x1091f, 0x10939,
- 0x1093f, 0x1093f,
- 0x10980, 0x109b7,
- 0x109be, 0x109bf,
- 0x10a00, 0x10a03,
- 0x10a05, 0x10a06,
- 0x10a0c, 0x10a13,
- 0x10a15, 0x10a17,
- 0x10a19, 0x10a33,
- 0x10a38, 0x10a3a,
- 0x10a3f, 0x10a47,
- 0x10a50, 0x10a58,
- 0x10a60, 0x10a7f,
- 0x10b00, 0x10b35,
- 0x10b39, 0x10b55,
- 0x10b58, 0x10b72,
- 0x10b78, 0x10b7f,
- 0x10c00, 0x10c48,
- 0x10e60, 0x10e7e,
- 0x11000, 0x1104d,
- 0x11052, 0x1106f,
- 0x11080, 0x110c1,
- 0x110d0, 0x110e8,
- 0x110f0, 0x110f9,
- 0x11100, 0x11134,
- 0x11136, 0x11143,
- 0x11180, 0x111c8,
- 0x111d0, 0x111d9,
- 0x11680, 0x116b7,
- 0x116c0, 0x116c9,
- 0x12000, 0x1236e,
- 0x12400, 0x12462,
- 0x12470, 0x12473,
- 0x13000, 0x1342e,
- 0x16800, 0x16a38,
- 0x16f00, 0x16f44,
- 0x16f50, 0x16f7e,
- 0x16f8f, 0x16f9f,
- 0x1b000, 0x1b001,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d129, 0x1d1dd,
- 0x1d200, 0x1d245,
- 0x1d300, 0x1d356,
- 0x1d360, 0x1d371,
- 0x1d400, 0x1d454,
- 0x1d456, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 0x1d4a2, 0x1d4a2,
- 0x1d4a5, 0x1d4a6,
- 0x1d4a9, 0x1d4ac,
- 0x1d4ae, 0x1d4b9,
- 0x1d4bb, 0x1d4bb,
- 0x1d4bd, 0x1d4c3,
- 0x1d4c5, 0x1d505,
- 0x1d507, 0x1d50a,
- 0x1d50d, 0x1d514,
- 0x1d516, 0x1d51c,
- 0x1d51e, 0x1d539,
- 0x1d53b, 0x1d53e,
- 0x1d540, 0x1d544,
- 0x1d546, 0x1d546,
- 0x1d54a, 0x1d550,
- 0x1d552, 0x1d6a5,
- 0x1d6a8, 0x1d7cb,
- 0x1d7ce, 0x1d7ff,
- 0x1ee00, 0x1ee03,
- 0x1ee05, 0x1ee1f,
- 0x1ee21, 0x1ee22,
- 0x1ee24, 0x1ee24,
- 0x1ee27, 0x1ee27,
- 0x1ee29, 0x1ee32,
- 0x1ee34, 0x1ee37,
- 0x1ee39, 0x1ee39,
- 0x1ee3b, 0x1ee3b,
- 0x1ee42, 0x1ee42,
- 0x1ee47, 0x1ee47,
- 0x1ee49, 0x1ee49,
- 0x1ee4b, 0x1ee4b,
- 0x1ee4d, 0x1ee4f,
- 0x1ee51, 0x1ee52,
- 0x1ee54, 0x1ee54,
- 0x1ee57, 0x1ee57,
- 0x1ee59, 0x1ee59,
- 0x1ee5b, 0x1ee5b,
- 0x1ee5d, 0x1ee5d,
- 0x1ee5f, 0x1ee5f,
- 0x1ee61, 0x1ee62,
- 0x1ee64, 0x1ee64,
- 0x1ee67, 0x1ee6a,
- 0x1ee6c, 0x1ee72,
- 0x1ee74, 0x1ee77,
- 0x1ee79, 0x1ee7c,
- 0x1ee7e, 0x1ee7e,
- 0x1ee80, 0x1ee89,
- 0x1ee8b, 0x1ee9b,
- 0x1eea1, 0x1eea3,
- 0x1eea5, 0x1eea9,
- 0x1eeab, 0x1eebb,
- 0x1eef0, 0x1eef1,
- 0x1f000, 0x1f02b,
- 0x1f030, 0x1f093,
- 0x1f0a0, 0x1f0ae,
- 0x1f0b1, 0x1f0be,
- 0x1f0c1, 0x1f0cf,
- 0x1f0d1, 0x1f0df,
- 0x1f100, 0x1f10a,
- 0x1f110, 0x1f12e,
- 0x1f130, 0x1f16b,
- 0x1f170, 0x1f19a,
- 0x1f1e6, 0x1f202,
- 0x1f210, 0x1f23a,
- 0x1f240, 0x1f248,
- 0x1f250, 0x1f251,
- 0x1f300, 0x1f320,
- 0x1f330, 0x1f335,
- 0x1f337, 0x1f37c,
- 0x1f380, 0x1f393,
- 0x1f3a0, 0x1f3c4,
- 0x1f3c6, 0x1f3ca,
- 0x1f3e0, 0x1f3f0,
- 0x1f400, 0x1f43e,
- 0x1f440, 0x1f440,
- 0x1f442, 0x1f4f7,
- 0x1f4f9, 0x1f4fc,
- 0x1f500, 0x1f53d,
- 0x1f540, 0x1f543,
- 0x1f550, 0x1f567,
- 0x1f5fb, 0x1f640,
- 0x1f645, 0x1f64f,
- 0x1f680, 0x1f6c5,
- 0x1f700, 0x1f773,
- 0x1fffe, 0x2a6d6,
- 0x2a700, 0x2b734,
- 0x2b740, 0x2b81d,
- 0x2f800, 0x2fa1d,
- 0x2fffe, 0x2ffff,
- 0x3fffe, 0x3ffff,
- 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_6_3 */
-
-/* 'Age_7_0': Derived Age 7.0 */
-static const OnigCodePoint CR_Age_7_0[] = {
- 610,
- 0x0000, 0x0377,
- 0x037a, 0x037f,
- 0x0384, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x052f,
- 0x0531, 0x0556,
- 0x0559, 0x055f,
- 0x0561, 0x0587,
- 0x0589, 0x058a,
- 0x058d, 0x058f,
- 0x0591, 0x05c7,
- 0x05d0, 0x05ea,
- 0x05f0, 0x05f4,
- 0x0600, 0x061c,
- 0x061e, 0x070d,
- 0x070f, 0x074a,
- 0x074d, 0x07b1,
- 0x07c0, 0x07fa,
- 0x0800, 0x082d,
- 0x0830, 0x083e,
- 0x0840, 0x085b,
- 0x085e, 0x085e,
- 0x08a0, 0x08b2,
- 0x08e4, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fb,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a51, 0x0a51,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a75,
- 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,
- 0x0b01, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b35, 0x0b39,
- 0x0b3c, 0x0b44,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4d,
- 0x0b56, 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,
- 0x0be6, 0x0bfa,
- 0x0c00, 0x0c03,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c39,
- 0x0c3d, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c58, 0x0c59,
- 0x0c60, 0x0c63,
- 0x0c66, 0x0c6f,
- 0x0c78, 0x0c7f,
- 0x0c81, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce3,
- 0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
- 0x0d01, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d3a,
- 0x0d3d, 0x0d44,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4e,
- 0x0d57, 0x0d57,
- 0x0d60, 0x0d63,
- 0x0d66, 0x0d75,
- 0x0d79, 0x0d7f,
- 0x0d82, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0de6, 0x0def,
- 0x0df2, 0x0df4,
- 0x0e01, 0x0e3a,
- 0x0e3f, 0x0e5b,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e87, 0x0e88,
- 0x0e8a, 0x0e8a,
- 0x0e8d, 0x0e8d,
- 0x0e94, 0x0e97,
- 0x0e99, 0x0e9f,
- 0x0ea1, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ea7,
- 0x0eaa, 0x0eab,
- 0x0ead, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f71, 0x0f97,
- 0x0f99, 0x0fbc,
- 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, 0x13f4,
- 0x1400, 0x169c,
- 0x16a0, 0x16f8,
- 0x1700, 0x170c,
- 0x170e, 0x1714,
- 0x1720, 0x1736,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17dd,
- 0x17e0, 0x17e9,
- 0x17f0, 0x17f9,
- 0x1800, 0x180e,
- 0x1810, 0x1819,
- 0x1820, 0x1877,
- 0x1880, 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, 0x1abe,
- 0x1b00, 0x1b4b,
- 0x1b50, 0x1b7c,
- 0x1b80, 0x1bf3,
- 0x1bfc, 0x1c37,
- 0x1c3b, 0x1c49,
- 0x1c4d, 0x1c7f,
- 0x1cc0, 0x1cc7,
- 0x1cd0, 0x1cf6,
- 0x1cf8, 0x1cf9,
- 0x1d00, 0x1df5,
- 0x1dfc, 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, 0x20bd,
- 0x20d0, 0x20f0,
- 0x2100, 0x2189,
- 0x2190, 0x23fa,
- 0x2400, 0x2426,
- 0x2440, 0x244a,
- 0x2460, 0x2b73,
- 0x2b76, 0x2b95,
- 0x2b98, 0x2bb9,
- 0x2bbd, 0x2bc8,
- 0x2bca, 0x2bd1,
- 0x2c00, 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, 0x2e42,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x303f,
- 0x3041, 0x3096,
- 0x3099, 0x30ff,
- 0x3105, 0x312d,
- 0x3131, 0x318e,
- 0x3190, 0x31ba,
- 0x31c0, 0x31e3,
- 0x31f0, 0x321e,
- 0x3220, 0x32fe,
- 0x3300, 0x4db5,
- 0x4dc0, 0x9fcc,
- 0xa000, 0xa48c,
- 0xa490, 0xa4c6,
- 0xa4d0, 0xa62b,
- 0xa640, 0xa69d,
- 0xa69f, 0xa6f7,
- 0xa700, 0xa78e,
- 0xa790, 0xa7ad,
- 0xa7b0, 0xa7b1,
- 0xa7f7, 0xa82b,
- 0xa830, 0xa839,
- 0xa840, 0xa877,
- 0xa880, 0xa8c4,
- 0xa8ce, 0xa8d9,
- 0xa8e0, 0xa8fb,
- 0xa900, 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, 0xab5f,
- 0xab64, 0xab65,
- 0xabc0, 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, 0xfe2d,
- 0xfe30, 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, 0x1018c,
- 0x10190, 0x1019b,
- 0x101a0, 0x101a0,
- 0x101d0, 0x101fd,
- 0x10280, 0x1029c,
- 0x102a0, 0x102d0,
- 0x102e0, 0x102fb,
- 0x10300, 0x10323,
- 0x10330, 0x1034a,
- 0x10350, 0x1037a,
- 0x10380, 0x1039d,
- 0x1039f, 0x103c3,
- 0x103c8, 0x103d5,
- 0x10400, 0x1049d,
- 0x104a0, 0x104a9,
- 0x10500, 0x10527,
- 0x10530, 0x10563,
- 0x1056f, 0x1056f,
- 0x10600, 0x10736,
- 0x10740, 0x10755,
- 0x10760, 0x10767,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x10855,
- 0x10857, 0x1089e,
- 0x108a7, 0x108af,
- 0x10900, 0x1091b,
- 0x1091f, 0x10939,
- 0x1093f, 0x1093f,
- 0x10980, 0x109b7,
- 0x109be, 0x109bf,
- 0x10a00, 0x10a03,
- 0x10a05, 0x10a06,
- 0x10a0c, 0x10a13,
- 0x10a15, 0x10a17,
- 0x10a19, 0x10a33,
- 0x10a38, 0x10a3a,
- 0x10a3f, 0x10a47,
- 0x10a50, 0x10a58,
- 0x10a60, 0x10a9f,
- 0x10ac0, 0x10ae6,
- 0x10aeb, 0x10af6,
- 0x10b00, 0x10b35,
- 0x10b39, 0x10b55,
- 0x10b58, 0x10b72,
- 0x10b78, 0x10b91,
- 0x10b99, 0x10b9c,
- 0x10ba9, 0x10baf,
- 0x10c00, 0x10c48,
- 0x10e60, 0x10e7e,
- 0x11000, 0x1104d,
- 0x11052, 0x1106f,
- 0x1107f, 0x110c1,
- 0x110d0, 0x110e8,
- 0x110f0, 0x110f9,
- 0x11100, 0x11134,
- 0x11136, 0x11143,
- 0x11150, 0x11176,
- 0x11180, 0x111c8,
- 0x111cd, 0x111cd,
- 0x111d0, 0x111da,
- 0x111e1, 0x111f4,
- 0x11200, 0x11211,
- 0x11213, 0x1123d,
- 0x112b0, 0x112ea,
- 0x112f0, 0x112f9,
- 0x11301, 0x11303,
- 0x11305, 0x1130c,
- 0x1130f, 0x11310,
- 0x11313, 0x11328,
- 0x1132a, 0x11330,
- 0x11332, 0x11333,
- 0x11335, 0x11339,
- 0x1133c, 0x11344,
- 0x11347, 0x11348,
- 0x1134b, 0x1134d,
- 0x11357, 0x11357,
- 0x1135d, 0x11363,
- 0x11366, 0x1136c,
- 0x11370, 0x11374,
- 0x11480, 0x114c7,
- 0x114d0, 0x114d9,
- 0x11580, 0x115b5,
- 0x115b8, 0x115c9,
- 0x11600, 0x11644,
- 0x11650, 0x11659,
- 0x11680, 0x116b7,
- 0x116c0, 0x116c9,
- 0x118a0, 0x118f2,
- 0x118ff, 0x118ff,
- 0x11ac0, 0x11af8,
- 0x12000, 0x12398,
- 0x12400, 0x1246e,
- 0x12470, 0x12474,
- 0x13000, 0x1342e,
- 0x16800, 0x16a38,
- 0x16a40, 0x16a5e,
- 0x16a60, 0x16a69,
- 0x16a6e, 0x16a6f,
- 0x16ad0, 0x16aed,
- 0x16af0, 0x16af5,
- 0x16b00, 0x16b45,
- 0x16b50, 0x16b59,
- 0x16b5b, 0x16b61,
- 0x16b63, 0x16b77,
- 0x16b7d, 0x16b8f,
- 0x16f00, 0x16f44,
- 0x16f50, 0x16f7e,
- 0x16f8f, 0x16f9f,
- 0x1b000, 0x1b001,
- 0x1bc00, 0x1bc6a,
- 0x1bc70, 0x1bc7c,
- 0x1bc80, 0x1bc88,
- 0x1bc90, 0x1bc99,
- 0x1bc9c, 0x1bca3,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d129, 0x1d1dd,
- 0x1d200, 0x1d245,
- 0x1d300, 0x1d356,
- 0x1d360, 0x1d371,
- 0x1d400, 0x1d454,
- 0x1d456, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 0x1d4a2, 0x1d4a2,
- 0x1d4a5, 0x1d4a6,
- 0x1d4a9, 0x1d4ac,
- 0x1d4ae, 0x1d4b9,
- 0x1d4bb, 0x1d4bb,
- 0x1d4bd, 0x1d4c3,
- 0x1d4c5, 0x1d505,
- 0x1d507, 0x1d50a,
- 0x1d50d, 0x1d514,
- 0x1d516, 0x1d51c,
- 0x1d51e, 0x1d539,
- 0x1d53b, 0x1d53e,
- 0x1d540, 0x1d544,
- 0x1d546, 0x1d546,
- 0x1d54a, 0x1d550,
- 0x1d552, 0x1d6a5,
- 0x1d6a8, 0x1d7cb,
- 0x1d7ce, 0x1d7ff,
- 0x1e800, 0x1e8c4,
- 0x1e8c7, 0x1e8d6,
- 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, 0x1f10c,
- 0x1f110, 0x1f12e,
- 0x1f130, 0x1f16b,
- 0x1f170, 0x1f19a,
- 0x1f1e6, 0x1f202,
- 0x1f210, 0x1f23a,
- 0x1f240, 0x1f248,
- 0x1f250, 0x1f251,
- 0x1f300, 0x1f32c,
- 0x1f330, 0x1f37d,
- 0x1f380, 0x1f3ce,
- 0x1f3d4, 0x1f3f7,
- 0x1f400, 0x1f4fe,
- 0x1f500, 0x1f54a,
- 0x1f550, 0x1f579,
- 0x1f57b, 0x1f5a3,
- 0x1f5a5, 0x1f642,
- 0x1f645, 0x1f6cf,
- 0x1f6e0, 0x1f6ec,
- 0x1f6f0, 0x1f6f3,
- 0x1f700, 0x1f773,
- 0x1f780, 0x1f7d4,
- 0x1f800, 0x1f80b,
- 0x1f810, 0x1f847,
- 0x1f850, 0x1f859,
- 0x1f860, 0x1f887,
- 0x1f890, 0x1f8ad,
- 0x1fffe, 0x2a6d6,
- 0x2a700, 0x2b734,
- 0x2b740, 0x2b81d,
- 0x2f800, 0x2fa1d,
- 0x2fffe, 0x2ffff,
- 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_7_0 */
-
-/* 'Age_8_0': Derived Age 8.0 */
-static const OnigCodePoint CR_Age_8_0[] = {
- 623,
- 0x0000, 0x0377,
- 0x037a, 0x037f,
- 0x0384, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x052f,
- 0x0531, 0x0556,
- 0x0559, 0x055f,
- 0x0561, 0x0587,
- 0x0589, 0x058a,
- 0x058d, 0x058f,
- 0x0591, 0x05c7,
- 0x05d0, 0x05ea,
- 0x05f0, 0x05f4,
- 0x0600, 0x061c,
- 0x061e, 0x070d,
- 0x070f, 0x074a,
- 0x074d, 0x07b1,
- 0x07c0, 0x07fa,
- 0x0800, 0x082d,
- 0x0830, 0x083e,
- 0x0840, 0x085b,
- 0x085e, 0x085e,
- 0x08a0, 0x08b4,
- 0x08e3, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fb,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a51, 0x0a51,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a75,
- 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, 0x0af9,
- 0x0b01, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b35, 0x0b39,
- 0x0b3c, 0x0b44,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4d,
- 0x0b56, 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,
- 0x0be6, 0x0bfa,
- 0x0c00, 0x0c03,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c39,
- 0x0c3d, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c58, 0x0c5a,
- 0x0c60, 0x0c63,
- 0x0c66, 0x0c6f,
- 0x0c78, 0x0c7f,
- 0x0c81, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce3,
- 0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
- 0x0d01, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d3a,
- 0x0d3d, 0x0d44,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4e,
- 0x0d57, 0x0d57,
- 0x0d5f, 0x0d63,
- 0x0d66, 0x0d75,
- 0x0d79, 0x0d7f,
- 0x0d82, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0de6, 0x0def,
- 0x0df2, 0x0df4,
- 0x0e01, 0x0e3a,
- 0x0e3f, 0x0e5b,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e87, 0x0e88,
- 0x0e8a, 0x0e8a,
- 0x0e8d, 0x0e8d,
- 0x0e94, 0x0e97,
- 0x0e99, 0x0e9f,
- 0x0ea1, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ea7,
- 0x0eaa, 0x0eab,
- 0x0ead, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f71, 0x0f97,
- 0x0f99, 0x0fbc,
- 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,
- 0x1780, 0x17dd,
- 0x17e0, 0x17e9,
- 0x17f0, 0x17f9,
- 0x1800, 0x180e,
- 0x1810, 0x1819,
- 0x1820, 0x1877,
- 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, 0x1abe,
- 0x1b00, 0x1b4b,
- 0x1b50, 0x1b7c,
- 0x1b80, 0x1bf3,
- 0x1bfc, 0x1c37,
- 0x1c3b, 0x1c49,
- 0x1c4d, 0x1c7f,
- 0x1cc0, 0x1cc7,
- 0x1cd0, 0x1cf6,
- 0x1cf8, 0x1cf9,
- 0x1d00, 0x1df5,
- 0x1dfc, 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, 0x20be,
- 0x20d0, 0x20f0,
- 0x2100, 0x218b,
- 0x2190, 0x23fa,
- 0x2400, 0x2426,
- 0x2440, 0x244a,
- 0x2460, 0x2b73,
- 0x2b76, 0x2b95,
- 0x2b98, 0x2bb9,
- 0x2bbd, 0x2bc8,
- 0x2bca, 0x2bd1,
- 0x2bec, 0x2bef,
- 0x2c00, 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, 0x2e42,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x303f,
- 0x3041, 0x3096,
- 0x3099, 0x30ff,
- 0x3105, 0x312d,
- 0x3131, 0x318e,
- 0x3190, 0x31ba,
- 0x31c0, 0x31e3,
- 0x31f0, 0x321e,
- 0x3220, 0x32fe,
- 0x3300, 0x4db5,
- 0x4dc0, 0x9fd5,
- 0xa000, 0xa48c,
- 0xa490, 0xa4c6,
- 0xa4d0, 0xa62b,
- 0xa640, 0xa6f7,
- 0xa700, 0xa7ad,
- 0xa7b0, 0xa7b7,
- 0xa7f7, 0xa82b,
- 0xa830, 0xa839,
- 0xa840, 0xa877,
- 0xa880, 0xa8c4,
- 0xa8ce, 0xa8d9,
- 0xa8e0, 0xa8fd,
- 0xa900, 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, 0xab65,
- 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, 0x1018c,
- 0x10190, 0x1019b,
- 0x101a0, 0x101a0,
- 0x101d0, 0x101fd,
- 0x10280, 0x1029c,
- 0x102a0, 0x102d0,
- 0x102e0, 0x102fb,
- 0x10300, 0x10323,
- 0x10330, 0x1034a,
- 0x10350, 0x1037a,
- 0x10380, 0x1039d,
- 0x1039f, 0x103c3,
- 0x103c8, 0x103d5,
- 0x10400, 0x1049d,
- 0x104a0, 0x104a9,
- 0x10500, 0x10527,
- 0x10530, 0x10563,
- 0x1056f, 0x1056f,
- 0x10600, 0x10736,
- 0x10740, 0x10755,
- 0x10760, 0x10767,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 0x10837, 0x10838,
- 0x1083c, 0x1083c,
- 0x1083f, 0x10855,
- 0x10857, 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, 0x10a33,
- 0x10a38, 0x10a3a,
- 0x10a3f, 0x10a47,
- 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, 0x10cff,
- 0x10e60, 0x10e7e,
- 0x11000, 0x1104d,
- 0x11052, 0x1106f,
- 0x1107f, 0x110c1,
- 0x110d0, 0x110e8,
- 0x110f0, 0x110f9,
- 0x11100, 0x11134,
- 0x11136, 0x11143,
- 0x11150, 0x11176,
- 0x11180, 0x111cd,
- 0x111d0, 0x111df,
- 0x111e1, 0x111f4,
- 0x11200, 0x11211,
- 0x11213, 0x1123d,
- 0x11280, 0x11286,
- 0x11288, 0x11288,
- 0x1128a, 0x1128d,
- 0x1128f, 0x1129d,
- 0x1129f, 0x112a9,
- 0x112b0, 0x112ea,
- 0x112f0, 0x112f9,
- 0x11300, 0x11303,
- 0x11305, 0x1130c,
- 0x1130f, 0x11310,
- 0x11313, 0x11328,
- 0x1132a, 0x11330,
- 0x11332, 0x11333,
- 0x11335, 0x11339,
- 0x1133c, 0x11344,
- 0x11347, 0x11348,
- 0x1134b, 0x1134d,
- 0x11350, 0x11350,
- 0x11357, 0x11357,
- 0x1135d, 0x11363,
- 0x11366, 0x1136c,
- 0x11370, 0x11374,
- 0x11480, 0x114c7,
- 0x114d0, 0x114d9,
- 0x11580, 0x115b5,
- 0x115b8, 0x115dd,
- 0x11600, 0x11644,
- 0x11650, 0x11659,
- 0x11680, 0x116b7,
- 0x116c0, 0x116c9,
- 0x11700, 0x11719,
- 0x1171d, 0x1172b,
- 0x11730, 0x1173f,
- 0x118a0, 0x118f2,
- 0x118ff, 0x118ff,
- 0x11ac0, 0x11af8,
- 0x12000, 0x12399,
- 0x12400, 0x1246e,
- 0x12470, 0x12474,
- 0x12480, 0x12543,
- 0x13000, 0x1342e,
- 0x14400, 0x14646,
- 0x16800, 0x16a38,
- 0x16a40, 0x16a5e,
- 0x16a60, 0x16a69,
- 0x16a6e, 0x16a6f,
- 0x16ad0, 0x16aed,
- 0x16af0, 0x16af5,
- 0x16b00, 0x16b45,
- 0x16b50, 0x16b59,
- 0x16b5b, 0x16b61,
- 0x16b63, 0x16b77,
- 0x16b7d, 0x16b8f,
- 0x16f00, 0x16f44,
- 0x16f50, 0x16f7e,
- 0x16f8f, 0x16f9f,
- 0x1b000, 0x1b001,
- 0x1bc00, 0x1bc6a,
- 0x1bc70, 0x1bc7c,
- 0x1bc80, 0x1bc88,
- 0x1bc90, 0x1bc99,
- 0x1bc9c, 0x1bca3,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d129, 0x1d1e8,
- 0x1d200, 0x1d245,
- 0x1d300, 0x1d356,
- 0x1d360, 0x1d371,
- 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,
- 0x1e800, 0x1e8c4,
- 0x1e8c7, 0x1e8d6,
- 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, 0x1f10c,
- 0x1f110, 0x1f12e,
- 0x1f130, 0x1f16b,
- 0x1f170, 0x1f19a,
- 0x1f1e6, 0x1f202,
- 0x1f210, 0x1f23a,
- 0x1f240, 0x1f248,
- 0x1f250, 0x1f251,
- 0x1f300, 0x1f579,
- 0x1f57b, 0x1f5a3,
- 0x1f5a5, 0x1f6d0,
- 0x1f6e0, 0x1f6ec,
- 0x1f6f0, 0x1f6f3,
- 0x1f700, 0x1f773,
- 0x1f780, 0x1f7d4,
- 0x1f800, 0x1f80b,
- 0x1f810, 0x1f847,
- 0x1f850, 0x1f859,
- 0x1f860, 0x1f887,
- 0x1f890, 0x1f8ad,
- 0x1f910, 0x1f918,
- 0x1f980, 0x1f984,
- 0x1f9c0, 0x1f9c0,
- 0x1fffe, 0x2a6d6,
- 0x2a700, 0x2b734,
- 0x2b740, 0x2b81d,
- 0x2b820, 0x2cea1,
- 0x2f800, 0x2fa1d,
- 0x2fffe, 0x2ffff,
- 0x3fffe, 0x3ffff,
- 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_8_0 */
-
-/* 'Age_9_0': Derived Age 9.0 */
-static const OnigCodePoint CR_Age_9_0[] = {
- 648,
- 0x0000, 0x0377,
- 0x037a, 0x037f,
- 0x0384, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x052f,
- 0x0531, 0x0556,
- 0x0559, 0x055f,
- 0x0561, 0x0587,
- 0x0589, 0x058a,
- 0x058d, 0x058f,
- 0x0591, 0x05c7,
- 0x05d0, 0x05ea,
- 0x05f0, 0x05f4,
- 0x0600, 0x061c,
- 0x061e, 0x070d,
- 0x070f, 0x074a,
- 0x074d, 0x07b1,
- 0x07c0, 0x07fa,
- 0x0800, 0x082d,
- 0x0830, 0x083e,
- 0x0840, 0x085b,
- 0x085e, 0x085e,
- 0x08a0, 0x08b4,
- 0x08b6, 0x08bd,
- 0x08d4, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fb,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a51, 0x0a51,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a75,
- 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, 0x0af9,
- 0x0b01, 0x0b03,
- 0x0b05, 0x0b0c,
- 0x0b0f, 0x0b10,
- 0x0b13, 0x0b28,
- 0x0b2a, 0x0b30,
- 0x0b32, 0x0b33,
- 0x0b35, 0x0b39,
- 0x0b3c, 0x0b44,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4d,
- 0x0b56, 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,
- 0x0be6, 0x0bfa,
- 0x0c00, 0x0c03,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c39,
- 0x0c3d, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c58, 0x0c5a,
- 0x0c60, 0x0c63,
- 0x0c66, 0x0c6f,
- 0x0c78, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce3,
- 0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
- 0x0d01, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d3a,
- 0x0d3d, 0x0d44,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4f,
- 0x0d54, 0x0d63,
- 0x0d66, 0x0d7f,
- 0x0d82, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0de6, 0x0def,
- 0x0df2, 0x0df4,
- 0x0e01, 0x0e3a,
- 0x0e3f, 0x0e5b,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e87, 0x0e88,
- 0x0e8a, 0x0e8a,
- 0x0e8d, 0x0e8d,
- 0x0e94, 0x0e97,
- 0x0e99, 0x0e9f,
- 0x0ea1, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ea7,
- 0x0eaa, 0x0eab,
- 0x0ead, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f71, 0x0f97,
- 0x0f99, 0x0fbc,
- 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,
- 0x1780, 0x17dd,
- 0x17e0, 0x17e9,
- 0x17f0, 0x17f9,
- 0x1800, 0x180e,
- 0x1810, 0x1819,
- 0x1820, 0x1877,
- 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, 0x1abe,
- 0x1b00, 0x1b4b,
- 0x1b50, 0x1b7c,
- 0x1b80, 0x1bf3,
- 0x1bfc, 0x1c37,
- 0x1c3b, 0x1c49,
- 0x1c4d, 0x1c88,
- 0x1cc0, 0x1cc7,
- 0x1cd0, 0x1cf6,
- 0x1cf8, 0x1cf9,
- 0x1d00, 0x1df5,
- 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, 0x20be,
- 0x20d0, 0x20f0,
- 0x2100, 0x218b,
- 0x2190, 0x23fe,
- 0x2400, 0x2426,
- 0x2440, 0x244a,
- 0x2460, 0x2b73,
- 0x2b76, 0x2b95,
- 0x2b98, 0x2bb9,
- 0x2bbd, 0x2bc8,
- 0x2bca, 0x2bd1,
- 0x2bec, 0x2bef,
- 0x2c00, 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, 0x2e44,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x303f,
- 0x3041, 0x3096,
- 0x3099, 0x30ff,
- 0x3105, 0x312d,
- 0x3131, 0x318e,
- 0x3190, 0x31ba,
- 0x31c0, 0x31e3,
- 0x31f0, 0x321e,
- 0x3220, 0x32fe,
- 0x3300, 0x4db5,
- 0x4dc0, 0x9fd5,
- 0xa000, 0xa48c,
- 0xa490, 0xa4c6,
- 0xa4d0, 0xa62b,
- 0xa640, 0xa6f7,
- 0xa700, 0xa7ae,
- 0xa7b0, 0xa7b7,
- 0xa7f7, 0xa82b,
- 0xa830, 0xa839,
- 0xa840, 0xa877,
- 0xa880, 0xa8c5,
- 0xa8ce, 0xa8d9,
- 0xa8e0, 0xa8fd,
- 0xa900, 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, 0xab65,
- 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, 0x1019b,
- 0x101a0, 0x101a0,
- 0x101d0, 0x101fd,
- 0x10280, 0x1029c,
- 0x102a0, 0x102d0,
- 0x102e0, 0x102fb,
- 0x10300, 0x10323,
- 0x10330, 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, 0x10a33,
- 0x10a38, 0x10a3a,
- 0x10a3f, 0x10a47,
- 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, 0x10cff,
- 0x10e60, 0x10e7e,
- 0x11000, 0x1104d,
- 0x11052, 0x1106f,
- 0x1107f, 0x110c1,
- 0x110d0, 0x110e8,
- 0x110f0, 0x110f9,
- 0x11100, 0x11134,
- 0x11136, 0x11143,
- 0x11150, 0x11176,
- 0x11180, 0x111cd,
- 0x111d0, 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,
- 0x1133c, 0x11344,
- 0x11347, 0x11348,
- 0x1134b, 0x1134d,
- 0x11350, 0x11350,
- 0x11357, 0x11357,
- 0x1135d, 0x11363,
- 0x11366, 0x1136c,
- 0x11370, 0x11374,
- 0x11400, 0x11459,
- 0x1145b, 0x1145b,
- 0x1145d, 0x1145d,
- 0x11480, 0x114c7,
- 0x114d0, 0x114d9,
- 0x11580, 0x115b5,
- 0x115b8, 0x115dd,
- 0x11600, 0x11644,
- 0x11650, 0x11659,
- 0x11660, 0x1166c,
- 0x11680, 0x116b7,
- 0x116c0, 0x116c9,
- 0x11700, 0x11719,
- 0x1171d, 0x1172b,
- 0x11730, 0x1173f,
- 0x118a0, 0x118f2,
- 0x118ff, 0x118ff,
- 0x11ac0, 0x11af8,
- 0x11c00, 0x11c08,
- 0x11c0a, 0x11c36,
- 0x11c38, 0x11c45,
- 0x11c50, 0x11c6c,
- 0x11c70, 0x11c8f,
- 0x11c92, 0x11ca7,
- 0x11ca9, 0x11cb6,
- 0x12000, 0x12399,
- 0x12400, 0x1246e,
- 0x12470, 0x12474,
- 0x12480, 0x12543,
- 0x13000, 0x1342e,
- 0x14400, 0x14646,
- 0x16800, 0x16a38,
- 0x16a40, 0x16a5e,
- 0x16a60, 0x16a69,
- 0x16a6e, 0x16a6f,
- 0x16ad0, 0x16aed,
- 0x16af0, 0x16af5,
- 0x16b00, 0x16b45,
- 0x16b50, 0x16b59,
- 0x16b5b, 0x16b61,
- 0x16b63, 0x16b77,
- 0x16b7d, 0x16b8f,
- 0x16f00, 0x16f44,
- 0x16f50, 0x16f7e,
- 0x16f8f, 0x16f9f,
- 0x16fe0, 0x16fe0,
- 0x17000, 0x187ec,
- 0x18800, 0x18af2,
- 0x1b000, 0x1b001,
- 0x1bc00, 0x1bc6a,
- 0x1bc70, 0x1bc7c,
- 0x1bc80, 0x1bc88,
- 0x1bc90, 0x1bc99,
- 0x1bc9c, 0x1bca3,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d129, 0x1d1e8,
- 0x1d200, 0x1d245,
- 0x1d300, 0x1d356,
- 0x1d360, 0x1d371,
- 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,
- 0x1e800, 0x1e8c4,
- 0x1e8c7, 0x1e8d6,
- 0x1e900, 0x1e94a,
- 0x1e950, 0x1e959,
- 0x1e95e, 0x1e95f,
- 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, 0x1f10c,
- 0x1f110, 0x1f12e,
- 0x1f130, 0x1f16b,
- 0x1f170, 0x1f1ac,
- 0x1f1e6, 0x1f202,
- 0x1f210, 0x1f23b,
- 0x1f240, 0x1f248,
- 0x1f250, 0x1f251,
- 0x1f300, 0x1f6d2,
- 0x1f6e0, 0x1f6ec,
- 0x1f6f0, 0x1f6f6,
- 0x1f700, 0x1f773,
- 0x1f780, 0x1f7d4,
- 0x1f800, 0x1f80b,
- 0x1f810, 0x1f847,
- 0x1f850, 0x1f859,
- 0x1f860, 0x1f887,
- 0x1f890, 0x1f8ad,
- 0x1f910, 0x1f91e,
- 0x1f920, 0x1f927,
- 0x1f930, 0x1f930,
- 0x1f933, 0x1f93e,
- 0x1f940, 0x1f94b,
- 0x1f950, 0x1f95e,
- 0x1f980, 0x1f991,
- 0x1f9c0, 0x1f9c0,
- 0x1fffe, 0x2a6d6,
- 0x2a700, 0x2b734,
- 0x2b740, 0x2b81d,
- 0x2b820, 0x2cea1,
- 0x2f800, 0x2fa1d,
- 0x2fffe, 0x2ffff,
- 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_9_0 */
-
-/* 'Age_10_0': Derived Age 10.0 */
-static const OnigCodePoint CR_Age_10_0[] = {
- 659,
- 0x0000, 0x0377,
- 0x037a, 0x037f,
- 0x0384, 0x038a,
- 0x038c, 0x038c,
- 0x038e, 0x03a1,
- 0x03a3, 0x052f,
- 0x0531, 0x0556,
- 0x0559, 0x055f,
- 0x0561, 0x0587,
- 0x0589, 0x058a,
- 0x058d, 0x058f,
- 0x0591, 0x05c7,
- 0x05d0, 0x05ea,
- 0x05f0, 0x05f4,
- 0x0600, 0x061c,
- 0x061e, 0x070d,
- 0x070f, 0x074a,
- 0x074d, 0x07b1,
- 0x07c0, 0x07fa,
- 0x0800, 0x082d,
- 0x0830, 0x083e,
- 0x0840, 0x085b,
- 0x085e, 0x085e,
- 0x0860, 0x086a,
- 0x08a0, 0x08b4,
- 0x08b6, 0x08bd,
- 0x08d4, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fd,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a51, 0x0a51,
- 0x0a59, 0x0a5c,
- 0x0a5e, 0x0a5e,
- 0x0a66, 0x0a75,
- 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,
- 0x0b56, 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,
- 0x0be6, 0x0bfa,
- 0x0c00, 0x0c03,
- 0x0c05, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c39,
- 0x0c3d, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c58, 0x0c5a,
- 0x0c60, 0x0c63,
- 0x0c66, 0x0c6f,
- 0x0c78, 0x0c83,
- 0x0c85, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce3,
- 0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
- 0x0d00, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d44,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4f,
- 0x0d54, 0x0d63,
- 0x0d66, 0x0d7f,
- 0x0d82, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0de6, 0x0def,
- 0x0df2, 0x0df4,
- 0x0e01, 0x0e3a,
- 0x0e3f, 0x0e5b,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e87, 0x0e88,
- 0x0e8a, 0x0e8a,
- 0x0e8d, 0x0e8d,
- 0x0e94, 0x0e97,
- 0x0e99, 0x0e9f,
- 0x0ea1, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ea7,
- 0x0eaa, 0x0eab,
- 0x0ead, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f71, 0x0f97,
- 0x0f99, 0x0fbc,
- 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,
- 0x1780, 0x17dd,
- 0x17e0, 0x17e9,
- 0x17f0, 0x17f9,
- 0x1800, 0x180e,
- 0x1810, 0x1819,
- 0x1820, 0x1877,
- 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, 0x1abe,
- 0x1b00, 0x1b4b,
- 0x1b50, 0x1b7c,
- 0x1b80, 0x1bf3,
- 0x1bfc, 0x1c37,
- 0x1c3b, 0x1c49,
- 0x1c4d, 0x1c88,
- 0x1cc0, 0x1cc7,
- 0x1cd0, 0x1cf9,
- 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,
- 0x2b98, 0x2bb9,
- 0x2bbd, 0x2bc8,
- 0x2bca, 0x2bd2,
- 0x2bec, 0x2bef,
- 0x2c00, 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, 0x2e49,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x303f,
- 0x3041, 0x3096,
- 0x3099, 0x30ff,
- 0x3105, 0x312e,
- 0x3131, 0x318e,
- 0x3190, 0x31ba,
- 0x31c0, 0x31e3,
- 0x31f0, 0x321e,
- 0x3220, 0x32fe,
- 0x3300, 0x4db5,
- 0x4dc0, 0x9fea,
- 0xa000, 0xa48c,
- 0xa490, 0xa4c6,
- 0xa4d0, 0xa62b,
- 0xa640, 0xa6f7,
- 0xa700, 0xa7ae,
- 0xa7b0, 0xa7b7,
- 0xa7f7, 0xa82b,
- 0xa830, 0xa839,
- 0xa840, 0xa877,
- 0xa880, 0xa8c5,
- 0xa8ce, 0xa8d9,
- 0xa8e0, 0xa8fd,
- 0xa900, 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, 0xab65,
- 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, 0x1019b,
- 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, 0x10a33,
- 0x10a38, 0x10a3a,
- 0x10a3f, 0x10a47,
- 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, 0x10cff,
- 0x10e60, 0x10e7e,
- 0x11000, 0x1104d,
- 0x11052, 0x1106f,
- 0x1107f, 0x110c1,
- 0x110d0, 0x110e8,
- 0x110f0, 0x110f9,
- 0x11100, 0x11134,
- 0x11136, 0x11143,
- 0x11150, 0x11176,
- 0x11180, 0x111cd,
- 0x111d0, 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,
- 0x1133c, 0x11344,
- 0x11347, 0x11348,
- 0x1134b, 0x1134d,
- 0x11350, 0x11350,
- 0x11357, 0x11357,
- 0x1135d, 0x11363,
- 0x11366, 0x1136c,
- 0x11370, 0x11374,
- 0x11400, 0x11459,
- 0x1145b, 0x1145b,
- 0x1145d, 0x1145d,
- 0x11480, 0x114c7,
- 0x114d0, 0x114d9,
- 0x11580, 0x115b5,
- 0x115b8, 0x115dd,
- 0x11600, 0x11644,
- 0x11650, 0x11659,
- 0x11660, 0x1166c,
- 0x11680, 0x116b7,
- 0x116c0, 0x116c9,
- 0x11700, 0x11719,
- 0x1171d, 0x1172b,
- 0x11730, 0x1173f,
- 0x118a0, 0x118f2,
- 0x118ff, 0x118ff,
- 0x11a00, 0x11a47,
- 0x11a50, 0x11a83,
- 0x11a86, 0x11a9c,
- 0x11a9e, 0x11aa2,
- 0x11ac0, 0x11af8,
- 0x11c00, 0x11c08,
- 0x11c0a, 0x11c36,
- 0x11c38, 0x11c45,
- 0x11c50, 0x11c6c,
- 0x11c70, 0x11c8f,
- 0x11c92, 0x11ca7,
- 0x11ca9, 0x11cb6,
- 0x11d00, 0x11d06,
- 0x11d08, 0x11d09,
- 0x11d0b, 0x11d36,
- 0x11d3a, 0x11d3a,
- 0x11d3c, 0x11d3d,
- 0x11d3f, 0x11d47,
- 0x11d50, 0x11d59,
- 0x12000, 0x12399,
- 0x12400, 0x1246e,
- 0x12470, 0x12474,
- 0x12480, 0x12543,
- 0x13000, 0x1342e,
- 0x14400, 0x14646,
- 0x16800, 0x16a38,
- 0x16a40, 0x16a5e,
- 0x16a60, 0x16a69,
- 0x16a6e, 0x16a6f,
- 0x16ad0, 0x16aed,
- 0x16af0, 0x16af5,
- 0x16b00, 0x16b45,
- 0x16b50, 0x16b59,
- 0x16b5b, 0x16b61,
- 0x16b63, 0x16b77,
- 0x16b7d, 0x16b8f,
- 0x16f00, 0x16f44,
- 0x16f50, 0x16f7e,
- 0x16f8f, 0x16f9f,
- 0x16fe0, 0x16fe1,
- 0x17000, 0x187ec,
- 0x18800, 0x18af2,
- 0x1b000, 0x1b11e,
- 0x1b170, 0x1b2fb,
- 0x1bc00, 0x1bc6a,
- 0x1bc70, 0x1bc7c,
- 0x1bc80, 0x1bc88,
- 0x1bc90, 0x1bc99,
- 0x1bc9c, 0x1bca3,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d129, 0x1d1e8,
- 0x1d200, 0x1d245,
- 0x1d300, 0x1d356,
- 0x1d360, 0x1d371,
- 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,
- 0x1e800, 0x1e8c4,
- 0x1e8c7, 0x1e8d6,
- 0x1e900, 0x1e94a,
- 0x1e950, 0x1e959,
- 0x1e95e, 0x1e95f,
- 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, 0x1f10c,
- 0x1f110, 0x1f12e,
- 0x1f130, 0x1f16b,
- 0x1f170, 0x1f1ac,
- 0x1f1e6, 0x1f202,
- 0x1f210, 0x1f23b,
- 0x1f240, 0x1f248,
- 0x1f250, 0x1f251,
- 0x1f260, 0x1f265,
- 0x1f300, 0x1f6d4,
- 0x1f6e0, 0x1f6ec,
- 0x1f6f0, 0x1f6f8,
- 0x1f700, 0x1f773,
- 0x1f780, 0x1f7d4,
- 0x1f800, 0x1f80b,
- 0x1f810, 0x1f847,
- 0x1f850, 0x1f859,
- 0x1f860, 0x1f887,
- 0x1f890, 0x1f8ad,
- 0x1f900, 0x1f90b,
- 0x1f910, 0x1f93e,
- 0x1f940, 0x1f94c,
- 0x1f950, 0x1f96b,
- 0x1f980, 0x1f997,
- 0x1f9c0, 0x1f9c0,
- 0x1f9d0, 0x1f9e6,
- 0x1fffe, 0x2a6d6,
- 0x2a700, 0x2b734,
- 0x2b740, 0x2b81d,
- 0x2b820, 0x2cea1,
- 0x2ceb0, 0x2ebe0,
- 0x2f800, 0x2fa1d,
- 0x2fffe, 0x2ffff,
- 0x3fffe, 0x3ffff,
- 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_10_0 */
-
-/* 'Age_11_0': Derived Age 11.0 */
-static const OnigCodePoint CR_Age_11_0[] = {
- 668,
- 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, 0x08bd,
- 0x08d3, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fe,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a51, 0x0a51,
- 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,
- 0x0b56, 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,
- 0x0be6, 0x0bfa,
- 0x0c00, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c39,
- 0x0c3d, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c58, 0x0c5a,
- 0x0c60, 0x0c63,
- 0x0c66, 0x0c6f,
- 0x0c78, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce3,
- 0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
- 0x0d00, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d44,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4f,
- 0x0d54, 0x0d63,
- 0x0d66, 0x0d7f,
- 0x0d82, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 0x0dd8, 0x0ddf,
- 0x0de6, 0x0def,
- 0x0df2, 0x0df4,
- 0x0e01, 0x0e3a,
- 0x0e3f, 0x0e5b,
- 0x0e81, 0x0e82,
- 0x0e84, 0x0e84,
- 0x0e87, 0x0e88,
- 0x0e8a, 0x0e8a,
- 0x0e8d, 0x0e8d,
- 0x0e94, 0x0e97,
- 0x0e99, 0x0e9f,
- 0x0ea1, 0x0ea3,
- 0x0ea5, 0x0ea5,
- 0x0ea7, 0x0ea7,
- 0x0eaa, 0x0eab,
- 0x0ead, 0x0eb9,
- 0x0ebb, 0x0ebd,
- 0x0ec0, 0x0ec4,
- 0x0ec6, 0x0ec6,
- 0x0ec8, 0x0ecd,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f71, 0x0f97,
- 0x0f99, 0x0fbc,
- 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,
- 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, 0x1abe,
- 0x1b00, 0x1b4b,
- 0x1b50, 0x1b7c,
- 0x1b80, 0x1bf3,
- 0x1bfc, 0x1c37,
- 0x1c3b, 0x1c49,
- 0x1c4d, 0x1c88,
- 0x1c90, 0x1cba,
- 0x1cbd, 0x1cc7,
- 0x1cd0, 0x1cf9,
- 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,
- 0x2b98, 0x2bc8,
- 0x2bca, 0x2bfe,
- 0x2c00, 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, 0x2e4e,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x303f,
- 0x3041, 0x3096,
- 0x3099, 0x30ff,
- 0x3105, 0x312f,
- 0x3131, 0x318e,
- 0x3190, 0x31ba,
- 0x31c0, 0x31e3,
- 0x31f0, 0x321e,
- 0x3220, 0x32fe,
- 0x3300, 0x4db5,
- 0x4dc0, 0x9fef,
- 0xa000, 0xa48c,
- 0xa490, 0xa4c6,
- 0xa4d0, 0xa62b,
- 0xa640, 0xa6f7,
- 0xa700, 0xa7b9,
- 0xa7f7, 0xa82b,
- 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, 0xab65,
- 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, 0x1019b,
- 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,
- 0x10f00, 0x10f27,
- 0x10f30, 0x10f59,
- 0x11000, 0x1104d,
- 0x11052, 0x1106f,
- 0x1107f, 0x110c1,
- 0x110cd, 0x110cd,
- 0x110d0, 0x110e8,
- 0x110f0, 0x110f9,
- 0x11100, 0x11134,
- 0x11136, 0x11146,
- 0x11150, 0x11176,
- 0x11180, 0x111cd,
- 0x111d0, 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, 0x11459,
- 0x1145b, 0x1145b,
- 0x1145d, 0x1145e,
- 0x11480, 0x114c7,
- 0x114d0, 0x114d9,
- 0x11580, 0x115b5,
- 0x115b8, 0x115dd,
- 0x11600, 0x11644,
- 0x11650, 0x11659,
- 0x11660, 0x1166c,
- 0x11680, 0x116b7,
- 0x116c0, 0x116c9,
- 0x11700, 0x1171a,
- 0x1171d, 0x1172b,
- 0x11730, 0x1173f,
- 0x11800, 0x1183b,
- 0x118a0, 0x118f2,
- 0x118ff, 0x118ff,
- 0x11a00, 0x11a47,
- 0x11a50, 0x11a83,
- 0x11a86, 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,
- 0x12000, 0x12399,
- 0x12400, 0x1246e,
- 0x12470, 0x12474,
- 0x12480, 0x12543,
- 0x13000, 0x1342e,
- 0x14400, 0x14646,
- 0x16800, 0x16a38,
- 0x16a40, 0x16a5e,
- 0x16a60, 0x16a69,
- 0x16a6e, 0x16a6f,
- 0x16ad0, 0x16aed,
- 0x16af0, 0x16af5,
- 0x16b00, 0x16b45,
- 0x16b50, 0x16b59,
- 0x16b5b, 0x16b61,
- 0x16b63, 0x16b77,
- 0x16b7d, 0x16b8f,
- 0x16e40, 0x16e9a,
- 0x16f00, 0x16f44,
- 0x16f50, 0x16f7e,
- 0x16f8f, 0x16f9f,
- 0x16fe0, 0x16fe1,
- 0x17000, 0x187f1,
- 0x18800, 0x18af2,
- 0x1b000, 0x1b11e,
- 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,
- 0x1e800, 0x1e8c4,
- 0x1e8c7, 0x1e8d6,
- 0x1e900, 0x1e94a,
- 0x1e950, 0x1e959,
- 0x1e95e, 0x1e95f,
- 0x1ec71, 0x1ecb4,
- 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, 0x1f10c,
- 0x1f110, 0x1f16b,
- 0x1f170, 0x1f1ac,
- 0x1f1e6, 0x1f202,
- 0x1f210, 0x1f23b,
- 0x1f240, 0x1f248,
- 0x1f250, 0x1f251,
- 0x1f260, 0x1f265,
- 0x1f300, 0x1f6d4,
- 0x1f6e0, 0x1f6ec,
- 0x1f6f0, 0x1f6f9,
- 0x1f700, 0x1f773,
- 0x1f780, 0x1f7d8,
- 0x1f800, 0x1f80b,
- 0x1f810, 0x1f847,
- 0x1f850, 0x1f859,
- 0x1f860, 0x1f887,
- 0x1f890, 0x1f8ad,
- 0x1f900, 0x1f90b,
- 0x1f910, 0x1f93e,
- 0x1f940, 0x1f970,
- 0x1f973, 0x1f976,
- 0x1f97a, 0x1f97a,
- 0x1f97c, 0x1f9a2,
- 0x1f9b0, 0x1f9b9,
- 0x1f9c0, 0x1f9c2,
- 0x1f9d0, 0x1f9ff,
- 0x1fa60, 0x1fa6d,
- 0x1fffe, 0x2a6d6,
- 0x2a700, 0x2b734,
- 0x2b740, 0x2b81d,
- 0x2b820, 0x2cea1,
- 0x2ceb0, 0x2ebe0,
- 0x2f800, 0x2fa1d,
- 0x2fffe, 0x2ffff,
- 0x3fffe, 0x3ffff,
- 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_11_0 */
-
-/* 'Age_12_0': Derived Age 12.0 */
-static const OnigCodePoint CR_Age_12_0[] = {
- 677,
- 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, 0x08bd,
- 0x08d3, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fe,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a51, 0x0a51,
- 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,
- 0x0b56, 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,
- 0x0be6, 0x0bfa,
- 0x0c00, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c39,
- 0x0c3d, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c58, 0x0c5a,
- 0x0c60, 0x0c63,
- 0x0c66, 0x0c6f,
- 0x0c77, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce3,
- 0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
- 0x0d00, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d44,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4f,
- 0x0d54, 0x0d63,
- 0x0d66, 0x0d7f,
- 0x0d82, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 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,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f71, 0x0f97,
- 0x0f99, 0x0fbc,
- 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,
- 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, 0x1abe,
- 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,
- 0x2b98, 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, 0x2e4f,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x303f,
- 0x3041, 0x3096,
- 0x3099, 0x30ff,
- 0x3105, 0x312f,
- 0x3131, 0x318e,
- 0x3190, 0x31ba,
- 0x31c0, 0x31e3,
- 0x31f0, 0x321e,
- 0x3220, 0x32fe,
- 0x3300, 0x4db5,
- 0x4dc0, 0x9fef,
- 0xa000, 0xa48c,
- 0xa490, 0xa4c6,
- 0xa4d0, 0xa62b,
- 0xa640, 0xa6f7,
- 0xa700, 0xa7bf,
- 0xa7c2, 0xa7c6,
- 0xa7f7, 0xa82b,
- 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, 0xab67,
- 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, 0x1019b,
- 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,
- 0x10f00, 0x10f27,
- 0x10f30, 0x10f59,
- 0x10fe0, 0x10ff6,
- 0x11000, 0x1104d,
- 0x11052, 0x1106f,
- 0x1107f, 0x110c1,
- 0x110cd, 0x110cd,
- 0x110d0, 0x110e8,
- 0x110f0, 0x110f9,
- 0x11100, 0x11134,
- 0x11136, 0x11146,
- 0x11150, 0x11176,
- 0x11180, 0x111cd,
- 0x111d0, 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, 0x11459,
- 0x1145b, 0x1145b,
- 0x1145d, 0x1145f,
- 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, 0x118ff,
- 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,
- 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, 0x16fe3,
- 0x17000, 0x187f7,
- 0x18800, 0x18af2,
- 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, 0x1f10c,
- 0x1f110, 0x1f16c,
- 0x1f170, 0x1f1ac,
- 0x1f1e6, 0x1f202,
- 0x1f210, 0x1f23b,
- 0x1f240, 0x1f248,
- 0x1f250, 0x1f251,
- 0x1f260, 0x1f265,
- 0x1f300, 0x1f6d5,
- 0x1f6e0, 0x1f6ec,
- 0x1f6f0, 0x1f6fa,
- 0x1f700, 0x1f773,
- 0x1f780, 0x1f7d8,
- 0x1f7e0, 0x1f7eb,
- 0x1f800, 0x1f80b,
- 0x1f810, 0x1f847,
- 0x1f850, 0x1f859,
- 0x1f860, 0x1f887,
- 0x1f890, 0x1f8ad,
- 0x1f900, 0x1f90b,
- 0x1f90d, 0x1f971,
- 0x1f973, 0x1f976,
- 0x1f97a, 0x1f9a2,
- 0x1f9a5, 0x1f9aa,
- 0x1f9ae, 0x1f9ca,
- 0x1f9cd, 0x1fa53,
- 0x1fa60, 0x1fa6d,
- 0x1fa70, 0x1fa73,
- 0x1fa78, 0x1fa7a,
- 0x1fa80, 0x1fa82,
- 0x1fa90, 0x1fa95,
- 0x1fffe, 0x2a6d6,
- 0x2a700, 0x2b734,
- 0x2b740, 0x2b81d,
- 0x2b820, 0x2cea1,
- 0x2ceb0, 0x2ebe0,
- 0x2f800, 0x2fa1d,
- 0x2fffe, 0x2ffff,
- 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_12_0 */
-
-/* 'Age_12_1': Derived Age 12.1 */
-static const OnigCodePoint CR_Age_12_1[] = {
- 676,
- 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, 0x08bd,
- 0x08d3, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fe,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a51, 0x0a51,
- 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,
- 0x0b56, 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,
- 0x0be6, 0x0bfa,
- 0x0c00, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c39,
- 0x0c3d, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c58, 0x0c5a,
- 0x0c60, 0x0c63,
- 0x0c66, 0x0c6f,
- 0x0c77, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cde, 0x0cde,
- 0x0ce0, 0x0ce3,
- 0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf2,
- 0x0d00, 0x0d03,
- 0x0d05, 0x0d0c,
- 0x0d0e, 0x0d10,
- 0x0d12, 0x0d44,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4f,
- 0x0d54, 0x0d63,
- 0x0d66, 0x0d7f,
- 0x0d82, 0x0d83,
- 0x0d85, 0x0d96,
- 0x0d9a, 0x0db1,
- 0x0db3, 0x0dbb,
- 0x0dbd, 0x0dbd,
- 0x0dc0, 0x0dc6,
- 0x0dca, 0x0dca,
- 0x0dcf, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 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,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f71, 0x0f97,
- 0x0f99, 0x0fbc,
- 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,
- 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, 0x1abe,
- 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,
- 0x2b98, 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, 0x2e4f,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x303f,
- 0x3041, 0x3096,
- 0x3099, 0x30ff,
- 0x3105, 0x312f,
- 0x3131, 0x318e,
- 0x3190, 0x31ba,
- 0x31c0, 0x31e3,
- 0x31f0, 0x321e,
- 0x3220, 0x4db5,
- 0x4dc0, 0x9fef,
- 0xa000, 0xa48c,
- 0xa490, 0xa4c6,
- 0xa4d0, 0xa62b,
- 0xa640, 0xa6f7,
- 0xa700, 0xa7bf,
- 0xa7c2, 0xa7c6,
- 0xa7f7, 0xa82b,
- 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, 0xab67,
- 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, 0x1019b,
- 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,
- 0x10f00, 0x10f27,
- 0x10f30, 0x10f59,
- 0x10fe0, 0x10ff6,
- 0x11000, 0x1104d,
- 0x11052, 0x1106f,
- 0x1107f, 0x110c1,
- 0x110cd, 0x110cd,
- 0x110d0, 0x110e8,
- 0x110f0, 0x110f9,
- 0x11100, 0x11134,
- 0x11136, 0x11146,
- 0x11150, 0x11176,
- 0x11180, 0x111cd,
- 0x111d0, 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, 0x11459,
- 0x1145b, 0x1145b,
- 0x1145d, 0x1145f,
- 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, 0x118ff,
- 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,
- 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, 0x16fe3,
- 0x17000, 0x187f7,
- 0x18800, 0x18af2,
- 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, 0x1f10c,
- 0x1f110, 0x1f16c,
- 0x1f170, 0x1f1ac,
- 0x1f1e6, 0x1f202,
- 0x1f210, 0x1f23b,
- 0x1f240, 0x1f248,
- 0x1f250, 0x1f251,
- 0x1f260, 0x1f265,
- 0x1f300, 0x1f6d5,
- 0x1f6e0, 0x1f6ec,
- 0x1f6f0, 0x1f6fa,
- 0x1f700, 0x1f773,
- 0x1f780, 0x1f7d8,
- 0x1f7e0, 0x1f7eb,
- 0x1f800, 0x1f80b,
- 0x1f810, 0x1f847,
- 0x1f850, 0x1f859,
- 0x1f860, 0x1f887,
- 0x1f890, 0x1f8ad,
- 0x1f900, 0x1f90b,
- 0x1f90d, 0x1f971,
- 0x1f973, 0x1f976,
- 0x1f97a, 0x1f9a2,
- 0x1f9a5, 0x1f9aa,
- 0x1f9ae, 0x1f9ca,
- 0x1f9cd, 0x1fa53,
- 0x1fa60, 0x1fa6d,
- 0x1fa70, 0x1fa73,
- 0x1fa78, 0x1fa7a,
- 0x1fa80, 0x1fa82,
- 0x1fa90, 0x1fa95,
- 0x1fffe, 0x2a6d6,
- 0x2a700, 0x2b734,
- 0x2b740, 0x2b81d,
- 0x2b820, 0x2cea1,
- 0x2ceb0, 0x2ebe0,
- 0x2f800, 0x2fa1d,
- 0x2fffe, 0x2ffff,
- 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_12_1 */
-
-/* '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,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fe,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a51, 0x0a51,
- 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,
- 0x0be6, 0x0bfa,
- 0x0c00, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c39,
- 0x0c3d, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c58, 0x0c5a,
- 0x0c60, 0x0c63,
- 0x0c66, 0x0c6f,
- 0x0c77, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 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, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 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,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f71, 0x0f97,
- 0x0f99, 0x0fbc,
- 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,
- 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 */
-
-/* 'Age_14_0': Derived Age 14.0 */
-static const OnigCodePoint CR_Age_14_0[] = {
- 706,
- 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, 0x070d,
- 0x070f, 0x074a,
- 0x074d, 0x07b1,
- 0x07c0, 0x07fa,
- 0x07fd, 0x082d,
- 0x0830, 0x083e,
- 0x0840, 0x085b,
- 0x085e, 0x085e,
- 0x0860, 0x086a,
- 0x0870, 0x088e,
- 0x0890, 0x0891,
- 0x0898, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fe,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a51, 0x0a51,
- 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,
- 0x0be6, 0x0bfa,
- 0x0c00, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c39,
- 0x0c3c, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c58, 0x0c5a,
- 0x0c5d, 0x0c5d,
- 0x0c60, 0x0c63,
- 0x0c66, 0x0c6f,
- 0x0c77, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cdd, 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, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 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,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f71, 0x0f97,
- 0x0f99, 0x0fbc,
- 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, 0x1715,
- 0x171f, 0x1736,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17dd,
- 0x17e0, 0x17e9,
- 0x17f0, 0x17f9,
- 0x1800, 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, 0x1ace,
- 0x1b00, 0x1b4c,
- 0x1b50, 0x1b7e,
- 0x1b80, 0x1bf3,
- 0x1bfc, 0x1c37,
- 0x1c3b, 0x1c49,
- 0x1c4d, 0x1c88,
- 0x1c90, 0x1cba,
- 0x1cbd, 0x1cc7,
- 0x1cd0, 0x1cfa,
- 0x1d00, 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, 0x20c0,
- 0x20d0, 0x20f0,
- 0x2100, 0x218b,
- 0x2190, 0x2426,
- 0x2440, 0x244a,
- 0x2460, 0x2b73,
- 0x2b76, 0x2b95,
- 0x2b97, 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, 0x2e5d,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x303f,
- 0x3041, 0x3096,
- 0x3099, 0x30ff,
- 0x3105, 0x312f,
- 0x3131, 0x318e,
- 0x3190, 0x31e3,
- 0x31f0, 0x321e,
- 0x3220, 0xa48c,
- 0xa490, 0xa4c6,
- 0xa4d0, 0xa62b,
- 0xa640, 0xa6f7,
- 0xa700, 0xa7ca,
- 0xa7d0, 0xa7d1,
- 0xa7d3, 0xa7d3,
- 0xa7d5, 0xa7d9,
- 0xa7f2, 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, 0xfbc2,
- 0xfbd3, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdcf, 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, 0x1057a,
- 0x1057c, 0x1058a,
- 0x1058c, 0x10592,
- 0x10594, 0x10595,
- 0x10597, 0x105a1,
- 0x105a3, 0x105b1,
- 0x105b3, 0x105b9,
- 0x105bb, 0x105bc,
- 0x10600, 0x10736,
- 0x10740, 0x10755,
- 0x10760, 0x10767,
- 0x10780, 0x10785,
- 0x10787, 0x107b0,
- 0x107b2, 0x107ba,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 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,
- 0x10f70, 0x10f89,
- 0x10fb0, 0x10fcb,
- 0x10fe0, 0x10ff6,
- 0x11000, 0x1104d,
- 0x11052, 0x11075,
- 0x1107f, 0x110c2,
- 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, 0x116b9,
- 0x116c0, 0x116c9,
- 0x11700, 0x1171a,
- 0x1171d, 0x1172b,
- 0x11730, 0x11746,
- 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,
- 0x11ab0, 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,
- 0x12f90, 0x12ff2,
- 0x13000, 0x1342e,
- 0x13430, 0x13438,
- 0x14400, 0x14646,
- 0x16800, 0x16a38,
- 0x16a40, 0x16a5e,
- 0x16a60, 0x16a69,
- 0x16a6e, 0x16abe,
- 0x16ac0, 0x16ac9,
- 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,
- 0x1aff0, 0x1aff3,
- 0x1aff5, 0x1affb,
- 0x1affd, 0x1affe,
- 0x1b000, 0x1b122,
- 0x1b150, 0x1b152,
- 0x1b164, 0x1b167,
- 0x1b170, 0x1b2fb,
- 0x1bc00, 0x1bc6a,
- 0x1bc70, 0x1bc7c,
- 0x1bc80, 0x1bc88,
- 0x1bc90, 0x1bc99,
- 0x1bc9c, 0x1bca3,
- 0x1cf00, 0x1cf2d,
- 0x1cf30, 0x1cf46,
- 0x1cf50, 0x1cfc3,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d129, 0x1d1ea,
- 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,
- 0x1df00, 0x1df1e,
- 0x1e000, 0x1e006,
- 0x1e008, 0x1e018,
- 0x1e01b, 0x1e021,
- 0x1e023, 0x1e024,
- 0x1e026, 0x1e02a,
- 0x1e100, 0x1e12c,
- 0x1e130, 0x1e13d,
- 0x1e140, 0x1e149,
- 0x1e14e, 0x1e14f,
- 0x1e290, 0x1e2ae,
- 0x1e2c0, 0x1e2f9,
- 0x1e2ff, 0x1e2ff,
- 0x1e7e0, 0x1e7e6,
- 0x1e7e8, 0x1e7eb,
- 0x1e7ed, 0x1e7ee,
- 0x1e7f0, 0x1e7fe,
- 0x1e800, 0x1e8c4,
- 0x1e8c7, 0x1e8d6,
- 0x1e900, 0x1e94b,
- 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,
- 0x1f6dd, 0x1f6ec,
- 0x1f6f0, 0x1f6fc,
- 0x1f700, 0x1f773,
- 0x1f780, 0x1f7d8,
- 0x1f7e0, 0x1f7eb,
- 0x1f7f0, 0x1f7f0,
- 0x1f800, 0x1f80b,
- 0x1f810, 0x1f847,
- 0x1f850, 0x1f859,
- 0x1f860, 0x1f887,
- 0x1f890, 0x1f8ad,
- 0x1f8b0, 0x1f8b1,
- 0x1f900, 0x1fa53,
- 0x1fa60, 0x1fa6d,
- 0x1fa70, 0x1fa74,
- 0x1fa78, 0x1fa7c,
- 0x1fa80, 0x1fa86,
- 0x1fa90, 0x1faac,
- 0x1fab0, 0x1faba,
- 0x1fac0, 0x1fac5,
- 0x1fad0, 0x1fad9,
- 0x1fae0, 0x1fae7,
- 0x1faf0, 0x1faf6,
- 0x1fb00, 0x1fb92,
- 0x1fb94, 0x1fbca,
- 0x1fbf0, 0x1fbf9,
- 0x1fffe, 0x2a6df,
- 0x2a700, 0x2b738,
- 0x2b740, 0x2b81d,
- 0x2b820, 0x2cea1,
- 0x2ceb0, 0x2ebe0,
- 0x2f800, 0x2fa1d,
- 0x2fffe, 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_14_0 */
-
-/* 'Age_15_0': Derived Age 15.0 */
-static const OnigCodePoint CR_Age_15_0[] = {
- 715,
- 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, 0x070d,
- 0x070f, 0x074a,
- 0x074d, 0x07b1,
- 0x07c0, 0x07fa,
- 0x07fd, 0x082d,
- 0x0830, 0x083e,
- 0x0840, 0x085b,
- 0x085e, 0x085e,
- 0x0860, 0x086a,
- 0x0870, 0x088e,
- 0x0890, 0x0891,
- 0x0898, 0x0983,
- 0x0985, 0x098c,
- 0x098f, 0x0990,
- 0x0993, 0x09a8,
- 0x09aa, 0x09b0,
- 0x09b2, 0x09b2,
- 0x09b6, 0x09b9,
- 0x09bc, 0x09c4,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09ce,
- 0x09d7, 0x09d7,
- 0x09dc, 0x09dd,
- 0x09df, 0x09e3,
- 0x09e6, 0x09fe,
- 0x0a01, 0x0a03,
- 0x0a05, 0x0a0a,
- 0x0a0f, 0x0a10,
- 0x0a13, 0x0a28,
- 0x0a2a, 0x0a30,
- 0x0a32, 0x0a33,
- 0x0a35, 0x0a36,
- 0x0a38, 0x0a39,
- 0x0a3c, 0x0a3c,
- 0x0a3e, 0x0a42,
- 0x0a47, 0x0a48,
- 0x0a4b, 0x0a4d,
- 0x0a51, 0x0a51,
- 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,
- 0x0be6, 0x0bfa,
- 0x0c00, 0x0c0c,
- 0x0c0e, 0x0c10,
- 0x0c12, 0x0c28,
- 0x0c2a, 0x0c39,
- 0x0c3c, 0x0c44,
- 0x0c46, 0x0c48,
- 0x0c4a, 0x0c4d,
- 0x0c55, 0x0c56,
- 0x0c58, 0x0c5a,
- 0x0c5d, 0x0c5d,
- 0x0c60, 0x0c63,
- 0x0c66, 0x0c6f,
- 0x0c77, 0x0c8c,
- 0x0c8e, 0x0c90,
- 0x0c92, 0x0ca8,
- 0x0caa, 0x0cb3,
- 0x0cb5, 0x0cb9,
- 0x0cbc, 0x0cc4,
- 0x0cc6, 0x0cc8,
- 0x0cca, 0x0ccd,
- 0x0cd5, 0x0cd6,
- 0x0cdd, 0x0cde,
- 0x0ce0, 0x0ce3,
- 0x0ce6, 0x0cef,
- 0x0cf1, 0x0cf3,
- 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, 0x0dd4,
- 0x0dd6, 0x0dd6,
- 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, 0x0ece,
- 0x0ed0, 0x0ed9,
- 0x0edc, 0x0edf,
- 0x0f00, 0x0f47,
- 0x0f49, 0x0f6c,
- 0x0f71, 0x0f97,
- 0x0f99, 0x0fbc,
- 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, 0x1715,
- 0x171f, 0x1736,
- 0x1740, 0x1753,
- 0x1760, 0x176c,
- 0x176e, 0x1770,
- 0x1772, 0x1773,
- 0x1780, 0x17dd,
- 0x17e0, 0x17e9,
- 0x17f0, 0x17f9,
- 0x1800, 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, 0x1ace,
- 0x1b00, 0x1b4c,
- 0x1b50, 0x1b7e,
- 0x1b80, 0x1bf3,
- 0x1bfc, 0x1c37,
- 0x1c3b, 0x1c49,
- 0x1c4d, 0x1c88,
- 0x1c90, 0x1cba,
- 0x1cbd, 0x1cc7,
- 0x1cd0, 0x1cfa,
- 0x1d00, 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, 0x20c0,
- 0x20d0, 0x20f0,
- 0x2100, 0x218b,
- 0x2190, 0x2426,
- 0x2440, 0x244a,
- 0x2460, 0x2b73,
- 0x2b76, 0x2b95,
- 0x2b97, 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, 0x2e5d,
- 0x2e80, 0x2e99,
- 0x2e9b, 0x2ef3,
- 0x2f00, 0x2fd5,
- 0x2ff0, 0x2ffb,
- 0x3000, 0x303f,
- 0x3041, 0x3096,
- 0x3099, 0x30ff,
- 0x3105, 0x312f,
- 0x3131, 0x318e,
- 0x3190, 0x31e3,
- 0x31f0, 0x321e,
- 0x3220, 0xa48c,
- 0xa490, 0xa4c6,
- 0xa4d0, 0xa62b,
- 0xa640, 0xa6f7,
- 0xa700, 0xa7ca,
- 0xa7d0, 0xa7d1,
- 0xa7d3, 0xa7d3,
- 0xa7d5, 0xa7d9,
- 0xa7f2, 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, 0xfbc2,
- 0xfbd3, 0xfd8f,
- 0xfd92, 0xfdc7,
- 0xfdcf, 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, 0x1057a,
- 0x1057c, 0x1058a,
- 0x1058c, 0x10592,
- 0x10594, 0x10595,
- 0x10597, 0x105a1,
- 0x105a3, 0x105b1,
- 0x105b3, 0x105b9,
- 0x105bb, 0x105bc,
- 0x10600, 0x10736,
- 0x10740, 0x10755,
- 0x10760, 0x10767,
- 0x10780, 0x10785,
- 0x10787, 0x107b0,
- 0x107b2, 0x107ba,
- 0x10800, 0x10805,
- 0x10808, 0x10808,
- 0x1080a, 0x10835,
- 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,
- 0x10efd, 0x10f27,
- 0x10f30, 0x10f59,
- 0x10f70, 0x10f89,
- 0x10fb0, 0x10fcb,
- 0x10fe0, 0x10ff6,
- 0x11000, 0x1104d,
- 0x11052, 0x11075,
- 0x1107f, 0x110c2,
- 0x110cd, 0x110cd,
- 0x110d0, 0x110e8,
- 0x110f0, 0x110f9,
- 0x11100, 0x11134,
- 0x11136, 0x11147,
- 0x11150, 0x11176,
- 0x11180, 0x111df,
- 0x111e1, 0x111f4,
- 0x11200, 0x11211,
- 0x11213, 0x11241,
- 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, 0x116b9,
- 0x116c0, 0x116c9,
- 0x11700, 0x1171a,
- 0x1171d, 0x1172b,
- 0x11730, 0x11746,
- 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,
- 0x11ab0, 0x11af8,
- 0x11b00, 0x11b09,
- 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,
- 0x11f00, 0x11f10,
- 0x11f12, 0x11f3a,
- 0x11f3e, 0x11f59,
- 0x11fb0, 0x11fb0,
- 0x11fc0, 0x11ff1,
- 0x11fff, 0x12399,
- 0x12400, 0x1246e,
- 0x12470, 0x12474,
- 0x12480, 0x12543,
- 0x12f90, 0x12ff2,
- 0x13000, 0x13455,
- 0x14400, 0x14646,
- 0x16800, 0x16a38,
- 0x16a40, 0x16a5e,
- 0x16a60, 0x16a69,
- 0x16a6e, 0x16abe,
- 0x16ac0, 0x16ac9,
- 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,
- 0x1aff0, 0x1aff3,
- 0x1aff5, 0x1affb,
- 0x1affd, 0x1affe,
- 0x1b000, 0x1b122,
- 0x1b132, 0x1b132,
- 0x1b150, 0x1b152,
- 0x1b155, 0x1b155,
- 0x1b164, 0x1b167,
- 0x1b170, 0x1b2fb,
- 0x1bc00, 0x1bc6a,
- 0x1bc70, 0x1bc7c,
- 0x1bc80, 0x1bc88,
- 0x1bc90, 0x1bc99,
- 0x1bc9c, 0x1bca3,
- 0x1cf00, 0x1cf2d,
- 0x1cf30, 0x1cf46,
- 0x1cf50, 0x1cfc3,
- 0x1d000, 0x1d0f5,
- 0x1d100, 0x1d126,
- 0x1d129, 0x1d1ea,
- 0x1d200, 0x1d245,
- 0x1d2c0, 0x1d2d3,
- 0x1d2e0, 0x1d2f3,
- 0x1d300, 0x1d356,
- 0x1d360, 0x1d378,
- 0x1d400, 0x1d454,
- 0x1d456, 0x1d49c,
- 0x1d49e, 0x1d49f,
- 0x1d4a2, 0x1d4a2,
- 0x1d4a5, 0x1d4a6,
- 0x1d4a9, 0x1d4ac,
- 0x1d4ae, 0x1d4b9,
- 0x1d4bb, 0x1d4bb,
- 0x1d4bd, 0x1d4c3,
- 0x1d4c5, 0x1d505,
- 0x1d507, 0x1d50a,
- 0x1d50d, 0x1d514,
- 0x1d516, 0x1d51c,
- 0x1d51e, 0x1d539,
- 0x1d53b, 0x1d53e,
- 0x1d540, 0x1d544,
- 0x1d546, 0x1d546,
- 0x1d54a, 0x1d550,
- 0x1d552, 0x1d6a5,
- 0x1d6a8, 0x1d7cb,
- 0x1d7ce, 0x1da8b,
- 0x1da9b, 0x1da9f,
- 0x1daa1, 0x1daaf,
- 0x1df00, 0x1df1e,
- 0x1df25, 0x1df2a,
- 0x1e000, 0x1e006,
- 0x1e008, 0x1e018,
- 0x1e01b, 0x1e021,
- 0x1e023, 0x1e024,
- 0x1e026, 0x1e02a,
- 0x1e030, 0x1e06d,
- 0x1e08f, 0x1e08f,
- 0x1e100, 0x1e12c,
- 0x1e130, 0x1e13d,
- 0x1e140, 0x1e149,
- 0x1e14e, 0x1e14f,
- 0x1e290, 0x1e2ae,
- 0x1e2c0, 0x1e2f9,
- 0x1e2ff, 0x1e2ff,
- 0x1e4d0, 0x1e4f9,
- 0x1e7e0, 0x1e7e6,
- 0x1e7e8, 0x1e7eb,
- 0x1e7ed, 0x1e7ee,
- 0x1e7f0, 0x1e7fe,
- 0x1e800, 0x1e8c4,
- 0x1e8c7, 0x1e8d6,
- 0x1e900, 0x1e94b,
- 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,
- 0x1f6dc, 0x1f6ec,
- 0x1f6f0, 0x1f6fc,
- 0x1f700, 0x1f776,
- 0x1f77b, 0x1f7d9,
- 0x1f7e0, 0x1f7eb,
- 0x1f7f0, 0x1f7f0,
- 0x1f800, 0x1f80b,
- 0x1f810, 0x1f847,
- 0x1f850, 0x1f859,
- 0x1f860, 0x1f887,
- 0x1f890, 0x1f8ad,
- 0x1f8b0, 0x1f8b1,
- 0x1f900, 0x1fa53,
- 0x1fa60, 0x1fa6d,
- 0x1fa70, 0x1fa7c,
- 0x1fa80, 0x1fa88,
- 0x1fa90, 0x1fabd,
- 0x1fabf, 0x1fac5,
- 0x1face, 0x1fadb,
- 0x1fae0, 0x1fae8,
- 0x1faf0, 0x1faf8,
- 0x1fb00, 0x1fb92,
- 0x1fb94, 0x1fbca,
- 0x1fbf0, 0x1fbf9,
- 0x1fffe, 0x2a6df,
- 0x2a700, 0x2b739,
- 0x2b740, 0x2b81d,
- 0x2b820, 0x2cea1,
- 0x2ceb0, 0x2ebe0,
- 0x2f800, 0x2fa1d,
- 0x2fffe, 0x3134a,
- 0x31350, 0x323af,
- 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_15_0 */
-
-#endif /* USE_UNICODE_AGE_PROPERTIES */
-/* 'Grapheme_Cluster_Break_Prepend': Grapheme_Cluster_Break=Prepend */
-static const OnigCodePoint CR_Grapheme_Cluster_Break_Prepend[] = {
- 15,
- 0x0600, 0x0605,
- 0x06dd, 0x06dd,
- 0x070f, 0x070f,
- 0x0890, 0x0891,
- 0x08e2, 0x08e2,
- 0x0d4e, 0x0d4e,
- 0x110bd, 0x110bd,
- 0x110cd, 0x110cd,
- 0x111c2, 0x111c3,
- 0x1193f, 0x1193f,
- 0x11941, 0x11941,
- 0x11a3a, 0x11a3a,
- 0x11a84, 0x11a89,
- 0x11d46, 0x11d46,
- 0x11f02, 0x11f02,
-}; /* 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, 0x1343f,
- 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[] = {
- 364,
- 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,
- 0x0898, 0x089f,
- 0x08ca, 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,
- 0x0c3c, 0x0c3c,
- 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, 0x0ece,
- 0x0f18, 0x0f19,
- 0x0f35, 0x0f35,
- 0x0f37, 0x0f37,
- 0x0f39, 0x0f39,
- 0x0f71, 0x0f7e,
- 0x0f80, 0x0f84,
- 0x0f86, 0x0f87,
- 0x0f8d, 0x0f97,
- 0x0f99, 0x0fbc,
- 0x0fc6, 0x0fc6,
- 0x102d, 0x1030,
- 0x1032, 0x1037,
- 0x1039, 0x103a,
- 0x103d, 0x103e,
- 0x1058, 0x1059,
- 0x105e, 0x1060,
- 0x1071, 0x1074,
- 0x1082, 0x1082,
- 0x1085, 0x1086,
- 0x108d, 0x108d,
- 0x109d, 0x109d,
- 0x135d, 0x135f,
- 0x1712, 0x1714,
- 0x1732, 0x1733,
- 0x1752, 0x1753,
- 0x1772, 0x1773,
- 0x17b4, 0x17b5,
- 0x17b7, 0x17bd,
- 0x17c6, 0x17c6,
- 0x17c9, 0x17d3,
- 0x17dd, 0x17dd,
- 0x180b, 0x180d,
- 0x180f, 0x180f,
- 0x1885, 0x1886,
- 0x18a9, 0x18a9,
- 0x1920, 0x1922,
- 0x1927, 0x1928,
- 0x1932, 0x1932,
- 0x1939, 0x193b,
- 0x1a17, 0x1a18,
- 0x1a1b, 0x1a1b,
- 0x1a56, 0x1a56,
- 0x1a58, 0x1a5e,
- 0x1a60, 0x1a60,
- 0x1a62, 0x1a62,
- 0x1a65, 0x1a6c,
- 0x1a73, 0x1a7c,
- 0x1a7f, 0x1a7f,
- 0x1ab0, 0x1ace,
- 0x1b00, 0x1b03,
- 0x1b34, 0x1b3a,
- 0x1b3c, 0x1b3c,
- 0x1b42, 0x1b42,
- 0x1b6b, 0x1b73,
- 0x1b80, 0x1b81,
- 0x1ba2, 0x1ba5,
- 0x1ba8, 0x1ba9,
- 0x1bab, 0x1bad,
- 0x1be6, 0x1be6,
- 0x1be8, 0x1be9,
- 0x1bed, 0x1bed,
- 0x1bef, 0x1bf1,
- 0x1c2c, 0x1c33,
- 0x1c36, 0x1c37,
- 0x1cd0, 0x1cd2,
- 0x1cd4, 0x1ce0,
- 0x1ce2, 0x1ce8,
- 0x1ced, 0x1ced,
- 0x1cf4, 0x1cf4,
- 0x1cf8, 0x1cf9,
- 0x1dc0, 0x1dff,
- 0x200c, 0x200c,
- 0x20d0, 0x20f0,
- 0x2cef, 0x2cf1,
- 0x2d7f, 0x2d7f,
- 0x2de0, 0x2dff,
- 0x302a, 0x302f,
- 0x3099, 0x309a,
- 0xa66f, 0xa672,
- 0xa674, 0xa67d,
- 0xa69e, 0xa69f,
- 0xa6f0, 0xa6f1,
- 0xa802, 0xa802,
- 0xa806, 0xa806,
- 0xa80b, 0xa80b,
- 0xa825, 0xa826,
- 0xa82c, 0xa82c,
- 0xa8c4, 0xa8c5,
- 0xa8e0, 0xa8f1,
- 0xa8ff, 0xa8ff,
- 0xa926, 0xa92d,
- 0xa947, 0xa951,
- 0xa980, 0xa982,
- 0xa9b3, 0xa9b3,
- 0xa9b6, 0xa9b9,
- 0xa9bc, 0xa9bd,
- 0xa9e5, 0xa9e5,
- 0xaa29, 0xaa2e,
- 0xaa31, 0xaa32,
- 0xaa35, 0xaa36,
- 0xaa43, 0xaa43,
- 0xaa4c, 0xaa4c,
- 0xaa7c, 0xaa7c,
- 0xaab0, 0xaab0,
- 0xaab2, 0xaab4,
- 0xaab7, 0xaab8,
- 0xaabe, 0xaabf,
- 0xaac1, 0xaac1,
- 0xaaec, 0xaaed,
- 0xaaf6, 0xaaf6,
- 0xabe5, 0xabe5,
- 0xabe8, 0xabe8,
- 0xabed, 0xabed,
- 0xfb1e, 0xfb1e,
- 0xfe00, 0xfe0f,
- 0xfe20, 0xfe2f,
- 0xff9e, 0xff9f,
- 0x101fd, 0x101fd,
- 0x102e0, 0x102e0,
- 0x10376, 0x1037a,
- 0x10a01, 0x10a03,
- 0x10a05, 0x10a06,
- 0x10a0c, 0x10a0f,
- 0x10a38, 0x10a3a,
- 0x10a3f, 0x10a3f,
- 0x10ae5, 0x10ae6,
- 0x10d24, 0x10d27,
- 0x10eab, 0x10eac,
- 0x10efd, 0x10eff,
- 0x10f46, 0x10f50,
- 0x10f82, 0x10f85,
- 0x11001, 0x11001,
- 0x11038, 0x11046,
- 0x11070, 0x11070,
- 0x11073, 0x11074,
- 0x1107f, 0x11081,
- 0x110b3, 0x110b6,
- 0x110b9, 0x110ba,
- 0x110c2, 0x110c2,
- 0x11100, 0x11102,
- 0x11127, 0x1112b,
- 0x1112d, 0x11134,
- 0x11173, 0x11173,
- 0x11180, 0x11181,
- 0x111b6, 0x111be,
- 0x111c9, 0x111cc,
- 0x111cf, 0x111cf,
- 0x1122f, 0x11231,
- 0x11234, 0x11234,
- 0x11236, 0x11237,
- 0x1123e, 0x1123e,
- 0x11241, 0x11241,
- 0x112df, 0x112df,
- 0x112e3, 0x112ea,
- 0x11300, 0x11301,
- 0x1133b, 0x1133c,
- 0x1133e, 0x1133e,
- 0x11340, 0x11340,
- 0x11357, 0x11357,
- 0x11366, 0x1136c,
- 0x11370, 0x11374,
- 0x11438, 0x1143f,
- 0x11442, 0x11444,
- 0x11446, 0x11446,
- 0x1145e, 0x1145e,
- 0x114b0, 0x114b0,
- 0x114b3, 0x114b8,
- 0x114ba, 0x114ba,
- 0x114bd, 0x114bd,
- 0x114bf, 0x114c0,
- 0x114c2, 0x114c3,
- 0x115af, 0x115af,
- 0x115b2, 0x115b5,
- 0x115bc, 0x115bd,
- 0x115bf, 0x115c0,
- 0x115dc, 0x115dd,
- 0x11633, 0x1163a,
- 0x1163d, 0x1163d,
- 0x1163f, 0x11640,
- 0x116ab, 0x116ab,
- 0x116ad, 0x116ad,
- 0x116b0, 0x116b5,
- 0x116b7, 0x116b7,
- 0x1171d, 0x1171f,
- 0x11722, 0x11725,
- 0x11727, 0x1172b,
- 0x1182f, 0x11837,
- 0x11839, 0x1183a,
- 0x11930, 0x11930,
- 0x1193b, 0x1193c,
- 0x1193e, 0x1193e,
- 0x11943, 0x11943,
- 0x119d4, 0x119d7,
- 0x119da, 0x119db,
- 0x119e0, 0x119e0,
- 0x11a01, 0x11a0a,
- 0x11a33, 0x11a38,
- 0x11a3b, 0x11a3e,
- 0x11a47, 0x11a47,
- 0x11a51, 0x11a56,
- 0x11a59, 0x11a5b,
- 0x11a8a, 0x11a96,
- 0x11a98, 0x11a99,
- 0x11c30, 0x11c36,
- 0x11c38, 0x11c3d,
- 0x11c3f, 0x11c3f,
- 0x11c92, 0x11ca7,
- 0x11caa, 0x11cb0,
- 0x11cb2, 0x11cb3,
- 0x11cb5, 0x11cb6,
- 0x11d31, 0x11d36,
- 0x11d3a, 0x11d3a,
- 0x11d3c, 0x11d3d,
- 0x11d3f, 0x11d45,
- 0x11d47, 0x11d47,
- 0x11d90, 0x11d91,
- 0x11d95, 0x11d95,
- 0x11d97, 0x11d97,
- 0x11ef3, 0x11ef4,
- 0x11f00, 0x11f01,
- 0x11f36, 0x11f3a,
- 0x11f40, 0x11f40,
- 0x11f42, 0x11f42,
- 0x13440, 0x13440,
- 0x13447, 0x13455,
- 0x16af0, 0x16af4,
- 0x16b30, 0x16b36,
- 0x16f4f, 0x16f4f,
- 0x16f8f, 0x16f92,
- 0x16fe4, 0x16fe4,
- 0x1bc9d, 0x1bc9e,
- 0x1cf00, 0x1cf2d,
- 0x1cf30, 0x1cf46,
- 0x1d165, 0x1d165,
- 0x1d167, 0x1d169,
- 0x1d16e, 0x1d172,
- 0x1d17b, 0x1d182,
- 0x1d185, 0x1d18b,
- 0x1d1aa, 0x1d1ad,
- 0x1d242, 0x1d244,
- 0x1da00, 0x1da36,
- 0x1da3b, 0x1da6c,
- 0x1da75, 0x1da75,
- 0x1da84, 0x1da84,
- 0x1da9b, 0x1da9f,
- 0x1daa1, 0x1daaf,
- 0x1e000, 0x1e006,
- 0x1e008, 0x1e018,
- 0x1e01b, 0x1e021,
- 0x1e023, 0x1e024,
- 0x1e026, 0x1e02a,
- 0x1e08f, 0x1e08f,
- 0x1e130, 0x1e136,
- 0x1e2ae, 0x1e2ae,
- 0x1e2ec, 0x1e2ef,
- 0x1e4ec, 0x1e4ef,
- 0x1e8d0, 0x1e8d6,
- 0x1e944, 0x1e94a,
- 0x1f3fb, 0x1f3ff,
- 0xe0020, 0xe007f,
- 0xe0100, 0xe01ef,
-}; /* CR_Grapheme_Cluster_Break_Extend */
-
-/* 'Grapheme_Cluster_Break_Regional_Indicator': Grapheme_Cluster_Break=Regional_Indicator */
-#define CR_Grapheme_Cluster_Break_Regional_Indicator CR_Regional_Indicator
-
-/* 'Grapheme_Cluster_Break_SpacingMark': Grapheme_Cluster_Break=SpacingMark */
-static const OnigCodePoint CR_Grapheme_Cluster_Break_SpacingMark[] = {
- 165,
- 0x0903, 0x0903,
- 0x093b, 0x093b,
- 0x093e, 0x0940,
- 0x0949, 0x094c,
- 0x094e, 0x094f,
- 0x0982, 0x0983,
- 0x09bf, 0x09c0,
- 0x09c7, 0x09c8,
- 0x09cb, 0x09cc,
- 0x0a03, 0x0a03,
- 0x0a3e, 0x0a40,
- 0x0a83, 0x0a83,
- 0x0abe, 0x0ac0,
- 0x0ac9, 0x0ac9,
- 0x0acb, 0x0acc,
- 0x0b02, 0x0b03,
- 0x0b40, 0x0b40,
- 0x0b47, 0x0b48,
- 0x0b4b, 0x0b4c,
- 0x0bbf, 0x0bbf,
- 0x0bc1, 0x0bc2,
- 0x0bc6, 0x0bc8,
- 0x0bca, 0x0bcc,
- 0x0c01, 0x0c03,
- 0x0c41, 0x0c44,
- 0x0c82, 0x0c83,
- 0x0cbe, 0x0cbe,
- 0x0cc0, 0x0cc1,
- 0x0cc3, 0x0cc4,
- 0x0cc7, 0x0cc8,
- 0x0cca, 0x0ccb,
- 0x0cf3, 0x0cf3,
- 0x0d02, 0x0d03,
- 0x0d3f, 0x0d40,
- 0x0d46, 0x0d48,
- 0x0d4a, 0x0d4c,
- 0x0d82, 0x0d83,
- 0x0dd0, 0x0dd1,
- 0x0dd8, 0x0dde,
- 0x0df2, 0x0df3,
- 0x0e33, 0x0e33,
- 0x0eb3, 0x0eb3,
- 0x0f3e, 0x0f3f,
- 0x0f7f, 0x0f7f,
- 0x1031, 0x1031,
- 0x103b, 0x103c,
- 0x1056, 0x1057,
- 0x1084, 0x1084,
- 0x1715, 0x1715,
- 0x1734, 0x1734,
- 0x17b6, 0x17b6,
- 0x17be, 0x17c5,
- 0x17c7, 0x17c8,
- 0x1923, 0x1926,
- 0x1929, 0x192b,
- 0x1930, 0x1931,
- 0x1933, 0x1938,
- 0x1a19, 0x1a1a,
- 0x1a55, 0x1a55,
- 0x1a57, 0x1a57,
- 0x1a6d, 0x1a72,
- 0x1b04, 0x1b04,
- 0x1b3b, 0x1b3b,
- 0x1b3d, 0x1b41,
- 0x1b43, 0x1b44,
- 0x1b82, 0x1b82,
- 0x1ba1, 0x1ba1,
- 0x1ba6, 0x1ba7,
- 0x1baa, 0x1baa,
- 0x1be7, 0x1be7,
- 0x1bea, 0x1bec,
- 0x1bee, 0x1bee,
- 0x1bf2, 0x1bf3,
- 0x1c24, 0x1c2b,
- 0x1c34, 0x1c35,
- 0x1ce1, 0x1ce1,
- 0x1cf7, 0x1cf7,
- 0xa823, 0xa824,
- 0xa827, 0xa827,
- 0xa880, 0xa881,
- 0xa8b4, 0xa8c3,
- 0xa952, 0xa953,
- 0xa983, 0xa983,
- 0xa9b4, 0xa9b5,
- 0xa9ba, 0xa9bb,
- 0xa9be, 0xa9c0,
- 0xaa2f, 0xaa30,
- 0xaa33, 0xaa34,
- 0xaa4d, 0xaa4d,
- 0xaaeb, 0xaaeb,
- 0xaaee, 0xaaef,
- 0xaaf5, 0xaaf5,
- 0xabe3, 0xabe4,
- 0xabe6, 0xabe7,
- 0xabe9, 0xabea,
- 0xabec, 0xabec,
- 0x11000, 0x11000,
- 0x11002, 0x11002,
- 0x11082, 0x11082,
- 0x110b0, 0x110b2,
- 0x110b7, 0x110b8,
- 0x1112c, 0x1112c,
- 0x11145, 0x11146,
- 0x11182, 0x11182,
- 0x111b3, 0x111b5,
- 0x111bf, 0x111c0,
- 0x111ce, 0x111ce,
- 0x1122c, 0x1122e,
- 0x11232, 0x11233,
- 0x11235, 0x11235,
- 0x112e0, 0x112e2,
- 0x11302, 0x11303,
- 0x1133f, 0x1133f,
- 0x11341, 0x11344,
- 0x11347, 0x11348,
- 0x1134b, 0x1134d,
- 0x11362, 0x11363,
- 0x11435, 0x11437,
- 0x11440, 0x11441,
- 0x11445, 0x11445,
- 0x114b1, 0x114b2,
- 0x114b9, 0x114b9,
- 0x114bb, 0x114bc,
- 0x114be, 0x114be,
- 0x114c1, 0x114c1,
- 0x115b0, 0x115b1,
- 0x115b8, 0x115bb,
- 0x115be, 0x115be,
- 0x11630, 0x11632,
- 0x1163b, 0x1163c,
- 0x1163e, 0x1163e,
- 0x116ac, 0x116ac,
- 0x116ae, 0x116af,
- 0x116b6, 0x116b6,
- 0x11726, 0x11726,
- 0x1182c, 0x1182e,
- 0x11838, 0x11838,
- 0x11931, 0x11935,
- 0x11937, 0x11938,
- 0x1193d, 0x1193d,
- 0x11940, 0x11940,
- 0x11942, 0x11942,
- 0x119d1, 0x119d3,
- 0x119dc, 0x119df,
- 0x119e4, 0x119e4,
- 0x11a39, 0x11a39,
- 0x11a57, 0x11a58,
- 0x11a97, 0x11a97,
- 0x11c2f, 0x11c2f,
- 0x11c3e, 0x11c3e,
- 0x11ca9, 0x11ca9,
- 0x11cb1, 0x11cb1,
- 0x11cb4, 0x11cb4,
- 0x11d8a, 0x11d8e,
- 0x11d93, 0x11d94,
- 0x11d96, 0x11d96,
- 0x11ef5, 0x11ef6,
- 0x11f03, 0x11f03,
- 0x11f34, 0x11f35,
- 0x11f3e, 0x11f3f,
- 0x11f41, 0x11f41,
- 0x16f51, 0x16f87,
- 0x16ff0, 0x16ff1,
- 0x1d166, 0x1d166,
- 0x1d16d, 0x1d16d,
-}; /* CR_Grapheme_Cluster_Break_SpacingMark */
-
-/* 'Grapheme_Cluster_Break_L': Grapheme_Cluster_Break=L */
-static const OnigCodePoint CR_Grapheme_Cluster_Break_L[] = {
- 2,
- 0x1100, 0x115f,
- 0xa960, 0xa97c,
-}; /* CR_Grapheme_Cluster_Break_L */
-
-/* 'Grapheme_Cluster_Break_V': Grapheme_Cluster_Break=V */
-static const OnigCodePoint CR_Grapheme_Cluster_Break_V[] = {
- 2,
- 0x1160, 0x11a7,
- 0xd7b0, 0xd7c6,
-}; /* CR_Grapheme_Cluster_Break_V */
-
-/* 'Grapheme_Cluster_Break_T': Grapheme_Cluster_Break=T */
-static const OnigCodePoint CR_Grapheme_Cluster_Break_T[] = {
- 2,
- 0x11a8, 0x11ff,
- 0xd7cb, 0xd7fb,
-}; /* CR_Grapheme_Cluster_Break_T */
-
-/* 'Grapheme_Cluster_Break_LV': Grapheme_Cluster_Break=LV */
-static const OnigCodePoint CR_Grapheme_Cluster_Break_LV[] = {
- 399,
- 0xac00, 0xac00,
- 0xac1c, 0xac1c,
- 0xac38, 0xac38,
- 0xac54, 0xac54,
- 0xac70, 0xac70,
- 0xac8c, 0xac8c,
- 0xaca8, 0xaca8,
- 0xacc4, 0xacc4,
- 0xace0, 0xace0,
- 0xacfc, 0xacfc,
- 0xad18, 0xad18,
- 0xad34, 0xad34,
- 0xad50, 0xad50,
- 0xad6c, 0xad6c,
- 0xad88, 0xad88,
- 0xada4, 0xada4,
- 0xadc0, 0xadc0,
- 0xaddc, 0xaddc,
- 0xadf8, 0xadf8,
- 0xae14, 0xae14,
- 0xae30, 0xae30,
- 0xae4c, 0xae4c,
- 0xae68, 0xae68,
- 0xae84, 0xae84,
- 0xaea0, 0xaea0,
- 0xaebc, 0xaebc,
- 0xaed8, 0xaed8,
- 0xaef4, 0xaef4,
- 0xaf10, 0xaf10,
- 0xaf2c, 0xaf2c,
- 0xaf48, 0xaf48,
- 0xaf64, 0xaf64,
- 0xaf80, 0xaf80,
- 0xaf9c, 0xaf9c,
- 0xafb8, 0xafb8,
- 0xafd4, 0xafd4,
- 0xaff0, 0xaff0,
- 0xb00c, 0xb00c,
- 0xb028, 0xb028,
- 0xb044, 0xb044,
- 0xb060, 0xb060,
- 0xb07c, 0xb07c,
- 0xb098, 0xb098,
- 0xb0b4, 0xb0b4,
- 0xb0d0, 0xb0d0,
- 0xb0ec, 0xb0ec,
- 0xb108, 0xb108,
- 0xb124, 0xb124,
- 0xb140, 0xb140,
- 0xb15c, 0xb15c,
- 0xb178, 0xb178,
- 0xb194, 0xb194,
- 0xb1b0, 0xb1b0,
- 0xb1cc, 0xb1cc,
- 0xb1e8, 0xb1e8,
- 0xb204, 0xb204,
- 0xb220, 0xb220,
- 0xb23c, 0xb23c,
- 0xb258, 0xb258,
- 0xb274, 0xb274,
- 0xb290, 0xb290,
- 0xb2ac, 0xb2ac,
- 0xb2c8, 0xb2c8,
- 0xb2e4, 0xb2e4,
- 0xb300, 0xb300,
- 0xb31c, 0xb31c,
- 0xb338, 0xb338,
- 0xb354, 0xb354,
- 0xb370, 0xb370,
- 0xb38c, 0xb38c,
- 0xb3a8, 0xb3a8,
- 0xb3c4, 0xb3c4,
- 0xb3e0, 0xb3e0,
- 0xb3fc, 0xb3fc,
- 0xb418, 0xb418,
- 0xb434, 0xb434,
- 0xb450, 0xb450,
- 0xb46c, 0xb46c,
- 0xb488, 0xb488,
- 0xb4a4, 0xb4a4,
- 0xb4c0, 0xb4c0,
- 0xb4dc, 0xb4dc,
- 0xb4f8, 0xb4f8,
- 0xb514, 0xb514,
- 0xb530, 0xb530,
- 0xb54c, 0xb54c,
- 0xb568, 0xb568,
- 0xb584, 0xb584,
- 0xb5a0, 0xb5a0,
- 0xb5bc, 0xb5bc,
- 0xb5d8, 0xb5d8,
- 0xb5f4, 0xb5f4,
- 0xb610, 0xb610,
- 0xb62c, 0xb62c,
- 0xb648, 0xb648,
- 0xb664, 0xb664,
- 0xb680, 0xb680,
- 0xb69c, 0xb69c,
- 0xb6b8, 0xb6b8,
- 0xb6d4, 0xb6d4,
- 0xb6f0, 0xb6f0,
- 0xb70c, 0xb70c,
- 0xb728, 0xb728,
- 0xb744, 0xb744,
- 0xb760, 0xb760,
- 0xb77c, 0xb77c,
- 0xb798, 0xb798,
- 0xb7b4, 0xb7b4,
- 0xb7d0, 0xb7d0,
- 0xb7ec, 0xb7ec,
- 0xb808, 0xb808,
- 0xb824, 0xb824,
- 0xb840, 0xb840,
- 0xb85c, 0xb85c,
- 0xb878, 0xb878,
- 0xb894, 0xb894,
- 0xb8b0, 0xb8b0,
- 0xb8cc, 0xb8cc,
- 0xb8e8, 0xb8e8,
- 0xb904, 0xb904,
- 0xb920, 0xb920,
- 0xb93c, 0xb93c,
- 0xb958, 0xb958,
- 0xb974, 0xb974,
- 0xb990, 0xb990,
- 0xb9ac, 0xb9ac,
- 0xb9c8, 0xb9c8,
- 0xb9e4, 0xb9e4,
- 0xba00, 0xba00,
- 0xba1c, 0xba1c,
- 0xba38, 0xba38,
- 0xba54, 0xba54,
- 0xba70, 0xba70,
- 0xba8c, 0xba8c,
- 0xbaa8, 0xbaa8,
- 0xbac4, 0xbac4,
- 0xbae0, 0xbae0,
- 0xbafc, 0xbafc,
- 0xbb18, 0xbb18,
- 0xbb34, 0xbb34,
- 0xbb50, 0xbb50,
- 0xbb6c, 0xbb6c,
- 0xbb88, 0xbb88,
- 0xbba4, 0xbba4,
- 0xbbc0, 0xbbc0,
- 0xbbdc, 0xbbdc,
- 0xbbf8, 0xbbf8,
- 0xbc14, 0xbc14,
- 0xbc30, 0xbc30,
- 0xbc4c, 0xbc4c,
- 0xbc68, 0xbc68,
- 0xbc84, 0xbc84,
- 0xbca0, 0xbca0,
- 0xbcbc, 0xbcbc,
- 0xbcd8, 0xbcd8,
- 0xbcf4, 0xbcf4,
- 0xbd10, 0xbd10,
- 0xbd2c, 0xbd2c,
- 0xbd48, 0xbd48,
- 0xbd64, 0xbd64,
- 0xbd80, 0xbd80,
- 0xbd9c, 0xbd9c,
- 0xbdb8, 0xbdb8,
- 0xbdd4, 0xbdd4,
- 0xbdf0, 0xbdf0,
- 0xbe0c, 0xbe0c,
- 0xbe28, 0xbe28,
- 0xbe44, 0xbe44,
- 0xbe60, 0xbe60,
- 0xbe7c, 0xbe7c,
- 0xbe98, 0xbe98,
- 0xbeb4, 0xbeb4,
- 0xbed0, 0xbed0,
- 0xbeec, 0xbeec,
- 0xbf08, 0xbf08,
- 0xbf24, 0xbf24,
- 0xbf40, 0xbf40,
- 0xbf5c, 0xbf5c,
- 0xbf78, 0xbf78,
- 0xbf94, 0xbf94,
- 0xbfb0, 0xbfb0,
- 0xbfcc, 0xbfcc,
- 0xbfe8, 0xbfe8,
- 0xc004, 0xc004,
- 0xc020, 0xc020,
- 0xc03c, 0xc03c,
- 0xc058, 0xc058,
- 0xc074, 0xc074,
- 0xc090, 0xc090,
- 0xc0ac, 0xc0ac,
- 0xc0c8, 0xc0c8,
- 0xc0e4, 0xc0e4,
- 0xc100, 0xc100,
- 0xc11c, 0xc11c,
- 0xc138, 0xc138,
- 0xc154, 0xc154,
- 0xc170, 0xc170,
- 0xc18c, 0xc18c,
- 0xc1a8, 0xc1a8,
- 0xc1c4, 0xc1c4,
- 0xc1e0, 0xc1e0,
- 0xc1fc, 0xc1fc,
- 0xc218, 0xc218,
- 0xc234, 0xc234,
- 0xc250, 0xc250,
- 0xc26c, 0xc26c,
- 0xc288, 0xc288,
- 0xc2a4, 0xc2a4,
- 0xc2c0, 0xc2c0,
- 0xc2dc, 0xc2dc,
- 0xc2f8, 0xc2f8,
- 0xc314, 0xc314,
- 0xc330, 0xc330,
- 0xc34c, 0xc34c,
- 0xc368, 0xc368,
- 0xc384, 0xc384,
- 0xc3a0, 0xc3a0,
- 0xc3bc, 0xc3bc,
- 0xc3d8, 0xc3d8,
- 0xc3f4, 0xc3f4,
- 0xc410, 0xc410,
- 0xc42c, 0xc42c,
- 0xc448, 0xc448,
- 0xc464, 0xc464,
- 0xc480, 0xc480,
- 0xc49c, 0xc49c,
- 0xc4b8, 0xc4b8,
- 0xc4d4, 0xc4d4,
- 0xc4f0, 0xc4f0,
- 0xc50c, 0xc50c,
- 0xc528, 0xc528,
- 0xc544, 0xc544,
- 0xc560, 0xc560,
- 0xc57c, 0xc57c,
- 0xc598, 0xc598,
- 0xc5b4, 0xc5b4,
- 0xc5d0, 0xc5d0,
- 0xc5ec, 0xc5ec,
- 0xc608, 0xc608,
- 0xc624, 0xc624,
- 0xc640, 0xc640,
- 0xc65c, 0xc65c,
- 0xc678, 0xc678,
- 0xc694, 0xc694,
- 0xc6b0, 0xc6b0,
- 0xc6cc, 0xc6cc,
- 0xc6e8, 0xc6e8,
- 0xc704, 0xc704,
- 0xc720, 0xc720,
- 0xc73c, 0xc73c,
- 0xc758, 0xc758,
- 0xc774, 0xc774,
- 0xc790, 0xc790,
- 0xc7ac, 0xc7ac,
- 0xc7c8, 0xc7c8,
- 0xc7e4, 0xc7e4,
- 0xc800, 0xc800,
- 0xc81c, 0xc81c,
- 0xc838, 0xc838,
- 0xc854, 0xc854,
- 0xc870, 0xc870,
- 0xc88c, 0xc88c,
- 0xc8a8, 0xc8a8,
- 0xc8c4, 0xc8c4,
- 0xc8e0, 0xc8e0,
- 0xc8fc, 0xc8fc,
- 0xc918, 0xc918,
- 0xc934, 0xc934,
- 0xc950, 0xc950,
- 0xc96c, 0xc96c,
- 0xc988, 0xc988,
- 0xc9a4, 0xc9a4,
- 0xc9c0, 0xc9c0,
- 0xc9dc, 0xc9dc,
- 0xc9f8, 0xc9f8,
- 0xca14, 0xca14,
- 0xca30, 0xca30,
- 0xca4c, 0xca4c,
- 0xca68, 0xca68,
- 0xca84, 0xca84,
- 0xcaa0, 0xcaa0,
- 0xcabc, 0xcabc,
- 0xcad8, 0xcad8,
- 0xcaf4, 0xcaf4,
- 0xcb10, 0xcb10,
- 0xcb2c, 0xcb2c,
- 0xcb48, 0xcb48,
- 0xcb64, 0xcb64,
- 0xcb80, 0xcb80,
- 0xcb9c, 0xcb9c,
- 0xcbb8, 0xcbb8,
- 0xcbd4, 0xcbd4,
- 0xcbf0, 0xcbf0,
- 0xcc0c, 0xcc0c,
- 0xcc28, 0xcc28,
- 0xcc44, 0xcc44,
- 0xcc60, 0xcc60,
- 0xcc7c, 0xcc7c,
- 0xcc98, 0xcc98,
- 0xccb4, 0xccb4,
- 0xccd0, 0xccd0,
- 0xccec, 0xccec,
- 0xcd08, 0xcd08,
- 0xcd24, 0xcd24,
- 0xcd40, 0xcd40,
- 0xcd5c, 0xcd5c,
- 0xcd78, 0xcd78,
- 0xcd94, 0xcd94,
- 0xcdb0, 0xcdb0,
- 0xcdcc, 0xcdcc,
- 0xcde8, 0xcde8,
- 0xce04, 0xce04,
- 0xce20, 0xce20,
- 0xce3c, 0xce3c,
- 0xce58, 0xce58,
- 0xce74, 0xce74,
- 0xce90, 0xce90,
- 0xceac, 0xceac,
- 0xcec8, 0xcec8,
- 0xcee4, 0xcee4,
- 0xcf00, 0xcf00,
- 0xcf1c, 0xcf1c,
- 0xcf38, 0xcf38,
- 0xcf54, 0xcf54,
- 0xcf70, 0xcf70,
- 0xcf8c, 0xcf8c,
- 0xcfa8, 0xcfa8,
- 0xcfc4, 0xcfc4,
- 0xcfe0, 0xcfe0,
- 0xcffc, 0xcffc,
- 0xd018, 0xd018,
- 0xd034, 0xd034,
- 0xd050, 0xd050,
- 0xd06c, 0xd06c,
- 0xd088, 0xd088,
- 0xd0a4, 0xd0a4,
- 0xd0c0, 0xd0c0,
- 0xd0dc, 0xd0dc,
- 0xd0f8, 0xd0f8,
- 0xd114, 0xd114,
- 0xd130, 0xd130,
- 0xd14c, 0xd14c,
- 0xd168, 0xd168,
- 0xd184, 0xd184,
- 0xd1a0, 0xd1a0,
- 0xd1bc, 0xd1bc,
- 0xd1d8, 0xd1d8,
- 0xd1f4, 0xd1f4,
- 0xd210, 0xd210,
- 0xd22c, 0xd22c,
- 0xd248, 0xd248,
- 0xd264, 0xd264,
- 0xd280, 0xd280,
- 0xd29c, 0xd29c,
- 0xd2b8, 0xd2b8,
- 0xd2d4, 0xd2d4,
- 0xd2f0, 0xd2f0,
- 0xd30c, 0xd30c,
- 0xd328, 0xd328,
- 0xd344, 0xd344,
- 0xd360, 0xd360,
- 0xd37c, 0xd37c,
- 0xd398, 0xd398,
- 0xd3b4, 0xd3b4,
- 0xd3d0, 0xd3d0,
- 0xd3ec, 0xd3ec,
- 0xd408, 0xd408,
- 0xd424, 0xd424,
- 0xd440, 0xd440,
- 0xd45c, 0xd45c,
- 0xd478, 0xd478,
- 0xd494, 0xd494,
- 0xd4b0, 0xd4b0,
- 0xd4cc, 0xd4cc,
- 0xd4e8, 0xd4e8,
- 0xd504, 0xd504,
- 0xd520, 0xd520,
- 0xd53c, 0xd53c,
- 0xd558, 0xd558,
- 0xd574, 0xd574,
- 0xd590, 0xd590,
- 0xd5ac, 0xd5ac,
- 0xd5c8, 0xd5c8,
- 0xd5e4, 0xd5e4,
- 0xd600, 0xd600,
- 0xd61c, 0xd61c,
- 0xd638, 0xd638,
- 0xd654, 0xd654,
- 0xd670, 0xd670,
- 0xd68c, 0xd68c,
- 0xd6a8, 0xd6a8,
- 0xd6c4, 0xd6c4,
- 0xd6e0, 0xd6e0,
- 0xd6fc, 0xd6fc,
- 0xd718, 0xd718,
- 0xd734, 0xd734,
- 0xd750, 0xd750,
- 0xd76c, 0xd76c,
- 0xd788, 0xd788,
-}; /* CR_Grapheme_Cluster_Break_LV */
-
-/* 'Grapheme_Cluster_Break_LVT': Grapheme_Cluster_Break=LVT */
-static const OnigCodePoint CR_Grapheme_Cluster_Break_LVT[] = {
- 399,
- 0xac01, 0xac1b,
- 0xac1d, 0xac37,
- 0xac39, 0xac53,
- 0xac55, 0xac6f,
- 0xac71, 0xac8b,
- 0xac8d, 0xaca7,
- 0xaca9, 0xacc3,
- 0xacc5, 0xacdf,
- 0xace1, 0xacfb,
- 0xacfd, 0xad17,
- 0xad19, 0xad33,
- 0xad35, 0xad4f,
- 0xad51, 0xad6b,
- 0xad6d, 0xad87,
- 0xad89, 0xada3,
- 0xada5, 0xadbf,
- 0xadc1, 0xaddb,
- 0xaddd, 0xadf7,
- 0xadf9, 0xae13,
- 0xae15, 0xae2f,
- 0xae31, 0xae4b,
- 0xae4d, 0xae67,
- 0xae69, 0xae83,
- 0xae85, 0xae9f,
- 0xaea1, 0xaebb,
- 0xaebd, 0xaed7,
- 0xaed9, 0xaef3,
- 0xaef5, 0xaf0f,
- 0xaf11, 0xaf2b,
- 0xaf2d, 0xaf47,
- 0xaf49, 0xaf63,
- 0xaf65, 0xaf7f,
- 0xaf81, 0xaf9b,
- 0xaf9d, 0xafb7,
- 0xafb9, 0xafd3,
- 0xafd5, 0xafef,
- 0xaff1, 0xb00b,
- 0xb00d, 0xb027,
- 0xb029, 0xb043,
- 0xb045, 0xb05f,
- 0xb061, 0xb07b,
- 0xb07d, 0xb097,
- 0xb099, 0xb0b3,
- 0xb0b5, 0xb0cf,
- 0xb0d1, 0xb0eb,
- 0xb0ed, 0xb107,
- 0xb109, 0xb123,
- 0xb125, 0xb13f,
- 0xb141, 0xb15b,
- 0xb15d, 0xb177,
- 0xb179, 0xb193,
- 0xb195, 0xb1af,
- 0xb1b1, 0xb1cb,
- 0xb1cd, 0xb1e7,
- 0xb1e9, 0xb203,
- 0xb205, 0xb21f,
- 0xb221, 0xb23b,
- 0xb23d, 0xb257,
- 0xb259, 0xb273,
- 0xb275, 0xb28f,
- 0xb291, 0xb2ab,
- 0xb2ad, 0xb2c7,
- 0xb2c9, 0xb2e3,
- 0xb2e5, 0xb2ff,
- 0xb301, 0xb31b,
- 0xb31d, 0xb337,
- 0xb339, 0xb353,
- 0xb355, 0xb36f,
- 0xb371, 0xb38b,
- 0xb38d, 0xb3a7,
- 0xb3a9, 0xb3c3,
- 0xb3c5, 0xb3df,
- 0xb3e1, 0xb3fb,
- 0xb3fd, 0xb417,
- 0xb419, 0xb433,
- 0xb435, 0xb44f,
- 0xb451, 0xb46b,
- 0xb46d, 0xb487,
- 0xb489, 0xb4a3,
- 0xb4a5, 0xb4bf,
- 0xb4c1, 0xb4db,
- 0xb4dd, 0xb4f7,
- 0xb4f9, 0xb513,
- 0xb515, 0xb52f,
- 0xb531, 0xb54b,
- 0xb54d, 0xb567,
- 0xb569, 0xb583,
- 0xb585, 0xb59f,
- 0xb5a1, 0xb5bb,
- 0xb5bd, 0xb5d7,
- 0xb5d9, 0xb5f3,
- 0xb5f5, 0xb60f,
- 0xb611, 0xb62b,
- 0xb62d, 0xb647,
- 0xb649, 0xb663,
- 0xb665, 0xb67f,
- 0xb681, 0xb69b,
- 0xb69d, 0xb6b7,
- 0xb6b9, 0xb6d3,
- 0xb6d5, 0xb6ef,
- 0xb6f1, 0xb70b,
- 0xb70d, 0xb727,
- 0xb729, 0xb743,
- 0xb745, 0xb75f,
- 0xb761, 0xb77b,
- 0xb77d, 0xb797,
- 0xb799, 0xb7b3,
- 0xb7b5, 0xb7cf,
- 0xb7d1, 0xb7eb,
- 0xb7ed, 0xb807,
- 0xb809, 0xb823,
- 0xb825, 0xb83f,
- 0xb841, 0xb85b,
- 0xb85d, 0xb877,
- 0xb879, 0xb893,
- 0xb895, 0xb8af,
- 0xb8b1, 0xb8cb,
- 0xb8cd, 0xb8e7,
- 0xb8e9, 0xb903,
- 0xb905, 0xb91f,
- 0xb921, 0xb93b,
- 0xb93d, 0xb957,
- 0xb959, 0xb973,
- 0xb975, 0xb98f,
- 0xb991, 0xb9ab,
- 0xb9ad, 0xb9c7,
- 0xb9c9, 0xb9e3,
- 0xb9e5, 0xb9ff,
- 0xba01, 0xba1b,
- 0xba1d, 0xba37,
- 0xba39, 0xba53,
- 0xba55, 0xba6f,
- 0xba71, 0xba8b,
- 0xba8d, 0xbaa7,
- 0xbaa9, 0xbac3,
- 0xbac5, 0xbadf,
- 0xbae1, 0xbafb,
- 0xbafd, 0xbb17,
- 0xbb19, 0xbb33,
- 0xbb35, 0xbb4f,
- 0xbb51, 0xbb6b,
- 0xbb6d, 0xbb87,
- 0xbb89, 0xbba3,
- 0xbba5, 0xbbbf,
- 0xbbc1, 0xbbdb,
- 0xbbdd, 0xbbf7,
- 0xbbf9, 0xbc13,
- 0xbc15, 0xbc2f,
- 0xbc31, 0xbc4b,
- 0xbc4d, 0xbc67,
- 0xbc69, 0xbc83,
- 0xbc85, 0xbc9f,
- 0xbca1, 0xbcbb,
- 0xbcbd, 0xbcd7,
- 0xbcd9, 0xbcf3,
- 0xbcf5, 0xbd0f,
- 0xbd11, 0xbd2b,
- 0xbd2d, 0xbd47,
- 0xbd49, 0xbd63,
- 0xbd65, 0xbd7f,
- 0xbd81, 0xbd9b,
- 0xbd9d, 0xbdb7,
- 0xbdb9, 0xbdd3,
- 0xbdd5, 0xbdef,
- 0xbdf1, 0xbe0b,
- 0xbe0d, 0xbe27,
- 0xbe29, 0xbe43,
- 0xbe45, 0xbe5f,
- 0xbe61, 0xbe7b,
- 0xbe7d, 0xbe97,
- 0xbe99, 0xbeb3,
- 0xbeb5, 0xbecf,
- 0xbed1, 0xbeeb,
- 0xbeed, 0xbf07,
- 0xbf09, 0xbf23,
- 0xbf25, 0xbf3f,
- 0xbf41, 0xbf5b,
- 0xbf5d, 0xbf77,
- 0xbf79, 0xbf93,
- 0xbf95, 0xbfaf,
- 0xbfb1, 0xbfcb,
- 0xbfcd, 0xbfe7,
- 0xbfe9, 0xc003,
- 0xc005, 0xc01f,
- 0xc021, 0xc03b,
- 0xc03d, 0xc057,
- 0xc059, 0xc073,
- 0xc075, 0xc08f,
- 0xc091, 0xc0ab,
- 0xc0ad, 0xc0c7,
- 0xc0c9, 0xc0e3,
- 0xc0e5, 0xc0ff,
- 0xc101, 0xc11b,
- 0xc11d, 0xc137,
- 0xc139, 0xc153,
- 0xc155, 0xc16f,
- 0xc171, 0xc18b,
- 0xc18d, 0xc1a7,
- 0xc1a9, 0xc1c3,
- 0xc1c5, 0xc1df,
- 0xc1e1, 0xc1fb,
- 0xc1fd, 0xc217,
- 0xc219, 0xc233,
- 0xc235, 0xc24f,
- 0xc251, 0xc26b,
- 0xc26d, 0xc287,
- 0xc289, 0xc2a3,
- 0xc2a5, 0xc2bf,
- 0xc2c1, 0xc2db,
- 0xc2dd, 0xc2f7,
- 0xc2f9, 0xc313,
- 0xc315, 0xc32f,
- 0xc331, 0xc34b,
- 0xc34d, 0xc367,
- 0xc369, 0xc383,
- 0xc385, 0xc39f,
- 0xc3a1, 0xc3bb,
- 0xc3bd, 0xc3d7,
- 0xc3d9, 0xc3f3,
- 0xc3f5, 0xc40f,
- 0xc411, 0xc42b,
- 0xc42d, 0xc447,
- 0xc449, 0xc463,
- 0xc465, 0xc47f,
- 0xc481, 0xc49b,
- 0xc49d, 0xc4b7,
- 0xc4b9, 0xc4d3,
- 0xc4d5, 0xc4ef,
- 0xc4f1, 0xc50b,
- 0xc50d, 0xc527,
- 0xc529, 0xc543,
- 0xc545, 0xc55f,
- 0xc561, 0xc57b,
- 0xc57d, 0xc597,
- 0xc599, 0xc5b3,
- 0xc5b5, 0xc5cf,
- 0xc5d1, 0xc5eb,
- 0xc5ed, 0xc607,
- 0xc609, 0xc623,
- 0xc625, 0xc63f,
- 0xc641, 0xc65b,
- 0xc65d, 0xc677,
- 0xc679, 0xc693,
- 0xc695, 0xc6af,
- 0xc6b1, 0xc6cb,
- 0xc6cd, 0xc6e7,
- 0xc6e9, 0xc703,
- 0xc705, 0xc71f,
- 0xc721, 0xc73b,
- 0xc73d, 0xc757,
- 0xc759, 0xc773,
- 0xc775, 0xc78f,
- 0xc791, 0xc7ab,
- 0xc7ad, 0xc7c7,
- 0xc7c9, 0xc7e3,
- 0xc7e5, 0xc7ff,
- 0xc801, 0xc81b,
- 0xc81d, 0xc837,
- 0xc839, 0xc853,
- 0xc855, 0xc86f,
- 0xc871, 0xc88b,
- 0xc88d, 0xc8a7,
- 0xc8a9, 0xc8c3,
- 0xc8c5, 0xc8df,
- 0xc8e1, 0xc8fb,
- 0xc8fd, 0xc917,
- 0xc919, 0xc933,
- 0xc935, 0xc94f,
- 0xc951, 0xc96b,
- 0xc96d, 0xc987,
- 0xc989, 0xc9a3,
- 0xc9a5, 0xc9bf,
- 0xc9c1, 0xc9db,
- 0xc9dd, 0xc9f7,
- 0xc9f9, 0xca13,
- 0xca15, 0xca2f,
- 0xca31, 0xca4b,
- 0xca4d, 0xca67,
- 0xca69, 0xca83,
- 0xca85, 0xca9f,
- 0xcaa1, 0xcabb,
- 0xcabd, 0xcad7,
- 0xcad9, 0xcaf3,
- 0xcaf5, 0xcb0f,
- 0xcb11, 0xcb2b,
- 0xcb2d, 0xcb47,
- 0xcb49, 0xcb63,
- 0xcb65, 0xcb7f,
- 0xcb81, 0xcb9b,
- 0xcb9d, 0xcbb7,
- 0xcbb9, 0xcbd3,
- 0xcbd5, 0xcbef,
- 0xcbf1, 0xcc0b,
- 0xcc0d, 0xcc27,
- 0xcc29, 0xcc43,
- 0xcc45, 0xcc5f,
- 0xcc61, 0xcc7b,
- 0xcc7d, 0xcc97,
- 0xcc99, 0xccb3,
- 0xccb5, 0xcccf,
- 0xccd1, 0xcceb,
- 0xcced, 0xcd07,
- 0xcd09, 0xcd23,
- 0xcd25, 0xcd3f,
- 0xcd41, 0xcd5b,
- 0xcd5d, 0xcd77,
- 0xcd79, 0xcd93,
- 0xcd95, 0xcdaf,
- 0xcdb1, 0xcdcb,
- 0xcdcd, 0xcde7,
- 0xcde9, 0xce03,
- 0xce05, 0xce1f,
- 0xce21, 0xce3b,
- 0xce3d, 0xce57,
- 0xce59, 0xce73,
- 0xce75, 0xce8f,
- 0xce91, 0xceab,
- 0xcead, 0xcec7,
- 0xcec9, 0xcee3,
- 0xcee5, 0xceff,
- 0xcf01, 0xcf1b,
- 0xcf1d, 0xcf37,
- 0xcf39, 0xcf53,
- 0xcf55, 0xcf6f,
- 0xcf71, 0xcf8b,
- 0xcf8d, 0xcfa7,
- 0xcfa9, 0xcfc3,
- 0xcfc5, 0xcfdf,
- 0xcfe1, 0xcffb,
- 0xcffd, 0xd017,
- 0xd019, 0xd033,
- 0xd035, 0xd04f,
- 0xd051, 0xd06b,
- 0xd06d, 0xd087,
- 0xd089, 0xd0a3,
- 0xd0a5, 0xd0bf,
- 0xd0c1, 0xd0db,
- 0xd0dd, 0xd0f7,
- 0xd0f9, 0xd113,
- 0xd115, 0xd12f,
- 0xd131, 0xd14b,
- 0xd14d, 0xd167,
- 0xd169, 0xd183,
- 0xd185, 0xd19f,
- 0xd1a1, 0xd1bb,
- 0xd1bd, 0xd1d7,
- 0xd1d9, 0xd1f3,
- 0xd1f5, 0xd20f,
- 0xd211, 0xd22b,
- 0xd22d, 0xd247,
- 0xd249, 0xd263,
- 0xd265, 0xd27f,
- 0xd281, 0xd29b,
- 0xd29d, 0xd2b7,
- 0xd2b9, 0xd2d3,
- 0xd2d5, 0xd2ef,
- 0xd2f1, 0xd30b,
- 0xd30d, 0xd327,
- 0xd329, 0xd343,
- 0xd345, 0xd35f,
- 0xd361, 0xd37b,
- 0xd37d, 0xd397,
- 0xd399, 0xd3b3,
- 0xd3b5, 0xd3cf,
- 0xd3d1, 0xd3eb,
- 0xd3ed, 0xd407,
- 0xd409, 0xd423,
- 0xd425, 0xd43f,
- 0xd441, 0xd45b,
- 0xd45d, 0xd477,
- 0xd479, 0xd493,
- 0xd495, 0xd4af,
- 0xd4b1, 0xd4cb,
- 0xd4cd, 0xd4e7,
- 0xd4e9, 0xd503,
- 0xd505, 0xd51f,
- 0xd521, 0xd53b,
- 0xd53d, 0xd557,
- 0xd559, 0xd573,
- 0xd575, 0xd58f,
- 0xd591, 0xd5ab,
- 0xd5ad, 0xd5c7,
- 0xd5c9, 0xd5e3,
- 0xd5e5, 0xd5ff,
- 0xd601, 0xd61b,
- 0xd61d, 0xd637,
- 0xd639, 0xd653,
- 0xd655, 0xd66f,
- 0xd671, 0xd68b,
- 0xd68d, 0xd6a7,
- 0xd6a9, 0xd6c3,
- 0xd6c5, 0xd6df,
- 0xd6e1, 0xd6fb,
- 0xd6fd, 0xd717,
- 0xd719, 0xd733,
- 0xd735, 0xd74f,
- 0xd751, 0xd76b,
- 0xd76d, 0xd787,
- 0xd789, 0xd7a3,
-}; /* CR_Grapheme_Cluster_Break_LVT */
-
-/* 'Grapheme_Cluster_Break_ZWJ': Grapheme_Cluster_Break=ZWJ */
-static const OnigCodePoint CR_Grapheme_Cluster_Break_ZWJ[] = {
- 1,
- 0x200d, 0x200d,
-}; /* CR_Grapheme_Cluster_Break_ZWJ */
-
-/* 'In_Basic_Latin': Block */
-#define CR_In_Basic_Latin CR_ASCII
-
-/* 'In_Latin_1_Supplement': Block */
-static const OnigCodePoint CR_In_Latin_1_Supplement[] = {
- 1,
- 0x0080, 0x00ff,
-}; /* CR_In_Latin_1_Supplement */
-
-/* 'In_Latin_Extended_A': Block */
-static const OnigCodePoint CR_In_Latin_Extended_A[] = {
- 1,
- 0x0100, 0x017f,
-}; /* CR_In_Latin_Extended_A */
-
-/* 'In_Latin_Extended_B': Block */
-static const OnigCodePoint CR_In_Latin_Extended_B[] = {
- 1,
- 0x0180, 0x024f,
-}; /* CR_In_Latin_Extended_B */
-
-/* 'In_IPA_Extensions': Block */
-static const OnigCodePoint CR_In_IPA_Extensions[] = {
- 1,
- 0x0250, 0x02af,
-}; /* CR_In_IPA_Extensions */
-
-/* 'In_Spacing_Modifier_Letters': Block */
-static const OnigCodePoint CR_In_Spacing_Modifier_Letters[] = {
- 1,
- 0x02b0, 0x02ff,
-}; /* CR_In_Spacing_Modifier_Letters */
-
-/* 'In_Combining_Diacritical_Marks': Block */
-static const OnigCodePoint CR_In_Combining_Diacritical_Marks[] = {
- 1,
- 0x0300, 0x036f,
-}; /* CR_In_Combining_Diacritical_Marks */
-
-/* 'In_Greek_and_Coptic': Block */
-static const OnigCodePoint CR_In_Greek_and_Coptic[] = {
- 1,
- 0x0370, 0x03ff,
-}; /* CR_In_Greek_and_Coptic */
-
-/* 'In_Cyrillic': Block */
-static const OnigCodePoint CR_In_Cyrillic[] = {
- 1,
- 0x0400, 0x04ff,
-}; /* CR_In_Cyrillic */
-
-/* 'In_Cyrillic_Supplement': Block */
-static const OnigCodePoint CR_In_Cyrillic_Supplement[] = {
- 1,
- 0x0500, 0x052f,
-}; /* CR_In_Cyrillic_Supplement */
-
-/* 'In_Armenian': Block */
-static const OnigCodePoint CR_In_Armenian[] = {
- 1,
- 0x0530, 0x058f,
-}; /* CR_In_Armenian */
-
-/* 'In_Hebrew': Block */
-static const OnigCodePoint CR_In_Hebrew[] = {
- 1,
- 0x0590, 0x05ff,
-}; /* CR_In_Hebrew */
-
-/* 'In_Arabic': Block */
-static const OnigCodePoint CR_In_Arabic[] = {
- 1,
- 0x0600, 0x06ff,
-}; /* CR_In_Arabic */
-
-/* 'In_Syriac': Block */
-static const OnigCodePoint CR_In_Syriac[] = {
- 1,
- 0x0700, 0x074f,
-}; /* CR_In_Syriac */
-
-/* 'In_Arabic_Supplement': Block */
-static const OnigCodePoint CR_In_Arabic_Supplement[] = {
- 1,
- 0x0750, 0x077f,
-}; /* CR_In_Arabic_Supplement */
-
-/* 'In_Thaana': Block */
-static const OnigCodePoint CR_In_Thaana[] = {
- 1,
- 0x0780, 0x07bf,
-}; /* CR_In_Thaana */
-
-/* 'In_NKo': Block */
-static const OnigCodePoint CR_In_NKo[] = {
- 1,
- 0x07c0, 0x07ff,
-}; /* CR_In_NKo */
-
-/* 'In_Samaritan': Block */
-static const OnigCodePoint CR_In_Samaritan[] = {
- 1,
- 0x0800, 0x083f,
-}; /* CR_In_Samaritan */
-
-/* 'In_Mandaic': Block */
-static const OnigCodePoint CR_In_Mandaic[] = {
- 1,
- 0x0840, 0x085f,
-}; /* CR_In_Mandaic */
-
-/* 'In_Syriac_Supplement': Block */
-static const OnigCodePoint CR_In_Syriac_Supplement[] = {
- 1,
- 0x0860, 0x086f,
-}; /* CR_In_Syriac_Supplement */
-
-/* 'In_Arabic_Extended_B': Block */
-static const OnigCodePoint CR_In_Arabic_Extended_B[] = {
- 1,
- 0x0870, 0x089f,
-}; /* CR_In_Arabic_Extended_B */
-
-/* 'In_Arabic_Extended_A': Block */
-static const OnigCodePoint CR_In_Arabic_Extended_A[] = {
- 1,
- 0x08a0, 0x08ff,
-}; /* CR_In_Arabic_Extended_A */
-
-/* 'In_Devanagari': Block */
-static const OnigCodePoint CR_In_Devanagari[] = {
- 1,
- 0x0900, 0x097f,
-}; /* CR_In_Devanagari */
-
-/* 'In_Bengali': Block */
-static const OnigCodePoint CR_In_Bengali[] = {
- 1,
- 0x0980, 0x09ff,
-}; /* CR_In_Bengali */
-
-/* 'In_Gurmukhi': Block */
-static const OnigCodePoint CR_In_Gurmukhi[] = {
- 1,
- 0x0a00, 0x0a7f,
-}; /* CR_In_Gurmukhi */
-
-/* 'In_Gujarati': Block */
-static const OnigCodePoint CR_In_Gujarati[] = {
- 1,
- 0x0a80, 0x0aff,
-}; /* CR_In_Gujarati */
-
-/* 'In_Oriya': Block */
-static const OnigCodePoint CR_In_Oriya[] = {
- 1,
- 0x0b00, 0x0b7f,
-}; /* CR_In_Oriya */
-
-/* 'In_Tamil': Block */
-static const OnigCodePoint CR_In_Tamil[] = {
- 1,
- 0x0b80, 0x0bff,
-}; /* CR_In_Tamil */
-
-/* 'In_Telugu': Block */
-static const OnigCodePoint CR_In_Telugu[] = {
- 1,
- 0x0c00, 0x0c7f,
-}; /* CR_In_Telugu */
-
-/* 'In_Kannada': Block */
-static const OnigCodePoint CR_In_Kannada[] = {
- 1,
- 0x0c80, 0x0cff,
-}; /* CR_In_Kannada */
-
-/* 'In_Malayalam': Block */
-static const OnigCodePoint CR_In_Malayalam[] = {
- 1,
- 0x0d00, 0x0d7f,
-}; /* CR_In_Malayalam */
-
-/* 'In_Sinhala': Block */
-static const OnigCodePoint CR_In_Sinhala[] = {
- 1,
- 0x0d80, 0x0dff,
-}; /* CR_In_Sinhala */
-
-/* 'In_Thai': Block */
-static const OnigCodePoint CR_In_Thai[] = {
- 1,
- 0x0e00, 0x0e7f,
-}; /* CR_In_Thai */
-
-/* 'In_Lao': Block */
-static const OnigCodePoint CR_In_Lao[] = {
- 1,
- 0x0e80, 0x0eff,
-}; /* CR_In_Lao */
-
-/* 'In_Tibetan': Block */
-static const OnigCodePoint CR_In_Tibetan[] = {
- 1,
- 0x0f00, 0x0fff,
-}; /* CR_In_Tibetan */
-
-/* 'In_Myanmar': Block */
-static const OnigCodePoint CR_In_Myanmar[] = {
- 1,
- 0x1000, 0x109f,
-}; /* CR_In_Myanmar */
-
-/* 'In_Georgian': Block */
-static const OnigCodePoint CR_In_Georgian[] = {
- 1,
- 0x10a0, 0x10ff,
-}; /* CR_In_Georgian */
-
-/* 'In_Hangul_Jamo': Block */
-static const OnigCodePoint CR_In_Hangul_Jamo[] = {
- 1,
- 0x1100, 0x11ff,
-}; /* CR_In_Hangul_Jamo */
-
-/* 'In_Ethiopic': Block */
-static const OnigCodePoint CR_In_Ethiopic[] = {
- 1,
- 0x1200, 0x137f,
-}; /* CR_In_Ethiopic */
-
-/* 'In_Ethiopic_Supplement': Block */
-static const OnigCodePoint CR_In_Ethiopic_Supplement[] = {
- 1,
- 0x1380, 0x139f,
-}; /* CR_In_Ethiopic_Supplement */
-
-/* 'In_Cherokee': Block */
-static const OnigCodePoint CR_In_Cherokee[] = {
- 1,
- 0x13a0, 0x13ff,
-}; /* CR_In_Cherokee */
-
-/* 'In_Unified_Canadian_Aboriginal_Syllabics': Block */
-static const OnigCodePoint CR_In_Unified_Canadian_Aboriginal_Syllabics[] = {
- 1,
- 0x1400, 0x167f,
-}; /* CR_In_Unified_Canadian_Aboriginal_Syllabics */
-
-/* 'In_Ogham': Block */
-static const OnigCodePoint CR_In_Ogham[] = {
- 1,
- 0x1680, 0x169f,
-}; /* CR_In_Ogham */
-
-/* 'In_Runic': Block */
-static const OnigCodePoint CR_In_Runic[] = {
- 1,
- 0x16a0, 0x16ff,
-}; /* CR_In_Runic */
-
-/* 'In_Tagalog': Block */
-static const OnigCodePoint CR_In_Tagalog[] = {
- 1,
- 0x1700, 0x171f,
-}; /* CR_In_Tagalog */
-
-/* 'In_Hanunoo': Block */
-static const OnigCodePoint CR_In_Hanunoo[] = {
- 1,
- 0x1720, 0x173f,
-}; /* CR_In_Hanunoo */
-
-/* 'In_Buhid': Block */
-static const OnigCodePoint CR_In_Buhid[] = {
- 1,
- 0x1740, 0x175f,
-}; /* CR_In_Buhid */
-
-/* 'In_Tagbanwa': Block */
-static const OnigCodePoint CR_In_Tagbanwa[] = {
- 1,
- 0x1760, 0x177f,
-}; /* CR_In_Tagbanwa */
-
-/* 'In_Khmer': Block */
-static const OnigCodePoint CR_In_Khmer[] = {
- 1,
- 0x1780, 0x17ff,
-}; /* CR_In_Khmer */
-
-/* 'In_Mongolian': Block */
-static const OnigCodePoint CR_In_Mongolian[] = {
- 1,
- 0x1800, 0x18af,
-}; /* CR_In_Mongolian */
-
-/* 'In_Unified_Canadian_Aboriginal_Syllabics_Extended': Block */
-static const OnigCodePoint CR_In_Unified_Canadian_Aboriginal_Syllabics_Extended[] = {
- 1,
- 0x18b0, 0x18ff,
-}; /* CR_In_Unified_Canadian_Aboriginal_Syllabics_Extended */
-
-/* 'In_Limbu': Block */
-static const OnigCodePoint CR_In_Limbu[] = {
- 1,
- 0x1900, 0x194f,
-}; /* CR_In_Limbu */
-
-/* 'In_Tai_Le': Block */
-static const OnigCodePoint CR_In_Tai_Le[] = {
- 1,
- 0x1950, 0x197f,
-}; /* CR_In_Tai_Le */
-
-/* 'In_New_Tai_Lue': Block */
-static const OnigCodePoint CR_In_New_Tai_Lue[] = {
- 1,
- 0x1980, 0x19df,
-}; /* CR_In_New_Tai_Lue */
-
-/* 'In_Khmer_Symbols': Block */
-static const OnigCodePoint CR_In_Khmer_Symbols[] = {
- 1,
- 0x19e0, 0x19ff,
-}; /* CR_In_Khmer_Symbols */
-
-/* 'In_Buginese': Block */
-static const OnigCodePoint CR_In_Buginese[] = {
- 1,
- 0x1a00, 0x1a1f,
-}; /* CR_In_Buginese */
-
-/* 'In_Tai_Tham': Block */
-static const OnigCodePoint CR_In_Tai_Tham[] = {
- 1,
- 0x1a20, 0x1aaf,
-}; /* CR_In_Tai_Tham */
-
-/* 'In_Combining_Diacritical_Marks_Extended': Block */
-static const OnigCodePoint CR_In_Combining_Diacritical_Marks_Extended[] = {
- 1,
- 0x1ab0, 0x1aff,
-}; /* CR_In_Combining_Diacritical_Marks_Extended */
-
-/* 'In_Balinese': Block */
-static const OnigCodePoint CR_In_Balinese[] = {
- 1,
- 0x1b00, 0x1b7f,
-}; /* CR_In_Balinese */
-
-/* 'In_Sundanese': Block */
-static const OnigCodePoint CR_In_Sundanese[] = {
- 1,
- 0x1b80, 0x1bbf,
-}; /* CR_In_Sundanese */
-
-/* 'In_Batak': Block */
-static const OnigCodePoint CR_In_Batak[] = {
- 1,
- 0x1bc0, 0x1bff,
-}; /* CR_In_Batak */
-
-/* 'In_Lepcha': Block */
-static const OnigCodePoint CR_In_Lepcha[] = {
- 1,
- 0x1c00, 0x1c4f,
-}; /* CR_In_Lepcha */
-
-/* 'In_Ol_Chiki': Block */
-#define CR_In_Ol_Chiki CR_Ol_Chiki
-
-/* 'In_Cyrillic_Extended_C': Block */
-static const OnigCodePoint CR_In_Cyrillic_Extended_C[] = {
- 1,
- 0x1c80, 0x1c8f,
-}; /* CR_In_Cyrillic_Extended_C */
-
-/* 'In_Georgian_Extended': Block */
-static const OnigCodePoint CR_In_Georgian_Extended[] = {
- 1,
- 0x1c90, 0x1cbf,
-}; /* CR_In_Georgian_Extended */
-
-/* 'In_Sundanese_Supplement': Block */
-static const OnigCodePoint CR_In_Sundanese_Supplement[] = {
- 1,
- 0x1cc0, 0x1ccf,
-}; /* CR_In_Sundanese_Supplement */
-
-/* 'In_Vedic_Extensions': Block */
-static const OnigCodePoint CR_In_Vedic_Extensions[] = {
- 1,
- 0x1cd0, 0x1cff,
-}; /* CR_In_Vedic_Extensions */
-
-/* 'In_Phonetic_Extensions': Block */
-static const OnigCodePoint CR_In_Phonetic_Extensions[] = {
- 1,
- 0x1d00, 0x1d7f,
-}; /* CR_In_Phonetic_Extensions */
-
-/* 'In_Phonetic_Extensions_Supplement': Block */
-static const OnigCodePoint CR_In_Phonetic_Extensions_Supplement[] = {
- 1,
- 0x1d80, 0x1dbf,
-}; /* CR_In_Phonetic_Extensions_Supplement */
-
-/* 'In_Combining_Diacritical_Marks_Supplement': Block */
-static const OnigCodePoint CR_In_Combining_Diacritical_Marks_Supplement[] = {
- 1,
- 0x1dc0, 0x1dff,
-}; /* CR_In_Combining_Diacritical_Marks_Supplement */
-
-/* 'In_Latin_Extended_Additional': Block */
-static const OnigCodePoint CR_In_Latin_Extended_Additional[] = {
- 1,
- 0x1e00, 0x1eff,
-}; /* CR_In_Latin_Extended_Additional */
-
-/* 'In_Greek_Extended': Block */
-static const OnigCodePoint CR_In_Greek_Extended[] = {
- 1,
- 0x1f00, 0x1fff,
-}; /* CR_In_Greek_Extended */
-
-/* 'In_General_Punctuation': Block */
-static const OnigCodePoint CR_In_General_Punctuation[] = {
- 1,
- 0x2000, 0x206f,
-}; /* CR_In_General_Punctuation */
-
-/* 'In_Superscripts_and_Subscripts': Block */
-static const OnigCodePoint CR_In_Superscripts_and_Subscripts[] = {
- 1,
- 0x2070, 0x209f,
-}; /* CR_In_Superscripts_and_Subscripts */
-
-/* 'In_Currency_Symbols': Block */
-static const OnigCodePoint CR_In_Currency_Symbols[] = {
- 1,
- 0x20a0, 0x20cf,
-}; /* CR_In_Currency_Symbols */
-
-/* 'In_Combining_Diacritical_Marks_for_Symbols': Block */
-static const OnigCodePoint CR_In_Combining_Diacritical_Marks_for_Symbols[] = {
- 1,
- 0x20d0, 0x20ff,
-}; /* CR_In_Combining_Diacritical_Marks_for_Symbols */
-
-/* 'In_Letterlike_Symbols': Block */
-static const OnigCodePoint CR_In_Letterlike_Symbols[] = {
- 1,
- 0x2100, 0x214f,
-}; /* CR_In_Letterlike_Symbols */
-
-/* 'In_Number_Forms': Block */
-static const OnigCodePoint CR_In_Number_Forms[] = {
- 1,
- 0x2150, 0x218f,
-}; /* CR_In_Number_Forms */
-
-/* 'In_Arrows': Block */
-static const OnigCodePoint CR_In_Arrows[] = {
- 1,
- 0x2190, 0x21ff,
-}; /* CR_In_Arrows */
-
-/* 'In_Mathematical_Operators': Block */
-static const OnigCodePoint CR_In_Mathematical_Operators[] = {
- 1,
- 0x2200, 0x22ff,
-}; /* CR_In_Mathematical_Operators */
-
-/* 'In_Miscellaneous_Technical': Block */
-static const OnigCodePoint CR_In_Miscellaneous_Technical[] = {
- 1,
- 0x2300, 0x23ff,
-}; /* CR_In_Miscellaneous_Technical */
-
-/* 'In_Control_Pictures': Block */
-static const OnigCodePoint CR_In_Control_Pictures[] = {
- 1,
- 0x2400, 0x243f,
-}; /* CR_In_Control_Pictures */
-
-/* 'In_Optical_Character_Recognition': Block */
-static const OnigCodePoint CR_In_Optical_Character_Recognition[] = {
- 1,
- 0x2440, 0x245f,
-}; /* CR_In_Optical_Character_Recognition */
-
-/* 'In_Enclosed_Alphanumerics': Block */
-static const OnigCodePoint CR_In_Enclosed_Alphanumerics[] = {
- 1,
- 0x2460, 0x24ff,
-}; /* CR_In_Enclosed_Alphanumerics */
-
-/* 'In_Box_Drawing': Block */
-static const OnigCodePoint CR_In_Box_Drawing[] = {
- 1,
- 0x2500, 0x257f,
-}; /* CR_In_Box_Drawing */
-
-/* 'In_Block_Elements': Block */
-static const OnigCodePoint CR_In_Block_Elements[] = {
- 1,
- 0x2580, 0x259f,
-}; /* CR_In_Block_Elements */
-
-/* 'In_Geometric_Shapes': Block */
-static const OnigCodePoint CR_In_Geometric_Shapes[] = {
- 1,
- 0x25a0, 0x25ff,
-}; /* CR_In_Geometric_Shapes */
-
-/* 'In_Miscellaneous_Symbols': Block */
-static const OnigCodePoint CR_In_Miscellaneous_Symbols[] = {
- 1,
- 0x2600, 0x26ff,
-}; /* CR_In_Miscellaneous_Symbols */
-
-/* 'In_Dingbats': Block */
-static const OnigCodePoint CR_In_Dingbats[] = {
- 1,
- 0x2700, 0x27bf,
-}; /* CR_In_Dingbats */
-
-/* 'In_Miscellaneous_Mathematical_Symbols_A': Block */
-static const OnigCodePoint CR_In_Miscellaneous_Mathematical_Symbols_A[] = {
- 1,
- 0x27c0, 0x27ef,
-}; /* CR_In_Miscellaneous_Mathematical_Symbols_A */
-
-/* 'In_Supplemental_Arrows_A': Block */
-static const OnigCodePoint CR_In_Supplemental_Arrows_A[] = {
- 1,
- 0x27f0, 0x27ff,
-}; /* CR_In_Supplemental_Arrows_A */
-
-/* 'In_Braille_Patterns': Block */
-#define CR_In_Braille_Patterns CR_Braille
-
-/* 'In_Supplemental_Arrows_B': Block */
-static const OnigCodePoint CR_In_Supplemental_Arrows_B[] = {
- 1,
- 0x2900, 0x297f,
-}; /* CR_In_Supplemental_Arrows_B */
-
-/* 'In_Miscellaneous_Mathematical_Symbols_B': Block */
-static const OnigCodePoint CR_In_Miscellaneous_Mathematical_Symbols_B[] = {
- 1,
- 0x2980, 0x29ff,
-}; /* CR_In_Miscellaneous_Mathematical_Symbols_B */
-
-/* 'In_Supplemental_Mathematical_Operators': Block */
-static const OnigCodePoint CR_In_Supplemental_Mathematical_Operators[] = {
- 1,
- 0x2a00, 0x2aff,
-}; /* CR_In_Supplemental_Mathematical_Operators */
-
-/* 'In_Miscellaneous_Symbols_and_Arrows': Block */
-static const OnigCodePoint CR_In_Miscellaneous_Symbols_and_Arrows[] = {
- 1,
- 0x2b00, 0x2bff,
-}; /* CR_In_Miscellaneous_Symbols_and_Arrows */
-
-/* 'In_Glagolitic': Block */
-static const OnigCodePoint CR_In_Glagolitic[] = {
- 1,
- 0x2c00, 0x2c5f,
-}; /* CR_In_Glagolitic */
-
-/* 'In_Latin_Extended_C': Block */
-static const OnigCodePoint CR_In_Latin_Extended_C[] = {
- 1,
- 0x2c60, 0x2c7f,
-}; /* CR_In_Latin_Extended_C */
-
-/* 'In_Coptic': Block */
-static const OnigCodePoint CR_In_Coptic[] = {
- 1,
- 0x2c80, 0x2cff,
-}; /* CR_In_Coptic */
-
-/* 'In_Georgian_Supplement': Block */
-static const OnigCodePoint CR_In_Georgian_Supplement[] = {
- 1,
- 0x2d00, 0x2d2f,
-}; /* CR_In_Georgian_Supplement */
-
-/* 'In_Tifinagh': Block */
-static const OnigCodePoint CR_In_Tifinagh[] = {
- 1,
- 0x2d30, 0x2d7f,
-}; /* CR_In_Tifinagh */
-
-/* 'In_Ethiopic_Extended': Block */
-static const OnigCodePoint CR_In_Ethiopic_Extended[] = {
- 1,
- 0x2d80, 0x2ddf,
-}; /* CR_In_Ethiopic_Extended */
-
-/* 'In_Cyrillic_Extended_A': Block */
-static const OnigCodePoint CR_In_Cyrillic_Extended_A[] = {
- 1,
- 0x2de0, 0x2dff,
-}; /* CR_In_Cyrillic_Extended_A */
-
-/* 'In_Supplemental_Punctuation': Block */
-static const OnigCodePoint CR_In_Supplemental_Punctuation[] = {
- 1,
- 0x2e00, 0x2e7f,
-}; /* CR_In_Supplemental_Punctuation */
-
-/* 'In_CJK_Radicals_Supplement': Block */
-static const OnigCodePoint CR_In_CJK_Radicals_Supplement[] = {
- 1,
- 0x2e80, 0x2eff,
-}; /* CR_In_CJK_Radicals_Supplement */
-
-/* 'In_Kangxi_Radicals': Block */
-static const OnigCodePoint CR_In_Kangxi_Radicals[] = {
- 1,
- 0x2f00, 0x2fdf,
-}; /* CR_In_Kangxi_Radicals */
-
-/* 'In_Ideographic_Description_Characters': Block */
-static const OnigCodePoint CR_In_Ideographic_Description_Characters[] = {
- 1,
- 0x2ff0, 0x2fff,
-}; /* CR_In_Ideographic_Description_Characters */
-
-/* 'In_CJK_Symbols_and_Punctuation': Block */
-static const OnigCodePoint CR_In_CJK_Symbols_and_Punctuation[] = {
- 1,
- 0x3000, 0x303f,
-}; /* CR_In_CJK_Symbols_and_Punctuation */
-
-/* 'In_Hiragana': Block */
-static const OnigCodePoint CR_In_Hiragana[] = {
- 1,
- 0x3040, 0x309f,
-}; /* CR_In_Hiragana */
-
-/* 'In_Katakana': Block */
-static const OnigCodePoint CR_In_Katakana[] = {
- 1,
- 0x30a0, 0x30ff,
-}; /* CR_In_Katakana */
-
-/* 'In_Bopomofo': Block */
-static const OnigCodePoint CR_In_Bopomofo[] = {
- 1,
- 0x3100, 0x312f,
-}; /* CR_In_Bopomofo */
-
-/* 'In_Hangul_Compatibility_Jamo': Block */
-static const OnigCodePoint CR_In_Hangul_Compatibility_Jamo[] = {
- 1,
- 0x3130, 0x318f,
-}; /* CR_In_Hangul_Compatibility_Jamo */
-
-/* 'In_Kanbun': Block */
-static const OnigCodePoint CR_In_Kanbun[] = {
- 1,
- 0x3190, 0x319f,
-}; /* CR_In_Kanbun */
-
-/* 'In_Bopomofo_Extended': Block */
-static const OnigCodePoint CR_In_Bopomofo_Extended[] = {
- 1,
- 0x31a0, 0x31bf,
-}; /* CR_In_Bopomofo_Extended */
-
-/* 'In_CJK_Strokes': Block */
-static const OnigCodePoint CR_In_CJK_Strokes[] = {
- 1,
- 0x31c0, 0x31ef,
-}; /* CR_In_CJK_Strokes */
-
-/* 'In_Katakana_Phonetic_Extensions': Block */
-static const OnigCodePoint CR_In_Katakana_Phonetic_Extensions[] = {
- 1,
- 0x31f0, 0x31ff,
-}; /* CR_In_Katakana_Phonetic_Extensions */
-
-/* 'In_Enclosed_CJK_Letters_and_Months': Block */
-static const OnigCodePoint CR_In_Enclosed_CJK_Letters_and_Months[] = {
- 1,
- 0x3200, 0x32ff,
-}; /* CR_In_Enclosed_CJK_Letters_and_Months */
-
-/* 'In_CJK_Compatibility': Block */
-static const OnigCodePoint CR_In_CJK_Compatibility[] = {
- 1,
- 0x3300, 0x33ff,
-}; /* CR_In_CJK_Compatibility */
-
-/* 'In_CJK_Unified_Ideographs_Extension_A': Block */
-static const OnigCodePoint CR_In_CJK_Unified_Ideographs_Extension_A[] = {
- 1,
- 0x3400, 0x4dbf,
-}; /* CR_In_CJK_Unified_Ideographs_Extension_A */
-
-/* 'In_Yijing_Hexagram_Symbols': Block */
-static const OnigCodePoint CR_In_Yijing_Hexagram_Symbols[] = {
- 1,
- 0x4dc0, 0x4dff,
-}; /* CR_In_Yijing_Hexagram_Symbols */
-
-/* 'In_CJK_Unified_Ideographs': Block */
-static const OnigCodePoint CR_In_CJK_Unified_Ideographs[] = {
- 1,
- 0x4e00, 0x9fff,
-}; /* CR_In_CJK_Unified_Ideographs */
-
-/* 'In_Yi_Syllables': Block */
-static const OnigCodePoint CR_In_Yi_Syllables[] = {
- 1,
- 0xa000, 0xa48f,
-}; /* CR_In_Yi_Syllables */
-
-/* 'In_Yi_Radicals': Block */
-static const OnigCodePoint CR_In_Yi_Radicals[] = {
- 1,
- 0xa490, 0xa4cf,
-}; /* CR_In_Yi_Radicals */
-
-/* 'In_Lisu': Block */
-static const OnigCodePoint CR_In_Lisu[] = {
- 1,
- 0xa4d0, 0xa4ff,
-}; /* CR_In_Lisu */
-
-/* 'In_Vai': Block */
-static const OnigCodePoint CR_In_Vai[] = {
- 1,
- 0xa500, 0xa63f,
-}; /* CR_In_Vai */
-
-/* 'In_Cyrillic_Extended_B': Block */
-static const OnigCodePoint CR_In_Cyrillic_Extended_B[] = {
- 1,
- 0xa640, 0xa69f,
-}; /* CR_In_Cyrillic_Extended_B */
-
-/* 'In_Bamum': Block */
-static const OnigCodePoint CR_In_Bamum[] = {
- 1,
- 0xa6a0, 0xa6ff,
-}; /* CR_In_Bamum */
-
-/* 'In_Modifier_Tone_Letters': Block */
-static const OnigCodePoint CR_In_Modifier_Tone_Letters[] = {
- 1,
- 0xa700, 0xa71f,
-}; /* CR_In_Modifier_Tone_Letters */
-
-/* 'In_Latin_Extended_D': Block */
-static const OnigCodePoint CR_In_Latin_Extended_D[] = {
- 1,
- 0xa720, 0xa7ff,
-}; /* CR_In_Latin_Extended_D */
-
-/* 'In_Syloti_Nagri': Block */
-static const OnigCodePoint CR_In_Syloti_Nagri[] = {
- 1,
- 0xa800, 0xa82f,
-}; /* CR_In_Syloti_Nagri */
-
-/* 'In_Common_Indic_Number_Forms': Block */
-static const OnigCodePoint CR_In_Common_Indic_Number_Forms[] = {
- 1,
- 0xa830, 0xa83f,
-}; /* CR_In_Common_Indic_Number_Forms */
-
-/* 'In_Phags_pa': Block */
-static const OnigCodePoint CR_In_Phags_pa[] = {
- 1,
- 0xa840, 0xa87f,
-}; /* CR_In_Phags_pa */
-
-/* 'In_Saurashtra': Block */
-static const OnigCodePoint CR_In_Saurashtra[] = {
- 1,
- 0xa880, 0xa8df,
-}; /* CR_In_Saurashtra */
-
-/* 'In_Devanagari_Extended': Block */
-static const OnigCodePoint CR_In_Devanagari_Extended[] = {
- 1,
- 0xa8e0, 0xa8ff,
-}; /* CR_In_Devanagari_Extended */
-
-/* 'In_Kayah_Li': Block */
-static const OnigCodePoint CR_In_Kayah_Li[] = {
- 1,
- 0xa900, 0xa92f,
-}; /* CR_In_Kayah_Li */
-
-/* 'In_Rejang': Block */
-static const OnigCodePoint CR_In_Rejang[] = {
- 1,
- 0xa930, 0xa95f,
-}; /* CR_In_Rejang */
-
-/* 'In_Hangul_Jamo_Extended_A': Block */
-static const OnigCodePoint CR_In_Hangul_Jamo_Extended_A[] = {
- 1,
- 0xa960, 0xa97f,
-}; /* CR_In_Hangul_Jamo_Extended_A */
-
-/* 'In_Javanese': Block */
-static const OnigCodePoint CR_In_Javanese[] = {
- 1,
- 0xa980, 0xa9df,
-}; /* CR_In_Javanese */
-
-/* 'In_Myanmar_Extended_B': Block */
-static const OnigCodePoint CR_In_Myanmar_Extended_B[] = {
- 1,
- 0xa9e0, 0xa9ff,
-}; /* CR_In_Myanmar_Extended_B */
-
-/* 'In_Cham': Block */
-static const OnigCodePoint CR_In_Cham[] = {
- 1,
- 0xaa00, 0xaa5f,
-}; /* CR_In_Cham */
-
-/* 'In_Myanmar_Extended_A': Block */
-static const OnigCodePoint CR_In_Myanmar_Extended_A[] = {
- 1,
- 0xaa60, 0xaa7f,
-}; /* CR_In_Myanmar_Extended_A */
-
-/* 'In_Tai_Viet': Block */
-static const OnigCodePoint CR_In_Tai_Viet[] = {
- 1,
- 0xaa80, 0xaadf,
-}; /* CR_In_Tai_Viet */
-
-/* 'In_Meetei_Mayek_Extensions': Block */
-static const OnigCodePoint CR_In_Meetei_Mayek_Extensions[] = {
- 1,
- 0xaae0, 0xaaff,
-}; /* CR_In_Meetei_Mayek_Extensions */
-
-/* 'In_Ethiopic_Extended_A': Block */
-static const OnigCodePoint CR_In_Ethiopic_Extended_A[] = {
- 1,
- 0xab00, 0xab2f,
-}; /* CR_In_Ethiopic_Extended_A */
-
-/* 'In_Latin_Extended_E': Block */
-static const OnigCodePoint CR_In_Latin_Extended_E[] = {
- 1,
- 0xab30, 0xab6f,
-}; /* CR_In_Latin_Extended_E */
-
-/* 'In_Cherokee_Supplement': Block */
-static const OnigCodePoint CR_In_Cherokee_Supplement[] = {
- 1,
- 0xab70, 0xabbf,
-}; /* CR_In_Cherokee_Supplement */
-
-/* 'In_Meetei_Mayek': Block */
-static const OnigCodePoint CR_In_Meetei_Mayek[] = {
- 1,
- 0xabc0, 0xabff,
-}; /* CR_In_Meetei_Mayek */
-
-/* 'In_Hangul_Syllables': Block */
-static const OnigCodePoint CR_In_Hangul_Syllables[] = {
- 1,
- 0xac00, 0xd7af,
-}; /* CR_In_Hangul_Syllables */
-
-/* 'In_Hangul_Jamo_Extended_B': Block */
-static const OnigCodePoint CR_In_Hangul_Jamo_Extended_B[] = {
- 1,
- 0xd7b0, 0xd7ff,
-}; /* CR_In_Hangul_Jamo_Extended_B */
-
-/* 'In_High_Surrogates': Block */
-static const OnigCodePoint CR_In_High_Surrogates[] = {
- 1,
- 0xd800, 0xdb7f,
-}; /* CR_In_High_Surrogates */
-
-/* 'In_High_Private_Use_Surrogates': Block */
-static const OnigCodePoint CR_In_High_Private_Use_Surrogates[] = {
- 1,
- 0xdb80, 0xdbff,
-}; /* CR_In_High_Private_Use_Surrogates */
-
-/* 'In_Low_Surrogates': Block */
-static const OnigCodePoint CR_In_Low_Surrogates[] = {
- 1,
- 0xdc00, 0xdfff,
-}; /* CR_In_Low_Surrogates */
-
-/* 'In_Private_Use_Area': Block */
-static const OnigCodePoint CR_In_Private_Use_Area[] = {
- 1,
- 0xe000, 0xf8ff,
-}; /* CR_In_Private_Use_Area */
-
-/* 'In_CJK_Compatibility_Ideographs': Block */
-static const OnigCodePoint CR_In_CJK_Compatibility_Ideographs[] = {
- 1,
- 0xf900, 0xfaff,
-}; /* CR_In_CJK_Compatibility_Ideographs */
-
-/* 'In_Alphabetic_Presentation_Forms': Block */
-static const OnigCodePoint CR_In_Alphabetic_Presentation_Forms[] = {
- 1,
- 0xfb00, 0xfb4f,
-}; /* CR_In_Alphabetic_Presentation_Forms */
-
-/* 'In_Arabic_Presentation_Forms_A': Block */
-static const OnigCodePoint CR_In_Arabic_Presentation_Forms_A[] = {
- 1,
- 0xfb50, 0xfdff,
-}; /* CR_In_Arabic_Presentation_Forms_A */
-
-/* 'In_Variation_Selectors': Block */
-static const OnigCodePoint CR_In_Variation_Selectors[] = {
- 1,
- 0xfe00, 0xfe0f,
-}; /* CR_In_Variation_Selectors */
-
-/* 'In_Vertical_Forms': Block */
-static const OnigCodePoint CR_In_Vertical_Forms[] = {
- 1,
- 0xfe10, 0xfe1f,
-}; /* CR_In_Vertical_Forms */
-
-/* 'In_Combining_Half_Marks': Block */
-static const OnigCodePoint CR_In_Combining_Half_Marks[] = {
- 1,
- 0xfe20, 0xfe2f,
-}; /* CR_In_Combining_Half_Marks */
-
-/* 'In_CJK_Compatibility_Forms': Block */
-static const OnigCodePoint CR_In_CJK_Compatibility_Forms[] = {
- 1,
- 0xfe30, 0xfe4f,
-}; /* CR_In_CJK_Compatibility_Forms */
-
-/* 'In_Small_Form_Variants': Block */
-static const OnigCodePoint CR_In_Small_Form_Variants[] = {
- 1,
- 0xfe50, 0xfe6f,
-}; /* CR_In_Small_Form_Variants */
-
-/* 'In_Arabic_Presentation_Forms_B': Block */
-static const OnigCodePoint CR_In_Arabic_Presentation_Forms_B[] = {
- 1,
- 0xfe70, 0xfeff,
-}; /* CR_In_Arabic_Presentation_Forms_B */
-
-/* 'In_Halfwidth_and_Fullwidth_Forms': Block */
-static const OnigCodePoint CR_In_Halfwidth_and_Fullwidth_Forms[] = {
- 1,
- 0xff00, 0xffef,
-}; /* CR_In_Halfwidth_and_Fullwidth_Forms */
-
-/* 'In_Specials': Block */
-static const OnigCodePoint CR_In_Specials[] = {
- 1,
- 0xfff0, 0xffff,
-}; /* CR_In_Specials */
-
-/* 'In_Linear_B_Syllabary': Block */
-static const OnigCodePoint CR_In_Linear_B_Syllabary[] = {
- 1,
- 0x10000, 0x1007f,
-}; /* CR_In_Linear_B_Syllabary */
-
-/* 'In_Linear_B_Ideograms': Block */
-static const OnigCodePoint CR_In_Linear_B_Ideograms[] = {
- 1,
- 0x10080, 0x100ff,
-}; /* CR_In_Linear_B_Ideograms */
-
-/* 'In_Aegean_Numbers': Block */
-static const OnigCodePoint CR_In_Aegean_Numbers[] = {
- 1,
- 0x10100, 0x1013f,
-}; /* CR_In_Aegean_Numbers */
-
-/* 'In_Ancient_Greek_Numbers': Block */
-static const OnigCodePoint CR_In_Ancient_Greek_Numbers[] = {
- 1,
- 0x10140, 0x1018f,
-}; /* CR_In_Ancient_Greek_Numbers */
-
-/* 'In_Ancient_Symbols': Block */
-static const OnigCodePoint CR_In_Ancient_Symbols[] = {
- 1,
- 0x10190, 0x101cf,
-}; /* CR_In_Ancient_Symbols */
-
-/* 'In_Phaistos_Disc': Block */
-static const OnigCodePoint CR_In_Phaistos_Disc[] = {
- 1,
- 0x101d0, 0x101ff,
-}; /* CR_In_Phaistos_Disc */
-
-/* 'In_Lycian': Block */
-static const OnigCodePoint CR_In_Lycian[] = {
- 1,
- 0x10280, 0x1029f,
-}; /* CR_In_Lycian */
-
-/* 'In_Carian': Block */
-static const OnigCodePoint CR_In_Carian[] = {
- 1,
- 0x102a0, 0x102df,
-}; /* CR_In_Carian */
-
-/* 'In_Coptic_Epact_Numbers': Block */
-static const OnigCodePoint CR_In_Coptic_Epact_Numbers[] = {
- 1,
- 0x102e0, 0x102ff,
-}; /* CR_In_Coptic_Epact_Numbers */
-
-/* 'In_Old_Italic': Block */
-static const OnigCodePoint CR_In_Old_Italic[] = {
- 1,
- 0x10300, 0x1032f,
-}; /* CR_In_Old_Italic */
-
-/* 'In_Gothic': Block */
-static const OnigCodePoint CR_In_Gothic[] = {
- 1,
- 0x10330, 0x1034f,
-}; /* CR_In_Gothic */
-
-/* 'In_Old_Permic': Block */
-static const OnigCodePoint CR_In_Old_Permic[] = {
- 1,
- 0x10350, 0x1037f,
-}; /* CR_In_Old_Permic */
-
-/* 'In_Ugaritic': Block */
-static const OnigCodePoint CR_In_Ugaritic[] = {
- 1,
- 0x10380, 0x1039f,
-}; /* CR_In_Ugaritic */
-
-/* 'In_Old_Persian': Block */
-static const OnigCodePoint CR_In_Old_Persian[] = {
- 1,
- 0x103a0, 0x103df,
-}; /* CR_In_Old_Persian */
-
-/* 'In_Deseret': Block */
-#define CR_In_Deseret CR_Deseret
-
-/* 'In_Shavian': Block */
-#define CR_In_Shavian CR_Shavian
-
-/* 'In_Osmanya': Block */
-static const OnigCodePoint CR_In_Osmanya[] = {
- 1,
- 0x10480, 0x104af,
-}; /* CR_In_Osmanya */
-
-/* 'In_Osage': Block */
-static const OnigCodePoint CR_In_Osage[] = {
- 1,
- 0x104b0, 0x104ff,
-}; /* CR_In_Osage */
-
-/* 'In_Elbasan': Block */
-static const OnigCodePoint CR_In_Elbasan[] = {
- 1,
- 0x10500, 0x1052f,
-}; /* CR_In_Elbasan */
-
-/* 'In_Caucasian_Albanian': Block */
-static const OnigCodePoint CR_In_Caucasian_Albanian[] = {
- 1,
- 0x10530, 0x1056f,
-}; /* CR_In_Caucasian_Albanian */
-
-/* 'In_Vithkuqi': Block */
-static const OnigCodePoint CR_In_Vithkuqi[] = {
- 1,
- 0x10570, 0x105bf,
-}; /* CR_In_Vithkuqi */
-
-/* 'In_Linear_A': Block */
-static const OnigCodePoint CR_In_Linear_A[] = {
- 1,
- 0x10600, 0x1077f,
-}; /* CR_In_Linear_A */
-
-/* 'In_Latin_Extended_F': Block */
-static const OnigCodePoint CR_In_Latin_Extended_F[] = {
- 1,
- 0x10780, 0x107bf,
-}; /* CR_In_Latin_Extended_F */
-
-/* 'In_Cypriot_Syllabary': Block */
-static const OnigCodePoint CR_In_Cypriot_Syllabary[] = {
- 1,
- 0x10800, 0x1083f,
-}; /* CR_In_Cypriot_Syllabary */
-
-/* 'In_Imperial_Aramaic': Block */
-static const OnigCodePoint CR_In_Imperial_Aramaic[] = {
- 1,
- 0x10840, 0x1085f,
-}; /* CR_In_Imperial_Aramaic */
-
-/* 'In_Palmyrene': Block */
-#define CR_In_Palmyrene CR_Palmyrene
-
-/* 'In_Nabataean': Block */
-static const OnigCodePoint CR_In_Nabataean[] = {
- 1,
- 0x10880, 0x108af,
-}; /* CR_In_Nabataean */
-
-/* 'In_Hatran': Block */
-static const OnigCodePoint CR_In_Hatran[] = {
- 1,
- 0x108e0, 0x108ff,
-}; /* CR_In_Hatran */
-
-/* 'In_Phoenician': Block */
-static const OnigCodePoint CR_In_Phoenician[] = {
- 1,
- 0x10900, 0x1091f,
-}; /* CR_In_Phoenician */
-
-/* 'In_Lydian': Block */
-static const OnigCodePoint CR_In_Lydian[] = {
- 1,
- 0x10920, 0x1093f,
-}; /* CR_In_Lydian */
-
-/* 'In_Meroitic_Hieroglyphs': Block */
-#define CR_In_Meroitic_Hieroglyphs CR_Meroitic_Hieroglyphs
-
-/* 'In_Meroitic_Cursive': Block */
-static const OnigCodePoint CR_In_Meroitic_Cursive[] = {
- 1,
- 0x109a0, 0x109ff,
-}; /* CR_In_Meroitic_Cursive */
-
-/* 'In_Kharoshthi': Block */
-static const OnigCodePoint CR_In_Kharoshthi[] = {
- 1,
- 0x10a00, 0x10a5f,
-}; /* CR_In_Kharoshthi */
-
-/* 'In_Old_South_Arabian': Block */
-#define CR_In_Old_South_Arabian CR_Old_South_Arabian
-
-/* 'In_Old_North_Arabian': Block */
-#define CR_In_Old_North_Arabian CR_Old_North_Arabian
-
-/* 'In_Manichaean': Block */
-static const OnigCodePoint CR_In_Manichaean[] = {
- 1,
- 0x10ac0, 0x10aff,
-}; /* CR_In_Manichaean */
-
-/* 'In_Avestan': Block */
-static const OnigCodePoint CR_In_Avestan[] = {
- 1,
- 0x10b00, 0x10b3f,
-}; /* CR_In_Avestan */
-
-/* 'In_Inscriptional_Parthian': Block */
-static const OnigCodePoint CR_In_Inscriptional_Parthian[] = {
- 1,
- 0x10b40, 0x10b5f,
-}; /* CR_In_Inscriptional_Parthian */
-
-/* 'In_Inscriptional_Pahlavi': Block */
-static const OnigCodePoint CR_In_Inscriptional_Pahlavi[] = {
- 1,
- 0x10b60, 0x10b7f,
-}; /* CR_In_Inscriptional_Pahlavi */
-
-/* 'In_Psalter_Pahlavi': Block */
-static const OnigCodePoint CR_In_Psalter_Pahlavi[] = {
- 1,
- 0x10b80, 0x10baf,
-}; /* CR_In_Psalter_Pahlavi */
-
-/* 'In_Old_Turkic': Block */
-static const OnigCodePoint CR_In_Old_Turkic[] = {
- 1,
- 0x10c00, 0x10c4f,
-}; /* CR_In_Old_Turkic */
-
-/* 'In_Old_Hungarian': Block */
-static const OnigCodePoint CR_In_Old_Hungarian[] = {
- 1,
- 0x10c80, 0x10cff,
-}; /* CR_In_Old_Hungarian */
-
-/* 'In_Hanifi_Rohingya': Block */
-static const OnigCodePoint CR_In_Hanifi_Rohingya[] = {
- 1,
- 0x10d00, 0x10d3f,
-}; /* CR_In_Hanifi_Rohingya */
-
-/* 'In_Rumi_Numeral_Symbols': Block */
-static const OnigCodePoint CR_In_Rumi_Numeral_Symbols[] = {
- 1,
- 0x10e60, 0x10e7f,
-}; /* CR_In_Rumi_Numeral_Symbols */
-
-/* 'In_Yezidi': Block */
-static const OnigCodePoint CR_In_Yezidi[] = {
- 1,
- 0x10e80, 0x10ebf,
-}; /* CR_In_Yezidi */
-
-/* 'In_Arabic_Extended_C': Block */
-static const OnigCodePoint CR_In_Arabic_Extended_C[] = {
- 1,
- 0x10ec0, 0x10eff,
-}; /* CR_In_Arabic_Extended_C */
-
-/* 'In_Old_Sogdian': Block */
-static const OnigCodePoint CR_In_Old_Sogdian[] = {
- 1,
- 0x10f00, 0x10f2f,
-}; /* CR_In_Old_Sogdian */
-
-/* 'In_Sogdian': Block */
-static const OnigCodePoint CR_In_Sogdian[] = {
- 1,
- 0x10f30, 0x10f6f,
-}; /* CR_In_Sogdian */
-
-/* 'In_Old_Uyghur': Block */
-static const OnigCodePoint CR_In_Old_Uyghur[] = {
- 1,
- 0x10f70, 0x10faf,
-}; /* CR_In_Old_Uyghur */
-
-/* '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,
- 0x10fe0, 0x10fff,
-}; /* CR_In_Elymaic */
-
-/* 'In_Brahmi': Block */
-static const OnigCodePoint CR_In_Brahmi[] = {
- 1,
- 0x11000, 0x1107f,
-}; /* CR_In_Brahmi */
-
-/* 'In_Kaithi': Block */
-static const OnigCodePoint CR_In_Kaithi[] = {
- 1,
- 0x11080, 0x110cf,
-}; /* CR_In_Kaithi */
-
-/* 'In_Sora_Sompeng': Block */
-static const OnigCodePoint CR_In_Sora_Sompeng[] = {
- 1,
- 0x110d0, 0x110ff,
-}; /* CR_In_Sora_Sompeng */
-
-/* 'In_Chakma': Block */
-static const OnigCodePoint CR_In_Chakma[] = {
- 1,
- 0x11100, 0x1114f,
-}; /* CR_In_Chakma */
-
-/* 'In_Mahajani': Block */
-static const OnigCodePoint CR_In_Mahajani[] = {
- 1,
- 0x11150, 0x1117f,
-}; /* CR_In_Mahajani */
-
-/* 'In_Sharada': Block */
-#define CR_In_Sharada CR_Sharada
-
-/* 'In_Sinhala_Archaic_Numbers': Block */
-static const OnigCodePoint CR_In_Sinhala_Archaic_Numbers[] = {
- 1,
- 0x111e0, 0x111ff,
-}; /* CR_In_Sinhala_Archaic_Numbers */
-
-/* 'In_Khojki': Block */
-static const OnigCodePoint CR_In_Khojki[] = {
- 1,
- 0x11200, 0x1124f,
-}; /* CR_In_Khojki */
-
-/* 'In_Multani': Block */
-static const OnigCodePoint CR_In_Multani[] = {
- 1,
- 0x11280, 0x112af,
-}; /* CR_In_Multani */
-
-/* 'In_Khudawadi': Block */
-static const OnigCodePoint CR_In_Khudawadi[] = {
- 1,
- 0x112b0, 0x112ff,
-}; /* CR_In_Khudawadi */
-
-/* 'In_Grantha': Block */
-static const OnigCodePoint CR_In_Grantha[] = {
- 1,
- 0x11300, 0x1137f,
-}; /* CR_In_Grantha */
-
-/* 'In_Newa': Block */
-static const OnigCodePoint CR_In_Newa[] = {
- 1,
- 0x11400, 0x1147f,
-}; /* CR_In_Newa */
-
-/* 'In_Tirhuta': Block */
-static const OnigCodePoint CR_In_Tirhuta[] = {
- 1,
- 0x11480, 0x114df,
-}; /* CR_In_Tirhuta */
-
-/* 'In_Siddham': Block */
-static const OnigCodePoint CR_In_Siddham[] = {
- 1,
- 0x11580, 0x115ff,
-}; /* CR_In_Siddham */
-
-/* 'In_Modi': Block */
-static const OnigCodePoint CR_In_Modi[] = {
- 1,
- 0x11600, 0x1165f,
-}; /* CR_In_Modi */
-
-/* 'In_Mongolian_Supplement': Block */
-static const OnigCodePoint CR_In_Mongolian_Supplement[] = {
- 1,
- 0x11660, 0x1167f,
-}; /* CR_In_Mongolian_Supplement */
-
-/* 'In_Takri': Block */
-static const OnigCodePoint CR_In_Takri[] = {
- 1,
- 0x11680, 0x116cf,
-}; /* CR_In_Takri */
-
-/* 'In_Ahom': Block */
-static const OnigCodePoint CR_In_Ahom[] = {
- 1,
- 0x11700, 0x1174f,
-}; /* CR_In_Ahom */
-
-/* 'In_Dogra': Block */
-static const OnigCodePoint CR_In_Dogra[] = {
- 1,
- 0x11800, 0x1184f,
-}; /* CR_In_Dogra */
-
-/* 'In_Warang_Citi': Block */
-static const OnigCodePoint CR_In_Warang_Citi[] = {
- 1,
- 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,
- 0x119a0, 0x119ff,
-}; /* CR_In_Nandinagari */
-
-/* 'In_Zanabazar_Square': Block */
-static const OnigCodePoint CR_In_Zanabazar_Square[] = {
- 1,
- 0x11a00, 0x11a4f,
-}; /* CR_In_Zanabazar_Square */
-
-/* 'In_Soyombo': Block */
-static const OnigCodePoint CR_In_Soyombo[] = {
- 1,
- 0x11a50, 0x11aaf,
-}; /* CR_In_Soyombo */
-
-/* 'In_Unified_Canadian_Aboriginal_Syllabics_Extended_A': Block */
-static const OnigCodePoint CR_In_Unified_Canadian_Aboriginal_Syllabics_Extended_A[] = {
- 1,
- 0x11ab0, 0x11abf,
-}; /* CR_In_Unified_Canadian_Aboriginal_Syllabics_Extended_A */
-
-/* 'In_Pau_Cin_Hau': Block */
-static const OnigCodePoint CR_In_Pau_Cin_Hau[] = {
- 1,
- 0x11ac0, 0x11aff,
-}; /* CR_In_Pau_Cin_Hau */
-
-/* 'In_Devanagari_Extended_A': Block */
-static const OnigCodePoint CR_In_Devanagari_Extended_A[] = {
- 1,
- 0x11b00, 0x11b5f,
-}; /* CR_In_Devanagari_Extended_A */
-
-/* 'In_Bhaiksuki': Block */
-static const OnigCodePoint CR_In_Bhaiksuki[] = {
- 1,
- 0x11c00, 0x11c6f,
-}; /* CR_In_Bhaiksuki */
-
-/* 'In_Marchen': Block */
-static const OnigCodePoint CR_In_Marchen[] = {
- 1,
- 0x11c70, 0x11cbf,
-}; /* CR_In_Marchen */
-
-/* 'In_Masaram_Gondi': Block */
-static const OnigCodePoint CR_In_Masaram_Gondi[] = {
- 1,
- 0x11d00, 0x11d5f,
-}; /* CR_In_Masaram_Gondi */
-
-/* 'In_Gunjala_Gondi': Block */
-static const OnigCodePoint CR_In_Gunjala_Gondi[] = {
- 1,
- 0x11d60, 0x11daf,
-}; /* CR_In_Gunjala_Gondi */
-
-/* 'In_Makasar': Block */
-static const OnigCodePoint CR_In_Makasar[] = {
- 1,
- 0x11ee0, 0x11eff,
-}; /* CR_In_Makasar */
-
-/* 'In_Kawi': Block */
-static const OnigCodePoint CR_In_Kawi[] = {
- 1,
- 0x11f00, 0x11f5f,
-}; /* CR_In_Kawi */
-
-/* '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,
- 0x11fc0, 0x11fff,
-}; /* CR_In_Tamil_Supplement */
-
-/* 'In_Cuneiform': Block */
-static const OnigCodePoint CR_In_Cuneiform[] = {
- 1,
- 0x12000, 0x123ff,
-}; /* CR_In_Cuneiform */
-
-/* 'In_Cuneiform_Numbers_and_Punctuation': Block */
-static const OnigCodePoint CR_In_Cuneiform_Numbers_and_Punctuation[] = {
- 1,
- 0x12400, 0x1247f,
-}; /* CR_In_Cuneiform_Numbers_and_Punctuation */
-
-/* 'In_Early_Dynastic_Cuneiform': Block */
-static const OnigCodePoint CR_In_Early_Dynastic_Cuneiform[] = {
- 1,
- 0x12480, 0x1254f,
-}; /* CR_In_Early_Dynastic_Cuneiform */
-
-/* 'In_Cypro_Minoan': Block */
-static const OnigCodePoint CR_In_Cypro_Minoan[] = {
- 1,
- 0x12f90, 0x12fff,
-}; /* CR_In_Cypro_Minoan */
-
-/* 'In_Egyptian_Hieroglyphs': Block */
-static const OnigCodePoint CR_In_Egyptian_Hieroglyphs[] = {
- 1,
- 0x13000, 0x1342f,
-}; /* CR_In_Egyptian_Hieroglyphs */
-
-/* 'In_Egyptian_Hieroglyph_Format_Controls': Block */
-static const OnigCodePoint CR_In_Egyptian_Hieroglyph_Format_Controls[] = {
- 1,
- 0x13430, 0x1345f,
-}; /* CR_In_Egyptian_Hieroglyph_Format_Controls */
-
-/* 'In_Anatolian_Hieroglyphs': Block */
-static const OnigCodePoint CR_In_Anatolian_Hieroglyphs[] = {
- 1,
- 0x14400, 0x1467f,
-}; /* CR_In_Anatolian_Hieroglyphs */
-
-/* 'In_Bamum_Supplement': Block */
-static const OnigCodePoint CR_In_Bamum_Supplement[] = {
- 1,
- 0x16800, 0x16a3f,
-}; /* CR_In_Bamum_Supplement */
-
-/* 'In_Mro': Block */
-static const OnigCodePoint CR_In_Mro[] = {
- 1,
- 0x16a40, 0x16a6f,
-}; /* CR_In_Mro */
-
-/* 'In_Tangsa': Block */
-static const OnigCodePoint CR_In_Tangsa[] = {
- 1,
- 0x16a70, 0x16acf,
-}; /* CR_In_Tangsa */
-
-/* 'In_Bassa_Vah': Block */
-static const OnigCodePoint CR_In_Bassa_Vah[] = {
- 1,
- 0x16ad0, 0x16aff,
-}; /* CR_In_Bassa_Vah */
-
-/* 'In_Pahawh_Hmong': Block */
-static const OnigCodePoint CR_In_Pahawh_Hmong[] = {
- 1,
- 0x16b00, 0x16b8f,
-}; /* CR_In_Pahawh_Hmong */
-
-/* 'In_Medefaidrin': Block */
-static const OnigCodePoint CR_In_Medefaidrin[] = {
- 1,
- 0x16e40, 0x16e9f,
-}; /* CR_In_Medefaidrin */
-
-/* 'In_Miao': Block */
-static const OnigCodePoint CR_In_Miao[] = {
- 1,
- 0x16f00, 0x16f9f,
-}; /* CR_In_Miao */
-
-/* 'In_Ideographic_Symbols_and_Punctuation': Block */
-static const OnigCodePoint CR_In_Ideographic_Symbols_and_Punctuation[] = {
- 1,
- 0x16fe0, 0x16fff,
-}; /* CR_In_Ideographic_Symbols_and_Punctuation */
-
-/* 'In_Tangut': Block */
-static const OnigCodePoint CR_In_Tangut[] = {
- 1,
- 0x17000, 0x187ff,
-}; /* CR_In_Tangut */
-
-/* 'In_Tangut_Components': Block */
-static const OnigCodePoint CR_In_Tangut_Components[] = {
- 1,
- 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, 0x18d7f,
-}; /* CR_In_Tangut_Supplement */
-
-/* 'In_Kana_Extended_B': Block */
-static const OnigCodePoint CR_In_Kana_Extended_B[] = {
- 1,
- 0x1aff0, 0x1afff,
-}; /* CR_In_Kana_Extended_B */
-
-/* 'In_Kana_Supplement': Block */
-static const OnigCodePoint CR_In_Kana_Supplement[] = {
- 1,
- 0x1b000, 0x1b0ff,
-}; /* CR_In_Kana_Supplement */
-
-/* 'In_Kana_Extended_A': Block */
-static const OnigCodePoint CR_In_Kana_Extended_A[] = {
- 1,
- 0x1b100, 0x1b12f,
-}; /* CR_In_Kana_Extended_A */
-
-/* 'In_Small_Kana_Extension': Block */
-static const OnigCodePoint CR_In_Small_Kana_Extension[] = {
- 1,
- 0x1b130, 0x1b16f,
-}; /* CR_In_Small_Kana_Extension */
-
-/* 'In_Nushu': Block */
-static const OnigCodePoint CR_In_Nushu[] = {
- 1,
- 0x1b170, 0x1b2ff,
-}; /* CR_In_Nushu */
-
-/* 'In_Duployan': Block */
-static const OnigCodePoint CR_In_Duployan[] = {
- 1,
- 0x1bc00, 0x1bc9f,
-}; /* CR_In_Duployan */
-
-/* 'In_Shorthand_Format_Controls': Block */
-static const OnigCodePoint CR_In_Shorthand_Format_Controls[] = {
- 1,
- 0x1bca0, 0x1bcaf,
-}; /* CR_In_Shorthand_Format_Controls */
-
-/* 'In_Znamenny_Musical_Notation': Block */
-static const OnigCodePoint CR_In_Znamenny_Musical_Notation[] = {
- 1,
- 0x1cf00, 0x1cfcf,
-}; /* CR_In_Znamenny_Musical_Notation */
-
-/* 'In_Byzantine_Musical_Symbols': Block */
-static const OnigCodePoint CR_In_Byzantine_Musical_Symbols[] = {
- 1,
- 0x1d000, 0x1d0ff,
-}; /* CR_In_Byzantine_Musical_Symbols */
-
-/* 'In_Musical_Symbols': Block */
-static const OnigCodePoint CR_In_Musical_Symbols[] = {
- 1,
- 0x1d100, 0x1d1ff,
-}; /* CR_In_Musical_Symbols */
-
-/* 'In_Ancient_Greek_Musical_Notation': Block */
-static const OnigCodePoint CR_In_Ancient_Greek_Musical_Notation[] = {
- 1,
- 0x1d200, 0x1d24f,
-}; /* CR_In_Ancient_Greek_Musical_Notation */
-
-/* 'In_Kaktovik_Numerals': Block */
-static const OnigCodePoint CR_In_Kaktovik_Numerals[] = {
- 1,
- 0x1d2c0, 0x1d2df,
-}; /* CR_In_Kaktovik_Numerals */
-
-/* 'In_Mayan_Numerals': Block */
-static const OnigCodePoint CR_In_Mayan_Numerals[] = {
- 1,
- 0x1d2e0, 0x1d2ff,
-}; /* CR_In_Mayan_Numerals */
-
-/* 'In_Tai_Xuan_Jing_Symbols': Block */
-static const OnigCodePoint CR_In_Tai_Xuan_Jing_Symbols[] = {
- 1,
- 0x1d300, 0x1d35f,
-}; /* CR_In_Tai_Xuan_Jing_Symbols */
-
-/* 'In_Counting_Rod_Numerals': Block */
-static const OnigCodePoint CR_In_Counting_Rod_Numerals[] = {
- 1,
- 0x1d360, 0x1d37f,
-}; /* CR_In_Counting_Rod_Numerals */
-
-/* 'In_Mathematical_Alphanumeric_Symbols': Block */
-static const OnigCodePoint CR_In_Mathematical_Alphanumeric_Symbols[] = {
- 1,
- 0x1d400, 0x1d7ff,
-}; /* CR_In_Mathematical_Alphanumeric_Symbols */
-
-/* 'In_Sutton_SignWriting': Block */
-static const OnigCodePoint CR_In_Sutton_SignWriting[] = {
- 1,
- 0x1d800, 0x1daaf,
-}; /* CR_In_Sutton_SignWriting */
-
-/* 'In_Latin_Extended_G': Block */
-static const OnigCodePoint CR_In_Latin_Extended_G[] = {
- 1,
- 0x1df00, 0x1dfff,
-}; /* CR_In_Latin_Extended_G */
-
-/* 'In_Glagolitic_Supplement': Block */
-static const OnigCodePoint CR_In_Glagolitic_Supplement[] = {
- 1,
- 0x1e000, 0x1e02f,
-}; /* CR_In_Glagolitic_Supplement */
-
-/* 'In_Cyrillic_Extended_D': Block */
-static const OnigCodePoint CR_In_Cyrillic_Extended_D[] = {
- 1,
- 0x1e030, 0x1e08f,
-}; /* CR_In_Cyrillic_Extended_D */
-
-/* 'In_Nyiakeng_Puachue_Hmong': Block */
-static const OnigCodePoint CR_In_Nyiakeng_Puachue_Hmong[] = {
- 1,
- 0x1e100, 0x1e14f,
-}; /* CR_In_Nyiakeng_Puachue_Hmong */
-
-/* 'In_Toto': Block */
-static const OnigCodePoint CR_In_Toto[] = {
- 1,
- 0x1e290, 0x1e2bf,
-}; /* CR_In_Toto */
-
-/* 'In_Wancho': Block */
-static const OnigCodePoint CR_In_Wancho[] = {
- 1,
- 0x1e2c0, 0x1e2ff,
-}; /* CR_In_Wancho */
-
-/* 'In_Nag_Mundari': Block */
-static const OnigCodePoint CR_In_Nag_Mundari[] = {
- 1,
- 0x1e4d0, 0x1e4ff,
-}; /* CR_In_Nag_Mundari */
-
-/* 'In_Ethiopic_Extended_B': Block */
-static const OnigCodePoint CR_In_Ethiopic_Extended_B[] = {
- 1,
- 0x1e7e0, 0x1e7ff,
-}; /* CR_In_Ethiopic_Extended_B */
-
-/* 'In_Mende_Kikakui': Block */
-static const OnigCodePoint CR_In_Mende_Kikakui[] = {
- 1,
- 0x1e800, 0x1e8df,
-}; /* CR_In_Mende_Kikakui */
-
-/* 'In_Adlam': Block */
-static const OnigCodePoint CR_In_Adlam[] = {
- 1,
- 0x1e900, 0x1e95f,
-}; /* CR_In_Adlam */
-
-/* 'In_Indic_Siyaq_Numbers': Block */
-static const OnigCodePoint CR_In_Indic_Siyaq_Numbers[] = {
- 1,
- 0x1ec70, 0x1ecbf,
-}; /* CR_In_Indic_Siyaq_Numbers */
-
-/* 'In_Ottoman_Siyaq_Numbers': Block */
-static const OnigCodePoint CR_In_Ottoman_Siyaq_Numbers[] = {
- 1,
- 0x1ed00, 0x1ed4f,
-}; /* CR_In_Ottoman_Siyaq_Numbers */
-
-/* 'In_Arabic_Mathematical_Alphabetic_Symbols': Block */
-static const OnigCodePoint CR_In_Arabic_Mathematical_Alphabetic_Symbols[] = {
- 1,
- 0x1ee00, 0x1eeff,
-}; /* CR_In_Arabic_Mathematical_Alphabetic_Symbols */
-
-/* 'In_Mahjong_Tiles': Block */
-static const OnigCodePoint CR_In_Mahjong_Tiles[] = {
- 1,
- 0x1f000, 0x1f02f,
-}; /* CR_In_Mahjong_Tiles */
-
-/* 'In_Domino_Tiles': Block */
-static const OnigCodePoint CR_In_Domino_Tiles[] = {
- 1,
- 0x1f030, 0x1f09f,
-}; /* CR_In_Domino_Tiles */
-
-/* 'In_Playing_Cards': Block */
-static const OnigCodePoint CR_In_Playing_Cards[] = {
- 1,
- 0x1f0a0, 0x1f0ff,
-}; /* CR_In_Playing_Cards */
-
-/* 'In_Enclosed_Alphanumeric_Supplement': Block */
-static const OnigCodePoint CR_In_Enclosed_Alphanumeric_Supplement[] = {
- 1,
- 0x1f100, 0x1f1ff,
-}; /* CR_In_Enclosed_Alphanumeric_Supplement */
-
-/* 'In_Enclosed_Ideographic_Supplement': Block */
-static const OnigCodePoint CR_In_Enclosed_Ideographic_Supplement[] = {
- 1,
- 0x1f200, 0x1f2ff,
-}; /* CR_In_Enclosed_Ideographic_Supplement */
-
-/* 'In_Miscellaneous_Symbols_and_Pictographs': Block */
-static const OnigCodePoint CR_In_Miscellaneous_Symbols_and_Pictographs[] = {
- 1,
- 0x1f300, 0x1f5ff,
-}; /* CR_In_Miscellaneous_Symbols_and_Pictographs */
-
-/* 'In_Emoticons': Block */
-static const OnigCodePoint CR_In_Emoticons[] = {
- 1,
- 0x1f600, 0x1f64f,
-}; /* CR_In_Emoticons */
-
-/* 'In_Ornamental_Dingbats': Block */
-static const OnigCodePoint CR_In_Ornamental_Dingbats[] = {
- 1,
- 0x1f650, 0x1f67f,
-}; /* CR_In_Ornamental_Dingbats */
-
-/* 'In_Transport_and_Map_Symbols': Block */
-static const OnigCodePoint CR_In_Transport_and_Map_Symbols[] = {
- 1,
- 0x1f680, 0x1f6ff,
-}; /* CR_In_Transport_and_Map_Symbols */
-
-/* 'In_Alchemical_Symbols': Block */
-static const OnigCodePoint CR_In_Alchemical_Symbols[] = {
- 1,
- 0x1f700, 0x1f77f,
-}; /* CR_In_Alchemical_Symbols */
-
-/* 'In_Geometric_Shapes_Extended': Block */
-static const OnigCodePoint CR_In_Geometric_Shapes_Extended[] = {
- 1,
- 0x1f780, 0x1f7ff,
-}; /* CR_In_Geometric_Shapes_Extended */
-
-/* 'In_Supplemental_Arrows_C': Block */
-static const OnigCodePoint CR_In_Supplemental_Arrows_C[] = {
- 1,
- 0x1f800, 0x1f8ff,
-}; /* CR_In_Supplemental_Arrows_C */
-
-/* 'In_Supplemental_Symbols_and_Pictographs': Block */
-static const OnigCodePoint CR_In_Supplemental_Symbols_and_Pictographs[] = {
- 1,
- 0x1f900, 0x1f9ff,
-}; /* CR_In_Supplemental_Symbols_and_Pictographs */
-
-/* 'In_Chess_Symbols': Block */
-static const OnigCodePoint CR_In_Chess_Symbols[] = {
- 1,
- 0x1fa00, 0x1fa6f,
-}; /* CR_In_Chess_Symbols */
-
-/* 'In_Symbols_and_Pictographs_Extended_A': Block */
-static const OnigCodePoint CR_In_Symbols_and_Pictographs_Extended_A[] = {
- 1,
- 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,
- 0x20000, 0x2a6df,
-}; /* CR_In_CJK_Unified_Ideographs_Extension_B */
-
-/* 'In_CJK_Unified_Ideographs_Extension_C': Block */
-static const OnigCodePoint CR_In_CJK_Unified_Ideographs_Extension_C[] = {
- 1,
- 0x2a700, 0x2b73f,
-}; /* CR_In_CJK_Unified_Ideographs_Extension_C */
-
-/* 'In_CJK_Unified_Ideographs_Extension_D': Block */
-static const OnigCodePoint CR_In_CJK_Unified_Ideographs_Extension_D[] = {
- 1,
- 0x2b740, 0x2b81f,
-}; /* CR_In_CJK_Unified_Ideographs_Extension_D */
-
-/* 'In_CJK_Unified_Ideographs_Extension_E': Block */
-static const OnigCodePoint CR_In_CJK_Unified_Ideographs_Extension_E[] = {
- 1,
- 0x2b820, 0x2ceaf,
-}; /* CR_In_CJK_Unified_Ideographs_Extension_E */
-
-/* 'In_CJK_Unified_Ideographs_Extension_F': Block */
-static const OnigCodePoint CR_In_CJK_Unified_Ideographs_Extension_F[] = {
- 1,
- 0x2ceb0, 0x2ebef,
-}; /* CR_In_CJK_Unified_Ideographs_Extension_F */
-
-/* 'In_CJK_Compatibility_Ideographs_Supplement': Block */
-static const OnigCodePoint CR_In_CJK_Compatibility_Ideographs_Supplement[] = {
- 1,
- 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_CJK_Unified_Ideographs_Extension_H': Block */
-static const OnigCodePoint CR_In_CJK_Unified_Ideographs_Extension_H[] = {
- 1,
- 0x31350, 0x323af,
-}; /* CR_In_CJK_Unified_Ideographs_Extension_H */
-
-/* 'In_Tags': Block */
-static const OnigCodePoint CR_In_Tags[] = {
- 1,
- 0xe0000, 0xe007f,
-}; /* CR_In_Tags */
-
-/* 'In_Variation_Selectors_Supplement': Block */
-static const OnigCodePoint CR_In_Variation_Selectors_Supplement[] = {
- 1,
- 0xe0100, 0xe01ef,
-}; /* CR_In_Variation_Selectors_Supplement */
-
-/* 'In_Supplementary_Private_Use_Area_A': Block */
-static const OnigCodePoint CR_In_Supplementary_Private_Use_Area_A[] = {
- 1,
- 0xf0000, 0xfffff,
-}; /* CR_In_Supplementary_Private_Use_Area_A */
-
-/* 'In_Supplementary_Private_Use_Area_B': Block */
-static const OnigCodePoint CR_In_Supplementary_Private_Use_Area_B[] = {
- 1,
- 0x100000, 0x10ffff,
-}; /* CR_In_Supplementary_Private_Use_Area_B */
-
-/* 'In_No_Block': Block */
-static const OnigCodePoint CR_In_No_Block[] = {
- 51,
- 0x2fe0, 0x2fef,
- 0x10200, 0x1027f,
- 0x103e0, 0x103ff,
- 0x105c0, 0x105ff,
- 0x107c0, 0x107ff,
- 0x108b0, 0x108df,
- 0x10940, 0x1097f,
- 0x10aa0, 0x10abf,
- 0x10bb0, 0x10bff,
- 0x10c50, 0x10c7f,
- 0x10d40, 0x10e5f,
- 0x11250, 0x1127f,
- 0x11380, 0x113ff,
- 0x114e0, 0x1157f,
- 0x116d0, 0x116ff,
- 0x11750, 0x117ff,
- 0x11850, 0x1189f,
- 0x11960, 0x1199f,
- 0x11b60, 0x11bff,
- 0x11cc0, 0x11cff,
- 0x11db0, 0x11edf,
- 0x11f60, 0x11faf,
- 0x12550, 0x12f8f,
- 0x13460, 0x143ff,
- 0x14680, 0x167ff,
- 0x16b90, 0x16e3f,
- 0x16ea0, 0x16eff,
- 0x16fa0, 0x16fdf,
- 0x18d80, 0x1afef,
- 0x1b300, 0x1bbff,
- 0x1bcb0, 0x1ceff,
- 0x1cfd0, 0x1cfff,
- 0x1d250, 0x1d2bf,
- 0x1d380, 0x1d3ff,
- 0x1dab0, 0x1deff,
- 0x1e090, 0x1e0ff,
- 0x1e150, 0x1e28f,
- 0x1e300, 0x1e4cf,
- 0x1e500, 0x1e7df,
- 0x1e8e0, 0x1e8ff,
- 0x1e960, 0x1ec6f,
- 0x1ecc0, 0x1ecff,
- 0x1ed50, 0x1edff,
- 0x1ef00, 0x1efff,
- 0x1fc00, 0x1ffff,
- 0x2a6e0, 0x2a6ff,
- 0x2ebf0, 0x2f7ff,
- 0x2fa20, 0x2ffff,
- 0x323b0, 0xdffff,
- 0xe0080, 0xe00ff,
- 0xe01f0, 0xeffff,
-}; /* CR_In_No_Block */
-
-#endif /* USE_UNICODE_PROPERTIES */
-static const OnigCodePoint* const CodeRanges[] = {
- CR_NEWLINE,
- CR_Alpha,
- CR_Blank,
- CR_Cntrl,
- CR_Digit,
- CR_Graph,
- CR_Lower,
- CR_Print,
- CR_XPosixPunct,
- CR_Space,
- CR_Upper,
- CR_XDigit,
- CR_Word,
- CR_Alnum,
- CR_ASCII,
- CR_Punct,
-#ifdef USE_UNICODE_PROPERTIES
- CR_Any,
- CR_Assigned,
- CR_C,
- CR_Cc,
- CR_Cf,
- CR_Cn,
- CR_Co,
- CR_Cs,
- CR_L,
- CR_LC,
- CR_Ll,
- CR_Lm,
- CR_Lo,
- CR_Lt,
- CR_Lu,
- CR_M,
- CR_Mc,
- CR_Me,
- CR_Mn,
- CR_N,
- CR_Nd,
- CR_Nl,
- CR_No,
- CR_P,
- CR_Pc,
- CR_Pd,
- CR_Pe,
- CR_Pf,
- CR_Pi,
- CR_Po,
- CR_Ps,
- CR_S,
- CR_Sc,
- CR_Sk,
- CR_Sm,
- CR_So,
- CR_Z,
- CR_Zl,
- CR_Zp,
- CR_Zs,
- CR_Math,
- CR_Alphabetic,
- CR_Lowercase,
- CR_Uppercase,
- CR_Cased,
- CR_Case_Ignorable,
- CR_Changes_When_Lowercased,
- CR_Changes_When_Uppercased,
- CR_Changes_When_Titlecased,
- CR_Changes_When_Casefolded,
- CR_Changes_When_Casemapped,
- CR_ID_Start,
- CR_ID_Continue,
- CR_XID_Start,
- CR_XID_Continue,
- CR_Default_Ignorable_Code_Point,
- CR_Grapheme_Extend,
- CR_Grapheme_Base,
- CR_Grapheme_Link,
- CR_Common,
- CR_Latin,
- CR_Greek,
- CR_Cyrillic,
- CR_Armenian,
- CR_Hebrew,
- CR_Arabic,
- CR_Syriac,
- CR_Thaana,
- CR_Devanagari,
- CR_Bengali,
- CR_Gurmukhi,
- CR_Gujarati,
- CR_Oriya,
- CR_Tamil,
- CR_Telugu,
- CR_Kannada,
- CR_Malayalam,
- CR_Sinhala,
- CR_Thai,
- CR_Lao,
- CR_Tibetan,
- CR_Myanmar,
- CR_Georgian,
- CR_Hangul,
- CR_Ethiopic,
- CR_Cherokee,
- CR_Canadian_Aboriginal,
- CR_Ogham,
- CR_Runic,
- CR_Khmer,
- CR_Mongolian,
- CR_Hiragana,
- CR_Katakana,
- CR_Bopomofo,
- CR_Han,
- CR_Yi,
- CR_Old_Italic,
- CR_Gothic,
- CR_Deseret,
- CR_Inherited,
- CR_Tagalog,
- CR_Hanunoo,
- CR_Buhid,
- CR_Tagbanwa,
- CR_Limbu,
- CR_Tai_Le,
- CR_Linear_B,
- CR_Ugaritic,
- CR_Shavian,
- CR_Osmanya,
- CR_Cypriot,
- CR_Braille,
- CR_Buginese,
- CR_Coptic,
- CR_New_Tai_Lue,
- CR_Glagolitic,
- CR_Tifinagh,
- CR_Syloti_Nagri,
- CR_Old_Persian,
- CR_Kharoshthi,
- CR_Balinese,
- CR_Cuneiform,
- CR_Phoenician,
- CR_Phags_Pa,
- CR_Nko,
- CR_Sundanese,
- CR_Lepcha,
- CR_Ol_Chiki,
- CR_Vai,
- CR_Saurashtra,
- CR_Kayah_Li,
- CR_Rejang,
- CR_Lycian,
- CR_Carian,
- CR_Lydian,
- CR_Cham,
- CR_Tai_Tham,
- CR_Tai_Viet,
- CR_Avestan,
- CR_Egyptian_Hieroglyphs,
- CR_Samaritan,
- CR_Lisu,
- CR_Bamum,
- CR_Javanese,
- CR_Meetei_Mayek,
- CR_Imperial_Aramaic,
- CR_Old_South_Arabian,
- CR_Inscriptional_Parthian,
- CR_Inscriptional_Pahlavi,
- CR_Old_Turkic,
- CR_Kaithi,
- CR_Batak,
- CR_Brahmi,
- CR_Mandaic,
- CR_Chakma,
- CR_Meroitic_Cursive,
- CR_Meroitic_Hieroglyphs,
- CR_Miao,
- CR_Sharada,
- CR_Sora_Sompeng,
- CR_Takri,
- CR_Caucasian_Albanian,
- CR_Bassa_Vah,
- CR_Duployan,
- CR_Elbasan,
- CR_Grantha,
- CR_Pahawh_Hmong,
- CR_Khojki,
- CR_Linear_A,
- CR_Mahajani,
- CR_Manichaean,
- CR_Mende_Kikakui,
- CR_Modi,
- CR_Mro,
- CR_Old_North_Arabian,
- CR_Nabataean,
- CR_Palmyrene,
- CR_Pau_Cin_Hau,
- CR_Old_Permic,
- CR_Psalter_Pahlavi,
- CR_Siddham,
- CR_Khudawadi,
- CR_Tirhuta,
- CR_Warang_Citi,
- CR_Ahom,
- CR_Anatolian_Hieroglyphs,
- CR_Hatran,
- CR_Multani,
- CR_Old_Hungarian,
- CR_SignWriting,
- CR_Adlam,
- CR_Bhaiksuki,
- CR_Marchen,
- CR_Newa,
- CR_Osage,
- CR_Tangut,
- CR_Masaram_Gondi,
- CR_Nushu,
- CR_Soyombo,
- CR_Zanabazar_Square,
- CR_Dogra,
- CR_Gunjala_Gondi,
- CR_Makasar,
- CR_Medefaidrin,
- CR_Hanifi_Rohingya,
- CR_Sogdian,
- CR_Old_Sogdian,
- CR_Elymaic,
- CR_Nandinagari,
- CR_Nyiakeng_Puachue_Hmong,
- CR_Wancho,
- CR_Chorasmian,
- CR_Dives_Akuru,
- CR_Khitan_Small_Script,
- CR_Yezidi,
- CR_Cypro_Minoan,
- CR_Old_Uyghur,
- CR_Tangsa,
- CR_Toto,
- CR_Vithkuqi,
- CR_Kawi,
- CR_Nag_Mundari,
- CR_White_Space,
- CR_Bidi_Control,
- CR_Join_Control,
- CR_Dash,
- CR_Hyphen,
- CR_Quotation_Mark,
- CR_Terminal_Punctuation,
- CR_Other_Math,
- CR_Hex_Digit,
- CR_ASCII_Hex_Digit,
- CR_Other_Alphabetic,
- CR_Ideographic,
- CR_Diacritic,
- CR_Extender,
- CR_Other_Lowercase,
- CR_Other_Uppercase,
- CR_Noncharacter_Code_Point,
- CR_Other_Grapheme_Extend,
- CR_IDS_Binary_Operator,
- CR_IDS_Trinary_Operator,
- CR_Radical,
- CR_Unified_Ideograph,
- CR_Other_Default_Ignorable_Code_Point,
- CR_Deprecated,
- CR_Soft_Dotted,
- CR_Logical_Order_Exception,
- CR_Other_ID_Start,
- CR_Other_ID_Continue,
- CR_Sentence_Terminal,
- CR_Variation_Selector,
- CR_Pattern_White_Space,
- CR_Pattern_Syntax,
- CR_Prepended_Concatenation_Mark,
- CR_Regional_Indicator,
- CR_Emoji,
- CR_Emoji_Presentation,
- CR_Emoji_Modifier,
- CR_Emoji_Modifier_Base,
- CR_Emoji_Component,
- CR_Extended_Pictographic,
- CR_Unknown,
-#ifdef USE_UNICODE_AGE_PROPERTIES
- CR_Age_1_1,
- CR_Age_2_0,
- CR_Age_2_1,
- CR_Age_3_0,
- CR_Age_3_1,
- CR_Age_3_2,
- CR_Age_4_0,
- CR_Age_4_1,
- CR_Age_5_0,
- CR_Age_5_1,
- CR_Age_5_2,
- CR_Age_6_0,
- CR_Age_6_1,
- CR_Age_6_2,
- CR_Age_6_3,
- CR_Age_7_0,
- CR_Age_8_0,
- CR_Age_9_0,
- CR_Age_10_0,
- CR_Age_11_0,
- CR_Age_12_0,
- CR_Age_12_1,
- CR_Age_13_0,
- CR_Age_14_0,
- CR_Age_15_0,
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- CR_Grapheme_Cluster_Break_Prepend,
- CR_Grapheme_Cluster_Break_CR,
- CR_Grapheme_Cluster_Break_LF,
- CR_Grapheme_Cluster_Break_Control,
- CR_Grapheme_Cluster_Break_Extend,
- CR_Grapheme_Cluster_Break_Regional_Indicator,
- CR_Grapheme_Cluster_Break_SpacingMark,
- CR_Grapheme_Cluster_Break_L,
- CR_Grapheme_Cluster_Break_V,
- CR_Grapheme_Cluster_Break_T,
- CR_Grapheme_Cluster_Break_LV,
- CR_Grapheme_Cluster_Break_LVT,
- CR_Grapheme_Cluster_Break_ZWJ,
- CR_In_Basic_Latin,
- CR_In_Latin_1_Supplement,
- CR_In_Latin_Extended_A,
- CR_In_Latin_Extended_B,
- CR_In_IPA_Extensions,
- CR_In_Spacing_Modifier_Letters,
- CR_In_Combining_Diacritical_Marks,
- CR_In_Greek_and_Coptic,
- CR_In_Cyrillic,
- CR_In_Cyrillic_Supplement,
- CR_In_Armenian,
- CR_In_Hebrew,
- CR_In_Arabic,
- CR_In_Syriac,
- CR_In_Arabic_Supplement,
- CR_In_Thaana,
- CR_In_NKo,
- CR_In_Samaritan,
- CR_In_Mandaic,
- CR_In_Syriac_Supplement,
- CR_In_Arabic_Extended_B,
- CR_In_Arabic_Extended_A,
- CR_In_Devanagari,
- CR_In_Bengali,
- CR_In_Gurmukhi,
- CR_In_Gujarati,
- CR_In_Oriya,
- CR_In_Tamil,
- CR_In_Telugu,
- CR_In_Kannada,
- CR_In_Malayalam,
- CR_In_Sinhala,
- CR_In_Thai,
- CR_In_Lao,
- CR_In_Tibetan,
- CR_In_Myanmar,
- CR_In_Georgian,
- CR_In_Hangul_Jamo,
- CR_In_Ethiopic,
- CR_In_Ethiopic_Supplement,
- CR_In_Cherokee,
- CR_In_Unified_Canadian_Aboriginal_Syllabics,
- CR_In_Ogham,
- CR_In_Runic,
- CR_In_Tagalog,
- CR_In_Hanunoo,
- CR_In_Buhid,
- CR_In_Tagbanwa,
- CR_In_Khmer,
- CR_In_Mongolian,
- CR_In_Unified_Canadian_Aboriginal_Syllabics_Extended,
- CR_In_Limbu,
- CR_In_Tai_Le,
- CR_In_New_Tai_Lue,
- CR_In_Khmer_Symbols,
- CR_In_Buginese,
- CR_In_Tai_Tham,
- CR_In_Combining_Diacritical_Marks_Extended,
- CR_In_Balinese,
- CR_In_Sundanese,
- CR_In_Batak,
- CR_In_Lepcha,
- CR_In_Ol_Chiki,
- CR_In_Cyrillic_Extended_C,
- CR_In_Georgian_Extended,
- CR_In_Sundanese_Supplement,
- CR_In_Vedic_Extensions,
- CR_In_Phonetic_Extensions,
- CR_In_Phonetic_Extensions_Supplement,
- CR_In_Combining_Diacritical_Marks_Supplement,
- CR_In_Latin_Extended_Additional,
- CR_In_Greek_Extended,
- CR_In_General_Punctuation,
- CR_In_Superscripts_and_Subscripts,
- CR_In_Currency_Symbols,
- CR_In_Combining_Diacritical_Marks_for_Symbols,
- CR_In_Letterlike_Symbols,
- CR_In_Number_Forms,
- CR_In_Arrows,
- CR_In_Mathematical_Operators,
- CR_In_Miscellaneous_Technical,
- CR_In_Control_Pictures,
- CR_In_Optical_Character_Recognition,
- CR_In_Enclosed_Alphanumerics,
- CR_In_Box_Drawing,
- CR_In_Block_Elements,
- CR_In_Geometric_Shapes,
- CR_In_Miscellaneous_Symbols,
- CR_In_Dingbats,
- CR_In_Miscellaneous_Mathematical_Symbols_A,
- CR_In_Supplemental_Arrows_A,
- CR_In_Braille_Patterns,
- CR_In_Supplemental_Arrows_B,
- CR_In_Miscellaneous_Mathematical_Symbols_B,
- CR_In_Supplemental_Mathematical_Operators,
- CR_In_Miscellaneous_Symbols_and_Arrows,
- CR_In_Glagolitic,
- CR_In_Latin_Extended_C,
- CR_In_Coptic,
- CR_In_Georgian_Supplement,
- CR_In_Tifinagh,
- CR_In_Ethiopic_Extended,
- CR_In_Cyrillic_Extended_A,
- CR_In_Supplemental_Punctuation,
- CR_In_CJK_Radicals_Supplement,
- CR_In_Kangxi_Radicals,
- CR_In_Ideographic_Description_Characters,
- CR_In_CJK_Symbols_and_Punctuation,
- CR_In_Hiragana,
- CR_In_Katakana,
- CR_In_Bopomofo,
- CR_In_Hangul_Compatibility_Jamo,
- CR_In_Kanbun,
- CR_In_Bopomofo_Extended,
- CR_In_CJK_Strokes,
- CR_In_Katakana_Phonetic_Extensions,
- CR_In_Enclosed_CJK_Letters_and_Months,
- CR_In_CJK_Compatibility,
- CR_In_CJK_Unified_Ideographs_Extension_A,
- CR_In_Yijing_Hexagram_Symbols,
- CR_In_CJK_Unified_Ideographs,
- CR_In_Yi_Syllables,
- CR_In_Yi_Radicals,
- CR_In_Lisu,
- CR_In_Vai,
- CR_In_Cyrillic_Extended_B,
- CR_In_Bamum,
- CR_In_Modifier_Tone_Letters,
- CR_In_Latin_Extended_D,
- CR_In_Syloti_Nagri,
- CR_In_Common_Indic_Number_Forms,
- CR_In_Phags_pa,
- CR_In_Saurashtra,
- CR_In_Devanagari_Extended,
- CR_In_Kayah_Li,
- CR_In_Rejang,
- CR_In_Hangul_Jamo_Extended_A,
- CR_In_Javanese,
- CR_In_Myanmar_Extended_B,
- CR_In_Cham,
- CR_In_Myanmar_Extended_A,
- CR_In_Tai_Viet,
- CR_In_Meetei_Mayek_Extensions,
- CR_In_Ethiopic_Extended_A,
- CR_In_Latin_Extended_E,
- CR_In_Cherokee_Supplement,
- CR_In_Meetei_Mayek,
- CR_In_Hangul_Syllables,
- CR_In_Hangul_Jamo_Extended_B,
- CR_In_High_Surrogates,
- CR_In_High_Private_Use_Surrogates,
- CR_In_Low_Surrogates,
- CR_In_Private_Use_Area,
- CR_In_CJK_Compatibility_Ideographs,
- CR_In_Alphabetic_Presentation_Forms,
- CR_In_Arabic_Presentation_Forms_A,
- CR_In_Variation_Selectors,
- CR_In_Vertical_Forms,
- CR_In_Combining_Half_Marks,
- CR_In_CJK_Compatibility_Forms,
- CR_In_Small_Form_Variants,
- CR_In_Arabic_Presentation_Forms_B,
- CR_In_Halfwidth_and_Fullwidth_Forms,
- CR_In_Specials,
- CR_In_Linear_B_Syllabary,
- CR_In_Linear_B_Ideograms,
- CR_In_Aegean_Numbers,
- CR_In_Ancient_Greek_Numbers,
- CR_In_Ancient_Symbols,
- CR_In_Phaistos_Disc,
- CR_In_Lycian,
- CR_In_Carian,
- CR_In_Coptic_Epact_Numbers,
- CR_In_Old_Italic,
- CR_In_Gothic,
- CR_In_Old_Permic,
- CR_In_Ugaritic,
- CR_In_Old_Persian,
- CR_In_Deseret,
- CR_In_Shavian,
- CR_In_Osmanya,
- CR_In_Osage,
- CR_In_Elbasan,
- CR_In_Caucasian_Albanian,
- CR_In_Vithkuqi,
- CR_In_Linear_A,
- CR_In_Latin_Extended_F,
- CR_In_Cypriot_Syllabary,
- CR_In_Imperial_Aramaic,
- CR_In_Palmyrene,
- CR_In_Nabataean,
- CR_In_Hatran,
- CR_In_Phoenician,
- CR_In_Lydian,
- CR_In_Meroitic_Hieroglyphs,
- CR_In_Meroitic_Cursive,
- CR_In_Kharoshthi,
- CR_In_Old_South_Arabian,
- CR_In_Old_North_Arabian,
- CR_In_Manichaean,
- CR_In_Avestan,
- CR_In_Inscriptional_Parthian,
- CR_In_Inscriptional_Pahlavi,
- CR_In_Psalter_Pahlavi,
- CR_In_Old_Turkic,
- CR_In_Old_Hungarian,
- CR_In_Hanifi_Rohingya,
- CR_In_Rumi_Numeral_Symbols,
- CR_In_Yezidi,
- CR_In_Arabic_Extended_C,
- CR_In_Old_Sogdian,
- CR_In_Sogdian,
- CR_In_Old_Uyghur,
- CR_In_Chorasmian,
- CR_In_Elymaic,
- CR_In_Brahmi,
- CR_In_Kaithi,
- CR_In_Sora_Sompeng,
- CR_In_Chakma,
- CR_In_Mahajani,
- CR_In_Sharada,
- CR_In_Sinhala_Archaic_Numbers,
- CR_In_Khojki,
- CR_In_Multani,
- CR_In_Khudawadi,
- CR_In_Grantha,
- CR_In_Newa,
- CR_In_Tirhuta,
- CR_In_Siddham,
- CR_In_Modi,
- CR_In_Mongolian_Supplement,
- CR_In_Takri,
- CR_In_Ahom,
- CR_In_Dogra,
- CR_In_Warang_Citi,
- CR_In_Dives_Akuru,
- CR_In_Nandinagari,
- CR_In_Zanabazar_Square,
- CR_In_Soyombo,
- CR_In_Unified_Canadian_Aboriginal_Syllabics_Extended_A,
- CR_In_Pau_Cin_Hau,
- CR_In_Devanagari_Extended_A,
- CR_In_Bhaiksuki,
- CR_In_Marchen,
- CR_In_Masaram_Gondi,
- CR_In_Gunjala_Gondi,
- CR_In_Makasar,
- CR_In_Kawi,
- CR_In_Lisu_Supplement,
- CR_In_Tamil_Supplement,
- CR_In_Cuneiform,
- CR_In_Cuneiform_Numbers_and_Punctuation,
- CR_In_Early_Dynastic_Cuneiform,
- CR_In_Cypro_Minoan,
- CR_In_Egyptian_Hieroglyphs,
- CR_In_Egyptian_Hieroglyph_Format_Controls,
- CR_In_Anatolian_Hieroglyphs,
- CR_In_Bamum_Supplement,
- CR_In_Mro,
- CR_In_Tangsa,
- CR_In_Bassa_Vah,
- CR_In_Pahawh_Hmong,
- CR_In_Medefaidrin,
- CR_In_Miao,
- 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_Extended_B,
- CR_In_Kana_Supplement,
- CR_In_Kana_Extended_A,
- CR_In_Small_Kana_Extension,
- CR_In_Nushu,
- CR_In_Duployan,
- CR_In_Shorthand_Format_Controls,
- CR_In_Znamenny_Musical_Notation,
- CR_In_Byzantine_Musical_Symbols,
- CR_In_Musical_Symbols,
- CR_In_Ancient_Greek_Musical_Notation,
- CR_In_Kaktovik_Numerals,
- CR_In_Mayan_Numerals,
- CR_In_Tai_Xuan_Jing_Symbols,
- CR_In_Counting_Rod_Numerals,
- CR_In_Mathematical_Alphanumeric_Symbols,
- CR_In_Sutton_SignWriting,
- CR_In_Latin_Extended_G,
- CR_In_Glagolitic_Supplement,
- CR_In_Cyrillic_Extended_D,
- CR_In_Nyiakeng_Puachue_Hmong,
- CR_In_Toto,
- CR_In_Wancho,
- CR_In_Nag_Mundari,
- CR_In_Ethiopic_Extended_B,
- CR_In_Mende_Kikakui,
- CR_In_Adlam,
- CR_In_Indic_Siyaq_Numbers,
- CR_In_Ottoman_Siyaq_Numbers,
- CR_In_Arabic_Mathematical_Alphabetic_Symbols,
- CR_In_Mahjong_Tiles,
- CR_In_Domino_Tiles,
- CR_In_Playing_Cards,
- CR_In_Enclosed_Alphanumeric_Supplement,
- CR_In_Enclosed_Ideographic_Supplement,
- CR_In_Miscellaneous_Symbols_and_Pictographs,
- CR_In_Emoticons,
- CR_In_Ornamental_Dingbats,
- CR_In_Transport_and_Map_Symbols,
- CR_In_Alchemical_Symbols,
- CR_In_Geometric_Shapes_Extended,
- CR_In_Supplemental_Arrows_C,
- 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_CJK_Unified_Ideographs_Extension_H,
- CR_In_Tags,
- CR_In_Variation_Selectors_Supplement,
- CR_In_Supplementary_Private_Use_Area_A,
- CR_In_Supplementary_Private_Use_Area_B,
- CR_In_No_Block,
-#endif /* USE_UNICODE_PROPERTIES */
-};
-struct uniname2ctype_struct {
- short name;
- unsigned short ctype;
-};
-#define uniname2ctype_offset(str) offsetof(struct uniname2ctype_pool_t, uniname2ctype_pool_##str)
-
-static const struct uniname2ctype_struct *uniname2ctype_p(register const char *str, register size_t len);
-
-#ifndef USE_UNICODE_PROPERTIES
-#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 866
-#else /* USE_UNICODE_AGE_PROPERTIES */
-#define TOTAL_KEYWORDS 891
-#endif /* USE_UNICODE_AGE_PROPERTIES */
-#define MIN_WORD_LENGTH 1
-#define MAX_WORD_LENGTH 45
-#define MIN_HASH_VALUE 11
-#define MAX_HASH_VALUE 6098
-/* maximum key range = 6088, duplicates = 0 */
-#endif /* USE_UNICODE_PROPERTIES */
-
-#ifdef __GNUC__
-__inline
-#else
-#ifdef __cplusplus
-inline
-#endif
-#endif
-static unsigned int
-uniname2ctype_hash (register const char *str, register size_t len)
-{
-#ifndef USE_UNICODE_PROPERTIES
- static const unsigned char asso_values[] =
-#else /* USE_UNICODE_PROPERTIES */
- static const unsigned short asso_values[] =
-#endif /* USE_UNICODE_PROPERTIES */
- {
-#ifndef USE_UNICODE_PROPERTIES
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 21, 21, 21, 21, 21, 21, 3, 12, 5,
- 4, 21, 21, 10, 21, 1, 21, 21, 11, 21,
- 2, 1, 1, 21, 1, 7, 4, 6, 21, 1,
- 4, 21, 21, 21, 21, 21, 21, 21
-#else /* USE_UNICODE_PROPERTIES */
- 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099,
- 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099,
- 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099,
- 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099,
-#ifndef USE_UNICODE_AGE_PROPERTIES
- 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099,
- 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099,
-#else /* USE_UNICODE_AGE_PROPERTIES */
- 6099, 6099, 6099, 6099, 6099, 6099, 12, 6099, 3, 1,
- 4, 8, 32, 26, 14, 17, 10, 7, 6099, 6099,
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099,
- 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099,
- 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099,
- 6099, 6099, 6099, 6099, 6099, 6099, 6099, 1, 1425, 113,
- 437, 37, 1086, 1071, 1051, 4, 1984, 9, 500, 88,
- 8, 18, 1371, 1287, 54, 203, 310, 619, 1958, 603,
- 275, 1624, 44, 1, 22, 6099, 6099, 6099, 6099, 6099
-#endif /* USE_UNICODE_PROPERTIES */
- };
-#ifndef USE_UNICODE_PROPERTIES
- return len + asso_values[(unsigned char)str[2]] + asso_values[(unsigned char)str[0]];
-#else /* USE_UNICODE_PROPERTIES */
- register unsigned int hval = (unsigned int)len;
-
- switch (hval)
- {
- default:
- hval += asso_values[(unsigned char)str[15]];
- /*FALLTHROUGH*/
- case 15:
- case 14:
- case 13:
- case 12:
- hval += asso_values[(unsigned char)str[11]];
- /*FALLTHROUGH*/
- case 11:
- case 10:
- case 9:
- case 8:
- case 7:
- case 6:
- hval += asso_values[(unsigned char)str[5]];
- /*FALLTHROUGH*/
- case 5:
- hval += asso_values[(unsigned char)str[4]];
- /*FALLTHROUGH*/
- case 4:
- case 3:
- hval += asso_values[(unsigned char)str[2]];
- /*FALLTHROUGH*/
- case 2:
- hval += asso_values[(unsigned char)str[1]];
- /*FALLTHROUGH*/
- case 1:
- hval += asso_values[(unsigned char)str[0]+2];
- break;
- }
- return hval + asso_values[(unsigned char)str[len - 1]];
-#endif /* USE_UNICODE_PROPERTIES */
-}
-
-struct uniname2ctype_pool_t
- {
-#ifndef USE_UNICODE_PROPERTIES
- char uniname2ctype_pool_str6[sizeof("word")];
- char uniname2ctype_pool_str7[sizeof("print")];
- char uniname2ctype_pool_str8[sizeof("punct")];
- char uniname2ctype_pool_str9[sizeof("alpha")];
- char uniname2ctype_pool_str10[sizeof("alnum")];
- char uniname2ctype_pool_str11[sizeof("xdigit")];
- char uniname2ctype_pool_str12[sizeof("upper")];
- char uniname2ctype_pool_str13[sizeof("ascii")];
- char uniname2ctype_pool_str14[sizeof("cntrl")];
- char uniname2ctype_pool_str15[sizeof("space")];
- char uniname2ctype_pool_str16[sizeof("xposixpunct")];
- char uniname2ctype_pool_str17[sizeof("lower")];
- char uniname2ctype_pool_str18[sizeof("graph")];
- char uniname2ctype_pool_str19[sizeof("digit")];
- char uniname2ctype_pool_str20[sizeof("blank")];
-#else /* USE_UNICODE_PROPERTIES */
- char uniname2ctype_pool_str11[sizeof("yi")];
- char uniname2ctype_pool_str17[sizeof("yiii")];
- char uniname2ctype_pool_str22[sizeof("lana")];
- char uniname2ctype_pool_str25[sizeof("lina")];
- char uniname2ctype_pool_str33[sizeof("maka")];
- char uniname2ctype_pool_str35[sizeof("mani")];
- char uniname2ctype_pool_str36[sizeof("mn")];
- char uniname2ctype_pool_str45[sizeof("miao")];
- char uniname2ctype_pool_str46[sizeof("lo")];
- char uniname2ctype_pool_str47[sizeof("ci")];
- char uniname2ctype_pool_str48[sizeof("lao")];
- char uniname2ctype_pool_str49[sizeof("laoo")];
- char uniname2ctype_pool_str52[sizeof("inkannada")];
- char uniname2ctype_pool_str55[sizeof("cn")];
- char uniname2ctype_pool_str64[sizeof("pi")];
- char uniname2ctype_pool_str66[sizeof("innko")];
- char uniname2ctype_pool_str67[sizeof("z")];
- char uniname2ctype_pool_str71[sizeof("gran")];
- char uniname2ctype_pool_str75[sizeof("co")];
- char uniname2ctype_pool_str83[sizeof("lineara")];
- char uniname2ctype_pool_str86[sizeof("mark")];
- char uniname2ctype_pool_str90[sizeof("yezi")];
- char uniname2ctype_pool_str92[sizeof("po")];
- char uniname2ctype_pool_str94[sizeof("me")];
- char uniname2ctype_pool_str100[sizeof("cari")];
- char uniname2ctype_pool_str101[sizeof("inkharoshthi")];
- char uniname2ctype_pool_str102[sizeof("kana")];
- char uniname2ctype_pool_str103[sizeof("loe")];
- char uniname2ctype_pool_str107[sizeof("m")];
- char uniname2ctype_pool_str108[sizeof("grek")];
- char uniname2ctype_pool_str111[sizeof("mro")];
- char uniname2ctype_pool_str112[sizeof("mroo")];
- char uniname2ctype_pool_str115[sizeof("carian")];
- char uniname2ctype_pool_str117[sizeof("geor")];
- char uniname2ctype_pool_str118[sizeof("greek")];
- char uniname2ctype_pool_str122[sizeof("gonm")];
- char uniname2ctype_pool_str129[sizeof("mendekikakui")];
- char uniname2ctype_pool_str130[sizeof("pe")];
- char uniname2ctype_pool_str131[sizeof("mero")];
- char uniname2ctype_pool_str134[sizeof("inosmanya")];
- char uniname2ctype_pool_str139[sizeof("cakm")];
- char uniname2ctype_pool_str145[sizeof("inmanichaean")];
- char uniname2ctype_pool_str146[sizeof("inmro")];
- char uniname2ctype_pool_str148[sizeof("inmiao")];
- char uniname2ctype_pool_str149[sizeof("inchakma")];
- char uniname2ctype_pool_str151[sizeof("c")];
- char uniname2ctype_pool_str152[sizeof("mandaic")];
- char uniname2ctype_pool_str153[sizeof("meeteimayek")];
- char uniname2ctype_pool_str158[sizeof("zzzz")];
- char uniname2ctype_pool_str161[sizeof("inarmenian")];
- char uniname2ctype_pool_str177[sizeof("inmyanmar")];
- char uniname2ctype_pool_str178[sizeof("inmakasar")];
- char uniname2ctype_pool_str183[sizeof("common")];
- char uniname2ctype_pool_str186[sizeof("lm")];
- char uniname2ctype_pool_str190[sizeof("marc")];
- char uniname2ctype_pool_str203[sizeof("inrunic")];
- char uniname2ctype_pool_str204[sizeof("incarian")];
- char uniname2ctype_pool_str210[sizeof("inideographicsymbolsandpunctuation")];
- char uniname2ctype_pool_str212[sizeof("inkhmer")];
- char uniname2ctype_pool_str213[sizeof("qaai")];
- char uniname2ctype_pool_str218[sizeof("inahom")];
- char uniname2ctype_pool_str226[sizeof("merc")];
- char uniname2ctype_pool_str230[sizeof("inchorasmian")];
- char uniname2ctype_pool_str231[sizeof("combiningmark")];
- char uniname2ctype_pool_str236[sizeof("lc")];
- char uniname2ctype_pool_str237[sizeof("perm")];
- char uniname2ctype_pool_str246[sizeof("mc")];
- char uniname2ctype_pool_str250[sizeof("connectorpunctuation")];
- char uniname2ctype_pool_str253[sizeof("cans")];
- char uniname2ctype_pool_str260[sizeof("incuneiformnumbersandpunctuation")];
- char uniname2ctype_pool_str263[sizeof("armi")];
- char uniname2ctype_pool_str265[sizeof("cc")];
- char uniname2ctype_pool_str267[sizeof("armn")];
- char uniname2ctype_pool_str268[sizeof("incherokee")];
- char uniname2ctype_pool_str270[sizeof("prependedconcatenationmark")];
- char uniname2ctype_pool_str274[sizeof("incuneiform")];
- char uniname2ctype_pool_str275[sizeof("inavestan")];
- char uniname2ctype_pool_str281[sizeof("inipaextensions")];
- char uniname2ctype_pool_str282[sizeof("pc")];
- char uniname2ctype_pool_str283[sizeof("armenian")];
- char uniname2ctype_pool_str285[sizeof("insharada")];
- char uniname2ctype_pool_str287[sizeof("vai")];
- char uniname2ctype_pool_str288[sizeof("vaii")];
- char uniname2ctype_pool_str289[sizeof("inmarchen")];
- char uniname2ctype_pool_str293[sizeof("makasar")];
- char uniname2ctype_pool_str297[sizeof("masaramgondi")];
- char uniname2ctype_pool_str301[sizeof("inarrows")];
- char uniname2ctype_pool_str311[sizeof("incyrillic")];
- char uniname2ctype_pool_str313[sizeof("incham")];
- char uniname2ctype_pool_str315[sizeof("qmark")];
- char uniname2ctype_pool_str320[sizeof("ri")];
- char uniname2ctype_pool_str322[sizeof("qaac")];
- char uniname2ctype_pool_str328[sizeof("insamaritan")];
- char uniname2ctype_pool_str331[sizeof("latn")];
- char uniname2ctype_pool_str335[sizeof("inmasaramgondi")];
- char uniname2ctype_pool_str338[sizeof("inthaana")];
- char uniname2ctype_pool_str340[sizeof("latin")];
- char uniname2ctype_pool_str342[sizeof("inthai")];
- char uniname2ctype_pool_str345[sizeof("lineseparator")];
- char uniname2ctype_pool_str346[sizeof("pcm")];
- char uniname2ctype_pool_str348[sizeof("inkatakana")];
- char uniname2ctype_pool_str352[sizeof("inkaithi")];
- char uniname2ctype_pool_str362[sizeof("inscriptionalparthian")];
- char uniname2ctype_pool_str366[sizeof("initialpunctuation")];
- char uniname2ctype_pool_str373[sizeof("mtei")];
- char uniname2ctype_pool_str381[sizeof("inzanabazarsquare")];
- char uniname2ctype_pool_str386[sizeof("inkhmersymbols")];
- char uniname2ctype_pool_str399[sizeof("insyriac")];
- char uniname2ctype_pool_str401[sizeof("intakri")];
- char uniname2ctype_pool_str404[sizeof("arabic")];
- char uniname2ctype_pool_str418[sizeof("katakana")];
- char uniname2ctype_pool_str426[sizeof("prti")];
- char uniname2ctype_pool_str430[sizeof("zs")];
- char uniname2ctype_pool_str442[sizeof("ascii")];
- char uniname2ctype_pool_str445[sizeof("cs")];
- char uniname2ctype_pool_str462[sizeof("ps")];
- char uniname2ctype_pool_str468[sizeof("mand")];
- char uniname2ctype_pool_str470[sizeof("privateuse")];
- char uniname2ctype_pool_str475[sizeof("inruminumeralsymbols")];
- char uniname2ctype_pool_str480[sizeof("inmyanmarextendeda")];
- char uniname2ctype_pool_str481[sizeof("modi")];
- char uniname2ctype_pool_str486[sizeof("incjkcompatibilityforms")];
- char uniname2ctype_pool_str488[sizeof("inkanaextendeda")];
- char uniname2ctype_pool_str491[sizeof("incjkcompatibilityideographs")];
- char uniname2ctype_pool_str500[sizeof("brai")];
- char uniname2ctype_pool_str504[sizeof("mend")];
- char uniname2ctype_pool_str505[sizeof("ideo")];
- char uniname2ctype_pool_str506[sizeof("letter")];
- char uniname2ctype_pool_str509[sizeof("l")];
- char uniname2ctype_pool_str511[sizeof("inmeeteimayek")];
- char uniname2ctype_pool_str520[sizeof("inideographicdescriptioncharacters")];
- char uniname2ctype_pool_str533[sizeof("yezidi")];
- char uniname2ctype_pool_str538[sizeof("knda")];
- char uniname2ctype_pool_str541[sizeof("innandinagari")];
- char uniname2ctype_pool_str543[sizeof("kannada")];
- char uniname2ctype_pool_str556[sizeof("inmodi")];
- char uniname2ctype_pool_str558[sizeof("inlao")];
- char uniname2ctype_pool_str559[sizeof("xidcontinue")];
- char uniname2ctype_pool_str560[sizeof("inoldnortharabian")];
- char uniname2ctype_pool_str565[sizeof("intransportandmapsymbols")];
- char uniname2ctype_pool_str566[sizeof("letternumber")];
- char uniname2ctype_pool_str568[sizeof("gothic")];
- char uniname2ctype_pool_str572[sizeof("inlineara")];
- char uniname2ctype_pool_str577[sizeof("inmendekikakui")];
- char uniname2ctype_pool_str579[sizeof("mongolian")];
- char uniname2ctype_pool_str582[sizeof("inmiscellaneousmathematicalsymbolsa")];
- char uniname2ctype_pool_str583[sizeof("inspecials")];
- char uniname2ctype_pool_str590[sizeof("grlink")];
- char uniname2ctype_pool_str594[sizeof("brahmi")];
- char uniname2ctype_pool_str596[sizeof("inemoticons")];
- char uniname2ctype_pool_str597[sizeof("kali")];
- char uniname2ctype_pool_str600[sizeof("inolditalic")];
- char uniname2ctype_pool_str602[sizeof("xidc")];
- char uniname2ctype_pool_str604[sizeof("inmedefaidrin")];
- char uniname2ctype_pool_str605[sizeof("inchesssymbols")];
- char uniname2ctype_pool_str608[sizeof("incjkcompatibilityideographssupplement")];
- char uniname2ctype_pool_str609[sizeof("kits")];
- char uniname2ctype_pool_str614[sizeof("inadlam")];
- char uniname2ctype_pool_str624[sizeof("psalterpahlavi")];
- char uniname2ctype_pool_str625[sizeof("incommonindicnumberforms")];
- char uniname2ctype_pool_str630[sizeof("lt")];
- char uniname2ctype_pool_str636[sizeof("innewa")];
- char uniname2ctype_pool_str639[sizeof("sk")];
- char uniname2ctype_pool_str642[sizeof("control")];
- char uniname2ctype_pool_str643[sizeof("inkawi")];
- char uniname2ctype_pool_str645[sizeof("inancientsymbols")];
- char uniname2ctype_pool_str647[sizeof("palm")];
- char uniname2ctype_pool_str650[sizeof("inlycian")];
- char uniname2ctype_pool_str657[sizeof("so")];
- char uniname2ctype_pool_str660[sizeof("patternwhitespace")];
- char uniname2ctype_pool_str672[sizeof("inmandaic")];
- char uniname2ctype_pool_str675[sizeof("idc")];
- char uniname2ctype_pool_str678[sizeof("meroiticcursive")];
- char uniname2ctype_pool_str679[sizeof("intoto")];
- char uniname2ctype_pool_str683[sizeof("vs")];
- char uniname2ctype_pool_str692[sizeof("xids")];
- char uniname2ctype_pool_str695[sizeof("inwarangciti")];
- char uniname2ctype_pool_str696[sizeof("sora")];
- char uniname2ctype_pool_str697[sizeof("inopticalcharacterrecognition")];
- char uniname2ctype_pool_str700[sizeof("kawi")];
- char uniname2ctype_pool_str703[sizeof("inoldsogdian")];
- char uniname2ctype_pool_str705[sizeof("inmalayalam")];
- char uniname2ctype_pool_str707[sizeof("bamum")];
- char uniname2ctype_pool_str708[sizeof("inkanasupplement")];
- char uniname2ctype_pool_str713[sizeof("insundanese")];
- char uniname2ctype_pool_str720[sizeof("grext")];
- char uniname2ctype_pool_str737[sizeof("print")];
- char uniname2ctype_pool_str738[sizeof("intaitham")];
- char uniname2ctype_pool_str742[sizeof("lower")];
- char uniname2ctype_pool_str745[sizeof("patternsyntax")];
- char uniname2ctype_pool_str753[sizeof("joinc")];
- char uniname2ctype_pool_str755[sizeof("inoldsoutharabian")];
- char uniname2ctype_pool_str760[sizeof("incjkstrokes")];
- char uniname2ctype_pool_str761[sizeof("batk")];
- char uniname2ctype_pool_str766[sizeof("samr")];
- char uniname2ctype_pool_str767[sizeof("inwancho")];
- char uniname2ctype_pool_str771[sizeof("batak")];
- char uniname2ctype_pool_str776[sizeof("patws")];
- char uniname2ctype_pool_str783[sizeof("samaritan")];
- char uniname2ctype_pool_str787[sizeof("idsbinaryoperator")];
- char uniname2ctype_pool_str791[sizeof("pauc")];
- char uniname2ctype_pool_str794[sizeof("insmallkanaextension")];
- char uniname2ctype_pool_str797[sizeof("sm")];
- char uniname2ctype_pool_str799[sizeof("indominotiles")];
- char uniname2ctype_pool_str802[sizeof("alnum")];
- char uniname2ctype_pool_str803[sizeof("inznamennymusicalnotation")];
- char uniname2ctype_pool_str809[sizeof("insylotinagri")];
- char uniname2ctype_pool_str814[sizeof("inugaritic")];
- char uniname2ctype_pool_str818[sizeof("incontrolpictures")];
- char uniname2ctype_pool_str821[sizeof("inlinearbideograms")];
- char uniname2ctype_pool_str822[sizeof("inmusicalsymbols")];
- char uniname2ctype_pool_str823[sizeof("s")];
- char uniname2ctype_pool_str824[sizeof("ital")];
- char uniname2ctype_pool_str825[sizeof("inmodifiertoneletters")];
- char uniname2ctype_pool_str828[sizeof("inancientgreekmusicalnotation")];
- char uniname2ctype_pool_str838[sizeof("lisu")];
- char uniname2ctype_pool_str842[sizeof("lowercase")];
- char uniname2ctype_pool_str845[sizeof("cwcm")];
- char uniname2ctype_pool_str847[sizeof("sc")];
- char uniname2ctype_pool_str848[sizeof("bass")];
- char uniname2ctype_pool_str855[sizeof("ids")];
- char uniname2ctype_pool_str857[sizeof("inlatinextendeda")];
- char uniname2ctype_pool_str875[sizeof("intaile")];
- char uniname2ctype_pool_str886[sizeof("inmiscellaneoussymbols")];
- char uniname2ctype_pool_str895[sizeof("inmiscellaneoussymbolsandarrows")];
- char uniname2ctype_pool_str898[sizeof("incaucasianalbanian")];
- char uniname2ctype_pool_str900[sizeof("inmiscellaneoussymbolsandpictographs")];
- char uniname2ctype_pool_str906[sizeof("inoldturkic")];
- char uniname2ctype_pool_str907[sizeof("insaurashtra")];
- char uniname2ctype_pool_str920[sizeof("incyrillicextendeda")];
- char uniname2ctype_pool_str924[sizeof("idcontinue")];
- char uniname2ctype_pool_str925[sizeof("intaixuanjingsymbols")];
- char uniname2ctype_pool_str926[sizeof("intamil")];
- char uniname2ctype_pool_str928[sizeof("inmultani")];
- char uniname2ctype_pool_str929[sizeof("inlatinextendede")];
- char uniname2ctype_pool_str930[sizeof("pd")];
- char uniname2ctype_pool_str946[sizeof("bali")];
- char uniname2ctype_pool_str961[sizeof("blank")];
- char uniname2ctype_pool_str963[sizeof("idst")];
- char uniname2ctype_pool_str974[sizeof("inlydian")];
- char uniname2ctype_pool_str986[sizeof("innewtailue")];
- char uniname2ctype_pool_str994[sizeof("bengali")];
- char uniname2ctype_pool_str995[sizeof("runr")];
- char uniname2ctype_pool_str1010[sizeof("ll")];
- char uniname2ctype_pool_str1013[sizeof("indeseret")];
- char uniname2ctype_pool_str1015[sizeof("inancientgreeknumbers")];
- char uniname2ctype_pool_str1021[sizeof("idstart")];
- char uniname2ctype_pool_str1024[sizeof("zl")];
- char uniname2ctype_pool_str1025[sizeof("inmeeteimayekextensions")];
- char uniname2ctype_pool_str1028[sizeof("balinese")];
- char uniname2ctype_pool_str1032[sizeof("incyrillicextendedc")];
- char uniname2ctype_pool_str1035[sizeof("inspacingmodifierletters")];
- char uniname2ctype_pool_str1036[sizeof("inearlydynasticcuneiform")];
- char uniname2ctype_pool_str1049[sizeof("plrd")];
- char uniname2ctype_pool_str1067[sizeof("canadianaboriginal")];
- char uniname2ctype_pool_str1072[sizeof("sind")];
- char uniname2ctype_pool_str1081[sizeof("inlatinextendedc")];
- char uniname2ctype_pool_str1085[sizeof("uideo")];
- char uniname2ctype_pool_str1087[sizeof("incountingrodnumerals")];
- char uniname2ctype_pool_str1089[sizeof("zinh")];
- char uniname2ctype_pool_str1095[sizeof("dia")];
- char uniname2ctype_pool_str1096[sizeof("di")];
- char uniname2ctype_pool_str1097[sizeof("inkhudawadi")];
- char uniname2ctype_pool_str1102[sizeof("inhanifirohingya")];
- char uniname2ctype_pool_str1104[sizeof("diak")];
- char uniname2ctype_pool_str1105[sizeof("gong")];
- char uniname2ctype_pool_str1107[sizeof("ingrantha")];
- char uniname2ctype_pool_str1109[sizeof("bidic")];
- char uniname2ctype_pool_str1114[sizeof("xidstart")];
- char uniname2ctype_pool_str1115[sizeof("xdigit")];
- char uniname2ctype_pool_str1119[sizeof("mong")];
- char uniname2ctype_pool_str1120[sizeof("cased")];
- char uniname2ctype_pool_str1134[sizeof("inhiragana")];
- char uniname2ctype_pool_str1140[sizeof("sinhala")];
- char uniname2ctype_pool_str1142[sizeof("adlm")];
- char uniname2ctype_pool_str1145[sizeof("xsux")];
- char uniname2ctype_pool_str1146[sizeof("glagolitic")];
- char uniname2ctype_pool_str1147[sizeof("sterm")];
- char uniname2ctype_pool_str1149[sizeof("bamu")];
- char uniname2ctype_pool_str1150[sizeof("georgian")];
- char uniname2ctype_pool_str1151[sizeof("inosage")];
- char uniname2ctype_pool_str1152[sizeof("gunjalagondi")];
- char uniname2ctype_pool_str1153[sizeof("phoenician")];
- char uniname2ctype_pool_str1156[sizeof("inolduyghur")];
- char uniname2ctype_pool_str1157[sizeof("multani")];
- char uniname2ctype_pool_str1158[sizeof("kaithi")];
- char uniname2ctype_pool_str1164[sizeof("joincontrol")];
- char uniname2ctype_pool_str1168[sizeof("runic")];
- char uniname2ctype_pool_str1170[sizeof("ingeneralpunctuation")];
- char uniname2ctype_pool_str1171[sizeof("inmahajani")];
- char uniname2ctype_pool_str1174[sizeof("incyrillicsupplement")];
- char uniname2ctype_pool_str1175[sizeof("lowercaseletter")];
- char uniname2ctype_pool_str1176[sizeof("marchen")];
- char uniname2ctype_pool_str1177[sizeof("graphemelink")];
- char uniname2ctype_pool_str1178[sizeof("ingeorgian")];
- char uniname2ctype_pool_str1180[sizeof("khojki")];
- char uniname2ctype_pool_str1181[sizeof("cham")];
- char uniname2ctype_pool_str1182[sizeof("inogham")];
- char uniname2ctype_pool_str1183[sizeof("cher")];
- char uniname2ctype_pool_str1185[sizeof("chakma")];
- char uniname2ctype_pool_str1186[sizeof("inkaktoviknumerals")];
- char uniname2ctype_pool_str1190[sizeof("emoji")];
- char uniname2ctype_pool_str1191[sizeof("insiddham")];
- char uniname2ctype_pool_str1197[sizeof("cherokee")];
- char uniname2ctype_pool_str1198[sizeof("khar")];
- char uniname2ctype_pool_str1203[sizeof("inmongolian")];
- char uniname2ctype_pool_str1204[sizeof("innagmundari")];
- char uniname2ctype_pool_str1207[sizeof("incherokeesupplement")];
- char uniname2ctype_pool_str1209[sizeof("manichaean")];
- char uniname2ctype_pool_str1212[sizeof("inolchiki")];
- char uniname2ctype_pool_str1223[sizeof("inkhitansmallscript")];
- char uniname2ctype_pool_str1227[sizeof("quotationmark")];
- char uniname2ctype_pool_str1229[sizeof("vithkuqi")];
- char uniname2ctype_pool_str1230[sizeof("variationselector")];
- char uniname2ctype_pool_str1231[sizeof("adlam")];
- char uniname2ctype_pool_str1232[sizeof("inethiopic")];
- char uniname2ctype_pool_str1233[sizeof("graphemebase")];
-#ifdef USE_UNICODE_AGE_PROPERTIES
- char uniname2ctype_pool_str1234[sizeof("age=11.0")];
- char uniname2ctype_pool_str1235[sizeof("age=12.1")];
- char uniname2ctype_pool_str1236[sizeof("age=10.0")];
- char uniname2ctype_pool_str1237[sizeof("age=12.0")];
- char uniname2ctype_pool_str1241[sizeof("age=13.0")];
- char uniname2ctype_pool_str1242[sizeof("age=1.1")];
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- char uniname2ctype_pool_str1243[sizeof("casedletter")];
- char uniname2ctype_pool_str1244[sizeof("ingurmukhi")];
-#ifdef USE_UNICODE_AGE_PROPERTIES
- char uniname2ctype_pool_str1245[sizeof("age=2.1")];
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- char uniname2ctype_pool_str1246[sizeof("incjkunifiedideographsextensiona")];
-#ifdef USE_UNICODE_AGE_PROPERTIES
- char uniname2ctype_pool_str1247[sizeof("age=2.0")];
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- char uniname2ctype_pool_str1248[sizeof("lu")];
-#ifdef USE_UNICODE_AGE_PROPERTIES
- char uniname2ctype_pool_str1249[sizeof("age=3.1")];
- char uniname2ctype_pool_str1250[sizeof("age=9.0")];
- char uniname2ctype_pool_str1251[sizeof("age=3.0")];
- char uniname2ctype_pool_str1252[sizeof("age=3.2")];
- char uniname2ctype_pool_str1253[sizeof("age=8.0")];
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- char uniname2ctype_pool_str1254[sizeof("intamilsupplement")];
-#ifdef USE_UNICODE_AGE_PROPERTIES
- char uniname2ctype_pool_str1255[sizeof("age=6.1")];
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- char uniname2ctype_pool_str1256[sizeof("unknown")];
-#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=15.0")];
- char uniname2ctype_pool_str1260[sizeof("age=7.0")];
- char uniname2ctype_pool_str1262[sizeof("age=6.3")];
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- char uniname2ctype_pool_str1263[sizeof("cwt")];
-#ifdef USE_UNICODE_AGE_PROPERTIES
- char uniname2ctype_pool_str1265[sizeof("age=14.0")];
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- char uniname2ctype_pool_str1266[sizeof("unassigned")];
-#ifdef USE_UNICODE_AGE_PROPERTIES
- char uniname2ctype_pool_str1267[sizeof("age=5.1")];
- char uniname2ctype_pool_str1269[sizeof("age=5.0")];
- char uniname2ctype_pool_str1270[sizeof("age=5.2")];
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- char uniname2ctype_pool_str1271[sizeof("diacritic")];
-#ifdef USE_UNICODE_AGE_PROPERTIES
- char uniname2ctype_pool_str1273[sizeof("age=4.1")];
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- char uniname2ctype_pool_str1274[sizeof("ahom")];
-#ifdef USE_UNICODE_AGE_PROPERTIES
- char uniname2ctype_pool_str1275[sizeof("age=4.0")];
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- char uniname2ctype_pool_str1282[sizeof("incjkunifiedideographsextensione")];
- char uniname2ctype_pool_str1285[sizeof("khmr")];
- char uniname2ctype_pool_str1289[sizeof("insinhala")];
- char uniname2ctype_pool_str1292[sizeof("inmiscellaneoustechnical")];
- char uniname2ctype_pool_str1297[sizeof("saur")];
- char uniname2ctype_pool_str1300[sizeof("guru")];
- char uniname2ctype_pool_str1301[sizeof("sundanese")];
- char uniname2ctype_pool_str1306[sizeof("punct")];
- char uniname2ctype_pool_str1314[sizeof("paucinhau")];
- char uniname2ctype_pool_str1317[sizeof("gurmukhi")];
- char uniname2ctype_pool_str1328[sizeof("chorasmian")];
- char uniname2ctype_pool_str1331[sizeof("logicalorderexception")];
- char uniname2ctype_pool_str1340[sizeof("khmer")];
- char uniname2ctype_pool_str1343[sizeof("limbu")];
- char uniname2ctype_pool_str1349[sizeof("chrs")];
- char uniname2ctype_pool_str1352[sizeof("oriya")];
- char uniname2ctype_pool_str1354[sizeof("inscriptionalpahlavi")];
- char uniname2ctype_pool_str1356[sizeof("incyrillicextendedd")];
- char uniname2ctype_pool_str1358[sizeof("incjkunifiedideographsextensionc")];
- char uniname2ctype_pool_str1360[sizeof("cntrl")];
- char uniname2ctype_pool_str1365[sizeof("inlatinextendedadditional")];
- char uniname2ctype_pool_str1367[sizeof("insorasompeng")];
- char uniname2ctype_pool_str1369[sizeof("radical")];
- char uniname2ctype_pool_str1373[sizeof("emojimodifier")];
- char uniname2ctype_pool_str1375[sizeof("kharoshthi")];
- char uniname2ctype_pool_str1380[sizeof("n")];
- char uniname2ctype_pool_str1384[sizeof("math")];
- char uniname2ctype_pool_str1387[sizeof("goth")];
- char uniname2ctype_pool_str1392[sizeof("phnx")];
- char uniname2ctype_pool_str1400[sizeof("anatolianhieroglyphs")];
- char uniname2ctype_pool_str1401[sizeof("inenclosedalphanumerics")];
- char uniname2ctype_pool_str1407[sizeof("nandinagari")];
- char uniname2ctype_pool_str1409[sizeof("no")];
- char uniname2ctype_pool_str1415[sizeof("intangsa")];
- char uniname2ctype_pool_str1419[sizeof("nko")];
- char uniname2ctype_pool_str1420[sizeof("nkoo")];
- char uniname2ctype_pool_str1422[sizeof("ingreekandcoptic")];
- char uniname2ctype_pool_str1426[sizeof("p")];
- char uniname2ctype_pool_str1428[sizeof("grantha")];
- char uniname2ctype_pool_str1429[sizeof("decimalnumber")];
- char uniname2ctype_pool_str1438[sizeof("incjkunifiedideographs")];
- char uniname2ctype_pool_str1442[sizeof("intirhuta")];
- char uniname2ctype_pool_str1448[sizeof("inhatran")];
- char uniname2ctype_pool_str1449[sizeof("linb")];
- char uniname2ctype_pool_str1451[sizeof("mult")];
- char uniname2ctype_pool_str1454[sizeof("saurashtra")];
- char uniname2ctype_pool_str1457[sizeof("kthi")];
- char uniname2ctype_pool_str1460[sizeof("zanb")];
- char uniname2ctype_pool_str1462[sizeof("inbhaiksuki")];
- char uniname2ctype_pool_str1470[sizeof("innabataean")];
- char uniname2ctype_pool_str1471[sizeof("inphoenician")];
- char uniname2ctype_pool_str1474[sizeof("xpeo")];
- char uniname2ctype_pool_str1475[sizeof("inkanbun")];
- char uniname2ctype_pool_str1476[sizeof("inmeroitichieroglyphs")];
- char uniname2ctype_pool_str1480[sizeof("ahex")];
- char uniname2ctype_pool_str1489[sizeof("enclosingmark")];
- char uniname2ctype_pool_str1495[sizeof("sd")];
- char uniname2ctype_pool_str1497[sizeof("inelbasan")];
- char uniname2ctype_pool_str1499[sizeof("inenclosedideographicsupplement")];
- char uniname2ctype_pool_str1501[sizeof("sidd")];
- char uniname2ctype_pool_str1507[sizeof("linearb")];
- char uniname2ctype_pool_str1508[sizeof("cpmn")];
- char uniname2ctype_pool_str1517[sizeof("inenclosedalphanumericsupplement")];
- char uniname2ctype_pool_str1520[sizeof("bidicontrol")];
- char uniname2ctype_pool_str1524[sizeof("inphaistosdisc")];
- char uniname2ctype_pool_str1529[sizeof("limb")];
- char uniname2ctype_pool_str1531[sizeof("inkangxiradicals")];
- char uniname2ctype_pool_str1533[sizeof("lepc")];
- char uniname2ctype_pool_str1536[sizeof("braille")];
- char uniname2ctype_pool_str1537[sizeof("regionalindicator")];
- char uniname2ctype_pool_str1542[sizeof("inlowsurrogates")];
- char uniname2ctype_pool_str1547[sizeof("brah")];
- char uniname2ctype_pool_str1549[sizeof("inoldhungarian")];
- char uniname2ctype_pool_str1557[sizeof("beng")];
- char uniname2ctype_pool_str1563[sizeof("emojimodifierbase")];
- char uniname2ctype_pool_str1565[sizeof("inarabic")];
- char uniname2ctype_pool_str1570[sizeof("osage")];
- char uniname2ctype_pool_str1572[sizeof("inherited")];
- char uniname2ctype_pool_str1577[sizeof("incyprominoan")];
- char uniname2ctype_pool_str1580[sizeof("glag")];
- char uniname2ctype_pool_str1582[sizeof("medf")];
- char uniname2ctype_pool_str1583[sizeof("osma")];
- char uniname2ctype_pool_str1587[sizeof("indogra")];
- char uniname2ctype_pool_str1597[sizeof("arab")];
- char uniname2ctype_pool_str1598[sizeof("medefaidrin")];
- char uniname2ctype_pool_str1607[sizeof("inshorthandformatcontrols")];
- char uniname2ctype_pool_str1613[sizeof("phli")];
- char uniname2ctype_pool_str1617[sizeof("inimperialaramaic")];
- char uniname2ctype_pool_str1618[sizeof("emod")];
- char uniname2ctype_pool_str1622[sizeof("ingreekextended")];
- char uniname2ctype_pool_str1623[sizeof("inanatolianhieroglyphs")];
- char uniname2ctype_pool_str1629[sizeof("punctuation")];
- char uniname2ctype_pool_str1635[sizeof("graphemeextend")];
- char uniname2ctype_pool_str1643[sizeof("cwl")];
- char uniname2ctype_pool_str1644[sizeof("vith")];
- char uniname2ctype_pool_str1654[sizeof("ingeometricshapes")];
- char uniname2ctype_pool_str1655[sizeof("emojicomponent")];
- char uniname2ctype_pool_str1657[sizeof("dsrt")];
- char uniname2ctype_pool_str1662[sizeof("coptic")];
- char uniname2ctype_pool_str1664[sizeof("inkayahli")];
- char uniname2ctype_pool_str1671[sizeof("inoriya")];
- char uniname2ctype_pool_str1675[sizeof("inarabicpresentationformsa")];
- char uniname2ctype_pool_str1677[sizeof("inbasiclatin")];
- char uniname2ctype_pool_str1682[sizeof("incjkunifiedideographsextensiond")];
- char uniname2ctype_pool_str1684[sizeof("wara")];
- char uniname2ctype_pool_str1686[sizeof("sinh")];
- char uniname2ctype_pool_str1687[sizeof("sund")];
- char uniname2ctype_pool_str1691[sizeof("shavian")];
- char uniname2ctype_pool_str1699[sizeof("insundanesesupplement")];
- char uniname2ctype_pool_str1701[sizeof("inyezidi")];
- char uniname2ctype_pool_str1704[sizeof("bhks")];
- char uniname2ctype_pool_str1714[sizeof("bhaiksuki")];
- char uniname2ctype_pool_str1722[sizeof("inhanunoo")];
- char uniname2ctype_pool_str1724[sizeof("intangut")];
- char uniname2ctype_pool_str1728[sizeof("sogdian")];
- char uniname2ctype_pool_str1729[sizeof("inlatinextendedd")];
- char uniname2ctype_pool_str1730[sizeof("sogo")];
- char uniname2ctype_pool_str1731[sizeof("insinhalaarchaicnumbers")];
- char uniname2ctype_pool_str1732[sizeof("ideographic")];
- char uniname2ctype_pool_str1733[sizeof("ugar")];
- char uniname2ctype_pool_str1734[sizeof("deseret")];
- char uniname2ctype_pool_str1735[sizeof("odi")];
- char uniname2ctype_pool_str1740[sizeof("copt")];
- char uniname2ctype_pool_str1742[sizeof("imperialaramaic")];
- char uniname2ctype_pool_str1745[sizeof("insogdian")];
- char uniname2ctype_pool_str1746[sizeof("indingbats")];
- char uniname2ctype_pool_str1750[sizeof("format")];
- char uniname2ctype_pool_str1752[sizeof("ininscriptionalpahlavi")];
- char uniname2ctype_pool_str1753[sizeof("lyci")];
- char uniname2ctype_pool_str1757[sizeof("ininscriptionalparthian")];
- char uniname2ctype_pool_str1766[sizeof("grbase")];
- char uniname2ctype_pool_str1768[sizeof("lycian")];
- char uniname2ctype_pool_str1769[sizeof("inbatak")];
- char uniname2ctype_pool_str1776[sizeof("cprt")];
- char uniname2ctype_pool_str1781[sizeof("inunifiedcanadianaboriginalsyllabicsextendeda")];
- char uniname2ctype_pool_str1788[sizeof("mymr")];
- char uniname2ctype_pool_str1793[sizeof("myanmar")];
- char uniname2ctype_pool_str1806[sizeof("intibetan")];
- char uniname2ctype_pool_str1810[sizeof("intags")];
- char uniname2ctype_pool_str1811[sizeof("asciihexdigit")];
- char uniname2ctype_pool_str1813[sizeof("sentenceterminal")];
- char uniname2ctype_pool_str1821[sizeof("nand")];
- char uniname2ctype_pool_str1828[sizeof("inblockelements")];
- char uniname2ctype_pool_str1838[sizeof("inornamentaldingbats")];
- char uniname2ctype_pool_str1841[sizeof("inethiopicextendeda")];
- char uniname2ctype_pool_str1842[sizeof("innumberforms")];
- char uniname2ctype_pool_str1843[sizeof("cwcf")];
- char uniname2ctype_pool_str1845[sizeof("oidc")];
- char uniname2ctype_pool_str1848[sizeof("bopo")];
- char uniname2ctype_pool_str1851[sizeof("cuneiform")];
- char uniname2ctype_pool_str1866[sizeof("caseignorable")];
- char uniname2ctype_pool_str1871[sizeof("inoldpersian")];
- char uniname2ctype_pool_str1881[sizeof("cwu")];
- char uniname2ctype_pool_str1888[sizeof("inelymaic")];
- char uniname2ctype_pool_str1889[sizeof("insoyombo")];
- char uniname2ctype_pool_str1896[sizeof("ingeometricshapesextended")];
- char uniname2ctype_pool_str1902[sizeof("incjkcompatibility")];
- char uniname2ctype_pool_str1904[sizeof("inmyanmarextendedb")];
- char uniname2ctype_pool_str1905[sizeof("innushu")];
- char uniname2ctype_pool_str1912[sizeof("inkanaextendedb")];
- char uniname2ctype_pool_str1913[sizeof("olck")];
- char uniname2ctype_pool_str1916[sizeof("inbyzantinemusicalsymbols")];
- char uniname2ctype_pool_str1924[sizeof("olchiki")];
- char uniname2ctype_pool_str1929[sizeof("inkatakanaphoneticextensions")];
- char uniname2ctype_pool_str1932[sizeof("incoptic")];
- char uniname2ctype_pool_str1935[sizeof("oids")];
- char uniname2ctype_pool_str1936[sizeof("inarabicextendeda")];
- char uniname2ctype_pool_str1941[sizeof("modifierletter")];
- char uniname2ctype_pool_str1950[sizeof("incjksymbolsandpunctuation")];
- char uniname2ctype_pool_str1956[sizeof("olower")];
- char uniname2ctype_pool_str1958[sizeof("bopomofo")];
- char uniname2ctype_pool_str1964[sizeof("inlisu")];
- char uniname2ctype_pool_str1967[sizeof("inoldpermic")];
- char uniname2ctype_pool_str1968[sizeof("innoblock")];
- char uniname2ctype_pool_str1969[sizeof("ext")];
- char uniname2ctype_pool_str1974[sizeof("inunifiedcanadianaboriginalsyllabics")];
- char uniname2ctype_pool_str1981[sizeof("takri")];
- char uniname2ctype_pool_str1985[sizeof("inbraillepatterns")];
- char uniname2ctype_pool_str1988[sizeof("invai")];
- char uniname2ctype_pool_str1991[sizeof("alpha")];
- char uniname2ctype_pool_str1993[sizeof("inbalinese")];
- char uniname2ctype_pool_str1994[sizeof("sorasompeng")];
- char uniname2ctype_pool_str1996[sizeof("closepunctuation")];
- char uniname2ctype_pool_str2001[sizeof("hani")];
- char uniname2ctype_pool_str2002[sizeof("inmayannumerals")];
- char uniname2ctype_pool_str2004[sizeof("han")];
- char uniname2ctype_pool_str2006[sizeof("inmiscellaneousmathematicalsymbolsb")];
- char uniname2ctype_pool_str2010[sizeof("inlepcha")];
- char uniname2ctype_pool_str2011[sizeof("patsyn")];
- char uniname2ctype_pool_str2012[sizeof("inlisusupplement")];
- char uniname2ctype_pool_str2014[sizeof("insyriacsupplement")];
- char uniname2ctype_pool_str2015[sizeof("hano")];
- char uniname2ctype_pool_str2016[sizeof("newa")];
- char uniname2ctype_pool_str2023[sizeof("spacingmark")];
- char uniname2ctype_pool_str2024[sizeof("inpalmyrene")];
- char uniname2ctype_pool_str2026[sizeof("takr")];
- char uniname2ctype_pool_str2033[sizeof("xposixpunct")];
- char uniname2ctype_pool_str2040[sizeof("inkhojki")];
- char uniname2ctype_pool_str2042[sizeof("taile")];
- char uniname2ctype_pool_str2043[sizeof("assigned")];
- char uniname2ctype_pool_str2044[sizeof("hanunoo")];
- char uniname2ctype_pool_str2047[sizeof("hira")];
- char uniname2ctype_pool_str2048[sizeof("inarabicextendedc")];
- char uniname2ctype_pool_str2062[sizeof("newtailue")];
- char uniname2ctype_pool_str2070[sizeof("space")];
- char uniname2ctype_pool_str2073[sizeof("intelugu")];
- char uniname2ctype_pool_str2077[sizeof("lydi")];
- char uniname2ctype_pool_str2078[sizeof("idsb")];
- char uniname2ctype_pool_str2090[sizeof("extpict")];
- char uniname2ctype_pool_str2092[sizeof("lydian")];
- char uniname2ctype_pool_str2095[sizeof("inethiopicsupplement")];
- char uniname2ctype_pool_str2103[sizeof("sarb")];
- char uniname2ctype_pool_str2110[sizeof("ugaritic")];
- char uniname2ctype_pool_str2114[sizeof("inyiradicals")];
- char uniname2ctype_pool_str2115[sizeof("inphoneticextensions")];
- char uniname2ctype_pool_str2117[sizeof("sharada")];
- char uniname2ctype_pool_str2128[sizeof("zanabazarsquare")];
- char uniname2ctype_pool_str2135[sizeof("bugi")];
- char uniname2ctype_pool_str2137[sizeof("word")];
- char uniname2ctype_pool_str2141[sizeof("term")];
- char uniname2ctype_pool_str2145[sizeof("separator")];
- char uniname2ctype_pool_str2146[sizeof("ingeorgiansupplement")];
- char uniname2ctype_pool_str2149[sizeof("sogd")];
- char uniname2ctype_pool_str2163[sizeof("extender")];
- char uniname2ctype_pool_str2165[sizeof("shrd")];
- char uniname2ctype_pool_str2166[sizeof("graph")];
- char uniname2ctype_pool_str2174[sizeof("tnsa")];
- char uniname2ctype_pool_str2178[sizeof("tangsa")];
- char uniname2ctype_pool_str2181[sizeof("phag")];
- char uniname2ctype_pool_str2182[sizeof("dogra")];
- char uniname2ctype_pool_str2195[sizeof("inhanguljamo")];
- char uniname2ctype_pool_str2196[sizeof("inshavian")];
- char uniname2ctype_pool_str2207[sizeof("siddham")];
- char uniname2ctype_pool_str2211[sizeof("cf")];
- char uniname2ctype_pool_str2216[sizeof("inunifiedcanadianaboriginalsyllabicsextended")];
- char uniname2ctype_pool_str2217[sizeof("buginese")];
- char uniname2ctype_pool_str2218[sizeof("inmongoliansupplement")];
- char uniname2ctype_pool_str2219[sizeof("cyrl")];
- char uniname2ctype_pool_str2224[sizeof("inhanguljamoextendeda")];
- char uniname2ctype_pool_str2228[sizeof("pf")];
- char uniname2ctype_pool_str2229[sizeof("number")];
- char uniname2ctype_pool_str2232[sizeof("inphoneticextensionssupplement")];
- char uniname2ctype_pool_str2233[sizeof("dogr")];
- char uniname2ctype_pool_str2234[sizeof("mlym")];
- char uniname2ctype_pool_str2235[sizeof("incopticepactnumbers")];
- char uniname2ctype_pool_str2241[sizeof("malayalam")];
- char uniname2ctype_pool_str2244[sizeof("inbamum")];
- char uniname2ctype_pool_str2247[sizeof("nd")];
- char uniname2ctype_pool_str2248[sizeof("insuttonsignwriting")];
- char uniname2ctype_pool_str2276[sizeof("inethiopicextended")];
- char uniname2ctype_pool_str2278[sizeof("shaw")];
- char uniname2ctype_pool_str2279[sizeof("palmyrene")];
- char uniname2ctype_pool_str2283[sizeof("soyo")];
- char uniname2ctype_pool_str2296[sizeof("incjkunifiedideographsextensionh")];
- char uniname2ctype_pool_str2305[sizeof("sgnw")];
- char uniname2ctype_pool_str2308[sizeof("toto")];
- char uniname2ctype_pool_str2312[sizeof("caucasianalbanian")];
- char uniname2ctype_pool_str2315[sizeof("inmathematicalalphanumericsymbols")];
- char uniname2ctype_pool_str2316[sizeof("incjkunifiedideographsextensiong")];
- char uniname2ctype_pool_str2318[sizeof("hatran")];
- char uniname2ctype_pool_str2321[sizeof("taiviet")];
- char uniname2ctype_pool_str2323[sizeof("meroitichieroglyphs")];
- char uniname2ctype_pool_str2327[sizeof("ingeorgianextended")];
- char uniname2ctype_pool_str2331[sizeof("incjkunifiedideographsextensionf")];
- char uniname2ctype_pool_str2333[sizeof("oldpersian")];
- char uniname2ctype_pool_str2343[sizeof("induployan")];
- char uniname2ctype_pool_str2344[sizeof("incyrillicextendedb")];
- char uniname2ctype_pool_str2345[sizeof("dash")];
- char uniname2ctype_pool_str2353[sizeof("hatr")];
- char uniname2ctype_pool_str2361[sizeof("innyiakengpuachuehmong")];
- char uniname2ctype_pool_str2364[sizeof("incombiningdiacriticalmarks")];
- char uniname2ctype_pool_str2373[sizeof("nl")];
- char uniname2ctype_pool_str2374[sizeof("incombiningdiacriticalmarksforsymbols")];
- char uniname2ctype_pool_str2375[sizeof("khudawadi")];
- char uniname2ctype_pool_str2397[sizeof("incjkradicalssupplement")];
- char uniname2ctype_pool_str2398[sizeof("inglagolitic")];
- char uniname2ctype_pool_str2405[sizeof("orkh")];
- char uniname2ctype_pool_str2414[sizeof("syrc")];
- char uniname2ctype_pool_str2427[sizeof("surrogate")];
- char uniname2ctype_pool_str2433[sizeof("indevanagari")];
- char uniname2ctype_pool_str2434[sizeof("avestan")];
- char uniname2ctype_pool_str2437[sizeof("oldpermic")];
- char uniname2ctype_pool_str2440[sizeof("ethi")];
- char uniname2ctype_pool_str2451[sizeof("ogam")];
- char uniname2ctype_pool_str2454[sizeof("rohg")];
- char uniname2ctype_pool_str2460[sizeof("idstrinaryoperator")];
- char uniname2ctype_pool_str2464[sizeof("java")];
- char uniname2ctype_pool_str2470[sizeof("inphagspa")];
- char uniname2ctype_pool_str2475[sizeof("lepcha")];
- char uniname2ctype_pool_str2476[sizeof("indevanagariextendeda")];
- char uniname2ctype_pool_str2478[sizeof("intifinagh")];
- char uniname2ctype_pool_str2479[sizeof("intagalog")];
- char uniname2ctype_pool_str2481[sizeof("incombiningdiacriticalmarkssupplement")];
- char uniname2ctype_pool_str2500[sizeof("tale")];
- char uniname2ctype_pool_str2506[sizeof("inbrahmi")];
- char uniname2ctype_pool_str2511[sizeof("terminalpunctuation")];
- char uniname2ctype_pool_str2513[sizeof("insymbolsandpictographsextendeda")];
- char uniname2ctype_pool_str2530[sizeof("syriac")];
- char uniname2ctype_pool_str2534[sizeof("inbengali")];
- char uniname2ctype_pool_str2535[sizeof("nagm")];
- char uniname2ctype_pool_str2545[sizeof("extendedpictographic")];
- char uniname2ctype_pool_str2548[sizeof("buhd")];
- char uniname2ctype_pool_str2549[sizeof("javanese")];
- char uniname2ctype_pool_str2551[sizeof("taml")];
- char uniname2ctype_pool_str2564[sizeof("inbuginese")];
- char uniname2ctype_pool_str2567[sizeof("inlatin1supplement")];
- char uniname2ctype_pool_str2570[sizeof("ingothic")];
- char uniname2ctype_pool_str2572[sizeof("invariationselectors")];
- char uniname2ctype_pool_str2574[sizeof("hex")];
- char uniname2ctype_pool_str2575[sizeof("inverticalforms")];
- char uniname2ctype_pool_str2576[sizeof("ebase")];
- char uniname2ctype_pool_str2582[sizeof("incurrencysymbols")];
- char uniname2ctype_pool_str2588[sizeof("avst")];
- char uniname2ctype_pool_str2602[sizeof("osge")];
- char uniname2ctype_pool_str2606[sizeof("incombiningdiacriticalmarksextended")];
- char uniname2ctype_pool_str2608[sizeof("intaiviet")];
- char uniname2ctype_pool_str2609[sizeof("spaceseparator")];
- char uniname2ctype_pool_str2625[sizeof("softdotted")];
- char uniname2ctype_pool_str2648[sizeof("nchar")];
- char uniname2ctype_pool_str2652[sizeof("invedicextensions")];
- char uniname2ctype_pool_str2656[sizeof("inlimbu")];
- char uniname2ctype_pool_str2657[sizeof("olditalic")];
- char uniname2ctype_pool_str2665[sizeof("gujr")];
- char uniname2ctype_pool_str2666[sizeof("mathsymbol")];
- char uniname2ctype_pool_str2670[sizeof("incjkunifiedideographsextensionb")];
- char uniname2ctype_pool_str2674[sizeof("gujarati")];
- char uniname2ctype_pool_str2688[sizeof("phagspa")];
- char uniname2ctype_pool_str2689[sizeof("invariationselectorssupplement")];
- char uniname2ctype_pool_str2694[sizeof("currencysymbol")];
- char uniname2ctype_pool_str2705[sizeof("inlinearbsyllabary")];
- char uniname2ctype_pool_str2726[sizeof("wancho")];
- char uniname2ctype_pool_str2750[sizeof("inpaucinhau")];
- char uniname2ctype_pool_str2761[sizeof("other")];
- char uniname2ctype_pool_str2762[sizeof("otheridcontinue")];
- char uniname2ctype_pool_str2765[sizeof("sylo")];
- char uniname2ctype_pool_str2766[sizeof("zp")];
- char uniname2ctype_pool_str2769[sizeof("inaegeannumbers")];
- char uniname2ctype_pool_str2772[sizeof("warangciti")];
- char uniname2ctype_pool_str2775[sizeof("othernumber")];
- char uniname2ctype_pool_str2786[sizeof("digit")];
- char uniname2ctype_pool_str2793[sizeof("nonspacingmark")];
- char uniname2ctype_pool_str2801[sizeof("titlecaseletter")];
- char uniname2ctype_pool_str2808[sizeof("inmeroiticcursive")];
- char uniname2ctype_pool_str2810[sizeof("wcho")];
- char uniname2ctype_pool_str2816[sizeof("graphemeclusterbreak=spacingmark")];
- char uniname2ctype_pool_str2821[sizeof("inletterlikesymbols")];
- char uniname2ctype_pool_str2830[sizeof("inottomansiyaqnumbers")];
- char uniname2ctype_pool_str2834[sizeof("intagbanwa")];
- char uniname2ctype_pool_str2836[sizeof("cyrillic")];
- char uniname2ctype_pool_str2847[sizeof("oalpha")];
- char uniname2ctype_pool_str2852[sizeof("graphemeclusterbreak=cr")];
- char uniname2ctype_pool_str2855[sizeof("narb")];
- char uniname2ctype_pool_str2856[sizeof("changeswhencasemapped")];
- char uniname2ctype_pool_str2859[sizeof("inbopomofo")];
- char uniname2ctype_pool_str2867[sizeof("graphemeclusterbreak=regionalindicator")];
- char uniname2ctype_pool_str2868[sizeof("otheralphabetic")];
- char uniname2ctype_pool_str2871[sizeof("noncharactercodepoint")];
- char uniname2ctype_pool_str2879[sizeof("oldhungarian")];
- char uniname2ctype_pool_str2886[sizeof("insymbolsforlegacycomputing")];
- char uniname2ctype_pool_str2902[sizeof("insmallformvariants")];
- char uniname2ctype_pool_str2904[sizeof("inhangulsyllables")];
- char uniname2ctype_pool_str2905[sizeof("emojipresentation")];
- char uniname2ctype_pool_str2907[sizeof("epres")];
- char uniname2ctype_pool_str2909[sizeof("inbassavah")];
- char uniname2ctype_pool_str2911[sizeof("indevanagariextended")];
- char uniname2ctype_pool_str2941[sizeof("inbuhid")];
- char uniname2ctype_pool_str2953[sizeof("tirhuta")];
- char uniname2ctype_pool_str2964[sizeof("inpsalterpahlavi")];
- char uniname2ctype_pool_str2966[sizeof("whitespace")];
- char uniname2ctype_pool_str2967[sizeof("finalpunctuation")];
- char uniname2ctype_pool_str2970[sizeof("orya")];
- char uniname2ctype_pool_str2980[sizeof("phlp")];
- char uniname2ctype_pool_str2984[sizeof("inbamumsupplement")];
- char uniname2ctype_pool_str2986[sizeof("buhid")];
- char uniname2ctype_pool_str2987[sizeof("paragraphseparator")];
- char uniname2ctype_pool_str2988[sizeof("inalphabeticpresentationforms")];
- char uniname2ctype_pool_str2997[sizeof("inlatinextendedg")];
- char uniname2ctype_pool_str3001[sizeof("elba")];
- char uniname2ctype_pool_str3002[sizeof("changeswhentitlecased")];
- char uniname2ctype_pool_str3005[sizeof("incombininghalfmarks")];
- char uniname2ctype_pool_str3006[sizeof("intangutcomponents")];
- char uniname2ctype_pool_str3015[sizeof("thaa")];
- char uniname2ctype_pool_str3018[sizeof("thai")];
- char uniname2ctype_pool_str3019[sizeof("oldturkic")];
- char uniname2ctype_pool_str3026[sizeof("thaana")];
- char uniname2ctype_pool_str3027[sizeof("inlatinextendedf")];
- char uniname2ctype_pool_str3035[sizeof("ougr")];
- char uniname2ctype_pool_str3042[sizeof("tang")];
- char uniname2ctype_pool_str3045[sizeof("inarabicmathematicalalphabeticsymbols")];
- char uniname2ctype_pool_str3048[sizeof("tagbanwa")];
- char uniname2ctype_pool_str3052[sizeof("tamil")];
- char uniname2ctype_pool_str3053[sizeof("khitansmallscript")];
- char uniname2ctype_pool_str3058[sizeof("mahj")];
- char uniname2ctype_pool_str3067[sizeof("mahajani")];
- char uniname2ctype_pool_str3068[sizeof("hang")];
- char uniname2ctype_pool_str3071[sizeof("tirh")];
- char uniname2ctype_pool_str3072[sizeof("sylotinagri")];
- char uniname2ctype_pool_str3082[sizeof("talu")];
- char uniname2ctype_pool_str3084[sizeof("nagmundari")];
- char uniname2ctype_pool_str3086[sizeof("deva")];
- char uniname2ctype_pool_str3087[sizeof("ingujarati")];
- char uniname2ctype_pool_str3091[sizeof("deprecated")];
- char uniname2ctype_pool_str3099[sizeof("inarabicpresentationformsb")];
- char uniname2ctype_pool_str3104[sizeof("devanagari")];
- char uniname2ctype_pool_str3106[sizeof("ingunjalagondi")];
- char uniname2ctype_pool_str3107[sizeof("graphemeclusterbreak=t")];
- char uniname2ctype_pool_str3109[sizeof("graphemeclusterbreak=lvt")];
- char uniname2ctype_pool_str3110[sizeof("taitham")];
- char uniname2ctype_pool_str3111[sizeof("nbat")];
- char uniname2ctype_pool_str3118[sizeof("telu")];
- char uniname2ctype_pool_str3123[sizeof("hiragana")];
- char uniname2ctype_pool_str3125[sizeof("nabataean")];
- char uniname2ctype_pool_str3135[sizeof("inrejang")];
- char uniname2ctype_pool_str3142[sizeof("intangutsupplement")];
- char uniname2ctype_pool_str3145[sizeof("khoj")];
- char uniname2ctype_pool_str3155[sizeof("hmng")];
- char uniname2ctype_pool_str3157[sizeof("cyprominoan")];
- char uniname2ctype_pool_str3158[sizeof("inhebrew")];
- char uniname2ctype_pool_str3176[sizeof("inmathematicaloperators")];
- char uniname2ctype_pool_str3180[sizeof("inarabicsupplement")];
- char uniname2ctype_pool_str3193[sizeof("inenclosedcjklettersandmonths")];
- char uniname2ctype_pool_str3209[sizeof("changeswhenlowercased")];
- char uniname2ctype_pool_str3212[sizeof("tangut")];
- char uniname2ctype_pool_str3215[sizeof("elbasan")];
- char uniname2ctype_pool_str3218[sizeof("osmanya")];
- char uniname2ctype_pool_str3237[sizeof("insuperscriptsandsubscripts")];
- char uniname2ctype_pool_str3239[sizeof("graphemeclusterbreak=extend")];
- char uniname2ctype_pool_str3240[sizeof("graphemeclusterbreak=prepend")];
- char uniname2ctype_pool_str3248[sizeof("nshu")];
- char uniname2ctype_pool_str3254[sizeof("otherlowercase")];
- char uniname2ctype_pool_str3265[sizeof("inethiopicextendedb")];
- char uniname2ctype_pool_str3267[sizeof("otherletter")];
- char uniname2ctype_pool_str3275[sizeof("kayahli")];
- char uniname2ctype_pool_str3284[sizeof("inplayingcards")];
- char uniname2ctype_pool_str3287[sizeof("elym")];
- char uniname2ctype_pool_str3297[sizeof("graphemeclusterbreak=l")];
- char uniname2ctype_pool_str3303[sizeof("graphemeclusterbreak=control")];
- char uniname2ctype_pool_str3313[sizeof("ogrext")];
- char uniname2ctype_pool_str3320[sizeof("elymaic")];
- char uniname2ctype_pool_str3328[sizeof("changeswhenuppercased")];
- char uniname2ctype_pool_str3329[sizeof("inalchemicalsymbols")];
- char uniname2ctype_pool_str3331[sizeof("oldsogdian")];
- char uniname2ctype_pool_str3338[sizeof("otheridstart")];
- char uniname2ctype_pool_str3348[sizeof("insupplementalarrowsa")];
- char uniname2ctype_pool_str3350[sizeof("invithkuqi")];
- char uniname2ctype_pool_str3355[sizeof("symbol")];
- char uniname2ctype_pool_str3360[sizeof("inarabicextendedb")];
- char uniname2ctype_pool_str3371[sizeof("cypriot")];
- char uniname2ctype_pool_str3372[sizeof("any")];
- char uniname2ctype_pool_str3373[sizeof("otheruppercase")];
- char uniname2ctype_pool_str3377[sizeof("rjng")];
- char uniname2ctype_pool_str3391[sizeof("wspace")];
- char uniname2ctype_pool_str3396[sizeof("inindicsiyaqnumbers")];
- char uniname2ctype_pool_str3405[sizeof("inprivateusearea")];
- char uniname2ctype_pool_str3416[sizeof("othersymbol")];
- char uniname2ctype_pool_str3428[sizeof("oupper")];
- char uniname2ctype_pool_str3433[sizeof("signwriting")];
- char uniname2ctype_pool_str3436[sizeof("nushu")];
- char uniname2ctype_pool_str3455[sizeof("hmnp")];
- char uniname2ctype_pool_str3458[sizeof("upper")];
- char uniname2ctype_pool_str3460[sizeof("insupplementalarrowsc")];
- char uniname2ctype_pool_str3483[sizeof("omath")];
- char uniname2ctype_pool_str3502[sizeof("modifiersymbol")];
- char uniname2ctype_pool_str3504[sizeof("hebr")];
- char uniname2ctype_pool_str3505[sizeof("inhalfwidthandfullwidthforms")];
- char uniname2ctype_pool_str3511[sizeof("insupplementalmathematicaloperators")];
- char uniname2ctype_pool_str3532[sizeof("inpahawhhmong")];
- char uniname2ctype_pool_str3533[sizeof("alphabetic")];
- char uniname2ctype_pool_str3558[sizeof("uppercase")];
- char uniname2ctype_pool_str3580[sizeof("dupl")];
- char uniname2ctype_pool_str3590[sizeof("ogham")];
- char uniname2ctype_pool_str3613[sizeof("dashpunctuation")];
- char uniname2ctype_pool_str3618[sizeof("hangul")];
- char uniname2ctype_pool_str3648[sizeof("inhanguljamoextendedb")];
- char uniname2ctype_pool_str3659[sizeof("bassavah")];
- char uniname2ctype_pool_str3664[sizeof("aghb")];
- char uniname2ctype_pool_str3686[sizeof("hung")];
- char uniname2ctype_pool_str3689[sizeof("hexdigit")];
- char uniname2ctype_pool_str3698[sizeof("incypriotsyllabary")];
- char uniname2ctype_pool_str3699[sizeof("indivesakuru")];
- char uniname2ctype_pool_str3701[sizeof("tibt")];
- char uniname2ctype_pool_str3705[sizeof("inlatinextendedb")];
- char uniname2ctype_pool_str3710[sizeof("hluw")];
- char uniname2ctype_pool_str3713[sizeof("tibetan")];
- char uniname2ctype_pool_str3721[sizeof("inyisyllables")];
- char uniname2ctype_pool_str3744[sizeof("oldnortharabian")];
- char uniname2ctype_pool_str3754[sizeof("defaultignorablecodepoint")];
- char uniname2ctype_pool_str3766[sizeof("inhighprivateusesurrogates")];
- char uniname2ctype_pool_str3799[sizeof("soyombo")];
- char uniname2ctype_pool_str3807[sizeof("otherdefaultignorablecodepoint")];
- char uniname2ctype_pool_str3842[sizeof("pahawhhmong")];
- char uniname2ctype_pool_str3845[sizeof("unifiedideograph")];
- char uniname2ctype_pool_str3850[sizeof("othermath")];
- char uniname2ctype_pool_str3854[sizeof("changeswhencasefolded")];
- char uniname2ctype_pool_str3857[sizeof("inmahjongtiles")];
- char uniname2ctype_pool_str3868[sizeof("dep")];
- char uniname2ctype_pool_str3881[sizeof("divesakuru")];
- char uniname2ctype_pool_str3884[sizeof("graphemeclusterbreak=lf")];
- char uniname2ctype_pool_str3891[sizeof("uppercaseletter")];
- char uniname2ctype_pool_str3924[sizeof("insupplementalpunctuation")];
- char uniname2ctype_pool_str3942[sizeof("ethiopic")];
- char uniname2ctype_pool_str3944[sizeof("inyijinghexagramsymbols")];
- char uniname2ctype_pool_str3949[sizeof("ecomp")];
- char uniname2ctype_pool_str3976[sizeof("inglagoliticsupplement")];
- char uniname2ctype_pool_str3998[sizeof("inbopomofoextended")];
- char uniname2ctype_pool_str4007[sizeof("injavanese")];
- char uniname2ctype_pool_str4106[sizeof("otherpunctuation")];
- char uniname2ctype_pool_str4116[sizeof("tifinagh")];
- char uniname2ctype_pool_str4127[sizeof("tfng")];
- char uniname2ctype_pool_str4169[sizeof("hanifirohingya")];
- char uniname2ctype_pool_str4231[sizeof("tavt")];
- char uniname2ctype_pool_str4308[sizeof("inboxdrawing")];
- char uniname2ctype_pool_str4309[sizeof("oldsoutharabian")];
- char uniname2ctype_pool_str4348[sizeof("inegyptianhieroglyphs")];
- char uniname2ctype_pool_str4361[sizeof("inegyptianhieroglyphformatcontrols")];
- char uniname2ctype_pool_str4459[sizeof("tagb")];
- char uniname2ctype_pool_str4487[sizeof("rejang")];
- char uniname2ctype_pool_str4604[sizeof("tglg")];
- char uniname2ctype_pool_str4626[sizeof("tagalog")];
- char uniname2ctype_pool_str4627[sizeof("othergraphemeextend")];
- char uniname2ctype_pool_str4674[sizeof("insupplementaryprivateuseareaa")];
- char uniname2ctype_pool_str4683[sizeof("inhighsurrogates")];
- char uniname2ctype_pool_str4695[sizeof("hebrew")];
- char uniname2ctype_pool_str4734[sizeof("duployan")];
- char uniname2ctype_pool_str4755[sizeof("graphemeclusterbreak=v")];
- char uniname2ctype_pool_str4756[sizeof("graphemeclusterbreak=lv")];
- char uniname2ctype_pool_str4772[sizeof("insupplementalarrowsb")];
- char uniname2ctype_pool_str4783[sizeof("graphemeclusterbreak=zwj")];
- char uniname2ctype_pool_str4810[sizeof("telugu")];
- char uniname2ctype_pool_str4898[sizeof("zyyy")];
- char uniname2ctype_pool_str4982[sizeof("olduyghur")];
- char uniname2ctype_pool_str4986[sizeof("inhangulcompatibilityjamo")];
- char uniname2ctype_pool_str5018[sizeof("openpunctuation")];
- char uniname2ctype_pool_str5038[sizeof("hyphen")];
- char uniname2ctype_pool_str5134[sizeof("insupplementalsymbolsandpictographs")];
- char uniname2ctype_pool_str5141[sizeof("egyp")];
- char uniname2ctype_pool_str5300[sizeof("nyiakengpuachuehmong")];
- char uniname2ctype_pool_str5980[sizeof("egyptianhieroglyphs")];
- char uniname2ctype_pool_str6098[sizeof("insupplementaryprivateuseareab")];
-#endif /* USE_UNICODE_PROPERTIES */
- };
-static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
- {
-#ifndef USE_UNICODE_PROPERTIES
- "word",
-#else /* USE_UNICODE_PROPERTIES */
- "yi",
- "yiii",
- "lana",
- "lina",
- "maka",
- "mani",
- "mn",
- "miao",
- "lo",
- "ci",
- "lao",
- "laoo",
- "inkannada",
- "cn",
- "pi",
- "innko",
- "z",
- "gran",
- "co",
- "lineara",
- "mark",
- "yezi",
- "po",
- "me",
- "cari",
- "inkharoshthi",
- "kana",
- "loe",
- "m",
- "grek",
- "mro",
- "mroo",
- "carian",
- "geor",
- "greek",
- "gonm",
- "mendekikakui",
- "pe",
- "mero",
- "inosmanya",
- "cakm",
- "inmanichaean",
- "inmro",
- "inmiao",
- "inchakma",
- "c",
- "mandaic",
- "meeteimayek",
- "zzzz",
- "inarmenian",
- "inmyanmar",
- "inmakasar",
- "common",
- "lm",
- "marc",
- "inrunic",
- "incarian",
- "inideographicsymbolsandpunctuation",
- "inkhmer",
- "qaai",
- "inahom",
- "merc",
- "inchorasmian",
- "combiningmark",
- "lc",
- "perm",
- "mc",
- "connectorpunctuation",
- "cans",
- "incuneiformnumbersandpunctuation",
- "armi",
- "cc",
- "armn",
- "incherokee",
- "prependedconcatenationmark",
- "incuneiform",
- "inavestan",
- "inipaextensions",
- "pc",
- "armenian",
- "insharada",
- "vai",
- "vaii",
- "inmarchen",
- "makasar",
- "masaramgondi",
- "inarrows",
- "incyrillic",
- "incham",
- "qmark",
- "ri",
- "qaac",
- "insamaritan",
- "latn",
- "inmasaramgondi",
- "inthaana",
- "latin",
- "inthai",
- "lineseparator",
- "pcm",
- "inkatakana",
- "inkaithi",
- "inscriptionalparthian",
- "initialpunctuation",
- "mtei",
- "inzanabazarsquare",
- "inkhmersymbols",
- "insyriac",
- "intakri",
- "arabic",
- "katakana",
- "prti",
- "zs",
- "ascii",
- "cs",
- "ps",
- "mand",
- "privateuse",
- "inruminumeralsymbols",
- "inmyanmarextendeda",
- "modi",
- "incjkcompatibilityforms",
- "inkanaextendeda",
- "incjkcompatibilityideographs",
- "brai",
- "mend",
- "ideo",
- "letter",
- "l",
- "inmeeteimayek",
- "inideographicdescriptioncharacters",
- "yezidi",
- "knda",
- "innandinagari",
- "kannada",
- "inmodi",
- "inlao",
- "xidcontinue",
- "inoldnortharabian",
- "intransportandmapsymbols",
- "letternumber",
- "gothic",
- "inlineara",
- "inmendekikakui",
- "mongolian",
- "inmiscellaneousmathematicalsymbolsa",
- "inspecials",
- "grlink",
- "brahmi",
- "inemoticons",
- "kali",
- "inolditalic",
- "xidc",
- "inmedefaidrin",
- "inchesssymbols",
- "incjkcompatibilityideographssupplement",
- "kits",
- "inadlam",
- "psalterpahlavi",
- "incommonindicnumberforms",
- "lt",
- "innewa",
- "sk",
- "control",
- "inkawi",
- "inancientsymbols",
- "palm",
- "inlycian",
- "so",
- "patternwhitespace",
- "inmandaic",
- "idc",
- "meroiticcursive",
- "intoto",
- "vs",
- "xids",
- "inwarangciti",
- "sora",
- "inopticalcharacterrecognition",
- "kawi",
- "inoldsogdian",
- "inmalayalam",
- "bamum",
- "inkanasupplement",
- "insundanese",
- "grext",
-#endif /* USE_UNICODE_PROPERTIES */
- "print",
-#ifndef USE_UNICODE_PROPERTIES
- "punct",
- "alpha",
-#else /* USE_UNICODE_PROPERTIES */
- "intaitham",
- "lower",
- "patternsyntax",
- "joinc",
- "inoldsoutharabian",
- "incjkstrokes",
- "batk",
- "samr",
- "inwancho",
- "batak",
- "patws",
- "samaritan",
- "idsbinaryoperator",
- "pauc",
- "insmallkanaextension",
- "sm",
- "indominotiles",
-#endif /* USE_UNICODE_PROPERTIES */
- "alnum",
-#ifdef USE_UNICODE_PROPERTIES
- "inznamennymusicalnotation",
- "insylotinagri",
- "inugaritic",
- "incontrolpictures",
- "inlinearbideograms",
- "inmusicalsymbols",
- "s",
- "ital",
- "inmodifiertoneletters",
- "inancientgreekmusicalnotation",
- "lisu",
- "lowercase",
- "cwcm",
- "sc",
- "bass",
- "ids",
- "inlatinextendeda",
- "intaile",
- "inmiscellaneoussymbols",
- "inmiscellaneoussymbolsandarrows",
- "incaucasianalbanian",
- "inmiscellaneoussymbolsandpictographs",
- "inoldturkic",
- "insaurashtra",
- "incyrillicextendeda",
- "idcontinue",
- "intaixuanjingsymbols",
- "intamil",
- "inmultani",
- "inlatinextendede",
- "pd",
- "bali",
- "blank",
- "idst",
- "inlydian",
- "innewtailue",
- "bengali",
- "runr",
- "ll",
- "indeseret",
- "inancientgreeknumbers",
- "idstart",
- "zl",
- "inmeeteimayekextensions",
- "balinese",
- "incyrillicextendedc",
- "inspacingmodifierletters",
- "inearlydynasticcuneiform",
- "plrd",
- "canadianaboriginal",
- "sind",
- "inlatinextendedc",
- "uideo",
- "incountingrodnumerals",
- "zinh",
- "dia",
- "di",
- "inkhudawadi",
- "inhanifirohingya",
- "diak",
- "gong",
- "ingrantha",
- "bidic",
- "xidstart",
-#endif /* USE_UNICODE_PROPERTIES */
- "xdigit",
-#ifndef USE_UNICODE_PROPERTIES
- "upper",
- "ascii",
-#else /* USE_UNICODE_PROPERTIES */
- "mong",
- "cased",
- "inhiragana",
- "sinhala",
- "adlm",
- "xsux",
- "glagolitic",
- "sterm",
- "bamu",
- "georgian",
- "inosage",
- "gunjalagondi",
- "phoenician",
- "inolduyghur",
- "multani",
- "kaithi",
- "joincontrol",
- "runic",
- "ingeneralpunctuation",
- "inmahajani",
- "incyrillicsupplement",
- "lowercaseletter",
- "marchen",
- "graphemelink",
- "ingeorgian",
- "khojki",
- "cham",
- "inogham",
- "cher",
- "chakma",
- "inkaktoviknumerals",
- "emoji",
- "insiddham",
- "cherokee",
- "khar",
- "inmongolian",
- "innagmundari",
- "incherokeesupplement",
- "manichaean",
- "inolchiki",
- "inkhitansmallscript",
- "quotationmark",
- "vithkuqi",
- "variationselector",
- "adlam",
- "inethiopic",
- "graphemebase",
-#ifdef USE_UNICODE_AGE_PROPERTIES
- "age=11.0",
- "age=12.1",
- "age=10.0",
- "age=12.0",
- "age=13.0",
- "age=1.1",
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- "casedletter",
- "ingurmukhi",
-#ifdef USE_UNICODE_AGE_PROPERTIES
- "age=2.1",
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- "incjkunifiedideographsextensiona",
-#ifdef USE_UNICODE_AGE_PROPERTIES
- "age=2.0",
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- "lu",
-#ifdef USE_UNICODE_AGE_PROPERTIES
- "age=3.1",
- "age=9.0",
- "age=3.0",
- "age=3.2",
- "age=8.0",
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- "intamilsupplement",
-#ifdef USE_UNICODE_AGE_PROPERTIES
- "age=6.1",
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- "unknown",
-#ifdef USE_UNICODE_AGE_PROPERTIES
- "age=6.0",
- "age=6.2",
- "age=15.0",
- "age=7.0",
- "age=6.3",
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- "cwt",
-#ifdef USE_UNICODE_AGE_PROPERTIES
- "age=14.0",
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- "unassigned",
-#ifdef USE_UNICODE_AGE_PROPERTIES
- "age=5.1",
- "age=5.0",
- "age=5.2",
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- "diacritic",
-#ifdef USE_UNICODE_AGE_PROPERTIES
- "age=4.1",
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- "ahom",
-#ifdef USE_UNICODE_AGE_PROPERTIES
- "age=4.0",
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- "incjkunifiedideographsextensione",
- "khmr",
- "insinhala",
- "inmiscellaneoustechnical",
- "saur",
- "guru",
- "sundanese",
- "punct",
- "paucinhau",
- "gurmukhi",
- "chorasmian",
- "logicalorderexception",
- "khmer",
- "limbu",
- "chrs",
- "oriya",
- "inscriptionalpahlavi",
- "incyrillicextendedd",
- "incjkunifiedideographsextensionc",
-#endif /* USE_UNICODE_PROPERTIES */
- "cntrl",
-#ifndef USE_UNICODE_PROPERTIES
- "space",
-#else /* USE_UNICODE_PROPERTIES */
- "inlatinextendedadditional",
- "insorasompeng",
- "radical",
- "emojimodifier",
- "kharoshthi",
- "n",
- "math",
- "goth",
- "phnx",
- "anatolianhieroglyphs",
- "inenclosedalphanumerics",
- "nandinagari",
- "no",
- "intangsa",
- "nko",
- "nkoo",
- "ingreekandcoptic",
- "p",
- "grantha",
- "decimalnumber",
- "incjkunifiedideographs",
- "intirhuta",
- "inhatran",
- "linb",
- "mult",
- "saurashtra",
- "kthi",
- "zanb",
- "inbhaiksuki",
- "innabataean",
- "inphoenician",
- "xpeo",
- "inkanbun",
- "inmeroitichieroglyphs",
- "ahex",
- "enclosingmark",
- "sd",
- "inelbasan",
- "inenclosedideographicsupplement",
- "sidd",
- "linearb",
- "cpmn",
- "inenclosedalphanumericsupplement",
- "bidicontrol",
- "inphaistosdisc",
- "limb",
- "inkangxiradicals",
- "lepc",
- "braille",
- "regionalindicator",
- "inlowsurrogates",
- "brah",
- "inoldhungarian",
- "beng",
- "emojimodifierbase",
- "inarabic",
- "osage",
- "inherited",
- "incyprominoan",
- "glag",
- "medf",
- "osma",
- "indogra",
- "arab",
- "medefaidrin",
- "inshorthandformatcontrols",
- "phli",
- "inimperialaramaic",
- "emod",
- "ingreekextended",
- "inanatolianhieroglyphs",
- "punctuation",
- "graphemeextend",
- "cwl",
- "vith",
- "ingeometricshapes",
- "emojicomponent",
- "dsrt",
- "coptic",
- "inkayahli",
- "inoriya",
- "inarabicpresentationformsa",
- "inbasiclatin",
- "incjkunifiedideographsextensiond",
- "wara",
- "sinh",
- "sund",
- "shavian",
- "insundanesesupplement",
- "inyezidi",
- "bhks",
- "bhaiksuki",
- "inhanunoo",
- "intangut",
- "sogdian",
- "inlatinextendedd",
- "sogo",
- "insinhalaarchaicnumbers",
- "ideographic",
- "ugar",
- "deseret",
- "odi",
- "copt",
- "imperialaramaic",
- "insogdian",
- "indingbats",
- "format",
- "ininscriptionalpahlavi",
- "lyci",
- "ininscriptionalparthian",
- "grbase",
- "lycian",
- "inbatak",
- "cprt",
- "inunifiedcanadianaboriginalsyllabicsextendeda",
- "mymr",
- "myanmar",
- "intibetan",
- "intags",
- "asciihexdigit",
- "sentenceterminal",
- "nand",
- "inblockelements",
- "inornamentaldingbats",
- "inethiopicextendeda",
- "innumberforms",
- "cwcf",
- "oidc",
- "bopo",
- "cuneiform",
- "caseignorable",
- "inoldpersian",
- "cwu",
- "inelymaic",
- "insoyombo",
- "ingeometricshapesextended",
- "incjkcompatibility",
- "inmyanmarextendedb",
- "innushu",
- "inkanaextendedb",
- "olck",
- "inbyzantinemusicalsymbols",
- "olchiki",
- "inkatakanaphoneticextensions",
- "incoptic",
- "oids",
- "inarabicextendeda",
- "modifierletter",
- "incjksymbolsandpunctuation",
- "olower",
- "bopomofo",
- "inlisu",
- "inoldpermic",
- "innoblock",
- "ext",
- "inunifiedcanadianaboriginalsyllabics",
- "takri",
- "inbraillepatterns",
- "invai",
- "alpha",
- "inbalinese",
- "sorasompeng",
- "closepunctuation",
- "hani",
- "inmayannumerals",
- "han",
- "inmiscellaneousmathematicalsymbolsb",
- "inlepcha",
- "patsyn",
- "inlisusupplement",
- "insyriacsupplement",
- "hano",
- "newa",
- "spacingmark",
- "inpalmyrene",
- "takr",
-#endif /* USE_UNICODE_PROPERTIES */
- "xposixpunct",
-#ifndef USE_UNICODE_PROPERTIES
- "lower",
-#else /* USE_UNICODE_PROPERTIES */
- "inkhojki",
- "taile",
- "assigned",
- "hanunoo",
- "hira",
- "inarabicextendedc",
- "newtailue",
- "space",
- "intelugu",
- "lydi",
- "idsb",
- "extpict",
- "lydian",
- "inethiopicsupplement",
- "sarb",
- "ugaritic",
- "inyiradicals",
- "inphoneticextensions",
- "sharada",
- "zanabazarsquare",
- "bugi",
- "word",
- "term",
- "separator",
- "ingeorgiansupplement",
- "sogd",
- "extender",
- "shrd",
-#endif /* USE_UNICODE_PROPERTIES */
- "graph",
-#ifdef USE_UNICODE_PROPERTIES
- "tnsa",
- "tangsa",
- "phag",
- "dogra",
- "inhanguljamo",
- "inshavian",
- "siddham",
- "cf",
- "inunifiedcanadianaboriginalsyllabicsextended",
- "buginese",
- "inmongoliansupplement",
- "cyrl",
- "inhanguljamoextendeda",
- "pf",
- "number",
- "inphoneticextensionssupplement",
- "dogr",
- "mlym",
- "incopticepactnumbers",
- "malayalam",
- "inbamum",
- "nd",
- "insuttonsignwriting",
- "inethiopicextended",
- "shaw",
- "palmyrene",
- "soyo",
- "incjkunifiedideographsextensionh",
- "sgnw",
- "toto",
- "caucasianalbanian",
- "inmathematicalalphanumericsymbols",
- "incjkunifiedideographsextensiong",
- "hatran",
- "taiviet",
- "meroitichieroglyphs",
- "ingeorgianextended",
- "incjkunifiedideographsextensionf",
- "oldpersian",
- "induployan",
- "incyrillicextendedb",
- "dash",
- "hatr",
- "innyiakengpuachuehmong",
- "incombiningdiacriticalmarks",
- "nl",
- "incombiningdiacriticalmarksforsymbols",
- "khudawadi",
- "incjkradicalssupplement",
- "inglagolitic",
- "orkh",
- "syrc",
- "surrogate",
- "indevanagari",
- "avestan",
- "oldpermic",
- "ethi",
- "ogam",
- "rohg",
- "idstrinaryoperator",
- "java",
- "inphagspa",
- "lepcha",
- "indevanagariextendeda",
- "intifinagh",
- "intagalog",
- "incombiningdiacriticalmarkssupplement",
- "tale",
- "inbrahmi",
- "terminalpunctuation",
- "insymbolsandpictographsextendeda",
- "syriac",
- "inbengali",
- "nagm",
- "extendedpictographic",
- "buhd",
- "javanese",
- "taml",
- "inbuginese",
- "inlatin1supplement",
- "ingothic",
- "invariationselectors",
- "hex",
- "inverticalforms",
- "ebase",
- "incurrencysymbols",
- "avst",
- "osge",
- "incombiningdiacriticalmarksextended",
- "intaiviet",
- "spaceseparator",
- "softdotted",
- "nchar",
- "invedicextensions",
- "inlimbu",
- "olditalic",
- "gujr",
- "mathsymbol",
- "incjkunifiedideographsextensionb",
- "gujarati",
- "phagspa",
- "invariationselectorssupplement",
- "currencysymbol",
- "inlinearbsyllabary",
- "wancho",
- "inpaucinhau",
- "other",
- "otheridcontinue",
- "sylo",
- "zp",
- "inaegeannumbers",
- "warangciti",
- "othernumber",
-#endif /* USE_UNICODE_PROPERTIES */
- "digit",
-#ifndef USE_UNICODE_PROPERTIES
- "blank"
-#else /* USE_UNICODE_PROPERTIES */
- "nonspacingmark",
- "titlecaseletter",
- "inmeroiticcursive",
- "wcho",
- "graphemeclusterbreak=spacingmark",
- "inletterlikesymbols",
- "inottomansiyaqnumbers",
- "intagbanwa",
- "cyrillic",
- "oalpha",
- "graphemeclusterbreak=cr",
- "narb",
- "changeswhencasemapped",
- "inbopomofo",
- "graphemeclusterbreak=regionalindicator",
- "otheralphabetic",
- "noncharactercodepoint",
- "oldhungarian",
- "insymbolsforlegacycomputing",
- "insmallformvariants",
- "inhangulsyllables",
- "emojipresentation",
- "epres",
- "inbassavah",
- "indevanagariextended",
- "inbuhid",
- "tirhuta",
- "inpsalterpahlavi",
- "whitespace",
- "finalpunctuation",
- "orya",
- "phlp",
- "inbamumsupplement",
- "buhid",
- "paragraphseparator",
- "inalphabeticpresentationforms",
- "inlatinextendedg",
- "elba",
- "changeswhentitlecased",
- "incombininghalfmarks",
- "intangutcomponents",
- "thaa",
- "thai",
- "oldturkic",
- "thaana",
- "inlatinextendedf",
- "ougr",
- "tang",
- "inarabicmathematicalalphabeticsymbols",
- "tagbanwa",
- "tamil",
- "khitansmallscript",
- "mahj",
- "mahajani",
- "hang",
- "tirh",
- "sylotinagri",
- "talu",
- "nagmundari",
- "deva",
- "ingujarati",
- "deprecated",
- "inarabicpresentationformsb",
- "devanagari",
- "ingunjalagondi",
- "graphemeclusterbreak=t",
- "graphemeclusterbreak=lvt",
- "taitham",
- "nbat",
- "telu",
- "hiragana",
- "nabataean",
- "inrejang",
- "intangutsupplement",
- "khoj",
- "hmng",
- "cyprominoan",
- "inhebrew",
- "inmathematicaloperators",
- "inarabicsupplement",
- "inenclosedcjklettersandmonths",
- "changeswhenlowercased",
- "tangut",
- "elbasan",
- "osmanya",
- "insuperscriptsandsubscripts",
- "graphemeclusterbreak=extend",
- "graphemeclusterbreak=prepend",
- "nshu",
- "otherlowercase",
- "inethiopicextendedb",
- "otherletter",
- "kayahli",
- "inplayingcards",
- "elym",
- "graphemeclusterbreak=l",
- "graphemeclusterbreak=control",
- "ogrext",
- "elymaic",
- "changeswhenuppercased",
- "inalchemicalsymbols",
- "oldsogdian",
- "otheridstart",
- "insupplementalarrowsa",
- "invithkuqi",
- "symbol",
- "inarabicextendedb",
- "cypriot",
- "any",
- "otheruppercase",
- "rjng",
- "wspace",
- "inindicsiyaqnumbers",
- "inprivateusearea",
- "othersymbol",
- "oupper",
- "signwriting",
- "nushu",
- "hmnp",
- "upper",
- "insupplementalarrowsc",
- "omath",
- "modifiersymbol",
- "hebr",
- "inhalfwidthandfullwidthforms",
- "insupplementalmathematicaloperators",
- "inpahawhhmong",
- "alphabetic",
- "uppercase",
- "dupl",
- "ogham",
- "dashpunctuation",
- "hangul",
- "inhanguljamoextendedb",
- "bassavah",
- "aghb",
- "hung",
- "hexdigit",
- "incypriotsyllabary",
- "indivesakuru",
- "tibt",
- "inlatinextendedb",
- "hluw",
- "tibetan",
- "inyisyllables",
- "oldnortharabian",
- "defaultignorablecodepoint",
- "inhighprivateusesurrogates",
- "soyombo",
- "otherdefaultignorablecodepoint",
- "pahawhhmong",
- "unifiedideograph",
- "othermath",
- "changeswhencasefolded",
- "inmahjongtiles",
- "dep",
- "divesakuru",
- "graphemeclusterbreak=lf",
- "uppercaseletter",
- "insupplementalpunctuation",
- "ethiopic",
- "inyijinghexagramsymbols",
- "ecomp",
- "inglagoliticsupplement",
- "inbopomofoextended",
- "injavanese",
- "otherpunctuation",
- "tifinagh",
- "tfng",
- "hanifirohingya",
- "tavt",
- "inboxdrawing",
- "oldsoutharabian",
- "inegyptianhieroglyphs",
- "inegyptianhieroglyphformatcontrols",
- "tagb",
- "rejang",
- "tglg",
- "tagalog",
- "othergraphemeextend",
- "insupplementaryprivateuseareaa",
- "inhighsurrogates",
- "hebrew",
- "duployan",
- "graphemeclusterbreak=v",
- "graphemeclusterbreak=lv",
- "insupplementalarrowsb",
- "graphemeclusterbreak=zwj",
- "telugu",
- "zyyy",
- "olduyghur",
- "inhangulcompatibilityjamo",
- "openpunctuation",
- "hyphen",
- "insupplementalsymbolsandpictographs",
- "egyp",
- "nyiakengpuachuehmong",
- "egyptianhieroglyphs",
- "insupplementaryprivateuseareab"
-#endif /* USE_UNICODE_PROPERTIES */
- };
-#define uniname2ctype_pool ((const char *) &uniname2ctype_pool_contents)
-const struct uniname2ctype_struct *
-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},
- {uniname2ctype_offset(str17), 111},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str22), 152},
- {-1}, {-1},
- {uniname2ctype_offset(str25), 184},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str33), 218},
- {-1},
- {uniname2ctype_offset(str35), 186},
- {uniname2ctype_offset(str36), 34},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str45), 173},
- {uniname2ctype_offset(str46), 28},
- {uniname2ctype_offset(str47), 61},
- {uniname2ctype_offset(str48), 95},
- {uniname2ctype_offset(str49), 95},
- {-1}, {-1},
- {uniname2ctype_offset(str52), 346},
- {-1}, {-1},
- {uniname2ctype_offset(str55), 21},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str64), 44},
- {-1},
- {uniname2ctype_offset(str66), 333},
- {uniname2ctype_offset(str67), 52},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str71), 181},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str75), 22},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str83), 184},
- {-1}, {-1},
- {uniname2ctype_offset(str86), 31},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str90), 230},
- {-1},
- {uniname2ctype_offset(str92), 45},
- {-1},
- {uniname2ctype_offset(str94), 33},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str100), 149},
- {uniname2ctype_offset(str101), 513},
- {uniname2ctype_offset(str102), 108},
- {uniname2ctype_offset(str103), 263},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str107), 31},
- {uniname2ctype_offset(str108), 77},
- {-1}, {-1},
- {uniname2ctype_offset(str111), 189},
- {uniname2ctype_offset(str112), 189},
- {-1}, {-1},
- {uniname2ctype_offset(str115), 149},
- {-1},
- {uniname2ctype_offset(str117), 98},
- {uniname2ctype_offset(str118), 77},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str122), 212},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str129), 187},
- {uniname2ctype_offset(str130), 42},
- {uniname2ctype_offset(str131), 172},
- {-1}, {-1},
- {uniname2ctype_offset(str134), 497},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str139), 170},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str145), 516},
- {uniname2ctype_offset(str146), 575},
- {-1},
- {uniname2ctype_offset(str148), 580},
- {uniname2ctype_offset(str149), 535},
- {-1},
- {uniname2ctype_offset(str151), 18},
- {uniname2ctype_offset(str152), 169},
- {uniname2ctype_offset(str153), 160},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str158), 278},
- {-1}, {-1},
- {uniname2ctype_offset(str161), 327},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str177), 352},
- {uniname2ctype_offset(str178), 563},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str183), 75},
- {-1}, {-1},
- {uniname2ctype_offset(str186), 27},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str190), 208},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str203), 360},
- {uniname2ctype_offset(str204), 488},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str210), 581},
- {-1},
- {uniname2ctype_offset(str212), 365},
- {uniname2ctype_offset(str213), 115},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str218), 549},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str226), 171},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str230), 530},
- {uniname2ctype_offset(str231), 31},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str236), 25},
- {uniname2ctype_offset(str237), 194},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str246), 32},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str250), 40},
- {-1}, {-1},
- {uniname2ctype_offset(str253), 102},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str260), 568},
- {-1}, {-1},
- {uniname2ctype_offset(str263), 161},
- {-1},
- {uniname2ctype_offset(str265), 19},
- {-1},
- {uniname2ctype_offset(str267), 79},
- {uniname2ctype_offset(str268), 357},
- {-1},
- {uniname2ctype_offset(str270), 270},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str274), 567},
- {uniname2ctype_offset(str275), 517},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str281), 321},
- {uniname2ctype_offset(str282), 40},
- {uniname2ctype_offset(str283), 79},
- {-1},
- {uniname2ctype_offset(str285), 537},
- {-1},
- {uniname2ctype_offset(str287), 144},
- {uniname2ctype_offset(str288), 144},
- {uniname2ctype_offset(str289), 560},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str293), 218},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str297), 212},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str301), 395},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str311), 325},
- {-1},
- {uniname2ctype_offset(str313), 456},
- {-1},
- {uniname2ctype_offset(str315), 243},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str320), 271},
- {-1},
- {uniname2ctype_offset(str322), 129},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str328), 334},
- {-1}, {-1},
- {uniname2ctype_offset(str331), 76},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str335), 561},
- {-1}, {-1},
- {uniname2ctype_offset(str338), 332},
- {-1},
- {uniname2ctype_offset(str340), 76},
- {-1},
- {uniname2ctype_offset(str342), 349},
- {-1}, {-1},
- {uniname2ctype_offset(str345), 53},
- {uniname2ctype_offset(str346), 270},
- {-1},
- {uniname2ctype_offset(str348), 426},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str352), 533},
- {-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}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str381), 554},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str386), 371},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str399), 330},
- {-1},
- {uniname2ctype_offset(str401), 548},
- {-1}, {-1},
- {uniname2ctype_offset(str404), 81},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str418), 108},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str426), 163},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str430), 55},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str442), 14},
- {-1}, {-1},
- {uniname2ctype_offset(str445), 23},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str462), 46},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str468), 169},
- {-1},
- {uniname2ctype_offset(str470), 22},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str475), 524},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str480), 457},
- {uniname2ctype_offset(str481), 188},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str486), 476},
- {-1},
- {uniname2ctype_offset(str488), 588},
- {-1}, {-1},
- {uniname2ctype_offset(str491), 470},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str500), 127},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str504), 187},
- {uniname2ctype_offset(str505), 249},
- {uniname2ctype_offset(str506), 24},
- {-1}, {-1},
- {uniname2ctype_offset(str509), 24},
- {-1},
- {uniname2ctype_offset(str511), 463},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str520), 423},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str533), 230},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str538), 91},
- {-1}, {-1},
- {uniname2ctype_offset(str541), 553},
- {-1},
- {uniname2ctype_offset(str543), 91},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str556), 546},
- {-1},
- {uniname2ctype_offset(str558), 350},
- {uniname2ctype_offset(str559), 70},
- {uniname2ctype_offset(str560), 515},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str565), 624},
- {uniname2ctype_offset(str566), 37},
- {-1},
- {uniname2ctype_offset(str568), 113},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str572), 502},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str577), 611},
- {-1},
- {uniname2ctype_offset(str579), 106},
- {-1}, {-1},
- {uniname2ctype_offset(str582), 406},
- {uniname2ctype_offset(str583), 480},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str590), 74},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str594), 168},
- {-1},
- {uniname2ctype_offset(str596), 622},
- {uniname2ctype_offset(str597), 146},
- {-1}, {-1},
- {uniname2ctype_offset(str600), 490},
- {-1},
- {uniname2ctype_offset(str602), 70},
- {-1},
- {uniname2ctype_offset(str604), 579},
- {uniname2ctype_offset(str605), 629},
- {-1}, {-1},
- {uniname2ctype_offset(str608), 637},
- {uniname2ctype_offset(str609), 229},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str614), 612},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str624), 195},
- {uniname2ctype_offset(str625), 447},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str630), 29},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str636), 543},
- {-1}, {-1},
- {uniname2ctype_offset(str639), 49},
- {-1}, {-1},
- {uniname2ctype_offset(str642), 19},
- {uniname2ctype_offset(str643), 564},
- {-1},
- {uniname2ctype_offset(str645), 485},
- {-1},
- {uniname2ctype_offset(str647), 192},
- {-1}, {-1},
- {uniname2ctype_offset(str650), 487},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str657), 51},
- {-1}, {-1},
- {uniname2ctype_offset(str660), 268},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str672), 335},
- {-1}, {-1},
- {uniname2ctype_offset(str675), 68},
- {-1}, {-1},
- {uniname2ctype_offset(str678), 171},
- {uniname2ctype_offset(str679), 607},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str683), 267},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str692), 69},
- {-1}, {-1},
- {uniname2ctype_offset(str695), 551},
- {uniname2ctype_offset(str696), 175},
- {uniname2ctype_offset(str697), 399},
- {-1}, {-1},
- {uniname2ctype_offset(str700), 236},
- {-1}, {-1},
- {uniname2ctype_offset(str703), 527},
- {-1},
- {uniname2ctype_offset(str705), 347},
- {-1},
- {uniname2ctype_offset(str707), 158},
- {uniname2ctype_offset(str708), 587},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str713), 376},
- {-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), 373},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str742), 6},
- {-1}, {-1},
- {uniname2ctype_offset(str745), 269},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str753), 240},
- {-1},
- {uniname2ctype_offset(str755), 514},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str760), 431},
- {uniname2ctype_offset(str761), 167},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str766), 156},
- {uniname2ctype_offset(str767), 608},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str771), 167},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str776), 268},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str783), 156},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str787), 256},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str791), 193},
- {-1}, {-1},
- {uniname2ctype_offset(str794), 589},
- {-1}, {-1},
- {uniname2ctype_offset(str797), 50},
- {-1},
- {uniname2ctype_offset(str799), 617},
- {-1}, {-1},
- {uniname2ctype_offset(str802), 13},
- {uniname2ctype_offset(str803), 593},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str809), 446},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str814), 493},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str818), 398},
- {-1}, {-1},
- {uniname2ctype_offset(str821), 482},
- {uniname2ctype_offset(str822), 595},
- {uniname2ctype_offset(str823), 47},
- {uniname2ctype_offset(str824), 112},
- {uniname2ctype_offset(str825), 444},
- {-1}, {-1},
- {uniname2ctype_offset(str828), 596},
- {-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},
- {uniname2ctype_offset(str847), 48},
- {uniname2ctype_offset(str848), 178},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str855), 67},
- {-1},
- {uniname2ctype_offset(str857), 319},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str875), 369},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
- {uniname2ctype_offset(str886), 404},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str895), 412},
- {-1}, {-1},
- {uniname2ctype_offset(str898), 500},
- {-1},
- {uniname2ctype_offset(str900), 621},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str906), 521},
- {uniname2ctype_offset(str907), 449},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str920), 419},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str924), 68},
- {uniname2ctype_offset(str925), 599},
- {uniname2ctype_offset(str926), 344},
- {-1},
- {uniname2ctype_offset(str928), 540},
- {uniname2ctype_offset(str929), 461},
- {uniname2ctype_offset(str930), 41},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str946), 136},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str961), 2},
- {-1},
- {uniname2ctype_offset(str963), 257},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
- {uniname2ctype_offset(str974), 510},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str986), 370},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str994), 85},
- {uniname2ctype_offset(str995), 104},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1010), 26},
- {-1}, {-1},
- {uniname2ctype_offset(str1013), 495},
- {-1},
- {uniname2ctype_offset(str1015), 484},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1021), 67},
- {-1}, {-1},
- {uniname2ctype_offset(str1024), 53},
- {uniname2ctype_offset(str1025), 459},
- {-1}, {-1},
- {uniname2ctype_offset(str1028), 136},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1032), 380},
- {-1}, {-1},
- {uniname2ctype_offset(str1035), 322},
- {uniname2ctype_offset(str1036), 569},
- {-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}, {-1}, {-1},
- {uniname2ctype_offset(str1072), 197},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1081), 414},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1085), 259},
- {-1},
- {uniname2ctype_offset(str1087), 600},
- {-1},
- {uniname2ctype_offset(str1089), 115},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1095), 250},
- {uniname2ctype_offset(str1096), 71},
- {uniname2ctype_offset(str1097), 541},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1102), 523},
- {-1},
- {uniname2ctype_offset(str1104), 228},
- {uniname2ctype_offset(str1105), 217},
- {-1},
- {uniname2ctype_offset(str1107), 542},
- {-1},
- {uniname2ctype_offset(str1109), 239},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1114), 69},
- {uniname2ctype_offset(str1115), 11},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1119), 106},
- {uniname2ctype_offset(str1120), 60},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1134), 425},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1140), 93},
- {-1},
- {uniname2ctype_offset(str1142), 206},
- {-1}, {-1},
- {uniname2ctype_offset(str1145), 137},
- {uniname2ctype_offset(str1146), 131},
- {uniname2ctype_offset(str1147), 266},
- {-1},
- {uniname2ctype_offset(str1149), 158},
- {uniname2ctype_offset(str1150), 98},
- {uniname2ctype_offset(str1151), 498},
- {uniname2ctype_offset(str1152), 217},
- {uniname2ctype_offset(str1153), 138},
- {-1}, {-1},
- {uniname2ctype_offset(str1156), 529},
- {uniname2ctype_offset(str1157), 203},
- {uniname2ctype_offset(str1158), 166},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1164), 240},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1168), 104},
- {-1},
- {uniname2ctype_offset(str1170), 389},
- {uniname2ctype_offset(str1171), 536},
- {-1}, {-1},
- {uniname2ctype_offset(str1174), 326},
- {uniname2ctype_offset(str1175), 26},
- {uniname2ctype_offset(str1176), 208},
- {uniname2ctype_offset(str1177), 74},
- {uniname2ctype_offset(str1178), 353},
- {-1},
- {uniname2ctype_offset(str1180), 183},
- {uniname2ctype_offset(str1181), 151},
- {uniname2ctype_offset(str1182), 359},
- {uniname2ctype_offset(str1183), 101},
- {-1},
- {uniname2ctype_offset(str1185), 170},
- {uniname2ctype_offset(str1186), 597},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1190), 272},
- {uniname2ctype_offset(str1191), 545},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1197), 101},
- {uniname2ctype_offset(str1198), 135},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1203), 366},
- {uniname2ctype_offset(str1204), 609},
- {-1}, {-1},
- {uniname2ctype_offset(str1207), 462},
- {-1},
- {uniname2ctype_offset(str1209), 186},
- {-1}, {-1},
- {uniname2ctype_offset(str1212), 379},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
- {uniname2ctype_offset(str1223), 584},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1227), 243},
- {-1},
- {uniname2ctype_offset(str1229), 235},
- {uniname2ctype_offset(str1230), 267},
- {uniname2ctype_offset(str1231), 206},
- {uniname2ctype_offset(str1232), 355},
- {uniname2ctype_offset(str1233), 73},
-#ifndef USE_UNICODE_AGE_PROPERTIES
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
-#else /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1234), 298},
- {uniname2ctype_offset(str1235), 300},
- {uniname2ctype_offset(str1236), 297},
- {uniname2ctype_offset(str1237), 299},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1241), 301},
- {uniname2ctype_offset(str1242), 279},
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1243), 25},
- {uniname2ctype_offset(str1244), 341},
-#ifndef USE_UNICODE_AGE_PROPERTIES
- {-1},
-#else /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1245), 281},
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1246), 435},
-#ifndef USE_UNICODE_AGE_PROPERTIES
- {-1},
-#else /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1247), 280},
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1248), 30},
-#ifndef USE_UNICODE_AGE_PROPERTIES
- {-1}, {-1}, {-1}, {-1}, {-1},
-#else /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1249), 283},
- {uniname2ctype_offset(str1250), 296},
- {uniname2ctype_offset(str1251), 282},
- {uniname2ctype_offset(str1252), 284},
- {uniname2ctype_offset(str1253), 295},
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1254), 566},
-#ifndef USE_UNICODE_AGE_PROPERTIES
- {-1},
-#else /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1255), 291},
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1256), 278},
-#ifndef USE_UNICODE_AGE_PROPERTIES
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
-#else /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1257), 290},
- {uniname2ctype_offset(str1258), 292},
- {uniname2ctype_offset(str1259), 303},
- {uniname2ctype_offset(str1260), 294},
- {-1},
- {uniname2ctype_offset(str1262), 293},
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1263), 64},
-#ifndef USE_UNICODE_AGE_PROPERTIES
- {-1}, {-1},
-#else /* USE_UNICODE_AGE_PROPERTIES */
- {-1},
- {uniname2ctype_offset(str1265), 302},
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1266), 21},
-#ifndef USE_UNICODE_AGE_PROPERTIES
- {-1}, {-1}, {-1}, {-1},
-#else /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1267), 288},
- {-1},
- {uniname2ctype_offset(str1269), 287},
- {uniname2ctype_offset(str1270), 289},
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1271), 250},
-#ifndef USE_UNICODE_AGE_PROPERTIES
- {-1}, {-1},
-#else /* USE_UNICODE_AGE_PROPERTIES */
- {-1},
- {uniname2ctype_offset(str1273), 286},
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1274), 200},
-#ifndef USE_UNICODE_AGE_PROPERTIES
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
-#else /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1275), 285},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
-#endif /* USE_UNICODE_AGE_PROPERTIES */
- {uniname2ctype_offset(str1282), 635},
- {-1}, {-1},
- {uniname2ctype_offset(str1285), 105},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1289), 348},
- {-1}, {-1},
- {uniname2ctype_offset(str1292), 397},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1297), 145},
- {-1}, {-1},
- {uniname2ctype_offset(str1300), 86},
- {uniname2ctype_offset(str1301), 141},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1306), 15},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1314), 193},
- {-1}, {-1},
- {uniname2ctype_offset(str1317), 86},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
- {uniname2ctype_offset(str1328), 227},
- {-1}, {-1},
- {uniname2ctype_offset(str1331), 263},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1340), 105},
- {-1}, {-1},
- {uniname2ctype_offset(str1343), 120},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1349), 227},
- {-1}, {-1},
- {uniname2ctype_offset(str1352), 88},
- {-1},
- {uniname2ctype_offset(str1354), 164},
- {-1},
- {uniname2ctype_offset(str1356), 605},
- {-1},
- {uniname2ctype_offset(str1358), 633},
- {-1},
- {uniname2ctype_offset(str1360), 3},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1365), 387},
- {-1},
- {uniname2ctype_offset(str1367), 534},
- {-1},
- {uniname2ctype_offset(str1369), 258},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1373), 274},
- {-1},
- {uniname2ctype_offset(str1375), 135},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1380), 35},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1384), 56},
- {-1}, {-1},
- {uniname2ctype_offset(str1387), 113},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1392), 138},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1400), 201},
- {uniname2ctype_offset(str1401), 400},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1407), 224},
- {-1},
- {uniname2ctype_offset(str1409), 38},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1415), 576},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1419), 140},
- {uniname2ctype_offset(str1420), 140},
- {-1},
- {uniname2ctype_offset(str1422), 324},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1426), 39},
- {-1},
- {uniname2ctype_offset(str1428), 181},
- {uniname2ctype_offset(str1429), 36},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1438), 437},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1442), 544},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1448), 508},
- {uniname2ctype_offset(str1449), 122},
- {-1},
- {uniname2ctype_offset(str1451), 203},
- {-1}, {-1},
- {uniname2ctype_offset(str1454), 145},
- {-1}, {-1},
- {uniname2ctype_offset(str1457), 166},
- {-1}, {-1},
- {uniname2ctype_offset(str1460), 215},
- {-1},
- {uniname2ctype_offset(str1462), 559},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1470), 507},
- {uniname2ctype_offset(str1471), 509},
- {-1}, {-1},
- {uniname2ctype_offset(str1474), 134},
- {uniname2ctype_offset(str1475), 429},
- {uniname2ctype_offset(str1476), 511},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1480), 247},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1489), 33},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1495), 262},
- {-1},
- {uniname2ctype_offset(str1497), 499},
- {-1},
- {uniname2ctype_offset(str1499), 620},
- {-1},
- {uniname2ctype_offset(str1501), 196},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1507), 122},
- {uniname2ctype_offset(str1508), 231},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1517), 619},
- {-1}, {-1},
- {uniname2ctype_offset(str1520), 239},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1524), 486},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1529), 120},
- {-1},
- {uniname2ctype_offset(str1531), 422},
- {-1},
- {uniname2ctype_offset(str1533), 142},
- {-1}, {-1},
- {uniname2ctype_offset(str1536), 127},
- {uniname2ctype_offset(str1537), 271},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1542), 468},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1547), 168},
- {-1},
- {uniname2ctype_offset(str1549), 522},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1557), 85},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1563), 275},
- {-1},
- {uniname2ctype_offset(str1565), 329},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1570), 210},
- {-1},
- {uniname2ctype_offset(str1572), 115},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1577), 570},
- {-1}, {-1},
- {uniname2ctype_offset(str1580), 131},
- {-1},
- {uniname2ctype_offset(str1582), 219},
- {uniname2ctype_offset(str1583), 125},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1587), 550},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1597), 81},
- {uniname2ctype_offset(str1598), 219},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1607), 592},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1613), 164},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1617), 505},
- {uniname2ctype_offset(str1618), 274},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1622), 388},
- {uniname2ctype_offset(str1623), 573},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1629), 39},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1635), 72},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1643), 62},
- {uniname2ctype_offset(str1644), 235},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1654), 403},
- {uniname2ctype_offset(str1655), 276},
- {-1},
- {uniname2ctype_offset(str1657), 114},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1662), 129},
- {-1},
- {uniname2ctype_offset(str1664), 451},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1671), 343},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1675), 472},
- {-1},
- {uniname2ctype_offset(str1677), 317},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1682), 634},
- {-1},
- {uniname2ctype_offset(str1684), 199},
- {-1},
- {uniname2ctype_offset(str1686), 93},
- {uniname2ctype_offset(str1687), 141},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1691), 124},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1699), 382},
- {-1},
- {uniname2ctype_offset(str1701), 525},
- {-1}, {-1},
- {uniname2ctype_offset(str1704), 207},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1714), 207},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1722), 362},
- {-1},
- {uniname2ctype_offset(str1724), 582},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1728), 221},
- {uniname2ctype_offset(str1729), 445},
- {uniname2ctype_offset(str1730), 222},
- {uniname2ctype_offset(str1731), 538},
- {uniname2ctype_offset(str1732), 249},
- {uniname2ctype_offset(str1733), 123},
- {uniname2ctype_offset(str1734), 114},
- {uniname2ctype_offset(str1735), 260},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1740), 129},
- {-1},
- {uniname2ctype_offset(str1742), 161},
- {-1}, {-1},
- {uniname2ctype_offset(str1745), 528},
- {uniname2ctype_offset(str1746), 405},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1750), 20},
- {-1},
- {uniname2ctype_offset(str1752), 519},
- {uniname2ctype_offset(str1753), 148},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1757), 518},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1766), 73},
- {-1},
- {uniname2ctype_offset(str1768), 148},
- {uniname2ctype_offset(str1769), 377},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1776), 126},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1781), 556},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1788), 97},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1793), 97},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1806), 351},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1810), 640},
- {uniname2ctype_offset(str1811), 247},
- {-1},
- {uniname2ctype_offset(str1813), 266},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1821), 224},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1828), 402},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1838), 623},
- {-1}, {-1},
- {uniname2ctype_offset(str1841), 460},
- {uniname2ctype_offset(str1842), 394},
- {uniname2ctype_offset(str1843), 65},
- {-1},
- {uniname2ctype_offset(str1845), 265},
- {-1}, {-1},
- {uniname2ctype_offset(str1848), 109},
- {-1}, {-1},
- {uniname2ctype_offset(str1851), 137},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1866), 61},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1871), 494},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1881), 63},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1888), 531},
- {uniname2ctype_offset(str1889), 555},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1896), 626},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1902), 434},
- {-1},
- {uniname2ctype_offset(str1904), 455},
- {uniname2ctype_offset(str1905), 590},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1912), 586},
- {uniname2ctype_offset(str1913), 143},
- {-1}, {-1},
- {uniname2ctype_offset(str1916), 594},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1924), 143},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1929), 432},
- {-1}, {-1},
- {uniname2ctype_offset(str1932), 415},
- {-1}, {-1},
- {uniname2ctype_offset(str1935), 264},
- {uniname2ctype_offset(str1936), 338},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1941), 27},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1950), 424},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1956), 252},
- {-1},
- {uniname2ctype_offset(str1958), 109},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1964), 440},
- {-1}, {-1},
- {uniname2ctype_offset(str1967), 492},
- {uniname2ctype_offset(str1968), 644},
- {uniname2ctype_offset(str1969), 251},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1974), 358},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1981), 176},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str1985), 408},
- {-1}, {-1},
- {uniname2ctype_offset(str1988), 441},
- {-1}, {-1},
- {uniname2ctype_offset(str1991), 1},
- {-1},
- {uniname2ctype_offset(str1993), 375},
- {uniname2ctype_offset(str1994), 175},
- {-1},
- {uniname2ctype_offset(str1996), 42},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2001), 110},
- {uniname2ctype_offset(str2002), 598},
- {-1},
- {uniname2ctype_offset(str2004), 110},
- {-1},
- {uniname2ctype_offset(str2006), 410},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2010), 378},
- {uniname2ctype_offset(str2011), 269},
- {uniname2ctype_offset(str2012), 565},
- {-1},
- {uniname2ctype_offset(str2014), 336},
- {uniname2ctype_offset(str2015), 117},
- {uniname2ctype_offset(str2016), 209},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2023), 32},
- {uniname2ctype_offset(str2024), 506},
- {-1},
- {uniname2ctype_offset(str2026), 176},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2033), 8},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2040), 539},
- {-1},
- {uniname2ctype_offset(str2042), 121},
- {uniname2ctype_offset(str2043), 17},
- {uniname2ctype_offset(str2044), 117},
- {-1}, {-1},
- {uniname2ctype_offset(str2047), 107},
- {uniname2ctype_offset(str2048), 526},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2062), 130},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2070), 9},
- {-1}, {-1},
- {uniname2ctype_offset(str2073), 345},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2077), 150},
- {uniname2ctype_offset(str2078), 256},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str2090), 277},
- {-1},
- {uniname2ctype_offset(str2092), 150},
- {-1}, {-1},
- {uniname2ctype_offset(str2095), 356},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2103), 162},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2110), 123},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2114), 439},
- {uniname2ctype_offset(str2115), 384},
- {-1},
- {uniname2ctype_offset(str2117), 174},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
- {uniname2ctype_offset(str2128), 215},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2135), 128},
- {-1},
- {uniname2ctype_offset(str2137), 12},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2141), 244},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2145), 52},
- {uniname2ctype_offset(str2146), 416},
- {-1}, {-1},
- {uniname2ctype_offset(str2149), 221},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2163), 251},
- {-1},
- {uniname2ctype_offset(str2165), 174},
- {uniname2ctype_offset(str2166), 5},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2174), 233},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2178), 233},
- {-1}, {-1},
- {uniname2ctype_offset(str2181), 139},
- {uniname2ctype_offset(str2182), 216},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2195), 354},
- {uniname2ctype_offset(str2196), 496},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
- {uniname2ctype_offset(str2207), 196},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2211), 20},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2216), 367},
- {uniname2ctype_offset(str2217), 128},
- {uniname2ctype_offset(str2218), 547},
- {uniname2ctype_offset(str2219), 78},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2224), 453},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2228), 43},
- {uniname2ctype_offset(str2229), 35},
- {-1}, {-1},
- {uniname2ctype_offset(str2232), 385},
- {uniname2ctype_offset(str2233), 216},
- {uniname2ctype_offset(str2234), 92},
- {uniname2ctype_offset(str2235), 489},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2241), 92},
- {-1}, {-1},
- {uniname2ctype_offset(str2244), 443},
- {-1}, {-1},
- {uniname2ctype_offset(str2247), 36},
- {uniname2ctype_offset(str2248), 602},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2276), 418},
- {-1},
- {uniname2ctype_offset(str2278), 124},
- {uniname2ctype_offset(str2279), 192},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2283), 214},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2296), 639},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2305), 205},
- {-1}, {-1},
- {uniname2ctype_offset(str2308), 234},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2312), 177},
- {-1}, {-1},
- {uniname2ctype_offset(str2315), 601},
- {uniname2ctype_offset(str2316), 638},
- {-1},
- {uniname2ctype_offset(str2318), 202},
- {-1}, {-1},
- {uniname2ctype_offset(str2321), 153},
- {-1},
- {uniname2ctype_offset(str2323), 172},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2327), 381},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2331), 636},
- {-1},
- {uniname2ctype_offset(str2333), 134},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2343), 591},
- {uniname2ctype_offset(str2344), 442},
- {uniname2ctype_offset(str2345), 241},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2353), 202},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2361), 606},
- {-1}, {-1},
- {uniname2ctype_offset(str2364), 323},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2373), 37},
- {uniname2ctype_offset(str2374), 392},
- {uniname2ctype_offset(str2375), 197},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2397), 421},
- {uniname2ctype_offset(str2398), 413},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2405), 165},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2414), 82},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2427), 23},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2433), 339},
- {uniname2ctype_offset(str2434), 154},
- {-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), 103},
- {-1}, {-1},
- {uniname2ctype_offset(str2454), 220},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2460), 257},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2464), 159},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2470), 448},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2475), 142},
- {uniname2ctype_offset(str2476), 558},
- {-1},
- {uniname2ctype_offset(str2478), 417},
- {uniname2ctype_offset(str2479), 361},
- {-1},
- {uniname2ctype_offset(str2481), 386},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2500), 121},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2506), 532},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2511), 244},
- {-1},
- {uniname2ctype_offset(str2513), 630},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2530), 82},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2534), 340},
- {uniname2ctype_offset(str2535), 237},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2545), 277},
- {-1}, {-1},
- {uniname2ctype_offset(str2548), 118},
- {uniname2ctype_offset(str2549), 159},
- {-1},
- {uniname2ctype_offset(str2551), 89},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2564), 372},
- {-1}, {-1},
- {uniname2ctype_offset(str2567), 318},
- {-1}, {-1},
- {uniname2ctype_offset(str2570), 491},
- {-1},
- {uniname2ctype_offset(str2572), 473},
- {-1},
- {uniname2ctype_offset(str2574), 246},
- {uniname2ctype_offset(str2575), 474},
- {uniname2ctype_offset(str2576), 275},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2582), 391},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2588), 154},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2602), 210},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2606), 374},
- {-1},
- {uniname2ctype_offset(str2608), 458},
- {uniname2ctype_offset(str2609), 55},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2625), 262},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2648), 254},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2652), 383},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2656), 368},
- {uniname2ctype_offset(str2657), 112},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2665), 87},
- {uniname2ctype_offset(str2666), 50},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2670), 632},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2674), 87},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2688), 139},
- {uniname2ctype_offset(str2689), 641},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2694), 48},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
- {uniname2ctype_offset(str2705), 481},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str2726), 226},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2750), 557},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
- {uniname2ctype_offset(str2761), 18},
- {uniname2ctype_offset(str2762), 265},
- {-1}, {-1},
- {uniname2ctype_offset(str2765), 133},
- {uniname2ctype_offset(str2766), 54},
- {-1}, {-1},
- {uniname2ctype_offset(str2769), 483},
- {-1}, {-1},
- {uniname2ctype_offset(str2772), 199},
- {-1}, {-1},
- {uniname2ctype_offset(str2775), 38},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
- {uniname2ctype_offset(str2786), 4},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2793), 34},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2801), 29},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2808), 512},
- {-1},
- {uniname2ctype_offset(str2810), 226},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2816), 310},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2821), 393},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2830), 614},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2834), 364},
- {-1},
- {uniname2ctype_offset(str2836), 78},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
- {uniname2ctype_offset(str2847), 248},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2852), 305},
- {-1}, {-1},
- {uniname2ctype_offset(str2855), 190},
- {uniname2ctype_offset(str2856), 66},
- {-1}, {-1},
- {uniname2ctype_offset(str2859), 427},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2867), 309},
- {uniname2ctype_offset(str2868), 248},
- {-1}, {-1},
- {uniname2ctype_offset(str2871), 254},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2879), 204},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2886), 631},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2902), 477},
- {-1},
- {uniname2ctype_offset(str2904), 464},
- {uniname2ctype_offset(str2905), 273},
- {-1},
- {uniname2ctype_offset(str2907), 273},
- {-1},
- {uniname2ctype_offset(str2909), 577},
- {-1},
- {uniname2ctype_offset(str2911), 450},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-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(str2941), 363},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str2953), 198},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
- {uniname2ctype_offset(str2964), 520},
- {-1},
- {uniname2ctype_offset(str2966), 238},
- {uniname2ctype_offset(str2967), 43},
- {-1}, {-1},
- {uniname2ctype_offset(str2970), 88},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2980), 195},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2984), 574},
- {-1},
- {uniname2ctype_offset(str2986), 118},
- {uniname2ctype_offset(str2987), 54},
- {uniname2ctype_offset(str2988), 471},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str2997), 603},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3001), 180},
- {uniname2ctype_offset(str3002), 64},
- {-1}, {-1},
- {uniname2ctype_offset(str3005), 475},
- {uniname2ctype_offset(str3006), 583},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3015), 83},
- {-1}, {-1},
- {uniname2ctype_offset(str3018), 94},
- {uniname2ctype_offset(str3019), 165},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3026), 83},
- {uniname2ctype_offset(str3027), 503},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3035), 232},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3042), 211},
- {-1}, {-1},
- {uniname2ctype_offset(str3045), 615},
- {-1}, {-1},
- {uniname2ctype_offset(str3048), 119},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3052), 89},
- {uniname2ctype_offset(str3053), 229},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3058), 185},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3067), 185},
- {uniname2ctype_offset(str3068), 99},
- {-1}, {-1},
- {uniname2ctype_offset(str3071), 198},
- {uniname2ctype_offset(str3072), 133},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3082), 130},
- {-1},
- {uniname2ctype_offset(str3084), 237},
- {-1},
- {uniname2ctype_offset(str3086), 84},
- {uniname2ctype_offset(str3087), 342},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3091), 261},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3099), 478},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3104), 84},
- {-1},
- {uniname2ctype_offset(str3106), 562},
- {uniname2ctype_offset(str3107), 313},
- {-1},
- {uniname2ctype_offset(str3109), 315},
- {uniname2ctype_offset(str3110), 152},
- {uniname2ctype_offset(str3111), 191},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3118), 90},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3123), 107},
- {-1},
- {uniname2ctype_offset(str3125), 191},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3135), 452},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3142), 585},
- {-1}, {-1},
- {uniname2ctype_offset(str3145), 183},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3155), 182},
- {-1},
- {uniname2ctype_offset(str3157), 231},
- {uniname2ctype_offset(str3158), 328},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3176), 396},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3180), 331},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3193), 433},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3209), 62},
- {-1}, {-1},
- {uniname2ctype_offset(str3212), 211},
- {-1}, {-1},
- {uniname2ctype_offset(str3215), 180},
- {-1}, {-1},
- {uniname2ctype_offset(str3218), 125},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3237), 390},
- {-1},
- {uniname2ctype_offset(str3239), 308},
- {uniname2ctype_offset(str3240), 304},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3248), 213},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3254), 252},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
- {uniname2ctype_offset(str3265), 610},
- {-1},
- {uniname2ctype_offset(str3267), 28},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3275), 146},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3284), 618},
- {-1}, {-1},
- {uniname2ctype_offset(str3287), 223},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3297), 311},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3303), 307},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3313), 255},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3320), 223},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3328), 63},
- {uniname2ctype_offset(str3329), 625},
- {-1},
- {uniname2ctype_offset(str3331), 222},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3338), 264},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3348), 407},
- {-1},
- {uniname2ctype_offset(str3350), 501},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3355), 47},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3360), 337},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
- {uniname2ctype_offset(str3371), 126},
- {uniname2ctype_offset(str3372), 16},
- {uniname2ctype_offset(str3373), 253},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3377), 147},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3391), 238},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3396), 613},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3405), 469},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
- {uniname2ctype_offset(str3416), 51},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str3428), 253},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3433), 205},
- {-1}, {-1},
- {uniname2ctype_offset(str3436), 213},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3455), 225},
- {-1}, {-1},
- {uniname2ctype_offset(str3458), 10},
- {-1},
- {uniname2ctype_offset(str3460), 627},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3483), 245},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3502), 49},
- {-1},
- {uniname2ctype_offset(str3504), 80},
- {uniname2ctype_offset(str3505), 479},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3511), 411},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str3532), 578},
- {uniname2ctype_offset(str3533), 57},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-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},
- {uniname2ctype_offset(str3580), 179},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3590), 103},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3613), 41},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3618), 99},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str3648), 465},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
- {uniname2ctype_offset(str3659), 178},
- {-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},
- {uniname2ctype_offset(str3686), 204},
- {-1}, {-1},
- {uniname2ctype_offset(str3689), 246},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3698), 504},
- {uniname2ctype_offset(str3699), 552},
- {-1},
- {uniname2ctype_offset(str3701), 96},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3705), 320},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3710), 201},
- {-1}, {-1},
- {uniname2ctype_offset(str3713), 96},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3721), 438},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3744), 190},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3754), 71},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str3766), 467},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3799), 214},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3807), 260},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3842), 182},
- {-1}, {-1},
- {uniname2ctype_offset(str3845), 259},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3850), 245},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3854), 65},
- {-1}, {-1},
- {uniname2ctype_offset(str3857), 616},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
- {uniname2ctype_offset(str3868), 261},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3881), 228},
- {-1}, {-1},
- {uniname2ctype_offset(str3884), 306},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3891), 30},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-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), 420},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3942), 100},
- {-1},
- {uniname2ctype_offset(str3944), 436},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3949), 276},
- {-1}, {-1}, {-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), 604},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str3998), 430},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4007), 454},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-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(str4106), 45},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4116), 132},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
- {uniname2ctype_offset(str4127), 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}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4169), 220},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4231), 153},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4308), 401},
- {uniname2ctype_offset(str4309), 162},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str4348), 571},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4361), 572},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4459), 119},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4487), 147},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4604), 116},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4626), 116},
- {uniname2ctype_offset(str4627), 255},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
- {uniname2ctype_offset(str4674), 642},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4683), 466},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str4695), 80},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str4734), 179},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1},
- {uniname2ctype_offset(str4755), 312},
- {uniname2ctype_offset(str4756), 314},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4772), 409},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
- {uniname2ctype_offset(str4783), 316},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4810), 90},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4898), 75},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-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(str4982), 232},
- {-1}, {-1}, {-1},
- {uniname2ctype_offset(str4986), 428},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str5018), 46},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1},
- {uniname2ctype_offset(str5038), 242},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str5134), 628},
-#endif /* USE_UNICODE_PROPERTIES */
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
-#ifndef USE_UNICODE_PROPERTIES
- {uniname2ctype_offset(str6), 12},
- {uniname2ctype_offset(str7), 7},
- {uniname2ctype_offset(str8), 15},
- {uniname2ctype_offset(str9), 1},
- {uniname2ctype_offset(str10), 13},
- {uniname2ctype_offset(str11), 11},
- {uniname2ctype_offset(str12), 10},
- {uniname2ctype_offset(str13), 14},
- {uniname2ctype_offset(str14), 3},
- {uniname2ctype_offset(str15), 9},
- {uniname2ctype_offset(str16), 8},
- {uniname2ctype_offset(str17), 6},
- {uniname2ctype_offset(str18), 5},
- {uniname2ctype_offset(str19), 4},
- {uniname2ctype_offset(str20), 2}
-#else /* USE_UNICODE_PROPERTIES */
- {uniname2ctype_offset(str5141), 155},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-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},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-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},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
- {uniname2ctype_offset(str6098), 643}
-#endif /* USE_UNICODE_PROPERTIES */
- };
-
- if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
- {
- register unsigned int key = uniname2ctype_hash (str, len);
-
- if (key <= MAX_HASH_VALUE)
- {
- register int o = wordlist[key].name;
- if (o >= 0)
- {
- register const char *s = o + uniname2ctype_pool;
-
- if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0')
- return &wordlist[key];
- }
- }
- }
- return 0;
-}
-
-static int
-uniname2ctype(const UChar *name, unsigned int len)
-{
- const struct uniname2ctype_struct *p = uniname2ctype_p((const char *)name, len);
- if (p) return p->ctype;
- return -1;
-}
-#if defined ONIG_UNICODE_VERSION_STRING && !( \
- ONIG_UNICODE_VERSION_MAJOR == 15 && \
- ONIG_UNICODE_VERSION_MINOR == 0 && \
- ONIG_UNICODE_VERSION_TEENY == 0 && \
- 1)
-# error ONIG_UNICODE_VERSION_STRING mismatch
-#endif
-#define ONIG_UNICODE_VERSION_STRING "15.0.0"
-#define ONIG_UNICODE_VERSION_MAJOR 15
-#define ONIG_UNICODE_VERSION_MINOR 0
-#define ONIG_UNICODE_VERSION_TEENY 0
-#if defined ONIG_UNICODE_EMOJI_VERSION_STRING && !( \
- ONIG_UNICODE_EMOJI_VERSION_MAJOR == 15 && \
- ONIG_UNICODE_EMOJI_VERSION_MINOR == 0 && \
- 1)
-# error ONIG_UNICODE_EMOJI_VERSION_STRING mismatch
-#endif
-#define ONIG_UNICODE_EMOJI_VERSION_STRING "15.0"
-#define ONIG_UNICODE_EMOJI_VERSION_MAJOR 15
-#define ONIG_UNICODE_EMOJI_VERSION_MINOR 0
diff --git a/enc/unicode/17.0.0/casefold.h b/enc/unicode/17.0.0/casefold.h
new file mode 100644
index 0000000000..82439f35fb
--- /dev/null
+++ b/enc/unicode/17.0.0/casefold.h
@@ -0,0 +1,8013 @@
+/* DO NOT EDIT THIS FILE. */
+/* Generated by enc-case-folding.rb */
+
+#if defined ONIG_UNICODE_VERSION_STRING && !( \
+ ONIG_UNICODE_VERSION_MAJOR == 17 && \
+ ONIG_UNICODE_VERSION_MINOR == 0 && \
+ ONIG_UNICODE_VERSION_TEENY == 0 && \
+ 1)
+# error ONIG_UNICODE_VERSION_STRING mismatch
+#endif
+#define ONIG_UNICODE_VERSION_STRING "17.0.0"
+#define ONIG_UNICODE_VERSION_MAJOR 17
+#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 (*)[1583])(CaseFold_11_Table+0))
+ {0x0041, {1|F|D, {0x0061}}},
+ {0x0042, {1|F|D, {0x0062}}},
+ {0x0043, {1|F|D, {0x0063}}},
+ {0x0044, {1|F|D, {0x0064}}},
+ {0x0045, {1|F|D, {0x0065}}},
+ {0x0046, {1|F|D, {0x0066}}},
+ {0x0047, {1|F|D, {0x0067}}},
+ {0x0048, {1|F|D, {0x0068}}},
+ {0x004a, {1|F|D, {0x006a}}},
+ {0x004b, {1|F|D, {0x006b}}},
+ {0x004c, {1|F|D, {0x006c}}},
+ {0x004d, {1|F|D, {0x006d}}},
+ {0x004e, {1|F|D, {0x006e}}},
+ {0x004f, {1|F|D, {0x006f}}},
+ {0x0050, {1|F|D, {0x0070}}},
+ {0x0051, {1|F|D, {0x0071}}},
+ {0x0052, {1|F|D, {0x0072}}},
+ {0x0053, {1|F|D, {0x0073}}},
+ {0x0054, {1|F|D, {0x0074}}},
+ {0x0055, {1|F|D, {0x0075}}},
+ {0x0056, {1|F|D, {0x0076}}},
+ {0x0057, {1|F|D, {0x0077}}},
+ {0x0058, {1|F|D, {0x0078}}},
+ {0x0059, {1|F|D, {0x0079}}},
+ {0x005a, {1|F|D, {0x007a}}},
+ {0x00b5, {1|F|SU|I(0), {0x03bc}}},
+ {0x00c0, {1|F|D, {0x00e0}}},
+ {0x00c1, {1|F|D, {0x00e1}}},
+ {0x00c2, {1|F|D, {0x00e2}}},
+ {0x00c3, {1|F|D, {0x00e3}}},
+ {0x00c4, {1|F|D, {0x00e4}}},
+ {0x00c5, {1|F|D, {0x00e5}}},
+ {0x00c6, {1|F|D, {0x00e6}}},
+ {0x00c7, {1|F|D, {0x00e7}}},
+ {0x00c8, {1|F|D, {0x00e8}}},
+ {0x00c9, {1|F|D, {0x00e9}}},
+ {0x00ca, {1|F|D, {0x00ea}}},
+ {0x00cb, {1|F|D, {0x00eb}}},
+ {0x00cc, {1|F|D, {0x00ec}}},
+ {0x00cd, {1|F|D, {0x00ed}}},
+ {0x00ce, {1|F|D, {0x00ee}}},
+ {0x00cf, {1|F|D, {0x00ef}}},
+ {0x00d0, {1|F|D, {0x00f0}}},
+ {0x00d1, {1|F|D, {0x00f1}}},
+ {0x00d2, {1|F|D, {0x00f2}}},
+ {0x00d3, {1|F|D, {0x00f3}}},
+ {0x00d4, {1|F|D, {0x00f4}}},
+ {0x00d5, {1|F|D, {0x00f5}}},
+ {0x00d6, {1|F|D, {0x00f6}}},
+ {0x00d8, {1|F|D, {0x00f8}}},
+ {0x00d9, {1|F|D, {0x00f9}}},
+ {0x00da, {1|F|D, {0x00fa}}},
+ {0x00db, {1|F|D, {0x00fb}}},
+ {0x00dc, {1|F|D, {0x00fc}}},
+ {0x00dd, {1|F|D, {0x00fd}}},
+ {0x00de, {1|F|D, {0x00fe}}},
+ {0x00df, {2|F|ST|SU|I(1), {0x0073, 0x0073}}},
+ {0x0100, {1|F|D, {0x0101}}},
+ {0x0102, {1|F|D, {0x0103}}},
+ {0x0104, {1|F|D, {0x0105}}},
+ {0x0106, {1|F|D, {0x0107}}},
+ {0x0108, {1|F|D, {0x0109}}},
+ {0x010a, {1|F|D, {0x010b}}},
+ {0x010c, {1|F|D, {0x010d}}},
+ {0x010e, {1|F|D, {0x010f}}},
+ {0x0110, {1|F|D, {0x0111}}},
+ {0x0112, {1|F|D, {0x0113}}},
+ {0x0114, {1|F|D, {0x0115}}},
+ {0x0116, {1|F|D, {0x0117}}},
+ {0x0118, {1|F|D, {0x0119}}},
+ {0x011a, {1|F|D, {0x011b}}},
+ {0x011c, {1|F|D, {0x011d}}},
+ {0x011e, {1|F|D, {0x011f}}},
+ {0x0120, {1|F|D, {0x0121}}},
+ {0x0122, {1|F|D, {0x0123}}},
+ {0x0124, {1|F|D, {0x0125}}},
+ {0x0126, {1|F|D, {0x0127}}},
+ {0x0128, {1|F|D, {0x0129}}},
+ {0x012a, {1|F|D, {0x012b}}},
+ {0x012c, {1|F|D, {0x012d}}},
+ {0x012e, {1|F|D, {0x012f}}},
+ {0x0132, {1|F|D, {0x0133}}},
+ {0x0134, {1|F|D, {0x0135}}},
+ {0x0136, {1|F|D, {0x0137}}},
+ {0x0139, {1|F|D, {0x013a}}},
+ {0x013b, {1|F|D, {0x013c}}},
+ {0x013d, {1|F|D, {0x013e}}},
+ {0x013f, {1|F|D, {0x0140}}},
+ {0x0141, {1|F|D, {0x0142}}},
+ {0x0143, {1|F|D, {0x0144}}},
+ {0x0145, {1|F|D, {0x0146}}},
+ {0x0147, {1|F|D, {0x0148}}},
+ {0x0149, {2|F|SU|I(5), {0x02bc, 0x006e}}},
+ {0x014a, {1|F|D, {0x014b}}},
+ {0x014c, {1|F|D, {0x014d}}},
+ {0x014e, {1|F|D, {0x014f}}},
+ {0x0150, {1|F|D, {0x0151}}},
+ {0x0152, {1|F|D, {0x0153}}},
+ {0x0154, {1|F|D, {0x0155}}},
+ {0x0156, {1|F|D, {0x0157}}},
+ {0x0158, {1|F|D, {0x0159}}},
+ {0x015a, {1|F|D, {0x015b}}},
+ {0x015c, {1|F|D, {0x015d}}},
+ {0x015e, {1|F|D, {0x015f}}},
+ {0x0160, {1|F|D, {0x0161}}},
+ {0x0162, {1|F|D, {0x0163}}},
+ {0x0164, {1|F|D, {0x0165}}},
+ {0x0166, {1|F|D, {0x0167}}},
+ {0x0168, {1|F|D, {0x0169}}},
+ {0x016a, {1|F|D, {0x016b}}},
+ {0x016c, {1|F|D, {0x016d}}},
+ {0x016e, {1|F|D, {0x016f}}},
+ {0x0170, {1|F|D, {0x0171}}},
+ {0x0172, {1|F|D, {0x0173}}},
+ {0x0174, {1|F|D, {0x0175}}},
+ {0x0176, {1|F|D, {0x0177}}},
+ {0x0178, {1|F|D, {0x00ff}}},
+ {0x0179, {1|F|D, {0x017a}}},
+ {0x017b, {1|F|D, {0x017c}}},
+ {0x017d, {1|F|D, {0x017e}}},
+ {0x017f, {1|F|SU|I(7), {0x0073}}},
+ {0x0181, {1|F|D, {0x0253}}},
+ {0x0182, {1|F|D, {0x0183}}},
+ {0x0184, {1|F|D, {0x0185}}},
+ {0x0186, {1|F|D, {0x0254}}},
+ {0x0187, {1|F|D, {0x0188}}},
+ {0x0189, {1|F|D, {0x0256}}},
+ {0x018a, {1|F|D, {0x0257}}},
+ {0x018b, {1|F|D, {0x018c}}},
+ {0x018e, {1|F|D, {0x01dd}}},
+ {0x018f, {1|F|D, {0x0259}}},
+ {0x0190, {1|F|D, {0x025b}}},
+ {0x0191, {1|F|D, {0x0192}}},
+ {0x0193, {1|F|D, {0x0260}}},
+ {0x0194, {1|F|D, {0x0263}}},
+ {0x0196, {1|F|D, {0x0269}}},
+ {0x0197, {1|F|D, {0x0268}}},
+ {0x0198, {1|F|D, {0x0199}}},
+ {0x019c, {1|F|D, {0x026f}}},
+ {0x019d, {1|F|D, {0x0272}}},
+ {0x019f, {1|F|D, {0x0275}}},
+ {0x01a0, {1|F|D, {0x01a1}}},
+ {0x01a2, {1|F|D, {0x01a3}}},
+ {0x01a4, {1|F|D, {0x01a5}}},
+ {0x01a6, {1|F|D, {0x0280}}},
+ {0x01a7, {1|F|D, {0x01a8}}},
+ {0x01a9, {1|F|D, {0x0283}}},
+ {0x01ac, {1|F|D, {0x01ad}}},
+ {0x01ae, {1|F|D, {0x0288}}},
+ {0x01af, {1|F|D, {0x01b0}}},
+ {0x01b1, {1|F|D, {0x028a}}},
+ {0x01b2, {1|F|D, {0x028b}}},
+ {0x01b3, {1|F|D, {0x01b4}}},
+ {0x01b5, {1|F|D, {0x01b6}}},
+ {0x01b7, {1|F|D, {0x0292}}},
+ {0x01b8, {1|F|D, {0x01b9}}},
+ {0x01bc, {1|F|D, {0x01bd}}},
+ {0x01c4, {1|F|D|ST|I(8), {0x01c6}}},
+ {0x01c5, {1|F|D|IT|SU|I(9), {0x01c6}}},
+ {0x01c7, {1|F|D|ST|I(12), {0x01c9}}},
+ {0x01c8, {1|F|D|IT|SU|I(13), {0x01c9}}},
+ {0x01ca, {1|F|D|ST|I(16), {0x01cc}}},
+ {0x01cb, {1|F|D|IT|SU|I(17), {0x01cc}}},
+ {0x01cd, {1|F|D, {0x01ce}}},
+ {0x01cf, {1|F|D, {0x01d0}}},
+ {0x01d1, {1|F|D, {0x01d2}}},
+ {0x01d3, {1|F|D, {0x01d4}}},
+ {0x01d5, {1|F|D, {0x01d6}}},
+ {0x01d7, {1|F|D, {0x01d8}}},
+ {0x01d9, {1|F|D, {0x01da}}},
+ {0x01db, {1|F|D, {0x01dc}}},
+ {0x01de, {1|F|D, {0x01df}}},
+ {0x01e0, {1|F|D, {0x01e1}}},
+ {0x01e2, {1|F|D, {0x01e3}}},
+ {0x01e4, {1|F|D, {0x01e5}}},
+ {0x01e6, {1|F|D, {0x01e7}}},
+ {0x01e8, {1|F|D, {0x01e9}}},
+ {0x01ea, {1|F|D, {0x01eb}}},
+ {0x01ec, {1|F|D, {0x01ed}}},
+ {0x01ee, {1|F|D, {0x01ef}}},
+ {0x01f0, {2|F|SU|I(20), {0x006a, 0x030c}}},
+ {0x01f1, {1|F|D|ST|I(22), {0x01f3}}},
+ {0x01f2, {1|F|D|IT|SU|I(23), {0x01f3}}},
+ {0x01f4, {1|F|D, {0x01f5}}},
+ {0x01f6, {1|F|D, {0x0195}}},
+ {0x01f7, {1|F|D, {0x01bf}}},
+ {0x01f8, {1|F|D, {0x01f9}}},
+ {0x01fa, {1|F|D, {0x01fb}}},
+ {0x01fc, {1|F|D, {0x01fd}}},
+ {0x01fe, {1|F|D, {0x01ff}}},
+ {0x0200, {1|F|D, {0x0201}}},
+ {0x0202, {1|F|D, {0x0203}}},
+ {0x0204, {1|F|D, {0x0205}}},
+ {0x0206, {1|F|D, {0x0207}}},
+ {0x0208, {1|F|D, {0x0209}}},
+ {0x020a, {1|F|D, {0x020b}}},
+ {0x020c, {1|F|D, {0x020d}}},
+ {0x020e, {1|F|D, {0x020f}}},
+ {0x0210, {1|F|D, {0x0211}}},
+ {0x0212, {1|F|D, {0x0213}}},
+ {0x0214, {1|F|D, {0x0215}}},
+ {0x0216, {1|F|D, {0x0217}}},
+ {0x0218, {1|F|D, {0x0219}}},
+ {0x021a, {1|F|D, {0x021b}}},
+ {0x021c, {1|F|D, {0x021d}}},
+ {0x021e, {1|F|D, {0x021f}}},
+ {0x0220, {1|F|D, {0x019e}}},
+ {0x0222, {1|F|D, {0x0223}}},
+ {0x0224, {1|F|D, {0x0225}}},
+ {0x0226, {1|F|D, {0x0227}}},
+ {0x0228, {1|F|D, {0x0229}}},
+ {0x022a, {1|F|D, {0x022b}}},
+ {0x022c, {1|F|D, {0x022d}}},
+ {0x022e, {1|F|D, {0x022f}}},
+ {0x0230, {1|F|D, {0x0231}}},
+ {0x0232, {1|F|D, {0x0233}}},
+ {0x023a, {1|F|D, {0x2c65}}},
+ {0x023b, {1|F|D, {0x023c}}},
+ {0x023d, {1|F|D, {0x019a}}},
+ {0x023e, {1|F|D, {0x2c66}}},
+ {0x0241, {1|F|D, {0x0242}}},
+ {0x0243, {1|F|D, {0x0180}}},
+ {0x0244, {1|F|D, {0x0289}}},
+ {0x0245, {1|F|D, {0x028c}}},
+ {0x0246, {1|F|D, {0x0247}}},
+ {0x0248, {1|F|D, {0x0249}}},
+ {0x024a, {1|F|D, {0x024b}}},
+ {0x024c, {1|F|D, {0x024d}}},
+ {0x024e, {1|F|D, {0x024f}}},
+ {0x0345, {1|F|SU|I(26), {0x03b9}}},
+ {0x0370, {1|F|D, {0x0371}}},
+ {0x0372, {1|F|D, {0x0373}}},
+ {0x0376, {1|F|D, {0x0377}}},
+ {0x037f, {1|F|D, {0x03f3}}},
+ {0x0386, {1|F|D, {0x03ac}}},
+ {0x0388, {1|F|D, {0x03ad}}},
+ {0x0389, {1|F|D, {0x03ae}}},
+ {0x038a, {1|F|D, {0x03af}}},
+ {0x038c, {1|F|D, {0x03cc}}},
+ {0x038e, {1|F|D, {0x03cd}}},
+ {0x038f, {1|F|D, {0x03ce}}},
+ {0x0390, {3|F|SU|I(27), {0x03b9, 0x0308, 0x0301}}},
+ {0x0391, {1|F|D, {0x03b1}}},
+ {0x0392, {1|F|D, {0x03b2}}},
+ {0x0393, {1|F|D, {0x03b3}}},
+ {0x0394, {1|F|D, {0x03b4}}},
+ {0x0395, {1|F|D, {0x03b5}}},
+ {0x0396, {1|F|D, {0x03b6}}},
+ {0x0397, {1|F|D, {0x03b7}}},
+ {0x0398, {1|F|D, {0x03b8}}},
+ {0x0399, {1|F|D, {0x03b9}}},
+ {0x039a, {1|F|D, {0x03ba}}},
+ {0x039b, {1|F|D, {0x03bb}}},
+ {0x039c, {1|F|D, {0x03bc}}},
+ {0x039d, {1|F|D, {0x03bd}}},
+ {0x039e, {1|F|D, {0x03be}}},
+ {0x039f, {1|F|D, {0x03bf}}},
+ {0x03a0, {1|F|D, {0x03c0}}},
+ {0x03a1, {1|F|D, {0x03c1}}},
+ {0x03a3, {1|F|D, {0x03c3}}},
+ {0x03a4, {1|F|D, {0x03c4}}},
+ {0x03a5, {1|F|D, {0x03c5}}},
+ {0x03a6, {1|F|D, {0x03c6}}},
+ {0x03a7, {1|F|D, {0x03c7}}},
+ {0x03a8, {1|F|D, {0x03c8}}},
+ {0x03a9, {1|F|D, {0x03c9}}},
+ {0x03aa, {1|F|D, {0x03ca}}},
+ {0x03ab, {1|F|D, {0x03cb}}},
+ {0x03b0, {3|F|SU|I(30), {0x03c5, 0x0308, 0x0301}}},
+ {0x03c2, {1|F|SU|I(33), {0x03c3}}},
+ {0x03cf, {1|F|D, {0x03d7}}},
+ {0x03d0, {1|F|SU|I(34), {0x03b2}}},
+ {0x03d1, {1|F|SU|I(35), {0x03b8}}},
+ {0x03d5, {1|F|SU|I(36), {0x03c6}}},
+ {0x03d6, {1|F|SU|I(37), {0x03c0}}},
+ {0x03d8, {1|F|D, {0x03d9}}},
+ {0x03da, {1|F|D, {0x03db}}},
+ {0x03dc, {1|F|D, {0x03dd}}},
+ {0x03de, {1|F|D, {0x03df}}},
+ {0x03e0, {1|F|D, {0x03e1}}},
+ {0x03e2, {1|F|D, {0x03e3}}},
+ {0x03e4, {1|F|D, {0x03e5}}},
+ {0x03e6, {1|F|D, {0x03e7}}},
+ {0x03e8, {1|F|D, {0x03e9}}},
+ {0x03ea, {1|F|D, {0x03eb}}},
+ {0x03ec, {1|F|D, {0x03ed}}},
+ {0x03ee, {1|F|D, {0x03ef}}},
+ {0x03f0, {1|F|SU|I(38), {0x03ba}}},
+ {0x03f1, {1|F|SU|I(39), {0x03c1}}},
+ {0x03f4, {1|F|D, {0x03b8}}},
+ {0x03f5, {1|F|SU|I(40), {0x03b5}}},
+ {0x03f7, {1|F|D, {0x03f8}}},
+ {0x03f9, {1|F|D, {0x03f2}}},
+ {0x03fa, {1|F|D, {0x03fb}}},
+ {0x03fd, {1|F|D, {0x037b}}},
+ {0x03fe, {1|F|D, {0x037c}}},
+ {0x03ff, {1|F|D, {0x037d}}},
+ {0x0400, {1|F|D, {0x0450}}},
+ {0x0401, {1|F|D, {0x0451}}},
+ {0x0402, {1|F|D, {0x0452}}},
+ {0x0403, {1|F|D, {0x0453}}},
+ {0x0404, {1|F|D, {0x0454}}},
+ {0x0405, {1|F|D, {0x0455}}},
+ {0x0406, {1|F|D, {0x0456}}},
+ {0x0407, {1|F|D, {0x0457}}},
+ {0x0408, {1|F|D, {0x0458}}},
+ {0x0409, {1|F|D, {0x0459}}},
+ {0x040a, {1|F|D, {0x045a}}},
+ {0x040b, {1|F|D, {0x045b}}},
+ {0x040c, {1|F|D, {0x045c}}},
+ {0x040d, {1|F|D, {0x045d}}},
+ {0x040e, {1|F|D, {0x045e}}},
+ {0x040f, {1|F|D, {0x045f}}},
+ {0x0410, {1|F|D, {0x0430}}},
+ {0x0411, {1|F|D, {0x0431}}},
+ {0x0412, {1|F|D, {0x0432}}},
+ {0x0413, {1|F|D, {0x0433}}},
+ {0x0414, {1|F|D, {0x0434}}},
+ {0x0415, {1|F|D, {0x0435}}},
+ {0x0416, {1|F|D, {0x0436}}},
+ {0x0417, {1|F|D, {0x0437}}},
+ {0x0418, {1|F|D, {0x0438}}},
+ {0x0419, {1|F|D, {0x0439}}},
+ {0x041a, {1|F|D, {0x043a}}},
+ {0x041b, {1|F|D, {0x043b}}},
+ {0x041c, {1|F|D, {0x043c}}},
+ {0x041d, {1|F|D, {0x043d}}},
+ {0x041e, {1|F|D, {0x043e}}},
+ {0x041f, {1|F|D, {0x043f}}},
+ {0x0420, {1|F|D, {0x0440}}},
+ {0x0421, {1|F|D, {0x0441}}},
+ {0x0422, {1|F|D, {0x0442}}},
+ {0x0423, {1|F|D, {0x0443}}},
+ {0x0424, {1|F|D, {0x0444}}},
+ {0x0425, {1|F|D, {0x0445}}},
+ {0x0426, {1|F|D, {0x0446}}},
+ {0x0427, {1|F|D, {0x0447}}},
+ {0x0428, {1|F|D, {0x0448}}},
+ {0x0429, {1|F|D, {0x0449}}},
+ {0x042a, {1|F|D, {0x044a}}},
+ {0x042b, {1|F|D, {0x044b}}},
+ {0x042c, {1|F|D, {0x044c}}},
+ {0x042d, {1|F|D, {0x044d}}},
+ {0x042e, {1|F|D, {0x044e}}},
+ {0x042f, {1|F|D, {0x044f}}},
+ {0x0460, {1|F|D, {0x0461}}},
+ {0x0462, {1|F|D, {0x0463}}},
+ {0x0464, {1|F|D, {0x0465}}},
+ {0x0466, {1|F|D, {0x0467}}},
+ {0x0468, {1|F|D, {0x0469}}},
+ {0x046a, {1|F|D, {0x046b}}},
+ {0x046c, {1|F|D, {0x046d}}},
+ {0x046e, {1|F|D, {0x046f}}},
+ {0x0470, {1|F|D, {0x0471}}},
+ {0x0472, {1|F|D, {0x0473}}},
+ {0x0474, {1|F|D, {0x0475}}},
+ {0x0476, {1|F|D, {0x0477}}},
+ {0x0478, {1|F|D, {0x0479}}},
+ {0x047a, {1|F|D, {0x047b}}},
+ {0x047c, {1|F|D, {0x047d}}},
+ {0x047e, {1|F|D, {0x047f}}},
+ {0x0480, {1|F|D, {0x0481}}},
+ {0x048a, {1|F|D, {0x048b}}},
+ {0x048c, {1|F|D, {0x048d}}},
+ {0x048e, {1|F|D, {0x048f}}},
+ {0x0490, {1|F|D, {0x0491}}},
+ {0x0492, {1|F|D, {0x0493}}},
+ {0x0494, {1|F|D, {0x0495}}},
+ {0x0496, {1|F|D, {0x0497}}},
+ {0x0498, {1|F|D, {0x0499}}},
+ {0x049a, {1|F|D, {0x049b}}},
+ {0x049c, {1|F|D, {0x049d}}},
+ {0x049e, {1|F|D, {0x049f}}},
+ {0x04a0, {1|F|D, {0x04a1}}},
+ {0x04a2, {1|F|D, {0x04a3}}},
+ {0x04a4, {1|F|D, {0x04a5}}},
+ {0x04a6, {1|F|D, {0x04a7}}},
+ {0x04a8, {1|F|D, {0x04a9}}},
+ {0x04aa, {1|F|D, {0x04ab}}},
+ {0x04ac, {1|F|D, {0x04ad}}},
+ {0x04ae, {1|F|D, {0x04af}}},
+ {0x04b0, {1|F|D, {0x04b1}}},
+ {0x04b2, {1|F|D, {0x04b3}}},
+ {0x04b4, {1|F|D, {0x04b5}}},
+ {0x04b6, {1|F|D, {0x04b7}}},
+ {0x04b8, {1|F|D, {0x04b9}}},
+ {0x04ba, {1|F|D, {0x04bb}}},
+ {0x04bc, {1|F|D, {0x04bd}}},
+ {0x04be, {1|F|D, {0x04bf}}},
+ {0x04c0, {1|F|D, {0x04cf}}},
+ {0x04c1, {1|F|D, {0x04c2}}},
+ {0x04c3, {1|F|D, {0x04c4}}},
+ {0x04c5, {1|F|D, {0x04c6}}},
+ {0x04c7, {1|F|D, {0x04c8}}},
+ {0x04c9, {1|F|D, {0x04ca}}},
+ {0x04cb, {1|F|D, {0x04cc}}},
+ {0x04cd, {1|F|D, {0x04ce}}},
+ {0x04d0, {1|F|D, {0x04d1}}},
+ {0x04d2, {1|F|D, {0x04d3}}},
+ {0x04d4, {1|F|D, {0x04d5}}},
+ {0x04d6, {1|F|D, {0x04d7}}},
+ {0x04d8, {1|F|D, {0x04d9}}},
+ {0x04da, {1|F|D, {0x04db}}},
+ {0x04dc, {1|F|D, {0x04dd}}},
+ {0x04de, {1|F|D, {0x04df}}},
+ {0x04e0, {1|F|D, {0x04e1}}},
+ {0x04e2, {1|F|D, {0x04e3}}},
+ {0x04e4, {1|F|D, {0x04e5}}},
+ {0x04e6, {1|F|D, {0x04e7}}},
+ {0x04e8, {1|F|D, {0x04e9}}},
+ {0x04ea, {1|F|D, {0x04eb}}},
+ {0x04ec, {1|F|D, {0x04ed}}},
+ {0x04ee, {1|F|D, {0x04ef}}},
+ {0x04f0, {1|F|D, {0x04f1}}},
+ {0x04f2, {1|F|D, {0x04f3}}},
+ {0x04f4, {1|F|D, {0x04f5}}},
+ {0x04f6, {1|F|D, {0x04f7}}},
+ {0x04f8, {1|F|D, {0x04f9}}},
+ {0x04fa, {1|F|D, {0x04fb}}},
+ {0x04fc, {1|F|D, {0x04fd}}},
+ {0x04fe, {1|F|D, {0x04ff}}},
+ {0x0500, {1|F|D, {0x0501}}},
+ {0x0502, {1|F|D, {0x0503}}},
+ {0x0504, {1|F|D, {0x0505}}},
+ {0x0506, {1|F|D, {0x0507}}},
+ {0x0508, {1|F|D, {0x0509}}},
+ {0x050a, {1|F|D, {0x050b}}},
+ {0x050c, {1|F|D, {0x050d}}},
+ {0x050e, {1|F|D, {0x050f}}},
+ {0x0510, {1|F|D, {0x0511}}},
+ {0x0512, {1|F|D, {0x0513}}},
+ {0x0514, {1|F|D, {0x0515}}},
+ {0x0516, {1|F|D, {0x0517}}},
+ {0x0518, {1|F|D, {0x0519}}},
+ {0x051a, {1|F|D, {0x051b}}},
+ {0x051c, {1|F|D, {0x051d}}},
+ {0x051e, {1|F|D, {0x051f}}},
+ {0x0520, {1|F|D, {0x0521}}},
+ {0x0522, {1|F|D, {0x0523}}},
+ {0x0524, {1|F|D, {0x0525}}},
+ {0x0526, {1|F|D, {0x0527}}},
+ {0x0528, {1|F|D, {0x0529}}},
+ {0x052a, {1|F|D, {0x052b}}},
+ {0x052c, {1|F|D, {0x052d}}},
+ {0x052e, {1|F|D, {0x052f}}},
+ {0x0531, {1|F|D, {0x0561}}},
+ {0x0532, {1|F|D, {0x0562}}},
+ {0x0533, {1|F|D, {0x0563}}},
+ {0x0534, {1|F|D, {0x0564}}},
+ {0x0535, {1|F|D, {0x0565}}},
+ {0x0536, {1|F|D, {0x0566}}},
+ {0x0537, {1|F|D, {0x0567}}},
+ {0x0538, {1|F|D, {0x0568}}},
+ {0x0539, {1|F|D, {0x0569}}},
+ {0x053a, {1|F|D, {0x056a}}},
+ {0x053b, {1|F|D, {0x056b}}},
+ {0x053c, {1|F|D, {0x056c}}},
+ {0x053d, {1|F|D, {0x056d}}},
+ {0x053e, {1|F|D, {0x056e}}},
+ {0x053f, {1|F|D, {0x056f}}},
+ {0x0540, {1|F|D, {0x0570}}},
+ {0x0541, {1|F|D, {0x0571}}},
+ {0x0542, {1|F|D, {0x0572}}},
+ {0x0543, {1|F|D, {0x0573}}},
+ {0x0544, {1|F|D, {0x0574}}},
+ {0x0545, {1|F|D, {0x0575}}},
+ {0x0546, {1|F|D, {0x0576}}},
+ {0x0547, {1|F|D, {0x0577}}},
+ {0x0548, {1|F|D, {0x0578}}},
+ {0x0549, {1|F|D, {0x0579}}},
+ {0x054a, {1|F|D, {0x057a}}},
+ {0x054b, {1|F|D, {0x057b}}},
+ {0x054c, {1|F|D, {0x057c}}},
+ {0x054d, {1|F|D, {0x057d}}},
+ {0x054e, {1|F|D, {0x057e}}},
+ {0x054f, {1|F|D, {0x057f}}},
+ {0x0550, {1|F|D, {0x0580}}},
+ {0x0551, {1|F|D, {0x0581}}},
+ {0x0552, {1|F|D, {0x0582}}},
+ {0x0553, {1|F|D, {0x0583}}},
+ {0x0554, {1|F|D, {0x0584}}},
+ {0x0555, {1|F|D, {0x0585}}},
+ {0x0556, {1|F|D, {0x0586}}},
+ {0x0587, {2|F|ST|SU|I(41), {0x0565, 0x0582}}},
+ {0x10a0, {1|F|D, {0x2d00}}},
+ {0x10a1, {1|F|D, {0x2d01}}},
+ {0x10a2, {1|F|D, {0x2d02}}},
+ {0x10a3, {1|F|D, {0x2d03}}},
+ {0x10a4, {1|F|D, {0x2d04}}},
+ {0x10a5, {1|F|D, {0x2d05}}},
+ {0x10a6, {1|F|D, {0x2d06}}},
+ {0x10a7, {1|F|D, {0x2d07}}},
+ {0x10a8, {1|F|D, {0x2d08}}},
+ {0x10a9, {1|F|D, {0x2d09}}},
+ {0x10aa, {1|F|D, {0x2d0a}}},
+ {0x10ab, {1|F|D, {0x2d0b}}},
+ {0x10ac, {1|F|D, {0x2d0c}}},
+ {0x10ad, {1|F|D, {0x2d0d}}},
+ {0x10ae, {1|F|D, {0x2d0e}}},
+ {0x10af, {1|F|D, {0x2d0f}}},
+ {0x10b0, {1|F|D, {0x2d10}}},
+ {0x10b1, {1|F|D, {0x2d11}}},
+ {0x10b2, {1|F|D, {0x2d12}}},
+ {0x10b3, {1|F|D, {0x2d13}}},
+ {0x10b4, {1|F|D, {0x2d14}}},
+ {0x10b5, {1|F|D, {0x2d15}}},
+ {0x10b6, {1|F|D, {0x2d16}}},
+ {0x10b7, {1|F|D, {0x2d17}}},
+ {0x10b8, {1|F|D, {0x2d18}}},
+ {0x10b9, {1|F|D, {0x2d19}}},
+ {0x10ba, {1|F|D, {0x2d1a}}},
+ {0x10bb, {1|F|D, {0x2d1b}}},
+ {0x10bc, {1|F|D, {0x2d1c}}},
+ {0x10bd, {1|F|D, {0x2d1d}}},
+ {0x10be, {1|F|D, {0x2d1e}}},
+ {0x10bf, {1|F|D, {0x2d1f}}},
+ {0x10c0, {1|F|D, {0x2d20}}},
+ {0x10c1, {1|F|D, {0x2d21}}},
+ {0x10c2, {1|F|D, {0x2d22}}},
+ {0x10c3, {1|F|D, {0x2d23}}},
+ {0x10c4, {1|F|D, {0x2d24}}},
+ {0x10c5, {1|F|D, {0x2d25}}},
+ {0x10c7, {1|F|D, {0x2d27}}},
+ {0x10cd, {1|F|D, {0x2d2d}}},
+ {0x13f8, {1|F|U, {0x13f0}}},
+ {0x13f9, {1|F|U, {0x13f1}}},
+ {0x13fa, {1|F|U, {0x13f2}}},
+ {0x13fb, {1|F|U, {0x13f3}}},
+ {0x13fc, {1|F|U, {0x13f4}}},
+ {0x13fd, {1|F|U, {0x13f5}}},
+ {0x1c80, {1|F|SU|I(45), {0x0432}}},
+ {0x1c81, {1|F|SU|I(46), {0x0434}}},
+ {0x1c82, {1|F|SU|I(47), {0x043e}}},
+ {0x1c83, {1|F|SU|I(48), {0x0441}}},
+ {0x1c84, {1|F|SU|I(49), {0x0442}}},
+ {0x1c85, {1|F|SU|I(50), {0x0442}}},
+ {0x1c86, {1|F|SU|I(51), {0x044a}}},
+ {0x1c87, {1|F|SU|I(52), {0x0463}}},
+ {0x1c88, {1|F|SU|I(53), {0xa64b}}},
+ {0x1c89, {1|F|D, {0x1c8a}}},
+ {0x1c90, {1|F|D, {0x10d0}}},
+ {0x1c91, {1|F|D, {0x10d1}}},
+ {0x1c92, {1|F|D, {0x10d2}}},
+ {0x1c93, {1|F|D, {0x10d3}}},
+ {0x1c94, {1|F|D, {0x10d4}}},
+ {0x1c95, {1|F|D, {0x10d5}}},
+ {0x1c96, {1|F|D, {0x10d6}}},
+ {0x1c97, {1|F|D, {0x10d7}}},
+ {0x1c98, {1|F|D, {0x10d8}}},
+ {0x1c99, {1|F|D, {0x10d9}}},
+ {0x1c9a, {1|F|D, {0x10da}}},
+ {0x1c9b, {1|F|D, {0x10db}}},
+ {0x1c9c, {1|F|D, {0x10dc}}},
+ {0x1c9d, {1|F|D, {0x10dd}}},
+ {0x1c9e, {1|F|D, {0x10de}}},
+ {0x1c9f, {1|F|D, {0x10df}}},
+ {0x1ca0, {1|F|D, {0x10e0}}},
+ {0x1ca1, {1|F|D, {0x10e1}}},
+ {0x1ca2, {1|F|D, {0x10e2}}},
+ {0x1ca3, {1|F|D, {0x10e3}}},
+ {0x1ca4, {1|F|D, {0x10e4}}},
+ {0x1ca5, {1|F|D, {0x10e5}}},
+ {0x1ca6, {1|F|D, {0x10e6}}},
+ {0x1ca7, {1|F|D, {0x10e7}}},
+ {0x1ca8, {1|F|D, {0x10e8}}},
+ {0x1ca9, {1|F|D, {0x10e9}}},
+ {0x1caa, {1|F|D, {0x10ea}}},
+ {0x1cab, {1|F|D, {0x10eb}}},
+ {0x1cac, {1|F|D, {0x10ec}}},
+ {0x1cad, {1|F|D, {0x10ed}}},
+ {0x1cae, {1|F|D, {0x10ee}}},
+ {0x1caf, {1|F|D, {0x10ef}}},
+ {0x1cb0, {1|F|D, {0x10f0}}},
+ {0x1cb1, {1|F|D, {0x10f1}}},
+ {0x1cb2, {1|F|D, {0x10f2}}},
+ {0x1cb3, {1|F|D, {0x10f3}}},
+ {0x1cb4, {1|F|D, {0x10f4}}},
+ {0x1cb5, {1|F|D, {0x10f5}}},
+ {0x1cb6, {1|F|D, {0x10f6}}},
+ {0x1cb7, {1|F|D, {0x10f7}}},
+ {0x1cb8, {1|F|D, {0x10f8}}},
+ {0x1cb9, {1|F|D, {0x10f9}}},
+ {0x1cba, {1|F|D, {0x10fa}}},
+ {0x1cbd, {1|F|D, {0x10fd}}},
+ {0x1cbe, {1|F|D, {0x10fe}}},
+ {0x1cbf, {1|F|D, {0x10ff}}},
+ {0x1e00, {1|F|D, {0x1e01}}},
+ {0x1e02, {1|F|D, {0x1e03}}},
+ {0x1e04, {1|F|D, {0x1e05}}},
+ {0x1e06, {1|F|D, {0x1e07}}},
+ {0x1e08, {1|F|D, {0x1e09}}},
+ {0x1e0a, {1|F|D, {0x1e0b}}},
+ {0x1e0c, {1|F|D, {0x1e0d}}},
+ {0x1e0e, {1|F|D, {0x1e0f}}},
+ {0x1e10, {1|F|D, {0x1e11}}},
+ {0x1e12, {1|F|D, {0x1e13}}},
+ {0x1e14, {1|F|D, {0x1e15}}},
+ {0x1e16, {1|F|D, {0x1e17}}},
+ {0x1e18, {1|F|D, {0x1e19}}},
+ {0x1e1a, {1|F|D, {0x1e1b}}},
+ {0x1e1c, {1|F|D, {0x1e1d}}},
+ {0x1e1e, {1|F|D, {0x1e1f}}},
+ {0x1e20, {1|F|D, {0x1e21}}},
+ {0x1e22, {1|F|D, {0x1e23}}},
+ {0x1e24, {1|F|D, {0x1e25}}},
+ {0x1e26, {1|F|D, {0x1e27}}},
+ {0x1e28, {1|F|D, {0x1e29}}},
+ {0x1e2a, {1|F|D, {0x1e2b}}},
+ {0x1e2c, {1|F|D, {0x1e2d}}},
+ {0x1e2e, {1|F|D, {0x1e2f}}},
+ {0x1e30, {1|F|D, {0x1e31}}},
+ {0x1e32, {1|F|D, {0x1e33}}},
+ {0x1e34, {1|F|D, {0x1e35}}},
+ {0x1e36, {1|F|D, {0x1e37}}},
+ {0x1e38, {1|F|D, {0x1e39}}},
+ {0x1e3a, {1|F|D, {0x1e3b}}},
+ {0x1e3c, {1|F|D, {0x1e3d}}},
+ {0x1e3e, {1|F|D, {0x1e3f}}},
+ {0x1e40, {1|F|D, {0x1e41}}},
+ {0x1e42, {1|F|D, {0x1e43}}},
+ {0x1e44, {1|F|D, {0x1e45}}},
+ {0x1e46, {1|F|D, {0x1e47}}},
+ {0x1e48, {1|F|D, {0x1e49}}},
+ {0x1e4a, {1|F|D, {0x1e4b}}},
+ {0x1e4c, {1|F|D, {0x1e4d}}},
+ {0x1e4e, {1|F|D, {0x1e4f}}},
+ {0x1e50, {1|F|D, {0x1e51}}},
+ {0x1e52, {1|F|D, {0x1e53}}},
+ {0x1e54, {1|F|D, {0x1e55}}},
+ {0x1e56, {1|F|D, {0x1e57}}},
+ {0x1e58, {1|F|D, {0x1e59}}},
+ {0x1e5a, {1|F|D, {0x1e5b}}},
+ {0x1e5c, {1|F|D, {0x1e5d}}},
+ {0x1e5e, {1|F|D, {0x1e5f}}},
+ {0x1e60, {1|F|D, {0x1e61}}},
+ {0x1e62, {1|F|D, {0x1e63}}},
+ {0x1e64, {1|F|D, {0x1e65}}},
+ {0x1e66, {1|F|D, {0x1e67}}},
+ {0x1e68, {1|F|D, {0x1e69}}},
+ {0x1e6a, {1|F|D, {0x1e6b}}},
+ {0x1e6c, {1|F|D, {0x1e6d}}},
+ {0x1e6e, {1|F|D, {0x1e6f}}},
+ {0x1e70, {1|F|D, {0x1e71}}},
+ {0x1e72, {1|F|D, {0x1e73}}},
+ {0x1e74, {1|F|D, {0x1e75}}},
+ {0x1e76, {1|F|D, {0x1e77}}},
+ {0x1e78, {1|F|D, {0x1e79}}},
+ {0x1e7a, {1|F|D, {0x1e7b}}},
+ {0x1e7c, {1|F|D, {0x1e7d}}},
+ {0x1e7e, {1|F|D, {0x1e7f}}},
+ {0x1e80, {1|F|D, {0x1e81}}},
+ {0x1e82, {1|F|D, {0x1e83}}},
+ {0x1e84, {1|F|D, {0x1e85}}},
+ {0x1e86, {1|F|D, {0x1e87}}},
+ {0x1e88, {1|F|D, {0x1e89}}},
+ {0x1e8a, {1|F|D, {0x1e8b}}},
+ {0x1e8c, {1|F|D, {0x1e8d}}},
+ {0x1e8e, {1|F|D, {0x1e8f}}},
+ {0x1e90, {1|F|D, {0x1e91}}},
+ {0x1e92, {1|F|D, {0x1e93}}},
+ {0x1e94, {1|F|D, {0x1e95}}},
+ {0x1e96, {2|F|SU|I(54), {0x0068, 0x0331}}},
+ {0x1e97, {2|F|SU|I(56), {0x0074, 0x0308}}},
+ {0x1e98, {2|F|SU|I(58), {0x0077, 0x030a}}},
+ {0x1e99, {2|F|SU|I(60), {0x0079, 0x030a}}},
+ {0x1e9a, {2|F|SU|I(62), {0x0061, 0x02be}}},
+ {0x1e9b, {1|F|SU|I(64), {0x1e61}}},
+ {0x1e9e, {2|F|SL|I(65), {0x0073, 0x0073}}},
+ {0x1ea0, {1|F|D, {0x1ea1}}},
+ {0x1ea2, {1|F|D, {0x1ea3}}},
+ {0x1ea4, {1|F|D, {0x1ea5}}},
+ {0x1ea6, {1|F|D, {0x1ea7}}},
+ {0x1ea8, {1|F|D, {0x1ea9}}},
+ {0x1eaa, {1|F|D, {0x1eab}}},
+ {0x1eac, {1|F|D, {0x1ead}}},
+ {0x1eae, {1|F|D, {0x1eaf}}},
+ {0x1eb0, {1|F|D, {0x1eb1}}},
+ {0x1eb2, {1|F|D, {0x1eb3}}},
+ {0x1eb4, {1|F|D, {0x1eb5}}},
+ {0x1eb6, {1|F|D, {0x1eb7}}},
+ {0x1eb8, {1|F|D, {0x1eb9}}},
+ {0x1eba, {1|F|D, {0x1ebb}}},
+ {0x1ebc, {1|F|D, {0x1ebd}}},
+ {0x1ebe, {1|F|D, {0x1ebf}}},
+ {0x1ec0, {1|F|D, {0x1ec1}}},
+ {0x1ec2, {1|F|D, {0x1ec3}}},
+ {0x1ec4, {1|F|D, {0x1ec5}}},
+ {0x1ec6, {1|F|D, {0x1ec7}}},
+ {0x1ec8, {1|F|D, {0x1ec9}}},
+ {0x1eca, {1|F|D, {0x1ecb}}},
+ {0x1ecc, {1|F|D, {0x1ecd}}},
+ {0x1ece, {1|F|D, {0x1ecf}}},
+ {0x1ed0, {1|F|D, {0x1ed1}}},
+ {0x1ed2, {1|F|D, {0x1ed3}}},
+ {0x1ed4, {1|F|D, {0x1ed5}}},
+ {0x1ed6, {1|F|D, {0x1ed7}}},
+ {0x1ed8, {1|F|D, {0x1ed9}}},
+ {0x1eda, {1|F|D, {0x1edb}}},
+ {0x1edc, {1|F|D, {0x1edd}}},
+ {0x1ede, {1|F|D, {0x1edf}}},
+ {0x1ee0, {1|F|D, {0x1ee1}}},
+ {0x1ee2, {1|F|D, {0x1ee3}}},
+ {0x1ee4, {1|F|D, {0x1ee5}}},
+ {0x1ee6, {1|F|D, {0x1ee7}}},
+ {0x1ee8, {1|F|D, {0x1ee9}}},
+ {0x1eea, {1|F|D, {0x1eeb}}},
+ {0x1eec, {1|F|D, {0x1eed}}},
+ {0x1eee, {1|F|D, {0x1eef}}},
+ {0x1ef0, {1|F|D, {0x1ef1}}},
+ {0x1ef2, {1|F|D, {0x1ef3}}},
+ {0x1ef4, {1|F|D, {0x1ef5}}},
+ {0x1ef6, {1|F|D, {0x1ef7}}},
+ {0x1ef8, {1|F|D, {0x1ef9}}},
+ {0x1efa, {1|F|D, {0x1efb}}},
+ {0x1efc, {1|F|D, {0x1efd}}},
+ {0x1efe, {1|F|D, {0x1eff}}},
+ {0x1f08, {1|F|D, {0x1f00}}},
+ {0x1f09, {1|F|D, {0x1f01}}},
+ {0x1f0a, {1|F|D, {0x1f02}}},
+ {0x1f0b, {1|F|D, {0x1f03}}},
+ {0x1f0c, {1|F|D, {0x1f04}}},
+ {0x1f0d, {1|F|D, {0x1f05}}},
+ {0x1f0e, {1|F|D, {0x1f06}}},
+ {0x1f0f, {1|F|D, {0x1f07}}},
+ {0x1f18, {1|F|D, {0x1f10}}},
+ {0x1f19, {1|F|D, {0x1f11}}},
+ {0x1f1a, {1|F|D, {0x1f12}}},
+ {0x1f1b, {1|F|D, {0x1f13}}},
+ {0x1f1c, {1|F|D, {0x1f14}}},
+ {0x1f1d, {1|F|D, {0x1f15}}},
+ {0x1f28, {1|F|D, {0x1f20}}},
+ {0x1f29, {1|F|D, {0x1f21}}},
+ {0x1f2a, {1|F|D, {0x1f22}}},
+ {0x1f2b, {1|F|D, {0x1f23}}},
+ {0x1f2c, {1|F|D, {0x1f24}}},
+ {0x1f2d, {1|F|D, {0x1f25}}},
+ {0x1f2e, {1|F|D, {0x1f26}}},
+ {0x1f2f, {1|F|D, {0x1f27}}},
+ {0x1f38, {1|F|D, {0x1f30}}},
+ {0x1f39, {1|F|D, {0x1f31}}},
+ {0x1f3a, {1|F|D, {0x1f32}}},
+ {0x1f3b, {1|F|D, {0x1f33}}},
+ {0x1f3c, {1|F|D, {0x1f34}}},
+ {0x1f3d, {1|F|D, {0x1f35}}},
+ {0x1f3e, {1|F|D, {0x1f36}}},
+ {0x1f3f, {1|F|D, {0x1f37}}},
+ {0x1f48, {1|F|D, {0x1f40}}},
+ {0x1f49, {1|F|D, {0x1f41}}},
+ {0x1f4a, {1|F|D, {0x1f42}}},
+ {0x1f4b, {1|F|D, {0x1f43}}},
+ {0x1f4c, {1|F|D, {0x1f44}}},
+ {0x1f4d, {1|F|D, {0x1f45}}},
+ {0x1f50, {2|F|SU|I(66), {0x03c5, 0x0313}}},
+ {0x1f52, {3|F|SU|I(68), {0x03c5, 0x0313, 0x0300}}},
+ {0x1f54, {3|F|SU|I(71), {0x03c5, 0x0313, 0x0301}}},
+ {0x1f56, {3|F|SU|I(74), {0x03c5, 0x0313, 0x0342}}},
+ {0x1f59, {1|F|D, {0x1f51}}},
+ {0x1f5b, {1|F|D, {0x1f53}}},
+ {0x1f5d, {1|F|D, {0x1f55}}},
+ {0x1f5f, {1|F|D, {0x1f57}}},
+ {0x1f68, {1|F|D, {0x1f60}}},
+ {0x1f69, {1|F|D, {0x1f61}}},
+ {0x1f6a, {1|F|D, {0x1f62}}},
+ {0x1f6b, {1|F|D, {0x1f63}}},
+ {0x1f6c, {1|F|D, {0x1f64}}},
+ {0x1f6d, {1|F|D, {0x1f65}}},
+ {0x1f6e, {1|F|D, {0x1f66}}},
+ {0x1f6f, {1|F|D, {0x1f67}}},
+ {0x1f80, {2|F|ST|SU|I(77), {0x1f00, 0x03b9}}},
+ {0x1f81, {2|F|ST|SU|I(80), {0x1f01, 0x03b9}}},
+ {0x1f82, {2|F|ST|SU|I(83), {0x1f02, 0x03b9}}},
+ {0x1f83, {2|F|ST|SU|I(86), {0x1f03, 0x03b9}}},
+ {0x1f84, {2|F|ST|SU|I(89), {0x1f04, 0x03b9}}},
+ {0x1f85, {2|F|ST|SU|I(92), {0x1f05, 0x03b9}}},
+ {0x1f86, {2|F|ST|SU|I(95), {0x1f06, 0x03b9}}},
+ {0x1f87, {2|F|ST|SU|I(98), {0x1f07, 0x03b9}}},
+ {0x1f88, {2|F|IT|SL|SU|I(101), {0x1f00, 0x03b9}}},
+ {0x1f89, {2|F|IT|SL|SU|I(106), {0x1f01, 0x03b9}}},
+ {0x1f8a, {2|F|IT|SL|SU|I(111), {0x1f02, 0x03b9}}},
+ {0x1f8b, {2|F|IT|SL|SU|I(116), {0x1f03, 0x03b9}}},
+ {0x1f8c, {2|F|IT|SL|SU|I(121), {0x1f04, 0x03b9}}},
+ {0x1f8d, {2|F|IT|SL|SU|I(126), {0x1f05, 0x03b9}}},
+ {0x1f8e, {2|F|IT|SL|SU|I(131), {0x1f06, 0x03b9}}},
+ {0x1f8f, {2|F|IT|SL|SU|I(136), {0x1f07, 0x03b9}}},
+ {0x1f90, {2|F|ST|SU|I(141), {0x1f20, 0x03b9}}},
+ {0x1f91, {2|F|ST|SU|I(144), {0x1f21, 0x03b9}}},
+ {0x1f92, {2|F|ST|SU|I(147), {0x1f22, 0x03b9}}},
+ {0x1f93, {2|F|ST|SU|I(150), {0x1f23, 0x03b9}}},
+ {0x1f94, {2|F|ST|SU|I(153), {0x1f24, 0x03b9}}},
+ {0x1f95, {2|F|ST|SU|I(156), {0x1f25, 0x03b9}}},
+ {0x1f96, {2|F|ST|SU|I(159), {0x1f26, 0x03b9}}},
+ {0x1f97, {2|F|ST|SU|I(162), {0x1f27, 0x03b9}}},
+ {0x1f98, {2|F|IT|SL|SU|I(165), {0x1f20, 0x03b9}}},
+ {0x1f99, {2|F|IT|SL|SU|I(170), {0x1f21, 0x03b9}}},
+ {0x1f9a, {2|F|IT|SL|SU|I(175), {0x1f22, 0x03b9}}},
+ {0x1f9b, {2|F|IT|SL|SU|I(180), {0x1f23, 0x03b9}}},
+ {0x1f9c, {2|F|IT|SL|SU|I(185), {0x1f24, 0x03b9}}},
+ {0x1f9d, {2|F|IT|SL|SU|I(190), {0x1f25, 0x03b9}}},
+ {0x1f9e, {2|F|IT|SL|SU|I(195), {0x1f26, 0x03b9}}},
+ {0x1f9f, {2|F|IT|SL|SU|I(200), {0x1f27, 0x03b9}}},
+ {0x1fa0, {2|F|ST|SU|I(205), {0x1f60, 0x03b9}}},
+ {0x1fa1, {2|F|ST|SU|I(208), {0x1f61, 0x03b9}}},
+ {0x1fa2, {2|F|ST|SU|I(211), {0x1f62, 0x03b9}}},
+ {0x1fa3, {2|F|ST|SU|I(214), {0x1f63, 0x03b9}}},
+ {0x1fa4, {2|F|ST|SU|I(217), {0x1f64, 0x03b9}}},
+ {0x1fa5, {2|F|ST|SU|I(220), {0x1f65, 0x03b9}}},
+ {0x1fa6, {2|F|ST|SU|I(223), {0x1f66, 0x03b9}}},
+ {0x1fa7, {2|F|ST|SU|I(226), {0x1f67, 0x03b9}}},
+ {0x1fa8, {2|F|IT|SL|SU|I(229), {0x1f60, 0x03b9}}},
+ {0x1fa9, {2|F|IT|SL|SU|I(234), {0x1f61, 0x03b9}}},
+ {0x1faa, {2|F|IT|SL|SU|I(239), {0x1f62, 0x03b9}}},
+ {0x1fab, {2|F|IT|SL|SU|I(244), {0x1f63, 0x03b9}}},
+ {0x1fac, {2|F|IT|SL|SU|I(249), {0x1f64, 0x03b9}}},
+ {0x1fad, {2|F|IT|SL|SU|I(254), {0x1f65, 0x03b9}}},
+ {0x1fae, {2|F|IT|SL|SU|I(259), {0x1f66, 0x03b9}}},
+ {0x1faf, {2|F|IT|SL|SU|I(264), {0x1f67, 0x03b9}}},
+ {0x1fb2, {2|F|ST|SU|I(269), {0x1f70, 0x03b9}}},
+ {0x1fb3, {2|F|ST|SU|I(273), {0x03b1, 0x03b9}}},
+ {0x1fb4, {2|F|ST|SU|I(276), {0x03ac, 0x03b9}}},
+ {0x1fb6, {2|F|SU|I(280), {0x03b1, 0x0342}}},
+ {0x1fb7, {3|F|ST|SU|I(282), {0x03b1, 0x0342, 0x03b9}}},
+ {0x1fb8, {1|F|D, {0x1fb0}}},
+ {0x1fb9, {1|F|D, {0x1fb1}}},
+ {0x1fba, {1|F|D, {0x1f70}}},
+ {0x1fbb, {1|F|D, {0x1f71}}},
+ {0x1fbc, {2|F|IT|SL|SU|I(288), {0x03b1, 0x03b9}}},
+ {0x1fbe, {1|F|SU|I(293), {0x03b9}}},
+ {0x1fc2, {2|F|ST|SU|I(294), {0x1f74, 0x03b9}}},
+ {0x1fc3, {2|F|ST|SU|I(298), {0x03b7, 0x03b9}}},
+ {0x1fc4, {2|F|ST|SU|I(301), {0x03ae, 0x03b9}}},
+ {0x1fc6, {2|F|SU|I(305), {0x03b7, 0x0342}}},
+ {0x1fc7, {3|F|ST|SU|I(307), {0x03b7, 0x0342, 0x03b9}}},
+ {0x1fc8, {1|F|D, {0x1f72}}},
+ {0x1fc9, {1|F|D, {0x1f73}}},
+ {0x1fca, {1|F|D, {0x1f74}}},
+ {0x1fcb, {1|F|D, {0x1f75}}},
+ {0x1fcc, {2|F|IT|SL|SU|I(313), {0x03b7, 0x03b9}}},
+ {0x1fd2, {3|F|SU|I(318), {0x03b9, 0x0308, 0x0300}}},
+ {0x1fd3, {3|F|SU|I(321), {0x03b9, 0x0308, 0x0301}}},
+ {0x1fd6, {2|F|SU|I(324), {0x03b9, 0x0342}}},
+ {0x1fd7, {3|F|SU|I(326), {0x03b9, 0x0308, 0x0342}}},
+ {0x1fd8, {1|F|D, {0x1fd0}}},
+ {0x1fd9, {1|F|D, {0x1fd1}}},
+ {0x1fda, {1|F|D, {0x1f76}}},
+ {0x1fdb, {1|F|D, {0x1f77}}},
+ {0x1fe2, {3|F|SU|I(329), {0x03c5, 0x0308, 0x0300}}},
+ {0x1fe3, {3|F|SU|I(332), {0x03c5, 0x0308, 0x0301}}},
+ {0x1fe4, {2|F|SU|I(335), {0x03c1, 0x0313}}},
+ {0x1fe6, {2|F|SU|I(337), {0x03c5, 0x0342}}},
+ {0x1fe7, {3|F|SU|I(339), {0x03c5, 0x0308, 0x0342}}},
+ {0x1fe8, {1|F|D, {0x1fe0}}},
+ {0x1fe9, {1|F|D, {0x1fe1}}},
+ {0x1fea, {1|F|D, {0x1f7a}}},
+ {0x1feb, {1|F|D, {0x1f7b}}},
+ {0x1fec, {1|F|D, {0x1fe5}}},
+ {0x1ff2, {2|F|ST|SU|I(342), {0x1f7c, 0x03b9}}},
+ {0x1ff3, {2|F|ST|SU|I(346), {0x03c9, 0x03b9}}},
+ {0x1ff4, {2|F|ST|SU|I(349), {0x03ce, 0x03b9}}},
+ {0x1ff6, {2|F|SU|I(353), {0x03c9, 0x0342}}},
+ {0x1ff7, {3|F|ST|SU|I(355), {0x03c9, 0x0342, 0x03b9}}},
+ {0x1ff8, {1|F|D, {0x1f78}}},
+ {0x1ff9, {1|F|D, {0x1f79}}},
+ {0x1ffa, {1|F|D, {0x1f7c}}},
+ {0x1ffb, {1|F|D, {0x1f7d}}},
+ {0x1ffc, {2|F|IT|SL|SU|I(361), {0x03c9, 0x03b9}}},
+ {0x2126, {1|F|D, {0x03c9}}},
+ {0x212a, {1|F|D, {0x006b}}},
+ {0x212b, {1|F|D, {0x00e5}}},
+ {0x2132, {1|F|D, {0x214e}}},
+ {0x2160, {1|F|D, {0x2170}}},
+ {0x2161, {1|F|D, {0x2171}}},
+ {0x2162, {1|F|D, {0x2172}}},
+ {0x2163, {1|F|D, {0x2173}}},
+ {0x2164, {1|F|D, {0x2174}}},
+ {0x2165, {1|F|D, {0x2175}}},
+ {0x2166, {1|F|D, {0x2176}}},
+ {0x2167, {1|F|D, {0x2177}}},
+ {0x2168, {1|F|D, {0x2178}}},
+ {0x2169, {1|F|D, {0x2179}}},
+ {0x216a, {1|F|D, {0x217a}}},
+ {0x216b, {1|F|D, {0x217b}}},
+ {0x216c, {1|F|D, {0x217c}}},
+ {0x216d, {1|F|D, {0x217d}}},
+ {0x216e, {1|F|D, {0x217e}}},
+ {0x216f, {1|F|D, {0x217f}}},
+ {0x2183, {1|F|D, {0x2184}}},
+ {0x24b6, {1|F|D, {0x24d0}}},
+ {0x24b7, {1|F|D, {0x24d1}}},
+ {0x24b8, {1|F|D, {0x24d2}}},
+ {0x24b9, {1|F|D, {0x24d3}}},
+ {0x24ba, {1|F|D, {0x24d4}}},
+ {0x24bb, {1|F|D, {0x24d5}}},
+ {0x24bc, {1|F|D, {0x24d6}}},
+ {0x24bd, {1|F|D, {0x24d7}}},
+ {0x24be, {1|F|D, {0x24d8}}},
+ {0x24bf, {1|F|D, {0x24d9}}},
+ {0x24c0, {1|F|D, {0x24da}}},
+ {0x24c1, {1|F|D, {0x24db}}},
+ {0x24c2, {1|F|D, {0x24dc}}},
+ {0x24c3, {1|F|D, {0x24dd}}},
+ {0x24c4, {1|F|D, {0x24de}}},
+ {0x24c5, {1|F|D, {0x24df}}},
+ {0x24c6, {1|F|D, {0x24e0}}},
+ {0x24c7, {1|F|D, {0x24e1}}},
+ {0x24c8, {1|F|D, {0x24e2}}},
+ {0x24c9, {1|F|D, {0x24e3}}},
+ {0x24ca, {1|F|D, {0x24e4}}},
+ {0x24cb, {1|F|D, {0x24e5}}},
+ {0x24cc, {1|F|D, {0x24e6}}},
+ {0x24cd, {1|F|D, {0x24e7}}},
+ {0x24ce, {1|F|D, {0x24e8}}},
+ {0x24cf, {1|F|D, {0x24e9}}},
+ {0x2c00, {1|F|D, {0x2c30}}},
+ {0x2c01, {1|F|D, {0x2c31}}},
+ {0x2c02, {1|F|D, {0x2c32}}},
+ {0x2c03, {1|F|D, {0x2c33}}},
+ {0x2c04, {1|F|D, {0x2c34}}},
+ {0x2c05, {1|F|D, {0x2c35}}},
+ {0x2c06, {1|F|D, {0x2c36}}},
+ {0x2c07, {1|F|D, {0x2c37}}},
+ {0x2c08, {1|F|D, {0x2c38}}},
+ {0x2c09, {1|F|D, {0x2c39}}},
+ {0x2c0a, {1|F|D, {0x2c3a}}},
+ {0x2c0b, {1|F|D, {0x2c3b}}},
+ {0x2c0c, {1|F|D, {0x2c3c}}},
+ {0x2c0d, {1|F|D, {0x2c3d}}},
+ {0x2c0e, {1|F|D, {0x2c3e}}},
+ {0x2c0f, {1|F|D, {0x2c3f}}},
+ {0x2c10, {1|F|D, {0x2c40}}},
+ {0x2c11, {1|F|D, {0x2c41}}},
+ {0x2c12, {1|F|D, {0x2c42}}},
+ {0x2c13, {1|F|D, {0x2c43}}},
+ {0x2c14, {1|F|D, {0x2c44}}},
+ {0x2c15, {1|F|D, {0x2c45}}},
+ {0x2c16, {1|F|D, {0x2c46}}},
+ {0x2c17, {1|F|D, {0x2c47}}},
+ {0x2c18, {1|F|D, {0x2c48}}},
+ {0x2c19, {1|F|D, {0x2c49}}},
+ {0x2c1a, {1|F|D, {0x2c4a}}},
+ {0x2c1b, {1|F|D, {0x2c4b}}},
+ {0x2c1c, {1|F|D, {0x2c4c}}},
+ {0x2c1d, {1|F|D, {0x2c4d}}},
+ {0x2c1e, {1|F|D, {0x2c4e}}},
+ {0x2c1f, {1|F|D, {0x2c4f}}},
+ {0x2c20, {1|F|D, {0x2c50}}},
+ {0x2c21, {1|F|D, {0x2c51}}},
+ {0x2c22, {1|F|D, {0x2c52}}},
+ {0x2c23, {1|F|D, {0x2c53}}},
+ {0x2c24, {1|F|D, {0x2c54}}},
+ {0x2c25, {1|F|D, {0x2c55}}},
+ {0x2c26, {1|F|D, {0x2c56}}},
+ {0x2c27, {1|F|D, {0x2c57}}},
+ {0x2c28, {1|F|D, {0x2c58}}},
+ {0x2c29, {1|F|D, {0x2c59}}},
+ {0x2c2a, {1|F|D, {0x2c5a}}},
+ {0x2c2b, {1|F|D, {0x2c5b}}},
+ {0x2c2c, {1|F|D, {0x2c5c}}},
+ {0x2c2d, {1|F|D, {0x2c5d}}},
+ {0x2c2e, {1|F|D, {0x2c5e}}},
+ {0x2c2f, {1|F|D, {0x2c5f}}},
+ {0x2c60, {1|F|D, {0x2c61}}},
+ {0x2c62, {1|F|D, {0x026b}}},
+ {0x2c63, {1|F|D, {0x1d7d}}},
+ {0x2c64, {1|F|D, {0x027d}}},
+ {0x2c67, {1|F|D, {0x2c68}}},
+ {0x2c69, {1|F|D, {0x2c6a}}},
+ {0x2c6b, {1|F|D, {0x2c6c}}},
+ {0x2c6d, {1|F|D, {0x0251}}},
+ {0x2c6e, {1|F|D, {0x0271}}},
+ {0x2c6f, {1|F|D, {0x0250}}},
+ {0x2c70, {1|F|D, {0x0252}}},
+ {0x2c72, {1|F|D, {0x2c73}}},
+ {0x2c75, {1|F|D, {0x2c76}}},
+ {0x2c7e, {1|F|D, {0x023f}}},
+ {0x2c7f, {1|F|D, {0x0240}}},
+ {0x2c80, {1|F|D, {0x2c81}}},
+ {0x2c82, {1|F|D, {0x2c83}}},
+ {0x2c84, {1|F|D, {0x2c85}}},
+ {0x2c86, {1|F|D, {0x2c87}}},
+ {0x2c88, {1|F|D, {0x2c89}}},
+ {0x2c8a, {1|F|D, {0x2c8b}}},
+ {0x2c8c, {1|F|D, {0x2c8d}}},
+ {0x2c8e, {1|F|D, {0x2c8f}}},
+ {0x2c90, {1|F|D, {0x2c91}}},
+ {0x2c92, {1|F|D, {0x2c93}}},
+ {0x2c94, {1|F|D, {0x2c95}}},
+ {0x2c96, {1|F|D, {0x2c97}}},
+ {0x2c98, {1|F|D, {0x2c99}}},
+ {0x2c9a, {1|F|D, {0x2c9b}}},
+ {0x2c9c, {1|F|D, {0x2c9d}}},
+ {0x2c9e, {1|F|D, {0x2c9f}}},
+ {0x2ca0, {1|F|D, {0x2ca1}}},
+ {0x2ca2, {1|F|D, {0x2ca3}}},
+ {0x2ca4, {1|F|D, {0x2ca5}}},
+ {0x2ca6, {1|F|D, {0x2ca7}}},
+ {0x2ca8, {1|F|D, {0x2ca9}}},
+ {0x2caa, {1|F|D, {0x2cab}}},
+ {0x2cac, {1|F|D, {0x2cad}}},
+ {0x2cae, {1|F|D, {0x2caf}}},
+ {0x2cb0, {1|F|D, {0x2cb1}}},
+ {0x2cb2, {1|F|D, {0x2cb3}}},
+ {0x2cb4, {1|F|D, {0x2cb5}}},
+ {0x2cb6, {1|F|D, {0x2cb7}}},
+ {0x2cb8, {1|F|D, {0x2cb9}}},
+ {0x2cba, {1|F|D, {0x2cbb}}},
+ {0x2cbc, {1|F|D, {0x2cbd}}},
+ {0x2cbe, {1|F|D, {0x2cbf}}},
+ {0x2cc0, {1|F|D, {0x2cc1}}},
+ {0x2cc2, {1|F|D, {0x2cc3}}},
+ {0x2cc4, {1|F|D, {0x2cc5}}},
+ {0x2cc6, {1|F|D, {0x2cc7}}},
+ {0x2cc8, {1|F|D, {0x2cc9}}},
+ {0x2cca, {1|F|D, {0x2ccb}}},
+ {0x2ccc, {1|F|D, {0x2ccd}}},
+ {0x2cce, {1|F|D, {0x2ccf}}},
+ {0x2cd0, {1|F|D, {0x2cd1}}},
+ {0x2cd2, {1|F|D, {0x2cd3}}},
+ {0x2cd4, {1|F|D, {0x2cd5}}},
+ {0x2cd6, {1|F|D, {0x2cd7}}},
+ {0x2cd8, {1|F|D, {0x2cd9}}},
+ {0x2cda, {1|F|D, {0x2cdb}}},
+ {0x2cdc, {1|F|D, {0x2cdd}}},
+ {0x2cde, {1|F|D, {0x2cdf}}},
+ {0x2ce0, {1|F|D, {0x2ce1}}},
+ {0x2ce2, {1|F|D, {0x2ce3}}},
+ {0x2ceb, {1|F|D, {0x2cec}}},
+ {0x2ced, {1|F|D, {0x2cee}}},
+ {0x2cf2, {1|F|D, {0x2cf3}}},
+ {0xa640, {1|F|D, {0xa641}}},
+ {0xa642, {1|F|D, {0xa643}}},
+ {0xa644, {1|F|D, {0xa645}}},
+ {0xa646, {1|F|D, {0xa647}}},
+ {0xa648, {1|F|D, {0xa649}}},
+ {0xa64a, {1|F|D, {0xa64b}}},
+ {0xa64c, {1|F|D, {0xa64d}}},
+ {0xa64e, {1|F|D, {0xa64f}}},
+ {0xa650, {1|F|D, {0xa651}}},
+ {0xa652, {1|F|D, {0xa653}}},
+ {0xa654, {1|F|D, {0xa655}}},
+ {0xa656, {1|F|D, {0xa657}}},
+ {0xa658, {1|F|D, {0xa659}}},
+ {0xa65a, {1|F|D, {0xa65b}}},
+ {0xa65c, {1|F|D, {0xa65d}}},
+ {0xa65e, {1|F|D, {0xa65f}}},
+ {0xa660, {1|F|D, {0xa661}}},
+ {0xa662, {1|F|D, {0xa663}}},
+ {0xa664, {1|F|D, {0xa665}}},
+ {0xa666, {1|F|D, {0xa667}}},
+ {0xa668, {1|F|D, {0xa669}}},
+ {0xa66a, {1|F|D, {0xa66b}}},
+ {0xa66c, {1|F|D, {0xa66d}}},
+ {0xa680, {1|F|D, {0xa681}}},
+ {0xa682, {1|F|D, {0xa683}}},
+ {0xa684, {1|F|D, {0xa685}}},
+ {0xa686, {1|F|D, {0xa687}}},
+ {0xa688, {1|F|D, {0xa689}}},
+ {0xa68a, {1|F|D, {0xa68b}}},
+ {0xa68c, {1|F|D, {0xa68d}}},
+ {0xa68e, {1|F|D, {0xa68f}}},
+ {0xa690, {1|F|D, {0xa691}}},
+ {0xa692, {1|F|D, {0xa693}}},
+ {0xa694, {1|F|D, {0xa695}}},
+ {0xa696, {1|F|D, {0xa697}}},
+ {0xa698, {1|F|D, {0xa699}}},
+ {0xa69a, {1|F|D, {0xa69b}}},
+ {0xa722, {1|F|D, {0xa723}}},
+ {0xa724, {1|F|D, {0xa725}}},
+ {0xa726, {1|F|D, {0xa727}}},
+ {0xa728, {1|F|D, {0xa729}}},
+ {0xa72a, {1|F|D, {0xa72b}}},
+ {0xa72c, {1|F|D, {0xa72d}}},
+ {0xa72e, {1|F|D, {0xa72f}}},
+ {0xa732, {1|F|D, {0xa733}}},
+ {0xa734, {1|F|D, {0xa735}}},
+ {0xa736, {1|F|D, {0xa737}}},
+ {0xa738, {1|F|D, {0xa739}}},
+ {0xa73a, {1|F|D, {0xa73b}}},
+ {0xa73c, {1|F|D, {0xa73d}}},
+ {0xa73e, {1|F|D, {0xa73f}}},
+ {0xa740, {1|F|D, {0xa741}}},
+ {0xa742, {1|F|D, {0xa743}}},
+ {0xa744, {1|F|D, {0xa745}}},
+ {0xa746, {1|F|D, {0xa747}}},
+ {0xa748, {1|F|D, {0xa749}}},
+ {0xa74a, {1|F|D, {0xa74b}}},
+ {0xa74c, {1|F|D, {0xa74d}}},
+ {0xa74e, {1|F|D, {0xa74f}}},
+ {0xa750, {1|F|D, {0xa751}}},
+ {0xa752, {1|F|D, {0xa753}}},
+ {0xa754, {1|F|D, {0xa755}}},
+ {0xa756, {1|F|D, {0xa757}}},
+ {0xa758, {1|F|D, {0xa759}}},
+ {0xa75a, {1|F|D, {0xa75b}}},
+ {0xa75c, {1|F|D, {0xa75d}}},
+ {0xa75e, {1|F|D, {0xa75f}}},
+ {0xa760, {1|F|D, {0xa761}}},
+ {0xa762, {1|F|D, {0xa763}}},
+ {0xa764, {1|F|D, {0xa765}}},
+ {0xa766, {1|F|D, {0xa767}}},
+ {0xa768, {1|F|D, {0xa769}}},
+ {0xa76a, {1|F|D, {0xa76b}}},
+ {0xa76c, {1|F|D, {0xa76d}}},
+ {0xa76e, {1|F|D, {0xa76f}}},
+ {0xa779, {1|F|D, {0xa77a}}},
+ {0xa77b, {1|F|D, {0xa77c}}},
+ {0xa77d, {1|F|D, {0x1d79}}},
+ {0xa77e, {1|F|D, {0xa77f}}},
+ {0xa780, {1|F|D, {0xa781}}},
+ {0xa782, {1|F|D, {0xa783}}},
+ {0xa784, {1|F|D, {0xa785}}},
+ {0xa786, {1|F|D, {0xa787}}},
+ {0xa78b, {1|F|D, {0xa78c}}},
+ {0xa78d, {1|F|D, {0x0265}}},
+ {0xa790, {1|F|D, {0xa791}}},
+ {0xa792, {1|F|D, {0xa793}}},
+ {0xa796, {1|F|D, {0xa797}}},
+ {0xa798, {1|F|D, {0xa799}}},
+ {0xa79a, {1|F|D, {0xa79b}}},
+ {0xa79c, {1|F|D, {0xa79d}}},
+ {0xa79e, {1|F|D, {0xa79f}}},
+ {0xa7a0, {1|F|D, {0xa7a1}}},
+ {0xa7a2, {1|F|D, {0xa7a3}}},
+ {0xa7a4, {1|F|D, {0xa7a5}}},
+ {0xa7a6, {1|F|D, {0xa7a7}}},
+ {0xa7a8, {1|F|D, {0xa7a9}}},
+ {0xa7aa, {1|F|D, {0x0266}}},
+ {0xa7ab, {1|F|D, {0x025c}}},
+ {0xa7ac, {1|F|D, {0x0261}}},
+ {0xa7ad, {1|F|D, {0x026c}}},
+ {0xa7ae, {1|F|D, {0x026a}}},
+ {0xa7b0, {1|F|D, {0x029e}}},
+ {0xa7b1, {1|F|D, {0x0287}}},
+ {0xa7b2, {1|F|D, {0x029d}}},
+ {0xa7b3, {1|F|D, {0xab53}}},
+ {0xa7b4, {1|F|D, {0xa7b5}}},
+ {0xa7b6, {1|F|D, {0xa7b7}}},
+ {0xa7b8, {1|F|D, {0xa7b9}}},
+ {0xa7ba, {1|F|D, {0xa7bb}}},
+ {0xa7bc, {1|F|D, {0xa7bd}}},
+ {0xa7be, {1|F|D, {0xa7bf}}},
+ {0xa7c0, {1|F|D, {0xa7c1}}},
+ {0xa7c2, {1|F|D, {0xa7c3}}},
+ {0xa7c4, {1|F|D, {0xa794}}},
+ {0xa7c5, {1|F|D, {0x0282}}},
+ {0xa7c6, {1|F|D, {0x1d8e}}},
+ {0xa7c7, {1|F|D, {0xa7c8}}},
+ {0xa7c9, {1|F|D, {0xa7ca}}},
+ {0xa7cb, {1|F|D, {0x0264}}},
+ {0xa7cc, {1|F|D, {0xa7cd}}},
+ {0xa7ce, {1|F|D, {0xa7cf}}},
+ {0xa7d0, {1|F|D, {0xa7d1}}},
+ {0xa7d2, {1|F|D, {0xa7d3}}},
+ {0xa7d4, {1|F|D, {0xa7d5}}},
+ {0xa7d6, {1|F|D, {0xa7d7}}},
+ {0xa7d8, {1|F|D, {0xa7d9}}},
+ {0xa7da, {1|F|D, {0xa7db}}},
+ {0xa7dc, {1|F|D, {0x019b}}},
+ {0xa7f5, {1|F|D, {0xa7f6}}},
+ {0xab70, {1|F|U, {0x13a0}}},
+ {0xab71, {1|F|U, {0x13a1}}},
+ {0xab72, {1|F|U, {0x13a2}}},
+ {0xab73, {1|F|U, {0x13a3}}},
+ {0xab74, {1|F|U, {0x13a4}}},
+ {0xab75, {1|F|U, {0x13a5}}},
+ {0xab76, {1|F|U, {0x13a6}}},
+ {0xab77, {1|F|U, {0x13a7}}},
+ {0xab78, {1|F|U, {0x13a8}}},
+ {0xab79, {1|F|U, {0x13a9}}},
+ {0xab7a, {1|F|U, {0x13aa}}},
+ {0xab7b, {1|F|U, {0x13ab}}},
+ {0xab7c, {1|F|U, {0x13ac}}},
+ {0xab7d, {1|F|U, {0x13ad}}},
+ {0xab7e, {1|F|U, {0x13ae}}},
+ {0xab7f, {1|F|U, {0x13af}}},
+ {0xab80, {1|F|U, {0x13b0}}},
+ {0xab81, {1|F|U, {0x13b1}}},
+ {0xab82, {1|F|U, {0x13b2}}},
+ {0xab83, {1|F|U, {0x13b3}}},
+ {0xab84, {1|F|U, {0x13b4}}},
+ {0xab85, {1|F|U, {0x13b5}}},
+ {0xab86, {1|F|U, {0x13b6}}},
+ {0xab87, {1|F|U, {0x13b7}}},
+ {0xab88, {1|F|U, {0x13b8}}},
+ {0xab89, {1|F|U, {0x13b9}}},
+ {0xab8a, {1|F|U, {0x13ba}}},
+ {0xab8b, {1|F|U, {0x13bb}}},
+ {0xab8c, {1|F|U, {0x13bc}}},
+ {0xab8d, {1|F|U, {0x13bd}}},
+ {0xab8e, {1|F|U, {0x13be}}},
+ {0xab8f, {1|F|U, {0x13bf}}},
+ {0xab90, {1|F|U, {0x13c0}}},
+ {0xab91, {1|F|U, {0x13c1}}},
+ {0xab92, {1|F|U, {0x13c2}}},
+ {0xab93, {1|F|U, {0x13c3}}},
+ {0xab94, {1|F|U, {0x13c4}}},
+ {0xab95, {1|F|U, {0x13c5}}},
+ {0xab96, {1|F|U, {0x13c6}}},
+ {0xab97, {1|F|U, {0x13c7}}},
+ {0xab98, {1|F|U, {0x13c8}}},
+ {0xab99, {1|F|U, {0x13c9}}},
+ {0xab9a, {1|F|U, {0x13ca}}},
+ {0xab9b, {1|F|U, {0x13cb}}},
+ {0xab9c, {1|F|U, {0x13cc}}},
+ {0xab9d, {1|F|U, {0x13cd}}},
+ {0xab9e, {1|F|U, {0x13ce}}},
+ {0xab9f, {1|F|U, {0x13cf}}},
+ {0xaba0, {1|F|U, {0x13d0}}},
+ {0xaba1, {1|F|U, {0x13d1}}},
+ {0xaba2, {1|F|U, {0x13d2}}},
+ {0xaba3, {1|F|U, {0x13d3}}},
+ {0xaba4, {1|F|U, {0x13d4}}},
+ {0xaba5, {1|F|U, {0x13d5}}},
+ {0xaba6, {1|F|U, {0x13d6}}},
+ {0xaba7, {1|F|U, {0x13d7}}},
+ {0xaba8, {1|F|U, {0x13d8}}},
+ {0xaba9, {1|F|U, {0x13d9}}},
+ {0xabaa, {1|F|U, {0x13da}}},
+ {0xabab, {1|F|U, {0x13db}}},
+ {0xabac, {1|F|U, {0x13dc}}},
+ {0xabad, {1|F|U, {0x13dd}}},
+ {0xabae, {1|F|U, {0x13de}}},
+ {0xabaf, {1|F|U, {0x13df}}},
+ {0xabb0, {1|F|U, {0x13e0}}},
+ {0xabb1, {1|F|U, {0x13e1}}},
+ {0xabb2, {1|F|U, {0x13e2}}},
+ {0xabb3, {1|F|U, {0x13e3}}},
+ {0xabb4, {1|F|U, {0x13e4}}},
+ {0xabb5, {1|F|U, {0x13e5}}},
+ {0xabb6, {1|F|U, {0x13e6}}},
+ {0xabb7, {1|F|U, {0x13e7}}},
+ {0xabb8, {1|F|U, {0x13e8}}},
+ {0xabb9, {1|F|U, {0x13e9}}},
+ {0xabba, {1|F|U, {0x13ea}}},
+ {0xabbb, {1|F|U, {0x13eb}}},
+ {0xabbc, {1|F|U, {0x13ec}}},
+ {0xabbd, {1|F|U, {0x13ed}}},
+ {0xabbe, {1|F|U, {0x13ee}}},
+ {0xabbf, {1|F|U, {0x13ef}}},
+ {0xfb00, {2|F|ST|SU|I(366), {0x0066, 0x0066}}},
+ {0xfb01, {2|F|ST|SU|I(370), {0x0066, 0x0069}}},
+ {0xfb02, {2|F|ST|SU|I(374), {0x0066, 0x006c}}},
+ {0xfb03, {3|F|ST|SU|I(378), {0x0066, 0x0066, 0x0069}}},
+ {0xfb04, {3|F|ST|SU|I(384), {0x0066, 0x0066, 0x006c}}},
+ {0xfb05, {2|F|ST|SU|I(390), {0x0073, 0x0074}}},
+ {0xfb06, {2|F|ST|SU|I(394), {0x0073, 0x0074}}},
+ {0xfb13, {2|F|ST|SU|I(398), {0x0574, 0x0576}}},
+ {0xfb14, {2|F|ST|SU|I(402), {0x0574, 0x0565}}},
+ {0xfb15, {2|F|ST|SU|I(406), {0x0574, 0x056b}}},
+ {0xfb16, {2|F|ST|SU|I(410), {0x057e, 0x0576}}},
+ {0xfb17, {2|F|ST|SU|I(414), {0x0574, 0x056d}}},
+ {0xff21, {1|F|D, {0xff41}}},
+ {0xff22, {1|F|D, {0xff42}}},
+ {0xff23, {1|F|D, {0xff43}}},
+ {0xff24, {1|F|D, {0xff44}}},
+ {0xff25, {1|F|D, {0xff45}}},
+ {0xff26, {1|F|D, {0xff46}}},
+ {0xff27, {1|F|D, {0xff47}}},
+ {0xff28, {1|F|D, {0xff48}}},
+ {0xff29, {1|F|D, {0xff49}}},
+ {0xff2a, {1|F|D, {0xff4a}}},
+ {0xff2b, {1|F|D, {0xff4b}}},
+ {0xff2c, {1|F|D, {0xff4c}}},
+ {0xff2d, {1|F|D, {0xff4d}}},
+ {0xff2e, {1|F|D, {0xff4e}}},
+ {0xff2f, {1|F|D, {0xff4f}}},
+ {0xff30, {1|F|D, {0xff50}}},
+ {0xff31, {1|F|D, {0xff51}}},
+ {0xff32, {1|F|D, {0xff52}}},
+ {0xff33, {1|F|D, {0xff53}}},
+ {0xff34, {1|F|D, {0xff54}}},
+ {0xff35, {1|F|D, {0xff55}}},
+ {0xff36, {1|F|D, {0xff56}}},
+ {0xff37, {1|F|D, {0xff57}}},
+ {0xff38, {1|F|D, {0xff58}}},
+ {0xff39, {1|F|D, {0xff59}}},
+ {0xff3a, {1|F|D, {0xff5a}}},
+ {0x10400, {1|F|D, {0x10428}}},
+ {0x10401, {1|F|D, {0x10429}}},
+ {0x10402, {1|F|D, {0x1042a}}},
+ {0x10403, {1|F|D, {0x1042b}}},
+ {0x10404, {1|F|D, {0x1042c}}},
+ {0x10405, {1|F|D, {0x1042d}}},
+ {0x10406, {1|F|D, {0x1042e}}},
+ {0x10407, {1|F|D, {0x1042f}}},
+ {0x10408, {1|F|D, {0x10430}}},
+ {0x10409, {1|F|D, {0x10431}}},
+ {0x1040a, {1|F|D, {0x10432}}},
+ {0x1040b, {1|F|D, {0x10433}}},
+ {0x1040c, {1|F|D, {0x10434}}},
+ {0x1040d, {1|F|D, {0x10435}}},
+ {0x1040e, {1|F|D, {0x10436}}},
+ {0x1040f, {1|F|D, {0x10437}}},
+ {0x10410, {1|F|D, {0x10438}}},
+ {0x10411, {1|F|D, {0x10439}}},
+ {0x10412, {1|F|D, {0x1043a}}},
+ {0x10413, {1|F|D, {0x1043b}}},
+ {0x10414, {1|F|D, {0x1043c}}},
+ {0x10415, {1|F|D, {0x1043d}}},
+ {0x10416, {1|F|D, {0x1043e}}},
+ {0x10417, {1|F|D, {0x1043f}}},
+ {0x10418, {1|F|D, {0x10440}}},
+ {0x10419, {1|F|D, {0x10441}}},
+ {0x1041a, {1|F|D, {0x10442}}},
+ {0x1041b, {1|F|D, {0x10443}}},
+ {0x1041c, {1|F|D, {0x10444}}},
+ {0x1041d, {1|F|D, {0x10445}}},
+ {0x1041e, {1|F|D, {0x10446}}},
+ {0x1041f, {1|F|D, {0x10447}}},
+ {0x10420, {1|F|D, {0x10448}}},
+ {0x10421, {1|F|D, {0x10449}}},
+ {0x10422, {1|F|D, {0x1044a}}},
+ {0x10423, {1|F|D, {0x1044b}}},
+ {0x10424, {1|F|D, {0x1044c}}},
+ {0x10425, {1|F|D, {0x1044d}}},
+ {0x10426, {1|F|D, {0x1044e}}},
+ {0x10427, {1|F|D, {0x1044f}}},
+ {0x104b0, {1|F|D, {0x104d8}}},
+ {0x104b1, {1|F|D, {0x104d9}}},
+ {0x104b2, {1|F|D, {0x104da}}},
+ {0x104b3, {1|F|D, {0x104db}}},
+ {0x104b4, {1|F|D, {0x104dc}}},
+ {0x104b5, {1|F|D, {0x104dd}}},
+ {0x104b6, {1|F|D, {0x104de}}},
+ {0x104b7, {1|F|D, {0x104df}}},
+ {0x104b8, {1|F|D, {0x104e0}}},
+ {0x104b9, {1|F|D, {0x104e1}}},
+ {0x104ba, {1|F|D, {0x104e2}}},
+ {0x104bb, {1|F|D, {0x104e3}}},
+ {0x104bc, {1|F|D, {0x104e4}}},
+ {0x104bd, {1|F|D, {0x104e5}}},
+ {0x104be, {1|F|D, {0x104e6}}},
+ {0x104bf, {1|F|D, {0x104e7}}},
+ {0x104c0, {1|F|D, {0x104e8}}},
+ {0x104c1, {1|F|D, {0x104e9}}},
+ {0x104c2, {1|F|D, {0x104ea}}},
+ {0x104c3, {1|F|D, {0x104eb}}},
+ {0x104c4, {1|F|D, {0x104ec}}},
+ {0x104c5, {1|F|D, {0x104ed}}},
+ {0x104c6, {1|F|D, {0x104ee}}},
+ {0x104c7, {1|F|D, {0x104ef}}},
+ {0x104c8, {1|F|D, {0x104f0}}},
+ {0x104c9, {1|F|D, {0x104f1}}},
+ {0x104ca, {1|F|D, {0x104f2}}},
+ {0x104cb, {1|F|D, {0x104f3}}},
+ {0x104cc, {1|F|D, {0x104f4}}},
+ {0x104cd, {1|F|D, {0x104f5}}},
+ {0x104ce, {1|F|D, {0x104f6}}},
+ {0x104cf, {1|F|D, {0x104f7}}},
+ {0x104d0, {1|F|D, {0x104f8}}},
+ {0x104d1, {1|F|D, {0x104f9}}},
+ {0x104d2, {1|F|D, {0x104fa}}},
+ {0x104d3, {1|F|D, {0x104fb}}},
+ {0x10570, {1|F|D, {0x10597}}},
+ {0x10571, {1|F|D, {0x10598}}},
+ {0x10572, {1|F|D, {0x10599}}},
+ {0x10573, {1|F|D, {0x1059a}}},
+ {0x10574, {1|F|D, {0x1059b}}},
+ {0x10575, {1|F|D, {0x1059c}}},
+ {0x10576, {1|F|D, {0x1059d}}},
+ {0x10577, {1|F|D, {0x1059e}}},
+ {0x10578, {1|F|D, {0x1059f}}},
+ {0x10579, {1|F|D, {0x105a0}}},
+ {0x1057a, {1|F|D, {0x105a1}}},
+ {0x1057c, {1|F|D, {0x105a3}}},
+ {0x1057d, {1|F|D, {0x105a4}}},
+ {0x1057e, {1|F|D, {0x105a5}}},
+ {0x1057f, {1|F|D, {0x105a6}}},
+ {0x10580, {1|F|D, {0x105a7}}},
+ {0x10581, {1|F|D, {0x105a8}}},
+ {0x10582, {1|F|D, {0x105a9}}},
+ {0x10583, {1|F|D, {0x105aa}}},
+ {0x10584, {1|F|D, {0x105ab}}},
+ {0x10585, {1|F|D, {0x105ac}}},
+ {0x10586, {1|F|D, {0x105ad}}},
+ {0x10587, {1|F|D, {0x105ae}}},
+ {0x10588, {1|F|D, {0x105af}}},
+ {0x10589, {1|F|D, {0x105b0}}},
+ {0x1058a, {1|F|D, {0x105b1}}},
+ {0x1058c, {1|F|D, {0x105b3}}},
+ {0x1058d, {1|F|D, {0x105b4}}},
+ {0x1058e, {1|F|D, {0x105b5}}},
+ {0x1058f, {1|F|D, {0x105b6}}},
+ {0x10590, {1|F|D, {0x105b7}}},
+ {0x10591, {1|F|D, {0x105b8}}},
+ {0x10592, {1|F|D, {0x105b9}}},
+ {0x10594, {1|F|D, {0x105bb}}},
+ {0x10595, {1|F|D, {0x105bc}}},
+ {0x10c80, {1|F|D, {0x10cc0}}},
+ {0x10c81, {1|F|D, {0x10cc1}}},
+ {0x10c82, {1|F|D, {0x10cc2}}},
+ {0x10c83, {1|F|D, {0x10cc3}}},
+ {0x10c84, {1|F|D, {0x10cc4}}},
+ {0x10c85, {1|F|D, {0x10cc5}}},
+ {0x10c86, {1|F|D, {0x10cc6}}},
+ {0x10c87, {1|F|D, {0x10cc7}}},
+ {0x10c88, {1|F|D, {0x10cc8}}},
+ {0x10c89, {1|F|D, {0x10cc9}}},
+ {0x10c8a, {1|F|D, {0x10cca}}},
+ {0x10c8b, {1|F|D, {0x10ccb}}},
+ {0x10c8c, {1|F|D, {0x10ccc}}},
+ {0x10c8d, {1|F|D, {0x10ccd}}},
+ {0x10c8e, {1|F|D, {0x10cce}}},
+ {0x10c8f, {1|F|D, {0x10ccf}}},
+ {0x10c90, {1|F|D, {0x10cd0}}},
+ {0x10c91, {1|F|D, {0x10cd1}}},
+ {0x10c92, {1|F|D, {0x10cd2}}},
+ {0x10c93, {1|F|D, {0x10cd3}}},
+ {0x10c94, {1|F|D, {0x10cd4}}},
+ {0x10c95, {1|F|D, {0x10cd5}}},
+ {0x10c96, {1|F|D, {0x10cd6}}},
+ {0x10c97, {1|F|D, {0x10cd7}}},
+ {0x10c98, {1|F|D, {0x10cd8}}},
+ {0x10c99, {1|F|D, {0x10cd9}}},
+ {0x10c9a, {1|F|D, {0x10cda}}},
+ {0x10c9b, {1|F|D, {0x10cdb}}},
+ {0x10c9c, {1|F|D, {0x10cdc}}},
+ {0x10c9d, {1|F|D, {0x10cdd}}},
+ {0x10c9e, {1|F|D, {0x10cde}}},
+ {0x10c9f, {1|F|D, {0x10cdf}}},
+ {0x10ca0, {1|F|D, {0x10ce0}}},
+ {0x10ca1, {1|F|D, {0x10ce1}}},
+ {0x10ca2, {1|F|D, {0x10ce2}}},
+ {0x10ca3, {1|F|D, {0x10ce3}}},
+ {0x10ca4, {1|F|D, {0x10ce4}}},
+ {0x10ca5, {1|F|D, {0x10ce5}}},
+ {0x10ca6, {1|F|D, {0x10ce6}}},
+ {0x10ca7, {1|F|D, {0x10ce7}}},
+ {0x10ca8, {1|F|D, {0x10ce8}}},
+ {0x10ca9, {1|F|D, {0x10ce9}}},
+ {0x10caa, {1|F|D, {0x10cea}}},
+ {0x10cab, {1|F|D, {0x10ceb}}},
+ {0x10cac, {1|F|D, {0x10cec}}},
+ {0x10cad, {1|F|D, {0x10ced}}},
+ {0x10cae, {1|F|D, {0x10cee}}},
+ {0x10caf, {1|F|D, {0x10cef}}},
+ {0x10cb0, {1|F|D, {0x10cf0}}},
+ {0x10cb1, {1|F|D, {0x10cf1}}},
+ {0x10cb2, {1|F|D, {0x10cf2}}},
+ {0x10d50, {1|F|D, {0x10d70}}},
+ {0x10d51, {1|F|D, {0x10d71}}},
+ {0x10d52, {1|F|D, {0x10d72}}},
+ {0x10d53, {1|F|D, {0x10d73}}},
+ {0x10d54, {1|F|D, {0x10d74}}},
+ {0x10d55, {1|F|D, {0x10d75}}},
+ {0x10d56, {1|F|D, {0x10d76}}},
+ {0x10d57, {1|F|D, {0x10d77}}},
+ {0x10d58, {1|F|D, {0x10d78}}},
+ {0x10d59, {1|F|D, {0x10d79}}},
+ {0x10d5a, {1|F|D, {0x10d7a}}},
+ {0x10d5b, {1|F|D, {0x10d7b}}},
+ {0x10d5c, {1|F|D, {0x10d7c}}},
+ {0x10d5d, {1|F|D, {0x10d7d}}},
+ {0x10d5e, {1|F|D, {0x10d7e}}},
+ {0x10d5f, {1|F|D, {0x10d7f}}},
+ {0x10d60, {1|F|D, {0x10d80}}},
+ {0x10d61, {1|F|D, {0x10d81}}},
+ {0x10d62, {1|F|D, {0x10d82}}},
+ {0x10d63, {1|F|D, {0x10d83}}},
+ {0x10d64, {1|F|D, {0x10d84}}},
+ {0x10d65, {1|F|D, {0x10d85}}},
+ {0x118a0, {1|F|D, {0x118c0}}},
+ {0x118a1, {1|F|D, {0x118c1}}},
+ {0x118a2, {1|F|D, {0x118c2}}},
+ {0x118a3, {1|F|D, {0x118c3}}},
+ {0x118a4, {1|F|D, {0x118c4}}},
+ {0x118a5, {1|F|D, {0x118c5}}},
+ {0x118a6, {1|F|D, {0x118c6}}},
+ {0x118a7, {1|F|D, {0x118c7}}},
+ {0x118a8, {1|F|D, {0x118c8}}},
+ {0x118a9, {1|F|D, {0x118c9}}},
+ {0x118aa, {1|F|D, {0x118ca}}},
+ {0x118ab, {1|F|D, {0x118cb}}},
+ {0x118ac, {1|F|D, {0x118cc}}},
+ {0x118ad, {1|F|D, {0x118cd}}},
+ {0x118ae, {1|F|D, {0x118ce}}},
+ {0x118af, {1|F|D, {0x118cf}}},
+ {0x118b0, {1|F|D, {0x118d0}}},
+ {0x118b1, {1|F|D, {0x118d1}}},
+ {0x118b2, {1|F|D, {0x118d2}}},
+ {0x118b3, {1|F|D, {0x118d3}}},
+ {0x118b4, {1|F|D, {0x118d4}}},
+ {0x118b5, {1|F|D, {0x118d5}}},
+ {0x118b6, {1|F|D, {0x118d6}}},
+ {0x118b7, {1|F|D, {0x118d7}}},
+ {0x118b8, {1|F|D, {0x118d8}}},
+ {0x118b9, {1|F|D, {0x118d9}}},
+ {0x118ba, {1|F|D, {0x118da}}},
+ {0x118bb, {1|F|D, {0x118db}}},
+ {0x118bc, {1|F|D, {0x118dc}}},
+ {0x118bd, {1|F|D, {0x118dd}}},
+ {0x118be, {1|F|D, {0x118de}}},
+ {0x118bf, {1|F|D, {0x118df}}},
+ {0x16e40, {1|F|D, {0x16e60}}},
+ {0x16e41, {1|F|D, {0x16e61}}},
+ {0x16e42, {1|F|D, {0x16e62}}},
+ {0x16e43, {1|F|D, {0x16e63}}},
+ {0x16e44, {1|F|D, {0x16e64}}},
+ {0x16e45, {1|F|D, {0x16e65}}},
+ {0x16e46, {1|F|D, {0x16e66}}},
+ {0x16e47, {1|F|D, {0x16e67}}},
+ {0x16e48, {1|F|D, {0x16e68}}},
+ {0x16e49, {1|F|D, {0x16e69}}},
+ {0x16e4a, {1|F|D, {0x16e6a}}},
+ {0x16e4b, {1|F|D, {0x16e6b}}},
+ {0x16e4c, {1|F|D, {0x16e6c}}},
+ {0x16e4d, {1|F|D, {0x16e6d}}},
+ {0x16e4e, {1|F|D, {0x16e6e}}},
+ {0x16e4f, {1|F|D, {0x16e6f}}},
+ {0x16e50, {1|F|D, {0x16e70}}},
+ {0x16e51, {1|F|D, {0x16e71}}},
+ {0x16e52, {1|F|D, {0x16e72}}},
+ {0x16e53, {1|F|D, {0x16e73}}},
+ {0x16e54, {1|F|D, {0x16e74}}},
+ {0x16e55, {1|F|D, {0x16e75}}},
+ {0x16e56, {1|F|D, {0x16e76}}},
+ {0x16e57, {1|F|D, {0x16e77}}},
+ {0x16e58, {1|F|D, {0x16e78}}},
+ {0x16e59, {1|F|D, {0x16e79}}},
+ {0x16e5a, {1|F|D, {0x16e7a}}},
+ {0x16e5b, {1|F|D, {0x16e7b}}},
+ {0x16e5c, {1|F|D, {0x16e7c}}},
+ {0x16e5d, {1|F|D, {0x16e7d}}},
+ {0x16e5e, {1|F|D, {0x16e7e}}},
+ {0x16e5f, {1|F|D, {0x16e7f}}},
+ {0x16ea0, {1|F|D, {0x16ebb}}},
+ {0x16ea1, {1|F|D, {0x16ebc}}},
+ {0x16ea2, {1|F|D, {0x16ebd}}},
+ {0x16ea3, {1|F|D, {0x16ebe}}},
+ {0x16ea4, {1|F|D, {0x16ebf}}},
+ {0x16ea5, {1|F|D, {0x16ec0}}},
+ {0x16ea6, {1|F|D, {0x16ec1}}},
+ {0x16ea7, {1|F|D, {0x16ec2}}},
+ {0x16ea8, {1|F|D, {0x16ec3}}},
+ {0x16ea9, {1|F|D, {0x16ec4}}},
+ {0x16eaa, {1|F|D, {0x16ec5}}},
+ {0x16eab, {1|F|D, {0x16ec6}}},
+ {0x16eac, {1|F|D, {0x16ec7}}},
+ {0x16ead, {1|F|D, {0x16ec8}}},
+ {0x16eae, {1|F|D, {0x16ec9}}},
+ {0x16eaf, {1|F|D, {0x16eca}}},
+ {0x16eb0, {1|F|D, {0x16ecb}}},
+ {0x16eb1, {1|F|D, {0x16ecc}}},
+ {0x16eb2, {1|F|D, {0x16ecd}}},
+ {0x16eb3, {1|F|D, {0x16ece}}},
+ {0x16eb4, {1|F|D, {0x16ecf}}},
+ {0x16eb5, {1|F|D, {0x16ed0}}},
+ {0x16eb6, {1|F|D, {0x16ed1}}},
+ {0x16eb7, {1|F|D, {0x16ed2}}},
+ {0x16eb8, {1|F|D, {0x16ed3}}},
+ {0x1e900, {1|F|D, {0x1e922}}},
+ {0x1e901, {1|F|D, {0x1e923}}},
+ {0x1e902, {1|F|D, {0x1e924}}},
+ {0x1e903, {1|F|D, {0x1e925}}},
+ {0x1e904, {1|F|D, {0x1e926}}},
+ {0x1e905, {1|F|D, {0x1e927}}},
+ {0x1e906, {1|F|D, {0x1e928}}},
+ {0x1e907, {1|F|D, {0x1e929}}},
+ {0x1e908, {1|F|D, {0x1e92a}}},
+ {0x1e909, {1|F|D, {0x1e92b}}},
+ {0x1e90a, {1|F|D, {0x1e92c}}},
+ {0x1e90b, {1|F|D, {0x1e92d}}},
+ {0x1e90c, {1|F|D, {0x1e92e}}},
+ {0x1e90d, {1|F|D, {0x1e92f}}},
+ {0x1e90e, {1|F|D, {0x1e930}}},
+ {0x1e90f, {1|F|D, {0x1e931}}},
+ {0x1e910, {1|F|D, {0x1e932}}},
+ {0x1e911, {1|F|D, {0x1e933}}},
+ {0x1e912, {1|F|D, {0x1e934}}},
+ {0x1e913, {1|F|D, {0x1e935}}},
+ {0x1e914, {1|F|D, {0x1e936}}},
+ {0x1e915, {1|F|D, {0x1e937}}},
+ {0x1e916, {1|F|D, {0x1e938}}},
+ {0x1e917, {1|F|D, {0x1e939}}},
+ {0x1e918, {1|F|D, {0x1e93a}}},
+ {0x1e919, {1|F|D, {0x1e93b}}},
+ {0x1e91a, {1|F|D, {0x1e93c}}},
+ {0x1e91b, {1|F|D, {0x1e93d}}},
+ {0x1e91c, {1|F|D, {0x1e93e}}},
+ {0x1e91d, {1|F|D, {0x1e93f}}},
+ {0x1e91e, {1|F|D, {0x1e940}}},
+ {0x1e91f, {1|F|D, {0x1e941}}},
+ {0x1e920, {1|F|D, {0x1e942}}},
+ {0x1e921, {1|F|D, {0x1e943}}},
+#define CaseFold_Locale (*(CaseFold_11_Type (*)[2])(CaseFold_11_Table+1583))
+ {0x0049, {1|F|D, {0x0069}}},
+ {0x0130, {2|F|D, {0x0069, 0x0307}}},
+};
+
+/* ANSI-C code produced by gperf version 3.1 */
+/* Command-line: gperf -7 -k1,2,3 -F,-1 -c -j1 -i1 -t -T -E -C -H onigenc_unicode_CaseFold_11_hash -N onigenc_unicode_CaseFold_11_lookup -n */
+
+/* maximum key range = 3756, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+/*ARGSUSED*/
+static unsigned int
+onigenc_unicode_CaseFold_11_hash(const OnigCodePoint code)
+{
+ static const unsigned short asso_values[] =
+ {
+ 2, 107, 6, 43, 1, 5, 70, 14, 5, 396,
+ 239, 925, 3763, 3763, 3763, 3763, 3763, 3763, 3763, 3763,
+ 3763, 3763, 3763, 3763, 3763, 45, 404, 3763, 3763, 3763,
+ 3763, 3763, 3763, 400, 3763, 3763, 3763, 3763, 3763, 20,
+ 3763, 3763, 3763, 3763, 3763, 3763, 3763, 3763, 3763, 472,
+ 3763, 3763, 3763, 3763, 3763, 3763, 3763, 163, 3763, 3763,
+ 311, 310, 445, 3, 3763, 3763, 482, 10, 3763, 3763,
+ 3763, 3763, 3763, 604, 3763, 3763, 315, 863, 428, 38,
+ 2198, 226, 42, 182, 240, 94, 1542, 7, 12, 24,
+ 2250, 764, 872, 684, 2182, 168, 1933, 308, 2170, 153,
+ 2106, 108, 1653, 261, 1889, 426, 1851, 484, 470, 506,
+ 2234, 286, 1417, 411, 1461, 366, 1436, 352, 60, 667,
+ 1357, 551, 1110, 611, 1440, 597, 631, 614, 1630, 691,
+ 1762, 821, 1950, 747, 1682, 542, 1752, 740, 1949, 855,
+ 1912, 845, 1840, 1230, 1928, 1106, 1572, 1003, 1323, 1223,
+ 500, 1203, 1783, 1094, 1602, 957, 1472, 1157, 2059, 1188,
+ 2140, 947, 937, 1257, 1395, 1168, 196, 1317, 258, 1246,
+ 141, 1587, 38, 1563, 3, 1663, 53, 1371, 178, 1480,
+ 41, 1745, 57, 1723, 356, 1698, 122, 1609, 77, 1726,
+ 76, 1710, 44, 1740, 2, 1815, 568, 2094, 146, 2214,
+ 340, 2126, 73, 408, 101, 1980, 149
+ };
+ return asso_values[bits_of(code, 2)+79] + asso_values[bits_of(code, 1)] + asso_values[bits_of(code, 0)];
+}
+
+static const CodePointList3 *
+onigenc_unicode_CaseFold_11_lookup(const OnigCodePoint code)
+{
+ enum
+ {
+ MIN_CODE_VALUE = 0x41,
+ MAX_CODE_VALUE = 0x1e921,
+ TOTAL_KEYWORDS = 1585,
+ MIN_WORD_LENGTH = 3,
+ MAX_WORD_LENGTH = 3,
+ MIN_HASH_VALUE = 7,
+ MAX_HASH_VALUE = 3762
+ };
+
+ static const short wordlist[] =
+ {
+ -1, -1, -1, -1, -1, -1,
+ -1,
+ /*0x1ff3*/ 856,
+ -1, -1,
+ /*0x0208*/ 194,
+ -1,
+ /*0x1f88*/ 776,
+ /*0x10408*/ 1284,
+ /*0x0408*/ 305,
+ /*0x0108*/ 61,
+ -1,
+ /*0x1f89*/ 777,
+ /*0x10409*/ 1285,
+ /*0x0409*/ 306,
+ /*0xab88*/ 1182,
+ /*0x2c08*/ 920,
+ -1,
+ /*0x0388*/ 235,
+ -1,
+ /*0xab89*/ 1183,
+ /*0x2c09*/ 921,
+ /*0x020a*/ 195,
+ /*0x0389*/ 236,
+ /*0x1f8a*/ 778,
+ /*0x1040a*/ 1286,
+ /*0x040a*/ 307,
+ /*0x010a*/ 62,
+ /*0x2c88*/ 979,
+ -1, -1, -1,
+ /*0xab8a*/ 1184,
+ /*0x2c0a*/ 922,
+ -1,
+ /*0x038a*/ 237,
+ /*0x0200*/ 190,
+ -1,
+ /*0x1f80*/ 768,
+ /*0x10400*/ 1276,
+ /*0x0400*/ 297,
+ /*0x0100*/ 57,
+ /*0x1f83*/ 771,
+ /*0x10403*/ 1279,
+ /*0x0403*/ 300,
+ /*0x2c8a*/ 980,
+ /*0xab80*/ 1174,
+ /*0x2c00*/ 912,
+ /*0x10c88*/ 1395,
+ /*0x2183*/ 885,
+ /*0xab83*/ 1177,
+ /*0x2c03*/ 915,
+ /*0x0189*/ 126,
+ /*0x10c89*/ 1396,
+ -1,
+ /*0x03f1*/ 288,
+ -1,
+ /*0x1fe7*/ 849,
+ /*0x1e908*/ 1557,
+ /*0x2c80*/ 975,
+ /*0x1fa7*/ 807,
+ /*0x10427*/ 1315,
+ /*0x0427*/ 336,
+ /*0x1e909*/ 1558,
+ /*0x018a*/ 127,
+ /*0x10c8a*/ 1397,
+ /*0x2c67*/ 964,
+ -1,
+ /*0xaba7*/ 1213,
+ /*0x2c27*/ 951,
+ -1,
+ /*0x03a7*/ 263,
+ -1,
+ /*0x1ffb*/ 863,
+ -1,
+ /*0x1e90a*/ 1559,
+ /*0x017b*/ 118,
+ /*0xa780*/ 1107,
+ -1,
+ /*0x10c80*/ 1387,
+ -1, -1, -1,
+ /*0x10c83*/ 1390,
+ /*0x01f1*/ 181,
+ /*0x2c6f*/ 969,
+ /*0x2c6d*/ 967,
+ -1, -1,
+ /*0x1e900*/ 1549,
+ /*0x13fb*/ 527,
+ -1,
+ /*0x0206*/ 193,
+ /*0x1e903*/ 1552,
+ /*0x1f86*/ 774,
+ /*0x10406*/ 1282,
+ /*0x0406*/ 303,
+ /*0x0106*/ 60,
+ /*0x2ced*/ 1026,
+ -1,
+ /*0x01a7*/ 145,
+ /*0x10ca7*/ 1426,
+ /*0xab86*/ 1180,
+ /*0x2c06*/ 918,
+ /*0x017d*/ 119,
+ /*0x0386*/ 234,
+ /*0x0216*/ 201,
+ /*0x00df*/ 56,
+ /*0x1f96*/ 790,
+ /*0x10416*/ 1298,
+ /*0x0416*/ 319,
+ /*0x0116*/ 68,
+ /*0x03fd*/ 294,
+ -1, -1,
+ /*0x2c86*/ 978,
+ /*0xab96*/ 1196,
+ /*0x2c16*/ 934,
+ /*0x13fd*/ 529,
+ /*0x0396*/ 247,
+ -1, -1,
+ /*0x1feb*/ 853,
+ -1, -1, -1, -1, -1, -1,
+ /*0x2c96*/ 986,
+ -1,
+ /*0x2c6b*/ 966,
+ -1,
+ /*0xa786*/ 1110,
+ /*0x0186*/ 124,
+ /*0x10c86*/ 1393,
+ /*0xfb00*/ 1238,
+ -1, -1, -1,
+ /*0xfb03*/ 1241,
+ /*0x1fdb*/ 844,
+ /*0x00dd*/ 54,
+ /*0x2ceb*/ 1025,
+ -1,
+ /*0x1e906*/ 1555,
+ /*0x1ff7*/ 859,
+ /*0xa796*/ 1115,
+ /*0x0196*/ 135,
+ /*0x10c96*/ 1409,
+ -1,
+ /*0x0214*/ 200,
+ /*0x017f*/ 120,
+ /*0x1f94*/ 788,
+ /*0x10414*/ 1296,
+ /*0x0414*/ 317,
+ /*0x0114*/ 67,
+ /*0x03f7*/ 291,
+ /*0x2c7f*/ 974,
+ /*0x1e916*/ 1571,
+ /*0x03ff*/ 296,
+ /*0xab94*/ 1194,
+ /*0x2c14*/ 932,
+ -1,
+ /*0x0394*/ 245,
+ -1,
+ /*0x0210*/ 198,
+ /*0x1c88*/ 538,
+ /*0x1f90*/ 784,
+ /*0x10410*/ 1292,
+ /*0x0410*/ 313,
+ /*0x0110*/ 65,
+ /*0x1c89*/ 539,
+ -1,
+ /*0x2c94*/ 985,
+ -1,
+ /*0xab90*/ 1190,
+ /*0x2c10*/ 928,
+ /*0x1fe3*/ 846,
+ /*0x0390*/ 241,
+ /*0x0204*/ 192,
+ /*0x01db*/ 170,
+ /*0x1f84*/ 772,
+ /*0x10404*/ 1280,
+ /*0x0404*/ 301,
+ /*0x0104*/ 59,
+ /*0x01f7*/ 185,
+ /*0x2c63*/ 962,
+ -1,
+ /*0x2c90*/ 983,
+ /*0xab84*/ 1178,
+ /*0x2c04*/ 916,
+ /*0xfb06*/ 1244,
+ /*0x0194*/ 134,
+ /*0x10c94*/ 1407,
+ /*0x0057*/ 21,
+ /*0x1fd7*/ 840,
+ -1,
+ /*0x1c80*/ 530,
+ -1, -1, -1,
+ /*0x1c83*/ 533,
+ /*0x2c84*/ 977,
+ /*0x1e914*/ 1569,
+ -1,
+ /*0xfb16*/ 1248,
+ /*0xa790*/ 1113,
+ /*0x0190*/ 131,
+ /*0x10c90*/ 1403,
+ -1, -1, -1, -1, -1, -1,
+ /*0x037f*/ 233,
+ -1, -1,
+ /*0x1e910*/ 1565,
+ /*0x1ca7*/ 563,
+ /*0xa784*/ 1109,
+ /*0x0184*/ 123,
+ /*0x10c84*/ 1391,
+ /*0x0202*/ 191,
+ -1,
+ /*0x1f82*/ 770,
+ /*0x10402*/ 1278,
+ /*0x0402*/ 299,
+ /*0x0102*/ 58,
+ -1, -1, -1,
+ /*0x1e904*/ 1553,
+ /*0xab82*/ 1176,
+ /*0x2c02*/ 914,
+ /*0x01d7*/ 168,
+ /*0x10573*/ 1355,
+ -1, -1,
+ /*0x1f85*/ 773,
+ /*0x10405*/ 1281,
+ /*0x0405*/ 302,
+ /*0x0508*/ 425,
+ -1,
+ /*0x00db*/ 52,
+ -1,
+ /*0x2c82*/ 976,
+ /*0xab85*/ 1179,
+ /*0x2c05*/ 917,
+ -1,
+ /*0xfb14*/ 1246,
+ -1, -1,
+ /*0x1c86*/ 536,
+ -1, -1,
+ /*0x0059*/ 23,
+ /*0x1fd9*/ 842,
+ /*0x0218*/ 202,
+ /*0x050a*/ 426,
+ /*0x1f98*/ 792,
+ /*0x10418*/ 1300,
+ /*0x0418*/ 321,
+ /*0x0118*/ 69,
+ /*0xa782*/ 1108,
+ /*0x0182*/ 122,
+ /*0x10c82*/ 1389,
+ /*0x1c96*/ 546,
+ /*0xab98*/ 1198,
+ /*0x2c18*/ 936,
+ -1,
+ /*0x0398*/ 249,
+ -1,
+ /*0x0500*/ 421,
+ -1, -1,
+ /*0x1e902*/ 1551,
+ -1,
+ /*0x10571*/ 1353,
+ /*0xfb04*/ 1242,
+ /*0x10c85*/ 1392,
+ /*0x2c98*/ 987,
+ -1,
+ /*0x0220*/ 206,
+ -1,
+ /*0x1fa0*/ 800,
+ /*0x10420*/ 1308,
+ /*0x0420*/ 329,
+ /*0x0120*/ 73,
+ -1,
+ /*0x1e905*/ 1554,
+ -1, -1,
+ /*0xaba0*/ 1206,
+ /*0x2c20*/ 944,
+ -1,
+ /*0x03a0*/ 257,
+ /*0x01d9*/ 169,
+ -1,
+ /*0xa798*/ 1116,
+ /*0x0198*/ 137,
+ /*0x10c98*/ 1411,
+ -1, -1, -1,
+ /*0x0212*/ 199,
+ /*0x2ca0*/ 991,
+ /*0x1f92*/ 786,
+ /*0x10412*/ 1294,
+ /*0x0412*/ 315,
+ /*0x0112*/ 66,
+ /*0x1e918*/ 1573,
+ /*0x1c94*/ 544,
+ /*0x1e88*/ 654,
+ /*0x1e08*/ 590,
+ /*0xab92*/ 1192,
+ /*0x2c12*/ 930,
+ -1,
+ /*0x0392*/ 243,
+ -1, -1, -1, -1,
+ /*0xfb02*/ 1240,
+ /*0xa7a0*/ 1120,
+ /*0x01a0*/ 141,
+ /*0x10ca0*/ 1419,
+ /*0x1c90*/ 540,
+ /*0x2c92*/ 984,
+ /*0x0506*/ 424,
+ /*0x1e8a*/ 655,
+ /*0x1e0a*/ 591,
+ -1, -1, -1,
+ /*0x1057d*/ 1364,
+ /*0x1e920*/ 1581,
+ /*0xfb05*/ 1243,
+ -1,
+ /*0x1ff9*/ 861,
+ -1,
+ /*0x1c84*/ 534,
+ /*0x0179*/ 117,
+ /*0x0516*/ 432,
+ /*0x1e80*/ 650,
+ /*0x1e00*/ 586,
+ /*0xa792*/ 1114,
+ -1,
+ /*0x10c92*/ 1405,
+ /*0x0226*/ 209,
+ /*0x03f9*/ 292,
+ /*0x1fa6*/ 806,
+ /*0x10426*/ 1314,
+ /*0x0426*/ 335,
+ /*0x0126*/ 76,
+ /*0x1fe9*/ 851,
+ /*0x13f9*/ 525,
+ -1,
+ /*0x1e912*/ 1567,
+ /*0xaba6*/ 1212,
+ /*0x2c26*/ 950,
+ /*0x00d9*/ 50,
+ /*0x03a6*/ 262,
+ /*0x0224*/ 208,
+ /*0x2c69*/ 965,
+ /*0x1fa4*/ 804,
+ /*0x10424*/ 1312,
+ /*0x0424*/ 333,
+ /*0x0124*/ 75,
+ -1, -1, -1,
+ /*0x2ca6*/ 994,
+ /*0xaba4*/ 1210,
+ /*0x2c24*/ 948,
+ -1,
+ /*0x03a4*/ 260,
+ -1, -1, -1,
+ /*0x10577*/ 1359,
+ -1, -1,
+ /*0x1057f*/ 1366,
+ -1,
+ /*0x1c82*/ 532,
+ /*0x2ca4*/ 993,
+ -1,
+ /*0x0514*/ 431,
+ -1,
+ /*0xa7a6*/ 1123,
+ /*0x01a6*/ 144,
+ /*0x10ca6*/ 1425,
+ -1, -1, -1, -1, -1, -1,
+ /*0x1c85*/ 535,
+ /*0x1e86*/ 653,
+ /*0x1e06*/ 589,
+ /*0x10d5f*/ 1453,
+ /*0x0510*/ 429,
+ /*0xa7a4*/ 1122,
+ /*0x01a4*/ 143,
+ /*0x10ca4*/ 1423,
+ /*0x1ffc*/ 864,
+ /*0x0222*/ 207,
+ /*0x047c*/ 359,
+ /*0x1fa2*/ 802,
+ /*0x10422*/ 1310,
+ /*0x0422*/ 331,
+ /*0x0122*/ 74,
+ /*0x1e96*/ 661,
+ /*0x1e16*/ 597,
+ /*0x048a*/ 362,
+ /*0x0504*/ 423,
+ /*0xaba2*/ 1208,
+ /*0x2c22*/ 946,
+ /*0x1c98*/ 548,
+ -1, -1,
+ /*0x021a*/ 203,
+ /*0x13fc*/ 528,
+ /*0x1f9a*/ 794,
+ /*0x1041a*/ 1302,
+ /*0x041a*/ 323,
+ /*0x011a*/ 70,
+ -1,
+ /*0x0480*/ 361,
+ /*0x2ca2*/ 992,
+ -1,
+ /*0xab9a*/ 1200,
+ /*0x2c1a*/ 938,
+ -1,
+ /*0x039a*/ 251,
+ /*0x10d5d*/ 1451,
+ -1, -1,
+ /*0x10d65*/ 1459,
+ -1, -1, -1,
+ /*0x1f5f*/ 759,
+ /*0x1ca0*/ 556,
+ /*0x2c9a*/ 988,
+ /*0x01fc*/ 188,
+ /*0x1f08*/ 716,
+ /*0xa7a2*/ 1121,
+ /*0x01a2*/ 142,
+ /*0x10ca2*/ 1421,
+ /*0x10d61*/ 1455,
+ /*0x1f09*/ 717,
+ -1, -1,
+ /*0x10a7*/ 491,
+ -1, -1,
+ /*0x1e94*/ 660,
+ /*0x1e14*/ 596,
+ /*0x0502*/ 422,
+ -1, -1,
+ /*0xa79a*/ 1117,
+ /*0x1f0a*/ 718,
+ /*0x10c9a*/ 1413,
+ /*0x1c92*/ 542,
+ -1,
+ /*0x1f9d*/ 797,
+ /*0x1041d*/ 1305,
+ /*0x041d*/ 326,
+ -1, -1,
+ /*0x1e90*/ 658,
+ /*0x1e10*/ 594,
+ /*0x1e91a*/ 1575,
+ /*0xab9d*/ 1203,
+ /*0x2c1d*/ 941,
+ /*0x1f5d*/ 758,
+ /*0x039d*/ 254,
+ /*0x021c*/ 204,
+ -1,
+ /*0x1f9c*/ 796,
+ /*0x1041c*/ 1304,
+ /*0x041c*/ 325,
+ /*0x011c*/ 71,
+ -1,
+ /*0x1e84*/ 652,
+ /*0x1e04*/ 588,
+ -1,
+ /*0xab9c*/ 1202,
+ /*0x2c1c*/ 940,
+ -1,
+ /*0x039c*/ 253,
+ -1,
+ /*0x0518*/ 433,
+ -1,
+ /*0x0047*/ 6,
+ /*0x1fc7*/ 831,
+ /*0x0496*/ 368,
+ /*0xa77b*/ 1104,
+ /*0x0147*/ 91,
+ /*0x021e*/ 205,
+ /*0x2c9c*/ 989,
+ /*0x1f9e*/ 798,
+ /*0x1041e*/ 1306,
+ /*0x041e*/ 327,
+ /*0x011e*/ 72,
+ /*0x019d*/ 139,
+ /*0x10c9d*/ 1416,
+ /*0x1ca6*/ 562,
+ -1,
+ /*0xab9e*/ 1204,
+ /*0x2c1e*/ 942,
+ -1,
+ /*0x039e*/ 255,
+ /*0x1f6f*/ 767,
+ /*0x1f6d*/ 765,
+ /*0x2165*/ 874,
+ /*0x1e91d*/ 1578,
+ /*0x0520*/ 437,
+ /*0xa79c*/ 1118,
+ /*0x019c*/ 138,
+ /*0x10c9c*/ 1415,
+ /*0x1ca4*/ 560,
+ /*0x2c9e*/ 990,
+ /*0x118a7*/ 1467,
+ -1,
+ /*0xa77d*/ 1105,
+ -1,
+ /*0x2161*/ 870,
+ /*0x1e82*/ 651,
+ /*0x1e02*/ 587,
+ /*0x1e91c*/ 1577,
+ /*0x2167*/ 876,
+ -1, -1,
+ /*0xa7c7*/ 1145,
+ /*0x01c7*/ 159,
+ /*0x10d5b*/ 1449,
+ /*0x1fb8*/ 821,
+ -1,
+ /*0x0512*/ 430,
+ /*0xa79e*/ 1119,
+ /*0x0494*/ 367,
+ /*0x10c9e*/ 1417,
+ -1,
+ /*0x022a*/ 211,
+ /*0xabb8*/ 1230,
+ /*0x1faa*/ 810,
+ -1,
+ /*0x042a*/ 339,
+ /*0x012a*/ 78,
+ /*0x216f*/ 884,
+ /*0x216d*/ 882,
+ /*0x1e91e*/ 1579,
+ -1,
+ /*0xabaa*/ 1216,
+ /*0x2c2a*/ 954,
+ /*0x0490*/ 365,
+ /*0x03aa*/ 266,
+ /*0x2cb8*/ 1003,
+ /*0x1f6b*/ 763,
+ -1, -1, -1,
+ /*0x1e98*/ 663,
+ /*0x1e18*/ 598,
+ -1,
+ /*0x1ca2*/ 558,
+ /*0x2caa*/ 996,
+ -1, -1,
+ /*0x10579*/ 1361,
+ -1,
+ /*0x2c75*/ 972,
+ /*0x10d63*/ 1457,
+ /*0x03f5*/ 290,
+ -1,
+ /*0xa7b8*/ 1136,
+ /*0x01b8*/ 155,
+ /*0x1f5b*/ 757,
+ -1, -1,
+ /*0x1c9a*/ 550,
+ -1,
+ /*0x0526*/ 440,
+ -1,
+ /*0xa7aa*/ 1125,
+ -1,
+ /*0x10caa*/ 1429,
+ /*0x1ea0*/ 668,
+ /*0x1e20*/ 602,
+ /*0x022e*/ 213,
+ /*0x10d57*/ 1445,
+ /*0x1fae*/ 814,
+ -1,
+ /*0x042e*/ 343,
+ /*0x012e*/ 80,
+ /*0x216b*/ 880,
+ /*0x0524*/ 439,
+ -1,
+ /*0x00c7*/ 33,
+ /*0xabae*/ 1220,
+ /*0x2c2e*/ 958,
+ /*0xa7f5*/ 1157,
+ -1,
+ /*0x022c*/ 212,
+ -1,
+ /*0x1fac*/ 812,
+ /*0x0230*/ 214,
+ /*0x042c*/ 341,
+ /*0x012c*/ 79,
+ /*0x1e92*/ 659,
+ /*0x1e12*/ 595,
+ /*0x0130*/ 1584,
+ /*0x2cae*/ 998,
+ /*0xabac*/ 1218,
+ /*0x2c2c*/ 956,
+ -1,
+ /*0xabb0*/ 1222,
+ -1, -1,
+ /*0x03b0*/ 268,
+ -1, -1, -1, -1,
+ /*0x1c9d*/ 553,
+ /*0x1faf*/ 815,
+ /*0x2cac*/ 997,
+ /*0x042f*/ 344,
+ -1,
+ /*0x2cb0*/ 999,
+ /*0xa7ae*/ 1129,
+ /*0x01ae*/ 148,
+ /*0x10cae*/ 1433,
+ /*0xabaf*/ 1221,
+ /*0x2c2f*/ 959,
+ -1, -1,
+ /*0x1057c*/ 1363,
+ /*0x1c9c*/ 552,
+ -1, -1,
+ /*0x0522*/ 438,
+ -1, -1,
+ /*0xa7ac*/ 1127,
+ /*0x01ac*/ 147,
+ /*0x10cac*/ 1431,
+ /*0xa7b0*/ 1130,
+ /*0x0498*/ 369,
+ /*0x10cb0*/ 1435,
+ -1,
+ /*0x2163*/ 872,
+ /*0x10d59*/ 1447,
+ /*0x1ea6*/ 671,
+ /*0x1e26*/ 605,
+ -1,
+ /*0x051a*/ 434,
+ -1, -1,
+ /*0x0228*/ 210,
+ /*0x1c9e*/ 554,
+ /*0x1fa8*/ 808,
+ -1,
+ /*0x0428*/ 337,
+ /*0x0128*/ 77,
+ /*0x01af*/ 149,
+ /*0x10caf*/ 1434,
+ /*0x1ea4*/ 670,
+ /*0x1e24*/ 604,
+ /*0xaba8*/ 1214,
+ /*0x2c28*/ 952,
+ -1,
+ /*0x03a8*/ 264,
+ /*0x04a0*/ 373,
+ -1, -1,
+ /*0x020e*/ 197,
+ /*0x10a0*/ 484,
+ /*0x1f8e*/ 782,
+ /*0x1040e*/ 1290,
+ /*0x040e*/ 311,
+ /*0x010e*/ 64,
+ /*0x2ca8*/ 995,
+ /*0x0232*/ 215,
+ -1,
+ /*0x1fb2*/ 816,
+ /*0xab8e*/ 1188,
+ /*0x2c0e*/ 926,
+ /*0x0132*/ 81,
+ /*0x038e*/ 239,
+ -1, -1, -1,
+ /*0xabb2*/ 1224,
+ /*0x1f59*/ 756,
+ /*0x0492*/ 366,
+ /*0x1cb8*/ 580,
+ /*0x1f18*/ 724,
+ -1,
+ /*0x2c8e*/ 982,
+ /*0xa7a8*/ 1124,
+ -1,
+ /*0x10ca8*/ 1427,
+ -1, -1,
+ /*0x1caa*/ 566,
+ /*0x2cb2*/ 1000,
+ -1, -1,
+ /*0x1efc*/ 714,
+ /*0x1e7c*/ 648,
+ -1,
+ /*0x1ea2*/ 669,
+ /*0x1e22*/ 603,
+ /*0x051c*/ 435,
+ -1, -1, -1,
+ /*0x018e*/ 129,
+ /*0x10c8e*/ 1401,
+ -1, -1, -1,
+ /*0xff27*/ 1256,
+ /*0xa7b2*/ 1132,
+ /*0x01b2*/ 151,
+ /*0x10cb2*/ 1437,
+ /*0x1e9a*/ 665,
+ /*0x1e1a*/ 599,
+ /*0x1e90e*/ 1563,
+ /*0x0547*/ 467,
+ -1,
+ /*0x023a*/ 216,
+ -1,
+ /*0x1fba*/ 823,
+ -1,
+ /*0x051e*/ 436,
+ -1,
+ /*0x16ea7*/ 1531,
+ /*0x04a6*/ 376,
+ -1,
+ /*0x1fb6*/ 819,
+ /*0xabba*/ 1232,
+ /*0x10a6*/ 490,
+ /*0x0136*/ 83,
+ -1, -1, -1,
+ /*0x118a0*/ 1460,
+ /*0xabb6*/ 1228,
+ -1,
+ /*0x1cae*/ 570,
+ -1,
+ /*0x04a4*/ 375,
+ -1,
+ /*0x2cba*/ 1004,
+ /*0x020c*/ 196,
+ /*0x10a4*/ 488,
+ /*0x1f8c*/ 780,
+ /*0x1040c*/ 1288,
+ /*0x040c*/ 309,
+ /*0x010c*/ 63,
+ /*0x2cb6*/ 1002,
+ /*0xa779*/ 1103,
+ -1,
+ /*0x1cac*/ 568,
+ /*0xab8c*/ 1186,
+ /*0x2c0c*/ 924,
+ /*0x1cb0*/ 572,
+ /*0x038c*/ 238,
+ -1, -1,
+ /*0x0538*/ 452,
+ /*0xa7ba*/ 1137,
+ -1,
+ /*0xa726*/ 1067,
+ -1, -1, -1,
+ /*0x2c8c*/ 981,
+ /*0xa7b6*/ 1135,
+ /*0x052a*/ 442,
+ -1, -1, -1,
+ /*0x1caf*/ 571,
+ /*0x1e1c*/ 600,
+ -1, -1,
+ /*0xa724*/ 1066,
+ -1, -1,
+ /*0x1f69*/ 761,
+ -1, -1,
+ /*0x04fc*/ 419,
+ -1,
+ /*0x10575*/ 1357,
+ /*0x04a2*/ 374,
+ /*0x10c8c*/ 1399,
+ -1, -1,
+ /*0x10a2*/ 486,
+ -1, -1, -1, -1,
+ /*0x1e9e*/ 667,
+ /*0x1e1e*/ 601,
+ /*0x1e90c*/ 1561,
+ -1, -1, -1,
+ /*0x049a*/ 370,
+ /*0x118a6*/ 1466,
+ /*0x1fb4*/ 818,
+ -1, -1,
+ /*0x0134*/ 82,
+ -1, -1,
+ /*0x1ca8*/ 564,
+ -1,
+ /*0xabb4*/ 1226,
+ -1,
+ /*0x2126*/ 865,
+ -1,
+ /*0x052e*/ 444,
+ /*0x118a4*/ 1464,
+ /*0x2169*/ 878,
+ -1, -1, -1, -1,
+ /*0xa722*/ 1065,
+ -1,
+ /*0x2cb4*/ 1001,
+ /*0x023e*/ 219,
+ -1,
+ /*0x1fbe*/ 826,
+ -1,
+ /*0x052c*/ 443,
+ -1,
+ /*0x1eb8*/ 680,
+ /*0x1e38*/ 614,
+ /*0x1cb2*/ 574,
+ -1,
+ /*0xabbe*/ 1236,
+ -1,
+ /*0x1fbc*/ 825,
+ -1, -1,
+ /*0x1eaa*/ 673,
+ /*0x1e2a*/ 607,
+ /*0xa7b4*/ 1134,
+ -1, -1,
+ /*0xabbc*/ 1234,
+ -1, -1,
+ /*0x2cbe*/ 1006,
+ -1,
+ /*0x1f1a*/ 726,
+ -1, -1,
+ /*0xa688*/ 1055,
+ /*0x1f8d*/ 781,
+ /*0x1040d*/ 1289,
+ /*0x040d*/ 310,
+ /*0x16e5f*/ 1523,
+ /*0x2cbc*/ 1005,
+ /*0x049c*/ 371,
+ -1,
+ /*0x118a2*/ 1462,
+ /*0xab8d*/ 1187,
+ /*0x2c0d*/ 925,
+ -1, -1,
+ /*0xa7be*/ 1139,
+ -1, -1, -1,
+ /*0xa68a*/ 1056,
+ -1, -1, -1,
+ /*0x104c7*/ 1339,
+ /*0x04c7*/ 393,
+ /*0xa7bc*/ 1138,
+ /*0x01bc*/ 156,
+ -1,
+ /*0x10c7*/ 522,
+ -1,
+ /*0x049e*/ 372,
+ /*0x1cba*/ 582,
+ -1,
+ /*0xa680*/ 1051,
+ /*0x0528*/ 441,
+ /*0x1eae*/ 675,
+ /*0x1e2e*/ 609,
+ -1,
+ /*0x1cb6*/ 578,
+ -1, -1,
+ /*0x16e5d*/ 1521,
+ /*0xa78d*/ 1112,
+ /*0x1f1d*/ 729,
+ /*0x10c8d*/ 1400,
+ -1, -1, -1, -1,
+ /*0x1eac*/ 674,
+ /*0x1e2c*/ 608,
+ /*0x050e*/ 428,
+ /*0x1eb0*/ 676,
+ /*0x1e30*/ 610,
+ /*0x1e90d*/ 1562,
+ -1, -1,
+ /*0x1f1c*/ 728,
+ /*0x0532*/ 446,
+ /*0x10588*/ 1375,
+ -1, -1, -1, -1,
+ /*0x10589*/ 1376,
+ /*0x104b8*/ 1324,
+ /*0x04b8*/ 385,
+ /*0x0053*/ 17,
+ /*0x1fd3*/ 838,
+ -1,
+ /*0x10b8*/ 508,
+ -1, -1, -1, -1,
+ /*0x04aa*/ 378,
+ /*0x1058a*/ 1377,
+ /*0x0052*/ 16,
+ /*0x1fd2*/ 837,
+ /*0x10aa*/ 494,
+ -1,
+ /*0x0152*/ 97,
+ -1, -1, -1, -1,
+ /*0x024c*/ 227,
+ /*0x004c*/ 10,
+ /*0x1fcc*/ 836,
+ /*0xa686*/ 1054,
+ /*0x10580*/ 1367,
+ /*0x014c*/ 94,
+ -1, -1,
+ /*0x10583*/ 1370,
+ -1, -1, -1, -1,
+ /*0x2cd2*/ 1016,
+ -1,
+ /*0x16ea0*/ 1524,
+ /*0xa738*/ 1075,
+ /*0xa696*/ 1062,
+ -1,
+ /*0x1ea8*/ 672,
+ /*0x1e28*/ 606,
+ /*0x053a*/ 454,
+ /*0x01d3*/ 166,
+ /*0x2ccc*/ 1013,
+ -1,
+ /*0xa72a*/ 1069,
+ /*0x1cb4*/ 576,
+ -1,
+ /*0x0536*/ 450,
+ /*0x1f38*/ 738,
+ -1,
+ /*0xa7d2*/ 1151,
+ -1, -1, -1,
+ /*0x04ae*/ 380,
+ /*0x1e8e*/ 657,
+ /*0x1e0e*/ 593,
+ /*0x1f2a*/ 732,
+ /*0x10ae*/ 498,
+ -1,
+ /*0xa7cc*/ 1148,
+ -1,
+ /*0x1eb2*/ 677,
+ /*0x1e32*/ 611,
+ /*0x050c*/ 427,
+ /*0x0244*/ 222,
+ /*0x0044*/ 3,
+ /*0x1fc4*/ 829,
+ /*0x04ac*/ 379,
+ /*0x1cbe*/ 584,
+ /*0x104b0*/ 1316,
+ /*0x04b0*/ 381,
+ /*0x10ac*/ 496,
+ -1,
+ /*0x118b8*/ 1484,
+ /*0x10b0*/ 500,
+ -1,
+ /*0x16e5b*/ 1519,
+ -1,
+ /*0x10586*/ 1373,
+ -1,
+ /*0xa694*/ 1061,
+ -1,
+ /*0x118aa*/ 1470,
+ -1,
+ /*0xff26*/ 1255,
+ -1, -1,
+ /*0x2cc4*/ 1009,
+ -1,
+ /*0xa72e*/ 1071,
+ -1,
+ /*0x10af*/ 499,
+ -1,
+ /*0x212a*/ 866,
+ -1,
+ /*0xa690*/ 1059,
+ -1, -1,
+ /*0xff24*/ 1253,
+ /*0x16ea6*/ 1530,
+ -1, -1,
+ /*0x1f2e*/ 736,
+ /*0xa72c*/ 1070,
+ /*0x00d3*/ 45,
+ /*0xa7c4*/ 1142,
+ /*0x01c4*/ 157,
+ -1, -1,
+ /*0xa684*/ 1053,
+ /*0x1eba*/ 681,
+ /*0x1e3a*/ 615,
+ -1,
+ /*0x16ea4*/ 1528,
+ /*0x00d2*/ 44,
+ -1,
+ /*0x1f2c*/ 734,
+ /*0x1eb6*/ 679,
+ /*0x1e36*/ 613,
+ -1,
+ /*0x0534*/ 448,
+ -1, -1,
+ /*0x04a8*/ 377,
+ /*0x00cc*/ 38,
+ -1, -1,
+ /*0x10a8*/ 492,
+ /*0x118ae*/ 1474,
+ -1, -1,
+ /*0x16e57*/ 1515,
+ -1, -1,
+ /*0x1e8c*/ 656,
+ /*0x1e0c*/ 592,
+ /*0x1f2f*/ 737,
+ /*0x10594*/ 1385,
+ -1, -1,
+ /*0x048e*/ 364,
+ -1,
+ /*0x118ac*/ 1472,
+ /*0xff22*/ 1251,
+ /*0x053e*/ 458,
+ /*0x118b0*/ 1476,
+ /*0x104b2*/ 1318,
+ /*0x04b2*/ 382,
+ -1, -1, -1,
+ /*0x10b2*/ 502,
+ /*0x10590*/ 1382,
+ /*0xa682*/ 1052,
+ /*0x053c*/ 456,
+ /*0x024a*/ 226,
+ /*0x004a*/ 8,
+ /*0x1fca*/ 834,
+ /*0x16ea2*/ 1526,
+ /*0xa728*/ 1068,
+ /*0x014a*/ 93,
+ -1,
+ /*0x118af*/ 1475,
+ -1,
+ /*0x24c7*/ 903,
+ -1,
+ /*0x10584*/ 1371,
+ -1,
+ /*0x0042*/ 1,
+ /*0x1fc2*/ 827,
+ /*0x00c4*/ 30,
+ -1,
+ /*0x1f28*/ 730,
+ /*0x1fab*/ 811,
+ -1,
+ /*0x042b*/ 340,
+ -1, -1,
+ /*0x2cca*/ 1012,
+ -1,
+ /*0x03c2*/ 269,
+ /*0xabab*/ 1217,
+ /*0x2c2b*/ 955,
+ /*0xa732*/ 1072,
+ /*0x03ab*/ 267,
+ -1, -1, -1,
+ /*0xa698*/ 1063,
+ /*0x1f0e*/ 722,
+ /*0x2cc2*/ 1008,
+ /*0x1eb4*/ 678,
+ /*0x1e34*/ 612,
+ /*0x16e59*/ 1517,
+ -1,
+ /*0x104ba*/ 1326,
+ /*0x04ba*/ 386,
+ /*0x01ca*/ 161,
+ /*0x118a8*/ 1468,
+ -1,
+ /*0x10ba*/ 510,
+ -1,
+ /*0x104b6*/ 1322,
+ /*0x04b6*/ 384,
+ -1, -1,
+ /*0x24b8*/ 888,
+ /*0x10b6*/ 506,
+ /*0xa7c2*/ 1141,
+ -1,
+ /*0x10582*/ 1369,
+ -1,
+ /*0xa7ab*/ 1126,
+ -1,
+ /*0x10cab*/ 1430,
+ /*0x1ebe*/ 683,
+ /*0x1e3e*/ 617,
+ -1,
+ /*0x024e*/ 228,
+ /*0x004e*/ 12,
+ /*0x048c*/ 363,
+ -1,
+ /*0x118b2*/ 1478,
+ /*0x014e*/ 95,
+ /*0x10585*/ 1372,
+ /*0x1ebc*/ 682,
+ /*0x1e3c*/ 616,
+ -1, -1, -1,
+ /*0x0056*/ 20,
+ /*0x1fd6*/ 839,
+ /*0xa73a*/ 1076,
+ /*0x2132*/ 868,
+ /*0x0156*/ 99,
+ /*0xa692*/ 1060,
+ /*0x0553*/ 479,
+ -1, -1,
+ /*0xa736*/ 1074,
+ -1,
+ /*0x2cce*/ 1014,
+ /*0x03d6*/ 274,
+ -1, -1,
+ /*0x1f3a*/ 740,
+ /*0x0552*/ 478,
+ -1, -1, -1,
+ /*0x0050*/ 14,
+ -1,
+ /*0x2cd6*/ 1018,
+ -1,
+ /*0x0150*/ 96,
+ -1,
+ /*0x054c*/ 472,
+ -1, -1,
+ /*0xa7ce*/ 1149,
+ -1,
+ /*0x00ca*/ 36,
+ /*0x03d0*/ 271,
+ -1,
+ /*0x0248*/ 225,
+ /*0x0048*/ 7,
+ /*0x1fc8*/ 832,
+ -1, -1,
+ /*0x1f0c*/ 720,
+ /*0xa7d6*/ 1153,
+ /*0x118ba*/ 1486,
+ /*0x2cd0*/ 1015,
+ /*0x00c2*/ 28,
+ /*0xff38*/ 1273,
+ -1,
+ /*0x104b4*/ 1320,
+ /*0x04b4*/ 383,
+ /*0x118b6*/ 1482,
+ -1, -1,
+ /*0x10b4*/ 504,
+ -1,
+ /*0xff2a*/ 1259,
+ /*0x0246*/ 224,
+ /*0x0046*/ 5,
+ /*0x1fc6*/ 830,
+ /*0x2cc8*/ 1011,
+ -1,
+ /*0x16eb8*/ 1548,
+ /*0xa7d0*/ 1150,
+ -1,
+ /*0x10592*/ 1384,
+ -1, -1, -1, -1, -1,
+ /*0x16eaa*/ 1534,
+ -1,
+ /*0x104be*/ 1330,
+ /*0x04be*/ 388,
+ /*0x0544*/ 464,
+ -1, -1,
+ /*0x10be*/ 514,
+ /*0x01c8*/ 160,
+ /*0x2cc6*/ 1010,
+ /*0x005a*/ 24,
+ /*0x1fda*/ 843,
+ /*0x104bc*/ 1328,
+ /*0x04bc*/ 387,
+ /*0x015a*/ 101,
+ /*0xa734*/ 1073,
+ /*0x2cc0*/ 1007,
+ /*0x10bc*/ 512,
+ -1,
+ /*0x1ed2*/ 693,
+ /*0x1e52*/ 627,
+ /*0x0054*/ 18,
+ /*0x03da*/ 276,
+ -1, -1,
+ /*0x0154*/ 98,
+ /*0x00ce*/ 40,
+ /*0xa7c6*/ 1144,
+ /*0xa652*/ 1037,
+ /*0x1ecc*/ 690,
+ /*0x1e4c*/ 624,
+ /*0xff2e*/ 1263,
+ /*0x2cda*/ 1020,
+ -1,
+ /*0xa7c0*/ 1140,
+ /*0x1cab*/ 567,
+ -1,
+ /*0x00d6*/ 48,
+ /*0xa64c*/ 1034,
+ /*0xa73e*/ 1078,
+ -1, -1, -1,
+ /*0x2cd4*/ 1017,
+ -1,
+ /*0xff2c*/ 1261,
+ /*0x16eae*/ 1538,
+ -1,
+ /*0xff30*/ 1265,
+ /*0xa73c*/ 1077,
+ /*0xa7da*/ 1155,
+ -1,
+ /*0x1f3e*/ 744,
+ -1,
+ /*0x118b4*/ 1480,
+ /*0xa69a*/ 1064,
+ -1,
+ /*0x00d0*/ 42,
+ -1, -1,
+ /*0x16eac*/ 1536,
+ /*0xa7d4*/ 1152,
+ /*0x1f3c*/ 742,
+ /*0x16eb0*/ 1540,
+ -1,
+ /*0xff2f*/ 1264,
+ -1, -1, -1, -1, -1, -1,
+ /*0x00c8*/ 34,
+ -1, -1,
+ /*0x1ec4*/ 686,
+ /*0x1e44*/ 620,
+ -1,
+ /*0x118be*/ 1490,
+ /*0x1f0d*/ 721,
+ /*0x16eaf*/ 1539,
+ /*0x0058*/ 22,
+ /*0x1fd8*/ 841,
+ -1,
+ /*0xa644*/ 1030,
+ /*0x0158*/ 100,
+ /*0x0245*/ 223,
+ /*0x0045*/ 4,
+ /*0x118bc*/ 1488,
+ -1, -1,
+ /*0x0145*/ 90,
+ /*0x00c6*/ 32,
+ /*0x03d8*/ 275,
+ /*0x104d3*/ 1351,
+ /*0x054a*/ 470,
+ -1, -1, -1,
+ /*0x00c0*/ 26,
+ -1,
+ /*0xff28*/ 1257,
+ /*0x10d53*/ 1441,
+ /*0x2cd8*/ 1019,
+ /*0x104d2*/ 1350,
+ /*0x04d2*/ 398,
+ /*0x24ba*/ 890,
+ /*0x0542*/ 462,
+ -1, -1, -1, -1,
+ /*0x10d52*/ 1440,
+ /*0x24b6*/ 886,
+ /*0x104cc*/ 1344,
+ /*0x00da*/ 51,
+ /*0x16ea8*/ 1532,
+ -1, -1, -1, -1,
+ /*0xa7d8*/ 1154,
+ /*0x1fa9*/ 809,
+ -1,
+ /*0x0429*/ 338,
+ /*0xff32*/ 1267,
+ /*0x00d4*/ 46,
+ /*0xa7c5*/ 1143,
+ /*0x01c5*/ 158,
+ -1,
+ /*0xaba9*/ 1215,
+ /*0x2c29*/ 953,
+ -1,
+ /*0x03a9*/ 265,
+ -1, -1,
+ /*0x1fe2*/ 845,
+ /*0x16e47*/ 1499,
+ /*0x0462*/ 346,
+ /*0x0162*/ 105,
+ /*0x16eb2*/ 1542,
+ /*0xa752*/ 1088,
+ -1, -1, -1,
+ /*0x2c62*/ 961,
+ -1,
+ /*0x03e2*/ 280,
+ -1, -1, -1,
+ /*0xa74c*/ 1085,
+ -1, -1,
+ /*0x1f52*/ 753,
+ /*0x0345*/ 229,
+ -1,
+ /*0x2ce2*/ 1024,
+ /*0x054e*/ 474,
+ /*0x0055*/ 19,
+ /*0x104c4*/ 1336,
+ -1,
+ /*0x01a9*/ 146,
+ /*0x10ca9*/ 1428,
+ /*0x1f4c*/ 750,
+ /*0x10c4*/ 520,
+ /*0x1eca*/ 689,
+ /*0x1e4a*/ 623,
+ -1,
+ /*0x0556*/ 482,
+ -1,
+ /*0x03d5*/ 273,
+ -1, -1,
+ /*0xff3a*/ 1275,
+ /*0xa64a*/ 1033,
+ /*0x01e2*/ 173,
+ -1,
+ /*0x1ec2*/ 685,
+ /*0x1e42*/ 619,
+ -1,
+ /*0xff36*/ 1271,
+ /*0x1fa1*/ 801,
+ /*0x10421*/ 1309,
+ /*0x0421*/ 330,
+ -1,
+ /*0x00d8*/ 49,
+ /*0xa642*/ 1029,
+ -1,
+ /*0x0550*/ 476,
+ /*0xaba1*/ 1207,
+ /*0x2c21*/ 945,
+ /*0x00c5*/ 31,
+ /*0x03a1*/ 258,
+ -1, -1,
+ /*0x16eb6*/ 1546,
+ /*0xa744*/ 1081,
+ -1, -1,
+ /*0x01d5*/ 167,
+ /*0x1fa5*/ 805,
+ /*0x10425*/ 1313,
+ /*0x0425*/ 334,
+ /*0x0548*/ 468,
+ /*0x1fad*/ 813,
+ -1,
+ /*0x042d*/ 342,
+ -1,
+ /*0xaba5*/ 1211,
+ /*0x2c25*/ 949,
+ /*0x24be*/ 894,
+ /*0x03a5*/ 261,
+ /*0xabad*/ 1219,
+ /*0x2c2d*/ 957,
+ -1, -1, -1, -1, -1, -1,
+ /*0x24bc*/ 892,
+ -1,
+ /*0x10ca1*/ 1420,
+ /*0x0546*/ 466,
+ -1,
+ /*0x1fa3*/ 803,
+ /*0x10423*/ 1311,
+ /*0x0423*/ 332,
+ /*0x1ece*/ 691,
+ /*0x1e4e*/ 625,
+ /*0x0540*/ 460,
+ -1,
+ /*0x1e921*/ 1582,
+ /*0xaba3*/ 1209,
+ /*0x2c23*/ 947,
+ /*0x004d*/ 11,
+ /*0x03a3*/ 259,
+ /*0xa64e*/ 1035,
+ -1,
+ /*0x1ed6*/ 695,
+ /*0x1e56*/ 629,
+ /*0x10ca5*/ 1424,
+ -1,
+ /*0xa7ad*/ 1128,
+ /*0x1fe4*/ 847,
+ /*0x10cad*/ 1432,
+ /*0x0464*/ 347,
+ /*0x0164*/ 106,
+ /*0xa656*/ 1039,
+ -1,
+ /*0x104ca*/ 1342,
+ -1, -1,
+ /*0x2c64*/ 963,
+ /*0xff34*/ 1269,
+ /*0x03e4*/ 281,
+ -1,
+ /*0x0554*/ 480,
+ -1,
+ /*0x1ed0*/ 692,
+ /*0x1e50*/ 626,
+ -1,
+ /*0x104c2*/ 1334,
+ /*0x00d5*/ 47,
+ -1, -1,
+ /*0x10ca3*/ 1422,
+ /*0x10c2*/ 518,
+ /*0xa650*/ 1036,
+ /*0x16eb4*/ 1544,
+ -1,
+ /*0x10ab*/ 495,
+ -1, -1,
+ /*0x1ec8*/ 688,
+ /*0x1e48*/ 622,
+ /*0x01cd*/ 163,
+ -1, -1, -1, -1,
+ /*0x1ca9*/ 565,
+ -1,
+ /*0xa648*/ 1032,
+ /*0x01e4*/ 174,
+ -1, -1,
+ /*0xa74a*/ 1084,
+ -1, -1, -1, -1, -1, -1,
+ /*0x1ec6*/ 687,
+ /*0x1e46*/ 621,
+ -1, -1, -1,
+ /*0xa742*/ 1080,
+ /*0x1f4a*/ 748,
+ /*0x1ec0*/ 684,
+ /*0x1e40*/ 618,
+ /*0xa646*/ 1031,
+ -1, -1,
+ /*0x1f87*/ 775,
+ /*0x10407*/ 1283,
+ /*0x0407*/ 304,
+ /*0xab73*/ 1161,
+ /*0xa640*/ 1028,
+ -1,
+ /*0xa68e*/ 1058,
+ /*0x104ce*/ 1346,
+ /*0xab87*/ 1181,
+ /*0x2c07*/ 919,
+ /*0x1f2b*/ 733,
+ /*0x1eda*/ 697,
+ /*0x1e5a*/ 631,
+ -1, -1, -1,
+ /*0x24cc*/ 908,
+ /*0x0545*/ 465,
+ -1,
+ /*0x04d6*/ 400,
+ /*0xa65a*/ 1041,
+ -1,
+ /*0x1ed4*/ 694,
+ /*0x1e54*/ 628,
+ /*0x015e*/ 103,
+ -1,
+ /*0x10d56*/ 1444,
+ -1,
+ /*0x0243*/ 221,
+ /*0x0043*/ 2,
+ /*0x1fc3*/ 828,
+ /*0xa654*/ 1038,
+ /*0x03de*/ 278,
+ /*0x0143*/ 89,
+ /*0x00cd*/ 39,
+ /*0x1ca1*/ 557,
+ /*0x118ab*/ 1471,
+ -1,
+ /*0x104d0*/ 1348,
+ /*0x04d0*/ 397,
+ /*0x0187*/ 125,
+ /*0x10c87*/ 1394,
+ /*0x2cde*/ 1022,
+ -1,
+ /*0xa74e*/ 1086,
+ /*0xab71*/ 1159,
+ /*0x10d50*/ 1438,
+ /*0x212b*/ 867,
+ /*0x015c*/ 102,
+ -1, -1,
+ /*0x1e907*/ 1556,
+ -1,
+ /*0x104c8*/ 1340,
+ /*0x1ca5*/ 561,
+ /*0xa756*/ 1090,
+ /*0x03dc*/ 277,
+ -1,
+ /*0x1cad*/ 569,
+ /*0x004b*/ 9,
+ /*0x1fcb*/ 835,
+ /*0x01de*/ 171,
+ /*0x24c4*/ 900,
+ /*0x1058e*/ 1380,
+ -1, -1,
+ /*0x2cdc*/ 1021,
+ /*0x1fec*/ 854,
+ /*0x1f56*/ 755,
+ /*0x046c*/ 351,
+ /*0x016c*/ 110,
+ -1, -1,
+ /*0x104c6*/ 1338,
+ /*0xab7b*/ 1169,
+ /*0xa750*/ 1087,
+ -1, -1,
+ /*0x03ec*/ 285,
+ /*0x1ca3*/ 559,
+ /*0x104c0*/ 1332,
+ /*0x04c0*/ 389,
+ /*0x1ed8*/ 696,
+ /*0x1e58*/ 630,
+ /*0xa7dc*/ 1156,
+ /*0x10c0*/ 516,
+ /*0xa68c*/ 1057,
+ -1,
+ /*0x1f50*/ 752,
+ /*0x0555*/ 481,
+ /*0xa748*/ 1083,
+ /*0xa658*/ 1040,
+ -1, -1, -1, -1,
+ /*0xabb1*/ 1223,
+ /*0x04da*/ 402,
+ -1,
+ /*0xa7cb*/ 1147,
+ /*0x01cb*/ 162,
+ -1,
+ /*0xab7d*/ 1171,
+ /*0x1f48*/ 746,
+ /*0x10d5a*/ 1448,
+ -1, -1,
+ /*0x01ec*/ 178,
+ /*0x04d4*/ 399,
+ -1,
+ /*0xa746*/ 1082,
+ /*0x1f97*/ 791,
+ /*0x10417*/ 1299,
+ /*0x0417*/ 320,
+ -1,
+ /*0x10d54*/ 1442,
+ -1,
+ /*0xa740*/ 1079,
+ -1,
+ /*0xab97*/ 1197,
+ /*0x2c17*/ 935,
+ -1,
+ /*0x0397*/ 248,
+ /*0x0460*/ 345,
+ /*0x0160*/ 104,
+ /*0x00de*/ 55,
+ -1,
+ /*0xa7b1*/ 1131,
+ /*0x01b1*/ 150,
+ /*0x10cb1*/ 1436,
+ /*0x2c60*/ 960,
+ -1,
+ /*0x03e0*/ 279,
+ /*0xa75a*/ 1092,
+ /*0x00c3*/ 29,
+ -1,
+ /*0x1ee2*/ 701,
+ /*0x1e62*/ 635,
+ -1, -1,
+ /*0x1fb7*/ 820,
+ -1,
+ /*0x2ce0*/ 1023,
+ /*0x1058c*/ 1378,
+ /*0xa754*/ 1089,
+ /*0xa662*/ 1045,
+ -1,
+ /*0xab77*/ 1165,
+ /*0xabb7*/ 1229,
+ /*0x00dc*/ 53,
+ /*0xab7f*/ 1173,
+ /*0x0197*/ 136,
+ /*0x10c97*/ 1410,
+ /*0x24ca*/ 906,
+ -1, -1,
+ /*0x1fea*/ 852,
+ /*0x1f54*/ 754,
+ /*0x046a*/ 350,
+ /*0x016a*/ 109,
+ /*0x1c87*/ 537,
+ /*0x01e0*/ 172,
+ /*0x1e917*/ 1572,
+ -1,
+ /*0x00cb*/ 37,
+ /*0x24c2*/ 898,
+ /*0x054d*/ 473,
+ /*0x03ea*/ 284,
+ /*0x04d8*/ 401,
+ -1,
+ /*0x0470*/ 353,
+ /*0x0170*/ 112,
+ -1,
+ /*0x104c5*/ 1337,
+ /*0x04c5*/ 392,
+ /*0x10d58*/ 1446,
+ -1,
+ /*0x2c70*/ 970,
+ /*0x10c5*/ 521,
+ /*0x03f0*/ 287,
+ /*0x01b7*/ 154,
+ /*0x1fe8*/ 850,
+ -1,
+ /*0x0468*/ 349,
+ /*0x0168*/ 108,
+ -1,
+ /*0x046e*/ 352,
+ /*0x016e*/ 111,
+ -1, -1, -1, -1,
+ /*0x03e8*/ 283,
+ /*0x2c6e*/ 968,
+ -1,
+ /*0x03ee*/ 286,
+ /*0x01ea*/ 177,
+ -1,
+ /*0x1ff2*/ 855,
+ -1,
+ /*0x0472*/ 354,
+ /*0x0172*/ 113,
+ -1,
+ /*0x1fe6*/ 848,
+ /*0xa758*/ 1091,
+ /*0x0466*/ 348,
+ /*0x0166*/ 107,
+ /*0x2c72*/ 971,
+ /*0x01f0*/ 180,
+ /*0xfb17*/ 1249,
+ /*0x1fb9*/ 822,
+ -1,
+ /*0x10a9*/ 493,
+ /*0x0139*/ 84,
+ /*0x03e6*/ 282,
+ -1,
+ /*0x24ce*/ 910,
+ -1,
+ /*0xabb9*/ 1231,
+ /*0x2cf2*/ 1027,
+ /*0x1fb3*/ 817,
+ /*0x01e8*/ 176,
+ /*0x04e2*/ 406,
+ -1,
+ /*0x01ee*/ 179,
+ -1, -1, -1,
+ /*0xabb3*/ 1225,
+ /*0x10d62*/ 1456,
+ -1, -1, -1, -1, -1,
+ /*0x0370*/ 230,
+ -1,
+ /*0xff2b*/ 1260,
+ /*0x01f2*/ 182,
+ -1,
+ /*0x0049*/ 1583,
+ /*0x1fc9*/ 833,
+ -1,
+ /*0x01e6*/ 175,
+ /*0x0149*/ 92,
+ /*0x1ee4*/ 702,
+ /*0x1e64*/ 636,
+ -1,
+ /*0x1cb1*/ 573,
+ -1, -1,
+ /*0x1058d*/ 1379,
+ /*0x16eab*/ 1535,
+ /*0x10d55*/ 1443,
+ /*0xa664*/ 1046,
+ -1, -1,
+ /*0x1f29*/ 731,
+ /*0xa762*/ 1096,
+ /*0xa7b3*/ 1133,
+ /*0x01b3*/ 152,
+ -1,
+ /*0x24c8*/ 904,
+ -1, -1,
+ /*0x0372*/ 231,
+ /*0x0543*/ 463,
+ /*0x16e53*/ 1511,
+ -1, -1, -1,
+ /*0x1c97*/ 547,
+ /*0x10a1*/ 485,
+ /*0x1ff4*/ 857,
+ -1,
+ /*0x0474*/ 355,
+ /*0x0174*/ 114,
+ /*0x16e52*/ 1510,
+ -1, -1,
+ /*0xa7c9*/ 1146,
+ -1,
+ /*0x24c6*/ 902,
+ /*0x118a9*/ 1469,
+ /*0x03f4*/ 289,
+ -1, -1,
+ /*0x16e4c*/ 1504,
+ -1,
+ /*0x24c0*/ 896,
+ -1,
+ /*0x10a5*/ 489,
+ -1, -1, -1,
+ /*0x10ad*/ 497,
+ /*0x054b*/ 471,
+ -1, -1, -1,
+ /*0x1cb7*/ 579,
+ /*0x013f*/ 87,
+ -1, -1, -1, -1,
+ /*0xabbf*/ 1237,
+ -1,
+ /*0x2162*/ 871,
+ /*0x1f9b*/ 795,
+ /*0x1041b*/ 1303,
+ /*0x041b*/ 324,
+ -1,
+ /*0x01f4*/ 183,
+ -1, -1,
+ /*0x10a3*/ 487,
+ /*0xab9b*/ 1201,
+ /*0x2c1b*/ 939,
+ -1,
+ /*0x039b*/ 252,
+ -1,
+ /*0x104cd*/ 1345,
+ /*0x04cd*/ 396,
+ /*0x0531*/ 445,
+ -1, -1,
+ /*0x10cd*/ 523,
+ /*0x1ede*/ 699,
+ /*0x1e5e*/ 633,
+ -1,
+ /*0x04e4*/ 407,
+ -1,
+ /*0x16e44*/ 1496,
+ -1, -1, -1,
+ /*0xa65e*/ 1043,
+ /*0x10d64*/ 1458,
+ -1,
+ /*0x1f2d*/ 735,
+ /*0xab79*/ 1167,
+ -1,
+ /*0x118a1*/ 1461,
+ -1,
+ /*0x00c9*/ 35,
+ -1,
+ /*0x1f99*/ 793,
+ /*0x10419*/ 1301,
+ /*0x0419*/ 322,
+ /*0x10c9b*/ 1414,
+ -1,
+ /*0x1edc*/ 698,
+ /*0x1e5c*/ 632,
+ -1,
+ /*0xab99*/ 1199,
+ /*0x2c19*/ 937,
+ -1,
+ /*0x0399*/ 250,
+ -1,
+ /*0x1e91b*/ 1576,
+ /*0xa65c*/ 1042,
+ /*0x118a5*/ 1465,
+ -1, -1, -1,
+ /*0x118ad*/ 1473,
+ /*0xa764*/ 1097,
+ /*0x023d*/ 218,
+ -1,
+ /*0x1cb9*/ 581,
+ -1,
+ /*0x1f4d*/ 751,
+ /*0x013d*/ 86,
+ /*0x1eec*/ 706,
+ /*0x1e6c*/ 640,
+ /*0x0537*/ 451,
+ -1,
+ /*0xabbd*/ 1235,
+ -1,
+ /*0x1cb3*/ 575,
+ -1,
+ /*0x24c5*/ 901,
+ /*0xa66c*/ 1050,
+ /*0x0241*/ 220,
+ /*0x0041*/ 0,
+ -1,
+ /*0x118a3*/ 1463,
+ /*0x10c99*/ 1412,
+ /*0x0141*/ 88,
+ -1,
+ /*0x1f91*/ 785,
+ /*0x10411*/ 1293,
+ /*0x0411*/ 314,
+ -1, -1, -1, -1,
+ /*0x1e919*/ 1574,
+ /*0xab91*/ 1191,
+ /*0x2c11*/ 929,
+ -1,
+ /*0x0391*/ 242,
+ /*0x10570*/ 1352,
+ -1,
+ /*0x023b*/ 217,
+ -1,
+ /*0x1fbb*/ 824,
+ -1,
+ /*0xab7c*/ 1170,
+ /*0x013b*/ 85,
+ -1, -1, -1,
+ /*0x04de*/ 404,
+ /*0xabbb*/ 1233,
+ /*0xabb5*/ 1227,
+ /*0x2164*/ 873,
+ /*0x1e97*/ 662,
+ -1, -1,
+ /*0x10d5e*/ 1452,
+ /*0x104c3*/ 1335,
+ /*0x04c3*/ 391,
+ /*0x16e4a*/ 1502,
+ -1, -1,
+ /*0x10c3*/ 519,
+ /*0x1ee0*/ 700,
+ /*0x1e60*/ 634,
+ -1,
+ /*0x0191*/ 132,
+ /*0x10c91*/ 1404,
+ /*0x10572*/ 1354,
+ -1, -1,
+ /*0x16e42*/ 1494,
+ /*0xa660*/ 1044,
+ /*0x04dc*/ 403,
+ -1,
+ /*0x047e*/ 360,
+ -1,
+ /*0x1e911*/ 1566,
+ -1, -1,
+ /*0x10d5c*/ 1450,
+ /*0x0539*/ 453,
+ /*0x2c7e*/ 973,
+ /*0x01b5*/ 153,
+ /*0x03fe*/ 295,
+ /*0xa75e*/ 1094,
+ -1,
+ /*0x104cb*/ 1343,
+ /*0x04cb*/ 395,
+ -1, -1,
+ /*0x0533*/ 447,
+ -1,
+ /*0x1cbf*/ 585,
+ -1,
+ /*0x04ec*/ 411,
+ -1, -1,
+ /*0x1eea*/ 705,
+ /*0x1e6a*/ 639,
+ -1, -1, -1, -1,
+ /*0x1c9b*/ 551,
+ -1, -1,
+ /*0xa66a*/ 1049,
+ -1,
+ /*0xa75c*/ 1093,
+ /*0x1ef0*/ 708,
+ /*0x1e70*/ 642,
+ /*0x0549*/ 469,
+ /*0x01fe*/ 189,
+ -1,
+ /*0x104b1*/ 1317,
+ -1, -1, -1,
+ /*0xff29*/ 1258,
+ /*0x10b1*/ 501,
+ -1,
+ /*0x16e4e*/ 1506,
+ /*0x1ee8*/ 704,
+ /*0x1e68*/ 638,
+ /*0x00c1*/ 27,
+ /*0x1eee*/ 707,
+ /*0x1e6e*/ 641,
+ -1, -1, -1,
+ /*0xa76c*/ 1101,
+ /*0xa668*/ 1048,
+ /*0x16e56*/ 1514,
+ /*0x16ea9*/ 1533,
+ -1, -1,
+ /*0x1f4b*/ 749,
+ -1, -1,
+ /*0x1ef2*/ 709,
+ /*0x1e72*/ 643,
+ /*0x1c99*/ 549,
+ /*0x10574*/ 1356,
+ /*0x1f6c*/ 764,
+ /*0x1ee6*/ 703,
+ /*0x1e66*/ 637,
+ /*0x00b5*/ 25,
+ -1,
+ /*0x04e0*/ 405,
+ -1,
+ /*0x004f*/ 13,
+ -1,
+ /*0x16e50*/ 1508,
+ /*0xa666*/ 1047,
+ -1,
+ /*0x10d60*/ 1454,
+ -1, -1, -1, -1, -1, -1,
+ /*0x03cf*/ 270,
+ -1,
+ /*0x1cbd*/ 583,
+ /*0x24cd*/ 909,
+ /*0x104b7*/ 1323,
+ /*0x16e48*/ 1500,
+ /*0x053f*/ 459,
+ -1, -1,
+ /*0x10b7*/ 507,
+ -1, -1, -1, -1, -1, -1,
+ /*0xff21*/ 1250,
+ -1,
+ /*0x216c*/ 881,
+ -1, -1,
+ /*0x04ea*/ 410,
+ /*0xa760*/ 1095,
+ /*0x1c91*/ 541,
+ /*0x1ff6*/ 858,
+ /*0x16e46*/ 1498,
+ /*0x0476*/ 356,
+ /*0x0176*/ 115,
+ /*0x118b1*/ 1477,
+ /*0x01cf*/ 164,
+ -1,
+ /*0x16ea1*/ 1525,
+ /*0x16e40*/ 1492,
+ /*0x04f0*/ 413,
+ -1,
+ /*0xff25*/ 1254,
+ /*0x1f95*/ 789,
+ /*0x10415*/ 1297,
+ /*0x0415*/ 318,
+ /*0xff2d*/ 1262,
+ /*0x1cb5*/ 577,
+ /*0xab75*/ 1163,
+ -1, -1,
+ /*0xab95*/ 1195,
+ /*0x2c15*/ 933,
+ /*0x04e8*/ 409,
+ /*0x0395*/ 246,
+ /*0x16e5a*/ 1518,
+ /*0x04ee*/ 412,
+ /*0x16ea5*/ 1529,
+ -1,
+ /*0x1ef4*/ 710,
+ /*0x1e74*/ 644,
+ /*0x16ead*/ 1537,
+ -1,
+ /*0x1ffa*/ 862,
+ /*0xa76a*/ 1100,
+ /*0x047a*/ 358,
+ /*0x16e54*/ 1512,
+ /*0xff23*/ 1252,
+ -1, -1,
+ /*0x04f2*/ 414,
+ /*0x01f6*/ 184,
+ -1, -1,
+ /*0x03fa*/ 293,
+ /*0x04e6*/ 408,
+ /*0x0051*/ 15,
+ /*0x1f6a*/ 762,
+ -1,
+ /*0x2160*/ 869,
+ /*0x13fa*/ 526,
+ /*0x104b9*/ 1325,
+ /*0x16ea3*/ 1527,
+ -1,
+ /*0x10c95*/ 1408,
+ /*0x053d*/ 457,
+ /*0x10b9*/ 509,
+ /*0x118b7*/ 1483,
+ /*0x03d1*/ 272,
+ /*0xa768*/ 1099,
+ -1,
+ /*0x104b3*/ 1319,
+ /*0xa76e*/ 1102,
+ -1,
+ /*0x1e915*/ 1570,
+ /*0x1e9b*/ 666,
+ /*0x10b3*/ 503,
+ -1,
+ /*0x0376*/ 232,
+ -1,
+ /*0x00cf*/ 41,
+ /*0x0541*/ 461,
+ /*0x1f68*/ 760,
+ /*0x01fa*/ 187,
+ -1,
+ /*0x1f6e*/ 766,
+ -1,
+ /*0x1f93*/ 787,
+ /*0x10413*/ 1295,
+ /*0x0413*/ 316,
+ /*0x24c3*/ 899,
+ /*0xa766*/ 1098,
+ /*0x104c9*/ 1341,
+ /*0x04c9*/ 394,
+ /*0x216a*/ 879,
+ /*0xab93*/ 1193,
+ /*0x2c13*/ 931,
+ /*0x01d1*/ 165,
+ /*0x0393*/ 244,
+ /*0x1f8f*/ 783,
+ /*0x1040f*/ 1291,
+ /*0x040f*/ 312,
+ /*0x053b*/ 455,
+ /*0x0535*/ 449,
+ -1, -1,
+ /*0x16e58*/ 1516,
+ /*0xab8f*/ 1189,
+ /*0x2c0f*/ 927,
+ -1,
+ /*0x038f*/ 240,
+ /*0x1f39*/ 739,
+ /*0x16e45*/ 1497,
+ /*0x1e99*/ 664,
+ -1,
+ /*0x1f81*/ 769,
+ /*0x10401*/ 1277,
+ /*0x0401*/ 298,
+ -1,
+ /*0x2168*/ 877,
+ /*0x24cb*/ 907,
+ /*0xfb15*/ 1247,
+ /*0x216e*/ 883,
+ /*0xab81*/ 1175,
+ /*0x2c01*/ 913,
+ /*0x04f4*/ 415,
+ -1,
+ /*0x0193*/ 133,
+ /*0x10c93*/ 1406,
+ -1, -1,
+ /*0x1ff8*/ 860,
+ /*0x1057e*/ 1365,
+ /*0x0478*/ 357,
+ /*0x0178*/ 116,
+ -1, -1,
+ /*0x118b9*/ 1485,
+ /*0x1e913*/ 1568,
+ /*0x018f*/ 130,
+ /*0x10c8f*/ 1402,
+ /*0x2166*/ 875,
+ /*0x1f49*/ 747,
+ -1, -1, -1, -1,
+ /*0x118b3*/ 1479,
+ /*0x13f8*/ 524,
+ /*0x104bf*/ 1331,
+ /*0x1e90f*/ 1564,
+ /*0x1f9f*/ 799,
+ /*0x1041f*/ 1307,
+ /*0x041f*/ 328,
+ /*0x10bf*/ 515,
+ /*0x0181*/ 121,
+ /*0x10c81*/ 1388,
+ -1, -1,
+ /*0xab9f*/ 1205,
+ /*0x2c1f*/ 943,
+ /*0x00d1*/ 43,
+ /*0x039f*/ 256,
+ -1, -1, -1,
+ /*0x1e901*/ 1550,
+ /*0x1f8b*/ 779,
+ /*0x1040b*/ 1287,
+ /*0x040b*/ 308,
+ -1,
+ /*0x01f8*/ 186,
+ -1, -1, -1,
+ /*0xab8b*/ 1185,
+ /*0x2c0b*/ 923,
+ -1, -1, -1, -1, -1, -1,
+ /*0x1c95*/ 545,
+ /*0x16e55*/ 1513,
+ /*0xfb13*/ 1245,
+ -1, -1, -1, -1, -1,
+ /*0x019f*/ 140,
+ /*0x10c9f*/ 1418,
+ -1, -1, -1, -1, -1, -1,
+ /*0x1f3f*/ 745,
+ /*0x24b7*/ 887,
+ -1,
+ /*0x1e91f*/ 1580,
+ -1,
+ /*0x1efe*/ 715,
+ /*0x1e7e*/ 649,
+ /*0xa78b*/ 1111,
+ /*0x018b*/ 128,
+ /*0x10c8b*/ 1398,
+ -1,
+ /*0x1f1b*/ 727,
+ -1,
+ /*0x054f*/ 475,
+ /*0xfb01*/ 1239,
+ -1, -1,
+ /*0xff31*/ 1266,
+ -1,
+ /*0x1e90b*/ 1560,
+ -1, -1,
+ /*0x104bd*/ 1329,
+ -1, -1, -1,
+ /*0x118bf*/ 1491,
+ /*0x10bd*/ 513,
+ -1, -1, -1, -1,
+ /*0x16eb1*/ 1541,
+ -1, -1, -1, -1, -1,
+ /*0x104c1*/ 1333,
+ /*0x04c1*/ 390,
+ -1, -1, -1,
+ /*0x10c1*/ 517,
+ -1, -1, -1,
+ /*0x10576*/ 1358,
+ /*0x1c93*/ 543,
+ /*0x1f19*/ 725,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1,
+ /*0x104bb*/ 1327,
+ /*0x104b5*/ 1321,
+ -1,
+ /*0x16e4d*/ 1505,
+ -1,
+ /*0x10bb*/ 511,
+ /*0x10b5*/ 505,
+ -1, -1, -1,
+ /*0xff37*/ 1272,
+ -1,
+ /*0x24b9*/ 889,
+ /*0x1f3d*/ 743,
+ -1, -1, -1,
+ /*0x1c81*/ 531,
+ -1, -1,
+ /*0x1057a*/ 1362,
+ -1, -1, -1, -1,
+ /*0x16eb7*/ 1547,
+ -1, -1, -1, -1, -1, -1,
+ /*0x04fe*/ 420,
+ -1, -1,
+ /*0x0551*/ 477,
+ -1, -1, -1,
+ /*0x118bd*/ 1489,
+ -1, -1, -1,
+ /*0x24c9*/ 905,
+ -1, -1, -1, -1, -1, -1,
+ /*0x1f3b*/ 741,
+ -1, -1,
+ /*0x1c9f*/ 555,
+ -1, -1, -1, -1, -1, -1,
+ /*0x1ef6*/ 711,
+ /*0x1e76*/ 645,
+ -1, -1, -1, -1, -1, -1,
+ /*0xa77e*/ 1106,
+ -1, -1, -1, -1, -1, -1,
+ -1,
+ /*0x118bb*/ 1487,
+ /*0x118b5*/ 1481,
+ -1, -1,
+ /*0xff39*/ 1274,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1,
+ /*0xff33*/ 1268,
+ -1,
+ /*0x1efa*/ 713,
+ /*0x1e7a*/ 647,
+ /*0x16e5e*/ 1522,
+ -1, -1, -1, -1, -1,
+ /*0x24bf*/ 895,
+ -1, -1,
+ /*0x16e43*/ 1495,
+ -1,
+ /*0x16eb3*/ 1543,
+ -1, -1,
+ /*0x10578*/ 1360,
+ -1,
+ /*0x104cf*/ 1347,
+ -1, -1, -1, -1, -1, -1,
+ -1,
+ /*0x16e5c*/ 1520,
+ -1, -1, -1,
+ /*0x10587*/ 1374,
+ /*0x0587*/ 483,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1,
+ /*0x16e4b*/ 1503,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ /*0x04f6*/ 416,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1,
+ /*0x24bd*/ 893,
+ -1, -1, -1, -1, -1,
+ /*0x04fa*/ 418,
+ -1,
+ /*0x1ef8*/ 712,
+ /*0x1e78*/ 646,
+ -1, -1, -1, -1, -1, -1,
+ /*0x24c1*/ 897,
+ -1, -1,
+ /*0x104d1*/ 1349,
+ -1, -1, -1, -1, -1, -1,
+ -1,
+ /*0x10d51*/ 1439,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1,
+ /*0x24bb*/ 891,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1,
+ /*0x04f8*/ 417,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1,
+ /*0xff35*/ 1270,
+ -1, -1, -1, -1,
+ /*0x1f0f*/ 723,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1,
+ /*0x16eb5*/ 1545,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1,
+ /*0x16e49*/ 1501,
+ -1, -1, -1, -1,
+ /*0x24cf*/ 911,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1,
+ /*0x1f0b*/ 719,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -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*/ 1493,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1,
+ /*0x10591*/ 1383,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1,
+ /*0x16e4f*/ 1507,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1,
+ /*0x16e51*/ 1509,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1,
+ /*0x10595*/ 1386,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1,
+ /*0x1058f*/ 1381,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1,
+ /*0x10581*/ 1368,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -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*/ 1158,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1,
+ /*0xab72*/ 1160,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1,
+ /*0xab74*/ 1162,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1,
+ /*0xab7e*/ 1172,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -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*/ 1164,
+ -1, -1, -1, -1, -1, -1,
+ -1, -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*/ 1168,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1,
+ /*0xab78*/ 1166
+ };
+
+ if (code <= MAX_CODE_VALUE && code >= MIN_CODE_VALUE)
+ {
+ register unsigned int key = onigenc_unicode_CaseFold_11_hash(code);
+
+ if (key <= MAX_HASH_VALUE)
+ {
+ register short s = wordlist[key];
+
+ if (s >= 0 && code1_equal(code, CaseFold_11_Table[s].from))
+ return &CaseFold_11_Table[s].to;
+ }
+ }
+ return 0;
+}
+
+static const CaseUnfold_11_Type CaseUnfold_11_Table[] = {
+#define CaseUnfold_11 (*(CaseUnfold_11_Type (*)[1450])(CaseUnfold_11_Table+0))
+ {0x0061, {1|U, {0x0041}}},
+ {0x0062, {1|U, {0x0042}}},
+ {0x0063, {1|U, {0x0043}}},
+ {0x0064, {1|U, {0x0044}}},
+ {0x0065, {1|U, {0x0045}}},
+ {0x0066, {1|U, {0x0046}}},
+ {0x0067, {1|U, {0x0047}}},
+ {0x0068, {1|U, {0x0048}}},
+ {0x006a, {1|U, {0x004a}}},
+ {0x006b, {2|U, {0x004b, 0x212a}}},
+ {0x006c, {1|U, {0x004c}}},
+ {0x006d, {1|U, {0x004d}}},
+ {0x006e, {1|U, {0x004e}}},
+ {0x006f, {1|U, {0x004f}}},
+ {0x0070, {1|U, {0x0050}}},
+ {0x0071, {1|U, {0x0051}}},
+ {0x0072, {1|U, {0x0052}}},
+ {0x0073, {2|U, {0x0053, 0x017f}}},
+ {0x0074, {1|U, {0x0054}}},
+ {0x0075, {1|U, {0x0055}}},
+ {0x0076, {1|U, {0x0056}}},
+ {0x0077, {1|U, {0x0057}}},
+ {0x0078, {1|U, {0x0058}}},
+ {0x0079, {1|U, {0x0059}}},
+ {0x007a, {1|U, {0x005a}}},
+ {0x00e0, {1|U, {0x00c0}}},
+ {0x00e1, {1|U, {0x00c1}}},
+ {0x00e2, {1|U, {0x00c2}}},
+ {0x00e3, {1|U, {0x00c3}}},
+ {0x00e4, {1|U, {0x00c4}}},
+ {0x00e5, {2|U, {0x00c5, 0x212b}}},
+ {0x00e6, {1|U, {0x00c6}}},
+ {0x00e7, {1|U, {0x00c7}}},
+ {0x00e8, {1|U, {0x00c8}}},
+ {0x00e9, {1|U, {0x00c9}}},
+ {0x00ea, {1|U, {0x00ca}}},
+ {0x00eb, {1|U, {0x00cb}}},
+ {0x00ec, {1|U, {0x00cc}}},
+ {0x00ed, {1|U, {0x00cd}}},
+ {0x00ee, {1|U, {0x00ce}}},
+ {0x00ef, {1|U, {0x00cf}}},
+ {0x00f0, {1|U, {0x00d0}}},
+ {0x00f1, {1|U, {0x00d1}}},
+ {0x00f2, {1|U, {0x00d2}}},
+ {0x00f3, {1|U, {0x00d3}}},
+ {0x00f4, {1|U, {0x00d4}}},
+ {0x00f5, {1|U, {0x00d5}}},
+ {0x00f6, {1|U, {0x00d6}}},
+ {0x00f8, {1|U, {0x00d8}}},
+ {0x00f9, {1|U, {0x00d9}}},
+ {0x00fa, {1|U, {0x00da}}},
+ {0x00fb, {1|U, {0x00db}}},
+ {0x00fc, {1|U, {0x00dc}}},
+ {0x00fd, {1|U, {0x00dd}}},
+ {0x00fe, {1|U, {0x00de}}},
+ {0x00ff, {1|U, {0x0178}}},
+ {0x0101, {1|U, {0x0100}}},
+ {0x0103, {1|U, {0x0102}}},
+ {0x0105, {1|U, {0x0104}}},
+ {0x0107, {1|U, {0x0106}}},
+ {0x0109, {1|U, {0x0108}}},
+ {0x010b, {1|U, {0x010a}}},
+ {0x010d, {1|U, {0x010c}}},
+ {0x010f, {1|U, {0x010e}}},
+ {0x0111, {1|U, {0x0110}}},
+ {0x0113, {1|U, {0x0112}}},
+ {0x0115, {1|U, {0x0114}}},
+ {0x0117, {1|U, {0x0116}}},
+ {0x0119, {1|U, {0x0118}}},
+ {0x011b, {1|U, {0x011a}}},
+ {0x011d, {1|U, {0x011c}}},
+ {0x011f, {1|U, {0x011e}}},
+ {0x0121, {1|U, {0x0120}}},
+ {0x0123, {1|U, {0x0122}}},
+ {0x0125, {1|U, {0x0124}}},
+ {0x0127, {1|U, {0x0126}}},
+ {0x0129, {1|U, {0x0128}}},
+ {0x012b, {1|U, {0x012a}}},
+ {0x012d, {1|U, {0x012c}}},
+ {0x012f, {1|U, {0x012e}}},
+ {0x0133, {1|U, {0x0132}}},
+ {0x0135, {1|U, {0x0134}}},
+ {0x0137, {1|U, {0x0136}}},
+ {0x013a, {1|U, {0x0139}}},
+ {0x013c, {1|U, {0x013b}}},
+ {0x013e, {1|U, {0x013d}}},
+ {0x0140, {1|U, {0x013f}}},
+ {0x0142, {1|U, {0x0141}}},
+ {0x0144, {1|U, {0x0143}}},
+ {0x0146, {1|U, {0x0145}}},
+ {0x0148, {1|U, {0x0147}}},
+ {0x014b, {1|U, {0x014a}}},
+ {0x014d, {1|U, {0x014c}}},
+ {0x014f, {1|U, {0x014e}}},
+ {0x0151, {1|U, {0x0150}}},
+ {0x0153, {1|U, {0x0152}}},
+ {0x0155, {1|U, {0x0154}}},
+ {0x0157, {1|U, {0x0156}}},
+ {0x0159, {1|U, {0x0158}}},
+ {0x015b, {1|U, {0x015a}}},
+ {0x015d, {1|U, {0x015c}}},
+ {0x015f, {1|U, {0x015e}}},
+ {0x0161, {1|U, {0x0160}}},
+ {0x0163, {1|U, {0x0162}}},
+ {0x0165, {1|U, {0x0164}}},
+ {0x0167, {1|U, {0x0166}}},
+ {0x0169, {1|U, {0x0168}}},
+ {0x016b, {1|U, {0x016a}}},
+ {0x016d, {1|U, {0x016c}}},
+ {0x016f, {1|U, {0x016e}}},
+ {0x0171, {1|U, {0x0170}}},
+ {0x0173, {1|U, {0x0172}}},
+ {0x0175, {1|U, {0x0174}}},
+ {0x0177, {1|U, {0x0176}}},
+ {0x017a, {1|U, {0x0179}}},
+ {0x017c, {1|U, {0x017b}}},
+ {0x017e, {1|U, {0x017d}}},
+ {0x0180, {1|U, {0x0243}}},
+ {0x0183, {1|U, {0x0182}}},
+ {0x0185, {1|U, {0x0184}}},
+ {0x0188, {1|U, {0x0187}}},
+ {0x018c, {1|U, {0x018b}}},
+ {0x0192, {1|U, {0x0191}}},
+ {0x0195, {1|U, {0x01f6}}},
+ {0x0199, {1|U, {0x0198}}},
+ {0x019a, {1|U, {0x023d}}},
+ {0x019b, {1|U, {0xa7dc}}},
+ {0x019e, {1|U, {0x0220}}},
+ {0x01a1, {1|U, {0x01a0}}},
+ {0x01a3, {1|U, {0x01a2}}},
+ {0x01a5, {1|U, {0x01a4}}},
+ {0x01a8, {1|U, {0x01a7}}},
+ {0x01ad, {1|U, {0x01ac}}},
+ {0x01b0, {1|U, {0x01af}}},
+ {0x01b4, {1|U, {0x01b3}}},
+ {0x01b6, {1|U, {0x01b5}}},
+ {0x01b9, {1|U, {0x01b8}}},
+ {0x01bd, {1|U, {0x01bc}}},
+ {0x01bf, {1|U, {0x01f7}}},
+ {0x01c6, {2|U|ST, {0x01c4, 0x01c5}}},
+ {0x01c9, {2|U|ST, {0x01c7, 0x01c8}}},
+ {0x01cc, {2|U|ST, {0x01ca, 0x01cb}}},
+ {0x01ce, {1|U, {0x01cd}}},
+ {0x01d0, {1|U, {0x01cf}}},
+ {0x01d2, {1|U, {0x01d1}}},
+ {0x01d4, {1|U, {0x01d3}}},
+ {0x01d6, {1|U, {0x01d5}}},
+ {0x01d8, {1|U, {0x01d7}}},
+ {0x01da, {1|U, {0x01d9}}},
+ {0x01dc, {1|U, {0x01db}}},
+ {0x01dd, {1|U, {0x018e}}},
+ {0x01df, {1|U, {0x01de}}},
+ {0x01e1, {1|U, {0x01e0}}},
+ {0x01e3, {1|U, {0x01e2}}},
+ {0x01e5, {1|U, {0x01e4}}},
+ {0x01e7, {1|U, {0x01e6}}},
+ {0x01e9, {1|U, {0x01e8}}},
+ {0x01eb, {1|U, {0x01ea}}},
+ {0x01ed, {1|U, {0x01ec}}},
+ {0x01ef, {1|U, {0x01ee}}},
+ {0x01f3, {2|U|ST, {0x01f1, 0x01f2}}},
+ {0x01f5, {1|U, {0x01f4}}},
+ {0x01f9, {1|U, {0x01f8}}},
+ {0x01fb, {1|U, {0x01fa}}},
+ {0x01fd, {1|U, {0x01fc}}},
+ {0x01ff, {1|U, {0x01fe}}},
+ {0x0201, {1|U, {0x0200}}},
+ {0x0203, {1|U, {0x0202}}},
+ {0x0205, {1|U, {0x0204}}},
+ {0x0207, {1|U, {0x0206}}},
+ {0x0209, {1|U, {0x0208}}},
+ {0x020b, {1|U, {0x020a}}},
+ {0x020d, {1|U, {0x020c}}},
+ {0x020f, {1|U, {0x020e}}},
+ {0x0211, {1|U, {0x0210}}},
+ {0x0213, {1|U, {0x0212}}},
+ {0x0215, {1|U, {0x0214}}},
+ {0x0217, {1|U, {0x0216}}},
+ {0x0219, {1|U, {0x0218}}},
+ {0x021b, {1|U, {0x021a}}},
+ {0x021d, {1|U, {0x021c}}},
+ {0x021f, {1|U, {0x021e}}},
+ {0x0223, {1|U, {0x0222}}},
+ {0x0225, {1|U, {0x0224}}},
+ {0x0227, {1|U, {0x0226}}},
+ {0x0229, {1|U, {0x0228}}},
+ {0x022b, {1|U, {0x022a}}},
+ {0x022d, {1|U, {0x022c}}},
+ {0x022f, {1|U, {0x022e}}},
+ {0x0231, {1|U, {0x0230}}},
+ {0x0233, {1|U, {0x0232}}},
+ {0x023c, {1|U, {0x023b}}},
+ {0x023f, {1|U, {0x2c7e}}},
+ {0x0240, {1|U, {0x2c7f}}},
+ {0x0242, {1|U, {0x0241}}},
+ {0x0247, {1|U, {0x0246}}},
+ {0x0249, {1|U, {0x0248}}},
+ {0x024b, {1|U, {0x024a}}},
+ {0x024d, {1|U, {0x024c}}},
+ {0x024f, {1|U, {0x024e}}},
+ {0x0250, {1|U, {0x2c6f}}},
+ {0x0251, {1|U, {0x2c6d}}},
+ {0x0252, {1|U, {0x2c70}}},
+ {0x0253, {1|U, {0x0181}}},
+ {0x0254, {1|U, {0x0186}}},
+ {0x0256, {1|U, {0x0189}}},
+ {0x0257, {1|U, {0x018a}}},
+ {0x0259, {1|U, {0x018f}}},
+ {0x025b, {1|U, {0x0190}}},
+ {0x025c, {1|U, {0xa7ab}}},
+ {0x0260, {1|U, {0x0193}}},
+ {0x0261, {1|U, {0xa7ac}}},
+ {0x0263, {1|U, {0x0194}}},
+ {0x0264, {1|U, {0xa7cb}}},
+ {0x0265, {1|U, {0xa78d}}},
+ {0x0266, {1|U, {0xa7aa}}},
+ {0x0268, {1|U, {0x0197}}},
+ {0x0269, {1|U, {0x0196}}},
+ {0x026a, {1|U, {0xa7ae}}},
+ {0x026b, {1|U, {0x2c62}}},
+ {0x026c, {1|U, {0xa7ad}}},
+ {0x026f, {1|U, {0x019c}}},
+ {0x0271, {1|U, {0x2c6e}}},
+ {0x0272, {1|U, {0x019d}}},
+ {0x0275, {1|U, {0x019f}}},
+ {0x027d, {1|U, {0x2c64}}},
+ {0x0280, {1|U, {0x01a6}}},
+ {0x0282, {1|U, {0xa7c5}}},
+ {0x0283, {1|U, {0x01a9}}},
+ {0x0287, {1|U, {0xa7b1}}},
+ {0x0288, {1|U, {0x01ae}}},
+ {0x0289, {1|U, {0x0244}}},
+ {0x028a, {1|U, {0x01b1}}},
+ {0x028b, {1|U, {0x01b2}}},
+ {0x028c, {1|U, {0x0245}}},
+ {0x0292, {1|U, {0x01b7}}},
+ {0x029d, {1|U, {0xa7b2}}},
+ {0x029e, {1|U, {0xa7b0}}},
+ {0x0371, {1|U, {0x0370}}},
+ {0x0373, {1|U, {0x0372}}},
+ {0x0377, {1|U, {0x0376}}},
+ {0x037b, {1|U, {0x03fd}}},
+ {0x037c, {1|U, {0x03fe}}},
+ {0x037d, {1|U, {0x03ff}}},
+ {0x03ac, {1|U, {0x0386}}},
+ {0x03ad, {1|U, {0x0388}}},
+ {0x03ae, {1|U, {0x0389}}},
+ {0x03af, {1|U, {0x038a}}},
+ {0x03b1, {1|U, {0x0391}}},
+ {0x03b2, {2|U, {0x0392, 0x03d0}}},
+ {0x03b3, {1|U, {0x0393}}},
+ {0x03b4, {1|U, {0x0394}}},
+ {0x03b5, {2|U, {0x0395, 0x03f5}}},
+ {0x03b6, {1|U, {0x0396}}},
+ {0x03b7, {1|U, {0x0397}}},
+ {0x03b8, {3|U, {0x0398, 0x03d1, 0x03f4}}},
+ {0x03b9, {3|U, {0x0399, 0x0345, 0x1fbe}}},
+ {0x03ba, {2|U, {0x039a, 0x03f0}}},
+ {0x03bb, {1|U, {0x039b}}},
+ {0x03bc, {2|U, {0x039c, 0x00b5}}},
+ {0x03bd, {1|U, {0x039d}}},
+ {0x03be, {1|U, {0x039e}}},
+ {0x03bf, {1|U, {0x039f}}},
+ {0x03c0, {2|U, {0x03a0, 0x03d6}}},
+ {0x03c1, {2|U, {0x03a1, 0x03f1}}},
+ {0x03c3, {2|U, {0x03a3, 0x03c2}}},
+ {0x03c4, {1|U, {0x03a4}}},
+ {0x03c5, {1|U, {0x03a5}}},
+ {0x03c6, {2|U, {0x03a6, 0x03d5}}},
+ {0x03c7, {1|U, {0x03a7}}},
+ {0x03c8, {1|U, {0x03a8}}},
+ {0x03c9, {2|U, {0x03a9, 0x2126}}},
+ {0x03ca, {1|U, {0x03aa}}},
+ {0x03cb, {1|U, {0x03ab}}},
+ {0x03cc, {1|U, {0x038c}}},
+ {0x03cd, {1|U, {0x038e}}},
+ {0x03ce, {1|U, {0x038f}}},
+ {0x03d7, {1|U, {0x03cf}}},
+ {0x03d9, {1|U, {0x03d8}}},
+ {0x03db, {1|U, {0x03da}}},
+ {0x03dd, {1|U, {0x03dc}}},
+ {0x03df, {1|U, {0x03de}}},
+ {0x03e1, {1|U, {0x03e0}}},
+ {0x03e3, {1|U, {0x03e2}}},
+ {0x03e5, {1|U, {0x03e4}}},
+ {0x03e7, {1|U, {0x03e6}}},
+ {0x03e9, {1|U, {0x03e8}}},
+ {0x03eb, {1|U, {0x03ea}}},
+ {0x03ed, {1|U, {0x03ec}}},
+ {0x03ef, {1|U, {0x03ee}}},
+ {0x03f2, {1|U, {0x03f9}}},
+ {0x03f3, {1|U, {0x037f}}},
+ {0x03f8, {1|U, {0x03f7}}},
+ {0x03fb, {1|U, {0x03fa}}},
+ {0x0430, {1|U, {0x0410}}},
+ {0x0431, {1|U, {0x0411}}},
+ {0x0432, {2|U, {0x0412, 0x1c80}}},
+ {0x0433, {1|U, {0x0413}}},
+ {0x0434, {2|U, {0x0414, 0x1c81}}},
+ {0x0435, {1|U, {0x0415}}},
+ {0x0436, {1|U, {0x0416}}},
+ {0x0437, {1|U, {0x0417}}},
+ {0x0438, {1|U, {0x0418}}},
+ {0x0439, {1|U, {0x0419}}},
+ {0x043a, {1|U, {0x041a}}},
+ {0x043b, {1|U, {0x041b}}},
+ {0x043c, {1|U, {0x041c}}},
+ {0x043d, {1|U, {0x041d}}},
+ {0x043e, {2|U, {0x041e, 0x1c82}}},
+ {0x043f, {1|U, {0x041f}}},
+ {0x0440, {1|U, {0x0420}}},
+ {0x0441, {2|U, {0x0421, 0x1c83}}},
+ {0x0442, {3|U, {0x0422, 0x1c84, 0x1c85}}},
+ {0x0443, {1|U, {0x0423}}},
+ {0x0444, {1|U, {0x0424}}},
+ {0x0445, {1|U, {0x0425}}},
+ {0x0446, {1|U, {0x0426}}},
+ {0x0447, {1|U, {0x0427}}},
+ {0x0448, {1|U, {0x0428}}},
+ {0x0449, {1|U, {0x0429}}},
+ {0x044a, {2|U, {0x042a, 0x1c86}}},
+ {0x044b, {1|U, {0x042b}}},
+ {0x044c, {1|U, {0x042c}}},
+ {0x044d, {1|U, {0x042d}}},
+ {0x044e, {1|U, {0x042e}}},
+ {0x044f, {1|U, {0x042f}}},
+ {0x0450, {1|U, {0x0400}}},
+ {0x0451, {1|U, {0x0401}}},
+ {0x0452, {1|U, {0x0402}}},
+ {0x0453, {1|U, {0x0403}}},
+ {0x0454, {1|U, {0x0404}}},
+ {0x0455, {1|U, {0x0405}}},
+ {0x0456, {1|U, {0x0406}}},
+ {0x0457, {1|U, {0x0407}}},
+ {0x0458, {1|U, {0x0408}}},
+ {0x0459, {1|U, {0x0409}}},
+ {0x045a, {1|U, {0x040a}}},
+ {0x045b, {1|U, {0x040b}}},
+ {0x045c, {1|U, {0x040c}}},
+ {0x045d, {1|U, {0x040d}}},
+ {0x045e, {1|U, {0x040e}}},
+ {0x045f, {1|U, {0x040f}}},
+ {0x0461, {1|U, {0x0460}}},
+ {0x0463, {2|U, {0x0462, 0x1c87}}},
+ {0x0465, {1|U, {0x0464}}},
+ {0x0467, {1|U, {0x0466}}},
+ {0x0469, {1|U, {0x0468}}},
+ {0x046b, {1|U, {0x046a}}},
+ {0x046d, {1|U, {0x046c}}},
+ {0x046f, {1|U, {0x046e}}},
+ {0x0471, {1|U, {0x0470}}},
+ {0x0473, {1|U, {0x0472}}},
+ {0x0475, {1|U, {0x0474}}},
+ {0x0477, {1|U, {0x0476}}},
+ {0x0479, {1|U, {0x0478}}},
+ {0x047b, {1|U, {0x047a}}},
+ {0x047d, {1|U, {0x047c}}},
+ {0x047f, {1|U, {0x047e}}},
+ {0x0481, {1|U, {0x0480}}},
+ {0x048b, {1|U, {0x048a}}},
+ {0x048d, {1|U, {0x048c}}},
+ {0x048f, {1|U, {0x048e}}},
+ {0x0491, {1|U, {0x0490}}},
+ {0x0493, {1|U, {0x0492}}},
+ {0x0495, {1|U, {0x0494}}},
+ {0x0497, {1|U, {0x0496}}},
+ {0x0499, {1|U, {0x0498}}},
+ {0x049b, {1|U, {0x049a}}},
+ {0x049d, {1|U, {0x049c}}},
+ {0x049f, {1|U, {0x049e}}},
+ {0x04a1, {1|U, {0x04a0}}},
+ {0x04a3, {1|U, {0x04a2}}},
+ {0x04a5, {1|U, {0x04a4}}},
+ {0x04a7, {1|U, {0x04a6}}},
+ {0x04a9, {1|U, {0x04a8}}},
+ {0x04ab, {1|U, {0x04aa}}},
+ {0x04ad, {1|U, {0x04ac}}},
+ {0x04af, {1|U, {0x04ae}}},
+ {0x04b1, {1|U, {0x04b0}}},
+ {0x04b3, {1|U, {0x04b2}}},
+ {0x04b5, {1|U, {0x04b4}}},
+ {0x04b7, {1|U, {0x04b6}}},
+ {0x04b9, {1|U, {0x04b8}}},
+ {0x04bb, {1|U, {0x04ba}}},
+ {0x04bd, {1|U, {0x04bc}}},
+ {0x04bf, {1|U, {0x04be}}},
+ {0x04c2, {1|U, {0x04c1}}},
+ {0x04c4, {1|U, {0x04c3}}},
+ {0x04c6, {1|U, {0x04c5}}},
+ {0x04c8, {1|U, {0x04c7}}},
+ {0x04ca, {1|U, {0x04c9}}},
+ {0x04cc, {1|U, {0x04cb}}},
+ {0x04ce, {1|U, {0x04cd}}},
+ {0x04cf, {1|U, {0x04c0}}},
+ {0x04d1, {1|U, {0x04d0}}},
+ {0x04d3, {1|U, {0x04d2}}},
+ {0x04d5, {1|U, {0x04d4}}},
+ {0x04d7, {1|U, {0x04d6}}},
+ {0x04d9, {1|U, {0x04d8}}},
+ {0x04db, {1|U, {0x04da}}},
+ {0x04dd, {1|U, {0x04dc}}},
+ {0x04df, {1|U, {0x04de}}},
+ {0x04e1, {1|U, {0x04e0}}},
+ {0x04e3, {1|U, {0x04e2}}},
+ {0x04e5, {1|U, {0x04e4}}},
+ {0x04e7, {1|U, {0x04e6}}},
+ {0x04e9, {1|U, {0x04e8}}},
+ {0x04eb, {1|U, {0x04ea}}},
+ {0x04ed, {1|U, {0x04ec}}},
+ {0x04ef, {1|U, {0x04ee}}},
+ {0x04f1, {1|U, {0x04f0}}},
+ {0x04f3, {1|U, {0x04f2}}},
+ {0x04f5, {1|U, {0x04f4}}},
+ {0x04f7, {1|U, {0x04f6}}},
+ {0x04f9, {1|U, {0x04f8}}},
+ {0x04fb, {1|U, {0x04fa}}},
+ {0x04fd, {1|U, {0x04fc}}},
+ {0x04ff, {1|U, {0x04fe}}},
+ {0x0501, {1|U, {0x0500}}},
+ {0x0503, {1|U, {0x0502}}},
+ {0x0505, {1|U, {0x0504}}},
+ {0x0507, {1|U, {0x0506}}},
+ {0x0509, {1|U, {0x0508}}},
+ {0x050b, {1|U, {0x050a}}},
+ {0x050d, {1|U, {0x050c}}},
+ {0x050f, {1|U, {0x050e}}},
+ {0x0511, {1|U, {0x0510}}},
+ {0x0513, {1|U, {0x0512}}},
+ {0x0515, {1|U, {0x0514}}},
+ {0x0517, {1|U, {0x0516}}},
+ {0x0519, {1|U, {0x0518}}},
+ {0x051b, {1|U, {0x051a}}},
+ {0x051d, {1|U, {0x051c}}},
+ {0x051f, {1|U, {0x051e}}},
+ {0x0521, {1|U, {0x0520}}},
+ {0x0523, {1|U, {0x0522}}},
+ {0x0525, {1|U, {0x0524}}},
+ {0x0527, {1|U, {0x0526}}},
+ {0x0529, {1|U, {0x0528}}},
+ {0x052b, {1|U, {0x052a}}},
+ {0x052d, {1|U, {0x052c}}},
+ {0x052f, {1|U, {0x052e}}},
+ {0x0561, {1|U, {0x0531}}},
+ {0x0562, {1|U, {0x0532}}},
+ {0x0563, {1|U, {0x0533}}},
+ {0x0564, {1|U, {0x0534}}},
+ {0x0565, {1|U, {0x0535}}},
+ {0x0566, {1|U, {0x0536}}},
+ {0x0567, {1|U, {0x0537}}},
+ {0x0568, {1|U, {0x0538}}},
+ {0x0569, {1|U, {0x0539}}},
+ {0x056a, {1|U, {0x053a}}},
+ {0x056b, {1|U, {0x053b}}},
+ {0x056c, {1|U, {0x053c}}},
+ {0x056d, {1|U, {0x053d}}},
+ {0x056e, {1|U, {0x053e}}},
+ {0x056f, {1|U, {0x053f}}},
+ {0x0570, {1|U, {0x0540}}},
+ {0x0571, {1|U, {0x0541}}},
+ {0x0572, {1|U, {0x0542}}},
+ {0x0573, {1|U, {0x0543}}},
+ {0x0574, {1|U, {0x0544}}},
+ {0x0575, {1|U, {0x0545}}},
+ {0x0576, {1|U, {0x0546}}},
+ {0x0577, {1|U, {0x0547}}},
+ {0x0578, {1|U, {0x0548}}},
+ {0x0579, {1|U, {0x0549}}},
+ {0x057a, {1|U, {0x054a}}},
+ {0x057b, {1|U, {0x054b}}},
+ {0x057c, {1|U, {0x054c}}},
+ {0x057d, {1|U, {0x054d}}},
+ {0x057e, {1|U, {0x054e}}},
+ {0x057f, {1|U, {0x054f}}},
+ {0x0580, {1|U, {0x0550}}},
+ {0x0581, {1|U, {0x0551}}},
+ {0x0582, {1|U, {0x0552}}},
+ {0x0583, {1|U, {0x0553}}},
+ {0x0584, {1|U, {0x0554}}},
+ {0x0585, {1|U, {0x0555}}},
+ {0x0586, {1|U, {0x0556}}},
+ {0x10d0, {1|U|IT, {0x1c90}}},
+ {0x10d1, {1|U|IT, {0x1c91}}},
+ {0x10d2, {1|U|IT, {0x1c92}}},
+ {0x10d3, {1|U|IT, {0x1c93}}},
+ {0x10d4, {1|U|IT, {0x1c94}}},
+ {0x10d5, {1|U|IT, {0x1c95}}},
+ {0x10d6, {1|U|IT, {0x1c96}}},
+ {0x10d7, {1|U|IT, {0x1c97}}},
+ {0x10d8, {1|U|IT, {0x1c98}}},
+ {0x10d9, {1|U|IT, {0x1c99}}},
+ {0x10da, {1|U|IT, {0x1c9a}}},
+ {0x10db, {1|U|IT, {0x1c9b}}},
+ {0x10dc, {1|U|IT, {0x1c9c}}},
+ {0x10dd, {1|U|IT, {0x1c9d}}},
+ {0x10de, {1|U|IT, {0x1c9e}}},
+ {0x10df, {1|U|IT, {0x1c9f}}},
+ {0x10e0, {1|U|IT, {0x1ca0}}},
+ {0x10e1, {1|U|IT, {0x1ca1}}},
+ {0x10e2, {1|U|IT, {0x1ca2}}},
+ {0x10e3, {1|U|IT, {0x1ca3}}},
+ {0x10e4, {1|U|IT, {0x1ca4}}},
+ {0x10e5, {1|U|IT, {0x1ca5}}},
+ {0x10e6, {1|U|IT, {0x1ca6}}},
+ {0x10e7, {1|U|IT, {0x1ca7}}},
+ {0x10e8, {1|U|IT, {0x1ca8}}},
+ {0x10e9, {1|U|IT, {0x1ca9}}},
+ {0x10ea, {1|U|IT, {0x1caa}}},
+ {0x10eb, {1|U|IT, {0x1cab}}},
+ {0x10ec, {1|U|IT, {0x1cac}}},
+ {0x10ed, {1|U|IT, {0x1cad}}},
+ {0x10ee, {1|U|IT, {0x1cae}}},
+ {0x10ef, {1|U|IT, {0x1caf}}},
+ {0x10f0, {1|U|IT, {0x1cb0}}},
+ {0x10f1, {1|U|IT, {0x1cb1}}},
+ {0x10f2, {1|U|IT, {0x1cb2}}},
+ {0x10f3, {1|U|IT, {0x1cb3}}},
+ {0x10f4, {1|U|IT, {0x1cb4}}},
+ {0x10f5, {1|U|IT, {0x1cb5}}},
+ {0x10f6, {1|U|IT, {0x1cb6}}},
+ {0x10f7, {1|U|IT, {0x1cb7}}},
+ {0x10f8, {1|U|IT, {0x1cb8}}},
+ {0x10f9, {1|U|IT, {0x1cb9}}},
+ {0x10fa, {1|U|IT, {0x1cba}}},
+ {0x10fd, {1|U|IT, {0x1cbd}}},
+ {0x10fe, {1|U|IT, {0x1cbe}}},
+ {0x10ff, {1|U|IT, {0x1cbf}}},
+ {0x13a0, {1|D, {0xab70}}},
+ {0x13a1, {1|D, {0xab71}}},
+ {0x13a2, {1|D, {0xab72}}},
+ {0x13a3, {1|D, {0xab73}}},
+ {0x13a4, {1|D, {0xab74}}},
+ {0x13a5, {1|D, {0xab75}}},
+ {0x13a6, {1|D, {0xab76}}},
+ {0x13a7, {1|D, {0xab77}}},
+ {0x13a8, {1|D, {0xab78}}},
+ {0x13a9, {1|D, {0xab79}}},
+ {0x13aa, {1|D, {0xab7a}}},
+ {0x13ab, {1|D, {0xab7b}}},
+ {0x13ac, {1|D, {0xab7c}}},
+ {0x13ad, {1|D, {0xab7d}}},
+ {0x13ae, {1|D, {0xab7e}}},
+ {0x13af, {1|D, {0xab7f}}},
+ {0x13b0, {1|D, {0xab80}}},
+ {0x13b1, {1|D, {0xab81}}},
+ {0x13b2, {1|D, {0xab82}}},
+ {0x13b3, {1|D, {0xab83}}},
+ {0x13b4, {1|D, {0xab84}}},
+ {0x13b5, {1|D, {0xab85}}},
+ {0x13b6, {1|D, {0xab86}}},
+ {0x13b7, {1|D, {0xab87}}},
+ {0x13b8, {1|D, {0xab88}}},
+ {0x13b9, {1|D, {0xab89}}},
+ {0x13ba, {1|D, {0xab8a}}},
+ {0x13bb, {1|D, {0xab8b}}},
+ {0x13bc, {1|D, {0xab8c}}},
+ {0x13bd, {1|D, {0xab8d}}},
+ {0x13be, {1|D, {0xab8e}}},
+ {0x13bf, {1|D, {0xab8f}}},
+ {0x13c0, {1|D, {0xab90}}},
+ {0x13c1, {1|D, {0xab91}}},
+ {0x13c2, {1|D, {0xab92}}},
+ {0x13c3, {1|D, {0xab93}}},
+ {0x13c4, {1|D, {0xab94}}},
+ {0x13c5, {1|D, {0xab95}}},
+ {0x13c6, {1|D, {0xab96}}},
+ {0x13c7, {1|D, {0xab97}}},
+ {0x13c8, {1|D, {0xab98}}},
+ {0x13c9, {1|D, {0xab99}}},
+ {0x13ca, {1|D, {0xab9a}}},
+ {0x13cb, {1|D, {0xab9b}}},
+ {0x13cc, {1|D, {0xab9c}}},
+ {0x13cd, {1|D, {0xab9d}}},
+ {0x13ce, {1|D, {0xab9e}}},
+ {0x13cf, {1|D, {0xab9f}}},
+ {0x13d0, {1|D, {0xaba0}}},
+ {0x13d1, {1|D, {0xaba1}}},
+ {0x13d2, {1|D, {0xaba2}}},
+ {0x13d3, {1|D, {0xaba3}}},
+ {0x13d4, {1|D, {0xaba4}}},
+ {0x13d5, {1|D, {0xaba5}}},
+ {0x13d6, {1|D, {0xaba6}}},
+ {0x13d7, {1|D, {0xaba7}}},
+ {0x13d8, {1|D, {0xaba8}}},
+ {0x13d9, {1|D, {0xaba9}}},
+ {0x13da, {1|D, {0xabaa}}},
+ {0x13db, {1|D, {0xabab}}},
+ {0x13dc, {1|D, {0xabac}}},
+ {0x13dd, {1|D, {0xabad}}},
+ {0x13de, {1|D, {0xabae}}},
+ {0x13df, {1|D, {0xabaf}}},
+ {0x13e0, {1|D, {0xabb0}}},
+ {0x13e1, {1|D, {0xabb1}}},
+ {0x13e2, {1|D, {0xabb2}}},
+ {0x13e3, {1|D, {0xabb3}}},
+ {0x13e4, {1|D, {0xabb4}}},
+ {0x13e5, {1|D, {0xabb5}}},
+ {0x13e6, {1|D, {0xabb6}}},
+ {0x13e7, {1|D, {0xabb7}}},
+ {0x13e8, {1|D, {0xabb8}}},
+ {0x13e9, {1|D, {0xabb9}}},
+ {0x13ea, {1|D, {0xabba}}},
+ {0x13eb, {1|D, {0xabbb}}},
+ {0x13ec, {1|D, {0xabbc}}},
+ {0x13ed, {1|D, {0xabbd}}},
+ {0x13ee, {1|D, {0xabbe}}},
+ {0x13ef, {1|D, {0xabbf}}},
+ {0x13f0, {1|D, {0x13f8}}},
+ {0x13f1, {1|D, {0x13f9}}},
+ {0x13f2, {1|D, {0x13fa}}},
+ {0x13f3, {1|D, {0x13fb}}},
+ {0x13f4, {1|D, {0x13fc}}},
+ {0x13f5, {1|D, {0x13fd}}},
+ {0x1c8a, {1|U, {0x1c89}}},
+ {0x1d79, {1|U, {0xa77d}}},
+ {0x1d7d, {1|U, {0x2c63}}},
+ {0x1d8e, {1|U, {0xa7c6}}},
+ {0x1e01, {1|U, {0x1e00}}},
+ {0x1e03, {1|U, {0x1e02}}},
+ {0x1e05, {1|U, {0x1e04}}},
+ {0x1e07, {1|U, {0x1e06}}},
+ {0x1e09, {1|U, {0x1e08}}},
+ {0x1e0b, {1|U, {0x1e0a}}},
+ {0x1e0d, {1|U, {0x1e0c}}},
+ {0x1e0f, {1|U, {0x1e0e}}},
+ {0x1e11, {1|U, {0x1e10}}},
+ {0x1e13, {1|U, {0x1e12}}},
+ {0x1e15, {1|U, {0x1e14}}},
+ {0x1e17, {1|U, {0x1e16}}},
+ {0x1e19, {1|U, {0x1e18}}},
+ {0x1e1b, {1|U, {0x1e1a}}},
+ {0x1e1d, {1|U, {0x1e1c}}},
+ {0x1e1f, {1|U, {0x1e1e}}},
+ {0x1e21, {1|U, {0x1e20}}},
+ {0x1e23, {1|U, {0x1e22}}},
+ {0x1e25, {1|U, {0x1e24}}},
+ {0x1e27, {1|U, {0x1e26}}},
+ {0x1e29, {1|U, {0x1e28}}},
+ {0x1e2b, {1|U, {0x1e2a}}},
+ {0x1e2d, {1|U, {0x1e2c}}},
+ {0x1e2f, {1|U, {0x1e2e}}},
+ {0x1e31, {1|U, {0x1e30}}},
+ {0x1e33, {1|U, {0x1e32}}},
+ {0x1e35, {1|U, {0x1e34}}},
+ {0x1e37, {1|U, {0x1e36}}},
+ {0x1e39, {1|U, {0x1e38}}},
+ {0x1e3b, {1|U, {0x1e3a}}},
+ {0x1e3d, {1|U, {0x1e3c}}},
+ {0x1e3f, {1|U, {0x1e3e}}},
+ {0x1e41, {1|U, {0x1e40}}},
+ {0x1e43, {1|U, {0x1e42}}},
+ {0x1e45, {1|U, {0x1e44}}},
+ {0x1e47, {1|U, {0x1e46}}},
+ {0x1e49, {1|U, {0x1e48}}},
+ {0x1e4b, {1|U, {0x1e4a}}},
+ {0x1e4d, {1|U, {0x1e4c}}},
+ {0x1e4f, {1|U, {0x1e4e}}},
+ {0x1e51, {1|U, {0x1e50}}},
+ {0x1e53, {1|U, {0x1e52}}},
+ {0x1e55, {1|U, {0x1e54}}},
+ {0x1e57, {1|U, {0x1e56}}},
+ {0x1e59, {1|U, {0x1e58}}},
+ {0x1e5b, {1|U, {0x1e5a}}},
+ {0x1e5d, {1|U, {0x1e5c}}},
+ {0x1e5f, {1|U, {0x1e5e}}},
+ {0x1e61, {2|U, {0x1e60, 0x1e9b}}},
+ {0x1e63, {1|U, {0x1e62}}},
+ {0x1e65, {1|U, {0x1e64}}},
+ {0x1e67, {1|U, {0x1e66}}},
+ {0x1e69, {1|U, {0x1e68}}},
+ {0x1e6b, {1|U, {0x1e6a}}},
+ {0x1e6d, {1|U, {0x1e6c}}},
+ {0x1e6f, {1|U, {0x1e6e}}},
+ {0x1e71, {1|U, {0x1e70}}},
+ {0x1e73, {1|U, {0x1e72}}},
+ {0x1e75, {1|U, {0x1e74}}},
+ {0x1e77, {1|U, {0x1e76}}},
+ {0x1e79, {1|U, {0x1e78}}},
+ {0x1e7b, {1|U, {0x1e7a}}},
+ {0x1e7d, {1|U, {0x1e7c}}},
+ {0x1e7f, {1|U, {0x1e7e}}},
+ {0x1e81, {1|U, {0x1e80}}},
+ {0x1e83, {1|U, {0x1e82}}},
+ {0x1e85, {1|U, {0x1e84}}},
+ {0x1e87, {1|U, {0x1e86}}},
+ {0x1e89, {1|U, {0x1e88}}},
+ {0x1e8b, {1|U, {0x1e8a}}},
+ {0x1e8d, {1|U, {0x1e8c}}},
+ {0x1e8f, {1|U, {0x1e8e}}},
+ {0x1e91, {1|U, {0x1e90}}},
+ {0x1e93, {1|U, {0x1e92}}},
+ {0x1e95, {1|U, {0x1e94}}},
+ {0x1ea1, {1|U, {0x1ea0}}},
+ {0x1ea3, {1|U, {0x1ea2}}},
+ {0x1ea5, {1|U, {0x1ea4}}},
+ {0x1ea7, {1|U, {0x1ea6}}},
+ {0x1ea9, {1|U, {0x1ea8}}},
+ {0x1eab, {1|U, {0x1eaa}}},
+ {0x1ead, {1|U, {0x1eac}}},
+ {0x1eaf, {1|U, {0x1eae}}},
+ {0x1eb1, {1|U, {0x1eb0}}},
+ {0x1eb3, {1|U, {0x1eb2}}},
+ {0x1eb5, {1|U, {0x1eb4}}},
+ {0x1eb7, {1|U, {0x1eb6}}},
+ {0x1eb9, {1|U, {0x1eb8}}},
+ {0x1ebb, {1|U, {0x1eba}}},
+ {0x1ebd, {1|U, {0x1ebc}}},
+ {0x1ebf, {1|U, {0x1ebe}}},
+ {0x1ec1, {1|U, {0x1ec0}}},
+ {0x1ec3, {1|U, {0x1ec2}}},
+ {0x1ec5, {1|U, {0x1ec4}}},
+ {0x1ec7, {1|U, {0x1ec6}}},
+ {0x1ec9, {1|U, {0x1ec8}}},
+ {0x1ecb, {1|U, {0x1eca}}},
+ {0x1ecd, {1|U, {0x1ecc}}},
+ {0x1ecf, {1|U, {0x1ece}}},
+ {0x1ed1, {1|U, {0x1ed0}}},
+ {0x1ed3, {1|U, {0x1ed2}}},
+ {0x1ed5, {1|U, {0x1ed4}}},
+ {0x1ed7, {1|U, {0x1ed6}}},
+ {0x1ed9, {1|U, {0x1ed8}}},
+ {0x1edb, {1|U, {0x1eda}}},
+ {0x1edd, {1|U, {0x1edc}}},
+ {0x1edf, {1|U, {0x1ede}}},
+ {0x1ee1, {1|U, {0x1ee0}}},
+ {0x1ee3, {1|U, {0x1ee2}}},
+ {0x1ee5, {1|U, {0x1ee4}}},
+ {0x1ee7, {1|U, {0x1ee6}}},
+ {0x1ee9, {1|U, {0x1ee8}}},
+ {0x1eeb, {1|U, {0x1eea}}},
+ {0x1eed, {1|U, {0x1eec}}},
+ {0x1eef, {1|U, {0x1eee}}},
+ {0x1ef1, {1|U, {0x1ef0}}},
+ {0x1ef3, {1|U, {0x1ef2}}},
+ {0x1ef5, {1|U, {0x1ef4}}},
+ {0x1ef7, {1|U, {0x1ef6}}},
+ {0x1ef9, {1|U, {0x1ef8}}},
+ {0x1efb, {1|U, {0x1efa}}},
+ {0x1efd, {1|U, {0x1efc}}},
+ {0x1eff, {1|U, {0x1efe}}},
+ {0x1f00, {1|U, {0x1f08}}},
+ {0x1f01, {1|U, {0x1f09}}},
+ {0x1f02, {1|U, {0x1f0a}}},
+ {0x1f03, {1|U, {0x1f0b}}},
+ {0x1f04, {1|U, {0x1f0c}}},
+ {0x1f05, {1|U, {0x1f0d}}},
+ {0x1f06, {1|U, {0x1f0e}}},
+ {0x1f07, {1|U, {0x1f0f}}},
+ {0x1f10, {1|U, {0x1f18}}},
+ {0x1f11, {1|U, {0x1f19}}},
+ {0x1f12, {1|U, {0x1f1a}}},
+ {0x1f13, {1|U, {0x1f1b}}},
+ {0x1f14, {1|U, {0x1f1c}}},
+ {0x1f15, {1|U, {0x1f1d}}},
+ {0x1f20, {1|U, {0x1f28}}},
+ {0x1f21, {1|U, {0x1f29}}},
+ {0x1f22, {1|U, {0x1f2a}}},
+ {0x1f23, {1|U, {0x1f2b}}},
+ {0x1f24, {1|U, {0x1f2c}}},
+ {0x1f25, {1|U, {0x1f2d}}},
+ {0x1f26, {1|U, {0x1f2e}}},
+ {0x1f27, {1|U, {0x1f2f}}},
+ {0x1f30, {1|U, {0x1f38}}},
+ {0x1f31, {1|U, {0x1f39}}},
+ {0x1f32, {1|U, {0x1f3a}}},
+ {0x1f33, {1|U, {0x1f3b}}},
+ {0x1f34, {1|U, {0x1f3c}}},
+ {0x1f35, {1|U, {0x1f3d}}},
+ {0x1f36, {1|U, {0x1f3e}}},
+ {0x1f37, {1|U, {0x1f3f}}},
+ {0x1f40, {1|U, {0x1f48}}},
+ {0x1f41, {1|U, {0x1f49}}},
+ {0x1f42, {1|U, {0x1f4a}}},
+ {0x1f43, {1|U, {0x1f4b}}},
+ {0x1f44, {1|U, {0x1f4c}}},
+ {0x1f45, {1|U, {0x1f4d}}},
+ {0x1f51, {1|U, {0x1f59}}},
+ {0x1f53, {1|U, {0x1f5b}}},
+ {0x1f55, {1|U, {0x1f5d}}},
+ {0x1f57, {1|U, {0x1f5f}}},
+ {0x1f60, {1|U, {0x1f68}}},
+ {0x1f61, {1|U, {0x1f69}}},
+ {0x1f62, {1|U, {0x1f6a}}},
+ {0x1f63, {1|U, {0x1f6b}}},
+ {0x1f64, {1|U, {0x1f6c}}},
+ {0x1f65, {1|U, {0x1f6d}}},
+ {0x1f66, {1|U, {0x1f6e}}},
+ {0x1f67, {1|U, {0x1f6f}}},
+ {0x1f70, {1|U, {0x1fba}}},
+ {0x1f71, {1|U, {0x1fbb}}},
+ {0x1f72, {1|U, {0x1fc8}}},
+ {0x1f73, {1|U, {0x1fc9}}},
+ {0x1f74, {1|U, {0x1fca}}},
+ {0x1f75, {1|U, {0x1fcb}}},
+ {0x1f76, {1|U, {0x1fda}}},
+ {0x1f77, {1|U, {0x1fdb}}},
+ {0x1f78, {1|U, {0x1ff8}}},
+ {0x1f79, {1|U, {0x1ff9}}},
+ {0x1f7a, {1|U, {0x1fea}}},
+ {0x1f7b, {1|U, {0x1feb}}},
+ {0x1f7c, {1|U, {0x1ffa}}},
+ {0x1f7d, {1|U, {0x1ffb}}},
+ {0x1fb0, {1|U, {0x1fb8}}},
+ {0x1fb1, {1|U, {0x1fb9}}},
+ {0x1fd0, {1|U, {0x1fd8}}},
+ {0x1fd1, {1|U, {0x1fd9}}},
+ {0x1fe0, {1|U, {0x1fe8}}},
+ {0x1fe1, {1|U, {0x1fe9}}},
+ {0x1fe5, {1|U, {0x1fec}}},
+ {0x214e, {1|U, {0x2132}}},
+ {0x2170, {1|U, {0x2160}}},
+ {0x2171, {1|U, {0x2161}}},
+ {0x2172, {1|U, {0x2162}}},
+ {0x2173, {1|U, {0x2163}}},
+ {0x2174, {1|U, {0x2164}}},
+ {0x2175, {1|U, {0x2165}}},
+ {0x2176, {1|U, {0x2166}}},
+ {0x2177, {1|U, {0x2167}}},
+ {0x2178, {1|U, {0x2168}}},
+ {0x2179, {1|U, {0x2169}}},
+ {0x217a, {1|U, {0x216a}}},
+ {0x217b, {1|U, {0x216b}}},
+ {0x217c, {1|U, {0x216c}}},
+ {0x217d, {1|U, {0x216d}}},
+ {0x217e, {1|U, {0x216e}}},
+ {0x217f, {1|U, {0x216f}}},
+ {0x2184, {1|U, {0x2183}}},
+ {0x24d0, {1|U, {0x24b6}}},
+ {0x24d1, {1|U, {0x24b7}}},
+ {0x24d2, {1|U, {0x24b8}}},
+ {0x24d3, {1|U, {0x24b9}}},
+ {0x24d4, {1|U, {0x24ba}}},
+ {0x24d5, {1|U, {0x24bb}}},
+ {0x24d6, {1|U, {0x24bc}}},
+ {0x24d7, {1|U, {0x24bd}}},
+ {0x24d8, {1|U, {0x24be}}},
+ {0x24d9, {1|U, {0x24bf}}},
+ {0x24da, {1|U, {0x24c0}}},
+ {0x24db, {1|U, {0x24c1}}},
+ {0x24dc, {1|U, {0x24c2}}},
+ {0x24dd, {1|U, {0x24c3}}},
+ {0x24de, {1|U, {0x24c4}}},
+ {0x24df, {1|U, {0x24c5}}},
+ {0x24e0, {1|U, {0x24c6}}},
+ {0x24e1, {1|U, {0x24c7}}},
+ {0x24e2, {1|U, {0x24c8}}},
+ {0x24e3, {1|U, {0x24c9}}},
+ {0x24e4, {1|U, {0x24ca}}},
+ {0x24e5, {1|U, {0x24cb}}},
+ {0x24e6, {1|U, {0x24cc}}},
+ {0x24e7, {1|U, {0x24cd}}},
+ {0x24e8, {1|U, {0x24ce}}},
+ {0x24e9, {1|U, {0x24cf}}},
+ {0x2c30, {1|U, {0x2c00}}},
+ {0x2c31, {1|U, {0x2c01}}},
+ {0x2c32, {1|U, {0x2c02}}},
+ {0x2c33, {1|U, {0x2c03}}},
+ {0x2c34, {1|U, {0x2c04}}},
+ {0x2c35, {1|U, {0x2c05}}},
+ {0x2c36, {1|U, {0x2c06}}},
+ {0x2c37, {1|U, {0x2c07}}},
+ {0x2c38, {1|U, {0x2c08}}},
+ {0x2c39, {1|U, {0x2c09}}},
+ {0x2c3a, {1|U, {0x2c0a}}},
+ {0x2c3b, {1|U, {0x2c0b}}},
+ {0x2c3c, {1|U, {0x2c0c}}},
+ {0x2c3d, {1|U, {0x2c0d}}},
+ {0x2c3e, {1|U, {0x2c0e}}},
+ {0x2c3f, {1|U, {0x2c0f}}},
+ {0x2c40, {1|U, {0x2c10}}},
+ {0x2c41, {1|U, {0x2c11}}},
+ {0x2c42, {1|U, {0x2c12}}},
+ {0x2c43, {1|U, {0x2c13}}},
+ {0x2c44, {1|U, {0x2c14}}},
+ {0x2c45, {1|U, {0x2c15}}},
+ {0x2c46, {1|U, {0x2c16}}},
+ {0x2c47, {1|U, {0x2c17}}},
+ {0x2c48, {1|U, {0x2c18}}},
+ {0x2c49, {1|U, {0x2c19}}},
+ {0x2c4a, {1|U, {0x2c1a}}},
+ {0x2c4b, {1|U, {0x2c1b}}},
+ {0x2c4c, {1|U, {0x2c1c}}},
+ {0x2c4d, {1|U, {0x2c1d}}},
+ {0x2c4e, {1|U, {0x2c1e}}},
+ {0x2c4f, {1|U, {0x2c1f}}},
+ {0x2c50, {1|U, {0x2c20}}},
+ {0x2c51, {1|U, {0x2c21}}},
+ {0x2c52, {1|U, {0x2c22}}},
+ {0x2c53, {1|U, {0x2c23}}},
+ {0x2c54, {1|U, {0x2c24}}},
+ {0x2c55, {1|U, {0x2c25}}},
+ {0x2c56, {1|U, {0x2c26}}},
+ {0x2c57, {1|U, {0x2c27}}},
+ {0x2c58, {1|U, {0x2c28}}},
+ {0x2c59, {1|U, {0x2c29}}},
+ {0x2c5a, {1|U, {0x2c2a}}},
+ {0x2c5b, {1|U, {0x2c2b}}},
+ {0x2c5c, {1|U, {0x2c2c}}},
+ {0x2c5d, {1|U, {0x2c2d}}},
+ {0x2c5e, {1|U, {0x2c2e}}},
+ {0x2c5f, {1|U, {0x2c2f}}},
+ {0x2c61, {1|U, {0x2c60}}},
+ {0x2c65, {1|U, {0x023a}}},
+ {0x2c66, {1|U, {0x023e}}},
+ {0x2c68, {1|U, {0x2c67}}},
+ {0x2c6a, {1|U, {0x2c69}}},
+ {0x2c6c, {1|U, {0x2c6b}}},
+ {0x2c73, {1|U, {0x2c72}}},
+ {0x2c76, {1|U, {0x2c75}}},
+ {0x2c81, {1|U, {0x2c80}}},
+ {0x2c83, {1|U, {0x2c82}}},
+ {0x2c85, {1|U, {0x2c84}}},
+ {0x2c87, {1|U, {0x2c86}}},
+ {0x2c89, {1|U, {0x2c88}}},
+ {0x2c8b, {1|U, {0x2c8a}}},
+ {0x2c8d, {1|U, {0x2c8c}}},
+ {0x2c8f, {1|U, {0x2c8e}}},
+ {0x2c91, {1|U, {0x2c90}}},
+ {0x2c93, {1|U, {0x2c92}}},
+ {0x2c95, {1|U, {0x2c94}}},
+ {0x2c97, {1|U, {0x2c96}}},
+ {0x2c99, {1|U, {0x2c98}}},
+ {0x2c9b, {1|U, {0x2c9a}}},
+ {0x2c9d, {1|U, {0x2c9c}}},
+ {0x2c9f, {1|U, {0x2c9e}}},
+ {0x2ca1, {1|U, {0x2ca0}}},
+ {0x2ca3, {1|U, {0x2ca2}}},
+ {0x2ca5, {1|U, {0x2ca4}}},
+ {0x2ca7, {1|U, {0x2ca6}}},
+ {0x2ca9, {1|U, {0x2ca8}}},
+ {0x2cab, {1|U, {0x2caa}}},
+ {0x2cad, {1|U, {0x2cac}}},
+ {0x2caf, {1|U, {0x2cae}}},
+ {0x2cb1, {1|U, {0x2cb0}}},
+ {0x2cb3, {1|U, {0x2cb2}}},
+ {0x2cb5, {1|U, {0x2cb4}}},
+ {0x2cb7, {1|U, {0x2cb6}}},
+ {0x2cb9, {1|U, {0x2cb8}}},
+ {0x2cbb, {1|U, {0x2cba}}},
+ {0x2cbd, {1|U, {0x2cbc}}},
+ {0x2cbf, {1|U, {0x2cbe}}},
+ {0x2cc1, {1|U, {0x2cc0}}},
+ {0x2cc3, {1|U, {0x2cc2}}},
+ {0x2cc5, {1|U, {0x2cc4}}},
+ {0x2cc7, {1|U, {0x2cc6}}},
+ {0x2cc9, {1|U, {0x2cc8}}},
+ {0x2ccb, {1|U, {0x2cca}}},
+ {0x2ccd, {1|U, {0x2ccc}}},
+ {0x2ccf, {1|U, {0x2cce}}},
+ {0x2cd1, {1|U, {0x2cd0}}},
+ {0x2cd3, {1|U, {0x2cd2}}},
+ {0x2cd5, {1|U, {0x2cd4}}},
+ {0x2cd7, {1|U, {0x2cd6}}},
+ {0x2cd9, {1|U, {0x2cd8}}},
+ {0x2cdb, {1|U, {0x2cda}}},
+ {0x2cdd, {1|U, {0x2cdc}}},
+ {0x2cdf, {1|U, {0x2cde}}},
+ {0x2ce1, {1|U, {0x2ce0}}},
+ {0x2ce3, {1|U, {0x2ce2}}},
+ {0x2cec, {1|U, {0x2ceb}}},
+ {0x2cee, {1|U, {0x2ced}}},
+ {0x2cf3, {1|U, {0x2cf2}}},
+ {0x2d00, {1|U, {0x10a0}}},
+ {0x2d01, {1|U, {0x10a1}}},
+ {0x2d02, {1|U, {0x10a2}}},
+ {0x2d03, {1|U, {0x10a3}}},
+ {0x2d04, {1|U, {0x10a4}}},
+ {0x2d05, {1|U, {0x10a5}}},
+ {0x2d06, {1|U, {0x10a6}}},
+ {0x2d07, {1|U, {0x10a7}}},
+ {0x2d08, {1|U, {0x10a8}}},
+ {0x2d09, {1|U, {0x10a9}}},
+ {0x2d0a, {1|U, {0x10aa}}},
+ {0x2d0b, {1|U, {0x10ab}}},
+ {0x2d0c, {1|U, {0x10ac}}},
+ {0x2d0d, {1|U, {0x10ad}}},
+ {0x2d0e, {1|U, {0x10ae}}},
+ {0x2d0f, {1|U, {0x10af}}},
+ {0x2d10, {1|U, {0x10b0}}},
+ {0x2d11, {1|U, {0x10b1}}},
+ {0x2d12, {1|U, {0x10b2}}},
+ {0x2d13, {1|U, {0x10b3}}},
+ {0x2d14, {1|U, {0x10b4}}},
+ {0x2d15, {1|U, {0x10b5}}},
+ {0x2d16, {1|U, {0x10b6}}},
+ {0x2d17, {1|U, {0x10b7}}},
+ {0x2d18, {1|U, {0x10b8}}},
+ {0x2d19, {1|U, {0x10b9}}},
+ {0x2d1a, {1|U, {0x10ba}}},
+ {0x2d1b, {1|U, {0x10bb}}},
+ {0x2d1c, {1|U, {0x10bc}}},
+ {0x2d1d, {1|U, {0x10bd}}},
+ {0x2d1e, {1|U, {0x10be}}},
+ {0x2d1f, {1|U, {0x10bf}}},
+ {0x2d20, {1|U, {0x10c0}}},
+ {0x2d21, {1|U, {0x10c1}}},
+ {0x2d22, {1|U, {0x10c2}}},
+ {0x2d23, {1|U, {0x10c3}}},
+ {0x2d24, {1|U, {0x10c4}}},
+ {0x2d25, {1|U, {0x10c5}}},
+ {0x2d27, {1|U, {0x10c7}}},
+ {0x2d2d, {1|U, {0x10cd}}},
+ {0xa641, {1|U, {0xa640}}},
+ {0xa643, {1|U, {0xa642}}},
+ {0xa645, {1|U, {0xa644}}},
+ {0xa647, {1|U, {0xa646}}},
+ {0xa649, {1|U, {0xa648}}},
+ {0xa64b, {2|U, {0xa64a, 0x1c88}}},
+ {0xa64d, {1|U, {0xa64c}}},
+ {0xa64f, {1|U, {0xa64e}}},
+ {0xa651, {1|U, {0xa650}}},
+ {0xa653, {1|U, {0xa652}}},
+ {0xa655, {1|U, {0xa654}}},
+ {0xa657, {1|U, {0xa656}}},
+ {0xa659, {1|U, {0xa658}}},
+ {0xa65b, {1|U, {0xa65a}}},
+ {0xa65d, {1|U, {0xa65c}}},
+ {0xa65f, {1|U, {0xa65e}}},
+ {0xa661, {1|U, {0xa660}}},
+ {0xa663, {1|U, {0xa662}}},
+ {0xa665, {1|U, {0xa664}}},
+ {0xa667, {1|U, {0xa666}}},
+ {0xa669, {1|U, {0xa668}}},
+ {0xa66b, {1|U, {0xa66a}}},
+ {0xa66d, {1|U, {0xa66c}}},
+ {0xa681, {1|U, {0xa680}}},
+ {0xa683, {1|U, {0xa682}}},
+ {0xa685, {1|U, {0xa684}}},
+ {0xa687, {1|U, {0xa686}}},
+ {0xa689, {1|U, {0xa688}}},
+ {0xa68b, {1|U, {0xa68a}}},
+ {0xa68d, {1|U, {0xa68c}}},
+ {0xa68f, {1|U, {0xa68e}}},
+ {0xa691, {1|U, {0xa690}}},
+ {0xa693, {1|U, {0xa692}}},
+ {0xa695, {1|U, {0xa694}}},
+ {0xa697, {1|U, {0xa696}}},
+ {0xa699, {1|U, {0xa698}}},
+ {0xa69b, {1|U, {0xa69a}}},
+ {0xa723, {1|U, {0xa722}}},
+ {0xa725, {1|U, {0xa724}}},
+ {0xa727, {1|U, {0xa726}}},
+ {0xa729, {1|U, {0xa728}}},
+ {0xa72b, {1|U, {0xa72a}}},
+ {0xa72d, {1|U, {0xa72c}}},
+ {0xa72f, {1|U, {0xa72e}}},
+ {0xa733, {1|U, {0xa732}}},
+ {0xa735, {1|U, {0xa734}}},
+ {0xa737, {1|U, {0xa736}}},
+ {0xa739, {1|U, {0xa738}}},
+ {0xa73b, {1|U, {0xa73a}}},
+ {0xa73d, {1|U, {0xa73c}}},
+ {0xa73f, {1|U, {0xa73e}}},
+ {0xa741, {1|U, {0xa740}}},
+ {0xa743, {1|U, {0xa742}}},
+ {0xa745, {1|U, {0xa744}}},
+ {0xa747, {1|U, {0xa746}}},
+ {0xa749, {1|U, {0xa748}}},
+ {0xa74b, {1|U, {0xa74a}}},
+ {0xa74d, {1|U, {0xa74c}}},
+ {0xa74f, {1|U, {0xa74e}}},
+ {0xa751, {1|U, {0xa750}}},
+ {0xa753, {1|U, {0xa752}}},
+ {0xa755, {1|U, {0xa754}}},
+ {0xa757, {1|U, {0xa756}}},
+ {0xa759, {1|U, {0xa758}}},
+ {0xa75b, {1|U, {0xa75a}}},
+ {0xa75d, {1|U, {0xa75c}}},
+ {0xa75f, {1|U, {0xa75e}}},
+ {0xa761, {1|U, {0xa760}}},
+ {0xa763, {1|U, {0xa762}}},
+ {0xa765, {1|U, {0xa764}}},
+ {0xa767, {1|U, {0xa766}}},
+ {0xa769, {1|U, {0xa768}}},
+ {0xa76b, {1|U, {0xa76a}}},
+ {0xa76d, {1|U, {0xa76c}}},
+ {0xa76f, {1|U, {0xa76e}}},
+ {0xa77a, {1|U, {0xa779}}},
+ {0xa77c, {1|U, {0xa77b}}},
+ {0xa77f, {1|U, {0xa77e}}},
+ {0xa781, {1|U, {0xa780}}},
+ {0xa783, {1|U, {0xa782}}},
+ {0xa785, {1|U, {0xa784}}},
+ {0xa787, {1|U, {0xa786}}},
+ {0xa78c, {1|U, {0xa78b}}},
+ {0xa791, {1|U, {0xa790}}},
+ {0xa793, {1|U, {0xa792}}},
+ {0xa794, {1|U, {0xa7c4}}},
+ {0xa797, {1|U, {0xa796}}},
+ {0xa799, {1|U, {0xa798}}},
+ {0xa79b, {1|U, {0xa79a}}},
+ {0xa79d, {1|U, {0xa79c}}},
+ {0xa79f, {1|U, {0xa79e}}},
+ {0xa7a1, {1|U, {0xa7a0}}},
+ {0xa7a3, {1|U, {0xa7a2}}},
+ {0xa7a5, {1|U, {0xa7a4}}},
+ {0xa7a7, {1|U, {0xa7a6}}},
+ {0xa7a9, {1|U, {0xa7a8}}},
+ {0xa7b5, {1|U, {0xa7b4}}},
+ {0xa7b7, {1|U, {0xa7b6}}},
+ {0xa7b9, {1|U, {0xa7b8}}},
+ {0xa7bb, {1|U, {0xa7ba}}},
+ {0xa7bd, {1|U, {0xa7bc}}},
+ {0xa7bf, {1|U, {0xa7be}}},
+ {0xa7c1, {1|U, {0xa7c0}}},
+ {0xa7c3, {1|U, {0xa7c2}}},
+ {0xa7c8, {1|U, {0xa7c7}}},
+ {0xa7ca, {1|U, {0xa7c9}}},
+ {0xa7cd, {1|U, {0xa7cc}}},
+ {0xa7cf, {1|U, {0xa7ce}}},
+ {0xa7d1, {1|U, {0xa7d0}}},
+ {0xa7d3, {1|U, {0xa7d2}}},
+ {0xa7d5, {1|U, {0xa7d4}}},
+ {0xa7d7, {1|U, {0xa7d6}}},
+ {0xa7d9, {1|U, {0xa7d8}}},
+ {0xa7db, {1|U, {0xa7da}}},
+ {0xa7f6, {1|U, {0xa7f5}}},
+ {0xab53, {1|U, {0xa7b3}}},
+ {0xff41, {1|U, {0xff21}}},
+ {0xff42, {1|U, {0xff22}}},
+ {0xff43, {1|U, {0xff23}}},
+ {0xff44, {1|U, {0xff24}}},
+ {0xff45, {1|U, {0xff25}}},
+ {0xff46, {1|U, {0xff26}}},
+ {0xff47, {1|U, {0xff27}}},
+ {0xff48, {1|U, {0xff28}}},
+ {0xff49, {1|U, {0xff29}}},
+ {0xff4a, {1|U, {0xff2a}}},
+ {0xff4b, {1|U, {0xff2b}}},
+ {0xff4c, {1|U, {0xff2c}}},
+ {0xff4d, {1|U, {0xff2d}}},
+ {0xff4e, {1|U, {0xff2e}}},
+ {0xff4f, {1|U, {0xff2f}}},
+ {0xff50, {1|U, {0xff30}}},
+ {0xff51, {1|U, {0xff31}}},
+ {0xff52, {1|U, {0xff32}}},
+ {0xff53, {1|U, {0xff33}}},
+ {0xff54, {1|U, {0xff34}}},
+ {0xff55, {1|U, {0xff35}}},
+ {0xff56, {1|U, {0xff36}}},
+ {0xff57, {1|U, {0xff37}}},
+ {0xff58, {1|U, {0xff38}}},
+ {0xff59, {1|U, {0xff39}}},
+ {0xff5a, {1|U, {0xff3a}}},
+ {0x10428, {1|U, {0x10400}}},
+ {0x10429, {1|U, {0x10401}}},
+ {0x1042a, {1|U, {0x10402}}},
+ {0x1042b, {1|U, {0x10403}}},
+ {0x1042c, {1|U, {0x10404}}},
+ {0x1042d, {1|U, {0x10405}}},
+ {0x1042e, {1|U, {0x10406}}},
+ {0x1042f, {1|U, {0x10407}}},
+ {0x10430, {1|U, {0x10408}}},
+ {0x10431, {1|U, {0x10409}}},
+ {0x10432, {1|U, {0x1040a}}},
+ {0x10433, {1|U, {0x1040b}}},
+ {0x10434, {1|U, {0x1040c}}},
+ {0x10435, {1|U, {0x1040d}}},
+ {0x10436, {1|U, {0x1040e}}},
+ {0x10437, {1|U, {0x1040f}}},
+ {0x10438, {1|U, {0x10410}}},
+ {0x10439, {1|U, {0x10411}}},
+ {0x1043a, {1|U, {0x10412}}},
+ {0x1043b, {1|U, {0x10413}}},
+ {0x1043c, {1|U, {0x10414}}},
+ {0x1043d, {1|U, {0x10415}}},
+ {0x1043e, {1|U, {0x10416}}},
+ {0x1043f, {1|U, {0x10417}}},
+ {0x10440, {1|U, {0x10418}}},
+ {0x10441, {1|U, {0x10419}}},
+ {0x10442, {1|U, {0x1041a}}},
+ {0x10443, {1|U, {0x1041b}}},
+ {0x10444, {1|U, {0x1041c}}},
+ {0x10445, {1|U, {0x1041d}}},
+ {0x10446, {1|U, {0x1041e}}},
+ {0x10447, {1|U, {0x1041f}}},
+ {0x10448, {1|U, {0x10420}}},
+ {0x10449, {1|U, {0x10421}}},
+ {0x1044a, {1|U, {0x10422}}},
+ {0x1044b, {1|U, {0x10423}}},
+ {0x1044c, {1|U, {0x10424}}},
+ {0x1044d, {1|U, {0x10425}}},
+ {0x1044e, {1|U, {0x10426}}},
+ {0x1044f, {1|U, {0x10427}}},
+ {0x104d8, {1|U, {0x104b0}}},
+ {0x104d9, {1|U, {0x104b1}}},
+ {0x104da, {1|U, {0x104b2}}},
+ {0x104db, {1|U, {0x104b3}}},
+ {0x104dc, {1|U, {0x104b4}}},
+ {0x104dd, {1|U, {0x104b5}}},
+ {0x104de, {1|U, {0x104b6}}},
+ {0x104df, {1|U, {0x104b7}}},
+ {0x104e0, {1|U, {0x104b8}}},
+ {0x104e1, {1|U, {0x104b9}}},
+ {0x104e2, {1|U, {0x104ba}}},
+ {0x104e3, {1|U, {0x104bb}}},
+ {0x104e4, {1|U, {0x104bc}}},
+ {0x104e5, {1|U, {0x104bd}}},
+ {0x104e6, {1|U, {0x104be}}},
+ {0x104e7, {1|U, {0x104bf}}},
+ {0x104e8, {1|U, {0x104c0}}},
+ {0x104e9, {1|U, {0x104c1}}},
+ {0x104ea, {1|U, {0x104c2}}},
+ {0x104eb, {1|U, {0x104c3}}},
+ {0x104ec, {1|U, {0x104c4}}},
+ {0x104ed, {1|U, {0x104c5}}},
+ {0x104ee, {1|U, {0x104c6}}},
+ {0x104ef, {1|U, {0x104c7}}},
+ {0x104f0, {1|U, {0x104c8}}},
+ {0x104f1, {1|U, {0x104c9}}},
+ {0x104f2, {1|U, {0x104ca}}},
+ {0x104f3, {1|U, {0x104cb}}},
+ {0x104f4, {1|U, {0x104cc}}},
+ {0x104f5, {1|U, {0x104cd}}},
+ {0x104f6, {1|U, {0x104ce}}},
+ {0x104f7, {1|U, {0x104cf}}},
+ {0x104f8, {1|U, {0x104d0}}},
+ {0x104f9, {1|U, {0x104d1}}},
+ {0x104fa, {1|U, {0x104d2}}},
+ {0x104fb, {1|U, {0x104d3}}},
+ {0x10597, {1|U, {0x10570}}},
+ {0x10598, {1|U, {0x10571}}},
+ {0x10599, {1|U, {0x10572}}},
+ {0x1059a, {1|U, {0x10573}}},
+ {0x1059b, {1|U, {0x10574}}},
+ {0x1059c, {1|U, {0x10575}}},
+ {0x1059d, {1|U, {0x10576}}},
+ {0x1059e, {1|U, {0x10577}}},
+ {0x1059f, {1|U, {0x10578}}},
+ {0x105a0, {1|U, {0x10579}}},
+ {0x105a1, {1|U, {0x1057a}}},
+ {0x105a3, {1|U, {0x1057c}}},
+ {0x105a4, {1|U, {0x1057d}}},
+ {0x105a5, {1|U, {0x1057e}}},
+ {0x105a6, {1|U, {0x1057f}}},
+ {0x105a7, {1|U, {0x10580}}},
+ {0x105a8, {1|U, {0x10581}}},
+ {0x105a9, {1|U, {0x10582}}},
+ {0x105aa, {1|U, {0x10583}}},
+ {0x105ab, {1|U, {0x10584}}},
+ {0x105ac, {1|U, {0x10585}}},
+ {0x105ad, {1|U, {0x10586}}},
+ {0x105ae, {1|U, {0x10587}}},
+ {0x105af, {1|U, {0x10588}}},
+ {0x105b0, {1|U, {0x10589}}},
+ {0x105b1, {1|U, {0x1058a}}},
+ {0x105b3, {1|U, {0x1058c}}},
+ {0x105b4, {1|U, {0x1058d}}},
+ {0x105b5, {1|U, {0x1058e}}},
+ {0x105b6, {1|U, {0x1058f}}},
+ {0x105b7, {1|U, {0x10590}}},
+ {0x105b8, {1|U, {0x10591}}},
+ {0x105b9, {1|U, {0x10592}}},
+ {0x105bb, {1|U, {0x10594}}},
+ {0x105bc, {1|U, {0x10595}}},
+ {0x10cc0, {1|U, {0x10c80}}},
+ {0x10cc1, {1|U, {0x10c81}}},
+ {0x10cc2, {1|U, {0x10c82}}},
+ {0x10cc3, {1|U, {0x10c83}}},
+ {0x10cc4, {1|U, {0x10c84}}},
+ {0x10cc5, {1|U, {0x10c85}}},
+ {0x10cc6, {1|U, {0x10c86}}},
+ {0x10cc7, {1|U, {0x10c87}}},
+ {0x10cc8, {1|U, {0x10c88}}},
+ {0x10cc9, {1|U, {0x10c89}}},
+ {0x10cca, {1|U, {0x10c8a}}},
+ {0x10ccb, {1|U, {0x10c8b}}},
+ {0x10ccc, {1|U, {0x10c8c}}},
+ {0x10ccd, {1|U, {0x10c8d}}},
+ {0x10cce, {1|U, {0x10c8e}}},
+ {0x10ccf, {1|U, {0x10c8f}}},
+ {0x10cd0, {1|U, {0x10c90}}},
+ {0x10cd1, {1|U, {0x10c91}}},
+ {0x10cd2, {1|U, {0x10c92}}},
+ {0x10cd3, {1|U, {0x10c93}}},
+ {0x10cd4, {1|U, {0x10c94}}},
+ {0x10cd5, {1|U, {0x10c95}}},
+ {0x10cd6, {1|U, {0x10c96}}},
+ {0x10cd7, {1|U, {0x10c97}}},
+ {0x10cd8, {1|U, {0x10c98}}},
+ {0x10cd9, {1|U, {0x10c99}}},
+ {0x10cda, {1|U, {0x10c9a}}},
+ {0x10cdb, {1|U, {0x10c9b}}},
+ {0x10cdc, {1|U, {0x10c9c}}},
+ {0x10cdd, {1|U, {0x10c9d}}},
+ {0x10cde, {1|U, {0x10c9e}}},
+ {0x10cdf, {1|U, {0x10c9f}}},
+ {0x10ce0, {1|U, {0x10ca0}}},
+ {0x10ce1, {1|U, {0x10ca1}}},
+ {0x10ce2, {1|U, {0x10ca2}}},
+ {0x10ce3, {1|U, {0x10ca3}}},
+ {0x10ce4, {1|U, {0x10ca4}}},
+ {0x10ce5, {1|U, {0x10ca5}}},
+ {0x10ce6, {1|U, {0x10ca6}}},
+ {0x10ce7, {1|U, {0x10ca7}}},
+ {0x10ce8, {1|U, {0x10ca8}}},
+ {0x10ce9, {1|U, {0x10ca9}}},
+ {0x10cea, {1|U, {0x10caa}}},
+ {0x10ceb, {1|U, {0x10cab}}},
+ {0x10cec, {1|U, {0x10cac}}},
+ {0x10ced, {1|U, {0x10cad}}},
+ {0x10cee, {1|U, {0x10cae}}},
+ {0x10cef, {1|U, {0x10caf}}},
+ {0x10cf0, {1|U, {0x10cb0}}},
+ {0x10cf1, {1|U, {0x10cb1}}},
+ {0x10cf2, {1|U, {0x10cb2}}},
+ {0x10d70, {1|U, {0x10d50}}},
+ {0x10d71, {1|U, {0x10d51}}},
+ {0x10d72, {1|U, {0x10d52}}},
+ {0x10d73, {1|U, {0x10d53}}},
+ {0x10d74, {1|U, {0x10d54}}},
+ {0x10d75, {1|U, {0x10d55}}},
+ {0x10d76, {1|U, {0x10d56}}},
+ {0x10d77, {1|U, {0x10d57}}},
+ {0x10d78, {1|U, {0x10d58}}},
+ {0x10d79, {1|U, {0x10d59}}},
+ {0x10d7a, {1|U, {0x10d5a}}},
+ {0x10d7b, {1|U, {0x10d5b}}},
+ {0x10d7c, {1|U, {0x10d5c}}},
+ {0x10d7d, {1|U, {0x10d5d}}},
+ {0x10d7e, {1|U, {0x10d5e}}},
+ {0x10d7f, {1|U, {0x10d5f}}},
+ {0x10d80, {1|U, {0x10d60}}},
+ {0x10d81, {1|U, {0x10d61}}},
+ {0x10d82, {1|U, {0x10d62}}},
+ {0x10d83, {1|U, {0x10d63}}},
+ {0x10d84, {1|U, {0x10d64}}},
+ {0x10d85, {1|U, {0x10d65}}},
+ {0x118c0, {1|U, {0x118a0}}},
+ {0x118c1, {1|U, {0x118a1}}},
+ {0x118c2, {1|U, {0x118a2}}},
+ {0x118c3, {1|U, {0x118a3}}},
+ {0x118c4, {1|U, {0x118a4}}},
+ {0x118c5, {1|U, {0x118a5}}},
+ {0x118c6, {1|U, {0x118a6}}},
+ {0x118c7, {1|U, {0x118a7}}},
+ {0x118c8, {1|U, {0x118a8}}},
+ {0x118c9, {1|U, {0x118a9}}},
+ {0x118ca, {1|U, {0x118aa}}},
+ {0x118cb, {1|U, {0x118ab}}},
+ {0x118cc, {1|U, {0x118ac}}},
+ {0x118cd, {1|U, {0x118ad}}},
+ {0x118ce, {1|U, {0x118ae}}},
+ {0x118cf, {1|U, {0x118af}}},
+ {0x118d0, {1|U, {0x118b0}}},
+ {0x118d1, {1|U, {0x118b1}}},
+ {0x118d2, {1|U, {0x118b2}}},
+ {0x118d3, {1|U, {0x118b3}}},
+ {0x118d4, {1|U, {0x118b4}}},
+ {0x118d5, {1|U, {0x118b5}}},
+ {0x118d6, {1|U, {0x118b6}}},
+ {0x118d7, {1|U, {0x118b7}}},
+ {0x118d8, {1|U, {0x118b8}}},
+ {0x118d9, {1|U, {0x118b9}}},
+ {0x118da, {1|U, {0x118ba}}},
+ {0x118db, {1|U, {0x118bb}}},
+ {0x118dc, {1|U, {0x118bc}}},
+ {0x118dd, {1|U, {0x118bd}}},
+ {0x118de, {1|U, {0x118be}}},
+ {0x118df, {1|U, {0x118bf}}},
+ {0x16e60, {1|U, {0x16e40}}},
+ {0x16e61, {1|U, {0x16e41}}},
+ {0x16e62, {1|U, {0x16e42}}},
+ {0x16e63, {1|U, {0x16e43}}},
+ {0x16e64, {1|U, {0x16e44}}},
+ {0x16e65, {1|U, {0x16e45}}},
+ {0x16e66, {1|U, {0x16e46}}},
+ {0x16e67, {1|U, {0x16e47}}},
+ {0x16e68, {1|U, {0x16e48}}},
+ {0x16e69, {1|U, {0x16e49}}},
+ {0x16e6a, {1|U, {0x16e4a}}},
+ {0x16e6b, {1|U, {0x16e4b}}},
+ {0x16e6c, {1|U, {0x16e4c}}},
+ {0x16e6d, {1|U, {0x16e4d}}},
+ {0x16e6e, {1|U, {0x16e4e}}},
+ {0x16e6f, {1|U, {0x16e4f}}},
+ {0x16e70, {1|U, {0x16e50}}},
+ {0x16e71, {1|U, {0x16e51}}},
+ {0x16e72, {1|U, {0x16e52}}},
+ {0x16e73, {1|U, {0x16e53}}},
+ {0x16e74, {1|U, {0x16e54}}},
+ {0x16e75, {1|U, {0x16e55}}},
+ {0x16e76, {1|U, {0x16e56}}},
+ {0x16e77, {1|U, {0x16e57}}},
+ {0x16e78, {1|U, {0x16e58}}},
+ {0x16e79, {1|U, {0x16e59}}},
+ {0x16e7a, {1|U, {0x16e5a}}},
+ {0x16e7b, {1|U, {0x16e5b}}},
+ {0x16e7c, {1|U, {0x16e5c}}},
+ {0x16e7d, {1|U, {0x16e5d}}},
+ {0x16e7e, {1|U, {0x16e5e}}},
+ {0x16e7f, {1|U, {0x16e5f}}},
+ {0x16ebb, {1|U, {0x16ea0}}},
+ {0x16ebc, {1|U, {0x16ea1}}},
+ {0x16ebd, {1|U, {0x16ea2}}},
+ {0x16ebe, {1|U, {0x16ea3}}},
+ {0x16ebf, {1|U, {0x16ea4}}},
+ {0x16ec0, {1|U, {0x16ea5}}},
+ {0x16ec1, {1|U, {0x16ea6}}},
+ {0x16ec2, {1|U, {0x16ea7}}},
+ {0x16ec3, {1|U, {0x16ea8}}},
+ {0x16ec4, {1|U, {0x16ea9}}},
+ {0x16ec5, {1|U, {0x16eaa}}},
+ {0x16ec6, {1|U, {0x16eab}}},
+ {0x16ec7, {1|U, {0x16eac}}},
+ {0x16ec8, {1|U, {0x16ead}}},
+ {0x16ec9, {1|U, {0x16eae}}},
+ {0x16eca, {1|U, {0x16eaf}}},
+ {0x16ecb, {1|U, {0x16eb0}}},
+ {0x16ecc, {1|U, {0x16eb1}}},
+ {0x16ecd, {1|U, {0x16eb2}}},
+ {0x16ece, {1|U, {0x16eb3}}},
+ {0x16ecf, {1|U, {0x16eb4}}},
+ {0x16ed0, {1|U, {0x16eb5}}},
+ {0x16ed1, {1|U, {0x16eb6}}},
+ {0x16ed2, {1|U, {0x16eb7}}},
+ {0x16ed3, {1|U, {0x16eb8}}},
+ {0x1e922, {1|U, {0x1e900}}},
+ {0x1e923, {1|U, {0x1e901}}},
+ {0x1e924, {1|U, {0x1e902}}},
+ {0x1e925, {1|U, {0x1e903}}},
+ {0x1e926, {1|U, {0x1e904}}},
+ {0x1e927, {1|U, {0x1e905}}},
+ {0x1e928, {1|U, {0x1e906}}},
+ {0x1e929, {1|U, {0x1e907}}},
+ {0x1e92a, {1|U, {0x1e908}}},
+ {0x1e92b, {1|U, {0x1e909}}},
+ {0x1e92c, {1|U, {0x1e90a}}},
+ {0x1e92d, {1|U, {0x1e90b}}},
+ {0x1e92e, {1|U, {0x1e90c}}},
+ {0x1e92f, {1|U, {0x1e90d}}},
+ {0x1e930, {1|U, {0x1e90e}}},
+ {0x1e931, {1|U, {0x1e90f}}},
+ {0x1e932, {1|U, {0x1e910}}},
+ {0x1e933, {1|U, {0x1e911}}},
+ {0x1e934, {1|U, {0x1e912}}},
+ {0x1e935, {1|U, {0x1e913}}},
+ {0x1e936, {1|U, {0x1e914}}},
+ {0x1e937, {1|U, {0x1e915}}},
+ {0x1e938, {1|U, {0x1e916}}},
+ {0x1e939, {1|U, {0x1e917}}},
+ {0x1e93a, {1|U, {0x1e918}}},
+ {0x1e93b, {1|U, {0x1e919}}},
+ {0x1e93c, {1|U, {0x1e91a}}},
+ {0x1e93d, {1|U, {0x1e91b}}},
+ {0x1e93e, {1|U, {0x1e91c}}},
+ {0x1e93f, {1|U, {0x1e91d}}},
+ {0x1e940, {1|U, {0x1e91e}}},
+ {0x1e941, {1|U, {0x1e91f}}},
+ {0x1e942, {1|U, {0x1e920}}},
+ {0x1e943, {1|U, {0x1e921}}},
+#define CaseUnfold_11_Locale (*(CaseUnfold_11_Type (*)[1])(CaseUnfold_11_Table+1450))
+ {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 = 2881, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+/*ARGSUSED*/
+static unsigned int
+onigenc_unicode_CaseUnfold_11_hash(const OnigCodePoint code)
+{
+ static const unsigned short asso_values[] =
+ {
+ 1, 2884, 2, 29, 4, 134, 9, 131, 10, 229,
+ 121, 246, 2, 3, 540, 359, 2884, 2884, 2884, 2884,
+ 2884, 2884, 2884, 2884, 2884, 2884, 2884, 2884, 2884, 103,
+ 401, 111, 2884, 2884, 2884, 2884, 2884, 127, 2884, 2884,
+ 2884, 2884, 2884, 1, 2884, 2884, 2884, 2884, 2884, 2884,
+ 2884, 2884, 2884, 339, 2884, 2884, 2884, 2884, 2884, 2884,
+ 2884, 15, 9, 1, 7, 8, 341, 797, 60, 1080,
+ 101, 804, 35, 1589, 7, 1841, 17, 16, 58, 1709,
+ 216, 1040, 47, 103, 64, 1339, 219, 1539, 4, 1704,
+ 52, 1508, 344, 11, 501, 1733, 526, 347, 133, 1161,
+ 340, 913, 104, 883, 170, 743, 339, 1103, 398, 1465,
+ 376, 829, 138, 1092, 280, 967, 1876, 785, 1694, 774,
+ 1640, 721, 1852, 951, 1830, 937, 1573, 925, 1736, 666,
+ 897, 502, 693, 475, 1385, 651, 1356, 639, 1184, 532,
+ 1532, 520, 1479, 420, 1225, 203, 1248, 82, 1277, 115,
+ 1758, 289, 1673, 93, 1686, 71, 1666, 60, 1650, 256,
+ 1789, 232, 1552, 1, 1649, 27, 1489, 38, 1247, 144,
+ 1445, 49, 1624, 221, 1418, 327, 1769, 312, 1306, 584,
+ 1075, 363, 1506, 609, 1405, 1213, 1074, 1065, 1362, 1151,
+ 1556, 863, 726, 1429
+ };
+ return asso_values[bits_of(code, 2)+66] + asso_values[bits_of(code, 1)+4] + asso_values[bits_of(code, 0)];
+}
+
+static const CodePointList3 *
+onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code)
+{
+ enum
+ {
+ MIN_CODE_VALUE = 0x61,
+ MAX_CODE_VALUE = 0x1e943,
+ TOTAL_KEYWORDS = 1451,
+ MIN_WORD_LENGTH = 3,
+ MAX_WORD_LENGTH = 3,
+ MIN_HASH_VALUE = 3,
+ MAX_HASH_VALUE = 2883
+ };
+
+ static const short wordlist[] =
+ {
+ -1, -1, -1,
+ /*0x13e1*/ 591,
+ /*0x0461*/ 342,
+ /*0x04e1*/ 402,
+ /*0x0061*/ 0,
+ -1,
+ /*0x104e1*/ 1192,
+ /*0x1e61*/ 664,
+ /*0x1ee1*/ 723,
+ /*0x0161*/ 102,
+ /*0x0261*/ 211,
+ /*0x2ce1*/ 956,
+ -1,
+ /*0x049b*/ 367,
+ -1, -1,
+ /*0x24e1*/ 843,
+ /*0x1e1b*/ 629,
+ /*0x048b*/ 359,
+ /*0x011b*/ 69,
+ /*0x021b*/ 179,
+ /*0x2c9b*/ 921,
+ /*0x1e0b*/ 621,
+ /*0x1e8b*/ 685,
+ /*0x010b*/ 61,
+ /*0x020b*/ 171,
+ /*0x2c8b*/ 913,
+ /*0x13e3*/ 593,
+ /*0x0463*/ 343,
+ /*0x04e3*/ 403,
+ /*0x0063*/ 2,
+ /*0x1c8a*/ 612,
+ /*0x104e3*/ 1194,
+ /*0x1e63*/ 665,
+ /*0x1ee3*/ 724,
+ /*0x0163*/ 103,
+ /*0x0263*/ 212,
+ /*0x2ce3*/ 957,
+ /*0x13e5*/ 595,
+ /*0x0465*/ 344,
+ /*0x04e5*/ 404,
+ /*0x0065*/ 4,
+ /*0x24e3*/ 845,
+ /*0x104e5*/ 1196,
+ /*0x1e65*/ 666,
+ /*0x1ee5*/ 725,
+ /*0x0165*/ 104,
+ /*0x0265*/ 214,
+ /*0xa761*/ 1068,
+ /*0x13e9*/ 599,
+ /*0x0469*/ 346,
+ /*0x04e9*/ 406,
+ /*0x0069*/ 1450,
+ /*0x24e5*/ 847,
+ /*0x104e9*/ 1200,
+ /*0x1e69*/ 668,
+ /*0x1ee9*/ 727,
+ /*0x0169*/ 106,
+ /*0x0269*/ 217,
+ -1,
+ /*0x13db*/ 585,
+ /*0x045b*/ 337,
+ /*0x04db*/ 399,
+ -1,
+ /*0x24e9*/ 851,
+ /*0x104db*/ 1186,
+ /*0x1e5b*/ 661,
+ /*0x1edb*/ 720,
+ /*0x015b*/ 99,
+ /*0x025b*/ 208,
+ /*0x2cdb*/ 953,
+ /*0x13d9*/ 583,
+ /*0x0459*/ 335,
+ /*0x04d9*/ 398,
+ /*0xa763*/ 1069,
+ /*0x24db*/ 837,
+ /*0x104d9*/ 1184,
+ /*0x1e59*/ 660,
+ /*0x1ed9*/ 719,
+ /*0x0159*/ 98,
+ /*0x0259*/ 207,
+ /*0x2cd9*/ 952,
+ /*0x13d1*/ 575,
+ /*0x0451*/ 327,
+ /*0x04d1*/ 394,
+ /*0xa765*/ 1070,
+ /*0x24d9*/ 835,
+ -1,
+ /*0x1e51*/ 656,
+ /*0x1ed1*/ 715,
+ /*0x0151*/ 94,
+ /*0x0251*/ 201,
+ /*0x2cd1*/ 948,
+ /*0x13d7*/ 581,
+ /*0x0457*/ 333,
+ /*0x04d7*/ 397,
+ /*0xa769*/ 1072,
+ /*0x24d1*/ 827,
+ -1,
+ /*0x1e57*/ 659,
+ /*0x1ed7*/ 718,
+ /*0x0157*/ 97,
+ /*0x0257*/ 206,
+ /*0x2cd7*/ 951,
+ /*0x13a4*/ 530,
+ /*0x0491*/ 362,
+ /*0x10ce1*/ 1287,
+ /*0xa75b*/ 1065,
+ /*0x24d7*/ 833,
+ /*0x1e11*/ 624,
+ /*0x1e91*/ 688,
+ /*0x0111*/ 64,
+ /*0x0211*/ 174,
+ /*0x2c91*/ 916,
+ /*0xa79b*/ 1089,
+ /*0x13d3*/ 577,
+ /*0x0453*/ 329,
+ /*0x04d3*/ 395,
+ /*0xa759*/ 1064,
+ -1, -1,
+ /*0x1e53*/ 657,
+ /*0x1ed3*/ 716,
+ /*0x0153*/ 95,
+ /*0x0253*/ 203,
+ /*0x2cd3*/ 949,
+ -1,
+ /*0x10e1*/ 497,
+ -1,
+ /*0xa751*/ 1060,
+ /*0x24d3*/ 829,
+ /*0x01e1*/ 152,
+ /*0x10ce3*/ 1289,
+ /*0x13a0*/ 526,
+ /*0x00e1*/ 26,
+ -1, -1,
+ /*0x0188*/ 120,
+ /*0x13ae*/ 540,
+ -1,
+ /*0xa757*/ 1063,
+ /*0x019b*/ 126,
+ /*0x1042e*/ 1149,
+ /*0x10ce5*/ 1291,
+ /*0x13e7*/ 597,
+ /*0x0467*/ 345,
+ /*0x04e7*/ 405,
+ /*0x0067*/ 6,
+ -1,
+ /*0x104e7*/ 1198,
+ /*0x1e67*/ 667,
+ /*0x1ee7*/ 726,
+ /*0x0167*/ 105,
+ /*0x10e3*/ 499,
+ /*0x10ce9*/ 1295,
+ -1, -1,
+ /*0x01e3*/ 153,
+ -1,
+ /*0x24e7*/ 849,
+ /*0x00e3*/ 28,
+ /*0xa78c*/ 1083,
+ /*0xa753*/ 1061,
+ /*0xa7db*/ 1114,
+ /*0x10e5*/ 501,
+ /*0x10cdb*/ 1281,
+ -1,
+ /*0xab53*/ 1116,
+ /*0x01e5*/ 154,
+ -1,
+ /*0x13a6*/ 532,
+ /*0x00e5*/ 30,
+ -1,
+ /*0x10d82*/ 1323,
+ /*0xa7d9*/ 1113,
+ /*0x10e9*/ 505,
+ /*0x10cd9*/ 1279,
+ -1, -1,
+ /*0x01e9*/ 156,
+ -1, -1,
+ /*0x00e9*/ 34,
+ -1, -1,
+ /*0xa7d1*/ 1109,
+ /*0x10db*/ 491,
+ /*0x10cd1*/ 1271,
+ /*0x018c*/ 121,
+ -1, -1,
+ /*0xa767*/ 1071,
+ -1, -1,
+ /*0x0192*/ 122,
+ -1,
+ /*0xa7d7*/ 1112,
+ /*0x10d9*/ 489,
+ /*0x10cd7*/ 1277,
+ -1, -1, -1, -1,
+ /*0x13cf*/ 573,
+ /*0x044f*/ 325,
+ /*0x04cf*/ 393,
+ /*0xa791*/ 1084,
+ /*0x1044f*/ 1182,
+ /*0x10d1*/ 481,
+ /*0x1e4f*/ 655,
+ /*0x1ecf*/ 714,
+ /*0x014f*/ 93,
+ /*0x024f*/ 199,
+ /*0x2ccf*/ 947,
+ /*0x10d84*/ 1325,
+ -1,
+ /*0x1d8e*/ 615,
+ /*0xa661*/ 1017,
+ /*0xa7d3*/ 1110,
+ /*0x10d7*/ 487,
+ /*0x10cd3*/ 1273,
+ /*0x13eb*/ 601,
+ /*0x046b*/ 347,
+ /*0x04eb*/ 407,
+ /*0x006b*/ 9,
+ -1,
+ /*0x104eb*/ 1202,
+ /*0x1e6b*/ 669,
+ /*0x1eeb*/ 728,
+ /*0x016b*/ 107,
+ /*0x026b*/ 219,
+ -1,
+ /*0x13df*/ 589,
+ /*0x045f*/ 341,
+ /*0x04df*/ 401,
+ /*0x0288*/ 230,
+ -1,
+ /*0x104df*/ 1190,
+ /*0x1e5f*/ 663,
+ /*0x1edf*/ 722,
+ /*0x015f*/ 101,
+ /*0x10d3*/ 483,
+ /*0x2cdf*/ 955,
+ /*0xa663*/ 1018,
+ /*0x028b*/ 233,
+ /*0x028a*/ 232,
+ /*0x03e1*/ 282,
+ /*0x24df*/ 841,
+ -1,
+ /*0x10ce7*/ 1293,
+ /*0xa74f*/ 1059,
+ -1, -1, -1,
+ /*0xa665*/ 1019,
+ -1,
+ /*0x13dd*/ 587,
+ /*0x045d*/ 339,
+ /*0x04dd*/ 400,
+ -1, -1,
+ /*0x104dd*/ 1188,
+ /*0x1e5d*/ 662,
+ /*0x1edd*/ 721,
+ /*0x015d*/ 100,
+ /*0xa669*/ 1021,
+ /*0x2cdd*/ 954,
+ -1,
+ /*0xa76b*/ 1073,
+ -1,
+ /*0x10e7*/ 503,
+ /*0x24dd*/ 839,
+ /*0x03e3*/ 283,
+ -1,
+ /*0x01e7*/ 155,
+ -1,
+ /*0xa65b*/ 1014,
+ /*0x00e7*/ 32,
+ -1,
+ /*0xa75f*/ 1067,
+ /*0x13b0*/ 542,
+ /*0x0430*/ 294,
+ -1,
+ /*0x03e5*/ 284,
+ /*0x10430*/ 1151,
+ -1,
+ /*0x028c*/ 234,
+ /*0xa659*/ 1013,
+ /*0x0282*/ 227,
+ /*0x13d5*/ 579,
+ /*0x0455*/ 331,
+ /*0x04d5*/ 396,
+ /*0x0292*/ 235,
+ -1,
+ /*0x03e9*/ 286,
+ /*0x1e55*/ 658,
+ /*0x1ed5*/ 717,
+ /*0x0155*/ 96,
+ /*0xa651*/ 1009,
+ /*0x2cd5*/ 950,
+ -1, -1, -1,
+ /*0xa75d*/ 1066,
+ /*0x24d5*/ 831,
+ /*0x03db*/ 279,
+ /*0xa7cf*/ 1108,
+ -1,
+ /*0x10ccf*/ 1269,
+ /*0xa657*/ 1012,
+ -1, -1,
+ /*0x13ef*/ 605,
+ /*0x046f*/ 349,
+ /*0x04ef*/ 409,
+ /*0x006f*/ 13,
+ /*0x03d9*/ 278,
+ /*0x104ef*/ 1206,
+ /*0x1e6f*/ 671,
+ /*0x1eef*/ 730,
+ /*0x016f*/ 109,
+ /*0x026f*/ 221,
+ /*0xa794*/ 1086,
+ -1, -1, -1,
+ /*0x10ceb*/ 1297,
+ /*0x13ed*/ 603,
+ /*0x046d*/ 348,
+ /*0x04ed*/ 408,
+ /*0x006d*/ 11,
+ /*0xa653*/ 1010,
+ /*0x104ed*/ 1204,
+ /*0x1e6d*/ 670,
+ /*0x1eed*/ 729,
+ /*0x016d*/ 108,
+ /*0xa755*/ 1062,
+ /*0x10cdf*/ 1285,
+ /*0x03d7*/ 277,
+ /*0x13a8*/ 534,
+ /*0x13a2*/ 528,
+ /*0x1f61*/ 780,
+ -1,
+ /*0x10428*/ 1143,
+ /*0x2c61*/ 900,
+ -1, -1,
+ /*0x10eb*/ 507,
+ -1,
+ /*0x049f*/ 369,
+ -1,
+ /*0x01eb*/ 157,
+ -1,
+ /*0x1e1f*/ 631,
+ /*0x00eb*/ 36,
+ /*0x011f*/ 71,
+ /*0x021f*/ 181,
+ /*0x2c9f*/ 923,
+ /*0x10df*/ 495,
+ /*0xa76f*/ 1075,
+ /*0xa667*/ 1020,
+ /*0x10cdd*/ 1283,
+ /*0x01df*/ 151,
+ /*0x13f3*/ 609,
+ /*0x0473*/ 351,
+ /*0x04f3*/ 411,
+ /*0x0073*/ 17,
+ /*0x1f63*/ 782,
+ /*0x104f3*/ 1210,
+ /*0x1e73*/ 673,
+ /*0x1ef3*/ 732,
+ /*0x0173*/ 111,
+ /*0x1059b*/ 1223,
+ /*0x2cf3*/ 960,
+ /*0xa76d*/ 1074,
+ /*0x1f06*/ 745,
+ /*0x13ac*/ 538,
+ -1,
+ /*0x1f65*/ 784,
+ -1,
+ /*0x1042c*/ 1147,
+ /*0x2c65*/ 901,
+ /*0x10dd*/ 493,
+ /*0x03ae*/ 246,
+ -1, -1,
+ /*0x01dd*/ 150,
+ /*0x1f10*/ 747,
+ -1,
+ /*0x03e7*/ 285,
+ -1, -1,
+ /*0xa7d5*/ 1111,
+ /*0x0586*/ 479,
+ /*0x10cd5*/ 1275,
+ -1, -1, -1,
+ /*0x13aa*/ 536,
+ -1,
+ /*0x1f02*/ 741,
+ /*0x118db*/ 1354,
+ /*0x1042a*/ 1145,
+ /*0x2c5b*/ 895,
+ /*0x1f12*/ 749,
+ -1, -1, -1, -1, -1,
+ /*0x01b0*/ 133,
+ -1,
+ /*0x118d9*/ 1352,
+ /*0x10598*/ 1220,
+ /*0x2c59*/ 893,
+ /*0x10d5*/ 485,
+ -1,
+ /*0x10cef*/ 1301,
+ /*0x0582*/ 475,
+ /*0xa64f*/ 1008,
+ /*0x13cd*/ 571,
+ /*0x044d*/ 323,
+ /*0x1f51*/ 775,
+ /*0x118d1*/ 1344,
+ /*0x1044d*/ 1180,
+ /*0x2c51*/ 885,
+ /*0x1e4d*/ 654,
+ /*0x1ecd*/ 713,
+ /*0x014d*/ 92,
+ /*0x024d*/ 198,
+ /*0x2ccd*/ 946,
+ -1,
+ /*0x10ced*/ 1299,
+ /*0x1f57*/ 778,
+ /*0x118d7*/ 1350,
+ -1,
+ /*0x2c57*/ 891,
+ /*0xa66b*/ 1022,
+ /*0x10ef*/ 511,
+ -1, -1,
+ /*0x1f04*/ 743,
+ /*0x01ef*/ 159,
+ /*0x1f11*/ 748,
+ /*0x1f24*/ 757,
+ /*0x00ef*/ 40,
+ -1, -1,
+ /*0xa65f*/ 1016,
+ -1,
+ /*0xa79f*/ 1091,
+ -1,
+ /*0x1e924*/ 1418,
+ /*0x10ed*/ 509,
+ /*0x10d80*/ 1321,
+ /*0x1f53*/ 776,
+ /*0x118d3*/ 1346,
+ /*0x01ed*/ 158,
+ /*0x2c53*/ 887,
+ /*0x0584*/ 477,
+ /*0x00ed*/ 38,
+ -1, -1,
+ /*0x2173*/ 812,
+ -1,
+ /*0x105a4*/ 1231,
+ /*0x03eb*/ 287,
+ /*0xa74d*/ 1058,
+ -1,
+ /*0x01a8*/ 131,
+ -1,
+ /*0x0180*/ 117,
+ /*0xa65d*/ 1015,
+ /*0x1f20*/ 753,
+ /*0x019a*/ 125,
+ /*0x13c3*/ 561,
+ /*0x0443*/ 313,
+ /*0x03df*/ 281,
+ -1,
+ /*0x10443*/ 1170,
+ -1,
+ /*0x1e43*/ 649,
+ /*0x1ec3*/ 708,
+ /*0x0373*/ 239,
+ /*0x1f67*/ 786,
+ /*0x2cc3*/ 941,
+ /*0x1e92e*/ 1428,
+ -1, -1,
+ /*0x10f3*/ 515,
+ -1, -1, -1,
+ /*0x01f3*/ 160,
+ /*0x105a0*/ 1228,
+ -1,
+ /*0x00f3*/ 44,
+ -1, -1,
+ /*0x105ae*/ 1241,
+ -1,
+ /*0x03dd*/ 280,
+ /*0x13c1*/ 559,
+ /*0x0441*/ 311,
+ /*0x2d16*/ 983,
+ /*0xa655*/ 1011,
+ /*0x10441*/ 1168,
+ /*0x2d08*/ 969,
+ /*0x1e41*/ 648,
+ /*0x1ec1*/ 707,
+ /*0x1f26*/ 759,
+ /*0x2d1b*/ 988,
+ /*0x2cc1*/ 940,
+ -1, -1, -1,
+ /*0x2d0b*/ 972,
+ /*0x2d0a*/ 971,
+ /*0x1e926*/ 1420,
+ -1,
+ /*0x13cb*/ 569,
+ /*0x044b*/ 321,
+ /*0xa743*/ 1053,
+ /*0xa7cd*/ 1107,
+ /*0x1044b*/ 1178,
+ /*0x10ccd*/ 1267,
+ /*0x1e4b*/ 653,
+ /*0x1ecb*/ 712,
+ /*0x014b*/ 91,
+ /*0x024b*/ 197,
+ /*0x2ccb*/ 945,
+ /*0x105a6*/ 1233,
+ /*0x13c9*/ 567,
+ /*0x0449*/ 319,
+ -1,
+ /*0x2d06*/ 967,
+ /*0x10449*/ 1176,
+ -1,
+ /*0x1e49*/ 652,
+ /*0x1ec9*/ 711,
+ /*0x0561*/ 442,
+ /*0x0249*/ 196,
+ /*0x2cc9*/ 944,
+ /*0xa66d*/ 1023,
+ /*0x118cf*/ 1342,
+ -1,
+ /*0x2c4f*/ 883,
+ /*0x2d10*/ 977,
+ -1,
+ /*0xa741*/ 1052,
+ /*0x051b*/ 431,
+ -1,
+ /*0x2d18*/ 985,
+ -1, -1,
+ /*0x050b*/ 423,
+ -1,
+ /*0x03ef*/ 289,
+ /*0x2d0c*/ 973,
+ /*0x1f14*/ 751,
+ /*0x2d02*/ 963,
+ /*0x16ed1*/ 1413,
+ -1, -1,
+ /*0x2d12*/ 979,
+ -1,
+ /*0x0563*/ 444,
+ /*0xa74b*/ 1057,
+ -1,
+ /*0x0280*/ 226,
+ -1, -1,
+ /*0x03ed*/ 288,
+ /*0x118df*/ 1358,
+ -1,
+ /*0x2c5f*/ 899,
+ -1,
+ /*0x0565*/ 446,
+ /*0xa7c3*/ 1104,
+ /*0xa749*/ 1056,
+ /*0x10cc3*/ 1257,
+ -1, -1, -1,
+ /*0x13f1*/ 607,
+ /*0x0471*/ 350,
+ /*0x04f1*/ 410,
+ /*0x0071*/ 15,
+ /*0x0569*/ 450,
+ /*0x104f1*/ 1208,
+ /*0x1e71*/ 672,
+ /*0x1ef1*/ 731,
+ /*0x0171*/ 110,
+ /*0x0271*/ 222,
+ /*0x16ed3*/ 1415,
+ -1, -1,
+ /*0x118dd*/ 1356,
+ -1,
+ /*0x2c5d*/ 897,
+ -1,
+ /*0x2d04*/ 965,
+ -1,
+ /*0x2d11*/ 978,
+ /*0x2d24*/ 997,
+ /*0xa7c1*/ 1103,
+ -1,
+ /*0x10cc1*/ 1255,
+ /*0x03f3*/ 291,
+ /*0x13f5*/ 611,
+ /*0x0475*/ 352,
+ /*0x04f5*/ 412,
+ /*0x0075*/ 19,
+ -1,
+ /*0x104f5*/ 1212,
+ /*0x1e75*/ 674,
+ /*0x1ef5*/ 733,
+ /*0x0175*/ 112,
+ /*0x0275*/ 224,
+ -1,
+ /*0x1f30*/ 761,
+ /*0x03ac*/ 244,
+ -1,
+ /*0x2c30*/ 852,
+ -1,
+ /*0x10ccb*/ 1265,
+ -1, -1,
+ /*0x1e930*/ 1430,
+ /*0x1f55*/ 777,
+ /*0x118d5*/ 1348,
+ -1,
+ /*0x2c55*/ 889,
+ /*0x2d20*/ 993,
+ -1, -1,
+ /*0xa64d*/ 1007,
+ /*0x10cc9*/ 1263,
+ -1,
+ /*0x13c7*/ 565,
+ /*0x0447*/ 317,
+ /*0x105b0*/ 1243,
+ /*0x0511*/ 426,
+ /*0x10447*/ 1174,
+ -1,
+ /*0x1e47*/ 651,
+ /*0x1ec7*/ 710,
+ -1,
+ /*0x0247*/ 195,
+ /*0x2cc7*/ 943,
+ -1,
+ /*0x13c5*/ 563,
+ /*0x0445*/ 315,
+ -1, -1,
+ /*0x10445*/ 1172,
+ /*0x019e*/ 127,
+ /*0x1e45*/ 650,
+ /*0x1ec5*/ 709,
+ /*0x16e61*/ 1360,
+ -1,
+ /*0x2cc5*/ 942,
+ /*0x01c9*/ 140,
+ -1, -1,
+ /*0x03cd*/ 275,
+ /*0x13bf*/ 557,
+ /*0x043f*/ 309,
+ /*0x04bf*/ 385,
+ -1,
+ /*0x1043f*/ 1166,
+ -1,
+ /*0x1e3f*/ 647,
+ /*0x1ebf*/ 706,
+ -1,
+ /*0x023f*/ 192,
+ /*0x2cbf*/ 939,
+ -1, -1, -1,
+ /*0x1f22*/ 755,
+ /*0x1f00*/ 739,
+ /*0x16ecf*/ 1411,
+ /*0x0567*/ 448,
+ /*0x2171*/ 810,
+ /*0x16e63*/ 1362,
+ /*0xa747*/ 1055,
+ /*0x1e928*/ 1422,
+ /*0x1e922*/ 1416,
+ /*0x10cf1*/ 1303,
+ -1,
+ /*0xa643*/ 1002,
+ -1,
+ /*0x13c2*/ 560,
+ /*0x0442*/ 312,
+ /*0x04c2*/ 386,
+ /*0x16e65*/ 1364,
+ /*0x10442*/ 1169,
+ /*0xa745*/ 1054,
+ /*0x0580*/ 473,
+ /*0x105a8*/ 1235,
+ /*0x0142*/ 87,
+ /*0x0242*/ 194,
+ /*0x1f73*/ 790,
+ /*0x0371*/ 238,
+ /*0x1059a*/ 1222,
+ /*0x2c73*/ 906,
+ /*0x16e69*/ 1368,
+ /*0x1059f*/ 1227,
+ /*0x2175*/ 814,
+ /*0x10f1*/ 513,
+ -1, -1,
+ /*0xa73f*/ 1051,
+ -1, -1,
+ /*0x2d0e*/ 975,
+ /*0x00f1*/ 42,
+ /*0xa641*/ 1001,
+ /*0x2d14*/ 981,
+ /*0x03c3*/ 265,
+ /*0x13b7*/ 549,
+ /*0x0437*/ 301,
+ /*0x04b7*/ 381,
+ /*0x1e92c*/ 1426,
+ /*0x10437*/ 1158,
+ -1,
+ /*0x1e37*/ 643,
+ /*0x1eb7*/ 702,
+ /*0x0137*/ 82,
+ -1,
+ /*0x2cb7*/ 935,
+ -1, -1,
+ /*0x017e*/ 116,
+ /*0x10f5*/ 517,
+ /*0xa64b*/ 1006,
+ /*0x105ac*/ 1239,
+ -1,
+ /*0x01f5*/ 161,
+ -1, -1,
+ /*0x00f5*/ 46,
+ /*0x13a7*/ 533,
+ /*0x10cc7*/ 1261,
+ /*0x04a7*/ 373,
+ /*0x1e92a*/ 1424,
+ /*0x03c1*/ 264,
+ /*0xa649*/ 1005,
+ /*0x1e27*/ 635,
+ /*0x1ea7*/ 694,
+ /*0x0127*/ 75,
+ /*0x0227*/ 184,
+ /*0x2ca7*/ 927,
+ /*0x029e*/ 237,
+ -1,
+ /*0x10cc5*/ 1259,
+ -1, -1,
+ /*0x105aa*/ 1237,
+ /*0x056b*/ 452,
+ /*0x118cd*/ 1340,
+ -1,
+ /*0x2c4d*/ 881,
+ -1,
+ /*0x03cb*/ 273,
+ /*0x10d73*/ 1308,
+ -1,
+ /*0xa737*/ 1047,
+ /*0xa7bf*/ 1102,
+ -1, -1, -1, -1,
+ /*0x13b5*/ 547,
+ /*0x0435*/ 299,
+ /*0x04b5*/ 380,
+ /*0x03c9*/ 271,
+ /*0x10435*/ 1156,
+ -1,
+ /*0x1e35*/ 642,
+ /*0x1eb5*/ 701,
+ /*0x0135*/ 81,
+ -1,
+ /*0x2cb5*/ 934,
+ /*0x13b3*/ 545,
+ /*0x0433*/ 297,
+ /*0x04b3*/ 379,
+ -1,
+ /*0x10433*/ 1154,
+ /*0xa727*/ 1040,
+ /*0x1e33*/ 641,
+ /*0x1eb3*/ 700,
+ /*0x0133*/ 80,
+ /*0x0233*/ 190,
+ /*0x2cb3*/ 933,
+ /*0x01bf*/ 138,
+ /*0x1fe1*/ 806,
+ /*0x10cc2*/ 1256,
+ /*0x0481*/ 358,
+ -1, -1,
+ /*0x16e67*/ 1366,
+ /*0x1e01*/ 616,
+ /*0x1e81*/ 680,
+ /*0x0101*/ 56,
+ /*0x0201*/ 166,
+ /*0x2c81*/ 908,
+ -1, -1,
+ /*0x1e05*/ 618,
+ /*0x1e85*/ 682,
+ /*0x0105*/ 58,
+ /*0x0205*/ 168,
+ /*0x2c85*/ 910,
+ /*0x1f43*/ 772,
+ /*0x118c3*/ 1330,
+ -1,
+ /*0x2c43*/ 871,
+ -1, -1,
+ /*0xa735*/ 1046,
+ -1,
+ /*0x1e943*/ 1449,
+ /*0xa7b7*/ 1098,
+ -1,
+ /*0x217e*/ 823,
+ -1, -1,
+ /*0x13ad*/ 539,
+ -1,
+ /*0x04ad*/ 376,
+ /*0xa733*/ 1045,
+ /*0x1042d*/ 1148,
+ /*0x1fe5*/ 807,
+ /*0x1e2d*/ 638,
+ /*0x1ead*/ 697,
+ /*0x012d*/ 78,
+ /*0x022d*/ 187,
+ /*0x2cad*/ 930,
+ /*0x2d22*/ 995,
+ /*0x2d00*/ 961,
+ /*0x1f41*/ 770,
+ /*0x118c1*/ 1328,
+ /*0x2d1a*/ 987,
+ /*0x2c41*/ 869,
+ /*0xa7a7*/ 1095,
+ /*0x2d1f*/ 992,
+ -1, -1,
+ /*0x1e941*/ 1447,
+ /*0x056f*/ 456,
+ /*0x10fe*/ 524,
+ -1, -1,
+ /*0xa647*/ 1004,
+ -1, -1, -1,
+ /*0x00fe*/ 54,
+ -1,
+ /*0x118cb*/ 1338,
+ /*0x1059c*/ 1224,
+ /*0x2c4b*/ 879,
+ /*0x047d*/ 356,
+ /*0x04fd*/ 416,
+ /*0x056d*/ 454,
+ /*0xa645*/ 1003,
+ -1,
+ /*0x1e7d*/ 678,
+ /*0x1efd*/ 737,
+ /*0x1d7d*/ 614,
+ /*0x027d*/ 225,
+ /*0x118c9*/ 1336,
+ -1,
+ /*0x2c49*/ 877,
+ /*0xa72d*/ 1043,
+ /*0xa7b5*/ 1097,
+ /*0x1fd1*/ 804,
+ /*0x16e6b*/ 1370,
+ -1, -1, -1,
+ /*0x13a5*/ 531,
+ /*0x03c7*/ 269,
+ /*0x04a5*/ 372,
+ /*0x051f*/ 433,
+ /*0x1059e*/ 1226,
+ -1,
+ /*0x1e25*/ 634,
+ /*0x1ea5*/ 693,
+ /*0x0125*/ 74,
+ /*0x0225*/ 183,
+ /*0x2ca5*/ 926,
+ -1, -1,
+ /*0x03c5*/ 267,
+ /*0x13c0*/ 558,
+ /*0x0440*/ 310,
+ /*0x16ecd*/ 1409,
+ /*0xa781*/ 1079,
+ /*0x10440*/ 1167,
+ /*0x0573*/ 460,
+ -1,
+ /*0x2184*/ 825,
+ /*0x0140*/ 86,
+ /*0x0240*/ 193,
+ /*0xa785*/ 1081,
+ -1, -1,
+ /*0x10d81*/ 1322,
+ /*0x03bf*/ 262,
+ -1,
+ /*0x13a3*/ 529,
+ -1,
+ /*0x04a3*/ 371,
+ -1,
+ /*0x10d85*/ 1326,
+ -1,
+ /*0x1e23*/ 633,
+ /*0x1ea3*/ 692,
+ /*0x0123*/ 73,
+ /*0x0223*/ 182,
+ /*0x2ca3*/ 925,
+ /*0x1f71*/ 788,
+ /*0x13bd*/ 555,
+ /*0x043d*/ 307,
+ /*0x04bd*/ 384,
+ -1,
+ /*0x1043d*/ 1164,
+ /*0xa725*/ 1039,
+ /*0x1e3d*/ 646,
+ /*0x1ebd*/ 705,
+ -1,
+ /*0x0185*/ 119,
+ /*0x2cbd*/ 938,
+ -1,
+ /*0x13bb*/ 553,
+ /*0x043b*/ 305,
+ /*0x04bb*/ 383,
+ -1,
+ /*0x1043b*/ 1162,
+ -1,
+ /*0x1e3b*/ 645,
+ /*0x1ebb*/ 704,
+ -1, -1,
+ /*0x2cbb*/ 937,
+ -1,
+ /*0x1f75*/ 792,
+ -1,
+ /*0x13b9*/ 551,
+ /*0x0439*/ 303,
+ /*0x04b9*/ 382,
+ /*0x16ec3*/ 1399,
+ /*0x10439*/ 1160,
+ -1,
+ /*0x1e39*/ 644,
+ /*0x1eb9*/ 703,
+ /*0x01ad*/ 132,
+ /*0xa723*/ 1038,
+ /*0x2cb9*/ 936,
+ -1,
+ /*0x217d*/ 822,
+ -1, -1,
+ /*0x03b7*/ 254,
+ /*0x13b1*/ 543,
+ /*0x0431*/ 295,
+ /*0x04b1*/ 378,
+ /*0x16e6f*/ 1374,
+ /*0x10431*/ 1152,
+ /*0xa73d*/ 1050,
+ /*0x1e31*/ 640,
+ /*0x1eb1*/ 699,
+ -1,
+ /*0x0231*/ 189,
+ /*0x2cb1*/ 932,
+ -1, -1,
+ /*0x118c7*/ 1334,
+ /*0x16ec1*/ 1397,
+ /*0x2c47*/ 875,
+ /*0x037d*/ 243,
+ /*0xa73b*/ 1049,
+ /*0x16e6d*/ 1372,
+ /*0xa7a5*/ 1094,
+ /*0x10d71*/ 1306,
+ -1,
+ /*0x10fd*/ 523,
+ -1,
+ /*0x1f45*/ 774,
+ /*0x118c5*/ 1332,
+ /*0x01fd*/ 164,
+ /*0x2c45*/ 873,
+ /*0xff59*/ 1141,
+ /*0x00fd*/ 53,
+ -1,
+ /*0xa739*/ 1048,
+ /*0x16ecb*/ 1407,
+ -1,
+ /*0x2d1c*/ 989,
+ /*0x10cc0*/ 1254,
+ -1, -1, -1,
+ /*0xff51*/ 1133,
+ -1, -1,
+ /*0x2c3f*/ 867,
+ -1,
+ /*0x16ec9*/ 1405,
+ /*0x10d75*/ 1310,
+ /*0x01a5*/ 130,
+ /*0x1e93f*/ 1445,
+ -1,
+ /*0xa7a3*/ 1093,
+ /*0xff57*/ 1139,
+ -1,
+ /*0x03b5*/ 252,
+ -1,
+ /*0x16e73*/ 1378,
+ -1, -1, -1, -1,
+ /*0x2d1e*/ 991,
+ -1,
+ /*0xa7bd*/ 1101,
+ -1,
+ /*0x03b3*/ 250,
+ -1, -1,
+ /*0x1f42*/ 771,
+ /*0x118c2*/ 1329,
+ -1,
+ /*0x2c42*/ 870,
+ -1, -1,
+ /*0xff53*/ 1135,
+ /*0xa7bb*/ 1100,
+ /*0x1e942*/ 1448,
+ /*0x048f*/ 361,
+ /*0x01a3*/ 129,
+ -1, -1,
+ /*0x1e0f*/ 623,
+ /*0x1e8f*/ 687,
+ /*0x010f*/ 63,
+ /*0x020f*/ 173,
+ /*0x2c8f*/ 915,
+ /*0xa69b*/ 1037,
+ -1, -1,
+ /*0xa7b9*/ 1099,
+ /*0x01bd*/ 137,
+ /*0xa68b*/ 1029,
+ -1, -1, -1, -1,
+ /*0x1f37*/ 768,
+ -1, -1,
+ /*0x2c37*/ 859,
+ -1,
+ /*0x0479*/ 354,
+ /*0x04f9*/ 414,
+ /*0x0079*/ 23,
+ /*0x1e937*/ 1437,
+ /*0x104f9*/ 1216,
+ /*0x1e79*/ 676,
+ /*0x1ef9*/ 735,
+ /*0x1d79*/ 613,
+ /*0x03ad*/ 245,
+ /*0x13f2*/ 608,
+ /*0x1fb0*/ 801,
+ /*0x0078*/ 22,
+ /*0x0072*/ 16,
+ /*0x104f8*/ 1215,
+ /*0x104f2*/ 1209,
+ /*0x01b9*/ 136,
+ /*0x105b7*/ 1249,
+ /*0x1f27*/ 760,
+ /*0x0272*/ 223,
+ -1,
+ /*0x1e03*/ 617,
+ /*0x1e83*/ 681,
+ /*0x0103*/ 57,
+ /*0x0203*/ 167,
+ /*0x2c83*/ 909,
+ /*0x1e927*/ 1421,
+ /*0x13af*/ 541,
+ -1,
+ /*0x04af*/ 377,
+ -1,
+ /*0x1042f*/ 1150,
+ -1,
+ /*0x1e2f*/ 639,
+ /*0x1eaf*/ 698,
+ /*0x012f*/ 79,
+ /*0x022f*/ 188,
+ /*0x2caf*/ 931,
+ /*0x13a9*/ 535,
+ /*0x105a7*/ 1234,
+ /*0x04a9*/ 374,
+ -1,
+ /*0x10429*/ 1144,
+ -1,
+ /*0x1e29*/ 636,
+ /*0x1ea9*/ 695,
+ /*0x0129*/ 76,
+ /*0x0229*/ 185,
+ /*0x2ca9*/ 928,
+ /*0x1f35*/ 766,
+ -1, -1,
+ /*0x2c35*/ 857,
+ /*0x16ec7*/ 1403,
+ -1, -1, -1,
+ /*0x1e935*/ 1435,
+ /*0x0571*/ 458,
+ -1,
+ /*0x1f33*/ 764,
+ -1,
+ /*0xff4f*/ 1131,
+ /*0x2c33*/ 855,
+ /*0x10d7e*/ 1319,
+ /*0x16ec5*/ 1401,
+ -1, -1,
+ /*0x1e933*/ 1433,
+ -1,
+ /*0x105b5*/ 1247,
+ -1,
+ /*0x1f01*/ 740,
+ -1,
+ /*0xa72f*/ 1044,
+ -1, -1,
+ /*0x03c0*/ 263,
+ /*0xa691*/ 1032,
+ /*0x1f05*/ 744,
+ /*0x16ebf*/ 1395,
+ /*0x105b3*/ 1245,
+ -1,
+ /*0x0575*/ 462,
+ -1,
+ /*0xa729*/ 1041,
+ -1,
+ /*0x047b*/ 355,
+ /*0x04fb*/ 415,
+ -1,
+ /*0x0581*/ 474,
+ /*0x104fb*/ 1218,
+ /*0x1e7b*/ 677,
+ /*0x1efb*/ 736,
+ -1, -1,
+ /*0x13a1*/ 527,
+ /*0x0585*/ 478,
+ /*0x04a1*/ 370,
+ -1,
+ /*0x2179*/ 818,
+ -1,
+ /*0x1e21*/ 632,
+ /*0x1ea1*/ 691,
+ /*0x0121*/ 72,
+ /*0x03bd*/ 260,
+ /*0x2ca1*/ 924,
+ /*0x16ec2*/ 1398,
+ -1,
+ /*0x2178*/ 817,
+ /*0x2172*/ 811,
+ -1,
+ /*0x1e92d*/ 1427,
+ -1, -1,
+ /*0x10cf2*/ 1304,
+ -1,
+ /*0x03bb*/ 258,
+ /*0xa783*/ 1080,
+ /*0x13c8*/ 566,
+ /*0x0448*/ 318,
+ /*0x04c8*/ 389,
+ -1,
+ /*0x10448*/ 1175,
+ -1,
+ /*0x105ad*/ 1240,
+ /*0x10f9*/ 521,
+ /*0x0148*/ 90,
+ /*0x10d83*/ 1324,
+ -1,
+ /*0x01f9*/ 162,
+ /*0x03b9*/ 256,
+ -1,
+ /*0x00f9*/ 49,
+ -1,
+ /*0x10f8*/ 520,
+ /*0x10f2*/ 514,
+ -1,
+ /*0x1f7d*/ 800,
+ -1, -1,
+ /*0xa7a9*/ 1096,
+ /*0x00f8*/ 48,
+ /*0x00f2*/ 43,
+ -1,
+ /*0x0183*/ 118,
+ -1,
+ /*0x03b1*/ 248,
+ /*0xff55*/ 1137,
+ /*0x0477*/ 353,
+ /*0x04f7*/ 413,
+ /*0x0077*/ 21,
+ -1,
+ /*0x104f7*/ 1214,
+ /*0x1e77*/ 675,
+ /*0x1ef7*/ 734,
+ /*0x0177*/ 113,
+ -1,
+ /*0x1f25*/ 758,
+ -1,
+ /*0x13ce*/ 572,
+ /*0x044e*/ 324,
+ /*0x04ce*/ 392,
+ -1,
+ /*0x1044e*/ 1181,
+ -1,
+ /*0x1e925*/ 1419,
+ -1, -1, -1, -1, -1,
+ /*0x1f40*/ 769,
+ /*0x118c0*/ 1327,
+ -1,
+ /*0x2c40*/ 868,
+ -1,
+ /*0x16e71*/ 1376,
+ /*0x2d27*/ 999,
+ /*0x105a5*/ 1232,
+ /*0x1e940*/ 1446,
+ -1,
+ /*0x13e6*/ 596,
+ /*0x13d0*/ 574,
+ /*0x0450*/ 326,
+ /*0x0066*/ 5,
+ /*0x217b*/ 820,
+ /*0x104e6*/ 1197,
+ /*0x1f23*/ 756,
+ -1, -1,
+ /*0x0266*/ 215,
+ /*0x0250*/ 200,
+ -1, -1, -1,
+ /*0x1e923*/ 1417,
+ /*0x24e6*/ 848,
+ /*0x24d0*/ 826,
+ /*0xa7a1*/ 1092,
+ /*0x057e*/ 471,
+ /*0x10d7d*/ 1318,
+ /*0x16e75*/ 1380,
+ /*0x2c3d*/ 865,
+ -1, -1,
+ /*0x037b*/ 241,
+ -1,
+ /*0x1e93d*/ 1443,
+ /*0x105a3*/ 1230,
+ -1, -1,
+ /*0x13d2*/ 576,
+ /*0x0452*/ 328,
+ -1,
+ /*0x2c3b*/ 863,
+ /*0x01fb*/ 163,
+ /*0x0527*/ 437,
+ -1,
+ /*0x00fb*/ 51,
+ /*0x1e93b*/ 1441,
+ /*0x0252*/ 202,
+ /*0xa7c8*/ 1105,
+ -1,
+ /*0x10cc8*/ 1262,
+ -1,
+ /*0x01a1*/ 128,
+ /*0x24d2*/ 828,
+ -1,
+ /*0x2c39*/ 861,
+ -1, -1,
+ /*0x2d01*/ 962,
+ /*0x105bb*/ 1252,
+ /*0x1e939*/ 1439,
+ -1, -1, -1, -1,
+ /*0x2d05*/ 966,
+ -1,
+ /*0x13f0*/ 606,
+ /*0x1f31*/ 762,
+ /*0x0283*/ 228,
+ /*0x0070*/ 14,
+ /*0x2c31*/ 853,
+ /*0x104f0*/ 1207,
+ /*0x105b9*/ 1251,
+ /*0x2177*/ 816,
+ -1,
+ /*0x1e931*/ 1431,
+ -1, -1, -1,
+ /*0x03f8*/ 292,
+ /*0x03f2*/ 290,
+ -1, -1, -1, -1,
+ /*0x214e*/ 808,
+ -1, -1,
+ /*0x105b1*/ 1244,
+ /*0x2d2d*/ 1000,
+ /*0x10cce*/ 1268,
+ -1, -1,
+ /*0x0377*/ 240,
+ -1, -1,
+ /*0x0501*/ 418,
+ /*0x03af*/ 247,
+ -1,
+ /*0x10f7*/ 519,
+ -1,
+ /*0x0493*/ 363,
+ -1,
+ /*0x0505*/ 420,
+ /*0xff4d*/ 1129,
+ /*0x1e13*/ 625,
+ /*0x1e93*/ 689,
+ /*0x0113*/ 65,
+ /*0x0213*/ 175,
+ /*0x2c93*/ 917,
+ -1, -1,
+ /*0x10ce6*/ 1292,
+ /*0x10cd0*/ 1270,
+ -1,
+ /*0x01ce*/ 142,
+ /*0x13c6*/ 564,
+ /*0x0446*/ 316,
+ /*0x04c6*/ 388,
+ -1,
+ /*0x10446*/ 1173,
+ -1, -1, -1,
+ /*0x0146*/ 89,
+ /*0x007a*/ 24,
+ -1,
+ /*0x104fa*/ 1217,
+ /*0x052d*/ 440,
+ -1,
+ /*0x017a*/ 114,
+ -1, -1,
+ /*0x10e6*/ 502,
+ /*0x10d0*/ 480,
+ -1,
+ /*0x16ec0*/ 1396,
+ -1,
+ /*0x01d0*/ 143,
+ -1,
+ /*0x00e6*/ 31,
+ -1,
+ /*0x10cd2*/ 1272,
+ /*0x2d25*/ 998,
+ /*0x16e7e*/ 1389,
+ /*0x13c4*/ 562,
+ /*0x0444*/ 314,
+ /*0x04c4*/ 387,
+ -1,
+ /*0x10444*/ 1171,
+ -1, -1, -1,
+ /*0x0144*/ 88,
+ -1, -1,
+ /*0x03fb*/ 293,
+ -1, -1,
+ /*0xff43*/ 1119,
+ -1, -1,
+ /*0x057d*/ 470,
+ /*0x10d2*/ 482,
+ /*0x16ebd*/ 1393,
+ /*0x1f79*/ 796,
+ /*0x2170*/ 809,
+ /*0x01d2*/ 144,
+ /*0x0076*/ 20,
+ /*0xa77a*/ 1076,
+ /*0x104f6*/ 1213,
+ /*0x10cf0*/ 1302,
+ -1,
+ /*0x2d23*/ 996,
+ /*0x1f78*/ 795,
+ /*0x1f72*/ 789,
+ /*0x16ebb*/ 1391,
+ -1,
+ /*0x13ec*/ 602,
+ -1,
+ /*0x1f03*/ 742,
+ /*0x006c*/ 10,
+ /*0x0525*/ 436,
+ /*0x104ec*/ 1203,
+ -1, -1,
+ /*0xff41*/ 1117,
+ /*0x026c*/ 220,
+ /*0x2cec*/ 958,
+ /*0x03c8*/ 270,
+ /*0x047f*/ 357,
+ /*0x04ff*/ 417,
+ /*0x10f0*/ 512,
+ -1, -1,
+ /*0x1e7f*/ 679,
+ /*0x1eff*/ 738,
+ -1,
+ /*0x0583*/ 476,
+ /*0x00f0*/ 41,
+ /*0x1e92f*/ 1429,
+ -1,
+ /*0xa793*/ 1085,
+ -1,
+ /*0xff4b*/ 1127,
+ /*0x13e8*/ 598,
+ -1, -1,
+ /*0x0068*/ 7,
+ -1,
+ /*0x104e8*/ 1199,
+ /*0x1e929*/ 1423,
+ /*0x0523*/ 435,
+ /*0x105af*/ 1242,
+ /*0x0268*/ 216,
+ -1,
+ /*0xff49*/ 1125,
+ -1, -1, -1,
+ /*0x24e8*/ 850,
+ /*0x10cc6*/ 1260,
+ /*0x217a*/ 819,
+ -1,
+ /*0x105a9*/ 1236,
+ /*0x13ab*/ 537,
+ -1,
+ /*0x04ab*/ 375,
+ /*0x10d79*/ 1314,
+ /*0x1042b*/ 1146,
+ /*0x03ce*/ 276,
+ /*0x1e2b*/ 637,
+ /*0x1eab*/ 696,
+ /*0x012b*/ 77,
+ /*0x022b*/ 186,
+ /*0x2cab*/ 929,
+ /*0xa77f*/ 1078,
+ /*0x10d78*/ 1313,
+ /*0x10d72*/ 1307,
+ /*0x13cc*/ 570,
+ /*0x044c*/ 322,
+ /*0x04cc*/ 391,
+ -1,
+ /*0x1044c*/ 1179,
+ -1, -1,
+ /*0x01c6*/ 139,
+ -1,
+ /*0x10fa*/ 522,
+ /*0x13e4*/ 594,
+ /*0x10cc4*/ 1258,
+ /*0x1f7b*/ 798,
+ /*0x0064*/ 3,
+ -1,
+ /*0x104e4*/ 1195,
+ /*0x00fa*/ 50,
+ -1, -1,
+ /*0x0264*/ 213,
+ -1, -1,
+ /*0x1f21*/ 754,
+ -1, -1,
+ /*0x24e4*/ 846,
+ /*0x2176*/ 815,
+ /*0x13f4*/ 610,
+ -1,
+ /*0xa7f6*/ 1115,
+ /*0x0074*/ 18,
+ /*0x0499*/ 366,
+ /*0x104f4*/ 1211,
+ /*0xa72b*/ 1042,
+ -1,
+ /*0x1e19*/ 628,
+ -1,
+ /*0x0119*/ 68,
+ /*0x0219*/ 178,
+ /*0x2c99*/ 920,
+ -1, -1,
+ /*0x16e7d*/ 1388,
+ /*0x105a1*/ 1229,
+ /*0x10cec*/ 1298,
+ -1,
+ /*0x118c8*/ 1335,
+ -1,
+ /*0x2c48*/ 876,
+ -1,
+ /*0x217f*/ 824,
+ -1,
+ /*0x10f6*/ 518,
+ /*0x13ca*/ 568,
+ /*0x044a*/ 320,
+ /*0x04ca*/ 390,
+ -1,
+ /*0x1044a*/ 1177,
+ -1,
+ /*0x00f6*/ 47,
+ -1,
+ /*0x2d0f*/ 976,
+ /*0x0495*/ 364,
+ -1, -1,
+ /*0x10ec*/ 508,
+ /*0x1e15*/ 626,
+ /*0x1e95*/ 690,
+ /*0x0115*/ 66,
+ /*0x0215*/ 176,
+ /*0x2c95*/ 918,
+ /*0x10ce8*/ 1294,
+ /*0x00ec*/ 37,
+ /*0x13e0*/ 590,
+ /*0x1f77*/ 794,
+ /*0x10d7b*/ 1316,
+ /*0x10ff*/ 525,
+ -1,
+ /*0x104e0*/ 1191,
+ -1,
+ /*0x01ff*/ 165,
+ -1,
+ /*0x0260*/ 210,
+ /*0x00ff*/ 55,
+ /*0xff47*/ 1123,
+ /*0x017c*/ 115,
+ -1,
+ /*0x118ce*/ 1341,
+ /*0x24e0*/ 842,
+ /*0x2c4e*/ 882,
+ -1, -1,
+ /*0x10e8*/ 504,
+ -1,
+ /*0x13bc*/ 554,
+ /*0x043c*/ 306,
+ /*0xff45*/ 1121,
+ -1,
+ /*0x1043c*/ 1163,
+ /*0x00e8*/ 33,
+ /*0x050f*/ 425,
+ /*0x2d03*/ 964,
+ /*0x013c*/ 84,
+ /*0x023c*/ 191,
+ -1,
+ /*0x10ccc*/ 1266,
+ -1, -1,
+ /*0x1f66*/ 785,
+ -1,
+ /*0x118d0*/ 1343,
+ /*0x2c66*/ 902,
+ /*0x2c50*/ 884,
+ -1, -1,
+ /*0x10ce4*/ 1290,
+ /*0x1e07*/ 619,
+ /*0x1e87*/ 683,
+ /*0x0107*/ 59,
+ /*0x0207*/ 169,
+ /*0x2c87*/ 911,
+ -1,
+ /*0x03c6*/ 268,
+ -1,
+ /*0xa77c*/ 1077,
+ /*0x0579*/ 466,
+ -1,
+ /*0x2174*/ 813,
+ -1, -1,
+ /*0x01cc*/ 141,
+ -1,
+ /*0xa799*/ 1088,
+ -1,
+ /*0x0578*/ 465,
+ /*0x0572*/ 459,
+ /*0x10e4*/ 500,
+ /*0x10d77*/ 1312,
+ /*0xff42*/ 1118,
+ /*0x118d2*/ 1345,
+ /*0x0503*/ 419,
+ /*0x2c52*/ 886,
+ -1,
+ /*0x00e4*/ 29,
+ -1,
+ /*0x13ea*/ 600,
+ -1, -1,
+ /*0x006a*/ 8,
+ -1,
+ /*0x104ea*/ 1201,
+ /*0x03c4*/ 266,
+ /*0x052f*/ 441,
+ /*0x10f4*/ 516,
+ /*0x026a*/ 218,
+ -1,
+ /*0xa7ca*/ 1106,
+ -1,
+ /*0x10cca*/ 1264,
+ /*0x0199*/ 124,
+ /*0x00f4*/ 45,
+ /*0x13b6*/ 548,
+ /*0x0436*/ 300,
+ /*0x0529*/ 438,
+ -1,
+ /*0x10436*/ 1157,
+ -1,
+ /*0x1f70*/ 787,
+ -1, -1,
+ /*0x13e2*/ 592,
+ /*0x13dc*/ 586,
+ /*0x045c*/ 338,
+ /*0x0062*/ 1,
+ -1,
+ /*0x104e2*/ 1193,
+ /*0x104dc*/ 1187,
+ /*0x217c*/ 821,
+ /*0x10ce0*/ 1286,
+ -1,
+ /*0x025c*/ 209,
+ -1,
+ /*0x2d21*/ 994,
+ -1,
+ /*0x16ec8*/ 1404,
+ /*0x24e2*/ 844,
+ /*0x24dc*/ 838,
+ /*0x13da*/ 584,
+ /*0x045a*/ 336,
+ -1,
+ /*0x0195*/ 123,
+ -1,
+ /*0x104da*/ 1185,
+ -1,
+ /*0x13d6*/ 580,
+ /*0x0456*/ 332,
+ -1,
+ /*0x037c*/ 242,
+ -1,
+ /*0x10e0*/ 496,
+ /*0x1f13*/ 750,
+ -1,
+ /*0x24da*/ 836,
+ /*0x0256*/ 205,
+ -1, -1,
+ /*0x00e0*/ 25,
+ /*0x13d8*/ 582,
+ /*0x0458*/ 334,
+ /*0x24d6*/ 832,
+ /*0x00fc*/ 52,
+ /*0x057b*/ 468,
+ /*0x104d8*/ 1183,
+ /*0xa787*/ 1082,
+ -1,
+ /*0x13b4*/ 546,
+ /*0x0434*/ 298,
+ -1,
+ /*0x118c6*/ 1333,
+ /*0x10434*/ 1155,
+ /*0x2c46*/ 874,
+ /*0x0521*/ 434,
+ /*0x24d8*/ 834,
+ /*0x1f7a*/ 797,
+ -1,
+ /*0x16ece*/ 1410,
+ -1,
+ /*0x0497*/ 365,
+ -1, -1,
+ /*0x10d70*/ 1305,
+ /*0x1e17*/ 627,
+ /*0x048d*/ 360,
+ /*0x0117*/ 67,
+ /*0x0217*/ 177,
+ /*0x2c97*/ 919,
+ /*0x1e0d*/ 622,
+ /*0x1e8d*/ 686,
+ /*0x010d*/ 62,
+ /*0x020d*/ 172,
+ /*0x2c8d*/ 914,
+ -1, -1, -1,
+ /*0x16e79*/ 1384,
+ /*0x03cc*/ 274,
+ /*0x1f44*/ 773,
+ /*0x118c4*/ 1331,
+ /*0x16ed0*/ 1412,
+ /*0x2c44*/ 872,
+ /*0x10cea*/ 1296,
+ -1, -1,
+ /*0x16e78*/ 1383,
+ /*0x16e72*/ 1377,
+ -1,
+ /*0x049d*/ 368,
+ /*0x13be*/ 556,
+ /*0x043e*/ 308,
+ -1,
+ /*0x1e1d*/ 630,
+ /*0x1043e*/ 1165,
+ /*0x011d*/ 70,
+ /*0x021d*/ 180,
+ /*0x2c9d*/ 922,
+ /*0x013e*/ 85,
+ /*0x1f76*/ 793,
+ -1, -1,
+ /*0x2c76*/ 907,
+ -1,
+ /*0x10ea*/ 506,
+ -1,
+ /*0x0577*/ 464,
+ -1,
+ /*0x10ce2*/ 1288,
+ /*0x10cdc*/ 1282,
+ /*0x16ed2*/ 1414,
+ /*0x00ea*/ 35,
+ /*0x13d4*/ 578,
+ /*0x0454*/ 330,
+ -1,
+ /*0x2c6c*/ 905,
+ -1,
+ /*0x1fb1*/ 802,
+ -1,
+ /*0x10d7a*/ 1315,
+ -1,
+ /*0x0254*/ 204,
+ -1,
+ /*0x13ee*/ 604,
+ /*0x01b6*/ 135,
+ /*0x10cda*/ 1280,
+ /*0x006e*/ 12,
+ /*0x24d4*/ 830,
+ /*0x104ee*/ 1205,
+ /*0x10e2*/ 498,
+ /*0x10dc*/ 492,
+ /*0x03ca*/ 272,
+ /*0x10cd6*/ 1276,
+ /*0x2cee*/ 959,
+ /*0x01dc*/ 149,
+ -1,
+ /*0x00e2*/ 27,
+ -1, -1, -1,
+ /*0x0566*/ 447,
+ -1,
+ /*0x2c68*/ 903,
+ /*0x13de*/ 588,
+ /*0x045e*/ 340,
+ /*0x10cd8*/ 1278,
+ /*0x10da*/ 490,
+ -1,
+ /*0x104de*/ 1189,
+ -1,
+ /*0x01da*/ 148,
+ -1, -1,
+ /*0x10d6*/ 486,
+ -1, -1, -1,
+ /*0x01d6*/ 146,
+ /*0x24de*/ 840,
+ -1, -1,
+ /*0xa797*/ 1087,
+ /*0x10d76*/ 1311,
+ /*0x16e7b*/ 1386,
+ -1, -1,
+ /*0x10d8*/ 488,
+ /*0x1e92b*/ 1425,
+ -1, -1,
+ /*0x01d8*/ 147,
+ /*0x0287*/ 229,
+ /*0x03bc*/ 259,
+ -1,
+ /*0x118cc*/ 1339,
+ -1,
+ /*0x2c4c*/ 880,
+ -1,
+ /*0x01b4*/ 134,
+ -1,
+ /*0x105ab*/ 1238,
+ -1, -1,
+ /*0x1f64*/ 783,
+ /*0x13ba*/ 552,
+ /*0x043a*/ 304,
+ /*0x10d7f*/ 1320,
+ -1,
+ /*0x1043a*/ 1161,
+ /*0x16ec6*/ 1402,
+ /*0xa79d*/ 1090,
+ /*0xa681*/ 1024,
+ /*0x013a*/ 83,
+ /*0x2d13*/ 980,
+ -1, -1, -1, -1,
+ /*0xa685*/ 1026,
+ /*0x0570*/ 457,
+ /*0x1f74*/ 791,
+ /*0x1e09*/ 620,
+ /*0x1e89*/ 684,
+ /*0x0109*/ 60,
+ /*0x0209*/ 170,
+ /*0x2c89*/ 912,
+ /*0x13b8*/ 550,
+ /*0x0438*/ 302,
+ -1, -1,
+ /*0x10438*/ 1159,
+ -1, -1, -1, -1, -1, -1,
+ /*0x10cd4*/ 1274,
+ /*0x16ec4*/ 1400,
+ -1, -1, -1, -1,
+ /*0x10599*/ 1221,
+ -1,
+ /*0x16e77*/ 1382,
+ -1,
+ /*0x118ca*/ 1337,
+ /*0x10cee*/ 1300,
+ /*0x2c4a*/ 878,
+ /*0x13b2*/ 544,
+ /*0x0432*/ 296,
+ /*0x0513*/ 427,
+ /*0x1f15*/ 752,
+ /*0x10432*/ 1153,
+ -1, -1, -1,
+ /*0x10d4*/ 484,
+ /*0x03b6*/ 253,
+ -1, -1,
+ /*0x01d4*/ 145,
+ -1, -1, -1,
+ /*0x1f60*/ 779,
+ -1,
+ /*0x10cde*/ 1284,
+ /*0x10ee*/ 510,
+ /*0x1f7c*/ 799,
+ -1, -1, -1, -1,
+ /*0x057a*/ 467,
+ /*0x00ee*/ 39,
+ -1, -1,
+ /*0x16e66*/ 1365,
+ -1, -1, -1,
+ /*0x10d74*/ 1309,
+ -1, -1, -1, -1, -1,
+ /*0x10de*/ 494,
+ /*0x2c3c*/ 864,
+ -1, -1, -1, -1,
+ /*0x1e93c*/ 1442,
+ -1, -1, -1, -1, -1, -1,
+ -1,
+ /*0x1f07*/ 746,
+ -1, -1, -1, -1,
+ /*0x105bc*/ 1253,
+ -1, -1, -1, -1,
+ /*0x03b4*/ 251,
+ -1, -1, -1, -1,
+ /*0x0576*/ 463,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ /*0x056c*/ 453,
+ /*0x16ecc*/ 1408,
+ /*0x10d7c*/ 1317,
+ -1,
+ /*0x029d*/ 236,
+ -1, -1,
+ /*0x16e70*/ 1375,
+ -1, -1,
+ /*0x2c6a*/ 904,
+ /*0x057f*/ 472,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1,
+ /*0x1f36*/ 767,
+ /*0x03be*/ 261,
+ -1,
+ /*0x2c36*/ 858,
+ /*0x0568*/ 449,
+ -1, -1, -1,
+ /*0x1e936*/ 1436,
+ /*0x1f62*/ 781,
+ -1,
+ /*0x118dc*/ 1355,
+ -1,
+ /*0x2c5c*/ 896,
+ -1, -1, -1, -1, -1, -1,
+ -1,
+ /*0x105b6*/ 1248,
+ -1, -1,
+ /*0x052b*/ 439,
+ -1, -1,
+ /*0x118da*/ 1353,
+ /*0x2d19*/ 986,
+ /*0x2c5a*/ 894,
+ -1,
+ /*0x16eca*/ 1406,
+ -1, -1,
+ /*0x118d6*/ 1349,
+ -1,
+ /*0x2c56*/ 890,
+ -1, -1, -1,
+ /*0x16e7a*/ 1385,
+ -1, -1, -1, -1, -1, -1,
+ /*0x118d8*/ 1351,
+ /*0x0564*/ 445,
+ /*0x2c58*/ 892,
+ -1, -1, -1, -1,
+ /*0x1f34*/ 765,
+ -1, -1,
+ /*0x2c34*/ 856,
+ -1,
+ /*0x2d15*/ 982,
+ -1, -1,
+ /*0x1e934*/ 1434,
+ -1,
+ /*0x1fd0*/ 803,
+ /*0x0574*/ 461,
+ -1,
+ /*0x0519*/ 430,
+ -1, -1, -1, -1,
+ /*0x16ebc*/ 1392,
+ -1, -1,
+ /*0x105b4*/ 1246,
+ -1, -1, -1, -1, -1, -1,
+ -1,
+ /*0x16e76*/ 1381,
+ -1,
+ /*0x10597*/ 1219,
+ -1, -1, -1,
+ /*0x0289*/ 231,
+ -1, -1, -1, -1, -1,
+ /*0x03ba*/ 257,
+ /*0x16e6c*/ 1371,
+ -1,
+ /*0x0515*/ 428,
+ /*0x2c3e*/ 866,
+ /*0xa68f*/ 1031,
+ -1, -1, -1,
+ /*0x1e93e*/ 1444,
+ -1, -1,
+ /*0x16e7f*/ 1390,
+ -1,
+ /*0x2d07*/ 968,
+ -1, -1, -1, -1,
+ /*0x1059d*/ 1225,
+ /*0x057c*/ 469,
+ -1,
+ /*0x03b8*/ 255,
+ -1,
+ /*0x118d4*/ 1347,
+ -1,
+ /*0x2c54*/ 888,
+ -1,
+ /*0x16e68*/ 1367,
+ -1, -1, -1, -1,
+ /*0xff48*/ 1124,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1,
+ /*0xa683*/ 1025,
+ /*0x03b2*/ 249,
+ -1, -1, -1, -1, -1, -1,
+ /*0x0507*/ 421,
+ -1,
+ /*0x118de*/ 1357,
+ -1,
+ /*0x2c5e*/ 898,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1,
+ /*0x16e64*/ 1363,
+ -1,
+ /*0xff4e*/ 1130,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1,
+ /*0x056a*/ 451,
+ /*0x16e74*/ 1379,
+ -1, -1, -1, -1, -1, -1,
+ -1,
+ /*0xff50*/ 1132,
+ /*0x2c3a*/ 862,
+ -1, -1, -1, -1,
+ /*0x1e93a*/ 1440,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1,
+ /*0x0562*/ 443,
+ -1, -1, -1, -1, -1, -1,
+ /*0x2c38*/ 860,
+ -1, -1, -1, -1,
+ /*0x1e938*/ 1438,
+ /*0xff52*/ 1134,
+ -1, -1,
+ /*0x2d17*/ 984,
+ -1, -1, -1, -1,
+ /*0x2d0d*/ 974,
+ /*0x16e60*/ 1359,
+ -1, -1,
+ /*0x105b8*/ 1250,
+ /*0x16e7c*/ 1387,
+ /*0x16ebe*/ 1394,
+ /*0x1f32*/ 763,
+ -1, -1,
+ /*0x2c32*/ 854,
+ -1, -1, -1, -1,
+ /*0x1e932*/ 1432,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1,
+ /*0x2d1d*/ 990,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1,
+ /*0x0517*/ 429,
+ -1, -1, -1, -1,
+ /*0x050d*/ 424,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1,
+ /*0x051d*/ 432,
+ -1, -1, -1, -1, -1, -1,
+ -1,
+ /*0xff46*/ 1122,
+ -1,
+ /*0x16e6a*/ 1369,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ /*0x16e62*/ 1361,
+ /*0x056e*/ 455,
+ /*0xff44*/ 1120,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1,
+ /*0x2d09*/ 970,
+ -1, -1, -1, -1, -1, -1,
+ /*0x1fe0*/ 805,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ /*0xa693*/ 1033,
+ /*0x0509*/ 422,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1,
+ /*0xff4c*/ 1128,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1,
+ /*0x16e6e*/ 1373,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1,
+ /*0xff4a*/ 1126,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1,
+ /*0xa699*/ 1036,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ /*0xa695*/ 1034,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1,
+ /*0xff5a*/ 1142,
+ -1, -1, -1, -1, -1, -1,
+ /*0xff56*/ 1138,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ /*0xff58*/ 1140,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ /*0xa687*/ 1027,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1,
+ /*0xff54*/ 1136,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1,
+ /*0xa697*/ 1035,
+ -1, -1, -1, -1,
+ /*0xa68d*/ 1030,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1,
+ /*0xa689*/ 1028
+ };
+
+ if (code <= MAX_CODE_VALUE && code >= MIN_CODE_VALUE)
+ {
+ register unsigned int key = onigenc_unicode_CaseUnfold_11_hash(code);
+
+ if (key <= MAX_HASH_VALUE)
+ {
+ register short s = wordlist[key];
+
+ if (s >= 0 && code1_equal(code, CaseUnfold_11_Table[s].from))
+ return &CaseUnfold_11_Table[s].to;
+ }
+ }
+ return 0;
+}
+
+static const CaseUnfold_12_Type CaseUnfold_12_Table[] = {
+#define CaseUnfold_12 (*(CaseUnfold_12_Type (*)[58])(CaseUnfold_12_Table+0))
+ {{0x0061, 0x02be}, {1, {0x1e9a}}},
+ {{0x0066, 0x0066}, {1, {0xfb00}}},
+ {{0x0066, 0x0069}, {1, {0xfb01}}},
+ {{0x0066, 0x006c}, {1, {0xfb02}}},
+ {{0x0068, 0x0331}, {1, {0x1e96}}},
+ {{0x006a, 0x030c}, {1, {0x01f0}}},
+ {{0x0073, 0x0073}, {2, {0x00df, 0x1e9e}}},
+ {{0x0073, 0x0074}, {2, {0xfb05, 0xfb06}}},
+ {{0x0074, 0x0308}, {1, {0x1e97}}},
+ {{0x0077, 0x030a}, {1, {0x1e98}}},
+ {{0x0079, 0x030a}, {1, {0x1e99}}},
+ {{0x02bc, 0x006e}, {1, {0x0149}}},
+ {{0x03ac, 0x03b9}, {1, {0x1fb4}}},
+ {{0x03ae, 0x03b9}, {1, {0x1fc4}}},
+ {{0x03b1, 0x0342}, {1, {0x1fb6}}},
+ {{0x03b1, 0x03b9}, {2, {0x1fb3, 0x1fbc}}},
+ {{0x03b7, 0x0342}, {1, {0x1fc6}}},
+ {{0x03b7, 0x03b9}, {2, {0x1fc3, 0x1fcc}}},
+ {{0x03b9, 0x0342}, {1, {0x1fd6}}},
+ {{0x03c1, 0x0313}, {1, {0x1fe4}}},
+ {{0x03c5, 0x0313}, {1, {0x1f50}}},
+ {{0x03c5, 0x0342}, {1, {0x1fe6}}},
+ {{0x03c9, 0x0342}, {1, {0x1ff6}}},
+ {{0x03c9, 0x03b9}, {2, {0x1ff3, 0x1ffc}}},
+ {{0x03ce, 0x03b9}, {1, {0x1ff4}}},
+ {{0x0565, 0x0582}, {1, {0x0587}}},
+ {{0x0574, 0x0565}, {1, {0xfb14}}},
+ {{0x0574, 0x056b}, {1, {0xfb15}}},
+ {{0x0574, 0x056d}, {1, {0xfb17}}},
+ {{0x0574, 0x0576}, {1, {0xfb13}}},
+ {{0x057e, 0x0576}, {1, {0xfb16}}},
+ {{0x1f00, 0x03b9}, {2, {0x1f80, 0x1f88}}},
+ {{0x1f01, 0x03b9}, {2, {0x1f81, 0x1f89}}},
+ {{0x1f02, 0x03b9}, {2, {0x1f82, 0x1f8a}}},
+ {{0x1f03, 0x03b9}, {2, {0x1f83, 0x1f8b}}},
+ {{0x1f04, 0x03b9}, {2, {0x1f84, 0x1f8c}}},
+ {{0x1f05, 0x03b9}, {2, {0x1f85, 0x1f8d}}},
+ {{0x1f06, 0x03b9}, {2, {0x1f86, 0x1f8e}}},
+ {{0x1f07, 0x03b9}, {2, {0x1f87, 0x1f8f}}},
+ {{0x1f20, 0x03b9}, {2, {0x1f90, 0x1f98}}},
+ {{0x1f21, 0x03b9}, {2, {0x1f91, 0x1f99}}},
+ {{0x1f22, 0x03b9}, {2, {0x1f92, 0x1f9a}}},
+ {{0x1f23, 0x03b9}, {2, {0x1f93, 0x1f9b}}},
+ {{0x1f24, 0x03b9}, {2, {0x1f94, 0x1f9c}}},
+ {{0x1f25, 0x03b9}, {2, {0x1f95, 0x1f9d}}},
+ {{0x1f26, 0x03b9}, {2, {0x1f96, 0x1f9e}}},
+ {{0x1f27, 0x03b9}, {2, {0x1f97, 0x1f9f}}},
+ {{0x1f60, 0x03b9}, {2, {0x1fa0, 0x1fa8}}},
+ {{0x1f61, 0x03b9}, {2, {0x1fa1, 0x1fa9}}},
+ {{0x1f62, 0x03b9}, {2, {0x1fa2, 0x1faa}}},
+ {{0x1f63, 0x03b9}, {2, {0x1fa3, 0x1fab}}},
+ {{0x1f64, 0x03b9}, {2, {0x1fa4, 0x1fac}}},
+ {{0x1f65, 0x03b9}, {2, {0x1fa5, 0x1fad}}},
+ {{0x1f66, 0x03b9}, {2, {0x1fa6, 0x1fae}}},
+ {{0x1f67, 0x03b9}, {2, {0x1fa7, 0x1faf}}},
+ {{0x1f70, 0x03b9}, {1, {0x1fb2}}},
+ {{0x1f74, 0x03b9}, {1, {0x1fc2}}},
+ {{0x1f7c, 0x03b9}, {1, {0x1ff2}}},
+#define CaseUnfold_12_Locale (*(CaseUnfold_12_Type (*)[1])(CaseUnfold_12_Table+58))
+ {{0x0069, 0x0307}, {1, {0x0130}}},
+};
+
+/* ANSI-C code produced by gperf version 3.1 */
+/* Command-line: gperf -7 -k1,2,3,4,5,6 -F,-1 -c -j1 -i1 -t -T -E -C -H onigenc_unicode_CaseUnfold_12_hash -N onigenc_unicode_CaseUnfold_12_lookup -n */
+
+/* maximum key range = 71, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+/*ARGSUSED*/
+static unsigned int
+onigenc_unicode_CaseUnfold_12_hash(const OnigCodePoint *codes)
+{
+ static const unsigned char asso_values[] =
+ {
+ 3, 58, 54, 57, 56, 16, 8, 2, 43, 82,
+ 3, 1, 23, 82, 82, 82, 82, 82, 82, 4,
+ 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
+ 82, 82, 52, 51, 50, 49, 48, 47, 46, 45,
+ 82, 82, 82, 82, 43, 82, 42, 82, 82, 13,
+ 82, 82, 82, 82, 82, 11, 82, 1, 82, 82,
+ 14, 82, 1, 82, 82, 31, 3, 82, 82, 30,
+ 82, 82, 82, 10, 82, 82, 82, 82, 37, 82,
+ 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
+ 82, 82, 82, 82, 82, 82, 37, 15, 36, 35,
+ 34, 17, 1, 33, 12, 4, 23, 23, 26, 21,
+ 13, 82, 27, 82, 82, 2, 5, 82, 11, 16,
+ 82, 15, 82, 82, 23, 82, 8, 82
+ };
+ return asso_values[bits_at(codes, 5)] + asso_values[bits_at(codes, 4)] + asso_values[bits_at(codes, 3)] + asso_values[bits_at(codes, 2)] + asso_values[bits_at(codes, 1)] + asso_values[bits_at(codes, 0)];
+}
+
+static const CodePointList2 *
+onigenc_unicode_CaseUnfold_12_lookup(const OnigCodePoint *codes)
+{
+ enum
+ {
+ MIN_CODE_VALUE = 0x61,
+ MAX_CODE_VALUE = 0x1f7c,
+ TOTAL_KEYWORDS = 59,
+ MIN_WORD_LENGTH = 6,
+ MAX_WORD_LENGTH = 6,
+ MIN_HASH_VALUE = 11,
+ MAX_HASH_VALUE = 81
+ };
+
+ static const short wordlist[] =
+ {
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1,
+ /*0x1f66,0x03b9*/ 53,
+ /*0x1f07,0x03b9*/ 38,
+ /*0x1f00,0x03b9*/ 31,
+ /*0x0066,0x0066*/ 1,
+ /*0x1f74,0x03b9*/ 56,
+ /*0x0073,0x0073*/ 6,
+ /*0x0066,0x0069*/ 2,
+ /*0x1f06,0x03b9*/ 37,
+ /*0x0073,0x0074*/ 7,
+ /*0x03b9,0x0342*/ 18,
+ /*0x03c9,0x03b9*/ 23,
+ /*0x03b7,0x03b9*/ 17,
+ /*0x0069,0x0307*/ 58,
+ /*0x03b1,0x03b9*/ 15,
+ /*0x1f61,0x03b9*/ 48,
+ /*0x1f05,0x03b9*/ 36,
+ /*0x1f65,0x03b9*/ 52,
+ /*0x0574,0x0576*/ 29,
+ /*0x03c9,0x0342*/ 22,
+ /*0x03b7,0x0342*/ 16,
+ /*0x057e,0x0576*/ 30,
+ /*0x03b1,0x0342*/ 14,
+ /*0x1f7c,0x03b9*/ 57,
+ /*0x0574,0x0565*/ 26,
+ /*0x0079,0x030a*/ 10,
+ /*0x0077,0x030a*/ 9,
+ /*0x1f70,0x03b9*/ 55,
+ /*0x0574,0x056d*/ 28,
+ /*0x0066,0x006c*/ 3,
+ /*0x0574,0x056b*/ 27,
+ /*0x0061,0x02be*/ 0,
+ /*0x0068,0x0331*/ 4,
+ /*0x1f67,0x03b9*/ 54,
+ /*0x1f64,0x03b9*/ 51,
+ /*0x1f63,0x03b9*/ 50,
+ /*0x1f62,0x03b9*/ 49,
+ /*0x1f60,0x03b9*/ 47,
+ /*0x03ce,0x03b9*/ 24,
+ /*0x03c5,0x0342*/ 21,
+ /*0x03c5,0x0313*/ 20,
+ /*0x03c1,0x0313*/ 19,
+ /*0x02bc,0x006e*/ 11,
+ /*0x03ae,0x03b9*/ 13,
+ /*0x03ac,0x03b9*/ 12,
+ /*0x1f27,0x03b9*/ 46,
+ /*0x1f26,0x03b9*/ 45,
+ /*0x1f25,0x03b9*/ 44,
+ /*0x1f24,0x03b9*/ 43,
+ /*0x1f23,0x03b9*/ 42,
+ /*0x1f22,0x03b9*/ 41,
+ /*0x1f21,0x03b9*/ 40,
+ /*0x1f20,0x03b9*/ 39,
+ /*0x006a,0x030c*/ 5,
+ /*0x1f02,0x03b9*/ 33,
+ /*0x0074,0x0308*/ 8,
+ /*0x1f04,0x03b9*/ 35,
+ /*0x1f03,0x03b9*/ 34,
+ /*0x1f01,0x03b9*/ 32,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ /*0x0565,0x0582*/ 25
+ };
+
+ if (codes[0] <= MAX_CODE_VALUE && codes[0] >= MIN_CODE_VALUE &&
+ codes[1] <= MAX_CODE_VALUE && codes[1] >= MIN_CODE_VALUE)
+ {
+ register unsigned int key = onigenc_unicode_CaseUnfold_12_hash(codes);
+
+ if (key <= MAX_HASH_VALUE)
+ {
+ register short s = wordlist[key];
+
+ if (s >= 0 && code2_equal(codes, CaseUnfold_12_Table[s].from))
+ return &CaseUnfold_12_Table[s].to;
+ }
+ }
+ return 0;
+}
+
+static const CaseUnfold_13_Type CaseUnfold_13_Table[] = {
+#define CaseUnfold_13 (*(CaseUnfold_13_Type (*)[14])(CaseUnfold_13_Table+0))
+ {{0x0066, 0x0066, 0x0069}, {1, {0xfb03}}},
+ {{0x0066, 0x0066, 0x006c}, {1, {0xfb04}}},
+ {{0x03b1, 0x0342, 0x03b9}, {1, {0x1fb7}}},
+ {{0x03b7, 0x0342, 0x03b9}, {1, {0x1fc7}}},
+ {{0x03b9, 0x0308, 0x0300}, {1, {0x1fd2}}},
+ {{0x03b9, 0x0308, 0x0301}, {2, {0x0390, 0x1fd3}}},
+ {{0x03b9, 0x0308, 0x0342}, {1, {0x1fd7}}},
+ {{0x03c5, 0x0308, 0x0300}, {1, {0x1fe2}}},
+ {{0x03c5, 0x0308, 0x0301}, {2, {0x03b0, 0x1fe3}}},
+ {{0x03c5, 0x0308, 0x0342}, {1, {0x1fe7}}},
+ {{0x03c5, 0x0313, 0x0300}, {1, {0x1f52}}},
+ {{0x03c5, 0x0313, 0x0301}, {1, {0x1f54}}},
+ {{0x03c5, 0x0313, 0x0342}, {1, {0x1f56}}},
+ {{0x03c9, 0x0342, 0x03b9}, {1, {0x1ff7}}},
+};
+
+/* ANSI-C code produced by gperf version 3.1 */
+/* Command-line: gperf -7 -k1,2,3,4,5,6,7,8,9 -F,-1 -c -j1 -i1 -t -T -E -C -H onigenc_unicode_CaseUnfold_13_hash -N onigenc_unicode_CaseUnfold_13_lookup -n */
+
+/* maximum key range = 20, duplicates = 0 */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+/*ARGSUSED*/
+static unsigned int
+onigenc_unicode_CaseUnfold_13_hash(const OnigCodePoint *codes)
+{
+ static const unsigned char asso_values[] =
+ {
+ 7, 4, 47, 47, 47, 47, 1, 1, 2, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 1,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 11,
+ 47, 47, 47, 47, 47, 10, 47, 2, 47, 47,
+ 47, 47, 47, 47, 47, 47, 1, 47, 47, 1,
+ 47, 47, 47, 9, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 1, 47, 47, 2, 47, 47, 1, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47
+ };
+ return asso_values[bits_at(codes, 8)] + asso_values[bits_at(codes, 7)] + asso_values[bits_at(codes, 6)] + asso_values[bits_at(codes, 5)] + asso_values[bits_at(codes, 4)] + asso_values[bits_at(codes, 3)] + asso_values[bits_at(codes, 2)] + asso_values[bits_at(codes, 1)] + asso_values[bits_at(codes, 0)];
+}
+
+static const CodePointList2 *
+onigenc_unicode_CaseUnfold_13_lookup(const OnigCodePoint *codes)
+{
+ enum
+ {
+ MIN_CODE_VALUE = 0x66,
+ MAX_CODE_VALUE = 0x3c9,
+ TOTAL_KEYWORDS = 14,
+ MIN_WORD_LENGTH = 9,
+ MAX_WORD_LENGTH = 9,
+ MIN_HASH_VALUE = 27,
+ MAX_HASH_VALUE = 46
+ };
+
+ static const short wordlist[] =
+ {
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1,
+ -1, -1, -1,
+ /*0x03c5,0x0313,0x0342*/ 12,
+ /*0x03c5,0x0308,0x0342*/ 9,
+ /*0x03b9,0x0308,0x0342*/ 6,
+ /*0x03c5,0x0313,0x0301*/ 11,
+ /*0x03c5,0x0308,0x0301*/ 8,
+ /*0x03b9,0x0308,0x0301*/ 5,
+ /*0x03c5,0x0313,0x0300*/ 10,
+ /*0x03c5,0x0308,0x0300*/ 7,
+ /*0x03b9,0x0308,0x0300*/ 4,
+ /*0x03c9,0x0342,0x03b9*/ 13,
+ /*0x03b7,0x0342,0x03b9*/ 3,
+ /*0x03b1,0x0342,0x03b9*/ 2,
+ -1, -1, -1, -1, -1, -1,
+ /*0x0066,0x0066,0x006c*/ 1,
+ /*0x0066,0x0066,0x0069*/ 0
+ };
+
+ if (codes[0] <= MAX_CODE_VALUE && codes[0] >= MIN_CODE_VALUE &&
+ codes[1] <= MAX_CODE_VALUE && codes[1] >= MIN_CODE_VALUE &&
+ codes[2] <= MAX_CODE_VALUE && codes[2] >= MIN_CODE_VALUE)
+ {
+ register unsigned int key = onigenc_unicode_CaseUnfold_13_hash(codes);
+
+ if (key <= MAX_HASH_VALUE)
+ {
+ register short s = wordlist[key];
+
+ if (s >= 0 && code3_equal(codes, CaseUnfold_13_Table[s].from))
+ return &CaseUnfold_13_Table[s].to;
+ }
+ }
+ return 0;
+}
+
+static const OnigCodePoint CaseMappingSpecials[] = {
+ L(1)|0x039C,
+ L(2)|0x0053, 0x0073, L(2)|0x0053, 0x0053,
+ L(2)|0x02BC, 0x004E,
+ L(1)|0x0053,
+ L(1)|0x01C5,
+ L(2)|0x0064, 0x017D, L(1)|0x01C4,
+ L(1)|0x01C8,
+ L(2)|0x006C, 0x004A, L(1)|0x01C7,
+ L(1)|0x01CB,
+ L(2)|0x006E, 0x004A, L(1)|0x01CA,
+ L(2)|0x004A, 0x030C,
+ L(1)|0x01F2,
+ L(2)|0x0064, 0x005A, L(1)|0x01F1,
+ L(1)|0x0399,
+ L(3)|0x0399, 0x0308, 0x0301,
+ L(3)|0x03A5, 0x0308, 0x0301,
+ L(1)|0x03A3,
+ L(1)|0x0392,
+ L(1)|0x0398,
+ L(1)|0x03A6,
+ L(1)|0x03A0,
+ L(1)|0x039A,
+ L(1)|0x03A1,
+ L(1)|0x0395,
+ L(2)|0x0535, 0x0582, L(2)|0x0535, 0x0552,
+ L(1)|0x0412,
+ L(1)|0x0414,
+ L(1)|0x041E,
+ L(1)|0x0421,
+ L(1)|0x0422,
+ L(1)|0x0422,
+ L(1)|0x042A,
+ L(1)|0x0462,
+ L(1)|0xA64A,
+ L(2)|0x0048, 0x0331,
+ L(2)|0x0054, 0x0308,
+ L(2)|0x0057, 0x030A,
+ L(2)|0x0059, 0x030A,
+ L(2)|0x0041, 0x02BE,
+ L(1)|0x1E60,
+ L(1)|0x00DF,
+ L(2)|0x03A5, 0x0313,
+ L(3)|0x03A5, 0x0313, 0x0300,
+ L(3)|0x03A5, 0x0313, 0x0301,
+ L(3)|0x03A5, 0x0313, 0x0342,
+ L(1)|0x1F88, L(2)|0x1F08, 0x0399,
+ L(1)|0x1F89, L(2)|0x1F09, 0x0399,
+ L(1)|0x1F8A, L(2)|0x1F0A, 0x0399,
+ L(1)|0x1F8B, L(2)|0x1F0B, 0x0399,
+ L(1)|0x1F8C, L(2)|0x1F0C, 0x0399,
+ L(1)|0x1F8D, L(2)|0x1F0D, 0x0399,
+ L(1)|0x1F8E, L(2)|0x1F0E, 0x0399,
+ L(1)|0x1F8F, L(2)|0x1F0F, 0x0399,
+ L(2)|0x1F00, 0x0399, L(1)|0x1F80, L(2)|0x1F08, 0x0399,
+ L(2)|0x1F01, 0x0399, L(1)|0x1F81, L(2)|0x1F09, 0x0399,
+ L(2)|0x1F02, 0x0399, L(1)|0x1F82, L(2)|0x1F0A, 0x0399,
+ L(2)|0x1F03, 0x0399, L(1)|0x1F83, L(2)|0x1F0B, 0x0399,
+ L(2)|0x1F04, 0x0399, L(1)|0x1F84, L(2)|0x1F0C, 0x0399,
+ L(2)|0x1F05, 0x0399, L(1)|0x1F85, L(2)|0x1F0D, 0x0399,
+ L(2)|0x1F06, 0x0399, L(1)|0x1F86, L(2)|0x1F0E, 0x0399,
+ L(2)|0x1F07, 0x0399, L(1)|0x1F87, L(2)|0x1F0F, 0x0399,
+ L(1)|0x1F98, L(2)|0x1F28, 0x0399,
+ L(1)|0x1F99, L(2)|0x1F29, 0x0399,
+ L(1)|0x1F9A, L(2)|0x1F2A, 0x0399,
+ L(1)|0x1F9B, L(2)|0x1F2B, 0x0399,
+ L(1)|0x1F9C, L(2)|0x1F2C, 0x0399,
+ L(1)|0x1F9D, L(2)|0x1F2D, 0x0399,
+ L(1)|0x1F9E, L(2)|0x1F2E, 0x0399,
+ L(1)|0x1F9F, L(2)|0x1F2F, 0x0399,
+ L(2)|0x1F20, 0x0399, L(1)|0x1F90, L(2)|0x1F28, 0x0399,
+ L(2)|0x1F21, 0x0399, L(1)|0x1F91, L(2)|0x1F29, 0x0399,
+ L(2)|0x1F22, 0x0399, L(1)|0x1F92, L(2)|0x1F2A, 0x0399,
+ L(2)|0x1F23, 0x0399, L(1)|0x1F93, L(2)|0x1F2B, 0x0399,
+ L(2)|0x1F24, 0x0399, L(1)|0x1F94, L(2)|0x1F2C, 0x0399,
+ L(2)|0x1F25, 0x0399, L(1)|0x1F95, L(2)|0x1F2D, 0x0399,
+ L(2)|0x1F26, 0x0399, L(1)|0x1F96, L(2)|0x1F2E, 0x0399,
+ L(2)|0x1F27, 0x0399, L(1)|0x1F97, L(2)|0x1F2F, 0x0399,
+ L(1)|0x1FA8, L(2)|0x1F68, 0x0399,
+ L(1)|0x1FA9, L(2)|0x1F69, 0x0399,
+ L(1)|0x1FAA, L(2)|0x1F6A, 0x0399,
+ L(1)|0x1FAB, L(2)|0x1F6B, 0x0399,
+ L(1)|0x1FAC, L(2)|0x1F6C, 0x0399,
+ L(1)|0x1FAD, L(2)|0x1F6D, 0x0399,
+ L(1)|0x1FAE, L(2)|0x1F6E, 0x0399,
+ L(1)|0x1FAF, L(2)|0x1F6F, 0x0399,
+ L(2)|0x1F60, 0x0399, L(1)|0x1FA0, L(2)|0x1F68, 0x0399,
+ L(2)|0x1F61, 0x0399, L(1)|0x1FA1, L(2)|0x1F69, 0x0399,
+ L(2)|0x1F62, 0x0399, L(1)|0x1FA2, L(2)|0x1F6A, 0x0399,
+ L(2)|0x1F63, 0x0399, L(1)|0x1FA3, L(2)|0x1F6B, 0x0399,
+ L(2)|0x1F64, 0x0399, L(1)|0x1FA4, L(2)|0x1F6C, 0x0399,
+ L(2)|0x1F65, 0x0399, L(1)|0x1FA5, L(2)|0x1F6D, 0x0399,
+ L(2)|0x1F66, 0x0399, L(1)|0x1FA6, L(2)|0x1F6E, 0x0399,
+ L(2)|0x1F67, 0x0399, L(1)|0x1FA7, L(2)|0x1F6F, 0x0399,
+ L(2)|0x1FBA, 0x0345, L(2)|0x1FBA, 0x0399,
+ L(1)|0x1FBC, L(2)|0x0391, 0x0399,
+ L(2)|0x0386, 0x0345, L(2)|0x0386, 0x0399,
+ L(2)|0x0391, 0x0342,
+ L(3)|0x0391, 0x0342, 0x0345, L(3)|0x0391, 0x0342, 0x0399,
+ L(2)|0x03B1, 0x0399, L(1)|0x1FB3, L(2)|0x0391, 0x0399,
+ L(1)|0x0399,
+ L(2)|0x1FCA, 0x0345, L(2)|0x1FCA, 0x0399,
+ L(1)|0x1FCC, L(2)|0x0397, 0x0399,
+ L(2)|0x0389, 0x0345, L(2)|0x0389, 0x0399,
+ L(2)|0x0397, 0x0342,
+ L(3)|0x0397, 0x0342, 0x0345, L(3)|0x0397, 0x0342, 0x0399,
+ L(2)|0x03B7, 0x0399, L(1)|0x1FC3, L(2)|0x0397, 0x0399,
+ L(3)|0x0399, 0x0308, 0x0300,
+ L(3)|0x0399, 0x0308, 0x0301,
+ L(2)|0x0399, 0x0342,
+ L(3)|0x0399, 0x0308, 0x0342,
+ L(3)|0x03A5, 0x0308, 0x0300,
+ L(3)|0x03A5, 0x0308, 0x0301,
+ L(2)|0x03A1, 0x0313,
+ L(2)|0x03A5, 0x0342,
+ L(3)|0x03A5, 0x0308, 0x0342,
+ L(2)|0x1FFA, 0x0345, L(2)|0x1FFA, 0x0399,
+ L(1)|0x1FFC, L(2)|0x03A9, 0x0399,
+ L(2)|0x038F, 0x0345, L(2)|0x038F, 0x0399,
+ L(2)|0x03A9, 0x0342,
+ L(3)|0x03A9, 0x0342, 0x0345, L(3)|0x03A9, 0x0342, 0x0399,
+ L(2)|0x03C9, 0x0399, L(1)|0x1FF3, L(2)|0x03A9, 0x0399,
+ L(2)|0x0046, 0x0066, L(2)|0x0046, 0x0046,
+ L(2)|0x0046, 0x0069, L(2)|0x0046, 0x0049,
+ L(2)|0x0046, 0x006C, L(2)|0x0046, 0x004C,
+ L(3)|0x0046, 0x0066, 0x0069, L(3)|0x0046, 0x0046, 0x0049,
+ L(3)|0x0046, 0x0066, 0x006C, L(3)|0x0046, 0x0046, 0x004C,
+ L(2)|0x0053, 0x0074, L(2)|0x0053, 0x0054,
+ L(2)|0x0053, 0x0074, L(2)|0x0053, 0x0054,
+ L(2)|0x0544, 0x0576, L(2)|0x0544, 0x0546,
+ L(2)|0x0544, 0x0565, L(2)|0x0544, 0x0535,
+ L(2)|0x0544, 0x056B, L(2)|0x0544, 0x053B,
+ L(2)|0x054E, 0x0576, L(2)|0x054E, 0x0546,
+ L(2)|0x0544, 0x056D, L(2)|0x0544, 0x053D,
+};
diff --git a/enc/unicode/17.0.0/name2ctype.h b/enc/unicode/17.0.0/name2ctype.h
new file mode 100644
index 0000000000..8c1c0659ac
--- /dev/null
+++ b/enc/unicode/17.0.0/name2ctype.h
@@ -0,0 +1,49725 @@
+/* ANSI-C code produced by gperf version 3.1 */
+/* Command-line: gperf -7 -c -j1 -i1 -t -C -P -T -H uniname2ctype_hash -Q uniname2ctype_pool -N uniname2ctype_p */
+#ifndef USE_UNICODE_PROPERTIES
+/* Computed positions: -k'1,3' */
+#else /* USE_UNICODE_PROPERTIES */
+/* Computed positions: -k'1-3,5-6,12,16,$' */
+#endif /* USE_UNICODE_PROPERTIES */
+
+#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
+ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
+ && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
+ && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
+ && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
+ && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
+ && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
+ && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
+ && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
+ && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
+ && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
+ && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
+ && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
+ && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
+ && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
+ && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
+ && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
+ && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
+ && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
+ && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
+ && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
+ && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
+ && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
+/* The character set is not based on ISO-646. */
+#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gperf@gnu.org>."
+#endif
+
+
+
+/* 'NEWLINE': [[:NEWLINE:]] */
+static const OnigCodePoint CR_NEWLINE[] = {
+ 1,
+ 0x000a, 0x000a,
+}; /* CR_NEWLINE */
+
+/* 'Alpha': [[:Alpha:]] */
+static const OnigCodePoint CR_Alpha[] = {
+ 761,
+ 0x0041, 0x005a,
+ 0x0061, 0x007a,
+ 0x00aa, 0x00aa,
+ 0x00b5, 0x00b5,
+ 0x00ba, 0x00ba,
+ 0x00c0, 0x00d6,
+ 0x00d8, 0x00f6,
+ 0x00f8, 0x02c1,
+ 0x02c6, 0x02d1,
+ 0x02e0, 0x02e4,
+ 0x02ec, 0x02ec,
+ 0x02ee, 0x02ee,
+ 0x0345, 0x0345,
+ 0x0363, 0x0374,
+ 0x0376, 0x0377,
+ 0x037a, 0x037d,
+ 0x037f, 0x037f,
+ 0x0386, 0x0386,
+ 0x0388, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x03f5,
+ 0x03f7, 0x0481,
+ 0x048a, 0x052f,
+ 0x0531, 0x0556,
+ 0x0559, 0x0559,
+ 0x0560, 0x0588,
+ 0x05b0, 0x05bd,
+ 0x05bf, 0x05bf,
+ 0x05c1, 0x05c2,
+ 0x05c4, 0x05c5,
+ 0x05c7, 0x05c7,
+ 0x05d0, 0x05ea,
+ 0x05ef, 0x05f2,
+ 0x0610, 0x061a,
+ 0x0620, 0x0657,
+ 0x0659, 0x065f,
+ 0x066e, 0x06d3,
+ 0x06d5, 0x06dc,
+ 0x06e1, 0x06e8,
+ 0x06ed, 0x06ef,
+ 0x06fa, 0x06fc,
+ 0x06ff, 0x06ff,
+ 0x0710, 0x073f,
+ 0x074d, 0x07b1,
+ 0x07ca, 0x07ea,
+ 0x07f4, 0x07f5,
+ 0x07fa, 0x07fa,
+ 0x0800, 0x0817,
+ 0x081a, 0x082c,
+ 0x0840, 0x0858,
+ 0x0860, 0x086a,
+ 0x0870, 0x0887,
+ 0x0889, 0x088f,
+ 0x0897, 0x0897,
+ 0x08a0, 0x08c9,
+ 0x08d4, 0x08df,
+ 0x08e3, 0x08e9,
+ 0x08f0, 0x093b,
+ 0x093d, 0x094c,
+ 0x094e, 0x0950,
+ 0x0955, 0x0963,
+ 0x0971, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bd, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09cc,
+ 0x09ce, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09f0, 0x09f1,
+ 0x09fc, 0x09fc,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4c,
+ 0x0a51, 0x0a51,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a70, 0x0a75,
+ 0x0a81, 0x0a83,
+ 0x0a85, 0x0a8d,
+ 0x0a8f, 0x0a91,
+ 0x0a93, 0x0aa8,
+ 0x0aaa, 0x0ab0,
+ 0x0ab2, 0x0ab3,
+ 0x0ab5, 0x0ab9,
+ 0x0abd, 0x0ac5,
+ 0x0ac7, 0x0ac9,
+ 0x0acb, 0x0acc,
+ 0x0ad0, 0x0ad0,
+ 0x0ae0, 0x0ae3,
+ 0x0af9, 0x0afc,
+ 0x0b01, 0x0b03,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b35, 0x0b39,
+ 0x0b3d, 0x0b44,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4c,
+ 0x0b56, 0x0b57,
+ 0x0b5c, 0x0b5d,
+ 0x0b5f, 0x0b63,
+ 0x0b71, 0x0b71,
+ 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, 0x0bcc,
+ 0x0bd0, 0x0bd0,
+ 0x0bd7, 0x0bd7,
+ 0x0c00, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3d, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4c,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c5a,
+ 0x0c5c, 0x0c5d,
+ 0x0c60, 0x0c63,
+ 0x0c80, 0x0c83,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbd, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccc,
+ 0x0cd5, 0x0cd6,
+ 0x0cdc, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0cf1, 0x0cf3,
+ 0x0d00, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d3a,
+ 0x0d3d, 0x0d44,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4c,
+ 0x0d4e, 0x0d4e,
+ 0x0d54, 0x0d57,
+ 0x0d5f, 0x0d63,
+ 0x0d7a, 0x0d7f,
+ 0x0d81, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0df2, 0x0df3,
+ 0x0e01, 0x0e3a,
+ 0x0e40, 0x0e46,
+ 0x0e4d, 0x0e4d,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e86, 0x0e8a,
+ 0x0e8c, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0eb9,
+ 0x0ebb, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ecd, 0x0ecd,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f00,
+ 0x0f40, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f83,
+ 0x0f88, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 0x1000, 0x1036,
+ 0x1038, 0x1038,
+ 0x103b, 0x103f,
+ 0x1050, 0x108f,
+ 0x109a, 0x109d,
+ 0x10a0, 0x10c5,
+ 0x10c7, 0x10c7,
+ 0x10cd, 0x10cd,
+ 0x10d0, 0x10fa,
+ 0x10fc, 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,
+ 0x1380, 0x138f,
+ 0x13a0, 0x13f5,
+ 0x13f8, 0x13fd,
+ 0x1401, 0x166c,
+ 0x166f, 0x167f,
+ 0x1681, 0x169a,
+ 0x16a0, 0x16ea,
+ 0x16ee, 0x16f8,
+ 0x1700, 0x1713,
+ 0x171f, 0x1733,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17b3,
+ 0x17b6, 0x17c8,
+ 0x17d7, 0x17d7,
+ 0x17dc, 0x17dc,
+ 0x1820, 0x1878,
+ 0x1880, 0x18aa,
+ 0x18b0, 0x18f5,
+ 0x1900, 0x191e,
+ 0x1920, 0x192b,
+ 0x1930, 0x1938,
+ 0x1950, 0x196d,
+ 0x1970, 0x1974,
+ 0x1980, 0x19ab,
+ 0x19b0, 0x19c9,
+ 0x1a00, 0x1a1b,
+ 0x1a20, 0x1a5e,
+ 0x1a61, 0x1a74,
+ 0x1aa7, 0x1aa7,
+ 0x1abf, 0x1ac0,
+ 0x1acc, 0x1ace,
+ 0x1b00, 0x1b33,
+ 0x1b35, 0x1b43,
+ 0x1b45, 0x1b4c,
+ 0x1b80, 0x1ba9,
+ 0x1bac, 0x1baf,
+ 0x1bba, 0x1be5,
+ 0x1be7, 0x1bf1,
+ 0x1c00, 0x1c36,
+ 0x1c4d, 0x1c4f,
+ 0x1c5a, 0x1c7d,
+ 0x1c80, 0x1c8a,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cbf,
+ 0x1ce9, 0x1cec,
+ 0x1cee, 0x1cf3,
+ 0x1cf5, 0x1cf6,
+ 0x1cfa, 0x1cfa,
+ 0x1d00, 0x1dbf,
+ 0x1dd3, 0x1df4,
+ 0x1e00, 0x1f15,
+ 0x1f18, 0x1f1d,
+ 0x1f20, 0x1f45,
+ 0x1f48, 0x1f4d,
+ 0x1f50, 0x1f57,
+ 0x1f59, 0x1f59,
+ 0x1f5b, 0x1f5b,
+ 0x1f5d, 0x1f5d,
+ 0x1f5f, 0x1f7d,
+ 0x1f80, 0x1fb4,
+ 0x1fb6, 0x1fbc,
+ 0x1fbe, 0x1fbe,
+ 0x1fc2, 0x1fc4,
+ 0x1fc6, 0x1fcc,
+ 0x1fd0, 0x1fd3,
+ 0x1fd6, 0x1fdb,
+ 0x1fe0, 0x1fec,
+ 0x1ff2, 0x1ff4,
+ 0x1ff6, 0x1ffc,
+ 0x2071, 0x2071,
+ 0x207f, 0x207f,
+ 0x2090, 0x209c,
+ 0x2102, 0x2102,
+ 0x2107, 0x2107,
+ 0x210a, 0x2113,
+ 0x2115, 0x2115,
+ 0x2119, 0x211d,
+ 0x2124, 0x2124,
+ 0x2126, 0x2126,
+ 0x2128, 0x2128,
+ 0x212a, 0x212d,
+ 0x212f, 0x2139,
+ 0x213c, 0x213f,
+ 0x2145, 0x2149,
+ 0x214e, 0x214e,
+ 0x2160, 0x2188,
+ 0x24b6, 0x24e9,
+ 0x2c00, 0x2ce4,
+ 0x2ceb, 0x2cee,
+ 0x2cf2, 0x2cf3,
+ 0x2d00, 0x2d25,
+ 0x2d27, 0x2d27,
+ 0x2d2d, 0x2d2d,
+ 0x2d30, 0x2d67,
+ 0x2d6f, 0x2d6f,
+ 0x2d80, 0x2d96,
+ 0x2da0, 0x2da6,
+ 0x2da8, 0x2dae,
+ 0x2db0, 0x2db6,
+ 0x2db8, 0x2dbe,
+ 0x2dc0, 0x2dc6,
+ 0x2dc8, 0x2dce,
+ 0x2dd0, 0x2dd6,
+ 0x2dd8, 0x2dde,
+ 0x2de0, 0x2dff,
+ 0x2e2f, 0x2e2f,
+ 0x3005, 0x3007,
+ 0x3021, 0x3029,
+ 0x3031, 0x3035,
+ 0x3038, 0x303c,
+ 0x3041, 0x3096,
+ 0x309d, 0x309f,
+ 0x30a1, 0x30fa,
+ 0x30fc, 0x30ff,
+ 0x3105, 0x312f,
+ 0x3131, 0x318e,
+ 0x31a0, 0x31bf,
+ 0x31f0, 0x31ff,
+ 0x3400, 0x4dbf,
+ 0x4e00, 0xa48c,
+ 0xa4d0, 0xa4fd,
+ 0xa500, 0xa60c,
+ 0xa610, 0xa61f,
+ 0xa62a, 0xa62b,
+ 0xa640, 0xa66e,
+ 0xa674, 0xa67b,
+ 0xa67f, 0xa6ef,
+ 0xa717, 0xa71f,
+ 0xa722, 0xa788,
+ 0xa78b, 0xa7dc,
+ 0xa7f1, 0xa805,
+ 0xa807, 0xa827,
+ 0xa840, 0xa873,
+ 0xa880, 0xa8c3,
+ 0xa8c5, 0xa8c5,
+ 0xa8f2, 0xa8f7,
+ 0xa8fb, 0xa8fb,
+ 0xa8fd, 0xa8ff,
+ 0xa90a, 0xa92a,
+ 0xa930, 0xa952,
+ 0xa960, 0xa97c,
+ 0xa980, 0xa9b2,
+ 0xa9b4, 0xa9bf,
+ 0xa9cf, 0xa9cf,
+ 0xa9e0, 0xa9ef,
+ 0xa9fa, 0xa9fe,
+ 0xaa00, 0xaa36,
+ 0xaa40, 0xaa4d,
+ 0xaa60, 0xaa76,
+ 0xaa7a, 0xaabe,
+ 0xaac0, 0xaac0,
+ 0xaac2, 0xaac2,
+ 0xaadb, 0xaadd,
+ 0xaae0, 0xaaef,
+ 0xaaf2, 0xaaf5,
+ 0xab01, 0xab06,
+ 0xab09, 0xab0e,
+ 0xab11, 0xab16,
+ 0xab20, 0xab26,
+ 0xab28, 0xab2e,
+ 0xab30, 0xab5a,
+ 0xab5c, 0xab69,
+ 0xab70, 0xabea,
+ 0xac00, 0xd7a3,
+ 0xd7b0, 0xd7c6,
+ 0xd7cb, 0xd7fb,
+ 0xf900, 0xfa6d,
+ 0xfa70, 0xfad9,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xfb1d, 0xfb28,
+ 0xfb2a, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfbb1,
+ 0xfbd3, 0xfd3d,
+ 0xfd50, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdf0, 0xfdfb,
+ 0xfe70, 0xfe74,
+ 0xfe76, 0xfefc,
+ 0xff21, 0xff3a,
+ 0xff41, 0xff5a,
+ 0xff66, 0xffbe,
+ 0xffc2, 0xffc7,
+ 0xffca, 0xffcf,
+ 0xffd2, 0xffd7,
+ 0xffda, 0xffdc,
+ 0x10000, 0x1000b,
+ 0x1000d, 0x10026,
+ 0x10028, 0x1003a,
+ 0x1003c, 0x1003d,
+ 0x1003f, 0x1004d,
+ 0x10050, 0x1005d,
+ 0x10080, 0x100fa,
+ 0x10140, 0x10174,
+ 0x10280, 0x1029c,
+ 0x102a0, 0x102d0,
+ 0x10300, 0x1031f,
+ 0x1032d, 0x1034a,
+ 0x10350, 0x1037a,
+ 0x10380, 0x1039d,
+ 0x103a0, 0x103c3,
+ 0x103c8, 0x103cf,
+ 0x103d1, 0x103d5,
+ 0x10400, 0x1049d,
+ 0x104b0, 0x104d3,
+ 0x104d8, 0x104fb,
+ 0x10500, 0x10527,
+ 0x10530, 0x10563,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x105c0, 0x105f3,
+ 0x10600, 0x10736,
+ 0x10740, 0x10755,
+ 0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 0x10837, 0x10838,
+ 0x1083c, 0x1083c,
+ 0x1083f, 0x10855,
+ 0x10860, 0x10876,
+ 0x10880, 0x1089e,
+ 0x108e0, 0x108f2,
+ 0x108f4, 0x108f5,
+ 0x10900, 0x10915,
+ 0x10920, 0x10939,
+ 0x10940, 0x10959,
+ 0x10980, 0x109b7,
+ 0x109be, 0x109bf,
+ 0x10a00, 0x10a03,
+ 0x10a05, 0x10a06,
+ 0x10a0c, 0x10a13,
+ 0x10a15, 0x10a17,
+ 0x10a19, 0x10a35,
+ 0x10a60, 0x10a7c,
+ 0x10a80, 0x10a9c,
+ 0x10ac0, 0x10ac7,
+ 0x10ac9, 0x10ae4,
+ 0x10b00, 0x10b35,
+ 0x10b40, 0x10b55,
+ 0x10b60, 0x10b72,
+ 0x10b80, 0x10b91,
+ 0x10c00, 0x10c48,
+ 0x10c80, 0x10cb2,
+ 0x10cc0, 0x10cf2,
+ 0x10d00, 0x10d27,
+ 0x10d4a, 0x10d65,
+ 0x10d69, 0x10d69,
+ 0x10d6f, 0x10d85,
+ 0x10e80, 0x10ea9,
+ 0x10eab, 0x10eac,
+ 0x10eb0, 0x10eb1,
+ 0x10ec2, 0x10ec7,
+ 0x10efa, 0x10efc,
+ 0x10f00, 0x10f1c,
+ 0x10f27, 0x10f27,
+ 0x10f30, 0x10f45,
+ 0x10f70, 0x10f81,
+ 0x10fb0, 0x10fc4,
+ 0x10fe0, 0x10ff6,
+ 0x11000, 0x11045,
+ 0x11071, 0x11075,
+ 0x11080, 0x110b8,
+ 0x110c2, 0x110c2,
+ 0x110d0, 0x110e8,
+ 0x11100, 0x11132,
+ 0x11144, 0x11147,
+ 0x11150, 0x11172,
+ 0x11176, 0x11176,
+ 0x11180, 0x111bf,
+ 0x111c1, 0x111c4,
+ 0x111ce, 0x111cf,
+ 0x111da, 0x111da,
+ 0x111dc, 0x111dc,
+ 0x11200, 0x11211,
+ 0x11213, 0x11234,
+ 0x11237, 0x11237,
+ 0x1123e, 0x11241,
+ 0x11280, 0x11286,
+ 0x11288, 0x11288,
+ 0x1128a, 0x1128d,
+ 0x1128f, 0x1129d,
+ 0x1129f, 0x112a8,
+ 0x112b0, 0x112e8,
+ 0x11300, 0x11303,
+ 0x11305, 0x1130c,
+ 0x1130f, 0x11310,
+ 0x11313, 0x11328,
+ 0x1132a, 0x11330,
+ 0x11332, 0x11333,
+ 0x11335, 0x11339,
+ 0x1133d, 0x11344,
+ 0x11347, 0x11348,
+ 0x1134b, 0x1134c,
+ 0x11350, 0x11350,
+ 0x11357, 0x11357,
+ 0x1135d, 0x11363,
+ 0x11380, 0x11389,
+ 0x1138b, 0x1138b,
+ 0x1138e, 0x1138e,
+ 0x11390, 0x113b5,
+ 0x113b7, 0x113c0,
+ 0x113c2, 0x113c2,
+ 0x113c5, 0x113c5,
+ 0x113c7, 0x113ca,
+ 0x113cc, 0x113cd,
+ 0x113d1, 0x113d1,
+ 0x113d3, 0x113d3,
+ 0x11400, 0x11441,
+ 0x11443, 0x11445,
+ 0x11447, 0x1144a,
+ 0x1145f, 0x11461,
+ 0x11480, 0x114c1,
+ 0x114c4, 0x114c5,
+ 0x114c7, 0x114c7,
+ 0x11580, 0x115b5,
+ 0x115b8, 0x115be,
+ 0x115d8, 0x115dd,
+ 0x11600, 0x1163e,
+ 0x11640, 0x11640,
+ 0x11644, 0x11644,
+ 0x11680, 0x116b5,
+ 0x116b8, 0x116b8,
+ 0x11700, 0x1171a,
+ 0x1171d, 0x1172a,
+ 0x11740, 0x11746,
+ 0x11800, 0x11838,
+ 0x118a0, 0x118df,
+ 0x118ff, 0x11906,
+ 0x11909, 0x11909,
+ 0x1190c, 0x11913,
+ 0x11915, 0x11916,
+ 0x11918, 0x11935,
+ 0x11937, 0x11938,
+ 0x1193b, 0x1193c,
+ 0x1193f, 0x11942,
+ 0x119a0, 0x119a7,
+ 0x119aa, 0x119d7,
+ 0x119da, 0x119df,
+ 0x119e1, 0x119e1,
+ 0x119e3, 0x119e4,
+ 0x11a00, 0x11a32,
+ 0x11a35, 0x11a3e,
+ 0x11a50, 0x11a97,
+ 0x11a9d, 0x11a9d,
+ 0x11ab0, 0x11af8,
+ 0x11b60, 0x11b67,
+ 0x11bc0, 0x11be0,
+ 0x11c00, 0x11c08,
+ 0x11c0a, 0x11c36,
+ 0x11c38, 0x11c3e,
+ 0x11c40, 0x11c40,
+ 0x11c72, 0x11c8f,
+ 0x11c92, 0x11ca7,
+ 0x11ca9, 0x11cb6,
+ 0x11d00, 0x11d06,
+ 0x11d08, 0x11d09,
+ 0x11d0b, 0x11d36,
+ 0x11d3a, 0x11d3a,
+ 0x11d3c, 0x11d3d,
+ 0x11d3f, 0x11d41,
+ 0x11d43, 0x11d43,
+ 0x11d46, 0x11d47,
+ 0x11d60, 0x11d65,
+ 0x11d67, 0x11d68,
+ 0x11d6a, 0x11d8e,
+ 0x11d90, 0x11d91,
+ 0x11d93, 0x11d96,
+ 0x11d98, 0x11d98,
+ 0x11db0, 0x11ddb,
+ 0x11ee0, 0x11ef6,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f40,
+ 0x11fb0, 0x11fb0,
+ 0x12000, 0x12399,
+ 0x12400, 0x1246e,
+ 0x12480, 0x12543,
+ 0x12f90, 0x12ff0,
+ 0x13000, 0x1342f,
+ 0x13441, 0x13446,
+ 0x13460, 0x143fa,
+ 0x14400, 0x14646,
+ 0x16100, 0x1612e,
+ 0x16800, 0x16a38,
+ 0x16a40, 0x16a5e,
+ 0x16a70, 0x16abe,
+ 0x16ad0, 0x16aed,
+ 0x16b00, 0x16b2f,
+ 0x16b40, 0x16b43,
+ 0x16b63, 0x16b77,
+ 0x16b7d, 0x16b8f,
+ 0x16d40, 0x16d6c,
+ 0x16e40, 0x16e7f,
+ 0x16ea0, 0x16eb8,
+ 0x16ebb, 0x16ed3,
+ 0x16f00, 0x16f4a,
+ 0x16f4f, 0x16f87,
+ 0x16f8f, 0x16f9f,
+ 0x16fe0, 0x16fe1,
+ 0x16fe3, 0x16fe3,
+ 0x16ff0, 0x16ff6,
+ 0x17000, 0x18cd5,
+ 0x18cff, 0x18d1e,
+ 0x18d80, 0x18df2,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
+ 0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
+ 0x1b164, 0x1b167,
+ 0x1b170, 0x1b2fb,
+ 0x1bc00, 0x1bc6a,
+ 0x1bc70, 0x1bc7c,
+ 0x1bc80, 0x1bc88,
+ 0x1bc90, 0x1bc99,
+ 0x1bc9e, 0x1bc9e,
+ 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, 0x1d6c0,
+ 0x1d6c2, 0x1d6da,
+ 0x1d6dc, 0x1d6fa,
+ 0x1d6fc, 0x1d714,
+ 0x1d716, 0x1d734,
+ 0x1d736, 0x1d74e,
+ 0x1d750, 0x1d76e,
+ 0x1d770, 0x1d788,
+ 0x1d78a, 0x1d7a8,
+ 0x1d7aa, 0x1d7c2,
+ 0x1d7c4, 0x1d7cb,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e000, 0x1e006,
+ 0x1e008, 0x1e018,
+ 0x1e01b, 0x1e021,
+ 0x1e023, 0x1e024,
+ 0x1e026, 0x1e02a,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
+ 0x1e100, 0x1e12c,
+ 0x1e137, 0x1e13d,
+ 0x1e14e, 0x1e14e,
+ 0x1e290, 0x1e2ad,
+ 0x1e2c0, 0x1e2eb,
+ 0x1e4d0, 0x1e4eb,
+ 0x1e5d0, 0x1e5ed,
+ 0x1e5f0, 0x1e5f0,
+ 0x1e6c0, 0x1e6de,
+ 0x1e6e0, 0x1e6f5,
+ 0x1e6fe, 0x1e6ff,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
+ 0x1e800, 0x1e8c4,
+ 0x1e900, 0x1e943,
+ 0x1e947, 0x1e947,
+ 0x1e94b, 0x1e94b,
+ 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,
+ 0x1f130, 0x1f149,
+ 0x1f150, 0x1f169,
+ 0x1f170, 0x1f189,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b81d,
+ 0x2b820, 0x2cead,
+ 0x2ceb0, 0x2ebe0,
+ 0x2ebf0, 0x2ee5d,
+ 0x2f800, 0x2fa1d,
+ 0x30000, 0x3134a,
+ 0x31350, 0x33479,
+}; /* CR_Alpha */
+
+/* 'Blank': [[:Blank:]] */
+static const OnigCodePoint CR_Blank[] = {
+ 8,
+ 0x0009, 0x0009,
+ 0x0020, 0x0020,
+ 0x00a0, 0x00a0,
+ 0x1680, 0x1680,
+ 0x2000, 0x200a,
+ 0x202f, 0x202f,
+ 0x205f, 0x205f,
+ 0x3000, 0x3000,
+}; /* CR_Blank */
+
+/* 'Cntrl': [[:Cntrl:]] */
+static const OnigCodePoint CR_Cntrl[] = {
+ 2,
+ 0x0000, 0x001f,
+ 0x007f, 0x009f,
+}; /* CR_Cntrl */
+
+/* 'Digit': [[:Digit:]] */
+static const OnigCodePoint CR_Digit[] = {
+ 72,
+ 0x0030, 0x0039,
+ 0x0660, 0x0669,
+ 0x06f0, 0x06f9,
+ 0x07c0, 0x07c9,
+ 0x0966, 0x096f,
+ 0x09e6, 0x09ef,
+ 0x0a66, 0x0a6f,
+ 0x0ae6, 0x0aef,
+ 0x0b66, 0x0b6f,
+ 0x0be6, 0x0bef,
+ 0x0c66, 0x0c6f,
+ 0x0ce6, 0x0cef,
+ 0x0d66, 0x0d6f,
+ 0x0de6, 0x0def,
+ 0x0e50, 0x0e59,
+ 0x0ed0, 0x0ed9,
+ 0x0f20, 0x0f29,
+ 0x1040, 0x1049,
+ 0x1090, 0x1099,
+ 0x17e0, 0x17e9,
+ 0x1810, 0x1819,
+ 0x1946, 0x194f,
+ 0x19d0, 0x19d9,
+ 0x1a80, 0x1a89,
+ 0x1a90, 0x1a99,
+ 0x1b50, 0x1b59,
+ 0x1bb0, 0x1bb9,
+ 0x1c40, 0x1c49,
+ 0x1c50, 0x1c59,
+ 0xa620, 0xa629,
+ 0xa8d0, 0xa8d9,
+ 0xa900, 0xa909,
+ 0xa9d0, 0xa9d9,
+ 0xa9f0, 0xa9f9,
+ 0xaa50, 0xaa59,
+ 0xabf0, 0xabf9,
+ 0xff10, 0xff19,
+ 0x104a0, 0x104a9,
+ 0x10d30, 0x10d39,
+ 0x10d40, 0x10d49,
+ 0x11066, 0x1106f,
+ 0x110f0, 0x110f9,
+ 0x11136, 0x1113f,
+ 0x111d0, 0x111d9,
+ 0x112f0, 0x112f9,
+ 0x11450, 0x11459,
+ 0x114d0, 0x114d9,
+ 0x11650, 0x11659,
+ 0x116c0, 0x116c9,
+ 0x116d0, 0x116e3,
+ 0x11730, 0x11739,
+ 0x118e0, 0x118e9,
+ 0x11950, 0x11959,
+ 0x11bf0, 0x11bf9,
+ 0x11c50, 0x11c59,
+ 0x11d50, 0x11d59,
+ 0x11da0, 0x11da9,
+ 0x11de0, 0x11de9,
+ 0x11f50, 0x11f59,
+ 0x16130, 0x16139,
+ 0x16a60, 0x16a69,
+ 0x16ac0, 0x16ac9,
+ 0x16b50, 0x16b59,
+ 0x16d70, 0x16d79,
+ 0x1ccf0, 0x1ccf9,
+ 0x1d7ce, 0x1d7ff,
+ 0x1e140, 0x1e149,
+ 0x1e2f0, 0x1e2f9,
+ 0x1e4f0, 0x1e4f9,
+ 0x1e5f1, 0x1e5fa,
+ 0x1e950, 0x1e959,
+ 0x1fbf0, 0x1fbf9,
+}; /* CR_Digit */
+
+/* 'Graph': [[:Graph:]] */
+static const OnigCodePoint CR_Graph[] = {
+ 741,
+ 0x0021, 0x007e,
+ 0x00a1, 0x0377,
+ 0x037a, 0x037f,
+ 0x0384, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x052f,
+ 0x0531, 0x0556,
+ 0x0559, 0x058a,
+ 0x058d, 0x058f,
+ 0x0591, 0x05c7,
+ 0x05d0, 0x05ea,
+ 0x05ef, 0x05f4,
+ 0x0600, 0x070d,
+ 0x070f, 0x074a,
+ 0x074d, 0x07b1,
+ 0x07c0, 0x07fa,
+ 0x07fd, 0x082d,
+ 0x0830, 0x083e,
+ 0x0840, 0x085b,
+ 0x085e, 0x085e,
+ 0x0860, 0x086a,
+ 0x0870, 0x0891,
+ 0x0897, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fe,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 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,
+ 0x0be6, 0x0bfa,
+ 0x0c00, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3c, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c5a,
+ 0x0c5c, 0x0c5d,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c77, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cdc, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf3,
+ 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, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 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, 0x0ece,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 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, 0x167f,
+ 0x1681, 0x169c,
+ 0x16a0, 0x16f8,
+ 0x1700, 0x1715,
+ 0x171f, 0x1736,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x1800, 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, 0x1add,
+ 0x1ae0, 0x1aeb,
+ 0x1b00, 0x1b4c,
+ 0x1b4e, 0x1bf3,
+ 0x1bfc, 0x1c37,
+ 0x1c3b, 0x1c49,
+ 0x1c4d, 0x1c8a,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cc7,
+ 0x1cd0, 0x1cfa,
+ 0x1d00, 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,
+ 0x200b, 0x2027,
+ 0x202a, 0x202e,
+ 0x2030, 0x205e,
+ 0x2060, 0x2064,
+ 0x2066, 0x2071,
+ 0x2074, 0x208e,
+ 0x2090, 0x209c,
+ 0x20a0, 0x20c1,
+ 0x20d0, 0x20f0,
+ 0x2100, 0x218b,
+ 0x2190, 0x2429,
+ 0x2440, 0x244a,
+ 0x2460, 0x2b73,
+ 0x2b76, 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, 0x2e5d,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2fff,
+ 0x3001, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312f,
+ 0x3131, 0x318e,
+ 0x3190, 0x31e5,
+ 0x31ef, 0x321e,
+ 0x3220, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa4d0, 0xa62b,
+ 0xa640, 0xa6f7,
+ 0xa700, 0xa7dc,
+ 0xa7f1, 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,
+ 0xe000, 0xfa6d,
+ 0xfa70, 0xfad9,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xfb1d, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfdcf,
+ 0xfdf0, 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, 0xfffd,
+ 0x10000, 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, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x105c0, 0x105f3,
+ 0x10600, 0x10736,
+ 0x10740, 0x10755,
+ 0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 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, 0x10959,
+ 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,
+ 0x10d40, 0x10d65,
+ 0x10d69, 0x10d85,
+ 0x10d8e, 0x10d8f,
+ 0x10e60, 0x10e7e,
+ 0x10e80, 0x10ea9,
+ 0x10eab, 0x10ead,
+ 0x10eb0, 0x10eb1,
+ 0x10ec2, 0x10ec7,
+ 0x10ed0, 0x10ed8,
+ 0x10efa, 0x10f27,
+ 0x10f30, 0x10f59,
+ 0x10f70, 0x10f89,
+ 0x10fb0, 0x10fcb,
+ 0x10fe0, 0x10ff6,
+ 0x11000, 0x1104d,
+ 0x11052, 0x11075,
+ 0x1107f, 0x110c2,
+ 0x110cd, 0x110cd,
+ 0x110d0, 0x110e8,
+ 0x110f0, 0x110f9,
+ 0x11100, 0x11134,
+ 0x11136, 0x11147,
+ 0x11150, 0x11176,
+ 0x11180, 0x111df,
+ 0x111e1, 0x111f4,
+ 0x11200, 0x11211,
+ 0x11213, 0x11241,
+ 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,
+ 0x11380, 0x11389,
+ 0x1138b, 0x1138b,
+ 0x1138e, 0x1138e,
+ 0x11390, 0x113b5,
+ 0x113b7, 0x113c0,
+ 0x113c2, 0x113c2,
+ 0x113c5, 0x113c5,
+ 0x113c7, 0x113ca,
+ 0x113cc, 0x113d5,
+ 0x113d7, 0x113d8,
+ 0x113e1, 0x113e2,
+ 0x11400, 0x1145b,
+ 0x1145d, 0x11461,
+ 0x11480, 0x114c7,
+ 0x114d0, 0x114d9,
+ 0x11580, 0x115b5,
+ 0x115b8, 0x115dd,
+ 0x11600, 0x11644,
+ 0x11650, 0x11659,
+ 0x11660, 0x1166c,
+ 0x11680, 0x116b9,
+ 0x116c0, 0x116c9,
+ 0x116d0, 0x116e3,
+ 0x11700, 0x1171a,
+ 0x1171d, 0x1172b,
+ 0x11730, 0x11746,
+ 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,
+ 0x11ab0, 0x11af8,
+ 0x11b00, 0x11b09,
+ 0x11b60, 0x11b67,
+ 0x11bc0, 0x11be1,
+ 0x11bf0, 0x11bf9,
+ 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,
+ 0x11db0, 0x11ddb,
+ 0x11de0, 0x11de9,
+ 0x11ee0, 0x11ef8,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f5a,
+ 0x11fb0, 0x11fb0,
+ 0x11fc0, 0x11ff1,
+ 0x11fff, 0x12399,
+ 0x12400, 0x1246e,
+ 0x12470, 0x12474,
+ 0x12480, 0x12543,
+ 0x12f90, 0x12ff2,
+ 0x13000, 0x13455,
+ 0x13460, 0x143fa,
+ 0x14400, 0x14646,
+ 0x16100, 0x16139,
+ 0x16800, 0x16a38,
+ 0x16a40, 0x16a5e,
+ 0x16a60, 0x16a69,
+ 0x16a6e, 0x16abe,
+ 0x16ac0, 0x16ac9,
+ 0x16ad0, 0x16aed,
+ 0x16af0, 0x16af5,
+ 0x16b00, 0x16b45,
+ 0x16b50, 0x16b59,
+ 0x16b5b, 0x16b61,
+ 0x16b63, 0x16b77,
+ 0x16b7d, 0x16b8f,
+ 0x16d40, 0x16d79,
+ 0x16e40, 0x16e9a,
+ 0x16ea0, 0x16eb8,
+ 0x16ebb, 0x16ed3,
+ 0x16f00, 0x16f4a,
+ 0x16f4f, 0x16f87,
+ 0x16f8f, 0x16f9f,
+ 0x16fe0, 0x16fe4,
+ 0x16ff0, 0x16ff6,
+ 0x17000, 0x18cd5,
+ 0x18cff, 0x18d1e,
+ 0x18d80, 0x18df2,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
+ 0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
+ 0x1b164, 0x1b167,
+ 0x1b170, 0x1b2fb,
+ 0x1bc00, 0x1bc6a,
+ 0x1bc70, 0x1bc7c,
+ 0x1bc80, 0x1bc88,
+ 0x1bc90, 0x1bc99,
+ 0x1bc9c, 0x1bca3,
+ 0x1cc00, 0x1ccfc,
+ 0x1cd00, 0x1ceb3,
+ 0x1ceba, 0x1ced0,
+ 0x1cee0, 0x1cef0,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
+ 0x1cf50, 0x1cfc3,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d129, 0x1d1ea,
+ 0x1d200, 0x1d245,
+ 0x1d2c0, 0x1d2d3,
+ 0x1d2e0, 0x1d2f3,
+ 0x1d300, 0x1d356,
+ 0x1d360, 0x1d378,
+ 0x1d400, 0x1d454,
+ 0x1d456, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 0x1d4a2, 0x1d4a2,
+ 0x1d4a5, 0x1d4a6,
+ 0x1d4a9, 0x1d4ac,
+ 0x1d4ae, 0x1d4b9,
+ 0x1d4bb, 0x1d4bb,
+ 0x1d4bd, 0x1d4c3,
+ 0x1d4c5, 0x1d505,
+ 0x1d507, 0x1d50a,
+ 0x1d50d, 0x1d514,
+ 0x1d516, 0x1d51c,
+ 0x1d51e, 0x1d539,
+ 0x1d53b, 0x1d53e,
+ 0x1d540, 0x1d544,
+ 0x1d546, 0x1d546,
+ 0x1d54a, 0x1d550,
+ 0x1d552, 0x1d6a5,
+ 0x1d6a8, 0x1d7cb,
+ 0x1d7ce, 0x1da8b,
+ 0x1da9b, 0x1da9f,
+ 0x1daa1, 0x1daaf,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e000, 0x1e006,
+ 0x1e008, 0x1e018,
+ 0x1e01b, 0x1e021,
+ 0x1e023, 0x1e024,
+ 0x1e026, 0x1e02a,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
+ 0x1e100, 0x1e12c,
+ 0x1e130, 0x1e13d,
+ 0x1e140, 0x1e149,
+ 0x1e14e, 0x1e14f,
+ 0x1e290, 0x1e2ae,
+ 0x1e2c0, 0x1e2f9,
+ 0x1e2ff, 0x1e2ff,
+ 0x1e4d0, 0x1e4f9,
+ 0x1e5d0, 0x1e5fa,
+ 0x1e5ff, 0x1e5ff,
+ 0x1e6c0, 0x1e6de,
+ 0x1e6e0, 0x1e6f5,
+ 0x1e6fe, 0x1e6ff,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
+ 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, 0x1f6d8,
+ 0x1f6dc, 0x1f6ec,
+ 0x1f6f0, 0x1f6fc,
+ 0x1f700, 0x1f7d9,
+ 0x1f7e0, 0x1f7eb,
+ 0x1f7f0, 0x1f7f0,
+ 0x1f800, 0x1f80b,
+ 0x1f810, 0x1f847,
+ 0x1f850, 0x1f859,
+ 0x1f860, 0x1f887,
+ 0x1f890, 0x1f8ad,
+ 0x1f8b0, 0x1f8bb,
+ 0x1f8c0, 0x1f8c1,
+ 0x1f8d0, 0x1f8d8,
+ 0x1f900, 0x1fa57,
+ 0x1fa60, 0x1fa6d,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa8a,
+ 0x1fa8e, 0x1fac6,
+ 0x1fac8, 0x1fac8,
+ 0x1facd, 0x1fadc,
+ 0x1fadf, 0x1faea,
+ 0x1faef, 0x1faf8,
+ 0x1fb00, 0x1fb92,
+ 0x1fb94, 0x1fbfa,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b81d,
+ 0x2b820, 0x2cead,
+ 0x2ceb0, 0x2ebe0,
+ 0x2ebf0, 0x2ee5d,
+ 0x2f800, 0x2fa1d,
+ 0x30000, 0x3134a,
+ 0x31350, 0x33479,
+ 0xe0001, 0xe0001,
+ 0xe0020, 0xe007f,
+ 0xe0100, 0xe01ef,
+ 0xf0000, 0xffffd,
+ 0x100000, 0x10fffd,
+}; /* CR_Graph */
+
+/* 'Lower': [[:Lower:]] */
+static const OnigCodePoint CR_Lower[] = {
+ 677,
+ 0x0061, 0x007a,
+ 0x00aa, 0x00aa,
+ 0x00b5, 0x00b5,
+ 0x00ba, 0x00ba,
+ 0x00df, 0x00f6,
+ 0x00f8, 0x00ff,
+ 0x0101, 0x0101,
+ 0x0103, 0x0103,
+ 0x0105, 0x0105,
+ 0x0107, 0x0107,
+ 0x0109, 0x0109,
+ 0x010b, 0x010b,
+ 0x010d, 0x010d,
+ 0x010f, 0x010f,
+ 0x0111, 0x0111,
+ 0x0113, 0x0113,
+ 0x0115, 0x0115,
+ 0x0117, 0x0117,
+ 0x0119, 0x0119,
+ 0x011b, 0x011b,
+ 0x011d, 0x011d,
+ 0x011f, 0x011f,
+ 0x0121, 0x0121,
+ 0x0123, 0x0123,
+ 0x0125, 0x0125,
+ 0x0127, 0x0127,
+ 0x0129, 0x0129,
+ 0x012b, 0x012b,
+ 0x012d, 0x012d,
+ 0x012f, 0x012f,
+ 0x0131, 0x0131,
+ 0x0133, 0x0133,
+ 0x0135, 0x0135,
+ 0x0137, 0x0138,
+ 0x013a, 0x013a,
+ 0x013c, 0x013c,
+ 0x013e, 0x013e,
+ 0x0140, 0x0140,
+ 0x0142, 0x0142,
+ 0x0144, 0x0144,
+ 0x0146, 0x0146,
+ 0x0148, 0x0149,
+ 0x014b, 0x014b,
+ 0x014d, 0x014d,
+ 0x014f, 0x014f,
+ 0x0151, 0x0151,
+ 0x0153, 0x0153,
+ 0x0155, 0x0155,
+ 0x0157, 0x0157,
+ 0x0159, 0x0159,
+ 0x015b, 0x015b,
+ 0x015d, 0x015d,
+ 0x015f, 0x015f,
+ 0x0161, 0x0161,
+ 0x0163, 0x0163,
+ 0x0165, 0x0165,
+ 0x0167, 0x0167,
+ 0x0169, 0x0169,
+ 0x016b, 0x016b,
+ 0x016d, 0x016d,
+ 0x016f, 0x016f,
+ 0x0171, 0x0171,
+ 0x0173, 0x0173,
+ 0x0175, 0x0175,
+ 0x0177, 0x0177,
+ 0x017a, 0x017a,
+ 0x017c, 0x017c,
+ 0x017e, 0x0180,
+ 0x0183, 0x0183,
+ 0x0185, 0x0185,
+ 0x0188, 0x0188,
+ 0x018c, 0x018d,
+ 0x0192, 0x0192,
+ 0x0195, 0x0195,
+ 0x0199, 0x019b,
+ 0x019e, 0x019e,
+ 0x01a1, 0x01a1,
+ 0x01a3, 0x01a3,
+ 0x01a5, 0x01a5,
+ 0x01a8, 0x01a8,
+ 0x01aa, 0x01ab,
+ 0x01ad, 0x01ad,
+ 0x01b0, 0x01b0,
+ 0x01b4, 0x01b4,
+ 0x01b6, 0x01b6,
+ 0x01b9, 0x01ba,
+ 0x01bd, 0x01bf,
+ 0x01c6, 0x01c6,
+ 0x01c9, 0x01c9,
+ 0x01cc, 0x01cc,
+ 0x01ce, 0x01ce,
+ 0x01d0, 0x01d0,
+ 0x01d2, 0x01d2,
+ 0x01d4, 0x01d4,
+ 0x01d6, 0x01d6,
+ 0x01d8, 0x01d8,
+ 0x01da, 0x01da,
+ 0x01dc, 0x01dd,
+ 0x01df, 0x01df,
+ 0x01e1, 0x01e1,
+ 0x01e3, 0x01e3,
+ 0x01e5, 0x01e5,
+ 0x01e7, 0x01e7,
+ 0x01e9, 0x01e9,
+ 0x01eb, 0x01eb,
+ 0x01ed, 0x01ed,
+ 0x01ef, 0x01f0,
+ 0x01f3, 0x01f3,
+ 0x01f5, 0x01f5,
+ 0x01f9, 0x01f9,
+ 0x01fb, 0x01fb,
+ 0x01fd, 0x01fd,
+ 0x01ff, 0x01ff,
+ 0x0201, 0x0201,
+ 0x0203, 0x0203,
+ 0x0205, 0x0205,
+ 0x0207, 0x0207,
+ 0x0209, 0x0209,
+ 0x020b, 0x020b,
+ 0x020d, 0x020d,
+ 0x020f, 0x020f,
+ 0x0211, 0x0211,
+ 0x0213, 0x0213,
+ 0x0215, 0x0215,
+ 0x0217, 0x0217,
+ 0x0219, 0x0219,
+ 0x021b, 0x021b,
+ 0x021d, 0x021d,
+ 0x021f, 0x021f,
+ 0x0221, 0x0221,
+ 0x0223, 0x0223,
+ 0x0225, 0x0225,
+ 0x0227, 0x0227,
+ 0x0229, 0x0229,
+ 0x022b, 0x022b,
+ 0x022d, 0x022d,
+ 0x022f, 0x022f,
+ 0x0231, 0x0231,
+ 0x0233, 0x0239,
+ 0x023c, 0x023c,
+ 0x023f, 0x0240,
+ 0x0242, 0x0242,
+ 0x0247, 0x0247,
+ 0x0249, 0x0249,
+ 0x024b, 0x024b,
+ 0x024d, 0x024d,
+ 0x024f, 0x0293,
+ 0x0296, 0x02b8,
+ 0x02c0, 0x02c1,
+ 0x02e0, 0x02e4,
+ 0x0345, 0x0345,
+ 0x0371, 0x0371,
+ 0x0373, 0x0373,
+ 0x0377, 0x0377,
+ 0x037a, 0x037d,
+ 0x0390, 0x0390,
+ 0x03ac, 0x03ce,
+ 0x03d0, 0x03d1,
+ 0x03d5, 0x03d7,
+ 0x03d9, 0x03d9,
+ 0x03db, 0x03db,
+ 0x03dd, 0x03dd,
+ 0x03df, 0x03df,
+ 0x03e1, 0x03e1,
+ 0x03e3, 0x03e3,
+ 0x03e5, 0x03e5,
+ 0x03e7, 0x03e7,
+ 0x03e9, 0x03e9,
+ 0x03eb, 0x03eb,
+ 0x03ed, 0x03ed,
+ 0x03ef, 0x03f3,
+ 0x03f5, 0x03f5,
+ 0x03f8, 0x03f8,
+ 0x03fb, 0x03fc,
+ 0x0430, 0x045f,
+ 0x0461, 0x0461,
+ 0x0463, 0x0463,
+ 0x0465, 0x0465,
+ 0x0467, 0x0467,
+ 0x0469, 0x0469,
+ 0x046b, 0x046b,
+ 0x046d, 0x046d,
+ 0x046f, 0x046f,
+ 0x0471, 0x0471,
+ 0x0473, 0x0473,
+ 0x0475, 0x0475,
+ 0x0477, 0x0477,
+ 0x0479, 0x0479,
+ 0x047b, 0x047b,
+ 0x047d, 0x047d,
+ 0x047f, 0x047f,
+ 0x0481, 0x0481,
+ 0x048b, 0x048b,
+ 0x048d, 0x048d,
+ 0x048f, 0x048f,
+ 0x0491, 0x0491,
+ 0x0493, 0x0493,
+ 0x0495, 0x0495,
+ 0x0497, 0x0497,
+ 0x0499, 0x0499,
+ 0x049b, 0x049b,
+ 0x049d, 0x049d,
+ 0x049f, 0x049f,
+ 0x04a1, 0x04a1,
+ 0x04a3, 0x04a3,
+ 0x04a5, 0x04a5,
+ 0x04a7, 0x04a7,
+ 0x04a9, 0x04a9,
+ 0x04ab, 0x04ab,
+ 0x04ad, 0x04ad,
+ 0x04af, 0x04af,
+ 0x04b1, 0x04b1,
+ 0x04b3, 0x04b3,
+ 0x04b5, 0x04b5,
+ 0x04b7, 0x04b7,
+ 0x04b9, 0x04b9,
+ 0x04bb, 0x04bb,
+ 0x04bd, 0x04bd,
+ 0x04bf, 0x04bf,
+ 0x04c2, 0x04c2,
+ 0x04c4, 0x04c4,
+ 0x04c6, 0x04c6,
+ 0x04c8, 0x04c8,
+ 0x04ca, 0x04ca,
+ 0x04cc, 0x04cc,
+ 0x04ce, 0x04cf,
+ 0x04d1, 0x04d1,
+ 0x04d3, 0x04d3,
+ 0x04d5, 0x04d5,
+ 0x04d7, 0x04d7,
+ 0x04d9, 0x04d9,
+ 0x04db, 0x04db,
+ 0x04dd, 0x04dd,
+ 0x04df, 0x04df,
+ 0x04e1, 0x04e1,
+ 0x04e3, 0x04e3,
+ 0x04e5, 0x04e5,
+ 0x04e7, 0x04e7,
+ 0x04e9, 0x04e9,
+ 0x04eb, 0x04eb,
+ 0x04ed, 0x04ed,
+ 0x04ef, 0x04ef,
+ 0x04f1, 0x04f1,
+ 0x04f3, 0x04f3,
+ 0x04f5, 0x04f5,
+ 0x04f7, 0x04f7,
+ 0x04f9, 0x04f9,
+ 0x04fb, 0x04fb,
+ 0x04fd, 0x04fd,
+ 0x04ff, 0x04ff,
+ 0x0501, 0x0501,
+ 0x0503, 0x0503,
+ 0x0505, 0x0505,
+ 0x0507, 0x0507,
+ 0x0509, 0x0509,
+ 0x050b, 0x050b,
+ 0x050d, 0x050d,
+ 0x050f, 0x050f,
+ 0x0511, 0x0511,
+ 0x0513, 0x0513,
+ 0x0515, 0x0515,
+ 0x0517, 0x0517,
+ 0x0519, 0x0519,
+ 0x051b, 0x051b,
+ 0x051d, 0x051d,
+ 0x051f, 0x051f,
+ 0x0521, 0x0521,
+ 0x0523, 0x0523,
+ 0x0525, 0x0525,
+ 0x0527, 0x0527,
+ 0x0529, 0x0529,
+ 0x052b, 0x052b,
+ 0x052d, 0x052d,
+ 0x052f, 0x052f,
+ 0x0560, 0x0588,
+ 0x10d0, 0x10fa,
+ 0x10fc, 0x10ff,
+ 0x13f8, 0x13fd,
+ 0x1c80, 0x1c88,
+ 0x1c8a, 0x1c8a,
+ 0x1d00, 0x1dbf,
+ 0x1e01, 0x1e01,
+ 0x1e03, 0x1e03,
+ 0x1e05, 0x1e05,
+ 0x1e07, 0x1e07,
+ 0x1e09, 0x1e09,
+ 0x1e0b, 0x1e0b,
+ 0x1e0d, 0x1e0d,
+ 0x1e0f, 0x1e0f,
+ 0x1e11, 0x1e11,
+ 0x1e13, 0x1e13,
+ 0x1e15, 0x1e15,
+ 0x1e17, 0x1e17,
+ 0x1e19, 0x1e19,
+ 0x1e1b, 0x1e1b,
+ 0x1e1d, 0x1e1d,
+ 0x1e1f, 0x1e1f,
+ 0x1e21, 0x1e21,
+ 0x1e23, 0x1e23,
+ 0x1e25, 0x1e25,
+ 0x1e27, 0x1e27,
+ 0x1e29, 0x1e29,
+ 0x1e2b, 0x1e2b,
+ 0x1e2d, 0x1e2d,
+ 0x1e2f, 0x1e2f,
+ 0x1e31, 0x1e31,
+ 0x1e33, 0x1e33,
+ 0x1e35, 0x1e35,
+ 0x1e37, 0x1e37,
+ 0x1e39, 0x1e39,
+ 0x1e3b, 0x1e3b,
+ 0x1e3d, 0x1e3d,
+ 0x1e3f, 0x1e3f,
+ 0x1e41, 0x1e41,
+ 0x1e43, 0x1e43,
+ 0x1e45, 0x1e45,
+ 0x1e47, 0x1e47,
+ 0x1e49, 0x1e49,
+ 0x1e4b, 0x1e4b,
+ 0x1e4d, 0x1e4d,
+ 0x1e4f, 0x1e4f,
+ 0x1e51, 0x1e51,
+ 0x1e53, 0x1e53,
+ 0x1e55, 0x1e55,
+ 0x1e57, 0x1e57,
+ 0x1e59, 0x1e59,
+ 0x1e5b, 0x1e5b,
+ 0x1e5d, 0x1e5d,
+ 0x1e5f, 0x1e5f,
+ 0x1e61, 0x1e61,
+ 0x1e63, 0x1e63,
+ 0x1e65, 0x1e65,
+ 0x1e67, 0x1e67,
+ 0x1e69, 0x1e69,
+ 0x1e6b, 0x1e6b,
+ 0x1e6d, 0x1e6d,
+ 0x1e6f, 0x1e6f,
+ 0x1e71, 0x1e71,
+ 0x1e73, 0x1e73,
+ 0x1e75, 0x1e75,
+ 0x1e77, 0x1e77,
+ 0x1e79, 0x1e79,
+ 0x1e7b, 0x1e7b,
+ 0x1e7d, 0x1e7d,
+ 0x1e7f, 0x1e7f,
+ 0x1e81, 0x1e81,
+ 0x1e83, 0x1e83,
+ 0x1e85, 0x1e85,
+ 0x1e87, 0x1e87,
+ 0x1e89, 0x1e89,
+ 0x1e8b, 0x1e8b,
+ 0x1e8d, 0x1e8d,
+ 0x1e8f, 0x1e8f,
+ 0x1e91, 0x1e91,
+ 0x1e93, 0x1e93,
+ 0x1e95, 0x1e9d,
+ 0x1e9f, 0x1e9f,
+ 0x1ea1, 0x1ea1,
+ 0x1ea3, 0x1ea3,
+ 0x1ea5, 0x1ea5,
+ 0x1ea7, 0x1ea7,
+ 0x1ea9, 0x1ea9,
+ 0x1eab, 0x1eab,
+ 0x1ead, 0x1ead,
+ 0x1eaf, 0x1eaf,
+ 0x1eb1, 0x1eb1,
+ 0x1eb3, 0x1eb3,
+ 0x1eb5, 0x1eb5,
+ 0x1eb7, 0x1eb7,
+ 0x1eb9, 0x1eb9,
+ 0x1ebb, 0x1ebb,
+ 0x1ebd, 0x1ebd,
+ 0x1ebf, 0x1ebf,
+ 0x1ec1, 0x1ec1,
+ 0x1ec3, 0x1ec3,
+ 0x1ec5, 0x1ec5,
+ 0x1ec7, 0x1ec7,
+ 0x1ec9, 0x1ec9,
+ 0x1ecb, 0x1ecb,
+ 0x1ecd, 0x1ecd,
+ 0x1ecf, 0x1ecf,
+ 0x1ed1, 0x1ed1,
+ 0x1ed3, 0x1ed3,
+ 0x1ed5, 0x1ed5,
+ 0x1ed7, 0x1ed7,
+ 0x1ed9, 0x1ed9,
+ 0x1edb, 0x1edb,
+ 0x1edd, 0x1edd,
+ 0x1edf, 0x1edf,
+ 0x1ee1, 0x1ee1,
+ 0x1ee3, 0x1ee3,
+ 0x1ee5, 0x1ee5,
+ 0x1ee7, 0x1ee7,
+ 0x1ee9, 0x1ee9,
+ 0x1eeb, 0x1eeb,
+ 0x1eed, 0x1eed,
+ 0x1eef, 0x1eef,
+ 0x1ef1, 0x1ef1,
+ 0x1ef3, 0x1ef3,
+ 0x1ef5, 0x1ef5,
+ 0x1ef7, 0x1ef7,
+ 0x1ef9, 0x1ef9,
+ 0x1efb, 0x1efb,
+ 0x1efd, 0x1efd,
+ 0x1eff, 0x1f07,
+ 0x1f10, 0x1f15,
+ 0x1f20, 0x1f27,
+ 0x1f30, 0x1f37,
+ 0x1f40, 0x1f45,
+ 0x1f50, 0x1f57,
+ 0x1f60, 0x1f67,
+ 0x1f70, 0x1f7d,
+ 0x1f80, 0x1f87,
+ 0x1f90, 0x1f97,
+ 0x1fa0, 0x1fa7,
+ 0x1fb0, 0x1fb4,
+ 0x1fb6, 0x1fb7,
+ 0x1fbe, 0x1fbe,
+ 0x1fc2, 0x1fc4,
+ 0x1fc6, 0x1fc7,
+ 0x1fd0, 0x1fd3,
+ 0x1fd6, 0x1fd7,
+ 0x1fe0, 0x1fe7,
+ 0x1ff2, 0x1ff4,
+ 0x1ff6, 0x1ff7,
+ 0x2071, 0x2071,
+ 0x207f, 0x207f,
+ 0x2090, 0x209c,
+ 0x210a, 0x210a,
+ 0x210e, 0x210f,
+ 0x2113, 0x2113,
+ 0x212f, 0x212f,
+ 0x2134, 0x2134,
+ 0x2139, 0x2139,
+ 0x213c, 0x213d,
+ 0x2146, 0x2149,
+ 0x214e, 0x214e,
+ 0x2170, 0x217f,
+ 0x2184, 0x2184,
+ 0x24d0, 0x24e9,
+ 0x2c30, 0x2c5f,
+ 0x2c61, 0x2c61,
+ 0x2c65, 0x2c66,
+ 0x2c68, 0x2c68,
+ 0x2c6a, 0x2c6a,
+ 0x2c6c, 0x2c6c,
+ 0x2c71, 0x2c71,
+ 0x2c73, 0x2c74,
+ 0x2c76, 0x2c7d,
+ 0x2c81, 0x2c81,
+ 0x2c83, 0x2c83,
+ 0x2c85, 0x2c85,
+ 0x2c87, 0x2c87,
+ 0x2c89, 0x2c89,
+ 0x2c8b, 0x2c8b,
+ 0x2c8d, 0x2c8d,
+ 0x2c8f, 0x2c8f,
+ 0x2c91, 0x2c91,
+ 0x2c93, 0x2c93,
+ 0x2c95, 0x2c95,
+ 0x2c97, 0x2c97,
+ 0x2c99, 0x2c99,
+ 0x2c9b, 0x2c9b,
+ 0x2c9d, 0x2c9d,
+ 0x2c9f, 0x2c9f,
+ 0x2ca1, 0x2ca1,
+ 0x2ca3, 0x2ca3,
+ 0x2ca5, 0x2ca5,
+ 0x2ca7, 0x2ca7,
+ 0x2ca9, 0x2ca9,
+ 0x2cab, 0x2cab,
+ 0x2cad, 0x2cad,
+ 0x2caf, 0x2caf,
+ 0x2cb1, 0x2cb1,
+ 0x2cb3, 0x2cb3,
+ 0x2cb5, 0x2cb5,
+ 0x2cb7, 0x2cb7,
+ 0x2cb9, 0x2cb9,
+ 0x2cbb, 0x2cbb,
+ 0x2cbd, 0x2cbd,
+ 0x2cbf, 0x2cbf,
+ 0x2cc1, 0x2cc1,
+ 0x2cc3, 0x2cc3,
+ 0x2cc5, 0x2cc5,
+ 0x2cc7, 0x2cc7,
+ 0x2cc9, 0x2cc9,
+ 0x2ccb, 0x2ccb,
+ 0x2ccd, 0x2ccd,
+ 0x2ccf, 0x2ccf,
+ 0x2cd1, 0x2cd1,
+ 0x2cd3, 0x2cd3,
+ 0x2cd5, 0x2cd5,
+ 0x2cd7, 0x2cd7,
+ 0x2cd9, 0x2cd9,
+ 0x2cdb, 0x2cdb,
+ 0x2cdd, 0x2cdd,
+ 0x2cdf, 0x2cdf,
+ 0x2ce1, 0x2ce1,
+ 0x2ce3, 0x2ce4,
+ 0x2cec, 0x2cec,
+ 0x2cee, 0x2cee,
+ 0x2cf3, 0x2cf3,
+ 0x2d00, 0x2d25,
+ 0x2d27, 0x2d27,
+ 0x2d2d, 0x2d2d,
+ 0xa641, 0xa641,
+ 0xa643, 0xa643,
+ 0xa645, 0xa645,
+ 0xa647, 0xa647,
+ 0xa649, 0xa649,
+ 0xa64b, 0xa64b,
+ 0xa64d, 0xa64d,
+ 0xa64f, 0xa64f,
+ 0xa651, 0xa651,
+ 0xa653, 0xa653,
+ 0xa655, 0xa655,
+ 0xa657, 0xa657,
+ 0xa659, 0xa659,
+ 0xa65b, 0xa65b,
+ 0xa65d, 0xa65d,
+ 0xa65f, 0xa65f,
+ 0xa661, 0xa661,
+ 0xa663, 0xa663,
+ 0xa665, 0xa665,
+ 0xa667, 0xa667,
+ 0xa669, 0xa669,
+ 0xa66b, 0xa66b,
+ 0xa66d, 0xa66d,
+ 0xa681, 0xa681,
+ 0xa683, 0xa683,
+ 0xa685, 0xa685,
+ 0xa687, 0xa687,
+ 0xa689, 0xa689,
+ 0xa68b, 0xa68b,
+ 0xa68d, 0xa68d,
+ 0xa68f, 0xa68f,
+ 0xa691, 0xa691,
+ 0xa693, 0xa693,
+ 0xa695, 0xa695,
+ 0xa697, 0xa697,
+ 0xa699, 0xa699,
+ 0xa69b, 0xa69d,
+ 0xa723, 0xa723,
+ 0xa725, 0xa725,
+ 0xa727, 0xa727,
+ 0xa729, 0xa729,
+ 0xa72b, 0xa72b,
+ 0xa72d, 0xa72d,
+ 0xa72f, 0xa731,
+ 0xa733, 0xa733,
+ 0xa735, 0xa735,
+ 0xa737, 0xa737,
+ 0xa739, 0xa739,
+ 0xa73b, 0xa73b,
+ 0xa73d, 0xa73d,
+ 0xa73f, 0xa73f,
+ 0xa741, 0xa741,
+ 0xa743, 0xa743,
+ 0xa745, 0xa745,
+ 0xa747, 0xa747,
+ 0xa749, 0xa749,
+ 0xa74b, 0xa74b,
+ 0xa74d, 0xa74d,
+ 0xa74f, 0xa74f,
+ 0xa751, 0xa751,
+ 0xa753, 0xa753,
+ 0xa755, 0xa755,
+ 0xa757, 0xa757,
+ 0xa759, 0xa759,
+ 0xa75b, 0xa75b,
+ 0xa75d, 0xa75d,
+ 0xa75f, 0xa75f,
+ 0xa761, 0xa761,
+ 0xa763, 0xa763,
+ 0xa765, 0xa765,
+ 0xa767, 0xa767,
+ 0xa769, 0xa769,
+ 0xa76b, 0xa76b,
+ 0xa76d, 0xa76d,
+ 0xa76f, 0xa778,
+ 0xa77a, 0xa77a,
+ 0xa77c, 0xa77c,
+ 0xa77f, 0xa77f,
+ 0xa781, 0xa781,
+ 0xa783, 0xa783,
+ 0xa785, 0xa785,
+ 0xa787, 0xa787,
+ 0xa78c, 0xa78c,
+ 0xa78e, 0xa78e,
+ 0xa791, 0xa791,
+ 0xa793, 0xa795,
+ 0xa797, 0xa797,
+ 0xa799, 0xa799,
+ 0xa79b, 0xa79b,
+ 0xa79d, 0xa79d,
+ 0xa79f, 0xa79f,
+ 0xa7a1, 0xa7a1,
+ 0xa7a3, 0xa7a3,
+ 0xa7a5, 0xa7a5,
+ 0xa7a7, 0xa7a7,
+ 0xa7a9, 0xa7a9,
+ 0xa7af, 0xa7af,
+ 0xa7b5, 0xa7b5,
+ 0xa7b7, 0xa7b7,
+ 0xa7b9, 0xa7b9,
+ 0xa7bb, 0xa7bb,
+ 0xa7bd, 0xa7bd,
+ 0xa7bf, 0xa7bf,
+ 0xa7c1, 0xa7c1,
+ 0xa7c3, 0xa7c3,
+ 0xa7c8, 0xa7c8,
+ 0xa7ca, 0xa7ca,
+ 0xa7cd, 0xa7cd,
+ 0xa7cf, 0xa7cf,
+ 0xa7d1, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d5,
+ 0xa7d7, 0xa7d7,
+ 0xa7d9, 0xa7d9,
+ 0xa7db, 0xa7db,
+ 0xa7f1, 0xa7f4,
+ 0xa7f6, 0xa7f6,
+ 0xa7f8, 0xa7fa,
+ 0xab30, 0xab5a,
+ 0xab5c, 0xab69,
+ 0xab70, 0xabbf,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xff41, 0xff5a,
+ 0x10428, 0x1044f,
+ 0x104d8, 0x104fb,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x10780, 0x10780,
+ 0x10783, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 0x10cc0, 0x10cf2,
+ 0x10d70, 0x10d85,
+ 0x118c0, 0x118df,
+ 0x16e60, 0x16e7f,
+ 0x16ebb, 0x16ed3,
+ 0x1d41a, 0x1d433,
+ 0x1d44e, 0x1d454,
+ 0x1d456, 0x1d467,
+ 0x1d482, 0x1d49b,
+ 0x1d4b6, 0x1d4b9,
+ 0x1d4bb, 0x1d4bb,
+ 0x1d4bd, 0x1d4c3,
+ 0x1d4c5, 0x1d4cf,
+ 0x1d4ea, 0x1d503,
+ 0x1d51e, 0x1d537,
+ 0x1d552, 0x1d56b,
+ 0x1d586, 0x1d59f,
+ 0x1d5ba, 0x1d5d3,
+ 0x1d5ee, 0x1d607,
+ 0x1d622, 0x1d63b,
+ 0x1d656, 0x1d66f,
+ 0x1d68a, 0x1d6a5,
+ 0x1d6c2, 0x1d6da,
+ 0x1d6dc, 0x1d6e1,
+ 0x1d6fc, 0x1d714,
+ 0x1d716, 0x1d71b,
+ 0x1d736, 0x1d74e,
+ 0x1d750, 0x1d755,
+ 0x1d770, 0x1d788,
+ 0x1d78a, 0x1d78f,
+ 0x1d7aa, 0x1d7c2,
+ 0x1d7c4, 0x1d7c9,
+ 0x1d7cb, 0x1d7cb,
+ 0x1df00, 0x1df09,
+ 0x1df0b, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e030, 0x1e06d,
+ 0x1e922, 0x1e943,
+}; /* CR_Lower */
+
+/* 'Print': [[:Print:]] */
+static const OnigCodePoint CR_Print[] = {
+ 737,
+ 0x0020, 0x007e,
+ 0x00a0, 0x0377,
+ 0x037a, 0x037f,
+ 0x0384, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x052f,
+ 0x0531, 0x0556,
+ 0x0559, 0x058a,
+ 0x058d, 0x058f,
+ 0x0591, 0x05c7,
+ 0x05d0, 0x05ea,
+ 0x05ef, 0x05f4,
+ 0x0600, 0x070d,
+ 0x070f, 0x074a,
+ 0x074d, 0x07b1,
+ 0x07c0, 0x07fa,
+ 0x07fd, 0x082d,
+ 0x0830, 0x083e,
+ 0x0840, 0x085b,
+ 0x085e, 0x085e,
+ 0x0860, 0x086a,
+ 0x0870, 0x0891,
+ 0x0897, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fe,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 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,
+ 0x0be6, 0x0bfa,
+ 0x0c00, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3c, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c5a,
+ 0x0c5c, 0x0c5d,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c77, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cdc, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf3,
+ 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, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 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, 0x0ece,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 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, 0x1715,
+ 0x171f, 0x1736,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x1800, 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, 0x1add,
+ 0x1ae0, 0x1aeb,
+ 0x1b00, 0x1b4c,
+ 0x1b4e, 0x1bf3,
+ 0x1bfc, 0x1c37,
+ 0x1c3b, 0x1c49,
+ 0x1c4d, 0x1c8a,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cc7,
+ 0x1cd0, 0x1cfa,
+ 0x1d00, 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, 0x2027,
+ 0x202a, 0x2064,
+ 0x2066, 0x2071,
+ 0x2074, 0x208e,
+ 0x2090, 0x209c,
+ 0x20a0, 0x20c1,
+ 0x20d0, 0x20f0,
+ 0x2100, 0x218b,
+ 0x2190, 0x2429,
+ 0x2440, 0x244a,
+ 0x2460, 0x2b73,
+ 0x2b76, 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, 0x2e5d,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312f,
+ 0x3131, 0x318e,
+ 0x3190, 0x31e5,
+ 0x31ef, 0x321e,
+ 0x3220, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa4d0, 0xa62b,
+ 0xa640, 0xa6f7,
+ 0xa700, 0xa7dc,
+ 0xa7f1, 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,
+ 0xe000, 0xfa6d,
+ 0xfa70, 0xfad9,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xfb1d, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfdcf,
+ 0xfdf0, 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, 0xfffd,
+ 0x10000, 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, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x105c0, 0x105f3,
+ 0x10600, 0x10736,
+ 0x10740, 0x10755,
+ 0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 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, 0x10959,
+ 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,
+ 0x10d40, 0x10d65,
+ 0x10d69, 0x10d85,
+ 0x10d8e, 0x10d8f,
+ 0x10e60, 0x10e7e,
+ 0x10e80, 0x10ea9,
+ 0x10eab, 0x10ead,
+ 0x10eb0, 0x10eb1,
+ 0x10ec2, 0x10ec7,
+ 0x10ed0, 0x10ed8,
+ 0x10efa, 0x10f27,
+ 0x10f30, 0x10f59,
+ 0x10f70, 0x10f89,
+ 0x10fb0, 0x10fcb,
+ 0x10fe0, 0x10ff6,
+ 0x11000, 0x1104d,
+ 0x11052, 0x11075,
+ 0x1107f, 0x110c2,
+ 0x110cd, 0x110cd,
+ 0x110d0, 0x110e8,
+ 0x110f0, 0x110f9,
+ 0x11100, 0x11134,
+ 0x11136, 0x11147,
+ 0x11150, 0x11176,
+ 0x11180, 0x111df,
+ 0x111e1, 0x111f4,
+ 0x11200, 0x11211,
+ 0x11213, 0x11241,
+ 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,
+ 0x11380, 0x11389,
+ 0x1138b, 0x1138b,
+ 0x1138e, 0x1138e,
+ 0x11390, 0x113b5,
+ 0x113b7, 0x113c0,
+ 0x113c2, 0x113c2,
+ 0x113c5, 0x113c5,
+ 0x113c7, 0x113ca,
+ 0x113cc, 0x113d5,
+ 0x113d7, 0x113d8,
+ 0x113e1, 0x113e2,
+ 0x11400, 0x1145b,
+ 0x1145d, 0x11461,
+ 0x11480, 0x114c7,
+ 0x114d0, 0x114d9,
+ 0x11580, 0x115b5,
+ 0x115b8, 0x115dd,
+ 0x11600, 0x11644,
+ 0x11650, 0x11659,
+ 0x11660, 0x1166c,
+ 0x11680, 0x116b9,
+ 0x116c0, 0x116c9,
+ 0x116d0, 0x116e3,
+ 0x11700, 0x1171a,
+ 0x1171d, 0x1172b,
+ 0x11730, 0x11746,
+ 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,
+ 0x11ab0, 0x11af8,
+ 0x11b00, 0x11b09,
+ 0x11b60, 0x11b67,
+ 0x11bc0, 0x11be1,
+ 0x11bf0, 0x11bf9,
+ 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,
+ 0x11db0, 0x11ddb,
+ 0x11de0, 0x11de9,
+ 0x11ee0, 0x11ef8,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f5a,
+ 0x11fb0, 0x11fb0,
+ 0x11fc0, 0x11ff1,
+ 0x11fff, 0x12399,
+ 0x12400, 0x1246e,
+ 0x12470, 0x12474,
+ 0x12480, 0x12543,
+ 0x12f90, 0x12ff2,
+ 0x13000, 0x13455,
+ 0x13460, 0x143fa,
+ 0x14400, 0x14646,
+ 0x16100, 0x16139,
+ 0x16800, 0x16a38,
+ 0x16a40, 0x16a5e,
+ 0x16a60, 0x16a69,
+ 0x16a6e, 0x16abe,
+ 0x16ac0, 0x16ac9,
+ 0x16ad0, 0x16aed,
+ 0x16af0, 0x16af5,
+ 0x16b00, 0x16b45,
+ 0x16b50, 0x16b59,
+ 0x16b5b, 0x16b61,
+ 0x16b63, 0x16b77,
+ 0x16b7d, 0x16b8f,
+ 0x16d40, 0x16d79,
+ 0x16e40, 0x16e9a,
+ 0x16ea0, 0x16eb8,
+ 0x16ebb, 0x16ed3,
+ 0x16f00, 0x16f4a,
+ 0x16f4f, 0x16f87,
+ 0x16f8f, 0x16f9f,
+ 0x16fe0, 0x16fe4,
+ 0x16ff0, 0x16ff6,
+ 0x17000, 0x18cd5,
+ 0x18cff, 0x18d1e,
+ 0x18d80, 0x18df2,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
+ 0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
+ 0x1b164, 0x1b167,
+ 0x1b170, 0x1b2fb,
+ 0x1bc00, 0x1bc6a,
+ 0x1bc70, 0x1bc7c,
+ 0x1bc80, 0x1bc88,
+ 0x1bc90, 0x1bc99,
+ 0x1bc9c, 0x1bca3,
+ 0x1cc00, 0x1ccfc,
+ 0x1cd00, 0x1ceb3,
+ 0x1ceba, 0x1ced0,
+ 0x1cee0, 0x1cef0,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
+ 0x1cf50, 0x1cfc3,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d129, 0x1d1ea,
+ 0x1d200, 0x1d245,
+ 0x1d2c0, 0x1d2d3,
+ 0x1d2e0, 0x1d2f3,
+ 0x1d300, 0x1d356,
+ 0x1d360, 0x1d378,
+ 0x1d400, 0x1d454,
+ 0x1d456, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 0x1d4a2, 0x1d4a2,
+ 0x1d4a5, 0x1d4a6,
+ 0x1d4a9, 0x1d4ac,
+ 0x1d4ae, 0x1d4b9,
+ 0x1d4bb, 0x1d4bb,
+ 0x1d4bd, 0x1d4c3,
+ 0x1d4c5, 0x1d505,
+ 0x1d507, 0x1d50a,
+ 0x1d50d, 0x1d514,
+ 0x1d516, 0x1d51c,
+ 0x1d51e, 0x1d539,
+ 0x1d53b, 0x1d53e,
+ 0x1d540, 0x1d544,
+ 0x1d546, 0x1d546,
+ 0x1d54a, 0x1d550,
+ 0x1d552, 0x1d6a5,
+ 0x1d6a8, 0x1d7cb,
+ 0x1d7ce, 0x1da8b,
+ 0x1da9b, 0x1da9f,
+ 0x1daa1, 0x1daaf,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e000, 0x1e006,
+ 0x1e008, 0x1e018,
+ 0x1e01b, 0x1e021,
+ 0x1e023, 0x1e024,
+ 0x1e026, 0x1e02a,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
+ 0x1e100, 0x1e12c,
+ 0x1e130, 0x1e13d,
+ 0x1e140, 0x1e149,
+ 0x1e14e, 0x1e14f,
+ 0x1e290, 0x1e2ae,
+ 0x1e2c0, 0x1e2f9,
+ 0x1e2ff, 0x1e2ff,
+ 0x1e4d0, 0x1e4f9,
+ 0x1e5d0, 0x1e5fa,
+ 0x1e5ff, 0x1e5ff,
+ 0x1e6c0, 0x1e6de,
+ 0x1e6e0, 0x1e6f5,
+ 0x1e6fe, 0x1e6ff,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
+ 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, 0x1f6d8,
+ 0x1f6dc, 0x1f6ec,
+ 0x1f6f0, 0x1f6fc,
+ 0x1f700, 0x1f7d9,
+ 0x1f7e0, 0x1f7eb,
+ 0x1f7f0, 0x1f7f0,
+ 0x1f800, 0x1f80b,
+ 0x1f810, 0x1f847,
+ 0x1f850, 0x1f859,
+ 0x1f860, 0x1f887,
+ 0x1f890, 0x1f8ad,
+ 0x1f8b0, 0x1f8bb,
+ 0x1f8c0, 0x1f8c1,
+ 0x1f8d0, 0x1f8d8,
+ 0x1f900, 0x1fa57,
+ 0x1fa60, 0x1fa6d,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa8a,
+ 0x1fa8e, 0x1fac6,
+ 0x1fac8, 0x1fac8,
+ 0x1facd, 0x1fadc,
+ 0x1fadf, 0x1faea,
+ 0x1faef, 0x1faf8,
+ 0x1fb00, 0x1fb92,
+ 0x1fb94, 0x1fbfa,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b81d,
+ 0x2b820, 0x2cead,
+ 0x2ceb0, 0x2ebe0,
+ 0x2ebf0, 0x2ee5d,
+ 0x2f800, 0x2fa1d,
+ 0x30000, 0x3134a,
+ 0x31350, 0x33479,
+ 0xe0001, 0xe0001,
+ 0xe0020, 0xe007f,
+ 0xe0100, 0xe01ef,
+ 0xf0000, 0xffffd,
+ 0x100000, 0x10fffd,
+}; /* CR_Print */
+
+/* 'XPosixPunct': [[:Punct:]] */
+static const OnigCodePoint CR_XPosixPunct[] = {
+ 194,
+ 0x0021, 0x002f,
+ 0x003a, 0x0040,
+ 0x005b, 0x0060,
+ 0x007b, 0x007e,
+ 0x00a1, 0x00a1,
+ 0x00a7, 0x00a7,
+ 0x00ab, 0x00ab,
+ 0x00b6, 0x00b7,
+ 0x00bb, 0x00bb,
+ 0x00bf, 0x00bf,
+ 0x037e, 0x037e,
+ 0x0387, 0x0387,
+ 0x055a, 0x055f,
+ 0x0589, 0x058a,
+ 0x05be, 0x05be,
+ 0x05c0, 0x05c0,
+ 0x05c3, 0x05c3,
+ 0x05c6, 0x05c6,
+ 0x05f3, 0x05f4,
+ 0x0609, 0x060a,
+ 0x060c, 0x060d,
+ 0x061b, 0x061b,
+ 0x061d, 0x061f,
+ 0x066a, 0x066d,
+ 0x06d4, 0x06d4,
+ 0x0700, 0x070d,
+ 0x07f7, 0x07f9,
+ 0x0830, 0x083e,
+ 0x085e, 0x085e,
+ 0x0964, 0x0965,
+ 0x0970, 0x0970,
+ 0x09fd, 0x09fd,
+ 0x0a76, 0x0a76,
+ 0x0af0, 0x0af0,
+ 0x0c77, 0x0c77,
+ 0x0c84, 0x0c84,
+ 0x0df4, 0x0df4,
+ 0x0e4f, 0x0e4f,
+ 0x0e5a, 0x0e5b,
+ 0x0f04, 0x0f12,
+ 0x0f14, 0x0f14,
+ 0x0f3a, 0x0f3d,
+ 0x0f85, 0x0f85,
+ 0x0fd0, 0x0fd4,
+ 0x0fd9, 0x0fda,
+ 0x104a, 0x104f,
+ 0x10fb, 0x10fb,
+ 0x1360, 0x1368,
+ 0x1400, 0x1400,
+ 0x166e, 0x166e,
+ 0x169b, 0x169c,
+ 0x16eb, 0x16ed,
+ 0x1735, 0x1736,
+ 0x17d4, 0x17d6,
+ 0x17d8, 0x17da,
+ 0x1800, 0x180a,
+ 0x1944, 0x1945,
+ 0x1a1e, 0x1a1f,
+ 0x1aa0, 0x1aa6,
+ 0x1aa8, 0x1aad,
+ 0x1b4e, 0x1b4f,
+ 0x1b5a, 0x1b60,
+ 0x1b7d, 0x1b7f,
+ 0x1bfc, 0x1bff,
+ 0x1c3b, 0x1c3f,
+ 0x1c7e, 0x1c7f,
+ 0x1cc0, 0x1cc7,
+ 0x1cd3, 0x1cd3,
+ 0x2010, 0x2027,
+ 0x2030, 0x2043,
+ 0x2045, 0x2051,
+ 0x2053, 0x205e,
+ 0x207d, 0x207e,
+ 0x208d, 0x208e,
+ 0x2308, 0x230b,
+ 0x2329, 0x232a,
+ 0x2768, 0x2775,
+ 0x27c5, 0x27c6,
+ 0x27e6, 0x27ef,
+ 0x2983, 0x2998,
+ 0x29d8, 0x29db,
+ 0x29fc, 0x29fd,
+ 0x2cf9, 0x2cfc,
+ 0x2cfe, 0x2cff,
+ 0x2d70, 0x2d70,
+ 0x2e00, 0x2e2e,
+ 0x2e30, 0x2e4f,
+ 0x2e52, 0x2e5d,
+ 0x3001, 0x3003,
+ 0x3008, 0x3011,
+ 0x3014, 0x301f,
+ 0x3030, 0x3030,
+ 0x303d, 0x303d,
+ 0x30a0, 0x30a0,
+ 0x30fb, 0x30fb,
+ 0xa4fe, 0xa4ff,
+ 0xa60d, 0xa60f,
+ 0xa673, 0xa673,
+ 0xa67e, 0xa67e,
+ 0xa6f2, 0xa6f7,
+ 0xa874, 0xa877,
+ 0xa8ce, 0xa8cf,
+ 0xa8f8, 0xa8fa,
+ 0xa8fc, 0xa8fc,
+ 0xa92e, 0xa92f,
+ 0xa95f, 0xa95f,
+ 0xa9c1, 0xa9cd,
+ 0xa9de, 0xa9df,
+ 0xaa5c, 0xaa5f,
+ 0xaade, 0xaadf,
+ 0xaaf0, 0xaaf1,
+ 0xabeb, 0xabeb,
+ 0xfd3e, 0xfd3f,
+ 0xfe10, 0xfe19,
+ 0xfe30, 0xfe52,
+ 0xfe54, 0xfe61,
+ 0xfe63, 0xfe63,
+ 0xfe68, 0xfe68,
+ 0xfe6a, 0xfe6b,
+ 0xff01, 0xff03,
+ 0xff05, 0xff0a,
+ 0xff0c, 0xff0f,
+ 0xff1a, 0xff1b,
+ 0xff1f, 0xff20,
+ 0xff3b, 0xff3d,
+ 0xff3f, 0xff3f,
+ 0xff5b, 0xff5b,
+ 0xff5d, 0xff5d,
+ 0xff5f, 0xff65,
+ 0x10100, 0x10102,
+ 0x1039f, 0x1039f,
+ 0x103d0, 0x103d0,
+ 0x1056f, 0x1056f,
+ 0x10857, 0x10857,
+ 0x1091f, 0x1091f,
+ 0x1093f, 0x1093f,
+ 0x10a50, 0x10a58,
+ 0x10a7f, 0x10a7f,
+ 0x10af0, 0x10af6,
+ 0x10b39, 0x10b3f,
+ 0x10b99, 0x10b9c,
+ 0x10d6e, 0x10d6e,
+ 0x10ead, 0x10ead,
+ 0x10ed0, 0x10ed0,
+ 0x10f55, 0x10f59,
+ 0x10f86, 0x10f89,
+ 0x11047, 0x1104d,
+ 0x110bb, 0x110bc,
+ 0x110be, 0x110c1,
+ 0x11140, 0x11143,
+ 0x11174, 0x11175,
+ 0x111c5, 0x111c8,
+ 0x111cd, 0x111cd,
+ 0x111db, 0x111db,
+ 0x111dd, 0x111df,
+ 0x11238, 0x1123d,
+ 0x112a9, 0x112a9,
+ 0x113d4, 0x113d5,
+ 0x113d7, 0x113d8,
+ 0x1144b, 0x1144f,
+ 0x1145a, 0x1145b,
+ 0x1145d, 0x1145d,
+ 0x114c6, 0x114c6,
+ 0x115c1, 0x115d7,
+ 0x11641, 0x11643,
+ 0x11660, 0x1166c,
+ 0x116b9, 0x116b9,
+ 0x1173c, 0x1173e,
+ 0x1183b, 0x1183b,
+ 0x11944, 0x11946,
+ 0x119e2, 0x119e2,
+ 0x11a3f, 0x11a46,
+ 0x11a9a, 0x11a9c,
+ 0x11a9e, 0x11aa2,
+ 0x11b00, 0x11b09,
+ 0x11be1, 0x11be1,
+ 0x11c41, 0x11c45,
+ 0x11c70, 0x11c71,
+ 0x11ef7, 0x11ef8,
+ 0x11f43, 0x11f4f,
+ 0x11fff, 0x11fff,
+ 0x12470, 0x12474,
+ 0x12ff1, 0x12ff2,
+ 0x16a6e, 0x16a6f,
+ 0x16af5, 0x16af5,
+ 0x16b37, 0x16b3b,
+ 0x16b44, 0x16b44,
+ 0x16d6d, 0x16d6f,
+ 0x16e97, 0x16e9a,
+ 0x16fe2, 0x16fe2,
+ 0x1bc9f, 0x1bc9f,
+ 0x1da87, 0x1da8b,
+ 0x1e5ff, 0x1e5ff,
+ 0x1e95e, 0x1e95f,
+}; /* CR_XPosixPunct */
+
+/* 'Space': [[:Space:]] */
+static const OnigCodePoint CR_Space[] = {
+ 10,
+ 0x0009, 0x000d,
+ 0x0020, 0x0020,
+ 0x0085, 0x0085,
+ 0x00a0, 0x00a0,
+ 0x1680, 0x1680,
+ 0x2000, 0x200a,
+ 0x2028, 0x2029,
+ 0x202f, 0x202f,
+ 0x205f, 0x205f,
+ 0x3000, 0x3000,
+}; /* CR_Space */
+
+/* 'Upper': [[:Upper:]] */
+static const OnigCodePoint CR_Upper[] = {
+ 660,
+ 0x0041, 0x005a,
+ 0x00c0, 0x00d6,
+ 0x00d8, 0x00de,
+ 0x0100, 0x0100,
+ 0x0102, 0x0102,
+ 0x0104, 0x0104,
+ 0x0106, 0x0106,
+ 0x0108, 0x0108,
+ 0x010a, 0x010a,
+ 0x010c, 0x010c,
+ 0x010e, 0x010e,
+ 0x0110, 0x0110,
+ 0x0112, 0x0112,
+ 0x0114, 0x0114,
+ 0x0116, 0x0116,
+ 0x0118, 0x0118,
+ 0x011a, 0x011a,
+ 0x011c, 0x011c,
+ 0x011e, 0x011e,
+ 0x0120, 0x0120,
+ 0x0122, 0x0122,
+ 0x0124, 0x0124,
+ 0x0126, 0x0126,
+ 0x0128, 0x0128,
+ 0x012a, 0x012a,
+ 0x012c, 0x012c,
+ 0x012e, 0x012e,
+ 0x0130, 0x0130,
+ 0x0132, 0x0132,
+ 0x0134, 0x0134,
+ 0x0136, 0x0136,
+ 0x0139, 0x0139,
+ 0x013b, 0x013b,
+ 0x013d, 0x013d,
+ 0x013f, 0x013f,
+ 0x0141, 0x0141,
+ 0x0143, 0x0143,
+ 0x0145, 0x0145,
+ 0x0147, 0x0147,
+ 0x014a, 0x014a,
+ 0x014c, 0x014c,
+ 0x014e, 0x014e,
+ 0x0150, 0x0150,
+ 0x0152, 0x0152,
+ 0x0154, 0x0154,
+ 0x0156, 0x0156,
+ 0x0158, 0x0158,
+ 0x015a, 0x015a,
+ 0x015c, 0x015c,
+ 0x015e, 0x015e,
+ 0x0160, 0x0160,
+ 0x0162, 0x0162,
+ 0x0164, 0x0164,
+ 0x0166, 0x0166,
+ 0x0168, 0x0168,
+ 0x016a, 0x016a,
+ 0x016c, 0x016c,
+ 0x016e, 0x016e,
+ 0x0170, 0x0170,
+ 0x0172, 0x0172,
+ 0x0174, 0x0174,
+ 0x0176, 0x0176,
+ 0x0178, 0x0179,
+ 0x017b, 0x017b,
+ 0x017d, 0x017d,
+ 0x0181, 0x0182,
+ 0x0184, 0x0184,
+ 0x0186, 0x0187,
+ 0x0189, 0x018b,
+ 0x018e, 0x0191,
+ 0x0193, 0x0194,
+ 0x0196, 0x0198,
+ 0x019c, 0x019d,
+ 0x019f, 0x01a0,
+ 0x01a2, 0x01a2,
+ 0x01a4, 0x01a4,
+ 0x01a6, 0x01a7,
+ 0x01a9, 0x01a9,
+ 0x01ac, 0x01ac,
+ 0x01ae, 0x01af,
+ 0x01b1, 0x01b3,
+ 0x01b5, 0x01b5,
+ 0x01b7, 0x01b8,
+ 0x01bc, 0x01bc,
+ 0x01c4, 0x01c4,
+ 0x01c7, 0x01c7,
+ 0x01ca, 0x01ca,
+ 0x01cd, 0x01cd,
+ 0x01cf, 0x01cf,
+ 0x01d1, 0x01d1,
+ 0x01d3, 0x01d3,
+ 0x01d5, 0x01d5,
+ 0x01d7, 0x01d7,
+ 0x01d9, 0x01d9,
+ 0x01db, 0x01db,
+ 0x01de, 0x01de,
+ 0x01e0, 0x01e0,
+ 0x01e2, 0x01e2,
+ 0x01e4, 0x01e4,
+ 0x01e6, 0x01e6,
+ 0x01e8, 0x01e8,
+ 0x01ea, 0x01ea,
+ 0x01ec, 0x01ec,
+ 0x01ee, 0x01ee,
+ 0x01f1, 0x01f1,
+ 0x01f4, 0x01f4,
+ 0x01f6, 0x01f8,
+ 0x01fa, 0x01fa,
+ 0x01fc, 0x01fc,
+ 0x01fe, 0x01fe,
+ 0x0200, 0x0200,
+ 0x0202, 0x0202,
+ 0x0204, 0x0204,
+ 0x0206, 0x0206,
+ 0x0208, 0x0208,
+ 0x020a, 0x020a,
+ 0x020c, 0x020c,
+ 0x020e, 0x020e,
+ 0x0210, 0x0210,
+ 0x0212, 0x0212,
+ 0x0214, 0x0214,
+ 0x0216, 0x0216,
+ 0x0218, 0x0218,
+ 0x021a, 0x021a,
+ 0x021c, 0x021c,
+ 0x021e, 0x021e,
+ 0x0220, 0x0220,
+ 0x0222, 0x0222,
+ 0x0224, 0x0224,
+ 0x0226, 0x0226,
+ 0x0228, 0x0228,
+ 0x022a, 0x022a,
+ 0x022c, 0x022c,
+ 0x022e, 0x022e,
+ 0x0230, 0x0230,
+ 0x0232, 0x0232,
+ 0x023a, 0x023b,
+ 0x023d, 0x023e,
+ 0x0241, 0x0241,
+ 0x0243, 0x0246,
+ 0x0248, 0x0248,
+ 0x024a, 0x024a,
+ 0x024c, 0x024c,
+ 0x024e, 0x024e,
+ 0x0370, 0x0370,
+ 0x0372, 0x0372,
+ 0x0376, 0x0376,
+ 0x037f, 0x037f,
+ 0x0386, 0x0386,
+ 0x0388, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x038f,
+ 0x0391, 0x03a1,
+ 0x03a3, 0x03ab,
+ 0x03cf, 0x03cf,
+ 0x03d2, 0x03d4,
+ 0x03d8, 0x03d8,
+ 0x03da, 0x03da,
+ 0x03dc, 0x03dc,
+ 0x03de, 0x03de,
+ 0x03e0, 0x03e0,
+ 0x03e2, 0x03e2,
+ 0x03e4, 0x03e4,
+ 0x03e6, 0x03e6,
+ 0x03e8, 0x03e8,
+ 0x03ea, 0x03ea,
+ 0x03ec, 0x03ec,
+ 0x03ee, 0x03ee,
+ 0x03f4, 0x03f4,
+ 0x03f7, 0x03f7,
+ 0x03f9, 0x03fa,
+ 0x03fd, 0x042f,
+ 0x0460, 0x0460,
+ 0x0462, 0x0462,
+ 0x0464, 0x0464,
+ 0x0466, 0x0466,
+ 0x0468, 0x0468,
+ 0x046a, 0x046a,
+ 0x046c, 0x046c,
+ 0x046e, 0x046e,
+ 0x0470, 0x0470,
+ 0x0472, 0x0472,
+ 0x0474, 0x0474,
+ 0x0476, 0x0476,
+ 0x0478, 0x0478,
+ 0x047a, 0x047a,
+ 0x047c, 0x047c,
+ 0x047e, 0x047e,
+ 0x0480, 0x0480,
+ 0x048a, 0x048a,
+ 0x048c, 0x048c,
+ 0x048e, 0x048e,
+ 0x0490, 0x0490,
+ 0x0492, 0x0492,
+ 0x0494, 0x0494,
+ 0x0496, 0x0496,
+ 0x0498, 0x0498,
+ 0x049a, 0x049a,
+ 0x049c, 0x049c,
+ 0x049e, 0x049e,
+ 0x04a0, 0x04a0,
+ 0x04a2, 0x04a2,
+ 0x04a4, 0x04a4,
+ 0x04a6, 0x04a6,
+ 0x04a8, 0x04a8,
+ 0x04aa, 0x04aa,
+ 0x04ac, 0x04ac,
+ 0x04ae, 0x04ae,
+ 0x04b0, 0x04b0,
+ 0x04b2, 0x04b2,
+ 0x04b4, 0x04b4,
+ 0x04b6, 0x04b6,
+ 0x04b8, 0x04b8,
+ 0x04ba, 0x04ba,
+ 0x04bc, 0x04bc,
+ 0x04be, 0x04be,
+ 0x04c0, 0x04c1,
+ 0x04c3, 0x04c3,
+ 0x04c5, 0x04c5,
+ 0x04c7, 0x04c7,
+ 0x04c9, 0x04c9,
+ 0x04cb, 0x04cb,
+ 0x04cd, 0x04cd,
+ 0x04d0, 0x04d0,
+ 0x04d2, 0x04d2,
+ 0x04d4, 0x04d4,
+ 0x04d6, 0x04d6,
+ 0x04d8, 0x04d8,
+ 0x04da, 0x04da,
+ 0x04dc, 0x04dc,
+ 0x04de, 0x04de,
+ 0x04e0, 0x04e0,
+ 0x04e2, 0x04e2,
+ 0x04e4, 0x04e4,
+ 0x04e6, 0x04e6,
+ 0x04e8, 0x04e8,
+ 0x04ea, 0x04ea,
+ 0x04ec, 0x04ec,
+ 0x04ee, 0x04ee,
+ 0x04f0, 0x04f0,
+ 0x04f2, 0x04f2,
+ 0x04f4, 0x04f4,
+ 0x04f6, 0x04f6,
+ 0x04f8, 0x04f8,
+ 0x04fa, 0x04fa,
+ 0x04fc, 0x04fc,
+ 0x04fe, 0x04fe,
+ 0x0500, 0x0500,
+ 0x0502, 0x0502,
+ 0x0504, 0x0504,
+ 0x0506, 0x0506,
+ 0x0508, 0x0508,
+ 0x050a, 0x050a,
+ 0x050c, 0x050c,
+ 0x050e, 0x050e,
+ 0x0510, 0x0510,
+ 0x0512, 0x0512,
+ 0x0514, 0x0514,
+ 0x0516, 0x0516,
+ 0x0518, 0x0518,
+ 0x051a, 0x051a,
+ 0x051c, 0x051c,
+ 0x051e, 0x051e,
+ 0x0520, 0x0520,
+ 0x0522, 0x0522,
+ 0x0524, 0x0524,
+ 0x0526, 0x0526,
+ 0x0528, 0x0528,
+ 0x052a, 0x052a,
+ 0x052c, 0x052c,
+ 0x052e, 0x052e,
+ 0x0531, 0x0556,
+ 0x10a0, 0x10c5,
+ 0x10c7, 0x10c7,
+ 0x10cd, 0x10cd,
+ 0x13a0, 0x13f5,
+ 0x1c89, 0x1c89,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cbf,
+ 0x1e00, 0x1e00,
+ 0x1e02, 0x1e02,
+ 0x1e04, 0x1e04,
+ 0x1e06, 0x1e06,
+ 0x1e08, 0x1e08,
+ 0x1e0a, 0x1e0a,
+ 0x1e0c, 0x1e0c,
+ 0x1e0e, 0x1e0e,
+ 0x1e10, 0x1e10,
+ 0x1e12, 0x1e12,
+ 0x1e14, 0x1e14,
+ 0x1e16, 0x1e16,
+ 0x1e18, 0x1e18,
+ 0x1e1a, 0x1e1a,
+ 0x1e1c, 0x1e1c,
+ 0x1e1e, 0x1e1e,
+ 0x1e20, 0x1e20,
+ 0x1e22, 0x1e22,
+ 0x1e24, 0x1e24,
+ 0x1e26, 0x1e26,
+ 0x1e28, 0x1e28,
+ 0x1e2a, 0x1e2a,
+ 0x1e2c, 0x1e2c,
+ 0x1e2e, 0x1e2e,
+ 0x1e30, 0x1e30,
+ 0x1e32, 0x1e32,
+ 0x1e34, 0x1e34,
+ 0x1e36, 0x1e36,
+ 0x1e38, 0x1e38,
+ 0x1e3a, 0x1e3a,
+ 0x1e3c, 0x1e3c,
+ 0x1e3e, 0x1e3e,
+ 0x1e40, 0x1e40,
+ 0x1e42, 0x1e42,
+ 0x1e44, 0x1e44,
+ 0x1e46, 0x1e46,
+ 0x1e48, 0x1e48,
+ 0x1e4a, 0x1e4a,
+ 0x1e4c, 0x1e4c,
+ 0x1e4e, 0x1e4e,
+ 0x1e50, 0x1e50,
+ 0x1e52, 0x1e52,
+ 0x1e54, 0x1e54,
+ 0x1e56, 0x1e56,
+ 0x1e58, 0x1e58,
+ 0x1e5a, 0x1e5a,
+ 0x1e5c, 0x1e5c,
+ 0x1e5e, 0x1e5e,
+ 0x1e60, 0x1e60,
+ 0x1e62, 0x1e62,
+ 0x1e64, 0x1e64,
+ 0x1e66, 0x1e66,
+ 0x1e68, 0x1e68,
+ 0x1e6a, 0x1e6a,
+ 0x1e6c, 0x1e6c,
+ 0x1e6e, 0x1e6e,
+ 0x1e70, 0x1e70,
+ 0x1e72, 0x1e72,
+ 0x1e74, 0x1e74,
+ 0x1e76, 0x1e76,
+ 0x1e78, 0x1e78,
+ 0x1e7a, 0x1e7a,
+ 0x1e7c, 0x1e7c,
+ 0x1e7e, 0x1e7e,
+ 0x1e80, 0x1e80,
+ 0x1e82, 0x1e82,
+ 0x1e84, 0x1e84,
+ 0x1e86, 0x1e86,
+ 0x1e88, 0x1e88,
+ 0x1e8a, 0x1e8a,
+ 0x1e8c, 0x1e8c,
+ 0x1e8e, 0x1e8e,
+ 0x1e90, 0x1e90,
+ 0x1e92, 0x1e92,
+ 0x1e94, 0x1e94,
+ 0x1e9e, 0x1e9e,
+ 0x1ea0, 0x1ea0,
+ 0x1ea2, 0x1ea2,
+ 0x1ea4, 0x1ea4,
+ 0x1ea6, 0x1ea6,
+ 0x1ea8, 0x1ea8,
+ 0x1eaa, 0x1eaa,
+ 0x1eac, 0x1eac,
+ 0x1eae, 0x1eae,
+ 0x1eb0, 0x1eb0,
+ 0x1eb2, 0x1eb2,
+ 0x1eb4, 0x1eb4,
+ 0x1eb6, 0x1eb6,
+ 0x1eb8, 0x1eb8,
+ 0x1eba, 0x1eba,
+ 0x1ebc, 0x1ebc,
+ 0x1ebe, 0x1ebe,
+ 0x1ec0, 0x1ec0,
+ 0x1ec2, 0x1ec2,
+ 0x1ec4, 0x1ec4,
+ 0x1ec6, 0x1ec6,
+ 0x1ec8, 0x1ec8,
+ 0x1eca, 0x1eca,
+ 0x1ecc, 0x1ecc,
+ 0x1ece, 0x1ece,
+ 0x1ed0, 0x1ed0,
+ 0x1ed2, 0x1ed2,
+ 0x1ed4, 0x1ed4,
+ 0x1ed6, 0x1ed6,
+ 0x1ed8, 0x1ed8,
+ 0x1eda, 0x1eda,
+ 0x1edc, 0x1edc,
+ 0x1ede, 0x1ede,
+ 0x1ee0, 0x1ee0,
+ 0x1ee2, 0x1ee2,
+ 0x1ee4, 0x1ee4,
+ 0x1ee6, 0x1ee6,
+ 0x1ee8, 0x1ee8,
+ 0x1eea, 0x1eea,
+ 0x1eec, 0x1eec,
+ 0x1eee, 0x1eee,
+ 0x1ef0, 0x1ef0,
+ 0x1ef2, 0x1ef2,
+ 0x1ef4, 0x1ef4,
+ 0x1ef6, 0x1ef6,
+ 0x1ef8, 0x1ef8,
+ 0x1efa, 0x1efa,
+ 0x1efc, 0x1efc,
+ 0x1efe, 0x1efe,
+ 0x1f08, 0x1f0f,
+ 0x1f18, 0x1f1d,
+ 0x1f28, 0x1f2f,
+ 0x1f38, 0x1f3f,
+ 0x1f48, 0x1f4d,
+ 0x1f59, 0x1f59,
+ 0x1f5b, 0x1f5b,
+ 0x1f5d, 0x1f5d,
+ 0x1f5f, 0x1f5f,
+ 0x1f68, 0x1f6f,
+ 0x1fb8, 0x1fbb,
+ 0x1fc8, 0x1fcb,
+ 0x1fd8, 0x1fdb,
+ 0x1fe8, 0x1fec,
+ 0x1ff8, 0x1ffb,
+ 0x2102, 0x2102,
+ 0x2107, 0x2107,
+ 0x210b, 0x210d,
+ 0x2110, 0x2112,
+ 0x2115, 0x2115,
+ 0x2119, 0x211d,
+ 0x2124, 0x2124,
+ 0x2126, 0x2126,
+ 0x2128, 0x2128,
+ 0x212a, 0x212d,
+ 0x2130, 0x2133,
+ 0x213e, 0x213f,
+ 0x2145, 0x2145,
+ 0x2160, 0x216f,
+ 0x2183, 0x2183,
+ 0x24b6, 0x24cf,
+ 0x2c00, 0x2c2f,
+ 0x2c60, 0x2c60,
+ 0x2c62, 0x2c64,
+ 0x2c67, 0x2c67,
+ 0x2c69, 0x2c69,
+ 0x2c6b, 0x2c6b,
+ 0x2c6d, 0x2c70,
+ 0x2c72, 0x2c72,
+ 0x2c75, 0x2c75,
+ 0x2c7e, 0x2c80,
+ 0x2c82, 0x2c82,
+ 0x2c84, 0x2c84,
+ 0x2c86, 0x2c86,
+ 0x2c88, 0x2c88,
+ 0x2c8a, 0x2c8a,
+ 0x2c8c, 0x2c8c,
+ 0x2c8e, 0x2c8e,
+ 0x2c90, 0x2c90,
+ 0x2c92, 0x2c92,
+ 0x2c94, 0x2c94,
+ 0x2c96, 0x2c96,
+ 0x2c98, 0x2c98,
+ 0x2c9a, 0x2c9a,
+ 0x2c9c, 0x2c9c,
+ 0x2c9e, 0x2c9e,
+ 0x2ca0, 0x2ca0,
+ 0x2ca2, 0x2ca2,
+ 0x2ca4, 0x2ca4,
+ 0x2ca6, 0x2ca6,
+ 0x2ca8, 0x2ca8,
+ 0x2caa, 0x2caa,
+ 0x2cac, 0x2cac,
+ 0x2cae, 0x2cae,
+ 0x2cb0, 0x2cb0,
+ 0x2cb2, 0x2cb2,
+ 0x2cb4, 0x2cb4,
+ 0x2cb6, 0x2cb6,
+ 0x2cb8, 0x2cb8,
+ 0x2cba, 0x2cba,
+ 0x2cbc, 0x2cbc,
+ 0x2cbe, 0x2cbe,
+ 0x2cc0, 0x2cc0,
+ 0x2cc2, 0x2cc2,
+ 0x2cc4, 0x2cc4,
+ 0x2cc6, 0x2cc6,
+ 0x2cc8, 0x2cc8,
+ 0x2cca, 0x2cca,
+ 0x2ccc, 0x2ccc,
+ 0x2cce, 0x2cce,
+ 0x2cd0, 0x2cd0,
+ 0x2cd2, 0x2cd2,
+ 0x2cd4, 0x2cd4,
+ 0x2cd6, 0x2cd6,
+ 0x2cd8, 0x2cd8,
+ 0x2cda, 0x2cda,
+ 0x2cdc, 0x2cdc,
+ 0x2cde, 0x2cde,
+ 0x2ce0, 0x2ce0,
+ 0x2ce2, 0x2ce2,
+ 0x2ceb, 0x2ceb,
+ 0x2ced, 0x2ced,
+ 0x2cf2, 0x2cf2,
+ 0xa640, 0xa640,
+ 0xa642, 0xa642,
+ 0xa644, 0xa644,
+ 0xa646, 0xa646,
+ 0xa648, 0xa648,
+ 0xa64a, 0xa64a,
+ 0xa64c, 0xa64c,
+ 0xa64e, 0xa64e,
+ 0xa650, 0xa650,
+ 0xa652, 0xa652,
+ 0xa654, 0xa654,
+ 0xa656, 0xa656,
+ 0xa658, 0xa658,
+ 0xa65a, 0xa65a,
+ 0xa65c, 0xa65c,
+ 0xa65e, 0xa65e,
+ 0xa660, 0xa660,
+ 0xa662, 0xa662,
+ 0xa664, 0xa664,
+ 0xa666, 0xa666,
+ 0xa668, 0xa668,
+ 0xa66a, 0xa66a,
+ 0xa66c, 0xa66c,
+ 0xa680, 0xa680,
+ 0xa682, 0xa682,
+ 0xa684, 0xa684,
+ 0xa686, 0xa686,
+ 0xa688, 0xa688,
+ 0xa68a, 0xa68a,
+ 0xa68c, 0xa68c,
+ 0xa68e, 0xa68e,
+ 0xa690, 0xa690,
+ 0xa692, 0xa692,
+ 0xa694, 0xa694,
+ 0xa696, 0xa696,
+ 0xa698, 0xa698,
+ 0xa69a, 0xa69a,
+ 0xa722, 0xa722,
+ 0xa724, 0xa724,
+ 0xa726, 0xa726,
+ 0xa728, 0xa728,
+ 0xa72a, 0xa72a,
+ 0xa72c, 0xa72c,
+ 0xa72e, 0xa72e,
+ 0xa732, 0xa732,
+ 0xa734, 0xa734,
+ 0xa736, 0xa736,
+ 0xa738, 0xa738,
+ 0xa73a, 0xa73a,
+ 0xa73c, 0xa73c,
+ 0xa73e, 0xa73e,
+ 0xa740, 0xa740,
+ 0xa742, 0xa742,
+ 0xa744, 0xa744,
+ 0xa746, 0xa746,
+ 0xa748, 0xa748,
+ 0xa74a, 0xa74a,
+ 0xa74c, 0xa74c,
+ 0xa74e, 0xa74e,
+ 0xa750, 0xa750,
+ 0xa752, 0xa752,
+ 0xa754, 0xa754,
+ 0xa756, 0xa756,
+ 0xa758, 0xa758,
+ 0xa75a, 0xa75a,
+ 0xa75c, 0xa75c,
+ 0xa75e, 0xa75e,
+ 0xa760, 0xa760,
+ 0xa762, 0xa762,
+ 0xa764, 0xa764,
+ 0xa766, 0xa766,
+ 0xa768, 0xa768,
+ 0xa76a, 0xa76a,
+ 0xa76c, 0xa76c,
+ 0xa76e, 0xa76e,
+ 0xa779, 0xa779,
+ 0xa77b, 0xa77b,
+ 0xa77d, 0xa77e,
+ 0xa780, 0xa780,
+ 0xa782, 0xa782,
+ 0xa784, 0xa784,
+ 0xa786, 0xa786,
+ 0xa78b, 0xa78b,
+ 0xa78d, 0xa78d,
+ 0xa790, 0xa790,
+ 0xa792, 0xa792,
+ 0xa796, 0xa796,
+ 0xa798, 0xa798,
+ 0xa79a, 0xa79a,
+ 0xa79c, 0xa79c,
+ 0xa79e, 0xa79e,
+ 0xa7a0, 0xa7a0,
+ 0xa7a2, 0xa7a2,
+ 0xa7a4, 0xa7a4,
+ 0xa7a6, 0xa7a6,
+ 0xa7a8, 0xa7a8,
+ 0xa7aa, 0xa7ae,
+ 0xa7b0, 0xa7b4,
+ 0xa7b6, 0xa7b6,
+ 0xa7b8, 0xa7b8,
+ 0xa7ba, 0xa7ba,
+ 0xa7bc, 0xa7bc,
+ 0xa7be, 0xa7be,
+ 0xa7c0, 0xa7c0,
+ 0xa7c2, 0xa7c2,
+ 0xa7c4, 0xa7c7,
+ 0xa7c9, 0xa7c9,
+ 0xa7cb, 0xa7cc,
+ 0xa7ce, 0xa7ce,
+ 0xa7d0, 0xa7d0,
+ 0xa7d2, 0xa7d2,
+ 0xa7d4, 0xa7d4,
+ 0xa7d6, 0xa7d6,
+ 0xa7d8, 0xa7d8,
+ 0xa7da, 0xa7da,
+ 0xa7dc, 0xa7dc,
+ 0xa7f5, 0xa7f5,
+ 0xff21, 0xff3a,
+ 0x10400, 0x10427,
+ 0x104b0, 0x104d3,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10c80, 0x10cb2,
+ 0x10d50, 0x10d65,
+ 0x118a0, 0x118bf,
+ 0x16e40, 0x16e5f,
+ 0x16ea0, 0x16eb8,
+ 0x1d400, 0x1d419,
+ 0x1d434, 0x1d44d,
+ 0x1d468, 0x1d481,
+ 0x1d49c, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 0x1d4a2, 0x1d4a2,
+ 0x1d4a5, 0x1d4a6,
+ 0x1d4a9, 0x1d4ac,
+ 0x1d4ae, 0x1d4b5,
+ 0x1d4d0, 0x1d4e9,
+ 0x1d504, 0x1d505,
+ 0x1d507, 0x1d50a,
+ 0x1d50d, 0x1d514,
+ 0x1d516, 0x1d51c,
+ 0x1d538, 0x1d539,
+ 0x1d53b, 0x1d53e,
+ 0x1d540, 0x1d544,
+ 0x1d546, 0x1d546,
+ 0x1d54a, 0x1d550,
+ 0x1d56c, 0x1d585,
+ 0x1d5a0, 0x1d5b9,
+ 0x1d5d4, 0x1d5ed,
+ 0x1d608, 0x1d621,
+ 0x1d63c, 0x1d655,
+ 0x1d670, 0x1d689,
+ 0x1d6a8, 0x1d6c0,
+ 0x1d6e2, 0x1d6fa,
+ 0x1d71c, 0x1d734,
+ 0x1d756, 0x1d76e,
+ 0x1d790, 0x1d7a8,
+ 0x1d7ca, 0x1d7ca,
+ 0x1e900, 0x1e921,
+ 0x1f130, 0x1f149,
+ 0x1f150, 0x1f169,
+ 0x1f170, 0x1f189,
+}; /* CR_Upper */
+
+/* 'XDigit': [[:XDigit:]] */
+static const OnigCodePoint CR_XDigit[] = {
+ 3,
+ 0x0030, 0x0039,
+ 0x0041, 0x0046,
+ 0x0061, 0x0066,
+}; /* CR_XDigit */
+
+/* 'Word': [[:Word:]] */
+static const OnigCodePoint CR_Word[] = {
+ 802,
+ 0x0030, 0x0039,
+ 0x0041, 0x005a,
+ 0x005f, 0x005f,
+ 0x0061, 0x007a,
+ 0x00aa, 0x00aa,
+ 0x00b5, 0x00b5,
+ 0x00ba, 0x00ba,
+ 0x00c0, 0x00d6,
+ 0x00d8, 0x00f6,
+ 0x00f8, 0x02c1,
+ 0x02c6, 0x02d1,
+ 0x02e0, 0x02e4,
+ 0x02ec, 0x02ec,
+ 0x02ee, 0x02ee,
+ 0x0300, 0x0374,
+ 0x0376, 0x0377,
+ 0x037a, 0x037d,
+ 0x037f, 0x037f,
+ 0x0386, 0x0386,
+ 0x0388, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x03f5,
+ 0x03f7, 0x0481,
+ 0x0483, 0x052f,
+ 0x0531, 0x0556,
+ 0x0559, 0x0559,
+ 0x0560, 0x0588,
+ 0x0591, 0x05bd,
+ 0x05bf, 0x05bf,
+ 0x05c1, 0x05c2,
+ 0x05c4, 0x05c5,
+ 0x05c7, 0x05c7,
+ 0x05d0, 0x05ea,
+ 0x05ef, 0x05f2,
+ 0x0610, 0x061a,
+ 0x0620, 0x0669,
+ 0x066e, 0x06d3,
+ 0x06d5, 0x06dc,
+ 0x06df, 0x06e8,
+ 0x06ea, 0x06fc,
+ 0x06ff, 0x06ff,
+ 0x0710, 0x074a,
+ 0x074d, 0x07b1,
+ 0x07c0, 0x07f5,
+ 0x07fa, 0x07fa,
+ 0x07fd, 0x07fd,
+ 0x0800, 0x082d,
+ 0x0840, 0x085b,
+ 0x0860, 0x086a,
+ 0x0870, 0x0887,
+ 0x0889, 0x088f,
+ 0x0897, 0x08e1,
+ 0x08e3, 0x0963,
+ 0x0966, 0x096f,
+ 0x0971, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09f1,
+ 0x09fc, 0x09fc,
+ 0x09fe, 0x09fe,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a75,
+ 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, 0x0aef,
+ 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, 0x0b6f,
+ 0x0b71, 0x0b71,
+ 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,
+ 0x0be6, 0x0bef,
+ 0x0c00, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3c, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c5a,
+ 0x0c5c, 0x0c5d,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c80, 0x0c83,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cdc, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf3,
+ 0x0d00, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d44,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4e,
+ 0x0d54, 0x0d57,
+ 0x0d5f, 0x0d63,
+ 0x0d66, 0x0d6f,
+ 0x0d7a, 0x0d7f,
+ 0x0d81, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0de6, 0x0def,
+ 0x0df2, 0x0df3,
+ 0x0e01, 0x0e3a,
+ 0x0e40, 0x0e4e,
+ 0x0e50, 0x0e59,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e86, 0x0e8a,
+ 0x0e8c, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ece,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f00,
+ 0x0f18, 0x0f19,
+ 0x0f20, 0x0f29,
+ 0x0f35, 0x0f35,
+ 0x0f37, 0x0f37,
+ 0x0f39, 0x0f39,
+ 0x0f3e, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f84,
+ 0x0f86, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 0x0fc6, 0x0fc6,
+ 0x1000, 0x1049,
+ 0x1050, 0x109d,
+ 0x10a0, 0x10c5,
+ 0x10c7, 0x10c7,
+ 0x10cd, 0x10cd,
+ 0x10d0, 0x10fa,
+ 0x10fc, 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, 0x135f,
+ 0x1380, 0x138f,
+ 0x13a0, 0x13f5,
+ 0x13f8, 0x13fd,
+ 0x1401, 0x166c,
+ 0x166f, 0x167f,
+ 0x1681, 0x169a,
+ 0x16a0, 0x16ea,
+ 0x16ee, 0x16f8,
+ 0x1700, 0x1715,
+ 0x171f, 0x1734,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17d3,
+ 0x17d7, 0x17d7,
+ 0x17dc, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x180b, 0x180d,
+ 0x180f, 0x1819,
+ 0x1820, 0x1878,
+ 0x1880, 0x18aa,
+ 0x18b0, 0x18f5,
+ 0x1900, 0x191e,
+ 0x1920, 0x192b,
+ 0x1930, 0x193b,
+ 0x1946, 0x196d,
+ 0x1970, 0x1974,
+ 0x1980, 0x19ab,
+ 0x19b0, 0x19c9,
+ 0x19d0, 0x19d9,
+ 0x1a00, 0x1a1b,
+ 0x1a20, 0x1a5e,
+ 0x1a60, 0x1a7c,
+ 0x1a7f, 0x1a89,
+ 0x1a90, 0x1a99,
+ 0x1aa7, 0x1aa7,
+ 0x1ab0, 0x1add,
+ 0x1ae0, 0x1aeb,
+ 0x1b00, 0x1b4c,
+ 0x1b50, 0x1b59,
+ 0x1b6b, 0x1b73,
+ 0x1b80, 0x1bf3,
+ 0x1c00, 0x1c37,
+ 0x1c40, 0x1c49,
+ 0x1c4d, 0x1c7d,
+ 0x1c80, 0x1c8a,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cbf,
+ 0x1cd0, 0x1cd2,
+ 0x1cd4, 0x1cfa,
+ 0x1d00, 0x1f15,
+ 0x1f18, 0x1f1d,
+ 0x1f20, 0x1f45,
+ 0x1f48, 0x1f4d,
+ 0x1f50, 0x1f57,
+ 0x1f59, 0x1f59,
+ 0x1f5b, 0x1f5b,
+ 0x1f5d, 0x1f5d,
+ 0x1f5f, 0x1f7d,
+ 0x1f80, 0x1fb4,
+ 0x1fb6, 0x1fbc,
+ 0x1fbe, 0x1fbe,
+ 0x1fc2, 0x1fc4,
+ 0x1fc6, 0x1fcc,
+ 0x1fd0, 0x1fd3,
+ 0x1fd6, 0x1fdb,
+ 0x1fe0, 0x1fec,
+ 0x1ff2, 0x1ff4,
+ 0x1ff6, 0x1ffc,
+ 0x200c, 0x200d,
+ 0x203f, 0x2040,
+ 0x2054, 0x2054,
+ 0x2071, 0x2071,
+ 0x207f, 0x207f,
+ 0x2090, 0x209c,
+ 0x20d0, 0x20f0,
+ 0x2102, 0x2102,
+ 0x2107, 0x2107,
+ 0x210a, 0x2113,
+ 0x2115, 0x2115,
+ 0x2119, 0x211d,
+ 0x2124, 0x2124,
+ 0x2126, 0x2126,
+ 0x2128, 0x2128,
+ 0x212a, 0x212d,
+ 0x212f, 0x2139,
+ 0x213c, 0x213f,
+ 0x2145, 0x2149,
+ 0x214e, 0x214e,
+ 0x2160, 0x2188,
+ 0x24b6, 0x24e9,
+ 0x2c00, 0x2ce4,
+ 0x2ceb, 0x2cf3,
+ 0x2d00, 0x2d25,
+ 0x2d27, 0x2d27,
+ 0x2d2d, 0x2d2d,
+ 0x2d30, 0x2d67,
+ 0x2d6f, 0x2d6f,
+ 0x2d7f, 0x2d96,
+ 0x2da0, 0x2da6,
+ 0x2da8, 0x2dae,
+ 0x2db0, 0x2db6,
+ 0x2db8, 0x2dbe,
+ 0x2dc0, 0x2dc6,
+ 0x2dc8, 0x2dce,
+ 0x2dd0, 0x2dd6,
+ 0x2dd8, 0x2dde,
+ 0x2de0, 0x2dff,
+ 0x2e2f, 0x2e2f,
+ 0x3005, 0x3007,
+ 0x3021, 0x302f,
+ 0x3031, 0x3035,
+ 0x3038, 0x303c,
+ 0x3041, 0x3096,
+ 0x3099, 0x309a,
+ 0x309d, 0x309f,
+ 0x30a1, 0x30fa,
+ 0x30fc, 0x30ff,
+ 0x3105, 0x312f,
+ 0x3131, 0x318e,
+ 0x31a0, 0x31bf,
+ 0x31f0, 0x31ff,
+ 0x3400, 0x4dbf,
+ 0x4e00, 0xa48c,
+ 0xa4d0, 0xa4fd,
+ 0xa500, 0xa60c,
+ 0xa610, 0xa62b,
+ 0xa640, 0xa672,
+ 0xa674, 0xa67d,
+ 0xa67f, 0xa6f1,
+ 0xa717, 0xa71f,
+ 0xa722, 0xa788,
+ 0xa78b, 0xa7dc,
+ 0xa7f1, 0xa827,
+ 0xa82c, 0xa82c,
+ 0xa840, 0xa873,
+ 0xa880, 0xa8c5,
+ 0xa8d0, 0xa8d9,
+ 0xa8e0, 0xa8f7,
+ 0xa8fb, 0xa8fb,
+ 0xa8fd, 0xa92d,
+ 0xa930, 0xa953,
+ 0xa960, 0xa97c,
+ 0xa980, 0xa9c0,
+ 0xa9cf, 0xa9d9,
+ 0xa9e0, 0xa9fe,
+ 0xaa00, 0xaa36,
+ 0xaa40, 0xaa4d,
+ 0xaa50, 0xaa59,
+ 0xaa60, 0xaa76,
+ 0xaa7a, 0xaac2,
+ 0xaadb, 0xaadd,
+ 0xaae0, 0xaaef,
+ 0xaaf2, 0xaaf6,
+ 0xab01, 0xab06,
+ 0xab09, 0xab0e,
+ 0xab11, 0xab16,
+ 0xab20, 0xab26,
+ 0xab28, 0xab2e,
+ 0xab30, 0xab5a,
+ 0xab5c, 0xab69,
+ 0xab70, 0xabea,
+ 0xabec, 0xabed,
+ 0xabf0, 0xabf9,
+ 0xac00, 0xd7a3,
+ 0xd7b0, 0xd7c6,
+ 0xd7cb, 0xd7fb,
+ 0xf900, 0xfa6d,
+ 0xfa70, 0xfad9,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xfb1d, 0xfb28,
+ 0xfb2a, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfbb1,
+ 0xfbd3, 0xfd3d,
+ 0xfd50, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdf0, 0xfdfb,
+ 0xfe00, 0xfe0f,
+ 0xfe20, 0xfe2f,
+ 0xfe33, 0xfe34,
+ 0xfe4d, 0xfe4f,
+ 0xfe70, 0xfe74,
+ 0xfe76, 0xfefc,
+ 0xff10, 0xff19,
+ 0xff21, 0xff3a,
+ 0xff3f, 0xff3f,
+ 0xff41, 0xff5a,
+ 0xff66, 0xffbe,
+ 0xffc2, 0xffc7,
+ 0xffca, 0xffcf,
+ 0xffd2, 0xffd7,
+ 0xffda, 0xffdc,
+ 0x10000, 0x1000b,
+ 0x1000d, 0x10026,
+ 0x10028, 0x1003a,
+ 0x1003c, 0x1003d,
+ 0x1003f, 0x1004d,
+ 0x10050, 0x1005d,
+ 0x10080, 0x100fa,
+ 0x10140, 0x10174,
+ 0x101fd, 0x101fd,
+ 0x10280, 0x1029c,
+ 0x102a0, 0x102d0,
+ 0x102e0, 0x102e0,
+ 0x10300, 0x1031f,
+ 0x1032d, 0x1034a,
+ 0x10350, 0x1037a,
+ 0x10380, 0x1039d,
+ 0x103a0, 0x103c3,
+ 0x103c8, 0x103cf,
+ 0x103d1, 0x103d5,
+ 0x10400, 0x1049d,
+ 0x104a0, 0x104a9,
+ 0x104b0, 0x104d3,
+ 0x104d8, 0x104fb,
+ 0x10500, 0x10527,
+ 0x10530, 0x10563,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x105c0, 0x105f3,
+ 0x10600, 0x10736,
+ 0x10740, 0x10755,
+ 0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 0x10837, 0x10838,
+ 0x1083c, 0x1083c,
+ 0x1083f, 0x10855,
+ 0x10860, 0x10876,
+ 0x10880, 0x1089e,
+ 0x108e0, 0x108f2,
+ 0x108f4, 0x108f5,
+ 0x10900, 0x10915,
+ 0x10920, 0x10939,
+ 0x10940, 0x10959,
+ 0x10980, 0x109b7,
+ 0x109be, 0x109bf,
+ 0x10a00, 0x10a03,
+ 0x10a05, 0x10a06,
+ 0x10a0c, 0x10a13,
+ 0x10a15, 0x10a17,
+ 0x10a19, 0x10a35,
+ 0x10a38, 0x10a3a,
+ 0x10a3f, 0x10a3f,
+ 0x10a60, 0x10a7c,
+ 0x10a80, 0x10a9c,
+ 0x10ac0, 0x10ac7,
+ 0x10ac9, 0x10ae6,
+ 0x10b00, 0x10b35,
+ 0x10b40, 0x10b55,
+ 0x10b60, 0x10b72,
+ 0x10b80, 0x10b91,
+ 0x10c00, 0x10c48,
+ 0x10c80, 0x10cb2,
+ 0x10cc0, 0x10cf2,
+ 0x10d00, 0x10d27,
+ 0x10d30, 0x10d39,
+ 0x10d40, 0x10d65,
+ 0x10d69, 0x10d6d,
+ 0x10d6f, 0x10d85,
+ 0x10e80, 0x10ea9,
+ 0x10eab, 0x10eac,
+ 0x10eb0, 0x10eb1,
+ 0x10ec2, 0x10ec7,
+ 0x10efa, 0x10f1c,
+ 0x10f27, 0x10f27,
+ 0x10f30, 0x10f50,
+ 0x10f70, 0x10f85,
+ 0x10fb0, 0x10fc4,
+ 0x10fe0, 0x10ff6,
+ 0x11000, 0x11046,
+ 0x11066, 0x11075,
+ 0x1107f, 0x110ba,
+ 0x110c2, 0x110c2,
+ 0x110d0, 0x110e8,
+ 0x110f0, 0x110f9,
+ 0x11100, 0x11134,
+ 0x11136, 0x1113f,
+ 0x11144, 0x11147,
+ 0x11150, 0x11173,
+ 0x11176, 0x11176,
+ 0x11180, 0x111c4,
+ 0x111c9, 0x111cc,
+ 0x111ce, 0x111da,
+ 0x111dc, 0x111dc,
+ 0x11200, 0x11211,
+ 0x11213, 0x11237,
+ 0x1123e, 0x11241,
+ 0x11280, 0x11286,
+ 0x11288, 0x11288,
+ 0x1128a, 0x1128d,
+ 0x1128f, 0x1129d,
+ 0x1129f, 0x112a8,
+ 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,
+ 0x11380, 0x11389,
+ 0x1138b, 0x1138b,
+ 0x1138e, 0x1138e,
+ 0x11390, 0x113b5,
+ 0x113b7, 0x113c0,
+ 0x113c2, 0x113c2,
+ 0x113c5, 0x113c5,
+ 0x113c7, 0x113ca,
+ 0x113cc, 0x113d3,
+ 0x113e1, 0x113e2,
+ 0x11400, 0x1144a,
+ 0x11450, 0x11459,
+ 0x1145e, 0x11461,
+ 0x11480, 0x114c5,
+ 0x114c7, 0x114c7,
+ 0x114d0, 0x114d9,
+ 0x11580, 0x115b5,
+ 0x115b8, 0x115c0,
+ 0x115d8, 0x115dd,
+ 0x11600, 0x11640,
+ 0x11644, 0x11644,
+ 0x11650, 0x11659,
+ 0x11680, 0x116b8,
+ 0x116c0, 0x116c9,
+ 0x116d0, 0x116e3,
+ 0x11700, 0x1171a,
+ 0x1171d, 0x1172b,
+ 0x11730, 0x11739,
+ 0x11740, 0x11746,
+ 0x11800, 0x1183a,
+ 0x118a0, 0x118e9,
+ 0x118ff, 0x11906,
+ 0x11909, 0x11909,
+ 0x1190c, 0x11913,
+ 0x11915, 0x11916,
+ 0x11918, 0x11935,
+ 0x11937, 0x11938,
+ 0x1193b, 0x11943,
+ 0x11950, 0x11959,
+ 0x119a0, 0x119a7,
+ 0x119aa, 0x119d7,
+ 0x119da, 0x119e1,
+ 0x119e3, 0x119e4,
+ 0x11a00, 0x11a3e,
+ 0x11a47, 0x11a47,
+ 0x11a50, 0x11a99,
+ 0x11a9d, 0x11a9d,
+ 0x11ab0, 0x11af8,
+ 0x11b60, 0x11b67,
+ 0x11bc0, 0x11be0,
+ 0x11bf0, 0x11bf9,
+ 0x11c00, 0x11c08,
+ 0x11c0a, 0x11c36,
+ 0x11c38, 0x11c40,
+ 0x11c50, 0x11c59,
+ 0x11c72, 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,
+ 0x11db0, 0x11ddb,
+ 0x11de0, 0x11de9,
+ 0x11ee0, 0x11ef6,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f42,
+ 0x11f50, 0x11f5a,
+ 0x11fb0, 0x11fb0,
+ 0x12000, 0x12399,
+ 0x12400, 0x1246e,
+ 0x12480, 0x12543,
+ 0x12f90, 0x12ff0,
+ 0x13000, 0x1342f,
+ 0x13440, 0x13455,
+ 0x13460, 0x143fa,
+ 0x14400, 0x14646,
+ 0x16100, 0x16139,
+ 0x16800, 0x16a38,
+ 0x16a40, 0x16a5e,
+ 0x16a60, 0x16a69,
+ 0x16a70, 0x16abe,
+ 0x16ac0, 0x16ac9,
+ 0x16ad0, 0x16aed,
+ 0x16af0, 0x16af4,
+ 0x16b00, 0x16b36,
+ 0x16b40, 0x16b43,
+ 0x16b50, 0x16b59,
+ 0x16b63, 0x16b77,
+ 0x16b7d, 0x16b8f,
+ 0x16d40, 0x16d6c,
+ 0x16d70, 0x16d79,
+ 0x16e40, 0x16e7f,
+ 0x16ea0, 0x16eb8,
+ 0x16ebb, 0x16ed3,
+ 0x16f00, 0x16f4a,
+ 0x16f4f, 0x16f87,
+ 0x16f8f, 0x16f9f,
+ 0x16fe0, 0x16fe1,
+ 0x16fe3, 0x16fe4,
+ 0x16ff0, 0x16ff6,
+ 0x17000, 0x18cd5,
+ 0x18cff, 0x18d1e,
+ 0x18d80, 0x18df2,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
+ 0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
+ 0x1b164, 0x1b167,
+ 0x1b170, 0x1b2fb,
+ 0x1bc00, 0x1bc6a,
+ 0x1bc70, 0x1bc7c,
+ 0x1bc80, 0x1bc88,
+ 0x1bc90, 0x1bc99,
+ 0x1bc9d, 0x1bc9e,
+ 0x1ccf0, 0x1ccf9,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
+ 0x1d165, 0x1d169,
+ 0x1d16d, 0x1d172,
+ 0x1d17b, 0x1d182,
+ 0x1d185, 0x1d18b,
+ 0x1d1aa, 0x1d1ad,
+ 0x1d242, 0x1d244,
+ 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, 0x1d6c0,
+ 0x1d6c2, 0x1d6da,
+ 0x1d6dc, 0x1d6fa,
+ 0x1d6fc, 0x1d714,
+ 0x1d716, 0x1d734,
+ 0x1d736, 0x1d74e,
+ 0x1d750, 0x1d76e,
+ 0x1d770, 0x1d788,
+ 0x1d78a, 0x1d7a8,
+ 0x1d7aa, 0x1d7c2,
+ 0x1d7c4, 0x1d7cb,
+ 0x1d7ce, 0x1d7ff,
+ 0x1da00, 0x1da36,
+ 0x1da3b, 0x1da6c,
+ 0x1da75, 0x1da75,
+ 0x1da84, 0x1da84,
+ 0x1da9b, 0x1da9f,
+ 0x1daa1, 0x1daaf,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e000, 0x1e006,
+ 0x1e008, 0x1e018,
+ 0x1e01b, 0x1e021,
+ 0x1e023, 0x1e024,
+ 0x1e026, 0x1e02a,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
+ 0x1e100, 0x1e12c,
+ 0x1e130, 0x1e13d,
+ 0x1e140, 0x1e149,
+ 0x1e14e, 0x1e14e,
+ 0x1e290, 0x1e2ae,
+ 0x1e2c0, 0x1e2f9,
+ 0x1e4d0, 0x1e4f9,
+ 0x1e5d0, 0x1e5fa,
+ 0x1e6c0, 0x1e6de,
+ 0x1e6e0, 0x1e6f5,
+ 0x1e6fe, 0x1e6ff,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
+ 0x1e800, 0x1e8c4,
+ 0x1e8d0, 0x1e8d6,
+ 0x1e900, 0x1e94b,
+ 0x1e950, 0x1e959,
+ 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,
+ 0x1f130, 0x1f149,
+ 0x1f150, 0x1f169,
+ 0x1f170, 0x1f189,
+ 0x1fbf0, 0x1fbf9,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b81d,
+ 0x2b820, 0x2cead,
+ 0x2ceb0, 0x2ebe0,
+ 0x2ebf0, 0x2ee5d,
+ 0x2f800, 0x2fa1d,
+ 0x30000, 0x3134a,
+ 0x31350, 0x33479,
+ 0xe0100, 0xe01ef,
+}; /* CR_Word */
+
+/* 'Alnum': [[:Alnum:]] */
+static const OnigCodePoint CR_Alnum[] = {
+ 807,
+ 0x0030, 0x0039,
+ 0x0041, 0x005a,
+ 0x0061, 0x007a,
+ 0x00aa, 0x00aa,
+ 0x00b5, 0x00b5,
+ 0x00ba, 0x00ba,
+ 0x00c0, 0x00d6,
+ 0x00d8, 0x00f6,
+ 0x00f8, 0x02c1,
+ 0x02c6, 0x02d1,
+ 0x02e0, 0x02e4,
+ 0x02ec, 0x02ec,
+ 0x02ee, 0x02ee,
+ 0x0345, 0x0345,
+ 0x0363, 0x0374,
+ 0x0376, 0x0377,
+ 0x037a, 0x037d,
+ 0x037f, 0x037f,
+ 0x0386, 0x0386,
+ 0x0388, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x03f5,
+ 0x03f7, 0x0481,
+ 0x048a, 0x052f,
+ 0x0531, 0x0556,
+ 0x0559, 0x0559,
+ 0x0560, 0x0588,
+ 0x05b0, 0x05bd,
+ 0x05bf, 0x05bf,
+ 0x05c1, 0x05c2,
+ 0x05c4, 0x05c5,
+ 0x05c7, 0x05c7,
+ 0x05d0, 0x05ea,
+ 0x05ef, 0x05f2,
+ 0x0610, 0x061a,
+ 0x0620, 0x0657,
+ 0x0659, 0x0669,
+ 0x066e, 0x06d3,
+ 0x06d5, 0x06dc,
+ 0x06e1, 0x06e8,
+ 0x06ed, 0x06fc,
+ 0x06ff, 0x06ff,
+ 0x0710, 0x073f,
+ 0x074d, 0x07b1,
+ 0x07c0, 0x07ea,
+ 0x07f4, 0x07f5,
+ 0x07fa, 0x07fa,
+ 0x0800, 0x0817,
+ 0x081a, 0x082c,
+ 0x0840, 0x0858,
+ 0x0860, 0x086a,
+ 0x0870, 0x0887,
+ 0x0889, 0x088f,
+ 0x0897, 0x0897,
+ 0x08a0, 0x08c9,
+ 0x08d4, 0x08df,
+ 0x08e3, 0x08e9,
+ 0x08f0, 0x093b,
+ 0x093d, 0x094c,
+ 0x094e, 0x0950,
+ 0x0955, 0x0963,
+ 0x0966, 0x096f,
+ 0x0971, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bd, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09cc,
+ 0x09ce, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09f1,
+ 0x09fc, 0x09fc,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4c,
+ 0x0a51, 0x0a51,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a75,
+ 0x0a81, 0x0a83,
+ 0x0a85, 0x0a8d,
+ 0x0a8f, 0x0a91,
+ 0x0a93, 0x0aa8,
+ 0x0aaa, 0x0ab0,
+ 0x0ab2, 0x0ab3,
+ 0x0ab5, 0x0ab9,
+ 0x0abd, 0x0ac5,
+ 0x0ac7, 0x0ac9,
+ 0x0acb, 0x0acc,
+ 0x0ad0, 0x0ad0,
+ 0x0ae0, 0x0ae3,
+ 0x0ae6, 0x0aef,
+ 0x0af9, 0x0afc,
+ 0x0b01, 0x0b03,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b35, 0x0b39,
+ 0x0b3d, 0x0b44,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4c,
+ 0x0b56, 0x0b57,
+ 0x0b5c, 0x0b5d,
+ 0x0b5f, 0x0b63,
+ 0x0b66, 0x0b6f,
+ 0x0b71, 0x0b71,
+ 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, 0x0bcc,
+ 0x0bd0, 0x0bd0,
+ 0x0bd7, 0x0bd7,
+ 0x0be6, 0x0bef,
+ 0x0c00, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3d, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4c,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c5a,
+ 0x0c5c, 0x0c5d,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c80, 0x0c83,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbd, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccc,
+ 0x0cd5, 0x0cd6,
+ 0x0cdc, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf3,
+ 0x0d00, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d3a,
+ 0x0d3d, 0x0d44,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4c,
+ 0x0d4e, 0x0d4e,
+ 0x0d54, 0x0d57,
+ 0x0d5f, 0x0d63,
+ 0x0d66, 0x0d6f,
+ 0x0d7a, 0x0d7f,
+ 0x0d81, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0de6, 0x0def,
+ 0x0df2, 0x0df3,
+ 0x0e01, 0x0e3a,
+ 0x0e40, 0x0e46,
+ 0x0e4d, 0x0e4d,
+ 0x0e50, 0x0e59,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e86, 0x0e8a,
+ 0x0e8c, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0eb9,
+ 0x0ebb, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ecd, 0x0ecd,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f00,
+ 0x0f20, 0x0f29,
+ 0x0f40, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f83,
+ 0x0f88, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 0x1000, 0x1036,
+ 0x1038, 0x1038,
+ 0x103b, 0x1049,
+ 0x1050, 0x109d,
+ 0x10a0, 0x10c5,
+ 0x10c7, 0x10c7,
+ 0x10cd, 0x10cd,
+ 0x10d0, 0x10fa,
+ 0x10fc, 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,
+ 0x1380, 0x138f,
+ 0x13a0, 0x13f5,
+ 0x13f8, 0x13fd,
+ 0x1401, 0x166c,
+ 0x166f, 0x167f,
+ 0x1681, 0x169a,
+ 0x16a0, 0x16ea,
+ 0x16ee, 0x16f8,
+ 0x1700, 0x1713,
+ 0x171f, 0x1733,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17b3,
+ 0x17b6, 0x17c8,
+ 0x17d7, 0x17d7,
+ 0x17dc, 0x17dc,
+ 0x17e0, 0x17e9,
+ 0x1810, 0x1819,
+ 0x1820, 0x1878,
+ 0x1880, 0x18aa,
+ 0x18b0, 0x18f5,
+ 0x1900, 0x191e,
+ 0x1920, 0x192b,
+ 0x1930, 0x1938,
+ 0x1946, 0x196d,
+ 0x1970, 0x1974,
+ 0x1980, 0x19ab,
+ 0x19b0, 0x19c9,
+ 0x19d0, 0x19d9,
+ 0x1a00, 0x1a1b,
+ 0x1a20, 0x1a5e,
+ 0x1a61, 0x1a74,
+ 0x1a80, 0x1a89,
+ 0x1a90, 0x1a99,
+ 0x1aa7, 0x1aa7,
+ 0x1abf, 0x1ac0,
+ 0x1acc, 0x1ace,
+ 0x1b00, 0x1b33,
+ 0x1b35, 0x1b43,
+ 0x1b45, 0x1b4c,
+ 0x1b50, 0x1b59,
+ 0x1b80, 0x1ba9,
+ 0x1bac, 0x1be5,
+ 0x1be7, 0x1bf1,
+ 0x1c00, 0x1c36,
+ 0x1c40, 0x1c49,
+ 0x1c4d, 0x1c7d,
+ 0x1c80, 0x1c8a,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cbf,
+ 0x1ce9, 0x1cec,
+ 0x1cee, 0x1cf3,
+ 0x1cf5, 0x1cf6,
+ 0x1cfa, 0x1cfa,
+ 0x1d00, 0x1dbf,
+ 0x1dd3, 0x1df4,
+ 0x1e00, 0x1f15,
+ 0x1f18, 0x1f1d,
+ 0x1f20, 0x1f45,
+ 0x1f48, 0x1f4d,
+ 0x1f50, 0x1f57,
+ 0x1f59, 0x1f59,
+ 0x1f5b, 0x1f5b,
+ 0x1f5d, 0x1f5d,
+ 0x1f5f, 0x1f7d,
+ 0x1f80, 0x1fb4,
+ 0x1fb6, 0x1fbc,
+ 0x1fbe, 0x1fbe,
+ 0x1fc2, 0x1fc4,
+ 0x1fc6, 0x1fcc,
+ 0x1fd0, 0x1fd3,
+ 0x1fd6, 0x1fdb,
+ 0x1fe0, 0x1fec,
+ 0x1ff2, 0x1ff4,
+ 0x1ff6, 0x1ffc,
+ 0x2071, 0x2071,
+ 0x207f, 0x207f,
+ 0x2090, 0x209c,
+ 0x2102, 0x2102,
+ 0x2107, 0x2107,
+ 0x210a, 0x2113,
+ 0x2115, 0x2115,
+ 0x2119, 0x211d,
+ 0x2124, 0x2124,
+ 0x2126, 0x2126,
+ 0x2128, 0x2128,
+ 0x212a, 0x212d,
+ 0x212f, 0x2139,
+ 0x213c, 0x213f,
+ 0x2145, 0x2149,
+ 0x214e, 0x214e,
+ 0x2160, 0x2188,
+ 0x24b6, 0x24e9,
+ 0x2c00, 0x2ce4,
+ 0x2ceb, 0x2cee,
+ 0x2cf2, 0x2cf3,
+ 0x2d00, 0x2d25,
+ 0x2d27, 0x2d27,
+ 0x2d2d, 0x2d2d,
+ 0x2d30, 0x2d67,
+ 0x2d6f, 0x2d6f,
+ 0x2d80, 0x2d96,
+ 0x2da0, 0x2da6,
+ 0x2da8, 0x2dae,
+ 0x2db0, 0x2db6,
+ 0x2db8, 0x2dbe,
+ 0x2dc0, 0x2dc6,
+ 0x2dc8, 0x2dce,
+ 0x2dd0, 0x2dd6,
+ 0x2dd8, 0x2dde,
+ 0x2de0, 0x2dff,
+ 0x2e2f, 0x2e2f,
+ 0x3005, 0x3007,
+ 0x3021, 0x3029,
+ 0x3031, 0x3035,
+ 0x3038, 0x303c,
+ 0x3041, 0x3096,
+ 0x309d, 0x309f,
+ 0x30a1, 0x30fa,
+ 0x30fc, 0x30ff,
+ 0x3105, 0x312f,
+ 0x3131, 0x318e,
+ 0x31a0, 0x31bf,
+ 0x31f0, 0x31ff,
+ 0x3400, 0x4dbf,
+ 0x4e00, 0xa48c,
+ 0xa4d0, 0xa4fd,
+ 0xa500, 0xa60c,
+ 0xa610, 0xa62b,
+ 0xa640, 0xa66e,
+ 0xa674, 0xa67b,
+ 0xa67f, 0xa6ef,
+ 0xa717, 0xa71f,
+ 0xa722, 0xa788,
+ 0xa78b, 0xa7dc,
+ 0xa7f1, 0xa805,
+ 0xa807, 0xa827,
+ 0xa840, 0xa873,
+ 0xa880, 0xa8c3,
+ 0xa8c5, 0xa8c5,
+ 0xa8d0, 0xa8d9,
+ 0xa8f2, 0xa8f7,
+ 0xa8fb, 0xa8fb,
+ 0xa8fd, 0xa92a,
+ 0xa930, 0xa952,
+ 0xa960, 0xa97c,
+ 0xa980, 0xa9b2,
+ 0xa9b4, 0xa9bf,
+ 0xa9cf, 0xa9d9,
+ 0xa9e0, 0xa9fe,
+ 0xaa00, 0xaa36,
+ 0xaa40, 0xaa4d,
+ 0xaa50, 0xaa59,
+ 0xaa60, 0xaa76,
+ 0xaa7a, 0xaabe,
+ 0xaac0, 0xaac0,
+ 0xaac2, 0xaac2,
+ 0xaadb, 0xaadd,
+ 0xaae0, 0xaaef,
+ 0xaaf2, 0xaaf5,
+ 0xab01, 0xab06,
+ 0xab09, 0xab0e,
+ 0xab11, 0xab16,
+ 0xab20, 0xab26,
+ 0xab28, 0xab2e,
+ 0xab30, 0xab5a,
+ 0xab5c, 0xab69,
+ 0xab70, 0xabea,
+ 0xabf0, 0xabf9,
+ 0xac00, 0xd7a3,
+ 0xd7b0, 0xd7c6,
+ 0xd7cb, 0xd7fb,
+ 0xf900, 0xfa6d,
+ 0xfa70, 0xfad9,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xfb1d, 0xfb28,
+ 0xfb2a, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfbb1,
+ 0xfbd3, 0xfd3d,
+ 0xfd50, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdf0, 0xfdfb,
+ 0xfe70, 0xfe74,
+ 0xfe76, 0xfefc,
+ 0xff10, 0xff19,
+ 0xff21, 0xff3a,
+ 0xff41, 0xff5a,
+ 0xff66, 0xffbe,
+ 0xffc2, 0xffc7,
+ 0xffca, 0xffcf,
+ 0xffd2, 0xffd7,
+ 0xffda, 0xffdc,
+ 0x10000, 0x1000b,
+ 0x1000d, 0x10026,
+ 0x10028, 0x1003a,
+ 0x1003c, 0x1003d,
+ 0x1003f, 0x1004d,
+ 0x10050, 0x1005d,
+ 0x10080, 0x100fa,
+ 0x10140, 0x10174,
+ 0x10280, 0x1029c,
+ 0x102a0, 0x102d0,
+ 0x10300, 0x1031f,
+ 0x1032d, 0x1034a,
+ 0x10350, 0x1037a,
+ 0x10380, 0x1039d,
+ 0x103a0, 0x103c3,
+ 0x103c8, 0x103cf,
+ 0x103d1, 0x103d5,
+ 0x10400, 0x1049d,
+ 0x104a0, 0x104a9,
+ 0x104b0, 0x104d3,
+ 0x104d8, 0x104fb,
+ 0x10500, 0x10527,
+ 0x10530, 0x10563,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x105c0, 0x105f3,
+ 0x10600, 0x10736,
+ 0x10740, 0x10755,
+ 0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 0x10837, 0x10838,
+ 0x1083c, 0x1083c,
+ 0x1083f, 0x10855,
+ 0x10860, 0x10876,
+ 0x10880, 0x1089e,
+ 0x108e0, 0x108f2,
+ 0x108f4, 0x108f5,
+ 0x10900, 0x10915,
+ 0x10920, 0x10939,
+ 0x10940, 0x10959,
+ 0x10980, 0x109b7,
+ 0x109be, 0x109bf,
+ 0x10a00, 0x10a03,
+ 0x10a05, 0x10a06,
+ 0x10a0c, 0x10a13,
+ 0x10a15, 0x10a17,
+ 0x10a19, 0x10a35,
+ 0x10a60, 0x10a7c,
+ 0x10a80, 0x10a9c,
+ 0x10ac0, 0x10ac7,
+ 0x10ac9, 0x10ae4,
+ 0x10b00, 0x10b35,
+ 0x10b40, 0x10b55,
+ 0x10b60, 0x10b72,
+ 0x10b80, 0x10b91,
+ 0x10c00, 0x10c48,
+ 0x10c80, 0x10cb2,
+ 0x10cc0, 0x10cf2,
+ 0x10d00, 0x10d27,
+ 0x10d30, 0x10d39,
+ 0x10d40, 0x10d65,
+ 0x10d69, 0x10d69,
+ 0x10d6f, 0x10d85,
+ 0x10e80, 0x10ea9,
+ 0x10eab, 0x10eac,
+ 0x10eb0, 0x10eb1,
+ 0x10ec2, 0x10ec7,
+ 0x10efa, 0x10efc,
+ 0x10f00, 0x10f1c,
+ 0x10f27, 0x10f27,
+ 0x10f30, 0x10f45,
+ 0x10f70, 0x10f81,
+ 0x10fb0, 0x10fc4,
+ 0x10fe0, 0x10ff6,
+ 0x11000, 0x11045,
+ 0x11066, 0x1106f,
+ 0x11071, 0x11075,
+ 0x11080, 0x110b8,
+ 0x110c2, 0x110c2,
+ 0x110d0, 0x110e8,
+ 0x110f0, 0x110f9,
+ 0x11100, 0x11132,
+ 0x11136, 0x1113f,
+ 0x11144, 0x11147,
+ 0x11150, 0x11172,
+ 0x11176, 0x11176,
+ 0x11180, 0x111bf,
+ 0x111c1, 0x111c4,
+ 0x111ce, 0x111da,
+ 0x111dc, 0x111dc,
+ 0x11200, 0x11211,
+ 0x11213, 0x11234,
+ 0x11237, 0x11237,
+ 0x1123e, 0x11241,
+ 0x11280, 0x11286,
+ 0x11288, 0x11288,
+ 0x1128a, 0x1128d,
+ 0x1128f, 0x1129d,
+ 0x1129f, 0x112a8,
+ 0x112b0, 0x112e8,
+ 0x112f0, 0x112f9,
+ 0x11300, 0x11303,
+ 0x11305, 0x1130c,
+ 0x1130f, 0x11310,
+ 0x11313, 0x11328,
+ 0x1132a, 0x11330,
+ 0x11332, 0x11333,
+ 0x11335, 0x11339,
+ 0x1133d, 0x11344,
+ 0x11347, 0x11348,
+ 0x1134b, 0x1134c,
+ 0x11350, 0x11350,
+ 0x11357, 0x11357,
+ 0x1135d, 0x11363,
+ 0x11380, 0x11389,
+ 0x1138b, 0x1138b,
+ 0x1138e, 0x1138e,
+ 0x11390, 0x113b5,
+ 0x113b7, 0x113c0,
+ 0x113c2, 0x113c2,
+ 0x113c5, 0x113c5,
+ 0x113c7, 0x113ca,
+ 0x113cc, 0x113cd,
+ 0x113d1, 0x113d1,
+ 0x113d3, 0x113d3,
+ 0x11400, 0x11441,
+ 0x11443, 0x11445,
+ 0x11447, 0x1144a,
+ 0x11450, 0x11459,
+ 0x1145f, 0x11461,
+ 0x11480, 0x114c1,
+ 0x114c4, 0x114c5,
+ 0x114c7, 0x114c7,
+ 0x114d0, 0x114d9,
+ 0x11580, 0x115b5,
+ 0x115b8, 0x115be,
+ 0x115d8, 0x115dd,
+ 0x11600, 0x1163e,
+ 0x11640, 0x11640,
+ 0x11644, 0x11644,
+ 0x11650, 0x11659,
+ 0x11680, 0x116b5,
+ 0x116b8, 0x116b8,
+ 0x116c0, 0x116c9,
+ 0x116d0, 0x116e3,
+ 0x11700, 0x1171a,
+ 0x1171d, 0x1172a,
+ 0x11730, 0x11739,
+ 0x11740, 0x11746,
+ 0x11800, 0x11838,
+ 0x118a0, 0x118e9,
+ 0x118ff, 0x11906,
+ 0x11909, 0x11909,
+ 0x1190c, 0x11913,
+ 0x11915, 0x11916,
+ 0x11918, 0x11935,
+ 0x11937, 0x11938,
+ 0x1193b, 0x1193c,
+ 0x1193f, 0x11942,
+ 0x11950, 0x11959,
+ 0x119a0, 0x119a7,
+ 0x119aa, 0x119d7,
+ 0x119da, 0x119df,
+ 0x119e1, 0x119e1,
+ 0x119e3, 0x119e4,
+ 0x11a00, 0x11a32,
+ 0x11a35, 0x11a3e,
+ 0x11a50, 0x11a97,
+ 0x11a9d, 0x11a9d,
+ 0x11ab0, 0x11af8,
+ 0x11b60, 0x11b67,
+ 0x11bc0, 0x11be0,
+ 0x11bf0, 0x11bf9,
+ 0x11c00, 0x11c08,
+ 0x11c0a, 0x11c36,
+ 0x11c38, 0x11c3e,
+ 0x11c40, 0x11c40,
+ 0x11c50, 0x11c59,
+ 0x11c72, 0x11c8f,
+ 0x11c92, 0x11ca7,
+ 0x11ca9, 0x11cb6,
+ 0x11d00, 0x11d06,
+ 0x11d08, 0x11d09,
+ 0x11d0b, 0x11d36,
+ 0x11d3a, 0x11d3a,
+ 0x11d3c, 0x11d3d,
+ 0x11d3f, 0x11d41,
+ 0x11d43, 0x11d43,
+ 0x11d46, 0x11d47,
+ 0x11d50, 0x11d59,
+ 0x11d60, 0x11d65,
+ 0x11d67, 0x11d68,
+ 0x11d6a, 0x11d8e,
+ 0x11d90, 0x11d91,
+ 0x11d93, 0x11d96,
+ 0x11d98, 0x11d98,
+ 0x11da0, 0x11da9,
+ 0x11db0, 0x11ddb,
+ 0x11de0, 0x11de9,
+ 0x11ee0, 0x11ef6,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f40,
+ 0x11f50, 0x11f59,
+ 0x11fb0, 0x11fb0,
+ 0x12000, 0x12399,
+ 0x12400, 0x1246e,
+ 0x12480, 0x12543,
+ 0x12f90, 0x12ff0,
+ 0x13000, 0x1342f,
+ 0x13441, 0x13446,
+ 0x13460, 0x143fa,
+ 0x14400, 0x14646,
+ 0x16100, 0x1612e,
+ 0x16130, 0x16139,
+ 0x16800, 0x16a38,
+ 0x16a40, 0x16a5e,
+ 0x16a60, 0x16a69,
+ 0x16a70, 0x16abe,
+ 0x16ac0, 0x16ac9,
+ 0x16ad0, 0x16aed,
+ 0x16b00, 0x16b2f,
+ 0x16b40, 0x16b43,
+ 0x16b50, 0x16b59,
+ 0x16b63, 0x16b77,
+ 0x16b7d, 0x16b8f,
+ 0x16d40, 0x16d6c,
+ 0x16d70, 0x16d79,
+ 0x16e40, 0x16e7f,
+ 0x16ea0, 0x16eb8,
+ 0x16ebb, 0x16ed3,
+ 0x16f00, 0x16f4a,
+ 0x16f4f, 0x16f87,
+ 0x16f8f, 0x16f9f,
+ 0x16fe0, 0x16fe1,
+ 0x16fe3, 0x16fe3,
+ 0x16ff0, 0x16ff6,
+ 0x17000, 0x18cd5,
+ 0x18cff, 0x18d1e,
+ 0x18d80, 0x18df2,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
+ 0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
+ 0x1b164, 0x1b167,
+ 0x1b170, 0x1b2fb,
+ 0x1bc00, 0x1bc6a,
+ 0x1bc70, 0x1bc7c,
+ 0x1bc80, 0x1bc88,
+ 0x1bc90, 0x1bc99,
+ 0x1bc9e, 0x1bc9e,
+ 0x1ccf0, 0x1ccf9,
+ 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, 0x1d6c0,
+ 0x1d6c2, 0x1d6da,
+ 0x1d6dc, 0x1d6fa,
+ 0x1d6fc, 0x1d714,
+ 0x1d716, 0x1d734,
+ 0x1d736, 0x1d74e,
+ 0x1d750, 0x1d76e,
+ 0x1d770, 0x1d788,
+ 0x1d78a, 0x1d7a8,
+ 0x1d7aa, 0x1d7c2,
+ 0x1d7c4, 0x1d7cb,
+ 0x1d7ce, 0x1d7ff,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e000, 0x1e006,
+ 0x1e008, 0x1e018,
+ 0x1e01b, 0x1e021,
+ 0x1e023, 0x1e024,
+ 0x1e026, 0x1e02a,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
+ 0x1e100, 0x1e12c,
+ 0x1e137, 0x1e13d,
+ 0x1e140, 0x1e149,
+ 0x1e14e, 0x1e14e,
+ 0x1e290, 0x1e2ad,
+ 0x1e2c0, 0x1e2eb,
+ 0x1e2f0, 0x1e2f9,
+ 0x1e4d0, 0x1e4eb,
+ 0x1e4f0, 0x1e4f9,
+ 0x1e5d0, 0x1e5ed,
+ 0x1e5f0, 0x1e5fa,
+ 0x1e6c0, 0x1e6de,
+ 0x1e6e0, 0x1e6f5,
+ 0x1e6fe, 0x1e6ff,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
+ 0x1e800, 0x1e8c4,
+ 0x1e900, 0x1e943,
+ 0x1e947, 0x1e947,
+ 0x1e94b, 0x1e94b,
+ 0x1e950, 0x1e959,
+ 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,
+ 0x1f130, 0x1f149,
+ 0x1f150, 0x1f169,
+ 0x1f170, 0x1f189,
+ 0x1fbf0, 0x1fbf9,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b81d,
+ 0x2b820, 0x2cead,
+ 0x2ceb0, 0x2ebe0,
+ 0x2ebf0, 0x2ee5d,
+ 0x2f800, 0x2fa1d,
+ 0x30000, 0x3134a,
+ 0x31350, 0x33479,
+}; /* CR_Alnum */
+
+/* 'ASCII': [[:ASCII:]] */
+static const OnigCodePoint CR_ASCII[] = {
+ 1,
+ 0x0000, 0x007f,
+}; /* CR_ASCII */
+
+/* 'Punct': [[:Punct:]] */
+static const OnigCodePoint CR_Punct[] = {
+ 199,
+ 0x0021, 0x0023,
+ 0x0025, 0x002a,
+ 0x002c, 0x002f,
+ 0x003a, 0x003b,
+ 0x003f, 0x0040,
+ 0x005b, 0x005d,
+ 0x005f, 0x005f,
+ 0x007b, 0x007b,
+ 0x007d, 0x007d,
+ 0x00a1, 0x00a1,
+ 0x00a7, 0x00a7,
+ 0x00ab, 0x00ab,
+ 0x00b6, 0x00b7,
+ 0x00bb, 0x00bb,
+ 0x00bf, 0x00bf,
+ 0x037e, 0x037e,
+ 0x0387, 0x0387,
+ 0x055a, 0x055f,
+ 0x0589, 0x058a,
+ 0x05be, 0x05be,
+ 0x05c0, 0x05c0,
+ 0x05c3, 0x05c3,
+ 0x05c6, 0x05c6,
+ 0x05f3, 0x05f4,
+ 0x0609, 0x060a,
+ 0x060c, 0x060d,
+ 0x061b, 0x061b,
+ 0x061d, 0x061f,
+ 0x066a, 0x066d,
+ 0x06d4, 0x06d4,
+ 0x0700, 0x070d,
+ 0x07f7, 0x07f9,
+ 0x0830, 0x083e,
+ 0x085e, 0x085e,
+ 0x0964, 0x0965,
+ 0x0970, 0x0970,
+ 0x09fd, 0x09fd,
+ 0x0a76, 0x0a76,
+ 0x0af0, 0x0af0,
+ 0x0c77, 0x0c77,
+ 0x0c84, 0x0c84,
+ 0x0df4, 0x0df4,
+ 0x0e4f, 0x0e4f,
+ 0x0e5a, 0x0e5b,
+ 0x0f04, 0x0f12,
+ 0x0f14, 0x0f14,
+ 0x0f3a, 0x0f3d,
+ 0x0f85, 0x0f85,
+ 0x0fd0, 0x0fd4,
+ 0x0fd9, 0x0fda,
+ 0x104a, 0x104f,
+ 0x10fb, 0x10fb,
+ 0x1360, 0x1368,
+ 0x1400, 0x1400,
+ 0x166e, 0x166e,
+ 0x169b, 0x169c,
+ 0x16eb, 0x16ed,
+ 0x1735, 0x1736,
+ 0x17d4, 0x17d6,
+ 0x17d8, 0x17da,
+ 0x1800, 0x180a,
+ 0x1944, 0x1945,
+ 0x1a1e, 0x1a1f,
+ 0x1aa0, 0x1aa6,
+ 0x1aa8, 0x1aad,
+ 0x1b4e, 0x1b4f,
+ 0x1b5a, 0x1b60,
+ 0x1b7d, 0x1b7f,
+ 0x1bfc, 0x1bff,
+ 0x1c3b, 0x1c3f,
+ 0x1c7e, 0x1c7f,
+ 0x1cc0, 0x1cc7,
+ 0x1cd3, 0x1cd3,
+ 0x2010, 0x2027,
+ 0x2030, 0x2043,
+ 0x2045, 0x2051,
+ 0x2053, 0x205e,
+ 0x207d, 0x207e,
+ 0x208d, 0x208e,
+ 0x2308, 0x230b,
+ 0x2329, 0x232a,
+ 0x2768, 0x2775,
+ 0x27c5, 0x27c6,
+ 0x27e6, 0x27ef,
+ 0x2983, 0x2998,
+ 0x29d8, 0x29db,
+ 0x29fc, 0x29fd,
+ 0x2cf9, 0x2cfc,
+ 0x2cfe, 0x2cff,
+ 0x2d70, 0x2d70,
+ 0x2e00, 0x2e2e,
+ 0x2e30, 0x2e4f,
+ 0x2e52, 0x2e5d,
+ 0x3001, 0x3003,
+ 0x3008, 0x3011,
+ 0x3014, 0x301f,
+ 0x3030, 0x3030,
+ 0x303d, 0x303d,
+ 0x30a0, 0x30a0,
+ 0x30fb, 0x30fb,
+ 0xa4fe, 0xa4ff,
+ 0xa60d, 0xa60f,
+ 0xa673, 0xa673,
+ 0xa67e, 0xa67e,
+ 0xa6f2, 0xa6f7,
+ 0xa874, 0xa877,
+ 0xa8ce, 0xa8cf,
+ 0xa8f8, 0xa8fa,
+ 0xa8fc, 0xa8fc,
+ 0xa92e, 0xa92f,
+ 0xa95f, 0xa95f,
+ 0xa9c1, 0xa9cd,
+ 0xa9de, 0xa9df,
+ 0xaa5c, 0xaa5f,
+ 0xaade, 0xaadf,
+ 0xaaf0, 0xaaf1,
+ 0xabeb, 0xabeb,
+ 0xfd3e, 0xfd3f,
+ 0xfe10, 0xfe19,
+ 0xfe30, 0xfe52,
+ 0xfe54, 0xfe61,
+ 0xfe63, 0xfe63,
+ 0xfe68, 0xfe68,
+ 0xfe6a, 0xfe6b,
+ 0xff01, 0xff03,
+ 0xff05, 0xff0a,
+ 0xff0c, 0xff0f,
+ 0xff1a, 0xff1b,
+ 0xff1f, 0xff20,
+ 0xff3b, 0xff3d,
+ 0xff3f, 0xff3f,
+ 0xff5b, 0xff5b,
+ 0xff5d, 0xff5d,
+ 0xff5f, 0xff65,
+ 0x10100, 0x10102,
+ 0x1039f, 0x1039f,
+ 0x103d0, 0x103d0,
+ 0x1056f, 0x1056f,
+ 0x10857, 0x10857,
+ 0x1091f, 0x1091f,
+ 0x1093f, 0x1093f,
+ 0x10a50, 0x10a58,
+ 0x10a7f, 0x10a7f,
+ 0x10af0, 0x10af6,
+ 0x10b39, 0x10b3f,
+ 0x10b99, 0x10b9c,
+ 0x10d6e, 0x10d6e,
+ 0x10ead, 0x10ead,
+ 0x10ed0, 0x10ed0,
+ 0x10f55, 0x10f59,
+ 0x10f86, 0x10f89,
+ 0x11047, 0x1104d,
+ 0x110bb, 0x110bc,
+ 0x110be, 0x110c1,
+ 0x11140, 0x11143,
+ 0x11174, 0x11175,
+ 0x111c5, 0x111c8,
+ 0x111cd, 0x111cd,
+ 0x111db, 0x111db,
+ 0x111dd, 0x111df,
+ 0x11238, 0x1123d,
+ 0x112a9, 0x112a9,
+ 0x113d4, 0x113d5,
+ 0x113d7, 0x113d8,
+ 0x1144b, 0x1144f,
+ 0x1145a, 0x1145b,
+ 0x1145d, 0x1145d,
+ 0x114c6, 0x114c6,
+ 0x115c1, 0x115d7,
+ 0x11641, 0x11643,
+ 0x11660, 0x1166c,
+ 0x116b9, 0x116b9,
+ 0x1173c, 0x1173e,
+ 0x1183b, 0x1183b,
+ 0x11944, 0x11946,
+ 0x119e2, 0x119e2,
+ 0x11a3f, 0x11a46,
+ 0x11a9a, 0x11a9c,
+ 0x11a9e, 0x11aa2,
+ 0x11b00, 0x11b09,
+ 0x11be1, 0x11be1,
+ 0x11c41, 0x11c45,
+ 0x11c70, 0x11c71,
+ 0x11ef7, 0x11ef8,
+ 0x11f43, 0x11f4f,
+ 0x11fff, 0x11fff,
+ 0x12470, 0x12474,
+ 0x12ff1, 0x12ff2,
+ 0x16a6e, 0x16a6f,
+ 0x16af5, 0x16af5,
+ 0x16b37, 0x16b3b,
+ 0x16b44, 0x16b44,
+ 0x16d6d, 0x16d6f,
+ 0x16e97, 0x16e9a,
+ 0x16fe2, 0x16fe2,
+ 0x1bc9f, 0x1bc9f,
+ 0x1da87, 0x1da8b,
+ 0x1e5ff, 0x1e5ff,
+ 0x1e95e, 0x1e95f,
+}; /* CR_Punct */
+
+#ifdef USE_UNICODE_PROPERTIES
+/* 'Any': - */
+static const OnigCodePoint CR_Any[] = {
+ 1,
+ 0x0000, 0x10ffff,
+}; /* CR_Any */
+
+/* 'Assigned': - */
+static const OnigCodePoint CR_Assigned[] = {
+ 735,
+ 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, 0x070d,
+ 0x070f, 0x074a,
+ 0x074d, 0x07b1,
+ 0x07c0, 0x07fa,
+ 0x07fd, 0x082d,
+ 0x0830, 0x083e,
+ 0x0840, 0x085b,
+ 0x085e, 0x085e,
+ 0x0860, 0x086a,
+ 0x0870, 0x0891,
+ 0x0897, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fe,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 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,
+ 0x0be6, 0x0bfa,
+ 0x0c00, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3c, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c5a,
+ 0x0c5c, 0x0c5d,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c77, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cdc, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf3,
+ 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, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 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, 0x0ece,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 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, 0x1715,
+ 0x171f, 0x1736,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x1800, 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, 0x1add,
+ 0x1ae0, 0x1aeb,
+ 0x1b00, 0x1b4c,
+ 0x1b4e, 0x1bf3,
+ 0x1bfc, 0x1c37,
+ 0x1c3b, 0x1c49,
+ 0x1c4d, 0x1c8a,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cc7,
+ 0x1cd0, 0x1cfa,
+ 0x1d00, 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, 0x20c1,
+ 0x20d0, 0x20f0,
+ 0x2100, 0x218b,
+ 0x2190, 0x2429,
+ 0x2440, 0x244a,
+ 0x2460, 0x2b73,
+ 0x2b76, 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, 0x2e5d,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312f,
+ 0x3131, 0x318e,
+ 0x3190, 0x31e5,
+ 0x31ef, 0x321e,
+ 0x3220, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa4d0, 0xa62b,
+ 0xa640, 0xa6f7,
+ 0xa700, 0xa7dc,
+ 0xa7f1, 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, 0xfdcf,
+ 0xfdf0, 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, 0xfffd,
+ 0x10000, 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, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x105c0, 0x105f3,
+ 0x10600, 0x10736,
+ 0x10740, 0x10755,
+ 0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 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, 0x10959,
+ 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,
+ 0x10d40, 0x10d65,
+ 0x10d69, 0x10d85,
+ 0x10d8e, 0x10d8f,
+ 0x10e60, 0x10e7e,
+ 0x10e80, 0x10ea9,
+ 0x10eab, 0x10ead,
+ 0x10eb0, 0x10eb1,
+ 0x10ec2, 0x10ec7,
+ 0x10ed0, 0x10ed8,
+ 0x10efa, 0x10f27,
+ 0x10f30, 0x10f59,
+ 0x10f70, 0x10f89,
+ 0x10fb0, 0x10fcb,
+ 0x10fe0, 0x10ff6,
+ 0x11000, 0x1104d,
+ 0x11052, 0x11075,
+ 0x1107f, 0x110c2,
+ 0x110cd, 0x110cd,
+ 0x110d0, 0x110e8,
+ 0x110f0, 0x110f9,
+ 0x11100, 0x11134,
+ 0x11136, 0x11147,
+ 0x11150, 0x11176,
+ 0x11180, 0x111df,
+ 0x111e1, 0x111f4,
+ 0x11200, 0x11211,
+ 0x11213, 0x11241,
+ 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,
+ 0x11380, 0x11389,
+ 0x1138b, 0x1138b,
+ 0x1138e, 0x1138e,
+ 0x11390, 0x113b5,
+ 0x113b7, 0x113c0,
+ 0x113c2, 0x113c2,
+ 0x113c5, 0x113c5,
+ 0x113c7, 0x113ca,
+ 0x113cc, 0x113d5,
+ 0x113d7, 0x113d8,
+ 0x113e1, 0x113e2,
+ 0x11400, 0x1145b,
+ 0x1145d, 0x11461,
+ 0x11480, 0x114c7,
+ 0x114d0, 0x114d9,
+ 0x11580, 0x115b5,
+ 0x115b8, 0x115dd,
+ 0x11600, 0x11644,
+ 0x11650, 0x11659,
+ 0x11660, 0x1166c,
+ 0x11680, 0x116b9,
+ 0x116c0, 0x116c9,
+ 0x116d0, 0x116e3,
+ 0x11700, 0x1171a,
+ 0x1171d, 0x1172b,
+ 0x11730, 0x11746,
+ 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,
+ 0x11ab0, 0x11af8,
+ 0x11b00, 0x11b09,
+ 0x11b60, 0x11b67,
+ 0x11bc0, 0x11be1,
+ 0x11bf0, 0x11bf9,
+ 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,
+ 0x11db0, 0x11ddb,
+ 0x11de0, 0x11de9,
+ 0x11ee0, 0x11ef8,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f5a,
+ 0x11fb0, 0x11fb0,
+ 0x11fc0, 0x11ff1,
+ 0x11fff, 0x12399,
+ 0x12400, 0x1246e,
+ 0x12470, 0x12474,
+ 0x12480, 0x12543,
+ 0x12f90, 0x12ff2,
+ 0x13000, 0x13455,
+ 0x13460, 0x143fa,
+ 0x14400, 0x14646,
+ 0x16100, 0x16139,
+ 0x16800, 0x16a38,
+ 0x16a40, 0x16a5e,
+ 0x16a60, 0x16a69,
+ 0x16a6e, 0x16abe,
+ 0x16ac0, 0x16ac9,
+ 0x16ad0, 0x16aed,
+ 0x16af0, 0x16af5,
+ 0x16b00, 0x16b45,
+ 0x16b50, 0x16b59,
+ 0x16b5b, 0x16b61,
+ 0x16b63, 0x16b77,
+ 0x16b7d, 0x16b8f,
+ 0x16d40, 0x16d79,
+ 0x16e40, 0x16e9a,
+ 0x16ea0, 0x16eb8,
+ 0x16ebb, 0x16ed3,
+ 0x16f00, 0x16f4a,
+ 0x16f4f, 0x16f87,
+ 0x16f8f, 0x16f9f,
+ 0x16fe0, 0x16fe4,
+ 0x16ff0, 0x16ff6,
+ 0x17000, 0x18cd5,
+ 0x18cff, 0x18d1e,
+ 0x18d80, 0x18df2,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
+ 0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
+ 0x1b164, 0x1b167,
+ 0x1b170, 0x1b2fb,
+ 0x1bc00, 0x1bc6a,
+ 0x1bc70, 0x1bc7c,
+ 0x1bc80, 0x1bc88,
+ 0x1bc90, 0x1bc99,
+ 0x1bc9c, 0x1bca3,
+ 0x1cc00, 0x1ccfc,
+ 0x1cd00, 0x1ceb3,
+ 0x1ceba, 0x1ced0,
+ 0x1cee0, 0x1cef0,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
+ 0x1cf50, 0x1cfc3,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d129, 0x1d1ea,
+ 0x1d200, 0x1d245,
+ 0x1d2c0, 0x1d2d3,
+ 0x1d2e0, 0x1d2f3,
+ 0x1d300, 0x1d356,
+ 0x1d360, 0x1d378,
+ 0x1d400, 0x1d454,
+ 0x1d456, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 0x1d4a2, 0x1d4a2,
+ 0x1d4a5, 0x1d4a6,
+ 0x1d4a9, 0x1d4ac,
+ 0x1d4ae, 0x1d4b9,
+ 0x1d4bb, 0x1d4bb,
+ 0x1d4bd, 0x1d4c3,
+ 0x1d4c5, 0x1d505,
+ 0x1d507, 0x1d50a,
+ 0x1d50d, 0x1d514,
+ 0x1d516, 0x1d51c,
+ 0x1d51e, 0x1d539,
+ 0x1d53b, 0x1d53e,
+ 0x1d540, 0x1d544,
+ 0x1d546, 0x1d546,
+ 0x1d54a, 0x1d550,
+ 0x1d552, 0x1d6a5,
+ 0x1d6a8, 0x1d7cb,
+ 0x1d7ce, 0x1da8b,
+ 0x1da9b, 0x1da9f,
+ 0x1daa1, 0x1daaf,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e000, 0x1e006,
+ 0x1e008, 0x1e018,
+ 0x1e01b, 0x1e021,
+ 0x1e023, 0x1e024,
+ 0x1e026, 0x1e02a,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
+ 0x1e100, 0x1e12c,
+ 0x1e130, 0x1e13d,
+ 0x1e140, 0x1e149,
+ 0x1e14e, 0x1e14f,
+ 0x1e290, 0x1e2ae,
+ 0x1e2c0, 0x1e2f9,
+ 0x1e2ff, 0x1e2ff,
+ 0x1e4d0, 0x1e4f9,
+ 0x1e5d0, 0x1e5fa,
+ 0x1e5ff, 0x1e5ff,
+ 0x1e6c0, 0x1e6de,
+ 0x1e6e0, 0x1e6f5,
+ 0x1e6fe, 0x1e6ff,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
+ 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, 0x1f6d8,
+ 0x1f6dc, 0x1f6ec,
+ 0x1f6f0, 0x1f6fc,
+ 0x1f700, 0x1f7d9,
+ 0x1f7e0, 0x1f7eb,
+ 0x1f7f0, 0x1f7f0,
+ 0x1f800, 0x1f80b,
+ 0x1f810, 0x1f847,
+ 0x1f850, 0x1f859,
+ 0x1f860, 0x1f887,
+ 0x1f890, 0x1f8ad,
+ 0x1f8b0, 0x1f8bb,
+ 0x1f8c0, 0x1f8c1,
+ 0x1f8d0, 0x1f8d8,
+ 0x1f900, 0x1fa57,
+ 0x1fa60, 0x1fa6d,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa8a,
+ 0x1fa8e, 0x1fac6,
+ 0x1fac8, 0x1fac8,
+ 0x1facd, 0x1fadc,
+ 0x1fadf, 0x1faea,
+ 0x1faef, 0x1faf8,
+ 0x1fb00, 0x1fb92,
+ 0x1fb94, 0x1fbfa,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b81d,
+ 0x2b820, 0x2cead,
+ 0x2ceb0, 0x2ebe0,
+ 0x2ebf0, 0x2ee5d,
+ 0x2f800, 0x2fa1d,
+ 0x30000, 0x3134a,
+ 0x31350, 0x33479,
+ 0xe0001, 0xe0001,
+ 0xe0020, 0xe007f,
+ 0xe0100, 0xe01ef,
+ 0xf0000, 0xffffd,
+ 0x100000, 0x10fffd,
+}; /* CR_Assigned */
+
+/* 'C': Major Category */
+static const OnigCodePoint CR_C[] = {
+ 741,
+ 0x0000, 0x001f,
+ 0x007f, 0x009f,
+ 0x00ad, 0x00ad,
+ 0x0378, 0x0379,
+ 0x0380, 0x0383,
+ 0x038b, 0x038b,
+ 0x038d, 0x038d,
+ 0x03a2, 0x03a2,
+ 0x0530, 0x0530,
+ 0x0557, 0x0558,
+ 0x058b, 0x058c,
+ 0x0590, 0x0590,
+ 0x05c8, 0x05cf,
+ 0x05eb, 0x05ee,
+ 0x05f5, 0x0605,
+ 0x061c, 0x061c,
+ 0x06dd, 0x06dd,
+ 0x070e, 0x070f,
+ 0x074b, 0x074c,
+ 0x07b2, 0x07bf,
+ 0x07fb, 0x07fc,
+ 0x082e, 0x082f,
+ 0x083f, 0x083f,
+ 0x085c, 0x085d,
+ 0x085f, 0x085f,
+ 0x086b, 0x086f,
+ 0x0890, 0x0896,
+ 0x08e2, 0x08e2,
+ 0x0984, 0x0984,
+ 0x098d, 0x098e,
+ 0x0991, 0x0992,
+ 0x09a9, 0x09a9,
+ 0x09b1, 0x09b1,
+ 0x09b3, 0x09b5,
+ 0x09ba, 0x09bb,
+ 0x09c5, 0x09c6,
+ 0x09c9, 0x09ca,
+ 0x09cf, 0x09d6,
+ 0x09d8, 0x09db,
+ 0x09de, 0x09de,
+ 0x09e4, 0x09e5,
+ 0x09ff, 0x0a00,
+ 0x0a04, 0x0a04,
+ 0x0a0b, 0x0a0e,
+ 0x0a11, 0x0a12,
+ 0x0a29, 0x0a29,
+ 0x0a31, 0x0a31,
+ 0x0a34, 0x0a34,
+ 0x0a37, 0x0a37,
+ 0x0a3a, 0x0a3b,
+ 0x0a3d, 0x0a3d,
+ 0x0a43, 0x0a46,
+ 0x0a49, 0x0a4a,
+ 0x0a4e, 0x0a50,
+ 0x0a52, 0x0a58,
+ 0x0a5d, 0x0a5d,
+ 0x0a5f, 0x0a65,
+ 0x0a77, 0x0a80,
+ 0x0a84, 0x0a84,
+ 0x0a8e, 0x0a8e,
+ 0x0a92, 0x0a92,
+ 0x0aa9, 0x0aa9,
+ 0x0ab1, 0x0ab1,
+ 0x0ab4, 0x0ab4,
+ 0x0aba, 0x0abb,
+ 0x0ac6, 0x0ac6,
+ 0x0aca, 0x0aca,
+ 0x0ace, 0x0acf,
+ 0x0ad1, 0x0adf,
+ 0x0ae4, 0x0ae5,
+ 0x0af2, 0x0af8,
+ 0x0b00, 0x0b00,
+ 0x0b04, 0x0b04,
+ 0x0b0d, 0x0b0e,
+ 0x0b11, 0x0b12,
+ 0x0b29, 0x0b29,
+ 0x0b31, 0x0b31,
+ 0x0b34, 0x0b34,
+ 0x0b3a, 0x0b3b,
+ 0x0b45, 0x0b46,
+ 0x0b49, 0x0b4a,
+ 0x0b4e, 0x0b54,
+ 0x0b58, 0x0b5b,
+ 0x0b5e, 0x0b5e,
+ 0x0b64, 0x0b65,
+ 0x0b78, 0x0b81,
+ 0x0b84, 0x0b84,
+ 0x0b8b, 0x0b8d,
+ 0x0b91, 0x0b91,
+ 0x0b96, 0x0b98,
+ 0x0b9b, 0x0b9b,
+ 0x0b9d, 0x0b9d,
+ 0x0ba0, 0x0ba2,
+ 0x0ba5, 0x0ba7,
+ 0x0bab, 0x0bad,
+ 0x0bba, 0x0bbd,
+ 0x0bc3, 0x0bc5,
+ 0x0bc9, 0x0bc9,
+ 0x0bce, 0x0bcf,
+ 0x0bd1, 0x0bd6,
+ 0x0bd8, 0x0be5,
+ 0x0bfb, 0x0bff,
+ 0x0c0d, 0x0c0d,
+ 0x0c11, 0x0c11,
+ 0x0c29, 0x0c29,
+ 0x0c3a, 0x0c3b,
+ 0x0c45, 0x0c45,
+ 0x0c49, 0x0c49,
+ 0x0c4e, 0x0c54,
+ 0x0c57, 0x0c57,
+ 0x0c5b, 0x0c5b,
+ 0x0c5e, 0x0c5f,
+ 0x0c64, 0x0c65,
+ 0x0c70, 0x0c76,
+ 0x0c8d, 0x0c8d,
+ 0x0c91, 0x0c91,
+ 0x0ca9, 0x0ca9,
+ 0x0cb4, 0x0cb4,
+ 0x0cba, 0x0cbb,
+ 0x0cc5, 0x0cc5,
+ 0x0cc9, 0x0cc9,
+ 0x0cce, 0x0cd4,
+ 0x0cd7, 0x0cdb,
+ 0x0cdf, 0x0cdf,
+ 0x0ce4, 0x0ce5,
+ 0x0cf0, 0x0cf0,
+ 0x0cf4, 0x0cff,
+ 0x0d0d, 0x0d0d,
+ 0x0d11, 0x0d11,
+ 0x0d45, 0x0d45,
+ 0x0d49, 0x0d49,
+ 0x0d50, 0x0d53,
+ 0x0d64, 0x0d65,
+ 0x0d80, 0x0d80,
+ 0x0d84, 0x0d84,
+ 0x0d97, 0x0d99,
+ 0x0db2, 0x0db2,
+ 0x0dbc, 0x0dbc,
+ 0x0dbe, 0x0dbf,
+ 0x0dc7, 0x0dc9,
+ 0x0dcb, 0x0dce,
+ 0x0dd5, 0x0dd5,
+ 0x0dd7, 0x0dd7,
+ 0x0de0, 0x0de5,
+ 0x0df0, 0x0df1,
+ 0x0df5, 0x0e00,
+ 0x0e3b, 0x0e3e,
+ 0x0e5c, 0x0e80,
+ 0x0e83, 0x0e83,
+ 0x0e85, 0x0e85,
+ 0x0e8b, 0x0e8b,
+ 0x0ea4, 0x0ea4,
+ 0x0ea6, 0x0ea6,
+ 0x0ebe, 0x0ebf,
+ 0x0ec5, 0x0ec5,
+ 0x0ec7, 0x0ec7,
+ 0x0ecf, 0x0ecf,
+ 0x0eda, 0x0edb,
+ 0x0ee0, 0x0eff,
+ 0x0f48, 0x0f48,
+ 0x0f6d, 0x0f70,
+ 0x0f98, 0x0f98,
+ 0x0fbd, 0x0fbd,
+ 0x0fcd, 0x0fcd,
+ 0x0fdb, 0x0fff,
+ 0x10c6, 0x10c6,
+ 0x10c8, 0x10cc,
+ 0x10ce, 0x10cf,
+ 0x1249, 0x1249,
+ 0x124e, 0x124f,
+ 0x1257, 0x1257,
+ 0x1259, 0x1259,
+ 0x125e, 0x125f,
+ 0x1289, 0x1289,
+ 0x128e, 0x128f,
+ 0x12b1, 0x12b1,
+ 0x12b6, 0x12b7,
+ 0x12bf, 0x12bf,
+ 0x12c1, 0x12c1,
+ 0x12c6, 0x12c7,
+ 0x12d7, 0x12d7,
+ 0x1311, 0x1311,
+ 0x1316, 0x1317,
+ 0x135b, 0x135c,
+ 0x137d, 0x137f,
+ 0x139a, 0x139f,
+ 0x13f6, 0x13f7,
+ 0x13fe, 0x13ff,
+ 0x169d, 0x169f,
+ 0x16f9, 0x16ff,
+ 0x1716, 0x171e,
+ 0x1737, 0x173f,
+ 0x1754, 0x175f,
+ 0x176d, 0x176d,
+ 0x1771, 0x1771,
+ 0x1774, 0x177f,
+ 0x17de, 0x17df,
+ 0x17ea, 0x17ef,
+ 0x17fa, 0x17ff,
+ 0x180e, 0x180e,
+ 0x181a, 0x181f,
+ 0x1879, 0x187f,
+ 0x18ab, 0x18af,
+ 0x18f6, 0x18ff,
+ 0x191f, 0x191f,
+ 0x192c, 0x192f,
+ 0x193c, 0x193f,
+ 0x1941, 0x1943,
+ 0x196e, 0x196f,
+ 0x1975, 0x197f,
+ 0x19ac, 0x19af,
+ 0x19ca, 0x19cf,
+ 0x19db, 0x19dd,
+ 0x1a1c, 0x1a1d,
+ 0x1a5f, 0x1a5f,
+ 0x1a7d, 0x1a7e,
+ 0x1a8a, 0x1a8f,
+ 0x1a9a, 0x1a9f,
+ 0x1aae, 0x1aaf,
+ 0x1ade, 0x1adf,
+ 0x1aec, 0x1aff,
+ 0x1b4d, 0x1b4d,
+ 0x1bf4, 0x1bfb,
+ 0x1c38, 0x1c3a,
+ 0x1c4a, 0x1c4c,
+ 0x1c8b, 0x1c8f,
+ 0x1cbb, 0x1cbc,
+ 0x1cc8, 0x1ccf,
+ 0x1cfb, 0x1cff,
+ 0x1f16, 0x1f17,
+ 0x1f1e, 0x1f1f,
+ 0x1f46, 0x1f47,
+ 0x1f4e, 0x1f4f,
+ 0x1f58, 0x1f58,
+ 0x1f5a, 0x1f5a,
+ 0x1f5c, 0x1f5c,
+ 0x1f5e, 0x1f5e,
+ 0x1f7e, 0x1f7f,
+ 0x1fb5, 0x1fb5,
+ 0x1fc5, 0x1fc5,
+ 0x1fd4, 0x1fd5,
+ 0x1fdc, 0x1fdc,
+ 0x1ff0, 0x1ff1,
+ 0x1ff5, 0x1ff5,
+ 0x1fff, 0x1fff,
+ 0x200b, 0x200f,
+ 0x202a, 0x202e,
+ 0x2060, 0x206f,
+ 0x2072, 0x2073,
+ 0x208f, 0x208f,
+ 0x209d, 0x209f,
+ 0x20c2, 0x20cf,
+ 0x20f1, 0x20ff,
+ 0x218c, 0x218f,
+ 0x242a, 0x243f,
+ 0x244b, 0x245f,
+ 0x2b74, 0x2b75,
+ 0x2cf4, 0x2cf8,
+ 0x2d26, 0x2d26,
+ 0x2d28, 0x2d2c,
+ 0x2d2e, 0x2d2f,
+ 0x2d68, 0x2d6e,
+ 0x2d71, 0x2d7e,
+ 0x2d97, 0x2d9f,
+ 0x2da7, 0x2da7,
+ 0x2daf, 0x2daf,
+ 0x2db7, 0x2db7,
+ 0x2dbf, 0x2dbf,
+ 0x2dc7, 0x2dc7,
+ 0x2dcf, 0x2dcf,
+ 0x2dd7, 0x2dd7,
+ 0x2ddf, 0x2ddf,
+ 0x2e5e, 0x2e7f,
+ 0x2e9a, 0x2e9a,
+ 0x2ef4, 0x2eff,
+ 0x2fd6, 0x2fef,
+ 0x3040, 0x3040,
+ 0x3097, 0x3098,
+ 0x3100, 0x3104,
+ 0x3130, 0x3130,
+ 0x318f, 0x318f,
+ 0x31e6, 0x31ee,
+ 0x321f, 0x321f,
+ 0xa48d, 0xa48f,
+ 0xa4c7, 0xa4cf,
+ 0xa62c, 0xa63f,
+ 0xa6f8, 0xa6ff,
+ 0xa7dd, 0xa7f0,
+ 0xa82d, 0xa82f,
+ 0xa83a, 0xa83f,
+ 0xa878, 0xa87f,
+ 0xa8c6, 0xa8cd,
+ 0xa8da, 0xa8df,
+ 0xa954, 0xa95e,
+ 0xa97d, 0xa97f,
+ 0xa9ce, 0xa9ce,
+ 0xa9da, 0xa9dd,
+ 0xa9ff, 0xa9ff,
+ 0xaa37, 0xaa3f,
+ 0xaa4e, 0xaa4f,
+ 0xaa5a, 0xaa5b,
+ 0xaac3, 0xaada,
+ 0xaaf7, 0xab00,
+ 0xab07, 0xab08,
+ 0xab0f, 0xab10,
+ 0xab17, 0xab1f,
+ 0xab27, 0xab27,
+ 0xab2f, 0xab2f,
+ 0xab6c, 0xab6f,
+ 0xabee, 0xabef,
+ 0xabfa, 0xabff,
+ 0xd7a4, 0xd7af,
+ 0xd7c7, 0xd7ca,
+ 0xd7fc, 0xf8ff,
+ 0xfa6e, 0xfa6f,
+ 0xfada, 0xfaff,
+ 0xfb07, 0xfb12,
+ 0xfb18, 0xfb1c,
+ 0xfb37, 0xfb37,
+ 0xfb3d, 0xfb3d,
+ 0xfb3f, 0xfb3f,
+ 0xfb42, 0xfb42,
+ 0xfb45, 0xfb45,
+ 0xfdd0, 0xfdef,
+ 0xfe1a, 0xfe1f,
+ 0xfe53, 0xfe53,
+ 0xfe67, 0xfe67,
+ 0xfe6c, 0xfe6f,
+ 0xfe75, 0xfe75,
+ 0xfefd, 0xff00,
+ 0xffbf, 0xffc1,
+ 0xffc8, 0xffc9,
+ 0xffd0, 0xffd1,
+ 0xffd8, 0xffd9,
+ 0xffdd, 0xffdf,
+ 0xffe7, 0xffe7,
+ 0xffef, 0xfffb,
+ 0xfffe, 0xffff,
+ 0x1000c, 0x1000c,
+ 0x10027, 0x10027,
+ 0x1003b, 0x1003b,
+ 0x1003e, 0x1003e,
+ 0x1004e, 0x1004f,
+ 0x1005e, 0x1007f,
+ 0x100fb, 0x100ff,
+ 0x10103, 0x10106,
+ 0x10134, 0x10136,
+ 0x1018f, 0x1018f,
+ 0x1019d, 0x1019f,
+ 0x101a1, 0x101cf,
+ 0x101fe, 0x1027f,
+ 0x1029d, 0x1029f,
+ 0x102d1, 0x102df,
+ 0x102fc, 0x102ff,
+ 0x10324, 0x1032c,
+ 0x1034b, 0x1034f,
+ 0x1037b, 0x1037f,
+ 0x1039e, 0x1039e,
+ 0x103c4, 0x103c7,
+ 0x103d6, 0x103ff,
+ 0x1049e, 0x1049f,
+ 0x104aa, 0x104af,
+ 0x104d4, 0x104d7,
+ 0x104fc, 0x104ff,
+ 0x10528, 0x1052f,
+ 0x10564, 0x1056e,
+ 0x1057b, 0x1057b,
+ 0x1058b, 0x1058b,
+ 0x10593, 0x10593,
+ 0x10596, 0x10596,
+ 0x105a2, 0x105a2,
+ 0x105b2, 0x105b2,
+ 0x105ba, 0x105ba,
+ 0x105bd, 0x105bf,
+ 0x105f4, 0x105ff,
+ 0x10737, 0x1073f,
+ 0x10756, 0x1075f,
+ 0x10768, 0x1077f,
+ 0x10786, 0x10786,
+ 0x107b1, 0x107b1,
+ 0x107bb, 0x107ff,
+ 0x10806, 0x10807,
+ 0x10809, 0x10809,
+ 0x10836, 0x10836,
+ 0x10839, 0x1083b,
+ 0x1083d, 0x1083e,
+ 0x10856, 0x10856,
+ 0x1089f, 0x108a6,
+ 0x108b0, 0x108df,
+ 0x108f3, 0x108f3,
+ 0x108f6, 0x108fa,
+ 0x1091c, 0x1091e,
+ 0x1093a, 0x1093e,
+ 0x1095a, 0x1097f,
+ 0x109b8, 0x109bb,
+ 0x109d0, 0x109d1,
+ 0x10a04, 0x10a04,
+ 0x10a07, 0x10a0b,
+ 0x10a14, 0x10a14,
+ 0x10a18, 0x10a18,
+ 0x10a36, 0x10a37,
+ 0x10a3b, 0x10a3e,
+ 0x10a49, 0x10a4f,
+ 0x10a59, 0x10a5f,
+ 0x10aa0, 0x10abf,
+ 0x10ae7, 0x10aea,
+ 0x10af7, 0x10aff,
+ 0x10b36, 0x10b38,
+ 0x10b56, 0x10b57,
+ 0x10b73, 0x10b77,
+ 0x10b92, 0x10b98,
+ 0x10b9d, 0x10ba8,
+ 0x10bb0, 0x10bff,
+ 0x10c49, 0x10c7f,
+ 0x10cb3, 0x10cbf,
+ 0x10cf3, 0x10cf9,
+ 0x10d28, 0x10d2f,
+ 0x10d3a, 0x10d3f,
+ 0x10d66, 0x10d68,
+ 0x10d86, 0x10d8d,
+ 0x10d90, 0x10e5f,
+ 0x10e7f, 0x10e7f,
+ 0x10eaa, 0x10eaa,
+ 0x10eae, 0x10eaf,
+ 0x10eb2, 0x10ec1,
+ 0x10ec8, 0x10ecf,
+ 0x10ed9, 0x10ef9,
+ 0x10f28, 0x10f2f,
+ 0x10f5a, 0x10f6f,
+ 0x10f8a, 0x10faf,
+ 0x10fcc, 0x10fdf,
+ 0x10ff7, 0x10fff,
+ 0x1104e, 0x11051,
+ 0x11076, 0x1107e,
+ 0x110bd, 0x110bd,
+ 0x110c3, 0x110cf,
+ 0x110e9, 0x110ef,
+ 0x110fa, 0x110ff,
+ 0x11135, 0x11135,
+ 0x11148, 0x1114f,
+ 0x11177, 0x1117f,
+ 0x111e0, 0x111e0,
+ 0x111f5, 0x111ff,
+ 0x11212, 0x11212,
+ 0x11242, 0x1127f,
+ 0x11287, 0x11287,
+ 0x11289, 0x11289,
+ 0x1128e, 0x1128e,
+ 0x1129e, 0x1129e,
+ 0x112aa, 0x112af,
+ 0x112eb, 0x112ef,
+ 0x112fa, 0x112ff,
+ 0x11304, 0x11304,
+ 0x1130d, 0x1130e,
+ 0x11311, 0x11312,
+ 0x11329, 0x11329,
+ 0x11331, 0x11331,
+ 0x11334, 0x11334,
+ 0x1133a, 0x1133a,
+ 0x11345, 0x11346,
+ 0x11349, 0x1134a,
+ 0x1134e, 0x1134f,
+ 0x11351, 0x11356,
+ 0x11358, 0x1135c,
+ 0x11364, 0x11365,
+ 0x1136d, 0x1136f,
+ 0x11375, 0x1137f,
+ 0x1138a, 0x1138a,
+ 0x1138c, 0x1138d,
+ 0x1138f, 0x1138f,
+ 0x113b6, 0x113b6,
+ 0x113c1, 0x113c1,
+ 0x113c3, 0x113c4,
+ 0x113c6, 0x113c6,
+ 0x113cb, 0x113cb,
+ 0x113d6, 0x113d6,
+ 0x113d9, 0x113e0,
+ 0x113e3, 0x113ff,
+ 0x1145c, 0x1145c,
+ 0x11462, 0x1147f,
+ 0x114c8, 0x114cf,
+ 0x114da, 0x1157f,
+ 0x115b6, 0x115b7,
+ 0x115de, 0x115ff,
+ 0x11645, 0x1164f,
+ 0x1165a, 0x1165f,
+ 0x1166d, 0x1167f,
+ 0x116ba, 0x116bf,
+ 0x116ca, 0x116cf,
+ 0x116e4, 0x116ff,
+ 0x1171b, 0x1171c,
+ 0x1172c, 0x1172f,
+ 0x11747, 0x117ff,
+ 0x1183c, 0x1189f,
+ 0x118f3, 0x118fe,
+ 0x11907, 0x11908,
+ 0x1190a, 0x1190b,
+ 0x11914, 0x11914,
+ 0x11917, 0x11917,
+ 0x11936, 0x11936,
+ 0x11939, 0x1193a,
+ 0x11947, 0x1194f,
+ 0x1195a, 0x1199f,
+ 0x119a8, 0x119a9,
+ 0x119d8, 0x119d9,
+ 0x119e5, 0x119ff,
+ 0x11a48, 0x11a4f,
+ 0x11aa3, 0x11aaf,
+ 0x11af9, 0x11aff,
+ 0x11b0a, 0x11b5f,
+ 0x11b68, 0x11bbf,
+ 0x11be2, 0x11bef,
+ 0x11bfa, 0x11bff,
+ 0x11c09, 0x11c09,
+ 0x11c37, 0x11c37,
+ 0x11c46, 0x11c4f,
+ 0x11c6d, 0x11c6f,
+ 0x11c90, 0x11c91,
+ 0x11ca8, 0x11ca8,
+ 0x11cb7, 0x11cff,
+ 0x11d07, 0x11d07,
+ 0x11d0a, 0x11d0a,
+ 0x11d37, 0x11d39,
+ 0x11d3b, 0x11d3b,
+ 0x11d3e, 0x11d3e,
+ 0x11d48, 0x11d4f,
+ 0x11d5a, 0x11d5f,
+ 0x11d66, 0x11d66,
+ 0x11d69, 0x11d69,
+ 0x11d8f, 0x11d8f,
+ 0x11d92, 0x11d92,
+ 0x11d99, 0x11d9f,
+ 0x11daa, 0x11daf,
+ 0x11ddc, 0x11ddf,
+ 0x11dea, 0x11edf,
+ 0x11ef9, 0x11eff,
+ 0x11f11, 0x11f11,
+ 0x11f3b, 0x11f3d,
+ 0x11f5b, 0x11faf,
+ 0x11fb1, 0x11fbf,
+ 0x11ff2, 0x11ffe,
+ 0x1239a, 0x123ff,
+ 0x1246f, 0x1246f,
+ 0x12475, 0x1247f,
+ 0x12544, 0x12f8f,
+ 0x12ff3, 0x12fff,
+ 0x13430, 0x1343f,
+ 0x13456, 0x1345f,
+ 0x143fb, 0x143ff,
+ 0x14647, 0x160ff,
+ 0x1613a, 0x167ff,
+ 0x16a39, 0x16a3f,
+ 0x16a5f, 0x16a5f,
+ 0x16a6a, 0x16a6d,
+ 0x16abf, 0x16abf,
+ 0x16aca, 0x16acf,
+ 0x16aee, 0x16aef,
+ 0x16af6, 0x16aff,
+ 0x16b46, 0x16b4f,
+ 0x16b5a, 0x16b5a,
+ 0x16b62, 0x16b62,
+ 0x16b78, 0x16b7c,
+ 0x16b90, 0x16d3f,
+ 0x16d7a, 0x16e3f,
+ 0x16e9b, 0x16e9f,
+ 0x16eb9, 0x16eba,
+ 0x16ed4, 0x16eff,
+ 0x16f4b, 0x16f4e,
+ 0x16f88, 0x16f8e,
+ 0x16fa0, 0x16fdf,
+ 0x16fe5, 0x16fef,
+ 0x16ff7, 0x16fff,
+ 0x18cd6, 0x18cfe,
+ 0x18d1f, 0x18d7f,
+ 0x18df3, 0x1afef,
+ 0x1aff4, 0x1aff4,
+ 0x1affc, 0x1affc,
+ 0x1afff, 0x1afff,
+ 0x1b123, 0x1b131,
+ 0x1b133, 0x1b14f,
+ 0x1b153, 0x1b154,
+ 0x1b156, 0x1b163,
+ 0x1b168, 0x1b16f,
+ 0x1b2fc, 0x1bbff,
+ 0x1bc6b, 0x1bc6f,
+ 0x1bc7d, 0x1bc7f,
+ 0x1bc89, 0x1bc8f,
+ 0x1bc9a, 0x1bc9b,
+ 0x1bca0, 0x1cbff,
+ 0x1ccfd, 0x1ccff,
+ 0x1ceb4, 0x1ceb9,
+ 0x1ced1, 0x1cedf,
+ 0x1cef1, 0x1ceff,
+ 0x1cf2e, 0x1cf2f,
+ 0x1cf47, 0x1cf4f,
+ 0x1cfc4, 0x1cfff,
+ 0x1d0f6, 0x1d0ff,
+ 0x1d127, 0x1d128,
+ 0x1d173, 0x1d17a,
+ 0x1d1eb, 0x1d1ff,
+ 0x1d246, 0x1d2bf,
+ 0x1d2d4, 0x1d2df,
+ 0x1d2f4, 0x1d2ff,
+ 0x1d357, 0x1d35f,
+ 0x1d379, 0x1d3ff,
+ 0x1d455, 0x1d455,
+ 0x1d49d, 0x1d49d,
+ 0x1d4a0, 0x1d4a1,
+ 0x1d4a3, 0x1d4a4,
+ 0x1d4a7, 0x1d4a8,
+ 0x1d4ad, 0x1d4ad,
+ 0x1d4ba, 0x1d4ba,
+ 0x1d4bc, 0x1d4bc,
+ 0x1d4c4, 0x1d4c4,
+ 0x1d506, 0x1d506,
+ 0x1d50b, 0x1d50c,
+ 0x1d515, 0x1d515,
+ 0x1d51d, 0x1d51d,
+ 0x1d53a, 0x1d53a,
+ 0x1d53f, 0x1d53f,
+ 0x1d545, 0x1d545,
+ 0x1d547, 0x1d549,
+ 0x1d551, 0x1d551,
+ 0x1d6a6, 0x1d6a7,
+ 0x1d7cc, 0x1d7cd,
+ 0x1da8c, 0x1da9a,
+ 0x1daa0, 0x1daa0,
+ 0x1dab0, 0x1deff,
+ 0x1df1f, 0x1df24,
+ 0x1df2b, 0x1dfff,
+ 0x1e007, 0x1e007,
+ 0x1e019, 0x1e01a,
+ 0x1e022, 0x1e022,
+ 0x1e025, 0x1e025,
+ 0x1e02b, 0x1e02f,
+ 0x1e06e, 0x1e08e,
+ 0x1e090, 0x1e0ff,
+ 0x1e12d, 0x1e12f,
+ 0x1e13e, 0x1e13f,
+ 0x1e14a, 0x1e14d,
+ 0x1e150, 0x1e28f,
+ 0x1e2af, 0x1e2bf,
+ 0x1e2fa, 0x1e2fe,
+ 0x1e300, 0x1e4cf,
+ 0x1e4fa, 0x1e5cf,
+ 0x1e5fb, 0x1e5fe,
+ 0x1e600, 0x1e6bf,
+ 0x1e6df, 0x1e6df,
+ 0x1e6f6, 0x1e6fd,
+ 0x1e700, 0x1e7df,
+ 0x1e7e7, 0x1e7e7,
+ 0x1e7ec, 0x1e7ec,
+ 0x1e7ef, 0x1e7ef,
+ 0x1e7ff, 0x1e7ff,
+ 0x1e8c5, 0x1e8c6,
+ 0x1e8d7, 0x1e8ff,
+ 0x1e94c, 0x1e94f,
+ 0x1e95a, 0x1e95d,
+ 0x1e960, 0x1ec70,
+ 0x1ecb5, 0x1ed00,
+ 0x1ed3e, 0x1edff,
+ 0x1ee04, 0x1ee04,
+ 0x1ee20, 0x1ee20,
+ 0x1ee23, 0x1ee23,
+ 0x1ee25, 0x1ee26,
+ 0x1ee28, 0x1ee28,
+ 0x1ee33, 0x1ee33,
+ 0x1ee38, 0x1ee38,
+ 0x1ee3a, 0x1ee3a,
+ 0x1ee3c, 0x1ee41,
+ 0x1ee43, 0x1ee46,
+ 0x1ee48, 0x1ee48,
+ 0x1ee4a, 0x1ee4a,
+ 0x1ee4c, 0x1ee4c,
+ 0x1ee50, 0x1ee50,
+ 0x1ee53, 0x1ee53,
+ 0x1ee55, 0x1ee56,
+ 0x1ee58, 0x1ee58,
+ 0x1ee5a, 0x1ee5a,
+ 0x1ee5c, 0x1ee5c,
+ 0x1ee5e, 0x1ee5e,
+ 0x1ee60, 0x1ee60,
+ 0x1ee63, 0x1ee63,
+ 0x1ee65, 0x1ee66,
+ 0x1ee6b, 0x1ee6b,
+ 0x1ee73, 0x1ee73,
+ 0x1ee78, 0x1ee78,
+ 0x1ee7d, 0x1ee7d,
+ 0x1ee7f, 0x1ee7f,
+ 0x1ee8a, 0x1ee8a,
+ 0x1ee9c, 0x1eea0,
+ 0x1eea4, 0x1eea4,
+ 0x1eeaa, 0x1eeaa,
+ 0x1eebc, 0x1eeef,
+ 0x1eef2, 0x1efff,
+ 0x1f02c, 0x1f02f,
+ 0x1f094, 0x1f09f,
+ 0x1f0af, 0x1f0b0,
+ 0x1f0c0, 0x1f0c0,
+ 0x1f0d0, 0x1f0d0,
+ 0x1f0f6, 0x1f0ff,
+ 0x1f1ae, 0x1f1e5,
+ 0x1f203, 0x1f20f,
+ 0x1f23c, 0x1f23f,
+ 0x1f249, 0x1f24f,
+ 0x1f252, 0x1f25f,
+ 0x1f266, 0x1f2ff,
+ 0x1f6d9, 0x1f6db,
+ 0x1f6ed, 0x1f6ef,
+ 0x1f6fd, 0x1f6ff,
+ 0x1f7da, 0x1f7df,
+ 0x1f7ec, 0x1f7ef,
+ 0x1f7f1, 0x1f7ff,
+ 0x1f80c, 0x1f80f,
+ 0x1f848, 0x1f84f,
+ 0x1f85a, 0x1f85f,
+ 0x1f888, 0x1f88f,
+ 0x1f8ae, 0x1f8af,
+ 0x1f8bc, 0x1f8bf,
+ 0x1f8c2, 0x1f8cf,
+ 0x1f8d9, 0x1f8ff,
+ 0x1fa58, 0x1fa5f,
+ 0x1fa6e, 0x1fa6f,
+ 0x1fa7d, 0x1fa7f,
+ 0x1fa8b, 0x1fa8d,
+ 0x1fac7, 0x1fac7,
+ 0x1fac9, 0x1facc,
+ 0x1fadd, 0x1fade,
+ 0x1faeb, 0x1faee,
+ 0x1faf9, 0x1faff,
+ 0x1fb93, 0x1fb93,
+ 0x1fbfb, 0x1ffff,
+ 0x2a6e0, 0x2a6ff,
+ 0x2b81e, 0x2b81f,
+ 0x2ceae, 0x2ceaf,
+ 0x2ebe1, 0x2ebef,
+ 0x2ee5e, 0x2f7ff,
+ 0x2fa1e, 0x2ffff,
+ 0x3134b, 0x3134f,
+ 0x3347a, 0xe00ff,
+ 0xe01f0, 0x10ffff,
+}; /* CR_C */
+
+/* 'Cc': General Category */
+#define CR_Cc CR_Cntrl
+
+/* 'Cf': General Category */
+static const OnigCodePoint CR_Cf[] = {
+ 21,
+ 0x00ad, 0x00ad,
+ 0x0600, 0x0605,
+ 0x061c, 0x061c,
+ 0x06dd, 0x06dd,
+ 0x070f, 0x070f,
+ 0x0890, 0x0891,
+ 0x08e2, 0x08e2,
+ 0x180e, 0x180e,
+ 0x200b, 0x200f,
+ 0x202a, 0x202e,
+ 0x2060, 0x2064,
+ 0x2066, 0x206f,
+ 0xfeff, 0xfeff,
+ 0xfff9, 0xfffb,
+ 0x110bd, 0x110bd,
+ 0x110cd, 0x110cd,
+ 0x13430, 0x1343f,
+ 0x1bca0, 0x1bca3,
+ 0x1d173, 0x1d17a,
+ 0xe0001, 0xe0001,
+ 0xe0020, 0xe007f,
+}; /* CR_Cf */
+
+/* 'Cn': General Category */
+static const OnigCodePoint CR_Cn[] = {
+ 735,
+ 0x0378, 0x0379,
+ 0x0380, 0x0383,
+ 0x038b, 0x038b,
+ 0x038d, 0x038d,
+ 0x03a2, 0x03a2,
+ 0x0530, 0x0530,
+ 0x0557, 0x0558,
+ 0x058b, 0x058c,
+ 0x0590, 0x0590,
+ 0x05c8, 0x05cf,
+ 0x05eb, 0x05ee,
+ 0x05f5, 0x05ff,
+ 0x070e, 0x070e,
+ 0x074b, 0x074c,
+ 0x07b2, 0x07bf,
+ 0x07fb, 0x07fc,
+ 0x082e, 0x082f,
+ 0x083f, 0x083f,
+ 0x085c, 0x085d,
+ 0x085f, 0x085f,
+ 0x086b, 0x086f,
+ 0x0892, 0x0896,
+ 0x0984, 0x0984,
+ 0x098d, 0x098e,
+ 0x0991, 0x0992,
+ 0x09a9, 0x09a9,
+ 0x09b1, 0x09b1,
+ 0x09b3, 0x09b5,
+ 0x09ba, 0x09bb,
+ 0x09c5, 0x09c6,
+ 0x09c9, 0x09ca,
+ 0x09cf, 0x09d6,
+ 0x09d8, 0x09db,
+ 0x09de, 0x09de,
+ 0x09e4, 0x09e5,
+ 0x09ff, 0x0a00,
+ 0x0a04, 0x0a04,
+ 0x0a0b, 0x0a0e,
+ 0x0a11, 0x0a12,
+ 0x0a29, 0x0a29,
+ 0x0a31, 0x0a31,
+ 0x0a34, 0x0a34,
+ 0x0a37, 0x0a37,
+ 0x0a3a, 0x0a3b,
+ 0x0a3d, 0x0a3d,
+ 0x0a43, 0x0a46,
+ 0x0a49, 0x0a4a,
+ 0x0a4e, 0x0a50,
+ 0x0a52, 0x0a58,
+ 0x0a5d, 0x0a5d,
+ 0x0a5f, 0x0a65,
+ 0x0a77, 0x0a80,
+ 0x0a84, 0x0a84,
+ 0x0a8e, 0x0a8e,
+ 0x0a92, 0x0a92,
+ 0x0aa9, 0x0aa9,
+ 0x0ab1, 0x0ab1,
+ 0x0ab4, 0x0ab4,
+ 0x0aba, 0x0abb,
+ 0x0ac6, 0x0ac6,
+ 0x0aca, 0x0aca,
+ 0x0ace, 0x0acf,
+ 0x0ad1, 0x0adf,
+ 0x0ae4, 0x0ae5,
+ 0x0af2, 0x0af8,
+ 0x0b00, 0x0b00,
+ 0x0b04, 0x0b04,
+ 0x0b0d, 0x0b0e,
+ 0x0b11, 0x0b12,
+ 0x0b29, 0x0b29,
+ 0x0b31, 0x0b31,
+ 0x0b34, 0x0b34,
+ 0x0b3a, 0x0b3b,
+ 0x0b45, 0x0b46,
+ 0x0b49, 0x0b4a,
+ 0x0b4e, 0x0b54,
+ 0x0b58, 0x0b5b,
+ 0x0b5e, 0x0b5e,
+ 0x0b64, 0x0b65,
+ 0x0b78, 0x0b81,
+ 0x0b84, 0x0b84,
+ 0x0b8b, 0x0b8d,
+ 0x0b91, 0x0b91,
+ 0x0b96, 0x0b98,
+ 0x0b9b, 0x0b9b,
+ 0x0b9d, 0x0b9d,
+ 0x0ba0, 0x0ba2,
+ 0x0ba5, 0x0ba7,
+ 0x0bab, 0x0bad,
+ 0x0bba, 0x0bbd,
+ 0x0bc3, 0x0bc5,
+ 0x0bc9, 0x0bc9,
+ 0x0bce, 0x0bcf,
+ 0x0bd1, 0x0bd6,
+ 0x0bd8, 0x0be5,
+ 0x0bfb, 0x0bff,
+ 0x0c0d, 0x0c0d,
+ 0x0c11, 0x0c11,
+ 0x0c29, 0x0c29,
+ 0x0c3a, 0x0c3b,
+ 0x0c45, 0x0c45,
+ 0x0c49, 0x0c49,
+ 0x0c4e, 0x0c54,
+ 0x0c57, 0x0c57,
+ 0x0c5b, 0x0c5b,
+ 0x0c5e, 0x0c5f,
+ 0x0c64, 0x0c65,
+ 0x0c70, 0x0c76,
+ 0x0c8d, 0x0c8d,
+ 0x0c91, 0x0c91,
+ 0x0ca9, 0x0ca9,
+ 0x0cb4, 0x0cb4,
+ 0x0cba, 0x0cbb,
+ 0x0cc5, 0x0cc5,
+ 0x0cc9, 0x0cc9,
+ 0x0cce, 0x0cd4,
+ 0x0cd7, 0x0cdb,
+ 0x0cdf, 0x0cdf,
+ 0x0ce4, 0x0ce5,
+ 0x0cf0, 0x0cf0,
+ 0x0cf4, 0x0cff,
+ 0x0d0d, 0x0d0d,
+ 0x0d11, 0x0d11,
+ 0x0d45, 0x0d45,
+ 0x0d49, 0x0d49,
+ 0x0d50, 0x0d53,
+ 0x0d64, 0x0d65,
+ 0x0d80, 0x0d80,
+ 0x0d84, 0x0d84,
+ 0x0d97, 0x0d99,
+ 0x0db2, 0x0db2,
+ 0x0dbc, 0x0dbc,
+ 0x0dbe, 0x0dbf,
+ 0x0dc7, 0x0dc9,
+ 0x0dcb, 0x0dce,
+ 0x0dd5, 0x0dd5,
+ 0x0dd7, 0x0dd7,
+ 0x0de0, 0x0de5,
+ 0x0df0, 0x0df1,
+ 0x0df5, 0x0e00,
+ 0x0e3b, 0x0e3e,
+ 0x0e5c, 0x0e80,
+ 0x0e83, 0x0e83,
+ 0x0e85, 0x0e85,
+ 0x0e8b, 0x0e8b,
+ 0x0ea4, 0x0ea4,
+ 0x0ea6, 0x0ea6,
+ 0x0ebe, 0x0ebf,
+ 0x0ec5, 0x0ec5,
+ 0x0ec7, 0x0ec7,
+ 0x0ecf, 0x0ecf,
+ 0x0eda, 0x0edb,
+ 0x0ee0, 0x0eff,
+ 0x0f48, 0x0f48,
+ 0x0f6d, 0x0f70,
+ 0x0f98, 0x0f98,
+ 0x0fbd, 0x0fbd,
+ 0x0fcd, 0x0fcd,
+ 0x0fdb, 0x0fff,
+ 0x10c6, 0x10c6,
+ 0x10c8, 0x10cc,
+ 0x10ce, 0x10cf,
+ 0x1249, 0x1249,
+ 0x124e, 0x124f,
+ 0x1257, 0x1257,
+ 0x1259, 0x1259,
+ 0x125e, 0x125f,
+ 0x1289, 0x1289,
+ 0x128e, 0x128f,
+ 0x12b1, 0x12b1,
+ 0x12b6, 0x12b7,
+ 0x12bf, 0x12bf,
+ 0x12c1, 0x12c1,
+ 0x12c6, 0x12c7,
+ 0x12d7, 0x12d7,
+ 0x1311, 0x1311,
+ 0x1316, 0x1317,
+ 0x135b, 0x135c,
+ 0x137d, 0x137f,
+ 0x139a, 0x139f,
+ 0x13f6, 0x13f7,
+ 0x13fe, 0x13ff,
+ 0x169d, 0x169f,
+ 0x16f9, 0x16ff,
+ 0x1716, 0x171e,
+ 0x1737, 0x173f,
+ 0x1754, 0x175f,
+ 0x176d, 0x176d,
+ 0x1771, 0x1771,
+ 0x1774, 0x177f,
+ 0x17de, 0x17df,
+ 0x17ea, 0x17ef,
+ 0x17fa, 0x17ff,
+ 0x181a, 0x181f,
+ 0x1879, 0x187f,
+ 0x18ab, 0x18af,
+ 0x18f6, 0x18ff,
+ 0x191f, 0x191f,
+ 0x192c, 0x192f,
+ 0x193c, 0x193f,
+ 0x1941, 0x1943,
+ 0x196e, 0x196f,
+ 0x1975, 0x197f,
+ 0x19ac, 0x19af,
+ 0x19ca, 0x19cf,
+ 0x19db, 0x19dd,
+ 0x1a1c, 0x1a1d,
+ 0x1a5f, 0x1a5f,
+ 0x1a7d, 0x1a7e,
+ 0x1a8a, 0x1a8f,
+ 0x1a9a, 0x1a9f,
+ 0x1aae, 0x1aaf,
+ 0x1ade, 0x1adf,
+ 0x1aec, 0x1aff,
+ 0x1b4d, 0x1b4d,
+ 0x1bf4, 0x1bfb,
+ 0x1c38, 0x1c3a,
+ 0x1c4a, 0x1c4c,
+ 0x1c8b, 0x1c8f,
+ 0x1cbb, 0x1cbc,
+ 0x1cc8, 0x1ccf,
+ 0x1cfb, 0x1cff,
+ 0x1f16, 0x1f17,
+ 0x1f1e, 0x1f1f,
+ 0x1f46, 0x1f47,
+ 0x1f4e, 0x1f4f,
+ 0x1f58, 0x1f58,
+ 0x1f5a, 0x1f5a,
+ 0x1f5c, 0x1f5c,
+ 0x1f5e, 0x1f5e,
+ 0x1f7e, 0x1f7f,
+ 0x1fb5, 0x1fb5,
+ 0x1fc5, 0x1fc5,
+ 0x1fd4, 0x1fd5,
+ 0x1fdc, 0x1fdc,
+ 0x1ff0, 0x1ff1,
+ 0x1ff5, 0x1ff5,
+ 0x1fff, 0x1fff,
+ 0x2065, 0x2065,
+ 0x2072, 0x2073,
+ 0x208f, 0x208f,
+ 0x209d, 0x209f,
+ 0x20c2, 0x20cf,
+ 0x20f1, 0x20ff,
+ 0x218c, 0x218f,
+ 0x242a, 0x243f,
+ 0x244b, 0x245f,
+ 0x2b74, 0x2b75,
+ 0x2cf4, 0x2cf8,
+ 0x2d26, 0x2d26,
+ 0x2d28, 0x2d2c,
+ 0x2d2e, 0x2d2f,
+ 0x2d68, 0x2d6e,
+ 0x2d71, 0x2d7e,
+ 0x2d97, 0x2d9f,
+ 0x2da7, 0x2da7,
+ 0x2daf, 0x2daf,
+ 0x2db7, 0x2db7,
+ 0x2dbf, 0x2dbf,
+ 0x2dc7, 0x2dc7,
+ 0x2dcf, 0x2dcf,
+ 0x2dd7, 0x2dd7,
+ 0x2ddf, 0x2ddf,
+ 0x2e5e, 0x2e7f,
+ 0x2e9a, 0x2e9a,
+ 0x2ef4, 0x2eff,
+ 0x2fd6, 0x2fef,
+ 0x3040, 0x3040,
+ 0x3097, 0x3098,
+ 0x3100, 0x3104,
+ 0x3130, 0x3130,
+ 0x318f, 0x318f,
+ 0x31e6, 0x31ee,
+ 0x321f, 0x321f,
+ 0xa48d, 0xa48f,
+ 0xa4c7, 0xa4cf,
+ 0xa62c, 0xa63f,
+ 0xa6f8, 0xa6ff,
+ 0xa7dd, 0xa7f0,
+ 0xa82d, 0xa82f,
+ 0xa83a, 0xa83f,
+ 0xa878, 0xa87f,
+ 0xa8c6, 0xa8cd,
+ 0xa8da, 0xa8df,
+ 0xa954, 0xa95e,
+ 0xa97d, 0xa97f,
+ 0xa9ce, 0xa9ce,
+ 0xa9da, 0xa9dd,
+ 0xa9ff, 0xa9ff,
+ 0xaa37, 0xaa3f,
+ 0xaa4e, 0xaa4f,
+ 0xaa5a, 0xaa5b,
+ 0xaac3, 0xaada,
+ 0xaaf7, 0xab00,
+ 0xab07, 0xab08,
+ 0xab0f, 0xab10,
+ 0xab17, 0xab1f,
+ 0xab27, 0xab27,
+ 0xab2f, 0xab2f,
+ 0xab6c, 0xab6f,
+ 0xabee, 0xabef,
+ 0xabfa, 0xabff,
+ 0xd7a4, 0xd7af,
+ 0xd7c7, 0xd7ca,
+ 0xd7fc, 0xd7ff,
+ 0xfa6e, 0xfa6f,
+ 0xfada, 0xfaff,
+ 0xfb07, 0xfb12,
+ 0xfb18, 0xfb1c,
+ 0xfb37, 0xfb37,
+ 0xfb3d, 0xfb3d,
+ 0xfb3f, 0xfb3f,
+ 0xfb42, 0xfb42,
+ 0xfb45, 0xfb45,
+ 0xfdd0, 0xfdef,
+ 0xfe1a, 0xfe1f,
+ 0xfe53, 0xfe53,
+ 0xfe67, 0xfe67,
+ 0xfe6c, 0xfe6f,
+ 0xfe75, 0xfe75,
+ 0xfefd, 0xfefe,
+ 0xff00, 0xff00,
+ 0xffbf, 0xffc1,
+ 0xffc8, 0xffc9,
+ 0xffd0, 0xffd1,
+ 0xffd8, 0xffd9,
+ 0xffdd, 0xffdf,
+ 0xffe7, 0xffe7,
+ 0xffef, 0xfff8,
+ 0xfffe, 0xffff,
+ 0x1000c, 0x1000c,
+ 0x10027, 0x10027,
+ 0x1003b, 0x1003b,
+ 0x1003e, 0x1003e,
+ 0x1004e, 0x1004f,
+ 0x1005e, 0x1007f,
+ 0x100fb, 0x100ff,
+ 0x10103, 0x10106,
+ 0x10134, 0x10136,
+ 0x1018f, 0x1018f,
+ 0x1019d, 0x1019f,
+ 0x101a1, 0x101cf,
+ 0x101fe, 0x1027f,
+ 0x1029d, 0x1029f,
+ 0x102d1, 0x102df,
+ 0x102fc, 0x102ff,
+ 0x10324, 0x1032c,
+ 0x1034b, 0x1034f,
+ 0x1037b, 0x1037f,
+ 0x1039e, 0x1039e,
+ 0x103c4, 0x103c7,
+ 0x103d6, 0x103ff,
+ 0x1049e, 0x1049f,
+ 0x104aa, 0x104af,
+ 0x104d4, 0x104d7,
+ 0x104fc, 0x104ff,
+ 0x10528, 0x1052f,
+ 0x10564, 0x1056e,
+ 0x1057b, 0x1057b,
+ 0x1058b, 0x1058b,
+ 0x10593, 0x10593,
+ 0x10596, 0x10596,
+ 0x105a2, 0x105a2,
+ 0x105b2, 0x105b2,
+ 0x105ba, 0x105ba,
+ 0x105bd, 0x105bf,
+ 0x105f4, 0x105ff,
+ 0x10737, 0x1073f,
+ 0x10756, 0x1075f,
+ 0x10768, 0x1077f,
+ 0x10786, 0x10786,
+ 0x107b1, 0x107b1,
+ 0x107bb, 0x107ff,
+ 0x10806, 0x10807,
+ 0x10809, 0x10809,
+ 0x10836, 0x10836,
+ 0x10839, 0x1083b,
+ 0x1083d, 0x1083e,
+ 0x10856, 0x10856,
+ 0x1089f, 0x108a6,
+ 0x108b0, 0x108df,
+ 0x108f3, 0x108f3,
+ 0x108f6, 0x108fa,
+ 0x1091c, 0x1091e,
+ 0x1093a, 0x1093e,
+ 0x1095a, 0x1097f,
+ 0x109b8, 0x109bb,
+ 0x109d0, 0x109d1,
+ 0x10a04, 0x10a04,
+ 0x10a07, 0x10a0b,
+ 0x10a14, 0x10a14,
+ 0x10a18, 0x10a18,
+ 0x10a36, 0x10a37,
+ 0x10a3b, 0x10a3e,
+ 0x10a49, 0x10a4f,
+ 0x10a59, 0x10a5f,
+ 0x10aa0, 0x10abf,
+ 0x10ae7, 0x10aea,
+ 0x10af7, 0x10aff,
+ 0x10b36, 0x10b38,
+ 0x10b56, 0x10b57,
+ 0x10b73, 0x10b77,
+ 0x10b92, 0x10b98,
+ 0x10b9d, 0x10ba8,
+ 0x10bb0, 0x10bff,
+ 0x10c49, 0x10c7f,
+ 0x10cb3, 0x10cbf,
+ 0x10cf3, 0x10cf9,
+ 0x10d28, 0x10d2f,
+ 0x10d3a, 0x10d3f,
+ 0x10d66, 0x10d68,
+ 0x10d86, 0x10d8d,
+ 0x10d90, 0x10e5f,
+ 0x10e7f, 0x10e7f,
+ 0x10eaa, 0x10eaa,
+ 0x10eae, 0x10eaf,
+ 0x10eb2, 0x10ec1,
+ 0x10ec8, 0x10ecf,
+ 0x10ed9, 0x10ef9,
+ 0x10f28, 0x10f2f,
+ 0x10f5a, 0x10f6f,
+ 0x10f8a, 0x10faf,
+ 0x10fcc, 0x10fdf,
+ 0x10ff7, 0x10fff,
+ 0x1104e, 0x11051,
+ 0x11076, 0x1107e,
+ 0x110c3, 0x110cc,
+ 0x110ce, 0x110cf,
+ 0x110e9, 0x110ef,
+ 0x110fa, 0x110ff,
+ 0x11135, 0x11135,
+ 0x11148, 0x1114f,
+ 0x11177, 0x1117f,
+ 0x111e0, 0x111e0,
+ 0x111f5, 0x111ff,
+ 0x11212, 0x11212,
+ 0x11242, 0x1127f,
+ 0x11287, 0x11287,
+ 0x11289, 0x11289,
+ 0x1128e, 0x1128e,
+ 0x1129e, 0x1129e,
+ 0x112aa, 0x112af,
+ 0x112eb, 0x112ef,
+ 0x112fa, 0x112ff,
+ 0x11304, 0x11304,
+ 0x1130d, 0x1130e,
+ 0x11311, 0x11312,
+ 0x11329, 0x11329,
+ 0x11331, 0x11331,
+ 0x11334, 0x11334,
+ 0x1133a, 0x1133a,
+ 0x11345, 0x11346,
+ 0x11349, 0x1134a,
+ 0x1134e, 0x1134f,
+ 0x11351, 0x11356,
+ 0x11358, 0x1135c,
+ 0x11364, 0x11365,
+ 0x1136d, 0x1136f,
+ 0x11375, 0x1137f,
+ 0x1138a, 0x1138a,
+ 0x1138c, 0x1138d,
+ 0x1138f, 0x1138f,
+ 0x113b6, 0x113b6,
+ 0x113c1, 0x113c1,
+ 0x113c3, 0x113c4,
+ 0x113c6, 0x113c6,
+ 0x113cb, 0x113cb,
+ 0x113d6, 0x113d6,
+ 0x113d9, 0x113e0,
+ 0x113e3, 0x113ff,
+ 0x1145c, 0x1145c,
+ 0x11462, 0x1147f,
+ 0x114c8, 0x114cf,
+ 0x114da, 0x1157f,
+ 0x115b6, 0x115b7,
+ 0x115de, 0x115ff,
+ 0x11645, 0x1164f,
+ 0x1165a, 0x1165f,
+ 0x1166d, 0x1167f,
+ 0x116ba, 0x116bf,
+ 0x116ca, 0x116cf,
+ 0x116e4, 0x116ff,
+ 0x1171b, 0x1171c,
+ 0x1172c, 0x1172f,
+ 0x11747, 0x117ff,
+ 0x1183c, 0x1189f,
+ 0x118f3, 0x118fe,
+ 0x11907, 0x11908,
+ 0x1190a, 0x1190b,
+ 0x11914, 0x11914,
+ 0x11917, 0x11917,
+ 0x11936, 0x11936,
+ 0x11939, 0x1193a,
+ 0x11947, 0x1194f,
+ 0x1195a, 0x1199f,
+ 0x119a8, 0x119a9,
+ 0x119d8, 0x119d9,
+ 0x119e5, 0x119ff,
+ 0x11a48, 0x11a4f,
+ 0x11aa3, 0x11aaf,
+ 0x11af9, 0x11aff,
+ 0x11b0a, 0x11b5f,
+ 0x11b68, 0x11bbf,
+ 0x11be2, 0x11bef,
+ 0x11bfa, 0x11bff,
+ 0x11c09, 0x11c09,
+ 0x11c37, 0x11c37,
+ 0x11c46, 0x11c4f,
+ 0x11c6d, 0x11c6f,
+ 0x11c90, 0x11c91,
+ 0x11ca8, 0x11ca8,
+ 0x11cb7, 0x11cff,
+ 0x11d07, 0x11d07,
+ 0x11d0a, 0x11d0a,
+ 0x11d37, 0x11d39,
+ 0x11d3b, 0x11d3b,
+ 0x11d3e, 0x11d3e,
+ 0x11d48, 0x11d4f,
+ 0x11d5a, 0x11d5f,
+ 0x11d66, 0x11d66,
+ 0x11d69, 0x11d69,
+ 0x11d8f, 0x11d8f,
+ 0x11d92, 0x11d92,
+ 0x11d99, 0x11d9f,
+ 0x11daa, 0x11daf,
+ 0x11ddc, 0x11ddf,
+ 0x11dea, 0x11edf,
+ 0x11ef9, 0x11eff,
+ 0x11f11, 0x11f11,
+ 0x11f3b, 0x11f3d,
+ 0x11f5b, 0x11faf,
+ 0x11fb1, 0x11fbf,
+ 0x11ff2, 0x11ffe,
+ 0x1239a, 0x123ff,
+ 0x1246f, 0x1246f,
+ 0x12475, 0x1247f,
+ 0x12544, 0x12f8f,
+ 0x12ff3, 0x12fff,
+ 0x13456, 0x1345f,
+ 0x143fb, 0x143ff,
+ 0x14647, 0x160ff,
+ 0x1613a, 0x167ff,
+ 0x16a39, 0x16a3f,
+ 0x16a5f, 0x16a5f,
+ 0x16a6a, 0x16a6d,
+ 0x16abf, 0x16abf,
+ 0x16aca, 0x16acf,
+ 0x16aee, 0x16aef,
+ 0x16af6, 0x16aff,
+ 0x16b46, 0x16b4f,
+ 0x16b5a, 0x16b5a,
+ 0x16b62, 0x16b62,
+ 0x16b78, 0x16b7c,
+ 0x16b90, 0x16d3f,
+ 0x16d7a, 0x16e3f,
+ 0x16e9b, 0x16e9f,
+ 0x16eb9, 0x16eba,
+ 0x16ed4, 0x16eff,
+ 0x16f4b, 0x16f4e,
+ 0x16f88, 0x16f8e,
+ 0x16fa0, 0x16fdf,
+ 0x16fe5, 0x16fef,
+ 0x16ff7, 0x16fff,
+ 0x18cd6, 0x18cfe,
+ 0x18d1f, 0x18d7f,
+ 0x18df3, 0x1afef,
+ 0x1aff4, 0x1aff4,
+ 0x1affc, 0x1affc,
+ 0x1afff, 0x1afff,
+ 0x1b123, 0x1b131,
+ 0x1b133, 0x1b14f,
+ 0x1b153, 0x1b154,
+ 0x1b156, 0x1b163,
+ 0x1b168, 0x1b16f,
+ 0x1b2fc, 0x1bbff,
+ 0x1bc6b, 0x1bc6f,
+ 0x1bc7d, 0x1bc7f,
+ 0x1bc89, 0x1bc8f,
+ 0x1bc9a, 0x1bc9b,
+ 0x1bca4, 0x1cbff,
+ 0x1ccfd, 0x1ccff,
+ 0x1ceb4, 0x1ceb9,
+ 0x1ced1, 0x1cedf,
+ 0x1cef1, 0x1ceff,
+ 0x1cf2e, 0x1cf2f,
+ 0x1cf47, 0x1cf4f,
+ 0x1cfc4, 0x1cfff,
+ 0x1d0f6, 0x1d0ff,
+ 0x1d127, 0x1d128,
+ 0x1d1eb, 0x1d1ff,
+ 0x1d246, 0x1d2bf,
+ 0x1d2d4, 0x1d2df,
+ 0x1d2f4, 0x1d2ff,
+ 0x1d357, 0x1d35f,
+ 0x1d379, 0x1d3ff,
+ 0x1d455, 0x1d455,
+ 0x1d49d, 0x1d49d,
+ 0x1d4a0, 0x1d4a1,
+ 0x1d4a3, 0x1d4a4,
+ 0x1d4a7, 0x1d4a8,
+ 0x1d4ad, 0x1d4ad,
+ 0x1d4ba, 0x1d4ba,
+ 0x1d4bc, 0x1d4bc,
+ 0x1d4c4, 0x1d4c4,
+ 0x1d506, 0x1d506,
+ 0x1d50b, 0x1d50c,
+ 0x1d515, 0x1d515,
+ 0x1d51d, 0x1d51d,
+ 0x1d53a, 0x1d53a,
+ 0x1d53f, 0x1d53f,
+ 0x1d545, 0x1d545,
+ 0x1d547, 0x1d549,
+ 0x1d551, 0x1d551,
+ 0x1d6a6, 0x1d6a7,
+ 0x1d7cc, 0x1d7cd,
+ 0x1da8c, 0x1da9a,
+ 0x1daa0, 0x1daa0,
+ 0x1dab0, 0x1deff,
+ 0x1df1f, 0x1df24,
+ 0x1df2b, 0x1dfff,
+ 0x1e007, 0x1e007,
+ 0x1e019, 0x1e01a,
+ 0x1e022, 0x1e022,
+ 0x1e025, 0x1e025,
+ 0x1e02b, 0x1e02f,
+ 0x1e06e, 0x1e08e,
+ 0x1e090, 0x1e0ff,
+ 0x1e12d, 0x1e12f,
+ 0x1e13e, 0x1e13f,
+ 0x1e14a, 0x1e14d,
+ 0x1e150, 0x1e28f,
+ 0x1e2af, 0x1e2bf,
+ 0x1e2fa, 0x1e2fe,
+ 0x1e300, 0x1e4cf,
+ 0x1e4fa, 0x1e5cf,
+ 0x1e5fb, 0x1e5fe,
+ 0x1e600, 0x1e6bf,
+ 0x1e6df, 0x1e6df,
+ 0x1e6f6, 0x1e6fd,
+ 0x1e700, 0x1e7df,
+ 0x1e7e7, 0x1e7e7,
+ 0x1e7ec, 0x1e7ec,
+ 0x1e7ef, 0x1e7ef,
+ 0x1e7ff, 0x1e7ff,
+ 0x1e8c5, 0x1e8c6,
+ 0x1e8d7, 0x1e8ff,
+ 0x1e94c, 0x1e94f,
+ 0x1e95a, 0x1e95d,
+ 0x1e960, 0x1ec70,
+ 0x1ecb5, 0x1ed00,
+ 0x1ed3e, 0x1edff,
+ 0x1ee04, 0x1ee04,
+ 0x1ee20, 0x1ee20,
+ 0x1ee23, 0x1ee23,
+ 0x1ee25, 0x1ee26,
+ 0x1ee28, 0x1ee28,
+ 0x1ee33, 0x1ee33,
+ 0x1ee38, 0x1ee38,
+ 0x1ee3a, 0x1ee3a,
+ 0x1ee3c, 0x1ee41,
+ 0x1ee43, 0x1ee46,
+ 0x1ee48, 0x1ee48,
+ 0x1ee4a, 0x1ee4a,
+ 0x1ee4c, 0x1ee4c,
+ 0x1ee50, 0x1ee50,
+ 0x1ee53, 0x1ee53,
+ 0x1ee55, 0x1ee56,
+ 0x1ee58, 0x1ee58,
+ 0x1ee5a, 0x1ee5a,
+ 0x1ee5c, 0x1ee5c,
+ 0x1ee5e, 0x1ee5e,
+ 0x1ee60, 0x1ee60,
+ 0x1ee63, 0x1ee63,
+ 0x1ee65, 0x1ee66,
+ 0x1ee6b, 0x1ee6b,
+ 0x1ee73, 0x1ee73,
+ 0x1ee78, 0x1ee78,
+ 0x1ee7d, 0x1ee7d,
+ 0x1ee7f, 0x1ee7f,
+ 0x1ee8a, 0x1ee8a,
+ 0x1ee9c, 0x1eea0,
+ 0x1eea4, 0x1eea4,
+ 0x1eeaa, 0x1eeaa,
+ 0x1eebc, 0x1eeef,
+ 0x1eef2, 0x1efff,
+ 0x1f02c, 0x1f02f,
+ 0x1f094, 0x1f09f,
+ 0x1f0af, 0x1f0b0,
+ 0x1f0c0, 0x1f0c0,
+ 0x1f0d0, 0x1f0d0,
+ 0x1f0f6, 0x1f0ff,
+ 0x1f1ae, 0x1f1e5,
+ 0x1f203, 0x1f20f,
+ 0x1f23c, 0x1f23f,
+ 0x1f249, 0x1f24f,
+ 0x1f252, 0x1f25f,
+ 0x1f266, 0x1f2ff,
+ 0x1f6d9, 0x1f6db,
+ 0x1f6ed, 0x1f6ef,
+ 0x1f6fd, 0x1f6ff,
+ 0x1f7da, 0x1f7df,
+ 0x1f7ec, 0x1f7ef,
+ 0x1f7f1, 0x1f7ff,
+ 0x1f80c, 0x1f80f,
+ 0x1f848, 0x1f84f,
+ 0x1f85a, 0x1f85f,
+ 0x1f888, 0x1f88f,
+ 0x1f8ae, 0x1f8af,
+ 0x1f8bc, 0x1f8bf,
+ 0x1f8c2, 0x1f8cf,
+ 0x1f8d9, 0x1f8ff,
+ 0x1fa58, 0x1fa5f,
+ 0x1fa6e, 0x1fa6f,
+ 0x1fa7d, 0x1fa7f,
+ 0x1fa8b, 0x1fa8d,
+ 0x1fac7, 0x1fac7,
+ 0x1fac9, 0x1facc,
+ 0x1fadd, 0x1fade,
+ 0x1faeb, 0x1faee,
+ 0x1faf9, 0x1faff,
+ 0x1fb93, 0x1fb93,
+ 0x1fbfb, 0x1ffff,
+ 0x2a6e0, 0x2a6ff,
+ 0x2b81e, 0x2b81f,
+ 0x2ceae, 0x2ceaf,
+ 0x2ebe1, 0x2ebef,
+ 0x2ee5e, 0x2f7ff,
+ 0x2fa1e, 0x2ffff,
+ 0x3134b, 0x3134f,
+ 0x3347a, 0xe0000,
+ 0xe0002, 0xe001f,
+ 0xe0080, 0xe00ff,
+ 0xe01f0, 0xeffff,
+ 0xffffe, 0xfffff,
+ 0x10fffe, 0x10ffff,
+}; /* CR_Cn */
+
+/* 'Co': General Category */
+static const OnigCodePoint CR_Co[] = {
+ 3,
+ 0xe000, 0xf8ff,
+ 0xf0000, 0xffffd,
+ 0x100000, 0x10fffd,
+}; /* CR_Co */
+
+/* 'Cs': General Category */
+static const OnigCodePoint CR_Cs[] = {
+ 1,
+ 0xd800, 0xdfff,
+}; /* CR_Cs */
+
+/* 'L': Major Category */
+static const OnigCodePoint CR_L[] = {
+ 684,
+ 0x0041, 0x005a,
+ 0x0061, 0x007a,
+ 0x00aa, 0x00aa,
+ 0x00b5, 0x00b5,
+ 0x00ba, 0x00ba,
+ 0x00c0, 0x00d6,
+ 0x00d8, 0x00f6,
+ 0x00f8, 0x02c1,
+ 0x02c6, 0x02d1,
+ 0x02e0, 0x02e4,
+ 0x02ec, 0x02ec,
+ 0x02ee, 0x02ee,
+ 0x0370, 0x0374,
+ 0x0376, 0x0377,
+ 0x037a, 0x037d,
+ 0x037f, 0x037f,
+ 0x0386, 0x0386,
+ 0x0388, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x03f5,
+ 0x03f7, 0x0481,
+ 0x048a, 0x052f,
+ 0x0531, 0x0556,
+ 0x0559, 0x0559,
+ 0x0560, 0x0588,
+ 0x05d0, 0x05ea,
+ 0x05ef, 0x05f2,
+ 0x0620, 0x064a,
+ 0x066e, 0x066f,
+ 0x0671, 0x06d3,
+ 0x06d5, 0x06d5,
+ 0x06e5, 0x06e6,
+ 0x06ee, 0x06ef,
+ 0x06fa, 0x06fc,
+ 0x06ff, 0x06ff,
+ 0x0710, 0x0710,
+ 0x0712, 0x072f,
+ 0x074d, 0x07a5,
+ 0x07b1, 0x07b1,
+ 0x07ca, 0x07ea,
+ 0x07f4, 0x07f5,
+ 0x07fa, 0x07fa,
+ 0x0800, 0x0815,
+ 0x081a, 0x081a,
+ 0x0824, 0x0824,
+ 0x0828, 0x0828,
+ 0x0840, 0x0858,
+ 0x0860, 0x086a,
+ 0x0870, 0x0887,
+ 0x0889, 0x088f,
+ 0x08a0, 0x08c9,
+ 0x0904, 0x0939,
+ 0x093d, 0x093d,
+ 0x0950, 0x0950,
+ 0x0958, 0x0961,
+ 0x0971, 0x0980,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bd, 0x09bd,
+ 0x09ce, 0x09ce,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e1,
+ 0x09f0, 0x09f1,
+ 0x09fc, 0x09fc,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a72, 0x0a74,
+ 0x0a85, 0x0a8d,
+ 0x0a8f, 0x0a91,
+ 0x0a93, 0x0aa8,
+ 0x0aaa, 0x0ab0,
+ 0x0ab2, 0x0ab3,
+ 0x0ab5, 0x0ab9,
+ 0x0abd, 0x0abd,
+ 0x0ad0, 0x0ad0,
+ 0x0ae0, 0x0ae1,
+ 0x0af9, 0x0af9,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b35, 0x0b39,
+ 0x0b3d, 0x0b3d,
+ 0x0b5c, 0x0b5d,
+ 0x0b5f, 0x0b61,
+ 0x0b71, 0x0b71,
+ 0x0b83, 0x0b83,
+ 0x0b85, 0x0b8a,
+ 0x0b8e, 0x0b90,
+ 0x0b92, 0x0b95,
+ 0x0b99, 0x0b9a,
+ 0x0b9c, 0x0b9c,
+ 0x0b9e, 0x0b9f,
+ 0x0ba3, 0x0ba4,
+ 0x0ba8, 0x0baa,
+ 0x0bae, 0x0bb9,
+ 0x0bd0, 0x0bd0,
+ 0x0c05, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3d, 0x0c3d,
+ 0x0c58, 0x0c5a,
+ 0x0c5c, 0x0c5d,
+ 0x0c60, 0x0c61,
+ 0x0c80, 0x0c80,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbd, 0x0cbd,
+ 0x0cdc, 0x0cde,
+ 0x0ce0, 0x0ce1,
+ 0x0cf1, 0x0cf2,
+ 0x0d04, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d3a,
+ 0x0d3d, 0x0d3d,
+ 0x0d4e, 0x0d4e,
+ 0x0d54, 0x0d56,
+ 0x0d5f, 0x0d61,
+ 0x0d7a, 0x0d7f,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0e01, 0x0e30,
+ 0x0e32, 0x0e33,
+ 0x0e40, 0x0e46,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e86, 0x0e8a,
+ 0x0e8c, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0eb0,
+ 0x0eb2, 0x0eb3,
+ 0x0ebd, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f00,
+ 0x0f40, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f88, 0x0f8c,
+ 0x1000, 0x102a,
+ 0x103f, 0x103f,
+ 0x1050, 0x1055,
+ 0x105a, 0x105d,
+ 0x1061, 0x1061,
+ 0x1065, 0x1066,
+ 0x106e, 0x1070,
+ 0x1075, 0x1081,
+ 0x108e, 0x108e,
+ 0x10a0, 0x10c5,
+ 0x10c7, 0x10c7,
+ 0x10cd, 0x10cd,
+ 0x10d0, 0x10fa,
+ 0x10fc, 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,
+ 0x1380, 0x138f,
+ 0x13a0, 0x13f5,
+ 0x13f8, 0x13fd,
+ 0x1401, 0x166c,
+ 0x166f, 0x167f,
+ 0x1681, 0x169a,
+ 0x16a0, 0x16ea,
+ 0x16f1, 0x16f8,
+ 0x1700, 0x1711,
+ 0x171f, 0x1731,
+ 0x1740, 0x1751,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1780, 0x17b3,
+ 0x17d7, 0x17d7,
+ 0x17dc, 0x17dc,
+ 0x1820, 0x1878,
+ 0x1880, 0x1884,
+ 0x1887, 0x18a8,
+ 0x18aa, 0x18aa,
+ 0x18b0, 0x18f5,
+ 0x1900, 0x191e,
+ 0x1950, 0x196d,
+ 0x1970, 0x1974,
+ 0x1980, 0x19ab,
+ 0x19b0, 0x19c9,
+ 0x1a00, 0x1a16,
+ 0x1a20, 0x1a54,
+ 0x1aa7, 0x1aa7,
+ 0x1b05, 0x1b33,
+ 0x1b45, 0x1b4c,
+ 0x1b83, 0x1ba0,
+ 0x1bae, 0x1baf,
+ 0x1bba, 0x1be5,
+ 0x1c00, 0x1c23,
+ 0x1c4d, 0x1c4f,
+ 0x1c5a, 0x1c7d,
+ 0x1c80, 0x1c8a,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cbf,
+ 0x1ce9, 0x1cec,
+ 0x1cee, 0x1cf3,
+ 0x1cf5, 0x1cf6,
+ 0x1cfa, 0x1cfa,
+ 0x1d00, 0x1dbf,
+ 0x1e00, 0x1f15,
+ 0x1f18, 0x1f1d,
+ 0x1f20, 0x1f45,
+ 0x1f48, 0x1f4d,
+ 0x1f50, 0x1f57,
+ 0x1f59, 0x1f59,
+ 0x1f5b, 0x1f5b,
+ 0x1f5d, 0x1f5d,
+ 0x1f5f, 0x1f7d,
+ 0x1f80, 0x1fb4,
+ 0x1fb6, 0x1fbc,
+ 0x1fbe, 0x1fbe,
+ 0x1fc2, 0x1fc4,
+ 0x1fc6, 0x1fcc,
+ 0x1fd0, 0x1fd3,
+ 0x1fd6, 0x1fdb,
+ 0x1fe0, 0x1fec,
+ 0x1ff2, 0x1ff4,
+ 0x1ff6, 0x1ffc,
+ 0x2071, 0x2071,
+ 0x207f, 0x207f,
+ 0x2090, 0x209c,
+ 0x2102, 0x2102,
+ 0x2107, 0x2107,
+ 0x210a, 0x2113,
+ 0x2115, 0x2115,
+ 0x2119, 0x211d,
+ 0x2124, 0x2124,
+ 0x2126, 0x2126,
+ 0x2128, 0x2128,
+ 0x212a, 0x212d,
+ 0x212f, 0x2139,
+ 0x213c, 0x213f,
+ 0x2145, 0x2149,
+ 0x214e, 0x214e,
+ 0x2183, 0x2184,
+ 0x2c00, 0x2ce4,
+ 0x2ceb, 0x2cee,
+ 0x2cf2, 0x2cf3,
+ 0x2d00, 0x2d25,
+ 0x2d27, 0x2d27,
+ 0x2d2d, 0x2d2d,
+ 0x2d30, 0x2d67,
+ 0x2d6f, 0x2d6f,
+ 0x2d80, 0x2d96,
+ 0x2da0, 0x2da6,
+ 0x2da8, 0x2dae,
+ 0x2db0, 0x2db6,
+ 0x2db8, 0x2dbe,
+ 0x2dc0, 0x2dc6,
+ 0x2dc8, 0x2dce,
+ 0x2dd0, 0x2dd6,
+ 0x2dd8, 0x2dde,
+ 0x2e2f, 0x2e2f,
+ 0x3005, 0x3006,
+ 0x3031, 0x3035,
+ 0x303b, 0x303c,
+ 0x3041, 0x3096,
+ 0x309d, 0x309f,
+ 0x30a1, 0x30fa,
+ 0x30fc, 0x30ff,
+ 0x3105, 0x312f,
+ 0x3131, 0x318e,
+ 0x31a0, 0x31bf,
+ 0x31f0, 0x31ff,
+ 0x3400, 0x4dbf,
+ 0x4e00, 0xa48c,
+ 0xa4d0, 0xa4fd,
+ 0xa500, 0xa60c,
+ 0xa610, 0xa61f,
+ 0xa62a, 0xa62b,
+ 0xa640, 0xa66e,
+ 0xa67f, 0xa69d,
+ 0xa6a0, 0xa6e5,
+ 0xa717, 0xa71f,
+ 0xa722, 0xa788,
+ 0xa78b, 0xa7dc,
+ 0xa7f1, 0xa801,
+ 0xa803, 0xa805,
+ 0xa807, 0xa80a,
+ 0xa80c, 0xa822,
+ 0xa840, 0xa873,
+ 0xa882, 0xa8b3,
+ 0xa8f2, 0xa8f7,
+ 0xa8fb, 0xa8fb,
+ 0xa8fd, 0xa8fe,
+ 0xa90a, 0xa925,
+ 0xa930, 0xa946,
+ 0xa960, 0xa97c,
+ 0xa984, 0xa9b2,
+ 0xa9cf, 0xa9cf,
+ 0xa9e0, 0xa9e4,
+ 0xa9e6, 0xa9ef,
+ 0xa9fa, 0xa9fe,
+ 0xaa00, 0xaa28,
+ 0xaa40, 0xaa42,
+ 0xaa44, 0xaa4b,
+ 0xaa60, 0xaa76,
+ 0xaa7a, 0xaa7a,
+ 0xaa7e, 0xaaaf,
+ 0xaab1, 0xaab1,
+ 0xaab5, 0xaab6,
+ 0xaab9, 0xaabd,
+ 0xaac0, 0xaac0,
+ 0xaac2, 0xaac2,
+ 0xaadb, 0xaadd,
+ 0xaae0, 0xaaea,
+ 0xaaf2, 0xaaf4,
+ 0xab01, 0xab06,
+ 0xab09, 0xab0e,
+ 0xab11, 0xab16,
+ 0xab20, 0xab26,
+ 0xab28, 0xab2e,
+ 0xab30, 0xab5a,
+ 0xab5c, 0xab69,
+ 0xab70, 0xabe2,
+ 0xac00, 0xd7a3,
+ 0xd7b0, 0xd7c6,
+ 0xd7cb, 0xd7fb,
+ 0xf900, 0xfa6d,
+ 0xfa70, 0xfad9,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xfb1d, 0xfb1d,
+ 0xfb1f, 0xfb28,
+ 0xfb2a, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfbb1,
+ 0xfbd3, 0xfd3d,
+ 0xfd50, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdf0, 0xfdfb,
+ 0xfe70, 0xfe74,
+ 0xfe76, 0xfefc,
+ 0xff21, 0xff3a,
+ 0xff41, 0xff5a,
+ 0xff66, 0xffbe,
+ 0xffc2, 0xffc7,
+ 0xffca, 0xffcf,
+ 0xffd2, 0xffd7,
+ 0xffda, 0xffdc,
+ 0x10000, 0x1000b,
+ 0x1000d, 0x10026,
+ 0x10028, 0x1003a,
+ 0x1003c, 0x1003d,
+ 0x1003f, 0x1004d,
+ 0x10050, 0x1005d,
+ 0x10080, 0x100fa,
+ 0x10280, 0x1029c,
+ 0x102a0, 0x102d0,
+ 0x10300, 0x1031f,
+ 0x1032d, 0x10340,
+ 0x10342, 0x10349,
+ 0x10350, 0x10375,
+ 0x10380, 0x1039d,
+ 0x103a0, 0x103c3,
+ 0x103c8, 0x103cf,
+ 0x10400, 0x1049d,
+ 0x104b0, 0x104d3,
+ 0x104d8, 0x104fb,
+ 0x10500, 0x10527,
+ 0x10530, 0x10563,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x105c0, 0x105f3,
+ 0x10600, 0x10736,
+ 0x10740, 0x10755,
+ 0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 0x10837, 0x10838,
+ 0x1083c, 0x1083c,
+ 0x1083f, 0x10855,
+ 0x10860, 0x10876,
+ 0x10880, 0x1089e,
+ 0x108e0, 0x108f2,
+ 0x108f4, 0x108f5,
+ 0x10900, 0x10915,
+ 0x10920, 0x10939,
+ 0x10940, 0x10959,
+ 0x10980, 0x109b7,
+ 0x109be, 0x109bf,
+ 0x10a00, 0x10a00,
+ 0x10a10, 0x10a13,
+ 0x10a15, 0x10a17,
+ 0x10a19, 0x10a35,
+ 0x10a60, 0x10a7c,
+ 0x10a80, 0x10a9c,
+ 0x10ac0, 0x10ac7,
+ 0x10ac9, 0x10ae4,
+ 0x10b00, 0x10b35,
+ 0x10b40, 0x10b55,
+ 0x10b60, 0x10b72,
+ 0x10b80, 0x10b91,
+ 0x10c00, 0x10c48,
+ 0x10c80, 0x10cb2,
+ 0x10cc0, 0x10cf2,
+ 0x10d00, 0x10d23,
+ 0x10d4a, 0x10d65,
+ 0x10d6f, 0x10d85,
+ 0x10e80, 0x10ea9,
+ 0x10eb0, 0x10eb1,
+ 0x10ec2, 0x10ec7,
+ 0x10f00, 0x10f1c,
+ 0x10f27, 0x10f27,
+ 0x10f30, 0x10f45,
+ 0x10f70, 0x10f81,
+ 0x10fb0, 0x10fc4,
+ 0x10fe0, 0x10ff6,
+ 0x11003, 0x11037,
+ 0x11071, 0x11072,
+ 0x11075, 0x11075,
+ 0x11083, 0x110af,
+ 0x110d0, 0x110e8,
+ 0x11103, 0x11126,
+ 0x11144, 0x11144,
+ 0x11147, 0x11147,
+ 0x11150, 0x11172,
+ 0x11176, 0x11176,
+ 0x11183, 0x111b2,
+ 0x111c1, 0x111c4,
+ 0x111da, 0x111da,
+ 0x111dc, 0x111dc,
+ 0x11200, 0x11211,
+ 0x11213, 0x1122b,
+ 0x1123f, 0x11240,
+ 0x11280, 0x11286,
+ 0x11288, 0x11288,
+ 0x1128a, 0x1128d,
+ 0x1128f, 0x1129d,
+ 0x1129f, 0x112a8,
+ 0x112b0, 0x112de,
+ 0x11305, 0x1130c,
+ 0x1130f, 0x11310,
+ 0x11313, 0x11328,
+ 0x1132a, 0x11330,
+ 0x11332, 0x11333,
+ 0x11335, 0x11339,
+ 0x1133d, 0x1133d,
+ 0x11350, 0x11350,
+ 0x1135d, 0x11361,
+ 0x11380, 0x11389,
+ 0x1138b, 0x1138b,
+ 0x1138e, 0x1138e,
+ 0x11390, 0x113b5,
+ 0x113b7, 0x113b7,
+ 0x113d1, 0x113d1,
+ 0x113d3, 0x113d3,
+ 0x11400, 0x11434,
+ 0x11447, 0x1144a,
+ 0x1145f, 0x11461,
+ 0x11480, 0x114af,
+ 0x114c4, 0x114c5,
+ 0x114c7, 0x114c7,
+ 0x11580, 0x115ae,
+ 0x115d8, 0x115db,
+ 0x11600, 0x1162f,
+ 0x11644, 0x11644,
+ 0x11680, 0x116aa,
+ 0x116b8, 0x116b8,
+ 0x11700, 0x1171a,
+ 0x11740, 0x11746,
+ 0x11800, 0x1182b,
+ 0x118a0, 0x118df,
+ 0x118ff, 0x11906,
+ 0x11909, 0x11909,
+ 0x1190c, 0x11913,
+ 0x11915, 0x11916,
+ 0x11918, 0x1192f,
+ 0x1193f, 0x1193f,
+ 0x11941, 0x11941,
+ 0x119a0, 0x119a7,
+ 0x119aa, 0x119d0,
+ 0x119e1, 0x119e1,
+ 0x119e3, 0x119e3,
+ 0x11a00, 0x11a00,
+ 0x11a0b, 0x11a32,
+ 0x11a3a, 0x11a3a,
+ 0x11a50, 0x11a50,
+ 0x11a5c, 0x11a89,
+ 0x11a9d, 0x11a9d,
+ 0x11ab0, 0x11af8,
+ 0x11bc0, 0x11be0,
+ 0x11c00, 0x11c08,
+ 0x11c0a, 0x11c2e,
+ 0x11c40, 0x11c40,
+ 0x11c72, 0x11c8f,
+ 0x11d00, 0x11d06,
+ 0x11d08, 0x11d09,
+ 0x11d0b, 0x11d30,
+ 0x11d46, 0x11d46,
+ 0x11d60, 0x11d65,
+ 0x11d67, 0x11d68,
+ 0x11d6a, 0x11d89,
+ 0x11d98, 0x11d98,
+ 0x11db0, 0x11ddb,
+ 0x11ee0, 0x11ef2,
+ 0x11f02, 0x11f02,
+ 0x11f04, 0x11f10,
+ 0x11f12, 0x11f33,
+ 0x11fb0, 0x11fb0,
+ 0x12000, 0x12399,
+ 0x12480, 0x12543,
+ 0x12f90, 0x12ff0,
+ 0x13000, 0x1342f,
+ 0x13441, 0x13446,
+ 0x13460, 0x143fa,
+ 0x14400, 0x14646,
+ 0x16100, 0x1611d,
+ 0x16800, 0x16a38,
+ 0x16a40, 0x16a5e,
+ 0x16a70, 0x16abe,
+ 0x16ad0, 0x16aed,
+ 0x16b00, 0x16b2f,
+ 0x16b40, 0x16b43,
+ 0x16b63, 0x16b77,
+ 0x16b7d, 0x16b8f,
+ 0x16d40, 0x16d6c,
+ 0x16e40, 0x16e7f,
+ 0x16ea0, 0x16eb8,
+ 0x16ebb, 0x16ed3,
+ 0x16f00, 0x16f4a,
+ 0x16f50, 0x16f50,
+ 0x16f93, 0x16f9f,
+ 0x16fe0, 0x16fe1,
+ 0x16fe3, 0x16fe3,
+ 0x16ff2, 0x16ff3,
+ 0x17000, 0x18cd5,
+ 0x18cff, 0x18d1e,
+ 0x18d80, 0x18df2,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
+ 0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
+ 0x1b164, 0x1b167,
+ 0x1b170, 0x1b2fb,
+ 0x1bc00, 0x1bc6a,
+ 0x1bc70, 0x1bc7c,
+ 0x1bc80, 0x1bc88,
+ 0x1bc90, 0x1bc99,
+ 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, 0x1d6c0,
+ 0x1d6c2, 0x1d6da,
+ 0x1d6dc, 0x1d6fa,
+ 0x1d6fc, 0x1d714,
+ 0x1d716, 0x1d734,
+ 0x1d736, 0x1d74e,
+ 0x1d750, 0x1d76e,
+ 0x1d770, 0x1d788,
+ 0x1d78a, 0x1d7a8,
+ 0x1d7aa, 0x1d7c2,
+ 0x1d7c4, 0x1d7cb,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e030, 0x1e06d,
+ 0x1e100, 0x1e12c,
+ 0x1e137, 0x1e13d,
+ 0x1e14e, 0x1e14e,
+ 0x1e290, 0x1e2ad,
+ 0x1e2c0, 0x1e2eb,
+ 0x1e4d0, 0x1e4eb,
+ 0x1e5d0, 0x1e5ed,
+ 0x1e5f0, 0x1e5f0,
+ 0x1e6c0, 0x1e6de,
+ 0x1e6e0, 0x1e6e2,
+ 0x1e6e4, 0x1e6e5,
+ 0x1e6e7, 0x1e6ed,
+ 0x1e6f0, 0x1e6f4,
+ 0x1e6fe, 0x1e6ff,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
+ 0x1e800, 0x1e8c4,
+ 0x1e900, 0x1e943,
+ 0x1e94b, 0x1e94b,
+ 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,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b81d,
+ 0x2b820, 0x2cead,
+ 0x2ceb0, 0x2ebe0,
+ 0x2ebf0, 0x2ee5d,
+ 0x2f800, 0x2fa1d,
+ 0x30000, 0x3134a,
+ 0x31350, 0x33479,
+}; /* CR_L */
+
+/* 'LC': General Category */
+static const OnigCodePoint CR_LC[] = {
+ 144,
+ 0x0041, 0x005a,
+ 0x0061, 0x007a,
+ 0x00b5, 0x00b5,
+ 0x00c0, 0x00d6,
+ 0x00d8, 0x00f6,
+ 0x00f8, 0x01ba,
+ 0x01bc, 0x01bf,
+ 0x01c4, 0x0293,
+ 0x0296, 0x02af,
+ 0x0370, 0x0373,
+ 0x0376, 0x0377,
+ 0x037b, 0x037d,
+ 0x037f, 0x037f,
+ 0x0386, 0x0386,
+ 0x0388, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x03f5,
+ 0x03f7, 0x0481,
+ 0x048a, 0x052f,
+ 0x0531, 0x0556,
+ 0x0560, 0x0588,
+ 0x10a0, 0x10c5,
+ 0x10c7, 0x10c7,
+ 0x10cd, 0x10cd,
+ 0x10d0, 0x10fa,
+ 0x10fd, 0x10ff,
+ 0x13a0, 0x13f5,
+ 0x13f8, 0x13fd,
+ 0x1c80, 0x1c8a,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cbf,
+ 0x1d00, 0x1d2b,
+ 0x1d6b, 0x1d77,
+ 0x1d79, 0x1d9a,
+ 0x1e00, 0x1f15,
+ 0x1f18, 0x1f1d,
+ 0x1f20, 0x1f45,
+ 0x1f48, 0x1f4d,
+ 0x1f50, 0x1f57,
+ 0x1f59, 0x1f59,
+ 0x1f5b, 0x1f5b,
+ 0x1f5d, 0x1f5d,
+ 0x1f5f, 0x1f7d,
+ 0x1f80, 0x1fb4,
+ 0x1fb6, 0x1fbc,
+ 0x1fbe, 0x1fbe,
+ 0x1fc2, 0x1fc4,
+ 0x1fc6, 0x1fcc,
+ 0x1fd0, 0x1fd3,
+ 0x1fd6, 0x1fdb,
+ 0x1fe0, 0x1fec,
+ 0x1ff2, 0x1ff4,
+ 0x1ff6, 0x1ffc,
+ 0x2102, 0x2102,
+ 0x2107, 0x2107,
+ 0x210a, 0x2113,
+ 0x2115, 0x2115,
+ 0x2119, 0x211d,
+ 0x2124, 0x2124,
+ 0x2126, 0x2126,
+ 0x2128, 0x2128,
+ 0x212a, 0x212d,
+ 0x212f, 0x2134,
+ 0x2139, 0x2139,
+ 0x213c, 0x213f,
+ 0x2145, 0x2149,
+ 0x214e, 0x214e,
+ 0x2183, 0x2184,
+ 0x2c00, 0x2c7b,
+ 0x2c7e, 0x2ce4,
+ 0x2ceb, 0x2cee,
+ 0x2cf2, 0x2cf3,
+ 0x2d00, 0x2d25,
+ 0x2d27, 0x2d27,
+ 0x2d2d, 0x2d2d,
+ 0xa640, 0xa66d,
+ 0xa680, 0xa69b,
+ 0xa722, 0xa76f,
+ 0xa771, 0xa787,
+ 0xa78b, 0xa78e,
+ 0xa790, 0xa7dc,
+ 0xa7f5, 0xa7f6,
+ 0xa7fa, 0xa7fa,
+ 0xab30, 0xab5a,
+ 0xab60, 0xab68,
+ 0xab70, 0xabbf,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xff21, 0xff3a,
+ 0xff41, 0xff5a,
+ 0x10400, 0x1044f,
+ 0x104b0, 0x104d3,
+ 0x104d8, 0x104fb,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x10c80, 0x10cb2,
+ 0x10cc0, 0x10cf2,
+ 0x10d50, 0x10d65,
+ 0x10d70, 0x10d85,
+ 0x118a0, 0x118df,
+ 0x16e40, 0x16e7f,
+ 0x16ea0, 0x16eb8,
+ 0x16ebb, 0x16ed3,
+ 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, 0x1d6c0,
+ 0x1d6c2, 0x1d6da,
+ 0x1d6dc, 0x1d6fa,
+ 0x1d6fc, 0x1d714,
+ 0x1d716, 0x1d734,
+ 0x1d736, 0x1d74e,
+ 0x1d750, 0x1d76e,
+ 0x1d770, 0x1d788,
+ 0x1d78a, 0x1d7a8,
+ 0x1d7aa, 0x1d7c2,
+ 0x1d7c4, 0x1d7cb,
+ 0x1df00, 0x1df09,
+ 0x1df0b, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e900, 0x1e943,
+}; /* CR_LC */
+
+/* 'Ll': General Category */
+static const OnigCodePoint CR_Ll[] = {
+ 664,
+ 0x0061, 0x007a,
+ 0x00b5, 0x00b5,
+ 0x00df, 0x00f6,
+ 0x00f8, 0x00ff,
+ 0x0101, 0x0101,
+ 0x0103, 0x0103,
+ 0x0105, 0x0105,
+ 0x0107, 0x0107,
+ 0x0109, 0x0109,
+ 0x010b, 0x010b,
+ 0x010d, 0x010d,
+ 0x010f, 0x010f,
+ 0x0111, 0x0111,
+ 0x0113, 0x0113,
+ 0x0115, 0x0115,
+ 0x0117, 0x0117,
+ 0x0119, 0x0119,
+ 0x011b, 0x011b,
+ 0x011d, 0x011d,
+ 0x011f, 0x011f,
+ 0x0121, 0x0121,
+ 0x0123, 0x0123,
+ 0x0125, 0x0125,
+ 0x0127, 0x0127,
+ 0x0129, 0x0129,
+ 0x012b, 0x012b,
+ 0x012d, 0x012d,
+ 0x012f, 0x012f,
+ 0x0131, 0x0131,
+ 0x0133, 0x0133,
+ 0x0135, 0x0135,
+ 0x0137, 0x0138,
+ 0x013a, 0x013a,
+ 0x013c, 0x013c,
+ 0x013e, 0x013e,
+ 0x0140, 0x0140,
+ 0x0142, 0x0142,
+ 0x0144, 0x0144,
+ 0x0146, 0x0146,
+ 0x0148, 0x0149,
+ 0x014b, 0x014b,
+ 0x014d, 0x014d,
+ 0x014f, 0x014f,
+ 0x0151, 0x0151,
+ 0x0153, 0x0153,
+ 0x0155, 0x0155,
+ 0x0157, 0x0157,
+ 0x0159, 0x0159,
+ 0x015b, 0x015b,
+ 0x015d, 0x015d,
+ 0x015f, 0x015f,
+ 0x0161, 0x0161,
+ 0x0163, 0x0163,
+ 0x0165, 0x0165,
+ 0x0167, 0x0167,
+ 0x0169, 0x0169,
+ 0x016b, 0x016b,
+ 0x016d, 0x016d,
+ 0x016f, 0x016f,
+ 0x0171, 0x0171,
+ 0x0173, 0x0173,
+ 0x0175, 0x0175,
+ 0x0177, 0x0177,
+ 0x017a, 0x017a,
+ 0x017c, 0x017c,
+ 0x017e, 0x0180,
+ 0x0183, 0x0183,
+ 0x0185, 0x0185,
+ 0x0188, 0x0188,
+ 0x018c, 0x018d,
+ 0x0192, 0x0192,
+ 0x0195, 0x0195,
+ 0x0199, 0x019b,
+ 0x019e, 0x019e,
+ 0x01a1, 0x01a1,
+ 0x01a3, 0x01a3,
+ 0x01a5, 0x01a5,
+ 0x01a8, 0x01a8,
+ 0x01aa, 0x01ab,
+ 0x01ad, 0x01ad,
+ 0x01b0, 0x01b0,
+ 0x01b4, 0x01b4,
+ 0x01b6, 0x01b6,
+ 0x01b9, 0x01ba,
+ 0x01bd, 0x01bf,
+ 0x01c6, 0x01c6,
+ 0x01c9, 0x01c9,
+ 0x01cc, 0x01cc,
+ 0x01ce, 0x01ce,
+ 0x01d0, 0x01d0,
+ 0x01d2, 0x01d2,
+ 0x01d4, 0x01d4,
+ 0x01d6, 0x01d6,
+ 0x01d8, 0x01d8,
+ 0x01da, 0x01da,
+ 0x01dc, 0x01dd,
+ 0x01df, 0x01df,
+ 0x01e1, 0x01e1,
+ 0x01e3, 0x01e3,
+ 0x01e5, 0x01e5,
+ 0x01e7, 0x01e7,
+ 0x01e9, 0x01e9,
+ 0x01eb, 0x01eb,
+ 0x01ed, 0x01ed,
+ 0x01ef, 0x01f0,
+ 0x01f3, 0x01f3,
+ 0x01f5, 0x01f5,
+ 0x01f9, 0x01f9,
+ 0x01fb, 0x01fb,
+ 0x01fd, 0x01fd,
+ 0x01ff, 0x01ff,
+ 0x0201, 0x0201,
+ 0x0203, 0x0203,
+ 0x0205, 0x0205,
+ 0x0207, 0x0207,
+ 0x0209, 0x0209,
+ 0x020b, 0x020b,
+ 0x020d, 0x020d,
+ 0x020f, 0x020f,
+ 0x0211, 0x0211,
+ 0x0213, 0x0213,
+ 0x0215, 0x0215,
+ 0x0217, 0x0217,
+ 0x0219, 0x0219,
+ 0x021b, 0x021b,
+ 0x021d, 0x021d,
+ 0x021f, 0x021f,
+ 0x0221, 0x0221,
+ 0x0223, 0x0223,
+ 0x0225, 0x0225,
+ 0x0227, 0x0227,
+ 0x0229, 0x0229,
+ 0x022b, 0x022b,
+ 0x022d, 0x022d,
+ 0x022f, 0x022f,
+ 0x0231, 0x0231,
+ 0x0233, 0x0239,
+ 0x023c, 0x023c,
+ 0x023f, 0x0240,
+ 0x0242, 0x0242,
+ 0x0247, 0x0247,
+ 0x0249, 0x0249,
+ 0x024b, 0x024b,
+ 0x024d, 0x024d,
+ 0x024f, 0x0293,
+ 0x0296, 0x02af,
+ 0x0371, 0x0371,
+ 0x0373, 0x0373,
+ 0x0377, 0x0377,
+ 0x037b, 0x037d,
+ 0x0390, 0x0390,
+ 0x03ac, 0x03ce,
+ 0x03d0, 0x03d1,
+ 0x03d5, 0x03d7,
+ 0x03d9, 0x03d9,
+ 0x03db, 0x03db,
+ 0x03dd, 0x03dd,
+ 0x03df, 0x03df,
+ 0x03e1, 0x03e1,
+ 0x03e3, 0x03e3,
+ 0x03e5, 0x03e5,
+ 0x03e7, 0x03e7,
+ 0x03e9, 0x03e9,
+ 0x03eb, 0x03eb,
+ 0x03ed, 0x03ed,
+ 0x03ef, 0x03f3,
+ 0x03f5, 0x03f5,
+ 0x03f8, 0x03f8,
+ 0x03fb, 0x03fc,
+ 0x0430, 0x045f,
+ 0x0461, 0x0461,
+ 0x0463, 0x0463,
+ 0x0465, 0x0465,
+ 0x0467, 0x0467,
+ 0x0469, 0x0469,
+ 0x046b, 0x046b,
+ 0x046d, 0x046d,
+ 0x046f, 0x046f,
+ 0x0471, 0x0471,
+ 0x0473, 0x0473,
+ 0x0475, 0x0475,
+ 0x0477, 0x0477,
+ 0x0479, 0x0479,
+ 0x047b, 0x047b,
+ 0x047d, 0x047d,
+ 0x047f, 0x047f,
+ 0x0481, 0x0481,
+ 0x048b, 0x048b,
+ 0x048d, 0x048d,
+ 0x048f, 0x048f,
+ 0x0491, 0x0491,
+ 0x0493, 0x0493,
+ 0x0495, 0x0495,
+ 0x0497, 0x0497,
+ 0x0499, 0x0499,
+ 0x049b, 0x049b,
+ 0x049d, 0x049d,
+ 0x049f, 0x049f,
+ 0x04a1, 0x04a1,
+ 0x04a3, 0x04a3,
+ 0x04a5, 0x04a5,
+ 0x04a7, 0x04a7,
+ 0x04a9, 0x04a9,
+ 0x04ab, 0x04ab,
+ 0x04ad, 0x04ad,
+ 0x04af, 0x04af,
+ 0x04b1, 0x04b1,
+ 0x04b3, 0x04b3,
+ 0x04b5, 0x04b5,
+ 0x04b7, 0x04b7,
+ 0x04b9, 0x04b9,
+ 0x04bb, 0x04bb,
+ 0x04bd, 0x04bd,
+ 0x04bf, 0x04bf,
+ 0x04c2, 0x04c2,
+ 0x04c4, 0x04c4,
+ 0x04c6, 0x04c6,
+ 0x04c8, 0x04c8,
+ 0x04ca, 0x04ca,
+ 0x04cc, 0x04cc,
+ 0x04ce, 0x04cf,
+ 0x04d1, 0x04d1,
+ 0x04d3, 0x04d3,
+ 0x04d5, 0x04d5,
+ 0x04d7, 0x04d7,
+ 0x04d9, 0x04d9,
+ 0x04db, 0x04db,
+ 0x04dd, 0x04dd,
+ 0x04df, 0x04df,
+ 0x04e1, 0x04e1,
+ 0x04e3, 0x04e3,
+ 0x04e5, 0x04e5,
+ 0x04e7, 0x04e7,
+ 0x04e9, 0x04e9,
+ 0x04eb, 0x04eb,
+ 0x04ed, 0x04ed,
+ 0x04ef, 0x04ef,
+ 0x04f1, 0x04f1,
+ 0x04f3, 0x04f3,
+ 0x04f5, 0x04f5,
+ 0x04f7, 0x04f7,
+ 0x04f9, 0x04f9,
+ 0x04fb, 0x04fb,
+ 0x04fd, 0x04fd,
+ 0x04ff, 0x04ff,
+ 0x0501, 0x0501,
+ 0x0503, 0x0503,
+ 0x0505, 0x0505,
+ 0x0507, 0x0507,
+ 0x0509, 0x0509,
+ 0x050b, 0x050b,
+ 0x050d, 0x050d,
+ 0x050f, 0x050f,
+ 0x0511, 0x0511,
+ 0x0513, 0x0513,
+ 0x0515, 0x0515,
+ 0x0517, 0x0517,
+ 0x0519, 0x0519,
+ 0x051b, 0x051b,
+ 0x051d, 0x051d,
+ 0x051f, 0x051f,
+ 0x0521, 0x0521,
+ 0x0523, 0x0523,
+ 0x0525, 0x0525,
+ 0x0527, 0x0527,
+ 0x0529, 0x0529,
+ 0x052b, 0x052b,
+ 0x052d, 0x052d,
+ 0x052f, 0x052f,
+ 0x0560, 0x0588,
+ 0x10d0, 0x10fa,
+ 0x10fd, 0x10ff,
+ 0x13f8, 0x13fd,
+ 0x1c80, 0x1c88,
+ 0x1c8a, 0x1c8a,
+ 0x1d00, 0x1d2b,
+ 0x1d6b, 0x1d77,
+ 0x1d79, 0x1d9a,
+ 0x1e01, 0x1e01,
+ 0x1e03, 0x1e03,
+ 0x1e05, 0x1e05,
+ 0x1e07, 0x1e07,
+ 0x1e09, 0x1e09,
+ 0x1e0b, 0x1e0b,
+ 0x1e0d, 0x1e0d,
+ 0x1e0f, 0x1e0f,
+ 0x1e11, 0x1e11,
+ 0x1e13, 0x1e13,
+ 0x1e15, 0x1e15,
+ 0x1e17, 0x1e17,
+ 0x1e19, 0x1e19,
+ 0x1e1b, 0x1e1b,
+ 0x1e1d, 0x1e1d,
+ 0x1e1f, 0x1e1f,
+ 0x1e21, 0x1e21,
+ 0x1e23, 0x1e23,
+ 0x1e25, 0x1e25,
+ 0x1e27, 0x1e27,
+ 0x1e29, 0x1e29,
+ 0x1e2b, 0x1e2b,
+ 0x1e2d, 0x1e2d,
+ 0x1e2f, 0x1e2f,
+ 0x1e31, 0x1e31,
+ 0x1e33, 0x1e33,
+ 0x1e35, 0x1e35,
+ 0x1e37, 0x1e37,
+ 0x1e39, 0x1e39,
+ 0x1e3b, 0x1e3b,
+ 0x1e3d, 0x1e3d,
+ 0x1e3f, 0x1e3f,
+ 0x1e41, 0x1e41,
+ 0x1e43, 0x1e43,
+ 0x1e45, 0x1e45,
+ 0x1e47, 0x1e47,
+ 0x1e49, 0x1e49,
+ 0x1e4b, 0x1e4b,
+ 0x1e4d, 0x1e4d,
+ 0x1e4f, 0x1e4f,
+ 0x1e51, 0x1e51,
+ 0x1e53, 0x1e53,
+ 0x1e55, 0x1e55,
+ 0x1e57, 0x1e57,
+ 0x1e59, 0x1e59,
+ 0x1e5b, 0x1e5b,
+ 0x1e5d, 0x1e5d,
+ 0x1e5f, 0x1e5f,
+ 0x1e61, 0x1e61,
+ 0x1e63, 0x1e63,
+ 0x1e65, 0x1e65,
+ 0x1e67, 0x1e67,
+ 0x1e69, 0x1e69,
+ 0x1e6b, 0x1e6b,
+ 0x1e6d, 0x1e6d,
+ 0x1e6f, 0x1e6f,
+ 0x1e71, 0x1e71,
+ 0x1e73, 0x1e73,
+ 0x1e75, 0x1e75,
+ 0x1e77, 0x1e77,
+ 0x1e79, 0x1e79,
+ 0x1e7b, 0x1e7b,
+ 0x1e7d, 0x1e7d,
+ 0x1e7f, 0x1e7f,
+ 0x1e81, 0x1e81,
+ 0x1e83, 0x1e83,
+ 0x1e85, 0x1e85,
+ 0x1e87, 0x1e87,
+ 0x1e89, 0x1e89,
+ 0x1e8b, 0x1e8b,
+ 0x1e8d, 0x1e8d,
+ 0x1e8f, 0x1e8f,
+ 0x1e91, 0x1e91,
+ 0x1e93, 0x1e93,
+ 0x1e95, 0x1e9d,
+ 0x1e9f, 0x1e9f,
+ 0x1ea1, 0x1ea1,
+ 0x1ea3, 0x1ea3,
+ 0x1ea5, 0x1ea5,
+ 0x1ea7, 0x1ea7,
+ 0x1ea9, 0x1ea9,
+ 0x1eab, 0x1eab,
+ 0x1ead, 0x1ead,
+ 0x1eaf, 0x1eaf,
+ 0x1eb1, 0x1eb1,
+ 0x1eb3, 0x1eb3,
+ 0x1eb5, 0x1eb5,
+ 0x1eb7, 0x1eb7,
+ 0x1eb9, 0x1eb9,
+ 0x1ebb, 0x1ebb,
+ 0x1ebd, 0x1ebd,
+ 0x1ebf, 0x1ebf,
+ 0x1ec1, 0x1ec1,
+ 0x1ec3, 0x1ec3,
+ 0x1ec5, 0x1ec5,
+ 0x1ec7, 0x1ec7,
+ 0x1ec9, 0x1ec9,
+ 0x1ecb, 0x1ecb,
+ 0x1ecd, 0x1ecd,
+ 0x1ecf, 0x1ecf,
+ 0x1ed1, 0x1ed1,
+ 0x1ed3, 0x1ed3,
+ 0x1ed5, 0x1ed5,
+ 0x1ed7, 0x1ed7,
+ 0x1ed9, 0x1ed9,
+ 0x1edb, 0x1edb,
+ 0x1edd, 0x1edd,
+ 0x1edf, 0x1edf,
+ 0x1ee1, 0x1ee1,
+ 0x1ee3, 0x1ee3,
+ 0x1ee5, 0x1ee5,
+ 0x1ee7, 0x1ee7,
+ 0x1ee9, 0x1ee9,
+ 0x1eeb, 0x1eeb,
+ 0x1eed, 0x1eed,
+ 0x1eef, 0x1eef,
+ 0x1ef1, 0x1ef1,
+ 0x1ef3, 0x1ef3,
+ 0x1ef5, 0x1ef5,
+ 0x1ef7, 0x1ef7,
+ 0x1ef9, 0x1ef9,
+ 0x1efb, 0x1efb,
+ 0x1efd, 0x1efd,
+ 0x1eff, 0x1f07,
+ 0x1f10, 0x1f15,
+ 0x1f20, 0x1f27,
+ 0x1f30, 0x1f37,
+ 0x1f40, 0x1f45,
+ 0x1f50, 0x1f57,
+ 0x1f60, 0x1f67,
+ 0x1f70, 0x1f7d,
+ 0x1f80, 0x1f87,
+ 0x1f90, 0x1f97,
+ 0x1fa0, 0x1fa7,
+ 0x1fb0, 0x1fb4,
+ 0x1fb6, 0x1fb7,
+ 0x1fbe, 0x1fbe,
+ 0x1fc2, 0x1fc4,
+ 0x1fc6, 0x1fc7,
+ 0x1fd0, 0x1fd3,
+ 0x1fd6, 0x1fd7,
+ 0x1fe0, 0x1fe7,
+ 0x1ff2, 0x1ff4,
+ 0x1ff6, 0x1ff7,
+ 0x210a, 0x210a,
+ 0x210e, 0x210f,
+ 0x2113, 0x2113,
+ 0x212f, 0x212f,
+ 0x2134, 0x2134,
+ 0x2139, 0x2139,
+ 0x213c, 0x213d,
+ 0x2146, 0x2149,
+ 0x214e, 0x214e,
+ 0x2184, 0x2184,
+ 0x2c30, 0x2c5f,
+ 0x2c61, 0x2c61,
+ 0x2c65, 0x2c66,
+ 0x2c68, 0x2c68,
+ 0x2c6a, 0x2c6a,
+ 0x2c6c, 0x2c6c,
+ 0x2c71, 0x2c71,
+ 0x2c73, 0x2c74,
+ 0x2c76, 0x2c7b,
+ 0x2c81, 0x2c81,
+ 0x2c83, 0x2c83,
+ 0x2c85, 0x2c85,
+ 0x2c87, 0x2c87,
+ 0x2c89, 0x2c89,
+ 0x2c8b, 0x2c8b,
+ 0x2c8d, 0x2c8d,
+ 0x2c8f, 0x2c8f,
+ 0x2c91, 0x2c91,
+ 0x2c93, 0x2c93,
+ 0x2c95, 0x2c95,
+ 0x2c97, 0x2c97,
+ 0x2c99, 0x2c99,
+ 0x2c9b, 0x2c9b,
+ 0x2c9d, 0x2c9d,
+ 0x2c9f, 0x2c9f,
+ 0x2ca1, 0x2ca1,
+ 0x2ca3, 0x2ca3,
+ 0x2ca5, 0x2ca5,
+ 0x2ca7, 0x2ca7,
+ 0x2ca9, 0x2ca9,
+ 0x2cab, 0x2cab,
+ 0x2cad, 0x2cad,
+ 0x2caf, 0x2caf,
+ 0x2cb1, 0x2cb1,
+ 0x2cb3, 0x2cb3,
+ 0x2cb5, 0x2cb5,
+ 0x2cb7, 0x2cb7,
+ 0x2cb9, 0x2cb9,
+ 0x2cbb, 0x2cbb,
+ 0x2cbd, 0x2cbd,
+ 0x2cbf, 0x2cbf,
+ 0x2cc1, 0x2cc1,
+ 0x2cc3, 0x2cc3,
+ 0x2cc5, 0x2cc5,
+ 0x2cc7, 0x2cc7,
+ 0x2cc9, 0x2cc9,
+ 0x2ccb, 0x2ccb,
+ 0x2ccd, 0x2ccd,
+ 0x2ccf, 0x2ccf,
+ 0x2cd1, 0x2cd1,
+ 0x2cd3, 0x2cd3,
+ 0x2cd5, 0x2cd5,
+ 0x2cd7, 0x2cd7,
+ 0x2cd9, 0x2cd9,
+ 0x2cdb, 0x2cdb,
+ 0x2cdd, 0x2cdd,
+ 0x2cdf, 0x2cdf,
+ 0x2ce1, 0x2ce1,
+ 0x2ce3, 0x2ce4,
+ 0x2cec, 0x2cec,
+ 0x2cee, 0x2cee,
+ 0x2cf3, 0x2cf3,
+ 0x2d00, 0x2d25,
+ 0x2d27, 0x2d27,
+ 0x2d2d, 0x2d2d,
+ 0xa641, 0xa641,
+ 0xa643, 0xa643,
+ 0xa645, 0xa645,
+ 0xa647, 0xa647,
+ 0xa649, 0xa649,
+ 0xa64b, 0xa64b,
+ 0xa64d, 0xa64d,
+ 0xa64f, 0xa64f,
+ 0xa651, 0xa651,
+ 0xa653, 0xa653,
+ 0xa655, 0xa655,
+ 0xa657, 0xa657,
+ 0xa659, 0xa659,
+ 0xa65b, 0xa65b,
+ 0xa65d, 0xa65d,
+ 0xa65f, 0xa65f,
+ 0xa661, 0xa661,
+ 0xa663, 0xa663,
+ 0xa665, 0xa665,
+ 0xa667, 0xa667,
+ 0xa669, 0xa669,
+ 0xa66b, 0xa66b,
+ 0xa66d, 0xa66d,
+ 0xa681, 0xa681,
+ 0xa683, 0xa683,
+ 0xa685, 0xa685,
+ 0xa687, 0xa687,
+ 0xa689, 0xa689,
+ 0xa68b, 0xa68b,
+ 0xa68d, 0xa68d,
+ 0xa68f, 0xa68f,
+ 0xa691, 0xa691,
+ 0xa693, 0xa693,
+ 0xa695, 0xa695,
+ 0xa697, 0xa697,
+ 0xa699, 0xa699,
+ 0xa69b, 0xa69b,
+ 0xa723, 0xa723,
+ 0xa725, 0xa725,
+ 0xa727, 0xa727,
+ 0xa729, 0xa729,
+ 0xa72b, 0xa72b,
+ 0xa72d, 0xa72d,
+ 0xa72f, 0xa731,
+ 0xa733, 0xa733,
+ 0xa735, 0xa735,
+ 0xa737, 0xa737,
+ 0xa739, 0xa739,
+ 0xa73b, 0xa73b,
+ 0xa73d, 0xa73d,
+ 0xa73f, 0xa73f,
+ 0xa741, 0xa741,
+ 0xa743, 0xa743,
+ 0xa745, 0xa745,
+ 0xa747, 0xa747,
+ 0xa749, 0xa749,
+ 0xa74b, 0xa74b,
+ 0xa74d, 0xa74d,
+ 0xa74f, 0xa74f,
+ 0xa751, 0xa751,
+ 0xa753, 0xa753,
+ 0xa755, 0xa755,
+ 0xa757, 0xa757,
+ 0xa759, 0xa759,
+ 0xa75b, 0xa75b,
+ 0xa75d, 0xa75d,
+ 0xa75f, 0xa75f,
+ 0xa761, 0xa761,
+ 0xa763, 0xa763,
+ 0xa765, 0xa765,
+ 0xa767, 0xa767,
+ 0xa769, 0xa769,
+ 0xa76b, 0xa76b,
+ 0xa76d, 0xa76d,
+ 0xa76f, 0xa76f,
+ 0xa771, 0xa778,
+ 0xa77a, 0xa77a,
+ 0xa77c, 0xa77c,
+ 0xa77f, 0xa77f,
+ 0xa781, 0xa781,
+ 0xa783, 0xa783,
+ 0xa785, 0xa785,
+ 0xa787, 0xa787,
+ 0xa78c, 0xa78c,
+ 0xa78e, 0xa78e,
+ 0xa791, 0xa791,
+ 0xa793, 0xa795,
+ 0xa797, 0xa797,
+ 0xa799, 0xa799,
+ 0xa79b, 0xa79b,
+ 0xa79d, 0xa79d,
+ 0xa79f, 0xa79f,
+ 0xa7a1, 0xa7a1,
+ 0xa7a3, 0xa7a3,
+ 0xa7a5, 0xa7a5,
+ 0xa7a7, 0xa7a7,
+ 0xa7a9, 0xa7a9,
+ 0xa7af, 0xa7af,
+ 0xa7b5, 0xa7b5,
+ 0xa7b7, 0xa7b7,
+ 0xa7b9, 0xa7b9,
+ 0xa7bb, 0xa7bb,
+ 0xa7bd, 0xa7bd,
+ 0xa7bf, 0xa7bf,
+ 0xa7c1, 0xa7c1,
+ 0xa7c3, 0xa7c3,
+ 0xa7c8, 0xa7c8,
+ 0xa7ca, 0xa7ca,
+ 0xa7cd, 0xa7cd,
+ 0xa7cf, 0xa7cf,
+ 0xa7d1, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d5,
+ 0xa7d7, 0xa7d7,
+ 0xa7d9, 0xa7d9,
+ 0xa7db, 0xa7db,
+ 0xa7f6, 0xa7f6,
+ 0xa7fa, 0xa7fa,
+ 0xab30, 0xab5a,
+ 0xab60, 0xab68,
+ 0xab70, 0xabbf,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xff41, 0xff5a,
+ 0x10428, 0x1044f,
+ 0x104d8, 0x104fb,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x10cc0, 0x10cf2,
+ 0x10d70, 0x10d85,
+ 0x118c0, 0x118df,
+ 0x16e60, 0x16e7f,
+ 0x16ebb, 0x16ed3,
+ 0x1d41a, 0x1d433,
+ 0x1d44e, 0x1d454,
+ 0x1d456, 0x1d467,
+ 0x1d482, 0x1d49b,
+ 0x1d4b6, 0x1d4b9,
+ 0x1d4bb, 0x1d4bb,
+ 0x1d4bd, 0x1d4c3,
+ 0x1d4c5, 0x1d4cf,
+ 0x1d4ea, 0x1d503,
+ 0x1d51e, 0x1d537,
+ 0x1d552, 0x1d56b,
+ 0x1d586, 0x1d59f,
+ 0x1d5ba, 0x1d5d3,
+ 0x1d5ee, 0x1d607,
+ 0x1d622, 0x1d63b,
+ 0x1d656, 0x1d66f,
+ 0x1d68a, 0x1d6a5,
+ 0x1d6c2, 0x1d6da,
+ 0x1d6dc, 0x1d6e1,
+ 0x1d6fc, 0x1d714,
+ 0x1d716, 0x1d71b,
+ 0x1d736, 0x1d74e,
+ 0x1d750, 0x1d755,
+ 0x1d770, 0x1d788,
+ 0x1d78a, 0x1d78f,
+ 0x1d7aa, 0x1d7c2,
+ 0x1d7c4, 0x1d7c9,
+ 0x1d7cb, 0x1d7cb,
+ 0x1df00, 0x1df09,
+ 0x1df0b, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e922, 0x1e943,
+}; /* CR_Ll */
+
+/* 'Lm': General Category */
+static const OnigCodePoint CR_Lm[] = {
+ 79,
+ 0x02b0, 0x02c1,
+ 0x02c6, 0x02d1,
+ 0x02e0, 0x02e4,
+ 0x02ec, 0x02ec,
+ 0x02ee, 0x02ee,
+ 0x0374, 0x0374,
+ 0x037a, 0x037a,
+ 0x0559, 0x0559,
+ 0x0640, 0x0640,
+ 0x06e5, 0x06e6,
+ 0x07f4, 0x07f5,
+ 0x07fa, 0x07fa,
+ 0x081a, 0x081a,
+ 0x0824, 0x0824,
+ 0x0828, 0x0828,
+ 0x08c9, 0x08c9,
+ 0x0971, 0x0971,
+ 0x0e46, 0x0e46,
+ 0x0ec6, 0x0ec6,
+ 0x10fc, 0x10fc,
+ 0x17d7, 0x17d7,
+ 0x1843, 0x1843,
+ 0x1aa7, 0x1aa7,
+ 0x1c78, 0x1c7d,
+ 0x1d2c, 0x1d6a,
+ 0x1d78, 0x1d78,
+ 0x1d9b, 0x1dbf,
+ 0x2071, 0x2071,
+ 0x207f, 0x207f,
+ 0x2090, 0x209c,
+ 0x2c7c, 0x2c7d,
+ 0x2d6f, 0x2d6f,
+ 0x2e2f, 0x2e2f,
+ 0x3005, 0x3005,
+ 0x3031, 0x3035,
+ 0x303b, 0x303b,
+ 0x309d, 0x309e,
+ 0x30fc, 0x30fe,
+ 0xa015, 0xa015,
+ 0xa4f8, 0xa4fd,
+ 0xa60c, 0xa60c,
+ 0xa67f, 0xa67f,
+ 0xa69c, 0xa69d,
+ 0xa717, 0xa71f,
+ 0xa770, 0xa770,
+ 0xa788, 0xa788,
+ 0xa7f1, 0xa7f4,
+ 0xa7f8, 0xa7f9,
+ 0xa9cf, 0xa9cf,
+ 0xa9e6, 0xa9e6,
+ 0xaa70, 0xaa70,
+ 0xaadd, 0xaadd,
+ 0xaaf3, 0xaaf4,
+ 0xab5c, 0xab5f,
+ 0xab69, 0xab69,
+ 0xff70, 0xff70,
+ 0xff9e, 0xff9f,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 0x10d4e, 0x10d4e,
+ 0x10d6f, 0x10d6f,
+ 0x10ec5, 0x10ec5,
+ 0x11dd9, 0x11dd9,
+ 0x16b40, 0x16b43,
+ 0x16d40, 0x16d42,
+ 0x16d6b, 0x16d6c,
+ 0x16f93, 0x16f9f,
+ 0x16fe0, 0x16fe1,
+ 0x16fe3, 0x16fe3,
+ 0x16ff2, 0x16ff3,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1e030, 0x1e06d,
+ 0x1e137, 0x1e13d,
+ 0x1e4eb, 0x1e4eb,
+ 0x1e6ff, 0x1e6ff,
+ 0x1e94b, 0x1e94b,
+}; /* CR_Lm */
+
+/* 'Lo': General Category */
+static const OnigCodePoint CR_Lo[] = {
+ 537,
+ 0x00aa, 0x00aa,
+ 0x00ba, 0x00ba,
+ 0x01bb, 0x01bb,
+ 0x01c0, 0x01c3,
+ 0x0294, 0x0295,
+ 0x05d0, 0x05ea,
+ 0x05ef, 0x05f2,
+ 0x0620, 0x063f,
+ 0x0641, 0x064a,
+ 0x066e, 0x066f,
+ 0x0671, 0x06d3,
+ 0x06d5, 0x06d5,
+ 0x06ee, 0x06ef,
+ 0x06fa, 0x06fc,
+ 0x06ff, 0x06ff,
+ 0x0710, 0x0710,
+ 0x0712, 0x072f,
+ 0x074d, 0x07a5,
+ 0x07b1, 0x07b1,
+ 0x07ca, 0x07ea,
+ 0x0800, 0x0815,
+ 0x0840, 0x0858,
+ 0x0860, 0x086a,
+ 0x0870, 0x0887,
+ 0x0889, 0x088f,
+ 0x08a0, 0x08c8,
+ 0x0904, 0x0939,
+ 0x093d, 0x093d,
+ 0x0950, 0x0950,
+ 0x0958, 0x0961,
+ 0x0972, 0x0980,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bd, 0x09bd,
+ 0x09ce, 0x09ce,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e1,
+ 0x09f0, 0x09f1,
+ 0x09fc, 0x09fc,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a72, 0x0a74,
+ 0x0a85, 0x0a8d,
+ 0x0a8f, 0x0a91,
+ 0x0a93, 0x0aa8,
+ 0x0aaa, 0x0ab0,
+ 0x0ab2, 0x0ab3,
+ 0x0ab5, 0x0ab9,
+ 0x0abd, 0x0abd,
+ 0x0ad0, 0x0ad0,
+ 0x0ae0, 0x0ae1,
+ 0x0af9, 0x0af9,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b35, 0x0b39,
+ 0x0b3d, 0x0b3d,
+ 0x0b5c, 0x0b5d,
+ 0x0b5f, 0x0b61,
+ 0x0b71, 0x0b71,
+ 0x0b83, 0x0b83,
+ 0x0b85, 0x0b8a,
+ 0x0b8e, 0x0b90,
+ 0x0b92, 0x0b95,
+ 0x0b99, 0x0b9a,
+ 0x0b9c, 0x0b9c,
+ 0x0b9e, 0x0b9f,
+ 0x0ba3, 0x0ba4,
+ 0x0ba8, 0x0baa,
+ 0x0bae, 0x0bb9,
+ 0x0bd0, 0x0bd0,
+ 0x0c05, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3d, 0x0c3d,
+ 0x0c58, 0x0c5a,
+ 0x0c5c, 0x0c5d,
+ 0x0c60, 0x0c61,
+ 0x0c80, 0x0c80,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbd, 0x0cbd,
+ 0x0cdc, 0x0cde,
+ 0x0ce0, 0x0ce1,
+ 0x0cf1, 0x0cf2,
+ 0x0d04, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d3a,
+ 0x0d3d, 0x0d3d,
+ 0x0d4e, 0x0d4e,
+ 0x0d54, 0x0d56,
+ 0x0d5f, 0x0d61,
+ 0x0d7a, 0x0d7f,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0e01, 0x0e30,
+ 0x0e32, 0x0e33,
+ 0x0e40, 0x0e45,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e86, 0x0e8a,
+ 0x0e8c, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0eb0,
+ 0x0eb2, 0x0eb3,
+ 0x0ebd, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f00,
+ 0x0f40, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f88, 0x0f8c,
+ 0x1000, 0x102a,
+ 0x103f, 0x103f,
+ 0x1050, 0x1055,
+ 0x105a, 0x105d,
+ 0x1061, 0x1061,
+ 0x1065, 0x1066,
+ 0x106e, 0x1070,
+ 0x1075, 0x1081,
+ 0x108e, 0x108e,
+ 0x1100, 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,
+ 0x1380, 0x138f,
+ 0x1401, 0x166c,
+ 0x166f, 0x167f,
+ 0x1681, 0x169a,
+ 0x16a0, 0x16ea,
+ 0x16f1, 0x16f8,
+ 0x1700, 0x1711,
+ 0x171f, 0x1731,
+ 0x1740, 0x1751,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1780, 0x17b3,
+ 0x17dc, 0x17dc,
+ 0x1820, 0x1842,
+ 0x1844, 0x1878,
+ 0x1880, 0x1884,
+ 0x1887, 0x18a8,
+ 0x18aa, 0x18aa,
+ 0x18b0, 0x18f5,
+ 0x1900, 0x191e,
+ 0x1950, 0x196d,
+ 0x1970, 0x1974,
+ 0x1980, 0x19ab,
+ 0x19b0, 0x19c9,
+ 0x1a00, 0x1a16,
+ 0x1a20, 0x1a54,
+ 0x1b05, 0x1b33,
+ 0x1b45, 0x1b4c,
+ 0x1b83, 0x1ba0,
+ 0x1bae, 0x1baf,
+ 0x1bba, 0x1be5,
+ 0x1c00, 0x1c23,
+ 0x1c4d, 0x1c4f,
+ 0x1c5a, 0x1c77,
+ 0x1ce9, 0x1cec,
+ 0x1cee, 0x1cf3,
+ 0x1cf5, 0x1cf6,
+ 0x1cfa, 0x1cfa,
+ 0x2135, 0x2138,
+ 0x2d30, 0x2d67,
+ 0x2d80, 0x2d96,
+ 0x2da0, 0x2da6,
+ 0x2da8, 0x2dae,
+ 0x2db0, 0x2db6,
+ 0x2db8, 0x2dbe,
+ 0x2dc0, 0x2dc6,
+ 0x2dc8, 0x2dce,
+ 0x2dd0, 0x2dd6,
+ 0x2dd8, 0x2dde,
+ 0x3006, 0x3006,
+ 0x303c, 0x303c,
+ 0x3041, 0x3096,
+ 0x309f, 0x309f,
+ 0x30a1, 0x30fa,
+ 0x30ff, 0x30ff,
+ 0x3105, 0x312f,
+ 0x3131, 0x318e,
+ 0x31a0, 0x31bf,
+ 0x31f0, 0x31ff,
+ 0x3400, 0x4dbf,
+ 0x4e00, 0xa014,
+ 0xa016, 0xa48c,
+ 0xa4d0, 0xa4f7,
+ 0xa500, 0xa60b,
+ 0xa610, 0xa61f,
+ 0xa62a, 0xa62b,
+ 0xa66e, 0xa66e,
+ 0xa6a0, 0xa6e5,
+ 0xa78f, 0xa78f,
+ 0xa7f7, 0xa7f7,
+ 0xa7fb, 0xa801,
+ 0xa803, 0xa805,
+ 0xa807, 0xa80a,
+ 0xa80c, 0xa822,
+ 0xa840, 0xa873,
+ 0xa882, 0xa8b3,
+ 0xa8f2, 0xa8f7,
+ 0xa8fb, 0xa8fb,
+ 0xa8fd, 0xa8fe,
+ 0xa90a, 0xa925,
+ 0xa930, 0xa946,
+ 0xa960, 0xa97c,
+ 0xa984, 0xa9b2,
+ 0xa9e0, 0xa9e4,
+ 0xa9e7, 0xa9ef,
+ 0xa9fa, 0xa9fe,
+ 0xaa00, 0xaa28,
+ 0xaa40, 0xaa42,
+ 0xaa44, 0xaa4b,
+ 0xaa60, 0xaa6f,
+ 0xaa71, 0xaa76,
+ 0xaa7a, 0xaa7a,
+ 0xaa7e, 0xaaaf,
+ 0xaab1, 0xaab1,
+ 0xaab5, 0xaab6,
+ 0xaab9, 0xaabd,
+ 0xaac0, 0xaac0,
+ 0xaac2, 0xaac2,
+ 0xaadb, 0xaadc,
+ 0xaae0, 0xaaea,
+ 0xaaf2, 0xaaf2,
+ 0xab01, 0xab06,
+ 0xab09, 0xab0e,
+ 0xab11, 0xab16,
+ 0xab20, 0xab26,
+ 0xab28, 0xab2e,
+ 0xabc0, 0xabe2,
+ 0xac00, 0xd7a3,
+ 0xd7b0, 0xd7c6,
+ 0xd7cb, 0xd7fb,
+ 0xf900, 0xfa6d,
+ 0xfa70, 0xfad9,
+ 0xfb1d, 0xfb1d,
+ 0xfb1f, 0xfb28,
+ 0xfb2a, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfbb1,
+ 0xfbd3, 0xfd3d,
+ 0xfd50, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdf0, 0xfdfb,
+ 0xfe70, 0xfe74,
+ 0xfe76, 0xfefc,
+ 0xff66, 0xff6f,
+ 0xff71, 0xff9d,
+ 0xffa0, 0xffbe,
+ 0xffc2, 0xffc7,
+ 0xffca, 0xffcf,
+ 0xffd2, 0xffd7,
+ 0xffda, 0xffdc,
+ 0x10000, 0x1000b,
+ 0x1000d, 0x10026,
+ 0x10028, 0x1003a,
+ 0x1003c, 0x1003d,
+ 0x1003f, 0x1004d,
+ 0x10050, 0x1005d,
+ 0x10080, 0x100fa,
+ 0x10280, 0x1029c,
+ 0x102a0, 0x102d0,
+ 0x10300, 0x1031f,
+ 0x1032d, 0x10340,
+ 0x10342, 0x10349,
+ 0x10350, 0x10375,
+ 0x10380, 0x1039d,
+ 0x103a0, 0x103c3,
+ 0x103c8, 0x103cf,
+ 0x10450, 0x1049d,
+ 0x10500, 0x10527,
+ 0x10530, 0x10563,
+ 0x105c0, 0x105f3,
+ 0x10600, 0x10736,
+ 0x10740, 0x10755,
+ 0x10760, 0x10767,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 0x10837, 0x10838,
+ 0x1083c, 0x1083c,
+ 0x1083f, 0x10855,
+ 0x10860, 0x10876,
+ 0x10880, 0x1089e,
+ 0x108e0, 0x108f2,
+ 0x108f4, 0x108f5,
+ 0x10900, 0x10915,
+ 0x10920, 0x10939,
+ 0x10940, 0x10959,
+ 0x10980, 0x109b7,
+ 0x109be, 0x109bf,
+ 0x10a00, 0x10a00,
+ 0x10a10, 0x10a13,
+ 0x10a15, 0x10a17,
+ 0x10a19, 0x10a35,
+ 0x10a60, 0x10a7c,
+ 0x10a80, 0x10a9c,
+ 0x10ac0, 0x10ac7,
+ 0x10ac9, 0x10ae4,
+ 0x10b00, 0x10b35,
+ 0x10b40, 0x10b55,
+ 0x10b60, 0x10b72,
+ 0x10b80, 0x10b91,
+ 0x10c00, 0x10c48,
+ 0x10d00, 0x10d23,
+ 0x10d4a, 0x10d4d,
+ 0x10d4f, 0x10d4f,
+ 0x10e80, 0x10ea9,
+ 0x10eb0, 0x10eb1,
+ 0x10ec2, 0x10ec4,
+ 0x10ec6, 0x10ec7,
+ 0x10f00, 0x10f1c,
+ 0x10f27, 0x10f27,
+ 0x10f30, 0x10f45,
+ 0x10f70, 0x10f81,
+ 0x10fb0, 0x10fc4,
+ 0x10fe0, 0x10ff6,
+ 0x11003, 0x11037,
+ 0x11071, 0x11072,
+ 0x11075, 0x11075,
+ 0x11083, 0x110af,
+ 0x110d0, 0x110e8,
+ 0x11103, 0x11126,
+ 0x11144, 0x11144,
+ 0x11147, 0x11147,
+ 0x11150, 0x11172,
+ 0x11176, 0x11176,
+ 0x11183, 0x111b2,
+ 0x111c1, 0x111c4,
+ 0x111da, 0x111da,
+ 0x111dc, 0x111dc,
+ 0x11200, 0x11211,
+ 0x11213, 0x1122b,
+ 0x1123f, 0x11240,
+ 0x11280, 0x11286,
+ 0x11288, 0x11288,
+ 0x1128a, 0x1128d,
+ 0x1128f, 0x1129d,
+ 0x1129f, 0x112a8,
+ 0x112b0, 0x112de,
+ 0x11305, 0x1130c,
+ 0x1130f, 0x11310,
+ 0x11313, 0x11328,
+ 0x1132a, 0x11330,
+ 0x11332, 0x11333,
+ 0x11335, 0x11339,
+ 0x1133d, 0x1133d,
+ 0x11350, 0x11350,
+ 0x1135d, 0x11361,
+ 0x11380, 0x11389,
+ 0x1138b, 0x1138b,
+ 0x1138e, 0x1138e,
+ 0x11390, 0x113b5,
+ 0x113b7, 0x113b7,
+ 0x113d1, 0x113d1,
+ 0x113d3, 0x113d3,
+ 0x11400, 0x11434,
+ 0x11447, 0x1144a,
+ 0x1145f, 0x11461,
+ 0x11480, 0x114af,
+ 0x114c4, 0x114c5,
+ 0x114c7, 0x114c7,
+ 0x11580, 0x115ae,
+ 0x115d8, 0x115db,
+ 0x11600, 0x1162f,
+ 0x11644, 0x11644,
+ 0x11680, 0x116aa,
+ 0x116b8, 0x116b8,
+ 0x11700, 0x1171a,
+ 0x11740, 0x11746,
+ 0x11800, 0x1182b,
+ 0x118ff, 0x11906,
+ 0x11909, 0x11909,
+ 0x1190c, 0x11913,
+ 0x11915, 0x11916,
+ 0x11918, 0x1192f,
+ 0x1193f, 0x1193f,
+ 0x11941, 0x11941,
+ 0x119a0, 0x119a7,
+ 0x119aa, 0x119d0,
+ 0x119e1, 0x119e1,
+ 0x119e3, 0x119e3,
+ 0x11a00, 0x11a00,
+ 0x11a0b, 0x11a32,
+ 0x11a3a, 0x11a3a,
+ 0x11a50, 0x11a50,
+ 0x11a5c, 0x11a89,
+ 0x11a9d, 0x11a9d,
+ 0x11ab0, 0x11af8,
+ 0x11bc0, 0x11be0,
+ 0x11c00, 0x11c08,
+ 0x11c0a, 0x11c2e,
+ 0x11c40, 0x11c40,
+ 0x11c72, 0x11c8f,
+ 0x11d00, 0x11d06,
+ 0x11d08, 0x11d09,
+ 0x11d0b, 0x11d30,
+ 0x11d46, 0x11d46,
+ 0x11d60, 0x11d65,
+ 0x11d67, 0x11d68,
+ 0x11d6a, 0x11d89,
+ 0x11d98, 0x11d98,
+ 0x11db0, 0x11dd8,
+ 0x11dda, 0x11ddb,
+ 0x11ee0, 0x11ef2,
+ 0x11f02, 0x11f02,
+ 0x11f04, 0x11f10,
+ 0x11f12, 0x11f33,
+ 0x11fb0, 0x11fb0,
+ 0x12000, 0x12399,
+ 0x12480, 0x12543,
+ 0x12f90, 0x12ff0,
+ 0x13000, 0x1342f,
+ 0x13441, 0x13446,
+ 0x13460, 0x143fa,
+ 0x14400, 0x14646,
+ 0x16100, 0x1611d,
+ 0x16800, 0x16a38,
+ 0x16a40, 0x16a5e,
+ 0x16a70, 0x16abe,
+ 0x16ad0, 0x16aed,
+ 0x16b00, 0x16b2f,
+ 0x16b63, 0x16b77,
+ 0x16b7d, 0x16b8f,
+ 0x16d43, 0x16d6a,
+ 0x16f00, 0x16f4a,
+ 0x16f50, 0x16f50,
+ 0x17000, 0x18cd5,
+ 0x18cff, 0x18d1e,
+ 0x18d80, 0x18df2,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
+ 0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
+ 0x1b164, 0x1b167,
+ 0x1b170, 0x1b2fb,
+ 0x1bc00, 0x1bc6a,
+ 0x1bc70, 0x1bc7c,
+ 0x1bc80, 0x1bc88,
+ 0x1bc90, 0x1bc99,
+ 0x1df0a, 0x1df0a,
+ 0x1e100, 0x1e12c,
+ 0x1e14e, 0x1e14e,
+ 0x1e290, 0x1e2ad,
+ 0x1e2c0, 0x1e2eb,
+ 0x1e4d0, 0x1e4ea,
+ 0x1e5d0, 0x1e5ed,
+ 0x1e5f0, 0x1e5f0,
+ 0x1e6c0, 0x1e6de,
+ 0x1e6e0, 0x1e6e2,
+ 0x1e6e4, 0x1e6e5,
+ 0x1e6e7, 0x1e6ed,
+ 0x1e6f0, 0x1e6f4,
+ 0x1e6fe, 0x1e6fe,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
+ 0x1e800, 0x1e8c4,
+ 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,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b81d,
+ 0x2b820, 0x2cead,
+ 0x2ceb0, 0x2ebe0,
+ 0x2ebf0, 0x2ee5d,
+ 0x2f800, 0x2fa1d,
+ 0x30000, 0x3134a,
+ 0x31350, 0x33479,
+}; /* CR_Lo */
+
+/* 'Lt': General Category */
+static const OnigCodePoint CR_Lt[] = {
+ 10,
+ 0x01c5, 0x01c5,
+ 0x01c8, 0x01c8,
+ 0x01cb, 0x01cb,
+ 0x01f2, 0x01f2,
+ 0x1f88, 0x1f8f,
+ 0x1f98, 0x1f9f,
+ 0x1fa8, 0x1faf,
+ 0x1fbc, 0x1fbc,
+ 0x1fcc, 0x1fcc,
+ 0x1ffc, 0x1ffc,
+}; /* CR_Lt */
+
+/* 'Lu': General Category */
+static const OnigCodePoint CR_Lu[] = {
+ 655,
+ 0x0041, 0x005a,
+ 0x00c0, 0x00d6,
+ 0x00d8, 0x00de,
+ 0x0100, 0x0100,
+ 0x0102, 0x0102,
+ 0x0104, 0x0104,
+ 0x0106, 0x0106,
+ 0x0108, 0x0108,
+ 0x010a, 0x010a,
+ 0x010c, 0x010c,
+ 0x010e, 0x010e,
+ 0x0110, 0x0110,
+ 0x0112, 0x0112,
+ 0x0114, 0x0114,
+ 0x0116, 0x0116,
+ 0x0118, 0x0118,
+ 0x011a, 0x011a,
+ 0x011c, 0x011c,
+ 0x011e, 0x011e,
+ 0x0120, 0x0120,
+ 0x0122, 0x0122,
+ 0x0124, 0x0124,
+ 0x0126, 0x0126,
+ 0x0128, 0x0128,
+ 0x012a, 0x012a,
+ 0x012c, 0x012c,
+ 0x012e, 0x012e,
+ 0x0130, 0x0130,
+ 0x0132, 0x0132,
+ 0x0134, 0x0134,
+ 0x0136, 0x0136,
+ 0x0139, 0x0139,
+ 0x013b, 0x013b,
+ 0x013d, 0x013d,
+ 0x013f, 0x013f,
+ 0x0141, 0x0141,
+ 0x0143, 0x0143,
+ 0x0145, 0x0145,
+ 0x0147, 0x0147,
+ 0x014a, 0x014a,
+ 0x014c, 0x014c,
+ 0x014e, 0x014e,
+ 0x0150, 0x0150,
+ 0x0152, 0x0152,
+ 0x0154, 0x0154,
+ 0x0156, 0x0156,
+ 0x0158, 0x0158,
+ 0x015a, 0x015a,
+ 0x015c, 0x015c,
+ 0x015e, 0x015e,
+ 0x0160, 0x0160,
+ 0x0162, 0x0162,
+ 0x0164, 0x0164,
+ 0x0166, 0x0166,
+ 0x0168, 0x0168,
+ 0x016a, 0x016a,
+ 0x016c, 0x016c,
+ 0x016e, 0x016e,
+ 0x0170, 0x0170,
+ 0x0172, 0x0172,
+ 0x0174, 0x0174,
+ 0x0176, 0x0176,
+ 0x0178, 0x0179,
+ 0x017b, 0x017b,
+ 0x017d, 0x017d,
+ 0x0181, 0x0182,
+ 0x0184, 0x0184,
+ 0x0186, 0x0187,
+ 0x0189, 0x018b,
+ 0x018e, 0x0191,
+ 0x0193, 0x0194,
+ 0x0196, 0x0198,
+ 0x019c, 0x019d,
+ 0x019f, 0x01a0,
+ 0x01a2, 0x01a2,
+ 0x01a4, 0x01a4,
+ 0x01a6, 0x01a7,
+ 0x01a9, 0x01a9,
+ 0x01ac, 0x01ac,
+ 0x01ae, 0x01af,
+ 0x01b1, 0x01b3,
+ 0x01b5, 0x01b5,
+ 0x01b7, 0x01b8,
+ 0x01bc, 0x01bc,
+ 0x01c4, 0x01c4,
+ 0x01c7, 0x01c7,
+ 0x01ca, 0x01ca,
+ 0x01cd, 0x01cd,
+ 0x01cf, 0x01cf,
+ 0x01d1, 0x01d1,
+ 0x01d3, 0x01d3,
+ 0x01d5, 0x01d5,
+ 0x01d7, 0x01d7,
+ 0x01d9, 0x01d9,
+ 0x01db, 0x01db,
+ 0x01de, 0x01de,
+ 0x01e0, 0x01e0,
+ 0x01e2, 0x01e2,
+ 0x01e4, 0x01e4,
+ 0x01e6, 0x01e6,
+ 0x01e8, 0x01e8,
+ 0x01ea, 0x01ea,
+ 0x01ec, 0x01ec,
+ 0x01ee, 0x01ee,
+ 0x01f1, 0x01f1,
+ 0x01f4, 0x01f4,
+ 0x01f6, 0x01f8,
+ 0x01fa, 0x01fa,
+ 0x01fc, 0x01fc,
+ 0x01fe, 0x01fe,
+ 0x0200, 0x0200,
+ 0x0202, 0x0202,
+ 0x0204, 0x0204,
+ 0x0206, 0x0206,
+ 0x0208, 0x0208,
+ 0x020a, 0x020a,
+ 0x020c, 0x020c,
+ 0x020e, 0x020e,
+ 0x0210, 0x0210,
+ 0x0212, 0x0212,
+ 0x0214, 0x0214,
+ 0x0216, 0x0216,
+ 0x0218, 0x0218,
+ 0x021a, 0x021a,
+ 0x021c, 0x021c,
+ 0x021e, 0x021e,
+ 0x0220, 0x0220,
+ 0x0222, 0x0222,
+ 0x0224, 0x0224,
+ 0x0226, 0x0226,
+ 0x0228, 0x0228,
+ 0x022a, 0x022a,
+ 0x022c, 0x022c,
+ 0x022e, 0x022e,
+ 0x0230, 0x0230,
+ 0x0232, 0x0232,
+ 0x023a, 0x023b,
+ 0x023d, 0x023e,
+ 0x0241, 0x0241,
+ 0x0243, 0x0246,
+ 0x0248, 0x0248,
+ 0x024a, 0x024a,
+ 0x024c, 0x024c,
+ 0x024e, 0x024e,
+ 0x0370, 0x0370,
+ 0x0372, 0x0372,
+ 0x0376, 0x0376,
+ 0x037f, 0x037f,
+ 0x0386, 0x0386,
+ 0x0388, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x038f,
+ 0x0391, 0x03a1,
+ 0x03a3, 0x03ab,
+ 0x03cf, 0x03cf,
+ 0x03d2, 0x03d4,
+ 0x03d8, 0x03d8,
+ 0x03da, 0x03da,
+ 0x03dc, 0x03dc,
+ 0x03de, 0x03de,
+ 0x03e0, 0x03e0,
+ 0x03e2, 0x03e2,
+ 0x03e4, 0x03e4,
+ 0x03e6, 0x03e6,
+ 0x03e8, 0x03e8,
+ 0x03ea, 0x03ea,
+ 0x03ec, 0x03ec,
+ 0x03ee, 0x03ee,
+ 0x03f4, 0x03f4,
+ 0x03f7, 0x03f7,
+ 0x03f9, 0x03fa,
+ 0x03fd, 0x042f,
+ 0x0460, 0x0460,
+ 0x0462, 0x0462,
+ 0x0464, 0x0464,
+ 0x0466, 0x0466,
+ 0x0468, 0x0468,
+ 0x046a, 0x046a,
+ 0x046c, 0x046c,
+ 0x046e, 0x046e,
+ 0x0470, 0x0470,
+ 0x0472, 0x0472,
+ 0x0474, 0x0474,
+ 0x0476, 0x0476,
+ 0x0478, 0x0478,
+ 0x047a, 0x047a,
+ 0x047c, 0x047c,
+ 0x047e, 0x047e,
+ 0x0480, 0x0480,
+ 0x048a, 0x048a,
+ 0x048c, 0x048c,
+ 0x048e, 0x048e,
+ 0x0490, 0x0490,
+ 0x0492, 0x0492,
+ 0x0494, 0x0494,
+ 0x0496, 0x0496,
+ 0x0498, 0x0498,
+ 0x049a, 0x049a,
+ 0x049c, 0x049c,
+ 0x049e, 0x049e,
+ 0x04a0, 0x04a0,
+ 0x04a2, 0x04a2,
+ 0x04a4, 0x04a4,
+ 0x04a6, 0x04a6,
+ 0x04a8, 0x04a8,
+ 0x04aa, 0x04aa,
+ 0x04ac, 0x04ac,
+ 0x04ae, 0x04ae,
+ 0x04b0, 0x04b0,
+ 0x04b2, 0x04b2,
+ 0x04b4, 0x04b4,
+ 0x04b6, 0x04b6,
+ 0x04b8, 0x04b8,
+ 0x04ba, 0x04ba,
+ 0x04bc, 0x04bc,
+ 0x04be, 0x04be,
+ 0x04c0, 0x04c1,
+ 0x04c3, 0x04c3,
+ 0x04c5, 0x04c5,
+ 0x04c7, 0x04c7,
+ 0x04c9, 0x04c9,
+ 0x04cb, 0x04cb,
+ 0x04cd, 0x04cd,
+ 0x04d0, 0x04d0,
+ 0x04d2, 0x04d2,
+ 0x04d4, 0x04d4,
+ 0x04d6, 0x04d6,
+ 0x04d8, 0x04d8,
+ 0x04da, 0x04da,
+ 0x04dc, 0x04dc,
+ 0x04de, 0x04de,
+ 0x04e0, 0x04e0,
+ 0x04e2, 0x04e2,
+ 0x04e4, 0x04e4,
+ 0x04e6, 0x04e6,
+ 0x04e8, 0x04e8,
+ 0x04ea, 0x04ea,
+ 0x04ec, 0x04ec,
+ 0x04ee, 0x04ee,
+ 0x04f0, 0x04f0,
+ 0x04f2, 0x04f2,
+ 0x04f4, 0x04f4,
+ 0x04f6, 0x04f6,
+ 0x04f8, 0x04f8,
+ 0x04fa, 0x04fa,
+ 0x04fc, 0x04fc,
+ 0x04fe, 0x04fe,
+ 0x0500, 0x0500,
+ 0x0502, 0x0502,
+ 0x0504, 0x0504,
+ 0x0506, 0x0506,
+ 0x0508, 0x0508,
+ 0x050a, 0x050a,
+ 0x050c, 0x050c,
+ 0x050e, 0x050e,
+ 0x0510, 0x0510,
+ 0x0512, 0x0512,
+ 0x0514, 0x0514,
+ 0x0516, 0x0516,
+ 0x0518, 0x0518,
+ 0x051a, 0x051a,
+ 0x051c, 0x051c,
+ 0x051e, 0x051e,
+ 0x0520, 0x0520,
+ 0x0522, 0x0522,
+ 0x0524, 0x0524,
+ 0x0526, 0x0526,
+ 0x0528, 0x0528,
+ 0x052a, 0x052a,
+ 0x052c, 0x052c,
+ 0x052e, 0x052e,
+ 0x0531, 0x0556,
+ 0x10a0, 0x10c5,
+ 0x10c7, 0x10c7,
+ 0x10cd, 0x10cd,
+ 0x13a0, 0x13f5,
+ 0x1c89, 0x1c89,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cbf,
+ 0x1e00, 0x1e00,
+ 0x1e02, 0x1e02,
+ 0x1e04, 0x1e04,
+ 0x1e06, 0x1e06,
+ 0x1e08, 0x1e08,
+ 0x1e0a, 0x1e0a,
+ 0x1e0c, 0x1e0c,
+ 0x1e0e, 0x1e0e,
+ 0x1e10, 0x1e10,
+ 0x1e12, 0x1e12,
+ 0x1e14, 0x1e14,
+ 0x1e16, 0x1e16,
+ 0x1e18, 0x1e18,
+ 0x1e1a, 0x1e1a,
+ 0x1e1c, 0x1e1c,
+ 0x1e1e, 0x1e1e,
+ 0x1e20, 0x1e20,
+ 0x1e22, 0x1e22,
+ 0x1e24, 0x1e24,
+ 0x1e26, 0x1e26,
+ 0x1e28, 0x1e28,
+ 0x1e2a, 0x1e2a,
+ 0x1e2c, 0x1e2c,
+ 0x1e2e, 0x1e2e,
+ 0x1e30, 0x1e30,
+ 0x1e32, 0x1e32,
+ 0x1e34, 0x1e34,
+ 0x1e36, 0x1e36,
+ 0x1e38, 0x1e38,
+ 0x1e3a, 0x1e3a,
+ 0x1e3c, 0x1e3c,
+ 0x1e3e, 0x1e3e,
+ 0x1e40, 0x1e40,
+ 0x1e42, 0x1e42,
+ 0x1e44, 0x1e44,
+ 0x1e46, 0x1e46,
+ 0x1e48, 0x1e48,
+ 0x1e4a, 0x1e4a,
+ 0x1e4c, 0x1e4c,
+ 0x1e4e, 0x1e4e,
+ 0x1e50, 0x1e50,
+ 0x1e52, 0x1e52,
+ 0x1e54, 0x1e54,
+ 0x1e56, 0x1e56,
+ 0x1e58, 0x1e58,
+ 0x1e5a, 0x1e5a,
+ 0x1e5c, 0x1e5c,
+ 0x1e5e, 0x1e5e,
+ 0x1e60, 0x1e60,
+ 0x1e62, 0x1e62,
+ 0x1e64, 0x1e64,
+ 0x1e66, 0x1e66,
+ 0x1e68, 0x1e68,
+ 0x1e6a, 0x1e6a,
+ 0x1e6c, 0x1e6c,
+ 0x1e6e, 0x1e6e,
+ 0x1e70, 0x1e70,
+ 0x1e72, 0x1e72,
+ 0x1e74, 0x1e74,
+ 0x1e76, 0x1e76,
+ 0x1e78, 0x1e78,
+ 0x1e7a, 0x1e7a,
+ 0x1e7c, 0x1e7c,
+ 0x1e7e, 0x1e7e,
+ 0x1e80, 0x1e80,
+ 0x1e82, 0x1e82,
+ 0x1e84, 0x1e84,
+ 0x1e86, 0x1e86,
+ 0x1e88, 0x1e88,
+ 0x1e8a, 0x1e8a,
+ 0x1e8c, 0x1e8c,
+ 0x1e8e, 0x1e8e,
+ 0x1e90, 0x1e90,
+ 0x1e92, 0x1e92,
+ 0x1e94, 0x1e94,
+ 0x1e9e, 0x1e9e,
+ 0x1ea0, 0x1ea0,
+ 0x1ea2, 0x1ea2,
+ 0x1ea4, 0x1ea4,
+ 0x1ea6, 0x1ea6,
+ 0x1ea8, 0x1ea8,
+ 0x1eaa, 0x1eaa,
+ 0x1eac, 0x1eac,
+ 0x1eae, 0x1eae,
+ 0x1eb0, 0x1eb0,
+ 0x1eb2, 0x1eb2,
+ 0x1eb4, 0x1eb4,
+ 0x1eb6, 0x1eb6,
+ 0x1eb8, 0x1eb8,
+ 0x1eba, 0x1eba,
+ 0x1ebc, 0x1ebc,
+ 0x1ebe, 0x1ebe,
+ 0x1ec0, 0x1ec0,
+ 0x1ec2, 0x1ec2,
+ 0x1ec4, 0x1ec4,
+ 0x1ec6, 0x1ec6,
+ 0x1ec8, 0x1ec8,
+ 0x1eca, 0x1eca,
+ 0x1ecc, 0x1ecc,
+ 0x1ece, 0x1ece,
+ 0x1ed0, 0x1ed0,
+ 0x1ed2, 0x1ed2,
+ 0x1ed4, 0x1ed4,
+ 0x1ed6, 0x1ed6,
+ 0x1ed8, 0x1ed8,
+ 0x1eda, 0x1eda,
+ 0x1edc, 0x1edc,
+ 0x1ede, 0x1ede,
+ 0x1ee0, 0x1ee0,
+ 0x1ee2, 0x1ee2,
+ 0x1ee4, 0x1ee4,
+ 0x1ee6, 0x1ee6,
+ 0x1ee8, 0x1ee8,
+ 0x1eea, 0x1eea,
+ 0x1eec, 0x1eec,
+ 0x1eee, 0x1eee,
+ 0x1ef0, 0x1ef0,
+ 0x1ef2, 0x1ef2,
+ 0x1ef4, 0x1ef4,
+ 0x1ef6, 0x1ef6,
+ 0x1ef8, 0x1ef8,
+ 0x1efa, 0x1efa,
+ 0x1efc, 0x1efc,
+ 0x1efe, 0x1efe,
+ 0x1f08, 0x1f0f,
+ 0x1f18, 0x1f1d,
+ 0x1f28, 0x1f2f,
+ 0x1f38, 0x1f3f,
+ 0x1f48, 0x1f4d,
+ 0x1f59, 0x1f59,
+ 0x1f5b, 0x1f5b,
+ 0x1f5d, 0x1f5d,
+ 0x1f5f, 0x1f5f,
+ 0x1f68, 0x1f6f,
+ 0x1fb8, 0x1fbb,
+ 0x1fc8, 0x1fcb,
+ 0x1fd8, 0x1fdb,
+ 0x1fe8, 0x1fec,
+ 0x1ff8, 0x1ffb,
+ 0x2102, 0x2102,
+ 0x2107, 0x2107,
+ 0x210b, 0x210d,
+ 0x2110, 0x2112,
+ 0x2115, 0x2115,
+ 0x2119, 0x211d,
+ 0x2124, 0x2124,
+ 0x2126, 0x2126,
+ 0x2128, 0x2128,
+ 0x212a, 0x212d,
+ 0x2130, 0x2133,
+ 0x213e, 0x213f,
+ 0x2145, 0x2145,
+ 0x2183, 0x2183,
+ 0x2c00, 0x2c2f,
+ 0x2c60, 0x2c60,
+ 0x2c62, 0x2c64,
+ 0x2c67, 0x2c67,
+ 0x2c69, 0x2c69,
+ 0x2c6b, 0x2c6b,
+ 0x2c6d, 0x2c70,
+ 0x2c72, 0x2c72,
+ 0x2c75, 0x2c75,
+ 0x2c7e, 0x2c80,
+ 0x2c82, 0x2c82,
+ 0x2c84, 0x2c84,
+ 0x2c86, 0x2c86,
+ 0x2c88, 0x2c88,
+ 0x2c8a, 0x2c8a,
+ 0x2c8c, 0x2c8c,
+ 0x2c8e, 0x2c8e,
+ 0x2c90, 0x2c90,
+ 0x2c92, 0x2c92,
+ 0x2c94, 0x2c94,
+ 0x2c96, 0x2c96,
+ 0x2c98, 0x2c98,
+ 0x2c9a, 0x2c9a,
+ 0x2c9c, 0x2c9c,
+ 0x2c9e, 0x2c9e,
+ 0x2ca0, 0x2ca0,
+ 0x2ca2, 0x2ca2,
+ 0x2ca4, 0x2ca4,
+ 0x2ca6, 0x2ca6,
+ 0x2ca8, 0x2ca8,
+ 0x2caa, 0x2caa,
+ 0x2cac, 0x2cac,
+ 0x2cae, 0x2cae,
+ 0x2cb0, 0x2cb0,
+ 0x2cb2, 0x2cb2,
+ 0x2cb4, 0x2cb4,
+ 0x2cb6, 0x2cb6,
+ 0x2cb8, 0x2cb8,
+ 0x2cba, 0x2cba,
+ 0x2cbc, 0x2cbc,
+ 0x2cbe, 0x2cbe,
+ 0x2cc0, 0x2cc0,
+ 0x2cc2, 0x2cc2,
+ 0x2cc4, 0x2cc4,
+ 0x2cc6, 0x2cc6,
+ 0x2cc8, 0x2cc8,
+ 0x2cca, 0x2cca,
+ 0x2ccc, 0x2ccc,
+ 0x2cce, 0x2cce,
+ 0x2cd0, 0x2cd0,
+ 0x2cd2, 0x2cd2,
+ 0x2cd4, 0x2cd4,
+ 0x2cd6, 0x2cd6,
+ 0x2cd8, 0x2cd8,
+ 0x2cda, 0x2cda,
+ 0x2cdc, 0x2cdc,
+ 0x2cde, 0x2cde,
+ 0x2ce0, 0x2ce0,
+ 0x2ce2, 0x2ce2,
+ 0x2ceb, 0x2ceb,
+ 0x2ced, 0x2ced,
+ 0x2cf2, 0x2cf2,
+ 0xa640, 0xa640,
+ 0xa642, 0xa642,
+ 0xa644, 0xa644,
+ 0xa646, 0xa646,
+ 0xa648, 0xa648,
+ 0xa64a, 0xa64a,
+ 0xa64c, 0xa64c,
+ 0xa64e, 0xa64e,
+ 0xa650, 0xa650,
+ 0xa652, 0xa652,
+ 0xa654, 0xa654,
+ 0xa656, 0xa656,
+ 0xa658, 0xa658,
+ 0xa65a, 0xa65a,
+ 0xa65c, 0xa65c,
+ 0xa65e, 0xa65e,
+ 0xa660, 0xa660,
+ 0xa662, 0xa662,
+ 0xa664, 0xa664,
+ 0xa666, 0xa666,
+ 0xa668, 0xa668,
+ 0xa66a, 0xa66a,
+ 0xa66c, 0xa66c,
+ 0xa680, 0xa680,
+ 0xa682, 0xa682,
+ 0xa684, 0xa684,
+ 0xa686, 0xa686,
+ 0xa688, 0xa688,
+ 0xa68a, 0xa68a,
+ 0xa68c, 0xa68c,
+ 0xa68e, 0xa68e,
+ 0xa690, 0xa690,
+ 0xa692, 0xa692,
+ 0xa694, 0xa694,
+ 0xa696, 0xa696,
+ 0xa698, 0xa698,
+ 0xa69a, 0xa69a,
+ 0xa722, 0xa722,
+ 0xa724, 0xa724,
+ 0xa726, 0xa726,
+ 0xa728, 0xa728,
+ 0xa72a, 0xa72a,
+ 0xa72c, 0xa72c,
+ 0xa72e, 0xa72e,
+ 0xa732, 0xa732,
+ 0xa734, 0xa734,
+ 0xa736, 0xa736,
+ 0xa738, 0xa738,
+ 0xa73a, 0xa73a,
+ 0xa73c, 0xa73c,
+ 0xa73e, 0xa73e,
+ 0xa740, 0xa740,
+ 0xa742, 0xa742,
+ 0xa744, 0xa744,
+ 0xa746, 0xa746,
+ 0xa748, 0xa748,
+ 0xa74a, 0xa74a,
+ 0xa74c, 0xa74c,
+ 0xa74e, 0xa74e,
+ 0xa750, 0xa750,
+ 0xa752, 0xa752,
+ 0xa754, 0xa754,
+ 0xa756, 0xa756,
+ 0xa758, 0xa758,
+ 0xa75a, 0xa75a,
+ 0xa75c, 0xa75c,
+ 0xa75e, 0xa75e,
+ 0xa760, 0xa760,
+ 0xa762, 0xa762,
+ 0xa764, 0xa764,
+ 0xa766, 0xa766,
+ 0xa768, 0xa768,
+ 0xa76a, 0xa76a,
+ 0xa76c, 0xa76c,
+ 0xa76e, 0xa76e,
+ 0xa779, 0xa779,
+ 0xa77b, 0xa77b,
+ 0xa77d, 0xa77e,
+ 0xa780, 0xa780,
+ 0xa782, 0xa782,
+ 0xa784, 0xa784,
+ 0xa786, 0xa786,
+ 0xa78b, 0xa78b,
+ 0xa78d, 0xa78d,
+ 0xa790, 0xa790,
+ 0xa792, 0xa792,
+ 0xa796, 0xa796,
+ 0xa798, 0xa798,
+ 0xa79a, 0xa79a,
+ 0xa79c, 0xa79c,
+ 0xa79e, 0xa79e,
+ 0xa7a0, 0xa7a0,
+ 0xa7a2, 0xa7a2,
+ 0xa7a4, 0xa7a4,
+ 0xa7a6, 0xa7a6,
+ 0xa7a8, 0xa7a8,
+ 0xa7aa, 0xa7ae,
+ 0xa7b0, 0xa7b4,
+ 0xa7b6, 0xa7b6,
+ 0xa7b8, 0xa7b8,
+ 0xa7ba, 0xa7ba,
+ 0xa7bc, 0xa7bc,
+ 0xa7be, 0xa7be,
+ 0xa7c0, 0xa7c0,
+ 0xa7c2, 0xa7c2,
+ 0xa7c4, 0xa7c7,
+ 0xa7c9, 0xa7c9,
+ 0xa7cb, 0xa7cc,
+ 0xa7ce, 0xa7ce,
+ 0xa7d0, 0xa7d0,
+ 0xa7d2, 0xa7d2,
+ 0xa7d4, 0xa7d4,
+ 0xa7d6, 0xa7d6,
+ 0xa7d8, 0xa7d8,
+ 0xa7da, 0xa7da,
+ 0xa7dc, 0xa7dc,
+ 0xa7f5, 0xa7f5,
+ 0xff21, 0xff3a,
+ 0x10400, 0x10427,
+ 0x104b0, 0x104d3,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10c80, 0x10cb2,
+ 0x10d50, 0x10d65,
+ 0x118a0, 0x118bf,
+ 0x16e40, 0x16e5f,
+ 0x16ea0, 0x16eb8,
+ 0x1d400, 0x1d419,
+ 0x1d434, 0x1d44d,
+ 0x1d468, 0x1d481,
+ 0x1d49c, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 0x1d4a2, 0x1d4a2,
+ 0x1d4a5, 0x1d4a6,
+ 0x1d4a9, 0x1d4ac,
+ 0x1d4ae, 0x1d4b5,
+ 0x1d4d0, 0x1d4e9,
+ 0x1d504, 0x1d505,
+ 0x1d507, 0x1d50a,
+ 0x1d50d, 0x1d514,
+ 0x1d516, 0x1d51c,
+ 0x1d538, 0x1d539,
+ 0x1d53b, 0x1d53e,
+ 0x1d540, 0x1d544,
+ 0x1d546, 0x1d546,
+ 0x1d54a, 0x1d550,
+ 0x1d56c, 0x1d585,
+ 0x1d5a0, 0x1d5b9,
+ 0x1d5d4, 0x1d5ed,
+ 0x1d608, 0x1d621,
+ 0x1d63c, 0x1d655,
+ 0x1d670, 0x1d689,
+ 0x1d6a8, 0x1d6c0,
+ 0x1d6e2, 0x1d6fa,
+ 0x1d71c, 0x1d734,
+ 0x1d756, 0x1d76e,
+ 0x1d790, 0x1d7a8,
+ 0x1d7ca, 0x1d7ca,
+ 0x1e900, 0x1e921,
+}; /* CR_Lu */
+
+/* 'M': Major Category */
+static const OnigCodePoint CR_M[] = {
+ 327,
+ 0x0300, 0x036f,
+ 0x0483, 0x0489,
+ 0x0591, 0x05bd,
+ 0x05bf, 0x05bf,
+ 0x05c1, 0x05c2,
+ 0x05c4, 0x05c5,
+ 0x05c7, 0x05c7,
+ 0x0610, 0x061a,
+ 0x064b, 0x065f,
+ 0x0670, 0x0670,
+ 0x06d6, 0x06dc,
+ 0x06df, 0x06e4,
+ 0x06e7, 0x06e8,
+ 0x06ea, 0x06ed,
+ 0x0711, 0x0711,
+ 0x0730, 0x074a,
+ 0x07a6, 0x07b0,
+ 0x07eb, 0x07f3,
+ 0x07fd, 0x07fd,
+ 0x0816, 0x0819,
+ 0x081b, 0x0823,
+ 0x0825, 0x0827,
+ 0x0829, 0x082d,
+ 0x0859, 0x085b,
+ 0x0897, 0x089f,
+ 0x08ca, 0x08e1,
+ 0x08e3, 0x0903,
+ 0x093a, 0x093c,
+ 0x093e, 0x094f,
+ 0x0951, 0x0957,
+ 0x0962, 0x0963,
+ 0x0981, 0x0983,
+ 0x09bc, 0x09bc,
+ 0x09be, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09cd,
+ 0x09d7, 0x09d7,
+ 0x09e2, 0x09e3,
+ 0x09fe, 0x09fe,
+ 0x0a01, 0x0a03,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 0x0a70, 0x0a71,
+ 0x0a75, 0x0a75,
+ 0x0a81, 0x0a83,
+ 0x0abc, 0x0abc,
+ 0x0abe, 0x0ac5,
+ 0x0ac7, 0x0ac9,
+ 0x0acb, 0x0acd,
+ 0x0ae2, 0x0ae3,
+ 0x0afa, 0x0aff,
+ 0x0b01, 0x0b03,
+ 0x0b3c, 0x0b3c,
+ 0x0b3e, 0x0b44,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4d,
+ 0x0b55, 0x0b57,
+ 0x0b62, 0x0b63,
+ 0x0b82, 0x0b82,
+ 0x0bbe, 0x0bc2,
+ 0x0bc6, 0x0bc8,
+ 0x0bca, 0x0bcd,
+ 0x0bd7, 0x0bd7,
+ 0x0c00, 0x0c04,
+ 0x0c3c, 0x0c3c,
+ 0x0c3e, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c62, 0x0c63,
+ 0x0c81, 0x0c83,
+ 0x0cbc, 0x0cbc,
+ 0x0cbe, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0ce2, 0x0ce3,
+ 0x0cf3, 0x0cf3,
+ 0x0d00, 0x0d03,
+ 0x0d3b, 0x0d3c,
+ 0x0d3e, 0x0d44,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4d,
+ 0x0d57, 0x0d57,
+ 0x0d62, 0x0d63,
+ 0x0d81, 0x0d83,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0df2, 0x0df3,
+ 0x0e31, 0x0e31,
+ 0x0e34, 0x0e3a,
+ 0x0e47, 0x0e4e,
+ 0x0eb1, 0x0eb1,
+ 0x0eb4, 0x0ebc,
+ 0x0ec8, 0x0ece,
+ 0x0f18, 0x0f19,
+ 0x0f35, 0x0f35,
+ 0x0f37, 0x0f37,
+ 0x0f39, 0x0f39,
+ 0x0f3e, 0x0f3f,
+ 0x0f71, 0x0f84,
+ 0x0f86, 0x0f87,
+ 0x0f8d, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 0x0fc6, 0x0fc6,
+ 0x102b, 0x103e,
+ 0x1056, 0x1059,
+ 0x105e, 0x1060,
+ 0x1062, 0x1064,
+ 0x1067, 0x106d,
+ 0x1071, 0x1074,
+ 0x1082, 0x108d,
+ 0x108f, 0x108f,
+ 0x109a, 0x109d,
+ 0x135d, 0x135f,
+ 0x1712, 0x1715,
+ 0x1732, 0x1734,
+ 0x1752, 0x1753,
+ 0x1772, 0x1773,
+ 0x17b4, 0x17d3,
+ 0x17dd, 0x17dd,
+ 0x180b, 0x180d,
+ 0x180f, 0x180f,
+ 0x1885, 0x1886,
+ 0x18a9, 0x18a9,
+ 0x1920, 0x192b,
+ 0x1930, 0x193b,
+ 0x1a17, 0x1a1b,
+ 0x1a55, 0x1a5e,
+ 0x1a60, 0x1a7c,
+ 0x1a7f, 0x1a7f,
+ 0x1ab0, 0x1add,
+ 0x1ae0, 0x1aeb,
+ 0x1b00, 0x1b04,
+ 0x1b34, 0x1b44,
+ 0x1b6b, 0x1b73,
+ 0x1b80, 0x1b82,
+ 0x1ba1, 0x1bad,
+ 0x1be6, 0x1bf3,
+ 0x1c24, 0x1c37,
+ 0x1cd0, 0x1cd2,
+ 0x1cd4, 0x1ce8,
+ 0x1ced, 0x1ced,
+ 0x1cf4, 0x1cf4,
+ 0x1cf7, 0x1cf9,
+ 0x1dc0, 0x1dff,
+ 0x20d0, 0x20f0,
+ 0x2cef, 0x2cf1,
+ 0x2d7f, 0x2d7f,
+ 0x2de0, 0x2dff,
+ 0x302a, 0x302f,
+ 0x3099, 0x309a,
+ 0xa66f, 0xa672,
+ 0xa674, 0xa67d,
+ 0xa69e, 0xa69f,
+ 0xa6f0, 0xa6f1,
+ 0xa802, 0xa802,
+ 0xa806, 0xa806,
+ 0xa80b, 0xa80b,
+ 0xa823, 0xa827,
+ 0xa82c, 0xa82c,
+ 0xa880, 0xa881,
+ 0xa8b4, 0xa8c5,
+ 0xa8e0, 0xa8f1,
+ 0xa8ff, 0xa8ff,
+ 0xa926, 0xa92d,
+ 0xa947, 0xa953,
+ 0xa980, 0xa983,
+ 0xa9b3, 0xa9c0,
+ 0xa9e5, 0xa9e5,
+ 0xaa29, 0xaa36,
+ 0xaa43, 0xaa43,
+ 0xaa4c, 0xaa4d,
+ 0xaa7b, 0xaa7d,
+ 0xaab0, 0xaab0,
+ 0xaab2, 0xaab4,
+ 0xaab7, 0xaab8,
+ 0xaabe, 0xaabf,
+ 0xaac1, 0xaac1,
+ 0xaaeb, 0xaaef,
+ 0xaaf5, 0xaaf6,
+ 0xabe3, 0xabea,
+ 0xabec, 0xabed,
+ 0xfb1e, 0xfb1e,
+ 0xfe00, 0xfe0f,
+ 0xfe20, 0xfe2f,
+ 0x101fd, 0x101fd,
+ 0x102e0, 0x102e0,
+ 0x10376, 0x1037a,
+ 0x10a01, 0x10a03,
+ 0x10a05, 0x10a06,
+ 0x10a0c, 0x10a0f,
+ 0x10a38, 0x10a3a,
+ 0x10a3f, 0x10a3f,
+ 0x10ae5, 0x10ae6,
+ 0x10d24, 0x10d27,
+ 0x10d69, 0x10d6d,
+ 0x10eab, 0x10eac,
+ 0x10efa, 0x10eff,
+ 0x10f46, 0x10f50,
+ 0x10f82, 0x10f85,
+ 0x11000, 0x11002,
+ 0x11038, 0x11046,
+ 0x11070, 0x11070,
+ 0x11073, 0x11074,
+ 0x1107f, 0x11082,
+ 0x110b0, 0x110ba,
+ 0x110c2, 0x110c2,
+ 0x11100, 0x11102,
+ 0x11127, 0x11134,
+ 0x11145, 0x11146,
+ 0x11173, 0x11173,
+ 0x11180, 0x11182,
+ 0x111b3, 0x111c0,
+ 0x111c9, 0x111cc,
+ 0x111ce, 0x111cf,
+ 0x1122c, 0x11237,
+ 0x1123e, 0x1123e,
+ 0x11241, 0x11241,
+ 0x112df, 0x112ea,
+ 0x11300, 0x11303,
+ 0x1133b, 0x1133c,
+ 0x1133e, 0x11344,
+ 0x11347, 0x11348,
+ 0x1134b, 0x1134d,
+ 0x11357, 0x11357,
+ 0x11362, 0x11363,
+ 0x11366, 0x1136c,
+ 0x11370, 0x11374,
+ 0x113b8, 0x113c0,
+ 0x113c2, 0x113c2,
+ 0x113c5, 0x113c5,
+ 0x113c7, 0x113ca,
+ 0x113cc, 0x113d0,
+ 0x113d2, 0x113d2,
+ 0x113e1, 0x113e2,
+ 0x11435, 0x11446,
+ 0x1145e, 0x1145e,
+ 0x114b0, 0x114c3,
+ 0x115af, 0x115b5,
+ 0x115b8, 0x115c0,
+ 0x115dc, 0x115dd,
+ 0x11630, 0x11640,
+ 0x116ab, 0x116b7,
+ 0x1171d, 0x1172b,
+ 0x1182c, 0x1183a,
+ 0x11930, 0x11935,
+ 0x11937, 0x11938,
+ 0x1193b, 0x1193e,
+ 0x11940, 0x11940,
+ 0x11942, 0x11943,
+ 0x119d1, 0x119d7,
+ 0x119da, 0x119e0,
+ 0x119e4, 0x119e4,
+ 0x11a01, 0x11a0a,
+ 0x11a33, 0x11a39,
+ 0x11a3b, 0x11a3e,
+ 0x11a47, 0x11a47,
+ 0x11a51, 0x11a5b,
+ 0x11a8a, 0x11a99,
+ 0x11b60, 0x11b67,
+ 0x11c2f, 0x11c36,
+ 0x11c38, 0x11c3f,
+ 0x11c92, 0x11ca7,
+ 0x11ca9, 0x11cb6,
+ 0x11d31, 0x11d36,
+ 0x11d3a, 0x11d3a,
+ 0x11d3c, 0x11d3d,
+ 0x11d3f, 0x11d45,
+ 0x11d47, 0x11d47,
+ 0x11d8a, 0x11d8e,
+ 0x11d90, 0x11d91,
+ 0x11d93, 0x11d97,
+ 0x11ef3, 0x11ef6,
+ 0x11f00, 0x11f01,
+ 0x11f03, 0x11f03,
+ 0x11f34, 0x11f3a,
+ 0x11f3e, 0x11f42,
+ 0x11f5a, 0x11f5a,
+ 0x13440, 0x13440,
+ 0x13447, 0x13455,
+ 0x1611e, 0x1612f,
+ 0x16af0, 0x16af4,
+ 0x16b30, 0x16b36,
+ 0x16f4f, 0x16f4f,
+ 0x16f51, 0x16f87,
+ 0x16f8f, 0x16f92,
+ 0x16fe4, 0x16fe4,
+ 0x16ff0, 0x16ff1,
+ 0x1bc9d, 0x1bc9e,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
+ 0x1d165, 0x1d169,
+ 0x1d16d, 0x1d172,
+ 0x1d17b, 0x1d182,
+ 0x1d185, 0x1d18b,
+ 0x1d1aa, 0x1d1ad,
+ 0x1d242, 0x1d244,
+ 0x1da00, 0x1da36,
+ 0x1da3b, 0x1da6c,
+ 0x1da75, 0x1da75,
+ 0x1da84, 0x1da84,
+ 0x1da9b, 0x1da9f,
+ 0x1daa1, 0x1daaf,
+ 0x1e000, 0x1e006,
+ 0x1e008, 0x1e018,
+ 0x1e01b, 0x1e021,
+ 0x1e023, 0x1e024,
+ 0x1e026, 0x1e02a,
+ 0x1e08f, 0x1e08f,
+ 0x1e130, 0x1e136,
+ 0x1e2ae, 0x1e2ae,
+ 0x1e2ec, 0x1e2ef,
+ 0x1e4ec, 0x1e4ef,
+ 0x1e5ee, 0x1e5ef,
+ 0x1e6e3, 0x1e6e3,
+ 0x1e6e6, 0x1e6e6,
+ 0x1e6ee, 0x1e6ef,
+ 0x1e6f5, 0x1e6f5,
+ 0x1e8d0, 0x1e8d6,
+ 0x1e944, 0x1e94a,
+ 0xe0100, 0xe01ef,
+}; /* CR_M */
+
+/* 'Mc': General Category */
+static const OnigCodePoint CR_Mc[] = {
+ 193,
+ 0x0903, 0x0903,
+ 0x093b, 0x093b,
+ 0x093e, 0x0940,
+ 0x0949, 0x094c,
+ 0x094e, 0x094f,
+ 0x0982, 0x0983,
+ 0x09be, 0x09c0,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09cc,
+ 0x09d7, 0x09d7,
+ 0x0a03, 0x0a03,
+ 0x0a3e, 0x0a40,
+ 0x0a83, 0x0a83,
+ 0x0abe, 0x0ac0,
+ 0x0ac9, 0x0ac9,
+ 0x0acb, 0x0acc,
+ 0x0b02, 0x0b03,
+ 0x0b3e, 0x0b3e,
+ 0x0b40, 0x0b40,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4c,
+ 0x0b57, 0x0b57,
+ 0x0bbe, 0x0bbf,
+ 0x0bc1, 0x0bc2,
+ 0x0bc6, 0x0bc8,
+ 0x0bca, 0x0bcc,
+ 0x0bd7, 0x0bd7,
+ 0x0c01, 0x0c03,
+ 0x0c41, 0x0c44,
+ 0x0c82, 0x0c83,
+ 0x0cbe, 0x0cbe,
+ 0x0cc0, 0x0cc4,
+ 0x0cc7, 0x0cc8,
+ 0x0cca, 0x0ccb,
+ 0x0cd5, 0x0cd6,
+ 0x0cf3, 0x0cf3,
+ 0x0d02, 0x0d03,
+ 0x0d3e, 0x0d40,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4c,
+ 0x0d57, 0x0d57,
+ 0x0d82, 0x0d83,
+ 0x0dcf, 0x0dd1,
+ 0x0dd8, 0x0ddf,
+ 0x0df2, 0x0df3,
+ 0x0f3e, 0x0f3f,
+ 0x0f7f, 0x0f7f,
+ 0x102b, 0x102c,
+ 0x1031, 0x1031,
+ 0x1038, 0x1038,
+ 0x103b, 0x103c,
+ 0x1056, 0x1057,
+ 0x1062, 0x1064,
+ 0x1067, 0x106d,
+ 0x1083, 0x1084,
+ 0x1087, 0x108c,
+ 0x108f, 0x108f,
+ 0x109a, 0x109c,
+ 0x1715, 0x1715,
+ 0x1734, 0x1734,
+ 0x17b6, 0x17b6,
+ 0x17be, 0x17c5,
+ 0x17c7, 0x17c8,
+ 0x1923, 0x1926,
+ 0x1929, 0x192b,
+ 0x1930, 0x1931,
+ 0x1933, 0x1938,
+ 0x1a19, 0x1a1a,
+ 0x1a55, 0x1a55,
+ 0x1a57, 0x1a57,
+ 0x1a61, 0x1a61,
+ 0x1a63, 0x1a64,
+ 0x1a6d, 0x1a72,
+ 0x1b04, 0x1b04,
+ 0x1b35, 0x1b35,
+ 0x1b3b, 0x1b3b,
+ 0x1b3d, 0x1b41,
+ 0x1b43, 0x1b44,
+ 0x1b82, 0x1b82,
+ 0x1ba1, 0x1ba1,
+ 0x1ba6, 0x1ba7,
+ 0x1baa, 0x1baa,
+ 0x1be7, 0x1be7,
+ 0x1bea, 0x1bec,
+ 0x1bee, 0x1bee,
+ 0x1bf2, 0x1bf3,
+ 0x1c24, 0x1c2b,
+ 0x1c34, 0x1c35,
+ 0x1ce1, 0x1ce1,
+ 0x1cf7, 0x1cf7,
+ 0x302e, 0x302f,
+ 0xa823, 0xa824,
+ 0xa827, 0xa827,
+ 0xa880, 0xa881,
+ 0xa8b4, 0xa8c3,
+ 0xa952, 0xa953,
+ 0xa983, 0xa983,
+ 0xa9b4, 0xa9b5,
+ 0xa9ba, 0xa9bb,
+ 0xa9be, 0xa9c0,
+ 0xaa2f, 0xaa30,
+ 0xaa33, 0xaa34,
+ 0xaa4d, 0xaa4d,
+ 0xaa7b, 0xaa7b,
+ 0xaa7d, 0xaa7d,
+ 0xaaeb, 0xaaeb,
+ 0xaaee, 0xaaef,
+ 0xaaf5, 0xaaf5,
+ 0xabe3, 0xabe4,
+ 0xabe6, 0xabe7,
+ 0xabe9, 0xabea,
+ 0xabec, 0xabec,
+ 0x11000, 0x11000,
+ 0x11002, 0x11002,
+ 0x11082, 0x11082,
+ 0x110b0, 0x110b2,
+ 0x110b7, 0x110b8,
+ 0x1112c, 0x1112c,
+ 0x11145, 0x11146,
+ 0x11182, 0x11182,
+ 0x111b3, 0x111b5,
+ 0x111bf, 0x111c0,
+ 0x111ce, 0x111ce,
+ 0x1122c, 0x1122e,
+ 0x11232, 0x11233,
+ 0x11235, 0x11235,
+ 0x112e0, 0x112e2,
+ 0x11302, 0x11303,
+ 0x1133e, 0x1133f,
+ 0x11341, 0x11344,
+ 0x11347, 0x11348,
+ 0x1134b, 0x1134d,
+ 0x11357, 0x11357,
+ 0x11362, 0x11363,
+ 0x113b8, 0x113ba,
+ 0x113c2, 0x113c2,
+ 0x113c5, 0x113c5,
+ 0x113c7, 0x113ca,
+ 0x113cc, 0x113cd,
+ 0x113cf, 0x113cf,
+ 0x11435, 0x11437,
+ 0x11440, 0x11441,
+ 0x11445, 0x11445,
+ 0x114b0, 0x114b2,
+ 0x114b9, 0x114b9,
+ 0x114bb, 0x114be,
+ 0x114c1, 0x114c1,
+ 0x115af, 0x115b1,
+ 0x115b8, 0x115bb,
+ 0x115be, 0x115be,
+ 0x11630, 0x11632,
+ 0x1163b, 0x1163c,
+ 0x1163e, 0x1163e,
+ 0x116ac, 0x116ac,
+ 0x116ae, 0x116af,
+ 0x116b6, 0x116b6,
+ 0x1171e, 0x1171e,
+ 0x11720, 0x11721,
+ 0x11726, 0x11726,
+ 0x1182c, 0x1182e,
+ 0x11838, 0x11838,
+ 0x11930, 0x11935,
+ 0x11937, 0x11938,
+ 0x1193d, 0x1193d,
+ 0x11940, 0x11940,
+ 0x11942, 0x11942,
+ 0x119d1, 0x119d3,
+ 0x119dc, 0x119df,
+ 0x119e4, 0x119e4,
+ 0x11a39, 0x11a39,
+ 0x11a57, 0x11a58,
+ 0x11a97, 0x11a97,
+ 0x11b61, 0x11b61,
+ 0x11b65, 0x11b65,
+ 0x11b67, 0x11b67,
+ 0x11c2f, 0x11c2f,
+ 0x11c3e, 0x11c3e,
+ 0x11ca9, 0x11ca9,
+ 0x11cb1, 0x11cb1,
+ 0x11cb4, 0x11cb4,
+ 0x11d8a, 0x11d8e,
+ 0x11d93, 0x11d94,
+ 0x11d96, 0x11d96,
+ 0x11ef5, 0x11ef6,
+ 0x11f03, 0x11f03,
+ 0x11f34, 0x11f35,
+ 0x11f3e, 0x11f3f,
+ 0x11f41, 0x11f41,
+ 0x1612a, 0x1612c,
+ 0x16f51, 0x16f87,
+ 0x16ff0, 0x16ff1,
+ 0x1d165, 0x1d166,
+ 0x1d16d, 0x1d172,
+}; /* CR_Mc */
+
+/* 'Me': General Category */
+static const OnigCodePoint CR_Me[] = {
+ 5,
+ 0x0488, 0x0489,
+ 0x1abe, 0x1abe,
+ 0x20dd, 0x20e0,
+ 0x20e2, 0x20e4,
+ 0xa670, 0xa672,
+}; /* CR_Me */
+
+/* 'Mn': General Category */
+static const OnigCodePoint CR_Mn[] = {
+ 365,
+ 0x0300, 0x036f,
+ 0x0483, 0x0487,
+ 0x0591, 0x05bd,
+ 0x05bf, 0x05bf,
+ 0x05c1, 0x05c2,
+ 0x05c4, 0x05c5,
+ 0x05c7, 0x05c7,
+ 0x0610, 0x061a,
+ 0x064b, 0x065f,
+ 0x0670, 0x0670,
+ 0x06d6, 0x06dc,
+ 0x06df, 0x06e4,
+ 0x06e7, 0x06e8,
+ 0x06ea, 0x06ed,
+ 0x0711, 0x0711,
+ 0x0730, 0x074a,
+ 0x07a6, 0x07b0,
+ 0x07eb, 0x07f3,
+ 0x07fd, 0x07fd,
+ 0x0816, 0x0819,
+ 0x081b, 0x0823,
+ 0x0825, 0x0827,
+ 0x0829, 0x082d,
+ 0x0859, 0x085b,
+ 0x0897, 0x089f,
+ 0x08ca, 0x08e1,
+ 0x08e3, 0x0902,
+ 0x093a, 0x093a,
+ 0x093c, 0x093c,
+ 0x0941, 0x0948,
+ 0x094d, 0x094d,
+ 0x0951, 0x0957,
+ 0x0962, 0x0963,
+ 0x0981, 0x0981,
+ 0x09bc, 0x09bc,
+ 0x09c1, 0x09c4,
+ 0x09cd, 0x09cd,
+ 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,
+ 0x0b3f, 0x0b3f,
+ 0x0b41, 0x0b44,
+ 0x0b4d, 0x0b4d,
+ 0x0b55, 0x0b56,
+ 0x0b62, 0x0b63,
+ 0x0b82, 0x0b82,
+ 0x0bc0, 0x0bc0,
+ 0x0bcd, 0x0bcd,
+ 0x0c00, 0x0c00,
+ 0x0c04, 0x0c04,
+ 0x0c3c, 0x0c3c,
+ 0x0c3e, 0x0c40,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c62, 0x0c63,
+ 0x0c81, 0x0c81,
+ 0x0cbc, 0x0cbc,
+ 0x0cbf, 0x0cbf,
+ 0x0cc6, 0x0cc6,
+ 0x0ccc, 0x0ccd,
+ 0x0ce2, 0x0ce3,
+ 0x0d00, 0x0d01,
+ 0x0d3b, 0x0d3c,
+ 0x0d41, 0x0d44,
+ 0x0d4d, 0x0d4d,
+ 0x0d62, 0x0d63,
+ 0x0d81, 0x0d81,
+ 0x0dca, 0x0dca,
+ 0x0dd2, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0e31, 0x0e31,
+ 0x0e34, 0x0e3a,
+ 0x0e47, 0x0e4e,
+ 0x0eb1, 0x0eb1,
+ 0x0eb4, 0x0ebc,
+ 0x0ec8, 0x0ece,
+ 0x0f18, 0x0f19,
+ 0x0f35, 0x0f35,
+ 0x0f37, 0x0f37,
+ 0x0f39, 0x0f39,
+ 0x0f71, 0x0f7e,
+ 0x0f80, 0x0f84,
+ 0x0f86, 0x0f87,
+ 0x0f8d, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 0x0fc6, 0x0fc6,
+ 0x102d, 0x1030,
+ 0x1032, 0x1037,
+ 0x1039, 0x103a,
+ 0x103d, 0x103e,
+ 0x1058, 0x1059,
+ 0x105e, 0x1060,
+ 0x1071, 0x1074,
+ 0x1082, 0x1082,
+ 0x1085, 0x1086,
+ 0x108d, 0x108d,
+ 0x109d, 0x109d,
+ 0x135d, 0x135f,
+ 0x1712, 0x1714,
+ 0x1732, 0x1733,
+ 0x1752, 0x1753,
+ 0x1772, 0x1773,
+ 0x17b4, 0x17b5,
+ 0x17b7, 0x17bd,
+ 0x17c6, 0x17c6,
+ 0x17c9, 0x17d3,
+ 0x17dd, 0x17dd,
+ 0x180b, 0x180d,
+ 0x180f, 0x180f,
+ 0x1885, 0x1886,
+ 0x18a9, 0x18a9,
+ 0x1920, 0x1922,
+ 0x1927, 0x1928,
+ 0x1932, 0x1932,
+ 0x1939, 0x193b,
+ 0x1a17, 0x1a18,
+ 0x1a1b, 0x1a1b,
+ 0x1a56, 0x1a56,
+ 0x1a58, 0x1a5e,
+ 0x1a60, 0x1a60,
+ 0x1a62, 0x1a62,
+ 0x1a65, 0x1a6c,
+ 0x1a73, 0x1a7c,
+ 0x1a7f, 0x1a7f,
+ 0x1ab0, 0x1abd,
+ 0x1abf, 0x1add,
+ 0x1ae0, 0x1aeb,
+ 0x1b00, 0x1b03,
+ 0x1b34, 0x1b34,
+ 0x1b36, 0x1b3a,
+ 0x1b3c, 0x1b3c,
+ 0x1b42, 0x1b42,
+ 0x1b6b, 0x1b73,
+ 0x1b80, 0x1b81,
+ 0x1ba2, 0x1ba5,
+ 0x1ba8, 0x1ba9,
+ 0x1bab, 0x1bad,
+ 0x1be6, 0x1be6,
+ 0x1be8, 0x1be9,
+ 0x1bed, 0x1bed,
+ 0x1bef, 0x1bf1,
+ 0x1c2c, 0x1c33,
+ 0x1c36, 0x1c37,
+ 0x1cd0, 0x1cd2,
+ 0x1cd4, 0x1ce0,
+ 0x1ce2, 0x1ce8,
+ 0x1ced, 0x1ced,
+ 0x1cf4, 0x1cf4,
+ 0x1cf8, 0x1cf9,
+ 0x1dc0, 0x1dff,
+ 0x20d0, 0x20dc,
+ 0x20e1, 0x20e1,
+ 0x20e5, 0x20f0,
+ 0x2cef, 0x2cf1,
+ 0x2d7f, 0x2d7f,
+ 0x2de0, 0x2dff,
+ 0x302a, 0x302d,
+ 0x3099, 0x309a,
+ 0xa66f, 0xa66f,
+ 0xa674, 0xa67d,
+ 0xa69e, 0xa69f,
+ 0xa6f0, 0xa6f1,
+ 0xa802, 0xa802,
+ 0xa806, 0xa806,
+ 0xa80b, 0xa80b,
+ 0xa825, 0xa826,
+ 0xa82c, 0xa82c,
+ 0xa8c4, 0xa8c5,
+ 0xa8e0, 0xa8f1,
+ 0xa8ff, 0xa8ff,
+ 0xa926, 0xa92d,
+ 0xa947, 0xa951,
+ 0xa980, 0xa982,
+ 0xa9b3, 0xa9b3,
+ 0xa9b6, 0xa9b9,
+ 0xa9bc, 0xa9bd,
+ 0xa9e5, 0xa9e5,
+ 0xaa29, 0xaa2e,
+ 0xaa31, 0xaa32,
+ 0xaa35, 0xaa36,
+ 0xaa43, 0xaa43,
+ 0xaa4c, 0xaa4c,
+ 0xaa7c, 0xaa7c,
+ 0xaab0, 0xaab0,
+ 0xaab2, 0xaab4,
+ 0xaab7, 0xaab8,
+ 0xaabe, 0xaabf,
+ 0xaac1, 0xaac1,
+ 0xaaec, 0xaaed,
+ 0xaaf6, 0xaaf6,
+ 0xabe5, 0xabe5,
+ 0xabe8, 0xabe8,
+ 0xabed, 0xabed,
+ 0xfb1e, 0xfb1e,
+ 0xfe00, 0xfe0f,
+ 0xfe20, 0xfe2f,
+ 0x101fd, 0x101fd,
+ 0x102e0, 0x102e0,
+ 0x10376, 0x1037a,
+ 0x10a01, 0x10a03,
+ 0x10a05, 0x10a06,
+ 0x10a0c, 0x10a0f,
+ 0x10a38, 0x10a3a,
+ 0x10a3f, 0x10a3f,
+ 0x10ae5, 0x10ae6,
+ 0x10d24, 0x10d27,
+ 0x10d69, 0x10d6d,
+ 0x10eab, 0x10eac,
+ 0x10efa, 0x10eff,
+ 0x10f46, 0x10f50,
+ 0x10f82, 0x10f85,
+ 0x11001, 0x11001,
+ 0x11038, 0x11046,
+ 0x11070, 0x11070,
+ 0x11073, 0x11074,
+ 0x1107f, 0x11081,
+ 0x110b3, 0x110b6,
+ 0x110b9, 0x110ba,
+ 0x110c2, 0x110c2,
+ 0x11100, 0x11102,
+ 0x11127, 0x1112b,
+ 0x1112d, 0x11134,
+ 0x11173, 0x11173,
+ 0x11180, 0x11181,
+ 0x111b6, 0x111be,
+ 0x111c9, 0x111cc,
+ 0x111cf, 0x111cf,
+ 0x1122f, 0x11231,
+ 0x11234, 0x11234,
+ 0x11236, 0x11237,
+ 0x1123e, 0x1123e,
+ 0x11241, 0x11241,
+ 0x112df, 0x112df,
+ 0x112e3, 0x112ea,
+ 0x11300, 0x11301,
+ 0x1133b, 0x1133c,
+ 0x11340, 0x11340,
+ 0x11366, 0x1136c,
+ 0x11370, 0x11374,
+ 0x113bb, 0x113c0,
+ 0x113ce, 0x113ce,
+ 0x113d0, 0x113d0,
+ 0x113d2, 0x113d2,
+ 0x113e1, 0x113e2,
+ 0x11438, 0x1143f,
+ 0x11442, 0x11444,
+ 0x11446, 0x11446,
+ 0x1145e, 0x1145e,
+ 0x114b3, 0x114b8,
+ 0x114ba, 0x114ba,
+ 0x114bf, 0x114c0,
+ 0x114c2, 0x114c3,
+ 0x115b2, 0x115b5,
+ 0x115bc, 0x115bd,
+ 0x115bf, 0x115c0,
+ 0x115dc, 0x115dd,
+ 0x11633, 0x1163a,
+ 0x1163d, 0x1163d,
+ 0x1163f, 0x11640,
+ 0x116ab, 0x116ab,
+ 0x116ad, 0x116ad,
+ 0x116b0, 0x116b5,
+ 0x116b7, 0x116b7,
+ 0x1171d, 0x1171d,
+ 0x1171f, 0x1171f,
+ 0x11722, 0x11725,
+ 0x11727, 0x1172b,
+ 0x1182f, 0x11837,
+ 0x11839, 0x1183a,
+ 0x1193b, 0x1193c,
+ 0x1193e, 0x1193e,
+ 0x11943, 0x11943,
+ 0x119d4, 0x119d7,
+ 0x119da, 0x119db,
+ 0x119e0, 0x119e0,
+ 0x11a01, 0x11a0a,
+ 0x11a33, 0x11a38,
+ 0x11a3b, 0x11a3e,
+ 0x11a47, 0x11a47,
+ 0x11a51, 0x11a56,
+ 0x11a59, 0x11a5b,
+ 0x11a8a, 0x11a96,
+ 0x11a98, 0x11a99,
+ 0x11b60, 0x11b60,
+ 0x11b62, 0x11b64,
+ 0x11b66, 0x11b66,
+ 0x11c30, 0x11c36,
+ 0x11c38, 0x11c3d,
+ 0x11c3f, 0x11c3f,
+ 0x11c92, 0x11ca7,
+ 0x11caa, 0x11cb0,
+ 0x11cb2, 0x11cb3,
+ 0x11cb5, 0x11cb6,
+ 0x11d31, 0x11d36,
+ 0x11d3a, 0x11d3a,
+ 0x11d3c, 0x11d3d,
+ 0x11d3f, 0x11d45,
+ 0x11d47, 0x11d47,
+ 0x11d90, 0x11d91,
+ 0x11d95, 0x11d95,
+ 0x11d97, 0x11d97,
+ 0x11ef3, 0x11ef4,
+ 0x11f00, 0x11f01,
+ 0x11f36, 0x11f3a,
+ 0x11f40, 0x11f40,
+ 0x11f42, 0x11f42,
+ 0x11f5a, 0x11f5a,
+ 0x13440, 0x13440,
+ 0x13447, 0x13455,
+ 0x1611e, 0x16129,
+ 0x1612d, 0x1612f,
+ 0x16af0, 0x16af4,
+ 0x16b30, 0x16b36,
+ 0x16f4f, 0x16f4f,
+ 0x16f8f, 0x16f92,
+ 0x16fe4, 0x16fe4,
+ 0x1bc9d, 0x1bc9e,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
+ 0x1d167, 0x1d169,
+ 0x1d17b, 0x1d182,
+ 0x1d185, 0x1d18b,
+ 0x1d1aa, 0x1d1ad,
+ 0x1d242, 0x1d244,
+ 0x1da00, 0x1da36,
+ 0x1da3b, 0x1da6c,
+ 0x1da75, 0x1da75,
+ 0x1da84, 0x1da84,
+ 0x1da9b, 0x1da9f,
+ 0x1daa1, 0x1daaf,
+ 0x1e000, 0x1e006,
+ 0x1e008, 0x1e018,
+ 0x1e01b, 0x1e021,
+ 0x1e023, 0x1e024,
+ 0x1e026, 0x1e02a,
+ 0x1e08f, 0x1e08f,
+ 0x1e130, 0x1e136,
+ 0x1e2ae, 0x1e2ae,
+ 0x1e2ec, 0x1e2ef,
+ 0x1e4ec, 0x1e4ef,
+ 0x1e5ee, 0x1e5ef,
+ 0x1e6e3, 0x1e6e3,
+ 0x1e6e6, 0x1e6e6,
+ 0x1e6ee, 0x1e6ef,
+ 0x1e6f5, 0x1e6f5,
+ 0x1e8d0, 0x1e8d6,
+ 0x1e944, 0x1e94a,
+ 0xe0100, 0xe01ef,
+}; /* CR_Mn */
+
+/* 'N': Major Category */
+static const OnigCodePoint CR_N[] = {
+ 146,
+ 0x0030, 0x0039,
+ 0x00b2, 0x00b3,
+ 0x00b9, 0x00b9,
+ 0x00bc, 0x00be,
+ 0x0660, 0x0669,
+ 0x06f0, 0x06f9,
+ 0x07c0, 0x07c9,
+ 0x0966, 0x096f,
+ 0x09e6, 0x09ef,
+ 0x09f4, 0x09f9,
+ 0x0a66, 0x0a6f,
+ 0x0ae6, 0x0aef,
+ 0x0b66, 0x0b6f,
+ 0x0b72, 0x0b77,
+ 0x0be6, 0x0bf2,
+ 0x0c66, 0x0c6f,
+ 0x0c78, 0x0c7e,
+ 0x0ce6, 0x0cef,
+ 0x0d58, 0x0d5e,
+ 0x0d66, 0x0d78,
+ 0x0de6, 0x0def,
+ 0x0e50, 0x0e59,
+ 0x0ed0, 0x0ed9,
+ 0x0f20, 0x0f33,
+ 0x1040, 0x1049,
+ 0x1090, 0x1099,
+ 0x1369, 0x137c,
+ 0x16ee, 0x16f0,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x1810, 0x1819,
+ 0x1946, 0x194f,
+ 0x19d0, 0x19da,
+ 0x1a80, 0x1a89,
+ 0x1a90, 0x1a99,
+ 0x1b50, 0x1b59,
+ 0x1bb0, 0x1bb9,
+ 0x1c40, 0x1c49,
+ 0x1c50, 0x1c59,
+ 0x2070, 0x2070,
+ 0x2074, 0x2079,
+ 0x2080, 0x2089,
+ 0x2150, 0x2182,
+ 0x2185, 0x2189,
+ 0x2460, 0x249b,
+ 0x24ea, 0x24ff,
+ 0x2776, 0x2793,
+ 0x2cfd, 0x2cfd,
+ 0x3007, 0x3007,
+ 0x3021, 0x3029,
+ 0x3038, 0x303a,
+ 0x3192, 0x3195,
+ 0x3220, 0x3229,
+ 0x3248, 0x324f,
+ 0x3251, 0x325f,
+ 0x3280, 0x3289,
+ 0x32b1, 0x32bf,
+ 0xa620, 0xa629,
+ 0xa6e6, 0xa6ef,
+ 0xa830, 0xa835,
+ 0xa8d0, 0xa8d9,
+ 0xa900, 0xa909,
+ 0xa9d0, 0xa9d9,
+ 0xa9f0, 0xa9f9,
+ 0xaa50, 0xaa59,
+ 0xabf0, 0xabf9,
+ 0xff10, 0xff19,
+ 0x10107, 0x10133,
+ 0x10140, 0x10178,
+ 0x1018a, 0x1018b,
+ 0x102e1, 0x102fb,
+ 0x10320, 0x10323,
+ 0x10341, 0x10341,
+ 0x1034a, 0x1034a,
+ 0x103d1, 0x103d5,
+ 0x104a0, 0x104a9,
+ 0x10858, 0x1085f,
+ 0x10879, 0x1087f,
+ 0x108a7, 0x108af,
+ 0x108fb, 0x108ff,
+ 0x10916, 0x1091b,
+ 0x109bc, 0x109bd,
+ 0x109c0, 0x109cf,
+ 0x109d2, 0x109ff,
+ 0x10a40, 0x10a48,
+ 0x10a7d, 0x10a7e,
+ 0x10a9d, 0x10a9f,
+ 0x10aeb, 0x10aef,
+ 0x10b58, 0x10b5f,
+ 0x10b78, 0x10b7f,
+ 0x10ba9, 0x10baf,
+ 0x10cfa, 0x10cff,
+ 0x10d30, 0x10d39,
+ 0x10d40, 0x10d49,
+ 0x10e60, 0x10e7e,
+ 0x10f1d, 0x10f26,
+ 0x10f51, 0x10f54,
+ 0x10fc5, 0x10fcb,
+ 0x11052, 0x1106f,
+ 0x110f0, 0x110f9,
+ 0x11136, 0x1113f,
+ 0x111d0, 0x111d9,
+ 0x111e1, 0x111f4,
+ 0x112f0, 0x112f9,
+ 0x11450, 0x11459,
+ 0x114d0, 0x114d9,
+ 0x11650, 0x11659,
+ 0x116c0, 0x116c9,
+ 0x116d0, 0x116e3,
+ 0x11730, 0x1173b,
+ 0x118e0, 0x118f2,
+ 0x11950, 0x11959,
+ 0x11bf0, 0x11bf9,
+ 0x11c50, 0x11c6c,
+ 0x11d50, 0x11d59,
+ 0x11da0, 0x11da9,
+ 0x11de0, 0x11de9,
+ 0x11f50, 0x11f59,
+ 0x11fc0, 0x11fd4,
+ 0x12400, 0x1246e,
+ 0x16130, 0x16139,
+ 0x16a60, 0x16a69,
+ 0x16ac0, 0x16ac9,
+ 0x16b50, 0x16b59,
+ 0x16b5b, 0x16b61,
+ 0x16d70, 0x16d79,
+ 0x16e80, 0x16e96,
+ 0x16ff4, 0x16ff6,
+ 0x1ccf0, 0x1ccf9,
+ 0x1d2c0, 0x1d2d3,
+ 0x1d2e0, 0x1d2f3,
+ 0x1d360, 0x1d378,
+ 0x1d7ce, 0x1d7ff,
+ 0x1e140, 0x1e149,
+ 0x1e2f0, 0x1e2f9,
+ 0x1e4f0, 0x1e4f9,
+ 0x1e5f1, 0x1e5fa,
+ 0x1e8c7, 0x1e8cf,
+ 0x1e950, 0x1e959,
+ 0x1ec71, 0x1ecab,
+ 0x1ecad, 0x1ecaf,
+ 0x1ecb1, 0x1ecb4,
+ 0x1ed01, 0x1ed2d,
+ 0x1ed2f, 0x1ed3d,
+ 0x1f100, 0x1f10c,
+ 0x1fbf0, 0x1fbf9,
+}; /* CR_N */
+
+/* 'Nd': General Category */
+#define CR_Nd CR_Digit
+
+/* 'Nl': General Category */
+static const OnigCodePoint CR_Nl[] = {
+ 13,
+ 0x16ee, 0x16f0,
+ 0x2160, 0x2182,
+ 0x2185, 0x2188,
+ 0x3007, 0x3007,
+ 0x3021, 0x3029,
+ 0x3038, 0x303a,
+ 0xa6e6, 0xa6ef,
+ 0x10140, 0x10174,
+ 0x10341, 0x10341,
+ 0x1034a, 0x1034a,
+ 0x103d1, 0x103d5,
+ 0x12400, 0x1246e,
+ 0x16ff4, 0x16ff6,
+}; /* CR_Nl */
+
+/* 'No': General Category */
+static const OnigCodePoint CR_No[] = {
+ 72,
+ 0x00b2, 0x00b3,
+ 0x00b9, 0x00b9,
+ 0x00bc, 0x00be,
+ 0x09f4, 0x09f9,
+ 0x0b72, 0x0b77,
+ 0x0bf0, 0x0bf2,
+ 0x0c78, 0x0c7e,
+ 0x0d58, 0x0d5e,
+ 0x0d70, 0x0d78,
+ 0x0f2a, 0x0f33,
+ 0x1369, 0x137c,
+ 0x17f0, 0x17f9,
+ 0x19da, 0x19da,
+ 0x2070, 0x2070,
+ 0x2074, 0x2079,
+ 0x2080, 0x2089,
+ 0x2150, 0x215f,
+ 0x2189, 0x2189,
+ 0x2460, 0x249b,
+ 0x24ea, 0x24ff,
+ 0x2776, 0x2793,
+ 0x2cfd, 0x2cfd,
+ 0x3192, 0x3195,
+ 0x3220, 0x3229,
+ 0x3248, 0x324f,
+ 0x3251, 0x325f,
+ 0x3280, 0x3289,
+ 0x32b1, 0x32bf,
+ 0xa830, 0xa835,
+ 0x10107, 0x10133,
+ 0x10175, 0x10178,
+ 0x1018a, 0x1018b,
+ 0x102e1, 0x102fb,
+ 0x10320, 0x10323,
+ 0x10858, 0x1085f,
+ 0x10879, 0x1087f,
+ 0x108a7, 0x108af,
+ 0x108fb, 0x108ff,
+ 0x10916, 0x1091b,
+ 0x109bc, 0x109bd,
+ 0x109c0, 0x109cf,
+ 0x109d2, 0x109ff,
+ 0x10a40, 0x10a48,
+ 0x10a7d, 0x10a7e,
+ 0x10a9d, 0x10a9f,
+ 0x10aeb, 0x10aef,
+ 0x10b58, 0x10b5f,
+ 0x10b78, 0x10b7f,
+ 0x10ba9, 0x10baf,
+ 0x10cfa, 0x10cff,
+ 0x10e60, 0x10e7e,
+ 0x10f1d, 0x10f26,
+ 0x10f51, 0x10f54,
+ 0x10fc5, 0x10fcb,
+ 0x11052, 0x11065,
+ 0x111e1, 0x111f4,
+ 0x1173a, 0x1173b,
+ 0x118ea, 0x118f2,
+ 0x11c5a, 0x11c6c,
+ 0x11fc0, 0x11fd4,
+ 0x16b5b, 0x16b61,
+ 0x16e80, 0x16e96,
+ 0x1d2c0, 0x1d2d3,
+ 0x1d2e0, 0x1d2f3,
+ 0x1d360, 0x1d378,
+ 0x1e8c7, 0x1e8cf,
+ 0x1ec71, 0x1ecab,
+ 0x1ecad, 0x1ecaf,
+ 0x1ecb1, 0x1ecb4,
+ 0x1ed01, 0x1ed2d,
+ 0x1ed2f, 0x1ed3d,
+ 0x1f100, 0x1f10c,
+}; /* CR_No */
+
+/* 'P': Major Category */
+#define CR_P CR_Punct
+
+/* 'Pc': General Category */
+static const OnigCodePoint CR_Pc[] = {
+ 6,
+ 0x005f, 0x005f,
+ 0x203f, 0x2040,
+ 0x2054, 0x2054,
+ 0xfe33, 0xfe34,
+ 0xfe4d, 0xfe4f,
+ 0xff3f, 0xff3f,
+}; /* CR_Pc */
+
+/* 'Pd': General Category */
+static const OnigCodePoint CR_Pd[] = {
+ 20,
+ 0x002d, 0x002d,
+ 0x058a, 0x058a,
+ 0x05be, 0x05be,
+ 0x1400, 0x1400,
+ 0x1806, 0x1806,
+ 0x2010, 0x2015,
+ 0x2e17, 0x2e17,
+ 0x2e1a, 0x2e1a,
+ 0x2e3a, 0x2e3b,
+ 0x2e40, 0x2e40,
+ 0x2e5d, 0x2e5d,
+ 0x301c, 0x301c,
+ 0x3030, 0x3030,
+ 0x30a0, 0x30a0,
+ 0xfe31, 0xfe32,
+ 0xfe58, 0xfe58,
+ 0xfe63, 0xfe63,
+ 0xff0d, 0xff0d,
+ 0x10d6e, 0x10d6e,
+ 0x10ead, 0x10ead,
+}; /* CR_Pd */
+
+/* 'Pe': General Category */
+static const OnigCodePoint CR_Pe[] = {
+ 76,
+ 0x0029, 0x0029,
+ 0x005d, 0x005d,
+ 0x007d, 0x007d,
+ 0x0f3b, 0x0f3b,
+ 0x0f3d, 0x0f3d,
+ 0x169c, 0x169c,
+ 0x2046, 0x2046,
+ 0x207e, 0x207e,
+ 0x208e, 0x208e,
+ 0x2309, 0x2309,
+ 0x230b, 0x230b,
+ 0x232a, 0x232a,
+ 0x2769, 0x2769,
+ 0x276b, 0x276b,
+ 0x276d, 0x276d,
+ 0x276f, 0x276f,
+ 0x2771, 0x2771,
+ 0x2773, 0x2773,
+ 0x2775, 0x2775,
+ 0x27c6, 0x27c6,
+ 0x27e7, 0x27e7,
+ 0x27e9, 0x27e9,
+ 0x27eb, 0x27eb,
+ 0x27ed, 0x27ed,
+ 0x27ef, 0x27ef,
+ 0x2984, 0x2984,
+ 0x2986, 0x2986,
+ 0x2988, 0x2988,
+ 0x298a, 0x298a,
+ 0x298c, 0x298c,
+ 0x298e, 0x298e,
+ 0x2990, 0x2990,
+ 0x2992, 0x2992,
+ 0x2994, 0x2994,
+ 0x2996, 0x2996,
+ 0x2998, 0x2998,
+ 0x29d9, 0x29d9,
+ 0x29db, 0x29db,
+ 0x29fd, 0x29fd,
+ 0x2e23, 0x2e23,
+ 0x2e25, 0x2e25,
+ 0x2e27, 0x2e27,
+ 0x2e29, 0x2e29,
+ 0x2e56, 0x2e56,
+ 0x2e58, 0x2e58,
+ 0x2e5a, 0x2e5a,
+ 0x2e5c, 0x2e5c,
+ 0x3009, 0x3009,
+ 0x300b, 0x300b,
+ 0x300d, 0x300d,
+ 0x300f, 0x300f,
+ 0x3011, 0x3011,
+ 0x3015, 0x3015,
+ 0x3017, 0x3017,
+ 0x3019, 0x3019,
+ 0x301b, 0x301b,
+ 0x301e, 0x301f,
+ 0xfd3e, 0xfd3e,
+ 0xfe18, 0xfe18,
+ 0xfe36, 0xfe36,
+ 0xfe38, 0xfe38,
+ 0xfe3a, 0xfe3a,
+ 0xfe3c, 0xfe3c,
+ 0xfe3e, 0xfe3e,
+ 0xfe40, 0xfe40,
+ 0xfe42, 0xfe42,
+ 0xfe44, 0xfe44,
+ 0xfe48, 0xfe48,
+ 0xfe5a, 0xfe5a,
+ 0xfe5c, 0xfe5c,
+ 0xfe5e, 0xfe5e,
+ 0xff09, 0xff09,
+ 0xff3d, 0xff3d,
+ 0xff5d, 0xff5d,
+ 0xff60, 0xff60,
+ 0xff63, 0xff63,
+}; /* CR_Pe */
+
+/* 'Pf': General Category */
+static const OnigCodePoint CR_Pf[] = {
+ 10,
+ 0x00bb, 0x00bb,
+ 0x2019, 0x2019,
+ 0x201d, 0x201d,
+ 0x203a, 0x203a,
+ 0x2e03, 0x2e03,
+ 0x2e05, 0x2e05,
+ 0x2e0a, 0x2e0a,
+ 0x2e0d, 0x2e0d,
+ 0x2e1d, 0x2e1d,
+ 0x2e21, 0x2e21,
+}; /* CR_Pf */
+
+/* 'Pi': General Category */
+static const OnigCodePoint CR_Pi[] = {
+ 11,
+ 0x00ab, 0x00ab,
+ 0x2018, 0x2018,
+ 0x201b, 0x201c,
+ 0x201f, 0x201f,
+ 0x2039, 0x2039,
+ 0x2e02, 0x2e02,
+ 0x2e04, 0x2e04,
+ 0x2e09, 0x2e09,
+ 0x2e0c, 0x2e0c,
+ 0x2e1c, 0x2e1c,
+ 0x2e20, 0x2e20,
+}; /* CR_Pi */
+
+/* 'Po': General Category */
+static const OnigCodePoint CR_Po[] = {
+ 194,
+ 0x0021, 0x0023,
+ 0x0025, 0x0027,
+ 0x002a, 0x002a,
+ 0x002c, 0x002c,
+ 0x002e, 0x002f,
+ 0x003a, 0x003b,
+ 0x003f, 0x0040,
+ 0x005c, 0x005c,
+ 0x00a1, 0x00a1,
+ 0x00a7, 0x00a7,
+ 0x00b6, 0x00b7,
+ 0x00bf, 0x00bf,
+ 0x037e, 0x037e,
+ 0x0387, 0x0387,
+ 0x055a, 0x055f,
+ 0x0589, 0x0589,
+ 0x05c0, 0x05c0,
+ 0x05c3, 0x05c3,
+ 0x05c6, 0x05c6,
+ 0x05f3, 0x05f4,
+ 0x0609, 0x060a,
+ 0x060c, 0x060d,
+ 0x061b, 0x061b,
+ 0x061d, 0x061f,
+ 0x066a, 0x066d,
+ 0x06d4, 0x06d4,
+ 0x0700, 0x070d,
+ 0x07f7, 0x07f9,
+ 0x0830, 0x083e,
+ 0x085e, 0x085e,
+ 0x0964, 0x0965,
+ 0x0970, 0x0970,
+ 0x09fd, 0x09fd,
+ 0x0a76, 0x0a76,
+ 0x0af0, 0x0af0,
+ 0x0c77, 0x0c77,
+ 0x0c84, 0x0c84,
+ 0x0df4, 0x0df4,
+ 0x0e4f, 0x0e4f,
+ 0x0e5a, 0x0e5b,
+ 0x0f04, 0x0f12,
+ 0x0f14, 0x0f14,
+ 0x0f85, 0x0f85,
+ 0x0fd0, 0x0fd4,
+ 0x0fd9, 0x0fda,
+ 0x104a, 0x104f,
+ 0x10fb, 0x10fb,
+ 0x1360, 0x1368,
+ 0x166e, 0x166e,
+ 0x16eb, 0x16ed,
+ 0x1735, 0x1736,
+ 0x17d4, 0x17d6,
+ 0x17d8, 0x17da,
+ 0x1800, 0x1805,
+ 0x1807, 0x180a,
+ 0x1944, 0x1945,
+ 0x1a1e, 0x1a1f,
+ 0x1aa0, 0x1aa6,
+ 0x1aa8, 0x1aad,
+ 0x1b4e, 0x1b4f,
+ 0x1b5a, 0x1b60,
+ 0x1b7d, 0x1b7f,
+ 0x1bfc, 0x1bff,
+ 0x1c3b, 0x1c3f,
+ 0x1c7e, 0x1c7f,
+ 0x1cc0, 0x1cc7,
+ 0x1cd3, 0x1cd3,
+ 0x2016, 0x2017,
+ 0x2020, 0x2027,
+ 0x2030, 0x2038,
+ 0x203b, 0x203e,
+ 0x2041, 0x2043,
+ 0x2047, 0x2051,
+ 0x2053, 0x2053,
+ 0x2055, 0x205e,
+ 0x2cf9, 0x2cfc,
+ 0x2cfe, 0x2cff,
+ 0x2d70, 0x2d70,
+ 0x2e00, 0x2e01,
+ 0x2e06, 0x2e08,
+ 0x2e0b, 0x2e0b,
+ 0x2e0e, 0x2e16,
+ 0x2e18, 0x2e19,
+ 0x2e1b, 0x2e1b,
+ 0x2e1e, 0x2e1f,
+ 0x2e2a, 0x2e2e,
+ 0x2e30, 0x2e39,
+ 0x2e3c, 0x2e3f,
+ 0x2e41, 0x2e41,
+ 0x2e43, 0x2e4f,
+ 0x2e52, 0x2e54,
+ 0x3001, 0x3003,
+ 0x303d, 0x303d,
+ 0x30fb, 0x30fb,
+ 0xa4fe, 0xa4ff,
+ 0xa60d, 0xa60f,
+ 0xa673, 0xa673,
+ 0xa67e, 0xa67e,
+ 0xa6f2, 0xa6f7,
+ 0xa874, 0xa877,
+ 0xa8ce, 0xa8cf,
+ 0xa8f8, 0xa8fa,
+ 0xa8fc, 0xa8fc,
+ 0xa92e, 0xa92f,
+ 0xa95f, 0xa95f,
+ 0xa9c1, 0xa9cd,
+ 0xa9de, 0xa9df,
+ 0xaa5c, 0xaa5f,
+ 0xaade, 0xaadf,
+ 0xaaf0, 0xaaf1,
+ 0xabeb, 0xabeb,
+ 0xfe10, 0xfe16,
+ 0xfe19, 0xfe19,
+ 0xfe30, 0xfe30,
+ 0xfe45, 0xfe46,
+ 0xfe49, 0xfe4c,
+ 0xfe50, 0xfe52,
+ 0xfe54, 0xfe57,
+ 0xfe5f, 0xfe61,
+ 0xfe68, 0xfe68,
+ 0xfe6a, 0xfe6b,
+ 0xff01, 0xff03,
+ 0xff05, 0xff07,
+ 0xff0a, 0xff0a,
+ 0xff0c, 0xff0c,
+ 0xff0e, 0xff0f,
+ 0xff1a, 0xff1b,
+ 0xff1f, 0xff20,
+ 0xff3c, 0xff3c,
+ 0xff61, 0xff61,
+ 0xff64, 0xff65,
+ 0x10100, 0x10102,
+ 0x1039f, 0x1039f,
+ 0x103d0, 0x103d0,
+ 0x1056f, 0x1056f,
+ 0x10857, 0x10857,
+ 0x1091f, 0x1091f,
+ 0x1093f, 0x1093f,
+ 0x10a50, 0x10a58,
+ 0x10a7f, 0x10a7f,
+ 0x10af0, 0x10af6,
+ 0x10b39, 0x10b3f,
+ 0x10b99, 0x10b9c,
+ 0x10ed0, 0x10ed0,
+ 0x10f55, 0x10f59,
+ 0x10f86, 0x10f89,
+ 0x11047, 0x1104d,
+ 0x110bb, 0x110bc,
+ 0x110be, 0x110c1,
+ 0x11140, 0x11143,
+ 0x11174, 0x11175,
+ 0x111c5, 0x111c8,
+ 0x111cd, 0x111cd,
+ 0x111db, 0x111db,
+ 0x111dd, 0x111df,
+ 0x11238, 0x1123d,
+ 0x112a9, 0x112a9,
+ 0x113d4, 0x113d5,
+ 0x113d7, 0x113d8,
+ 0x1144b, 0x1144f,
+ 0x1145a, 0x1145b,
+ 0x1145d, 0x1145d,
+ 0x114c6, 0x114c6,
+ 0x115c1, 0x115d7,
+ 0x11641, 0x11643,
+ 0x11660, 0x1166c,
+ 0x116b9, 0x116b9,
+ 0x1173c, 0x1173e,
+ 0x1183b, 0x1183b,
+ 0x11944, 0x11946,
+ 0x119e2, 0x119e2,
+ 0x11a3f, 0x11a46,
+ 0x11a9a, 0x11a9c,
+ 0x11a9e, 0x11aa2,
+ 0x11b00, 0x11b09,
+ 0x11be1, 0x11be1,
+ 0x11c41, 0x11c45,
+ 0x11c70, 0x11c71,
+ 0x11ef7, 0x11ef8,
+ 0x11f43, 0x11f4f,
+ 0x11fff, 0x11fff,
+ 0x12470, 0x12474,
+ 0x12ff1, 0x12ff2,
+ 0x16a6e, 0x16a6f,
+ 0x16af5, 0x16af5,
+ 0x16b37, 0x16b3b,
+ 0x16b44, 0x16b44,
+ 0x16d6d, 0x16d6f,
+ 0x16e97, 0x16e9a,
+ 0x16fe2, 0x16fe2,
+ 0x1bc9f, 0x1bc9f,
+ 0x1da87, 0x1da8b,
+ 0x1e5ff, 0x1e5ff,
+ 0x1e95e, 0x1e95f,
+}; /* CR_Po */
+
+/* 'Ps': General Category */
+static const OnigCodePoint CR_Ps[] = {
+ 79,
+ 0x0028, 0x0028,
+ 0x005b, 0x005b,
+ 0x007b, 0x007b,
+ 0x0f3a, 0x0f3a,
+ 0x0f3c, 0x0f3c,
+ 0x169b, 0x169b,
+ 0x201a, 0x201a,
+ 0x201e, 0x201e,
+ 0x2045, 0x2045,
+ 0x207d, 0x207d,
+ 0x208d, 0x208d,
+ 0x2308, 0x2308,
+ 0x230a, 0x230a,
+ 0x2329, 0x2329,
+ 0x2768, 0x2768,
+ 0x276a, 0x276a,
+ 0x276c, 0x276c,
+ 0x276e, 0x276e,
+ 0x2770, 0x2770,
+ 0x2772, 0x2772,
+ 0x2774, 0x2774,
+ 0x27c5, 0x27c5,
+ 0x27e6, 0x27e6,
+ 0x27e8, 0x27e8,
+ 0x27ea, 0x27ea,
+ 0x27ec, 0x27ec,
+ 0x27ee, 0x27ee,
+ 0x2983, 0x2983,
+ 0x2985, 0x2985,
+ 0x2987, 0x2987,
+ 0x2989, 0x2989,
+ 0x298b, 0x298b,
+ 0x298d, 0x298d,
+ 0x298f, 0x298f,
+ 0x2991, 0x2991,
+ 0x2993, 0x2993,
+ 0x2995, 0x2995,
+ 0x2997, 0x2997,
+ 0x29d8, 0x29d8,
+ 0x29da, 0x29da,
+ 0x29fc, 0x29fc,
+ 0x2e22, 0x2e22,
+ 0x2e24, 0x2e24,
+ 0x2e26, 0x2e26,
+ 0x2e28, 0x2e28,
+ 0x2e42, 0x2e42,
+ 0x2e55, 0x2e55,
+ 0x2e57, 0x2e57,
+ 0x2e59, 0x2e59,
+ 0x2e5b, 0x2e5b,
+ 0x3008, 0x3008,
+ 0x300a, 0x300a,
+ 0x300c, 0x300c,
+ 0x300e, 0x300e,
+ 0x3010, 0x3010,
+ 0x3014, 0x3014,
+ 0x3016, 0x3016,
+ 0x3018, 0x3018,
+ 0x301a, 0x301a,
+ 0x301d, 0x301d,
+ 0xfd3f, 0xfd3f,
+ 0xfe17, 0xfe17,
+ 0xfe35, 0xfe35,
+ 0xfe37, 0xfe37,
+ 0xfe39, 0xfe39,
+ 0xfe3b, 0xfe3b,
+ 0xfe3d, 0xfe3d,
+ 0xfe3f, 0xfe3f,
+ 0xfe41, 0xfe41,
+ 0xfe43, 0xfe43,
+ 0xfe47, 0xfe47,
+ 0xfe59, 0xfe59,
+ 0xfe5b, 0xfe5b,
+ 0xfe5d, 0xfe5d,
+ 0xff08, 0xff08,
+ 0xff3b, 0xff3b,
+ 0xff5b, 0xff5b,
+ 0xff5f, 0xff5f,
+ 0xff62, 0xff62,
+}; /* CR_Ps */
+
+/* 'S': Major Category */
+static const OnigCodePoint CR_S[] = {
+ 242,
+ 0x0024, 0x0024,
+ 0x002b, 0x002b,
+ 0x003c, 0x003e,
+ 0x005e, 0x005e,
+ 0x0060, 0x0060,
+ 0x007c, 0x007c,
+ 0x007e, 0x007e,
+ 0x00a2, 0x00a6,
+ 0x00a8, 0x00a9,
+ 0x00ac, 0x00ac,
+ 0x00ae, 0x00b1,
+ 0x00b4, 0x00b4,
+ 0x00b8, 0x00b8,
+ 0x00d7, 0x00d7,
+ 0x00f7, 0x00f7,
+ 0x02c2, 0x02c5,
+ 0x02d2, 0x02df,
+ 0x02e5, 0x02eb,
+ 0x02ed, 0x02ed,
+ 0x02ef, 0x02ff,
+ 0x0375, 0x0375,
+ 0x0384, 0x0385,
+ 0x03f6, 0x03f6,
+ 0x0482, 0x0482,
+ 0x058d, 0x058f,
+ 0x0606, 0x0608,
+ 0x060b, 0x060b,
+ 0x060e, 0x060f,
+ 0x06de, 0x06de,
+ 0x06e9, 0x06e9,
+ 0x06fd, 0x06fe,
+ 0x07f6, 0x07f6,
+ 0x07fe, 0x07ff,
+ 0x0888, 0x0888,
+ 0x09f2, 0x09f3,
+ 0x09fa, 0x09fb,
+ 0x0af1, 0x0af1,
+ 0x0b70, 0x0b70,
+ 0x0bf3, 0x0bfa,
+ 0x0c7f, 0x0c7f,
+ 0x0d4f, 0x0d4f,
+ 0x0d79, 0x0d79,
+ 0x0e3f, 0x0e3f,
+ 0x0f01, 0x0f03,
+ 0x0f13, 0x0f13,
+ 0x0f15, 0x0f17,
+ 0x0f1a, 0x0f1f,
+ 0x0f34, 0x0f34,
+ 0x0f36, 0x0f36,
+ 0x0f38, 0x0f38,
+ 0x0fbe, 0x0fc5,
+ 0x0fc7, 0x0fcc,
+ 0x0fce, 0x0fcf,
+ 0x0fd5, 0x0fd8,
+ 0x109e, 0x109f,
+ 0x1390, 0x1399,
+ 0x166d, 0x166d,
+ 0x17db, 0x17db,
+ 0x1940, 0x1940,
+ 0x19de, 0x19ff,
+ 0x1b61, 0x1b6a,
+ 0x1b74, 0x1b7c,
+ 0x1fbd, 0x1fbd,
+ 0x1fbf, 0x1fc1,
+ 0x1fcd, 0x1fcf,
+ 0x1fdd, 0x1fdf,
+ 0x1fed, 0x1fef,
+ 0x1ffd, 0x1ffe,
+ 0x2044, 0x2044,
+ 0x2052, 0x2052,
+ 0x207a, 0x207c,
+ 0x208a, 0x208c,
+ 0x20a0, 0x20c1,
+ 0x2100, 0x2101,
+ 0x2103, 0x2106,
+ 0x2108, 0x2109,
+ 0x2114, 0x2114,
+ 0x2116, 0x2118,
+ 0x211e, 0x2123,
+ 0x2125, 0x2125,
+ 0x2127, 0x2127,
+ 0x2129, 0x2129,
+ 0x212e, 0x212e,
+ 0x213a, 0x213b,
+ 0x2140, 0x2144,
+ 0x214a, 0x214d,
+ 0x214f, 0x214f,
+ 0x218a, 0x218b,
+ 0x2190, 0x2307,
+ 0x230c, 0x2328,
+ 0x232b, 0x2429,
+ 0x2440, 0x244a,
+ 0x249c, 0x24e9,
+ 0x2500, 0x2767,
+ 0x2794, 0x27c4,
+ 0x27c7, 0x27e5,
+ 0x27f0, 0x2982,
+ 0x2999, 0x29d7,
+ 0x29dc, 0x29fb,
+ 0x29fe, 0x2b73,
+ 0x2b76, 0x2bff,
+ 0x2ce5, 0x2cea,
+ 0x2e50, 0x2e51,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2fff,
+ 0x3004, 0x3004,
+ 0x3012, 0x3013,
+ 0x3020, 0x3020,
+ 0x3036, 0x3037,
+ 0x303e, 0x303f,
+ 0x309b, 0x309c,
+ 0x3190, 0x3191,
+ 0x3196, 0x319f,
+ 0x31c0, 0x31e5,
+ 0x31ef, 0x31ef,
+ 0x3200, 0x321e,
+ 0x322a, 0x3247,
+ 0x3250, 0x3250,
+ 0x3260, 0x327f,
+ 0x328a, 0x32b0,
+ 0x32c0, 0x33ff,
+ 0x4dc0, 0x4dff,
+ 0xa490, 0xa4c6,
+ 0xa700, 0xa716,
+ 0xa720, 0xa721,
+ 0xa789, 0xa78a,
+ 0xa828, 0xa82b,
+ 0xa836, 0xa839,
+ 0xaa77, 0xaa79,
+ 0xab5b, 0xab5b,
+ 0xab6a, 0xab6b,
+ 0xfb29, 0xfb29,
+ 0xfbb2, 0xfbd2,
+ 0xfd40, 0xfd4f,
+ 0xfd90, 0xfd91,
+ 0xfdc8, 0xfdcf,
+ 0xfdfc, 0xfdff,
+ 0xfe62, 0xfe62,
+ 0xfe64, 0xfe66,
+ 0xfe69, 0xfe69,
+ 0xff04, 0xff04,
+ 0xff0b, 0xff0b,
+ 0xff1c, 0xff1e,
+ 0xff3e, 0xff3e,
+ 0xff40, 0xff40,
+ 0xff5c, 0xff5c,
+ 0xff5e, 0xff5e,
+ 0xffe0, 0xffe6,
+ 0xffe8, 0xffee,
+ 0xfffc, 0xfffd,
+ 0x10137, 0x1013f,
+ 0x10179, 0x10189,
+ 0x1018c, 0x1018e,
+ 0x10190, 0x1019c,
+ 0x101a0, 0x101a0,
+ 0x101d0, 0x101fc,
+ 0x10877, 0x10878,
+ 0x10ac8, 0x10ac8,
+ 0x10d8e, 0x10d8f,
+ 0x10ed1, 0x10ed8,
+ 0x1173f, 0x1173f,
+ 0x11fd5, 0x11ff1,
+ 0x16b3c, 0x16b3f,
+ 0x16b45, 0x16b45,
+ 0x1bc9c, 0x1bc9c,
+ 0x1cc00, 0x1ccef,
+ 0x1ccfa, 0x1ccfc,
+ 0x1cd00, 0x1ceb3,
+ 0x1ceba, 0x1ced0,
+ 0x1cee0, 0x1cef0,
+ 0x1cf50, 0x1cfc3,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d129, 0x1d164,
+ 0x1d16a, 0x1d16c,
+ 0x1d183, 0x1d184,
+ 0x1d18c, 0x1d1a9,
+ 0x1d1ae, 0x1d1ea,
+ 0x1d200, 0x1d241,
+ 0x1d245, 0x1d245,
+ 0x1d300, 0x1d356,
+ 0x1d6c1, 0x1d6c1,
+ 0x1d6db, 0x1d6db,
+ 0x1d6fb, 0x1d6fb,
+ 0x1d715, 0x1d715,
+ 0x1d735, 0x1d735,
+ 0x1d74f, 0x1d74f,
+ 0x1d76f, 0x1d76f,
+ 0x1d789, 0x1d789,
+ 0x1d7a9, 0x1d7a9,
+ 0x1d7c3, 0x1d7c3,
+ 0x1d800, 0x1d9ff,
+ 0x1da37, 0x1da3a,
+ 0x1da6d, 0x1da74,
+ 0x1da76, 0x1da83,
+ 0x1da85, 0x1da86,
+ 0x1e14f, 0x1e14f,
+ 0x1e2ff, 0x1e2ff,
+ 0x1ecac, 0x1ecac,
+ 0x1ecb0, 0x1ecb0,
+ 0x1ed2e, 0x1ed2e,
+ 0x1eef0, 0x1eef1,
+ 0x1f000, 0x1f02b,
+ 0x1f030, 0x1f093,
+ 0x1f0a0, 0x1f0ae,
+ 0x1f0b1, 0x1f0bf,
+ 0x1f0c1, 0x1f0cf,
+ 0x1f0d1, 0x1f0f5,
+ 0x1f10d, 0x1f1ad,
+ 0x1f1e6, 0x1f202,
+ 0x1f210, 0x1f23b,
+ 0x1f240, 0x1f248,
+ 0x1f250, 0x1f251,
+ 0x1f260, 0x1f265,
+ 0x1f300, 0x1f6d8,
+ 0x1f6dc, 0x1f6ec,
+ 0x1f6f0, 0x1f6fc,
+ 0x1f700, 0x1f7d9,
+ 0x1f7e0, 0x1f7eb,
+ 0x1f7f0, 0x1f7f0,
+ 0x1f800, 0x1f80b,
+ 0x1f810, 0x1f847,
+ 0x1f850, 0x1f859,
+ 0x1f860, 0x1f887,
+ 0x1f890, 0x1f8ad,
+ 0x1f8b0, 0x1f8bb,
+ 0x1f8c0, 0x1f8c1,
+ 0x1f8d0, 0x1f8d8,
+ 0x1f900, 0x1fa57,
+ 0x1fa60, 0x1fa6d,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa8a,
+ 0x1fa8e, 0x1fac6,
+ 0x1fac8, 0x1fac8,
+ 0x1facd, 0x1fadc,
+ 0x1fadf, 0x1faea,
+ 0x1faef, 0x1faf8,
+ 0x1fb00, 0x1fb92,
+ 0x1fb94, 0x1fbef,
+ 0x1fbfa, 0x1fbfa,
+}; /* CR_S */
+
+/* 'Sc': General Category */
+static const OnigCodePoint CR_Sc[] = {
+ 21,
+ 0x0024, 0x0024,
+ 0x00a2, 0x00a5,
+ 0x058f, 0x058f,
+ 0x060b, 0x060b,
+ 0x07fe, 0x07ff,
+ 0x09f2, 0x09f3,
+ 0x09fb, 0x09fb,
+ 0x0af1, 0x0af1,
+ 0x0bf9, 0x0bf9,
+ 0x0e3f, 0x0e3f,
+ 0x17db, 0x17db,
+ 0x20a0, 0x20c1,
+ 0xa838, 0xa838,
+ 0xfdfc, 0xfdfc,
+ 0xfe69, 0xfe69,
+ 0xff04, 0xff04,
+ 0xffe0, 0xffe1,
+ 0xffe5, 0xffe6,
+ 0x11fdd, 0x11fe0,
+ 0x1e2ff, 0x1e2ff,
+ 0x1ecb0, 0x1ecb0,
+}; /* CR_Sc */
+
+/* 'Sk': General Category */
+static const OnigCodePoint CR_Sk[] = {
+ 31,
+ 0x005e, 0x005e,
+ 0x0060, 0x0060,
+ 0x00a8, 0x00a8,
+ 0x00af, 0x00af,
+ 0x00b4, 0x00b4,
+ 0x00b8, 0x00b8,
+ 0x02c2, 0x02c5,
+ 0x02d2, 0x02df,
+ 0x02e5, 0x02eb,
+ 0x02ed, 0x02ed,
+ 0x02ef, 0x02ff,
+ 0x0375, 0x0375,
+ 0x0384, 0x0385,
+ 0x0888, 0x0888,
+ 0x1fbd, 0x1fbd,
+ 0x1fbf, 0x1fc1,
+ 0x1fcd, 0x1fcf,
+ 0x1fdd, 0x1fdf,
+ 0x1fed, 0x1fef,
+ 0x1ffd, 0x1ffe,
+ 0x309b, 0x309c,
+ 0xa700, 0xa716,
+ 0xa720, 0xa721,
+ 0xa789, 0xa78a,
+ 0xab5b, 0xab5b,
+ 0xab6a, 0xab6b,
+ 0xfbb2, 0xfbc2,
+ 0xff3e, 0xff3e,
+ 0xff40, 0xff40,
+ 0xffe3, 0xffe3,
+ 0x1f3fb, 0x1f3ff,
+}; /* CR_Sk */
+
+/* 'Sm': General Category */
+static const OnigCodePoint CR_Sm[] = {
+ 67,
+ 0x002b, 0x002b,
+ 0x003c, 0x003e,
+ 0x007c, 0x007c,
+ 0x007e, 0x007e,
+ 0x00ac, 0x00ac,
+ 0x00b1, 0x00b1,
+ 0x00d7, 0x00d7,
+ 0x00f7, 0x00f7,
+ 0x03f6, 0x03f6,
+ 0x0606, 0x0608,
+ 0x2044, 0x2044,
+ 0x2052, 0x2052,
+ 0x207a, 0x207c,
+ 0x208a, 0x208c,
+ 0x2118, 0x2118,
+ 0x2140, 0x2144,
+ 0x214b, 0x214b,
+ 0x2190, 0x2194,
+ 0x219a, 0x219b,
+ 0x21a0, 0x21a0,
+ 0x21a3, 0x21a3,
+ 0x21a6, 0x21a6,
+ 0x21ae, 0x21ae,
+ 0x21ce, 0x21cf,
+ 0x21d2, 0x21d2,
+ 0x21d4, 0x21d4,
+ 0x21f4, 0x22ff,
+ 0x2320, 0x2321,
+ 0x237c, 0x237c,
+ 0x239b, 0x23b3,
+ 0x23dc, 0x23e1,
+ 0x25b7, 0x25b7,
+ 0x25c1, 0x25c1,
+ 0x25f8, 0x25ff,
+ 0x266f, 0x266f,
+ 0x27c0, 0x27c4,
+ 0x27c7, 0x27e5,
+ 0x27f0, 0x27ff,
+ 0x2900, 0x2982,
+ 0x2999, 0x29d7,
+ 0x29dc, 0x29fb,
+ 0x29fe, 0x2aff,
+ 0x2b30, 0x2b44,
+ 0x2b47, 0x2b4c,
+ 0xfb29, 0xfb29,
+ 0xfe62, 0xfe62,
+ 0xfe64, 0xfe66,
+ 0xff0b, 0xff0b,
+ 0xff1c, 0xff1e,
+ 0xff5c, 0xff5c,
+ 0xff5e, 0xff5e,
+ 0xffe2, 0xffe2,
+ 0xffe9, 0xffec,
+ 0x10d8e, 0x10d8f,
+ 0x1cef0, 0x1cef0,
+ 0x1d6c1, 0x1d6c1,
+ 0x1d6db, 0x1d6db,
+ 0x1d6fb, 0x1d6fb,
+ 0x1d715, 0x1d715,
+ 0x1d735, 0x1d735,
+ 0x1d74f, 0x1d74f,
+ 0x1d76f, 0x1d76f,
+ 0x1d789, 0x1d789,
+ 0x1d7a9, 0x1d7a9,
+ 0x1d7c3, 0x1d7c3,
+ 0x1eef0, 0x1eef1,
+ 0x1f8d0, 0x1f8d8,
+}; /* CR_Sm */
+
+/* 'So': General Category */
+static const OnigCodePoint CR_So[] = {
+ 193,
+ 0x00a6, 0x00a6,
+ 0x00a9, 0x00a9,
+ 0x00ae, 0x00ae,
+ 0x00b0, 0x00b0,
+ 0x0482, 0x0482,
+ 0x058d, 0x058e,
+ 0x060e, 0x060f,
+ 0x06de, 0x06de,
+ 0x06e9, 0x06e9,
+ 0x06fd, 0x06fe,
+ 0x07f6, 0x07f6,
+ 0x09fa, 0x09fa,
+ 0x0b70, 0x0b70,
+ 0x0bf3, 0x0bf8,
+ 0x0bfa, 0x0bfa,
+ 0x0c7f, 0x0c7f,
+ 0x0d4f, 0x0d4f,
+ 0x0d79, 0x0d79,
+ 0x0f01, 0x0f03,
+ 0x0f13, 0x0f13,
+ 0x0f15, 0x0f17,
+ 0x0f1a, 0x0f1f,
+ 0x0f34, 0x0f34,
+ 0x0f36, 0x0f36,
+ 0x0f38, 0x0f38,
+ 0x0fbe, 0x0fc5,
+ 0x0fc7, 0x0fcc,
+ 0x0fce, 0x0fcf,
+ 0x0fd5, 0x0fd8,
+ 0x109e, 0x109f,
+ 0x1390, 0x1399,
+ 0x166d, 0x166d,
+ 0x1940, 0x1940,
+ 0x19de, 0x19ff,
+ 0x1b61, 0x1b6a,
+ 0x1b74, 0x1b7c,
+ 0x2100, 0x2101,
+ 0x2103, 0x2106,
+ 0x2108, 0x2109,
+ 0x2114, 0x2114,
+ 0x2116, 0x2117,
+ 0x211e, 0x2123,
+ 0x2125, 0x2125,
+ 0x2127, 0x2127,
+ 0x2129, 0x2129,
+ 0x212e, 0x212e,
+ 0x213a, 0x213b,
+ 0x214a, 0x214a,
+ 0x214c, 0x214d,
+ 0x214f, 0x214f,
+ 0x218a, 0x218b,
+ 0x2195, 0x2199,
+ 0x219c, 0x219f,
+ 0x21a1, 0x21a2,
+ 0x21a4, 0x21a5,
+ 0x21a7, 0x21ad,
+ 0x21af, 0x21cd,
+ 0x21d0, 0x21d1,
+ 0x21d3, 0x21d3,
+ 0x21d5, 0x21f3,
+ 0x2300, 0x2307,
+ 0x230c, 0x231f,
+ 0x2322, 0x2328,
+ 0x232b, 0x237b,
+ 0x237d, 0x239a,
+ 0x23b4, 0x23db,
+ 0x23e2, 0x2429,
+ 0x2440, 0x244a,
+ 0x249c, 0x24e9,
+ 0x2500, 0x25b6,
+ 0x25b8, 0x25c0,
+ 0x25c2, 0x25f7,
+ 0x2600, 0x266e,
+ 0x2670, 0x2767,
+ 0x2794, 0x27bf,
+ 0x2800, 0x28ff,
+ 0x2b00, 0x2b2f,
+ 0x2b45, 0x2b46,
+ 0x2b4d, 0x2b73,
+ 0x2b76, 0x2bff,
+ 0x2ce5, 0x2cea,
+ 0x2e50, 0x2e51,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2fff,
+ 0x3004, 0x3004,
+ 0x3012, 0x3013,
+ 0x3020, 0x3020,
+ 0x3036, 0x3037,
+ 0x303e, 0x303f,
+ 0x3190, 0x3191,
+ 0x3196, 0x319f,
+ 0x31c0, 0x31e5,
+ 0x31ef, 0x31ef,
+ 0x3200, 0x321e,
+ 0x322a, 0x3247,
+ 0x3250, 0x3250,
+ 0x3260, 0x327f,
+ 0x328a, 0x32b0,
+ 0x32c0, 0x33ff,
+ 0x4dc0, 0x4dff,
+ 0xa490, 0xa4c6,
+ 0xa828, 0xa82b,
+ 0xa836, 0xa837,
+ 0xa839, 0xa839,
+ 0xaa77, 0xaa79,
+ 0xfbc3, 0xfbd2,
+ 0xfd40, 0xfd4f,
+ 0xfd90, 0xfd91,
+ 0xfdc8, 0xfdcf,
+ 0xfdfd, 0xfdff,
+ 0xffe4, 0xffe4,
+ 0xffe8, 0xffe8,
+ 0xffed, 0xffee,
+ 0xfffc, 0xfffd,
+ 0x10137, 0x1013f,
+ 0x10179, 0x10189,
+ 0x1018c, 0x1018e,
+ 0x10190, 0x1019c,
+ 0x101a0, 0x101a0,
+ 0x101d0, 0x101fc,
+ 0x10877, 0x10878,
+ 0x10ac8, 0x10ac8,
+ 0x10ed1, 0x10ed8,
+ 0x1173f, 0x1173f,
+ 0x11fd5, 0x11fdc,
+ 0x11fe1, 0x11ff1,
+ 0x16b3c, 0x16b3f,
+ 0x16b45, 0x16b45,
+ 0x1bc9c, 0x1bc9c,
+ 0x1cc00, 0x1ccef,
+ 0x1ccfa, 0x1ccfc,
+ 0x1cd00, 0x1ceb3,
+ 0x1ceba, 0x1ced0,
+ 0x1cee0, 0x1ceef,
+ 0x1cf50, 0x1cfc3,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d129, 0x1d164,
+ 0x1d16a, 0x1d16c,
+ 0x1d183, 0x1d184,
+ 0x1d18c, 0x1d1a9,
+ 0x1d1ae, 0x1d1ea,
+ 0x1d200, 0x1d241,
+ 0x1d245, 0x1d245,
+ 0x1d300, 0x1d356,
+ 0x1d800, 0x1d9ff,
+ 0x1da37, 0x1da3a,
+ 0x1da6d, 0x1da74,
+ 0x1da76, 0x1da83,
+ 0x1da85, 0x1da86,
+ 0x1e14f, 0x1e14f,
+ 0x1ecac, 0x1ecac,
+ 0x1ed2e, 0x1ed2e,
+ 0x1f000, 0x1f02b,
+ 0x1f030, 0x1f093,
+ 0x1f0a0, 0x1f0ae,
+ 0x1f0b1, 0x1f0bf,
+ 0x1f0c1, 0x1f0cf,
+ 0x1f0d1, 0x1f0f5,
+ 0x1f10d, 0x1f1ad,
+ 0x1f1e6, 0x1f202,
+ 0x1f210, 0x1f23b,
+ 0x1f240, 0x1f248,
+ 0x1f250, 0x1f251,
+ 0x1f260, 0x1f265,
+ 0x1f300, 0x1f3fa,
+ 0x1f400, 0x1f6d8,
+ 0x1f6dc, 0x1f6ec,
+ 0x1f6f0, 0x1f6fc,
+ 0x1f700, 0x1f7d9,
+ 0x1f7e0, 0x1f7eb,
+ 0x1f7f0, 0x1f7f0,
+ 0x1f800, 0x1f80b,
+ 0x1f810, 0x1f847,
+ 0x1f850, 0x1f859,
+ 0x1f860, 0x1f887,
+ 0x1f890, 0x1f8ad,
+ 0x1f8b0, 0x1f8bb,
+ 0x1f8c0, 0x1f8c1,
+ 0x1f900, 0x1fa57,
+ 0x1fa60, 0x1fa6d,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa8a,
+ 0x1fa8e, 0x1fac6,
+ 0x1fac8, 0x1fac8,
+ 0x1facd, 0x1fadc,
+ 0x1fadf, 0x1faea,
+ 0x1faef, 0x1faf8,
+ 0x1fb00, 0x1fb92,
+ 0x1fb94, 0x1fbef,
+ 0x1fbfa, 0x1fbfa,
+}; /* CR_So */
+
+/* 'Z': Major Category */
+static const OnigCodePoint CR_Z[] = {
+ 8,
+ 0x0020, 0x0020,
+ 0x00a0, 0x00a0,
+ 0x1680, 0x1680,
+ 0x2000, 0x200a,
+ 0x2028, 0x2029,
+ 0x202f, 0x202f,
+ 0x205f, 0x205f,
+ 0x3000, 0x3000,
+}; /* CR_Z */
+
+/* 'Zl': General Category */
+static const OnigCodePoint CR_Zl[] = {
+ 1,
+ 0x2028, 0x2028,
+}; /* CR_Zl */
+
+/* 'Zp': General Category */
+static const OnigCodePoint CR_Zp[] = {
+ 1,
+ 0x2029, 0x2029,
+}; /* CR_Zp */
+
+/* 'Zs': General Category */
+static const OnigCodePoint CR_Zs[] = {
+ 7,
+ 0x0020, 0x0020,
+ 0x00a0, 0x00a0,
+ 0x1680, 0x1680,
+ 0x2000, 0x200a,
+ 0x202f, 0x202f,
+ 0x205f, 0x205f,
+ 0x3000, 0x3000,
+}; /* CR_Zs */
+
+/* 'Math': Derived Property */
+static const OnigCodePoint CR_Math[] = {
+ 141,
+ 0x002b, 0x002b,
+ 0x003c, 0x003e,
+ 0x005e, 0x005e,
+ 0x007c, 0x007c,
+ 0x007e, 0x007e,
+ 0x00ac, 0x00ac,
+ 0x00b1, 0x00b1,
+ 0x00d7, 0x00d7,
+ 0x00f7, 0x00f7,
+ 0x03d0, 0x03d2,
+ 0x03d5, 0x03d5,
+ 0x03f0, 0x03f1,
+ 0x03f4, 0x03f6,
+ 0x0606, 0x0608,
+ 0x2016, 0x2016,
+ 0x2032, 0x2034,
+ 0x2040, 0x2040,
+ 0x2044, 0x2044,
+ 0x2052, 0x2052,
+ 0x2061, 0x2064,
+ 0x207a, 0x207e,
+ 0x208a, 0x208e,
+ 0x20d0, 0x20dc,
+ 0x20e1, 0x20e1,
+ 0x20e5, 0x20e6,
+ 0x20eb, 0x20ef,
+ 0x2102, 0x2102,
+ 0x2107, 0x2107,
+ 0x210a, 0x2113,
+ 0x2115, 0x2115,
+ 0x2118, 0x211d,
+ 0x2124, 0x2124,
+ 0x2128, 0x2129,
+ 0x212c, 0x212d,
+ 0x212f, 0x2131,
+ 0x2133, 0x2138,
+ 0x213c, 0x2149,
+ 0x214b, 0x214b,
+ 0x2190, 0x21a7,
+ 0x21a9, 0x21ae,
+ 0x21b0, 0x21b1,
+ 0x21b6, 0x21b7,
+ 0x21bc, 0x21db,
+ 0x21dd, 0x21dd,
+ 0x21e4, 0x21e5,
+ 0x21f4, 0x22ff,
+ 0x2308, 0x230b,
+ 0x2320, 0x2321,
+ 0x237c, 0x237c,
+ 0x239b, 0x23b5,
+ 0x23b7, 0x23b7,
+ 0x23d0, 0x23d0,
+ 0x23dc, 0x23e2,
+ 0x25a0, 0x25a1,
+ 0x25ae, 0x25b7,
+ 0x25bc, 0x25c1,
+ 0x25c6, 0x25c7,
+ 0x25ca, 0x25cb,
+ 0x25cf, 0x25d3,
+ 0x25e2, 0x25e2,
+ 0x25e4, 0x25e4,
+ 0x25e7, 0x25ec,
+ 0x25f8, 0x25ff,
+ 0x2605, 0x2606,
+ 0x2640, 0x2640,
+ 0x2642, 0x2642,
+ 0x2660, 0x2663,
+ 0x266d, 0x266f,
+ 0x27c0, 0x27ff,
+ 0x2900, 0x2aff,
+ 0x2b30, 0x2b44,
+ 0x2b47, 0x2b4c,
+ 0xfb29, 0xfb29,
+ 0xfe61, 0xfe66,
+ 0xfe68, 0xfe68,
+ 0xff0b, 0xff0b,
+ 0xff1c, 0xff1e,
+ 0xff3c, 0xff3c,
+ 0xff3e, 0xff3e,
+ 0xff5c, 0xff5c,
+ 0xff5e, 0xff5e,
+ 0xffe2, 0xffe2,
+ 0xffe9, 0xffec,
+ 0x10d8e, 0x10d8f,
+ 0x1cef0, 0x1cef0,
+ 0x1d400, 0x1d454,
+ 0x1d456, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 0x1d4a2, 0x1d4a2,
+ 0x1d4a5, 0x1d4a6,
+ 0x1d4a9, 0x1d4ac,
+ 0x1d4ae, 0x1d4b9,
+ 0x1d4bb, 0x1d4bb,
+ 0x1d4bd, 0x1d4c3,
+ 0x1d4c5, 0x1d505,
+ 0x1d507, 0x1d50a,
+ 0x1d50d, 0x1d514,
+ 0x1d516, 0x1d51c,
+ 0x1d51e, 0x1d539,
+ 0x1d53b, 0x1d53e,
+ 0x1d540, 0x1d544,
+ 0x1d546, 0x1d546,
+ 0x1d54a, 0x1d550,
+ 0x1d552, 0x1d6a5,
+ 0x1d6a8, 0x1d7cb,
+ 0x1d7ce, 0x1d7ff,
+ 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,
+ 0x1f8d0, 0x1f8d8,
+}; /* CR_Math */
+
+/* 'Alphabetic': Derived Property */
+#define CR_Alphabetic CR_Alpha
+
+/* 'Lowercase': Derived Property */
+#define CR_Lowercase CR_Lower
+
+/* 'Uppercase': Derived Property */
+#define CR_Uppercase CR_Upper
+
+/* 'Cased': Derived Property */
+static const OnigCodePoint CR_Cased[] = {
+ 158,
+ 0x0041, 0x005a,
+ 0x0061, 0x007a,
+ 0x00aa, 0x00aa,
+ 0x00b5, 0x00b5,
+ 0x00ba, 0x00ba,
+ 0x00c0, 0x00d6,
+ 0x00d8, 0x00f6,
+ 0x00f8, 0x01ba,
+ 0x01bc, 0x01bf,
+ 0x01c4, 0x0293,
+ 0x0296, 0x02b8,
+ 0x02c0, 0x02c1,
+ 0x02e0, 0x02e4,
+ 0x0345, 0x0345,
+ 0x0370, 0x0373,
+ 0x0376, 0x0377,
+ 0x037a, 0x037d,
+ 0x037f, 0x037f,
+ 0x0386, 0x0386,
+ 0x0388, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x03f5,
+ 0x03f7, 0x0481,
+ 0x048a, 0x052f,
+ 0x0531, 0x0556,
+ 0x0560, 0x0588,
+ 0x10a0, 0x10c5,
+ 0x10c7, 0x10c7,
+ 0x10cd, 0x10cd,
+ 0x10d0, 0x10fa,
+ 0x10fc, 0x10ff,
+ 0x13a0, 0x13f5,
+ 0x13f8, 0x13fd,
+ 0x1c80, 0x1c8a,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cbf,
+ 0x1d00, 0x1dbf,
+ 0x1e00, 0x1f15,
+ 0x1f18, 0x1f1d,
+ 0x1f20, 0x1f45,
+ 0x1f48, 0x1f4d,
+ 0x1f50, 0x1f57,
+ 0x1f59, 0x1f59,
+ 0x1f5b, 0x1f5b,
+ 0x1f5d, 0x1f5d,
+ 0x1f5f, 0x1f7d,
+ 0x1f80, 0x1fb4,
+ 0x1fb6, 0x1fbc,
+ 0x1fbe, 0x1fbe,
+ 0x1fc2, 0x1fc4,
+ 0x1fc6, 0x1fcc,
+ 0x1fd0, 0x1fd3,
+ 0x1fd6, 0x1fdb,
+ 0x1fe0, 0x1fec,
+ 0x1ff2, 0x1ff4,
+ 0x1ff6, 0x1ffc,
+ 0x2071, 0x2071,
+ 0x207f, 0x207f,
+ 0x2090, 0x209c,
+ 0x2102, 0x2102,
+ 0x2107, 0x2107,
+ 0x210a, 0x2113,
+ 0x2115, 0x2115,
+ 0x2119, 0x211d,
+ 0x2124, 0x2124,
+ 0x2126, 0x2126,
+ 0x2128, 0x2128,
+ 0x212a, 0x212d,
+ 0x212f, 0x2134,
+ 0x2139, 0x2139,
+ 0x213c, 0x213f,
+ 0x2145, 0x2149,
+ 0x214e, 0x214e,
+ 0x2160, 0x217f,
+ 0x2183, 0x2184,
+ 0x24b6, 0x24e9,
+ 0x2c00, 0x2ce4,
+ 0x2ceb, 0x2cee,
+ 0x2cf2, 0x2cf3,
+ 0x2d00, 0x2d25,
+ 0x2d27, 0x2d27,
+ 0x2d2d, 0x2d2d,
+ 0xa640, 0xa66d,
+ 0xa680, 0xa69d,
+ 0xa722, 0xa787,
+ 0xa78b, 0xa78e,
+ 0xa790, 0xa7dc,
+ 0xa7f1, 0xa7f6,
+ 0xa7f8, 0xa7fa,
+ 0xab30, 0xab5a,
+ 0xab5c, 0xab69,
+ 0xab70, 0xabbf,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xff21, 0xff3a,
+ 0xff41, 0xff5a,
+ 0x10400, 0x1044f,
+ 0x104b0, 0x104d3,
+ 0x104d8, 0x104fb,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x10780, 0x10780,
+ 0x10783, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 0x10c80, 0x10cb2,
+ 0x10cc0, 0x10cf2,
+ 0x10d50, 0x10d65,
+ 0x10d70, 0x10d85,
+ 0x118a0, 0x118df,
+ 0x16e40, 0x16e7f,
+ 0x16ea0, 0x16eb8,
+ 0x16ebb, 0x16ed3,
+ 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, 0x1d6c0,
+ 0x1d6c2, 0x1d6da,
+ 0x1d6dc, 0x1d6fa,
+ 0x1d6fc, 0x1d714,
+ 0x1d716, 0x1d734,
+ 0x1d736, 0x1d74e,
+ 0x1d750, 0x1d76e,
+ 0x1d770, 0x1d788,
+ 0x1d78a, 0x1d7a8,
+ 0x1d7aa, 0x1d7c2,
+ 0x1d7c4, 0x1d7cb,
+ 0x1df00, 0x1df09,
+ 0x1df0b, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e030, 0x1e06d,
+ 0x1e900, 0x1e943,
+ 0x1f130, 0x1f149,
+ 0x1f150, 0x1f169,
+ 0x1f170, 0x1f189,
+}; /* CR_Cased */
+
+/* 'Case_Ignorable': Derived Property */
+static const OnigCodePoint CR_Case_Ignorable[] = {
+ 464,
+ 0x0027, 0x0027,
+ 0x002e, 0x002e,
+ 0x003a, 0x003a,
+ 0x005e, 0x005e,
+ 0x0060, 0x0060,
+ 0x00a8, 0x00a8,
+ 0x00ad, 0x00ad,
+ 0x00af, 0x00af,
+ 0x00b4, 0x00b4,
+ 0x00b7, 0x00b8,
+ 0x02b0, 0x036f,
+ 0x0374, 0x0375,
+ 0x037a, 0x037a,
+ 0x0384, 0x0385,
+ 0x0387, 0x0387,
+ 0x0483, 0x0489,
+ 0x0559, 0x0559,
+ 0x055f, 0x055f,
+ 0x0591, 0x05bd,
+ 0x05bf, 0x05bf,
+ 0x05c1, 0x05c2,
+ 0x05c4, 0x05c5,
+ 0x05c7, 0x05c7,
+ 0x05f4, 0x05f4,
+ 0x0600, 0x0605,
+ 0x0610, 0x061a,
+ 0x061c, 0x061c,
+ 0x0640, 0x0640,
+ 0x064b, 0x065f,
+ 0x0670, 0x0670,
+ 0x06d6, 0x06dd,
+ 0x06df, 0x06e8,
+ 0x06ea, 0x06ed,
+ 0x070f, 0x070f,
+ 0x0711, 0x0711,
+ 0x0730, 0x074a,
+ 0x07a6, 0x07b0,
+ 0x07eb, 0x07f5,
+ 0x07fa, 0x07fa,
+ 0x07fd, 0x07fd,
+ 0x0816, 0x082d,
+ 0x0859, 0x085b,
+ 0x0888, 0x0888,
+ 0x0890, 0x0891,
+ 0x0897, 0x089f,
+ 0x08c9, 0x0902,
+ 0x093a, 0x093a,
+ 0x093c, 0x093c,
+ 0x0941, 0x0948,
+ 0x094d, 0x094d,
+ 0x0951, 0x0957,
+ 0x0962, 0x0963,
+ 0x0971, 0x0971,
+ 0x0981, 0x0981,
+ 0x09bc, 0x09bc,
+ 0x09c1, 0x09c4,
+ 0x09cd, 0x09cd,
+ 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,
+ 0x0b3f, 0x0b3f,
+ 0x0b41, 0x0b44,
+ 0x0b4d, 0x0b4d,
+ 0x0b55, 0x0b56,
+ 0x0b62, 0x0b63,
+ 0x0b82, 0x0b82,
+ 0x0bc0, 0x0bc0,
+ 0x0bcd, 0x0bcd,
+ 0x0c00, 0x0c00,
+ 0x0c04, 0x0c04,
+ 0x0c3c, 0x0c3c,
+ 0x0c3e, 0x0c40,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c62, 0x0c63,
+ 0x0c81, 0x0c81,
+ 0x0cbc, 0x0cbc,
+ 0x0cbf, 0x0cbf,
+ 0x0cc6, 0x0cc6,
+ 0x0ccc, 0x0ccd,
+ 0x0ce2, 0x0ce3,
+ 0x0d00, 0x0d01,
+ 0x0d3b, 0x0d3c,
+ 0x0d41, 0x0d44,
+ 0x0d4d, 0x0d4d,
+ 0x0d62, 0x0d63,
+ 0x0d81, 0x0d81,
+ 0x0dca, 0x0dca,
+ 0x0dd2, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0e31, 0x0e31,
+ 0x0e34, 0x0e3a,
+ 0x0e46, 0x0e4e,
+ 0x0eb1, 0x0eb1,
+ 0x0eb4, 0x0ebc,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ece,
+ 0x0f18, 0x0f19,
+ 0x0f35, 0x0f35,
+ 0x0f37, 0x0f37,
+ 0x0f39, 0x0f39,
+ 0x0f71, 0x0f7e,
+ 0x0f80, 0x0f84,
+ 0x0f86, 0x0f87,
+ 0x0f8d, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 0x0fc6, 0x0fc6,
+ 0x102d, 0x1030,
+ 0x1032, 0x1037,
+ 0x1039, 0x103a,
+ 0x103d, 0x103e,
+ 0x1058, 0x1059,
+ 0x105e, 0x1060,
+ 0x1071, 0x1074,
+ 0x1082, 0x1082,
+ 0x1085, 0x1086,
+ 0x108d, 0x108d,
+ 0x109d, 0x109d,
+ 0x10fc, 0x10fc,
+ 0x135d, 0x135f,
+ 0x1712, 0x1714,
+ 0x1732, 0x1733,
+ 0x1752, 0x1753,
+ 0x1772, 0x1773,
+ 0x17b4, 0x17b5,
+ 0x17b7, 0x17bd,
+ 0x17c6, 0x17c6,
+ 0x17c9, 0x17d3,
+ 0x17d7, 0x17d7,
+ 0x17dd, 0x17dd,
+ 0x180b, 0x180f,
+ 0x1843, 0x1843,
+ 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,
+ 0x1aa7, 0x1aa7,
+ 0x1ab0, 0x1add,
+ 0x1ae0, 0x1aeb,
+ 0x1b00, 0x1b03,
+ 0x1b34, 0x1b34,
+ 0x1b36, 0x1b3a,
+ 0x1b3c, 0x1b3c,
+ 0x1b42, 0x1b42,
+ 0x1b6b, 0x1b73,
+ 0x1b80, 0x1b81,
+ 0x1ba2, 0x1ba5,
+ 0x1ba8, 0x1ba9,
+ 0x1bab, 0x1bad,
+ 0x1be6, 0x1be6,
+ 0x1be8, 0x1be9,
+ 0x1bed, 0x1bed,
+ 0x1bef, 0x1bf1,
+ 0x1c2c, 0x1c33,
+ 0x1c36, 0x1c37,
+ 0x1c78, 0x1c7d,
+ 0x1cd0, 0x1cd2,
+ 0x1cd4, 0x1ce0,
+ 0x1ce2, 0x1ce8,
+ 0x1ced, 0x1ced,
+ 0x1cf4, 0x1cf4,
+ 0x1cf8, 0x1cf9,
+ 0x1d2c, 0x1d6a,
+ 0x1d78, 0x1d78,
+ 0x1d9b, 0x1dff,
+ 0x1fbd, 0x1fbd,
+ 0x1fbf, 0x1fc1,
+ 0x1fcd, 0x1fcf,
+ 0x1fdd, 0x1fdf,
+ 0x1fed, 0x1fef,
+ 0x1ffd, 0x1ffe,
+ 0x200b, 0x200f,
+ 0x2018, 0x2019,
+ 0x2024, 0x2024,
+ 0x2027, 0x2027,
+ 0x202a, 0x202e,
+ 0x2060, 0x2064,
+ 0x2066, 0x206f,
+ 0x2071, 0x2071,
+ 0x207f, 0x207f,
+ 0x2090, 0x209c,
+ 0x20d0, 0x20f0,
+ 0x2c7c, 0x2c7d,
+ 0x2cef, 0x2cf1,
+ 0x2d6f, 0x2d6f,
+ 0x2d7f, 0x2d7f,
+ 0x2de0, 0x2dff,
+ 0x2e2f, 0x2e2f,
+ 0x3005, 0x3005,
+ 0x302a, 0x302d,
+ 0x3031, 0x3035,
+ 0x303b, 0x303b,
+ 0x3099, 0x309e,
+ 0x30fc, 0x30fe,
+ 0xa015, 0xa015,
+ 0xa4f8, 0xa4fd,
+ 0xa60c, 0xa60c,
+ 0xa66f, 0xa672,
+ 0xa674, 0xa67d,
+ 0xa67f, 0xa67f,
+ 0xa69c, 0xa69f,
+ 0xa6f0, 0xa6f1,
+ 0xa700, 0xa721,
+ 0xa770, 0xa770,
+ 0xa788, 0xa78a,
+ 0xa7f1, 0xa7f4,
+ 0xa7f8, 0xa7f9,
+ 0xa802, 0xa802,
+ 0xa806, 0xa806,
+ 0xa80b, 0xa80b,
+ 0xa825, 0xa826,
+ 0xa82c, 0xa82c,
+ 0xa8c4, 0xa8c5,
+ 0xa8e0, 0xa8f1,
+ 0xa8ff, 0xa8ff,
+ 0xa926, 0xa92d,
+ 0xa947, 0xa951,
+ 0xa980, 0xa982,
+ 0xa9b3, 0xa9b3,
+ 0xa9b6, 0xa9b9,
+ 0xa9bc, 0xa9bd,
+ 0xa9cf, 0xa9cf,
+ 0xa9e5, 0xa9e6,
+ 0xaa29, 0xaa2e,
+ 0xaa31, 0xaa32,
+ 0xaa35, 0xaa36,
+ 0xaa43, 0xaa43,
+ 0xaa4c, 0xaa4c,
+ 0xaa70, 0xaa70,
+ 0xaa7c, 0xaa7c,
+ 0xaab0, 0xaab0,
+ 0xaab2, 0xaab4,
+ 0xaab7, 0xaab8,
+ 0xaabe, 0xaabf,
+ 0xaac1, 0xaac1,
+ 0xaadd, 0xaadd,
+ 0xaaec, 0xaaed,
+ 0xaaf3, 0xaaf4,
+ 0xaaf6, 0xaaf6,
+ 0xab5b, 0xab5f,
+ 0xab69, 0xab6b,
+ 0xabe5, 0xabe5,
+ 0xabe8, 0xabe8,
+ 0xabed, 0xabed,
+ 0xfb1e, 0xfb1e,
+ 0xfbb2, 0xfbc2,
+ 0xfe00, 0xfe0f,
+ 0xfe13, 0xfe13,
+ 0xfe20, 0xfe2f,
+ 0xfe52, 0xfe52,
+ 0xfe55, 0xfe55,
+ 0xfeff, 0xfeff,
+ 0xff07, 0xff07,
+ 0xff0e, 0xff0e,
+ 0xff1a, 0xff1a,
+ 0xff3e, 0xff3e,
+ 0xff40, 0xff40,
+ 0xff70, 0xff70,
+ 0xff9e, 0xff9f,
+ 0xffe3, 0xffe3,
+ 0xfff9, 0xfffb,
+ 0x101fd, 0x101fd,
+ 0x102e0, 0x102e0,
+ 0x10376, 0x1037a,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 0x10a01, 0x10a03,
+ 0x10a05, 0x10a06,
+ 0x10a0c, 0x10a0f,
+ 0x10a38, 0x10a3a,
+ 0x10a3f, 0x10a3f,
+ 0x10ae5, 0x10ae6,
+ 0x10d24, 0x10d27,
+ 0x10d4e, 0x10d4e,
+ 0x10d69, 0x10d6d,
+ 0x10d6f, 0x10d6f,
+ 0x10eab, 0x10eac,
+ 0x10ec5, 0x10ec5,
+ 0x10efa, 0x10eff,
+ 0x10f46, 0x10f50,
+ 0x10f82, 0x10f85,
+ 0x11001, 0x11001,
+ 0x11038, 0x11046,
+ 0x11070, 0x11070,
+ 0x11073, 0x11074,
+ 0x1107f, 0x11081,
+ 0x110b3, 0x110b6,
+ 0x110b9, 0x110ba,
+ 0x110bd, 0x110bd,
+ 0x110c2, 0x110c2,
+ 0x110cd, 0x110cd,
+ 0x11100, 0x11102,
+ 0x11127, 0x1112b,
+ 0x1112d, 0x11134,
+ 0x11173, 0x11173,
+ 0x11180, 0x11181,
+ 0x111b6, 0x111be,
+ 0x111c9, 0x111cc,
+ 0x111cf, 0x111cf,
+ 0x1122f, 0x11231,
+ 0x11234, 0x11234,
+ 0x11236, 0x11237,
+ 0x1123e, 0x1123e,
+ 0x11241, 0x11241,
+ 0x112df, 0x112df,
+ 0x112e3, 0x112ea,
+ 0x11300, 0x11301,
+ 0x1133b, 0x1133c,
+ 0x11340, 0x11340,
+ 0x11366, 0x1136c,
+ 0x11370, 0x11374,
+ 0x113bb, 0x113c0,
+ 0x113ce, 0x113ce,
+ 0x113d0, 0x113d0,
+ 0x113d2, 0x113d2,
+ 0x113e1, 0x113e2,
+ 0x11438, 0x1143f,
+ 0x11442, 0x11444,
+ 0x11446, 0x11446,
+ 0x1145e, 0x1145e,
+ 0x114b3, 0x114b8,
+ 0x114ba, 0x114ba,
+ 0x114bf, 0x114c0,
+ 0x114c2, 0x114c3,
+ 0x115b2, 0x115b5,
+ 0x115bc, 0x115bd,
+ 0x115bf, 0x115c0,
+ 0x115dc, 0x115dd,
+ 0x11633, 0x1163a,
+ 0x1163d, 0x1163d,
+ 0x1163f, 0x11640,
+ 0x116ab, 0x116ab,
+ 0x116ad, 0x116ad,
+ 0x116b0, 0x116b5,
+ 0x116b7, 0x116b7,
+ 0x1171d, 0x1171d,
+ 0x1171f, 0x1171f,
+ 0x11722, 0x11725,
+ 0x11727, 0x1172b,
+ 0x1182f, 0x11837,
+ 0x11839, 0x1183a,
+ 0x1193b, 0x1193c,
+ 0x1193e, 0x1193e,
+ 0x11943, 0x11943,
+ 0x119d4, 0x119d7,
+ 0x119da, 0x119db,
+ 0x119e0, 0x119e0,
+ 0x11a01, 0x11a0a,
+ 0x11a33, 0x11a38,
+ 0x11a3b, 0x11a3e,
+ 0x11a47, 0x11a47,
+ 0x11a51, 0x11a56,
+ 0x11a59, 0x11a5b,
+ 0x11a8a, 0x11a96,
+ 0x11a98, 0x11a99,
+ 0x11b60, 0x11b60,
+ 0x11b62, 0x11b64,
+ 0x11b66, 0x11b66,
+ 0x11c30, 0x11c36,
+ 0x11c38, 0x11c3d,
+ 0x11c3f, 0x11c3f,
+ 0x11c92, 0x11ca7,
+ 0x11caa, 0x11cb0,
+ 0x11cb2, 0x11cb3,
+ 0x11cb5, 0x11cb6,
+ 0x11d31, 0x11d36,
+ 0x11d3a, 0x11d3a,
+ 0x11d3c, 0x11d3d,
+ 0x11d3f, 0x11d45,
+ 0x11d47, 0x11d47,
+ 0x11d90, 0x11d91,
+ 0x11d95, 0x11d95,
+ 0x11d97, 0x11d97,
+ 0x11dd9, 0x11dd9,
+ 0x11ef3, 0x11ef4,
+ 0x11f00, 0x11f01,
+ 0x11f36, 0x11f3a,
+ 0x11f40, 0x11f40,
+ 0x11f42, 0x11f42,
+ 0x11f5a, 0x11f5a,
+ 0x13430, 0x13440,
+ 0x13447, 0x13455,
+ 0x1611e, 0x16129,
+ 0x1612d, 0x1612f,
+ 0x16af0, 0x16af4,
+ 0x16b30, 0x16b36,
+ 0x16b40, 0x16b43,
+ 0x16d40, 0x16d42,
+ 0x16d6b, 0x16d6c,
+ 0x16f4f, 0x16f4f,
+ 0x16f8f, 0x16f9f,
+ 0x16fe0, 0x16fe1,
+ 0x16fe3, 0x16fe4,
+ 0x16ff2, 0x16ff3,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1bc9d, 0x1bc9e,
+ 0x1bca0, 0x1bca3,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
+ 0x1d167, 0x1d169,
+ 0x1d173, 0x1d182,
+ 0x1d185, 0x1d18b,
+ 0x1d1aa, 0x1d1ad,
+ 0x1d242, 0x1d244,
+ 0x1da00, 0x1da36,
+ 0x1da3b, 0x1da6c,
+ 0x1da75, 0x1da75,
+ 0x1da84, 0x1da84,
+ 0x1da9b, 0x1da9f,
+ 0x1daa1, 0x1daaf,
+ 0x1e000, 0x1e006,
+ 0x1e008, 0x1e018,
+ 0x1e01b, 0x1e021,
+ 0x1e023, 0x1e024,
+ 0x1e026, 0x1e02a,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
+ 0x1e130, 0x1e13d,
+ 0x1e2ae, 0x1e2ae,
+ 0x1e2ec, 0x1e2ef,
+ 0x1e4eb, 0x1e4ef,
+ 0x1e5ee, 0x1e5ef,
+ 0x1e6e3, 0x1e6e3,
+ 0x1e6e6, 0x1e6e6,
+ 0x1e6ee, 0x1e6ef,
+ 0x1e6f5, 0x1e6f5,
+ 0x1e6ff, 0x1e6ff,
+ 0x1e8d0, 0x1e8d6,
+ 0x1e944, 0x1e94b,
+ 0x1f3fb, 0x1f3ff,
+ 0xe0001, 0xe0001,
+ 0xe0020, 0xe007f,
+ 0xe0100, 0xe01ef,
+}; /* CR_Case_Ignorable */
+
+/* 'Changes_When_Lowercased': Derived Property */
+static const OnigCodePoint CR_Changes_When_Lowercased[] = {
+ 618,
+ 0x0041, 0x005a,
+ 0x00c0, 0x00d6,
+ 0x00d8, 0x00de,
+ 0x0100, 0x0100,
+ 0x0102, 0x0102,
+ 0x0104, 0x0104,
+ 0x0106, 0x0106,
+ 0x0108, 0x0108,
+ 0x010a, 0x010a,
+ 0x010c, 0x010c,
+ 0x010e, 0x010e,
+ 0x0110, 0x0110,
+ 0x0112, 0x0112,
+ 0x0114, 0x0114,
+ 0x0116, 0x0116,
+ 0x0118, 0x0118,
+ 0x011a, 0x011a,
+ 0x011c, 0x011c,
+ 0x011e, 0x011e,
+ 0x0120, 0x0120,
+ 0x0122, 0x0122,
+ 0x0124, 0x0124,
+ 0x0126, 0x0126,
+ 0x0128, 0x0128,
+ 0x012a, 0x012a,
+ 0x012c, 0x012c,
+ 0x012e, 0x012e,
+ 0x0130, 0x0130,
+ 0x0132, 0x0132,
+ 0x0134, 0x0134,
+ 0x0136, 0x0136,
+ 0x0139, 0x0139,
+ 0x013b, 0x013b,
+ 0x013d, 0x013d,
+ 0x013f, 0x013f,
+ 0x0141, 0x0141,
+ 0x0143, 0x0143,
+ 0x0145, 0x0145,
+ 0x0147, 0x0147,
+ 0x014a, 0x014a,
+ 0x014c, 0x014c,
+ 0x014e, 0x014e,
+ 0x0150, 0x0150,
+ 0x0152, 0x0152,
+ 0x0154, 0x0154,
+ 0x0156, 0x0156,
+ 0x0158, 0x0158,
+ 0x015a, 0x015a,
+ 0x015c, 0x015c,
+ 0x015e, 0x015e,
+ 0x0160, 0x0160,
+ 0x0162, 0x0162,
+ 0x0164, 0x0164,
+ 0x0166, 0x0166,
+ 0x0168, 0x0168,
+ 0x016a, 0x016a,
+ 0x016c, 0x016c,
+ 0x016e, 0x016e,
+ 0x0170, 0x0170,
+ 0x0172, 0x0172,
+ 0x0174, 0x0174,
+ 0x0176, 0x0176,
+ 0x0178, 0x0179,
+ 0x017b, 0x017b,
+ 0x017d, 0x017d,
+ 0x0181, 0x0182,
+ 0x0184, 0x0184,
+ 0x0186, 0x0187,
+ 0x0189, 0x018b,
+ 0x018e, 0x0191,
+ 0x0193, 0x0194,
+ 0x0196, 0x0198,
+ 0x019c, 0x019d,
+ 0x019f, 0x01a0,
+ 0x01a2, 0x01a2,
+ 0x01a4, 0x01a4,
+ 0x01a6, 0x01a7,
+ 0x01a9, 0x01a9,
+ 0x01ac, 0x01ac,
+ 0x01ae, 0x01af,
+ 0x01b1, 0x01b3,
+ 0x01b5, 0x01b5,
+ 0x01b7, 0x01b8,
+ 0x01bc, 0x01bc,
+ 0x01c4, 0x01c5,
+ 0x01c7, 0x01c8,
+ 0x01ca, 0x01cb,
+ 0x01cd, 0x01cd,
+ 0x01cf, 0x01cf,
+ 0x01d1, 0x01d1,
+ 0x01d3, 0x01d3,
+ 0x01d5, 0x01d5,
+ 0x01d7, 0x01d7,
+ 0x01d9, 0x01d9,
+ 0x01db, 0x01db,
+ 0x01de, 0x01de,
+ 0x01e0, 0x01e0,
+ 0x01e2, 0x01e2,
+ 0x01e4, 0x01e4,
+ 0x01e6, 0x01e6,
+ 0x01e8, 0x01e8,
+ 0x01ea, 0x01ea,
+ 0x01ec, 0x01ec,
+ 0x01ee, 0x01ee,
+ 0x01f1, 0x01f2,
+ 0x01f4, 0x01f4,
+ 0x01f6, 0x01f8,
+ 0x01fa, 0x01fa,
+ 0x01fc, 0x01fc,
+ 0x01fe, 0x01fe,
+ 0x0200, 0x0200,
+ 0x0202, 0x0202,
+ 0x0204, 0x0204,
+ 0x0206, 0x0206,
+ 0x0208, 0x0208,
+ 0x020a, 0x020a,
+ 0x020c, 0x020c,
+ 0x020e, 0x020e,
+ 0x0210, 0x0210,
+ 0x0212, 0x0212,
+ 0x0214, 0x0214,
+ 0x0216, 0x0216,
+ 0x0218, 0x0218,
+ 0x021a, 0x021a,
+ 0x021c, 0x021c,
+ 0x021e, 0x021e,
+ 0x0220, 0x0220,
+ 0x0222, 0x0222,
+ 0x0224, 0x0224,
+ 0x0226, 0x0226,
+ 0x0228, 0x0228,
+ 0x022a, 0x022a,
+ 0x022c, 0x022c,
+ 0x022e, 0x022e,
+ 0x0230, 0x0230,
+ 0x0232, 0x0232,
+ 0x023a, 0x023b,
+ 0x023d, 0x023e,
+ 0x0241, 0x0241,
+ 0x0243, 0x0246,
+ 0x0248, 0x0248,
+ 0x024a, 0x024a,
+ 0x024c, 0x024c,
+ 0x024e, 0x024e,
+ 0x0370, 0x0370,
+ 0x0372, 0x0372,
+ 0x0376, 0x0376,
+ 0x037f, 0x037f,
+ 0x0386, 0x0386,
+ 0x0388, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x038f,
+ 0x0391, 0x03a1,
+ 0x03a3, 0x03ab,
+ 0x03cf, 0x03cf,
+ 0x03d8, 0x03d8,
+ 0x03da, 0x03da,
+ 0x03dc, 0x03dc,
+ 0x03de, 0x03de,
+ 0x03e0, 0x03e0,
+ 0x03e2, 0x03e2,
+ 0x03e4, 0x03e4,
+ 0x03e6, 0x03e6,
+ 0x03e8, 0x03e8,
+ 0x03ea, 0x03ea,
+ 0x03ec, 0x03ec,
+ 0x03ee, 0x03ee,
+ 0x03f4, 0x03f4,
+ 0x03f7, 0x03f7,
+ 0x03f9, 0x03fa,
+ 0x03fd, 0x042f,
+ 0x0460, 0x0460,
+ 0x0462, 0x0462,
+ 0x0464, 0x0464,
+ 0x0466, 0x0466,
+ 0x0468, 0x0468,
+ 0x046a, 0x046a,
+ 0x046c, 0x046c,
+ 0x046e, 0x046e,
+ 0x0470, 0x0470,
+ 0x0472, 0x0472,
+ 0x0474, 0x0474,
+ 0x0476, 0x0476,
+ 0x0478, 0x0478,
+ 0x047a, 0x047a,
+ 0x047c, 0x047c,
+ 0x047e, 0x047e,
+ 0x0480, 0x0480,
+ 0x048a, 0x048a,
+ 0x048c, 0x048c,
+ 0x048e, 0x048e,
+ 0x0490, 0x0490,
+ 0x0492, 0x0492,
+ 0x0494, 0x0494,
+ 0x0496, 0x0496,
+ 0x0498, 0x0498,
+ 0x049a, 0x049a,
+ 0x049c, 0x049c,
+ 0x049e, 0x049e,
+ 0x04a0, 0x04a0,
+ 0x04a2, 0x04a2,
+ 0x04a4, 0x04a4,
+ 0x04a6, 0x04a6,
+ 0x04a8, 0x04a8,
+ 0x04aa, 0x04aa,
+ 0x04ac, 0x04ac,
+ 0x04ae, 0x04ae,
+ 0x04b0, 0x04b0,
+ 0x04b2, 0x04b2,
+ 0x04b4, 0x04b4,
+ 0x04b6, 0x04b6,
+ 0x04b8, 0x04b8,
+ 0x04ba, 0x04ba,
+ 0x04bc, 0x04bc,
+ 0x04be, 0x04be,
+ 0x04c0, 0x04c1,
+ 0x04c3, 0x04c3,
+ 0x04c5, 0x04c5,
+ 0x04c7, 0x04c7,
+ 0x04c9, 0x04c9,
+ 0x04cb, 0x04cb,
+ 0x04cd, 0x04cd,
+ 0x04d0, 0x04d0,
+ 0x04d2, 0x04d2,
+ 0x04d4, 0x04d4,
+ 0x04d6, 0x04d6,
+ 0x04d8, 0x04d8,
+ 0x04da, 0x04da,
+ 0x04dc, 0x04dc,
+ 0x04de, 0x04de,
+ 0x04e0, 0x04e0,
+ 0x04e2, 0x04e2,
+ 0x04e4, 0x04e4,
+ 0x04e6, 0x04e6,
+ 0x04e8, 0x04e8,
+ 0x04ea, 0x04ea,
+ 0x04ec, 0x04ec,
+ 0x04ee, 0x04ee,
+ 0x04f0, 0x04f0,
+ 0x04f2, 0x04f2,
+ 0x04f4, 0x04f4,
+ 0x04f6, 0x04f6,
+ 0x04f8, 0x04f8,
+ 0x04fa, 0x04fa,
+ 0x04fc, 0x04fc,
+ 0x04fe, 0x04fe,
+ 0x0500, 0x0500,
+ 0x0502, 0x0502,
+ 0x0504, 0x0504,
+ 0x0506, 0x0506,
+ 0x0508, 0x0508,
+ 0x050a, 0x050a,
+ 0x050c, 0x050c,
+ 0x050e, 0x050e,
+ 0x0510, 0x0510,
+ 0x0512, 0x0512,
+ 0x0514, 0x0514,
+ 0x0516, 0x0516,
+ 0x0518, 0x0518,
+ 0x051a, 0x051a,
+ 0x051c, 0x051c,
+ 0x051e, 0x051e,
+ 0x0520, 0x0520,
+ 0x0522, 0x0522,
+ 0x0524, 0x0524,
+ 0x0526, 0x0526,
+ 0x0528, 0x0528,
+ 0x052a, 0x052a,
+ 0x052c, 0x052c,
+ 0x052e, 0x052e,
+ 0x0531, 0x0556,
+ 0x10a0, 0x10c5,
+ 0x10c7, 0x10c7,
+ 0x10cd, 0x10cd,
+ 0x13a0, 0x13f5,
+ 0x1c89, 0x1c89,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cbf,
+ 0x1e00, 0x1e00,
+ 0x1e02, 0x1e02,
+ 0x1e04, 0x1e04,
+ 0x1e06, 0x1e06,
+ 0x1e08, 0x1e08,
+ 0x1e0a, 0x1e0a,
+ 0x1e0c, 0x1e0c,
+ 0x1e0e, 0x1e0e,
+ 0x1e10, 0x1e10,
+ 0x1e12, 0x1e12,
+ 0x1e14, 0x1e14,
+ 0x1e16, 0x1e16,
+ 0x1e18, 0x1e18,
+ 0x1e1a, 0x1e1a,
+ 0x1e1c, 0x1e1c,
+ 0x1e1e, 0x1e1e,
+ 0x1e20, 0x1e20,
+ 0x1e22, 0x1e22,
+ 0x1e24, 0x1e24,
+ 0x1e26, 0x1e26,
+ 0x1e28, 0x1e28,
+ 0x1e2a, 0x1e2a,
+ 0x1e2c, 0x1e2c,
+ 0x1e2e, 0x1e2e,
+ 0x1e30, 0x1e30,
+ 0x1e32, 0x1e32,
+ 0x1e34, 0x1e34,
+ 0x1e36, 0x1e36,
+ 0x1e38, 0x1e38,
+ 0x1e3a, 0x1e3a,
+ 0x1e3c, 0x1e3c,
+ 0x1e3e, 0x1e3e,
+ 0x1e40, 0x1e40,
+ 0x1e42, 0x1e42,
+ 0x1e44, 0x1e44,
+ 0x1e46, 0x1e46,
+ 0x1e48, 0x1e48,
+ 0x1e4a, 0x1e4a,
+ 0x1e4c, 0x1e4c,
+ 0x1e4e, 0x1e4e,
+ 0x1e50, 0x1e50,
+ 0x1e52, 0x1e52,
+ 0x1e54, 0x1e54,
+ 0x1e56, 0x1e56,
+ 0x1e58, 0x1e58,
+ 0x1e5a, 0x1e5a,
+ 0x1e5c, 0x1e5c,
+ 0x1e5e, 0x1e5e,
+ 0x1e60, 0x1e60,
+ 0x1e62, 0x1e62,
+ 0x1e64, 0x1e64,
+ 0x1e66, 0x1e66,
+ 0x1e68, 0x1e68,
+ 0x1e6a, 0x1e6a,
+ 0x1e6c, 0x1e6c,
+ 0x1e6e, 0x1e6e,
+ 0x1e70, 0x1e70,
+ 0x1e72, 0x1e72,
+ 0x1e74, 0x1e74,
+ 0x1e76, 0x1e76,
+ 0x1e78, 0x1e78,
+ 0x1e7a, 0x1e7a,
+ 0x1e7c, 0x1e7c,
+ 0x1e7e, 0x1e7e,
+ 0x1e80, 0x1e80,
+ 0x1e82, 0x1e82,
+ 0x1e84, 0x1e84,
+ 0x1e86, 0x1e86,
+ 0x1e88, 0x1e88,
+ 0x1e8a, 0x1e8a,
+ 0x1e8c, 0x1e8c,
+ 0x1e8e, 0x1e8e,
+ 0x1e90, 0x1e90,
+ 0x1e92, 0x1e92,
+ 0x1e94, 0x1e94,
+ 0x1e9e, 0x1e9e,
+ 0x1ea0, 0x1ea0,
+ 0x1ea2, 0x1ea2,
+ 0x1ea4, 0x1ea4,
+ 0x1ea6, 0x1ea6,
+ 0x1ea8, 0x1ea8,
+ 0x1eaa, 0x1eaa,
+ 0x1eac, 0x1eac,
+ 0x1eae, 0x1eae,
+ 0x1eb0, 0x1eb0,
+ 0x1eb2, 0x1eb2,
+ 0x1eb4, 0x1eb4,
+ 0x1eb6, 0x1eb6,
+ 0x1eb8, 0x1eb8,
+ 0x1eba, 0x1eba,
+ 0x1ebc, 0x1ebc,
+ 0x1ebe, 0x1ebe,
+ 0x1ec0, 0x1ec0,
+ 0x1ec2, 0x1ec2,
+ 0x1ec4, 0x1ec4,
+ 0x1ec6, 0x1ec6,
+ 0x1ec8, 0x1ec8,
+ 0x1eca, 0x1eca,
+ 0x1ecc, 0x1ecc,
+ 0x1ece, 0x1ece,
+ 0x1ed0, 0x1ed0,
+ 0x1ed2, 0x1ed2,
+ 0x1ed4, 0x1ed4,
+ 0x1ed6, 0x1ed6,
+ 0x1ed8, 0x1ed8,
+ 0x1eda, 0x1eda,
+ 0x1edc, 0x1edc,
+ 0x1ede, 0x1ede,
+ 0x1ee0, 0x1ee0,
+ 0x1ee2, 0x1ee2,
+ 0x1ee4, 0x1ee4,
+ 0x1ee6, 0x1ee6,
+ 0x1ee8, 0x1ee8,
+ 0x1eea, 0x1eea,
+ 0x1eec, 0x1eec,
+ 0x1eee, 0x1eee,
+ 0x1ef0, 0x1ef0,
+ 0x1ef2, 0x1ef2,
+ 0x1ef4, 0x1ef4,
+ 0x1ef6, 0x1ef6,
+ 0x1ef8, 0x1ef8,
+ 0x1efa, 0x1efa,
+ 0x1efc, 0x1efc,
+ 0x1efe, 0x1efe,
+ 0x1f08, 0x1f0f,
+ 0x1f18, 0x1f1d,
+ 0x1f28, 0x1f2f,
+ 0x1f38, 0x1f3f,
+ 0x1f48, 0x1f4d,
+ 0x1f59, 0x1f59,
+ 0x1f5b, 0x1f5b,
+ 0x1f5d, 0x1f5d,
+ 0x1f5f, 0x1f5f,
+ 0x1f68, 0x1f6f,
+ 0x1f88, 0x1f8f,
+ 0x1f98, 0x1f9f,
+ 0x1fa8, 0x1faf,
+ 0x1fb8, 0x1fbc,
+ 0x1fc8, 0x1fcc,
+ 0x1fd8, 0x1fdb,
+ 0x1fe8, 0x1fec,
+ 0x1ff8, 0x1ffc,
+ 0x2126, 0x2126,
+ 0x212a, 0x212b,
+ 0x2132, 0x2132,
+ 0x2160, 0x216f,
+ 0x2183, 0x2183,
+ 0x24b6, 0x24cf,
+ 0x2c00, 0x2c2f,
+ 0x2c60, 0x2c60,
+ 0x2c62, 0x2c64,
+ 0x2c67, 0x2c67,
+ 0x2c69, 0x2c69,
+ 0x2c6b, 0x2c6b,
+ 0x2c6d, 0x2c70,
+ 0x2c72, 0x2c72,
+ 0x2c75, 0x2c75,
+ 0x2c7e, 0x2c80,
+ 0x2c82, 0x2c82,
+ 0x2c84, 0x2c84,
+ 0x2c86, 0x2c86,
+ 0x2c88, 0x2c88,
+ 0x2c8a, 0x2c8a,
+ 0x2c8c, 0x2c8c,
+ 0x2c8e, 0x2c8e,
+ 0x2c90, 0x2c90,
+ 0x2c92, 0x2c92,
+ 0x2c94, 0x2c94,
+ 0x2c96, 0x2c96,
+ 0x2c98, 0x2c98,
+ 0x2c9a, 0x2c9a,
+ 0x2c9c, 0x2c9c,
+ 0x2c9e, 0x2c9e,
+ 0x2ca0, 0x2ca0,
+ 0x2ca2, 0x2ca2,
+ 0x2ca4, 0x2ca4,
+ 0x2ca6, 0x2ca6,
+ 0x2ca8, 0x2ca8,
+ 0x2caa, 0x2caa,
+ 0x2cac, 0x2cac,
+ 0x2cae, 0x2cae,
+ 0x2cb0, 0x2cb0,
+ 0x2cb2, 0x2cb2,
+ 0x2cb4, 0x2cb4,
+ 0x2cb6, 0x2cb6,
+ 0x2cb8, 0x2cb8,
+ 0x2cba, 0x2cba,
+ 0x2cbc, 0x2cbc,
+ 0x2cbe, 0x2cbe,
+ 0x2cc0, 0x2cc0,
+ 0x2cc2, 0x2cc2,
+ 0x2cc4, 0x2cc4,
+ 0x2cc6, 0x2cc6,
+ 0x2cc8, 0x2cc8,
+ 0x2cca, 0x2cca,
+ 0x2ccc, 0x2ccc,
+ 0x2cce, 0x2cce,
+ 0x2cd0, 0x2cd0,
+ 0x2cd2, 0x2cd2,
+ 0x2cd4, 0x2cd4,
+ 0x2cd6, 0x2cd6,
+ 0x2cd8, 0x2cd8,
+ 0x2cda, 0x2cda,
+ 0x2cdc, 0x2cdc,
+ 0x2cde, 0x2cde,
+ 0x2ce0, 0x2ce0,
+ 0x2ce2, 0x2ce2,
+ 0x2ceb, 0x2ceb,
+ 0x2ced, 0x2ced,
+ 0x2cf2, 0x2cf2,
+ 0xa640, 0xa640,
+ 0xa642, 0xa642,
+ 0xa644, 0xa644,
+ 0xa646, 0xa646,
+ 0xa648, 0xa648,
+ 0xa64a, 0xa64a,
+ 0xa64c, 0xa64c,
+ 0xa64e, 0xa64e,
+ 0xa650, 0xa650,
+ 0xa652, 0xa652,
+ 0xa654, 0xa654,
+ 0xa656, 0xa656,
+ 0xa658, 0xa658,
+ 0xa65a, 0xa65a,
+ 0xa65c, 0xa65c,
+ 0xa65e, 0xa65e,
+ 0xa660, 0xa660,
+ 0xa662, 0xa662,
+ 0xa664, 0xa664,
+ 0xa666, 0xa666,
+ 0xa668, 0xa668,
+ 0xa66a, 0xa66a,
+ 0xa66c, 0xa66c,
+ 0xa680, 0xa680,
+ 0xa682, 0xa682,
+ 0xa684, 0xa684,
+ 0xa686, 0xa686,
+ 0xa688, 0xa688,
+ 0xa68a, 0xa68a,
+ 0xa68c, 0xa68c,
+ 0xa68e, 0xa68e,
+ 0xa690, 0xa690,
+ 0xa692, 0xa692,
+ 0xa694, 0xa694,
+ 0xa696, 0xa696,
+ 0xa698, 0xa698,
+ 0xa69a, 0xa69a,
+ 0xa722, 0xa722,
+ 0xa724, 0xa724,
+ 0xa726, 0xa726,
+ 0xa728, 0xa728,
+ 0xa72a, 0xa72a,
+ 0xa72c, 0xa72c,
+ 0xa72e, 0xa72e,
+ 0xa732, 0xa732,
+ 0xa734, 0xa734,
+ 0xa736, 0xa736,
+ 0xa738, 0xa738,
+ 0xa73a, 0xa73a,
+ 0xa73c, 0xa73c,
+ 0xa73e, 0xa73e,
+ 0xa740, 0xa740,
+ 0xa742, 0xa742,
+ 0xa744, 0xa744,
+ 0xa746, 0xa746,
+ 0xa748, 0xa748,
+ 0xa74a, 0xa74a,
+ 0xa74c, 0xa74c,
+ 0xa74e, 0xa74e,
+ 0xa750, 0xa750,
+ 0xa752, 0xa752,
+ 0xa754, 0xa754,
+ 0xa756, 0xa756,
+ 0xa758, 0xa758,
+ 0xa75a, 0xa75a,
+ 0xa75c, 0xa75c,
+ 0xa75e, 0xa75e,
+ 0xa760, 0xa760,
+ 0xa762, 0xa762,
+ 0xa764, 0xa764,
+ 0xa766, 0xa766,
+ 0xa768, 0xa768,
+ 0xa76a, 0xa76a,
+ 0xa76c, 0xa76c,
+ 0xa76e, 0xa76e,
+ 0xa779, 0xa779,
+ 0xa77b, 0xa77b,
+ 0xa77d, 0xa77e,
+ 0xa780, 0xa780,
+ 0xa782, 0xa782,
+ 0xa784, 0xa784,
+ 0xa786, 0xa786,
+ 0xa78b, 0xa78b,
+ 0xa78d, 0xa78d,
+ 0xa790, 0xa790,
+ 0xa792, 0xa792,
+ 0xa796, 0xa796,
+ 0xa798, 0xa798,
+ 0xa79a, 0xa79a,
+ 0xa79c, 0xa79c,
+ 0xa79e, 0xa79e,
+ 0xa7a0, 0xa7a0,
+ 0xa7a2, 0xa7a2,
+ 0xa7a4, 0xa7a4,
+ 0xa7a6, 0xa7a6,
+ 0xa7a8, 0xa7a8,
+ 0xa7aa, 0xa7ae,
+ 0xa7b0, 0xa7b4,
+ 0xa7b6, 0xa7b6,
+ 0xa7b8, 0xa7b8,
+ 0xa7ba, 0xa7ba,
+ 0xa7bc, 0xa7bc,
+ 0xa7be, 0xa7be,
+ 0xa7c0, 0xa7c0,
+ 0xa7c2, 0xa7c2,
+ 0xa7c4, 0xa7c7,
+ 0xa7c9, 0xa7c9,
+ 0xa7cb, 0xa7cc,
+ 0xa7ce, 0xa7ce,
+ 0xa7d0, 0xa7d0,
+ 0xa7d2, 0xa7d2,
+ 0xa7d4, 0xa7d4,
+ 0xa7d6, 0xa7d6,
+ 0xa7d8, 0xa7d8,
+ 0xa7da, 0xa7da,
+ 0xa7dc, 0xa7dc,
+ 0xa7f5, 0xa7f5,
+ 0xff21, 0xff3a,
+ 0x10400, 0x10427,
+ 0x104b0, 0x104d3,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10c80, 0x10cb2,
+ 0x10d50, 0x10d65,
+ 0x118a0, 0x118bf,
+ 0x16e40, 0x16e5f,
+ 0x16ea0, 0x16eb8,
+ 0x1e900, 0x1e921,
+}; /* CR_Changes_When_Lowercased */
+
+/* 'Changes_When_Uppercased': Derived Property */
+static const OnigCodePoint CR_Changes_When_Uppercased[] = {
+ 634,
+ 0x0061, 0x007a,
+ 0x00b5, 0x00b5,
+ 0x00df, 0x00f6,
+ 0x00f8, 0x00ff,
+ 0x0101, 0x0101,
+ 0x0103, 0x0103,
+ 0x0105, 0x0105,
+ 0x0107, 0x0107,
+ 0x0109, 0x0109,
+ 0x010b, 0x010b,
+ 0x010d, 0x010d,
+ 0x010f, 0x010f,
+ 0x0111, 0x0111,
+ 0x0113, 0x0113,
+ 0x0115, 0x0115,
+ 0x0117, 0x0117,
+ 0x0119, 0x0119,
+ 0x011b, 0x011b,
+ 0x011d, 0x011d,
+ 0x011f, 0x011f,
+ 0x0121, 0x0121,
+ 0x0123, 0x0123,
+ 0x0125, 0x0125,
+ 0x0127, 0x0127,
+ 0x0129, 0x0129,
+ 0x012b, 0x012b,
+ 0x012d, 0x012d,
+ 0x012f, 0x012f,
+ 0x0131, 0x0131,
+ 0x0133, 0x0133,
+ 0x0135, 0x0135,
+ 0x0137, 0x0137,
+ 0x013a, 0x013a,
+ 0x013c, 0x013c,
+ 0x013e, 0x013e,
+ 0x0140, 0x0140,
+ 0x0142, 0x0142,
+ 0x0144, 0x0144,
+ 0x0146, 0x0146,
+ 0x0148, 0x0149,
+ 0x014b, 0x014b,
+ 0x014d, 0x014d,
+ 0x014f, 0x014f,
+ 0x0151, 0x0151,
+ 0x0153, 0x0153,
+ 0x0155, 0x0155,
+ 0x0157, 0x0157,
+ 0x0159, 0x0159,
+ 0x015b, 0x015b,
+ 0x015d, 0x015d,
+ 0x015f, 0x015f,
+ 0x0161, 0x0161,
+ 0x0163, 0x0163,
+ 0x0165, 0x0165,
+ 0x0167, 0x0167,
+ 0x0169, 0x0169,
+ 0x016b, 0x016b,
+ 0x016d, 0x016d,
+ 0x016f, 0x016f,
+ 0x0171, 0x0171,
+ 0x0173, 0x0173,
+ 0x0175, 0x0175,
+ 0x0177, 0x0177,
+ 0x017a, 0x017a,
+ 0x017c, 0x017c,
+ 0x017e, 0x0180,
+ 0x0183, 0x0183,
+ 0x0185, 0x0185,
+ 0x0188, 0x0188,
+ 0x018c, 0x018c,
+ 0x0192, 0x0192,
+ 0x0195, 0x0195,
+ 0x0199, 0x019b,
+ 0x019e, 0x019e,
+ 0x01a1, 0x01a1,
+ 0x01a3, 0x01a3,
+ 0x01a5, 0x01a5,
+ 0x01a8, 0x01a8,
+ 0x01ad, 0x01ad,
+ 0x01b0, 0x01b0,
+ 0x01b4, 0x01b4,
+ 0x01b6, 0x01b6,
+ 0x01b9, 0x01b9,
+ 0x01bd, 0x01bd,
+ 0x01bf, 0x01bf,
+ 0x01c5, 0x01c6,
+ 0x01c8, 0x01c9,
+ 0x01cb, 0x01cc,
+ 0x01ce, 0x01ce,
+ 0x01d0, 0x01d0,
+ 0x01d2, 0x01d2,
+ 0x01d4, 0x01d4,
+ 0x01d6, 0x01d6,
+ 0x01d8, 0x01d8,
+ 0x01da, 0x01da,
+ 0x01dc, 0x01dd,
+ 0x01df, 0x01df,
+ 0x01e1, 0x01e1,
+ 0x01e3, 0x01e3,
+ 0x01e5, 0x01e5,
+ 0x01e7, 0x01e7,
+ 0x01e9, 0x01e9,
+ 0x01eb, 0x01eb,
+ 0x01ed, 0x01ed,
+ 0x01ef, 0x01f0,
+ 0x01f2, 0x01f3,
+ 0x01f5, 0x01f5,
+ 0x01f9, 0x01f9,
+ 0x01fb, 0x01fb,
+ 0x01fd, 0x01fd,
+ 0x01ff, 0x01ff,
+ 0x0201, 0x0201,
+ 0x0203, 0x0203,
+ 0x0205, 0x0205,
+ 0x0207, 0x0207,
+ 0x0209, 0x0209,
+ 0x020b, 0x020b,
+ 0x020d, 0x020d,
+ 0x020f, 0x020f,
+ 0x0211, 0x0211,
+ 0x0213, 0x0213,
+ 0x0215, 0x0215,
+ 0x0217, 0x0217,
+ 0x0219, 0x0219,
+ 0x021b, 0x021b,
+ 0x021d, 0x021d,
+ 0x021f, 0x021f,
+ 0x0223, 0x0223,
+ 0x0225, 0x0225,
+ 0x0227, 0x0227,
+ 0x0229, 0x0229,
+ 0x022b, 0x022b,
+ 0x022d, 0x022d,
+ 0x022f, 0x022f,
+ 0x0231, 0x0231,
+ 0x0233, 0x0233,
+ 0x023c, 0x023c,
+ 0x023f, 0x0240,
+ 0x0242, 0x0242,
+ 0x0247, 0x0247,
+ 0x0249, 0x0249,
+ 0x024b, 0x024b,
+ 0x024d, 0x024d,
+ 0x024f, 0x0254,
+ 0x0256, 0x0257,
+ 0x0259, 0x0259,
+ 0x025b, 0x025c,
+ 0x0260, 0x0261,
+ 0x0263, 0x0266,
+ 0x0268, 0x026c,
+ 0x026f, 0x026f,
+ 0x0271, 0x0272,
+ 0x0275, 0x0275,
+ 0x027d, 0x027d,
+ 0x0280, 0x0280,
+ 0x0282, 0x0283,
+ 0x0287, 0x028c,
+ 0x0292, 0x0292,
+ 0x029d, 0x029e,
+ 0x0345, 0x0345,
+ 0x0371, 0x0371,
+ 0x0373, 0x0373,
+ 0x0377, 0x0377,
+ 0x037b, 0x037d,
+ 0x0390, 0x0390,
+ 0x03ac, 0x03ce,
+ 0x03d0, 0x03d1,
+ 0x03d5, 0x03d7,
+ 0x03d9, 0x03d9,
+ 0x03db, 0x03db,
+ 0x03dd, 0x03dd,
+ 0x03df, 0x03df,
+ 0x03e1, 0x03e1,
+ 0x03e3, 0x03e3,
+ 0x03e5, 0x03e5,
+ 0x03e7, 0x03e7,
+ 0x03e9, 0x03e9,
+ 0x03eb, 0x03eb,
+ 0x03ed, 0x03ed,
+ 0x03ef, 0x03f3,
+ 0x03f5, 0x03f5,
+ 0x03f8, 0x03f8,
+ 0x03fb, 0x03fb,
+ 0x0430, 0x045f,
+ 0x0461, 0x0461,
+ 0x0463, 0x0463,
+ 0x0465, 0x0465,
+ 0x0467, 0x0467,
+ 0x0469, 0x0469,
+ 0x046b, 0x046b,
+ 0x046d, 0x046d,
+ 0x046f, 0x046f,
+ 0x0471, 0x0471,
+ 0x0473, 0x0473,
+ 0x0475, 0x0475,
+ 0x0477, 0x0477,
+ 0x0479, 0x0479,
+ 0x047b, 0x047b,
+ 0x047d, 0x047d,
+ 0x047f, 0x047f,
+ 0x0481, 0x0481,
+ 0x048b, 0x048b,
+ 0x048d, 0x048d,
+ 0x048f, 0x048f,
+ 0x0491, 0x0491,
+ 0x0493, 0x0493,
+ 0x0495, 0x0495,
+ 0x0497, 0x0497,
+ 0x0499, 0x0499,
+ 0x049b, 0x049b,
+ 0x049d, 0x049d,
+ 0x049f, 0x049f,
+ 0x04a1, 0x04a1,
+ 0x04a3, 0x04a3,
+ 0x04a5, 0x04a5,
+ 0x04a7, 0x04a7,
+ 0x04a9, 0x04a9,
+ 0x04ab, 0x04ab,
+ 0x04ad, 0x04ad,
+ 0x04af, 0x04af,
+ 0x04b1, 0x04b1,
+ 0x04b3, 0x04b3,
+ 0x04b5, 0x04b5,
+ 0x04b7, 0x04b7,
+ 0x04b9, 0x04b9,
+ 0x04bb, 0x04bb,
+ 0x04bd, 0x04bd,
+ 0x04bf, 0x04bf,
+ 0x04c2, 0x04c2,
+ 0x04c4, 0x04c4,
+ 0x04c6, 0x04c6,
+ 0x04c8, 0x04c8,
+ 0x04ca, 0x04ca,
+ 0x04cc, 0x04cc,
+ 0x04ce, 0x04cf,
+ 0x04d1, 0x04d1,
+ 0x04d3, 0x04d3,
+ 0x04d5, 0x04d5,
+ 0x04d7, 0x04d7,
+ 0x04d9, 0x04d9,
+ 0x04db, 0x04db,
+ 0x04dd, 0x04dd,
+ 0x04df, 0x04df,
+ 0x04e1, 0x04e1,
+ 0x04e3, 0x04e3,
+ 0x04e5, 0x04e5,
+ 0x04e7, 0x04e7,
+ 0x04e9, 0x04e9,
+ 0x04eb, 0x04eb,
+ 0x04ed, 0x04ed,
+ 0x04ef, 0x04ef,
+ 0x04f1, 0x04f1,
+ 0x04f3, 0x04f3,
+ 0x04f5, 0x04f5,
+ 0x04f7, 0x04f7,
+ 0x04f9, 0x04f9,
+ 0x04fb, 0x04fb,
+ 0x04fd, 0x04fd,
+ 0x04ff, 0x04ff,
+ 0x0501, 0x0501,
+ 0x0503, 0x0503,
+ 0x0505, 0x0505,
+ 0x0507, 0x0507,
+ 0x0509, 0x0509,
+ 0x050b, 0x050b,
+ 0x050d, 0x050d,
+ 0x050f, 0x050f,
+ 0x0511, 0x0511,
+ 0x0513, 0x0513,
+ 0x0515, 0x0515,
+ 0x0517, 0x0517,
+ 0x0519, 0x0519,
+ 0x051b, 0x051b,
+ 0x051d, 0x051d,
+ 0x051f, 0x051f,
+ 0x0521, 0x0521,
+ 0x0523, 0x0523,
+ 0x0525, 0x0525,
+ 0x0527, 0x0527,
+ 0x0529, 0x0529,
+ 0x052b, 0x052b,
+ 0x052d, 0x052d,
+ 0x052f, 0x052f,
+ 0x0561, 0x0587,
+ 0x10d0, 0x10fa,
+ 0x10fd, 0x10ff,
+ 0x13f8, 0x13fd,
+ 0x1c80, 0x1c88,
+ 0x1c8a, 0x1c8a,
+ 0x1d79, 0x1d79,
+ 0x1d7d, 0x1d7d,
+ 0x1d8e, 0x1d8e,
+ 0x1e01, 0x1e01,
+ 0x1e03, 0x1e03,
+ 0x1e05, 0x1e05,
+ 0x1e07, 0x1e07,
+ 0x1e09, 0x1e09,
+ 0x1e0b, 0x1e0b,
+ 0x1e0d, 0x1e0d,
+ 0x1e0f, 0x1e0f,
+ 0x1e11, 0x1e11,
+ 0x1e13, 0x1e13,
+ 0x1e15, 0x1e15,
+ 0x1e17, 0x1e17,
+ 0x1e19, 0x1e19,
+ 0x1e1b, 0x1e1b,
+ 0x1e1d, 0x1e1d,
+ 0x1e1f, 0x1e1f,
+ 0x1e21, 0x1e21,
+ 0x1e23, 0x1e23,
+ 0x1e25, 0x1e25,
+ 0x1e27, 0x1e27,
+ 0x1e29, 0x1e29,
+ 0x1e2b, 0x1e2b,
+ 0x1e2d, 0x1e2d,
+ 0x1e2f, 0x1e2f,
+ 0x1e31, 0x1e31,
+ 0x1e33, 0x1e33,
+ 0x1e35, 0x1e35,
+ 0x1e37, 0x1e37,
+ 0x1e39, 0x1e39,
+ 0x1e3b, 0x1e3b,
+ 0x1e3d, 0x1e3d,
+ 0x1e3f, 0x1e3f,
+ 0x1e41, 0x1e41,
+ 0x1e43, 0x1e43,
+ 0x1e45, 0x1e45,
+ 0x1e47, 0x1e47,
+ 0x1e49, 0x1e49,
+ 0x1e4b, 0x1e4b,
+ 0x1e4d, 0x1e4d,
+ 0x1e4f, 0x1e4f,
+ 0x1e51, 0x1e51,
+ 0x1e53, 0x1e53,
+ 0x1e55, 0x1e55,
+ 0x1e57, 0x1e57,
+ 0x1e59, 0x1e59,
+ 0x1e5b, 0x1e5b,
+ 0x1e5d, 0x1e5d,
+ 0x1e5f, 0x1e5f,
+ 0x1e61, 0x1e61,
+ 0x1e63, 0x1e63,
+ 0x1e65, 0x1e65,
+ 0x1e67, 0x1e67,
+ 0x1e69, 0x1e69,
+ 0x1e6b, 0x1e6b,
+ 0x1e6d, 0x1e6d,
+ 0x1e6f, 0x1e6f,
+ 0x1e71, 0x1e71,
+ 0x1e73, 0x1e73,
+ 0x1e75, 0x1e75,
+ 0x1e77, 0x1e77,
+ 0x1e79, 0x1e79,
+ 0x1e7b, 0x1e7b,
+ 0x1e7d, 0x1e7d,
+ 0x1e7f, 0x1e7f,
+ 0x1e81, 0x1e81,
+ 0x1e83, 0x1e83,
+ 0x1e85, 0x1e85,
+ 0x1e87, 0x1e87,
+ 0x1e89, 0x1e89,
+ 0x1e8b, 0x1e8b,
+ 0x1e8d, 0x1e8d,
+ 0x1e8f, 0x1e8f,
+ 0x1e91, 0x1e91,
+ 0x1e93, 0x1e93,
+ 0x1e95, 0x1e9b,
+ 0x1ea1, 0x1ea1,
+ 0x1ea3, 0x1ea3,
+ 0x1ea5, 0x1ea5,
+ 0x1ea7, 0x1ea7,
+ 0x1ea9, 0x1ea9,
+ 0x1eab, 0x1eab,
+ 0x1ead, 0x1ead,
+ 0x1eaf, 0x1eaf,
+ 0x1eb1, 0x1eb1,
+ 0x1eb3, 0x1eb3,
+ 0x1eb5, 0x1eb5,
+ 0x1eb7, 0x1eb7,
+ 0x1eb9, 0x1eb9,
+ 0x1ebb, 0x1ebb,
+ 0x1ebd, 0x1ebd,
+ 0x1ebf, 0x1ebf,
+ 0x1ec1, 0x1ec1,
+ 0x1ec3, 0x1ec3,
+ 0x1ec5, 0x1ec5,
+ 0x1ec7, 0x1ec7,
+ 0x1ec9, 0x1ec9,
+ 0x1ecb, 0x1ecb,
+ 0x1ecd, 0x1ecd,
+ 0x1ecf, 0x1ecf,
+ 0x1ed1, 0x1ed1,
+ 0x1ed3, 0x1ed3,
+ 0x1ed5, 0x1ed5,
+ 0x1ed7, 0x1ed7,
+ 0x1ed9, 0x1ed9,
+ 0x1edb, 0x1edb,
+ 0x1edd, 0x1edd,
+ 0x1edf, 0x1edf,
+ 0x1ee1, 0x1ee1,
+ 0x1ee3, 0x1ee3,
+ 0x1ee5, 0x1ee5,
+ 0x1ee7, 0x1ee7,
+ 0x1ee9, 0x1ee9,
+ 0x1eeb, 0x1eeb,
+ 0x1eed, 0x1eed,
+ 0x1eef, 0x1eef,
+ 0x1ef1, 0x1ef1,
+ 0x1ef3, 0x1ef3,
+ 0x1ef5, 0x1ef5,
+ 0x1ef7, 0x1ef7,
+ 0x1ef9, 0x1ef9,
+ 0x1efb, 0x1efb,
+ 0x1efd, 0x1efd,
+ 0x1eff, 0x1f07,
+ 0x1f10, 0x1f15,
+ 0x1f20, 0x1f27,
+ 0x1f30, 0x1f37,
+ 0x1f40, 0x1f45,
+ 0x1f50, 0x1f57,
+ 0x1f60, 0x1f67,
+ 0x1f70, 0x1f7d,
+ 0x1f80, 0x1fb4,
+ 0x1fb6, 0x1fb7,
+ 0x1fbc, 0x1fbc,
+ 0x1fbe, 0x1fbe,
+ 0x1fc2, 0x1fc4,
+ 0x1fc6, 0x1fc7,
+ 0x1fcc, 0x1fcc,
+ 0x1fd0, 0x1fd3,
+ 0x1fd6, 0x1fd7,
+ 0x1fe0, 0x1fe7,
+ 0x1ff2, 0x1ff4,
+ 0x1ff6, 0x1ff7,
+ 0x1ffc, 0x1ffc,
+ 0x214e, 0x214e,
+ 0x2170, 0x217f,
+ 0x2184, 0x2184,
+ 0x24d0, 0x24e9,
+ 0x2c30, 0x2c5f,
+ 0x2c61, 0x2c61,
+ 0x2c65, 0x2c66,
+ 0x2c68, 0x2c68,
+ 0x2c6a, 0x2c6a,
+ 0x2c6c, 0x2c6c,
+ 0x2c73, 0x2c73,
+ 0x2c76, 0x2c76,
+ 0x2c81, 0x2c81,
+ 0x2c83, 0x2c83,
+ 0x2c85, 0x2c85,
+ 0x2c87, 0x2c87,
+ 0x2c89, 0x2c89,
+ 0x2c8b, 0x2c8b,
+ 0x2c8d, 0x2c8d,
+ 0x2c8f, 0x2c8f,
+ 0x2c91, 0x2c91,
+ 0x2c93, 0x2c93,
+ 0x2c95, 0x2c95,
+ 0x2c97, 0x2c97,
+ 0x2c99, 0x2c99,
+ 0x2c9b, 0x2c9b,
+ 0x2c9d, 0x2c9d,
+ 0x2c9f, 0x2c9f,
+ 0x2ca1, 0x2ca1,
+ 0x2ca3, 0x2ca3,
+ 0x2ca5, 0x2ca5,
+ 0x2ca7, 0x2ca7,
+ 0x2ca9, 0x2ca9,
+ 0x2cab, 0x2cab,
+ 0x2cad, 0x2cad,
+ 0x2caf, 0x2caf,
+ 0x2cb1, 0x2cb1,
+ 0x2cb3, 0x2cb3,
+ 0x2cb5, 0x2cb5,
+ 0x2cb7, 0x2cb7,
+ 0x2cb9, 0x2cb9,
+ 0x2cbb, 0x2cbb,
+ 0x2cbd, 0x2cbd,
+ 0x2cbf, 0x2cbf,
+ 0x2cc1, 0x2cc1,
+ 0x2cc3, 0x2cc3,
+ 0x2cc5, 0x2cc5,
+ 0x2cc7, 0x2cc7,
+ 0x2cc9, 0x2cc9,
+ 0x2ccb, 0x2ccb,
+ 0x2ccd, 0x2ccd,
+ 0x2ccf, 0x2ccf,
+ 0x2cd1, 0x2cd1,
+ 0x2cd3, 0x2cd3,
+ 0x2cd5, 0x2cd5,
+ 0x2cd7, 0x2cd7,
+ 0x2cd9, 0x2cd9,
+ 0x2cdb, 0x2cdb,
+ 0x2cdd, 0x2cdd,
+ 0x2cdf, 0x2cdf,
+ 0x2ce1, 0x2ce1,
+ 0x2ce3, 0x2ce3,
+ 0x2cec, 0x2cec,
+ 0x2cee, 0x2cee,
+ 0x2cf3, 0x2cf3,
+ 0x2d00, 0x2d25,
+ 0x2d27, 0x2d27,
+ 0x2d2d, 0x2d2d,
+ 0xa641, 0xa641,
+ 0xa643, 0xa643,
+ 0xa645, 0xa645,
+ 0xa647, 0xa647,
+ 0xa649, 0xa649,
+ 0xa64b, 0xa64b,
+ 0xa64d, 0xa64d,
+ 0xa64f, 0xa64f,
+ 0xa651, 0xa651,
+ 0xa653, 0xa653,
+ 0xa655, 0xa655,
+ 0xa657, 0xa657,
+ 0xa659, 0xa659,
+ 0xa65b, 0xa65b,
+ 0xa65d, 0xa65d,
+ 0xa65f, 0xa65f,
+ 0xa661, 0xa661,
+ 0xa663, 0xa663,
+ 0xa665, 0xa665,
+ 0xa667, 0xa667,
+ 0xa669, 0xa669,
+ 0xa66b, 0xa66b,
+ 0xa66d, 0xa66d,
+ 0xa681, 0xa681,
+ 0xa683, 0xa683,
+ 0xa685, 0xa685,
+ 0xa687, 0xa687,
+ 0xa689, 0xa689,
+ 0xa68b, 0xa68b,
+ 0xa68d, 0xa68d,
+ 0xa68f, 0xa68f,
+ 0xa691, 0xa691,
+ 0xa693, 0xa693,
+ 0xa695, 0xa695,
+ 0xa697, 0xa697,
+ 0xa699, 0xa699,
+ 0xa69b, 0xa69b,
+ 0xa723, 0xa723,
+ 0xa725, 0xa725,
+ 0xa727, 0xa727,
+ 0xa729, 0xa729,
+ 0xa72b, 0xa72b,
+ 0xa72d, 0xa72d,
+ 0xa72f, 0xa72f,
+ 0xa733, 0xa733,
+ 0xa735, 0xa735,
+ 0xa737, 0xa737,
+ 0xa739, 0xa739,
+ 0xa73b, 0xa73b,
+ 0xa73d, 0xa73d,
+ 0xa73f, 0xa73f,
+ 0xa741, 0xa741,
+ 0xa743, 0xa743,
+ 0xa745, 0xa745,
+ 0xa747, 0xa747,
+ 0xa749, 0xa749,
+ 0xa74b, 0xa74b,
+ 0xa74d, 0xa74d,
+ 0xa74f, 0xa74f,
+ 0xa751, 0xa751,
+ 0xa753, 0xa753,
+ 0xa755, 0xa755,
+ 0xa757, 0xa757,
+ 0xa759, 0xa759,
+ 0xa75b, 0xa75b,
+ 0xa75d, 0xa75d,
+ 0xa75f, 0xa75f,
+ 0xa761, 0xa761,
+ 0xa763, 0xa763,
+ 0xa765, 0xa765,
+ 0xa767, 0xa767,
+ 0xa769, 0xa769,
+ 0xa76b, 0xa76b,
+ 0xa76d, 0xa76d,
+ 0xa76f, 0xa76f,
+ 0xa77a, 0xa77a,
+ 0xa77c, 0xa77c,
+ 0xa77f, 0xa77f,
+ 0xa781, 0xa781,
+ 0xa783, 0xa783,
+ 0xa785, 0xa785,
+ 0xa787, 0xa787,
+ 0xa78c, 0xa78c,
+ 0xa791, 0xa791,
+ 0xa793, 0xa794,
+ 0xa797, 0xa797,
+ 0xa799, 0xa799,
+ 0xa79b, 0xa79b,
+ 0xa79d, 0xa79d,
+ 0xa79f, 0xa79f,
+ 0xa7a1, 0xa7a1,
+ 0xa7a3, 0xa7a3,
+ 0xa7a5, 0xa7a5,
+ 0xa7a7, 0xa7a7,
+ 0xa7a9, 0xa7a9,
+ 0xa7b5, 0xa7b5,
+ 0xa7b7, 0xa7b7,
+ 0xa7b9, 0xa7b9,
+ 0xa7bb, 0xa7bb,
+ 0xa7bd, 0xa7bd,
+ 0xa7bf, 0xa7bf,
+ 0xa7c1, 0xa7c1,
+ 0xa7c3, 0xa7c3,
+ 0xa7c8, 0xa7c8,
+ 0xa7ca, 0xa7ca,
+ 0xa7cd, 0xa7cd,
+ 0xa7cf, 0xa7cf,
+ 0xa7d1, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d5,
+ 0xa7d7, 0xa7d7,
+ 0xa7d9, 0xa7d9,
+ 0xa7db, 0xa7db,
+ 0xa7f6, 0xa7f6,
+ 0xab53, 0xab53,
+ 0xab70, 0xabbf,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xff41, 0xff5a,
+ 0x10428, 0x1044f,
+ 0x104d8, 0x104fb,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x10cc0, 0x10cf2,
+ 0x10d70, 0x10d85,
+ 0x118c0, 0x118df,
+ 0x16e60, 0x16e7f,
+ 0x16ebb, 0x16ed3,
+ 0x1e922, 0x1e943,
+}; /* CR_Changes_When_Uppercased */
+
+/* 'Changes_When_Titlecased': Derived Property */
+static const OnigCodePoint CR_Changes_When_Titlecased[] = {
+ 633,
+ 0x0061, 0x007a,
+ 0x00b5, 0x00b5,
+ 0x00df, 0x00f6,
+ 0x00f8, 0x00ff,
+ 0x0101, 0x0101,
+ 0x0103, 0x0103,
+ 0x0105, 0x0105,
+ 0x0107, 0x0107,
+ 0x0109, 0x0109,
+ 0x010b, 0x010b,
+ 0x010d, 0x010d,
+ 0x010f, 0x010f,
+ 0x0111, 0x0111,
+ 0x0113, 0x0113,
+ 0x0115, 0x0115,
+ 0x0117, 0x0117,
+ 0x0119, 0x0119,
+ 0x011b, 0x011b,
+ 0x011d, 0x011d,
+ 0x011f, 0x011f,
+ 0x0121, 0x0121,
+ 0x0123, 0x0123,
+ 0x0125, 0x0125,
+ 0x0127, 0x0127,
+ 0x0129, 0x0129,
+ 0x012b, 0x012b,
+ 0x012d, 0x012d,
+ 0x012f, 0x012f,
+ 0x0131, 0x0131,
+ 0x0133, 0x0133,
+ 0x0135, 0x0135,
+ 0x0137, 0x0137,
+ 0x013a, 0x013a,
+ 0x013c, 0x013c,
+ 0x013e, 0x013e,
+ 0x0140, 0x0140,
+ 0x0142, 0x0142,
+ 0x0144, 0x0144,
+ 0x0146, 0x0146,
+ 0x0148, 0x0149,
+ 0x014b, 0x014b,
+ 0x014d, 0x014d,
+ 0x014f, 0x014f,
+ 0x0151, 0x0151,
+ 0x0153, 0x0153,
+ 0x0155, 0x0155,
+ 0x0157, 0x0157,
+ 0x0159, 0x0159,
+ 0x015b, 0x015b,
+ 0x015d, 0x015d,
+ 0x015f, 0x015f,
+ 0x0161, 0x0161,
+ 0x0163, 0x0163,
+ 0x0165, 0x0165,
+ 0x0167, 0x0167,
+ 0x0169, 0x0169,
+ 0x016b, 0x016b,
+ 0x016d, 0x016d,
+ 0x016f, 0x016f,
+ 0x0171, 0x0171,
+ 0x0173, 0x0173,
+ 0x0175, 0x0175,
+ 0x0177, 0x0177,
+ 0x017a, 0x017a,
+ 0x017c, 0x017c,
+ 0x017e, 0x0180,
+ 0x0183, 0x0183,
+ 0x0185, 0x0185,
+ 0x0188, 0x0188,
+ 0x018c, 0x018c,
+ 0x0192, 0x0192,
+ 0x0195, 0x0195,
+ 0x0199, 0x019b,
+ 0x019e, 0x019e,
+ 0x01a1, 0x01a1,
+ 0x01a3, 0x01a3,
+ 0x01a5, 0x01a5,
+ 0x01a8, 0x01a8,
+ 0x01ad, 0x01ad,
+ 0x01b0, 0x01b0,
+ 0x01b4, 0x01b4,
+ 0x01b6, 0x01b6,
+ 0x01b9, 0x01b9,
+ 0x01bd, 0x01bd,
+ 0x01bf, 0x01bf,
+ 0x01c4, 0x01c4,
+ 0x01c6, 0x01c7,
+ 0x01c9, 0x01ca,
+ 0x01cc, 0x01cc,
+ 0x01ce, 0x01ce,
+ 0x01d0, 0x01d0,
+ 0x01d2, 0x01d2,
+ 0x01d4, 0x01d4,
+ 0x01d6, 0x01d6,
+ 0x01d8, 0x01d8,
+ 0x01da, 0x01da,
+ 0x01dc, 0x01dd,
+ 0x01df, 0x01df,
+ 0x01e1, 0x01e1,
+ 0x01e3, 0x01e3,
+ 0x01e5, 0x01e5,
+ 0x01e7, 0x01e7,
+ 0x01e9, 0x01e9,
+ 0x01eb, 0x01eb,
+ 0x01ed, 0x01ed,
+ 0x01ef, 0x01f1,
+ 0x01f3, 0x01f3,
+ 0x01f5, 0x01f5,
+ 0x01f9, 0x01f9,
+ 0x01fb, 0x01fb,
+ 0x01fd, 0x01fd,
+ 0x01ff, 0x01ff,
+ 0x0201, 0x0201,
+ 0x0203, 0x0203,
+ 0x0205, 0x0205,
+ 0x0207, 0x0207,
+ 0x0209, 0x0209,
+ 0x020b, 0x020b,
+ 0x020d, 0x020d,
+ 0x020f, 0x020f,
+ 0x0211, 0x0211,
+ 0x0213, 0x0213,
+ 0x0215, 0x0215,
+ 0x0217, 0x0217,
+ 0x0219, 0x0219,
+ 0x021b, 0x021b,
+ 0x021d, 0x021d,
+ 0x021f, 0x021f,
+ 0x0223, 0x0223,
+ 0x0225, 0x0225,
+ 0x0227, 0x0227,
+ 0x0229, 0x0229,
+ 0x022b, 0x022b,
+ 0x022d, 0x022d,
+ 0x022f, 0x022f,
+ 0x0231, 0x0231,
+ 0x0233, 0x0233,
+ 0x023c, 0x023c,
+ 0x023f, 0x0240,
+ 0x0242, 0x0242,
+ 0x0247, 0x0247,
+ 0x0249, 0x0249,
+ 0x024b, 0x024b,
+ 0x024d, 0x024d,
+ 0x024f, 0x0254,
+ 0x0256, 0x0257,
+ 0x0259, 0x0259,
+ 0x025b, 0x025c,
+ 0x0260, 0x0261,
+ 0x0263, 0x0266,
+ 0x0268, 0x026c,
+ 0x026f, 0x026f,
+ 0x0271, 0x0272,
+ 0x0275, 0x0275,
+ 0x027d, 0x027d,
+ 0x0280, 0x0280,
+ 0x0282, 0x0283,
+ 0x0287, 0x028c,
+ 0x0292, 0x0292,
+ 0x029d, 0x029e,
+ 0x0345, 0x0345,
+ 0x0371, 0x0371,
+ 0x0373, 0x0373,
+ 0x0377, 0x0377,
+ 0x037b, 0x037d,
+ 0x0390, 0x0390,
+ 0x03ac, 0x03ce,
+ 0x03d0, 0x03d1,
+ 0x03d5, 0x03d7,
+ 0x03d9, 0x03d9,
+ 0x03db, 0x03db,
+ 0x03dd, 0x03dd,
+ 0x03df, 0x03df,
+ 0x03e1, 0x03e1,
+ 0x03e3, 0x03e3,
+ 0x03e5, 0x03e5,
+ 0x03e7, 0x03e7,
+ 0x03e9, 0x03e9,
+ 0x03eb, 0x03eb,
+ 0x03ed, 0x03ed,
+ 0x03ef, 0x03f3,
+ 0x03f5, 0x03f5,
+ 0x03f8, 0x03f8,
+ 0x03fb, 0x03fb,
+ 0x0430, 0x045f,
+ 0x0461, 0x0461,
+ 0x0463, 0x0463,
+ 0x0465, 0x0465,
+ 0x0467, 0x0467,
+ 0x0469, 0x0469,
+ 0x046b, 0x046b,
+ 0x046d, 0x046d,
+ 0x046f, 0x046f,
+ 0x0471, 0x0471,
+ 0x0473, 0x0473,
+ 0x0475, 0x0475,
+ 0x0477, 0x0477,
+ 0x0479, 0x0479,
+ 0x047b, 0x047b,
+ 0x047d, 0x047d,
+ 0x047f, 0x047f,
+ 0x0481, 0x0481,
+ 0x048b, 0x048b,
+ 0x048d, 0x048d,
+ 0x048f, 0x048f,
+ 0x0491, 0x0491,
+ 0x0493, 0x0493,
+ 0x0495, 0x0495,
+ 0x0497, 0x0497,
+ 0x0499, 0x0499,
+ 0x049b, 0x049b,
+ 0x049d, 0x049d,
+ 0x049f, 0x049f,
+ 0x04a1, 0x04a1,
+ 0x04a3, 0x04a3,
+ 0x04a5, 0x04a5,
+ 0x04a7, 0x04a7,
+ 0x04a9, 0x04a9,
+ 0x04ab, 0x04ab,
+ 0x04ad, 0x04ad,
+ 0x04af, 0x04af,
+ 0x04b1, 0x04b1,
+ 0x04b3, 0x04b3,
+ 0x04b5, 0x04b5,
+ 0x04b7, 0x04b7,
+ 0x04b9, 0x04b9,
+ 0x04bb, 0x04bb,
+ 0x04bd, 0x04bd,
+ 0x04bf, 0x04bf,
+ 0x04c2, 0x04c2,
+ 0x04c4, 0x04c4,
+ 0x04c6, 0x04c6,
+ 0x04c8, 0x04c8,
+ 0x04ca, 0x04ca,
+ 0x04cc, 0x04cc,
+ 0x04ce, 0x04cf,
+ 0x04d1, 0x04d1,
+ 0x04d3, 0x04d3,
+ 0x04d5, 0x04d5,
+ 0x04d7, 0x04d7,
+ 0x04d9, 0x04d9,
+ 0x04db, 0x04db,
+ 0x04dd, 0x04dd,
+ 0x04df, 0x04df,
+ 0x04e1, 0x04e1,
+ 0x04e3, 0x04e3,
+ 0x04e5, 0x04e5,
+ 0x04e7, 0x04e7,
+ 0x04e9, 0x04e9,
+ 0x04eb, 0x04eb,
+ 0x04ed, 0x04ed,
+ 0x04ef, 0x04ef,
+ 0x04f1, 0x04f1,
+ 0x04f3, 0x04f3,
+ 0x04f5, 0x04f5,
+ 0x04f7, 0x04f7,
+ 0x04f9, 0x04f9,
+ 0x04fb, 0x04fb,
+ 0x04fd, 0x04fd,
+ 0x04ff, 0x04ff,
+ 0x0501, 0x0501,
+ 0x0503, 0x0503,
+ 0x0505, 0x0505,
+ 0x0507, 0x0507,
+ 0x0509, 0x0509,
+ 0x050b, 0x050b,
+ 0x050d, 0x050d,
+ 0x050f, 0x050f,
+ 0x0511, 0x0511,
+ 0x0513, 0x0513,
+ 0x0515, 0x0515,
+ 0x0517, 0x0517,
+ 0x0519, 0x0519,
+ 0x051b, 0x051b,
+ 0x051d, 0x051d,
+ 0x051f, 0x051f,
+ 0x0521, 0x0521,
+ 0x0523, 0x0523,
+ 0x0525, 0x0525,
+ 0x0527, 0x0527,
+ 0x0529, 0x0529,
+ 0x052b, 0x052b,
+ 0x052d, 0x052d,
+ 0x052f, 0x052f,
+ 0x0561, 0x0587,
+ 0x13f8, 0x13fd,
+ 0x1c80, 0x1c88,
+ 0x1c8a, 0x1c8a,
+ 0x1d79, 0x1d79,
+ 0x1d7d, 0x1d7d,
+ 0x1d8e, 0x1d8e,
+ 0x1e01, 0x1e01,
+ 0x1e03, 0x1e03,
+ 0x1e05, 0x1e05,
+ 0x1e07, 0x1e07,
+ 0x1e09, 0x1e09,
+ 0x1e0b, 0x1e0b,
+ 0x1e0d, 0x1e0d,
+ 0x1e0f, 0x1e0f,
+ 0x1e11, 0x1e11,
+ 0x1e13, 0x1e13,
+ 0x1e15, 0x1e15,
+ 0x1e17, 0x1e17,
+ 0x1e19, 0x1e19,
+ 0x1e1b, 0x1e1b,
+ 0x1e1d, 0x1e1d,
+ 0x1e1f, 0x1e1f,
+ 0x1e21, 0x1e21,
+ 0x1e23, 0x1e23,
+ 0x1e25, 0x1e25,
+ 0x1e27, 0x1e27,
+ 0x1e29, 0x1e29,
+ 0x1e2b, 0x1e2b,
+ 0x1e2d, 0x1e2d,
+ 0x1e2f, 0x1e2f,
+ 0x1e31, 0x1e31,
+ 0x1e33, 0x1e33,
+ 0x1e35, 0x1e35,
+ 0x1e37, 0x1e37,
+ 0x1e39, 0x1e39,
+ 0x1e3b, 0x1e3b,
+ 0x1e3d, 0x1e3d,
+ 0x1e3f, 0x1e3f,
+ 0x1e41, 0x1e41,
+ 0x1e43, 0x1e43,
+ 0x1e45, 0x1e45,
+ 0x1e47, 0x1e47,
+ 0x1e49, 0x1e49,
+ 0x1e4b, 0x1e4b,
+ 0x1e4d, 0x1e4d,
+ 0x1e4f, 0x1e4f,
+ 0x1e51, 0x1e51,
+ 0x1e53, 0x1e53,
+ 0x1e55, 0x1e55,
+ 0x1e57, 0x1e57,
+ 0x1e59, 0x1e59,
+ 0x1e5b, 0x1e5b,
+ 0x1e5d, 0x1e5d,
+ 0x1e5f, 0x1e5f,
+ 0x1e61, 0x1e61,
+ 0x1e63, 0x1e63,
+ 0x1e65, 0x1e65,
+ 0x1e67, 0x1e67,
+ 0x1e69, 0x1e69,
+ 0x1e6b, 0x1e6b,
+ 0x1e6d, 0x1e6d,
+ 0x1e6f, 0x1e6f,
+ 0x1e71, 0x1e71,
+ 0x1e73, 0x1e73,
+ 0x1e75, 0x1e75,
+ 0x1e77, 0x1e77,
+ 0x1e79, 0x1e79,
+ 0x1e7b, 0x1e7b,
+ 0x1e7d, 0x1e7d,
+ 0x1e7f, 0x1e7f,
+ 0x1e81, 0x1e81,
+ 0x1e83, 0x1e83,
+ 0x1e85, 0x1e85,
+ 0x1e87, 0x1e87,
+ 0x1e89, 0x1e89,
+ 0x1e8b, 0x1e8b,
+ 0x1e8d, 0x1e8d,
+ 0x1e8f, 0x1e8f,
+ 0x1e91, 0x1e91,
+ 0x1e93, 0x1e93,
+ 0x1e95, 0x1e9b,
+ 0x1ea1, 0x1ea1,
+ 0x1ea3, 0x1ea3,
+ 0x1ea5, 0x1ea5,
+ 0x1ea7, 0x1ea7,
+ 0x1ea9, 0x1ea9,
+ 0x1eab, 0x1eab,
+ 0x1ead, 0x1ead,
+ 0x1eaf, 0x1eaf,
+ 0x1eb1, 0x1eb1,
+ 0x1eb3, 0x1eb3,
+ 0x1eb5, 0x1eb5,
+ 0x1eb7, 0x1eb7,
+ 0x1eb9, 0x1eb9,
+ 0x1ebb, 0x1ebb,
+ 0x1ebd, 0x1ebd,
+ 0x1ebf, 0x1ebf,
+ 0x1ec1, 0x1ec1,
+ 0x1ec3, 0x1ec3,
+ 0x1ec5, 0x1ec5,
+ 0x1ec7, 0x1ec7,
+ 0x1ec9, 0x1ec9,
+ 0x1ecb, 0x1ecb,
+ 0x1ecd, 0x1ecd,
+ 0x1ecf, 0x1ecf,
+ 0x1ed1, 0x1ed1,
+ 0x1ed3, 0x1ed3,
+ 0x1ed5, 0x1ed5,
+ 0x1ed7, 0x1ed7,
+ 0x1ed9, 0x1ed9,
+ 0x1edb, 0x1edb,
+ 0x1edd, 0x1edd,
+ 0x1edf, 0x1edf,
+ 0x1ee1, 0x1ee1,
+ 0x1ee3, 0x1ee3,
+ 0x1ee5, 0x1ee5,
+ 0x1ee7, 0x1ee7,
+ 0x1ee9, 0x1ee9,
+ 0x1eeb, 0x1eeb,
+ 0x1eed, 0x1eed,
+ 0x1eef, 0x1eef,
+ 0x1ef1, 0x1ef1,
+ 0x1ef3, 0x1ef3,
+ 0x1ef5, 0x1ef5,
+ 0x1ef7, 0x1ef7,
+ 0x1ef9, 0x1ef9,
+ 0x1efb, 0x1efb,
+ 0x1efd, 0x1efd,
+ 0x1eff, 0x1f07,
+ 0x1f10, 0x1f15,
+ 0x1f20, 0x1f27,
+ 0x1f30, 0x1f37,
+ 0x1f40, 0x1f45,
+ 0x1f50, 0x1f57,
+ 0x1f60, 0x1f67,
+ 0x1f70, 0x1f7d,
+ 0x1f80, 0x1f87,
+ 0x1f90, 0x1f97,
+ 0x1fa0, 0x1fa7,
+ 0x1fb0, 0x1fb4,
+ 0x1fb6, 0x1fb7,
+ 0x1fbe, 0x1fbe,
+ 0x1fc2, 0x1fc4,
+ 0x1fc6, 0x1fc7,
+ 0x1fd0, 0x1fd3,
+ 0x1fd6, 0x1fd7,
+ 0x1fe0, 0x1fe7,
+ 0x1ff2, 0x1ff4,
+ 0x1ff6, 0x1ff7,
+ 0x214e, 0x214e,
+ 0x2170, 0x217f,
+ 0x2184, 0x2184,
+ 0x24d0, 0x24e9,
+ 0x2c30, 0x2c5f,
+ 0x2c61, 0x2c61,
+ 0x2c65, 0x2c66,
+ 0x2c68, 0x2c68,
+ 0x2c6a, 0x2c6a,
+ 0x2c6c, 0x2c6c,
+ 0x2c73, 0x2c73,
+ 0x2c76, 0x2c76,
+ 0x2c81, 0x2c81,
+ 0x2c83, 0x2c83,
+ 0x2c85, 0x2c85,
+ 0x2c87, 0x2c87,
+ 0x2c89, 0x2c89,
+ 0x2c8b, 0x2c8b,
+ 0x2c8d, 0x2c8d,
+ 0x2c8f, 0x2c8f,
+ 0x2c91, 0x2c91,
+ 0x2c93, 0x2c93,
+ 0x2c95, 0x2c95,
+ 0x2c97, 0x2c97,
+ 0x2c99, 0x2c99,
+ 0x2c9b, 0x2c9b,
+ 0x2c9d, 0x2c9d,
+ 0x2c9f, 0x2c9f,
+ 0x2ca1, 0x2ca1,
+ 0x2ca3, 0x2ca3,
+ 0x2ca5, 0x2ca5,
+ 0x2ca7, 0x2ca7,
+ 0x2ca9, 0x2ca9,
+ 0x2cab, 0x2cab,
+ 0x2cad, 0x2cad,
+ 0x2caf, 0x2caf,
+ 0x2cb1, 0x2cb1,
+ 0x2cb3, 0x2cb3,
+ 0x2cb5, 0x2cb5,
+ 0x2cb7, 0x2cb7,
+ 0x2cb9, 0x2cb9,
+ 0x2cbb, 0x2cbb,
+ 0x2cbd, 0x2cbd,
+ 0x2cbf, 0x2cbf,
+ 0x2cc1, 0x2cc1,
+ 0x2cc3, 0x2cc3,
+ 0x2cc5, 0x2cc5,
+ 0x2cc7, 0x2cc7,
+ 0x2cc9, 0x2cc9,
+ 0x2ccb, 0x2ccb,
+ 0x2ccd, 0x2ccd,
+ 0x2ccf, 0x2ccf,
+ 0x2cd1, 0x2cd1,
+ 0x2cd3, 0x2cd3,
+ 0x2cd5, 0x2cd5,
+ 0x2cd7, 0x2cd7,
+ 0x2cd9, 0x2cd9,
+ 0x2cdb, 0x2cdb,
+ 0x2cdd, 0x2cdd,
+ 0x2cdf, 0x2cdf,
+ 0x2ce1, 0x2ce1,
+ 0x2ce3, 0x2ce3,
+ 0x2cec, 0x2cec,
+ 0x2cee, 0x2cee,
+ 0x2cf3, 0x2cf3,
+ 0x2d00, 0x2d25,
+ 0x2d27, 0x2d27,
+ 0x2d2d, 0x2d2d,
+ 0xa641, 0xa641,
+ 0xa643, 0xa643,
+ 0xa645, 0xa645,
+ 0xa647, 0xa647,
+ 0xa649, 0xa649,
+ 0xa64b, 0xa64b,
+ 0xa64d, 0xa64d,
+ 0xa64f, 0xa64f,
+ 0xa651, 0xa651,
+ 0xa653, 0xa653,
+ 0xa655, 0xa655,
+ 0xa657, 0xa657,
+ 0xa659, 0xa659,
+ 0xa65b, 0xa65b,
+ 0xa65d, 0xa65d,
+ 0xa65f, 0xa65f,
+ 0xa661, 0xa661,
+ 0xa663, 0xa663,
+ 0xa665, 0xa665,
+ 0xa667, 0xa667,
+ 0xa669, 0xa669,
+ 0xa66b, 0xa66b,
+ 0xa66d, 0xa66d,
+ 0xa681, 0xa681,
+ 0xa683, 0xa683,
+ 0xa685, 0xa685,
+ 0xa687, 0xa687,
+ 0xa689, 0xa689,
+ 0xa68b, 0xa68b,
+ 0xa68d, 0xa68d,
+ 0xa68f, 0xa68f,
+ 0xa691, 0xa691,
+ 0xa693, 0xa693,
+ 0xa695, 0xa695,
+ 0xa697, 0xa697,
+ 0xa699, 0xa699,
+ 0xa69b, 0xa69b,
+ 0xa723, 0xa723,
+ 0xa725, 0xa725,
+ 0xa727, 0xa727,
+ 0xa729, 0xa729,
+ 0xa72b, 0xa72b,
+ 0xa72d, 0xa72d,
+ 0xa72f, 0xa72f,
+ 0xa733, 0xa733,
+ 0xa735, 0xa735,
+ 0xa737, 0xa737,
+ 0xa739, 0xa739,
+ 0xa73b, 0xa73b,
+ 0xa73d, 0xa73d,
+ 0xa73f, 0xa73f,
+ 0xa741, 0xa741,
+ 0xa743, 0xa743,
+ 0xa745, 0xa745,
+ 0xa747, 0xa747,
+ 0xa749, 0xa749,
+ 0xa74b, 0xa74b,
+ 0xa74d, 0xa74d,
+ 0xa74f, 0xa74f,
+ 0xa751, 0xa751,
+ 0xa753, 0xa753,
+ 0xa755, 0xa755,
+ 0xa757, 0xa757,
+ 0xa759, 0xa759,
+ 0xa75b, 0xa75b,
+ 0xa75d, 0xa75d,
+ 0xa75f, 0xa75f,
+ 0xa761, 0xa761,
+ 0xa763, 0xa763,
+ 0xa765, 0xa765,
+ 0xa767, 0xa767,
+ 0xa769, 0xa769,
+ 0xa76b, 0xa76b,
+ 0xa76d, 0xa76d,
+ 0xa76f, 0xa76f,
+ 0xa77a, 0xa77a,
+ 0xa77c, 0xa77c,
+ 0xa77f, 0xa77f,
+ 0xa781, 0xa781,
+ 0xa783, 0xa783,
+ 0xa785, 0xa785,
+ 0xa787, 0xa787,
+ 0xa78c, 0xa78c,
+ 0xa791, 0xa791,
+ 0xa793, 0xa794,
+ 0xa797, 0xa797,
+ 0xa799, 0xa799,
+ 0xa79b, 0xa79b,
+ 0xa79d, 0xa79d,
+ 0xa79f, 0xa79f,
+ 0xa7a1, 0xa7a1,
+ 0xa7a3, 0xa7a3,
+ 0xa7a5, 0xa7a5,
+ 0xa7a7, 0xa7a7,
+ 0xa7a9, 0xa7a9,
+ 0xa7b5, 0xa7b5,
+ 0xa7b7, 0xa7b7,
+ 0xa7b9, 0xa7b9,
+ 0xa7bb, 0xa7bb,
+ 0xa7bd, 0xa7bd,
+ 0xa7bf, 0xa7bf,
+ 0xa7c1, 0xa7c1,
+ 0xa7c3, 0xa7c3,
+ 0xa7c8, 0xa7c8,
+ 0xa7ca, 0xa7ca,
+ 0xa7cd, 0xa7cd,
+ 0xa7cf, 0xa7cf,
+ 0xa7d1, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d5,
+ 0xa7d7, 0xa7d7,
+ 0xa7d9, 0xa7d9,
+ 0xa7db, 0xa7db,
+ 0xa7f6, 0xa7f6,
+ 0xab53, 0xab53,
+ 0xab70, 0xabbf,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xff41, 0xff5a,
+ 0x10428, 0x1044f,
+ 0x104d8, 0x104fb,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x10cc0, 0x10cf2,
+ 0x10d70, 0x10d85,
+ 0x118c0, 0x118df,
+ 0x16e60, 0x16e7f,
+ 0x16ebb, 0x16ed3,
+ 0x1e922, 0x1e943,
+}; /* CR_Changes_When_Titlecased */
+
+/* 'Changes_When_Casefolded': Derived Property */
+static const OnigCodePoint CR_Changes_When_Casefolded[] = {
+ 630,
+ 0x0041, 0x005a,
+ 0x00b5, 0x00b5,
+ 0x00c0, 0x00d6,
+ 0x00d8, 0x00df,
+ 0x0100, 0x0100,
+ 0x0102, 0x0102,
+ 0x0104, 0x0104,
+ 0x0106, 0x0106,
+ 0x0108, 0x0108,
+ 0x010a, 0x010a,
+ 0x010c, 0x010c,
+ 0x010e, 0x010e,
+ 0x0110, 0x0110,
+ 0x0112, 0x0112,
+ 0x0114, 0x0114,
+ 0x0116, 0x0116,
+ 0x0118, 0x0118,
+ 0x011a, 0x011a,
+ 0x011c, 0x011c,
+ 0x011e, 0x011e,
+ 0x0120, 0x0120,
+ 0x0122, 0x0122,
+ 0x0124, 0x0124,
+ 0x0126, 0x0126,
+ 0x0128, 0x0128,
+ 0x012a, 0x012a,
+ 0x012c, 0x012c,
+ 0x012e, 0x012e,
+ 0x0130, 0x0130,
+ 0x0132, 0x0132,
+ 0x0134, 0x0134,
+ 0x0136, 0x0136,
+ 0x0139, 0x0139,
+ 0x013b, 0x013b,
+ 0x013d, 0x013d,
+ 0x013f, 0x013f,
+ 0x0141, 0x0141,
+ 0x0143, 0x0143,
+ 0x0145, 0x0145,
+ 0x0147, 0x0147,
+ 0x0149, 0x014a,
+ 0x014c, 0x014c,
+ 0x014e, 0x014e,
+ 0x0150, 0x0150,
+ 0x0152, 0x0152,
+ 0x0154, 0x0154,
+ 0x0156, 0x0156,
+ 0x0158, 0x0158,
+ 0x015a, 0x015a,
+ 0x015c, 0x015c,
+ 0x015e, 0x015e,
+ 0x0160, 0x0160,
+ 0x0162, 0x0162,
+ 0x0164, 0x0164,
+ 0x0166, 0x0166,
+ 0x0168, 0x0168,
+ 0x016a, 0x016a,
+ 0x016c, 0x016c,
+ 0x016e, 0x016e,
+ 0x0170, 0x0170,
+ 0x0172, 0x0172,
+ 0x0174, 0x0174,
+ 0x0176, 0x0176,
+ 0x0178, 0x0179,
+ 0x017b, 0x017b,
+ 0x017d, 0x017d,
+ 0x017f, 0x017f,
+ 0x0181, 0x0182,
+ 0x0184, 0x0184,
+ 0x0186, 0x0187,
+ 0x0189, 0x018b,
+ 0x018e, 0x0191,
+ 0x0193, 0x0194,
+ 0x0196, 0x0198,
+ 0x019c, 0x019d,
+ 0x019f, 0x01a0,
+ 0x01a2, 0x01a2,
+ 0x01a4, 0x01a4,
+ 0x01a6, 0x01a7,
+ 0x01a9, 0x01a9,
+ 0x01ac, 0x01ac,
+ 0x01ae, 0x01af,
+ 0x01b1, 0x01b3,
+ 0x01b5, 0x01b5,
+ 0x01b7, 0x01b8,
+ 0x01bc, 0x01bc,
+ 0x01c4, 0x01c5,
+ 0x01c7, 0x01c8,
+ 0x01ca, 0x01cb,
+ 0x01cd, 0x01cd,
+ 0x01cf, 0x01cf,
+ 0x01d1, 0x01d1,
+ 0x01d3, 0x01d3,
+ 0x01d5, 0x01d5,
+ 0x01d7, 0x01d7,
+ 0x01d9, 0x01d9,
+ 0x01db, 0x01db,
+ 0x01de, 0x01de,
+ 0x01e0, 0x01e0,
+ 0x01e2, 0x01e2,
+ 0x01e4, 0x01e4,
+ 0x01e6, 0x01e6,
+ 0x01e8, 0x01e8,
+ 0x01ea, 0x01ea,
+ 0x01ec, 0x01ec,
+ 0x01ee, 0x01ee,
+ 0x01f1, 0x01f2,
+ 0x01f4, 0x01f4,
+ 0x01f6, 0x01f8,
+ 0x01fa, 0x01fa,
+ 0x01fc, 0x01fc,
+ 0x01fe, 0x01fe,
+ 0x0200, 0x0200,
+ 0x0202, 0x0202,
+ 0x0204, 0x0204,
+ 0x0206, 0x0206,
+ 0x0208, 0x0208,
+ 0x020a, 0x020a,
+ 0x020c, 0x020c,
+ 0x020e, 0x020e,
+ 0x0210, 0x0210,
+ 0x0212, 0x0212,
+ 0x0214, 0x0214,
+ 0x0216, 0x0216,
+ 0x0218, 0x0218,
+ 0x021a, 0x021a,
+ 0x021c, 0x021c,
+ 0x021e, 0x021e,
+ 0x0220, 0x0220,
+ 0x0222, 0x0222,
+ 0x0224, 0x0224,
+ 0x0226, 0x0226,
+ 0x0228, 0x0228,
+ 0x022a, 0x022a,
+ 0x022c, 0x022c,
+ 0x022e, 0x022e,
+ 0x0230, 0x0230,
+ 0x0232, 0x0232,
+ 0x023a, 0x023b,
+ 0x023d, 0x023e,
+ 0x0241, 0x0241,
+ 0x0243, 0x0246,
+ 0x0248, 0x0248,
+ 0x024a, 0x024a,
+ 0x024c, 0x024c,
+ 0x024e, 0x024e,
+ 0x0345, 0x0345,
+ 0x0370, 0x0370,
+ 0x0372, 0x0372,
+ 0x0376, 0x0376,
+ 0x037f, 0x037f,
+ 0x0386, 0x0386,
+ 0x0388, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x038f,
+ 0x0391, 0x03a1,
+ 0x03a3, 0x03ab,
+ 0x03c2, 0x03c2,
+ 0x03cf, 0x03d1,
+ 0x03d5, 0x03d6,
+ 0x03d8, 0x03d8,
+ 0x03da, 0x03da,
+ 0x03dc, 0x03dc,
+ 0x03de, 0x03de,
+ 0x03e0, 0x03e0,
+ 0x03e2, 0x03e2,
+ 0x03e4, 0x03e4,
+ 0x03e6, 0x03e6,
+ 0x03e8, 0x03e8,
+ 0x03ea, 0x03ea,
+ 0x03ec, 0x03ec,
+ 0x03ee, 0x03ee,
+ 0x03f0, 0x03f1,
+ 0x03f4, 0x03f5,
+ 0x03f7, 0x03f7,
+ 0x03f9, 0x03fa,
+ 0x03fd, 0x042f,
+ 0x0460, 0x0460,
+ 0x0462, 0x0462,
+ 0x0464, 0x0464,
+ 0x0466, 0x0466,
+ 0x0468, 0x0468,
+ 0x046a, 0x046a,
+ 0x046c, 0x046c,
+ 0x046e, 0x046e,
+ 0x0470, 0x0470,
+ 0x0472, 0x0472,
+ 0x0474, 0x0474,
+ 0x0476, 0x0476,
+ 0x0478, 0x0478,
+ 0x047a, 0x047a,
+ 0x047c, 0x047c,
+ 0x047e, 0x047e,
+ 0x0480, 0x0480,
+ 0x048a, 0x048a,
+ 0x048c, 0x048c,
+ 0x048e, 0x048e,
+ 0x0490, 0x0490,
+ 0x0492, 0x0492,
+ 0x0494, 0x0494,
+ 0x0496, 0x0496,
+ 0x0498, 0x0498,
+ 0x049a, 0x049a,
+ 0x049c, 0x049c,
+ 0x049e, 0x049e,
+ 0x04a0, 0x04a0,
+ 0x04a2, 0x04a2,
+ 0x04a4, 0x04a4,
+ 0x04a6, 0x04a6,
+ 0x04a8, 0x04a8,
+ 0x04aa, 0x04aa,
+ 0x04ac, 0x04ac,
+ 0x04ae, 0x04ae,
+ 0x04b0, 0x04b0,
+ 0x04b2, 0x04b2,
+ 0x04b4, 0x04b4,
+ 0x04b6, 0x04b6,
+ 0x04b8, 0x04b8,
+ 0x04ba, 0x04ba,
+ 0x04bc, 0x04bc,
+ 0x04be, 0x04be,
+ 0x04c0, 0x04c1,
+ 0x04c3, 0x04c3,
+ 0x04c5, 0x04c5,
+ 0x04c7, 0x04c7,
+ 0x04c9, 0x04c9,
+ 0x04cb, 0x04cb,
+ 0x04cd, 0x04cd,
+ 0x04d0, 0x04d0,
+ 0x04d2, 0x04d2,
+ 0x04d4, 0x04d4,
+ 0x04d6, 0x04d6,
+ 0x04d8, 0x04d8,
+ 0x04da, 0x04da,
+ 0x04dc, 0x04dc,
+ 0x04de, 0x04de,
+ 0x04e0, 0x04e0,
+ 0x04e2, 0x04e2,
+ 0x04e4, 0x04e4,
+ 0x04e6, 0x04e6,
+ 0x04e8, 0x04e8,
+ 0x04ea, 0x04ea,
+ 0x04ec, 0x04ec,
+ 0x04ee, 0x04ee,
+ 0x04f0, 0x04f0,
+ 0x04f2, 0x04f2,
+ 0x04f4, 0x04f4,
+ 0x04f6, 0x04f6,
+ 0x04f8, 0x04f8,
+ 0x04fa, 0x04fa,
+ 0x04fc, 0x04fc,
+ 0x04fe, 0x04fe,
+ 0x0500, 0x0500,
+ 0x0502, 0x0502,
+ 0x0504, 0x0504,
+ 0x0506, 0x0506,
+ 0x0508, 0x0508,
+ 0x050a, 0x050a,
+ 0x050c, 0x050c,
+ 0x050e, 0x050e,
+ 0x0510, 0x0510,
+ 0x0512, 0x0512,
+ 0x0514, 0x0514,
+ 0x0516, 0x0516,
+ 0x0518, 0x0518,
+ 0x051a, 0x051a,
+ 0x051c, 0x051c,
+ 0x051e, 0x051e,
+ 0x0520, 0x0520,
+ 0x0522, 0x0522,
+ 0x0524, 0x0524,
+ 0x0526, 0x0526,
+ 0x0528, 0x0528,
+ 0x052a, 0x052a,
+ 0x052c, 0x052c,
+ 0x052e, 0x052e,
+ 0x0531, 0x0556,
+ 0x0587, 0x0587,
+ 0x10a0, 0x10c5,
+ 0x10c7, 0x10c7,
+ 0x10cd, 0x10cd,
+ 0x13f8, 0x13fd,
+ 0x1c80, 0x1c89,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cbf,
+ 0x1e00, 0x1e00,
+ 0x1e02, 0x1e02,
+ 0x1e04, 0x1e04,
+ 0x1e06, 0x1e06,
+ 0x1e08, 0x1e08,
+ 0x1e0a, 0x1e0a,
+ 0x1e0c, 0x1e0c,
+ 0x1e0e, 0x1e0e,
+ 0x1e10, 0x1e10,
+ 0x1e12, 0x1e12,
+ 0x1e14, 0x1e14,
+ 0x1e16, 0x1e16,
+ 0x1e18, 0x1e18,
+ 0x1e1a, 0x1e1a,
+ 0x1e1c, 0x1e1c,
+ 0x1e1e, 0x1e1e,
+ 0x1e20, 0x1e20,
+ 0x1e22, 0x1e22,
+ 0x1e24, 0x1e24,
+ 0x1e26, 0x1e26,
+ 0x1e28, 0x1e28,
+ 0x1e2a, 0x1e2a,
+ 0x1e2c, 0x1e2c,
+ 0x1e2e, 0x1e2e,
+ 0x1e30, 0x1e30,
+ 0x1e32, 0x1e32,
+ 0x1e34, 0x1e34,
+ 0x1e36, 0x1e36,
+ 0x1e38, 0x1e38,
+ 0x1e3a, 0x1e3a,
+ 0x1e3c, 0x1e3c,
+ 0x1e3e, 0x1e3e,
+ 0x1e40, 0x1e40,
+ 0x1e42, 0x1e42,
+ 0x1e44, 0x1e44,
+ 0x1e46, 0x1e46,
+ 0x1e48, 0x1e48,
+ 0x1e4a, 0x1e4a,
+ 0x1e4c, 0x1e4c,
+ 0x1e4e, 0x1e4e,
+ 0x1e50, 0x1e50,
+ 0x1e52, 0x1e52,
+ 0x1e54, 0x1e54,
+ 0x1e56, 0x1e56,
+ 0x1e58, 0x1e58,
+ 0x1e5a, 0x1e5a,
+ 0x1e5c, 0x1e5c,
+ 0x1e5e, 0x1e5e,
+ 0x1e60, 0x1e60,
+ 0x1e62, 0x1e62,
+ 0x1e64, 0x1e64,
+ 0x1e66, 0x1e66,
+ 0x1e68, 0x1e68,
+ 0x1e6a, 0x1e6a,
+ 0x1e6c, 0x1e6c,
+ 0x1e6e, 0x1e6e,
+ 0x1e70, 0x1e70,
+ 0x1e72, 0x1e72,
+ 0x1e74, 0x1e74,
+ 0x1e76, 0x1e76,
+ 0x1e78, 0x1e78,
+ 0x1e7a, 0x1e7a,
+ 0x1e7c, 0x1e7c,
+ 0x1e7e, 0x1e7e,
+ 0x1e80, 0x1e80,
+ 0x1e82, 0x1e82,
+ 0x1e84, 0x1e84,
+ 0x1e86, 0x1e86,
+ 0x1e88, 0x1e88,
+ 0x1e8a, 0x1e8a,
+ 0x1e8c, 0x1e8c,
+ 0x1e8e, 0x1e8e,
+ 0x1e90, 0x1e90,
+ 0x1e92, 0x1e92,
+ 0x1e94, 0x1e94,
+ 0x1e9a, 0x1e9b,
+ 0x1e9e, 0x1e9e,
+ 0x1ea0, 0x1ea0,
+ 0x1ea2, 0x1ea2,
+ 0x1ea4, 0x1ea4,
+ 0x1ea6, 0x1ea6,
+ 0x1ea8, 0x1ea8,
+ 0x1eaa, 0x1eaa,
+ 0x1eac, 0x1eac,
+ 0x1eae, 0x1eae,
+ 0x1eb0, 0x1eb0,
+ 0x1eb2, 0x1eb2,
+ 0x1eb4, 0x1eb4,
+ 0x1eb6, 0x1eb6,
+ 0x1eb8, 0x1eb8,
+ 0x1eba, 0x1eba,
+ 0x1ebc, 0x1ebc,
+ 0x1ebe, 0x1ebe,
+ 0x1ec0, 0x1ec0,
+ 0x1ec2, 0x1ec2,
+ 0x1ec4, 0x1ec4,
+ 0x1ec6, 0x1ec6,
+ 0x1ec8, 0x1ec8,
+ 0x1eca, 0x1eca,
+ 0x1ecc, 0x1ecc,
+ 0x1ece, 0x1ece,
+ 0x1ed0, 0x1ed0,
+ 0x1ed2, 0x1ed2,
+ 0x1ed4, 0x1ed4,
+ 0x1ed6, 0x1ed6,
+ 0x1ed8, 0x1ed8,
+ 0x1eda, 0x1eda,
+ 0x1edc, 0x1edc,
+ 0x1ede, 0x1ede,
+ 0x1ee0, 0x1ee0,
+ 0x1ee2, 0x1ee2,
+ 0x1ee4, 0x1ee4,
+ 0x1ee6, 0x1ee6,
+ 0x1ee8, 0x1ee8,
+ 0x1eea, 0x1eea,
+ 0x1eec, 0x1eec,
+ 0x1eee, 0x1eee,
+ 0x1ef0, 0x1ef0,
+ 0x1ef2, 0x1ef2,
+ 0x1ef4, 0x1ef4,
+ 0x1ef6, 0x1ef6,
+ 0x1ef8, 0x1ef8,
+ 0x1efa, 0x1efa,
+ 0x1efc, 0x1efc,
+ 0x1efe, 0x1efe,
+ 0x1f08, 0x1f0f,
+ 0x1f18, 0x1f1d,
+ 0x1f28, 0x1f2f,
+ 0x1f38, 0x1f3f,
+ 0x1f48, 0x1f4d,
+ 0x1f59, 0x1f59,
+ 0x1f5b, 0x1f5b,
+ 0x1f5d, 0x1f5d,
+ 0x1f5f, 0x1f5f,
+ 0x1f68, 0x1f6f,
+ 0x1f80, 0x1faf,
+ 0x1fb2, 0x1fb4,
+ 0x1fb7, 0x1fbc,
+ 0x1fc2, 0x1fc4,
+ 0x1fc7, 0x1fcc,
+ 0x1fd8, 0x1fdb,
+ 0x1fe8, 0x1fec,
+ 0x1ff2, 0x1ff4,
+ 0x1ff7, 0x1ffc,
+ 0x2126, 0x2126,
+ 0x212a, 0x212b,
+ 0x2132, 0x2132,
+ 0x2160, 0x216f,
+ 0x2183, 0x2183,
+ 0x24b6, 0x24cf,
+ 0x2c00, 0x2c2f,
+ 0x2c60, 0x2c60,
+ 0x2c62, 0x2c64,
+ 0x2c67, 0x2c67,
+ 0x2c69, 0x2c69,
+ 0x2c6b, 0x2c6b,
+ 0x2c6d, 0x2c70,
+ 0x2c72, 0x2c72,
+ 0x2c75, 0x2c75,
+ 0x2c7e, 0x2c80,
+ 0x2c82, 0x2c82,
+ 0x2c84, 0x2c84,
+ 0x2c86, 0x2c86,
+ 0x2c88, 0x2c88,
+ 0x2c8a, 0x2c8a,
+ 0x2c8c, 0x2c8c,
+ 0x2c8e, 0x2c8e,
+ 0x2c90, 0x2c90,
+ 0x2c92, 0x2c92,
+ 0x2c94, 0x2c94,
+ 0x2c96, 0x2c96,
+ 0x2c98, 0x2c98,
+ 0x2c9a, 0x2c9a,
+ 0x2c9c, 0x2c9c,
+ 0x2c9e, 0x2c9e,
+ 0x2ca0, 0x2ca0,
+ 0x2ca2, 0x2ca2,
+ 0x2ca4, 0x2ca4,
+ 0x2ca6, 0x2ca6,
+ 0x2ca8, 0x2ca8,
+ 0x2caa, 0x2caa,
+ 0x2cac, 0x2cac,
+ 0x2cae, 0x2cae,
+ 0x2cb0, 0x2cb0,
+ 0x2cb2, 0x2cb2,
+ 0x2cb4, 0x2cb4,
+ 0x2cb6, 0x2cb6,
+ 0x2cb8, 0x2cb8,
+ 0x2cba, 0x2cba,
+ 0x2cbc, 0x2cbc,
+ 0x2cbe, 0x2cbe,
+ 0x2cc0, 0x2cc0,
+ 0x2cc2, 0x2cc2,
+ 0x2cc4, 0x2cc4,
+ 0x2cc6, 0x2cc6,
+ 0x2cc8, 0x2cc8,
+ 0x2cca, 0x2cca,
+ 0x2ccc, 0x2ccc,
+ 0x2cce, 0x2cce,
+ 0x2cd0, 0x2cd0,
+ 0x2cd2, 0x2cd2,
+ 0x2cd4, 0x2cd4,
+ 0x2cd6, 0x2cd6,
+ 0x2cd8, 0x2cd8,
+ 0x2cda, 0x2cda,
+ 0x2cdc, 0x2cdc,
+ 0x2cde, 0x2cde,
+ 0x2ce0, 0x2ce0,
+ 0x2ce2, 0x2ce2,
+ 0x2ceb, 0x2ceb,
+ 0x2ced, 0x2ced,
+ 0x2cf2, 0x2cf2,
+ 0xa640, 0xa640,
+ 0xa642, 0xa642,
+ 0xa644, 0xa644,
+ 0xa646, 0xa646,
+ 0xa648, 0xa648,
+ 0xa64a, 0xa64a,
+ 0xa64c, 0xa64c,
+ 0xa64e, 0xa64e,
+ 0xa650, 0xa650,
+ 0xa652, 0xa652,
+ 0xa654, 0xa654,
+ 0xa656, 0xa656,
+ 0xa658, 0xa658,
+ 0xa65a, 0xa65a,
+ 0xa65c, 0xa65c,
+ 0xa65e, 0xa65e,
+ 0xa660, 0xa660,
+ 0xa662, 0xa662,
+ 0xa664, 0xa664,
+ 0xa666, 0xa666,
+ 0xa668, 0xa668,
+ 0xa66a, 0xa66a,
+ 0xa66c, 0xa66c,
+ 0xa680, 0xa680,
+ 0xa682, 0xa682,
+ 0xa684, 0xa684,
+ 0xa686, 0xa686,
+ 0xa688, 0xa688,
+ 0xa68a, 0xa68a,
+ 0xa68c, 0xa68c,
+ 0xa68e, 0xa68e,
+ 0xa690, 0xa690,
+ 0xa692, 0xa692,
+ 0xa694, 0xa694,
+ 0xa696, 0xa696,
+ 0xa698, 0xa698,
+ 0xa69a, 0xa69a,
+ 0xa722, 0xa722,
+ 0xa724, 0xa724,
+ 0xa726, 0xa726,
+ 0xa728, 0xa728,
+ 0xa72a, 0xa72a,
+ 0xa72c, 0xa72c,
+ 0xa72e, 0xa72e,
+ 0xa732, 0xa732,
+ 0xa734, 0xa734,
+ 0xa736, 0xa736,
+ 0xa738, 0xa738,
+ 0xa73a, 0xa73a,
+ 0xa73c, 0xa73c,
+ 0xa73e, 0xa73e,
+ 0xa740, 0xa740,
+ 0xa742, 0xa742,
+ 0xa744, 0xa744,
+ 0xa746, 0xa746,
+ 0xa748, 0xa748,
+ 0xa74a, 0xa74a,
+ 0xa74c, 0xa74c,
+ 0xa74e, 0xa74e,
+ 0xa750, 0xa750,
+ 0xa752, 0xa752,
+ 0xa754, 0xa754,
+ 0xa756, 0xa756,
+ 0xa758, 0xa758,
+ 0xa75a, 0xa75a,
+ 0xa75c, 0xa75c,
+ 0xa75e, 0xa75e,
+ 0xa760, 0xa760,
+ 0xa762, 0xa762,
+ 0xa764, 0xa764,
+ 0xa766, 0xa766,
+ 0xa768, 0xa768,
+ 0xa76a, 0xa76a,
+ 0xa76c, 0xa76c,
+ 0xa76e, 0xa76e,
+ 0xa779, 0xa779,
+ 0xa77b, 0xa77b,
+ 0xa77d, 0xa77e,
+ 0xa780, 0xa780,
+ 0xa782, 0xa782,
+ 0xa784, 0xa784,
+ 0xa786, 0xa786,
+ 0xa78b, 0xa78b,
+ 0xa78d, 0xa78d,
+ 0xa790, 0xa790,
+ 0xa792, 0xa792,
+ 0xa796, 0xa796,
+ 0xa798, 0xa798,
+ 0xa79a, 0xa79a,
+ 0xa79c, 0xa79c,
+ 0xa79e, 0xa79e,
+ 0xa7a0, 0xa7a0,
+ 0xa7a2, 0xa7a2,
+ 0xa7a4, 0xa7a4,
+ 0xa7a6, 0xa7a6,
+ 0xa7a8, 0xa7a8,
+ 0xa7aa, 0xa7ae,
+ 0xa7b0, 0xa7b4,
+ 0xa7b6, 0xa7b6,
+ 0xa7b8, 0xa7b8,
+ 0xa7ba, 0xa7ba,
+ 0xa7bc, 0xa7bc,
+ 0xa7be, 0xa7be,
+ 0xa7c0, 0xa7c0,
+ 0xa7c2, 0xa7c2,
+ 0xa7c4, 0xa7c7,
+ 0xa7c9, 0xa7c9,
+ 0xa7cb, 0xa7cc,
+ 0xa7ce, 0xa7ce,
+ 0xa7d0, 0xa7d0,
+ 0xa7d2, 0xa7d2,
+ 0xa7d4, 0xa7d4,
+ 0xa7d6, 0xa7d6,
+ 0xa7d8, 0xa7d8,
+ 0xa7da, 0xa7da,
+ 0xa7dc, 0xa7dc,
+ 0xa7f5, 0xa7f5,
+ 0xab70, 0xabbf,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xff21, 0xff3a,
+ 0x10400, 0x10427,
+ 0x104b0, 0x104d3,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10c80, 0x10cb2,
+ 0x10d50, 0x10d65,
+ 0x118a0, 0x118bf,
+ 0x16e40, 0x16e5f,
+ 0x16ea0, 0x16eb8,
+ 0x1e900, 0x1e921,
+}; /* CR_Changes_When_Casefolded */
+
+/* 'Changes_When_Casemapped': Derived Property */
+static const OnigCodePoint CR_Changes_When_Casemapped[] = {
+ 131,
+ 0x0041, 0x005a,
+ 0x0061, 0x007a,
+ 0x00b5, 0x00b5,
+ 0x00c0, 0x00d6,
+ 0x00d8, 0x00f6,
+ 0x00f8, 0x0137,
+ 0x0139, 0x018c,
+ 0x018e, 0x01a9,
+ 0x01ac, 0x01b9,
+ 0x01bc, 0x01bd,
+ 0x01bf, 0x01bf,
+ 0x01c4, 0x0220,
+ 0x0222, 0x0233,
+ 0x023a, 0x0254,
+ 0x0256, 0x0257,
+ 0x0259, 0x0259,
+ 0x025b, 0x025c,
+ 0x0260, 0x0261,
+ 0x0263, 0x0266,
+ 0x0268, 0x026c,
+ 0x026f, 0x026f,
+ 0x0271, 0x0272,
+ 0x0275, 0x0275,
+ 0x027d, 0x027d,
+ 0x0280, 0x0280,
+ 0x0282, 0x0283,
+ 0x0287, 0x028c,
+ 0x0292, 0x0292,
+ 0x029d, 0x029e,
+ 0x0345, 0x0345,
+ 0x0370, 0x0373,
+ 0x0376, 0x0377,
+ 0x037b, 0x037d,
+ 0x037f, 0x037f,
+ 0x0386, 0x0386,
+ 0x0388, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x03d1,
+ 0x03d5, 0x03f5,
+ 0x03f7, 0x03fb,
+ 0x03fd, 0x0481,
+ 0x048a, 0x052f,
+ 0x0531, 0x0556,
+ 0x0561, 0x0587,
+ 0x10a0, 0x10c5,
+ 0x10c7, 0x10c7,
+ 0x10cd, 0x10cd,
+ 0x10d0, 0x10fa,
+ 0x10fd, 0x10ff,
+ 0x13a0, 0x13f5,
+ 0x13f8, 0x13fd,
+ 0x1c80, 0x1c8a,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cbf,
+ 0x1d79, 0x1d79,
+ 0x1d7d, 0x1d7d,
+ 0x1d8e, 0x1d8e,
+ 0x1e00, 0x1e9b,
+ 0x1e9e, 0x1e9e,
+ 0x1ea0, 0x1f15,
+ 0x1f18, 0x1f1d,
+ 0x1f20, 0x1f45,
+ 0x1f48, 0x1f4d,
+ 0x1f50, 0x1f57,
+ 0x1f59, 0x1f59,
+ 0x1f5b, 0x1f5b,
+ 0x1f5d, 0x1f5d,
+ 0x1f5f, 0x1f7d,
+ 0x1f80, 0x1fb4,
+ 0x1fb6, 0x1fbc,
+ 0x1fbe, 0x1fbe,
+ 0x1fc2, 0x1fc4,
+ 0x1fc6, 0x1fcc,
+ 0x1fd0, 0x1fd3,
+ 0x1fd6, 0x1fdb,
+ 0x1fe0, 0x1fec,
+ 0x1ff2, 0x1ff4,
+ 0x1ff6, 0x1ffc,
+ 0x2126, 0x2126,
+ 0x212a, 0x212b,
+ 0x2132, 0x2132,
+ 0x214e, 0x214e,
+ 0x2160, 0x217f,
+ 0x2183, 0x2184,
+ 0x24b6, 0x24e9,
+ 0x2c00, 0x2c70,
+ 0x2c72, 0x2c73,
+ 0x2c75, 0x2c76,
+ 0x2c7e, 0x2ce3,
+ 0x2ceb, 0x2cee,
+ 0x2cf2, 0x2cf3,
+ 0x2d00, 0x2d25,
+ 0x2d27, 0x2d27,
+ 0x2d2d, 0x2d2d,
+ 0xa640, 0xa66d,
+ 0xa680, 0xa69b,
+ 0xa722, 0xa72f,
+ 0xa732, 0xa76f,
+ 0xa779, 0xa787,
+ 0xa78b, 0xa78d,
+ 0xa790, 0xa794,
+ 0xa796, 0xa7ae,
+ 0xa7b0, 0xa7dc,
+ 0xa7f5, 0xa7f6,
+ 0xab53, 0xab53,
+ 0xab70, 0xabbf,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xff21, 0xff3a,
+ 0xff41, 0xff5a,
+ 0x10400, 0x1044f,
+ 0x104b0, 0x104d3,
+ 0x104d8, 0x104fb,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x10c80, 0x10cb2,
+ 0x10cc0, 0x10cf2,
+ 0x10d50, 0x10d65,
+ 0x10d70, 0x10d85,
+ 0x118a0, 0x118df,
+ 0x16e40, 0x16e7f,
+ 0x16ea0, 0x16eb8,
+ 0x16ebb, 0x16ed3,
+ 0x1e900, 0x1e943,
+}; /* CR_Changes_When_Casemapped */
+
+/* 'ID_Start': Derived Property */
+static const OnigCodePoint CR_ID_Start[] = {
+ 684,
+ 0x0041, 0x005a,
+ 0x0061, 0x007a,
+ 0x00aa, 0x00aa,
+ 0x00b5, 0x00b5,
+ 0x00ba, 0x00ba,
+ 0x00c0, 0x00d6,
+ 0x00d8, 0x00f6,
+ 0x00f8, 0x02c1,
+ 0x02c6, 0x02d1,
+ 0x02e0, 0x02e4,
+ 0x02ec, 0x02ec,
+ 0x02ee, 0x02ee,
+ 0x0370, 0x0374,
+ 0x0376, 0x0377,
+ 0x037a, 0x037d,
+ 0x037f, 0x037f,
+ 0x0386, 0x0386,
+ 0x0388, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x03f5,
+ 0x03f7, 0x0481,
+ 0x048a, 0x052f,
+ 0x0531, 0x0556,
+ 0x0559, 0x0559,
+ 0x0560, 0x0588,
+ 0x05d0, 0x05ea,
+ 0x05ef, 0x05f2,
+ 0x0620, 0x064a,
+ 0x066e, 0x066f,
+ 0x0671, 0x06d3,
+ 0x06d5, 0x06d5,
+ 0x06e5, 0x06e6,
+ 0x06ee, 0x06ef,
+ 0x06fa, 0x06fc,
+ 0x06ff, 0x06ff,
+ 0x0710, 0x0710,
+ 0x0712, 0x072f,
+ 0x074d, 0x07a5,
+ 0x07b1, 0x07b1,
+ 0x07ca, 0x07ea,
+ 0x07f4, 0x07f5,
+ 0x07fa, 0x07fa,
+ 0x0800, 0x0815,
+ 0x081a, 0x081a,
+ 0x0824, 0x0824,
+ 0x0828, 0x0828,
+ 0x0840, 0x0858,
+ 0x0860, 0x086a,
+ 0x0870, 0x0887,
+ 0x0889, 0x088f,
+ 0x08a0, 0x08c9,
+ 0x0904, 0x0939,
+ 0x093d, 0x093d,
+ 0x0950, 0x0950,
+ 0x0958, 0x0961,
+ 0x0971, 0x0980,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bd, 0x09bd,
+ 0x09ce, 0x09ce,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e1,
+ 0x09f0, 0x09f1,
+ 0x09fc, 0x09fc,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a72, 0x0a74,
+ 0x0a85, 0x0a8d,
+ 0x0a8f, 0x0a91,
+ 0x0a93, 0x0aa8,
+ 0x0aaa, 0x0ab0,
+ 0x0ab2, 0x0ab3,
+ 0x0ab5, 0x0ab9,
+ 0x0abd, 0x0abd,
+ 0x0ad0, 0x0ad0,
+ 0x0ae0, 0x0ae1,
+ 0x0af9, 0x0af9,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b35, 0x0b39,
+ 0x0b3d, 0x0b3d,
+ 0x0b5c, 0x0b5d,
+ 0x0b5f, 0x0b61,
+ 0x0b71, 0x0b71,
+ 0x0b83, 0x0b83,
+ 0x0b85, 0x0b8a,
+ 0x0b8e, 0x0b90,
+ 0x0b92, 0x0b95,
+ 0x0b99, 0x0b9a,
+ 0x0b9c, 0x0b9c,
+ 0x0b9e, 0x0b9f,
+ 0x0ba3, 0x0ba4,
+ 0x0ba8, 0x0baa,
+ 0x0bae, 0x0bb9,
+ 0x0bd0, 0x0bd0,
+ 0x0c05, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3d, 0x0c3d,
+ 0x0c58, 0x0c5a,
+ 0x0c5c, 0x0c5d,
+ 0x0c60, 0x0c61,
+ 0x0c80, 0x0c80,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbd, 0x0cbd,
+ 0x0cdc, 0x0cde,
+ 0x0ce0, 0x0ce1,
+ 0x0cf1, 0x0cf2,
+ 0x0d04, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d3a,
+ 0x0d3d, 0x0d3d,
+ 0x0d4e, 0x0d4e,
+ 0x0d54, 0x0d56,
+ 0x0d5f, 0x0d61,
+ 0x0d7a, 0x0d7f,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0e01, 0x0e30,
+ 0x0e32, 0x0e33,
+ 0x0e40, 0x0e46,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e86, 0x0e8a,
+ 0x0e8c, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0eb0,
+ 0x0eb2, 0x0eb3,
+ 0x0ebd, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f00,
+ 0x0f40, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f88, 0x0f8c,
+ 0x1000, 0x102a,
+ 0x103f, 0x103f,
+ 0x1050, 0x1055,
+ 0x105a, 0x105d,
+ 0x1061, 0x1061,
+ 0x1065, 0x1066,
+ 0x106e, 0x1070,
+ 0x1075, 0x1081,
+ 0x108e, 0x108e,
+ 0x10a0, 0x10c5,
+ 0x10c7, 0x10c7,
+ 0x10cd, 0x10cd,
+ 0x10d0, 0x10fa,
+ 0x10fc, 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,
+ 0x1380, 0x138f,
+ 0x13a0, 0x13f5,
+ 0x13f8, 0x13fd,
+ 0x1401, 0x166c,
+ 0x166f, 0x167f,
+ 0x1681, 0x169a,
+ 0x16a0, 0x16ea,
+ 0x16ee, 0x16f8,
+ 0x1700, 0x1711,
+ 0x171f, 0x1731,
+ 0x1740, 0x1751,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1780, 0x17b3,
+ 0x17d7, 0x17d7,
+ 0x17dc, 0x17dc,
+ 0x1820, 0x1878,
+ 0x1880, 0x18a8,
+ 0x18aa, 0x18aa,
+ 0x18b0, 0x18f5,
+ 0x1900, 0x191e,
+ 0x1950, 0x196d,
+ 0x1970, 0x1974,
+ 0x1980, 0x19ab,
+ 0x19b0, 0x19c9,
+ 0x1a00, 0x1a16,
+ 0x1a20, 0x1a54,
+ 0x1aa7, 0x1aa7,
+ 0x1b05, 0x1b33,
+ 0x1b45, 0x1b4c,
+ 0x1b83, 0x1ba0,
+ 0x1bae, 0x1baf,
+ 0x1bba, 0x1be5,
+ 0x1c00, 0x1c23,
+ 0x1c4d, 0x1c4f,
+ 0x1c5a, 0x1c7d,
+ 0x1c80, 0x1c8a,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cbf,
+ 0x1ce9, 0x1cec,
+ 0x1cee, 0x1cf3,
+ 0x1cf5, 0x1cf6,
+ 0x1cfa, 0x1cfa,
+ 0x1d00, 0x1dbf,
+ 0x1e00, 0x1f15,
+ 0x1f18, 0x1f1d,
+ 0x1f20, 0x1f45,
+ 0x1f48, 0x1f4d,
+ 0x1f50, 0x1f57,
+ 0x1f59, 0x1f59,
+ 0x1f5b, 0x1f5b,
+ 0x1f5d, 0x1f5d,
+ 0x1f5f, 0x1f7d,
+ 0x1f80, 0x1fb4,
+ 0x1fb6, 0x1fbc,
+ 0x1fbe, 0x1fbe,
+ 0x1fc2, 0x1fc4,
+ 0x1fc6, 0x1fcc,
+ 0x1fd0, 0x1fd3,
+ 0x1fd6, 0x1fdb,
+ 0x1fe0, 0x1fec,
+ 0x1ff2, 0x1ff4,
+ 0x1ff6, 0x1ffc,
+ 0x2071, 0x2071,
+ 0x207f, 0x207f,
+ 0x2090, 0x209c,
+ 0x2102, 0x2102,
+ 0x2107, 0x2107,
+ 0x210a, 0x2113,
+ 0x2115, 0x2115,
+ 0x2118, 0x211d,
+ 0x2124, 0x2124,
+ 0x2126, 0x2126,
+ 0x2128, 0x2128,
+ 0x212a, 0x2139,
+ 0x213c, 0x213f,
+ 0x2145, 0x2149,
+ 0x214e, 0x214e,
+ 0x2160, 0x2188,
+ 0x2c00, 0x2ce4,
+ 0x2ceb, 0x2cee,
+ 0x2cf2, 0x2cf3,
+ 0x2d00, 0x2d25,
+ 0x2d27, 0x2d27,
+ 0x2d2d, 0x2d2d,
+ 0x2d30, 0x2d67,
+ 0x2d6f, 0x2d6f,
+ 0x2d80, 0x2d96,
+ 0x2da0, 0x2da6,
+ 0x2da8, 0x2dae,
+ 0x2db0, 0x2db6,
+ 0x2db8, 0x2dbe,
+ 0x2dc0, 0x2dc6,
+ 0x2dc8, 0x2dce,
+ 0x2dd0, 0x2dd6,
+ 0x2dd8, 0x2dde,
+ 0x3005, 0x3007,
+ 0x3021, 0x3029,
+ 0x3031, 0x3035,
+ 0x3038, 0x303c,
+ 0x3041, 0x3096,
+ 0x309b, 0x309f,
+ 0x30a1, 0x30fa,
+ 0x30fc, 0x30ff,
+ 0x3105, 0x312f,
+ 0x3131, 0x318e,
+ 0x31a0, 0x31bf,
+ 0x31f0, 0x31ff,
+ 0x3400, 0x4dbf,
+ 0x4e00, 0xa48c,
+ 0xa4d0, 0xa4fd,
+ 0xa500, 0xa60c,
+ 0xa610, 0xa61f,
+ 0xa62a, 0xa62b,
+ 0xa640, 0xa66e,
+ 0xa67f, 0xa69d,
+ 0xa6a0, 0xa6ef,
+ 0xa717, 0xa71f,
+ 0xa722, 0xa788,
+ 0xa78b, 0xa7dc,
+ 0xa7f1, 0xa801,
+ 0xa803, 0xa805,
+ 0xa807, 0xa80a,
+ 0xa80c, 0xa822,
+ 0xa840, 0xa873,
+ 0xa882, 0xa8b3,
+ 0xa8f2, 0xa8f7,
+ 0xa8fb, 0xa8fb,
+ 0xa8fd, 0xa8fe,
+ 0xa90a, 0xa925,
+ 0xa930, 0xa946,
+ 0xa960, 0xa97c,
+ 0xa984, 0xa9b2,
+ 0xa9cf, 0xa9cf,
+ 0xa9e0, 0xa9e4,
+ 0xa9e6, 0xa9ef,
+ 0xa9fa, 0xa9fe,
+ 0xaa00, 0xaa28,
+ 0xaa40, 0xaa42,
+ 0xaa44, 0xaa4b,
+ 0xaa60, 0xaa76,
+ 0xaa7a, 0xaa7a,
+ 0xaa7e, 0xaaaf,
+ 0xaab1, 0xaab1,
+ 0xaab5, 0xaab6,
+ 0xaab9, 0xaabd,
+ 0xaac0, 0xaac0,
+ 0xaac2, 0xaac2,
+ 0xaadb, 0xaadd,
+ 0xaae0, 0xaaea,
+ 0xaaf2, 0xaaf4,
+ 0xab01, 0xab06,
+ 0xab09, 0xab0e,
+ 0xab11, 0xab16,
+ 0xab20, 0xab26,
+ 0xab28, 0xab2e,
+ 0xab30, 0xab5a,
+ 0xab5c, 0xab69,
+ 0xab70, 0xabe2,
+ 0xac00, 0xd7a3,
+ 0xd7b0, 0xd7c6,
+ 0xd7cb, 0xd7fb,
+ 0xf900, 0xfa6d,
+ 0xfa70, 0xfad9,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xfb1d, 0xfb1d,
+ 0xfb1f, 0xfb28,
+ 0xfb2a, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfbb1,
+ 0xfbd3, 0xfd3d,
+ 0xfd50, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdf0, 0xfdfb,
+ 0xfe70, 0xfe74,
+ 0xfe76, 0xfefc,
+ 0xff21, 0xff3a,
+ 0xff41, 0xff5a,
+ 0xff66, 0xffbe,
+ 0xffc2, 0xffc7,
+ 0xffca, 0xffcf,
+ 0xffd2, 0xffd7,
+ 0xffda, 0xffdc,
+ 0x10000, 0x1000b,
+ 0x1000d, 0x10026,
+ 0x10028, 0x1003a,
+ 0x1003c, 0x1003d,
+ 0x1003f, 0x1004d,
+ 0x10050, 0x1005d,
+ 0x10080, 0x100fa,
+ 0x10140, 0x10174,
+ 0x10280, 0x1029c,
+ 0x102a0, 0x102d0,
+ 0x10300, 0x1031f,
+ 0x1032d, 0x1034a,
+ 0x10350, 0x10375,
+ 0x10380, 0x1039d,
+ 0x103a0, 0x103c3,
+ 0x103c8, 0x103cf,
+ 0x103d1, 0x103d5,
+ 0x10400, 0x1049d,
+ 0x104b0, 0x104d3,
+ 0x104d8, 0x104fb,
+ 0x10500, 0x10527,
+ 0x10530, 0x10563,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x105c0, 0x105f3,
+ 0x10600, 0x10736,
+ 0x10740, 0x10755,
+ 0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 0x10837, 0x10838,
+ 0x1083c, 0x1083c,
+ 0x1083f, 0x10855,
+ 0x10860, 0x10876,
+ 0x10880, 0x1089e,
+ 0x108e0, 0x108f2,
+ 0x108f4, 0x108f5,
+ 0x10900, 0x10915,
+ 0x10920, 0x10939,
+ 0x10940, 0x10959,
+ 0x10980, 0x109b7,
+ 0x109be, 0x109bf,
+ 0x10a00, 0x10a00,
+ 0x10a10, 0x10a13,
+ 0x10a15, 0x10a17,
+ 0x10a19, 0x10a35,
+ 0x10a60, 0x10a7c,
+ 0x10a80, 0x10a9c,
+ 0x10ac0, 0x10ac7,
+ 0x10ac9, 0x10ae4,
+ 0x10b00, 0x10b35,
+ 0x10b40, 0x10b55,
+ 0x10b60, 0x10b72,
+ 0x10b80, 0x10b91,
+ 0x10c00, 0x10c48,
+ 0x10c80, 0x10cb2,
+ 0x10cc0, 0x10cf2,
+ 0x10d00, 0x10d23,
+ 0x10d4a, 0x10d65,
+ 0x10d6f, 0x10d85,
+ 0x10e80, 0x10ea9,
+ 0x10eb0, 0x10eb1,
+ 0x10ec2, 0x10ec7,
+ 0x10f00, 0x10f1c,
+ 0x10f27, 0x10f27,
+ 0x10f30, 0x10f45,
+ 0x10f70, 0x10f81,
+ 0x10fb0, 0x10fc4,
+ 0x10fe0, 0x10ff6,
+ 0x11003, 0x11037,
+ 0x11071, 0x11072,
+ 0x11075, 0x11075,
+ 0x11083, 0x110af,
+ 0x110d0, 0x110e8,
+ 0x11103, 0x11126,
+ 0x11144, 0x11144,
+ 0x11147, 0x11147,
+ 0x11150, 0x11172,
+ 0x11176, 0x11176,
+ 0x11183, 0x111b2,
+ 0x111c1, 0x111c4,
+ 0x111da, 0x111da,
+ 0x111dc, 0x111dc,
+ 0x11200, 0x11211,
+ 0x11213, 0x1122b,
+ 0x1123f, 0x11240,
+ 0x11280, 0x11286,
+ 0x11288, 0x11288,
+ 0x1128a, 0x1128d,
+ 0x1128f, 0x1129d,
+ 0x1129f, 0x112a8,
+ 0x112b0, 0x112de,
+ 0x11305, 0x1130c,
+ 0x1130f, 0x11310,
+ 0x11313, 0x11328,
+ 0x1132a, 0x11330,
+ 0x11332, 0x11333,
+ 0x11335, 0x11339,
+ 0x1133d, 0x1133d,
+ 0x11350, 0x11350,
+ 0x1135d, 0x11361,
+ 0x11380, 0x11389,
+ 0x1138b, 0x1138b,
+ 0x1138e, 0x1138e,
+ 0x11390, 0x113b5,
+ 0x113b7, 0x113b7,
+ 0x113d1, 0x113d1,
+ 0x113d3, 0x113d3,
+ 0x11400, 0x11434,
+ 0x11447, 0x1144a,
+ 0x1145f, 0x11461,
+ 0x11480, 0x114af,
+ 0x114c4, 0x114c5,
+ 0x114c7, 0x114c7,
+ 0x11580, 0x115ae,
+ 0x115d8, 0x115db,
+ 0x11600, 0x1162f,
+ 0x11644, 0x11644,
+ 0x11680, 0x116aa,
+ 0x116b8, 0x116b8,
+ 0x11700, 0x1171a,
+ 0x11740, 0x11746,
+ 0x11800, 0x1182b,
+ 0x118a0, 0x118df,
+ 0x118ff, 0x11906,
+ 0x11909, 0x11909,
+ 0x1190c, 0x11913,
+ 0x11915, 0x11916,
+ 0x11918, 0x1192f,
+ 0x1193f, 0x1193f,
+ 0x11941, 0x11941,
+ 0x119a0, 0x119a7,
+ 0x119aa, 0x119d0,
+ 0x119e1, 0x119e1,
+ 0x119e3, 0x119e3,
+ 0x11a00, 0x11a00,
+ 0x11a0b, 0x11a32,
+ 0x11a3a, 0x11a3a,
+ 0x11a50, 0x11a50,
+ 0x11a5c, 0x11a89,
+ 0x11a9d, 0x11a9d,
+ 0x11ab0, 0x11af8,
+ 0x11bc0, 0x11be0,
+ 0x11c00, 0x11c08,
+ 0x11c0a, 0x11c2e,
+ 0x11c40, 0x11c40,
+ 0x11c72, 0x11c8f,
+ 0x11d00, 0x11d06,
+ 0x11d08, 0x11d09,
+ 0x11d0b, 0x11d30,
+ 0x11d46, 0x11d46,
+ 0x11d60, 0x11d65,
+ 0x11d67, 0x11d68,
+ 0x11d6a, 0x11d89,
+ 0x11d98, 0x11d98,
+ 0x11db0, 0x11ddb,
+ 0x11ee0, 0x11ef2,
+ 0x11f02, 0x11f02,
+ 0x11f04, 0x11f10,
+ 0x11f12, 0x11f33,
+ 0x11fb0, 0x11fb0,
+ 0x12000, 0x12399,
+ 0x12400, 0x1246e,
+ 0x12480, 0x12543,
+ 0x12f90, 0x12ff0,
+ 0x13000, 0x1342f,
+ 0x13441, 0x13446,
+ 0x13460, 0x143fa,
+ 0x14400, 0x14646,
+ 0x16100, 0x1611d,
+ 0x16800, 0x16a38,
+ 0x16a40, 0x16a5e,
+ 0x16a70, 0x16abe,
+ 0x16ad0, 0x16aed,
+ 0x16b00, 0x16b2f,
+ 0x16b40, 0x16b43,
+ 0x16b63, 0x16b77,
+ 0x16b7d, 0x16b8f,
+ 0x16d40, 0x16d6c,
+ 0x16e40, 0x16e7f,
+ 0x16ea0, 0x16eb8,
+ 0x16ebb, 0x16ed3,
+ 0x16f00, 0x16f4a,
+ 0x16f50, 0x16f50,
+ 0x16f93, 0x16f9f,
+ 0x16fe0, 0x16fe1,
+ 0x16fe3, 0x16fe3,
+ 0x16ff2, 0x16ff6,
+ 0x17000, 0x18cd5,
+ 0x18cff, 0x18d1e,
+ 0x18d80, 0x18df2,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
+ 0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
+ 0x1b164, 0x1b167,
+ 0x1b170, 0x1b2fb,
+ 0x1bc00, 0x1bc6a,
+ 0x1bc70, 0x1bc7c,
+ 0x1bc80, 0x1bc88,
+ 0x1bc90, 0x1bc99,
+ 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, 0x1d6c0,
+ 0x1d6c2, 0x1d6da,
+ 0x1d6dc, 0x1d6fa,
+ 0x1d6fc, 0x1d714,
+ 0x1d716, 0x1d734,
+ 0x1d736, 0x1d74e,
+ 0x1d750, 0x1d76e,
+ 0x1d770, 0x1d788,
+ 0x1d78a, 0x1d7a8,
+ 0x1d7aa, 0x1d7c2,
+ 0x1d7c4, 0x1d7cb,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e030, 0x1e06d,
+ 0x1e100, 0x1e12c,
+ 0x1e137, 0x1e13d,
+ 0x1e14e, 0x1e14e,
+ 0x1e290, 0x1e2ad,
+ 0x1e2c0, 0x1e2eb,
+ 0x1e4d0, 0x1e4eb,
+ 0x1e5d0, 0x1e5ed,
+ 0x1e5f0, 0x1e5f0,
+ 0x1e6c0, 0x1e6de,
+ 0x1e6e0, 0x1e6e2,
+ 0x1e6e4, 0x1e6e5,
+ 0x1e6e7, 0x1e6ed,
+ 0x1e6f0, 0x1e6f4,
+ 0x1e6fe, 0x1e6ff,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
+ 0x1e800, 0x1e8c4,
+ 0x1e900, 0x1e943,
+ 0x1e94b, 0x1e94b,
+ 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,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b81d,
+ 0x2b820, 0x2cead,
+ 0x2ceb0, 0x2ebe0,
+ 0x2ebf0, 0x2ee5d,
+ 0x2f800, 0x2fa1d,
+ 0x30000, 0x3134a,
+ 0x31350, 0x33479,
+}; /* CR_ID_Start */
+
+/* 'ID_Continue': Derived Property */
+static const OnigCodePoint CR_ID_Continue[] = {
+ 799,
+ 0x0030, 0x0039,
+ 0x0041, 0x005a,
+ 0x005f, 0x005f,
+ 0x0061, 0x007a,
+ 0x00aa, 0x00aa,
+ 0x00b5, 0x00b5,
+ 0x00b7, 0x00b7,
+ 0x00ba, 0x00ba,
+ 0x00c0, 0x00d6,
+ 0x00d8, 0x00f6,
+ 0x00f8, 0x02c1,
+ 0x02c6, 0x02d1,
+ 0x02e0, 0x02e4,
+ 0x02ec, 0x02ec,
+ 0x02ee, 0x02ee,
+ 0x0300, 0x0374,
+ 0x0376, 0x0377,
+ 0x037a, 0x037d,
+ 0x037f, 0x037f,
+ 0x0386, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x03f5,
+ 0x03f7, 0x0481,
+ 0x0483, 0x0487,
+ 0x048a, 0x052f,
+ 0x0531, 0x0556,
+ 0x0559, 0x0559,
+ 0x0560, 0x0588,
+ 0x0591, 0x05bd,
+ 0x05bf, 0x05bf,
+ 0x05c1, 0x05c2,
+ 0x05c4, 0x05c5,
+ 0x05c7, 0x05c7,
+ 0x05d0, 0x05ea,
+ 0x05ef, 0x05f2,
+ 0x0610, 0x061a,
+ 0x0620, 0x0669,
+ 0x066e, 0x06d3,
+ 0x06d5, 0x06dc,
+ 0x06df, 0x06e8,
+ 0x06ea, 0x06fc,
+ 0x06ff, 0x06ff,
+ 0x0710, 0x074a,
+ 0x074d, 0x07b1,
+ 0x07c0, 0x07f5,
+ 0x07fa, 0x07fa,
+ 0x07fd, 0x07fd,
+ 0x0800, 0x082d,
+ 0x0840, 0x085b,
+ 0x0860, 0x086a,
+ 0x0870, 0x0887,
+ 0x0889, 0x088f,
+ 0x0897, 0x08e1,
+ 0x08e3, 0x0963,
+ 0x0966, 0x096f,
+ 0x0971, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09f1,
+ 0x09fc, 0x09fc,
+ 0x09fe, 0x09fe,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a75,
+ 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, 0x0aef,
+ 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, 0x0b6f,
+ 0x0b71, 0x0b71,
+ 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,
+ 0x0be6, 0x0bef,
+ 0x0c00, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3c, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c5a,
+ 0x0c5c, 0x0c5d,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c80, 0x0c83,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cdc, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf3,
+ 0x0d00, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d44,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4e,
+ 0x0d54, 0x0d57,
+ 0x0d5f, 0x0d63,
+ 0x0d66, 0x0d6f,
+ 0x0d7a, 0x0d7f,
+ 0x0d81, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0de6, 0x0def,
+ 0x0df2, 0x0df3,
+ 0x0e01, 0x0e3a,
+ 0x0e40, 0x0e4e,
+ 0x0e50, 0x0e59,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e86, 0x0e8a,
+ 0x0e8c, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ece,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f00,
+ 0x0f18, 0x0f19,
+ 0x0f20, 0x0f29,
+ 0x0f35, 0x0f35,
+ 0x0f37, 0x0f37,
+ 0x0f39, 0x0f39,
+ 0x0f3e, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f84,
+ 0x0f86, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 0x0fc6, 0x0fc6,
+ 0x1000, 0x1049,
+ 0x1050, 0x109d,
+ 0x10a0, 0x10c5,
+ 0x10c7, 0x10c7,
+ 0x10cd, 0x10cd,
+ 0x10d0, 0x10fa,
+ 0x10fc, 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, 0x135f,
+ 0x1369, 0x1371,
+ 0x1380, 0x138f,
+ 0x13a0, 0x13f5,
+ 0x13f8, 0x13fd,
+ 0x1401, 0x166c,
+ 0x166f, 0x167f,
+ 0x1681, 0x169a,
+ 0x16a0, 0x16ea,
+ 0x16ee, 0x16f8,
+ 0x1700, 0x1715,
+ 0x171f, 0x1734,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17d3,
+ 0x17d7, 0x17d7,
+ 0x17dc, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x180b, 0x180d,
+ 0x180f, 0x1819,
+ 0x1820, 0x1878,
+ 0x1880, 0x18aa,
+ 0x18b0, 0x18f5,
+ 0x1900, 0x191e,
+ 0x1920, 0x192b,
+ 0x1930, 0x193b,
+ 0x1946, 0x196d,
+ 0x1970, 0x1974,
+ 0x1980, 0x19ab,
+ 0x19b0, 0x19c9,
+ 0x19d0, 0x19da,
+ 0x1a00, 0x1a1b,
+ 0x1a20, 0x1a5e,
+ 0x1a60, 0x1a7c,
+ 0x1a7f, 0x1a89,
+ 0x1a90, 0x1a99,
+ 0x1aa7, 0x1aa7,
+ 0x1ab0, 0x1abd,
+ 0x1abf, 0x1add,
+ 0x1ae0, 0x1aeb,
+ 0x1b00, 0x1b4c,
+ 0x1b50, 0x1b59,
+ 0x1b6b, 0x1b73,
+ 0x1b80, 0x1bf3,
+ 0x1c00, 0x1c37,
+ 0x1c40, 0x1c49,
+ 0x1c4d, 0x1c7d,
+ 0x1c80, 0x1c8a,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cbf,
+ 0x1cd0, 0x1cd2,
+ 0x1cd4, 0x1cfa,
+ 0x1d00, 0x1f15,
+ 0x1f18, 0x1f1d,
+ 0x1f20, 0x1f45,
+ 0x1f48, 0x1f4d,
+ 0x1f50, 0x1f57,
+ 0x1f59, 0x1f59,
+ 0x1f5b, 0x1f5b,
+ 0x1f5d, 0x1f5d,
+ 0x1f5f, 0x1f7d,
+ 0x1f80, 0x1fb4,
+ 0x1fb6, 0x1fbc,
+ 0x1fbe, 0x1fbe,
+ 0x1fc2, 0x1fc4,
+ 0x1fc6, 0x1fcc,
+ 0x1fd0, 0x1fd3,
+ 0x1fd6, 0x1fdb,
+ 0x1fe0, 0x1fec,
+ 0x1ff2, 0x1ff4,
+ 0x1ff6, 0x1ffc,
+ 0x200c, 0x200d,
+ 0x203f, 0x2040,
+ 0x2054, 0x2054,
+ 0x2071, 0x2071,
+ 0x207f, 0x207f,
+ 0x2090, 0x209c,
+ 0x20d0, 0x20dc,
+ 0x20e1, 0x20e1,
+ 0x20e5, 0x20f0,
+ 0x2102, 0x2102,
+ 0x2107, 0x2107,
+ 0x210a, 0x2113,
+ 0x2115, 0x2115,
+ 0x2118, 0x211d,
+ 0x2124, 0x2124,
+ 0x2126, 0x2126,
+ 0x2128, 0x2128,
+ 0x212a, 0x2139,
+ 0x213c, 0x213f,
+ 0x2145, 0x2149,
+ 0x214e, 0x214e,
+ 0x2160, 0x2188,
+ 0x2c00, 0x2ce4,
+ 0x2ceb, 0x2cf3,
+ 0x2d00, 0x2d25,
+ 0x2d27, 0x2d27,
+ 0x2d2d, 0x2d2d,
+ 0x2d30, 0x2d67,
+ 0x2d6f, 0x2d6f,
+ 0x2d7f, 0x2d96,
+ 0x2da0, 0x2da6,
+ 0x2da8, 0x2dae,
+ 0x2db0, 0x2db6,
+ 0x2db8, 0x2dbe,
+ 0x2dc0, 0x2dc6,
+ 0x2dc8, 0x2dce,
+ 0x2dd0, 0x2dd6,
+ 0x2dd8, 0x2dde,
+ 0x2de0, 0x2dff,
+ 0x3005, 0x3007,
+ 0x3021, 0x302f,
+ 0x3031, 0x3035,
+ 0x3038, 0x303c,
+ 0x3041, 0x3096,
+ 0x3099, 0x309f,
+ 0x30a1, 0x30ff,
+ 0x3105, 0x312f,
+ 0x3131, 0x318e,
+ 0x31a0, 0x31bf,
+ 0x31f0, 0x31ff,
+ 0x3400, 0x4dbf,
+ 0x4e00, 0xa48c,
+ 0xa4d0, 0xa4fd,
+ 0xa500, 0xa60c,
+ 0xa610, 0xa62b,
+ 0xa640, 0xa66f,
+ 0xa674, 0xa67d,
+ 0xa67f, 0xa6f1,
+ 0xa717, 0xa71f,
+ 0xa722, 0xa788,
+ 0xa78b, 0xa7dc,
+ 0xa7f1, 0xa827,
+ 0xa82c, 0xa82c,
+ 0xa840, 0xa873,
+ 0xa880, 0xa8c5,
+ 0xa8d0, 0xa8d9,
+ 0xa8e0, 0xa8f7,
+ 0xa8fb, 0xa8fb,
+ 0xa8fd, 0xa92d,
+ 0xa930, 0xa953,
+ 0xa960, 0xa97c,
+ 0xa980, 0xa9c0,
+ 0xa9cf, 0xa9d9,
+ 0xa9e0, 0xa9fe,
+ 0xaa00, 0xaa36,
+ 0xaa40, 0xaa4d,
+ 0xaa50, 0xaa59,
+ 0xaa60, 0xaa76,
+ 0xaa7a, 0xaac2,
+ 0xaadb, 0xaadd,
+ 0xaae0, 0xaaef,
+ 0xaaf2, 0xaaf6,
+ 0xab01, 0xab06,
+ 0xab09, 0xab0e,
+ 0xab11, 0xab16,
+ 0xab20, 0xab26,
+ 0xab28, 0xab2e,
+ 0xab30, 0xab5a,
+ 0xab5c, 0xab69,
+ 0xab70, 0xabea,
+ 0xabec, 0xabed,
+ 0xabf0, 0xabf9,
+ 0xac00, 0xd7a3,
+ 0xd7b0, 0xd7c6,
+ 0xd7cb, 0xd7fb,
+ 0xf900, 0xfa6d,
+ 0xfa70, 0xfad9,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xfb1d, 0xfb28,
+ 0xfb2a, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfbb1,
+ 0xfbd3, 0xfd3d,
+ 0xfd50, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdf0, 0xfdfb,
+ 0xfe00, 0xfe0f,
+ 0xfe20, 0xfe2f,
+ 0xfe33, 0xfe34,
+ 0xfe4d, 0xfe4f,
+ 0xfe70, 0xfe74,
+ 0xfe76, 0xfefc,
+ 0xff10, 0xff19,
+ 0xff21, 0xff3a,
+ 0xff3f, 0xff3f,
+ 0xff41, 0xff5a,
+ 0xff65, 0xffbe,
+ 0xffc2, 0xffc7,
+ 0xffca, 0xffcf,
+ 0xffd2, 0xffd7,
+ 0xffda, 0xffdc,
+ 0x10000, 0x1000b,
+ 0x1000d, 0x10026,
+ 0x10028, 0x1003a,
+ 0x1003c, 0x1003d,
+ 0x1003f, 0x1004d,
+ 0x10050, 0x1005d,
+ 0x10080, 0x100fa,
+ 0x10140, 0x10174,
+ 0x101fd, 0x101fd,
+ 0x10280, 0x1029c,
+ 0x102a0, 0x102d0,
+ 0x102e0, 0x102e0,
+ 0x10300, 0x1031f,
+ 0x1032d, 0x1034a,
+ 0x10350, 0x1037a,
+ 0x10380, 0x1039d,
+ 0x103a0, 0x103c3,
+ 0x103c8, 0x103cf,
+ 0x103d1, 0x103d5,
+ 0x10400, 0x1049d,
+ 0x104a0, 0x104a9,
+ 0x104b0, 0x104d3,
+ 0x104d8, 0x104fb,
+ 0x10500, 0x10527,
+ 0x10530, 0x10563,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x105c0, 0x105f3,
+ 0x10600, 0x10736,
+ 0x10740, 0x10755,
+ 0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 0x10837, 0x10838,
+ 0x1083c, 0x1083c,
+ 0x1083f, 0x10855,
+ 0x10860, 0x10876,
+ 0x10880, 0x1089e,
+ 0x108e0, 0x108f2,
+ 0x108f4, 0x108f5,
+ 0x10900, 0x10915,
+ 0x10920, 0x10939,
+ 0x10940, 0x10959,
+ 0x10980, 0x109b7,
+ 0x109be, 0x109bf,
+ 0x10a00, 0x10a03,
+ 0x10a05, 0x10a06,
+ 0x10a0c, 0x10a13,
+ 0x10a15, 0x10a17,
+ 0x10a19, 0x10a35,
+ 0x10a38, 0x10a3a,
+ 0x10a3f, 0x10a3f,
+ 0x10a60, 0x10a7c,
+ 0x10a80, 0x10a9c,
+ 0x10ac0, 0x10ac7,
+ 0x10ac9, 0x10ae6,
+ 0x10b00, 0x10b35,
+ 0x10b40, 0x10b55,
+ 0x10b60, 0x10b72,
+ 0x10b80, 0x10b91,
+ 0x10c00, 0x10c48,
+ 0x10c80, 0x10cb2,
+ 0x10cc0, 0x10cf2,
+ 0x10d00, 0x10d27,
+ 0x10d30, 0x10d39,
+ 0x10d40, 0x10d65,
+ 0x10d69, 0x10d6d,
+ 0x10d6f, 0x10d85,
+ 0x10e80, 0x10ea9,
+ 0x10eab, 0x10eac,
+ 0x10eb0, 0x10eb1,
+ 0x10ec2, 0x10ec7,
+ 0x10efa, 0x10f1c,
+ 0x10f27, 0x10f27,
+ 0x10f30, 0x10f50,
+ 0x10f70, 0x10f85,
+ 0x10fb0, 0x10fc4,
+ 0x10fe0, 0x10ff6,
+ 0x11000, 0x11046,
+ 0x11066, 0x11075,
+ 0x1107f, 0x110ba,
+ 0x110c2, 0x110c2,
+ 0x110d0, 0x110e8,
+ 0x110f0, 0x110f9,
+ 0x11100, 0x11134,
+ 0x11136, 0x1113f,
+ 0x11144, 0x11147,
+ 0x11150, 0x11173,
+ 0x11176, 0x11176,
+ 0x11180, 0x111c4,
+ 0x111c9, 0x111cc,
+ 0x111ce, 0x111da,
+ 0x111dc, 0x111dc,
+ 0x11200, 0x11211,
+ 0x11213, 0x11237,
+ 0x1123e, 0x11241,
+ 0x11280, 0x11286,
+ 0x11288, 0x11288,
+ 0x1128a, 0x1128d,
+ 0x1128f, 0x1129d,
+ 0x1129f, 0x112a8,
+ 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,
+ 0x11380, 0x11389,
+ 0x1138b, 0x1138b,
+ 0x1138e, 0x1138e,
+ 0x11390, 0x113b5,
+ 0x113b7, 0x113c0,
+ 0x113c2, 0x113c2,
+ 0x113c5, 0x113c5,
+ 0x113c7, 0x113ca,
+ 0x113cc, 0x113d3,
+ 0x113e1, 0x113e2,
+ 0x11400, 0x1144a,
+ 0x11450, 0x11459,
+ 0x1145e, 0x11461,
+ 0x11480, 0x114c5,
+ 0x114c7, 0x114c7,
+ 0x114d0, 0x114d9,
+ 0x11580, 0x115b5,
+ 0x115b8, 0x115c0,
+ 0x115d8, 0x115dd,
+ 0x11600, 0x11640,
+ 0x11644, 0x11644,
+ 0x11650, 0x11659,
+ 0x11680, 0x116b8,
+ 0x116c0, 0x116c9,
+ 0x116d0, 0x116e3,
+ 0x11700, 0x1171a,
+ 0x1171d, 0x1172b,
+ 0x11730, 0x11739,
+ 0x11740, 0x11746,
+ 0x11800, 0x1183a,
+ 0x118a0, 0x118e9,
+ 0x118ff, 0x11906,
+ 0x11909, 0x11909,
+ 0x1190c, 0x11913,
+ 0x11915, 0x11916,
+ 0x11918, 0x11935,
+ 0x11937, 0x11938,
+ 0x1193b, 0x11943,
+ 0x11950, 0x11959,
+ 0x119a0, 0x119a7,
+ 0x119aa, 0x119d7,
+ 0x119da, 0x119e1,
+ 0x119e3, 0x119e4,
+ 0x11a00, 0x11a3e,
+ 0x11a47, 0x11a47,
+ 0x11a50, 0x11a99,
+ 0x11a9d, 0x11a9d,
+ 0x11ab0, 0x11af8,
+ 0x11b60, 0x11b67,
+ 0x11bc0, 0x11be0,
+ 0x11bf0, 0x11bf9,
+ 0x11c00, 0x11c08,
+ 0x11c0a, 0x11c36,
+ 0x11c38, 0x11c40,
+ 0x11c50, 0x11c59,
+ 0x11c72, 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,
+ 0x11db0, 0x11ddb,
+ 0x11de0, 0x11de9,
+ 0x11ee0, 0x11ef6,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f42,
+ 0x11f50, 0x11f5a,
+ 0x11fb0, 0x11fb0,
+ 0x12000, 0x12399,
+ 0x12400, 0x1246e,
+ 0x12480, 0x12543,
+ 0x12f90, 0x12ff0,
+ 0x13000, 0x1342f,
+ 0x13440, 0x13455,
+ 0x13460, 0x143fa,
+ 0x14400, 0x14646,
+ 0x16100, 0x16139,
+ 0x16800, 0x16a38,
+ 0x16a40, 0x16a5e,
+ 0x16a60, 0x16a69,
+ 0x16a70, 0x16abe,
+ 0x16ac0, 0x16ac9,
+ 0x16ad0, 0x16aed,
+ 0x16af0, 0x16af4,
+ 0x16b00, 0x16b36,
+ 0x16b40, 0x16b43,
+ 0x16b50, 0x16b59,
+ 0x16b63, 0x16b77,
+ 0x16b7d, 0x16b8f,
+ 0x16d40, 0x16d6c,
+ 0x16d70, 0x16d79,
+ 0x16e40, 0x16e7f,
+ 0x16ea0, 0x16eb8,
+ 0x16ebb, 0x16ed3,
+ 0x16f00, 0x16f4a,
+ 0x16f4f, 0x16f87,
+ 0x16f8f, 0x16f9f,
+ 0x16fe0, 0x16fe1,
+ 0x16fe3, 0x16fe4,
+ 0x16ff0, 0x16ff6,
+ 0x17000, 0x18cd5,
+ 0x18cff, 0x18d1e,
+ 0x18d80, 0x18df2,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
+ 0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
+ 0x1b164, 0x1b167,
+ 0x1b170, 0x1b2fb,
+ 0x1bc00, 0x1bc6a,
+ 0x1bc70, 0x1bc7c,
+ 0x1bc80, 0x1bc88,
+ 0x1bc90, 0x1bc99,
+ 0x1bc9d, 0x1bc9e,
+ 0x1ccf0, 0x1ccf9,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
+ 0x1d165, 0x1d169,
+ 0x1d16d, 0x1d172,
+ 0x1d17b, 0x1d182,
+ 0x1d185, 0x1d18b,
+ 0x1d1aa, 0x1d1ad,
+ 0x1d242, 0x1d244,
+ 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, 0x1d6c0,
+ 0x1d6c2, 0x1d6da,
+ 0x1d6dc, 0x1d6fa,
+ 0x1d6fc, 0x1d714,
+ 0x1d716, 0x1d734,
+ 0x1d736, 0x1d74e,
+ 0x1d750, 0x1d76e,
+ 0x1d770, 0x1d788,
+ 0x1d78a, 0x1d7a8,
+ 0x1d7aa, 0x1d7c2,
+ 0x1d7c4, 0x1d7cb,
+ 0x1d7ce, 0x1d7ff,
+ 0x1da00, 0x1da36,
+ 0x1da3b, 0x1da6c,
+ 0x1da75, 0x1da75,
+ 0x1da84, 0x1da84,
+ 0x1da9b, 0x1da9f,
+ 0x1daa1, 0x1daaf,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e000, 0x1e006,
+ 0x1e008, 0x1e018,
+ 0x1e01b, 0x1e021,
+ 0x1e023, 0x1e024,
+ 0x1e026, 0x1e02a,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
+ 0x1e100, 0x1e12c,
+ 0x1e130, 0x1e13d,
+ 0x1e140, 0x1e149,
+ 0x1e14e, 0x1e14e,
+ 0x1e290, 0x1e2ae,
+ 0x1e2c0, 0x1e2f9,
+ 0x1e4d0, 0x1e4f9,
+ 0x1e5d0, 0x1e5fa,
+ 0x1e6c0, 0x1e6de,
+ 0x1e6e0, 0x1e6f5,
+ 0x1e6fe, 0x1e6ff,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
+ 0x1e800, 0x1e8c4,
+ 0x1e8d0, 0x1e8d6,
+ 0x1e900, 0x1e94b,
+ 0x1e950, 0x1e959,
+ 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,
+ 0x1fbf0, 0x1fbf9,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b81d,
+ 0x2b820, 0x2cead,
+ 0x2ceb0, 0x2ebe0,
+ 0x2ebf0, 0x2ee5d,
+ 0x2f800, 0x2fa1d,
+ 0x30000, 0x3134a,
+ 0x31350, 0x33479,
+ 0xe0100, 0xe01ef,
+}; /* CR_ID_Continue */
+
+/* 'XID_Start': Derived Property */
+static const OnigCodePoint CR_XID_Start[] = {
+ 691,
+ 0x0041, 0x005a,
+ 0x0061, 0x007a,
+ 0x00aa, 0x00aa,
+ 0x00b5, 0x00b5,
+ 0x00ba, 0x00ba,
+ 0x00c0, 0x00d6,
+ 0x00d8, 0x00f6,
+ 0x00f8, 0x02c1,
+ 0x02c6, 0x02d1,
+ 0x02e0, 0x02e4,
+ 0x02ec, 0x02ec,
+ 0x02ee, 0x02ee,
+ 0x0370, 0x0374,
+ 0x0376, 0x0377,
+ 0x037b, 0x037d,
+ 0x037f, 0x037f,
+ 0x0386, 0x0386,
+ 0x0388, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x03f5,
+ 0x03f7, 0x0481,
+ 0x048a, 0x052f,
+ 0x0531, 0x0556,
+ 0x0559, 0x0559,
+ 0x0560, 0x0588,
+ 0x05d0, 0x05ea,
+ 0x05ef, 0x05f2,
+ 0x0620, 0x064a,
+ 0x066e, 0x066f,
+ 0x0671, 0x06d3,
+ 0x06d5, 0x06d5,
+ 0x06e5, 0x06e6,
+ 0x06ee, 0x06ef,
+ 0x06fa, 0x06fc,
+ 0x06ff, 0x06ff,
+ 0x0710, 0x0710,
+ 0x0712, 0x072f,
+ 0x074d, 0x07a5,
+ 0x07b1, 0x07b1,
+ 0x07ca, 0x07ea,
+ 0x07f4, 0x07f5,
+ 0x07fa, 0x07fa,
+ 0x0800, 0x0815,
+ 0x081a, 0x081a,
+ 0x0824, 0x0824,
+ 0x0828, 0x0828,
+ 0x0840, 0x0858,
+ 0x0860, 0x086a,
+ 0x0870, 0x0887,
+ 0x0889, 0x088f,
+ 0x08a0, 0x08c9,
+ 0x0904, 0x0939,
+ 0x093d, 0x093d,
+ 0x0950, 0x0950,
+ 0x0958, 0x0961,
+ 0x0971, 0x0980,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bd, 0x09bd,
+ 0x09ce, 0x09ce,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e1,
+ 0x09f0, 0x09f1,
+ 0x09fc, 0x09fc,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a72, 0x0a74,
+ 0x0a85, 0x0a8d,
+ 0x0a8f, 0x0a91,
+ 0x0a93, 0x0aa8,
+ 0x0aaa, 0x0ab0,
+ 0x0ab2, 0x0ab3,
+ 0x0ab5, 0x0ab9,
+ 0x0abd, 0x0abd,
+ 0x0ad0, 0x0ad0,
+ 0x0ae0, 0x0ae1,
+ 0x0af9, 0x0af9,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b35, 0x0b39,
+ 0x0b3d, 0x0b3d,
+ 0x0b5c, 0x0b5d,
+ 0x0b5f, 0x0b61,
+ 0x0b71, 0x0b71,
+ 0x0b83, 0x0b83,
+ 0x0b85, 0x0b8a,
+ 0x0b8e, 0x0b90,
+ 0x0b92, 0x0b95,
+ 0x0b99, 0x0b9a,
+ 0x0b9c, 0x0b9c,
+ 0x0b9e, 0x0b9f,
+ 0x0ba3, 0x0ba4,
+ 0x0ba8, 0x0baa,
+ 0x0bae, 0x0bb9,
+ 0x0bd0, 0x0bd0,
+ 0x0c05, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3d, 0x0c3d,
+ 0x0c58, 0x0c5a,
+ 0x0c5c, 0x0c5d,
+ 0x0c60, 0x0c61,
+ 0x0c80, 0x0c80,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbd, 0x0cbd,
+ 0x0cdc, 0x0cde,
+ 0x0ce0, 0x0ce1,
+ 0x0cf1, 0x0cf2,
+ 0x0d04, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d3a,
+ 0x0d3d, 0x0d3d,
+ 0x0d4e, 0x0d4e,
+ 0x0d54, 0x0d56,
+ 0x0d5f, 0x0d61,
+ 0x0d7a, 0x0d7f,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0e01, 0x0e30,
+ 0x0e32, 0x0e32,
+ 0x0e40, 0x0e46,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e86, 0x0e8a,
+ 0x0e8c, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0eb0,
+ 0x0eb2, 0x0eb2,
+ 0x0ebd, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f00,
+ 0x0f40, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f88, 0x0f8c,
+ 0x1000, 0x102a,
+ 0x103f, 0x103f,
+ 0x1050, 0x1055,
+ 0x105a, 0x105d,
+ 0x1061, 0x1061,
+ 0x1065, 0x1066,
+ 0x106e, 0x1070,
+ 0x1075, 0x1081,
+ 0x108e, 0x108e,
+ 0x10a0, 0x10c5,
+ 0x10c7, 0x10c7,
+ 0x10cd, 0x10cd,
+ 0x10d0, 0x10fa,
+ 0x10fc, 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,
+ 0x1380, 0x138f,
+ 0x13a0, 0x13f5,
+ 0x13f8, 0x13fd,
+ 0x1401, 0x166c,
+ 0x166f, 0x167f,
+ 0x1681, 0x169a,
+ 0x16a0, 0x16ea,
+ 0x16ee, 0x16f8,
+ 0x1700, 0x1711,
+ 0x171f, 0x1731,
+ 0x1740, 0x1751,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1780, 0x17b3,
+ 0x17d7, 0x17d7,
+ 0x17dc, 0x17dc,
+ 0x1820, 0x1878,
+ 0x1880, 0x18a8,
+ 0x18aa, 0x18aa,
+ 0x18b0, 0x18f5,
+ 0x1900, 0x191e,
+ 0x1950, 0x196d,
+ 0x1970, 0x1974,
+ 0x1980, 0x19ab,
+ 0x19b0, 0x19c9,
+ 0x1a00, 0x1a16,
+ 0x1a20, 0x1a54,
+ 0x1aa7, 0x1aa7,
+ 0x1b05, 0x1b33,
+ 0x1b45, 0x1b4c,
+ 0x1b83, 0x1ba0,
+ 0x1bae, 0x1baf,
+ 0x1bba, 0x1be5,
+ 0x1c00, 0x1c23,
+ 0x1c4d, 0x1c4f,
+ 0x1c5a, 0x1c7d,
+ 0x1c80, 0x1c8a,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cbf,
+ 0x1ce9, 0x1cec,
+ 0x1cee, 0x1cf3,
+ 0x1cf5, 0x1cf6,
+ 0x1cfa, 0x1cfa,
+ 0x1d00, 0x1dbf,
+ 0x1e00, 0x1f15,
+ 0x1f18, 0x1f1d,
+ 0x1f20, 0x1f45,
+ 0x1f48, 0x1f4d,
+ 0x1f50, 0x1f57,
+ 0x1f59, 0x1f59,
+ 0x1f5b, 0x1f5b,
+ 0x1f5d, 0x1f5d,
+ 0x1f5f, 0x1f7d,
+ 0x1f80, 0x1fb4,
+ 0x1fb6, 0x1fbc,
+ 0x1fbe, 0x1fbe,
+ 0x1fc2, 0x1fc4,
+ 0x1fc6, 0x1fcc,
+ 0x1fd0, 0x1fd3,
+ 0x1fd6, 0x1fdb,
+ 0x1fe0, 0x1fec,
+ 0x1ff2, 0x1ff4,
+ 0x1ff6, 0x1ffc,
+ 0x2071, 0x2071,
+ 0x207f, 0x207f,
+ 0x2090, 0x209c,
+ 0x2102, 0x2102,
+ 0x2107, 0x2107,
+ 0x210a, 0x2113,
+ 0x2115, 0x2115,
+ 0x2118, 0x211d,
+ 0x2124, 0x2124,
+ 0x2126, 0x2126,
+ 0x2128, 0x2128,
+ 0x212a, 0x2139,
+ 0x213c, 0x213f,
+ 0x2145, 0x2149,
+ 0x214e, 0x214e,
+ 0x2160, 0x2188,
+ 0x2c00, 0x2ce4,
+ 0x2ceb, 0x2cee,
+ 0x2cf2, 0x2cf3,
+ 0x2d00, 0x2d25,
+ 0x2d27, 0x2d27,
+ 0x2d2d, 0x2d2d,
+ 0x2d30, 0x2d67,
+ 0x2d6f, 0x2d6f,
+ 0x2d80, 0x2d96,
+ 0x2da0, 0x2da6,
+ 0x2da8, 0x2dae,
+ 0x2db0, 0x2db6,
+ 0x2db8, 0x2dbe,
+ 0x2dc0, 0x2dc6,
+ 0x2dc8, 0x2dce,
+ 0x2dd0, 0x2dd6,
+ 0x2dd8, 0x2dde,
+ 0x3005, 0x3007,
+ 0x3021, 0x3029,
+ 0x3031, 0x3035,
+ 0x3038, 0x303c,
+ 0x3041, 0x3096,
+ 0x309d, 0x309f,
+ 0x30a1, 0x30fa,
+ 0x30fc, 0x30ff,
+ 0x3105, 0x312f,
+ 0x3131, 0x318e,
+ 0x31a0, 0x31bf,
+ 0x31f0, 0x31ff,
+ 0x3400, 0x4dbf,
+ 0x4e00, 0xa48c,
+ 0xa4d0, 0xa4fd,
+ 0xa500, 0xa60c,
+ 0xa610, 0xa61f,
+ 0xa62a, 0xa62b,
+ 0xa640, 0xa66e,
+ 0xa67f, 0xa69d,
+ 0xa6a0, 0xa6ef,
+ 0xa717, 0xa71f,
+ 0xa722, 0xa788,
+ 0xa78b, 0xa7dc,
+ 0xa7f1, 0xa801,
+ 0xa803, 0xa805,
+ 0xa807, 0xa80a,
+ 0xa80c, 0xa822,
+ 0xa840, 0xa873,
+ 0xa882, 0xa8b3,
+ 0xa8f2, 0xa8f7,
+ 0xa8fb, 0xa8fb,
+ 0xa8fd, 0xa8fe,
+ 0xa90a, 0xa925,
+ 0xa930, 0xa946,
+ 0xa960, 0xa97c,
+ 0xa984, 0xa9b2,
+ 0xa9cf, 0xa9cf,
+ 0xa9e0, 0xa9e4,
+ 0xa9e6, 0xa9ef,
+ 0xa9fa, 0xa9fe,
+ 0xaa00, 0xaa28,
+ 0xaa40, 0xaa42,
+ 0xaa44, 0xaa4b,
+ 0xaa60, 0xaa76,
+ 0xaa7a, 0xaa7a,
+ 0xaa7e, 0xaaaf,
+ 0xaab1, 0xaab1,
+ 0xaab5, 0xaab6,
+ 0xaab9, 0xaabd,
+ 0xaac0, 0xaac0,
+ 0xaac2, 0xaac2,
+ 0xaadb, 0xaadd,
+ 0xaae0, 0xaaea,
+ 0xaaf2, 0xaaf4,
+ 0xab01, 0xab06,
+ 0xab09, 0xab0e,
+ 0xab11, 0xab16,
+ 0xab20, 0xab26,
+ 0xab28, 0xab2e,
+ 0xab30, 0xab5a,
+ 0xab5c, 0xab69,
+ 0xab70, 0xabe2,
+ 0xac00, 0xd7a3,
+ 0xd7b0, 0xd7c6,
+ 0xd7cb, 0xd7fb,
+ 0xf900, 0xfa6d,
+ 0xfa70, 0xfad9,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xfb1d, 0xfb1d,
+ 0xfb1f, 0xfb28,
+ 0xfb2a, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfbb1,
+ 0xfbd3, 0xfc5d,
+ 0xfc64, 0xfd3d,
+ 0xfd50, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdf0, 0xfdf9,
+ 0xfe71, 0xfe71,
+ 0xfe73, 0xfe73,
+ 0xfe77, 0xfe77,
+ 0xfe79, 0xfe79,
+ 0xfe7b, 0xfe7b,
+ 0xfe7d, 0xfe7d,
+ 0xfe7f, 0xfefc,
+ 0xff21, 0xff3a,
+ 0xff41, 0xff5a,
+ 0xff66, 0xff9d,
+ 0xffa0, 0xffbe,
+ 0xffc2, 0xffc7,
+ 0xffca, 0xffcf,
+ 0xffd2, 0xffd7,
+ 0xffda, 0xffdc,
+ 0x10000, 0x1000b,
+ 0x1000d, 0x10026,
+ 0x10028, 0x1003a,
+ 0x1003c, 0x1003d,
+ 0x1003f, 0x1004d,
+ 0x10050, 0x1005d,
+ 0x10080, 0x100fa,
+ 0x10140, 0x10174,
+ 0x10280, 0x1029c,
+ 0x102a0, 0x102d0,
+ 0x10300, 0x1031f,
+ 0x1032d, 0x1034a,
+ 0x10350, 0x10375,
+ 0x10380, 0x1039d,
+ 0x103a0, 0x103c3,
+ 0x103c8, 0x103cf,
+ 0x103d1, 0x103d5,
+ 0x10400, 0x1049d,
+ 0x104b0, 0x104d3,
+ 0x104d8, 0x104fb,
+ 0x10500, 0x10527,
+ 0x10530, 0x10563,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x105c0, 0x105f3,
+ 0x10600, 0x10736,
+ 0x10740, 0x10755,
+ 0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 0x10837, 0x10838,
+ 0x1083c, 0x1083c,
+ 0x1083f, 0x10855,
+ 0x10860, 0x10876,
+ 0x10880, 0x1089e,
+ 0x108e0, 0x108f2,
+ 0x108f4, 0x108f5,
+ 0x10900, 0x10915,
+ 0x10920, 0x10939,
+ 0x10940, 0x10959,
+ 0x10980, 0x109b7,
+ 0x109be, 0x109bf,
+ 0x10a00, 0x10a00,
+ 0x10a10, 0x10a13,
+ 0x10a15, 0x10a17,
+ 0x10a19, 0x10a35,
+ 0x10a60, 0x10a7c,
+ 0x10a80, 0x10a9c,
+ 0x10ac0, 0x10ac7,
+ 0x10ac9, 0x10ae4,
+ 0x10b00, 0x10b35,
+ 0x10b40, 0x10b55,
+ 0x10b60, 0x10b72,
+ 0x10b80, 0x10b91,
+ 0x10c00, 0x10c48,
+ 0x10c80, 0x10cb2,
+ 0x10cc0, 0x10cf2,
+ 0x10d00, 0x10d23,
+ 0x10d4a, 0x10d65,
+ 0x10d6f, 0x10d85,
+ 0x10e80, 0x10ea9,
+ 0x10eb0, 0x10eb1,
+ 0x10ec2, 0x10ec7,
+ 0x10f00, 0x10f1c,
+ 0x10f27, 0x10f27,
+ 0x10f30, 0x10f45,
+ 0x10f70, 0x10f81,
+ 0x10fb0, 0x10fc4,
+ 0x10fe0, 0x10ff6,
+ 0x11003, 0x11037,
+ 0x11071, 0x11072,
+ 0x11075, 0x11075,
+ 0x11083, 0x110af,
+ 0x110d0, 0x110e8,
+ 0x11103, 0x11126,
+ 0x11144, 0x11144,
+ 0x11147, 0x11147,
+ 0x11150, 0x11172,
+ 0x11176, 0x11176,
+ 0x11183, 0x111b2,
+ 0x111c1, 0x111c4,
+ 0x111da, 0x111da,
+ 0x111dc, 0x111dc,
+ 0x11200, 0x11211,
+ 0x11213, 0x1122b,
+ 0x1123f, 0x11240,
+ 0x11280, 0x11286,
+ 0x11288, 0x11288,
+ 0x1128a, 0x1128d,
+ 0x1128f, 0x1129d,
+ 0x1129f, 0x112a8,
+ 0x112b0, 0x112de,
+ 0x11305, 0x1130c,
+ 0x1130f, 0x11310,
+ 0x11313, 0x11328,
+ 0x1132a, 0x11330,
+ 0x11332, 0x11333,
+ 0x11335, 0x11339,
+ 0x1133d, 0x1133d,
+ 0x11350, 0x11350,
+ 0x1135d, 0x11361,
+ 0x11380, 0x11389,
+ 0x1138b, 0x1138b,
+ 0x1138e, 0x1138e,
+ 0x11390, 0x113b5,
+ 0x113b7, 0x113b7,
+ 0x113d1, 0x113d1,
+ 0x113d3, 0x113d3,
+ 0x11400, 0x11434,
+ 0x11447, 0x1144a,
+ 0x1145f, 0x11461,
+ 0x11480, 0x114af,
+ 0x114c4, 0x114c5,
+ 0x114c7, 0x114c7,
+ 0x11580, 0x115ae,
+ 0x115d8, 0x115db,
+ 0x11600, 0x1162f,
+ 0x11644, 0x11644,
+ 0x11680, 0x116aa,
+ 0x116b8, 0x116b8,
+ 0x11700, 0x1171a,
+ 0x11740, 0x11746,
+ 0x11800, 0x1182b,
+ 0x118a0, 0x118df,
+ 0x118ff, 0x11906,
+ 0x11909, 0x11909,
+ 0x1190c, 0x11913,
+ 0x11915, 0x11916,
+ 0x11918, 0x1192f,
+ 0x1193f, 0x1193f,
+ 0x11941, 0x11941,
+ 0x119a0, 0x119a7,
+ 0x119aa, 0x119d0,
+ 0x119e1, 0x119e1,
+ 0x119e3, 0x119e3,
+ 0x11a00, 0x11a00,
+ 0x11a0b, 0x11a32,
+ 0x11a3a, 0x11a3a,
+ 0x11a50, 0x11a50,
+ 0x11a5c, 0x11a89,
+ 0x11a9d, 0x11a9d,
+ 0x11ab0, 0x11af8,
+ 0x11bc0, 0x11be0,
+ 0x11c00, 0x11c08,
+ 0x11c0a, 0x11c2e,
+ 0x11c40, 0x11c40,
+ 0x11c72, 0x11c8f,
+ 0x11d00, 0x11d06,
+ 0x11d08, 0x11d09,
+ 0x11d0b, 0x11d30,
+ 0x11d46, 0x11d46,
+ 0x11d60, 0x11d65,
+ 0x11d67, 0x11d68,
+ 0x11d6a, 0x11d89,
+ 0x11d98, 0x11d98,
+ 0x11db0, 0x11ddb,
+ 0x11ee0, 0x11ef2,
+ 0x11f02, 0x11f02,
+ 0x11f04, 0x11f10,
+ 0x11f12, 0x11f33,
+ 0x11fb0, 0x11fb0,
+ 0x12000, 0x12399,
+ 0x12400, 0x1246e,
+ 0x12480, 0x12543,
+ 0x12f90, 0x12ff0,
+ 0x13000, 0x1342f,
+ 0x13441, 0x13446,
+ 0x13460, 0x143fa,
+ 0x14400, 0x14646,
+ 0x16100, 0x1611d,
+ 0x16800, 0x16a38,
+ 0x16a40, 0x16a5e,
+ 0x16a70, 0x16abe,
+ 0x16ad0, 0x16aed,
+ 0x16b00, 0x16b2f,
+ 0x16b40, 0x16b43,
+ 0x16b63, 0x16b77,
+ 0x16b7d, 0x16b8f,
+ 0x16d40, 0x16d6c,
+ 0x16e40, 0x16e7f,
+ 0x16ea0, 0x16eb8,
+ 0x16ebb, 0x16ed3,
+ 0x16f00, 0x16f4a,
+ 0x16f50, 0x16f50,
+ 0x16f93, 0x16f9f,
+ 0x16fe0, 0x16fe1,
+ 0x16fe3, 0x16fe3,
+ 0x16ff2, 0x16ff6,
+ 0x17000, 0x18cd5,
+ 0x18cff, 0x18d1e,
+ 0x18d80, 0x18df2,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
+ 0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
+ 0x1b164, 0x1b167,
+ 0x1b170, 0x1b2fb,
+ 0x1bc00, 0x1bc6a,
+ 0x1bc70, 0x1bc7c,
+ 0x1bc80, 0x1bc88,
+ 0x1bc90, 0x1bc99,
+ 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, 0x1d6c0,
+ 0x1d6c2, 0x1d6da,
+ 0x1d6dc, 0x1d6fa,
+ 0x1d6fc, 0x1d714,
+ 0x1d716, 0x1d734,
+ 0x1d736, 0x1d74e,
+ 0x1d750, 0x1d76e,
+ 0x1d770, 0x1d788,
+ 0x1d78a, 0x1d7a8,
+ 0x1d7aa, 0x1d7c2,
+ 0x1d7c4, 0x1d7cb,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e030, 0x1e06d,
+ 0x1e100, 0x1e12c,
+ 0x1e137, 0x1e13d,
+ 0x1e14e, 0x1e14e,
+ 0x1e290, 0x1e2ad,
+ 0x1e2c0, 0x1e2eb,
+ 0x1e4d0, 0x1e4eb,
+ 0x1e5d0, 0x1e5ed,
+ 0x1e5f0, 0x1e5f0,
+ 0x1e6c0, 0x1e6de,
+ 0x1e6e0, 0x1e6e2,
+ 0x1e6e4, 0x1e6e5,
+ 0x1e6e7, 0x1e6ed,
+ 0x1e6f0, 0x1e6f4,
+ 0x1e6fe, 0x1e6ff,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
+ 0x1e800, 0x1e8c4,
+ 0x1e900, 0x1e943,
+ 0x1e94b, 0x1e94b,
+ 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,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b81d,
+ 0x2b820, 0x2cead,
+ 0x2ceb0, 0x2ebe0,
+ 0x2ebf0, 0x2ee5d,
+ 0x2f800, 0x2fa1d,
+ 0x30000, 0x3134a,
+ 0x31350, 0x33479,
+}; /* CR_XID_Start */
+
+/* 'XID_Continue': Derived Property */
+static const OnigCodePoint CR_XID_Continue[] = {
+ 806,
+ 0x0030, 0x0039,
+ 0x0041, 0x005a,
+ 0x005f, 0x005f,
+ 0x0061, 0x007a,
+ 0x00aa, 0x00aa,
+ 0x00b5, 0x00b5,
+ 0x00b7, 0x00b7,
+ 0x00ba, 0x00ba,
+ 0x00c0, 0x00d6,
+ 0x00d8, 0x00f6,
+ 0x00f8, 0x02c1,
+ 0x02c6, 0x02d1,
+ 0x02e0, 0x02e4,
+ 0x02ec, 0x02ec,
+ 0x02ee, 0x02ee,
+ 0x0300, 0x0374,
+ 0x0376, 0x0377,
+ 0x037b, 0x037d,
+ 0x037f, 0x037f,
+ 0x0386, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x03f5,
+ 0x03f7, 0x0481,
+ 0x0483, 0x0487,
+ 0x048a, 0x052f,
+ 0x0531, 0x0556,
+ 0x0559, 0x0559,
+ 0x0560, 0x0588,
+ 0x0591, 0x05bd,
+ 0x05bf, 0x05bf,
+ 0x05c1, 0x05c2,
+ 0x05c4, 0x05c5,
+ 0x05c7, 0x05c7,
+ 0x05d0, 0x05ea,
+ 0x05ef, 0x05f2,
+ 0x0610, 0x061a,
+ 0x0620, 0x0669,
+ 0x066e, 0x06d3,
+ 0x06d5, 0x06dc,
+ 0x06df, 0x06e8,
+ 0x06ea, 0x06fc,
+ 0x06ff, 0x06ff,
+ 0x0710, 0x074a,
+ 0x074d, 0x07b1,
+ 0x07c0, 0x07f5,
+ 0x07fa, 0x07fa,
+ 0x07fd, 0x07fd,
+ 0x0800, 0x082d,
+ 0x0840, 0x085b,
+ 0x0860, 0x086a,
+ 0x0870, 0x0887,
+ 0x0889, 0x088f,
+ 0x0897, 0x08e1,
+ 0x08e3, 0x0963,
+ 0x0966, 0x096f,
+ 0x0971, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09f1,
+ 0x09fc, 0x09fc,
+ 0x09fe, 0x09fe,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a75,
+ 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, 0x0aef,
+ 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, 0x0b6f,
+ 0x0b71, 0x0b71,
+ 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,
+ 0x0be6, 0x0bef,
+ 0x0c00, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3c, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c5a,
+ 0x0c5c, 0x0c5d,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c80, 0x0c83,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cdc, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf3,
+ 0x0d00, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d44,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4e,
+ 0x0d54, 0x0d57,
+ 0x0d5f, 0x0d63,
+ 0x0d66, 0x0d6f,
+ 0x0d7a, 0x0d7f,
+ 0x0d81, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0de6, 0x0def,
+ 0x0df2, 0x0df3,
+ 0x0e01, 0x0e3a,
+ 0x0e40, 0x0e4e,
+ 0x0e50, 0x0e59,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e86, 0x0e8a,
+ 0x0e8c, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ece,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f00,
+ 0x0f18, 0x0f19,
+ 0x0f20, 0x0f29,
+ 0x0f35, 0x0f35,
+ 0x0f37, 0x0f37,
+ 0x0f39, 0x0f39,
+ 0x0f3e, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f84,
+ 0x0f86, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 0x0fc6, 0x0fc6,
+ 0x1000, 0x1049,
+ 0x1050, 0x109d,
+ 0x10a0, 0x10c5,
+ 0x10c7, 0x10c7,
+ 0x10cd, 0x10cd,
+ 0x10d0, 0x10fa,
+ 0x10fc, 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, 0x135f,
+ 0x1369, 0x1371,
+ 0x1380, 0x138f,
+ 0x13a0, 0x13f5,
+ 0x13f8, 0x13fd,
+ 0x1401, 0x166c,
+ 0x166f, 0x167f,
+ 0x1681, 0x169a,
+ 0x16a0, 0x16ea,
+ 0x16ee, 0x16f8,
+ 0x1700, 0x1715,
+ 0x171f, 0x1734,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17d3,
+ 0x17d7, 0x17d7,
+ 0x17dc, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x180b, 0x180d,
+ 0x180f, 0x1819,
+ 0x1820, 0x1878,
+ 0x1880, 0x18aa,
+ 0x18b0, 0x18f5,
+ 0x1900, 0x191e,
+ 0x1920, 0x192b,
+ 0x1930, 0x193b,
+ 0x1946, 0x196d,
+ 0x1970, 0x1974,
+ 0x1980, 0x19ab,
+ 0x19b0, 0x19c9,
+ 0x19d0, 0x19da,
+ 0x1a00, 0x1a1b,
+ 0x1a20, 0x1a5e,
+ 0x1a60, 0x1a7c,
+ 0x1a7f, 0x1a89,
+ 0x1a90, 0x1a99,
+ 0x1aa7, 0x1aa7,
+ 0x1ab0, 0x1abd,
+ 0x1abf, 0x1add,
+ 0x1ae0, 0x1aeb,
+ 0x1b00, 0x1b4c,
+ 0x1b50, 0x1b59,
+ 0x1b6b, 0x1b73,
+ 0x1b80, 0x1bf3,
+ 0x1c00, 0x1c37,
+ 0x1c40, 0x1c49,
+ 0x1c4d, 0x1c7d,
+ 0x1c80, 0x1c8a,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cbf,
+ 0x1cd0, 0x1cd2,
+ 0x1cd4, 0x1cfa,
+ 0x1d00, 0x1f15,
+ 0x1f18, 0x1f1d,
+ 0x1f20, 0x1f45,
+ 0x1f48, 0x1f4d,
+ 0x1f50, 0x1f57,
+ 0x1f59, 0x1f59,
+ 0x1f5b, 0x1f5b,
+ 0x1f5d, 0x1f5d,
+ 0x1f5f, 0x1f7d,
+ 0x1f80, 0x1fb4,
+ 0x1fb6, 0x1fbc,
+ 0x1fbe, 0x1fbe,
+ 0x1fc2, 0x1fc4,
+ 0x1fc6, 0x1fcc,
+ 0x1fd0, 0x1fd3,
+ 0x1fd6, 0x1fdb,
+ 0x1fe0, 0x1fec,
+ 0x1ff2, 0x1ff4,
+ 0x1ff6, 0x1ffc,
+ 0x200c, 0x200d,
+ 0x203f, 0x2040,
+ 0x2054, 0x2054,
+ 0x2071, 0x2071,
+ 0x207f, 0x207f,
+ 0x2090, 0x209c,
+ 0x20d0, 0x20dc,
+ 0x20e1, 0x20e1,
+ 0x20e5, 0x20f0,
+ 0x2102, 0x2102,
+ 0x2107, 0x2107,
+ 0x210a, 0x2113,
+ 0x2115, 0x2115,
+ 0x2118, 0x211d,
+ 0x2124, 0x2124,
+ 0x2126, 0x2126,
+ 0x2128, 0x2128,
+ 0x212a, 0x2139,
+ 0x213c, 0x213f,
+ 0x2145, 0x2149,
+ 0x214e, 0x214e,
+ 0x2160, 0x2188,
+ 0x2c00, 0x2ce4,
+ 0x2ceb, 0x2cf3,
+ 0x2d00, 0x2d25,
+ 0x2d27, 0x2d27,
+ 0x2d2d, 0x2d2d,
+ 0x2d30, 0x2d67,
+ 0x2d6f, 0x2d6f,
+ 0x2d7f, 0x2d96,
+ 0x2da0, 0x2da6,
+ 0x2da8, 0x2dae,
+ 0x2db0, 0x2db6,
+ 0x2db8, 0x2dbe,
+ 0x2dc0, 0x2dc6,
+ 0x2dc8, 0x2dce,
+ 0x2dd0, 0x2dd6,
+ 0x2dd8, 0x2dde,
+ 0x2de0, 0x2dff,
+ 0x3005, 0x3007,
+ 0x3021, 0x302f,
+ 0x3031, 0x3035,
+ 0x3038, 0x303c,
+ 0x3041, 0x3096,
+ 0x3099, 0x309a,
+ 0x309d, 0x309f,
+ 0x30a1, 0x30ff,
+ 0x3105, 0x312f,
+ 0x3131, 0x318e,
+ 0x31a0, 0x31bf,
+ 0x31f0, 0x31ff,
+ 0x3400, 0x4dbf,
+ 0x4e00, 0xa48c,
+ 0xa4d0, 0xa4fd,
+ 0xa500, 0xa60c,
+ 0xa610, 0xa62b,
+ 0xa640, 0xa66f,
+ 0xa674, 0xa67d,
+ 0xa67f, 0xa6f1,
+ 0xa717, 0xa71f,
+ 0xa722, 0xa788,
+ 0xa78b, 0xa7dc,
+ 0xa7f1, 0xa827,
+ 0xa82c, 0xa82c,
+ 0xa840, 0xa873,
+ 0xa880, 0xa8c5,
+ 0xa8d0, 0xa8d9,
+ 0xa8e0, 0xa8f7,
+ 0xa8fb, 0xa8fb,
+ 0xa8fd, 0xa92d,
+ 0xa930, 0xa953,
+ 0xa960, 0xa97c,
+ 0xa980, 0xa9c0,
+ 0xa9cf, 0xa9d9,
+ 0xa9e0, 0xa9fe,
+ 0xaa00, 0xaa36,
+ 0xaa40, 0xaa4d,
+ 0xaa50, 0xaa59,
+ 0xaa60, 0xaa76,
+ 0xaa7a, 0xaac2,
+ 0xaadb, 0xaadd,
+ 0xaae0, 0xaaef,
+ 0xaaf2, 0xaaf6,
+ 0xab01, 0xab06,
+ 0xab09, 0xab0e,
+ 0xab11, 0xab16,
+ 0xab20, 0xab26,
+ 0xab28, 0xab2e,
+ 0xab30, 0xab5a,
+ 0xab5c, 0xab69,
+ 0xab70, 0xabea,
+ 0xabec, 0xabed,
+ 0xabf0, 0xabf9,
+ 0xac00, 0xd7a3,
+ 0xd7b0, 0xd7c6,
+ 0xd7cb, 0xd7fb,
+ 0xf900, 0xfa6d,
+ 0xfa70, 0xfad9,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xfb1d, 0xfb28,
+ 0xfb2a, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfbb1,
+ 0xfbd3, 0xfc5d,
+ 0xfc64, 0xfd3d,
+ 0xfd50, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdf0, 0xfdf9,
+ 0xfe00, 0xfe0f,
+ 0xfe20, 0xfe2f,
+ 0xfe33, 0xfe34,
+ 0xfe4d, 0xfe4f,
+ 0xfe71, 0xfe71,
+ 0xfe73, 0xfe73,
+ 0xfe77, 0xfe77,
+ 0xfe79, 0xfe79,
+ 0xfe7b, 0xfe7b,
+ 0xfe7d, 0xfe7d,
+ 0xfe7f, 0xfefc,
+ 0xff10, 0xff19,
+ 0xff21, 0xff3a,
+ 0xff3f, 0xff3f,
+ 0xff41, 0xff5a,
+ 0xff65, 0xffbe,
+ 0xffc2, 0xffc7,
+ 0xffca, 0xffcf,
+ 0xffd2, 0xffd7,
+ 0xffda, 0xffdc,
+ 0x10000, 0x1000b,
+ 0x1000d, 0x10026,
+ 0x10028, 0x1003a,
+ 0x1003c, 0x1003d,
+ 0x1003f, 0x1004d,
+ 0x10050, 0x1005d,
+ 0x10080, 0x100fa,
+ 0x10140, 0x10174,
+ 0x101fd, 0x101fd,
+ 0x10280, 0x1029c,
+ 0x102a0, 0x102d0,
+ 0x102e0, 0x102e0,
+ 0x10300, 0x1031f,
+ 0x1032d, 0x1034a,
+ 0x10350, 0x1037a,
+ 0x10380, 0x1039d,
+ 0x103a0, 0x103c3,
+ 0x103c8, 0x103cf,
+ 0x103d1, 0x103d5,
+ 0x10400, 0x1049d,
+ 0x104a0, 0x104a9,
+ 0x104b0, 0x104d3,
+ 0x104d8, 0x104fb,
+ 0x10500, 0x10527,
+ 0x10530, 0x10563,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x105c0, 0x105f3,
+ 0x10600, 0x10736,
+ 0x10740, 0x10755,
+ 0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 0x10837, 0x10838,
+ 0x1083c, 0x1083c,
+ 0x1083f, 0x10855,
+ 0x10860, 0x10876,
+ 0x10880, 0x1089e,
+ 0x108e0, 0x108f2,
+ 0x108f4, 0x108f5,
+ 0x10900, 0x10915,
+ 0x10920, 0x10939,
+ 0x10940, 0x10959,
+ 0x10980, 0x109b7,
+ 0x109be, 0x109bf,
+ 0x10a00, 0x10a03,
+ 0x10a05, 0x10a06,
+ 0x10a0c, 0x10a13,
+ 0x10a15, 0x10a17,
+ 0x10a19, 0x10a35,
+ 0x10a38, 0x10a3a,
+ 0x10a3f, 0x10a3f,
+ 0x10a60, 0x10a7c,
+ 0x10a80, 0x10a9c,
+ 0x10ac0, 0x10ac7,
+ 0x10ac9, 0x10ae6,
+ 0x10b00, 0x10b35,
+ 0x10b40, 0x10b55,
+ 0x10b60, 0x10b72,
+ 0x10b80, 0x10b91,
+ 0x10c00, 0x10c48,
+ 0x10c80, 0x10cb2,
+ 0x10cc0, 0x10cf2,
+ 0x10d00, 0x10d27,
+ 0x10d30, 0x10d39,
+ 0x10d40, 0x10d65,
+ 0x10d69, 0x10d6d,
+ 0x10d6f, 0x10d85,
+ 0x10e80, 0x10ea9,
+ 0x10eab, 0x10eac,
+ 0x10eb0, 0x10eb1,
+ 0x10ec2, 0x10ec7,
+ 0x10efa, 0x10f1c,
+ 0x10f27, 0x10f27,
+ 0x10f30, 0x10f50,
+ 0x10f70, 0x10f85,
+ 0x10fb0, 0x10fc4,
+ 0x10fe0, 0x10ff6,
+ 0x11000, 0x11046,
+ 0x11066, 0x11075,
+ 0x1107f, 0x110ba,
+ 0x110c2, 0x110c2,
+ 0x110d0, 0x110e8,
+ 0x110f0, 0x110f9,
+ 0x11100, 0x11134,
+ 0x11136, 0x1113f,
+ 0x11144, 0x11147,
+ 0x11150, 0x11173,
+ 0x11176, 0x11176,
+ 0x11180, 0x111c4,
+ 0x111c9, 0x111cc,
+ 0x111ce, 0x111da,
+ 0x111dc, 0x111dc,
+ 0x11200, 0x11211,
+ 0x11213, 0x11237,
+ 0x1123e, 0x11241,
+ 0x11280, 0x11286,
+ 0x11288, 0x11288,
+ 0x1128a, 0x1128d,
+ 0x1128f, 0x1129d,
+ 0x1129f, 0x112a8,
+ 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,
+ 0x11380, 0x11389,
+ 0x1138b, 0x1138b,
+ 0x1138e, 0x1138e,
+ 0x11390, 0x113b5,
+ 0x113b7, 0x113c0,
+ 0x113c2, 0x113c2,
+ 0x113c5, 0x113c5,
+ 0x113c7, 0x113ca,
+ 0x113cc, 0x113d3,
+ 0x113e1, 0x113e2,
+ 0x11400, 0x1144a,
+ 0x11450, 0x11459,
+ 0x1145e, 0x11461,
+ 0x11480, 0x114c5,
+ 0x114c7, 0x114c7,
+ 0x114d0, 0x114d9,
+ 0x11580, 0x115b5,
+ 0x115b8, 0x115c0,
+ 0x115d8, 0x115dd,
+ 0x11600, 0x11640,
+ 0x11644, 0x11644,
+ 0x11650, 0x11659,
+ 0x11680, 0x116b8,
+ 0x116c0, 0x116c9,
+ 0x116d0, 0x116e3,
+ 0x11700, 0x1171a,
+ 0x1171d, 0x1172b,
+ 0x11730, 0x11739,
+ 0x11740, 0x11746,
+ 0x11800, 0x1183a,
+ 0x118a0, 0x118e9,
+ 0x118ff, 0x11906,
+ 0x11909, 0x11909,
+ 0x1190c, 0x11913,
+ 0x11915, 0x11916,
+ 0x11918, 0x11935,
+ 0x11937, 0x11938,
+ 0x1193b, 0x11943,
+ 0x11950, 0x11959,
+ 0x119a0, 0x119a7,
+ 0x119aa, 0x119d7,
+ 0x119da, 0x119e1,
+ 0x119e3, 0x119e4,
+ 0x11a00, 0x11a3e,
+ 0x11a47, 0x11a47,
+ 0x11a50, 0x11a99,
+ 0x11a9d, 0x11a9d,
+ 0x11ab0, 0x11af8,
+ 0x11b60, 0x11b67,
+ 0x11bc0, 0x11be0,
+ 0x11bf0, 0x11bf9,
+ 0x11c00, 0x11c08,
+ 0x11c0a, 0x11c36,
+ 0x11c38, 0x11c40,
+ 0x11c50, 0x11c59,
+ 0x11c72, 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,
+ 0x11db0, 0x11ddb,
+ 0x11de0, 0x11de9,
+ 0x11ee0, 0x11ef6,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f42,
+ 0x11f50, 0x11f5a,
+ 0x11fb0, 0x11fb0,
+ 0x12000, 0x12399,
+ 0x12400, 0x1246e,
+ 0x12480, 0x12543,
+ 0x12f90, 0x12ff0,
+ 0x13000, 0x1342f,
+ 0x13440, 0x13455,
+ 0x13460, 0x143fa,
+ 0x14400, 0x14646,
+ 0x16100, 0x16139,
+ 0x16800, 0x16a38,
+ 0x16a40, 0x16a5e,
+ 0x16a60, 0x16a69,
+ 0x16a70, 0x16abe,
+ 0x16ac0, 0x16ac9,
+ 0x16ad0, 0x16aed,
+ 0x16af0, 0x16af4,
+ 0x16b00, 0x16b36,
+ 0x16b40, 0x16b43,
+ 0x16b50, 0x16b59,
+ 0x16b63, 0x16b77,
+ 0x16b7d, 0x16b8f,
+ 0x16d40, 0x16d6c,
+ 0x16d70, 0x16d79,
+ 0x16e40, 0x16e7f,
+ 0x16ea0, 0x16eb8,
+ 0x16ebb, 0x16ed3,
+ 0x16f00, 0x16f4a,
+ 0x16f4f, 0x16f87,
+ 0x16f8f, 0x16f9f,
+ 0x16fe0, 0x16fe1,
+ 0x16fe3, 0x16fe4,
+ 0x16ff0, 0x16ff6,
+ 0x17000, 0x18cd5,
+ 0x18cff, 0x18d1e,
+ 0x18d80, 0x18df2,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
+ 0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
+ 0x1b164, 0x1b167,
+ 0x1b170, 0x1b2fb,
+ 0x1bc00, 0x1bc6a,
+ 0x1bc70, 0x1bc7c,
+ 0x1bc80, 0x1bc88,
+ 0x1bc90, 0x1bc99,
+ 0x1bc9d, 0x1bc9e,
+ 0x1ccf0, 0x1ccf9,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
+ 0x1d165, 0x1d169,
+ 0x1d16d, 0x1d172,
+ 0x1d17b, 0x1d182,
+ 0x1d185, 0x1d18b,
+ 0x1d1aa, 0x1d1ad,
+ 0x1d242, 0x1d244,
+ 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, 0x1d6c0,
+ 0x1d6c2, 0x1d6da,
+ 0x1d6dc, 0x1d6fa,
+ 0x1d6fc, 0x1d714,
+ 0x1d716, 0x1d734,
+ 0x1d736, 0x1d74e,
+ 0x1d750, 0x1d76e,
+ 0x1d770, 0x1d788,
+ 0x1d78a, 0x1d7a8,
+ 0x1d7aa, 0x1d7c2,
+ 0x1d7c4, 0x1d7cb,
+ 0x1d7ce, 0x1d7ff,
+ 0x1da00, 0x1da36,
+ 0x1da3b, 0x1da6c,
+ 0x1da75, 0x1da75,
+ 0x1da84, 0x1da84,
+ 0x1da9b, 0x1da9f,
+ 0x1daa1, 0x1daaf,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e000, 0x1e006,
+ 0x1e008, 0x1e018,
+ 0x1e01b, 0x1e021,
+ 0x1e023, 0x1e024,
+ 0x1e026, 0x1e02a,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
+ 0x1e100, 0x1e12c,
+ 0x1e130, 0x1e13d,
+ 0x1e140, 0x1e149,
+ 0x1e14e, 0x1e14e,
+ 0x1e290, 0x1e2ae,
+ 0x1e2c0, 0x1e2f9,
+ 0x1e4d0, 0x1e4f9,
+ 0x1e5d0, 0x1e5fa,
+ 0x1e6c0, 0x1e6de,
+ 0x1e6e0, 0x1e6f5,
+ 0x1e6fe, 0x1e6ff,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
+ 0x1e800, 0x1e8c4,
+ 0x1e8d0, 0x1e8d6,
+ 0x1e900, 0x1e94b,
+ 0x1e950, 0x1e959,
+ 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,
+ 0x1fbf0, 0x1fbf9,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b81d,
+ 0x2b820, 0x2cead,
+ 0x2ceb0, 0x2ebe0,
+ 0x2ebf0, 0x2ee5d,
+ 0x2f800, 0x2fa1d,
+ 0x30000, 0x3134a,
+ 0x31350, 0x33479,
+ 0xe0100, 0xe01ef,
+}; /* CR_XID_Continue */
+
+/* 'Default_Ignorable_Code_Point': Derived Property */
+static const OnigCodePoint CR_Default_Ignorable_Code_Point[] = {
+ 17,
+ 0x00ad, 0x00ad,
+ 0x034f, 0x034f,
+ 0x061c, 0x061c,
+ 0x115f, 0x1160,
+ 0x17b4, 0x17b5,
+ 0x180b, 0x180f,
+ 0x200b, 0x200f,
+ 0x202a, 0x202e,
+ 0x2060, 0x206f,
+ 0x3164, 0x3164,
+ 0xfe00, 0xfe0f,
+ 0xfeff, 0xfeff,
+ 0xffa0, 0xffa0,
+ 0xfff0, 0xfff8,
+ 0x1bca0, 0x1bca3,
+ 0x1d173, 0x1d17a,
+ 0xe0000, 0xe0fff,
+}; /* CR_Default_Ignorable_Code_Point */
+
+/* 'Grapheme_Extend': Derived Property */
+static const OnigCodePoint CR_Grapheme_Extend[] = {
+ 383,
+ 0x0300, 0x036f,
+ 0x0483, 0x0489,
+ 0x0591, 0x05bd,
+ 0x05bf, 0x05bf,
+ 0x05c1, 0x05c2,
+ 0x05c4, 0x05c5,
+ 0x05c7, 0x05c7,
+ 0x0610, 0x061a,
+ 0x064b, 0x065f,
+ 0x0670, 0x0670,
+ 0x06d6, 0x06dc,
+ 0x06df, 0x06e4,
+ 0x06e7, 0x06e8,
+ 0x06ea, 0x06ed,
+ 0x0711, 0x0711,
+ 0x0730, 0x074a,
+ 0x07a6, 0x07b0,
+ 0x07eb, 0x07f3,
+ 0x07fd, 0x07fd,
+ 0x0816, 0x0819,
+ 0x081b, 0x0823,
+ 0x0825, 0x0827,
+ 0x0829, 0x082d,
+ 0x0859, 0x085b,
+ 0x0897, 0x089f,
+ 0x08ca, 0x08e1,
+ 0x08e3, 0x0902,
+ 0x093a, 0x093a,
+ 0x093c, 0x093c,
+ 0x0941, 0x0948,
+ 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,
+ 0x0c3c, 0x0c3c,
+ 0x0c3e, 0x0c40,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c62, 0x0c63,
+ 0x0c81, 0x0c81,
+ 0x0cbc, 0x0cbc,
+ 0x0cbf, 0x0cc0,
+ 0x0cc2, 0x0cc2,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0ce2, 0x0ce3,
+ 0x0d00, 0x0d01,
+ 0x0d3b, 0x0d3c,
+ 0x0d3e, 0x0d3e,
+ 0x0d41, 0x0d44,
+ 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, 0x0ece,
+ 0x0f18, 0x0f19,
+ 0x0f35, 0x0f35,
+ 0x0f37, 0x0f37,
+ 0x0f39, 0x0f39,
+ 0x0f71, 0x0f7e,
+ 0x0f80, 0x0f84,
+ 0x0f86, 0x0f87,
+ 0x0f8d, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 0x0fc6, 0x0fc6,
+ 0x102d, 0x1030,
+ 0x1032, 0x1037,
+ 0x1039, 0x103a,
+ 0x103d, 0x103e,
+ 0x1058, 0x1059,
+ 0x105e, 0x1060,
+ 0x1071, 0x1074,
+ 0x1082, 0x1082,
+ 0x1085, 0x1086,
+ 0x108d, 0x108d,
+ 0x109d, 0x109d,
+ 0x135d, 0x135f,
+ 0x1712, 0x1715,
+ 0x1732, 0x1734,
+ 0x1752, 0x1753,
+ 0x1772, 0x1773,
+ 0x17b4, 0x17b5,
+ 0x17b7, 0x17bd,
+ 0x17c6, 0x17c6,
+ 0x17c9, 0x17d3,
+ 0x17dd, 0x17dd,
+ 0x180b, 0x180d,
+ 0x180f, 0x180f,
+ 0x1885, 0x1886,
+ 0x18a9, 0x18a9,
+ 0x1920, 0x1922,
+ 0x1927, 0x1928,
+ 0x1932, 0x1932,
+ 0x1939, 0x193b,
+ 0x1a17, 0x1a18,
+ 0x1a1b, 0x1a1b,
+ 0x1a56, 0x1a56,
+ 0x1a58, 0x1a5e,
+ 0x1a60, 0x1a60,
+ 0x1a62, 0x1a62,
+ 0x1a65, 0x1a6c,
+ 0x1a73, 0x1a7c,
+ 0x1a7f, 0x1a7f,
+ 0x1ab0, 0x1add,
+ 0x1ae0, 0x1aeb,
+ 0x1b00, 0x1b03,
+ 0x1b34, 0x1b3d,
+ 0x1b42, 0x1b44,
+ 0x1b6b, 0x1b73,
+ 0x1b80, 0x1b81,
+ 0x1ba2, 0x1ba5,
+ 0x1ba8, 0x1bad,
+ 0x1be6, 0x1be6,
+ 0x1be8, 0x1be9,
+ 0x1bed, 0x1bed,
+ 0x1bef, 0x1bf3,
+ 0x1c2c, 0x1c33,
+ 0x1c36, 0x1c37,
+ 0x1cd0, 0x1cd2,
+ 0x1cd4, 0x1ce0,
+ 0x1ce2, 0x1ce8,
+ 0x1ced, 0x1ced,
+ 0x1cf4, 0x1cf4,
+ 0x1cf8, 0x1cf9,
+ 0x1dc0, 0x1dff,
+ 0x200c, 0x200c,
+ 0x20d0, 0x20f0,
+ 0x2cef, 0x2cf1,
+ 0x2d7f, 0x2d7f,
+ 0x2de0, 0x2dff,
+ 0x302a, 0x302f,
+ 0x3099, 0x309a,
+ 0xa66f, 0xa672,
+ 0xa674, 0xa67d,
+ 0xa69e, 0xa69f,
+ 0xa6f0, 0xa6f1,
+ 0xa802, 0xa802,
+ 0xa806, 0xa806,
+ 0xa80b, 0xa80b,
+ 0xa825, 0xa826,
+ 0xa82c, 0xa82c,
+ 0xa8c4, 0xa8c5,
+ 0xa8e0, 0xa8f1,
+ 0xa8ff, 0xa8ff,
+ 0xa926, 0xa92d,
+ 0xa947, 0xa951,
+ 0xa953, 0xa953,
+ 0xa980, 0xa982,
+ 0xa9b3, 0xa9b3,
+ 0xa9b6, 0xa9b9,
+ 0xa9bc, 0xa9bd,
+ 0xa9c0, 0xa9c0,
+ 0xa9e5, 0xa9e5,
+ 0xaa29, 0xaa2e,
+ 0xaa31, 0xaa32,
+ 0xaa35, 0xaa36,
+ 0xaa43, 0xaa43,
+ 0xaa4c, 0xaa4c,
+ 0xaa7c, 0xaa7c,
+ 0xaab0, 0xaab0,
+ 0xaab2, 0xaab4,
+ 0xaab7, 0xaab8,
+ 0xaabe, 0xaabf,
+ 0xaac1, 0xaac1,
+ 0xaaec, 0xaaed,
+ 0xaaf6, 0xaaf6,
+ 0xabe5, 0xabe5,
+ 0xabe8, 0xabe8,
+ 0xabed, 0xabed,
+ 0xfb1e, 0xfb1e,
+ 0xfe00, 0xfe0f,
+ 0xfe20, 0xfe2f,
+ 0xff9e, 0xff9f,
+ 0x101fd, 0x101fd,
+ 0x102e0, 0x102e0,
+ 0x10376, 0x1037a,
+ 0x10a01, 0x10a03,
+ 0x10a05, 0x10a06,
+ 0x10a0c, 0x10a0f,
+ 0x10a38, 0x10a3a,
+ 0x10a3f, 0x10a3f,
+ 0x10ae5, 0x10ae6,
+ 0x10d24, 0x10d27,
+ 0x10d69, 0x10d6d,
+ 0x10eab, 0x10eac,
+ 0x10efa, 0x10eff,
+ 0x10f46, 0x10f50,
+ 0x10f82, 0x10f85,
+ 0x11001, 0x11001,
+ 0x11038, 0x11046,
+ 0x11070, 0x11070,
+ 0x11073, 0x11074,
+ 0x1107f, 0x11081,
+ 0x110b3, 0x110b6,
+ 0x110b9, 0x110ba,
+ 0x110c2, 0x110c2,
+ 0x11100, 0x11102,
+ 0x11127, 0x1112b,
+ 0x1112d, 0x11134,
+ 0x11173, 0x11173,
+ 0x11180, 0x11181,
+ 0x111b6, 0x111be,
+ 0x111c0, 0x111c0,
+ 0x111c9, 0x111cc,
+ 0x111cf, 0x111cf,
+ 0x1122f, 0x11231,
+ 0x11234, 0x11237,
+ 0x1123e, 0x1123e,
+ 0x11241, 0x11241,
+ 0x112df, 0x112df,
+ 0x112e3, 0x112ea,
+ 0x11300, 0x11301,
+ 0x1133b, 0x1133c,
+ 0x1133e, 0x1133e,
+ 0x11340, 0x11340,
+ 0x1134d, 0x1134d,
+ 0x11357, 0x11357,
+ 0x11366, 0x1136c,
+ 0x11370, 0x11374,
+ 0x113b8, 0x113b8,
+ 0x113bb, 0x113c0,
+ 0x113c2, 0x113c2,
+ 0x113c5, 0x113c5,
+ 0x113c7, 0x113c9,
+ 0x113ce, 0x113d0,
+ 0x113d2, 0x113d2,
+ 0x113e1, 0x113e2,
+ 0x11438, 0x1143f,
+ 0x11442, 0x11444,
+ 0x11446, 0x11446,
+ 0x1145e, 0x1145e,
+ 0x114b0, 0x114b0,
+ 0x114b3, 0x114b8,
+ 0x114ba, 0x114ba,
+ 0x114bd, 0x114bd,
+ 0x114bf, 0x114c0,
+ 0x114c2, 0x114c3,
+ 0x115af, 0x115af,
+ 0x115b2, 0x115b5,
+ 0x115bc, 0x115bd,
+ 0x115bf, 0x115c0,
+ 0x115dc, 0x115dd,
+ 0x11633, 0x1163a,
+ 0x1163d, 0x1163d,
+ 0x1163f, 0x11640,
+ 0x116ab, 0x116ab,
+ 0x116ad, 0x116ad,
+ 0x116b0, 0x116b7,
+ 0x1171d, 0x1171d,
+ 0x1171f, 0x1171f,
+ 0x11722, 0x11725,
+ 0x11727, 0x1172b,
+ 0x1182f, 0x11837,
+ 0x11839, 0x1183a,
+ 0x11930, 0x11930,
+ 0x1193b, 0x1193e,
+ 0x11943, 0x11943,
+ 0x119d4, 0x119d7,
+ 0x119da, 0x119db,
+ 0x119e0, 0x119e0,
+ 0x11a01, 0x11a0a,
+ 0x11a33, 0x11a38,
+ 0x11a3b, 0x11a3e,
+ 0x11a47, 0x11a47,
+ 0x11a51, 0x11a56,
+ 0x11a59, 0x11a5b,
+ 0x11a8a, 0x11a96,
+ 0x11a98, 0x11a99,
+ 0x11b60, 0x11b60,
+ 0x11b62, 0x11b64,
+ 0x11b66, 0x11b66,
+ 0x11c30, 0x11c36,
+ 0x11c38, 0x11c3d,
+ 0x11c3f, 0x11c3f,
+ 0x11c92, 0x11ca7,
+ 0x11caa, 0x11cb0,
+ 0x11cb2, 0x11cb3,
+ 0x11cb5, 0x11cb6,
+ 0x11d31, 0x11d36,
+ 0x11d3a, 0x11d3a,
+ 0x11d3c, 0x11d3d,
+ 0x11d3f, 0x11d45,
+ 0x11d47, 0x11d47,
+ 0x11d90, 0x11d91,
+ 0x11d95, 0x11d95,
+ 0x11d97, 0x11d97,
+ 0x11ef3, 0x11ef4,
+ 0x11f00, 0x11f01,
+ 0x11f36, 0x11f3a,
+ 0x11f40, 0x11f42,
+ 0x11f5a, 0x11f5a,
+ 0x13440, 0x13440,
+ 0x13447, 0x13455,
+ 0x1611e, 0x16129,
+ 0x1612d, 0x1612f,
+ 0x16af0, 0x16af4,
+ 0x16b30, 0x16b36,
+ 0x16f4f, 0x16f4f,
+ 0x16f8f, 0x16f92,
+ 0x16fe4, 0x16fe4,
+ 0x16ff0, 0x16ff1,
+ 0x1bc9d, 0x1bc9e,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
+ 0x1d165, 0x1d169,
+ 0x1d16d, 0x1d172,
+ 0x1d17b, 0x1d182,
+ 0x1d185, 0x1d18b,
+ 0x1d1aa, 0x1d1ad,
+ 0x1d242, 0x1d244,
+ 0x1da00, 0x1da36,
+ 0x1da3b, 0x1da6c,
+ 0x1da75, 0x1da75,
+ 0x1da84, 0x1da84,
+ 0x1da9b, 0x1da9f,
+ 0x1daa1, 0x1daaf,
+ 0x1e000, 0x1e006,
+ 0x1e008, 0x1e018,
+ 0x1e01b, 0x1e021,
+ 0x1e023, 0x1e024,
+ 0x1e026, 0x1e02a,
+ 0x1e08f, 0x1e08f,
+ 0x1e130, 0x1e136,
+ 0x1e2ae, 0x1e2ae,
+ 0x1e2ec, 0x1e2ef,
+ 0x1e4ec, 0x1e4ef,
+ 0x1e5ee, 0x1e5ef,
+ 0x1e6e3, 0x1e6e3,
+ 0x1e6e6, 0x1e6e6,
+ 0x1e6ee, 0x1e6ef,
+ 0x1e6f5, 0x1e6f5,
+ 0x1e8d0, 0x1e8d6,
+ 0x1e944, 0x1e94a,
+ 0xe0020, 0xe007f,
+ 0xe0100, 0xe01ef,
+}; /* CR_Grapheme_Extend */
+
+/* 'Grapheme_Base': Derived Property */
+static const OnigCodePoint CR_Grapheme_Base[] = {
+ 904,
+ 0x0020, 0x007e,
+ 0x00a0, 0x00ac,
+ 0x00ae, 0x02ff,
+ 0x0370, 0x0377,
+ 0x037a, 0x037f,
+ 0x0384, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x0482,
+ 0x048a, 0x052f,
+ 0x0531, 0x0556,
+ 0x0559, 0x058a,
+ 0x058d, 0x058f,
+ 0x05be, 0x05be,
+ 0x05c0, 0x05c0,
+ 0x05c3, 0x05c3,
+ 0x05c6, 0x05c6,
+ 0x05d0, 0x05ea,
+ 0x05ef, 0x05f4,
+ 0x0606, 0x060f,
+ 0x061b, 0x061b,
+ 0x061d, 0x064a,
+ 0x0660, 0x066f,
+ 0x0671, 0x06d5,
+ 0x06de, 0x06de,
+ 0x06e5, 0x06e6,
+ 0x06e9, 0x06e9,
+ 0x06ee, 0x070d,
+ 0x0710, 0x0710,
+ 0x0712, 0x072f,
+ 0x074d, 0x07a5,
+ 0x07b1, 0x07b1,
+ 0x07c0, 0x07ea,
+ 0x07f4, 0x07fa,
+ 0x07fe, 0x0815,
+ 0x081a, 0x081a,
+ 0x0824, 0x0824,
+ 0x0828, 0x0828,
+ 0x0830, 0x083e,
+ 0x0840, 0x0858,
+ 0x085e, 0x085e,
+ 0x0860, 0x086a,
+ 0x0870, 0x088f,
+ 0x08a0, 0x08c9,
+ 0x0903, 0x0939,
+ 0x093b, 0x093b,
+ 0x093d, 0x0940,
+ 0x0949, 0x094c,
+ 0x094e, 0x0950,
+ 0x0958, 0x0961,
+ 0x0964, 0x0980,
+ 0x0982, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bd, 0x09bd,
+ 0x09bf, 0x09c0,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09cc,
+ 0x09ce, 0x09ce,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e1,
+ 0x09e6, 0x09fd,
+ 0x0a03, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3e, 0x0a40,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a6f,
+ 0x0a72, 0x0a74,
+ 0x0a76, 0x0a76,
+ 0x0a83, 0x0a83,
+ 0x0a85, 0x0a8d,
+ 0x0a8f, 0x0a91,
+ 0x0a93, 0x0aa8,
+ 0x0aaa, 0x0ab0,
+ 0x0ab2, 0x0ab3,
+ 0x0ab5, 0x0ab9,
+ 0x0abd, 0x0ac0,
+ 0x0ac9, 0x0ac9,
+ 0x0acb, 0x0acc,
+ 0x0ad0, 0x0ad0,
+ 0x0ae0, 0x0ae1,
+ 0x0ae6, 0x0af1,
+ 0x0af9, 0x0af9,
+ 0x0b02, 0x0b03,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b35, 0x0b39,
+ 0x0b3d, 0x0b3d,
+ 0x0b40, 0x0b40,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4c,
+ 0x0b5c, 0x0b5d,
+ 0x0b5f, 0x0b61,
+ 0x0b66, 0x0b77,
+ 0x0b83, 0x0b83,
+ 0x0b85, 0x0b8a,
+ 0x0b8e, 0x0b90,
+ 0x0b92, 0x0b95,
+ 0x0b99, 0x0b9a,
+ 0x0b9c, 0x0b9c,
+ 0x0b9e, 0x0b9f,
+ 0x0ba3, 0x0ba4,
+ 0x0ba8, 0x0baa,
+ 0x0bae, 0x0bb9,
+ 0x0bbf, 0x0bbf,
+ 0x0bc1, 0x0bc2,
+ 0x0bc6, 0x0bc8,
+ 0x0bca, 0x0bcc,
+ 0x0bd0, 0x0bd0,
+ 0x0be6, 0x0bfa,
+ 0x0c01, 0x0c03,
+ 0x0c05, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3d, 0x0c3d,
+ 0x0c41, 0x0c44,
+ 0x0c58, 0x0c5a,
+ 0x0c5c, 0x0c5d,
+ 0x0c60, 0x0c61,
+ 0x0c66, 0x0c6f,
+ 0x0c77, 0x0c80,
+ 0x0c82, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbd, 0x0cbe,
+ 0x0cc1, 0x0cc1,
+ 0x0cc3, 0x0cc4,
+ 0x0cdc, 0x0cde,
+ 0x0ce0, 0x0ce1,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf3,
+ 0x0d02, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d3a,
+ 0x0d3d, 0x0d3d,
+ 0x0d3f, 0x0d40,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4c,
+ 0x0d4e, 0x0d4f,
+ 0x0d54, 0x0d56,
+ 0x0d58, 0x0d61,
+ 0x0d66, 0x0d7f,
+ 0x0d82, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dd0, 0x0dd1,
+ 0x0dd8, 0x0dde,
+ 0x0de6, 0x0def,
+ 0x0df2, 0x0df4,
+ 0x0e01, 0x0e30,
+ 0x0e32, 0x0e33,
+ 0x0e3f, 0x0e46,
+ 0x0e4f, 0x0e5b,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e86, 0x0e8a,
+ 0x0e8c, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0eb0,
+ 0x0eb2, 0x0eb3,
+ 0x0ebd, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f17,
+ 0x0f1a, 0x0f34,
+ 0x0f36, 0x0f36,
+ 0x0f38, 0x0f38,
+ 0x0f3a, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f7f, 0x0f7f,
+ 0x0f85, 0x0f85,
+ 0x0f88, 0x0f8c,
+ 0x0fbe, 0x0fc5,
+ 0x0fc7, 0x0fcc,
+ 0x0fce, 0x0fda,
+ 0x1000, 0x102c,
+ 0x1031, 0x1031,
+ 0x1038, 0x1038,
+ 0x103b, 0x103c,
+ 0x103f, 0x1057,
+ 0x105a, 0x105d,
+ 0x1061, 0x1070,
+ 0x1075, 0x1081,
+ 0x1083, 0x1084,
+ 0x1087, 0x108c,
+ 0x108e, 0x109c,
+ 0x109e, 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,
+ 0x1360, 0x137c,
+ 0x1380, 0x1399,
+ 0x13a0, 0x13f5,
+ 0x13f8, 0x13fd,
+ 0x1400, 0x169c,
+ 0x16a0, 0x16f8,
+ 0x1700, 0x1711,
+ 0x171f, 0x1731,
+ 0x1735, 0x1736,
+ 0x1740, 0x1751,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1780, 0x17b3,
+ 0x17b6, 0x17b6,
+ 0x17be, 0x17c5,
+ 0x17c7, 0x17c8,
+ 0x17d4, 0x17dc,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x1800, 0x180a,
+ 0x1810, 0x1819,
+ 0x1820, 0x1878,
+ 0x1880, 0x1884,
+ 0x1887, 0x18a8,
+ 0x18aa, 0x18aa,
+ 0x18b0, 0x18f5,
+ 0x1900, 0x191e,
+ 0x1923, 0x1926,
+ 0x1929, 0x192b,
+ 0x1930, 0x1931,
+ 0x1933, 0x1938,
+ 0x1940, 0x1940,
+ 0x1944, 0x196d,
+ 0x1970, 0x1974,
+ 0x1980, 0x19ab,
+ 0x19b0, 0x19c9,
+ 0x19d0, 0x19da,
+ 0x19de, 0x1a16,
+ 0x1a19, 0x1a1a,
+ 0x1a1e, 0x1a55,
+ 0x1a57, 0x1a57,
+ 0x1a61, 0x1a61,
+ 0x1a63, 0x1a64,
+ 0x1a6d, 0x1a72,
+ 0x1a80, 0x1a89,
+ 0x1a90, 0x1a99,
+ 0x1aa0, 0x1aad,
+ 0x1b04, 0x1b33,
+ 0x1b3e, 0x1b41,
+ 0x1b45, 0x1b4c,
+ 0x1b4e, 0x1b6a,
+ 0x1b74, 0x1b7f,
+ 0x1b82, 0x1ba1,
+ 0x1ba6, 0x1ba7,
+ 0x1bae, 0x1be5,
+ 0x1be7, 0x1be7,
+ 0x1bea, 0x1bec,
+ 0x1bee, 0x1bee,
+ 0x1bfc, 0x1c2b,
+ 0x1c34, 0x1c35,
+ 0x1c3b, 0x1c49,
+ 0x1c4d, 0x1c8a,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cc7,
+ 0x1cd3, 0x1cd3,
+ 0x1ce1, 0x1ce1,
+ 0x1ce9, 0x1cec,
+ 0x1cee, 0x1cf3,
+ 0x1cf5, 0x1cf7,
+ 0x1cfa, 0x1cfa,
+ 0x1d00, 0x1dbf,
+ 0x1e00, 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, 0x200a,
+ 0x2010, 0x2027,
+ 0x202f, 0x205f,
+ 0x2070, 0x2071,
+ 0x2074, 0x208e,
+ 0x2090, 0x209c,
+ 0x20a0, 0x20c1,
+ 0x2100, 0x218b,
+ 0x2190, 0x2429,
+ 0x2440, 0x244a,
+ 0x2460, 0x2b73,
+ 0x2b76, 0x2cee,
+ 0x2cf2, 0x2cf3,
+ 0x2cf9, 0x2d25,
+ 0x2d27, 0x2d27,
+ 0x2d2d, 0x2d2d,
+ 0x2d30, 0x2d67,
+ 0x2d6f, 0x2d70,
+ 0x2d80, 0x2d96,
+ 0x2da0, 0x2da6,
+ 0x2da8, 0x2dae,
+ 0x2db0, 0x2db6,
+ 0x2db8, 0x2dbe,
+ 0x2dc0, 0x2dc6,
+ 0x2dc8, 0x2dce,
+ 0x2dd0, 0x2dd6,
+ 0x2dd8, 0x2dde,
+ 0x2e00, 0x2e5d,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x3029,
+ 0x3030, 0x303f,
+ 0x3041, 0x3096,
+ 0x309b, 0x30ff,
+ 0x3105, 0x312f,
+ 0x3131, 0x318e,
+ 0x3190, 0x31e5,
+ 0x31ef, 0x321e,
+ 0x3220, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa4d0, 0xa62b,
+ 0xa640, 0xa66e,
+ 0xa673, 0xa673,
+ 0xa67e, 0xa69d,
+ 0xa6a0, 0xa6ef,
+ 0xa6f2, 0xa6f7,
+ 0xa700, 0xa7dc,
+ 0xa7f1, 0xa801,
+ 0xa803, 0xa805,
+ 0xa807, 0xa80a,
+ 0xa80c, 0xa824,
+ 0xa827, 0xa82b,
+ 0xa830, 0xa839,
+ 0xa840, 0xa877,
+ 0xa880, 0xa8c3,
+ 0xa8ce, 0xa8d9,
+ 0xa8f2, 0xa8fe,
+ 0xa900, 0xa925,
+ 0xa92e, 0xa946,
+ 0xa952, 0xa952,
+ 0xa95f, 0xa97c,
+ 0xa983, 0xa9b2,
+ 0xa9b4, 0xa9b5,
+ 0xa9ba, 0xa9bb,
+ 0xa9be, 0xa9bf,
+ 0xa9c1, 0xa9cd,
+ 0xa9cf, 0xa9d9,
+ 0xa9de, 0xa9e4,
+ 0xa9e6, 0xa9fe,
+ 0xaa00, 0xaa28,
+ 0xaa2f, 0xaa30,
+ 0xaa33, 0xaa34,
+ 0xaa40, 0xaa42,
+ 0xaa44, 0xaa4b,
+ 0xaa4d, 0xaa4d,
+ 0xaa50, 0xaa59,
+ 0xaa5c, 0xaa7b,
+ 0xaa7d, 0xaaaf,
+ 0xaab1, 0xaab1,
+ 0xaab5, 0xaab6,
+ 0xaab9, 0xaabd,
+ 0xaac0, 0xaac0,
+ 0xaac2, 0xaac2,
+ 0xaadb, 0xaaeb,
+ 0xaaee, 0xaaf5,
+ 0xab01, 0xab06,
+ 0xab09, 0xab0e,
+ 0xab11, 0xab16,
+ 0xab20, 0xab26,
+ 0xab28, 0xab2e,
+ 0xab30, 0xab6b,
+ 0xab70, 0xabe4,
+ 0xabe6, 0xabe7,
+ 0xabe9, 0xabec,
+ 0xabf0, 0xabf9,
+ 0xac00, 0xd7a3,
+ 0xd7b0, 0xd7c6,
+ 0xd7cb, 0xd7fb,
+ 0xf900, 0xfa6d,
+ 0xfa70, 0xfad9,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xfb1d, 0xfb1d,
+ 0xfb1f, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfdcf,
+ 0xfdf0, 0xfdff,
+ 0xfe10, 0xfe19,
+ 0xfe30, 0xfe52,
+ 0xfe54, 0xfe66,
+ 0xfe68, 0xfe6b,
+ 0xfe70, 0xfe74,
+ 0xfe76, 0xfefc,
+ 0xff01, 0xff9d,
+ 0xffa0, 0xffbe,
+ 0xffc2, 0xffc7,
+ 0xffca, 0xffcf,
+ 0xffd2, 0xffd7,
+ 0xffda, 0xffdc,
+ 0xffe0, 0xffe6,
+ 0xffe8, 0xffee,
+ 0xfffc, 0xfffd,
+ 0x10000, 0x1000b,
+ 0x1000d, 0x10026,
+ 0x10028, 0x1003a,
+ 0x1003c, 0x1003d,
+ 0x1003f, 0x1004d,
+ 0x10050, 0x1005d,
+ 0x10080, 0x100fa,
+ 0x10100, 0x10102,
+ 0x10107, 0x10133,
+ 0x10137, 0x1018e,
+ 0x10190, 0x1019c,
+ 0x101a0, 0x101a0,
+ 0x101d0, 0x101fc,
+ 0x10280, 0x1029c,
+ 0x102a0, 0x102d0,
+ 0x102e1, 0x102fb,
+ 0x10300, 0x10323,
+ 0x1032d, 0x1034a,
+ 0x10350, 0x10375,
+ 0x10380, 0x1039d,
+ 0x1039f, 0x103c3,
+ 0x103c8, 0x103d5,
+ 0x10400, 0x1049d,
+ 0x104a0, 0x104a9,
+ 0x104b0, 0x104d3,
+ 0x104d8, 0x104fb,
+ 0x10500, 0x10527,
+ 0x10530, 0x10563,
+ 0x1056f, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x105c0, 0x105f3,
+ 0x10600, 0x10736,
+ 0x10740, 0x10755,
+ 0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 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, 0x10959,
+ 0x10980, 0x109b7,
+ 0x109bc, 0x109cf,
+ 0x109d2, 0x10a00,
+ 0x10a10, 0x10a13,
+ 0x10a15, 0x10a17,
+ 0x10a19, 0x10a35,
+ 0x10a40, 0x10a48,
+ 0x10a50, 0x10a58,
+ 0x10a60, 0x10a9f,
+ 0x10ac0, 0x10ae4,
+ 0x10aeb, 0x10af6,
+ 0x10b00, 0x10b35,
+ 0x10b39, 0x10b55,
+ 0x10b58, 0x10b72,
+ 0x10b78, 0x10b91,
+ 0x10b99, 0x10b9c,
+ 0x10ba9, 0x10baf,
+ 0x10c00, 0x10c48,
+ 0x10c80, 0x10cb2,
+ 0x10cc0, 0x10cf2,
+ 0x10cfa, 0x10d23,
+ 0x10d30, 0x10d39,
+ 0x10d40, 0x10d65,
+ 0x10d6e, 0x10d85,
+ 0x10d8e, 0x10d8f,
+ 0x10e60, 0x10e7e,
+ 0x10e80, 0x10ea9,
+ 0x10ead, 0x10ead,
+ 0x10eb0, 0x10eb1,
+ 0x10ec2, 0x10ec7,
+ 0x10ed0, 0x10ed8,
+ 0x10f00, 0x10f27,
+ 0x10f30, 0x10f45,
+ 0x10f51, 0x10f59,
+ 0x10f70, 0x10f81,
+ 0x10f86, 0x10f89,
+ 0x10fb0, 0x10fcb,
+ 0x10fe0, 0x10ff6,
+ 0x11000, 0x11000,
+ 0x11002, 0x11037,
+ 0x11047, 0x1104d,
+ 0x11052, 0x1106f,
+ 0x11071, 0x11072,
+ 0x11075, 0x11075,
+ 0x11082, 0x110b2,
+ 0x110b7, 0x110b8,
+ 0x110bb, 0x110bc,
+ 0x110be, 0x110c1,
+ 0x110d0, 0x110e8,
+ 0x110f0, 0x110f9,
+ 0x11103, 0x11126,
+ 0x1112c, 0x1112c,
+ 0x11136, 0x11147,
+ 0x11150, 0x11172,
+ 0x11174, 0x11176,
+ 0x11182, 0x111b5,
+ 0x111bf, 0x111bf,
+ 0x111c1, 0x111c8,
+ 0x111cd, 0x111ce,
+ 0x111d0, 0x111df,
+ 0x111e1, 0x111f4,
+ 0x11200, 0x11211,
+ 0x11213, 0x1122e,
+ 0x11232, 0x11233,
+ 0x11238, 0x1123d,
+ 0x1123f, 0x11240,
+ 0x11280, 0x11286,
+ 0x11288, 0x11288,
+ 0x1128a, 0x1128d,
+ 0x1128f, 0x1129d,
+ 0x1129f, 0x112a9,
+ 0x112b0, 0x112de,
+ 0x112e0, 0x112e2,
+ 0x112f0, 0x112f9,
+ 0x11302, 0x11303,
+ 0x11305, 0x1130c,
+ 0x1130f, 0x11310,
+ 0x11313, 0x11328,
+ 0x1132a, 0x11330,
+ 0x11332, 0x11333,
+ 0x11335, 0x11339,
+ 0x1133d, 0x1133d,
+ 0x1133f, 0x1133f,
+ 0x11341, 0x11344,
+ 0x11347, 0x11348,
+ 0x1134b, 0x1134c,
+ 0x11350, 0x11350,
+ 0x1135d, 0x11363,
+ 0x11380, 0x11389,
+ 0x1138b, 0x1138b,
+ 0x1138e, 0x1138e,
+ 0x11390, 0x113b5,
+ 0x113b7, 0x113b7,
+ 0x113b9, 0x113ba,
+ 0x113ca, 0x113ca,
+ 0x113cc, 0x113cd,
+ 0x113d1, 0x113d1,
+ 0x113d3, 0x113d5,
+ 0x113d7, 0x113d8,
+ 0x11400, 0x11437,
+ 0x11440, 0x11441,
+ 0x11445, 0x11445,
+ 0x11447, 0x1145b,
+ 0x1145d, 0x1145d,
+ 0x1145f, 0x11461,
+ 0x11480, 0x114af,
+ 0x114b1, 0x114b2,
+ 0x114b9, 0x114b9,
+ 0x114bb, 0x114bc,
+ 0x114be, 0x114be,
+ 0x114c1, 0x114c1,
+ 0x114c4, 0x114c7,
+ 0x114d0, 0x114d9,
+ 0x11580, 0x115ae,
+ 0x115b0, 0x115b1,
+ 0x115b8, 0x115bb,
+ 0x115be, 0x115be,
+ 0x115c1, 0x115db,
+ 0x11600, 0x11632,
+ 0x1163b, 0x1163c,
+ 0x1163e, 0x1163e,
+ 0x11641, 0x11644,
+ 0x11650, 0x11659,
+ 0x11660, 0x1166c,
+ 0x11680, 0x116aa,
+ 0x116ac, 0x116ac,
+ 0x116ae, 0x116af,
+ 0x116b8, 0x116b9,
+ 0x116c0, 0x116c9,
+ 0x116d0, 0x116e3,
+ 0x11700, 0x1171a,
+ 0x1171e, 0x1171e,
+ 0x11720, 0x11721,
+ 0x11726, 0x11726,
+ 0x11730, 0x11746,
+ 0x11800, 0x1182e,
+ 0x11838, 0x11838,
+ 0x1183b, 0x1183b,
+ 0x118a0, 0x118f2,
+ 0x118ff, 0x11906,
+ 0x11909, 0x11909,
+ 0x1190c, 0x11913,
+ 0x11915, 0x11916,
+ 0x11918, 0x1192f,
+ 0x11931, 0x11935,
+ 0x11937, 0x11938,
+ 0x1193f, 0x11942,
+ 0x11944, 0x11946,
+ 0x11950, 0x11959,
+ 0x119a0, 0x119a7,
+ 0x119aa, 0x119d3,
+ 0x119dc, 0x119df,
+ 0x119e1, 0x119e4,
+ 0x11a00, 0x11a00,
+ 0x11a0b, 0x11a32,
+ 0x11a39, 0x11a3a,
+ 0x11a3f, 0x11a46,
+ 0x11a50, 0x11a50,
+ 0x11a57, 0x11a58,
+ 0x11a5c, 0x11a89,
+ 0x11a97, 0x11a97,
+ 0x11a9a, 0x11aa2,
+ 0x11ab0, 0x11af8,
+ 0x11b00, 0x11b09,
+ 0x11b61, 0x11b61,
+ 0x11b65, 0x11b65,
+ 0x11b67, 0x11b67,
+ 0x11bc0, 0x11be1,
+ 0x11bf0, 0x11bf9,
+ 0x11c00, 0x11c08,
+ 0x11c0a, 0x11c2f,
+ 0x11c3e, 0x11c3e,
+ 0x11c40, 0x11c45,
+ 0x11c50, 0x11c6c,
+ 0x11c70, 0x11c8f,
+ 0x11ca9, 0x11ca9,
+ 0x11cb1, 0x11cb1,
+ 0x11cb4, 0x11cb4,
+ 0x11d00, 0x11d06,
+ 0x11d08, 0x11d09,
+ 0x11d0b, 0x11d30,
+ 0x11d46, 0x11d46,
+ 0x11d50, 0x11d59,
+ 0x11d60, 0x11d65,
+ 0x11d67, 0x11d68,
+ 0x11d6a, 0x11d8e,
+ 0x11d93, 0x11d94,
+ 0x11d96, 0x11d96,
+ 0x11d98, 0x11d98,
+ 0x11da0, 0x11da9,
+ 0x11db0, 0x11ddb,
+ 0x11de0, 0x11de9,
+ 0x11ee0, 0x11ef2,
+ 0x11ef5, 0x11ef8,
+ 0x11f02, 0x11f10,
+ 0x11f12, 0x11f35,
+ 0x11f3e, 0x11f3f,
+ 0x11f43, 0x11f59,
+ 0x11fb0, 0x11fb0,
+ 0x11fc0, 0x11ff1,
+ 0x11fff, 0x12399,
+ 0x12400, 0x1246e,
+ 0x12470, 0x12474,
+ 0x12480, 0x12543,
+ 0x12f90, 0x12ff2,
+ 0x13000, 0x1342f,
+ 0x13441, 0x13446,
+ 0x13460, 0x143fa,
+ 0x14400, 0x14646,
+ 0x16100, 0x1611d,
+ 0x1612a, 0x1612c,
+ 0x16130, 0x16139,
+ 0x16800, 0x16a38,
+ 0x16a40, 0x16a5e,
+ 0x16a60, 0x16a69,
+ 0x16a6e, 0x16abe,
+ 0x16ac0, 0x16ac9,
+ 0x16ad0, 0x16aed,
+ 0x16af5, 0x16af5,
+ 0x16b00, 0x16b2f,
+ 0x16b37, 0x16b45,
+ 0x16b50, 0x16b59,
+ 0x16b5b, 0x16b61,
+ 0x16b63, 0x16b77,
+ 0x16b7d, 0x16b8f,
+ 0x16d40, 0x16d79,
+ 0x16e40, 0x16e9a,
+ 0x16ea0, 0x16eb8,
+ 0x16ebb, 0x16ed3,
+ 0x16f00, 0x16f4a,
+ 0x16f50, 0x16f87,
+ 0x16f93, 0x16f9f,
+ 0x16fe0, 0x16fe3,
+ 0x16ff2, 0x16ff6,
+ 0x17000, 0x18cd5,
+ 0x18cff, 0x18d1e,
+ 0x18d80, 0x18df2,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
+ 0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
+ 0x1b164, 0x1b167,
+ 0x1b170, 0x1b2fb,
+ 0x1bc00, 0x1bc6a,
+ 0x1bc70, 0x1bc7c,
+ 0x1bc80, 0x1bc88,
+ 0x1bc90, 0x1bc99,
+ 0x1bc9c, 0x1bc9c,
+ 0x1bc9f, 0x1bc9f,
+ 0x1cc00, 0x1ccfc,
+ 0x1cd00, 0x1ceb3,
+ 0x1ceba, 0x1ced0,
+ 0x1cee0, 0x1cef0,
+ 0x1cf50, 0x1cfc3,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d129, 0x1d164,
+ 0x1d16a, 0x1d16c,
+ 0x1d183, 0x1d184,
+ 0x1d18c, 0x1d1a9,
+ 0x1d1ae, 0x1d1ea,
+ 0x1d200, 0x1d241,
+ 0x1d245, 0x1d245,
+ 0x1d2c0, 0x1d2d3,
+ 0x1d2e0, 0x1d2f3,
+ 0x1d300, 0x1d356,
+ 0x1d360, 0x1d378,
+ 0x1d400, 0x1d454,
+ 0x1d456, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 0x1d4a2, 0x1d4a2,
+ 0x1d4a5, 0x1d4a6,
+ 0x1d4a9, 0x1d4ac,
+ 0x1d4ae, 0x1d4b9,
+ 0x1d4bb, 0x1d4bb,
+ 0x1d4bd, 0x1d4c3,
+ 0x1d4c5, 0x1d505,
+ 0x1d507, 0x1d50a,
+ 0x1d50d, 0x1d514,
+ 0x1d516, 0x1d51c,
+ 0x1d51e, 0x1d539,
+ 0x1d53b, 0x1d53e,
+ 0x1d540, 0x1d544,
+ 0x1d546, 0x1d546,
+ 0x1d54a, 0x1d550,
+ 0x1d552, 0x1d6a5,
+ 0x1d6a8, 0x1d7cb,
+ 0x1d7ce, 0x1d9ff,
+ 0x1da37, 0x1da3a,
+ 0x1da6d, 0x1da74,
+ 0x1da76, 0x1da83,
+ 0x1da85, 0x1da8b,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e030, 0x1e06d,
+ 0x1e100, 0x1e12c,
+ 0x1e137, 0x1e13d,
+ 0x1e140, 0x1e149,
+ 0x1e14e, 0x1e14f,
+ 0x1e290, 0x1e2ad,
+ 0x1e2c0, 0x1e2eb,
+ 0x1e2f0, 0x1e2f9,
+ 0x1e2ff, 0x1e2ff,
+ 0x1e4d0, 0x1e4eb,
+ 0x1e4f0, 0x1e4f9,
+ 0x1e5d0, 0x1e5ed,
+ 0x1e5f0, 0x1e5fa,
+ 0x1e5ff, 0x1e5ff,
+ 0x1e6c0, 0x1e6de,
+ 0x1e6e0, 0x1e6e2,
+ 0x1e6e4, 0x1e6e5,
+ 0x1e6e7, 0x1e6ed,
+ 0x1e6f0, 0x1e6f4,
+ 0x1e6fe, 0x1e6ff,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
+ 0x1e800, 0x1e8c4,
+ 0x1e8c7, 0x1e8cf,
+ 0x1e900, 0x1e943,
+ 0x1e94b, 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, 0x1f6d8,
+ 0x1f6dc, 0x1f6ec,
+ 0x1f6f0, 0x1f6fc,
+ 0x1f700, 0x1f7d9,
+ 0x1f7e0, 0x1f7eb,
+ 0x1f7f0, 0x1f7f0,
+ 0x1f800, 0x1f80b,
+ 0x1f810, 0x1f847,
+ 0x1f850, 0x1f859,
+ 0x1f860, 0x1f887,
+ 0x1f890, 0x1f8ad,
+ 0x1f8b0, 0x1f8bb,
+ 0x1f8c0, 0x1f8c1,
+ 0x1f8d0, 0x1f8d8,
+ 0x1f900, 0x1fa57,
+ 0x1fa60, 0x1fa6d,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa8a,
+ 0x1fa8e, 0x1fac6,
+ 0x1fac8, 0x1fac8,
+ 0x1facd, 0x1fadc,
+ 0x1fadf, 0x1faea,
+ 0x1faef, 0x1faf8,
+ 0x1fb00, 0x1fb92,
+ 0x1fb94, 0x1fbfa,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b81d,
+ 0x2b820, 0x2cead,
+ 0x2ceb0, 0x2ebe0,
+ 0x2ebf0, 0x2ee5d,
+ 0x2f800, 0x2fa1d,
+ 0x30000, 0x3134a,
+ 0x31350, 0x33479,
+}; /* CR_Grapheme_Base */
+
+/* 'Grapheme_Link': Derived Property */
+static const OnigCodePoint CR_Grapheme_Link[] = {
+ 58,
+ 0x094d, 0x094d,
+ 0x09cd, 0x09cd,
+ 0x0a4d, 0x0a4d,
+ 0x0acd, 0x0acd,
+ 0x0b4d, 0x0b4d,
+ 0x0bcd, 0x0bcd,
+ 0x0c4d, 0x0c4d,
+ 0x0ccd, 0x0ccd,
+ 0x0d3b, 0x0d3c,
+ 0x0d4d, 0x0d4d,
+ 0x0dca, 0x0dca,
+ 0x0e3a, 0x0e3a,
+ 0x0eba, 0x0eba,
+ 0x0f84, 0x0f84,
+ 0x1039, 0x103a,
+ 0x1714, 0x1715,
+ 0x1734, 0x1734,
+ 0x17d2, 0x17d2,
+ 0x1a60, 0x1a60,
+ 0x1b44, 0x1b44,
+ 0x1baa, 0x1bab,
+ 0x1bf2, 0x1bf3,
+ 0x2d7f, 0x2d7f,
+ 0xa806, 0xa806,
+ 0xa82c, 0xa82c,
+ 0xa8c4, 0xa8c4,
+ 0xa953, 0xa953,
+ 0xa9c0, 0xa9c0,
+ 0xaaf6, 0xaaf6,
+ 0xabed, 0xabed,
+ 0x10a3f, 0x10a3f,
+ 0x11046, 0x11046,
+ 0x11070, 0x11070,
+ 0x1107f, 0x1107f,
+ 0x110b9, 0x110b9,
+ 0x11133, 0x11134,
+ 0x111c0, 0x111c0,
+ 0x11235, 0x11235,
+ 0x112ea, 0x112ea,
+ 0x1134d, 0x1134d,
+ 0x113ce, 0x113d0,
+ 0x11442, 0x11442,
+ 0x114c2, 0x114c2,
+ 0x115bf, 0x115bf,
+ 0x1163f, 0x1163f,
+ 0x116b6, 0x116b6,
+ 0x1172b, 0x1172b,
+ 0x11839, 0x11839,
+ 0x1193d, 0x1193e,
+ 0x119e0, 0x119e0,
+ 0x11a34, 0x11a34,
+ 0x11a47, 0x11a47,
+ 0x11a99, 0x11a99,
+ 0x11c3f, 0x11c3f,
+ 0x11d44, 0x11d45,
+ 0x11d97, 0x11d97,
+ 0x11f41, 0x11f42,
+ 0x1612f, 0x1612f,
+}; /* CR_Grapheme_Link */
+
+/* 'InCB_Linker': Derived Property */
+static const OnigCodePoint CR_InCB_Linker[] = {
+ 20,
+ 0x094d, 0x094d,
+ 0x09cd, 0x09cd,
+ 0x0acd, 0x0acd,
+ 0x0b4d, 0x0b4d,
+ 0x0c4d, 0x0c4d,
+ 0x0d4d, 0x0d4d,
+ 0x1039, 0x1039,
+ 0x17d2, 0x17d2,
+ 0x1a60, 0x1a60,
+ 0x1b44, 0x1b44,
+ 0x1bab, 0x1bab,
+ 0xa9c0, 0xa9c0,
+ 0xaaf6, 0xaaf6,
+ 0x10a3f, 0x10a3f,
+ 0x11133, 0x11133,
+ 0x113d0, 0x113d0,
+ 0x1193e, 0x1193e,
+ 0x11a47, 0x11a47,
+ 0x11a99, 0x11a99,
+ 0x11f42, 0x11f42,
+}; /* CR_InCB_Linker */
+
+/* 'InCB_Consonant': Derived Property */
+static const OnigCodePoint CR_InCB_Consonant[] = {
+ 76,
+ 0x0915, 0x0939,
+ 0x0958, 0x095f,
+ 0x0978, 0x097f,
+ 0x0995, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09df,
+ 0x09f0, 0x09f1,
+ 0x0a95, 0x0aa8,
+ 0x0aaa, 0x0ab0,
+ 0x0ab2, 0x0ab3,
+ 0x0ab5, 0x0ab9,
+ 0x0af9, 0x0af9,
+ 0x0b15, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b35, 0x0b39,
+ 0x0b5c, 0x0b5d,
+ 0x0b5f, 0x0b5f,
+ 0x0b71, 0x0b71,
+ 0x0c15, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c58, 0x0c5a,
+ 0x0d15, 0x0d3a,
+ 0x1000, 0x102a,
+ 0x103f, 0x103f,
+ 0x1050, 0x1055,
+ 0x105a, 0x105d,
+ 0x1061, 0x1061,
+ 0x1065, 0x1066,
+ 0x106e, 0x1070,
+ 0x1075, 0x1081,
+ 0x108e, 0x108e,
+ 0x1780, 0x17b3,
+ 0x1a20, 0x1a54,
+ 0x1b0b, 0x1b0c,
+ 0x1b13, 0x1b33,
+ 0x1b45, 0x1b4c,
+ 0x1b83, 0x1ba0,
+ 0x1bae, 0x1baf,
+ 0x1bbb, 0x1bbd,
+ 0xa989, 0xa98b,
+ 0xa98f, 0xa9b2,
+ 0xa9e0, 0xa9e4,
+ 0xa9e7, 0xa9ef,
+ 0xa9fa, 0xa9fe,
+ 0xaa60, 0xaa6f,
+ 0xaa71, 0xaa73,
+ 0xaa7a, 0xaa7a,
+ 0xaa7e, 0xaa7f,
+ 0xaae0, 0xaaea,
+ 0xabc0, 0xabda,
+ 0x10a00, 0x10a00,
+ 0x10a10, 0x10a13,
+ 0x10a15, 0x10a17,
+ 0x10a19, 0x10a35,
+ 0x11103, 0x11126,
+ 0x11144, 0x11144,
+ 0x11147, 0x11147,
+ 0x11380, 0x11389,
+ 0x1138b, 0x1138b,
+ 0x1138e, 0x1138e,
+ 0x11390, 0x113b5,
+ 0x11900, 0x11906,
+ 0x11909, 0x11909,
+ 0x1190c, 0x11913,
+ 0x11915, 0x11916,
+ 0x11918, 0x1192f,
+ 0x11a00, 0x11a00,
+ 0x11a0b, 0x11a32,
+ 0x11a50, 0x11a50,
+ 0x11a5c, 0x11a83,
+ 0x11f04, 0x11f10,
+ 0x11f12, 0x11f33,
+}; /* CR_InCB_Consonant */
+
+/* 'InCB_Extend': Derived Property */
+static const OnigCodePoint CR_InCB_Extend[] = {
+ 377,
+ 0x0300, 0x036f,
+ 0x0483, 0x0489,
+ 0x0591, 0x05bd,
+ 0x05bf, 0x05bf,
+ 0x05c1, 0x05c2,
+ 0x05c4, 0x05c5,
+ 0x05c7, 0x05c7,
+ 0x0610, 0x061a,
+ 0x064b, 0x065f,
+ 0x0670, 0x0670,
+ 0x06d6, 0x06dc,
+ 0x06df, 0x06e4,
+ 0x06e7, 0x06e8,
+ 0x06ea, 0x06ed,
+ 0x0711, 0x0711,
+ 0x0730, 0x074a,
+ 0x07a6, 0x07b0,
+ 0x07eb, 0x07f3,
+ 0x07fd, 0x07fd,
+ 0x0816, 0x0819,
+ 0x081b, 0x0823,
+ 0x0825, 0x0827,
+ 0x0829, 0x082d,
+ 0x0859, 0x085b,
+ 0x0897, 0x089f,
+ 0x08ca, 0x08e1,
+ 0x08e3, 0x0902,
+ 0x093a, 0x093a,
+ 0x093c, 0x093c,
+ 0x0941, 0x0948,
+ 0x0951, 0x0957,
+ 0x0962, 0x0963,
+ 0x0981, 0x0981,
+ 0x09bc, 0x09bc,
+ 0x09be, 0x09be,
+ 0x09c1, 0x09c4,
+ 0x09d7, 0x09d7,
+ 0x09e2, 0x09e3,
+ 0x09fe, 0x09fe,
+ 0x0a01, 0x0a02,
+ 0x0a3c, 0x0a3c,
+ 0x0a41, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 0x0a70, 0x0a71,
+ 0x0a75, 0x0a75,
+ 0x0a81, 0x0a82,
+ 0x0abc, 0x0abc,
+ 0x0ac1, 0x0ac5,
+ 0x0ac7, 0x0ac8,
+ 0x0ae2, 0x0ae3,
+ 0x0afa, 0x0aff,
+ 0x0b01, 0x0b01,
+ 0x0b3c, 0x0b3c,
+ 0x0b3e, 0x0b3f,
+ 0x0b41, 0x0b44,
+ 0x0b55, 0x0b57,
+ 0x0b62, 0x0b63,
+ 0x0b82, 0x0b82,
+ 0x0bbe, 0x0bbe,
+ 0x0bc0, 0x0bc0,
+ 0x0bcd, 0x0bcd,
+ 0x0bd7, 0x0bd7,
+ 0x0c00, 0x0c00,
+ 0x0c04, 0x0c04,
+ 0x0c3c, 0x0c3c,
+ 0x0c3e, 0x0c40,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4c,
+ 0x0c55, 0x0c56,
+ 0x0c62, 0x0c63,
+ 0x0c81, 0x0c81,
+ 0x0cbc, 0x0cbc,
+ 0x0cbf, 0x0cc0,
+ 0x0cc2, 0x0cc2,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0ce2, 0x0ce3,
+ 0x0d00, 0x0d01,
+ 0x0d3b, 0x0d3c,
+ 0x0d3e, 0x0d3e,
+ 0x0d41, 0x0d44,
+ 0x0d57, 0x0d57,
+ 0x0d62, 0x0d63,
+ 0x0d81, 0x0d81,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dcf,
+ 0x0dd2, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0ddf, 0x0ddf,
+ 0x0e31, 0x0e31,
+ 0x0e34, 0x0e3a,
+ 0x0e47, 0x0e4e,
+ 0x0eb1, 0x0eb1,
+ 0x0eb4, 0x0ebc,
+ 0x0ec8, 0x0ece,
+ 0x0f18, 0x0f19,
+ 0x0f35, 0x0f35,
+ 0x0f37, 0x0f37,
+ 0x0f39, 0x0f39,
+ 0x0f71, 0x0f7e,
+ 0x0f80, 0x0f84,
+ 0x0f86, 0x0f87,
+ 0x0f8d, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 0x0fc6, 0x0fc6,
+ 0x102d, 0x1030,
+ 0x1032, 0x1037,
+ 0x103a, 0x103a,
+ 0x103d, 0x103e,
+ 0x1058, 0x1059,
+ 0x105e, 0x1060,
+ 0x1071, 0x1074,
+ 0x1082, 0x1082,
+ 0x1085, 0x1086,
+ 0x108d, 0x108d,
+ 0x109d, 0x109d,
+ 0x135d, 0x135f,
+ 0x1712, 0x1715,
+ 0x1732, 0x1734,
+ 0x1752, 0x1753,
+ 0x1772, 0x1773,
+ 0x17b4, 0x17b5,
+ 0x17b7, 0x17bd,
+ 0x17c6, 0x17c6,
+ 0x17c9, 0x17d1,
+ 0x17d3, 0x17d3,
+ 0x17dd, 0x17dd,
+ 0x180b, 0x180d,
+ 0x180f, 0x180f,
+ 0x1885, 0x1886,
+ 0x18a9, 0x18a9,
+ 0x1920, 0x1922,
+ 0x1927, 0x1928,
+ 0x1932, 0x1932,
+ 0x1939, 0x193b,
+ 0x1a17, 0x1a18,
+ 0x1a1b, 0x1a1b,
+ 0x1a56, 0x1a56,
+ 0x1a58, 0x1a5e,
+ 0x1a62, 0x1a62,
+ 0x1a65, 0x1a6c,
+ 0x1a73, 0x1a7c,
+ 0x1a7f, 0x1a7f,
+ 0x1ab0, 0x1add,
+ 0x1ae0, 0x1aeb,
+ 0x1b00, 0x1b03,
+ 0x1b34, 0x1b3d,
+ 0x1b42, 0x1b43,
+ 0x1b6b, 0x1b73,
+ 0x1b80, 0x1b81,
+ 0x1ba2, 0x1ba5,
+ 0x1ba8, 0x1baa,
+ 0x1bac, 0x1bad,
+ 0x1be6, 0x1be6,
+ 0x1be8, 0x1be9,
+ 0x1bed, 0x1bed,
+ 0x1bef, 0x1bf3,
+ 0x1c2c, 0x1c33,
+ 0x1c36, 0x1c37,
+ 0x1cd0, 0x1cd2,
+ 0x1cd4, 0x1ce0,
+ 0x1ce2, 0x1ce8,
+ 0x1ced, 0x1ced,
+ 0x1cf4, 0x1cf4,
+ 0x1cf8, 0x1cf9,
+ 0x1dc0, 0x1dff,
+ 0x200d, 0x200d,
+ 0x20d0, 0x20f0,
+ 0x2cef, 0x2cf1,
+ 0x2d7f, 0x2d7f,
+ 0x2de0, 0x2dff,
+ 0x302a, 0x302f,
+ 0x3099, 0x309a,
+ 0xa66f, 0xa672,
+ 0xa674, 0xa67d,
+ 0xa69e, 0xa69f,
+ 0xa6f0, 0xa6f1,
+ 0xa802, 0xa802,
+ 0xa806, 0xa806,
+ 0xa80b, 0xa80b,
+ 0xa825, 0xa826,
+ 0xa82c, 0xa82c,
+ 0xa8c4, 0xa8c5,
+ 0xa8e0, 0xa8f1,
+ 0xa8ff, 0xa8ff,
+ 0xa926, 0xa92d,
+ 0xa947, 0xa951,
+ 0xa953, 0xa953,
+ 0xa980, 0xa982,
+ 0xa9b3, 0xa9b3,
+ 0xa9b6, 0xa9b9,
+ 0xa9bc, 0xa9bd,
+ 0xa9e5, 0xa9e5,
+ 0xaa29, 0xaa2e,
+ 0xaa31, 0xaa32,
+ 0xaa35, 0xaa36,
+ 0xaa43, 0xaa43,
+ 0xaa4c, 0xaa4c,
+ 0xaa7c, 0xaa7c,
+ 0xaab0, 0xaab0,
+ 0xaab2, 0xaab4,
+ 0xaab7, 0xaab8,
+ 0xaabe, 0xaabf,
+ 0xaac1, 0xaac1,
+ 0xaaec, 0xaaed,
+ 0xabe5, 0xabe5,
+ 0xabe8, 0xabe8,
+ 0xabed, 0xabed,
+ 0xfb1e, 0xfb1e,
+ 0xfe00, 0xfe0f,
+ 0xfe20, 0xfe2f,
+ 0xff9e, 0xff9f,
+ 0x101fd, 0x101fd,
+ 0x102e0, 0x102e0,
+ 0x10376, 0x1037a,
+ 0x10a01, 0x10a03,
+ 0x10a05, 0x10a06,
+ 0x10a0c, 0x10a0f,
+ 0x10a38, 0x10a3a,
+ 0x10ae5, 0x10ae6,
+ 0x10d24, 0x10d27,
+ 0x10d69, 0x10d6d,
+ 0x10eab, 0x10eac,
+ 0x10efa, 0x10eff,
+ 0x10f46, 0x10f50,
+ 0x10f82, 0x10f85,
+ 0x11001, 0x11001,
+ 0x11038, 0x11046,
+ 0x11070, 0x11070,
+ 0x11073, 0x11074,
+ 0x1107f, 0x11081,
+ 0x110b3, 0x110b6,
+ 0x110b9, 0x110ba,
+ 0x110c2, 0x110c2,
+ 0x11100, 0x11102,
+ 0x11127, 0x1112b,
+ 0x1112d, 0x11132,
+ 0x11134, 0x11134,
+ 0x11173, 0x11173,
+ 0x11180, 0x11181,
+ 0x111b6, 0x111be,
+ 0x111c0, 0x111c0,
+ 0x111c9, 0x111cc,
+ 0x111cf, 0x111cf,
+ 0x1122f, 0x11231,
+ 0x11234, 0x11237,
+ 0x1123e, 0x1123e,
+ 0x11241, 0x11241,
+ 0x112df, 0x112df,
+ 0x112e3, 0x112ea,
+ 0x11300, 0x11301,
+ 0x1133b, 0x1133c,
+ 0x1133e, 0x1133e,
+ 0x11340, 0x11340,
+ 0x1134d, 0x1134d,
+ 0x11357, 0x11357,
+ 0x11366, 0x1136c,
+ 0x11370, 0x11374,
+ 0x113b8, 0x113b8,
+ 0x113bb, 0x113c0,
+ 0x113c2, 0x113c2,
+ 0x113c5, 0x113c5,
+ 0x113c7, 0x113c9,
+ 0x113ce, 0x113cf,
+ 0x113d2, 0x113d2,
+ 0x113e1, 0x113e2,
+ 0x11438, 0x1143f,
+ 0x11442, 0x11444,
+ 0x11446, 0x11446,
+ 0x1145e, 0x1145e,
+ 0x114b0, 0x114b0,
+ 0x114b3, 0x114b8,
+ 0x114ba, 0x114ba,
+ 0x114bd, 0x114bd,
+ 0x114bf, 0x114c0,
+ 0x114c2, 0x114c3,
+ 0x115af, 0x115af,
+ 0x115b2, 0x115b5,
+ 0x115bc, 0x115bd,
+ 0x115bf, 0x115c0,
+ 0x115dc, 0x115dd,
+ 0x11633, 0x1163a,
+ 0x1163d, 0x1163d,
+ 0x1163f, 0x11640,
+ 0x116ab, 0x116ab,
+ 0x116ad, 0x116ad,
+ 0x116b0, 0x116b7,
+ 0x1171d, 0x1171d,
+ 0x1171f, 0x1171f,
+ 0x11722, 0x11725,
+ 0x11727, 0x1172b,
+ 0x1182f, 0x11837,
+ 0x11839, 0x1183a,
+ 0x11930, 0x11930,
+ 0x1193b, 0x1193d,
+ 0x11943, 0x11943,
+ 0x119d4, 0x119d7,
+ 0x119da, 0x119db,
+ 0x119e0, 0x119e0,
+ 0x11a01, 0x11a0a,
+ 0x11a33, 0x11a38,
+ 0x11a3b, 0x11a3e,
+ 0x11a51, 0x11a56,
+ 0x11a59, 0x11a5b,
+ 0x11a8a, 0x11a96,
+ 0x11a98, 0x11a98,
+ 0x11b60, 0x11b60,
+ 0x11b62, 0x11b64,
+ 0x11b66, 0x11b66,
+ 0x11c30, 0x11c36,
+ 0x11c38, 0x11c3d,
+ 0x11c3f, 0x11c3f,
+ 0x11c92, 0x11ca7,
+ 0x11caa, 0x11cb0,
+ 0x11cb2, 0x11cb3,
+ 0x11cb5, 0x11cb6,
+ 0x11d31, 0x11d36,
+ 0x11d3a, 0x11d3a,
+ 0x11d3c, 0x11d3d,
+ 0x11d3f, 0x11d45,
+ 0x11d47, 0x11d47,
+ 0x11d90, 0x11d91,
+ 0x11d95, 0x11d95,
+ 0x11d97, 0x11d97,
+ 0x11ef3, 0x11ef4,
+ 0x11f00, 0x11f01,
+ 0x11f36, 0x11f3a,
+ 0x11f40, 0x11f41,
+ 0x11f5a, 0x11f5a,
+ 0x13440, 0x13440,
+ 0x13447, 0x13455,
+ 0x1611e, 0x16129,
+ 0x1612d, 0x1612f,
+ 0x16af0, 0x16af4,
+ 0x16b30, 0x16b36,
+ 0x16f4f, 0x16f4f,
+ 0x16f8f, 0x16f92,
+ 0x16fe4, 0x16fe4,
+ 0x16ff0, 0x16ff1,
+ 0x1bc9d, 0x1bc9e,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
+ 0x1d165, 0x1d169,
+ 0x1d16d, 0x1d172,
+ 0x1d17b, 0x1d182,
+ 0x1d185, 0x1d18b,
+ 0x1d1aa, 0x1d1ad,
+ 0x1d242, 0x1d244,
+ 0x1da00, 0x1da36,
+ 0x1da3b, 0x1da6c,
+ 0x1da75, 0x1da75,
+ 0x1da84, 0x1da84,
+ 0x1da9b, 0x1da9f,
+ 0x1daa1, 0x1daaf,
+ 0x1e000, 0x1e006,
+ 0x1e008, 0x1e018,
+ 0x1e01b, 0x1e021,
+ 0x1e023, 0x1e024,
+ 0x1e026, 0x1e02a,
+ 0x1e08f, 0x1e08f,
+ 0x1e130, 0x1e136,
+ 0x1e2ae, 0x1e2ae,
+ 0x1e2ec, 0x1e2ef,
+ 0x1e4ec, 0x1e4ef,
+ 0x1e5ee, 0x1e5ef,
+ 0x1e6e3, 0x1e6e3,
+ 0x1e6e6, 0x1e6e6,
+ 0x1e6ee, 0x1e6ef,
+ 0x1e6f5, 0x1e6f5,
+ 0x1e8d0, 0x1e8d6,
+ 0x1e944, 0x1e94a,
+ 0x1f3fb, 0x1f3ff,
+ 0xe0020, 0xe007f,
+ 0xe0100, 0xe01ef,
+}; /* CR_InCB_Extend */
+
+/* 'Common': Script */
+static const OnigCodePoint CR_Common[] = {
+ 176,
+ 0x0000, 0x0040,
+ 0x005b, 0x0060,
+ 0x007b, 0x00a9,
+ 0x00ab, 0x00b9,
+ 0x00bb, 0x00bf,
+ 0x00d7, 0x00d7,
+ 0x00f7, 0x00f7,
+ 0x02b9, 0x02df,
+ 0x02e5, 0x02e9,
+ 0x02ec, 0x02ff,
+ 0x0374, 0x0374,
+ 0x037e, 0x037e,
+ 0x0385, 0x0385,
+ 0x0387, 0x0387,
+ 0x0605, 0x0605,
+ 0x060c, 0x060c,
+ 0x061b, 0x061b,
+ 0x061f, 0x061f,
+ 0x0640, 0x0640,
+ 0x06dd, 0x06dd,
+ 0x08e2, 0x08e2,
+ 0x0964, 0x0965,
+ 0x0e3f, 0x0e3f,
+ 0x0fd5, 0x0fd8,
+ 0x10fb, 0x10fb,
+ 0x16eb, 0x16ed,
+ 0x1735, 0x1736,
+ 0x1802, 0x1803,
+ 0x1805, 0x1805,
+ 0x1cd3, 0x1cd3,
+ 0x1ce1, 0x1ce1,
+ 0x1ce9, 0x1cec,
+ 0x1cee, 0x1cf3,
+ 0x1cf5, 0x1cf7,
+ 0x1cfa, 0x1cfa,
+ 0x2000, 0x200b,
+ 0x200e, 0x2064,
+ 0x2066, 0x2070,
+ 0x2074, 0x207e,
+ 0x2080, 0x208e,
+ 0x20a0, 0x20c1,
+ 0x2100, 0x2125,
+ 0x2127, 0x2129,
+ 0x212c, 0x2131,
+ 0x2133, 0x214d,
+ 0x214f, 0x215f,
+ 0x2189, 0x218b,
+ 0x2190, 0x2429,
+ 0x2440, 0x244a,
+ 0x2460, 0x27ff,
+ 0x2900, 0x2b73,
+ 0x2b76, 0x2bff,
+ 0x2e00, 0x2e5d,
+ 0x2ff0, 0x3004,
+ 0x3006, 0x3006,
+ 0x3008, 0x3020,
+ 0x3030, 0x3037,
+ 0x303c, 0x303f,
+ 0x309b, 0x309c,
+ 0x30a0, 0x30a0,
+ 0x30fb, 0x30fc,
+ 0x3190, 0x319f,
+ 0x31c0, 0x31e5,
+ 0x31ef, 0x31ef,
+ 0x3220, 0x325f,
+ 0x327f, 0x32cf,
+ 0x32ff, 0x32ff,
+ 0x3358, 0x33ff,
+ 0x4dc0, 0x4dff,
+ 0xa700, 0xa721,
+ 0xa788, 0xa78a,
+ 0xa830, 0xa839,
+ 0xa92e, 0xa92e,
+ 0xa9cf, 0xa9cf,
+ 0xab5b, 0xab5b,
+ 0xab6a, 0xab6b,
+ 0xfd3e, 0xfd3f,
+ 0xfe10, 0xfe19,
+ 0xfe30, 0xfe52,
+ 0xfe54, 0xfe66,
+ 0xfe68, 0xfe6b,
+ 0xfeff, 0xfeff,
+ 0xff01, 0xff20,
+ 0xff3b, 0xff40,
+ 0xff5b, 0xff65,
+ 0xff70, 0xff70,
+ 0xff9e, 0xff9f,
+ 0xffe0, 0xffe6,
+ 0xffe8, 0xffee,
+ 0xfff9, 0xfffd,
+ 0x10100, 0x10102,
+ 0x10107, 0x10133,
+ 0x10137, 0x1013f,
+ 0x10190, 0x1019c,
+ 0x101d0, 0x101fc,
+ 0x102e1, 0x102fb,
+ 0x1bca0, 0x1bca3,
+ 0x1cc00, 0x1ccfc,
+ 0x1cd00, 0x1ceb3,
+ 0x1ceba, 0x1ced0,
+ 0x1cee0, 0x1cef0,
+ 0x1cf50, 0x1cfc3,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d129, 0x1d166,
+ 0x1d16a, 0x1d17a,
+ 0x1d183, 0x1d184,
+ 0x1d18c, 0x1d1a9,
+ 0x1d1ae, 0x1d1ea,
+ 0x1d2c0, 0x1d2d3,
+ 0x1d2e0, 0x1d2f3,
+ 0x1d300, 0x1d356,
+ 0x1d360, 0x1d378,
+ 0x1d400, 0x1d454,
+ 0x1d456, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 0x1d4a2, 0x1d4a2,
+ 0x1d4a5, 0x1d4a6,
+ 0x1d4a9, 0x1d4ac,
+ 0x1d4ae, 0x1d4b9,
+ 0x1d4bb, 0x1d4bb,
+ 0x1d4bd, 0x1d4c3,
+ 0x1d4c5, 0x1d505,
+ 0x1d507, 0x1d50a,
+ 0x1d50d, 0x1d514,
+ 0x1d516, 0x1d51c,
+ 0x1d51e, 0x1d539,
+ 0x1d53b, 0x1d53e,
+ 0x1d540, 0x1d544,
+ 0x1d546, 0x1d546,
+ 0x1d54a, 0x1d550,
+ 0x1d552, 0x1d6a5,
+ 0x1d6a8, 0x1d7cb,
+ 0x1d7ce, 0x1d7ff,
+ 0x1ec71, 0x1ecb4,
+ 0x1ed01, 0x1ed3d,
+ 0x1f000, 0x1f02b,
+ 0x1f030, 0x1f093,
+ 0x1f0a0, 0x1f0ae,
+ 0x1f0b1, 0x1f0bf,
+ 0x1f0c1, 0x1f0cf,
+ 0x1f0d1, 0x1f0f5,
+ 0x1f100, 0x1f1ad,
+ 0x1f1e6, 0x1f1ff,
+ 0x1f201, 0x1f202,
+ 0x1f210, 0x1f23b,
+ 0x1f240, 0x1f248,
+ 0x1f250, 0x1f251,
+ 0x1f260, 0x1f265,
+ 0x1f300, 0x1f6d8,
+ 0x1f6dc, 0x1f6ec,
+ 0x1f6f0, 0x1f6fc,
+ 0x1f700, 0x1f7d9,
+ 0x1f7e0, 0x1f7eb,
+ 0x1f7f0, 0x1f7f0,
+ 0x1f800, 0x1f80b,
+ 0x1f810, 0x1f847,
+ 0x1f850, 0x1f859,
+ 0x1f860, 0x1f887,
+ 0x1f890, 0x1f8ad,
+ 0x1f8b0, 0x1f8bb,
+ 0x1f8c0, 0x1f8c1,
+ 0x1f8d0, 0x1f8d8,
+ 0x1f900, 0x1fa57,
+ 0x1fa60, 0x1fa6d,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa8a,
+ 0x1fa8e, 0x1fac6,
+ 0x1fac8, 0x1fac8,
+ 0x1facd, 0x1fadc,
+ 0x1fadf, 0x1faea,
+ 0x1faef, 0x1faf8,
+ 0x1fb00, 0x1fb92,
+ 0x1fb94, 0x1fbfa,
+ 0xe0001, 0xe0001,
+ 0xe0020, 0xe007f,
+}; /* CR_Common */
+
+/* 'Latin': Script */
+static const OnigCodePoint CR_Latin[] = {
+ 36,
+ 0x0041, 0x005a,
+ 0x0061, 0x007a,
+ 0x00aa, 0x00aa,
+ 0x00ba, 0x00ba,
+ 0x00c0, 0x00d6,
+ 0x00d8, 0x00f6,
+ 0x00f8, 0x02b8,
+ 0x02e0, 0x02e4,
+ 0x1d00, 0x1d25,
+ 0x1d2c, 0x1d5c,
+ 0x1d62, 0x1d65,
+ 0x1d6b, 0x1d77,
+ 0x1d79, 0x1dbe,
+ 0x1e00, 0x1eff,
+ 0x2071, 0x2071,
+ 0x207f, 0x207f,
+ 0x2090, 0x209c,
+ 0x212a, 0x212b,
+ 0x2132, 0x2132,
+ 0x214e, 0x214e,
+ 0x2160, 0x2188,
+ 0x2c60, 0x2c7f,
+ 0xa722, 0xa787,
+ 0xa78b, 0xa7dc,
+ 0xa7f1, 0xa7ff,
+ 0xab30, 0xab5a,
+ 0xab5c, 0xab64,
+ 0xab66, 0xab69,
+ 0xfb00, 0xfb06,
+ 0xff21, 0xff3a,
+ 0xff41, 0xff5a,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
+}; /* CR_Latin */
+
+/* 'Greek': Script */
+static const OnigCodePoint CR_Greek[] = {
+ 36,
+ 0x0370, 0x0373,
+ 0x0375, 0x0377,
+ 0x037a, 0x037d,
+ 0x037f, 0x037f,
+ 0x0384, 0x0384,
+ 0x0386, 0x0386,
+ 0x0388, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x03e1,
+ 0x03f0, 0x03ff,
+ 0x1d26, 0x1d2a,
+ 0x1d5d, 0x1d61,
+ 0x1d66, 0x1d6a,
+ 0x1dbf, 0x1dbf,
+ 0x1f00, 0x1f15,
+ 0x1f18, 0x1f1d,
+ 0x1f20, 0x1f45,
+ 0x1f48, 0x1f4d,
+ 0x1f50, 0x1f57,
+ 0x1f59, 0x1f59,
+ 0x1f5b, 0x1f5b,
+ 0x1f5d, 0x1f5d,
+ 0x1f5f, 0x1f7d,
+ 0x1f80, 0x1fb4,
+ 0x1fb6, 0x1fc4,
+ 0x1fc6, 0x1fd3,
+ 0x1fd6, 0x1fdb,
+ 0x1fdd, 0x1fef,
+ 0x1ff2, 0x1ff4,
+ 0x1ff6, 0x1ffe,
+ 0x2126, 0x2126,
+ 0xab65, 0xab65,
+ 0x10140, 0x1018e,
+ 0x101a0, 0x101a0,
+ 0x1d200, 0x1d245,
+}; /* CR_Greek */
+
+/* 'Cyrillic': Script */
+static const OnigCodePoint CR_Cyrillic[] = {
+ 10,
+ 0x0400, 0x0484,
+ 0x0487, 0x052f,
+ 0x1c80, 0x1c8a,
+ 0x1d2b, 0x1d2b,
+ 0x1d78, 0x1d78,
+ 0x2de0, 0x2dff,
+ 0xa640, 0xa69f,
+ 0xfe2e, 0xfe2f,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
+}; /* CR_Cyrillic */
+
+/* 'Armenian': Script */
+static const OnigCodePoint CR_Armenian[] = {
+ 4,
+ 0x0531, 0x0556,
+ 0x0559, 0x058a,
+ 0x058d, 0x058f,
+ 0xfb13, 0xfb17,
+}; /* CR_Armenian */
+
+/* 'Hebrew': Script */
+static const OnigCodePoint CR_Hebrew[] = {
+ 9,
+ 0x0591, 0x05c7,
+ 0x05d0, 0x05ea,
+ 0x05ef, 0x05f4,
+ 0xfb1d, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfb4f,
+}; /* CR_Hebrew */
+
+/* 'Arabic': Script */
+static const OnigCodePoint CR_Arabic[] = {
+ 56,
+ 0x0600, 0x0604,
+ 0x0606, 0x060b,
+ 0x060d, 0x061a,
+ 0x061c, 0x061e,
+ 0x0620, 0x063f,
+ 0x0641, 0x064a,
+ 0x0656, 0x066f,
+ 0x0671, 0x06dc,
+ 0x06de, 0x06ff,
+ 0x0750, 0x077f,
+ 0x0870, 0x0891,
+ 0x0897, 0x08e1,
+ 0x08e3, 0x08ff,
+ 0xfb50, 0xfd3d,
+ 0xfd40, 0xfdcf,
+ 0xfdf0, 0xfdff,
+ 0xfe70, 0xfe74,
+ 0xfe76, 0xfefc,
+ 0x10e60, 0x10e7e,
+ 0x10ec2, 0x10ec7,
+ 0x10ed0, 0x10ed8,
+ 0x10efa, 0x10eff,
+ 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,
+}; /* CR_Arabic */
+
+/* 'Syriac': Script */
+static const OnigCodePoint CR_Syriac[] = {
+ 4,
+ 0x0700, 0x070d,
+ 0x070f, 0x074a,
+ 0x074d, 0x074f,
+ 0x0860, 0x086a,
+}; /* CR_Syriac */
+
+/* 'Thaana': Script */
+static const OnigCodePoint CR_Thaana[] = {
+ 1,
+ 0x0780, 0x07b1,
+}; /* CR_Thaana */
+
+/* 'Devanagari': Script */
+static const OnigCodePoint CR_Devanagari[] = {
+ 5,
+ 0x0900, 0x0950,
+ 0x0955, 0x0963,
+ 0x0966, 0x097f,
+ 0xa8e0, 0xa8ff,
+ 0x11b00, 0x11b09,
+}; /* CR_Devanagari */
+
+/* 'Bengali': Script */
+static const OnigCodePoint CR_Bengali[] = {
+ 14,
+ 0x0980, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fe,
+}; /* CR_Bengali */
+
+/* 'Gurmukhi': Script */
+static const OnigCodePoint CR_Gurmukhi[] = {
+ 16,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a76,
+}; /* CR_Gurmukhi */
+
+/* 'Gujarati': Script */
+static const OnigCodePoint CR_Gujarati[] = {
+ 14,
+ 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,
+}; /* CR_Gujarati */
+
+/* 'Oriya': Script */
+static const OnigCodePoint CR_Oriya[] = {
+ 14,
+ 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,
+}; /* CR_Oriya */
+
+/* 'Tamil': Script */
+static const OnigCodePoint CR_Tamil[] = {
+ 18,
+ 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,
+ 0x0be6, 0x0bfa,
+ 0x11fc0, 0x11ff1,
+ 0x11fff, 0x11fff,
+}; /* CR_Tamil */
+
+/* 'Telugu': Script */
+static const OnigCodePoint CR_Telugu[] = {
+ 13,
+ 0x0c00, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3c, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c5a,
+ 0x0c5c, 0x0c5d,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c77, 0x0c7f,
+}; /* CR_Telugu */
+
+/* 'Kannada': Script */
+static const OnigCodePoint CR_Kannada[] = {
+ 13,
+ 0x0c80, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cdc, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf3,
+}; /* CR_Kannada */
+
+/* 'Malayalam': Script */
+static const OnigCodePoint CR_Malayalam[] = {
+ 7,
+ 0x0d00, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d44,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4f,
+ 0x0d54, 0x0d63,
+ 0x0d66, 0x0d7f,
+}; /* CR_Malayalam */
+
+/* 'Sinhala': Script */
+static const OnigCodePoint CR_Sinhala[] = {
+ 13,
+ 0x0d81, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0de6, 0x0def,
+ 0x0df2, 0x0df4,
+ 0x111e1, 0x111f4,
+}; /* CR_Sinhala */
+
+/* 'Thai': Script */
+static const OnigCodePoint CR_Thai[] = {
+ 2,
+ 0x0e01, 0x0e3a,
+ 0x0e40, 0x0e5b,
+}; /* CR_Thai */
+
+/* 'Lao': Script */
+static const OnigCodePoint CR_Lao[] = {
+ 11,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e86, 0x0e8a,
+ 0x0e8c, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ece,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+}; /* CR_Lao */
+
+/* 'Tibetan': Script */
+static const OnigCodePoint CR_Tibetan[] = {
+ 7,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 0x0fbe, 0x0fcc,
+ 0x0fce, 0x0fd4,
+ 0x0fd9, 0x0fda,
+}; /* CR_Tibetan */
+
+/* 'Myanmar': Script */
+static const OnigCodePoint CR_Myanmar[] = {
+ 4,
+ 0x1000, 0x109f,
+ 0xa9e0, 0xa9fe,
+ 0xaa60, 0xaa7f,
+ 0x116d0, 0x116e3,
+}; /* CR_Myanmar */
+
+/* 'Georgian': Script */
+static const OnigCodePoint CR_Georgian[] = {
+ 10,
+ 0x10a0, 0x10c5,
+ 0x10c7, 0x10c7,
+ 0x10cd, 0x10cd,
+ 0x10d0, 0x10fa,
+ 0x10fc, 0x10ff,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cbf,
+ 0x2d00, 0x2d25,
+ 0x2d27, 0x2d27,
+ 0x2d2d, 0x2d2d,
+}; /* CR_Georgian */
+
+/* 'Hangul': Script */
+static const OnigCodePoint CR_Hangul[] = {
+ 14,
+ 0x1100, 0x11ff,
+ 0x302e, 0x302f,
+ 0x3131, 0x318e,
+ 0x3200, 0x321e,
+ 0x3260, 0x327e,
+ 0xa960, 0xa97c,
+ 0xac00, 0xd7a3,
+ 0xd7b0, 0xd7c6,
+ 0xd7cb, 0xd7fb,
+ 0xffa0, 0xffbe,
+ 0xffc2, 0xffc7,
+ 0xffca, 0xffcf,
+ 0xffd2, 0xffd7,
+ 0xffda, 0xffdc,
+}; /* CR_Hangul */
+
+/* 'Ethiopic': Script */
+static const OnigCodePoint CR_Ethiopic[] = {
+ 36,
+ 0x1200, 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,
+ 0x2d80, 0x2d96,
+ 0x2da0, 0x2da6,
+ 0x2da8, 0x2dae,
+ 0x2db0, 0x2db6,
+ 0x2db8, 0x2dbe,
+ 0x2dc0, 0x2dc6,
+ 0x2dc8, 0x2dce,
+ 0x2dd0, 0x2dd6,
+ 0x2dd8, 0x2dde,
+ 0xab01, 0xab06,
+ 0xab09, 0xab0e,
+ 0xab11, 0xab16,
+ 0xab20, 0xab26,
+ 0xab28, 0xab2e,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
+}; /* CR_Ethiopic */
+
+/* 'Cherokee': Script */
+static const OnigCodePoint CR_Cherokee[] = {
+ 3,
+ 0x13a0, 0x13f5,
+ 0x13f8, 0x13fd,
+ 0xab70, 0xabbf,
+}; /* CR_Cherokee */
+
+/* 'Canadian_Aboriginal': Script */
+static const OnigCodePoint CR_Canadian_Aboriginal[] = {
+ 3,
+ 0x1400, 0x167f,
+ 0x18b0, 0x18f5,
+ 0x11ab0, 0x11abf,
+}; /* CR_Canadian_Aboriginal */
+
+/* 'Ogham': Script */
+static const OnigCodePoint CR_Ogham[] = {
+ 1,
+ 0x1680, 0x169c,
+}; /* CR_Ogham */
+
+/* 'Runic': Script */
+static const OnigCodePoint CR_Runic[] = {
+ 2,
+ 0x16a0, 0x16ea,
+ 0x16ee, 0x16f8,
+}; /* CR_Runic */
+
+/* 'Khmer': Script */
+static const OnigCodePoint CR_Khmer[] = {
+ 4,
+ 0x1780, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x19e0, 0x19ff,
+}; /* CR_Khmer */
+
+/* 'Mongolian': Script */
+static const OnigCodePoint CR_Mongolian[] = {
+ 6,
+ 0x1800, 0x1801,
+ 0x1804, 0x1804,
+ 0x1806, 0x1819,
+ 0x1820, 0x1878,
+ 0x1880, 0x18aa,
+ 0x11660, 0x1166c,
+}; /* CR_Mongolian */
+
+/* 'Hiragana': Script */
+static const OnigCodePoint CR_Hiragana[] = {
+ 6,
+ 0x3041, 0x3096,
+ 0x309d, 0x309f,
+ 0x1b001, 0x1b11f,
+ 0x1b132, 0x1b132,
+ 0x1b150, 0x1b152,
+ 0x1f200, 0x1f200,
+}; /* CR_Hiragana */
+
+/* 'Katakana': Script */
+static const OnigCodePoint CR_Katakana[] = {
+ 14,
+ 0x30a1, 0x30fa,
+ 0x30fd, 0x30ff,
+ 0x31f0, 0x31ff,
+ 0x32d0, 0x32fe,
+ 0x3300, 0x3357,
+ 0xff66, 0xff6f,
+ 0xff71, 0xff9d,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b000,
+ 0x1b120, 0x1b122,
+ 0x1b155, 0x1b155,
+ 0x1b164, 0x1b167,
+}; /* CR_Katakana */
+
+/* 'Bopomofo': Script */
+static const OnigCodePoint CR_Bopomofo[] = {
+ 3,
+ 0x02ea, 0x02eb,
+ 0x3105, 0x312f,
+ 0x31a0, 0x31bf,
+}; /* CR_Bopomofo */
+
+/* 'Han': Script */
+static const OnigCodePoint CR_Han[] = {
+ 21,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x3005, 0x3005,
+ 0x3007, 0x3007,
+ 0x3021, 0x3029,
+ 0x3038, 0x303b,
+ 0x3400, 0x4dbf,
+ 0x4e00, 0x9fff,
+ 0xf900, 0xfa6d,
+ 0xfa70, 0xfad9,
+ 0x16fe2, 0x16fe3,
+ 0x16ff0, 0x16ff6,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b81d,
+ 0x2b820, 0x2cead,
+ 0x2ceb0, 0x2ebe0,
+ 0x2ebf0, 0x2ee5d,
+ 0x2f800, 0x2fa1d,
+ 0x30000, 0x3134a,
+ 0x31350, 0x33479,
+}; /* CR_Han */
+
+/* 'Yi': Script */
+static const OnigCodePoint CR_Yi[] = {
+ 2,
+ 0xa000, 0xa48c,
+ 0xa490, 0xa4c6,
+}; /* CR_Yi */
+
+/* 'Old_Italic': Script */
+static const OnigCodePoint CR_Old_Italic[] = {
+ 2,
+ 0x10300, 0x10323,
+ 0x1032d, 0x1032f,
+}; /* CR_Old_Italic */
+
+/* 'Gothic': Script */
+static const OnigCodePoint CR_Gothic[] = {
+ 1,
+ 0x10330, 0x1034a,
+}; /* CR_Gothic */
+
+/* 'Deseret': Script */
+static const OnigCodePoint CR_Deseret[] = {
+ 1,
+ 0x10400, 0x1044f,
+}; /* CR_Deseret */
+
+/* 'Inherited': Script */
+static const OnigCodePoint CR_Inherited[] = {
+ 30,
+ 0x0300, 0x036f,
+ 0x0485, 0x0486,
+ 0x064b, 0x0655,
+ 0x0670, 0x0670,
+ 0x0951, 0x0954,
+ 0x1ab0, 0x1add,
+ 0x1ae0, 0x1aeb,
+ 0x1cd0, 0x1cd2,
+ 0x1cd4, 0x1ce0,
+ 0x1ce2, 0x1ce8,
+ 0x1ced, 0x1ced,
+ 0x1cf4, 0x1cf4,
+ 0x1cf8, 0x1cf9,
+ 0x1dc0, 0x1dff,
+ 0x200c, 0x200d,
+ 0x20d0, 0x20f0,
+ 0x302a, 0x302d,
+ 0x3099, 0x309a,
+ 0xfe00, 0xfe0f,
+ 0xfe20, 0xfe2d,
+ 0x101fd, 0x101fd,
+ 0x102e0, 0x102e0,
+ 0x1133b, 0x1133b,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
+ 0x1d167, 0x1d169,
+ 0x1d17b, 0x1d182,
+ 0x1d185, 0x1d18b,
+ 0x1d1aa, 0x1d1ad,
+ 0xe0100, 0xe01ef,
+}; /* CR_Inherited */
+
+/* 'Tagalog': Script */
+static const OnigCodePoint CR_Tagalog[] = {
+ 2,
+ 0x1700, 0x1715,
+ 0x171f, 0x171f,
+}; /* CR_Tagalog */
+
+/* 'Hanunoo': Script */
+static const OnigCodePoint CR_Hanunoo[] = {
+ 1,
+ 0x1720, 0x1734,
+}; /* CR_Hanunoo */
+
+/* 'Buhid': Script */
+static const OnigCodePoint CR_Buhid[] = {
+ 1,
+ 0x1740, 0x1753,
+}; /* CR_Buhid */
+
+/* 'Tagbanwa': Script */
+static const OnigCodePoint CR_Tagbanwa[] = {
+ 3,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+}; /* CR_Tagbanwa */
+
+/* 'Limbu': Script */
+static const OnigCodePoint CR_Limbu[] = {
+ 5,
+ 0x1900, 0x191e,
+ 0x1920, 0x192b,
+ 0x1930, 0x193b,
+ 0x1940, 0x1940,
+ 0x1944, 0x194f,
+}; /* CR_Limbu */
+
+/* 'Tai_Le': Script */
+static const OnigCodePoint CR_Tai_Le[] = {
+ 2,
+ 0x1950, 0x196d,
+ 0x1970, 0x1974,
+}; /* CR_Tai_Le */
+
+/* 'Linear_B': Script */
+static const OnigCodePoint CR_Linear_B[] = {
+ 7,
+ 0x10000, 0x1000b,
+ 0x1000d, 0x10026,
+ 0x10028, 0x1003a,
+ 0x1003c, 0x1003d,
+ 0x1003f, 0x1004d,
+ 0x10050, 0x1005d,
+ 0x10080, 0x100fa,
+}; /* CR_Linear_B */
+
+/* 'Ugaritic': Script */
+static const OnigCodePoint CR_Ugaritic[] = {
+ 2,
+ 0x10380, 0x1039d,
+ 0x1039f, 0x1039f,
+}; /* CR_Ugaritic */
+
+/* 'Shavian': Script */
+static const OnigCodePoint CR_Shavian[] = {
+ 1,
+ 0x10450, 0x1047f,
+}; /* CR_Shavian */
+
+/* 'Osmanya': Script */
+static const OnigCodePoint CR_Osmanya[] = {
+ 2,
+ 0x10480, 0x1049d,
+ 0x104a0, 0x104a9,
+}; /* CR_Osmanya */
+
+/* 'Cypriot': Script */
+static const OnigCodePoint CR_Cypriot[] = {
+ 6,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 0x10837, 0x10838,
+ 0x1083c, 0x1083c,
+ 0x1083f, 0x1083f,
+}; /* CR_Cypriot */
+
+/* 'Braille': Script */
+static const OnigCodePoint CR_Braille[] = {
+ 1,
+ 0x2800, 0x28ff,
+}; /* CR_Braille */
+
+/* 'Buginese': Script */
+static const OnigCodePoint CR_Buginese[] = {
+ 2,
+ 0x1a00, 0x1a1b,
+ 0x1a1e, 0x1a1f,
+}; /* CR_Buginese */
+
+/* 'Coptic': Script */
+static const OnigCodePoint CR_Coptic[] = {
+ 3,
+ 0x03e2, 0x03ef,
+ 0x2c80, 0x2cf3,
+ 0x2cf9, 0x2cff,
+}; /* CR_Coptic */
+
+/* 'New_Tai_Lue': Script */
+static const OnigCodePoint CR_New_Tai_Lue[] = {
+ 4,
+ 0x1980, 0x19ab,
+ 0x19b0, 0x19c9,
+ 0x19d0, 0x19da,
+ 0x19de, 0x19df,
+}; /* CR_New_Tai_Lue */
+
+/* 'Glagolitic': Script */
+static const OnigCodePoint CR_Glagolitic[] = {
+ 6,
+ 0x2c00, 0x2c5f,
+ 0x1e000, 0x1e006,
+ 0x1e008, 0x1e018,
+ 0x1e01b, 0x1e021,
+ 0x1e023, 0x1e024,
+ 0x1e026, 0x1e02a,
+}; /* CR_Glagolitic */
+
+/* 'Tifinagh': Script */
+static const OnigCodePoint CR_Tifinagh[] = {
+ 3,
+ 0x2d30, 0x2d67,
+ 0x2d6f, 0x2d70,
+ 0x2d7f, 0x2d7f,
+}; /* CR_Tifinagh */
+
+/* 'Syloti_Nagri': Script */
+static const OnigCodePoint CR_Syloti_Nagri[] = {
+ 1,
+ 0xa800, 0xa82c,
+}; /* CR_Syloti_Nagri */
+
+/* 'Old_Persian': Script */
+static const OnigCodePoint CR_Old_Persian[] = {
+ 2,
+ 0x103a0, 0x103c3,
+ 0x103c8, 0x103d5,
+}; /* CR_Old_Persian */
+
+/* 'Kharoshthi': Script */
+static const OnigCodePoint CR_Kharoshthi[] = {
+ 8,
+ 0x10a00, 0x10a03,
+ 0x10a05, 0x10a06,
+ 0x10a0c, 0x10a13,
+ 0x10a15, 0x10a17,
+ 0x10a19, 0x10a35,
+ 0x10a38, 0x10a3a,
+ 0x10a3f, 0x10a48,
+ 0x10a50, 0x10a58,
+}; /* CR_Kharoshthi */
+
+/* 'Balinese': Script */
+static const OnigCodePoint CR_Balinese[] = {
+ 2,
+ 0x1b00, 0x1b4c,
+ 0x1b4e, 0x1b7f,
+}; /* CR_Balinese */
+
+/* 'Cuneiform': Script */
+static const OnigCodePoint CR_Cuneiform[] = {
+ 4,
+ 0x12000, 0x12399,
+ 0x12400, 0x1246e,
+ 0x12470, 0x12474,
+ 0x12480, 0x12543,
+}; /* CR_Cuneiform */
+
+/* 'Phoenician': Script */
+static const OnigCodePoint CR_Phoenician[] = {
+ 2,
+ 0x10900, 0x1091b,
+ 0x1091f, 0x1091f,
+}; /* CR_Phoenician */
+
+/* 'Phags_Pa': Script */
+static const OnigCodePoint CR_Phags_Pa[] = {
+ 1,
+ 0xa840, 0xa877,
+}; /* CR_Phags_Pa */
+
+/* 'Nko': Script */
+static const OnigCodePoint CR_Nko[] = {
+ 2,
+ 0x07c0, 0x07fa,
+ 0x07fd, 0x07ff,
+}; /* CR_Nko */
+
+/* 'Sundanese': Script */
+static const OnigCodePoint CR_Sundanese[] = {
+ 2,
+ 0x1b80, 0x1bbf,
+ 0x1cc0, 0x1cc7,
+}; /* CR_Sundanese */
+
+/* 'Lepcha': Script */
+static const OnigCodePoint CR_Lepcha[] = {
+ 3,
+ 0x1c00, 0x1c37,
+ 0x1c3b, 0x1c49,
+ 0x1c4d, 0x1c4f,
+}; /* CR_Lepcha */
+
+/* 'Ol_Chiki': Script */
+static const OnigCodePoint CR_Ol_Chiki[] = {
+ 1,
+ 0x1c50, 0x1c7f,
+}; /* CR_Ol_Chiki */
+
+/* 'Vai': Script */
+static const OnigCodePoint CR_Vai[] = {
+ 1,
+ 0xa500, 0xa62b,
+}; /* CR_Vai */
+
+/* 'Saurashtra': Script */
+static const OnigCodePoint CR_Saurashtra[] = {
+ 2,
+ 0xa880, 0xa8c5,
+ 0xa8ce, 0xa8d9,
+}; /* CR_Saurashtra */
+
+/* 'Kayah_Li': Script */
+static const OnigCodePoint CR_Kayah_Li[] = {
+ 2,
+ 0xa900, 0xa92d,
+ 0xa92f, 0xa92f,
+}; /* CR_Kayah_Li */
+
+/* 'Rejang': Script */
+static const OnigCodePoint CR_Rejang[] = {
+ 2,
+ 0xa930, 0xa953,
+ 0xa95f, 0xa95f,
+}; /* CR_Rejang */
+
+/* 'Lycian': Script */
+static const OnigCodePoint CR_Lycian[] = {
+ 1,
+ 0x10280, 0x1029c,
+}; /* CR_Lycian */
+
+/* 'Carian': Script */
+static const OnigCodePoint CR_Carian[] = {
+ 1,
+ 0x102a0, 0x102d0,
+}; /* CR_Carian */
+
+/* 'Lydian': Script */
+static const OnigCodePoint CR_Lydian[] = {
+ 2,
+ 0x10920, 0x10939,
+ 0x1093f, 0x1093f,
+}; /* CR_Lydian */
+
+/* 'Cham': Script */
+static const OnigCodePoint CR_Cham[] = {
+ 4,
+ 0xaa00, 0xaa36,
+ 0xaa40, 0xaa4d,
+ 0xaa50, 0xaa59,
+ 0xaa5c, 0xaa5f,
+}; /* CR_Cham */
+
+/* 'Tai_Tham': Script */
+static const OnigCodePoint CR_Tai_Tham[] = {
+ 5,
+ 0x1a20, 0x1a5e,
+ 0x1a60, 0x1a7c,
+ 0x1a7f, 0x1a89,
+ 0x1a90, 0x1a99,
+ 0x1aa0, 0x1aad,
+}; /* CR_Tai_Tham */
+
+/* 'Tai_Viet': Script */
+static const OnigCodePoint CR_Tai_Viet[] = {
+ 2,
+ 0xaa80, 0xaac2,
+ 0xaadb, 0xaadf,
+}; /* CR_Tai_Viet */
+
+/* 'Avestan': Script */
+static const OnigCodePoint CR_Avestan[] = {
+ 2,
+ 0x10b00, 0x10b35,
+ 0x10b39, 0x10b3f,
+}; /* CR_Avestan */
+
+/* 'Egyptian_Hieroglyphs': Script */
+static const OnigCodePoint CR_Egyptian_Hieroglyphs[] = {
+ 2,
+ 0x13000, 0x13455,
+ 0x13460, 0x143fa,
+}; /* CR_Egyptian_Hieroglyphs */
+
+/* 'Samaritan': Script */
+static const OnigCodePoint CR_Samaritan[] = {
+ 2,
+ 0x0800, 0x082d,
+ 0x0830, 0x083e,
+}; /* CR_Samaritan */
+
+/* 'Lisu': Script */
+static const OnigCodePoint CR_Lisu[] = {
+ 2,
+ 0xa4d0, 0xa4ff,
+ 0x11fb0, 0x11fb0,
+}; /* CR_Lisu */
+
+/* 'Bamum': Script */
+static const OnigCodePoint CR_Bamum[] = {
+ 2,
+ 0xa6a0, 0xa6f7,
+ 0x16800, 0x16a38,
+}; /* CR_Bamum */
+
+/* 'Javanese': Script */
+static const OnigCodePoint CR_Javanese[] = {
+ 3,
+ 0xa980, 0xa9cd,
+ 0xa9d0, 0xa9d9,
+ 0xa9de, 0xa9df,
+}; /* CR_Javanese */
+
+/* 'Meetei_Mayek': Script */
+static const OnigCodePoint CR_Meetei_Mayek[] = {
+ 3,
+ 0xaae0, 0xaaf6,
+ 0xabc0, 0xabed,
+ 0xabf0, 0xabf9,
+}; /* CR_Meetei_Mayek */
+
+/* 'Imperial_Aramaic': Script */
+static const OnigCodePoint CR_Imperial_Aramaic[] = {
+ 2,
+ 0x10840, 0x10855,
+ 0x10857, 0x1085f,
+}; /* CR_Imperial_Aramaic */
+
+/* 'Old_South_Arabian': Script */
+static const OnigCodePoint CR_Old_South_Arabian[] = {
+ 1,
+ 0x10a60, 0x10a7f,
+}; /* CR_Old_South_Arabian */
+
+/* 'Inscriptional_Parthian': Script */
+static const OnigCodePoint CR_Inscriptional_Parthian[] = {
+ 2,
+ 0x10b40, 0x10b55,
+ 0x10b58, 0x10b5f,
+}; /* CR_Inscriptional_Parthian */
+
+/* 'Inscriptional_Pahlavi': Script */
+static const OnigCodePoint CR_Inscriptional_Pahlavi[] = {
+ 2,
+ 0x10b60, 0x10b72,
+ 0x10b78, 0x10b7f,
+}; /* CR_Inscriptional_Pahlavi */
+
+/* 'Old_Turkic': Script */
+static const OnigCodePoint CR_Old_Turkic[] = {
+ 1,
+ 0x10c00, 0x10c48,
+}; /* CR_Old_Turkic */
+
+/* 'Kaithi': Script */
+static const OnigCodePoint CR_Kaithi[] = {
+ 2,
+ 0x11080, 0x110c2,
+ 0x110cd, 0x110cd,
+}; /* CR_Kaithi */
+
+/* 'Batak': Script */
+static const OnigCodePoint CR_Batak[] = {
+ 2,
+ 0x1bc0, 0x1bf3,
+ 0x1bfc, 0x1bff,
+}; /* CR_Batak */
+
+/* 'Brahmi': Script */
+static const OnigCodePoint CR_Brahmi[] = {
+ 3,
+ 0x11000, 0x1104d,
+ 0x11052, 0x11075,
+ 0x1107f, 0x1107f,
+}; /* CR_Brahmi */
+
+/* 'Mandaic': Script */
+static const OnigCodePoint CR_Mandaic[] = {
+ 2,
+ 0x0840, 0x085b,
+ 0x085e, 0x085e,
+}; /* CR_Mandaic */
+
+/* 'Chakma': Script */
+static const OnigCodePoint CR_Chakma[] = {
+ 2,
+ 0x11100, 0x11134,
+ 0x11136, 0x11147,
+}; /* CR_Chakma */
+
+/* 'Meroitic_Cursive': Script */
+static const OnigCodePoint CR_Meroitic_Cursive[] = {
+ 3,
+ 0x109a0, 0x109b7,
+ 0x109bc, 0x109cf,
+ 0x109d2, 0x109ff,
+}; /* CR_Meroitic_Cursive */
+
+/* 'Meroitic_Hieroglyphs': Script */
+static const OnigCodePoint CR_Meroitic_Hieroglyphs[] = {
+ 1,
+ 0x10980, 0x1099f,
+}; /* CR_Meroitic_Hieroglyphs */
+
+/* 'Miao': Script */
+static const OnigCodePoint CR_Miao[] = {
+ 3,
+ 0x16f00, 0x16f4a,
+ 0x16f4f, 0x16f87,
+ 0x16f8f, 0x16f9f,
+}; /* CR_Miao */
+
+/* 'Sharada': Script */
+static const OnigCodePoint CR_Sharada[] = {
+ 2,
+ 0x11180, 0x111df,
+ 0x11b60, 0x11b67,
+}; /* CR_Sharada */
+
+/* 'Sora_Sompeng': Script */
+static const OnigCodePoint CR_Sora_Sompeng[] = {
+ 2,
+ 0x110d0, 0x110e8,
+ 0x110f0, 0x110f9,
+}; /* CR_Sora_Sompeng */
+
+/* 'Takri': Script */
+static const OnigCodePoint CR_Takri[] = {
+ 2,
+ 0x11680, 0x116b9,
+ 0x116c0, 0x116c9,
+}; /* CR_Takri */
+
+/* 'Caucasian_Albanian': Script */
+static const OnigCodePoint CR_Caucasian_Albanian[] = {
+ 2,
+ 0x10530, 0x10563,
+ 0x1056f, 0x1056f,
+}; /* CR_Caucasian_Albanian */
+
+/* 'Bassa_Vah': Script */
+static const OnigCodePoint CR_Bassa_Vah[] = {
+ 2,
+ 0x16ad0, 0x16aed,
+ 0x16af0, 0x16af5,
+}; /* CR_Bassa_Vah */
+
+/* 'Duployan': Script */
+static const OnigCodePoint CR_Duployan[] = {
+ 5,
+ 0x1bc00, 0x1bc6a,
+ 0x1bc70, 0x1bc7c,
+ 0x1bc80, 0x1bc88,
+ 0x1bc90, 0x1bc99,
+ 0x1bc9c, 0x1bc9f,
+}; /* CR_Duployan */
+
+/* 'Elbasan': Script */
+static const OnigCodePoint CR_Elbasan[] = {
+ 1,
+ 0x10500, 0x10527,
+}; /* CR_Elbasan */
+
+/* 'Grantha': Script */
+static const OnigCodePoint CR_Grantha[] = {
+ 15,
+ 0x11300, 0x11303,
+ 0x11305, 0x1130c,
+ 0x1130f, 0x11310,
+ 0x11313, 0x11328,
+ 0x1132a, 0x11330,
+ 0x11332, 0x11333,
+ 0x11335, 0x11339,
+ 0x1133c, 0x11344,
+ 0x11347, 0x11348,
+ 0x1134b, 0x1134d,
+ 0x11350, 0x11350,
+ 0x11357, 0x11357,
+ 0x1135d, 0x11363,
+ 0x11366, 0x1136c,
+ 0x11370, 0x11374,
+}; /* CR_Grantha */
+
+/* 'Pahawh_Hmong': Script */
+static const OnigCodePoint CR_Pahawh_Hmong[] = {
+ 5,
+ 0x16b00, 0x16b45,
+ 0x16b50, 0x16b59,
+ 0x16b5b, 0x16b61,
+ 0x16b63, 0x16b77,
+ 0x16b7d, 0x16b8f,
+}; /* CR_Pahawh_Hmong */
+
+/* 'Khojki': Script */
+static const OnigCodePoint CR_Khojki[] = {
+ 2,
+ 0x11200, 0x11211,
+ 0x11213, 0x11241,
+}; /* CR_Khojki */
+
+/* 'Linear_A': Script */
+static const OnigCodePoint CR_Linear_A[] = {
+ 3,
+ 0x10600, 0x10736,
+ 0x10740, 0x10755,
+ 0x10760, 0x10767,
+}; /* CR_Linear_A */
+
+/* 'Mahajani': Script */
+static const OnigCodePoint CR_Mahajani[] = {
+ 1,
+ 0x11150, 0x11176,
+}; /* CR_Mahajani */
+
+/* 'Manichaean': Script */
+static const OnigCodePoint CR_Manichaean[] = {
+ 2,
+ 0x10ac0, 0x10ae6,
+ 0x10aeb, 0x10af6,
+}; /* CR_Manichaean */
+
+/* 'Mende_Kikakui': Script */
+static const OnigCodePoint CR_Mende_Kikakui[] = {
+ 2,
+ 0x1e800, 0x1e8c4,
+ 0x1e8c7, 0x1e8d6,
+}; /* CR_Mende_Kikakui */
+
+/* 'Modi': Script */
+static const OnigCodePoint CR_Modi[] = {
+ 2,
+ 0x11600, 0x11644,
+ 0x11650, 0x11659,
+}; /* CR_Modi */
+
+/* 'Mro': Script */
+static const OnigCodePoint CR_Mro[] = {
+ 3,
+ 0x16a40, 0x16a5e,
+ 0x16a60, 0x16a69,
+ 0x16a6e, 0x16a6f,
+}; /* CR_Mro */
+
+/* 'Old_North_Arabian': Script */
+static const OnigCodePoint CR_Old_North_Arabian[] = {
+ 1,
+ 0x10a80, 0x10a9f,
+}; /* CR_Old_North_Arabian */
+
+/* 'Nabataean': Script */
+static const OnigCodePoint CR_Nabataean[] = {
+ 2,
+ 0x10880, 0x1089e,
+ 0x108a7, 0x108af,
+}; /* CR_Nabataean */
+
+/* 'Palmyrene': Script */
+static const OnigCodePoint CR_Palmyrene[] = {
+ 1,
+ 0x10860, 0x1087f,
+}; /* CR_Palmyrene */
+
+/* 'Pau_Cin_Hau': Script */
+static const OnigCodePoint CR_Pau_Cin_Hau[] = {
+ 1,
+ 0x11ac0, 0x11af8,
+}; /* CR_Pau_Cin_Hau */
+
+/* 'Old_Permic': Script */
+static const OnigCodePoint CR_Old_Permic[] = {
+ 1,
+ 0x10350, 0x1037a,
+}; /* CR_Old_Permic */
+
+/* 'Psalter_Pahlavi': Script */
+static const OnigCodePoint CR_Psalter_Pahlavi[] = {
+ 3,
+ 0x10b80, 0x10b91,
+ 0x10b99, 0x10b9c,
+ 0x10ba9, 0x10baf,
+}; /* CR_Psalter_Pahlavi */
+
+/* 'Siddham': Script */
+static const OnigCodePoint CR_Siddham[] = {
+ 2,
+ 0x11580, 0x115b5,
+ 0x115b8, 0x115dd,
+}; /* CR_Siddham */
+
+/* 'Khudawadi': Script */
+static const OnigCodePoint CR_Khudawadi[] = {
+ 2,
+ 0x112b0, 0x112ea,
+ 0x112f0, 0x112f9,
+}; /* CR_Khudawadi */
+
+/* 'Tirhuta': Script */
+static const OnigCodePoint CR_Tirhuta[] = {
+ 2,
+ 0x11480, 0x114c7,
+ 0x114d0, 0x114d9,
+}; /* CR_Tirhuta */
+
+/* 'Warang_Citi': Script */
+static const OnigCodePoint CR_Warang_Citi[] = {
+ 2,
+ 0x118a0, 0x118f2,
+ 0x118ff, 0x118ff,
+}; /* CR_Warang_Citi */
+
+/* 'Ahom': Script */
+static const OnigCodePoint CR_Ahom[] = {
+ 3,
+ 0x11700, 0x1171a,
+ 0x1171d, 0x1172b,
+ 0x11730, 0x11746,
+}; /* CR_Ahom */
+
+/* 'Anatolian_Hieroglyphs': Script */
+static const OnigCodePoint CR_Anatolian_Hieroglyphs[] = {
+ 1,
+ 0x14400, 0x14646,
+}; /* CR_Anatolian_Hieroglyphs */
+
+/* 'Hatran': Script */
+static const OnigCodePoint CR_Hatran[] = {
+ 3,
+ 0x108e0, 0x108f2,
+ 0x108f4, 0x108f5,
+ 0x108fb, 0x108ff,
+}; /* CR_Hatran */
+
+/* 'Multani': Script */
+static const OnigCodePoint CR_Multani[] = {
+ 5,
+ 0x11280, 0x11286,
+ 0x11288, 0x11288,
+ 0x1128a, 0x1128d,
+ 0x1128f, 0x1129d,
+ 0x1129f, 0x112a9,
+}; /* CR_Multani */
+
+/* 'Old_Hungarian': Script */
+static const OnigCodePoint CR_Old_Hungarian[] = {
+ 3,
+ 0x10c80, 0x10cb2,
+ 0x10cc0, 0x10cf2,
+ 0x10cfa, 0x10cff,
+}; /* CR_Old_Hungarian */
+
+/* 'SignWriting': Script */
+static const OnigCodePoint CR_SignWriting[] = {
+ 3,
+ 0x1d800, 0x1da8b,
+ 0x1da9b, 0x1da9f,
+ 0x1daa1, 0x1daaf,
+}; /* CR_SignWriting */
+
+/* 'Adlam': Script */
+static const OnigCodePoint CR_Adlam[] = {
+ 3,
+ 0x1e900, 0x1e94b,
+ 0x1e950, 0x1e959,
+ 0x1e95e, 0x1e95f,
+}; /* CR_Adlam */
+
+/* 'Bhaiksuki': Script */
+static const OnigCodePoint CR_Bhaiksuki[] = {
+ 4,
+ 0x11c00, 0x11c08,
+ 0x11c0a, 0x11c36,
+ 0x11c38, 0x11c45,
+ 0x11c50, 0x11c6c,
+}; /* CR_Bhaiksuki */
+
+/* 'Marchen': Script */
+static const OnigCodePoint CR_Marchen[] = {
+ 3,
+ 0x11c70, 0x11c8f,
+ 0x11c92, 0x11ca7,
+ 0x11ca9, 0x11cb6,
+}; /* CR_Marchen */
+
+/* 'Newa': Script */
+static const OnigCodePoint CR_Newa[] = {
+ 2,
+ 0x11400, 0x1145b,
+ 0x1145d, 0x11461,
+}; /* CR_Newa */
+
+/* 'Osage': Script */
+static const OnigCodePoint CR_Osage[] = {
+ 2,
+ 0x104b0, 0x104d3,
+ 0x104d8, 0x104fb,
+}; /* CR_Osage */
+
+/* 'Tangut': Script */
+static const OnigCodePoint CR_Tangut[] = {
+ 4,
+ 0x16fe0, 0x16fe0,
+ 0x17000, 0x18aff,
+ 0x18d00, 0x18d1e,
+ 0x18d80, 0x18df2,
+}; /* CR_Tangut */
+
+/* 'Masaram_Gondi': Script */
+static const OnigCodePoint CR_Masaram_Gondi[] = {
+ 7,
+ 0x11d00, 0x11d06,
+ 0x11d08, 0x11d09,
+ 0x11d0b, 0x11d36,
+ 0x11d3a, 0x11d3a,
+ 0x11d3c, 0x11d3d,
+ 0x11d3f, 0x11d47,
+ 0x11d50, 0x11d59,
+}; /* CR_Masaram_Gondi */
+
+/* 'Nushu': Script */
+static const OnigCodePoint CR_Nushu[] = {
+ 2,
+ 0x16fe1, 0x16fe1,
+ 0x1b170, 0x1b2fb,
+}; /* CR_Nushu */
+
+/* 'Soyombo': Script */
+static const OnigCodePoint CR_Soyombo[] = {
+ 1,
+ 0x11a50, 0x11aa2,
+}; /* CR_Soyombo */
+
+/* 'Zanabazar_Square': Script */
+static const OnigCodePoint CR_Zanabazar_Square[] = {
+ 1,
+ 0x11a00, 0x11a47,
+}; /* CR_Zanabazar_Square */
+
+/* 'Dogra': Script */
+static const OnigCodePoint CR_Dogra[] = {
+ 1,
+ 0x11800, 0x1183b,
+}; /* CR_Dogra */
+
+/* 'Gunjala_Gondi': Script */
+static const OnigCodePoint CR_Gunjala_Gondi[] = {
+ 6,
+ 0x11d60, 0x11d65,
+ 0x11d67, 0x11d68,
+ 0x11d6a, 0x11d8e,
+ 0x11d90, 0x11d91,
+ 0x11d93, 0x11d98,
+ 0x11da0, 0x11da9,
+}; /* CR_Gunjala_Gondi */
+
+/* 'Makasar': Script */
+static const OnigCodePoint CR_Makasar[] = {
+ 1,
+ 0x11ee0, 0x11ef8,
+}; /* CR_Makasar */
+
+/* 'Medefaidrin': Script */
+static const OnigCodePoint CR_Medefaidrin[] = {
+ 1,
+ 0x16e40, 0x16e9a,
+}; /* CR_Medefaidrin */
+
+/* 'Hanifi_Rohingya': Script */
+static const OnigCodePoint CR_Hanifi_Rohingya[] = {
+ 2,
+ 0x10d00, 0x10d27,
+ 0x10d30, 0x10d39,
+}; /* CR_Hanifi_Rohingya */
+
+/* 'Sogdian': Script */
+static const OnigCodePoint CR_Sogdian[] = {
+ 1,
+ 0x10f30, 0x10f59,
+}; /* CR_Sogdian */
+
+/* 'Old_Sogdian': Script */
+static const OnigCodePoint CR_Old_Sogdian[] = {
+ 1,
+ 0x10f00, 0x10f27,
+}; /* CR_Old_Sogdian */
+
+/* 'Elymaic': Script */
+static const OnigCodePoint CR_Elymaic[] = {
+ 1,
+ 0x10fe0, 0x10ff6,
+}; /* CR_Elymaic */
+
+/* 'Nandinagari': Script */
+static const OnigCodePoint CR_Nandinagari[] = {
+ 3,
+ 0x119a0, 0x119a7,
+ 0x119aa, 0x119d7,
+ 0x119da, 0x119e4,
+}; /* CR_Nandinagari */
+
+/* 'Nyiakeng_Puachue_Hmong': Script */
+static const OnigCodePoint CR_Nyiakeng_Puachue_Hmong[] = {
+ 4,
+ 0x1e100, 0x1e12c,
+ 0x1e130, 0x1e13d,
+ 0x1e140, 0x1e149,
+ 0x1e14e, 0x1e14f,
+}; /* CR_Nyiakeng_Puachue_Hmong */
+
+/* 'Wancho': Script */
+static const OnigCodePoint CR_Wancho[] = {
+ 2,
+ 0x1e2c0, 0x1e2f9,
+ 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[] = {
+ 3,
+ 0x16fe4, 0x16fe4,
+ 0x18b00, 0x18cd5,
+ 0x18cff, 0x18cff,
+}; /* CR_Khitan_Small_Script */
+
+/* 'Yezidi': Script */
+static const OnigCodePoint CR_Yezidi[] = {
+ 3,
+ 0x10e80, 0x10ea9,
+ 0x10eab, 0x10ead,
+ 0x10eb0, 0x10eb1,
+}; /* CR_Yezidi */
+
+/* 'Cypro_Minoan': Script */
+static const OnigCodePoint CR_Cypro_Minoan[] = {
+ 1,
+ 0x12f90, 0x12ff2,
+}; /* CR_Cypro_Minoan */
+
+/* 'Old_Uyghur': Script */
+static const OnigCodePoint CR_Old_Uyghur[] = {
+ 1,
+ 0x10f70, 0x10f89,
+}; /* CR_Old_Uyghur */
+
+/* 'Tangsa': Script */
+static const OnigCodePoint CR_Tangsa[] = {
+ 2,
+ 0x16a70, 0x16abe,
+ 0x16ac0, 0x16ac9,
+}; /* CR_Tangsa */
+
+/* 'Toto': Script */
+static const OnigCodePoint CR_Toto[] = {
+ 1,
+ 0x1e290, 0x1e2ae,
+}; /* CR_Toto */
+
+/* 'Vithkuqi': Script */
+static const OnigCodePoint CR_Vithkuqi[] = {
+ 8,
+ 0x10570, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+}; /* CR_Vithkuqi */
+
+/* 'Kawi': Script */
+static const OnigCodePoint CR_Kawi[] = {
+ 3,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f5a,
+}; /* CR_Kawi */
+
+/* 'Nag_Mundari': Script */
+static const OnigCodePoint CR_Nag_Mundari[] = {
+ 1,
+ 0x1e4d0, 0x1e4f9,
+}; /* CR_Nag_Mundari */
+
+/* 'Garay': Script */
+static const OnigCodePoint CR_Garay[] = {
+ 3,
+ 0x10d40, 0x10d65,
+ 0x10d69, 0x10d85,
+ 0x10d8e, 0x10d8f,
+}; /* CR_Garay */
+
+/* 'Gurung_Khema': Script */
+static const OnigCodePoint CR_Gurung_Khema[] = {
+ 1,
+ 0x16100, 0x16139,
+}; /* CR_Gurung_Khema */
+
+/* 'Kirat_Rai': Script */
+static const OnigCodePoint CR_Kirat_Rai[] = {
+ 1,
+ 0x16d40, 0x16d79,
+}; /* CR_Kirat_Rai */
+
+/* 'Ol_Onal': Script */
+static const OnigCodePoint CR_Ol_Onal[] = {
+ 2,
+ 0x1e5d0, 0x1e5fa,
+ 0x1e5ff, 0x1e5ff,
+}; /* CR_Ol_Onal */
+
+/* 'Sunuwar': Script */
+static const OnigCodePoint CR_Sunuwar[] = {
+ 2,
+ 0x11bc0, 0x11be1,
+ 0x11bf0, 0x11bf9,
+}; /* CR_Sunuwar */
+
+/* 'Todhri': Script */
+static const OnigCodePoint CR_Todhri[] = {
+ 1,
+ 0x105c0, 0x105f3,
+}; /* CR_Todhri */
+
+/* 'Tulu_Tigalari': Script */
+static const OnigCodePoint CR_Tulu_Tigalari[] = {
+ 11,
+ 0x11380, 0x11389,
+ 0x1138b, 0x1138b,
+ 0x1138e, 0x1138e,
+ 0x11390, 0x113b5,
+ 0x113b7, 0x113c0,
+ 0x113c2, 0x113c2,
+ 0x113c5, 0x113c5,
+ 0x113c7, 0x113ca,
+ 0x113cc, 0x113d5,
+ 0x113d7, 0x113d8,
+ 0x113e1, 0x113e2,
+}; /* CR_Tulu_Tigalari */
+
+/* 'Sidetic': Script */
+static const OnigCodePoint CR_Sidetic[] = {
+ 1,
+ 0x10940, 0x10959,
+}; /* CR_Sidetic */
+
+/* 'Tai_Yo': Script */
+static const OnigCodePoint CR_Tai_Yo[] = {
+ 3,
+ 0x1e6c0, 0x1e6de,
+ 0x1e6e0, 0x1e6f5,
+ 0x1e6fe, 0x1e6ff,
+}; /* CR_Tai_Yo */
+
+/* 'Tolong_Siki': Script */
+static const OnigCodePoint CR_Tolong_Siki[] = {
+ 2,
+ 0x11db0, 0x11ddb,
+ 0x11de0, 0x11de9,
+}; /* CR_Tolong_Siki */
+
+/* 'Beria_Erfe': Script */
+static const OnigCodePoint CR_Beria_Erfe[] = {
+ 2,
+ 0x16ea0, 0x16eb8,
+ 0x16ebb, 0x16ed3,
+}; /* CR_Beria_Erfe */
+
+/* 'White_Space': Binary Property */
+#define CR_White_Space CR_Space
+
+/* 'Bidi_Control': Binary Property */
+static const OnigCodePoint CR_Bidi_Control[] = {
+ 4,
+ 0x061c, 0x061c,
+ 0x200e, 0x200f,
+ 0x202a, 0x202e,
+ 0x2066, 0x2069,
+}; /* CR_Bidi_Control */
+
+/* 'Join_Control': Binary Property */
+static const OnigCodePoint CR_Join_Control[] = {
+ 1,
+ 0x200c, 0x200d,
+}; /* CR_Join_Control */
+
+/* 'Dash': Binary Property */
+static const OnigCodePoint CR_Dash[] = {
+ 24,
+ 0x002d, 0x002d,
+ 0x058a, 0x058a,
+ 0x05be, 0x05be,
+ 0x1400, 0x1400,
+ 0x1806, 0x1806,
+ 0x2010, 0x2015,
+ 0x2053, 0x2053,
+ 0x207b, 0x207b,
+ 0x208b, 0x208b,
+ 0x2212, 0x2212,
+ 0x2e17, 0x2e17,
+ 0x2e1a, 0x2e1a,
+ 0x2e3a, 0x2e3b,
+ 0x2e40, 0x2e40,
+ 0x2e5d, 0x2e5d,
+ 0x301c, 0x301c,
+ 0x3030, 0x3030,
+ 0x30a0, 0x30a0,
+ 0xfe31, 0xfe32,
+ 0xfe58, 0xfe58,
+ 0xfe63, 0xfe63,
+ 0xff0d, 0xff0d,
+ 0x10d6e, 0x10d6e,
+ 0x10ead, 0x10ead,
+}; /* CR_Dash */
+
+/* 'Hyphen': Binary Property */
+static const OnigCodePoint CR_Hyphen[] = {
+ 10,
+ 0x002d, 0x002d,
+ 0x00ad, 0x00ad,
+ 0x058a, 0x058a,
+ 0x1806, 0x1806,
+ 0x2010, 0x2011,
+ 0x2e17, 0x2e17,
+ 0x30fb, 0x30fb,
+ 0xfe63, 0xfe63,
+ 0xff0d, 0xff0d,
+ 0xff65, 0xff65,
+}; /* CR_Hyphen */
+
+/* 'Quotation_Mark': Binary Property */
+static const OnigCodePoint CR_Quotation_Mark[] = {
+ 13,
+ 0x0022, 0x0022,
+ 0x0027, 0x0027,
+ 0x00ab, 0x00ab,
+ 0x00bb, 0x00bb,
+ 0x2018, 0x201f,
+ 0x2039, 0x203a,
+ 0x2e42, 0x2e42,
+ 0x300c, 0x300f,
+ 0x301d, 0x301f,
+ 0xfe41, 0xfe44,
+ 0xff02, 0xff02,
+ 0xff07, 0xff07,
+ 0xff62, 0xff63,
+}; /* CR_Quotation_Mark */
+
+/* 'Terminal_Punctuation': Binary Property */
+static const OnigCodePoint CR_Terminal_Punctuation[] = {
+ 116,
+ 0x0021, 0x0021,
+ 0x002c, 0x002c,
+ 0x002e, 0x002e,
+ 0x003a, 0x003b,
+ 0x003f, 0x003f,
+ 0x037e, 0x037e,
+ 0x0387, 0x0387,
+ 0x0589, 0x0589,
+ 0x05c3, 0x05c3,
+ 0x060c, 0x060c,
+ 0x061b, 0x061b,
+ 0x061d, 0x061f,
+ 0x06d4, 0x06d4,
+ 0x0700, 0x070a,
+ 0x070c, 0x070c,
+ 0x07f8, 0x07f9,
+ 0x0830, 0x0835,
+ 0x0837, 0x083e,
+ 0x085e, 0x085e,
+ 0x0964, 0x0965,
+ 0x0e5a, 0x0e5b,
+ 0x0f08, 0x0f08,
+ 0x0f0d, 0x0f12,
+ 0x104a, 0x104b,
+ 0x1361, 0x1368,
+ 0x166e, 0x166e,
+ 0x16eb, 0x16ed,
+ 0x1735, 0x1736,
+ 0x17d4, 0x17d6,
+ 0x17da, 0x17da,
+ 0x1802, 0x1805,
+ 0x1808, 0x1809,
+ 0x1944, 0x1945,
+ 0x1aa8, 0x1aab,
+ 0x1b4e, 0x1b4f,
+ 0x1b5a, 0x1b5b,
+ 0x1b5d, 0x1b5f,
+ 0x1b7d, 0x1b7f,
+ 0x1c3b, 0x1c3f,
+ 0x1c7e, 0x1c7f,
+ 0x2024, 0x2024,
+ 0x203c, 0x203d,
+ 0x2047, 0x2049,
+ 0x2cf9, 0x2cfb,
+ 0x2e2e, 0x2e2e,
+ 0x2e3c, 0x2e3c,
+ 0x2e41, 0x2e41,
+ 0x2e4c, 0x2e4c,
+ 0x2e4e, 0x2e4f,
+ 0x2e53, 0x2e54,
+ 0x3001, 0x3002,
+ 0xa4fe, 0xa4ff,
+ 0xa60d, 0xa60f,
+ 0xa6f3, 0xa6f7,
+ 0xa876, 0xa877,
+ 0xa8ce, 0xa8cf,
+ 0xa92f, 0xa92f,
+ 0xa9c7, 0xa9c9,
+ 0xaa5d, 0xaa5f,
+ 0xaadf, 0xaadf,
+ 0xaaf0, 0xaaf1,
+ 0xabeb, 0xabeb,
+ 0xfe12, 0xfe12,
+ 0xfe15, 0xfe16,
+ 0xfe50, 0xfe52,
+ 0xfe54, 0xfe57,
+ 0xff01, 0xff01,
+ 0xff0c, 0xff0c,
+ 0xff0e, 0xff0e,
+ 0xff1a, 0xff1b,
+ 0xff1f, 0xff1f,
+ 0xff61, 0xff61,
+ 0xff64, 0xff64,
+ 0x1039f, 0x1039f,
+ 0x103d0, 0x103d0,
+ 0x10857, 0x10857,
+ 0x1091f, 0x1091f,
+ 0x10a56, 0x10a57,
+ 0x10af0, 0x10af5,
+ 0x10b3a, 0x10b3f,
+ 0x10b99, 0x10b9c,
+ 0x10f55, 0x10f59,
+ 0x10f86, 0x10f89,
+ 0x11047, 0x1104d,
+ 0x110be, 0x110c1,
+ 0x11141, 0x11143,
+ 0x111c5, 0x111c6,
+ 0x111cd, 0x111cd,
+ 0x111de, 0x111df,
+ 0x11238, 0x1123c,
+ 0x112a9, 0x112a9,
+ 0x113d4, 0x113d5,
+ 0x1144b, 0x1144d,
+ 0x1145a, 0x1145b,
+ 0x115c2, 0x115c5,
+ 0x115c9, 0x115d7,
+ 0x11641, 0x11642,
+ 0x1173c, 0x1173e,
+ 0x11944, 0x11944,
+ 0x11946, 0x11946,
+ 0x11a42, 0x11a43,
+ 0x11a9b, 0x11a9c,
+ 0x11aa1, 0x11aa2,
+ 0x11c41, 0x11c43,
+ 0x11c71, 0x11c71,
+ 0x11ef7, 0x11ef8,
+ 0x11f43, 0x11f44,
+ 0x12470, 0x12474,
+ 0x16a6e, 0x16a6f,
+ 0x16af5, 0x16af5,
+ 0x16b37, 0x16b39,
+ 0x16b44, 0x16b44,
+ 0x16d6e, 0x16d6f,
+ 0x16e97, 0x16e98,
+ 0x1bc9f, 0x1bc9f,
+ 0x1da87, 0x1da8a,
+}; /* CR_Terminal_Punctuation */
+
+/* 'Other_Math': Binary Property */
+static const OnigCodePoint CR_Other_Math[] = {
+ 134,
+ 0x005e, 0x005e,
+ 0x03d0, 0x03d2,
+ 0x03d5, 0x03d5,
+ 0x03f0, 0x03f1,
+ 0x03f4, 0x03f5,
+ 0x2016, 0x2016,
+ 0x2032, 0x2034,
+ 0x2040, 0x2040,
+ 0x2061, 0x2064,
+ 0x207d, 0x207e,
+ 0x208d, 0x208e,
+ 0x20d0, 0x20dc,
+ 0x20e1, 0x20e1,
+ 0x20e5, 0x20e6,
+ 0x20eb, 0x20ef,
+ 0x2102, 0x2102,
+ 0x2107, 0x2107,
+ 0x210a, 0x2113,
+ 0x2115, 0x2115,
+ 0x2119, 0x211d,
+ 0x2124, 0x2124,
+ 0x2128, 0x2129,
+ 0x212c, 0x212d,
+ 0x212f, 0x2131,
+ 0x2133, 0x2138,
+ 0x213c, 0x213f,
+ 0x2145, 0x2149,
+ 0x2195, 0x2199,
+ 0x219c, 0x219f,
+ 0x21a1, 0x21a2,
+ 0x21a4, 0x21a5,
+ 0x21a7, 0x21a7,
+ 0x21a9, 0x21ad,
+ 0x21b0, 0x21b1,
+ 0x21b6, 0x21b7,
+ 0x21bc, 0x21cd,
+ 0x21d0, 0x21d1,
+ 0x21d3, 0x21d3,
+ 0x21d5, 0x21db,
+ 0x21dd, 0x21dd,
+ 0x21e4, 0x21e5,
+ 0x2308, 0x230b,
+ 0x23b4, 0x23b5,
+ 0x23b7, 0x23b7,
+ 0x23d0, 0x23d0,
+ 0x23e2, 0x23e2,
+ 0x25a0, 0x25a1,
+ 0x25ae, 0x25b6,
+ 0x25bc, 0x25c0,
+ 0x25c6, 0x25c7,
+ 0x25ca, 0x25cb,
+ 0x25cf, 0x25d3,
+ 0x25e2, 0x25e2,
+ 0x25e4, 0x25e4,
+ 0x25e7, 0x25ec,
+ 0x2605, 0x2606,
+ 0x2640, 0x2640,
+ 0x2642, 0x2642,
+ 0x2660, 0x2663,
+ 0x266d, 0x266e,
+ 0x27c5, 0x27c6,
+ 0x27e6, 0x27ef,
+ 0x2983, 0x2998,
+ 0x29d8, 0x29db,
+ 0x29fc, 0x29fd,
+ 0xfe61, 0xfe61,
+ 0xfe63, 0xfe63,
+ 0xfe68, 0xfe68,
+ 0xff3c, 0xff3c,
+ 0xff3e, 0xff3e,
+ 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, 0x1d6c0,
+ 0x1d6c2, 0x1d6da,
+ 0x1d6dc, 0x1d6fa,
+ 0x1d6fc, 0x1d714,
+ 0x1d716, 0x1d734,
+ 0x1d736, 0x1d74e,
+ 0x1d750, 0x1d76e,
+ 0x1d770, 0x1d788,
+ 0x1d78a, 0x1d7a8,
+ 0x1d7aa, 0x1d7c2,
+ 0x1d7c4, 0x1d7cb,
+ 0x1d7ce, 0x1d7ff,
+ 0x1ee00, 0x1ee03,
+ 0x1ee05, 0x1ee1f,
+ 0x1ee21, 0x1ee22,
+ 0x1ee24, 0x1ee24,
+ 0x1ee27, 0x1ee27,
+ 0x1ee29, 0x1ee32,
+ 0x1ee34, 0x1ee37,
+ 0x1ee39, 0x1ee39,
+ 0x1ee3b, 0x1ee3b,
+ 0x1ee42, 0x1ee42,
+ 0x1ee47, 0x1ee47,
+ 0x1ee49, 0x1ee49,
+ 0x1ee4b, 0x1ee4b,
+ 0x1ee4d, 0x1ee4f,
+ 0x1ee51, 0x1ee52,
+ 0x1ee54, 0x1ee54,
+ 0x1ee57, 0x1ee57,
+ 0x1ee59, 0x1ee59,
+ 0x1ee5b, 0x1ee5b,
+ 0x1ee5d, 0x1ee5d,
+ 0x1ee5f, 0x1ee5f,
+ 0x1ee61, 0x1ee62,
+ 0x1ee64, 0x1ee64,
+ 0x1ee67, 0x1ee6a,
+ 0x1ee6c, 0x1ee72,
+ 0x1ee74, 0x1ee77,
+ 0x1ee79, 0x1ee7c,
+ 0x1ee7e, 0x1ee7e,
+ 0x1ee80, 0x1ee89,
+ 0x1ee8b, 0x1ee9b,
+ 0x1eea1, 0x1eea3,
+ 0x1eea5, 0x1eea9,
+ 0x1eeab, 0x1eebb,
+}; /* CR_Other_Math */
+
+/* 'Hex_Digit': Binary Property */
+static const OnigCodePoint CR_Hex_Digit[] = {
+ 6,
+ 0x0030, 0x0039,
+ 0x0041, 0x0046,
+ 0x0061, 0x0066,
+ 0xff10, 0xff19,
+ 0xff21, 0xff26,
+ 0xff41, 0xff46,
+}; /* CR_Hex_Digit */
+
+/* 'ASCII_Hex_Digit': Binary Property */
+#define CR_ASCII_Hex_Digit CR_XDigit
+
+/* 'Other_Alphabetic': Binary Property */
+static const OnigCodePoint CR_Other_Alphabetic[] = {
+ 255,
+ 0x0345, 0x0345,
+ 0x0363, 0x036f,
+ 0x05b0, 0x05bd,
+ 0x05bf, 0x05bf,
+ 0x05c1, 0x05c2,
+ 0x05c4, 0x05c5,
+ 0x05c7, 0x05c7,
+ 0x0610, 0x061a,
+ 0x064b, 0x0657,
+ 0x0659, 0x065f,
+ 0x0670, 0x0670,
+ 0x06d6, 0x06dc,
+ 0x06e1, 0x06e4,
+ 0x06e7, 0x06e8,
+ 0x06ed, 0x06ed,
+ 0x0711, 0x0711,
+ 0x0730, 0x073f,
+ 0x07a6, 0x07b0,
+ 0x0816, 0x0817,
+ 0x081b, 0x0823,
+ 0x0825, 0x0827,
+ 0x0829, 0x082c,
+ 0x0897, 0x0897,
+ 0x08d4, 0x08df,
+ 0x08e3, 0x08e9,
+ 0x08f0, 0x0903,
+ 0x093a, 0x093b,
+ 0x093e, 0x094c,
+ 0x094e, 0x094f,
+ 0x0955, 0x0957,
+ 0x0962, 0x0963,
+ 0x0981, 0x0983,
+ 0x09be, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09cc,
+ 0x09d7, 0x09d7,
+ 0x09e2, 0x09e3,
+ 0x0a01, 0x0a03,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4c,
+ 0x0a51, 0x0a51,
+ 0x0a70, 0x0a71,
+ 0x0a75, 0x0a75,
+ 0x0a81, 0x0a83,
+ 0x0abe, 0x0ac5,
+ 0x0ac7, 0x0ac9,
+ 0x0acb, 0x0acc,
+ 0x0ae2, 0x0ae3,
+ 0x0afa, 0x0afc,
+ 0x0b01, 0x0b03,
+ 0x0b3e, 0x0b44,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4c,
+ 0x0b56, 0x0b57,
+ 0x0b62, 0x0b63,
+ 0x0b82, 0x0b82,
+ 0x0bbe, 0x0bc2,
+ 0x0bc6, 0x0bc8,
+ 0x0bca, 0x0bcc,
+ 0x0bd7, 0x0bd7,
+ 0x0c00, 0x0c04,
+ 0x0c3e, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4c,
+ 0x0c55, 0x0c56,
+ 0x0c62, 0x0c63,
+ 0x0c81, 0x0c83,
+ 0x0cbe, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccc,
+ 0x0cd5, 0x0cd6,
+ 0x0ce2, 0x0ce3,
+ 0x0cf3, 0x0cf3,
+ 0x0d00, 0x0d03,
+ 0x0d3e, 0x0d44,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4c,
+ 0x0d57, 0x0d57,
+ 0x0d62, 0x0d63,
+ 0x0d81, 0x0d83,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0df2, 0x0df3,
+ 0x0e31, 0x0e31,
+ 0x0e34, 0x0e3a,
+ 0x0e4d, 0x0e4d,
+ 0x0eb1, 0x0eb1,
+ 0x0eb4, 0x0eb9,
+ 0x0ebb, 0x0ebc,
+ 0x0ecd, 0x0ecd,
+ 0x0f71, 0x0f83,
+ 0x0f8d, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 0x102b, 0x1036,
+ 0x1038, 0x1038,
+ 0x103b, 0x103e,
+ 0x1056, 0x1059,
+ 0x105e, 0x1060,
+ 0x1062, 0x1064,
+ 0x1067, 0x106d,
+ 0x1071, 0x1074,
+ 0x1082, 0x108d,
+ 0x108f, 0x108f,
+ 0x109a, 0x109d,
+ 0x1712, 0x1713,
+ 0x1732, 0x1733,
+ 0x1752, 0x1753,
+ 0x1772, 0x1773,
+ 0x17b6, 0x17c8,
+ 0x1885, 0x1886,
+ 0x18a9, 0x18a9,
+ 0x1920, 0x192b,
+ 0x1930, 0x1938,
+ 0x1a17, 0x1a1b,
+ 0x1a55, 0x1a5e,
+ 0x1a61, 0x1a74,
+ 0x1abf, 0x1ac0,
+ 0x1acc, 0x1ace,
+ 0x1b00, 0x1b04,
+ 0x1b35, 0x1b43,
+ 0x1b80, 0x1b82,
+ 0x1ba1, 0x1ba9,
+ 0x1bac, 0x1bad,
+ 0x1be7, 0x1bf1,
+ 0x1c24, 0x1c36,
+ 0x1dd3, 0x1df4,
+ 0x24b6, 0x24e9,
+ 0x2de0, 0x2dff,
+ 0xa674, 0xa67b,
+ 0xa69e, 0xa69f,
+ 0xa802, 0xa802,
+ 0xa80b, 0xa80b,
+ 0xa823, 0xa827,
+ 0xa880, 0xa881,
+ 0xa8b4, 0xa8c3,
+ 0xa8c5, 0xa8c5,
+ 0xa8ff, 0xa8ff,
+ 0xa926, 0xa92a,
+ 0xa947, 0xa952,
+ 0xa980, 0xa983,
+ 0xa9b4, 0xa9bf,
+ 0xa9e5, 0xa9e5,
+ 0xaa29, 0xaa36,
+ 0xaa43, 0xaa43,
+ 0xaa4c, 0xaa4d,
+ 0xaa7b, 0xaa7d,
+ 0xaab0, 0xaab0,
+ 0xaab2, 0xaab4,
+ 0xaab7, 0xaab8,
+ 0xaabe, 0xaabe,
+ 0xaaeb, 0xaaef,
+ 0xaaf5, 0xaaf5,
+ 0xabe3, 0xabea,
+ 0xfb1e, 0xfb1e,
+ 0x10376, 0x1037a,
+ 0x10a01, 0x10a03,
+ 0x10a05, 0x10a06,
+ 0x10a0c, 0x10a0f,
+ 0x10d24, 0x10d27,
+ 0x10d69, 0x10d69,
+ 0x10eab, 0x10eac,
+ 0x10efa, 0x10efc,
+ 0x11000, 0x11002,
+ 0x11038, 0x11045,
+ 0x11073, 0x11074,
+ 0x11080, 0x11082,
+ 0x110b0, 0x110b8,
+ 0x110c2, 0x110c2,
+ 0x11100, 0x11102,
+ 0x11127, 0x11132,
+ 0x11145, 0x11146,
+ 0x11180, 0x11182,
+ 0x111b3, 0x111bf,
+ 0x111ce, 0x111cf,
+ 0x1122c, 0x11234,
+ 0x11237, 0x11237,
+ 0x1123e, 0x1123e,
+ 0x11241, 0x11241,
+ 0x112df, 0x112e8,
+ 0x11300, 0x11303,
+ 0x1133e, 0x11344,
+ 0x11347, 0x11348,
+ 0x1134b, 0x1134c,
+ 0x11357, 0x11357,
+ 0x11362, 0x11363,
+ 0x113b8, 0x113c0,
+ 0x113c2, 0x113c2,
+ 0x113c5, 0x113c5,
+ 0x113c7, 0x113ca,
+ 0x113cc, 0x113cd,
+ 0x11435, 0x11441,
+ 0x11443, 0x11445,
+ 0x114b0, 0x114c1,
+ 0x115af, 0x115b5,
+ 0x115b8, 0x115be,
+ 0x115dc, 0x115dd,
+ 0x11630, 0x1163e,
+ 0x11640, 0x11640,
+ 0x116ab, 0x116b5,
+ 0x1171d, 0x1172a,
+ 0x1182c, 0x11838,
+ 0x11930, 0x11935,
+ 0x11937, 0x11938,
+ 0x1193b, 0x1193c,
+ 0x11940, 0x11940,
+ 0x11942, 0x11942,
+ 0x119d1, 0x119d7,
+ 0x119da, 0x119df,
+ 0x119e4, 0x119e4,
+ 0x11a01, 0x11a0a,
+ 0x11a35, 0x11a39,
+ 0x11a3b, 0x11a3e,
+ 0x11a51, 0x11a5b,
+ 0x11a8a, 0x11a97,
+ 0x11b60, 0x11b67,
+ 0x11c2f, 0x11c36,
+ 0x11c38, 0x11c3e,
+ 0x11c92, 0x11ca7,
+ 0x11ca9, 0x11cb6,
+ 0x11d31, 0x11d36,
+ 0x11d3a, 0x11d3a,
+ 0x11d3c, 0x11d3d,
+ 0x11d3f, 0x11d41,
+ 0x11d43, 0x11d43,
+ 0x11d47, 0x11d47,
+ 0x11d8a, 0x11d8e,
+ 0x11d90, 0x11d91,
+ 0x11d93, 0x11d96,
+ 0x11ef3, 0x11ef6,
+ 0x11f00, 0x11f01,
+ 0x11f03, 0x11f03,
+ 0x11f34, 0x11f3a,
+ 0x11f3e, 0x11f40,
+ 0x1611e, 0x1612e,
+ 0x16f4f, 0x16f4f,
+ 0x16f51, 0x16f87,
+ 0x16f8f, 0x16f92,
+ 0x16ff0, 0x16ff1,
+ 0x1bc9e, 0x1bc9e,
+ 0x1e000, 0x1e006,
+ 0x1e008, 0x1e018,
+ 0x1e01b, 0x1e021,
+ 0x1e023, 0x1e024,
+ 0x1e026, 0x1e02a,
+ 0x1e08f, 0x1e08f,
+ 0x1e6e3, 0x1e6e3,
+ 0x1e6e6, 0x1e6e6,
+ 0x1e6ee, 0x1e6ef,
+ 0x1e6f5, 0x1e6f5,
+ 0x1e947, 0x1e947,
+ 0x1f130, 0x1f149,
+ 0x1f150, 0x1f169,
+ 0x1f170, 0x1f189,
+}; /* CR_Other_Alphabetic */
+
+/* 'Ideographic': Binary Property */
+static const OnigCodePoint CR_Ideographic[] = {
+ 21,
+ 0x3006, 0x3007,
+ 0x3021, 0x3029,
+ 0x3038, 0x303a,
+ 0x3400, 0x4dbf,
+ 0x4e00, 0x9fff,
+ 0xf900, 0xfa6d,
+ 0xfa70, 0xfad9,
+ 0x16fe4, 0x16fe4,
+ 0x16ff2, 0x16ff6,
+ 0x17000, 0x18cd5,
+ 0x18cff, 0x18d1e,
+ 0x18d80, 0x18df2,
+ 0x1b170, 0x1b2fb,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b81d,
+ 0x2b820, 0x2cead,
+ 0x2ceb0, 0x2ebe0,
+ 0x2ebf0, 0x2ee5d,
+ 0x2f800, 0x2fa1d,
+ 0x30000, 0x3134a,
+ 0x31350, 0x33479,
+}; /* CR_Ideographic */
+
+/* 'Diacritic': Binary Property */
+static const OnigCodePoint CR_Diacritic[] = {
+ 220,
+ 0x005e, 0x005e,
+ 0x0060, 0x0060,
+ 0x00a8, 0x00a8,
+ 0x00af, 0x00af,
+ 0x00b4, 0x00b4,
+ 0x00b7, 0x00b8,
+ 0x02b0, 0x034e,
+ 0x0350, 0x0357,
+ 0x035d, 0x0362,
+ 0x0374, 0x0375,
+ 0x037a, 0x037a,
+ 0x0384, 0x0385,
+ 0x0483, 0x0487,
+ 0x0559, 0x0559,
+ 0x0591, 0x05bd,
+ 0x05bf, 0x05bf,
+ 0x05c1, 0x05c2,
+ 0x05c4, 0x05c5,
+ 0x05c7, 0x05c7,
+ 0x064b, 0x0652,
+ 0x0657, 0x0658,
+ 0x06df, 0x06e0,
+ 0x06e5, 0x06e6,
+ 0x06ea, 0x06ec,
+ 0x0730, 0x074a,
+ 0x07a6, 0x07b0,
+ 0x07eb, 0x07f5,
+ 0x0818, 0x0819,
+ 0x0898, 0x089f,
+ 0x08c9, 0x08d2,
+ 0x08e3, 0x08fe,
+ 0x093c, 0x093c,
+ 0x094d, 0x094d,
+ 0x0951, 0x0954,
+ 0x0971, 0x0971,
+ 0x09bc, 0x09bc,
+ 0x09cd, 0x09cd,
+ 0x0a3c, 0x0a3c,
+ 0x0a4d, 0x0a4d,
+ 0x0abc, 0x0abc,
+ 0x0acd, 0x0acd,
+ 0x0afd, 0x0aff,
+ 0x0b3c, 0x0b3c,
+ 0x0b4d, 0x0b4d,
+ 0x0b55, 0x0b55,
+ 0x0bcd, 0x0bcd,
+ 0x0c3c, 0x0c3c,
+ 0x0c4d, 0x0c4d,
+ 0x0cbc, 0x0cbc,
+ 0x0ccd, 0x0ccd,
+ 0x0d3b, 0x0d3c,
+ 0x0d4d, 0x0d4d,
+ 0x0dca, 0x0dca,
+ 0x0e3a, 0x0e3a,
+ 0x0e47, 0x0e4c,
+ 0x0e4e, 0x0e4e,
+ 0x0eba, 0x0eba,
+ 0x0ec8, 0x0ecc,
+ 0x0f18, 0x0f19,
+ 0x0f35, 0x0f35,
+ 0x0f37, 0x0f37,
+ 0x0f39, 0x0f39,
+ 0x0f3e, 0x0f3f,
+ 0x0f82, 0x0f84,
+ 0x0f86, 0x0f87,
+ 0x0fc6, 0x0fc6,
+ 0x1037, 0x1037,
+ 0x1039, 0x103a,
+ 0x1063, 0x1064,
+ 0x1069, 0x106d,
+ 0x1087, 0x108d,
+ 0x108f, 0x108f,
+ 0x109a, 0x109b,
+ 0x135d, 0x135f,
+ 0x1714, 0x1715,
+ 0x1734, 0x1734,
+ 0x17c9, 0x17d3,
+ 0x17dd, 0x17dd,
+ 0x1939, 0x193b,
+ 0x1a60, 0x1a60,
+ 0x1a75, 0x1a7c,
+ 0x1a7f, 0x1a7f,
+ 0x1ab0, 0x1abe,
+ 0x1ac1, 0x1acb,
+ 0x1acf, 0x1add,
+ 0x1ae0, 0x1aeb,
+ 0x1b34, 0x1b34,
+ 0x1b44, 0x1b44,
+ 0x1b6b, 0x1b73,
+ 0x1baa, 0x1bab,
+ 0x1be6, 0x1be6,
+ 0x1bf2, 0x1bf3,
+ 0x1c36, 0x1c37,
+ 0x1c78, 0x1c7d,
+ 0x1cd0, 0x1ce8,
+ 0x1ced, 0x1ced,
+ 0x1cf4, 0x1cf4,
+ 0x1cf7, 0x1cf9,
+ 0x1d2c, 0x1d6a,
+ 0x1d9b, 0x1dbe,
+ 0x1dc4, 0x1dcf,
+ 0x1df5, 0x1dff,
+ 0x1fbd, 0x1fbd,
+ 0x1fbf, 0x1fc1,
+ 0x1fcd, 0x1fcf,
+ 0x1fdd, 0x1fdf,
+ 0x1fed, 0x1fef,
+ 0x1ffd, 0x1ffe,
+ 0x2cef, 0x2cf1,
+ 0x2e2f, 0x2e2f,
+ 0x302a, 0x302f,
+ 0x3099, 0x309c,
+ 0x30fc, 0x30fc,
+ 0xa66f, 0xa66f,
+ 0xa67c, 0xa67d,
+ 0xa67f, 0xa67f,
+ 0xa69c, 0xa69d,
+ 0xa6f0, 0xa6f1,
+ 0xa700, 0xa721,
+ 0xa788, 0xa78a,
+ 0xa7f1, 0xa7f1,
+ 0xa7f8, 0xa7f9,
+ 0xa806, 0xa806,
+ 0xa82c, 0xa82c,
+ 0xa8c4, 0xa8c4,
+ 0xa8e0, 0xa8f1,
+ 0xa92b, 0xa92e,
+ 0xa953, 0xa953,
+ 0xa9b3, 0xa9b3,
+ 0xa9c0, 0xa9c0,
+ 0xa9e5, 0xa9e5,
+ 0xaa7b, 0xaa7d,
+ 0xaabf, 0xaac2,
+ 0xaaf6, 0xaaf6,
+ 0xab5b, 0xab5f,
+ 0xab69, 0xab6b,
+ 0xabec, 0xabed,
+ 0xfb1e, 0xfb1e,
+ 0xfe20, 0xfe2f,
+ 0xff3e, 0xff3e,
+ 0xff40, 0xff40,
+ 0xff70, 0xff70,
+ 0xff9e, 0xff9f,
+ 0xffe3, 0xffe3,
+ 0x102e0, 0x102e0,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 0x10a38, 0x10a3a,
+ 0x10a3f, 0x10a3f,
+ 0x10ae5, 0x10ae6,
+ 0x10d22, 0x10d27,
+ 0x10d4e, 0x10d4e,
+ 0x10d69, 0x10d6d,
+ 0x10efa, 0x10efa,
+ 0x10efd, 0x10eff,
+ 0x10f46, 0x10f50,
+ 0x10f82, 0x10f85,
+ 0x11046, 0x11046,
+ 0x11070, 0x11070,
+ 0x110b9, 0x110ba,
+ 0x11133, 0x11134,
+ 0x11173, 0x11173,
+ 0x111c0, 0x111c0,
+ 0x111ca, 0x111cc,
+ 0x11235, 0x11236,
+ 0x112e9, 0x112ea,
+ 0x1133b, 0x1133c,
+ 0x1134d, 0x1134d,
+ 0x11366, 0x1136c,
+ 0x11370, 0x11374,
+ 0x113ce, 0x113d0,
+ 0x113d2, 0x113d3,
+ 0x113e1, 0x113e2,
+ 0x11442, 0x11442,
+ 0x11446, 0x11446,
+ 0x114c2, 0x114c3,
+ 0x115bf, 0x115c0,
+ 0x1163f, 0x1163f,
+ 0x116b6, 0x116b7,
+ 0x1172b, 0x1172b,
+ 0x11839, 0x1183a,
+ 0x1193d, 0x1193e,
+ 0x11943, 0x11943,
+ 0x119e0, 0x119e0,
+ 0x11a34, 0x11a34,
+ 0x11a47, 0x11a47,
+ 0x11a99, 0x11a99,
+ 0x11c3f, 0x11c3f,
+ 0x11d42, 0x11d42,
+ 0x11d44, 0x11d45,
+ 0x11d97, 0x11d97,
+ 0x11dd9, 0x11dd9,
+ 0x11f41, 0x11f42,
+ 0x11f5a, 0x11f5a,
+ 0x13447, 0x13455,
+ 0x1612f, 0x1612f,
+ 0x16af0, 0x16af4,
+ 0x16b30, 0x16b36,
+ 0x16d6b, 0x16d6c,
+ 0x16f8f, 0x16f9f,
+ 0x16ff0, 0x16ff1,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
+ 0x1d167, 0x1d169,
+ 0x1d16d, 0x1d172,
+ 0x1d17b, 0x1d182,
+ 0x1d185, 0x1d18b,
+ 0x1d1aa, 0x1d1ad,
+ 0x1e030, 0x1e06d,
+ 0x1e130, 0x1e136,
+ 0x1e2ae, 0x1e2ae,
+ 0x1e2ec, 0x1e2ef,
+ 0x1e5ee, 0x1e5ef,
+ 0x1e8d0, 0x1e8d6,
+ 0x1e944, 0x1e946,
+ 0x1e948, 0x1e94a,
+}; /* CR_Diacritic */
+
+/* 'Extender': Binary Property */
+static const OnigCodePoint CR_Extender[] = {
+ 43,
+ 0x00b7, 0x00b7,
+ 0x02d0, 0x02d1,
+ 0x0640, 0x0640,
+ 0x07fa, 0x07fa,
+ 0x0a71, 0x0a71,
+ 0x0afb, 0x0afb,
+ 0x0b55, 0x0b55,
+ 0x0e46, 0x0e46,
+ 0x0ec6, 0x0ec6,
+ 0x180a, 0x180a,
+ 0x1843, 0x1843,
+ 0x1aa7, 0x1aa7,
+ 0x1c36, 0x1c36,
+ 0x1c7b, 0x1c7b,
+ 0x3005, 0x3005,
+ 0x3031, 0x3035,
+ 0x309d, 0x309e,
+ 0x30fc, 0x30fe,
+ 0xa015, 0xa015,
+ 0xa60c, 0xa60c,
+ 0xa9cf, 0xa9cf,
+ 0xa9e6, 0xa9e6,
+ 0xaa70, 0xaa70,
+ 0xaadd, 0xaadd,
+ 0xaaf3, 0xaaf4,
+ 0xff70, 0xff70,
+ 0x10781, 0x10782,
+ 0x10d4e, 0x10d4e,
+ 0x10d6a, 0x10d6a,
+ 0x10d6f, 0x10d6f,
+ 0x11237, 0x11237,
+ 0x1135d, 0x1135d,
+ 0x113d2, 0x113d3,
+ 0x115c6, 0x115c8,
+ 0x11a98, 0x11a98,
+ 0x11dd9, 0x11dd9,
+ 0x16b42, 0x16b43,
+ 0x16fe0, 0x16fe1,
+ 0x16fe3, 0x16fe3,
+ 0x16ff2, 0x16ff3,
+ 0x1e13c, 0x1e13d,
+ 0x1e5ef, 0x1e5ef,
+ 0x1e944, 0x1e946,
+}; /* CR_Extender */
+
+/* 'Other_Lowercase': Binary Property */
+static const OnigCodePoint CR_Other_Lowercase[] = {
+ 28,
+ 0x00aa, 0x00aa,
+ 0x00ba, 0x00ba,
+ 0x02b0, 0x02b8,
+ 0x02c0, 0x02c1,
+ 0x02e0, 0x02e4,
+ 0x0345, 0x0345,
+ 0x037a, 0x037a,
+ 0x10fc, 0x10fc,
+ 0x1d2c, 0x1d6a,
+ 0x1d78, 0x1d78,
+ 0x1d9b, 0x1dbf,
+ 0x2071, 0x2071,
+ 0x207f, 0x207f,
+ 0x2090, 0x209c,
+ 0x2170, 0x217f,
+ 0x24d0, 0x24e9,
+ 0x2c7c, 0x2c7d,
+ 0xa69c, 0xa69d,
+ 0xa770, 0xa770,
+ 0xa7f1, 0xa7f4,
+ 0xa7f8, 0xa7f9,
+ 0xab5c, 0xab5f,
+ 0xab69, 0xab69,
+ 0x10780, 0x10780,
+ 0x10783, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 0x1e030, 0x1e06d,
+}; /* CR_Other_Lowercase */
+
+/* 'Other_Uppercase': Binary Property */
+static const OnigCodePoint CR_Other_Uppercase[] = {
+ 5,
+ 0x2160, 0x216f,
+ 0x24b6, 0x24cf,
+ 0x1f130, 0x1f149,
+ 0x1f150, 0x1f169,
+ 0x1f170, 0x1f189,
+}; /* CR_Other_Uppercase */
+
+/* 'Noncharacter_Code_Point': Binary Property */
+static const OnigCodePoint CR_Noncharacter_Code_Point[] = {
+ 18,
+ 0xfdd0, 0xfdef,
+ 0xfffe, 0xffff,
+ 0x1fffe, 0x1ffff,
+ 0x2fffe, 0x2ffff,
+ 0x3fffe, 0x3ffff,
+ 0x4fffe, 0x4ffff,
+ 0x5fffe, 0x5ffff,
+ 0x6fffe, 0x6ffff,
+ 0x7fffe, 0x7ffff,
+ 0x8fffe, 0x8ffff,
+ 0x9fffe, 0x9ffff,
+ 0xafffe, 0xaffff,
+ 0xbfffe, 0xbffff,
+ 0xcfffe, 0xcffff,
+ 0xdfffe, 0xdffff,
+ 0xefffe, 0xeffff,
+ 0xffffe, 0xfffff,
+ 0x10fffe, 0x10ffff,
+}; /* CR_Noncharacter_Code_Point */
+
+/* 'Other_Grapheme_Extend': Binary Property */
+static const OnigCodePoint CR_Other_Grapheme_Extend[] = {
+ 49,
+ 0x09be, 0x09be,
+ 0x09d7, 0x09d7,
+ 0x0b3e, 0x0b3e,
+ 0x0b57, 0x0b57,
+ 0x0bbe, 0x0bbe,
+ 0x0bd7, 0x0bd7,
+ 0x0cc0, 0x0cc0,
+ 0x0cc2, 0x0cc2,
+ 0x0cc7, 0x0cc8,
+ 0x0cca, 0x0ccb,
+ 0x0cd5, 0x0cd6,
+ 0x0d3e, 0x0d3e,
+ 0x0d57, 0x0d57,
+ 0x0dcf, 0x0dcf,
+ 0x0ddf, 0x0ddf,
+ 0x1715, 0x1715,
+ 0x1734, 0x1734,
+ 0x1b35, 0x1b35,
+ 0x1b3b, 0x1b3b,
+ 0x1b3d, 0x1b3d,
+ 0x1b43, 0x1b44,
+ 0x1baa, 0x1baa,
+ 0x1bf2, 0x1bf3,
+ 0x200c, 0x200c,
+ 0x302e, 0x302f,
+ 0xa953, 0xa953,
+ 0xa9c0, 0xa9c0,
+ 0xff9e, 0xff9f,
+ 0x111c0, 0x111c0,
+ 0x11235, 0x11235,
+ 0x1133e, 0x1133e,
+ 0x1134d, 0x1134d,
+ 0x11357, 0x11357,
+ 0x113b8, 0x113b8,
+ 0x113c2, 0x113c2,
+ 0x113c5, 0x113c5,
+ 0x113c7, 0x113c9,
+ 0x113cf, 0x113cf,
+ 0x114b0, 0x114b0,
+ 0x114bd, 0x114bd,
+ 0x115af, 0x115af,
+ 0x116b6, 0x116b6,
+ 0x11930, 0x11930,
+ 0x1193d, 0x1193d,
+ 0x11f41, 0x11f41,
+ 0x16ff0, 0x16ff1,
+ 0x1d165, 0x1d166,
+ 0x1d16d, 0x1d172,
+ 0xe0020, 0xe007f,
+}; /* CR_Other_Grapheme_Extend */
+
+/* 'IDS_Binary_Operator': Binary Property */
+static const OnigCodePoint CR_IDS_Binary_Operator[] = {
+ 3,
+ 0x2ff0, 0x2ff1,
+ 0x2ff4, 0x2ffd,
+ 0x31ef, 0x31ef,
+}; /* CR_IDS_Binary_Operator */
+
+/* 'IDS_Trinary_Operator': Binary Property */
+static const OnigCodePoint CR_IDS_Trinary_Operator[] = {
+ 1,
+ 0x2ff2, 0x2ff3,
+}; /* CR_IDS_Trinary_Operator */
+
+/* 'IDS_Unary_Operator': Binary Property */
+static const OnigCodePoint CR_IDS_Unary_Operator[] = {
+ 1,
+ 0x2ffe, 0x2fff,
+}; /* CR_IDS_Unary_Operator */
+
+/* 'Radical': Binary Property */
+static const OnigCodePoint CR_Radical[] = {
+ 3,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+}; /* CR_Radical */
+
+/* 'Unified_Ideograph': Binary Property */
+static const OnigCodePoint CR_Unified_Ideograph[] = {
+ 16,
+ 0x3400, 0x4dbf,
+ 0x4e00, 0x9fff,
+ 0xfa0e, 0xfa0f,
+ 0xfa11, 0xfa11,
+ 0xfa13, 0xfa14,
+ 0xfa1f, 0xfa1f,
+ 0xfa21, 0xfa21,
+ 0xfa23, 0xfa24,
+ 0xfa27, 0xfa29,
+ 0x20000, 0x2a6df,
+ 0x2a700, 0x2b81d,
+ 0x2b820, 0x2cead,
+ 0x2ceb0, 0x2ebe0,
+ 0x2ebf0, 0x2ee5d,
+ 0x30000, 0x3134a,
+ 0x31350, 0x33479,
+}; /* CR_Unified_Ideograph */
+
+/* 'Other_Default_Ignorable_Code_Point': Binary Property */
+static const OnigCodePoint CR_Other_Default_Ignorable_Code_Point[] = {
+ 11,
+ 0x034f, 0x034f,
+ 0x115f, 0x1160,
+ 0x17b4, 0x17b5,
+ 0x2065, 0x2065,
+ 0x3164, 0x3164,
+ 0xffa0, 0xffa0,
+ 0xfff0, 0xfff8,
+ 0xe0000, 0xe0000,
+ 0xe0002, 0xe001f,
+ 0xe0080, 0xe00ff,
+ 0xe01f0, 0xe0fff,
+}; /* CR_Other_Default_Ignorable_Code_Point */
+
+/* 'Deprecated': Binary Property */
+static const OnigCodePoint CR_Deprecated[] = {
+ 8,
+ 0x0149, 0x0149,
+ 0x0673, 0x0673,
+ 0x0f77, 0x0f77,
+ 0x0f79, 0x0f79,
+ 0x17a3, 0x17a4,
+ 0x206a, 0x206f,
+ 0x2329, 0x232a,
+ 0xe0001, 0xe0001,
+}; /* CR_Deprecated */
+
+/* 'Soft_Dotted': Binary Property */
+static const OnigCodePoint CR_Soft_Dotted[] = {
+ 34,
+ 0x0069, 0x006a,
+ 0x012f, 0x012f,
+ 0x0249, 0x0249,
+ 0x0268, 0x0268,
+ 0x029d, 0x029d,
+ 0x02b2, 0x02b2,
+ 0x03f3, 0x03f3,
+ 0x0456, 0x0456,
+ 0x0458, 0x0458,
+ 0x1d62, 0x1d62,
+ 0x1d96, 0x1d96,
+ 0x1da4, 0x1da4,
+ 0x1da8, 0x1da8,
+ 0x1e2d, 0x1e2d,
+ 0x1ecb, 0x1ecb,
+ 0x2071, 0x2071,
+ 0x2148, 0x2149,
+ 0x2c7c, 0x2c7c,
+ 0x1d422, 0x1d423,
+ 0x1d456, 0x1d457,
+ 0x1d48a, 0x1d48b,
+ 0x1d4be, 0x1d4bf,
+ 0x1d4f2, 0x1d4f3,
+ 0x1d526, 0x1d527,
+ 0x1d55a, 0x1d55b,
+ 0x1d58e, 0x1d58f,
+ 0x1d5c2, 0x1d5c3,
+ 0x1d5f6, 0x1d5f7,
+ 0x1d62a, 0x1d62b,
+ 0x1d65e, 0x1d65f,
+ 0x1d692, 0x1d693,
+ 0x1df1a, 0x1df1a,
+ 0x1e04c, 0x1e04d,
+ 0x1e068, 0x1e068,
+}; /* CR_Soft_Dotted */
+
+/* 'Logical_Order_Exception': Binary Property */
+static const OnigCodePoint CR_Logical_Order_Exception[] = {
+ 7,
+ 0x0e40, 0x0e44,
+ 0x0ec0, 0x0ec4,
+ 0x19b5, 0x19b7,
+ 0x19ba, 0x19ba,
+ 0xaab5, 0xaab6,
+ 0xaab9, 0xaab9,
+ 0xaabb, 0xaabc,
+}; /* CR_Logical_Order_Exception */
+
+/* 'Other_ID_Start': Binary Property */
+static const OnigCodePoint CR_Other_ID_Start[] = {
+ 4,
+ 0x1885, 0x1886,
+ 0x2118, 0x2118,
+ 0x212e, 0x212e,
+ 0x309b, 0x309c,
+}; /* CR_Other_ID_Start */
+
+/* 'Other_ID_Continue': Binary Property */
+static const OnigCodePoint CR_Other_ID_Continue[] = {
+ 7,
+ 0x00b7, 0x00b7,
+ 0x0387, 0x0387,
+ 0x1369, 0x1371,
+ 0x19da, 0x19da,
+ 0x200c, 0x200d,
+ 0x30fb, 0x30fb,
+ 0xff65, 0xff65,
+}; /* CR_Other_ID_Continue */
+
+/* 'ID_Compat_Math_Continue': Binary Property */
+static const OnigCodePoint CR_ID_Compat_Math_Continue[] = {
+ 18,
+ 0x00b2, 0x00b3,
+ 0x00b9, 0x00b9,
+ 0x2070, 0x2070,
+ 0x2074, 0x207e,
+ 0x2080, 0x208e,
+ 0x2202, 0x2202,
+ 0x2207, 0x2207,
+ 0x221e, 0x221e,
+ 0x1d6c1, 0x1d6c1,
+ 0x1d6db, 0x1d6db,
+ 0x1d6fb, 0x1d6fb,
+ 0x1d715, 0x1d715,
+ 0x1d735, 0x1d735,
+ 0x1d74f, 0x1d74f,
+ 0x1d76f, 0x1d76f,
+ 0x1d789, 0x1d789,
+ 0x1d7a9, 0x1d7a9,
+ 0x1d7c3, 0x1d7c3,
+}; /* CR_ID_Compat_Math_Continue */
+
+/* 'ID_Compat_Math_Start': Binary Property */
+static const OnigCodePoint CR_ID_Compat_Math_Start[] = {
+ 13,
+ 0x2202, 0x2202,
+ 0x2207, 0x2207,
+ 0x221e, 0x221e,
+ 0x1d6c1, 0x1d6c1,
+ 0x1d6db, 0x1d6db,
+ 0x1d6fb, 0x1d6fb,
+ 0x1d715, 0x1d715,
+ 0x1d735, 0x1d735,
+ 0x1d74f, 0x1d74f,
+ 0x1d76f, 0x1d76f,
+ 0x1d789, 0x1d789,
+ 0x1d7a9, 0x1d7a9,
+ 0x1d7c3, 0x1d7c3,
+}; /* CR_ID_Compat_Math_Start */
+
+/* 'Sentence_Terminal': Binary Property */
+static const OnigCodePoint CR_Sentence_Terminal[] = {
+ 88,
+ 0x0021, 0x0021,
+ 0x002e, 0x002e,
+ 0x003f, 0x003f,
+ 0x0589, 0x0589,
+ 0x061d, 0x061f,
+ 0x06d4, 0x06d4,
+ 0x0700, 0x0702,
+ 0x07f9, 0x07f9,
+ 0x0837, 0x0837,
+ 0x0839, 0x0839,
+ 0x083d, 0x083e,
+ 0x0964, 0x0965,
+ 0x104a, 0x104b,
+ 0x1362, 0x1362,
+ 0x1367, 0x1368,
+ 0x166e, 0x166e,
+ 0x1735, 0x1736,
+ 0x17d4, 0x17d5,
+ 0x1803, 0x1803,
+ 0x1809, 0x1809,
+ 0x1944, 0x1945,
+ 0x1aa8, 0x1aab,
+ 0x1b4e, 0x1b4f,
+ 0x1b5a, 0x1b5b,
+ 0x1b5e, 0x1b5f,
+ 0x1b7d, 0x1b7f,
+ 0x1c3b, 0x1c3c,
+ 0x1c7e, 0x1c7f,
+ 0x2024, 0x2024,
+ 0x203c, 0x203d,
+ 0x2047, 0x2049,
+ 0x2cf9, 0x2cfb,
+ 0x2e2e, 0x2e2e,
+ 0x2e3c, 0x2e3c,
+ 0x2e53, 0x2e54,
+ 0x3002, 0x3002,
+ 0xa4ff, 0xa4ff,
+ 0xa60e, 0xa60f,
+ 0xa6f3, 0xa6f3,
+ 0xa6f7, 0xa6f7,
+ 0xa876, 0xa877,
+ 0xa8ce, 0xa8cf,
+ 0xa92f, 0xa92f,
+ 0xa9c8, 0xa9c9,
+ 0xaa5d, 0xaa5f,
+ 0xaaf0, 0xaaf1,
+ 0xabeb, 0xabeb,
+ 0xfe12, 0xfe12,
+ 0xfe15, 0xfe16,
+ 0xfe52, 0xfe52,
+ 0xfe56, 0xfe57,
+ 0xff01, 0xff01,
+ 0xff0e, 0xff0e,
+ 0xff1f, 0xff1f,
+ 0xff61, 0xff61,
+ 0x10a56, 0x10a57,
+ 0x10f55, 0x10f59,
+ 0x10f86, 0x10f89,
+ 0x11047, 0x11048,
+ 0x110be, 0x110c1,
+ 0x11141, 0x11143,
+ 0x111c5, 0x111c6,
+ 0x111cd, 0x111cd,
+ 0x111de, 0x111df,
+ 0x11238, 0x11239,
+ 0x1123b, 0x1123c,
+ 0x112a9, 0x112a9,
+ 0x113d4, 0x113d5,
+ 0x1144b, 0x1144c,
+ 0x115c2, 0x115c3,
+ 0x115c9, 0x115d7,
+ 0x11641, 0x11642,
+ 0x1173c, 0x1173e,
+ 0x11944, 0x11944,
+ 0x11946, 0x11946,
+ 0x11a42, 0x11a43,
+ 0x11a9b, 0x11a9c,
+ 0x11c41, 0x11c42,
+ 0x11ef7, 0x11ef8,
+ 0x11f43, 0x11f44,
+ 0x16a6e, 0x16a6f,
+ 0x16af5, 0x16af5,
+ 0x16b37, 0x16b38,
+ 0x16b44, 0x16b44,
+ 0x16d6e, 0x16d6f,
+ 0x16e98, 0x16e98,
+ 0x1bc9f, 0x1bc9f,
+ 0x1da88, 0x1da88,
+}; /* CR_Sentence_Terminal */
+
+/* 'Variation_Selector': Binary Property */
+static const OnigCodePoint CR_Variation_Selector[] = {
+ 4,
+ 0x180b, 0x180d,
+ 0x180f, 0x180f,
+ 0xfe00, 0xfe0f,
+ 0xe0100, 0xe01ef,
+}; /* CR_Variation_Selector */
+
+/* 'Pattern_White_Space': Binary Property */
+static const OnigCodePoint CR_Pattern_White_Space[] = {
+ 5,
+ 0x0009, 0x000d,
+ 0x0020, 0x0020,
+ 0x0085, 0x0085,
+ 0x200e, 0x200f,
+ 0x2028, 0x2029,
+}; /* CR_Pattern_White_Space */
+
+/* 'Pattern_Syntax': Binary Property */
+static const OnigCodePoint CR_Pattern_Syntax[] = {
+ 28,
+ 0x0021, 0x002f,
+ 0x003a, 0x0040,
+ 0x005b, 0x005e,
+ 0x0060, 0x0060,
+ 0x007b, 0x007e,
+ 0x00a1, 0x00a7,
+ 0x00a9, 0x00a9,
+ 0x00ab, 0x00ac,
+ 0x00ae, 0x00ae,
+ 0x00b0, 0x00b1,
+ 0x00b6, 0x00b6,
+ 0x00bb, 0x00bb,
+ 0x00bf, 0x00bf,
+ 0x00d7, 0x00d7,
+ 0x00f7, 0x00f7,
+ 0x2010, 0x2027,
+ 0x2030, 0x203e,
+ 0x2041, 0x2053,
+ 0x2055, 0x205e,
+ 0x2190, 0x245f,
+ 0x2500, 0x2775,
+ 0x2794, 0x2bff,
+ 0x2e00, 0x2e7f,
+ 0x3001, 0x3003,
+ 0x3008, 0x3020,
+ 0x3030, 0x3030,
+ 0xfd3e, 0xfd3f,
+ 0xfe45, 0xfe46,
+}; /* CR_Pattern_Syntax */
+
+/* 'Prepended_Concatenation_Mark': Binary Property */
+static const OnigCodePoint CR_Prepended_Concatenation_Mark[] = {
+ 7,
+ 0x0600, 0x0605,
+ 0x06dd, 0x06dd,
+ 0x070f, 0x070f,
+ 0x0890, 0x0891,
+ 0x08e2, 0x08e2,
+ 0x110bd, 0x110bd,
+ 0x110cd, 0x110cd,
+}; /* CR_Prepended_Concatenation_Mark */
+
+/* 'Regional_Indicator': Binary Property */
+static const OnigCodePoint CR_Regional_Indicator[] = {
+ 1,
+ 0x1f1e6, 0x1f1ff,
+}; /* CR_Regional_Indicator */
+
+/* 'Modifier_Combining_Mark': Binary Property */
+static const OnigCodePoint CR_Modifier_Combining_Mark[] = {
+ 9,
+ 0x0654, 0x0655,
+ 0x0658, 0x0658,
+ 0x06dc, 0x06dc,
+ 0x06e3, 0x06e3,
+ 0x06e7, 0x06e8,
+ 0x08ca, 0x08cb,
+ 0x08cd, 0x08cf,
+ 0x08d3, 0x08d3,
+ 0x08f3, 0x08f3,
+}; /* CR_Modifier_Combining_Mark */
+
+/* 'Emoji': Emoji */
+static const OnigCodePoint CR_Emoji[] = {
+ 151,
+ 0x0023, 0x0023,
+ 0x002a, 0x002a,
+ 0x0030, 0x0039,
+ 0x00a9, 0x00a9,
+ 0x00ae, 0x00ae,
+ 0x203c, 0x203c,
+ 0x2049, 0x2049,
+ 0x2122, 0x2122,
+ 0x2139, 0x2139,
+ 0x2194, 0x2199,
+ 0x21a9, 0x21aa,
+ 0x231a, 0x231b,
+ 0x2328, 0x2328,
+ 0x23cf, 0x23cf,
+ 0x23e9, 0x23f3,
+ 0x23f8, 0x23fa,
+ 0x24c2, 0x24c2,
+ 0x25aa, 0x25ab,
+ 0x25b6, 0x25b6,
+ 0x25c0, 0x25c0,
+ 0x25fb, 0x25fe,
+ 0x2600, 0x2604,
+ 0x260e, 0x260e,
+ 0x2611, 0x2611,
+ 0x2614, 0x2615,
+ 0x2618, 0x2618,
+ 0x261d, 0x261d,
+ 0x2620, 0x2620,
+ 0x2622, 0x2623,
+ 0x2626, 0x2626,
+ 0x262a, 0x262a,
+ 0x262e, 0x262f,
+ 0x2638, 0x263a,
+ 0x2640, 0x2640,
+ 0x2642, 0x2642,
+ 0x2648, 0x2653,
+ 0x265f, 0x2660,
+ 0x2663, 0x2663,
+ 0x2665, 0x2666,
+ 0x2668, 0x2668,
+ 0x267b, 0x267b,
+ 0x267e, 0x267f,
+ 0x2692, 0x2697,
+ 0x2699, 0x2699,
+ 0x269b, 0x269c,
+ 0x26a0, 0x26a1,
+ 0x26a7, 0x26a7,
+ 0x26aa, 0x26ab,
+ 0x26b0, 0x26b1,
+ 0x26bd, 0x26be,
+ 0x26c4, 0x26c5,
+ 0x26c8, 0x26c8,
+ 0x26ce, 0x26cf,
+ 0x26d1, 0x26d1,
+ 0x26d3, 0x26d4,
+ 0x26e9, 0x26ea,
+ 0x26f0, 0x26f5,
+ 0x26f7, 0x26fa,
+ 0x26fd, 0x26fd,
+ 0x2702, 0x2702,
+ 0x2705, 0x2705,
+ 0x2708, 0x270d,
+ 0x270f, 0x270f,
+ 0x2712, 0x2712,
+ 0x2714, 0x2714,
+ 0x2716, 0x2716,
+ 0x271d, 0x271d,
+ 0x2721, 0x2721,
+ 0x2728, 0x2728,
+ 0x2733, 0x2734,
+ 0x2744, 0x2744,
+ 0x2747, 0x2747,
+ 0x274c, 0x274c,
+ 0x274e, 0x274e,
+ 0x2753, 0x2755,
+ 0x2757, 0x2757,
+ 0x2763, 0x2764,
+ 0x2795, 0x2797,
+ 0x27a1, 0x27a1,
+ 0x27b0, 0x27b0,
+ 0x27bf, 0x27bf,
+ 0x2934, 0x2935,
+ 0x2b05, 0x2b07,
+ 0x2b1b, 0x2b1c,
+ 0x2b50, 0x2b50,
+ 0x2b55, 0x2b55,
+ 0x3030, 0x3030,
+ 0x303d, 0x303d,
+ 0x3297, 0x3297,
+ 0x3299, 0x3299,
+ 0x1f004, 0x1f004,
+ 0x1f0cf, 0x1f0cf,
+ 0x1f170, 0x1f171,
+ 0x1f17e, 0x1f17f,
+ 0x1f18e, 0x1f18e,
+ 0x1f191, 0x1f19a,
+ 0x1f1e6, 0x1f1ff,
+ 0x1f201, 0x1f202,
+ 0x1f21a, 0x1f21a,
+ 0x1f22f, 0x1f22f,
+ 0x1f232, 0x1f23a,
+ 0x1f250, 0x1f251,
+ 0x1f300, 0x1f321,
+ 0x1f324, 0x1f393,
+ 0x1f396, 0x1f397,
+ 0x1f399, 0x1f39b,
+ 0x1f39e, 0x1f3f0,
+ 0x1f3f3, 0x1f3f5,
+ 0x1f3f7, 0x1f4fd,
+ 0x1f4ff, 0x1f53d,
+ 0x1f549, 0x1f54e,
+ 0x1f550, 0x1f567,
+ 0x1f56f, 0x1f570,
+ 0x1f573, 0x1f57a,
+ 0x1f587, 0x1f587,
+ 0x1f58a, 0x1f58d,
+ 0x1f590, 0x1f590,
+ 0x1f595, 0x1f596,
+ 0x1f5a4, 0x1f5a5,
+ 0x1f5a8, 0x1f5a8,
+ 0x1f5b1, 0x1f5b2,
+ 0x1f5bc, 0x1f5bc,
+ 0x1f5c2, 0x1f5c4,
+ 0x1f5d1, 0x1f5d3,
+ 0x1f5dc, 0x1f5de,
+ 0x1f5e1, 0x1f5e1,
+ 0x1f5e3, 0x1f5e3,
+ 0x1f5e8, 0x1f5e8,
+ 0x1f5ef, 0x1f5ef,
+ 0x1f5f3, 0x1f5f3,
+ 0x1f5fa, 0x1f64f,
+ 0x1f680, 0x1f6c5,
+ 0x1f6cb, 0x1f6d2,
+ 0x1f6d5, 0x1f6d8,
+ 0x1f6dc, 0x1f6e5,
+ 0x1f6e9, 0x1f6e9,
+ 0x1f6eb, 0x1f6ec,
+ 0x1f6f0, 0x1f6f0,
+ 0x1f6f3, 0x1f6fc,
+ 0x1f7e0, 0x1f7eb,
+ 0x1f7f0, 0x1f7f0,
+ 0x1f90c, 0x1f93a,
+ 0x1f93c, 0x1f945,
+ 0x1f947, 0x1f9ff,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa8a,
+ 0x1fa8e, 0x1fac6,
+ 0x1fac8, 0x1fac8,
+ 0x1facd, 0x1fadc,
+ 0x1fadf, 0x1faea,
+ 0x1faef, 0x1faf8,
+}; /* CR_Emoji */
+
+/* 'Emoji_Presentation': Emoji */
+static const OnigCodePoint CR_Emoji_Presentation[] = {
+ 81,
+ 0x231a, 0x231b,
+ 0x23e9, 0x23ec,
+ 0x23f0, 0x23f0,
+ 0x23f3, 0x23f3,
+ 0x25fd, 0x25fe,
+ 0x2614, 0x2615,
+ 0x2648, 0x2653,
+ 0x267f, 0x267f,
+ 0x2693, 0x2693,
+ 0x26a1, 0x26a1,
+ 0x26aa, 0x26ab,
+ 0x26bd, 0x26be,
+ 0x26c4, 0x26c5,
+ 0x26ce, 0x26ce,
+ 0x26d4, 0x26d4,
+ 0x26ea, 0x26ea,
+ 0x26f2, 0x26f3,
+ 0x26f5, 0x26f5,
+ 0x26fa, 0x26fa,
+ 0x26fd, 0x26fd,
+ 0x2705, 0x2705,
+ 0x270a, 0x270b,
+ 0x2728, 0x2728,
+ 0x274c, 0x274c,
+ 0x274e, 0x274e,
+ 0x2753, 0x2755,
+ 0x2757, 0x2757,
+ 0x2795, 0x2797,
+ 0x27b0, 0x27b0,
+ 0x27bf, 0x27bf,
+ 0x2b1b, 0x2b1c,
+ 0x2b50, 0x2b50,
+ 0x2b55, 0x2b55,
+ 0x1f004, 0x1f004,
+ 0x1f0cf, 0x1f0cf,
+ 0x1f18e, 0x1f18e,
+ 0x1f191, 0x1f19a,
+ 0x1f1e6, 0x1f1ff,
+ 0x1f201, 0x1f201,
+ 0x1f21a, 0x1f21a,
+ 0x1f22f, 0x1f22f,
+ 0x1f232, 0x1f236,
+ 0x1f238, 0x1f23a,
+ 0x1f250, 0x1f251,
+ 0x1f300, 0x1f320,
+ 0x1f32d, 0x1f335,
+ 0x1f337, 0x1f37c,
+ 0x1f37e, 0x1f393,
+ 0x1f3a0, 0x1f3ca,
+ 0x1f3cf, 0x1f3d3,
+ 0x1f3e0, 0x1f3f0,
+ 0x1f3f4, 0x1f3f4,
+ 0x1f3f8, 0x1f43e,
+ 0x1f440, 0x1f440,
+ 0x1f442, 0x1f4fc,
+ 0x1f4ff, 0x1f53d,
+ 0x1f54b, 0x1f54e,
+ 0x1f550, 0x1f567,
+ 0x1f57a, 0x1f57a,
+ 0x1f595, 0x1f596,
+ 0x1f5a4, 0x1f5a4,
+ 0x1f5fb, 0x1f64f,
+ 0x1f680, 0x1f6c5,
+ 0x1f6cc, 0x1f6cc,
+ 0x1f6d0, 0x1f6d2,
+ 0x1f6d5, 0x1f6d8,
+ 0x1f6dc, 0x1f6df,
+ 0x1f6eb, 0x1f6ec,
+ 0x1f6f4, 0x1f6fc,
+ 0x1f7e0, 0x1f7eb,
+ 0x1f7f0, 0x1f7f0,
+ 0x1f90c, 0x1f93a,
+ 0x1f93c, 0x1f945,
+ 0x1f947, 0x1f9ff,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa8a,
+ 0x1fa8e, 0x1fac6,
+ 0x1fac8, 0x1fac8,
+ 0x1facd, 0x1fadc,
+ 0x1fadf, 0x1faea,
+ 0x1faef, 0x1faf8,
+}; /* CR_Emoji_Presentation */
+
+/* 'Emoji_Modifier': Emoji */
+static const OnigCodePoint CR_Emoji_Modifier[] = {
+ 1,
+ 0x1f3fb, 0x1f3ff,
+}; /* CR_Emoji_Modifier */
+
+/* 'Emoji_Modifier_Base': Emoji */
+static const OnigCodePoint CR_Emoji_Modifier_Base[] = {
+ 40,
+ 0x261d, 0x261d,
+ 0x26f9, 0x26f9,
+ 0x270a, 0x270d,
+ 0x1f385, 0x1f385,
+ 0x1f3c2, 0x1f3c4,
+ 0x1f3c7, 0x1f3c7,
+ 0x1f3ca, 0x1f3cc,
+ 0x1f442, 0x1f443,
+ 0x1f446, 0x1f450,
+ 0x1f466, 0x1f478,
+ 0x1f47c, 0x1f47c,
+ 0x1f481, 0x1f483,
+ 0x1f485, 0x1f487,
+ 0x1f48f, 0x1f48f,
+ 0x1f491, 0x1f491,
+ 0x1f4aa, 0x1f4aa,
+ 0x1f574, 0x1f575,
+ 0x1f57a, 0x1f57a,
+ 0x1f590, 0x1f590,
+ 0x1f595, 0x1f596,
+ 0x1f645, 0x1f647,
+ 0x1f64b, 0x1f64f,
+ 0x1f6a3, 0x1f6a3,
+ 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,
+ 0x1f9cd, 0x1f9cf,
+ 0x1f9d1, 0x1f9dd,
+ 0x1fac3, 0x1fac5,
+ 0x1faf0, 0x1faf8,
+}; /* CR_Emoji_Modifier_Base */
+
+/* 'Emoji_Component': Emoji */
+static const OnigCodePoint CR_Emoji_Component[] = {
+ 10,
+ 0x0023, 0x0023,
+ 0x002a, 0x002a,
+ 0x0030, 0x0039,
+ 0x200d, 0x200d,
+ 0x20e3, 0x20e3,
+ 0xfe0f, 0xfe0f,
+ 0x1f1e6, 0x1f1ff,
+ 0x1f3fb, 0x1f3ff,
+ 0x1f9b0, 0x1f9b3,
+ 0xe0020, 0xe007f,
+}; /* CR_Emoji_Component */
+
+/* 'Extended_Pictographic': Emoji */
+static const OnigCodePoint CR_Extended_Pictographic[] = {
+ 156,
+ 0x00a9, 0x00a9,
+ 0x00ae, 0x00ae,
+ 0x203c, 0x203c,
+ 0x2049, 0x2049,
+ 0x2122, 0x2122,
+ 0x2139, 0x2139,
+ 0x2194, 0x2199,
+ 0x21a9, 0x21aa,
+ 0x231a, 0x231b,
+ 0x2328, 0x2328,
+ 0x23cf, 0x23cf,
+ 0x23e9, 0x23f3,
+ 0x23f8, 0x23fa,
+ 0x24c2, 0x24c2,
+ 0x25aa, 0x25ab,
+ 0x25b6, 0x25b6,
+ 0x25c0, 0x25c0,
+ 0x25fb, 0x25fe,
+ 0x2600, 0x2604,
+ 0x260e, 0x260e,
+ 0x2611, 0x2611,
+ 0x2614, 0x2615,
+ 0x2618, 0x2618,
+ 0x261d, 0x261d,
+ 0x2620, 0x2620,
+ 0x2622, 0x2623,
+ 0x2626, 0x2626,
+ 0x262a, 0x262a,
+ 0x262e, 0x262f,
+ 0x2638, 0x263a,
+ 0x2640, 0x2640,
+ 0x2642, 0x2642,
+ 0x2648, 0x2653,
+ 0x265f, 0x2660,
+ 0x2663, 0x2663,
+ 0x2665, 0x2666,
+ 0x2668, 0x2668,
+ 0x267b, 0x267b,
+ 0x267e, 0x267f,
+ 0x2692, 0x2697,
+ 0x2699, 0x2699,
+ 0x269b, 0x269c,
+ 0x26a0, 0x26a1,
+ 0x26a7, 0x26a7,
+ 0x26aa, 0x26ab,
+ 0x26b0, 0x26b1,
+ 0x26bd, 0x26be,
+ 0x26c4, 0x26c5,
+ 0x26c8, 0x26c8,
+ 0x26ce, 0x26cf,
+ 0x26d1, 0x26d1,
+ 0x26d3, 0x26d4,
+ 0x26e9, 0x26ea,
+ 0x26f0, 0x26f5,
+ 0x26f7, 0x26fa,
+ 0x26fd, 0x26fd,
+ 0x2702, 0x2702,
+ 0x2705, 0x2705,
+ 0x2708, 0x270d,
+ 0x270f, 0x270f,
+ 0x2712, 0x2712,
+ 0x2714, 0x2714,
+ 0x2716, 0x2716,
+ 0x271d, 0x271d,
+ 0x2721, 0x2721,
+ 0x2728, 0x2728,
+ 0x2733, 0x2734,
+ 0x2744, 0x2744,
+ 0x2747, 0x2747,
+ 0x274c, 0x274c,
+ 0x274e, 0x274e,
+ 0x2753, 0x2755,
+ 0x2757, 0x2757,
+ 0x2763, 0x2764,
+ 0x2795, 0x2797,
+ 0x27a1, 0x27a1,
+ 0x27b0, 0x27b0,
+ 0x27bf, 0x27bf,
+ 0x2934, 0x2935,
+ 0x2b05, 0x2b07,
+ 0x2b1b, 0x2b1c,
+ 0x2b50, 0x2b50,
+ 0x2b55, 0x2b55,
+ 0x3030, 0x3030,
+ 0x303d, 0x303d,
+ 0x3297, 0x3297,
+ 0x3299, 0x3299,
+ 0x1f004, 0x1f004,
+ 0x1f02c, 0x1f02f,
+ 0x1f094, 0x1f09f,
+ 0x1f0af, 0x1f0b0,
+ 0x1f0c0, 0x1f0c0,
+ 0x1f0cf, 0x1f0d0,
+ 0x1f0f6, 0x1f0ff,
+ 0x1f170, 0x1f171,
+ 0x1f17e, 0x1f17f,
+ 0x1f18e, 0x1f18e,
+ 0x1f191, 0x1f19a,
+ 0x1f1ae, 0x1f1e5,
+ 0x1f201, 0x1f20f,
+ 0x1f21a, 0x1f21a,
+ 0x1f22f, 0x1f22f,
+ 0x1f232, 0x1f23a,
+ 0x1f23c, 0x1f23f,
+ 0x1f249, 0x1f25f,
+ 0x1f266, 0x1f321,
+ 0x1f324, 0x1f393,
+ 0x1f396, 0x1f397,
+ 0x1f399, 0x1f39b,
+ 0x1f39e, 0x1f3f0,
+ 0x1f3f3, 0x1f3f5,
+ 0x1f3f7, 0x1f3fa,
+ 0x1f400, 0x1f4fd,
+ 0x1f4ff, 0x1f53d,
+ 0x1f549, 0x1f54e,
+ 0x1f550, 0x1f567,
+ 0x1f56f, 0x1f570,
+ 0x1f573, 0x1f57a,
+ 0x1f587, 0x1f587,
+ 0x1f58a, 0x1f58d,
+ 0x1f590, 0x1f590,
+ 0x1f595, 0x1f596,
+ 0x1f5a4, 0x1f5a5,
+ 0x1f5a8, 0x1f5a8,
+ 0x1f5b1, 0x1f5b2,
+ 0x1f5bc, 0x1f5bc,
+ 0x1f5c2, 0x1f5c4,
+ 0x1f5d1, 0x1f5d3,
+ 0x1f5dc, 0x1f5de,
+ 0x1f5e1, 0x1f5e1,
+ 0x1f5e3, 0x1f5e3,
+ 0x1f5e8, 0x1f5e8,
+ 0x1f5ef, 0x1f5ef,
+ 0x1f5f3, 0x1f5f3,
+ 0x1f5fa, 0x1f64f,
+ 0x1f680, 0x1f6c5,
+ 0x1f6cb, 0x1f6d2,
+ 0x1f6d5, 0x1f6e5,
+ 0x1f6e9, 0x1f6e9,
+ 0x1f6eb, 0x1f6f0,
+ 0x1f6f3, 0x1f6ff,
+ 0x1f7da, 0x1f7ff,
+ 0x1f80c, 0x1f80f,
+ 0x1f848, 0x1f84f,
+ 0x1f85a, 0x1f85f,
+ 0x1f888, 0x1f88f,
+ 0x1f8ae, 0x1f8af,
+ 0x1f8bc, 0x1f8bf,
+ 0x1f8c2, 0x1f8cf,
+ 0x1f8d9, 0x1f8ff,
+ 0x1f90c, 0x1f93a,
+ 0x1f93c, 0x1f945,
+ 0x1f947, 0x1f9ff,
+ 0x1fa58, 0x1fa5f,
+ 0x1fa6e, 0x1faff,
+ 0x1fc00, 0x1fffd,
+}; /* CR_Extended_Pictographic */
+
+/* 'Unknown': Script */
+static const OnigCodePoint CR_Unknown[] = {
+ 733,
+ 0x0378, 0x0379,
+ 0x0380, 0x0383,
+ 0x038b, 0x038b,
+ 0x038d, 0x038d,
+ 0x03a2, 0x03a2,
+ 0x0530, 0x0530,
+ 0x0557, 0x0558,
+ 0x058b, 0x058c,
+ 0x0590, 0x0590,
+ 0x05c8, 0x05cf,
+ 0x05eb, 0x05ee,
+ 0x05f5, 0x05ff,
+ 0x070e, 0x070e,
+ 0x074b, 0x074c,
+ 0x07b2, 0x07bf,
+ 0x07fb, 0x07fc,
+ 0x082e, 0x082f,
+ 0x083f, 0x083f,
+ 0x085c, 0x085d,
+ 0x085f, 0x085f,
+ 0x086b, 0x086f,
+ 0x0892, 0x0896,
+ 0x0984, 0x0984,
+ 0x098d, 0x098e,
+ 0x0991, 0x0992,
+ 0x09a9, 0x09a9,
+ 0x09b1, 0x09b1,
+ 0x09b3, 0x09b5,
+ 0x09ba, 0x09bb,
+ 0x09c5, 0x09c6,
+ 0x09c9, 0x09ca,
+ 0x09cf, 0x09d6,
+ 0x09d8, 0x09db,
+ 0x09de, 0x09de,
+ 0x09e4, 0x09e5,
+ 0x09ff, 0x0a00,
+ 0x0a04, 0x0a04,
+ 0x0a0b, 0x0a0e,
+ 0x0a11, 0x0a12,
+ 0x0a29, 0x0a29,
+ 0x0a31, 0x0a31,
+ 0x0a34, 0x0a34,
+ 0x0a37, 0x0a37,
+ 0x0a3a, 0x0a3b,
+ 0x0a3d, 0x0a3d,
+ 0x0a43, 0x0a46,
+ 0x0a49, 0x0a4a,
+ 0x0a4e, 0x0a50,
+ 0x0a52, 0x0a58,
+ 0x0a5d, 0x0a5d,
+ 0x0a5f, 0x0a65,
+ 0x0a77, 0x0a80,
+ 0x0a84, 0x0a84,
+ 0x0a8e, 0x0a8e,
+ 0x0a92, 0x0a92,
+ 0x0aa9, 0x0aa9,
+ 0x0ab1, 0x0ab1,
+ 0x0ab4, 0x0ab4,
+ 0x0aba, 0x0abb,
+ 0x0ac6, 0x0ac6,
+ 0x0aca, 0x0aca,
+ 0x0ace, 0x0acf,
+ 0x0ad1, 0x0adf,
+ 0x0ae4, 0x0ae5,
+ 0x0af2, 0x0af8,
+ 0x0b00, 0x0b00,
+ 0x0b04, 0x0b04,
+ 0x0b0d, 0x0b0e,
+ 0x0b11, 0x0b12,
+ 0x0b29, 0x0b29,
+ 0x0b31, 0x0b31,
+ 0x0b34, 0x0b34,
+ 0x0b3a, 0x0b3b,
+ 0x0b45, 0x0b46,
+ 0x0b49, 0x0b4a,
+ 0x0b4e, 0x0b54,
+ 0x0b58, 0x0b5b,
+ 0x0b5e, 0x0b5e,
+ 0x0b64, 0x0b65,
+ 0x0b78, 0x0b81,
+ 0x0b84, 0x0b84,
+ 0x0b8b, 0x0b8d,
+ 0x0b91, 0x0b91,
+ 0x0b96, 0x0b98,
+ 0x0b9b, 0x0b9b,
+ 0x0b9d, 0x0b9d,
+ 0x0ba0, 0x0ba2,
+ 0x0ba5, 0x0ba7,
+ 0x0bab, 0x0bad,
+ 0x0bba, 0x0bbd,
+ 0x0bc3, 0x0bc5,
+ 0x0bc9, 0x0bc9,
+ 0x0bce, 0x0bcf,
+ 0x0bd1, 0x0bd6,
+ 0x0bd8, 0x0be5,
+ 0x0bfb, 0x0bff,
+ 0x0c0d, 0x0c0d,
+ 0x0c11, 0x0c11,
+ 0x0c29, 0x0c29,
+ 0x0c3a, 0x0c3b,
+ 0x0c45, 0x0c45,
+ 0x0c49, 0x0c49,
+ 0x0c4e, 0x0c54,
+ 0x0c57, 0x0c57,
+ 0x0c5b, 0x0c5b,
+ 0x0c5e, 0x0c5f,
+ 0x0c64, 0x0c65,
+ 0x0c70, 0x0c76,
+ 0x0c8d, 0x0c8d,
+ 0x0c91, 0x0c91,
+ 0x0ca9, 0x0ca9,
+ 0x0cb4, 0x0cb4,
+ 0x0cba, 0x0cbb,
+ 0x0cc5, 0x0cc5,
+ 0x0cc9, 0x0cc9,
+ 0x0cce, 0x0cd4,
+ 0x0cd7, 0x0cdb,
+ 0x0cdf, 0x0cdf,
+ 0x0ce4, 0x0ce5,
+ 0x0cf0, 0x0cf0,
+ 0x0cf4, 0x0cff,
+ 0x0d0d, 0x0d0d,
+ 0x0d11, 0x0d11,
+ 0x0d45, 0x0d45,
+ 0x0d49, 0x0d49,
+ 0x0d50, 0x0d53,
+ 0x0d64, 0x0d65,
+ 0x0d80, 0x0d80,
+ 0x0d84, 0x0d84,
+ 0x0d97, 0x0d99,
+ 0x0db2, 0x0db2,
+ 0x0dbc, 0x0dbc,
+ 0x0dbe, 0x0dbf,
+ 0x0dc7, 0x0dc9,
+ 0x0dcb, 0x0dce,
+ 0x0dd5, 0x0dd5,
+ 0x0dd7, 0x0dd7,
+ 0x0de0, 0x0de5,
+ 0x0df0, 0x0df1,
+ 0x0df5, 0x0e00,
+ 0x0e3b, 0x0e3e,
+ 0x0e5c, 0x0e80,
+ 0x0e83, 0x0e83,
+ 0x0e85, 0x0e85,
+ 0x0e8b, 0x0e8b,
+ 0x0ea4, 0x0ea4,
+ 0x0ea6, 0x0ea6,
+ 0x0ebe, 0x0ebf,
+ 0x0ec5, 0x0ec5,
+ 0x0ec7, 0x0ec7,
+ 0x0ecf, 0x0ecf,
+ 0x0eda, 0x0edb,
+ 0x0ee0, 0x0eff,
+ 0x0f48, 0x0f48,
+ 0x0f6d, 0x0f70,
+ 0x0f98, 0x0f98,
+ 0x0fbd, 0x0fbd,
+ 0x0fcd, 0x0fcd,
+ 0x0fdb, 0x0fff,
+ 0x10c6, 0x10c6,
+ 0x10c8, 0x10cc,
+ 0x10ce, 0x10cf,
+ 0x1249, 0x1249,
+ 0x124e, 0x124f,
+ 0x1257, 0x1257,
+ 0x1259, 0x1259,
+ 0x125e, 0x125f,
+ 0x1289, 0x1289,
+ 0x128e, 0x128f,
+ 0x12b1, 0x12b1,
+ 0x12b6, 0x12b7,
+ 0x12bf, 0x12bf,
+ 0x12c1, 0x12c1,
+ 0x12c6, 0x12c7,
+ 0x12d7, 0x12d7,
+ 0x1311, 0x1311,
+ 0x1316, 0x1317,
+ 0x135b, 0x135c,
+ 0x137d, 0x137f,
+ 0x139a, 0x139f,
+ 0x13f6, 0x13f7,
+ 0x13fe, 0x13ff,
+ 0x169d, 0x169f,
+ 0x16f9, 0x16ff,
+ 0x1716, 0x171e,
+ 0x1737, 0x173f,
+ 0x1754, 0x175f,
+ 0x176d, 0x176d,
+ 0x1771, 0x1771,
+ 0x1774, 0x177f,
+ 0x17de, 0x17df,
+ 0x17ea, 0x17ef,
+ 0x17fa, 0x17ff,
+ 0x181a, 0x181f,
+ 0x1879, 0x187f,
+ 0x18ab, 0x18af,
+ 0x18f6, 0x18ff,
+ 0x191f, 0x191f,
+ 0x192c, 0x192f,
+ 0x193c, 0x193f,
+ 0x1941, 0x1943,
+ 0x196e, 0x196f,
+ 0x1975, 0x197f,
+ 0x19ac, 0x19af,
+ 0x19ca, 0x19cf,
+ 0x19db, 0x19dd,
+ 0x1a1c, 0x1a1d,
+ 0x1a5f, 0x1a5f,
+ 0x1a7d, 0x1a7e,
+ 0x1a8a, 0x1a8f,
+ 0x1a9a, 0x1a9f,
+ 0x1aae, 0x1aaf,
+ 0x1ade, 0x1adf,
+ 0x1aec, 0x1aff,
+ 0x1b4d, 0x1b4d,
+ 0x1bf4, 0x1bfb,
+ 0x1c38, 0x1c3a,
+ 0x1c4a, 0x1c4c,
+ 0x1c8b, 0x1c8f,
+ 0x1cbb, 0x1cbc,
+ 0x1cc8, 0x1ccf,
+ 0x1cfb, 0x1cff,
+ 0x1f16, 0x1f17,
+ 0x1f1e, 0x1f1f,
+ 0x1f46, 0x1f47,
+ 0x1f4e, 0x1f4f,
+ 0x1f58, 0x1f58,
+ 0x1f5a, 0x1f5a,
+ 0x1f5c, 0x1f5c,
+ 0x1f5e, 0x1f5e,
+ 0x1f7e, 0x1f7f,
+ 0x1fb5, 0x1fb5,
+ 0x1fc5, 0x1fc5,
+ 0x1fd4, 0x1fd5,
+ 0x1fdc, 0x1fdc,
+ 0x1ff0, 0x1ff1,
+ 0x1ff5, 0x1ff5,
+ 0x1fff, 0x1fff,
+ 0x2065, 0x2065,
+ 0x2072, 0x2073,
+ 0x208f, 0x208f,
+ 0x209d, 0x209f,
+ 0x20c2, 0x20cf,
+ 0x20f1, 0x20ff,
+ 0x218c, 0x218f,
+ 0x242a, 0x243f,
+ 0x244b, 0x245f,
+ 0x2b74, 0x2b75,
+ 0x2cf4, 0x2cf8,
+ 0x2d26, 0x2d26,
+ 0x2d28, 0x2d2c,
+ 0x2d2e, 0x2d2f,
+ 0x2d68, 0x2d6e,
+ 0x2d71, 0x2d7e,
+ 0x2d97, 0x2d9f,
+ 0x2da7, 0x2da7,
+ 0x2daf, 0x2daf,
+ 0x2db7, 0x2db7,
+ 0x2dbf, 0x2dbf,
+ 0x2dc7, 0x2dc7,
+ 0x2dcf, 0x2dcf,
+ 0x2dd7, 0x2dd7,
+ 0x2ddf, 0x2ddf,
+ 0x2e5e, 0x2e7f,
+ 0x2e9a, 0x2e9a,
+ 0x2ef4, 0x2eff,
+ 0x2fd6, 0x2fef,
+ 0x3040, 0x3040,
+ 0x3097, 0x3098,
+ 0x3100, 0x3104,
+ 0x3130, 0x3130,
+ 0x318f, 0x318f,
+ 0x31e6, 0x31ee,
+ 0x321f, 0x321f,
+ 0xa48d, 0xa48f,
+ 0xa4c7, 0xa4cf,
+ 0xa62c, 0xa63f,
+ 0xa6f8, 0xa6ff,
+ 0xa7dd, 0xa7f0,
+ 0xa82d, 0xa82f,
+ 0xa83a, 0xa83f,
+ 0xa878, 0xa87f,
+ 0xa8c6, 0xa8cd,
+ 0xa8da, 0xa8df,
+ 0xa954, 0xa95e,
+ 0xa97d, 0xa97f,
+ 0xa9ce, 0xa9ce,
+ 0xa9da, 0xa9dd,
+ 0xa9ff, 0xa9ff,
+ 0xaa37, 0xaa3f,
+ 0xaa4e, 0xaa4f,
+ 0xaa5a, 0xaa5b,
+ 0xaac3, 0xaada,
+ 0xaaf7, 0xab00,
+ 0xab07, 0xab08,
+ 0xab0f, 0xab10,
+ 0xab17, 0xab1f,
+ 0xab27, 0xab27,
+ 0xab2f, 0xab2f,
+ 0xab6c, 0xab6f,
+ 0xabee, 0xabef,
+ 0xabfa, 0xabff,
+ 0xd7a4, 0xd7af,
+ 0xd7c7, 0xd7ca,
+ 0xd7fc, 0xf8ff,
+ 0xfa6e, 0xfa6f,
+ 0xfada, 0xfaff,
+ 0xfb07, 0xfb12,
+ 0xfb18, 0xfb1c,
+ 0xfb37, 0xfb37,
+ 0xfb3d, 0xfb3d,
+ 0xfb3f, 0xfb3f,
+ 0xfb42, 0xfb42,
+ 0xfb45, 0xfb45,
+ 0xfdd0, 0xfdef,
+ 0xfe1a, 0xfe1f,
+ 0xfe53, 0xfe53,
+ 0xfe67, 0xfe67,
+ 0xfe6c, 0xfe6f,
+ 0xfe75, 0xfe75,
+ 0xfefd, 0xfefe,
+ 0xff00, 0xff00,
+ 0xffbf, 0xffc1,
+ 0xffc8, 0xffc9,
+ 0xffd0, 0xffd1,
+ 0xffd8, 0xffd9,
+ 0xffdd, 0xffdf,
+ 0xffe7, 0xffe7,
+ 0xffef, 0xfff8,
+ 0xfffe, 0xffff,
+ 0x1000c, 0x1000c,
+ 0x10027, 0x10027,
+ 0x1003b, 0x1003b,
+ 0x1003e, 0x1003e,
+ 0x1004e, 0x1004f,
+ 0x1005e, 0x1007f,
+ 0x100fb, 0x100ff,
+ 0x10103, 0x10106,
+ 0x10134, 0x10136,
+ 0x1018f, 0x1018f,
+ 0x1019d, 0x1019f,
+ 0x101a1, 0x101cf,
+ 0x101fe, 0x1027f,
+ 0x1029d, 0x1029f,
+ 0x102d1, 0x102df,
+ 0x102fc, 0x102ff,
+ 0x10324, 0x1032c,
+ 0x1034b, 0x1034f,
+ 0x1037b, 0x1037f,
+ 0x1039e, 0x1039e,
+ 0x103c4, 0x103c7,
+ 0x103d6, 0x103ff,
+ 0x1049e, 0x1049f,
+ 0x104aa, 0x104af,
+ 0x104d4, 0x104d7,
+ 0x104fc, 0x104ff,
+ 0x10528, 0x1052f,
+ 0x10564, 0x1056e,
+ 0x1057b, 0x1057b,
+ 0x1058b, 0x1058b,
+ 0x10593, 0x10593,
+ 0x10596, 0x10596,
+ 0x105a2, 0x105a2,
+ 0x105b2, 0x105b2,
+ 0x105ba, 0x105ba,
+ 0x105bd, 0x105bf,
+ 0x105f4, 0x105ff,
+ 0x10737, 0x1073f,
+ 0x10756, 0x1075f,
+ 0x10768, 0x1077f,
+ 0x10786, 0x10786,
+ 0x107b1, 0x107b1,
+ 0x107bb, 0x107ff,
+ 0x10806, 0x10807,
+ 0x10809, 0x10809,
+ 0x10836, 0x10836,
+ 0x10839, 0x1083b,
+ 0x1083d, 0x1083e,
+ 0x10856, 0x10856,
+ 0x1089f, 0x108a6,
+ 0x108b0, 0x108df,
+ 0x108f3, 0x108f3,
+ 0x108f6, 0x108fa,
+ 0x1091c, 0x1091e,
+ 0x1093a, 0x1093e,
+ 0x1095a, 0x1097f,
+ 0x109b8, 0x109bb,
+ 0x109d0, 0x109d1,
+ 0x10a04, 0x10a04,
+ 0x10a07, 0x10a0b,
+ 0x10a14, 0x10a14,
+ 0x10a18, 0x10a18,
+ 0x10a36, 0x10a37,
+ 0x10a3b, 0x10a3e,
+ 0x10a49, 0x10a4f,
+ 0x10a59, 0x10a5f,
+ 0x10aa0, 0x10abf,
+ 0x10ae7, 0x10aea,
+ 0x10af7, 0x10aff,
+ 0x10b36, 0x10b38,
+ 0x10b56, 0x10b57,
+ 0x10b73, 0x10b77,
+ 0x10b92, 0x10b98,
+ 0x10b9d, 0x10ba8,
+ 0x10bb0, 0x10bff,
+ 0x10c49, 0x10c7f,
+ 0x10cb3, 0x10cbf,
+ 0x10cf3, 0x10cf9,
+ 0x10d28, 0x10d2f,
+ 0x10d3a, 0x10d3f,
+ 0x10d66, 0x10d68,
+ 0x10d86, 0x10d8d,
+ 0x10d90, 0x10e5f,
+ 0x10e7f, 0x10e7f,
+ 0x10eaa, 0x10eaa,
+ 0x10eae, 0x10eaf,
+ 0x10eb2, 0x10ec1,
+ 0x10ec8, 0x10ecf,
+ 0x10ed9, 0x10ef9,
+ 0x10f28, 0x10f2f,
+ 0x10f5a, 0x10f6f,
+ 0x10f8a, 0x10faf,
+ 0x10fcc, 0x10fdf,
+ 0x10ff7, 0x10fff,
+ 0x1104e, 0x11051,
+ 0x11076, 0x1107e,
+ 0x110c3, 0x110cc,
+ 0x110ce, 0x110cf,
+ 0x110e9, 0x110ef,
+ 0x110fa, 0x110ff,
+ 0x11135, 0x11135,
+ 0x11148, 0x1114f,
+ 0x11177, 0x1117f,
+ 0x111e0, 0x111e0,
+ 0x111f5, 0x111ff,
+ 0x11212, 0x11212,
+ 0x11242, 0x1127f,
+ 0x11287, 0x11287,
+ 0x11289, 0x11289,
+ 0x1128e, 0x1128e,
+ 0x1129e, 0x1129e,
+ 0x112aa, 0x112af,
+ 0x112eb, 0x112ef,
+ 0x112fa, 0x112ff,
+ 0x11304, 0x11304,
+ 0x1130d, 0x1130e,
+ 0x11311, 0x11312,
+ 0x11329, 0x11329,
+ 0x11331, 0x11331,
+ 0x11334, 0x11334,
+ 0x1133a, 0x1133a,
+ 0x11345, 0x11346,
+ 0x11349, 0x1134a,
+ 0x1134e, 0x1134f,
+ 0x11351, 0x11356,
+ 0x11358, 0x1135c,
+ 0x11364, 0x11365,
+ 0x1136d, 0x1136f,
+ 0x11375, 0x1137f,
+ 0x1138a, 0x1138a,
+ 0x1138c, 0x1138d,
+ 0x1138f, 0x1138f,
+ 0x113b6, 0x113b6,
+ 0x113c1, 0x113c1,
+ 0x113c3, 0x113c4,
+ 0x113c6, 0x113c6,
+ 0x113cb, 0x113cb,
+ 0x113d6, 0x113d6,
+ 0x113d9, 0x113e0,
+ 0x113e3, 0x113ff,
+ 0x1145c, 0x1145c,
+ 0x11462, 0x1147f,
+ 0x114c8, 0x114cf,
+ 0x114da, 0x1157f,
+ 0x115b6, 0x115b7,
+ 0x115de, 0x115ff,
+ 0x11645, 0x1164f,
+ 0x1165a, 0x1165f,
+ 0x1166d, 0x1167f,
+ 0x116ba, 0x116bf,
+ 0x116ca, 0x116cf,
+ 0x116e4, 0x116ff,
+ 0x1171b, 0x1171c,
+ 0x1172c, 0x1172f,
+ 0x11747, 0x117ff,
+ 0x1183c, 0x1189f,
+ 0x118f3, 0x118fe,
+ 0x11907, 0x11908,
+ 0x1190a, 0x1190b,
+ 0x11914, 0x11914,
+ 0x11917, 0x11917,
+ 0x11936, 0x11936,
+ 0x11939, 0x1193a,
+ 0x11947, 0x1194f,
+ 0x1195a, 0x1199f,
+ 0x119a8, 0x119a9,
+ 0x119d8, 0x119d9,
+ 0x119e5, 0x119ff,
+ 0x11a48, 0x11a4f,
+ 0x11aa3, 0x11aaf,
+ 0x11af9, 0x11aff,
+ 0x11b0a, 0x11b5f,
+ 0x11b68, 0x11bbf,
+ 0x11be2, 0x11bef,
+ 0x11bfa, 0x11bff,
+ 0x11c09, 0x11c09,
+ 0x11c37, 0x11c37,
+ 0x11c46, 0x11c4f,
+ 0x11c6d, 0x11c6f,
+ 0x11c90, 0x11c91,
+ 0x11ca8, 0x11ca8,
+ 0x11cb7, 0x11cff,
+ 0x11d07, 0x11d07,
+ 0x11d0a, 0x11d0a,
+ 0x11d37, 0x11d39,
+ 0x11d3b, 0x11d3b,
+ 0x11d3e, 0x11d3e,
+ 0x11d48, 0x11d4f,
+ 0x11d5a, 0x11d5f,
+ 0x11d66, 0x11d66,
+ 0x11d69, 0x11d69,
+ 0x11d8f, 0x11d8f,
+ 0x11d92, 0x11d92,
+ 0x11d99, 0x11d9f,
+ 0x11daa, 0x11daf,
+ 0x11ddc, 0x11ddf,
+ 0x11dea, 0x11edf,
+ 0x11ef9, 0x11eff,
+ 0x11f11, 0x11f11,
+ 0x11f3b, 0x11f3d,
+ 0x11f5b, 0x11faf,
+ 0x11fb1, 0x11fbf,
+ 0x11ff2, 0x11ffe,
+ 0x1239a, 0x123ff,
+ 0x1246f, 0x1246f,
+ 0x12475, 0x1247f,
+ 0x12544, 0x12f8f,
+ 0x12ff3, 0x12fff,
+ 0x13456, 0x1345f,
+ 0x143fb, 0x143ff,
+ 0x14647, 0x160ff,
+ 0x1613a, 0x167ff,
+ 0x16a39, 0x16a3f,
+ 0x16a5f, 0x16a5f,
+ 0x16a6a, 0x16a6d,
+ 0x16abf, 0x16abf,
+ 0x16aca, 0x16acf,
+ 0x16aee, 0x16aef,
+ 0x16af6, 0x16aff,
+ 0x16b46, 0x16b4f,
+ 0x16b5a, 0x16b5a,
+ 0x16b62, 0x16b62,
+ 0x16b78, 0x16b7c,
+ 0x16b90, 0x16d3f,
+ 0x16d7a, 0x16e3f,
+ 0x16e9b, 0x16e9f,
+ 0x16eb9, 0x16eba,
+ 0x16ed4, 0x16eff,
+ 0x16f4b, 0x16f4e,
+ 0x16f88, 0x16f8e,
+ 0x16fa0, 0x16fdf,
+ 0x16fe5, 0x16fef,
+ 0x16ff7, 0x16fff,
+ 0x18cd6, 0x18cfe,
+ 0x18d1f, 0x18d7f,
+ 0x18df3, 0x1afef,
+ 0x1aff4, 0x1aff4,
+ 0x1affc, 0x1affc,
+ 0x1afff, 0x1afff,
+ 0x1b123, 0x1b131,
+ 0x1b133, 0x1b14f,
+ 0x1b153, 0x1b154,
+ 0x1b156, 0x1b163,
+ 0x1b168, 0x1b16f,
+ 0x1b2fc, 0x1bbff,
+ 0x1bc6b, 0x1bc6f,
+ 0x1bc7d, 0x1bc7f,
+ 0x1bc89, 0x1bc8f,
+ 0x1bc9a, 0x1bc9b,
+ 0x1bca4, 0x1cbff,
+ 0x1ccfd, 0x1ccff,
+ 0x1ceb4, 0x1ceb9,
+ 0x1ced1, 0x1cedf,
+ 0x1cef1, 0x1ceff,
+ 0x1cf2e, 0x1cf2f,
+ 0x1cf47, 0x1cf4f,
+ 0x1cfc4, 0x1cfff,
+ 0x1d0f6, 0x1d0ff,
+ 0x1d127, 0x1d128,
+ 0x1d1eb, 0x1d1ff,
+ 0x1d246, 0x1d2bf,
+ 0x1d2d4, 0x1d2df,
+ 0x1d2f4, 0x1d2ff,
+ 0x1d357, 0x1d35f,
+ 0x1d379, 0x1d3ff,
+ 0x1d455, 0x1d455,
+ 0x1d49d, 0x1d49d,
+ 0x1d4a0, 0x1d4a1,
+ 0x1d4a3, 0x1d4a4,
+ 0x1d4a7, 0x1d4a8,
+ 0x1d4ad, 0x1d4ad,
+ 0x1d4ba, 0x1d4ba,
+ 0x1d4bc, 0x1d4bc,
+ 0x1d4c4, 0x1d4c4,
+ 0x1d506, 0x1d506,
+ 0x1d50b, 0x1d50c,
+ 0x1d515, 0x1d515,
+ 0x1d51d, 0x1d51d,
+ 0x1d53a, 0x1d53a,
+ 0x1d53f, 0x1d53f,
+ 0x1d545, 0x1d545,
+ 0x1d547, 0x1d549,
+ 0x1d551, 0x1d551,
+ 0x1d6a6, 0x1d6a7,
+ 0x1d7cc, 0x1d7cd,
+ 0x1da8c, 0x1da9a,
+ 0x1daa0, 0x1daa0,
+ 0x1dab0, 0x1deff,
+ 0x1df1f, 0x1df24,
+ 0x1df2b, 0x1dfff,
+ 0x1e007, 0x1e007,
+ 0x1e019, 0x1e01a,
+ 0x1e022, 0x1e022,
+ 0x1e025, 0x1e025,
+ 0x1e02b, 0x1e02f,
+ 0x1e06e, 0x1e08e,
+ 0x1e090, 0x1e0ff,
+ 0x1e12d, 0x1e12f,
+ 0x1e13e, 0x1e13f,
+ 0x1e14a, 0x1e14d,
+ 0x1e150, 0x1e28f,
+ 0x1e2af, 0x1e2bf,
+ 0x1e2fa, 0x1e2fe,
+ 0x1e300, 0x1e4cf,
+ 0x1e4fa, 0x1e5cf,
+ 0x1e5fb, 0x1e5fe,
+ 0x1e600, 0x1e6bf,
+ 0x1e6df, 0x1e6df,
+ 0x1e6f6, 0x1e6fd,
+ 0x1e700, 0x1e7df,
+ 0x1e7e7, 0x1e7e7,
+ 0x1e7ec, 0x1e7ec,
+ 0x1e7ef, 0x1e7ef,
+ 0x1e7ff, 0x1e7ff,
+ 0x1e8c5, 0x1e8c6,
+ 0x1e8d7, 0x1e8ff,
+ 0x1e94c, 0x1e94f,
+ 0x1e95a, 0x1e95d,
+ 0x1e960, 0x1ec70,
+ 0x1ecb5, 0x1ed00,
+ 0x1ed3e, 0x1edff,
+ 0x1ee04, 0x1ee04,
+ 0x1ee20, 0x1ee20,
+ 0x1ee23, 0x1ee23,
+ 0x1ee25, 0x1ee26,
+ 0x1ee28, 0x1ee28,
+ 0x1ee33, 0x1ee33,
+ 0x1ee38, 0x1ee38,
+ 0x1ee3a, 0x1ee3a,
+ 0x1ee3c, 0x1ee41,
+ 0x1ee43, 0x1ee46,
+ 0x1ee48, 0x1ee48,
+ 0x1ee4a, 0x1ee4a,
+ 0x1ee4c, 0x1ee4c,
+ 0x1ee50, 0x1ee50,
+ 0x1ee53, 0x1ee53,
+ 0x1ee55, 0x1ee56,
+ 0x1ee58, 0x1ee58,
+ 0x1ee5a, 0x1ee5a,
+ 0x1ee5c, 0x1ee5c,
+ 0x1ee5e, 0x1ee5e,
+ 0x1ee60, 0x1ee60,
+ 0x1ee63, 0x1ee63,
+ 0x1ee65, 0x1ee66,
+ 0x1ee6b, 0x1ee6b,
+ 0x1ee73, 0x1ee73,
+ 0x1ee78, 0x1ee78,
+ 0x1ee7d, 0x1ee7d,
+ 0x1ee7f, 0x1ee7f,
+ 0x1ee8a, 0x1ee8a,
+ 0x1ee9c, 0x1eea0,
+ 0x1eea4, 0x1eea4,
+ 0x1eeaa, 0x1eeaa,
+ 0x1eebc, 0x1eeef,
+ 0x1eef2, 0x1efff,
+ 0x1f02c, 0x1f02f,
+ 0x1f094, 0x1f09f,
+ 0x1f0af, 0x1f0b0,
+ 0x1f0c0, 0x1f0c0,
+ 0x1f0d0, 0x1f0d0,
+ 0x1f0f6, 0x1f0ff,
+ 0x1f1ae, 0x1f1e5,
+ 0x1f203, 0x1f20f,
+ 0x1f23c, 0x1f23f,
+ 0x1f249, 0x1f24f,
+ 0x1f252, 0x1f25f,
+ 0x1f266, 0x1f2ff,
+ 0x1f6d9, 0x1f6db,
+ 0x1f6ed, 0x1f6ef,
+ 0x1f6fd, 0x1f6ff,
+ 0x1f7da, 0x1f7df,
+ 0x1f7ec, 0x1f7ef,
+ 0x1f7f1, 0x1f7ff,
+ 0x1f80c, 0x1f80f,
+ 0x1f848, 0x1f84f,
+ 0x1f85a, 0x1f85f,
+ 0x1f888, 0x1f88f,
+ 0x1f8ae, 0x1f8af,
+ 0x1f8bc, 0x1f8bf,
+ 0x1f8c2, 0x1f8cf,
+ 0x1f8d9, 0x1f8ff,
+ 0x1fa58, 0x1fa5f,
+ 0x1fa6e, 0x1fa6f,
+ 0x1fa7d, 0x1fa7f,
+ 0x1fa8b, 0x1fa8d,
+ 0x1fac7, 0x1fac7,
+ 0x1fac9, 0x1facc,
+ 0x1fadd, 0x1fade,
+ 0x1faeb, 0x1faee,
+ 0x1faf9, 0x1faff,
+ 0x1fb93, 0x1fb93,
+ 0x1fbfb, 0x1ffff,
+ 0x2a6e0, 0x2a6ff,
+ 0x2b81e, 0x2b81f,
+ 0x2ceae, 0x2ceaf,
+ 0x2ebe1, 0x2ebef,
+ 0x2ee5e, 0x2f7ff,
+ 0x2fa1e, 0x2ffff,
+ 0x3134b, 0x3134f,
+ 0x3347a, 0xe0000,
+ 0xe0002, 0xe001f,
+ 0xe0080, 0xe00ff,
+ 0xe01f0, 0x10ffff,
+}; /* CR_Unknown */
+
+#ifdef USE_UNICODE_AGE_PROPERTIES
+/* 'Age_1_1': Derived Age 1.1 */
+static const OnigCodePoint CR_Age_1_1[] = {
+ 288,
+ 0x0000, 0x01f5,
+ 0x01fa, 0x0217,
+ 0x0250, 0x02a8,
+ 0x02b0, 0x02de,
+ 0x02e0, 0x02e9,
+ 0x0300, 0x0345,
+ 0x0360, 0x0361,
+ 0x0374, 0x0375,
+ 0x037a, 0x037a,
+ 0x037e, 0x037e,
+ 0x0384, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x03ce,
+ 0x03d0, 0x03d6,
+ 0x03da, 0x03da,
+ 0x03dc, 0x03dc,
+ 0x03de, 0x03de,
+ 0x03e0, 0x03e0,
+ 0x03e2, 0x03f3,
+ 0x0401, 0x040c,
+ 0x040e, 0x044f,
+ 0x0451, 0x045c,
+ 0x045e, 0x0486,
+ 0x0490, 0x04c4,
+ 0x04c7, 0x04c8,
+ 0x04cb, 0x04cc,
+ 0x04d0, 0x04eb,
+ 0x04ee, 0x04f5,
+ 0x04f8, 0x04f9,
+ 0x0531, 0x0556,
+ 0x0559, 0x055f,
+ 0x0561, 0x0587,
+ 0x0589, 0x0589,
+ 0x05b0, 0x05b9,
+ 0x05bb, 0x05c3,
+ 0x05d0, 0x05ea,
+ 0x05f0, 0x05f4,
+ 0x060c, 0x060c,
+ 0x061b, 0x061b,
+ 0x061f, 0x061f,
+ 0x0621, 0x063a,
+ 0x0640, 0x0652,
+ 0x0660, 0x066d,
+ 0x0670, 0x06b7,
+ 0x06ba, 0x06be,
+ 0x06c0, 0x06ce,
+ 0x06d0, 0x06ed,
+ 0x06f0, 0x06f9,
+ 0x0901, 0x0903,
+ 0x0905, 0x0939,
+ 0x093c, 0x094d,
+ 0x0950, 0x0954,
+ 0x0958, 0x0970,
+ 0x0981, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09bc,
+ 0x09be, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09cd,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fa,
+ 0x0a02, 0x0a02,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a74,
+ 0x0a81, 0x0a83,
+ 0x0a85, 0x0a8b,
+ 0x0a8d, 0x0a8d,
+ 0x0a8f, 0x0a91,
+ 0x0a93, 0x0aa8,
+ 0x0aaa, 0x0ab0,
+ 0x0ab2, 0x0ab3,
+ 0x0ab5, 0x0ab9,
+ 0x0abc, 0x0ac5,
+ 0x0ac7, 0x0ac9,
+ 0x0acb, 0x0acd,
+ 0x0ad0, 0x0ad0,
+ 0x0ae0, 0x0ae0,
+ 0x0ae6, 0x0aef,
+ 0x0b01, 0x0b03,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b36, 0x0b39,
+ 0x0b3c, 0x0b43,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4d,
+ 0x0b56, 0x0b57,
+ 0x0b5c, 0x0b5d,
+ 0x0b5f, 0x0b61,
+ 0x0b66, 0x0b70,
+ 0x0b82, 0x0b83,
+ 0x0b85, 0x0b8a,
+ 0x0b8e, 0x0b90,
+ 0x0b92, 0x0b95,
+ 0x0b99, 0x0b9a,
+ 0x0b9c, 0x0b9c,
+ 0x0b9e, 0x0b9f,
+ 0x0ba3, 0x0ba4,
+ 0x0ba8, 0x0baa,
+ 0x0bae, 0x0bb5,
+ 0x0bb7, 0x0bb9,
+ 0x0bbe, 0x0bc2,
+ 0x0bc6, 0x0bc8,
+ 0x0bca, 0x0bcd,
+ 0x0bd7, 0x0bd7,
+ 0x0be7, 0x0bf2,
+ 0x0c01, 0x0c03,
+ 0x0c05, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c33,
+ 0x0c35, 0x0c39,
+ 0x0c3e, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c60, 0x0c61,
+ 0x0c66, 0x0c6f,
+ 0x0c82, 0x0c83,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbe, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cde, 0x0cde,
+ 0x0ce0, 0x0ce1,
+ 0x0ce6, 0x0cef,
+ 0x0d02, 0x0d03,
+ 0x0d05, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d28,
+ 0x0d2a, 0x0d39,
+ 0x0d3e, 0x0d43,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4d,
+ 0x0d57, 0x0d57,
+ 0x0d60, 0x0d61,
+ 0x0d66, 0x0d6f,
+ 0x0e01, 0x0e3a,
+ 0x0e3f, 0x0e5b,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e87, 0x0e88,
+ 0x0e8a, 0x0e8a,
+ 0x0e8d, 0x0e8d,
+ 0x0e94, 0x0e97,
+ 0x0e99, 0x0e9f,
+ 0x0ea1, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ea7,
+ 0x0eaa, 0x0eab,
+ 0x0ead, 0x0eb9,
+ 0x0ebb, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ecd,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edd,
+ 0x10a0, 0x10c5,
+ 0x10d0, 0x10f6,
+ 0x10fb, 0x10fb,
+ 0x1100, 0x1159,
+ 0x115f, 0x11a2,
+ 0x11a8, 0x11f9,
+ 0x1e00, 0x1e9a,
+ 0x1ea0, 0x1ef9,
+ 0x1f00, 0x1f15,
+ 0x1f18, 0x1f1d,
+ 0x1f20, 0x1f45,
+ 0x1f48, 0x1f4d,
+ 0x1f50, 0x1f57,
+ 0x1f59, 0x1f59,
+ 0x1f5b, 0x1f5b,
+ 0x1f5d, 0x1f5d,
+ 0x1f5f, 0x1f7d,
+ 0x1f80, 0x1fb4,
+ 0x1fb6, 0x1fc4,
+ 0x1fc6, 0x1fd3,
+ 0x1fd6, 0x1fdb,
+ 0x1fdd, 0x1fef,
+ 0x1ff2, 0x1ff4,
+ 0x1ff6, 0x1ffe,
+ 0x2000, 0x202e,
+ 0x2030, 0x2046,
+ 0x206a, 0x2070,
+ 0x2074, 0x208e,
+ 0x20a0, 0x20aa,
+ 0x20d0, 0x20e1,
+ 0x2100, 0x2138,
+ 0x2153, 0x2182,
+ 0x2190, 0x21ea,
+ 0x2200, 0x22f1,
+ 0x2300, 0x2300,
+ 0x2302, 0x237a,
+ 0x2400, 0x2424,
+ 0x2440, 0x244a,
+ 0x2460, 0x24ea,
+ 0x2500, 0x2595,
+ 0x25a0, 0x25ef,
+ 0x2600, 0x2613,
+ 0x261a, 0x266f,
+ 0x2701, 0x2704,
+ 0x2706, 0x2709,
+ 0x270c, 0x2727,
+ 0x2729, 0x274b,
+ 0x274d, 0x274d,
+ 0x274f, 0x2752,
+ 0x2756, 0x2756,
+ 0x2758, 0x275e,
+ 0x2761, 0x2767,
+ 0x2776, 0x2794,
+ 0x2798, 0x27af,
+ 0x27b1, 0x27be,
+ 0x3000, 0x3037,
+ 0x303f, 0x303f,
+ 0x3041, 0x3094,
+ 0x3099, 0x309e,
+ 0x30a1, 0x30fe,
+ 0x3105, 0x312c,
+ 0x3131, 0x318e,
+ 0x3190, 0x319f,
+ 0x3200, 0x321c,
+ 0x3220, 0x3243,
+ 0x3260, 0x327b,
+ 0x327f, 0x32b0,
+ 0x32c0, 0x32cb,
+ 0x32d0, 0x32fe,
+ 0x3300, 0x3376,
+ 0x337b, 0x33dd,
+ 0x33e0, 0x33fe,
+ 0x4e00, 0x9fa5,
+ 0xe000, 0xfa2d,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xfb1e, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfbb1,
+ 0xfbd3, 0xfd3f,
+ 0xfd50, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdf0, 0xfdfb,
+ 0xfe20, 0xfe23,
+ 0xfe30, 0xfe44,
+ 0xfe49, 0xfe52,
+ 0xfe54, 0xfe66,
+ 0xfe68, 0xfe6b,
+ 0xfe70, 0xfe72,
+ 0xfe74, 0xfe74,
+ 0xfe76, 0xfefc,
+ 0xfeff, 0xfeff,
+ 0xff01, 0xff5e,
+ 0xff61, 0xffbe,
+ 0xffc2, 0xffc7,
+ 0xffca, 0xffcf,
+ 0xffd2, 0xffd7,
+ 0xffda, 0xffdc,
+ 0xffe0, 0xffe6,
+ 0xffe8, 0xffee,
+ 0xfffd, 0xffff,
+}; /* CR_Age_1_1 */
+
+/* 'Age_2_0': Derived Age 2.0 */
+static const OnigCodePoint CR_Age_2_0[] = {
+ 312,
+ 0x0000, 0x01f5,
+ 0x01fa, 0x0217,
+ 0x0250, 0x02a8,
+ 0x02b0, 0x02de,
+ 0x02e0, 0x02e9,
+ 0x0300, 0x0345,
+ 0x0360, 0x0361,
+ 0x0374, 0x0375,
+ 0x037a, 0x037a,
+ 0x037e, 0x037e,
+ 0x0384, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x03ce,
+ 0x03d0, 0x03d6,
+ 0x03da, 0x03da,
+ 0x03dc, 0x03dc,
+ 0x03de, 0x03de,
+ 0x03e0, 0x03e0,
+ 0x03e2, 0x03f3,
+ 0x0401, 0x040c,
+ 0x040e, 0x044f,
+ 0x0451, 0x045c,
+ 0x045e, 0x0486,
+ 0x0490, 0x04c4,
+ 0x04c7, 0x04c8,
+ 0x04cb, 0x04cc,
+ 0x04d0, 0x04eb,
+ 0x04ee, 0x04f5,
+ 0x04f8, 0x04f9,
+ 0x0531, 0x0556,
+ 0x0559, 0x055f,
+ 0x0561, 0x0587,
+ 0x0589, 0x0589,
+ 0x0591, 0x05a1,
+ 0x05a3, 0x05b9,
+ 0x05bb, 0x05c4,
+ 0x05d0, 0x05ea,
+ 0x05f0, 0x05f4,
+ 0x060c, 0x060c,
+ 0x061b, 0x061b,
+ 0x061f, 0x061f,
+ 0x0621, 0x063a,
+ 0x0640, 0x0652,
+ 0x0660, 0x066d,
+ 0x0670, 0x06b7,
+ 0x06ba, 0x06be,
+ 0x06c0, 0x06ce,
+ 0x06d0, 0x06ed,
+ 0x06f0, 0x06f9,
+ 0x0901, 0x0903,
+ 0x0905, 0x0939,
+ 0x093c, 0x094d,
+ 0x0950, 0x0954,
+ 0x0958, 0x0970,
+ 0x0981, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09bc,
+ 0x09be, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09cd,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fa,
+ 0x0a02, 0x0a02,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a74,
+ 0x0a81, 0x0a83,
+ 0x0a85, 0x0a8b,
+ 0x0a8d, 0x0a8d,
+ 0x0a8f, 0x0a91,
+ 0x0a93, 0x0aa8,
+ 0x0aaa, 0x0ab0,
+ 0x0ab2, 0x0ab3,
+ 0x0ab5, 0x0ab9,
+ 0x0abc, 0x0ac5,
+ 0x0ac7, 0x0ac9,
+ 0x0acb, 0x0acd,
+ 0x0ad0, 0x0ad0,
+ 0x0ae0, 0x0ae0,
+ 0x0ae6, 0x0aef,
+ 0x0b01, 0x0b03,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b36, 0x0b39,
+ 0x0b3c, 0x0b43,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4d,
+ 0x0b56, 0x0b57,
+ 0x0b5c, 0x0b5d,
+ 0x0b5f, 0x0b61,
+ 0x0b66, 0x0b70,
+ 0x0b82, 0x0b83,
+ 0x0b85, 0x0b8a,
+ 0x0b8e, 0x0b90,
+ 0x0b92, 0x0b95,
+ 0x0b99, 0x0b9a,
+ 0x0b9c, 0x0b9c,
+ 0x0b9e, 0x0b9f,
+ 0x0ba3, 0x0ba4,
+ 0x0ba8, 0x0baa,
+ 0x0bae, 0x0bb5,
+ 0x0bb7, 0x0bb9,
+ 0x0bbe, 0x0bc2,
+ 0x0bc6, 0x0bc8,
+ 0x0bca, 0x0bcd,
+ 0x0bd7, 0x0bd7,
+ 0x0be7, 0x0bf2,
+ 0x0c01, 0x0c03,
+ 0x0c05, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c33,
+ 0x0c35, 0x0c39,
+ 0x0c3e, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c60, 0x0c61,
+ 0x0c66, 0x0c6f,
+ 0x0c82, 0x0c83,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbe, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cde, 0x0cde,
+ 0x0ce0, 0x0ce1,
+ 0x0ce6, 0x0cef,
+ 0x0d02, 0x0d03,
+ 0x0d05, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d28,
+ 0x0d2a, 0x0d39,
+ 0x0d3e, 0x0d43,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4d,
+ 0x0d57, 0x0d57,
+ 0x0d60, 0x0d61,
+ 0x0d66, 0x0d6f,
+ 0x0e01, 0x0e3a,
+ 0x0e3f, 0x0e5b,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e87, 0x0e88,
+ 0x0e8a, 0x0e8a,
+ 0x0e8d, 0x0e8d,
+ 0x0e94, 0x0e97,
+ 0x0e99, 0x0e9f,
+ 0x0ea1, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ea7,
+ 0x0eaa, 0x0eab,
+ 0x0ead, 0x0eb9,
+ 0x0ebb, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ecd,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edd,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f69,
+ 0x0f71, 0x0f8b,
+ 0x0f90, 0x0f95,
+ 0x0f97, 0x0f97,
+ 0x0f99, 0x0fad,
+ 0x0fb1, 0x0fb7,
+ 0x0fb9, 0x0fb9,
+ 0x10a0, 0x10c5,
+ 0x10d0, 0x10f6,
+ 0x10fb, 0x10fb,
+ 0x1100, 0x1159,
+ 0x115f, 0x11a2,
+ 0x11a8, 0x11f9,
+ 0x1e00, 0x1e9b,
+ 0x1ea0, 0x1ef9,
+ 0x1f00, 0x1f15,
+ 0x1f18, 0x1f1d,
+ 0x1f20, 0x1f45,
+ 0x1f48, 0x1f4d,
+ 0x1f50, 0x1f57,
+ 0x1f59, 0x1f59,
+ 0x1f5b, 0x1f5b,
+ 0x1f5d, 0x1f5d,
+ 0x1f5f, 0x1f7d,
+ 0x1f80, 0x1fb4,
+ 0x1fb6, 0x1fc4,
+ 0x1fc6, 0x1fd3,
+ 0x1fd6, 0x1fdb,
+ 0x1fdd, 0x1fef,
+ 0x1ff2, 0x1ff4,
+ 0x1ff6, 0x1ffe,
+ 0x2000, 0x202e,
+ 0x2030, 0x2046,
+ 0x206a, 0x2070,
+ 0x2074, 0x208e,
+ 0x20a0, 0x20ab,
+ 0x20d0, 0x20e1,
+ 0x2100, 0x2138,
+ 0x2153, 0x2182,
+ 0x2190, 0x21ea,
+ 0x2200, 0x22f1,
+ 0x2300, 0x2300,
+ 0x2302, 0x237a,
+ 0x2400, 0x2424,
+ 0x2440, 0x244a,
+ 0x2460, 0x24ea,
+ 0x2500, 0x2595,
+ 0x25a0, 0x25ef,
+ 0x2600, 0x2613,
+ 0x261a, 0x266f,
+ 0x2701, 0x2704,
+ 0x2706, 0x2709,
+ 0x270c, 0x2727,
+ 0x2729, 0x274b,
+ 0x274d, 0x274d,
+ 0x274f, 0x2752,
+ 0x2756, 0x2756,
+ 0x2758, 0x275e,
+ 0x2761, 0x2767,
+ 0x2776, 0x2794,
+ 0x2798, 0x27af,
+ 0x27b1, 0x27be,
+ 0x3000, 0x3037,
+ 0x303f, 0x303f,
+ 0x3041, 0x3094,
+ 0x3099, 0x309e,
+ 0x30a1, 0x30fe,
+ 0x3105, 0x312c,
+ 0x3131, 0x318e,
+ 0x3190, 0x319f,
+ 0x3200, 0x321c,
+ 0x3220, 0x3243,
+ 0x3260, 0x327b,
+ 0x327f, 0x32b0,
+ 0x32c0, 0x32cb,
+ 0x32d0, 0x32fe,
+ 0x3300, 0x3376,
+ 0x337b, 0x33dd,
+ 0x33e0, 0x33fe,
+ 0x4e00, 0x9fa5,
+ 0xac00, 0xd7a3,
+ 0xd800, 0xfa2d,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xfb1e, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfbb1,
+ 0xfbd3, 0xfd3f,
+ 0xfd50, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdf0, 0xfdfb,
+ 0xfe20, 0xfe23,
+ 0xfe30, 0xfe44,
+ 0xfe49, 0xfe52,
+ 0xfe54, 0xfe66,
+ 0xfe68, 0xfe6b,
+ 0xfe70, 0xfe72,
+ 0xfe74, 0xfe74,
+ 0xfe76, 0xfefc,
+ 0xfeff, 0xfeff,
+ 0xff01, 0xff5e,
+ 0xff61, 0xffbe,
+ 0xffc2, 0xffc7,
+ 0xffca, 0xffcf,
+ 0xffd2, 0xffd7,
+ 0xffda, 0xffdc,
+ 0xffe0, 0xffe6,
+ 0xffe8, 0xffee,
+ 0xfffd, 0xffff,
+ 0x1fffe, 0x1ffff,
+ 0x2fffe, 0x2ffff,
+ 0x3fffe, 0x3ffff,
+ 0x4fffe, 0x4ffff,
+ 0x5fffe, 0x5ffff,
+ 0x6fffe, 0x6ffff,
+ 0x7fffe, 0x7ffff,
+ 0x8fffe, 0x8ffff,
+ 0x9fffe, 0x9ffff,
+ 0xafffe, 0xaffff,
+ 0xbfffe, 0xbffff,
+ 0xcfffe, 0xcffff,
+ 0xdfffe, 0xdffff,
+ 0xefffe, 0x10ffff,
+}; /* CR_Age_2_0 */
+
+/* 'Age_2_1': Derived Age 2.1 */
+static const OnigCodePoint CR_Age_2_1[] = {
+ 312,
+ 0x0000, 0x01f5,
+ 0x01fa, 0x0217,
+ 0x0250, 0x02a8,
+ 0x02b0, 0x02de,
+ 0x02e0, 0x02e9,
+ 0x0300, 0x0345,
+ 0x0360, 0x0361,
+ 0x0374, 0x0375,
+ 0x037a, 0x037a,
+ 0x037e, 0x037e,
+ 0x0384, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x03ce,
+ 0x03d0, 0x03d6,
+ 0x03da, 0x03da,
+ 0x03dc, 0x03dc,
+ 0x03de, 0x03de,
+ 0x03e0, 0x03e0,
+ 0x03e2, 0x03f3,
+ 0x0401, 0x040c,
+ 0x040e, 0x044f,
+ 0x0451, 0x045c,
+ 0x045e, 0x0486,
+ 0x0490, 0x04c4,
+ 0x04c7, 0x04c8,
+ 0x04cb, 0x04cc,
+ 0x04d0, 0x04eb,
+ 0x04ee, 0x04f5,
+ 0x04f8, 0x04f9,
+ 0x0531, 0x0556,
+ 0x0559, 0x055f,
+ 0x0561, 0x0587,
+ 0x0589, 0x0589,
+ 0x0591, 0x05a1,
+ 0x05a3, 0x05b9,
+ 0x05bb, 0x05c4,
+ 0x05d0, 0x05ea,
+ 0x05f0, 0x05f4,
+ 0x060c, 0x060c,
+ 0x061b, 0x061b,
+ 0x061f, 0x061f,
+ 0x0621, 0x063a,
+ 0x0640, 0x0652,
+ 0x0660, 0x066d,
+ 0x0670, 0x06b7,
+ 0x06ba, 0x06be,
+ 0x06c0, 0x06ce,
+ 0x06d0, 0x06ed,
+ 0x06f0, 0x06f9,
+ 0x0901, 0x0903,
+ 0x0905, 0x0939,
+ 0x093c, 0x094d,
+ 0x0950, 0x0954,
+ 0x0958, 0x0970,
+ 0x0981, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09bc,
+ 0x09be, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09cd,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fa,
+ 0x0a02, 0x0a02,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a74,
+ 0x0a81, 0x0a83,
+ 0x0a85, 0x0a8b,
+ 0x0a8d, 0x0a8d,
+ 0x0a8f, 0x0a91,
+ 0x0a93, 0x0aa8,
+ 0x0aaa, 0x0ab0,
+ 0x0ab2, 0x0ab3,
+ 0x0ab5, 0x0ab9,
+ 0x0abc, 0x0ac5,
+ 0x0ac7, 0x0ac9,
+ 0x0acb, 0x0acd,
+ 0x0ad0, 0x0ad0,
+ 0x0ae0, 0x0ae0,
+ 0x0ae6, 0x0aef,
+ 0x0b01, 0x0b03,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b36, 0x0b39,
+ 0x0b3c, 0x0b43,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4d,
+ 0x0b56, 0x0b57,
+ 0x0b5c, 0x0b5d,
+ 0x0b5f, 0x0b61,
+ 0x0b66, 0x0b70,
+ 0x0b82, 0x0b83,
+ 0x0b85, 0x0b8a,
+ 0x0b8e, 0x0b90,
+ 0x0b92, 0x0b95,
+ 0x0b99, 0x0b9a,
+ 0x0b9c, 0x0b9c,
+ 0x0b9e, 0x0b9f,
+ 0x0ba3, 0x0ba4,
+ 0x0ba8, 0x0baa,
+ 0x0bae, 0x0bb5,
+ 0x0bb7, 0x0bb9,
+ 0x0bbe, 0x0bc2,
+ 0x0bc6, 0x0bc8,
+ 0x0bca, 0x0bcd,
+ 0x0bd7, 0x0bd7,
+ 0x0be7, 0x0bf2,
+ 0x0c01, 0x0c03,
+ 0x0c05, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c33,
+ 0x0c35, 0x0c39,
+ 0x0c3e, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c60, 0x0c61,
+ 0x0c66, 0x0c6f,
+ 0x0c82, 0x0c83,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbe, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cde, 0x0cde,
+ 0x0ce0, 0x0ce1,
+ 0x0ce6, 0x0cef,
+ 0x0d02, 0x0d03,
+ 0x0d05, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d28,
+ 0x0d2a, 0x0d39,
+ 0x0d3e, 0x0d43,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4d,
+ 0x0d57, 0x0d57,
+ 0x0d60, 0x0d61,
+ 0x0d66, 0x0d6f,
+ 0x0e01, 0x0e3a,
+ 0x0e3f, 0x0e5b,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e87, 0x0e88,
+ 0x0e8a, 0x0e8a,
+ 0x0e8d, 0x0e8d,
+ 0x0e94, 0x0e97,
+ 0x0e99, 0x0e9f,
+ 0x0ea1, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ea7,
+ 0x0eaa, 0x0eab,
+ 0x0ead, 0x0eb9,
+ 0x0ebb, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ecd,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edd,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f69,
+ 0x0f71, 0x0f8b,
+ 0x0f90, 0x0f95,
+ 0x0f97, 0x0f97,
+ 0x0f99, 0x0fad,
+ 0x0fb1, 0x0fb7,
+ 0x0fb9, 0x0fb9,
+ 0x10a0, 0x10c5,
+ 0x10d0, 0x10f6,
+ 0x10fb, 0x10fb,
+ 0x1100, 0x1159,
+ 0x115f, 0x11a2,
+ 0x11a8, 0x11f9,
+ 0x1e00, 0x1e9b,
+ 0x1ea0, 0x1ef9,
+ 0x1f00, 0x1f15,
+ 0x1f18, 0x1f1d,
+ 0x1f20, 0x1f45,
+ 0x1f48, 0x1f4d,
+ 0x1f50, 0x1f57,
+ 0x1f59, 0x1f59,
+ 0x1f5b, 0x1f5b,
+ 0x1f5d, 0x1f5d,
+ 0x1f5f, 0x1f7d,
+ 0x1f80, 0x1fb4,
+ 0x1fb6, 0x1fc4,
+ 0x1fc6, 0x1fd3,
+ 0x1fd6, 0x1fdb,
+ 0x1fdd, 0x1fef,
+ 0x1ff2, 0x1ff4,
+ 0x1ff6, 0x1ffe,
+ 0x2000, 0x202e,
+ 0x2030, 0x2046,
+ 0x206a, 0x2070,
+ 0x2074, 0x208e,
+ 0x20a0, 0x20ac,
+ 0x20d0, 0x20e1,
+ 0x2100, 0x2138,
+ 0x2153, 0x2182,
+ 0x2190, 0x21ea,
+ 0x2200, 0x22f1,
+ 0x2300, 0x2300,
+ 0x2302, 0x237a,
+ 0x2400, 0x2424,
+ 0x2440, 0x244a,
+ 0x2460, 0x24ea,
+ 0x2500, 0x2595,
+ 0x25a0, 0x25ef,
+ 0x2600, 0x2613,
+ 0x261a, 0x266f,
+ 0x2701, 0x2704,
+ 0x2706, 0x2709,
+ 0x270c, 0x2727,
+ 0x2729, 0x274b,
+ 0x274d, 0x274d,
+ 0x274f, 0x2752,
+ 0x2756, 0x2756,
+ 0x2758, 0x275e,
+ 0x2761, 0x2767,
+ 0x2776, 0x2794,
+ 0x2798, 0x27af,
+ 0x27b1, 0x27be,
+ 0x3000, 0x3037,
+ 0x303f, 0x303f,
+ 0x3041, 0x3094,
+ 0x3099, 0x309e,
+ 0x30a1, 0x30fe,
+ 0x3105, 0x312c,
+ 0x3131, 0x318e,
+ 0x3190, 0x319f,
+ 0x3200, 0x321c,
+ 0x3220, 0x3243,
+ 0x3260, 0x327b,
+ 0x327f, 0x32b0,
+ 0x32c0, 0x32cb,
+ 0x32d0, 0x32fe,
+ 0x3300, 0x3376,
+ 0x337b, 0x33dd,
+ 0x33e0, 0x33fe,
+ 0x4e00, 0x9fa5,
+ 0xac00, 0xd7a3,
+ 0xd800, 0xfa2d,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xfb1e, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfbb1,
+ 0xfbd3, 0xfd3f,
+ 0xfd50, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdf0, 0xfdfb,
+ 0xfe20, 0xfe23,
+ 0xfe30, 0xfe44,
+ 0xfe49, 0xfe52,
+ 0xfe54, 0xfe66,
+ 0xfe68, 0xfe6b,
+ 0xfe70, 0xfe72,
+ 0xfe74, 0xfe74,
+ 0xfe76, 0xfefc,
+ 0xfeff, 0xfeff,
+ 0xff01, 0xff5e,
+ 0xff61, 0xffbe,
+ 0xffc2, 0xffc7,
+ 0xffca, 0xffcf,
+ 0xffd2, 0xffd7,
+ 0xffda, 0xffdc,
+ 0xffe0, 0xffe6,
+ 0xffe8, 0xffee,
+ 0xfffc, 0xffff,
+ 0x1fffe, 0x1ffff,
+ 0x2fffe, 0x2ffff,
+ 0x3fffe, 0x3ffff,
+ 0x4fffe, 0x4ffff,
+ 0x5fffe, 0x5ffff,
+ 0x6fffe, 0x6ffff,
+ 0x7fffe, 0x7ffff,
+ 0x8fffe, 0x8ffff,
+ 0x9fffe, 0x9ffff,
+ 0xafffe, 0xaffff,
+ 0xbfffe, 0xbffff,
+ 0xcfffe, 0xcffff,
+ 0xdfffe, 0xdffff,
+ 0xefffe, 0x10ffff,
+}; /* CR_Age_2_1 */
+
+/* 'Age_3_0': Derived Age 3.0 */
+static const OnigCodePoint CR_Age_3_0[] = {
+ 369,
+ 0x0000, 0x021f,
+ 0x0222, 0x0233,
+ 0x0250, 0x02ad,
+ 0x02b0, 0x02ee,
+ 0x0300, 0x034e,
+ 0x0360, 0x0362,
+ 0x0374, 0x0375,
+ 0x037a, 0x037a,
+ 0x037e, 0x037e,
+ 0x0384, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x03ce,
+ 0x03d0, 0x03d7,
+ 0x03da, 0x03f3,
+ 0x0400, 0x0486,
+ 0x0488, 0x0489,
+ 0x048c, 0x04c4,
+ 0x04c7, 0x04c8,
+ 0x04cb, 0x04cc,
+ 0x04d0, 0x04f5,
+ 0x04f8, 0x04f9,
+ 0x0531, 0x0556,
+ 0x0559, 0x055f,
+ 0x0561, 0x0587,
+ 0x0589, 0x058a,
+ 0x0591, 0x05a1,
+ 0x05a3, 0x05b9,
+ 0x05bb, 0x05c4,
+ 0x05d0, 0x05ea,
+ 0x05f0, 0x05f4,
+ 0x060c, 0x060c,
+ 0x061b, 0x061b,
+ 0x061f, 0x061f,
+ 0x0621, 0x063a,
+ 0x0640, 0x0655,
+ 0x0660, 0x066d,
+ 0x0670, 0x06ed,
+ 0x06f0, 0x06fe,
+ 0x0700, 0x070d,
+ 0x070f, 0x072c,
+ 0x0730, 0x074a,
+ 0x0780, 0x07b0,
+ 0x0901, 0x0903,
+ 0x0905, 0x0939,
+ 0x093c, 0x094d,
+ 0x0950, 0x0954,
+ 0x0958, 0x0970,
+ 0x0981, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09bc,
+ 0x09be, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09cd,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fa,
+ 0x0a02, 0x0a02,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a74,
+ 0x0a81, 0x0a83,
+ 0x0a85, 0x0a8b,
+ 0x0a8d, 0x0a8d,
+ 0x0a8f, 0x0a91,
+ 0x0a93, 0x0aa8,
+ 0x0aaa, 0x0ab0,
+ 0x0ab2, 0x0ab3,
+ 0x0ab5, 0x0ab9,
+ 0x0abc, 0x0ac5,
+ 0x0ac7, 0x0ac9,
+ 0x0acb, 0x0acd,
+ 0x0ad0, 0x0ad0,
+ 0x0ae0, 0x0ae0,
+ 0x0ae6, 0x0aef,
+ 0x0b01, 0x0b03,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b36, 0x0b39,
+ 0x0b3c, 0x0b43,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4d,
+ 0x0b56, 0x0b57,
+ 0x0b5c, 0x0b5d,
+ 0x0b5f, 0x0b61,
+ 0x0b66, 0x0b70,
+ 0x0b82, 0x0b83,
+ 0x0b85, 0x0b8a,
+ 0x0b8e, 0x0b90,
+ 0x0b92, 0x0b95,
+ 0x0b99, 0x0b9a,
+ 0x0b9c, 0x0b9c,
+ 0x0b9e, 0x0b9f,
+ 0x0ba3, 0x0ba4,
+ 0x0ba8, 0x0baa,
+ 0x0bae, 0x0bb5,
+ 0x0bb7, 0x0bb9,
+ 0x0bbe, 0x0bc2,
+ 0x0bc6, 0x0bc8,
+ 0x0bca, 0x0bcd,
+ 0x0bd7, 0x0bd7,
+ 0x0be7, 0x0bf2,
+ 0x0c01, 0x0c03,
+ 0x0c05, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c33,
+ 0x0c35, 0x0c39,
+ 0x0c3e, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c60, 0x0c61,
+ 0x0c66, 0x0c6f,
+ 0x0c82, 0x0c83,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbe, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cde, 0x0cde,
+ 0x0ce0, 0x0ce1,
+ 0x0ce6, 0x0cef,
+ 0x0d02, 0x0d03,
+ 0x0d05, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d28,
+ 0x0d2a, 0x0d39,
+ 0x0d3e, 0x0d43,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4d,
+ 0x0d57, 0x0d57,
+ 0x0d60, 0x0d61,
+ 0x0d66, 0x0d6f,
+ 0x0d82, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0df2, 0x0df4,
+ 0x0e01, 0x0e3a,
+ 0x0e3f, 0x0e5b,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e87, 0x0e88,
+ 0x0e8a, 0x0e8a,
+ 0x0e8d, 0x0e8d,
+ 0x0e94, 0x0e97,
+ 0x0e99, 0x0e9f,
+ 0x0ea1, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ea7,
+ 0x0eaa, 0x0eab,
+ 0x0ead, 0x0eb9,
+ 0x0ebb, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ecd,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edd,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6a,
+ 0x0f71, 0x0f8b,
+ 0x0f90, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 0x0fbe, 0x0fcc,
+ 0x0fcf, 0x0fcf,
+ 0x1000, 0x1021,
+ 0x1023, 0x1027,
+ 0x1029, 0x102a,
+ 0x102c, 0x1032,
+ 0x1036, 0x1039,
+ 0x1040, 0x1059,
+ 0x10a0, 0x10c5,
+ 0x10d0, 0x10f6,
+ 0x10fb, 0x10fb,
+ 0x1100, 0x1159,
+ 0x115f, 0x11a2,
+ 0x11a8, 0x11f9,
+ 0x1200, 0x1206,
+ 0x1208, 0x1246,
+ 0x1248, 0x1248,
+ 0x124a, 0x124d,
+ 0x1250, 0x1256,
+ 0x1258, 0x1258,
+ 0x125a, 0x125d,
+ 0x1260, 0x1286,
+ 0x1288, 0x1288,
+ 0x128a, 0x128d,
+ 0x1290, 0x12ae,
+ 0x12b0, 0x12b0,
+ 0x12b2, 0x12b5,
+ 0x12b8, 0x12be,
+ 0x12c0, 0x12c0,
+ 0x12c2, 0x12c5,
+ 0x12c8, 0x12ce,
+ 0x12d0, 0x12d6,
+ 0x12d8, 0x12ee,
+ 0x12f0, 0x130e,
+ 0x1310, 0x1310,
+ 0x1312, 0x1315,
+ 0x1318, 0x131e,
+ 0x1320, 0x1346,
+ 0x1348, 0x135a,
+ 0x1361, 0x137c,
+ 0x13a0, 0x13f4,
+ 0x1401, 0x1676,
+ 0x1680, 0x169c,
+ 0x16a0, 0x16f0,
+ 0x1780, 0x17dc,
+ 0x17e0, 0x17e9,
+ 0x1800, 0x180e,
+ 0x1810, 0x1819,
+ 0x1820, 0x1877,
+ 0x1880, 0x18a9,
+ 0x1e00, 0x1e9b,
+ 0x1ea0, 0x1ef9,
+ 0x1f00, 0x1f15,
+ 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, 0x2046,
+ 0x2048, 0x204d,
+ 0x206a, 0x2070,
+ 0x2074, 0x208e,
+ 0x20a0, 0x20af,
+ 0x20d0, 0x20e3,
+ 0x2100, 0x213a,
+ 0x2153, 0x2183,
+ 0x2190, 0x21f3,
+ 0x2200, 0x22f1,
+ 0x2300, 0x237b,
+ 0x237d, 0x239a,
+ 0x2400, 0x2426,
+ 0x2440, 0x244a,
+ 0x2460, 0x24ea,
+ 0x2500, 0x2595,
+ 0x25a0, 0x25f7,
+ 0x2600, 0x2613,
+ 0x2619, 0x2671,
+ 0x2701, 0x2704,
+ 0x2706, 0x2709,
+ 0x270c, 0x2727,
+ 0x2729, 0x274b,
+ 0x274d, 0x274d,
+ 0x274f, 0x2752,
+ 0x2756, 0x2756,
+ 0x2758, 0x275e,
+ 0x2761, 0x2767,
+ 0x2776, 0x2794,
+ 0x2798, 0x27af,
+ 0x27b1, 0x27be,
+ 0x2800, 0x28ff,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2ffb,
+ 0x3000, 0x303a,
+ 0x303e, 0x303f,
+ 0x3041, 0x3094,
+ 0x3099, 0x309e,
+ 0x30a1, 0x30fe,
+ 0x3105, 0x312c,
+ 0x3131, 0x318e,
+ 0x3190, 0x31b7,
+ 0x3200, 0x321c,
+ 0x3220, 0x3243,
+ 0x3260, 0x327b,
+ 0x327f, 0x32b0,
+ 0x32c0, 0x32cb,
+ 0x32d0, 0x32fe,
+ 0x3300, 0x3376,
+ 0x337b, 0x33dd,
+ 0x33e0, 0x33fe,
+ 0x3400, 0x4db5,
+ 0x4e00, 0x9fa5,
+ 0xa000, 0xa48c,
+ 0xa490, 0xa4a1,
+ 0xa4a4, 0xa4b3,
+ 0xa4b5, 0xa4c0,
+ 0xa4c2, 0xa4c4,
+ 0xa4c6, 0xa4c6,
+ 0xac00, 0xd7a3,
+ 0xd800, 0xfa2d,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xfb1d, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfbb1,
+ 0xfbd3, 0xfd3f,
+ 0xfd50, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdf0, 0xfdfb,
+ 0xfe20, 0xfe23,
+ 0xfe30, 0xfe44,
+ 0xfe49, 0xfe52,
+ 0xfe54, 0xfe66,
+ 0xfe68, 0xfe6b,
+ 0xfe70, 0xfe72,
+ 0xfe74, 0xfe74,
+ 0xfe76, 0xfefc,
+ 0xfeff, 0xfeff,
+ 0xff01, 0xff5e,
+ 0xff61, 0xffbe,
+ 0xffc2, 0xffc7,
+ 0xffca, 0xffcf,
+ 0xffd2, 0xffd7,
+ 0xffda, 0xffdc,
+ 0xffe0, 0xffe6,
+ 0xffe8, 0xffee,
+ 0xfff9, 0xffff,
+ 0x1fffe, 0x1ffff,
+ 0x2fffe, 0x2ffff,
+ 0x3fffe, 0x3ffff,
+ 0x4fffe, 0x4ffff,
+ 0x5fffe, 0x5ffff,
+ 0x6fffe, 0x6ffff,
+ 0x7fffe, 0x7ffff,
+ 0x8fffe, 0x8ffff,
+ 0x9fffe, 0x9ffff,
+ 0xafffe, 0xaffff,
+ 0xbfffe, 0xbffff,
+ 0xcfffe, 0xcffff,
+ 0xdfffe, 0xdffff,
+ 0xefffe, 0x10ffff,
+}; /* CR_Age_3_0 */
+
+/* 'Age_3_1': Derived Age 3.1 */
+static const OnigCodePoint CR_Age_3_1[] = {
+ 402,
+ 0x0000, 0x021f,
+ 0x0222, 0x0233,
+ 0x0250, 0x02ad,
+ 0x02b0, 0x02ee,
+ 0x0300, 0x034e,
+ 0x0360, 0x0362,
+ 0x0374, 0x0375,
+ 0x037a, 0x037a,
+ 0x037e, 0x037e,
+ 0x0384, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x03ce,
+ 0x03d0, 0x03d7,
+ 0x03da, 0x03f5,
+ 0x0400, 0x0486,
+ 0x0488, 0x0489,
+ 0x048c, 0x04c4,
+ 0x04c7, 0x04c8,
+ 0x04cb, 0x04cc,
+ 0x04d0, 0x04f5,
+ 0x04f8, 0x04f9,
+ 0x0531, 0x0556,
+ 0x0559, 0x055f,
+ 0x0561, 0x0587,
+ 0x0589, 0x058a,
+ 0x0591, 0x05a1,
+ 0x05a3, 0x05b9,
+ 0x05bb, 0x05c4,
+ 0x05d0, 0x05ea,
+ 0x05f0, 0x05f4,
+ 0x060c, 0x060c,
+ 0x061b, 0x061b,
+ 0x061f, 0x061f,
+ 0x0621, 0x063a,
+ 0x0640, 0x0655,
+ 0x0660, 0x066d,
+ 0x0670, 0x06ed,
+ 0x06f0, 0x06fe,
+ 0x0700, 0x070d,
+ 0x070f, 0x072c,
+ 0x0730, 0x074a,
+ 0x0780, 0x07b0,
+ 0x0901, 0x0903,
+ 0x0905, 0x0939,
+ 0x093c, 0x094d,
+ 0x0950, 0x0954,
+ 0x0958, 0x0970,
+ 0x0981, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09bc,
+ 0x09be, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09cd,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fa,
+ 0x0a02, 0x0a02,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a74,
+ 0x0a81, 0x0a83,
+ 0x0a85, 0x0a8b,
+ 0x0a8d, 0x0a8d,
+ 0x0a8f, 0x0a91,
+ 0x0a93, 0x0aa8,
+ 0x0aaa, 0x0ab0,
+ 0x0ab2, 0x0ab3,
+ 0x0ab5, 0x0ab9,
+ 0x0abc, 0x0ac5,
+ 0x0ac7, 0x0ac9,
+ 0x0acb, 0x0acd,
+ 0x0ad0, 0x0ad0,
+ 0x0ae0, 0x0ae0,
+ 0x0ae6, 0x0aef,
+ 0x0b01, 0x0b03,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b36, 0x0b39,
+ 0x0b3c, 0x0b43,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4d,
+ 0x0b56, 0x0b57,
+ 0x0b5c, 0x0b5d,
+ 0x0b5f, 0x0b61,
+ 0x0b66, 0x0b70,
+ 0x0b82, 0x0b83,
+ 0x0b85, 0x0b8a,
+ 0x0b8e, 0x0b90,
+ 0x0b92, 0x0b95,
+ 0x0b99, 0x0b9a,
+ 0x0b9c, 0x0b9c,
+ 0x0b9e, 0x0b9f,
+ 0x0ba3, 0x0ba4,
+ 0x0ba8, 0x0baa,
+ 0x0bae, 0x0bb5,
+ 0x0bb7, 0x0bb9,
+ 0x0bbe, 0x0bc2,
+ 0x0bc6, 0x0bc8,
+ 0x0bca, 0x0bcd,
+ 0x0bd7, 0x0bd7,
+ 0x0be7, 0x0bf2,
+ 0x0c01, 0x0c03,
+ 0x0c05, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c33,
+ 0x0c35, 0x0c39,
+ 0x0c3e, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c60, 0x0c61,
+ 0x0c66, 0x0c6f,
+ 0x0c82, 0x0c83,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbe, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cde, 0x0cde,
+ 0x0ce0, 0x0ce1,
+ 0x0ce6, 0x0cef,
+ 0x0d02, 0x0d03,
+ 0x0d05, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d28,
+ 0x0d2a, 0x0d39,
+ 0x0d3e, 0x0d43,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4d,
+ 0x0d57, 0x0d57,
+ 0x0d60, 0x0d61,
+ 0x0d66, 0x0d6f,
+ 0x0d82, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0df2, 0x0df4,
+ 0x0e01, 0x0e3a,
+ 0x0e3f, 0x0e5b,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e87, 0x0e88,
+ 0x0e8a, 0x0e8a,
+ 0x0e8d, 0x0e8d,
+ 0x0e94, 0x0e97,
+ 0x0e99, 0x0e9f,
+ 0x0ea1, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ea7,
+ 0x0eaa, 0x0eab,
+ 0x0ead, 0x0eb9,
+ 0x0ebb, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ecd,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edd,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6a,
+ 0x0f71, 0x0f8b,
+ 0x0f90, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 0x0fbe, 0x0fcc,
+ 0x0fcf, 0x0fcf,
+ 0x1000, 0x1021,
+ 0x1023, 0x1027,
+ 0x1029, 0x102a,
+ 0x102c, 0x1032,
+ 0x1036, 0x1039,
+ 0x1040, 0x1059,
+ 0x10a0, 0x10c5,
+ 0x10d0, 0x10f6,
+ 0x10fb, 0x10fb,
+ 0x1100, 0x1159,
+ 0x115f, 0x11a2,
+ 0x11a8, 0x11f9,
+ 0x1200, 0x1206,
+ 0x1208, 0x1246,
+ 0x1248, 0x1248,
+ 0x124a, 0x124d,
+ 0x1250, 0x1256,
+ 0x1258, 0x1258,
+ 0x125a, 0x125d,
+ 0x1260, 0x1286,
+ 0x1288, 0x1288,
+ 0x128a, 0x128d,
+ 0x1290, 0x12ae,
+ 0x12b0, 0x12b0,
+ 0x12b2, 0x12b5,
+ 0x12b8, 0x12be,
+ 0x12c0, 0x12c0,
+ 0x12c2, 0x12c5,
+ 0x12c8, 0x12ce,
+ 0x12d0, 0x12d6,
+ 0x12d8, 0x12ee,
+ 0x12f0, 0x130e,
+ 0x1310, 0x1310,
+ 0x1312, 0x1315,
+ 0x1318, 0x131e,
+ 0x1320, 0x1346,
+ 0x1348, 0x135a,
+ 0x1361, 0x137c,
+ 0x13a0, 0x13f4,
+ 0x1401, 0x1676,
+ 0x1680, 0x169c,
+ 0x16a0, 0x16f0,
+ 0x1780, 0x17dc,
+ 0x17e0, 0x17e9,
+ 0x1800, 0x180e,
+ 0x1810, 0x1819,
+ 0x1820, 0x1877,
+ 0x1880, 0x18a9,
+ 0x1e00, 0x1e9b,
+ 0x1ea0, 0x1ef9,
+ 0x1f00, 0x1f15,
+ 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, 0x2046,
+ 0x2048, 0x204d,
+ 0x206a, 0x2070,
+ 0x2074, 0x208e,
+ 0x20a0, 0x20af,
+ 0x20d0, 0x20e3,
+ 0x2100, 0x213a,
+ 0x2153, 0x2183,
+ 0x2190, 0x21f3,
+ 0x2200, 0x22f1,
+ 0x2300, 0x237b,
+ 0x237d, 0x239a,
+ 0x2400, 0x2426,
+ 0x2440, 0x244a,
+ 0x2460, 0x24ea,
+ 0x2500, 0x2595,
+ 0x25a0, 0x25f7,
+ 0x2600, 0x2613,
+ 0x2619, 0x2671,
+ 0x2701, 0x2704,
+ 0x2706, 0x2709,
+ 0x270c, 0x2727,
+ 0x2729, 0x274b,
+ 0x274d, 0x274d,
+ 0x274f, 0x2752,
+ 0x2756, 0x2756,
+ 0x2758, 0x275e,
+ 0x2761, 0x2767,
+ 0x2776, 0x2794,
+ 0x2798, 0x27af,
+ 0x27b1, 0x27be,
+ 0x2800, 0x28ff,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2ffb,
+ 0x3000, 0x303a,
+ 0x303e, 0x303f,
+ 0x3041, 0x3094,
+ 0x3099, 0x309e,
+ 0x30a1, 0x30fe,
+ 0x3105, 0x312c,
+ 0x3131, 0x318e,
+ 0x3190, 0x31b7,
+ 0x3200, 0x321c,
+ 0x3220, 0x3243,
+ 0x3260, 0x327b,
+ 0x327f, 0x32b0,
+ 0x32c0, 0x32cb,
+ 0x32d0, 0x32fe,
+ 0x3300, 0x3376,
+ 0x337b, 0x33dd,
+ 0x33e0, 0x33fe,
+ 0x3400, 0x4db5,
+ 0x4e00, 0x9fa5,
+ 0xa000, 0xa48c,
+ 0xa490, 0xa4a1,
+ 0xa4a4, 0xa4b3,
+ 0xa4b5, 0xa4c0,
+ 0xa4c2, 0xa4c4,
+ 0xa4c6, 0xa4c6,
+ 0xac00, 0xd7a3,
+ 0xd800, 0xfa2d,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xfb1d, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfbb1,
+ 0xfbd3, 0xfd3f,
+ 0xfd50, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdd0, 0xfdfb,
+ 0xfe20, 0xfe23,
+ 0xfe30, 0xfe44,
+ 0xfe49, 0xfe52,
+ 0xfe54, 0xfe66,
+ 0xfe68, 0xfe6b,
+ 0xfe70, 0xfe72,
+ 0xfe74, 0xfe74,
+ 0xfe76, 0xfefc,
+ 0xfeff, 0xfeff,
+ 0xff01, 0xff5e,
+ 0xff61, 0xffbe,
+ 0xffc2, 0xffc7,
+ 0xffca, 0xffcf,
+ 0xffd2, 0xffd7,
+ 0xffda, 0xffdc,
+ 0xffe0, 0xffe6,
+ 0xffe8, 0xffee,
+ 0xfff9, 0xffff,
+ 0x10300, 0x1031e,
+ 0x10320, 0x10323,
+ 0x10330, 0x1034a,
+ 0x10400, 0x10425,
+ 0x10428, 0x1044d,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d12a, 0x1d1dd,
+ 0x1d400, 0x1d454,
+ 0x1d456, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 0x1d4a2, 0x1d4a2,
+ 0x1d4a5, 0x1d4a6,
+ 0x1d4a9, 0x1d4ac,
+ 0x1d4ae, 0x1d4b9,
+ 0x1d4bb, 0x1d4bb,
+ 0x1d4bd, 0x1d4c0,
+ 0x1d4c2, 0x1d4c3,
+ 0x1d4c5, 0x1d505,
+ 0x1d507, 0x1d50a,
+ 0x1d50d, 0x1d514,
+ 0x1d516, 0x1d51c,
+ 0x1d51e, 0x1d539,
+ 0x1d53b, 0x1d53e,
+ 0x1d540, 0x1d544,
+ 0x1d546, 0x1d546,
+ 0x1d54a, 0x1d550,
+ 0x1d552, 0x1d6a3,
+ 0x1d6a8, 0x1d7c9,
+ 0x1d7ce, 0x1d7ff,
+ 0x1fffe, 0x2a6d6,
+ 0x2f800, 0x2fa1d,
+ 0x2fffe, 0x2ffff,
+ 0x3fffe, 0x3ffff,
+ 0x4fffe, 0x4ffff,
+ 0x5fffe, 0x5ffff,
+ 0x6fffe, 0x6ffff,
+ 0x7fffe, 0x7ffff,
+ 0x8fffe, 0x8ffff,
+ 0x9fffe, 0x9ffff,
+ 0xafffe, 0xaffff,
+ 0xbfffe, 0xbffff,
+ 0xcfffe, 0xcffff,
+ 0xdfffe, 0xdffff,
+ 0xe0001, 0xe0001,
+ 0xe0020, 0xe007f,
+ 0xefffe, 0x10ffff,
+}; /* CR_Age_3_1 */
+
+/* 'Age_3_2': Derived Age 3.2 */
+static const OnigCodePoint CR_Age_3_2[] = {
+ 397,
+ 0x0000, 0x0220,
+ 0x0222, 0x0233,
+ 0x0250, 0x02ad,
+ 0x02b0, 0x02ee,
+ 0x0300, 0x034f,
+ 0x0360, 0x036f,
+ 0x0374, 0x0375,
+ 0x037a, 0x037a,
+ 0x037e, 0x037e,
+ 0x0384, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x03ce,
+ 0x03d0, 0x03f6,
+ 0x0400, 0x0486,
+ 0x0488, 0x04ce,
+ 0x04d0, 0x04f5,
+ 0x04f8, 0x04f9,
+ 0x0500, 0x050f,
+ 0x0531, 0x0556,
+ 0x0559, 0x055f,
+ 0x0561, 0x0587,
+ 0x0589, 0x058a,
+ 0x0591, 0x05a1,
+ 0x05a3, 0x05b9,
+ 0x05bb, 0x05c4,
+ 0x05d0, 0x05ea,
+ 0x05f0, 0x05f4,
+ 0x060c, 0x060c,
+ 0x061b, 0x061b,
+ 0x061f, 0x061f,
+ 0x0621, 0x063a,
+ 0x0640, 0x0655,
+ 0x0660, 0x06ed,
+ 0x06f0, 0x06fe,
+ 0x0700, 0x070d,
+ 0x070f, 0x072c,
+ 0x0730, 0x074a,
+ 0x0780, 0x07b1,
+ 0x0901, 0x0903,
+ 0x0905, 0x0939,
+ 0x093c, 0x094d,
+ 0x0950, 0x0954,
+ 0x0958, 0x0970,
+ 0x0981, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09bc,
+ 0x09be, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09cd,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fa,
+ 0x0a02, 0x0a02,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a74,
+ 0x0a81, 0x0a83,
+ 0x0a85, 0x0a8b,
+ 0x0a8d, 0x0a8d,
+ 0x0a8f, 0x0a91,
+ 0x0a93, 0x0aa8,
+ 0x0aaa, 0x0ab0,
+ 0x0ab2, 0x0ab3,
+ 0x0ab5, 0x0ab9,
+ 0x0abc, 0x0ac5,
+ 0x0ac7, 0x0ac9,
+ 0x0acb, 0x0acd,
+ 0x0ad0, 0x0ad0,
+ 0x0ae0, 0x0ae0,
+ 0x0ae6, 0x0aef,
+ 0x0b01, 0x0b03,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b36, 0x0b39,
+ 0x0b3c, 0x0b43,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4d,
+ 0x0b56, 0x0b57,
+ 0x0b5c, 0x0b5d,
+ 0x0b5f, 0x0b61,
+ 0x0b66, 0x0b70,
+ 0x0b82, 0x0b83,
+ 0x0b85, 0x0b8a,
+ 0x0b8e, 0x0b90,
+ 0x0b92, 0x0b95,
+ 0x0b99, 0x0b9a,
+ 0x0b9c, 0x0b9c,
+ 0x0b9e, 0x0b9f,
+ 0x0ba3, 0x0ba4,
+ 0x0ba8, 0x0baa,
+ 0x0bae, 0x0bb5,
+ 0x0bb7, 0x0bb9,
+ 0x0bbe, 0x0bc2,
+ 0x0bc6, 0x0bc8,
+ 0x0bca, 0x0bcd,
+ 0x0bd7, 0x0bd7,
+ 0x0be7, 0x0bf2,
+ 0x0c01, 0x0c03,
+ 0x0c05, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c33,
+ 0x0c35, 0x0c39,
+ 0x0c3e, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c60, 0x0c61,
+ 0x0c66, 0x0c6f,
+ 0x0c82, 0x0c83,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbe, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cde, 0x0cde,
+ 0x0ce0, 0x0ce1,
+ 0x0ce6, 0x0cef,
+ 0x0d02, 0x0d03,
+ 0x0d05, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d28,
+ 0x0d2a, 0x0d39,
+ 0x0d3e, 0x0d43,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4d,
+ 0x0d57, 0x0d57,
+ 0x0d60, 0x0d61,
+ 0x0d66, 0x0d6f,
+ 0x0d82, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0df2, 0x0df4,
+ 0x0e01, 0x0e3a,
+ 0x0e3f, 0x0e5b,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e87, 0x0e88,
+ 0x0e8a, 0x0e8a,
+ 0x0e8d, 0x0e8d,
+ 0x0e94, 0x0e97,
+ 0x0e99, 0x0e9f,
+ 0x0ea1, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ea7,
+ 0x0eaa, 0x0eab,
+ 0x0ead, 0x0eb9,
+ 0x0ebb, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ecd,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edd,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6a,
+ 0x0f71, 0x0f8b,
+ 0x0f90, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 0x0fbe, 0x0fcc,
+ 0x0fcf, 0x0fcf,
+ 0x1000, 0x1021,
+ 0x1023, 0x1027,
+ 0x1029, 0x102a,
+ 0x102c, 0x1032,
+ 0x1036, 0x1039,
+ 0x1040, 0x1059,
+ 0x10a0, 0x10c5,
+ 0x10d0, 0x10f8,
+ 0x10fb, 0x10fb,
+ 0x1100, 0x1159,
+ 0x115f, 0x11a2,
+ 0x11a8, 0x11f9,
+ 0x1200, 0x1206,
+ 0x1208, 0x1246,
+ 0x1248, 0x1248,
+ 0x124a, 0x124d,
+ 0x1250, 0x1256,
+ 0x1258, 0x1258,
+ 0x125a, 0x125d,
+ 0x1260, 0x1286,
+ 0x1288, 0x1288,
+ 0x128a, 0x128d,
+ 0x1290, 0x12ae,
+ 0x12b0, 0x12b0,
+ 0x12b2, 0x12b5,
+ 0x12b8, 0x12be,
+ 0x12c0, 0x12c0,
+ 0x12c2, 0x12c5,
+ 0x12c8, 0x12ce,
+ 0x12d0, 0x12d6,
+ 0x12d8, 0x12ee,
+ 0x12f0, 0x130e,
+ 0x1310, 0x1310,
+ 0x1312, 0x1315,
+ 0x1318, 0x131e,
+ 0x1320, 0x1346,
+ 0x1348, 0x135a,
+ 0x1361, 0x137c,
+ 0x13a0, 0x13f4,
+ 0x1401, 0x1676,
+ 0x1680, 0x169c,
+ 0x16a0, 0x16f0,
+ 0x1700, 0x170c,
+ 0x170e, 0x1714,
+ 0x1720, 0x1736,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17dc,
+ 0x17e0, 0x17e9,
+ 0x1800, 0x180e,
+ 0x1810, 0x1819,
+ 0x1820, 0x1877,
+ 0x1880, 0x18a9,
+ 0x1e00, 0x1e9b,
+ 0x1ea0, 0x1ef9,
+ 0x1f00, 0x1f15,
+ 0x1f18, 0x1f1d,
+ 0x1f20, 0x1f45,
+ 0x1f48, 0x1f4d,
+ 0x1f50, 0x1f57,
+ 0x1f59, 0x1f59,
+ 0x1f5b, 0x1f5b,
+ 0x1f5d, 0x1f5d,
+ 0x1f5f, 0x1f7d,
+ 0x1f80, 0x1fb4,
+ 0x1fb6, 0x1fc4,
+ 0x1fc6, 0x1fd3,
+ 0x1fd6, 0x1fdb,
+ 0x1fdd, 0x1fef,
+ 0x1ff2, 0x1ff4,
+ 0x1ff6, 0x1ffe,
+ 0x2000, 0x2052,
+ 0x2057, 0x2057,
+ 0x205f, 0x2063,
+ 0x206a, 0x2071,
+ 0x2074, 0x208e,
+ 0x20a0, 0x20b1,
+ 0x20d0, 0x20ea,
+ 0x2100, 0x213a,
+ 0x213d, 0x214b,
+ 0x2153, 0x2183,
+ 0x2190, 0x23ce,
+ 0x2400, 0x2426,
+ 0x2440, 0x244a,
+ 0x2460, 0x24fe,
+ 0x2500, 0x2613,
+ 0x2616, 0x2617,
+ 0x2619, 0x267d,
+ 0x2680, 0x2689,
+ 0x2701, 0x2704,
+ 0x2706, 0x2709,
+ 0x270c, 0x2727,
+ 0x2729, 0x274b,
+ 0x274d, 0x274d,
+ 0x274f, 0x2752,
+ 0x2756, 0x2756,
+ 0x2758, 0x275e,
+ 0x2761, 0x2794,
+ 0x2798, 0x27af,
+ 0x27b1, 0x27be,
+ 0x27d0, 0x27eb,
+ 0x27f0, 0x2aff,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2ffb,
+ 0x3000, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312c,
+ 0x3131, 0x318e,
+ 0x3190, 0x31b7,
+ 0x31f0, 0x321c,
+ 0x3220, 0x3243,
+ 0x3251, 0x327b,
+ 0x327f, 0x32cb,
+ 0x32d0, 0x32fe,
+ 0x3300, 0x3376,
+ 0x337b, 0x33dd,
+ 0x33e0, 0x33fe,
+ 0x3400, 0x4db5,
+ 0x4e00, 0x9fa5,
+ 0xa000, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xac00, 0xd7a3,
+ 0xd800, 0xfa2d,
+ 0xfa30, 0xfa6a,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xfb1d, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfbb1,
+ 0xfbd3, 0xfd3f,
+ 0xfd50, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdd0, 0xfdfc,
+ 0xfe00, 0xfe0f,
+ 0xfe20, 0xfe23,
+ 0xfe30, 0xfe46,
+ 0xfe49, 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, 0xffff,
+ 0x10300, 0x1031e,
+ 0x10320, 0x10323,
+ 0x10330, 0x1034a,
+ 0x10400, 0x10425,
+ 0x10428, 0x1044d,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d12a, 0x1d1dd,
+ 0x1d400, 0x1d454,
+ 0x1d456, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 0x1d4a2, 0x1d4a2,
+ 0x1d4a5, 0x1d4a6,
+ 0x1d4a9, 0x1d4ac,
+ 0x1d4ae, 0x1d4b9,
+ 0x1d4bb, 0x1d4bb,
+ 0x1d4bd, 0x1d4c0,
+ 0x1d4c2, 0x1d4c3,
+ 0x1d4c5, 0x1d505,
+ 0x1d507, 0x1d50a,
+ 0x1d50d, 0x1d514,
+ 0x1d516, 0x1d51c,
+ 0x1d51e, 0x1d539,
+ 0x1d53b, 0x1d53e,
+ 0x1d540, 0x1d544,
+ 0x1d546, 0x1d546,
+ 0x1d54a, 0x1d550,
+ 0x1d552, 0x1d6a3,
+ 0x1d6a8, 0x1d7c9,
+ 0x1d7ce, 0x1d7ff,
+ 0x1fffe, 0x2a6d6,
+ 0x2f800, 0x2fa1d,
+ 0x2fffe, 0x2ffff,
+ 0x3fffe, 0x3ffff,
+ 0x4fffe, 0x4ffff,
+ 0x5fffe, 0x5ffff,
+ 0x6fffe, 0x6ffff,
+ 0x7fffe, 0x7ffff,
+ 0x8fffe, 0x8ffff,
+ 0x9fffe, 0x9ffff,
+ 0xafffe, 0xaffff,
+ 0xbfffe, 0xbffff,
+ 0xcfffe, 0xcffff,
+ 0xdfffe, 0xdffff,
+ 0xe0001, 0xe0001,
+ 0xe0020, 0xe007f,
+ 0xefffe, 0x10ffff,
+}; /* CR_Age_3_2 */
+
+/* 'Age_4_0': Derived Age 4.0 */
+static const OnigCodePoint CR_Age_4_0[] = {
+ 412,
+ 0x0000, 0x0236,
+ 0x0250, 0x0357,
+ 0x035d, 0x036f,
+ 0x0374, 0x0375,
+ 0x037a, 0x037a,
+ 0x037e, 0x037e,
+ 0x0384, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x03ce,
+ 0x03d0, 0x03fb,
+ 0x0400, 0x0486,
+ 0x0488, 0x04ce,
+ 0x04d0, 0x04f5,
+ 0x04f8, 0x04f9,
+ 0x0500, 0x050f,
+ 0x0531, 0x0556,
+ 0x0559, 0x055f,
+ 0x0561, 0x0587,
+ 0x0589, 0x058a,
+ 0x0591, 0x05a1,
+ 0x05a3, 0x05b9,
+ 0x05bb, 0x05c4,
+ 0x05d0, 0x05ea,
+ 0x05f0, 0x05f4,
+ 0x0600, 0x0603,
+ 0x060c, 0x0615,
+ 0x061b, 0x061b,
+ 0x061f, 0x061f,
+ 0x0621, 0x063a,
+ 0x0640, 0x0658,
+ 0x0660, 0x070d,
+ 0x070f, 0x074a,
+ 0x074d, 0x074f,
+ 0x0780, 0x07b1,
+ 0x0901, 0x0939,
+ 0x093c, 0x094d,
+ 0x0950, 0x0954,
+ 0x0958, 0x0970,
+ 0x0981, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09cd,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fa,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a74,
+ 0x0a81, 0x0a83,
+ 0x0a85, 0x0a8d,
+ 0x0a8f, 0x0a91,
+ 0x0a93, 0x0aa8,
+ 0x0aaa, 0x0ab0,
+ 0x0ab2, 0x0ab3,
+ 0x0ab5, 0x0ab9,
+ 0x0abc, 0x0ac5,
+ 0x0ac7, 0x0ac9,
+ 0x0acb, 0x0acd,
+ 0x0ad0, 0x0ad0,
+ 0x0ae0, 0x0ae3,
+ 0x0ae6, 0x0aef,
+ 0x0af1, 0x0af1,
+ 0x0b01, 0x0b03,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b35, 0x0b39,
+ 0x0b3c, 0x0b43,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4d,
+ 0x0b56, 0x0b57,
+ 0x0b5c, 0x0b5d,
+ 0x0b5f, 0x0b61,
+ 0x0b66, 0x0b71,
+ 0x0b82, 0x0b83,
+ 0x0b85, 0x0b8a,
+ 0x0b8e, 0x0b90,
+ 0x0b92, 0x0b95,
+ 0x0b99, 0x0b9a,
+ 0x0b9c, 0x0b9c,
+ 0x0b9e, 0x0b9f,
+ 0x0ba3, 0x0ba4,
+ 0x0ba8, 0x0baa,
+ 0x0bae, 0x0bb5,
+ 0x0bb7, 0x0bb9,
+ 0x0bbe, 0x0bc2,
+ 0x0bc6, 0x0bc8,
+ 0x0bca, 0x0bcd,
+ 0x0bd7, 0x0bd7,
+ 0x0be7, 0x0bfa,
+ 0x0c01, 0x0c03,
+ 0x0c05, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c33,
+ 0x0c35, 0x0c39,
+ 0x0c3e, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c60, 0x0c61,
+ 0x0c66, 0x0c6f,
+ 0x0c82, 0x0c83,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cde, 0x0cde,
+ 0x0ce0, 0x0ce1,
+ 0x0ce6, 0x0cef,
+ 0x0d02, 0x0d03,
+ 0x0d05, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d28,
+ 0x0d2a, 0x0d39,
+ 0x0d3e, 0x0d43,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4d,
+ 0x0d57, 0x0d57,
+ 0x0d60, 0x0d61,
+ 0x0d66, 0x0d6f,
+ 0x0d82, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0df2, 0x0df4,
+ 0x0e01, 0x0e3a,
+ 0x0e3f, 0x0e5b,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e87, 0x0e88,
+ 0x0e8a, 0x0e8a,
+ 0x0e8d, 0x0e8d,
+ 0x0e94, 0x0e97,
+ 0x0e99, 0x0e9f,
+ 0x0ea1, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ea7,
+ 0x0eaa, 0x0eab,
+ 0x0ead, 0x0eb9,
+ 0x0ebb, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ecd,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edd,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6a,
+ 0x0f71, 0x0f8b,
+ 0x0f90, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 0x0fbe, 0x0fcc,
+ 0x0fcf, 0x0fcf,
+ 0x1000, 0x1021,
+ 0x1023, 0x1027,
+ 0x1029, 0x102a,
+ 0x102c, 0x1032,
+ 0x1036, 0x1039,
+ 0x1040, 0x1059,
+ 0x10a0, 0x10c5,
+ 0x10d0, 0x10f8,
+ 0x10fb, 0x10fb,
+ 0x1100, 0x1159,
+ 0x115f, 0x11a2,
+ 0x11a8, 0x11f9,
+ 0x1200, 0x1206,
+ 0x1208, 0x1246,
+ 0x1248, 0x1248,
+ 0x124a, 0x124d,
+ 0x1250, 0x1256,
+ 0x1258, 0x1258,
+ 0x125a, 0x125d,
+ 0x1260, 0x1286,
+ 0x1288, 0x1288,
+ 0x128a, 0x128d,
+ 0x1290, 0x12ae,
+ 0x12b0, 0x12b0,
+ 0x12b2, 0x12b5,
+ 0x12b8, 0x12be,
+ 0x12c0, 0x12c0,
+ 0x12c2, 0x12c5,
+ 0x12c8, 0x12ce,
+ 0x12d0, 0x12d6,
+ 0x12d8, 0x12ee,
+ 0x12f0, 0x130e,
+ 0x1310, 0x1310,
+ 0x1312, 0x1315,
+ 0x1318, 0x131e,
+ 0x1320, 0x1346,
+ 0x1348, 0x135a,
+ 0x1361, 0x137c,
+ 0x13a0, 0x13f4,
+ 0x1401, 0x1676,
+ 0x1680, 0x169c,
+ 0x16a0, 0x16f0,
+ 0x1700, 0x170c,
+ 0x170e, 0x1714,
+ 0x1720, 0x1736,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x1800, 0x180e,
+ 0x1810, 0x1819,
+ 0x1820, 0x1877,
+ 0x1880, 0x18a9,
+ 0x1900, 0x191c,
+ 0x1920, 0x192b,
+ 0x1930, 0x193b,
+ 0x1940, 0x1940,
+ 0x1944, 0x196d,
+ 0x1970, 0x1974,
+ 0x19e0, 0x19ff,
+ 0x1d00, 0x1d6b,
+ 0x1e00, 0x1e9b,
+ 0x1ea0, 0x1ef9,
+ 0x1f00, 0x1f15,
+ 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, 0x2054,
+ 0x2057, 0x2057,
+ 0x205f, 0x2063,
+ 0x206a, 0x2071,
+ 0x2074, 0x208e,
+ 0x20a0, 0x20b1,
+ 0x20d0, 0x20ea,
+ 0x2100, 0x213b,
+ 0x213d, 0x214b,
+ 0x2153, 0x2183,
+ 0x2190, 0x23d0,
+ 0x2400, 0x2426,
+ 0x2440, 0x244a,
+ 0x2460, 0x2617,
+ 0x2619, 0x267d,
+ 0x2680, 0x2691,
+ 0x26a0, 0x26a1,
+ 0x2701, 0x2704,
+ 0x2706, 0x2709,
+ 0x270c, 0x2727,
+ 0x2729, 0x274b,
+ 0x274d, 0x274d,
+ 0x274f, 0x2752,
+ 0x2756, 0x2756,
+ 0x2758, 0x275e,
+ 0x2761, 0x2794,
+ 0x2798, 0x27af,
+ 0x27b1, 0x27be,
+ 0x27d0, 0x27eb,
+ 0x27f0, 0x2b0d,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2ffb,
+ 0x3000, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312c,
+ 0x3131, 0x318e,
+ 0x3190, 0x31b7,
+ 0x31f0, 0x321e,
+ 0x3220, 0x3243,
+ 0x3250, 0x327d,
+ 0x327f, 0x32fe,
+ 0x3300, 0x4db5,
+ 0x4dc0, 0x9fa5,
+ 0xa000, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xac00, 0xd7a3,
+ 0xd800, 0xfa2d,
+ 0xfa30, 0xfa6a,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xfb1d, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfbb1,
+ 0xfbd3, 0xfd3f,
+ 0xfd50, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdd0, 0xfdfd,
+ 0xfe00, 0xfe0f,
+ 0xfe20, 0xfe23,
+ 0xfe30, 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, 0x1013f,
+ 0x10300, 0x1031e,
+ 0x10320, 0x10323,
+ 0x10330, 0x1034a,
+ 0x10380, 0x1039d,
+ 0x1039f, 0x1039f,
+ 0x10400, 0x1049d,
+ 0x104a0, 0x104a9,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 0x10837, 0x10838,
+ 0x1083c, 0x1083c,
+ 0x1083f, 0x1083f,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d12a, 0x1d1dd,
+ 0x1d300, 0x1d356,
+ 0x1d400, 0x1d454,
+ 0x1d456, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 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, 0x1d6a3,
+ 0x1d6a8, 0x1d7c9,
+ 0x1d7ce, 0x1d7ff,
+ 0x1fffe, 0x2a6d6,
+ 0x2f800, 0x2fa1d,
+ 0x2fffe, 0x2ffff,
+ 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_4_0 */
+
+/* 'Age_4_1': Derived Age 4.1 */
+static const OnigCodePoint CR_Age_4_1[] = {
+ 430,
+ 0x0000, 0x0241,
+ 0x0250, 0x036f,
+ 0x0374, 0x0375,
+ 0x037a, 0x037a,
+ 0x037e, 0x037e,
+ 0x0384, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x03ce,
+ 0x03d0, 0x0486,
+ 0x0488, 0x04ce,
+ 0x04d0, 0x04f9,
+ 0x0500, 0x050f,
+ 0x0531, 0x0556,
+ 0x0559, 0x055f,
+ 0x0561, 0x0587,
+ 0x0589, 0x058a,
+ 0x0591, 0x05b9,
+ 0x05bb, 0x05c7,
+ 0x05d0, 0x05ea,
+ 0x05f0, 0x05f4,
+ 0x0600, 0x0603,
+ 0x060b, 0x0615,
+ 0x061b, 0x061b,
+ 0x061e, 0x061f,
+ 0x0621, 0x063a,
+ 0x0640, 0x065e,
+ 0x0660, 0x070d,
+ 0x070f, 0x074a,
+ 0x074d, 0x076d,
+ 0x0780, 0x07b1,
+ 0x0901, 0x0939,
+ 0x093c, 0x094d,
+ 0x0950, 0x0954,
+ 0x0958, 0x0970,
+ 0x097d, 0x097d,
+ 0x0981, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fa,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a74,
+ 0x0a81, 0x0a83,
+ 0x0a85, 0x0a8d,
+ 0x0a8f, 0x0a91,
+ 0x0a93, 0x0aa8,
+ 0x0aaa, 0x0ab0,
+ 0x0ab2, 0x0ab3,
+ 0x0ab5, 0x0ab9,
+ 0x0abc, 0x0ac5,
+ 0x0ac7, 0x0ac9,
+ 0x0acb, 0x0acd,
+ 0x0ad0, 0x0ad0,
+ 0x0ae0, 0x0ae3,
+ 0x0ae6, 0x0aef,
+ 0x0af1, 0x0af1,
+ 0x0b01, 0x0b03,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b35, 0x0b39,
+ 0x0b3c, 0x0b43,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4d,
+ 0x0b56, 0x0b57,
+ 0x0b5c, 0x0b5d,
+ 0x0b5f, 0x0b61,
+ 0x0b66, 0x0b71,
+ 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,
+ 0x0bd7, 0x0bd7,
+ 0x0be6, 0x0bfa,
+ 0x0c01, 0x0c03,
+ 0x0c05, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c33,
+ 0x0c35, 0x0c39,
+ 0x0c3e, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c60, 0x0c61,
+ 0x0c66, 0x0c6f,
+ 0x0c82, 0x0c83,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cde, 0x0cde,
+ 0x0ce0, 0x0ce1,
+ 0x0ce6, 0x0cef,
+ 0x0d02, 0x0d03,
+ 0x0d05, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d28,
+ 0x0d2a, 0x0d39,
+ 0x0d3e, 0x0d43,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4d,
+ 0x0d57, 0x0d57,
+ 0x0d60, 0x0d61,
+ 0x0d66, 0x0d6f,
+ 0x0d82, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0df2, 0x0df4,
+ 0x0e01, 0x0e3a,
+ 0x0e3f, 0x0e5b,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e87, 0x0e88,
+ 0x0e8a, 0x0e8a,
+ 0x0e8d, 0x0e8d,
+ 0x0e94, 0x0e97,
+ 0x0e99, 0x0e9f,
+ 0x0ea1, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ea7,
+ 0x0eaa, 0x0eab,
+ 0x0ead, 0x0eb9,
+ 0x0ebb, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ecd,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edd,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6a,
+ 0x0f71, 0x0f8b,
+ 0x0f90, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 0x0fbe, 0x0fcc,
+ 0x0fcf, 0x0fd1,
+ 0x1000, 0x1021,
+ 0x1023, 0x1027,
+ 0x1029, 0x102a,
+ 0x102c, 0x1032,
+ 0x1036, 0x1039,
+ 0x1040, 0x1059,
+ 0x10a0, 0x10c5,
+ 0x10d0, 0x10fc,
+ 0x1100, 0x1159,
+ 0x115f, 0x11a2,
+ 0x11a8, 0x11f9,
+ 0x1200, 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,
+ 0x135f, 0x137c,
+ 0x1380, 0x1399,
+ 0x13a0, 0x13f4,
+ 0x1401, 0x1676,
+ 0x1680, 0x169c,
+ 0x16a0, 0x16f0,
+ 0x1700, 0x170c,
+ 0x170e, 0x1714,
+ 0x1720, 0x1736,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x1800, 0x180e,
+ 0x1810, 0x1819,
+ 0x1820, 0x1877,
+ 0x1880, 0x18a9,
+ 0x1900, 0x191c,
+ 0x1920, 0x192b,
+ 0x1930, 0x193b,
+ 0x1940, 0x1940,
+ 0x1944, 0x196d,
+ 0x1970, 0x1974,
+ 0x1980, 0x19a9,
+ 0x19b0, 0x19c9,
+ 0x19d0, 0x19d9,
+ 0x19de, 0x1a1b,
+ 0x1a1e, 0x1a1f,
+ 0x1d00, 0x1dc3,
+ 0x1e00, 0x1e9b,
+ 0x1ea0, 0x1ef9,
+ 0x1f00, 0x1f15,
+ 0x1f18, 0x1f1d,
+ 0x1f20, 0x1f45,
+ 0x1f48, 0x1f4d,
+ 0x1f50, 0x1f57,
+ 0x1f59, 0x1f59,
+ 0x1f5b, 0x1f5b,
+ 0x1f5d, 0x1f5d,
+ 0x1f5f, 0x1f7d,
+ 0x1f80, 0x1fb4,
+ 0x1fb6, 0x1fc4,
+ 0x1fc6, 0x1fd3,
+ 0x1fd6, 0x1fdb,
+ 0x1fdd, 0x1fef,
+ 0x1ff2, 0x1ff4,
+ 0x1ff6, 0x1ffe,
+ 0x2000, 0x2063,
+ 0x206a, 0x2071,
+ 0x2074, 0x208e,
+ 0x2090, 0x2094,
+ 0x20a0, 0x20b5,
+ 0x20d0, 0x20eb,
+ 0x2100, 0x214c,
+ 0x2153, 0x2183,
+ 0x2190, 0x23db,
+ 0x2400, 0x2426,
+ 0x2440, 0x244a,
+ 0x2460, 0x269c,
+ 0x26a0, 0x26b1,
+ 0x2701, 0x2704,
+ 0x2706, 0x2709,
+ 0x270c, 0x2727,
+ 0x2729, 0x274b,
+ 0x274d, 0x274d,
+ 0x274f, 0x2752,
+ 0x2756, 0x2756,
+ 0x2758, 0x275e,
+ 0x2761, 0x2794,
+ 0x2798, 0x27af,
+ 0x27b1, 0x27be,
+ 0x27c0, 0x27c6,
+ 0x27d0, 0x27eb,
+ 0x27f0, 0x2b13,
+ 0x2c00, 0x2c2e,
+ 0x2c30, 0x2c5e,
+ 0x2c80, 0x2cea,
+ 0x2cf9, 0x2d25,
+ 0x2d30, 0x2d65,
+ 0x2d6f, 0x2d6f,
+ 0x2d80, 0x2d96,
+ 0x2da0, 0x2da6,
+ 0x2da8, 0x2dae,
+ 0x2db0, 0x2db6,
+ 0x2db8, 0x2dbe,
+ 0x2dc0, 0x2dc6,
+ 0x2dc8, 0x2dce,
+ 0x2dd0, 0x2dd6,
+ 0x2dd8, 0x2dde,
+ 0x2e00, 0x2e17,
+ 0x2e1c, 0x2e1d,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2ffb,
+ 0x3000, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312c,
+ 0x3131, 0x318e,
+ 0x3190, 0x31b7,
+ 0x31c0, 0x31cf,
+ 0x31f0, 0x321e,
+ 0x3220, 0x3243,
+ 0x3250, 0x32fe,
+ 0x3300, 0x4db5,
+ 0x4dc0, 0x9fbb,
+ 0xa000, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa700, 0xa716,
+ 0xa800, 0xa82b,
+ 0xac00, 0xd7a3,
+ 0xd800, 0xfa2d,
+ 0xfa30, 0xfa6a,
+ 0xfa70, 0xfad9,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xfb1d, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfbb1,
+ 0xfbd3, 0xfd3f,
+ 0xfd50, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdd0, 0xfdfd,
+ 0xfe00, 0xfe19,
+ 0xfe20, 0xfe23,
+ 0xfe30, 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, 0x1018a,
+ 0x10300, 0x1031e,
+ 0x10320, 0x10323,
+ 0x10330, 0x1034a,
+ 0x10380, 0x1039d,
+ 0x1039f, 0x103c3,
+ 0x103c8, 0x103d5,
+ 0x10400, 0x1049d,
+ 0x104a0, 0x104a9,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 0x10837, 0x10838,
+ 0x1083c, 0x1083c,
+ 0x1083f, 0x1083f,
+ 0x10a00, 0x10a03,
+ 0x10a05, 0x10a06,
+ 0x10a0c, 0x10a13,
+ 0x10a15, 0x10a17,
+ 0x10a19, 0x10a33,
+ 0x10a38, 0x10a3a,
+ 0x10a3f, 0x10a47,
+ 0x10a50, 0x10a58,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d12a, 0x1d1dd,
+ 0x1d200, 0x1d245,
+ 0x1d300, 0x1d356,
+ 0x1d400, 0x1d454,
+ 0x1d456, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 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, 0x1d7c9,
+ 0x1d7ce, 0x1d7ff,
+ 0x1fffe, 0x2a6d6,
+ 0x2f800, 0x2fa1d,
+ 0x2fffe, 0x2ffff,
+ 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_4_1 */
+
+/* 'Age_5_0': Derived Age 5.0 */
+static const OnigCodePoint CR_Age_5_0[] = {
+ 440,
+ 0x0000, 0x036f,
+ 0x0374, 0x0375,
+ 0x037a, 0x037e,
+ 0x0384, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x03ce,
+ 0x03d0, 0x0486,
+ 0x0488, 0x0513,
+ 0x0531, 0x0556,
+ 0x0559, 0x055f,
+ 0x0561, 0x0587,
+ 0x0589, 0x058a,
+ 0x0591, 0x05c7,
+ 0x05d0, 0x05ea,
+ 0x05f0, 0x05f4,
+ 0x0600, 0x0603,
+ 0x060b, 0x0615,
+ 0x061b, 0x061b,
+ 0x061e, 0x061f,
+ 0x0621, 0x063a,
+ 0x0640, 0x065e,
+ 0x0660, 0x070d,
+ 0x070f, 0x074a,
+ 0x074d, 0x076d,
+ 0x0780, 0x07b1,
+ 0x07c0, 0x07fa,
+ 0x0901, 0x0939,
+ 0x093c, 0x094d,
+ 0x0950, 0x0954,
+ 0x0958, 0x0970,
+ 0x097b, 0x097f,
+ 0x0981, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fa,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a74,
+ 0x0a81, 0x0a83,
+ 0x0a85, 0x0a8d,
+ 0x0a8f, 0x0a91,
+ 0x0a93, 0x0aa8,
+ 0x0aaa, 0x0ab0,
+ 0x0ab2, 0x0ab3,
+ 0x0ab5, 0x0ab9,
+ 0x0abc, 0x0ac5,
+ 0x0ac7, 0x0ac9,
+ 0x0acb, 0x0acd,
+ 0x0ad0, 0x0ad0,
+ 0x0ae0, 0x0ae3,
+ 0x0ae6, 0x0aef,
+ 0x0af1, 0x0af1,
+ 0x0b01, 0x0b03,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b35, 0x0b39,
+ 0x0b3c, 0x0b43,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4d,
+ 0x0b56, 0x0b57,
+ 0x0b5c, 0x0b5d,
+ 0x0b5f, 0x0b61,
+ 0x0b66, 0x0b71,
+ 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,
+ 0x0bd7, 0x0bd7,
+ 0x0be6, 0x0bfa,
+ 0x0c01, 0x0c03,
+ 0x0c05, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c33,
+ 0x0c35, 0x0c39,
+ 0x0c3e, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c60, 0x0c61,
+ 0x0c66, 0x0c6f,
+ 0x0c82, 0x0c83,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cde, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf2,
+ 0x0d02, 0x0d03,
+ 0x0d05, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d28,
+ 0x0d2a, 0x0d39,
+ 0x0d3e, 0x0d43,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4d,
+ 0x0d57, 0x0d57,
+ 0x0d60, 0x0d61,
+ 0x0d66, 0x0d6f,
+ 0x0d82, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0df2, 0x0df4,
+ 0x0e01, 0x0e3a,
+ 0x0e3f, 0x0e5b,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e87, 0x0e88,
+ 0x0e8a, 0x0e8a,
+ 0x0e8d, 0x0e8d,
+ 0x0e94, 0x0e97,
+ 0x0e99, 0x0e9f,
+ 0x0ea1, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ea7,
+ 0x0eaa, 0x0eab,
+ 0x0ead, 0x0eb9,
+ 0x0ebb, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ecd,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edd,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6a,
+ 0x0f71, 0x0f8b,
+ 0x0f90, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 0x0fbe, 0x0fcc,
+ 0x0fcf, 0x0fd1,
+ 0x1000, 0x1021,
+ 0x1023, 0x1027,
+ 0x1029, 0x102a,
+ 0x102c, 0x1032,
+ 0x1036, 0x1039,
+ 0x1040, 0x1059,
+ 0x10a0, 0x10c5,
+ 0x10d0, 0x10fc,
+ 0x1100, 0x1159,
+ 0x115f, 0x11a2,
+ 0x11a8, 0x11f9,
+ 0x1200, 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,
+ 0x135f, 0x137c,
+ 0x1380, 0x1399,
+ 0x13a0, 0x13f4,
+ 0x1401, 0x1676,
+ 0x1680, 0x169c,
+ 0x16a0, 0x16f0,
+ 0x1700, 0x170c,
+ 0x170e, 0x1714,
+ 0x1720, 0x1736,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x1800, 0x180e,
+ 0x1810, 0x1819,
+ 0x1820, 0x1877,
+ 0x1880, 0x18a9,
+ 0x1900, 0x191c,
+ 0x1920, 0x192b,
+ 0x1930, 0x193b,
+ 0x1940, 0x1940,
+ 0x1944, 0x196d,
+ 0x1970, 0x1974,
+ 0x1980, 0x19a9,
+ 0x19b0, 0x19c9,
+ 0x19d0, 0x19d9,
+ 0x19de, 0x1a1b,
+ 0x1a1e, 0x1a1f,
+ 0x1b00, 0x1b4b,
+ 0x1b50, 0x1b7c,
+ 0x1d00, 0x1dca,
+ 0x1dfe, 0x1e9b,
+ 0x1ea0, 0x1ef9,
+ 0x1f00, 0x1f15,
+ 0x1f18, 0x1f1d,
+ 0x1f20, 0x1f45,
+ 0x1f48, 0x1f4d,
+ 0x1f50, 0x1f57,
+ 0x1f59, 0x1f59,
+ 0x1f5b, 0x1f5b,
+ 0x1f5d, 0x1f5d,
+ 0x1f5f, 0x1f7d,
+ 0x1f80, 0x1fb4,
+ 0x1fb6, 0x1fc4,
+ 0x1fc6, 0x1fd3,
+ 0x1fd6, 0x1fdb,
+ 0x1fdd, 0x1fef,
+ 0x1ff2, 0x1ff4,
+ 0x1ff6, 0x1ffe,
+ 0x2000, 0x2063,
+ 0x206a, 0x2071,
+ 0x2074, 0x208e,
+ 0x2090, 0x2094,
+ 0x20a0, 0x20b5,
+ 0x20d0, 0x20ef,
+ 0x2100, 0x214e,
+ 0x2153, 0x2184,
+ 0x2190, 0x23e7,
+ 0x2400, 0x2426,
+ 0x2440, 0x244a,
+ 0x2460, 0x269c,
+ 0x26a0, 0x26b2,
+ 0x2701, 0x2704,
+ 0x2706, 0x2709,
+ 0x270c, 0x2727,
+ 0x2729, 0x274b,
+ 0x274d, 0x274d,
+ 0x274f, 0x2752,
+ 0x2756, 0x2756,
+ 0x2758, 0x275e,
+ 0x2761, 0x2794,
+ 0x2798, 0x27af,
+ 0x27b1, 0x27be,
+ 0x27c0, 0x27ca,
+ 0x27d0, 0x27eb,
+ 0x27f0, 0x2b1a,
+ 0x2b20, 0x2b23,
+ 0x2c00, 0x2c2e,
+ 0x2c30, 0x2c5e,
+ 0x2c60, 0x2c6c,
+ 0x2c74, 0x2c77,
+ 0x2c80, 0x2cea,
+ 0x2cf9, 0x2d25,
+ 0x2d30, 0x2d65,
+ 0x2d6f, 0x2d6f,
+ 0x2d80, 0x2d96,
+ 0x2da0, 0x2da6,
+ 0x2da8, 0x2dae,
+ 0x2db0, 0x2db6,
+ 0x2db8, 0x2dbe,
+ 0x2dc0, 0x2dc6,
+ 0x2dc8, 0x2dce,
+ 0x2dd0, 0x2dd6,
+ 0x2dd8, 0x2dde,
+ 0x2e00, 0x2e17,
+ 0x2e1c, 0x2e1d,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2ffb,
+ 0x3000, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312c,
+ 0x3131, 0x318e,
+ 0x3190, 0x31b7,
+ 0x31c0, 0x31cf,
+ 0x31f0, 0x321e,
+ 0x3220, 0x3243,
+ 0x3250, 0x32fe,
+ 0x3300, 0x4db5,
+ 0x4dc0, 0x9fbb,
+ 0xa000, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa700, 0xa71a,
+ 0xa720, 0xa721,
+ 0xa800, 0xa82b,
+ 0xa840, 0xa877,
+ 0xac00, 0xd7a3,
+ 0xd800, 0xfa2d,
+ 0xfa30, 0xfa6a,
+ 0xfa70, 0xfad9,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xfb1d, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfbb1,
+ 0xfbd3, 0xfd3f,
+ 0xfd50, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdd0, 0xfdfd,
+ 0xfe00, 0xfe19,
+ 0xfe20, 0xfe23,
+ 0xfe30, 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, 0x1018a,
+ 0x10300, 0x1031e,
+ 0x10320, 0x10323,
+ 0x10330, 0x1034a,
+ 0x10380, 0x1039d,
+ 0x1039f, 0x103c3,
+ 0x103c8, 0x103d5,
+ 0x10400, 0x1049d,
+ 0x104a0, 0x104a9,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 0x10837, 0x10838,
+ 0x1083c, 0x1083c,
+ 0x1083f, 0x1083f,
+ 0x10900, 0x10919,
+ 0x1091f, 0x1091f,
+ 0x10a00, 0x10a03,
+ 0x10a05, 0x10a06,
+ 0x10a0c, 0x10a13,
+ 0x10a15, 0x10a17,
+ 0x10a19, 0x10a33,
+ 0x10a38, 0x10a3a,
+ 0x10a3f, 0x10a47,
+ 0x10a50, 0x10a58,
+ 0x12000, 0x1236e,
+ 0x12400, 0x12462,
+ 0x12470, 0x12473,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d12a, 0x1d1dd,
+ 0x1d200, 0x1d245,
+ 0x1d300, 0x1d356,
+ 0x1d360, 0x1d371,
+ 0x1d400, 0x1d454,
+ 0x1d456, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 0x1d4a2, 0x1d4a2,
+ 0x1d4a5, 0x1d4a6,
+ 0x1d4a9, 0x1d4ac,
+ 0x1d4ae, 0x1d4b9,
+ 0x1d4bb, 0x1d4bb,
+ 0x1d4bd, 0x1d4c3,
+ 0x1d4c5, 0x1d505,
+ 0x1d507, 0x1d50a,
+ 0x1d50d, 0x1d514,
+ 0x1d516, 0x1d51c,
+ 0x1d51e, 0x1d539,
+ 0x1d53b, 0x1d53e,
+ 0x1d540, 0x1d544,
+ 0x1d546, 0x1d546,
+ 0x1d54a, 0x1d550,
+ 0x1d552, 0x1d6a5,
+ 0x1d6a8, 0x1d7cb,
+ 0x1d7ce, 0x1d7ff,
+ 0x1fffe, 0x2a6d6,
+ 0x2f800, 0x2fa1d,
+ 0x2fffe, 0x2ffff,
+ 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_5_0 */
+
+/* 'Age_5_1': Derived Age 5.1 */
+static const OnigCodePoint CR_Age_5_1[] = {
+ 455,
+ 0x0000, 0x0377,
+ 0x037a, 0x037e,
+ 0x0384, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x0523,
+ 0x0531, 0x0556,
+ 0x0559, 0x055f,
+ 0x0561, 0x0587,
+ 0x0589, 0x058a,
+ 0x0591, 0x05c7,
+ 0x05d0, 0x05ea,
+ 0x05f0, 0x05f4,
+ 0x0600, 0x0603,
+ 0x0606, 0x061b,
+ 0x061e, 0x061f,
+ 0x0621, 0x065e,
+ 0x0660, 0x070d,
+ 0x070f, 0x074a,
+ 0x074d, 0x07b1,
+ 0x07c0, 0x07fa,
+ 0x0901, 0x0939,
+ 0x093c, 0x094d,
+ 0x0950, 0x0954,
+ 0x0958, 0x0972,
+ 0x097b, 0x097f,
+ 0x0981, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fa,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a75,
+ 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, 0x0aef,
+ 0x0af1, 0x0af1,
+ 0x0b01, 0x0b03,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b35, 0x0b39,
+ 0x0b3c, 0x0b44,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4d,
+ 0x0b56, 0x0b57,
+ 0x0b5c, 0x0b5d,
+ 0x0b5f, 0x0b63,
+ 0x0b66, 0x0b71,
+ 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,
+ 0x0be6, 0x0bfa,
+ 0x0c01, 0x0c03,
+ 0x0c05, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c33,
+ 0x0c35, 0x0c39,
+ 0x0c3d, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c59,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c78, 0x0c7f,
+ 0x0c82, 0x0c83,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cde, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf2,
+ 0x0d02, 0x0d03,
+ 0x0d05, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d28,
+ 0x0d2a, 0x0d39,
+ 0x0d3d, 0x0d44,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4d,
+ 0x0d57, 0x0d57,
+ 0x0d60, 0x0d63,
+ 0x0d66, 0x0d75,
+ 0x0d79, 0x0d7f,
+ 0x0d82, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0df2, 0x0df4,
+ 0x0e01, 0x0e3a,
+ 0x0e3f, 0x0e5b,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e87, 0x0e88,
+ 0x0e8a, 0x0e8a,
+ 0x0e8d, 0x0e8d,
+ 0x0e94, 0x0e97,
+ 0x0e99, 0x0e9f,
+ 0x0ea1, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ea7,
+ 0x0eaa, 0x0eab,
+ 0x0ead, 0x0eb9,
+ 0x0ebb, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ecd,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edd,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f8b,
+ 0x0f90, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 0x0fbe, 0x0fcc,
+ 0x0fce, 0x0fd4,
+ 0x1000, 0x1099,
+ 0x109e, 0x10c5,
+ 0x10d0, 0x10fc,
+ 0x1100, 0x1159,
+ 0x115f, 0x11a2,
+ 0x11a8, 0x11f9,
+ 0x1200, 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,
+ 0x135f, 0x137c,
+ 0x1380, 0x1399,
+ 0x13a0, 0x13f4,
+ 0x1401, 0x1676,
+ 0x1680, 0x169c,
+ 0x16a0, 0x16f0,
+ 0x1700, 0x170c,
+ 0x170e, 0x1714,
+ 0x1720, 0x1736,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x1800, 0x180e,
+ 0x1810, 0x1819,
+ 0x1820, 0x1877,
+ 0x1880, 0x18aa,
+ 0x1900, 0x191c,
+ 0x1920, 0x192b,
+ 0x1930, 0x193b,
+ 0x1940, 0x1940,
+ 0x1944, 0x196d,
+ 0x1970, 0x1974,
+ 0x1980, 0x19a9,
+ 0x19b0, 0x19c9,
+ 0x19d0, 0x19d9,
+ 0x19de, 0x1a1b,
+ 0x1a1e, 0x1a1f,
+ 0x1b00, 0x1b4b,
+ 0x1b50, 0x1b7c,
+ 0x1b80, 0x1baa,
+ 0x1bae, 0x1bb9,
+ 0x1c00, 0x1c37,
+ 0x1c3b, 0x1c49,
+ 0x1c4d, 0x1c7f,
+ 0x1d00, 0x1de6,
+ 0x1dfe, 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,
+ 0x206a, 0x2071,
+ 0x2074, 0x208e,
+ 0x2090, 0x2094,
+ 0x20a0, 0x20b5,
+ 0x20d0, 0x20f0,
+ 0x2100, 0x214f,
+ 0x2153, 0x2188,
+ 0x2190, 0x23e7,
+ 0x2400, 0x2426,
+ 0x2440, 0x244a,
+ 0x2460, 0x269d,
+ 0x26a0, 0x26bc,
+ 0x26c0, 0x26c3,
+ 0x2701, 0x2704,
+ 0x2706, 0x2709,
+ 0x270c, 0x2727,
+ 0x2729, 0x274b,
+ 0x274d, 0x274d,
+ 0x274f, 0x2752,
+ 0x2756, 0x2756,
+ 0x2758, 0x275e,
+ 0x2761, 0x2794,
+ 0x2798, 0x27af,
+ 0x27b1, 0x27be,
+ 0x27c0, 0x27ca,
+ 0x27cc, 0x27cc,
+ 0x27d0, 0x2b4c,
+ 0x2b50, 0x2b54,
+ 0x2c00, 0x2c2e,
+ 0x2c30, 0x2c5e,
+ 0x2c60, 0x2c6f,
+ 0x2c71, 0x2c7d,
+ 0x2c80, 0x2cea,
+ 0x2cf9, 0x2d25,
+ 0x2d30, 0x2d65,
+ 0x2d6f, 0x2d6f,
+ 0x2d80, 0x2d96,
+ 0x2da0, 0x2da6,
+ 0x2da8, 0x2dae,
+ 0x2db0, 0x2db6,
+ 0x2db8, 0x2dbe,
+ 0x2dc0, 0x2dc6,
+ 0x2dc8, 0x2dce,
+ 0x2dd0, 0x2dd6,
+ 0x2dd8, 0x2dde,
+ 0x2de0, 0x2e30,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2ffb,
+ 0x3000, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312d,
+ 0x3131, 0x318e,
+ 0x3190, 0x31b7,
+ 0x31c0, 0x31e3,
+ 0x31f0, 0x321e,
+ 0x3220, 0x3243,
+ 0x3250, 0x32fe,
+ 0x3300, 0x4db5,
+ 0x4dc0, 0x9fc3,
+ 0xa000, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa500, 0xa62b,
+ 0xa640, 0xa65f,
+ 0xa662, 0xa673,
+ 0xa67c, 0xa697,
+ 0xa700, 0xa78c,
+ 0xa7fb, 0xa82b,
+ 0xa840, 0xa877,
+ 0xa880, 0xa8c4,
+ 0xa8ce, 0xa8d9,
+ 0xa900, 0xa953,
+ 0xa95f, 0xa95f,
+ 0xaa00, 0xaa36,
+ 0xaa40, 0xaa4d,
+ 0xaa50, 0xaa59,
+ 0xaa5c, 0xaa5f,
+ 0xac00, 0xd7a3,
+ 0xd800, 0xfa2d,
+ 0xfa30, 0xfa6a,
+ 0xfa70, 0xfad9,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xfb1d, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfbb1,
+ 0xfbd3, 0xfd3f,
+ 0xfd50, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdd0, 0xfdfd,
+ 0xfe00, 0xfe19,
+ 0xfe20, 0xfe26,
+ 0xfe30, 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, 0x1018a,
+ 0x10190, 0x1019b,
+ 0x101d0, 0x101fd,
+ 0x10280, 0x1029c,
+ 0x102a0, 0x102d0,
+ 0x10300, 0x1031e,
+ 0x10320, 0x10323,
+ 0x10330, 0x1034a,
+ 0x10380, 0x1039d,
+ 0x1039f, 0x103c3,
+ 0x103c8, 0x103d5,
+ 0x10400, 0x1049d,
+ 0x104a0, 0x104a9,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 0x10837, 0x10838,
+ 0x1083c, 0x1083c,
+ 0x1083f, 0x1083f,
+ 0x10900, 0x10919,
+ 0x1091f, 0x10939,
+ 0x1093f, 0x1093f,
+ 0x10a00, 0x10a03,
+ 0x10a05, 0x10a06,
+ 0x10a0c, 0x10a13,
+ 0x10a15, 0x10a17,
+ 0x10a19, 0x10a33,
+ 0x10a38, 0x10a3a,
+ 0x10a3f, 0x10a47,
+ 0x10a50, 0x10a58,
+ 0x12000, 0x1236e,
+ 0x12400, 0x12462,
+ 0x12470, 0x12473,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d129, 0x1d1dd,
+ 0x1d200, 0x1d245,
+ 0x1d300, 0x1d356,
+ 0x1d360, 0x1d371,
+ 0x1d400, 0x1d454,
+ 0x1d456, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 0x1d4a2, 0x1d4a2,
+ 0x1d4a5, 0x1d4a6,
+ 0x1d4a9, 0x1d4ac,
+ 0x1d4ae, 0x1d4b9,
+ 0x1d4bb, 0x1d4bb,
+ 0x1d4bd, 0x1d4c3,
+ 0x1d4c5, 0x1d505,
+ 0x1d507, 0x1d50a,
+ 0x1d50d, 0x1d514,
+ 0x1d516, 0x1d51c,
+ 0x1d51e, 0x1d539,
+ 0x1d53b, 0x1d53e,
+ 0x1d540, 0x1d544,
+ 0x1d546, 0x1d546,
+ 0x1d54a, 0x1d550,
+ 0x1d552, 0x1d6a5,
+ 0x1d6a8, 0x1d7cb,
+ 0x1d7ce, 0x1d7ff,
+ 0x1f000, 0x1f02b,
+ 0x1f030, 0x1f093,
+ 0x1fffe, 0x2a6d6,
+ 0x2f800, 0x2fa1d,
+ 0x2fffe, 0x2ffff,
+ 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_5_1 */
+
+/* 'Age_5_2': Derived Age 5.2 */
+static const OnigCodePoint CR_Age_5_2[] = {
+ 495,
+ 0x0000, 0x0377,
+ 0x037a, 0x037e,
+ 0x0384, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x0525,
+ 0x0531, 0x0556,
+ 0x0559, 0x055f,
+ 0x0561, 0x0587,
+ 0x0589, 0x058a,
+ 0x0591, 0x05c7,
+ 0x05d0, 0x05ea,
+ 0x05f0, 0x05f4,
+ 0x0600, 0x0603,
+ 0x0606, 0x061b,
+ 0x061e, 0x061f,
+ 0x0621, 0x065e,
+ 0x0660, 0x070d,
+ 0x070f, 0x074a,
+ 0x074d, 0x07b1,
+ 0x07c0, 0x07fa,
+ 0x0800, 0x082d,
+ 0x0830, 0x083e,
+ 0x0900, 0x0939,
+ 0x093c, 0x094e,
+ 0x0950, 0x0955,
+ 0x0958, 0x0972,
+ 0x0979, 0x097f,
+ 0x0981, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fb,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a75,
+ 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, 0x0aef,
+ 0x0af1, 0x0af1,
+ 0x0b01, 0x0b03,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b35, 0x0b39,
+ 0x0b3c, 0x0b44,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4d,
+ 0x0b56, 0x0b57,
+ 0x0b5c, 0x0b5d,
+ 0x0b5f, 0x0b63,
+ 0x0b66, 0x0b71,
+ 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,
+ 0x0be6, 0x0bfa,
+ 0x0c01, 0x0c03,
+ 0x0c05, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c33,
+ 0x0c35, 0x0c39,
+ 0x0c3d, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c59,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c78, 0x0c7f,
+ 0x0c82, 0x0c83,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cde, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf2,
+ 0x0d02, 0x0d03,
+ 0x0d05, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d28,
+ 0x0d2a, 0x0d39,
+ 0x0d3d, 0x0d44,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4d,
+ 0x0d57, 0x0d57,
+ 0x0d60, 0x0d63,
+ 0x0d66, 0x0d75,
+ 0x0d79, 0x0d7f,
+ 0x0d82, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0df2, 0x0df4,
+ 0x0e01, 0x0e3a,
+ 0x0e3f, 0x0e5b,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e87, 0x0e88,
+ 0x0e8a, 0x0e8a,
+ 0x0e8d, 0x0e8d,
+ 0x0e94, 0x0e97,
+ 0x0e99, 0x0e9f,
+ 0x0ea1, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ea7,
+ 0x0eaa, 0x0eab,
+ 0x0ead, 0x0eb9,
+ 0x0ebb, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ecd,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edd,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f8b,
+ 0x0f90, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 0x0fbe, 0x0fcc,
+ 0x0fce, 0x0fd8,
+ 0x1000, 0x10c5,
+ 0x10d0, 0x10fc,
+ 0x1100, 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,
+ 0x135f, 0x137c,
+ 0x1380, 0x1399,
+ 0x13a0, 0x13f4,
+ 0x1400, 0x169c,
+ 0x16a0, 0x16f0,
+ 0x1700, 0x170c,
+ 0x170e, 0x1714,
+ 0x1720, 0x1736,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x1800, 0x180e,
+ 0x1810, 0x1819,
+ 0x1820, 0x1877,
+ 0x1880, 0x18aa,
+ 0x18b0, 0x18f5,
+ 0x1900, 0x191c,
+ 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,
+ 0x1b00, 0x1b4b,
+ 0x1b50, 0x1b7c,
+ 0x1b80, 0x1baa,
+ 0x1bae, 0x1bb9,
+ 0x1c00, 0x1c37,
+ 0x1c3b, 0x1c49,
+ 0x1c4d, 0x1c7f,
+ 0x1cd0, 0x1cf2,
+ 0x1d00, 0x1de6,
+ 0x1dfd, 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,
+ 0x206a, 0x2071,
+ 0x2074, 0x208e,
+ 0x2090, 0x2094,
+ 0x20a0, 0x20b8,
+ 0x20d0, 0x20f0,
+ 0x2100, 0x2189,
+ 0x2190, 0x23e8,
+ 0x2400, 0x2426,
+ 0x2440, 0x244a,
+ 0x2460, 0x26cd,
+ 0x26cf, 0x26e1,
+ 0x26e3, 0x26e3,
+ 0x26e8, 0x26ff,
+ 0x2701, 0x2704,
+ 0x2706, 0x2709,
+ 0x270c, 0x2727,
+ 0x2729, 0x274b,
+ 0x274d, 0x274d,
+ 0x274f, 0x2752,
+ 0x2756, 0x275e,
+ 0x2761, 0x2794,
+ 0x2798, 0x27af,
+ 0x27b1, 0x27be,
+ 0x27c0, 0x27ca,
+ 0x27cc, 0x27cc,
+ 0x27d0, 0x2b4c,
+ 0x2b50, 0x2b59,
+ 0x2c00, 0x2c2e,
+ 0x2c30, 0x2c5e,
+ 0x2c60, 0x2cf1,
+ 0x2cf9, 0x2d25,
+ 0x2d30, 0x2d65,
+ 0x2d6f, 0x2d6f,
+ 0x2d80, 0x2d96,
+ 0x2da0, 0x2da6,
+ 0x2da8, 0x2dae,
+ 0x2db0, 0x2db6,
+ 0x2db8, 0x2dbe,
+ 0x2dc0, 0x2dc6,
+ 0x2dc8, 0x2dce,
+ 0x2dd0, 0x2dd6,
+ 0x2dd8, 0x2dde,
+ 0x2de0, 0x2e31,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2ffb,
+ 0x3000, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312d,
+ 0x3131, 0x318e,
+ 0x3190, 0x31b7,
+ 0x31c0, 0x31e3,
+ 0x31f0, 0x321e,
+ 0x3220, 0x32fe,
+ 0x3300, 0x4db5,
+ 0x4dc0, 0x9fcb,
+ 0xa000, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa4d0, 0xa62b,
+ 0xa640, 0xa65f,
+ 0xa662, 0xa673,
+ 0xa67c, 0xa697,
+ 0xa6a0, 0xa6f7,
+ 0xa700, 0xa78c,
+ 0xa7fb, 0xa82b,
+ 0xa830, 0xa839,
+ 0xa840, 0xa877,
+ 0xa880, 0xa8c4,
+ 0xa8ce, 0xa8d9,
+ 0xa8e0, 0xa8fb,
+ 0xa900, 0xa953,
+ 0xa95f, 0xa97c,
+ 0xa980, 0xa9cd,
+ 0xa9cf, 0xa9d9,
+ 0xa9de, 0xa9df,
+ 0xaa00, 0xaa36,
+ 0xaa40, 0xaa4d,
+ 0xaa50, 0xaa59,
+ 0xaa5c, 0xaa7b,
+ 0xaa80, 0xaac2,
+ 0xaadb, 0xaadf,
+ 0xabc0, 0xabed,
+ 0xabf0, 0xabf9,
+ 0xac00, 0xd7a3,
+ 0xd7b0, 0xd7c6,
+ 0xd7cb, 0xd7fb,
+ 0xd800, 0xfa2d,
+ 0xfa30, 0xfa6d,
+ 0xfa70, 0xfad9,
+ 0xfb00, 0xfb06,
+ 0xfb13, 0xfb17,
+ 0xfb1d, 0xfb36,
+ 0xfb38, 0xfb3c,
+ 0xfb3e, 0xfb3e,
+ 0xfb40, 0xfb41,
+ 0xfb43, 0xfb44,
+ 0xfb46, 0xfbb1,
+ 0xfbd3, 0xfd3f,
+ 0xfd50, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdd0, 0xfdfd,
+ 0xfe00, 0xfe19,
+ 0xfe20, 0xfe26,
+ 0xfe30, 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, 0x1018a,
+ 0x10190, 0x1019b,
+ 0x101d0, 0x101fd,
+ 0x10280, 0x1029c,
+ 0x102a0, 0x102d0,
+ 0x10300, 0x1031e,
+ 0x10320, 0x10323,
+ 0x10330, 0x1034a,
+ 0x10380, 0x1039d,
+ 0x1039f, 0x103c3,
+ 0x103c8, 0x103d5,
+ 0x10400, 0x1049d,
+ 0x104a0, 0x104a9,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 0x10837, 0x10838,
+ 0x1083c, 0x1083c,
+ 0x1083f, 0x10855,
+ 0x10857, 0x1085f,
+ 0x10900, 0x1091b,
+ 0x1091f, 0x10939,
+ 0x1093f, 0x1093f,
+ 0x10a00, 0x10a03,
+ 0x10a05, 0x10a06,
+ 0x10a0c, 0x10a13,
+ 0x10a15, 0x10a17,
+ 0x10a19, 0x10a33,
+ 0x10a38, 0x10a3a,
+ 0x10a3f, 0x10a47,
+ 0x10a50, 0x10a58,
+ 0x10a60, 0x10a7f,
+ 0x10b00, 0x10b35,
+ 0x10b39, 0x10b55,
+ 0x10b58, 0x10b72,
+ 0x10b78, 0x10b7f,
+ 0x10c00, 0x10c48,
+ 0x10e60, 0x10e7e,
+ 0x11080, 0x110c1,
+ 0x12000, 0x1236e,
+ 0x12400, 0x12462,
+ 0x12470, 0x12473,
+ 0x13000, 0x1342e,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d129, 0x1d1dd,
+ 0x1d200, 0x1d245,
+ 0x1d300, 0x1d356,
+ 0x1d360, 0x1d371,
+ 0x1d400, 0x1d454,
+ 0x1d456, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 0x1d4a2, 0x1d4a2,
+ 0x1d4a5, 0x1d4a6,
+ 0x1d4a9, 0x1d4ac,
+ 0x1d4ae, 0x1d4b9,
+ 0x1d4bb, 0x1d4bb,
+ 0x1d4bd, 0x1d4c3,
+ 0x1d4c5, 0x1d505,
+ 0x1d507, 0x1d50a,
+ 0x1d50d, 0x1d514,
+ 0x1d516, 0x1d51c,
+ 0x1d51e, 0x1d539,
+ 0x1d53b, 0x1d53e,
+ 0x1d540, 0x1d544,
+ 0x1d546, 0x1d546,
+ 0x1d54a, 0x1d550,
+ 0x1d552, 0x1d6a5,
+ 0x1d6a8, 0x1d7cb,
+ 0x1d7ce, 0x1d7ff,
+ 0x1f000, 0x1f02b,
+ 0x1f030, 0x1f093,
+ 0x1f100, 0x1f10a,
+ 0x1f110, 0x1f12e,
+ 0x1f131, 0x1f131,
+ 0x1f13d, 0x1f13d,
+ 0x1f13f, 0x1f13f,
+ 0x1f142, 0x1f142,
+ 0x1f146, 0x1f146,
+ 0x1f14a, 0x1f14e,
+ 0x1f157, 0x1f157,
+ 0x1f15f, 0x1f15f,
+ 0x1f179, 0x1f179,
+ 0x1f17b, 0x1f17c,
+ 0x1f17f, 0x1f17f,
+ 0x1f18a, 0x1f18d,
+ 0x1f190, 0x1f190,
+ 0x1f200, 0x1f200,
+ 0x1f210, 0x1f231,
+ 0x1f240, 0x1f248,
+ 0x1fffe, 0x2a6d6,
+ 0x2a700, 0x2b734,
+ 0x2f800, 0x2fa1d,
+ 0x2fffe, 0x2ffff,
+ 0x3fffe, 0x3ffff,
+ 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_5_2 */
+
+/* 'Age_6_0': Derived Age 6.0 */
+static const OnigCodePoint CR_Age_6_0[] = {
+ 511,
+ 0x0000, 0x0377,
+ 0x037a, 0x037e,
+ 0x0384, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x0527,
+ 0x0531, 0x0556,
+ 0x0559, 0x055f,
+ 0x0561, 0x0587,
+ 0x0589, 0x058a,
+ 0x0591, 0x05c7,
+ 0x05d0, 0x05ea,
+ 0x05f0, 0x05f4,
+ 0x0600, 0x0603,
+ 0x0606, 0x061b,
+ 0x061e, 0x070d,
+ 0x070f, 0x074a,
+ 0x074d, 0x07b1,
+ 0x07c0, 0x07fa,
+ 0x0800, 0x082d,
+ 0x0830, 0x083e,
+ 0x0840, 0x085b,
+ 0x085e, 0x085e,
+ 0x0900, 0x0977,
+ 0x0979, 0x097f,
+ 0x0981, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fb,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a75,
+ 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, 0x0aef,
+ 0x0af1, 0x0af1,
+ 0x0b01, 0x0b03,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b35, 0x0b39,
+ 0x0b3c, 0x0b44,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4d,
+ 0x0b56, 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,
+ 0x0be6, 0x0bfa,
+ 0x0c01, 0x0c03,
+ 0x0c05, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c33,
+ 0x0c35, 0x0c39,
+ 0x0c3d, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c59,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c78, 0x0c7f,
+ 0x0c82, 0x0c83,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cde, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf2,
+ 0x0d02, 0x0d03,
+ 0x0d05, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d3a,
+ 0x0d3d, 0x0d44,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4e,
+ 0x0d57, 0x0d57,
+ 0x0d60, 0x0d63,
+ 0x0d66, 0x0d75,
+ 0x0d79, 0x0d7f,
+ 0x0d82, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0df2, 0x0df4,
+ 0x0e01, 0x0e3a,
+ 0x0e3f, 0x0e5b,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e87, 0x0e88,
+ 0x0e8a, 0x0e8a,
+ 0x0e8d, 0x0e8d,
+ 0x0e94, 0x0e97,
+ 0x0e99, 0x0e9f,
+ 0x0ea1, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ea7,
+ 0x0eaa, 0x0eab,
+ 0x0ead, 0x0eb9,
+ 0x0ebb, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ecd,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edd,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 0x0fbe, 0x0fcc,
+ 0x0fce, 0x0fda,
+ 0x1000, 0x10c5,
+ 0x10d0, 0x10fc,
+ 0x1100, 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, 0x13f4,
+ 0x1400, 0x169c,
+ 0x16a0, 0x16f0,
+ 0x1700, 0x170c,
+ 0x170e, 0x1714,
+ 0x1720, 0x1736,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x1800, 0x180e,
+ 0x1810, 0x1819,
+ 0x1820, 0x1877,
+ 0x1880, 0x18aa,
+ 0x18b0, 0x18f5,
+ 0x1900, 0x191c,
+ 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,
+ 0x1b00, 0x1b4b,
+ 0x1b50, 0x1b7c,
+ 0x1b80, 0x1baa,
+ 0x1bae, 0x1bb9,
+ 0x1bc0, 0x1bf3,
+ 0x1bfc, 0x1c37,
+ 0x1c3b, 0x1c49,
+ 0x1c4d, 0x1c7f,
+ 0x1cd0, 0x1cf2,
+ 0x1d00, 0x1de6,
+ 0x1dfc, 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,
+ 0x206a, 0x2071,
+ 0x2074, 0x208e,
+ 0x2090, 0x209c,
+ 0x20a0, 0x20b9,
+ 0x20d0, 0x20f0,
+ 0x2100, 0x2189,
+ 0x2190, 0x23f3,
+ 0x2400, 0x2426,
+ 0x2440, 0x244a,
+ 0x2460, 0x26ff,
+ 0x2701, 0x27ca,
+ 0x27cc, 0x27cc,
+ 0x27ce, 0x2b4c,
+ 0x2b50, 0x2b59,
+ 0x2c00, 0x2c2e,
+ 0x2c30, 0x2c5e,
+ 0x2c60, 0x2cf1,
+ 0x2cf9, 0x2d25,
+ 0x2d30, 0x2d65,
+ 0x2d6f, 0x2d70,
+ 0x2d7f, 0x2d96,
+ 0x2da0, 0x2da6,
+ 0x2da8, 0x2dae,
+ 0x2db0, 0x2db6,
+ 0x2db8, 0x2dbe,
+ 0x2dc0, 0x2dc6,
+ 0x2dc8, 0x2dce,
+ 0x2dd0, 0x2dd6,
+ 0x2dd8, 0x2dde,
+ 0x2de0, 0x2e31,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2ffb,
+ 0x3000, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312d,
+ 0x3131, 0x318e,
+ 0x3190, 0x31ba,
+ 0x31c0, 0x31e3,
+ 0x31f0, 0x321e,
+ 0x3220, 0x32fe,
+ 0x3300, 0x4db5,
+ 0x4dc0, 0x9fcb,
+ 0xa000, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa4d0, 0xa62b,
+ 0xa640, 0xa673,
+ 0xa67c, 0xa697,
+ 0xa6a0, 0xa6f7,
+ 0xa700, 0xa78e,
+ 0xa790, 0xa791,
+ 0xa7a0, 0xa7a9,
+ 0xa7fa, 0xa82b,
+ 0xa830, 0xa839,
+ 0xa840, 0xa877,
+ 0xa880, 0xa8c4,
+ 0xa8ce, 0xa8d9,
+ 0xa8e0, 0xa8fb,
+ 0xa900, 0xa953,
+ 0xa95f, 0xa97c,
+ 0xa980, 0xa9cd,
+ 0xa9cf, 0xa9d9,
+ 0xa9de, 0xa9df,
+ 0xaa00, 0xaa36,
+ 0xaa40, 0xaa4d,
+ 0xaa50, 0xaa59,
+ 0xaa5c, 0xaa7b,
+ 0xaa80, 0xaac2,
+ 0xaadb, 0xaadf,
+ 0xab01, 0xab06,
+ 0xab09, 0xab0e,
+ 0xab11, 0xab16,
+ 0xab20, 0xab26,
+ 0xab28, 0xab2e,
+ 0xabc0, 0xabed,
+ 0xabf0, 0xabf9,
+ 0xac00, 0xd7a3,
+ 0xd7b0, 0xd7c6,
+ 0xd7cb, 0xd7fb,
+ 0xd800, 0xfa2d,
+ 0xfa30, 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, 0xfe26,
+ 0xfe30, 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, 0x1018a,
+ 0x10190, 0x1019b,
+ 0x101d0, 0x101fd,
+ 0x10280, 0x1029c,
+ 0x102a0, 0x102d0,
+ 0x10300, 0x1031e,
+ 0x10320, 0x10323,
+ 0x10330, 0x1034a,
+ 0x10380, 0x1039d,
+ 0x1039f, 0x103c3,
+ 0x103c8, 0x103d5,
+ 0x10400, 0x1049d,
+ 0x104a0, 0x104a9,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 0x10837, 0x10838,
+ 0x1083c, 0x1083c,
+ 0x1083f, 0x10855,
+ 0x10857, 0x1085f,
+ 0x10900, 0x1091b,
+ 0x1091f, 0x10939,
+ 0x1093f, 0x1093f,
+ 0x10a00, 0x10a03,
+ 0x10a05, 0x10a06,
+ 0x10a0c, 0x10a13,
+ 0x10a15, 0x10a17,
+ 0x10a19, 0x10a33,
+ 0x10a38, 0x10a3a,
+ 0x10a3f, 0x10a47,
+ 0x10a50, 0x10a58,
+ 0x10a60, 0x10a7f,
+ 0x10b00, 0x10b35,
+ 0x10b39, 0x10b55,
+ 0x10b58, 0x10b72,
+ 0x10b78, 0x10b7f,
+ 0x10c00, 0x10c48,
+ 0x10e60, 0x10e7e,
+ 0x11000, 0x1104d,
+ 0x11052, 0x1106f,
+ 0x11080, 0x110c1,
+ 0x12000, 0x1236e,
+ 0x12400, 0x12462,
+ 0x12470, 0x12473,
+ 0x13000, 0x1342e,
+ 0x16800, 0x16a38,
+ 0x1b000, 0x1b001,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d129, 0x1d1dd,
+ 0x1d200, 0x1d245,
+ 0x1d300, 0x1d356,
+ 0x1d360, 0x1d371,
+ 0x1d400, 0x1d454,
+ 0x1d456, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 0x1d4a2, 0x1d4a2,
+ 0x1d4a5, 0x1d4a6,
+ 0x1d4a9, 0x1d4ac,
+ 0x1d4ae, 0x1d4b9,
+ 0x1d4bb, 0x1d4bb,
+ 0x1d4bd, 0x1d4c3,
+ 0x1d4c5, 0x1d505,
+ 0x1d507, 0x1d50a,
+ 0x1d50d, 0x1d514,
+ 0x1d516, 0x1d51c,
+ 0x1d51e, 0x1d539,
+ 0x1d53b, 0x1d53e,
+ 0x1d540, 0x1d544,
+ 0x1d546, 0x1d546,
+ 0x1d54a, 0x1d550,
+ 0x1d552, 0x1d6a5,
+ 0x1d6a8, 0x1d7cb,
+ 0x1d7ce, 0x1d7ff,
+ 0x1f000, 0x1f02b,
+ 0x1f030, 0x1f093,
+ 0x1f0a0, 0x1f0ae,
+ 0x1f0b1, 0x1f0be,
+ 0x1f0c1, 0x1f0cf,
+ 0x1f0d1, 0x1f0df,
+ 0x1f100, 0x1f10a,
+ 0x1f110, 0x1f12e,
+ 0x1f130, 0x1f169,
+ 0x1f170, 0x1f19a,
+ 0x1f1e6, 0x1f202,
+ 0x1f210, 0x1f23a,
+ 0x1f240, 0x1f248,
+ 0x1f250, 0x1f251,
+ 0x1f300, 0x1f320,
+ 0x1f330, 0x1f335,
+ 0x1f337, 0x1f37c,
+ 0x1f380, 0x1f393,
+ 0x1f3a0, 0x1f3c4,
+ 0x1f3c6, 0x1f3ca,
+ 0x1f3e0, 0x1f3f0,
+ 0x1f400, 0x1f43e,
+ 0x1f440, 0x1f440,
+ 0x1f442, 0x1f4f7,
+ 0x1f4f9, 0x1f4fc,
+ 0x1f500, 0x1f53d,
+ 0x1f550, 0x1f567,
+ 0x1f5fb, 0x1f5ff,
+ 0x1f601, 0x1f610,
+ 0x1f612, 0x1f614,
+ 0x1f616, 0x1f616,
+ 0x1f618, 0x1f618,
+ 0x1f61a, 0x1f61a,
+ 0x1f61c, 0x1f61e,
+ 0x1f620, 0x1f625,
+ 0x1f628, 0x1f62b,
+ 0x1f62d, 0x1f62d,
+ 0x1f630, 0x1f633,
+ 0x1f635, 0x1f640,
+ 0x1f645, 0x1f64f,
+ 0x1f680, 0x1f6c5,
+ 0x1f700, 0x1f773,
+ 0x1fffe, 0x2a6d6,
+ 0x2a700, 0x2b734,
+ 0x2b740, 0x2b81d,
+ 0x2f800, 0x2fa1d,
+ 0x2fffe, 0x2ffff,
+ 0x3fffe, 0x3ffff,
+ 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_6_0 */
+
+/* 'Age_6_1': Derived Age 6.1 */
+static const OnigCodePoint CR_Age_6_1[] = {
+ 549,
+ 0x0000, 0x0377,
+ 0x037a, 0x037e,
+ 0x0384, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x0527,
+ 0x0531, 0x0556,
+ 0x0559, 0x055f,
+ 0x0561, 0x0587,
+ 0x0589, 0x058a,
+ 0x058f, 0x058f,
+ 0x0591, 0x05c7,
+ 0x05d0, 0x05ea,
+ 0x05f0, 0x05f4,
+ 0x0600, 0x0604,
+ 0x0606, 0x061b,
+ 0x061e, 0x070d,
+ 0x070f, 0x074a,
+ 0x074d, 0x07b1,
+ 0x07c0, 0x07fa,
+ 0x0800, 0x082d,
+ 0x0830, 0x083e,
+ 0x0840, 0x085b,
+ 0x085e, 0x085e,
+ 0x08a0, 0x08a0,
+ 0x08a2, 0x08ac,
+ 0x08e4, 0x08fe,
+ 0x0900, 0x0977,
+ 0x0979, 0x097f,
+ 0x0981, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fb,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a75,
+ 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,
+ 0x0b01, 0x0b03,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b35, 0x0b39,
+ 0x0b3c, 0x0b44,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4d,
+ 0x0b56, 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,
+ 0x0be6, 0x0bfa,
+ 0x0c01, 0x0c03,
+ 0x0c05, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c33,
+ 0x0c35, 0x0c39,
+ 0x0c3d, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c59,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c78, 0x0c7f,
+ 0x0c82, 0x0c83,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cde, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf2,
+ 0x0d02, 0x0d03,
+ 0x0d05, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d3a,
+ 0x0d3d, 0x0d44,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4e,
+ 0x0d57, 0x0d57,
+ 0x0d60, 0x0d63,
+ 0x0d66, 0x0d75,
+ 0x0d79, 0x0d7f,
+ 0x0d82, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0df2, 0x0df4,
+ 0x0e01, 0x0e3a,
+ 0x0e3f, 0x0e5b,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e87, 0x0e88,
+ 0x0e8a, 0x0e8a,
+ 0x0e8d, 0x0e8d,
+ 0x0e94, 0x0e97,
+ 0x0e99, 0x0e9f,
+ 0x0ea1, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ea7,
+ 0x0eaa, 0x0eab,
+ 0x0ead, 0x0eb9,
+ 0x0ebb, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ecd,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 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, 0x13f4,
+ 0x1400, 0x169c,
+ 0x16a0, 0x16f0,
+ 0x1700, 0x170c,
+ 0x170e, 0x1714,
+ 0x1720, 0x1736,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x1800, 0x180e,
+ 0x1810, 0x1819,
+ 0x1820, 0x1877,
+ 0x1880, 0x18aa,
+ 0x18b0, 0x18f5,
+ 0x1900, 0x191c,
+ 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,
+ 0x1b00, 0x1b4b,
+ 0x1b50, 0x1b7c,
+ 0x1b80, 0x1bf3,
+ 0x1bfc, 0x1c37,
+ 0x1c3b, 0x1c49,
+ 0x1c4d, 0x1c7f,
+ 0x1cc0, 0x1cc7,
+ 0x1cd0, 0x1cf6,
+ 0x1d00, 0x1de6,
+ 0x1dfc, 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,
+ 0x206a, 0x2071,
+ 0x2074, 0x208e,
+ 0x2090, 0x209c,
+ 0x20a0, 0x20b9,
+ 0x20d0, 0x20f0,
+ 0x2100, 0x2189,
+ 0x2190, 0x23f3,
+ 0x2400, 0x2426,
+ 0x2440, 0x244a,
+ 0x2460, 0x26ff,
+ 0x2701, 0x2b4c,
+ 0x2b50, 0x2b59,
+ 0x2c00, 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, 0x2e3b,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2ffb,
+ 0x3000, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312d,
+ 0x3131, 0x318e,
+ 0x3190, 0x31ba,
+ 0x31c0, 0x31e3,
+ 0x31f0, 0x321e,
+ 0x3220, 0x32fe,
+ 0x3300, 0x4db5,
+ 0x4dc0, 0x9fcc,
+ 0xa000, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa4d0, 0xa62b,
+ 0xa640, 0xa697,
+ 0xa69f, 0xa6f7,
+ 0xa700, 0xa78e,
+ 0xa790, 0xa793,
+ 0xa7a0, 0xa7aa,
+ 0xa7f8, 0xa82b,
+ 0xa830, 0xa839,
+ 0xa840, 0xa877,
+ 0xa880, 0xa8c4,
+ 0xa8ce, 0xa8d9,
+ 0xa8e0, 0xa8fb,
+ 0xa900, 0xa953,
+ 0xa95f, 0xa97c,
+ 0xa980, 0xa9cd,
+ 0xa9cf, 0xa9d9,
+ 0xa9de, 0xa9df,
+ 0xaa00, 0xaa36,
+ 0xaa40, 0xaa4d,
+ 0xaa50, 0xaa59,
+ 0xaa5c, 0xaa7b,
+ 0xaa80, 0xaac2,
+ 0xaadb, 0xaaf6,
+ 0xab01, 0xab06,
+ 0xab09, 0xab0e,
+ 0xab11, 0xab16,
+ 0xab20, 0xab26,
+ 0xab28, 0xab2e,
+ 0xabc0, 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, 0xfe26,
+ 0xfe30, 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, 0x1018a,
+ 0x10190, 0x1019b,
+ 0x101d0, 0x101fd,
+ 0x10280, 0x1029c,
+ 0x102a0, 0x102d0,
+ 0x10300, 0x1031e,
+ 0x10320, 0x10323,
+ 0x10330, 0x1034a,
+ 0x10380, 0x1039d,
+ 0x1039f, 0x103c3,
+ 0x103c8, 0x103d5,
+ 0x10400, 0x1049d,
+ 0x104a0, 0x104a9,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 0x10837, 0x10838,
+ 0x1083c, 0x1083c,
+ 0x1083f, 0x10855,
+ 0x10857, 0x1085f,
+ 0x10900, 0x1091b,
+ 0x1091f, 0x10939,
+ 0x1093f, 0x1093f,
+ 0x10980, 0x109b7,
+ 0x109be, 0x109bf,
+ 0x10a00, 0x10a03,
+ 0x10a05, 0x10a06,
+ 0x10a0c, 0x10a13,
+ 0x10a15, 0x10a17,
+ 0x10a19, 0x10a33,
+ 0x10a38, 0x10a3a,
+ 0x10a3f, 0x10a47,
+ 0x10a50, 0x10a58,
+ 0x10a60, 0x10a7f,
+ 0x10b00, 0x10b35,
+ 0x10b39, 0x10b55,
+ 0x10b58, 0x10b72,
+ 0x10b78, 0x10b7f,
+ 0x10c00, 0x10c48,
+ 0x10e60, 0x10e7e,
+ 0x11000, 0x1104d,
+ 0x11052, 0x1106f,
+ 0x11080, 0x110c1,
+ 0x110d0, 0x110e8,
+ 0x110f0, 0x110f9,
+ 0x11100, 0x11134,
+ 0x11136, 0x11143,
+ 0x11180, 0x111c8,
+ 0x111d0, 0x111d9,
+ 0x11680, 0x116b7,
+ 0x116c0, 0x116c9,
+ 0x12000, 0x1236e,
+ 0x12400, 0x12462,
+ 0x12470, 0x12473,
+ 0x13000, 0x1342e,
+ 0x16800, 0x16a38,
+ 0x16f00, 0x16f44,
+ 0x16f50, 0x16f7e,
+ 0x16f8f, 0x16f9f,
+ 0x1b000, 0x1b001,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d129, 0x1d1dd,
+ 0x1d200, 0x1d245,
+ 0x1d300, 0x1d356,
+ 0x1d360, 0x1d371,
+ 0x1d400, 0x1d454,
+ 0x1d456, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 0x1d4a2, 0x1d4a2,
+ 0x1d4a5, 0x1d4a6,
+ 0x1d4a9, 0x1d4ac,
+ 0x1d4ae, 0x1d4b9,
+ 0x1d4bb, 0x1d4bb,
+ 0x1d4bd, 0x1d4c3,
+ 0x1d4c5, 0x1d505,
+ 0x1d507, 0x1d50a,
+ 0x1d50d, 0x1d514,
+ 0x1d516, 0x1d51c,
+ 0x1d51e, 0x1d539,
+ 0x1d53b, 0x1d53e,
+ 0x1d540, 0x1d544,
+ 0x1d546, 0x1d546,
+ 0x1d54a, 0x1d550,
+ 0x1d552, 0x1d6a5,
+ 0x1d6a8, 0x1d7cb,
+ 0x1d7ce, 0x1d7ff,
+ 0x1ee00, 0x1ee03,
+ 0x1ee05, 0x1ee1f,
+ 0x1ee21, 0x1ee22,
+ 0x1ee24, 0x1ee24,
+ 0x1ee27, 0x1ee27,
+ 0x1ee29, 0x1ee32,
+ 0x1ee34, 0x1ee37,
+ 0x1ee39, 0x1ee39,
+ 0x1ee3b, 0x1ee3b,
+ 0x1ee42, 0x1ee42,
+ 0x1ee47, 0x1ee47,
+ 0x1ee49, 0x1ee49,
+ 0x1ee4b, 0x1ee4b,
+ 0x1ee4d, 0x1ee4f,
+ 0x1ee51, 0x1ee52,
+ 0x1ee54, 0x1ee54,
+ 0x1ee57, 0x1ee57,
+ 0x1ee59, 0x1ee59,
+ 0x1ee5b, 0x1ee5b,
+ 0x1ee5d, 0x1ee5d,
+ 0x1ee5f, 0x1ee5f,
+ 0x1ee61, 0x1ee62,
+ 0x1ee64, 0x1ee64,
+ 0x1ee67, 0x1ee6a,
+ 0x1ee6c, 0x1ee72,
+ 0x1ee74, 0x1ee77,
+ 0x1ee79, 0x1ee7c,
+ 0x1ee7e, 0x1ee7e,
+ 0x1ee80, 0x1ee89,
+ 0x1ee8b, 0x1ee9b,
+ 0x1eea1, 0x1eea3,
+ 0x1eea5, 0x1eea9,
+ 0x1eeab, 0x1eebb,
+ 0x1eef0, 0x1eef1,
+ 0x1f000, 0x1f02b,
+ 0x1f030, 0x1f093,
+ 0x1f0a0, 0x1f0ae,
+ 0x1f0b1, 0x1f0be,
+ 0x1f0c1, 0x1f0cf,
+ 0x1f0d1, 0x1f0df,
+ 0x1f100, 0x1f10a,
+ 0x1f110, 0x1f12e,
+ 0x1f130, 0x1f16b,
+ 0x1f170, 0x1f19a,
+ 0x1f1e6, 0x1f202,
+ 0x1f210, 0x1f23a,
+ 0x1f240, 0x1f248,
+ 0x1f250, 0x1f251,
+ 0x1f300, 0x1f320,
+ 0x1f330, 0x1f335,
+ 0x1f337, 0x1f37c,
+ 0x1f380, 0x1f393,
+ 0x1f3a0, 0x1f3c4,
+ 0x1f3c6, 0x1f3ca,
+ 0x1f3e0, 0x1f3f0,
+ 0x1f400, 0x1f43e,
+ 0x1f440, 0x1f440,
+ 0x1f442, 0x1f4f7,
+ 0x1f4f9, 0x1f4fc,
+ 0x1f500, 0x1f53d,
+ 0x1f540, 0x1f543,
+ 0x1f550, 0x1f567,
+ 0x1f5fb, 0x1f640,
+ 0x1f645, 0x1f64f,
+ 0x1f680, 0x1f6c5,
+ 0x1f700, 0x1f773,
+ 0x1fffe, 0x2a6d6,
+ 0x2a700, 0x2b734,
+ 0x2b740, 0x2b81d,
+ 0x2f800, 0x2fa1d,
+ 0x2fffe, 0x2ffff,
+ 0x3fffe, 0x3ffff,
+ 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_6_1 */
+
+/* 'Age_6_2': Derived Age 6.2 */
+static const OnigCodePoint CR_Age_6_2[] = {
+ 549,
+ 0x0000, 0x0377,
+ 0x037a, 0x037e,
+ 0x0384, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x0527,
+ 0x0531, 0x0556,
+ 0x0559, 0x055f,
+ 0x0561, 0x0587,
+ 0x0589, 0x058a,
+ 0x058f, 0x058f,
+ 0x0591, 0x05c7,
+ 0x05d0, 0x05ea,
+ 0x05f0, 0x05f4,
+ 0x0600, 0x0604,
+ 0x0606, 0x061b,
+ 0x061e, 0x070d,
+ 0x070f, 0x074a,
+ 0x074d, 0x07b1,
+ 0x07c0, 0x07fa,
+ 0x0800, 0x082d,
+ 0x0830, 0x083e,
+ 0x0840, 0x085b,
+ 0x085e, 0x085e,
+ 0x08a0, 0x08a0,
+ 0x08a2, 0x08ac,
+ 0x08e4, 0x08fe,
+ 0x0900, 0x0977,
+ 0x0979, 0x097f,
+ 0x0981, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fb,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a75,
+ 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,
+ 0x0b01, 0x0b03,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b35, 0x0b39,
+ 0x0b3c, 0x0b44,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4d,
+ 0x0b56, 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,
+ 0x0be6, 0x0bfa,
+ 0x0c01, 0x0c03,
+ 0x0c05, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c33,
+ 0x0c35, 0x0c39,
+ 0x0c3d, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c59,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c78, 0x0c7f,
+ 0x0c82, 0x0c83,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cde, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf2,
+ 0x0d02, 0x0d03,
+ 0x0d05, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d3a,
+ 0x0d3d, 0x0d44,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4e,
+ 0x0d57, 0x0d57,
+ 0x0d60, 0x0d63,
+ 0x0d66, 0x0d75,
+ 0x0d79, 0x0d7f,
+ 0x0d82, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0df2, 0x0df4,
+ 0x0e01, 0x0e3a,
+ 0x0e3f, 0x0e5b,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e87, 0x0e88,
+ 0x0e8a, 0x0e8a,
+ 0x0e8d, 0x0e8d,
+ 0x0e94, 0x0e97,
+ 0x0e99, 0x0e9f,
+ 0x0ea1, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ea7,
+ 0x0eaa, 0x0eab,
+ 0x0ead, 0x0eb9,
+ 0x0ebb, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ecd,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 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, 0x13f4,
+ 0x1400, 0x169c,
+ 0x16a0, 0x16f0,
+ 0x1700, 0x170c,
+ 0x170e, 0x1714,
+ 0x1720, 0x1736,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x1800, 0x180e,
+ 0x1810, 0x1819,
+ 0x1820, 0x1877,
+ 0x1880, 0x18aa,
+ 0x18b0, 0x18f5,
+ 0x1900, 0x191c,
+ 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,
+ 0x1b00, 0x1b4b,
+ 0x1b50, 0x1b7c,
+ 0x1b80, 0x1bf3,
+ 0x1bfc, 0x1c37,
+ 0x1c3b, 0x1c49,
+ 0x1c4d, 0x1c7f,
+ 0x1cc0, 0x1cc7,
+ 0x1cd0, 0x1cf6,
+ 0x1d00, 0x1de6,
+ 0x1dfc, 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,
+ 0x206a, 0x2071,
+ 0x2074, 0x208e,
+ 0x2090, 0x209c,
+ 0x20a0, 0x20ba,
+ 0x20d0, 0x20f0,
+ 0x2100, 0x2189,
+ 0x2190, 0x23f3,
+ 0x2400, 0x2426,
+ 0x2440, 0x244a,
+ 0x2460, 0x26ff,
+ 0x2701, 0x2b4c,
+ 0x2b50, 0x2b59,
+ 0x2c00, 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, 0x2e3b,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2ffb,
+ 0x3000, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312d,
+ 0x3131, 0x318e,
+ 0x3190, 0x31ba,
+ 0x31c0, 0x31e3,
+ 0x31f0, 0x321e,
+ 0x3220, 0x32fe,
+ 0x3300, 0x4db5,
+ 0x4dc0, 0x9fcc,
+ 0xa000, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa4d0, 0xa62b,
+ 0xa640, 0xa697,
+ 0xa69f, 0xa6f7,
+ 0xa700, 0xa78e,
+ 0xa790, 0xa793,
+ 0xa7a0, 0xa7aa,
+ 0xa7f8, 0xa82b,
+ 0xa830, 0xa839,
+ 0xa840, 0xa877,
+ 0xa880, 0xa8c4,
+ 0xa8ce, 0xa8d9,
+ 0xa8e0, 0xa8fb,
+ 0xa900, 0xa953,
+ 0xa95f, 0xa97c,
+ 0xa980, 0xa9cd,
+ 0xa9cf, 0xa9d9,
+ 0xa9de, 0xa9df,
+ 0xaa00, 0xaa36,
+ 0xaa40, 0xaa4d,
+ 0xaa50, 0xaa59,
+ 0xaa5c, 0xaa7b,
+ 0xaa80, 0xaac2,
+ 0xaadb, 0xaaf6,
+ 0xab01, 0xab06,
+ 0xab09, 0xab0e,
+ 0xab11, 0xab16,
+ 0xab20, 0xab26,
+ 0xab28, 0xab2e,
+ 0xabc0, 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, 0xfe26,
+ 0xfe30, 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, 0x1018a,
+ 0x10190, 0x1019b,
+ 0x101d0, 0x101fd,
+ 0x10280, 0x1029c,
+ 0x102a0, 0x102d0,
+ 0x10300, 0x1031e,
+ 0x10320, 0x10323,
+ 0x10330, 0x1034a,
+ 0x10380, 0x1039d,
+ 0x1039f, 0x103c3,
+ 0x103c8, 0x103d5,
+ 0x10400, 0x1049d,
+ 0x104a0, 0x104a9,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 0x10837, 0x10838,
+ 0x1083c, 0x1083c,
+ 0x1083f, 0x10855,
+ 0x10857, 0x1085f,
+ 0x10900, 0x1091b,
+ 0x1091f, 0x10939,
+ 0x1093f, 0x1093f,
+ 0x10980, 0x109b7,
+ 0x109be, 0x109bf,
+ 0x10a00, 0x10a03,
+ 0x10a05, 0x10a06,
+ 0x10a0c, 0x10a13,
+ 0x10a15, 0x10a17,
+ 0x10a19, 0x10a33,
+ 0x10a38, 0x10a3a,
+ 0x10a3f, 0x10a47,
+ 0x10a50, 0x10a58,
+ 0x10a60, 0x10a7f,
+ 0x10b00, 0x10b35,
+ 0x10b39, 0x10b55,
+ 0x10b58, 0x10b72,
+ 0x10b78, 0x10b7f,
+ 0x10c00, 0x10c48,
+ 0x10e60, 0x10e7e,
+ 0x11000, 0x1104d,
+ 0x11052, 0x1106f,
+ 0x11080, 0x110c1,
+ 0x110d0, 0x110e8,
+ 0x110f0, 0x110f9,
+ 0x11100, 0x11134,
+ 0x11136, 0x11143,
+ 0x11180, 0x111c8,
+ 0x111d0, 0x111d9,
+ 0x11680, 0x116b7,
+ 0x116c0, 0x116c9,
+ 0x12000, 0x1236e,
+ 0x12400, 0x12462,
+ 0x12470, 0x12473,
+ 0x13000, 0x1342e,
+ 0x16800, 0x16a38,
+ 0x16f00, 0x16f44,
+ 0x16f50, 0x16f7e,
+ 0x16f8f, 0x16f9f,
+ 0x1b000, 0x1b001,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d129, 0x1d1dd,
+ 0x1d200, 0x1d245,
+ 0x1d300, 0x1d356,
+ 0x1d360, 0x1d371,
+ 0x1d400, 0x1d454,
+ 0x1d456, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 0x1d4a2, 0x1d4a2,
+ 0x1d4a5, 0x1d4a6,
+ 0x1d4a9, 0x1d4ac,
+ 0x1d4ae, 0x1d4b9,
+ 0x1d4bb, 0x1d4bb,
+ 0x1d4bd, 0x1d4c3,
+ 0x1d4c5, 0x1d505,
+ 0x1d507, 0x1d50a,
+ 0x1d50d, 0x1d514,
+ 0x1d516, 0x1d51c,
+ 0x1d51e, 0x1d539,
+ 0x1d53b, 0x1d53e,
+ 0x1d540, 0x1d544,
+ 0x1d546, 0x1d546,
+ 0x1d54a, 0x1d550,
+ 0x1d552, 0x1d6a5,
+ 0x1d6a8, 0x1d7cb,
+ 0x1d7ce, 0x1d7ff,
+ 0x1ee00, 0x1ee03,
+ 0x1ee05, 0x1ee1f,
+ 0x1ee21, 0x1ee22,
+ 0x1ee24, 0x1ee24,
+ 0x1ee27, 0x1ee27,
+ 0x1ee29, 0x1ee32,
+ 0x1ee34, 0x1ee37,
+ 0x1ee39, 0x1ee39,
+ 0x1ee3b, 0x1ee3b,
+ 0x1ee42, 0x1ee42,
+ 0x1ee47, 0x1ee47,
+ 0x1ee49, 0x1ee49,
+ 0x1ee4b, 0x1ee4b,
+ 0x1ee4d, 0x1ee4f,
+ 0x1ee51, 0x1ee52,
+ 0x1ee54, 0x1ee54,
+ 0x1ee57, 0x1ee57,
+ 0x1ee59, 0x1ee59,
+ 0x1ee5b, 0x1ee5b,
+ 0x1ee5d, 0x1ee5d,
+ 0x1ee5f, 0x1ee5f,
+ 0x1ee61, 0x1ee62,
+ 0x1ee64, 0x1ee64,
+ 0x1ee67, 0x1ee6a,
+ 0x1ee6c, 0x1ee72,
+ 0x1ee74, 0x1ee77,
+ 0x1ee79, 0x1ee7c,
+ 0x1ee7e, 0x1ee7e,
+ 0x1ee80, 0x1ee89,
+ 0x1ee8b, 0x1ee9b,
+ 0x1eea1, 0x1eea3,
+ 0x1eea5, 0x1eea9,
+ 0x1eeab, 0x1eebb,
+ 0x1eef0, 0x1eef1,
+ 0x1f000, 0x1f02b,
+ 0x1f030, 0x1f093,
+ 0x1f0a0, 0x1f0ae,
+ 0x1f0b1, 0x1f0be,
+ 0x1f0c1, 0x1f0cf,
+ 0x1f0d1, 0x1f0df,
+ 0x1f100, 0x1f10a,
+ 0x1f110, 0x1f12e,
+ 0x1f130, 0x1f16b,
+ 0x1f170, 0x1f19a,
+ 0x1f1e6, 0x1f202,
+ 0x1f210, 0x1f23a,
+ 0x1f240, 0x1f248,
+ 0x1f250, 0x1f251,
+ 0x1f300, 0x1f320,
+ 0x1f330, 0x1f335,
+ 0x1f337, 0x1f37c,
+ 0x1f380, 0x1f393,
+ 0x1f3a0, 0x1f3c4,
+ 0x1f3c6, 0x1f3ca,
+ 0x1f3e0, 0x1f3f0,
+ 0x1f400, 0x1f43e,
+ 0x1f440, 0x1f440,
+ 0x1f442, 0x1f4f7,
+ 0x1f4f9, 0x1f4fc,
+ 0x1f500, 0x1f53d,
+ 0x1f540, 0x1f543,
+ 0x1f550, 0x1f567,
+ 0x1f5fb, 0x1f640,
+ 0x1f645, 0x1f64f,
+ 0x1f680, 0x1f6c5,
+ 0x1f700, 0x1f773,
+ 0x1fffe, 0x2a6d6,
+ 0x2a700, 0x2b734,
+ 0x2b740, 0x2b81d,
+ 0x2f800, 0x2fa1d,
+ 0x2fffe, 0x2ffff,
+ 0x3fffe, 0x3ffff,
+ 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_6_2 */
+
+/* 'Age_6_3': Derived Age 6.3 */
+static const OnigCodePoint CR_Age_6_3[] = {
+ 549,
+ 0x0000, 0x0377,
+ 0x037a, 0x037e,
+ 0x0384, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x0527,
+ 0x0531, 0x0556,
+ 0x0559, 0x055f,
+ 0x0561, 0x0587,
+ 0x0589, 0x058a,
+ 0x058f, 0x058f,
+ 0x0591, 0x05c7,
+ 0x05d0, 0x05ea,
+ 0x05f0, 0x05f4,
+ 0x0600, 0x0604,
+ 0x0606, 0x061c,
+ 0x061e, 0x070d,
+ 0x070f, 0x074a,
+ 0x074d, 0x07b1,
+ 0x07c0, 0x07fa,
+ 0x0800, 0x082d,
+ 0x0830, 0x083e,
+ 0x0840, 0x085b,
+ 0x085e, 0x085e,
+ 0x08a0, 0x08a0,
+ 0x08a2, 0x08ac,
+ 0x08e4, 0x08fe,
+ 0x0900, 0x0977,
+ 0x0979, 0x097f,
+ 0x0981, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fb,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a75,
+ 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,
+ 0x0b01, 0x0b03,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b35, 0x0b39,
+ 0x0b3c, 0x0b44,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4d,
+ 0x0b56, 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,
+ 0x0be6, 0x0bfa,
+ 0x0c01, 0x0c03,
+ 0x0c05, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c33,
+ 0x0c35, 0x0c39,
+ 0x0c3d, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c59,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c78, 0x0c7f,
+ 0x0c82, 0x0c83,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cde, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf2,
+ 0x0d02, 0x0d03,
+ 0x0d05, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d3a,
+ 0x0d3d, 0x0d44,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4e,
+ 0x0d57, 0x0d57,
+ 0x0d60, 0x0d63,
+ 0x0d66, 0x0d75,
+ 0x0d79, 0x0d7f,
+ 0x0d82, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0df2, 0x0df4,
+ 0x0e01, 0x0e3a,
+ 0x0e3f, 0x0e5b,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e87, 0x0e88,
+ 0x0e8a, 0x0e8a,
+ 0x0e8d, 0x0e8d,
+ 0x0e94, 0x0e97,
+ 0x0e99, 0x0e9f,
+ 0x0ea1, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ea7,
+ 0x0eaa, 0x0eab,
+ 0x0ead, 0x0eb9,
+ 0x0ebb, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ecd,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 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, 0x13f4,
+ 0x1400, 0x169c,
+ 0x16a0, 0x16f0,
+ 0x1700, 0x170c,
+ 0x170e, 0x1714,
+ 0x1720, 0x1736,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x1800, 0x180e,
+ 0x1810, 0x1819,
+ 0x1820, 0x1877,
+ 0x1880, 0x18aa,
+ 0x18b0, 0x18f5,
+ 0x1900, 0x191c,
+ 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,
+ 0x1b00, 0x1b4b,
+ 0x1b50, 0x1b7c,
+ 0x1b80, 0x1bf3,
+ 0x1bfc, 0x1c37,
+ 0x1c3b, 0x1c49,
+ 0x1c4d, 0x1c7f,
+ 0x1cc0, 0x1cc7,
+ 0x1cd0, 0x1cf6,
+ 0x1d00, 0x1de6,
+ 0x1dfc, 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, 0x20ba,
+ 0x20d0, 0x20f0,
+ 0x2100, 0x2189,
+ 0x2190, 0x23f3,
+ 0x2400, 0x2426,
+ 0x2440, 0x244a,
+ 0x2460, 0x26ff,
+ 0x2701, 0x2b4c,
+ 0x2b50, 0x2b59,
+ 0x2c00, 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, 0x2e3b,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2ffb,
+ 0x3000, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312d,
+ 0x3131, 0x318e,
+ 0x3190, 0x31ba,
+ 0x31c0, 0x31e3,
+ 0x31f0, 0x321e,
+ 0x3220, 0x32fe,
+ 0x3300, 0x4db5,
+ 0x4dc0, 0x9fcc,
+ 0xa000, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa4d0, 0xa62b,
+ 0xa640, 0xa697,
+ 0xa69f, 0xa6f7,
+ 0xa700, 0xa78e,
+ 0xa790, 0xa793,
+ 0xa7a0, 0xa7aa,
+ 0xa7f8, 0xa82b,
+ 0xa830, 0xa839,
+ 0xa840, 0xa877,
+ 0xa880, 0xa8c4,
+ 0xa8ce, 0xa8d9,
+ 0xa8e0, 0xa8fb,
+ 0xa900, 0xa953,
+ 0xa95f, 0xa97c,
+ 0xa980, 0xa9cd,
+ 0xa9cf, 0xa9d9,
+ 0xa9de, 0xa9df,
+ 0xaa00, 0xaa36,
+ 0xaa40, 0xaa4d,
+ 0xaa50, 0xaa59,
+ 0xaa5c, 0xaa7b,
+ 0xaa80, 0xaac2,
+ 0xaadb, 0xaaf6,
+ 0xab01, 0xab06,
+ 0xab09, 0xab0e,
+ 0xab11, 0xab16,
+ 0xab20, 0xab26,
+ 0xab28, 0xab2e,
+ 0xabc0, 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, 0xfe26,
+ 0xfe30, 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, 0x1018a,
+ 0x10190, 0x1019b,
+ 0x101d0, 0x101fd,
+ 0x10280, 0x1029c,
+ 0x102a0, 0x102d0,
+ 0x10300, 0x1031e,
+ 0x10320, 0x10323,
+ 0x10330, 0x1034a,
+ 0x10380, 0x1039d,
+ 0x1039f, 0x103c3,
+ 0x103c8, 0x103d5,
+ 0x10400, 0x1049d,
+ 0x104a0, 0x104a9,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 0x10837, 0x10838,
+ 0x1083c, 0x1083c,
+ 0x1083f, 0x10855,
+ 0x10857, 0x1085f,
+ 0x10900, 0x1091b,
+ 0x1091f, 0x10939,
+ 0x1093f, 0x1093f,
+ 0x10980, 0x109b7,
+ 0x109be, 0x109bf,
+ 0x10a00, 0x10a03,
+ 0x10a05, 0x10a06,
+ 0x10a0c, 0x10a13,
+ 0x10a15, 0x10a17,
+ 0x10a19, 0x10a33,
+ 0x10a38, 0x10a3a,
+ 0x10a3f, 0x10a47,
+ 0x10a50, 0x10a58,
+ 0x10a60, 0x10a7f,
+ 0x10b00, 0x10b35,
+ 0x10b39, 0x10b55,
+ 0x10b58, 0x10b72,
+ 0x10b78, 0x10b7f,
+ 0x10c00, 0x10c48,
+ 0x10e60, 0x10e7e,
+ 0x11000, 0x1104d,
+ 0x11052, 0x1106f,
+ 0x11080, 0x110c1,
+ 0x110d0, 0x110e8,
+ 0x110f0, 0x110f9,
+ 0x11100, 0x11134,
+ 0x11136, 0x11143,
+ 0x11180, 0x111c8,
+ 0x111d0, 0x111d9,
+ 0x11680, 0x116b7,
+ 0x116c0, 0x116c9,
+ 0x12000, 0x1236e,
+ 0x12400, 0x12462,
+ 0x12470, 0x12473,
+ 0x13000, 0x1342e,
+ 0x16800, 0x16a38,
+ 0x16f00, 0x16f44,
+ 0x16f50, 0x16f7e,
+ 0x16f8f, 0x16f9f,
+ 0x1b000, 0x1b001,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d129, 0x1d1dd,
+ 0x1d200, 0x1d245,
+ 0x1d300, 0x1d356,
+ 0x1d360, 0x1d371,
+ 0x1d400, 0x1d454,
+ 0x1d456, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 0x1d4a2, 0x1d4a2,
+ 0x1d4a5, 0x1d4a6,
+ 0x1d4a9, 0x1d4ac,
+ 0x1d4ae, 0x1d4b9,
+ 0x1d4bb, 0x1d4bb,
+ 0x1d4bd, 0x1d4c3,
+ 0x1d4c5, 0x1d505,
+ 0x1d507, 0x1d50a,
+ 0x1d50d, 0x1d514,
+ 0x1d516, 0x1d51c,
+ 0x1d51e, 0x1d539,
+ 0x1d53b, 0x1d53e,
+ 0x1d540, 0x1d544,
+ 0x1d546, 0x1d546,
+ 0x1d54a, 0x1d550,
+ 0x1d552, 0x1d6a5,
+ 0x1d6a8, 0x1d7cb,
+ 0x1d7ce, 0x1d7ff,
+ 0x1ee00, 0x1ee03,
+ 0x1ee05, 0x1ee1f,
+ 0x1ee21, 0x1ee22,
+ 0x1ee24, 0x1ee24,
+ 0x1ee27, 0x1ee27,
+ 0x1ee29, 0x1ee32,
+ 0x1ee34, 0x1ee37,
+ 0x1ee39, 0x1ee39,
+ 0x1ee3b, 0x1ee3b,
+ 0x1ee42, 0x1ee42,
+ 0x1ee47, 0x1ee47,
+ 0x1ee49, 0x1ee49,
+ 0x1ee4b, 0x1ee4b,
+ 0x1ee4d, 0x1ee4f,
+ 0x1ee51, 0x1ee52,
+ 0x1ee54, 0x1ee54,
+ 0x1ee57, 0x1ee57,
+ 0x1ee59, 0x1ee59,
+ 0x1ee5b, 0x1ee5b,
+ 0x1ee5d, 0x1ee5d,
+ 0x1ee5f, 0x1ee5f,
+ 0x1ee61, 0x1ee62,
+ 0x1ee64, 0x1ee64,
+ 0x1ee67, 0x1ee6a,
+ 0x1ee6c, 0x1ee72,
+ 0x1ee74, 0x1ee77,
+ 0x1ee79, 0x1ee7c,
+ 0x1ee7e, 0x1ee7e,
+ 0x1ee80, 0x1ee89,
+ 0x1ee8b, 0x1ee9b,
+ 0x1eea1, 0x1eea3,
+ 0x1eea5, 0x1eea9,
+ 0x1eeab, 0x1eebb,
+ 0x1eef0, 0x1eef1,
+ 0x1f000, 0x1f02b,
+ 0x1f030, 0x1f093,
+ 0x1f0a0, 0x1f0ae,
+ 0x1f0b1, 0x1f0be,
+ 0x1f0c1, 0x1f0cf,
+ 0x1f0d1, 0x1f0df,
+ 0x1f100, 0x1f10a,
+ 0x1f110, 0x1f12e,
+ 0x1f130, 0x1f16b,
+ 0x1f170, 0x1f19a,
+ 0x1f1e6, 0x1f202,
+ 0x1f210, 0x1f23a,
+ 0x1f240, 0x1f248,
+ 0x1f250, 0x1f251,
+ 0x1f300, 0x1f320,
+ 0x1f330, 0x1f335,
+ 0x1f337, 0x1f37c,
+ 0x1f380, 0x1f393,
+ 0x1f3a0, 0x1f3c4,
+ 0x1f3c6, 0x1f3ca,
+ 0x1f3e0, 0x1f3f0,
+ 0x1f400, 0x1f43e,
+ 0x1f440, 0x1f440,
+ 0x1f442, 0x1f4f7,
+ 0x1f4f9, 0x1f4fc,
+ 0x1f500, 0x1f53d,
+ 0x1f540, 0x1f543,
+ 0x1f550, 0x1f567,
+ 0x1f5fb, 0x1f640,
+ 0x1f645, 0x1f64f,
+ 0x1f680, 0x1f6c5,
+ 0x1f700, 0x1f773,
+ 0x1fffe, 0x2a6d6,
+ 0x2a700, 0x2b734,
+ 0x2b740, 0x2b81d,
+ 0x2f800, 0x2fa1d,
+ 0x2fffe, 0x2ffff,
+ 0x3fffe, 0x3ffff,
+ 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_6_3 */
+
+/* 'Age_7_0': Derived Age 7.0 */
+static const OnigCodePoint CR_Age_7_0[] = {
+ 610,
+ 0x0000, 0x0377,
+ 0x037a, 0x037f,
+ 0x0384, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x052f,
+ 0x0531, 0x0556,
+ 0x0559, 0x055f,
+ 0x0561, 0x0587,
+ 0x0589, 0x058a,
+ 0x058d, 0x058f,
+ 0x0591, 0x05c7,
+ 0x05d0, 0x05ea,
+ 0x05f0, 0x05f4,
+ 0x0600, 0x061c,
+ 0x061e, 0x070d,
+ 0x070f, 0x074a,
+ 0x074d, 0x07b1,
+ 0x07c0, 0x07fa,
+ 0x0800, 0x082d,
+ 0x0830, 0x083e,
+ 0x0840, 0x085b,
+ 0x085e, 0x085e,
+ 0x08a0, 0x08b2,
+ 0x08e4, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fb,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a75,
+ 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,
+ 0x0b01, 0x0b03,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b35, 0x0b39,
+ 0x0b3c, 0x0b44,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4d,
+ 0x0b56, 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,
+ 0x0be6, 0x0bfa,
+ 0x0c00, 0x0c03,
+ 0x0c05, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3d, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c59,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c78, 0x0c7f,
+ 0x0c81, 0x0c83,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cde, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf2,
+ 0x0d01, 0x0d03,
+ 0x0d05, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d3a,
+ 0x0d3d, 0x0d44,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4e,
+ 0x0d57, 0x0d57,
+ 0x0d60, 0x0d63,
+ 0x0d66, 0x0d75,
+ 0x0d79, 0x0d7f,
+ 0x0d82, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0de6, 0x0def,
+ 0x0df2, 0x0df4,
+ 0x0e01, 0x0e3a,
+ 0x0e3f, 0x0e5b,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e87, 0x0e88,
+ 0x0e8a, 0x0e8a,
+ 0x0e8d, 0x0e8d,
+ 0x0e94, 0x0e97,
+ 0x0e99, 0x0e9f,
+ 0x0ea1, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ea7,
+ 0x0eaa, 0x0eab,
+ 0x0ead, 0x0eb9,
+ 0x0ebb, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ecd,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 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, 0x13f4,
+ 0x1400, 0x169c,
+ 0x16a0, 0x16f8,
+ 0x1700, 0x170c,
+ 0x170e, 0x1714,
+ 0x1720, 0x1736,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x1800, 0x180e,
+ 0x1810, 0x1819,
+ 0x1820, 0x1877,
+ 0x1880, 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, 0x1abe,
+ 0x1b00, 0x1b4b,
+ 0x1b50, 0x1b7c,
+ 0x1b80, 0x1bf3,
+ 0x1bfc, 0x1c37,
+ 0x1c3b, 0x1c49,
+ 0x1c4d, 0x1c7f,
+ 0x1cc0, 0x1cc7,
+ 0x1cd0, 0x1cf6,
+ 0x1cf8, 0x1cf9,
+ 0x1d00, 0x1df5,
+ 0x1dfc, 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, 0x20bd,
+ 0x20d0, 0x20f0,
+ 0x2100, 0x2189,
+ 0x2190, 0x23fa,
+ 0x2400, 0x2426,
+ 0x2440, 0x244a,
+ 0x2460, 0x2b73,
+ 0x2b76, 0x2b95,
+ 0x2b98, 0x2bb9,
+ 0x2bbd, 0x2bc8,
+ 0x2bca, 0x2bd1,
+ 0x2c00, 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, 0x2e42,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2ffb,
+ 0x3000, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312d,
+ 0x3131, 0x318e,
+ 0x3190, 0x31ba,
+ 0x31c0, 0x31e3,
+ 0x31f0, 0x321e,
+ 0x3220, 0x32fe,
+ 0x3300, 0x4db5,
+ 0x4dc0, 0x9fcc,
+ 0xa000, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa4d0, 0xa62b,
+ 0xa640, 0xa69d,
+ 0xa69f, 0xa6f7,
+ 0xa700, 0xa78e,
+ 0xa790, 0xa7ad,
+ 0xa7b0, 0xa7b1,
+ 0xa7f7, 0xa82b,
+ 0xa830, 0xa839,
+ 0xa840, 0xa877,
+ 0xa880, 0xa8c4,
+ 0xa8ce, 0xa8d9,
+ 0xa8e0, 0xa8fb,
+ 0xa900, 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, 0xab5f,
+ 0xab64, 0xab65,
+ 0xabc0, 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, 0xfe2d,
+ 0xfe30, 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, 0x1018c,
+ 0x10190, 0x1019b,
+ 0x101a0, 0x101a0,
+ 0x101d0, 0x101fd,
+ 0x10280, 0x1029c,
+ 0x102a0, 0x102d0,
+ 0x102e0, 0x102fb,
+ 0x10300, 0x10323,
+ 0x10330, 0x1034a,
+ 0x10350, 0x1037a,
+ 0x10380, 0x1039d,
+ 0x1039f, 0x103c3,
+ 0x103c8, 0x103d5,
+ 0x10400, 0x1049d,
+ 0x104a0, 0x104a9,
+ 0x10500, 0x10527,
+ 0x10530, 0x10563,
+ 0x1056f, 0x1056f,
+ 0x10600, 0x10736,
+ 0x10740, 0x10755,
+ 0x10760, 0x10767,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 0x10837, 0x10838,
+ 0x1083c, 0x1083c,
+ 0x1083f, 0x10855,
+ 0x10857, 0x1089e,
+ 0x108a7, 0x108af,
+ 0x10900, 0x1091b,
+ 0x1091f, 0x10939,
+ 0x1093f, 0x1093f,
+ 0x10980, 0x109b7,
+ 0x109be, 0x109bf,
+ 0x10a00, 0x10a03,
+ 0x10a05, 0x10a06,
+ 0x10a0c, 0x10a13,
+ 0x10a15, 0x10a17,
+ 0x10a19, 0x10a33,
+ 0x10a38, 0x10a3a,
+ 0x10a3f, 0x10a47,
+ 0x10a50, 0x10a58,
+ 0x10a60, 0x10a9f,
+ 0x10ac0, 0x10ae6,
+ 0x10aeb, 0x10af6,
+ 0x10b00, 0x10b35,
+ 0x10b39, 0x10b55,
+ 0x10b58, 0x10b72,
+ 0x10b78, 0x10b91,
+ 0x10b99, 0x10b9c,
+ 0x10ba9, 0x10baf,
+ 0x10c00, 0x10c48,
+ 0x10e60, 0x10e7e,
+ 0x11000, 0x1104d,
+ 0x11052, 0x1106f,
+ 0x1107f, 0x110c1,
+ 0x110d0, 0x110e8,
+ 0x110f0, 0x110f9,
+ 0x11100, 0x11134,
+ 0x11136, 0x11143,
+ 0x11150, 0x11176,
+ 0x11180, 0x111c8,
+ 0x111cd, 0x111cd,
+ 0x111d0, 0x111da,
+ 0x111e1, 0x111f4,
+ 0x11200, 0x11211,
+ 0x11213, 0x1123d,
+ 0x112b0, 0x112ea,
+ 0x112f0, 0x112f9,
+ 0x11301, 0x11303,
+ 0x11305, 0x1130c,
+ 0x1130f, 0x11310,
+ 0x11313, 0x11328,
+ 0x1132a, 0x11330,
+ 0x11332, 0x11333,
+ 0x11335, 0x11339,
+ 0x1133c, 0x11344,
+ 0x11347, 0x11348,
+ 0x1134b, 0x1134d,
+ 0x11357, 0x11357,
+ 0x1135d, 0x11363,
+ 0x11366, 0x1136c,
+ 0x11370, 0x11374,
+ 0x11480, 0x114c7,
+ 0x114d0, 0x114d9,
+ 0x11580, 0x115b5,
+ 0x115b8, 0x115c9,
+ 0x11600, 0x11644,
+ 0x11650, 0x11659,
+ 0x11680, 0x116b7,
+ 0x116c0, 0x116c9,
+ 0x118a0, 0x118f2,
+ 0x118ff, 0x118ff,
+ 0x11ac0, 0x11af8,
+ 0x12000, 0x12398,
+ 0x12400, 0x1246e,
+ 0x12470, 0x12474,
+ 0x13000, 0x1342e,
+ 0x16800, 0x16a38,
+ 0x16a40, 0x16a5e,
+ 0x16a60, 0x16a69,
+ 0x16a6e, 0x16a6f,
+ 0x16ad0, 0x16aed,
+ 0x16af0, 0x16af5,
+ 0x16b00, 0x16b45,
+ 0x16b50, 0x16b59,
+ 0x16b5b, 0x16b61,
+ 0x16b63, 0x16b77,
+ 0x16b7d, 0x16b8f,
+ 0x16f00, 0x16f44,
+ 0x16f50, 0x16f7e,
+ 0x16f8f, 0x16f9f,
+ 0x1b000, 0x1b001,
+ 0x1bc00, 0x1bc6a,
+ 0x1bc70, 0x1bc7c,
+ 0x1bc80, 0x1bc88,
+ 0x1bc90, 0x1bc99,
+ 0x1bc9c, 0x1bca3,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d129, 0x1d1dd,
+ 0x1d200, 0x1d245,
+ 0x1d300, 0x1d356,
+ 0x1d360, 0x1d371,
+ 0x1d400, 0x1d454,
+ 0x1d456, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 0x1d4a2, 0x1d4a2,
+ 0x1d4a5, 0x1d4a6,
+ 0x1d4a9, 0x1d4ac,
+ 0x1d4ae, 0x1d4b9,
+ 0x1d4bb, 0x1d4bb,
+ 0x1d4bd, 0x1d4c3,
+ 0x1d4c5, 0x1d505,
+ 0x1d507, 0x1d50a,
+ 0x1d50d, 0x1d514,
+ 0x1d516, 0x1d51c,
+ 0x1d51e, 0x1d539,
+ 0x1d53b, 0x1d53e,
+ 0x1d540, 0x1d544,
+ 0x1d546, 0x1d546,
+ 0x1d54a, 0x1d550,
+ 0x1d552, 0x1d6a5,
+ 0x1d6a8, 0x1d7cb,
+ 0x1d7ce, 0x1d7ff,
+ 0x1e800, 0x1e8c4,
+ 0x1e8c7, 0x1e8d6,
+ 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, 0x1f10c,
+ 0x1f110, 0x1f12e,
+ 0x1f130, 0x1f16b,
+ 0x1f170, 0x1f19a,
+ 0x1f1e6, 0x1f202,
+ 0x1f210, 0x1f23a,
+ 0x1f240, 0x1f248,
+ 0x1f250, 0x1f251,
+ 0x1f300, 0x1f32c,
+ 0x1f330, 0x1f37d,
+ 0x1f380, 0x1f3ce,
+ 0x1f3d4, 0x1f3f7,
+ 0x1f400, 0x1f4fe,
+ 0x1f500, 0x1f54a,
+ 0x1f550, 0x1f579,
+ 0x1f57b, 0x1f5a3,
+ 0x1f5a5, 0x1f642,
+ 0x1f645, 0x1f6cf,
+ 0x1f6e0, 0x1f6ec,
+ 0x1f6f0, 0x1f6f3,
+ 0x1f700, 0x1f773,
+ 0x1f780, 0x1f7d4,
+ 0x1f800, 0x1f80b,
+ 0x1f810, 0x1f847,
+ 0x1f850, 0x1f859,
+ 0x1f860, 0x1f887,
+ 0x1f890, 0x1f8ad,
+ 0x1fffe, 0x2a6d6,
+ 0x2a700, 0x2b734,
+ 0x2b740, 0x2b81d,
+ 0x2f800, 0x2fa1d,
+ 0x2fffe, 0x2ffff,
+ 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_7_0 */
+
+/* 'Age_8_0': Derived Age 8.0 */
+static const OnigCodePoint CR_Age_8_0[] = {
+ 623,
+ 0x0000, 0x0377,
+ 0x037a, 0x037f,
+ 0x0384, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x052f,
+ 0x0531, 0x0556,
+ 0x0559, 0x055f,
+ 0x0561, 0x0587,
+ 0x0589, 0x058a,
+ 0x058d, 0x058f,
+ 0x0591, 0x05c7,
+ 0x05d0, 0x05ea,
+ 0x05f0, 0x05f4,
+ 0x0600, 0x061c,
+ 0x061e, 0x070d,
+ 0x070f, 0x074a,
+ 0x074d, 0x07b1,
+ 0x07c0, 0x07fa,
+ 0x0800, 0x082d,
+ 0x0830, 0x083e,
+ 0x0840, 0x085b,
+ 0x085e, 0x085e,
+ 0x08a0, 0x08b4,
+ 0x08e3, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fb,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a75,
+ 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, 0x0af9,
+ 0x0b01, 0x0b03,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b35, 0x0b39,
+ 0x0b3c, 0x0b44,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4d,
+ 0x0b56, 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,
+ 0x0be6, 0x0bfa,
+ 0x0c00, 0x0c03,
+ 0x0c05, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3d, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c5a,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c78, 0x0c7f,
+ 0x0c81, 0x0c83,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cde, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf2,
+ 0x0d01, 0x0d03,
+ 0x0d05, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d3a,
+ 0x0d3d, 0x0d44,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4e,
+ 0x0d57, 0x0d57,
+ 0x0d5f, 0x0d63,
+ 0x0d66, 0x0d75,
+ 0x0d79, 0x0d7f,
+ 0x0d82, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0de6, 0x0def,
+ 0x0df2, 0x0df4,
+ 0x0e01, 0x0e3a,
+ 0x0e3f, 0x0e5b,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e87, 0x0e88,
+ 0x0e8a, 0x0e8a,
+ 0x0e8d, 0x0e8d,
+ 0x0e94, 0x0e97,
+ 0x0e99, 0x0e9f,
+ 0x0ea1, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ea7,
+ 0x0eaa, 0x0eab,
+ 0x0ead, 0x0eb9,
+ 0x0ebb, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ecd,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 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,
+ 0x1780, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x1800, 0x180e,
+ 0x1810, 0x1819,
+ 0x1820, 0x1877,
+ 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, 0x1abe,
+ 0x1b00, 0x1b4b,
+ 0x1b50, 0x1b7c,
+ 0x1b80, 0x1bf3,
+ 0x1bfc, 0x1c37,
+ 0x1c3b, 0x1c49,
+ 0x1c4d, 0x1c7f,
+ 0x1cc0, 0x1cc7,
+ 0x1cd0, 0x1cf6,
+ 0x1cf8, 0x1cf9,
+ 0x1d00, 0x1df5,
+ 0x1dfc, 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, 0x20be,
+ 0x20d0, 0x20f0,
+ 0x2100, 0x218b,
+ 0x2190, 0x23fa,
+ 0x2400, 0x2426,
+ 0x2440, 0x244a,
+ 0x2460, 0x2b73,
+ 0x2b76, 0x2b95,
+ 0x2b98, 0x2bb9,
+ 0x2bbd, 0x2bc8,
+ 0x2bca, 0x2bd1,
+ 0x2bec, 0x2bef,
+ 0x2c00, 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, 0x2e42,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2ffb,
+ 0x3000, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312d,
+ 0x3131, 0x318e,
+ 0x3190, 0x31ba,
+ 0x31c0, 0x31e3,
+ 0x31f0, 0x321e,
+ 0x3220, 0x32fe,
+ 0x3300, 0x4db5,
+ 0x4dc0, 0x9fd5,
+ 0xa000, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa4d0, 0xa62b,
+ 0xa640, 0xa6f7,
+ 0xa700, 0xa7ad,
+ 0xa7b0, 0xa7b7,
+ 0xa7f7, 0xa82b,
+ 0xa830, 0xa839,
+ 0xa840, 0xa877,
+ 0xa880, 0xa8c4,
+ 0xa8ce, 0xa8d9,
+ 0xa8e0, 0xa8fd,
+ 0xa900, 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, 0xab65,
+ 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, 0x1018c,
+ 0x10190, 0x1019b,
+ 0x101a0, 0x101a0,
+ 0x101d0, 0x101fd,
+ 0x10280, 0x1029c,
+ 0x102a0, 0x102d0,
+ 0x102e0, 0x102fb,
+ 0x10300, 0x10323,
+ 0x10330, 0x1034a,
+ 0x10350, 0x1037a,
+ 0x10380, 0x1039d,
+ 0x1039f, 0x103c3,
+ 0x103c8, 0x103d5,
+ 0x10400, 0x1049d,
+ 0x104a0, 0x104a9,
+ 0x10500, 0x10527,
+ 0x10530, 0x10563,
+ 0x1056f, 0x1056f,
+ 0x10600, 0x10736,
+ 0x10740, 0x10755,
+ 0x10760, 0x10767,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 0x10837, 0x10838,
+ 0x1083c, 0x1083c,
+ 0x1083f, 0x10855,
+ 0x10857, 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, 0x10a33,
+ 0x10a38, 0x10a3a,
+ 0x10a3f, 0x10a47,
+ 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, 0x10cff,
+ 0x10e60, 0x10e7e,
+ 0x11000, 0x1104d,
+ 0x11052, 0x1106f,
+ 0x1107f, 0x110c1,
+ 0x110d0, 0x110e8,
+ 0x110f0, 0x110f9,
+ 0x11100, 0x11134,
+ 0x11136, 0x11143,
+ 0x11150, 0x11176,
+ 0x11180, 0x111cd,
+ 0x111d0, 0x111df,
+ 0x111e1, 0x111f4,
+ 0x11200, 0x11211,
+ 0x11213, 0x1123d,
+ 0x11280, 0x11286,
+ 0x11288, 0x11288,
+ 0x1128a, 0x1128d,
+ 0x1128f, 0x1129d,
+ 0x1129f, 0x112a9,
+ 0x112b0, 0x112ea,
+ 0x112f0, 0x112f9,
+ 0x11300, 0x11303,
+ 0x11305, 0x1130c,
+ 0x1130f, 0x11310,
+ 0x11313, 0x11328,
+ 0x1132a, 0x11330,
+ 0x11332, 0x11333,
+ 0x11335, 0x11339,
+ 0x1133c, 0x11344,
+ 0x11347, 0x11348,
+ 0x1134b, 0x1134d,
+ 0x11350, 0x11350,
+ 0x11357, 0x11357,
+ 0x1135d, 0x11363,
+ 0x11366, 0x1136c,
+ 0x11370, 0x11374,
+ 0x11480, 0x114c7,
+ 0x114d0, 0x114d9,
+ 0x11580, 0x115b5,
+ 0x115b8, 0x115dd,
+ 0x11600, 0x11644,
+ 0x11650, 0x11659,
+ 0x11680, 0x116b7,
+ 0x116c0, 0x116c9,
+ 0x11700, 0x11719,
+ 0x1171d, 0x1172b,
+ 0x11730, 0x1173f,
+ 0x118a0, 0x118f2,
+ 0x118ff, 0x118ff,
+ 0x11ac0, 0x11af8,
+ 0x12000, 0x12399,
+ 0x12400, 0x1246e,
+ 0x12470, 0x12474,
+ 0x12480, 0x12543,
+ 0x13000, 0x1342e,
+ 0x14400, 0x14646,
+ 0x16800, 0x16a38,
+ 0x16a40, 0x16a5e,
+ 0x16a60, 0x16a69,
+ 0x16a6e, 0x16a6f,
+ 0x16ad0, 0x16aed,
+ 0x16af0, 0x16af5,
+ 0x16b00, 0x16b45,
+ 0x16b50, 0x16b59,
+ 0x16b5b, 0x16b61,
+ 0x16b63, 0x16b77,
+ 0x16b7d, 0x16b8f,
+ 0x16f00, 0x16f44,
+ 0x16f50, 0x16f7e,
+ 0x16f8f, 0x16f9f,
+ 0x1b000, 0x1b001,
+ 0x1bc00, 0x1bc6a,
+ 0x1bc70, 0x1bc7c,
+ 0x1bc80, 0x1bc88,
+ 0x1bc90, 0x1bc99,
+ 0x1bc9c, 0x1bca3,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d129, 0x1d1e8,
+ 0x1d200, 0x1d245,
+ 0x1d300, 0x1d356,
+ 0x1d360, 0x1d371,
+ 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,
+ 0x1e800, 0x1e8c4,
+ 0x1e8c7, 0x1e8d6,
+ 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, 0x1f10c,
+ 0x1f110, 0x1f12e,
+ 0x1f130, 0x1f16b,
+ 0x1f170, 0x1f19a,
+ 0x1f1e6, 0x1f202,
+ 0x1f210, 0x1f23a,
+ 0x1f240, 0x1f248,
+ 0x1f250, 0x1f251,
+ 0x1f300, 0x1f579,
+ 0x1f57b, 0x1f5a3,
+ 0x1f5a5, 0x1f6d0,
+ 0x1f6e0, 0x1f6ec,
+ 0x1f6f0, 0x1f6f3,
+ 0x1f700, 0x1f773,
+ 0x1f780, 0x1f7d4,
+ 0x1f800, 0x1f80b,
+ 0x1f810, 0x1f847,
+ 0x1f850, 0x1f859,
+ 0x1f860, 0x1f887,
+ 0x1f890, 0x1f8ad,
+ 0x1f910, 0x1f918,
+ 0x1f980, 0x1f984,
+ 0x1f9c0, 0x1f9c0,
+ 0x1fffe, 0x2a6d6,
+ 0x2a700, 0x2b734,
+ 0x2b740, 0x2b81d,
+ 0x2b820, 0x2cea1,
+ 0x2f800, 0x2fa1d,
+ 0x2fffe, 0x2ffff,
+ 0x3fffe, 0x3ffff,
+ 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_8_0 */
+
+/* 'Age_9_0': Derived Age 9.0 */
+static const OnigCodePoint CR_Age_9_0[] = {
+ 648,
+ 0x0000, 0x0377,
+ 0x037a, 0x037f,
+ 0x0384, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x052f,
+ 0x0531, 0x0556,
+ 0x0559, 0x055f,
+ 0x0561, 0x0587,
+ 0x0589, 0x058a,
+ 0x058d, 0x058f,
+ 0x0591, 0x05c7,
+ 0x05d0, 0x05ea,
+ 0x05f0, 0x05f4,
+ 0x0600, 0x061c,
+ 0x061e, 0x070d,
+ 0x070f, 0x074a,
+ 0x074d, 0x07b1,
+ 0x07c0, 0x07fa,
+ 0x0800, 0x082d,
+ 0x0830, 0x083e,
+ 0x0840, 0x085b,
+ 0x085e, 0x085e,
+ 0x08a0, 0x08b4,
+ 0x08b6, 0x08bd,
+ 0x08d4, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fb,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a75,
+ 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, 0x0af9,
+ 0x0b01, 0x0b03,
+ 0x0b05, 0x0b0c,
+ 0x0b0f, 0x0b10,
+ 0x0b13, 0x0b28,
+ 0x0b2a, 0x0b30,
+ 0x0b32, 0x0b33,
+ 0x0b35, 0x0b39,
+ 0x0b3c, 0x0b44,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4d,
+ 0x0b56, 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,
+ 0x0be6, 0x0bfa,
+ 0x0c00, 0x0c03,
+ 0x0c05, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3d, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c5a,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c78, 0x0c83,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cde, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf2,
+ 0x0d01, 0x0d03,
+ 0x0d05, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d3a,
+ 0x0d3d, 0x0d44,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4f,
+ 0x0d54, 0x0d63,
+ 0x0d66, 0x0d7f,
+ 0x0d82, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0de6, 0x0def,
+ 0x0df2, 0x0df4,
+ 0x0e01, 0x0e3a,
+ 0x0e3f, 0x0e5b,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e87, 0x0e88,
+ 0x0e8a, 0x0e8a,
+ 0x0e8d, 0x0e8d,
+ 0x0e94, 0x0e97,
+ 0x0e99, 0x0e9f,
+ 0x0ea1, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ea7,
+ 0x0eaa, 0x0eab,
+ 0x0ead, 0x0eb9,
+ 0x0ebb, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ecd,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 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,
+ 0x1780, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x1800, 0x180e,
+ 0x1810, 0x1819,
+ 0x1820, 0x1877,
+ 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, 0x1abe,
+ 0x1b00, 0x1b4b,
+ 0x1b50, 0x1b7c,
+ 0x1b80, 0x1bf3,
+ 0x1bfc, 0x1c37,
+ 0x1c3b, 0x1c49,
+ 0x1c4d, 0x1c88,
+ 0x1cc0, 0x1cc7,
+ 0x1cd0, 0x1cf6,
+ 0x1cf8, 0x1cf9,
+ 0x1d00, 0x1df5,
+ 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, 0x20be,
+ 0x20d0, 0x20f0,
+ 0x2100, 0x218b,
+ 0x2190, 0x23fe,
+ 0x2400, 0x2426,
+ 0x2440, 0x244a,
+ 0x2460, 0x2b73,
+ 0x2b76, 0x2b95,
+ 0x2b98, 0x2bb9,
+ 0x2bbd, 0x2bc8,
+ 0x2bca, 0x2bd1,
+ 0x2bec, 0x2bef,
+ 0x2c00, 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, 0x2e44,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2ffb,
+ 0x3000, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312d,
+ 0x3131, 0x318e,
+ 0x3190, 0x31ba,
+ 0x31c0, 0x31e3,
+ 0x31f0, 0x321e,
+ 0x3220, 0x32fe,
+ 0x3300, 0x4db5,
+ 0x4dc0, 0x9fd5,
+ 0xa000, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa4d0, 0xa62b,
+ 0xa640, 0xa6f7,
+ 0xa700, 0xa7ae,
+ 0xa7b0, 0xa7b7,
+ 0xa7f7, 0xa82b,
+ 0xa830, 0xa839,
+ 0xa840, 0xa877,
+ 0xa880, 0xa8c5,
+ 0xa8ce, 0xa8d9,
+ 0xa8e0, 0xa8fd,
+ 0xa900, 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, 0xab65,
+ 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, 0x1019b,
+ 0x101a0, 0x101a0,
+ 0x101d0, 0x101fd,
+ 0x10280, 0x1029c,
+ 0x102a0, 0x102d0,
+ 0x102e0, 0x102fb,
+ 0x10300, 0x10323,
+ 0x10330, 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, 0x10a33,
+ 0x10a38, 0x10a3a,
+ 0x10a3f, 0x10a47,
+ 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, 0x10cff,
+ 0x10e60, 0x10e7e,
+ 0x11000, 0x1104d,
+ 0x11052, 0x1106f,
+ 0x1107f, 0x110c1,
+ 0x110d0, 0x110e8,
+ 0x110f0, 0x110f9,
+ 0x11100, 0x11134,
+ 0x11136, 0x11143,
+ 0x11150, 0x11176,
+ 0x11180, 0x111cd,
+ 0x111d0, 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,
+ 0x1133c, 0x11344,
+ 0x11347, 0x11348,
+ 0x1134b, 0x1134d,
+ 0x11350, 0x11350,
+ 0x11357, 0x11357,
+ 0x1135d, 0x11363,
+ 0x11366, 0x1136c,
+ 0x11370, 0x11374,
+ 0x11400, 0x11459,
+ 0x1145b, 0x1145b,
+ 0x1145d, 0x1145d,
+ 0x11480, 0x114c7,
+ 0x114d0, 0x114d9,
+ 0x11580, 0x115b5,
+ 0x115b8, 0x115dd,
+ 0x11600, 0x11644,
+ 0x11650, 0x11659,
+ 0x11660, 0x1166c,
+ 0x11680, 0x116b7,
+ 0x116c0, 0x116c9,
+ 0x11700, 0x11719,
+ 0x1171d, 0x1172b,
+ 0x11730, 0x1173f,
+ 0x118a0, 0x118f2,
+ 0x118ff, 0x118ff,
+ 0x11ac0, 0x11af8,
+ 0x11c00, 0x11c08,
+ 0x11c0a, 0x11c36,
+ 0x11c38, 0x11c45,
+ 0x11c50, 0x11c6c,
+ 0x11c70, 0x11c8f,
+ 0x11c92, 0x11ca7,
+ 0x11ca9, 0x11cb6,
+ 0x12000, 0x12399,
+ 0x12400, 0x1246e,
+ 0x12470, 0x12474,
+ 0x12480, 0x12543,
+ 0x13000, 0x1342e,
+ 0x14400, 0x14646,
+ 0x16800, 0x16a38,
+ 0x16a40, 0x16a5e,
+ 0x16a60, 0x16a69,
+ 0x16a6e, 0x16a6f,
+ 0x16ad0, 0x16aed,
+ 0x16af0, 0x16af5,
+ 0x16b00, 0x16b45,
+ 0x16b50, 0x16b59,
+ 0x16b5b, 0x16b61,
+ 0x16b63, 0x16b77,
+ 0x16b7d, 0x16b8f,
+ 0x16f00, 0x16f44,
+ 0x16f50, 0x16f7e,
+ 0x16f8f, 0x16f9f,
+ 0x16fe0, 0x16fe0,
+ 0x17000, 0x187ec,
+ 0x18800, 0x18af2,
+ 0x1b000, 0x1b001,
+ 0x1bc00, 0x1bc6a,
+ 0x1bc70, 0x1bc7c,
+ 0x1bc80, 0x1bc88,
+ 0x1bc90, 0x1bc99,
+ 0x1bc9c, 0x1bca3,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d129, 0x1d1e8,
+ 0x1d200, 0x1d245,
+ 0x1d300, 0x1d356,
+ 0x1d360, 0x1d371,
+ 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,
+ 0x1e800, 0x1e8c4,
+ 0x1e8c7, 0x1e8d6,
+ 0x1e900, 0x1e94a,
+ 0x1e950, 0x1e959,
+ 0x1e95e, 0x1e95f,
+ 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, 0x1f10c,
+ 0x1f110, 0x1f12e,
+ 0x1f130, 0x1f16b,
+ 0x1f170, 0x1f1ac,
+ 0x1f1e6, 0x1f202,
+ 0x1f210, 0x1f23b,
+ 0x1f240, 0x1f248,
+ 0x1f250, 0x1f251,
+ 0x1f300, 0x1f6d2,
+ 0x1f6e0, 0x1f6ec,
+ 0x1f6f0, 0x1f6f6,
+ 0x1f700, 0x1f773,
+ 0x1f780, 0x1f7d4,
+ 0x1f800, 0x1f80b,
+ 0x1f810, 0x1f847,
+ 0x1f850, 0x1f859,
+ 0x1f860, 0x1f887,
+ 0x1f890, 0x1f8ad,
+ 0x1f910, 0x1f91e,
+ 0x1f920, 0x1f927,
+ 0x1f930, 0x1f930,
+ 0x1f933, 0x1f93e,
+ 0x1f940, 0x1f94b,
+ 0x1f950, 0x1f95e,
+ 0x1f980, 0x1f991,
+ 0x1f9c0, 0x1f9c0,
+ 0x1fffe, 0x2a6d6,
+ 0x2a700, 0x2b734,
+ 0x2b740, 0x2b81d,
+ 0x2b820, 0x2cea1,
+ 0x2f800, 0x2fa1d,
+ 0x2fffe, 0x2ffff,
+ 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_9_0 */
+
+/* 'Age_10_0': Derived Age 10.0 */
+static const OnigCodePoint CR_Age_10_0[] = {
+ 659,
+ 0x0000, 0x0377,
+ 0x037a, 0x037f,
+ 0x0384, 0x038a,
+ 0x038c, 0x038c,
+ 0x038e, 0x03a1,
+ 0x03a3, 0x052f,
+ 0x0531, 0x0556,
+ 0x0559, 0x055f,
+ 0x0561, 0x0587,
+ 0x0589, 0x058a,
+ 0x058d, 0x058f,
+ 0x0591, 0x05c7,
+ 0x05d0, 0x05ea,
+ 0x05f0, 0x05f4,
+ 0x0600, 0x061c,
+ 0x061e, 0x070d,
+ 0x070f, 0x074a,
+ 0x074d, 0x07b1,
+ 0x07c0, 0x07fa,
+ 0x0800, 0x082d,
+ 0x0830, 0x083e,
+ 0x0840, 0x085b,
+ 0x085e, 0x085e,
+ 0x0860, 0x086a,
+ 0x08a0, 0x08b4,
+ 0x08b6, 0x08bd,
+ 0x08d4, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fd,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 0x0a59, 0x0a5c,
+ 0x0a5e, 0x0a5e,
+ 0x0a66, 0x0a75,
+ 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,
+ 0x0b56, 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,
+ 0x0be6, 0x0bfa,
+ 0x0c00, 0x0c03,
+ 0x0c05, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3d, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c5a,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c78, 0x0c83,
+ 0x0c85, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cde, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf2,
+ 0x0d00, 0x0d03,
+ 0x0d05, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d44,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4f,
+ 0x0d54, 0x0d63,
+ 0x0d66, 0x0d7f,
+ 0x0d82, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0de6, 0x0def,
+ 0x0df2, 0x0df4,
+ 0x0e01, 0x0e3a,
+ 0x0e3f, 0x0e5b,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e87, 0x0e88,
+ 0x0e8a, 0x0e8a,
+ 0x0e8d, 0x0e8d,
+ 0x0e94, 0x0e97,
+ 0x0e99, 0x0e9f,
+ 0x0ea1, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ea7,
+ 0x0eaa, 0x0eab,
+ 0x0ead, 0x0eb9,
+ 0x0ebb, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ecd,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 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,
+ 0x1780, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x1800, 0x180e,
+ 0x1810, 0x1819,
+ 0x1820, 0x1877,
+ 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, 0x1abe,
+ 0x1b00, 0x1b4b,
+ 0x1b50, 0x1b7c,
+ 0x1b80, 0x1bf3,
+ 0x1bfc, 0x1c37,
+ 0x1c3b, 0x1c49,
+ 0x1c4d, 0x1c88,
+ 0x1cc0, 0x1cc7,
+ 0x1cd0, 0x1cf9,
+ 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,
+ 0x2b98, 0x2bb9,
+ 0x2bbd, 0x2bc8,
+ 0x2bca, 0x2bd2,
+ 0x2bec, 0x2bef,
+ 0x2c00, 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, 0x2e49,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2ffb,
+ 0x3000, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312e,
+ 0x3131, 0x318e,
+ 0x3190, 0x31ba,
+ 0x31c0, 0x31e3,
+ 0x31f0, 0x321e,
+ 0x3220, 0x32fe,
+ 0x3300, 0x4db5,
+ 0x4dc0, 0x9fea,
+ 0xa000, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa4d0, 0xa62b,
+ 0xa640, 0xa6f7,
+ 0xa700, 0xa7ae,
+ 0xa7b0, 0xa7b7,
+ 0xa7f7, 0xa82b,
+ 0xa830, 0xa839,
+ 0xa840, 0xa877,
+ 0xa880, 0xa8c5,
+ 0xa8ce, 0xa8d9,
+ 0xa8e0, 0xa8fd,
+ 0xa900, 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, 0xab65,
+ 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, 0x1019b,
+ 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, 0x10a33,
+ 0x10a38, 0x10a3a,
+ 0x10a3f, 0x10a47,
+ 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, 0x10cff,
+ 0x10e60, 0x10e7e,
+ 0x11000, 0x1104d,
+ 0x11052, 0x1106f,
+ 0x1107f, 0x110c1,
+ 0x110d0, 0x110e8,
+ 0x110f0, 0x110f9,
+ 0x11100, 0x11134,
+ 0x11136, 0x11143,
+ 0x11150, 0x11176,
+ 0x11180, 0x111cd,
+ 0x111d0, 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,
+ 0x1133c, 0x11344,
+ 0x11347, 0x11348,
+ 0x1134b, 0x1134d,
+ 0x11350, 0x11350,
+ 0x11357, 0x11357,
+ 0x1135d, 0x11363,
+ 0x11366, 0x1136c,
+ 0x11370, 0x11374,
+ 0x11400, 0x11459,
+ 0x1145b, 0x1145b,
+ 0x1145d, 0x1145d,
+ 0x11480, 0x114c7,
+ 0x114d0, 0x114d9,
+ 0x11580, 0x115b5,
+ 0x115b8, 0x115dd,
+ 0x11600, 0x11644,
+ 0x11650, 0x11659,
+ 0x11660, 0x1166c,
+ 0x11680, 0x116b7,
+ 0x116c0, 0x116c9,
+ 0x11700, 0x11719,
+ 0x1171d, 0x1172b,
+ 0x11730, 0x1173f,
+ 0x118a0, 0x118f2,
+ 0x118ff, 0x118ff,
+ 0x11a00, 0x11a47,
+ 0x11a50, 0x11a83,
+ 0x11a86, 0x11a9c,
+ 0x11a9e, 0x11aa2,
+ 0x11ac0, 0x11af8,
+ 0x11c00, 0x11c08,
+ 0x11c0a, 0x11c36,
+ 0x11c38, 0x11c45,
+ 0x11c50, 0x11c6c,
+ 0x11c70, 0x11c8f,
+ 0x11c92, 0x11ca7,
+ 0x11ca9, 0x11cb6,
+ 0x11d00, 0x11d06,
+ 0x11d08, 0x11d09,
+ 0x11d0b, 0x11d36,
+ 0x11d3a, 0x11d3a,
+ 0x11d3c, 0x11d3d,
+ 0x11d3f, 0x11d47,
+ 0x11d50, 0x11d59,
+ 0x12000, 0x12399,
+ 0x12400, 0x1246e,
+ 0x12470, 0x12474,
+ 0x12480, 0x12543,
+ 0x13000, 0x1342e,
+ 0x14400, 0x14646,
+ 0x16800, 0x16a38,
+ 0x16a40, 0x16a5e,
+ 0x16a60, 0x16a69,
+ 0x16a6e, 0x16a6f,
+ 0x16ad0, 0x16aed,
+ 0x16af0, 0x16af5,
+ 0x16b00, 0x16b45,
+ 0x16b50, 0x16b59,
+ 0x16b5b, 0x16b61,
+ 0x16b63, 0x16b77,
+ 0x16b7d, 0x16b8f,
+ 0x16f00, 0x16f44,
+ 0x16f50, 0x16f7e,
+ 0x16f8f, 0x16f9f,
+ 0x16fe0, 0x16fe1,
+ 0x17000, 0x187ec,
+ 0x18800, 0x18af2,
+ 0x1b000, 0x1b11e,
+ 0x1b170, 0x1b2fb,
+ 0x1bc00, 0x1bc6a,
+ 0x1bc70, 0x1bc7c,
+ 0x1bc80, 0x1bc88,
+ 0x1bc90, 0x1bc99,
+ 0x1bc9c, 0x1bca3,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d129, 0x1d1e8,
+ 0x1d200, 0x1d245,
+ 0x1d300, 0x1d356,
+ 0x1d360, 0x1d371,
+ 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,
+ 0x1e800, 0x1e8c4,
+ 0x1e8c7, 0x1e8d6,
+ 0x1e900, 0x1e94a,
+ 0x1e950, 0x1e959,
+ 0x1e95e, 0x1e95f,
+ 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, 0x1f10c,
+ 0x1f110, 0x1f12e,
+ 0x1f130, 0x1f16b,
+ 0x1f170, 0x1f1ac,
+ 0x1f1e6, 0x1f202,
+ 0x1f210, 0x1f23b,
+ 0x1f240, 0x1f248,
+ 0x1f250, 0x1f251,
+ 0x1f260, 0x1f265,
+ 0x1f300, 0x1f6d4,
+ 0x1f6e0, 0x1f6ec,
+ 0x1f6f0, 0x1f6f8,
+ 0x1f700, 0x1f773,
+ 0x1f780, 0x1f7d4,
+ 0x1f800, 0x1f80b,
+ 0x1f810, 0x1f847,
+ 0x1f850, 0x1f859,
+ 0x1f860, 0x1f887,
+ 0x1f890, 0x1f8ad,
+ 0x1f900, 0x1f90b,
+ 0x1f910, 0x1f93e,
+ 0x1f940, 0x1f94c,
+ 0x1f950, 0x1f96b,
+ 0x1f980, 0x1f997,
+ 0x1f9c0, 0x1f9c0,
+ 0x1f9d0, 0x1f9e6,
+ 0x1fffe, 0x2a6d6,
+ 0x2a700, 0x2b734,
+ 0x2b740, 0x2b81d,
+ 0x2b820, 0x2cea1,
+ 0x2ceb0, 0x2ebe0,
+ 0x2f800, 0x2fa1d,
+ 0x2fffe, 0x2ffff,
+ 0x3fffe, 0x3ffff,
+ 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_10_0 */
+
+/* 'Age_11_0': Derived Age 11.0 */
+static const OnigCodePoint CR_Age_11_0[] = {
+ 668,
+ 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, 0x08bd,
+ 0x08d3, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fe,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 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,
+ 0x0b56, 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,
+ 0x0be6, 0x0bfa,
+ 0x0c00, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3d, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c5a,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c78, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cde, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf2,
+ 0x0d00, 0x0d03,
+ 0x0d05, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d44,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4f,
+ 0x0d54, 0x0d63,
+ 0x0d66, 0x0d7f,
+ 0x0d82, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 0x0dd8, 0x0ddf,
+ 0x0de6, 0x0def,
+ 0x0df2, 0x0df4,
+ 0x0e01, 0x0e3a,
+ 0x0e3f, 0x0e5b,
+ 0x0e81, 0x0e82,
+ 0x0e84, 0x0e84,
+ 0x0e87, 0x0e88,
+ 0x0e8a, 0x0e8a,
+ 0x0e8d, 0x0e8d,
+ 0x0e94, 0x0e97,
+ 0x0e99, 0x0e9f,
+ 0x0ea1, 0x0ea3,
+ 0x0ea5, 0x0ea5,
+ 0x0ea7, 0x0ea7,
+ 0x0eaa, 0x0eab,
+ 0x0ead, 0x0eb9,
+ 0x0ebb, 0x0ebd,
+ 0x0ec0, 0x0ec4,
+ 0x0ec6, 0x0ec6,
+ 0x0ec8, 0x0ecd,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 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,
+ 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, 0x1abe,
+ 0x1b00, 0x1b4b,
+ 0x1b50, 0x1b7c,
+ 0x1b80, 0x1bf3,
+ 0x1bfc, 0x1c37,
+ 0x1c3b, 0x1c49,
+ 0x1c4d, 0x1c88,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cc7,
+ 0x1cd0, 0x1cf9,
+ 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,
+ 0x2b98, 0x2bc8,
+ 0x2bca, 0x2bfe,
+ 0x2c00, 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, 0x2e4e,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2ffb,
+ 0x3000, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312f,
+ 0x3131, 0x318e,
+ 0x3190, 0x31ba,
+ 0x31c0, 0x31e3,
+ 0x31f0, 0x321e,
+ 0x3220, 0x32fe,
+ 0x3300, 0x4db5,
+ 0x4dc0, 0x9fef,
+ 0xa000, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa4d0, 0xa62b,
+ 0xa640, 0xa6f7,
+ 0xa700, 0xa7b9,
+ 0xa7f7, 0xa82b,
+ 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, 0xab65,
+ 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, 0x1019b,
+ 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,
+ 0x10f00, 0x10f27,
+ 0x10f30, 0x10f59,
+ 0x11000, 0x1104d,
+ 0x11052, 0x1106f,
+ 0x1107f, 0x110c1,
+ 0x110cd, 0x110cd,
+ 0x110d0, 0x110e8,
+ 0x110f0, 0x110f9,
+ 0x11100, 0x11134,
+ 0x11136, 0x11146,
+ 0x11150, 0x11176,
+ 0x11180, 0x111cd,
+ 0x111d0, 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, 0x11459,
+ 0x1145b, 0x1145b,
+ 0x1145d, 0x1145e,
+ 0x11480, 0x114c7,
+ 0x114d0, 0x114d9,
+ 0x11580, 0x115b5,
+ 0x115b8, 0x115dd,
+ 0x11600, 0x11644,
+ 0x11650, 0x11659,
+ 0x11660, 0x1166c,
+ 0x11680, 0x116b7,
+ 0x116c0, 0x116c9,
+ 0x11700, 0x1171a,
+ 0x1171d, 0x1172b,
+ 0x11730, 0x1173f,
+ 0x11800, 0x1183b,
+ 0x118a0, 0x118f2,
+ 0x118ff, 0x118ff,
+ 0x11a00, 0x11a47,
+ 0x11a50, 0x11a83,
+ 0x11a86, 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,
+ 0x12000, 0x12399,
+ 0x12400, 0x1246e,
+ 0x12470, 0x12474,
+ 0x12480, 0x12543,
+ 0x13000, 0x1342e,
+ 0x14400, 0x14646,
+ 0x16800, 0x16a38,
+ 0x16a40, 0x16a5e,
+ 0x16a60, 0x16a69,
+ 0x16a6e, 0x16a6f,
+ 0x16ad0, 0x16aed,
+ 0x16af0, 0x16af5,
+ 0x16b00, 0x16b45,
+ 0x16b50, 0x16b59,
+ 0x16b5b, 0x16b61,
+ 0x16b63, 0x16b77,
+ 0x16b7d, 0x16b8f,
+ 0x16e40, 0x16e9a,
+ 0x16f00, 0x16f44,
+ 0x16f50, 0x16f7e,
+ 0x16f8f, 0x16f9f,
+ 0x16fe0, 0x16fe1,
+ 0x17000, 0x187f1,
+ 0x18800, 0x18af2,
+ 0x1b000, 0x1b11e,
+ 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,
+ 0x1e800, 0x1e8c4,
+ 0x1e8c7, 0x1e8d6,
+ 0x1e900, 0x1e94a,
+ 0x1e950, 0x1e959,
+ 0x1e95e, 0x1e95f,
+ 0x1ec71, 0x1ecb4,
+ 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, 0x1f10c,
+ 0x1f110, 0x1f16b,
+ 0x1f170, 0x1f1ac,
+ 0x1f1e6, 0x1f202,
+ 0x1f210, 0x1f23b,
+ 0x1f240, 0x1f248,
+ 0x1f250, 0x1f251,
+ 0x1f260, 0x1f265,
+ 0x1f300, 0x1f6d4,
+ 0x1f6e0, 0x1f6ec,
+ 0x1f6f0, 0x1f6f9,
+ 0x1f700, 0x1f773,
+ 0x1f780, 0x1f7d8,
+ 0x1f800, 0x1f80b,
+ 0x1f810, 0x1f847,
+ 0x1f850, 0x1f859,
+ 0x1f860, 0x1f887,
+ 0x1f890, 0x1f8ad,
+ 0x1f900, 0x1f90b,
+ 0x1f910, 0x1f93e,
+ 0x1f940, 0x1f970,
+ 0x1f973, 0x1f976,
+ 0x1f97a, 0x1f97a,
+ 0x1f97c, 0x1f9a2,
+ 0x1f9b0, 0x1f9b9,
+ 0x1f9c0, 0x1f9c2,
+ 0x1f9d0, 0x1f9ff,
+ 0x1fa60, 0x1fa6d,
+ 0x1fffe, 0x2a6d6,
+ 0x2a700, 0x2b734,
+ 0x2b740, 0x2b81d,
+ 0x2b820, 0x2cea1,
+ 0x2ceb0, 0x2ebe0,
+ 0x2f800, 0x2fa1d,
+ 0x2fffe, 0x2ffff,
+ 0x3fffe, 0x3ffff,
+ 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_11_0 */
+
+/* 'Age_12_0': Derived Age 12.0 */
+static const OnigCodePoint CR_Age_12_0[] = {
+ 677,
+ 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, 0x08bd,
+ 0x08d3, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fe,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 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,
+ 0x0b56, 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,
+ 0x0be6, 0x0bfa,
+ 0x0c00, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3d, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c5a,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c77, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cde, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf2,
+ 0x0d00, 0x0d03,
+ 0x0d05, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d44,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4f,
+ 0x0d54, 0x0d63,
+ 0x0d66, 0x0d7f,
+ 0x0d82, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 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,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 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,
+ 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, 0x1abe,
+ 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,
+ 0x2b98, 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, 0x2e4f,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2ffb,
+ 0x3000, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312f,
+ 0x3131, 0x318e,
+ 0x3190, 0x31ba,
+ 0x31c0, 0x31e3,
+ 0x31f0, 0x321e,
+ 0x3220, 0x32fe,
+ 0x3300, 0x4db5,
+ 0x4dc0, 0x9fef,
+ 0xa000, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa4d0, 0xa62b,
+ 0xa640, 0xa6f7,
+ 0xa700, 0xa7bf,
+ 0xa7c2, 0xa7c6,
+ 0xa7f7, 0xa82b,
+ 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, 0xab67,
+ 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, 0x1019b,
+ 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,
+ 0x10f00, 0x10f27,
+ 0x10f30, 0x10f59,
+ 0x10fe0, 0x10ff6,
+ 0x11000, 0x1104d,
+ 0x11052, 0x1106f,
+ 0x1107f, 0x110c1,
+ 0x110cd, 0x110cd,
+ 0x110d0, 0x110e8,
+ 0x110f0, 0x110f9,
+ 0x11100, 0x11134,
+ 0x11136, 0x11146,
+ 0x11150, 0x11176,
+ 0x11180, 0x111cd,
+ 0x111d0, 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, 0x11459,
+ 0x1145b, 0x1145b,
+ 0x1145d, 0x1145f,
+ 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, 0x118ff,
+ 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,
+ 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, 0x16fe3,
+ 0x17000, 0x187f7,
+ 0x18800, 0x18af2,
+ 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, 0x1f10c,
+ 0x1f110, 0x1f16c,
+ 0x1f170, 0x1f1ac,
+ 0x1f1e6, 0x1f202,
+ 0x1f210, 0x1f23b,
+ 0x1f240, 0x1f248,
+ 0x1f250, 0x1f251,
+ 0x1f260, 0x1f265,
+ 0x1f300, 0x1f6d5,
+ 0x1f6e0, 0x1f6ec,
+ 0x1f6f0, 0x1f6fa,
+ 0x1f700, 0x1f773,
+ 0x1f780, 0x1f7d8,
+ 0x1f7e0, 0x1f7eb,
+ 0x1f800, 0x1f80b,
+ 0x1f810, 0x1f847,
+ 0x1f850, 0x1f859,
+ 0x1f860, 0x1f887,
+ 0x1f890, 0x1f8ad,
+ 0x1f900, 0x1f90b,
+ 0x1f90d, 0x1f971,
+ 0x1f973, 0x1f976,
+ 0x1f97a, 0x1f9a2,
+ 0x1f9a5, 0x1f9aa,
+ 0x1f9ae, 0x1f9ca,
+ 0x1f9cd, 0x1fa53,
+ 0x1fa60, 0x1fa6d,
+ 0x1fa70, 0x1fa73,
+ 0x1fa78, 0x1fa7a,
+ 0x1fa80, 0x1fa82,
+ 0x1fa90, 0x1fa95,
+ 0x1fffe, 0x2a6d6,
+ 0x2a700, 0x2b734,
+ 0x2b740, 0x2b81d,
+ 0x2b820, 0x2cea1,
+ 0x2ceb0, 0x2ebe0,
+ 0x2f800, 0x2fa1d,
+ 0x2fffe, 0x2ffff,
+ 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_12_0 */
+
+/* 'Age_12_1': Derived Age 12.1 */
+static const OnigCodePoint CR_Age_12_1[] = {
+ 676,
+ 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, 0x08bd,
+ 0x08d3, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fe,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 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,
+ 0x0b56, 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,
+ 0x0be6, 0x0bfa,
+ 0x0c00, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3d, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c5a,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c77, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cde, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf2,
+ 0x0d00, 0x0d03,
+ 0x0d05, 0x0d0c,
+ 0x0d0e, 0x0d10,
+ 0x0d12, 0x0d44,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4f,
+ 0x0d54, 0x0d63,
+ 0x0d66, 0x0d7f,
+ 0x0d82, 0x0d83,
+ 0x0d85, 0x0d96,
+ 0x0d9a, 0x0db1,
+ 0x0db3, 0x0dbb,
+ 0x0dbd, 0x0dbd,
+ 0x0dc0, 0x0dc6,
+ 0x0dca, 0x0dca,
+ 0x0dcf, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 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,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 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,
+ 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, 0x1abe,
+ 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,
+ 0x2b98, 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, 0x2e4f,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2ffb,
+ 0x3000, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312f,
+ 0x3131, 0x318e,
+ 0x3190, 0x31ba,
+ 0x31c0, 0x31e3,
+ 0x31f0, 0x321e,
+ 0x3220, 0x4db5,
+ 0x4dc0, 0x9fef,
+ 0xa000, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa4d0, 0xa62b,
+ 0xa640, 0xa6f7,
+ 0xa700, 0xa7bf,
+ 0xa7c2, 0xa7c6,
+ 0xa7f7, 0xa82b,
+ 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, 0xab67,
+ 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, 0x1019b,
+ 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,
+ 0x10f00, 0x10f27,
+ 0x10f30, 0x10f59,
+ 0x10fe0, 0x10ff6,
+ 0x11000, 0x1104d,
+ 0x11052, 0x1106f,
+ 0x1107f, 0x110c1,
+ 0x110cd, 0x110cd,
+ 0x110d0, 0x110e8,
+ 0x110f0, 0x110f9,
+ 0x11100, 0x11134,
+ 0x11136, 0x11146,
+ 0x11150, 0x11176,
+ 0x11180, 0x111cd,
+ 0x111d0, 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, 0x11459,
+ 0x1145b, 0x1145b,
+ 0x1145d, 0x1145f,
+ 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, 0x118ff,
+ 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,
+ 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, 0x16fe3,
+ 0x17000, 0x187f7,
+ 0x18800, 0x18af2,
+ 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, 0x1f10c,
+ 0x1f110, 0x1f16c,
+ 0x1f170, 0x1f1ac,
+ 0x1f1e6, 0x1f202,
+ 0x1f210, 0x1f23b,
+ 0x1f240, 0x1f248,
+ 0x1f250, 0x1f251,
+ 0x1f260, 0x1f265,
+ 0x1f300, 0x1f6d5,
+ 0x1f6e0, 0x1f6ec,
+ 0x1f6f0, 0x1f6fa,
+ 0x1f700, 0x1f773,
+ 0x1f780, 0x1f7d8,
+ 0x1f7e0, 0x1f7eb,
+ 0x1f800, 0x1f80b,
+ 0x1f810, 0x1f847,
+ 0x1f850, 0x1f859,
+ 0x1f860, 0x1f887,
+ 0x1f890, 0x1f8ad,
+ 0x1f900, 0x1f90b,
+ 0x1f90d, 0x1f971,
+ 0x1f973, 0x1f976,
+ 0x1f97a, 0x1f9a2,
+ 0x1f9a5, 0x1f9aa,
+ 0x1f9ae, 0x1f9ca,
+ 0x1f9cd, 0x1fa53,
+ 0x1fa60, 0x1fa6d,
+ 0x1fa70, 0x1fa73,
+ 0x1fa78, 0x1fa7a,
+ 0x1fa80, 0x1fa82,
+ 0x1fa90, 0x1fa95,
+ 0x1fffe, 0x2a6d6,
+ 0x2a700, 0x2b734,
+ 0x2b740, 0x2b81d,
+ 0x2b820, 0x2cea1,
+ 0x2ceb0, 0x2ebe0,
+ 0x2f800, 0x2fa1d,
+ 0x2fffe, 0x2ffff,
+ 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_12_1 */
+
+/* '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,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fe,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 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,
+ 0x0be6, 0x0bfa,
+ 0x0c00, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3d, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c5a,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c77, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 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, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 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,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 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,
+ 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 */
+
+/* 'Age_14_0': Derived Age 14.0 */
+static const OnigCodePoint CR_Age_14_0[] = {
+ 706,
+ 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, 0x070d,
+ 0x070f, 0x074a,
+ 0x074d, 0x07b1,
+ 0x07c0, 0x07fa,
+ 0x07fd, 0x082d,
+ 0x0830, 0x083e,
+ 0x0840, 0x085b,
+ 0x085e, 0x085e,
+ 0x0860, 0x086a,
+ 0x0870, 0x088e,
+ 0x0890, 0x0891,
+ 0x0898, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fe,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 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,
+ 0x0be6, 0x0bfa,
+ 0x0c00, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3c, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c5a,
+ 0x0c5d, 0x0c5d,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c77, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cdd, 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, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 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,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 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, 0x1715,
+ 0x171f, 0x1736,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x1800, 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, 0x1ace,
+ 0x1b00, 0x1b4c,
+ 0x1b50, 0x1b7e,
+ 0x1b80, 0x1bf3,
+ 0x1bfc, 0x1c37,
+ 0x1c3b, 0x1c49,
+ 0x1c4d, 0x1c88,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cc7,
+ 0x1cd0, 0x1cfa,
+ 0x1d00, 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, 0x20c0,
+ 0x20d0, 0x20f0,
+ 0x2100, 0x218b,
+ 0x2190, 0x2426,
+ 0x2440, 0x244a,
+ 0x2460, 0x2b73,
+ 0x2b76, 0x2b95,
+ 0x2b97, 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, 0x2e5d,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2ffb,
+ 0x3000, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312f,
+ 0x3131, 0x318e,
+ 0x3190, 0x31e3,
+ 0x31f0, 0x321e,
+ 0x3220, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa4d0, 0xa62b,
+ 0xa640, 0xa6f7,
+ 0xa700, 0xa7ca,
+ 0xa7d0, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d9,
+ 0xa7f2, 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, 0xfbc2,
+ 0xfbd3, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdcf, 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, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x10600, 0x10736,
+ 0x10740, 0x10755,
+ 0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 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,
+ 0x10f70, 0x10f89,
+ 0x10fb0, 0x10fcb,
+ 0x10fe0, 0x10ff6,
+ 0x11000, 0x1104d,
+ 0x11052, 0x11075,
+ 0x1107f, 0x110c2,
+ 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, 0x116b9,
+ 0x116c0, 0x116c9,
+ 0x11700, 0x1171a,
+ 0x1171d, 0x1172b,
+ 0x11730, 0x11746,
+ 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,
+ 0x11ab0, 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,
+ 0x12f90, 0x12ff2,
+ 0x13000, 0x1342e,
+ 0x13430, 0x13438,
+ 0x14400, 0x14646,
+ 0x16800, 0x16a38,
+ 0x16a40, 0x16a5e,
+ 0x16a60, 0x16a69,
+ 0x16a6e, 0x16abe,
+ 0x16ac0, 0x16ac9,
+ 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,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b150, 0x1b152,
+ 0x1b164, 0x1b167,
+ 0x1b170, 0x1b2fb,
+ 0x1bc00, 0x1bc6a,
+ 0x1bc70, 0x1bc7c,
+ 0x1bc80, 0x1bc88,
+ 0x1bc90, 0x1bc99,
+ 0x1bc9c, 0x1bca3,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
+ 0x1cf50, 0x1cfc3,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d129, 0x1d1ea,
+ 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,
+ 0x1df00, 0x1df1e,
+ 0x1e000, 0x1e006,
+ 0x1e008, 0x1e018,
+ 0x1e01b, 0x1e021,
+ 0x1e023, 0x1e024,
+ 0x1e026, 0x1e02a,
+ 0x1e100, 0x1e12c,
+ 0x1e130, 0x1e13d,
+ 0x1e140, 0x1e149,
+ 0x1e14e, 0x1e14f,
+ 0x1e290, 0x1e2ae,
+ 0x1e2c0, 0x1e2f9,
+ 0x1e2ff, 0x1e2ff,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
+ 0x1e800, 0x1e8c4,
+ 0x1e8c7, 0x1e8d6,
+ 0x1e900, 0x1e94b,
+ 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,
+ 0x1f6dd, 0x1f6ec,
+ 0x1f6f0, 0x1f6fc,
+ 0x1f700, 0x1f773,
+ 0x1f780, 0x1f7d8,
+ 0x1f7e0, 0x1f7eb,
+ 0x1f7f0, 0x1f7f0,
+ 0x1f800, 0x1f80b,
+ 0x1f810, 0x1f847,
+ 0x1f850, 0x1f859,
+ 0x1f860, 0x1f887,
+ 0x1f890, 0x1f8ad,
+ 0x1f8b0, 0x1f8b1,
+ 0x1f900, 0x1fa53,
+ 0x1fa60, 0x1fa6d,
+ 0x1fa70, 0x1fa74,
+ 0x1fa78, 0x1fa7c,
+ 0x1fa80, 0x1fa86,
+ 0x1fa90, 0x1faac,
+ 0x1fab0, 0x1faba,
+ 0x1fac0, 0x1fac5,
+ 0x1fad0, 0x1fad9,
+ 0x1fae0, 0x1fae7,
+ 0x1faf0, 0x1faf6,
+ 0x1fb00, 0x1fb92,
+ 0x1fb94, 0x1fbca,
+ 0x1fbf0, 0x1fbf9,
+ 0x1fffe, 0x2a6df,
+ 0x2a700, 0x2b738,
+ 0x2b740, 0x2b81d,
+ 0x2b820, 0x2cea1,
+ 0x2ceb0, 0x2ebe0,
+ 0x2f800, 0x2fa1d,
+ 0x2fffe, 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_14_0 */
+
+/* 'Age_15_0': Derived Age 15.0 */
+static const OnigCodePoint CR_Age_15_0[] = {
+ 715,
+ 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, 0x070d,
+ 0x070f, 0x074a,
+ 0x074d, 0x07b1,
+ 0x07c0, 0x07fa,
+ 0x07fd, 0x082d,
+ 0x0830, 0x083e,
+ 0x0840, 0x085b,
+ 0x085e, 0x085e,
+ 0x0860, 0x086a,
+ 0x0870, 0x088e,
+ 0x0890, 0x0891,
+ 0x0898, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fe,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 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,
+ 0x0be6, 0x0bfa,
+ 0x0c00, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3c, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c5a,
+ 0x0c5d, 0x0c5d,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c77, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cdd, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf3,
+ 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, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 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, 0x0ece,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 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, 0x1715,
+ 0x171f, 0x1736,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x1800, 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, 0x1ace,
+ 0x1b00, 0x1b4c,
+ 0x1b50, 0x1b7e,
+ 0x1b80, 0x1bf3,
+ 0x1bfc, 0x1c37,
+ 0x1c3b, 0x1c49,
+ 0x1c4d, 0x1c88,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cc7,
+ 0x1cd0, 0x1cfa,
+ 0x1d00, 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, 0x20c0,
+ 0x20d0, 0x20f0,
+ 0x2100, 0x218b,
+ 0x2190, 0x2426,
+ 0x2440, 0x244a,
+ 0x2460, 0x2b73,
+ 0x2b76, 0x2b95,
+ 0x2b97, 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, 0x2e5d,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x2ffb,
+ 0x3000, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312f,
+ 0x3131, 0x318e,
+ 0x3190, 0x31e3,
+ 0x31f0, 0x321e,
+ 0x3220, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa4d0, 0xa62b,
+ 0xa640, 0xa6f7,
+ 0xa700, 0xa7ca,
+ 0xa7d0, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d9,
+ 0xa7f2, 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, 0xfbc2,
+ 0xfbd3, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdcf, 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, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x10600, 0x10736,
+ 0x10740, 0x10755,
+ 0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 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,
+ 0x10efd, 0x10f27,
+ 0x10f30, 0x10f59,
+ 0x10f70, 0x10f89,
+ 0x10fb0, 0x10fcb,
+ 0x10fe0, 0x10ff6,
+ 0x11000, 0x1104d,
+ 0x11052, 0x11075,
+ 0x1107f, 0x110c2,
+ 0x110cd, 0x110cd,
+ 0x110d0, 0x110e8,
+ 0x110f0, 0x110f9,
+ 0x11100, 0x11134,
+ 0x11136, 0x11147,
+ 0x11150, 0x11176,
+ 0x11180, 0x111df,
+ 0x111e1, 0x111f4,
+ 0x11200, 0x11211,
+ 0x11213, 0x11241,
+ 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, 0x116b9,
+ 0x116c0, 0x116c9,
+ 0x11700, 0x1171a,
+ 0x1171d, 0x1172b,
+ 0x11730, 0x11746,
+ 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,
+ 0x11ab0, 0x11af8,
+ 0x11b00, 0x11b09,
+ 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,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f59,
+ 0x11fb0, 0x11fb0,
+ 0x11fc0, 0x11ff1,
+ 0x11fff, 0x12399,
+ 0x12400, 0x1246e,
+ 0x12470, 0x12474,
+ 0x12480, 0x12543,
+ 0x12f90, 0x12ff2,
+ 0x13000, 0x13455,
+ 0x14400, 0x14646,
+ 0x16800, 0x16a38,
+ 0x16a40, 0x16a5e,
+ 0x16a60, 0x16a69,
+ 0x16a6e, 0x16abe,
+ 0x16ac0, 0x16ac9,
+ 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,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
+ 0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
+ 0x1b164, 0x1b167,
+ 0x1b170, 0x1b2fb,
+ 0x1bc00, 0x1bc6a,
+ 0x1bc70, 0x1bc7c,
+ 0x1bc80, 0x1bc88,
+ 0x1bc90, 0x1bc99,
+ 0x1bc9c, 0x1bca3,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
+ 0x1cf50, 0x1cfc3,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d129, 0x1d1ea,
+ 0x1d200, 0x1d245,
+ 0x1d2c0, 0x1d2d3,
+ 0x1d2e0, 0x1d2f3,
+ 0x1d300, 0x1d356,
+ 0x1d360, 0x1d378,
+ 0x1d400, 0x1d454,
+ 0x1d456, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 0x1d4a2, 0x1d4a2,
+ 0x1d4a5, 0x1d4a6,
+ 0x1d4a9, 0x1d4ac,
+ 0x1d4ae, 0x1d4b9,
+ 0x1d4bb, 0x1d4bb,
+ 0x1d4bd, 0x1d4c3,
+ 0x1d4c5, 0x1d505,
+ 0x1d507, 0x1d50a,
+ 0x1d50d, 0x1d514,
+ 0x1d516, 0x1d51c,
+ 0x1d51e, 0x1d539,
+ 0x1d53b, 0x1d53e,
+ 0x1d540, 0x1d544,
+ 0x1d546, 0x1d546,
+ 0x1d54a, 0x1d550,
+ 0x1d552, 0x1d6a5,
+ 0x1d6a8, 0x1d7cb,
+ 0x1d7ce, 0x1da8b,
+ 0x1da9b, 0x1da9f,
+ 0x1daa1, 0x1daaf,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e000, 0x1e006,
+ 0x1e008, 0x1e018,
+ 0x1e01b, 0x1e021,
+ 0x1e023, 0x1e024,
+ 0x1e026, 0x1e02a,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
+ 0x1e100, 0x1e12c,
+ 0x1e130, 0x1e13d,
+ 0x1e140, 0x1e149,
+ 0x1e14e, 0x1e14f,
+ 0x1e290, 0x1e2ae,
+ 0x1e2c0, 0x1e2f9,
+ 0x1e2ff, 0x1e2ff,
+ 0x1e4d0, 0x1e4f9,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
+ 0x1e800, 0x1e8c4,
+ 0x1e8c7, 0x1e8d6,
+ 0x1e900, 0x1e94b,
+ 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,
+ 0x1f6dc, 0x1f6ec,
+ 0x1f6f0, 0x1f6fc,
+ 0x1f700, 0x1f776,
+ 0x1f77b, 0x1f7d9,
+ 0x1f7e0, 0x1f7eb,
+ 0x1f7f0, 0x1f7f0,
+ 0x1f800, 0x1f80b,
+ 0x1f810, 0x1f847,
+ 0x1f850, 0x1f859,
+ 0x1f860, 0x1f887,
+ 0x1f890, 0x1f8ad,
+ 0x1f8b0, 0x1f8b1,
+ 0x1f900, 0x1fa53,
+ 0x1fa60, 0x1fa6d,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa88,
+ 0x1fa90, 0x1fabd,
+ 0x1fabf, 0x1fac5,
+ 0x1face, 0x1fadb,
+ 0x1fae0, 0x1fae8,
+ 0x1faf0, 0x1faf8,
+ 0x1fb00, 0x1fb92,
+ 0x1fb94, 0x1fbca,
+ 0x1fbf0, 0x1fbf9,
+ 0x1fffe, 0x2a6df,
+ 0x2a700, 0x2b739,
+ 0x2b740, 0x2b81d,
+ 0x2b820, 0x2cea1,
+ 0x2ceb0, 0x2ebe0,
+ 0x2f800, 0x2fa1d,
+ 0x2fffe, 0x3134a,
+ 0x31350, 0x323af,
+ 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_15_0 */
+
+/* 'Age_15_1': Derived Age 15.1 */
+static const OnigCodePoint CR_Age_15_1[] = {
+ 715,
+ 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, 0x070d,
+ 0x070f, 0x074a,
+ 0x074d, 0x07b1,
+ 0x07c0, 0x07fa,
+ 0x07fd, 0x082d,
+ 0x0830, 0x083e,
+ 0x0840, 0x085b,
+ 0x085e, 0x085e,
+ 0x0860, 0x086a,
+ 0x0870, 0x088e,
+ 0x0890, 0x0891,
+ 0x0898, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fe,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 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,
+ 0x0be6, 0x0bfa,
+ 0x0c00, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3c, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c5a,
+ 0x0c5d, 0x0c5d,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c77, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cdd, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf3,
+ 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, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 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, 0x0ece,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 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, 0x1715,
+ 0x171f, 0x1736,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x1800, 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, 0x1ace,
+ 0x1b00, 0x1b4c,
+ 0x1b50, 0x1b7e,
+ 0x1b80, 0x1bf3,
+ 0x1bfc, 0x1c37,
+ 0x1c3b, 0x1c49,
+ 0x1c4d, 0x1c88,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cc7,
+ 0x1cd0, 0x1cfa,
+ 0x1d00, 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, 0x20c0,
+ 0x20d0, 0x20f0,
+ 0x2100, 0x218b,
+ 0x2190, 0x2426,
+ 0x2440, 0x244a,
+ 0x2460, 0x2b73,
+ 0x2b76, 0x2b95,
+ 0x2b97, 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, 0x2e5d,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312f,
+ 0x3131, 0x318e,
+ 0x3190, 0x31e3,
+ 0x31ef, 0x321e,
+ 0x3220, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa4d0, 0xa62b,
+ 0xa640, 0xa6f7,
+ 0xa700, 0xa7ca,
+ 0xa7d0, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7d9,
+ 0xa7f2, 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, 0xfbc2,
+ 0xfbd3, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdcf, 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, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x10600, 0x10736,
+ 0x10740, 0x10755,
+ 0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 0x10800, 0x10805,
+ 0x10808, 0x10808,
+ 0x1080a, 0x10835,
+ 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,
+ 0x10efd, 0x10f27,
+ 0x10f30, 0x10f59,
+ 0x10f70, 0x10f89,
+ 0x10fb0, 0x10fcb,
+ 0x10fe0, 0x10ff6,
+ 0x11000, 0x1104d,
+ 0x11052, 0x11075,
+ 0x1107f, 0x110c2,
+ 0x110cd, 0x110cd,
+ 0x110d0, 0x110e8,
+ 0x110f0, 0x110f9,
+ 0x11100, 0x11134,
+ 0x11136, 0x11147,
+ 0x11150, 0x11176,
+ 0x11180, 0x111df,
+ 0x111e1, 0x111f4,
+ 0x11200, 0x11211,
+ 0x11213, 0x11241,
+ 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, 0x116b9,
+ 0x116c0, 0x116c9,
+ 0x11700, 0x1171a,
+ 0x1171d, 0x1172b,
+ 0x11730, 0x11746,
+ 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,
+ 0x11ab0, 0x11af8,
+ 0x11b00, 0x11b09,
+ 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,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f59,
+ 0x11fb0, 0x11fb0,
+ 0x11fc0, 0x11ff1,
+ 0x11fff, 0x12399,
+ 0x12400, 0x1246e,
+ 0x12470, 0x12474,
+ 0x12480, 0x12543,
+ 0x12f90, 0x12ff2,
+ 0x13000, 0x13455,
+ 0x14400, 0x14646,
+ 0x16800, 0x16a38,
+ 0x16a40, 0x16a5e,
+ 0x16a60, 0x16a69,
+ 0x16a6e, 0x16abe,
+ 0x16ac0, 0x16ac9,
+ 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,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
+ 0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
+ 0x1b164, 0x1b167,
+ 0x1b170, 0x1b2fb,
+ 0x1bc00, 0x1bc6a,
+ 0x1bc70, 0x1bc7c,
+ 0x1bc80, 0x1bc88,
+ 0x1bc90, 0x1bc99,
+ 0x1bc9c, 0x1bca3,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
+ 0x1cf50, 0x1cfc3,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d129, 0x1d1ea,
+ 0x1d200, 0x1d245,
+ 0x1d2c0, 0x1d2d3,
+ 0x1d2e0, 0x1d2f3,
+ 0x1d300, 0x1d356,
+ 0x1d360, 0x1d378,
+ 0x1d400, 0x1d454,
+ 0x1d456, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 0x1d4a2, 0x1d4a2,
+ 0x1d4a5, 0x1d4a6,
+ 0x1d4a9, 0x1d4ac,
+ 0x1d4ae, 0x1d4b9,
+ 0x1d4bb, 0x1d4bb,
+ 0x1d4bd, 0x1d4c3,
+ 0x1d4c5, 0x1d505,
+ 0x1d507, 0x1d50a,
+ 0x1d50d, 0x1d514,
+ 0x1d516, 0x1d51c,
+ 0x1d51e, 0x1d539,
+ 0x1d53b, 0x1d53e,
+ 0x1d540, 0x1d544,
+ 0x1d546, 0x1d546,
+ 0x1d54a, 0x1d550,
+ 0x1d552, 0x1d6a5,
+ 0x1d6a8, 0x1d7cb,
+ 0x1d7ce, 0x1da8b,
+ 0x1da9b, 0x1da9f,
+ 0x1daa1, 0x1daaf,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e000, 0x1e006,
+ 0x1e008, 0x1e018,
+ 0x1e01b, 0x1e021,
+ 0x1e023, 0x1e024,
+ 0x1e026, 0x1e02a,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
+ 0x1e100, 0x1e12c,
+ 0x1e130, 0x1e13d,
+ 0x1e140, 0x1e149,
+ 0x1e14e, 0x1e14f,
+ 0x1e290, 0x1e2ae,
+ 0x1e2c0, 0x1e2f9,
+ 0x1e2ff, 0x1e2ff,
+ 0x1e4d0, 0x1e4f9,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
+ 0x1e800, 0x1e8c4,
+ 0x1e8c7, 0x1e8d6,
+ 0x1e900, 0x1e94b,
+ 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,
+ 0x1f6dc, 0x1f6ec,
+ 0x1f6f0, 0x1f6fc,
+ 0x1f700, 0x1f776,
+ 0x1f77b, 0x1f7d9,
+ 0x1f7e0, 0x1f7eb,
+ 0x1f7f0, 0x1f7f0,
+ 0x1f800, 0x1f80b,
+ 0x1f810, 0x1f847,
+ 0x1f850, 0x1f859,
+ 0x1f860, 0x1f887,
+ 0x1f890, 0x1f8ad,
+ 0x1f8b0, 0x1f8b1,
+ 0x1f900, 0x1fa53,
+ 0x1fa60, 0x1fa6d,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa88,
+ 0x1fa90, 0x1fabd,
+ 0x1fabf, 0x1fac5,
+ 0x1face, 0x1fadb,
+ 0x1fae0, 0x1fae8,
+ 0x1faf0, 0x1faf8,
+ 0x1fb00, 0x1fb92,
+ 0x1fb94, 0x1fbca,
+ 0x1fbf0, 0x1fbf9,
+ 0x1fffe, 0x2a6df,
+ 0x2a700, 0x2b739,
+ 0x2b740, 0x2b81d,
+ 0x2b820, 0x2cea1,
+ 0x2ceb0, 0x2ebe0,
+ 0x2ebf0, 0x2ee5d,
+ 0x2f800, 0x2fa1d,
+ 0x2fffe, 0x3134a,
+ 0x31350, 0x323af,
+ 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_15_1 */
+
+/* 'Age_16_0': Derived Age 16.0 */
+static const OnigCodePoint CR_Age_16_0[] = {
+ 739,
+ 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, 0x070d,
+ 0x070f, 0x074a,
+ 0x074d, 0x07b1,
+ 0x07c0, 0x07fa,
+ 0x07fd, 0x082d,
+ 0x0830, 0x083e,
+ 0x0840, 0x085b,
+ 0x085e, 0x085e,
+ 0x0860, 0x086a,
+ 0x0870, 0x088e,
+ 0x0890, 0x0891,
+ 0x0897, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fe,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 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,
+ 0x0be6, 0x0bfa,
+ 0x0c00, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3c, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c5a,
+ 0x0c5d, 0x0c5d,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c77, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cdd, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf3,
+ 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, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 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, 0x0ece,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 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, 0x1715,
+ 0x171f, 0x1736,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x1800, 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, 0x1ace,
+ 0x1b00, 0x1b4c,
+ 0x1b4e, 0x1bf3,
+ 0x1bfc, 0x1c37,
+ 0x1c3b, 0x1c49,
+ 0x1c4d, 0x1c8a,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cc7,
+ 0x1cd0, 0x1cfa,
+ 0x1d00, 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, 0x20c0,
+ 0x20d0, 0x20f0,
+ 0x2100, 0x218b,
+ 0x2190, 0x2429,
+ 0x2440, 0x244a,
+ 0x2460, 0x2b73,
+ 0x2b76, 0x2b95,
+ 0x2b97, 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, 0x2e5d,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312f,
+ 0x3131, 0x318e,
+ 0x3190, 0x31e5,
+ 0x31ef, 0x321e,
+ 0x3220, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa4d0, 0xa62b,
+ 0xa640, 0xa6f7,
+ 0xa700, 0xa7cd,
+ 0xa7d0, 0xa7d1,
+ 0xa7d3, 0xa7d3,
+ 0xa7d5, 0xa7dc,
+ 0xa7f2, 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, 0xfbc2,
+ 0xfbd3, 0xfd8f,
+ 0xfd92, 0xfdc7,
+ 0xfdcf, 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, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x105c0, 0x105f3,
+ 0x10600, 0x10736,
+ 0x10740, 0x10755,
+ 0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 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,
+ 0x10d40, 0x10d65,
+ 0x10d69, 0x10d85,
+ 0x10d8e, 0x10d8f,
+ 0x10e60, 0x10e7e,
+ 0x10e80, 0x10ea9,
+ 0x10eab, 0x10ead,
+ 0x10eb0, 0x10eb1,
+ 0x10ec2, 0x10ec4,
+ 0x10efc, 0x10f27,
+ 0x10f30, 0x10f59,
+ 0x10f70, 0x10f89,
+ 0x10fb0, 0x10fcb,
+ 0x10fe0, 0x10ff6,
+ 0x11000, 0x1104d,
+ 0x11052, 0x11075,
+ 0x1107f, 0x110c2,
+ 0x110cd, 0x110cd,
+ 0x110d0, 0x110e8,
+ 0x110f0, 0x110f9,
+ 0x11100, 0x11134,
+ 0x11136, 0x11147,
+ 0x11150, 0x11176,
+ 0x11180, 0x111df,
+ 0x111e1, 0x111f4,
+ 0x11200, 0x11211,
+ 0x11213, 0x11241,
+ 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,
+ 0x11380, 0x11389,
+ 0x1138b, 0x1138b,
+ 0x1138e, 0x1138e,
+ 0x11390, 0x113b5,
+ 0x113b7, 0x113c0,
+ 0x113c2, 0x113c2,
+ 0x113c5, 0x113c5,
+ 0x113c7, 0x113ca,
+ 0x113cc, 0x113d5,
+ 0x113d7, 0x113d8,
+ 0x113e1, 0x113e2,
+ 0x11400, 0x1145b,
+ 0x1145d, 0x11461,
+ 0x11480, 0x114c7,
+ 0x114d0, 0x114d9,
+ 0x11580, 0x115b5,
+ 0x115b8, 0x115dd,
+ 0x11600, 0x11644,
+ 0x11650, 0x11659,
+ 0x11660, 0x1166c,
+ 0x11680, 0x116b9,
+ 0x116c0, 0x116c9,
+ 0x116d0, 0x116e3,
+ 0x11700, 0x1171a,
+ 0x1171d, 0x1172b,
+ 0x11730, 0x11746,
+ 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,
+ 0x11ab0, 0x11af8,
+ 0x11b00, 0x11b09,
+ 0x11bc0, 0x11be1,
+ 0x11bf0, 0x11bf9,
+ 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,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f5a,
+ 0x11fb0, 0x11fb0,
+ 0x11fc0, 0x11ff1,
+ 0x11fff, 0x12399,
+ 0x12400, 0x1246e,
+ 0x12470, 0x12474,
+ 0x12480, 0x12543,
+ 0x12f90, 0x12ff2,
+ 0x13000, 0x13455,
+ 0x13460, 0x143fa,
+ 0x14400, 0x14646,
+ 0x16100, 0x16139,
+ 0x16800, 0x16a38,
+ 0x16a40, 0x16a5e,
+ 0x16a60, 0x16a69,
+ 0x16a6e, 0x16abe,
+ 0x16ac0, 0x16ac9,
+ 0x16ad0, 0x16aed,
+ 0x16af0, 0x16af5,
+ 0x16b00, 0x16b45,
+ 0x16b50, 0x16b59,
+ 0x16b5b, 0x16b61,
+ 0x16b63, 0x16b77,
+ 0x16b7d, 0x16b8f,
+ 0x16d40, 0x16d79,
+ 0x16e40, 0x16e9a,
+ 0x16f00, 0x16f4a,
+ 0x16f4f, 0x16f87,
+ 0x16f8f, 0x16f9f,
+ 0x16fe0, 0x16fe4,
+ 0x16ff0, 0x16ff1,
+ 0x17000, 0x187f7,
+ 0x18800, 0x18cd5,
+ 0x18cff, 0x18d08,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
+ 0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
+ 0x1b164, 0x1b167,
+ 0x1b170, 0x1b2fb,
+ 0x1bc00, 0x1bc6a,
+ 0x1bc70, 0x1bc7c,
+ 0x1bc80, 0x1bc88,
+ 0x1bc90, 0x1bc99,
+ 0x1bc9c, 0x1bca3,
+ 0x1cc00, 0x1ccf9,
+ 0x1cd00, 0x1ceb3,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
+ 0x1cf50, 0x1cfc3,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d129, 0x1d1ea,
+ 0x1d200, 0x1d245,
+ 0x1d2c0, 0x1d2d3,
+ 0x1d2e0, 0x1d2f3,
+ 0x1d300, 0x1d356,
+ 0x1d360, 0x1d378,
+ 0x1d400, 0x1d454,
+ 0x1d456, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 0x1d4a2, 0x1d4a2,
+ 0x1d4a5, 0x1d4a6,
+ 0x1d4a9, 0x1d4ac,
+ 0x1d4ae, 0x1d4b9,
+ 0x1d4bb, 0x1d4bb,
+ 0x1d4bd, 0x1d4c3,
+ 0x1d4c5, 0x1d505,
+ 0x1d507, 0x1d50a,
+ 0x1d50d, 0x1d514,
+ 0x1d516, 0x1d51c,
+ 0x1d51e, 0x1d539,
+ 0x1d53b, 0x1d53e,
+ 0x1d540, 0x1d544,
+ 0x1d546, 0x1d546,
+ 0x1d54a, 0x1d550,
+ 0x1d552, 0x1d6a5,
+ 0x1d6a8, 0x1d7cb,
+ 0x1d7ce, 0x1da8b,
+ 0x1da9b, 0x1da9f,
+ 0x1daa1, 0x1daaf,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e000, 0x1e006,
+ 0x1e008, 0x1e018,
+ 0x1e01b, 0x1e021,
+ 0x1e023, 0x1e024,
+ 0x1e026, 0x1e02a,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
+ 0x1e100, 0x1e12c,
+ 0x1e130, 0x1e13d,
+ 0x1e140, 0x1e149,
+ 0x1e14e, 0x1e14f,
+ 0x1e290, 0x1e2ae,
+ 0x1e2c0, 0x1e2f9,
+ 0x1e2ff, 0x1e2ff,
+ 0x1e4d0, 0x1e4f9,
+ 0x1e5d0, 0x1e5fa,
+ 0x1e5ff, 0x1e5ff,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
+ 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,
+ 0x1f6dc, 0x1f6ec,
+ 0x1f6f0, 0x1f6fc,
+ 0x1f700, 0x1f776,
+ 0x1f77b, 0x1f7d9,
+ 0x1f7e0, 0x1f7eb,
+ 0x1f7f0, 0x1f7f0,
+ 0x1f800, 0x1f80b,
+ 0x1f810, 0x1f847,
+ 0x1f850, 0x1f859,
+ 0x1f860, 0x1f887,
+ 0x1f890, 0x1f8ad,
+ 0x1f8b0, 0x1f8bb,
+ 0x1f8c0, 0x1f8c1,
+ 0x1f900, 0x1fa53,
+ 0x1fa60, 0x1fa6d,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa89,
+ 0x1fa8f, 0x1fac6,
+ 0x1face, 0x1fadc,
+ 0x1fadf, 0x1fae9,
+ 0x1faf0, 0x1faf8,
+ 0x1fb00, 0x1fb92,
+ 0x1fb94, 0x1fbf9,
+ 0x1fffe, 0x2a6df,
+ 0x2a700, 0x2b739,
+ 0x2b740, 0x2b81d,
+ 0x2b820, 0x2cea1,
+ 0x2ceb0, 0x2ebe0,
+ 0x2ebf0, 0x2ee5d,
+ 0x2f800, 0x2fa1d,
+ 0x2fffe, 0x3134a,
+ 0x31350, 0x323af,
+ 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_16_0 */
+
+/* 'Age_17_0': Derived Age 17.0 */
+static const OnigCodePoint CR_Age_17_0[] = {
+ 743,
+ 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, 0x070d,
+ 0x070f, 0x074a,
+ 0x074d, 0x07b1,
+ 0x07c0, 0x07fa,
+ 0x07fd, 0x082d,
+ 0x0830, 0x083e,
+ 0x0840, 0x085b,
+ 0x085e, 0x085e,
+ 0x0860, 0x086a,
+ 0x0870, 0x0891,
+ 0x0897, 0x0983,
+ 0x0985, 0x098c,
+ 0x098f, 0x0990,
+ 0x0993, 0x09a8,
+ 0x09aa, 0x09b0,
+ 0x09b2, 0x09b2,
+ 0x09b6, 0x09b9,
+ 0x09bc, 0x09c4,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09ce,
+ 0x09d7, 0x09d7,
+ 0x09dc, 0x09dd,
+ 0x09df, 0x09e3,
+ 0x09e6, 0x09fe,
+ 0x0a01, 0x0a03,
+ 0x0a05, 0x0a0a,
+ 0x0a0f, 0x0a10,
+ 0x0a13, 0x0a28,
+ 0x0a2a, 0x0a30,
+ 0x0a32, 0x0a33,
+ 0x0a35, 0x0a36,
+ 0x0a38, 0x0a39,
+ 0x0a3c, 0x0a3c,
+ 0x0a3e, 0x0a42,
+ 0x0a47, 0x0a48,
+ 0x0a4b, 0x0a4d,
+ 0x0a51, 0x0a51,
+ 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,
+ 0x0be6, 0x0bfa,
+ 0x0c00, 0x0c0c,
+ 0x0c0e, 0x0c10,
+ 0x0c12, 0x0c28,
+ 0x0c2a, 0x0c39,
+ 0x0c3c, 0x0c44,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c58, 0x0c5a,
+ 0x0c5c, 0x0c5d,
+ 0x0c60, 0x0c63,
+ 0x0c66, 0x0c6f,
+ 0x0c77, 0x0c8c,
+ 0x0c8e, 0x0c90,
+ 0x0c92, 0x0ca8,
+ 0x0caa, 0x0cb3,
+ 0x0cb5, 0x0cb9,
+ 0x0cbc, 0x0cc4,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0cdc, 0x0cde,
+ 0x0ce0, 0x0ce3,
+ 0x0ce6, 0x0cef,
+ 0x0cf1, 0x0cf3,
+ 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, 0x0dd4,
+ 0x0dd6, 0x0dd6,
+ 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, 0x0ece,
+ 0x0ed0, 0x0ed9,
+ 0x0edc, 0x0edf,
+ 0x0f00, 0x0f47,
+ 0x0f49, 0x0f6c,
+ 0x0f71, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 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, 0x1715,
+ 0x171f, 0x1736,
+ 0x1740, 0x1753,
+ 0x1760, 0x176c,
+ 0x176e, 0x1770,
+ 0x1772, 0x1773,
+ 0x1780, 0x17dd,
+ 0x17e0, 0x17e9,
+ 0x17f0, 0x17f9,
+ 0x1800, 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, 0x1add,
+ 0x1ae0, 0x1aeb,
+ 0x1b00, 0x1b4c,
+ 0x1b4e, 0x1bf3,
+ 0x1bfc, 0x1c37,
+ 0x1c3b, 0x1c49,
+ 0x1c4d, 0x1c8a,
+ 0x1c90, 0x1cba,
+ 0x1cbd, 0x1cc7,
+ 0x1cd0, 0x1cfa,
+ 0x1d00, 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, 0x20c1,
+ 0x20d0, 0x20f0,
+ 0x2100, 0x218b,
+ 0x2190, 0x2429,
+ 0x2440, 0x244a,
+ 0x2460, 0x2b73,
+ 0x2b76, 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, 0x2e5d,
+ 0x2e80, 0x2e99,
+ 0x2e9b, 0x2ef3,
+ 0x2f00, 0x2fd5,
+ 0x2ff0, 0x303f,
+ 0x3041, 0x3096,
+ 0x3099, 0x30ff,
+ 0x3105, 0x312f,
+ 0x3131, 0x318e,
+ 0x3190, 0x31e5,
+ 0x31ef, 0x321e,
+ 0x3220, 0xa48c,
+ 0xa490, 0xa4c6,
+ 0xa4d0, 0xa62b,
+ 0xa640, 0xa6f7,
+ 0xa700, 0xa7dc,
+ 0xa7f1, 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, 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, 0x1057a,
+ 0x1057c, 0x1058a,
+ 0x1058c, 0x10592,
+ 0x10594, 0x10595,
+ 0x10597, 0x105a1,
+ 0x105a3, 0x105b1,
+ 0x105b3, 0x105b9,
+ 0x105bb, 0x105bc,
+ 0x105c0, 0x105f3,
+ 0x10600, 0x10736,
+ 0x10740, 0x10755,
+ 0x10760, 0x10767,
+ 0x10780, 0x10785,
+ 0x10787, 0x107b0,
+ 0x107b2, 0x107ba,
+ 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, 0x10959,
+ 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,
+ 0x10d40, 0x10d65,
+ 0x10d69, 0x10d85,
+ 0x10d8e, 0x10d8f,
+ 0x10e60, 0x10e7e,
+ 0x10e80, 0x10ea9,
+ 0x10eab, 0x10ead,
+ 0x10eb0, 0x10eb1,
+ 0x10ec2, 0x10ec7,
+ 0x10ed0, 0x10ed8,
+ 0x10efa, 0x10f27,
+ 0x10f30, 0x10f59,
+ 0x10f70, 0x10f89,
+ 0x10fb0, 0x10fcb,
+ 0x10fe0, 0x10ff6,
+ 0x11000, 0x1104d,
+ 0x11052, 0x11075,
+ 0x1107f, 0x110c2,
+ 0x110cd, 0x110cd,
+ 0x110d0, 0x110e8,
+ 0x110f0, 0x110f9,
+ 0x11100, 0x11134,
+ 0x11136, 0x11147,
+ 0x11150, 0x11176,
+ 0x11180, 0x111df,
+ 0x111e1, 0x111f4,
+ 0x11200, 0x11211,
+ 0x11213, 0x11241,
+ 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,
+ 0x11380, 0x11389,
+ 0x1138b, 0x1138b,
+ 0x1138e, 0x1138e,
+ 0x11390, 0x113b5,
+ 0x113b7, 0x113c0,
+ 0x113c2, 0x113c2,
+ 0x113c5, 0x113c5,
+ 0x113c7, 0x113ca,
+ 0x113cc, 0x113d5,
+ 0x113d7, 0x113d8,
+ 0x113e1, 0x113e2,
+ 0x11400, 0x1145b,
+ 0x1145d, 0x11461,
+ 0x11480, 0x114c7,
+ 0x114d0, 0x114d9,
+ 0x11580, 0x115b5,
+ 0x115b8, 0x115dd,
+ 0x11600, 0x11644,
+ 0x11650, 0x11659,
+ 0x11660, 0x1166c,
+ 0x11680, 0x116b9,
+ 0x116c0, 0x116c9,
+ 0x116d0, 0x116e3,
+ 0x11700, 0x1171a,
+ 0x1171d, 0x1172b,
+ 0x11730, 0x11746,
+ 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,
+ 0x11ab0, 0x11af8,
+ 0x11b00, 0x11b09,
+ 0x11b60, 0x11b67,
+ 0x11bc0, 0x11be1,
+ 0x11bf0, 0x11bf9,
+ 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,
+ 0x11db0, 0x11ddb,
+ 0x11de0, 0x11de9,
+ 0x11ee0, 0x11ef8,
+ 0x11f00, 0x11f10,
+ 0x11f12, 0x11f3a,
+ 0x11f3e, 0x11f5a,
+ 0x11fb0, 0x11fb0,
+ 0x11fc0, 0x11ff1,
+ 0x11fff, 0x12399,
+ 0x12400, 0x1246e,
+ 0x12470, 0x12474,
+ 0x12480, 0x12543,
+ 0x12f90, 0x12ff2,
+ 0x13000, 0x13455,
+ 0x13460, 0x143fa,
+ 0x14400, 0x14646,
+ 0x16100, 0x16139,
+ 0x16800, 0x16a38,
+ 0x16a40, 0x16a5e,
+ 0x16a60, 0x16a69,
+ 0x16a6e, 0x16abe,
+ 0x16ac0, 0x16ac9,
+ 0x16ad0, 0x16aed,
+ 0x16af0, 0x16af5,
+ 0x16b00, 0x16b45,
+ 0x16b50, 0x16b59,
+ 0x16b5b, 0x16b61,
+ 0x16b63, 0x16b77,
+ 0x16b7d, 0x16b8f,
+ 0x16d40, 0x16d79,
+ 0x16e40, 0x16e9a,
+ 0x16ea0, 0x16eb8,
+ 0x16ebb, 0x16ed3,
+ 0x16f00, 0x16f4a,
+ 0x16f4f, 0x16f87,
+ 0x16f8f, 0x16f9f,
+ 0x16fe0, 0x16fe4,
+ 0x16ff0, 0x16ff6,
+ 0x17000, 0x18cd5,
+ 0x18cff, 0x18d1e,
+ 0x18d80, 0x18df2,
+ 0x1aff0, 0x1aff3,
+ 0x1aff5, 0x1affb,
+ 0x1affd, 0x1affe,
+ 0x1b000, 0x1b122,
+ 0x1b132, 0x1b132,
+ 0x1b150, 0x1b152,
+ 0x1b155, 0x1b155,
+ 0x1b164, 0x1b167,
+ 0x1b170, 0x1b2fb,
+ 0x1bc00, 0x1bc6a,
+ 0x1bc70, 0x1bc7c,
+ 0x1bc80, 0x1bc88,
+ 0x1bc90, 0x1bc99,
+ 0x1bc9c, 0x1bca3,
+ 0x1cc00, 0x1ccfc,
+ 0x1cd00, 0x1ceb3,
+ 0x1ceba, 0x1ced0,
+ 0x1cee0, 0x1cef0,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
+ 0x1cf50, 0x1cfc3,
+ 0x1d000, 0x1d0f5,
+ 0x1d100, 0x1d126,
+ 0x1d129, 0x1d1ea,
+ 0x1d200, 0x1d245,
+ 0x1d2c0, 0x1d2d3,
+ 0x1d2e0, 0x1d2f3,
+ 0x1d300, 0x1d356,
+ 0x1d360, 0x1d378,
+ 0x1d400, 0x1d454,
+ 0x1d456, 0x1d49c,
+ 0x1d49e, 0x1d49f,
+ 0x1d4a2, 0x1d4a2,
+ 0x1d4a5, 0x1d4a6,
+ 0x1d4a9, 0x1d4ac,
+ 0x1d4ae, 0x1d4b9,
+ 0x1d4bb, 0x1d4bb,
+ 0x1d4bd, 0x1d4c3,
+ 0x1d4c5, 0x1d505,
+ 0x1d507, 0x1d50a,
+ 0x1d50d, 0x1d514,
+ 0x1d516, 0x1d51c,
+ 0x1d51e, 0x1d539,
+ 0x1d53b, 0x1d53e,
+ 0x1d540, 0x1d544,
+ 0x1d546, 0x1d546,
+ 0x1d54a, 0x1d550,
+ 0x1d552, 0x1d6a5,
+ 0x1d6a8, 0x1d7cb,
+ 0x1d7ce, 0x1da8b,
+ 0x1da9b, 0x1da9f,
+ 0x1daa1, 0x1daaf,
+ 0x1df00, 0x1df1e,
+ 0x1df25, 0x1df2a,
+ 0x1e000, 0x1e006,
+ 0x1e008, 0x1e018,
+ 0x1e01b, 0x1e021,
+ 0x1e023, 0x1e024,
+ 0x1e026, 0x1e02a,
+ 0x1e030, 0x1e06d,
+ 0x1e08f, 0x1e08f,
+ 0x1e100, 0x1e12c,
+ 0x1e130, 0x1e13d,
+ 0x1e140, 0x1e149,
+ 0x1e14e, 0x1e14f,
+ 0x1e290, 0x1e2ae,
+ 0x1e2c0, 0x1e2f9,
+ 0x1e2ff, 0x1e2ff,
+ 0x1e4d0, 0x1e4f9,
+ 0x1e5d0, 0x1e5fa,
+ 0x1e5ff, 0x1e5ff,
+ 0x1e6c0, 0x1e6de,
+ 0x1e6e0, 0x1e6f5,
+ 0x1e6fe, 0x1e6ff,
+ 0x1e7e0, 0x1e7e6,
+ 0x1e7e8, 0x1e7eb,
+ 0x1e7ed, 0x1e7ee,
+ 0x1e7f0, 0x1e7fe,
+ 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, 0x1f6d8,
+ 0x1f6dc, 0x1f6ec,
+ 0x1f6f0, 0x1f6fc,
+ 0x1f700, 0x1f7d9,
+ 0x1f7e0, 0x1f7eb,
+ 0x1f7f0, 0x1f7f0,
+ 0x1f800, 0x1f80b,
+ 0x1f810, 0x1f847,
+ 0x1f850, 0x1f859,
+ 0x1f860, 0x1f887,
+ 0x1f890, 0x1f8ad,
+ 0x1f8b0, 0x1f8bb,
+ 0x1f8c0, 0x1f8c1,
+ 0x1f8d0, 0x1f8d8,
+ 0x1f900, 0x1fa57,
+ 0x1fa60, 0x1fa6d,
+ 0x1fa70, 0x1fa7c,
+ 0x1fa80, 0x1fa8a,
+ 0x1fa8e, 0x1fac6,
+ 0x1fac8, 0x1fac8,
+ 0x1facd, 0x1fadc,
+ 0x1fadf, 0x1faea,
+ 0x1faef, 0x1faf8,
+ 0x1fb00, 0x1fb92,
+ 0x1fb94, 0x1fbfa,
+ 0x1fffe, 0x2a6df,
+ 0x2a700, 0x2b81d,
+ 0x2b820, 0x2cead,
+ 0x2ceb0, 0x2ebe0,
+ 0x2ebf0, 0x2ee5d,
+ 0x2f800, 0x2fa1d,
+ 0x2fffe, 0x3134a,
+ 0x31350, 0x33479,
+ 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_17_0 */
+
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+/* 'Grapheme_Cluster_Break_Prepend': Grapheme_Cluster_Break=Prepend */
+static const OnigCodePoint CR_Grapheme_Cluster_Break_Prepend[] = {
+ 15,
+ 0x0600, 0x0605,
+ 0x06dd, 0x06dd,
+ 0x070f, 0x070f,
+ 0x0890, 0x0891,
+ 0x08e2, 0x08e2,
+ 0x0d4e, 0x0d4e,
+ 0x110bd, 0x110bd,
+ 0x110cd, 0x110cd,
+ 0x111c2, 0x111c3,
+ 0x113d1, 0x113d1,
+ 0x1193f, 0x1193f,
+ 0x11941, 0x11941,
+ 0x11a84, 0x11a89,
+ 0x11d46, 0x11d46,
+ 0x11f02, 0x11f02,
+}; /* 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, 0x1343f,
+ 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[] = {
+ 384,
+ 0x0300, 0x036f,
+ 0x0483, 0x0489,
+ 0x0591, 0x05bd,
+ 0x05bf, 0x05bf,
+ 0x05c1, 0x05c2,
+ 0x05c4, 0x05c5,
+ 0x05c7, 0x05c7,
+ 0x0610, 0x061a,
+ 0x064b, 0x065f,
+ 0x0670, 0x0670,
+ 0x06d6, 0x06dc,
+ 0x06df, 0x06e4,
+ 0x06e7, 0x06e8,
+ 0x06ea, 0x06ed,
+ 0x0711, 0x0711,
+ 0x0730, 0x074a,
+ 0x07a6, 0x07b0,
+ 0x07eb, 0x07f3,
+ 0x07fd, 0x07fd,
+ 0x0816, 0x0819,
+ 0x081b, 0x0823,
+ 0x0825, 0x0827,
+ 0x0829, 0x082d,
+ 0x0859, 0x085b,
+ 0x0897, 0x089f,
+ 0x08ca, 0x08e1,
+ 0x08e3, 0x0902,
+ 0x093a, 0x093a,
+ 0x093c, 0x093c,
+ 0x0941, 0x0948,
+ 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,
+ 0x0c3c, 0x0c3c,
+ 0x0c3e, 0x0c40,
+ 0x0c46, 0x0c48,
+ 0x0c4a, 0x0c4d,
+ 0x0c55, 0x0c56,
+ 0x0c62, 0x0c63,
+ 0x0c81, 0x0c81,
+ 0x0cbc, 0x0cbc,
+ 0x0cbf, 0x0cc0,
+ 0x0cc2, 0x0cc2,
+ 0x0cc6, 0x0cc8,
+ 0x0cca, 0x0ccd,
+ 0x0cd5, 0x0cd6,
+ 0x0ce2, 0x0ce3,
+ 0x0d00, 0x0d01,
+ 0x0d3b, 0x0d3c,
+ 0x0d3e, 0x0d3e,
+ 0x0d41, 0x0d44,
+ 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, 0x0ece,
+ 0x0f18, 0x0f19,
+ 0x0f35, 0x0f35,
+ 0x0f37, 0x0f37,
+ 0x0f39, 0x0f39,
+ 0x0f71, 0x0f7e,
+ 0x0f80, 0x0f84,
+ 0x0f86, 0x0f87,
+ 0x0f8d, 0x0f97,
+ 0x0f99, 0x0fbc,
+ 0x0fc6, 0x0fc6,
+ 0x102d, 0x1030,
+ 0x1032, 0x1037,
+ 0x1039, 0x103a,
+ 0x103d, 0x103e,
+ 0x1058, 0x1059,
+ 0x105e, 0x1060,
+ 0x1071, 0x1074,
+ 0x1082, 0x1082,
+ 0x1085, 0x1086,
+ 0x108d, 0x108d,
+ 0x109d, 0x109d,
+ 0x135d, 0x135f,
+ 0x1712, 0x1715,
+ 0x1732, 0x1734,
+ 0x1752, 0x1753,
+ 0x1772, 0x1773,
+ 0x17b4, 0x17b5,
+ 0x17b7, 0x17bd,
+ 0x17c6, 0x17c6,
+ 0x17c9, 0x17d3,
+ 0x17dd, 0x17dd,
+ 0x180b, 0x180d,
+ 0x180f, 0x180f,
+ 0x1885, 0x1886,
+ 0x18a9, 0x18a9,
+ 0x1920, 0x1922,
+ 0x1927, 0x1928,
+ 0x1932, 0x1932,
+ 0x1939, 0x193b,
+ 0x1a17, 0x1a18,
+ 0x1a1b, 0x1a1b,
+ 0x1a56, 0x1a56,
+ 0x1a58, 0x1a5e,
+ 0x1a60, 0x1a60,
+ 0x1a62, 0x1a62,
+ 0x1a65, 0x1a6c,
+ 0x1a73, 0x1a7c,
+ 0x1a7f, 0x1a7f,
+ 0x1ab0, 0x1add,
+ 0x1ae0, 0x1aeb,
+ 0x1b00, 0x1b03,
+ 0x1b34, 0x1b3d,
+ 0x1b42, 0x1b44,
+ 0x1b6b, 0x1b73,
+ 0x1b80, 0x1b81,
+ 0x1ba2, 0x1ba5,
+ 0x1ba8, 0x1bad,
+ 0x1be6, 0x1be6,
+ 0x1be8, 0x1be9,
+ 0x1bed, 0x1bed,
+ 0x1bef, 0x1bf3,
+ 0x1c2c, 0x1c33,
+ 0x1c36, 0x1c37,
+ 0x1cd0, 0x1cd2,
+ 0x1cd4, 0x1ce0,
+ 0x1ce2, 0x1ce8,
+ 0x1ced, 0x1ced,
+ 0x1cf4, 0x1cf4,
+ 0x1cf8, 0x1cf9,
+ 0x1dc0, 0x1dff,
+ 0x200c, 0x200c,
+ 0x20d0, 0x20f0,
+ 0x2cef, 0x2cf1,
+ 0x2d7f, 0x2d7f,
+ 0x2de0, 0x2dff,
+ 0x302a, 0x302f,
+ 0x3099, 0x309a,
+ 0xa66f, 0xa672,
+ 0xa674, 0xa67d,
+ 0xa69e, 0xa69f,
+ 0xa6f0, 0xa6f1,
+ 0xa802, 0xa802,
+ 0xa806, 0xa806,
+ 0xa80b, 0xa80b,
+ 0xa825, 0xa826,
+ 0xa82c, 0xa82c,
+ 0xa8c4, 0xa8c5,
+ 0xa8e0, 0xa8f1,
+ 0xa8ff, 0xa8ff,
+ 0xa926, 0xa92d,
+ 0xa947, 0xa951,
+ 0xa953, 0xa953,
+ 0xa980, 0xa982,
+ 0xa9b3, 0xa9b3,
+ 0xa9b6, 0xa9b9,
+ 0xa9bc, 0xa9bd,
+ 0xa9c0, 0xa9c0,
+ 0xa9e5, 0xa9e5,
+ 0xaa29, 0xaa2e,
+ 0xaa31, 0xaa32,
+ 0xaa35, 0xaa36,
+ 0xaa43, 0xaa43,
+ 0xaa4c, 0xaa4c,
+ 0xaa7c, 0xaa7c,
+ 0xaab0, 0xaab0,
+ 0xaab2, 0xaab4,
+ 0xaab7, 0xaab8,
+ 0xaabe, 0xaabf,
+ 0xaac1, 0xaac1,
+ 0xaaec, 0xaaed,
+ 0xaaf6, 0xaaf6,
+ 0xabe5, 0xabe5,
+ 0xabe8, 0xabe8,
+ 0xabed, 0xabed,
+ 0xfb1e, 0xfb1e,
+ 0xfe00, 0xfe0f,
+ 0xfe20, 0xfe2f,
+ 0xff9e, 0xff9f,
+ 0x101fd, 0x101fd,
+ 0x102e0, 0x102e0,
+ 0x10376, 0x1037a,
+ 0x10a01, 0x10a03,
+ 0x10a05, 0x10a06,
+ 0x10a0c, 0x10a0f,
+ 0x10a38, 0x10a3a,
+ 0x10a3f, 0x10a3f,
+ 0x10ae5, 0x10ae6,
+ 0x10d24, 0x10d27,
+ 0x10d69, 0x10d6d,
+ 0x10eab, 0x10eac,
+ 0x10efa, 0x10eff,
+ 0x10f46, 0x10f50,
+ 0x10f82, 0x10f85,
+ 0x11001, 0x11001,
+ 0x11038, 0x11046,
+ 0x11070, 0x11070,
+ 0x11073, 0x11074,
+ 0x1107f, 0x11081,
+ 0x110b3, 0x110b6,
+ 0x110b9, 0x110ba,
+ 0x110c2, 0x110c2,
+ 0x11100, 0x11102,
+ 0x11127, 0x1112b,
+ 0x1112d, 0x11134,
+ 0x11173, 0x11173,
+ 0x11180, 0x11181,
+ 0x111b6, 0x111be,
+ 0x111c0, 0x111c0,
+ 0x111c9, 0x111cc,
+ 0x111cf, 0x111cf,
+ 0x1122f, 0x11231,
+ 0x11234, 0x11237,
+ 0x1123e, 0x1123e,
+ 0x11241, 0x11241,
+ 0x112df, 0x112df,
+ 0x112e3, 0x112ea,
+ 0x11300, 0x11301,
+ 0x1133b, 0x1133c,
+ 0x1133e, 0x1133e,
+ 0x11340, 0x11340,
+ 0x1134d, 0x1134d,
+ 0x11357, 0x11357,
+ 0x11366, 0x1136c,
+ 0x11370, 0x11374,
+ 0x113b8, 0x113b8,
+ 0x113bb, 0x113c0,
+ 0x113c2, 0x113c2,
+ 0x113c5, 0x113c5,
+ 0x113c7, 0x113c9,
+ 0x113ce, 0x113d0,
+ 0x113d2, 0x113d2,
+ 0x113e1, 0x113e2,
+ 0x11438, 0x1143f,
+ 0x11442, 0x11444,
+ 0x11446, 0x11446,
+ 0x1145e, 0x1145e,
+ 0x114b0, 0x114b0,
+ 0x114b3, 0x114b8,
+ 0x114ba, 0x114ba,
+ 0x114bd, 0x114bd,
+ 0x114bf, 0x114c0,
+ 0x114c2, 0x114c3,
+ 0x115af, 0x115af,
+ 0x115b2, 0x115b5,
+ 0x115bc, 0x115bd,
+ 0x115bf, 0x115c0,
+ 0x115dc, 0x115dd,
+ 0x11633, 0x1163a,
+ 0x1163d, 0x1163d,
+ 0x1163f, 0x11640,
+ 0x116ab, 0x116ab,
+ 0x116ad, 0x116ad,
+ 0x116b0, 0x116b7,
+ 0x1171d, 0x1171d,
+ 0x1171f, 0x1171f,
+ 0x11722, 0x11725,
+ 0x11727, 0x1172b,
+ 0x1182f, 0x11837,
+ 0x11839, 0x1183a,
+ 0x11930, 0x11930,
+ 0x1193b, 0x1193e,
+ 0x11943, 0x11943,
+ 0x119d4, 0x119d7,
+ 0x119da, 0x119db,
+ 0x119e0, 0x119e0,
+ 0x11a01, 0x11a0a,
+ 0x11a33, 0x11a38,
+ 0x11a3b, 0x11a3e,
+ 0x11a47, 0x11a47,
+ 0x11a51, 0x11a56,
+ 0x11a59, 0x11a5b,
+ 0x11a8a, 0x11a96,
+ 0x11a98, 0x11a99,
+ 0x11b60, 0x11b60,
+ 0x11b62, 0x11b64,
+ 0x11b66, 0x11b66,
+ 0x11c30, 0x11c36,
+ 0x11c38, 0x11c3d,
+ 0x11c3f, 0x11c3f,
+ 0x11c92, 0x11ca7,
+ 0x11caa, 0x11cb0,
+ 0x11cb2, 0x11cb3,
+ 0x11cb5, 0x11cb6,
+ 0x11d31, 0x11d36,
+ 0x11d3a, 0x11d3a,
+ 0x11d3c, 0x11d3d,
+ 0x11d3f, 0x11d45,
+ 0x11d47, 0x11d47,
+ 0x11d90, 0x11d91,
+ 0x11d95, 0x11d95,
+ 0x11d97, 0x11d97,
+ 0x11ef3, 0x11ef4,
+ 0x11f00, 0x11f01,
+ 0x11f36, 0x11f3a,
+ 0x11f40, 0x11f42,
+ 0x11f5a, 0x11f5a,
+ 0x13440, 0x13440,
+ 0x13447, 0x13455,
+ 0x1611e, 0x16129,
+ 0x1612d, 0x1612f,
+ 0x16af0, 0x16af4,
+ 0x16b30, 0x16b36,
+ 0x16f4f, 0x16f4f,
+ 0x16f8f, 0x16f92,
+ 0x16fe4, 0x16fe4,
+ 0x16ff0, 0x16ff1,
+ 0x1bc9d, 0x1bc9e,
+ 0x1cf00, 0x1cf2d,
+ 0x1cf30, 0x1cf46,
+ 0x1d165, 0x1d169,
+ 0x1d16d, 0x1d172,
+ 0x1d17b, 0x1d182,
+ 0x1d185, 0x1d18b,
+ 0x1d1aa, 0x1d1ad,
+ 0x1d242, 0x1d244,
+ 0x1da00, 0x1da36,
+ 0x1da3b, 0x1da6c,
+ 0x1da75, 0x1da75,
+ 0x1da84, 0x1da84,
+ 0x1da9b, 0x1da9f,
+ 0x1daa1, 0x1daaf,
+ 0x1e000, 0x1e006,
+ 0x1e008, 0x1e018,
+ 0x1e01b, 0x1e021,
+ 0x1e023, 0x1e024,
+ 0x1e026, 0x1e02a,
+ 0x1e08f, 0x1e08f,
+ 0x1e130, 0x1e136,
+ 0x1e2ae, 0x1e2ae,
+ 0x1e2ec, 0x1e2ef,
+ 0x1e4ec, 0x1e4ef,
+ 0x1e5ee, 0x1e5ef,
+ 0x1e6e3, 0x1e6e3,
+ 0x1e6e6, 0x1e6e6,
+ 0x1e6ee, 0x1e6ef,
+ 0x1e6f5, 0x1e6f5,
+ 0x1e8d0, 0x1e8d6,
+ 0x1e944, 0x1e94a,
+ 0x1f3fb, 0x1f3ff,
+ 0xe0020, 0xe007f,
+ 0xe0100, 0xe01ef,
+}; /* CR_Grapheme_Cluster_Break_Extend */
+
+/* 'Grapheme_Cluster_Break_Regional_Indicator': Grapheme_Cluster_Break=Regional_Indicator */
+#define CR_Grapheme_Cluster_Break_Regional_Indicator CR_Regional_Indicator
+
+/* 'Grapheme_Cluster_Break_SpacingMark': Grapheme_Cluster_Break=SpacingMark */
+static const OnigCodePoint CR_Grapheme_Cluster_Break_SpacingMark[] = {
+ 158,
+ 0x0903, 0x0903,
+ 0x093b, 0x093b,
+ 0x093e, 0x0940,
+ 0x0949, 0x094c,
+ 0x094e, 0x094f,
+ 0x0982, 0x0983,
+ 0x09bf, 0x09c0,
+ 0x09c7, 0x09c8,
+ 0x09cb, 0x09cc,
+ 0x0a03, 0x0a03,
+ 0x0a3e, 0x0a40,
+ 0x0a83, 0x0a83,
+ 0x0abe, 0x0ac0,
+ 0x0ac9, 0x0ac9,
+ 0x0acb, 0x0acc,
+ 0x0b02, 0x0b03,
+ 0x0b40, 0x0b40,
+ 0x0b47, 0x0b48,
+ 0x0b4b, 0x0b4c,
+ 0x0bbf, 0x0bbf,
+ 0x0bc1, 0x0bc2,
+ 0x0bc6, 0x0bc8,
+ 0x0bca, 0x0bcc,
+ 0x0c01, 0x0c03,
+ 0x0c41, 0x0c44,
+ 0x0c82, 0x0c83,
+ 0x0cbe, 0x0cbe,
+ 0x0cc1, 0x0cc1,
+ 0x0cc3, 0x0cc4,
+ 0x0cf3, 0x0cf3,
+ 0x0d02, 0x0d03,
+ 0x0d3f, 0x0d40,
+ 0x0d46, 0x0d48,
+ 0x0d4a, 0x0d4c,
+ 0x0d82, 0x0d83,
+ 0x0dd0, 0x0dd1,
+ 0x0dd8, 0x0dde,
+ 0x0df2, 0x0df3,
+ 0x0e33, 0x0e33,
+ 0x0eb3, 0x0eb3,
+ 0x0f3e, 0x0f3f,
+ 0x0f7f, 0x0f7f,
+ 0x1031, 0x1031,
+ 0x103b, 0x103c,
+ 0x1056, 0x1057,
+ 0x1084, 0x1084,
+ 0x17b6, 0x17b6,
+ 0x17be, 0x17c5,
+ 0x17c7, 0x17c8,
+ 0x1923, 0x1926,
+ 0x1929, 0x192b,
+ 0x1930, 0x1931,
+ 0x1933, 0x1938,
+ 0x1a19, 0x1a1a,
+ 0x1a55, 0x1a55,
+ 0x1a57, 0x1a57,
+ 0x1a6d, 0x1a72,
+ 0x1b04, 0x1b04,
+ 0x1b3e, 0x1b41,
+ 0x1b82, 0x1b82,
+ 0x1ba1, 0x1ba1,
+ 0x1ba6, 0x1ba7,
+ 0x1be7, 0x1be7,
+ 0x1bea, 0x1bec,
+ 0x1bee, 0x1bee,
+ 0x1c24, 0x1c2b,
+ 0x1c34, 0x1c35,
+ 0x1ce1, 0x1ce1,
+ 0x1cf7, 0x1cf7,
+ 0xa823, 0xa824,
+ 0xa827, 0xa827,
+ 0xa880, 0xa881,
+ 0xa8b4, 0xa8c3,
+ 0xa952, 0xa952,
+ 0xa983, 0xa983,
+ 0xa9b4, 0xa9b5,
+ 0xa9ba, 0xa9bb,
+ 0xa9be, 0xa9bf,
+ 0xaa2f, 0xaa30,
+ 0xaa33, 0xaa34,
+ 0xaa4d, 0xaa4d,
+ 0xaaeb, 0xaaeb,
+ 0xaaee, 0xaaef,
+ 0xaaf5, 0xaaf5,
+ 0xabe3, 0xabe4,
+ 0xabe6, 0xabe7,
+ 0xabe9, 0xabea,
+ 0xabec, 0xabec,
+ 0x11000, 0x11000,
+ 0x11002, 0x11002,
+ 0x11082, 0x11082,
+ 0x110b0, 0x110b2,
+ 0x110b7, 0x110b8,
+ 0x1112c, 0x1112c,
+ 0x11145, 0x11146,
+ 0x11182, 0x11182,
+ 0x111b3, 0x111b5,
+ 0x111bf, 0x111bf,
+ 0x111ce, 0x111ce,
+ 0x1122c, 0x1122e,
+ 0x11232, 0x11233,
+ 0x112e0, 0x112e2,
+ 0x11302, 0x11303,
+ 0x1133f, 0x1133f,
+ 0x11341, 0x11344,
+ 0x11347, 0x11348,
+ 0x1134b, 0x1134c,
+ 0x11362, 0x11363,
+ 0x113b9, 0x113ba,
+ 0x113ca, 0x113ca,
+ 0x113cc, 0x113cd,
+ 0x11435, 0x11437,
+ 0x11440, 0x11441,
+ 0x11445, 0x11445,
+ 0x114b1, 0x114b2,
+ 0x114b9, 0x114b9,
+ 0x114bb, 0x114bc,
+ 0x114be, 0x114be,
+ 0x114c1, 0x114c1,
+ 0x115b0, 0x115b1,
+ 0x115b8, 0x115bb,
+ 0x115be, 0x115be,
+ 0x11630, 0x11632,
+ 0x1163b, 0x1163c,
+ 0x1163e, 0x1163e,
+ 0x116ac, 0x116ac,
+ 0x116ae, 0x116af,
+ 0x1171e, 0x1171e,
+ 0x11726, 0x11726,
+ 0x1182c, 0x1182e,
+ 0x11838, 0x11838,
+ 0x11931, 0x11935,
+ 0x11937, 0x11938,
+ 0x11940, 0x11940,
+ 0x11942, 0x11942,
+ 0x119d1, 0x119d3,
+ 0x119dc, 0x119df,
+ 0x119e4, 0x119e4,
+ 0x11a39, 0x11a39,
+ 0x11a57, 0x11a58,
+ 0x11a97, 0x11a97,
+ 0x11b61, 0x11b61,
+ 0x11b65, 0x11b65,
+ 0x11b67, 0x11b67,
+ 0x11c2f, 0x11c2f,
+ 0x11c3e, 0x11c3e,
+ 0x11ca9, 0x11ca9,
+ 0x11cb1, 0x11cb1,
+ 0x11cb4, 0x11cb4,
+ 0x11d8a, 0x11d8e,
+ 0x11d93, 0x11d94,
+ 0x11d96, 0x11d96,
+ 0x11ef5, 0x11ef6,
+ 0x11f03, 0x11f03,
+ 0x11f34, 0x11f35,
+ 0x11f3e, 0x11f3f,
+ 0x1612a, 0x1612c,
+ 0x16f51, 0x16f87,
+}; /* CR_Grapheme_Cluster_Break_SpacingMark */
+
+/* 'Grapheme_Cluster_Break_L': Grapheme_Cluster_Break=L */
+static const OnigCodePoint CR_Grapheme_Cluster_Break_L[] = {
+ 2,
+ 0x1100, 0x115f,
+ 0xa960, 0xa97c,
+}; /* CR_Grapheme_Cluster_Break_L */
+
+/* 'Grapheme_Cluster_Break_V': Grapheme_Cluster_Break=V */
+static const OnigCodePoint CR_Grapheme_Cluster_Break_V[] = {
+ 4,
+ 0x1160, 0x11a7,
+ 0xd7b0, 0xd7c6,
+ 0x16d63, 0x16d63,
+ 0x16d67, 0x16d6a,
+}; /* CR_Grapheme_Cluster_Break_V */
+
+/* 'Grapheme_Cluster_Break_T': Grapheme_Cluster_Break=T */
+static const OnigCodePoint CR_Grapheme_Cluster_Break_T[] = {
+ 2,
+ 0x11a8, 0x11ff,
+ 0xd7cb, 0xd7fb,
+}; /* CR_Grapheme_Cluster_Break_T */
+
+/* 'Grapheme_Cluster_Break_LV': Grapheme_Cluster_Break=LV */
+static const OnigCodePoint CR_Grapheme_Cluster_Break_LV[] = {
+ 399,
+ 0xac00, 0xac00,
+ 0xac1c, 0xac1c,
+ 0xac38, 0xac38,
+ 0xac54, 0xac54,
+ 0xac70, 0xac70,
+ 0xac8c, 0xac8c,
+ 0xaca8, 0xaca8,
+ 0xacc4, 0xacc4,
+ 0xace0, 0xace0,
+ 0xacfc, 0xacfc,
+ 0xad18, 0xad18,
+ 0xad34, 0xad34,
+ 0xad50, 0xad50,
+ 0xad6c, 0xad6c,
+ 0xad88, 0xad88,
+ 0xada4, 0xada4,
+ 0xadc0, 0xadc0,
+ 0xaddc, 0xaddc,
+ 0xadf8, 0xadf8,
+ 0xae14, 0xae14,
+ 0xae30, 0xae30,
+ 0xae4c, 0xae4c,
+ 0xae68, 0xae68,
+ 0xae84, 0xae84,
+ 0xaea0, 0xaea0,
+ 0xaebc, 0xaebc,
+ 0xaed8, 0xaed8,
+ 0xaef4, 0xaef4,
+ 0xaf10, 0xaf10,
+ 0xaf2c, 0xaf2c,
+ 0xaf48, 0xaf48,
+ 0xaf64, 0xaf64,
+ 0xaf80, 0xaf80,
+ 0xaf9c, 0xaf9c,
+ 0xafb8, 0xafb8,
+ 0xafd4, 0xafd4,
+ 0xaff0, 0xaff0,
+ 0xb00c, 0xb00c,
+ 0xb028, 0xb028,
+ 0xb044, 0xb044,
+ 0xb060, 0xb060,
+ 0xb07c, 0xb07c,
+ 0xb098, 0xb098,
+ 0xb0b4, 0xb0b4,
+ 0xb0d0, 0xb0d0,
+ 0xb0ec, 0xb0ec,
+ 0xb108, 0xb108,
+ 0xb124, 0xb124,
+ 0xb140, 0xb140,
+ 0xb15c, 0xb15c,
+ 0xb178, 0xb178,
+ 0xb194, 0xb194,
+ 0xb1b0, 0xb1b0,
+ 0xb1cc, 0xb1cc,
+ 0xb1e8, 0xb1e8,
+ 0xb204, 0xb204,
+ 0xb220, 0xb220,
+ 0xb23c, 0xb23c,
+ 0xb258, 0xb258,
+ 0xb274, 0xb274,
+ 0xb290, 0xb290,
+ 0xb2ac, 0xb2ac,
+ 0xb2c8, 0xb2c8,
+ 0xb2e4, 0xb2e4,
+ 0xb300, 0xb300,
+ 0xb31c, 0xb31c,
+ 0xb338, 0xb338,
+ 0xb354, 0xb354,
+ 0xb370, 0xb370,
+ 0xb38c, 0xb38c,
+ 0xb3a8, 0xb3a8,
+ 0xb3c4, 0xb3c4,
+ 0xb3e0, 0xb3e0,
+ 0xb3fc, 0xb3fc,
+ 0xb418, 0xb418,
+ 0xb434, 0xb434,
+ 0xb450, 0xb450,
+ 0xb46c, 0xb46c,
+ 0xb488, 0xb488,
+ 0xb4a4, 0xb4a4,
+ 0xb4c0, 0xb4c0,
+ 0xb4dc, 0xb4dc,
+ 0xb4f8, 0xb4f8,
+ 0xb514, 0xb514,
+ 0xb530, 0xb530,
+ 0xb54c, 0xb54c,
+ 0xb568, 0xb568,
+ 0xb584, 0xb584,
+ 0xb5a0, 0xb5a0,
+ 0xb5bc, 0xb5bc,
+ 0xb5d8, 0xb5d8,
+ 0xb5f4, 0xb5f4,
+ 0xb610, 0xb610,
+ 0xb62c, 0xb62c,
+ 0xb648, 0xb648,
+ 0xb664, 0xb664,
+ 0xb680, 0xb680,
+ 0xb69c, 0xb69c,
+ 0xb6b8, 0xb6b8,
+ 0xb6d4, 0xb6d4,
+ 0xb6f0, 0xb6f0,
+ 0xb70c, 0xb70c,
+ 0xb728, 0xb728,
+ 0xb744, 0xb744,
+ 0xb760, 0xb760,
+ 0xb77c, 0xb77c,
+ 0xb798, 0xb798,
+ 0xb7b4, 0xb7b4,
+ 0xb7d0, 0xb7d0,
+ 0xb7ec, 0xb7ec,
+ 0xb808, 0xb808,
+ 0xb824, 0xb824,
+ 0xb840, 0xb840,
+ 0xb85c, 0xb85c,
+ 0xb878, 0xb878,
+ 0xb894, 0xb894,
+ 0xb8b0, 0xb8b0,
+ 0xb8cc, 0xb8cc,
+ 0xb8e8, 0xb8e8,
+ 0xb904, 0xb904,
+ 0xb920, 0xb920,
+ 0xb93c, 0xb93c,
+ 0xb958, 0xb958,
+ 0xb974, 0xb974,
+ 0xb990, 0xb990,
+ 0xb9ac, 0xb9ac,
+ 0xb9c8, 0xb9c8,
+ 0xb9e4, 0xb9e4,
+ 0xba00, 0xba00,
+ 0xba1c, 0xba1c,
+ 0xba38, 0xba38,
+ 0xba54, 0xba54,
+ 0xba70, 0xba70,
+ 0xba8c, 0xba8c,
+ 0xbaa8, 0xbaa8,
+ 0xbac4, 0xbac4,
+ 0xbae0, 0xbae0,
+ 0xbafc, 0xbafc,
+ 0xbb18, 0xbb18,
+ 0xbb34, 0xbb34,
+ 0xbb50, 0xbb50,
+ 0xbb6c, 0xbb6c,
+ 0xbb88, 0xbb88,
+ 0xbba4, 0xbba4,
+ 0xbbc0, 0xbbc0,
+ 0xbbdc, 0xbbdc,
+ 0xbbf8, 0xbbf8,
+ 0xbc14, 0xbc14,
+ 0xbc30, 0xbc30,
+ 0xbc4c, 0xbc4c,
+ 0xbc68, 0xbc68,
+ 0xbc84, 0xbc84,
+ 0xbca0, 0xbca0,
+ 0xbcbc, 0xbcbc,
+ 0xbcd8, 0xbcd8,
+ 0xbcf4, 0xbcf4,
+ 0xbd10, 0xbd10,
+ 0xbd2c, 0xbd2c,
+ 0xbd48, 0xbd48,
+ 0xbd64, 0xbd64,
+ 0xbd80, 0xbd80,
+ 0xbd9c, 0xbd9c,
+ 0xbdb8, 0xbdb8,
+ 0xbdd4, 0xbdd4,
+ 0xbdf0, 0xbdf0,
+ 0xbe0c, 0xbe0c,
+ 0xbe28, 0xbe28,
+ 0xbe44, 0xbe44,
+ 0xbe60, 0xbe60,
+ 0xbe7c, 0xbe7c,
+ 0xbe98, 0xbe98,
+ 0xbeb4, 0xbeb4,
+ 0xbed0, 0xbed0,
+ 0xbeec, 0xbeec,
+ 0xbf08, 0xbf08,
+ 0xbf24, 0xbf24,
+ 0xbf40, 0xbf40,
+ 0xbf5c, 0xbf5c,
+ 0xbf78, 0xbf78,
+ 0xbf94, 0xbf94,
+ 0xbfb0, 0xbfb0,
+ 0xbfcc, 0xbfcc,
+ 0xbfe8, 0xbfe8,
+ 0xc004, 0xc004,
+ 0xc020, 0xc020,
+ 0xc03c, 0xc03c,
+ 0xc058, 0xc058,
+ 0xc074, 0xc074,
+ 0xc090, 0xc090,
+ 0xc0ac, 0xc0ac,
+ 0xc0c8, 0xc0c8,
+ 0xc0e4, 0xc0e4,
+ 0xc100, 0xc100,
+ 0xc11c, 0xc11c,
+ 0xc138, 0xc138,
+ 0xc154, 0xc154,
+ 0xc170, 0xc170,
+ 0xc18c, 0xc18c,
+ 0xc1a8, 0xc1a8,
+ 0xc1c4, 0xc1c4,
+ 0xc1e0, 0xc1e0,
+ 0xc1fc, 0xc1fc,
+ 0xc218, 0xc218,
+ 0xc234, 0xc234,
+ 0xc250, 0xc250,
+ 0xc26c, 0xc26c,
+ 0xc288, 0xc288,
+ 0xc2a4, 0xc2a4,
+ 0xc2c0, 0xc2c0,
+ 0xc2dc, 0xc2dc,
+ 0xc2f8, 0xc2f8,
+ 0xc314, 0xc314,
+ 0xc330, 0xc330,
+ 0xc34c, 0xc34c,
+ 0xc368, 0xc368,
+ 0xc384, 0xc384,
+ 0xc3a0, 0xc3a0,
+ 0xc3bc, 0xc3bc,
+ 0xc3d8, 0xc3d8,
+ 0xc3f4, 0xc3f4,
+ 0xc410, 0xc410,
+ 0xc42c, 0xc42c,
+ 0xc448, 0xc448,
+ 0xc464, 0xc464,
+ 0xc480, 0xc480,
+ 0xc49c, 0xc49c,
+ 0xc4b8, 0xc4b8,
+ 0xc4d4, 0xc4d4,
+ 0xc4f0, 0xc4f0,
+ 0xc50c, 0xc50c,
+ 0xc528, 0xc528,
+ 0xc544, 0xc544,
+ 0xc560, 0xc560,
+ 0xc57c, 0xc57c,
+ 0xc598, 0xc598,
+ 0xc5b4, 0xc5b4,
+ 0xc5d0, 0xc5d0,
+ 0xc5ec, 0xc5ec,
+ 0xc608, 0xc608,
+ 0xc624, 0xc624,
+ 0xc640, 0xc640,
+ 0xc65c, 0xc65c,
+ 0xc678, 0xc678,
+ 0xc694, 0xc694,
+ 0xc6b0, 0xc6b0,
+ 0xc6cc, 0xc6cc,
+ 0xc6e8, 0xc6e8,
+ 0xc704, 0xc704,
+ 0xc720, 0xc720,
+ 0xc73c, 0xc73c,
+ 0xc758, 0xc758,
+ 0xc774, 0xc774,
+ 0xc790, 0xc790,
+ 0xc7ac, 0xc7ac,
+ 0xc7c8, 0xc7c8,
+ 0xc7e4, 0xc7e4,
+ 0xc800, 0xc800,
+ 0xc81c, 0xc81c,
+ 0xc838, 0xc838,
+ 0xc854, 0xc854,
+ 0xc870, 0xc870,
+ 0xc88c, 0xc88c,
+ 0xc8a8, 0xc8a8,
+ 0xc8c4, 0xc8c4,
+ 0xc8e0, 0xc8e0,
+ 0xc8fc, 0xc8fc,
+ 0xc918, 0xc918,
+ 0xc934, 0xc934,
+ 0xc950, 0xc950,
+ 0xc96c, 0xc96c,
+ 0xc988, 0xc988,
+ 0xc9a4, 0xc9a4,
+ 0xc9c0, 0xc9c0,
+ 0xc9dc, 0xc9dc,
+ 0xc9f8, 0xc9f8,
+ 0xca14, 0xca14,
+ 0xca30, 0xca30,
+ 0xca4c, 0xca4c,
+ 0xca68, 0xca68,
+ 0xca84, 0xca84,
+ 0xcaa0, 0xcaa0,
+ 0xcabc, 0xcabc,
+ 0xcad8, 0xcad8,
+ 0xcaf4, 0xcaf4,
+ 0xcb10, 0xcb10,
+ 0xcb2c, 0xcb2c,
+ 0xcb48, 0xcb48,
+ 0xcb64, 0xcb64,
+ 0xcb80, 0xcb80,
+ 0xcb9c, 0xcb9c,
+ 0xcbb8, 0xcbb8,
+ 0xcbd4, 0xcbd4,
+ 0xcbf0, 0xcbf0,
+ 0xcc0c, 0xcc0c,
+ 0xcc28, 0xcc28,
+ 0xcc44, 0xcc44,
+ 0xcc60, 0xcc60,
+ 0xcc7c, 0xcc7c,
+ 0xcc98, 0xcc98,
+ 0xccb4, 0xccb4,
+ 0xccd0, 0xccd0,
+ 0xccec, 0xccec,
+ 0xcd08, 0xcd08,
+ 0xcd24, 0xcd24,
+ 0xcd40, 0xcd40,
+ 0xcd5c, 0xcd5c,
+ 0xcd78, 0xcd78,
+ 0xcd94, 0xcd94,
+ 0xcdb0, 0xcdb0,
+ 0xcdcc, 0xcdcc,
+ 0xcde8, 0xcde8,
+ 0xce04, 0xce04,
+ 0xce20, 0xce20,
+ 0xce3c, 0xce3c,
+ 0xce58, 0xce58,
+ 0xce74, 0xce74,
+ 0xce90, 0xce90,
+ 0xceac, 0xceac,
+ 0xcec8, 0xcec8,
+ 0xcee4, 0xcee4,
+ 0xcf00, 0xcf00,
+ 0xcf1c, 0xcf1c,
+ 0xcf38, 0xcf38,
+ 0xcf54, 0xcf54,
+ 0xcf70, 0xcf70,
+ 0xcf8c, 0xcf8c,
+ 0xcfa8, 0xcfa8,
+ 0xcfc4, 0xcfc4,
+ 0xcfe0, 0xcfe0,
+ 0xcffc, 0xcffc,
+ 0xd018, 0xd018,
+ 0xd034, 0xd034,
+ 0xd050, 0xd050,
+ 0xd06c, 0xd06c,
+ 0xd088, 0xd088,
+ 0xd0a4, 0xd0a4,
+ 0xd0c0, 0xd0c0,
+ 0xd0dc, 0xd0dc,
+ 0xd0f8, 0xd0f8,
+ 0xd114, 0xd114,
+ 0xd130, 0xd130,
+ 0xd14c, 0xd14c,
+ 0xd168, 0xd168,
+ 0xd184, 0xd184,
+ 0xd1a0, 0xd1a0,
+ 0xd1bc, 0xd1bc,
+ 0xd1d8, 0xd1d8,
+ 0xd1f4, 0xd1f4,
+ 0xd210, 0xd210,
+ 0xd22c, 0xd22c,
+ 0xd248, 0xd248,
+ 0xd264, 0xd264,
+ 0xd280, 0xd280,
+ 0xd29c, 0xd29c,
+ 0xd2b8, 0xd2b8,
+ 0xd2d4, 0xd2d4,
+ 0xd2f0, 0xd2f0,
+ 0xd30c, 0xd30c,
+ 0xd328, 0xd328,
+ 0xd344, 0xd344,
+ 0xd360, 0xd360,
+ 0xd37c, 0xd37c,
+ 0xd398, 0xd398,
+ 0xd3b4, 0xd3b4,
+ 0xd3d0, 0xd3d0,
+ 0xd3ec, 0xd3ec,
+ 0xd408, 0xd408,
+ 0xd424, 0xd424,
+ 0xd440, 0xd440,
+ 0xd45c, 0xd45c,
+ 0xd478, 0xd478,
+ 0xd494, 0xd494,
+ 0xd4b0, 0xd4b0,
+ 0xd4cc, 0xd4cc,
+ 0xd4e8, 0xd4e8,
+ 0xd504, 0xd504,
+ 0xd520, 0xd520,
+ 0xd53c, 0xd53c,
+ 0xd558, 0xd558,
+ 0xd574, 0xd574,
+ 0xd590, 0xd590,
+ 0xd5ac, 0xd5ac,
+ 0xd5c8, 0xd5c8,
+ 0xd5e4, 0xd5e4,
+ 0xd600, 0xd600,
+ 0xd61c, 0xd61c,
+ 0xd638, 0xd638,
+ 0xd654, 0xd654,
+ 0xd670, 0xd670,
+ 0xd68c, 0xd68c,
+ 0xd6a8, 0xd6a8,
+ 0xd6c4, 0xd6c4,
+ 0xd6e0, 0xd6e0,
+ 0xd6fc, 0xd6fc,
+ 0xd718, 0xd718,
+ 0xd734, 0xd734,
+ 0xd750, 0xd750,
+ 0xd76c, 0xd76c,
+ 0xd788, 0xd788,
+}; /* CR_Grapheme_Cluster_Break_LV */
+
+/* 'Grapheme_Cluster_Break_LVT': Grapheme_Cluster_Break=LVT */
+static const OnigCodePoint CR_Grapheme_Cluster_Break_LVT[] = {
+ 399,
+ 0xac01, 0xac1b,
+ 0xac1d, 0xac37,
+ 0xac39, 0xac53,
+ 0xac55, 0xac6f,
+ 0xac71, 0xac8b,
+ 0xac8d, 0xaca7,
+ 0xaca9, 0xacc3,
+ 0xacc5, 0xacdf,
+ 0xace1, 0xacfb,
+ 0xacfd, 0xad17,
+ 0xad19, 0xad33,
+ 0xad35, 0xad4f,
+ 0xad51, 0xad6b,
+ 0xad6d, 0xad87,
+ 0xad89, 0xada3,
+ 0xada5, 0xadbf,
+ 0xadc1, 0xaddb,
+ 0xaddd, 0xadf7,
+ 0xadf9, 0xae13,
+ 0xae15, 0xae2f,
+ 0xae31, 0xae4b,
+ 0xae4d, 0xae67,
+ 0xae69, 0xae83,
+ 0xae85, 0xae9f,
+ 0xaea1, 0xaebb,
+ 0xaebd, 0xaed7,
+ 0xaed9, 0xaef3,
+ 0xaef5, 0xaf0f,
+ 0xaf11, 0xaf2b,
+ 0xaf2d, 0xaf47,
+ 0xaf49, 0xaf63,
+ 0xaf65, 0xaf7f,
+ 0xaf81, 0xaf9b,
+ 0xaf9d, 0xafb7,
+ 0xafb9, 0xafd3,
+ 0xafd5, 0xafef,
+ 0xaff1, 0xb00b,
+ 0xb00d, 0xb027,
+ 0xb029, 0xb043,
+ 0xb045, 0xb05f,
+ 0xb061, 0xb07b,
+ 0xb07d, 0xb097,
+ 0xb099, 0xb0b3,
+ 0xb0b5, 0xb0cf,
+ 0xb0d1, 0xb0eb,
+ 0xb0ed, 0xb107,
+ 0xb109, 0xb123,
+ 0xb125, 0xb13f,
+ 0xb141, 0xb15b,
+ 0xb15d, 0xb177,
+ 0xb179, 0xb193,
+ 0xb195, 0xb1af,
+ 0xb1b1, 0xb1cb,
+ 0xb1cd, 0xb1e7,
+ 0xb1e9, 0xb203,
+ 0xb205, 0xb21f,
+ 0xb221, 0xb23b,
+ 0xb23d, 0xb257,
+ 0xb259, 0xb273,
+ 0xb275, 0xb28f,
+ 0xb291, 0xb2ab,
+ 0xb2ad, 0xb2c7,
+ 0xb2c9, 0xb2e3,
+ 0xb2e5, 0xb2ff,
+ 0xb301, 0xb31b,
+ 0xb31d, 0xb337,
+ 0xb339, 0xb353,
+ 0xb355, 0xb36f,
+ 0xb371, 0xb38b,
+ 0xb38d, 0xb3a7,
+ 0xb3a9, 0xb3c3,
+ 0xb3c5, 0xb3df,
+ 0xb3e1, 0xb3fb,
+ 0xb3fd, 0xb417,
+ 0xb419, 0xb433,
+ 0xb435, 0xb44f,
+ 0xb451, 0xb46b,
+ 0xb46d, 0xb487,
+ 0xb489, 0xb4a3,
+ 0xb4a5, 0xb4bf,
+ 0xb4c1, 0xb4db,
+ 0xb4dd, 0xb4f7,
+ 0xb4f9, 0xb513,
+ 0xb515, 0xb52f,
+ 0xb531, 0xb54b,
+ 0xb54d, 0xb567,
+ 0xb569, 0xb583,
+ 0xb585, 0xb59f,
+ 0xb5a1, 0xb5bb,
+ 0xb5bd, 0xb5d7,
+ 0xb5d9, 0xb5f3,
+ 0xb5f5, 0xb60f,
+ 0xb611, 0xb62b,
+ 0xb62d, 0xb647,
+ 0xb649, 0xb663,
+ 0xb665, 0xb67f,
+ 0xb681, 0xb69b,
+ 0xb69d, 0xb6b7,
+ 0xb6b9, 0xb6d3,
+ 0xb6d5, 0xb6ef,
+ 0xb6f1, 0xb70b,
+ 0xb70d, 0xb727,
+ 0xb729, 0xb743,
+ 0xb745, 0xb75f,
+ 0xb761, 0xb77b,
+ 0xb77d, 0xb797,
+ 0xb799, 0xb7b3,
+ 0xb7b5, 0xb7cf,
+ 0xb7d1, 0xb7eb,
+ 0xb7ed, 0xb807,
+ 0xb809, 0xb823,
+ 0xb825, 0xb83f,
+ 0xb841, 0xb85b,
+ 0xb85d, 0xb877,
+ 0xb879, 0xb893,
+ 0xb895, 0xb8af,
+ 0xb8b1, 0xb8cb,
+ 0xb8cd, 0xb8e7,
+ 0xb8e9, 0xb903,
+ 0xb905, 0xb91f,
+ 0xb921, 0xb93b,
+ 0xb93d, 0xb957,
+ 0xb959, 0xb973,
+ 0xb975, 0xb98f,
+ 0xb991, 0xb9ab,
+ 0xb9ad, 0xb9c7,
+ 0xb9c9, 0xb9e3,
+ 0xb9e5, 0xb9ff,
+ 0xba01, 0xba1b,
+ 0xba1d, 0xba37,
+ 0xba39, 0xba53,
+ 0xba55, 0xba6f,
+ 0xba71, 0xba8b,
+ 0xba8d, 0xbaa7,
+ 0xbaa9, 0xbac3,
+ 0xbac5, 0xbadf,
+ 0xbae1, 0xbafb,
+ 0xbafd, 0xbb17,
+ 0xbb19, 0xbb33,
+ 0xbb35, 0xbb4f,
+ 0xbb51, 0xbb6b,
+ 0xbb6d, 0xbb87,
+ 0xbb89, 0xbba3,
+ 0xbba5, 0xbbbf,
+ 0xbbc1, 0xbbdb,
+ 0xbbdd, 0xbbf7,
+ 0xbbf9, 0xbc13,
+ 0xbc15, 0xbc2f,
+ 0xbc31, 0xbc4b,
+ 0xbc4d, 0xbc67,
+ 0xbc69, 0xbc83,
+ 0xbc85, 0xbc9f,
+ 0xbca1, 0xbcbb,
+ 0xbcbd, 0xbcd7,
+ 0xbcd9, 0xbcf3,
+ 0xbcf5, 0xbd0f,
+ 0xbd11, 0xbd2b,
+ 0xbd2d, 0xbd47,
+ 0xbd49, 0xbd63,
+ 0xbd65, 0xbd7f,
+ 0xbd81, 0xbd9b,
+ 0xbd9d, 0xbdb7,
+ 0xbdb9, 0xbdd3,
+ 0xbdd5, 0xbdef,
+ 0xbdf1, 0xbe0b,
+ 0xbe0d, 0xbe27,
+ 0xbe29, 0xbe43,
+ 0xbe45, 0xbe5f,
+ 0xbe61, 0xbe7b,
+ 0xbe7d, 0xbe97,
+ 0xbe99, 0xbeb3,
+ 0xbeb5, 0xbecf,
+ 0xbed1, 0xbeeb,
+ 0xbeed, 0xbf07,
+ 0xbf09, 0xbf23,
+ 0xbf25, 0xbf3f,
+ 0xbf41, 0xbf5b,
+ 0xbf5d, 0xbf77,
+ 0xbf79, 0xbf93,
+ 0xbf95, 0xbfaf,
+ 0xbfb1, 0xbfcb,
+ 0xbfcd, 0xbfe7,
+ 0xbfe9, 0xc003,
+ 0xc005, 0xc01f,
+ 0xc021, 0xc03b,
+ 0xc03d, 0xc057,
+ 0xc059, 0xc073,
+ 0xc075, 0xc08f,
+ 0xc091, 0xc0ab,
+ 0xc0ad, 0xc0c7,
+ 0xc0c9, 0xc0e3,
+ 0xc0e5, 0xc0ff,
+ 0xc101, 0xc11b,
+ 0xc11d, 0xc137,
+ 0xc139, 0xc153,
+ 0xc155, 0xc16f,
+ 0xc171, 0xc18b,
+ 0xc18d, 0xc1a7,
+ 0xc1a9, 0xc1c3,
+ 0xc1c5, 0xc1df,
+ 0xc1e1, 0xc1fb,
+ 0xc1fd, 0xc217,
+ 0xc219, 0xc233,
+ 0xc235, 0xc24f,
+ 0xc251, 0xc26b,
+ 0xc26d, 0xc287,
+ 0xc289, 0xc2a3,
+ 0xc2a5, 0xc2bf,
+ 0xc2c1, 0xc2db,
+ 0xc2dd, 0xc2f7,
+ 0xc2f9, 0xc313,
+ 0xc315, 0xc32f,
+ 0xc331, 0xc34b,
+ 0xc34d, 0xc367,
+ 0xc369, 0xc383,
+ 0xc385, 0xc39f,
+ 0xc3a1, 0xc3bb,
+ 0xc3bd, 0xc3d7,
+ 0xc3d9, 0xc3f3,
+ 0xc3f5, 0xc40f,
+ 0xc411, 0xc42b,
+ 0xc42d, 0xc447,
+ 0xc449, 0xc463,
+ 0xc465, 0xc47f,
+ 0xc481, 0xc49b,
+ 0xc49d, 0xc4b7,
+ 0xc4b9, 0xc4d3,
+ 0xc4d5, 0xc4ef,
+ 0xc4f1, 0xc50b,
+ 0xc50d, 0xc527,
+ 0xc529, 0xc543,
+ 0xc545, 0xc55f,
+ 0xc561, 0xc57b,
+ 0xc57d, 0xc597,
+ 0xc599, 0xc5b3,
+ 0xc5b5, 0xc5cf,
+ 0xc5d1, 0xc5eb,
+ 0xc5ed, 0xc607,
+ 0xc609, 0xc623,
+ 0xc625, 0xc63f,
+ 0xc641, 0xc65b,
+ 0xc65d, 0xc677,
+ 0xc679, 0xc693,
+ 0xc695, 0xc6af,
+ 0xc6b1, 0xc6cb,
+ 0xc6cd, 0xc6e7,
+ 0xc6e9, 0xc703,
+ 0xc705, 0xc71f,
+ 0xc721, 0xc73b,
+ 0xc73d, 0xc757,
+ 0xc759, 0xc773,
+ 0xc775, 0xc78f,
+ 0xc791, 0xc7ab,
+ 0xc7ad, 0xc7c7,
+ 0xc7c9, 0xc7e3,
+ 0xc7e5, 0xc7ff,
+ 0xc801, 0xc81b,
+ 0xc81d, 0xc837,
+ 0xc839, 0xc853,
+ 0xc855, 0xc86f,
+ 0xc871, 0xc88b,
+ 0xc88d, 0xc8a7,
+ 0xc8a9, 0xc8c3,
+ 0xc8c5, 0xc8df,
+ 0xc8e1, 0xc8fb,
+ 0xc8fd, 0xc917,
+ 0xc919, 0xc933,
+ 0xc935, 0xc94f,
+ 0xc951, 0xc96b,
+ 0xc96d, 0xc987,
+ 0xc989, 0xc9a3,
+ 0xc9a5, 0xc9bf,
+ 0xc9c1, 0xc9db,
+ 0xc9dd, 0xc9f7,
+ 0xc9f9, 0xca13,
+ 0xca15, 0xca2f,
+ 0xca31, 0xca4b,
+ 0xca4d, 0xca67,
+ 0xca69, 0xca83,
+ 0xca85, 0xca9f,
+ 0xcaa1, 0xcabb,
+ 0xcabd, 0xcad7,
+ 0xcad9, 0xcaf3,
+ 0xcaf5, 0xcb0f,
+ 0xcb11, 0xcb2b,
+ 0xcb2d, 0xcb47,
+ 0xcb49, 0xcb63,
+ 0xcb65, 0xcb7f,
+ 0xcb81, 0xcb9b,
+ 0xcb9d, 0xcbb7,
+ 0xcbb9, 0xcbd3,
+ 0xcbd5, 0xcbef,
+ 0xcbf1, 0xcc0b,
+ 0xcc0d, 0xcc27,
+ 0xcc29, 0xcc43,
+ 0xcc45, 0xcc5f,
+ 0xcc61, 0xcc7b,
+ 0xcc7d, 0xcc97,
+ 0xcc99, 0xccb3,
+ 0xccb5, 0xcccf,
+ 0xccd1, 0xcceb,
+ 0xcced, 0xcd07,
+ 0xcd09, 0xcd23,
+ 0xcd25, 0xcd3f,
+ 0xcd41, 0xcd5b,
+ 0xcd5d, 0xcd77,
+ 0xcd79, 0xcd93,
+ 0xcd95, 0xcdaf,
+ 0xcdb1, 0xcdcb,
+ 0xcdcd, 0xcde7,
+ 0xcde9, 0xce03,
+ 0xce05, 0xce1f,
+ 0xce21, 0xce3b,
+ 0xce3d, 0xce57,
+ 0xce59, 0xce73,
+ 0xce75, 0xce8f,
+ 0xce91, 0xceab,
+ 0xcead, 0xcec7,
+ 0xcec9, 0xcee3,
+ 0xcee5, 0xceff,
+ 0xcf01, 0xcf1b,
+ 0xcf1d, 0xcf37,
+ 0xcf39, 0xcf53,
+ 0xcf55, 0xcf6f,
+ 0xcf71, 0xcf8b,
+ 0xcf8d, 0xcfa7,
+ 0xcfa9, 0xcfc3,
+ 0xcfc5, 0xcfdf,
+ 0xcfe1, 0xcffb,
+ 0xcffd, 0xd017,
+ 0xd019, 0xd033,
+ 0xd035, 0xd04f,
+ 0xd051, 0xd06b,
+ 0xd06d, 0xd087,
+ 0xd089, 0xd0a3,
+ 0xd0a5, 0xd0bf,
+ 0xd0c1, 0xd0db,
+ 0xd0dd, 0xd0f7,
+ 0xd0f9, 0xd113,
+ 0xd115, 0xd12f,
+ 0xd131, 0xd14b,
+ 0xd14d, 0xd167,
+ 0xd169, 0xd183,
+ 0xd185, 0xd19f,
+ 0xd1a1, 0xd1bb,
+ 0xd1bd, 0xd1d7,
+ 0xd1d9, 0xd1f3,
+ 0xd1f5, 0xd20f,
+ 0xd211, 0xd22b,
+ 0xd22d, 0xd247,
+ 0xd249, 0xd263,
+ 0xd265, 0xd27f,
+ 0xd281, 0xd29b,
+ 0xd29d, 0xd2b7,
+ 0xd2b9, 0xd2d3,
+ 0xd2d5, 0xd2ef,
+ 0xd2f1, 0xd30b,
+ 0xd30d, 0xd327,
+ 0xd329, 0xd343,
+ 0xd345, 0xd35f,
+ 0xd361, 0xd37b,
+ 0xd37d, 0xd397,
+ 0xd399, 0xd3b3,
+ 0xd3b5, 0xd3cf,
+ 0xd3d1, 0xd3eb,
+ 0xd3ed, 0xd407,
+ 0xd409, 0xd423,
+ 0xd425, 0xd43f,
+ 0xd441, 0xd45b,
+ 0xd45d, 0xd477,
+ 0xd479, 0xd493,
+ 0xd495, 0xd4af,
+ 0xd4b1, 0xd4cb,
+ 0xd4cd, 0xd4e7,
+ 0xd4e9, 0xd503,
+ 0xd505, 0xd51f,
+ 0xd521, 0xd53b,
+ 0xd53d, 0xd557,
+ 0xd559, 0xd573,
+ 0xd575, 0xd58f,
+ 0xd591, 0xd5ab,
+ 0xd5ad, 0xd5c7,
+ 0xd5c9, 0xd5e3,
+ 0xd5e5, 0xd5ff,
+ 0xd601, 0xd61b,
+ 0xd61d, 0xd637,
+ 0xd639, 0xd653,
+ 0xd655, 0xd66f,
+ 0xd671, 0xd68b,
+ 0xd68d, 0xd6a7,
+ 0xd6a9, 0xd6c3,
+ 0xd6c5, 0xd6df,
+ 0xd6e1, 0xd6fb,
+ 0xd6fd, 0xd717,
+ 0xd719, 0xd733,
+ 0xd735, 0xd74f,
+ 0xd751, 0xd76b,
+ 0xd76d, 0xd787,
+ 0xd789, 0xd7a3,
+}; /* CR_Grapheme_Cluster_Break_LVT */
+
+/* 'Grapheme_Cluster_Break_ZWJ': Grapheme_Cluster_Break=ZWJ */
+static const OnigCodePoint CR_Grapheme_Cluster_Break_ZWJ[] = {
+ 1,
+ 0x200d, 0x200d,
+}; /* CR_Grapheme_Cluster_Break_ZWJ */
+
+/* 'In_Basic_Latin': Block */
+#define CR_In_Basic_Latin CR_ASCII
+
+/* 'In_Latin_1_Supplement': Block */
+static const OnigCodePoint CR_In_Latin_1_Supplement[] = {
+ 1,
+ 0x0080, 0x00ff,
+}; /* CR_In_Latin_1_Supplement */
+
+/* 'In_Latin_Extended_A': Block */
+static const OnigCodePoint CR_In_Latin_Extended_A[] = {
+ 1,
+ 0x0100, 0x017f,
+}; /* CR_In_Latin_Extended_A */
+
+/* 'In_Latin_Extended_B': Block */
+static const OnigCodePoint CR_In_Latin_Extended_B[] = {
+ 1,
+ 0x0180, 0x024f,
+}; /* CR_In_Latin_Extended_B */
+
+/* 'In_IPA_Extensions': Block */
+static const OnigCodePoint CR_In_IPA_Extensions[] = {
+ 1,
+ 0x0250, 0x02af,
+}; /* CR_In_IPA_Extensions */
+
+/* 'In_Spacing_Modifier_Letters': Block */
+static const OnigCodePoint CR_In_Spacing_Modifier_Letters[] = {
+ 1,
+ 0x02b0, 0x02ff,
+}; /* CR_In_Spacing_Modifier_Letters */
+
+/* 'In_Combining_Diacritical_Marks': Block */
+static const OnigCodePoint CR_In_Combining_Diacritical_Marks[] = {
+ 1,
+ 0x0300, 0x036f,
+}; /* CR_In_Combining_Diacritical_Marks */
+
+/* 'In_Greek_and_Coptic': Block */
+static const OnigCodePoint CR_In_Greek_and_Coptic[] = {
+ 1,
+ 0x0370, 0x03ff,
+}; /* CR_In_Greek_and_Coptic */
+
+/* 'In_Cyrillic': Block */
+static const OnigCodePoint CR_In_Cyrillic[] = {
+ 1,
+ 0x0400, 0x04ff,
+}; /* CR_In_Cyrillic */
+
+/* 'In_Cyrillic_Supplement': Block */
+static const OnigCodePoint CR_In_Cyrillic_Supplement[] = {
+ 1,
+ 0x0500, 0x052f,
+}; /* CR_In_Cyrillic_Supplement */
+
+/* 'In_Armenian': Block */
+static const OnigCodePoint CR_In_Armenian[] = {
+ 1,
+ 0x0530, 0x058f,
+}; /* CR_In_Armenian */
+
+/* 'In_Hebrew': Block */
+static const OnigCodePoint CR_In_Hebrew[] = {
+ 1,
+ 0x0590, 0x05ff,
+}; /* CR_In_Hebrew */
+
+/* 'In_Arabic': Block */
+static const OnigCodePoint CR_In_Arabic[] = {
+ 1,
+ 0x0600, 0x06ff,
+}; /* CR_In_Arabic */
+
+/* 'In_Syriac': Block */
+static const OnigCodePoint CR_In_Syriac[] = {
+ 1,
+ 0x0700, 0x074f,
+}; /* CR_In_Syriac */
+
+/* 'In_Arabic_Supplement': Block */
+static const OnigCodePoint CR_In_Arabic_Supplement[] = {
+ 1,
+ 0x0750, 0x077f,
+}; /* CR_In_Arabic_Supplement */
+
+/* 'In_Thaana': Block */
+static const OnigCodePoint CR_In_Thaana[] = {
+ 1,
+ 0x0780, 0x07bf,
+}; /* CR_In_Thaana */
+
+/* 'In_NKo': Block */
+static const OnigCodePoint CR_In_NKo[] = {
+ 1,
+ 0x07c0, 0x07ff,
+}; /* CR_In_NKo */
+
+/* 'In_Samaritan': Block */
+static const OnigCodePoint CR_In_Samaritan[] = {
+ 1,
+ 0x0800, 0x083f,
+}; /* CR_In_Samaritan */
+
+/* 'In_Mandaic': Block */
+static const OnigCodePoint CR_In_Mandaic[] = {
+ 1,
+ 0x0840, 0x085f,
+}; /* CR_In_Mandaic */
+
+/* 'In_Syriac_Supplement': Block */
+static const OnigCodePoint CR_In_Syriac_Supplement[] = {
+ 1,
+ 0x0860, 0x086f,
+}; /* CR_In_Syriac_Supplement */
+
+/* 'In_Arabic_Extended_B': Block */
+static const OnigCodePoint CR_In_Arabic_Extended_B[] = {
+ 1,
+ 0x0870, 0x089f,
+}; /* CR_In_Arabic_Extended_B */
+
+/* 'In_Arabic_Extended_A': Block */
+static const OnigCodePoint CR_In_Arabic_Extended_A[] = {
+ 1,
+ 0x08a0, 0x08ff,
+}; /* CR_In_Arabic_Extended_A */
+
+/* 'In_Devanagari': Block */
+static const OnigCodePoint CR_In_Devanagari[] = {
+ 1,
+ 0x0900, 0x097f,
+}; /* CR_In_Devanagari */
+
+/* 'In_Bengali': Block */
+static const OnigCodePoint CR_In_Bengali[] = {
+ 1,
+ 0x0980, 0x09ff,
+}; /* CR_In_Bengali */
+
+/* 'In_Gurmukhi': Block */
+static const OnigCodePoint CR_In_Gurmukhi[] = {
+ 1,
+ 0x0a00, 0x0a7f,
+}; /* CR_In_Gurmukhi */
+
+/* 'In_Gujarati': Block */
+static const OnigCodePoint CR_In_Gujarati[] = {
+ 1,
+ 0x0a80, 0x0aff,
+}; /* CR_In_Gujarati */
+
+/* 'In_Oriya': Block */
+static const OnigCodePoint CR_In_Oriya[] = {
+ 1,
+ 0x0b00, 0x0b7f,
+}; /* CR_In_Oriya */
+
+/* 'In_Tamil': Block */
+static const OnigCodePoint CR_In_Tamil[] = {
+ 1,
+ 0x0b80, 0x0bff,
+}; /* CR_In_Tamil */
+
+/* 'In_Telugu': Block */
+static const OnigCodePoint CR_In_Telugu[] = {
+ 1,
+ 0x0c00, 0x0c7f,
+}; /* CR_In_Telugu */
+
+/* 'In_Kannada': Block */
+static const OnigCodePoint CR_In_Kannada[] = {
+ 1,
+ 0x0c80, 0x0cff,
+}; /* CR_In_Kannada */
+
+/* 'In_Malayalam': Block */
+static const OnigCodePoint CR_In_Malayalam[] = {
+ 1,
+ 0x0d00, 0x0d7f,
+}; /* CR_In_Malayalam */
+
+/* 'In_Sinhala': Block */
+static const OnigCodePoint CR_In_Sinhala[] = {
+ 1,
+ 0x0d80, 0x0dff,
+}; /* CR_In_Sinhala */
+
+/* 'In_Thai': Block */
+static const OnigCodePoint CR_In_Thai[] = {
+ 1,
+ 0x0e00, 0x0e7f,
+}; /* CR_In_Thai */
+
+/* 'In_Lao': Block */
+static const OnigCodePoint CR_In_Lao[] = {
+ 1,
+ 0x0e80, 0x0eff,
+}; /* CR_In_Lao */
+
+/* 'In_Tibetan': Block */
+static const OnigCodePoint CR_In_Tibetan[] = {
+ 1,
+ 0x0f00, 0x0fff,
+}; /* CR_In_Tibetan */
+
+/* 'In_Myanmar': Block */
+static const OnigCodePoint CR_In_Myanmar[] = {
+ 1,
+ 0x1000, 0x109f,
+}; /* CR_In_Myanmar */
+
+/* 'In_Georgian': Block */
+static const OnigCodePoint CR_In_Georgian[] = {
+ 1,
+ 0x10a0, 0x10ff,
+}; /* CR_In_Georgian */
+
+/* 'In_Hangul_Jamo': Block */
+static const OnigCodePoint CR_In_Hangul_Jamo[] = {
+ 1,
+ 0x1100, 0x11ff,
+}; /* CR_In_Hangul_Jamo */
+
+/* 'In_Ethiopic': Block */
+static const OnigCodePoint CR_In_Ethiopic[] = {
+ 1,
+ 0x1200, 0x137f,
+}; /* CR_In_Ethiopic */
+
+/* 'In_Ethiopic_Supplement': Block */
+static const OnigCodePoint CR_In_Ethiopic_Supplement[] = {
+ 1,
+ 0x1380, 0x139f,
+}; /* CR_In_Ethiopic_Supplement */
+
+/* 'In_Cherokee': Block */
+static const OnigCodePoint CR_In_Cherokee[] = {
+ 1,
+ 0x13a0, 0x13ff,
+}; /* CR_In_Cherokee */
+
+/* 'In_Unified_Canadian_Aboriginal_Syllabics': Block */
+static const OnigCodePoint CR_In_Unified_Canadian_Aboriginal_Syllabics[] = {
+ 1,
+ 0x1400, 0x167f,
+}; /* CR_In_Unified_Canadian_Aboriginal_Syllabics */
+
+/* 'In_Ogham': Block */
+static const OnigCodePoint CR_In_Ogham[] = {
+ 1,
+ 0x1680, 0x169f,
+}; /* CR_In_Ogham */
+
+/* 'In_Runic': Block */
+static const OnigCodePoint CR_In_Runic[] = {
+ 1,
+ 0x16a0, 0x16ff,
+}; /* CR_In_Runic */
+
+/* 'In_Tagalog': Block */
+static const OnigCodePoint CR_In_Tagalog[] = {
+ 1,
+ 0x1700, 0x171f,
+}; /* CR_In_Tagalog */
+
+/* 'In_Hanunoo': Block */
+static const OnigCodePoint CR_In_Hanunoo[] = {
+ 1,
+ 0x1720, 0x173f,
+}; /* CR_In_Hanunoo */
+
+/* 'In_Buhid': Block */
+static const OnigCodePoint CR_In_Buhid[] = {
+ 1,
+ 0x1740, 0x175f,
+}; /* CR_In_Buhid */
+
+/* 'In_Tagbanwa': Block */
+static const OnigCodePoint CR_In_Tagbanwa[] = {
+ 1,
+ 0x1760, 0x177f,
+}; /* CR_In_Tagbanwa */
+
+/* 'In_Khmer': Block */
+static const OnigCodePoint CR_In_Khmer[] = {
+ 1,
+ 0x1780, 0x17ff,
+}; /* CR_In_Khmer */
+
+/* 'In_Mongolian': Block */
+static const OnigCodePoint CR_In_Mongolian[] = {
+ 1,
+ 0x1800, 0x18af,
+}; /* CR_In_Mongolian */
+
+/* 'In_Unified_Canadian_Aboriginal_Syllabics_Extended': Block */
+static const OnigCodePoint CR_In_Unified_Canadian_Aboriginal_Syllabics_Extended[] = {
+ 1,
+ 0x18b0, 0x18ff,
+}; /* CR_In_Unified_Canadian_Aboriginal_Syllabics_Extended */
+
+/* 'In_Limbu': Block */
+static const OnigCodePoint CR_In_Limbu[] = {
+ 1,
+ 0x1900, 0x194f,
+}; /* CR_In_Limbu */
+
+/* 'In_Tai_Le': Block */
+static const OnigCodePoint CR_In_Tai_Le[] = {
+ 1,
+ 0x1950, 0x197f,
+}; /* CR_In_Tai_Le */
+
+/* 'In_New_Tai_Lue': Block */
+static const OnigCodePoint CR_In_New_Tai_Lue[] = {
+ 1,
+ 0x1980, 0x19df,
+}; /* CR_In_New_Tai_Lue */
+
+/* 'In_Khmer_Symbols': Block */
+static const OnigCodePoint CR_In_Khmer_Symbols[] = {
+ 1,
+ 0x19e0, 0x19ff,
+}; /* CR_In_Khmer_Symbols */
+
+/* 'In_Buginese': Block */
+static const OnigCodePoint CR_In_Buginese[] = {
+ 1,
+ 0x1a00, 0x1a1f,
+}; /* CR_In_Buginese */
+
+/* 'In_Tai_Tham': Block */
+static const OnigCodePoint CR_In_Tai_Tham[] = {
+ 1,
+ 0x1a20, 0x1aaf,
+}; /* CR_In_Tai_Tham */
+
+/* 'In_Combining_Diacritical_Marks_Extended': Block */
+static const OnigCodePoint CR_In_Combining_Diacritical_Marks_Extended[] = {
+ 1,
+ 0x1ab0, 0x1aff,
+}; /* CR_In_Combining_Diacritical_Marks_Extended */
+
+/* 'In_Balinese': Block */
+static const OnigCodePoint CR_In_Balinese[] = {
+ 1,
+ 0x1b00, 0x1b7f,
+}; /* CR_In_Balinese */
+
+/* 'In_Sundanese': Block */
+static const OnigCodePoint CR_In_Sundanese[] = {
+ 1,
+ 0x1b80, 0x1bbf,
+}; /* CR_In_Sundanese */
+
+/* 'In_Batak': Block */
+static const OnigCodePoint CR_In_Batak[] = {
+ 1,
+ 0x1bc0, 0x1bff,
+}; /* CR_In_Batak */
+
+/* 'In_Lepcha': Block */
+static const OnigCodePoint CR_In_Lepcha[] = {
+ 1,
+ 0x1c00, 0x1c4f,
+}; /* CR_In_Lepcha */
+
+/* 'In_Ol_Chiki': Block */
+#define CR_In_Ol_Chiki CR_Ol_Chiki
+
+/* 'In_Cyrillic_Extended_C': Block */
+static const OnigCodePoint CR_In_Cyrillic_Extended_C[] = {
+ 1,
+ 0x1c80, 0x1c8f,
+}; /* CR_In_Cyrillic_Extended_C */
+
+/* 'In_Georgian_Extended': Block */
+static const OnigCodePoint CR_In_Georgian_Extended[] = {
+ 1,
+ 0x1c90, 0x1cbf,
+}; /* CR_In_Georgian_Extended */
+
+/* 'In_Sundanese_Supplement': Block */
+static const OnigCodePoint CR_In_Sundanese_Supplement[] = {
+ 1,
+ 0x1cc0, 0x1ccf,
+}; /* CR_In_Sundanese_Supplement */
+
+/* 'In_Vedic_Extensions': Block */
+static const OnigCodePoint CR_In_Vedic_Extensions[] = {
+ 1,
+ 0x1cd0, 0x1cff,
+}; /* CR_In_Vedic_Extensions */
+
+/* 'In_Phonetic_Extensions': Block */
+static const OnigCodePoint CR_In_Phonetic_Extensions[] = {
+ 1,
+ 0x1d00, 0x1d7f,
+}; /* CR_In_Phonetic_Extensions */
+
+/* 'In_Phonetic_Extensions_Supplement': Block */
+static const OnigCodePoint CR_In_Phonetic_Extensions_Supplement[] = {
+ 1,
+ 0x1d80, 0x1dbf,
+}; /* CR_In_Phonetic_Extensions_Supplement */
+
+/* 'In_Combining_Diacritical_Marks_Supplement': Block */
+static const OnigCodePoint CR_In_Combining_Diacritical_Marks_Supplement[] = {
+ 1,
+ 0x1dc0, 0x1dff,
+}; /* CR_In_Combining_Diacritical_Marks_Supplement */
+
+/* 'In_Latin_Extended_Additional': Block */
+static const OnigCodePoint CR_In_Latin_Extended_Additional[] = {
+ 1,
+ 0x1e00, 0x1eff,
+}; /* CR_In_Latin_Extended_Additional */
+
+/* 'In_Greek_Extended': Block */
+static const OnigCodePoint CR_In_Greek_Extended[] = {
+ 1,
+ 0x1f00, 0x1fff,
+}; /* CR_In_Greek_Extended */
+
+/* 'In_General_Punctuation': Block */
+static const OnigCodePoint CR_In_General_Punctuation[] = {
+ 1,
+ 0x2000, 0x206f,
+}; /* CR_In_General_Punctuation */
+
+/* 'In_Superscripts_and_Subscripts': Block */
+static const OnigCodePoint CR_In_Superscripts_and_Subscripts[] = {
+ 1,
+ 0x2070, 0x209f,
+}; /* CR_In_Superscripts_and_Subscripts */
+
+/* 'In_Currency_Symbols': Block */
+static const OnigCodePoint CR_In_Currency_Symbols[] = {
+ 1,
+ 0x20a0, 0x20cf,
+}; /* CR_In_Currency_Symbols */
+
+/* 'In_Combining_Diacritical_Marks_for_Symbols': Block */
+static const OnigCodePoint CR_In_Combining_Diacritical_Marks_for_Symbols[] = {
+ 1,
+ 0x20d0, 0x20ff,
+}; /* CR_In_Combining_Diacritical_Marks_for_Symbols */
+
+/* 'In_Letterlike_Symbols': Block */
+static const OnigCodePoint CR_In_Letterlike_Symbols[] = {
+ 1,
+ 0x2100, 0x214f,
+}; /* CR_In_Letterlike_Symbols */
+
+/* 'In_Number_Forms': Block */
+static const OnigCodePoint CR_In_Number_Forms[] = {
+ 1,
+ 0x2150, 0x218f,
+}; /* CR_In_Number_Forms */
+
+/* 'In_Arrows': Block */
+static const OnigCodePoint CR_In_Arrows[] = {
+ 1,
+ 0x2190, 0x21ff,
+}; /* CR_In_Arrows */
+
+/* 'In_Mathematical_Operators': Block */
+static const OnigCodePoint CR_In_Mathematical_Operators[] = {
+ 1,
+ 0x2200, 0x22ff,
+}; /* CR_In_Mathematical_Operators */
+
+/* 'In_Miscellaneous_Technical': Block */
+static const OnigCodePoint CR_In_Miscellaneous_Technical[] = {
+ 1,
+ 0x2300, 0x23ff,
+}; /* CR_In_Miscellaneous_Technical */
+
+/* 'In_Control_Pictures': Block */
+static const OnigCodePoint CR_In_Control_Pictures[] = {
+ 1,
+ 0x2400, 0x243f,
+}; /* CR_In_Control_Pictures */
+
+/* 'In_Optical_Character_Recognition': Block */
+static const OnigCodePoint CR_In_Optical_Character_Recognition[] = {
+ 1,
+ 0x2440, 0x245f,
+}; /* CR_In_Optical_Character_Recognition */
+
+/* 'In_Enclosed_Alphanumerics': Block */
+static const OnigCodePoint CR_In_Enclosed_Alphanumerics[] = {
+ 1,
+ 0x2460, 0x24ff,
+}; /* CR_In_Enclosed_Alphanumerics */
+
+/* 'In_Box_Drawing': Block */
+static const OnigCodePoint CR_In_Box_Drawing[] = {
+ 1,
+ 0x2500, 0x257f,
+}; /* CR_In_Box_Drawing */
+
+/* 'In_Block_Elements': Block */
+static const OnigCodePoint CR_In_Block_Elements[] = {
+ 1,
+ 0x2580, 0x259f,
+}; /* CR_In_Block_Elements */
+
+/* 'In_Geometric_Shapes': Block */
+static const OnigCodePoint CR_In_Geometric_Shapes[] = {
+ 1,
+ 0x25a0, 0x25ff,
+}; /* CR_In_Geometric_Shapes */
+
+/* 'In_Miscellaneous_Symbols': Block */
+static const OnigCodePoint CR_In_Miscellaneous_Symbols[] = {
+ 1,
+ 0x2600, 0x26ff,
+}; /* CR_In_Miscellaneous_Symbols */
+
+/* 'In_Dingbats': Block */
+static const OnigCodePoint CR_In_Dingbats[] = {
+ 1,
+ 0x2700, 0x27bf,
+}; /* CR_In_Dingbats */
+
+/* 'In_Miscellaneous_Mathematical_Symbols_A': Block */
+static const OnigCodePoint CR_In_Miscellaneous_Mathematical_Symbols_A[] = {
+ 1,
+ 0x27c0, 0x27ef,
+}; /* CR_In_Miscellaneous_Mathematical_Symbols_A */
+
+/* 'In_Supplemental_Arrows_A': Block */
+static const OnigCodePoint CR_In_Supplemental_Arrows_A[] = {
+ 1,
+ 0x27f0, 0x27ff,
+}; /* CR_In_Supplemental_Arrows_A */
+
+/* 'In_Braille_Patterns': Block */
+#define CR_In_Braille_Patterns CR_Braille
+
+/* 'In_Supplemental_Arrows_B': Block */
+static const OnigCodePoint CR_In_Supplemental_Arrows_B[] = {
+ 1,
+ 0x2900, 0x297f,
+}; /* CR_In_Supplemental_Arrows_B */
+
+/* 'In_Miscellaneous_Mathematical_Symbols_B': Block */
+static const OnigCodePoint CR_In_Miscellaneous_Mathematical_Symbols_B[] = {
+ 1,
+ 0x2980, 0x29ff,
+}; /* CR_In_Miscellaneous_Mathematical_Symbols_B */
+
+/* 'In_Supplemental_Mathematical_Operators': Block */
+static const OnigCodePoint CR_In_Supplemental_Mathematical_Operators[] = {
+ 1,
+ 0x2a00, 0x2aff,
+}; /* CR_In_Supplemental_Mathematical_Operators */
+
+/* 'In_Miscellaneous_Symbols_and_Arrows': Block */
+static const OnigCodePoint CR_In_Miscellaneous_Symbols_and_Arrows[] = {
+ 1,
+ 0x2b00, 0x2bff,
+}; /* CR_In_Miscellaneous_Symbols_and_Arrows */
+
+/* 'In_Glagolitic': Block */
+static const OnigCodePoint CR_In_Glagolitic[] = {
+ 1,
+ 0x2c00, 0x2c5f,
+}; /* CR_In_Glagolitic */
+
+/* 'In_Latin_Extended_C': Block */
+static const OnigCodePoint CR_In_Latin_Extended_C[] = {
+ 1,
+ 0x2c60, 0x2c7f,
+}; /* CR_In_Latin_Extended_C */
+
+/* 'In_Coptic': Block */
+static const OnigCodePoint CR_In_Coptic[] = {
+ 1,
+ 0x2c80, 0x2cff,
+}; /* CR_In_Coptic */
+
+/* 'In_Georgian_Supplement': Block */
+static const OnigCodePoint CR_In_Georgian_Supplement[] = {
+ 1,
+ 0x2d00, 0x2d2f,
+}; /* CR_In_Georgian_Supplement */
+
+/* 'In_Tifinagh': Block */
+static const OnigCodePoint CR_In_Tifinagh[] = {
+ 1,
+ 0x2d30, 0x2d7f,
+}; /* CR_In_Tifinagh */
+
+/* 'In_Ethiopic_Extended': Block */
+static const OnigCodePoint CR_In_Ethiopic_Extended[] = {
+ 1,
+ 0x2d80, 0x2ddf,
+}; /* CR_In_Ethiopic_Extended */
+
+/* 'In_Cyrillic_Extended_A': Block */
+static const OnigCodePoint CR_In_Cyrillic_Extended_A[] = {
+ 1,
+ 0x2de0, 0x2dff,
+}; /* CR_In_Cyrillic_Extended_A */
+
+/* 'In_Supplemental_Punctuation': Block */
+static const OnigCodePoint CR_In_Supplemental_Punctuation[] = {
+ 1,
+ 0x2e00, 0x2e7f,
+}; /* CR_In_Supplemental_Punctuation */
+
+/* 'In_CJK_Radicals_Supplement': Block */
+static const OnigCodePoint CR_In_CJK_Radicals_Supplement[] = {
+ 1,
+ 0x2e80, 0x2eff,
+}; /* CR_In_CJK_Radicals_Supplement */
+
+/* 'In_Kangxi_Radicals': Block */
+static const OnigCodePoint CR_In_Kangxi_Radicals[] = {
+ 1,
+ 0x2f00, 0x2fdf,
+}; /* CR_In_Kangxi_Radicals */
+
+/* 'In_Ideographic_Description_Characters': Block */
+static const OnigCodePoint CR_In_Ideographic_Description_Characters[] = {
+ 1,
+ 0x2ff0, 0x2fff,
+}; /* CR_In_Ideographic_Description_Characters */
+
+/* 'In_CJK_Symbols_and_Punctuation': Block */
+static const OnigCodePoint CR_In_CJK_Symbols_and_Punctuation[] = {
+ 1,
+ 0x3000, 0x303f,
+}; /* CR_In_CJK_Symbols_and_Punctuation */
+
+/* 'In_Hiragana': Block */
+static const OnigCodePoint CR_In_Hiragana[] = {
+ 1,
+ 0x3040, 0x309f,
+}; /* CR_In_Hiragana */
+
+/* 'In_Katakana': Block */
+static const OnigCodePoint CR_In_Katakana[] = {
+ 1,
+ 0x30a0, 0x30ff,
+}; /* CR_In_Katakana */
+
+/* 'In_Bopomofo': Block */
+static const OnigCodePoint CR_In_Bopomofo[] = {
+ 1,
+ 0x3100, 0x312f,
+}; /* CR_In_Bopomofo */
+
+/* 'In_Hangul_Compatibility_Jamo': Block */
+static const OnigCodePoint CR_In_Hangul_Compatibility_Jamo[] = {
+ 1,
+ 0x3130, 0x318f,
+}; /* CR_In_Hangul_Compatibility_Jamo */
+
+/* 'In_Kanbun': Block */
+static const OnigCodePoint CR_In_Kanbun[] = {
+ 1,
+ 0x3190, 0x319f,
+}; /* CR_In_Kanbun */
+
+/* 'In_Bopomofo_Extended': Block */
+static const OnigCodePoint CR_In_Bopomofo_Extended[] = {
+ 1,
+ 0x31a0, 0x31bf,
+}; /* CR_In_Bopomofo_Extended */
+
+/* 'In_CJK_Strokes': Block */
+static const OnigCodePoint CR_In_CJK_Strokes[] = {
+ 1,
+ 0x31c0, 0x31ef,
+}; /* CR_In_CJK_Strokes */
+
+/* 'In_Katakana_Phonetic_Extensions': Block */
+static const OnigCodePoint CR_In_Katakana_Phonetic_Extensions[] = {
+ 1,
+ 0x31f0, 0x31ff,
+}; /* CR_In_Katakana_Phonetic_Extensions */
+
+/* 'In_Enclosed_CJK_Letters_and_Months': Block */
+static const OnigCodePoint CR_In_Enclosed_CJK_Letters_and_Months[] = {
+ 1,
+ 0x3200, 0x32ff,
+}; /* CR_In_Enclosed_CJK_Letters_and_Months */
+
+/* 'In_CJK_Compatibility': Block */
+static const OnigCodePoint CR_In_CJK_Compatibility[] = {
+ 1,
+ 0x3300, 0x33ff,
+}; /* CR_In_CJK_Compatibility */
+
+/* 'In_CJK_Unified_Ideographs_Extension_A': Block */
+static const OnigCodePoint CR_In_CJK_Unified_Ideographs_Extension_A[] = {
+ 1,
+ 0x3400, 0x4dbf,
+}; /* CR_In_CJK_Unified_Ideographs_Extension_A */
+
+/* 'In_Yijing_Hexagram_Symbols': Block */
+static const OnigCodePoint CR_In_Yijing_Hexagram_Symbols[] = {
+ 1,
+ 0x4dc0, 0x4dff,
+}; /* CR_In_Yijing_Hexagram_Symbols */
+
+/* 'In_CJK_Unified_Ideographs': Block */
+static const OnigCodePoint CR_In_CJK_Unified_Ideographs[] = {
+ 1,
+ 0x4e00, 0x9fff,
+}; /* CR_In_CJK_Unified_Ideographs */
+
+/* 'In_Yi_Syllables': Block */
+static const OnigCodePoint CR_In_Yi_Syllables[] = {
+ 1,
+ 0xa000, 0xa48f,
+}; /* CR_In_Yi_Syllables */
+
+/* 'In_Yi_Radicals': Block */
+static const OnigCodePoint CR_In_Yi_Radicals[] = {
+ 1,
+ 0xa490, 0xa4cf,
+}; /* CR_In_Yi_Radicals */
+
+/* 'In_Lisu': Block */
+static const OnigCodePoint CR_In_Lisu[] = {
+ 1,
+ 0xa4d0, 0xa4ff,
+}; /* CR_In_Lisu */
+
+/* 'In_Vai': Block */
+static const OnigCodePoint CR_In_Vai[] = {
+ 1,
+ 0xa500, 0xa63f,
+}; /* CR_In_Vai */
+
+/* 'In_Cyrillic_Extended_B': Block */
+static const OnigCodePoint CR_In_Cyrillic_Extended_B[] = {
+ 1,
+ 0xa640, 0xa69f,
+}; /* CR_In_Cyrillic_Extended_B */
+
+/* 'In_Bamum': Block */
+static const OnigCodePoint CR_In_Bamum[] = {
+ 1,
+ 0xa6a0, 0xa6ff,
+}; /* CR_In_Bamum */
+
+/* 'In_Modifier_Tone_Letters': Block */
+static const OnigCodePoint CR_In_Modifier_Tone_Letters[] = {
+ 1,
+ 0xa700, 0xa71f,
+}; /* CR_In_Modifier_Tone_Letters */
+
+/* 'In_Latin_Extended_D': Block */
+static const OnigCodePoint CR_In_Latin_Extended_D[] = {
+ 1,
+ 0xa720, 0xa7ff,
+}; /* CR_In_Latin_Extended_D */
+
+/* 'In_Syloti_Nagri': Block */
+static const OnigCodePoint CR_In_Syloti_Nagri[] = {
+ 1,
+ 0xa800, 0xa82f,
+}; /* CR_In_Syloti_Nagri */
+
+/* 'In_Common_Indic_Number_Forms': Block */
+static const OnigCodePoint CR_In_Common_Indic_Number_Forms[] = {
+ 1,
+ 0xa830, 0xa83f,
+}; /* CR_In_Common_Indic_Number_Forms */
+
+/* 'In_Phags_pa': Block */
+static const OnigCodePoint CR_In_Phags_pa[] = {
+ 1,
+ 0xa840, 0xa87f,
+}; /* CR_In_Phags_pa */
+
+/* 'In_Saurashtra': Block */
+static const OnigCodePoint CR_In_Saurashtra[] = {
+ 1,
+ 0xa880, 0xa8df,
+}; /* CR_In_Saurashtra */
+
+/* 'In_Devanagari_Extended': Block */
+static const OnigCodePoint CR_In_Devanagari_Extended[] = {
+ 1,
+ 0xa8e0, 0xa8ff,
+}; /* CR_In_Devanagari_Extended */
+
+/* 'In_Kayah_Li': Block */
+static const OnigCodePoint CR_In_Kayah_Li[] = {
+ 1,
+ 0xa900, 0xa92f,
+}; /* CR_In_Kayah_Li */
+
+/* 'In_Rejang': Block */
+static const OnigCodePoint CR_In_Rejang[] = {
+ 1,
+ 0xa930, 0xa95f,
+}; /* CR_In_Rejang */
+
+/* 'In_Hangul_Jamo_Extended_A': Block */
+static const OnigCodePoint CR_In_Hangul_Jamo_Extended_A[] = {
+ 1,
+ 0xa960, 0xa97f,
+}; /* CR_In_Hangul_Jamo_Extended_A */
+
+/* 'In_Javanese': Block */
+static const OnigCodePoint CR_In_Javanese[] = {
+ 1,
+ 0xa980, 0xa9df,
+}; /* CR_In_Javanese */
+
+/* 'In_Myanmar_Extended_B': Block */
+static const OnigCodePoint CR_In_Myanmar_Extended_B[] = {
+ 1,
+ 0xa9e0, 0xa9ff,
+}; /* CR_In_Myanmar_Extended_B */
+
+/* 'In_Cham': Block */
+static const OnigCodePoint CR_In_Cham[] = {
+ 1,
+ 0xaa00, 0xaa5f,
+}; /* CR_In_Cham */
+
+/* 'In_Myanmar_Extended_A': Block */
+static const OnigCodePoint CR_In_Myanmar_Extended_A[] = {
+ 1,
+ 0xaa60, 0xaa7f,
+}; /* CR_In_Myanmar_Extended_A */
+
+/* 'In_Tai_Viet': Block */
+static const OnigCodePoint CR_In_Tai_Viet[] = {
+ 1,
+ 0xaa80, 0xaadf,
+}; /* CR_In_Tai_Viet */
+
+/* 'In_Meetei_Mayek_Extensions': Block */
+static const OnigCodePoint CR_In_Meetei_Mayek_Extensions[] = {
+ 1,
+ 0xaae0, 0xaaff,
+}; /* CR_In_Meetei_Mayek_Extensions */
+
+/* 'In_Ethiopic_Extended_A': Block */
+static const OnigCodePoint CR_In_Ethiopic_Extended_A[] = {
+ 1,
+ 0xab00, 0xab2f,
+}; /* CR_In_Ethiopic_Extended_A */
+
+/* 'In_Latin_Extended_E': Block */
+static const OnigCodePoint CR_In_Latin_Extended_E[] = {
+ 1,
+ 0xab30, 0xab6f,
+}; /* CR_In_Latin_Extended_E */
+
+/* 'In_Cherokee_Supplement': Block */
+static const OnigCodePoint CR_In_Cherokee_Supplement[] = {
+ 1,
+ 0xab70, 0xabbf,
+}; /* CR_In_Cherokee_Supplement */
+
+/* 'In_Meetei_Mayek': Block */
+static const OnigCodePoint CR_In_Meetei_Mayek[] = {
+ 1,
+ 0xabc0, 0xabff,
+}; /* CR_In_Meetei_Mayek */
+
+/* 'In_Hangul_Syllables': Block */
+static const OnigCodePoint CR_In_Hangul_Syllables[] = {
+ 1,
+ 0xac00, 0xd7af,
+}; /* CR_In_Hangul_Syllables */
+
+/* 'In_Hangul_Jamo_Extended_B': Block */
+static const OnigCodePoint CR_In_Hangul_Jamo_Extended_B[] = {
+ 1,
+ 0xd7b0, 0xd7ff,
+}; /* CR_In_Hangul_Jamo_Extended_B */
+
+/* 'In_High_Surrogates': Block */
+static const OnigCodePoint CR_In_High_Surrogates[] = {
+ 1,
+ 0xd800, 0xdb7f,
+}; /* CR_In_High_Surrogates */
+
+/* 'In_High_Private_Use_Surrogates': Block */
+static const OnigCodePoint CR_In_High_Private_Use_Surrogates[] = {
+ 1,
+ 0xdb80, 0xdbff,
+}; /* CR_In_High_Private_Use_Surrogates */
+
+/* 'In_Low_Surrogates': Block */
+static const OnigCodePoint CR_In_Low_Surrogates[] = {
+ 1,
+ 0xdc00, 0xdfff,
+}; /* CR_In_Low_Surrogates */
+
+/* 'In_Private_Use_Area': Block */
+static const OnigCodePoint CR_In_Private_Use_Area[] = {
+ 1,
+ 0xe000, 0xf8ff,
+}; /* CR_In_Private_Use_Area */
+
+/* 'In_CJK_Compatibility_Ideographs': Block */
+static const OnigCodePoint CR_In_CJK_Compatibility_Ideographs[] = {
+ 1,
+ 0xf900, 0xfaff,
+}; /* CR_In_CJK_Compatibility_Ideographs */
+
+/* 'In_Alphabetic_Presentation_Forms': Block */
+static const OnigCodePoint CR_In_Alphabetic_Presentation_Forms[] = {
+ 1,
+ 0xfb00, 0xfb4f,
+}; /* CR_In_Alphabetic_Presentation_Forms */
+
+/* 'In_Arabic_Presentation_Forms_A': Block */
+static const OnigCodePoint CR_In_Arabic_Presentation_Forms_A[] = {
+ 1,
+ 0xfb50, 0xfdff,
+}; /* CR_In_Arabic_Presentation_Forms_A */
+
+/* 'In_Variation_Selectors': Block */
+static const OnigCodePoint CR_In_Variation_Selectors[] = {
+ 1,
+ 0xfe00, 0xfe0f,
+}; /* CR_In_Variation_Selectors */
+
+/* 'In_Vertical_Forms': Block */
+static const OnigCodePoint CR_In_Vertical_Forms[] = {
+ 1,
+ 0xfe10, 0xfe1f,
+}; /* CR_In_Vertical_Forms */
+
+/* 'In_Combining_Half_Marks': Block */
+static const OnigCodePoint CR_In_Combining_Half_Marks[] = {
+ 1,
+ 0xfe20, 0xfe2f,
+}; /* CR_In_Combining_Half_Marks */
+
+/* 'In_CJK_Compatibility_Forms': Block */
+static const OnigCodePoint CR_In_CJK_Compatibility_Forms[] = {
+ 1,
+ 0xfe30, 0xfe4f,
+}; /* CR_In_CJK_Compatibility_Forms */
+
+/* 'In_Small_Form_Variants': Block */
+static const OnigCodePoint CR_In_Small_Form_Variants[] = {
+ 1,
+ 0xfe50, 0xfe6f,
+}; /* CR_In_Small_Form_Variants */
+
+/* 'In_Arabic_Presentation_Forms_B': Block */
+static const OnigCodePoint CR_In_Arabic_Presentation_Forms_B[] = {
+ 1,
+ 0xfe70, 0xfeff,
+}; /* CR_In_Arabic_Presentation_Forms_B */
+
+/* 'In_Halfwidth_and_Fullwidth_Forms': Block */
+static const OnigCodePoint CR_In_Halfwidth_and_Fullwidth_Forms[] = {
+ 1,
+ 0xff00, 0xffef,
+}; /* CR_In_Halfwidth_and_Fullwidth_Forms */
+
+/* 'In_Specials': Block */
+static const OnigCodePoint CR_In_Specials[] = {
+ 1,
+ 0xfff0, 0xffff,
+}; /* CR_In_Specials */
+
+/* 'In_Linear_B_Syllabary': Block */
+static const OnigCodePoint CR_In_Linear_B_Syllabary[] = {
+ 1,
+ 0x10000, 0x1007f,
+}; /* CR_In_Linear_B_Syllabary */
+
+/* 'In_Linear_B_Ideograms': Block */
+static const OnigCodePoint CR_In_Linear_B_Ideograms[] = {
+ 1,
+ 0x10080, 0x100ff,
+}; /* CR_In_Linear_B_Ideograms */
+
+/* 'In_Aegean_Numbers': Block */
+static const OnigCodePoint CR_In_Aegean_Numbers[] = {
+ 1,
+ 0x10100, 0x1013f,
+}; /* CR_In_Aegean_Numbers */
+
+/* 'In_Ancient_Greek_Numbers': Block */
+static const OnigCodePoint CR_In_Ancient_Greek_Numbers[] = {
+ 1,
+ 0x10140, 0x1018f,
+}; /* CR_In_Ancient_Greek_Numbers */
+
+/* 'In_Ancient_Symbols': Block */
+static const OnigCodePoint CR_In_Ancient_Symbols[] = {
+ 1,
+ 0x10190, 0x101cf,
+}; /* CR_In_Ancient_Symbols */
+
+/* 'In_Phaistos_Disc': Block */
+static const OnigCodePoint CR_In_Phaistos_Disc[] = {
+ 1,
+ 0x101d0, 0x101ff,
+}; /* CR_In_Phaistos_Disc */
+
+/* 'In_Lycian': Block */
+static const OnigCodePoint CR_In_Lycian[] = {
+ 1,
+ 0x10280, 0x1029f,
+}; /* CR_In_Lycian */
+
+/* 'In_Carian': Block */
+static const OnigCodePoint CR_In_Carian[] = {
+ 1,
+ 0x102a0, 0x102df,
+}; /* CR_In_Carian */
+
+/* 'In_Coptic_Epact_Numbers': Block */
+static const OnigCodePoint CR_In_Coptic_Epact_Numbers[] = {
+ 1,
+ 0x102e0, 0x102ff,
+}; /* CR_In_Coptic_Epact_Numbers */
+
+/* 'In_Old_Italic': Block */
+static const OnigCodePoint CR_In_Old_Italic[] = {
+ 1,
+ 0x10300, 0x1032f,
+}; /* CR_In_Old_Italic */
+
+/* 'In_Gothic': Block */
+static const OnigCodePoint CR_In_Gothic[] = {
+ 1,
+ 0x10330, 0x1034f,
+}; /* CR_In_Gothic */
+
+/* 'In_Old_Permic': Block */
+static const OnigCodePoint CR_In_Old_Permic[] = {
+ 1,
+ 0x10350, 0x1037f,
+}; /* CR_In_Old_Permic */
+
+/* 'In_Ugaritic': Block */
+static const OnigCodePoint CR_In_Ugaritic[] = {
+ 1,
+ 0x10380, 0x1039f,
+}; /* CR_In_Ugaritic */
+
+/* 'In_Old_Persian': Block */
+static const OnigCodePoint CR_In_Old_Persian[] = {
+ 1,
+ 0x103a0, 0x103df,
+}; /* CR_In_Old_Persian */
+
+/* 'In_Deseret': Block */
+#define CR_In_Deseret CR_Deseret
+
+/* 'In_Shavian': Block */
+#define CR_In_Shavian CR_Shavian
+
+/* 'In_Osmanya': Block */
+static const OnigCodePoint CR_In_Osmanya[] = {
+ 1,
+ 0x10480, 0x104af,
+}; /* CR_In_Osmanya */
+
+/* 'In_Osage': Block */
+static const OnigCodePoint CR_In_Osage[] = {
+ 1,
+ 0x104b0, 0x104ff,
+}; /* CR_In_Osage */
+
+/* 'In_Elbasan': Block */
+static const OnigCodePoint CR_In_Elbasan[] = {
+ 1,
+ 0x10500, 0x1052f,
+}; /* CR_In_Elbasan */
+
+/* 'In_Caucasian_Albanian': Block */
+static const OnigCodePoint CR_In_Caucasian_Albanian[] = {
+ 1,
+ 0x10530, 0x1056f,
+}; /* CR_In_Caucasian_Albanian */
+
+/* 'In_Vithkuqi': Block */
+static const OnigCodePoint CR_In_Vithkuqi[] = {
+ 1,
+ 0x10570, 0x105bf,
+}; /* CR_In_Vithkuqi */
+
+/* 'In_Todhri': Block */
+static const OnigCodePoint CR_In_Todhri[] = {
+ 1,
+ 0x105c0, 0x105ff,
+}; /* CR_In_Todhri */
+
+/* 'In_Linear_A': Block */
+static const OnigCodePoint CR_In_Linear_A[] = {
+ 1,
+ 0x10600, 0x1077f,
+}; /* CR_In_Linear_A */
+
+/* 'In_Latin_Extended_F': Block */
+static const OnigCodePoint CR_In_Latin_Extended_F[] = {
+ 1,
+ 0x10780, 0x107bf,
+}; /* CR_In_Latin_Extended_F */
+
+/* 'In_Cypriot_Syllabary': Block */
+static const OnigCodePoint CR_In_Cypriot_Syllabary[] = {
+ 1,
+ 0x10800, 0x1083f,
+}; /* CR_In_Cypriot_Syllabary */
+
+/* 'In_Imperial_Aramaic': Block */
+static const OnigCodePoint CR_In_Imperial_Aramaic[] = {
+ 1,
+ 0x10840, 0x1085f,
+}; /* CR_In_Imperial_Aramaic */
+
+/* 'In_Palmyrene': Block */
+#define CR_In_Palmyrene CR_Palmyrene
+
+/* 'In_Nabataean': Block */
+static const OnigCodePoint CR_In_Nabataean[] = {
+ 1,
+ 0x10880, 0x108af,
+}; /* CR_In_Nabataean */
+
+/* 'In_Hatran': Block */
+static const OnigCodePoint CR_In_Hatran[] = {
+ 1,
+ 0x108e0, 0x108ff,
+}; /* CR_In_Hatran */
+
+/* 'In_Phoenician': Block */
+static const OnigCodePoint CR_In_Phoenician[] = {
+ 1,
+ 0x10900, 0x1091f,
+}; /* CR_In_Phoenician */
+
+/* 'In_Lydian': Block */
+static const OnigCodePoint CR_In_Lydian[] = {
+ 1,
+ 0x10920, 0x1093f,
+}; /* CR_In_Lydian */
+
+/* 'In_Sidetic': Block */
+static const OnigCodePoint CR_In_Sidetic[] = {
+ 1,
+ 0x10940, 0x1095f,
+}; /* CR_In_Sidetic */
+
+/* 'In_Meroitic_Hieroglyphs': Block */
+#define CR_In_Meroitic_Hieroglyphs CR_Meroitic_Hieroglyphs
+
+/* 'In_Meroitic_Cursive': Block */
+static const OnigCodePoint CR_In_Meroitic_Cursive[] = {
+ 1,
+ 0x109a0, 0x109ff,
+}; /* CR_In_Meroitic_Cursive */
+
+/* 'In_Kharoshthi': Block */
+static const OnigCodePoint CR_In_Kharoshthi[] = {
+ 1,
+ 0x10a00, 0x10a5f,
+}; /* CR_In_Kharoshthi */
+
+/* 'In_Old_South_Arabian': Block */
+#define CR_In_Old_South_Arabian CR_Old_South_Arabian
+
+/* 'In_Old_North_Arabian': Block */
+#define CR_In_Old_North_Arabian CR_Old_North_Arabian
+
+/* 'In_Manichaean': Block */
+static const OnigCodePoint CR_In_Manichaean[] = {
+ 1,
+ 0x10ac0, 0x10aff,
+}; /* CR_In_Manichaean */
+
+/* 'In_Avestan': Block */
+static const OnigCodePoint CR_In_Avestan[] = {
+ 1,
+ 0x10b00, 0x10b3f,
+}; /* CR_In_Avestan */
+
+/* 'In_Inscriptional_Parthian': Block */
+static const OnigCodePoint CR_In_Inscriptional_Parthian[] = {
+ 1,
+ 0x10b40, 0x10b5f,
+}; /* CR_In_Inscriptional_Parthian */
+
+/* 'In_Inscriptional_Pahlavi': Block */
+static const OnigCodePoint CR_In_Inscriptional_Pahlavi[] = {
+ 1,
+ 0x10b60, 0x10b7f,
+}; /* CR_In_Inscriptional_Pahlavi */
+
+/* 'In_Psalter_Pahlavi': Block */
+static const OnigCodePoint CR_In_Psalter_Pahlavi[] = {
+ 1,
+ 0x10b80, 0x10baf,
+}; /* CR_In_Psalter_Pahlavi */
+
+/* 'In_Old_Turkic': Block */
+static const OnigCodePoint CR_In_Old_Turkic[] = {
+ 1,
+ 0x10c00, 0x10c4f,
+}; /* CR_In_Old_Turkic */
+
+/* 'In_Old_Hungarian': Block */
+static const OnigCodePoint CR_In_Old_Hungarian[] = {
+ 1,
+ 0x10c80, 0x10cff,
+}; /* CR_In_Old_Hungarian */
+
+/* 'In_Hanifi_Rohingya': Block */
+static const OnigCodePoint CR_In_Hanifi_Rohingya[] = {
+ 1,
+ 0x10d00, 0x10d3f,
+}; /* CR_In_Hanifi_Rohingya */
+
+/* 'In_Garay': Block */
+static const OnigCodePoint CR_In_Garay[] = {
+ 1,
+ 0x10d40, 0x10d8f,
+}; /* CR_In_Garay */
+
+/* 'In_Rumi_Numeral_Symbols': Block */
+static const OnigCodePoint CR_In_Rumi_Numeral_Symbols[] = {
+ 1,
+ 0x10e60, 0x10e7f,
+}; /* CR_In_Rumi_Numeral_Symbols */
+
+/* 'In_Yezidi': Block */
+static const OnigCodePoint CR_In_Yezidi[] = {
+ 1,
+ 0x10e80, 0x10ebf,
+}; /* CR_In_Yezidi */
+
+/* 'In_Arabic_Extended_C': Block */
+static const OnigCodePoint CR_In_Arabic_Extended_C[] = {
+ 1,
+ 0x10ec0, 0x10eff,
+}; /* CR_In_Arabic_Extended_C */
+
+/* 'In_Old_Sogdian': Block */
+static const OnigCodePoint CR_In_Old_Sogdian[] = {
+ 1,
+ 0x10f00, 0x10f2f,
+}; /* CR_In_Old_Sogdian */
+
+/* 'In_Sogdian': Block */
+static const OnigCodePoint CR_In_Sogdian[] = {
+ 1,
+ 0x10f30, 0x10f6f,
+}; /* CR_In_Sogdian */
+
+/* 'In_Old_Uyghur': Block */
+static const OnigCodePoint CR_In_Old_Uyghur[] = {
+ 1,
+ 0x10f70, 0x10faf,
+}; /* CR_In_Old_Uyghur */
+
+/* '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,
+ 0x10fe0, 0x10fff,
+}; /* CR_In_Elymaic */
+
+/* 'In_Brahmi': Block */
+static const OnigCodePoint CR_In_Brahmi[] = {
+ 1,
+ 0x11000, 0x1107f,
+}; /* CR_In_Brahmi */
+
+/* 'In_Kaithi': Block */
+static const OnigCodePoint CR_In_Kaithi[] = {
+ 1,
+ 0x11080, 0x110cf,
+}; /* CR_In_Kaithi */
+
+/* 'In_Sora_Sompeng': Block */
+static const OnigCodePoint CR_In_Sora_Sompeng[] = {
+ 1,
+ 0x110d0, 0x110ff,
+}; /* CR_In_Sora_Sompeng */
+
+/* 'In_Chakma': Block */
+static const OnigCodePoint CR_In_Chakma[] = {
+ 1,
+ 0x11100, 0x1114f,
+}; /* CR_In_Chakma */
+
+/* 'In_Mahajani': Block */
+static const OnigCodePoint CR_In_Mahajani[] = {
+ 1,
+ 0x11150, 0x1117f,
+}; /* CR_In_Mahajani */
+
+/* 'In_Sharada': Block */
+static const OnigCodePoint CR_In_Sharada[] = {
+ 1,
+ 0x11180, 0x111df,
+}; /* CR_In_Sharada */
+
+/* 'In_Sinhala_Archaic_Numbers': Block */
+static const OnigCodePoint CR_In_Sinhala_Archaic_Numbers[] = {
+ 1,
+ 0x111e0, 0x111ff,
+}; /* CR_In_Sinhala_Archaic_Numbers */
+
+/* 'In_Khojki': Block */
+static const OnigCodePoint CR_In_Khojki[] = {
+ 1,
+ 0x11200, 0x1124f,
+}; /* CR_In_Khojki */
+
+/* 'In_Multani': Block */
+static const OnigCodePoint CR_In_Multani[] = {
+ 1,
+ 0x11280, 0x112af,
+}; /* CR_In_Multani */
+
+/* 'In_Khudawadi': Block */
+static const OnigCodePoint CR_In_Khudawadi[] = {
+ 1,
+ 0x112b0, 0x112ff,
+}; /* CR_In_Khudawadi */
+
+/* 'In_Grantha': Block */
+static const OnigCodePoint CR_In_Grantha[] = {
+ 1,
+ 0x11300, 0x1137f,
+}; /* CR_In_Grantha */
+
+/* 'In_Tulu_Tigalari': Block */
+static const OnigCodePoint CR_In_Tulu_Tigalari[] = {
+ 1,
+ 0x11380, 0x113ff,
+}; /* CR_In_Tulu_Tigalari */
+
+/* 'In_Newa': Block */
+static const OnigCodePoint CR_In_Newa[] = {
+ 1,
+ 0x11400, 0x1147f,
+}; /* CR_In_Newa */
+
+/* 'In_Tirhuta': Block */
+static const OnigCodePoint CR_In_Tirhuta[] = {
+ 1,
+ 0x11480, 0x114df,
+}; /* CR_In_Tirhuta */
+
+/* 'In_Siddham': Block */
+static const OnigCodePoint CR_In_Siddham[] = {
+ 1,
+ 0x11580, 0x115ff,
+}; /* CR_In_Siddham */
+
+/* 'In_Modi': Block */
+static const OnigCodePoint CR_In_Modi[] = {
+ 1,
+ 0x11600, 0x1165f,
+}; /* CR_In_Modi */
+
+/* 'In_Mongolian_Supplement': Block */
+static const OnigCodePoint CR_In_Mongolian_Supplement[] = {
+ 1,
+ 0x11660, 0x1167f,
+}; /* CR_In_Mongolian_Supplement */
+
+/* 'In_Takri': Block */
+static const OnigCodePoint CR_In_Takri[] = {
+ 1,
+ 0x11680, 0x116cf,
+}; /* CR_In_Takri */
+
+/* 'In_Myanmar_Extended_C': Block */
+static const OnigCodePoint CR_In_Myanmar_Extended_C[] = {
+ 1,
+ 0x116d0, 0x116ff,
+}; /* CR_In_Myanmar_Extended_C */
+
+/* 'In_Ahom': Block */
+static const OnigCodePoint CR_In_Ahom[] = {
+ 1,
+ 0x11700, 0x1174f,
+}; /* CR_In_Ahom */
+
+/* 'In_Dogra': Block */
+static const OnigCodePoint CR_In_Dogra[] = {
+ 1,
+ 0x11800, 0x1184f,
+}; /* CR_In_Dogra */
+
+/* 'In_Warang_Citi': Block */
+static const OnigCodePoint CR_In_Warang_Citi[] = {
+ 1,
+ 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,
+ 0x119a0, 0x119ff,
+}; /* CR_In_Nandinagari */
+
+/* 'In_Zanabazar_Square': Block */
+static const OnigCodePoint CR_In_Zanabazar_Square[] = {
+ 1,
+ 0x11a00, 0x11a4f,
+}; /* CR_In_Zanabazar_Square */
+
+/* 'In_Soyombo': Block */
+static const OnigCodePoint CR_In_Soyombo[] = {
+ 1,
+ 0x11a50, 0x11aaf,
+}; /* CR_In_Soyombo */
+
+/* 'In_Unified_Canadian_Aboriginal_Syllabics_Extended_A': Block */
+static const OnigCodePoint CR_In_Unified_Canadian_Aboriginal_Syllabics_Extended_A[] = {
+ 1,
+ 0x11ab0, 0x11abf,
+}; /* CR_In_Unified_Canadian_Aboriginal_Syllabics_Extended_A */
+
+/* 'In_Pau_Cin_Hau': Block */
+static const OnigCodePoint CR_In_Pau_Cin_Hau[] = {
+ 1,
+ 0x11ac0, 0x11aff,
+}; /* CR_In_Pau_Cin_Hau */
+
+/* 'In_Devanagari_Extended_A': Block */
+static const OnigCodePoint CR_In_Devanagari_Extended_A[] = {
+ 1,
+ 0x11b00, 0x11b5f,
+}; /* CR_In_Devanagari_Extended_A */
+
+/* 'In_Sharada_Supplement': Block */
+static const OnigCodePoint CR_In_Sharada_Supplement[] = {
+ 1,
+ 0x11b60, 0x11b7f,
+}; /* CR_In_Sharada_Supplement */
+
+/* 'In_Sunuwar': Block */
+static const OnigCodePoint CR_In_Sunuwar[] = {
+ 1,
+ 0x11bc0, 0x11bff,
+}; /* CR_In_Sunuwar */
+
+/* 'In_Bhaiksuki': Block */
+static const OnigCodePoint CR_In_Bhaiksuki[] = {
+ 1,
+ 0x11c00, 0x11c6f,
+}; /* CR_In_Bhaiksuki */
+
+/* 'In_Marchen': Block */
+static const OnigCodePoint CR_In_Marchen[] = {
+ 1,
+ 0x11c70, 0x11cbf,
+}; /* CR_In_Marchen */
+
+/* 'In_Masaram_Gondi': Block */
+static const OnigCodePoint CR_In_Masaram_Gondi[] = {
+ 1,
+ 0x11d00, 0x11d5f,
+}; /* CR_In_Masaram_Gondi */
+
+/* 'In_Gunjala_Gondi': Block */
+static const OnigCodePoint CR_In_Gunjala_Gondi[] = {
+ 1,
+ 0x11d60, 0x11daf,
+}; /* CR_In_Gunjala_Gondi */
+
+/* 'In_Tolong_Siki': Block */
+static const OnigCodePoint CR_In_Tolong_Siki[] = {
+ 1,
+ 0x11db0, 0x11def,
+}; /* CR_In_Tolong_Siki */
+
+/* 'In_Makasar': Block */
+static const OnigCodePoint CR_In_Makasar[] = {
+ 1,
+ 0x11ee0, 0x11eff,
+}; /* CR_In_Makasar */
+
+/* 'In_Kawi': Block */
+static const OnigCodePoint CR_In_Kawi[] = {
+ 1,
+ 0x11f00, 0x11f5f,
+}; /* CR_In_Kawi */
+
+/* '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,
+ 0x11fc0, 0x11fff,
+}; /* CR_In_Tamil_Supplement */
+
+/* 'In_Cuneiform': Block */
+static const OnigCodePoint CR_In_Cuneiform[] = {
+ 1,
+ 0x12000, 0x123ff,
+}; /* CR_In_Cuneiform */
+
+/* 'In_Cuneiform_Numbers_and_Punctuation': Block */
+static const OnigCodePoint CR_In_Cuneiform_Numbers_and_Punctuation[] = {
+ 1,
+ 0x12400, 0x1247f,
+}; /* CR_In_Cuneiform_Numbers_and_Punctuation */
+
+/* 'In_Early_Dynastic_Cuneiform': Block */
+static const OnigCodePoint CR_In_Early_Dynastic_Cuneiform[] = {
+ 1,
+ 0x12480, 0x1254f,
+}; /* CR_In_Early_Dynastic_Cuneiform */
+
+/* 'In_Cypro_Minoan': Block */
+static const OnigCodePoint CR_In_Cypro_Minoan[] = {
+ 1,
+ 0x12f90, 0x12fff,
+}; /* CR_In_Cypro_Minoan */
+
+/* 'In_Egyptian_Hieroglyphs': Block */
+static const OnigCodePoint CR_In_Egyptian_Hieroglyphs[] = {
+ 1,
+ 0x13000, 0x1342f,
+}; /* CR_In_Egyptian_Hieroglyphs */
+
+/* 'In_Egyptian_Hieroglyph_Format_Controls': Block */
+static const OnigCodePoint CR_In_Egyptian_Hieroglyph_Format_Controls[] = {
+ 1,
+ 0x13430, 0x1345f,
+}; /* CR_In_Egyptian_Hieroglyph_Format_Controls */
+
+/* 'In_Egyptian_Hieroglyphs_Extended_A': Block */
+static const OnigCodePoint CR_In_Egyptian_Hieroglyphs_Extended_A[] = {
+ 1,
+ 0x13460, 0x143ff,
+}; /* CR_In_Egyptian_Hieroglyphs_Extended_A */
+
+/* 'In_Anatolian_Hieroglyphs': Block */
+static const OnigCodePoint CR_In_Anatolian_Hieroglyphs[] = {
+ 1,
+ 0x14400, 0x1467f,
+}; /* CR_In_Anatolian_Hieroglyphs */
+
+/* 'In_Gurung_Khema': Block */
+static const OnigCodePoint CR_In_Gurung_Khema[] = {
+ 1,
+ 0x16100, 0x1613f,
+}; /* CR_In_Gurung_Khema */
+
+/* 'In_Bamum_Supplement': Block */
+static const OnigCodePoint CR_In_Bamum_Supplement[] = {
+ 1,
+ 0x16800, 0x16a3f,
+}; /* CR_In_Bamum_Supplement */
+
+/* 'In_Mro': Block */
+static const OnigCodePoint CR_In_Mro[] = {
+ 1,
+ 0x16a40, 0x16a6f,
+}; /* CR_In_Mro */
+
+/* 'In_Tangsa': Block */
+static const OnigCodePoint CR_In_Tangsa[] = {
+ 1,
+ 0x16a70, 0x16acf,
+}; /* CR_In_Tangsa */
+
+/* 'In_Bassa_Vah': Block */
+static const OnigCodePoint CR_In_Bassa_Vah[] = {
+ 1,
+ 0x16ad0, 0x16aff,
+}; /* CR_In_Bassa_Vah */
+
+/* 'In_Pahawh_Hmong': Block */
+static const OnigCodePoint CR_In_Pahawh_Hmong[] = {
+ 1,
+ 0x16b00, 0x16b8f,
+}; /* CR_In_Pahawh_Hmong */
+
+/* 'In_Kirat_Rai': Block */
+static const OnigCodePoint CR_In_Kirat_Rai[] = {
+ 1,
+ 0x16d40, 0x16d7f,
+}; /* CR_In_Kirat_Rai */
+
+/* 'In_Medefaidrin': Block */
+static const OnigCodePoint CR_In_Medefaidrin[] = {
+ 1,
+ 0x16e40, 0x16e9f,
+}; /* CR_In_Medefaidrin */
+
+/* 'In_Beria_Erfe': Block */
+static const OnigCodePoint CR_In_Beria_Erfe[] = {
+ 1,
+ 0x16ea0, 0x16edf,
+}; /* CR_In_Beria_Erfe */
+
+/* 'In_Miao': Block */
+static const OnigCodePoint CR_In_Miao[] = {
+ 1,
+ 0x16f00, 0x16f9f,
+}; /* CR_In_Miao */
+
+/* 'In_Ideographic_Symbols_and_Punctuation': Block */
+static const OnigCodePoint CR_In_Ideographic_Symbols_and_Punctuation[] = {
+ 1,
+ 0x16fe0, 0x16fff,
+}; /* CR_In_Ideographic_Symbols_and_Punctuation */
+
+/* 'In_Tangut': Block */
+static const OnigCodePoint CR_In_Tangut[] = {
+ 1,
+ 0x17000, 0x187ff,
+}; /* CR_In_Tangut */
+
+/* 'In_Tangut_Components': Block */
+static const OnigCodePoint CR_In_Tangut_Components[] = {
+ 1,
+ 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, 0x18d7f,
+}; /* CR_In_Tangut_Supplement */
+
+/* 'In_Tangut_Components_Supplement': Block */
+static const OnigCodePoint CR_In_Tangut_Components_Supplement[] = {
+ 1,
+ 0x18d80, 0x18dff,
+}; /* CR_In_Tangut_Components_Supplement */
+
+/* 'In_Kana_Extended_B': Block */
+static const OnigCodePoint CR_In_Kana_Extended_B[] = {
+ 1,
+ 0x1aff0, 0x1afff,
+}; /* CR_In_Kana_Extended_B */
+
+/* 'In_Kana_Supplement': Block */
+static const OnigCodePoint CR_In_Kana_Supplement[] = {
+ 1,
+ 0x1b000, 0x1b0ff,
+}; /* CR_In_Kana_Supplement */
+
+/* 'In_Kana_Extended_A': Block */
+static const OnigCodePoint CR_In_Kana_Extended_A[] = {
+ 1,
+ 0x1b100, 0x1b12f,
+}; /* CR_In_Kana_Extended_A */
+
+/* 'In_Small_Kana_Extension': Block */
+static const OnigCodePoint CR_In_Small_Kana_Extension[] = {
+ 1,
+ 0x1b130, 0x1b16f,
+}; /* CR_In_Small_Kana_Extension */
+
+/* 'In_Nushu': Block */
+static const OnigCodePoint CR_In_Nushu[] = {
+ 1,
+ 0x1b170, 0x1b2ff,
+}; /* CR_In_Nushu */
+
+/* 'In_Duployan': Block */
+static const OnigCodePoint CR_In_Duployan[] = {
+ 1,
+ 0x1bc00, 0x1bc9f,
+}; /* CR_In_Duployan */
+
+/* 'In_Shorthand_Format_Controls': Block */
+static const OnigCodePoint CR_In_Shorthand_Format_Controls[] = {
+ 1,
+ 0x1bca0, 0x1bcaf,
+}; /* CR_In_Shorthand_Format_Controls */
+
+/* 'In_Symbols_for_Legacy_Computing_Supplement': Block */
+static const OnigCodePoint CR_In_Symbols_for_Legacy_Computing_Supplement[] = {
+ 1,
+ 0x1cc00, 0x1cebf,
+}; /* CR_In_Symbols_for_Legacy_Computing_Supplement */
+
+/* 'In_Miscellaneous_Symbols_Supplement': Block */
+static const OnigCodePoint CR_In_Miscellaneous_Symbols_Supplement[] = {
+ 1,
+ 0x1cec0, 0x1ceff,
+}; /* CR_In_Miscellaneous_Symbols_Supplement */
+
+/* 'In_Znamenny_Musical_Notation': Block */
+static const OnigCodePoint CR_In_Znamenny_Musical_Notation[] = {
+ 1,
+ 0x1cf00, 0x1cfcf,
+}; /* CR_In_Znamenny_Musical_Notation */
+
+/* 'In_Byzantine_Musical_Symbols': Block */
+static const OnigCodePoint CR_In_Byzantine_Musical_Symbols[] = {
+ 1,
+ 0x1d000, 0x1d0ff,
+}; /* CR_In_Byzantine_Musical_Symbols */
+
+/* 'In_Musical_Symbols': Block */
+static const OnigCodePoint CR_In_Musical_Symbols[] = {
+ 1,
+ 0x1d100, 0x1d1ff,
+}; /* CR_In_Musical_Symbols */
+
+/* 'In_Ancient_Greek_Musical_Notation': Block */
+static const OnigCodePoint CR_In_Ancient_Greek_Musical_Notation[] = {
+ 1,
+ 0x1d200, 0x1d24f,
+}; /* CR_In_Ancient_Greek_Musical_Notation */
+
+/* 'In_Kaktovik_Numerals': Block */
+static const OnigCodePoint CR_In_Kaktovik_Numerals[] = {
+ 1,
+ 0x1d2c0, 0x1d2df,
+}; /* CR_In_Kaktovik_Numerals */
+
+/* 'In_Mayan_Numerals': Block */
+static const OnigCodePoint CR_In_Mayan_Numerals[] = {
+ 1,
+ 0x1d2e0, 0x1d2ff,
+}; /* CR_In_Mayan_Numerals */
+
+/* 'In_Tai_Xuan_Jing_Symbols': Block */
+static const OnigCodePoint CR_In_Tai_Xuan_Jing_Symbols[] = {
+ 1,
+ 0x1d300, 0x1d35f,
+}; /* CR_In_Tai_Xuan_Jing_Symbols */
+
+/* 'In_Counting_Rod_Numerals': Block */
+static const OnigCodePoint CR_In_Counting_Rod_Numerals[] = {
+ 1,
+ 0x1d360, 0x1d37f,
+}; /* CR_In_Counting_Rod_Numerals */
+
+/* 'In_Mathematical_Alphanumeric_Symbols': Block */
+static const OnigCodePoint CR_In_Mathematical_Alphanumeric_Symbols[] = {
+ 1,
+ 0x1d400, 0x1d7ff,
+}; /* CR_In_Mathematical_Alphanumeric_Symbols */
+
+/* 'In_Sutton_SignWriting': Block */
+static const OnigCodePoint CR_In_Sutton_SignWriting[] = {
+ 1,
+ 0x1d800, 0x1daaf,
+}; /* CR_In_Sutton_SignWriting */
+
+/* 'In_Latin_Extended_G': Block */
+static const OnigCodePoint CR_In_Latin_Extended_G[] = {
+ 1,
+ 0x1df00, 0x1dfff,
+}; /* CR_In_Latin_Extended_G */
+
+/* 'In_Glagolitic_Supplement': Block */
+static const OnigCodePoint CR_In_Glagolitic_Supplement[] = {
+ 1,
+ 0x1e000, 0x1e02f,
+}; /* CR_In_Glagolitic_Supplement */
+
+/* 'In_Cyrillic_Extended_D': Block */
+static const OnigCodePoint CR_In_Cyrillic_Extended_D[] = {
+ 1,
+ 0x1e030, 0x1e08f,
+}; /* CR_In_Cyrillic_Extended_D */
+
+/* 'In_Nyiakeng_Puachue_Hmong': Block */
+static const OnigCodePoint CR_In_Nyiakeng_Puachue_Hmong[] = {
+ 1,
+ 0x1e100, 0x1e14f,
+}; /* CR_In_Nyiakeng_Puachue_Hmong */
+
+/* 'In_Toto': Block */
+static const OnigCodePoint CR_In_Toto[] = {
+ 1,
+ 0x1e290, 0x1e2bf,
+}; /* CR_In_Toto */
+
+/* 'In_Wancho': Block */
+static const OnigCodePoint CR_In_Wancho[] = {
+ 1,
+ 0x1e2c0, 0x1e2ff,
+}; /* CR_In_Wancho */
+
+/* 'In_Nag_Mundari': Block */
+static const OnigCodePoint CR_In_Nag_Mundari[] = {
+ 1,
+ 0x1e4d0, 0x1e4ff,
+}; /* CR_In_Nag_Mundari */
+
+/* 'In_Ol_Onal': Block */
+static const OnigCodePoint CR_In_Ol_Onal[] = {
+ 1,
+ 0x1e5d0, 0x1e5ff,
+}; /* CR_In_Ol_Onal */
+
+/* 'In_Tai_Yo': Block */
+static const OnigCodePoint CR_In_Tai_Yo[] = {
+ 1,
+ 0x1e6c0, 0x1e6ff,
+}; /* CR_In_Tai_Yo */
+
+/* 'In_Ethiopic_Extended_B': Block */
+static const OnigCodePoint CR_In_Ethiopic_Extended_B[] = {
+ 1,
+ 0x1e7e0, 0x1e7ff,
+}; /* CR_In_Ethiopic_Extended_B */
+
+/* 'In_Mende_Kikakui': Block */
+static const OnigCodePoint CR_In_Mende_Kikakui[] = {
+ 1,
+ 0x1e800, 0x1e8df,
+}; /* CR_In_Mende_Kikakui */
+
+/* 'In_Adlam': Block */
+static const OnigCodePoint CR_In_Adlam[] = {
+ 1,
+ 0x1e900, 0x1e95f,
+}; /* CR_In_Adlam */
+
+/* 'In_Indic_Siyaq_Numbers': Block */
+static const OnigCodePoint CR_In_Indic_Siyaq_Numbers[] = {
+ 1,
+ 0x1ec70, 0x1ecbf,
+}; /* CR_In_Indic_Siyaq_Numbers */
+
+/* 'In_Ottoman_Siyaq_Numbers': Block */
+static const OnigCodePoint CR_In_Ottoman_Siyaq_Numbers[] = {
+ 1,
+ 0x1ed00, 0x1ed4f,
+}; /* CR_In_Ottoman_Siyaq_Numbers */
+
+/* 'In_Arabic_Mathematical_Alphabetic_Symbols': Block */
+static const OnigCodePoint CR_In_Arabic_Mathematical_Alphabetic_Symbols[] = {
+ 1,
+ 0x1ee00, 0x1eeff,
+}; /* CR_In_Arabic_Mathematical_Alphabetic_Symbols */
+
+/* 'In_Mahjong_Tiles': Block */
+static const OnigCodePoint CR_In_Mahjong_Tiles[] = {
+ 1,
+ 0x1f000, 0x1f02f,
+}; /* CR_In_Mahjong_Tiles */
+
+/* 'In_Domino_Tiles': Block */
+static const OnigCodePoint CR_In_Domino_Tiles[] = {
+ 1,
+ 0x1f030, 0x1f09f,
+}; /* CR_In_Domino_Tiles */
+
+/* 'In_Playing_Cards': Block */
+static const OnigCodePoint CR_In_Playing_Cards[] = {
+ 1,
+ 0x1f0a0, 0x1f0ff,
+}; /* CR_In_Playing_Cards */
+
+/* 'In_Enclosed_Alphanumeric_Supplement': Block */
+static const OnigCodePoint CR_In_Enclosed_Alphanumeric_Supplement[] = {
+ 1,
+ 0x1f100, 0x1f1ff,
+}; /* CR_In_Enclosed_Alphanumeric_Supplement */
+
+/* 'In_Enclosed_Ideographic_Supplement': Block */
+static const OnigCodePoint CR_In_Enclosed_Ideographic_Supplement[] = {
+ 1,
+ 0x1f200, 0x1f2ff,
+}; /* CR_In_Enclosed_Ideographic_Supplement */
+
+/* 'In_Miscellaneous_Symbols_and_Pictographs': Block */
+static const OnigCodePoint CR_In_Miscellaneous_Symbols_and_Pictographs[] = {
+ 1,
+ 0x1f300, 0x1f5ff,
+}; /* CR_In_Miscellaneous_Symbols_and_Pictographs */
+
+/* 'In_Emoticons': Block */
+static const OnigCodePoint CR_In_Emoticons[] = {
+ 1,
+ 0x1f600, 0x1f64f,
+}; /* CR_In_Emoticons */
+
+/* 'In_Ornamental_Dingbats': Block */
+static const OnigCodePoint CR_In_Ornamental_Dingbats[] = {
+ 1,
+ 0x1f650, 0x1f67f,
+}; /* CR_In_Ornamental_Dingbats */
+
+/* 'In_Transport_and_Map_Symbols': Block */
+static const OnigCodePoint CR_In_Transport_and_Map_Symbols[] = {
+ 1,
+ 0x1f680, 0x1f6ff,
+}; /* CR_In_Transport_and_Map_Symbols */
+
+/* 'In_Alchemical_Symbols': Block */
+static const OnigCodePoint CR_In_Alchemical_Symbols[] = {
+ 1,
+ 0x1f700, 0x1f77f,
+}; /* CR_In_Alchemical_Symbols */
+
+/* 'In_Geometric_Shapes_Extended': Block */
+static const OnigCodePoint CR_In_Geometric_Shapes_Extended[] = {
+ 1,
+ 0x1f780, 0x1f7ff,
+}; /* CR_In_Geometric_Shapes_Extended */
+
+/* 'In_Supplemental_Arrows_C': Block */
+static const OnigCodePoint CR_In_Supplemental_Arrows_C[] = {
+ 1,
+ 0x1f800, 0x1f8ff,
+}; /* CR_In_Supplemental_Arrows_C */
+
+/* 'In_Supplemental_Symbols_and_Pictographs': Block */
+static const OnigCodePoint CR_In_Supplemental_Symbols_and_Pictographs[] = {
+ 1,
+ 0x1f900, 0x1f9ff,
+}; /* CR_In_Supplemental_Symbols_and_Pictographs */
+
+/* 'In_Chess_Symbols': Block */
+static const OnigCodePoint CR_In_Chess_Symbols[] = {
+ 1,
+ 0x1fa00, 0x1fa6f,
+}; /* CR_In_Chess_Symbols */
+
+/* 'In_Symbols_and_Pictographs_Extended_A': Block */
+static const OnigCodePoint CR_In_Symbols_and_Pictographs_Extended_A[] = {
+ 1,
+ 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,
+ 0x20000, 0x2a6df,
+}; /* CR_In_CJK_Unified_Ideographs_Extension_B */
+
+/* 'In_CJK_Unified_Ideographs_Extension_C': Block */
+static const OnigCodePoint CR_In_CJK_Unified_Ideographs_Extension_C[] = {
+ 1,
+ 0x2a700, 0x2b73f,
+}; /* CR_In_CJK_Unified_Ideographs_Extension_C */
+
+/* 'In_CJK_Unified_Ideographs_Extension_D': Block */
+static const OnigCodePoint CR_In_CJK_Unified_Ideographs_Extension_D[] = {
+ 1,
+ 0x2b740, 0x2b81f,
+}; /* CR_In_CJK_Unified_Ideographs_Extension_D */
+
+/* 'In_CJK_Unified_Ideographs_Extension_E': Block */
+static const OnigCodePoint CR_In_CJK_Unified_Ideographs_Extension_E[] = {
+ 1,
+ 0x2b820, 0x2ceaf,
+}; /* CR_In_CJK_Unified_Ideographs_Extension_E */
+
+/* 'In_CJK_Unified_Ideographs_Extension_F': Block */
+static const OnigCodePoint CR_In_CJK_Unified_Ideographs_Extension_F[] = {
+ 1,
+ 0x2ceb0, 0x2ebef,
+}; /* CR_In_CJK_Unified_Ideographs_Extension_F */
+
+/* 'In_CJK_Unified_Ideographs_Extension_I': Block */
+static const OnigCodePoint CR_In_CJK_Unified_Ideographs_Extension_I[] = {
+ 1,
+ 0x2ebf0, 0x2ee5f,
+}; /* CR_In_CJK_Unified_Ideographs_Extension_I */
+
+/* 'In_CJK_Compatibility_Ideographs_Supplement': Block */
+static const OnigCodePoint CR_In_CJK_Compatibility_Ideographs_Supplement[] = {
+ 1,
+ 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_CJK_Unified_Ideographs_Extension_H': Block */
+static const OnigCodePoint CR_In_CJK_Unified_Ideographs_Extension_H[] = {
+ 1,
+ 0x31350, 0x323af,
+}; /* CR_In_CJK_Unified_Ideographs_Extension_H */
+
+/* 'In_CJK_Unified_Ideographs_Extension_J': Block */
+static const OnigCodePoint CR_In_CJK_Unified_Ideographs_Extension_J[] = {
+ 1,
+ 0x323b0, 0x3347f,
+}; /* CR_In_CJK_Unified_Ideographs_Extension_J */
+
+/* 'In_Tags': Block */
+static const OnigCodePoint CR_In_Tags[] = {
+ 1,
+ 0xe0000, 0xe007f,
+}; /* CR_In_Tags */
+
+/* 'In_Variation_Selectors_Supplement': Block */
+static const OnigCodePoint CR_In_Variation_Selectors_Supplement[] = {
+ 1,
+ 0xe0100, 0xe01ef,
+}; /* CR_In_Variation_Selectors_Supplement */
+
+/* 'In_Supplementary_Private_Use_Area_A': Block */
+static const OnigCodePoint CR_In_Supplementary_Private_Use_Area_A[] = {
+ 1,
+ 0xf0000, 0xfffff,
+}; /* CR_In_Supplementary_Private_Use_Area_A */
+
+/* 'In_Supplementary_Private_Use_Area_B': Block */
+static const OnigCodePoint CR_In_Supplementary_Private_Use_Area_B[] = {
+ 1,
+ 0x100000, 0x10ffff,
+}; /* CR_In_Supplementary_Private_Use_Area_B */
+
+/* 'In_No_Block': Block */
+static const OnigCodePoint CR_In_No_Block[] = {
+ 51,
+ 0x2fe0, 0x2fef,
+ 0x10200, 0x1027f,
+ 0x103e0, 0x103ff,
+ 0x107c0, 0x107ff,
+ 0x108b0, 0x108df,
+ 0x10960, 0x1097f,
+ 0x10aa0, 0x10abf,
+ 0x10bb0, 0x10bff,
+ 0x10c50, 0x10c7f,
+ 0x10d90, 0x10e5f,
+ 0x11250, 0x1127f,
+ 0x114e0, 0x1157f,
+ 0x11750, 0x117ff,
+ 0x11850, 0x1189f,
+ 0x11960, 0x1199f,
+ 0x11b80, 0x11bbf,
+ 0x11cc0, 0x11cff,
+ 0x11df0, 0x11edf,
+ 0x11f60, 0x11faf,
+ 0x12550, 0x12f8f,
+ 0x14680, 0x160ff,
+ 0x16140, 0x167ff,
+ 0x16b90, 0x16d3f,
+ 0x16d80, 0x16e3f,
+ 0x16ee0, 0x16eff,
+ 0x16fa0, 0x16fdf,
+ 0x18e00, 0x1afef,
+ 0x1b300, 0x1bbff,
+ 0x1bcb0, 0x1cbff,
+ 0x1cfd0, 0x1cfff,
+ 0x1d250, 0x1d2bf,
+ 0x1d380, 0x1d3ff,
+ 0x1dab0, 0x1deff,
+ 0x1e090, 0x1e0ff,
+ 0x1e150, 0x1e28f,
+ 0x1e300, 0x1e4cf,
+ 0x1e500, 0x1e5cf,
+ 0x1e600, 0x1e6bf,
+ 0x1e700, 0x1e7df,
+ 0x1e8e0, 0x1e8ff,
+ 0x1e960, 0x1ec6f,
+ 0x1ecc0, 0x1ecff,
+ 0x1ed50, 0x1edff,
+ 0x1ef00, 0x1efff,
+ 0x1fc00, 0x1ffff,
+ 0x2a6e0, 0x2a6ff,
+ 0x2ee60, 0x2f7ff,
+ 0x2fa20, 0x2ffff,
+ 0x33480, 0xdffff,
+ 0xe0080, 0xe00ff,
+ 0xe01f0, 0xeffff,
+}; /* CR_In_No_Block */
+
+#endif /* USE_UNICODE_PROPERTIES */
+static const OnigCodePoint* const CodeRanges[] = {
+ CR_NEWLINE,
+ CR_Alpha,
+ CR_Blank,
+ CR_Cntrl,
+ CR_Digit,
+ CR_Graph,
+ CR_Lower,
+ CR_Print,
+ CR_XPosixPunct,
+ CR_Space,
+ CR_Upper,
+ CR_XDigit,
+ CR_Word,
+ CR_Alnum,
+ CR_ASCII,
+ CR_Punct,
+#ifdef USE_UNICODE_PROPERTIES
+ CR_Any,
+ CR_Assigned,
+ CR_C,
+ CR_Cc,
+ CR_Cf,
+ CR_Cn,
+ CR_Co,
+ CR_Cs,
+ CR_L,
+ CR_LC,
+ CR_Ll,
+ CR_Lm,
+ CR_Lo,
+ CR_Lt,
+ CR_Lu,
+ CR_M,
+ CR_Mc,
+ CR_Me,
+ CR_Mn,
+ CR_N,
+ CR_Nd,
+ CR_Nl,
+ CR_No,
+ CR_P,
+ CR_Pc,
+ CR_Pd,
+ CR_Pe,
+ CR_Pf,
+ CR_Pi,
+ CR_Po,
+ CR_Ps,
+ CR_S,
+ CR_Sc,
+ CR_Sk,
+ CR_Sm,
+ CR_So,
+ CR_Z,
+ CR_Zl,
+ CR_Zp,
+ CR_Zs,
+ CR_Math,
+ CR_Alphabetic,
+ CR_Lowercase,
+ CR_Uppercase,
+ CR_Cased,
+ CR_Case_Ignorable,
+ CR_Changes_When_Lowercased,
+ CR_Changes_When_Uppercased,
+ CR_Changes_When_Titlecased,
+ CR_Changes_When_Casefolded,
+ CR_Changes_When_Casemapped,
+ CR_ID_Start,
+ CR_ID_Continue,
+ CR_XID_Start,
+ CR_XID_Continue,
+ CR_Default_Ignorable_Code_Point,
+ CR_Grapheme_Extend,
+ CR_Grapheme_Base,
+ CR_Grapheme_Link,
+ CR_InCB_Linker,
+ CR_InCB_Consonant,
+ CR_InCB_Extend,
+ CR_Common,
+ CR_Latin,
+ CR_Greek,
+ CR_Cyrillic,
+ CR_Armenian,
+ CR_Hebrew,
+ CR_Arabic,
+ CR_Syriac,
+ CR_Thaana,
+ CR_Devanagari,
+ CR_Bengali,
+ CR_Gurmukhi,
+ CR_Gujarati,
+ CR_Oriya,
+ CR_Tamil,
+ CR_Telugu,
+ CR_Kannada,
+ CR_Malayalam,
+ CR_Sinhala,
+ CR_Thai,
+ CR_Lao,
+ CR_Tibetan,
+ CR_Myanmar,
+ CR_Georgian,
+ CR_Hangul,
+ CR_Ethiopic,
+ CR_Cherokee,
+ CR_Canadian_Aboriginal,
+ CR_Ogham,
+ CR_Runic,
+ CR_Khmer,
+ CR_Mongolian,
+ CR_Hiragana,
+ CR_Katakana,
+ CR_Bopomofo,
+ CR_Han,
+ CR_Yi,
+ CR_Old_Italic,
+ CR_Gothic,
+ CR_Deseret,
+ CR_Inherited,
+ CR_Tagalog,
+ CR_Hanunoo,
+ CR_Buhid,
+ CR_Tagbanwa,
+ CR_Limbu,
+ CR_Tai_Le,
+ CR_Linear_B,
+ CR_Ugaritic,
+ CR_Shavian,
+ CR_Osmanya,
+ CR_Cypriot,
+ CR_Braille,
+ CR_Buginese,
+ CR_Coptic,
+ CR_New_Tai_Lue,
+ CR_Glagolitic,
+ CR_Tifinagh,
+ CR_Syloti_Nagri,
+ CR_Old_Persian,
+ CR_Kharoshthi,
+ CR_Balinese,
+ CR_Cuneiform,
+ CR_Phoenician,
+ CR_Phags_Pa,
+ CR_Nko,
+ CR_Sundanese,
+ CR_Lepcha,
+ CR_Ol_Chiki,
+ CR_Vai,
+ CR_Saurashtra,
+ CR_Kayah_Li,
+ CR_Rejang,
+ CR_Lycian,
+ CR_Carian,
+ CR_Lydian,
+ CR_Cham,
+ CR_Tai_Tham,
+ CR_Tai_Viet,
+ CR_Avestan,
+ CR_Egyptian_Hieroglyphs,
+ CR_Samaritan,
+ CR_Lisu,
+ CR_Bamum,
+ CR_Javanese,
+ CR_Meetei_Mayek,
+ CR_Imperial_Aramaic,
+ CR_Old_South_Arabian,
+ CR_Inscriptional_Parthian,
+ CR_Inscriptional_Pahlavi,
+ CR_Old_Turkic,
+ CR_Kaithi,
+ CR_Batak,
+ CR_Brahmi,
+ CR_Mandaic,
+ CR_Chakma,
+ CR_Meroitic_Cursive,
+ CR_Meroitic_Hieroglyphs,
+ CR_Miao,
+ CR_Sharada,
+ CR_Sora_Sompeng,
+ CR_Takri,
+ CR_Caucasian_Albanian,
+ CR_Bassa_Vah,
+ CR_Duployan,
+ CR_Elbasan,
+ CR_Grantha,
+ CR_Pahawh_Hmong,
+ CR_Khojki,
+ CR_Linear_A,
+ CR_Mahajani,
+ CR_Manichaean,
+ CR_Mende_Kikakui,
+ CR_Modi,
+ CR_Mro,
+ CR_Old_North_Arabian,
+ CR_Nabataean,
+ CR_Palmyrene,
+ CR_Pau_Cin_Hau,
+ CR_Old_Permic,
+ CR_Psalter_Pahlavi,
+ CR_Siddham,
+ CR_Khudawadi,
+ CR_Tirhuta,
+ CR_Warang_Citi,
+ CR_Ahom,
+ CR_Anatolian_Hieroglyphs,
+ CR_Hatran,
+ CR_Multani,
+ CR_Old_Hungarian,
+ CR_SignWriting,
+ CR_Adlam,
+ CR_Bhaiksuki,
+ CR_Marchen,
+ CR_Newa,
+ CR_Osage,
+ CR_Tangut,
+ CR_Masaram_Gondi,
+ CR_Nushu,
+ CR_Soyombo,
+ CR_Zanabazar_Square,
+ CR_Dogra,
+ CR_Gunjala_Gondi,
+ CR_Makasar,
+ CR_Medefaidrin,
+ CR_Hanifi_Rohingya,
+ CR_Sogdian,
+ CR_Old_Sogdian,
+ CR_Elymaic,
+ CR_Nandinagari,
+ CR_Nyiakeng_Puachue_Hmong,
+ CR_Wancho,
+ CR_Chorasmian,
+ CR_Dives_Akuru,
+ CR_Khitan_Small_Script,
+ CR_Yezidi,
+ CR_Cypro_Minoan,
+ CR_Old_Uyghur,
+ CR_Tangsa,
+ CR_Toto,
+ CR_Vithkuqi,
+ CR_Kawi,
+ CR_Nag_Mundari,
+ CR_Garay,
+ CR_Gurung_Khema,
+ CR_Kirat_Rai,
+ CR_Ol_Onal,
+ CR_Sunuwar,
+ CR_Todhri,
+ CR_Tulu_Tigalari,
+ CR_Sidetic,
+ CR_Tai_Yo,
+ CR_Tolong_Siki,
+ CR_Beria_Erfe,
+ CR_White_Space,
+ CR_Bidi_Control,
+ CR_Join_Control,
+ CR_Dash,
+ CR_Hyphen,
+ CR_Quotation_Mark,
+ CR_Terminal_Punctuation,
+ CR_Other_Math,
+ CR_Hex_Digit,
+ CR_ASCII_Hex_Digit,
+ CR_Other_Alphabetic,
+ CR_Ideographic,
+ CR_Diacritic,
+ CR_Extender,
+ CR_Other_Lowercase,
+ CR_Other_Uppercase,
+ CR_Noncharacter_Code_Point,
+ CR_Other_Grapheme_Extend,
+ CR_IDS_Binary_Operator,
+ CR_IDS_Trinary_Operator,
+ CR_IDS_Unary_Operator,
+ CR_Radical,
+ CR_Unified_Ideograph,
+ CR_Other_Default_Ignorable_Code_Point,
+ CR_Deprecated,
+ CR_Soft_Dotted,
+ CR_Logical_Order_Exception,
+ CR_Other_ID_Start,
+ CR_Other_ID_Continue,
+ CR_ID_Compat_Math_Continue,
+ CR_ID_Compat_Math_Start,
+ CR_Sentence_Terminal,
+ CR_Variation_Selector,
+ CR_Pattern_White_Space,
+ CR_Pattern_Syntax,
+ CR_Prepended_Concatenation_Mark,
+ CR_Regional_Indicator,
+ CR_Modifier_Combining_Mark,
+ CR_Emoji,
+ CR_Emoji_Presentation,
+ CR_Emoji_Modifier,
+ CR_Emoji_Modifier_Base,
+ CR_Emoji_Component,
+ CR_Extended_Pictographic,
+ CR_Unknown,
+#ifdef USE_UNICODE_AGE_PROPERTIES
+ CR_Age_1_1,
+ CR_Age_2_0,
+ CR_Age_2_1,
+ CR_Age_3_0,
+ CR_Age_3_1,
+ CR_Age_3_2,
+ CR_Age_4_0,
+ CR_Age_4_1,
+ CR_Age_5_0,
+ CR_Age_5_1,
+ CR_Age_5_2,
+ CR_Age_6_0,
+ CR_Age_6_1,
+ CR_Age_6_2,
+ CR_Age_6_3,
+ CR_Age_7_0,
+ CR_Age_8_0,
+ CR_Age_9_0,
+ CR_Age_10_0,
+ CR_Age_11_0,
+ CR_Age_12_0,
+ CR_Age_12_1,
+ CR_Age_13_0,
+ CR_Age_14_0,
+ CR_Age_15_0,
+ CR_Age_15_1,
+ CR_Age_16_0,
+ CR_Age_17_0,
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ CR_Grapheme_Cluster_Break_Prepend,
+ CR_Grapheme_Cluster_Break_CR,
+ CR_Grapheme_Cluster_Break_LF,
+ CR_Grapheme_Cluster_Break_Control,
+ CR_Grapheme_Cluster_Break_Extend,
+ CR_Grapheme_Cluster_Break_Regional_Indicator,
+ CR_Grapheme_Cluster_Break_SpacingMark,
+ CR_Grapheme_Cluster_Break_L,
+ CR_Grapheme_Cluster_Break_V,
+ CR_Grapheme_Cluster_Break_T,
+ CR_Grapheme_Cluster_Break_LV,
+ CR_Grapheme_Cluster_Break_LVT,
+ CR_Grapheme_Cluster_Break_ZWJ,
+ CR_In_Basic_Latin,
+ CR_In_Latin_1_Supplement,
+ CR_In_Latin_Extended_A,
+ CR_In_Latin_Extended_B,
+ CR_In_IPA_Extensions,
+ CR_In_Spacing_Modifier_Letters,
+ CR_In_Combining_Diacritical_Marks,
+ CR_In_Greek_and_Coptic,
+ CR_In_Cyrillic,
+ CR_In_Cyrillic_Supplement,
+ CR_In_Armenian,
+ CR_In_Hebrew,
+ CR_In_Arabic,
+ CR_In_Syriac,
+ CR_In_Arabic_Supplement,
+ CR_In_Thaana,
+ CR_In_NKo,
+ CR_In_Samaritan,
+ CR_In_Mandaic,
+ CR_In_Syriac_Supplement,
+ CR_In_Arabic_Extended_B,
+ CR_In_Arabic_Extended_A,
+ CR_In_Devanagari,
+ CR_In_Bengali,
+ CR_In_Gurmukhi,
+ CR_In_Gujarati,
+ CR_In_Oriya,
+ CR_In_Tamil,
+ CR_In_Telugu,
+ CR_In_Kannada,
+ CR_In_Malayalam,
+ CR_In_Sinhala,
+ CR_In_Thai,
+ CR_In_Lao,
+ CR_In_Tibetan,
+ CR_In_Myanmar,
+ CR_In_Georgian,
+ CR_In_Hangul_Jamo,
+ CR_In_Ethiopic,
+ CR_In_Ethiopic_Supplement,
+ CR_In_Cherokee,
+ CR_In_Unified_Canadian_Aboriginal_Syllabics,
+ CR_In_Ogham,
+ CR_In_Runic,
+ CR_In_Tagalog,
+ CR_In_Hanunoo,
+ CR_In_Buhid,
+ CR_In_Tagbanwa,
+ CR_In_Khmer,
+ CR_In_Mongolian,
+ CR_In_Unified_Canadian_Aboriginal_Syllabics_Extended,
+ CR_In_Limbu,
+ CR_In_Tai_Le,
+ CR_In_New_Tai_Lue,
+ CR_In_Khmer_Symbols,
+ CR_In_Buginese,
+ CR_In_Tai_Tham,
+ CR_In_Combining_Diacritical_Marks_Extended,
+ CR_In_Balinese,
+ CR_In_Sundanese,
+ CR_In_Batak,
+ CR_In_Lepcha,
+ CR_In_Ol_Chiki,
+ CR_In_Cyrillic_Extended_C,
+ CR_In_Georgian_Extended,
+ CR_In_Sundanese_Supplement,
+ CR_In_Vedic_Extensions,
+ CR_In_Phonetic_Extensions,
+ CR_In_Phonetic_Extensions_Supplement,
+ CR_In_Combining_Diacritical_Marks_Supplement,
+ CR_In_Latin_Extended_Additional,
+ CR_In_Greek_Extended,
+ CR_In_General_Punctuation,
+ CR_In_Superscripts_and_Subscripts,
+ CR_In_Currency_Symbols,
+ CR_In_Combining_Diacritical_Marks_for_Symbols,
+ CR_In_Letterlike_Symbols,
+ CR_In_Number_Forms,
+ CR_In_Arrows,
+ CR_In_Mathematical_Operators,
+ CR_In_Miscellaneous_Technical,
+ CR_In_Control_Pictures,
+ CR_In_Optical_Character_Recognition,
+ CR_In_Enclosed_Alphanumerics,
+ CR_In_Box_Drawing,
+ CR_In_Block_Elements,
+ CR_In_Geometric_Shapes,
+ CR_In_Miscellaneous_Symbols,
+ CR_In_Dingbats,
+ CR_In_Miscellaneous_Mathematical_Symbols_A,
+ CR_In_Supplemental_Arrows_A,
+ CR_In_Braille_Patterns,
+ CR_In_Supplemental_Arrows_B,
+ CR_In_Miscellaneous_Mathematical_Symbols_B,
+ CR_In_Supplemental_Mathematical_Operators,
+ CR_In_Miscellaneous_Symbols_and_Arrows,
+ CR_In_Glagolitic,
+ CR_In_Latin_Extended_C,
+ CR_In_Coptic,
+ CR_In_Georgian_Supplement,
+ CR_In_Tifinagh,
+ CR_In_Ethiopic_Extended,
+ CR_In_Cyrillic_Extended_A,
+ CR_In_Supplemental_Punctuation,
+ CR_In_CJK_Radicals_Supplement,
+ CR_In_Kangxi_Radicals,
+ CR_In_Ideographic_Description_Characters,
+ CR_In_CJK_Symbols_and_Punctuation,
+ CR_In_Hiragana,
+ CR_In_Katakana,
+ CR_In_Bopomofo,
+ CR_In_Hangul_Compatibility_Jamo,
+ CR_In_Kanbun,
+ CR_In_Bopomofo_Extended,
+ CR_In_CJK_Strokes,
+ CR_In_Katakana_Phonetic_Extensions,
+ CR_In_Enclosed_CJK_Letters_and_Months,
+ CR_In_CJK_Compatibility,
+ CR_In_CJK_Unified_Ideographs_Extension_A,
+ CR_In_Yijing_Hexagram_Symbols,
+ CR_In_CJK_Unified_Ideographs,
+ CR_In_Yi_Syllables,
+ CR_In_Yi_Radicals,
+ CR_In_Lisu,
+ CR_In_Vai,
+ CR_In_Cyrillic_Extended_B,
+ CR_In_Bamum,
+ CR_In_Modifier_Tone_Letters,
+ CR_In_Latin_Extended_D,
+ CR_In_Syloti_Nagri,
+ CR_In_Common_Indic_Number_Forms,
+ CR_In_Phags_pa,
+ CR_In_Saurashtra,
+ CR_In_Devanagari_Extended,
+ CR_In_Kayah_Li,
+ CR_In_Rejang,
+ CR_In_Hangul_Jamo_Extended_A,
+ CR_In_Javanese,
+ CR_In_Myanmar_Extended_B,
+ CR_In_Cham,
+ CR_In_Myanmar_Extended_A,
+ CR_In_Tai_Viet,
+ CR_In_Meetei_Mayek_Extensions,
+ CR_In_Ethiopic_Extended_A,
+ CR_In_Latin_Extended_E,
+ CR_In_Cherokee_Supplement,
+ CR_In_Meetei_Mayek,
+ CR_In_Hangul_Syllables,
+ CR_In_Hangul_Jamo_Extended_B,
+ CR_In_High_Surrogates,
+ CR_In_High_Private_Use_Surrogates,
+ CR_In_Low_Surrogates,
+ CR_In_Private_Use_Area,
+ CR_In_CJK_Compatibility_Ideographs,
+ CR_In_Alphabetic_Presentation_Forms,
+ CR_In_Arabic_Presentation_Forms_A,
+ CR_In_Variation_Selectors,
+ CR_In_Vertical_Forms,
+ CR_In_Combining_Half_Marks,
+ CR_In_CJK_Compatibility_Forms,
+ CR_In_Small_Form_Variants,
+ CR_In_Arabic_Presentation_Forms_B,
+ CR_In_Halfwidth_and_Fullwidth_Forms,
+ CR_In_Specials,
+ CR_In_Linear_B_Syllabary,
+ CR_In_Linear_B_Ideograms,
+ CR_In_Aegean_Numbers,
+ CR_In_Ancient_Greek_Numbers,
+ CR_In_Ancient_Symbols,
+ CR_In_Phaistos_Disc,
+ CR_In_Lycian,
+ CR_In_Carian,
+ CR_In_Coptic_Epact_Numbers,
+ CR_In_Old_Italic,
+ CR_In_Gothic,
+ CR_In_Old_Permic,
+ CR_In_Ugaritic,
+ CR_In_Old_Persian,
+ CR_In_Deseret,
+ CR_In_Shavian,
+ CR_In_Osmanya,
+ CR_In_Osage,
+ CR_In_Elbasan,
+ CR_In_Caucasian_Albanian,
+ CR_In_Vithkuqi,
+ CR_In_Todhri,
+ CR_In_Linear_A,
+ CR_In_Latin_Extended_F,
+ CR_In_Cypriot_Syllabary,
+ CR_In_Imperial_Aramaic,
+ CR_In_Palmyrene,
+ CR_In_Nabataean,
+ CR_In_Hatran,
+ CR_In_Phoenician,
+ CR_In_Lydian,
+ CR_In_Sidetic,
+ CR_In_Meroitic_Hieroglyphs,
+ CR_In_Meroitic_Cursive,
+ CR_In_Kharoshthi,
+ CR_In_Old_South_Arabian,
+ CR_In_Old_North_Arabian,
+ CR_In_Manichaean,
+ CR_In_Avestan,
+ CR_In_Inscriptional_Parthian,
+ CR_In_Inscriptional_Pahlavi,
+ CR_In_Psalter_Pahlavi,
+ CR_In_Old_Turkic,
+ CR_In_Old_Hungarian,
+ CR_In_Hanifi_Rohingya,
+ CR_In_Garay,
+ CR_In_Rumi_Numeral_Symbols,
+ CR_In_Yezidi,
+ CR_In_Arabic_Extended_C,
+ CR_In_Old_Sogdian,
+ CR_In_Sogdian,
+ CR_In_Old_Uyghur,
+ CR_In_Chorasmian,
+ CR_In_Elymaic,
+ CR_In_Brahmi,
+ CR_In_Kaithi,
+ CR_In_Sora_Sompeng,
+ CR_In_Chakma,
+ CR_In_Mahajani,
+ CR_In_Sharada,
+ CR_In_Sinhala_Archaic_Numbers,
+ CR_In_Khojki,
+ CR_In_Multani,
+ CR_In_Khudawadi,
+ CR_In_Grantha,
+ CR_In_Tulu_Tigalari,
+ CR_In_Newa,
+ CR_In_Tirhuta,
+ CR_In_Siddham,
+ CR_In_Modi,
+ CR_In_Mongolian_Supplement,
+ CR_In_Takri,
+ CR_In_Myanmar_Extended_C,
+ CR_In_Ahom,
+ CR_In_Dogra,
+ CR_In_Warang_Citi,
+ CR_In_Dives_Akuru,
+ CR_In_Nandinagari,
+ CR_In_Zanabazar_Square,
+ CR_In_Soyombo,
+ CR_In_Unified_Canadian_Aboriginal_Syllabics_Extended_A,
+ CR_In_Pau_Cin_Hau,
+ CR_In_Devanagari_Extended_A,
+ CR_In_Sharada_Supplement,
+ CR_In_Sunuwar,
+ CR_In_Bhaiksuki,
+ CR_In_Marchen,
+ CR_In_Masaram_Gondi,
+ CR_In_Gunjala_Gondi,
+ CR_In_Tolong_Siki,
+ CR_In_Makasar,
+ CR_In_Kawi,
+ CR_In_Lisu_Supplement,
+ CR_In_Tamil_Supplement,
+ CR_In_Cuneiform,
+ CR_In_Cuneiform_Numbers_and_Punctuation,
+ CR_In_Early_Dynastic_Cuneiform,
+ CR_In_Cypro_Minoan,
+ CR_In_Egyptian_Hieroglyphs,
+ CR_In_Egyptian_Hieroglyph_Format_Controls,
+ CR_In_Egyptian_Hieroglyphs_Extended_A,
+ CR_In_Anatolian_Hieroglyphs,
+ CR_In_Gurung_Khema,
+ CR_In_Bamum_Supplement,
+ CR_In_Mro,
+ CR_In_Tangsa,
+ CR_In_Bassa_Vah,
+ CR_In_Pahawh_Hmong,
+ CR_In_Kirat_Rai,
+ CR_In_Medefaidrin,
+ CR_In_Beria_Erfe,
+ CR_In_Miao,
+ CR_In_Ideographic_Symbols_and_Punctuation,
+ CR_In_Tangut,
+ CR_In_Tangut_Components,
+ CR_In_Khitan_Small_Script,
+ CR_In_Tangut_Supplement,
+ CR_In_Tangut_Components_Supplement,
+ CR_In_Kana_Extended_B,
+ CR_In_Kana_Supplement,
+ CR_In_Kana_Extended_A,
+ CR_In_Small_Kana_Extension,
+ CR_In_Nushu,
+ CR_In_Duployan,
+ CR_In_Shorthand_Format_Controls,
+ CR_In_Symbols_for_Legacy_Computing_Supplement,
+ CR_In_Miscellaneous_Symbols_Supplement,
+ CR_In_Znamenny_Musical_Notation,
+ CR_In_Byzantine_Musical_Symbols,
+ CR_In_Musical_Symbols,
+ CR_In_Ancient_Greek_Musical_Notation,
+ CR_In_Kaktovik_Numerals,
+ CR_In_Mayan_Numerals,
+ CR_In_Tai_Xuan_Jing_Symbols,
+ CR_In_Counting_Rod_Numerals,
+ CR_In_Mathematical_Alphanumeric_Symbols,
+ CR_In_Sutton_SignWriting,
+ CR_In_Latin_Extended_G,
+ CR_In_Glagolitic_Supplement,
+ CR_In_Cyrillic_Extended_D,
+ CR_In_Nyiakeng_Puachue_Hmong,
+ CR_In_Toto,
+ CR_In_Wancho,
+ CR_In_Nag_Mundari,
+ CR_In_Ol_Onal,
+ CR_In_Tai_Yo,
+ CR_In_Ethiopic_Extended_B,
+ CR_In_Mende_Kikakui,
+ CR_In_Adlam,
+ CR_In_Indic_Siyaq_Numbers,
+ CR_In_Ottoman_Siyaq_Numbers,
+ CR_In_Arabic_Mathematical_Alphabetic_Symbols,
+ CR_In_Mahjong_Tiles,
+ CR_In_Domino_Tiles,
+ CR_In_Playing_Cards,
+ CR_In_Enclosed_Alphanumeric_Supplement,
+ CR_In_Enclosed_Ideographic_Supplement,
+ CR_In_Miscellaneous_Symbols_and_Pictographs,
+ CR_In_Emoticons,
+ CR_In_Ornamental_Dingbats,
+ CR_In_Transport_and_Map_Symbols,
+ CR_In_Alchemical_Symbols,
+ CR_In_Geometric_Shapes_Extended,
+ CR_In_Supplemental_Arrows_C,
+ 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_Unified_Ideographs_Extension_I,
+ CR_In_CJK_Compatibility_Ideographs_Supplement,
+ CR_In_CJK_Unified_Ideographs_Extension_G,
+ CR_In_CJK_Unified_Ideographs_Extension_H,
+ CR_In_CJK_Unified_Ideographs_Extension_J,
+ CR_In_Tags,
+ CR_In_Variation_Selectors_Supplement,
+ CR_In_Supplementary_Private_Use_Area_A,
+ CR_In_Supplementary_Private_Use_Area_B,
+ CR_In_No_Block,
+#endif /* USE_UNICODE_PROPERTIES */
+};
+struct uniname2ctype_struct {
+ short name;
+ unsigned short ctype;
+};
+#define uniname2ctype_offset(str) offsetof(struct uniname2ctype_pool_t, uniname2ctype_pool_##str)
+
+static const struct uniname2ctype_struct *uniname2ctype_p(register const char *str, register size_t len);
+
+#ifndef USE_UNICODE_PROPERTIES
+#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 916
+#else /* USE_UNICODE_AGE_PROPERTIES */
+#define TOTAL_KEYWORDS 944
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+#define MIN_WORD_LENGTH 1
+#define MAX_WORD_LENGTH 45
+#define MIN_HASH_VALUE 10
+#define MAX_HASH_VALUE 6068
+/* maximum key range = 6059, duplicates = 0 */
+#endif /* USE_UNICODE_PROPERTIES */
+
+#ifdef __GNUC__
+__inline
+#else
+#ifdef __cplusplus
+inline
+#endif
+#endif
+static unsigned int
+uniname2ctype_hash (register const char *str, register size_t len)
+{
+#ifndef USE_UNICODE_PROPERTIES
+ static const unsigned char asso_values[] =
+#else /* USE_UNICODE_PROPERTIES */
+ static const unsigned short asso_values[] =
+#endif /* USE_UNICODE_PROPERTIES */
+ {
+#ifndef USE_UNICODE_PROPERTIES
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 21, 21, 21, 21, 21, 21, 3, 12, 5,
+ 4, 21, 21, 10, 21, 1, 21, 21, 11, 21,
+ 2, 1, 1, 21, 1, 7, 4, 6, 21, 1,
+ 4, 21, 21, 21, 21, 21, 21, 21
+#else /* USE_UNICODE_PROPERTIES */
+ 6069, 6069, 6069, 6069, 6069, 6069, 6069, 6069, 6069, 6069,
+ 6069, 6069, 6069, 6069, 6069, 6069, 6069, 6069, 6069, 6069,
+ 6069, 6069, 6069, 6069, 6069, 6069, 6069, 6069, 6069, 6069,
+ 6069, 6069, 6069, 6069, 6069, 6069, 6069, 6069, 6069, 6069,
+#ifndef USE_UNICODE_AGE_PROPERTIES
+ 6069, 6069, 6069, 6069, 6069, 6069, 6069, 6069, 6069, 6069,
+ 6069, 6069, 6069, 6069, 6069, 6069, 6069, 6069, 6069, 6069,
+#else /* USE_UNICODE_AGE_PROPERTIES */
+ 6069, 6069, 6069, 6069, 6069, 6069, 8, 6069, 2, 1,
+ 4, 31, 11, 20, 27, 15, 23, 17, 6069, 6069,
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ 6069, 1, 6069, 6069, 6069, 6069, 6069, 6069, 6069, 6069,
+ 6069, 6069, 6069, 6069, 6069, 6069, 6069, 6069, 6069, 6069,
+ 6069, 6069, 6069, 6069, 6069, 6069, 6069, 6069, 6069, 6069,
+ 6069, 6069, 6069, 6069, 6069, 6069, 6069, 22, 28, 165,
+ 250, 131, 1160, 1288, 949, 4, 12, 1918, 452, 7,
+ 8, 1, 756, 2041, 623, 20, 68, 1025, 1509, 246,
+ 1475, 944, 814, 2, 6069, 6069, 6069, 6069, 6069
+#endif /* USE_UNICODE_PROPERTIES */
+ };
+#ifndef USE_UNICODE_PROPERTIES
+ return len + asso_values[(unsigned char)str[2]] + asso_values[(unsigned char)str[0]];
+#else /* USE_UNICODE_PROPERTIES */
+ register unsigned int hval = (unsigned int)len;
+
+ switch (hval)
+ {
+ default:
+ hval += asso_values[(unsigned char)str[15]];
+ /*FALLTHROUGH*/
+ case 15:
+ case 14:
+ case 13:
+ case 12:
+ hval += asso_values[(unsigned char)str[11]];
+ /*FALLTHROUGH*/
+ case 11:
+ case 10:
+ case 9:
+ case 8:
+ case 7:
+ case 6:
+ hval += asso_values[(unsigned char)str[5]];
+ /*FALLTHROUGH*/
+ case 5:
+ hval += asso_values[(unsigned char)str[4]];
+ /*FALLTHROUGH*/
+ case 4:
+ case 3:
+ hval += asso_values[(unsigned char)str[2]];
+ /*FALLTHROUGH*/
+ case 2:
+ hval += asso_values[(unsigned char)str[1]+1];
+ /*FALLTHROUGH*/
+ case 1:
+ hval += asso_values[(unsigned char)str[0]+1];
+ break;
+ }
+ return hval + asso_values[(unsigned char)str[len - 1]];
+#endif /* USE_UNICODE_PROPERTIES */
+}
+
+struct uniname2ctype_pool_t
+ {
+#ifndef USE_UNICODE_PROPERTIES
+ char uniname2ctype_pool_str6[sizeof("word")];
+ char uniname2ctype_pool_str7[sizeof("print")];
+ char uniname2ctype_pool_str8[sizeof("punct")];
+ char uniname2ctype_pool_str9[sizeof("alpha")];
+ char uniname2ctype_pool_str10[sizeof("alnum")];
+ char uniname2ctype_pool_str11[sizeof("xdigit")];
+ char uniname2ctype_pool_str12[sizeof("upper")];
+ char uniname2ctype_pool_str13[sizeof("ascii")];
+ char uniname2ctype_pool_str14[sizeof("cntrl")];
+ char uniname2ctype_pool_str15[sizeof("space")];
+ char uniname2ctype_pool_str16[sizeof("xposixpunct")];
+ char uniname2ctype_pool_str17[sizeof("lower")];
+ char uniname2ctype_pool_str18[sizeof("graph")];
+ char uniname2ctype_pool_str19[sizeof("digit")];
+ char uniname2ctype_pool_str20[sizeof("blank")];
+#else /* USE_UNICODE_PROPERTIES */
+ char uniname2ctype_pool_str10[sizeof("n")];
+ char uniname2ctype_pool_str16[sizeof("m")];
+ char uniname2ctype_pool_str19[sizeof("mn")];
+ char uniname2ctype_pool_str24[sizeof("lm")];
+ char uniname2ctype_pool_str27[sizeof("inmro")];
+ char uniname2ctype_pool_str28[sizeof("innko")];
+ char uniname2ctype_pool_str33[sizeof("mro")];
+ char uniname2ctype_pool_str34[sizeof("mroo")];
+ char uniname2ctype_pool_str38[sizeof("ri")];
+ char uniname2ctype_pool_str40[sizeof("lao")];
+ char uniname2ctype_pool_str41[sizeof("laoo")];
+ char uniname2ctype_pool_str44[sizeof("ahom")];
+ char uniname2ctype_pool_str45[sizeof("hano")];
+ char uniname2ctype_pool_str47[sizeof("miao")];
+ char uniname2ctype_pool_str48[sizeof("hani")];
+ char uniname2ctype_pool_str50[sizeof("inmiao")];
+ char uniname2ctype_pool_str51[sizeof("han")];
+ char uniname2ctype_pool_str52[sizeof("mani")];
+ char uniname2ctype_pool_str53[sizeof("lina")];
+ char uniname2ctype_pool_str56[sizeof("inahom")];
+ char uniname2ctype_pool_str57[sizeof("hanunoo")];
+ char uniname2ctype_pool_str58[sizeof("limb")];
+ char uniname2ctype_pool_str59[sizeof("linb")];
+ char uniname2ctype_pool_str60[sizeof("inmanichaean")];
+ char uniname2ctype_pool_str62[sizeof("alnum")];
+ char uniname2ctype_pool_str63[sizeof("armi")];
+ char uniname2ctype_pool_str64[sizeof("nandinagari")];
+ char uniname2ctype_pool_str67[sizeof("armn")];
+ char uniname2ctype_pool_str69[sizeof("lana")];
+ char uniname2ctype_pool_str70[sizeof("zanb")];
+ char uniname2ctype_pool_str74[sizeof("inosmanya")];
+ char uniname2ctype_pool_str81[sizeof("insamaritan")];
+ char uniname2ctype_pool_str82[sizeof("inbhaiksuki")];
+ char uniname2ctype_pool_str83[sizeof("armenian")];
+ char uniname2ctype_pool_str85[sizeof("sm")];
+ char uniname2ctype_pool_str88[sizeof("inmasaramgondi")];
+ char uniname2ctype_pool_str89[sizeof("s")];
+ char uniname2ctype_pool_str90[sizeof("innabataean")];
+ char uniname2ctype_pool_str92[sizeof("zs")];
+ char uniname2ctype_pool_str93[sizeof("inbasiclatin")];
+ char uniname2ctype_pool_str96[sizeof("innumberforms")];
+ char uniname2ctype_pool_str102[sizeof("arab")];
+ char uniname2ctype_pool_str107[sizeof("inmusicalsymbols")];
+ char uniname2ctype_pool_str115[sizeof("latn")];
+ char uniname2ctype_pool_str117[sizeof("inthai")];
+ char uniname2ctype_pool_str124[sizeof("latin")];
+ char uniname2ctype_pool_str135[sizeof("shavian")];
+ char uniname2ctype_pool_str141[sizeof("initialpunctuation")];
+ char uniname2ctype_pool_str144[sizeof("hatran")];
+ char uniname2ctype_pool_str149[sizeof("di")];
+ char uniname2ctype_pool_str155[sizeof("inthaana")];
+ char uniname2ctype_pool_str157[sizeof("intoto")];
+ char uniname2ctype_pool_str164[sizeof("nabataean")];
+ char uniname2ctype_pool_str169[sizeof("intaitham")];
+ char uniname2ctype_pool_str175[sizeof("inarabicpresentationformsa")];
+ char uniname2ctype_pool_str180[sizeof("inbraillepatterns")];
+ char uniname2ctype_pool_str181[sizeof("inarabicpresentationformsb")];
+ char uniname2ctype_pool_str186[sizeof("ids")];
+ char uniname2ctype_pool_str190[sizeof("dia")];
+ char uniname2ctype_pool_str191[sizeof("inarmenian")];
+ char uniname2ctype_pool_str195[sizeof("idsb")];
+ char uniname2ctype_pool_str199[sizeof("intransportandmapsymbols")];
+ char uniname2ctype_pool_str202[sizeof("inideographicsymbolsandpunctuation")];
+ char uniname2ctype_pool_str203[sizeof("inavestan")];
+ char uniname2ctype_pool_str209[sizeof("inipaextensions")];
+ char uniname2ctype_pool_str211[sizeof("inelbasan")];
+ char uniname2ctype_pool_str213[sizeof("inopticalcharacterrecognition")];
+ char uniname2ctype_pool_str215[sizeof("brai")];
+ char uniname2ctype_pool_str219[sizeof("bamum")];
+ char uniname2ctype_pool_str220[sizeof("incham")];
+ char uniname2ctype_pool_str227[sizeof("inideographicdescriptioncharacters")];
+ char uniname2ctype_pool_str228[sizeof("brahmi")];
+ char uniname2ctype_pool_str235[sizeof("idst")];
+ char uniname2ctype_pool_str237[sizeof("bass")];
+ char uniname2ctype_pool_str242[sizeof("mandaic")];
+ char uniname2ctype_pool_str244[sizeof("inemoticons")];
+ char uniname2ctype_pool_str247[sizeof("incommonindicnumberforms")];
+ char uniname2ctype_pool_str257[sizeof("intibetan")];
+ char uniname2ctype_pool_str258[sizeof("inarabic")];
+ char uniname2ctype_pool_str260[sizeof("nbat")];
+ char uniname2ctype_pool_str261[sizeof("cn")];
+ char uniname2ctype_pool_str267[sizeof("inancientsymbols")];
+ char uniname2ctype_pool_str268[sizeof("ci")];
+ char uniname2ctype_pool_str274[sizeof("ascii")];
+ char uniname2ctype_pool_str275[sizeof("mcm")];
+ char uniname2ctype_pool_str279[sizeof("ideo")];
+ char uniname2ctype_pool_str284[sizeof("inmodi")];
+ char uniname2ctype_pool_str285[sizeof("vai")];
+ char uniname2ctype_pool_str286[sizeof("vaii")];
+ char uniname2ctype_pool_str287[sizeof("cham")];
+ char uniname2ctype_pool_str289[sizeof("inmyanmarextendeda")];
+ char uniname2ctype_pool_str291[sizeof("nand")];
+ char uniname2ctype_pool_str295[sizeof("inmyanmarextendedb")];
+ char uniname2ctype_pool_str298[sizeof("mand")];
+ char uniname2ctype_pool_str310[sizeof("cans")];
+ char uniname2ctype_pool_str312[sizeof("inoldsogdian")];
+ char uniname2ctype_pool_str315[sizeof("chorasmian")];
+ char uniname2ctype_pool_str317[sizeof("innewa")];
+ char uniname2ctype_pool_str333[sizeof("chakma")];
+ char uniname2ctype_pool_str335[sizeof("incuneiform")];
+ char uniname2ctype_pool_str336[sizeof("vs")];
+ char uniname2ctype_pool_str340[sizeof("cs")];
+ char uniname2ctype_pool_str342[sizeof("sind")];
+ char uniname2ctype_pool_str344[sizeof("shaw")];
+ char uniname2ctype_pool_str359[sizeof("inspecials")];
+ char uniname2ctype_pool_str364[sizeof("inchesssymbols")];
+ char uniname2ctype_pool_str366[sizeof("avst")];
+ char uniname2ctype_pool_str373[sizeof("inblockelements")];
+ char uniname2ctype_pool_str384[sizeof("nd")];
+ char uniname2ctype_pool_str395[sizeof("sharada")];
+ char uniname2ctype_pool_str398[sizeof("inmiscellaneoussymbols")];
+ char uniname2ctype_pool_str400[sizeof("inmiscellaneousmathematicalsymbolsa")];
+ char uniname2ctype_pool_str402[sizeof("sidt")];
+ char uniname2ctype_pool_str406[sizeof("inmiscellaneousmathematicalsymbolsb")];
+ char uniname2ctype_pool_str407[sizeof("inmiscellaneoussymbolsandarrows")];
+ char uniname2ctype_pool_str410[sizeof("arabic")];
+ char uniname2ctype_pool_str412[sizeof("inmiscellaneoussymbolsandpictographs")];
+ char uniname2ctype_pool_str416[sizeof("c")];
+ char uniname2ctype_pool_str424[sizeof("lc")];
+ char uniname2ctype_pool_str425[sizeof("mc")];
+ char uniname2ctype_pool_str426[sizeof("inmedefaidrin")];
+ char uniname2ctype_pool_str432[sizeof("inmyanmarextendedc")];
+ char uniname2ctype_pool_str433[sizeof("insundanese")];
+ char uniname2ctype_pool_str438[sizeof("indominotiles")];
+ char uniname2ctype_pool_str440[sizeof("insymbolsandpictographsextendeda")];
+ char uniname2ctype_pool_str441[sizeof("inwancho")];
+ char uniname2ctype_pool_str444[sizeof("inolditalic")];
+ char uniname2ctype_pool_str447[sizeof("inmodifiertoneletters")];
+ char uniname2ctype_pool_str448[sizeof("incb=consonant")];
+ char uniname2ctype_pool_str451[sizeof("sd")];
+ char uniname2ctype_pool_str452[sizeof("inmandaic")];
+ char uniname2ctype_pool_str456[sizeof("inmiscellaneoussymbolssupplement")];
+ char uniname2ctype_pool_str458[sizeof("nko")];
+ char uniname2ctype_pool_str459[sizeof("nkoo")];
+ char uniname2ctype_pool_str460[sizeof("l")];
+ char uniname2ctype_pool_str461[sizeof("inmeeteimayekextensions")];
+ char uniname2ctype_pool_str462[sizeof("nl")];
+ char uniname2ctype_pool_str463[sizeof("zl")];
+ char uniname2ctype_pool_str468[sizeof("ll")];
+ char uniname2ctype_pool_str472[sizeof("inlao")];
+ char uniname2ctype_pool_str473[sizeof("khoj")];
+ char uniname2ctype_pool_str476[sizeof("idc")];
+ char uniname2ctype_pool_str477[sizeof("innewtailue")];
+ char uniname2ctype_pool_str483[sizeof("inolonal")];
+ char uniname2ctype_pool_str485[sizeof("sc")];
+ char uniname2ctype_pool_str491[sizeof("indeseret")];
+ char uniname2ctype_pool_str496[sizeof("incuneiformnumbersandpunctuation")];
+ char uniname2ctype_pool_str502[sizeof("krai")];
+ char uniname2ctype_pool_str505[sizeof("inarabicextendeda")];
+ char uniname2ctype_pool_str508[sizeof("inoldturkic")];
+ char uniname2ctype_pool_str510[sizeof("avestan")];
+ char uniname2ctype_pool_str511[sizeof("inarabicextendedb")];
+ char uniname2ctype_pool_str512[sizeof("inmalayalam")];
+ char uniname2ctype_pool_str513[sizeof("kharoshthi")];
+ char uniname2ctype_pool_str514[sizeof("kana")];
+ char uniname2ctype_pool_str523[sizeof("inadlam")];
+ char uniname2ctype_pool_str525[sizeof("idcontinue")];
+ char uniname2ctype_pool_str549[sizeof("insiddham")];
+ char uniname2ctype_pool_str551[sizeof("intamil")];
+ char uniname2ctype_pool_str553[sizeof("inmultani")];
+ char uniname2ctype_pool_str554[sizeof("intolongsiki")];
+ char uniname2ctype_pool_str556[sizeof("kits")];
+ char uniname2ctype_pool_str571[sizeof("incb=extend")];
+ char uniname2ctype_pool_str574[sizeof("sidetic")];
+ char uniname2ctype_pool_str584[sizeof("sidd")];
+ char uniname2ctype_pool_str587[sizeof("incontrolpictures")];
+ char uniname2ctype_pool_str588[sizeof("insidetic")];
+ char uniname2ctype_pool_str591[sizeof("sinhala")];
+ char uniname2ctype_pool_str605[sizeof("inlatinextendeda")];
+ char uniname2ctype_pool_str617[sizeof("inlatinextendedb")];
+ char uniname2ctype_pool_str622[sizeof("adlm")];
+ char uniname2ctype_pool_str630[sizeof("adlam")];
+ char uniname2ctype_pool_str635[sizeof("inlineara")];
+ char uniname2ctype_pool_str637[sizeof("intamilsupplement")];
+ char uniname2ctype_pool_str638[sizeof("inbalinese")];
+ char uniname2ctype_pool_str645[sizeof("inspacingmodifierletters")];
+ char uniname2ctype_pool_str648[sizeof("inarabicextendedc")];
+ char uniname2ctype_pool_str650[sizeof("inlycian")];
+ char uniname2ctype_pool_str653[sizeof("bali")];
+ char uniname2ctype_pool_str665[sizeof("hira")];
+ char uniname2ctype_pool_str667[sizeof("cc")];
+ char uniname2ctype_pool_str674[sizeof("insmallkanaextension")];
+ char uniname2ctype_pool_str675[sizeof("intaile")];
+ char uniname2ctype_pool_str681[sizeof("qaai")];
+ char uniname2ctype_pool_str682[sizeof("inmyanmar")];
+ char uniname2ctype_pool_str684[sizeof("narb")];
+ char uniname2ctype_pool_str687[sizeof("inarrows")];
+ char uniname2ctype_pool_str701[sizeof("lineara")];
+ char uniname2ctype_pool_str707[sizeof("linearb")];
+ char uniname2ctype_pool_str709[sizeof("insharada")];
+ char uniname2ctype_pool_str716[sizeof("inruminumeralsymbols")];
+ char uniname2ctype_pool_str721[sizeof("masaramgondi")];
+ char uniname2ctype_pool_str727[sizeof("hatr")];
+ char uniname2ctype_pool_str729[sizeof("knda")];
+ char uniname2ctype_pool_str730[sizeof("samr")];
+ char uniname2ctype_pool_str734[sizeof("kawi")];
+ char uniname2ctype_pool_str735[sizeof("inlydian")];
+ char uniname2ctype_pool_str747[sizeof("samaritan")];
+ char uniname2ctype_pool_str751[sizeof("sarb")];
+ char uniname2ctype_pool_str760[sizeof("no")];
+ char uniname2ctype_pool_str762[sizeof("bidic")];
+ char uniname2ctype_pool_str766[sizeof("lo")];
+ char uniname2ctype_pool_str780[sizeof("hmnp")];
+ char uniname2ctype_pool_str784[sizeof("onao")];
+ char uniname2ctype_pool_str788[sizeof("inlowsurrogates")];
+ char uniname2ctype_pool_str789[sizeof("kannada")];
+ char uniname2ctype_pool_str795[sizeof("inlinearbideograms")];
+ char uniname2ctype_pool_str799[sizeof("inletterlikesymbols")];
+ char uniname2ctype_pool_str803[sizeof("cased")];
+ char uniname2ctype_pool_str809[sizeof("inbopomofo")];
+ char uniname2ctype_pool_str810[sizeof("inberiaerfe")];
+ char uniname2ctype_pool_str815[sizeof("lineseparator")];
+ char uniname2ctype_pool_str817[sizeof("z")];
+ char uniname2ctype_pool_str818[sizeof("insymbolsforlegacycomputingsupplement")];
+ char uniname2ctype_pool_str820[sizeof("inrunic")];
+ char uniname2ctype_pool_str821[sizeof("incarian")];
+ char uniname2ctype_pool_str823[sizeof("inlatinextendede")];
+ char uniname2ctype_pool_str825[sizeof("inmarchen")];
+ char uniname2ctype_pool_str827[sizeof("so")];
+ char uniname2ctype_pool_str828[sizeof("marc")];
+ char uniname2ctype_pool_str829[sizeof("oriya")];
+ char uniname2ctype_pool_str830[sizeof("inchorasmian")];
+ char uniname2ctype_pool_str832[sizeof("yi")];
+ char uniname2ctype_pool_str833[sizeof("insyriac")];
+ char uniname2ctype_pool_str838[sizeof("yiii")];
+ char uniname2ctype_pool_str840[sizeof("alpha")];
+ char uniname2ctype_pool_str842[sizeof("qaac")];
+ char uniname2ctype_pool_str852[sizeof("insundanesesupplement")];
+ char uniname2ctype_pool_str857[sizeof("osma")];
+ char uniname2ctype_pool_str880[sizeof("inmiscellaneoustechnical")];
+ char uniname2ctype_pool_str883[sizeof("idstart")];
+ char uniname2ctype_pool_str890[sizeof("inenclosedcjklettersandmonths")];
+ char uniname2ctype_pool_str891[sizeof("inlatinextendedc")];
+ char uniname2ctype_pool_str894[sizeof("dsrt")];
+ char uniname2ctype_pool_str898[sizeof("odi")];
+ char uniname2ctype_pool_str901[sizeof("chrs")];
+ char uniname2ctype_pool_str909[sizeof("cari")];
+ char uniname2ctype_pool_str919[sizeof("innandinagari")];
+ char uniname2ctype_pool_str923[sizeof("balinese")];
+ char uniname2ctype_pool_str924[sizeof("inwarangciti")];
+ char uniname2ctype_pool_str929[sizeof("inphoenician")];
+ char uniname2ctype_pool_str940[sizeof("kali")];
+ char uniname2ctype_pool_str942[sizeof("inoldnortharabian")];
+ char uniname2ctype_pool_str944[sizeof("radical")];
+ char uniname2ctype_pool_str945[sizeof("carian")];
+ char uniname2ctype_pool_str947[sizeof("idsbinaryoperator")];
+ char uniname2ctype_pool_str949[sizeof("shrd")];
+ char uniname2ctype_pool_str954[sizeof("inoldsoutharabian")];
+ char uniname2ctype_pool_str966[sizeof("diacritic")];
+ char uniname2ctype_pool_str970[sizeof("mlym")];
+ char uniname2ctype_pool_str975[sizeof("zinh")];
+ char uniname2ctype_pool_str978[sizeof("inphaistosdisc")];
+ char uniname2ctype_pool_str980[sizeof("incyrillic")];
+ char uniname2ctype_pool_str985[sizeof("ininscriptionalpahlavi")];
+ char uniname2ctype_pool_str988[sizeof("insoyombo")];
+ char uniname2ctype_pool_str990[sizeof("ininscriptionalparthian")];
+ char uniname2ctype_pool_str991[sizeof("inoriya")];
+ char uniname2ctype_pool_str994[sizeof("lyci")];
+ char uniname2ctype_pool_str999[sizeof("inogham")];
+ char uniname2ctype_pool_str1001[sizeof("mahj")];
+ char uniname2ctype_pool_str1003[sizeof("gran")];
+ char uniname2ctype_pool_str1005[sizeof("inmahajani")];
+ char uniname2ctype_pool_str1009[sizeof("co")];
+ char uniname2ctype_pool_str1012[sizeof("cher")];
+ char uniname2ctype_pool_str1016[sizeof("alphabetic")];
+ char uniname2ctype_pool_str1021[sizeof("insinhala")];
+ char uniname2ctype_pool_str1022[sizeof("modi")];
+ char uniname2ctype_pool_str1024[sizeof("inbrahmi")];
+ char uniname2ctype_pool_str1028[sizeof("loe")];
+ char uniname2ctype_pool_str1030[sizeof("lycian")];
+ char uniname2ctype_pool_str1031[sizeof("mahajani")];
+ char uniname2ctype_pool_str1036[sizeof("common")];
+ char uniname2ctype_pool_str1037[sizeof("intaiyo")];
+ char uniname2ctype_pool_str1038[sizeof("inhanifirohingya")];
+ char uniname2ctype_pool_str1040[sizeof("inbassavah")];
+ char uniname2ctype_pool_str1041[sizeof("sinh")];
+ char uniname2ctype_pool_str1042[sizeof("oids")];
+ char uniname2ctype_pool_str1044[sizeof("inlatinextendedadditional")];
+ char uniname2ctype_pool_str1045[sizeof("inyijinghexagramsymbols")];
+ char uniname2ctype_pool_str1048[sizeof("inoldpersian")];
+ char uniname2ctype_pool_str1056[sizeof("bidicontrol")];
+ char uniname2ctype_pool_str1057[sizeof("math")];
+ char uniname2ctype_pool_str1058[sizeof("inarabicsupplement")];
+ char uniname2ctype_pool_str1059[sizeof("thai")];
+ char uniname2ctype_pool_str1061[sizeof("inlatinextendedd")];
+ char uniname2ctype_pool_str1064[sizeof("taiyo")];
+ char uniname2ctype_pool_str1068[sizeof("lisu")];
+ char uniname2ctype_pool_str1072[sizeof("tnsa")];
+ char uniname2ctype_pool_str1073[sizeof("incherokee")];
+ char uniname2ctype_pool_str1077[sizeof("thaa")];
+ char uniname2ctype_pool_str1079[sizeof("lydi")];
+ char uniname2ctype_pool_str1087[sizeof("inbamum")];
+ char uniname2ctype_pool_str1090[sizeof("khmr")];
+ char uniname2ctype_pool_str1094[sizeof("inbyzantinemusicalsymbols")];
+ char uniname2ctype_pool_str1102[sizeof("lt")];
+ char uniname2ctype_pool_str1105[sizeof("khar")];
+ char uniname2ctype_pool_str1109[sizeof("thaana")];
+ char uniname2ctype_pool_str1113[sizeof("osage")];
+ char uniname2ctype_pool_str1115[sizeof("lydian")];
+ char uniname2ctype_pool_str1117[sizeof("inanatolianhieroglyphs")];
+#ifdef USE_UNICODE_AGE_PROPERTIES
+ char uniname2ctype_pool_str1120[sizeof("age=11.0")];
+ char uniname2ctype_pool_str1121[sizeof("age=10.0")];
+ char uniname2ctype_pool_str1122[sizeof("age=12.1")];
+ char uniname2ctype_pool_str1123[sizeof("age=12.0")];
+ char uniname2ctype_pool_str1125[sizeof("age=1.1")];
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ char uniname2ctype_pool_str1126[sizeof("insylotinagri")];
+ char uniname2ctype_pool_str1127[sizeof("anatolianhieroglyphs")];
+#ifdef USE_UNICODE_AGE_PROPERTIES
+ char uniname2ctype_pool_str1128[sizeof("age=2.1")];
+ char uniname2ctype_pool_str1129[sizeof("age=2.0")];
+ char uniname2ctype_pool_str1130[sizeof("age=14.0")];
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ char uniname2ctype_pool_str1131[sizeof("tangsa")];
+ char uniname2ctype_pool_str1132[sizeof("dash")];
+ char uniname2ctype_pool_str1133[sizeof("incombiningdiacriticalmarks")];
+#ifdef USE_UNICODE_AGE_PROPERTIES
+ char uniname2ctype_pool_str1134[sizeof("age=17.0")];
+ char uniname2ctype_pool_str1135[sizeof("age=4.1")];
+ char uniname2ctype_pool_str1136[sizeof("age=4.0")];
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ char uniname2ctype_pool_str1137[sizeof("tibt")];
+#ifdef USE_UNICODE_AGE_PROPERTIES
+ char uniname2ctype_pool_str1138[sizeof("age=15.1")];
+ char uniname2ctype_pool_str1139[sizeof("age=15.0")];
+ char uniname2ctype_pool_str1140[sizeof("age=7.0")];
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ char uniname2ctype_pool_str1141[sizeof("inolchiki")];
+#ifdef USE_UNICODE_AGE_PROPERTIES
+ char uniname2ctype_pool_str1142[sizeof("age=9.0")];
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ char uniname2ctype_pool_str1143[sizeof("incombiningdiacriticalmarksforsymbols")];
+#ifdef USE_UNICODE_AGE_PROPERTIES
+ char uniname2ctype_pool_str1144[sizeof("age=5.1")];
+ char uniname2ctype_pool_str1145[sizeof("age=5.0")];
+ char uniname2ctype_pool_str1146[sizeof("age=16.0")];
+ char uniname2ctype_pool_str1147[sizeof("age=5.2")];
+ char uniname2ctype_pool_str1148[sizeof("age=8.0")];
+ char uniname2ctype_pool_str1150[sizeof("age=13.0")];
+ char uniname2ctype_pool_str1151[sizeof("age=6.1")];
+ char uniname2ctype_pool_str1152[sizeof("age=6.0")];
+ char uniname2ctype_pool_str1154[sizeof("age=6.2")];
+ char uniname2ctype_pool_str1155[sizeof("age=3.1")];
+ char uniname2ctype_pool_str1156[sizeof("age=3.0")];
+ char uniname2ctype_pool_str1158[sizeof("age=3.2")];
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ char uniname2ctype_pool_str1159[sizeof("inarabicmathematicalalphabeticsymbols")];
+ char uniname2ctype_pool_str1160[sizeof("brah")];
+ char uniname2ctype_pool_str1170[sizeof("tibetan")];
+ char uniname2ctype_pool_str1172[sizeof("mtei")];
+ char uniname2ctype_pool_str1175[sizeof("incoptic")];
+ char uniname2ctype_pool_str1176[sizeof("manichaean")];
+#ifdef USE_UNICODE_AGE_PROPERTIES
+ char uniname2ctype_pool_str1181[sizeof("age=6.3")];
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ char uniname2ctype_pool_str1182[sizeof("emoji")];
+ char uniname2ctype_pool_str1187[sizeof("oidc")];
+ char uniname2ctype_pool_str1191[sizeof("incombiningdiacriticalmarkssupplement")];
+ char uniname2ctype_pool_str1192[sizeof("idsu")];
+ char uniname2ctype_pool_str1195[sizeof("saurashtra")];
+ char uniname2ctype_pool_str1196[sizeof("inoldpermic")];
+ char uniname2ctype_pool_str1199[sizeof("closepunctuation")];
+ char uniname2ctype_pool_str1209[sizeof("incombininghalfmarks")];
+ char uniname2ctype_pool_str1214[sizeof("incopticepactnumbers")];
+ char uniname2ctype_pool_str1221[sizeof("elba")];
+ char uniname2ctype_pool_str1225[sizeof("xdigit")];
+ char uniname2ctype_pool_str1228[sizeof("cntrl")];
+ char uniname2ctype_pool_str1229[sizeof("bamu")];
+ char uniname2ctype_pool_str1230[sizeof("xids")];
+ char uniname2ctype_pool_str1239[sizeof("inoldhungarian")];
+ char uniname2ctype_pool_str1241[sizeof("grext")];
+ char uniname2ctype_pool_str1242[sizeof("mongolian")];
+ char uniname2ctype_pool_str1243[sizeof("sterm")];
+ char uniname2ctype_pool_str1249[sizeof("braille")];
+ char uniname2ctype_pool_str1251[sizeof("inbuhid")];
+ char uniname2ctype_pool_str1252[sizeof("elbasan")];
+ char uniname2ctype_pool_str1259[sizeof("zanabazarsquare")];
+ char uniname2ctype_pool_str1260[sizeof("incountingrodnumerals")];
+ char uniname2ctype_pool_str1264[sizeof("inenclosedalphanumerics")];
+ char uniname2ctype_pool_str1265[sizeof("incb=linker")];
+ char uniname2ctype_pool_str1267[sizeof("taiviet")];
+ char uniname2ctype_pool_str1269[sizeof("inelymaic")];
+ char uniname2ctype_pool_str1272[sizeof("inethiopic")];
+ char uniname2ctype_pool_str1275[sizeof("sgnw")];
+ char uniname2ctype_pool_str1277[sizeof("olditalic")];
+ char uniname2ctype_pool_str1279[sizeof("vith")];
+ char uniname2ctype_pool_str1285[sizeof("grbase")];
+ char uniname2ctype_pool_str1286[sizeof("hluw")];
+ char uniname2ctype_pool_str1292[sizeof("intodhri")];
+ char uniname2ctype_pool_str1299[sizeof("asciihexdigit")];
+ char uniname2ctype_pool_str1301[sizeof("me")];
+ char uniname2ctype_pool_str1312[sizeof("hmng")];
+ char uniname2ctype_pool_str1315[sizeof("siddham")];
+ char uniname2ctype_pool_str1321[sizeof("inenclosedalphanumericsupplement")];
+ char uniname2ctype_pool_str1324[sizeof("taile")];
+ char uniname2ctype_pool_str1328[sizeof("nagm")];
+ char uniname2ctype_pool_str1332[sizeof("hang")];
+ char uniname2ctype_pool_str1334[sizeof("inscriptionalparthian")];
+ char uniname2ctype_pool_str1335[sizeof("inmongolian")];
+ char uniname2ctype_pool_str1336[sizeof("innagmundari")];
+ char uniname2ctype_pool_str1339[sizeof("sylo")];
+ char uniname2ctype_pool_str1347[sizeof("ingunjalagondi")];
+ char uniname2ctype_pool_str1349[sizeof("ingujarati")];
+ char uniname2ctype_pool_str1350[sizeof("inbengali")];
+ char uniname2ctype_pool_str1351[sizeof("khitansmallscript")];
+ char uniname2ctype_pool_str1357[sizeof("xidcontinue")];
+ char uniname2ctype_pool_str1362[sizeof("ingrantha")];
+ char uniname2ctype_pool_str1363[sizeof("insinhalaarchaicnumbers")];
+ char uniname2ctype_pool_str1368[sizeof("connectorpunctuation")];
+ char uniname2ctype_pool_str1370[sizeof("inpalmyrene")];
+ char uniname2ctype_pool_str1371[sizeof("incombiningdiacriticalmarksextended")];
+ char uniname2ctype_pool_str1372[sizeof("xidstart")];
+ char uniname2ctype_pool_str1375[sizeof("xidc")];
+ char uniname2ctype_pool_str1397[sizeof("inancientgreekmusicalnotation")];
+ char uniname2ctype_pool_str1401[sizeof("inancientgreeknumbers")];
+ char uniname2ctype_pool_str1407[sizeof("intangsa")];
+ char uniname2ctype_pool_str1415[sizeof("intags")];
+ char uniname2ctype_pool_str1416[sizeof("inlepcha")];
+ char uniname2ctype_pool_str1420[sizeof("caucasianalbanian")];
+ char uniname2ctype_pool_str1421[sizeof("sylotinagri")];
+ char uniname2ctype_pool_str1423[sizeof("emod")];
+ char uniname2ctype_pool_str1425[sizeof("incaucasianalbanian")];
+ char uniname2ctype_pool_str1429[sizeof("intagbanwa")];
+ char uniname2ctype_pool_str1430[sizeof("mend")];
+ char uniname2ctype_pool_str1433[sizeof("newa")];
+ char uniname2ctype_pool_str1435[sizeof("inearlydynasticcuneiform")];
+ char uniname2ctype_pool_str1447[sizeof("kaithi")];
+ char uniname2ctype_pool_str1453[sizeof("intangut")];
+ char uniname2ctype_pool_str1456[sizeof("mymr")];
+ char uniname2ctype_pool_str1462[sizeof("inosage")];
+ char uniname2ctype_pool_str1467[sizeof("inmahjongtiles")];
+ char uniname2ctype_pool_str1470[sizeof("malayalam")];
+ char uniname2ctype_pool_str1473[sizeof("sora")];
+ char uniname2ctype_pool_str1474[sizeof("inbuginese")];
+ char uniname2ctype_pool_str1479[sizeof("emojimodifierbase")];
+ char uniname2ctype_pool_str1489[sizeof("induployan")];
+ char uniname2ctype_pool_str1497[sizeof("ingeometricshapes")];
+ char uniname2ctype_pool_str1498[sizeof("ingeneralpunctuation")];
+ char uniname2ctype_pool_str1503[sizeof("myanmar")];
+ char uniname2ctype_pool_str1510[sizeof("inlatin1supplement")];
+ char uniname2ctype_pool_str1515[sizeof("ital")];
+ char uniname2ctype_pool_str1516[sizeof("taml")];
+ char uniname2ctype_pool_str1517[sizeof("inaegeannumbers")];
+ char uniname2ctype_pool_str1528[sizeof("insharadasupplement")];
+ char uniname2ctype_pool_str1530[sizeof("mathsymbol")];
+ char uniname2ctype_pool_str1532[sizeof("inlimbu")];
+ char uniname2ctype_pool_str1535[sizeof("invai")];
+ char uniname2ctype_pool_str1551[sizeof("emojicomponent")];
+ char uniname2ctype_pool_str1552[sizeof("insuttonsignwriting")];
+ char uniname2ctype_pool_str1572[sizeof("digit")];
+ char uniname2ctype_pool_str1573[sizeof("newtailue")];
+ char uniname2ctype_pool_str1581[sizeof("inshavian")];
+ char uniname2ctype_pool_str1588[sizeof("insogdian")];
+ char uniname2ctype_pool_str1589[sizeof("indingbats")];
+ char uniname2ctype_pool_str1590[sizeof("imperialaramaic")];
+ char uniname2ctype_pool_str1598[sizeof("intulutigalari")];
+ char uniname2ctype_pool_str1600[sizeof("incyprominoan")];
+ char uniname2ctype_pool_str1606[sizeof("glagolitic")];
+ char uniname2ctype_pool_str1614[sizeof("ebase")];
+ char uniname2ctype_pool_str1615[sizeof("intaixuanjingsymbols")];
+ char uniname2ctype_pool_str1618[sizeof("inbamumsupplement")];
+ char uniname2ctype_pool_str1626[sizeof("gara")];
+ char uniname2ctype_pool_str1633[sizeof("insyriacsupplement")];
+ char uniname2ctype_pool_str1634[sizeof("casedletter")];
+ char uniname2ctype_pool_str1636[sizeof("zzzz")];
+ char uniname2ctype_pool_str1639[sizeof("inhiragana")];
+ char uniname2ctype_pool_str1640[sizeof("tale")];
+ char uniname2ctype_pool_str1641[sizeof("canadianaboriginal")];
+ char uniname2ctype_pool_str1642[sizeof("ahex")];
+ char uniname2ctype_pool_str1644[sizeof("inmayannumerals")];
+ char uniname2ctype_pool_str1648[sizeof("inzanabazarsquare")];
+ char uniname2ctype_pool_str1654[sizeof("inyiradicals")];
+ char uniname2ctype_pool_str1655[sizeof("inscriptionalpahlavi")];
+ char uniname2ctype_pool_str1668[sizeof("inalchemicalsymbols")];
+ char uniname2ctype_pool_str1669[sizeof("inhatran")];
+ char uniname2ctype_pool_str1670[sizeof("assigned")];
+ char uniname2ctype_pool_str1671[sizeof("intaiviet")];
+ char uniname2ctype_pool_str1674[sizeof("syrc")];
+ char uniname2ctype_pool_str1682[sizeof("bopo")];
+ char uniname2ctype_pool_str1684[sizeof("intirhuta")];
+ char uniname2ctype_pool_str1688[sizeof("oldnortharabian")];
+ char uniname2ctype_pool_str1690[sizeof("insupplementalmathematicaloperators")];
+ char uniname2ctype_pool_str1694[sizeof("bopomofo")];
+ char uniname2ctype_pool_str1696[sizeof("olonal")];
+ char uniname2ctype_pool_str1697[sizeof("injavanese")];
+ char uniname2ctype_pool_str1698[sizeof("insunuwar")];
+ char uniname2ctype_pool_str1707[sizeof("inmathematicalalphanumericsymbols")];
+ char uniname2ctype_pool_str1713[sizeof("inimperialaramaic")];
+ char uniname2ctype_pool_str1714[sizeof("khmer")];
+ char uniname2ctype_pool_str1724[sizeof("gonm")];
+ char uniname2ctype_pool_str1727[sizeof("hyphen")];
+ char uniname2ctype_pool_str1731[sizeof("insuperscriptsandsubscripts")];
+ char uniname2ctype_pool_str1733[sizeof("inenclosedideographicsupplement")];
+ char uniname2ctype_pool_str1735[sizeof("ingeometricshapesextended")];
+ char uniname2ctype_pool_str1737[sizeof("insaurashtra")];
+ char uniname2ctype_pool_str1738[sizeof("ogam")];
+ char uniname2ctype_pool_str1746[sizeof("orya")];
+ char uniname2ctype_pool_str1748[sizeof("saur")];
+ char uniname2ctype_pool_str1754[sizeof("marchen")];
+ char uniname2ctype_pool_str1755[sizeof("sundanese")];
+ char uniname2ctype_pool_str1762[sizeof("khudawadi")];
+ char uniname2ctype_pool_str1773[sizeof("soyo")];
+ char uniname2ctype_pool_str1775[sizeof("whitespace")];
+ char uniname2ctype_pool_str1778[sizeof("uideo")];
+ char uniname2ctype_pool_str1785[sizeof("oldpersian")];
+ char uniname2ctype_pool_str1787[sizeof("inyezidi")];
+ char uniname2ctype_pool_str1790[sizeof("kiratrai")];
+ char uniname2ctype_pool_str1793[sizeof("inlisusupplement")];
+ char uniname2ctype_pool_str1796[sizeof("mero")];
+ char uniname2ctype_pool_str1800[sizeof("symbol")];
+ char uniname2ctype_pool_str1811[sizeof("soyombo")];
+ char uniname2ctype_pool_str1812[sizeof("osmanya")];
+ char uniname2ctype_pool_str1814[sizeof("indevanagari")];
+ char uniname2ctype_pool_str1816[sizeof("unassigned")];
+ char uniname2ctype_pool_str1818[sizeof("bengali")];
+ char uniname2ctype_pool_str1819[sizeof("hebr")];
+ char uniname2ctype_pool_str1821[sizeof("hebrew")];
+ char uniname2ctype_pool_str1824[sizeof("inornamentaldingbats")];
+ char uniname2ctype_pool_str1829[sizeof("invedicextensions")];
+ char uniname2ctype_pool_str1834[sizeof("copt")];
+ char uniname2ctype_pool_str1836[sizeof("ingreekextended")];
+ char uniname2ctype_pool_str1839[sizeof("sund")];
+ char uniname2ctype_pool_str1847[sizeof("cyprominoan")];
+ char uniname2ctype_pool_str1848[sizeof("inherited")];
+ char uniname2ctype_pool_str1854[sizeof("toto")];
+ char uniname2ctype_pool_str1858[sizeof("inugaritic")];
+ char uniname2ctype_pool_str1863[sizeof("syriac")];
+ char uniname2ctype_pool_str1864[sizeof("cwt")];
+ char uniname2ctype_pool_str1867[sizeof("inhebrew")];
+ char uniname2ctype_pool_str1872[sizeof("runic")];
+ char uniname2ctype_pool_str1877[sizeof("inmongoliansupplement")];
+ char uniname2ctype_pool_str1884[sizeof("inshorthandformatcontrols")];
+ char uniname2ctype_pool_str1900[sizeof("cypriot")];
+ char uniname2ctype_pool_str1901[sizeof("cwcm")];
+ char uniname2ctype_pool_str1910[sizeof("ingreekandcoptic")];
+ char uniname2ctype_pool_str1920[sizeof("any")];
+ char uniname2ctype_pool_str1923[sizeof("inolduyghur")];
+ char uniname2ctype_pool_str1936[sizeof("inznamennymusicalnotation")];
+ char uniname2ctype_pool_str1937[sizeof("lowercase")];
+ char uniname2ctype_pool_str1941[sizeof("oldpermic")];
+ char uniname2ctype_pool_str1943[sizeof("ingeorgian")];
+ char uniname2ctype_pool_str1945[sizeof("ingurmukhi")];
+ char uniname2ctype_pool_str1947[sizeof("emojimodifier")];
+ char uniname2ctype_pool_str1956[sizeof("inkhojki")];
+ char uniname2ctype_pool_str1958[sizeof("aghb")];
+ char uniname2ctype_pool_str1960[sizeof("merc")];
+ char uniname2ctype_pool_str1966[sizeof("inrejang")];
+ char uniname2ctype_pool_str1969[sizeof("tamil")];
+ char uniname2ctype_pool_str1972[sizeof("indevanagariextendeda")];
+ char uniname2ctype_pool_str1974[sizeof("inalphabeticpresentationforms")];
+ char uniname2ctype_pool_str1975[sizeof("hangul")];
+ char uniname2ctype_pool_str1977[sizeof("inmeroitichieroglyphs")];
+ char uniname2ctype_pool_str1978[sizeof("inkannada")];
+ char uniname2ctype_pool_str1979[sizeof("hiragana")];
+ char uniname2ctype_pool_str1980[sizeof("maka")];
+ char uniname2ctype_pool_str1983[sizeof("inkanbun")];
+ char uniname2ctype_pool_str1987[sizeof("insorasompeng")];
+ char uniname2ctype_pool_str2001[sizeof("inmathematicaloperators")];
+ char uniname2ctype_pool_str2002[sizeof("tayo")];
+ char uniname2ctype_pool_str2005[sizeof("inhanunoo")];
+ char uniname2ctype_pool_str2010[sizeof("multani")];
+ char uniname2ctype_pool_str2015[sizeof("inkaithi")];
+ char uniname2ctype_pool_str2022[sizeof("innushu")];
+ char uniname2ctype_pool_str2023[sizeof("emojipresentation")];
+ char uniname2ctype_pool_str2028[sizeof("insymbolsforlegacycomputing")];
+ char uniname2ctype_pool_str2029[sizeof("meroiticcursive")];
+ char uniname2ctype_pool_str2037[sizeof("grantha")];
+ char uniname2ctype_pool_str2040[sizeof("inlinearbsyllabary")];
+ char uniname2ctype_pool_str2041[sizeof("mult")];
+ char uniname2ctype_pool_str2042[sizeof("taitham")];
+ char uniname2ctype_pool_str2047[sizeof("nshu")];
+ char uniname2ctype_pool_str2049[sizeof("incyrillicsupplement")];
+ char uniname2ctype_pool_str2051[sizeof("dashpunctuation")];
+ char uniname2ctype_pool_str2053[sizeof("inkatakana")];
+ char uniname2ctype_pool_str2056[sizeof("inbatak")];
+ char uniname2ctype_pool_str2059[sizeof("pi")];
+ char uniname2ctype_pool_str2064[sizeof("mong")];
+ char uniname2ctype_pool_str2074[sizeof("oldhungarian")];
+ char uniname2ctype_pool_str2076[sizeof("phoenician")];
+ char uniname2ctype_pool_str2077[sizeof("insmallformvariants")];
+ char uniname2ctype_pool_str2078[sizeof("idsunaryoperator")];
+ char uniname2ctype_pool_str2080[sizeof("variationselector")];
+ char uniname2ctype_pool_str2081[sizeof("limbu")];
+ char uniname2ctype_pool_str2085[sizeof("inyisyllables")];
+ char uniname2ctype_pool_str2087[sizeof("diak")];
+ char uniname2ctype_pool_str2090[sizeof("oldsoutharabian")];
+ char uniname2ctype_pool_str2092[sizeof("lepc")];
+ char uniname2ctype_pool_str2093[sizeof("inottomansiyaqnumbers")];
+ char uniname2ctype_pool_str2097[sizeof("control")];
+ char uniname2ctype_pool_str2102[sizeof("coptic")];
+ char uniname2ctype_pool_str2104[sizeof("inkhmersymbols")];
+ char uniname2ctype_pool_str2107[sizeof("titlecaseletter")];
+ char uniname2ctype_pool_str2110[sizeof("inphagspa")];
+ char uniname2ctype_pool_str2111[sizeof("bhks")];
+ char uniname2ctype_pool_str2113[sizeof("gothic")];
+ char uniname2ctype_pool_str2117[sizeof("sogo")];
+ char uniname2ctype_pool_str2122[sizeof("elym")];
+ char uniname2ctype_pool_str2131[sizeof("ps")];
+ char uniname2ctype_pool_str2137[sizeof("prti")];
+ char uniname2ctype_pool_str2138[sizeof("changeswhencasemapped")];
+ char uniname2ctype_pool_str2140[sizeof("deseret")];
+ char uniname2ctype_pool_str2142[sizeof("bhaiksuki")];
+ char uniname2ctype_pool_str2143[sizeof("cyrl")];
+ char uniname2ctype_pool_str2147[sizeof("olower")];
+ char uniname2ctype_pool_str2148[sizeof("inchakma")];
+ char uniname2ctype_pool_str2152[sizeof("wara")];
+ char uniname2ctype_pool_str2153[sizeof("sogdian")];
+ char uniname2ctype_pool_str2155[sizeof("graphemeclusterbreak=zwj")];
+ char uniname2ctype_pool_str2164[sizeof("runr")];
+ char uniname2ctype_pool_str2165[sizeof("changeswhentitlecased")];
+ char uniname2ctype_pool_str2168[sizeof("incjkstrokes")];
+ char uniname2ctype_pool_str2176[sizeof("incherokeesupplement")];
+ char uniname2ctype_pool_str2179[sizeof("intangutcomponents")];
+ char uniname2ctype_pool_str2182[sizeof("patws")];
+ char uniname2ctype_pool_str2183[sizeof("batk")];
+ char uniname2ctype_pool_str2186[sizeof("caseignorable")];
+ char uniname2ctype_pool_str2191[sizeof("inkawi")];
+ char uniname2ctype_pool_str2199[sizeof("indevanagariextended")];
+ char uniname2ctype_pool_str2203[sizeof("indogra")];
+ char uniname2ctype_pool_str2204[sizeof("intifinagh")];
+ char uniname2ctype_pool_str2206[sizeof("print")];
+ char uniname2ctype_pool_str2207[sizeof("cakm")];
+ char uniname2ctype_pool_str2209[sizeof("graphemeclusterbreak=t")];
+ char uniname2ctype_pool_str2211[sizeof("graphemeclusterbreak=lvt")];
+ char uniname2ctype_pool_str2214[sizeof("inmendekikakui")];
+ char uniname2ctype_pool_str2216[sizeof("inpsalterpahlavi")];
+ char uniname2ctype_pool_str2224[sizeof("dogra")];
+ char uniname2ctype_pool_str2228[sizeof("tangut")];
+ char uniname2ctype_pool_str2235[sizeof("oalpha")];
+ char uniname2ctype_pool_str2237[sizeof("intangutcomponentssupplement")];
+ char uniname2ctype_pool_str2239[sizeof("idcompatmathcontinue")];
+ char uniname2ctype_pool_str2241[sizeof("beriaerfe")];
+ char uniname2ctype_pool_str2243[sizeof("ext")];
+ char uniname2ctype_pool_str2244[sizeof("inkanasupplement")];
+ char uniname2ctype_pool_str2247[sizeof("osge")];
+ char uniname2ctype_pool_str2248[sizeof("inkanaextendeda")];
+ char uniname2ctype_pool_str2249[sizeof("inverticalforms")];
+ char uniname2ctype_pool_str2252[sizeof("decimalnumber")];
+ char uniname2ctype_pool_str2254[sizeof("inkanaextendedb")];
+ char uniname2ctype_pool_str2255[sizeof("idstrinaryoperator")];
+ char uniname2ctype_pool_str2257[sizeof("tols")];
+ char uniname2ctype_pool_str2260[sizeof("lower")];
+ char uniname2ctype_pool_str2270[sizeof("glag")];
+ char uniname2ctype_pool_str2272[sizeof("inhanguljamo")];
+ char uniname2ctype_pool_str2279[sizeof("insupplementalarrowsa")];
+ char uniname2ctype_pool_str2281[sizeof("inmeeteimayek")];
+ char uniname2ctype_pool_str2285[sizeof("insupplementalarrowsb")];
+ char uniname2ctype_pool_str2288[sizeof("inunifiedcanadianaboriginalsyllabics")];
+ char uniname2ctype_pool_str2296[sizeof("privateuse")];
+ char uniname2ctype_pool_str2299[sizeof("inunifiedcanadianaboriginalsyllabicsextendeda")];
+ char uniname2ctype_pool_str2302[sizeof("sentenceterminal")];
+ char uniname2ctype_pool_str2308[sizeof("pcm")];
+ char uniname2ctype_pool_str2309[sizeof("elymaic")];
+ char uniname2ctype_pool_str2310[sizeof("cpmn")];
+ char uniname2ctype_pool_str2312[sizeof("incjkcompatibilityforms")];
+ char uniname2ctype_pool_str2313[sizeof("inphoneticextensions")];
+ char uniname2ctype_pool_str2317[sizeof("incjkcompatibilityideographs")];
+ char uniname2ctype_pool_str2320[sizeof("oldsogdian")];
+ char uniname2ctype_pool_str2341[sizeof("inethiopicsupplement")];
+ char uniname2ctype_pool_str2345[sizeof("graphemebase")];
+ char uniname2ctype_pool_str2350[sizeof("intangutsupplement")];
+ char uniname2ctype_pool_str2353[sizeof("tang")];
+ char uniname2ctype_pool_str2361[sizeof("ideographic")];
+ char uniname2ctype_pool_str2364[sizeof("nagmundari")];
+ char uniname2ctype_pool_str2366[sizeof("sogd")];
+ char uniname2ctype_pool_str2370[sizeof("psalterpahlavi")];
+ char uniname2ctype_pool_str2371[sizeof("inphoneticextensionssupplement")];
+ char uniname2ctype_pool_str2373[sizeof("tagb")];
+ char uniname2ctype_pool_str2374[sizeof("invariationselectors")];
+ char uniname2ctype_pool_str2375[sizeof("incjkcompatibilityideographssupplement")];
+ char uniname2ctype_pool_str2379[sizeof("inindicsiyaqnumbers")];
+ char uniname2ctype_pool_str2389[sizeof("khojki")];
+ char uniname2ctype_pool_str2392[sizeof("inplayingcards")];
+ char uniname2ctype_pool_str2396[sizeof("graphemeclusterbreak=extend")];
+ char uniname2ctype_pool_str2397[sizeof("graphemeclusterbreak=prepend")];
+ char uniname2ctype_pool_str2398[sizeof("space")];
+ char uniname2ctype_pool_str2401[sizeof("tagbanwa")];
+ char uniname2ctype_pool_str2416[sizeof("extpict")];
+ char uniname2ctype_pool_str2421[sizeof("insupplementaryprivateuseareaa")];
+ char uniname2ctype_pool_str2422[sizeof("insupplementalarrowsc")];
+ char uniname2ctype_pool_str2424[sizeof("pd")];
+ char uniname2ctype_pool_str2427[sizeof("insupplementaryprivateuseareab")];
+ char uniname2ctype_pool_str2428[sizeof("innoblock")];
+ char uniname2ctype_pool_str2432[sizeof("invariationselectorssupplement")];
+ char uniname2ctype_pool_str2433[sizeof("inhanguljamoextendeda")];
+ char uniname2ctype_pool_str2434[sizeof("kthi")];
+ char uniname2ctype_pool_str2439[sizeof("inhanguljamoextendedb")];
+ char uniname2ctype_pool_str2440[sizeof("sk")];
+ char uniname2ctype_pool_str2443[sizeof("cherokee")];
+ char uniname2ctype_pool_str2451[sizeof("nchar")];
+ char uniname2ctype_pool_str2458[sizeof("pc")];
+ char uniname2ctype_pool_str2466[sizeof("graphemeextend")];
+ char uniname2ctype_pool_str2468[sizeof("wancho")];
+ char uniname2ctype_pool_str2473[sizeof("inprivateusearea")];
+ char uniname2ctype_pool_str2483[sizeof("sunuwar")];
+ char uniname2ctype_pool_str2491[sizeof("ingothic")];
+ char uniname2ctype_pool_str2495[sizeof("softdotted")];
+ char uniname2ctype_pool_str2503[sizeof("lowercaseletter")];
+ char uniname2ctype_pool_str2505[sizeof("phli")];
+ char uniname2ctype_pool_str2518[sizeof("katakana")];
+ char uniname2ctype_pool_str2526[sizeof("inunifiedcanadianaboriginalsyllabicsextended")];
+ char uniname2ctype_pool_str2528[sizeof("hanifirohingya")];
+ char uniname2ctype_pool_str2532[sizeof("palm")];
+ char uniname2ctype_pool_str2534[sizeof("talu")];
+ char uniname2ctype_pool_str2541[sizeof("inlisu")];
+ char uniname2ctype_pool_str2543[sizeof("lu")];
+ char uniname2ctype_pool_str2553[sizeof("invithkuqi")];
+ char uniname2ctype_pool_str2570[sizeof("finalpunctuation")];
+ char uniname2ctype_pool_str2571[sizeof("incyrillicextendeda")];
+ char uniname2ctype_pool_str2577[sizeof("incyrillicextendedb")];
+ char uniname2ctype_pool_str2579[sizeof("noncharactercodepoint")];
+ char uniname2ctype_pool_str2581[sizeof("mark")];
+ char uniname2ctype_pool_str2582[sizeof("medf")];
+ char uniname2ctype_pool_str2590[sizeof("inkiratrai")];
+ char uniname2ctype_pool_str2591[sizeof("intelugu")];
+ char uniname2ctype_pool_str2592[sizeof("inmakasar")];
+ char uniname2ctype_pool_str2593[sizeof("graphemeclusterbreak=l")];
+ char uniname2ctype_pool_str2596[sizeof("inkharoshthi")];
+ char uniname2ctype_pool_str2599[sizeof("graphemeclusterbreak=control")];
+ char uniname2ctype_pool_str2603[sizeof("deprecated")];
+ char uniname2ctype_pool_str2612[sizeof("insupplementalsymbolsandpictographs")];
+ char uniname2ctype_pool_str2613[sizeof("tirh")];
+ char uniname2ctype_pool_str2614[sizeof("sunu")];
+ char uniname2ctype_pool_str2618[sizeof("letter")];
+ char uniname2ctype_pool_str2619[sizeof("medefaidrin")];
+ char uniname2ctype_pool_str2625[sizeof("beng")];
+ char uniname2ctype_pool_str2626[sizeof("makasar")];
+ char uniname2ctype_pool_str2632[sizeof("cwl")];
+ char uniname2ctype_pool_str2633[sizeof("intakri")];
+ char uniname2ctype_pool_str2634[sizeof("tavt")];
+ char uniname2ctype_pool_str2658[sizeof("todr")];
+ char uniname2ctype_pool_str2668[sizeof("todhri")];
+ char uniname2ctype_pool_str2671[sizeof("insupplementalpunctuation")];
+ char uniname2ctype_pool_str2672[sizeof("modifiersymbol")];
+ char uniname2ctype_pool_str2673[sizeof("ogham")];
+ char uniname2ctype_pool_str2679[sizeof("wcho")];
+ char uniname2ctype_pool_str2688[sizeof("intagalog")];
+ char uniname2ctype_pool_str2689[sizeof("omath")];
+ char uniname2ctype_pool_str2699[sizeof("inkhmer")];
+ char uniname2ctype_pool_str2700[sizeof("cf")];
+ char uniname2ctype_pool_str2701[sizeof("bassavah")];
+ char uniname2ctype_pool_str2705[sizeof("extendedpictographic")];
+ char uniname2ctype_pool_str2708[sizeof("zyyy")];
+ char uniname2ctype_pool_str2714[sizeof("incyrillicextendedc")];
+ char uniname2ctype_pool_str2725[sizeof("ugaritic")];
+ char uniname2ctype_pool_str2726[sizeof("goth")];
+ char uniname2ctype_pool_str2728[sizeof("idcompatmathstart")];
+ char uniname2ctype_pool_str2729[sizeof("divesakuru")];
+ char uniname2ctype_pool_str2732[sizeof("wspace")];
+ char uniname2ctype_pool_str2737[sizeof("geor")];
+ char uniname2ctype_pool_str2764[sizeof("cyrillic")];
+ char uniname2ctype_pool_str2765[sizeof("graphemeclusterbreak=cr")];
+ char uniname2ctype_pool_str2767[sizeof("sorasompeng")];
+ char uniname2ctype_pool_str2780[sizeof("graphemeclusterbreak=regionalindicator")];
+ char uniname2ctype_pool_str2782[sizeof("tirhuta")];
+ char uniname2ctype_pool_str2791[sizeof("inbopomofoextended")];
+ char uniname2ctype_pool_str2796[sizeof("yezi")];
+ char uniname2ctype_pool_str2798[sizeof("p")];
+ char uniname2ctype_pool_str2799[sizeof("incyrillicextendedd")];
+ char uniname2ctype_pool_str2800[sizeof("po")];
+ char uniname2ctype_pool_str2801[sizeof("zp")];
+ char uniname2ctype_pool_str2802[sizeof("dogr")];
+ char uniname2ctype_pool_str2806[sizeof("dep")];
+ char uniname2ctype_pool_str2813[sizeof("hung")];
+ char uniname2ctype_pool_str2819[sizeof("term")];
+ char uniname2ctype_pool_str2826[sizeof("deva")];
+ char uniname2ctype_pool_str2831[sizeof("format")];
+ char uniname2ctype_pool_str2835[sizeof("oldturkic")];
+ char uniname2ctype_pool_str2836[sizeof("kayahli")];
+ char uniname2ctype_pool_str2844[sizeof("devanagari")];
+ char uniname2ctype_pool_str2850[sizeof("olck")];
+ char uniname2ctype_pool_str2852[sizeof("dupl")];
+ char uniname2ctype_pool_str2857[sizeof("incurrencysymbols")];
+ char uniname2ctype_pool_str2861[sizeof("olchiki")];
+ char uniname2ctype_pool_str2863[sizeof("inethiopicextendeda")];
+ char uniname2ctype_pool_str2869[sizeof("inethiopicextendedb")];
+ char uniname2ctype_pool_str2872[sizeof("phagspa")];
+ char uniname2ctype_pool_str2877[sizeof("buhd")];
+ char uniname2ctype_pool_str2878[sizeof("inhangulsyllables")];
+ char uniname2ctype_pool_str2881[sizeof("inlatinextendedf")];
+ char uniname2ctype_pool_str2883[sizeof("modifierletter")];
+ char uniname2ctype_pool_str2894[sizeof("graph")];
+ char uniname2ctype_pool_str2897[sizeof("ingaray")];
+ char uniname2ctype_pool_str2900[sizeof("number")];
+ char uniname2ctype_pool_str2910[sizeof("inkayahli")];
+ char uniname2ctype_pool_str2922[sizeof("lepcha")];
+ char uniname2ctype_pool_str2925[sizeof("plrd")];
+ char uniname2ctype_pool_str2926[sizeof("incjksymbolsandpunctuation")];
+ char uniname2ctype_pool_str2928[sizeof("ecomp")];
+ char uniname2ctype_pool_str2947[sizeof("cuneiform")];
+ char uniname2ctype_pool_str2953[sizeof("inglagolitic")];
+ char uniname2ctype_pool_str2960[sizeof("gunjalagondi")];
+ char uniname2ctype_pool_str2970[sizeof("bugi")];
+ char uniname2ctype_pool_str2984[sizeof("takri")];
+ char uniname2ctype_pool_str2986[sizeof("cprt")];
+ char uniname2ctype_pool_str2987[sizeof("spaceseparator")];
+ char uniname2ctype_pool_str2991[sizeof("ingurungkhema")];
+ char uniname2ctype_pool_str2993[sizeof("incypriotsyllabary")];
+ char uniname2ctype_pool_str2995[sizeof("inpaucinhau")];
+ char uniname2ctype_pool_str3005[sizeof("gong")];
+ char uniname2ctype_pool_str3013[sizeof("joinc")];
+ char uniname2ctype_pool_str3015[sizeof("currencysymbol")];
+ char uniname2ctype_pool_str3017[sizeof("rohg")];
+ char uniname2ctype_pool_str3021[sizeof("logicalorderexception")];
+ char uniname2ctype_pool_str3022[sizeof("grek")];
+ char uniname2ctype_pool_str3041[sizeof("changeswhenlowercased")];
+ char uniname2ctype_pool_str3049[sizeof("inpahawhhmong")];
+ char uniname2ctype_pool_str3052[sizeof("yezidi")];
+ char uniname2ctype_pool_str3054[sizeof("cwcf")];
+ char uniname2ctype_pool_str3061[sizeof("extender")];
+ char uniname2ctype_pool_str3068[sizeof("inhangulcompatibilityjamo")];
+ char uniname2ctype_pool_str3078[sizeof("tulutigalari")];
+ char uniname2ctype_pool_str3080[sizeof("terminalpunctuation")];
+ char uniname2ctype_pool_str3086[sizeof("inkatakanaphoneticextensions")];
+ char uniname2ctype_pool_str3090[sizeof("inethiopicextended")];
+ char uniname2ctype_pool_str3097[sizeof("gujr")];
+ char uniname2ctype_pool_str3103[sizeof("patsyn")];
+ char uniname2ctype_pool_str3107[sizeof("ugar")];
+ char uniname2ctype_pool_str3108[sizeof("word")];
+ char uniname2ctype_pool_str3112[sizeof("berf")];
+ char uniname2ctype_pool_str3121[sizeof("xpeo")];
+ char uniname2ctype_pool_str3122[sizeof("regionalindicator")];
+ char uniname2ctype_pool_str3127[sizeof("gujarati")];
+ char uniname2ctype_pool_str3128[sizeof("buhid")];
+ char uniname2ctype_pool_str3137[sizeof("inlatinextendedg")];
+ char uniname2ctype_pool_str3142[sizeof("ethi")];
+ char uniname2ctype_pool_str3165[sizeof("inkhitansmallscript")];
+ char uniname2ctype_pool_str3169[sizeof("ingeorgiansupplement")];
+ char uniname2ctype_pool_str3177[sizeof("inegyptianhieroglyphs")];
+ char uniname2ctype_pool_str3184[sizeof("tifinagh")];
+ char uniname2ctype_pool_str3188[sizeof("inegyptianhieroglyphsextendeda")];
+ char uniname2ctype_pool_str3190[sizeof("inegyptianhieroglyphformatcontrols")];
+ char uniname2ctype_pool_str3221[sizeof("inkhudawadi")];
+ char uniname2ctype_pool_str3231[sizeof("incjkcompatibility")];
+ char uniname2ctype_pool_str3238[sizeof("rjng")];
+ char uniname2ctype_pool_str3240[sizeof("buginese")];
+ char uniname2ctype_pool_str3245[sizeof("mendekikakui")];
+ char uniname2ctype_pool_str3247[sizeof("letternumber")];
+ char uniname2ctype_pool_str3257[sizeof("phlp")];
+ char uniname2ctype_pool_str3261[sizeof("separator")];
+ char uniname2ctype_pool_str3263[sizeof("pauc")];
+ char uniname2ctype_pool_str3281[sizeof("vithkuqi")];
+ char uniname2ctype_pool_str3287[sizeof("inkangxiradicals")];
+ char uniname2ctype_pool_str3291[sizeof("changeswhencasefolded")];
+ char uniname2ctype_pool_str3302[sizeof("graphemeclusterbreak=lf")];
+ char uniname2ctype_pool_str3307[sizeof("joincontrol")];
+ char uniname2ctype_pool_str3326[sizeof("inmeroiticcursive")];
+ char uniname2ctype_pool_str3334[sizeof("pe")];
+ char uniname2ctype_pool_str3335[sizeof("patternwhitespace")];
+ char uniname2ctype_pool_str3357[sizeof("duployan")];
+ char uniname2ctype_pool_str3359[sizeof("phag")];
+ char uniname2ctype_pool_str3363[sizeof("meeteimayek")];
+ char uniname2ctype_pool_str3407[sizeof("innyiakengpuachuehmong")];
+ char uniname2ctype_pool_str3408[sizeof("incjkunifiedideographsextensioni")];
+ char uniname2ctype_pool_str3414[sizeof("incjkunifiedideographs")];
+ char uniname2ctype_pool_str3416[sizeof("incjkunifiedideographsextensionj")];
+ char uniname2ctype_pool_str3418[sizeof("georgian")];
+ char uniname2ctype_pool_str3426[sizeof("incjkunifiedideographsextensiona")];
+ char uniname2ctype_pool_str3432[sizeof("incjkunifiedideographsextensionb")];
+ char uniname2ctype_pool_str3436[sizeof("warangciti")];
+ char uniname2ctype_pool_str3444[sizeof("inhighprivateusesurrogates")];
+ char uniname2ctype_pool_str3469[sizeof("meroitichieroglyphs")];
+ char uniname2ctype_pool_str3481[sizeof("java")];
+ char uniname2ctype_pool_str3493[sizeof("garay")];
+ char uniname2ctype_pool_str3497[sizeof("nonspacingmark")];
+ char uniname2ctype_pool_str3505[sizeof("otheridstart")];
+ char uniname2ctype_pool_str3507[sizeof("otheridcontinue")];
+ char uniname2ctype_pool_str3516[sizeof("xsux")];
+ char uniname2ctype_pool_str3532[sizeof("phnx")];
+ char uniname2ctype_pool_str3535[sizeof("incjkunifiedideographsextensione")];
+ char uniname2ctype_pool_str3536[sizeof("signwriting")];
+ char uniname2ctype_pool_str3543[sizeof("tolongsiki")];
+ char uniname2ctype_pool_str3569[sizeof("incjkunifiedideographsextensionc")];
+ char uniname2ctype_pool_str3579[sizeof("combiningmark")];
+ char uniname2ctype_pool_str3585[sizeof("nushu")];
+ char uniname2ctype_pool_str3598[sizeof("takr")];
+ char uniname2ctype_pool_str3613[sizeof("tfng")];
+ char uniname2ctype_pool_str3614[sizeof("changeswhenuppercased")];
+ char uniname2ctype_pool_str3622[sizeof("inglagoliticsupplement")];
+ char uniname2ctype_pool_str3629[sizeof("surrogate")];
+ char uniname2ctype_pool_str3647[sizeof("orkh")];
+ char uniname2ctype_pool_str3650[sizeof("graphemeclusterbreak=v")];
+ char uniname2ctype_pool_str3651[sizeof("graphemeclusterbreak=lv")];
+ char uniname2ctype_pool_str3654[sizeof("incjkunifiedideographsextensiond")];
+ char uniname2ctype_pool_str3666[sizeof("telu")];
+ char uniname2ctype_pool_str3669[sizeof("inhalfwidthandfullwidthforms")];
+ char uniname2ctype_pool_str3686[sizeof("otheralphabetic")];
+ char uniname2ctype_pool_str3690[sizeof("unknown")];
+ char uniname2ctype_pool_str3699[sizeof("punct")];
+ char uniname2ctype_pool_str3718[sizeof("tglg")];
+ char uniname2ctype_pool_str3733[sizeof("javanese")];
+ char uniname2ctype_pool_str3770[sizeof("otherdefaultignorablecodepoint")];
+ char uniname2ctype_pool_str3778[sizeof("cwu")];
+ char uniname2ctype_pool_str3782[sizeof("rejang")];
+ char uniname2ctype_pool_str3813[sizeof("egyp")];
+ char uniname2ctype_pool_str3835[sizeof("perm")];
+ char uniname2ctype_pool_str3836[sizeof("othersymbol")];
+ char uniname2ctype_pool_str3869[sizeof("epres")];
+ char uniname2ctype_pool_str3877[sizeof("olduyghur")];
+ char uniname2ctype_pool_str3894[sizeof("tutg")];
+ char uniname2ctype_pool_str3901[sizeof("enclosingmark")];
+ char uniname2ctype_pool_str3918[sizeof("ingeorgianextended")];
+ char uniname2ctype_pool_str3945[sizeof("ogrext")];
+ char uniname2ctype_pool_str3965[sizeof("indivesakuru")];
+ char uniname2ctype_pool_str3972[sizeof("otherlowercase")];
+ char uniname2ctype_pool_str3981[sizeof("other")];
+ char uniname2ctype_pool_str3995[sizeof("othernumber")];
+ char uniname2ctype_pool_str4007[sizeof("hexdigit")];
+ char uniname2ctype_pool_str4018[sizeof("incjkradicalssupplement")];
+ char uniname2ctype_pool_str4035[sizeof("blank")];
+ char uniname2ctype_pool_str4064[sizeof("ethiopic")];
+ char uniname2ctype_pool_str4069[sizeof("graphemeclusterbreak=spacingmark")];
+ char uniname2ctype_pool_str4072[sizeof("spacingmark")];
+ char uniname2ctype_pool_str4089[sizeof("tagalog")];
+ char uniname2ctype_pool_str4102[sizeof("batak")];
+ char uniname2ctype_pool_str4110[sizeof("guru")];
+ char uniname2ctype_pool_str4117[sizeof("hex")];
+ char uniname2ctype_pool_str4140[sizeof("paucinhau")];
+ char uniname2ctype_pool_str4153[sizeof("modifiercombiningmark")];
+ char uniname2ctype_pool_str4163[sizeof("otherpunctuation")];
+ char uniname2ctype_pool_str4180[sizeof("ougr")];
+ char uniname2ctype_pool_str4228[sizeof("palmyrene")];
+ char uniname2ctype_pool_str4318[sizeof("othermath")];
+ char uniname2ctype_pool_str4353[sizeof("incjkunifiedideographsextensionh")];
+ char uniname2ctype_pool_str4354[sizeof("inboxdrawing")];
+ char uniname2ctype_pool_str4401[sizeof("patternsyntax")];
+ char uniname2ctype_pool_str4404[sizeof("oupper")];
+ char uniname2ctype_pool_str4410[sizeof("gurungkhema")];
+ char uniname2ctype_pool_str4414[sizeof("prependedconcatenationmark")];
+ char uniname2ctype_pool_str4439[sizeof("otherletter")];
+ char uniname2ctype_pool_str4491[sizeof("pf")];
+ char uniname2ctype_pool_str4494[sizeof("qmark")];
+ char uniname2ctype_pool_str4543[sizeof("inhighsurrogates")];
+ char uniname2ctype_pool_str4544[sizeof("xposixpunct")];
+ char uniname2ctype_pool_str4545[sizeof("otheruppercase")];
+ char uniname2ctype_pool_str4564[sizeof("incjkunifiedideographsextensionf")];
+ char uniname2ctype_pool_str4670[sizeof("punctuation")];
+ char uniname2ctype_pool_str4692[sizeof("incjkunifiedideographsextensiong")];
+ char uniname2ctype_pool_str4731[sizeof("egyptianhieroglyphs")];
+ char uniname2ctype_pool_str4775[sizeof("defaultignorablecodepoint")];
+ char uniname2ctype_pool_str4777[sizeof("quotationmark")];
+ char uniname2ctype_pool_str4800[sizeof("openpunctuation")];
+ char uniname2ctype_pool_str4851[sizeof("unifiedideograph")];
+ char uniname2ctype_pool_str4941[sizeof("greek")];
+ char uniname2ctype_pool_str4985[sizeof("othergraphemeextend")];
+ char uniname2ctype_pool_str5002[sizeof("inkaktoviknumerals")];
+ char uniname2ctype_pool_str5234[sizeof("uppercase")];
+ char uniname2ctype_pool_str5271[sizeof("grlink")];
+ char uniname2ctype_pool_str5290[sizeof("nyiakengpuachuehmong")];
+ char uniname2ctype_pool_str5329[sizeof("gukh")];
+ char uniname2ctype_pool_str5512[sizeof("pahawhhmong")];
+ char uniname2ctype_pool_str5557[sizeof("upper")];
+ char uniname2ctype_pool_str5800[sizeof("uppercaseletter")];
+ char uniname2ctype_pool_str5919[sizeof("graphemelink")];
+ char uniname2ctype_pool_str5981[sizeof("telugu")];
+ char uniname2ctype_pool_str6036[sizeof("gurmukhi")];
+ char uniname2ctype_pool_str6068[sizeof("paragraphseparator")];
+#endif /* USE_UNICODE_PROPERTIES */
+ };
+static const struct uniname2ctype_pool_t uniname2ctype_pool_contents =
+ {
+#ifndef USE_UNICODE_PROPERTIES
+ "word",
+ "print",
+ "punct",
+ "alpha",
+#else /* USE_UNICODE_PROPERTIES */
+ "n",
+ "m",
+ "mn",
+ "lm",
+ "inmro",
+ "innko",
+ "mro",
+ "mroo",
+ "ri",
+ "lao",
+ "laoo",
+ "ahom",
+ "hano",
+ "miao",
+ "hani",
+ "inmiao",
+ "han",
+ "mani",
+ "lina",
+ "inahom",
+ "hanunoo",
+ "limb",
+ "linb",
+ "inmanichaean",
+#endif /* USE_UNICODE_PROPERTIES */
+ "alnum",
+#ifndef USE_UNICODE_PROPERTIES
+ "xdigit",
+ "upper",
+#else /* USE_UNICODE_PROPERTIES */
+ "armi",
+ "nandinagari",
+ "armn",
+ "lana",
+ "zanb",
+ "inosmanya",
+ "insamaritan",
+ "inbhaiksuki",
+ "armenian",
+ "sm",
+ "inmasaramgondi",
+ "s",
+ "innabataean",
+ "zs",
+ "inbasiclatin",
+ "innumberforms",
+ "arab",
+ "inmusicalsymbols",
+ "latn",
+ "inthai",
+ "latin",
+ "shavian",
+ "initialpunctuation",
+ "hatran",
+ "di",
+ "inthaana",
+ "intoto",
+ "nabataean",
+ "intaitham",
+ "inarabicpresentationformsa",
+ "inbraillepatterns",
+ "inarabicpresentationformsb",
+ "ids",
+ "dia",
+ "inarmenian",
+ "idsb",
+ "intransportandmapsymbols",
+ "inideographicsymbolsandpunctuation",
+ "inavestan",
+ "inipaextensions",
+ "inelbasan",
+ "inopticalcharacterrecognition",
+ "brai",
+ "bamum",
+ "incham",
+ "inideographicdescriptioncharacters",
+ "brahmi",
+ "idst",
+ "bass",
+ "mandaic",
+ "inemoticons",
+ "incommonindicnumberforms",
+ "intibetan",
+ "inarabic",
+ "nbat",
+ "cn",
+ "inancientsymbols",
+ "ci",
+#endif /* USE_UNICODE_PROPERTIES */
+ "ascii",
+#ifdef USE_UNICODE_PROPERTIES
+ "mcm",
+ "ideo",
+ "inmodi",
+ "vai",
+ "vaii",
+ "cham",
+ "inmyanmarextendeda",
+ "nand",
+ "inmyanmarextendedb",
+ "mand",
+ "cans",
+ "inoldsogdian",
+ "chorasmian",
+ "innewa",
+ "chakma",
+ "incuneiform",
+ "vs",
+ "cs",
+ "sind",
+ "shaw",
+ "inspecials",
+ "inchesssymbols",
+ "avst",
+ "inblockelements",
+ "nd",
+ "sharada",
+ "inmiscellaneoussymbols",
+ "inmiscellaneousmathematicalsymbolsa",
+ "sidt",
+ "inmiscellaneousmathematicalsymbolsb",
+ "inmiscellaneoussymbolsandarrows",
+ "arabic",
+ "inmiscellaneoussymbolsandpictographs",
+ "c",
+ "lc",
+ "mc",
+ "inmedefaidrin",
+ "inmyanmarextendedc",
+ "insundanese",
+ "indominotiles",
+ "insymbolsandpictographsextendeda",
+ "inwancho",
+ "inolditalic",
+ "inmodifiertoneletters",
+ "incb=consonant",
+ "sd",
+ "inmandaic",
+ "inmiscellaneoussymbolssupplement",
+ "nko",
+ "nkoo",
+ "l",
+ "inmeeteimayekextensions",
+ "nl",
+ "zl",
+ "ll",
+ "inlao",
+ "khoj",
+ "idc",
+ "innewtailue",
+ "inolonal",
+ "sc",
+ "indeseret",
+ "incuneiformnumbersandpunctuation",
+ "krai",
+ "inarabicextendeda",
+ "inoldturkic",
+ "avestan",
+ "inarabicextendedb",
+ "inmalayalam",
+ "kharoshthi",
+ "kana",
+ "inadlam",
+ "idcontinue",
+ "insiddham",
+ "intamil",
+ "inmultani",
+ "intolongsiki",
+ "kits",
+ "incb=extend",
+ "sidetic",
+ "sidd",
+ "incontrolpictures",
+ "insidetic",
+ "sinhala",
+ "inlatinextendeda",
+ "inlatinextendedb",
+ "adlm",
+ "adlam",
+ "inlineara",
+ "intamilsupplement",
+ "inbalinese",
+ "inspacingmodifierletters",
+ "inarabicextendedc",
+ "inlycian",
+ "bali",
+ "hira",
+ "cc",
+ "insmallkanaextension",
+ "intaile",
+ "qaai",
+ "inmyanmar",
+ "narb",
+ "inarrows",
+ "lineara",
+ "linearb",
+ "insharada",
+ "inruminumeralsymbols",
+ "masaramgondi",
+ "hatr",
+ "knda",
+ "samr",
+ "kawi",
+ "inlydian",
+ "samaritan",
+ "sarb",
+ "no",
+ "bidic",
+ "lo",
+ "hmnp",
+ "onao",
+ "inlowsurrogates",
+ "kannada",
+ "inlinearbideograms",
+ "inletterlikesymbols",
+ "cased",
+ "inbopomofo",
+ "inberiaerfe",
+ "lineseparator",
+ "z",
+ "insymbolsforlegacycomputingsupplement",
+ "inrunic",
+ "incarian",
+ "inlatinextendede",
+ "inmarchen",
+ "so",
+ "marc",
+ "oriya",
+ "inchorasmian",
+ "yi",
+ "insyriac",
+ "yiii",
+ "alpha",
+ "qaac",
+ "insundanesesupplement",
+ "osma",
+ "inmiscellaneoustechnical",
+ "idstart",
+ "inenclosedcjklettersandmonths",
+ "inlatinextendedc",
+ "dsrt",
+ "odi",
+ "chrs",
+ "cari",
+ "innandinagari",
+ "balinese",
+ "inwarangciti",
+ "inphoenician",
+ "kali",
+ "inoldnortharabian",
+ "radical",
+ "carian",
+ "idsbinaryoperator",
+ "shrd",
+ "inoldsoutharabian",
+ "diacritic",
+ "mlym",
+ "zinh",
+ "inphaistosdisc",
+ "incyrillic",
+ "ininscriptionalpahlavi",
+ "insoyombo",
+ "ininscriptionalparthian",
+ "inoriya",
+ "lyci",
+ "inogham",
+ "mahj",
+ "gran",
+ "inmahajani",
+ "co",
+ "cher",
+ "alphabetic",
+ "insinhala",
+ "modi",
+ "inbrahmi",
+ "loe",
+ "lycian",
+ "mahajani",
+ "common",
+ "intaiyo",
+ "inhanifirohingya",
+ "inbassavah",
+ "sinh",
+ "oids",
+ "inlatinextendedadditional",
+ "inyijinghexagramsymbols",
+ "inoldpersian",
+ "bidicontrol",
+ "math",
+ "inarabicsupplement",
+ "thai",
+ "inlatinextendedd",
+ "taiyo",
+ "lisu",
+ "tnsa",
+ "incherokee",
+ "thaa",
+ "lydi",
+ "inbamum",
+ "khmr",
+ "inbyzantinemusicalsymbols",
+ "lt",
+ "khar",
+ "thaana",
+ "osage",
+ "lydian",
+ "inanatolianhieroglyphs",
+#ifdef USE_UNICODE_AGE_PROPERTIES
+ "age=11.0",
+ "age=10.0",
+ "age=12.1",
+ "age=12.0",
+ "age=1.1",
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ "insylotinagri",
+ "anatolianhieroglyphs",
+#ifdef USE_UNICODE_AGE_PROPERTIES
+ "age=2.1",
+ "age=2.0",
+ "age=14.0",
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ "tangsa",
+ "dash",
+ "incombiningdiacriticalmarks",
+#ifdef USE_UNICODE_AGE_PROPERTIES
+ "age=17.0",
+ "age=4.1",
+ "age=4.0",
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ "tibt",
+#ifdef USE_UNICODE_AGE_PROPERTIES
+ "age=15.1",
+ "age=15.0",
+ "age=7.0",
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ "inolchiki",
+#ifdef USE_UNICODE_AGE_PROPERTIES
+ "age=9.0",
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ "incombiningdiacriticalmarksforsymbols",
+#ifdef USE_UNICODE_AGE_PROPERTIES
+ "age=5.1",
+ "age=5.0",
+ "age=16.0",
+ "age=5.2",
+ "age=8.0",
+ "age=13.0",
+ "age=6.1",
+ "age=6.0",
+ "age=6.2",
+ "age=3.1",
+ "age=3.0",
+ "age=3.2",
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ "inarabicmathematicalalphabeticsymbols",
+ "brah",
+ "tibetan",
+ "mtei",
+ "incoptic",
+ "manichaean",
+#ifdef USE_UNICODE_AGE_PROPERTIES
+ "age=6.3",
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ "emoji",
+ "oidc",
+ "incombiningdiacriticalmarkssupplement",
+ "idsu",
+ "saurashtra",
+ "inoldpermic",
+ "closepunctuation",
+ "incombininghalfmarks",
+ "incopticepactnumbers",
+ "elba",
+ "xdigit",
+#endif /* USE_UNICODE_PROPERTIES */
+ "cntrl",
+#ifndef USE_UNICODE_PROPERTIES
+ "space",
+ "xposixpunct",
+#else /* USE_UNICODE_PROPERTIES */
+ "bamu",
+ "xids",
+ "inoldhungarian",
+ "grext",
+ "mongolian",
+ "sterm",
+ "braille",
+ "inbuhid",
+ "elbasan",
+ "zanabazarsquare",
+ "incountingrodnumerals",
+ "inenclosedalphanumerics",
+ "incb=linker",
+ "taiviet",
+ "inelymaic",
+ "inethiopic",
+ "sgnw",
+ "olditalic",
+ "vith",
+ "grbase",
+ "hluw",
+ "intodhri",
+ "asciihexdigit",
+ "me",
+ "hmng",
+ "siddham",
+ "inenclosedalphanumericsupplement",
+ "taile",
+ "nagm",
+ "hang",
+ "inscriptionalparthian",
+ "inmongolian",
+ "innagmundari",
+ "sylo",
+ "ingunjalagondi",
+ "ingujarati",
+ "inbengali",
+ "khitansmallscript",
+ "xidcontinue",
+ "ingrantha",
+ "insinhalaarchaicnumbers",
+ "connectorpunctuation",
+ "inpalmyrene",
+ "incombiningdiacriticalmarksextended",
+ "xidstart",
+ "xidc",
+ "inancientgreekmusicalnotation",
+ "inancientgreeknumbers",
+ "intangsa",
+ "intags",
+ "inlepcha",
+ "caucasianalbanian",
+ "sylotinagri",
+ "emod",
+ "incaucasianalbanian",
+ "intagbanwa",
+ "mend",
+ "newa",
+ "inearlydynasticcuneiform",
+ "kaithi",
+ "intangut",
+ "mymr",
+ "inosage",
+ "inmahjongtiles",
+ "malayalam",
+ "sora",
+ "inbuginese",
+ "emojimodifierbase",
+ "induployan",
+ "ingeometricshapes",
+ "ingeneralpunctuation",
+ "myanmar",
+ "inlatin1supplement",
+ "ital",
+ "taml",
+ "inaegeannumbers",
+ "insharadasupplement",
+ "mathsymbol",
+ "inlimbu",
+ "invai",
+ "emojicomponent",
+ "insuttonsignwriting",
+ "digit",
+ "newtailue",
+ "inshavian",
+ "insogdian",
+ "indingbats",
+ "imperialaramaic",
+ "intulutigalari",
+ "incyprominoan",
+ "glagolitic",
+ "ebase",
+ "intaixuanjingsymbols",
+ "inbamumsupplement",
+ "gara",
+ "insyriacsupplement",
+ "casedletter",
+ "zzzz",
+ "inhiragana",
+ "tale",
+ "canadianaboriginal",
+ "ahex",
+ "inmayannumerals",
+ "inzanabazarsquare",
+ "inyiradicals",
+ "inscriptionalpahlavi",
+ "inalchemicalsymbols",
+ "inhatran",
+ "assigned",
+ "intaiviet",
+ "syrc",
+ "bopo",
+ "intirhuta",
+ "oldnortharabian",
+ "insupplementalmathematicaloperators",
+ "bopomofo",
+ "olonal",
+ "injavanese",
+ "insunuwar",
+ "inmathematicalalphanumericsymbols",
+ "inimperialaramaic",
+ "khmer",
+ "gonm",
+ "hyphen",
+ "insuperscriptsandsubscripts",
+ "inenclosedideographicsupplement",
+ "ingeometricshapesextended",
+ "insaurashtra",
+ "ogam",
+ "orya",
+ "saur",
+ "marchen",
+ "sundanese",
+ "khudawadi",
+ "soyo",
+ "whitespace",
+ "uideo",
+ "oldpersian",
+ "inyezidi",
+ "kiratrai",
+ "inlisusupplement",
+ "mero",
+ "symbol",
+ "soyombo",
+ "osmanya",
+ "indevanagari",
+ "unassigned",
+ "bengali",
+ "hebr",
+ "hebrew",
+ "inornamentaldingbats",
+ "invedicextensions",
+ "copt",
+ "ingreekextended",
+ "sund",
+ "cyprominoan",
+ "inherited",
+ "toto",
+ "inugaritic",
+ "syriac",
+ "cwt",
+ "inhebrew",
+ "runic",
+ "inmongoliansupplement",
+ "inshorthandformatcontrols",
+ "cypriot",
+ "cwcm",
+ "ingreekandcoptic",
+ "any",
+ "inolduyghur",
+ "inznamennymusicalnotation",
+ "lowercase",
+ "oldpermic",
+ "ingeorgian",
+ "ingurmukhi",
+ "emojimodifier",
+ "inkhojki",
+ "aghb",
+ "merc",
+ "inrejang",
+ "tamil",
+ "indevanagariextendeda",
+ "inalphabeticpresentationforms",
+ "hangul",
+ "inmeroitichieroglyphs",
+ "inkannada",
+ "hiragana",
+ "maka",
+ "inkanbun",
+ "insorasompeng",
+ "inmathematicaloperators",
+ "tayo",
+ "inhanunoo",
+ "multani",
+ "inkaithi",
+ "innushu",
+ "emojipresentation",
+ "insymbolsforlegacycomputing",
+ "meroiticcursive",
+ "grantha",
+ "inlinearbsyllabary",
+ "mult",
+ "taitham",
+ "nshu",
+ "incyrillicsupplement",
+ "dashpunctuation",
+ "inkatakana",
+ "inbatak",
+ "pi",
+ "mong",
+ "oldhungarian",
+ "phoenician",
+ "insmallformvariants",
+ "idsunaryoperator",
+ "variationselector",
+ "limbu",
+ "inyisyllables",
+ "diak",
+ "oldsoutharabian",
+ "lepc",
+ "inottomansiyaqnumbers",
+ "control",
+ "coptic",
+ "inkhmersymbols",
+ "titlecaseletter",
+ "inphagspa",
+ "bhks",
+ "gothic",
+ "sogo",
+ "elym",
+ "ps",
+ "prti",
+ "changeswhencasemapped",
+ "deseret",
+ "bhaiksuki",
+ "cyrl",
+ "olower",
+ "inchakma",
+ "wara",
+ "sogdian",
+ "graphemeclusterbreak=zwj",
+ "runr",
+ "changeswhentitlecased",
+ "incjkstrokes",
+ "incherokeesupplement",
+ "intangutcomponents",
+ "patws",
+ "batk",
+ "caseignorable",
+ "inkawi",
+ "indevanagariextended",
+ "indogra",
+ "intifinagh",
+ "print",
+ "cakm",
+ "graphemeclusterbreak=t",
+ "graphemeclusterbreak=lvt",
+ "inmendekikakui",
+ "inpsalterpahlavi",
+ "dogra",
+ "tangut",
+ "oalpha",
+ "intangutcomponentssupplement",
+ "idcompatmathcontinue",
+ "beriaerfe",
+ "ext",
+ "inkanasupplement",
+ "osge",
+ "inkanaextendeda",
+ "inverticalforms",
+ "decimalnumber",
+ "inkanaextendedb",
+ "idstrinaryoperator",
+ "tols",
+#endif /* USE_UNICODE_PROPERTIES */
+ "lower",
+#ifdef USE_UNICODE_PROPERTIES
+ "glag",
+ "inhanguljamo",
+ "insupplementalarrowsa",
+ "inmeeteimayek",
+ "insupplementalarrowsb",
+ "inunifiedcanadianaboriginalsyllabics",
+ "privateuse",
+ "inunifiedcanadianaboriginalsyllabicsextendeda",
+ "sentenceterminal",
+ "pcm",
+ "elymaic",
+ "cpmn",
+ "incjkcompatibilityforms",
+ "inphoneticextensions",
+ "incjkcompatibilityideographs",
+ "oldsogdian",
+ "inethiopicsupplement",
+ "graphemebase",
+ "intangutsupplement",
+ "tang",
+ "ideographic",
+ "nagmundari",
+ "sogd",
+ "psalterpahlavi",
+ "inphoneticextensionssupplement",
+ "tagb",
+ "invariationselectors",
+ "incjkcompatibilityideographssupplement",
+ "inindicsiyaqnumbers",
+ "khojki",
+ "inplayingcards",
+ "graphemeclusterbreak=extend",
+ "graphemeclusterbreak=prepend",
+ "space",
+ "tagbanwa",
+ "extpict",
+ "insupplementaryprivateuseareaa",
+ "insupplementalarrowsc",
+ "pd",
+ "insupplementaryprivateuseareab",
+ "innoblock",
+ "invariationselectorssupplement",
+ "inhanguljamoextendeda",
+ "kthi",
+ "inhanguljamoextendedb",
+ "sk",
+ "cherokee",
+ "nchar",
+ "pc",
+ "graphemeextend",
+ "wancho",
+ "inprivateusearea",
+ "sunuwar",
+ "ingothic",
+ "softdotted",
+ "lowercaseletter",
+ "phli",
+ "katakana",
+ "inunifiedcanadianaboriginalsyllabicsextended",
+ "hanifirohingya",
+ "palm",
+ "talu",
+ "inlisu",
+ "lu",
+ "invithkuqi",
+ "finalpunctuation",
+ "incyrillicextendeda",
+ "incyrillicextendedb",
+ "noncharactercodepoint",
+ "mark",
+ "medf",
+ "inkiratrai",
+ "intelugu",
+ "inmakasar",
+ "graphemeclusterbreak=l",
+ "inkharoshthi",
+ "graphemeclusterbreak=control",
+ "deprecated",
+ "insupplementalsymbolsandpictographs",
+ "tirh",
+ "sunu",
+ "letter",
+ "medefaidrin",
+ "beng",
+ "makasar",
+ "cwl",
+ "intakri",
+ "tavt",
+ "todr",
+ "todhri",
+ "insupplementalpunctuation",
+ "modifiersymbol",
+ "ogham",
+ "wcho",
+ "intagalog",
+ "omath",
+ "inkhmer",
+ "cf",
+ "bassavah",
+ "extendedpictographic",
+ "zyyy",
+ "incyrillicextendedc",
+ "ugaritic",
+ "goth",
+ "idcompatmathstart",
+ "divesakuru",
+ "wspace",
+ "geor",
+ "cyrillic",
+ "graphemeclusterbreak=cr",
+ "sorasompeng",
+ "graphemeclusterbreak=regionalindicator",
+ "tirhuta",
+ "inbopomofoextended",
+ "yezi",
+ "p",
+ "incyrillicextendedd",
+ "po",
+ "zp",
+ "dogr",
+ "dep",
+ "hung",
+ "term",
+ "deva",
+ "format",
+ "oldturkic",
+ "kayahli",
+ "devanagari",
+ "olck",
+ "dupl",
+ "incurrencysymbols",
+ "olchiki",
+ "inethiopicextendeda",
+ "inethiopicextendedb",
+ "phagspa",
+ "buhd",
+ "inhangulsyllables",
+ "inlatinextendedf",
+ "modifierletter",
+#endif /* USE_UNICODE_PROPERTIES */
+ "graph",
+#ifndef USE_UNICODE_PROPERTIES
+ "digit",
+ "blank"
+#else /* USE_UNICODE_PROPERTIES */
+ "ingaray",
+ "number",
+ "inkayahli",
+ "lepcha",
+ "plrd",
+ "incjksymbolsandpunctuation",
+ "ecomp",
+ "cuneiform",
+ "inglagolitic",
+ "gunjalagondi",
+ "bugi",
+ "takri",
+ "cprt",
+ "spaceseparator",
+ "ingurungkhema",
+ "incypriotsyllabary",
+ "inpaucinhau",
+ "gong",
+ "joinc",
+ "currencysymbol",
+ "rohg",
+ "logicalorderexception",
+ "grek",
+ "changeswhenlowercased",
+ "inpahawhhmong",
+ "yezidi",
+ "cwcf",
+ "extender",
+ "inhangulcompatibilityjamo",
+ "tulutigalari",
+ "terminalpunctuation",
+ "inkatakanaphoneticextensions",
+ "inethiopicextended",
+ "gujr",
+ "patsyn",
+ "ugar",
+ "word",
+ "berf",
+ "xpeo",
+ "regionalindicator",
+ "gujarati",
+ "buhid",
+ "inlatinextendedg",
+ "ethi",
+ "inkhitansmallscript",
+ "ingeorgiansupplement",
+ "inegyptianhieroglyphs",
+ "tifinagh",
+ "inegyptianhieroglyphsextendeda",
+ "inegyptianhieroglyphformatcontrols",
+ "inkhudawadi",
+ "incjkcompatibility",
+ "rjng",
+ "buginese",
+ "mendekikakui",
+ "letternumber",
+ "phlp",
+ "separator",
+ "pauc",
+ "vithkuqi",
+ "inkangxiradicals",
+ "changeswhencasefolded",
+ "graphemeclusterbreak=lf",
+ "joincontrol",
+ "inmeroiticcursive",
+ "pe",
+ "patternwhitespace",
+ "duployan",
+ "phag",
+ "meeteimayek",
+ "innyiakengpuachuehmong",
+ "incjkunifiedideographsextensioni",
+ "incjkunifiedideographs",
+ "incjkunifiedideographsextensionj",
+ "georgian",
+ "incjkunifiedideographsextensiona",
+ "incjkunifiedideographsextensionb",
+ "warangciti",
+ "inhighprivateusesurrogates",
+ "meroitichieroglyphs",
+ "java",
+ "garay",
+ "nonspacingmark",
+ "otheridstart",
+ "otheridcontinue",
+ "xsux",
+ "phnx",
+ "incjkunifiedideographsextensione",
+ "signwriting",
+ "tolongsiki",
+ "incjkunifiedideographsextensionc",
+ "combiningmark",
+ "nushu",
+ "takr",
+ "tfng",
+ "changeswhenuppercased",
+ "inglagoliticsupplement",
+ "surrogate",
+ "orkh",
+ "graphemeclusterbreak=v",
+ "graphemeclusterbreak=lv",
+ "incjkunifiedideographsextensiond",
+ "telu",
+ "inhalfwidthandfullwidthforms",
+ "otheralphabetic",
+ "unknown",
+ "punct",
+ "tglg",
+ "javanese",
+ "otherdefaultignorablecodepoint",
+ "cwu",
+ "rejang",
+ "egyp",
+ "perm",
+ "othersymbol",
+ "epres",
+ "olduyghur",
+ "tutg",
+ "enclosingmark",
+ "ingeorgianextended",
+ "ogrext",
+ "indivesakuru",
+ "otherlowercase",
+ "other",
+ "othernumber",
+ "hexdigit",
+ "incjkradicalssupplement",
+ "blank",
+ "ethiopic",
+ "graphemeclusterbreak=spacingmark",
+ "spacingmark",
+ "tagalog",
+ "batak",
+ "guru",
+ "hex",
+ "paucinhau",
+ "modifiercombiningmark",
+ "otherpunctuation",
+ "ougr",
+ "palmyrene",
+ "othermath",
+ "incjkunifiedideographsextensionh",
+ "inboxdrawing",
+ "patternsyntax",
+ "oupper",
+ "gurungkhema",
+ "prependedconcatenationmark",
+ "otherletter",
+ "pf",
+ "qmark",
+ "inhighsurrogates",
+ "xposixpunct",
+ "otheruppercase",
+ "incjkunifiedideographsextensionf",
+ "punctuation",
+ "incjkunifiedideographsextensiong",
+ "egyptianhieroglyphs",
+ "defaultignorablecodepoint",
+ "quotationmark",
+ "openpunctuation",
+ "unifiedideograph",
+ "greek",
+ "othergraphemeextend",
+ "inkaktoviknumerals",
+ "uppercase",
+ "grlink",
+ "nyiakengpuachuehmong",
+ "gukh",
+ "pahawhhmong",
+ "upper",
+ "uppercaseletter",
+ "graphemelink",
+ "telugu",
+ "gurmukhi",
+ "paragraphseparator"
+#endif /* USE_UNICODE_PROPERTIES */
+ };
+#define uniname2ctype_pool ((const char *) &uniname2ctype_pool_contents)
+const struct uniname2ctype_struct *
+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},
+ {uniname2ctype_offset(str10), 35},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str16), 31},
+ {-1}, {-1},
+ {uniname2ctype_offset(str19), 34},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str24), 27},
+ {-1}, {-1},
+ {uniname2ctype_offset(str27), 606},
+ {uniname2ctype_offset(str28), 354},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str33), 192},
+ {uniname2ctype_offset(str34), 192},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str38), 288},
+ {-1},
+ {uniname2ctype_offset(str40), 98},
+ {uniname2ctype_offset(str41), 98},
+ {-1}, {-1},
+ {uniname2ctype_offset(str44), 203},
+ {uniname2ctype_offset(str45), 120},
+ {-1},
+ {uniname2ctype_offset(str47), 176},
+ {uniname2ctype_offset(str48), 113},
+ {-1},
+ {uniname2ctype_offset(str50), 613},
+ {uniname2ctype_offset(str51), 113},
+ {uniname2ctype_offset(str52), 189},
+ {uniname2ctype_offset(str53), 187},
+ {-1}, {-1},
+ {uniname2ctype_offset(str56), 575},
+ {uniname2ctype_offset(str57), 120},
+ {uniname2ctype_offset(str58), 123},
+ {uniname2ctype_offset(str59), 125},
+ {uniname2ctype_offset(str60), 539},
+ {-1},
+ {uniname2ctype_offset(str62), 13},
+ {uniname2ctype_offset(str63), 164},
+ {uniname2ctype_offset(str64), 227},
+ {-1}, {-1},
+ {uniname2ctype_offset(str67), 82},
+ {-1},
+ {uniname2ctype_offset(str69), 155},
+ {uniname2ctype_offset(str70), 218},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str74), 518},
+#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(str81), 355},
+ {uniname2ctype_offset(str82), 587},
+ {uniname2ctype_offset(str83), 82},
+ {-1},
+ {uniname2ctype_offset(str85), 50},
+ {-1}, {-1},
+ {uniname2ctype_offset(str88), 589},
+ {uniname2ctype_offset(str89), 47},
+ {uniname2ctype_offset(str90), 529},
+ {-1},
+ {uniname2ctype_offset(str92), 55},
+ {uniname2ctype_offset(str93), 338},
+ {-1}, {-1},
+ {uniname2ctype_offset(str96), 415},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str102), 84},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str107), 631},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str115), 79},
+ {-1},
+ {uniname2ctype_offset(str117), 370},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str124), 79},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1},
+ {uniname2ctype_offset(str135), 127},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str141), 44},
+ {-1}, {-1},
+ {uniname2ctype_offset(str144), 205},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str149), 71},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str155), 353},
+ {-1},
+ {uniname2ctype_offset(str157), 643},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str164), 194},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str169), 394},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str175), 493},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str180), 429},
+ {uniname2ctype_offset(str181), 499},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str186), 67},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str190), 264},
+ {uniname2ctype_offset(str191), 348},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str195), 270},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str199), 662},
+ {-1}, {-1},
+ {uniname2ctype_offset(str202), 614},
+ {uniname2ctype_offset(str203), 540},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str209), 342},
+ {-1},
+ {uniname2ctype_offset(str211), 520},
+ {-1},
+ {uniname2ctype_offset(str213), 420},
+ {-1},
+ {uniname2ctype_offset(str215), 130},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str219), 161},
+ {uniname2ctype_offset(str220), 477},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str227), 444},
+ {uniname2ctype_offset(str228), 171},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str235), 271},
+ {-1},
+ {uniname2ctype_offset(str237), 181},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str242), 172},
+ {-1},
+ {uniname2ctype_offset(str244), 660},
+ {-1}, {-1},
+ {uniname2ctype_offset(str247), 468},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str257), 372},
+ {uniname2ctype_offset(str258), 350},
+ {-1},
+ {uniname2ctype_offset(str260), 194},
+ {uniname2ctype_offset(str261), 21},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str267), 506},
+ {uniname2ctype_offset(str268), 61},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str274), 14},
+ {uniname2ctype_offset(str275), 289},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str279), 263},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str284), 571},
+ {uniname2ctype_offset(str285), 147},
+ {uniname2ctype_offset(str286), 147},
+ {uniname2ctype_offset(str287), 154},
+ {-1},
+ {uniname2ctype_offset(str289), 478},
+ {-1},
+ {uniname2ctype_offset(str291), 227},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str295), 476},
+ {-1}, {-1},
+ {uniname2ctype_offset(str298), 172},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1},
+ {uniname2ctype_offset(str310), 105},
+ {-1},
+ {uniname2ctype_offset(str312), 551},
+ {-1}, {-1},
+ {uniname2ctype_offset(str315), 230},
+ {-1},
+ {uniname2ctype_offset(str317), 568},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str333), 173},
+ {-1},
+ {uniname2ctype_offset(str335), 596},
+ {uniname2ctype_offset(str336), 284},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str340), 23},
+ {-1},
+ {uniname2ctype_offset(str342), 200},
+ {-1},
+ {uniname2ctype_offset(str344), 127},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str359), 501},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str364), 667},
+ {-1},
+ {uniname2ctype_offset(str366), 157},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str373), 423},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1},
+ {uniname2ctype_offset(str384), 36},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1},
+ {uniname2ctype_offset(str395), 177},
+ {-1}, {-1},
+ {uniname2ctype_offset(str398), 425},
+ {-1},
+ {uniname2ctype_offset(str400), 427},
+ {-1},
+ {uniname2ctype_offset(str402), 248},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str406), 431},
+ {uniname2ctype_offset(str407), 433},
+ {-1}, {-1},
+ {uniname2ctype_offset(str410), 84},
+ {-1},
+ {uniname2ctype_offset(str412), 659},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str416), 18},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str424), 25},
+ {uniname2ctype_offset(str425), 32},
+ {uniname2ctype_offset(str426), 611},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str432), 574},
+ {uniname2ctype_offset(str433), 397},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str438), 655},
+ {-1},
+ {uniname2ctype_offset(str440), 668},
+ {uniname2ctype_offset(str441), 644},
+ {-1}, {-1},
+ {uniname2ctype_offset(str444), 511},
+ {-1}, {-1},
+ {uniname2ctype_offset(str447), 465},
+ {uniname2ctype_offset(str448), 76},
+ {-1}, {-1},
+ {uniname2ctype_offset(str451), 277},
+ {uniname2ctype_offset(str452), 356},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str456), 628},
+ {-1},
+ {uniname2ctype_offset(str458), 143},
+ {uniname2ctype_offset(str459), 143},
+ {uniname2ctype_offset(str460), 24},
+ {uniname2ctype_offset(str461), 480},
+ {uniname2ctype_offset(str462), 37},
+ {uniname2ctype_offset(str463), 53},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str468), 26},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str472), 371},
+ {uniname2ctype_offset(str473), 186},
+ {-1}, {-1},
+ {uniname2ctype_offset(str476), 68},
+ {uniname2ctype_offset(str477), 391},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str483), 646},
+ {-1},
+ {uniname2ctype_offset(str485), 48},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str491), 516},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str496), 597},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str502), 243},
+ {-1}, {-1},
+ {uniname2ctype_offset(str505), 359},
+ {-1}, {-1},
+ {uniname2ctype_offset(str508), 544},
+ {-1},
+ {uniname2ctype_offset(str510), 157},
+ {uniname2ctype_offset(str511), 358},
+ {uniname2ctype_offset(str512), 368},
+ {uniname2ctype_offset(str513), 138},
+ {uniname2ctype_offset(str514), 111},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str523), 650},
+ {-1},
+ {uniname2ctype_offset(str525), 68},
+ {-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(str549), 570},
+ {-1},
+ {uniname2ctype_offset(str551), 365},
+ {-1},
+ {uniname2ctype_offset(str553), 564},
+ {uniname2ctype_offset(str554), 591},
+ {-1},
+ {uniname2ctype_offset(str556), 232},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str571), 77},
+ {-1}, {-1},
+ {uniname2ctype_offset(str574), 248},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str584), 199},
+ {-1}, {-1},
+ {uniname2ctype_offset(str587), 419},
+ {uniname2ctype_offset(str588), 533},
+ {-1}, {-1},
+ {uniname2ctype_offset(str591), 96},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str605), 340},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1},
+ {uniname2ctype_offset(str617), 341},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str622), 209},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str630), 209},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str635), 524},
+ {-1},
+ {uniname2ctype_offset(str637), 595},
+ {uniname2ctype_offset(str638), 396},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str645), 343},
+ {-1}, {-1},
+ {uniname2ctype_offset(str648), 550},
+ {-1},
+ {uniname2ctype_offset(str650), 508},
+ {-1}, {-1},
+ {uniname2ctype_offset(str653), 139},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1},
+ {uniname2ctype_offset(str665), 110},
+ {-1},
+ {uniname2ctype_offset(str667), 19},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str674), 623},
+ {uniname2ctype_offset(str675), 390},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str681), 118},
+ {uniname2ctype_offset(str682), 373},
+ {-1},
+ {uniname2ctype_offset(str684), 193},
+ {-1}, {-1},
+ {uniname2ctype_offset(str687), 416},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str701), 187},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str707), 125},
+ {-1},
+ {uniname2ctype_offset(str709), 561},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str716), 548},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str721), 215},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str727), 205},
+ {-1},
+ {uniname2ctype_offset(str729), 94},
+ {uniname2ctype_offset(str730), 159},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str734), 239},
+ {uniname2ctype_offset(str735), 532},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1},
+ {uniname2ctype_offset(str747), 159},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str751), 165},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str760), 38},
+ {-1},
+ {uniname2ctype_offset(str762), 253},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str766), 28},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str780), 228},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str784), 244},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str788), 489},
+ {uniname2ctype_offset(str789), 94},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str795), 503},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str799), 414},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str803), 60},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str809), 448},
+ {uniname2ctype_offset(str810), 612},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str815), 53},
+ {-1},
+ {uniname2ctype_offset(str817), 52},
+ {uniname2ctype_offset(str818), 627},
+ {-1},
+ {uniname2ctype_offset(str820), 381},
+ {uniname2ctype_offset(str821), 509},
+ {-1},
+ {uniname2ctype_offset(str823), 482},
+ {-1},
+ {uniname2ctype_offset(str825), 588},
+ {-1},
+ {uniname2ctype_offset(str827), 51},
+ {uniname2ctype_offset(str828), 211},
+ {uniname2ctype_offset(str829), 91},
+ {uniname2ctype_offset(str830), 554},
+ {-1},
+ {uniname2ctype_offset(str832), 114},
+ {uniname2ctype_offset(str833), 351},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str838), 114},
+ {-1},
+ {uniname2ctype_offset(str840), 1},
+ {-1},
+ {uniname2ctype_offset(str842), 132},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str852), 403},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str857), 128},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str880), 418},
+ {-1}, {-1},
+ {uniname2ctype_offset(str883), 67},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str890), 454},
+ {uniname2ctype_offset(str891), 435},
+ {-1}, {-1},
+ {uniname2ctype_offset(str894), 117},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str898), 275},
+ {-1}, {-1},
+ {uniname2ctype_offset(str901), 230},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str909), 152},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str919), 579},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str923), 139},
+ {uniname2ctype_offset(str924), 577},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str929), 531},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1},
+ {uniname2ctype_offset(str940), 149},
+ {-1},
+ {uniname2ctype_offset(str942), 538},
+ {-1},
+ {uniname2ctype_offset(str944), 273},
+ {uniname2ctype_offset(str945), 152},
+ {-1},
+ {uniname2ctype_offset(str947), 270},
+ {-1},
+ {uniname2ctype_offset(str949), 177},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str954), 537},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1},
+ {uniname2ctype_offset(str966), 264},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str970), 95},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str975), 118},
+ {-1}, {-1},
+ {uniname2ctype_offset(str978), 507},
+ {-1},
+ {uniname2ctype_offset(str980), 346},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str985), 542},
+ {-1}, {-1},
+ {uniname2ctype_offset(str988), 581},
+ {-1},
+ {uniname2ctype_offset(str990), 541},
+ {uniname2ctype_offset(str991), 364},
+ {-1}, {-1},
+ {uniname2ctype_offset(str994), 151},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str999), 380},
+ {-1},
+ {uniname2ctype_offset(str1001), 188},
+ {-1},
+ {uniname2ctype_offset(str1003), 184},
+ {-1},
+ {uniname2ctype_offset(str1005), 560},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1009), 22},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1012), 104},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1016), 57},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1021), 369},
+ {uniname2ctype_offset(str1022), 191},
+ {-1},
+ {uniname2ctype_offset(str1024), 556},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1028), 278},
+ {-1},
+ {uniname2ctype_offset(str1030), 151},
+ {uniname2ctype_offset(str1031), 188},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1036), 78},
+ {uniname2ctype_offset(str1037), 647},
+ {uniname2ctype_offset(str1038), 546},
+ {-1},
+ {uniname2ctype_offset(str1040), 608},
+ {uniname2ctype_offset(str1041), 96},
+ {uniname2ctype_offset(str1042), 279},
+ {-1},
+ {uniname2ctype_offset(str1044), 408},
+ {uniname2ctype_offset(str1045), 457},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1048), 515},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1056), 253},
+ {uniname2ctype_offset(str1057), 56},
+ {uniname2ctype_offset(str1058), 352},
+ {uniname2ctype_offset(str1059), 97},
+ {-1},
+ {uniname2ctype_offset(str1061), 466},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1064), 249},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1068), 160},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1072), 236},
+ {uniname2ctype_offset(str1073), 378},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1077), 86},
+ {-1},
+ {uniname2ctype_offset(str1079), 153},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1087), 464},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1090), 108},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1094), 630},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1102), 29},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1105), 138},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1109), 86},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1113), 213},
+ {-1},
+ {uniname2ctype_offset(str1115), 153},
+ {-1},
+ {uniname2ctype_offset(str1117), 603},
+#ifndef USE_UNICODE_AGE_PROPERTIES
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+#else /* USE_UNICODE_AGE_PROPERTIES */
+ {-1}, {-1},
+ {uniname2ctype_offset(str1120), 316},
+ {uniname2ctype_offset(str1121), 315},
+ {uniname2ctype_offset(str1122), 318},
+ {uniname2ctype_offset(str1123), 317},
+ {-1},
+ {uniname2ctype_offset(str1125), 297},
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ {uniname2ctype_offset(str1126), 467},
+ {uniname2ctype_offset(str1127), 204},
+#ifndef USE_UNICODE_AGE_PROPERTIES
+ {-1}, {-1}, {-1},
+#else /* USE_UNICODE_AGE_PROPERTIES */
+ {uniname2ctype_offset(str1128), 299},
+ {uniname2ctype_offset(str1129), 298},
+ {uniname2ctype_offset(str1130), 320},
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ {uniname2ctype_offset(str1131), 236},
+ {uniname2ctype_offset(str1132), 255},
+ {uniname2ctype_offset(str1133), 344},
+#ifndef USE_UNICODE_AGE_PROPERTIES
+ {-1}, {-1}, {-1},
+#else /* USE_UNICODE_AGE_PROPERTIES */
+ {uniname2ctype_offset(str1134), 324},
+ {uniname2ctype_offset(str1135), 304},
+ {uniname2ctype_offset(str1136), 303},
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ {uniname2ctype_offset(str1137), 99},
+#ifndef USE_UNICODE_AGE_PROPERTIES
+ {-1}, {-1}, {-1},
+#else /* USE_UNICODE_AGE_PROPERTIES */
+ {uniname2ctype_offset(str1138), 322},
+ {uniname2ctype_offset(str1139), 321},
+ {uniname2ctype_offset(str1140), 312},
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ {uniname2ctype_offset(str1141), 400},
+#ifndef USE_UNICODE_AGE_PROPERTIES
+ {-1},
+#else /* USE_UNICODE_AGE_PROPERTIES */
+ {uniname2ctype_offset(str1142), 314},
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ {uniname2ctype_offset(str1143), 413},
+#ifndef USE_UNICODE_AGE_PROPERTIES
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+#else /* USE_UNICODE_AGE_PROPERTIES */
+ {uniname2ctype_offset(str1144), 306},
+ {uniname2ctype_offset(str1145), 305},
+ {uniname2ctype_offset(str1146), 323},
+ {uniname2ctype_offset(str1147), 307},
+ {uniname2ctype_offset(str1148), 313},
+ {-1},
+ {uniname2ctype_offset(str1150), 319},
+ {uniname2ctype_offset(str1151), 309},
+ {uniname2ctype_offset(str1152), 308},
+ {-1},
+ {uniname2ctype_offset(str1154), 310},
+ {uniname2ctype_offset(str1155), 301},
+ {uniname2ctype_offset(str1156), 300},
+ {-1},
+ {uniname2ctype_offset(str1158), 302},
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ {uniname2ctype_offset(str1159), 653},
+ {uniname2ctype_offset(str1160), 171},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1170), 99},
+ {-1},
+ {uniname2ctype_offset(str1172), 163},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1175), 436},
+ {uniname2ctype_offset(str1176), 189},
+#ifndef USE_UNICODE_AGE_PROPERTIES
+ {-1}, {-1}, {-1}, {-1}, {-1},
+#else /* USE_UNICODE_AGE_PROPERTIES */
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1181), 311},
+#endif /* USE_UNICODE_AGE_PROPERTIES */
+ {uniname2ctype_offset(str1182), 290},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1187), 280},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1191), 407},
+ {uniname2ctype_offset(str1192), 272},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1195), 148},
+ {uniname2ctype_offset(str1196), 513},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1199), 42},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1209), 496},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1214), 510},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1221), 183},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1225), 11},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1228), 3},
+ {uniname2ctype_offset(str1229), 161},
+ {uniname2ctype_offset(str1230), 69},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1239), 545},
+ {-1},
+ {uniname2ctype_offset(str1241), 72},
+ {uniname2ctype_offset(str1242), 109},
+ {uniname2ctype_offset(str1243), 283},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1249), 130},
+ {-1},
+ {uniname2ctype_offset(str1251), 384},
+ {uniname2ctype_offset(str1252), 183},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1259), 218},
+ {uniname2ctype_offset(str1260), 636},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1264), 421},
+ {uniname2ctype_offset(str1265), 75},
+ {-1},
+ {uniname2ctype_offset(str1267), 156},
+ {-1},
+ {uniname2ctype_offset(str1269), 555},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1272), 376},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1275), 208},
+ {-1},
+ {uniname2ctype_offset(str1277), 115},
+ {-1},
+ {uniname2ctype_offset(str1279), 238},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1285), 73},
+ {uniname2ctype_offset(str1286), 204},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1292), 523},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1299), 261},
+ {-1},
+ {uniname2ctype_offset(str1301), 33},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1},
+ {uniname2ctype_offset(str1312), 185},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1315), 199},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1321), 657},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1324), 124},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1328), 240},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1332), 102},
+ {-1},
+ {uniname2ctype_offset(str1334), 166},
+ {uniname2ctype_offset(str1335), 387},
+ {uniname2ctype_offset(str1336), 645},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1339), 136},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1347), 590},
+ {-1},
+ {uniname2ctype_offset(str1349), 363},
+ {uniname2ctype_offset(str1350), 361},
+ {uniname2ctype_offset(str1351), 232},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1357), 70},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1362), 566},
+ {uniname2ctype_offset(str1363), 562},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1368), 40},
+ {-1},
+ {uniname2ctype_offset(str1370), 528},
+ {uniname2ctype_offset(str1371), 395},
+ {uniname2ctype_offset(str1372), 69},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1375), 70},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1397), 632},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1401), 505},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1407), 607},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1415), 680},
+ {uniname2ctype_offset(str1416), 399},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1420), 180},
+ {uniname2ctype_offset(str1421), 136},
+ {-1},
+ {uniname2ctype_offset(str1423), 292},
+ {-1},
+ {uniname2ctype_offset(str1425), 521},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1429), 385},
+ {uniname2ctype_offset(str1430), 190},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1433), 212},
+ {-1},
+ {uniname2ctype_offset(str1435), 598},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1447), 169},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1453), 615},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1456), 100},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1462), 519},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1467), 654},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1470), 95},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1473), 178},
+ {uniname2ctype_offset(str1474), 393},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1479), 293},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1489), 625},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1497), 424},
+ {uniname2ctype_offset(str1498), 410},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1503), 100},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1510), 339},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1515), 115},
+ {uniname2ctype_offset(str1516), 92},
+ {uniname2ctype_offset(str1517), 504},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1},
+ {uniname2ctype_offset(str1528), 585},
+ {-1},
+ {uniname2ctype_offset(str1530), 50},
+ {-1},
+ {uniname2ctype_offset(str1532), 389},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1535), 462},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1551), 294},
+ {uniname2ctype_offset(str1552), 638},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1},
+ {uniname2ctype_offset(str1572), 4},
+ {uniname2ctype_offset(str1573), 133},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1581), 517},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1588), 552},
+ {uniname2ctype_offset(str1589), 426},
+ {uniname2ctype_offset(str1590), 164},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1598), 567},
+ {-1},
+ {uniname2ctype_offset(str1600), 599},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1606), 134},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1614), 293},
+ {uniname2ctype_offset(str1615), 635},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1618), 605},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1626), 241},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1633), 357},
+ {uniname2ctype_offset(str1634), 25},
+ {-1},
+ {uniname2ctype_offset(str1636), 296},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1639), 446},
+ {uniname2ctype_offset(str1640), 124},
+ {uniname2ctype_offset(str1641), 105},
+ {uniname2ctype_offset(str1642), 261},
+ {-1},
+ {uniname2ctype_offset(str1644), 634},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1648), 580},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1654), 460},
+ {uniname2ctype_offset(str1655), 167},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1668), 663},
+ {uniname2ctype_offset(str1669), 530},
+ {uniname2ctype_offset(str1670), 17},
+ {uniname2ctype_offset(str1671), 479},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1674), 85},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1682), 112},
+ {-1},
+ {uniname2ctype_offset(str1684), 569},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1688), 193},
+ {-1},
+ {uniname2ctype_offset(str1690), 432},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1694), 112},
+ {-1},
+ {uniname2ctype_offset(str1696), 244},
+ {uniname2ctype_offset(str1697), 475},
+ {uniname2ctype_offset(str1698), 586},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1707), 637},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1713), 527},
+ {uniname2ctype_offset(str1714), 108},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1724), 215},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1727), 256},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1731), 411},
+ {-1},
+ {uniname2ctype_offset(str1733), 658},
+ {-1},
+ {uniname2ctype_offset(str1735), 664},
+ {-1},
+ {uniname2ctype_offset(str1737), 470},
+ {uniname2ctype_offset(str1738), 106},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1746), 91},
+ {-1},
+ {uniname2ctype_offset(str1748), 148},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1754), 211},
+ {uniname2ctype_offset(str1755), 144},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1762), 200},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1},
+ {uniname2ctype_offset(str1773), 217},
+ {-1},
+ {uniname2ctype_offset(str1775), 252},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1778), 274},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1785), 137},
+ {-1},
+ {uniname2ctype_offset(str1787), 549},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1790), 243},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1793), 594},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1796), 175},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1800), 47},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1},
+ {uniname2ctype_offset(str1811), 217},
+ {uniname2ctype_offset(str1812), 128},
+ {-1},
+ {uniname2ctype_offset(str1814), 360},
+ {-1},
+ {uniname2ctype_offset(str1816), 21},
+ {-1},
+ {uniname2ctype_offset(str1818), 88},
+ {uniname2ctype_offset(str1819), 83},
+ {-1},
+ {uniname2ctype_offset(str1821), 83},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1824), 661},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1829), 404},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1834), 132},
+ {-1},
+ {uniname2ctype_offset(str1836), 409},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1839), 144},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1847), 234},
+ {uniname2ctype_offset(str1848), 118},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1854), 237},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1858), 514},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1863), 85},
+ {uniname2ctype_offset(str1864), 64},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1867), 349},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1872), 107},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1877), 572},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1884), 626},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1900), 129},
+ {uniname2ctype_offset(str1901), 66},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1910), 345},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1920), 16},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1923), 553},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1936), 629},
+ {uniname2ctype_offset(str1937), 58},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1941), 197},
+ {-1},
+ {uniname2ctype_offset(str1943), 374},
+ {-1},
+ {uniname2ctype_offset(str1945), 362},
+ {-1},
+ {uniname2ctype_offset(str1947), 292},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1956), 563},
+ {-1},
+ {uniname2ctype_offset(str1958), 180},
+ {-1},
+ {uniname2ctype_offset(str1960), 174},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1966), 473},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1969), 92},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1972), 584},
+ {-1},
+ {uniname2ctype_offset(str1974), 492},
+ {uniname2ctype_offset(str1975), 102},
+ {-1},
+ {uniname2ctype_offset(str1977), 534},
+ {uniname2ctype_offset(str1978), 367},
+ {uniname2ctype_offset(str1979), 110},
+ {uniname2ctype_offset(str1980), 221},
+ {-1}, {-1},
+ {uniname2ctype_offset(str1983), 450},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str1987), 558},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2001), 417},
+ {uniname2ctype_offset(str2002), 249},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2005), 383},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2010), 206},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2015), 557},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2022), 624},
+ {uniname2ctype_offset(str2023), 291},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2028), 669},
+ {uniname2ctype_offset(str2029), 174},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2037), 184},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2040), 502},
+ {uniname2ctype_offset(str2041), 206},
+ {uniname2ctype_offset(str2042), 155},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2047), 216},
+ {-1},
+ {uniname2ctype_offset(str2049), 347},
+ {-1},
+ {uniname2ctype_offset(str2051), 41},
+ {-1},
+ {uniname2ctype_offset(str2053), 447},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2056), 398},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2059), 44},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2064), 109},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2074), 207},
+ {-1},
+ {uniname2ctype_offset(str2076), 141},
+ {uniname2ctype_offset(str2077), 498},
+ {uniname2ctype_offset(str2078), 272},
+ {-1},
+ {uniname2ctype_offset(str2080), 284},
+ {uniname2ctype_offset(str2081), 123},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2085), 459},
+ {-1},
+ {uniname2ctype_offset(str2087), 231},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2090), 165},
+ {-1},
+ {uniname2ctype_offset(str2092), 145},
+ {uniname2ctype_offset(str2093), 652},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2097), 19},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2102), 132},
+ {-1},
+ {uniname2ctype_offset(str2104), 392},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2107), 29},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2110), 469},
+ {uniname2ctype_offset(str2111), 210},
+ {-1},
+ {uniname2ctype_offset(str2113), 116},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2117), 225},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2122), 226},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2131), 46},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2137), 166},
+ {uniname2ctype_offset(str2138), 66},
+ {-1},
+ {uniname2ctype_offset(str2140), 117},
+ {-1},
+ {uniname2ctype_offset(str2142), 210},
+ {uniname2ctype_offset(str2143), 81},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2147), 266},
+ {uniname2ctype_offset(str2148), 559},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2152), 202},
+ {uniname2ctype_offset(str2153), 224},
+ {-1},
+ {uniname2ctype_offset(str2155), 337},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2164), 107},
+ {uniname2ctype_offset(str2165), 64},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2168), 452},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2176), 483},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2179), 616},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2182), 285},
+ {uniname2ctype_offset(str2183), 170},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2186), 61},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2191), 593},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2199), 471},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2203), 576},
+ {uniname2ctype_offset(str2204), 438},
+ {-1},
+ {uniname2ctype_offset(str2206), 7},
+ {uniname2ctype_offset(str2207), 173},
+ {-1},
+ {uniname2ctype_offset(str2209), 334},
+ {-1},
+ {uniname2ctype_offset(str2211), 336},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2214), 649},
+ {-1},
+ {uniname2ctype_offset(str2216), 543},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2224), 219},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2228), 214},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2235), 262},
+ {-1},
+ {uniname2ctype_offset(str2237), 619},
+ {-1},
+ {uniname2ctype_offset(str2239), 281},
+ {-1},
+ {uniname2ctype_offset(str2241), 251},
+ {-1},
+ {uniname2ctype_offset(str2243), 265},
+ {uniname2ctype_offset(str2244), 621},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2247), 213},
+ {uniname2ctype_offset(str2248), 622},
+ {uniname2ctype_offset(str2249), 495},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2252), 36},
+ {-1},
+ {uniname2ctype_offset(str2254), 620},
+ {uniname2ctype_offset(str2255), 271},
+ {-1},
+ {uniname2ctype_offset(str2257), 250},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2260), 6},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2270), 134},
+ {-1},
+ {uniname2ctype_offset(str2272), 375},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2279), 428},
+ {-1},
+ {uniname2ctype_offset(str2281), 484},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2285), 430},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2288), 379},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2296), 22},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2299), 582},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2302), 283},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2308), 287},
+ {uniname2ctype_offset(str2309), 226},
+ {uniname2ctype_offset(str2310), 234},
+ {-1},
+ {uniname2ctype_offset(str2312), 497},
+ {uniname2ctype_offset(str2313), 405},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2317), 491},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2320), 225},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2341), 377},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2345), 73},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2350), 618},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2353), 214},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2361), 263},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2364), 240},
+ {-1},
+ {uniname2ctype_offset(str2366), 224},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2370), 198},
+ {uniname2ctype_offset(str2371), 406},
+ {-1},
+ {uniname2ctype_offset(str2373), 122},
+ {uniname2ctype_offset(str2374), 494},
+ {uniname2ctype_offset(str2375), 676},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2379), 651},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2389), 186},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2392), 656},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2396), 329},
+ {uniname2ctype_offset(str2397), 325},
+ {uniname2ctype_offset(str2398), 9},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2401), 122},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2416), 295},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2421), 682},
+ {uniname2ctype_offset(str2422), 665},
+ {-1},
+ {uniname2ctype_offset(str2424), 41},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2427), 683},
+ {uniname2ctype_offset(str2428), 684},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2432), 681},
+ {uniname2ctype_offset(str2433), 474},
+ {uniname2ctype_offset(str2434), 169},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2439), 486},
+ {uniname2ctype_offset(str2440), 49},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2443), 104},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2451), 268},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2458), 40},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2466), 72},
+ {-1},
+ {uniname2ctype_offset(str2468), 229},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2473), 490},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2483), 245},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2491), 512},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2495), 277},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2503), 26},
+ {-1},
+ {uniname2ctype_offset(str2505), 167},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2518), 111},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2526), 388},
+ {-1},
+ {uniname2ctype_offset(str2528), 223},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2532), 195},
+ {-1},
+ {uniname2ctype_offset(str2534), 133},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2541), 461},
+ {-1},
+ {uniname2ctype_offset(str2543), 30},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2553), 522},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2570), 43},
+ {uniname2ctype_offset(str2571), 440},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2577), 463},
+ {-1},
+ {uniname2ctype_offset(str2579), 268},
+ {-1},
+ {uniname2ctype_offset(str2581), 31},
+ {uniname2ctype_offset(str2582), 222},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2590), 610},
+ {uniname2ctype_offset(str2591), 366},
+ {uniname2ctype_offset(str2592), 592},
+ {uniname2ctype_offset(str2593), 332},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2596), 536},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2599), 328},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2603), 276},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2612), 666},
+ {uniname2ctype_offset(str2613), 201},
+ {uniname2ctype_offset(str2614), 245},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2618), 24},
+ {uniname2ctype_offset(str2619), 222},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2625), 88},
+ {uniname2ctype_offset(str2626), 221},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2632), 62},
+ {uniname2ctype_offset(str2633), 573},
+ {uniname2ctype_offset(str2634), 156},
+ {-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(str2658), 246},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2668), 246},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2671), 441},
+ {uniname2ctype_offset(str2672), 49},
+ {uniname2ctype_offset(str2673), 106},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2679), 229},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2688), 382},
+ {uniname2ctype_offset(str2689), 259},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2699), 386},
+ {uniname2ctype_offset(str2700), 20},
+ {uniname2ctype_offset(str2701), 181},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2705), 295},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2708), 78},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2714), 401},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1},
+ {uniname2ctype_offset(str2725), 126},
+ {uniname2ctype_offset(str2726), 116},
+ {-1},
+ {uniname2ctype_offset(str2728), 282},
+ {uniname2ctype_offset(str2729), 231},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2732), 252},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2737), 101},
+ {-1}, {-1}, {-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(str2764), 81},
+ {uniname2ctype_offset(str2765), 326},
+ {-1},
+ {uniname2ctype_offset(str2767), 178},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2780), 330},
+ {-1},
+ {uniname2ctype_offset(str2782), 201},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2791), 451},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2796), 233},
+ {-1},
+ {uniname2ctype_offset(str2798), 39},
+ {uniname2ctype_offset(str2799), 641},
+ {uniname2ctype_offset(str2800), 45},
+ {uniname2ctype_offset(str2801), 54},
+ {uniname2ctype_offset(str2802), 219},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2806), 276},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2813), 207},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2819), 258},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2826), 87},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2831), 20},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2835), 168},
+ {uniname2ctype_offset(str2836), 149},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2844), 87},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2850), 146},
+ {-1},
+ {uniname2ctype_offset(str2852), 182},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2857), 412},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2861), 146},
+ {-1},
+ {uniname2ctype_offset(str2863), 481},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2869), 648},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2872), 142},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2877), 121},
+ {uniname2ctype_offset(str2878), 485},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2881), 525},
+ {-1},
+ {uniname2ctype_offset(str2883), 27},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1},
+ {uniname2ctype_offset(str2894), 5},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2897), 547},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2900), 35},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2910), 472},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2922), 145},
+ {-1}, {-1},
+ {uniname2ctype_offset(str2925), 176},
+ {uniname2ctype_offset(str2926), 445},
+ {-1},
+ {uniname2ctype_offset(str2928), 294},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2947), 140},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2953), 434},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2960), 220},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2970), 131},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2984), 179},
+ {-1},
+ {uniname2ctype_offset(str2986), 129},
+ {uniname2ctype_offset(str2987), 55},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str2991), 604},
+ {-1},
+ {uniname2ctype_offset(str2993), 526},
+ {-1},
+ {uniname2ctype_offset(str2995), 583},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3005), 220},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3013), 254},
+ {-1},
+ {uniname2ctype_offset(str3015), 48},
+ {-1},
+ {uniname2ctype_offset(str3017), 223},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3021), 278},
+ {uniname2ctype_offset(str3022), 80},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3041), 62},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3049), 609},
+ {-1}, {-1},
+ {uniname2ctype_offset(str3052), 233},
+ {-1},
+ {uniname2ctype_offset(str3054), 65},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3061), 265},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3068), 449},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3078), 247},
+ {-1},
+ {uniname2ctype_offset(str3080), 258},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3086), 453},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3090), 439},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3097), 90},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3103), 286},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3107), 126},
+ {uniname2ctype_offset(str3108), 12},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3112), 251},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3121), 137},
+ {uniname2ctype_offset(str3122), 288},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3127), 90},
+ {uniname2ctype_offset(str3128), 121},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3137), 639},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3142), 103},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3165), 617},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3169), 437},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3177), 600},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3184), 135},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3188), 602},
+ {-1},
+ {uniname2ctype_offset(str3190), 601},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-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(str3221), 565},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3231), 455},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3238), 150},
+ {-1},
+ {uniname2ctype_offset(str3240), 131},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3245), 190},
+ {-1},
+ {uniname2ctype_offset(str3247), 37},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3257), 198},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3261), 52},
+ {-1},
+ {uniname2ctype_offset(str3263), 196},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3281), 238},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3287), 443},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3291), 65},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1},
+ {uniname2ctype_offset(str3302), 327},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3307), 254},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3326), 535},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3334), 42},
+ {uniname2ctype_offset(str3335), 285},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3357), 182},
+ {-1},
+ {uniname2ctype_offset(str3359), 142},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3363), 163},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-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(str3407), 642},
+ {uniname2ctype_offset(str3408), 675},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3414), 458},
+ {-1},
+ {uniname2ctype_offset(str3416), 679},
+ {-1},
+ {uniname2ctype_offset(str3418), 101},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3426), 456},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3432), 670},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3436), 202},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3444), 488},
+ {-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(str3469), 175},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1},
+ {uniname2ctype_offset(str3481), 162},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1},
+ {uniname2ctype_offset(str3493), 241},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3497), 34},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3505), 279},
+ {-1},
+ {uniname2ctype_offset(str3507), 280},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3516), 140},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3532), 141},
+ {-1}, {-1},
+ {uniname2ctype_offset(str3535), 673},
+ {uniname2ctype_offset(str3536), 208},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3543), 250},
+ {-1}, {-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(str3569), 671},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3579), 31},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3585), 216},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3598), 179},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3613), 135},
+ {uniname2ctype_offset(str3614), 63},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3622), 640},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3629), 23},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3647), 168},
+ {-1}, {-1},
+ {uniname2ctype_offset(str3650), 333},
+ {uniname2ctype_offset(str3651), 335},
+ {-1}, {-1},
+ {uniname2ctype_offset(str3654), 672},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1},
+ {uniname2ctype_offset(str3666), 93},
+ {-1}, {-1},
+ {uniname2ctype_offset(str3669), 500},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3686), 262},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3690), 296},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3699), 15},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3718), 119},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3733), 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},
+ {uniname2ctype_offset(str3770), 275},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3778), 63},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3782), 150},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-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(str3813), 158},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3835), 197},
+ {uniname2ctype_offset(str3836), 51},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-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(str3869), 291},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3877), 235},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3894), 247},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3901), 33},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3918), 402},
+ {-1}, {-1}, {-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(str3945), 269},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1},
+ {uniname2ctype_offset(str3965), 578},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3972), 266},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3981), 18},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str3995), 38},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1},
+ {uniname2ctype_offset(str4007), 260},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1},
+ {uniname2ctype_offset(str4018), 442},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4035), 2},
+ {-1}, {-1}, {-1}, {-1}, {-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(str4064), 103},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4069), 331},
+ {-1}, {-1},
+ {uniname2ctype_offset(str4072), 32},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4089), 119},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4102), 170},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4110), 89},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4117), 260},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4140), 196},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4153), 289},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4163), 45},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4180), 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},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1},
+ {uniname2ctype_offset(str4228), 195},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-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(str4318), 259},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-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(str4353), 678},
+ {uniname2ctype_offset(str4354), 422},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-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(str4401), 286},
+ {-1}, {-1},
+ {uniname2ctype_offset(str4404), 267},
+ {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4410), 242},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4414), 287},
+ {-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(str4439), 28},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-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(str4491), 43},
+ {-1}, {-1},
+ {uniname2ctype_offset(str4494), 257},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-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(str4543), 487},
+ {uniname2ctype_offset(str4544), 8},
+ {uniname2ctype_offset(str4545), 267},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4564), 674},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-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(str4670), 39},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4692), 677},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-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(str4731), 158},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4775), 71},
+ {-1},
+ {uniname2ctype_offset(str4777), 257},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str4800), 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},
+ {-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(str4851), 274},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-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(str4941), 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},
+ {uniname2ctype_offset(str4985), 269},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str5002), 633},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-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(str5234), 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},
+ {uniname2ctype_offset(str5271), 74},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {uniname2ctype_offset(str5290), 228},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1},
+ {uniname2ctype_offset(str5329), 242},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-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(str5512), 185},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-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(str5557), 10},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-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(str5800), 30},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-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(str5919), 74},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-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(str5981), 93},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
+ {-1}, {-1}, {-1}, {-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(str6036), 89},
+ {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-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(str6068), 54}
+#endif /* USE_UNICODE_PROPERTIES */
+ };
+
+ if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
+ {
+ register unsigned int key = uniname2ctype_hash (str, len);
+
+ if (key <= MAX_HASH_VALUE)
+ {
+ register int o = wordlist[key].name;
+ if (o >= 0)
+ {
+ register const char *s = o + uniname2ctype_pool;
+
+ if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0')
+ return &wordlist[key];
+ }
+ }
+ }
+ return 0;
+}
+
+static int
+uniname2ctype(const UChar *name, unsigned int len)
+{
+ const struct uniname2ctype_struct *p = uniname2ctype_p((const char *)name, len);
+ if (p) return p->ctype;
+ return -1;
+}
+#if defined ONIG_UNICODE_VERSION_STRING && !( \
+ ONIG_UNICODE_VERSION_MAJOR == 17 && \
+ ONIG_UNICODE_VERSION_MINOR == 0 && \
+ ONIG_UNICODE_VERSION_TEENY == 0 && \
+ 1)
+# error ONIG_UNICODE_VERSION_STRING mismatch
+#endif
+#define ONIG_UNICODE_VERSION_STRING "17.0.0"
+#define ONIG_UNICODE_VERSION_MAJOR 17
+#define ONIG_UNICODE_VERSION_MINOR 0
+#define ONIG_UNICODE_VERSION_TEENY 0
+#if defined ONIG_UNICODE_EMOJI_VERSION_STRING && !( \
+ ONIG_UNICODE_EMOJI_VERSION_MAJOR == 17 && \
+ ONIG_UNICODE_EMOJI_VERSION_MINOR == 0 && \
+ 1)
+# error ONIG_UNICODE_EMOJI_VERSION_STRING mismatch
+#endif
+#define ONIG_UNICODE_EMOJI_VERSION_STRING "17.0"
+#define ONIG_UNICODE_EMOJI_VERSION_MAJOR 17
+#define ONIG_UNICODE_EMOJI_VERSION_MINOR 0
diff --git a/enc/us_ascii.c b/enc/us_ascii.c
index 08f9072c43..253ee69572 100644
--- a/enc/us_ascii.c
+++ b/enc/us_ascii.c
@@ -32,7 +32,11 @@ OnigEncodingDefine(us_ascii, US_ASCII) = {
onigenc_not_support_get_ctype_code_range,
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
onigenc_single_byte_ascii_only_case_map,
+#else
+ NULL,
+#endif
ENCINDEX_US_ASCII,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/utf_16be.c b/enc/utf_16be.c
index f9dd7119d6..0086040b5d 100644
--- a/enc/utf_16be.c
+++ b/enc/utf_16be.c
@@ -249,7 +249,11 @@ OnigEncodingDefine(utf_16be, UTF_16BE) = {
onigenc_utf16_32_get_ctype_code_range,
utf16be_left_adjust_char_head,
onigenc_always_false_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
onigenc_unicode_case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_UNICODE,
};
diff --git a/enc/utf_16le.c b/enc/utf_16le.c
index 2c8438d0be..ca0fce5387 100644
--- a/enc/utf_16le.c
+++ b/enc/utf_16le.c
@@ -242,7 +242,11 @@ OnigEncodingDefine(utf_16le, UTF_16LE) = {
onigenc_utf16_32_get_ctype_code_range,
utf16le_left_adjust_char_head,
onigenc_always_false_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
onigenc_unicode_case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_UNICODE,
};
diff --git a/enc/utf_32be.c b/enc/utf_32be.c
index 17841e52a4..e05cfaf1b2 100644
--- a/enc/utf_32be.c
+++ b/enc/utf_32be.c
@@ -199,7 +199,11 @@ OnigEncodingDefine(utf_32be, UTF_32BE) = {
onigenc_utf16_32_get_ctype_code_range,
utf32be_left_adjust_char_head,
onigenc_always_false_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
onigenc_unicode_case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_UNICODE,
};
diff --git a/enc/utf_32le.c b/enc/utf_32le.c
index 18b798f102..651efdcec5 100644
--- a/enc/utf_32le.c
+++ b/enc/utf_32le.c
@@ -199,7 +199,11 @@ OnigEncodingDefine(utf_32le, UTF_32LE) = {
onigenc_utf16_32_get_ctype_code_range,
utf32le_left_adjust_char_head,
onigenc_always_false_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
onigenc_unicode_case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_UNICODE,
};
diff --git a/enc/utf_8.c b/enc/utf_8.c
index cdf2510d84..ae7c98469d 100644
--- a/enc/utf_8.c
+++ b/enc/utf_8.c
@@ -431,7 +431,11 @@ OnigEncodingDefine(utf_8, UTF_8) = {
get_ctype_code_range,
left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
onigenc_unicode_case_map,
+#else
+ NULL,
+#endif
ENCINDEX_UTF_8,
ONIGENC_FLAG_UNICODE,
};
diff --git a/enc/windows_1250.c b/enc/windows_1250.c
index daf23e9d1e..d38d50a01d 100644
--- a/enc/windows_1250.c
+++ b/enc/windows_1250.c
@@ -190,6 +190,7 @@ cp1250_get_case_fold_codes_by_str(OnigCaseFoldType flag,
flag, p, end, items);
}
+#ifdef USE_CASE_MAP_API
static int
case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
const OnigUChar* end, OnigUChar* to, OnigUChar* to_end,
@@ -239,6 +240,7 @@ case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
*flagP = flags;
return (int )(to - to_start);
}
+#endif
OnigEncodingDefine(windows_1250, Windows_1250) = {
onigenc_single_byte_mbc_enc_len,
@@ -257,7 +259,11 @@ OnigEncodingDefine(windows_1250, Windows_1250) = {
onigenc_not_support_get_ctype_code_range,
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/windows_1251.c b/enc/windows_1251.c
index 6c892c1b8c..81641d0337 100644
--- a/enc/windows_1251.c
+++ b/enc/windows_1251.c
@@ -180,6 +180,7 @@ cp1251_get_case_fold_codes_by_str(OnigCaseFoldType flag,
flag, p, end, items);
}
+#ifdef USE_CASE_MAP_API
static int
case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
const OnigUChar* end, OnigUChar* to, OnigUChar* to_end,
@@ -221,6 +222,7 @@ case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
*flagP = flags;
return (int )(to - to_start);
}
+#endif
OnigEncodingDefine(windows_1251, Windows_1251) = {
onigenc_single_byte_mbc_enc_len,
@@ -239,7 +241,11 @@ OnigEncodingDefine(windows_1251, Windows_1251) = {
onigenc_not_support_get_ctype_code_range,
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/windows_1252.c b/enc/windows_1252.c
index b685878d3f..6aece95c0a 100644
--- a/enc/windows_1252.c
+++ b/enc/windows_1252.c
@@ -181,6 +181,7 @@ cp1252_get_case_fold_codes_by_str(OnigCaseFoldType flag,
flag, p, end, items);
}
+#ifdef USE_CASE_MAP_API
static int
case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
const OnigUChar* end, OnigUChar* to, OnigUChar* to_end,
@@ -228,6 +229,7 @@ case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
*flagP = flags;
return (int )(to - to_start);
}
+#endif
OnigEncodingDefine(windows_1252, Windows_1252) = {
onigenc_single_byte_mbc_enc_len,
@@ -246,7 +248,11 @@ OnigEncodingDefine(windows_1252, Windows_1252) = {
onigenc_not_support_get_ctype_code_range,
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/windows_1253.c b/enc/windows_1253.c
index b2a43581c3..c95ea3f41c 100644
--- a/enc/windows_1253.c
+++ b/enc/windows_1253.c
@@ -213,6 +213,7 @@ get_case_fold_codes_by_str(OnigCaseFoldType flag,
flag, p, end, items);
}
+#ifdef USE_CASE_MAP_API
static int
case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
const OnigUChar* end, OnigUChar* to, OnigUChar* to_end,
@@ -272,6 +273,7 @@ case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
*flagP = flags;
return (int )(to - to_start);
}
+#endif
OnigEncodingDefine(windows_1253, Windows_1253) = {
onigenc_single_byte_mbc_enc_len,
@@ -290,7 +292,11 @@ OnigEncodingDefine(windows_1253, Windows_1253) = {
onigenc_not_support_get_ctype_code_range,
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/windows_1254.c b/enc/windows_1254.c
index 5e6d92d3d2..c8d5991686 100644
--- a/enc/windows_1254.c
+++ b/enc/windows_1254.c
@@ -221,6 +221,7 @@ get_case_fold_codes_by_str(OnigCaseFoldType flag,
flag, p, end, items);
}
+#ifdef USE_CASE_MAP_API
#define DOTLESS_i (0xFD)
#define I_WITH_DOT_ABOVE (0xDD)
static int
@@ -277,6 +278,7 @@ case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
*flagP = flags;
return (int )(to - to_start);
}
+#endif
OnigEncodingDefine(windows_1254, Windows_1254) = {
onigenc_single_byte_mbc_enc_len,
@@ -295,7 +297,11 @@ OnigEncodingDefine(windows_1254, Windows_1254) = {
onigenc_not_support_get_ctype_code_range,
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/windows_1257.c b/enc/windows_1257.c
index ada03b72bf..def13c8c49 100644
--- a/enc/windows_1257.c
+++ b/enc/windows_1257.c
@@ -225,6 +225,7 @@ get_case_fold_codes_by_str(OnigCaseFoldType flag,
flag, p, end, items);
}
+#ifdef USE_CASE_MAP_API
#define DOTLESS_i (0xB9)
#define I_WITH_DOT_ABOVE (0xA9)
static int
@@ -279,6 +280,7 @@ case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
*flagP = flags;
return (int )(to - to_start);
}
+#endif
OnigEncodingDefine(windows_1257, Windows_1257) = {
onigenc_single_byte_mbc_enc_len,
@@ -297,7 +299,11 @@ OnigEncodingDefine(windows_1257, Windows_1257) = {
onigenc_not_support_get_ctype_code_range,
onigenc_single_byte_left_adjust_char_head,
onigenc_always_true_is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/enc/windows_31j.c b/enc/windows_31j.c
index 1eb859596a..cd8bd83fdd 100644
--- a/enc/windows_31j.c
+++ b/enc/windows_31j.c
@@ -48,7 +48,11 @@ OnigEncodingDefine(windows_31j, Windows_31J) = {
get_ctype_code_range,
left_adjust_char_head,
is_allowed_reverse_match,
+#ifdef USE_CASE_MAP_API
onigenc_ascii_only_case_map,
+#else
+ NULL,
+#endif
0,
ONIGENC_FLAG_NONE,
};
diff --git a/encoding.c b/encoding.c
index 480cc8bdc6..8bb393b471 100644
--- a/encoding.c
+++ b/encoding.c
@@ -24,10 +24,13 @@
#include "internal/string.h"
#include "internal/vm.h"
#include "regenc.h"
+#include "ruby/atomic.h"
#include "ruby/encoding.h"
#include "ruby/util.h"
+#include "ruby/ractor.h"
#include "ruby_assert.h"
#include "vm_sync.h"
+#include "ruby_atomic.h"
#ifndef ENC_DEBUG
#define ENC_DEBUG 0
@@ -53,13 +56,14 @@ int rb_encdb_alias(const char *alias, const char *orig);
#pragma GCC visibility pop
#endif
-static ID id_encoding;
+static ID id_encoding, id_i_name;
VALUE rb_cEncoding;
#define ENCODING_LIST_CAPA 256
static VALUE rb_encoding_list;
struct rb_encoding_entry {
+ rb_atomic_t loaded;
const char *name;
rb_encoding *enc;
rb_encoding *base;
@@ -93,15 +97,13 @@ 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)
+static int filesystem_encindex = ENCINDEX_ASCII_8BIT;
+
+#define GLOBAL_ENC_TABLE_LOCKING(tbl) \
+ for (struct enc_table *tbl = &global_enc_table, **locking = &tbl; \
+ locking; \
+ locking = NULL) \
+ RB_VM_LOCKING()
#define ENC_DUMMY_FLAG (1<<24)
@@ -123,8 +125,9 @@ static const rb_data_type_t encoding_data_type = {
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
};
-#define is_data_encoding(obj) (RTYPEDDATA_P(obj) && RTYPEDDATA_TYPE(obj) == &encoding_data_type)
-#define is_obj_encoding(obj) (RB_TYPE_P((obj), T_DATA) && is_data_encoding(obj))
+#define is_encoding_type(obj) (RTYPEDDATA_TYPE(obj) == &encoding_data_type)
+#define is_data_encoding(obj) (rbimpl_rtypeddata_p(obj) && is_encoding_type(obj))
+#define is_obj_encoding(obj) (rbimpl_obj_typeddata_p(obj) && is_encoding_type(obj))
int
rb_data_is_encoding(VALUE obj)
@@ -136,8 +139,8 @@ static VALUE
enc_new(rb_encoding *encoding)
{
VALUE enc = TypedData_Wrap_Struct(rb_cEncoding, &encoding_data_type, (void *)encoding);
- rb_obj_freeze(enc);
- FL_SET_RAW(enc, RUBY_FL_SHAREABLE);
+ rb_ivar_set(enc, id_i_name, rb_fstring_cstr(encoding->name));
+ RB_OBJ_SET_FROZEN_SHAREABLE(enc);
return enc;
}
@@ -146,10 +149,16 @@ enc_list_update(int index, rb_raw_encoding *encoding)
{
RUBY_ASSERT(index < ENCODING_LIST_CAPA);
- VALUE list = rb_encoding_list;
+ VALUE list = RUBY_ATOMIC_VALUE_LOAD(rb_encoding_list);
+
if (list && NIL_P(rb_ary_entry(list, index))) {
+ VALUE new_list = rb_ary_dup(list);
+ RBASIC_CLEAR_CLASS(new_list);
/* initialize encoding data */
- rb_ary_store(list, index, enc_new(encoding));
+ rb_ary_store(new_list, index, enc_new(encoding));
+ rb_ary_freeze(new_list);
+ FL_SET_RAW(new_list, RUBY_FL_SHAREABLE);
+ RUBY_ATOMIC_VALUE_SET(rb_encoding_list, new_list);
}
}
@@ -159,7 +168,7 @@ enc_list_lookup(int idx)
VALUE list, enc = Qnil;
if (idx < ENCODING_LIST_CAPA) {
- list = rb_encoding_list;
+ list = RUBY_ATOMIC_VALUE_LOAD(rb_encoding_list);
RUBY_ASSERT(list);
enc = rb_ary_entry(list, idx);
}
@@ -217,7 +226,7 @@ enc_check_encoding(VALUE obj)
if (!is_obj_encoding(obj)) {
return -1;
}
- return check_encoding(RDATA(obj)->data);
+ return check_encoding(RTYPEDDATA_GET_DATA(obj));
}
NORETURN(static void not_encoding(VALUE enc));
@@ -235,7 +244,7 @@ must_encoding(VALUE enc)
if (index < 0) {
not_encoding(enc);
}
- return DATA_PTR(enc);
+ return RTYPEDDATA_GET_DATA(enc);
}
static rb_encoding *
@@ -246,20 +255,21 @@ must_encindex(int index)
rb_raise(rb_eEncodingError, "encoding index out of bound: %d",
index);
}
- if (ENC_TO_ENCINDEX(enc) != (int)(index & ENC_INDEX_MASK)) {
- rb_raise(rb_eEncodingError, "wrong encoding index %d for %s (expected %d)",
- index, rb_enc_name(enc), ENC_TO_ENCINDEX(enc));
- }
if (rb_enc_autoload_p(enc) && rb_enc_autoload(enc) == -1) {
rb_loaderror("failed to load encoding (%s)",
rb_enc_name(enc));
}
+ if (ENC_TO_ENCINDEX(enc) != (int)(index & ENC_INDEX_MASK)) {
+ rb_raise(rb_eEncodingError, "wrong encoding index %d for %s (expected %d)",
+ index, rb_enc_name(enc), ENC_TO_ENCINDEX(enc));
+ }
return enc;
}
int
rb_to_encoding_index(VALUE enc)
{
+ ASSERT_vm_unlocking(); // can load encoding, so must not hold VM lock
int idx;
const char *name;
@@ -322,7 +332,7 @@ str_to_encoding(VALUE enc)
rb_encoding *
rb_to_encoding(VALUE enc)
{
- if (enc_check_encoding(enc) >= 0) return RDATA(enc)->data;
+ if (enc_check_encoding(enc) >= 0) return RTYPEDDATA_GET_DATA(enc);
return str_to_encoding(enc);
}
@@ -330,7 +340,7 @@ rb_encoding *
rb_find_encoding(VALUE enc)
{
int idx;
- if (enc_check_encoding(enc) >= 0) return RDATA(enc)->data;
+ if (enc_check_encoding(enc) >= 0) return RTYPEDDATA_GET_DATA(enc);
idx = str_find_encindex(enc);
if (idx < 0) return NULL;
return rb_enc_from_index(idx);
@@ -345,41 +355,81 @@ enc_table_expand(struct enc_table *enc_table, int newsize)
return newsize;
}
+/* Load an encoding using the values from base_encoding */
+static void
+enc_load_from_base(struct enc_table *enc_table, int index, rb_encoding *base_encoding)
+{
+ ASSERT_vm_locking();
+
+ struct rb_encoding_entry *ent = &enc_table->list[index];
+
+ if (ent->loaded) {
+ return;
+ }
+
+ rb_raw_encoding *encoding = (rb_raw_encoding *)ent->enc;
+ RUBY_ASSERT(encoding);
+
+ // FIXME: Before the base is loaded, the encoding may be accessed
+ // concurrently by other Ractors.
+ // We're copying all fields from base_encoding except name and
+ // ruby_encoding_index which we preserve from the original. Since these are
+ // the only fields other threads should read it is likely safe despite
+ // technically being a data race.
+ rb_raw_encoding tmp_encoding = *base_encoding;
+ tmp_encoding.name = encoding->name;
+ tmp_encoding.ruby_encoding_index = encoding->ruby_encoding_index;
+ *encoding = tmp_encoding;
+
+ RUBY_ATOMIC_SET(ent->loaded, encoding->max_enc_len);
+}
+
static int
enc_register_at(struct enc_table *enc_table, int index, const char *name, rb_encoding *base_encoding)
{
+ ASSERT_vm_locking();
+
struct rb_encoding_entry *ent = &enc_table->list[index];
rb_raw_encoding *encoding;
- if (!valid_encoding_name_p(name)) return -1;
- if (!ent->name) {
- ent->name = name = strdup(name);
- }
- else if (STRCASECMP(name, ent->name)) {
- return -1;
- }
- encoding = (rb_raw_encoding *)ent->enc;
- if (!encoding) {
- encoding = xmalloc(sizeof(rb_encoding));
+ RUBY_ASSERT(!ent->loaded);
+ RUBY_ASSERT(!ent->name);
+ RUBY_ASSERT(!ent->enc);
+ RUBY_ASSERT(!ent->base);
+
+ RUBY_ASSERT(valid_encoding_name_p(name));
+
+ ent->name = name = strdup(name);
+
+ encoding = ZALLOC(rb_raw_encoding);
+ encoding->name = name;
+ encoding->ruby_encoding_index = index;
+ ent->enc = encoding;
+
+ if (st_insert(enc_table->names, (st_data_t)name, (st_data_t)index)) {
+ rb_bug("encoding name was somehow registered twice");
}
+
+ enc_list_update(index, encoding);
+
if (base_encoding) {
- *encoding = *base_encoding;
+ enc_load_from_base(enc_table, index, base_encoding);
}
else {
- memset(encoding, 0, sizeof(*ent->enc));
+ /* it should not be loaded yet */
+ RUBY_ASSERT(!encoding->max_enc_len);
}
- encoding->name = name;
- encoding->ruby_encoding_index = index;
- ent->enc = 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(struct enc_table *enc_table, const char *name, rb_encoding *encoding)
{
+ ASSERT_vm_locking();
+
+ if (!valid_encoding_name_p(name)) return -1;
+
int index = enc_table->count;
enc_table->count = enc_table_expand(enc_table, index + 1);
@@ -395,7 +445,9 @@ 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 *enc = enc_table->list[index].enc;
+ RUBY_ASSERT(ENC_TO_ENCINDEX(enc) == index);
+ return enc;
}
rb_encoding *
@@ -409,8 +461,7 @@ rb_enc_register(const char *name, rb_encoding *encoding)
{
int index;
- GLOBAL_ENC_TABLE_ENTER(enc_table);
- {
+ GLOBAL_ENC_TABLE_LOCKING(enc_table) {
index = enc_registered(enc_table, name);
if (index >= 0) {
@@ -419,7 +470,7 @@ rb_enc_register(const char *name, rb_encoding *encoding)
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);
+ enc_load_from_base(enc_table, index, encoding);
}
else {
rb_raise(rb_eArgError, "encoding %s is already registered", name);
@@ -430,13 +481,13 @@ rb_enc_register(const char *name, rb_encoding *encoding)
set_encoding_const(name, rb_enc_from_index(index));
}
}
- GLOBAL_ENC_TABLE_LEAVE();
return index;
}
int
enc_registered(struct enc_table *enc_table, const char *name)
{
+ ASSERT_vm_locking();
st_data_t idx = 0;
if (!name) return -1;
@@ -447,18 +498,26 @@ enc_registered(struct enc_table *enc_table, const char *name)
return -1;
}
+int
+rb_enc_registered(const char *name)
+{
+ int idx;
+ GLOBAL_ENC_TABLE_LOCKING(enc_table) {
+ idx = enc_registered(enc_table, name);
+ }
+ return idx;
+}
+
void
rb_encdb_declare(const char *name)
{
- GLOBAL_ENC_TABLE_ENTER(enc_table);
- {
+ GLOBAL_ENC_TABLE_LOCKING(enc_table) {
int idx = enc_registered(enc_table, name);
if (idx < 0) {
idx = enc_register(enc_table, name, 0);
}
set_encoding_const(name, rb_enc_from_index(idx));
}
- GLOBAL_ENC_TABLE_LEAVE();
}
static void
@@ -490,13 +549,11 @@ set_base_encoding(struct enc_table *enc_table, int index, rb_encoding *base)
void
rb_enc_set_base(const char *name, const char *orig)
{
- GLOBAL_ENC_TABLE_ENTER(enc_table);
- {
+ GLOBAL_ENC_TABLE_LOCKING(enc_table) {
int idx = enc_registered(enc_table, name);
int origidx = enc_registered(enc_table, orig);
set_base_encoding(enc_table, idx, rb_enc_from_index(origidx));
}
- GLOBAL_ENC_TABLE_LEAVE();
}
/* for encdb.h
@@ -530,7 +587,7 @@ enc_replicate_with_index(struct enc_table *enc_table, const char *name, rb_encod
idx = enc_register(enc_table, name, origenc);
}
else {
- idx = enc_register_at(enc_table, idx, name, origenc);
+ enc_load_from_base(enc_table, idx, origenc);
}
if (idx >= 0) {
set_base_encoding(enc_table, idx, origenc);
@@ -547,8 +604,7 @@ rb_encdb_replicate(const char *name, const char *orig)
{
int r;
- GLOBAL_ENC_TABLE_ENTER(enc_table);
- {
+ GLOBAL_ENC_TABLE_LOCKING(enc_table) {
int origidx = enc_registered(enc_table, orig);
int idx = enc_registered(enc_table, name);
@@ -557,7 +613,6 @@ rb_encdb_replicate(const char *name, const char *orig)
}
r = enc_replicate_with_index(enc_table, name, rb_enc_from_index(origidx), idx);
}
- GLOBAL_ENC_TABLE_LEAVE();
return r;
}
@@ -567,13 +622,11 @@ rb_define_dummy_encoding(const char *name)
{
int index;
- GLOBAL_ENC_TABLE_ENTER(enc_table);
- {
+ GLOBAL_ENC_TABLE_LOCKING(enc_table) {
index = enc_replicate(enc_table, name, rb_ascii8bit_encoding());
rb_encoding *enc = enc_table->list[index].enc;
ENC_SET_DUMMY((rb_raw_encoding *)enc);
}
- GLOBAL_ENC_TABLE_LEAVE();
return index;
}
@@ -583,15 +636,13 @@ rb_encdb_dummy(const char *name)
{
int index;
- GLOBAL_ENC_TABLE_ENTER(enc_table);
- {
+ GLOBAL_ENC_TABLE_LOCKING(enc_table) {
index = enc_replicate_with_index(enc_table, name,
rb_ascii8bit_encoding(),
enc_registered(enc_table, name));
rb_encoding *enc = enc_table->list[index].enc;
ENC_SET_DUMMY((rb_raw_encoding *)enc);
}
- GLOBAL_ENC_TABLE_LEAVE();
return index;
}
@@ -653,6 +704,7 @@ enc_dup_name(st_data_t name)
static int
enc_alias_internal(struct enc_table *enc_table, const char *alias, int idx)
{
+ ASSERT_vm_locking();
return st_insert2(enc_table->names, (st_data_t)alias, (st_data_t)idx,
enc_dup_name);
}
@@ -670,18 +722,16 @@ int
rb_enc_alias(const char *alias, const char *orig)
{
int idx, r;
+ GLOBAL_ENC_TABLE_LOCKING(enc_table) {
+ enc_check_addable(enc_table, alias); // can raise
+ }
- GLOBAL_ENC_TABLE_ENTER(enc_table);
- {
- enc_check_addable(enc_table, alias);
- if ((idx = rb_enc_find_index(orig)) < 0) {
- r = -1;
- }
- else {
- r = enc_alias(enc_table, alias, idx);
- }
+ idx = rb_enc_find_index(orig);
+ if (idx < 0) return -1;
+
+ GLOBAL_ENC_TABLE_LOCKING(enc_table) {
+ r = enc_alias(enc_table, alias, idx);
}
- GLOBAL_ENC_TABLE_LEAVE();
return r;
}
@@ -691,8 +741,7 @@ rb_encdb_alias(const char *alias, const char *orig)
{
int r;
- GLOBAL_ENC_TABLE_ENTER(enc_table);
- {
+ GLOBAL_ENC_TABLE_LOCKING(enc_table) {
int idx = enc_registered(enc_table, orig);
if (idx < 0) {
@@ -700,7 +749,6 @@ rb_encdb_alias(const char *alias, const char *orig)
}
r = enc_alias(enc_table, alias, idx);
}
- GLOBAL_ENC_TABLE_LEAVE();
return r;
}
@@ -708,6 +756,7 @@ rb_encdb_alias(const char *alias, const char *orig)
static void
rb_enc_init(struct enc_table *enc_table)
{
+ ASSERT_vm_locking();
enc_table_expand(enc_table, ENCODING_COUNT + 1);
if (!enc_table->names) {
enc_table->names = st_init_strcasetable_with_size(ENCODING_LIST_CAPA);
@@ -748,6 +797,7 @@ int rb_require_internal_silent(VALUE fname);
static int
load_encoding(const char *name)
{
+ ASSERT_vm_unlocking();
VALUE enclib = rb_sprintf("enc/%s.so", name);
VALUE debug = ruby_debug;
VALUE errinfo;
@@ -763,12 +813,11 @@ load_encoding(const char *name)
enclib = rb_fstring(enclib);
ruby_debug = Qfalse;
errinfo = rb_errinfo();
- loaded = rb_require_internal_silent(enclib);
+ loaded = rb_require_internal_silent(enclib); // must run without VM_LOCK
ruby_debug = debug;
rb_set_errinfo(errinfo);
- GLOBAL_ENC_TABLE_ENTER(enc_table);
- {
+ GLOBAL_ENC_TABLE_LOCKING(enc_table) {
if (loaded < 0 || 1 < loaded) {
idx = -1;
}
@@ -779,51 +828,73 @@ load_encoding(const char *name)
idx = -1;
}
}
- GLOBAL_ENC_TABLE_LEAVE();
return idx;
}
static int
-enc_autoload_body(struct enc_table *enc_table, rb_encoding *enc)
+enc_autoload_body(rb_encoding *enc)
{
- rb_encoding *base = enc_table->list[ENC_TO_ENCINDEX(enc)].base;
+ rb_encoding *base;
+ int i = 0;
+ ASSERT_vm_unlocking();
+
+ GLOBAL_ENC_TABLE_LOCKING(enc_table) {
+ base = enc_table->list[ENC_TO_ENCINDEX(enc)].base;
+ }
if (base) {
- int i = 0;
- do {
- if (i >= enc_table->count) return -1;
- } while (enc_table->list[i].enc != base && (++i, 1));
+ bool do_register = true;
if (rb_enc_autoload_p(base)) {
- if (rb_enc_autoload(base) < 0) return -1;
+ if (rb_enc_autoload(base) < 0) {
+ do_register = false;
+ i = -1;
+ }
+ }
+
+ if (do_register) {
+ GLOBAL_ENC_TABLE_LOCKING(enc_table) {
+ i = ENC_TO_ENCINDEX(enc);
+ enc_load_from_base(enc_table, i, base);
+ RUBY_ASSERT(((rb_raw_encoding *)enc)->ruby_encoding_index == i);
+ }
}
- i = enc->ruby_encoding_index;
- enc_register_at(enc_table, i & ENC_INDEX_MASK, rb_enc_name(enc), base);
- ((rb_raw_encoding *)enc)->ruby_encoding_index = i;
- i &= ENC_INDEX_MASK;
- return i;
}
else {
- return -2;
+ i = -2;
}
+
+ return i;
}
int
rb_enc_autoload(rb_encoding *enc)
{
- int i;
- GLOBAL_ENC_TABLE_EVAL(enc_table, i = enc_autoload_body(enc_table, enc));
+ ASSERT_vm_unlocking();
+ int i = enc_autoload_body(enc);
if (i == -2) {
i = load_encoding(rb_enc_name(enc));
}
return i;
}
+bool
+rb_enc_autoload_p(rb_encoding *enc)
+{
+ int idx = ENC_TO_ENCINDEX(enc);
+ RUBY_ASSERT(rb_enc_from_index(idx) == enc);
+ return !RUBY_ATOMIC_LOAD(global_enc_table.list[idx].loaded);
+}
+
/* Return encoding index or UNSPECIFIED_ENCODING from encoding name */
int
rb_enc_find_index(const char *name)
{
- int i = enc_registered(&global_enc_table, name);
+ int i;
+ ASSERT_vm_unlocking(); // it needs to be unlocked so it can call `load_encoding` if necessary
+ GLOBAL_ENC_TABLE_LOCKING(enc_table) {
+ i = enc_registered(enc_table, name);
+ }
rb_encoding *enc;
if (i < 0) {
@@ -968,6 +1039,21 @@ enc_set_index(VALUE obj, int idx)
}
void
+rb_enc_raw_set(VALUE obj, rb_encoding *enc)
+{
+ RUBY_ASSERT(enc_capable(obj));
+
+ int idx = enc ? ENC_TO_ENCINDEX(enc) : 0;
+
+ if (idx < ENCODING_INLINE_MAX) {
+ ENCODING_SET_INLINED(obj, idx);
+ return;
+ }
+ ENCODING_SET_INLINED(obj, ENCODING_INLINE_MAX);
+ rb_ivar_set(obj, rb_id_encoding(), INT2NUM(idx));
+}
+
+void
rb_enc_set_index(VALUE obj, int idx)
{
rb_check_frozen(obj);
@@ -981,7 +1067,6 @@ rb_enc_associate_index(VALUE obj, int idx)
rb_encoding *enc;
int oldidx, oldtermlen, termlen;
-/* enc_check_capable(obj);*/
rb_check_frozen(obj);
oldidx = rb_enc_get_index(obj);
if (oldidx == idx)
@@ -1053,6 +1138,13 @@ rb_enc_check(VALUE str1, VALUE str2)
static rb_encoding*
enc_compatible_latter(VALUE str1, VALUE str2, int idx1, int idx2)
{
+ if (idx1 < 0 || idx2 < 0)
+ return 0;
+
+ if (idx1 == idx2) {
+ return rb_enc_from_index(idx1);
+ }
+
int isstr1, isstr2;
rb_encoding *enc1 = rb_enc_from_index(idx1);
rb_encoding *enc2 = rb_enc_from_index(idx2);
@@ -1111,15 +1203,7 @@ enc_compatible_str(VALUE str1, VALUE str2)
int idx1 = enc_get_index_str(str1);
int idx2 = enc_get_index_str(str2);
- if (idx1 < 0 || idx2 < 0)
- return 0;
-
- if (idx1 == idx2) {
- return rb_enc_from_index(idx1);
- }
- else {
- return enc_compatible_latter(str1, str2, idx1, idx2);
- }
+ return enc_compatible_latter(str1, str2, idx1, idx2);
}
rb_encoding*
@@ -1128,13 +1212,6 @@ rb_enc_compatible(VALUE str1, VALUE str2)
int idx1 = rb_enc_get_index(str1);
int idx2 = rb_enc_get_index(str2);
- if (idx1 < 0 || idx2 < 0)
- return 0;
-
- if (idx1 == idx2) {
- return rb_enc_from_index(idx1);
- }
-
return enc_compatible_latter(str1, str2, idx1, idx2);
}
@@ -1147,9 +1224,12 @@ rb_enc_copy(VALUE obj1, VALUE obj2)
/*
* call-seq:
- * obj.encoding -> encoding
+ * encoding -> encoding
*
- * Returns the Encoding object that represents the encoding of obj.
+ * Returns an Encoding object that represents the encoding of +self+;
+ * see {Encodings}[rdoc-ref:encodings.rdoc].
+ *
+ * Related: see {Querying}[rdoc-ref:String@Querying].
*/
VALUE
@@ -1266,10 +1346,10 @@ enc_inspect(VALUE self)
{
rb_encoding *enc;
- if (!is_data_encoding(self)) {
+ if (!is_obj_encoding(self)) { /* do not resolve autoload */
not_encoding(self);
}
- if (!(enc = DATA_PTR(self)) || rb_enc_from_index(rb_enc_to_index(enc)) != enc) {
+ if (!(enc = RTYPEDDATA_GET_DATA(self)) || rb_enc_from_index(rb_enc_to_index(enc)) != enc) {
rb_raise(rb_eTypeError, "broken Encoding");
}
@@ -1280,20 +1360,6 @@ enc_inspect(VALUE self)
rb_enc_autoload_p(enc) ? " (autoload)" : "");
}
-/*
- * call-seq:
- * enc.name -> string
- * enc.to_s -> string
- *
- * Returns the name of the encoding.
- *
- * Encoding::UTF_8.name #=> "UTF-8"
- */
-static VALUE
-enc_name(VALUE self)
-{
- return rb_fstring_cstr(rb_enc_name((rb_encoding*)DATA_PTR(self)));
-}
static int
enc_names_i(st_data_t name, st_data_t idx, st_data_t args)
@@ -1301,7 +1367,7 @@ enc_names_i(st_data_t name, st_data_t idx, st_data_t args)
VALUE *arg = (VALUE *)args;
if ((int)idx == (int)arg[0]) {
- VALUE str = rb_fstring_cstr((char *)name);
+ VALUE str = rb_interned_str_cstr((char *)name);
rb_ary_push(arg[1], str);
}
return ST_CONTINUE;
@@ -1322,7 +1388,10 @@ enc_names(VALUE self)
args[0] = (VALUE)rb_to_encoding_index(self);
args[1] = rb_ary_new2(0);
- st_foreach(global_enc_table.names, enc_names_i, (st_data_t)args);
+
+ GLOBAL_ENC_TABLE_LOCKING(enc_table) {
+ st_foreach(enc_table->names, enc_names_i, (st_data_t)args);
+ }
return args[1];
}
@@ -1347,9 +1416,8 @@ enc_names(VALUE self)
static VALUE
enc_list(VALUE klass)
{
- VALUE ary = rb_ary_new2(0);
- rb_ary_replace(ary, rb_encoding_list);
- return ary;
+ VALUE list = RUBY_ATOMIC_VALUE_LOAD(rb_encoding_list);
+ return rb_ary_dup(list);
}
/*
@@ -1435,7 +1503,7 @@ static VALUE
enc_dump(int argc, VALUE *argv, VALUE self)
{
rb_check_arity(argc, 0, 1);
- return enc_name(self);
+ return rb_attr_get(self, id_i_name);
}
/* :nodoc: */
@@ -1493,20 +1561,23 @@ int rb_locale_charmap_index(void);
int
rb_locale_encindex(void)
{
+ // `rb_locale_charmap_index` can call `enc_find_index`, which can
+ // load an encoding. This needs to be done without VM lock held.
+ ASSERT_vm_unlocking();
int idx = rb_locale_charmap_index();
if (idx < 0) idx = ENCINDEX_UTF_8;
- if (enc_registered(&global_enc_table, "locale") < 0) {
+ GLOBAL_ENC_TABLE_LOCKING(enc_table) {
+ if (enc_registered(enc_table, "locale") < 0) {
# if defined _WIN32
- void Init_w32_codepage(void);
- Init_w32_codepage();
+ void Init_w32_codepage(void);
+ Init_w32_codepage();
# endif
- GLOBAL_ENC_TABLE_ENTER(enc_table);
- {
- enc_alias_internal(enc_table, "locale", idx);
+ GLOBAL_ENC_TABLE_LOCKING(enc_table) {
+ enc_alias_internal(enc_table, "locale", idx);
+ }
}
- GLOBAL_ENC_TABLE_LEAVE();
}
return idx;
@@ -1521,9 +1592,7 @@ rb_locale_encoding(void)
int
rb_filesystem_encindex(void)
{
- int idx = enc_registered(&global_enc_table, "filesystem");
- if (idx < 0) idx = ENCINDEX_ASCII_8BIT;
- return idx;
+ return filesystem_encindex;
}
rb_encoding *
@@ -1548,8 +1617,13 @@ enc_set_default_encoding(struct default_encoding *def, VALUE encoding, const cha
/* Already set */
overridden = TRUE;
- GLOBAL_ENC_TABLE_ENTER(enc_table);
- {
+ int index = 0;
+ if (!NIL_P(encoding)) {
+ enc_check_encoding(encoding); // loads it if necessary. Needs to be done outside of VM lock.
+ index = rb_enc_to_index(rb_to_encoding(encoding));
+ }
+
+ GLOBAL_ENC_TABLE_LOCKING(enc_table) {
if (NIL_P(encoding)) {
def->index = -1;
def->enc = 0;
@@ -1564,16 +1638,17 @@ enc_set_default_encoding(struct default_encoding *def, VALUE encoding, const cha
(st_data_t)UNSPECIFIED_ENCODING);
}
else {
- def->index = rb_enc_to_index(rb_to_encoding(encoding));
+ def->index = index;
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());
+ int fs_idx = Init_enc_set_filesystem_encoding();
+ enc_alias_internal(enc_table, "filesystem", fs_idx);
+ filesystem_encindex = fs_idx;
}
}
- GLOBAL_ENC_TABLE_LEAVE();
return overridden;
}
@@ -1798,7 +1873,7 @@ static int
rb_enc_name_list_i(st_data_t name, st_data_t idx, st_data_t arg)
{
VALUE ary = (VALUE)arg;
- VALUE str = rb_fstring_cstr((char *)name);
+ VALUE str = rb_interned_str_cstr((char *)name);
rb_ary_push(ary, str);
return ST_CONTINUE;
}
@@ -1820,8 +1895,11 @@ 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(global_enc_table.names->num_entries);
- st_foreach(global_enc_table.names, rb_enc_name_list_i, (st_data_t)ary);
+ VALUE ary;
+ GLOBAL_ENC_TABLE_LOCKING(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);
+ }
return ary;
}
@@ -1843,7 +1921,7 @@ rb_enc_aliases_enc_i(st_data_t name, st_data_t orig, st_data_t arg)
str = rb_fstring_cstr(rb_enc_name(enc));
rb_ary_store(ary, idx, str);
}
- key = rb_fstring_cstr((char *)name);
+ key = rb_interned_str_cstr((char *)name);
rb_hash_aset(aliases, key, str);
return ST_CONTINUE;
}
@@ -1867,7 +1945,9 @@ rb_enc_aliases(VALUE klass)
aliases[0] = rb_hash_new();
aliases[1] = rb_ary_new();
- st_foreach(global_enc_table.names, rb_enc_aliases_enc_i, (st_data_t)aliases);
+ GLOBAL_ENC_TABLE_LOCKING(enc_table) {
+ st_foreach(enc_table->names, rb_enc_aliases_enc_i, (st_data_t)aliases);
+ }
return aliases[0];
}
@@ -1909,12 +1989,19 @@ Init_Encoding(void)
VALUE list;
int i;
+ id_i_name = rb_intern_const("@name");
rb_cEncoding = rb_define_class("Encoding", rb_cObject);
rb_define_alloc_func(rb_cEncoding, enc_s_alloc);
rb_undef_method(CLASS_OF(rb_cEncoding), "new");
- rb_define_method(rb_cEncoding, "to_s", enc_name, 0);
+
+ /* The name of the encoding.
+ *
+ * Encoding::UTF_8.name #=> "UTF-8"
+ */
+ rb_attr(rb_cEncoding, rb_intern("name"), TRUE, FALSE, Qfalse);
+ rb_define_alias(rb_cEncoding, "to_s", "name");
+
rb_define_method(rb_cEncoding, "inspect", enc_inspect, 0);
- rb_define_method(rb_cEncoding, "name", enc_name, 0);
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);
@@ -1935,9 +2022,9 @@ Init_Encoding(void)
struct enc_table *enc_table = &global_enc_table;
+ rb_gc_register_address(&rb_encoding_list);
list = rb_encoding_list = rb_ary_new2(ENCODING_LIST_CAPA);
RBASIC_CLEAR_CLASS(list);
- rb_vm_register_global_object(list);
for (i = 0; i < enc_table->count; ++i) {
rb_ary_push(list, enc_new(enc_table->list[i].enc));
@@ -1947,6 +2034,18 @@ Init_Encoding(void)
}
void
+Init_unicode_version(void)
+{
+ extern const char onigenc_unicode_version_string[];
+
+ VALUE str = rb_usascii_str_new_static(onigenc_unicode_version_string,
+ strlen(onigenc_unicode_version_string));
+ OBJ_FREEZE(str);
+ /* The supported Unicode version. */
+ rb_define_const(rb_cEncoding, "UNICODE_VERSION", str);
+}
+
+void
Init_encodings(void)
{
rb_enc_init(&global_enc_table);
@@ -1957,5 +2056,7 @@ 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(global_enc_table.names, func, arg);
+ GLOBAL_ENC_TABLE_LOCKING(enc_table) {
+ st_foreach(enc_table->names, func, arg);
+ }
}
diff --git a/enum.c b/enum.c
index dcb374778e..765c093da7 100644
--- a/enum.c
+++ b/enum.c
@@ -127,7 +127,7 @@ static VALUE
enum_grep0(VALUE obj, VALUE pat, VALUE test)
{
VALUE ary = rb_ary_new();
- struct MEMO *memo = MEMO_NEW(pat, ary, test);
+ struct MEMO *memo = rb_imemo_memo_new(pat, ary, test);
rb_block_call_func_t fn;
if (rb_block_given_p()) {
fn = grep_iter_i;
@@ -317,21 +317,38 @@ enum_count(int argc, VALUE *argv, VALUE obj)
func = count_i;
}
- memo = MEMO_NEW(item, 0, 0);
+ memo = rb_imemo_memo_new(item, 0, 0);
rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
return imemo_count_value(memo);
}
+NORETURN(static void found(VALUE i, VALUE memop));
+static void
+found(VALUE i, VALUE memop)
+{
+ struct MEMO *memo = MEMO_CAST(memop);
+ MEMO_V1_SET(memo, i);
+ memo->u3.cnt = 1;
+ rb_iter_break();
+}
+
+static VALUE
+find_i_fast(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
+{
+ if (RTEST(rb_yield_values2(argc, argv))) {
+ ENUM_WANT_SVALUE();
+ found(i, memop);
+ }
+ return Qnil;
+}
+
static VALUE
find_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop))
{
ENUM_WANT_SVALUE();
if (RTEST(enum_yield(argc, i))) {
- struct MEMO *memo = MEMO_CAST(memop);
- MEMO_V1_SET(memo, i);
- memo->u3.cnt = 1;
- rb_iter_break();
+ found(i, memop);
}
return Qnil;
}
@@ -365,8 +382,11 @@ enum_find(int argc, VALUE *argv, VALUE obj)
if_none = rb_check_arity(argc, 0, 1) ? argv[0] : Qnil;
RETURN_ENUMERATOR(obj, argc, argv);
- memo = MEMO_NEW(Qundef, 0, 0);
- rb_block_call(obj, id_each, 0, 0, find_i, (VALUE)memo);
+ memo = rb_imemo_memo_new(Qundef, 0, 0);
+ if (rb_block_pair_yield_optimizable())
+ rb_block_call2(obj, id_each, 0, 0, find_i_fast, (VALUE)memo, RB_BLOCK_NO_USE_PACKED_ARGS);
+ else
+ rb_block_call2(obj, id_each, 0, 0, find_i, (VALUE)memo, RB_BLOCK_NO_USE_PACKED_ARGS);
if (memo->u3.cnt) {
return memo->v1;
}
@@ -447,7 +467,7 @@ enum_find_index(int argc, VALUE *argv, VALUE obj)
func = find_index_i;
}
- memo = MEMO_NEW(Qnil, condition_value, 0);
+ memo = rb_imemo_memo_new(Qnil, condition_value, 0);
rb_block_call(obj, id_each, 0, 0, func, (VALUE)memo);
return memo->v1;
}
@@ -1064,7 +1084,7 @@ enum_inject(int argc, VALUE *argv, VALUE obj)
return ary_inject_op(obj, init, op);
}
- memo = MEMO_NEW(init, Qnil, op);
+ memo = rb_imemo_memo_new(init, Qnil, op);
rb_block_call(obj, id_each, 0, 0, iter, (VALUE)memo);
if (UNDEF_P(memo->v1)) return Qnil;
return memo->v1;
@@ -1122,7 +1142,7 @@ enum_partition(VALUE obj)
RETURN_SIZED_ENUMERATOR(obj, 0, 0, enum_size);
- memo = MEMO_NEW(rb_ary_new(), rb_ary_new(), 0);
+ memo = rb_imemo_memo_new(rb_ary_new(), rb_ary_new(), 0);
rb_block_call(obj, id_each, 0, 0, partition_i, (VALUE)memo);
return rb_assoc_new(memo->v1, memo->v2);
@@ -1195,14 +1215,15 @@ tally_up(st_data_t *group, st_data_t *value, st_data_t arg, int existing)
RB_OBJ_WRITTEN(hash, Qundef, tally);
}
*value = (st_data_t)tally;
- if (!SPECIAL_CONST_P(*group)) RB_OBJ_WRITTEN(hash, Qundef, *group);
return ST_CONTINUE;
}
static VALUE
rb_enum_tally_up(VALUE hash, VALUE group)
{
- rb_hash_stlike_update(hash, group, tally_up, (st_data_t)hash);
+ if (!rb_hash_stlike_update(hash, group, tally_up, (st_data_t)hash)) {
+ RB_OBJ_WRITTEN(hash, Qundef, group);
+ }
return hash;
}
@@ -1216,29 +1237,47 @@ tally_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash))
/*
* call-seq:
- * tally -> new_hash
- * tally(hash) -> hash
+ * tally(hash = {}) -> hash
*
- * Returns a hash containing the counts of equal elements:
+ * When argument +hash+ is not given,
+ * returns a new hash whose keys are the distinct elements in +self+;
+ * each integer value is the count of occurrences of each element:
*
- * - Each key is an element of +self+.
- * - Each value is the number elements equal to that key.
+ * %w[a b c b c a c b].tally # => {"a"=>2, "b"=>3, "c"=>3}
*
- * With no argument:
+ * When argument +hash+ is given,
+ * returns +hash+, possibly augmented; for each element +ele+ in +self+:
*
- * %w[a b c b c a c b].tally # => {"a"=>2, "b"=>3, "c"=>3}
+ * - Adds it as a key with a zero value if that key does not already exist:
*
- * 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[ele] = 0 unless hash.include?(ele)
*
- * 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}
+ * - Increments the value of key +ele+:
+ *
+ * hash[ele] += 1
+ *
+ * This is useful for accumulating tallies across multiple enumerables:
+ *
+ * h = {} # => {}
+ * %w[a c d b c a].tally(h) # => {"a"=>2, "c"=>2, "d"=>1, "b"=>1}
+ * %w[b a z].tally(h) # => {"a"=>3, "c"=>2, "d"=>1, "b"=>2, "z"=>1}
+ * %w[b a m].tally(h) # => {"a"=>4, "c"=>2, "d"=>1, "b"=>3, "z"=>1, "m"=>1}
+ *
+ * The key to be added or found for an element depends on the class of +self+;
+ * see {Enumerable in Ruby Classes}[rdoc-ref:Enumerable@Enumerable+in+Ruby+Classes].
+ *
+ * Examples:
+ *
+ * - Array (and certain array-like classes):
+ * the key is the element (as above).
+ * - Hash (and certain hash-like classes):
+ * the key is the 2-element array formed from the key-value pair:
+ *
+ * h = {} # => {}
+ * {foo: 'a', bar: 'b'}.tally(h) # => {[:foo, "a"]=>1, [:bar, "b"]=>1}
+ * {foo: 'c', bar: 'd'}.tally(h) # => {[:foo, "a"]=>1, [:bar, "b"]=>1, [:foo, "c"]=>1, [:bar, "d"]=>1}
+ * {foo: 'a', bar: 'b'}.tally(h) # => {[:foo, "a"]=>2, [:bar, "b"]=>2, [:foo, "c"]=>1, [:bar, "d"]=>1}
+ * {foo: 'c', bar: 'd'}.tally(h) # => {[:foo, "a"]=>2, [:bar, "b"]=>2, [:foo, "c"]=>2, [:bar, "d"]=>2}
*
*/
@@ -1306,7 +1345,7 @@ enum_first(int argc, VALUE *argv, VALUE obj)
return enum_take(obj, argv[0]);
}
else {
- memo = MEMO_NEW(Qnil, 0, 0);
+ memo = rb_imemo_memo_new(Qnil, 0, 0);
rb_block_call(obj, id_each, 0, 0, first_i, (VALUE)memo);
return memo->v1;
}
@@ -1321,7 +1360,7 @@ enum_first(int argc, VALUE *argv, VALUE obj)
* The ordering of equal elements is indeterminate and may be unstable.
*
* With no block given, the sort compares
- * using the elements' own method <tt><=></tt>:
+ * using the elements' own method <tt>#<=></tt>:
*
* %w[b c a d].sort # => ["a", "b", "c", "d"]
* {foo: 0, bar: 1, baz: 2}.sort # => [[:bar, 1], [:baz, 2], [:foo, 0]]
@@ -1683,7 +1722,7 @@ enum_sort_by(VALUE obj)
RBASIC_CLEAR_CLASS(ary);
buf = rb_ary_hidden_new(SORT_BY_BUFSIZE*2);
rb_ary_store(buf, SORT_BY_BUFSIZE*2-1, Qnil);
- memo = MEMO_NEW(0, 0, 0);
+ memo = rb_imemo_memo_new(0, 0, 0);
data = (struct sort_by_data *)&memo->v1;
RB_OBJ_WRITE(memo, &data->ary, ary);
RB_OBJ_WRITE(memo, &data->buf, buf);
@@ -1724,7 +1763,10 @@ enum_sort_by(VALUE obj)
#define ENUMFUNC(name) argc ? name##_eqq : rb_block_given_p() ? name##_iter_i : name##_i
-#define MEMO_ENUM_NEW(v1) (rb_check_arity(argc, 0, 1), MEMO_NEW((v1), (argc ? *argv : 0), 0))
+#define ENUM_BLOCK_CALL(name) \
+ rb_block_call2(obj, id_each, 0, 0, ENUMFUNC(name), (VALUE)memo, rb_block_given_p() && rb_block_pair_yield_optimizable() ? RB_BLOCK_NO_USE_PACKED_ARGS : 0);
+
+#define MEMO_ENUM_NEW(v1) (rb_check_arity(argc, 0, 1), rb_imemo_memo_new((v1), (argc ? *argv : 0), 0))
#define DEFINE_ENUMFUNCS(name) \
static VALUE enum_##name##_func(VALUE result, struct MEMO *memo); \
@@ -1817,7 +1859,7 @@ enum_all(int argc, VALUE *argv, VALUE obj)
{
struct MEMO *memo = MEMO_ENUM_NEW(Qtrue);
WARN_UNUSED_BLOCK(argc);
- rb_block_call(obj, id_each, 0, 0, ENUMFUNC(all), (VALUE)memo);
+ ENUM_BLOCK_CALL(all);
return memo->v1;
}
@@ -1879,7 +1921,7 @@ enum_any(int argc, VALUE *argv, VALUE obj)
{
struct MEMO *memo = MEMO_ENUM_NEW(Qfalse);
WARN_UNUSED_BLOCK(argc);
- rb_block_call(obj, id_each, 0, 0, ENUMFUNC(any), (VALUE)memo);
+ ENUM_BLOCK_CALL(any);
return memo->v1;
}
@@ -2168,7 +2210,7 @@ enum_one(int argc, VALUE *argv, VALUE obj)
VALUE result;
WARN_UNUSED_BLOCK(argc);
- rb_block_call(obj, id_each, 0, 0, ENUMFUNC(one), (VALUE)memo);
+ ENUM_BLOCK_CALL(one);
result = memo->v1;
if (UNDEF_P(result)) return Qfalse;
return result;
@@ -2229,7 +2271,7 @@ enum_none(int argc, VALUE *argv, VALUE obj)
struct MEMO *memo = MEMO_ENUM_NEW(Qtrue);
WARN_UNUSED_BLOCK(argc);
- rb_block_call(obj, id_each, 0, 0, ENUMFUNC(none), (VALUE)memo);
+ ENUM_BLOCK_CALL(none);
return memo->v1;
}
@@ -2287,7 +2329,7 @@ min_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
* The ordering of equal elements is indeterminate and may be unstable.
*
* With no argument and no block, returns the minimum element,
- * using the elements' own method <tt><=></tt> for comparison:
+ * using the elements' own method <tt>#<=></tt> for comparison:
*
* (1..4).min # => 1
* (-4..-1).min # => -4
@@ -2409,7 +2451,7 @@ max_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
* The ordering of equal elements is indeterminate and may be unstable.
*
* With no argument and no block, returns the maximum element,
- * using the elements' own method <tt><=></tt> for comparison:
+ * using the elements' own method <tt>#<=></tt> for comparison:
*
* (1..4).max # => 4
* (-4..-1).max # => -1
@@ -2598,7 +2640,7 @@ minmax_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo))
* The ordering of equal elements is indeterminate and may be unstable.
*
* With no argument and no block, returns the minimum and maximum elements,
- * using the elements' own method <tt><=></tt> for comparison:
+ * using the elements' own method <tt>#<=></tt> for comparison:
*
* (1..4).minmax # => [1, 4]
* (-4..-1).minmax # => [-4, -1]
@@ -2712,7 +2754,7 @@ enum_min_by(int argc, VALUE *argv, VALUE obj)
if (argc && !NIL_P(num = argv[0]))
return rb_nmin_run(obj, num, 1, 0, 0);
- memo = MEMO_NEW(Qundef, Qnil, 0);
+ memo = rb_imemo_memo_new(Qundef, Qnil, 0);
rb_block_call(obj, id_each, 0, 0, min_by_i, (VALUE)memo);
return memo->v2;
}
@@ -2786,7 +2828,7 @@ enum_max_by(int argc, VALUE *argv, VALUE obj)
if (argc && !NIL_P(num = argv[0]))
return rb_nmin_run(obj, num, 1, 1, 0);
- memo = MEMO_NEW(Qundef, Qnil, 0);
+ memo = rb_imemo_memo_new(Qundef, Qnil, 0);
rb_block_call(obj, id_each, 0, 0, max_by_i, (VALUE)memo);
return memo->v2;
}
@@ -2937,20 +2979,19 @@ member_i(RB_BLOCK_CALL_FUNC_ARGLIST(iter, args))
static VALUE
enum_member(VALUE obj, VALUE val)
{
- struct MEMO *memo = MEMO_NEW(val, Qfalse, 0);
+ struct MEMO *memo = rb_imemo_memo_new(val, Qfalse, 0);
rb_block_call(obj, id_each, 0, 0, member_i, (VALUE)memo);
return memo->v2;
}
static VALUE
-each_with_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo))
+each_with_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(_, index))
{
- struct MEMO *m = MEMO_CAST(memo);
- VALUE n = imemo_count_value(m);
+ struct vm_ifunc *ifunc = rb_current_ifunc();
+ ifunc->data = (const void *)rb_int_succ(index);
- imemo_count_up(m);
- return rb_yield_values(2, rb_enum_values_pack(argc, argv), n);
+ return rb_yield_values(2, rb_enum_values_pack(argc, argv), index);
}
/*
@@ -2958,7 +2999,8 @@ each_with_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo))
* each_with_index(*args) {|element, i| ..... } -> self
* each_with_index(*args) -> enumerator
*
- * With a block given, calls the block with each element and its index;
+ * Invoke <tt>self.each</tt> with <tt>*args</tt>.
+ * With a block given, the block receives each element and its index;
* returns +self+:
*
* h = {}
@@ -2983,12 +3025,9 @@ each_with_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo))
static VALUE
enum_each_with_index(int argc, VALUE *argv, VALUE obj)
{
- struct MEMO *memo;
-
RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size);
- memo = MEMO_NEW(0, 0, 0);
- rb_block_call(obj, id_each, argc, argv, each_with_index_i, (VALUE)memo);
+ rb_block_call(obj, id_each, argc, argv, each_with_index_i, INT2FIX(0));
return obj;
}
@@ -3192,7 +3231,7 @@ enum_each_slice(VALUE obj, VALUE n)
size = limit_by_enum_size(obj, size);
ary = rb_ary_new2(size);
arity = rb_block_arity();
- memo = MEMO_NEW(ary, dont_recycle_block_arg(arity), size);
+ memo = rb_imemo_memo_new(ary, dont_recycle_block_arg(arity), size);
rb_block_call(obj, id_each, 0, 0, each_slice_i, (VALUE)memo);
ary = memo->v1;
if (RARRAY_LEN(ary) > 0) rb_yield(ary);
@@ -3268,7 +3307,7 @@ enum_each_cons(VALUE obj, VALUE n)
RETURN_SIZED_ENUMERATOR(obj, 1, &n, enum_each_cons_size);
arity = rb_block_arity();
if (enum_size_over_p(obj, size)) return obj;
- memo = MEMO_NEW(rb_ary_new2(size), dont_recycle_block_arg(arity), size);
+ memo = rb_imemo_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 obj;
@@ -3497,7 +3536,7 @@ enum_zip(int argc, VALUE *argv, VALUE obj)
}
/* TODO: use NODE_DOT2 as memo(v, v, -) */
- memo = MEMO_NEW(result, args, 0);
+ memo = rb_imemo_memo_new(result, args, 0);
rb_block_call(obj, id_each, 0, 0, allary ? zip_ary : zip_i, (VALUE)memo);
return result;
@@ -3540,7 +3579,7 @@ enum_take(VALUE obj, VALUE n)
if (len == 0) return rb_ary_new2(0);
result = rb_ary_new2(len);
- memo = MEMO_NEW(result, 0, len);
+ memo = rb_imemo_memo_new(result, 0, len);
rb_block_call(obj, id_each, 0, 0, take_i, (VALUE)memo);
return result;
}
@@ -3628,7 +3667,7 @@ enum_drop(VALUE obj, VALUE n)
}
result = rb_ary_new();
- memo = MEMO_NEW(result, 0, len);
+ memo = rb_imemo_memo_new(result, 0, len);
rb_block_call(obj, id_each, 0, 0, drop_i, (VALUE)memo);
return result;
}
@@ -3666,6 +3705,17 @@ drop_while_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args))
*
* With no block given, returns an Enumerator.
*
+ * e = (1..4).drop_while
+ * p e #=> #<Enumerator: 1..4:drop_while>
+ * i = e.next; p i; e.feed(i < 3) #=> 1
+ * i = e.next; p i; e.feed(i < 3) #=> 2
+ * i = e.next; p i; e.feed(i < 3) #=> 3
+ * begin
+ * e.next
+ * rescue StopIteration
+ * p $!.result #=> [3, 4]
+ * end
+ *
*/
static VALUE
@@ -3676,7 +3726,7 @@ enum_drop_while(VALUE obj)
RETURN_ENUMERATOR(obj, 0, 0);
result = rb_ary_new();
- memo = MEMO_NEW(result, 0, FALSE);
+ memo = rb_imemo_memo_new(result, 0, FALSE);
rb_block_call(obj, id_each, 0, 0, drop_while_i, (VALUE)memo);
return result;
}
@@ -3875,7 +3925,7 @@ chunk_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator))
* e.next # => [2, [6, 7, 8]]
* e.next # => [3, [9, 10]]
*
- * \Method +chunk+ is especially useful for an enumerable that is already sorted.
+ * Method +chunk+ is especially useful for an enumerable that is already sorted.
* This example counts words for each initial letter in a large array of words:
*
* # Get sorted words from a web page.
@@ -3896,7 +3946,7 @@ chunk_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator))
* ["F", 6860]
*
* You can use the special symbol <tt>:_alone</tt> to force an element
- * into its own separate chuck:
+ * into its own separate chunk:
*
* a = [0, 0, 1, 1]
* e = a.chunk{|i| i.even? ? :_alone : true }
@@ -4667,7 +4717,7 @@ sum_iter(VALUE i, struct enum_sum_memo *memo)
}
else switch (TYPE(memo->v)) {
default: sum_iter_some_value(i, memo); return;
- case T_FLOAT: sum_iter_Kahan_Babuska(i, memo); return;
+ case T_FLOAT:
case T_FIXNUM:
case T_BIGNUM:
case T_RATIONAL:
@@ -4902,7 +4952,7 @@ enum_compact(VALUE obj)
/*
* == What's Here
*
- * \Module \Enumerable provides methods that are useful to a collection class for:
+ * Module \Enumerable provides methods that are useful to a collection class for:
*
* - {Querying}[rdoc-ref:Enumerable@Methods+for+Querying]
* - {Fetching}[rdoc-ref:Enumerable@Methods+for+Fetching]
@@ -4915,7 +4965,7 @@ enum_compact(VALUE obj)
*
* These methods return information about the \Enumerable other than the elements themselves:
*
- * - #include?, #member?: Returns +true+ if <tt>self == object</tt>, +false+ otherwise.
+ * - #member? (aliased as #include?): Returns +true+ if <tt>self == object</tt>, +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.
@@ -4930,7 +4980,7 @@ enum_compact(VALUE obj)
*
* <i>Leading, trailing, or all elements</i>:
*
- * - #entries, #to_a: Returns all elements.
+ * - #to_a (aliased as #entries): Returns all elements.
* - #first: Returns the first element or leading elements.
* - #take: Returns a specified number of leading elements.
* - #drop: Returns a specified number of trailing elements.
@@ -4940,9 +4990,9 @@ enum_compact(VALUE obj)
* <i>Minimum and maximum value elements</i>:
*
* - #min: Returns the elements whose values are smallest among the elements,
- * as determined by <tt><=></tt> or a given block.
+ * as determined by <tt>#<=></tt> or a given block.
* - #max: Returns the elements whose values are largest among the elements,
- * as determined by <tt><=></tt> or a given block.
+ * as determined by <tt>#<=></tt> 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.
@@ -4965,8 +5015,8 @@ enum_compact(VALUE obj)
*
* These methods return elements that meet a specified criterion:
*
- * - #find, #detect: Returns an element selected by the block.
- * - #find_all, #filter, #select: Returns elements selected by the block.
+ * - #find (aliased as #detect): Returns an element selected by the block.
+ * - #find_all (aliased as #filter, #select): Returns elements selected by the block.
* - #find_index: Returns the index of an element selected by a given object or block.
* - #reject: Returns elements not rejected by the block.
* - #uniq: Returns elements that are not duplicates.
@@ -4975,7 +5025,7 @@ enum_compact(VALUE obj)
*
* These methods return elements in sorted order:
*
- * - #sort: Returns the elements, sorted by <tt><=></tt> or the given block.
+ * - #sort: Returns the elements, sorted by <tt>#<=></tt> or the given block.
* - #sort_by: Returns the elements, sorted by the given block.
*
* === Methods for Iterating
@@ -4991,14 +5041,14 @@ enum_compact(VALUE obj)
*
* === Other Methods
*
- * - #map, #collect: Returns objects returned by the block.
+ * - #collect (aliased as #map): Returns objects returned by the block.
* - #filter_map: Returns truthy objects returned by the block.
- * - #flat_map, #collect_concat: Returns flattened objects returned by the block.
+ * - #flat_map (aliased as #collect_concat): Returns flattened objects returned by the block.
* - #grep: Returns elements selected by a given object
* or objects returned by a given block.
- * - #grep_v: Returns elements selected by a given object
+ * - #grep_v: Returns elements not selected by a given object
* or objects returned by a given block.
- * - #reduce, #inject: Returns the object formed by combining all elements.
+ * - #inject (aliased as #reduce): Returns the object formed by combining all elements.
* - #sum: Returns the sum of the elements, using method <tt>+</tt>.
* - #zip: Combines each element with elements from other enumerables;
* returns the n-tuples or calls the block with each.
@@ -5070,6 +5120,82 @@ enum_compact(VALUE obj)
* For some methods, though, the usage would not make sense,
* and so it is not shown. Example: #tally would find exactly one of each Hash entry.
*
+ * == Extended Methods
+ *
+ * A Enumerable class may define extended methods. This section describes the standard
+ * behavior of extension methods for reference purposes.
+ *
+ * === #size
+ *
+ * \Enumerator has a #size method.
+ * It uses the size function argument passed to +Enumerator.new+.
+ *
+ * e = Enumerator.new(-> { 3 }) {|y| p y; y.yield :a; y.yield :b; y.yield :c; :z }
+ * p e.size #=> 3
+ * p e.next #=> :a
+ * p e.next #=> :b
+ * p e.next #=> :c
+ * begin
+ * e.next
+ * rescue StopIteration
+ * p $!.result #=> :z
+ * end
+ *
+ * The result of the size function should represent the number of iterations
+ * (i.e., the number of times Enumerator::Yielder#yield is called).
+ * In the above example, the block calls #yield three times, and
+ * the size function, +-> { 3 }+, returns 3 accordingly.
+ * The result of the size function can be an integer, +Float::INFINITY+,
+ * or +nil+.
+ * An integer means the exact number of times #yield will be called,
+ * as shown above.
+ * +Float::INFINITY+ indicates an infinite number of #yield calls.
+ * +nil+ means the number of #yield calls is difficult or impossible to
+ * determine.
+ *
+ * Many iteration methods return an \Enumerator object with an
+ * appropriate size function if no block is given.
+ *
+ * Examples:
+ *
+ * ["a", "b", "c"].each.size #=> 3
+ * {a: "x", b: "y", c: "z"}.each.size #=> 3
+ * (0..20).to_a.permutation.size #=> 51090942171709440000
+ * loop.size #=> Float::INFINITY
+ * (1..100).drop_while.size #=> nil # size depends on the block's behavior
+ * STDIN.each.size #=> nil # cannot be computed without consuming input
+ * File.open("/etc/resolv.conf").each.size #=> nil # cannot be computed without reading the file
+ *
+ * The behavior of #size for Range-based enumerators depends on the #begin element:
+ *
+ * - If the #begin element is an Integer, the #size method returns an Integer or +Float::INFINITY+.
+ * - If the #begin element is an object with a #succ method (other than Integer), #size returns +nil+.
+ * (Computing the size would require repeatedly calling #succ, which may be too slow.)
+ * - If the #begin element does not have a #succ method, #size raises a TypeError.
+ *
+ * Examples:
+ *
+ * (10..42).each.size #=> 33
+ * (10..42.9).each.size #=> 33 (the #end element may be a non-integer numeric)
+ * (10..).each.size #=> Float::INFINITY
+ * ("a".."z").each.size #=> nil
+ * ("a"..).each.size #=> nil
+ * (1.0..9.0).each.size # raises TypeError (Float does not have #succ)
+ * (..10).each.size # raises TypeError (beginless range has nil as its #begin)
+ *
+ * The \Enumerable module itself does not define a #size method.
+ * A class that includes \Enumerable may define its own #size method.
+ * It is recommended that such a #size method be consistent with
+ * Enumerator#size.
+ *
+ * Array and Hash implement #size and return values consistent with
+ * Enumerator#size.
+ * IO and Dir do not define #size, which is also consistent because the
+ * corresponding enumerator's size function returns +nil+.
+ *
+ * However, it is not strictly required for a class's #size method to match Enumerator#size.
+ * For example, File#size returns the number of bytes in the file, not the number of lines.
+ *
*/
void
diff --git a/enumerator.c b/enumerator.c
index 193a865dbc..b60036a3de 100644
--- a/enumerator.c
+++ b/enumerator.c
@@ -18,6 +18,7 @@
#include <float.h>
#endif
+#include <limits.h>
#include "id.h"
#include "internal.h"
#include "internal/class.h"
@@ -33,79 +34,93 @@
/*
* Document-class: Enumerator
*
- * A class which allows both internal and external iteration.
+ * \Class \Enumerator supports:
*
- * An Enumerator can be created by the following methods.
- * - Object#to_enum
- * - Object#enum_for
- * - Enumerator.new
+ * - {External iteration}[rdoc-ref:Enumerator@External+Iteration].
+ * - {Internal iteration}[rdoc-ref:Enumerator@Internal+Iteration].
*
- * Most methods have two forms: a block form where the contents
- * are evaluated for each item in the enumeration, and a non-block form
- * which returns a new Enumerator wrapping the iteration.
+ * An \Enumerator may be created by the following methods:
*
- * enumerator = %w(one two three).each
- * puts enumerator.class # => Enumerator
+ * - Object#to_enum.
+ * - Object#enum_for.
+ * - Enumerator.new.
*
- * enumerator.each_with_object("foo") do |item, obj|
- * puts "#{obj}: #{item}"
- * end
+ * In addition, certain Ruby methods return \Enumerator objects:
+ * a Ruby iterator method that accepts a block
+ * may return an \Enumerator if no block is given.
+ * There are many such methods, for example, in classes Array and Hash.
+ * (In the documentation for those classes, search for `new_enumerator`.)
*
- * # foo: one
- * # foo: two
- * # foo: three
+ * == Internal Iteration
*
- * enum_with_obj = enumerator.each_with_object("foo")
- * puts enum_with_obj.class # => Enumerator
+ * In _internal iteration_, an iterator method drives the iteration
+ * and the caller's block handles the processing;
+ * this example uses method #each_with_index:
*
- * enum_with_obj.each do |item, obj|
- * puts "#{obj}: #{item}"
- * end
+ * words = %w[foo bar baz] # => ["foo", "bar", "baz"]
+ * enumerator = words.each # => #<Enumerator: ...>
+ * enumerator.each_with_index {|word, i| puts "#{i}: #{word}" }
+ * 0: foo
+ * 1: bar
+ * 2: baz
*
- * # foo: one
- * # foo: two
- * # foo: three
+ * Iterator methods in class \Enumerator include:
*
- * This allows you to chain Enumerators together. For example, you
- * can map a list's elements to strings containing the index
- * and the element as a string via:
+ * - #each:
+ * passes each item to the block.
+ * - #each_with_index:
+ * passes each item and its index to the block.
+ * - #each_with_object (aliased as #with_object):
+ * passes each item and a given object to the block.
+ * - #with_index:
+ * like #each_with_index, but starting at a given offset (instead of zero).
*
- * puts %w[foo bar baz].map.with_index { |w, i| "#{i}:#{w}" }
- * # => ["0:foo", "1:bar", "2:baz"]
+ * \Class \Enumerator includes module Enumerable,
+ * which provides many more iterator methods.
*
* == External Iteration
*
- * An Enumerator can also be used as an external iterator.
- * For example, Enumerator#next returns the next value of the iterator
- * or raises StopIteration if the Enumerator is at the end.
- *
- * e = [1,2,3].each # returns an enumerator object.
- * puts e.next # => 1
- * puts e.next # => 2
- * puts e.next # => 3
- * puts e.next # raises StopIteration
- *
- * +next+, +next_values+, +peek+, and +peek_values+ are the only methods
- * which use external iteration (and Array#zip(Enumerable-not-Array) which uses +next+ internally).
- *
- * These methods do not affect other internal enumeration methods,
- * unless the underlying iteration method itself has side-effect, e.g. IO#each_line.
- *
- * FrozenError will be raised if these methods are called against a frozen enumerator.
- * Since +rewind+ and +feed+ also change state for external iteration,
- * these methods may raise FrozenError too.
- *
- * External iteration differs *significantly* from internal iteration
- * due to using a Fiber:
- * - The Fiber adds some overhead compared to internal enumeration.
- * - The stacktrace will only include the stack from the Enumerator, not above.
- * - Fiber-local variables are *not* inherited inside the Enumerator Fiber,
- * which instead starts with no Fiber-local variables.
- * - Fiber storage variables *are* inherited and are designed
- * to handle Enumerator Fibers. Assigning to a Fiber storage variable
- * only affects the current Fiber, so if you want to change state
- * in the caller Fiber of the Enumerator Fiber, you need to use an
- * extra indirection (e.g., use some object in the Fiber storage
+ * In _external iteration_, the user's program both drives the iteration
+ * and handles the processing in stream-like fashion;
+ * this example uses method #next:
+ *
+ * words = %w[foo bar baz]
+ * enumerator = words.each
+ * enumerator.next # => "foo"
+ * enumerator.next # => "bar"
+ * enumerator.next # => "baz"
+ * enumerator.next # Raises StopIteration: iteration reached an end
+ *
+ * External iteration methods in class \Enumerator include:
+ *
+ * - #feed:
+ * sets the value that is next to be returned.
+ * - #next:
+ * returns the next value and increments the position.
+ * - #next_values:
+ * returns the next value in a 1-element array and increments the position.
+ * - #peek:
+ * returns the next value but does not increment the position.
+ * - #peek_values:
+ * returns the next value in a 1-element array but does not increment the position.
+ * - #rewind:
+ * sets the position to zero.
+ *
+ * Each of these methods raises FrozenError if called from a frozen \Enumerator.
+ *
+ * == External Iteration and \Fiber
+ *
+ * External iteration that uses Fiber differs *significantly* from internal iteration:
+ *
+ * - Using \Fiber adds some overhead compared to internal enumeration.
+ * - The stacktrace will only include the stack from the \Enumerator, not above.
+ * - \Fiber-local variables are *not* inherited inside the \Enumerator \Fiber,
+ * which instead starts with no \Fiber-local variables.
+ * - \Fiber storage variables *are* inherited and are designed
+ * to handle \Enumerator Fibers. Assigning to a \Fiber storage variable
+ * only affects the current \Fiber, so if you want to change state
+ * in the caller \Fiber of the \Enumerator \Fiber, you need to use an
+ * extra indirection (e.g., use some object in the \Fiber storage
* variable and mutate some ivar of it).
*
* Concretely:
@@ -125,7 +140,7 @@
* e.each { p _1 }
* p Fiber[:storage_var] # => 2 (it ran in the same Fiber/"stack" as the current Fiber)
*
- * == Convert External Iteration to Internal Iteration
+ * == Converting External Iteration to Internal Iteration
*
* You can use an external iterator to implement an internal iterator as follows:
*
@@ -162,10 +177,9 @@
*/
VALUE rb_cEnumerator;
static VALUE rb_cLazy;
-static ID id_rewind, id_new, id_to_enum, id_each_entry;
+static ID id_rewind, id_to_enum, id_each_entry;
static ID id_next, id_result, id_receiver, id_arguments, id_memo, id_method, id_force;
-static ID id_begin, id_end, id_step, id_exclude_end;
-static VALUE sym_each, sym_cycle, sym_yield;
+static VALUE sym_each, sym_yield;
static VALUE lazy_use_super_method;
@@ -222,6 +236,7 @@ struct yielder {
struct producer {
VALUE init;
VALUE proc;
+ VALUE size;
};
typedef struct MEMO *lazyenum_proc_func(VALUE, struct MEMO *, VALUE, long);
@@ -281,28 +296,20 @@ enumerator_ptr(VALUE obj)
}
static void
-proc_entry_mark(void *p)
-{
- struct proc_entry *ptr = p;
- rb_gc_mark_movable(ptr->proc);
- rb_gc_mark_movable(ptr->memo);
-}
-
-static void
-proc_entry_compact(void *p)
+proc_entry_mark_and_move(void *p)
{
struct proc_entry *ptr = p;
- ptr->proc = rb_gc_location(ptr->proc);
- ptr->memo = rb_gc_location(ptr->memo);
+ rb_gc_mark_and_move(&ptr->proc);
+ rb_gc_mark_and_move(&ptr->memo);
}
static const rb_data_type_t proc_entry_data_type = {
"proc_entry",
{
- proc_entry_mark,
+ proc_entry_mark_and_move,
RUBY_TYPED_DEFAULT_FREE,
NULL, // Nothing allocated externally, so don't need a memsize function
- proc_entry_compact,
+ proc_entry_mark_and_move,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
};
@@ -452,28 +459,31 @@ convert_to_feasible_size_value(VALUE obj)
/*
* call-seq:
- * Enumerator.new(size = nil) { |yielder| ... }
+ * Enumerator.new(size = nil) {|yielder| ... }
*
- * Creates a new Enumerator object, which can be used as an
- * Enumerable.
+ * Returns a new \Enumerator object that can be used for iteration.
*
- * 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 <code><<</code>):
+ * The given block defines the iteration;
+ * it is called with a "yielder" object that can yield an object
+ * via a call to method <tt>yielder.yield</tt>:
*
- * fib = Enumerator.new do |y|
- * a = b = 1
- * loop do
- * y << a
- * a, b = b, a + b
+ * fib = Enumerator.new do |yielder|
+ * n = next_n = 1
+ * while true do
+ * yielder.yield(n)
+ * n, next_n = next_n, n + next_n
* end
* end
*
* fib.take(10) # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
*
- * 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.
+ * Parameter +size+ specifies how the size is to be calculated (see #size);
+ * it can either be a value or a callable object:
+ *
+ * Enumerator.new{}.size # => nil
+ * Enumerator.new(42){}.size # => 42
+ * Enumerator.new(-> {42}){}.size # => 42
+ *
*/
static VALUE
enumerator_initialize(int argc, VALUE *argv, VALUE obj)
@@ -506,7 +516,7 @@ enumerator_init_copy(VALUE obj, VALUE orig)
}
RB_OBJ_WRITE(obj, &ptr1->obj, ptr0->obj);
- RB_OBJ_WRITE(obj, &ptr1->meth, ptr0->meth);
+ ptr1->meth = ptr0->meth;
RB_OBJ_WRITE(obj, &ptr1->args, ptr0->args);
ptr1->fib = 0;
ptr1->lookahead = Qundef;
@@ -679,7 +689,7 @@ enumerator_with_index(int argc, VALUE *argv, VALUE obj)
rb_check_arity(argc, 0, 1);
RETURN_SIZED_ENUMERATOR(obj, argc, argv, enumerator_enum_size);
memo = (!argc || NIL_P(memo = argv[0])) ? INT2FIX(0) : rb_to_int(memo);
- return enumerator_block_call(obj, enumerator_with_index_i, (VALUE)MEMO_NEW(memo, 0, 0));
+ return enumerator_block_call(obj, enumerator_with_index_i, (VALUE)rb_imemo_memo_new(memo, 0, 0));
}
/*
@@ -1238,6 +1248,24 @@ enumerator_inspect(VALUE obj)
* (1..100).to_a.permutation(4).size # => 94109400
* loop.size # => Float::INFINITY
* (1..100).drop_while.size # => nil
+ *
+ * Note that enumerator size might be inaccurate, and should be rather treated as a hint.
+ * For example, there is no check that the size provided to ::new is accurate:
+ *
+ * e = Enumerator.new(5) { |y| 2.times { y << it} }
+ * e.size # => 5
+ * e.to_a.size # => 2
+ *
+ * Another example is an enumerator created by ::produce without a +size+ argument.
+ * Such enumerators return +Infinity+ for size, but this is inaccurate if the passed
+ * block raises StopIteration:
+ *
+ * e = Enumerator.produce(1) { it + 1 }
+ * e.size # => Infinity
+ *
+ * e = Enumerator.produce(1) { it > 3 ? raise(StopIteration) : it + 1 }
+ * e.size # => Infinity
+ * e.to_a.size # => 4
*/
static VALUE
@@ -1281,26 +1309,19 @@ enumerator_size(VALUE obj)
* Yielder
*/
static void
-yielder_mark(void *p)
+yielder_mark_and_move(void *p)
{
struct yielder *ptr = p;
- rb_gc_mark_movable(ptr->proc);
-}
-
-static void
-yielder_compact(void *p)
-{
- struct yielder *ptr = p;
- ptr->proc = rb_gc_location(ptr->proc);
+ rb_gc_mark_and_move(&ptr->proc);
}
static const rb_data_type_t yielder_data_type = {
"yielder",
{
- yielder_mark,
+ yielder_mark_and_move,
RUBY_TYPED_DEFAULT_FREE,
NULL,
- yielder_compact,
+ yielder_mark_and_move,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
};
@@ -1411,28 +1432,20 @@ yielder_new(void)
* Generator
*/
static void
-generator_mark(void *p)
+generator_mark_and_move(void *p)
{
struct generator *ptr = p;
- rb_gc_mark_movable(ptr->proc);
- rb_gc_mark_movable(ptr->obj);
-}
-
-static void
-generator_compact(void *p)
-{
- struct generator *ptr = p;
- ptr->proc = rb_gc_location(ptr->proc);
- ptr->obj = rb_gc_location(ptr->obj);
+ rb_gc_mark_and_move(&ptr->proc);
+ rb_gc_mark_and_move(&ptr->obj);
}
static const rb_data_type_t generator_data_type = {
"generator",
{
- generator_mark,
+ generator_mark_and_move,
RUBY_TYPED_DEFAULT_FREE,
NULL,
- generator_compact,
+ generator_mark_and_move,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
};
@@ -1603,6 +1616,11 @@ lazy_init_block_i(RB_BLOCK_CALL_FUNC_ARGLIST(val, m))
#define LAZY_MEMO_SET_PACKED(memo) ((memo)->memo_flags |= LAZY_MEMO_PACKED)
#define LAZY_MEMO_RESET_PACKED(memo) ((memo)->memo_flags &= ~LAZY_MEMO_PACKED)
+#define LAZY_NEED_BLOCK(func) \
+ if (!rb_block_given_p()) { \
+ rb_raise(rb_eArgError, "tried to call lazy " #func " without a block"); \
+ }
+
static VALUE lazy_yielder_result(struct MEMO *result, VALUE yielder, VALUE procs_array, VALUE memos, long i);
static VALUE
@@ -1613,7 +1631,7 @@ lazy_init_yielder(RB_BLOCK_CALL_FUNC_ARGLIST(_, m))
VALUE memos = rb_attr_get(yielder, id_memo);
struct MEMO *result;
- result = MEMO_NEW(m, rb_enum_values_pack(argc, argv),
+ result = rb_imemo_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);
}
@@ -1806,9 +1824,7 @@ lazy_initialize(int argc, VALUE *argv, VALUE self)
VALUE generator;
rb_check_arity(argc, 1, 2);
- if (!rb_block_given_p()) {
- rb_raise(rb_eArgError, "tried to call lazy new without a block");
- }
+ LAZY_NEED_BLOCK(new);
obj = argv[0];
if (argc > 1) {
size = argv[1];
@@ -2066,10 +2082,7 @@ static const lazyenum_funcs lazy_map_funcs = {
static VALUE
lazy_map(VALUE obj)
{
- if (!rb_block_given_p()) {
- rb_raise(rb_eArgError, "tried to call lazy map without a block");
- }
-
+ LAZY_NEED_BLOCK(map);
return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_map_funcs);
}
@@ -2151,10 +2164,7 @@ static const lazyenum_funcs lazy_flat_map_funcs = {
static VALUE
lazy_flat_map(VALUE obj)
{
- if (!rb_block_given_p()) {
- rb_raise(rb_eArgError, "tried to call lazy flat_map without a block");
- }
-
+ LAZY_NEED_BLOCK(flat_map);
return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_flat_map_funcs);
}
@@ -2181,10 +2191,7 @@ static const lazyenum_funcs lazy_select_funcs = {
static VALUE
lazy_select(VALUE obj)
{
- if (!rb_block_given_p()) {
- rb_raise(rb_eArgError, "tried to call lazy select without a block");
- }
-
+ LAZY_NEED_BLOCK(select);
return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_select_funcs);
}
@@ -2215,10 +2222,7 @@ static const lazyenum_funcs lazy_filter_map_funcs = {
static VALUE
lazy_filter_map(VALUE obj)
{
- if (!rb_block_given_p()) {
- rb_raise(rb_eArgError, "tried to call lazy filter_map without a block");
- }
-
+ LAZY_NEED_BLOCK(filter_map);
return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_filter_map_funcs);
}
@@ -2244,10 +2248,7 @@ static const lazyenum_funcs lazy_reject_funcs = {
static VALUE
lazy_reject(VALUE obj)
{
- if (!rb_block_given_p()) {
- rb_raise(rb_eArgError, "tried to call lazy reject without a block");
- }
-
+ LAZY_NEED_BLOCK(reject);
return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_reject_funcs);
}
@@ -2400,7 +2401,6 @@ lazy_zip_func(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_inde
rb_ary_push(ary, v);
}
LAZY_MEMO_SET_VALUE(result, ary);
- LAZY_MEMO_SET_PACKED(result);
return result;
}
@@ -2531,10 +2531,7 @@ static const lazyenum_funcs lazy_take_while_funcs = {
static VALUE
lazy_take_while(VALUE obj)
{
- if (!rb_block_given_p()) {
- rb_raise(rb_eArgError, "tried to call lazy take_while without a block");
- }
-
+ LAZY_NEED_BLOCK(take_while);
return lazy_add_method(obj, 0, 0, Qnil, Qnil, &lazy_take_while_funcs);
}
@@ -2629,10 +2626,7 @@ static const lazyenum_funcs lazy_drop_while_funcs = {
static VALUE
lazy_drop_while(VALUE obj)
{
- if (!rb_block_given_p()) {
- rb_raise(rb_eArgError, "tried to call lazy drop_while without a block");
- }
-
+ LAZY_NEED_BLOCK(drop_while);
return lazy_add_method(obj, 0, 0, Qfalse, Qnil, &lazy_drop_while_funcs);
}
@@ -2914,19 +2908,12 @@ stop_result(VALUE self)
*/
static void
-producer_mark(void *p)
+producer_mark_and_move(void *p)
{
struct producer *ptr = p;
- rb_gc_mark_movable(ptr->init);
- rb_gc_mark_movable(ptr->proc);
-}
-
-static void
-producer_compact(void *p)
-{
- struct producer *ptr = p;
- ptr->init = rb_gc_location(ptr->init);
- ptr->proc = rb_gc_location(ptr->proc);
+ rb_gc_mark_and_move(&ptr->init);
+ rb_gc_mark_and_move(&ptr->proc);
+ rb_gc_mark_and_move(&ptr->size);
}
#define producer_free RUBY_TYPED_DEFAULT_FREE
@@ -2940,10 +2927,10 @@ producer_memsize(const void *p)
static const rb_data_type_t producer_data_type = {
"producer",
{
- producer_mark,
+ producer_mark_and_move,
producer_free,
producer_memsize,
- producer_compact,
+ producer_mark_and_move,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
};
@@ -2970,12 +2957,13 @@ producer_allocate(VALUE klass)
obj = TypedData_Make_Struct(klass, struct producer, &producer_data_type, ptr);
ptr->init = Qundef;
ptr->proc = Qundef;
+ ptr->size = Qnil;
return obj;
}
static VALUE
-producer_init(VALUE obj, VALUE init, VALUE proc)
+producer_init(VALUE obj, VALUE init, VALUE proc, VALUE size)
{
struct producer *ptr;
@@ -2987,6 +2975,7 @@ producer_init(VALUE obj, VALUE init, VALUE proc)
RB_OBJ_WRITE(obj, &ptr->init, init);
RB_OBJ_WRITE(obj, &ptr->proc, proc);
+ RB_OBJ_WRITE(obj, &ptr->size, size);
return obj;
}
@@ -3037,12 +3026,18 @@ producer_each(VALUE obj)
static VALUE
producer_size(VALUE obj, VALUE args, VALUE eobj)
{
- return DBL2NUM(HUGE_VAL);
+ struct producer *ptr = producer_ptr(obj);
+ VALUE size = ptr->size;
+
+ if (NIL_P(size)) return Qnil;
+ if (RB_INTEGER_TYPE_P(size) || RB_FLOAT_TYPE_P(size)) return size;
+
+ return rb_funcall(size, id_call, 0);
}
/*
* call-seq:
- * Enumerator.produce(initial = nil) { |prev| block } -> enumerator
+ * Enumerator.produce(initial = nil, size: nil) { |prev| block } -> enumerator
*
* Creates an infinite enumerator from any block, just called over and
* over. The result of the previous iteration is passed to the next one.
@@ -3074,19 +3069,50 @@ producer_size(VALUE obj, VALUE args, VALUE eobj)
* PATTERN = %r{\d+|[-/+*]}
* Enumerator.produce { scanner.scan(PATTERN) }.slice_after { scanner.eos? }.first
* # => ["7", "+", "38", "/", "6"]
+ *
+ * The optional +size+ keyword argument specifies the size of the enumerator,
+ * which can be retrieved by Enumerator#size. It can be an integer,
+ * +Float::INFINITY+, a callable object (such as a lambda), or +nil+ to
+ * indicate unknown size. When not specified, the size defaults to
+ * +Float::INFINITY+.
+ *
+ * # Infinite enumerator
+ * enum = Enumerator.produce(1, size: Float::INFINITY, &:succ)
+ * enum.size # => Float::INFINITY
+ *
+ * # Finite enumerator with known/computable size
+ * abs_dir = File.expand_path("./baz") # => "/foo/bar/baz"
+ * traverser = Enumerator.produce(abs_dir, size: -> { abs_dir.count("/") + 1 }) {
+ * raise StopIteration if it == "/"
+ * File.dirname(it)
+ * }
+ * traverser.size # => 4
+ *
+ * # Finite enumerator with unknown size
+ * calendar = Enumerator.produce(Date.today, size: nil) {
+ * it.monday? ? raise(StopIteration) : it + 1
+ * }
+ * calendar.size # => nil
*/
static VALUE
enumerator_s_produce(int argc, VALUE *argv, VALUE klass)
{
- VALUE init, producer;
+ VALUE init, producer, opts, size;
+ ID keyword_ids[1];
if (!rb_block_given_p()) rb_raise(rb_eArgError, "no block given");
- if (rb_scan_args(argc, argv, "01", &init) == 0) {
+ keyword_ids[0] = rb_intern("size");
+ rb_scan_args_kw(RB_SCAN_ARGS_LAST_HASH_KEYWORDS, argc, argv, "01:", &init, &opts);
+ rb_get_kwargs(opts, keyword_ids, 0, 1, &size);
+
+ size = UNDEF_P(size) ? DBL2NUM(HUGE_VAL) : convert_to_feasible_size_value(size);
+
+ if (argc == 0 || (argc == 1 && !NIL_P(opts))) {
init = Qundef;
}
- producer = producer_init(producer_allocate(rb_cEnumProducer), init, rb_block_proc());
+ producer = producer_init(producer_allocate(rb_cEnumProducer), init, rb_block_proc(), size);
return rb_enumeratorize_with_size_kw(producer, sym_each, 0, 0, producer_size, RB_NO_KEYWORDS);
}
@@ -3102,17 +3128,10 @@ enumerator_s_produce(int argc, VALUE *argv, VALUE klass)
*/
static void
-enum_chain_mark(void *p)
-{
- struct enum_chain *ptr = p;
- rb_gc_mark_movable(ptr->enums);
-}
-
-static void
-enum_chain_compact(void *p)
+enum_chain_mark_and_move(void *p)
{
struct enum_chain *ptr = p;
- ptr->enums = rb_gc_location(ptr->enums);
+ rb_gc_mark_and_move(&ptr->enums);
}
#define enum_chain_free RUBY_TYPED_DEFAULT_FREE
@@ -3126,12 +3145,12 @@ enum_chain_memsize(const void *p)
static const rb_data_type_t enum_chain_data_type = {
"chain",
{
- enum_chain_mark,
+ enum_chain_mark_and_move,
enum_chain_free,
enum_chain_memsize,
- enum_chain_compact,
+ enum_chain_mark_and_move,
},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
};
static struct enum_chain *
@@ -3181,7 +3200,7 @@ enum_chain_initialize(VALUE obj, VALUE enums)
if (!ptr) rb_raise(rb_eArgError, "unallocated chain");
- ptr->enums = rb_obj_freeze(enums);
+ RB_OBJ_WRITE(obj, &ptr->enums, rb_ary_freeze(enums));
ptr->pos = -1;
return obj;
@@ -3215,7 +3234,7 @@ enum_chain_init_copy(VALUE obj, VALUE orig)
if (!ptr1) rb_raise(rb_eArgError, "unallocated chain");
- ptr1->enums = ptr0->enums;
+ RB_OBJ_WRITE(obj, &ptr1->enums, ptr0->enums);
ptr1->pos = ptr0->pos;
return obj;
@@ -3424,17 +3443,10 @@ enumerator_plus(VALUE obj, VALUE eobj)
*/
static void
-enum_product_mark(void *p)
+enum_product_mark_and_move(void *p)
{
struct enum_product *ptr = p;
- rb_gc_mark_movable(ptr->enums);
-}
-
-static void
-enum_product_compact(void *p)
-{
- struct enum_product *ptr = p;
- ptr->enums = rb_gc_location(ptr->enums);
+ rb_gc_mark_and_move(&ptr->enums);
}
#define enum_product_free RUBY_TYPED_DEFAULT_FREE
@@ -3448,12 +3460,12 @@ enum_product_memsize(const void *p)
static const rb_data_type_t enum_product_data_type = {
"product",
{
- enum_product_mark,
+ enum_product_mark_and_move,
enum_product_free,
enum_product_memsize,
- enum_product_compact,
+ enum_product_mark_and_move,
},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
};
static struct enum_product *
@@ -3509,7 +3521,7 @@ enum_product_initialize(int argc, VALUE *argv, VALUE obj)
if (!ptr) rb_raise(rb_eArgError, "unallocated product");
- ptr->enums = rb_obj_freeze(enums);
+ RB_OBJ_WRITE(obj, &ptr->enums, rb_ary_freeze(enums));
return obj;
}
@@ -3527,7 +3539,7 @@ enum_product_init_copy(VALUE obj, VALUE orig)
if (!ptr1) rb_raise(rb_eArgError, "unallocated product");
- ptr1->enums = ptr0->enums;
+ RB_OBJ_WRITE(obj, &ptr1->enums, ptr0->enums);
return obj;
}
@@ -3587,9 +3599,9 @@ enum_product_enum_size(VALUE obj, VALUE args, VALUE eobj)
struct product_state {
VALUE obj;
VALUE block;
+ int index;
int argc;
VALUE *argv;
- int index;
};
static VALUE product_each(VALUE, struct product_state *);
@@ -3628,15 +3640,23 @@ enum_product_run(VALUE obj, VALUE block)
{
struct enum_product *ptr = enum_product_ptr(obj);
int argc = RARRAY_LENINT(ptr->enums);
+ if (argc == 0) { /* no need to allocate state.argv */
+ rb_funcall(block, id_call, 1, rb_ary_new());
+ return obj;
+ }
+
+ VALUE argsbuf = 0;
struct product_state state = {
.obj = obj,
.block = block,
.index = 0,
.argc = argc,
- .argv = ALLOCA_N(VALUE, argc),
+ .argv = ALLOCV_N(VALUE, argsbuf, argc),
};
- return product_each(obj, &state);
+ VALUE ret = product_each(obj, &state);
+ ALLOCV_END(argsbuf);
+ return ret;
}
/*
@@ -3749,6 +3769,55 @@ enumerator_s_product(int argc, VALUE *argv, VALUE klass)
return obj;
}
+struct arith_seq {
+ struct enumerator enumerator;
+ VALUE begin;
+ VALUE end;
+ VALUE step;
+ bool exclude_end;
+};
+
+RUBY_REFERENCES(arith_seq_refs) = {
+ RUBY_REF_EDGE(struct enumerator, obj),
+ RUBY_REF_EDGE(struct enumerator, args),
+ RUBY_REF_EDGE(struct enumerator, fib),
+ RUBY_REF_EDGE(struct enumerator, dst),
+ RUBY_REF_EDGE(struct enumerator, lookahead),
+ RUBY_REF_EDGE(struct enumerator, feedvalue),
+ RUBY_REF_EDGE(struct enumerator, stop_exc),
+ RUBY_REF_EDGE(struct enumerator, size),
+ RUBY_REF_EDGE(struct enumerator, procs),
+
+ RUBY_REF_EDGE(struct arith_seq, begin),
+ RUBY_REF_EDGE(struct arith_seq, end),
+ RUBY_REF_EDGE(struct arith_seq, step),
+ RUBY_REF_END
+};
+
+static const rb_data_type_t arith_seq_data_type = {
+ "arithmetic_sequence",
+ {
+ RUBY_REFS_LIST_PTR(arith_seq_refs),
+ RUBY_TYPED_DEFAULT_FREE,
+ NULL, // Nothing allocated externally, so don't need a memsize function
+ NULL,
+ },
+ .parent = &enumerator_data_type,
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_DECL_MARKING | RUBY_TYPED_EMBEDDABLE
+};
+
+static VALUE
+arith_seq_allocate(VALUE klass)
+{
+ struct arith_seq *ptr;
+ VALUE enum_obj;
+
+ enum_obj = TypedData_Make_Struct(klass, struct arith_seq, &arith_seq_data_type, ptr);
+ ptr->enumerator.obj = Qundef;
+
+ return enum_obj;
+}
+
/*
* Document-class: Enumerator::ArithmeticSequence
*
@@ -3766,12 +3835,16 @@ rb_arith_seq_new(VALUE obj, VALUE meth, int argc, VALUE const *argv,
rb_enumerator_size_func *size_fn,
VALUE beg, VALUE end, VALUE step, int excl)
{
- VALUE aseq = enumerator_init(enumerator_allocate(rb_cArithSeq),
+ VALUE aseq = enumerator_init(arith_seq_allocate(rb_cArithSeq),
obj, meth, argc, argv, size_fn, Qnil, rb_keyword_given_p());
- rb_ivar_set(aseq, id_begin, beg);
- rb_ivar_set(aseq, id_end, end);
- rb_ivar_set(aseq, id_step, step);
- rb_ivar_set(aseq, id_exclude_end, RBOOL(excl));
+ struct arith_seq *ptr;
+ TypedData_Get_Struct(aseq, struct arith_seq, &enumerator_data_type, ptr);
+
+ RB_OBJ_WRITE(aseq, &ptr->begin, beg);
+ RB_OBJ_WRITE(aseq, &ptr->end, end);
+ RB_OBJ_WRITE(aseq, &ptr->step, step);
+ ptr->exclude_end = excl;
+
return aseq;
}
@@ -3784,7 +3857,9 @@ rb_arith_seq_new(VALUE obj, VALUE meth, int argc, VALUE const *argv,
static inline VALUE
arith_seq_begin(VALUE self)
{
- return rb_ivar_get(self, id_begin);
+ struct arith_seq *ptr;
+ TypedData_Get_Struct(self, struct arith_seq, &enumerator_data_type, ptr);
+ return ptr->begin;
}
/*
@@ -3795,7 +3870,9 @@ arith_seq_begin(VALUE self)
static inline VALUE
arith_seq_end(VALUE self)
{
- return rb_ivar_get(self, id_end);
+ struct arith_seq *ptr;
+ TypedData_Get_Struct(self, struct arith_seq, &enumerator_data_type, ptr);
+ return ptr->end;
}
/*
@@ -3807,7 +3884,9 @@ arith_seq_end(VALUE self)
static inline VALUE
arith_seq_step(VALUE self)
{
- return rb_ivar_get(self, id_step);
+ struct arith_seq *ptr;
+ TypedData_Get_Struct(self, struct arith_seq, &enumerator_data_type, ptr);
+ return ptr->step;
}
/*
@@ -3818,13 +3897,17 @@ arith_seq_step(VALUE self)
static inline VALUE
arith_seq_exclude_end(VALUE self)
{
- return rb_ivar_get(self, id_exclude_end);
+ struct arith_seq *ptr;
+ TypedData_Get_Struct(self, struct arith_seq, &enumerator_data_type, ptr);
+ return RBOOL(ptr->exclude_end);
}
static inline int
arith_seq_exclude_end_p(VALUE self)
{
- return RTEST(arith_seq_exclude_end(self));
+ struct arith_seq *ptr;
+ TypedData_Get_Struct(self, struct arith_seq, &enumerator_data_type, ptr);
+ return ptr->exclude_end;
}
int
@@ -3891,46 +3974,14 @@ rb_arithmetic_sequence_beg_len_step(VALUE obj, long *begp, long *lenp, long *ste
return Qnil;
}
-/*
- * call-seq:
- * aseq.first -> num or nil
- * aseq.first(n) -> an_array
- *
- * Returns the first number in this arithmetic sequence,
- * or an array of the first +n+ elements.
- */
static VALUE
-arith_seq_first(int argc, VALUE *argv, VALUE self)
+arith_seq_take(VALUE self, VALUE num)
{
VALUE b, e, s, ary;
long n;
int x;
- rb_check_arity(argc, 0, 1);
-
- b = arith_seq_begin(self);
- e = arith_seq_end(self);
- s = arith_seq_step(self);
- if (argc == 0) {
- if (NIL_P(b)) {
- return Qnil;
- }
- if (!NIL_P(e)) {
- VALUE zero = INT2FIX(0);
- int r = rb_cmpint(rb_num_coerce_cmp(s, zero, idCmp), s, zero);
- if (r > 0 && RTEST(rb_funcall(b, '>', 1, e))) {
- return Qnil;
- }
- if (r < 0 && RTEST(rb_funcall(b, '<', 1, e))) {
- return Qnil;
- }
- }
- return b;
- }
-
- // TODO: the following code should be extracted as arith_seq_take
-
- n = NUM2LONG(argv[0]);
+ n = NUM2LONG(num);
if (n < 0) {
rb_raise(rb_eArgError, "attempt to take negative size");
}
@@ -3938,6 +3989,9 @@ arith_seq_first(int argc, VALUE *argv, VALUE self)
return rb_ary_new_capa(0);
}
+ b = arith_seq_begin(self);
+ e = arith_seq_end(self);
+ s = arith_seq_step(self);
x = arith_seq_exclude_end_p(self);
if (FIXNUM_P(b) && NIL_P(e) && FIXNUM_P(s)) {
@@ -3972,7 +4026,7 @@ arith_seq_first(int argc, VALUE *argv, VALUE self)
ary = rb_ary_new_capa((n < len) ? n : len);
while (n > 0 && i < end) {
rb_ary_push(ary, LONG2FIX(i));
- if (i + unit < i) break;
+ if (i > LONG_MAX - unit) break;
i += unit;
--n;
}
@@ -3985,7 +4039,7 @@ arith_seq_first(int argc, VALUE *argv, VALUE self)
ary = rb_ary_new_capa((n < len) ? n : len);
while (n > 0 && i > end) {
rb_ary_push(ary, LONG2FIX(i));
- if (i + unit > i) break;
+ if (i < LONG_MIN - unit) break;
i += unit;
--n;
}
@@ -4032,7 +4086,49 @@ arith_seq_first(int argc, VALUE *argv, VALUE self)
return ary;
}
- return rb_call_super(argc, argv);
+ {
+ VALUE argv[1];
+ argv[0] = num;
+ return rb_call_super(1, argv);
+ }
+}
+
+/*
+ * call-seq:
+ * aseq.first -> num or nil
+ * aseq.first(n) -> an_array
+ *
+ * Returns the first number in this arithmetic sequence,
+ * or an array of the first +n+ elements.
+ */
+static VALUE
+arith_seq_first(int argc, VALUE *argv, VALUE self)
+{
+ VALUE b, e, s;
+
+ rb_check_arity(argc, 0, 1);
+
+ b = arith_seq_begin(self);
+ e = arith_seq_end(self);
+ s = arith_seq_step(self);
+ if (argc == 0) {
+ if (NIL_P(b)) {
+ return Qnil;
+ }
+ if (!NIL_P(e)) {
+ VALUE zero = INT2FIX(0);
+ int r = rb_cmpint(rb_num_coerce_cmp(s, zero, idCmp), s, zero);
+ if (r > 0 && RTEST(rb_funcall(b, '>', 1, e))) {
+ return Qnil;
+ }
+ if (r < 0 && RTEST(rb_funcall(b, '<', 1, e))) {
+ return Qnil;
+ }
+ }
+ return b;
+ }
+
+ return arith_seq_take(self, argv[0]);
}
static inline VALUE
@@ -4665,7 +4761,6 @@ void
Init_Enumerator(void)
{
id_rewind = rb_intern_const("rewind");
- id_new = rb_intern_const("new");
id_next = rb_intern_const("next");
id_result = rb_intern_const("result");
id_receiver = rb_intern_const("receiver");
@@ -4675,12 +4770,7 @@ Init_Enumerator(void)
id_force = rb_intern_const("force");
id_to_enum = rb_intern_const("to_enum");
id_each_entry = rb_intern_const("each_entry");
- id_begin = rb_intern_const("begin");
- id_end = rb_intern_const("end");
- id_step = rb_intern_const("step");
- id_exclude_end = rb_intern_const("exclude_end");
sym_each = ID2SYM(id_each);
- sym_cycle = ID2SYM(rb_intern_const("cycle"));
sym_yield = ID2SYM(rb_intern_const("yield"));
InitVM(Enumerator);
diff --git a/error.c b/error.c
index bb063a1772..d6518feb34 100644
--- a/error.c
+++ b/error.c
@@ -86,6 +86,7 @@ static ID id_category;
static ID id_deprecated;
static ID id_experimental;
static ID id_performance;
+static ID id_strict_unused_block;
static VALUE sym_category;
static VALUE sym_highlight;
static struct {
@@ -217,7 +218,6 @@ rb_warning_category_enabled_p(rb_warning_category_t category)
*
* +:experimental+ ::
* experimental features
- * * Pattern matching
*
* +:performance+ ::
* performance hints
@@ -475,7 +475,7 @@ rb_warn(const char *fmt, ...)
void
rb_category_warn(rb_warning_category_t category, const char *fmt, ...)
{
- if (!NIL_P(ruby_verbose)) {
+ if (!NIL_P(ruby_verbose) && rb_warning_category_enabled_p(category)) {
with_warning_string(mesg, 0, fmt) {
rb_warn_category(mesg, rb_warning_category_to_name(category));
}
@@ -507,7 +507,7 @@ rb_warning(const char *fmt, ...)
void
rb_category_warning(rb_warning_category_t category, const char *fmt, ...)
{
- if (RTEST(ruby_verbose)) {
+ if (RTEST(ruby_verbose) && rb_warning_category_enabled_p(category)) {
with_warning_string(mesg, 0, fmt) {
rb_warn_category(mesg, rb_warning_category_to_name(category));
}
@@ -575,6 +575,18 @@ rb_warn_deprecated_to_remove(const char *removal, const char *fmt, const char *s
}
}
+void
+rb_warn_reserved_name(const char *coming, const char *fmt, ...)
+{
+ if (!deprecation_warning_enabled()) return;
+
+ with_warning_string_from(mesg, 0, fmt, fmt) {
+ rb_str_set_len(mesg, RSTRING_LEN(mesg) - 1);
+ rb_str_catf(mesg, " is reserved for Ruby %s\n", coming);
+ rb_warn_category(mesg, ID2SYM(id_deprecated));
+ }
+}
+
static inline int
end_with_asciichar(VALUE str, int c)
{
@@ -1065,6 +1077,7 @@ static void
die(void)
{
#if defined(_WIN32) && defined(RUBY_MSVCRT_VERSION) && RUBY_MSVCRT_VERSION >= 80
+ /* mingw32 declares in stdlib.h but does not provide. */
_set_abort_behavior( 0, _CALL_REPORTFAULT);
#endif
@@ -1072,25 +1085,35 @@ die(void)
}
RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 0)
-void
-rb_bug_without_die(const char *fmt, va_list args)
+static void
+rb_bug_without_die_internal(const char *fmt, va_list args)
{
const char *file = NULL;
int line = 0;
- if (GET_EC()) {
+ if (rb_current_execution_context(false)) {
file = rb_source_location_cstr(&line);
}
report_bug_valist(file, line, fmt, NULL, args);
}
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 0)
+void
+rb_bug_without_die(const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ rb_bug_without_die_internal(fmt, args);
+ va_end(args);
+}
+
void
rb_bug(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
- rb_bug_without_die(fmt, args);
+ rb_bug_without_die_internal(fmt, args);
va_end(args);
die();
}
@@ -1101,7 +1124,7 @@ rb_bug_for_fatal_signal(ruby_sighandler_t default_sighandler, int sig, const voi
const char *file = NULL;
int line = 0;
- if (GET_EC()) {
+ if (rb_current_execution_context(false)) {
file = rb_source_location_cstr(&line);
}
@@ -1173,21 +1196,27 @@ void
rb_assert_failure_detail(const char *file, int line, const char *name, const char *expr,
const char *fmt, ...)
{
- FILE *out = stderr;
- fprintf(out, "Assertion Failed: %s:%d:", file, line);
- if (name) fprintf(out, "%s:", name);
- fprintf(out, "%s\n%s\n\n", expr, rb_dynamic_description);
+ rb_pid_t pid = -1;
+ FILE *out = bug_report_file(file, line, &pid);
+ if (out) {
+ fputs("Assertion Failed: ", out);
+ if (name) fprintf(out, "%s:", name);
+ fputs(expr, out);
+
+ if (fmt && *fmt) {
+ va_list args;
+ va_start(args, fmt);
+ fputs(": ", out);
+ vfprintf(out, fmt, args);
+ va_end(args);
+ }
+ fprintf(out, "\n%s\n\n", rb_dynamic_description);
- if (fmt && *fmt) {
- va_list args;
- va_start(args, fmt);
- vfprintf(out, fmt, args);
- va_end(args);
+ preface_dump(out);
+ rb_vm_bugreport(NULL, out);
+ bug_report_end(out, pid);
}
- preface_dump(out);
- rb_vm_bugreport(NULL, out);
- bug_report_end(out, -1);
die();
}
@@ -1284,6 +1313,20 @@ rb_builtin_class_name(VALUE x)
COLDFUNC NORETURN(static void unexpected_type(VALUE, int, int));
#define UNDEF_LEAKED "undef leaked to the Ruby space"
+void
+rb_unexpected_typeddata(const rb_data_type_t *actual, const rb_data_type_t *expected)
+{
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
+ actual->wrap_struct_name, expected->wrap_struct_name);
+}
+
+void
+rb_unexpected_object_type(VALUE obj, const char *expected)
+{
+ rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected %s)",
+ displaying_class_of(obj), expected);
+}
+
static void
unexpected_type(VALUE x, int xt, int t)
{
@@ -1291,9 +1334,7 @@ unexpected_type(VALUE x, int xt, int t)
VALUE mesg, exc = rb_eFatal;
if (tname) {
- mesg = rb_sprintf("wrong argument type %"PRIsVALUE" (expected %s)",
- displaying_class_of(x), tname);
- exc = rb_eTypeError;
+ rb_unexpected_object_type(x, tname);
}
else if (xt > T_MASK && xt <= 0x3f) {
mesg = rb_sprintf("unknown type 0x%x (0x%x given, probably comes"
@@ -1338,24 +1379,18 @@ rb_unexpected_type(VALUE x, int t)
unexpected_type(x, TYPE(x), t);
}
+#undef rb_typeddata_inherited_p
int
rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent)
{
- while (child) {
- if (child == parent) return 1;
- child = child->parent;
- }
- return 0;
+ return rbimpl_typeddata_inherited_p_inline(child, parent);
}
+#undef rb_typeddata_is_kind_of
int
rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type)
{
- if (!RB_TYPE_P(obj, T_DATA) ||
- !RTYPEDDATA_P(obj) || !rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj), data_type)) {
- return 0;
- }
- return 1;
+ return rbimpl_typeddata_is_kind_of_inline(obj, data_type);
}
#undef rb_typeddata_is_instance_of
@@ -1368,26 +1403,7 @@ 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)
{
- VALUE actual;
-
- if (!RB_TYPE_P(obj, T_DATA)) {
- 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)) {
- const char *name = RTYPEDDATA_TYPE(obj)->wrap_struct_name;
- actual = rb_str_new_cstr(name); /* or rb_fstring_cstr? not sure... */
- }
- else {
- return RTYPEDDATA_GET_DATA(obj);
- }
-
- const char *expected = data_type->wrap_struct_name;
- rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected %s)",
- actual, expected);
- UNREACHABLE_RETURN(NULL);
+ return rbimpl_check_typeddata(obj, data_type);
}
/* exception classes */
@@ -1467,12 +1483,23 @@ exc_init(VALUE exc, VALUE mesg)
}
/*
- * call-seq:
- * Exception.new(msg = nil) -> exception
- * Exception.exception(msg = nil) -> exception
+ * call-seq:
+ * Exception.new(message = nil) -> exception
+ *
+ * Returns a new exception object.
+ *
+ * The given +message+ should be
+ * a {string-convertible object}[rdoc-ref:implicit_conversion.rdoc@String-Convertible+Objects];
+ * see method #message;
+ * if not given, the message is the class name of the new instance
+ * (which may be the name of a subclass):
+ *
+ * Examples:
+ *
+ * Exception.new # => #<Exception: Exception>
+ * LoadError.new # => #<LoadError: LoadError> # Subclass of Exception.
+ * Exception.new('Boom') # => #<Exception: Boom>
*
- * Construct a new Exception object, optionally passing in
- * a message.
*/
static VALUE
@@ -1488,12 +1515,24 @@ exc_initialize(int argc, VALUE *argv, VALUE exc)
* Document-method: exception
*
* call-seq:
- * exc.exception([string]) -> an_exception or exc
+ * exception(message = nil) -> self or new_exception
+ *
+ * Returns an exception object of the same class as +self+;
+ * useful for creating a similar exception, but with a different message.
+ *
+ * With +message+ +nil+, returns +self+:
*
- * With no argument, or if the argument is the same as the receiver,
- * return the receiver. Otherwise, create a new
- * exception object of the same class as the receiver, but with a
- * message equal to <code>string.to_str</code>.
+ * x0 = StandardError.new('Boom') # => #<StandardError: Boom>
+ * x1 = x0.exception # => #<StandardError: Boom>
+ * x0.__id__ == x1.__id__ # => true
+ *
+ * With {string-convertible object}[rdoc-ref:implicit_conversion.rdoc@String-Convertible+Objects]
+ * +message+ (even the same as the original message),
+ * returns a new exception object whose class is the same as +self+,
+ * and whose message is the given +message+:
+ *
+ * x1 = x0.exception('Boom') # => #<StandardError: Boom>
+ * x0..equal?(x1) # => false
*
*/
@@ -1512,10 +1551,15 @@ exc_exception(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * exception.to_s -> string
+ * to_s -> string
+ *
+ * Returns a string representation of +self+:
+ *
+ * x = RuntimeError.new('Boom')
+ * x.to_s # => "Boom"
+ * x = RuntimeError.new
+ * x.to_s # => "RuntimeError"
*
- * Returns exception's message (or the name of the exception if
- * no message is set).
*/
static VALUE
@@ -1555,10 +1599,10 @@ rb_get_detailed_message(VALUE exc, VALUE opt)
}
/*
- * call-seq:
- * Exception.to_tty? -> true or false
+ * call-seq:
+ * Exception.to_tty? -> true or false
*
- * Returns +true+ if exception messages will be sent to a tty.
+ * Returns +true+ if exception messages will be sent to a terminal device.
*/
static VALUE
exc_s_to_tty_p(VALUE self)
@@ -1618,20 +1662,51 @@ check_order_keyword(VALUE opt)
/*
* call-seq:
- * exception.full_message(highlight: bool, order: [:top or :bottom]) -> string
+ * full_message(highlight: true, order: :top) -> string
*
- * Returns formatted string of _exception_.
- * The returned string is formatted using the same format that Ruby uses
- * when printing an uncaught exceptions to stderr.
+ * Returns an enhanced message string:
*
- * If _highlight_ is +true+ the default error handler will send the
- * messages to a tty.
+ * - Includes the exception class name.
+ * - If the value of keyword +highlight+ is true (not +nil+ or +false+),
+ * includes bolding ANSI codes (see below) to enhance the appearance of the message.
+ * - Includes the {backtrace}[rdoc-ref:exceptions.md@Backtraces]:
*
- * _order_ must be either of +:top+ or +:bottom+, and places the error
- * message and the innermost backtrace come at the top or the bottom.
+ * - If the value of keyword +order+ is +:top+ (the default),
+ * lists the error message and the innermost backtrace entry first.
+ * - If the value of keyword +order+ is +:bottom+,
+ * lists the error message the innermost entry last.
*
- * The default values of these options depend on <code>$stderr</code>
- * and its +tty?+ at the timing of a call.
+ * Example:
+ *
+ * def baz
+ * begin
+ * 1 / 0
+ * rescue => x
+ * pp x.message
+ * pp x.full_message(highlight: false).split("\n")
+ * pp x.full_message.split("\n")
+ * end
+ * end
+ * def bar; baz; end
+ * def foo; bar; end
+ * foo
+ *
+ * Output:
+ *
+ * "divided by 0"
+ * ["t.rb:3:in 'Integer#/': divided by 0 (ZeroDivisionError)",
+ * "\tfrom t.rb:3:in 'Object#baz'",
+ * "\tfrom t.rb:10:in 'Object#bar'",
+ * "\tfrom t.rb:11:in 'Object#foo'",
+ * "\tfrom t.rb:12:in '<main>'"]
+ * ["t.rb:3:in 'Integer#/': \e[1mdivided by 0 (\e[1;4mZeroDivisionError\e[m\e[1m)\e[m",
+ * "\tfrom t.rb:3:in 'Object#baz'",
+ * "\tfrom t.rb:10:in 'Object#bar'",
+ * "\tfrom t.rb:11:in 'Object#foo'",
+ * "\tfrom t.rb:12:in '<main>'"]
+ *
+ * An overriding method should be careful with ANSI code enhancements;
+ * see {Messages}[rdoc-ref:exceptions.md@Messages].
*/
static VALUE
@@ -1660,10 +1735,11 @@ exc_full_message(int argc, VALUE *argv, VALUE exc)
/*
* call-seq:
- * exception.message -> string
+ * message -> string
*
- * Returns the result of invoking <code>exception.to_s</code>.
- * Normally this returns the exception's message or name.
+ * Returns #to_s.
+ *
+ * See {Messages}[rdoc-ref:exceptions.md@Messages].
*/
static VALUE
@@ -1674,42 +1750,47 @@ exc_message(VALUE exc)
/*
* call-seq:
- * exception.detailed_message(highlight: bool, **opt) -> string
+ * detailed_message(highlight: false, **kwargs) -> string
+ *
+ * Returns the message string with enhancements:
+ *
+ * - Includes the exception class name in the first line.
+ * - If the value of keyword +highlight+ is +true+,
+ * includes bolding and underlining ANSI codes (see below)
+ * to enhance the appearance of the message.
*
- * Processes a string returned by #message.
+ * Examples:
*
- * It may add the class name of the exception to the end of the first line.
- * Also, when +highlight+ keyword is true, it adds ANSI escape sequences to
- * make the message bold.
+ * begin
+ * 1 / 0
+ * rescue => x
+ * p x.message
+ * p x.detailed_message # Class name added.
+ * p x.detailed_message(highlight: true) # Class name, bolding, and underlining added.
+ * end
*
- * If you override this method, it must be tolerant for unknown keyword
- * arguments. All keyword arguments passed to #full_message are delegated
- * to this method.
+ * Output:
*
- * This method is overridden by did_you_mean and error_highlight to add
- * their information.
+ * "divided by 0"
+ * "divided by 0 (ZeroDivisionError)"
+ * "\e[1mdivided by 0 (\e[1;4mZeroDivisionError\e[m\e[1m)\e[m"
*
- * A user-defined exception class can also define their own
- * +detailed_message+ method to add supplemental information.
- * When +highlight+ is true, it can return a string containing escape
- * sequences, but use widely-supported ones. It is recommended to limit
- * the following codes:
+ * This method is overridden by some gems in the Ruby standard library to add information:
*
- * - Reset (+\e[0m+)
- * - Bold (+\e[1m+)
- * - Underline (+\e[4m+)
- * - Foreground color except white and black
- * - Red (+\e[31m+)
- * - Green (+\e[32m+)
- * - Yellow (+\e[33m+)
- * - Blue (+\e[34m+)
- * - Magenta (+\e[35m+)
- * - Cyan (+\e[36m+)
+ * - DidYouMean::Correctable#detailed_message.
+ * - ErrorHighlight::CoreExt#detailed_message.
+ * - SyntaxSuggest#detailed_message.
*
- * Use escape sequences carefully even if +highlight+ is true.
- * Do not use escape sequences to express essential information;
- * the message should be readable even if all escape sequences are
- * ignored.
+ * An overriding method must be tolerant of passed keyword arguments,
+ * which may include (but may not be limited to):
+ *
+ * - +:highlight+.
+ * - +:did_you_mean+.
+ * - +:error_highlight+.
+ * - +:syntax_suggest+.
+ *
+ * An overriding method should also be careful with ANSI code enhancements;
+ * see {Messages}[rdoc-ref:exceptions.md@Messages].
*/
static VALUE
@@ -1728,9 +1809,15 @@ exc_detailed_message(int argc, VALUE *argv, VALUE exc)
/*
* call-seq:
- * exception.inspect -> string
+ * inspect -> string
+ *
+ * Returns a string representation of +self+:
+ *
+ * x = RuntimeError.new('Boom')
+ * x.inspect # => "#<RuntimeError: Boom>"
+ * x = RuntimeError.new
+ * x.inspect # => "#<RuntimeError: RuntimeError>"
*
- * Return this exception's class name and message.
*/
static VALUE
@@ -1763,38 +1850,36 @@ exc_inspect(VALUE exc)
/*
* call-seq:
- * exception.backtrace -> array or nil
+ * backtrace -> array or nil
*
- * Returns any backtrace associated with the exception. The backtrace
- * is an array of strings, each containing either ``filename:lineNo: in
- * `method''' or ``filename:lineNo.''
+ * Returns the backtrace (the list of code locations that led to the exception),
+ * as an array of strings.
*
- * def a
- * raise "boom"
- * end
+ * Example (assuming the code is stored in the file named <tt>t.rb</tt>):
*
- * def b
- * a()
- * end
- *
- * begin
- * b()
- * rescue => detail
- * print detail.backtrace.join("\n")
- * end
+ * def division(numerator, denominator)
+ * numerator / denominator
+ * end
*
- * <em>produces:</em>
+ * begin
+ * division(1, 0)
+ * rescue => ex
+ * p ex.backtrace
+ * # ["t.rb:2:in 'Integer#/'", "t.rb:2:in 'Object#division'", "t.rb:6:in '<main>'"]
+ * loc = ex.backtrace.first
+ * p loc.class
+ * # String
+ * end
*
- * prog.rb:2:in `a'
- * prog.rb:6:in `b'
- * prog.rb:10
+ * The value returned by this method might be adjusted when raising (see Kernel#raise),
+ * or during intermediate handling by #set_backtrace.
*
- * In the case no backtrace has been set, +nil+ is returned
+ * See also #backtrace_locations that provide the same value, as structured objects.
+ * (Note though that two values might not be consistent with each other when
+ * backtraces are manually adjusted.)
*
- * ex = StandardError.new
- * ex.backtrace
- * #=> nil
-*/
+ * see {Backtraces}[rdoc-ref:exceptions.md@Backtraces].
+ */
static VALUE
exc_backtrace(VALUE exc)
@@ -1836,13 +1921,41 @@ rb_get_backtrace(VALUE exc)
/*
* call-seq:
- * exception.backtrace_locations -> array or nil
+ * backtrace_locations -> array or nil
+ *
+ * Returns the backtrace (the list of code locations that led to the exception),
+ * as an array of Thread::Backtrace::Location instances.
+ *
+ * Example (assuming the code is stored in the file named <tt>t.rb</tt>):
*
- * Returns any backtrace associated with the exception. This method is
- * similar to Exception#backtrace, but the backtrace is an array of
- * Thread::Backtrace::Location.
+ * def division(numerator, denominator)
+ * numerator / denominator
+ * end
+ *
+ * begin
+ * division(1, 0)
+ * rescue => ex
+ * p ex.backtrace_locations
+ * # ["t.rb:2:in 'Integer#/'", "t.rb:2:in 'Object#division'", "t.rb:6:in '<main>'"]
+ * loc = ex.backtrace_locations.first
+ * p loc.class
+ * # Thread::Backtrace::Location
+ * p loc.path
+ * # "t.rb"
+ * p loc.lineno
+ * # 2
+ * p loc.label
+ * # "Integer#/"
+ * end
*
- * This method is not affected by Exception#set_backtrace().
+ * The value returned by this method might be adjusted when raising (see Kernel#raise),
+ * or during intermediate handling by #set_backtrace.
+ *
+ * See also #backtrace that provide the same value as an array of strings.
+ * (Note though that two values might not be consistent with each other when
+ * backtraces are manually adjusted.)
+ *
+ * See {Backtraces}[rdoc-ref:exceptions.md@Backtraces].
*/
static VALUE
exc_backtrace_locations(VALUE exc)
@@ -1880,12 +1993,104 @@ rb_check_backtrace(VALUE bt)
/*
* call-seq:
- * exc.set_backtrace(backtrace) -> array
+ * set_backtrace(value) -> value
+ *
+ * Sets the backtrace value for +self+; returns the given +value+.
+ *
+ * The +value+ might be:
+ *
+ * - an array of Thread::Backtrace::Location;
+ * - an array of String instances;
+ * - a single String instance; or
+ * - +nil+.
+ *
+ * Using array of Thread::Backtrace::Location is the most consistent
+ * option: it sets both #backtrace and #backtrace_locations. It should be
+ * preferred when possible. The suitable array of locations can be obtained
+ * from Kernel#caller_locations, copied from another error, or just set to
+ * the adjusted result of the current error's #backtrace_locations:
+ *
+ * require 'json'
+ *
+ * def parse_payload(text)
+ * JSON.parse(text) # test.rb, line 4
+ * rescue JSON::ParserError => ex
+ * ex.set_backtrace(ex.backtrace_locations[2...])
+ * raise
+ * end
+ *
+ * parse_payload('{"wrong: "json"')
+ * # test.rb:4:in 'Object#parse_payload': unexpected token at '{"wrong: "json"' (JSON::ParserError)
+ * #
+ * # An error points to the body of parse_payload method,
+ * # hiding the parts of the backtrace related to the internals
+ * # of the "json" library
+ *
+ * # The error has both #backtace and #backtrace_locations set
+ * # consistently:
+ * begin
+ * parse_payload('{"wrong: "json"')
+ * rescue => ex
+ * p ex.backtrace
+ * # ["test.rb:4:in 'Object#parse_payload'", "test.rb:20:in '<main>'"]
+ * p ex.backtrace_locations
+ * # ["test.rb:4:in 'Object#parse_payload'", "test.rb:20:in '<main>'"]
+ * end
*
- * Sets the backtrace information associated with +exc+. The +backtrace+ must
- * be an array of Thread::Backtrace::Location objects or an array of String objects
- * or a single String in the format described in Exception#backtrace.
+ * When the desired stack of locations is not available and should
+ * be constructed from scratch, an array of strings or a singular
+ * string can be used. In this case, only #backtrace is affected:
+ *
+ * def parse_payload(text)
+ * JSON.parse(text)
+ * rescue JSON::ParserError => ex
+ * ex.set_backtrace(["dsl.rb:34", "framework.rb:1"])
+ * # The error have the new value in #backtrace:
+ * p ex.backtrace
+ * # ["dsl.rb:34", "framework.rb:1"]
+ *
+ * # but the original one in #backtrace_locations
+ * p ex.backtrace_locations
+ * # [".../json/common.rb:221:in 'JSON::Ext::Parser.parse'", ...]
+ * end
+ *
+ * parse_payload('{"wrong: "json"')
+ *
+ * Calling #set_backtrace with +nil+ clears up #backtrace but doesn't affect
+ * #backtrace_locations:
+ *
+ * def parse_payload(text)
+ * JSON.parse(text)
+ * rescue JSON::ParserError => ex
+ * ex.set_backtrace(nil)
+ * p ex.backtrace
+ * # nil
+ * p ex.backtrace_locations
+ * # [".../json/common.rb:221:in 'JSON::Ext::Parser.parse'", ...]
+ * end
+ *
+ * parse_payload('{"wrong: "json"')
*
+ * On reraising of such an exception, both #backtrace and #backtrace_locations
+ * is set to the place of reraising:
+ *
+ * def parse_payload(text)
+ * JSON.parse(text)
+ * rescue JSON::ParserError => ex
+ * ex.set_backtrace(nil)
+ * raise # test.rb, line 7
+ * end
+ *
+ * begin
+ * parse_payload('{"wrong: "json"')
+ * rescue => ex
+ * p ex.backtrace
+ * # ["test.rb:7:in 'Object#parse_payload'", "test.rb:11:in '<main>'"]
+ * p ex.backtrace_locations
+ * # ["test.rb:7:in 'Object#parse_payload'", "test.rb:11:in '<main>'"]
+ * end
+ *
+ * See {Backtraces}[rdoc-ref:exceptions.md@Backtraces].
*/
static VALUE
@@ -1909,12 +2114,35 @@ rb_exc_set_backtrace(VALUE exc, VALUE bt)
}
/*
- * call-seq:
- * exception.cause -> an_exception or nil
+ * call-seq:
+ * cause -> exception or nil
+ *
+ * Returns the previous value of global variable <tt>$!</tt>,
+ * which may be +nil+
+ * (see {Global Variables}[rdoc-ref:exceptions.md@Global+Variables]):
+ *
+ * begin
+ * raise('Boom 0')
+ * rescue => x0
+ * puts "Exception: #{x0}; $!: #{$!}; cause: #{x0.cause.inspect}."
+ * begin
+ * raise('Boom 1')
+ * rescue => x1
+ * puts "Exception: #{x1}; $!: #{$!}; cause: #{x1.cause}."
+ * begin
+ * raise('Boom 2')
+ * rescue => x2
+ * puts "Exception: #{x2}; $!: #{$!}; cause: #{x2.cause}."
+ * end
+ * end
+ * end
+ *
+ * Output:
+ *
+ * Exception: Boom 0; $!: Boom 0; cause: nil.
+ * Exception: Boom 1; $!: Boom 1; cause: Boom 0.
+ * Exception: Boom 2; $!: Boom 2; cause: Boom 1.
*
- * Returns the previous exception ($!) at the time this exception was raised.
- * This is useful for wrapping exceptions and retaining the original exception
- * information.
*/
static VALUE
@@ -1931,11 +2159,11 @@ try_convert_to_exception(VALUE obj)
/*
* call-seq:
- * exc == obj -> true or false
+ * self == other -> true or false
+ *
+ * Returns whether +other+ is the same class as +self+
+ * and its #message and #backtrace are equal to those of +self+.
*
- * Equality---If <i>obj</i> is not an Exception, returns
- * <code>false</code>. Otherwise, returns <code>true</code> if <i>exc</i> and
- * <i>obj</i> share same class, messages, and backtrace.
*/
static VALUE
@@ -2277,30 +2505,21 @@ typedef struct name_error_message_struct {
} name_error_message_t;
static void
-name_err_mesg_mark(void *p)
-{
- name_error_message_t *ptr = (name_error_message_t *)p;
- rb_gc_mark_movable(ptr->mesg);
- rb_gc_mark_movable(ptr->recv);
- rb_gc_mark_movable(ptr->name);
-}
-
-static void
-name_err_mesg_update(void *p)
+name_err_mesg_mark_and_move(void *p)
{
name_error_message_t *ptr = (name_error_message_t *)p;
- ptr->mesg = rb_gc_location(ptr->mesg);
- ptr->recv = rb_gc_location(ptr->recv);
- ptr->name = rb_gc_location(ptr->name);
+ rb_gc_mark_and_move(&ptr->mesg);
+ rb_gc_mark_and_move(&ptr->recv);
+ rb_gc_mark_and_move(&ptr->name);
}
static const rb_data_type_t name_err_mesg_data_type = {
"name_err_mesg",
{
- name_err_mesg_mark,
+ name_err_mesg_mark_and_move,
RUBY_TYPED_DEFAULT_FREE,
NULL, // No external memory to report,
- name_err_mesg_update,
+ name_err_mesg_mark_and_move,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
};
@@ -2388,7 +2607,7 @@ name_err_mesg_to_str(VALUE obj)
VALUE mesg = ptr->mesg;
if (NIL_P(mesg)) return Qnil;
else {
- struct RString s_str, c_str, d_str;
+ struct RString s_str = {RBASIC_INIT}, c_str = {RBASIC_INIT}, d_str = {RBASIC_INIT};
VALUE c, s, d = 0, args[4], c2;
int state = 0;
rb_encoding *usascii = rb_usascii_encoding();
@@ -2742,31 +2961,53 @@ syntax_error_with_path(VALUE exc, VALUE path, VALUE *mesg, rb_encoding *enc)
/*
* Document-module: Errno
*
- * Ruby exception objects are subclasses of Exception. However,
- * operating systems typically report errors using plain
- * integers. Module Errno is created dynamically to map these
- * operating system errors to Ruby classes, with each error number
- * generating its own subclass of SystemCallError. As the subclass
- * is created in module Errno, its name will start
- * <code>Errno::</code>.
+ * When an operating system encounters an error,
+ * it typically reports the error as an integer error code:
*
- * The names of the <code>Errno::</code> classes depend on the
- * environment in which Ruby runs. On a typical Unix or Windows
- * platform, there are Errno classes such as Errno::EACCES,
- * Errno::EAGAIN, Errno::EINTR, and so on.
+ * $ ls nosuch.txt
+ * ls: cannot access 'nosuch.txt': No such file or directory
+ * $ echo $? # Code for last error.
+ * 2
*
- * The integer operating system error number corresponding to a
- * particular error is available as the class constant
- * <code>Errno::</code><em>error</em><code>::Errno</code>.
+ * When the Ruby interpreter interacts with the operating system
+ * and receives such an error code (e.g., +2+),
+ * it maps the code to a particular Ruby exception class (e.g., +Errno::ENOENT+):
*
- * Errno::EACCES::Errno #=> 13
- * Errno::EAGAIN::Errno #=> 11
- * Errno::EINTR::Errno #=> 4
+ * File.open('nosuch.txt')
+ * # => No such file or directory @ rb_sysopen - nosuch.txt (Errno::ENOENT)
*
- * The full list of operating system errors on your particular platform
- * are available as the constants of Errno.
+ * Each such class is:
*
- * Errno.constants #=> :E2BIG, :EACCES, :EADDRINUSE, :EADDRNOTAVAIL, ...
+ * - A nested class in this module, +Errno+.
+ * - A subclass of class SystemCallError.
+ * - Associated with an error code.
+ *
+ * Thus:
+ *
+ * Errno::ENOENT.superclass # => SystemCallError
+ * Errno::ENOENT::Errno # => 2
+ *
+ * The names of nested classes are returned by method +Errno.constants+:
+ *
+ * Errno.constants.size # => 158
+ * Errno.constants.sort.take(5) # => [:E2BIG, :EACCES, :EADDRINUSE, :EADDRNOTAVAIL, :EADV]
+ *
+ * As seen above, the error code associated with each class
+ * is available as the value of a constant;
+ * the value for a particular class may vary among operating systems.
+ * If the class is not needed for the particular operating system,
+ * the value is zero:
+ *
+ * Errno::ENOENT::Errno # => 2
+ * Errno::ENOTCAPABLE::Errno # => 0
+ *
+ * Each class in Errno can be created with optional messages:
+ *
+ * Errno::EPIPE.new # => #<Errno::EPIPE: Broken pipe>
+ * Errno::EPIPE.new("foo") # => #<Errno::EPIPE: Broken pipe - foo>
+ * Errno::EPIPE.new("foo", "here") # => #<Errno::EPIPE: Broken pipe @ here - foo>
+ *
+ * See SystemCallError.new.
*/
static st_table *syserr_tbl;
@@ -2837,12 +3078,33 @@ get_syserr(int n)
/*
* call-seq:
- * SystemCallError.new(msg, errno) -> system_call_error_subclass
+ * SystemCallError.new(msg, errno = nil, func = nil) -> system_call_error_subclass
*
* If _errno_ corresponds to a known system error code, constructs the
* appropriate Errno class for that error, otherwise constructs a
* generic SystemCallError object. The error number is subsequently
* available via the #errno method.
+ *
+ * If only numeric object is given, it is treated as an Integer _errno_,
+ * and _msg_ is omitted, otherwise the first argument _msg_ is used as
+ * the additional error message.
+ *
+ * SystemCallError.new(Errno::EPIPE::Errno)
+ * #=> #<Errno::EPIPE: Broken pipe>
+ *
+ * SystemCallError.new("foo")
+ * #=> #<SystemCallError: unknown error - foo>
+ *
+ * SystemCallError.new("foo", Errno::EPIPE::Errno)
+ * #=> #<Errno::EPIPE: Broken pipe - foo>
+ *
+ * If _func_ is not +nil+, it is appended to the message with "<tt> @ </tt>".
+ *
+ * SystemCallError.new("foo", Errno::EPIPE::Errno, "here")
+ * #=> #<Errno::EPIPE: Broken pipe @ here - foo>
+ *
+ * A subclass of SystemCallError can also be instantiated via the
+ * +new+ method of the subclass. See Errno.
*/
static VALUE
@@ -3217,6 +3479,18 @@ syserr_eqq(VALUE self, VALUE exc)
*/
/*
+ * Document-class: NoMatchingPatternError
+ *
+ * Raised when matching pattern not found.
+ */
+
+/*
+ * Document-class: NoMatchingPatternKeyError
+ *
+ * Raised when matching key not found.
+ */
+
+/*
* Document-class: fatal
*
* +fatal+ is an Exception that is raised when Ruby has encountered a fatal
@@ -3231,62 +3505,26 @@ syserr_eqq(VALUE self, VALUE exc)
/*
* Document-class: Exception
*
- * \Class Exception and its subclasses are used to communicate between
- * Kernel#raise and +rescue+ statements in <code>begin ... end</code> blocks.
- *
- * An Exception object carries information about an exception:
- * - Its type (the exception's class).
- * - An optional descriptive message.
- * - Optional backtrace information.
- *
- * Some built-in subclasses of Exception have additional methods: e.g., NameError#name.
- *
- * == Defaults
- *
- * Two Ruby statements have default exception classes:
- * - +raise+: defaults to RuntimeError.
- * - +rescue+: defaults to StandardError.
- *
- * == Global Variables
- *
- * When an exception has been raised but not yet handled (in +rescue+,
- * +ensure+, +at_exit+ and +END+ blocks), two global variables are set:
- * - <code>$!</code> contains the current exception.
- * - <code>$@</code> contains its backtrace.
- *
- * == Custom Exceptions
- *
- * To provide additional or alternate information,
- * a program may create custom exception classes
- * that derive from the built-in exception classes.
- *
- * A good practice is for a library to create a single "generic" exception class
- * (typically a subclass of StandardError or RuntimeError)
- * and have its other exception classes derive from that class.
- * This allows the user to rescue the generic exception, thus catching all exceptions
- * the library may raise even if future versions of the library add new
- * exception subclasses.
- *
- * For example:
- *
- * class MyLibrary
- * class Error < ::StandardError
- * end
- *
- * class WidgetError < Error
- * end
+ * Class +Exception+ and its subclasses are used to indicate that an error
+ * or other problem has occurred,
+ * and may need to be handled.
+ * See {Exceptions}[rdoc-ref:exceptions.md].
*
- * class FrobError < Error
- * end
- *
- * end
+ * An +Exception+ object carries certain information:
*
- * To handle both MyLibrary::WidgetError and MyLibrary::FrobError the library
- * user can rescue MyLibrary::Error.
+ * - The type (the exception's class),
+ * commonly StandardError, RuntimeError, or a subclass of one or the other;
+ * see {Built-In Exception Class Hierarchy}[rdoc-ref:Exception@Built-In+Exception+Class+Hierarchy].
+ * - An optional descriptive message;
+ * see methods ::new, #message.
+ * - Optional backtrace information;
+ * see methods #backtrace, #backtrace_locations, #set_backtrace.
+ * - An optional cause;
+ * see method #cause.
*
- * == Built-In Exception Classes
+ * == Built-In \Exception Class Hierarchy
*
- * The built-in subclasses of Exception are:
+ * The hierarchy of built-in subclasses of class +Exception+:
*
* * NoMemoryError
* * ScriptError
@@ -3316,13 +3554,14 @@ syserr_eqq(VALUE self, VALUE exc)
* * RuntimeError
* * FrozenError
* * SystemCallError
- * * Errno::*
+ * * Errno (and its subclasses, representing system errors)
* * ThreadError
* * TypeError
* * ZeroDivisionError
* * SystemExit
* * SystemStackError
- * * fatal
+ * * {fatal}[rdoc-ref:fatal]
+ *
*/
static VALUE
@@ -3421,11 +3660,11 @@ Init_Exception(void)
* and will render `idPath` as an attribute name without this trick */
ID path = idPath;
- /* the path failed to parse */
+ /* the path that failed to parse */
rb_attr(rb_eSyntaxError, path, TRUE, FALSE, FALSE);
rb_eLoadError = rb_define_class("LoadError", rb_eScriptError);
- /* the path failed to load */
+ /* the path that failed to load */
rb_attr(rb_eLoadError, path, TRUE, FALSE, FALSE);
rb_eNotImpError = rb_define_class("NotImplementedError", rb_eScriptError);
@@ -3498,6 +3737,7 @@ Init_Exception(void)
id_deprecated = rb_intern_const("deprecated");
id_experimental = rb_intern_const("experimental");
id_performance = rb_intern_const("performance");
+ id_strict_unused_block = rb_intern_const("strict_unused_block");
id_top = rb_intern_const("top");
id_bottom = rb_intern_const("bottom");
id_iseq = rb_make_internal_id();
@@ -3510,12 +3750,14 @@ Init_Exception(void)
st_add_direct(warning_categories.id2enum, id_deprecated, RB_WARN_CATEGORY_DEPRECATED);
st_add_direct(warning_categories.id2enum, id_experimental, RB_WARN_CATEGORY_EXPERIMENTAL);
st_add_direct(warning_categories.id2enum, id_performance, RB_WARN_CATEGORY_PERFORMANCE);
+ st_add_direct(warning_categories.id2enum, id_strict_unused_block, RB_WARN_CATEGORY_STRICT_UNUSED_BLOCK);
warning_categories.enum2id = rb_init_identtable();
st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_NONE, 0);
st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_DEPRECATED, id_deprecated);
st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_EXPERIMENTAL, id_experimental);
st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_PERFORMANCE, id_performance);
+ st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_STRICT_UNUSED_BLOCK, id_strict_unused_block);
}
void
@@ -3538,12 +3780,13 @@ rb_vraise(VALUE exc, const char *fmt, va_list ap)
}
void
-rb_raise(VALUE exc, const char *fmt, ...)
+rb_raise(VALUE exc_class, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
- rb_vraise(exc, fmt, args);
+ VALUE exc = rb_exc_new3(exc_class, rb_vsprintf(fmt, args));
va_end(args);
+ rb_exc_raise(exc);
}
NORETURN(static void raise_loaderror(VALUE path, VALUE mesg));
@@ -3887,43 +4130,90 @@ inspect_frozen_obj(VALUE obj, VALUE mesg, int recur)
return mesg;
}
+static VALUE
+get_created_info(VALUE obj, int *pline)
+{
+ VALUE info = rb_attr_get(obj, id_debug_created_info);
+
+ if (NIL_P(info)) return Qnil;
+
+ VALUE path = rb_ary_entry(info, 0);
+ VALUE line = rb_ary_entry(info, 1);
+ if (NIL_P(path)) return Qnil;
+ *pline = NUM2INT(line);
+ return StringValue(path);
+}
+
void
rb_error_frozen_object(VALUE frozen_obj)
{
rb_yjit_lazy_push_frame(GET_EC()->cfp->pc);
- VALUE debug_info;
- const ID created_info = id_debug_created_info;
VALUE mesg = rb_sprintf("can't modify frozen %"PRIsVALUE": ",
- CLASS_OF(frozen_obj));
+ rb_obj_class(frozen_obj));
VALUE exc = rb_exc_new_str(rb_eFrozenError, mesg);
rb_ivar_set(exc, id_recv, frozen_obj);
rb_exec_recursive(inspect_frozen_obj, frozen_obj, mesg);
- if (!NIL_P(debug_info = rb_attr_get(frozen_obj, created_info))) {
- VALUE path = rb_ary_entry(debug_info, 0);
- VALUE line = rb_ary_entry(debug_info, 1);
-
- rb_str_catf(mesg, ", created at %"PRIsVALUE":%"PRIsVALUE, path, line);
+ int created_line;
+ VALUE created_path = get_created_info(frozen_obj, &created_line);
+ if (!NIL_P(created_path)) {
+ rb_str_catf(mesg, ", created at %"PRIsVALUE":%d", created_path, created_line);
}
rb_exc_raise(exc);
}
-#undef rb_check_frozen
void
-rb_check_frozen(VALUE obj)
+rb_warn_unchilled_literal(VALUE obj)
{
- if (RB_UNLIKELY(RB_OBJ_FROZEN(obj))) {
- rb_error_frozen_object(obj);
- }
+ rb_warning_category_t category = RB_WARN_CATEGORY_DEPRECATED;
+ if (!NIL_P(ruby_verbose) && rb_warning_category_enabled_p(category)) {
+ int line;
+ VALUE file = rb_source_location(&line);
+ VALUE mesg = NIL_P(file) ? rb_str_new(0, 0) : rb_str_dup(file);
+
+ if (!NIL_P(file)) {
+ if (line) rb_str_catf(mesg, ":%d", line);
+ rb_str_cat2(mesg, ": ");
+ }
+ rb_str_cat2(mesg, "warning: literal string will be frozen in the future");
- if (RB_UNLIKELY(CHILLED_STRING_P(obj))) {
- rb_str_modify(obj);
+ VALUE str = obj;
+ if (STR_SHARED_P(str)) {
+ str = RSTRING(obj)->as.heap.aux.shared;
+ }
+ VALUE created = get_created_info(str, &line);
+ if (NIL_P(created)) {
+ rb_str_cat2(mesg, " (run with --debug-frozen-string-literal for more information)\n");
+ }
+ else {
+ rb_str_cat2(mesg, "\n");
+ rb_str_append(mesg, created);
+ if (line) rb_str_catf(mesg, ":%d", line);
+ rb_str_cat2(mesg, ": info: the string was created here\n");
+ }
+ rb_warn_category(mesg, rb_warning_category_to_name(category));
}
}
void
+rb_warn_unchilled_symbol_to_s(VALUE obj)
+{
+ rb_category_warn(
+ RB_WARN_CATEGORY_DEPRECATED,
+ "string returned by :%s.to_s will be frozen in the future", RSTRING_PTR(obj)
+ );
+}
+
+#undef rb_check_frozen
+void
+rb_check_frozen(VALUE obj)
+{
+ rb_check_frozen_inline(obj);
+}
+
+void
rb_check_copyable(VALUE obj, VALUE orig)
{
if (!FL_ABLE(obj)) return;
diff --git a/eval.c b/eval.c
index e8da342ac6..deadd5dd64 100644
--- a/eval.c
+++ b/eval.c
@@ -32,7 +32,6 @@
#include "internal/variable.h"
#include "ruby/fiber/scheduler.h"
#include "iseq.h"
-#include "rjit.h"
#include "probes.h"
#include "probes_helper.h"
#include "ruby/vm.h"
@@ -79,7 +78,10 @@ ruby_setup(void)
#endif
Init_BareVM();
rb_vm_encoded_insn_data_table_init();
+ Init_enable_box();
Init_vm_objects();
+ Init_root_box();
+ Init_fstring_table();
EC_PUSH_TAG(GET_EC());
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
@@ -161,7 +163,7 @@ rb_ec_finalize(rb_execution_context_t *ec)
{
ruby_sig_finalize();
ec->errinfo = Qnil;
- rb_objspace_call_finalizer(rb_ec_vm_ptr(ec)->objspace);
+ rb_objspace_call_finalizer();
}
void
@@ -422,43 +424,14 @@ rb_class_modify_check(VALUE klass)
Check_Type(klass, T_CLASS);
}
if (RB_TYPE_P(klass, T_MODULE)) {
- rb_module_set_initialized(klass);
+ // TODO: shouldn't this only happen in a few places?
+ rb_class_set_initialized(klass);
}
if (OBJ_FROZEN(klass)) {
- const char *desc;
-
if (RCLASS_SINGLETON_P(klass)) {
- desc = "object";
klass = RCLASS_ATTACHED_OBJECT(klass);
- if (!SPECIAL_CONST_P(klass)) {
- switch (BUILTIN_TYPE(klass)) {
- case T_MODULE:
- case T_ICLASS:
- desc = "Module";
- break;
- case T_CLASS:
- desc = "Class";
- break;
- default:
- break;
- }
- }
}
- else {
- switch (BUILTIN_TYPE(klass)) {
- case T_MODULE:
- case T_ICLASS:
- desc = "module";
- break;
- case T_CLASS:
- desc = "class";
- break;
- default:
- Check_Type(klass, T_CLASS);
- UNREACHABLE;
- }
- }
- rb_frozen_error_raise(klass, "can't modify frozen %s: %"PRIsVALUE, desc, klass);
+ rb_error_frozen_object(klass);
}
}
@@ -529,10 +502,14 @@ exc_setup_message(const rb_execution_context_t *ec, VALUE mesg, VALUE *cause)
rb_exc_check_circular_cause(*cause);
#else
VALUE c = *cause;
- while (!NIL_P(c = rb_attr_get(c, id_cause))) {
+ while (!NIL_P(c)) {
if (c == mesg) {
rb_raise(rb_eArgError, "circular causes");
}
+ if (THROW_DATA_P(c)) {
+ break;
+ }
+ c = rb_attr_get(c, id_cause);
}
#endif
}
@@ -697,81 +674,257 @@ rb_interrupt(void)
rb_exc_raise(rb_exc_new(rb_eInterrupt, 0, 0));
}
-enum {raise_opt_cause, raise_max_opt}; /*< \private */
-
static int
-extract_raise_opts(int argc, VALUE *argv, VALUE *opts)
+extract_raise_options(int argc, VALUE *argv, VALUE *cause)
{
- int i;
+ // Keyword arguments:
+ static ID keywords[1] = {0};
+ if (!keywords[0]) {
+ CONST_ID(keywords[0], "cause");
+ }
+
if (argc > 0) {
- VALUE opt;
- argc = rb_scan_args(argc, argv, "*:", NULL, &opt);
- if (!NIL_P(opt)) {
- if (!RHASH_EMPTY_P(opt)) {
- ID keywords[1];
- CONST_ID(keywords[0], "cause");
- rb_get_kwargs(opt, keywords, 0, -1-raise_max_opt, opts);
- if (!RHASH_EMPTY_P(opt)) argv[argc++] = opt;
- return argc;
+ VALUE options;
+ argc = rb_scan_args(argc, argv, "*:", NULL, &options);
+
+ if (!NIL_P(options)) {
+ if (!RHASH_EMPTY_P(options)) {
+ // Extract optional cause keyword argument, leaving any other options alone:
+ rb_get_kwargs(options, keywords, 0, -2, cause);
+
+ // If there were any other options, add them back to the arguments:
+ if (!RHASH_EMPTY_P(options)) argv[argc++] = options;
}
}
}
- for (i = 0; i < raise_max_opt; ++i) {
- opts[i] = Qundef;
- }
+
return argc;
}
+/**
+ * Complete exception setup for cross-context raises (Thread#raise, Fiber#raise).
+ * Handles keyword extraction, validation, exception creation, and cause assignment.
+ *
+ * @param[in] argc Number of arguments
+ * @param[in] argv Argument array (will be modified for keyword extraction)
+ * @return Prepared exception object with cause applied
+ */
+VALUE
+rb_exception_setup(int argc, VALUE *argv)
+{
+ rb_execution_context_t *ec = GET_EC();
+
+ // Extract cause keyword argument:
+ VALUE cause = Qundef;
+ argc = extract_raise_options(argc, argv, &cause);
+
+ // Validate cause-only case:
+ if (argc == 0 && !UNDEF_P(cause)) {
+ rb_raise(rb_eArgError, "only cause is given with no arguments");
+ }
+
+ // Create exception:
+ VALUE exception;
+ if (argc == 0) {
+ exception = rb_exc_new(rb_eRuntimeError, 0, 0);
+ }
+ else {
+ exception = rb_make_exception(argc, argv);
+ }
+
+ VALUE resolved_cause = Qnil;
+
+ // Resolve cause with validation:
+ if (UNDEF_P(cause)) {
+ // No explicit cause - use automatic cause chaining from calling context:
+ resolved_cause = rb_ec_get_errinfo(ec);
+
+ // Prevent self-referential cause (e.g. `raise $!`):
+ if (resolved_cause == exception) {
+ resolved_cause = Qnil;
+ }
+ }
+ else if (NIL_P(cause)) {
+ // Explicit nil cause - prevent chaining:
+ resolved_cause = Qnil;
+ }
+ else {
+ // Explicit cause - validate and assign:
+ if (!rb_obj_is_kind_of(cause, rb_eException)) {
+ rb_raise(rb_eTypeError, "exception object expected");
+ }
+
+ if (cause == exception) {
+ // Prevent self-referential cause (e.g. `raise error, cause: error`) - although I'm not sure this is good behaviour, it's inherited from `Kernel#raise`.
+ resolved_cause = Qnil;
+ }
+ else {
+ // Check for circular causes:
+ VALUE current_cause = cause;
+ while (!NIL_P(current_cause)) {
+ // We guarantee that the cause chain is always terminated. Then, creating an exception with an existing cause is not circular as long as exception is not an existing cause of any other exception.
+ if (current_cause == exception) {
+ rb_raise(rb_eArgError, "circular causes");
+ }
+ if (THROW_DATA_P(current_cause)) {
+ break;
+ }
+ current_cause = rb_attr_get(current_cause, id_cause);
+ }
+ resolved_cause = cause;
+ }
+ }
+
+ // Apply cause to exception object (duplicate if frozen):
+ if (!UNDEF_P(resolved_cause)) {
+ if (OBJ_FROZEN(exception)) {
+ exception = rb_obj_dup(exception);
+ }
+ rb_ivar_set(exception, id_cause, resolved_cause);
+ }
+
+ return exception;
+}
+
VALUE
rb_f_raise(int argc, VALUE *argv)
{
- VALUE err;
- VALUE opts[raise_max_opt], *const cause = &opts[raise_opt_cause];
+ VALUE cause = Qundef;
+ argc = extract_raise_options(argc, argv, &cause);
+
+ VALUE exception;
- argc = extract_raise_opts(argc, argv, opts);
+ // Bare re-raise case:
if (argc == 0) {
- if (!UNDEF_P(*cause)) {
+ // Cause was extracted, but no arguments were provided:
+ if (!UNDEF_P(cause)) {
rb_raise(rb_eArgError, "only cause is given with no arguments");
}
- err = get_errinfo();
- if (!NIL_P(err)) {
+
+ // Otherwise, re-raise the current exception:
+ exception = get_errinfo();
+ if (!NIL_P(exception)) {
argc = 1;
- argv = &err;
+ argv = &exception;
}
}
- rb_raise_jump(rb_make_exception(argc, argv), *cause);
+
+ rb_raise_jump(rb_make_exception(argc, argv), cause);
UNREACHABLE_RETURN(Qnil);
}
/*
* call-seq:
- * raise
- * raise(string, cause: $!)
- * raise(exception [, string [, array]], cause: $!)
- * fail
- * fail(string, cause: $!)
- * fail(exception [, string [, array]], cause: $!)
- *
- * With no arguments, raises the exception in <code>$!</code> or raises
- * a RuntimeError if <code>$!</code> is +nil+. With a single +String+
- * argument, raises a +RuntimeError+ with the string as a message. Otherwise,
- * the first parameter should be an +Exception+ class (or another
- * object that returns an +Exception+ object when sent an +exception+
- * message). The optional second parameter sets the message associated with
- * the exception (accessible via Exception#message), and the third parameter
- * is an array of callback information (accessible via
- * Exception#backtrace_locations or Exception#backtrace).
- * The +cause+ of the generated exception (accessible via Exception#cause)
- * is automatically set to the "current" exception (<code>$!</code>), if any.
- * An alternative value, either an +Exception+ object or +nil+, can be
- * specified via the +:cause+ argument.
- *
- * Exceptions are caught by the +rescue+ clause of
- * <code>begin...end</code> blocks.
- *
- * raise "Failed to create socket"
- * raise ArgumentError, "No parameters", caller_locations
+ * raise(exception, message = exception.to_s, backtrace = nil, cause: $!)
+ * raise(message = nil, cause: $!)
+ *
+ * Raises an exception;
+ * see {Exceptions}[rdoc-ref:exceptions.md].
+ *
+ * Argument +exception+ sets the class of the new exception;
+ * it should be class Exception or one of its subclasses
+ * (most commonly, RuntimeError or StandardError),
+ * or an instance of one of those classes:
+ *
+ * begin
+ * raise(StandardError)
+ * rescue => x
+ * p x.class
+ * end
+ * # => StandardError
+ *
+ * Argument +message+ sets the stored message in the new exception,
+ * which may be retrieved by method Exception#message;
+ * the message must be
+ * a {string-convertible object}[rdoc-ref:implicit_conversion.rdoc@String-Convertible+Objects]
+ * or +nil+:
+ *
+ * begin
+ * raise(StandardError, 'Boom')
+ * rescue => x
+ * p x.message
+ * end
+ * # => "Boom"
+ *
+ * If argument +message+ is not given,
+ * the message is the exception class name.
+ *
+ * See {Messages}[rdoc-ref:exceptions.md@Messages].
+ *
+ * Argument +backtrace+ might be used to modify the backtrace of the new exception,
+ * as reported by Exception#backtrace and Exception#backtrace_locations;
+ * the backtrace must be an array of Thread::Backtrace::Location, an array of
+ * strings, a single string, or +nil+.
+ *
+ * Using the array of Thread::Backtrace::Location instances is the most consistent option
+ * and should be preferred when possible. The necessary value might be obtained
+ * from #caller_locations, or copied from Exception#backtrace_locations of another
+ * error:
+ *
+ * begin
+ * do_some_work()
+ * rescue ZeroDivisionError => ex
+ * raise(LogicalError, "You have an error in your math", ex.backtrace_locations)
+ * end
+ *
+ * The ways, both Exception#backtrace and Exception#backtrace_locations of the
+ * raised error are set to the same backtrace.
+ *
+ * When the desired stack of locations is not available and should
+ * be constructed from scratch, an array of strings or a singular
+ * string can be used. In this case, only Exception#backtrace is set:
+ *
+ * begin
+ * raise(StandardError, 'Boom', %w[dsl.rb:3 framework.rb:1])
+ * rescue => ex
+ * p ex.backtrace
+ * # => ["dsl.rb:3", "framework.rb:1"]
+ * p ex.backtrace_locations
+ * # => nil
+ * end
+ *
+ * If argument +backtrace+ is not given,
+ * the backtrace is set according to an array of Thread::Backtrace::Location objects,
+ * as derived from the call stack.
+ *
+ * See {Backtraces}[rdoc-ref:exceptions.md@Backtraces].
+ *
+ * Keyword argument +cause+ sets the stored cause in the new exception,
+ * which may be retrieved by method Exception#cause;
+ * the cause must be an exception object (Exception or one of its subclasses),
+ * or +nil+:
+ *
+ * begin
+ * raise(StandardError, cause: RuntimeError.new)
+ * rescue => x
+ * p x.cause
+ * end
+ * # => #<RuntimeError: RuntimeError>
+ *
+ * If keyword argument +cause+ is not given,
+ * the cause is the value of <tt>$!</tt>.
+ *
+ * See {Cause}[rdoc-ref:exceptions.md@Cause].
+ *
+ * In the alternate calling sequence,
+ * where argument +exception+ _not_ given,
+ * raises a new exception of the class given by <tt>$!</tt>,
+ * or of class RuntimeError if <tt>$!</tt> is +nil+:
+ *
+ * begin
+ * raise
+ * rescue => x
+ * p x
+ * end
+ * # => RuntimeError
+ *
+ * With argument +exception+ not given,
+ * argument +message+ and keyword argument +cause+ may be given,
+ * but argument +backtrace+ may not be given.
+ *
+ * +cause+ can not be given as an only argument.
+ *
*/
static VALUE
@@ -983,18 +1136,11 @@ rb_protect(VALUE (* proc) (VALUE), VALUE data, int *pstate)
}
VALUE
-rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2)
+rb_ec_ensure(rb_execution_context_t *ec, VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2)
{
enum ruby_tag_type state;
volatile VALUE result = Qnil;
VALUE errinfo;
- rb_execution_context_t * volatile ec = GET_EC();
- rb_ensure_list_t ensure_list;
- ensure_list.entry.marker = 0;
- ensure_list.entry.e_proc = e_proc;
- ensure_list.entry.data2 = data2;
- ensure_list.next = ec->ensure_list;
- ec->ensure_list = &ensure_list;
EC_PUSH_TAG(ec);
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
result = (*b_proc) (data1);
@@ -1004,14 +1150,19 @@ rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE dat
if (!NIL_P(errinfo) && !RB_TYPE_P(errinfo, T_OBJECT)) {
ec->errinfo = Qnil;
}
- ec->ensure_list=ensure_list.next;
- (*ensure_list.entry.e_proc)(ensure_list.entry.data2);
+ (*e_proc)(data2);
ec->errinfo = errinfo;
if (state)
EC_JUMP_TAG(ec, state);
return result;
}
+VALUE
+rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2)
+{
+ return rb_ec_ensure(GET_EC(), b_proc, data1, e_proc, data2);
+}
+
static ID
frame_func_id(const rb_control_frame_t *cfp)
{
@@ -1119,6 +1270,8 @@ rb_mod_append_features(VALUE module, VALUE include)
return module;
}
+static VALUE refinement_import_methods(int argc, VALUE *argv, VALUE refinement);
+
/*
* call-seq:
* include(module, ...) -> self
@@ -1272,9 +1425,9 @@ rb_using_refinement(rb_cref_t *cref, VALUE klass, VALUE module)
}
superclass = refinement_superclass(superclass);
c = iclass = rb_include_class_new(module, superclass);
- RB_OBJ_WRITE(c, &RCLASS_REFINED_CLASS(c), klass);
+ RCLASS_SET_REFINED_CLASS(c, klass);
- RCLASS_M_TBL(c) = RCLASS_M_TBL(module);
+ RCLASS_WRITE_M_TBL(c, RCLASS_M_TBL(module));
rb_hash_aset(CREF_REFINEMENTS(cref), klass, iclass);
}
@@ -1329,6 +1482,12 @@ rb_using_module(const rb_cref_t *cref, VALUE module)
rb_clear_all_refinement_method_cache();
}
+void
+rb_vm_using_module(VALUE module)
+{
+ rb_using_module(rb_vm_cref_replace_with_duplicated_cref(), module);
+}
+
/*
* call-seq:
* target -> class_or_module
@@ -1351,21 +1510,6 @@ rb_refinement_module_get_refined_class(VALUE module)
return rb_attr_get(module, id_refined_class);
}
-/*
- * call-seq:
- * refined_class -> class
- *
- * Deprecated; prefer #target.
- *
- * Return the class refined by the receiver.
- */
-static VALUE
-rb_refinement_refined_class(VALUE module)
-{
- rb_warn_deprecated_to_remove("3.4", "Refinement#refined_class", "Refinement#target");
- return rb_refinement_module_get_refined_class(module);
-}
-
static void
add_activated_refinement(VALUE activated_refinements,
VALUE klass, VALUE refinement)
@@ -1384,43 +1528,24 @@ add_activated_refinement(VALUE activated_refinements,
}
superclass = refinement_superclass(superclass);
c = iclass = rb_include_class_new(refinement, superclass);
- RB_OBJ_WRITE(c, &RCLASS_REFINED_CLASS(c), klass);
+ RCLASS_SET_REFINED_CLASS(c, klass);
refinement = RCLASS_SUPER(refinement);
while (refinement && refinement != klass) {
- c = RCLASS_SET_SUPER(c, rb_include_class_new(refinement, RCLASS_SUPER(c)));
- RB_OBJ_WRITE(c, &RCLASS_REFINED_CLASS(c), klass);
+ c = rb_class_set_super(c, rb_include_class_new(refinement, RCLASS_SUPER(c)));
+ RCLASS_SET_REFINED_CLASS(c, klass);
refinement = RCLASS_SUPER(refinement);
}
rb_hash_aset(activated_refinements, klass, iclass);
}
-/*
- * call-seq:
- * refine(mod) { block } -> module
- *
- * Refine <i>mod</i> in the receiver.
- *
- * Returns a module, where refined methods are defined.
- */
-
-static VALUE
-rb_mod_refine(VALUE module, VALUE klass)
+void
+rb_refinement_setup(struct rb_refinements_data *data, VALUE module, VALUE klass)
{
VALUE refinement;
ID id_refinements, id_activated_refinements,
id_refined_class, id_defined_at;
VALUE refinements, activated_refinements;
- rb_thread_t *th = GET_THREAD();
- VALUE block_handler = rb_vm_frame_block_handler(th->ec->cfp);
-
- if (block_handler == VM_BLOCK_HANDLER_NONE) {
- rb_raise(rb_eArgError, "no block given");
- }
- if (vm_block_handler_type(block_handler) != block_handler_type_iseq) {
- rb_raise(rb_eArgError, "can't pass a Proc as a block to Module#refine");
- }
- ensure_class_or_module(klass);
CONST_ID(id_refinements, "__refinements__");
refinements = rb_attr_get(module, id_refinements);
if (NIL_P(refinements)) {
@@ -1438,7 +1563,7 @@ rb_mod_refine(VALUE module, VALUE klass)
if (NIL_P(refinement)) {
VALUE superclass = refinement_superclass(klass);
refinement = rb_refinement_new();
- RCLASS_SET_SUPER(refinement, superclass);
+ rb_class_set_super(refinement, superclass);
RUBY_ASSERT(BUILTIN_TYPE(refinement) == T_MODULE);
FL_SET(refinement, RMODULE_IS_REFINEMENT);
CONST_ID(id_refined_class, "__refined_class__");
@@ -1448,8 +1573,41 @@ rb_mod_refine(VALUE module, VALUE klass)
rb_hash_aset(refinements, klass, refinement);
add_activated_refinement(activated_refinements, klass, refinement);
}
- rb_yield_refine_block(refinement, activated_refinements);
- return refinement;
+
+ data->refinement = refinement;
+ data->refinements = activated_refinements;
+}
+
+/*
+ * call-seq:
+ * refine(mod) { block } -> module
+ *
+ * Refine <i>mod</i> in the receiver.
+ *
+ * Returns a module, where refined methods are defined.
+ */
+
+static VALUE
+rb_mod_refine(VALUE module, VALUE klass)
+{
+ /* module is the receiver of #refine, klass is a module to be refined (`mod` in the doc) */
+ rb_thread_t *th = GET_THREAD();
+ VALUE block_handler = rb_vm_frame_block_handler(th->ec->cfp);
+ struct rb_refinements_data data;
+
+ if (block_handler == VM_BLOCK_HANDLER_NONE) {
+ rb_raise(rb_eArgError, "no block given");
+ }
+ if (vm_block_handler_type(block_handler) != block_handler_type_iseq) {
+ rb_raise(rb_eArgError, "can't pass a Proc as a block to Module#refine");
+ }
+
+ ensure_class_or_module(klass);
+
+ rb_refinement_setup(&data, module, klass);
+
+ rb_yield_refine_block(data.refinement, data.refinements);
+ return data.refinement;
}
static void
@@ -1495,7 +1653,7 @@ mod_using(VALUE self, VALUE module)
* call-seq:
* refinements -> array
*
- * Returns an array of modules defined within the receiver.
+ * Returns an array of +Refinement+ defined within the receiver.
*
* module A
* refine Integer do
@@ -2079,7 +2237,6 @@ Init_eval(void)
rb_undef_method(rb_cClass, "refine");
rb_define_private_method(rb_cRefinement, "import_methods", refinement_import_methods, -1);
rb_define_method(rb_cRefinement, "target", rb_refinement_module_get_refined_class, 0);
- rb_define_method(rb_cRefinement, "refined_class", rb_refinement_refined_class, 0);
rb_undef_method(rb_cRefinement, "append_features");
rb_undef_method(rb_cRefinement, "prepend_features");
rb_undef_method(rb_cRefinement, "extend_object");
diff --git a/eval_intern.h b/eval_intern.h
index 9a551120ff..91808f1f29 100644
--- a/eval_intern.h
+++ b/eval_intern.h
@@ -296,10 +296,17 @@ VALUE rb_vm_make_jump_tag_but_local_jump(enum ruby_tag_type state, VALUE val);
rb_cref_t *rb_vm_cref(void);
rb_cref_t *rb_vm_cref_replace_with_duplicated_cref(void);
VALUE rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, VALUE block_handler, VALUE filename);
+VALUE rb_vm_call_cfunc_in_box(VALUE recv, VALUE (*func)(VALUE, VALUE), VALUE arg1, VALUE arg2, VALUE filename, const rb_box_t *box);
+void rb_vm_frame_flag_set_box_require(const rb_execution_context_t *ec);
+const rb_box_t *rb_vm_current_box(const rb_execution_context_t *ec);
+const rb_box_t *rb_vm_caller_box(const rb_execution_context_t *ec);
+const rb_box_t *rb_vm_loading_box(const rb_execution_context_t *ec);
void rb_vm_set_progname(VALUE filename);
VALUE rb_vm_cbase(void);
/* vm_backtrace.c */
+#define RUBY_BACKTRACE_START 0
+#define RUBY_ALL_BACKTRACE_LINES -1
VALUE rb_ec_backtrace_object(const rb_execution_context_t *ec);
VALUE rb_ec_backtrace_str_ary(const rb_execution_context_t *ec, long lev, long n);
VALUE rb_ec_backtrace_location_ary(const rb_execution_context_t *ec, long lev, long n, bool skip_internal);
diff --git a/eval_jump.c b/eval_jump.c
index e8e74f4e70..7593a35e36 100644
--- a/eval_jump.c
+++ b/eval_jump.c
@@ -112,21 +112,21 @@ rb_ec_exec_end_proc(rb_execution_context_t * ec)
{
enum ruby_tag_type state;
volatile VALUE errinfo = ec->errinfo;
-
- EC_PUSH_TAG(ec);
- if ((state = EC_EXEC_TAG()) == TAG_NONE) {
- again:
- exec_end_procs_chain(&ephemeral_end_procs, &ec->errinfo);
- exec_end_procs_chain(&end_procs, &ec->errinfo);
- }
- else {
- EC_TMPPOP_TAG();
- error_handle(ec, ec->errinfo, state);
- if (!NIL_P(ec->errinfo)) errinfo = ec->errinfo;
- EC_REPUSH_TAG();
- goto again;
+ volatile bool finished = false;
+
+ while (!finished) {
+ EC_PUSH_TAG(ec);
+ if ((state = EC_EXEC_TAG()) == TAG_NONE) {
+ exec_end_procs_chain(&ephemeral_end_procs, &ec->errinfo);
+ exec_end_procs_chain(&end_procs, &ec->errinfo);
+ finished = true;
+ }
+ EC_POP_TAG();
+ if (state != TAG_NONE) {
+ error_handle(ec, ec->errinfo, state);
+ if (!NIL_P(ec->errinfo)) errinfo = ec->errinfo;
+ }
}
- EC_POP_TAG();
ec->errinfo = errinfo;
}
diff --git a/ext/-test-/RUBY_ALIGNOF/depend b/ext/-test-/RUBY_ALIGNOF/depend
index 25364e55fb..103d20b33c 100644
--- a/ext/-test-/RUBY_ALIGNOF/depend
+++ b/ext/-test-/RUBY_ALIGNOF/depend
@@ -128,6 +128,7 @@ c.o: $(hdrdir)/ruby/internal/intern/re.h
c.o: $(hdrdir)/ruby/internal/intern/ruby.h
c.o: $(hdrdir)/ruby/internal/intern/select.h
c.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+c.o: $(hdrdir)/ruby/internal/intern/set.h
c.o: $(hdrdir)/ruby/internal/intern/signal.h
c.o: $(hdrdir)/ruby/internal/intern/sprintf.h
c.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/abi/depend b/ext/-test-/abi/depend
new file mode 100644
index 0000000000..716a7b1356
--- /dev/null
+++ b/ext/-test-/abi/depend
@@ -0,0 +1,3 @@
+# AUTOGENERATED DEPENDENCIES START
+abi.o: abi.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/arith_seq/beg_len_step/depend b/ext/-test-/arith_seq/beg_len_step/depend
index 702a0037a8..098c8ff1f0 100644
--- a/ext/-test-/arith_seq/beg_len_step/depend
+++ b/ext/-test-/arith_seq/beg_len_step/depend
@@ -127,6 +127,7 @@ beg_len_step.o: $(hdrdir)/ruby/internal/intern/re.h
beg_len_step.o: $(hdrdir)/ruby/internal/intern/ruby.h
beg_len_step.o: $(hdrdir)/ruby/internal/intern/select.h
beg_len_step.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+beg_len_step.o: $(hdrdir)/ruby/internal/intern/set.h
beg_len_step.o: $(hdrdir)/ruby/internal/intern/signal.h
beg_len_step.o: $(hdrdir)/ruby/internal/intern/sprintf.h
beg_len_step.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/arith_seq/extract/depend b/ext/-test-/arith_seq/extract/depend
index fdbd71dfbc..5c07cea4b4 100644
--- a/ext/-test-/arith_seq/extract/depend
+++ b/ext/-test-/arith_seq/extract/depend
@@ -127,6 +127,7 @@ extract.o: $(hdrdir)/ruby/internal/intern/re.h
extract.o: $(hdrdir)/ruby/internal/intern/ruby.h
extract.o: $(hdrdir)/ruby/internal/intern/select.h
extract.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+extract.o: $(hdrdir)/ruby/internal/intern/set.h
extract.o: $(hdrdir)/ruby/internal/intern/signal.h
extract.o: $(hdrdir)/ruby/internal/intern/sprintf.h
extract.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/array/concat/depend b/ext/-test-/array/concat/depend
index f2213a42ea..8edf45465f 100644
--- a/ext/-test-/array/concat/depend
+++ b/ext/-test-/array/concat/depend
@@ -128,6 +128,7 @@ to_ary_concat.o: $(hdrdir)/ruby/internal/intern/re.h
to_ary_concat.o: $(hdrdir)/ruby/internal/intern/ruby.h
to_ary_concat.o: $(hdrdir)/ruby/internal/intern/select.h
to_ary_concat.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+to_ary_concat.o: $(hdrdir)/ruby/internal/intern/set.h
to_ary_concat.o: $(hdrdir)/ruby/internal/intern/signal.h
to_ary_concat.o: $(hdrdir)/ruby/internal/intern/sprintf.h
to_ary_concat.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/array/resize/depend b/ext/-test-/array/resize/depend
index f88a9d03c1..e6a228b43d 100644
--- a/ext/-test-/array/resize/depend
+++ b/ext/-test-/array/resize/depend
@@ -127,6 +127,7 @@ resize.o: $(hdrdir)/ruby/internal/intern/re.h
resize.o: $(hdrdir)/ruby/internal/intern/ruby.h
resize.o: $(hdrdir)/ruby/internal/intern/select.h
resize.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+resize.o: $(hdrdir)/ruby/internal/intern/set.h
resize.o: $(hdrdir)/ruby/internal/intern/signal.h
resize.o: $(hdrdir)/ruby/internal/intern/sprintf.h
resize.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/asan/asan.c b/ext/-test-/asan/asan.c
deleted file mode 100644
index 45b6253fda..0000000000
--- a/ext/-test-/asan/asan.c
+++ /dev/null
@@ -1,24 +0,0 @@
-#include "ruby/ruby.h"
-
-static VALUE
-asan_enabled_p(VALUE self)
-{
-#if defined(__has_feature)
- /* clang uses __has_feature for determining asan */
- return __has_feature(address_sanitizer) ? Qtrue : Qfalse;
-#elif defined(__SANITIZE_ADDRESS__)
- /* GCC sets __SANITIZE_ADDRESS__ for determining asan */
- return Qtrue;
-#else
- return Qfalse;
-#endif
-}
-
-void
-Init_asan(void)
-{
- VALUE m = rb_define_module("Test");
- VALUE c = rb_define_class_under(m, "ASAN", rb_cObject);
- rb_define_singleton_method(c, "enabled?", asan_enabled_p, 0);
-}
-
diff --git a/ext/-test-/asan/extconf.rb b/ext/-test-/asan/extconf.rb
deleted file mode 100644
index ec02742b81..0000000000
--- a/ext/-test-/asan/extconf.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-require 'mkmf'
-create_makefile('-test-/asan')
diff --git a/ext/-test-/bignum/depend b/ext/-test-/bignum/depend
index 078915ab72..82972f1032 100644
--- a/ext/-test-/bignum/depend
+++ b/ext/-test-/bignum/depend
@@ -6,6 +6,7 @@ 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/gcc_version_since.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
@@ -127,6 +128,7 @@ big2str.o: $(hdrdir)/ruby/internal/intern/re.h
big2str.o: $(hdrdir)/ruby/internal/intern/ruby.h
big2str.o: $(hdrdir)/ruby/internal/intern/select.h
big2str.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+big2str.o: $(hdrdir)/ruby/internal/intern/set.h
big2str.o: $(hdrdir)/ruby/internal/intern/signal.h
big2str.o: $(hdrdir)/ruby/internal/intern/sprintf.h
big2str.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -158,6 +160,7 @@ big2str.o: $(hdrdir)/ruby/ruby.h
big2str.o: $(hdrdir)/ruby/st.h
big2str.o: $(hdrdir)/ruby/subst.h
big2str.o: $(top_srcdir)/internal/bignum.h
+big2str.o: $(top_srcdir)/internal/compilers.h
big2str.o: big2str.c
bigzero.o: $(RUBY_EXTCONF_H)
bigzero.o: $(arch_hdrdir)/ruby/config.h
@@ -166,6 +169,7 @@ 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/gcc_version_since.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
@@ -287,6 +291,7 @@ bigzero.o: $(hdrdir)/ruby/internal/intern/re.h
bigzero.o: $(hdrdir)/ruby/internal/intern/ruby.h
bigzero.o: $(hdrdir)/ruby/internal/intern/select.h
bigzero.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+bigzero.o: $(hdrdir)/ruby/internal/intern/set.h
bigzero.o: $(hdrdir)/ruby/internal/intern/signal.h
bigzero.o: $(hdrdir)/ruby/internal/intern/sprintf.h
bigzero.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -318,6 +323,7 @@ bigzero.o: $(hdrdir)/ruby/ruby.h
bigzero.o: $(hdrdir)/ruby/st.h
bigzero.o: $(hdrdir)/ruby/subst.h
bigzero.o: $(top_srcdir)/internal/bignum.h
+bigzero.o: $(top_srcdir)/internal/compilers.h
bigzero.o: bigzero.c
div.o: $(RUBY_EXTCONF_H)
div.o: $(arch_hdrdir)/ruby/config.h
@@ -326,6 +332,7 @@ 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/gcc_version_since.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
@@ -447,6 +454,7 @@ div.o: $(hdrdir)/ruby/internal/intern/re.h
div.o: $(hdrdir)/ruby/internal/intern/ruby.h
div.o: $(hdrdir)/ruby/internal/intern/select.h
div.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+div.o: $(hdrdir)/ruby/internal/intern/set.h
div.o: $(hdrdir)/ruby/internal/intern/signal.h
div.o: $(hdrdir)/ruby/internal/intern/sprintf.h
div.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -478,6 +486,7 @@ div.o: $(hdrdir)/ruby/ruby.h
div.o: $(hdrdir)/ruby/st.h
div.o: $(hdrdir)/ruby/subst.h
div.o: $(top_srcdir)/internal/bignum.h
+div.o: $(top_srcdir)/internal/compilers.h
div.o: div.c
init.o: $(RUBY_EXTCONF_H)
init.o: $(arch_hdrdir)/ruby/config.h
@@ -608,6 +617,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h
init.o: $(hdrdir)/ruby/internal/intern/ruby.h
init.o: $(hdrdir)/ruby/internal/intern/select.h
init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
init.o: $(hdrdir)/ruby/internal/intern/signal.h
init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
init.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -646,6 +656,7 @@ 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/gcc_version_since.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
@@ -767,6 +778,7 @@ intpack.o: $(hdrdir)/ruby/internal/intern/re.h
intpack.o: $(hdrdir)/ruby/internal/intern/ruby.h
intpack.o: $(hdrdir)/ruby/internal/intern/select.h
intpack.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+intpack.o: $(hdrdir)/ruby/internal/intern/set.h
intpack.o: $(hdrdir)/ruby/internal/intern/signal.h
intpack.o: $(hdrdir)/ruby/internal/intern/sprintf.h
intpack.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -798,6 +810,7 @@ intpack.o: $(hdrdir)/ruby/ruby.h
intpack.o: $(hdrdir)/ruby/st.h
intpack.o: $(hdrdir)/ruby/subst.h
intpack.o: $(top_srcdir)/internal/bignum.h
+intpack.o: $(top_srcdir)/internal/compilers.h
intpack.o: intpack.c
mul.o: $(RUBY_EXTCONF_H)
mul.o: $(arch_hdrdir)/ruby/config.h
@@ -806,6 +819,7 @@ 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/gcc_version_since.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
@@ -927,6 +941,7 @@ mul.o: $(hdrdir)/ruby/internal/intern/re.h
mul.o: $(hdrdir)/ruby/internal/intern/ruby.h
mul.o: $(hdrdir)/ruby/internal/intern/select.h
mul.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+mul.o: $(hdrdir)/ruby/internal/intern/set.h
mul.o: $(hdrdir)/ruby/internal/intern/signal.h
mul.o: $(hdrdir)/ruby/internal/intern/sprintf.h
mul.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -958,6 +973,7 @@ mul.o: $(hdrdir)/ruby/ruby.h
mul.o: $(hdrdir)/ruby/st.h
mul.o: $(hdrdir)/ruby/subst.h
mul.o: $(top_srcdir)/internal/bignum.h
+mul.o: $(top_srcdir)/internal/compilers.h
mul.o: mul.c
str2big.o: $(RUBY_EXTCONF_H)
str2big.o: $(arch_hdrdir)/ruby/config.h
@@ -966,6 +982,7 @@ 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/gcc_version_since.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
@@ -1087,6 +1104,7 @@ str2big.o: $(hdrdir)/ruby/internal/intern/re.h
str2big.o: $(hdrdir)/ruby/internal/intern/ruby.h
str2big.o: $(hdrdir)/ruby/internal/intern/select.h
str2big.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+str2big.o: $(hdrdir)/ruby/internal/intern/set.h
str2big.o: $(hdrdir)/ruby/internal/intern/signal.h
str2big.o: $(hdrdir)/ruby/internal/intern/sprintf.h
str2big.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -1118,5 +1136,6 @@ str2big.o: $(hdrdir)/ruby/ruby.h
str2big.o: $(hdrdir)/ruby/st.h
str2big.o: $(hdrdir)/ruby/subst.h
str2big.o: $(top_srcdir)/internal/bignum.h
+str2big.o: $(top_srcdir)/internal/compilers.h
str2big.o: str2big.c
# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/box/yay1/extconf.rb b/ext/-test-/box/yay1/extconf.rb
new file mode 100644
index 0000000000..54387cedf1
--- /dev/null
+++ b/ext/-test-/box/yay1/extconf.rb
@@ -0,0 +1 @@
+create_makefile('-test-/box/yay1')
diff --git a/ext/-test-/box/yay1/yay1.c b/ext/-test-/box/yay1/yay1.c
new file mode 100644
index 0000000000..564a221c8c
--- /dev/null
+++ b/ext/-test-/box/yay1/yay1.c
@@ -0,0 +1,28 @@
+#include "yay1.h"
+
+VALUE
+yay_value(void)
+{
+ return rb_str_new_cstr("yay");
+}
+
+static VALUE
+yay1_f_version(VALUE klass)
+{
+ return rb_str_new_cstr("1.0.0");
+}
+
+static VALUE
+yay1_yay(VALUE klass)
+{
+ return yay_value();
+}
+
+void
+Init_yay1(void)
+{
+ VALUE mod = rb_define_module("Yay");
+ rb_define_const(mod, "VERSION", rb_str_new_cstr("1.0.0"));
+ rb_define_singleton_method(mod, "version", yay1_f_version, 0);
+ rb_define_singleton_method(mod, "yay", yay1_yay, 0);
+}
diff --git a/ext/-test-/box/yay1/yay1.def b/ext/-test-/box/yay1/yay1.def
new file mode 100644
index 0000000000..510fbe7017
--- /dev/null
+++ b/ext/-test-/box/yay1/yay1.def
@@ -0,0 +1,3 @@
+EXPORTS
+ Init_yay1
+ yay_value
diff --git a/ext/-test-/box/yay1/yay1.h b/ext/-test-/box/yay1/yay1.h
new file mode 100644
index 0000000000..c4dade928a
--- /dev/null
+++ b/ext/-test-/box/yay1/yay1.h
@@ -0,0 +1,4 @@
+#include <ruby.h>
+#include "ruby/internal/dllexport.h"
+
+RUBY_FUNC_EXPORTED VALUE yay_value(void);
diff --git a/ext/-test-/box/yay2/extconf.rb b/ext/-test-/box/yay2/extconf.rb
new file mode 100644
index 0000000000..850ef3edc9
--- /dev/null
+++ b/ext/-test-/box/yay2/extconf.rb
@@ -0,0 +1 @@
+create_makefile('-test-/box/yay2')
diff --git a/ext/-test-/box/yay2/yay2.c b/ext/-test-/box/yay2/yay2.c
new file mode 100644
index 0000000000..b632ae8495
--- /dev/null
+++ b/ext/-test-/box/yay2/yay2.c
@@ -0,0 +1,28 @@
+#include "yay2.h"
+
+VALUE
+yay_value(void)
+{
+ return rb_str_new_cstr("yaaay");
+}
+
+static VALUE
+yay2_f_version(VALUE klass)
+{
+ return rb_str_new_cstr("2.0.0");
+}
+
+static VALUE
+yay2_yay(VALUE klass)
+{
+ return yay_value();
+}
+
+void
+Init_yay2(void)
+{
+ VALUE mod = rb_define_module("Yay");
+ rb_define_const(mod, "VERSION", rb_str_new_cstr("2.0.0"));
+ rb_define_singleton_method(mod, "version", yay2_f_version, 0);
+ rb_define_singleton_method(mod, "yay", yay2_yay, 0);
+}
diff --git a/ext/-test-/box/yay2/yay2.def b/ext/-test-/box/yay2/yay2.def
new file mode 100644
index 0000000000..163fc44c04
--- /dev/null
+++ b/ext/-test-/box/yay2/yay2.def
@@ -0,0 +1,3 @@
+EXPORTS
+ Init_yay2
+ yay_value
diff --git a/ext/-test-/box/yay2/yay2.h b/ext/-test-/box/yay2/yay2.h
new file mode 100644
index 0000000000..c4dade928a
--- /dev/null
+++ b/ext/-test-/box/yay2/yay2.h
@@ -0,0 +1,4 @@
+#include <ruby.h>
+#include "ruby/internal/dllexport.h"
+
+RUBY_FUNC_EXPORTED VALUE yay_value(void);
diff --git a/ext/-test-/bug-14834/bug-14384.c b/ext/-test-/bug-14834/bug-14384.c
deleted file mode 100644
index 3a16a2d222..0000000000
--- a/ext/-test-/bug-14834/bug-14384.c
+++ /dev/null
@@ -1,39 +0,0 @@
-#include <ruby/ruby.h>
-#include <ruby/debug.h>
-
-#ifndef MAYBE_UNUSED
-# define MAYBE_UNUSED(x) x
-#endif
-
-static NOINLINE(VALUE f(VALUE));
-static NOINLINE(void g(VALUE, void*));
-extern NOINLINE(void Init_bug_14384(void));
-
-void
-Init_bug_14834(void)
-{
- VALUE q = rb_define_module("Bug");
- rb_define_module_function(q, "bug_14834", f, 0);
-}
-
-VALUE
-f(VALUE q)
-{
- int w[] = { 0, 1024 };
- VALUE e = rb_tracepoint_new(Qnil, RUBY_INTERNAL_EVENT_NEWOBJ, g, w);
-
- rb_tracepoint_enable(e);
- return rb_ensure(rb_yield, q, rb_tracepoint_disable, e);
-}
-
-void
-g(MAYBE_UNUSED(VALUE q), void* w)
-{
- const int *e = (const int *)w;
- const int r = *e++;
- const int t = *e++;
- VALUE *y = ALLOCA_N(VALUE, t);
- int *u = ALLOCA_N(int, t);
-
- rb_profile_frames(r, t, y, u);
-}
diff --git a/ext/-test-/bug-14834/bug-14834.c b/ext/-test-/bug-14834/bug-14834.c
new file mode 100644
index 0000000000..af2070d303
--- /dev/null
+++ b/ext/-test-/bug-14834/bug-14834.c
@@ -0,0 +1,39 @@
+#include <ruby/ruby.h>
+#include <ruby/debug.h>
+
+#ifndef MAYBE_UNUSED
+# define MAYBE_UNUSED(x) x
+#endif
+
+static NOINLINE(VALUE f(VALUE));
+static NOINLINE(void g(VALUE, void*));
+extern NOINLINE(void Init_bug_14834(void));
+
+void
+Init_bug_14834(void)
+{
+ VALUE q = rb_define_module("Bug");
+ rb_define_module_function(q, "bug_14834", f, 0);
+}
+
+VALUE
+f(VALUE q)
+{
+ int w[] = { 0, 1024 };
+ VALUE e = rb_tracepoint_new(Qnil, RUBY_INTERNAL_EVENT_NEWOBJ, g, w);
+
+ rb_tracepoint_enable(e);
+ return rb_ensure(rb_yield, q, rb_tracepoint_disable, e);
+}
+
+void
+g(MAYBE_UNUSED(VALUE q), void* w)
+{
+ const int *e = (const int *)w;
+ const int r = *e++;
+ const int t = *e++;
+ VALUE *y = ALLOCA_N(VALUE, t);
+ int *u = ALLOCA_N(int, t);
+
+ rb_profile_frames(r, t, y, u);
+}
diff --git a/ext/-test-/bug-14834/depend b/ext/-test-/bug-14834/depend
index 695094fa7a..f83939d559 100644
--- a/ext/-test-/bug-14834/depend
+++ b/ext/-test-/bug-14834/depend
@@ -1,162 +1,163 @@
# AUTOGENERATED DEPENDENCIES START
-bug-14384.o: $(RUBY_EXTCONF_H)
-bug-14384.o: $(arch_hdrdir)/ruby/config.h
-bug-14384.o: $(hdrdir)/ruby/assert.h
-bug-14384.o: $(hdrdir)/ruby/backward.h
-bug-14384.o: $(hdrdir)/ruby/backward/2/assume.h
-bug-14384.o: $(hdrdir)/ruby/backward/2/attributes.h
-bug-14384.o: $(hdrdir)/ruby/backward/2/bool.h
-bug-14384.o: $(hdrdir)/ruby/backward/2/inttypes.h
-bug-14384.o: $(hdrdir)/ruby/backward/2/limits.h
-bug-14384.o: $(hdrdir)/ruby/backward/2/long_long.h
-bug-14384.o: $(hdrdir)/ruby/backward/2/stdalign.h
-bug-14384.o: $(hdrdir)/ruby/backward/2/stdarg.h
-bug-14384.o: $(hdrdir)/ruby/debug.h
-bug-14384.o: $(hdrdir)/ruby/defines.h
-bug-14384.o: $(hdrdir)/ruby/intern.h
-bug-14384.o: $(hdrdir)/ruby/internal/abi.h
-bug-14384.o: $(hdrdir)/ruby/internal/anyargs.h
-bug-14384.o: $(hdrdir)/ruby/internal/arithmetic.h
-bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/char.h
-bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/double.h
-bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
-bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
-bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/int.h
-bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
-bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/long.h
-bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
-bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
-bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
-bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
-bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/short.h
-bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
-bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
-bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
-bug-14384.o: $(hdrdir)/ruby/internal/assume.h
-bug-14384.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
-bug-14384.o: $(hdrdir)/ruby/internal/attr/artificial.h
-bug-14384.o: $(hdrdir)/ruby/internal/attr/cold.h
-bug-14384.o: $(hdrdir)/ruby/internal/attr/const.h
-bug-14384.o: $(hdrdir)/ruby/internal/attr/constexpr.h
-bug-14384.o: $(hdrdir)/ruby/internal/attr/deprecated.h
-bug-14384.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
-bug-14384.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
-bug-14384.o: $(hdrdir)/ruby/internal/attr/error.h
-bug-14384.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
-bug-14384.o: $(hdrdir)/ruby/internal/attr/forceinline.h
-bug-14384.o: $(hdrdir)/ruby/internal/attr/format.h
-bug-14384.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
-bug-14384.o: $(hdrdir)/ruby/internal/attr/noalias.h
-bug-14384.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
-bug-14384.o: $(hdrdir)/ruby/internal/attr/noexcept.h
-bug-14384.o: $(hdrdir)/ruby/internal/attr/noinline.h
-bug-14384.o: $(hdrdir)/ruby/internal/attr/nonnull.h
-bug-14384.o: $(hdrdir)/ruby/internal/attr/noreturn.h
-bug-14384.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
-bug-14384.o: $(hdrdir)/ruby/internal/attr/pure.h
-bug-14384.o: $(hdrdir)/ruby/internal/attr/restrict.h
-bug-14384.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
-bug-14384.o: $(hdrdir)/ruby/internal/attr/warning.h
-bug-14384.o: $(hdrdir)/ruby/internal/attr/weakref.h
-bug-14384.o: $(hdrdir)/ruby/internal/cast.h
-bug-14384.o: $(hdrdir)/ruby/internal/compiler_is.h
-bug-14384.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
-bug-14384.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
-bug-14384.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
-bug-14384.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
-bug-14384.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
-bug-14384.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
-bug-14384.o: $(hdrdir)/ruby/internal/compiler_since.h
-bug-14384.o: $(hdrdir)/ruby/internal/config.h
-bug-14384.o: $(hdrdir)/ruby/internal/constant_p.h
-bug-14384.o: $(hdrdir)/ruby/internal/core.h
-bug-14384.o: $(hdrdir)/ruby/internal/core/rarray.h
-bug-14384.o: $(hdrdir)/ruby/internal/core/rbasic.h
-bug-14384.o: $(hdrdir)/ruby/internal/core/rbignum.h
-bug-14384.o: $(hdrdir)/ruby/internal/core/rclass.h
-bug-14384.o: $(hdrdir)/ruby/internal/core/rdata.h
-bug-14384.o: $(hdrdir)/ruby/internal/core/rfile.h
-bug-14384.o: $(hdrdir)/ruby/internal/core/rhash.h
-bug-14384.o: $(hdrdir)/ruby/internal/core/robject.h
-bug-14384.o: $(hdrdir)/ruby/internal/core/rregexp.h
-bug-14384.o: $(hdrdir)/ruby/internal/core/rstring.h
-bug-14384.o: $(hdrdir)/ruby/internal/core/rstruct.h
-bug-14384.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
-bug-14384.o: $(hdrdir)/ruby/internal/ctype.h
-bug-14384.o: $(hdrdir)/ruby/internal/dllexport.h
-bug-14384.o: $(hdrdir)/ruby/internal/dosish.h
-bug-14384.o: $(hdrdir)/ruby/internal/error.h
-bug-14384.o: $(hdrdir)/ruby/internal/eval.h
-bug-14384.o: $(hdrdir)/ruby/internal/event.h
-bug-14384.o: $(hdrdir)/ruby/internal/fl_type.h
-bug-14384.o: $(hdrdir)/ruby/internal/gc.h
-bug-14384.o: $(hdrdir)/ruby/internal/glob.h
-bug-14384.o: $(hdrdir)/ruby/internal/globals.h
-bug-14384.o: $(hdrdir)/ruby/internal/has/attribute.h
-bug-14384.o: $(hdrdir)/ruby/internal/has/builtin.h
-bug-14384.o: $(hdrdir)/ruby/internal/has/c_attribute.h
-bug-14384.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
-bug-14384.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
-bug-14384.o: $(hdrdir)/ruby/internal/has/extension.h
-bug-14384.o: $(hdrdir)/ruby/internal/has/feature.h
-bug-14384.o: $(hdrdir)/ruby/internal/has/warning.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/array.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/bignum.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/class.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/compar.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/complex.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/cont.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/dir.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/enum.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/enumerator.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/error.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/eval.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/file.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/hash.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/io.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/load.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/marshal.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/numeric.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/object.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/parse.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/proc.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/process.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/random.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/range.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/rational.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/re.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/ruby.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/select.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/signal.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/sprintf.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/string.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/struct.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/thread.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/time.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/variable.h
-bug-14384.o: $(hdrdir)/ruby/internal/intern/vm.h
-bug-14384.o: $(hdrdir)/ruby/internal/interpreter.h
-bug-14384.o: $(hdrdir)/ruby/internal/iterator.h
-bug-14384.o: $(hdrdir)/ruby/internal/memory.h
-bug-14384.o: $(hdrdir)/ruby/internal/method.h
-bug-14384.o: $(hdrdir)/ruby/internal/module.h
-bug-14384.o: $(hdrdir)/ruby/internal/newobj.h
-bug-14384.o: $(hdrdir)/ruby/internal/scan_args.h
-bug-14384.o: $(hdrdir)/ruby/internal/special_consts.h
-bug-14384.o: $(hdrdir)/ruby/internal/static_assert.h
-bug-14384.o: $(hdrdir)/ruby/internal/stdalign.h
-bug-14384.o: $(hdrdir)/ruby/internal/stdbool.h
-bug-14384.o: $(hdrdir)/ruby/internal/stdckdint.h
-bug-14384.o: $(hdrdir)/ruby/internal/symbol.h
-bug-14384.o: $(hdrdir)/ruby/internal/value.h
-bug-14384.o: $(hdrdir)/ruby/internal/value_type.h
-bug-14384.o: $(hdrdir)/ruby/internal/variable.h
-bug-14384.o: $(hdrdir)/ruby/internal/warning_push.h
-bug-14384.o: $(hdrdir)/ruby/internal/xmalloc.h
-bug-14384.o: $(hdrdir)/ruby/missing.h
-bug-14384.o: $(hdrdir)/ruby/ruby.h
-bug-14384.o: $(hdrdir)/ruby/st.h
-bug-14384.o: $(hdrdir)/ruby/subst.h
-bug-14384.o: bug-14384.c
+bug-14834.o: $(RUBY_EXTCONF_H)
+bug-14834.o: $(arch_hdrdir)/ruby/config.h
+bug-14834.o: $(hdrdir)/ruby/assert.h
+bug-14834.o: $(hdrdir)/ruby/backward.h
+bug-14834.o: $(hdrdir)/ruby/backward/2/assume.h
+bug-14834.o: $(hdrdir)/ruby/backward/2/attributes.h
+bug-14834.o: $(hdrdir)/ruby/backward/2/bool.h
+bug-14834.o: $(hdrdir)/ruby/backward/2/inttypes.h
+bug-14834.o: $(hdrdir)/ruby/backward/2/limits.h
+bug-14834.o: $(hdrdir)/ruby/backward/2/long_long.h
+bug-14834.o: $(hdrdir)/ruby/backward/2/stdalign.h
+bug-14834.o: $(hdrdir)/ruby/backward/2/stdarg.h
+bug-14834.o: $(hdrdir)/ruby/debug.h
+bug-14834.o: $(hdrdir)/ruby/defines.h
+bug-14834.o: $(hdrdir)/ruby/intern.h
+bug-14834.o: $(hdrdir)/ruby/internal/abi.h
+bug-14834.o: $(hdrdir)/ruby/internal/anyargs.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+bug-14834.o: $(hdrdir)/ruby/internal/assume.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/artificial.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/cold.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/const.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/error.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/format.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/noalias.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/noinline.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/pure.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/restrict.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/warning.h
+bug-14834.o: $(hdrdir)/ruby/internal/attr/weakref.h
+bug-14834.o: $(hdrdir)/ruby/internal/cast.h
+bug-14834.o: $(hdrdir)/ruby/internal/compiler_is.h
+bug-14834.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+bug-14834.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+bug-14834.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+bug-14834.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+bug-14834.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+bug-14834.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+bug-14834.o: $(hdrdir)/ruby/internal/compiler_since.h
+bug-14834.o: $(hdrdir)/ruby/internal/config.h
+bug-14834.o: $(hdrdir)/ruby/internal/constant_p.h
+bug-14834.o: $(hdrdir)/ruby/internal/core.h
+bug-14834.o: $(hdrdir)/ruby/internal/core/rarray.h
+bug-14834.o: $(hdrdir)/ruby/internal/core/rbasic.h
+bug-14834.o: $(hdrdir)/ruby/internal/core/rbignum.h
+bug-14834.o: $(hdrdir)/ruby/internal/core/rclass.h
+bug-14834.o: $(hdrdir)/ruby/internal/core/rdata.h
+bug-14834.o: $(hdrdir)/ruby/internal/core/rfile.h
+bug-14834.o: $(hdrdir)/ruby/internal/core/rhash.h
+bug-14834.o: $(hdrdir)/ruby/internal/core/robject.h
+bug-14834.o: $(hdrdir)/ruby/internal/core/rregexp.h
+bug-14834.o: $(hdrdir)/ruby/internal/core/rstring.h
+bug-14834.o: $(hdrdir)/ruby/internal/core/rstruct.h
+bug-14834.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+bug-14834.o: $(hdrdir)/ruby/internal/ctype.h
+bug-14834.o: $(hdrdir)/ruby/internal/dllexport.h
+bug-14834.o: $(hdrdir)/ruby/internal/dosish.h
+bug-14834.o: $(hdrdir)/ruby/internal/error.h
+bug-14834.o: $(hdrdir)/ruby/internal/eval.h
+bug-14834.o: $(hdrdir)/ruby/internal/event.h
+bug-14834.o: $(hdrdir)/ruby/internal/fl_type.h
+bug-14834.o: $(hdrdir)/ruby/internal/gc.h
+bug-14834.o: $(hdrdir)/ruby/internal/glob.h
+bug-14834.o: $(hdrdir)/ruby/internal/globals.h
+bug-14834.o: $(hdrdir)/ruby/internal/has/attribute.h
+bug-14834.o: $(hdrdir)/ruby/internal/has/builtin.h
+bug-14834.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+bug-14834.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+bug-14834.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+bug-14834.o: $(hdrdir)/ruby/internal/has/extension.h
+bug-14834.o: $(hdrdir)/ruby/internal/has/feature.h
+bug-14834.o: $(hdrdir)/ruby/internal/has/warning.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/array.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/bignum.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/class.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/compar.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/complex.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/cont.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/dir.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/enum.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/error.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/eval.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/file.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/hash.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/io.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/load.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/marshal.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/numeric.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/object.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/parse.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/proc.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/process.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/random.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/range.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/rational.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/re.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/ruby.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/select.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/set.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/signal.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/string.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/struct.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/thread.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/time.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/variable.h
+bug-14834.o: $(hdrdir)/ruby/internal/intern/vm.h
+bug-14834.o: $(hdrdir)/ruby/internal/interpreter.h
+bug-14834.o: $(hdrdir)/ruby/internal/iterator.h
+bug-14834.o: $(hdrdir)/ruby/internal/memory.h
+bug-14834.o: $(hdrdir)/ruby/internal/method.h
+bug-14834.o: $(hdrdir)/ruby/internal/module.h
+bug-14834.o: $(hdrdir)/ruby/internal/newobj.h
+bug-14834.o: $(hdrdir)/ruby/internal/scan_args.h
+bug-14834.o: $(hdrdir)/ruby/internal/special_consts.h
+bug-14834.o: $(hdrdir)/ruby/internal/static_assert.h
+bug-14834.o: $(hdrdir)/ruby/internal/stdalign.h
+bug-14834.o: $(hdrdir)/ruby/internal/stdbool.h
+bug-14834.o: $(hdrdir)/ruby/internal/stdckdint.h
+bug-14834.o: $(hdrdir)/ruby/internal/symbol.h
+bug-14834.o: $(hdrdir)/ruby/internal/value.h
+bug-14834.o: $(hdrdir)/ruby/internal/value_type.h
+bug-14834.o: $(hdrdir)/ruby/internal/variable.h
+bug-14834.o: $(hdrdir)/ruby/internal/warning_push.h
+bug-14834.o: $(hdrdir)/ruby/internal/xmalloc.h
+bug-14834.o: $(hdrdir)/ruby/missing.h
+bug-14834.o: $(hdrdir)/ruby/ruby.h
+bug-14834.o: $(hdrdir)/ruby/st.h
+bug-14834.o: $(hdrdir)/ruby/subst.h
+bug-14834.o: bug-14834.c
# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/bug-3571/depend b/ext/-test-/bug-3571/depend
index 84517a9c15..69c970b6f2 100644
--- a/ext/-test-/bug-3571/depend
+++ b/ext/-test-/bug-3571/depend
@@ -128,6 +128,7 @@ bug.o: $(hdrdir)/ruby/internal/intern/re.h
bug.o: $(hdrdir)/ruby/internal/intern/ruby.h
bug.o: $(hdrdir)/ruby/internal/intern/select.h
bug.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+bug.o: $(hdrdir)/ruby/internal/intern/set.h
bug.o: $(hdrdir)/ruby/internal/intern/signal.h
bug.o: $(hdrdir)/ruby/internal/intern/sprintf.h
bug.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/bug-5832/depend b/ext/-test-/bug-5832/depend
index 84517a9c15..69c970b6f2 100644
--- a/ext/-test-/bug-5832/depend
+++ b/ext/-test-/bug-5832/depend
@@ -128,6 +128,7 @@ bug.o: $(hdrdir)/ruby/internal/intern/re.h
bug.o: $(hdrdir)/ruby/internal/intern/ruby.h
bug.o: $(hdrdir)/ruby/internal/intern/select.h
bug.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+bug.o: $(hdrdir)/ruby/internal/intern/set.h
bug.o: $(hdrdir)/ruby/internal/intern/signal.h
bug.o: $(hdrdir)/ruby/internal/intern/sprintf.h
bug.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/bug_reporter/depend b/ext/-test-/bug_reporter/depend
index 1c73234247..e9993c3295 100644
--- a/ext/-test-/bug_reporter/depend
+++ b/ext/-test-/bug_reporter/depend
@@ -128,6 +128,7 @@ bug_reporter.o: $(hdrdir)/ruby/internal/intern/re.h
bug_reporter.o: $(hdrdir)/ruby/internal/intern/ruby.h
bug_reporter.o: $(hdrdir)/ruby/internal/intern/select.h
bug_reporter.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+bug_reporter.o: $(hdrdir)/ruby/internal/intern/set.h
bug_reporter.o: $(hdrdir)/ruby/internal/intern/signal.h
bug_reporter.o: $(hdrdir)/ruby/internal/intern/sprintf.h
bug_reporter.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/class/depend b/ext/-test-/class/depend
index b0595fdc46..557206cefb 100644
--- a/ext/-test-/class/depend
+++ b/ext/-test-/class/depend
@@ -127,6 +127,7 @@ class2name.o: $(hdrdir)/ruby/internal/intern/re.h
class2name.o: $(hdrdir)/ruby/internal/intern/ruby.h
class2name.o: $(hdrdir)/ruby/internal/intern/select.h
class2name.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+class2name.o: $(hdrdir)/ruby/internal/intern/set.h
class2name.o: $(hdrdir)/ruby/internal/intern/signal.h
class2name.o: $(hdrdir)/ruby/internal/intern/sprintf.h
class2name.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -287,6 +288,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h
init.o: $(hdrdir)/ruby/internal/intern/ruby.h
init.o: $(hdrdir)/ruby/internal/intern/select.h
init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
init.o: $(hdrdir)/ruby/internal/intern/signal.h
init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
init.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/class/init.c b/ext/-test-/class/init.c
index ed715c1942..108ff7525c 100644
--- a/ext/-test-/class/init.c
+++ b/ext/-test-/class/init.c
@@ -7,5 +7,6 @@ Init_class(void)
{
VALUE mBug = rb_define_module("Bug");
VALUE mod = rb_define_module_under(mBug, "Class");
+ rb_define_class_under(mod, "TestClassDefinedInC", rb_cObject);
TEST_INIT_FUNCS(init);
}
diff --git a/ext/-test-/cxxanyargs/cxxanyargs.cpp b/ext/-test-/cxxanyargs/cxxanyargs.cpp
index eded13e2ee..c7df7f9038 100644
--- a/ext/-test-/cxxanyargs/cxxanyargs.cpp
+++ b/ext/-test-/cxxanyargs/cxxanyargs.cpp
@@ -97,31 +97,6 @@ struct test_rb_define_hooked_variable {
};
VALUE test_rb_define_hooked_variable::v = Qundef;
-namespace test_rb_iterate {
- VALUE
- iter(VALUE self)
- {
- return rb_funcall(self, rb_intern("yield"), 0);
- }
-
- VALUE
- block(RB_BLOCK_CALL_FUNC_ARGLIST(arg, param))
- {
- return rb_funcall(arg, rb_intern("=="), 1, param);
- }
-
- 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
- }
-}
-
namespace test_rb_block_call {
VALUE
block(RB_BLOCK_CALL_FUNC_ARGLIST(arg, param))
@@ -936,7 +911,6 @@ Init_cxxanyargs(void)
test(rb_define_virtual_variable);
test(rb_define_hooked_variable);
- test(rb_iterate);
test(rb_block_call);
test(rb_rescue);
test(rb_rescue2);
diff --git a/ext/-test-/debug/depend b/ext/-test-/debug/depend
index 67e32c6aa6..4ae0378ef2 100644
--- a/ext/-test-/debug/depend
+++ b/ext/-test-/debug/depend
@@ -128,6 +128,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h
init.o: $(hdrdir)/ruby/internal/intern/ruby.h
init.o: $(hdrdir)/ruby/internal/intern/select.h
init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
init.o: $(hdrdir)/ruby/internal/intern/signal.h
init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
init.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -288,6 +289,7 @@ inspector.o: $(hdrdir)/ruby/internal/intern/re.h
inspector.o: $(hdrdir)/ruby/internal/intern/ruby.h
inspector.o: $(hdrdir)/ruby/internal/intern/select.h
inspector.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+inspector.o: $(hdrdir)/ruby/internal/intern/set.h
inspector.o: $(hdrdir)/ruby/internal/intern/signal.h
inspector.o: $(hdrdir)/ruby/internal/intern/sprintf.h
inspector.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -448,6 +450,7 @@ profile_frames.o: $(hdrdir)/ruby/internal/intern/re.h
profile_frames.o: $(hdrdir)/ruby/internal/intern/ruby.h
profile_frames.o: $(hdrdir)/ruby/internal/intern/select.h
profile_frames.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+profile_frames.o: $(hdrdir)/ruby/internal/intern/set.h
profile_frames.o: $(hdrdir)/ruby/internal/intern/signal.h
profile_frames.o: $(hdrdir)/ruby/internal/intern/sprintf.h
profile_frames.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/dln/empty/depend b/ext/-test-/dln/empty/depend
index d3e606df57..58f1508598 100644
--- a/ext/-test-/dln/empty/depend
+++ b/ext/-test-/dln/empty/depend
@@ -128,6 +128,7 @@ empty.o: $(hdrdir)/ruby/internal/intern/re.h
empty.o: $(hdrdir)/ruby/internal/intern/ruby.h
empty.o: $(hdrdir)/ruby/internal/intern/select.h
empty.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+empty.o: $(hdrdir)/ruby/internal/intern/set.h
empty.o: $(hdrdir)/ruby/internal/intern/signal.h
empty.o: $(hdrdir)/ruby/internal/intern/sprintf.h
empty.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/econv/append.c b/ext/-test-/econv/append.c
index 724cd136c0..eb473c47a3 100644
--- a/ext/-test-/econv/append.c
+++ b/ext/-test-/econv/append.c
@@ -5,6 +5,8 @@ static VALUE
econv_append(VALUE self, VALUE src, VALUE dst)
{
rb_econv_t *ec = DATA_PTR(self);
+ StringValue(src);
+ StringValue(dst);
return rb_econv_str_append(ec, src, dst, 0);
}
diff --git a/ext/-test-/econv/depend b/ext/-test-/econv/depend
new file mode 100644
index 0000000000..3a5bc9c659
--- /dev/null
+++ b/ext/-test-/econv/depend
@@ -0,0 +1,336 @@
+# AUTOGENERATED DEPENDENCIES START
+append.o: $(RUBY_EXTCONF_H)
+append.o: $(arch_hdrdir)/ruby/config.h
+append.o: $(hdrdir)/ruby.h
+append.o: $(hdrdir)/ruby/assert.h
+append.o: $(hdrdir)/ruby/backward.h
+append.o: $(hdrdir)/ruby/backward/2/assume.h
+append.o: $(hdrdir)/ruby/backward/2/attributes.h
+append.o: $(hdrdir)/ruby/backward/2/bool.h
+append.o: $(hdrdir)/ruby/backward/2/inttypes.h
+append.o: $(hdrdir)/ruby/backward/2/limits.h
+append.o: $(hdrdir)/ruby/backward/2/long_long.h
+append.o: $(hdrdir)/ruby/backward/2/stdalign.h
+append.o: $(hdrdir)/ruby/backward/2/stdarg.h
+append.o: $(hdrdir)/ruby/defines.h
+append.o: $(hdrdir)/ruby/encoding.h
+append.o: $(hdrdir)/ruby/intern.h
+append.o: $(hdrdir)/ruby/internal/abi.h
+append.o: $(hdrdir)/ruby/internal/anyargs.h
+append.o: $(hdrdir)/ruby/internal/arithmetic.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+append.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+append.o: $(hdrdir)/ruby/internal/assume.h
+append.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+append.o: $(hdrdir)/ruby/internal/attr/artificial.h
+append.o: $(hdrdir)/ruby/internal/attr/cold.h
+append.o: $(hdrdir)/ruby/internal/attr/const.h
+append.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+append.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+append.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+append.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+append.o: $(hdrdir)/ruby/internal/attr/error.h
+append.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+append.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+append.o: $(hdrdir)/ruby/internal/attr/format.h
+append.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+append.o: $(hdrdir)/ruby/internal/attr/noalias.h
+append.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+append.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+append.o: $(hdrdir)/ruby/internal/attr/noinline.h
+append.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+append.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+append.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+append.o: $(hdrdir)/ruby/internal/attr/pure.h
+append.o: $(hdrdir)/ruby/internal/attr/restrict.h
+append.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+append.o: $(hdrdir)/ruby/internal/attr/warning.h
+append.o: $(hdrdir)/ruby/internal/attr/weakref.h
+append.o: $(hdrdir)/ruby/internal/cast.h
+append.o: $(hdrdir)/ruby/internal/compiler_is.h
+append.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+append.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+append.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+append.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+append.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+append.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+append.o: $(hdrdir)/ruby/internal/compiler_since.h
+append.o: $(hdrdir)/ruby/internal/config.h
+append.o: $(hdrdir)/ruby/internal/constant_p.h
+append.o: $(hdrdir)/ruby/internal/core.h
+append.o: $(hdrdir)/ruby/internal/core/rarray.h
+append.o: $(hdrdir)/ruby/internal/core/rbasic.h
+append.o: $(hdrdir)/ruby/internal/core/rbignum.h
+append.o: $(hdrdir)/ruby/internal/core/rclass.h
+append.o: $(hdrdir)/ruby/internal/core/rdata.h
+append.o: $(hdrdir)/ruby/internal/core/rfile.h
+append.o: $(hdrdir)/ruby/internal/core/rhash.h
+append.o: $(hdrdir)/ruby/internal/core/robject.h
+append.o: $(hdrdir)/ruby/internal/core/rregexp.h
+append.o: $(hdrdir)/ruby/internal/core/rstring.h
+append.o: $(hdrdir)/ruby/internal/core/rstruct.h
+append.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+append.o: $(hdrdir)/ruby/internal/ctype.h
+append.o: $(hdrdir)/ruby/internal/dllexport.h
+append.o: $(hdrdir)/ruby/internal/dosish.h
+append.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+append.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+append.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+append.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+append.o: $(hdrdir)/ruby/internal/encoding/re.h
+append.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+append.o: $(hdrdir)/ruby/internal/encoding/string.h
+append.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+append.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+append.o: $(hdrdir)/ruby/internal/error.h
+append.o: $(hdrdir)/ruby/internal/eval.h
+append.o: $(hdrdir)/ruby/internal/event.h
+append.o: $(hdrdir)/ruby/internal/fl_type.h
+append.o: $(hdrdir)/ruby/internal/gc.h
+append.o: $(hdrdir)/ruby/internal/glob.h
+append.o: $(hdrdir)/ruby/internal/globals.h
+append.o: $(hdrdir)/ruby/internal/has/attribute.h
+append.o: $(hdrdir)/ruby/internal/has/builtin.h
+append.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+append.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+append.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+append.o: $(hdrdir)/ruby/internal/has/extension.h
+append.o: $(hdrdir)/ruby/internal/has/feature.h
+append.o: $(hdrdir)/ruby/internal/has/warning.h
+append.o: $(hdrdir)/ruby/internal/intern/array.h
+append.o: $(hdrdir)/ruby/internal/intern/bignum.h
+append.o: $(hdrdir)/ruby/internal/intern/class.h
+append.o: $(hdrdir)/ruby/internal/intern/compar.h
+append.o: $(hdrdir)/ruby/internal/intern/complex.h
+append.o: $(hdrdir)/ruby/internal/intern/cont.h
+append.o: $(hdrdir)/ruby/internal/intern/dir.h
+append.o: $(hdrdir)/ruby/internal/intern/enum.h
+append.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+append.o: $(hdrdir)/ruby/internal/intern/error.h
+append.o: $(hdrdir)/ruby/internal/intern/eval.h
+append.o: $(hdrdir)/ruby/internal/intern/file.h
+append.o: $(hdrdir)/ruby/internal/intern/hash.h
+append.o: $(hdrdir)/ruby/internal/intern/io.h
+append.o: $(hdrdir)/ruby/internal/intern/load.h
+append.o: $(hdrdir)/ruby/internal/intern/marshal.h
+append.o: $(hdrdir)/ruby/internal/intern/numeric.h
+append.o: $(hdrdir)/ruby/internal/intern/object.h
+append.o: $(hdrdir)/ruby/internal/intern/parse.h
+append.o: $(hdrdir)/ruby/internal/intern/proc.h
+append.o: $(hdrdir)/ruby/internal/intern/process.h
+append.o: $(hdrdir)/ruby/internal/intern/random.h
+append.o: $(hdrdir)/ruby/internal/intern/range.h
+append.o: $(hdrdir)/ruby/internal/intern/rational.h
+append.o: $(hdrdir)/ruby/internal/intern/re.h
+append.o: $(hdrdir)/ruby/internal/intern/ruby.h
+append.o: $(hdrdir)/ruby/internal/intern/select.h
+append.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+append.o: $(hdrdir)/ruby/internal/intern/set.h
+append.o: $(hdrdir)/ruby/internal/intern/signal.h
+append.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+append.o: $(hdrdir)/ruby/internal/intern/string.h
+append.o: $(hdrdir)/ruby/internal/intern/struct.h
+append.o: $(hdrdir)/ruby/internal/intern/thread.h
+append.o: $(hdrdir)/ruby/internal/intern/time.h
+append.o: $(hdrdir)/ruby/internal/intern/variable.h
+append.o: $(hdrdir)/ruby/internal/intern/vm.h
+append.o: $(hdrdir)/ruby/internal/interpreter.h
+append.o: $(hdrdir)/ruby/internal/iterator.h
+append.o: $(hdrdir)/ruby/internal/memory.h
+append.o: $(hdrdir)/ruby/internal/method.h
+append.o: $(hdrdir)/ruby/internal/module.h
+append.o: $(hdrdir)/ruby/internal/newobj.h
+append.o: $(hdrdir)/ruby/internal/scan_args.h
+append.o: $(hdrdir)/ruby/internal/special_consts.h
+append.o: $(hdrdir)/ruby/internal/static_assert.h
+append.o: $(hdrdir)/ruby/internal/stdalign.h
+append.o: $(hdrdir)/ruby/internal/stdbool.h
+append.o: $(hdrdir)/ruby/internal/stdckdint.h
+append.o: $(hdrdir)/ruby/internal/symbol.h
+append.o: $(hdrdir)/ruby/internal/value.h
+append.o: $(hdrdir)/ruby/internal/value_type.h
+append.o: $(hdrdir)/ruby/internal/variable.h
+append.o: $(hdrdir)/ruby/internal/warning_push.h
+append.o: $(hdrdir)/ruby/internal/xmalloc.h
+append.o: $(hdrdir)/ruby/missing.h
+append.o: $(hdrdir)/ruby/onigmo.h
+append.o: $(hdrdir)/ruby/oniguruma.h
+append.o: $(hdrdir)/ruby/ruby.h
+append.o: $(hdrdir)/ruby/st.h
+append.o: $(hdrdir)/ruby/subst.h
+append.o: append.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/abi.h
+init.o: $(hdrdir)/ruby/internal/anyargs.h
+init.o: $(hdrdir)/ruby/internal/arithmetic.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+init.o: $(hdrdir)/ruby/internal/assume.h
+init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+init.o: $(hdrdir)/ruby/internal/attr/artificial.h
+init.o: $(hdrdir)/ruby/internal/attr/cold.h
+init.o: $(hdrdir)/ruby/internal/attr/const.h
+init.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+init.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+init.o: $(hdrdir)/ruby/internal/attr/error.h
+init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+init.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+init.o: $(hdrdir)/ruby/internal/attr/format.h
+init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+init.o: $(hdrdir)/ruby/internal/attr/noalias.h
+init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+init.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+init.o: $(hdrdir)/ruby/internal/attr/noinline.h
+init.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+init.o: $(hdrdir)/ruby/internal/attr/pure.h
+init.o: $(hdrdir)/ruby/internal/attr/restrict.h
+init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+init.o: $(hdrdir)/ruby/internal/attr/warning.h
+init.o: $(hdrdir)/ruby/internal/attr/weakref.h
+init.o: $(hdrdir)/ruby/internal/cast.h
+init.o: $(hdrdir)/ruby/internal/compiler_is.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+init.o: $(hdrdir)/ruby/internal/compiler_since.h
+init.o: $(hdrdir)/ruby/internal/config.h
+init.o: $(hdrdir)/ruby/internal/constant_p.h
+init.o: $(hdrdir)/ruby/internal/core.h
+init.o: $(hdrdir)/ruby/internal/core/rarray.h
+init.o: $(hdrdir)/ruby/internal/core/rbasic.h
+init.o: $(hdrdir)/ruby/internal/core/rbignum.h
+init.o: $(hdrdir)/ruby/internal/core/rclass.h
+init.o: $(hdrdir)/ruby/internal/core/rdata.h
+init.o: $(hdrdir)/ruby/internal/core/rfile.h
+init.o: $(hdrdir)/ruby/internal/core/rhash.h
+init.o: $(hdrdir)/ruby/internal/core/robject.h
+init.o: $(hdrdir)/ruby/internal/core/rregexp.h
+init.o: $(hdrdir)/ruby/internal/core/rstring.h
+init.o: $(hdrdir)/ruby/internal/core/rstruct.h
+init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+init.o: $(hdrdir)/ruby/internal/ctype.h
+init.o: $(hdrdir)/ruby/internal/dllexport.h
+init.o: $(hdrdir)/ruby/internal/dosish.h
+init.o: $(hdrdir)/ruby/internal/error.h
+init.o: $(hdrdir)/ruby/internal/eval.h
+init.o: $(hdrdir)/ruby/internal/event.h
+init.o: $(hdrdir)/ruby/internal/fl_type.h
+init.o: $(hdrdir)/ruby/internal/gc.h
+init.o: $(hdrdir)/ruby/internal/glob.h
+init.o: $(hdrdir)/ruby/internal/globals.h
+init.o: $(hdrdir)/ruby/internal/has/attribute.h
+init.o: $(hdrdir)/ruby/internal/has/builtin.h
+init.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+init.o: $(hdrdir)/ruby/internal/has/extension.h
+init.o: $(hdrdir)/ruby/internal/has/feature.h
+init.o: $(hdrdir)/ruby/internal/has/warning.h
+init.o: $(hdrdir)/ruby/internal/intern/array.h
+init.o: $(hdrdir)/ruby/internal/intern/bignum.h
+init.o: $(hdrdir)/ruby/internal/intern/class.h
+init.o: $(hdrdir)/ruby/internal/intern/compar.h
+init.o: $(hdrdir)/ruby/internal/intern/complex.h
+init.o: $(hdrdir)/ruby/internal/intern/cont.h
+init.o: $(hdrdir)/ruby/internal/intern/dir.h
+init.o: $(hdrdir)/ruby/internal/intern/enum.h
+init.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+init.o: $(hdrdir)/ruby/internal/intern/error.h
+init.o: $(hdrdir)/ruby/internal/intern/eval.h
+init.o: $(hdrdir)/ruby/internal/intern/file.h
+init.o: $(hdrdir)/ruby/internal/intern/hash.h
+init.o: $(hdrdir)/ruby/internal/intern/io.h
+init.o: $(hdrdir)/ruby/internal/intern/load.h
+init.o: $(hdrdir)/ruby/internal/intern/marshal.h
+init.o: $(hdrdir)/ruby/internal/intern/numeric.h
+init.o: $(hdrdir)/ruby/internal/intern/object.h
+init.o: $(hdrdir)/ruby/internal/intern/parse.h
+init.o: $(hdrdir)/ruby/internal/intern/proc.h
+init.o: $(hdrdir)/ruby/internal/intern/process.h
+init.o: $(hdrdir)/ruby/internal/intern/random.h
+init.o: $(hdrdir)/ruby/internal/intern/range.h
+init.o: $(hdrdir)/ruby/internal/intern/rational.h
+init.o: $(hdrdir)/ruby/internal/intern/re.h
+init.o: $(hdrdir)/ruby/internal/intern/ruby.h
+init.o: $(hdrdir)/ruby/internal/intern/select.h
+init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
+init.o: $(hdrdir)/ruby/internal/intern/signal.h
+init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+init.o: $(hdrdir)/ruby/internal/intern/string.h
+init.o: $(hdrdir)/ruby/internal/intern/struct.h
+init.o: $(hdrdir)/ruby/internal/intern/thread.h
+init.o: $(hdrdir)/ruby/internal/intern/time.h
+init.o: $(hdrdir)/ruby/internal/intern/variable.h
+init.o: $(hdrdir)/ruby/internal/intern/vm.h
+init.o: $(hdrdir)/ruby/internal/interpreter.h
+init.o: $(hdrdir)/ruby/internal/iterator.h
+init.o: $(hdrdir)/ruby/internal/memory.h
+init.o: $(hdrdir)/ruby/internal/method.h
+init.o: $(hdrdir)/ruby/internal/module.h
+init.o: $(hdrdir)/ruby/internal/newobj.h
+init.o: $(hdrdir)/ruby/internal/scan_args.h
+init.o: $(hdrdir)/ruby/internal/special_consts.h
+init.o: $(hdrdir)/ruby/internal/static_assert.h
+init.o: $(hdrdir)/ruby/internal/stdalign.h
+init.o: $(hdrdir)/ruby/internal/stdbool.h
+init.o: $(hdrdir)/ruby/internal/stdckdint.h
+init.o: $(hdrdir)/ruby/internal/symbol.h
+init.o: $(hdrdir)/ruby/internal/value.h
+init.o: $(hdrdir)/ruby/internal/value_type.h
+init.o: $(hdrdir)/ruby/internal/variable.h
+init.o: $(hdrdir)/ruby/internal/warning_push.h
+init.o: $(hdrdir)/ruby/internal/xmalloc.h
+init.o: $(hdrdir)/ruby/missing.h
+init.o: $(hdrdir)/ruby/ruby.h
+init.o: $(hdrdir)/ruby/st.h
+init.o: $(hdrdir)/ruby/subst.h
+init.o: init.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/ensure_and_callcc/depend b/ext/-test-/ensure_and_callcc/depend
new file mode 100644
index 0000000000..54431847a6
--- /dev/null
+++ b/ext/-test-/ensure_and_callcc/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+ensure_and_callcc.o: $(RUBY_EXTCONF_H)
+ensure_and_callcc.o: $(arch_hdrdir)/ruby/config.h
+ensure_and_callcc.o: $(hdrdir)/ruby.h
+ensure_and_callcc.o: $(hdrdir)/ruby/assert.h
+ensure_and_callcc.o: $(hdrdir)/ruby/backward.h
+ensure_and_callcc.o: $(hdrdir)/ruby/backward/2/assume.h
+ensure_and_callcc.o: $(hdrdir)/ruby/backward/2/attributes.h
+ensure_and_callcc.o: $(hdrdir)/ruby/backward/2/bool.h
+ensure_and_callcc.o: $(hdrdir)/ruby/backward/2/inttypes.h
+ensure_and_callcc.o: $(hdrdir)/ruby/backward/2/limits.h
+ensure_and_callcc.o: $(hdrdir)/ruby/backward/2/long_long.h
+ensure_and_callcc.o: $(hdrdir)/ruby/backward/2/stdalign.h
+ensure_and_callcc.o: $(hdrdir)/ruby/backward/2/stdarg.h
+ensure_and_callcc.o: $(hdrdir)/ruby/defines.h
+ensure_and_callcc.o: $(hdrdir)/ruby/intern.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/abi.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/anyargs.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/assume.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/artificial.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/cold.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/const.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/error.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/format.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/noalias.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/noinline.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/pure.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/restrict.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/warning.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/attr/weakref.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/cast.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/compiler_is.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/compiler_since.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/config.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/constant_p.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core/rarray.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core/rbasic.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core/rbignum.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core/rclass.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core/rdata.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core/rfile.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core/rhash.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core/robject.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core/rregexp.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core/rstring.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core/rstruct.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/ctype.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/dllexport.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/dosish.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/error.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/eval.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/event.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/fl_type.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/gc.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/glob.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/globals.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/has/attribute.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/has/builtin.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/has/extension.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/has/feature.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/has/warning.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/array.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/bignum.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/class.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/compar.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/complex.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/cont.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/dir.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/enum.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/error.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/eval.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/file.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/hash.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/io.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/load.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/marshal.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/numeric.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/object.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/parse.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/proc.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/process.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/random.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/range.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/rational.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/re.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/ruby.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/select.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/set.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/signal.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/string.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/struct.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/thread.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/time.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/variable.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/intern/vm.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/interpreter.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/iterator.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/memory.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/method.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/module.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/newobj.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/scan_args.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/special_consts.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/static_assert.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/stdalign.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/stdbool.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/stdckdint.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/symbol.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/value.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/value_type.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/variable.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/warning_push.h
+ensure_and_callcc.o: $(hdrdir)/ruby/internal/xmalloc.h
+ensure_and_callcc.o: $(hdrdir)/ruby/missing.h
+ensure_and_callcc.o: $(hdrdir)/ruby/ruby.h
+ensure_and_callcc.o: $(hdrdir)/ruby/st.h
+ensure_and_callcc.o: $(hdrdir)/ruby/subst.h
+ensure_and_callcc.o: ensure_and_callcc.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/ensure_and_callcc/ensure_and_callcc.c b/ext/-test-/ensure_and_callcc/ensure_and_callcc.c
new file mode 100644
index 0000000000..1a92de69c3
--- /dev/null
+++ b/ext/-test-/ensure_and_callcc/ensure_and_callcc.c
@@ -0,0 +1,58 @@
+#include "ruby.h"
+
+static VALUE rb_mEnsureAndCallcc;
+
+struct require_data {
+ VALUE obj;
+ VALUE fname;
+};
+
+static VALUE
+call_require(VALUE arg)
+{
+ struct require_data *data = (struct require_data *)arg;
+ rb_f_require(data->obj, data->fname);
+ return Qnil;
+}
+
+static VALUE
+call_ensure(VALUE _)
+{
+ VALUE v = rb_iv_get(rb_mEnsureAndCallcc, "@ensure_called");
+ int called = FIX2INT(v) + 1;
+ rb_iv_set(rb_mEnsureAndCallcc, "@ensure_called", INT2FIX(called));
+ return Qnil;
+}
+
+static VALUE
+require_with_ensure(VALUE self, VALUE fname)
+{
+ struct require_data data = {
+ .obj = self,
+ .fname = fname
+ };
+ return rb_ensure(call_require, (VALUE)&data, call_ensure, Qnil);
+}
+
+static VALUE
+ensure_called(VALUE self)
+{
+ return rb_iv_get(rb_mEnsureAndCallcc, "@ensure_called");
+}
+
+static VALUE
+reset(VALUE self)
+{
+ rb_iv_set(rb_mEnsureAndCallcc, "@ensure_called", INT2FIX(0));
+ return Qnil;
+}
+
+void
+Init_ensure_and_callcc(void)
+{
+ rb_mEnsureAndCallcc = rb_define_module("EnsureAndCallcc");
+ rb_iv_set(rb_mEnsureAndCallcc, "@ensure_called", INT2FIX(0));
+ rb_define_singleton_method(rb_mEnsureAndCallcc, "reset", reset, 0);
+ rb_define_singleton_method(rb_mEnsureAndCallcc, "ensure_called", ensure_called, 0);
+ rb_define_singleton_method(rb_mEnsureAndCallcc, "require_with_ensure", require_with_ensure, 1);
+}
diff --git a/ext/-test-/ensure_and_callcc/extconf.rb b/ext/-test-/ensure_and_callcc/extconf.rb
new file mode 100644
index 0000000000..123b80b8d0
--- /dev/null
+++ b/ext/-test-/ensure_and_callcc/extconf.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: false
+require "mkmf"
+
+require_relative "../auto_ext.rb"
+auto_ext(inc: true)
diff --git a/ext/-test-/enumerator_kw/depend b/ext/-test-/enumerator_kw/depend
index 85daa55b53..b6d2f0a998 100644
--- a/ext/-test-/enumerator_kw/depend
+++ b/ext/-test-/enumerator_kw/depend
@@ -128,6 +128,7 @@ enumerator_kw.o: $(hdrdir)/ruby/internal/intern/re.h
enumerator_kw.o: $(hdrdir)/ruby/internal/intern/ruby.h
enumerator_kw.o: $(hdrdir)/ruby/internal/intern/select.h
enumerator_kw.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+enumerator_kw.o: $(hdrdir)/ruby/internal/intern/set.h
enumerator_kw.o: $(hdrdir)/ruby/internal/intern/signal.h
enumerator_kw.o: $(hdrdir)/ruby/internal/intern/sprintf.h
enumerator_kw.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/eval/depend b/ext/-test-/eval/depend
new file mode 100644
index 0000000000..03a1c7d7ef
--- /dev/null
+++ b/ext/-test-/eval/depend
@@ -0,0 +1,162 @@
+# AUTOGENERATED DEPENDENCIES START
+eval.o: $(RUBY_EXTCONF_H)
+eval.o: $(arch_hdrdir)/ruby/config.h
+eval.o: $(hdrdir)/ruby/assert.h
+eval.o: $(hdrdir)/ruby/backward.h
+eval.o: $(hdrdir)/ruby/backward/2/assume.h
+eval.o: $(hdrdir)/ruby/backward/2/attributes.h
+eval.o: $(hdrdir)/ruby/backward/2/bool.h
+eval.o: $(hdrdir)/ruby/backward/2/inttypes.h
+eval.o: $(hdrdir)/ruby/backward/2/limits.h
+eval.o: $(hdrdir)/ruby/backward/2/long_long.h
+eval.o: $(hdrdir)/ruby/backward/2/stdalign.h
+eval.o: $(hdrdir)/ruby/backward/2/stdarg.h
+eval.o: $(hdrdir)/ruby/defines.h
+eval.o: $(hdrdir)/ruby/intern.h
+eval.o: $(hdrdir)/ruby/internal/abi.h
+eval.o: $(hdrdir)/ruby/internal/anyargs.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+eval.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+eval.o: $(hdrdir)/ruby/internal/assume.h
+eval.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+eval.o: $(hdrdir)/ruby/internal/attr/artificial.h
+eval.o: $(hdrdir)/ruby/internal/attr/cold.h
+eval.o: $(hdrdir)/ruby/internal/attr/const.h
+eval.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+eval.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+eval.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+eval.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+eval.o: $(hdrdir)/ruby/internal/attr/error.h
+eval.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+eval.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+eval.o: $(hdrdir)/ruby/internal/attr/format.h
+eval.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+eval.o: $(hdrdir)/ruby/internal/attr/noalias.h
+eval.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+eval.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+eval.o: $(hdrdir)/ruby/internal/attr/noinline.h
+eval.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+eval.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+eval.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+eval.o: $(hdrdir)/ruby/internal/attr/pure.h
+eval.o: $(hdrdir)/ruby/internal/attr/restrict.h
+eval.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+eval.o: $(hdrdir)/ruby/internal/attr/warning.h
+eval.o: $(hdrdir)/ruby/internal/attr/weakref.h
+eval.o: $(hdrdir)/ruby/internal/cast.h
+eval.o: $(hdrdir)/ruby/internal/compiler_is.h
+eval.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+eval.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+eval.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+eval.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+eval.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+eval.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+eval.o: $(hdrdir)/ruby/internal/compiler_since.h
+eval.o: $(hdrdir)/ruby/internal/config.h
+eval.o: $(hdrdir)/ruby/internal/constant_p.h
+eval.o: $(hdrdir)/ruby/internal/core.h
+eval.o: $(hdrdir)/ruby/internal/core/rarray.h
+eval.o: $(hdrdir)/ruby/internal/core/rbasic.h
+eval.o: $(hdrdir)/ruby/internal/core/rbignum.h
+eval.o: $(hdrdir)/ruby/internal/core/rclass.h
+eval.o: $(hdrdir)/ruby/internal/core/rdata.h
+eval.o: $(hdrdir)/ruby/internal/core/rfile.h
+eval.o: $(hdrdir)/ruby/internal/core/rhash.h
+eval.o: $(hdrdir)/ruby/internal/core/robject.h
+eval.o: $(hdrdir)/ruby/internal/core/rregexp.h
+eval.o: $(hdrdir)/ruby/internal/core/rstring.h
+eval.o: $(hdrdir)/ruby/internal/core/rstruct.h
+eval.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+eval.o: $(hdrdir)/ruby/internal/ctype.h
+eval.o: $(hdrdir)/ruby/internal/dllexport.h
+eval.o: $(hdrdir)/ruby/internal/dosish.h
+eval.o: $(hdrdir)/ruby/internal/error.h
+eval.o: $(hdrdir)/ruby/internal/eval.h
+eval.o: $(hdrdir)/ruby/internal/event.h
+eval.o: $(hdrdir)/ruby/internal/fl_type.h
+eval.o: $(hdrdir)/ruby/internal/gc.h
+eval.o: $(hdrdir)/ruby/internal/glob.h
+eval.o: $(hdrdir)/ruby/internal/globals.h
+eval.o: $(hdrdir)/ruby/internal/has/attribute.h
+eval.o: $(hdrdir)/ruby/internal/has/builtin.h
+eval.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+eval.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+eval.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+eval.o: $(hdrdir)/ruby/internal/has/extension.h
+eval.o: $(hdrdir)/ruby/internal/has/feature.h
+eval.o: $(hdrdir)/ruby/internal/has/warning.h
+eval.o: $(hdrdir)/ruby/internal/intern/array.h
+eval.o: $(hdrdir)/ruby/internal/intern/bignum.h
+eval.o: $(hdrdir)/ruby/internal/intern/class.h
+eval.o: $(hdrdir)/ruby/internal/intern/compar.h
+eval.o: $(hdrdir)/ruby/internal/intern/complex.h
+eval.o: $(hdrdir)/ruby/internal/intern/cont.h
+eval.o: $(hdrdir)/ruby/internal/intern/dir.h
+eval.o: $(hdrdir)/ruby/internal/intern/enum.h
+eval.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+eval.o: $(hdrdir)/ruby/internal/intern/error.h
+eval.o: $(hdrdir)/ruby/internal/intern/eval.h
+eval.o: $(hdrdir)/ruby/internal/intern/file.h
+eval.o: $(hdrdir)/ruby/internal/intern/hash.h
+eval.o: $(hdrdir)/ruby/internal/intern/io.h
+eval.o: $(hdrdir)/ruby/internal/intern/load.h
+eval.o: $(hdrdir)/ruby/internal/intern/marshal.h
+eval.o: $(hdrdir)/ruby/internal/intern/numeric.h
+eval.o: $(hdrdir)/ruby/internal/intern/object.h
+eval.o: $(hdrdir)/ruby/internal/intern/parse.h
+eval.o: $(hdrdir)/ruby/internal/intern/proc.h
+eval.o: $(hdrdir)/ruby/internal/intern/process.h
+eval.o: $(hdrdir)/ruby/internal/intern/random.h
+eval.o: $(hdrdir)/ruby/internal/intern/range.h
+eval.o: $(hdrdir)/ruby/internal/intern/rational.h
+eval.o: $(hdrdir)/ruby/internal/intern/re.h
+eval.o: $(hdrdir)/ruby/internal/intern/ruby.h
+eval.o: $(hdrdir)/ruby/internal/intern/select.h
+eval.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+eval.o: $(hdrdir)/ruby/internal/intern/set.h
+eval.o: $(hdrdir)/ruby/internal/intern/signal.h
+eval.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+eval.o: $(hdrdir)/ruby/internal/intern/string.h
+eval.o: $(hdrdir)/ruby/internal/intern/struct.h
+eval.o: $(hdrdir)/ruby/internal/intern/thread.h
+eval.o: $(hdrdir)/ruby/internal/intern/time.h
+eval.o: $(hdrdir)/ruby/internal/intern/variable.h
+eval.o: $(hdrdir)/ruby/internal/intern/vm.h
+eval.o: $(hdrdir)/ruby/internal/interpreter.h
+eval.o: $(hdrdir)/ruby/internal/iterator.h
+eval.o: $(hdrdir)/ruby/internal/memory.h
+eval.o: $(hdrdir)/ruby/internal/method.h
+eval.o: $(hdrdir)/ruby/internal/module.h
+eval.o: $(hdrdir)/ruby/internal/newobj.h
+eval.o: $(hdrdir)/ruby/internal/scan_args.h
+eval.o: $(hdrdir)/ruby/internal/special_consts.h
+eval.o: $(hdrdir)/ruby/internal/static_assert.h
+eval.o: $(hdrdir)/ruby/internal/stdalign.h
+eval.o: $(hdrdir)/ruby/internal/stdbool.h
+eval.o: $(hdrdir)/ruby/internal/stdckdint.h
+eval.o: $(hdrdir)/ruby/internal/symbol.h
+eval.o: $(hdrdir)/ruby/internal/value.h
+eval.o: $(hdrdir)/ruby/internal/value_type.h
+eval.o: $(hdrdir)/ruby/internal/variable.h
+eval.o: $(hdrdir)/ruby/internal/warning_push.h
+eval.o: $(hdrdir)/ruby/internal/xmalloc.h
+eval.o: $(hdrdir)/ruby/missing.h
+eval.o: $(hdrdir)/ruby/ruby.h
+eval.o: $(hdrdir)/ruby/st.h
+eval.o: $(hdrdir)/ruby/subst.h
+eval.o: eval.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/exception/depend b/ext/-test-/exception/depend
index 7a0544b1e1..690e5ad377 100644
--- a/ext/-test-/exception/depend
+++ b/ext/-test-/exception/depend
@@ -127,6 +127,7 @@ dataerror.o: $(hdrdir)/ruby/internal/intern/re.h
dataerror.o: $(hdrdir)/ruby/internal/intern/ruby.h
dataerror.o: $(hdrdir)/ruby/internal/intern/select.h
dataerror.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+dataerror.o: $(hdrdir)/ruby/internal/intern/set.h
dataerror.o: $(hdrdir)/ruby/internal/intern/signal.h
dataerror.o: $(hdrdir)/ruby/internal/intern/sprintf.h
dataerror.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -297,6 +298,7 @@ enc_raise.o: $(hdrdir)/ruby/internal/intern/re.h
enc_raise.o: $(hdrdir)/ruby/internal/intern/ruby.h
enc_raise.o: $(hdrdir)/ruby/internal/intern/select.h
enc_raise.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+enc_raise.o: $(hdrdir)/ruby/internal/intern/set.h
enc_raise.o: $(hdrdir)/ruby/internal/intern/signal.h
enc_raise.o: $(hdrdir)/ruby/internal/intern/sprintf.h
enc_raise.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -459,6 +461,7 @@ ensured.o: $(hdrdir)/ruby/internal/intern/re.h
ensured.o: $(hdrdir)/ruby/internal/intern/ruby.h
ensured.o: $(hdrdir)/ruby/internal/intern/select.h
ensured.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ensured.o: $(hdrdir)/ruby/internal/intern/set.h
ensured.o: $(hdrdir)/ruby/internal/intern/signal.h
ensured.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ensured.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -619,6 +622,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h
init.o: $(hdrdir)/ruby/internal/intern/ruby.h
init.o: $(hdrdir)/ruby/internal/intern/select.h
init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
init.o: $(hdrdir)/ruby/internal/intern/signal.h
init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
init.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/fatal/depend b/ext/-test-/fatal/depend
index 36b0ad4205..306bc9099c 100644
--- a/ext/-test-/fatal/depend
+++ b/ext/-test-/fatal/depend
@@ -129,6 +129,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h
init.o: $(hdrdir)/ruby/internal/intern/ruby.h
init.o: $(hdrdir)/ruby/internal/intern/select.h
init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
init.o: $(hdrdir)/ruby/internal/intern/signal.h
init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
init.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -289,6 +290,7 @@ invalid.o: $(hdrdir)/ruby/internal/intern/re.h
invalid.o: $(hdrdir)/ruby/internal/intern/ruby.h
invalid.o: $(hdrdir)/ruby/internal/intern/select.h
invalid.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+invalid.o: $(hdrdir)/ruby/internal/intern/set.h
invalid.o: $(hdrdir)/ruby/internal/intern/signal.h
invalid.o: $(hdrdir)/ruby/internal/intern/sprintf.h
invalid.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -449,6 +451,7 @@ rb_fatal.o: $(hdrdir)/ruby/internal/intern/re.h
rb_fatal.o: $(hdrdir)/ruby/internal/intern/ruby.h
rb_fatal.o: $(hdrdir)/ruby/internal/intern/select.h
rb_fatal.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+rb_fatal.o: $(hdrdir)/ruby/internal/intern/set.h
rb_fatal.o: $(hdrdir)/ruby/internal/intern/signal.h
rb_fatal.o: $(hdrdir)/ruby/internal/intern/sprintf.h
rb_fatal.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/fatal/invalid.c b/ext/-test-/fatal/invalid.c
index f0726edb52..6fd970b181 100644
--- a/ext/-test-/fatal/invalid.c
+++ b/ext/-test-/fatal/invalid.c
@@ -1,11 +1,5 @@
#include <ruby.h>
-#if SIZEOF_LONG == SIZEOF_VOIDP
-# define NUM2PTR(x) (void *)NUM2ULONG(x)
-#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
-# define NUM2PTR(x) (void *)NUM2ULL(x)
-#endif
-
static VALUE
invalid_call(VALUE obj, VALUE address)
{
diff --git a/ext/-test-/file/depend b/ext/-test-/file/depend
index e985f914b2..fe320f3d44 100644
--- a/ext/-test-/file/depend
+++ b/ext/-test-/file/depend
@@ -137,6 +137,7 @@ fs.o: $(hdrdir)/ruby/internal/intern/re.h
fs.o: $(hdrdir)/ruby/internal/intern/ruby.h
fs.o: $(hdrdir)/ruby/internal/intern/select.h
fs.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+fs.o: $(hdrdir)/ruby/internal/intern/set.h
fs.o: $(hdrdir)/ruby/internal/intern/signal.h
fs.o: $(hdrdir)/ruby/internal/intern/sprintf.h
fs.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -300,6 +301,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h
init.o: $(hdrdir)/ruby/internal/intern/ruby.h
init.o: $(hdrdir)/ruby/internal/intern/select.h
init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
init.o: $(hdrdir)/ruby/internal/intern/signal.h
init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
init.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -469,6 +471,7 @@ newline_conv.o: $(hdrdir)/ruby/internal/intern/re.h
newline_conv.o: $(hdrdir)/ruby/internal/intern/ruby.h
newline_conv.o: $(hdrdir)/ruby/internal/intern/select.h
newline_conv.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+newline_conv.o: $(hdrdir)/ruby/internal/intern/set.h
newline_conv.o: $(hdrdir)/ruby/internal/intern/signal.h
newline_conv.o: $(hdrdir)/ruby/internal/intern/sprintf.h
newline_conv.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -641,6 +644,7 @@ stat.o: $(hdrdir)/ruby/internal/intern/re.h
stat.o: $(hdrdir)/ruby/internal/intern/ruby.h
stat.o: $(hdrdir)/ruby/internal/intern/select.h
stat.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+stat.o: $(hdrdir)/ruby/internal/intern/set.h
stat.o: $(hdrdir)/ruby/internal/intern/signal.h
stat.o: $(hdrdir)/ruby/internal/intern/sprintf.h
stat.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/float/depend b/ext/-test-/float/depend
index 3e34818d5f..334ed33c3b 100644
--- a/ext/-test-/float/depend
+++ b/ext/-test-/float/depend
@@ -131,6 +131,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h
init.o: $(hdrdir)/ruby/internal/intern/ruby.h
init.o: $(hdrdir)/ruby/internal/intern/select.h
init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
init.o: $(hdrdir)/ruby/internal/intern/signal.h
init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
init.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -291,6 +292,7 @@ nextafter.o: $(hdrdir)/ruby/internal/intern/re.h
nextafter.o: $(hdrdir)/ruby/internal/intern/ruby.h
nextafter.o: $(hdrdir)/ruby/internal/intern/select.h
nextafter.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+nextafter.o: $(hdrdir)/ruby/internal/intern/set.h
nextafter.o: $(hdrdir)/ruby/internal/intern/signal.h
nextafter.o: $(hdrdir)/ruby/internal/intern/sprintf.h
nextafter.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/funcall/depend b/ext/-test-/funcall/depend
index a5a30873ac..e54370306f 100644
--- a/ext/-test-/funcall/depend
+++ b/ext/-test-/funcall/depend
@@ -128,6 +128,7 @@ funcall.o: $(hdrdir)/ruby/internal/intern/re.h
funcall.o: $(hdrdir)/ruby/internal/intern/ruby.h
funcall.o: $(hdrdir)/ruby/internal/intern/select.h
funcall.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+funcall.o: $(hdrdir)/ruby/internal/intern/set.h
funcall.o: $(hdrdir)/ruby/internal/intern/signal.h
funcall.o: $(hdrdir)/ruby/internal/intern/sprintf.h
funcall.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/gvl/call_without_gvl/depend b/ext/-test-/gvl/call_without_gvl/depend
index 6463d4527d..236d1e1d3b 100644
--- a/ext/-test-/gvl/call_without_gvl/depend
+++ b/ext/-test-/gvl/call_without_gvl/depend
@@ -127,6 +127,7 @@ call_without_gvl.o: $(hdrdir)/ruby/internal/intern/re.h
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/ruby.h
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/select.h
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+call_without_gvl.o: $(hdrdir)/ruby/internal/intern/set.h
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/signal.h
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/sprintf.h
call_without_gvl.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/hash/depend b/ext/-test-/hash/depend
index 4bc4bfcdd6..416b93f9de 100644
--- a/ext/-test-/hash/depend
+++ b/ext/-test-/hash/depend
@@ -128,6 +128,7 @@ delete.o: $(hdrdir)/ruby/internal/intern/re.h
delete.o: $(hdrdir)/ruby/internal/intern/ruby.h
delete.o: $(hdrdir)/ruby/internal/intern/select.h
delete.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+delete.o: $(hdrdir)/ruby/internal/intern/set.h
delete.o: $(hdrdir)/ruby/internal/intern/signal.h
delete.o: $(hdrdir)/ruby/internal/intern/sprintf.h
delete.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -288,6 +289,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h
init.o: $(hdrdir)/ruby/internal/intern/ruby.h
init.o: $(hdrdir)/ruby/internal/intern/select.h
init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
init.o: $(hdrdir)/ruby/internal/intern/signal.h
init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
init.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/integer/depend b/ext/-test-/integer/depend
index d89965e3d9..0ea007e814 100644
--- a/ext/-test-/integer/depend
+++ b/ext/-test-/integer/depend
@@ -128,6 +128,7 @@ core_ext.o: $(hdrdir)/ruby/internal/intern/re.h
core_ext.o: $(hdrdir)/ruby/internal/intern/ruby.h
core_ext.o: $(hdrdir)/ruby/internal/intern/select.h
core_ext.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+core_ext.o: $(hdrdir)/ruby/internal/intern/set.h
core_ext.o: $(hdrdir)/ruby/internal/intern/signal.h
core_ext.o: $(hdrdir)/ruby/internal/intern/sprintf.h
core_ext.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -296,6 +297,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h
init.o: $(hdrdir)/ruby/internal/intern/ruby.h
init.o: $(hdrdir)/ruby/internal/intern/select.h
init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
init.o: $(hdrdir)/ruby/internal/intern/signal.h
init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
init.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -456,6 +458,7 @@ my_integer.o: $(hdrdir)/ruby/internal/intern/re.h
my_integer.o: $(hdrdir)/ruby/internal/intern/ruby.h
my_integer.o: $(hdrdir)/ruby/internal/intern/select.h
my_integer.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+my_integer.o: $(hdrdir)/ruby/internal/intern/set.h
my_integer.o: $(hdrdir)/ruby/internal/intern/signal.h
my_integer.o: $(hdrdir)/ruby/internal/intern/sprintf.h
my_integer.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/integer/my_integer.c b/ext/-test-/integer/my_integer.c
index d86474bd7d..94f14d2765 100644
--- a/ext/-test-/integer/my_integer.c
+++ b/ext/-test-/integer/my_integer.c
@@ -1,9 +1,13 @@
#include "ruby.h"
+static const rb_data_type_t my_integer_type = {
+ "MyInteger", {0}, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+};
+
static VALUE
my_integer_s_new(VALUE klass)
{
- return Data_Wrap_Struct(klass, 0, 0, 0);
+ return TypedData_Wrap_Struct(klass, &my_integer_type, 0);
}
void
diff --git a/ext/-test-/iseq_load/depend b/ext/-test-/iseq_load/depend
index fd07b3199c..9361ddb938 100644
--- a/ext/-test-/iseq_load/depend
+++ b/ext/-test-/iseq_load/depend
@@ -128,6 +128,7 @@ iseq_load.o: $(hdrdir)/ruby/internal/intern/re.h
iseq_load.o: $(hdrdir)/ruby/internal/intern/ruby.h
iseq_load.o: $(hdrdir)/ruby/internal/intern/select.h
iseq_load.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+iseq_load.o: $(hdrdir)/ruby/internal/intern/set.h
iseq_load.o: $(hdrdir)/ruby/internal/intern/signal.h
iseq_load.o: $(hdrdir)/ruby/internal/intern/sprintf.h
iseq_load.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/iter/depend b/ext/-test-/iter/depend
index cff4b1bb43..161947382c 100644
--- a/ext/-test-/iter/depend
+++ b/ext/-test-/iter/depend
@@ -128,6 +128,7 @@ break.o: $(hdrdir)/ruby/internal/intern/re.h
break.o: $(hdrdir)/ruby/internal/intern/ruby.h
break.o: $(hdrdir)/ruby/internal/intern/select.h
break.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+break.o: $(hdrdir)/ruby/internal/intern/set.h
break.o: $(hdrdir)/ruby/internal/intern/signal.h
break.o: $(hdrdir)/ruby/internal/intern/sprintf.h
break.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -288,6 +289,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h
init.o: $(hdrdir)/ruby/internal/intern/ruby.h
init.o: $(hdrdir)/ruby/internal/intern/select.h
init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
init.o: $(hdrdir)/ruby/internal/intern/signal.h
init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
init.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -448,6 +450,7 @@ yield.o: $(hdrdir)/ruby/internal/intern/re.h
yield.o: $(hdrdir)/ruby/internal/intern/ruby.h
yield.o: $(hdrdir)/ruby/internal/intern/select.h
yield.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+yield.o: $(hdrdir)/ruby/internal/intern/set.h
yield.o: $(hdrdir)/ruby/internal/intern/signal.h
yield.o: $(hdrdir)/ruby/internal/intern/sprintf.h
yield.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/load/dot.dot/depend b/ext/-test-/load/dot.dot/depend
index f9be79e957..339837d183 100644
--- a/ext/-test-/load/dot.dot/depend
+++ b/ext/-test-/load/dot.dot/depend
@@ -128,6 +128,7 @@ dot.dot.o: $(hdrdir)/ruby/internal/intern/re.h
dot.dot.o: $(hdrdir)/ruby/internal/intern/ruby.h
dot.dot.o: $(hdrdir)/ruby/internal/intern/select.h
dot.dot.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+dot.dot.o: $(hdrdir)/ruby/internal/intern/set.h
dot.dot.o: $(hdrdir)/ruby/internal/intern/signal.h
dot.dot.o: $(hdrdir)/ruby/internal/intern/sprintf.h
dot.dot.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/load/protect/depend b/ext/-test-/load/protect/depend
index 324c17237a..c76c6f88ed 100644
--- a/ext/-test-/load/protect/depend
+++ b/ext/-test-/load/protect/depend
@@ -128,6 +128,7 @@ protect.o: $(hdrdir)/ruby/internal/intern/re.h
protect.o: $(hdrdir)/ruby/internal/intern/ruby.h
protect.o: $(hdrdir)/ruby/internal/intern/select.h
protect.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+protect.o: $(hdrdir)/ruby/internal/intern/set.h
protect.o: $(hdrdir)/ruby/internal/intern/signal.h
protect.o: $(hdrdir)/ruby/internal/intern/sprintf.h
protect.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/load/resolve_symbol_resolver/depend b/ext/-test-/load/resolve_symbol_resolver/depend
new file mode 100644
index 0000000000..f422898b69
--- /dev/null
+++ b/ext/-test-/load/resolve_symbol_resolver/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+resolve_symbol_resolver.o: $(RUBY_EXTCONF_H)
+resolve_symbol_resolver.o: $(arch_hdrdir)/ruby/config.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/assert.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/backward.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/backward/2/assume.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/backward/2/attributes.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/backward/2/bool.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/backward/2/inttypes.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/backward/2/limits.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/backward/2/long_long.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/backward/2/stdalign.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/backward/2/stdarg.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/defines.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/intern.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/abi.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/anyargs.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/assume.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/artificial.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/cold.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/const.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/error.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/format.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/noalias.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/noinline.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/pure.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/restrict.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/warning.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/weakref.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/cast.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/compiler_is.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/compiler_since.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/config.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/constant_p.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rarray.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rbasic.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rbignum.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rclass.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rdata.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rfile.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rhash.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/robject.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rregexp.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rstring.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rstruct.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/ctype.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/dllexport.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/dosish.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/error.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/eval.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/event.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/fl_type.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/gc.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/glob.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/globals.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/has/attribute.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/has/builtin.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/has/extension.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/has/feature.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/has/warning.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/array.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/bignum.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/class.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/compar.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/complex.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/cont.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/dir.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/enum.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/error.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/eval.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/file.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/hash.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/io.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/load.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/marshal.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/numeric.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/object.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/parse.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/proc.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/process.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/random.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/range.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/rational.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/re.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/ruby.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/select.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/set.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/signal.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/string.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/struct.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/thread.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/time.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/variable.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/vm.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/interpreter.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/iterator.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/memory.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/method.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/module.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/newobj.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/scan_args.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/special_consts.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/static_assert.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/stdalign.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/stdbool.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/stdckdint.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/symbol.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/value.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/value_type.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/variable.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/warning_push.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/xmalloc.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/missing.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/ruby.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/st.h
+resolve_symbol_resolver.o: $(hdrdir)/ruby/subst.h
+resolve_symbol_resolver.o: resolve_symbol_resolver.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/load/resolve_symbol_resolver/resolve_symbol_resolver.c b/ext/-test-/load/resolve_symbol_resolver/resolve_symbol_resolver.c
index a856319cfb..6cc07cc1f8 100644
--- a/ext/-test-/load/resolve_symbol_resolver/resolve_symbol_resolver.c
+++ b/ext/-test-/load/resolve_symbol_resolver/resolve_symbol_resolver.c
@@ -5,6 +5,7 @@ typedef VALUE(*target_func)(VALUE);
static target_func rst_any_method;
+#define resolve_func(file, name) (target_func)(uintptr_t)rb_ext_resolve_symbol(file, name)
VALUE
rsr_any_method(VALUE klass)
{
@@ -15,7 +16,7 @@ VALUE
rsr_try_resolve_fname(VALUE klass)
{
target_func rst_something_missing =
- (target_func) rb_ext_resolve_symbol("-test-/load/resolve_symbol_missing", "rst_any_method");
+ resolve_func("-test-/load/resolve_symbol_missing", "rst_any_method");
if (rst_something_missing == NULL) {
// This should be done in Init_*, so the error is LoadError
rb_raise(rb_eLoadError, "symbol not found: missing fname");
@@ -27,7 +28,7 @@ VALUE
rsr_try_resolve_sname(VALUE klass)
{
target_func rst_something_missing =
- (target_func)rb_ext_resolve_symbol("-test-/load/resolve_symbol_target", "rst_something_missing");
+ resolve_func("-test-/load/resolve_symbol_target", "rst_something_missing");
if (rst_something_missing == NULL) {
// This should be done in Init_*, so the error is LoadError
rb_raise(rb_eLoadError, "symbol not found: missing sname");
@@ -43,7 +44,7 @@ Init_resolve_symbol_resolver(void)
* If the module and methods are defined before raising LoadError, retrying `require "this.so"` will
* cause re-defining those methods (and will be warned).
*/
- rst_any_method = (target_func)rb_ext_resolve_symbol("-test-/load/resolve_symbol_target", "rst_any_method");
+ rst_any_method = resolve_func("-test-/load/resolve_symbol_target", "rst_any_method");
if (rst_any_method == NULL) {
rb_raise(rb_eLoadError, "resolve_symbol_target is not loaded");
}
diff --git a/ext/-test-/load/resolve_symbol_target/depend b/ext/-test-/load/resolve_symbol_target/depend
new file mode 100644
index 0000000000..aa0b5327be
--- /dev/null
+++ b/ext/-test-/load/resolve_symbol_target/depend
@@ -0,0 +1,164 @@
+# AUTOGENERATED DEPENDENCIES START
+resolve_symbol_target.o: $(RUBY_EXTCONF_H)
+resolve_symbol_target.o: $(arch_hdrdir)/ruby/config.h
+resolve_symbol_target.o: $(hdrdir)/ruby.h
+resolve_symbol_target.o: $(hdrdir)/ruby/assert.h
+resolve_symbol_target.o: $(hdrdir)/ruby/backward.h
+resolve_symbol_target.o: $(hdrdir)/ruby/backward/2/assume.h
+resolve_symbol_target.o: $(hdrdir)/ruby/backward/2/attributes.h
+resolve_symbol_target.o: $(hdrdir)/ruby/backward/2/bool.h
+resolve_symbol_target.o: $(hdrdir)/ruby/backward/2/inttypes.h
+resolve_symbol_target.o: $(hdrdir)/ruby/backward/2/limits.h
+resolve_symbol_target.o: $(hdrdir)/ruby/backward/2/long_long.h
+resolve_symbol_target.o: $(hdrdir)/ruby/backward/2/stdalign.h
+resolve_symbol_target.o: $(hdrdir)/ruby/backward/2/stdarg.h
+resolve_symbol_target.o: $(hdrdir)/ruby/defines.h
+resolve_symbol_target.o: $(hdrdir)/ruby/intern.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/abi.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/anyargs.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/assume.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/artificial.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/cold.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/const.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/error.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/format.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/noalias.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/noinline.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/pure.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/restrict.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/warning.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/weakref.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/cast.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/compiler_is.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/compiler_since.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/config.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/constant_p.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rarray.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rbasic.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rbignum.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rclass.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rdata.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rfile.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rhash.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/robject.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rregexp.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rstring.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rstruct.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/ctype.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/dllexport.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/dosish.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/error.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/eval.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/event.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/fl_type.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/gc.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/glob.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/globals.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/has/attribute.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/has/builtin.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/has/extension.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/has/feature.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/has/warning.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/array.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/bignum.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/class.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/compar.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/complex.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/cont.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/dir.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/enum.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/error.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/eval.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/file.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/hash.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/io.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/load.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/marshal.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/numeric.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/object.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/parse.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/proc.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/process.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/random.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/range.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/rational.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/re.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/ruby.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/select.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/set.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/signal.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/string.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/struct.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/thread.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/time.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/variable.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/vm.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/interpreter.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/iterator.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/memory.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/method.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/module.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/newobj.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/scan_args.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/special_consts.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/static_assert.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/stdalign.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/stdbool.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/stdckdint.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/symbol.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/value.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/value_type.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/variable.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/warning_push.h
+resolve_symbol_target.o: $(hdrdir)/ruby/internal/xmalloc.h
+resolve_symbol_target.o: $(hdrdir)/ruby/missing.h
+resolve_symbol_target.o: $(hdrdir)/ruby/ruby.h
+resolve_symbol_target.o: $(hdrdir)/ruby/st.h
+resolve_symbol_target.o: $(hdrdir)/ruby/subst.h
+resolve_symbol_target.o: resolve_symbol_target.c
+resolve_symbol_target.o: resolve_symbol_target.h
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/load/resolve_symbol_target/resolve_symbol_target.def b/ext/-test-/load/resolve_symbol_target/resolve_symbol_target.def
deleted file mode 100644
index c2ed3610fe..0000000000
--- a/ext/-test-/load/resolve_symbol_target/resolve_symbol_target.def
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBRARY resolve_symbol_target
-EXPORTS
- Init_resolve_symbol_target
- rst_any_method
diff --git a/ext/-test-/load/stringify_symbols/depend b/ext/-test-/load/stringify_symbols/depend
new file mode 100644
index 0000000000..2d4d79a7b7
--- /dev/null
+++ b/ext/-test-/load/stringify_symbols/depend
@@ -0,0 +1,164 @@
+# AUTOGENERATED DEPENDENCIES START
+stringify_symbols.o: $(RUBY_EXTCONF_H)
+stringify_symbols.o: $(arch_hdrdir)/ruby/config.h
+stringify_symbols.o: $(hdrdir)/ruby.h
+stringify_symbols.o: $(hdrdir)/ruby/assert.h
+stringify_symbols.o: $(hdrdir)/ruby/backward.h
+stringify_symbols.o: $(hdrdir)/ruby/backward/2/assume.h
+stringify_symbols.o: $(hdrdir)/ruby/backward/2/attributes.h
+stringify_symbols.o: $(hdrdir)/ruby/backward/2/bool.h
+stringify_symbols.o: $(hdrdir)/ruby/backward/2/inttypes.h
+stringify_symbols.o: $(hdrdir)/ruby/backward/2/limits.h
+stringify_symbols.o: $(hdrdir)/ruby/backward/2/long_long.h
+stringify_symbols.o: $(hdrdir)/ruby/backward/2/stdalign.h
+stringify_symbols.o: $(hdrdir)/ruby/backward/2/stdarg.h
+stringify_symbols.o: $(hdrdir)/ruby/defines.h
+stringify_symbols.o: $(hdrdir)/ruby/intern.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/abi.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/anyargs.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/assume.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/artificial.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/cold.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/const.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/error.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/format.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/noalias.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/noinline.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/pure.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/restrict.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/warning.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/attr/weakref.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/cast.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/compiler_is.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/compiler_since.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/config.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/constant_p.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core/rarray.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core/rbasic.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core/rbignum.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core/rclass.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core/rdata.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core/rfile.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core/rhash.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core/robject.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core/rregexp.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core/rstring.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core/rstruct.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/ctype.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/dllexport.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/dosish.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/error.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/eval.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/event.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/fl_type.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/gc.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/glob.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/globals.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/has/attribute.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/has/builtin.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/has/extension.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/has/feature.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/has/warning.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/array.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/bignum.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/class.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/compar.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/complex.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/cont.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/dir.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/enum.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/error.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/eval.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/file.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/hash.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/io.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/load.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/marshal.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/numeric.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/object.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/parse.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/proc.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/process.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/random.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/range.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/rational.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/re.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/ruby.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/select.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/set.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/signal.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/string.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/struct.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/thread.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/time.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/variable.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/intern/vm.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/interpreter.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/iterator.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/memory.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/method.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/module.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/newobj.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/scan_args.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/special_consts.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/static_assert.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/stdalign.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/stdbool.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/stdckdint.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/symbol.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/value.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/value_type.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/variable.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/warning_push.h
+stringify_symbols.o: $(hdrdir)/ruby/internal/xmalloc.h
+stringify_symbols.o: $(hdrdir)/ruby/missing.h
+stringify_symbols.o: $(hdrdir)/ruby/ruby.h
+stringify_symbols.o: $(hdrdir)/ruby/st.h
+stringify_symbols.o: $(hdrdir)/ruby/subst.h
+stringify_symbols.o: $(hdrdir)/ruby/util.h
+stringify_symbols.o: stringify_symbols.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/load/stringify_target/depend b/ext/-test-/load/stringify_target/depend
new file mode 100644
index 0000000000..c66575d4e4
--- /dev/null
+++ b/ext/-test-/load/stringify_target/depend
@@ -0,0 +1,164 @@
+# AUTOGENERATED DEPENDENCIES START
+stringify_target.o: $(RUBY_EXTCONF_H)
+stringify_target.o: $(arch_hdrdir)/ruby/config.h
+stringify_target.o: $(hdrdir)/ruby.h
+stringify_target.o: $(hdrdir)/ruby/assert.h
+stringify_target.o: $(hdrdir)/ruby/backward.h
+stringify_target.o: $(hdrdir)/ruby/backward/2/assume.h
+stringify_target.o: $(hdrdir)/ruby/backward/2/attributes.h
+stringify_target.o: $(hdrdir)/ruby/backward/2/bool.h
+stringify_target.o: $(hdrdir)/ruby/backward/2/inttypes.h
+stringify_target.o: $(hdrdir)/ruby/backward/2/limits.h
+stringify_target.o: $(hdrdir)/ruby/backward/2/long_long.h
+stringify_target.o: $(hdrdir)/ruby/backward/2/stdalign.h
+stringify_target.o: $(hdrdir)/ruby/backward/2/stdarg.h
+stringify_target.o: $(hdrdir)/ruby/defines.h
+stringify_target.o: $(hdrdir)/ruby/intern.h
+stringify_target.o: $(hdrdir)/ruby/internal/abi.h
+stringify_target.o: $(hdrdir)/ruby/internal/anyargs.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+stringify_target.o: $(hdrdir)/ruby/internal/assume.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/artificial.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/cold.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/const.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/error.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/format.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/noalias.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/noinline.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/pure.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/restrict.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/warning.h
+stringify_target.o: $(hdrdir)/ruby/internal/attr/weakref.h
+stringify_target.o: $(hdrdir)/ruby/internal/cast.h
+stringify_target.o: $(hdrdir)/ruby/internal/compiler_is.h
+stringify_target.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+stringify_target.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+stringify_target.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+stringify_target.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+stringify_target.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+stringify_target.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+stringify_target.o: $(hdrdir)/ruby/internal/compiler_since.h
+stringify_target.o: $(hdrdir)/ruby/internal/config.h
+stringify_target.o: $(hdrdir)/ruby/internal/constant_p.h
+stringify_target.o: $(hdrdir)/ruby/internal/core.h
+stringify_target.o: $(hdrdir)/ruby/internal/core/rarray.h
+stringify_target.o: $(hdrdir)/ruby/internal/core/rbasic.h
+stringify_target.o: $(hdrdir)/ruby/internal/core/rbignum.h
+stringify_target.o: $(hdrdir)/ruby/internal/core/rclass.h
+stringify_target.o: $(hdrdir)/ruby/internal/core/rdata.h
+stringify_target.o: $(hdrdir)/ruby/internal/core/rfile.h
+stringify_target.o: $(hdrdir)/ruby/internal/core/rhash.h
+stringify_target.o: $(hdrdir)/ruby/internal/core/robject.h
+stringify_target.o: $(hdrdir)/ruby/internal/core/rregexp.h
+stringify_target.o: $(hdrdir)/ruby/internal/core/rstring.h
+stringify_target.o: $(hdrdir)/ruby/internal/core/rstruct.h
+stringify_target.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+stringify_target.o: $(hdrdir)/ruby/internal/ctype.h
+stringify_target.o: $(hdrdir)/ruby/internal/dllexport.h
+stringify_target.o: $(hdrdir)/ruby/internal/dosish.h
+stringify_target.o: $(hdrdir)/ruby/internal/error.h
+stringify_target.o: $(hdrdir)/ruby/internal/eval.h
+stringify_target.o: $(hdrdir)/ruby/internal/event.h
+stringify_target.o: $(hdrdir)/ruby/internal/fl_type.h
+stringify_target.o: $(hdrdir)/ruby/internal/gc.h
+stringify_target.o: $(hdrdir)/ruby/internal/glob.h
+stringify_target.o: $(hdrdir)/ruby/internal/globals.h
+stringify_target.o: $(hdrdir)/ruby/internal/has/attribute.h
+stringify_target.o: $(hdrdir)/ruby/internal/has/builtin.h
+stringify_target.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+stringify_target.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+stringify_target.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+stringify_target.o: $(hdrdir)/ruby/internal/has/extension.h
+stringify_target.o: $(hdrdir)/ruby/internal/has/feature.h
+stringify_target.o: $(hdrdir)/ruby/internal/has/warning.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/array.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/bignum.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/class.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/compar.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/complex.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/cont.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/dir.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/enum.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/error.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/eval.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/file.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/hash.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/io.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/load.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/marshal.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/numeric.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/object.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/parse.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/proc.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/process.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/random.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/range.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/rational.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/re.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/ruby.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/select.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/set.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/signal.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/string.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/struct.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/thread.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/time.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/variable.h
+stringify_target.o: $(hdrdir)/ruby/internal/intern/vm.h
+stringify_target.o: $(hdrdir)/ruby/internal/interpreter.h
+stringify_target.o: $(hdrdir)/ruby/internal/iterator.h
+stringify_target.o: $(hdrdir)/ruby/internal/memory.h
+stringify_target.o: $(hdrdir)/ruby/internal/method.h
+stringify_target.o: $(hdrdir)/ruby/internal/module.h
+stringify_target.o: $(hdrdir)/ruby/internal/newobj.h
+stringify_target.o: $(hdrdir)/ruby/internal/scan_args.h
+stringify_target.o: $(hdrdir)/ruby/internal/special_consts.h
+stringify_target.o: $(hdrdir)/ruby/internal/static_assert.h
+stringify_target.o: $(hdrdir)/ruby/internal/stdalign.h
+stringify_target.o: $(hdrdir)/ruby/internal/stdbool.h
+stringify_target.o: $(hdrdir)/ruby/internal/stdckdint.h
+stringify_target.o: $(hdrdir)/ruby/internal/symbol.h
+stringify_target.o: $(hdrdir)/ruby/internal/value.h
+stringify_target.o: $(hdrdir)/ruby/internal/value_type.h
+stringify_target.o: $(hdrdir)/ruby/internal/variable.h
+stringify_target.o: $(hdrdir)/ruby/internal/warning_push.h
+stringify_target.o: $(hdrdir)/ruby/internal/xmalloc.h
+stringify_target.o: $(hdrdir)/ruby/missing.h
+stringify_target.o: $(hdrdir)/ruby/ruby.h
+stringify_target.o: $(hdrdir)/ruby/st.h
+stringify_target.o: $(hdrdir)/ruby/subst.h
+stringify_target.o: stringify_target.c
+stringify_target.o: stringify_target.h
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/load/stringify_target/stringify_target.def b/ext/-test-/load/stringify_target/stringify_target.def
deleted file mode 100644
index 89c2b762de..0000000000
--- a/ext/-test-/load/stringify_target/stringify_target.def
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBRARY stringify_target
-EXPORTS
- Init_stringify_target
- stt_any_method
diff --git a/ext/-test-/marshal/compat/depend b/ext/-test-/marshal/compat/depend
index 8bcd9f8b5e..36b9235c23 100644
--- a/ext/-test-/marshal/compat/depend
+++ b/ext/-test-/marshal/compat/depend
@@ -128,6 +128,7 @@ usrcompat.o: $(hdrdir)/ruby/internal/intern/re.h
usrcompat.o: $(hdrdir)/ruby/internal/intern/ruby.h
usrcompat.o: $(hdrdir)/ruby/internal/intern/select.h
usrcompat.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+usrcompat.o: $(hdrdir)/ruby/internal/intern/set.h
usrcompat.o: $(hdrdir)/ruby/internal/intern/signal.h
usrcompat.o: $(hdrdir)/ruby/internal/intern/sprintf.h
usrcompat.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/marshal/internal_ivar/depend b/ext/-test-/marshal/internal_ivar/depend
index f8be031efc..a2e093d809 100644
--- a/ext/-test-/marshal/internal_ivar/depend
+++ b/ext/-test-/marshal/internal_ivar/depend
@@ -128,6 +128,7 @@ internal_ivar.o: $(hdrdir)/ruby/internal/intern/re.h
internal_ivar.o: $(hdrdir)/ruby/internal/intern/ruby.h
internal_ivar.o: $(hdrdir)/ruby/internal/intern/select.h
internal_ivar.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+internal_ivar.o: $(hdrdir)/ruby/internal/intern/set.h
internal_ivar.o: $(hdrdir)/ruby/internal/intern/signal.h
internal_ivar.o: $(hdrdir)/ruby/internal/intern/sprintf.h
internal_ivar.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/marshal/internal_ivar/internal_ivar.c b/ext/-test-/marshal/internal_ivar/internal_ivar.c
index b2188f737a..2e2f9cb235 100644
--- a/ext/-test-/marshal/internal_ivar/internal_ivar.c
+++ b/ext/-test-/marshal/internal_ivar/internal_ivar.c
@@ -1,13 +1,14 @@
#include <ruby.h>
-static ID id_normal_ivar, id_internal_ivar, id_encoding_short;
+static ID id_normal_ivar, id_internal_ivar, id_encoding_short, id_encoding_long;
static VALUE
-init(VALUE self, VALUE arg1, VALUE arg2, VALUE arg3)
+init(VALUE self, VALUE arg1, VALUE arg2, VALUE arg3, VALUE arg4)
{
rb_ivar_set(self, id_normal_ivar, arg1);
rb_ivar_set(self, id_internal_ivar, arg2);
rb_ivar_set(self, id_encoding_short, arg3);
+ rb_ivar_set(self, id_encoding_long, arg4);
return self;
}
@@ -29,6 +30,12 @@ get_encoding_short(VALUE self)
return rb_attr_get(self, id_encoding_short);
}
+static VALUE
+get_encoding_long(VALUE self)
+{
+ return rb_attr_get(self, id_encoding_long);
+}
+
void
Init_internal_ivar(void)
{
@@ -38,8 +45,10 @@ Init_internal_ivar(void)
id_normal_ivar = rb_intern_const("normal");
id_internal_ivar = rb_intern_const("K");
id_encoding_short = rb_intern_const("E");
- rb_define_method(newclass, "initialize", init, 3);
+ id_encoding_long = rb_intern_const("encoding");
+ rb_define_method(newclass, "initialize", init, 4);
rb_define_method(newclass, "normal", get_normal, 0);
rb_define_method(newclass, "internal", get_internal, 0);
rb_define_method(newclass, "encoding_short", get_encoding_short, 0);
+ rb_define_method(newclass, "encoding_long", get_encoding_long, 0);
}
diff --git a/ext/-test-/marshal/usr/depend b/ext/-test-/marshal/usr/depend
index 09e8207d3a..5ffb8c58de 100644
--- a/ext/-test-/marshal/usr/depend
+++ b/ext/-test-/marshal/usr/depend
@@ -128,6 +128,7 @@ usrmarshal.o: $(hdrdir)/ruby/internal/intern/re.h
usrmarshal.o: $(hdrdir)/ruby/internal/intern/ruby.h
usrmarshal.o: $(hdrdir)/ruby/internal/intern/select.h
usrmarshal.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+usrmarshal.o: $(hdrdir)/ruby/internal/intern/set.h
usrmarshal.o: $(hdrdir)/ruby/internal/intern/signal.h
usrmarshal.o: $(hdrdir)/ruby/internal/intern/sprintf.h
usrmarshal.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/memory_status/depend b/ext/-test-/memory_status/depend
index 52e2fe8e1f..4dd503e1bb 100644
--- a/ext/-test-/memory_status/depend
+++ b/ext/-test-/memory_status/depend
@@ -147,6 +147,7 @@ memory_status.o: $(hdrdir)/ruby/internal/special_consts.h
memory_status.o: $(hdrdir)/ruby/internal/static_assert.h
memory_status.o: $(hdrdir)/ruby/internal/stdalign.h
memory_status.o: $(hdrdir)/ruby/internal/stdbool.h
+memory_status.o: $(hdrdir)/ruby/internal/stdckdint.h
memory_status.o: $(hdrdir)/ruby/internal/symbol.h
memory_status.o: $(hdrdir)/ruby/internal/value.h
memory_status.o: $(hdrdir)/ruby/internal/value_type.h
diff --git a/ext/-test-/memory_view/depend b/ext/-test-/memory_view/depend
index 0c92fc1236..a6ffd76f45 100644
--- a/ext/-test-/memory_view/depend
+++ b/ext/-test-/memory_view/depend
@@ -128,6 +128,7 @@ memory_view.o: $(hdrdir)/ruby/internal/intern/re.h
memory_view.o: $(hdrdir)/ruby/internal/intern/ruby.h
memory_view.o: $(hdrdir)/ruby/internal/intern/select.h
memory_view.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+memory_view.o: $(hdrdir)/ruby/internal/intern/set.h
memory_view.o: $(hdrdir)/ruby/internal/intern/signal.h
memory_view.o: $(hdrdir)/ruby/internal/intern/sprintf.h
memory_view.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/method/depend b/ext/-test-/method/depend
index dce2a815a4..95745b3dae 100644
--- a/ext/-test-/method/depend
+++ b/ext/-test-/method/depend
@@ -128,6 +128,7 @@ arity.o: $(hdrdir)/ruby/internal/intern/re.h
arity.o: $(hdrdir)/ruby/internal/intern/ruby.h
arity.o: $(hdrdir)/ruby/internal/intern/select.h
arity.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+arity.o: $(hdrdir)/ruby/internal/intern/set.h
arity.o: $(hdrdir)/ruby/internal/intern/signal.h
arity.o: $(hdrdir)/ruby/internal/intern/sprintf.h
arity.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -288,6 +289,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h
init.o: $(hdrdir)/ruby/internal/intern/ruby.h
init.o: $(hdrdir)/ruby/internal/intern/select.h
init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
init.o: $(hdrdir)/ruby/internal/intern/signal.h
init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
init.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/notimplement/depend b/ext/-test-/notimplement/depend
index 84517a9c15..69c970b6f2 100644
--- a/ext/-test-/notimplement/depend
+++ b/ext/-test-/notimplement/depend
@@ -128,6 +128,7 @@ bug.o: $(hdrdir)/ruby/internal/intern/re.h
bug.o: $(hdrdir)/ruby/internal/intern/ruby.h
bug.o: $(hdrdir)/ruby/internal/intern/select.h
bug.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+bug.o: $(hdrdir)/ruby/internal/intern/set.h
bug.o: $(hdrdir)/ruby/internal/intern/signal.h
bug.o: $(hdrdir)/ruby/internal/intern/sprintf.h
bug.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/num2int/depend b/ext/-test-/num2int/depend
index 5550033be7..75536363ac 100644
--- a/ext/-test-/num2int/depend
+++ b/ext/-test-/num2int/depend
@@ -128,6 +128,7 @@ num2int.o: $(hdrdir)/ruby/internal/intern/re.h
num2int.o: $(hdrdir)/ruby/internal/intern/ruby.h
num2int.o: $(hdrdir)/ruby/internal/intern/select.h
num2int.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+num2int.o: $(hdrdir)/ruby/internal/intern/set.h
num2int.o: $(hdrdir)/ruby/internal/intern/signal.h
num2int.o: $(hdrdir)/ruby/internal/intern/sprintf.h
num2int.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/path_to_class/depend b/ext/-test-/path_to_class/depend
index a1657c9574..e535058e09 100644
--- a/ext/-test-/path_to_class/depend
+++ b/ext/-test-/path_to_class/depend
@@ -128,6 +128,7 @@ path_to_class.o: $(hdrdir)/ruby/internal/intern/re.h
path_to_class.o: $(hdrdir)/ruby/internal/intern/ruby.h
path_to_class.o: $(hdrdir)/ruby/internal/intern/select.h
path_to_class.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+path_to_class.o: $(hdrdir)/ruby/internal/intern/set.h
path_to_class.o: $(hdrdir)/ruby/internal/intern/signal.h
path_to_class.o: $(hdrdir)/ruby/internal/intern/sprintf.h
path_to_class.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/popen_deadlock/depend b/ext/-test-/popen_deadlock/depend
index 1904e64e59..0b8932e8b8 100644
--- a/ext/-test-/popen_deadlock/depend
+++ b/ext/-test-/popen_deadlock/depend
@@ -128,6 +128,7 @@ infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/re.h
infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/ruby.h
infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/select.h
infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/set.h
infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/signal.h
infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/sprintf.h
infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/postponed_job/depend b/ext/-test-/postponed_job/depend
index 72250896b0..ff567e3921 100644
--- a/ext/-test-/postponed_job/depend
+++ b/ext/-test-/postponed_job/depend
@@ -129,6 +129,7 @@ postponed_job.o: $(hdrdir)/ruby/internal/intern/re.h
postponed_job.o: $(hdrdir)/ruby/internal/intern/ruby.h
postponed_job.o: $(hdrdir)/ruby/internal/intern/select.h
postponed_job.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+postponed_job.o: $(hdrdir)/ruby/internal/intern/set.h
postponed_job.o: $(hdrdir)/ruby/internal/intern/signal.h
postponed_job.o: $(hdrdir)/ruby/internal/intern/sprintf.h
postponed_job.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/printf/depend b/ext/-test-/printf/depend
index 0530df78bf..be895cf769 100644
--- a/ext/-test-/printf/depend
+++ b/ext/-test-/printf/depend
@@ -138,6 +138,7 @@ printf.o: $(hdrdir)/ruby/internal/intern/re.h
printf.o: $(hdrdir)/ruby/internal/intern/ruby.h
printf.o: $(hdrdir)/ruby/internal/intern/select.h
printf.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+printf.o: $(hdrdir)/ruby/internal/intern/set.h
printf.o: $(hdrdir)/ruby/internal/intern/signal.h
printf.o: $(hdrdir)/ruby/internal/intern/sprintf.h
printf.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/proc/depend b/ext/-test-/proc/depend
index 45e12bcd09..97834db0a2 100644
--- a/ext/-test-/proc/depend
+++ b/ext/-test-/proc/depend
@@ -128,6 +128,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h
init.o: $(hdrdir)/ruby/internal/intern/ruby.h
init.o: $(hdrdir)/ruby/internal/intern/select.h
init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
init.o: $(hdrdir)/ruby/internal/intern/signal.h
init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
init.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -288,6 +289,7 @@ receiver.o: $(hdrdir)/ruby/internal/intern/re.h
receiver.o: $(hdrdir)/ruby/internal/intern/ruby.h
receiver.o: $(hdrdir)/ruby/internal/intern/select.h
receiver.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+receiver.o: $(hdrdir)/ruby/internal/intern/set.h
receiver.o: $(hdrdir)/ruby/internal/intern/signal.h
receiver.o: $(hdrdir)/ruby/internal/intern/sprintf.h
receiver.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -448,6 +450,7 @@ super.o: $(hdrdir)/ruby/internal/intern/re.h
super.o: $(hdrdir)/ruby/internal/intern/ruby.h
super.o: $(hdrdir)/ruby/internal/intern/select.h
super.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+super.o: $(hdrdir)/ruby/internal/intern/set.h
super.o: $(hdrdir)/ruby/internal/intern/signal.h
super.o: $(hdrdir)/ruby/internal/intern/sprintf.h
super.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/public_header_warnings/extconf.rb b/ext/-test-/public_header_warnings/extconf.rb
index f6a8a51f63..4431e09da4 100644
--- a/ext/-test-/public_header_warnings/extconf.rb
+++ b/ext/-test-/public_header_warnings/extconf.rb
@@ -5,9 +5,14 @@
#
def check_append_cflags(flag, msg = nil)
msg ||= "flag #{flag} is not acceptable"
- !$CFLAGS.include?(flag) or raise("flag #{flag} already present in $CFLAGS")
+ if $CFLAGS.include?(flag)
+ raise("flag #{flag} already present in $CFLAGS")
+ end
append_cflags(flag)
- $CFLAGS.include?(flag) or raise(msg)
+ unless $CFLAGS.include?(flag)
+ system("cat mkmf.log")
+ raise(msg)
+ end
end
if %w[gcc clang].include?(RbConfig::CONFIG['CC'])
diff --git a/ext/-test-/random/depend b/ext/-test-/random/depend
index 71f5f6e1e6..380c30fbe4 100644
--- a/ext/-test-/random/depend
+++ b/ext/-test-/random/depend
@@ -127,6 +127,7 @@ bad_version.o: $(hdrdir)/ruby/internal/intern/re.h
bad_version.o: $(hdrdir)/ruby/internal/intern/ruby.h
bad_version.o: $(hdrdir)/ruby/internal/intern/select.h
bad_version.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+bad_version.o: $(hdrdir)/ruby/internal/intern/set.h
bad_version.o: $(hdrdir)/ruby/internal/intern/signal.h
bad_version.o: $(hdrdir)/ruby/internal/intern/sprintf.h
bad_version.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -288,6 +289,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h
init.o: $(hdrdir)/ruby/internal/intern/ruby.h
init.o: $(hdrdir)/ruby/internal/intern/select.h
init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
init.o: $(hdrdir)/ruby/internal/intern/signal.h
init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
init.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -447,6 +449,7 @@ loop.o: $(hdrdir)/ruby/internal/intern/re.h
loop.o: $(hdrdir)/ruby/internal/intern/ruby.h
loop.o: $(hdrdir)/ruby/internal/intern/select.h
loop.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+loop.o: $(hdrdir)/ruby/internal/intern/set.h
loop.o: $(hdrdir)/ruby/internal/intern/signal.h
loop.o: $(hdrdir)/ruby/internal/intern/sprintf.h
loop.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/random/loop.c b/ext/-test-/random/loop.c
index b789ab1d01..f79e5cfd83 100644
--- a/ext/-test-/random/loop.c
+++ b/ext/-test-/random/loop.c
@@ -13,6 +13,15 @@ static const rb_random_interface_t random_loop_if = {
RB_RANDOM_INTERFACE_DEFINE_WITH_REAL(loop)
};
+static void
+loop_free(void *ptr)
+{
+ rand_loop_t *r = ptr;
+
+ xfree(r->buf);
+ xfree(r);
+}
+
RB_RANDOM_DEFINE_INIT_INT32_FUNC(loop)
static size_t
random_loop_memsize(const void *ptr)
@@ -25,7 +34,7 @@ static rb_random_data_type_t random_loop_type = {
"random/loop",
{
rb_random_mark,
- RUBY_TYPED_DEFAULT_FREE,
+ loop_free,
random_loop_memsize,
},
RB_RANDOM_PARENT,
diff --git a/ext/-test-/rational/depend b/ext/-test-/rational/depend
index 363d779302..56d6ab77d6 100644
--- a/ext/-test-/rational/depend
+++ b/ext/-test-/rational/depend
@@ -132,6 +132,7 @@ rat.o: $(hdrdir)/ruby/internal/intern/re.h
rat.o: $(hdrdir)/ruby/internal/intern/ruby.h
rat.o: $(hdrdir)/ruby/internal/intern/select.h
rat.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+rat.o: $(hdrdir)/ruby/internal/intern/set.h
rat.o: $(hdrdir)/ruby/internal/intern/signal.h
rat.o: $(hdrdir)/ruby/internal/intern/sprintf.h
rat.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/rb_call_super_kw/depend b/ext/-test-/rb_call_super_kw/depend
index 04a0fac12c..bf34323ca7 100644
--- a/ext/-test-/rb_call_super_kw/depend
+++ b/ext/-test-/rb_call_super_kw/depend
@@ -128,6 +128,7 @@ rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/re.h
rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/ruby.h
rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/select.h
rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/set.h
rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/signal.h
rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/sprintf.h
rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/recursion/depend b/ext/-test-/recursion/depend
index 2a65c98b09..b6487eb4df 100644
--- a/ext/-test-/recursion/depend
+++ b/ext/-test-/recursion/depend
@@ -128,6 +128,7 @@ recursion.o: $(hdrdir)/ruby/internal/intern/re.h
recursion.o: $(hdrdir)/ruby/internal/intern/ruby.h
recursion.o: $(hdrdir)/ruby/internal/intern/select.h
recursion.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+recursion.o: $(hdrdir)/ruby/internal/intern/set.h
recursion.o: $(hdrdir)/ruby/internal/intern/signal.h
recursion.o: $(hdrdir)/ruby/internal/intern/sprintf.h
recursion.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/regexp/depend b/ext/-test-/regexp/depend
index 0127a66a2e..5ba1b92f18 100644
--- a/ext/-test-/regexp/depend
+++ b/ext/-test-/regexp/depend
@@ -128,6 +128,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h
init.o: $(hdrdir)/ruby/internal/intern/ruby.h
init.o: $(hdrdir)/ruby/internal/intern/select.h
init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
init.o: $(hdrdir)/ruby/internal/intern/signal.h
init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
init.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -288,6 +289,7 @@ parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/re.h
parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/ruby.h
parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/select.h
parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/set.h
parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/signal.h
parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/sprintf.h
parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/sanitizers/depend b/ext/-test-/sanitizers/depend
new file mode 100644
index 0000000000..0e6e632803
--- /dev/null
+++ b/ext/-test-/sanitizers/depend
@@ -0,0 +1,162 @@
+# AUTOGENERATED DEPENDENCIES START
+sanitizers.o: $(RUBY_EXTCONF_H)
+sanitizers.o: $(arch_hdrdir)/ruby/config.h
+sanitizers.o: $(hdrdir)/ruby/assert.h
+sanitizers.o: $(hdrdir)/ruby/backward.h
+sanitizers.o: $(hdrdir)/ruby/backward/2/assume.h
+sanitizers.o: $(hdrdir)/ruby/backward/2/attributes.h
+sanitizers.o: $(hdrdir)/ruby/backward/2/bool.h
+sanitizers.o: $(hdrdir)/ruby/backward/2/inttypes.h
+sanitizers.o: $(hdrdir)/ruby/backward/2/limits.h
+sanitizers.o: $(hdrdir)/ruby/backward/2/long_long.h
+sanitizers.o: $(hdrdir)/ruby/backward/2/stdalign.h
+sanitizers.o: $(hdrdir)/ruby/backward/2/stdarg.h
+sanitizers.o: $(hdrdir)/ruby/defines.h
+sanitizers.o: $(hdrdir)/ruby/intern.h
+sanitizers.o: $(hdrdir)/ruby/internal/abi.h
+sanitizers.o: $(hdrdir)/ruby/internal/anyargs.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+sanitizers.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+sanitizers.o: $(hdrdir)/ruby/internal/assume.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/artificial.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/cold.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/const.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/error.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/format.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/noalias.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/noinline.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/pure.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/restrict.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/warning.h
+sanitizers.o: $(hdrdir)/ruby/internal/attr/weakref.h
+sanitizers.o: $(hdrdir)/ruby/internal/cast.h
+sanitizers.o: $(hdrdir)/ruby/internal/compiler_is.h
+sanitizers.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+sanitizers.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+sanitizers.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+sanitizers.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+sanitizers.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+sanitizers.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+sanitizers.o: $(hdrdir)/ruby/internal/compiler_since.h
+sanitizers.o: $(hdrdir)/ruby/internal/config.h
+sanitizers.o: $(hdrdir)/ruby/internal/constant_p.h
+sanitizers.o: $(hdrdir)/ruby/internal/core.h
+sanitizers.o: $(hdrdir)/ruby/internal/core/rarray.h
+sanitizers.o: $(hdrdir)/ruby/internal/core/rbasic.h
+sanitizers.o: $(hdrdir)/ruby/internal/core/rbignum.h
+sanitizers.o: $(hdrdir)/ruby/internal/core/rclass.h
+sanitizers.o: $(hdrdir)/ruby/internal/core/rdata.h
+sanitizers.o: $(hdrdir)/ruby/internal/core/rfile.h
+sanitizers.o: $(hdrdir)/ruby/internal/core/rhash.h
+sanitizers.o: $(hdrdir)/ruby/internal/core/robject.h
+sanitizers.o: $(hdrdir)/ruby/internal/core/rregexp.h
+sanitizers.o: $(hdrdir)/ruby/internal/core/rstring.h
+sanitizers.o: $(hdrdir)/ruby/internal/core/rstruct.h
+sanitizers.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+sanitizers.o: $(hdrdir)/ruby/internal/ctype.h
+sanitizers.o: $(hdrdir)/ruby/internal/dllexport.h
+sanitizers.o: $(hdrdir)/ruby/internal/dosish.h
+sanitizers.o: $(hdrdir)/ruby/internal/error.h
+sanitizers.o: $(hdrdir)/ruby/internal/eval.h
+sanitizers.o: $(hdrdir)/ruby/internal/event.h
+sanitizers.o: $(hdrdir)/ruby/internal/fl_type.h
+sanitizers.o: $(hdrdir)/ruby/internal/gc.h
+sanitizers.o: $(hdrdir)/ruby/internal/glob.h
+sanitizers.o: $(hdrdir)/ruby/internal/globals.h
+sanitizers.o: $(hdrdir)/ruby/internal/has/attribute.h
+sanitizers.o: $(hdrdir)/ruby/internal/has/builtin.h
+sanitizers.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+sanitizers.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+sanitizers.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+sanitizers.o: $(hdrdir)/ruby/internal/has/extension.h
+sanitizers.o: $(hdrdir)/ruby/internal/has/feature.h
+sanitizers.o: $(hdrdir)/ruby/internal/has/warning.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/array.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/bignum.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/class.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/compar.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/complex.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/cont.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/dir.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/enum.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/error.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/eval.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/file.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/hash.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/io.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/load.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/marshal.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/numeric.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/object.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/parse.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/proc.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/process.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/random.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/range.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/rational.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/re.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/ruby.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/select.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/set.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/signal.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/string.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/struct.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/thread.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/time.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/variable.h
+sanitizers.o: $(hdrdir)/ruby/internal/intern/vm.h
+sanitizers.o: $(hdrdir)/ruby/internal/interpreter.h
+sanitizers.o: $(hdrdir)/ruby/internal/iterator.h
+sanitizers.o: $(hdrdir)/ruby/internal/memory.h
+sanitizers.o: $(hdrdir)/ruby/internal/method.h
+sanitizers.o: $(hdrdir)/ruby/internal/module.h
+sanitizers.o: $(hdrdir)/ruby/internal/newobj.h
+sanitizers.o: $(hdrdir)/ruby/internal/scan_args.h
+sanitizers.o: $(hdrdir)/ruby/internal/special_consts.h
+sanitizers.o: $(hdrdir)/ruby/internal/static_assert.h
+sanitizers.o: $(hdrdir)/ruby/internal/stdalign.h
+sanitizers.o: $(hdrdir)/ruby/internal/stdbool.h
+sanitizers.o: $(hdrdir)/ruby/internal/stdckdint.h
+sanitizers.o: $(hdrdir)/ruby/internal/symbol.h
+sanitizers.o: $(hdrdir)/ruby/internal/value.h
+sanitizers.o: $(hdrdir)/ruby/internal/value_type.h
+sanitizers.o: $(hdrdir)/ruby/internal/variable.h
+sanitizers.o: $(hdrdir)/ruby/internal/warning_push.h
+sanitizers.o: $(hdrdir)/ruby/internal/xmalloc.h
+sanitizers.o: $(hdrdir)/ruby/missing.h
+sanitizers.o: $(hdrdir)/ruby/ruby.h
+sanitizers.o: $(hdrdir)/ruby/st.h
+sanitizers.o: $(hdrdir)/ruby/subst.h
+sanitizers.o: sanitizers.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/sanitizers/extconf.rb b/ext/-test-/sanitizers/extconf.rb
new file mode 100644
index 0000000000..c94a96de6c
--- /dev/null
+++ b/ext/-test-/sanitizers/extconf.rb
@@ -0,0 +1,2 @@
+require 'mkmf'
+create_makefile('-test-/sanitizers')
diff --git a/ext/-test-/sanitizers/sanitizers.c b/ext/-test-/sanitizers/sanitizers.c
new file mode 100644
index 0000000000..97a85b26ef
--- /dev/null
+++ b/ext/-test-/sanitizers/sanitizers.c
@@ -0,0 +1,36 @@
+#include "ruby/ruby.h"
+
+static VALUE
+asan_enabled_p(VALUE self)
+{
+#if defined(__has_feature)
+ /* clang uses __has_feature for determining asan */
+ return __has_feature(address_sanitizer) ? Qtrue : Qfalse;
+#elif defined(__SANITIZE_ADDRESS__)
+ /* GCC sets __SANITIZE_ADDRESS__ for determining asan */
+ return Qtrue;
+#else
+ return Qfalse;
+#endif
+}
+
+static VALUE
+lsan_enabled_p(VALUE self)
+{
+#if defined(__has_feature)
+ /* clang uses __has_feature for determining LSAN */
+ return __has_feature(leak_sanitizer) ? Qtrue : Qfalse;
+#else
+ return Qfalse;
+#endif
+}
+
+void
+Init_sanitizers(void)
+{
+ VALUE m = rb_define_module("Test");
+ VALUE c = rb_define_class_under(m, "Sanitizers", rb_cObject);
+ rb_define_singleton_method(c, "asan_enabled?", asan_enabled_p, 0);
+ rb_define_singleton_method(c, "lsan_enabled?", lsan_enabled_p, 0);
+}
+
diff --git a/ext/-test-/scan_args/depend b/ext/-test-/scan_args/depend
index 922e5bbd5c..ca0fc19238 100644
--- a/ext/-test-/scan_args/depend
+++ b/ext/-test-/scan_args/depend
@@ -128,6 +128,7 @@ scan_args.o: $(hdrdir)/ruby/internal/intern/re.h
scan_args.o: $(hdrdir)/ruby/internal/intern/ruby.h
scan_args.o: $(hdrdir)/ruby/internal/intern/select.h
scan_args.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+scan_args.o: $(hdrdir)/ruby/internal/intern/set.h
scan_args.o: $(hdrdir)/ruby/internal/intern/signal.h
scan_args.o: $(hdrdir)/ruby/internal/intern/sprintf.h
scan_args.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/scheduler/extconf.rb b/ext/-test-/scheduler/extconf.rb
new file mode 100644
index 0000000000..159699bd8e
--- /dev/null
+++ b/ext/-test-/scheduler/extconf.rb
@@ -0,0 +1,2 @@
+# frozen_string_literal: false
+create_makefile("-test-/scheduler")
diff --git a/ext/-test-/scheduler/scheduler.c b/ext/-test-/scheduler/scheduler.c
new file mode 100644
index 0000000000..b742a5573b
--- /dev/null
+++ b/ext/-test-/scheduler/scheduler.c
@@ -0,0 +1,92 @@
+#include "ruby/ruby.h"
+#include "ruby/thread.h"
+#include "ruby/io.h"
+#include "ruby/fiber/scheduler.h"
+
+/*
+ * Test extension for reproducing the gRPC interrupt handling bug.
+ *
+ * This reproduces the exact issue from grpc/grpc commit 69f229e (June 2025):
+ * https://github.com/grpc/grpc/commit/69f229edd1d79ab7a7dfda98e3aef6fd807adcad
+ *
+ * The bug occurs when:
+ * 1. A fiber scheduler uses Thread.handle_interrupt(::SignalException => :never)
+ * (like Async::Scheduler does)
+ * 2. Native code uses rb_thread_call_without_gvl in a retry loop that checks
+ * the interrupted flag and retries (like gRPC's completion queue)
+ * 3. A signal (SIGINT/SIGTERM) is sent
+ * 4. The unblock_func sets interrupted=1, but Thread.handle_interrupt defers the signal
+ * 5. The loop sees interrupted=1 and retries without yielding to the scheduler
+ * 6. The deferred interrupt never gets processed -> infinite hang
+ *
+ * The fix is in vm_check_ints_blocking() in thread.c, which should yield to
+ * the fiber scheduler when interrupts are pending, allowing the scheduler to
+ * detect Thread.pending_interrupt? and exit its run loop.
+ */
+
+struct blocking_state {
+ int notify_descriptor;
+ volatile int interrupted;
+};
+
+static void
+unblock_callback(void *argument)
+{
+ struct blocking_state *blocking_state = (struct blocking_state *)argument;
+ blocking_state->interrupted = 1;
+}
+
+static void *
+blocking_operation(void *argument)
+{
+ struct blocking_state *blocking_state = (struct blocking_state *)argument;
+
+ ssize_t ret = write(blocking_state->notify_descriptor, "x", 1);
+ (void)ret; // ignore the result for now
+
+ while (!blocking_state->interrupted) {
+ struct timeval tv = {1, 0}; // 1 second timeout.
+ int result = select(0, NULL, NULL, NULL, &tv);
+
+ if (result == -1 && errno == EINTR) {
+ blocking_state->interrupted = 1;
+ }
+
+ // Otherwise, timeout -> loop again.
+ }
+
+ return NULL;
+}
+
+static VALUE
+scheduler_blocking_loop(VALUE self, VALUE notify)
+{
+ struct blocking_state blocking_state = {
+ .notify_descriptor = rb_io_descriptor(notify),
+ .interrupted = 0,
+ };
+
+ while (true) {
+ blocking_state.interrupted = 0;
+
+ rb_thread_call_without_gvl(
+ blocking_operation, &blocking_state,
+ unblock_callback, &blocking_state
+ );
+
+ // The bug: When interrupted, loop retries without yielding to scheduler.
+ // With Thread.handle_interrupt(:never), this causes an infinite hang,
+ // because the deferred interrupt never gets a chance to be processed.
+ } while (blocking_state.interrupted);
+
+ return Qnil;
+}
+
+void
+Init_scheduler(void)
+{
+ VALUE mBug = rb_define_module("Bug");
+ VALUE mScheduler = rb_define_module_under(mBug, "Scheduler");
+
+ rb_define_module_function(mScheduler, "blocking_loop", scheduler_blocking_loop, 1);
+}
diff --git a/ext/-test-/st/foreach/depend b/ext/-test-/st/foreach/depend
index 36273f8df8..29aab2bb29 100644
--- a/ext/-test-/st/foreach/depend
+++ b/ext/-test-/st/foreach/depend
@@ -128,6 +128,7 @@ foreach.o: $(hdrdir)/ruby/internal/intern/re.h
foreach.o: $(hdrdir)/ruby/internal/intern/ruby.h
foreach.o: $(hdrdir)/ruby/internal/intern/select.h
foreach.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+foreach.o: $(hdrdir)/ruby/internal/intern/set.h
foreach.o: $(hdrdir)/ruby/internal/intern/signal.h
foreach.o: $(hdrdir)/ruby/internal/intern/sprintf.h
foreach.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/st/numhash/depend b/ext/-test-/st/numhash/depend
index a0916183b6..18320d55f5 100644
--- a/ext/-test-/st/numhash/depend
+++ b/ext/-test-/st/numhash/depend
@@ -128,6 +128,7 @@ numhash.o: $(hdrdir)/ruby/internal/intern/re.h
numhash.o: $(hdrdir)/ruby/internal/intern/ruby.h
numhash.o: $(hdrdir)/ruby/internal/intern/select.h
numhash.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+numhash.o: $(hdrdir)/ruby/internal/intern/set.h
numhash.o: $(hdrdir)/ruby/internal/intern/signal.h
numhash.o: $(hdrdir)/ruby/internal/intern/sprintf.h
numhash.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/st/update/depend b/ext/-test-/st/update/depend
index 96ba194df0..247f0efd6b 100644
--- a/ext/-test-/st/update/depend
+++ b/ext/-test-/st/update/depend
@@ -128,6 +128,7 @@ update.o: $(hdrdir)/ruby/internal/intern/re.h
update.o: $(hdrdir)/ruby/internal/intern/ruby.h
update.o: $(hdrdir)/ruby/internal/intern/select.h
update.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+update.o: $(hdrdir)/ruby/internal/intern/set.h
update.o: $(hdrdir)/ruby/internal/intern/signal.h
update.o: $(hdrdir)/ruby/internal/intern/sprintf.h
update.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/stack/depend b/ext/-test-/stack/depend
new file mode 100644
index 0000000000..77e93bb201
--- /dev/null
+++ b/ext/-test-/stack/depend
@@ -0,0 +1,179 @@
+# AUTOGENERATED DEPENDENCIES START
+stack.o: $(RUBY_EXTCONF_H)
+stack.o: $(arch_hdrdir)/ruby/config.h
+stack.o: $(hdrdir)/ruby.h
+stack.o: $(hdrdir)/ruby/assert.h
+stack.o: $(hdrdir)/ruby/backward.h
+stack.o: $(hdrdir)/ruby/backward/2/assume.h
+stack.o: $(hdrdir)/ruby/backward/2/attributes.h
+stack.o: $(hdrdir)/ruby/backward/2/bool.h
+stack.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h
+stack.o: $(hdrdir)/ruby/backward/2/inttypes.h
+stack.o: $(hdrdir)/ruby/backward/2/limits.h
+stack.o: $(hdrdir)/ruby/backward/2/long_long.h
+stack.o: $(hdrdir)/ruby/backward/2/stdalign.h
+stack.o: $(hdrdir)/ruby/backward/2/stdarg.h
+stack.o: $(hdrdir)/ruby/defines.h
+stack.o: $(hdrdir)/ruby/encoding.h
+stack.o: $(hdrdir)/ruby/intern.h
+stack.o: $(hdrdir)/ruby/internal/abi.h
+stack.o: $(hdrdir)/ruby/internal/anyargs.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+stack.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+stack.o: $(hdrdir)/ruby/internal/assume.h
+stack.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+stack.o: $(hdrdir)/ruby/internal/attr/artificial.h
+stack.o: $(hdrdir)/ruby/internal/attr/cold.h
+stack.o: $(hdrdir)/ruby/internal/attr/const.h
+stack.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+stack.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+stack.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+stack.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+stack.o: $(hdrdir)/ruby/internal/attr/error.h
+stack.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+stack.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+stack.o: $(hdrdir)/ruby/internal/attr/format.h
+stack.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+stack.o: $(hdrdir)/ruby/internal/attr/noalias.h
+stack.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+stack.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+stack.o: $(hdrdir)/ruby/internal/attr/noinline.h
+stack.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+stack.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+stack.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+stack.o: $(hdrdir)/ruby/internal/attr/pure.h
+stack.o: $(hdrdir)/ruby/internal/attr/restrict.h
+stack.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+stack.o: $(hdrdir)/ruby/internal/attr/warning.h
+stack.o: $(hdrdir)/ruby/internal/attr/weakref.h
+stack.o: $(hdrdir)/ruby/internal/cast.h
+stack.o: $(hdrdir)/ruby/internal/compiler_is.h
+stack.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+stack.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+stack.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+stack.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+stack.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+stack.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+stack.o: $(hdrdir)/ruby/internal/compiler_since.h
+stack.o: $(hdrdir)/ruby/internal/config.h
+stack.o: $(hdrdir)/ruby/internal/constant_p.h
+stack.o: $(hdrdir)/ruby/internal/core.h
+stack.o: $(hdrdir)/ruby/internal/core/rarray.h
+stack.o: $(hdrdir)/ruby/internal/core/rbasic.h
+stack.o: $(hdrdir)/ruby/internal/core/rbignum.h
+stack.o: $(hdrdir)/ruby/internal/core/rclass.h
+stack.o: $(hdrdir)/ruby/internal/core/rdata.h
+stack.o: $(hdrdir)/ruby/internal/core/rfile.h
+stack.o: $(hdrdir)/ruby/internal/core/rhash.h
+stack.o: $(hdrdir)/ruby/internal/core/robject.h
+stack.o: $(hdrdir)/ruby/internal/core/rregexp.h
+stack.o: $(hdrdir)/ruby/internal/core/rstring.h
+stack.o: $(hdrdir)/ruby/internal/core/rstruct.h
+stack.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+stack.o: $(hdrdir)/ruby/internal/ctype.h
+stack.o: $(hdrdir)/ruby/internal/dllexport.h
+stack.o: $(hdrdir)/ruby/internal/dosish.h
+stack.o: $(hdrdir)/ruby/internal/encoding/coderange.h
+stack.o: $(hdrdir)/ruby/internal/encoding/ctype.h
+stack.o: $(hdrdir)/ruby/internal/encoding/encoding.h
+stack.o: $(hdrdir)/ruby/internal/encoding/pathname.h
+stack.o: $(hdrdir)/ruby/internal/encoding/re.h
+stack.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
+stack.o: $(hdrdir)/ruby/internal/encoding/string.h
+stack.o: $(hdrdir)/ruby/internal/encoding/symbol.h
+stack.o: $(hdrdir)/ruby/internal/encoding/transcode.h
+stack.o: $(hdrdir)/ruby/internal/error.h
+stack.o: $(hdrdir)/ruby/internal/eval.h
+stack.o: $(hdrdir)/ruby/internal/event.h
+stack.o: $(hdrdir)/ruby/internal/fl_type.h
+stack.o: $(hdrdir)/ruby/internal/gc.h
+stack.o: $(hdrdir)/ruby/internal/glob.h
+stack.o: $(hdrdir)/ruby/internal/globals.h
+stack.o: $(hdrdir)/ruby/internal/has/attribute.h
+stack.o: $(hdrdir)/ruby/internal/has/builtin.h
+stack.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+stack.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+stack.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+stack.o: $(hdrdir)/ruby/internal/has/extension.h
+stack.o: $(hdrdir)/ruby/internal/has/feature.h
+stack.o: $(hdrdir)/ruby/internal/has/warning.h
+stack.o: $(hdrdir)/ruby/internal/intern/array.h
+stack.o: $(hdrdir)/ruby/internal/intern/bignum.h
+stack.o: $(hdrdir)/ruby/internal/intern/class.h
+stack.o: $(hdrdir)/ruby/internal/intern/compar.h
+stack.o: $(hdrdir)/ruby/internal/intern/complex.h
+stack.o: $(hdrdir)/ruby/internal/intern/cont.h
+stack.o: $(hdrdir)/ruby/internal/intern/dir.h
+stack.o: $(hdrdir)/ruby/internal/intern/enum.h
+stack.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+stack.o: $(hdrdir)/ruby/internal/intern/error.h
+stack.o: $(hdrdir)/ruby/internal/intern/eval.h
+stack.o: $(hdrdir)/ruby/internal/intern/file.h
+stack.o: $(hdrdir)/ruby/internal/intern/hash.h
+stack.o: $(hdrdir)/ruby/internal/intern/io.h
+stack.o: $(hdrdir)/ruby/internal/intern/load.h
+stack.o: $(hdrdir)/ruby/internal/intern/marshal.h
+stack.o: $(hdrdir)/ruby/internal/intern/numeric.h
+stack.o: $(hdrdir)/ruby/internal/intern/object.h
+stack.o: $(hdrdir)/ruby/internal/intern/parse.h
+stack.o: $(hdrdir)/ruby/internal/intern/proc.h
+stack.o: $(hdrdir)/ruby/internal/intern/process.h
+stack.o: $(hdrdir)/ruby/internal/intern/random.h
+stack.o: $(hdrdir)/ruby/internal/intern/range.h
+stack.o: $(hdrdir)/ruby/internal/intern/rational.h
+stack.o: $(hdrdir)/ruby/internal/intern/re.h
+stack.o: $(hdrdir)/ruby/internal/intern/ruby.h
+stack.o: $(hdrdir)/ruby/internal/intern/select.h
+stack.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+stack.o: $(hdrdir)/ruby/internal/intern/set.h
+stack.o: $(hdrdir)/ruby/internal/intern/signal.h
+stack.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+stack.o: $(hdrdir)/ruby/internal/intern/string.h
+stack.o: $(hdrdir)/ruby/internal/intern/struct.h
+stack.o: $(hdrdir)/ruby/internal/intern/thread.h
+stack.o: $(hdrdir)/ruby/internal/intern/time.h
+stack.o: $(hdrdir)/ruby/internal/intern/variable.h
+stack.o: $(hdrdir)/ruby/internal/intern/vm.h
+stack.o: $(hdrdir)/ruby/internal/interpreter.h
+stack.o: $(hdrdir)/ruby/internal/iterator.h
+stack.o: $(hdrdir)/ruby/internal/memory.h
+stack.o: $(hdrdir)/ruby/internal/method.h
+stack.o: $(hdrdir)/ruby/internal/module.h
+stack.o: $(hdrdir)/ruby/internal/newobj.h
+stack.o: $(hdrdir)/ruby/internal/scan_args.h
+stack.o: $(hdrdir)/ruby/internal/special_consts.h
+stack.o: $(hdrdir)/ruby/internal/static_assert.h
+stack.o: $(hdrdir)/ruby/internal/stdalign.h
+stack.o: $(hdrdir)/ruby/internal/stdbool.h
+stack.o: $(hdrdir)/ruby/internal/stdckdint.h
+stack.o: $(hdrdir)/ruby/internal/symbol.h
+stack.o: $(hdrdir)/ruby/internal/value.h
+stack.o: $(hdrdir)/ruby/internal/value_type.h
+stack.o: $(hdrdir)/ruby/internal/variable.h
+stack.o: $(hdrdir)/ruby/internal/warning_push.h
+stack.o: $(hdrdir)/ruby/internal/xmalloc.h
+stack.o: $(hdrdir)/ruby/missing.h
+stack.o: $(hdrdir)/ruby/onigmo.h
+stack.o: $(hdrdir)/ruby/oniguruma.h
+stack.o: $(hdrdir)/ruby/ruby.h
+stack.o: $(hdrdir)/ruby/st.h
+stack.o: $(hdrdir)/ruby/subst.h
+stack.o: $(top_srcdir)/encindex.h
+stack.o: $(top_srcdir)/internal/compilers.h
+stack.o: $(top_srcdir)/internal/string.h
+stack.o: stack.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/stack/extconf.rb b/ext/-test-/stack/extconf.rb
new file mode 100644
index 0000000000..d786b15db9
--- /dev/null
+++ b/ext/-test-/stack/extconf.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: false
+require_relative "../auto_ext.rb"
+auto_ext(inc: true)
diff --git a/ext/-test-/stack/stack.c b/ext/-test-/stack/stack.c
new file mode 100644
index 0000000000..f0e65e74b2
--- /dev/null
+++ b/ext/-test-/stack/stack.c
@@ -0,0 +1,35 @@
+#include "ruby.h"
+#include "internal/string.h"
+
+static VALUE
+stack_overflow(VALUE self)
+{
+ size_t i = 0;
+
+ while (1) {
+ // Allocate and touch memory to force actual stack usage:
+ volatile char *stack = alloca(1024);
+ stack[0] = (char)i;
+ stack[1023] = (char)i;
+ i++;
+ }
+
+ return Qnil;
+}
+
+static VALUE
+asan_p(VALUE klass)
+{
+#if defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer)
+ return Qtrue;
+#else
+ return Qfalse;
+#endif
+}
+
+void
+Init_stack(VALUE klass)
+{
+ rb_define_singleton_method(rb_cThread, "stack_overflow", stack_overflow, 0);
+ rb_define_singleton_method(rb_cThread, "asan?", asan_p, 0);
+}
diff --git a/ext/-test-/string/depend b/ext/-test-/string/depend
index 044b6109ff..478ae3b82b 100644
--- a/ext/-test-/string/depend
+++ b/ext/-test-/string/depend
@@ -139,6 +139,7 @@ capacity.o: $(hdrdir)/ruby/internal/intern/re.h
capacity.o: $(hdrdir)/ruby/internal/intern/ruby.h
capacity.o: $(hdrdir)/ruby/internal/intern/select.h
capacity.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+capacity.o: $(hdrdir)/ruby/internal/intern/set.h
capacity.o: $(hdrdir)/ruby/internal/intern/signal.h
capacity.o: $(hdrdir)/ruby/internal/intern/sprintf.h
capacity.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -171,6 +172,7 @@ 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)/encindex.h
capacity.o: $(top_srcdir)/internal/compilers.h
capacity.o: $(top_srcdir)/internal/string.h
capacity.o: capacity.c
@@ -472,6 +474,7 @@ coderange.o: $(hdrdir)/ruby/internal/intern/re.h
coderange.o: $(hdrdir)/ruby/internal/intern/ruby.h
coderange.o: $(hdrdir)/ruby/internal/intern/select.h
coderange.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+coderange.o: $(hdrdir)/ruby/internal/intern/set.h
coderange.o: $(hdrdir)/ruby/internal/intern/signal.h
coderange.o: $(hdrdir)/ruby/internal/intern/sprintf.h
coderange.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -644,6 +647,7 @@ cstr.o: $(hdrdir)/ruby/internal/intern/re.h
cstr.o: $(hdrdir)/ruby/internal/intern/ruby.h
cstr.o: $(hdrdir)/ruby/internal/intern/select.h
cstr.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+cstr.o: $(hdrdir)/ruby/internal/intern/set.h
cstr.o: $(hdrdir)/ruby/internal/intern/signal.h
cstr.o: $(hdrdir)/ruby/internal/intern/sprintf.h
cstr.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -676,6 +680,7 @@ cstr.o: $(hdrdir)/ruby/oniguruma.h
cstr.o: $(hdrdir)/ruby/ruby.h
cstr.o: $(hdrdir)/ruby/st.h
cstr.o: $(hdrdir)/ruby/subst.h
+cstr.o: $(top_srcdir)/encindex.h
cstr.o: $(top_srcdir)/internal.h
cstr.o: $(top_srcdir)/internal/compilers.h
cstr.o: $(top_srcdir)/internal/string.h
@@ -809,6 +814,7 @@ ellipsize.o: $(hdrdir)/ruby/internal/intern/re.h
ellipsize.o: $(hdrdir)/ruby/internal/intern/ruby.h
ellipsize.o: $(hdrdir)/ruby/internal/intern/select.h
ellipsize.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ellipsize.o: $(hdrdir)/ruby/internal/intern/set.h
ellipsize.o: $(hdrdir)/ruby/internal/intern/signal.h
ellipsize.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ellipsize.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -979,6 +985,7 @@ enc_associate.o: $(hdrdir)/ruby/internal/intern/re.h
enc_associate.o: $(hdrdir)/ruby/internal/intern/ruby.h
enc_associate.o: $(hdrdir)/ruby/internal/intern/select.h
enc_associate.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+enc_associate.o: $(hdrdir)/ruby/internal/intern/set.h
enc_associate.o: $(hdrdir)/ruby/internal/intern/signal.h
enc_associate.o: $(hdrdir)/ruby/internal/intern/sprintf.h
enc_associate.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -1151,6 +1158,7 @@ enc_dummy.o: $(hdrdir)/ruby/internal/intern/re.h
enc_dummy.o: $(hdrdir)/ruby/internal/intern/ruby.h
enc_dummy.o: $(hdrdir)/ruby/internal/intern/select.h
enc_dummy.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+enc_dummy.o: $(hdrdir)/ruby/internal/intern/set.h
enc_dummy.o: $(hdrdir)/ruby/internal/intern/signal.h
enc_dummy.o: $(hdrdir)/ruby/internal/intern/sprintf.h
enc_dummy.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -1322,6 +1330,7 @@ enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/re.h
enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/ruby.h
enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/select.h
enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/set.h
enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/signal.h
enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/sprintf.h
enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -1495,6 +1504,7 @@ fstring.o: $(hdrdir)/ruby/internal/intern/re.h
fstring.o: $(hdrdir)/ruby/internal/intern/ruby.h
fstring.o: $(hdrdir)/ruby/internal/intern/select.h
fstring.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+fstring.o: $(hdrdir)/ruby/internal/intern/set.h
fstring.o: $(hdrdir)/ruby/internal/intern/signal.h
fstring.o: $(hdrdir)/ruby/internal/intern/sprintf.h
fstring.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -1527,6 +1537,7 @@ fstring.o: $(hdrdir)/ruby/oniguruma.h
fstring.o: $(hdrdir)/ruby/ruby.h
fstring.o: $(hdrdir)/ruby/st.h
fstring.o: $(hdrdir)/ruby/subst.h
+fstring.o: $(top_srcdir)/encindex.h
fstring.o: $(top_srcdir)/internal/compilers.h
fstring.o: $(top_srcdir)/internal/string.h
fstring.o: fstring.c
@@ -1659,6 +1670,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h
init.o: $(hdrdir)/ruby/internal/intern/ruby.h
init.o: $(hdrdir)/ruby/internal/intern/select.h
init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
init.o: $(hdrdir)/ruby/internal/intern/signal.h
init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
init.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -1819,6 +1831,7 @@ modify.o: $(hdrdir)/ruby/internal/intern/re.h
modify.o: $(hdrdir)/ruby/internal/intern/ruby.h
modify.o: $(hdrdir)/ruby/internal/intern/select.h
modify.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+modify.o: $(hdrdir)/ruby/internal/intern/set.h
modify.o: $(hdrdir)/ruby/internal/intern/signal.h
modify.o: $(hdrdir)/ruby/internal/intern/sprintf.h
modify.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -1989,6 +2002,7 @@ new.o: $(hdrdir)/ruby/internal/intern/re.h
new.o: $(hdrdir)/ruby/internal/intern/ruby.h
new.o: $(hdrdir)/ruby/internal/intern/select.h
new.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+new.o: $(hdrdir)/ruby/internal/intern/set.h
new.o: $(hdrdir)/ruby/internal/intern/signal.h
new.o: $(hdrdir)/ruby/internal/intern/sprintf.h
new.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -2151,6 +2165,7 @@ nofree.o: $(hdrdir)/ruby/internal/intern/re.h
nofree.o: $(hdrdir)/ruby/internal/intern/ruby.h
nofree.o: $(hdrdir)/ruby/internal/intern/select.h
nofree.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+nofree.o: $(hdrdir)/ruby/internal/intern/set.h
nofree.o: $(hdrdir)/ruby/internal/intern/signal.h
nofree.o: $(hdrdir)/ruby/internal/intern/sprintf.h
nofree.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -2320,6 +2335,7 @@ normalize.o: $(hdrdir)/ruby/internal/intern/re.h
normalize.o: $(hdrdir)/ruby/internal/intern/ruby.h
normalize.o: $(hdrdir)/ruby/internal/intern/select.h
normalize.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+normalize.o: $(hdrdir)/ruby/internal/intern/set.h
normalize.o: $(hdrdir)/ruby/internal/intern/signal.h
normalize.o: $(hdrdir)/ruby/internal/intern/sprintf.h
normalize.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -2493,6 +2509,7 @@ qsort.o: $(hdrdir)/ruby/internal/intern/re.h
qsort.o: $(hdrdir)/ruby/internal/intern/ruby.h
qsort.o: $(hdrdir)/ruby/internal/intern/select.h
qsort.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+qsort.o: $(hdrdir)/ruby/internal/intern/set.h
qsort.o: $(hdrdir)/ruby/internal/intern/signal.h
qsort.o: $(hdrdir)/ruby/internal/intern/sprintf.h
qsort.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -2656,6 +2673,7 @@ rb_interned_str.o: $(hdrdir)/ruby/internal/intern/re.h
rb_interned_str.o: $(hdrdir)/ruby/internal/intern/ruby.h
rb_interned_str.o: $(hdrdir)/ruby/internal/intern/select.h
rb_interned_str.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+rb_interned_str.o: $(hdrdir)/ruby/internal/intern/set.h
rb_interned_str.o: $(hdrdir)/ruby/internal/intern/signal.h
rb_interned_str.o: $(hdrdir)/ruby/internal/intern/sprintf.h
rb_interned_str.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -2816,6 +2834,7 @@ rb_str_dup.o: $(hdrdir)/ruby/internal/intern/re.h
rb_str_dup.o: $(hdrdir)/ruby/internal/intern/ruby.h
rb_str_dup.o: $(hdrdir)/ruby/internal/intern/select.h
rb_str_dup.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+rb_str_dup.o: $(hdrdir)/ruby/internal/intern/set.h
rb_str_dup.o: $(hdrdir)/ruby/internal/intern/signal.h
rb_str_dup.o: $(hdrdir)/ruby/internal/intern/sprintf.h
rb_str_dup.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -2976,6 +2995,7 @@ set_len.o: $(hdrdir)/ruby/internal/intern/re.h
set_len.o: $(hdrdir)/ruby/internal/intern/ruby.h
set_len.o: $(hdrdir)/ruby/internal/intern/select.h
set_len.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+set_len.o: $(hdrdir)/ruby/internal/intern/set.h
set_len.o: $(hdrdir)/ruby/internal/intern/signal.h
set_len.o: $(hdrdir)/ruby/internal/intern/sprintf.h
set_len.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/string/fstring.c b/ext/-test-/string/fstring.c
index 71c4b7f97e..0b5940f28c 100644
--- a/ext/-test-/string/fstring.c
+++ b/ext/-test-/string/fstring.c
@@ -12,20 +12,20 @@ VALUE
bug_s_fstring_fake_str(VALUE self)
{
static const char literal[] = "abcdefghijklmnopqrstuvwxyz";
- struct RString fake_str;
+ struct RString fake_str = {RBASIC_INIT};
return rb_str_to_interned_str(rb_setup_fake_str(&fake_str, literal, sizeof(literal) - 1, 0));
}
VALUE
bug_s_rb_enc_interned_str(VALUE self, VALUE encoding)
{
- return rb_enc_interned_str("foo", 3, NIL_P(encoding) ? NULL : RDATA(encoding)->data);
+ return rb_enc_interned_str("foo", 3, NIL_P(encoding) ? NULL : RTYPEDDATA_GET_DATA(encoding));
}
VALUE
bug_s_rb_enc_str_new(VALUE self, VALUE encoding)
{
- return rb_enc_str_new("foo", 3, NIL_P(encoding) ? NULL : RDATA(encoding)->data);
+ return rb_enc_str_new("foo", 3, NIL_P(encoding) ? NULL : RTYPEDDATA_GET_DATA(encoding));
}
void
diff --git a/ext/-test-/string/set_len.c b/ext/-test-/string/set_len.c
index 049da2cdb5..b55ef6f469 100644
--- a/ext/-test-/string/set_len.c
+++ b/ext/-test-/string/set_len.c
@@ -16,9 +16,17 @@ bug_str_append(VALUE str, VALUE addendum)
return str;
}
+static VALUE
+bug_str_resize(VALUE str, VALUE len)
+{
+ rb_str_resize(str, NUM2LONG(len));
+ return str;
+}
+
void
Init_string_set_len(VALUE klass)
{
rb_define_method(klass, "set_len", bug_str_set_len, 1);
rb_define_method(klass, "append", bug_str_append, 1);
+ rb_define_method(klass, "resize", bug_str_resize, 1);
}
diff --git a/ext/-test-/struct/depend b/ext/-test-/struct/depend
index 951dddd5dd..e2638e4cdf 100644
--- a/ext/-test-/struct/depend
+++ b/ext/-test-/struct/depend
@@ -128,6 +128,7 @@ data.o: $(hdrdir)/ruby/internal/intern/re.h
data.o: $(hdrdir)/ruby/internal/intern/ruby.h
data.o: $(hdrdir)/ruby/internal/intern/select.h
data.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+data.o: $(hdrdir)/ruby/internal/intern/set.h
data.o: $(hdrdir)/ruby/internal/intern/signal.h
data.o: $(hdrdir)/ruby/internal/intern/sprintf.h
data.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -288,6 +289,7 @@ duplicate.o: $(hdrdir)/ruby/internal/intern/re.h
duplicate.o: $(hdrdir)/ruby/internal/intern/ruby.h
duplicate.o: $(hdrdir)/ruby/internal/intern/select.h
duplicate.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+duplicate.o: $(hdrdir)/ruby/internal/intern/set.h
duplicate.o: $(hdrdir)/ruby/internal/intern/signal.h
duplicate.o: $(hdrdir)/ruby/internal/intern/sprintf.h
duplicate.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -448,6 +450,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h
init.o: $(hdrdir)/ruby/internal/intern/ruby.h
init.o: $(hdrdir)/ruby/internal/intern/select.h
init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
init.o: $(hdrdir)/ruby/internal/intern/signal.h
init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
init.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -608,6 +611,7 @@ len.o: $(hdrdir)/ruby/internal/intern/re.h
len.o: $(hdrdir)/ruby/internal/intern/ruby.h
len.o: $(hdrdir)/ruby/internal/intern/select.h
len.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+len.o: $(hdrdir)/ruby/internal/intern/set.h
len.o: $(hdrdir)/ruby/internal/intern/signal.h
len.o: $(hdrdir)/ruby/internal/intern/sprintf.h
len.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -768,6 +772,7 @@ member.o: $(hdrdir)/ruby/internal/intern/re.h
member.o: $(hdrdir)/ruby/internal/intern/ruby.h
member.o: $(hdrdir)/ruby/internal/intern/select.h
member.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+member.o: $(hdrdir)/ruby/internal/intern/set.h
member.o: $(hdrdir)/ruby/internal/intern/signal.h
member.o: $(hdrdir)/ruby/internal/intern/sprintf.h
member.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/symbol/depend b/ext/-test-/symbol/depend
index 7c76596fdf..b1d8e1aab6 100644
--- a/ext/-test-/symbol/depend
+++ b/ext/-test-/symbol/depend
@@ -128,6 +128,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h
init.o: $(hdrdir)/ruby/internal/intern/ruby.h
init.o: $(hdrdir)/ruby/internal/intern/select.h
init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
init.o: $(hdrdir)/ruby/internal/intern/signal.h
init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
init.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -288,6 +289,7 @@ type.o: $(hdrdir)/ruby/internal/intern/re.h
type.o: $(hdrdir)/ruby/internal/intern/ruby.h
type.o: $(hdrdir)/ruby/internal/intern/select.h
type.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+type.o: $(hdrdir)/ruby/internal/intern/set.h
type.o: $(hdrdir)/ruby/internal/intern/signal.h
type.o: $(hdrdir)/ruby/internal/intern/sprintf.h
type.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/thread/id/depend b/ext/-test-/thread/id/depend
new file mode 100644
index 0000000000..6b76b31ddc
--- /dev/null
+++ b/ext/-test-/thread/id/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+id.o: $(RUBY_EXTCONF_H)
+id.o: $(arch_hdrdir)/ruby/config.h
+id.o: $(hdrdir)/ruby.h
+id.o: $(hdrdir)/ruby/assert.h
+id.o: $(hdrdir)/ruby/backward.h
+id.o: $(hdrdir)/ruby/backward/2/assume.h
+id.o: $(hdrdir)/ruby/backward/2/attributes.h
+id.o: $(hdrdir)/ruby/backward/2/bool.h
+id.o: $(hdrdir)/ruby/backward/2/inttypes.h
+id.o: $(hdrdir)/ruby/backward/2/limits.h
+id.o: $(hdrdir)/ruby/backward/2/long_long.h
+id.o: $(hdrdir)/ruby/backward/2/stdalign.h
+id.o: $(hdrdir)/ruby/backward/2/stdarg.h
+id.o: $(hdrdir)/ruby/defines.h
+id.o: $(hdrdir)/ruby/intern.h
+id.o: $(hdrdir)/ruby/internal/abi.h
+id.o: $(hdrdir)/ruby/internal/anyargs.h
+id.o: $(hdrdir)/ruby/internal/arithmetic.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+id.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+id.o: $(hdrdir)/ruby/internal/assume.h
+id.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+id.o: $(hdrdir)/ruby/internal/attr/artificial.h
+id.o: $(hdrdir)/ruby/internal/attr/cold.h
+id.o: $(hdrdir)/ruby/internal/attr/const.h
+id.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+id.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+id.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+id.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+id.o: $(hdrdir)/ruby/internal/attr/error.h
+id.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+id.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+id.o: $(hdrdir)/ruby/internal/attr/format.h
+id.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+id.o: $(hdrdir)/ruby/internal/attr/noalias.h
+id.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+id.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+id.o: $(hdrdir)/ruby/internal/attr/noinline.h
+id.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+id.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+id.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+id.o: $(hdrdir)/ruby/internal/attr/pure.h
+id.o: $(hdrdir)/ruby/internal/attr/restrict.h
+id.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+id.o: $(hdrdir)/ruby/internal/attr/warning.h
+id.o: $(hdrdir)/ruby/internal/attr/weakref.h
+id.o: $(hdrdir)/ruby/internal/cast.h
+id.o: $(hdrdir)/ruby/internal/compiler_is.h
+id.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+id.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+id.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+id.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+id.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+id.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+id.o: $(hdrdir)/ruby/internal/compiler_since.h
+id.o: $(hdrdir)/ruby/internal/config.h
+id.o: $(hdrdir)/ruby/internal/constant_p.h
+id.o: $(hdrdir)/ruby/internal/core.h
+id.o: $(hdrdir)/ruby/internal/core/rarray.h
+id.o: $(hdrdir)/ruby/internal/core/rbasic.h
+id.o: $(hdrdir)/ruby/internal/core/rbignum.h
+id.o: $(hdrdir)/ruby/internal/core/rclass.h
+id.o: $(hdrdir)/ruby/internal/core/rdata.h
+id.o: $(hdrdir)/ruby/internal/core/rfile.h
+id.o: $(hdrdir)/ruby/internal/core/rhash.h
+id.o: $(hdrdir)/ruby/internal/core/robject.h
+id.o: $(hdrdir)/ruby/internal/core/rregexp.h
+id.o: $(hdrdir)/ruby/internal/core/rstring.h
+id.o: $(hdrdir)/ruby/internal/core/rstruct.h
+id.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+id.o: $(hdrdir)/ruby/internal/ctype.h
+id.o: $(hdrdir)/ruby/internal/dllexport.h
+id.o: $(hdrdir)/ruby/internal/dosish.h
+id.o: $(hdrdir)/ruby/internal/error.h
+id.o: $(hdrdir)/ruby/internal/eval.h
+id.o: $(hdrdir)/ruby/internal/event.h
+id.o: $(hdrdir)/ruby/internal/fl_type.h
+id.o: $(hdrdir)/ruby/internal/gc.h
+id.o: $(hdrdir)/ruby/internal/glob.h
+id.o: $(hdrdir)/ruby/internal/globals.h
+id.o: $(hdrdir)/ruby/internal/has/attribute.h
+id.o: $(hdrdir)/ruby/internal/has/builtin.h
+id.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+id.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+id.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+id.o: $(hdrdir)/ruby/internal/has/extension.h
+id.o: $(hdrdir)/ruby/internal/has/feature.h
+id.o: $(hdrdir)/ruby/internal/has/warning.h
+id.o: $(hdrdir)/ruby/internal/intern/array.h
+id.o: $(hdrdir)/ruby/internal/intern/bignum.h
+id.o: $(hdrdir)/ruby/internal/intern/class.h
+id.o: $(hdrdir)/ruby/internal/intern/compar.h
+id.o: $(hdrdir)/ruby/internal/intern/complex.h
+id.o: $(hdrdir)/ruby/internal/intern/cont.h
+id.o: $(hdrdir)/ruby/internal/intern/dir.h
+id.o: $(hdrdir)/ruby/internal/intern/enum.h
+id.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+id.o: $(hdrdir)/ruby/internal/intern/error.h
+id.o: $(hdrdir)/ruby/internal/intern/eval.h
+id.o: $(hdrdir)/ruby/internal/intern/file.h
+id.o: $(hdrdir)/ruby/internal/intern/hash.h
+id.o: $(hdrdir)/ruby/internal/intern/io.h
+id.o: $(hdrdir)/ruby/internal/intern/load.h
+id.o: $(hdrdir)/ruby/internal/intern/marshal.h
+id.o: $(hdrdir)/ruby/internal/intern/numeric.h
+id.o: $(hdrdir)/ruby/internal/intern/object.h
+id.o: $(hdrdir)/ruby/internal/intern/parse.h
+id.o: $(hdrdir)/ruby/internal/intern/proc.h
+id.o: $(hdrdir)/ruby/internal/intern/process.h
+id.o: $(hdrdir)/ruby/internal/intern/random.h
+id.o: $(hdrdir)/ruby/internal/intern/range.h
+id.o: $(hdrdir)/ruby/internal/intern/rational.h
+id.o: $(hdrdir)/ruby/internal/intern/re.h
+id.o: $(hdrdir)/ruby/internal/intern/ruby.h
+id.o: $(hdrdir)/ruby/internal/intern/select.h
+id.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+id.o: $(hdrdir)/ruby/internal/intern/set.h
+id.o: $(hdrdir)/ruby/internal/intern/signal.h
+id.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+id.o: $(hdrdir)/ruby/internal/intern/string.h
+id.o: $(hdrdir)/ruby/internal/intern/struct.h
+id.o: $(hdrdir)/ruby/internal/intern/thread.h
+id.o: $(hdrdir)/ruby/internal/intern/time.h
+id.o: $(hdrdir)/ruby/internal/intern/variable.h
+id.o: $(hdrdir)/ruby/internal/intern/vm.h
+id.o: $(hdrdir)/ruby/internal/interpreter.h
+id.o: $(hdrdir)/ruby/internal/iterator.h
+id.o: $(hdrdir)/ruby/internal/memory.h
+id.o: $(hdrdir)/ruby/internal/method.h
+id.o: $(hdrdir)/ruby/internal/module.h
+id.o: $(hdrdir)/ruby/internal/newobj.h
+id.o: $(hdrdir)/ruby/internal/scan_args.h
+id.o: $(hdrdir)/ruby/internal/special_consts.h
+id.o: $(hdrdir)/ruby/internal/static_assert.h
+id.o: $(hdrdir)/ruby/internal/stdalign.h
+id.o: $(hdrdir)/ruby/internal/stdbool.h
+id.o: $(hdrdir)/ruby/internal/stdckdint.h
+id.o: $(hdrdir)/ruby/internal/symbol.h
+id.o: $(hdrdir)/ruby/internal/value.h
+id.o: $(hdrdir)/ruby/internal/value_type.h
+id.o: $(hdrdir)/ruby/internal/variable.h
+id.o: $(hdrdir)/ruby/internal/warning_push.h
+id.o: $(hdrdir)/ruby/internal/xmalloc.h
+id.o: $(hdrdir)/ruby/missing.h
+id.o: $(hdrdir)/ruby/ruby.h
+id.o: $(hdrdir)/ruby/st.h
+id.o: $(hdrdir)/ruby/subst.h
+id.o: id.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/thread/id/extconf.rb b/ext/-test-/thread/id/extconf.rb
new file mode 100644
index 0000000000..a0ae0eff15
--- /dev/null
+++ b/ext/-test-/thread/id/extconf.rb
@@ -0,0 +1,3 @@
+if have_func("gettid")
+ create_makefile("-test-/thread/id")
+end
diff --git a/ext/-test-/thread/id/id.c b/ext/-test-/thread/id/id.c
new file mode 100644
index 0000000000..b46a5955e2
--- /dev/null
+++ b/ext/-test-/thread/id/id.c
@@ -0,0 +1,15 @@
+#include <ruby.h>
+
+static VALUE
+bug_gettid(VALUE self)
+{
+ pid_t tid = gettid();
+ return PIDT2NUM(tid);
+}
+
+void
+Init_id(void)
+{
+ VALUE klass = rb_define_module_under(rb_define_module("Bug"), "ThreadID");
+ rb_define_module_function(klass, "gettid", bug_gettid, 0);
+}
diff --git a/ext/-test-/thread/instrumentation/depend b/ext/-test-/thread/instrumentation/depend
index a37e4d5675..63e1c7e44f 100644
--- a/ext/-test-/thread/instrumentation/depend
+++ b/ext/-test-/thread/instrumentation/depend
@@ -128,6 +128,7 @@ instrumentation.o: $(hdrdir)/ruby/internal/intern/re.h
instrumentation.o: $(hdrdir)/ruby/internal/intern/ruby.h
instrumentation.o: $(hdrdir)/ruby/internal/intern/select.h
instrumentation.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+instrumentation.o: $(hdrdir)/ruby/internal/intern/set.h
instrumentation.o: $(hdrdir)/ruby/internal/intern/signal.h
instrumentation.o: $(hdrdir)/ruby/internal/intern/sprintf.h
instrumentation.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/thread/instrumentation/instrumentation.c b/ext/-test-/thread/instrumentation/instrumentation.c
index d81bc0f2a7..25e2902a78 100644
--- a/ext/-test-/thread/instrumentation/instrumentation.c
+++ b/ext/-test-/thread/instrumentation/instrumentation.c
@@ -6,7 +6,6 @@
# define RB_THREAD_LOCAL_SPECIFIER
#endif
-static VALUE last_thread = Qnil;
static VALUE timeline_value = Qnil;
struct thread_event {
@@ -211,9 +210,8 @@ Init_instrumentation(void)
VALUE mBug = rb_define_module("Bug");
VALUE klass = rb_define_module_under(mBug, "ThreadInstrumentation");
rb_global_variable(&timeline_value);
- timeline_value = TypedData_Wrap_Struct(0, &event_timeline_type, 0);
+ timeline_value = TypedData_Wrap_Struct(0, &event_timeline_type, (void *)1);
- rb_global_variable(&last_thread);
rb_define_singleton_method(klass, "register_callback", thread_register_callback, 1);
rb_define_singleton_method(klass, "unregister_callback", thread_unregister_callback, 0);
rb_define_singleton_method(klass, "register_and_unregister_callbacks", thread_register_and_unregister_callback, 0);
diff --git a/ext/-test-/thread/lock_native_thread/depend b/ext/-test-/thread/lock_native_thread/depend
new file mode 100644
index 0000000000..a32843e531
--- /dev/null
+++ b/ext/-test-/thread/lock_native_thread/depend
@@ -0,0 +1,163 @@
+# AUTOGENERATED DEPENDENCIES START
+lock_native_thread.o: $(RUBY_EXTCONF_H)
+lock_native_thread.o: $(arch_hdrdir)/ruby/config.h
+lock_native_thread.o: $(hdrdir)/ruby/assert.h
+lock_native_thread.o: $(hdrdir)/ruby/backward.h
+lock_native_thread.o: $(hdrdir)/ruby/backward/2/assume.h
+lock_native_thread.o: $(hdrdir)/ruby/backward/2/attributes.h
+lock_native_thread.o: $(hdrdir)/ruby/backward/2/bool.h
+lock_native_thread.o: $(hdrdir)/ruby/backward/2/inttypes.h
+lock_native_thread.o: $(hdrdir)/ruby/backward/2/limits.h
+lock_native_thread.o: $(hdrdir)/ruby/backward/2/long_long.h
+lock_native_thread.o: $(hdrdir)/ruby/backward/2/stdalign.h
+lock_native_thread.o: $(hdrdir)/ruby/backward/2/stdarg.h
+lock_native_thread.o: $(hdrdir)/ruby/defines.h
+lock_native_thread.o: $(hdrdir)/ruby/intern.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/abi.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/anyargs.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/char.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/double.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/int.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/long.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/short.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/assume.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/artificial.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/cold.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/const.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/constexpr.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/deprecated.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/error.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/forceinline.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/format.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/noalias.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/noexcept.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/noinline.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/nonnull.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/noreturn.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/pure.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/restrict.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/warning.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/attr/weakref.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/cast.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_since.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/config.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/constant_p.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core/rarray.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core/rbasic.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core/rbignum.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core/rclass.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core/rdata.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core/rfile.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core/rhash.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core/robject.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core/rregexp.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core/rstring.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core/rstruct.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/ctype.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/dllexport.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/dosish.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/error.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/eval.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/event.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/fl_type.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/gc.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/glob.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/globals.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/has/attribute.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/has/builtin.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/has/c_attribute.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/has/extension.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/has/feature.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/has/warning.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/array.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/bignum.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/class.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/compar.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/complex.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/cont.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/dir.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/enum.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/enumerator.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/error.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/eval.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/file.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/hash.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/io.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/load.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/marshal.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/numeric.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/object.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/parse.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/proc.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/process.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/random.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/range.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/rational.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/re.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/ruby.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/select.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/set.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/signal.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/sprintf.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/string.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/struct.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/thread.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/time.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/variable.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/intern/vm.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/interpreter.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/iterator.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/memory.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/method.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/module.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/newobj.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/scan_args.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/special_consts.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/static_assert.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/stdalign.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/stdbool.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/stdckdint.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/symbol.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/value.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/value_type.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/variable.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/warning_push.h
+lock_native_thread.o: $(hdrdir)/ruby/internal/xmalloc.h
+lock_native_thread.o: $(hdrdir)/ruby/missing.h
+lock_native_thread.o: $(hdrdir)/ruby/ruby.h
+lock_native_thread.o: $(hdrdir)/ruby/st.h
+lock_native_thread.o: $(hdrdir)/ruby/subst.h
+lock_native_thread.o: $(hdrdir)/ruby/thread.h
+lock_native_thread.o: lock_native_thread.c
+# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/thread_fd/depend b/ext/-test-/thread_fd/depend
deleted file mode 100644
index 0fda9f6dbf..0000000000
--- a/ext/-test-/thread_fd/depend
+++ /dev/null
@@ -1,161 +0,0 @@
-# AUTOGENERATED DEPENDENCIES START
-thread_fd.o: $(RUBY_EXTCONF_H)
-thread_fd.o: $(arch_hdrdir)/ruby/config.h
-thread_fd.o: $(hdrdir)/ruby/assert.h
-thread_fd.o: $(hdrdir)/ruby/backward.h
-thread_fd.o: $(hdrdir)/ruby/backward/2/assume.h
-thread_fd.o: $(hdrdir)/ruby/backward/2/attributes.h
-thread_fd.o: $(hdrdir)/ruby/backward/2/bool.h
-thread_fd.o: $(hdrdir)/ruby/backward/2/inttypes.h
-thread_fd.o: $(hdrdir)/ruby/backward/2/limits.h
-thread_fd.o: $(hdrdir)/ruby/backward/2/long_long.h
-thread_fd.o: $(hdrdir)/ruby/backward/2/stdalign.h
-thread_fd.o: $(hdrdir)/ruby/backward/2/stdarg.h
-thread_fd.o: $(hdrdir)/ruby/defines.h
-thread_fd.o: $(hdrdir)/ruby/intern.h
-thread_fd.o: $(hdrdir)/ruby/internal/abi.h
-thread_fd.o: $(hdrdir)/ruby/internal/anyargs.h
-thread_fd.o: $(hdrdir)/ruby/internal/arithmetic.h
-thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/char.h
-thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/double.h
-thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
-thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
-thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/int.h
-thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
-thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/long.h
-thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
-thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
-thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
-thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
-thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/short.h
-thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
-thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
-thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
-thread_fd.o: $(hdrdir)/ruby/internal/assume.h
-thread_fd.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
-thread_fd.o: $(hdrdir)/ruby/internal/attr/artificial.h
-thread_fd.o: $(hdrdir)/ruby/internal/attr/cold.h
-thread_fd.o: $(hdrdir)/ruby/internal/attr/const.h
-thread_fd.o: $(hdrdir)/ruby/internal/attr/constexpr.h
-thread_fd.o: $(hdrdir)/ruby/internal/attr/deprecated.h
-thread_fd.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
-thread_fd.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
-thread_fd.o: $(hdrdir)/ruby/internal/attr/error.h
-thread_fd.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
-thread_fd.o: $(hdrdir)/ruby/internal/attr/forceinline.h
-thread_fd.o: $(hdrdir)/ruby/internal/attr/format.h
-thread_fd.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
-thread_fd.o: $(hdrdir)/ruby/internal/attr/noalias.h
-thread_fd.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
-thread_fd.o: $(hdrdir)/ruby/internal/attr/noexcept.h
-thread_fd.o: $(hdrdir)/ruby/internal/attr/noinline.h
-thread_fd.o: $(hdrdir)/ruby/internal/attr/nonnull.h
-thread_fd.o: $(hdrdir)/ruby/internal/attr/noreturn.h
-thread_fd.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
-thread_fd.o: $(hdrdir)/ruby/internal/attr/pure.h
-thread_fd.o: $(hdrdir)/ruby/internal/attr/restrict.h
-thread_fd.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
-thread_fd.o: $(hdrdir)/ruby/internal/attr/warning.h
-thread_fd.o: $(hdrdir)/ruby/internal/attr/weakref.h
-thread_fd.o: $(hdrdir)/ruby/internal/cast.h
-thread_fd.o: $(hdrdir)/ruby/internal/compiler_is.h
-thread_fd.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
-thread_fd.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
-thread_fd.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
-thread_fd.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
-thread_fd.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
-thread_fd.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
-thread_fd.o: $(hdrdir)/ruby/internal/compiler_since.h
-thread_fd.o: $(hdrdir)/ruby/internal/config.h
-thread_fd.o: $(hdrdir)/ruby/internal/constant_p.h
-thread_fd.o: $(hdrdir)/ruby/internal/core.h
-thread_fd.o: $(hdrdir)/ruby/internal/core/rarray.h
-thread_fd.o: $(hdrdir)/ruby/internal/core/rbasic.h
-thread_fd.o: $(hdrdir)/ruby/internal/core/rbignum.h
-thread_fd.o: $(hdrdir)/ruby/internal/core/rclass.h
-thread_fd.o: $(hdrdir)/ruby/internal/core/rdata.h
-thread_fd.o: $(hdrdir)/ruby/internal/core/rfile.h
-thread_fd.o: $(hdrdir)/ruby/internal/core/rhash.h
-thread_fd.o: $(hdrdir)/ruby/internal/core/robject.h
-thread_fd.o: $(hdrdir)/ruby/internal/core/rregexp.h
-thread_fd.o: $(hdrdir)/ruby/internal/core/rstring.h
-thread_fd.o: $(hdrdir)/ruby/internal/core/rstruct.h
-thread_fd.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
-thread_fd.o: $(hdrdir)/ruby/internal/ctype.h
-thread_fd.o: $(hdrdir)/ruby/internal/dllexport.h
-thread_fd.o: $(hdrdir)/ruby/internal/dosish.h
-thread_fd.o: $(hdrdir)/ruby/internal/error.h
-thread_fd.o: $(hdrdir)/ruby/internal/eval.h
-thread_fd.o: $(hdrdir)/ruby/internal/event.h
-thread_fd.o: $(hdrdir)/ruby/internal/fl_type.h
-thread_fd.o: $(hdrdir)/ruby/internal/gc.h
-thread_fd.o: $(hdrdir)/ruby/internal/glob.h
-thread_fd.o: $(hdrdir)/ruby/internal/globals.h
-thread_fd.o: $(hdrdir)/ruby/internal/has/attribute.h
-thread_fd.o: $(hdrdir)/ruby/internal/has/builtin.h
-thread_fd.o: $(hdrdir)/ruby/internal/has/c_attribute.h
-thread_fd.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
-thread_fd.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
-thread_fd.o: $(hdrdir)/ruby/internal/has/extension.h
-thread_fd.o: $(hdrdir)/ruby/internal/has/feature.h
-thread_fd.o: $(hdrdir)/ruby/internal/has/warning.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/array.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/bignum.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/class.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/compar.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/complex.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/cont.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/dir.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/enum.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/enumerator.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/error.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/eval.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/file.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/hash.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/io.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/load.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/marshal.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/numeric.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/object.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/parse.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/proc.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/process.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/random.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/range.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/rational.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/re.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/ruby.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/select.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/signal.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/sprintf.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/string.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/struct.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/thread.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/time.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/variable.h
-thread_fd.o: $(hdrdir)/ruby/internal/intern/vm.h
-thread_fd.o: $(hdrdir)/ruby/internal/interpreter.h
-thread_fd.o: $(hdrdir)/ruby/internal/iterator.h
-thread_fd.o: $(hdrdir)/ruby/internal/memory.h
-thread_fd.o: $(hdrdir)/ruby/internal/method.h
-thread_fd.o: $(hdrdir)/ruby/internal/module.h
-thread_fd.o: $(hdrdir)/ruby/internal/newobj.h
-thread_fd.o: $(hdrdir)/ruby/internal/scan_args.h
-thread_fd.o: $(hdrdir)/ruby/internal/special_consts.h
-thread_fd.o: $(hdrdir)/ruby/internal/static_assert.h
-thread_fd.o: $(hdrdir)/ruby/internal/stdalign.h
-thread_fd.o: $(hdrdir)/ruby/internal/stdbool.h
-thread_fd.o: $(hdrdir)/ruby/internal/stdckdint.h
-thread_fd.o: $(hdrdir)/ruby/internal/symbol.h
-thread_fd.o: $(hdrdir)/ruby/internal/value.h
-thread_fd.o: $(hdrdir)/ruby/internal/value_type.h
-thread_fd.o: $(hdrdir)/ruby/internal/variable.h
-thread_fd.o: $(hdrdir)/ruby/internal/warning_push.h
-thread_fd.o: $(hdrdir)/ruby/internal/xmalloc.h
-thread_fd.o: $(hdrdir)/ruby/missing.h
-thread_fd.o: $(hdrdir)/ruby/ruby.h
-thread_fd.o: $(hdrdir)/ruby/st.h
-thread_fd.o: $(hdrdir)/ruby/subst.h
-thread_fd.o: thread_fd.c
-# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/-test-/thread_fd/extconf.rb b/ext/-test-/thread_fd/extconf.rb
deleted file mode 100644
index a8bbe9d169..0000000000
--- a/ext/-test-/thread_fd/extconf.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-# frozen_string_literal: true
-create_makefile('-test-/thread_fd')
diff --git a/ext/-test-/thread_fd/thread_fd.c b/ext/-test-/thread_fd/thread_fd.c
deleted file mode 100644
index 042b799dc8..0000000000
--- a/ext/-test-/thread_fd/thread_fd.c
+++ /dev/null
@@ -1,30 +0,0 @@
-#include "ruby/ruby.h"
-
-static VALUE
-thread_fd_close(VALUE ign, VALUE fd)
-{
- rb_thread_fd_close(NUM2INT(fd));
- return Qnil;
-}
-
-static VALUE
-thread_fd_wait(VALUE ign, VALUE fd)
-{
- int ret = rb_thread_wait_fd(NUM2INT(fd));
- return INT2NUM(ret);
-}
-
-static VALUE
-thread_fd_writable(VALUE ign, VALUE fd)
-{
- int ret = rb_thread_fd_writable(NUM2INT(fd));
- return INT2NUM(ret);
-}
-
-void
-Init_thread_fd(void)
-{
- rb_define_singleton_method(rb_cIO, "thread_fd_close", thread_fd_close, 1);
- rb_define_singleton_method(rb_cIO, "thread_fd_wait", thread_fd_wait, 1);
- rb_define_singleton_method(rb_cIO, "thread_fd_writable", thread_fd_writable, 1);
-}
diff --git a/ext/-test-/time/depend b/ext/-test-/time/depend
index 5ed791bcc5..e5b05f3113 100644
--- a/ext/-test-/time/depend
+++ b/ext/-test-/time/depend
@@ -128,6 +128,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h
init.o: $(hdrdir)/ruby/internal/intern/ruby.h
init.o: $(hdrdir)/ruby/internal/intern/select.h
init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
init.o: $(hdrdir)/ruby/internal/intern/signal.h
init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
init.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -289,6 +290,7 @@ leap_second.o: $(hdrdir)/ruby/internal/intern/re.h
leap_second.o: $(hdrdir)/ruby/internal/intern/ruby.h
leap_second.o: $(hdrdir)/ruby/internal/intern/select.h
leap_second.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+leap_second.o: $(hdrdir)/ruby/internal/intern/set.h
leap_second.o: $(hdrdir)/ruby/internal/intern/signal.h
leap_second.o: $(hdrdir)/ruby/internal/intern/sprintf.h
leap_second.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -453,6 +455,7 @@ new.o: $(hdrdir)/ruby/internal/intern/re.h
new.o: $(hdrdir)/ruby/internal/intern/ruby.h
new.o: $(hdrdir)/ruby/internal/intern/select.h
new.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+new.o: $(hdrdir)/ruby/internal/intern/set.h
new.o: $(hdrdir)/ruby/internal/intern/signal.h
new.o: $(hdrdir)/ruby/internal/intern/sprintf.h
new.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/time/leap_second.c b/ext/-test-/time/leap_second.c
deleted file mode 100644
index ee7011fa97..0000000000
--- a/ext/-test-/time/leap_second.c
+++ /dev/null
@@ -1,15 +0,0 @@
-#include "ruby.h"
-#include "internal/time.h"
-
-static VALUE
-bug_time_s_reset_leap_second_info(VALUE klass)
-{
- ruby_reset_leap_second_info();
- return Qnil;
-}
-
-void
-Init_time_leap_second(VALUE klass)
-{
- rb_define_singleton_method(klass, "reset_leap_second_info", bug_time_s_reset_leap_second_info, 0);
-}
diff --git a/ext/-test-/tracepoint/depend b/ext/-test-/tracepoint/depend
index 133663b3bd..014ba83b16 100644
--- a/ext/-test-/tracepoint/depend
+++ b/ext/-test-/tracepoint/depend
@@ -128,6 +128,7 @@ gc_hook.o: $(hdrdir)/ruby/internal/intern/re.h
gc_hook.o: $(hdrdir)/ruby/internal/intern/ruby.h
gc_hook.o: $(hdrdir)/ruby/internal/intern/select.h
gc_hook.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+gc_hook.o: $(hdrdir)/ruby/internal/intern/set.h
gc_hook.o: $(hdrdir)/ruby/internal/intern/signal.h
gc_hook.o: $(hdrdir)/ruby/internal/intern/sprintf.h
gc_hook.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -288,6 +289,7 @@ tracepoint.o: $(hdrdir)/ruby/internal/intern/re.h
tracepoint.o: $(hdrdir)/ruby/internal/intern/ruby.h
tracepoint.o: $(hdrdir)/ruby/internal/intern/select.h
tracepoint.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+tracepoint.o: $(hdrdir)/ruby/internal/intern/set.h
tracepoint.o: $(hdrdir)/ruby/internal/intern/signal.h
tracepoint.o: $(hdrdir)/ruby/internal/intern/sprintf.h
tracepoint.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/tracepoint/gc_hook.c b/ext/-test-/tracepoint/gc_hook.c
index 54c06c54a5..525be6da63 100644
--- a/ext/-test-/tracepoint/gc_hook.c
+++ b/ext/-test-/tracepoint/gc_hook.c
@@ -2,6 +2,7 @@
#include "ruby/debug.h"
static int invoking; /* TODO: should not be global variable */
+extern VALUE tp_mBug;
static VALUE
invoke_proc_ensure(VALUE _)
@@ -17,9 +18,9 @@ invoke_proc_begin(VALUE proc)
}
static void
-invoke_proc(void *data)
+invoke_proc(void *ivar_name)
{
- VALUE proc = (VALUE)data;
+ VALUE proc = rb_ivar_get(tp_mBug, rb_intern(ivar_name));
invoking += 1;
rb_ensure(invoke_proc_begin, proc, invoke_proc_ensure, 0);
}
@@ -40,16 +41,16 @@ gc_start_end_i(VALUE tpval, void *data)
}
static VALUE
-set_gc_hook(VALUE module, VALUE proc, rb_event_flag_t event, const char *tp_str, const char *proc_str)
+set_gc_hook(VALUE proc, rb_event_flag_t event, const char *tp_str, const char *proc_str)
{
VALUE tpval;
ID tp_key = rb_intern(tp_str);
/* disable previous keys */
- if (rb_ivar_defined(module, tp_key) != 0 &&
- RTEST(tpval = rb_ivar_get(module, tp_key))) {
+ if (rb_ivar_defined(tp_mBug, tp_key) != 0 &&
+ RTEST(tpval = rb_ivar_get(tp_mBug, tp_key))) {
rb_tracepoint_disable(tpval);
- rb_ivar_set(module, tp_key, Qnil);
+ rb_ivar_set(tp_mBug, tp_key, Qnil);
}
if (RTEST(proc)) {
@@ -57,8 +58,9 @@ set_gc_hook(VALUE module, VALUE proc, rb_event_flag_t event, const char *tp_str,
rb_raise(rb_eTypeError, "trace_func needs to be Proc");
}
- tpval = rb_tracepoint_new(0, event, gc_start_end_i, (void *)proc);
- rb_ivar_set(module, tp_key, tpval);
+ rb_ivar_set(tp_mBug, rb_intern(proc_str), proc);
+ tpval = rb_tracepoint_new(0, event, gc_start_end_i, (void *)proc_str);
+ rb_ivar_set(tp_mBug, tp_key, tpval);
rb_tracepoint_enable(tpval);
}
@@ -66,16 +68,16 @@ set_gc_hook(VALUE module, VALUE proc, rb_event_flag_t event, const char *tp_str,
}
static VALUE
-set_after_gc_start(VALUE module, VALUE proc)
+set_after_gc_start(VALUE _self, VALUE proc)
{
- return set_gc_hook(module, proc, RUBY_INTERNAL_EVENT_GC_START,
+ return set_gc_hook(proc, RUBY_INTERNAL_EVENT_GC_START,
"__set_after_gc_start_tpval__", "__set_after_gc_start_proc__");
}
static VALUE
-start_after_gc_exit(VALUE module, VALUE proc)
+start_after_gc_exit(VALUE _self, VALUE proc)
{
- return set_gc_hook(module, proc, RUBY_INTERNAL_EVENT_GC_EXIT,
+ return set_gc_hook(proc, RUBY_INTERNAL_EVENT_GC_EXIT,
"__set_after_gc_exit_tpval__", "__set_after_gc_exit_proc__");
}
diff --git a/ext/-test-/tracepoint/tracepoint.c b/ext/-test-/tracepoint/tracepoint.c
index 2826cc038c..001d9513b2 100644
--- a/ext/-test-/tracepoint/tracepoint.c
+++ b/ext/-test-/tracepoint/tracepoint.c
@@ -1,6 +1,8 @@
#include "ruby/ruby.h"
#include "ruby/debug.h"
+VALUE tp_mBug;
+
struct tracepoint_track {
size_t newobj_count;
size_t free_count;
@@ -89,8 +91,8 @@ void Init_gc_hook(VALUE);
void
Init_tracepoint(void)
{
- VALUE mBug = rb_define_module("Bug");
- Init_gc_hook(mBug);
- rb_define_module_function(mBug, "tracepoint_track_objspace_events", tracepoint_track_objspace_events, 0);
- rb_define_module_function(mBug, "tracepoint_specify_normal_and_internal_events", tracepoint_specify_normal_and_internal_events, 0);
+ tp_mBug = rb_define_module("Bug"); // GC root
+ Init_gc_hook(tp_mBug);
+ rb_define_module_function(tp_mBug, "tracepoint_track_objspace_events", tracepoint_track_objspace_events, 0);
+ rb_define_module_function(tp_mBug, "tracepoint_specify_normal_and_internal_events", tracepoint_specify_normal_and_internal_events, 0);
}
diff --git a/ext/-test-/typeddata/depend b/ext/-test-/typeddata/depend
index 6c0847c82d..b9b4915eee 100644
--- a/ext/-test-/typeddata/depend
+++ b/ext/-test-/typeddata/depend
@@ -128,6 +128,7 @@ typeddata.o: $(hdrdir)/ruby/internal/intern/re.h
typeddata.o: $(hdrdir)/ruby/internal/intern/ruby.h
typeddata.o: $(hdrdir)/ruby/internal/intern/select.h
typeddata.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+typeddata.o: $(hdrdir)/ruby/internal/intern/set.h
typeddata.o: $(hdrdir)/ruby/internal/intern/signal.h
typeddata.o: $(hdrdir)/ruby/internal/intern/sprintf.h
typeddata.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/vm/depend b/ext/-test-/vm/depend
index 422b40a32d..9313f2ee36 100644
--- a/ext/-test-/vm/depend
+++ b/ext/-test-/vm/depend
@@ -127,6 +127,7 @@ at_exit.o: $(hdrdir)/ruby/internal/intern/re.h
at_exit.o: $(hdrdir)/ruby/internal/intern/ruby.h
at_exit.o: $(hdrdir)/ruby/internal/intern/select.h
at_exit.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+at_exit.o: $(hdrdir)/ruby/internal/intern/set.h
at_exit.o: $(hdrdir)/ruby/internal/intern/signal.h
at_exit.o: $(hdrdir)/ruby/internal/intern/sprintf.h
at_exit.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/wait/depend b/ext/-test-/wait/depend
index 7997a16709..f793d84831 100644
--- a/ext/-test-/wait/depend
+++ b/ext/-test-/wait/depend
@@ -137,6 +137,7 @@ wait.o: $(hdrdir)/ruby/internal/intern/re.h
wait.o: $(hdrdir)/ruby/internal/intern/ruby.h
wait.o: $(hdrdir)/ruby/internal/intern/select.h
wait.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+wait.o: $(hdrdir)/ruby/internal/intern/set.h
wait.o: $(hdrdir)/ruby/internal/intern/signal.h
wait.o: $(hdrdir)/ruby/internal/intern/sprintf.h
wait.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/-test-/win32/dln/extconf.rb b/ext/-test-/win32/dln/extconf.rb
index d72b6a868c..bea52cfec3 100644
--- a/ext/-test-/win32/dln/extconf.rb
+++ b/ext/-test-/win32/dln/extconf.rb
@@ -7,6 +7,7 @@ if $mingw or $mswin
testdll = "dlntest.dll"
$cleanfiles << testdll
$cleanfiles << "dlntest.#{$LIBEXT}"
+ $cleanfiles << "libdlntest.#{$OBJEXT}"
config_string('cleanobjs') {|t| $cleanfiles.concat(t.gsub(/\$\*/, 'dlntest').split)}
create_makefile("-test-/win32/dln") do |m|
diff --git a/ext/.document b/ext/.document
index 0efd511a61..374abe6580 100644
--- a/ext/.document
+++ b/ext/.document
@@ -76,8 +76,6 @@ openssl/ossl_x509name.c
openssl/ossl_x509req.c
openssl/ossl_x509revoked.c
openssl/ossl_x509store.c
-pathname/lib
-pathname/pathname.c
psych/lib
psych/psych.c
psych/psych_emitter.c
@@ -92,6 +90,7 @@ readline/readline.c
ripper/lib
socket
stringio/stringio.c
+strscan/lib
strscan/strscan.c
syslog/syslog.c
syslog/lib
diff --git a/ext/cgi/escape/depend b/ext/cgi/escape/depend
index 746b47246a..05b59bfdea 100644
--- a/ext/cgi/escape/depend
+++ b/ext/cgi/escape/depend
@@ -138,6 +138,7 @@ escape.o: $(hdrdir)/ruby/internal/intern/re.h
escape.o: $(hdrdir)/ruby/internal/intern/ruby.h
escape.o: $(hdrdir)/ruby/internal/intern/select.h
escape.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+escape.o: $(hdrdir)/ruby/internal/intern/set.h
escape.o: $(hdrdir)/ruby/internal/intern/signal.h
escape.o: $(hdrdir)/ruby/internal/intern/sprintf.h
escape.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/cgi/escape/escape.c b/ext/cgi/escape/escape.c
index 495ad83aa3..4773186603 100644
--- a/ext/cgi/escape/escape.c
+++ b/ext/cgi/escape/escape.c
@@ -8,7 +8,7 @@ RUBY_EXTERN const signed char ruby_digit36_to_number_table[];
#define upper_hexdigits (ruby_hexdigits+16)
#define char_to_number(c) ruby_digit36_to_number_table[(unsigned char)(c)]
-static VALUE rb_cCGI, rb_mUtil, rb_mEscape;
+static VALUE rb_cCGI, rb_mEscape, rb_mEscapeExt;
static ID id_accept_charset;
#define HTML_ESCAPE_MAX_LEN 6
@@ -45,6 +45,7 @@ escaped_length(VALUE str)
static VALUE
optimized_escape_html(VALUE str)
{
+ VALUE escaped;
VALUE vbuf;
char *buf = ALLOCV_N(char, vbuf, escaped_length(str));
const char *cstr = RSTRING_PTR(str);
@@ -63,7 +64,6 @@ optimized_escape_html(VALUE str)
}
}
- VALUE escaped;
if (RSTRING_LEN(str) < (dest - buf)) {
escaped = rb_str_new(buf, dest - buf);
preserve_original_state(str, escaped);
@@ -471,17 +471,17 @@ Init_escape(void)
void
InitVM_escape(void)
{
- rb_cCGI = rb_define_class("CGI", rb_cObject);
- rb_mEscape = rb_define_module_under(rb_cCGI, "Escape");
- rb_mUtil = rb_define_module_under(rb_cCGI, "Util");
- rb_define_method(rb_mEscape, "escapeHTML", cgiesc_escape_html, 1);
- rb_define_method(rb_mEscape, "unescapeHTML", cgiesc_unescape_html, 1);
- rb_define_method(rb_mEscape, "escapeURIComponent", cgiesc_escape_uri_component, 1);
- rb_define_alias(rb_mEscape, "escape_uri_component", "escapeURIComponent");
- rb_define_method(rb_mEscape, "unescapeURIComponent", cgiesc_unescape_uri_component, -1);
- rb_define_alias(rb_mEscape, "unescape_uri_component", "unescapeURIComponent");
- rb_define_method(rb_mEscape, "escape", cgiesc_escape, 1);
- rb_define_method(rb_mEscape, "unescape", cgiesc_unescape, -1);
- rb_prepend_module(rb_mUtil, rb_mEscape);
- rb_extend_object(rb_cCGI, rb_mEscape);
+ rb_cCGI = rb_define_class("CGI", rb_cObject);
+ rb_mEscapeExt = rb_define_module_under(rb_cCGI, "EscapeExt");
+ rb_mEscape = rb_define_module_under(rb_cCGI, "Escape");
+ rb_define_method(rb_mEscapeExt, "escapeHTML", cgiesc_escape_html, 1);
+ rb_define_method(rb_mEscapeExt, "unescapeHTML", cgiesc_unescape_html, 1);
+ rb_define_method(rb_mEscapeExt, "escapeURIComponent", cgiesc_escape_uri_component, 1);
+ rb_define_alias(rb_mEscapeExt, "escape_uri_component", "escapeURIComponent");
+ rb_define_method(rb_mEscapeExt, "unescapeURIComponent", cgiesc_unescape_uri_component, -1);
+ rb_define_alias(rb_mEscapeExt, "unescape_uri_component", "unescapeURIComponent");
+ rb_define_method(rb_mEscapeExt, "escape", cgiesc_escape, 1);
+ rb_define_method(rb_mEscapeExt, "unescape", cgiesc_unescape, -1);
+ rb_prepend_module(rb_mEscape, rb_mEscapeExt);
+ rb_extend_object(rb_cCGI, rb_mEscapeExt);
}
diff --git a/ext/continuation/depend b/ext/continuation/depend
index b40e52e29b..b395d3d4d7 100644
--- a/ext/continuation/depend
+++ b/ext/continuation/depend
@@ -127,6 +127,7 @@ continuation.o: $(hdrdir)/ruby/internal/intern/re.h
continuation.o: $(hdrdir)/ruby/internal/intern/ruby.h
continuation.o: $(hdrdir)/ruby/internal/intern/select.h
continuation.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+continuation.o: $(hdrdir)/ruby/internal/intern/set.h
continuation.o: $(hdrdir)/ruby/internal/intern/signal.h
continuation.o: $(hdrdir)/ruby/internal/intern/sprintf.h
continuation.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/coverage/coverage.c b/ext/coverage/coverage.c
index 9fc93bb58d..1f82193567 100644
--- a/ext/coverage/coverage.c
+++ b/ext/coverage/coverage.c
@@ -243,8 +243,8 @@ method_coverage_i(void *vstart, void *vend, size_t stride, void *data)
VALUE ncoverages = *(VALUE*)data, v;
for (v = (VALUE)vstart; v != (VALUE)vend; v += stride) {
- void *poisoned = asan_poisoned_object_p(v);
- asan_unpoison_object(v, false);
+ void *poisoned = rb_asan_poisoned_object_p(v);
+ rb_asan_unpoison_object(v, false);
if (RB_TYPE_P(v, T_IMEMO) && imemo_type(v) == imemo_ment) {
const rb_method_entry_t *me = (rb_method_entry_t *) v;
@@ -287,7 +287,7 @@ method_coverage_i(void *vstart, void *vend, size_t stride, void *data)
}
if (poisoned) {
- asan_poison_object(v);
+ rb_asan_poison_object(v);
}
}
return 0;
@@ -337,7 +337,7 @@ coverage_peek_result_i(st_data_t key, st_data_t val, st_data_t h)
* Coverage.peek_result => hash
*
* Returns a hash that contains filename as key and coverage array as value.
- * This is the same as `Coverage.result(stop: false, clear: false)`.
+ * This is the same as <tt>Coverage.result(stop: false, clear: false)</tt>.
*
* {
* "file.rb" => [1, 2, nil],
@@ -352,7 +352,6 @@ rb_coverage_peek_result(VALUE klass)
if (!RTEST(coverages)) {
rb_raise(rb_eRuntimeError, "coverage measurement is not enabled");
}
- OBJ_WB_UNPROTECT(coverages);
rb_hash_foreach(coverages, coverage_peek_result_i, ncoverages);
diff --git a/ext/coverage/depend b/ext/coverage/depend
index 1be81c5e9a..fb7f9a95af 100644
--- a/ext/coverage/depend
+++ b/ext/coverage/depend
@@ -140,6 +140,7 @@ coverage.o: $(hdrdir)/ruby/internal/intern/re.h
coverage.o: $(hdrdir)/ruby/internal/intern/ruby.h
coverage.o: $(hdrdir)/ruby/internal/intern/select.h
coverage.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+coverage.o: $(hdrdir)/ruby/internal/intern/set.h
coverage.o: $(hdrdir)/ruby/internal/intern/signal.h
coverage.o: $(hdrdir)/ruby/internal/intern/sprintf.h
coverage.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -182,12 +183,14 @@ coverage.o: $(top_srcdir)/id_table.h
coverage.o: $(top_srcdir)/internal.h
coverage.o: $(top_srcdir)/internal/array.h
coverage.o: $(top_srcdir)/internal/basic_operators.h
+coverage.o: $(top_srcdir)/internal/box.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/set_table.h
coverage.o: $(top_srcdir)/internal/static_assert.h
coverage.o: $(top_srcdir)/internal/thread.h
coverage.o: $(top_srcdir)/internal/variable.h
diff --git a/ext/coverage/lib/coverage.rb b/ext/coverage/lib/coverage.rb
index f1923ef366..4bd20e22cb 100644
--- a/ext/coverage/lib/coverage.rb
+++ b/ext/coverage/lib/coverage.rb
@@ -1,6 +1,11 @@
require "coverage.so"
module Coverage
+ # call-seq:
+ # line_stub(file) -> array
+ #
+ # A simple helper function that creates the "stub" of line coverage
+ # from a given source code.
def self.line_stub(file)
lines = File.foreach(file).map { nil }
iseqs = [RubyVM::InstructionSequence.compile_file(file)]
diff --git a/ext/date/date.gemspec b/ext/date/date.gemspec
index bd42b1518a..cb439bd0a5 100644
--- a/ext/date/date.gemspec
+++ b/ext/date/date.gemspec
@@ -7,8 +7,8 @@ end
Gem::Specification.new do |s|
s.name = "date"
s.version = version
- s.summary = "A subclass of Object includes Comparable module for handling dates."
- s.description = "A subclass of Object includes Comparable module for handling dates."
+ s.summary = "The official date library for Ruby."
+ s.description = "The official date library for Ruby."
if Gem::Platform === s.platform and s.platform =~ 'java' or RUBY_ENGINE == 'jruby'
s.platform = 'java'
@@ -17,7 +17,7 @@ Gem::Specification.new do |s|
s.require_path = %w{lib}
s.files = [
- "README.md",
+ "README.md", "COPYING", "BSDL",
"lib/date.rb", "ext/date/date_core.c", "ext/date/date_parse.c", "ext/date/date_strftime.c",
"ext/date/date_strptime.c", "ext/date/date_tmx.h", "ext/date/extconf.rb", "ext/date/prereq.mk",
"ext/date/zonetab.h", "ext/date/zonetab.list"
diff --git a/ext/date/date_core.c b/ext/date/date_core.c
index 0fcefd671b..9755fb819e 100644
--- a/ext/date/date_core.c
+++ b/ext/date/date_core.c
@@ -57,7 +57,7 @@ static VALUE sym_hour, sym_min, sym_sec, sym_sec_fraction, sym_zone;
#define f_add3(x,y,z) f_add(f_add(x, y), z)
#define f_sub3(x,y,z) f_sub(f_sub(x, y), z)
-#define f_frozen_ary(...) rb_obj_freeze(rb_ary_new3(__VA_ARGS__))
+#define f_frozen_ary(...) rb_ary_freeze(rb_ary_new3(__VA_ARGS__))
static VALUE date_initialize(int argc, VALUE *argv, VALUE self);
static VALUE datetime_initialize(int argc, VALUE *argv, VALUE self);
@@ -248,6 +248,11 @@ f_negative_p(VALUE x)
#define date_sg_t double
#endif
+#define JULIAN_EPOCH_DATE "-4712-01-01"
+#define JULIAN_EPOCH_DATETIME JULIAN_EPOCH_DATE "T00:00:00+00:00"
+#define JULIAN_EPOCH_DATETIME_RFC3339 "Mon, 1 Jan -4712 00:00:00 +0000"
+#define JULIAN_EPOCH_DATETIME_HTTPDATE "Mon, 01 Jan -4712 00:00:00 GMT"
+
/* A set of nth, jd, df and sf denote ajd + 1/2. Each ajd begin at
* noon of GMT (assume equal to UTC). However, this begins at
* midnight.
@@ -447,11 +452,43 @@ do {\
static int c_valid_civil_p(int, int, int, double,
int *, int *, int *, int *);
+/* Check if using pure Gregorian calendar (sg == -Infinity) */
+#define c_gregorian_only_p(sg) (isinf(sg) && (sg) < 0)
+
+/*
+ * Fast path macros for pure Gregorian calendar.
+ * Sets *rjd to the JD value, *ns to 1 (new style), and returns.
+ */
+#define GREGORIAN_JD_FAST_PATH_RET(sg, jd_expr, rjd, ns) \
+ if (c_gregorian_only_p(sg)) { \
+ *(rjd) = (jd_expr); \
+ *(ns) = 1; \
+ return 1; \
+ }
+
+#define GREGORIAN_JD_FAST_PATH(sg, jd_expr, rjd, ns) \
+ if (c_gregorian_only_p(sg)) { \
+ *(rjd) = (jd_expr); \
+ *(ns) = 1; \
+ return; \
+ }
+
+/* Forward declarations for Neri-Schneider optimized functions */
+static int c_gregorian_civil_to_jd(int y, int m, int d);
+static void c_gregorian_jd_to_civil(int jd, int *ry, int *rm, int *rd);
+static int c_gregorian_fdoy(int y);
+static int c_gregorian_ldoy(int y);
+static int c_gregorian_ldom_jd(int y, int m);
+static int ns_jd_in_range(int jd);
+
static int
c_find_fdoy(int y, double sg, int *rjd, int *ns)
{
int d, rm, rd;
+ GREGORIAN_JD_FAST_PATH_RET(sg, c_gregorian_fdoy(y), rjd, ns);
+
+ /* Keep existing loop for Julian/reform period */
for (d = 1; d < 31; d++)
if (c_valid_civil_p(y, 1, d, sg, &rm, &rd, rjd, ns))
return 1;
@@ -463,6 +500,9 @@ c_find_ldoy(int y, double sg, int *rjd, int *ns)
{
int i, rm, rd;
+ GREGORIAN_JD_FAST_PATH_RET(sg, c_gregorian_ldoy(y), rjd, ns);
+
+ /* Keep existing loop for Julian/reform period */
for (i = 0; i < 30; i++)
if (c_valid_civil_p(y, 12, 31 - i, sg, &rm, &rd, rjd, ns))
return 1;
@@ -488,6 +528,9 @@ c_find_ldom(int y, int m, double sg, int *rjd, int *ns)
{
int i, rm, rd;
+ GREGORIAN_JD_FAST_PATH_RET(sg, c_gregorian_ldom_jd(y, m), rjd, ns);
+
+ /* Keep existing loop for Julian/reform period */
for (i = 0; i < 30; i++)
if (c_valid_civil_p(y, m, 31 - i, sg, &rm, &rd, rjd, ns))
return 1;
@@ -497,55 +540,69 @@ c_find_ldom(int y, int m, double sg, int *rjd, int *ns)
static void
c_civil_to_jd(int y, int m, int d, double sg, int *rjd, int *ns)
{
- double a, b, jd;
+ int jd;
+
+ GREGORIAN_JD_FAST_PATH(sg, c_gregorian_civil_to_jd(y, m, d), rjd, ns);
+
+ /* Calculate Gregorian JD using optimized algorithm */
+ jd = c_gregorian_civil_to_jd(y, m, d);
- if (m <= 2) {
- y -= 1;
- m += 12;
- }
- a = floor(y / 100.0);
- b = 2 - a + floor(a / 4.0);
- jd = floor(365.25 * (y + 4716)) +
- floor(30.6001 * (m + 1)) +
- d + b - 1524;
if (jd < sg) {
- jd -= b;
+ /* Before Gregorian switchover - use Julian calendar */
+ int y2 = y, m2 = m;
+ if (m2 <= 2) {
+ y2 -= 1;
+ m2 += 12;
+ }
+ jd = (int)(floor(365.25 * (y2 + 4716)) +
+ floor(30.6001 * (m2 + 1)) +
+ d - 1524);
*ns = 0;
}
- else
+ else {
*ns = 1;
+ }
- *rjd = (int)jd;
+ *rjd = jd;
}
static void
c_jd_to_civil(int jd, double sg, int *ry, int *rm, int *rdom)
{
- double x, a, b, c, d, e, y, m, dom;
-
- if (jd < sg)
- a = jd;
- else {
- x = floor((jd - 1867216.25) / 36524.25);
- a = jd + 1 + x - floor(x / 4.0);
- }
- b = a + 1524;
- c = floor((b - 122.1) / 365.25);
- d = floor(365.25 * c);
- e = floor((b - d) / 30.6001);
- dom = b - d - floor(30.6001 * e);
- if (e <= 13) {
- m = e - 1;
- y = c - 4716;
- }
- else {
- m = e - 13;
- y = c - 4715;
+ /* Fast path: pure Gregorian or date after switchover, within safe range */
+ if ((c_gregorian_only_p(sg) || jd >= sg) && ns_jd_in_range(jd)) {
+ c_gregorian_jd_to_civil(jd, ry, rm, rdom);
+ return;
}
- *ry = (int)y;
- *rm = (int)m;
- *rdom = (int)dom;
+ /* Original algorithm for Julian calendar or extreme dates */
+ {
+ double x, a, b, c, d, e, y, m, dom;
+
+ if (jd < sg)
+ a = jd;
+ else {
+ x = floor((jd - 1867216.25) / 36524.25);
+ a = jd + 1 + x - floor(x / 4.0);
+ }
+ b = a + 1524;
+ c = floor((b - 122.1) / 365.25);
+ d = floor(365.25 * c);
+ e = floor((b - d) / 30.6001);
+ dom = b - d - floor(30.6001 * e);
+ if (e <= 13) {
+ m = e - 1;
+ y = c - 4716;
+ }
+ else {
+ m = e - 13;
+ y = c - 4715;
+ }
+
+ *ry = (int)y;
+ *rm = (int)m;
+ *rdom = (int)dom;
+ }
}
static void
@@ -720,6 +777,147 @@ c_gregorian_last_day_of_month(int y, int m)
return monthtab[c_gregorian_leap_p(y) ? 1 : 0][m];
}
+/*
+ * Neri-Schneider algorithm for optimized Gregorian date conversion.
+ * Reference: Neri & Schneider, "Euclidean Affine Functions and Applications
+ * to Calendar Algorithms", Software: Practice and Experience, 2023.
+ * https://arxiv.org/abs/2102.06959
+ *
+ * This algorithm provides ~2-3x speedup over traditional floating-point
+ * implementations by using pure integer arithmetic with multiplication
+ * and bit-shifts instead of expensive division operations.
+ */
+
+/* JDN of March 1, Year 0 in proleptic Gregorian calendar */
+#define NS_EPOCH 1721120
+
+/* Days in a 4-year cycle (3 normal years + 1 leap year) */
+#define NS_DAYS_IN_4_YEARS 1461
+
+/* Days in a 400-year Gregorian cycle (97 leap years in 400 years) */
+#define NS_DAYS_IN_400_YEARS 146097
+
+/* Years per century */
+#define NS_YEARS_PER_CENTURY 100
+
+/*
+ * Multiplier for extracting year within century using fixed-point arithmetic.
+ * This is ceil(2^32 / NS_DAYS_IN_4_YEARS) for the Euclidean affine function.
+ */
+#define NS_YEAR_MULTIPLIER 2939745
+
+/*
+ * Coefficients for month calculation from day-of-year.
+ * Maps day-of-year to month using: month = (NS_MONTH_COEFF * doy + NS_MONTH_OFFSET) >> 16
+ */
+#define NS_MONTH_COEFF 2141
+#define NS_MONTH_OFFSET 197913
+
+/*
+ * Coefficients for civil date to JDN month contribution.
+ * Maps month to accumulated days: days = (NS_CIVIL_MONTH_COEFF * m - NS_CIVIL_MONTH_OFFSET) / 32
+ */
+#define NS_CIVIL_MONTH_COEFF 979
+#define NS_CIVIL_MONTH_OFFSET 2919
+#define NS_CIVIL_MONTH_DIVISOR 32
+
+/* Days from March 1 to December 31 (for Jan/Feb year adjustment) */
+#define NS_DAYS_BEFORE_NEW_YEAR 306
+
+/*
+ * Safe bounds for Neri-Schneider algorithm to avoid integer overflow.
+ * These correspond to approximately years -1,000,000 to +1,000,000.
+ */
+#define NS_JD_MIN -364000000
+#define NS_JD_MAX 538000000
+
+inline static int
+ns_jd_in_range(int jd)
+{
+ return jd >= NS_JD_MIN && jd <= NS_JD_MAX;
+}
+
+/* Optimized: Gregorian date -> Julian Day Number */
+static int
+c_gregorian_civil_to_jd(int y, int m, int d)
+{
+ /* Shift epoch to March 1 of year 0 (Jan/Feb belong to previous year) */
+ int j = (m < 3) ? 1 : 0;
+ int y0 = y - j;
+ int m0 = j ? m + 12 : m;
+ int d0 = d - 1;
+
+ /* Calculate year contribution with leap year correction */
+ int q1 = DIV(y0, NS_YEARS_PER_CENTURY);
+ int yc = DIV(NS_DAYS_IN_4_YEARS * y0, 4) - q1 + DIV(q1, 4);
+
+ /* Calculate month contribution using integer arithmetic */
+ int mc = (NS_CIVIL_MONTH_COEFF * m0 - NS_CIVIL_MONTH_OFFSET) / NS_CIVIL_MONTH_DIVISOR;
+
+ /* Combine and add epoch offset to get JDN */
+ return yc + mc + d0 + NS_EPOCH;
+}
+
+/* Optimized: Julian Day Number -> Gregorian date */
+static void
+c_gregorian_jd_to_civil(int jd, int *ry, int *rm, int *rd)
+{
+ int r0, n1, q1, r1, n2, q2, r2, n3, q3, r3, y0, j;
+ uint64_t u2;
+
+ /* Convert JDN to rata die (March 1, Year 0 epoch) */
+ r0 = jd - NS_EPOCH;
+
+ /* Extract century and day within 400-year cycle */
+ /* Use Euclidean (floor) division for negative values */
+ n1 = 4 * r0 + 3;
+ q1 = DIV(n1, NS_DAYS_IN_400_YEARS);
+ r1 = MOD(n1, NS_DAYS_IN_400_YEARS) / 4;
+
+ /* Calculate year within century and day of year */
+ n2 = 4 * r1 + 3;
+ /* Use 64-bit arithmetic to avoid overflow */
+ u2 = (uint64_t)NS_YEAR_MULTIPLIER * (uint64_t)n2;
+ q2 = (int)(u2 >> 32);
+ r2 = (int)((uint32_t)u2 / NS_YEAR_MULTIPLIER / 4);
+
+ /* Calculate month and day using integer arithmetic */
+ n3 = NS_MONTH_COEFF * r2 + NS_MONTH_OFFSET;
+ q3 = n3 >> 16;
+ r3 = (n3 & 0xFFFF) / NS_MONTH_COEFF;
+
+ /* Combine century and year */
+ y0 = NS_YEARS_PER_CENTURY * q1 + q2;
+
+ /* Adjust for January/February (shift from fiscal year) */
+ j = (r2 >= NS_DAYS_BEFORE_NEW_YEAR) ? 1 : 0;
+
+ *ry = y0 + j;
+ *rm = j ? q3 - 12 : q3;
+ *rd = r3 + 1;
+}
+
+/* O(1) first day of year for Gregorian calendar */
+inline static int
+c_gregorian_fdoy(int y)
+{
+ return c_gregorian_civil_to_jd(y, 1, 1);
+}
+
+/* O(1) last day of year for Gregorian calendar */
+inline static int
+c_gregorian_ldoy(int y)
+{
+ return c_gregorian_civil_to_jd(y, 12, 31);
+}
+
+/* O(1) last day of month (JDN) for Gregorian calendar */
+inline static int
+c_gregorian_ldom_jd(int y, int m)
+{
+ return c_gregorian_civil_to_jd(y, m, c_gregorian_last_day_of_month(y, m));
+}
+
static int
c_valid_julian_p(int y, int m, int d, int *rm, int *rd)
{
@@ -1594,7 +1792,7 @@ m_ajd(union DateData *x)
if (simple_dat_p(x)) {
r = m_real_jd(x);
- if (FIXNUM_P(r) && FIX2LONG(r) <= (FIXNUM_MAX / 2)) {
+ if (FIXNUM_P(r) && FIX2LONG(r) <= (FIXNUM_MAX / 2) && FIX2LONG(r) >= (FIXNUM_MIN + 1) / 2) {
long ir = FIX2LONG(r);
ir = ir * 2 - 1;
return rb_rational_new2(LONG2FIX(ir), INT2FIX(2));
@@ -2493,7 +2691,7 @@ date_s__valid_jd_p(int argc, VALUE *argv, VALUE klass)
*
* Date.valid_jd?(2451944) # => true
*
- * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
*
* Related: Date.jd.
*/
@@ -2587,7 +2785,7 @@ date_s__valid_civil_p(int argc, VALUE *argv, VALUE klass)
* Date.valid_date?(2001, 2, 29) # => false
* Date.valid_date?(2001, 2, -1) # => true
*
- * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
*
* Related: Date.jd, Date.new.
*/
@@ -2675,7 +2873,7 @@ date_s__valid_ordinal_p(int argc, VALUE *argv, VALUE klass)
* Date.valid_ordinal?(2001, 34) # => true
* Date.valid_ordinal?(2001, 366) # => false
*
- * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
*
* Related: Date.jd, Date.ordinal.
*/
@@ -2765,7 +2963,7 @@ date_s__valid_commercial_p(int argc, VALUE *argv, VALUE klass)
*
* See Date.commercial.
*
- * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
*
* Related: Date.jd, Date.commercial.
*/
@@ -3345,7 +3543,7 @@ static VALUE d_lite_plus(VALUE, VALUE);
*
* Date.jd(Date::ITALY - 1).julian? # => true
*
- * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
*
* Related: Date.new.
*/
@@ -3410,7 +3608,7 @@ date_s_jd(int argc, VALUE *argv, VALUE klass)
*
* Raises an exception if +yday+ is zero or out of range.
*
- * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
*
* Related: Date.jd, Date.new.
*/
@@ -3487,7 +3685,7 @@ date_s_civil(int argc, VALUE *argv, VALUE klass)
* where +n+ is the number of days in the month;
* when the argument is negative, counts backward from the end of the month.
*
- * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
*
* Related: Date.jd.
*/
@@ -3593,7 +3791,7 @@ date_initialize(int argc, VALUE *argv, VALUE self)
* Date.commercial(2020, 1, 1).to_s # => "2019-12-30"
Date.commercial(2020, 1, 7).to_s # => "2020-01-05"
*
- * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
*
* Related: Date.jd, Date.new, Date.ordinal.
*/
@@ -3778,7 +3976,7 @@ static void set_sg(union DateData *, double);
*
* Date.today.to_s # => "2022-07-06"
*
- * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
*
*/
static VALUE
@@ -3873,7 +4071,6 @@ static VALUE
rt_complete_frags(VALUE klass, VALUE hash)
{
static VALUE tab = Qnil;
- int g;
long e;
VALUE k, a, d;
@@ -3970,9 +4167,13 @@ rt_complete_frags(VALUE klass, VALUE hash)
rb_gc_register_mark_object(tab);
}
+ k = a = Qnil;
+
{
- long i, eno = 0, idx = 0;
+ long i, eno = 0;
+ VALUE t = Qnil;
+ e = 0;
for (i = 0; i < RARRAY_LEN(tab); i++) {
VALUE x, a;
@@ -3987,23 +4188,20 @@ rt_complete_frags(VALUE klass, VALUE hash)
n++;
if (n > eno) {
eno = n;
- idx = i;
+ t = x;
}
}
}
- if (eno == 0)
- g = 0;
- else {
- g = 1;
- k = RARRAY_AREF(RARRAY_AREF(tab, idx), 0);
- a = RARRAY_AREF(RARRAY_AREF(tab, idx), 1);
- e = eno;
+ if (eno > 0) {
+ k = RARRAY_AREF(t, 0);
+ a = RARRAY_AREF(t, 1);
}
+ e = eno;
}
d = Qnil;
- if (g && !NIL_P(k) && (RARRAY_LEN(a) - e)) {
+ if (!NIL_P(k) && (RARRAY_LEN(a) > e)) {
if (k == sym("ordinal")) {
if (NIL_P(ref_hash("year"))) {
if (NIL_P(d))
@@ -4090,7 +4288,7 @@ rt_complete_frags(VALUE klass, VALUE hash)
}
}
- if (g && k == sym("time")) {
+ if (k == sym("time")) {
if (f_le_p(klass, cDateTime)) {
if (NIL_P(d))
d = date_s_today(0, (VALUE *)0, cDate);
@@ -4378,7 +4576,7 @@ date_s__strptime_internal(int argc, VALUE *argv, VALUE klass,
* Date._strptime('2001-02-03', '%Y-%m-%d') # => {:year=>2001, :mon=>2, :mday=>3}
*
* For other formats, see
- * {Formats for Dates and Times}[rdoc-ref:strftime_formatting.rdoc].
+ * {Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc].
* (Unlike Date.strftime, does not support flags and width.)
*
* See also {strptime(3)}[https://man7.org/linux/man-pages/man3/strptime.3.html].
@@ -4407,10 +4605,10 @@ date_s__strptime(int argc, VALUE *argv, VALUE klass)
* Date.strptime('sat3feb01', '%a%d%b%y') # => #<Date: 2001-02-03>
*
* For other formats, see
- * {Formats for Dates and Times}[rdoc-ref:strftime_formatting.rdoc].
+ * {Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc].
* (Unlike Date.strftime, does not support flags and width.)
*
- * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
*
* See also {strptime(3)}[https://man7.org/linux/man-pages/man3/strptime.3.html].
*
@@ -4425,7 +4623,7 @@ date_s_strptime(int argc, VALUE *argv, VALUE klass)
switch (argc) {
case 0:
- str = rb_str_new2("-4712-01-01");
+ str = rb_str_new2(JULIAN_EPOCH_DATE);
case 1:
fmt = rb_str_new2("%F");
case 2:
@@ -4459,11 +4657,10 @@ get_limit(VALUE opt)
#define rb_category_warn(category, fmt) rb_warn(fmt)
#endif
-static void
+static VALUE
check_limit(VALUE str, VALUE opt)
{
size_t slen, limit;
- if (NIL_P(str)) return;
StringValue(str);
slen = RSTRING_LEN(str);
limit = get_limit(opt);
@@ -4471,6 +4668,7 @@ check_limit(VALUE str, VALUE opt)
rb_raise(rb_eArgError,
"string length (%"PRI_SIZE_PREFIX"u) exceeds the limit %"PRI_SIZE_PREFIX"u", slen, limit);
}
+ return str;
}
static VALUE
@@ -4478,10 +4676,8 @@ date_s__parse_internal(int argc, VALUE *argv, VALUE klass)
{
VALUE vstr, vcomp, hash, opt;
- rb_scan_args(argc, argv, "11:", &vstr, &vcomp, &opt);
- if (!NIL_P(opt)) argc--;
- check_limit(vstr, opt);
- StringValue(vstr);
+ argc = rb_scan_args(argc, argv, "11:", &vstr, &vcomp, &opt);
+ vstr = check_limit(vstr, opt);
if (!rb_enc_str_asciicompat_p(vstr))
rb_raise(rb_eArgError,
"string should have ASCII compatible encoding");
@@ -4501,7 +4697,7 @@ date_s__parse_internal(int argc, VALUE *argv, VALUE klass)
* This method recognizes many forms in +string+,
* but it is not a validator.
* For formats, see
- * {"Specialized Format Strings" in Formats for Dates and Times}[rdoc-ref:strftime_formatting.rdoc@Specialized+Format+Strings]
+ * {"Specialized Format Strings" in Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc@Specialized+Format+Strings]
*
* If +string+ does not specify a valid date,
* the result is unpredictable;
@@ -4536,7 +4732,7 @@ date_s__parse(int argc, VALUE *argv, VALUE klass)
* This method recognizes many forms in +string+,
* but it is not a validator.
* For formats, see
- * {"Specialized Format Strings" in Formats for Dates and Times}[rdoc-ref:strftime_formatting.rdoc@Specialized+Format+Strings]
+ * {"Specialized Format Strings" in Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc@Specialized+Format+Strings]
* If +string+ does not specify a valid date,
* the result is unpredictable;
* consider using Date._strptime instead.
@@ -4556,7 +4752,7 @@ date_s__parse(int argc, VALUE *argv, VALUE klass)
*
* See:
*
- * - Argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * - Argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
* - Argument {limit}[rdoc-ref:Date@Argument+limit].
*
* Related: Date._parse (returns a hash).
@@ -4566,12 +4762,11 @@ date_s_parse(int argc, VALUE *argv, VALUE klass)
{
VALUE str, comp, sg, opt;
- rb_scan_args(argc, argv, "03:", &str, &comp, &sg, &opt);
- if (!NIL_P(opt)) argc--;
+ argc = rb_scan_args(argc, argv, "03:", &str, &comp, &sg, &opt);
switch (argc) {
case 0:
- str = rb_str_new2("-4712-01-01");
+ str = rb_str_new2(JULIAN_EPOCH_DATE);
case 1:
comp = Qtrue;
case 2:
@@ -4601,7 +4796,7 @@ VALUE date__jisx0301(VALUE);
* Date._iso8601(string, limit: 128) -> hash
*
* Returns a hash of values parsed from +string+, which should contain
- * an {ISO 8601 formatted date}[rdoc-ref:strftime_formatting.rdoc@ISO+8601+Format+Specifications]:
+ * an {ISO 8601 formatted date}[rdoc-ref:language/strftime_formatting.rdoc@ISO+8601+Format+Specifications]:
*
* d = Date.new(2001, 2, 3)
* s = d.iso8601 # => "2001-02-03"
@@ -4617,7 +4812,7 @@ date_s__iso8601(int argc, VALUE *argv, VALUE klass)
VALUE str, opt;
rb_scan_args(argc, argv, "1:", &str, &opt);
- check_limit(str, opt);
+ if (!NIL_P(str)) str = check_limit(str, opt);
return date__iso8601(str);
}
@@ -4628,7 +4823,7 @@ date_s__iso8601(int argc, VALUE *argv, VALUE klass)
*
* Returns a new \Date object with values parsed from +string+,
* which should contain
- * an {ISO 8601 formatted date}[rdoc-ref:strftime_formatting.rdoc@ISO+8601+Format+Specifications]:
+ * an {ISO 8601 formatted date}[rdoc-ref:language/strftime_formatting.rdoc@ISO+8601+Format+Specifications]:
*
* d = Date.new(2001, 2, 3)
* s = d.iso8601 # => "2001-02-03"
@@ -4636,7 +4831,7 @@ date_s__iso8601(int argc, VALUE *argv, VALUE klass)
*
* See:
*
- * - Argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * - Argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
* - Argument {limit}[rdoc-ref:Date@Argument+limit].
*
* Related: Date._iso8601 (returns a hash).
@@ -4646,12 +4841,11 @@ date_s_iso8601(int argc, VALUE *argv, VALUE klass)
{
VALUE str, sg, opt;
- rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
- if (!NIL_P(opt)) argc--;
+ argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
switch (argc) {
case 0:
- str = rb_str_new2("-4712-01-01");
+ str = rb_str_new2(JULIAN_EPOCH_DATE);
case 1:
sg = INT2FIX(DEFAULT_SG);
}
@@ -4671,7 +4865,7 @@ date_s_iso8601(int argc, VALUE *argv, VALUE klass)
* Date._rfc3339(string, limit: 128) -> hash
*
* Returns a hash of values parsed from +string+, which should be a valid
- * {RFC 3339 format}[rdoc-ref:strftime_formatting.rdoc@RFC+3339+Format]:
+ * {RFC 3339 format}[rdoc-ref:language/strftime_formatting.rdoc@RFC+3339+Format]:
*
* d = Date.new(2001, 2, 3)
* s = d.rfc3339 # => "2001-02-03T00:00:00+00:00"
@@ -4688,7 +4882,7 @@ date_s__rfc3339(int argc, VALUE *argv, VALUE klass)
VALUE str, opt;
rb_scan_args(argc, argv, "1:", &str, &opt);
- check_limit(str, opt);
+ if (!NIL_P(str)) str = check_limit(str, opt);
return date__rfc3339(str);
}
@@ -4699,7 +4893,7 @@ date_s__rfc3339(int argc, VALUE *argv, VALUE klass)
*
* Returns a new \Date object with values parsed from +string+,
* which should be a valid
- * {RFC 3339 format}[rdoc-ref:strftime_formatting.rdoc@RFC+3339+Format]:
+ * {RFC 3339 format}[rdoc-ref:language/strftime_formatting.rdoc@RFC+3339+Format]:
*
* d = Date.new(2001, 2, 3)
* s = d.rfc3339 # => "2001-02-03T00:00:00+00:00"
@@ -4707,7 +4901,7 @@ date_s__rfc3339(int argc, VALUE *argv, VALUE klass)
*
* See:
*
- * - Argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * - Argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
* - Argument {limit}[rdoc-ref:Date@Argument+limit].
*
* Related: Date._rfc3339 (returns a hash).
@@ -4717,12 +4911,11 @@ date_s_rfc3339(int argc, VALUE *argv, VALUE klass)
{
VALUE str, sg, opt;
- rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
- if (!NIL_P(opt)) argc--;
+ argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
switch (argc) {
case 0:
- str = rb_str_new2("-4712-01-01T00:00:00+00:00");
+ str = rb_str_new2(JULIAN_EPOCH_DATETIME);
case 1:
sg = INT2FIX(DEFAULT_SG);
}
@@ -4758,7 +4951,7 @@ date_s__xmlschema(int argc, VALUE *argv, VALUE klass)
VALUE str, opt;
rb_scan_args(argc, argv, "1:", &str, &opt);
- check_limit(str, opt);
+ if (!NIL_P(str)) str = check_limit(str, opt);
return date__xmlschema(str);
}
@@ -4776,7 +4969,7 @@ date_s__xmlschema(int argc, VALUE *argv, VALUE klass)
*
* See:
*
- * - Argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * - Argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
* - Argument {limit}[rdoc-ref:Date@Argument+limit].
*
* Related: Date._xmlschema (returns a hash).
@@ -4786,12 +4979,11 @@ date_s_xmlschema(int argc, VALUE *argv, VALUE klass)
{
VALUE str, sg, opt;
- rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
- if (!NIL_P(opt)) argc--;
+ argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
switch (argc) {
case 0:
- str = rb_str_new2("-4712-01-01");
+ str = rb_str_new2(JULIAN_EPOCH_DATE);
case 1:
sg = INT2FIX(DEFAULT_SG);
}
@@ -4811,7 +5003,7 @@ date_s_xmlschema(int argc, VALUE *argv, VALUE klass)
* Date._rfc2822(string, limit: 128) -> hash
*
* Returns a hash of values parsed from +string+, which should be a valid
- * {RFC 2822 date format}[rdoc-ref:strftime_formatting.rdoc@RFC+2822+Format]:
+ * {RFC 2822 date format}[rdoc-ref:language/strftime_formatting.rdoc@RFC+2822+Format]:
*
* d = Date.new(2001, 2, 3)
* s = d.rfc2822 # => "Sat, 3 Feb 2001 00:00:00 +0000"
@@ -4828,7 +5020,7 @@ date_s__rfc2822(int argc, VALUE *argv, VALUE klass)
VALUE str, opt;
rb_scan_args(argc, argv, "1:", &str, &opt);
- check_limit(str, opt);
+ if (!NIL_P(str)) str = check_limit(str, opt);
return date__rfc2822(str);
}
@@ -4839,7 +5031,7 @@ date_s__rfc2822(int argc, VALUE *argv, VALUE klass)
*
* Returns a new \Date object with values parsed from +string+,
* which should be a valid
- * {RFC 2822 date format}[rdoc-ref:strftime_formatting.rdoc@RFC+2822+Format]:
+ * {RFC 2822 date format}[rdoc-ref:language/strftime_formatting.rdoc@RFC+2822+Format]:
*
* d = Date.new(2001, 2, 3)
* s = d.rfc2822 # => "Sat, 3 Feb 2001 00:00:00 +0000"
@@ -4847,7 +5039,7 @@ date_s__rfc2822(int argc, VALUE *argv, VALUE klass)
*
* See:
*
- * - Argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * - Argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
* - Argument {limit}[rdoc-ref:Date@Argument+limit].
*
* Related: Date._rfc2822 (returns a hash).
@@ -4857,11 +5049,11 @@ date_s_rfc2822(int argc, VALUE *argv, VALUE klass)
{
VALUE str, sg, opt;
- rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+ argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
switch (argc) {
case 0:
- str = rb_str_new2("Mon, 1 Jan -4712 00:00:00 +0000");
+ str = rb_str_new2(JULIAN_EPOCH_DATETIME_RFC3339);
case 1:
sg = INT2FIX(DEFAULT_SG);
}
@@ -4881,7 +5073,7 @@ date_s_rfc2822(int argc, VALUE *argv, VALUE klass)
* Date._httpdate(string, limit: 128) -> hash
*
* Returns a hash of values parsed from +string+, which should be a valid
- * {HTTP date format}[rdoc-ref:strftime_formatting.rdoc@HTTP+Format]:
+ * {HTTP date format}[rdoc-ref:language/strftime_formatting.rdoc@HTTP+Format]:
*
* d = Date.new(2001, 2, 3)
* s = d.httpdate # => "Sat, 03 Feb 2001 00:00:00 GMT"
@@ -4896,7 +5088,7 @@ date_s__httpdate(int argc, VALUE *argv, VALUE klass)
VALUE str, opt;
rb_scan_args(argc, argv, "1:", &str, &opt);
- check_limit(str, opt);
+ if (!NIL_P(str)) str = check_limit(str, opt);
return date__httpdate(str);
}
@@ -4907,7 +5099,7 @@ date_s__httpdate(int argc, VALUE *argv, VALUE klass)
*
* Returns a new \Date object with values parsed from +string+,
* which should be a valid
- * {HTTP date format}[rdoc-ref:strftime_formatting.rdoc@HTTP+Format]:
+ * {HTTP date format}[rdoc-ref:language/strftime_formatting.rdoc@HTTP+Format]:
*
* d = Date.new(2001, 2, 3)
s = d.httpdate # => "Sat, 03 Feb 2001 00:00:00 GMT"
@@ -4915,7 +5107,7 @@ date_s__httpdate(int argc, VALUE *argv, VALUE klass)
*
* See:
*
- * - Argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * - Argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
* - Argument {limit}[rdoc-ref:Date@Argument+limit].
*
* Related: Date._httpdate (returns a hash).
@@ -4925,11 +5117,11 @@ date_s_httpdate(int argc, VALUE *argv, VALUE klass)
{
VALUE str, sg, opt;
- rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
+ argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
switch (argc) {
case 0:
- str = rb_str_new2("Mon, 01 Jan -4712 00:00:00 GMT");
+ str = rb_str_new2(JULIAN_EPOCH_DATETIME_HTTPDATE);
case 1:
sg = INT2FIX(DEFAULT_SG);
}
@@ -4949,7 +5141,7 @@ date_s_httpdate(int argc, VALUE *argv, VALUE klass)
* Date._jisx0301(string, limit: 128) -> hash
*
* Returns a hash of values parsed from +string+, which should be a valid
- * {JIS X 0301 date format}[rdoc-ref:strftime_formatting.rdoc@JIS+X+0301+Format]:
+ * {JIS X 0301 date format}[rdoc-ref:language/strftime_formatting.rdoc@JIS+X+0301+Format]:
*
* d = Date.new(2001, 2, 3)
* s = d.jisx0301 # => "H13.02.03"
@@ -4965,7 +5157,7 @@ date_s__jisx0301(int argc, VALUE *argv, VALUE klass)
VALUE str, opt;
rb_scan_args(argc, argv, "1:", &str, &opt);
- check_limit(str, opt);
+ if (!NIL_P(str)) str = check_limit(str, opt);
return date__jisx0301(str);
}
@@ -4975,7 +5167,7 @@ date_s__jisx0301(int argc, VALUE *argv, VALUE klass)
* Date.jisx0301(string = '-4712-01-01', start = Date::ITALY, limit: 128) -> date
*
* Returns a new \Date object with values parsed from +string+,
- * which should be a valid {JIS X 0301 format}[rdoc-ref:strftime_formatting.rdoc@JIS+X+0301+Format]:
+ * which should be a valid {JIS X 0301 format}[rdoc-ref:language/strftime_formatting.rdoc@JIS+X+0301+Format]:
*
* d = Date.new(2001, 2, 3)
* s = d.jisx0301 # => "H13.02.03"
@@ -4987,7 +5179,7 @@ date_s__jisx0301(int argc, VALUE *argv, VALUE klass)
*
* See:
*
- * - Argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * - Argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
* - Argument {limit}[rdoc-ref:Date@Argument+limit].
*
* Related: Date._jisx0301 (returns a hash).
@@ -4997,12 +5189,11 @@ date_s_jisx0301(int argc, VALUE *argv, VALUE klass)
{
VALUE str, sg, opt;
- rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
- if (!NIL_P(opt)) argc--;
+ argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
switch (argc) {
case 0:
- str = rb_str_new2("-4712-01-01");
+ str = rb_str_new2(JULIAN_EPOCH_DATE);
case 1:
sg = INT2FIX(DEFAULT_SG);
}
@@ -5746,7 +5937,7 @@ d_lite_leap_p(VALUE self)
* Date.new(2001, 2, 3, Date::GREGORIAN).start # => -Infinity
* Date.new(2001, 2, 3, Date::JULIAN).start # => Infinity
*
- * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
*
*/
static VALUE
@@ -5821,7 +6012,7 @@ dup_obj_with_new_start(VALUE obj, double sg)
* d1 = d0.new_start(Date::JULIAN)
* d1.julian? # => true
*
- * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start].
+ * See argument {start}[rdoc-ref:language/calendars.rdoc@Argument+start].
*
*/
static VALUE
@@ -6326,9 +6517,11 @@ minus_dd(VALUE self, VALUE other)
* call-seq:
* d - other -> date or rational
*
- * Returns the difference between the two dates if the other is a date
- * object. If the other is a numeric value, returns a date object
- * pointing +other+ days before self. If the other is a fractional number,
+ * If the other is a date object, returns a Rational
+ * whose value is the difference between the two dates in days.
+ * If the other is a numeric value, returns a date object
+ * pointing +other+ days before self.
+ * If the other is a fractional number,
* assumes its precision is at most nanosecond.
*
* Date.new(2001,2,3) - 1 #=> #<Date: 2001-02-02 ...>
@@ -6935,13 +7128,24 @@ d_lite_eql_p(VALUE self, VALUE other)
static VALUE
d_lite_hash(VALUE self)
{
- st_index_t v, h[4];
+ st_index_t v, h[5];
+ VALUE nth;
get_d1(self);
- h[0] = m_nth(dat);
- h[1] = m_jd(dat);
- h[2] = m_df(dat);
- h[3] = m_sf(dat);
+ nth = m_nth(dat);
+
+ if (FIXNUM_P(nth)) {
+ h[0] = 0;
+ h[1] = (st_index_t)nth;
+ } else {
+ h[0] = 1;
+ h[1] = (st_index_t)FIX2LONG(rb_hash(nth));
+ }
+
+ h[2] = m_jd(dat);
+ h[3] = m_df(dat);
+ h[4] = m_sf(dat);
+
v = rb_memhash(h, sizeof(h));
return ST2FIX(v);
}
@@ -6956,7 +7160,7 @@ static VALUE strftimev(const char *, VALUE,
* to_s -> string
*
* Returns a string representation of the date in +self+
- * in {ISO 8601 extended date format}[rdoc-ref:strftime_formatting.rdoc@ISO+8601+Format+Specifications]
+ * in {ISO 8601 extended date format}[rdoc-ref:language/strftime_formatting.rdoc@ISO+8601+Format+Specifications]
* (<tt>'%Y-%m-%d'</tt>):
*
* Date.new(2001, 2, 3).to_s # => "2001-02-03"
@@ -7237,7 +7441,7 @@ date_strftime_internal(int argc, VALUE *argv, VALUE self,
* Date.new(2001, 2, 3).strftime # => "2001-02-03"
*
* For other formats, see
- * {Formats for Dates and Times}[rdoc-ref:strftime_formatting.rdoc].
+ * {Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc].
*
*/
static VALUE
@@ -7269,7 +7473,7 @@ strftimev(const char *fmt, VALUE self,
* asctime -> string
*
* Equivalent to #strftime with argument <tt>'%a %b %e %T %Y'</tt>
- * (or its {shorthand form}[rdoc-ref:strftime_formatting.rdoc@Shorthand+Conversion+Specifiers]
+ * (or its {shorthand form}[rdoc-ref:language/strftime_formatting.rdoc@Shorthand+Conversion+Specifiers]
* <tt>'%c'</tt>):
*
* Date.new(2001, 2, 3).asctime # => "Sat Feb 3 00:00:00 2001"
@@ -7288,7 +7492,7 @@ d_lite_asctime(VALUE self)
* iso8601 -> string
*
* Equivalent to #strftime with argument <tt>'%Y-%m-%d'</tt>
- * (or its {shorthand form}[rdoc-ref:strftime_formatting.rdoc@Shorthand+Conversion+Specifiers]
+ * (or its {shorthand form}[rdoc-ref:language/strftime_formatting.rdoc@Shorthand+Conversion+Specifiers]
* <tt>'%F'</tt>);
*
* Date.new(2001, 2, 3).iso8601 # => "2001-02-03"
@@ -7305,7 +7509,7 @@ d_lite_iso8601(VALUE self)
* rfc3339 -> string
*
* Equivalent to #strftime with argument <tt>'%FT%T%:z'</tt>;
- * see {Formats for Dates and Times}[rdoc-ref:strftime_formatting.rdoc]:
+ * see {Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc]:
*
* Date.new(2001, 2, 3).rfc3339 # => "2001-02-03T00:00:00+00:00"
*
@@ -7321,7 +7525,7 @@ d_lite_rfc3339(VALUE self)
* rfc2822 -> string
*
* Equivalent to #strftime with argument <tt>'%a, %-d %b %Y %T %z'</tt>;
- * see {Formats for Dates and Times}[rdoc-ref:strftime_formatting.rdoc]:
+ * see {Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc]:
*
* Date.new(2001, 2, 3).rfc2822 # => "Sat, 3 Feb 2001 00:00:00 +0000"
*
@@ -7337,7 +7541,7 @@ d_lite_rfc2822(VALUE self)
* httpdate -> string
*
* Equivalent to #strftime with argument <tt>'%a, %d %b %Y %T GMT'</tt>;
- * see {Formats for Dates and Times}[rdoc-ref:strftime_formatting.rdoc]:
+ * see {Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc]:
*
* Date.new(2001, 2, 3).httpdate # => "Sat, 03 Feb 2001 00:00:00 GMT"
*
@@ -7516,10 +7720,7 @@ d_lite_marshal_dump_old(VALUE self)
m_of_in_day(dat),
DBL2NUM(m_sg(dat)));
- if (FL_TEST(self, FL_EXIVAR)) {
- rb_copy_generic_ivar(a, self);
- FL_SET(a, FL_EXIVAR);
- }
+ rb_copy_generic_ivar(a, self);
return a;
}
@@ -7541,10 +7742,8 @@ d_lite_marshal_dump(VALUE self)
INT2FIX(m_of(dat)),
DBL2NUM(m_sg(dat)));
- if (FL_TEST(self, FL_EXIVAR)) {
- rb_copy_generic_ivar(a, self);
- FL_SET(a, FL_EXIVAR);
- }
+
+ rb_copy_generic_ivar(a, self);
return a;
}
@@ -7617,10 +7816,7 @@ d_lite_marshal_load(VALUE self, VALUE a)
HAVE_JD | HAVE_DF);
}
- if (FL_TEST(a, FL_EXIVAR)) {
- rb_copy_generic_ivar(self, a);
- FL_SET(self, FL_EXIVAR);
- }
+ rb_copy_generic_ivar(self, a);
return self;
}
@@ -8373,7 +8569,7 @@ datetime_s_strptime(int argc, VALUE *argv, VALUE klass)
switch (argc) {
case 0:
- str = rb_str_new2("-4712-01-01T00:00:00+00:00");
+ str = rb_str_new2(JULIAN_EPOCH_DATETIME);
case 1:
fmt = rb_str_new2("%FT%T%z");
case 2:
@@ -8421,12 +8617,11 @@ datetime_s_parse(int argc, VALUE *argv, VALUE klass)
{
VALUE str, comp, sg, opt;
- rb_scan_args(argc, argv, "03:", &str, &comp, &sg, &opt);
- if (!NIL_P(opt)) argc--;
+ argc = rb_scan_args(argc, argv, "03:", &str, &comp, &sg, &opt);
switch (argc) {
case 0:
- str = rb_str_new2("-4712-01-01T00:00:00+00:00");
+ str = rb_str_new2(JULIAN_EPOCH_DATETIME);
case 1:
comp = Qtrue;
case 2:
@@ -8468,12 +8663,11 @@ datetime_s_iso8601(int argc, VALUE *argv, VALUE klass)
{
VALUE str, sg, opt;
- rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
- if (!NIL_P(opt)) argc--;
+ argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
switch (argc) {
case 0:
- str = rb_str_new2("-4712-01-01T00:00:00+00:00");
+ str = rb_str_new2(JULIAN_EPOCH_DATETIME);
case 1:
sg = INT2FIX(DEFAULT_SG);
}
@@ -8483,7 +8677,7 @@ datetime_s_iso8601(int argc, VALUE *argv, VALUE klass)
VALUE argv2[2], hash;
argv2[0] = str;
argv2[1] = opt;
- if (!NIL_P(opt)) argc2--;
+ if (!NIL_P(opt)) argc2++;
hash = date_s__iso8601(argc2, argv2, klass);
return dt_new_by_frags(klass, hash, sg);
}
@@ -8508,12 +8702,11 @@ datetime_s_rfc3339(int argc, VALUE *argv, VALUE klass)
{
VALUE str, sg, opt;
- rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
- if (!NIL_P(opt)) argc--;
+ argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
switch (argc) {
case 0:
- str = rb_str_new2("-4712-01-01T00:00:00+00:00");
+ str = rb_str_new2(JULIAN_EPOCH_DATETIME);
case 1:
sg = INT2FIX(DEFAULT_SG);
}
@@ -8548,12 +8741,11 @@ datetime_s_xmlschema(int argc, VALUE *argv, VALUE klass)
{
VALUE str, sg, opt;
- rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
- if (!NIL_P(opt)) argc--;
+ argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
switch (argc) {
case 0:
- str = rb_str_new2("-4712-01-01T00:00:00+00:00");
+ str = rb_str_new2(JULIAN_EPOCH_DATETIME);
case 1:
sg = INT2FIX(DEFAULT_SG);
}
@@ -8589,12 +8781,11 @@ datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass)
{
VALUE str, sg, opt;
- rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
- if (!NIL_P(opt)) argc--;
+ argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
switch (argc) {
case 0:
- str = rb_str_new2("Mon, 1 Jan -4712 00:00:00 +0000");
+ str = rb_str_new2(JULIAN_EPOCH_DATETIME_RFC3339);
case 1:
sg = INT2FIX(DEFAULT_SG);
}
@@ -8629,12 +8820,11 @@ datetime_s_httpdate(int argc, VALUE *argv, VALUE klass)
{
VALUE str, sg, opt;
- rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
- if (!NIL_P(opt)) argc--;
+ argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
switch (argc) {
case 0:
- str = rb_str_new2("Mon, 01 Jan -4712 00:00:00 GMT");
+ str = rb_str_new2(JULIAN_EPOCH_DATETIME_HTTPDATE);
case 1:
sg = INT2FIX(DEFAULT_SG);
}
@@ -8674,12 +8864,11 @@ datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass)
{
VALUE str, sg, opt;
- rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
- if (!NIL_P(opt)) argc--;
+ argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt);
switch (argc) {
case 0:
- str = rb_str_new2("-4712-01-01T00:00:00+00:00");
+ str = rb_str_new2(JULIAN_EPOCH_DATETIME);
case 1:
sg = INT2FIX(DEFAULT_SG);
}
@@ -8721,7 +8910,7 @@ dt_lite_to_s(VALUE self)
* DateTime.now.strftime # => "2022-07-01T11:03:19-05:00"
*
* For other formats,
- * see {Formats for Dates and Times}[rdoc-ref:strftime_formatting.rdoc]:
+ * see {Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc]:
*
*/
static VALUE
@@ -8955,18 +9144,23 @@ time_to_datetime(VALUE self)
static VALUE
date_to_time(VALUE self)
{
+ VALUE t;
+
get_d1a(self);
if (m_julian_p(adat)) {
- VALUE tmp = d_lite_gregorian(self);
- get_d1b(tmp);
+ VALUE g = d_lite_gregorian(self);
+ get_d1b(g);
adat = bdat;
+ self = g;
}
- return f_local3(rb_cTime,
+ t = f_local3(rb_cTime,
m_real_year(adat),
INT2FIX(m_mon(adat)),
INT2FIX(m_mday(adat)));
+ RB_GC_GUARD(self); /* may be the converted gregorian */
+ return t;
}
/*
@@ -9036,9 +9230,10 @@ datetime_to_time(VALUE self)
get_d1(self);
if (m_julian_p(dat)) {
- self = d_lite_gregorian(self);
- get_d1a(self);
+ VALUE g = d_lite_gregorian(self);
+ get_d1a(g);
dat = adat;
+ self = g;
}
{
@@ -9055,6 +9250,7 @@ datetime_to_time(VALUE self)
f_add(INT2FIX(m_sec(dat)),
m_sf_in_sec(dat)),
INT2FIX(m_of(dat)));
+ RB_GC_GUARD(self); /* may be the converted gregorian */
return t;
}
}
@@ -9459,7 +9655,7 @@ mk_ary_of_str(long len, const char *a[])
}
rb_ary_push(o, e);
}
- rb_obj_freeze(o);
+ rb_ary_freeze(o);
return o;
}
@@ -9493,6 +9689,7 @@ Init_date_core(void)
sym_zone = ID2SYM(rb_intern_const("zone"));
half_days_in_day = rb_rational_new2(INT2FIX(1), INT2FIX(2));
+ rb_gc_register_mark_object(half_days_in_day);
#if (LONG_MAX / DAY_IN_SECONDS) > SECOND_IN_NANOSECONDS
day_in_nanoseconds = LONG2NUM((long)DAY_IN_SECONDS *
@@ -9504,8 +9701,6 @@ Init_date_core(void)
day_in_nanoseconds = f_mul(INT2FIX(DAY_IN_SECONDS),
INT2FIX(SECOND_IN_NANOSECONDS));
#endif
-
- rb_gc_register_mark_object(half_days_in_day);
rb_gc_register_mark_object(day_in_nanoseconds);
positive_inf = +INFINITY;
@@ -9521,7 +9716,7 @@ Init_date_core(void)
*
* - You need both dates and times; \Date handles only dates.
* - You need only Gregorian dates (and not Julian dates);
- * see {Julian and Gregorian Calendars}[rdoc-ref:calendars.rdoc].
+ * see {Julian and Gregorian Calendars}[rdoc-ref:language/calendars.rdoc].
*
* A \Date object, once created, is immutable, and cannot be modified.
*
@@ -9568,7 +9763,7 @@ Init_date_core(void)
* Date.strptime('fri31dec99', '%a%d%b%y') # => #<Date: 1999-12-31>
*
* See also the specialized methods in
- * {"Specialized Format Strings" in Formats for Dates and Times}[rdoc-ref:strftime_formatting.rdoc@Specialized+Format+Strings]
+ * {"Specialized Format Strings" in Formats for Dates and Times}[rdoc-ref:language/strftime_formatting.rdoc@Specialized+Format+Strings]
*
* == Argument +limit+
*
diff --git a/ext/date/date_parse.c b/ext/date/date_parse.c
index c6f26ecb91..a1600e4708 100644
--- a/ext/date/date_parse.c
+++ b/ext/date/date_parse.c
@@ -7,6 +7,9 @@
#include "ruby/re.h"
#include <ctype.h>
+#undef strncasecmp
+#define strncasecmp STRNCASECMP
+
RUBY_EXTERN VALUE rb_int_positive_pow(long x, unsigned long y);
RUBY_EXTERN unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow);
diff --git a/ext/date/date_strptime.c b/ext/date/date_strptime.c
index f731629df1..f1c8201de8 100644
--- a/ext/date/date_strptime.c
+++ b/ext/date/date_strptime.c
@@ -7,6 +7,9 @@
#include "ruby/re.h"
#include <ctype.h>
+#undef strncasecmp
+#define strncasecmp STRNCASECMP
+
static const char *day_names[] = {
"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday",
@@ -119,8 +122,9 @@ do { \
do { \
size_t l; \
l = read_digits(&str[si], slen - si, &n, w); \
- if (l == 0) \
+ if (l == 0) { \
fail(); \
+ } \
si += l; \
} while (0)
diff --git a/ext/date/depend b/ext/date/depend
index d07f10a593..4fb78149a1 100644
--- a/ext/date/depend
+++ b/ext/date/depend
@@ -138,6 +138,7 @@ date_core.o: $(hdrdir)/ruby/internal/intern/re.h
date_core.o: $(hdrdir)/ruby/internal/intern/ruby.h
date_core.o: $(hdrdir)/ruby/internal/intern/select.h
date_core.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+date_core.o: $(hdrdir)/ruby/internal/intern/set.h
date_core.o: $(hdrdir)/ruby/internal/intern/signal.h
date_core.o: $(hdrdir)/ruby/internal/intern/sprintf.h
date_core.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -313,6 +314,7 @@ date_parse.o: $(hdrdir)/ruby/internal/intern/re.h
date_parse.o: $(hdrdir)/ruby/internal/intern/ruby.h
date_parse.o: $(hdrdir)/ruby/internal/intern/select.h
date_parse.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+date_parse.o: $(hdrdir)/ruby/internal/intern/set.h
date_parse.o: $(hdrdir)/ruby/internal/intern/signal.h
date_parse.o: $(hdrdir)/ruby/internal/intern/sprintf.h
date_parse.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -478,6 +480,7 @@ date_strftime.o: $(hdrdir)/ruby/internal/intern/re.h
date_strftime.o: $(hdrdir)/ruby/internal/intern/ruby.h
date_strftime.o: $(hdrdir)/ruby/internal/intern/select.h
date_strftime.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+date_strftime.o: $(hdrdir)/ruby/internal/intern/set.h
date_strftime.o: $(hdrdir)/ruby/internal/intern/signal.h
date_strftime.o: $(hdrdir)/ruby/internal/intern/sprintf.h
date_strftime.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -650,6 +653,7 @@ date_strptime.o: $(hdrdir)/ruby/internal/intern/re.h
date_strptime.o: $(hdrdir)/ruby/internal/intern/ruby.h
date_strptime.o: $(hdrdir)/ruby/internal/intern/select.h
date_strptime.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+date_strptime.o: $(hdrdir)/ruby/internal/intern/set.h
date_strptime.o: $(hdrdir)/ruby/internal/intern/signal.h
date_strptime.o: $(hdrdir)/ruby/internal/intern/sprintf.h
date_strptime.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/date/extconf.rb b/ext/date/extconf.rb
index 358f64173a..8a1467df09 100644
--- a/ext/date/extconf.rb
+++ b/ext/date/extconf.rb
@@ -3,6 +3,7 @@ require 'mkmf'
config_string("strict_warnflags") {|w| $warnflags += " #{w}"}
+append_cflags("-Wno-compound-token-split-by-macro") if RUBY_VERSION < "2.7."
have_func("rb_category_warn")
with_werror("", {:werror => true}) do |opt, |
have_var("timezone", "time.h", opt)
diff --git a/ext/date/lib/date.rb b/ext/date/lib/date.rb
index 6888bd2d4e..0cb763017f 100644
--- a/ext/date/lib/date.rb
+++ b/ext/date/lib/date.rb
@@ -4,7 +4,7 @@
require 'date_core'
class Date
- VERSION = "3.3.4" # :nodoc:
+ VERSION = "3.5.1" # :nodoc:
# call-seq:
# infinite? -> false
diff --git a/ext/date/prereq.mk b/ext/date/prereq.mk
index cee7685975..b5d271a32c 100644
--- a/ext/date/prereq.mk
+++ b/ext/date/prereq.mk
@@ -1,7 +1,7 @@
.SUFFIXES: .list
.list.h:
- gperf --ignore-case -C -c -P -p -j1 -i 1 -g -o -t -N $(*F) $< \
+ gperf --ignore-case -L ANSI-C -C -c -P -p -j1 -i 1 -g -o -t -N $(*F) $< \
| sed -f $(top_srcdir)/tool/gperf.sed \
> $(@F)
diff --git a/ext/date/zonetab.h b/ext/date/zonetab.h
index 7ced9e0308..2a2e8910c9 100644
--- a/ext/date/zonetab.h
+++ b/ext/date/zonetab.h
@@ -1,5 +1,5 @@
/* ANSI-C code produced by gperf version 3.1 */
-/* Command-line: gperf --ignore-case -C -c -P -p -j1 -i 1 -g -o -t -N zonetab zonetab.list */
+/* Command-line: gperf --ignore-case -L ANSI-C -C -c -P -p -j1 -i 1 -g -o -t -N zonetab zonetab.list */
/* Computed positions: -k'1-4,9' */
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
@@ -29,15 +29,17 @@
#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gperf@gnu.org>."
#endif
-#define gperf_offsetof(s, n) (short)offsetof(struct s##_t, s##_str##n)
#line 1 "zonetab.list"
+#define GPERF_DOWNCASE 1
+#define GPERF_CASE_STRNCMP 1
+#define gperf_case_strncmp strncasecmp
struct zone {
int name;
int offset;
};
static const struct zone *zonetab(register const char *str, register size_t len);
-#line 9 "zonetab.list"
+#line 12 "zonetab.list"
struct zone;
#define TOTAL_KEYWORDS 316
@@ -49,7 +51,7 @@ struct zone;
#ifndef GPERF_DOWNCASE
#define GPERF_DOWNCASE 1
-static const unsigned char gperf_downcase[256] =
+static unsigned char gperf_downcase[256] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
@@ -808,736 +810,736 @@ zonetab (register const char *str, register size_t len)
static const struct zone wordlist[] =
{
{-1}, {-1},
-#line 34 "zonetab.list"
- {gperf_offsetof(stringpool, 2), -2*3600},
-#line 43 "zonetab.list"
- {gperf_offsetof(stringpool, 3), -11*3600},
-#line 45 "zonetab.list"
- {gperf_offsetof(stringpool, 4), 0*3600},
-#line 36 "zonetab.list"
- {gperf_offsetof(stringpool, 5), -4*3600},
- {-1}, {-1},
-#line 269 "zonetab.list"
- {gperf_offsetof(stringpool, 8),21600},
-#line 268 "zonetab.list"
- {gperf_offsetof(stringpool, 9),25200},
-#line 35 "zonetab.list"
- {gperf_offsetof(stringpool, 10), -3*3600},
+#line 37 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str2, -2*3600},
+#line 46 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str3, -11*3600},
+#line 48 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str4, 0*3600},
+#line 39 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str5, -4*3600},
{-1}, {-1},
-#line 21 "zonetab.list"
- {gperf_offsetof(stringpool, 13), 1*3600},
-#line 25 "zonetab.list"
- {gperf_offsetof(stringpool, 14), 5*3600},
-#line 271 "zonetab.list"
- {gperf_offsetof(stringpool, 15),-18000},
-#line 279 "zonetab.list"
- {gperf_offsetof(stringpool, 16),-10800},
-#line 273 "zonetab.list"
- {gperf_offsetof(stringpool, 17),43200},
#line 272 "zonetab.list"
- {gperf_offsetof(stringpool, 18),43200},
-#line 80 "zonetab.list"
- {gperf_offsetof(stringpool, 19), 2*3600},
-#line 186 "zonetab.list"
- {gperf_offsetof(stringpool, 20),36000},
-#line 88 "zonetab.list"
- {gperf_offsetof(stringpool, 21), 3*3600},
-#line 87 "zonetab.list"
- {gperf_offsetof(stringpool, 22), 3*3600},
- {-1},
-#line 101 "zonetab.list"
- {gperf_offsetof(stringpool, 24),-6*3600},
-#line 217 "zonetab.list"
- {gperf_offsetof(stringpool, 25),-18000},
-#line 19 "zonetab.list"
- {gperf_offsetof(stringpool, 26), -8*3600},
-#line 133 "zonetab.list"
- {gperf_offsetof(stringpool, 27), -18000},
-#line 32 "zonetab.list"
- {gperf_offsetof(stringpool, 28), 12*3600},
-#line 56 "zonetab.list"
- {gperf_offsetof(stringpool, 29), -4*3600},
-#line 13 "zonetab.list"
- {gperf_offsetof(stringpool, 30), -5*3600},
-#line 23 "zonetab.list"
- {gperf_offsetof(stringpool, 31), 3*3600},
-#line 256 "zonetab.list"
- {gperf_offsetof(stringpool, 32),23400},
-#line 73 "zonetab.list"
- {gperf_offsetof(stringpool, 33), 1*3600},
- {-1},
-#line 82 "zonetab.list"
- {gperf_offsetof(stringpool, 35), 2*3600},
-#line 71 "zonetab.list"
- {gperf_offsetof(stringpool, 36), 1*3600},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str8,21600},
+#line 271 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str9,25200},
+#line 38 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str10, -3*3600},
+ {-1}, {-1},
#line 24 "zonetab.list"
- {gperf_offsetof(stringpool, 37), 4*3600},
-#line 79 "zonetab.list"
- {gperf_offsetof(stringpool, 38), 2*3600},
-#line 65 "zonetab.list"
- {gperf_offsetof(stringpool, 39),2*3600},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str13, 1*3600},
+#line 28 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str14, 5*3600},
+#line 274 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str15,-18000},
+#line 282 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str16,-10800},
+#line 276 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str17,43200},
+#line 275 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str18,43200},
+#line 83 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str19, 2*3600},
+#line 189 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str20,36000},
+#line 91 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str21, 3*3600},
+#line 90 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str22, 3*3600},
{-1},
-#line 202 "zonetab.list"
- {gperf_offsetof(stringpool, 41),28800},
-#line 252 "zonetab.list"
- {gperf_offsetof(stringpool, 42),39600},
-#line 251 "zonetab.list"
- {gperf_offsetof(stringpool, 43),43200},
-#line 17 "zonetab.list"
- {gperf_offsetof(stringpool, 44), -7*3600},
-#line 89 "zonetab.list"
- {gperf_offsetof(stringpool, 45), 3*3600},
-#line 212 "zonetab.list"
- {gperf_offsetof(stringpool, 46),-18000},
-#line 15 "zonetab.list"
- {gperf_offsetof(stringpool, 47), -6*3600},
-#line 192 "zonetab.list"
- {gperf_offsetof(stringpool, 48),18000},
-#line 26 "zonetab.list"
- {gperf_offsetof(stringpool, 49), 6*3600},
- {-1}, {-1},
-#line 51 "zonetab.list"
- {gperf_offsetof(stringpool, 52), -3*3600},
-#line 226 "zonetab.list"
- {gperf_offsetof(stringpool, 53),-7200},
-#line 221 "zonetab.list"
- {gperf_offsetof(stringpool, 54),10800},
+#line 104 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str24,-6*3600},
+#line 220 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str25,-18000},
#line 22 "zonetab.list"
- {gperf_offsetof(stringpool, 55), 2*3600},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str26, -8*3600},
+#line 136 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str27, -18000},
+#line 35 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str28, 12*3600},
+#line 59 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str29, -4*3600},
+#line 16 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str30, -5*3600},
+#line 26 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str31, 3*3600},
+#line 259 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str32,23400},
+#line 76 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str33, 1*3600},
{-1},
-#line 190 "zonetab.list"
- {gperf_offsetof(stringpool, 57),43200},
-#line 189 "zonetab.list"
- {gperf_offsetof(stringpool, 58),43200},
-#line 199 "zonetab.list"
- {gperf_offsetof(stringpool, 59),28800},
-#line 29 "zonetab.list"
- {gperf_offsetof(stringpool, 60), 9*3600},
-#line 276 "zonetab.list"
- {gperf_offsetof(stringpool, 61),28800},
-#line 48 "zonetab.list"
- {gperf_offsetof(stringpool, 62), -2*3600},
-#line 94 "zonetab.list"
- {gperf_offsetof(stringpool, 63), 6*3600},
+#line 85 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str35, 2*3600},
#line 74 "zonetab.list"
- {gperf_offsetof(stringpool, 64), 1*3600},
-#line 81 "zonetab.list"
- {gperf_offsetof(stringpool, 65), 2*3600},
-#line 64 "zonetab.list"
- {gperf_offsetof(stringpool, 66),-10*3600},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str36, 1*3600},
+#line 27 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str37, 4*3600},
+#line 82 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str38, 2*3600},
+#line 68 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str39,2*3600},
+ {-1},
+#line 205 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str41,28800},
+#line 255 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str42,39600},
#line 254 "zonetab.list"
- {gperf_offsetof(stringpool, 67),18000},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str43,43200},
+#line 20 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str44, -7*3600},
#line 92 "zonetab.list"
- {gperf_offsetof(stringpool, 68), 5*3600},
- {-1},
-#line 200 "zonetab.list"
- {gperf_offsetof(stringpool, 70),-14400},
-#line 70 "zonetab.list"
- {gperf_offsetof(stringpool, 71), 1*3600},
-#line 281 "zonetab.list"
- {gperf_offsetof(stringpool, 72),32400},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str45, 3*3600},
+#line 215 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str46,-18000},
+#line 18 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str47, -6*3600},
+#line 195 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str48,18000},
+#line 29 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str49, 6*3600},
+ {-1}, {-1},
+#line 54 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str52, -3*3600},
+#line 229 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str53,-7200},
+#line 224 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str54,10800},
+#line 25 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str55, 2*3600},
{-1},
-#line 280 "zonetab.list"
- {gperf_offsetof(stringpool, 74),39600},
-#line 238 "zonetab.list"
- {gperf_offsetof(stringpool, 75),21600},
-#line 93 "zonetab.list"
- {gperf_offsetof(stringpool, 76), (5*3600+1800)},
-#line 194 "zonetab.list"
- {gperf_offsetof(stringpool, 77),28800},
+#line 193 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str57,43200},
+#line 192 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str58,43200},
+#line 202 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str59,28800},
+#line 32 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str60, 9*3600},
+#line 279 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str61,28800},
+#line 51 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str62, -2*3600},
+#line 97 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str63, 6*3600},
+#line 77 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str64, 1*3600},
+#line 84 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str65, 2*3600},
+#line 67 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str66,-10*3600},
+#line 257 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str67,18000},
+#line 95 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str68, 5*3600},
{-1},
-#line 255 "zonetab.list"
- {gperf_offsetof(stringpool, 79),43200},
-#line 75 "zonetab.list"
- {gperf_offsetof(stringpool, 80), 1*3600},
-#line 270 "zonetab.list"
- {gperf_offsetof(stringpool, 81),18000},
-#line 83 "zonetab.list"
- {gperf_offsetof(stringpool, 82), 2*3600},
+#line 203 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str70,-14400},
+#line 73 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str71, 1*3600},
+#line 284 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str72,32400},
{-1},
-#line 207 "zonetab.list"
- {gperf_offsetof(stringpool, 84),36000},
-#line 278 "zonetab.list"
- {gperf_offsetof(stringpool, 85),-7200},
- {-1}, {-1},
-#line 126 "zonetab.list"
- {gperf_offsetof(stringpool, 88), -21600},
-#line 185 "zonetab.list"
- {gperf_offsetof(stringpool, 89),39600},
-#line 183 "zonetab.list"
- {gperf_offsetof(stringpool, 90),-18000},
-#line 218 "zonetab.list"
- {gperf_offsetof(stringpool, 91),-18000},
-#line 182 "zonetab.list"
- {gperf_offsetof(stringpool, 92),34200},
-#line 103 "zonetab.list"
- {gperf_offsetof(stringpool, 93),11*3600},
-#line 53 "zonetab.list"
- {gperf_offsetof(stringpool, 94), -3*3600},
-#line 208 "zonetab.list"
- {gperf_offsetof(stringpool, 95),36000},
-#line 49 "zonetab.list"
- {gperf_offsetof(stringpool, 96),-2*3600},
-#line 120 "zonetab.list"
- {gperf_offsetof(stringpool, 97), 34200},
- {-1}, {-1},
-#line 215 "zonetab.list"
- {gperf_offsetof(stringpool, 100),25200},
-#line 242 "zonetab.list"
- {gperf_offsetof(stringpool, 101),12600},
+#line 283 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str74,39600},
#line 241 "zonetab.list"
- {gperf_offsetof(stringpool, 102),28800},
-#line 240 "zonetab.list"
- {gperf_offsetof(stringpool, 103),32400},
-#line 86 "zonetab.list"
- {gperf_offsetof(stringpool, 104), 3*3600},
-#line 33 "zonetab.list"
- {gperf_offsetof(stringpool, 105), -1*3600},
-#line 201 "zonetab.list"
- {gperf_offsetof(stringpool, 106),21600},
-#line 148 "zonetab.list"
- {gperf_offsetof(stringpool, 107), -25200},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str75,21600},
#line 96 "zonetab.list"
- {gperf_offsetof(stringpool, 108), (6*3600+1800)},
-#line 42 "zonetab.list"
- {gperf_offsetof(stringpool, 109), -10*3600},
-#line 31 "zonetab.list"
- {gperf_offsetof(stringpool, 110), 11*3600},
-#line 72 "zonetab.list"
- {gperf_offsetof(stringpool, 111), 1*3600},
- {-1},
-#line 90 "zonetab.list"
- {gperf_offsetof(stringpool, 113), 4*3600},
-#line 47 "zonetab.list"
- {gperf_offsetof(stringpool, 114), 0*3600},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str76, (5*3600+1800)},
+#line 197 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str77,28800},
{-1},
+#line 258 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str79,43200},
#line 78 "zonetab.list"
- {gperf_offsetof(stringpool, 116), 1*3600},
-#line 77 "zonetab.list"
- {gperf_offsetof(stringpool, 117), 1*3600},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str80, 1*3600},
+#line 273 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str81,18000},
+#line 86 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str82, 2*3600},
{-1},
-#line 95 "zonetab.list"
- {gperf_offsetof(stringpool, 119), 2*3600},
-#line 313 "zonetab.list"
- {gperf_offsetof(stringpool, 120),43200},
-#line 55 "zonetab.list"
- {gperf_offsetof(stringpool, 121), -(2*3600+1800)},
-#line 184 "zonetab.list"
- {gperf_offsetof(stringpool, 122),31500},
-#line 204 "zonetab.list"
- {gperf_offsetof(stringpool, 123),45900},
#line 210 "zonetab.list"
- {gperf_offsetof(stringpool, 124),-18000},
-#line 198 "zonetab.list"
- {gperf_offsetof(stringpool, 125),14400},
-#line 57 "zonetab.list"
- {gperf_offsetof(stringpool, 126), -4*3600},
-#line 197 "zonetab.list"
- {gperf_offsetof(stringpool, 127),18000},
-#line 54 "zonetab.list"
- {gperf_offsetof(stringpool, 128),-3*3600},
-#line 253 "zonetab.list"
- {gperf_offsetof(stringpool, 129),-30600},
-#line 91 "zonetab.list"
- {gperf_offsetof(stringpool, 130), 4*3600},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str84,36000},
+#line 281 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str85,-7200},
+ {-1}, {-1},
+#line 129 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str88, -21600},
+#line 188 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str89,39600},
+#line 186 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str90,-18000},
+#line 221 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str91,-18000},
+#line 185 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str92,34200},
+#line 106 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str93,11*3600},
+#line 56 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str94, -3*3600},
+#line 211 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str95,36000},
+#line 52 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str96,-2*3600},
+#line 123 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str97, 34200},
+ {-1}, {-1},
+#line 218 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str100,25200},
+#line 245 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str101,12600},
+#line 244 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str102,28800},
+#line 243 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str103,32400},
+#line 89 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str104, 3*3600},
+#line 36 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str105, -1*3600},
+#line 204 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str106,21600},
+#line 151 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str107, -25200},
#line 99 "zonetab.list"
- {gperf_offsetof(stringpool, 131), 9*3600},
-#line 122 "zonetab.list"
- {gperf_offsetof(stringpool, 132), 21600},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str108, (6*3600+1800)},
+#line 45 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str109, -10*3600},
+#line 34 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str110, 11*3600},
+#line 75 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str111, 1*3600},
+ {-1},
+#line 93 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str113, 4*3600},
+#line 50 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str114, 0*3600},
+ {-1},
+#line 81 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str116, 1*3600},
+#line 80 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str117, 1*3600},
+ {-1},
+#line 98 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str119, 2*3600},
+#line 316 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str120,43200},
+#line 58 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str121, -(2*3600+1800)},
#line 187 "zonetab.list"
- {gperf_offsetof(stringpool, 133),16200},
-#line 132 "zonetab.list"
- {gperf_offsetof(stringpool, 134), -10800},
-#line 121 "zonetab.list"
- {gperf_offsetof(stringpool, 135), -21600},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str122,31500},
+#line 207 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str123,45900},
+#line 213 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str124,-18000},
+#line 201 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str125,14400},
+#line 60 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str126, -4*3600},
+#line 200 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str127,18000},
+#line 57 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str128,-3*3600},
+#line 256 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str129,-30600},
+#line 94 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str130, 4*3600},
+#line 102 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str131, 9*3600},
+#line 125 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str132, 21600},
+#line 190 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str133,16200},
+#line 135 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str134, -10800},
+#line 124 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str135, -21600},
{-1},
-#line 236 "zonetab.list"
- {gperf_offsetof(stringpool, 137),25200},
+#line 239 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str137,25200},
{-1}, {-1}, {-1}, {-1}, {-1},
-#line 274 "zonetab.list"
- {gperf_offsetof(stringpool, 143),36000},
-#line 266 "zonetab.list"
- {gperf_offsetof(stringpool, 144),43200},
-#line 146 "zonetab.list"
- {gperf_offsetof(stringpool, 145), -21600},
-#line 193 "zonetab.list"
- {gperf_offsetof(stringpool, 146),32400},
-#line 220 "zonetab.list"
- {gperf_offsetof(stringpool, 147),-3600},
-#line 214 "zonetab.list"
- {gperf_offsetof(stringpool, 148),25200},
-#line 219 "zonetab.list"
- {gperf_offsetof(stringpool, 149),0},
-#line 275 "zonetab.list"
- {gperf_offsetof(stringpool, 150),46800},
-#line 109 "zonetab.list"
- {gperf_offsetof(stringpool, 151), -32400},
+#line 277 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str143,36000},
+#line 269 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str144,43200},
+#line 149 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str145, -21600},
+#line 196 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str146,32400},
+#line 223 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str147,-3600},
+#line 217 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str148,25200},
+#line 222 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str149,0},
+#line 278 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str150,46800},
+#line 112 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str151, -32400},
{-1}, {-1},
-#line 68 "zonetab.list"
- {gperf_offsetof(stringpool, 154), -11*3600},
+#line 71 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str154, -11*3600},
{-1}, {-1}, {-1},
-#line 321 "zonetab.list"
- {gperf_offsetof(stringpool, 158),0},
+#line 324 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str158,0},
{-1},
-#line 178 "zonetab.list"
- {gperf_offsetof(stringpool, 160), 18000},
#line 181 "zonetab.list"
- {gperf_offsetof(stringpool, 161),37800},
-#line 265 "zonetab.list"
- {gperf_offsetof(stringpool, 162),20700},
-#line 249 "zonetab.list"
- {gperf_offsetof(stringpool, 163),37800},
-#line 108 "zonetab.list"
- {gperf_offsetof(stringpool, 164), 16200},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str160, 18000},
+#line 184 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str161,37800},
+#line 268 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str162,20700},
+#line 252 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str163,37800},
+#line 111 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str164, 16200},
{-1}, {-1},
+#line 33 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str167, 10*3600},
+ {-1},
#line 30 "zonetab.list"
- {gperf_offsetof(stringpool, 167), 10*3600},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str169, 7*3600},
+#line 242 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str170,16200},
+#line 209 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str171,28800},
+#line 208 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str172,32400},
+#line 15 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str173, 0*3600},
+#line 232 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str174,14400},
+#line 267 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str175,25200},
+#line 266 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str176,25200},
+#line 226 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str177,43200},
+#line 43 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str178, -8*3600},
+#line 225 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str179,46800},
{-1},
-#line 27 "zonetab.list"
- {gperf_offsetof(stringpool, 169), 7*3600},
-#line 239 "zonetab.list"
- {gperf_offsetof(stringpool, 170),16200},
-#line 206 "zonetab.list"
- {gperf_offsetof(stringpool, 171),28800},
-#line 205 "zonetab.list"
- {gperf_offsetof(stringpool, 172),32400},
-#line 12 "zonetab.list"
- {gperf_offsetof(stringpool, 173), 0*3600},
-#line 229 "zonetab.list"
- {gperf_offsetof(stringpool, 174),14400},
-#line 264 "zonetab.list"
- {gperf_offsetof(stringpool, 175),25200},
+#line 285 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str181,-10800},
#line 263 "zonetab.list"
- {gperf_offsetof(stringpool, 176),25200},
-#line 223 "zonetab.list"
- {gperf_offsetof(stringpool, 177),43200},
-#line 40 "zonetab.list"
- {gperf_offsetof(stringpool, 178), -8*3600},
-#line 222 "zonetab.list"
- {gperf_offsetof(stringpool, 179),46800},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str182,39600},
+#line 103 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str183, 9*3600},
+#line 247 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str184,39600},
+#line 105 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str185, 10*3600},
+#line 146 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str186, 12600},
+#line 132 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str187, 10800},
+#line 101 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str188, 8*3600},
+#line 42 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str189, -7*3600},
+#line 133 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str190, 36000},
+#line 41 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str191, -6*3600},
+#line 206 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str192,49500},
+#line 301 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str193,18000},
+#line 212 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str194,-14400},
+#line 194 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str195,-43200},
{-1},
-#line 282 "zonetab.list"
- {gperf_offsetof(stringpool, 181),-10800},
+#line 262 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str197,28800},
+#line 182 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str198, 36000},
#line 260 "zonetab.list"
- {gperf_offsetof(stringpool, 182),39600},
-#line 100 "zonetab.list"
- {gperf_offsetof(stringpool, 183), 9*3600},
-#line 244 "zonetab.list"
- {gperf_offsetof(stringpool, 184),39600},
-#line 102 "zonetab.list"
- {gperf_offsetof(stringpool, 185), 10*3600},
-#line 143 "zonetab.list"
- {gperf_offsetof(stringpool, 186), 12600},
-#line 129 "zonetab.list"
- {gperf_offsetof(stringpool, 187), 10800},
-#line 98 "zonetab.list"
- {gperf_offsetof(stringpool, 188), 8*3600},
-#line 39 "zonetab.list"
- {gperf_offsetof(stringpool, 189), -7*3600},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str199,14400},
+#line 322 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str200,32400},
+#line 87 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str201, 2*3600},
+#line 289 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str202,39600},
+#line 155 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str203, 43200},
+#line 303 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str204,46800},
#line 130 "zonetab.list"
- {gperf_offsetof(stringpool, 190), 36000},
-#line 38 "zonetab.list"
- {gperf_offsetof(stringpool, 191), -6*3600},
-#line 203 "zonetab.list"
- {gperf_offsetof(stringpool, 192),49500},
-#line 298 "zonetab.list"
- {gperf_offsetof(stringpool, 193),18000},
-#line 209 "zonetab.list"
- {gperf_offsetof(stringpool, 194),-14400},
-#line 191 "zonetab.list"
- {gperf_offsetof(stringpool, 195),-43200},
- {-1},
-#line 259 "zonetab.list"
- {gperf_offsetof(stringpool, 197),28800},
-#line 179 "zonetab.list"
- {gperf_offsetof(stringpool, 198), 36000},
-#line 257 "zonetab.list"
- {gperf_offsetof(stringpool, 199),14400},
-#line 319 "zonetab.list"
- {gperf_offsetof(stringpool, 200),32400},
-#line 84 "zonetab.list"
- {gperf_offsetof(stringpool, 201), 2*3600},
-#line 286 "zonetab.list"
- {gperf_offsetof(stringpool, 202),39600},
-#line 152 "zonetab.list"
- {gperf_offsetof(stringpool, 203), 43200},
-#line 300 "zonetab.list"
- {gperf_offsetof(stringpool, 204),46800},
-#line 127 "zonetab.list"
- {gperf_offsetof(stringpool, 205), 28800},
-#line 299 "zonetab.list"
- {gperf_offsetof(stringpool, 206),50400},
-#line 85 "zonetab.list"
- {gperf_offsetof(stringpool, 207), -11*3600},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str205, 28800},
+#line 302 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str206,50400},
+#line 88 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str207, -11*3600},
{-1},
-#line 142 "zonetab.list"
- {gperf_offsetof(stringpool, 209), 19800},
+#line 145 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str209, 19800},
{-1},
-#line 314 "zonetab.list"
- {gperf_offsetof(stringpool, 211),-10800},
-#line 288 "zonetab.list"
- {gperf_offsetof(stringpool, 212),39600},
+#line 317 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str211,-10800},
+#line 291 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str212,39600},
{-1},
-#line 196 "zonetab.list"
- {gperf_offsetof(stringpool, 214),-3600},
-#line 195 "zonetab.list"
- {gperf_offsetof(stringpool, 215),0},
-#line 293 "zonetab.list"
- {gperf_offsetof(stringpool, 216),-36000},
-#line 106 "zonetab.list"
- {gperf_offsetof(stringpool, 217), 12*3600},
+#line 199 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str214,-3600},
+#line 198 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str215,0},
+#line 296 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str216,-36000},
+#line 109 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str217, 12*3600},
+#line 131 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str218, -43200},
+#line 108 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str219,12*3600},
+#line 173 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str220, 32400},
#line 128 "zonetab.list"
- {gperf_offsetof(stringpool, 218), -43200},
-#line 105 "zonetab.list"
- {gperf_offsetof(stringpool, 219),12*3600},
-#line 170 "zonetab.list"
- {gperf_offsetof(stringpool, 220), 32400},
-#line 125 "zonetab.list"
- {gperf_offsetof(stringpool, 221), 39600},
- {-1},
-#line 283 "zonetab.list"
- {gperf_offsetof(stringpool, 223),21600},
-#line 113 "zonetab.list"
- {gperf_offsetof(stringpool, 224), -14400},
-#line 262 "zonetab.list"
- {gperf_offsetof(stringpool, 225),39600},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str221, 39600},
{-1},
-#line 11 "zonetab.list"
- {gperf_offsetof(stringpool, 227), 0*3600},
-#line 301 "zonetab.list"
- {gperf_offsetof(stringpool, 228),10800},
-#line 315 "zonetab.list"
- {gperf_offsetof(stringpool, 229),43200},
-#line 291 "zonetab.list"
- {gperf_offsetof(stringpool, 230),-10800},
-#line 20 "zonetab.list"
- {gperf_offsetof(stringpool, 231), -7*3600},
-#line 248 "zonetab.list"
- {gperf_offsetof(stringpool, 232),39600},
+#line 286 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str223,21600},
+#line 116 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str224, -14400},
+#line 265 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str225,39600},
{-1},
-#line 52 "zonetab.list"
- {gperf_offsetof(stringpool, 234), -3*3600},
#line 14 "zonetab.list"
- {gperf_offsetof(stringpool, 235), -4*3600},
- {-1}, {-1},
-#line 277 "zonetab.list"
- {gperf_offsetof(stringpool, 238),18000},
-#line 188 "zonetab.list"
- {gperf_offsetof(stringpool, 239),21600},
-#line 320 "zonetab.list"
- {gperf_offsetof(stringpool, 240),28800},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str227, 0*3600},
+#line 304 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str228,10800},
+#line 318 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str229,43200},
+#line 294 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str230,-10800},
+#line 23 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str231, -7*3600},
+#line 251 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str232,39600},
{-1},
-#line 317 "zonetab.list"
- {gperf_offsetof(stringpool, 242),-10800},
-#line 60 "zonetab.list"
- {gperf_offsetof(stringpool, 243),-9*3600},
-#line 316 "zonetab.list"
- {gperf_offsetof(stringpool, 244),-7200},
+#line 55 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str234, -3*3600},
+#line 17 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str235, -4*3600},
+ {-1}, {-1},
+#line 280 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str238,18000},
+#line 191 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str239,21600},
+#line 323 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str240,28800},
{-1},
-#line 246 "zonetab.list"
- {gperf_offsetof(stringpool, 246),25200},
-#line 245 "zonetab.list"
- {gperf_offsetof(stringpool, 247),28800},
-#line 147 "zonetab.list"
- {gperf_offsetof(stringpool, 248), -7200},
-#line 18 "zonetab.list"
- {gperf_offsetof(stringpool, 249), -6*3600},
-#line 250 "zonetab.list"
- {gperf_offsetof(stringpool, 250),50400},
-#line 165 "zonetab.list"
- {gperf_offsetof(stringpool, 251), 28800},
-#line 16 "zonetab.list"
- {gperf_offsetof(stringpool, 252), -5*3600},
-#line 76 "zonetab.list"
- {gperf_offsetof(stringpool, 253), 1*3600},
+#line 320 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str242,-7200},
+#line 63 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str243,-9*3600},
+#line 319 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str244,-3600},
{-1},
-#line 164 "zonetab.list"
- {gperf_offsetof(stringpool, 255), 25200},
-#line 41 "zonetab.list"
- {gperf_offsetof(stringpool, 256), -9*3600},
+#line 249 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str246,25200},
+#line 248 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str247,28800},
+#line 150 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str248, -7200},
+#line 21 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str249, -6*3600},
+#line 253 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str250,50400},
+#line 168 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str251, 28800},
+#line 19 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str252, -5*3600},
+#line 79 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str253, 1*3600},
{-1},
-#line 171 "zonetab.list"
- {gperf_offsetof(stringpool, 258), 46800},
-#line 211 "zonetab.list"
- {gperf_offsetof(stringpool, 259),-36000},
+#line 167 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str255, 25200},
+#line 44 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str256, -9*3600},
{-1},
-#line 308 "zonetab.list"
- {gperf_offsetof(stringpool, 261),-14400},
-#line 119 "zonetab.list"
- {gperf_offsetof(stringpool, 262), 14400},
-#line 123 "zonetab.list"
- {gperf_offsetof(stringpool, 263), 3600},
-#line 28 "zonetab.list"
- {gperf_offsetof(stringpool, 264), 8*3600},
-#line 124 "zonetab.list"
- {gperf_offsetof(stringpool, 265), 3600},
-#line 153 "zonetab.list"
- {gperf_offsetof(stringpool, 266), -12600},
-#line 110 "zonetab.list"
- {gperf_offsetof(stringpool, 267), 10800},
-#line 289 "zonetab.list"
- {gperf_offsetof(stringpool, 268),14400},
-#line 112 "zonetab.list"
- {gperf_offsetof(stringpool, 269), 10800},
-#line 111 "zonetab.list"
- {gperf_offsetof(stringpool, 270), 14400},
-#line 216 "zonetab.list"
- {gperf_offsetof(stringpool, 271),36000},
+#line 174 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str258, 46800},
+#line 214 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str259,-36000},
{-1},
#line 311 "zonetab.list"
- {gperf_offsetof(stringpool, 273),21600},
-#line 66 "zonetab.list"
- {gperf_offsetof(stringpool, 274),-10*3600},
-#line 151 "zonetab.list"
- {gperf_offsetof(stringpool, 275), 20700},
-#line 267 "zonetab.list"
- {gperf_offsetof(stringpool, 276),-39600},
-#line 225 "zonetab.list"
- {gperf_offsetof(stringpool, 277),-14400},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str261,-14400},
+#line 122 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str262, 14400},
+#line 126 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str263, 3600},
+#line 31 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str264, 8*3600},
+#line 127 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str265, 3600},
+#line 156 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str266, -12600},
+#line 113 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str267, 10800},
+#line 292 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str268,14400},
+#line 115 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str269, 10800},
+#line 114 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str270, 14400},
+#line 219 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str271,36000},
{-1},
-#line 224 "zonetab.list"
- {gperf_offsetof(stringpool, 279),-10800},
-#line 67 "zonetab.list"
- {gperf_offsetof(stringpool, 280),-10*3600},
-#line 237 "zonetab.list"
- {gperf_offsetof(stringpool, 281),10800},
+#line 314 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str273,21600},
+#line 69 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str274,-10*3600},
+#line 154 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str275, 20700},
+#line 270 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str276,-39600},
+#line 228 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str277,-14400},
+ {-1},
+#line 227 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str279,-10800},
+#line 70 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str280,-10*3600},
+#line 240 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str281,10800},
{-1}, {-1},
-#line 297 "zonetab.list"
- {gperf_offsetof(stringpool, 284),32400},
-#line 175 "zonetab.list"
- {gperf_offsetof(stringpool, 285), 28800},
-#line 134 "zonetab.list"
- {gperf_offsetof(stringpool, 286), 7200},
-#line 149 "zonetab.list"
- {gperf_offsetof(stringpool, 287), 23400},
-#line 107 "zonetab.list"
- {gperf_offsetof(stringpool, 288),13*3600},
-#line 230 "zonetab.list"
- {gperf_offsetof(stringpool, 289),-10800},
-#line 307 "zonetab.list"
- {gperf_offsetof(stringpool, 290),18000},
+#line 300 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str284,32400},
+#line 178 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str285, 28800},
+#line 137 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str286, 7200},
+#line 152 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str287, 23400},
+#line 110 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str288,13*3600},
+#line 233 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str289,-10800},
+#line 310 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str290,18000},
{-1}, {-1},
-#line 155 "zonetab.list"
- {gperf_offsetof(stringpool, 293), 25200},
-#line 258 "zonetab.list"
- {gperf_offsetof(stringpool, 294),18000},
-#line 227 "zonetab.list"
- {gperf_offsetof(stringpool, 295),-21600},
+#line 158 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str293, 25200},
#line 261 "zonetab.list"
- {gperf_offsetof(stringpool, 296),43200},
-#line 213 "zonetab.list"
- {gperf_offsetof(stringpool, 297),-3600},
-#line 154 "zonetab.list"
- {gperf_offsetof(stringpool, 298), 28800},
- {-1},
-#line 243 "zonetab.list"
- {gperf_offsetof(stringpool, 300),21600},
-#line 114 "zonetab.list"
- {gperf_offsetof(stringpool, 301), 34200},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str294,18000},
+#line 230 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str295,-21600},
+#line 264 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str296,43200},
+#line 216 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str297,-3600},
#line 157 "zonetab.list"
- {gperf_offsetof(stringpool, 302), -28800},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str298, 28800},
{-1},
+#line 246 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str300,21600},
#line 117 "zonetab.list"
- {gperf_offsetof(stringpool, 304), -21600},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str301, 34200},
+#line 160 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str302, -28800},
{-1},
-#line 156 "zonetab.list"
- {gperf_offsetof(stringpool, 306), -14400},
-#line 116 "zonetab.list"
- {gperf_offsetof(stringpool, 307), -3600},
-#line 228 "zonetab.list"
- {gperf_offsetof(stringpool, 308),-32400},
-#line 294 "zonetab.list"
- {gperf_offsetof(stringpool, 309),18000},
-#line 37 "zonetab.list"
- {gperf_offsetof(stringpool, 310), -5*3600},
-#line 137 "zonetab.list"
- {gperf_offsetof(stringpool, 311), 7200},
-#line 58 "zonetab.list"
- {gperf_offsetof(stringpool, 312),-8*3600},
-#line 304 "zonetab.list"
- {gperf_offsetof(stringpool, 313),28800},
-#line 303 "zonetab.list"
- {gperf_offsetof(stringpool, 314),32400},
-#line 284 "zonetab.list"
- {gperf_offsetof(stringpool, 315),14400},
+#line 120 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str304, -21600},
{-1},
-#line 295 "zonetab.list"
- {gperf_offsetof(stringpool, 317),18000},
+#line 159 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str306, -14400},
+#line 119 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str307, -3600},
+#line 231 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str308,-32400},
+#line 297 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str309,18000},
+#line 40 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str310, -5*3600},
+#line 140 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str311, 7200},
+#line 61 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str312,-8*3600},
+#line 307 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str313,28800},
+#line 306 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str314,32400},
+#line 287 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str315,14400},
{-1},
-#line 166 "zonetab.list"
- {gperf_offsetof(stringpool, 319), 7200},
+#line 298 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str317,18000},
+ {-1},
+#line 169 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str319, 7200},
{-1}, {-1}, {-1}, {-1},
-#line 97 "zonetab.list"
- {gperf_offsetof(stringpool, 324), 8*3600},
+#line 100 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str324, 8*3600},
{-1},
-#line 50 "zonetab.list"
- {gperf_offsetof(stringpool, 326), -(1*3600+1800)},
-#line 285 "zonetab.list"
- {gperf_offsetof(stringpool, 327),-10800},
+#line 53 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str326, -(1*3600+1800)},
+#line 288 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str327,-10800},
{-1}, {-1},
-#line 287 "zonetab.list"
- {gperf_offsetof(stringpool, 330),14400},
+#line 290 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str330,14400},
{-1},
-#line 169 "zonetab.list"
- {gperf_offsetof(stringpool, 332), 36000},
+#line 172 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str332, 36000},
{-1},
-#line 235 "zonetab.list"
- {gperf_offsetof(stringpool, 334),25200},
-#line 234 "zonetab.list"
- {gperf_offsetof(stringpool, 335),28800},
+#line 238 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str334,25200},
+#line 237 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str335,28800},
{-1}, {-1},
-#line 232 "zonetab.list"
- {gperf_offsetof(stringpool, 338),-14400},
+#line 235 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str338,-14400},
{-1}, {-1}, {-1},
-#line 44 "zonetab.list"
- {gperf_offsetof(stringpool, 342), -12*3600},
-#line 61 "zonetab.list"
- {gperf_offsetof(stringpool, 343),-9*3600},
-#line 162 "zonetab.list"
- {gperf_offsetof(stringpool, 344), -14400},
-#line 141 "zonetab.list"
- {gperf_offsetof(stringpool, 345), -36000},
+#line 47 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str342, -12*3600},
+#line 64 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str343,-9*3600},
+#line 165 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str344, -14400},
+#line 144 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str345, -36000},
{-1},
-#line 306 "zonetab.list"
- {gperf_offsetof(stringpool, 347),-10800},
+#line 309 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str347,-10800},
{-1},
-#line 305 "zonetab.list"
- {gperf_offsetof(stringpool, 349),-7200},
+#line 308 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str349,-7200},
+#line 329 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str350,18000},
+#line 328 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str351,21600},
+#line 250 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str352,14400},
#line 326 "zonetab.list"
- {gperf_offsetof(stringpool, 350),18000},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str353,32400},
#line 325 "zonetab.list"
- {gperf_offsetof(stringpool, 351),21600},
-#line 247 "zonetab.list"
- {gperf_offsetof(stringpool, 352),14400},
-#line 323 "zonetab.list"
- {gperf_offsetof(stringpool, 353),32400},
-#line 322 "zonetab.list"
- {gperf_offsetof(stringpool, 354),36000},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str354,36000},
{-1}, {-1}, {-1},
-#line 63 "zonetab.list"
- {gperf_offsetof(stringpool, 358), -9*3600},
-#line 144 "zonetab.list"
- {gperf_offsetof(stringpool, 359), 7200},
+#line 66 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str358, -9*3600},
+#line 147 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str359, 7200},
{-1}, {-1}, {-1}, {-1}, {-1},
-#line 167 "zonetab.list"
- {gperf_offsetof(stringpool, 365), 21600},
+#line 170 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str365, 21600},
{-1},
-#line 180 "zonetab.list"
- {gperf_offsetof(stringpool, 367), 32400},
+#line 183 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str367, 32400},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
-#line 318 "zonetab.list"
- {gperf_offsetof(stringpool, 375),25200},
+#line 321 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str375,25200},
{-1},
-#line 115 "zonetab.list"
- {gperf_offsetof(stringpool, 377), 36000},
-#line 231 "zonetab.list"
- {gperf_offsetof(stringpool, 378),43200},
+#line 118 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str377, 36000},
+#line 234 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str378,43200},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
-#line 173 "zonetab.list"
- {gperf_offsetof(stringpool, 387), -25200},
+#line 176 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str387, -25200},
{-1}, {-1}, {-1},
-#line 310 "zonetab.list"
- {gperf_offsetof(stringpool, 391),36000},
-#line 309 "zonetab.list"
- {gperf_offsetof(stringpool, 392),39600},
+#line 313 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str391,36000},
+#line 312 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str392,39600},
{-1}, {-1},
-#line 140 "zonetab.list"
- {gperf_offsetof(stringpool, 395), 7200},
+#line 143 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str395, 7200},
{-1}, {-1},
-#line 168 "zonetab.list"
- {gperf_offsetof(stringpool, 398), 28800},
-#line 290 "zonetab.list"
- {gperf_offsetof(stringpool, 399),39600},
+#line 171 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str398, 28800},
+#line 293 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str399,39600},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
-#line 118 "zonetab.list"
- {gperf_offsetof(stringpool, 408), -3600},
+#line 121 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str408, -3600},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
-#line 296 "zonetab.list"
- {gperf_offsetof(stringpool, 417),46800},
-#line 163 "zonetab.list"
- {gperf_offsetof(stringpool, 418), -39600},
+#line 299 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str417,46800},
+#line 166 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str418, -39600},
{-1}, {-1},
-#line 161 "zonetab.list"
- {gperf_offsetof(stringpool, 421), -18000},
+#line 164 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str421, -18000},
{-1}, {-1}, {-1}, {-1}, {-1},
-#line 312 "zonetab.list"
- {gperf_offsetof(stringpool, 427),39600},
-#line 69 "zonetab.list"
- {gperf_offsetof(stringpool, 428),-12*3600},
+#line 315 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str427,39600},
+#line 72 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str428,-12*3600},
{-1}, {-1}, {-1},
-#line 136 "zonetab.list"
- {gperf_offsetof(stringpool, 432), 43200},
+#line 139 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str432, 43200},
{-1}, {-1},
-#line 46 "zonetab.list"
- {gperf_offsetof(stringpool, 435), 0*3600},
+#line 49 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str435, 0*3600},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
-#line 145 "zonetab.list"
- {gperf_offsetof(stringpool, 443), 32400},
+#line 148 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str443, 32400},
{-1},
-#line 131 "zonetab.list"
- {gperf_offsetof(stringpool, 445), 7200},
+#line 134 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str445, 7200},
{-1}, {-1}, {-1},
-#line 292 "zonetab.list"
- {gperf_offsetof(stringpool, 449),10800},
+#line 295 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str449,10800},
{-1}, {-1},
-#line 150 "zonetab.list"
- {gperf_offsetof(stringpool, 452), 21600},
+#line 153 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str452, 21600},
{-1}, {-1},
-#line 302 "zonetab.list"
- {gperf_offsetof(stringpool, 455),43200},
+#line 305 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str455,43200},
{-1}, {-1},
-#line 176 "zonetab.list"
- {gperf_offsetof(stringpool, 458), 3600},
+#line 179 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str458, 3600},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
-#line 135 "zonetab.list"
- {gperf_offsetof(stringpool, 466), 18000},
+#line 138 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str466, 18000},
{-1},
-#line 174 "zonetab.list"
- {gperf_offsetof(stringpool, 468), 36000},
+#line 177 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str468, 36000},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
-#line 324 "zonetab.list"
- {gperf_offsetof(stringpool, 476),36000},
-#line 172 "zonetab.list"
- {gperf_offsetof(stringpool, 477), -18000},
+#line 327 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str476,36000},
+#line 175 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str477, -18000},
{-1}, {-1}, {-1}, {-1},
-#line 160 "zonetab.list"
- {gperf_offsetof(stringpool, 482), -10800},
+#line 163 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str482, -10800},
{-1}, {-1},
-#line 62 "zonetab.list"
- {gperf_offsetof(stringpool, 485), -9*3600},
-#line 159 "zonetab.list"
- {gperf_offsetof(stringpool, 486), 10800},
+#line 65 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str485, -9*3600},
+#line 162 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str486, 10800},
{-1}, {-1}, {-1}, {-1}, {-1},
-#line 233 "zonetab.list"
- {gperf_offsetof(stringpool, 492),28800},
+#line 236 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str492,28800},
{-1}, {-1}, {-1}, {-1},
-#line 158 "zonetab.list"
- {gperf_offsetof(stringpool, 497), 3600},
+#line 161 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str497, 3600},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
-#line 177 "zonetab.list"
- {gperf_offsetof(stringpool, 540), 3600},
+#line 180 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str540, 3600},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1},
-#line 59 "zonetab.list"
- {gperf_offsetof(stringpool, 563), -8*3600},
+#line 62 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str563, -8*3600},
{-1}, {-1},
-#line 104 "zonetab.list"
- {gperf_offsetof(stringpool, 566),12*3600},
-#line 139 "zonetab.list"
- {gperf_offsetof(stringpool, 567), 0},
+#line 107 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str566,12*3600},
+#line 142 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str567, 0},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
-#line 138 "zonetab.list"
- {gperf_offsetof(stringpool, 619), -10800}
+#line 141 "zonetab.list"
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str619, -10800}
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
@@ -1558,5 +1560,5 @@ zonetab (register const char *str, register size_t len)
}
return 0;
}
-#line 327 "zonetab.list"
+#line 330 "zonetab.list"
diff --git a/ext/date/zonetab.list b/ext/date/zonetab.list
index 748aec1d8a..63b6873447 100644
--- a/ext/date/zonetab.list
+++ b/ext/date/zonetab.list
@@ -1,4 +1,7 @@
%{
+#define GPERF_DOWNCASE 1
+#define GPERF_CASE_STRNCMP 1
+#define gperf_case_strncmp strncasecmp
struct zone {
int name;
int offset;
@@ -313,8 +316,8 @@ vut,39600
wakt,43200
warst,-10800
wft,43200
-wgst,-7200
-wgt,-10800
+wgst,-3600
+wgt,-7200
wib,25200
wit,32400
wita,28800
diff --git a/ext/digest/bubblebabble/depend b/ext/digest/bubblebabble/depend
index 0da9c223ee..02d88e960c 100644
--- a/ext/digest/bubblebabble/depend
+++ b/ext/digest/bubblebabble/depend
@@ -128,6 +128,7 @@ bubblebabble.o: $(hdrdir)/ruby/internal/intern/re.h
bubblebabble.o: $(hdrdir)/ruby/internal/intern/ruby.h
bubblebabble.o: $(hdrdir)/ruby/internal/intern/select.h
bubblebabble.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+bubblebabble.o: $(hdrdir)/ruby/internal/intern/set.h
bubblebabble.o: $(hdrdir)/ruby/internal/intern/signal.h
bubblebabble.o: $(hdrdir)/ruby/internal/intern/sprintf.h
bubblebabble.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/digest/defs.h b/ext/digest/defs.h
index 77a134f364..9b11f4eca9 100644
--- a/ext/digest/defs.h
+++ b/ext/digest/defs.h
@@ -16,4 +16,26 @@
# define __END_DECLS
#endif
+#define RB_DIGEST_DIAGNOSTIC(compiler, op, flag) _Pragma(STRINGIZE(compiler diagnostic op flag))
+#ifdef RBIMPL_WARNING_IGNORED
+# define RB_DIGEST_WARNING_IGNORED(flag) RBIMPL_WARNING_IGNORED(flag)
+# define RB_DIGEST_WARNING_PUSH() RBIMPL_WARNING_PUSH()
+# define RB_DIGEST_WARNING_POP() RBIMPL_WARNING_POP()
+#elif defined(__clang__)
+# define RB_DIGEST_WARNING_IGNORED(flag) RB_DIGEST_DIAGNOSTIC(clang, ignored, #flag)
+# define RB_DIGEST_WARNING_PUSH() _Pragma("clang diagnostic push")
+# define RB_DIGEST_WARNING_POP() _Pragma("clang diagnostic pop")
+#else /* __GNUC__ */
+# define RB_DIGEST_WARNING_IGNORED(flag) RB_DIGEST_DIAGNOSTIC(GCC, ignored, #flag)
+# define RB_DIGEST_WARNING_PUSH() _Pragma("GCC diagnostic push")
+# define RB_DIGEST_WARNING_POP() _Pragma("GCC diagnostic pop")
+#endif
+#ifdef RBIMPL_HAS_WARNING
+# define RB_DIGEST_HAS_WARNING(_) RBIMPL_HAS_WARNING(_)
+#elif defined(__has_warning)
+# define RB_DIGEST_HAS_WARNING(_) __has_warning(_)
+#else
+# define RB_DIGEST_HAS_WARNING(_) 0
+#endif
+
#endif /* DEFS_H */
diff --git a/ext/digest/depend b/ext/digest/depend
index cb9e8d4813..3eabb1d1d6 100644
--- a/ext/digest/depend
+++ b/ext/digest/depend
@@ -128,6 +128,7 @@ digest.o: $(hdrdir)/ruby/internal/intern/re.h
digest.o: $(hdrdir)/ruby/internal/intern/ruby.h
digest.o: $(hdrdir)/ruby/internal/intern/select.h
digest.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+digest.o: $(hdrdir)/ruby/internal/intern/set.h
digest.o: $(hdrdir)/ruby/internal/intern/signal.h
digest.o: $(hdrdir)/ruby/internal/intern/sprintf.h
digest.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/digest/digest.c b/ext/digest/digest.c
index 68837a674c..bd8d3e815f 100644
--- a/ext/digest/digest.c
+++ b/ext/digest/digest.c
@@ -534,9 +534,39 @@ rb_digest_class_init(VALUE self)
*
*
* rb_ivar_set(cDigest_SHA1, rb_intern("metadata"),
- * Data_Wrap_Struct(0, 0, 0, (void *)&sha1));
+ * rb_digest_make_metadata(&sha1));
*/
+#ifdef DIGEST_USE_RB_EXT_RESOLVE_SYMBOL
+static const rb_data_type_t metadata_type = {
+ "digest/metadata",
+ {0},
+};
+
+RUBY_FUNC_EXPORTED VALUE
+rb_digest_wrap_metadata(const rb_digest_metadata_t *meta)
+{
+ return rb_obj_freeze(TypedData_Wrap_Struct(0, &metadata_type, (void *)meta));
+}
+#endif
+
+static rb_digest_metadata_t *
+get_metadata_ptr(VALUE obj)
+{
+ rb_digest_metadata_t *algo;
+
+#ifdef DIGEST_USE_RB_EXT_RESOLVE_SYMBOL
+ if (!rb_typeddata_is_kind_of(obj, &metadata_type)) return 0;
+ algo = RTYPEDDATA_DATA(obj);
+#else
+# undef RUBY_UNTYPED_DATA_WARNING
+# define RUBY_UNTYPED_DATA_WARNING 0
+ Data_Get_Struct(obj, rb_digest_metadata_t, algo);
+#endif
+
+ return algo;
+}
+
static rb_digest_metadata_t *
get_digest_base_metadata(VALUE klass)
{
@@ -554,8 +584,8 @@ get_digest_base_metadata(VALUE klass)
if (NIL_P(p))
rb_raise(rb_eRuntimeError, "Digest::Base cannot be directly inherited in Ruby");
- if (!RB_TYPE_P(obj, T_DATA) || RTYPEDDATA_P(obj)) {
- wrong:
+ algo = get_metadata_ptr(obj);
+ if (!algo) {
if (p == klass)
rb_raise(rb_eTypeError, "%"PRIsVALUE"::metadata is not initialized properly",
klass);
@@ -564,12 +594,6 @@ get_digest_base_metadata(VALUE klass)
klass, p);
}
-#undef RUBY_UNTYPED_DATA_WARNING
-#define RUBY_UNTYPED_DATA_WARNING 0
- Data_Get_Struct(obj, rb_digest_metadata_t, algo);
-
- if (!algo) goto wrong;
-
switch (algo->api_version) {
case 3:
break;
diff --git a/ext/digest/digest.h b/ext/digest/digest.h
index 68a3da5dd2..c5c37583a6 100644
--- a/ext/digest/digest.h
+++ b/ext/digest/digest.h
@@ -64,10 +64,43 @@ rb_id_metadata(void)
return rb_intern_const("metadata");
}
+#if !defined(HAVE_RB_EXT_RESOLVE_SYMBOL)
+#elif !defined(RUBY_UNTYPED_DATA_WARNING)
+# error RUBY_UNTYPED_DATA_WARNING is not defined
+#elif RUBY_UNTYPED_DATA_WARNING
+/* rb_ext_resolve_symbol() has been defined since Ruby 3.3, but digest
+ * bundled with 3.3 didn't use it. */
+# define DIGEST_USE_RB_EXT_RESOLVE_SYMBOL 1
+#endif
+
static inline VALUE
rb_digest_make_metadata(const rb_digest_metadata_t *meta)
{
-#undef RUBY_UNTYPED_DATA_WARNING
-#define RUBY_UNTYPED_DATA_WARNING 0
+#if defined(EXTSTATIC) && EXTSTATIC
+ /* The extension is built as a static library, so safe to refer to
+ * rb_digest_wrap_metadata directly. */
+ extern VALUE rb_digest_wrap_metadata(const rb_digest_metadata_t *meta);
+ return rb_digest_wrap_metadata(meta);
+#else
+ /* The extension is built as a shared library, so we can't refer
+ * to rb_digest_wrap_metadata directly. */
+# ifdef DIGEST_USE_RB_EXT_RESOLVE_SYMBOL
+ /* If rb_ext_resolve_symbol() is available, use it to get the address of
+ * rb_digest_wrap_metadata. */
+ typedef VALUE (*wrapper_func_type)(const rb_digest_metadata_t *meta);
+ static wrapper_func_type wrapper;
+ if (!wrapper) {
+ wrapper = (wrapper_func_type)(uintptr_t)
+ rb_ext_resolve_symbol("digest.so", "rb_digest_wrap_metadata");
+ if (!wrapper) rb_raise(rb_eLoadError, "rb_digest_wrap_metadata not found");
+ }
+ return wrapper(meta);
+# else
+ /* If rb_ext_resolve_symbol() is not available, keep using untyped
+ * data. */
+# undef RUBY_UNTYPED_DATA_WARNING
+# define RUBY_UNTYPED_DATA_WARNING 0
return rb_obj_freeze(Data_Wrap_Struct(0, 0, 0, (void *)meta));
+# endif
+#endif
}
diff --git a/ext/digest/digest_conf.rb b/ext/digest/digest_conf.rb
index 36a7d75289..099d20fcbe 100644
--- a/ext/digest/digest_conf.rb
+++ b/ext/digest/digest_conf.rb
@@ -2,14 +2,16 @@
def digest_conf(name)
unless with_config("bundled-#{name}")
- cc = with_config("common-digest")
- if cc != false or /\b#{name}\b/ =~ cc
- if File.exist?("#$srcdir/#{name}cc.h") and
- have_header("CommonCrypto/CommonDigest.h")
- $defs << "-D#{name.upcase}_USE_COMMONDIGEST"
- $headers << "#{name}cc.h"
- return :commondigest
- end
+ case cc = with_config("common-digest", true)
+ when true, false
+ else
+ cc = cc.split(/[\s,]++/).any? {|pat| File.fnmatch?(pat, name)}
+ end
+ if cc and File.exist?("#$srcdir/#{name}cc.h") and
+ have_header("CommonCrypto/CommonDigest.h")
+ $defs << "-D#{name.upcase}_USE_COMMONDIGEST"
+ $headers << "#{name}cc.h"
+ return :commondigest
end
end
$objs << "#{name}.#{$OBJEXT}"
diff --git a/ext/digest/lib/digest/version.rb b/ext/digest/lib/digest/version.rb
index 42fd7acf6e..a56e80c54e 100644
--- a/ext/digest/lib/digest/version.rb
+++ b/ext/digest/lib/digest/version.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
module Digest
- VERSION = "3.1.1"
+ # The version string
+ VERSION = "3.2.1"
end
diff --git a/ext/digest/md5/depend b/ext/digest/md5/depend
index e71915e5b4..d1c25c28c8 100644
--- a/ext/digest/md5/depend
+++ b/ext/digest/md5/depend
@@ -131,6 +131,7 @@ md5.o: $(hdrdir)/ruby/internal/intern/re.h
md5.o: $(hdrdir)/ruby/internal/intern/ruby.h
md5.o: $(hdrdir)/ruby/internal/intern/select.h
md5.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+md5.o: $(hdrdir)/ruby/internal/intern/set.h
md5.o: $(hdrdir)/ruby/internal/intern/signal.h
md5.o: $(hdrdir)/ruby/internal/intern/sprintf.h
md5.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -293,6 +294,7 @@ md5init.o: $(hdrdir)/ruby/internal/intern/re.h
md5init.o: $(hdrdir)/ruby/internal/intern/ruby.h
md5init.o: $(hdrdir)/ruby/internal/intern/select.h
md5init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+md5init.o: $(hdrdir)/ruby/internal/intern/set.h
md5init.o: $(hdrdir)/ruby/internal/intern/signal.h
md5init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
md5init.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/digest/md5/md5cc.h b/ext/digest/md5/md5cc.h
index e34d7d5c11..a002c17604 100644
--- a/ext/digest/md5/md5cc.h
+++ b/ext/digest/md5/md5cc.h
@@ -1,8 +1,8 @@
#define COMMON_DIGEST_FOR_OPENSSL 1
#include <CommonCrypto/CommonDigest.h>
-#ifdef __clang__
-# pragma clang diagnostic ignored "-Wdeprecated-declarations"
+#ifdef __GNUC__
+RB_DIGEST_WARNING_IGNORED(-Wdeprecated-declarations)
/* Suppress deprecation warnings of MD5 from Xcode 11.1 */
/* Although we know MD5 is deprecated too, provide just for backward
* compatibility, as well as Apple does. */
@@ -17,3 +17,11 @@ static DEFINE_FINISH_FUNC_FROM_FINAL(MD5)
#undef MD5_Finish
#define MD5_Update rb_digest_MD5_update
#define MD5_Finish rb_digest_MD5_finish
+
+/*
+ * Pre-10.6 defines are with args, which don't match the argless use in
+ * the function pointer inits. Thus, we redefine MD5_Init as well.
+ * This is a NOP on 10.6+.
+ */
+#undef MD5_Init
+#define MD5_Init CC_MD5_Init
diff --git a/ext/digest/md5/md5init.c b/ext/digest/md5/md5init.c
index b81fd94864..c919060587 100644
--- a/ext/digest/md5/md5init.c
+++ b/ext/digest/md5/md5init.c
@@ -3,6 +3,7 @@
#include <ruby/ruby.h>
#include "../digest.h"
+#include "../defs.h"
#if defined(MD5_USE_COMMONDIGEST)
#include "md5cc.h"
#else
diff --git a/ext/digest/rmd160/depend b/ext/digest/rmd160/depend
index 09558ad92b..aec484f7b3 100644
--- a/ext/digest/rmd160/depend
+++ b/ext/digest/rmd160/depend
@@ -131,6 +131,7 @@ rmd160.o: $(hdrdir)/ruby/internal/intern/re.h
rmd160.o: $(hdrdir)/ruby/internal/intern/ruby.h
rmd160.o: $(hdrdir)/ruby/internal/intern/select.h
rmd160.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+rmd160.o: $(hdrdir)/ruby/internal/intern/set.h
rmd160.o: $(hdrdir)/ruby/internal/intern/signal.h
rmd160.o: $(hdrdir)/ruby/internal/intern/sprintf.h
rmd160.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -293,6 +294,7 @@ rmd160init.o: $(hdrdir)/ruby/internal/intern/re.h
rmd160init.o: $(hdrdir)/ruby/internal/intern/ruby.h
rmd160init.o: $(hdrdir)/ruby/internal/intern/select.h
rmd160init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+rmd160init.o: $(hdrdir)/ruby/internal/intern/set.h
rmd160init.o: $(hdrdir)/ruby/internal/intern/signal.h
rmd160init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
rmd160init.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/digest/sha1/depend b/ext/digest/sha1/depend
index 827b8a0852..e6bd9d8f73 100644
--- a/ext/digest/sha1/depend
+++ b/ext/digest/sha1/depend
@@ -131,6 +131,7 @@ sha1.o: $(hdrdir)/ruby/internal/intern/re.h
sha1.o: $(hdrdir)/ruby/internal/intern/ruby.h
sha1.o: $(hdrdir)/ruby/internal/intern/select.h
sha1.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+sha1.o: $(hdrdir)/ruby/internal/intern/set.h
sha1.o: $(hdrdir)/ruby/internal/intern/signal.h
sha1.o: $(hdrdir)/ruby/internal/intern/sprintf.h
sha1.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -293,6 +294,7 @@ sha1init.o: $(hdrdir)/ruby/internal/intern/re.h
sha1init.o: $(hdrdir)/ruby/internal/intern/ruby.h
sha1init.o: $(hdrdir)/ruby/internal/intern/select.h
sha1init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+sha1init.o: $(hdrdir)/ruby/internal/intern/set.h
sha1init.o: $(hdrdir)/ruby/internal/intern/signal.h
sha1init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
sha1init.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/digest/sha1/sha1.c b/ext/digest/sha1/sha1.c
index 5311227549..ce200270b7 100644
--- a/ext/digest/sha1/sha1.c
+++ b/ext/digest/sha1/sha1.c
@@ -232,8 +232,14 @@ void SHA1_Update(SHA1_CTX *context, const uint8_t *data, size_t len)
if ((j + len) > 63) {
(void)memcpy(&context->buffer[j], data, (i = 64-j));
SHA1_Transform(context->state, context->buffer);
- for ( ; i + 63 < len; i += 64)
+ for ( ; i + 63 < len; i += 64) {
+ RB_DIGEST_WARNING_PUSH();
+#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 11
+ RB_DIGEST_WARNING_IGNORED(-Wstringop-overread);
+#endif
SHA1_Transform(context->state, &data[i]);
+ RB_DIGEST_WARNING_POP();
+ }
j = 0;
} else {
i = 0;
diff --git a/ext/digest/sha1/sha1cc.h b/ext/digest/sha1/sha1cc.h
index 2ed8d646ab..f39ecc6234 100644
--- a/ext/digest/sha1/sha1cc.h
+++ b/ext/digest/sha1/sha1cc.h
@@ -12,3 +12,11 @@ static DEFINE_FINISH_FUNC_FROM_FINAL(SHA1)
#undef SHA1_Finish
#define SHA1_Update rb_digest_SHA1_update
#define SHA1_Finish rb_digest_SHA1_finish
+
+/*
+ * Pre-10.6 defines are with args, which don't match the argless use in
+ * the function pointer inits. Thus, we redefine SHA1_Init as well.
+ * This is a NOP on 10.6+.
+ */
+#undef SHA1_Init
+#define SHA1_Init CC_SHA1_Init
diff --git a/ext/digest/sha2/depend b/ext/digest/sha2/depend
index af1600d346..2b74776b3e 100644
--- a/ext/digest/sha2/depend
+++ b/ext/digest/sha2/depend
@@ -131,6 +131,7 @@ sha2.o: $(hdrdir)/ruby/internal/intern/re.h
sha2.o: $(hdrdir)/ruby/internal/intern/ruby.h
sha2.o: $(hdrdir)/ruby/internal/intern/select.h
sha2.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+sha2.o: $(hdrdir)/ruby/internal/intern/set.h
sha2.o: $(hdrdir)/ruby/internal/intern/signal.h
sha2.o: $(hdrdir)/ruby/internal/intern/sprintf.h
sha2.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -293,6 +294,7 @@ sha2init.o: $(hdrdir)/ruby/internal/intern/re.h
sha2init.o: $(hdrdir)/ruby/internal/intern/ruby.h
sha2init.o: $(hdrdir)/ruby/internal/intern/select.h
sha2init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+sha2init.o: $(hdrdir)/ruby/internal/intern/set.h
sha2init.o: $(hdrdir)/ruby/internal/intern/signal.h
sha2init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
sha2init.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/digest/sha2/sha2cc.h b/ext/digest/sha2/sha2cc.h
index 3f99604465..1245a2e2c7 100644
--- a/ext/digest/sha2/sha2cc.h
+++ b/ext/digest/sha2/sha2cc.h
@@ -1,6 +1,33 @@
#define COMMON_DIGEST_FOR_OPENSSL 1
#include <CommonCrypto/CommonDigest.h>
+/*
+ * Prior to 10.5, OpenSSL-compatible definitions are missing for
+ * SHA2 macros, though the CC_ versions are present.
+ * Add the missing definitions we actually use here if needed.
+ * Note that the definitions are the argless 10.6+-style.
+ * The weird CTX mismatch is copied from the 10.6 header.
+ */
+#ifndef SHA256_DIGEST_LENGTH
+#define SHA256_DIGEST_LENGTH CC_SHA256_DIGEST_LENGTH
+#define SHA256_CTX CC_SHA256_CTX
+#define SHA256_Update CC_SHA256_Update
+#define SHA256_Final CC_SHA256_Final
+#endif /* !defined SHA256_DIGEST_LENGTH */
+
+#ifndef SHA384_DIGEST_LENGTH
+#define SHA384_DIGEST_LENGTH CC_SHA384_DIGEST_LENGTH
+#define SHA512_CTX CC_SHA512_CTX
+#define SHA384_Update CC_SHA384_Update
+#define SHA384_Final CC_SHA384_Final
+#endif /* !defined SHA384_DIGEST_LENGTH */
+
+#ifndef SHA512_DIGEST_LENGTH
+#define SHA512_DIGEST_LENGTH CC_SHA512_DIGEST_LENGTH
+#define SHA512_Update CC_SHA512_Update
+#define SHA512_Final CC_SHA512_Final
+#endif /* !defined SHA512_DIGEST_LENGTH */
+
#define SHA256_BLOCK_LENGTH CC_SHA256_BLOCK_BYTES
#define SHA384_BLOCK_LENGTH CC_SHA384_BLOCK_BYTES
#define SHA512_BLOCK_LENGTH CC_SHA512_BLOCK_BYTES
@@ -29,3 +56,15 @@ static DEFINE_FINISH_FUNC_FROM_FINAL(SHA512)
#undef SHA512_Finish
#define SHA512_Update rb_digest_SHA512_update
#define SHA512_Finish rb_digest_SHA512_finish
+
+/*
+ * Pre-10.6 defines are with args, which don't match the argless use in
+ * the function pointer inits. Thus, we redefine SHA*_Init as well.
+ * This is a NOP on 10.6+.
+ */
+#undef SHA256_Init
+#define SHA256_Init CC_SHA256_Init
+#undef SHA384_Init
+#define SHA384_Init CC_SHA384_Init
+#undef SHA512_Init
+#define SHA512_Init CC_SHA512_Init
diff --git a/ext/digest/test.sh b/ext/digest/test.sh
deleted file mode 100644
index 328c7575e6..0000000000
--- a/ext/digest/test.sh
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/sh
-#
-# $RoughId: test.sh,v 1.5 2001/07/13 15:38:27 knu Exp $
-# $Id$
-
-RUBY=${RUBY:=ruby}
-MAKE=${MAKE:=make}
-CFLAGS=${CFLAGS:=-Wall}
-
-${RUBY} extconf.rb --with-cflags="${CFLAGS}"
-${MAKE} clean
-${MAKE}
-
-for algo in md5 rmd160 sha1 sha2; do
- args=--with-cflags="${CFLAGS}"
-
- if [ $WITH_BUNDLED_ENGINES ]; then
- args="$args --with-bundled-$algo"
- fi
-
- (cd $algo &&
- ${RUBY} extconf.rb $args;
- ${MAKE} clean;
- ${MAKE})
- ln -sf ../../$algo/$algo.so lib/digest/
-done
-
-${RUBY} -I. -I./lib ../../test/digest/test_digest.rb
-
-rm lib/digest/*.so
diff --git a/ext/erb/escape/escape.c b/ext/erb/escape/escape.c
index 67b2d1ef34..1794fc30eb 100644
--- a/ext/erb/escape/escape.c
+++ b/ext/erb/escape/escape.c
@@ -39,35 +39,50 @@ static VALUE
optimized_escape_html(VALUE str)
{
VALUE vbuf;
- char *buf = ALLOCV_N(char, vbuf, escaped_length(str));
+ char *buf = NULL;
const char *cstr = RSTRING_PTR(str);
const char *end = cstr + RSTRING_LEN(str);
- char *dest = buf;
+ const char *segment_start = cstr;
+ char *dest = NULL;
while (cstr < end) {
const unsigned char c = *cstr++;
uint8_t len = html_escape_table[c].len;
if (len) {
+ size_t segment_len = cstr - segment_start - 1;
+ if (!buf) {
+ buf = ALLOCV_N(char, vbuf, escaped_length(str));
+ dest = buf;
+ }
+ if (segment_len) {
+ memcpy(dest, segment_start, segment_len);
+ dest += segment_len;
+ }
+ segment_start = cstr;
memcpy(dest, html_escape_table[c].str, len);
dest += len;
}
- else {
- *dest++ = c;
- }
}
-
VALUE escaped = str;
- if (RSTRING_LEN(str) < (dest - buf)) {
+ if (buf) {
+ size_t segment_len = cstr - segment_start;
+ if (segment_len) {
+ memcpy(dest, segment_start, segment_len);
+ dest += segment_len;
+ }
escaped = rb_str_new(buf, dest - buf);
preserve_original_state(str, escaped);
+ ALLOCV_END(vbuf);
}
- ALLOCV_END(vbuf);
return escaped;
}
-// ERB::Util.html_escape is different from CGI.escapeHTML in the following two parts:
-// * ERB::Util.html_escape converts an argument with #to_s first (only if it's not T_STRING)
-// * ERB::Util.html_escape does not allocate a new string when nothing needs to be escaped
+/*
+ * ERB::Util.html_escape is similar to CGI.escapeHTML but different in the following two parts:
+ *
+ * * ERB::Util.html_escape converts an argument with #to_s first (only if it's not T_STRING)
+ * * ERB::Util.html_escape does not allocate a new string when nothing needs to be escaped
+ */
static VALUE
erb_escape_html(VALUE self, VALUE str)
{
@@ -86,6 +101,10 @@ erb_escape_html(VALUE self, VALUE str)
void
Init_escape(void)
{
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
+
rb_cERB = rb_define_class("ERB", rb_cObject);
rb_mEscape = rb_define_module_under(rb_cERB, "Escape");
rb_define_module_function(rb_mEscape, "html_escape", erb_escape_html, 1);
diff --git a/ext/erb/escape/extconf.rb b/ext/erb/escape/extconf.rb
index 783e8c1f55..b211a9783f 100644
--- a/ext/erb/escape/extconf.rb
+++ b/ext/erb/escape/extconf.rb
@@ -4,5 +4,6 @@ case RUBY_ENGINE
when 'jruby', 'truffleruby'
File.write('Makefile', dummy_makefile($srcdir).join)
else
+ have_func("rb_ext_ractor_safe", "ruby.h")
create_makefile 'erb/escape'
end
diff --git a/ext/etc/depend b/ext/etc/depend
index 675699b129..77fe56a6bf 100644
--- a/ext/etc/depend
+++ b/ext/etc/depend
@@ -143,6 +143,7 @@ etc.o: $(hdrdir)/ruby/internal/intern/re.h
etc.o: $(hdrdir)/ruby/internal/intern/ruby.h
etc.o: $(hdrdir)/ruby/internal/intern/select.h
etc.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+etc.o: $(hdrdir)/ruby/internal/intern/set.h
etc.o: $(hdrdir)/ruby/internal/intern/signal.h
etc.o: $(hdrdir)/ruby/internal/intern/sprintf.h
etc.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/etc/etc.c b/ext/etc/etc.c
index fcbd1af1b5..8d50a96a62 100644
--- a/ext/etc/etc.c
+++ b/ext/etc/etc.c
@@ -56,7 +56,9 @@ static VALUE sGroup;
#endif
RUBY_EXTERN char *getlogin(void);
-#define RUBY_ETC_VERSION "1.4.3"
+#define RUBY_ETC_VERSION "1.4.6"
+
+#define SYMBOL_LIT(str) ID2SYM(rb_intern_const(str ""))
#ifdef HAVE_RB_DEPRECATE_CONSTANT
void rb_deprecate_constant(VALUE mod, const char *name);
@@ -691,6 +693,16 @@ etc_getgrent(VALUE obj)
VALUE rb_w32_special_folder(int type);
UINT rb_w32_system_tmpdir(WCHAR *path, UINT len);
VALUE rb_w32_conv_from_wchar(const WCHAR *wstr, rb_encoding *enc);
+#elif defined(LOAD_RELATIVE)
+static inline VALUE
+rbconfig(void)
+{
+ VALUE config;
+ rb_require("rbconfig");
+ config = rb_const_get(rb_path2class("RbConfig"), rb_intern_const("CONFIG"));
+ Check_Type(config, T_HASH);
+ return config;
+}
#endif
/* call-seq:
@@ -710,6 +722,8 @@ etc_sysconfdir(VALUE obj)
{
#ifdef _WIN32
return rb_w32_special_folder(CSIDL_COMMON_APPDATA);
+#elif defined(LOAD_RELATIVE)
+ return rb_hash_aref(rbconfig(), rb_str_new_lit("sysconfdir"));
#else
return rb_filesystem_str_new_cstr(SYSCONFDIR);
#endif
@@ -811,18 +825,14 @@ etc_uname(VALUE obj)
sysname = "Windows";
break;
}
- rb_hash_aset(result, ID2SYM(rb_intern("sysname")), rb_str_new_cstr(sysname));
+ rb_hash_aset(result, SYMBOL_LIT("sysname"), rb_str_new_cstr(sysname));
release = rb_sprintf("%lu.%lu.%lu", v.dwMajorVersion, v.dwMinorVersion, v.dwBuildNumber);
- rb_hash_aset(result, ID2SYM(rb_intern("release")), release);
+ rb_hash_aset(result, SYMBOL_LIT("release"), release);
version = rb_sprintf("%s Version %"PRIsVALUE": %"PRIsVALUE, sysname, release,
rb_w32_conv_from_wchar(v.szCSDVersion, rb_utf8_encoding()));
- rb_hash_aset(result, ID2SYM(rb_intern("version")), version);
+ rb_hash_aset(result, SYMBOL_LIT("version"), version);
-# if defined _MSC_VER && _MSC_VER < 1300
-# define GET_COMPUTER_NAME(ptr, plen) GetComputerNameW(ptr, plen)
-# else
# define GET_COMPUTER_NAME(ptr, plen) GetComputerNameExW(ComputerNameDnsFullyQualified, ptr, plen)
-# endif
GET_COMPUTER_NAME(NULL, &len);
buf = ALLOCV_N(WCHAR, vbuf, len);
if (GET_COMPUTER_NAME(buf, &len)) {
@@ -830,7 +840,7 @@ etc_uname(VALUE obj)
}
ALLOCV_END(vbuf);
if (NIL_P(nodename)) nodename = rb_str_new(0, 0);
- rb_hash_aset(result, ID2SYM(rb_intern("nodename")), nodename);
+ rb_hash_aset(result, SYMBOL_LIT("nodename"), nodename);
# ifndef PROCESSOR_ARCHITECTURE_AMD64
# define PROCESSOR_ARCHITECTURE_AMD64 9
@@ -854,7 +864,7 @@ etc_uname(VALUE obj)
break;
}
- rb_hash_aset(result, ID2SYM(rb_intern("machine")), rb_str_new_cstr(mach));
+ rb_hash_aset(result, SYMBOL_LIT("machine"), rb_str_new_cstr(mach));
#else
struct utsname u;
int ret;
@@ -865,11 +875,11 @@ etc_uname(VALUE obj)
rb_sys_fail("uname");
result = rb_hash_new();
- rb_hash_aset(result, ID2SYM(rb_intern("sysname")), rb_str_new_cstr(u.sysname));
- rb_hash_aset(result, ID2SYM(rb_intern("nodename")), rb_str_new_cstr(u.nodename));
- rb_hash_aset(result, ID2SYM(rb_intern("release")), rb_str_new_cstr(u.release));
- rb_hash_aset(result, ID2SYM(rb_intern("version")), rb_str_new_cstr(u.version));
- rb_hash_aset(result, ID2SYM(rb_intern("machine")), rb_str_new_cstr(u.machine));
+ rb_hash_aset(result, SYMBOL_LIT("sysname"), rb_str_new_cstr(u.sysname));
+ rb_hash_aset(result, SYMBOL_LIT("nodename"), rb_str_new_cstr(u.nodename));
+ rb_hash_aset(result, SYMBOL_LIT("release"), rb_str_new_cstr(u.release));
+ rb_hash_aset(result, SYMBOL_LIT("version"), rb_str_new_cstr(u.version));
+ rb_hash_aset(result, SYMBOL_LIT("machine"), rb_str_new_cstr(u.machine));
#endif
return result;
@@ -1149,14 +1159,26 @@ Init_etc(void)
{
VALUE mEtc;
-#ifdef HAVE_RB_EXT_RACTOR_SAFE
- RB_EXT_RACTOR_SAFE(true);
-#endif
mEtc = rb_define_module("Etc");
/* The version */
rb_define_const(mEtc, "VERSION", rb_str_new_cstr(RUBY_ETC_VERSION));
init_constants(mEtc);
+ /* Ractor-safe methods */
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ RB_EXT_RACTOR_SAFE(true);
+#endif
+ rb_define_module_function(mEtc, "systmpdir", etc_systmpdir, 0);
+ rb_define_module_function(mEtc, "uname", etc_uname, 0);
+ rb_define_module_function(mEtc, "sysconf", etc_sysconf, 1);
+ rb_define_module_function(mEtc, "confstr", etc_confstr, 1);
+ rb_define_method(rb_cIO, "pathconf", io_pathconf, 1);
+ rb_define_module_function(mEtc, "nprocessors", etc_nprocessors, 0);
+
+ /* Non-Ractor-safe methods, see https://bugs.ruby-lang.org/issues/21115 */
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ RB_EXT_RACTOR_SAFE(false);
+#endif
rb_define_module_function(mEtc, "getlogin", etc_getlogin, 0);
rb_define_module_function(mEtc, "getpwuid", etc_getpwuid, -1);
@@ -1172,13 +1194,9 @@ Init_etc(void)
rb_define_module_function(mEtc, "setgrent", etc_setgrent, 0);
rb_define_module_function(mEtc, "endgrent", etc_endgrent, 0);
rb_define_module_function(mEtc, "getgrent", etc_getgrent, 0);
+
+ /* Uses RbConfig::CONFIG so does not work in a Ractor */
rb_define_module_function(mEtc, "sysconfdir", etc_sysconfdir, 0);
- rb_define_module_function(mEtc, "systmpdir", etc_systmpdir, 0);
- rb_define_module_function(mEtc, "uname", etc_uname, 0);
- rb_define_module_function(mEtc, "sysconf", etc_sysconf, 1);
- rb_define_module_function(mEtc, "confstr", etc_confstr, 1);
- rb_define_method(rb_cIO, "pathconf", io_pathconf, 1);
- rb_define_module_function(mEtc, "nprocessors", etc_nprocessors, 0);
sPasswd = rb_struct_define_under(mEtc, "Passwd",
"name",
@@ -1289,4 +1307,8 @@ Init_etc(void)
rb_extend_object(sGroup, rb_mEnumerable);
rb_define_singleton_method(sGroup, "each", etc_each_group, 0);
#endif
+
+#if defined(HAVE_GETPWENT) || defined(HAVE_GETGRENT)
+ (void)safe_setup_str;
+#endif
}
diff --git a/ext/etc/etc.gemspec b/ext/etc/etc.gemspec
index 98c6d66faa..0e9803dc62 100644
--- a/ext/etc/etc.gemspec
+++ b/ext/etc/etc.gemspec
@@ -24,7 +24,8 @@ Gem::Specification.new do |spec|
changelogs = Dir.glob("logs/ChangeLog-[1-9]*[^~]", base: __dir__)
spec.files = %w[
- LICENSE.txt
+ BSDL
+ COPYING
README.md
ChangeLog
ext/etc/constdefs.h
@@ -39,5 +40,5 @@ Gem::Specification.new do |spec|
spec.require_paths = ["lib"]
spec.extensions = %w{ext/etc/extconf.rb}
- spec.required_ruby_version = ">= 2.6.0"
+ spec.required_ruby_version = ">= 2.7.0"
end
diff --git a/ext/etc/extconf.rb b/ext/etc/extconf.rb
index 2e28d58037..497303a4fa 100644
--- a/ext/etc/extconf.rb
+++ b/ext/etc/extconf.rb
@@ -10,8 +10,30 @@ headers = []
have_library("sun", "getpwnam") # NIS (== YP) interface for IRIX 4
have_func("uname((struct utsname *)NULL)", headers)
have_func("getlogin")
-have_func("getpwent")
-have_func("getgrent")
+if have_func("getpwent")
+ have_struct_member('struct passwd', 'pw_gecos', 'pwd.h')
+ have_struct_member('struct passwd', 'pw_change', 'pwd.h')
+ have_struct_member('struct passwd', 'pw_quota', 'pwd.h')
+ if have_struct_member('struct passwd', 'pw_age', 'pwd.h')
+ case what_type?('struct passwd', 'pw_age', 'pwd.h')
+ when "string"
+ f = "safe_setup_str"
+ when "long long"
+ f = "LL2NUM"
+ else
+ f = "INT2NUM"
+ end
+ $defs.push("-DPW_AGE2VAL="+f)
+ end
+ have_struct_member('struct passwd', 'pw_class', 'pwd.h')
+ have_struct_member('struct passwd', 'pw_comment', 'pwd.h') unless /cygwin/ === RUBY_PLATFORM
+ have_struct_member('struct passwd', 'pw_expire', 'pwd.h')
+ have_struct_member('struct passwd', 'pw_passwd', 'pwd.h')
+end
+if have_func("getgrent")
+ have_struct_member('struct group', 'gr_passwd', 'grp.h')
+end
+
if (sysconfdir = RbConfig::CONFIG["sysconfdir"] and
!RbConfig.expand(sysconfdir.dup, "prefix"=>"", "DESTDIR"=>"").empty?)
$defs.push("-DSYSCONFDIR=#{Shellwords.escape(sysconfdir.dump)}")
@@ -21,26 +43,6 @@ have_func("sysconf")
have_func("confstr")
have_func("fpathconf")
-have_struct_member('struct passwd', 'pw_gecos', 'pwd.h')
-have_struct_member('struct passwd', 'pw_change', 'pwd.h')
-have_struct_member('struct passwd', 'pw_quota', 'pwd.h')
-if have_struct_member('struct passwd', 'pw_age', 'pwd.h')
- case what_type?('struct passwd', 'pw_age', 'pwd.h')
- when "string"
- f = "safe_setup_str"
- when "long long"
- f = "LL2NUM"
- else
- f = "INT2NUM"
- end
- $defs.push("-DPW_AGE2VAL="+f)
-end
-have_struct_member('struct passwd', 'pw_class', 'pwd.h')
-have_struct_member('struct passwd', 'pw_comment', 'pwd.h') unless /cygwin/ === RUBY_PLATFORM
-have_struct_member('struct passwd', 'pw_expire', 'pwd.h')
-have_struct_member('struct passwd', 'pw_passwd', 'pwd.h')
-have_struct_member('struct group', 'gr_passwd', 'grp.h')
-
# for https://github.com/ruby/etc
srcdir = File.expand_path("..", __FILE__)
constdefs = "#{srcdir}/constdefs.h"
@@ -58,7 +60,7 @@ end
# TODO: remove when dropping 2.7 support, as exported since 3.0
have_func('rb_deprecate_constant(Qnil, "None")')
-have_func("rb_io_descriptor")
+have_func("rb_io_descriptor", "ruby/io.h")
$distcleanfiles << "constdefs.h"
diff --git a/ext/extmk.rb b/ext/extmk.rb
index 2f76e174d5..8f847f4f3a 100755
--- a/ext/extmk.rb
+++ b/ext/extmk.rb
@@ -2,7 +2,13 @@
# -*- mode: ruby; coding: us-ascii -*-
# frozen_string_literal: false
-module Gem; end # only needs Gem::Platform
+module Gem
+ # Used by Gem::Platform.local
+ def self.target_rbconfig
+ RbConfig::CONFIG
+ end
+end
+# only needs Gem::Platform
require 'rubygems/platform'
# :stopdoc:
@@ -37,6 +43,7 @@ require 'rbconfig'
$topdir = "."
$top_srcdir = srcdir
+$extmk = true
inplace = File.identical?($top_srcdir, $topdir)
$" << "mkmf.rb"
@@ -132,14 +139,6 @@ def extract_makefile(makefile, keep = true)
true
end
-def create_makefile(target, srcprefix = nil)
- if $static and target.include?("/")
- base = File.basename(target)
- $defs << "-DInit_#{base}=Init_#{target.tr('/', '_')}"
- end
- super
-end
-
def extmake(target, basedir = 'ext', maybestatic = true)
FileUtils.mkpath target unless File.directory?(target)
begin
@@ -167,8 +166,6 @@ def extmake(target, basedir = 'ext', maybestatic = true)
$mdir = target
$srcdir = File.join($top_srcdir, basedir, $mdir)
$preload = nil
- $objs = []
- $srcs = []
$extso = []
makefile = "./Makefile"
static = $static
@@ -202,7 +199,7 @@ def extmake(target, basedir = 'ext', maybestatic = true)
begin
$extconf_h = nil
ok &&= extract_makefile(makefile)
- old_objs = $objs
+ old_objs = $objs || []
old_cleanfiles = $distcleanfiles | $cleanfiles
conf = ["#{$srcdir}/makefile.rb", "#{$srcdir}/extconf.rb"].find {|f| File.exist?(f)}
if (!ok || ($extconf_h && !File.exist?($extconf_h)) ||
@@ -265,6 +262,8 @@ def extmake(target, basedir = 'ext', maybestatic = true)
unless $destdir.to_s.empty? or $mflags.defined?("DESTDIR")
args += ["DESTDIR=" + relative_from($destdir, "../"+prefix)]
end
+ $objs ||= []
+ $srcs ||= []
if $static and ok and !$objs.empty? and !noinstall
args += ["static"]
$extlist.push [(maybestatic ? $static : false), target, $target, $preload]
@@ -560,6 +559,7 @@ extend Module.new {
if $static and (target = args.first).include?("/")
base = File.basename(target)
$defs << "-DInit_#{base}=Init_#{target.tr('/', '_')}"
+ $defs << "-DInitVM_#{base}=InitVM_#{target.tr('/', '_')}"
end
return super
end
@@ -578,7 +578,8 @@ extend Module.new {
}
end
- gemlib = File.directory?("#{$top_srcdir}/#{@ext_prefix}/#{@gemname}/lib")
+ conf = yield conf if block
+
if conf.any? {|s| /^TARGET *= *\S/ =~ s}
conf << %{
gem_platform = #{Gem::Platform.local}
@@ -611,23 +612,25 @@ gemspec: $(gemspec)
clean-gemspec:
-$(Q)$(RM) $(gemspec)
-}
-
- if gemlib
- conf << %{
-install-rb: gemlib
-clean-rb:: clean-gemlib
LN_S = #{config_string('LN_S')}
CP_R = #{config_string('CP')} -r
-
-gemlib = $(TARGET_TOPDIR)/gems/$(gem)/lib
-gemlib:#{%{ $(gemlib)\n$(gemlib): $(gem_srcdir)/lib} if $nmake}
- $(Q) #{@inplace ? '$(NULLCMD) ' : ''}$(RUBY) $(top_srcdir)/tool/ln_sr.rb -q -f -T $(gem_srcdir)/lib $(gemlib)
-
-clean-gemlib:
- $(Q) $(#{@inplace ? 'NULLCMD' : 'RM_RF'}) $(gemlib)
}
+ unless @inplace
+ %w[bin lib].each do |d|
+ next unless File.directory?("#{$top_srcdir}/#{@ext_prefix}/#{@gemname}/#{d}")
+ conf << %{
+install-rb: gem#{d}
+clean-rb:: clean-gem#{d}
+
+gem#{d} = $(TARGET_TOPDIR)/gems/$(gem)/#{d}
+gem#{d}:#{%{ $(gem#{d})\n$(gem#{d}): $(gem_srcdir)/#{d}} if $nmake}
+ $(Q) $(RUBY) $(top_srcdir)/tool/ln_sr.rb -q -f -T $(gem_srcdir)/#{d} $(gem#{d})
+
+clean-gem#{d}:
+ $(Q) $(RM_RF) $(gem#{d})
+}
+ end
end
end
@@ -811,9 +814,9 @@ begin
if $gnumake == "yes"
submake = "$(MAKE) -C $(@D)"
else
- submake = "cd $(@D) && "
- config_string("exec") {|str| submake << str << " "}
- submake << "$(MAKE)"
+ submake = ["cd", (sep ? "$(@D:/=#{sep})" : "$(@D)"), "&&"]
+ config_string("exec") {|str| submake << str}
+ submake = (submake << "$(MAKE)").join(" ")
end
targets.each do |tgt|
exts.each do |d|
diff --git a/ext/fcntl/depend b/ext/fcntl/depend
index 5ed652563b..57ea0f2106 100644
--- a/ext/fcntl/depend
+++ b/ext/fcntl/depend
@@ -128,6 +128,7 @@ fcntl.o: $(hdrdir)/ruby/internal/intern/re.h
fcntl.o: $(hdrdir)/ruby/internal/intern/ruby.h
fcntl.o: $(hdrdir)/ruby/internal/intern/select.h
fcntl.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+fcntl.o: $(hdrdir)/ruby/internal/intern/set.h
fcntl.o: $(hdrdir)/ruby/internal/intern/signal.h
fcntl.o: $(hdrdir)/ruby/internal/intern/sprintf.h
fcntl.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/fcntl/fcntl.c b/ext/fcntl/fcntl.c
index e34a3aeae3..b987e237dd 100644
--- a/ext/fcntl/fcntl.c
+++ b/ext/fcntl/fcntl.c
@@ -65,7 +65,7 @@ pack up your own arguments to pass as args for locking functions, etc.
*
*/
-#define FCNTL_VERSION "1.1.0"
+#define FCNTL_VERSION "1.3.0"
void
Init_fcntl(void)
@@ -251,4 +251,50 @@ Init_fcntl(void)
*/
rb_define_const(mFcntl, "F_DUP2FD_CLOEXEC", INT2NUM(F_DUP2FD_CLOEXEC));
#endif
+
+#ifdef F_PREALLOCATE
+ /*
+ * macOS specific flag used for preallocating file space.
+ */
+ rb_define_const(mFcntl, "F_PREALLOCATE", INT2NUM(F_PREALLOCATE));
+#endif
+
+#ifdef F_ALLOCATECONTIG
+ /*
+ * macOS specific flag used with F_PREALLOCATE for allocating contiguous
+ * space.
+ */
+ rb_define_const(mFcntl, "F_ALLOCATECONTIG", INT2NUM(F_ALLOCATECONTIG));
+#endif
+
+#ifdef F_ALLOCATEALL
+ /*
+ * macOS specific flag used with F_PREALLOCATE for allocating all contiguous
+ * space or no space.
+ */
+ rb_define_const(mFcntl, "F_ALLOCATEALL", INT2NUM(F_ALLOCATEALL));
+#endif
+
+#ifdef F_ALLOCATEPERSIST
+ /*
+ * macOS specific flag used with F_PREALLOCATE. Allocate space that is not
+ * freed when close is called.
+ */
+ rb_define_const(mFcntl, "F_ALLOCATEPERSIST", INT2NUM(F_ALLOCATEPERSIST));
+#endif
+
+#ifdef F_PEOFPOSMODE
+ /*
+ * macOS specific flag used with F_PREALLOCATE. Allocate from the physical
+ * end of file
+ */
+ rb_define_const(mFcntl, "F_PEOFPOSMODE", INT2NUM(F_PEOFPOSMODE));
+#endif
+
+#ifdef F_VOLPOSMODE
+ /*
+ * macOS specific flag used with F_PREALLOCATE. Allocate from the volume offset.
+ */
+ rb_define_const(mFcntl, "F_VOLPOSMODE", INT2NUM(F_VOLPOSMODE));
+#endif
}
diff --git a/ext/fcntl/fcntl.gemspec b/ext/fcntl/fcntl.gemspec
index d621bc0491..613a90d1ae 100644
--- a/ext/fcntl/fcntl.gemspec
+++ b/ext/fcntl/fcntl.gemspec
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.files = ["ext/fcntl/extconf.rb", "ext/fcntl/fcntl.c"]
- spec.extra_rdoc_files = [".document", ".rdoc_options", "LICENSE.txt", "README.md"]
+ spec.extra_rdoc_files = [".document", ".rdoc_options", "BSDL", "COPYING", "README.md"]
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
diff --git a/ext/fiddle/closure.c b/ext/fiddle/closure.c
deleted file mode 100644
index 2b4cdb6608..0000000000
--- a/ext/fiddle/closure.c
+++ /dev/null
@@ -1,458 +0,0 @@
-#include <fiddle.h>
-#include <stdbool.h>
-#include <ruby/thread.h>
-
-int ruby_thread_has_gvl_p(void); /* from internal.h */
-
-VALUE cFiddleClosure;
-
-typedef struct {
- void * code;
- ffi_closure *pcl;
- ffi_cif cif;
- int argc;
- ffi_type **argv;
-} fiddle_closure;
-
-#if defined(__OpenBSD__)
-# define USE_FFI_CLOSURE_ALLOC 0
-#endif
-
-#if defined(USE_FFI_CLOSURE_ALLOC)
-#elif !defined(HAVE_FFI_CLOSURE_ALLOC)
-# define USE_FFI_CLOSURE_ALLOC 0
-#else
-# define USE_FFI_CLOSURE_ALLOC 1
-#endif
-
-static void
-dealloc(void * ptr)
-{
- fiddle_closure * cls = (fiddle_closure *)ptr;
-#if USE_FFI_CLOSURE_ALLOC
- ffi_closure_free(cls->pcl);
-#else
- munmap(cls->pcl, sizeof(*cls->pcl));
-#endif
- if (cls->argv) xfree(cls->argv);
- xfree(cls);
-}
-
-static size_t
-closure_memsize(const void * ptr)
-{
- fiddle_closure * cls = (fiddle_closure *)ptr;
- size_t size = 0;
-
- size += sizeof(*cls);
-#if !defined(FFI_NO_RAW_API) || !FFI_NO_RAW_API
- size += ffi_raw_size(&cls->cif);
-#endif
- size += sizeof(*cls->argv);
- size += sizeof(ffi_closure);
-
- return size;
-}
-
-const rb_data_type_t closure_data_type = {
- .wrap_struct_name = "fiddle/closure",
- .function = {
- .dmark = 0,
- .dfree = dealloc,
- .dsize = closure_memsize
- },
- .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
-};
-
-struct callback_args {
- ffi_cif *cif;
- void *resp;
- void **args;
- void *ctx;
-};
-
-static void *
-with_gvl_callback(void *ptr)
-{
- struct callback_args *x = ptr;
-
- VALUE self = (VALUE)x->ctx;
- VALUE rbargs = rb_iv_get(self, "@args");
- VALUE ctype = rb_iv_get(self, "@ctype");
- int argc = RARRAY_LENINT(rbargs);
- VALUE params = rb_ary_tmp_new(argc);
- VALUE ret;
- VALUE cPointer;
- int i, type;
-
- cPointer = rb_const_get(mFiddle, rb_intern("Pointer"));
-
- for (i = 0; i < argc; i++) {
- type = NUM2INT(RARRAY_AREF(rbargs, i));
- switch (type) {
- case TYPE_VOID:
- argc = 0;
- break;
- case TYPE_INT:
- rb_ary_push(params, INT2NUM(*(int *)x->args[i]));
- break;
- case TYPE_UINT:
- rb_ary_push(params, UINT2NUM(*(unsigned int *)x->args[i]));
- break;
- case TYPE_VOIDP:
- rb_ary_push(params,
- rb_funcall(cPointer, rb_intern("[]"), 1,
- PTR2NUM(*(void **)x->args[i])));
- break;
- case TYPE_LONG:
- rb_ary_push(params, LONG2NUM(*(long *)x->args[i]));
- break;
- case TYPE_ULONG:
- rb_ary_push(params, ULONG2NUM(*(unsigned long *)x->args[i]));
- break;
- case TYPE_CHAR:
- rb_ary_push(params, INT2NUM(*(signed char *)x->args[i]));
- break;
- case TYPE_UCHAR:
- rb_ary_push(params, UINT2NUM(*(unsigned char *)x->args[i]));
- break;
- case TYPE_SHORT:
- rb_ary_push(params, INT2NUM(*(signed short *)x->args[i]));
- break;
- case TYPE_USHORT:
- rb_ary_push(params, UINT2NUM(*(unsigned short *)x->args[i]));
- break;
- case TYPE_DOUBLE:
- rb_ary_push(params, rb_float_new(*(double *)x->args[i]));
- break;
- case TYPE_FLOAT:
- rb_ary_push(params, rb_float_new(*(float *)x->args[i]));
- break;
-#if HAVE_LONG_LONG
- case TYPE_LONG_LONG:
- rb_ary_push(params, LL2NUM(*(LONG_LONG *)x->args[i]));
- break;
- case TYPE_ULONG_LONG:
- rb_ary_push(params, ULL2NUM(*(unsigned LONG_LONG *)x->args[i]));
- break;
-#endif
- case TYPE_CONST_STRING:
- rb_ary_push(params,
- rb_str_new_cstr(*((const char **)(x->args[i]))));
- break;
- case TYPE_BOOL:
- if (sizeof(bool) == sizeof(char)) {
- rb_ary_push(params, CBOOL2RBBOOL(*(unsigned char *)x->args[i]));
- } else if (sizeof(bool) == sizeof(short)) {
- rb_ary_push(params, CBOOL2RBBOOL(*(unsigned short *)x->args[i]));
- } else if (sizeof(bool) == sizeof(int)) {
- rb_ary_push(params, CBOOL2RBBOOL(*(unsigned int *)x->args[i]));
- } else if (sizeof(bool) == sizeof(long)) {
- rb_ary_push(params, CBOOL2RBBOOL(*(unsigned long *)x->args[i]));
- } else {
- rb_raise(rb_eNotImpError, "bool isn't supported: %u",
- (unsigned int)sizeof(bool));
- }
- break;
- default:
- rb_raise(rb_eRuntimeError, "closure args: %d", type);
- }
- }
-
- ret = rb_funcall2(self, rb_intern("call"), argc, RARRAY_CONST_PTR(params));
- RB_GC_GUARD(params);
-
- type = NUM2INT(ctype);
- switch (type) {
- case TYPE_VOID:
- break;
- case TYPE_LONG:
- *(long *)x->resp = NUM2LONG(ret);
- break;
- case TYPE_ULONG:
- *(unsigned long *)x->resp = NUM2ULONG(ret);
- break;
- case TYPE_CHAR:
- case TYPE_SHORT:
- case TYPE_INT:
- *(ffi_sarg *)x->resp = NUM2INT(ret);
- break;
- case TYPE_UCHAR:
- case TYPE_USHORT:
- case TYPE_UINT:
- *(ffi_arg *)x->resp = NUM2UINT(ret);
- break;
- case TYPE_VOIDP:
- *(void **)x->resp = NUM2PTR(ret);
- break;
- case TYPE_DOUBLE:
- *(double *)x->resp = NUM2DBL(ret);
- break;
- case TYPE_FLOAT:
- *(float *)x->resp = (float)NUM2DBL(ret);
- break;
-#if HAVE_LONG_LONG
- case TYPE_LONG_LONG:
- *(LONG_LONG *)x->resp = NUM2LL(ret);
- break;
- case TYPE_ULONG_LONG:
- *(unsigned LONG_LONG *)x->resp = NUM2ULL(ret);
- break;
-#endif
- case TYPE_CONST_STRING:
- /* Dangerous. Callback must keep reference of the String. */
- *((const char **)(x->resp)) = StringValueCStr(ret);
- break;
- case TYPE_BOOL:
- if (sizeof(bool) == sizeof(long)) {
- *(unsigned long *)x->resp = RB_TEST(ret);
- } else {
- *(ffi_arg *)x->resp = RB_TEST(ret);
- }
- break;
- default:
- rb_raise(rb_eRuntimeError, "closure retval: %d", type);
- }
- return 0;
-}
-
-static void
-callback(ffi_cif *cif, void *resp, void **args, void *ctx)
-{
- struct callback_args x;
-
- x.cif = cif;
- x.resp = resp;
- x.args = args;
- x.ctx = ctx;
-
- if (ruby_thread_has_gvl_p()) {
- (void)with_gvl_callback(&x);
- } else {
- (void)rb_thread_call_with_gvl(with_gvl_callback, &x);
- }
-}
-
-static VALUE
-allocate(VALUE klass)
-{
- fiddle_closure * closure;
-
- VALUE i = TypedData_Make_Struct(klass, fiddle_closure,
- &closure_data_type, closure);
-
-#if USE_FFI_CLOSURE_ALLOC
- closure->pcl = ffi_closure_alloc(sizeof(ffi_closure), &closure->code);
-#else
- closure->pcl = mmap(NULL, sizeof(ffi_closure), PROT_READ | PROT_WRITE,
- MAP_ANON | MAP_PRIVATE, -1, 0);
-#endif
-
- return i;
-}
-
-static fiddle_closure *
-get_raw(VALUE self)
-{
- fiddle_closure *closure;
- TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, closure);
- if (!closure) {
- rb_raise(rb_eArgError, "already freed: %+"PRIsVALUE, self);
- }
- return closure;
-}
-
-typedef struct {
- VALUE self;
- int argc;
- VALUE *argv;
-} initialize_data;
-
-static VALUE
-initialize_body(VALUE user_data)
-{
- initialize_data *data = (initialize_data *)user_data;
- VALUE ret;
- VALUE args;
- VALUE normalized_args;
- VALUE abi;
- fiddle_closure * cl;
- ffi_cif * cif;
- ffi_closure *pcl;
- ffi_status result;
- int i, argc;
-
- if (2 == rb_scan_args(data->argc, data->argv, "21", &ret, &args, &abi))
- abi = INT2NUM(FFI_DEFAULT_ABI);
-
- Check_Type(args, T_ARRAY);
-
- argc = RARRAY_LENINT(args);
-
- TypedData_Get_Struct(data->self, fiddle_closure, &closure_data_type, cl);
-
- cl->argv = (ffi_type **)xcalloc(argc + 1, sizeof(ffi_type *));
-
- normalized_args = rb_ary_new_capa(argc);
- for (i = 0; i < argc; i++) {
- VALUE arg = rb_fiddle_type_ensure(RARRAY_AREF(args, i));
- rb_ary_push(normalized_args, arg);
- cl->argv[i] = rb_fiddle_int_to_ffi_type(NUM2INT(arg));
- }
- cl->argv[argc] = NULL;
-
- ret = rb_fiddle_type_ensure(ret);
- rb_iv_set(data->self, "@ctype", ret);
- rb_iv_set(data->self, "@args", normalized_args);
-
- cif = &cl->cif;
- pcl = cl->pcl;
-
- result = ffi_prep_cif(cif,
- NUM2INT(abi),
- argc,
- rb_fiddle_int_to_ffi_type(NUM2INT(ret)),
- cl->argv);
-
- if (FFI_OK != result) {
- rb_raise(rb_eRuntimeError, "error prepping CIF %d", result);
- }
-
-#if USE_FFI_CLOSURE_ALLOC
- result = ffi_prep_closure_loc(pcl, cif, callback,
- (void *)(data->self), cl->code);
-#else
- result = ffi_prep_closure(pcl, cif, callback, (void *)(data->self));
- cl->code = (void *)pcl;
- i = mprotect(pcl, sizeof(*pcl), PROT_READ | PROT_EXEC);
- if (i) {
- rb_sys_fail("mprotect");
- }
-#endif
-
- if (FFI_OK != result) {
- rb_raise(rb_eRuntimeError, "error prepping closure %d", result);
- }
-
- return data->self;
-}
-
-static VALUE
-initialize_rescue(VALUE user_data, VALUE exception)
-{
- initialize_data *data = (initialize_data *)user_data;
- dealloc(RTYPEDDATA_DATA(data->self));
- RTYPEDDATA_DATA(data->self) = NULL;
- rb_exc_raise(exception);
- return data->self;
-}
-
-static VALUE
-initialize(int argc, VALUE *argv, VALUE self)
-{
- initialize_data data;
- data.self = self;
- data.argc = argc;
- data.argv = argv;
- return rb_rescue(initialize_body, (VALUE)&data,
- initialize_rescue, (VALUE)&data);
-}
-
-static VALUE
-to_i(VALUE self)
-{
- fiddle_closure *closure = get_raw(self);
- return PTR2NUM(closure->code);
-}
-
-static VALUE
-closure_free(VALUE self)
-{
- fiddle_closure *closure;
- TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, closure);
- if (closure) {
- dealloc(closure);
- RTYPEDDATA_DATA(self) = NULL;
- }
- return RUBY_Qnil;
-}
-
-static VALUE
-closure_freed_p(VALUE self)
-{
- fiddle_closure *closure;
- TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, closure);
- return closure ? RUBY_Qfalse : RUBY_Qtrue;
-}
-
-void
-Init_fiddle_closure(void)
-{
-#if 0
- mFiddle = rb_define_module("Fiddle"); /* let rdoc know about mFiddle */
-#endif
-
- /*
- * Document-class: Fiddle::Closure
- *
- * == Description
- *
- * An FFI closure wrapper, for handling callbacks.
- *
- * == Example
- *
- * closure = Class.new(Fiddle::Closure) {
- * def call
- * 10
- * end
- * }.new(Fiddle::TYPE_INT, [])
- * #=> #<#<Class:0x0000000150d308>:0x0000000150d240>
- * func = Fiddle::Function.new(closure, [], Fiddle::TYPE_INT)
- * #=> #<Fiddle::Function:0x00000001516e58>
- * func.call
- * #=> 10
- */
- cFiddleClosure = rb_define_class_under(mFiddle, "Closure", rb_cObject);
-
- rb_define_alloc_func(cFiddleClosure, allocate);
-
- /*
- * Document-method: new
- *
- * call-seq: new(ret, args, abi = Fiddle::DEFAULT)
- *
- * Construct a new Closure object.
- *
- * * +ret+ is the C type to be returned
- * * +args+ is an Array of arguments, passed to the callback function
- * * +abi+ is the abi of the closure
- *
- * If there is an error in preparing the ffi_cif or ffi_prep_closure,
- * then a RuntimeError will be raised.
- */
- rb_define_method(cFiddleClosure, "initialize", initialize, -1);
-
- /*
- * Document-method: to_i
- *
- * Returns the memory address for this closure.
- */
- rb_define_method(cFiddleClosure, "to_i", to_i, 0);
-
- /*
- * Document-method: free
- *
- * Free this closure explicitly. You can't use this closure anymore.
- *
- * If this closure is already freed, this does nothing.
- */
- rb_define_method(cFiddleClosure, "free", closure_free, 0);
-
- /*
- * Document-method: freed?
- *
- * Whether this closure was freed explicitly.
- */
- rb_define_method(cFiddleClosure, "freed?", closure_freed_p, 0);
-}
-/* vim: set noet sw=4 sts=4 */
diff --git a/ext/fiddle/closure.h b/ext/fiddle/closure.h
deleted file mode 100644
index d0a8be6180..0000000000
--- a/ext/fiddle/closure.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef FIDDLE_CLOSURE_H
-#define FIDDLE_CLOSURE_H
-
-#include <fiddle.h>
-
-void Init_fiddle_closure(void);
-
-#endif
diff --git a/ext/fiddle/conversions.c b/ext/fiddle/conversions.c
deleted file mode 100644
index 796bf929c3..0000000000
--- a/ext/fiddle/conversions.c
+++ /dev/null
@@ -1,383 +0,0 @@
-#include <stdbool.h>
-
-#include <fiddle.h>
-
-VALUE
-rb_fiddle_type_ensure(VALUE type)
-{
- VALUE original_type = type;
-
- if (!RB_SYMBOL_P(type)) {
- VALUE type_string = rb_check_string_type(type);
- if (!NIL_P(type_string)) {
- type = rb_to_symbol(type_string);
- }
- }
-
- if (RB_SYMBOL_P(type)) {
- ID type_id = rb_sym2id(type);
- ID void_id;
- ID voidp_id;
- ID char_id;
- ID short_id;
- ID int_id;
- ID long_id;
-#ifdef TYPE_LONG_LONG
- ID long_long_id;
-#endif
-#ifdef TYPE_INT8_T
- ID int8_t_id;
-#endif
-#ifdef TYPE_INT16_T
- ID int16_t_id;
-#endif
-#ifdef TYPE_INT32_T
- ID int32_t_id;
-#endif
-#ifdef TYPE_INT64_T
- ID int64_t_id;
-#endif
- ID float_id;
- ID double_id;
- ID variadic_id;
- ID const_string_id;
- ID size_t_id;
- ID ssize_t_id;
- ID ptrdiff_t_id;
- ID intptr_t_id;
- ID uintptr_t_id;
- ID bool_id;
- RUBY_CONST_ID(void_id, "void");
- RUBY_CONST_ID(voidp_id, "voidp");
- RUBY_CONST_ID(char_id, "char");
- RUBY_CONST_ID(short_id, "short");
- RUBY_CONST_ID(int_id, "int");
- RUBY_CONST_ID(long_id, "long");
-#ifdef TYPE_LONG_LONG
- RUBY_CONST_ID(long_long_id, "long_long");
-#endif
-#ifdef TYPE_INT8_T
- RUBY_CONST_ID(int8_t_id, "int8_t");
-#endif
-#ifdef TYPE_INT16_T
- RUBY_CONST_ID(int16_t_id, "int16_t");
-#endif
-#ifdef TYPE_INT32_T
- RUBY_CONST_ID(int32_t_id, "int32_t");
-#endif
-#ifdef TYPE_INT64_T
- RUBY_CONST_ID(int64_t_id, "int64_t");
-#endif
- RUBY_CONST_ID(float_id, "float");
- RUBY_CONST_ID(double_id, "double");
- RUBY_CONST_ID(variadic_id, "variadic");
- RUBY_CONST_ID(const_string_id, "const_string");
- RUBY_CONST_ID(size_t_id, "size_t");
- RUBY_CONST_ID(ssize_t_id, "ssize_t");
- RUBY_CONST_ID(ptrdiff_t_id, "ptrdiff_t");
- RUBY_CONST_ID(intptr_t_id, "intptr_t");
- RUBY_CONST_ID(uintptr_t_id, "uintptr_t");
- RUBY_CONST_ID(bool_id, "bool");
- if (type_id == void_id) {
- return INT2NUM(TYPE_VOID);
- }
- else if (type_id == voidp_id) {
- return INT2NUM(TYPE_VOIDP);
- }
- else if (type_id == char_id) {
- return INT2NUM(TYPE_CHAR);
- }
- else if (type_id == short_id) {
- return INT2NUM(TYPE_SHORT);
- }
- else if (type_id == int_id) {
- return INT2NUM(TYPE_INT);
- }
- else if (type_id == long_id) {
- return INT2NUM(TYPE_LONG);
- }
-#ifdef TYPE_LONG_LONG
- else if (type_id == long_long_id) {
- return INT2NUM(TYPE_LONG_LONG);
- }
-#endif
-#ifdef TYPE_INT8_T
- else if (type_id == int8_t_id) {
- return INT2NUM(TYPE_INT8_T);
- }
-#endif
-#ifdef TYPE_INT16_T
- else if (type_id == int16_t_id) {
- return INT2NUM(TYPE_INT16_T);
- }
-#endif
-#ifdef TYPE_INT32_T
- else if (type_id == int32_t_id) {
- return INT2NUM(TYPE_INT32_T);
- }
-#endif
-#ifdef TYPE_INT64_T
- else if (type_id == int64_t_id) {
- return INT2NUM(TYPE_INT64_T);
- }
-#endif
- else if (type_id == float_id) {
- return INT2NUM(TYPE_FLOAT);
- }
- else if (type_id == double_id) {
- return INT2NUM(TYPE_DOUBLE);
- }
- else if (type_id == variadic_id) {
- return INT2NUM(TYPE_VARIADIC);
- }
- else if (type_id == const_string_id) {
- return INT2NUM(TYPE_CONST_STRING);
- }
- else if (type_id == size_t_id) {
- return INT2NUM(TYPE_SIZE_T);
- }
- else if (type_id == ssize_t_id) {
- return INT2NUM(TYPE_SSIZE_T);
- }
- else if (type_id == ptrdiff_t_id) {
- return INT2NUM(TYPE_PTRDIFF_T);
- }
- else if (type_id == intptr_t_id) {
- return INT2NUM(TYPE_INTPTR_T);
- }
- else if (type_id == uintptr_t_id) {
- return INT2NUM(TYPE_UINTPTR_T);
- }
- else if (type_id == bool_id) {
- return INT2NUM(TYPE_BOOL);
- }
- else {
- type = original_type;
- }
- }
-
- return rb_to_int(type);
-}
-
-ffi_type *
-rb_fiddle_int_to_ffi_type(int type)
-{
- int signed_p = 1;
-
- if (type < 0) {
- type = -1 * type;
- signed_p = 0;
- }
-
-#define rb_ffi_type_of(t) (signed_p ? &ffi_type_s##t : &ffi_type_u##t)
-
- switch (type) {
- case TYPE_VOID:
- return &ffi_type_void;
- case TYPE_VOIDP:
- return &ffi_type_pointer;
- case TYPE_CHAR:
- return rb_ffi_type_of(char);
- case TYPE_SHORT:
- return rb_ffi_type_of(short);
- case TYPE_INT:
- return rb_ffi_type_of(int);
- case TYPE_LONG:
- return rb_ffi_type_of(long);
-#if HAVE_LONG_LONG
- case TYPE_LONG_LONG:
- return rb_ffi_type_of(long_long);
-#endif
- case TYPE_FLOAT:
- return &ffi_type_float;
- case TYPE_DOUBLE:
- return &ffi_type_double;
- case TYPE_CONST_STRING:
- return &ffi_type_pointer;
- case TYPE_BOOL:
- signed_p = 0;
- if (sizeof(bool) == sizeof(char)) {
- return rb_ffi_type_of(char);
- } else if (sizeof(bool) == sizeof(short)) {
- return rb_ffi_type_of(short);
- } else if (sizeof(bool) == sizeof(int)) {
- return rb_ffi_type_of(int);
- } else if (sizeof(bool) == sizeof(long)) {
- return rb_ffi_type_of(long);
- } else {
- rb_raise(rb_eNotImpError, "bool isn't supported: %u",
- (unsigned int)sizeof(bool));
- }
- default:
- rb_raise(rb_eRuntimeError, "unknown type %d", type);
- }
- return &ffi_type_pointer;
-}
-
-ffi_type *
-int_to_ffi_type(int type)
-{
- return rb_fiddle_int_to_ffi_type(type);
-}
-
-void
-rb_fiddle_value_to_generic(int type, VALUE *src, fiddle_generic *dst)
-{
- switch (type) {
- case TYPE_VOID:
- break;
- case TYPE_VOIDP:
- dst->pointer = NUM2PTR(rb_Integer(*src));
- break;
- case TYPE_CHAR:
- if (RB_TYPE_P(*src, RUBY_T_STRING) && RSTRING_LEN(*src) == 1) {
- dst->schar = RSTRING_PTR(*src)[0];
- } else {
- dst->schar = (signed char)NUM2INT(*src);
- }
- break;
- case TYPE_UCHAR:
- dst->uchar = (unsigned char)NUM2UINT(*src);
- break;
- case TYPE_SHORT:
- dst->sshort = (unsigned short)NUM2INT(*src);
- break;
- case TYPE_USHORT:
- dst->sshort = (signed short)NUM2UINT(*src);
- break;
- case TYPE_INT:
- dst->sint = NUM2INT(*src);
- break;
- case TYPE_UINT:
- dst->uint = NUM2UINT(*src);
- break;
- case TYPE_LONG:
- dst->slong = NUM2LONG(*src);
- break;
- case TYPE_ULONG:
- dst->ulong = NUM2ULONG(*src);
- break;
-#if HAVE_LONG_LONG
- case TYPE_LONG_LONG:
- dst->slong_long = NUM2LL(*src);
- break;
- case TYPE_ULONG_LONG:
- dst->ulong_long = NUM2ULL(*src);
- break;
-#endif
- case TYPE_FLOAT:
- dst->ffloat = (float)NUM2DBL(*src);
- break;
- case TYPE_DOUBLE:
- dst->ddouble = NUM2DBL(*src);
- break;
- case TYPE_CONST_STRING:
- if (NIL_P(*src)) {
- dst->pointer = NULL;
- }
- else {
- dst->pointer = rb_string_value_cstr(src);
- }
- break;
- case TYPE_BOOL:
- if (sizeof(bool) == sizeof(char)) {
- dst->uchar = RB_TEST(*src);
- } else if (sizeof(bool) == sizeof(short)) {
- dst->ushort = RB_TEST(*src);
- } else if (sizeof(bool) == sizeof(int)) {
- dst->uint = RB_TEST(*src);
- } else if (sizeof(bool) == sizeof(long)) {
- dst->ulong = RB_TEST(*src);
- } else {
- rb_raise(rb_eNotImpError, "bool isn't supported: %u",
- (unsigned int)sizeof(bool));
- }
- break;
- default:
- rb_raise(rb_eRuntimeError, "unknown type %d", type);
- break;
- }
-}
-
-void
-value_to_generic(int type, VALUE src, fiddle_generic *dst)
-{
- /* src isn't safe from GC when type is TYPE_CONST_STRING and src
- * isn't String. */
- rb_fiddle_value_to_generic(type, &src, dst);
-}
-
-VALUE
-rb_fiddle_generic_to_value(VALUE rettype, fiddle_generic retval)
-{
- int type = NUM2INT(rettype);
- VALUE cPointer;
-
- cPointer = rb_const_get(mFiddle, rb_intern("Pointer"));
-
- switch (type) {
- case TYPE_VOID:
- return Qnil;
- case TYPE_VOIDP:
- return rb_funcall(cPointer, rb_intern("[]"), 1,
- PTR2NUM((void *)retval.pointer));
- case TYPE_CHAR:
- return INT2NUM((signed char)retval.fffi_sarg);
- case TYPE_UCHAR:
- return INT2NUM((unsigned char)retval.fffi_arg);
- case TYPE_SHORT:
- return INT2NUM((signed short)retval.fffi_sarg);
- case TYPE_USHORT:
- return INT2NUM((unsigned short)retval.fffi_arg);
- case TYPE_INT:
- return INT2NUM((signed int)retval.fffi_sarg);
- case TYPE_UINT:
- return UINT2NUM((unsigned int)retval.fffi_arg);
- case TYPE_LONG:
- return LONG2NUM(retval.slong);
- case TYPE_ULONG:
- return ULONG2NUM(retval.ulong);
-#if HAVE_LONG_LONG
- case TYPE_LONG_LONG:
- return LL2NUM(retval.slong_long);
- case TYPE_ULONG_LONG:
- return ULL2NUM(retval.ulong_long);
-#endif
- case TYPE_FLOAT:
- return rb_float_new(retval.ffloat);
- case TYPE_DOUBLE:
- return rb_float_new(retval.ddouble);
- case TYPE_CONST_STRING:
- if (retval.pointer) {
- return rb_str_new_cstr(retval.pointer);
- }
- else {
- return Qnil;
- }
- case TYPE_BOOL:
- if (sizeof(bool) == sizeof(char)) {
- return CBOOL2RBBOOL((unsigned char)retval.fffi_arg);
- } else if (sizeof(bool) == sizeof(short)) {
- return CBOOL2RBBOOL((unsigned short)retval.fffi_arg);
- } else if (sizeof(bool) == sizeof(int)) {
- return CBOOL2RBBOOL((unsigned int)retval.fffi_arg);
- } else if (sizeof(bool) == sizeof(long)) {
- return CBOOL2RBBOOL(retval.ulong);
- } else {
- rb_raise(rb_eNotImpError, "bool isn't supported: %u",
- (unsigned int)sizeof(bool));
- }
- default:
- rb_raise(rb_eRuntimeError, "unknown type %d", type);
- }
-
- UNREACHABLE;
-}
-
-VALUE
-generic_to_value(VALUE rettype, fiddle_generic retval)
-{
- return rb_fiddle_generic_to_value(rettype, retval);
-}
-
-/* vim: set noet sw=4 sts=4 */
diff --git a/ext/fiddle/conversions.h b/ext/fiddle/conversions.h
deleted file mode 100644
index 7a1e928d56..0000000000
--- a/ext/fiddle/conversions.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#ifndef FIDDLE_CONVERSIONS_H
-#define FIDDLE_CONVERSIONS_H
-
-#include <fiddle.h>
-
-typedef union
-{
- ffi_arg fffi_arg; /* rvalue smaller than unsigned long */
- ffi_sarg fffi_sarg; /* rvalue smaller than signed long */
- unsigned char uchar; /* ffi_type_uchar */
- signed char schar; /* ffi_type_schar */
- unsigned short ushort; /* ffi_type_sshort */
- signed short sshort; /* ffi_type_ushort */
- unsigned int uint; /* ffi_type_uint */
- signed int sint; /* ffi_type_sint */
- unsigned long ulong; /* ffi_type_ulong */
- signed long slong; /* ffi_type_slong */
- float ffloat; /* ffi_type_float */
- double ddouble; /* ffi_type_double */
-#if HAVE_LONG_LONG
- unsigned LONG_LONG ulong_long; /* ffi_type_ulong_long */
- signed LONG_LONG slong_long; /* ffi_type_ulong_long */
-#endif
- void * pointer; /* ffi_type_pointer */
-} fiddle_generic;
-
-VALUE rb_fiddle_type_ensure(VALUE type);
-ffi_type * rb_fiddle_int_to_ffi_type(int type);
-void rb_fiddle_value_to_generic(int type, VALUE *src, fiddle_generic *dst);
-VALUE rb_fiddle_generic_to_value(VALUE rettype, fiddle_generic retval);
-
-/* Deprecated. Use rb_fiddle_*() version. */
-ffi_type * int_to_ffi_type(int type);
-void value_to_generic(int type, VALUE src, fiddle_generic *dst);
-VALUE generic_to_value(VALUE rettype, fiddle_generic retval);
-
-#define VALUE2GENERIC(_type, _src, _dst) \
- rb_fiddle_value_to_generic((_type), &(_src), (_dst))
-#define INT2FFI_TYPE(_type) \
- rb_fiddle_int_to_ffi_type(_type)
-#define GENERIC2VALUE(_type, _retval) \
- rb_fiddle_generic_to_value((_type), (_retval))
-
-#if SIZEOF_VOIDP == SIZEOF_LONG
-# define PTR2NUM(x) (LONG2NUM((long)(x)))
-# define NUM2PTR(x) ((void*)(NUM2ULONG(x)))
-#else
-/* # error --->> Ruby/DL2 requires sizeof(void*) == sizeof(long) to be compiled. <<--- */
-# define PTR2NUM(x) (LL2NUM((LONG_LONG)(x)))
-# define NUM2PTR(x) ((void*)(NUM2ULL(x)))
-#endif
-
-#define CBOOL2RBBOOL(cbool) ((cbool) ? RUBY_Qtrue : RUBY_Qfalse)
-
-#endif
diff --git a/ext/fiddle/depend b/ext/fiddle/depend
deleted file mode 100644
index 43b11ca780..0000000000
--- a/ext/fiddle/depend
+++ /dev/null
@@ -1,1396 +0,0 @@
-PWD =
-
-CONFIGURE_LIBFFI = \
- $(LIBFFI_CONFIGURE) --disable-shared \
- --host=$(LIBFFI_ARCH) --enable-builddir=$(arch) \
- CC="$(CC)" CFLAGS="$(LIBFFI_CFLAGS)" \
- LD="$(LD)" LDFLAGS="$(LIBFFI_LDFLAGS)"
-
-$(STATIC_LIB) $(RUBYARCHDIR)/$(DLLIB) $(DLLIB): $(LIBFFI_A)
-
-$(OBJS): $(FFI_H)
-
-.PHONY: .FORCE hdr
-
-.FORCE:
-
-hdr: $(FFI_H)
-
-configure-libffi build-libffi: .FORCE
-configure-libffi \
-$(LIBFFI_DIR)/include/ffi.h \
-$(LIBFFI_DIR)/include/ffitarget.h \
-$(LIBFFI_DIR)/fficonfig.h \
-$(LIBFFI_DIR)/Makefile:
- $(Q) $(MAKEDIRS) $(LIBFFI_DIR)
- $(Q) $(CONFIGURE_LIBFFI)
-
-build-libffi $(LIBFFI_A):
- $(Q) $(SUBMAKE_PRE) $(MAKE) $(SUBMAKE_ARG)
-
-clean-none:
-clean-libffi:
- $(Q) $(SUBMAKE_PRE) $(MAKE) $(SUBMAKE_ARG) clean
-
-distclean-none:
-distclean-libffi:
- $(Q) $(SUBMAKE_PRE) $(MAKE) $(SUBMAKE_ARG) distclean
- $(Q) $(RM) $(LIBFFI_DIR)/local.exp
- $(Q) $(RUBY) -rfileutils -e "FileUtils.rmdir(Dir.glob(ARGV[0]+'/**/{,.*/}'), :parents=>true)" $(LIBFFI_DIR)
-
-realclean-none:
-realclean-libffi:
- $(Q) $(RMALL) $(LIBFFI_DIR)
-
-.PHONY: clean-libffi distclean-libffi realclean-libffi
-.PHONY: clean-none distclean-none realclean-none
-
-clean: clean-$(LIBFFI_CLEAN)
-distclean: distclean-$(LIBFFI_CLEAN)
-realclean: realclean-$(LIBFFI_CLEAN)
-
-.PHONY: configure configure-libffi
-
-# AUTOGENERATED DEPENDENCIES START
-closure.o: $(RUBY_EXTCONF_H)
-closure.o: $(arch_hdrdir)/ruby/config.h
-closure.o: $(hdrdir)/ruby.h
-closure.o: $(hdrdir)/ruby/assert.h
-closure.o: $(hdrdir)/ruby/backward.h
-closure.o: $(hdrdir)/ruby/backward/2/assume.h
-closure.o: $(hdrdir)/ruby/backward/2/attributes.h
-closure.o: $(hdrdir)/ruby/backward/2/bool.h
-closure.o: $(hdrdir)/ruby/backward/2/inttypes.h
-closure.o: $(hdrdir)/ruby/backward/2/limits.h
-closure.o: $(hdrdir)/ruby/backward/2/long_long.h
-closure.o: $(hdrdir)/ruby/backward/2/stdalign.h
-closure.o: $(hdrdir)/ruby/backward/2/stdarg.h
-closure.o: $(hdrdir)/ruby/defines.h
-closure.o: $(hdrdir)/ruby/intern.h
-closure.o: $(hdrdir)/ruby/internal/abi.h
-closure.o: $(hdrdir)/ruby/internal/anyargs.h
-closure.o: $(hdrdir)/ruby/internal/arithmetic.h
-closure.o: $(hdrdir)/ruby/internal/arithmetic/char.h
-closure.o: $(hdrdir)/ruby/internal/arithmetic/double.h
-closure.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
-closure.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
-closure.o: $(hdrdir)/ruby/internal/arithmetic/int.h
-closure.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
-closure.o: $(hdrdir)/ruby/internal/arithmetic/long.h
-closure.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
-closure.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
-closure.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
-closure.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
-closure.o: $(hdrdir)/ruby/internal/arithmetic/short.h
-closure.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
-closure.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
-closure.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
-closure.o: $(hdrdir)/ruby/internal/assume.h
-closure.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
-closure.o: $(hdrdir)/ruby/internal/attr/artificial.h
-closure.o: $(hdrdir)/ruby/internal/attr/cold.h
-closure.o: $(hdrdir)/ruby/internal/attr/const.h
-closure.o: $(hdrdir)/ruby/internal/attr/constexpr.h
-closure.o: $(hdrdir)/ruby/internal/attr/deprecated.h
-closure.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
-closure.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
-closure.o: $(hdrdir)/ruby/internal/attr/error.h
-closure.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
-closure.o: $(hdrdir)/ruby/internal/attr/forceinline.h
-closure.o: $(hdrdir)/ruby/internal/attr/format.h
-closure.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
-closure.o: $(hdrdir)/ruby/internal/attr/noalias.h
-closure.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
-closure.o: $(hdrdir)/ruby/internal/attr/noexcept.h
-closure.o: $(hdrdir)/ruby/internal/attr/noinline.h
-closure.o: $(hdrdir)/ruby/internal/attr/nonnull.h
-closure.o: $(hdrdir)/ruby/internal/attr/noreturn.h
-closure.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
-closure.o: $(hdrdir)/ruby/internal/attr/pure.h
-closure.o: $(hdrdir)/ruby/internal/attr/restrict.h
-closure.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
-closure.o: $(hdrdir)/ruby/internal/attr/warning.h
-closure.o: $(hdrdir)/ruby/internal/attr/weakref.h
-closure.o: $(hdrdir)/ruby/internal/cast.h
-closure.o: $(hdrdir)/ruby/internal/compiler_is.h
-closure.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
-closure.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
-closure.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
-closure.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
-closure.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
-closure.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
-closure.o: $(hdrdir)/ruby/internal/compiler_since.h
-closure.o: $(hdrdir)/ruby/internal/config.h
-closure.o: $(hdrdir)/ruby/internal/constant_p.h
-closure.o: $(hdrdir)/ruby/internal/core.h
-closure.o: $(hdrdir)/ruby/internal/core/rarray.h
-closure.o: $(hdrdir)/ruby/internal/core/rbasic.h
-closure.o: $(hdrdir)/ruby/internal/core/rbignum.h
-closure.o: $(hdrdir)/ruby/internal/core/rclass.h
-closure.o: $(hdrdir)/ruby/internal/core/rdata.h
-closure.o: $(hdrdir)/ruby/internal/core/rfile.h
-closure.o: $(hdrdir)/ruby/internal/core/rhash.h
-closure.o: $(hdrdir)/ruby/internal/core/robject.h
-closure.o: $(hdrdir)/ruby/internal/core/rregexp.h
-closure.o: $(hdrdir)/ruby/internal/core/rstring.h
-closure.o: $(hdrdir)/ruby/internal/core/rstruct.h
-closure.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
-closure.o: $(hdrdir)/ruby/internal/ctype.h
-closure.o: $(hdrdir)/ruby/internal/dllexport.h
-closure.o: $(hdrdir)/ruby/internal/dosish.h
-closure.o: $(hdrdir)/ruby/internal/error.h
-closure.o: $(hdrdir)/ruby/internal/eval.h
-closure.o: $(hdrdir)/ruby/internal/event.h
-closure.o: $(hdrdir)/ruby/internal/fl_type.h
-closure.o: $(hdrdir)/ruby/internal/gc.h
-closure.o: $(hdrdir)/ruby/internal/glob.h
-closure.o: $(hdrdir)/ruby/internal/globals.h
-closure.o: $(hdrdir)/ruby/internal/has/attribute.h
-closure.o: $(hdrdir)/ruby/internal/has/builtin.h
-closure.o: $(hdrdir)/ruby/internal/has/c_attribute.h
-closure.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
-closure.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
-closure.o: $(hdrdir)/ruby/internal/has/extension.h
-closure.o: $(hdrdir)/ruby/internal/has/feature.h
-closure.o: $(hdrdir)/ruby/internal/has/warning.h
-closure.o: $(hdrdir)/ruby/internal/intern/array.h
-closure.o: $(hdrdir)/ruby/internal/intern/bignum.h
-closure.o: $(hdrdir)/ruby/internal/intern/class.h
-closure.o: $(hdrdir)/ruby/internal/intern/compar.h
-closure.o: $(hdrdir)/ruby/internal/intern/complex.h
-closure.o: $(hdrdir)/ruby/internal/intern/cont.h
-closure.o: $(hdrdir)/ruby/internal/intern/dir.h
-closure.o: $(hdrdir)/ruby/internal/intern/enum.h
-closure.o: $(hdrdir)/ruby/internal/intern/enumerator.h
-closure.o: $(hdrdir)/ruby/internal/intern/error.h
-closure.o: $(hdrdir)/ruby/internal/intern/eval.h
-closure.o: $(hdrdir)/ruby/internal/intern/file.h
-closure.o: $(hdrdir)/ruby/internal/intern/hash.h
-closure.o: $(hdrdir)/ruby/internal/intern/io.h
-closure.o: $(hdrdir)/ruby/internal/intern/load.h
-closure.o: $(hdrdir)/ruby/internal/intern/marshal.h
-closure.o: $(hdrdir)/ruby/internal/intern/numeric.h
-closure.o: $(hdrdir)/ruby/internal/intern/object.h
-closure.o: $(hdrdir)/ruby/internal/intern/parse.h
-closure.o: $(hdrdir)/ruby/internal/intern/proc.h
-closure.o: $(hdrdir)/ruby/internal/intern/process.h
-closure.o: $(hdrdir)/ruby/internal/intern/random.h
-closure.o: $(hdrdir)/ruby/internal/intern/range.h
-closure.o: $(hdrdir)/ruby/internal/intern/rational.h
-closure.o: $(hdrdir)/ruby/internal/intern/re.h
-closure.o: $(hdrdir)/ruby/internal/intern/ruby.h
-closure.o: $(hdrdir)/ruby/internal/intern/select.h
-closure.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
-closure.o: $(hdrdir)/ruby/internal/intern/signal.h
-closure.o: $(hdrdir)/ruby/internal/intern/sprintf.h
-closure.o: $(hdrdir)/ruby/internal/intern/string.h
-closure.o: $(hdrdir)/ruby/internal/intern/struct.h
-closure.o: $(hdrdir)/ruby/internal/intern/thread.h
-closure.o: $(hdrdir)/ruby/internal/intern/time.h
-closure.o: $(hdrdir)/ruby/internal/intern/variable.h
-closure.o: $(hdrdir)/ruby/internal/intern/vm.h
-closure.o: $(hdrdir)/ruby/internal/interpreter.h
-closure.o: $(hdrdir)/ruby/internal/iterator.h
-closure.o: $(hdrdir)/ruby/internal/memory.h
-closure.o: $(hdrdir)/ruby/internal/method.h
-closure.o: $(hdrdir)/ruby/internal/module.h
-closure.o: $(hdrdir)/ruby/internal/newobj.h
-closure.o: $(hdrdir)/ruby/internal/scan_args.h
-closure.o: $(hdrdir)/ruby/internal/special_consts.h
-closure.o: $(hdrdir)/ruby/internal/static_assert.h
-closure.o: $(hdrdir)/ruby/internal/stdalign.h
-closure.o: $(hdrdir)/ruby/internal/stdbool.h
-closure.o: $(hdrdir)/ruby/internal/stdckdint.h
-closure.o: $(hdrdir)/ruby/internal/symbol.h
-closure.o: $(hdrdir)/ruby/internal/value.h
-closure.o: $(hdrdir)/ruby/internal/value_type.h
-closure.o: $(hdrdir)/ruby/internal/variable.h
-closure.o: $(hdrdir)/ruby/internal/warning_push.h
-closure.o: $(hdrdir)/ruby/internal/xmalloc.h
-closure.o: $(hdrdir)/ruby/missing.h
-closure.o: $(hdrdir)/ruby/ruby.h
-closure.o: $(hdrdir)/ruby/st.h
-closure.o: $(hdrdir)/ruby/subst.h
-closure.o: $(hdrdir)/ruby/thread.h
-closure.o: closure.c
-closure.o: closure.h
-closure.o: conversions.h
-closure.o: fiddle.h
-closure.o: function.h
-conversions.o: $(RUBY_EXTCONF_H)
-conversions.o: $(arch_hdrdir)/ruby/config.h
-conversions.o: $(hdrdir)/ruby.h
-conversions.o: $(hdrdir)/ruby/assert.h
-conversions.o: $(hdrdir)/ruby/backward.h
-conversions.o: $(hdrdir)/ruby/backward/2/assume.h
-conversions.o: $(hdrdir)/ruby/backward/2/attributes.h
-conversions.o: $(hdrdir)/ruby/backward/2/bool.h
-conversions.o: $(hdrdir)/ruby/backward/2/inttypes.h
-conversions.o: $(hdrdir)/ruby/backward/2/limits.h
-conversions.o: $(hdrdir)/ruby/backward/2/long_long.h
-conversions.o: $(hdrdir)/ruby/backward/2/stdalign.h
-conversions.o: $(hdrdir)/ruby/backward/2/stdarg.h
-conversions.o: $(hdrdir)/ruby/defines.h
-conversions.o: $(hdrdir)/ruby/intern.h
-conversions.o: $(hdrdir)/ruby/internal/abi.h
-conversions.o: $(hdrdir)/ruby/internal/anyargs.h
-conversions.o: $(hdrdir)/ruby/internal/arithmetic.h
-conversions.o: $(hdrdir)/ruby/internal/arithmetic/char.h
-conversions.o: $(hdrdir)/ruby/internal/arithmetic/double.h
-conversions.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
-conversions.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
-conversions.o: $(hdrdir)/ruby/internal/arithmetic/int.h
-conversions.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
-conversions.o: $(hdrdir)/ruby/internal/arithmetic/long.h
-conversions.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
-conversions.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
-conversions.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
-conversions.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
-conversions.o: $(hdrdir)/ruby/internal/arithmetic/short.h
-conversions.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
-conversions.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
-conversions.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
-conversions.o: $(hdrdir)/ruby/internal/assume.h
-conversions.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
-conversions.o: $(hdrdir)/ruby/internal/attr/artificial.h
-conversions.o: $(hdrdir)/ruby/internal/attr/cold.h
-conversions.o: $(hdrdir)/ruby/internal/attr/const.h
-conversions.o: $(hdrdir)/ruby/internal/attr/constexpr.h
-conversions.o: $(hdrdir)/ruby/internal/attr/deprecated.h
-conversions.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
-conversions.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
-conversions.o: $(hdrdir)/ruby/internal/attr/error.h
-conversions.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
-conversions.o: $(hdrdir)/ruby/internal/attr/forceinline.h
-conversions.o: $(hdrdir)/ruby/internal/attr/format.h
-conversions.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
-conversions.o: $(hdrdir)/ruby/internal/attr/noalias.h
-conversions.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
-conversions.o: $(hdrdir)/ruby/internal/attr/noexcept.h
-conversions.o: $(hdrdir)/ruby/internal/attr/noinline.h
-conversions.o: $(hdrdir)/ruby/internal/attr/nonnull.h
-conversions.o: $(hdrdir)/ruby/internal/attr/noreturn.h
-conversions.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
-conversions.o: $(hdrdir)/ruby/internal/attr/pure.h
-conversions.o: $(hdrdir)/ruby/internal/attr/restrict.h
-conversions.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
-conversions.o: $(hdrdir)/ruby/internal/attr/warning.h
-conversions.o: $(hdrdir)/ruby/internal/attr/weakref.h
-conversions.o: $(hdrdir)/ruby/internal/cast.h
-conversions.o: $(hdrdir)/ruby/internal/compiler_is.h
-conversions.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
-conversions.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
-conversions.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
-conversions.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
-conversions.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
-conversions.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
-conversions.o: $(hdrdir)/ruby/internal/compiler_since.h
-conversions.o: $(hdrdir)/ruby/internal/config.h
-conversions.o: $(hdrdir)/ruby/internal/constant_p.h
-conversions.o: $(hdrdir)/ruby/internal/core.h
-conversions.o: $(hdrdir)/ruby/internal/core/rarray.h
-conversions.o: $(hdrdir)/ruby/internal/core/rbasic.h
-conversions.o: $(hdrdir)/ruby/internal/core/rbignum.h
-conversions.o: $(hdrdir)/ruby/internal/core/rclass.h
-conversions.o: $(hdrdir)/ruby/internal/core/rdata.h
-conversions.o: $(hdrdir)/ruby/internal/core/rfile.h
-conversions.o: $(hdrdir)/ruby/internal/core/rhash.h
-conversions.o: $(hdrdir)/ruby/internal/core/robject.h
-conversions.o: $(hdrdir)/ruby/internal/core/rregexp.h
-conversions.o: $(hdrdir)/ruby/internal/core/rstring.h
-conversions.o: $(hdrdir)/ruby/internal/core/rstruct.h
-conversions.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
-conversions.o: $(hdrdir)/ruby/internal/ctype.h
-conversions.o: $(hdrdir)/ruby/internal/dllexport.h
-conversions.o: $(hdrdir)/ruby/internal/dosish.h
-conversions.o: $(hdrdir)/ruby/internal/error.h
-conversions.o: $(hdrdir)/ruby/internal/eval.h
-conversions.o: $(hdrdir)/ruby/internal/event.h
-conversions.o: $(hdrdir)/ruby/internal/fl_type.h
-conversions.o: $(hdrdir)/ruby/internal/gc.h
-conversions.o: $(hdrdir)/ruby/internal/glob.h
-conversions.o: $(hdrdir)/ruby/internal/globals.h
-conversions.o: $(hdrdir)/ruby/internal/has/attribute.h
-conversions.o: $(hdrdir)/ruby/internal/has/builtin.h
-conversions.o: $(hdrdir)/ruby/internal/has/c_attribute.h
-conversions.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
-conversions.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
-conversions.o: $(hdrdir)/ruby/internal/has/extension.h
-conversions.o: $(hdrdir)/ruby/internal/has/feature.h
-conversions.o: $(hdrdir)/ruby/internal/has/warning.h
-conversions.o: $(hdrdir)/ruby/internal/intern/array.h
-conversions.o: $(hdrdir)/ruby/internal/intern/bignum.h
-conversions.o: $(hdrdir)/ruby/internal/intern/class.h
-conversions.o: $(hdrdir)/ruby/internal/intern/compar.h
-conversions.o: $(hdrdir)/ruby/internal/intern/complex.h
-conversions.o: $(hdrdir)/ruby/internal/intern/cont.h
-conversions.o: $(hdrdir)/ruby/internal/intern/dir.h
-conversions.o: $(hdrdir)/ruby/internal/intern/enum.h
-conversions.o: $(hdrdir)/ruby/internal/intern/enumerator.h
-conversions.o: $(hdrdir)/ruby/internal/intern/error.h
-conversions.o: $(hdrdir)/ruby/internal/intern/eval.h
-conversions.o: $(hdrdir)/ruby/internal/intern/file.h
-conversions.o: $(hdrdir)/ruby/internal/intern/hash.h
-conversions.o: $(hdrdir)/ruby/internal/intern/io.h
-conversions.o: $(hdrdir)/ruby/internal/intern/load.h
-conversions.o: $(hdrdir)/ruby/internal/intern/marshal.h
-conversions.o: $(hdrdir)/ruby/internal/intern/numeric.h
-conversions.o: $(hdrdir)/ruby/internal/intern/object.h
-conversions.o: $(hdrdir)/ruby/internal/intern/parse.h
-conversions.o: $(hdrdir)/ruby/internal/intern/proc.h
-conversions.o: $(hdrdir)/ruby/internal/intern/process.h
-conversions.o: $(hdrdir)/ruby/internal/intern/random.h
-conversions.o: $(hdrdir)/ruby/internal/intern/range.h
-conversions.o: $(hdrdir)/ruby/internal/intern/rational.h
-conversions.o: $(hdrdir)/ruby/internal/intern/re.h
-conversions.o: $(hdrdir)/ruby/internal/intern/ruby.h
-conversions.o: $(hdrdir)/ruby/internal/intern/select.h
-conversions.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
-conversions.o: $(hdrdir)/ruby/internal/intern/signal.h
-conversions.o: $(hdrdir)/ruby/internal/intern/sprintf.h
-conversions.o: $(hdrdir)/ruby/internal/intern/string.h
-conversions.o: $(hdrdir)/ruby/internal/intern/struct.h
-conversions.o: $(hdrdir)/ruby/internal/intern/thread.h
-conversions.o: $(hdrdir)/ruby/internal/intern/time.h
-conversions.o: $(hdrdir)/ruby/internal/intern/variable.h
-conversions.o: $(hdrdir)/ruby/internal/intern/vm.h
-conversions.o: $(hdrdir)/ruby/internal/interpreter.h
-conversions.o: $(hdrdir)/ruby/internal/iterator.h
-conversions.o: $(hdrdir)/ruby/internal/memory.h
-conversions.o: $(hdrdir)/ruby/internal/method.h
-conversions.o: $(hdrdir)/ruby/internal/module.h
-conversions.o: $(hdrdir)/ruby/internal/newobj.h
-conversions.o: $(hdrdir)/ruby/internal/scan_args.h
-conversions.o: $(hdrdir)/ruby/internal/special_consts.h
-conversions.o: $(hdrdir)/ruby/internal/static_assert.h
-conversions.o: $(hdrdir)/ruby/internal/stdalign.h
-conversions.o: $(hdrdir)/ruby/internal/stdbool.h
-conversions.o: $(hdrdir)/ruby/internal/stdckdint.h
-conversions.o: $(hdrdir)/ruby/internal/symbol.h
-conversions.o: $(hdrdir)/ruby/internal/value.h
-conversions.o: $(hdrdir)/ruby/internal/value_type.h
-conversions.o: $(hdrdir)/ruby/internal/variable.h
-conversions.o: $(hdrdir)/ruby/internal/warning_push.h
-conversions.o: $(hdrdir)/ruby/internal/xmalloc.h
-conversions.o: $(hdrdir)/ruby/missing.h
-conversions.o: $(hdrdir)/ruby/ruby.h
-conversions.o: $(hdrdir)/ruby/st.h
-conversions.o: $(hdrdir)/ruby/subst.h
-conversions.o: closure.h
-conversions.o: conversions.c
-conversions.o: conversions.h
-conversions.o: fiddle.h
-conversions.o: function.h
-fiddle.o: $(RUBY_EXTCONF_H)
-fiddle.o: $(arch_hdrdir)/ruby/config.h
-fiddle.o: $(hdrdir)/ruby.h
-fiddle.o: $(hdrdir)/ruby/assert.h
-fiddle.o: $(hdrdir)/ruby/backward.h
-fiddle.o: $(hdrdir)/ruby/backward/2/assume.h
-fiddle.o: $(hdrdir)/ruby/backward/2/attributes.h
-fiddle.o: $(hdrdir)/ruby/backward/2/bool.h
-fiddle.o: $(hdrdir)/ruby/backward/2/inttypes.h
-fiddle.o: $(hdrdir)/ruby/backward/2/limits.h
-fiddle.o: $(hdrdir)/ruby/backward/2/long_long.h
-fiddle.o: $(hdrdir)/ruby/backward/2/stdalign.h
-fiddle.o: $(hdrdir)/ruby/backward/2/stdarg.h
-fiddle.o: $(hdrdir)/ruby/defines.h
-fiddle.o: $(hdrdir)/ruby/intern.h
-fiddle.o: $(hdrdir)/ruby/internal/abi.h
-fiddle.o: $(hdrdir)/ruby/internal/anyargs.h
-fiddle.o: $(hdrdir)/ruby/internal/arithmetic.h
-fiddle.o: $(hdrdir)/ruby/internal/arithmetic/char.h
-fiddle.o: $(hdrdir)/ruby/internal/arithmetic/double.h
-fiddle.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
-fiddle.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
-fiddle.o: $(hdrdir)/ruby/internal/arithmetic/int.h
-fiddle.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
-fiddle.o: $(hdrdir)/ruby/internal/arithmetic/long.h
-fiddle.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
-fiddle.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
-fiddle.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
-fiddle.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
-fiddle.o: $(hdrdir)/ruby/internal/arithmetic/short.h
-fiddle.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
-fiddle.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
-fiddle.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
-fiddle.o: $(hdrdir)/ruby/internal/assume.h
-fiddle.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
-fiddle.o: $(hdrdir)/ruby/internal/attr/artificial.h
-fiddle.o: $(hdrdir)/ruby/internal/attr/cold.h
-fiddle.o: $(hdrdir)/ruby/internal/attr/const.h
-fiddle.o: $(hdrdir)/ruby/internal/attr/constexpr.h
-fiddle.o: $(hdrdir)/ruby/internal/attr/deprecated.h
-fiddle.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
-fiddle.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
-fiddle.o: $(hdrdir)/ruby/internal/attr/error.h
-fiddle.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
-fiddle.o: $(hdrdir)/ruby/internal/attr/forceinline.h
-fiddle.o: $(hdrdir)/ruby/internal/attr/format.h
-fiddle.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
-fiddle.o: $(hdrdir)/ruby/internal/attr/noalias.h
-fiddle.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
-fiddle.o: $(hdrdir)/ruby/internal/attr/noexcept.h
-fiddle.o: $(hdrdir)/ruby/internal/attr/noinline.h
-fiddle.o: $(hdrdir)/ruby/internal/attr/nonnull.h
-fiddle.o: $(hdrdir)/ruby/internal/attr/noreturn.h
-fiddle.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
-fiddle.o: $(hdrdir)/ruby/internal/attr/pure.h
-fiddle.o: $(hdrdir)/ruby/internal/attr/restrict.h
-fiddle.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
-fiddle.o: $(hdrdir)/ruby/internal/attr/warning.h
-fiddle.o: $(hdrdir)/ruby/internal/attr/weakref.h
-fiddle.o: $(hdrdir)/ruby/internal/cast.h
-fiddle.o: $(hdrdir)/ruby/internal/compiler_is.h
-fiddle.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
-fiddle.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
-fiddle.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
-fiddle.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
-fiddle.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
-fiddle.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
-fiddle.o: $(hdrdir)/ruby/internal/compiler_since.h
-fiddle.o: $(hdrdir)/ruby/internal/config.h
-fiddle.o: $(hdrdir)/ruby/internal/constant_p.h
-fiddle.o: $(hdrdir)/ruby/internal/core.h
-fiddle.o: $(hdrdir)/ruby/internal/core/rarray.h
-fiddle.o: $(hdrdir)/ruby/internal/core/rbasic.h
-fiddle.o: $(hdrdir)/ruby/internal/core/rbignum.h
-fiddle.o: $(hdrdir)/ruby/internal/core/rclass.h
-fiddle.o: $(hdrdir)/ruby/internal/core/rdata.h
-fiddle.o: $(hdrdir)/ruby/internal/core/rfile.h
-fiddle.o: $(hdrdir)/ruby/internal/core/rhash.h
-fiddle.o: $(hdrdir)/ruby/internal/core/robject.h
-fiddle.o: $(hdrdir)/ruby/internal/core/rregexp.h
-fiddle.o: $(hdrdir)/ruby/internal/core/rstring.h
-fiddle.o: $(hdrdir)/ruby/internal/core/rstruct.h
-fiddle.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
-fiddle.o: $(hdrdir)/ruby/internal/ctype.h
-fiddle.o: $(hdrdir)/ruby/internal/dllexport.h
-fiddle.o: $(hdrdir)/ruby/internal/dosish.h
-fiddle.o: $(hdrdir)/ruby/internal/error.h
-fiddle.o: $(hdrdir)/ruby/internal/eval.h
-fiddle.o: $(hdrdir)/ruby/internal/event.h
-fiddle.o: $(hdrdir)/ruby/internal/fl_type.h
-fiddle.o: $(hdrdir)/ruby/internal/gc.h
-fiddle.o: $(hdrdir)/ruby/internal/glob.h
-fiddle.o: $(hdrdir)/ruby/internal/globals.h
-fiddle.o: $(hdrdir)/ruby/internal/has/attribute.h
-fiddle.o: $(hdrdir)/ruby/internal/has/builtin.h
-fiddle.o: $(hdrdir)/ruby/internal/has/c_attribute.h
-fiddle.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
-fiddle.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
-fiddle.o: $(hdrdir)/ruby/internal/has/extension.h
-fiddle.o: $(hdrdir)/ruby/internal/has/feature.h
-fiddle.o: $(hdrdir)/ruby/internal/has/warning.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/array.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/bignum.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/class.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/compar.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/complex.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/cont.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/dir.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/enum.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/enumerator.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/error.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/eval.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/file.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/hash.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/io.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/load.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/marshal.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/numeric.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/object.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/parse.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/proc.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/process.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/random.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/range.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/rational.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/re.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/ruby.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/select.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/signal.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/sprintf.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/string.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/struct.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/thread.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/time.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/variable.h
-fiddle.o: $(hdrdir)/ruby/internal/intern/vm.h
-fiddle.o: $(hdrdir)/ruby/internal/interpreter.h
-fiddle.o: $(hdrdir)/ruby/internal/iterator.h
-fiddle.o: $(hdrdir)/ruby/internal/memory.h
-fiddle.o: $(hdrdir)/ruby/internal/method.h
-fiddle.o: $(hdrdir)/ruby/internal/module.h
-fiddle.o: $(hdrdir)/ruby/internal/newobj.h
-fiddle.o: $(hdrdir)/ruby/internal/scan_args.h
-fiddle.o: $(hdrdir)/ruby/internal/special_consts.h
-fiddle.o: $(hdrdir)/ruby/internal/static_assert.h
-fiddle.o: $(hdrdir)/ruby/internal/stdalign.h
-fiddle.o: $(hdrdir)/ruby/internal/stdbool.h
-fiddle.o: $(hdrdir)/ruby/internal/stdckdint.h
-fiddle.o: $(hdrdir)/ruby/internal/symbol.h
-fiddle.o: $(hdrdir)/ruby/internal/value.h
-fiddle.o: $(hdrdir)/ruby/internal/value_type.h
-fiddle.o: $(hdrdir)/ruby/internal/variable.h
-fiddle.o: $(hdrdir)/ruby/internal/warning_push.h
-fiddle.o: $(hdrdir)/ruby/internal/xmalloc.h
-fiddle.o: $(hdrdir)/ruby/missing.h
-fiddle.o: $(hdrdir)/ruby/ruby.h
-fiddle.o: $(hdrdir)/ruby/st.h
-fiddle.o: $(hdrdir)/ruby/subst.h
-fiddle.o: closure.h
-fiddle.o: conversions.h
-fiddle.o: fiddle.c
-fiddle.o: fiddle.h
-fiddle.o: function.h
-function.o: $(RUBY_EXTCONF_H)
-function.o: $(arch_hdrdir)/ruby/config.h
-function.o: $(hdrdir)/ruby.h
-function.o: $(hdrdir)/ruby/assert.h
-function.o: $(hdrdir)/ruby/backward.h
-function.o: $(hdrdir)/ruby/backward/2/assume.h
-function.o: $(hdrdir)/ruby/backward/2/attributes.h
-function.o: $(hdrdir)/ruby/backward/2/bool.h
-function.o: $(hdrdir)/ruby/backward/2/inttypes.h
-function.o: $(hdrdir)/ruby/backward/2/limits.h
-function.o: $(hdrdir)/ruby/backward/2/long_long.h
-function.o: $(hdrdir)/ruby/backward/2/stdalign.h
-function.o: $(hdrdir)/ruby/backward/2/stdarg.h
-function.o: $(hdrdir)/ruby/defines.h
-function.o: $(hdrdir)/ruby/intern.h
-function.o: $(hdrdir)/ruby/internal/abi.h
-function.o: $(hdrdir)/ruby/internal/anyargs.h
-function.o: $(hdrdir)/ruby/internal/arithmetic.h
-function.o: $(hdrdir)/ruby/internal/arithmetic/char.h
-function.o: $(hdrdir)/ruby/internal/arithmetic/double.h
-function.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
-function.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
-function.o: $(hdrdir)/ruby/internal/arithmetic/int.h
-function.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
-function.o: $(hdrdir)/ruby/internal/arithmetic/long.h
-function.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
-function.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
-function.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
-function.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
-function.o: $(hdrdir)/ruby/internal/arithmetic/short.h
-function.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
-function.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
-function.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
-function.o: $(hdrdir)/ruby/internal/assume.h
-function.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
-function.o: $(hdrdir)/ruby/internal/attr/artificial.h
-function.o: $(hdrdir)/ruby/internal/attr/cold.h
-function.o: $(hdrdir)/ruby/internal/attr/const.h
-function.o: $(hdrdir)/ruby/internal/attr/constexpr.h
-function.o: $(hdrdir)/ruby/internal/attr/deprecated.h
-function.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
-function.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
-function.o: $(hdrdir)/ruby/internal/attr/error.h
-function.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
-function.o: $(hdrdir)/ruby/internal/attr/forceinline.h
-function.o: $(hdrdir)/ruby/internal/attr/format.h
-function.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
-function.o: $(hdrdir)/ruby/internal/attr/noalias.h
-function.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
-function.o: $(hdrdir)/ruby/internal/attr/noexcept.h
-function.o: $(hdrdir)/ruby/internal/attr/noinline.h
-function.o: $(hdrdir)/ruby/internal/attr/nonnull.h
-function.o: $(hdrdir)/ruby/internal/attr/noreturn.h
-function.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
-function.o: $(hdrdir)/ruby/internal/attr/pure.h
-function.o: $(hdrdir)/ruby/internal/attr/restrict.h
-function.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
-function.o: $(hdrdir)/ruby/internal/attr/warning.h
-function.o: $(hdrdir)/ruby/internal/attr/weakref.h
-function.o: $(hdrdir)/ruby/internal/cast.h
-function.o: $(hdrdir)/ruby/internal/compiler_is.h
-function.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
-function.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
-function.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
-function.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
-function.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
-function.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
-function.o: $(hdrdir)/ruby/internal/compiler_since.h
-function.o: $(hdrdir)/ruby/internal/config.h
-function.o: $(hdrdir)/ruby/internal/constant_p.h
-function.o: $(hdrdir)/ruby/internal/core.h
-function.o: $(hdrdir)/ruby/internal/core/rarray.h
-function.o: $(hdrdir)/ruby/internal/core/rbasic.h
-function.o: $(hdrdir)/ruby/internal/core/rbignum.h
-function.o: $(hdrdir)/ruby/internal/core/rclass.h
-function.o: $(hdrdir)/ruby/internal/core/rdata.h
-function.o: $(hdrdir)/ruby/internal/core/rfile.h
-function.o: $(hdrdir)/ruby/internal/core/rhash.h
-function.o: $(hdrdir)/ruby/internal/core/robject.h
-function.o: $(hdrdir)/ruby/internal/core/rregexp.h
-function.o: $(hdrdir)/ruby/internal/core/rstring.h
-function.o: $(hdrdir)/ruby/internal/core/rstruct.h
-function.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
-function.o: $(hdrdir)/ruby/internal/ctype.h
-function.o: $(hdrdir)/ruby/internal/dllexport.h
-function.o: $(hdrdir)/ruby/internal/dosish.h
-function.o: $(hdrdir)/ruby/internal/error.h
-function.o: $(hdrdir)/ruby/internal/eval.h
-function.o: $(hdrdir)/ruby/internal/event.h
-function.o: $(hdrdir)/ruby/internal/fl_type.h
-function.o: $(hdrdir)/ruby/internal/gc.h
-function.o: $(hdrdir)/ruby/internal/glob.h
-function.o: $(hdrdir)/ruby/internal/globals.h
-function.o: $(hdrdir)/ruby/internal/has/attribute.h
-function.o: $(hdrdir)/ruby/internal/has/builtin.h
-function.o: $(hdrdir)/ruby/internal/has/c_attribute.h
-function.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
-function.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
-function.o: $(hdrdir)/ruby/internal/has/extension.h
-function.o: $(hdrdir)/ruby/internal/has/feature.h
-function.o: $(hdrdir)/ruby/internal/has/warning.h
-function.o: $(hdrdir)/ruby/internal/intern/array.h
-function.o: $(hdrdir)/ruby/internal/intern/bignum.h
-function.o: $(hdrdir)/ruby/internal/intern/class.h
-function.o: $(hdrdir)/ruby/internal/intern/compar.h
-function.o: $(hdrdir)/ruby/internal/intern/complex.h
-function.o: $(hdrdir)/ruby/internal/intern/cont.h
-function.o: $(hdrdir)/ruby/internal/intern/dir.h
-function.o: $(hdrdir)/ruby/internal/intern/enum.h
-function.o: $(hdrdir)/ruby/internal/intern/enumerator.h
-function.o: $(hdrdir)/ruby/internal/intern/error.h
-function.o: $(hdrdir)/ruby/internal/intern/eval.h
-function.o: $(hdrdir)/ruby/internal/intern/file.h
-function.o: $(hdrdir)/ruby/internal/intern/hash.h
-function.o: $(hdrdir)/ruby/internal/intern/io.h
-function.o: $(hdrdir)/ruby/internal/intern/load.h
-function.o: $(hdrdir)/ruby/internal/intern/marshal.h
-function.o: $(hdrdir)/ruby/internal/intern/numeric.h
-function.o: $(hdrdir)/ruby/internal/intern/object.h
-function.o: $(hdrdir)/ruby/internal/intern/parse.h
-function.o: $(hdrdir)/ruby/internal/intern/proc.h
-function.o: $(hdrdir)/ruby/internal/intern/process.h
-function.o: $(hdrdir)/ruby/internal/intern/random.h
-function.o: $(hdrdir)/ruby/internal/intern/range.h
-function.o: $(hdrdir)/ruby/internal/intern/rational.h
-function.o: $(hdrdir)/ruby/internal/intern/re.h
-function.o: $(hdrdir)/ruby/internal/intern/ruby.h
-function.o: $(hdrdir)/ruby/internal/intern/select.h
-function.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
-function.o: $(hdrdir)/ruby/internal/intern/signal.h
-function.o: $(hdrdir)/ruby/internal/intern/sprintf.h
-function.o: $(hdrdir)/ruby/internal/intern/string.h
-function.o: $(hdrdir)/ruby/internal/intern/struct.h
-function.o: $(hdrdir)/ruby/internal/intern/thread.h
-function.o: $(hdrdir)/ruby/internal/intern/time.h
-function.o: $(hdrdir)/ruby/internal/intern/variable.h
-function.o: $(hdrdir)/ruby/internal/intern/vm.h
-function.o: $(hdrdir)/ruby/internal/interpreter.h
-function.o: $(hdrdir)/ruby/internal/iterator.h
-function.o: $(hdrdir)/ruby/internal/memory.h
-function.o: $(hdrdir)/ruby/internal/method.h
-function.o: $(hdrdir)/ruby/internal/module.h
-function.o: $(hdrdir)/ruby/internal/newobj.h
-function.o: $(hdrdir)/ruby/internal/scan_args.h
-function.o: $(hdrdir)/ruby/internal/special_consts.h
-function.o: $(hdrdir)/ruby/internal/static_assert.h
-function.o: $(hdrdir)/ruby/internal/stdalign.h
-function.o: $(hdrdir)/ruby/internal/stdbool.h
-function.o: $(hdrdir)/ruby/internal/stdckdint.h
-function.o: $(hdrdir)/ruby/internal/symbol.h
-function.o: $(hdrdir)/ruby/internal/value.h
-function.o: $(hdrdir)/ruby/internal/value_type.h
-function.o: $(hdrdir)/ruby/internal/variable.h
-function.o: $(hdrdir)/ruby/internal/warning_push.h
-function.o: $(hdrdir)/ruby/internal/xmalloc.h
-function.o: $(hdrdir)/ruby/missing.h
-function.o: $(hdrdir)/ruby/ruby.h
-function.o: $(hdrdir)/ruby/st.h
-function.o: $(hdrdir)/ruby/subst.h
-function.o: $(hdrdir)/ruby/thread.h
-function.o: closure.h
-function.o: conversions.h
-function.o: fiddle.h
-function.o: function.c
-function.o: function.h
-handle.o: $(RUBY_EXTCONF_H)
-handle.o: $(arch_hdrdir)/ruby/config.h
-handle.o: $(hdrdir)/ruby.h
-handle.o: $(hdrdir)/ruby/assert.h
-handle.o: $(hdrdir)/ruby/backward.h
-handle.o: $(hdrdir)/ruby/backward/2/assume.h
-handle.o: $(hdrdir)/ruby/backward/2/attributes.h
-handle.o: $(hdrdir)/ruby/backward/2/bool.h
-handle.o: $(hdrdir)/ruby/backward/2/inttypes.h
-handle.o: $(hdrdir)/ruby/backward/2/limits.h
-handle.o: $(hdrdir)/ruby/backward/2/long_long.h
-handle.o: $(hdrdir)/ruby/backward/2/stdalign.h
-handle.o: $(hdrdir)/ruby/backward/2/stdarg.h
-handle.o: $(hdrdir)/ruby/defines.h
-handle.o: $(hdrdir)/ruby/intern.h
-handle.o: $(hdrdir)/ruby/internal/abi.h
-handle.o: $(hdrdir)/ruby/internal/anyargs.h
-handle.o: $(hdrdir)/ruby/internal/arithmetic.h
-handle.o: $(hdrdir)/ruby/internal/arithmetic/char.h
-handle.o: $(hdrdir)/ruby/internal/arithmetic/double.h
-handle.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
-handle.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
-handle.o: $(hdrdir)/ruby/internal/arithmetic/int.h
-handle.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
-handle.o: $(hdrdir)/ruby/internal/arithmetic/long.h
-handle.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
-handle.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
-handle.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
-handle.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
-handle.o: $(hdrdir)/ruby/internal/arithmetic/short.h
-handle.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
-handle.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
-handle.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
-handle.o: $(hdrdir)/ruby/internal/assume.h
-handle.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
-handle.o: $(hdrdir)/ruby/internal/attr/artificial.h
-handle.o: $(hdrdir)/ruby/internal/attr/cold.h
-handle.o: $(hdrdir)/ruby/internal/attr/const.h
-handle.o: $(hdrdir)/ruby/internal/attr/constexpr.h
-handle.o: $(hdrdir)/ruby/internal/attr/deprecated.h
-handle.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
-handle.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
-handle.o: $(hdrdir)/ruby/internal/attr/error.h
-handle.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
-handle.o: $(hdrdir)/ruby/internal/attr/forceinline.h
-handle.o: $(hdrdir)/ruby/internal/attr/format.h
-handle.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
-handle.o: $(hdrdir)/ruby/internal/attr/noalias.h
-handle.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
-handle.o: $(hdrdir)/ruby/internal/attr/noexcept.h
-handle.o: $(hdrdir)/ruby/internal/attr/noinline.h
-handle.o: $(hdrdir)/ruby/internal/attr/nonnull.h
-handle.o: $(hdrdir)/ruby/internal/attr/noreturn.h
-handle.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
-handle.o: $(hdrdir)/ruby/internal/attr/pure.h
-handle.o: $(hdrdir)/ruby/internal/attr/restrict.h
-handle.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
-handle.o: $(hdrdir)/ruby/internal/attr/warning.h
-handle.o: $(hdrdir)/ruby/internal/attr/weakref.h
-handle.o: $(hdrdir)/ruby/internal/cast.h
-handle.o: $(hdrdir)/ruby/internal/compiler_is.h
-handle.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
-handle.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
-handle.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
-handle.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
-handle.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
-handle.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
-handle.o: $(hdrdir)/ruby/internal/compiler_since.h
-handle.o: $(hdrdir)/ruby/internal/config.h
-handle.o: $(hdrdir)/ruby/internal/constant_p.h
-handle.o: $(hdrdir)/ruby/internal/core.h
-handle.o: $(hdrdir)/ruby/internal/core/rarray.h
-handle.o: $(hdrdir)/ruby/internal/core/rbasic.h
-handle.o: $(hdrdir)/ruby/internal/core/rbignum.h
-handle.o: $(hdrdir)/ruby/internal/core/rclass.h
-handle.o: $(hdrdir)/ruby/internal/core/rdata.h
-handle.o: $(hdrdir)/ruby/internal/core/rfile.h
-handle.o: $(hdrdir)/ruby/internal/core/rhash.h
-handle.o: $(hdrdir)/ruby/internal/core/robject.h
-handle.o: $(hdrdir)/ruby/internal/core/rregexp.h
-handle.o: $(hdrdir)/ruby/internal/core/rstring.h
-handle.o: $(hdrdir)/ruby/internal/core/rstruct.h
-handle.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
-handle.o: $(hdrdir)/ruby/internal/ctype.h
-handle.o: $(hdrdir)/ruby/internal/dllexport.h
-handle.o: $(hdrdir)/ruby/internal/dosish.h
-handle.o: $(hdrdir)/ruby/internal/error.h
-handle.o: $(hdrdir)/ruby/internal/eval.h
-handle.o: $(hdrdir)/ruby/internal/event.h
-handle.o: $(hdrdir)/ruby/internal/fl_type.h
-handle.o: $(hdrdir)/ruby/internal/gc.h
-handle.o: $(hdrdir)/ruby/internal/glob.h
-handle.o: $(hdrdir)/ruby/internal/globals.h
-handle.o: $(hdrdir)/ruby/internal/has/attribute.h
-handle.o: $(hdrdir)/ruby/internal/has/builtin.h
-handle.o: $(hdrdir)/ruby/internal/has/c_attribute.h
-handle.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
-handle.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
-handle.o: $(hdrdir)/ruby/internal/has/extension.h
-handle.o: $(hdrdir)/ruby/internal/has/feature.h
-handle.o: $(hdrdir)/ruby/internal/has/warning.h
-handle.o: $(hdrdir)/ruby/internal/intern/array.h
-handle.o: $(hdrdir)/ruby/internal/intern/bignum.h
-handle.o: $(hdrdir)/ruby/internal/intern/class.h
-handle.o: $(hdrdir)/ruby/internal/intern/compar.h
-handle.o: $(hdrdir)/ruby/internal/intern/complex.h
-handle.o: $(hdrdir)/ruby/internal/intern/cont.h
-handle.o: $(hdrdir)/ruby/internal/intern/dir.h
-handle.o: $(hdrdir)/ruby/internal/intern/enum.h
-handle.o: $(hdrdir)/ruby/internal/intern/enumerator.h
-handle.o: $(hdrdir)/ruby/internal/intern/error.h
-handle.o: $(hdrdir)/ruby/internal/intern/eval.h
-handle.o: $(hdrdir)/ruby/internal/intern/file.h
-handle.o: $(hdrdir)/ruby/internal/intern/hash.h
-handle.o: $(hdrdir)/ruby/internal/intern/io.h
-handle.o: $(hdrdir)/ruby/internal/intern/load.h
-handle.o: $(hdrdir)/ruby/internal/intern/marshal.h
-handle.o: $(hdrdir)/ruby/internal/intern/numeric.h
-handle.o: $(hdrdir)/ruby/internal/intern/object.h
-handle.o: $(hdrdir)/ruby/internal/intern/parse.h
-handle.o: $(hdrdir)/ruby/internal/intern/proc.h
-handle.o: $(hdrdir)/ruby/internal/intern/process.h
-handle.o: $(hdrdir)/ruby/internal/intern/random.h
-handle.o: $(hdrdir)/ruby/internal/intern/range.h
-handle.o: $(hdrdir)/ruby/internal/intern/rational.h
-handle.o: $(hdrdir)/ruby/internal/intern/re.h
-handle.o: $(hdrdir)/ruby/internal/intern/ruby.h
-handle.o: $(hdrdir)/ruby/internal/intern/select.h
-handle.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
-handle.o: $(hdrdir)/ruby/internal/intern/signal.h
-handle.o: $(hdrdir)/ruby/internal/intern/sprintf.h
-handle.o: $(hdrdir)/ruby/internal/intern/string.h
-handle.o: $(hdrdir)/ruby/internal/intern/struct.h
-handle.o: $(hdrdir)/ruby/internal/intern/thread.h
-handle.o: $(hdrdir)/ruby/internal/intern/time.h
-handle.o: $(hdrdir)/ruby/internal/intern/variable.h
-handle.o: $(hdrdir)/ruby/internal/intern/vm.h
-handle.o: $(hdrdir)/ruby/internal/interpreter.h
-handle.o: $(hdrdir)/ruby/internal/iterator.h
-handle.o: $(hdrdir)/ruby/internal/memory.h
-handle.o: $(hdrdir)/ruby/internal/method.h
-handle.o: $(hdrdir)/ruby/internal/module.h
-handle.o: $(hdrdir)/ruby/internal/newobj.h
-handle.o: $(hdrdir)/ruby/internal/scan_args.h
-handle.o: $(hdrdir)/ruby/internal/special_consts.h
-handle.o: $(hdrdir)/ruby/internal/static_assert.h
-handle.o: $(hdrdir)/ruby/internal/stdalign.h
-handle.o: $(hdrdir)/ruby/internal/stdbool.h
-handle.o: $(hdrdir)/ruby/internal/stdckdint.h
-handle.o: $(hdrdir)/ruby/internal/symbol.h
-handle.o: $(hdrdir)/ruby/internal/value.h
-handle.o: $(hdrdir)/ruby/internal/value_type.h
-handle.o: $(hdrdir)/ruby/internal/variable.h
-handle.o: $(hdrdir)/ruby/internal/warning_push.h
-handle.o: $(hdrdir)/ruby/internal/xmalloc.h
-handle.o: $(hdrdir)/ruby/missing.h
-handle.o: $(hdrdir)/ruby/ruby.h
-handle.o: $(hdrdir)/ruby/st.h
-handle.o: $(hdrdir)/ruby/subst.h
-handle.o: closure.h
-handle.o: conversions.h
-handle.o: fiddle.h
-handle.o: function.h
-handle.o: handle.c
-memory_view.o: $(RUBY_EXTCONF_H)
-memory_view.o: $(arch_hdrdir)/ruby/config.h
-memory_view.o: $(hdrdir)/ruby.h
-memory_view.o: $(hdrdir)/ruby/assert.h
-memory_view.o: $(hdrdir)/ruby/backward.h
-memory_view.o: $(hdrdir)/ruby/backward/2/assume.h
-memory_view.o: $(hdrdir)/ruby/backward/2/attributes.h
-memory_view.o: $(hdrdir)/ruby/backward/2/bool.h
-memory_view.o: $(hdrdir)/ruby/backward/2/inttypes.h
-memory_view.o: $(hdrdir)/ruby/backward/2/limits.h
-memory_view.o: $(hdrdir)/ruby/backward/2/long_long.h
-memory_view.o: $(hdrdir)/ruby/backward/2/stdalign.h
-memory_view.o: $(hdrdir)/ruby/backward/2/stdarg.h
-memory_view.o: $(hdrdir)/ruby/defines.h
-memory_view.o: $(hdrdir)/ruby/encoding.h
-memory_view.o: $(hdrdir)/ruby/intern.h
-memory_view.o: $(hdrdir)/ruby/internal/abi.h
-memory_view.o: $(hdrdir)/ruby/internal/anyargs.h
-memory_view.o: $(hdrdir)/ruby/internal/arithmetic.h
-memory_view.o: $(hdrdir)/ruby/internal/arithmetic/char.h
-memory_view.o: $(hdrdir)/ruby/internal/arithmetic/double.h
-memory_view.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
-memory_view.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
-memory_view.o: $(hdrdir)/ruby/internal/arithmetic/int.h
-memory_view.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
-memory_view.o: $(hdrdir)/ruby/internal/arithmetic/long.h
-memory_view.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
-memory_view.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
-memory_view.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
-memory_view.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
-memory_view.o: $(hdrdir)/ruby/internal/arithmetic/short.h
-memory_view.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
-memory_view.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
-memory_view.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
-memory_view.o: $(hdrdir)/ruby/internal/assume.h
-memory_view.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
-memory_view.o: $(hdrdir)/ruby/internal/attr/artificial.h
-memory_view.o: $(hdrdir)/ruby/internal/attr/cold.h
-memory_view.o: $(hdrdir)/ruby/internal/attr/const.h
-memory_view.o: $(hdrdir)/ruby/internal/attr/constexpr.h
-memory_view.o: $(hdrdir)/ruby/internal/attr/deprecated.h
-memory_view.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
-memory_view.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
-memory_view.o: $(hdrdir)/ruby/internal/attr/error.h
-memory_view.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
-memory_view.o: $(hdrdir)/ruby/internal/attr/forceinline.h
-memory_view.o: $(hdrdir)/ruby/internal/attr/format.h
-memory_view.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
-memory_view.o: $(hdrdir)/ruby/internal/attr/noalias.h
-memory_view.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
-memory_view.o: $(hdrdir)/ruby/internal/attr/noexcept.h
-memory_view.o: $(hdrdir)/ruby/internal/attr/noinline.h
-memory_view.o: $(hdrdir)/ruby/internal/attr/nonnull.h
-memory_view.o: $(hdrdir)/ruby/internal/attr/noreturn.h
-memory_view.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
-memory_view.o: $(hdrdir)/ruby/internal/attr/pure.h
-memory_view.o: $(hdrdir)/ruby/internal/attr/restrict.h
-memory_view.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
-memory_view.o: $(hdrdir)/ruby/internal/attr/warning.h
-memory_view.o: $(hdrdir)/ruby/internal/attr/weakref.h
-memory_view.o: $(hdrdir)/ruby/internal/cast.h
-memory_view.o: $(hdrdir)/ruby/internal/compiler_is.h
-memory_view.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
-memory_view.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
-memory_view.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
-memory_view.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
-memory_view.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
-memory_view.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
-memory_view.o: $(hdrdir)/ruby/internal/compiler_since.h
-memory_view.o: $(hdrdir)/ruby/internal/config.h
-memory_view.o: $(hdrdir)/ruby/internal/constant_p.h
-memory_view.o: $(hdrdir)/ruby/internal/core.h
-memory_view.o: $(hdrdir)/ruby/internal/core/rarray.h
-memory_view.o: $(hdrdir)/ruby/internal/core/rbasic.h
-memory_view.o: $(hdrdir)/ruby/internal/core/rbignum.h
-memory_view.o: $(hdrdir)/ruby/internal/core/rclass.h
-memory_view.o: $(hdrdir)/ruby/internal/core/rdata.h
-memory_view.o: $(hdrdir)/ruby/internal/core/rfile.h
-memory_view.o: $(hdrdir)/ruby/internal/core/rhash.h
-memory_view.o: $(hdrdir)/ruby/internal/core/robject.h
-memory_view.o: $(hdrdir)/ruby/internal/core/rregexp.h
-memory_view.o: $(hdrdir)/ruby/internal/core/rstring.h
-memory_view.o: $(hdrdir)/ruby/internal/core/rstruct.h
-memory_view.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
-memory_view.o: $(hdrdir)/ruby/internal/ctype.h
-memory_view.o: $(hdrdir)/ruby/internal/dllexport.h
-memory_view.o: $(hdrdir)/ruby/internal/dosish.h
-memory_view.o: $(hdrdir)/ruby/internal/encoding/coderange.h
-memory_view.o: $(hdrdir)/ruby/internal/encoding/ctype.h
-memory_view.o: $(hdrdir)/ruby/internal/encoding/encoding.h
-memory_view.o: $(hdrdir)/ruby/internal/encoding/pathname.h
-memory_view.o: $(hdrdir)/ruby/internal/encoding/re.h
-memory_view.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
-memory_view.o: $(hdrdir)/ruby/internal/encoding/string.h
-memory_view.o: $(hdrdir)/ruby/internal/encoding/symbol.h
-memory_view.o: $(hdrdir)/ruby/internal/encoding/transcode.h
-memory_view.o: $(hdrdir)/ruby/internal/error.h
-memory_view.o: $(hdrdir)/ruby/internal/eval.h
-memory_view.o: $(hdrdir)/ruby/internal/event.h
-memory_view.o: $(hdrdir)/ruby/internal/fl_type.h
-memory_view.o: $(hdrdir)/ruby/internal/gc.h
-memory_view.o: $(hdrdir)/ruby/internal/glob.h
-memory_view.o: $(hdrdir)/ruby/internal/globals.h
-memory_view.o: $(hdrdir)/ruby/internal/has/attribute.h
-memory_view.o: $(hdrdir)/ruby/internal/has/builtin.h
-memory_view.o: $(hdrdir)/ruby/internal/has/c_attribute.h
-memory_view.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
-memory_view.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
-memory_view.o: $(hdrdir)/ruby/internal/has/extension.h
-memory_view.o: $(hdrdir)/ruby/internal/has/feature.h
-memory_view.o: $(hdrdir)/ruby/internal/has/warning.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/array.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/bignum.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/class.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/compar.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/complex.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/cont.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/dir.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/enum.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/enumerator.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/error.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/eval.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/file.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/hash.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/io.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/load.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/marshal.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/numeric.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/object.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/parse.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/proc.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/process.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/random.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/range.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/rational.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/re.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/ruby.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/select.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/signal.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/sprintf.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/string.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/struct.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/thread.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/time.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/variable.h
-memory_view.o: $(hdrdir)/ruby/internal/intern/vm.h
-memory_view.o: $(hdrdir)/ruby/internal/interpreter.h
-memory_view.o: $(hdrdir)/ruby/internal/iterator.h
-memory_view.o: $(hdrdir)/ruby/internal/memory.h
-memory_view.o: $(hdrdir)/ruby/internal/method.h
-memory_view.o: $(hdrdir)/ruby/internal/module.h
-memory_view.o: $(hdrdir)/ruby/internal/newobj.h
-memory_view.o: $(hdrdir)/ruby/internal/scan_args.h
-memory_view.o: $(hdrdir)/ruby/internal/special_consts.h
-memory_view.o: $(hdrdir)/ruby/internal/static_assert.h
-memory_view.o: $(hdrdir)/ruby/internal/stdalign.h
-memory_view.o: $(hdrdir)/ruby/internal/stdbool.h
-memory_view.o: $(hdrdir)/ruby/internal/stdckdint.h
-memory_view.o: $(hdrdir)/ruby/internal/symbol.h
-memory_view.o: $(hdrdir)/ruby/internal/value.h
-memory_view.o: $(hdrdir)/ruby/internal/value_type.h
-memory_view.o: $(hdrdir)/ruby/internal/variable.h
-memory_view.o: $(hdrdir)/ruby/internal/warning_push.h
-memory_view.o: $(hdrdir)/ruby/internal/xmalloc.h
-memory_view.o: $(hdrdir)/ruby/memory_view.h
-memory_view.o: $(hdrdir)/ruby/missing.h
-memory_view.o: $(hdrdir)/ruby/onigmo.h
-memory_view.o: $(hdrdir)/ruby/oniguruma.h
-memory_view.o: $(hdrdir)/ruby/ruby.h
-memory_view.o: $(hdrdir)/ruby/st.h
-memory_view.o: $(hdrdir)/ruby/subst.h
-memory_view.o: closure.h
-memory_view.o: conversions.h
-memory_view.o: fiddle.h
-memory_view.o: function.h
-memory_view.o: memory_view.c
-pinned.o: $(RUBY_EXTCONF_H)
-pinned.o: $(arch_hdrdir)/ruby/config.h
-pinned.o: $(hdrdir)/ruby.h
-pinned.o: $(hdrdir)/ruby/assert.h
-pinned.o: $(hdrdir)/ruby/backward.h
-pinned.o: $(hdrdir)/ruby/backward/2/assume.h
-pinned.o: $(hdrdir)/ruby/backward/2/attributes.h
-pinned.o: $(hdrdir)/ruby/backward/2/bool.h
-pinned.o: $(hdrdir)/ruby/backward/2/inttypes.h
-pinned.o: $(hdrdir)/ruby/backward/2/limits.h
-pinned.o: $(hdrdir)/ruby/backward/2/long_long.h
-pinned.o: $(hdrdir)/ruby/backward/2/stdalign.h
-pinned.o: $(hdrdir)/ruby/backward/2/stdarg.h
-pinned.o: $(hdrdir)/ruby/defines.h
-pinned.o: $(hdrdir)/ruby/intern.h
-pinned.o: $(hdrdir)/ruby/internal/abi.h
-pinned.o: $(hdrdir)/ruby/internal/anyargs.h
-pinned.o: $(hdrdir)/ruby/internal/arithmetic.h
-pinned.o: $(hdrdir)/ruby/internal/arithmetic/char.h
-pinned.o: $(hdrdir)/ruby/internal/arithmetic/double.h
-pinned.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
-pinned.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
-pinned.o: $(hdrdir)/ruby/internal/arithmetic/int.h
-pinned.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
-pinned.o: $(hdrdir)/ruby/internal/arithmetic/long.h
-pinned.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
-pinned.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
-pinned.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
-pinned.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
-pinned.o: $(hdrdir)/ruby/internal/arithmetic/short.h
-pinned.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
-pinned.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
-pinned.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
-pinned.o: $(hdrdir)/ruby/internal/assume.h
-pinned.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
-pinned.o: $(hdrdir)/ruby/internal/attr/artificial.h
-pinned.o: $(hdrdir)/ruby/internal/attr/cold.h
-pinned.o: $(hdrdir)/ruby/internal/attr/const.h
-pinned.o: $(hdrdir)/ruby/internal/attr/constexpr.h
-pinned.o: $(hdrdir)/ruby/internal/attr/deprecated.h
-pinned.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
-pinned.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
-pinned.o: $(hdrdir)/ruby/internal/attr/error.h
-pinned.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
-pinned.o: $(hdrdir)/ruby/internal/attr/forceinline.h
-pinned.o: $(hdrdir)/ruby/internal/attr/format.h
-pinned.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
-pinned.o: $(hdrdir)/ruby/internal/attr/noalias.h
-pinned.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
-pinned.o: $(hdrdir)/ruby/internal/attr/noexcept.h
-pinned.o: $(hdrdir)/ruby/internal/attr/noinline.h
-pinned.o: $(hdrdir)/ruby/internal/attr/nonnull.h
-pinned.o: $(hdrdir)/ruby/internal/attr/noreturn.h
-pinned.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
-pinned.o: $(hdrdir)/ruby/internal/attr/pure.h
-pinned.o: $(hdrdir)/ruby/internal/attr/restrict.h
-pinned.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
-pinned.o: $(hdrdir)/ruby/internal/attr/warning.h
-pinned.o: $(hdrdir)/ruby/internal/attr/weakref.h
-pinned.o: $(hdrdir)/ruby/internal/cast.h
-pinned.o: $(hdrdir)/ruby/internal/compiler_is.h
-pinned.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
-pinned.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
-pinned.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
-pinned.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
-pinned.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
-pinned.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
-pinned.o: $(hdrdir)/ruby/internal/compiler_since.h
-pinned.o: $(hdrdir)/ruby/internal/config.h
-pinned.o: $(hdrdir)/ruby/internal/constant_p.h
-pinned.o: $(hdrdir)/ruby/internal/core.h
-pinned.o: $(hdrdir)/ruby/internal/core/rarray.h
-pinned.o: $(hdrdir)/ruby/internal/core/rbasic.h
-pinned.o: $(hdrdir)/ruby/internal/core/rbignum.h
-pinned.o: $(hdrdir)/ruby/internal/core/rclass.h
-pinned.o: $(hdrdir)/ruby/internal/core/rdata.h
-pinned.o: $(hdrdir)/ruby/internal/core/rfile.h
-pinned.o: $(hdrdir)/ruby/internal/core/rhash.h
-pinned.o: $(hdrdir)/ruby/internal/core/robject.h
-pinned.o: $(hdrdir)/ruby/internal/core/rregexp.h
-pinned.o: $(hdrdir)/ruby/internal/core/rstring.h
-pinned.o: $(hdrdir)/ruby/internal/core/rstruct.h
-pinned.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
-pinned.o: $(hdrdir)/ruby/internal/ctype.h
-pinned.o: $(hdrdir)/ruby/internal/dllexport.h
-pinned.o: $(hdrdir)/ruby/internal/dosish.h
-pinned.o: $(hdrdir)/ruby/internal/error.h
-pinned.o: $(hdrdir)/ruby/internal/eval.h
-pinned.o: $(hdrdir)/ruby/internal/event.h
-pinned.o: $(hdrdir)/ruby/internal/fl_type.h
-pinned.o: $(hdrdir)/ruby/internal/gc.h
-pinned.o: $(hdrdir)/ruby/internal/glob.h
-pinned.o: $(hdrdir)/ruby/internal/globals.h
-pinned.o: $(hdrdir)/ruby/internal/has/attribute.h
-pinned.o: $(hdrdir)/ruby/internal/has/builtin.h
-pinned.o: $(hdrdir)/ruby/internal/has/c_attribute.h
-pinned.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
-pinned.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
-pinned.o: $(hdrdir)/ruby/internal/has/extension.h
-pinned.o: $(hdrdir)/ruby/internal/has/feature.h
-pinned.o: $(hdrdir)/ruby/internal/has/warning.h
-pinned.o: $(hdrdir)/ruby/internal/intern/array.h
-pinned.o: $(hdrdir)/ruby/internal/intern/bignum.h
-pinned.o: $(hdrdir)/ruby/internal/intern/class.h
-pinned.o: $(hdrdir)/ruby/internal/intern/compar.h
-pinned.o: $(hdrdir)/ruby/internal/intern/complex.h
-pinned.o: $(hdrdir)/ruby/internal/intern/cont.h
-pinned.o: $(hdrdir)/ruby/internal/intern/dir.h
-pinned.o: $(hdrdir)/ruby/internal/intern/enum.h
-pinned.o: $(hdrdir)/ruby/internal/intern/enumerator.h
-pinned.o: $(hdrdir)/ruby/internal/intern/error.h
-pinned.o: $(hdrdir)/ruby/internal/intern/eval.h
-pinned.o: $(hdrdir)/ruby/internal/intern/file.h
-pinned.o: $(hdrdir)/ruby/internal/intern/hash.h
-pinned.o: $(hdrdir)/ruby/internal/intern/io.h
-pinned.o: $(hdrdir)/ruby/internal/intern/load.h
-pinned.o: $(hdrdir)/ruby/internal/intern/marshal.h
-pinned.o: $(hdrdir)/ruby/internal/intern/numeric.h
-pinned.o: $(hdrdir)/ruby/internal/intern/object.h
-pinned.o: $(hdrdir)/ruby/internal/intern/parse.h
-pinned.o: $(hdrdir)/ruby/internal/intern/proc.h
-pinned.o: $(hdrdir)/ruby/internal/intern/process.h
-pinned.o: $(hdrdir)/ruby/internal/intern/random.h
-pinned.o: $(hdrdir)/ruby/internal/intern/range.h
-pinned.o: $(hdrdir)/ruby/internal/intern/rational.h
-pinned.o: $(hdrdir)/ruby/internal/intern/re.h
-pinned.o: $(hdrdir)/ruby/internal/intern/ruby.h
-pinned.o: $(hdrdir)/ruby/internal/intern/select.h
-pinned.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
-pinned.o: $(hdrdir)/ruby/internal/intern/signal.h
-pinned.o: $(hdrdir)/ruby/internal/intern/sprintf.h
-pinned.o: $(hdrdir)/ruby/internal/intern/string.h
-pinned.o: $(hdrdir)/ruby/internal/intern/struct.h
-pinned.o: $(hdrdir)/ruby/internal/intern/thread.h
-pinned.o: $(hdrdir)/ruby/internal/intern/time.h
-pinned.o: $(hdrdir)/ruby/internal/intern/variable.h
-pinned.o: $(hdrdir)/ruby/internal/intern/vm.h
-pinned.o: $(hdrdir)/ruby/internal/interpreter.h
-pinned.o: $(hdrdir)/ruby/internal/iterator.h
-pinned.o: $(hdrdir)/ruby/internal/memory.h
-pinned.o: $(hdrdir)/ruby/internal/method.h
-pinned.o: $(hdrdir)/ruby/internal/module.h
-pinned.o: $(hdrdir)/ruby/internal/newobj.h
-pinned.o: $(hdrdir)/ruby/internal/scan_args.h
-pinned.o: $(hdrdir)/ruby/internal/special_consts.h
-pinned.o: $(hdrdir)/ruby/internal/static_assert.h
-pinned.o: $(hdrdir)/ruby/internal/stdalign.h
-pinned.o: $(hdrdir)/ruby/internal/stdbool.h
-pinned.o: $(hdrdir)/ruby/internal/stdckdint.h
-pinned.o: $(hdrdir)/ruby/internal/symbol.h
-pinned.o: $(hdrdir)/ruby/internal/value.h
-pinned.o: $(hdrdir)/ruby/internal/value_type.h
-pinned.o: $(hdrdir)/ruby/internal/variable.h
-pinned.o: $(hdrdir)/ruby/internal/warning_push.h
-pinned.o: $(hdrdir)/ruby/internal/xmalloc.h
-pinned.o: $(hdrdir)/ruby/missing.h
-pinned.o: $(hdrdir)/ruby/ruby.h
-pinned.o: $(hdrdir)/ruby/st.h
-pinned.o: $(hdrdir)/ruby/subst.h
-pinned.o: closure.h
-pinned.o: conversions.h
-pinned.o: fiddle.h
-pinned.o: function.h
-pinned.o: pinned.c
-pointer.o: $(RUBY_EXTCONF_H)
-pointer.o: $(arch_hdrdir)/ruby/config.h
-pointer.o: $(hdrdir)/ruby.h
-pointer.o: $(hdrdir)/ruby/assert.h
-pointer.o: $(hdrdir)/ruby/backward.h
-pointer.o: $(hdrdir)/ruby/backward/2/assume.h
-pointer.o: $(hdrdir)/ruby/backward/2/attributes.h
-pointer.o: $(hdrdir)/ruby/backward/2/bool.h
-pointer.o: $(hdrdir)/ruby/backward/2/inttypes.h
-pointer.o: $(hdrdir)/ruby/backward/2/limits.h
-pointer.o: $(hdrdir)/ruby/backward/2/long_long.h
-pointer.o: $(hdrdir)/ruby/backward/2/stdalign.h
-pointer.o: $(hdrdir)/ruby/backward/2/stdarg.h
-pointer.o: $(hdrdir)/ruby/defines.h
-pointer.o: $(hdrdir)/ruby/encoding.h
-pointer.o: $(hdrdir)/ruby/intern.h
-pointer.o: $(hdrdir)/ruby/internal/abi.h
-pointer.o: $(hdrdir)/ruby/internal/anyargs.h
-pointer.o: $(hdrdir)/ruby/internal/arithmetic.h
-pointer.o: $(hdrdir)/ruby/internal/arithmetic/char.h
-pointer.o: $(hdrdir)/ruby/internal/arithmetic/double.h
-pointer.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h
-pointer.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h
-pointer.o: $(hdrdir)/ruby/internal/arithmetic/int.h
-pointer.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h
-pointer.o: $(hdrdir)/ruby/internal/arithmetic/long.h
-pointer.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h
-pointer.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h
-pointer.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h
-pointer.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h
-pointer.o: $(hdrdir)/ruby/internal/arithmetic/short.h
-pointer.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h
-pointer.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h
-pointer.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h
-pointer.o: $(hdrdir)/ruby/internal/assume.h
-pointer.o: $(hdrdir)/ruby/internal/attr/alloc_size.h
-pointer.o: $(hdrdir)/ruby/internal/attr/artificial.h
-pointer.o: $(hdrdir)/ruby/internal/attr/cold.h
-pointer.o: $(hdrdir)/ruby/internal/attr/const.h
-pointer.o: $(hdrdir)/ruby/internal/attr/constexpr.h
-pointer.o: $(hdrdir)/ruby/internal/attr/deprecated.h
-pointer.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h
-pointer.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h
-pointer.o: $(hdrdir)/ruby/internal/attr/error.h
-pointer.o: $(hdrdir)/ruby/internal/attr/flag_enum.h
-pointer.o: $(hdrdir)/ruby/internal/attr/forceinline.h
-pointer.o: $(hdrdir)/ruby/internal/attr/format.h
-pointer.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h
-pointer.o: $(hdrdir)/ruby/internal/attr/noalias.h
-pointer.o: $(hdrdir)/ruby/internal/attr/nodiscard.h
-pointer.o: $(hdrdir)/ruby/internal/attr/noexcept.h
-pointer.o: $(hdrdir)/ruby/internal/attr/noinline.h
-pointer.o: $(hdrdir)/ruby/internal/attr/nonnull.h
-pointer.o: $(hdrdir)/ruby/internal/attr/noreturn.h
-pointer.o: $(hdrdir)/ruby/internal/attr/packed_struct.h
-pointer.o: $(hdrdir)/ruby/internal/attr/pure.h
-pointer.o: $(hdrdir)/ruby/internal/attr/restrict.h
-pointer.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h
-pointer.o: $(hdrdir)/ruby/internal/attr/warning.h
-pointer.o: $(hdrdir)/ruby/internal/attr/weakref.h
-pointer.o: $(hdrdir)/ruby/internal/cast.h
-pointer.o: $(hdrdir)/ruby/internal/compiler_is.h
-pointer.o: $(hdrdir)/ruby/internal/compiler_is/apple.h
-pointer.o: $(hdrdir)/ruby/internal/compiler_is/clang.h
-pointer.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h
-pointer.o: $(hdrdir)/ruby/internal/compiler_is/intel.h
-pointer.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h
-pointer.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h
-pointer.o: $(hdrdir)/ruby/internal/compiler_since.h
-pointer.o: $(hdrdir)/ruby/internal/config.h
-pointer.o: $(hdrdir)/ruby/internal/constant_p.h
-pointer.o: $(hdrdir)/ruby/internal/core.h
-pointer.o: $(hdrdir)/ruby/internal/core/rarray.h
-pointer.o: $(hdrdir)/ruby/internal/core/rbasic.h
-pointer.o: $(hdrdir)/ruby/internal/core/rbignum.h
-pointer.o: $(hdrdir)/ruby/internal/core/rclass.h
-pointer.o: $(hdrdir)/ruby/internal/core/rdata.h
-pointer.o: $(hdrdir)/ruby/internal/core/rfile.h
-pointer.o: $(hdrdir)/ruby/internal/core/rhash.h
-pointer.o: $(hdrdir)/ruby/internal/core/robject.h
-pointer.o: $(hdrdir)/ruby/internal/core/rregexp.h
-pointer.o: $(hdrdir)/ruby/internal/core/rstring.h
-pointer.o: $(hdrdir)/ruby/internal/core/rstruct.h
-pointer.o: $(hdrdir)/ruby/internal/core/rtypeddata.h
-pointer.o: $(hdrdir)/ruby/internal/ctype.h
-pointer.o: $(hdrdir)/ruby/internal/dllexport.h
-pointer.o: $(hdrdir)/ruby/internal/dosish.h
-pointer.o: $(hdrdir)/ruby/internal/encoding/coderange.h
-pointer.o: $(hdrdir)/ruby/internal/encoding/ctype.h
-pointer.o: $(hdrdir)/ruby/internal/encoding/encoding.h
-pointer.o: $(hdrdir)/ruby/internal/encoding/pathname.h
-pointer.o: $(hdrdir)/ruby/internal/encoding/re.h
-pointer.o: $(hdrdir)/ruby/internal/encoding/sprintf.h
-pointer.o: $(hdrdir)/ruby/internal/encoding/string.h
-pointer.o: $(hdrdir)/ruby/internal/encoding/symbol.h
-pointer.o: $(hdrdir)/ruby/internal/encoding/transcode.h
-pointer.o: $(hdrdir)/ruby/internal/error.h
-pointer.o: $(hdrdir)/ruby/internal/eval.h
-pointer.o: $(hdrdir)/ruby/internal/event.h
-pointer.o: $(hdrdir)/ruby/internal/fl_type.h
-pointer.o: $(hdrdir)/ruby/internal/gc.h
-pointer.o: $(hdrdir)/ruby/internal/glob.h
-pointer.o: $(hdrdir)/ruby/internal/globals.h
-pointer.o: $(hdrdir)/ruby/internal/has/attribute.h
-pointer.o: $(hdrdir)/ruby/internal/has/builtin.h
-pointer.o: $(hdrdir)/ruby/internal/has/c_attribute.h
-pointer.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h
-pointer.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h
-pointer.o: $(hdrdir)/ruby/internal/has/extension.h
-pointer.o: $(hdrdir)/ruby/internal/has/feature.h
-pointer.o: $(hdrdir)/ruby/internal/has/warning.h
-pointer.o: $(hdrdir)/ruby/internal/intern/array.h
-pointer.o: $(hdrdir)/ruby/internal/intern/bignum.h
-pointer.o: $(hdrdir)/ruby/internal/intern/class.h
-pointer.o: $(hdrdir)/ruby/internal/intern/compar.h
-pointer.o: $(hdrdir)/ruby/internal/intern/complex.h
-pointer.o: $(hdrdir)/ruby/internal/intern/cont.h
-pointer.o: $(hdrdir)/ruby/internal/intern/dir.h
-pointer.o: $(hdrdir)/ruby/internal/intern/enum.h
-pointer.o: $(hdrdir)/ruby/internal/intern/enumerator.h
-pointer.o: $(hdrdir)/ruby/internal/intern/error.h
-pointer.o: $(hdrdir)/ruby/internal/intern/eval.h
-pointer.o: $(hdrdir)/ruby/internal/intern/file.h
-pointer.o: $(hdrdir)/ruby/internal/intern/hash.h
-pointer.o: $(hdrdir)/ruby/internal/intern/io.h
-pointer.o: $(hdrdir)/ruby/internal/intern/load.h
-pointer.o: $(hdrdir)/ruby/internal/intern/marshal.h
-pointer.o: $(hdrdir)/ruby/internal/intern/numeric.h
-pointer.o: $(hdrdir)/ruby/internal/intern/object.h
-pointer.o: $(hdrdir)/ruby/internal/intern/parse.h
-pointer.o: $(hdrdir)/ruby/internal/intern/proc.h
-pointer.o: $(hdrdir)/ruby/internal/intern/process.h
-pointer.o: $(hdrdir)/ruby/internal/intern/random.h
-pointer.o: $(hdrdir)/ruby/internal/intern/range.h
-pointer.o: $(hdrdir)/ruby/internal/intern/rational.h
-pointer.o: $(hdrdir)/ruby/internal/intern/re.h
-pointer.o: $(hdrdir)/ruby/internal/intern/ruby.h
-pointer.o: $(hdrdir)/ruby/internal/intern/select.h
-pointer.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
-pointer.o: $(hdrdir)/ruby/internal/intern/signal.h
-pointer.o: $(hdrdir)/ruby/internal/intern/sprintf.h
-pointer.o: $(hdrdir)/ruby/internal/intern/string.h
-pointer.o: $(hdrdir)/ruby/internal/intern/struct.h
-pointer.o: $(hdrdir)/ruby/internal/intern/thread.h
-pointer.o: $(hdrdir)/ruby/internal/intern/time.h
-pointer.o: $(hdrdir)/ruby/internal/intern/variable.h
-pointer.o: $(hdrdir)/ruby/internal/intern/vm.h
-pointer.o: $(hdrdir)/ruby/internal/interpreter.h
-pointer.o: $(hdrdir)/ruby/internal/iterator.h
-pointer.o: $(hdrdir)/ruby/internal/memory.h
-pointer.o: $(hdrdir)/ruby/internal/method.h
-pointer.o: $(hdrdir)/ruby/internal/module.h
-pointer.o: $(hdrdir)/ruby/internal/newobj.h
-pointer.o: $(hdrdir)/ruby/internal/scan_args.h
-pointer.o: $(hdrdir)/ruby/internal/special_consts.h
-pointer.o: $(hdrdir)/ruby/internal/static_assert.h
-pointer.o: $(hdrdir)/ruby/internal/stdalign.h
-pointer.o: $(hdrdir)/ruby/internal/stdbool.h
-pointer.o: $(hdrdir)/ruby/internal/stdckdint.h
-pointer.o: $(hdrdir)/ruby/internal/symbol.h
-pointer.o: $(hdrdir)/ruby/internal/value.h
-pointer.o: $(hdrdir)/ruby/internal/value_type.h
-pointer.o: $(hdrdir)/ruby/internal/variable.h
-pointer.o: $(hdrdir)/ruby/internal/warning_push.h
-pointer.o: $(hdrdir)/ruby/internal/xmalloc.h
-pointer.o: $(hdrdir)/ruby/io.h
-pointer.o: $(hdrdir)/ruby/memory_view.h
-pointer.o: $(hdrdir)/ruby/missing.h
-pointer.o: $(hdrdir)/ruby/onigmo.h
-pointer.o: $(hdrdir)/ruby/oniguruma.h
-pointer.o: $(hdrdir)/ruby/ruby.h
-pointer.o: $(hdrdir)/ruby/st.h
-pointer.o: $(hdrdir)/ruby/subst.h
-pointer.o: closure.h
-pointer.o: conversions.h
-pointer.o: fiddle.h
-pointer.o: function.h
-pointer.o: pointer.c
-# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/fiddle/extconf.rb b/ext/fiddle/extconf.rb
deleted file mode 100644
index 2d85b3eea5..0000000000
--- a/ext/fiddle/extconf.rb
+++ /dev/null
@@ -1,256 +0,0 @@
-# frozen_string_literal: true
-require 'mkmf'
-
-# :stopdoc:
-
-def gcc?
- RbConfig::CONFIG["GCC"] == "yes"
-end
-
-def disable_optimization_build_flag(flags)
- if gcc?
- expanded_flags = RbConfig.expand(flags.dup)
- optimization_option_pattern = /(^|\s)?-O\d(\s|$)?/
- if optimization_option_pattern.match?(expanded_flags)
- expanded_flags.gsub(optimization_option_pattern, '\\1-Og\\2')
- else
- flags + " -Og"
- end
- else
- flags
- end
-end
-
-def enable_debug_build_flag(flags)
- if gcc?
- expanded_flags = RbConfig.expand(flags.dup)
- debug_option_pattern = /(^|\s)-g(?:gdb)?\d?(\s|$)/
- if debug_option_pattern.match?(expanded_flags)
- expanded_flags.gsub(debug_option_pattern, '\\1-ggdb3\\2')
- else
- flags + " -ggdb3"
- end
- else
- flags
- end
-end
-
-checking_for(checking_message("--enable-debug-build option")) do
- enable_debug_build = enable_config("debug-build", false)
- if enable_debug_build
- $CFLAGS = disable_optimization_build_flag($CFLAGS)
- $CFLAGS = enable_debug_build_flag($CFLAGS)
- end
- enable_debug_build
-end
-
-libffi_version = nil
-have_libffi = false
-bundle = with_config("libffi-source-dir")
-unless bundle
- dir_config 'libffi'
-
- if pkg_config("libffi")
- libffi_version = pkg_config("libffi", "modversion")
- end
-
- have_ffi_header = false
- if have_header(ffi_header = 'ffi.h')
- have_ffi_header = true
- elsif have_header(ffi_header = 'ffi/ffi.h')
- $defs.push('-DUSE_HEADER_HACKS')
- have_ffi_header = true
- end
- if have_ffi_header && (have_library('ffi') || have_library('libffi'))
- have_libffi = true
- checking_for("undefined FFI_GO_CLOSURES is used") do
- if egrep_cpp(/warning: 'FFI_GO_CLOSURES' is not defined/, cpp_include(ffi_header), "2>&1")
- $defs.push('-DFFI_GO_CLOSURES=0')
- end
- end
- end
-end
-
-unless have_libffi
- if bundle
- libffi_srcdir = libffi_package_name = bundle
- else
- raise "missing libffi. Please install libffi or use --with-libffi-source-dir with libffi source location."
- end
- ffi_header = 'ffi.h'
- libffi = Struct.new(*%I[dir srcdir builddir include lib a cflags ldflags opt arch]).new
- libffi.dir = libffi_package_name
- if $srcdir == "."
- libffi.builddir = libffi_package_name
- libffi.srcdir = "."
- else
- libffi.builddir = libffi.dir
- libffi.srcdir = relative_from(libffi_srcdir, "..")
- end
- libffi.include = "#{libffi.builddir}/include"
- libffi.lib = "#{libffi.builddir}/.libs"
- libffi.a = "#{libffi.lib}/libffi_convenience.#{$LIBEXT}"
- nowarn = CONFIG.merge("warnflags"=>"")
- libffi.cflags = RbConfig.expand("$(CFLAGS)".dup, nowarn)
- libffi_version = libffi_package_name[/libffi-(.*)/, 1]
-
- FileUtils.mkdir_p(libffi.dir)
- libffi.opt = CONFIG['configure_args'][/'(-C)'/, 1]
- libffi.ldflags = RbConfig.expand("$(LDFLAGS) #{libpathflag([relative_from($topdir, "..")])} #{$LIBRUBYARG}".dup)
- libffi.arch = RbConfig::CONFIG['host']
- if $mswin
- unless find_executable(as = /x64/ =~ libffi.arch ? "ml64" : "ml")
- raise "missing #{as} command."
- end
- $defs << "-DFFI_BUILDING"
- libffi_config = "#{relative_from($srcdir, '..')}/win32/libffi-config.rb"
- config = CONFIG.merge("top_srcdir" => $top_srcdir)
- args = $ruby.gsub(/:\/=\\/, '')
- args.gsub!(/\)\\/, ')/')
- args = args.shellsplit
- args.map! {|s| RbConfig.expand(s, config)}
- args << '-C' << libffi.dir << libffi_config
- opts = {}
- else
- args = %W[sh #{libffi.srcdir}/configure ]
- opts = {chdir: libffi.dir}
- end
- cc = RbConfig::CONFIG['CC']
- cxx = RbConfig::CONFIG['CXX']
- ld = RbConfig::CONFIG['LD']
- args.concat %W[
- --srcdir=#{libffi.srcdir}
- --host=#{libffi.arch}
- ]
- args << ($enable_shared || !$static ? '--enable-shared' : '--enable-static')
- args << libffi.opt if libffi.opt
- args.concat %W[
- CC=#{cc} CFLAGS=#{libffi.cflags}
- CXX=#{cxx} CXXFLAGS=#{RbConfig.expand("$(CXXFLAGS)".dup, nowarn)}
- LD=#{ld} LDFLAGS=#{libffi.ldflags}
- ]
-
- FileUtils.rm_f("#{libffi.include}/ffitarget.h")
- Logging::open do
- Logging.message("%p in %p\n", args, opts)
- unless system(*args, **opts)
- begin
- IO.copy_stream(libffi.dir + "/config.log", Logging.instance_variable_get(:@logfile))
- rescue SystemCallError => e
- Logging.message("%s\n", e.message)
- end
- raise "failed to configure libffi. Please install libffi."
- end
- end
- if $mswin && File.file?("#{libffi.include}/ffitarget.h")
- FileUtils.rm_f("#{libffi.include}/ffitarget.h")
- end
- unless File.file?("#{libffi.include}/ffitarget.h")
- FileUtils.cp("#{libffi_srcdir}/src/x86/ffitarget.h", libffi.include, preserve: true)
- end
- $INCFLAGS << " -I" << libffi.include
-end
-
-if libffi_version
- # If libffi_version contains rc version, just ignored.
- libffi_version = libffi_version.gsub(/-rc\d+/, '')
- libffi_version = (libffi_version.split('.').map(&:to_i) + [0,0])[0,3]
- $defs.push(%{-DRUBY_LIBFFI_MODVERSION=#{ '%d%03d%03d' % libffi_version }})
- warn "libffi_version: #{libffi_version.join('.')}"
-end
-
-case
-when $mswin, $mingw, (libffi_version && (libffi_version <=> [3, 2]) >= 0)
- $defs << "-DUSE_FFI_CLOSURE_ALLOC=1"
-when (libffi_version && (libffi_version <=> [3, 2]) < 0)
-else
- have_func('ffi_closure_alloc', ffi_header)
-end
-
-if libffi_version
- if (libffi_version <=> [3, 0, 11]) >= 0
- $defs << "-DHAVE_FFI_PREP_CIF_VAR"
- end
-else
- have_func('ffi_prep_cif_var', ffi_header)
-end
-
-have_header 'sys/mman.h'
-have_header 'link.h'
-
-if have_header "dlfcn.h"
- have_library "dl"
-
- %w{ dlopen dlclose dlsym }.each do |func|
- abort "missing function #{func}" unless have_func(func)
- end
-
- have_func "dlerror"
- have_func "dlinfo"
- have_const("RTLD_DI_LINKMAP", "dlfcn.h")
-elsif have_header "windows.h"
- %w{ LoadLibrary FreeLibrary GetProcAddress GetModuleFileName }.each do |func|
- abort "missing function #{func}" unless have_func(func)
- end
-
- have_library "ws2_32"
-end
-
-have_const('FFI_STDCALL', ffi_header)
-
-config = File.read(RbConfig.expand(File.join($arch_hdrdir, "ruby/config.h")))
-types = {"SIZE_T"=>"SSIZE_T", "PTRDIFF_T"=>nil, "INTPTR_T"=>nil}
-types.each do |type, signed|
- if /^\#define\s+SIZEOF_#{type}\s+(SIZEOF_(.+)|\d+)/ =~ config
- if size = $2 and size != 'VOIDP'
- size = types.fetch(size) {size}
- $defs << "-DTYPE_#{signed||type}=TYPE_#{size}"
- end
- if signed
- check_signedness(type.downcase, "stddef.h")
- end
- else
- check_signedness(type.downcase, "stddef.h")
- end
-end
-
-if libffi
- $LOCAL_LIBS.prepend("#{libffi.a} ").strip! # to exts.mk
- $INCFLAGS.gsub!(/-I#{libffi.dir}/, '-I$(LIBFFI_DIR)')
-end
-create_makefile 'fiddle' do |conf|
- if !libffi
- next conf << "LIBFFI_CLEAN = none\n"
- elsif $gnumake && !$nmake
- submake_arg = "-C $(LIBFFI_DIR)\n"
- else
- submake_pre = "cd $(LIBFFI_DIR) && #{config_string("exec")}".strip
- end
- if $nmake
- cmd = "$(RUBY) -C $(LIBFFI_DIR) #{libffi_config} --srcdir=$(LIBFFI_SRCDIR)"
- else
- cmd = "cd $(LIBFFI_DIR) && #$exec $(LIBFFI_SRCDIR)/configure #{libffi.opt}"
- end
- sep = "/"
- seprpl = config_string('BUILD_FILE_SEPARATOR') {|s| sep = s; ":/=#{s}" if s != "/"} || ""
- conf << <<-MK.gsub(/^ +| +$/, '')
- PWD =
- LIBFFI_CONFIGURE = #{cmd}
- LIBFFI_ARCH = #{libffi.arch}
- LIBFFI_SRCDIR = #{libffi.srcdir.sub(libffi.dir, '$(LIBFFI_DIR)')}
- LIBFFI_DIR = #{libffi.dir}
- LIBFFI_A = #{libffi.a.sub(libffi.dir, '$(LIBFFI_DIR)')}
- LIBFFI_CFLAGS = #{libffi.cflags}
- LIBFFI_LDFLAGS = #{libffi.ldflags}
- FFI_H = $(LIBFFI_DIR)/include/ffi.h
- SUBMAKE_PRE = #{submake_pre}
- SUBMAKE_ARG = #{submake_arg}
- LIBFFI_CLEAN = libffi
- MK
-end
-
-if libffi
- $LIBPATH.pop
-end
-
-# :startdoc:
diff --git a/ext/fiddle/fiddle.c b/ext/fiddle/fiddle.c
deleted file mode 100644
index f420d9fa3b..0000000000
--- a/ext/fiddle/fiddle.c
+++ /dev/null
@@ -1,712 +0,0 @@
-#include <stdbool.h>
-
-#include <fiddle.h>
-
-VALUE mFiddle;
-VALUE rb_eFiddleDLError;
-VALUE rb_eFiddleError;
-
-void Init_fiddle_pointer(void);
-void Init_fiddle_pinned(void);
-
-#ifdef HAVE_RUBY_MEMORY_VIEW_H
-void Init_fiddle_memory_view(void);
-#endif
-
-/*
- * call-seq: Fiddle.malloc(size)
- *
- * Allocate +size+ bytes of memory and return the integer memory address
- * for the allocated memory.
- */
-static VALUE
-rb_fiddle_malloc(VALUE self, VALUE size)
-{
- void *ptr;
- ptr = (void*)ruby_xcalloc(1, NUM2SIZET(size));
- return PTR2NUM(ptr);
-}
-
-/*
- * call-seq: Fiddle.realloc(addr, size)
- *
- * Change the size of the memory allocated at the memory location +addr+ to
- * +size+ bytes. Returns the memory address of the reallocated memory, which
- * may be different than the address passed in.
- */
-static VALUE
-rb_fiddle_realloc(VALUE self, VALUE addr, VALUE size)
-{
- void *ptr = NUM2PTR(addr);
-
- ptr = (void*)ruby_xrealloc(ptr, NUM2SIZET(size));
- return PTR2NUM(ptr);
-}
-
-/*
- * call-seq: Fiddle.free(addr)
- *
- * Free the memory at address +addr+
- */
-VALUE
-rb_fiddle_free(VALUE self, VALUE addr)
-{
- void *ptr = NUM2PTR(addr);
-
- ruby_xfree(ptr);
- return Qnil;
-}
-
-/*
- * call-seq: Fiddle.dlunwrap(addr)
- *
- * Returns the Ruby object stored at the memory address +addr+
- *
- * Example:
- *
- * x = Object.new
- * # => #<Object:0x0000000107c7d870>
- * Fiddle.dlwrap(x)
- * # => 4425504880
- * Fiddle.dlunwrap(_)
- * # => #<Object:0x0000000107c7d870>
- */
-VALUE
-rb_fiddle_ptr2value(VALUE self, VALUE addr)
-{
- return (VALUE)NUM2PTR(addr);
-}
-
-/*
- * call-seq: Fiddle.dlwrap(val)
- *
- * Returns the memory address of the Ruby object stored at +val+
- *
- * Example:
- *
- * x = Object.new
- * # => #<Object:0x0000000107c7d870>
- * Fiddle.dlwrap(x)
- * # => 4425504880
- *
- * In the case +val+ is not a heap allocated object, this method will return
- * the tagged pointer value.
- *
- * Example:
- *
- * Fiddle.dlwrap(123)
- * # => 247
- */
-static VALUE
-rb_fiddle_value2ptr(VALUE self, VALUE val)
-{
- return PTR2NUM((void*)val);
-}
-
-void Init_fiddle_handle(void);
-
-void
-Init_fiddle(void)
-{
- /*
- * Document-module: Fiddle
- *
- * A libffi wrapper for Ruby.
- *
- * == Description
- *
- * Fiddle is an extension to translate a foreign function interface (FFI)
- * with ruby.
- *
- * It wraps {libffi}[http://sourceware.org/libffi/], a popular C library
- * which provides a portable interface that allows code written in one
- * language to call code written in another language.
- *
- * == Example
- *
- * Here we will use Fiddle::Function to wrap {floor(3) from
- * libm}[http://linux.die.net/man/3/floor]
- *
- * require 'fiddle'
- *
- * libm = Fiddle.dlopen('/lib/libm.so.6')
- *
- * floor = Fiddle::Function.new(
- * libm['floor'],
- * [Fiddle::TYPE_DOUBLE],
- * Fiddle::TYPE_DOUBLE
- * )
- *
- * puts floor.call(3.14159) #=> 3.0
- *
- *
- */
- mFiddle = rb_define_module("Fiddle");
-
- /*
- * Document-class: Fiddle::Error
- *
- * Generic error class for Fiddle
- */
- rb_eFiddleError = rb_define_class_under(mFiddle, "Error", rb_eStandardError);
-
- /*
- * Ruby installed by RubyInstaller for Windows always require
- * bundled Fiddle because ruby_installer/runtime/dll_directory.rb
- * requires Fiddle. It's used by
- * rubygems/defaults/operating_system.rb. It means that the
- * bundled Fiddle is always required on initialization.
- *
- * We just remove existing Fiddle::DLError here to override
- * the bundled Fiddle.
- */
- if (rb_const_defined(mFiddle, rb_intern("DLError"))) {
- rb_const_remove(mFiddle, rb_intern("DLError"));
- }
-
- /*
- * Document-class: Fiddle::DLError
- *
- * standard dynamic load exception
- */
- rb_eFiddleDLError = rb_define_class_under(mFiddle, "DLError", rb_eFiddleError);
-
- VALUE mFiddleTypes = rb_define_module_under(mFiddle, "Types");
-
- /* Document-const: Fiddle::Types::VOID
- *
- * C type - void
- */
- rb_define_const(mFiddleTypes, "VOID", INT2NUM(TYPE_VOID));
-
- /* Document-const: Fiddle::Types::VOIDP
- *
- * C type - void*
- */
- rb_define_const(mFiddleTypes, "VOIDP", INT2NUM(TYPE_VOIDP));
-
- /* Document-const: Fiddle::Types::CHAR
- *
- * C type - char
- */
- rb_define_const(mFiddleTypes, "CHAR", INT2NUM(TYPE_CHAR));
-
- /* Document-const: Fiddle::Types::UCHAR
- *
- * C type - unsigned char
- */
- rb_define_const(mFiddleTypes, "UCHAR", INT2NUM(TYPE_UCHAR));
-
- /* Document-const: Fiddle::Types::SHORT
- *
- * C type - short
- */
- rb_define_const(mFiddleTypes, "SHORT", INT2NUM(TYPE_SHORT));
-
- /* Document-const: Fiddle::Types::USHORT
- *
- * C type - unsigned short
- */
- rb_define_const(mFiddleTypes, "USHORT", INT2NUM(TYPE_USHORT));
-
- /* Document-const: Fiddle::Types::INT
- *
- * C type - int
- */
- rb_define_const(mFiddleTypes, "INT", INT2NUM(TYPE_INT));
-
- /* Document-const: Fiddle::Types::UINT
- *
- * C type - unsigned int
- */
- rb_define_const(mFiddleTypes, "UINT", INT2NUM(TYPE_UINT));
-
- /* Document-const: Fiddle::Types::LONG
- *
- * C type - long
- */
- rb_define_const(mFiddleTypes, "LONG", INT2NUM(TYPE_LONG));
-
- /* Document-const: Fiddle::Types::ULONG
- *
- * C type - long
- */
- rb_define_const(mFiddleTypes, "ULONG", INT2NUM(TYPE_ULONG));
-
-#if HAVE_LONG_LONG
- /* Document-const: Fiddle::Types::LONG_LONG
- *
- * C type - long long
- */
- rb_define_const(mFiddleTypes, "LONG_LONG", INT2NUM(TYPE_LONG_LONG));
-
- /* Document-const: Fiddle::Types::ULONG_LONG
- *
- * C type - long long
- */
- rb_define_const(mFiddleTypes, "ULONG_LONG", INT2NUM(TYPE_ULONG_LONG));
-#endif
-
-#ifdef TYPE_INT8_T
- /* Document-const: Fiddle::Types::INT8_T
- *
- * C type - int8_t
- */
- rb_define_const(mFiddleTypes, "INT8_T", INT2NUM(TYPE_INT8_T));
-
- /* Document-const: Fiddle::Types::UINT8_T
- *
- * C type - uint8_t
- */
- rb_define_const(mFiddleTypes, "UINT8_T", INT2NUM(TYPE_UINT8_T));
-#endif
-
-#ifdef TYPE_INT16_T
- /* Document-const: Fiddle::Types::INT16_T
- *
- * C type - int16_t
- */
- rb_define_const(mFiddleTypes, "INT16_T", INT2NUM(TYPE_INT16_T));
-
- /* Document-const: Fiddle::Types::UINT16_T
- *
- * C type - uint16_t
- */
- rb_define_const(mFiddleTypes, "UINT16_T", INT2NUM(TYPE_UINT16_T));
-#endif
-
-#ifdef TYPE_INT32_T
- /* Document-const: Fiddle::Types::INT32_T
- *
- * C type - int32_t
- */
- rb_define_const(mFiddleTypes, "INT32_T", INT2NUM(TYPE_INT32_T));
-
- /* Document-const: Fiddle::Types::UINT32_T
- *
- * C type - uint32_t
- */
- rb_define_const(mFiddleTypes, "UINT32_T", INT2NUM(TYPE_UINT32_T));
-#endif
-
-#ifdef TYPE_INT64_T
- /* Document-const: Fiddle::Types::INT64_T
- *
- * C type - int64_t
- */
- rb_define_const(mFiddleTypes, "INT64_T", INT2NUM(TYPE_INT64_T));
-
- /* Document-const: Fiddle::Types::UINT64_T
- *
- * C type - uint64_t
- */
- rb_define_const(mFiddleTypes, "UINT64_T", INT2NUM(TYPE_UINT64_T));
-#endif
-
- /* Document-const: Fiddle::Types::FLOAT
- *
- * C type - float
- */
- rb_define_const(mFiddleTypes, "FLOAT", INT2NUM(TYPE_FLOAT));
-
- /* Document-const: Fiddle::Types::DOUBLE
- *
- * C type - double
- */
- rb_define_const(mFiddleTypes, "DOUBLE", INT2NUM(TYPE_DOUBLE));
-
-#ifdef HAVE_FFI_PREP_CIF_VAR
- /* Document-const: Fiddle::Types::VARIADIC
- *
- * C type - ...
- */
- rb_define_const(mFiddleTypes, "VARIADIC", INT2NUM(TYPE_VARIADIC));
-#endif
-
- /* Document-const: Fiddle::Types::CONST_STRING
- *
- * C type - const char* ('\0' terminated const char*)
- */
- rb_define_const(mFiddleTypes, "CONST_STRING", INT2NUM(TYPE_CONST_STRING));
-
- /* Document-const: Fiddle::Types::SIZE_T
- *
- * C type - size_t
- */
- rb_define_const(mFiddleTypes, "SIZE_T", INT2NUM(TYPE_SIZE_T));
-
- /* Document-const: Fiddle::Types::SSIZE_T
- *
- * C type - ssize_t
- */
- rb_define_const(mFiddleTypes, "SSIZE_T", INT2NUM(TYPE_SSIZE_T));
-
- /* Document-const: Fiddle::Types::PTRDIFF_T
- *
- * C type - ptrdiff_t
- */
- rb_define_const(mFiddleTypes, "PTRDIFF_T", INT2NUM(TYPE_PTRDIFF_T));
-
- /* Document-const: Fiddle::Types::INTPTR_T
- *
- * C type - intptr_t
- */
- rb_define_const(mFiddleTypes, "INTPTR_T", INT2NUM(TYPE_INTPTR_T));
-
- /* Document-const: Fiddle::Types::UINTPTR_T
- *
- * C type - uintptr_t
- */
- rb_define_const(mFiddleTypes, "UINTPTR_T", INT2NUM(TYPE_UINTPTR_T));
-
- /* Document-const: Fiddle::Types::BOOL
- *
- * C type - bool
- */
- rb_define_const(mFiddleTypes, "BOOL" , INT2NUM(TYPE_BOOL));
-
- /* Document-const: ALIGN_VOIDP
- *
- * The alignment size of a void*
- */
- rb_define_const(mFiddle, "ALIGN_VOIDP", INT2NUM(ALIGN_VOIDP));
-
- /* Document-const: ALIGN_CHAR
- *
- * The alignment size of a char
- */
- rb_define_const(mFiddle, "ALIGN_CHAR", INT2NUM(ALIGN_CHAR));
-
- /* Document-const: ALIGN_SHORT
- *
- * The alignment size of a short
- */
- rb_define_const(mFiddle, "ALIGN_SHORT", INT2NUM(ALIGN_SHORT));
-
- /* Document-const: ALIGN_INT
- *
- * The alignment size of an int
- */
- rb_define_const(mFiddle, "ALIGN_INT", INT2NUM(ALIGN_INT));
-
- /* Document-const: ALIGN_LONG
- *
- * The alignment size of a long
- */
- rb_define_const(mFiddle, "ALIGN_LONG", INT2NUM(ALIGN_LONG));
-
-#if HAVE_LONG_LONG
- /* Document-const: ALIGN_LONG_LONG
- *
- * The alignment size of a long long
- */
- rb_define_const(mFiddle, "ALIGN_LONG_LONG", INT2NUM(ALIGN_LONG_LONG));
-#endif
-
- /* Document-const: ALIGN_INT8_T
- *
- * The alignment size of a int8_t
- */
- rb_define_const(mFiddle, "ALIGN_INT8_T", INT2NUM(ALIGN_INT8_T));
-
- /* Document-const: ALIGN_INT16_T
- *
- * The alignment size of a int16_t
- */
- rb_define_const(mFiddle, "ALIGN_INT16_T", INT2NUM(ALIGN_INT16_T));
-
- /* Document-const: ALIGN_INT32_T
- *
- * The alignment size of a int32_t
- */
- rb_define_const(mFiddle, "ALIGN_INT32_T", INT2NUM(ALIGN_INT32_T));
-
- /* Document-const: ALIGN_INT64_T
- *
- * The alignment size of a int64_t
- */
- rb_define_const(mFiddle, "ALIGN_INT64_T", INT2NUM(ALIGN_INT64_T));
-
- /* Document-const: ALIGN_FLOAT
- *
- * The alignment size of a float
- */
- rb_define_const(mFiddle, "ALIGN_FLOAT", INT2NUM(ALIGN_FLOAT));
-
- /* Document-const: ALIGN_DOUBLE
- *
- * The alignment size of a double
- */
- rb_define_const(mFiddle, "ALIGN_DOUBLE",INT2NUM(ALIGN_DOUBLE));
-
- /* Document-const: ALIGN_SIZE_T
- *
- * The alignment size of a size_t
- */
- rb_define_const(mFiddle, "ALIGN_SIZE_T", INT2NUM(ALIGN_OF(size_t)));
-
- /* Document-const: ALIGN_SSIZE_T
- *
- * The alignment size of a ssize_t
- */
- rb_define_const(mFiddle, "ALIGN_SSIZE_T", INT2NUM(ALIGN_OF(size_t))); /* same as size_t */
-
- /* Document-const: ALIGN_PTRDIFF_T
- *
- * The alignment size of a ptrdiff_t
- */
- rb_define_const(mFiddle, "ALIGN_PTRDIFF_T", INT2NUM(ALIGN_OF(ptrdiff_t)));
-
- /* Document-const: ALIGN_INTPTR_T
- *
- * The alignment size of a intptr_t
- */
- rb_define_const(mFiddle, "ALIGN_INTPTR_T", INT2NUM(ALIGN_OF(intptr_t)));
-
- /* Document-const: ALIGN_UINTPTR_T
- *
- * The alignment size of a uintptr_t
- */
- rb_define_const(mFiddle, "ALIGN_UINTPTR_T", INT2NUM(ALIGN_OF(uintptr_t)));
-
- /* Document-const: ALIGN_BOOL
- *
- * The alignment size of a bool
- */
- rb_define_const(mFiddle, "ALIGN_BOOL", INT2NUM(ALIGN_OF(bool)));
-
- /* Document-const: WINDOWS
- *
- * Returns a boolean regarding whether the host is WIN32
- */
-#if defined(_WIN32)
- rb_define_const(mFiddle, "WINDOWS", Qtrue);
-#else
- rb_define_const(mFiddle, "WINDOWS", Qfalse);
-#endif
-
- /* Document-const: SIZEOF_VOIDP
- *
- * size of a void*
- */
- rb_define_const(mFiddle, "SIZEOF_VOIDP", INT2NUM(sizeof(void*)));
-
- /* Document-const: SIZEOF_CHAR
- *
- * size of a char
- */
- rb_define_const(mFiddle, "SIZEOF_CHAR", INT2NUM(sizeof(char)));
-
- /* Document-const: SIZEOF_UCHAR
- *
- * size of a unsigned char
- */
- rb_define_const(mFiddle, "SIZEOF_UCHAR", INT2NUM(sizeof(unsigned char)));
-
- /* Document-const: SIZEOF_SHORT
- *
- * size of a short
- */
- rb_define_const(mFiddle, "SIZEOF_SHORT", INT2NUM(sizeof(short)));
-
- /* Document-const: SIZEOF_USHORT
- *
- * size of a unsigned short
- */
- rb_define_const(mFiddle, "SIZEOF_USHORT", INT2NUM(sizeof(unsigned short)));
-
- /* Document-const: SIZEOF_INT
- *
- * size of an int
- */
- rb_define_const(mFiddle, "SIZEOF_INT", INT2NUM(sizeof(int)));
-
- /* Document-const: SIZEOF_UINT
- *
- * size of an unsigned int
- */
- rb_define_const(mFiddle, "SIZEOF_UINT", INT2NUM(sizeof(unsigned int)));
-
- /* Document-const: SIZEOF_LONG
- *
- * size of a long
- */
- rb_define_const(mFiddle, "SIZEOF_LONG", INT2NUM(sizeof(long)));
-
- /* Document-const: SIZEOF_ULONG
- *
- * size of a unsigned long
- */
- rb_define_const(mFiddle, "SIZEOF_ULONG", INT2NUM(sizeof(unsigned long)));
-
-#if HAVE_LONG_LONG
- /* Document-const: SIZEOF_LONG_LONG
- *
- * size of a long long
- */
- rb_define_const(mFiddle, "SIZEOF_LONG_LONG", INT2NUM(sizeof(LONG_LONG)));
-
- /* Document-const: SIZEOF_ULONG_LONG
- *
- * size of a unsigned long long
- */
- rb_define_const(mFiddle, "SIZEOF_ULONG_LONG", INT2NUM(sizeof(unsigned LONG_LONG)));
-#endif
-
- /* Document-const: SIZEOF_INT8_T
- *
- * size of a int8_t
- */
- rb_define_const(mFiddle, "SIZEOF_INT8_T", INT2NUM(sizeof(int8_t)));
-
- /* Document-const: SIZEOF_UINT8_T
- *
- * size of a uint8_t
- */
- rb_define_const(mFiddle, "SIZEOF_UINT8_T", INT2NUM(sizeof(uint8_t)));
-
- /* Document-const: SIZEOF_INT16_T
- *
- * size of a int16_t
- */
- rb_define_const(mFiddle, "SIZEOF_INT16_T", INT2NUM(sizeof(int16_t)));
-
- /* Document-const: SIZEOF_UINT16_T
- *
- * size of a uint16_t
- */
- rb_define_const(mFiddle, "SIZEOF_UINT16_T", INT2NUM(sizeof(uint16_t)));
-
- /* Document-const: SIZEOF_INT32_T
- *
- * size of a int32_t
- */
- rb_define_const(mFiddle, "SIZEOF_INT32_T", INT2NUM(sizeof(int32_t)));
-
- /* Document-const: SIZEOF_UINT32_T
- *
- * size of a uint32_t
- */
- rb_define_const(mFiddle, "SIZEOF_UINT32_T", INT2NUM(sizeof(uint32_t)));
-
- /* Document-const: SIZEOF_INT64_T
- *
- * size of a int64_t
- */
- rb_define_const(mFiddle, "SIZEOF_INT64_T", INT2NUM(sizeof(int64_t)));
-
- /* Document-const: SIZEOF_UINT64_T
- *
- * size of a uint64_t
- */
- rb_define_const(mFiddle, "SIZEOF_UINT64_T", INT2NUM(sizeof(uint64_t)));
-
- /* Document-const: SIZEOF_FLOAT
- *
- * size of a float
- */
- rb_define_const(mFiddle, "SIZEOF_FLOAT", INT2NUM(sizeof(float)));
-
- /* Document-const: SIZEOF_DOUBLE
- *
- * size of a double
- */
- rb_define_const(mFiddle, "SIZEOF_DOUBLE",INT2NUM(sizeof(double)));
-
- /* Document-const: SIZEOF_SIZE_T
- *
- * size of a size_t
- */
- rb_define_const(mFiddle, "SIZEOF_SIZE_T", INT2NUM(sizeof(size_t)));
-
- /* Document-const: SIZEOF_SSIZE_T
- *
- * size of a ssize_t
- */
- rb_define_const(mFiddle, "SIZEOF_SSIZE_T", INT2NUM(sizeof(size_t))); /* same as size_t */
-
- /* Document-const: SIZEOF_PTRDIFF_T
- *
- * size of a ptrdiff_t
- */
- rb_define_const(mFiddle, "SIZEOF_PTRDIFF_T", INT2NUM(sizeof(ptrdiff_t)));
-
- /* Document-const: SIZEOF_INTPTR_T
- *
- * size of a intptr_t
- */
- rb_define_const(mFiddle, "SIZEOF_INTPTR_T", INT2NUM(sizeof(intptr_t)));
-
- /* Document-const: SIZEOF_UINTPTR_T
- *
- * size of a uintptr_t
- */
- rb_define_const(mFiddle, "SIZEOF_UINTPTR_T", INT2NUM(sizeof(uintptr_t)));
-
- /* Document-const: SIZEOF_CONST_STRING
- *
- * size of a const char*
- */
- rb_define_const(mFiddle, "SIZEOF_CONST_STRING", INT2NUM(sizeof(const char*)));
-
- /* Document-const: SIZEOF_BOOL
- *
- * size of a bool
- */
- rb_define_const(mFiddle, "SIZEOF_BOOL", INT2NUM(sizeof(bool)));
-
- /* Document-const: RUBY_FREE
- *
- * Address of the ruby_xfree() function
- */
- rb_define_const(mFiddle, "RUBY_FREE", PTR2NUM(ruby_xfree));
-
- /* Document-const: BUILD_RUBY_PLATFORM
- *
- * Platform built against (i.e. "x86_64-linux", etc.)
- *
- * See also RUBY_PLATFORM
- */
- rb_define_const(mFiddle, "BUILD_RUBY_PLATFORM", rb_str_new2(RUBY_PLATFORM));
-
- rb_define_module_function(mFiddle, "dlwrap", rb_fiddle_value2ptr, 1);
- rb_define_module_function(mFiddle, "dlunwrap", rb_fiddle_ptr2value, 1);
- rb_define_module_function(mFiddle, "malloc", rb_fiddle_malloc, 1);
- rb_define_module_function(mFiddle, "realloc", rb_fiddle_realloc, 2);
- rb_define_module_function(mFiddle, "free", rb_fiddle_free, 1);
-
- /* Document-const: Qtrue
- *
- * The value of Qtrue
- */
- rb_define_const(mFiddle, "Qtrue", INT2NUM(Qtrue));
-
- /* Document-const: Qfalse
- *
- * The value of Qfalse
- */
- rb_define_const(mFiddle, "Qfalse", INT2NUM(Qfalse));
-
- /* Document-const: Qnil
- *
- * The value of Qnil
- */
- rb_define_const(mFiddle, "Qnil", INT2NUM(Qnil));
-
- /* Document-const: Qundef
- *
- * The value of Qundef
- */
- rb_define_const(mFiddle, "Qundef", INT2NUM(Qundef));
-
- Init_fiddle_function();
- Init_fiddle_closure();
- Init_fiddle_handle();
- Init_fiddle_pointer();
- Init_fiddle_pinned();
-
-#ifdef HAVE_RUBY_MEMORY_VIEW_H
- Init_fiddle_memory_view();
-#endif
-}
-/* vim: set noet sws=4 sw=4: */
diff --git a/ext/fiddle/fiddle.gemspec b/ext/fiddle/fiddle.gemspec
deleted file mode 100644
index 3a1072dd49..0000000000
--- a/ext/fiddle/fiddle.gemspec
+++ /dev/null
@@ -1,60 +0,0 @@
-# frozen_string_literal: true
-
-version_module = Module.new do
- version_rb = File.join(__dir__, "lib/fiddle/version.rb")
- module_eval(File.read(version_rb), version_rb, __LINE__)
-end
-
-Gem::Specification.new do |spec|
- spec.name = "fiddle"
- spec.version = version_module::Fiddle::VERSION
- spec.authors = ["Aaron Patterson", "SHIBATA Hiroshi"]
- spec.email = ["aaron@tenderlovemaking.com", "hsbt@ruby-lang.org"]
-
- spec.summary = %q{A libffi wrapper for Ruby.}
- spec.description = %q{A libffi wrapper for Ruby.}
- spec.homepage = "https://github.com/ruby/fiddle"
- spec.licenses = ["Ruby", "BSD-2-Clause"]
-
- spec.files = [
- "LICENSE.txt",
- "README.md",
- "Rakefile",
- "ext/fiddle/closure.c",
- "ext/fiddle/closure.h",
- "ext/fiddle/conversions.c",
- "ext/fiddle/conversions.h",
- "ext/fiddle/depend",
- "ext/fiddle/extconf.rb",
- "ext/fiddle/fiddle.c",
- "ext/fiddle/fiddle.h",
- "ext/fiddle/function.c",
- "ext/fiddle/function.h",
- "ext/fiddle/handle.c",
- "ext/fiddle/memory_view.c",
- "ext/fiddle/pinned.c",
- "ext/fiddle/pointer.c",
- "ext/fiddle/win32/fficonfig.h",
- "ext/fiddle/win32/libffi-3.2.1-mswin.patch",
- "ext/fiddle/win32/libffi-config.rb",
- "ext/fiddle/win32/libffi.mk.tmpl",
- "fiddle.gemspec",
- "lib/fiddle.rb",
- "lib/fiddle/closure.rb",
- "lib/fiddle/cparser.rb",
- "lib/fiddle/function.rb",
- "lib/fiddle/import.rb",
- "lib/fiddle/pack.rb",
- "lib/fiddle/struct.rb",
- "lib/fiddle/types.rb",
- "lib/fiddle/value.rb",
- "lib/fiddle/version.rb",
- ]
- spec.require_paths = ["lib"]
- spec.extensions = ["ext/fiddle/extconf.rb"]
-
- spec.required_ruby_version = ">= 2.5.0"
-
- spec.metadata["msys2_mingw_dependencies"] = "libffi"
- spec.metadata["changelog_uri"] = "https://github.com/ruby/fiddle/releases"
-end
diff --git a/ext/fiddle/fiddle.h b/ext/fiddle/fiddle.h
deleted file mode 100644
index 348baa9ab9..0000000000
--- a/ext/fiddle/fiddle.h
+++ /dev/null
@@ -1,240 +0,0 @@
-#ifndef FIDDLE_H
-#define FIDDLE_H
-
-#include <ruby.h>
-#include <errno.h>
-
-#if defined(_WIN32)
-#include <windows.h>
-#endif
-
-#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-
-#if defined(HAVE_LINK_H)
-# include <link.h>
-#endif
-
-#if defined(HAVE_DLFCN_H)
-# include <dlfcn.h>
-# /* some stranger systems may not define all of these */
-#ifndef RTLD_LAZY
-#define RTLD_LAZY 0
-#endif
-#ifndef RTLD_GLOBAL
-#define RTLD_GLOBAL 0
-#endif
-#ifndef RTLD_NOW
-#define RTLD_NOW 0
-#endif
-#else
-# if defined(_WIN32)
-# include <windows.h>
-# define dlopen(name,flag) ((void*)LoadLibrary(name))
-# define dlerror() strerror(rb_w32_map_errno(GetLastError()))
-# define dlsym(handle,name) ((void*)GetProcAddress((handle),(name)))
-# define RTLD_LAZY -1
-# define RTLD_NOW -1
-# define RTLD_GLOBAL -1
-# endif
-#endif
-
-#ifdef USE_HEADER_HACKS
-#include <ffi/ffi.h>
-#else
-#include <ffi.h>
-#endif
-
-#undef ffi_type_uchar
-#undef ffi_type_schar
-#undef ffi_type_ushort
-#undef ffi_type_sshort
-#undef ffi_type_uint
-#undef ffi_type_sint
-#undef ffi_type_ulong
-#undef ffi_type_slong
-
-#if CHAR_BIT == 8
-# define ffi_type_uchar ffi_type_uint8
-# define ffi_type_schar ffi_type_sint8
-#else
-# error "CHAR_BIT not supported"
-#endif
-
-#if SIZEOF_SHORT == 2
-# define ffi_type_ushort ffi_type_uint16
-# define ffi_type_sshort ffi_type_sint16
-#elif SIZEOF_SHORT == 4
-# define ffi_type_ushort ffi_type_uint32
-# define ffi_type_sshort ffi_type_sint32
-#else
-# error "short size not supported"
-#endif
-
-#if SIZEOF_INT == 2
-# define ffi_type_uint ffi_type_uint16
-# define ffi_type_sint ffi_type_sint16
-#elif SIZEOF_INT == 4
-# define ffi_type_uint ffi_type_uint32
-# define ffi_type_sint ffi_type_sint32
-#elif SIZEOF_INT == 8
-# define ffi_type_uint ffi_type_uint64
-# define ffi_type_sint ffi_type_sint64
-#else
-# error "int size not supported"
-#endif
-
-#if SIZEOF_LONG == 4
-# define ffi_type_ulong ffi_type_uint32
-# define ffi_type_slong ffi_type_sint32
-#elif SIZEOF_LONG == 8
-# define ffi_type_ulong ffi_type_uint64
-# define ffi_type_slong ffi_type_sint64
-#else
-# error "long size not supported"
-#endif
-
-#if HAVE_LONG_LONG
-# if SIZEOF_LONG_LONG == 8
-# define ffi_type_slong_long ffi_type_sint64
-# define ffi_type_ulong_long ffi_type_uint64
-# else
-# error "long long size not supported"
-# endif
-#endif
-
-#include <closure.h>
-#include <conversions.h>
-#include <function.h>
-
-#define TYPE_VOID 0
-#define TYPE_VOIDP 1
-#define TYPE_CHAR 2
-#define TYPE_UCHAR -TYPE_CHAR
-#define TYPE_SHORT 3
-#define TYPE_USHORT -TYPE_SHORT
-#define TYPE_INT 4
-#define TYPE_UINT -TYPE_INT
-#define TYPE_LONG 5
-#define TYPE_ULONG -TYPE_LONG
-#ifdef HAVE_LONG_LONG
-#define TYPE_LONG_LONG 6
-#define TYPE_ULONG_LONG -TYPE_LONG_LONG
-#endif
-#define TYPE_FLOAT 7
-#define TYPE_DOUBLE 8
-#define TYPE_VARIADIC 9
-#define TYPE_CONST_STRING 10
-#define TYPE_BOOL 11
-
-#define TYPE_INT8_T TYPE_CHAR
-#define TYPE_UINT8_T -TYPE_INT8_T
-
-#if SIZEOF_SHORT == 2
-# define TYPE_INT16_T TYPE_SHORT
-#elif SIZEOF_INT == 2
-# define TYPE_INT16_T TYPE_INT
-#endif
-
-#ifdef TYPE_INT16_T
-# define TYPE_UINT16_T -TYPE_INT16_T
-#endif
-
-#if SIZEOF_SHORT == 4
-# define TYPE_INT32_T TYPE_SHORT
-#elif SIZEOF_INT == 4
-# define TYPE_INT32_T TYPE_INT
-#elif SIZEOF_LONG == 4
-# define TYPE_INT32_T TYPE_LONG
-#endif
-
-#ifdef TYPE_INT32_T
-#define TYPE_UINT32_T -TYPE_INT32_T
-#endif
-
-#if SIZEOF_INT == 8
-# define TYPE_INT64_T TYPE_INT
-#elif SIZEOF_LONG == 8
-# define TYPE_INT64_T TYPE_LONG
-#elif defined(TYPE_LONG_LONG)
-# define TYPE_INT64_T TYPE_LONG_LONG
-#endif
-
-#ifdef TYPE_INT64_T
-#define TYPE_UINT64_T -TYPE_INT64_T
-#endif
-
-#ifndef TYPE_SSIZE_T
-# if SIZEOF_SIZE_T == SIZEOF_INT
-# define TYPE_SSIZE_T TYPE_INT
-# elif SIZEOF_SIZE_T == SIZEOF_LONG
-# define TYPE_SSIZE_T TYPE_LONG
-# elif defined HAVE_LONG_LONG && SIZEOF_SIZE_T == SIZEOF_LONG_LONG
-# define TYPE_SSIZE_T TYPE_LONG_LONG
-# endif
-#endif
-#define TYPE_SIZE_T (-1*SIGNEDNESS_OF_SIZE_T*TYPE_SSIZE_T)
-
-#ifndef TYPE_PTRDIFF_T
-# if SIZEOF_PTRDIFF_T == SIZEOF_INT
-# define TYPE_PTRDIFF_T TYPE_INT
-# elif SIZEOF_PTRDIFF_T == SIZEOF_LONG
-# define TYPE_PTRDIFF_T TYPE_LONG
-# elif defined HAVE_LONG_LONG && SIZEOF_PTRDIFF_T == SIZEOF_LONG_LONG
-# define TYPE_PTRDIFF_T TYPE_LONG_LONG
-# endif
-#endif
-
-#ifndef TYPE_INTPTR_T
-# if SIZEOF_INTPTR_T == SIZEOF_INT
-# define TYPE_INTPTR_T TYPE_INT
-# elif SIZEOF_INTPTR_T == SIZEOF_LONG
-# define TYPE_INTPTR_T TYPE_LONG
-# elif defined HAVE_LONG_LONG && SIZEOF_INTPTR_T == SIZEOF_LONG_LONG
-# define TYPE_INTPTR_T TYPE_LONG_LONG
-# endif
-#endif
-#define TYPE_UINTPTR_T (-TYPE_INTPTR_T)
-
-/* GCC releases before GCC 4.9 had a bug in _Alignof. See GCC bug 52023
- <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52023>.
- clang versions < 8.0.0 have the same bug. */
-#if defined(HAVE__ALIGNOF)
-# /* Autoconf detected availability of a sane `_Alignof()`. */
-# define ALIGN_OF(type) RB_GNUC_EXTENSION(_Alignof(type))
-#elif (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112 \
- || (defined(__GNUC__) && __GNUC__ < 4 + (__GNUC_MINOR__ < 9) \
- && !defined(__clang__)) \
- || (defined(__clang__) && __clang_major__ < 8))
-# define ALIGN_OF(type) offsetof(struct {char align_c; type align_x;}, align_x)
-#else
-# define ALIGN_OF(type) _Alignof(type)
-#endif
-
-#define ALIGN_VOIDP ALIGN_OF(void*)
-#define ALIGN_CHAR ALIGN_OF(char)
-#define ALIGN_SHORT ALIGN_OF(short)
-#define ALIGN_INT ALIGN_OF(int)
-#define ALIGN_LONG ALIGN_OF(long)
-#if HAVE_LONG_LONG
-#define ALIGN_LONG_LONG ALIGN_OF(LONG_LONG)
-#endif
-#define ALIGN_FLOAT ALIGN_OF(float)
-#define ALIGN_DOUBLE ALIGN_OF(double)
-
-#define ALIGN_INT8_T ALIGN_OF(int8_t)
-#define ALIGN_INT16_T ALIGN_OF(int16_t)
-#define ALIGN_INT32_T ALIGN_OF(int32_t)
-#define ALIGN_INT64_T ALIGN_OF(int64_t)
-
-extern VALUE mFiddle;
-extern VALUE rb_eFiddleDLError;
-
-VALUE rb_fiddle_new_function(VALUE address, VALUE arg_types, VALUE ret_type);
-
-typedef void (*rb_fiddle_freefunc_t)(void*);
-VALUE rb_fiddle_ptr_new_wrap(void *ptr, long size, rb_fiddle_freefunc_t func, VALUE wrap0, VALUE wrap1);
-
-#endif
-/* vim: set noet sws=4 sw=4: */
diff --git a/ext/fiddle/function.c b/ext/fiddle/function.c
deleted file mode 100644
index 5469e09e37..0000000000
--- a/ext/fiddle/function.c
+++ /dev/null
@@ -1,496 +0,0 @@
-#include <fiddle.h>
-#include <ruby/thread.h>
-
-#include <stdbool.h>
-
-#ifdef PRIsVALUE
-# define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj)
-# define RB_OBJ_STRING(obj) (obj)
-#else
-# define PRIsVALUE "s"
-# define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj)
-# define RB_OBJ_STRING(obj) StringValueCStr(obj)
-#endif
-
-VALUE cFiddleFunction;
-
-#define MAX_ARGS (SIZE_MAX / (sizeof(void *) + sizeof(fiddle_generic)) - 1)
-
-#define Check_Max_Args(name, len) \
- Check_Max_Args_(name, len, "")
-#define Check_Max_Args_Long(name, len) \
- Check_Max_Args_(name, len, "l")
-#define Check_Max_Args_(name, len, fmt) \
- do { \
- if ((size_t)(len) >= MAX_ARGS) { \
- rb_raise(rb_eTypeError, \
- "%s is so large " \
- "that it can cause integer overflow (%"fmt"d)", \
- (name), (len)); \
- } \
- } while (0)
-
-static void
-deallocate(void *p)
-{
- ffi_cif *cif = p;
- if (cif->arg_types) xfree(cif->arg_types);
- xfree(cif);
-}
-
-static size_t
-function_memsize(const void *p)
-{
- /* const */ffi_cif *ptr = (ffi_cif *)p;
- size_t size = 0;
-
- size += sizeof(*ptr);
-#if !defined(FFI_NO_RAW_API) || !FFI_NO_RAW_API
- size += ffi_raw_size(ptr);
-#endif
-
- return size;
-}
-
-const rb_data_type_t function_data_type = {
- .wrap_struct_name = "fiddle/function",
- .function = {
- .dmark = 0,
- .dfree = deallocate,
- .dsize = function_memsize
- },
- .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
-};
-
-static VALUE
-allocate(VALUE klass)
-{
- ffi_cif * cif;
-
- return TypedData_Make_Struct(klass, ffi_cif, &function_data_type, cif);
-}
-
-VALUE
-rb_fiddle_new_function(VALUE address, VALUE arg_types, VALUE ret_type)
-{
- VALUE argv[3];
-
- argv[0] = address;
- argv[1] = arg_types;
- argv[2] = ret_type;
-
- return rb_class_new_instance(3, argv, cFiddleFunction);
-}
-
-static VALUE
-normalize_argument_types(const char *name,
- VALUE arg_types,
- bool *is_variadic)
-{
- VALUE normalized_arg_types;
- int i;
- int n_arg_types;
- *is_variadic = false;
-
- Check_Type(arg_types, T_ARRAY);
- n_arg_types = RARRAY_LENINT(arg_types);
- Check_Max_Args(name, n_arg_types);
-
- normalized_arg_types = rb_ary_new_capa(n_arg_types);
- for (i = 0; i < n_arg_types; i++) {
- VALUE arg_type = RARRAY_AREF(arg_types, i);
- int c_arg_type;
- arg_type = rb_fiddle_type_ensure(arg_type);
- c_arg_type = NUM2INT(arg_type);
- if (c_arg_type == TYPE_VARIADIC) {
- if (i != n_arg_types - 1) {
- rb_raise(rb_eArgError,
- "Fiddle::TYPE_VARIADIC must be the last argument type: "
- "%"PRIsVALUE,
- arg_types);
- }
- *is_variadic = true;
- break;
- }
- else {
- (void)INT2FFI_TYPE(c_arg_type); /* raise */
- }
- rb_ary_push(normalized_arg_types, INT2FIX(c_arg_type));
- }
-
- /* freeze to prevent inconsistency at calling #to_int later */
- OBJ_FREEZE(normalized_arg_types);
- return normalized_arg_types;
-}
-
-static VALUE
-initialize(int argc, VALUE argv[], VALUE self)
-{
- ffi_cif * cif;
- VALUE ptr, arg_types, ret_type, abi, kwargs;
- VALUE name = Qnil;
- VALUE need_gvl = Qfalse;
- int c_ret_type;
- bool is_variadic = false;
- ffi_abi c_ffi_abi;
- void *cfunc;
-
- rb_scan_args(argc, argv, "31:", &ptr, &arg_types, &ret_type, &abi, &kwargs);
- rb_iv_set(self, "@closure", ptr);
-
- if (!NIL_P(kwargs)) {
- enum {
- kw_name,
- kw_need_gvl,
- kw_max_,
- };
- static ID kw[kw_max_];
- VALUE args[kw_max_];
- if (!kw[0]) {
- kw[kw_name] = rb_intern_const("name");
- kw[kw_need_gvl] = rb_intern_const("need_gvl");
- }
- rb_get_kwargs(kwargs, kw, 0, kw_max_, args);
- if (args[kw_name] != Qundef) {
- name = args[kw_name];
- }
- if (args[kw_need_gvl] != Qundef) {
- need_gvl = args[kw_need_gvl];
- }
- }
- rb_iv_set(self, "@name", name);
- rb_iv_set(self, "@need_gvl", need_gvl);
-
- ptr = rb_Integer(ptr);
- cfunc = NUM2PTR(ptr);
- PTR2NUM(cfunc);
- c_ffi_abi = NIL_P(abi) ? FFI_DEFAULT_ABI : NUM2INT(abi);
- abi = INT2FIX(c_ffi_abi);
- ret_type = rb_fiddle_type_ensure(ret_type);
- c_ret_type = NUM2INT(ret_type);
- (void)INT2FFI_TYPE(c_ret_type); /* raise */
- ret_type = INT2FIX(c_ret_type);
-
- arg_types = normalize_argument_types("argument types",
- arg_types,
- &is_variadic);
-#ifndef HAVE_FFI_PREP_CIF_VAR
- if (is_variadic) {
- rb_raise(rb_eNotImpError,
- "ffi_prep_cif_var() is required in libffi "
- "for variadic arguments");
- }
-#endif
-
- rb_iv_set(self, "@ptr", ptr);
- rb_iv_set(self, "@argument_types", arg_types);
- rb_iv_set(self, "@return_type", ret_type);
- rb_iv_set(self, "@abi", abi);
- rb_iv_set(self, "@is_variadic", is_variadic ? Qtrue : Qfalse);
-
- TypedData_Get_Struct(self, ffi_cif, &function_data_type, cif);
- cif->arg_types = NULL;
-
- return self;
-}
-
-struct nogvl_ffi_call_args {
- ffi_cif *cif;
- void (*fn)(void);
- void **values;
- fiddle_generic retval;
-};
-
-static void *
-nogvl_ffi_call(void *ptr)
-{
- struct nogvl_ffi_call_args *args = ptr;
-
- ffi_call(args->cif, args->fn, &args->retval, args->values);
-
- return NULL;
-}
-
-static VALUE
-function_call(int argc, VALUE argv[], VALUE self)
-{
- struct nogvl_ffi_call_args args = { 0 };
- fiddle_generic *generic_args;
- VALUE cfunc;
- VALUE abi;
- VALUE arg_types;
- VALUE cPointer;
- VALUE is_variadic;
- VALUE need_gvl;
- int n_arg_types;
- int n_fixed_args = 0;
- int n_call_args = 0;
- int i;
- int i_call;
- VALUE converted_args = Qnil;
- VALUE alloc_buffer = 0;
-
- cfunc = rb_iv_get(self, "@ptr");
- abi = rb_iv_get(self, "@abi");
- arg_types = rb_iv_get(self, "@argument_types");
- cPointer = rb_const_get(mFiddle, rb_intern("Pointer"));
- is_variadic = rb_iv_get(self, "@is_variadic");
- need_gvl = rb_iv_get(self, "@need_gvl");
-
- n_arg_types = RARRAY_LENINT(arg_types);
- n_fixed_args = n_arg_types;
- if (RTEST(is_variadic)) {
- if (argc < n_arg_types) {
- rb_error_arity(argc, n_arg_types, UNLIMITED_ARGUMENTS);
- }
- if (((argc - n_arg_types) % 2) != 0) {
- rb_raise(rb_eArgError,
- "variadic arguments must be type and value pairs: "
- "%"PRIsVALUE,
- rb_ary_new_from_values(argc, argv));
- }
- n_call_args = n_arg_types + ((argc - n_arg_types) / 2);
- }
- else {
- if (argc != n_arg_types) {
- rb_error_arity(argc, n_arg_types, n_arg_types);
- }
- n_call_args = n_arg_types;
- }
- Check_Max_Args("the number of arguments", n_call_args);
-
- TypedData_Get_Struct(self, ffi_cif, &function_data_type, args.cif);
-
- if (is_variadic && args.cif->arg_types) {
- xfree(args.cif->arg_types);
- args.cif->arg_types = NULL;
- }
-
- if (!args.cif->arg_types) {
- VALUE fixed_arg_types = arg_types;
- VALUE return_type;
- int c_return_type;
- ffi_type *ffi_return_type;
- ffi_type **ffi_arg_types;
- ffi_status result;
-
- arg_types = rb_ary_dup(fixed_arg_types);
- for (i = n_fixed_args; i < argc; i += 2) {
- VALUE arg_type = argv[i];
- int c_arg_type;
- arg_type = rb_fiddle_type_ensure(arg_type);
- c_arg_type = NUM2INT(arg_type);
- (void)INT2FFI_TYPE(c_arg_type); /* raise */
- rb_ary_push(arg_types, INT2FIX(c_arg_type));
- }
-
- return_type = rb_iv_get(self, "@return_type");
- c_return_type = FIX2INT(return_type);
- ffi_return_type = INT2FFI_TYPE(c_return_type);
-
- ffi_arg_types = xcalloc(n_call_args + 1, sizeof(ffi_type *));
- for (i_call = 0; i_call < n_call_args; i_call++) {
- VALUE arg_type;
- int c_arg_type;
- arg_type = RARRAY_AREF(arg_types, i_call);
- c_arg_type = FIX2INT(arg_type);
- ffi_arg_types[i_call] = INT2FFI_TYPE(c_arg_type);
- }
- ffi_arg_types[i_call] = NULL;
-
- if (is_variadic) {
-#ifdef HAVE_FFI_PREP_CIF_VAR
- result = ffi_prep_cif_var(args.cif,
- FIX2INT(abi),
- n_fixed_args,
- n_call_args,
- ffi_return_type,
- ffi_arg_types);
-#else
- /* This code is never used because ffi_prep_cif_var()
- * availability check is done in #initialize. */
- result = FFI_BAD_TYPEDEF;
-#endif
- }
- else {
- result = ffi_prep_cif(args.cif,
- FIX2INT(abi),
- n_call_args,
- ffi_return_type,
- ffi_arg_types);
- }
- if (result != FFI_OK) {
- xfree(ffi_arg_types);
- args.cif->arg_types = NULL;
- rb_raise(rb_eRuntimeError, "error creating CIF %d", result);
- }
- }
-
- generic_args = ALLOCV(alloc_buffer,
- sizeof(fiddle_generic) * n_call_args +
- sizeof(void *) * (n_call_args + 1));
- args.values = (void **)((char *)generic_args +
- sizeof(fiddle_generic) * n_call_args);
-
- for (i = 0, i_call = 0;
- i < argc && i_call < n_call_args;
- i++, i_call++) {
- VALUE arg_type;
- int c_arg_type;
- VALUE original_src;
- VALUE src;
- arg_type = RARRAY_AREF(arg_types, i_call);
- c_arg_type = FIX2INT(arg_type);
- if (i >= n_fixed_args) {
- i++;
- }
- src = argv[i];
-
- if (c_arg_type == TYPE_VOIDP) {
- if (NIL_P(src)) {
- src = INT2FIX(0);
- }
- else if (cPointer != CLASS_OF(src)) {
- src = rb_funcall(cPointer, rb_intern("[]"), 1, src);
- if (NIL_P(converted_args)) {
- converted_args = rb_ary_new();
- }
- rb_ary_push(converted_args, src);
- }
- src = rb_Integer(src);
- }
-
- original_src = src;
- VALUE2GENERIC(c_arg_type, src, &generic_args[i_call]);
- if (src != original_src) {
- if (NIL_P(converted_args)) {
- converted_args = rb_ary_new();
- }
- rb_ary_push(converted_args, src);
- }
- args.values[i_call] = (void *)&generic_args[i_call];
- }
- args.values[i_call] = NULL;
- args.fn = (void(*)(void))NUM2PTR(cfunc);
-
- if (RTEST(need_gvl)) {
- ffi_call(args.cif, args.fn, &(args.retval), args.values);
- }
- else {
- (void)rb_thread_call_without_gvl(nogvl_ffi_call, &args, 0, 0);
- }
-
- {
- int errno_keep = errno;
-#if defined(_WIN32)
- DWORD error = WSAGetLastError();
- int socket_error = WSAGetLastError();
- rb_funcall(mFiddle, rb_intern("win32_last_error="), 1,
- ULONG2NUM(error));
- rb_funcall(mFiddle, rb_intern("win32_last_socket_error="), 1,
- INT2NUM(socket_error));
-#endif
- rb_funcall(mFiddle, rb_intern("last_error="), 1, INT2NUM(errno_keep));
- }
-
- ALLOCV_END(alloc_buffer);
-
- return GENERIC2VALUE(rb_iv_get(self, "@return_type"), args.retval);
-}
-
-void
-Init_fiddle_function(void)
-{
- /*
- * Document-class: Fiddle::Function
- *
- * == Description
- *
- * A representation of a C function
- *
- * == Examples
- *
- * === 'strcpy'
- *
- * @libc = Fiddle.dlopen "/lib/libc.so.6"
- * #=> #<Fiddle::Handle:0x00000001d7a8d8>
- * f = Fiddle::Function.new(
- * @libc['strcpy'],
- * [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP],
- * Fiddle::TYPE_VOIDP)
- * #=> #<Fiddle::Function:0x00000001d8ee00>
- * buff = "000"
- * #=> "000"
- * str = f.call(buff, "123")
- * #=> #<Fiddle::Pointer:0x00000001d0c380 ptr=0x000000018a21b8 size=0 free=0x00000000000000>
- * str.to_s
- * => "123"
- *
- * === ABI check
- *
- * @libc = Fiddle.dlopen "/lib/libc.so.6"
- * #=> #<Fiddle::Handle:0x00000001d7a8d8>
- * f = Fiddle::Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP)
- * #=> #<Fiddle::Function:0x00000001d8ee00>
- * f.abi == Fiddle::Function::DEFAULT
- * #=> true
- */
- cFiddleFunction = rb_define_class_under(mFiddle, "Function", rb_cObject);
-
- /*
- * Document-const: DEFAULT
- *
- * Default ABI
- *
- */
- rb_define_const(cFiddleFunction, "DEFAULT", INT2NUM(FFI_DEFAULT_ABI));
-
-#ifdef HAVE_CONST_FFI_STDCALL
- /*
- * Document-const: STDCALL
- *
- * FFI implementation of WIN32 stdcall convention
- *
- */
- rb_define_const(cFiddleFunction, "STDCALL", INT2NUM(FFI_STDCALL));
-#endif
-
- rb_define_alloc_func(cFiddleFunction, allocate);
-
- /*
- * Document-method: call
- *
- * Calls the constructed Function, with +args+.
- * Caller must ensure the underlying function is called in a
- * thread-safe manner if running in a multi-threaded process.
- *
- * Note that it is not thread-safe to use this method to
- * directly or indirectly call many Ruby C-extension APIs unless
- * you don't pass +need_gvl: true+ to Fiddle::Function#new.
- *
- * For an example see Fiddle::Function
- *
- */
- rb_define_method(cFiddleFunction, "call", function_call, -1);
-
- /*
- * Document-method: new
- * call-seq: new(ptr,
- * args,
- * ret_type,
- * abi = DEFAULT,
- * name: nil,
- * need_gvl: false)
- *
- * Constructs a Function object.
- * * +ptr+ is a referenced function, of a Fiddle::Handle
- * * +args+ is an Array of arguments, passed to the +ptr+ function
- * * +ret_type+ is the return type of the function
- * * +abi+ is the ABI of the function
- * * +name+ is the name of the function
- * * +need_gvl+ is whether GVL is needed to call the function
- *
- */
- rb_define_method(cFiddleFunction, "initialize", initialize, -1);
-}
-/* vim: set noet sws=4 sw=4: */
diff --git a/ext/fiddle/function.h b/ext/fiddle/function.h
deleted file mode 100644
index 829e592c8a..0000000000
--- a/ext/fiddle/function.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef FIDDLE_FUNCTION_H
-#define FIDDLE_FUNCTION_H
-
-#include <fiddle.h>
-
-void Init_fiddle_function(void);
-
-#endif
diff --git a/ext/fiddle/handle.c b/ext/fiddle/handle.c
deleted file mode 100644
index 8ba416952a..0000000000
--- a/ext/fiddle/handle.c
+++ /dev/null
@@ -1,591 +0,0 @@
-#include <ruby.h>
-#include <fiddle.h>
-
-VALUE rb_cHandle;
-
-struct dl_handle {
- void *ptr;
- int open;
- int enable_close;
-};
-
-#ifdef _WIN32
-# ifndef _WIN32_WCE
-static void *
-w32_coredll(void)
-{
- MEMORY_BASIC_INFORMATION m;
- memset(&m, 0, sizeof(m));
- if( !VirtualQuery(_errno, &m, sizeof(m)) ) return NULL;
- return m.AllocationBase;
-}
-# endif
-
-static int
-w32_dlclose(void *ptr)
-{
-# ifndef _WIN32_WCE
- if( ptr == w32_coredll() ) return 0;
-# endif
- if( FreeLibrary((HMODULE)ptr) ) return 0;
- return errno = rb_w32_map_errno(GetLastError());
-}
-#define dlclose(ptr) w32_dlclose(ptr)
-#endif
-
-static void
-fiddle_handle_free(void *ptr)
-{
- struct dl_handle *fiddle_handle = ptr;
- if( fiddle_handle->ptr && fiddle_handle->open && fiddle_handle->enable_close ){
- dlclose(fiddle_handle->ptr);
- }
- xfree(ptr);
-}
-
-static size_t
-fiddle_handle_memsize(const void *ptr)
-{
- return sizeof(struct dl_handle);
-}
-
-static const rb_data_type_t fiddle_handle_data_type = {
- .wrap_struct_name = "fiddle/handle",
- .function = {
- .dmark = 0,
- .dfree = fiddle_handle_free,
- .dsize = fiddle_handle_memsize
- },
- .flags = RUBY_TYPED_WB_PROTECTED,
-};
-
-/*
- * call-seq: close
- *
- * Close this handle.
- *
- * Calling close more than once will raise a Fiddle::DLError exception.
- */
-static VALUE
-rb_fiddle_handle_close(VALUE self)
-{
- struct dl_handle *fiddle_handle;
-
- TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
- if(fiddle_handle->open) {
- int ret = dlclose(fiddle_handle->ptr);
- fiddle_handle->open = 0;
-
- /* Check dlclose for successful return value */
- if(ret) {
-#if defined(HAVE_DLERROR)
- rb_raise(rb_eFiddleDLError, "%s", dlerror());
-#else
- rb_raise(rb_eFiddleDLError, "could not close handle");
-#endif
- }
- return INT2NUM(ret);
- }
- rb_raise(rb_eFiddleDLError, "dlclose() called too many times");
-
- UNREACHABLE;
-}
-
-static VALUE
-rb_fiddle_handle_s_allocate(VALUE klass)
-{
- VALUE obj;
- struct dl_handle *fiddle_handle;
-
- obj = TypedData_Make_Struct(rb_cHandle, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
- fiddle_handle->ptr = 0;
- fiddle_handle->open = 0;
- fiddle_handle->enable_close = 0;
-
- return obj;
-}
-
-static VALUE
-predefined_fiddle_handle(void *handle)
-{
- VALUE obj = rb_fiddle_handle_s_allocate(rb_cHandle);
- struct dl_handle *fiddle_handle = DATA_PTR(obj);
-
- fiddle_handle->ptr = handle;
- fiddle_handle->open = 1;
- OBJ_FREEZE(obj);
- return obj;
-}
-
-/*
- * call-seq:
- * new(library = nil, flags = Fiddle::RTLD_LAZY | Fiddle::RTLD_GLOBAL)
- *
- * Create a new handler that opens +library+ with +flags+.
- *
- * If no +library+ is specified or +nil+ is given, DEFAULT is used, which is
- * the equivalent to RTLD_DEFAULT. See <code>man 3 dlopen</code> for more.
- *
- * lib = Fiddle::Handle.new
- *
- * The default is dependent on OS, and provide a handle for all libraries
- * already loaded. For example, in most cases you can use this to access +libc+
- * functions, or ruby functions like +rb_str_new+.
- */
-static VALUE
-rb_fiddle_handle_initialize(int argc, VALUE argv[], VALUE self)
-{
- void *ptr;
- struct dl_handle *fiddle_handle;
- VALUE lib, flag;
- char *clib;
- int cflag;
- const char *err;
-
- switch( rb_scan_args(argc, argv, "02", &lib, &flag) ){
- case 0:
- clib = NULL;
- cflag = RTLD_LAZY | RTLD_GLOBAL;
- break;
- case 1:
- clib = NIL_P(lib) ? NULL : StringValueCStr(lib);
- cflag = RTLD_LAZY | RTLD_GLOBAL;
- break;
- case 2:
- clib = NIL_P(lib) ? NULL : StringValueCStr(lib);
- cflag = NUM2INT(flag);
- break;
- default:
- rb_bug("rb_fiddle_handle_new");
- }
-
-#if defined(_WIN32)
- if( !clib ){
- HANDLE rb_libruby_handle(void);
- ptr = rb_libruby_handle();
- }
- else if( STRCASECMP(clib, "libc") == 0
-# ifdef RUBY_COREDLL
- || STRCASECMP(clib, RUBY_COREDLL) == 0
- || STRCASECMP(clib, RUBY_COREDLL".dll") == 0
-# endif
- ){
-# ifdef _WIN32_WCE
- ptr = dlopen("coredll.dll", cflag);
-# else
- (void)cflag;
- ptr = w32_coredll();
-# endif
- }
- else
-#endif
- ptr = dlopen(clib, cflag);
-#if defined(HAVE_DLERROR)
- if( !ptr && (err = dlerror()) ){
- rb_raise(rb_eFiddleDLError, "%s", err);
- }
-#else
- if( !ptr ){
- err = dlerror();
- rb_raise(rb_eFiddleDLError, "%s", err);
- }
-#endif
- TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
- if( fiddle_handle->ptr && fiddle_handle->open && fiddle_handle->enable_close ){
- dlclose(fiddle_handle->ptr);
- }
- fiddle_handle->ptr = ptr;
- fiddle_handle->open = 1;
- fiddle_handle->enable_close = 0;
-
- if( rb_block_given_p() ){
- rb_ensure(rb_yield, self, rb_fiddle_handle_close, self);
- }
-
- return Qnil;
-}
-
-/*
- * call-seq: enable_close
- *
- * Enable a call to dlclose() when this handle is garbage collected.
- */
-static VALUE
-rb_fiddle_handle_enable_close(VALUE self)
-{
- struct dl_handle *fiddle_handle;
-
- TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
- fiddle_handle->enable_close = 1;
- return Qnil;
-}
-
-/*
- * call-seq: disable_close
- *
- * Disable a call to dlclose() when this handle is garbage collected.
- */
-static VALUE
-rb_fiddle_handle_disable_close(VALUE self)
-{
- struct dl_handle *fiddle_handle;
-
- TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
- fiddle_handle->enable_close = 0;
- return Qnil;
-}
-
-/*
- * call-seq: close_enabled?
- *
- * Returns +true+ if dlclose() will be called when this handle is garbage collected.
- *
- * See man(3) dlclose() for more info.
- */
-static VALUE
-rb_fiddle_handle_close_enabled_p(VALUE self)
-{
- struct dl_handle *fiddle_handle;
-
- TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
-
- if(fiddle_handle->enable_close) return Qtrue;
- return Qfalse;
-}
-
-/*
- * call-seq: to_i
- *
- * Returns the memory address for this handle.
- */
-static VALUE
-rb_fiddle_handle_to_i(VALUE self)
-{
- struct dl_handle *fiddle_handle;
-
- TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
- return PTR2NUM(fiddle_handle->ptr);
-}
-
-/*
- * call-seq: to_ptr
- *
- * Returns the Fiddle::Pointer of this handle.
- */
-static VALUE
-rb_fiddle_handle_to_ptr(VALUE self)
-{
- struct dl_handle *fiddle_handle;
-
- TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
- return rb_fiddle_ptr_new_wrap(fiddle_handle->ptr, 0, 0, self, 0);
-}
-
-static VALUE fiddle_handle_sym(void *handle, VALUE symbol);
-
-/*
- * Document-method: sym
- *
- * call-seq: sym(name)
- *
- * Get the address as an Integer for the function named +name+.
- */
-static VALUE
-rb_fiddle_handle_sym(VALUE self, VALUE sym)
-{
- struct dl_handle *fiddle_handle;
-
- TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
- if( ! fiddle_handle->open ){
- rb_raise(rb_eFiddleDLError, "closed handle");
- }
-
- return fiddle_handle_sym(fiddle_handle->ptr, sym);
-}
-
-#ifndef RTLD_NEXT
-#define RTLD_NEXT NULL
-#endif
-#ifndef RTLD_DEFAULT
-#define RTLD_DEFAULT NULL
-#endif
-
-/*
- * Document-method: sym
- *
- * call-seq: sym(name)
- *
- * Get the address as an Integer for the function named +name+. The function
- * is searched via dlsym on RTLD_NEXT.
- *
- * See man(3) dlsym() for more info.
- */
-static VALUE
-rb_fiddle_handle_s_sym(VALUE self, VALUE sym)
-{
- return fiddle_handle_sym(RTLD_NEXT, sym);
-}
-
-typedef void (*fiddle_void_func)(void);
-
-static fiddle_void_func
-fiddle_handle_find_func(void *handle, VALUE symbol)
-{
-#if defined(HAVE_DLERROR)
- const char *err;
-# define CHECK_DLERROR if ((err = dlerror()) != 0) { func = 0; }
-#else
-# define CHECK_DLERROR
-#endif
- fiddle_void_func func;
- const char *name = StringValueCStr(symbol);
-
-#ifdef HAVE_DLERROR
- dlerror();
-#endif
- func = (fiddle_void_func)(VALUE)dlsym(handle, name);
- CHECK_DLERROR;
-#if defined(FUNC_STDCALL)
- if( !func ){
- int i;
- int len = (int)strlen(name);
- char *name_n;
-#if defined(__CYGWIN__) || defined(_WIN32) || defined(__MINGW32__)
- {
- char *name_a = (char*)xmalloc(len+2);
- strcpy(name_a, name);
- name_n = name_a;
- name_a[len] = 'A';
- name_a[len+1] = '\0';
- func = dlsym(handle, name_a);
- CHECK_DLERROR;
- if( func ) goto found;
- name_n = xrealloc(name_a, len+6);
- }
-#else
- name_n = (char*)xmalloc(len+6);
-#endif
- memcpy(name_n, name, len);
- name_n[len++] = '@';
- for( i = 0; i < 256; i += 4 ){
- sprintf(name_n + len, "%d", i);
- func = dlsym(handle, name_n);
- CHECK_DLERROR;
- if( func ) break;
- }
- if( func ) goto found;
- name_n[len-1] = 'A';
- name_n[len++] = '@';
- for( i = 0; i < 256; i += 4 ){
- sprintf(name_n + len, "%d", i);
- func = dlsym(handle, name_n);
- CHECK_DLERROR;
- if( func ) break;
- }
- found:
- xfree(name_n);
- }
-#endif
-
- return func;
-}
-
-static VALUE
-rb_fiddle_handle_s_sym_defined(VALUE self, VALUE sym)
-{
- fiddle_void_func func;
-
- func = fiddle_handle_find_func(RTLD_NEXT, sym);
-
- if( func ) {
- return PTR2NUM(func);
- }
- else {
- return Qnil;
- }
-}
-
-static VALUE
-rb_fiddle_handle_sym_defined(VALUE self, VALUE sym)
-{
- struct dl_handle *fiddle_handle;
- fiddle_void_func func;
-
- TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
- if( ! fiddle_handle->open ){
- rb_raise(rb_eFiddleDLError, "closed handle");
- }
-
- func = fiddle_handle_find_func(fiddle_handle->ptr, sym);
-
- if( func ) {
- return PTR2NUM(func);
- }
- else {
- return Qnil;
- }
-}
-
-static VALUE
-fiddle_handle_sym(void *handle, VALUE symbol)
-{
- fiddle_void_func func;
-
- func = fiddle_handle_find_func(handle, symbol);
-
- if( !func ){
- rb_raise(rb_eFiddleDLError, "unknown symbol \"%"PRIsVALUE"\"", symbol);
- }
-
- return PTR2NUM(func);
-}
-
-/*
- * call-seq: file_name
- *
- * Returns the file name of this handle.
- */
-static VALUE
-rb_fiddle_handle_file_name(VALUE self)
-{
- struct dl_handle *fiddle_handle;
-
- TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle);
-
-#if defined(HAVE_DLINFO) && defined(HAVE_CONST_RTLD_DI_LINKMAP)
- {
- struct link_map *lm = NULL;
- int res = dlinfo(fiddle_handle->ptr, RTLD_DI_LINKMAP, &lm);
- if (res == 0 && lm != NULL) {
- return rb_str_new_cstr(lm->l_name);
- }
- else {
-#if defined(HAVE_DLERROR)
- rb_raise(rb_eFiddleDLError, "could not get handle file name: %s", dlerror());
-#else
- rb_raise(rb_eFiddleDLError, "could not get handle file name");
-#endif
- }
- }
-#elif defined(HAVE_GETMODULEFILENAME)
- {
- char filename[MAX_PATH];
- DWORD res = GetModuleFileName(fiddle_handle->ptr, filename, MAX_PATH);
- if (res == 0) {
- rb_raise(rb_eFiddleDLError, "could not get handle file name: %s", dlerror());
- }
- return rb_str_new_cstr(filename);
- }
-#else
- (void)fiddle_handle;
- return Qnil;
-#endif
-}
-
-void
-Init_fiddle_handle(void)
-{
- /*
- * Document-class: Fiddle::Handle
- *
- * The Fiddle::Handle is the manner to access the dynamic library
- *
- * == Example
- *
- * === Setup
- *
- * libc_so = "/lib64/libc.so.6"
- * => "/lib64/libc.so.6"
- * @handle = Fiddle::Handle.new(libc_so)
- * => #<Fiddle::Handle:0x00000000d69ef8>
- *
- * === Setup, with flags
- *
- * libc_so = "/lib64/libc.so.6"
- * => "/lib64/libc.so.6"
- * @handle = Fiddle::Handle.new(libc_so, Fiddle::RTLD_LAZY | Fiddle::RTLD_GLOBAL)
- * => #<Fiddle::Handle:0x00000000d69ef8>
- *
- * See RTLD_LAZY and RTLD_GLOBAL
- *
- * === Addresses to symbols
- *
- * strcpy_addr = @handle['strcpy']
- * => 140062278451968
- *
- * or
- *
- * strcpy_addr = @handle.sym('strcpy')
- * => 140062278451968
- *
- */
- rb_cHandle = rb_define_class_under(mFiddle, "Handle", rb_cObject);
- rb_define_alloc_func(rb_cHandle, rb_fiddle_handle_s_allocate);
- rb_define_singleton_method(rb_cHandle, "sym", rb_fiddle_handle_s_sym, 1);
- rb_define_singleton_method(rb_cHandle, "sym_defined?", rb_fiddle_handle_s_sym_defined, 1);
- rb_define_singleton_method(rb_cHandle, "[]", rb_fiddle_handle_s_sym, 1);
-
- /* Document-const: NEXT
- *
- * A predefined pseudo-handle of RTLD_NEXT
- *
- * Which will find the next occurrence of a function in the search order
- * after the current library.
- */
- rb_define_const(rb_cHandle, "NEXT", predefined_fiddle_handle(RTLD_NEXT));
-
- /* Document-const: DEFAULT
- *
- * A predefined pseudo-handle of RTLD_DEFAULT
- *
- * Which will find the first occurrence of the desired symbol using the
- * default library search order
- */
- rb_define_const(rb_cHandle, "DEFAULT", predefined_fiddle_handle(RTLD_DEFAULT));
-
- /* Document-const: RTLD_GLOBAL
- *
- * rtld Fiddle::Handle flag.
- *
- * The symbols defined by this library will be made available for symbol
- * resolution of subsequently loaded libraries.
- */
- rb_define_const(rb_cHandle, "RTLD_GLOBAL", INT2NUM(RTLD_GLOBAL));
-
- /* Document-const: RTLD_LAZY
- *
- * rtld Fiddle::Handle flag.
- *
- * Perform lazy binding. Only resolve symbols as the code that references
- * them is executed. If the symbol is never referenced, then it is never
- * resolved. (Lazy binding is only performed for function references;
- * references to variables are always immediately bound when the library
- * is loaded.)
- */
- rb_define_const(rb_cHandle, "RTLD_LAZY", INT2NUM(RTLD_LAZY));
-
- /* Document-const: RTLD_NOW
- *
- * rtld Fiddle::Handle flag.
- *
- * If this value is specified or the environment variable LD_BIND_NOW is
- * set to a nonempty string, all undefined symbols in the library are
- * resolved before Fiddle.dlopen returns. If this cannot be done an error
- * is returned.
- */
- rb_define_const(rb_cHandle, "RTLD_NOW", INT2NUM(RTLD_NOW));
-
- rb_define_method(rb_cHandle, "initialize", rb_fiddle_handle_initialize, -1);
- rb_define_method(rb_cHandle, "to_i", rb_fiddle_handle_to_i, 0);
- rb_define_method(rb_cHandle, "to_ptr", rb_fiddle_handle_to_ptr, 0);
- rb_define_method(rb_cHandle, "close", rb_fiddle_handle_close, 0);
- rb_define_method(rb_cHandle, "sym", rb_fiddle_handle_sym, 1);
- rb_define_method(rb_cHandle, "[]", rb_fiddle_handle_sym, 1);
- rb_define_method(rb_cHandle, "sym_defined?", rb_fiddle_handle_sym_defined, 1);
- rb_define_method(rb_cHandle, "file_name", rb_fiddle_handle_file_name, 0);
- rb_define_method(rb_cHandle, "disable_close", rb_fiddle_handle_disable_close, 0);
- rb_define_method(rb_cHandle, "enable_close", rb_fiddle_handle_enable_close, 0);
- rb_define_method(rb_cHandle, "close_enabled?", rb_fiddle_handle_close_enabled_p, 0);
-}
-
-/* vim: set noet sws=4 sw=4: */
diff --git a/ext/fiddle/lib/fiddle.rb b/ext/fiddle/lib/fiddle.rb
deleted file mode 100644
index 6137c487c6..0000000000
--- a/ext/fiddle/lib/fiddle.rb
+++ /dev/null
@@ -1,103 +0,0 @@
-# frozen_string_literal: true
-
-require 'fiddle.so'
-require 'fiddle/closure'
-require 'fiddle/function'
-require 'fiddle/version'
-
-module Fiddle
- if WINDOWS
- # Returns the last win32 +Error+ of the current executing +Thread+ or nil
- # if none
- def self.win32_last_error
- Thread.current[:__FIDDLE_WIN32_LAST_ERROR__]
- end
-
- # Sets the last win32 +Error+ of the current executing +Thread+ to +error+
- def self.win32_last_error= error
- Thread.current[:__FIDDLE_WIN32_LAST_ERROR__] = error
- end
-
- # Returns the last win32 socket +Error+ of the current executing
- # +Thread+ or nil if none
- def self.win32_last_socket_error
- Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__]
- end
-
- # Sets the last win32 socket +Error+ of the current executing
- # +Thread+ to +error+
- def self.win32_last_socket_error= error
- Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__] = error
- end
- end
-
- # Returns the last +Error+ of the current executing +Thread+ or nil if none
- def self.last_error
- Thread.current[:__FIDDLE_LAST_ERROR__]
- end
-
- # Sets the last +Error+ of the current executing +Thread+ to +error+
- def self.last_error= error
- Thread.current[:__DL2_LAST_ERROR__] = error
- Thread.current[:__FIDDLE_LAST_ERROR__] = error
- end
-
- # call-seq: dlopen(library) => Fiddle::Handle
- #
- # Creates a new handler that opens +library+, and returns an instance of
- # Fiddle::Handle.
- #
- # If +nil+ is given for the +library+, Fiddle::Handle::DEFAULT is used, which
- # is the equivalent to RTLD_DEFAULT. See <code>man 3 dlopen</code> for more.
- #
- # lib = Fiddle.dlopen(nil)
- #
- # The default is dependent on OS, and provide a handle for all libraries
- # already loaded. For example, in most cases you can use this to access
- # +libc+ functions, or ruby functions like +rb_str_new+.
- #
- # See Fiddle::Handle.new for more.
- def dlopen library
- begin
- Fiddle::Handle.new(library)
- rescue DLError => error
- case RUBY_PLATFORM
- when /linux/
- case error.message
- when /\A(\/.+?): (?:invalid ELF header|file too short)/
- # This may be a linker script:
- # https://sourceware.org/binutils/docs/ld.html#Scripts
- path = $1
- else
- raise
- end
- else
- raise
- end
-
- File.open(path) do |input|
- input.each_line do |line|
- case line
- when /\A\s*(?:INPUT|GROUP)\s*\(\s*([^\s,\)]+)/
- # TODO: Should we support multiple files?
- return dlopen($1)
- end
- end
- end
-
- # Not found
- raise
- end
- end
- module_function :dlopen
-
- # Add constants for backwards compat
-
- RTLD_GLOBAL = Handle::RTLD_GLOBAL # :nodoc:
- RTLD_LAZY = Handle::RTLD_LAZY # :nodoc:
- RTLD_NOW = Handle::RTLD_NOW # :nodoc:
-
- Fiddle::Types.constants.each do |type|
- const_set "TYPE_#{type}", Fiddle::Types.const_get(type)
- end
-end
diff --git a/ext/fiddle/lib/fiddle/closure.rb b/ext/fiddle/lib/fiddle/closure.rb
deleted file mode 100644
index 7e0077ea52..0000000000
--- a/ext/fiddle/lib/fiddle/closure.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-# frozen_string_literal: true
-module Fiddle
- class Closure
- class << self
- # Create a new closure. If a block is given, the created closure
- # is automatically freed after the given block is executed.
- #
- # The all given arguments are passed to Fiddle::Closure.new. So
- # using this method without block equals to Fiddle::Closure.new.
- #
- # == Example
- #
- # Fiddle::Closure.create(TYPE_INT, [TYPE_INT]) do |closure|
- # # closure is freed automatically when this block is finished.
- # end
- def create(*args)
- if block_given?
- closure = new(*args)
- begin
- yield(closure)
- ensure
- closure.free
- end
- else
- new(*args)
- end
- end
- end
-
- # the C type of the return of the FFI closure
- attr_reader :ctype
-
- # arguments of the FFI closure
- attr_reader :args
-
- # Extends Fiddle::Closure to allow for building the closure in a block
- class BlockCaller < Fiddle::Closure
-
- # == Description
- #
- # Construct a new BlockCaller object.
- #
- # * +ctype+ is the C type to be returned
- # * +args+ are passed the callback
- # * +abi+ is the abi of the closure
- #
- # If there is an error in preparing the +ffi_cif+ or +ffi_prep_closure+,
- # then a RuntimeError will be raised.
- #
- # == Example
- #
- # include Fiddle
- #
- # cb = Closure::BlockCaller.new(TYPE_INT, [TYPE_INT]) do |one|
- # one
- # end
- #
- # func = Function.new(cb, [TYPE_INT], TYPE_INT)
- #
- def initialize ctype, args, abi = Fiddle::Function::DEFAULT, &block
- super(ctype, args, abi)
- @block = block
- end
-
- # Calls the constructed BlockCaller, with +args+
- #
- # For an example see Fiddle::Closure::BlockCaller.new
- #
- def call *args
- @block.call(*args)
- end
- end
- end
-end
diff --git a/ext/fiddle/lib/fiddle/cparser.rb b/ext/fiddle/lib/fiddle/cparser.rb
deleted file mode 100644
index 264ca166dd..0000000000
--- a/ext/fiddle/lib/fiddle/cparser.rb
+++ /dev/null
@@ -1,278 +0,0 @@
-# frozen_string_literal: true
-module Fiddle
- # A mixin that provides methods for parsing C struct and prototype signatures.
- #
- # == Example
- # require 'fiddle/import'
- #
- # include Fiddle::CParser
- # #=> Object
- #
- # parse_ctype('int')
- # #=> Fiddle::TYPE_INT
- #
- # parse_struct_signature(['int i', 'char c'])
- # #=> [[Fiddle::TYPE_INT, Fiddle::TYPE_CHAR], ["i", "c"]]
- #
- # parse_signature('double sum(double, double)')
- # #=> ["sum", Fiddle::TYPE_DOUBLE, [Fiddle::TYPE_DOUBLE, Fiddle::TYPE_DOUBLE]]
- #
- module CParser
- # Parses a C struct's members
- #
- # Example:
- # require 'fiddle/import'
- #
- # include Fiddle::CParser
- # #=> Object
- #
- # parse_struct_signature(['int i', 'char c'])
- # #=> [[Fiddle::TYPE_INT, Fiddle::TYPE_CHAR], ["i", "c"]]
- #
- # parse_struct_signature(['char buffer[80]'])
- # #=> [[[Fiddle::TYPE_CHAR, 80]], ["buffer"]]
- #
- def parse_struct_signature(signature, tymap=nil)
- if signature.is_a?(String)
- signature = split_arguments(signature, /[,;]/)
- elsif signature.is_a?(Hash)
- signature = [signature]
- end
- mems = []
- tys = []
- signature.each{|msig|
- msig = compact(msig) if msig.is_a?(String)
- case msig
- when Hash
- msig.each do |struct_name, struct_signature|
- struct_name = struct_name.to_s if struct_name.is_a?(Symbol)
- struct_name = compact(struct_name)
- struct_count = nil
- if struct_name =~ /^([\w\*\s]+)\[(\d+)\]$/
- struct_count = $2.to_i
- struct_name = $1
- end
- if struct_signature.respond_to?(:entity_class)
- struct_type = struct_signature
- else
- parsed_struct = parse_struct_signature(struct_signature, tymap)
- struct_type = CStructBuilder.create(CStruct, *parsed_struct)
- end
- if struct_count
- ty = [struct_type, struct_count]
- else
- ty = struct_type
- end
- mems.push([struct_name, struct_type.members])
- tys.push(ty)
- end
- when /^[\w\*\s]+[\*\s](\w+)$/
- mems.push($1)
- tys.push(parse_ctype(msig, tymap))
- when /^[\w\*\s]+\(\*(\w+)\)\(.*?\)$/
- mems.push($1)
- tys.push(parse_ctype(msig, tymap))
- when /^([\w\*\s]+[\*\s])(\w+)\[(\d+)\]$/
- mems.push($2)
- tys.push([parse_ctype($1.strip, tymap), $3.to_i])
- when /^([\w\*\s]+)\[(\d+)\](\w+)$/
- mems.push($3)
- tys.push([parse_ctype($1.strip, tymap), $2.to_i])
- else
- raise(RuntimeError,"can't parse the struct member: #{msig}")
- end
- }
- return tys, mems
- end
-
- # Parses a C prototype signature
- #
- # If Hash +tymap+ is provided, the return value and the arguments from the
- # +signature+ are expected to be keys, and the value will be the C type to
- # be looked up.
- #
- # Example:
- # require 'fiddle/import'
- #
- # include Fiddle::CParser
- # #=> Object
- #
- # parse_signature('double sum(double, double)')
- # #=> ["sum", Fiddle::TYPE_DOUBLE, [Fiddle::TYPE_DOUBLE, Fiddle::TYPE_DOUBLE]]
- #
- # parse_signature('void update(void (*cb)(int code))')
- # #=> ["update", Fiddle::TYPE_VOID, [Fiddle::TYPE_VOIDP]]
- #
- # parse_signature('char (*getbuffer(void))[80]')
- # #=> ["getbuffer", Fiddle::TYPE_VOIDP, []]
- #
- def parse_signature(signature, tymap=nil)
- tymap ||= {}
- case compact(signature)
- when /^(?:[\w\*\s]+)\(\*(\w+)\((.*?)\)\)(?:\[\w*\]|\(.*?\));?$/
- func, args = $1, $2
- return [func, TYPE_VOIDP, split_arguments(args).collect {|arg| parse_ctype(arg, tymap)}]
- when /^([\w\*\s]+[\*\s])(\w+)\((.*?)\);?$/
- ret, func, args = $1.strip, $2, $3
- return [func, parse_ctype(ret, tymap), split_arguments(args).collect {|arg| parse_ctype(arg, tymap)}]
- else
- raise(RuntimeError,"can't parse the function prototype: #{signature}")
- end
- end
-
- # Given a String of C type +ty+, returns the corresponding Fiddle constant.
- #
- # +ty+ can also accept an Array of C type Strings, and will be returned in
- # a corresponding Array.
- #
- # If Hash +tymap+ is provided, +ty+ is expected to be the key, and the
- # value will be the C type to be looked up.
- #
- # Example:
- # require 'fiddle/import'
- #
- # include Fiddle::CParser
- # #=> Object
- #
- # parse_ctype('int')
- # #=> Fiddle::TYPE_INT
- #
- # parse_ctype('double diff')
- # #=> Fiddle::TYPE_DOUBLE
- #
- # parse_ctype('unsigned char byte')
- # #=> -Fiddle::TYPE_CHAR
- #
- # parse_ctype('const char* const argv[]')
- # #=> -Fiddle::TYPE_VOIDP
- #
- def parse_ctype(ty, tymap=nil)
- tymap ||= {}
- if ty.is_a?(Array)
- return [parse_ctype(ty[0], tymap), ty[1]]
- end
- ty = ty.gsub(/\Aconst\s+/, "")
- case ty
- when 'void'
- return TYPE_VOID
- when /\A(?:(?:signed\s+)?long\s+long(?:\s+int\s+)?|int64_t)(?:\s+\w+)?\z/
- unless Fiddle.const_defined?(:TYPE_LONG_LONG)
- raise(RuntimeError, "unsupported type: #{ty}")
- end
- return TYPE_LONG_LONG
- when /\A(?:unsigned\s+long\s+long(?:\s+int\s+)?|uint64_t)(?:\s+\w+)?\z/
- unless Fiddle.const_defined?(:TYPE_LONG_LONG)
- raise(RuntimeError, "unsupported type: #{ty}")
- end
- return TYPE_ULONG_LONG
- when /\Aunsigned\s+long(?:\s+int\s+)?(?:\s+\w+)?\z/,
- /\Aunsigned\s+int\s+long(?:\s+\w+)?\z/,
- /\Along(?:\s+int)?\s+unsigned(?:\s+\w+)?\z/,
- /\Aint\s+unsigned\s+long(?:\s+\w+)?\z/,
- /\A(?:int\s+)?long\s+unsigned(?:\s+\w+)?\z/
- return TYPE_ULONG
- when /\A(?:signed\s+)?long(?:\s+int\s+)?(?:\s+\w+)?\z/,
- /\A(?:signed\s+)?int\s+long(?:\s+\w+)?\z/,
- /\Along(?:\s+int)?\s+signed(?:\s+\w+)?\z/
- return TYPE_LONG
- when /\Aunsigned\s+short(?:\s+int\s+)?(?:\s+\w+)?\z/,
- /\Aunsigned\s+int\s+short(?:\s+\w+)?\z/,
- /\Ashort(?:\s+int)?\s+unsigned(?:\s+\w+)?\z/,
- /\Aint\s+unsigned\s+short(?:\s+\w+)?\z/,
- /\A(?:int\s+)?short\s+unsigned(?:\s+\w+)?\z/
- return TYPE_USHORT
- when /\A(?:signed\s+)?short(?:\s+int\s+)?(?:\s+\w+)?\z/,
- /\A(?:signed\s+)?int\s+short(?:\s+\w+)?\z/,
- /\Aint\s+(?:signed\s+)?short(?:\s+\w+)?\z/
- return TYPE_SHORT
- when /\A(?:signed\s+)?int(?:\s+\w+)?\z/
- return TYPE_INT
- when /\A(?:unsigned\s+int|uint)(?:\s+\w+)?\z/
- return TYPE_UINT
- when /\A(?:signed\s+)?char(?:\s+\w+)?\z/
- return TYPE_CHAR
- when /\Aunsigned\s+char(?:\s+\w+)?\z/
- return TYPE_UCHAR
- when /\Aint8_t(?:\s+\w+)?\z/
- unless Fiddle.const_defined?(:TYPE_INT8_T)
- raise(RuntimeError, "unsupported type: #{ty}")
- end
- return TYPE_INT8_T
- when /\Auint8_t(?:\s+\w+)?\z/
- unless Fiddle.const_defined?(:TYPE_INT8_T)
- raise(RuntimeError, "unsupported type: #{ty}")
- end
- return TYPE_UINT8_T
- when /\Aint16_t(?:\s+\w+)?\z/
- unless Fiddle.const_defined?(:TYPE_INT16_T)
- raise(RuntimeError, "unsupported type: #{ty}")
- end
- return TYPE_INT16_T
- when /\Auint16_t(?:\s+\w+)?\z/
- unless Fiddle.const_defined?(:TYPE_INT16_T)
- raise(RuntimeError, "unsupported type: #{ty}")
- end
- return TYPE_UINT16_T
- when /\Aint32_t(?:\s+\w+)?\z/
- unless Fiddle.const_defined?(:TYPE_INT32_T)
- raise(RuntimeError, "unsupported type: #{ty}")
- end
- return TYPE_INT32_T
- when /\Auint32_t(?:\s+\w+)?\z/
- unless Fiddle.const_defined?(:TYPE_INT32_T)
- raise(RuntimeError, "unsupported type: #{ty}")
- end
- return TYPE_UINT32_T
- when /\Aint64_t(?:\s+\w+)?\z/
- unless Fiddle.const_defined?(:TYPE_INT64_T)
- raise(RuntimeError, "unsupported type: #{ty}")
- end
- return TYPE_INT64_T
- when /\Auint64_t(?:\s+\w+)?\z/
- unless Fiddle.const_defined?(:TYPE_INT64_T)
- raise(RuntimeError, "unsupported type: #{ty}")
- end
- return TYPE_UINT64_T
- when /\Afloat(?:\s+\w+)?\z/
- return TYPE_FLOAT
- when /\Adouble(?:\s+\w+)?\z/
- return TYPE_DOUBLE
- when /\Asize_t(?:\s+\w+)?\z/
- return TYPE_SIZE_T
- when /\Assize_t(?:\s+\w+)?\z/
- return TYPE_SSIZE_T
- when /\Aptrdiff_t(?:\s+\w+)?\z/
- return TYPE_PTRDIFF_T
- when /\Aintptr_t(?:\s+\w+)?\z/
- return TYPE_INTPTR_T
- when /\Auintptr_t(?:\s+\w+)?\z/
- return TYPE_UINTPTR_T
- when "bool"
- return TYPE_BOOL
- when /\*/, /\[[\s\d]*\]/
- return TYPE_VOIDP
- when "..."
- return TYPE_VARIADIC
- else
- ty = ty.split(' ', 2)[0]
- if( tymap[ty] )
- return parse_ctype(tymap[ty], tymap)
- else
- raise(DLError, "unknown type: #{ty}")
- end
- end
- end
-
- private
-
- def split_arguments(arguments, sep=',')
- return [] if arguments.strip == 'void'
- arguments.scan(/([\w\*\s]+\(\*\w*\)\(.*?\)|[\w\*\s\[\]]+|\.\.\.)(?:#{sep}\s*|\z)/).collect {|m| m[0]}
- end
-
- def compact(signature)
- signature.gsub(/\s+/, ' ').gsub(/\s*([\(\)\[\]\*,;])\s*/, '\1').strip
- end
-
- end
-end
diff --git a/ext/fiddle/lib/fiddle/function.rb b/ext/fiddle/lib/fiddle/function.rb
deleted file mode 100644
index dc2e3e6bf5..0000000000
--- a/ext/fiddle/lib/fiddle/function.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-module Fiddle
- class Function
- # The ABI of the Function.
- attr_reader :abi
-
- # The address of this function
- attr_reader :ptr
-
- # The name of this function
- attr_reader :name
-
- # Whether GVL is needed to call this function
- def need_gvl?
- @need_gvl
- end
-
- # The integer memory location of this function
- def to_i
- ptr.to_i
- end
-
- # Turn this function in to a proc
- def to_proc
- this = self
- lambda { |*args| this.call(*args) }
- end
- end
-end
diff --git a/ext/fiddle/lib/fiddle/import.rb b/ext/fiddle/lib/fiddle/import.rb
deleted file mode 100644
index 050708fb96..0000000000
--- a/ext/fiddle/lib/fiddle/import.rb
+++ /dev/null
@@ -1,322 +0,0 @@
-# frozen_string_literal: true
-require 'fiddle'
-require 'fiddle/struct'
-require 'fiddle/cparser'
-
-module Fiddle
-
- # Used internally by Fiddle::Importer
- class CompositeHandler
- # Create a new handler with the open +handlers+
- #
- # Used internally by Fiddle::Importer.dlload
- def initialize(handlers)
- @handlers = handlers
- end
-
- # Array of the currently loaded libraries.
- def handlers()
- @handlers
- end
-
- # Returns the address as an Integer from any handlers with the function
- # named +symbol+.
- #
- # Raises a DLError if the handle is closed.
- def sym(symbol)
- @handlers.each{|handle|
- if( handle )
- begin
- addr = handle.sym(symbol)
- return addr
- rescue DLError
- end
- end
- }
- return nil
- end
-
- # See Fiddle::CompositeHandler.sym
- def [](symbol)
- sym(symbol)
- end
- end
-
- # A DSL that provides the means to dynamically load libraries and build
- # modules around them including calling extern functions within the C
- # library that has been loaded.
- #
- # == Example
- #
- # require 'fiddle'
- # require 'fiddle/import'
- #
- # module LibSum
- # extend Fiddle::Importer
- # dlload './libsum.so'
- # extern 'double sum(double*, int)'
- # extern 'double split(double)'
- # end
- #
- module Importer
- include Fiddle
- include CParser
- extend Importer
-
- attr_reader :type_alias
- private :type_alias
-
- # Creates an array of handlers for the given +libs+, can be an instance of
- # Fiddle::Handle, Fiddle::Importer, or will create a new instance of
- # Fiddle::Handle using Fiddle.dlopen
- #
- # Raises a DLError if the library cannot be loaded.
- #
- # See Fiddle.dlopen
- def dlload(*libs)
- handles = libs.collect{|lib|
- case lib
- when nil
- nil
- when Handle
- lib
- when Importer
- lib.handlers
- else
- Fiddle.dlopen(lib)
- end
- }.flatten()
- @handler = CompositeHandler.new(handles)
- @func_map = {}
- @type_alias = {}
- end
-
- # Sets the type alias for +alias_type+ as +orig_type+
- def typealias(alias_type, orig_type)
- @type_alias[alias_type] = orig_type
- end
-
- # Returns the sizeof +ty+, using Fiddle::Importer.parse_ctype to determine
- # the C type and the appropriate Fiddle constant.
- def sizeof(ty)
- case ty
- when String
- ty = parse_ctype(ty, type_alias).abs()
- case ty
- when TYPE_CHAR
- return SIZEOF_CHAR
- when TYPE_SHORT
- return SIZEOF_SHORT
- when TYPE_INT
- return SIZEOF_INT
- when TYPE_LONG
- return SIZEOF_LONG
- when TYPE_FLOAT
- return SIZEOF_FLOAT
- when TYPE_DOUBLE
- return SIZEOF_DOUBLE
- when TYPE_VOIDP
- return SIZEOF_VOIDP
- when TYPE_CONST_STRING
- return SIZEOF_CONST_STRING
- when TYPE_BOOL
- return SIZEOF_BOOL
- else
- if defined?(TYPE_LONG_LONG) and
- ty == TYPE_LONG_LONG
- return SIZEOF_LONG_LONG
- else
- raise(DLError, "unknown type: #{ty}")
- end
- end
- when Class
- if( ty.instance_methods().include?(:to_ptr) )
- return ty.size()
- end
- end
- return Pointer[ty].size()
- end
-
- def parse_bind_options(opts)
- h = {}
- while( opt = opts.shift() )
- case opt
- when :stdcall, :cdecl
- h[:call_type] = opt
- when :carried, :temp, :temporal, :bind
- h[:callback_type] = opt
- h[:carrier] = opts.shift()
- else
- h[opt] = true
- end
- end
- h
- end
- private :parse_bind_options
-
- # :stopdoc:
- CALL_TYPE_TO_ABI = Hash.new { |h, k|
- raise RuntimeError, "unsupported call type: #{k}"
- }.merge({ :stdcall => Function.const_defined?(:STDCALL) ? Function::STDCALL :
- Function::DEFAULT,
- :cdecl => Function::DEFAULT,
- nil => Function::DEFAULT
- }).freeze
- private_constant :CALL_TYPE_TO_ABI
- # :startdoc:
-
- # Creates a global method from the given C +signature+.
- def extern(signature, *opts)
- symname, ctype, argtype = parse_signature(signature, type_alias)
- opt = parse_bind_options(opts)
- f = import_function(symname, ctype, argtype, opt[:call_type])
- name = symname.gsub(/@.+/,'')
- @func_map[name] = f
- # define_method(name){|*args,&block| f.call(*args,&block)}
- begin
- /^(.+?):(\d+)/ =~ caller.first
- file, line = $1, $2.to_i
- rescue
- file, line = __FILE__, __LINE__+3
- end
- module_eval(<<-EOS, file, line)
- def #{name}(*args, &block)
- @func_map['#{name}'].call(*args,&block)
- end
- EOS
- module_function(name)
- f
- end
-
- # Creates a global method from the given C +signature+ using the given
- # +opts+ as bind parameters with the given block.
- def bind(signature, *opts, &blk)
- name, ctype, argtype = parse_signature(signature, type_alias)
- h = parse_bind_options(opts)
- case h[:callback_type]
- when :bind, nil
- f = bind_function(name, ctype, argtype, h[:call_type], &blk)
- else
- raise(RuntimeError, "unknown callback type: #{h[:callback_type]}")
- end
- @func_map[name] = f
- #define_method(name){|*args,&block| f.call(*args,&block)}
- begin
- /^(.+?):(\d+)/ =~ caller.first
- file, line = $1, $2.to_i
- rescue
- file, line = __FILE__, __LINE__+3
- end
- module_eval(<<-EOS, file, line)
- def #{name}(*args,&block)
- @func_map['#{name}'].call(*args,&block)
- end
- EOS
- module_function(name)
- f
- end
-
- # Creates a class to wrap the C struct described by +signature+.
- #
- # MyStruct = struct ['int i', 'char c']
- def struct(signature)
- tys, mems = parse_struct_signature(signature, type_alias)
- Fiddle::CStructBuilder.create(CStruct, tys, mems)
- end
-
- # Creates a class to wrap the C union described by +signature+.
- #
- # MyUnion = union ['int i', 'char c']
- def union(signature)
- tys, mems = parse_struct_signature(signature, type_alias)
- Fiddle::CStructBuilder.create(CUnion, tys, mems)
- end
-
- # Returns the function mapped to +name+, that was created by either
- # Fiddle::Importer.extern or Fiddle::Importer.bind
- def [](name)
- @func_map[name]
- end
-
- # Creates a class to wrap the C struct with the value +ty+
- #
- # See also Fiddle::Importer.struct
- def create_value(ty, val=nil)
- s = struct([ty + " value"])
- ptr = s.malloc()
- if( val )
- ptr.value = val
- end
- return ptr
- end
- alias value create_value
-
- # Returns a new instance of the C struct with the value +ty+ at the +addr+
- # address.
- def import_value(ty, addr)
- s = struct([ty + " value"])
- ptr = s.new(addr)
- return ptr
- end
-
-
- # The Fiddle::CompositeHandler instance
- #
- # Will raise an error if no handlers are open.
- def handler
- (@handler ||= nil) or raise "call dlload before importing symbols and functions"
- end
-
- # Returns a new Fiddle::Pointer instance at the memory address of the given
- # +name+ symbol.
- #
- # Raises a DLError if the +name+ doesn't exist.
- #
- # See Fiddle::CompositeHandler.sym and Fiddle::Handle.sym
- def import_symbol(name)
- addr = handler.sym(name)
- if( !addr )
- raise(DLError, "cannot find the symbol: #{name}")
- end
- Pointer.new(addr)
- end
-
- # Returns a new Fiddle::Function instance at the memory address of the given
- # +name+ function.
- #
- # Raises a DLError if the +name+ doesn't exist.
- #
- # * +argtype+ is an Array of arguments, passed to the +name+ function.
- # * +ctype+ is the return type of the function
- # * +call_type+ is the ABI of the function
- #
- # See also Fiddle:Function.new
- #
- # See Fiddle::CompositeHandler.sym and Fiddle::Handler.sym
- def import_function(name, ctype, argtype, call_type = nil)
- addr = handler.sym(name)
- if( !addr )
- raise(DLError, "cannot find the function: #{name}()")
- end
- Function.new(addr, argtype, ctype, CALL_TYPE_TO_ABI[call_type],
- name: name)
- end
-
- # Returns a new closure wrapper for the +name+ function.
- #
- # * +ctype+ is the return type of the function
- # * +argtype+ is an Array of arguments, passed to the callback function
- # * +call_type+ is the abi of the closure
- # * +block+ is passed to the callback
- #
- # See Fiddle::Closure
- def bind_function(name, ctype, argtype, call_type = nil, &block)
- abi = CALL_TYPE_TO_ABI[call_type]
- closure = Class.new(Fiddle::Closure) {
- define_method(:call, block)
- }.new(ctype, argtype, abi)
-
- Function.new(closure, argtype, ctype, abi, name: name)
- end
- end
-end
diff --git a/ext/fiddle/lib/fiddle/pack.rb b/ext/fiddle/lib/fiddle/pack.rb
deleted file mode 100644
index 81088f402b..0000000000
--- a/ext/fiddle/lib/fiddle/pack.rb
+++ /dev/null
@@ -1,149 +0,0 @@
-# frozen_string_literal: true
-require 'fiddle'
-
-module Fiddle
- module PackInfo # :nodoc: all
- ALIGN_MAP = {
- TYPE_VOIDP => ALIGN_VOIDP,
- TYPE_CHAR => ALIGN_CHAR,
- TYPE_SHORT => ALIGN_SHORT,
- TYPE_INT => ALIGN_INT,
- TYPE_LONG => ALIGN_LONG,
- TYPE_FLOAT => ALIGN_FLOAT,
- TYPE_DOUBLE => ALIGN_DOUBLE,
- TYPE_UCHAR => ALIGN_CHAR,
- TYPE_USHORT => ALIGN_SHORT,
- TYPE_UINT => ALIGN_INT,
- TYPE_ULONG => ALIGN_LONG,
- TYPE_BOOL => ALIGN_BOOL,
- }
-
- PACK_MAP = {
- TYPE_VOIDP => "L!",
- TYPE_CHAR => "c",
- TYPE_SHORT => "s!",
- TYPE_INT => "i!",
- TYPE_LONG => "l!",
- TYPE_FLOAT => "f",
- TYPE_DOUBLE => "d",
- TYPE_UCHAR => "C",
- TYPE_USHORT => "S!",
- TYPE_UINT => "I!",
- TYPE_ULONG => "L!",
- }
- case SIZEOF_BOOL
- when SIZEOF_CHAR
- PACK_MAP[TYPE_BOOL] = PACK_MAP[TYPE_UCHAR]
- when SIZEOF_SHORT
- PACK_MAP[TYPE_BOOL] = PACK_MAP[TYPE_USHORT]
- when SIZEOF_INT
- PACK_MAP[TYPE_BOOL] = PACK_MAP[TYPE_UINT]
- when SIZEOF_LONG
- PACK_MAP[TYPE_BOOL] = PACK_MAP[TYPE_ULONG]
- end
-
- SIZE_MAP = {
- TYPE_VOIDP => SIZEOF_VOIDP,
- TYPE_CHAR => SIZEOF_CHAR,
- TYPE_SHORT => SIZEOF_SHORT,
- TYPE_INT => SIZEOF_INT,
- TYPE_LONG => SIZEOF_LONG,
- TYPE_FLOAT => SIZEOF_FLOAT,
- TYPE_DOUBLE => SIZEOF_DOUBLE,
- TYPE_UCHAR => SIZEOF_CHAR,
- TYPE_USHORT => SIZEOF_SHORT,
- TYPE_UINT => SIZEOF_INT,
- TYPE_ULONG => SIZEOF_LONG,
- TYPE_BOOL => SIZEOF_BOOL,
- }
- if defined?(TYPE_LONG_LONG)
- ALIGN_MAP[TYPE_LONG_LONG] = ALIGN_MAP[TYPE_ULONG_LONG] = ALIGN_LONG_LONG
- PACK_MAP[TYPE_LONG_LONG] = "q"
- PACK_MAP[TYPE_ULONG_LONG] = "Q"
- SIZE_MAP[TYPE_LONG_LONG] = SIZE_MAP[TYPE_ULONG_LONG] = SIZEOF_LONG_LONG
- PACK_MAP[TYPE_VOIDP] = "Q" if SIZEOF_LONG_LONG == SIZEOF_VOIDP
- end
-
- def align(addr, align)
- d = addr % align
- if( d == 0 )
- addr
- else
- addr + (align - d)
- end
- end
- module_function :align
- end
-
- class Packer # :nodoc: all
- include PackInfo
-
- def self.[](*types)
- new(types)
- end
-
- def initialize(types)
- parse_types(types)
- end
-
- def size()
- @size
- end
-
- def pack(ary)
- case SIZEOF_VOIDP
- when SIZEOF_LONG
- ary.pack(@template)
- else
- if defined?(TYPE_LONG_LONG) and
- SIZEOF_VOIDP == SIZEOF_LONG_LONG
- ary.pack(@template)
- else
- raise(RuntimeError, "sizeof(void*)?")
- end
- end
- end
-
- def unpack(ary)
- case SIZEOF_VOIDP
- when SIZEOF_LONG
- ary.join().unpack(@template)
- else
- if defined?(TYPE_LONG_LONG) and
- SIZEOF_VOIDP == SIZEOF_LONG_LONG
- ary.join().unpack(@template)
- else
- raise(RuntimeError, "sizeof(void*)?")
- end
- end
- end
-
- private
-
- def parse_types(types)
- @template = "".dup
- addr = 0
- types.each{|t|
- orig_addr = addr
- if( t.is_a?(Array) )
- addr = align(orig_addr, ALIGN_MAP[TYPE_VOIDP])
- else
- addr = align(orig_addr, ALIGN_MAP[t])
- end
- d = addr - orig_addr
- if( d > 0 )
- @template << "x#{d}"
- end
- if( t.is_a?(Array) )
- @template << (PACK_MAP[t[0]] * t[1])
- addr += (SIZE_MAP[t[0]] * t[1])
- else
- @template << PACK_MAP[t]
- addr += SIZE_MAP[t]
- end
- }
- addr = align(addr, ALIGN_MAP[TYPE_VOIDP])
- @size = addr
- end
- end
-end
diff --git a/ext/fiddle/lib/fiddle/struct.rb b/ext/fiddle/lib/fiddle/struct.rb
deleted file mode 100644
index 6d05bbd742..0000000000
--- a/ext/fiddle/lib/fiddle/struct.rb
+++ /dev/null
@@ -1,539 +0,0 @@
-# frozen_string_literal: true
-require 'fiddle'
-require 'fiddle/value'
-require 'fiddle/pack'
-
-module Fiddle
- # A base class for objects representing a C structure
- class CStruct
- include Enumerable
-
- # accessor to Fiddle::CStructEntity
- def CStruct.entity_class
- CStructEntity
- end
-
- def self.offsetof(name, members, types) # :nodoc:
- offset = 0
- worklist = name.split('.')
- this_type = self
- while search_name = worklist.shift
- index = 0
- member_index = members.index(search_name)
-
- unless member_index
- # Possibly a sub-structure
- member_index = members.index { |member_name, _|
- member_name == search_name
- }
- return unless member_index
- end
-
- types.each { |type, count = 1|
- orig_offset = offset
- if type.respond_to?(:entity_class)
- align = type.alignment
- type_size = type.size
- else
- align = PackInfo::ALIGN_MAP[type]
- type_size = PackInfo::SIZE_MAP[type]
- end
-
- # Unions shouldn't advance the offset
- if this_type.entity_class == CUnionEntity
- type_size = 0
- end
-
- offset = PackInfo.align(orig_offset, align)
-
- if worklist.empty?
- return offset if index == member_index
- else
- if index == member_index
- subtype = types[member_index]
- members = subtype.members
- types = subtype.types
- this_type = subtype
- break
- end
- end
-
- offset += (type_size * count)
- index += 1
- }
- end
- nil
- end
-
- def each
- return enum_for(__function__) unless block_given?
-
- self.class.members.each do |name,|
- yield(self[name])
- end
- end
-
- def each_pair
- return enum_for(__function__) unless block_given?
-
- self.class.members.each do |name,|
- yield(name, self[name])
- end
- end
-
- def to_h
- hash = {}
- each_pair do |name, value|
- hash[name] = unstruct(value)
- end
- hash
- end
-
- def replace(another)
- if another.nil?
- self.class.members.each do |name,|
- self[name] = nil
- end
- elsif another.respond_to?(:each_pair)
- another.each_pair do |name, value|
- self[name] = value
- end
- else
- another.each do |name, value|
- self[name] = value
- end
- end
- self
- end
-
- private
- def unstruct(value)
- case value
- when CStruct
- value.to_h
- when Array
- value.collect do |v|
- unstruct(v)
- end
- else
- value
- end
- end
- end
-
- # A base class for objects representing a C union
- class CUnion
- # accessor to Fiddle::CUnionEntity
- def CUnion.entity_class
- CUnionEntity
- end
-
- def self.offsetof(name, members, types) # :nodoc:
- 0
- end
- end
-
- # Wrapper for arrays within a struct
- class StructArray < Array
- include ValueUtil
-
- def initialize(ptr, type, initial_values)
- @ptr = ptr
- @type = type
- @is_struct = @type.respond_to?(:entity_class)
- if @is_struct
- super(initial_values)
- else
- @size = Fiddle::PackInfo::SIZE_MAP[type]
- @pack_format = Fiddle::PackInfo::PACK_MAP[type]
- super(initial_values.collect { |v| unsigned_value(v, type) })
- end
- end
-
- def to_ptr
- @ptr
- end
-
- def []=(index, value)
- if index < 0 || index >= size
- raise IndexError, 'index %d outside of array bounds 0...%d' % [index, size]
- end
-
- if @is_struct
- self[index].replace(value)
- else
- to_ptr[index * @size, @size] = [value].pack(@pack_format)
- super(index, value)
- end
- end
- end
-
- # Used to construct C classes (CUnion, CStruct, etc)
- #
- # Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an
- # easy-to-use manner.
- module CStructBuilder
- # Construct a new class given a C:
- # * class +klass+ (CUnion, CStruct, or other that provide an
- # #entity_class)
- # * +types+ (Fiddle::TYPE_INT, Fiddle::TYPE_SIZE_T, etc., see the C types
- # constants)
- # * corresponding +members+
- #
- # Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an
- # easy-to-use manner.
- #
- # Examples:
- #
- # require 'fiddle/struct'
- # require 'fiddle/cparser'
- #
- # include Fiddle::CParser
- #
- # types, members = parse_struct_signature(['int i','char c'])
- #
- # MyStruct = Fiddle::CStructBuilder.create(Fiddle::CUnion, types, members)
- #
- # MyStruct.malloc(Fiddle::RUBY_FREE) do |obj|
- # ...
- # end
- #
- # obj = MyStruct.malloc(Fiddle::RUBY_FREE)
- # begin
- # ...
- # ensure
- # obj.call_free
- # end
- #
- # obj = MyStruct.malloc
- # begin
- # ...
- # ensure
- # Fiddle.free obj.to_ptr
- # end
- #
- def create(klass, types, members)
- new_class = Class.new(klass){
- define_method(:initialize){|addr, func = nil|
- if addr.is_a?(self.class.entity_class)
- @entity = addr
- else
- @entity = self.class.entity_class.new(addr, types, func)
- end
- @entity.assign_names(members)
- }
- define_method(:[]) { |*args| @entity.send(:[], *args) }
- define_method(:[]=) { |*args| @entity.send(:[]=, *args) }
- define_method(:to_ptr){ @entity }
- define_method(:to_i){ @entity.to_i }
- define_singleton_method(:types) { types }
- define_singleton_method(:members) { members }
-
- # Return the offset of a struct member given its name.
- # For example:
- #
- # MyStruct = struct [
- # "int64_t i",
- # "char c",
- # ]
- #
- # MyStruct.offsetof("i") # => 0
- # MyStruct.offsetof("c") # => 8
- #
- define_singleton_method(:offsetof) { |name|
- klass.offsetof(name, members, types)
- }
- members.each{|name|
- name = name[0] if name.is_a?(Array) # name is a nested struct
- next if method_defined?(name)
- define_method(name){ @entity[name] }
- define_method(name + "="){|val| @entity[name] = val }
- }
- entity_class = klass.entity_class
- alignment = entity_class.alignment(types)
- size = entity_class.size(types)
- define_singleton_method(:alignment) { alignment }
- define_singleton_method(:size) { size }
- define_singleton_method(:malloc) do |func=nil, &block|
- if block
- entity_class.malloc(types, func, size) do |entity|
- block.call(new(entity))
- end
- else
- new(entity_class.malloc(types, func, size))
- end
- end
- }
- return new_class
- end
- module_function :create
- end
-
- # A pointer to a C structure
- class CStructEntity < Fiddle::Pointer
- include PackInfo
- include ValueUtil
-
- def CStructEntity.alignment(types)
- max = 1
- types.each do |type, count = 1|
- if type.respond_to?(:entity_class)
- n = type.alignment
- else
- n = ALIGN_MAP[type]
- end
- max = n if n > max
- end
- max
- end
-
- # Allocates a C struct with the +types+ provided.
- #
- # See Fiddle::Pointer.malloc for memory management issues.
- def CStructEntity.malloc(types, func = nil, size = size(types), &block)
- if block_given?
- super(size, func) do |struct|
- struct.set_ctypes types
- yield struct
- end
- else
- struct = super(size, func)
- struct.set_ctypes types
- struct
- end
- end
-
- # Returns the offset for the packed sizes for the given +types+.
- #
- # Fiddle::CStructEntity.size(
- # [ Fiddle::TYPE_DOUBLE,
- # Fiddle::TYPE_INT,
- # Fiddle::TYPE_CHAR,
- # Fiddle::TYPE_VOIDP ]) #=> 24
- def CStructEntity.size(types)
- offset = 0
-
- max_align = types.map { |type, count = 1|
- last_offset = offset
-
- if type.respond_to?(:entity_class)
- align = type.alignment
- type_size = type.size
- else
- align = PackInfo::ALIGN_MAP[type]
- type_size = PackInfo::SIZE_MAP[type]
- end
- offset = PackInfo.align(last_offset, align) +
- (type_size * count)
-
- align
- }.max
-
- PackInfo.align(offset, max_align)
- end
-
- # Wraps the C pointer +addr+ as a C struct with the given +types+.
- #
- # When the instance is garbage collected, the C function +func+ is called.
- #
- # See also Fiddle::Pointer.new
- def initialize(addr, types, func = nil)
- if func && addr.is_a?(Pointer) && addr.free
- raise ArgumentError, 'free function specified on both underlying struct Pointer and when creating a CStructEntity - who do you want to free this?'
- end
- set_ctypes(types)
- super(addr, @size, func)
- end
-
- # Set the names of the +members+ in this C struct
- def assign_names(members)
- @members = []
- @nested_structs = {}
- members.each_with_index do |member, index|
- if member.is_a?(Array) # nested struct
- member_name = member[0]
- struct_type, struct_count = @ctypes[index]
- if struct_count.nil?
- struct = struct_type.new(to_i + @offset[index])
- else
- structs = struct_count.times.map do |i|
- struct_type.new(to_i + @offset[index] + i * struct_type.size)
- end
- struct = StructArray.new(to_i + @offset[index],
- struct_type,
- structs)
- end
- @nested_structs[member_name] = struct
- else
- member_name = member
- end
- @members << member_name
- end
- end
-
- # Calculates the offsets and sizes for the given +types+ in the struct.
- def set_ctypes(types)
- @ctypes = types
- @offset = []
- offset = 0
-
- max_align = types.map { |type, count = 1|
- orig_offset = offset
- if type.respond_to?(:entity_class)
- align = type.alignment
- type_size = type.size
- else
- align = ALIGN_MAP[type]
- type_size = SIZE_MAP[type]
- end
- offset = PackInfo.align(orig_offset, align)
-
- @offset << offset
-
- offset += (type_size * count)
-
- align
- }.max
-
- @size = PackInfo.align(offset, max_align)
- end
-
- # Fetch struct member +name+ if only one argument is specified. If two
- # arguments are specified, the first is an offset and the second is a
- # length and this method returns the string of +length+ bytes beginning at
- # +offset+.
- #
- # Examples:
- #
- # my_struct = struct(['int id']).malloc
- # my_struct.id = 1
- # my_struct['id'] # => 1
- # my_struct[0, 4] # => "\x01\x00\x00\x00".b
- #
- def [](*args)
- return super(*args) if args.size > 1
- name = args[0]
- idx = @members.index(name)
- if( idx.nil? )
- raise(ArgumentError, "no such member: #{name}")
- end
- ty = @ctypes[idx]
- if( ty.is_a?(Array) )
- if ty.first.respond_to?(:entity_class)
- return @nested_structs[name]
- else
- r = super(@offset[idx], SIZE_MAP[ty[0]] * ty[1])
- end
- elsif ty.respond_to?(:entity_class)
- return @nested_structs[name]
- else
- r = super(@offset[idx], SIZE_MAP[ty.abs])
- end
- packer = Packer.new([ty])
- val = packer.unpack([r])
- case ty
- when Array
- case ty[0]
- when TYPE_VOIDP
- val = val.collect{|v| Pointer.new(v)}
- end
- when TYPE_VOIDP
- val = Pointer.new(val[0])
- else
- val = val[0]
- end
- if( ty.is_a?(Integer) && (ty < 0) )
- return unsigned_value(val, ty)
- elsif( ty.is_a?(Array) && (ty[0] < 0) )
- return StructArray.new(self + @offset[idx], ty[0], val)
- else
- return val
- end
- end
-
- # Set struct member +name+, to value +val+. If more arguments are
- # specified, writes the string of bytes to the memory at the given
- # +offset+ and +length+.
- #
- # Examples:
- #
- # my_struct = struct(['int id']).malloc
- # my_struct['id'] = 1
- # my_struct[0, 4] = "\x01\x00\x00\x00".b
- # my_struct.id # => 1
- #
- def []=(*args)
- return super(*args) if args.size > 2
- name, val = *args
- name = name.to_s if name.is_a?(Symbol)
- nested_struct = @nested_structs[name]
- if nested_struct
- if nested_struct.is_a?(StructArray)
- if val.nil?
- nested_struct.each do |s|
- s.replace(nil)
- end
- else
- val.each_with_index do |v, i|
- nested_struct[i] = v
- end
- end
- else
- nested_struct.replace(val)
- end
- return val
- end
- idx = @members.index(name)
- if( idx.nil? )
- raise(ArgumentError, "no such member: #{name}")
- end
- ty = @ctypes[idx]
- packer = Packer.new([ty])
- val = wrap_arg(val, ty, [])
- buff = packer.pack([val].flatten())
- super(@offset[idx], buff.size, buff)
- if( ty.is_a?(Integer) && (ty < 0) )
- return unsigned_value(val, ty)
- elsif( ty.is_a?(Array) && (ty[0] < 0) )
- return val.collect{|v| unsigned_value(v,ty[0])}
- else
- return val
- end
- end
-
- undef_method :size=
- def to_s() # :nodoc:
- super(@size)
- end
- end
-
- # A pointer to a C union
- class CUnionEntity < CStructEntity
- include PackInfo
-
- # Returns the size needed for the union with the given +types+.
- #
- # Fiddle::CUnionEntity.size(
- # [ Fiddle::TYPE_DOUBLE,
- # Fiddle::TYPE_INT,
- # Fiddle::TYPE_CHAR,
- # Fiddle::TYPE_VOIDP ]) #=> 8
- def CUnionEntity.size(types)
- types.map { |type, count = 1|
- if type.respond_to?(:entity_class)
- type.size * count
- else
- PackInfo::SIZE_MAP[type] * count
- end
- }.max
- end
-
- # Calculate the necessary offset and for each union member with the given
- # +types+
- def set_ctypes(types)
- @ctypes = types
- @offset = Array.new(types.length, 0)
- @size = self.class.size types
- end
- end
-end
diff --git a/ext/fiddle/lib/fiddle/types.rb b/ext/fiddle/lib/fiddle/types.rb
deleted file mode 100644
index 7baf31ec9e..0000000000
--- a/ext/fiddle/lib/fiddle/types.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# frozen_string_literal: true
-module Fiddle
- # Adds Windows type aliases to the including class for use with
- # Fiddle::Importer.
- #
- # The aliases added are:
- # * ATOM
- # * BOOL
- # * BYTE
- # * DWORD
- # * DWORD32
- # * DWORD64
- # * HANDLE
- # * HDC
- # * HINSTANCE
- # * HWND
- # * LPCSTR
- # * LPSTR
- # * PBYTE
- # * PDWORD
- # * PHANDLE
- # * PVOID
- # * PWORD
- # * UCHAR
- # * UINT
- # * ULONG
- # * WORD
- module Win32Types
- def included(m) # :nodoc:
- # https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types
- m.module_eval{
- typealias "ATOM", "WORD"
- typealias "BOOL", "int"
- typealias "BYTE", "unsigned char"
- typealias "DWORD", "unsigned long"
- typealias "DWORD32", "uint32_t"
- typealias "DWORD64", "uint64_t"
- typealias "HANDLE", "PVOID"
- typealias "HDC", "HANDLE"
- typealias "HINSTANCE", "HANDLE"
- typealias "HWND", "HANDLE"
- typealias "LPCSTR", "const char *"
- typealias "LPSTR", "char *"
- typealias "PBYTE", "BYTE *"
- typealias "PDWORD", "DWORD *"
- typealias "PHANDLE", "HANDLE *"
- typealias "PVOID", "void *"
- typealias "PWORD", "WORD *"
- typealias "UCHAR", "unsigned char"
- typealias "UINT", "unsigned int"
- typealias "ULONG", "unsigned long"
- typealias "WORD", "unsigned short"
- }
- end
- module_function :included
- end
-
- # Adds basic type aliases to the including class for use with Fiddle::Importer.
- #
- # The aliases added are +uint+ and +u_int+ (<tt>unsigned int</tt>) and
- # +ulong+ and +u_long+ (<tt>unsigned long</tt>)
- module BasicTypes
- def included(m) # :nodoc:
- m.module_eval{
- typealias "uint", "unsigned int"
- typealias "u_int", "unsigned int"
- typealias "ulong", "unsigned long"
- typealias "u_long", "unsigned long"
- }
- end
- module_function :included
- end
-end
diff --git a/ext/fiddle/lib/fiddle/value.rb b/ext/fiddle/lib/fiddle/value.rb
deleted file mode 100644
index 5f0b2e951e..0000000000
--- a/ext/fiddle/lib/fiddle/value.rb
+++ /dev/null
@@ -1,120 +0,0 @@
-# frozen_string_literal: true
-require 'fiddle'
-
-module Fiddle
- module ValueUtil #:nodoc: all
- def unsigned_value(val, ty)
- case ty.abs
- when TYPE_CHAR
- [val].pack("c").unpack1("C")
- when TYPE_SHORT
- [val].pack("s!").unpack1("S!")
- when TYPE_INT
- [val].pack("i!").unpack1("I!")
- when TYPE_LONG
- [val].pack("l!").unpack1("L!")
- else
- if defined?(TYPE_LONG_LONG) and
- ty.abs == TYPE_LONG_LONG
- [val].pack("q").unpack1("Q")
- else
- val
- end
- end
- end
-
- def signed_value(val, ty)
- case ty.abs
- when TYPE_CHAR
- [val].pack("C").unpack1("c")
- when TYPE_SHORT
- [val].pack("S!").unpack1("s!")
- when TYPE_INT
- [val].pack("I!").unpack1("i!")
- when TYPE_LONG
- [val].pack("L!").unpack1("l!")
- else
- if defined?(TYPE_LONG_LONG) and
- ty.abs == TYPE_LONG_LONG
- [val].pack("Q").unpack1("q")
- else
- val
- end
- end
- end
-
- def wrap_args(args, tys, funcs, &block)
- result = []
- tys ||= []
- args.each_with_index{|arg, idx|
- result.push(wrap_arg(arg, tys[idx], funcs, &block))
- }
- result
- end
-
- def wrap_arg(arg, ty, funcs = [], &block)
- funcs ||= []
- case arg
- when nil
- return 0
- when Pointer
- return arg.to_i
- when IO
- case ty
- when TYPE_VOIDP
- return Pointer[arg].to_i
- else
- return arg.to_i
- end
- when Function
- if( block )
- arg.bind_at_call(&block)
- funcs.push(arg)
- elsif !arg.bound?
- raise(RuntimeError, "block must be given.")
- end
- return arg.to_i
- when String
- if( ty.is_a?(Array) )
- return arg.unpack('C*')
- else
- case SIZEOF_VOIDP
- when SIZEOF_LONG
- return [arg].pack("p").unpack1("l!")
- else
- if defined?(SIZEOF_LONG_LONG) and
- SIZEOF_VOIDP == SIZEOF_LONG_LONG
- return [arg].pack("p").unpack1("q")
- else
- raise(RuntimeError, "sizeof(void*)?")
- end
- end
- end
- when Float, Integer
- return arg
- when Array
- if( ty.is_a?(Array) ) # used only by struct
- case ty[0]
- when TYPE_VOIDP
- return arg.collect{|v| Integer(v)}
- when TYPE_CHAR
- if( arg.is_a?(String) )
- return val.unpack('C*')
- end
- end
- end
- return arg
- else
- if( arg.respond_to?(:to_ptr) )
- return arg.to_ptr.to_i
- else
- begin
- return Integer(arg)
- rescue
- raise(ArgumentError, "unknown argument type: #{arg.class}")
- end
- end
- end
- end
- end
-end
diff --git a/ext/fiddle/lib/fiddle/version.rb b/ext/fiddle/lib/fiddle/version.rb
deleted file mode 100644
index 6c5109dca8..0000000000
--- a/ext/fiddle/lib/fiddle/version.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-module Fiddle
- VERSION = "1.1.3"
-end
diff --git a/ext/fiddle/memory_view.c b/ext/fiddle/memory_view.c
deleted file mode 100644
index fa66fc2c7b..0000000000
--- a/ext/fiddle/memory_view.c
+++ /dev/null
@@ -1,321 +0,0 @@
-#include <fiddle.h>
-
-#ifdef HAVE_RUBY_MEMORY_VIEW_H
-
-#include <stdbool.h>
-#include <ruby/ruby.h>
-#include <ruby/encoding.h>
-#include <ruby/memory_view.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
-
-VALUE rb_cMemoryView = Qnil;
-
-struct memview_data {
- rb_memory_view_t view;
- rb_memory_view_item_component_t *members;
- size_t n_members;
-};
-
-static void
-fiddle_memview_mark(void *ptr)
-{
- const struct memview_data *data = ptr;
- rb_gc_mark(data->view.obj);
-}
-
-static void
-fiddle_memview_release(struct memview_data *data)
-{
- if (NIL_P(data->view.obj)) return;
-
- rb_memory_view_release(&data->view);
- data->view.obj = Qnil;
- data->view.byte_size = 0;
- if (data->members) {
- xfree(data->members);
- data->members = NULL;
- data->n_members = 0;
- }
-}
-
-static void
-fiddle_memview_free(void *ptr)
-{
- struct memview_data *data = ptr;
- fiddle_memview_release(data);
- xfree(ptr);
-}
-
-static size_t
-fiddle_memview_memsize(const void *ptr)
-{
- const struct memview_data *data = ptr;
- return sizeof(*data) + sizeof(rb_memory_view_item_component_t)*data->n_members + (size_t)data->view.byte_size;
-}
-
-static const rb_data_type_t fiddle_memview_data_type = {
- "fiddle/memory_view",
- {fiddle_memview_mark, fiddle_memview_free, fiddle_memview_memsize,},
-};
-
-static VALUE
-rb_fiddle_memview_s_allocate(VALUE klass)
-{
- struct memview_data *data;
- VALUE obj = TypedData_Make_Struct(klass, struct memview_data, &fiddle_memview_data_type, data);
- data->view.obj = Qnil;
- data->view.byte_size = 0;
- data->members = NULL;
- data->n_members = 0;
- return obj;
-}
-
-static VALUE
-rb_fiddle_memview_release(VALUE obj)
-{
- struct memview_data *data;
- TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
-
- if (NIL_P(data->view.obj)) return Qnil;
- fiddle_memview_release(data);
- return Qnil;
-}
-
-static VALUE
-rb_fiddle_memview_s_export(VALUE klass, VALUE target)
-{
- ID id_new;
- CONST_ID(id_new, "new");
- VALUE memview = rb_funcall(klass, id_new, 1, target);
- return rb_ensure(rb_yield, memview, rb_fiddle_memview_release, memview);
-}
-
-static VALUE
-rb_fiddle_memview_initialize(VALUE obj, VALUE target)
-{
- struct memview_data *data;
- TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
-
- if (!rb_memory_view_get(target, &data->view, 0)) {
- data->view.obj = Qnil;
- rb_raise(rb_eArgError, "Unable to get a memory view from %+"PRIsVALUE, target);
- }
-
- return Qnil;
-}
-
-static VALUE
-rb_fiddle_memview_get_obj(VALUE obj)
-{
- struct memview_data *data;
- TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
-
- return data->view.obj;
-}
-
-static VALUE
-rb_fiddle_memview_get_byte_size(VALUE obj)
-{
- struct memview_data *data;
- TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
-
- if (NIL_P(data->view.obj)) return Qnil;
- return SSIZET2NUM(data->view.byte_size);
-}
-
-static VALUE
-rb_fiddle_memview_get_readonly(VALUE obj)
-{
- struct memview_data *data;
- TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
-
- if (NIL_P(data->view.obj)) return Qnil;
- return data->view.readonly ? Qtrue : Qfalse;
-}
-
-static VALUE
-rb_fiddle_memview_get_format(VALUE obj)
-{
- struct memview_data *data;
- TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
-
- if (NIL_P(data->view.obj)) return Qnil;
- return data->view.format == NULL ? Qnil : rb_str_new_cstr(data->view.format);
-}
-
-static VALUE
-rb_fiddle_memview_get_item_size(VALUE obj)
-{
- struct memview_data *data;
- TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
-
- if (NIL_P(data->view.obj)) return Qnil;
- return SSIZET2NUM(data->view.item_size);
-}
-
-static VALUE
-rb_fiddle_memview_get_ndim(VALUE obj)
-{
- struct memview_data *data;
- TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
-
- if (NIL_P(data->view.obj)) return Qnil;
- return SSIZET2NUM(data->view.ndim);
-}
-
-static VALUE
-rb_fiddle_memview_get_shape(VALUE obj)
-{
- struct memview_data *data;
- TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
-
- if (NIL_P(data->view.obj)) return Qnil;
- if (data->view.shape == NULL) return Qnil;
-
- const ssize_t ndim = data->view.ndim;
- VALUE shape = rb_ary_new_capa(ndim);
- ssize_t i;
- for (i = 0; i < ndim; ++i) {
- rb_ary_push(shape, SSIZET2NUM(data->view.shape[i]));
- }
- return shape;
-}
-
-static VALUE
-rb_fiddle_memview_get_strides(VALUE obj)
-{
- struct memview_data *data;
- TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
-
- if (NIL_P(data->view.obj)) return Qnil;
- if (data->view.strides == NULL) return Qnil;
-
- const ssize_t ndim = data->view.ndim;
- VALUE strides = rb_ary_new_capa(ndim);
- ssize_t i;
- for (i = 0; i < ndim; ++i) {
- rb_ary_push(strides, SSIZET2NUM(data->view.strides[i]));
- }
- return strides;
-}
-
-static VALUE
-rb_fiddle_memview_get_sub_offsets(VALUE obj)
-{
- struct memview_data *data;
- TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
-
- if (NIL_P(data->view.obj)) return Qnil;
- if (data->view.sub_offsets == NULL) return Qnil;
-
- const ssize_t ndim = data->view.ndim;
- VALUE sub_offsets = rb_ary_new_capa(ndim);
- ssize_t i;
- for (i = 0; i < ndim; ++i) {
- rb_ary_push(sub_offsets, SSIZET2NUM(data->view.sub_offsets[i]));
- }
- return sub_offsets;
-}
-
-static VALUE
-rb_fiddle_memview_aref(int argc, VALUE *argv, VALUE obj)
-{
- struct memview_data *data;
- TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data);
-
- if (NIL_P(data->view.obj)) return Qnil;
-
- const ssize_t ndim = data->view.ndim;
- if (argc != ndim) {
- rb_raise(rb_eIndexError, "wrong number of index (%d for %"PRIdSIZE")", argc, ndim);
- }
-
- VALUE indices_v = 0;
- ssize_t *indices = ALLOCV_N(ssize_t, indices_v, ndim);
-
- ssize_t i;
- for (i = 0; i < ndim; ++i) {
- ssize_t x = NUM2SSIZET(argv[i]);
- indices[i] = x;
- }
-
- uint8_t *ptr = rb_memory_view_get_item_pointer(&data->view, indices);
- ALLOCV_END(indices_v);
-
- if (data->view.format == NULL) {
- return INT2FIX(*ptr);
- }
-
- if (!data->members) {
- const char *err;
- if (rb_memory_view_parse_item_format(data->view.format, &data->members, &data->n_members, &err) < 0) {
- rb_raise(rb_eRuntimeError, "Unable to recognize item format at %"PRIdSIZE" in \"%s\"",
- err - data->view.format, data->view.format);
- }
- }
-
- return rb_memory_view_extract_item_members(ptr, data->members, data->n_members);
-}
-
-static VALUE
-rb_fiddle_memview_to_s(VALUE self)
-{
- struct memview_data *data;
- const char *raw_data;
- long byte_size;
- VALUE string;
-
- TypedData_Get_Struct(self,
- struct memview_data,
- &fiddle_memview_data_type,
- data);
-
- if (NIL_P(data->view.obj)) {
- raw_data = NULL;
- byte_size = 0;
- } else {
- raw_data = data->view.data;
- byte_size = data->view.byte_size;
- }
-
- string = rb_enc_str_new_static(raw_data, byte_size, rb_ascii8bit_encoding());
- {
- ID id_memory_view;
- CONST_ID(id_memory_view, "memory_view");
- rb_ivar_set(string, id_memory_view, self);
- }
- return rb_obj_freeze(string);
-}
-
-void
-Init_fiddle_memory_view(void)
-{
- rb_cMemoryView = rb_define_class_under(mFiddle, "MemoryView", rb_cObject);
- rb_define_alloc_func(rb_cMemoryView, rb_fiddle_memview_s_allocate);
- rb_define_singleton_method(rb_cMemoryView, "export", rb_fiddle_memview_s_export, 1);
- rb_define_method(rb_cMemoryView, "initialize", rb_fiddle_memview_initialize, 1);
- rb_define_method(rb_cMemoryView, "release", rb_fiddle_memview_release, 0);
- rb_define_method(rb_cMemoryView, "obj", rb_fiddle_memview_get_obj, 0);
- rb_define_method(rb_cMemoryView, "byte_size", rb_fiddle_memview_get_byte_size, 0);
- rb_define_method(rb_cMemoryView, "readonly?", rb_fiddle_memview_get_readonly, 0);
- rb_define_method(rb_cMemoryView, "format", rb_fiddle_memview_get_format, 0);
- rb_define_method(rb_cMemoryView, "item_size", rb_fiddle_memview_get_item_size, 0);
- rb_define_method(rb_cMemoryView, "ndim", rb_fiddle_memview_get_ndim, 0);
- rb_define_method(rb_cMemoryView, "shape", rb_fiddle_memview_get_shape, 0);
- rb_define_method(rb_cMemoryView, "strides", rb_fiddle_memview_get_strides, 0);
- rb_define_method(rb_cMemoryView, "sub_offsets", rb_fiddle_memview_get_sub_offsets, 0);
- rb_define_method(rb_cMemoryView, "[]", rb_fiddle_memview_aref, -1);
- rb_define_method(rb_cMemoryView, "to_s", rb_fiddle_memview_to_s, 0);
-}
-
-#endif /* HAVE_RUBY_MEMORY_VIEW_H */
diff --git a/ext/fiddle/pinned.c b/ext/fiddle/pinned.c
deleted file mode 100644
index 019a3020e2..0000000000
--- a/ext/fiddle/pinned.c
+++ /dev/null
@@ -1,123 +0,0 @@
-#include <fiddle.h>
-
-VALUE rb_cPinned;
-VALUE rb_eFiddleClearedReferenceError;
-
-struct pinned_data {
- VALUE ptr;
-};
-
-static void
-pinned_mark(void *ptr)
-{
- struct pinned_data *data = (struct pinned_data*)ptr;
- /* Ensure reference is pinned */
- if (data->ptr) {
- rb_gc_mark(data->ptr);
- }
-}
-
-static size_t
-pinned_memsize(const void *ptr)
-{
- return sizeof(struct pinned_data);
-}
-
-static const rb_data_type_t pinned_data_type = {
- "fiddle/pinned",
- {pinned_mark, xfree, pinned_memsize, },
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
-};
-
-static VALUE
-allocate(VALUE klass)
-{
- struct pinned_data *data;
- VALUE obj = TypedData_Make_Struct(klass, struct pinned_data, &pinned_data_type, data);
- data->ptr = 0;
- return obj;
-}
-
-/*
- * call-seq:
- * Fiddle::Pinned.new(object) => pinned_object
- *
- * Create a new pinned object reference. The Fiddle::Pinned instance will
- * prevent the GC from moving +object+.
- */
-static VALUE
-initialize(VALUE self, VALUE ref)
-{
- struct pinned_data *data;
- TypedData_Get_Struct(self, struct pinned_data, &pinned_data_type, data);
- RB_OBJ_WRITE(self, &data->ptr, ref);
- return self;
-}
-
-/*
- * call-seq: ref
- *
- * Return the object that this pinned instance references.
- */
-static VALUE
-ref(VALUE self)
-{
- struct pinned_data *data;
- TypedData_Get_Struct(self, struct pinned_data, &pinned_data_type, data);
- if (data->ptr) {
- return data->ptr;
- } else {
- rb_raise(rb_eFiddleClearedReferenceError, "`ref` called on a cleared object");
- }
-}
-
-/*
- * call-seq: clear
- *
- * Clear the reference to the object this is pinning.
- */
-static VALUE
-clear(VALUE self)
-{
- struct pinned_data *data;
- TypedData_Get_Struct(self, struct pinned_data, &pinned_data_type, data);
- data->ptr = 0;
- return self;
-}
-
-/*
- * call-seq: cleared?
- *
- * Returns true if the reference has been cleared, otherwise returns false.
- */
-static VALUE
-cleared_p(VALUE self)
-{
- struct pinned_data *data;
- TypedData_Get_Struct(self, struct pinned_data, &pinned_data_type, data);
- if (data->ptr) {
- return Qfalse;
- } else {
- return Qtrue;
- }
-}
-
-extern VALUE rb_eFiddleError;
-
-void
-Init_fiddle_pinned(void)
-{
- rb_cPinned = rb_define_class_under(mFiddle, "Pinned", rb_cObject);
- rb_define_alloc_func(rb_cPinned, allocate);
- rb_define_method(rb_cPinned, "initialize", initialize, 1);
- rb_define_method(rb_cPinned, "ref", ref, 0);
- rb_define_method(rb_cPinned, "clear", clear, 0);
- rb_define_method(rb_cPinned, "cleared?", cleared_p, 0);
-
- /*
- * Document-class: Fiddle::ClearedReferenceError
- *
- * Cleared reference exception
- */
- rb_eFiddleClearedReferenceError = rb_define_class_under(mFiddle, "ClearedReferenceError", rb_eFiddleError);
-}
diff --git a/ext/fiddle/pointer.c b/ext/fiddle/pointer.c
deleted file mode 100644
index 1b7d7a69f6..0000000000
--- a/ext/fiddle/pointer.c
+++ /dev/null
@@ -1,887 +0,0 @@
-/* -*- C -*-
- * $Id$
- */
-
-#include <stdbool.h>
-#include <ruby/ruby.h>
-#include <ruby/io.h>
-
-#include <ctype.h>
-#include <fiddle.h>
-
-#ifdef HAVE_RUBY_MEMORY_VIEW_H
-# include <ruby/memory_view.h>
-#endif
-
-#ifdef PRIsVALUE
-# define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj)
-# define RB_OBJ_STRING(obj) (obj)
-#else
-# define PRIsVALUE "s"
-# define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj)
-# define RB_OBJ_STRING(obj) StringValueCStr(obj)
-#endif
-
-VALUE rb_cPointer;
-
-typedef rb_fiddle_freefunc_t freefunc_t;
-
-struct ptr_data {
- void *ptr;
- long size;
- freefunc_t free;
- bool freed;
- VALUE wrap[2];
-};
-
-#define RPTR_DATA(obj) ((struct ptr_data *)(DATA_PTR(obj)))
-
-static inline freefunc_t
-get_freefunc(VALUE func, volatile VALUE *wrap)
-{
- VALUE addrnum;
- if (NIL_P(func)) {
- *wrap = 0;
- return NULL;
- }
- addrnum = rb_Integer(func);
- *wrap = (addrnum != func) ? func : 0;
- return (freefunc_t)(VALUE)NUM2PTR(addrnum);
-}
-
-static ID id_to_ptr;
-
-static void
-fiddle_ptr_mark(void *ptr)
-{
- struct ptr_data *data = ptr;
- if (data->wrap[0]) {
- rb_gc_mark(data->wrap[0]);
- }
- if (data->wrap[1]) {
- rb_gc_mark(data->wrap[1]);
- }
-}
-
-static void
-fiddle_ptr_free_ptr(void *ptr)
-{
- struct ptr_data *data = ptr;
- if (data->ptr && data->free && !data->freed) {
- data->freed = true;
- (*(data->free))(data->ptr);
- }
-}
-
-static void
-fiddle_ptr_free(void *ptr)
-{
- fiddle_ptr_free_ptr(ptr);
- xfree(ptr);
-}
-
-static size_t
-fiddle_ptr_memsize(const void *ptr)
-{
- const struct ptr_data *data = ptr;
- return sizeof(*data) + data->size;
-}
-
-static const rb_data_type_t fiddle_ptr_data_type = {
- .wrap_struct_name = "fiddle/pointer",
- .function = {
- .dmark = fiddle_ptr_mark,
- .dfree = fiddle_ptr_free,
- .dsize = fiddle_ptr_memsize,
- },
- .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
-};
-
-#ifdef HAVE_RUBY_MEMORY_VIEW_H
-static struct ptr_data *
-fiddle_ptr_check_memory_view(VALUE obj)
-{
- struct ptr_data *data;
- TypedData_Get_Struct(obj, struct ptr_data, &fiddle_ptr_data_type, data);
- if (data->ptr == NULL || data->size == 0) return NULL;
- return data;
-}
-
-static bool
-fiddle_ptr_memory_view_available_p(VALUE obj)
-{
- return fiddle_ptr_check_memory_view(obj) != NULL;
-}
-
-static bool
-fiddle_ptr_get_memory_view(VALUE obj, rb_memory_view_t *view, int flags)
-{
- struct ptr_data *data = fiddle_ptr_check_memory_view(obj);
- rb_memory_view_init_as_byte_array(view, obj, data->ptr, data->size, true);
-
- return true;
-}
-
-static const rb_memory_view_entry_t fiddle_ptr_memory_view_entry = {
- fiddle_ptr_get_memory_view,
- NULL,
- fiddle_ptr_memory_view_available_p
-};
-#endif
-
-static VALUE
-rb_fiddle_ptr_new2(VALUE klass, void *ptr, long size, freefunc_t func, VALUE wrap0, VALUE wrap1)
-{
- struct ptr_data *data;
- VALUE val;
-
- val = TypedData_Make_Struct(klass, struct ptr_data, &fiddle_ptr_data_type, data);
- data->ptr = ptr;
- data->free = func;
- data->freed = false;
- data->size = size;
- RB_OBJ_WRITE(val, &data->wrap[0], wrap0);
- RB_OBJ_WRITE(val, &data->wrap[1], wrap1);
-
- return val;
-}
-
-VALUE
-rb_fiddle_ptr_new_wrap(void *ptr, long size, freefunc_t func, VALUE wrap0, VALUE wrap1)
-{
- return rb_fiddle_ptr_new2(rb_cPointer, ptr, size, func, wrap0, wrap1);
-}
-
-static VALUE
-rb_fiddle_ptr_new(void *ptr, long size, freefunc_t func)
-{
- return rb_fiddle_ptr_new2(rb_cPointer, ptr, size, func, 0, 0);
-}
-
-static VALUE
-rb_fiddle_ptr_malloc(VALUE klass, long size, freefunc_t func)
-{
- void *ptr;
-
- ptr = ruby_xmalloc((size_t)size);
- memset(ptr,0,(size_t)size);
- return rb_fiddle_ptr_new2(klass, ptr, size, func, 0, 0);
-}
-
-static void *
-rb_fiddle_ptr2cptr(VALUE val)
-{
- struct ptr_data *data;
- void *ptr;
-
- if (rb_obj_is_kind_of(val, rb_cPointer)) {
- TypedData_Get_Struct(val, struct ptr_data, &fiddle_ptr_data_type, data);
- ptr = data->ptr;
- }
- else if (val == Qnil) {
- ptr = NULL;
- }
- else{
- rb_raise(rb_eTypeError, "Fiddle::Pointer was expected");
- }
-
- return ptr;
-}
-
-static VALUE
-rb_fiddle_ptr_s_allocate(VALUE klass)
-{
- VALUE obj;
- struct ptr_data *data;
-
- obj = TypedData_Make_Struct(klass, struct ptr_data, &fiddle_ptr_data_type, data);
- data->ptr = 0;
- data->size = 0;
- data->free = 0;
- data->freed = false;
-
- return obj;
-}
-
-/*
- * call-seq:
- * Fiddle::Pointer.new(address) => fiddle_cptr
- * new(address, size) => fiddle_cptr
- * new(address, size, freefunc) => fiddle_cptr
- *
- * Create a new pointer to +address+ with an optional +size+ and +freefunc+.
- *
- * +freefunc+ will be called when the instance is garbage collected.
- */
-static VALUE
-rb_fiddle_ptr_initialize(int argc, VALUE argv[], VALUE self)
-{
- VALUE ptr, sym, size, wrap = 0, funcwrap = 0;
- struct ptr_data *data;
- void *p = NULL;
- freefunc_t f = NULL;
- long s = 0;
-
- if (rb_scan_args(argc, argv, "12", &ptr, &size, &sym) >= 1) {
- VALUE addrnum = rb_Integer(ptr);
- if (addrnum != ptr) wrap = ptr;
- p = NUM2PTR(addrnum);
- }
- if (argc >= 2) {
- s = NUM2LONG(size);
- }
- if (argc >= 3) {
- f = get_freefunc(sym, &funcwrap);
- }
-
- if (p) {
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- if (data->ptr && data->free) {
- /* Free previous memory. Use of inappropriate initialize may cause SEGV. */
- (*(data->free))(data->ptr);
- }
- RB_OBJ_WRITE(self, &data->wrap[0], wrap);
- RB_OBJ_WRITE(self, &data->wrap[1], funcwrap);
- data->ptr = p;
- data->size = s;
- data->free = f;
- }
-
- return Qnil;
-}
-
-static VALUE
-rb_fiddle_ptr_call_free(VALUE self);
-
-/*
- * call-seq:
- * Fiddle::Pointer.malloc(size, freefunc = nil) => fiddle pointer instance
- * Fiddle::Pointer.malloc(size, freefunc) { |pointer| ... } => ...
- *
- * == Examples
- *
- * # Automatically freeing the pointer when the block is exited - recommended
- * Fiddle::Pointer.malloc(size, Fiddle::RUBY_FREE) do |pointer|
- * ...
- * end
- *
- * # Manually freeing but relying on the garbage collector otherwise
- * pointer = Fiddle::Pointer.malloc(size, Fiddle::RUBY_FREE)
- * ...
- * pointer.call_free
- *
- * # Relying on the garbage collector - may lead to unlimited memory allocated before freeing any, but safe
- * pointer = Fiddle::Pointer.malloc(size, Fiddle::RUBY_FREE)
- * ...
- *
- * # Only manually freeing
- * pointer = Fiddle::Pointer.malloc(size)
- * begin
- * ...
- * ensure
- * Fiddle.free pointer
- * end
- *
- * # No free function and no call to free - the native memory will leak if the pointer is garbage collected
- * pointer = Fiddle::Pointer.malloc(size)
- * ...
- *
- * Allocate +size+ bytes of memory and associate it with an optional
- * +freefunc+.
- *
- * If a block is supplied, the pointer will be yielded to the block instead of
- * being returned, and the return value of the block will be returned. A
- * +freefunc+ must be supplied if a block is.
- *
- * If a +freefunc+ is supplied it will be called once, when the pointer is
- * garbage collected or when the block is left if a block is supplied or
- * when the user calls +call_free+, whichever happens first. +freefunc+ must be
- * an address pointing to a function or an instance of +Fiddle::Function+.
- */
-static VALUE
-rb_fiddle_ptr_s_malloc(int argc, VALUE argv[], VALUE klass)
-{
- VALUE size, sym, obj, wrap = 0;
- long s;
- freefunc_t f;
-
- switch (rb_scan_args(argc, argv, "11", &size, &sym)) {
- case 1:
- s = NUM2LONG(size);
- f = NULL;
- break;
- case 2:
- s = NUM2LONG(size);
- f = get_freefunc(sym, &wrap);
- break;
- default:
- rb_bug("rb_fiddle_ptr_s_malloc");
- }
-
- obj = rb_fiddle_ptr_malloc(klass, s,f);
- if (wrap) RB_OBJ_WRITE(obj, &RPTR_DATA(obj)->wrap[1], wrap);
-
- if (rb_block_given_p()) {
- if (!f) {
- rb_raise(rb_eArgError, "a free function must be supplied to Fiddle::Pointer.malloc when it is called with a block");
- }
- return rb_ensure(rb_yield, obj, rb_fiddle_ptr_call_free, obj);
- } else {
- return obj;
- }
-}
-
-/*
- * call-seq: to_i
- *
- * Returns the integer memory location of this pointer.
- */
-static VALUE
-rb_fiddle_ptr_to_i(VALUE self)
-{
- struct ptr_data *data;
-
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- return PTR2NUM(data->ptr);
-}
-
-/*
- * call-seq: to_value
- *
- * Cast this pointer to a ruby object.
- */
-static VALUE
-rb_fiddle_ptr_to_value(VALUE self)
-{
- struct ptr_data *data;
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- return (VALUE)(data->ptr);
-}
-
-/*
- * call-seq: ptr
- *
- * Returns a new Fiddle::Pointer instance that is a dereferenced pointer for
- * this pointer.
- *
- * Analogous to the star operator in C.
- */
-static VALUE
-rb_fiddle_ptr_ptr(VALUE self)
-{
- struct ptr_data *data;
-
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- return rb_fiddle_ptr_new(*((void**)(data->ptr)),0,0);
-}
-
-/*
- * call-seq: ref
- *
- * Returns a new Fiddle::Pointer instance that is a reference pointer for this
- * pointer.
- *
- * Analogous to the ampersand operator in C.
- */
-static VALUE
-rb_fiddle_ptr_ref(VALUE self)
-{
- struct ptr_data *data;
-
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- return rb_fiddle_ptr_new(&(data->ptr),0,0);
-}
-
-/*
- * call-seq: null?
- *
- * Returns +true+ if this is a null pointer.
- */
-static VALUE
-rb_fiddle_ptr_null_p(VALUE self)
-{
- struct ptr_data *data;
-
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- return data->ptr ? Qfalse : Qtrue;
-}
-
-/*
- * call-seq: free=(function)
- *
- * Set the free function for this pointer to +function+ in the given
- * Fiddle::Function.
- */
-static VALUE
-rb_fiddle_ptr_free_set(VALUE self, VALUE val)
-{
- struct ptr_data *data;
-
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- data->free = get_freefunc(val, &data->wrap[1]);
-
- return Qnil;
-}
-
-/*
- * call-seq: free => Fiddle::Function
- *
- * Get the free function for this pointer.
- *
- * Returns a new instance of Fiddle::Function.
- *
- * See Fiddle::Function.new
- */
-static VALUE
-rb_fiddle_ptr_free_get(VALUE self)
-{
- struct ptr_data *pdata;
- VALUE address;
- VALUE arg_types;
- VALUE ret_type;
-
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, pdata);
-
- if (!pdata->free)
- return Qnil;
-
- address = PTR2NUM(pdata->free);
- ret_type = INT2NUM(TYPE_VOID);
- arg_types = rb_ary_new();
- rb_ary_push(arg_types, INT2NUM(TYPE_VOIDP));
-
- return rb_fiddle_new_function(address, arg_types, ret_type);
-}
-
-/*
- * call-seq: call_free => nil
- *
- * Call the free function for this pointer. Calling more than once will do
- * nothing. Does nothing if there is no free function attached.
- */
-static VALUE
-rb_fiddle_ptr_call_free(VALUE self)
-{
- struct ptr_data *pdata;
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, pdata);
- fiddle_ptr_free_ptr(pdata);
- return Qnil;
-}
-
-/*
- * call-seq: freed? => bool
- *
- * Returns if the free function for this pointer has been called.
- */
-static VALUE
-rb_fiddle_ptr_freed_p(VALUE self)
-{
- struct ptr_data *pdata;
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, pdata);
- return pdata->freed ? Qtrue : Qfalse;
-}
-
-/*
- * call-seq:
- *
- * ptr.to_s => string
- * ptr.to_s(len) => string
- *
- * Returns the pointer contents as a string.
- *
- * When called with no arguments, this method will return the contents until
- * the first NULL byte.
- *
- * When called with +len+, a string of +len+ bytes will be returned.
- *
- * See to_str
- */
-static VALUE
-rb_fiddle_ptr_to_s(int argc, VALUE argv[], VALUE self)
-{
- struct ptr_data *data;
- VALUE arg1, val;
- int len;
-
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- switch (rb_scan_args(argc, argv, "01", &arg1)) {
- case 0:
- val = rb_str_new2((char*)(data->ptr));
- break;
- case 1:
- len = NUM2INT(arg1);
- val = rb_str_new((char*)(data->ptr), len);
- break;
- default:
- rb_bug("rb_fiddle_ptr_to_s");
- }
-
- return val;
-}
-
-/*
- * call-seq:
- *
- * ptr.to_str => string
- * ptr.to_str(len) => string
- *
- * Returns the pointer contents as a string.
- *
- * When called with no arguments, this method will return the contents with the
- * length of this pointer's +size+.
- *
- * When called with +len+, a string of +len+ bytes will be returned.
- *
- * See to_s
- */
-static VALUE
-rb_fiddle_ptr_to_str(int argc, VALUE argv[], VALUE self)
-{
- struct ptr_data *data;
- VALUE arg1, val;
- int len;
-
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- switch (rb_scan_args(argc, argv, "01", &arg1)) {
- case 0:
- val = rb_str_new((char*)(data->ptr),data->size);
- break;
- case 1:
- len = NUM2INT(arg1);
- val = rb_str_new((char*)(data->ptr), len);
- break;
- default:
- rb_bug("rb_fiddle_ptr_to_str");
- }
-
- return val;
-}
-
-/*
- * call-seq: inspect
- *
- * Returns a string formatted with an easily readable representation of the
- * internal state of the pointer.
- */
-static VALUE
-rb_fiddle_ptr_inspect(VALUE self)
-{
- struct ptr_data *data;
-
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- return rb_sprintf("#<%"PRIsVALUE":%p ptr=%p size=%ld free=%p>",
- RB_OBJ_CLASSNAME(self), (void *)data, data->ptr, data->size, (void *)data->free);
-}
-
-/*
- * call-seq:
- * ptr == other => true or false
- * ptr.eql?(other) => true or false
- *
- * Returns true if +other+ wraps the same pointer, otherwise returns
- * false.
- */
-static VALUE
-rb_fiddle_ptr_eql(VALUE self, VALUE other)
-{
- void *ptr1, *ptr2;
-
- if(!rb_obj_is_kind_of(other, rb_cPointer)) return Qfalse;
-
- ptr1 = rb_fiddle_ptr2cptr(self);
- ptr2 = rb_fiddle_ptr2cptr(other);
-
- return ptr1 == ptr2 ? Qtrue : Qfalse;
-}
-
-/*
- * call-seq:
- * ptr <=> other => -1, 0, 1, or nil
- *
- * Returns -1 if less than, 0 if equal to, 1 if greater than +other+.
- *
- * Returns nil if +ptr+ cannot be compared to +other+.
- */
-static VALUE
-rb_fiddle_ptr_cmp(VALUE self, VALUE other)
-{
- void *ptr1, *ptr2;
- SIGNED_VALUE diff;
-
- if(!rb_obj_is_kind_of(other, rb_cPointer)) return Qnil;
-
- ptr1 = rb_fiddle_ptr2cptr(self);
- ptr2 = rb_fiddle_ptr2cptr(other);
- diff = (SIGNED_VALUE)ptr1 - (SIGNED_VALUE)ptr2;
- if (!diff) return INT2FIX(0);
- return diff > 0 ? INT2NUM(1) : INT2NUM(-1);
-}
-
-/*
- * call-seq:
- * ptr + n => new cptr
- *
- * Returns a new pointer instance that has been advanced +n+ bytes.
- */
-static VALUE
-rb_fiddle_ptr_plus(VALUE self, VALUE other)
-{
- void *ptr;
- long num, size;
-
- ptr = rb_fiddle_ptr2cptr(self);
- size = RPTR_DATA(self)->size;
- num = NUM2LONG(other);
- return rb_fiddle_ptr_new((char *)ptr + num, size - num, 0);
-}
-
-/*
- * call-seq:
- * ptr - n => new cptr
- *
- * Returns a new pointer instance that has been moved back +n+ bytes.
- */
-static VALUE
-rb_fiddle_ptr_minus(VALUE self, VALUE other)
-{
- void *ptr;
- long num, size;
-
- ptr = rb_fiddle_ptr2cptr(self);
- size = RPTR_DATA(self)->size;
- num = NUM2LONG(other);
- return rb_fiddle_ptr_new((char *)ptr - num, size + num, 0);
-}
-
-/*
- * call-seq:
- * ptr[index] -> an_integer
- * ptr[start, length] -> a_string
- *
- * Returns integer stored at _index_.
- *
- * If _start_ and _length_ are given, a string containing the bytes from
- * _start_ of _length_ will be returned.
- */
-static VALUE
-rb_fiddle_ptr_aref(int argc, VALUE argv[], VALUE self)
-{
- VALUE arg0, arg1;
- VALUE retval = Qnil;
- size_t offset, len;
- struct ptr_data *data;
-
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- if (!data->ptr) rb_raise(rb_eFiddleDLError, "NULL pointer dereference");
- switch( rb_scan_args(argc, argv, "11", &arg0, &arg1) ){
- case 1:
- offset = NUM2ULONG(arg0);
- retval = INT2NUM(*((char *)data->ptr + offset));
- break;
- case 2:
- offset = NUM2ULONG(arg0);
- len = NUM2ULONG(arg1);
- retval = rb_str_new((char *)data->ptr + offset, len);
- break;
- default:
- rb_bug("rb_fiddle_ptr_aref()");
- }
- return retval;
-}
-
-/*
- * call-seq:
- * ptr[index] = int -> int
- * ptr[start, length] = string or cptr or addr -> string or dl_cptr or addr
- *
- * Set the value at +index+ to +int+.
- *
- * Or, set the memory at +start+ until +length+ with the contents of +string+,
- * the memory from +dl_cptr+, or the memory pointed at by the memory address
- * +addr+.
- */
-static VALUE
-rb_fiddle_ptr_aset(int argc, VALUE argv[], VALUE self)
-{
- VALUE arg0, arg1, arg2;
- VALUE retval = Qnil;
- size_t offset, len;
- void *mem;
- struct ptr_data *data;
-
- TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data);
- if (!data->ptr) rb_raise(rb_eFiddleDLError, "NULL pointer dereference");
- switch( rb_scan_args(argc, argv, "21", &arg0, &arg1, &arg2) ){
- case 2:
- offset = NUM2ULONG(arg0);
- ((char*)data->ptr)[offset] = NUM2UINT(arg1);
- retval = arg1;
- break;
- case 3:
- offset = NUM2ULONG(arg0);
- len = NUM2ULONG(arg1);
- if (RB_TYPE_P(arg2, T_STRING)) {
- mem = StringValuePtr(arg2);
- }
- else if( rb_obj_is_kind_of(arg2, rb_cPointer) ){
- mem = rb_fiddle_ptr2cptr(arg2);
- }
- else{
- mem = NUM2PTR(arg2);
- }
- memcpy((char *)data->ptr + offset, mem, len);
- retval = arg2;
- break;
- default:
- rb_bug("rb_fiddle_ptr_aset()");
- }
- return retval;
-}
-
-/*
- * call-seq: size=(size)
- *
- * Set the size of this pointer to +size+
- */
-static VALUE
-rb_fiddle_ptr_size_set(VALUE self, VALUE size)
-{
- RPTR_DATA(self)->size = NUM2LONG(size);
- return size;
-}
-
-/*
- * call-seq: size
- *
- * Get the size of this pointer.
- */
-static VALUE
-rb_fiddle_ptr_size_get(VALUE self)
-{
- return LONG2NUM(RPTR_DATA(self)->size);
-}
-
-/*
- * call-seq:
- * Fiddle::Pointer[val] => cptr
- * to_ptr(val) => cptr
- *
- * Get the underlying pointer for ruby object +val+ and return it as a
- * Fiddle::Pointer object.
- */
-static VALUE
-rb_fiddle_ptr_s_to_ptr(VALUE self, VALUE val)
-{
- VALUE ptr, wrap = val, vptr;
-
- if (RTEST(rb_obj_is_kind_of(val, rb_cIO))){
- rb_io_t *fptr;
- FILE *fp;
- GetOpenFile(val, fptr);
- fp = rb_io_stdio_file(fptr);
- ptr = rb_fiddle_ptr_new(fp, 0, NULL);
- }
- else if (RTEST(rb_obj_is_kind_of(val, rb_cString))){
- char *str = StringValuePtr(val);
- wrap = val;
- ptr = rb_fiddle_ptr_new(str, RSTRING_LEN(val), NULL);
- }
- else if ((vptr = rb_check_funcall(val, id_to_ptr, 0, 0)) != Qundef){
- if (rb_obj_is_kind_of(vptr, rb_cPointer)){
- ptr = vptr;
- wrap = 0;
- }
- else{
- rb_raise(rb_eFiddleDLError, "to_ptr should return a Fiddle::Pointer object");
- }
- }
- else{
- VALUE num = rb_Integer(val);
- if (num == val) wrap = 0;
- ptr = rb_fiddle_ptr_new(NUM2PTR(num), 0, NULL);
- }
- if (wrap) RB_OBJ_WRITE(ptr, &RPTR_DATA(ptr)->wrap[0], wrap);
- return ptr;
-}
-
-/*
- * call-seq:
- * Fiddle::Pointer.read(address, len) => string
- *
- * Or read the memory at address +address+ with length +len+ and return a
- * string with that memory
- */
-
-static VALUE
-rb_fiddle_ptr_read_mem(VALUE klass, VALUE address, VALUE len)
-{
- return rb_str_new((char *)NUM2PTR(address), NUM2ULONG(len));
-}
-
-/*
- * call-seq:
- * Fiddle::Pointer.write(address, str)
- *
- * Write bytes in +str+ to the location pointed to by +address+.
- */
-static VALUE
-rb_fiddle_ptr_write_mem(VALUE klass, VALUE addr, VALUE str)
-{
- memcpy(NUM2PTR(addr), StringValuePtr(str), RSTRING_LEN(str));
- return str;
-}
-
-void
-Init_fiddle_pointer(void)
-{
-#undef rb_intern
- id_to_ptr = rb_intern("to_ptr");
-
- /* Document-class: Fiddle::Pointer
- *
- * Fiddle::Pointer is a class to handle C pointers
- *
- */
- rb_cPointer = rb_define_class_under(mFiddle, "Pointer", rb_cObject);
- rb_define_alloc_func(rb_cPointer, rb_fiddle_ptr_s_allocate);
- rb_define_singleton_method(rb_cPointer, "malloc", rb_fiddle_ptr_s_malloc, -1);
- rb_define_singleton_method(rb_cPointer, "to_ptr", rb_fiddle_ptr_s_to_ptr, 1);
- rb_define_singleton_method(rb_cPointer, "[]", rb_fiddle_ptr_s_to_ptr, 1);
- rb_define_singleton_method(rb_cPointer, "read", rb_fiddle_ptr_read_mem, 2);
- rb_define_singleton_method(rb_cPointer, "write", rb_fiddle_ptr_write_mem, 2);
- rb_define_method(rb_cPointer, "initialize", rb_fiddle_ptr_initialize, -1);
- rb_define_method(rb_cPointer, "free=", rb_fiddle_ptr_free_set, 1);
- rb_define_method(rb_cPointer, "free", rb_fiddle_ptr_free_get, 0);
- rb_define_method(rb_cPointer, "call_free", rb_fiddle_ptr_call_free, 0);
- rb_define_method(rb_cPointer, "freed?", rb_fiddle_ptr_freed_p, 0);
- rb_define_method(rb_cPointer, "to_i", rb_fiddle_ptr_to_i, 0);
- rb_define_method(rb_cPointer, "to_int", rb_fiddle_ptr_to_i, 0);
- rb_define_method(rb_cPointer, "to_value", rb_fiddle_ptr_to_value, 0);
- rb_define_method(rb_cPointer, "ptr", rb_fiddle_ptr_ptr, 0);
- rb_define_method(rb_cPointer, "+@", rb_fiddle_ptr_ptr, 0);
- rb_define_method(rb_cPointer, "ref", rb_fiddle_ptr_ref, 0);
- rb_define_method(rb_cPointer, "-@", rb_fiddle_ptr_ref, 0);
- rb_define_method(rb_cPointer, "null?", rb_fiddle_ptr_null_p, 0);
- rb_define_method(rb_cPointer, "to_s", rb_fiddle_ptr_to_s, -1);
- rb_define_method(rb_cPointer, "to_str", rb_fiddle_ptr_to_str, -1);
- rb_define_method(rb_cPointer, "inspect", rb_fiddle_ptr_inspect, 0);
- rb_define_method(rb_cPointer, "<=>", rb_fiddle_ptr_cmp, 1);
- rb_define_method(rb_cPointer, "==", rb_fiddle_ptr_eql, 1);
- rb_define_method(rb_cPointer, "eql?", rb_fiddle_ptr_eql, 1);
- rb_define_method(rb_cPointer, "+", rb_fiddle_ptr_plus, 1);
- rb_define_method(rb_cPointer, "-", rb_fiddle_ptr_minus, 1);
- rb_define_method(rb_cPointer, "[]", rb_fiddle_ptr_aref, -1);
- rb_define_method(rb_cPointer, "[]=", rb_fiddle_ptr_aset, -1);
- rb_define_method(rb_cPointer, "size", rb_fiddle_ptr_size_get, 0);
- rb_define_method(rb_cPointer, "size=", rb_fiddle_ptr_size_set, 1);
-
-#ifdef HAVE_RUBY_MEMORY_VIEW_H
- rb_memory_view_register(rb_cPointer, &fiddle_ptr_memory_view_entry);
-#endif
-
- /* Document-const: NULL
- *
- * A NULL pointer
- */
- rb_define_const(mFiddle, "NULL", rb_fiddle_ptr_new(0, 0, 0));
-}
diff --git a/ext/fiddle/win32/fficonfig.h b/ext/fiddle/win32/fficonfig.h
deleted file mode 100644
index 776808159c..0000000000
--- a/ext/fiddle/win32/fficonfig.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#define HAVE_ALLOCA 1
-#define HAVE_MEMCPY 1
-#define HAVE_MEMORY_H 1
-#define HAVE_STDLIB_H 1
-#define HAVE_STRING_H 1
-#define HAVE_SYS_STAT_H 1
-#define HAVE_SYS_TYPES_H 1
-#if _MSC_VER >= 1600
-#define HAVE_INTTYPES_H 1
-#define HAVE_STDINT_H 1
-#endif
-
-#define SIZEOF_DOUBLE 8
-#if defined(X86_WIN64)
-#define SIZEOF_SIZE_T 8
-#else
-#define SIZEOF_SIZE_T 4
-#endif
-
-#define STACK_DIRECTION -1
-
-#define STDC_HEADERS 1
-
-#ifdef LIBFFI_ASM
-#define FFI_HIDDEN(name)
-#else
-#define FFI_HIDDEN
-#endif
-
diff --git a/ext/fiddle/win32/libffi-3.2.1-mswin.patch b/ext/fiddle/win32/libffi-3.2.1-mswin.patch
deleted file mode 100644
index f9100e703d..0000000000
--- a/ext/fiddle/win32/libffi-3.2.1-mswin.patch
+++ /dev/null
@@ -1,191 +0,0 @@
-diff -ru libffi-3.2.1/src/x86/ffi.c libffi-3.2.1/src/x86/ffi.c
---- libffi-3.2.1/src/x86/ffi.c 2014-11-08 21:47:24.000000000 +0900
-+++ libffi-3.2.1/src/x86/ffi.c 2014-12-25 18:46:14.806761900 +0900
-@@ -99,11 +99,13 @@
- i != 0;
- i--, p_arg += dir, p_argv += dir)
- {
-+ size_t z;
-+
- /* Align if necessary */
- if ((sizeof(void*) - 1) & (size_t) argp)
- argp = (char *) ALIGN(argp, sizeof(void*));
-
-- size_t z = (*p_arg)->size;
-+ z = (*p_arg)->size;
-
- #ifdef X86_WIN64
- if (z > FFI_SIZEOF_ARG
-@@ -202,6 +204,7 @@
- on top of stack, so that those can be moved to registers by call-handler. */
- if (stack_args_count > 0)
- {
-+ int i;
- if (dir < 0 && stack_args_count > 1)
- {
- /* Reverse order if iterating arguments backwards */
-@@ -210,7 +213,6 @@
- *(ffi_arg*) p_stack_data[stack_args_count - 1] = tmp;
- }
-
-- int i;
- for (i = 0; i < stack_args_count; i++)
- {
- if (p_stack_data[i] != argp2)
-@@ -569,11 +571,12 @@
- i < cif->nargs && passed_regs < max_stack_count;
- i++, p_arg++)
- {
-+ size_t sz;
- if ((*p_arg)->type == FFI_TYPE_FLOAT
- || (*p_arg)->type == FFI_TYPE_STRUCT)
- continue;
-
-- size_t sz = (*p_arg)->size;
-+ sz = (*p_arg)->size;
- if(sz == 0 || sz > FFI_SIZEOF_ARG)
- continue;
-
-@@ -599,11 +602,13 @@
- i != 0;
- i--, p_arg += dir, p_argv += dir)
- {
-+ size_t z;
-+
- /* Align if necessary */
- if ((sizeof(void*) - 1) & (size_t) argp)
- argp = (char *) ALIGN(argp, sizeof(void*));
-
-- size_t z = (*p_arg)->size;
-+ z = (*p_arg)->size;
-
- #ifdef X86_WIN64
- if (z > FFI_SIZEOF_ARG
-@@ -642,7 +647,7 @@
- #endif
- }
-
-- return (size_t)argp - (size_t)stack;
-+ return (int)((size_t)argp - (size_t)stack);
- }
-
- #define FFI_INIT_TRAMPOLINE_WIN64(TRAMP,FUN,CTX,MASK) \
-@@ -855,11 +860,12 @@
-
- for (i = 0; i < cif->nargs && passed_regs <= max_regs; i++)
- {
-+ size_t sz;
- if (cif->arg_types[i]->type == FFI_TYPE_FLOAT
- || cif->arg_types[i]->type == FFI_TYPE_STRUCT)
- continue;
-
-- size_t sz = cif->arg_types[i]->size;
-+ sz = cif->arg_types[i]->size;
- if (sz == 0 || sz > FFI_SIZEOF_ARG)
- continue;
-
-diff -ru libffi-3.2.1/src/x86/ffitarget.h libffi-3.2.1/src/x86/ffitarget.h
---- libffi-3.2.1/src/x86/ffitarget.h 2014-11-08 21:47:24.000000000 +0900
-+++ libffi-3.2.1/src/x86/ffitarget.h 2014-12-22 15:45:54.000000000 +0900
-@@ -50,7 +50,9 @@
- #endif
-
- #define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION
-+#ifndef _MSC_VER
- #define FFI_TARGET_HAS_COMPLEX_TYPE
-+#endif
-
- /* ---- Generic type definitions ----------------------------------------- */
-
-diff -ru libffi-3.2.1/src/x86/win64.S libffi-3.2.1/src/x86/win64.S
---- libffi-3.2.1/src/x86/win64.S 2014-11-08 21:47:24.000000000 +0900
-+++ libffi-3.2.1/src/x86/win64.S 2014-12-22 16:14:40.000000000 +0900
-@@ -127,7 +127,7 @@
-
- mov rcx, QWORD PTR RVALUE[rbp]
- mov DWORD PTR [rcx], eax
-- jmp ret_void$
-+ jmp SHORT ret_void$
-
- ret_struct2b$:
- cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_2B
-@@ -135,7 +135,7 @@
-
- mov rcx, QWORD PTR RVALUE[rbp]
- mov WORD PTR [rcx], ax
-- jmp ret_void$
-+ jmp SHORT ret_void$
-
- ret_struct1b$:
- cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_1B
-@@ -143,7 +143,7 @@
-
- mov rcx, QWORD PTR RVALUE[rbp]
- mov BYTE PTR [rcx], al
-- jmp ret_void$
-+ jmp SHORT ret_void$
-
- ret_uint8$:
- cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT8
-@@ -152,7 +152,7 @@
- mov rcx, QWORD PTR RVALUE[rbp]
- movzx rax, al
- mov QWORD PTR [rcx], rax
-- jmp ret_void$
-+ jmp SHORT ret_void$
-
- ret_sint8$:
- cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT8
-@@ -161,7 +161,7 @@
- mov rcx, QWORD PTR RVALUE[rbp]
- movsx rax, al
- mov QWORD PTR [rcx], rax
-- jmp ret_void$
-+ jmp SHORT ret_void$
-
- ret_uint16$:
- cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT16
-@@ -188,7 +188,13 @@
- mov rcx, QWORD PTR RVALUE[rbp]
- mov eax, eax
- mov QWORD PTR [rcx], rax
-- jmp SHORT ret_void$
-+
-+ret_void$:
-+ xor rax, rax
-+
-+ lea rsp, QWORD PTR [rbp+16]
-+ pop rbp
-+ ret 0
-
- ret_sint32$:
- cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT32
-@@ -247,13 +253,6 @@
- cdqe
- mov QWORD PTR [rcx], rax
- jmp SHORT ret_void$
--
--ret_void$:
-- xor rax, rax
--
-- lea rsp, QWORD PTR [rbp+16]
-- pop rbp
-- ret 0
- ffi_call_win64 ENDP
- _TEXT ENDS
- END
-diff -ru libffi-3.2.1/include/ffi.h.in libffi-3.2.1/include/ffi.h.in
---- libffi-3.2.1/include/ffi.h.in 2014-11-08 21:47:24.000000000 +0900
-+++ libffi-3.2.1/include/ffi.h.in 2015-01-11 12:35:30.000000000 +0900
-@@ -103,6 +103,11 @@
- # undef FFI_64_BIT_MAX
- # define FFI_64_BIT_MAX 9223372036854775807LL
- # endif
-+# ifdef _MSC_VER
-+# define FFI_LONG_LONG_MAX _I64_MAX
-+# undef FFI_64_BIT_MAX
-+# define FFI_64_BIT_MAX 9223372036854775807I64
-+# endif
- # endif
- #endif
-
diff --git a/ext/fiddle/win32/libffi-config.rb b/ext/fiddle/win32/libffi-config.rb
deleted file mode 100755
index 8e8069a943..0000000000
--- a/ext/fiddle/win32/libffi-config.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/ruby
-# frozen_string_literal: true
-require 'fileutils'
-
-basedir = File.dirname(__FILE__)
-conf = {}
-enable = {}
-until ARGV.empty?
- arg = ARGV.shift
- case arg
- when '-C'
- # ignore
- when /\A--srcdir=(.*)/
- conf['SRCDIR'] = srcdir = $1
- when /\A(CC|CFLAGS|CXX|CXXFLAGS|LD|LDFLAGS)=(.*)/
- conf[$1] = $2
- when /\A--host=(.*)/
- host = $1
- when /\A--enable-([^=]+)(?:=(.*))?/
- enable[$1] = $2 || true
- when /\A--disable-([^=]+)/
- enable[$1] = false
- end
-end
-
-File.foreach("#{srcdir}/configure.ac") do |line|
- if /^AC_INIT\((.*)\)/ =~ line
- version = $1.split(/,\s*/)[1]
- version.gsub!(/\A\[|\]\z/, '')
- conf['VERSION'] = version
- break
- end
-end
-
-builddir = srcdir == "." ? (enable['builddir'] || ".") : "."
-conf['TARGET'] = /^x64/ =~ host ? "X86_WIN64" : "X86_WIN32"
-
-FileUtils.mkdir_p([builddir, "#{builddir}/include", "#{builddir}/src/x86"])
-FileUtils.cp("#{basedir}/fficonfig.h", ".", preserve: true)
-
-hdr = File.binread("#{srcdir}/include/ffi.h.in")
-hdr.gsub!(/@(\w+)@/) {conf[$1] || $&}
-hdr.gsub!(/^(#if\s+)@\w+@/, '\10')
-File.binwrite("#{builddir}/include/ffi.h", hdr)
-
-mk = File.binread("#{basedir}/libffi.mk.tmpl")
-mk.gsub!(/@(\w+)@/) {conf[$1] || $&}
-File.binwrite("Makefile", mk)
diff --git a/ext/fiddle/win32/libffi.mk.tmpl b/ext/fiddle/win32/libffi.mk.tmpl
deleted file mode 100644
index 2a16e8efec..0000000000
--- a/ext/fiddle/win32/libffi.mk.tmpl
+++ /dev/null
@@ -1,96 +0,0 @@
-# -*- makefile -*-
-# ====================================================================
-#
-# libffi Windows Makefile
-#
-#
-# ====================================================================
-#
-NAME = ffi
-TARGET = @TARGET@
-CC = cl
-!if "$(TARGET)" == "X86_WIN64"
-AS = ml64
-!else
-AS = ml
-!endif
-AR = link
-DLEXT = dll
-OBJEXT = obj
-LIBEXT = lib
-TOPDIR = @SRCDIR@
-CPP = $(CC) -EP
-CFLAGS = @CFLAGS@
-ARFLAGS = -lib
-ASFLAGS = -coff -W3 -Cx
-INCLUDES= -I. -I./include -I./src/x86 \
- -I$(TOPDIR)/include -I$(TOPDIR)/include/src/x86
-
-SRCDIR = $(TOPDIR)/src
-WORKDIR = ./.libs
-BUILDDIR= ./src
-LIBNAME = lib$(NAME)
-STATICLIB= $(WORKDIR)/$(LIBNAME)_convenience.$(LIBEXT)
-
-HEADERS = \
- ./fficonfig.h
-FFI_HEADERS = \
- ./include/ffi.h \
- ./include/ffitarget.h
-
-!if "$(TARGET)" == "X86_WIN32"
-OSSRC = win32
-!else if "$(TARGET)" == "X86_WIN64"
-OSSRC = win64
-!else
-! error unknown target: $(TARGET)
-!endif
-
-OBJECTS = \
- $(BUILDDIR)/closures.$(OBJEXT) \
- $(BUILDDIR)/debug.$(OBJEXT) \
- $(BUILDDIR)/java_raw_api.$(OBJEXT) \
- $(BUILDDIR)/prep_cif.$(OBJEXT) \
- $(BUILDDIR)/raw_api.$(OBJEXT) \
- $(BUILDDIR)/types.$(OBJEXT) \
- $(BUILDDIR)/x86/ffi.$(OBJEXT) \
- $(BUILDDIR)/x86/$(OSSRC).$(OBJEXT)
-ASMSRCS = \
- $(BUILDDIR)/x86/$(OSSRC).asm
-
-.SUFFIXES : .S .asm
-
-all: $(WORKDIR) $(STATICLIB)
-
-{$(SRCDIR)}.c{$(BUILDDIR)}.$(OBJEXT):
- $(CC) -c $(CFLAGS) $(INCLUDES) -Fo$(@:\=/) -Fd$(WORKDIR)/$(NAME)-src $(<:\=/)
-
-{$(SRCDIR)/x86}.c{$(BUILDDIR)/x86}.$(OBJEXT):
- $(CC) -c $(CFLAGS) $(INCLUDES) -Fo$(@:\=/) -Fd$(WORKDIR)/$(NAME)-src $(<:\=/)
-
-{$(SRCDIR)/x86}.S{$(BUILDDIR)/x86}.asm:
- $(CPP) $(CFLAGS) $(INCLUDES) $(<:\=/) >$(@:\=/)
-
-{$(BUILDDIR)/x86}.asm{$(BUILDDIR)/x86}.$(OBJEXT):
- cd $(@D) && $(AS) -c $(ASFLAGS) -Fo $(@F) $(<F)
-
-$(BUILDDIR)/x86/$(OSSRC).asm: $(SRCDIR)/x86/$(OSSRC).S
-
-$(OBJECTS): $(FFI_HEADERS) $(HEADERS)
-
-$(WORKDIR):
- -@if not exist "$(WORKDIR:/=\)\$(NULL)" mkdir $(WORKDIR:/=\)
-
-$(STATICLIB): $(WORKDIR) $(OBJECTS)
- $(AR) $(ARFLAGS) -out:$(STATICLIB) @<<
- $(OBJECTS)
-<<
-
-clean:
- -@del /Q $(OBJECTS:/=\) 2>NUL
- -@del /Q $(ASMSRCS:/=\) 2>NUL
- -@del /Q /S $(WORKDIR:/=\) 2>NUL
-
-distclean: clean
- -@del /Q $(HEADERS:/=\) $(FFI_HEADERS:/=\) 2>NUL
- -@del /Q Makefile 2>NUL
diff --git a/ext/io/console/console.c b/ext/io/console/console.c
index 7130c29a8b..7ddaf071a8 100644
--- a/ext/io/console/console.c
+++ b/ext/io/console/console.c
@@ -4,7 +4,7 @@
*/
static const char *const
-IO_CONSOLE_VERSION = "0.7.2";
+IO_CONSOLE_VERSION = "0.8.2";
#include "ruby.h"
#include "ruby/io.h"
@@ -81,9 +81,14 @@ getattr(int fd, conmode *t)
#define CSI "\x1b\x5b"
-static ID id_getc, id_console, id_close;
+static ID id_getc, id_close;
static ID id_gets, id_flush, id_chomp_bang;
+#ifndef HAVE_RB_INTERNED_STR_CSTR
+# define rb_str_to_interned_str(str) rb_str_freeze(str)
+# define rb_interned_str_cstr(str) rb_str_freeze(rb_usascii_str_new_cstr(str))
+#endif
+
#if defined HAVE_RUBY_FIBER_SCHEDULER_H
# include "ruby/fiber/scheduler.h"
#elif defined HAVE_RB_SCHEDULER_TIMEOUT
@@ -125,7 +130,14 @@ io_get_write_io_fallback(VALUE io)
#define rb_io_get_write_io io_get_write_io_fallback
#endif
-#define sys_fail(io) rb_sys_fail_str(rb_io_path(io))
+#ifndef DHAVE_RB_SYSERR_FAIL_STR
+# define rb_syserr_fail_str(e, mesg) rb_exc_raise(rb_syserr_new_str(e, mesg))
+#endif
+
+#define sys_fail(io) do { \
+ int err = errno; \
+ rb_syserr_fail_str(err, rb_io_path(io)); \
+} while (0)
#ifndef HAVE_RB_F_SEND
#ifndef RB_PASS_CALLED_KEYWORDS
@@ -828,6 +840,9 @@ console_winsize(VALUE io)
return rb_assoc_new(INT2NUM(winsize_row(&ws)), INT2NUM(winsize_col(&ws)));
}
+static VALUE console_scroll(VALUE io, int line);
+static VALUE console_goto(VALUE io, VALUE y, VALUE x);
+
/*
* call-seq:
* io.winsize = [rows, columns]
@@ -844,6 +859,8 @@ console_set_winsize(VALUE io, VALUE size)
#if defined _WIN32
HANDLE wh;
int newrow, newcol;
+ COORD oldsize;
+ SMALL_RECT oldwindow;
BOOL ret;
#endif
VALUE row, col, xpixel, ypixel;
@@ -879,18 +896,62 @@ console_set_winsize(VALUE io, VALUE size)
if (!GetConsoleScreenBufferInfo(wh, &ws)) {
rb_syserr_fail(LAST_ERROR, "GetConsoleScreenBufferInfo");
}
+ oldsize = ws.dwSize;
+ oldwindow = ws.srWindow;
+ if (ws.srWindow.Right + 1 < newcol) {
+ ws.dwSize.X = newcol;
+ }
+ if (ws.dwSize.Y < newrow) {
+ ws.dwSize.Y = newrow;
+ }
+ /* expand screen buffer first if needed */
+ if (!SetConsoleScreenBufferSize(wh, ws.dwSize)) {
+ rb_syserr_fail(LAST_ERROR, "SetConsoleScreenBufferInfo");
+ }
+ /* refresh ws for new dwMaximumWindowSize */
+ if (!GetConsoleScreenBufferInfo(wh, &ws)) {
+ rb_syserr_fail(LAST_ERROR, "GetConsoleScreenBufferInfo");
+ }
+ /* check new size before modifying buffer content */
+ if (newrow <= 0 || newcol <= 0 ||
+ newrow > ws.dwMaximumWindowSize.Y ||
+ newcol > ws.dwMaximumWindowSize.X) {
+ SetConsoleScreenBufferSize(wh, oldsize);
+ /* remove scrollbar if possible */
+ SetConsoleWindowInfo(wh, TRUE, &oldwindow);
+ rb_raise(rb_eArgError, "out of range winsize: [%d, %d]", newrow, newcol);
+ }
+ /* shrink screen buffer width */
ws.dwSize.X = newcol;
- ret = SetConsoleScreenBufferSize(wh, ws.dwSize);
+ /* shrink screen buffer height if window height were the same */
+ if (oldsize.Y == ws.srWindow.Bottom - ws.srWindow.Top + 1) {
+ ws.dwSize.Y = newrow;
+ }
ws.srWindow.Left = 0;
- ws.srWindow.Top = 0;
- ws.srWindow.Right = newcol-1;
- ws.srWindow.Bottom = newrow-1;
+ ws.srWindow.Right = newcol - 1;
+ ws.srWindow.Bottom = ws.srWindow.Top + newrow -1;
+ if (ws.dwCursorPosition.Y > ws.srWindow.Bottom) {
+ console_scroll(io, ws.dwCursorPosition.Y - ws.srWindow.Bottom);
+ ws.dwCursorPosition.Y = ws.srWindow.Bottom;
+ console_goto(io, INT2FIX(ws.dwCursorPosition.Y), INT2FIX(ws.dwCursorPosition.X));
+ }
+ if (ws.srWindow.Bottom > ws.dwSize.Y - 1) {
+ console_scroll(io, ws.srWindow.Bottom - (ws.dwSize.Y - 1));
+ ws.dwCursorPosition.Y -= ws.srWindow.Bottom - (ws.dwSize.Y - 1);
+ console_goto(io, INT2FIX(ws.dwCursorPosition.Y), INT2FIX(ws.dwCursorPosition.X));
+ ws.srWindow.Bottom = ws.dwSize.Y - 1;
+ }
+ ws.srWindow.Top = ws.srWindow.Bottom - (newrow - 1);
+ /* perform changes to winsize */
if (!SetConsoleWindowInfo(wh, TRUE, &ws.srWindow)) {
- rb_syserr_fail(LAST_ERROR, "SetConsoleWindowInfo");
+ int last_error = LAST_ERROR;
+ SetConsoleScreenBufferSize(wh, oldsize);
+ rb_syserr_fail(last_error, "SetConsoleWindowInfo");
}
- /* retry when shrinking buffer after shrunk window */
- if (!ret && !SetConsoleScreenBufferSize(wh, ws.dwSize)) {
- rb_syserr_fail(LAST_ERROR, "SetConsoleScreenBufferInfo");
+ /* perform screen buffer shrinking if necessary */
+ if ((ws.dwSize.Y < oldsize.Y || ws.dwSize.X < oldsize.X) &&
+ !SetConsoleScreenBufferSize(wh, ws.dwSize)) {
+ rb_syserr_fail(LAST_ERROR, "SetConsoleScreenBufferInfo");
}
/* remove scrollbar if possible */
if (!SetConsoleWindowInfo(wh, TRUE, &ws.srWindow)) {
@@ -1071,6 +1132,9 @@ console_scroll(VALUE io, int line)
return io;
}
+#define GPERF_DOWNCASE 1
+#define GPERF_CASE_STRCMP 1
+#define gperf_case_strcmp STRCASECMP
#include "win32_vk.inc"
/*
@@ -1206,7 +1270,7 @@ console_cursor_pos(VALUE io)
if (!GetConsoleScreenBufferInfo((HANDLE)rb_w32_get_osfhandle(fd), &ws)) {
rb_syserr_fail(LAST_ERROR, 0);
}
- return rb_assoc_new(UINT2NUM(ws.dwCursorPosition.Y), UINT2NUM(ws.dwCursorPosition.X));
+ return rb_assoc_new(UINT2NUM(ws.dwCursorPosition.Y - ws.srWindow.Top), UINT2NUM(ws.dwCursorPosition.X));
#else
static const struct query_args query = {"\033[6n", 0};
VALUE resp = console_vt_response(0, 0, io, &query);
@@ -1239,11 +1303,17 @@ static VALUE
console_goto(VALUE io, VALUE y, VALUE x)
{
#ifdef _WIN32
- COORD pos;
- int fd = GetWriteFD(io);
- pos.X = NUM2UINT(x);
- pos.Y = NUM2UINT(y);
- if (!SetConsoleCursorPosition((HANDLE)rb_w32_get_osfhandle(fd), pos)) {
+ HANDLE h;
+ rb_console_size_t ws;
+ COORD *pos = &ws.dwCursorPosition;
+
+ h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io));
+ if (!GetConsoleScreenBufferInfo(h, &ws)) {
+ rb_syserr_fail(LAST_ERROR, 0);
+ }
+ pos->X = NUM2UINT(x);
+ pos->Y = ws.srWindow.Top + NUM2UINT(y);
+ if (!SetConsoleCursorPosition(h, *pos)) {
rb_syserr_fail(LAST_ERROR, 0);
}
#else
@@ -1535,10 +1605,8 @@ console_clear_screen(VALUE io)
static VALUE
io_open_descriptor_fallback(VALUE klass, int descriptor, int mode, VALUE path, VALUE timeout, void *encoding)
{
- rb_update_max_fd(descriptor);
-
VALUE arguments[2] = {
- INT2NUM(descriptor),
+ (rb_update_max_fd(descriptor), INT2NUM(descriptor)),
INT2FIX(mode),
};
@@ -1563,6 +1631,62 @@ rb_io_closed_p(VALUE io)
}
#endif
+#if defined(RB_EXT_RACTOR_SAFE) && defined(HAVE_RB_RACTOR_LOCAL_STORAGE_VALUE_NEWKEY)
+# define USE_RACTOR_STORAGE 1
+#else
+# define USE_RACTOR_STORAGE 0
+#endif
+
+#if USE_RACTOR_STORAGE
+#include "ruby/ractor.h"
+static rb_ractor_local_key_t key_console_dev;
+
+static bool
+console_dev_get(VALUE klass, VALUE *dev)
+{
+ return rb_ractor_local_storage_value_lookup(key_console_dev, dev);
+}
+
+static void
+console_dev_set(VALUE klass, VALUE value)
+{
+ rb_ractor_local_storage_value_set(key_console_dev, value);
+}
+
+static void
+console_dev_remove(VALUE klass)
+{
+ console_dev_set(klass, Qnil);
+}
+
+#else
+
+static ID id_console;
+
+static int
+console_dev_get(VALUE klass, VALUE *dev)
+{
+ if (rb_const_defined(klass, id_console)) {
+ *dev = rb_const_get(klass, id_console);
+ return 1;
+ }
+ return 0;
+}
+
+static void
+console_dev_set(VALUE klass, VALUE value)
+{
+ rb_const_set(klass, id_console, value);
+}
+
+static void
+console_dev_remove(VALUE klass)
+{
+ rb_const_remove(klass, id_console);
+}
+
+#endif
+
/*
* call-seq:
* IO.console -> #<File:/dev/tty>
@@ -1582,8 +1706,6 @@ console_dev(int argc, VALUE *argv, VALUE klass)
VALUE con = 0;
VALUE sym = 0;
- rb_check_arity(argc, 0, UNLIMITED_ARGUMENTS);
-
if (argc) {
Check_Type(sym = argv[0], T_SYMBOL);
}
@@ -1591,10 +1713,9 @@ console_dev(int argc, VALUE *argv, VALUE klass)
// Force the class to be File.
if (klass == rb_cIO) klass = rb_cFile;
- if (rb_const_defined(klass, id_console)) {
- con = rb_const_get(klass, id_console);
+ if (console_dev_get(klass, &con)) {
if (!RB_TYPE_P(con, T_FILE) || RTEST(rb_io_closed_p(con))) {
- rb_const_remove(klass, id_console);
+ console_dev_remove(klass);
con = 0;
}
}
@@ -1603,7 +1724,7 @@ console_dev(int argc, VALUE *argv, VALUE klass)
if (sym == ID2SYM(id_close) && argc == 1) {
if (con) {
rb_io_close(con);
- rb_const_remove(klass, id_console);
+ console_dev_remove(klass);
con = 0;
}
return Qnil;
@@ -1623,7 +1744,6 @@ console_dev(int argc, VALUE *argv, VALUE klass)
#endif
#ifdef CONSOLE_DEVICE_FOR_WRITING
VALUE out;
- rb_io_t *ofptr;
#endif
int fd;
VALUE path = rb_obj_freeze(rb_str_new2(CONSOLE_DEVICE));
@@ -1645,7 +1765,7 @@ console_dev(int argc, VALUE *argv, VALUE klass)
#ifdef CONSOLE_DEVICE_FOR_WRITING
rb_io_set_write_io(con, out);
#endif
- rb_const_set(klass, id_console, con);
+ console_dev_set(klass, con);
}
if (sym) {
@@ -1756,18 +1876,81 @@ io_getpass(int argc, VALUE *argv, VALUE io)
return str_chomp(str);
}
+#if defined(_WIN32) || defined(HAVE_TTYNAME_R) || defined(HAVE_TTYNAME)
+/*
+ * call-seq:
+ * io.ttyname -> string or nil
+ *
+ * Returns name of associated terminal (tty) if +io+ is not a tty.
+ * Returns +nil+ otherwise.
+ */
+static VALUE
+console_ttyname(VALUE io)
+{
+ int fd = rb_io_descriptor(io);
+ if (!isatty(fd)) return Qnil;
+# if defined _WIN32
+ return rb_usascii_str_new_lit("con");
+# elif defined HAVE_TTYNAME_R
+ {
+ char termname[1024], *tn = termname;
+ size_t size = sizeof(termname);
+ int e;
+ if (ttyname_r(fd, tn, size) == 0)
+ return rb_interned_str_cstr(tn);
+ if ((e = errno) == ERANGE) {
+ VALUE s = rb_str_new(0, size);
+ while (1) {
+ tn = RSTRING_PTR(s);
+ size = rb_str_capacity(s);
+ if (ttyname_r(fd, tn, size) == 0) {
+ return rb_str_to_interned_str(rb_str_resize(s, strlen(tn)));
+ }
+ if ((e = errno) != ERANGE) break;
+ if ((size *= 2) >= INT_MAX/2) break;
+ rb_str_resize(s, size);
+ }
+ }
+ rb_syserr_fail_str(e, rb_sprintf("ttyname_r(%d)", fd));
+ UNREACHABLE_RETURN(Qnil);
+ }
+# elif defined HAVE_TTYNAME
+ {
+ const char *tn = ttyname(fd);
+ if (!tn) {
+ int e = errno;
+ rb_syserr_fail_str(e, rb_sprintf("ttyname(%d)", fd));
+ }
+ return rb_interned_str_cstr(tn);
+ }
+# else
+# error No ttyname function
+# endif
+}
+#else
+# define console_ttyname rb_f_notimplement
+#endif
+
/*
* IO console methods
*/
void
Init_console(void)
{
+#if USE_RACTOR_STORAGE
+ RB_EXT_RACTOR_SAFE(true);
+#endif
+
#undef rb_intern
+#if USE_RACTOR_STORAGE
+ key_console_dev = rb_ractor_local_storage_value_newkey();
+#else
+ id_console = rb_intern("console");
+#endif
id_getc = rb_intern("getc");
id_gets = rb_intern("gets");
id_flush = rb_intern("flush");
id_chomp_bang = rb_intern("chomp!");
- id_console = rb_intern("console");
id_close = rb_intern("close");
#define init_rawmode_opt_id(name) \
rawmode_opt_ids[kwd_##name] = rb_intern(#name)
@@ -1815,6 +1998,7 @@ InitVM_console(void)
rb_define_method(rb_cIO, "pressed?", console_key_pressed_p, 1);
rb_define_method(rb_cIO, "check_winsize_changed", console_check_winsize_changed, 0);
rb_define_method(rb_cIO, "getpass", console_getpass, -1);
+ rb_define_method(rb_cIO, "ttyname", console_ttyname, 0);
rb_define_singleton_method(rb_cIO, "console", console_dev, -1);
{
/* :stopdoc: */
@@ -1826,7 +2010,7 @@ InitVM_console(void)
{
/* :stopdoc: */
cConmode = rb_define_class_under(rb_cIO, "ConsoleMode", rb_cObject);
- rb_define_const(cConmode, "VERSION", rb_str_new_cstr(IO_CONSOLE_VERSION));
+ rb_define_const(cConmode, "VERSION", rb_obj_freeze(rb_str_new_cstr(IO_CONSOLE_VERSION)));
rb_define_alloc_func(cConmode, conmode_alloc);
rb_undef_method(cConmode, "initialize");
rb_define_method(cConmode, "initialize_copy", conmode_init_copy, 1);
diff --git a/ext/io/console/depend b/ext/io/console/depend
index 5b91413f38..150a138d4d 100644
--- a/ext/io/console/depend
+++ b/ext/io/console/depend
@@ -139,6 +139,7 @@ console.o: $(hdrdir)/ruby/internal/intern/re.h
console.o: $(hdrdir)/ruby/internal/intern/ruby.h
console.o: $(hdrdir)/ruby/internal/intern/select.h
console.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+console.o: $(hdrdir)/ruby/internal/intern/set.h
console.o: $(hdrdir)/ruby/internal/intern/signal.h
console.o: $(hdrdir)/ruby/internal/intern/sprintf.h
console.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -169,6 +170,7 @@ console.o: $(hdrdir)/ruby/io.h
console.o: $(hdrdir)/ruby/missing.h
console.o: $(hdrdir)/ruby/onigmo.h
console.o: $(hdrdir)/ruby/oniguruma.h
+console.o: $(hdrdir)/ruby/ractor.h
console.o: $(hdrdir)/ruby/ruby.h
console.o: $(hdrdir)/ruby/st.h
console.o: $(hdrdir)/ruby/subst.h
@@ -185,7 +187,7 @@ win32_vk.inc: win32_vk.list
-e 'n=$$F[1] and (n.strip!; /\AVK_/=~n) and' \
-e 'puts(%[#ifndef #{n}\n# define #{n} UNDEFINED_VK\n#endif])' \
$< && \
- gperf --ignore-case -E -C -P -p -j1 -i 1 -g -o -t -K ofs -N console_win32_vk -k* $< \
+ gperf --ignore-case -L ANSI-C -E -C -P -p -j1 -i 1 -g -o -t -K ofs -N console_win32_vk -k* $< \
| sed -f $(top_srcdir)/tool/gperf.sed \
) > $(@F)
diff --git a/ext/io/console/extconf.rb b/ext/io/console/extconf.rb
index a72403c7f9..dd3d221ae5 100644
--- a/ext/io/console/extconf.rb
+++ b/ext/io/console/extconf.rb
@@ -1,13 +1,30 @@
# frozen_string_literal: false
require 'mkmf'
-have_func("rb_io_path")
-have_func("rb_io_descriptor")
-have_func("rb_io_get_write_io")
-have_func("rb_io_closed_p")
-have_func("rb_io_open_descriptor")
+# `--target-rbconfig` compatibility for Ruby 3.3 or earlier
+# See https://bugs.ruby-lang.org/issues/20345
+MakeMakefile::RbConfig ||= ::RbConfig
-ok = true if RUBY_ENGINE == "ruby" || RUBY_ENGINE == "truffleruby"
+have_func("rb_syserr_fail_str(0, Qnil)") or
+have_func("rb_syserr_new_str(0, Qnil)") or
+ abort
+
+have_func("rb_interned_str_cstr")
+have_func("rb_io_path", "ruby/io.h")
+have_func("rb_io_descriptor", "ruby/io.h")
+have_func("rb_io_get_write_io", "ruby/io.h")
+have_func("rb_io_closed_p", "ruby/io.h")
+have_func("rb_io_open_descriptor", "ruby/io.h")
+have_func("rb_ractor_local_storage_value_newkey")
+
+is_wasi = /wasi/ =~ MakeMakefile::RbConfig::CONFIG["platform"]
+# `ok` can be `true`, `false`, or `nil`:
+# * `true` : Required headers and functions available, proceed regular build.
+# * `false`: Required headers or functions not available, abort build.
+# * `nil` : Unsupported compilation target, generate dummy Makefile.
+#
+# Skip building io/console on WASI, as it does not support termios.h.
+ok = true if (RUBY_ENGINE == "ruby" && !is_wasi) || RUBY_ENGINE == "truffleruby"
hdr = nil
case
when macro_defined?("_WIN32", "")
@@ -35,6 +52,7 @@ when true
elsif have_func("rb_scheduler_timeout") # 3.0
have_func("rb_io_wait")
end
+ have_func("ttyname_r") or have_func("ttyname")
create_makefile("io/console") {|conf|
conf << "\n""VK_HEADER = #{vk_header}\n"
}
diff --git a/ext/io/console/io-console.gemspec b/ext/io/console/io-console.gemspec
index f9c1729cb7..0a19992734 100644
--- a/ext/io/console/io-console.gemspec
+++ b/ext/io/console/io-console.gemspec
@@ -23,7 +23,8 @@ Gem::Specification.new do |s|
s.require_path = %[lib]
s.files = %w[
.document
- LICENSE.txt
+ BSDL
+ COPYING
README.md
ext/io/console/console.c
ext/io/console/extconf.rb
diff --git a/ext/io/console/win32_vk.inc b/ext/io/console/win32_vk.inc
index cbec7bef15..348e6be5ed 100644
--- a/ext/io/console/win32_vk.inc
+++ b/ext/io/console/win32_vk.inc
@@ -480,7 +480,7 @@
# define VK_OEM_CLEAR UNDEFINED_VK
#endif
/* ANSI-C code produced by gperf version 3.1 */
-/* Command-line: gperf --ignore-case -E -C -P -p -j1 -i 1 -g -o -t -K ofs -N console_win32_vk -k'*' win32_vk.list */
+/* Command-line: gperf --ignore-case -L ANSI-C -E -C -P -p -j1 -i 1 -g -o -t -K ofs -N console_win32_vk -k'*' win32_vk.list */
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
&& ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
@@ -509,11 +509,10 @@
#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gperf@gnu.org>."
#endif
-#define gperf_offsetof(s, n) (short)offsetof(struct s##_t, s##_str##n)
#line 1 "win32_vk.list"
struct vktable {short ofs; unsigned short vk;};
-static const struct vktable *console_win32_vk(/*const char *, unsigned int*/);
+static const struct vktable *console_win32_vk(const char *, size_t);
#line 5 "win32_vk.list"
struct vktable;
/* maximum key range = 245, duplicates = 0 */
@@ -1007,368 +1006,368 @@ console_win32_vk (register const char *str, register size_t len)
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1},
#line 40 "win32_vk.list"
- {gperf_offsetof(stringpool, 12), VK_UP},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str12, VK_UP},
#line 52 "win32_vk.list"
- {gperf_offsetof(stringpool, 13), VK_APPS},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str13, VK_APPS},
#line 159 "win32_vk.list"
- {gperf_offsetof(stringpool, 14), VK_CRSEL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str14, VK_CRSEL},
#line 34 "win32_vk.list"
- {gperf_offsetof(stringpool, 15), VK_SPACE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str15, VK_SPACE},
#line 95 "win32_vk.list"
- {gperf_offsetof(stringpool, 16), VK_SCROLL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str16, VK_SCROLL},
#line 29 "win32_vk.list"
- {gperf_offsetof(stringpool, 17), VK_ESCAPE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str17, VK_ESCAPE},
#line 9 "win32_vk.list"
- {gperf_offsetof(stringpool, 18), VK_CANCEL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str18, VK_CANCEL},
#line 32 "win32_vk.list"
- {gperf_offsetof(stringpool, 19), VK_ACCEPT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str19, VK_ACCEPT},
#line 66 "win32_vk.list"
- {gperf_offsetof(stringpool, 20), VK_SEPARATOR},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str20, VK_SEPARATOR},
#line 43 "win32_vk.list"
- {gperf_offsetof(stringpool, 21), VK_SELECT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str21, VK_SELECT},
#line 18 "win32_vk.list"
- {gperf_offsetof(stringpool, 22), VK_CONTROL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str22, VK_CONTROL},
#line 166 "win32_vk.list"
- {gperf_offsetof(stringpool, 23), VK_OEM_CLEAR},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str23, VK_OEM_CLEAR},
#line 145 "win32_vk.list"
- {gperf_offsetof(stringpool, 24), VK_OEM_RESET},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str24, VK_OEM_RESET},
#line 155 "win32_vk.list"
- {gperf_offsetof(stringpool, 25), VK_OEM_AUTO},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str25, VK_OEM_AUTO},
#line 151 "win32_vk.list"
- {gperf_offsetof(stringpool, 26), VK_OEM_CUSEL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str26, VK_OEM_CUSEL},
{-1},
#line 22 "win32_vk.list"
- {gperf_offsetof(stringpool, 28), VK_KANA},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str28, VK_KANA},
#line 127 "win32_vk.list"
- {gperf_offsetof(stringpool, 29), VK_OEM_PLUS},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str29, VK_OEM_PLUS},
#line 35 "win32_vk.list"
- {gperf_offsetof(stringpool, 30), VK_PRIOR},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str30, VK_PRIOR},
#line 152 "win32_vk.list"
- {gperf_offsetof(stringpool, 31), VK_OEM_ATTN},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str31, VK_OEM_ATTN},
#line 20 "win32_vk.list"
- {gperf_offsetof(stringpool, 32), VK_PAUSE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str32, VK_PAUSE},
#line 13 "win32_vk.list"
- {gperf_offsetof(stringpool, 33), VK_BACK},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str33, VK_BACK},
#line 144 "win32_vk.list"
- {gperf_offsetof(stringpool, 34), VK_PACKET},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str34, VK_PACKET},
#line 105 "win32_vk.list"
- {gperf_offsetof(stringpool, 35), VK_RCONTROL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str35, VK_RCONTROL},
#line 104 "win32_vk.list"
- {gperf_offsetof(stringpool, 36), VK_LCONTROL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str36, VK_LCONTROL},
#line 37 "win32_vk.list"
- {gperf_offsetof(stringpool, 37), VK_END},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str37, VK_END},
#line 38 "win32_vk.list"
- {gperf_offsetof(stringpool, 38), VK_HOME},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str38, VK_HOME},
#line 44 "win32_vk.list"
- {gperf_offsetof(stringpool, 39), VK_PRINT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str39, VK_PRINT},
#line 94 "win32_vk.list"
- {gperf_offsetof(stringpool, 40), VK_NUMLOCK},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str40, VK_NUMLOCK},
#line 39 "win32_vk.list"
- {gperf_offsetof(stringpool, 41), VK_LEFT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str41, VK_LEFT},
#line 25 "win32_vk.list"
- {gperf_offsetof(stringpool, 42), VK_JUNJA},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str42, VK_JUNJA},
#line 19 "win32_vk.list"
- {gperf_offsetof(stringpool, 43), VK_MENU},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str43, VK_MENU},
#line 150 "win32_vk.list"
- {gperf_offsetof(stringpool, 44), VK_OEM_WSCTRL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str44, VK_OEM_WSCTRL},
#line 156 "win32_vk.list"
- {gperf_offsetof(stringpool, 45), VK_OEM_ENLW},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str45, VK_OEM_ENLW},
#line 36 "win32_vk.list"
- {gperf_offsetof(stringpool, 46), VK_NEXT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str46, VK_NEXT},
#line 51 "win32_vk.list"
- {gperf_offsetof(stringpool, 47), VK_RWIN},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str47, VK_RWIN},
#line 50 "win32_vk.list"
- {gperf_offsetof(stringpool, 48), VK_LWIN},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str48, VK_LWIN},
#line 21 "win32_vk.list"
- {gperf_offsetof(stringpool, 49), VK_CAPITAL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str49, VK_CAPITAL},
#line 49 "win32_vk.list"
- {gperf_offsetof(stringpool, 50), VK_HELP},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str50, VK_HELP},
#line 164 "win32_vk.list"
- {gperf_offsetof(stringpool, 51), VK_NONAME},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str51, VK_NONAME},
#line 8 "win32_vk.list"
- {gperf_offsetof(stringpool, 52), VK_RBUTTON},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str52, VK_RBUTTON},
#line 7 "win32_vk.list"
- {gperf_offsetof(stringpool, 53), VK_LBUTTON},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str53, VK_LBUTTON},
#line 96 "win32_vk.list"
- {gperf_offsetof(stringpool, 54), VK_OEM_NEC_EQUAL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str54, VK_OEM_NEC_EQUAL},
{-1},
#line 47 "win32_vk.list"
- {gperf_offsetof(stringpool, 56), VK_INSERT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str56, VK_INSERT},
#line 27 "win32_vk.list"
- {gperf_offsetof(stringpool, 57), VK_HANJA},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str57, VK_HANJA},
{-1}, {-1},
#line 46 "win32_vk.list"
- {gperf_offsetof(stringpool, 60), VK_SNAPSHOT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str60, VK_SNAPSHOT},
#line 158 "win32_vk.list"
- {gperf_offsetof(stringpool, 61), VK_ATTN},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str61, VK_ATTN},
#line 14 "win32_vk.list"
- {gperf_offsetof(stringpool, 62), VK_TAB},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str62, VK_TAB},
#line 157 "win32_vk.list"
- {gperf_offsetof(stringpool, 63), VK_OEM_BACKTAB},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str63, VK_OEM_BACKTAB},
#line 143 "win32_vk.list"
- {gperf_offsetof(stringpool, 64), VK_ICO_CLEAR},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str64, VK_ICO_CLEAR},
#line 30 "win32_vk.list"
- {gperf_offsetof(stringpool, 65), VK_CONVERT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str65, VK_CONVERT},
#line 16 "win32_vk.list"
- {gperf_offsetof(stringpool, 66), VK_RETURN},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str66, VK_RETURN},
#line 146 "win32_vk.list"
- {gperf_offsetof(stringpool, 67), VK_OEM_JUMP},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str67, VK_OEM_JUMP},
{-1}, {-1}, {-1},
#line 111 "win32_vk.list"
- {gperf_offsetof(stringpool, 71), VK_BROWSER_STOP},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str71, VK_BROWSER_STOP},
#line 26 "win32_vk.list"
- {gperf_offsetof(stringpool, 72), VK_FINAL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str72, VK_FINAL},
#line 163 "win32_vk.list"
- {gperf_offsetof(stringpool, 73), VK_ZOOM},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str73, VK_ZOOM},
#line 28 "win32_vk.list"
- {gperf_offsetof(stringpool, 74), VK_KANJI},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str74, VK_KANJI},
#line 48 "win32_vk.list"
- {gperf_offsetof(stringpool, 75), VK_DELETE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str75, VK_DELETE},
#line 128 "win32_vk.list"
- {gperf_offsetof(stringpool, 76), VK_OEM_COMMA},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str76, VK_OEM_COMMA},
#line 67 "win32_vk.list"
- {gperf_offsetof(stringpool, 77), VK_SUBTRACT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str77, VK_SUBTRACT},
{-1},
#line 10 "win32_vk.list"
- {gperf_offsetof(stringpool, 79), VK_MBUTTON},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str79, VK_MBUTTON},
#line 78 "win32_vk.list"
- {gperf_offsetof(stringpool, 80), VK_F9},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str80, VK_F9},
#line 17 "win32_vk.list"
- {gperf_offsetof(stringpool, 81), VK_SHIFT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str81, VK_SHIFT},
#line 103 "win32_vk.list"
- {gperf_offsetof(stringpool, 82), VK_RSHIFT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str82, VK_RSHIFT},
#line 102 "win32_vk.list"
- {gperf_offsetof(stringpool, 83), VK_LSHIFT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str83, VK_LSHIFT},
#line 65 "win32_vk.list"
- {gperf_offsetof(stringpool, 84), VK_ADD},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str84, VK_ADD},
#line 31 "win32_vk.list"
- {gperf_offsetof(stringpool, 85), VK_NONCONVERT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str85, VK_NONCONVERT},
#line 160 "win32_vk.list"
- {gperf_offsetof(stringpool, 86), VK_EXSEL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str86, VK_EXSEL},
#line 126 "win32_vk.list"
- {gperf_offsetof(stringpool, 87), VK_OEM_1},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str87, VK_OEM_1},
#line 138 "win32_vk.list"
- {gperf_offsetof(stringpool, 88), VK_OEM_AX},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str88, VK_OEM_AX},
#line 108 "win32_vk.list"
- {gperf_offsetof(stringpool, 89), VK_BROWSER_BACK},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str89, VK_BROWSER_BACK},
#line 137 "win32_vk.list"
- {gperf_offsetof(stringpool, 90), VK_OEM_8},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str90, VK_OEM_8},
#line 129 "win32_vk.list"
- {gperf_offsetof(stringpool, 91), VK_OEM_MINUS},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str91, VK_OEM_MINUS},
#line 162 "win32_vk.list"
- {gperf_offsetof(stringpool, 92), VK_PLAY},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str92, VK_PLAY},
#line 131 "win32_vk.list"
- {gperf_offsetof(stringpool, 93), VK_OEM_2},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str93, VK_OEM_2},
#line 15 "win32_vk.list"
- {gperf_offsetof(stringpool, 94), VK_CLEAR},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str94, VK_CLEAR},
#line 99 "win32_vk.list"
- {gperf_offsetof(stringpool, 95), VK_OEM_FJ_TOUROKU},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str95, VK_OEM_FJ_TOUROKU},
#line 147 "win32_vk.list"
- {gperf_offsetof(stringpool, 96), VK_OEM_PA1},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str96, VK_OEM_PA1},
#line 140 "win32_vk.list"
- {gperf_offsetof(stringpool, 97), VK_ICO_HELP},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str97, VK_ICO_HELP},
#line 112 "win32_vk.list"
- {gperf_offsetof(stringpool, 98), VK_BROWSER_SEARCH},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str98, VK_BROWSER_SEARCH},
#line 53 "win32_vk.list"
- {gperf_offsetof(stringpool, 99), VK_SLEEP},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str99, VK_SLEEP},
{-1},
#line 70 "win32_vk.list"
- {gperf_offsetof(stringpool, 101), VK_F1},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str101, VK_F1},
#line 148 "win32_vk.list"
- {gperf_offsetof(stringpool, 102), VK_OEM_PA2},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str102, VK_OEM_PA2},
#line 154 "win32_vk.list"
- {gperf_offsetof(stringpool, 103), VK_OEM_COPY},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str103, VK_OEM_COPY},
#line 77 "win32_vk.list"
- {gperf_offsetof(stringpool, 104), VK_F8},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str104, VK_F8},
#line 88 "win32_vk.list"
- {gperf_offsetof(stringpool, 105), VK_F19},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str105, VK_F19},
#line 41 "win32_vk.list"
- {gperf_offsetof(stringpool, 106), VK_RIGHT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str106, VK_RIGHT},
#line 71 "win32_vk.list"
- {gperf_offsetof(stringpool, 107), VK_F2},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str107, VK_F2},
#line 135 "win32_vk.list"
- {gperf_offsetof(stringpool, 108), VK_OEM_6},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str108, VK_OEM_6},
#line 87 "win32_vk.list"
- {gperf_offsetof(stringpool, 109), VK_F18},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str109, VK_F18},
{-1},
#line 117 "win32_vk.list"
- {gperf_offsetof(stringpool, 111), VK_VOLUME_UP},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str111, VK_VOLUME_UP},
{-1}, {-1},
#line 120 "win32_vk.list"
- {gperf_offsetof(stringpool, 114), VK_MEDIA_STOP},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str114, VK_MEDIA_STOP},
#line 130 "win32_vk.list"
- {gperf_offsetof(stringpool, 115), VK_OEM_PERIOD},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str115, VK_OEM_PERIOD},
{-1},
#line 161 "win32_vk.list"
- {gperf_offsetof(stringpool, 117), VK_EREOF},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str117, VK_EREOF},
{-1}, {-1}, {-1},
#line 114 "win32_vk.list"
- {gperf_offsetof(stringpool, 121), VK_BROWSER_HOME},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str121, VK_BROWSER_HOME},
#line 75 "win32_vk.list"
- {gperf_offsetof(stringpool, 122), VK_F6},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str122, VK_F6},
{-1},
#line 110 "win32_vk.list"
- {gperf_offsetof(stringpool, 124), VK_BROWSER_REFRESH},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str124, VK_BROWSER_REFRESH},
{-1},
#line 165 "win32_vk.list"
- {gperf_offsetof(stringpool, 126), VK_PA1},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str126, VK_PA1},
#line 142 "win32_vk.list"
- {gperf_offsetof(stringpool, 127), VK_PROCESSKEY},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str127, VK_PROCESSKEY},
#line 68 "win32_vk.list"
- {gperf_offsetof(stringpool, 128), VK_DECIMAL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str128, VK_DECIMAL},
#line 132 "win32_vk.list"
- {gperf_offsetof(stringpool, 129), VK_OEM_3},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str129, VK_OEM_3},
#line 107 "win32_vk.list"
- {gperf_offsetof(stringpool, 130), VK_RMENU},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str130, VK_RMENU},
#line 106 "win32_vk.list"
- {gperf_offsetof(stringpool, 131), VK_LMENU},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str131, VK_LMENU},
#line 98 "win32_vk.list"
- {gperf_offsetof(stringpool, 132), VK_OEM_FJ_MASSHOU},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str132, VK_OEM_FJ_MASSHOU},
#line 54 "win32_vk.list"
- {gperf_offsetof(stringpool, 133), VK_NUMPAD0},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str133, VK_NUMPAD0},
#line 24 "win32_vk.list"
- {gperf_offsetof(stringpool, 134), VK_HANGUL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str134, VK_HANGUL},
#line 63 "win32_vk.list"
- {gperf_offsetof(stringpool, 135), VK_NUMPAD9},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str135, VK_NUMPAD9},
#line 23 "win32_vk.list"
- {gperf_offsetof(stringpool, 136), VK_HANGEUL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str136, VK_HANGEUL},
#line 134 "win32_vk.list"
- {gperf_offsetof(stringpool, 137), VK_OEM_5},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str137, VK_OEM_5},
#line 149 "win32_vk.list"
- {gperf_offsetof(stringpool, 138), VK_OEM_PA3},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str138, VK_OEM_PA3},
#line 115 "win32_vk.list"
- {gperf_offsetof(stringpool, 139), VK_VOLUME_MUTE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str139, VK_VOLUME_MUTE},
#line 133 "win32_vk.list"
- {gperf_offsetof(stringpool, 140), VK_OEM_4},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str140, VK_OEM_4},
#line 122 "win32_vk.list"
- {gperf_offsetof(stringpool, 141), VK_LAUNCH_MAIL},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str141, VK_LAUNCH_MAIL},
#line 97 "win32_vk.list"
- {gperf_offsetof(stringpool, 142), VK_OEM_FJ_JISHO},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str142, VK_OEM_FJ_JISHO},
#line 72 "win32_vk.list"
- {gperf_offsetof(stringpool, 143), VK_F3},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str143, VK_F3},
#line 101 "win32_vk.list"
- {gperf_offsetof(stringpool, 144), VK_OEM_FJ_ROYA},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str144, VK_OEM_FJ_ROYA},
#line 100 "win32_vk.list"
- {gperf_offsetof(stringpool, 145), VK_OEM_FJ_LOYA},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str145, VK_OEM_FJ_LOYA},
{-1},
#line 42 "win32_vk.list"
- {gperf_offsetof(stringpool, 147), VK_DOWN},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str147, VK_DOWN},
{-1},
#line 153 "win32_vk.list"
- {gperf_offsetof(stringpool, 149), VK_OEM_FINISH},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str149, VK_OEM_FINISH},
{-1},
#line 74 "win32_vk.list"
- {gperf_offsetof(stringpool, 151), VK_F5},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str151, VK_F5},
{-1},
#line 136 "win32_vk.list"
- {gperf_offsetof(stringpool, 153), VK_OEM_7},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str153, VK_OEM_7},
#line 73 "win32_vk.list"
- {gperf_offsetof(stringpool, 154), VK_F4},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str154, VK_F4},
#line 86 "win32_vk.list"
- {gperf_offsetof(stringpool, 155), VK_F17},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str155, VK_F17},
#line 55 "win32_vk.list"
- {gperf_offsetof(stringpool, 156), VK_NUMPAD1},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str156, VK_NUMPAD1},
#line 141 "win32_vk.list"
- {gperf_offsetof(stringpool, 157), VK_ICO_00},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str157, VK_ICO_00},
{-1},
#line 62 "win32_vk.list"
- {gperf_offsetof(stringpool, 159), VK_NUMPAD8},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str159, VK_NUMPAD8},
{-1}, {-1},
#line 56 "win32_vk.list"
- {gperf_offsetof(stringpool, 162), VK_NUMPAD2},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str162, VK_NUMPAD2},
{-1},
#line 124 "win32_vk.list"
- {gperf_offsetof(stringpool, 164), VK_LAUNCH_APP1},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str164, VK_LAUNCH_APP1},
#line 109 "win32_vk.list"
- {gperf_offsetof(stringpool, 165), VK_BROWSER_FORWARD},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str165, VK_BROWSER_FORWARD},
{-1},
#line 76 "win32_vk.list"
- {gperf_offsetof(stringpool, 167), VK_F7},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str167, VK_F7},
{-1}, {-1},
#line 125 "win32_vk.list"
- {gperf_offsetof(stringpool, 170), VK_LAUNCH_APP2},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str170, VK_LAUNCH_APP2},
#line 64 "win32_vk.list"
- {gperf_offsetof(stringpool, 171), VK_MULTIPLY},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str171, VK_MULTIPLY},
{-1}, {-1},
#line 45 "win32_vk.list"
- {gperf_offsetof(stringpool, 174), VK_EXECUTE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str174, VK_EXECUTE},
{-1},
#line 113 "win32_vk.list"
- {gperf_offsetof(stringpool, 176), VK_BROWSER_FAVORITES},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str176, VK_BROWSER_FAVORITES},
#line 60 "win32_vk.list"
- {gperf_offsetof(stringpool, 177), VK_NUMPAD6},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str177, VK_NUMPAD6},
{-1},
#line 85 "win32_vk.list"
- {gperf_offsetof(stringpool, 179), VK_F16},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str179, VK_F16},
{-1}, {-1},
#line 79 "win32_vk.list"
- {gperf_offsetof(stringpool, 182), VK_F10},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str182, VK_F10},
{-1}, {-1},
#line 116 "win32_vk.list"
- {gperf_offsetof(stringpool, 185), VK_VOLUME_DOWN},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str185, VK_VOLUME_DOWN},
{-1}, {-1},
#line 89 "win32_vk.list"
- {gperf_offsetof(stringpool, 188), VK_F20},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str188, VK_F20},
#line 119 "win32_vk.list"
- {gperf_offsetof(stringpool, 189), VK_MEDIA_PREV_TRACK},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str189, VK_MEDIA_PREV_TRACK},
{-1},
#line 33 "win32_vk.list"
- {gperf_offsetof(stringpool, 191), VK_MODECHANGE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str191, VK_MODECHANGE},
{-1}, {-1}, {-1}, {-1}, {-1},
#line 83 "win32_vk.list"
- {gperf_offsetof(stringpool, 197), VK_F14},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str197, VK_F14},
#line 57 "win32_vk.list"
- {gperf_offsetof(stringpool, 198), VK_NUMPAD3},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str198, VK_NUMPAD3},
#line 11 "win32_vk.list"
- {gperf_offsetof(stringpool, 199), VK_XBUTTON1},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str199, VK_XBUTTON1},
{-1}, {-1}, {-1},
#line 93 "win32_vk.list"
- {gperf_offsetof(stringpool, 203), VK_F24},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str203, VK_F24},
{-1},
#line 12 "win32_vk.list"
- {gperf_offsetof(stringpool, 205), VK_XBUTTON2},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str205, VK_XBUTTON2},
#line 59 "win32_vk.list"
- {gperf_offsetof(stringpool, 206), VK_NUMPAD5},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str206, VK_NUMPAD5},
{-1}, {-1},
#line 58 "win32_vk.list"
- {gperf_offsetof(stringpool, 209), VK_NUMPAD4},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str209, VK_NUMPAD4},
{-1}, {-1}, {-1}, {-1}, {-1},
#line 121 "win32_vk.list"
- {gperf_offsetof(stringpool, 215), VK_MEDIA_PLAY_PAUSE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str215, VK_MEDIA_PLAY_PAUSE},
{-1},
#line 123 "win32_vk.list"
- {gperf_offsetof(stringpool, 217), VK_LAUNCH_MEDIA_SELECT},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str217, VK_LAUNCH_MEDIA_SELECT},
#line 80 "win32_vk.list"
- {gperf_offsetof(stringpool, 218), VK_F11},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str218, VK_F11},
{-1},
#line 139 "win32_vk.list"
- {gperf_offsetof(stringpool, 220), VK_OEM_102},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str220, VK_OEM_102},
#line 118 "win32_vk.list"
- {gperf_offsetof(stringpool, 221), VK_MEDIA_NEXT_TRACK},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str221, VK_MEDIA_NEXT_TRACK},
#line 61 "win32_vk.list"
- {gperf_offsetof(stringpool, 222), VK_NUMPAD7},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str222, VK_NUMPAD7},
{-1},
#line 90 "win32_vk.list"
- {gperf_offsetof(stringpool, 224), VK_F21},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str224, VK_F21},
{-1},
#line 82 "win32_vk.list"
- {gperf_offsetof(stringpool, 226), VK_F13},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str226, VK_F13},
{-1}, {-1},
#line 81 "win32_vk.list"
- {gperf_offsetof(stringpool, 229), VK_F12},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str229, VK_F12},
{-1}, {-1},
#line 92 "win32_vk.list"
- {gperf_offsetof(stringpool, 232), VK_F23},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str232, VK_F23},
{-1}, {-1},
#line 91 "win32_vk.list"
- {gperf_offsetof(stringpool, 235), VK_F22},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str235, VK_F22},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1},
#line 84 "win32_vk.list"
- {gperf_offsetof(stringpool, 242), VK_F15},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str242, VK_F15},
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
{-1}, {-1}, {-1}, {-1},
#line 69 "win32_vk.list"
- {gperf_offsetof(stringpool, 256), VK_DIVIDE}
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str256, VK_DIVIDE}
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
diff --git a/ext/io/console/win32_vk.list b/ext/io/console/win32_vk.list
index 7909a4d1f0..5df3d6da57 100644
--- a/ext/io/console/win32_vk.list
+++ b/ext/io/console/win32_vk.list
@@ -1,6 +1,6 @@
%{
struct vktable {short ofs; unsigned short vk;};
-static const struct vktable *console_win32_vk(/*!ANSI{*/const char *, unsigned int/*}!ANSI*/);
+static const struct vktable *console_win32_vk(const char *, size_t);
%}
struct vktable
%%
diff --git a/ext/io/nonblock/depend b/ext/io/nonblock/depend
index 20a96f1252..e78a05c316 100644
--- a/ext/io/nonblock/depend
+++ b/ext/io/nonblock/depend
@@ -138,6 +138,7 @@ nonblock.o: $(hdrdir)/ruby/internal/intern/re.h
nonblock.o: $(hdrdir)/ruby/internal/intern/ruby.h
nonblock.o: $(hdrdir)/ruby/internal/intern/select.h
nonblock.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+nonblock.o: $(hdrdir)/ruby/internal/intern/set.h
nonblock.o: $(hdrdir)/ruby/internal/intern/signal.h
nonblock.o: $(hdrdir)/ruby/internal/intern/sprintf.h
nonblock.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/io/nonblock/extconf.rb b/ext/io/nonblock/extconf.rb
index a1e6075c9b..505c9e6252 100644
--- a/ext/io/nonblock/extconf.rb
+++ b/ext/io/nonblock/extconf.rb
@@ -7,7 +7,7 @@ unless RUBY_ENGINE == 'ruby'
return
end
-have_func("rb_io_descriptor")
+have_func("rb_io_descriptor", "ruby/io.h")
hdr = %w"fcntl.h"
if have_macro("O_NONBLOCK", hdr) and
diff --git a/ext/io/nonblock/io-nonblock.gemspec b/ext/io/nonblock/io-nonblock.gemspec
index 6a16c8b03b..4f5b8cef6f 100644
--- a/ext/io/nonblock/io-nonblock.gemspec
+++ b/ext/io/nonblock/io-nonblock.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "io-nonblock"
- spec.version = "0.3.0"
+ spec.version = "0.3.2"
spec.authors = ["Nobu Nakada"]
spec.email = ["nobu@ruby-lang.org"]
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
spec.description = %q{Enables non-blocking mode with IO class}
spec.homepage = "https://github.com/ruby/io-nonblock"
spec.licenses = ["Ruby", "BSD-2-Clause"]
- spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.required_ruby_version = Gem::Requirement.new(">= 3.0")
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
diff --git a/ext/io/nonblock/nonblock.c b/ext/io/nonblock/nonblock.c
index d90538f735..cd40ea3335 100644
--- a/ext/io/nonblock/nonblock.c
+++ b/ext/io/nonblock/nonblock.c
@@ -197,6 +197,10 @@ rb_io_nonblock_block(int argc, VALUE *argv, VALUE self)
void
Init_nonblock(void)
{
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
+
#ifndef RUBY_IO_NONBLOCK_METHODS
rb_define_method(rb_cIO, "nonblock?", rb_io_nonblock_p, 0);
rb_define_method(rb_cIO, "nonblock=", rb_io_nonblock_set, 1);
diff --git a/ext/io/wait/depend b/ext/io/wait/depend
index 70317b1497..41d53c1400 100644
--- a/ext/io/wait/depend
+++ b/ext/io/wait/depend
@@ -1,5 +1,4 @@
# AUTOGENERATED DEPENDENCIES START
-# wait.o: $(hdrdir)/ruby/assert.h # not in 2.6
wait.o: $(RUBY_EXTCONF_H)
wait.o: $(arch_hdrdir)/ruby/config.h
wait.o: $(hdrdir)/ruby.h
@@ -139,6 +138,7 @@ wait.o: $(hdrdir)/ruby/internal/intern/re.h
wait.o: $(hdrdir)/ruby/internal/intern/ruby.h
wait.o: $(hdrdir)/ruby/internal/intern/select.h
wait.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+wait.o: $(hdrdir)/ruby/internal/intern/set.h
wait.o: $(hdrdir)/ruby/internal/intern/signal.h
wait.o: $(hdrdir)/ruby/internal/intern/sprintf.h
wait.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/io/wait/extconf.rb b/ext/io/wait/extconf.rb
index e63c046187..00c455a45c 100644
--- a/ext/io/wait/extconf.rb
+++ b/ext/io/wait/extconf.rb
@@ -1,25 +1,4 @@
# frozen_string_literal: false
require 'mkmf'
-if RUBY_VERSION < "2.6"
- File.write("Makefile", dummy_makefile($srcdir).join(""))
-else
- target = "io/wait"
- have_func("rb_io_wait")
- have_func("rb_io_descriptor")
- unless macro_defined?("DOSISH", "#include <ruby.h>")
- have_header(ioctl_h = "sys/ioctl.h") or ioctl_h = nil
- fionread = %w[sys/ioctl.h sys/filio.h sys/socket.h].find do |h|
- have_macro("FIONREAD", [h, ioctl_h].compact)
- end
- if fionread
- $defs << "-DFIONREAD_HEADER=\"<#{fionread}>\""
- create_makefile(target)
- end
- else
- if have_func("rb_w32_ioctlsocket", "ruby.h")
- have_func("rb_w32_is_socket", "ruby.h")
- create_makefile(target)
- end
- end
-end
+create_makefile("io/wait")
diff --git a/ext/io/wait/io-wait.gemspec b/ext/io/wait/io-wait.gemspec
index e850e10bf9..c1c6172589 100644
--- a/ext/io/wait/io-wait.gemspec
+++ b/ext/io/wait/io-wait.gemspec
@@ -1,4 +1,4 @@
-_VERSION = "0.3.1"
+_VERSION = "0.4.0"
Gem::Specification.new do |spec|
spec.name = "io-wait"
@@ -10,24 +10,25 @@ Gem::Specification.new do |spec|
spec.description = %q{Waits until IO is readable or writable without blocking.}
spec.homepage = "https://github.com/ruby/io-wait"
spec.licenses = ["Ruby", "BSD-2-Clause"]
+ spec.required_ruby_version = Gem::Requirement.new(">= 3.2")
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|
- File.identical?(f, __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features|rakelib)/|\.(?:git|travis|circleci)|appveyor|Rakefile)})
- end
- end
+ jruby = true if Gem::Platform.new('java') =~ spec.platform or RUBY_ENGINE == 'jruby'
+ dir, gemspec = File.split(__FILE__)
+ excludes = [
+ *%w[:^/.git* :^/Gemfile* :^/Rakefile* :^/bin/ :^/test/ :^/rakelib/ :^*.java],
+ *(jruby ? %w[:^/ext/io] : %w[:^/ext/java]),
+ ":(exclude,literal,top)#{gemspec}"
+ ]
+ files = IO.popen(%w[git ls-files -z --] + excludes, chdir: dir, &:read).split("\x0")
+
+ spec.files = files
spec.bindir = "exe"
spec.executables = []
spec.require_paths = ["lib"]
- jruby = true if Gem::Platform.new('java') =~ spec.platform or RUBY_ENGINE == 'jruby'
- spec.files.delete_if do |f|
- f.end_with?(".java") or
- f.start_with?("ext/") && (jruby ^ f.start_with?("ext/java/"))
- end
if jruby
spec.platform = 'java'
spec.files << "lib/io/wait.jar"
diff --git a/ext/io/wait/wait.c b/ext/io/wait/wait.c
index 8835670e59..f7575191fe 100644
--- a/ext/io/wait/wait.c
+++ b/ext/io/wait/wait.c
@@ -11,427 +11,13 @@
**********************************************************************/
-#include "ruby.h"
-#include "ruby/io.h"
-
-#include <sys/types.h>
-#if defined(HAVE_UNISTD_H) && (defined(__sun))
-#include <unistd.h>
-#endif
-#if defined(HAVE_SYS_IOCTL_H)
-#include <sys/ioctl.h>
-#endif
-#if defined(FIONREAD_HEADER)
-#include FIONREAD_HEADER
-#endif
-
-#ifdef HAVE_RB_W32_IOCTLSOCKET
-#define ioctl ioctlsocket
-#define ioctl_arg u_long
-#define ioctl_arg2num(i) ULONG2NUM(i)
-#else
-#define ioctl_arg int
-#define ioctl_arg2num(i) INT2NUM(i)
-#endif
-
-#ifdef HAVE_RB_W32_IS_SOCKET
-#define FIONREAD_POSSIBLE_P(fd) rb_w32_is_socket(fd)
-#else
-#define FIONREAD_POSSIBLE_P(fd) ((void)(fd),Qtrue)
-#endif
-
-#ifndef HAVE_RB_IO_WAIT
-static struct timeval *
-get_timeout(int argc, VALUE *argv, struct timeval *timerec)
-{
- VALUE timeout = Qnil;
- rb_check_arity(argc, 0, 1);
- if (!argc || NIL_P(timeout = argv[0])) {
- return NULL;
- }
- else {
- *timerec = rb_time_interval(timeout);
- return timerec;
- }
-}
-
-static int
-wait_for_single_fd(rb_io_t *fptr, int events, struct timeval *tv)
-{
- int i = rb_wait_for_single_fd(fptr->fd, events, tv);
- if (i < 0)
- rb_sys_fail(0);
- rb_io_check_closed(fptr);
- return (i & events);
-}
-#endif
-
-/*
- * call-seq:
- * io.nread -> int
- *
- * Returns number of bytes that can be read without blocking.
- * Returns zero if no information available.
- *
- * You must require 'io/wait' to use this method.
- */
-
-static VALUE
-io_nread(VALUE io)
-{
- rb_io_t *fptr;
- int len;
- ioctl_arg n;
-
- GetOpenFile(io, fptr);
- rb_io_check_readable(fptr);
- len = rb_io_read_pending(fptr);
- if (len > 0) return INT2FIX(len);
-
-#ifdef HAVE_RB_IO_DESCRIPTOR
- int fd = rb_io_descriptor(io);
-#else
- int fd = fptr->fd;
-#endif
-
- if (!FIONREAD_POSSIBLE_P(fd)) return INT2FIX(0);
- if (ioctl(fd, FIONREAD, &n)) return INT2FIX(0);
- if (n > 0) return ioctl_arg2num(n);
- return INT2FIX(0);
-}
-
-#ifdef HAVE_RB_IO_WAIT
-static VALUE
-io_wait_event(VALUE io, int event, VALUE timeout, int return_io)
-{
- VALUE result = rb_io_wait(io, RB_INT2NUM(event), timeout);
-
- if (!RB_TEST(result)) {
- return Qnil;
- }
-
- int mask = RB_NUM2INT(result);
-
- if (mask & event) {
- if (return_io)
- return io;
- else
- return result;
- }
- else {
- return Qfalse;
- }
-}
-#endif
-
-/*
- * call-seq:
- * io.ready? -> truthy or falsy
- *
- * Returns a truthy value if input available without blocking, or a
- * falsy value.
- *
- * You must require 'io/wait' to use this method.
- */
-
-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
- return wait_for_single_fd(fptr, RB_WAITFD_IN, &tv) ? Qtrue : Qfalse;
-#else
- return io_wait_event(io, RUBY_IO_READABLE, RB_INT2NUM(0), 1);
-#endif
-}
-
-/* Ruby 3.2+ can define these methods. This macro indicates that case. */
-#ifndef RUBY_IO_WAIT_METHODS
-
-/*
- * call-seq:
- * io.wait_readable -> truthy or falsy
- * io.wait_readable(timeout) -> truthy or falsy
- *
- * Waits until IO is readable and returns a truthy value, or a falsy
- * value when times out. Returns a truthy value immediately when
- * buffered data is available.
- *
- * You must require 'io/wait' to use this method.
- */
-
-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, 1);
-#endif
-}
+#include "ruby.h" /* abi_version */
/*
- * call-seq:
- * io.wait_writable -> truthy or falsy
- * io.wait_writable(timeout) -> truthy or falsy
- *
- * Waits until IO is writable and returns a truthy value or a falsy
- * value when times out.
- *
- * You must require 'io/wait' to use this method.
- */
-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, 1);
-#endif
-}
-
-#ifdef HAVE_RB_IO_WAIT
-/*
- * call-seq:
- * io.wait_priority -> truthy or falsy
- * io.wait_priority(timeout) -> truthy or falsy
- *
- * Waits until IO is priority and returns a truthy value or a falsy
- * value when times out. Priority data is sent and received using
- * the Socket::MSG_OOB flag and is typically limited to streams.
- *
- * You must require 'io/wait' to use this method.
- */
-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, 1);
-}
-#endif
-
-static int
-wait_mode_sym(VALUE mode)
-{
- if (mode == ID2SYM(rb_intern("r"))) {
- return RB_WAITFD_IN;
- }
- if (mode == ID2SYM(rb_intern("read"))) {
- return RB_WAITFD_IN;
- }
- if (mode == ID2SYM(rb_intern("readable"))) {
- return RB_WAITFD_IN;
- }
- if (mode == ID2SYM(rb_intern("w"))) {
- return RB_WAITFD_OUT;
- }
- if (mode == ID2SYM(rb_intern("write"))) {
- return RB_WAITFD_OUT;
- }
- if (mode == ID2SYM(rb_intern("writable"))) {
- return RB_WAITFD_OUT;
- }
- if (mode == ID2SYM(rb_intern("rw"))) {
- return RB_WAITFD_IN|RB_WAITFD_OUT;
- }
- if (mode == ID2SYM(rb_intern("read_write"))) {
- return RB_WAITFD_IN|RB_WAITFD_OUT;
- }
- if (mode == ID2SYM(rb_intern("readable_writable"))) {
- return RB_WAITFD_IN|RB_WAITFD_OUT;
- }
- rb_raise(rb_eArgError, "unsupported mode: %"PRIsVALUE, mode);
- return 0;
-}
-
-#ifdef HAVE_RB_IO_WAIT
-static inline rb_io_event_t
-io_event_from_value(VALUE value)
-{
- int events = RB_NUM2INT(value);
-
- if (events <= 0) rb_raise(rb_eArgError, "Events must be positive integer!");
-
- return events;
-}
-#endif
-
-/*
- * call-seq:
- * io.wait(events, timeout) -> event mask, false or nil
- * io.wait(timeout = nil, mode = :read) -> self, true, or false
- *
- * Waits until the IO becomes ready for the specified events and returns the
- * subset of events that become ready, or a falsy value when times out.
- *
- * The events can be a bit mask of +IO::READABLE+, +IO::WRITABLE+ or
- * +IO::PRIORITY+.
- *
- * Returns a truthy value immediately when buffered data is available.
- *
- * Optional parameter +mode+ is one of +:read+, +:write+, or
- * +:read_write+.
- *
- * You must require 'io/wait' to use this method.
- */
-
-static VALUE
-io_wait(int argc, VALUE *argv, VALUE io)
-{
-#ifndef HAVE_RB_IO_WAIT
- rb_io_t *fptr;
- struct timeval timerec;
- struct timeval *tv = NULL;
- int event = 0;
- int i;
-
- GetOpenFile(io, fptr);
- for (i = 0; i < argc; ++i) {
- if (SYMBOL_P(argv[i])) {
- event |= wait_mode_sym(argv[i]);
- }
- else {
- *(tv = &timerec) = rb_time_interval(argv[i]);
- }
- }
- /* rb_time_interval() and might_mode() might convert the argument */
- rb_io_check_closed(fptr);
- if (!event) event = RB_WAITFD_IN;
- if ((event & RB_WAITFD_IN) && rb_io_read_pending(fptr))
- return Qtrue;
- if (wait_for_single_fd(fptr, event, tv))
- return io;
- return Qnil;
-#else
- VALUE timeout = Qundef;
- rb_io_event_t events = 0;
- int i, return_io = 0;
-
- /* The documented signature for this method is actually incorrect.
- * A single timeout is allowed in any position, and multiple symbols can be given.
- * Whether this is intentional or not, I don't know, and as such I consider this to
- * be a legacy/slow path. */
- if (argc != 2 || (RB_SYMBOL_P(argv[0]) || RB_SYMBOL_P(argv[1]))) {
- /* We'd prefer to return the actual mask, but this form would return the io itself: */
- return_io = 1;
-
- /* Slow/messy path: */
- for (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;
-
- if (events == 0) {
- events = RUBY_IO_READABLE;
- }
- }
- else /* argc == 2 and neither are symbols */ {
- /* This is the fast path: */
- events = io_event_from_value(argv[0]);
- timeout = argv[1];
- }
-
- if (events & RUBY_IO_READABLE) {
- rb_io_t *fptr = NULL;
- RB_IO_POINTER(io, fptr);
-
- if (rb_io_read_pending(fptr)) {
- /* This was the original behaviour: */
- if (return_io) return Qtrue;
- /* New behaviour always returns an event mask: */
- else return RB_INT2NUM(RUBY_IO_READABLE);
- }
- }
-
- return io_wait_event(io, events, timeout, return_io);
-#endif
-}
-
-#endif /* RUBY_IO_WAIT_METHODS */
-
-/*
- * IO wait methods
+ * IO wait methods are built in ruby now, just for backward compatibility.
*/
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);
-
-#ifndef RUBY_IO_WAIT_METHODS
- 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
-#endif
}
diff --git a/ext/json/fbuffer/fbuffer.h b/ext/json/fbuffer/fbuffer.h
index dc8f406b5b..752d153b31 100644
--- a/ext/json/fbuffer/fbuffer.h
+++ b/ext/json/fbuffer/fbuffer.h
@@ -1,89 +1,71 @@
-
#ifndef _FBUFFER_H_
#define _FBUFFER_H_
-#include "ruby.h"
-
-#ifndef RHASH_SIZE
-#define RHASH_SIZE(hsh) (RHASH(hsh)->tbl->num_entries)
-#endif
-
-#ifndef RFLOAT_VALUE
-#define RFLOAT_VALUE(val) (RFLOAT(val)->value)
-#endif
-
-#ifndef RARRAY_LEN
-#define RARRAY_LEN(ARRAY) RARRAY(ARRAY)->len
-#endif
-#ifndef RSTRING_PTR
-#define RSTRING_PTR(string) RSTRING(string)->ptr
-#endif
-#ifndef RSTRING_LEN
-#define RSTRING_LEN(string) RSTRING(string)->len
-#endif
+#include "../json.h"
+#include "../vendor/jeaiii-ltoa.h"
-#ifdef PRIsVALUE
-# define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj)
-# define RB_OBJ_STRING(obj) (obj)
-#else
-# define PRIsVALUE "s"
-# define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj)
-# define RB_OBJ_STRING(obj) StringValueCStr(obj)
-#endif
-
-#ifdef HAVE_RUBY_ENCODING_H
-#include "ruby/encoding.h"
-#define FORCE_UTF8(obj) rb_enc_associate((obj), rb_utf8_encoding())
-#else
-#define FORCE_UTF8(obj)
-#endif
-
-/* We don't need to guard objects for rbx, so let's do nothing at all. */
-#ifndef RB_GC_GUARD
-#define RB_GC_GUARD(object)
-#endif
+enum fbuffer_type {
+ FBUFFER_HEAP_ALLOCATED = 0,
+ FBUFFER_STACK_ALLOCATED = 1,
+};
typedef struct FBufferStruct {
+ enum fbuffer_type type;
unsigned long initial_length;
- char *ptr;
unsigned long len;
unsigned long capa;
+#if JSON_DEBUG
+ unsigned long requested;
+#endif
+ char *ptr;
+ VALUE io;
} FBuffer;
+#define FBUFFER_STACK_SIZE 512
+#define FBUFFER_IO_BUFFER_SIZE (16384 - 1)
#define FBUFFER_INITIAL_LENGTH_DEFAULT 1024
-#define FBUFFER_PTR(fb) (fb->ptr)
-#define FBUFFER_LEN(fb) (fb->len)
-#define FBUFFER_CAPA(fb) (fb->capa)
+#define FBUFFER_PTR(fb) ((fb)->ptr)
+#define FBUFFER_LEN(fb) ((fb)->len)
+#define FBUFFER_CAPA(fb) ((fb)->capa)
#define FBUFFER_PAIR(fb) FBUFFER_PTR(fb), FBUFFER_LEN(fb)
-static FBuffer *fbuffer_alloc(unsigned long initial_length);
static void fbuffer_free(FBuffer *fb);
static void fbuffer_clear(FBuffer *fb);
static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len);
-#ifdef JSON_GENERATOR
static void fbuffer_append_long(FBuffer *fb, long number);
+static inline void fbuffer_append_char(FBuffer *fb, char newchr);
+static VALUE fbuffer_finalize(FBuffer *fb);
+
+static void fbuffer_stack_init(FBuffer *fb, unsigned long initial_length, char *stack_buffer, long stack_buffer_size)
+{
+ fb->initial_length = (initial_length > 0) ? initial_length : FBUFFER_INITIAL_LENGTH_DEFAULT;
+ if (stack_buffer) {
+ fb->type = FBUFFER_STACK_ALLOCATED;
+ fb->ptr = stack_buffer;
+ fb->capa = stack_buffer_size;
+ }
+#if JSON_DEBUG
+ fb->requested = 0;
#endif
-static void fbuffer_append_char(FBuffer *fb, char newchr);
-#ifdef JSON_GENERATOR
-static FBuffer *fbuffer_dup(FBuffer *fb);
-static VALUE fbuffer_to_s(FBuffer *fb);
-#endif
+}
-static FBuffer *fbuffer_alloc(unsigned long initial_length)
+static inline void fbuffer_consumed(FBuffer *fb, unsigned long consumed)
{
- FBuffer *fb;
- if (initial_length <= 0) initial_length = FBUFFER_INITIAL_LENGTH_DEFAULT;
- fb = ALLOC(FBuffer);
- memset((void *) fb, 0, sizeof(FBuffer));
- fb->initial_length = initial_length;
- return fb;
+#if JSON_DEBUG
+ if (consumed > fb->requested) {
+ rb_bug("fbuffer: Out of bound write");
+ }
+ fb->requested = 0;
+#endif
+ fb->len += consumed;
}
static void fbuffer_free(FBuffer *fb)
{
- if (fb->ptr) ruby_xfree(fb->ptr);
- ruby_xfree(fb);
+ if (fb->ptr && fb->type == FBUFFER_HEAP_ALLOCATED) {
+ ruby_xfree(fb->ptr);
+ }
}
static void fbuffer_clear(FBuffer *fb)
@@ -91,97 +73,175 @@ static void fbuffer_clear(FBuffer *fb)
fb->len = 0;
}
-static void fbuffer_inc_capa(FBuffer *fb, unsigned long requested)
+static void fbuffer_flush(FBuffer *fb)
+{
+ rb_io_write(fb->io, rb_utf8_str_new(fb->ptr, fb->len));
+ fbuffer_clear(fb);
+}
+
+static void fbuffer_realloc(FBuffer *fb, unsigned long required)
{
+ if (required > fb->capa) {
+ if (fb->type == FBUFFER_STACK_ALLOCATED) {
+ const char *old_buffer = fb->ptr;
+ fb->ptr = ALLOC_N(char, required);
+ fb->type = FBUFFER_HEAP_ALLOCATED;
+ MEMCPY(fb->ptr, old_buffer, char, fb->len);
+ } else {
+ REALLOC_N(fb->ptr, char, required);
+ }
+ fb->capa = required;
+ }
+}
+
+static void fbuffer_do_inc_capa(FBuffer *fb, unsigned long requested)
+{
+ if (RB_UNLIKELY(fb->io)) {
+ if (fb->capa < FBUFFER_IO_BUFFER_SIZE) {
+ fbuffer_realloc(fb, FBUFFER_IO_BUFFER_SIZE);
+ } else {
+ fbuffer_flush(fb);
+ }
+
+ if (RB_LIKELY(requested < fb->capa)) {
+ return;
+ }
+ }
+
unsigned long required;
- if (!fb->ptr) {
+ if (RB_UNLIKELY(!fb->ptr)) {
fb->ptr = ALLOC_N(char, fb->initial_length);
fb->capa = fb->initial_length;
}
for (required = fb->capa; requested > required - fb->len; required <<= 1);
- if (required > fb->capa) {
- REALLOC_N(fb->ptr, char, required);
- fb->capa = required;
+ fbuffer_realloc(fb, required);
+}
+
+static inline void fbuffer_inc_capa(FBuffer *fb, unsigned long requested)
+{
+#if JSON_DEBUG
+ fb->requested = requested;
+#endif
+
+ if (RB_UNLIKELY(requested > fb->capa - fb->len)) {
+ fbuffer_do_inc_capa(fb, requested);
}
}
-static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len)
+static inline void fbuffer_append_reserved(FBuffer *fb, const char *newstr, unsigned long len)
+{
+ MEMCPY(fb->ptr + fb->len, newstr, char, len);
+ fbuffer_consumed(fb, len);
+}
+
+static inline void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len)
{
if (len > 0) {
fbuffer_inc_capa(fb, len);
- MEMCPY(fb->ptr + fb->len, newstr, char, len);
- fb->len += len;
+ fbuffer_append_reserved(fb, newstr, len);
}
}
-#ifdef JSON_GENERATOR
+/* Appends a character into a buffer. The buffer needs to have sufficient capacity, via fbuffer_inc_capa(...). */
+static inline void fbuffer_append_reserved_char(FBuffer *fb, char chr)
+{
+#if JSON_DEBUG
+ if (fb->requested < 1) {
+ rb_bug("fbuffer: unreserved write");
+ }
+ fb->requested--;
+#endif
+
+ fb->ptr[fb->len] = chr;
+ fb->len++;
+}
+
static void fbuffer_append_str(FBuffer *fb, VALUE str)
{
const char *newstr = StringValuePtr(str);
unsigned long len = RSTRING_LEN(str);
- RB_GC_GUARD(str);
-
fbuffer_append(fb, newstr, len);
}
+
+static void fbuffer_append_str_repeat(FBuffer *fb, VALUE str, size_t repeat)
+{
+ const char *newstr = StringValuePtr(str);
+ unsigned long len = RSTRING_LEN(str);
+
+ fbuffer_inc_capa(fb, repeat * len);
+ while (repeat) {
+#if JSON_DEBUG
+ fb->requested = len;
#endif
+ fbuffer_append_reserved(fb, newstr, len);
+ repeat--;
+ }
+}
-static void fbuffer_append_char(FBuffer *fb, char newchr)
+static inline void fbuffer_append_char(FBuffer *fb, char newchr)
{
fbuffer_inc_capa(fb, 1);
*(fb->ptr + fb->len) = newchr;
- fb->len++;
+ fbuffer_consumed(fb, 1);
}
-#ifdef JSON_GENERATOR
-static void freverse(char *start, char *end)
+static inline char *fbuffer_cursor(FBuffer *fb)
{
- char c;
-
- while (end > start) {
- c = *end, *end-- = *start, *start++ = c;
- }
+ return fb->ptr + fb->len;
}
-static long fltoa(long number, char *buf)
+static inline void fbuffer_advance_to(FBuffer *fb, char *end)
{
- static char digits[] = "0123456789";
- long sign = number;
- char* tmp = buf;
-
- if (sign < 0) number = -number;
- do *tmp++ = digits[number % 10]; while (number /= 10);
- if (sign < 0) *tmp++ = '-';
- freverse(buf, tmp - 1);
- return tmp - buf;
+ fbuffer_consumed(fb, (end - fb->ptr) - fb->len);
}
+/*
+ * Appends the decimal string representation of \a number into the buffer.
+ */
static void fbuffer_append_long(FBuffer *fb, long number)
{
- char buf[20];
- unsigned long len = fltoa(number, buf);
- fbuffer_append(fb, buf, len);
-}
-
-static FBuffer *fbuffer_dup(FBuffer *fb)
-{
- unsigned long len = fb->len;
- FBuffer *result;
+ /*
+ * The jeaiii_ultoa() function produces digits left-to-right,
+ * allowing us to write directly into the buffer, but we don't know
+ * the number of resulting characters.
+ *
+ * We do know, however, that the `number` argument is always in the
+ * range 0xc000000000000000 to 0x3fffffffffffffff, or, in decimal,
+ * -4611686018427387904 to 4611686018427387903. The max number of chars
+ * generated is therefore 20 (including a potential sign character).
+ */
+
+ static const int MAX_CHARS_FOR_LONG = 20;
+
+ fbuffer_inc_capa(fb, MAX_CHARS_FOR_LONG);
+
+ if (number < 0) {
+ fbuffer_append_reserved_char(fb, '-');
+
+ /*
+ * Since number is always > LONG_MIN, `-number` will not overflow
+ * and is always the positive abs() value.
+ */
+ number = -number;
+ }
- result = fbuffer_alloc(len);
- fbuffer_append(result, FBUFFER_PAIR(fb));
- return result;
+ char *end = jeaiii_ultoa(fbuffer_cursor(fb), number);
+ fbuffer_advance_to(fb, end);
}
-static VALUE fbuffer_to_s(FBuffer *fb)
+static VALUE fbuffer_finalize(FBuffer *fb)
{
- VALUE result = rb_str_new(FBUFFER_PTR(fb), FBUFFER_LEN(fb));
- fbuffer_free(fb);
- FORCE_UTF8(result);
- return result;
+ if (fb->io) {
+ fbuffer_flush(fb);
+ rb_io_flush(fb->io);
+ return fb->io;
+ } else {
+ return rb_utf8_str_new(FBUFFER_PTR(fb), FBUFFER_LEN(fb));
+ }
}
-#endif
-#endif
+
+#endif // _FBUFFER_H_
diff --git a/ext/json/generator/depend b/ext/json/generator/depend
index f47e5f3a70..3ba4acfdd2 100644
--- a/ext/json/generator/depend
+++ b/ext/json/generator/depend
@@ -1,5 +1,5 @@
$(OBJS): $(ruby_headers)
-generator.o: generator.c generator.h $(srcdir)/../fbuffer/fbuffer.h
+generator.o: generator.c $(srcdir)/../fbuffer/fbuffer.h
# AUTOGENERATED DEPENDENCIES START
generator.o: $(RUBY_EXTCONF_H)
@@ -142,6 +142,7 @@ generator.o: $(hdrdir)/ruby/internal/intern/re.h
generator.o: $(hdrdir)/ruby/internal/intern/ruby.h
generator.o: $(hdrdir)/ruby/internal/intern/select.h
generator.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+generator.o: $(hdrdir)/ruby/internal/intern/set.h
generator.o: $(hdrdir)/ruby/internal/intern/signal.h
generator.o: $(hdrdir)/ruby/internal/intern/sprintf.h
generator.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -177,6 +178,9 @@ generator.o: $(hdrdir)/ruby/ruby.h
generator.o: $(hdrdir)/ruby/st.h
generator.o: $(hdrdir)/ruby/subst.h
generator.o: $(srcdir)/../fbuffer/fbuffer.h
+generator.o: $(srcdir)/../json.h
+generator.o: $(srcdir)/../simd/simd.h
+generator.o: $(srcdir)/../vendor/fpconv.c
+generator.o: $(srcdir)/../vendor/jeaiii-ltoa.h
generator.o: generator.c
-generator.o: generator.h
# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/json/generator/extconf.rb b/ext/json/generator/extconf.rb
index 8627c5f4bd..ee1bbeaba7 100644
--- a/ext/json/generator/extconf.rb
+++ b/ext/json/generator/extconf.rb
@@ -1,4 +1,16 @@
require 'mkmf'
-$defs << "-DJSON_GENERATOR"
-create_makefile 'json/ext/generator'
+if RUBY_ENGINE == 'truffleruby'
+ # The pure-Ruby generator is faster on TruffleRuby, so skip compiling the generator extension
+ File.write('Makefile', dummy_makefile("").join)
+else
+ append_cflags("-std=c99")
+ $defs << "-DJSON_GENERATOR"
+ $defs << "-DJSON_DEBUG" if ENV.fetch("JSON_DEBUG", "0") != "0"
+
+ if enable_config('generator-use-simd', default=!ENV["JSON_DISABLE_SIMD"])
+ load __dir__ + "/../simd/conf.rb"
+ end
+
+ create_makefile 'json/ext/generator'
+end
diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c
index 6d78284bc4..dbba99c455 100644
--- a/ext/json/generator/generator.c
+++ b/ext/json/generator/generator.c
@@ -1,340 +1,706 @@
+#include "../json.h"
#include "../fbuffer/fbuffer.h"
-#include "generator.h"
+#include "../vendor/fpconv.c"
-static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject,
- mHash, mArray,
+#include <math.h>
+#include <ctype.h>
+
+#include "../simd/simd.h"
+
+/* ruby api and some helpers */
+
+enum duplicate_key_action {
+ JSON_DEPRECATED = 0,
+ JSON_IGNORE,
+ JSON_RAISE,
+};
+
+typedef struct JSON_Generator_StateStruct {
+ VALUE indent;
+ VALUE space;
+ VALUE space_before;
+ VALUE object_nl;
+ VALUE array_nl;
+ VALUE as_json;
+
+ long max_nesting;
+ long depth;
+ long buffer_initial_length;
+
+ enum duplicate_key_action on_duplicate_key;
+
+ bool as_json_single_arg;
+ bool allow_nan;
+ bool ascii_only;
+ bool script_safe;
+ bool strict;
+} JSON_Generator_State;
+
+static VALUE mJSON, cState, cFragment, eGeneratorError, eNestingError, Encoding_UTF_8;
+
+static ID i_to_s, i_to_json, i_new, i_encode;
+static VALUE sym_indent, sym_space, sym_space_before, sym_object_nl, sym_array_nl, sym_max_nesting, sym_allow_nan, sym_allow_duplicate_key,
+ sym_ascii_only, sym_depth, sym_buffer_initial_length, sym_script_safe, sym_escape_slash, sym_strict, sym_as_json;
+
+
+#define GET_STATE_TO(self, state) \
+ TypedData_Get_Struct(self, JSON_Generator_State, &JSON_Generator_State_type, state)
+
+#define GET_STATE(self) \
+ JSON_Generator_State *state; \
+ GET_STATE_TO(self, state)
+
+struct generate_json_data;
+
+typedef void (*generator_func)(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
+
+struct generate_json_data {
+ FBuffer *buffer;
+ VALUE vstate;
+ JSON_Generator_State *state;
+ VALUE obj;
+ generator_func func;
+ long depth;
+};
+
+static SIMD_Implementation simd_impl;
+
+static VALUE cState_from_state_s(VALUE self, VALUE opts);
+static VALUE cState_partial_generate(VALUE self, VALUE obj, generator_func, VALUE io);
+static void generate_json(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
+static void generate_json_object(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
+static void generate_json_array(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
+static void generate_json_string(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
+static void generate_json_null(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
+static void generate_json_false(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
+static void generate_json_true(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
#ifdef RUBY_INTEGER_UNIFICATION
- mInteger,
-#else
- mFixnum, mBignum,
+static void generate_json_integer(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
#endif
- mFloat, mString, mString_Extend,
- mTrueClass, mFalseClass, mNilClass, eGeneratorError,
- eNestingError;
+static void generate_json_fixnum(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
+static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
+static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
+static void generate_json_fragment(FBuffer *buffer, struct generate_json_data *data, VALUE obj);
-static 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_script_safe, i_escape_slash, i_strict;
+static int usascii_encindex, utf8_encindex, binary_encindex;
-/*
- * Copyright 2001-2004 Unicode, Inc.
+NORETURN(static void) raise_generator_error_str(VALUE invalid_object, VALUE str)
+{
+ rb_enc_associate_index(str, utf8_encindex);
+ VALUE exc = rb_exc_new_str(eGeneratorError, str);
+ rb_ivar_set(exc, rb_intern("@invalid_object"), invalid_object);
+ rb_exc_raise(exc);
+}
+
+#ifdef RBIMPL_ATTR_FORMAT
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3)
+#endif
+NORETURN(static void) raise_generator_error(VALUE invalid_object, const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ VALUE str = rb_vsprintf(fmt, args);
+ va_end(args);
+ raise_generator_error_str(invalid_object, str);
+}
+
+// 0 - single byte char that don't need to be escaped.
+// (x | 8) - char that needs to be escaped.
+static const unsigned char CHAR_LENGTH_MASK = 7;
+static const unsigned char ESCAPE_MASK = 8;
+
+typedef struct _search_state {
+ const char *ptr;
+ const char *end;
+ const char *cursor;
+ FBuffer *buffer;
+
+#ifdef HAVE_SIMD
+ const char *chunk_base;
+ const char *chunk_end;
+ bool has_matches;
+
+#if defined(HAVE_SIMD_NEON)
+ uint64_t matches_mask;
+#elif defined(HAVE_SIMD_SSE2)
+ int matches_mask;
+#else
+#error "Unknown SIMD Implementation."
+#endif /* HAVE_SIMD_NEON */
+#endif /* HAVE_SIMD */
+} search_state;
+
+ALWAYS_INLINE(static) void search_flush(search_state *search)
+{
+ // Do not remove this conditional without profiling, specifically escape-heavy text.
+ // escape_UTF8_char_basic will advance search->ptr and search->cursor (effectively a search_flush).
+ // For back-to-back characters that need to be escaped, specifically for the SIMD code paths, this method
+ // will be called just before calling escape_UTF8_char_basic. There will be no characters to append for the
+ // consecutive characters that need to be escaped. While the fbuffer_append is a no-op if
+ // nothing needs to be flushed, we can save a few memory references with this conditional.
+ if (search->ptr > search->cursor) {
+ fbuffer_append(search->buffer, search->cursor, search->ptr - search->cursor);
+ search->cursor = search->ptr;
+ }
+}
+
+static const unsigned char escape_table_basic[256] = {
+ // ASCII Control Characters
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ // ASCII Characters
+ 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // '"'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, // '\\'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static inline unsigned char search_escape_basic(search_state *search)
+{
+ while (search->ptr < search->end) {
+ if (RB_UNLIKELY(escape_table_basic[(const unsigned char)*search->ptr])) {
+ search_flush(search);
+ return 1;
+ } else {
+ search->ptr++;
+ }
+ }
+ search_flush(search);
+ return 0;
+}
+
+ALWAYS_INLINE(static) void escape_UTF8_char_basic(search_state *search)
+{
+ const unsigned char ch = (unsigned char)*search->ptr;
+ switch (ch) {
+ case '"': fbuffer_append(search->buffer, "\\\"", 2); break;
+ case '\\': fbuffer_append(search->buffer, "\\\\", 2); break;
+ case '/': fbuffer_append(search->buffer, "\\/", 2); break;
+ case '\b': fbuffer_append(search->buffer, "\\b", 2); break;
+ case '\f': fbuffer_append(search->buffer, "\\f", 2); break;
+ case '\n': fbuffer_append(search->buffer, "\\n", 2); break;
+ case '\r': fbuffer_append(search->buffer, "\\r", 2); break;
+ case '\t': fbuffer_append(search->buffer, "\\t", 2); break;
+ default: {
+ const char *hexdig = "0123456789abcdef";
+ char scratch[6] = { '\\', 'u', '0', '0', 0, 0 };
+ scratch[4] = hexdig[(ch >> 4) & 0xf];
+ scratch[5] = hexdig[ch & 0xf];
+ fbuffer_append(search->buffer, scratch, 6);
+ break;
+ }
+ }
+ search->ptr++;
+ search->cursor = search->ptr;
+}
+
+/* Converts in_string to a JSON string (without the wrapping '"'
+ * characters) in FBuffer out_buffer.
+ *
+ * Character are JSON-escaped according to:
*
- * Disclaimer
+ * - Always: ASCII control characters (0x00-0x1F), dquote, and
+ * backslash.
*
- * This source code is provided as is by Unicode, Inc. No claims are
- * made as to fitness for any particular purpose. No warranties of any
- * kind are expressed or implied. The recipient agrees to determine
- * applicability of information provided. If this file has been
- * purchased on magnetic or optical media from Unicode, Inc., the
- * sole remedy for any claim will be exchange of defective media
- * within 90 days of receipt.
+ * - If out_ascii_only: non-ASCII characters (>0x7F)
*
- * Limitations on Rights to Redistribute This Code
+ * - If script_safe: forwardslash (/), line separator (U+2028), and
+ * paragraph separator (U+2029)
*
- * Unicode, Inc. hereby grants the right to freely use the information
- * supplied in this file in the creation of products supporting the
- * Unicode Standard, and to make copies of this file in any form
- * for internal or external distribution as long as this notice
- * remains attached.
+ * Everything else (should be UTF-8) is just passed through and
+ * appended to the result.
*/
-/*
- * Index into the table below with the first byte of a UTF-8 sequence to
- * get the number of trailing bytes that are supposed to follow it.
- * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is
- * left as-is for anyone who may want to do such conversion, which was
- * allowed in earlier algorithms.
- */
-static const char trailingBytesForUTF8[256] = {
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
- 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
- 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
-};
-/*
- * Magic values subtracted from a buffer value during UTF8 conversion.
- * This table contains as many values as there might be trailing bytes
- * in a UTF-8 sequence.
- */
-static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
- 0x03C82080UL, 0xFA082080UL, 0x82082080UL };
+#if defined(HAVE_SIMD_NEON)
+static inline unsigned char search_escape_basic_neon(search_state *search);
+#elif defined(HAVE_SIMD_SSE2)
+static inline unsigned char search_escape_basic_sse2(search_state *search);
+#endif
-/*
- * Utility routine to tell whether a sequence of bytes is legal UTF-8.
- * This must be called with the length pre-determined by the first byte.
- * If not calling this from ConvertUTF8to*, then the length can be set by:
- * length = trailingBytesForUTF8[*source]+1;
- * and the sequence is illegal right away if there aren't that many bytes
- * available.
- * If presented with a length > 4, this returns 0. The Unicode
- * definition of UTF-8 goes up to 4-byte sequences.
- */
-static unsigned char isLegalUTF8(const UTF8 *source, unsigned long length)
-{
- UTF8 a;
- const UTF8 *srcptr = source+length;
- switch (length) {
- default: return 0;
- /* Everything else falls through when "1"... */
- case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0;
- case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0;
- case 2: if ((a = (*--srcptr)) > 0xBF) return 0;
-
- switch (*source) {
- /* no fall-through in this inner switch */
- case 0xE0: if (a < 0xA0) return 0; break;
- case 0xED: if (a > 0x9F) return 0; break;
- case 0xF0: if (a < 0x90) return 0; break;
- case 0xF4: if (a > 0x8F) return 0; break;
- default: if (a < 0x80) return 0;
- }
+static inline unsigned char search_escape_basic(search_state *search);
- case 1: if (*source >= 0x80 && *source < 0xC2) return 0;
+static inline void convert_UTF8_to_JSON(search_state *search)
+{
+#ifdef HAVE_SIMD
+#if defined(HAVE_SIMD_NEON)
+ while (search_escape_basic_neon(search)) {
+ escape_UTF8_char_basic(search);
}
- if (*source > 0xF4) return 0;
- return 1;
+#elif defined(HAVE_SIMD_SSE2)
+ if (simd_impl == SIMD_SSE2) {
+ while (search_escape_basic_sse2(search)) {
+ escape_UTF8_char_basic(search);
+ }
+ return;
+ }
+ while (search_escape_basic(search)) {
+ escape_UTF8_char_basic(search);
+ }
+#endif
+#else
+ while (search_escape_basic(search)) {
+ escape_UTF8_char_basic(search);
+ }
+#endif /* HAVE_SIMD */
+}
+
+static inline void escape_UTF8_char(search_state *search, unsigned char ch_len)
+{
+ const unsigned char ch = (unsigned char)*search->ptr;
+ switch (ch_len) {
+ case 1: {
+ switch (ch) {
+ case '"': fbuffer_append(search->buffer, "\\\"", 2); break;
+ case '\\': fbuffer_append(search->buffer, "\\\\", 2); break;
+ case '/': fbuffer_append(search->buffer, "\\/", 2); break;
+ case '\b': fbuffer_append(search->buffer, "\\b", 2); break;
+ case '\f': fbuffer_append(search->buffer, "\\f", 2); break;
+ case '\n': fbuffer_append(search->buffer, "\\n", 2); break;
+ case '\r': fbuffer_append(search->buffer, "\\r", 2); break;
+ case '\t': fbuffer_append(search->buffer, "\\t", 2); break;
+ default: {
+ const char *hexdig = "0123456789abcdef";
+ char scratch[6] = { '\\', 'u', '0', '0', 0, 0 };
+ scratch[4] = hexdig[(ch >> 4) & 0xf];
+ scratch[5] = hexdig[ch & 0xf];
+ fbuffer_append(search->buffer, scratch, 6);
+ break;
+ }
+ }
+ break;
+ }
+ case 3: {
+ if (search->ptr[2] & 1) {
+ fbuffer_append(search->buffer, "\\u2029", 6);
+ } else {
+ fbuffer_append(search->buffer, "\\u2028", 6);
+ }
+ break;
+ }
+ }
+ search->cursor = (search->ptr += ch_len);
}
-/* Escapes the UTF16 character and stores the result in the buffer buf. */
-static void unicode_escape(char *buf, UTF16 character)
+#ifdef HAVE_SIMD
+
+ALWAYS_INLINE(static) char *copy_remaining_bytes(search_state *search, unsigned long vec_len, unsigned long len)
{
- const char *digits = "0123456789abcdef";
+ RBIMPL_ASSERT_OR_ASSUME(len < vec_len);
+
+ // Flush the buffer so everything up until the last 'len' characters are unflushed.
+ search_flush(search);
+
+ FBuffer *buf = search->buffer;
+ fbuffer_inc_capa(buf, vec_len);
+
+ char *s = (buf->ptr + buf->len);
- buf[2] = digits[character >> 12];
- buf[3] = digits[(character >> 8) & 0xf];
- buf[4] = digits[(character >> 4) & 0xf];
- buf[5] = digits[character & 0xf];
+ // Pad the buffer with dummy characters that won't need escaping.
+ // This seem wasteful at first sight, but memset of vector length is very fast.
+ // This is a space as it can be directly represented as an immediate on AArch64.
+ memset(s, ' ', vec_len);
+
+ // Optimistically copy the remaining 'len' characters to the output FBuffer. If there are no characters
+ // to escape, then everything ends up in the correct spot. Otherwise it was convenient temporary storage.
+ if (vec_len == 16) {
+ RBIMPL_ASSERT_OR_ASSUME(len >= SIMD_MINIMUM_THRESHOLD);
+ json_fast_memcpy16(s, search->ptr, len);
+ } else {
+ MEMCPY(s, search->ptr, char, len);
+ }
+
+ return s;
}
-/* Escapes the UTF16 character and stores the result in the buffer buf, then
- * the buffer buf is appended to the FBuffer buffer. */
-static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16
- character)
+#ifdef HAVE_SIMD_NEON
+
+ALWAYS_INLINE(static) unsigned char neon_next_match(search_state *search)
{
- unicode_escape(buf, character);
- fbuffer_append(buffer, buf, 6);
+ uint64_t mask = search->matches_mask;
+ uint32_t index = trailing_zeros64(mask) >> 2;
+
+ // It is assumed escape_UTF8_char_basic will only ever increase search->ptr by at most one character.
+ // If we want to use a similar approach for full escaping we'll need to ensure:
+ // search->chunk_base + index >= search->ptr
+ // However, since we know escape_UTF8_char_basic only increases search->ptr by one, if the next match
+ // is one byte after the previous match then:
+ // search->chunk_base + index == search->ptr
+ search->ptr = search->chunk_base + index;
+ mask &= mask - 1;
+ search->matches_mask = mask;
+ search_flush(search);
+ return 1;
}
-/* Converts string to a JSON string in FBuffer buffer, where all but the ASCII
- * and control characters are JSON escaped. */
-static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char script_safe)
+static inline unsigned char search_escape_basic_neon(search_state *search)
{
- const UTF8 *source = (UTF8 *) RSTRING_PTR(string);
- const UTF8 *sourceEnd = source + RSTRING_LEN(string);
- char buf[6] = { '\\', 'u' };
-
- while (source < sourceEnd) {
- UTF32 ch = 0;
- unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
- if (source + extraBytesToRead >= sourceEnd) {
- rb_raise(rb_path2class("JSON::GeneratorError"),
- "partial character in source, but hit end");
- }
- if (!isLegalUTF8(source, extraBytesToRead+1)) {
- rb_raise(rb_path2class("JSON::GeneratorError"),
- "source sequence is illegal/malformed utf-8");
+ if (RB_UNLIKELY(search->has_matches)) {
+ // There are more matches if search->matches_mask > 0.
+ if (search->matches_mask > 0) {
+ return neon_next_match(search);
+ } else {
+ // neon_next_match will only advance search->ptr up to the last matching character.
+ // Skip over any characters in the last chunk that occur after the last match.
+ search->has_matches = false;
+ search->ptr = search->chunk_end;
}
- /*
- * The cases all fall through. See "Note A" below.
- */
- switch (extraBytesToRead) {
- case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
- case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
- case 3: ch += *source++; ch <<= 6;
- case 2: ch += *source++; ch <<= 6;
- case 1: ch += *source++; ch <<= 6;
- case 0: ch += *source++;
+ }
+
+ /*
+ * The code below implements an SIMD-based algorithm to determine if N bytes at a time
+ * need to be escaped.
+ *
+ * Assume the ptr = "Te\sting!" (the double quotes are included in the string)
+ *
+ * The explanation will be limited to the first 8 bytes of the string for simplicity. However
+ * the vector insructions may work on larger vectors.
+ *
+ * First, we load three constants 'lower_bound', 'backslash' and 'dblquote" in vector registers.
+ *
+ * lower_bound: [20 20 20 20 20 20 20 20]
+ * backslash: [5C 5C 5C 5C 5C 5C 5C 5C]
+ * dblquote: [22 22 22 22 22 22 22 22]
+ *
+ * Next we load the first chunk of the ptr:
+ * [22 54 65 5C 73 74 69 6E] (" T e \ s t i n)
+ *
+ * First we check if any byte in chunk is less than 32 (0x20). This returns the following vector
+ * as no bytes are less than 32 (0x20):
+ * [0 0 0 0 0 0 0 0]
+ *
+ * Next, we check if any byte in chunk is equal to a backslash:
+ * [0 0 0 FF 0 0 0 0]
+ *
+ * Finally we check if any byte in chunk is equal to a double quote:
+ * [FF 0 0 0 0 0 0 0]
+ *
+ * Now we have three vectors where each byte indicates if the corresponding byte in chunk
+ * needs to be escaped. We combine these vectors with a series of logical OR instructions.
+ * This is the needs_escape vector and it is equal to:
+ * [FF 0 0 FF 0 0 0 0]
+ *
+ * Next we compute the bitwise AND between each byte and 0x1 and compute the horizontal sum of
+ * the values in the vector. This computes how many bytes need to be escaped within this chunk.
+ *
+ * Finally we compute a mask that indicates which bytes need to be escaped. If the mask is 0 then,
+ * no bytes need to be escaped and we can continue to the next chunk. If the mask is not 0 then we
+ * have at least one byte that needs to be escaped.
+ */
+
+ if (string_scan_simd_neon(&search->ptr, search->end, &search->matches_mask)) {
+ search->has_matches = true;
+ search->chunk_base = search->ptr;
+ search->chunk_end = search->ptr + sizeof(uint8x16_t);
+ return neon_next_match(search);
+ }
+
+ // There are fewer than 16 bytes left.
+ unsigned long remaining = (search->end - search->ptr);
+ if (remaining >= SIMD_MINIMUM_THRESHOLD) {
+ char *s = copy_remaining_bytes(search, sizeof(uint8x16_t), remaining);
+
+ uint64_t mask = compute_chunk_mask_neon(s);
+
+ if (!mask) {
+ // Nothing to escape, ensure search_flush doesn't do anything by setting
+ // search->cursor to search->ptr.
+ fbuffer_consumed(search->buffer, remaining);
+ search->ptr = search->end;
+ search->cursor = search->end;
+ return 0;
}
- ch -= offsetsFromUTF8[extraBytesToRead];
-
- if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
- /* UTF-16 surrogate values are illegal in UTF-32 */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
-#if UNI_STRICT_CONVERSION
- source -= (extraBytesToRead+1); /* return to the illegal value itself */
- rb_raise(rb_path2class("JSON::GeneratorError"),
- "source sequence is illegal/malformed utf-8");
+
+ search->matches_mask = mask;
+ search->has_matches = true;
+ search->chunk_end = search->end;
+ search->chunk_base = search->ptr;
+ return neon_next_match(search);
+ }
+
+ if (search->ptr < search->end) {
+ return search_escape_basic(search);
+ }
+
+ search_flush(search);
+ return 0;
+}
+#endif /* HAVE_SIMD_NEON */
+
+#ifdef HAVE_SIMD_SSE2
+
+ALWAYS_INLINE(static) unsigned char sse2_next_match(search_state *search)
+{
+ int mask = search->matches_mask;
+ int index = trailing_zeros(mask);
+
+ // It is assumed escape_UTF8_char_basic will only ever increase search->ptr by at most one character.
+ // If we want to use a similar approach for full escaping we'll need to ensure:
+ // search->chunk_base + index >= search->ptr
+ // However, since we know escape_UTF8_char_basic only increases search->ptr by one, if the next match
+ // is one byte after the previous match then:
+ // search->chunk_base + index == search->ptr
+ search->ptr = search->chunk_base + index;
+ mask &= mask - 1;
+ search->matches_mask = mask;
+ search_flush(search);
+ return 1;
+}
+
+#if defined(__clang__) || defined(__GNUC__)
+#define TARGET_SSE2 __attribute__((target("sse2")))
#else
- unicode_escape_to_buffer(buffer, buf, UNI_REPLACEMENT_CHAR);
+#define TARGET_SSE2
#endif
+
+ALWAYS_INLINE(static) TARGET_SSE2 unsigned char search_escape_basic_sse2(search_state *search)
+{
+ if (RB_UNLIKELY(search->has_matches)) {
+ // There are more matches if search->matches_mask > 0.
+ if (search->matches_mask > 0) {
+ return sse2_next_match(search);
+ } else {
+ // sse2_next_match will only advance search->ptr up to the last matching character.
+ // Skip over any characters in the last chunk that occur after the last match.
+ search->has_matches = false;
+ if (RB_UNLIKELY(search->chunk_base + sizeof(__m128i) >= search->end)) {
+ search->ptr = search->end;
} else {
- /* normal case */
- if (ch >= 0x20 && ch <= 0x7f) {
- switch (ch) {
- case '\\':
- fbuffer_append(buffer, "\\\\", 2);
- break;
- case '"':
- fbuffer_append(buffer, "\\\"", 2);
- break;
- case '/':
- if(script_safe) {
- fbuffer_append(buffer, "\\/", 2);
- break;
- }
- default:
- fbuffer_append_char(buffer, (char)ch);
- break;
- }
- } else {
- switch (ch) {
- case '\n':
- fbuffer_append(buffer, "\\n", 2);
- break;
- case '\r':
- fbuffer_append(buffer, "\\r", 2);
- break;
- case '\t':
- fbuffer_append(buffer, "\\t", 2);
- break;
- case '\f':
- fbuffer_append(buffer, "\\f", 2);
- break;
- case '\b':
- fbuffer_append(buffer, "\\b", 2);
- break;
- default:
- unicode_escape_to_buffer(buffer, buf, (UTF16) ch);
- break;
+ search->ptr = search->chunk_base + sizeof(__m128i);
+ }
+ }
+ }
+
+ if (string_scan_simd_sse2(&search->ptr, search->end, &search->matches_mask)) {
+ search->has_matches = true;
+ search->chunk_base = search->ptr;
+ search->chunk_end = search->ptr + sizeof(__m128i);
+ return sse2_next_match(search);
+ }
+
+ // There are fewer than 16 bytes left.
+ unsigned long remaining = (search->end - search->ptr);
+ if (remaining >= SIMD_MINIMUM_THRESHOLD) {
+ char *s = copy_remaining_bytes(search, sizeof(__m128i), remaining);
+
+ int needs_escape_mask = compute_chunk_mask_sse2(s);
+
+ if (needs_escape_mask == 0) {
+ // Nothing to escape, ensure search_flush doesn't do anything by setting
+ // search->cursor to search->ptr.
+ fbuffer_consumed(search->buffer, remaining);
+ search->ptr = search->end;
+ search->cursor = search->end;
+ return 0;
+ }
+
+ search->has_matches = true;
+ search->matches_mask = needs_escape_mask;
+ search->chunk_base = search->ptr;
+ return sse2_next_match(search);
+ }
+
+ if (search->ptr < search->end) {
+ return search_escape_basic(search);
+ }
+
+ search_flush(search);
+ return 0;
+}
+
+#endif /* HAVE_SIMD_SSE2 */
+
+#endif /* HAVE_SIMD */
+
+static const unsigned char script_safe_escape_table[256] = {
+ // ASCII Control Characters
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ // ASCII Characters
+ 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, // '"' and '/'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, // '\\'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ // Continuation byte
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ // First byte of a 2-byte code point
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ // First byte of a 3-byte code point
+ 3, 3,11, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xE2 is the start of \u2028 and \u2029
+ //First byte of a 4+ byte code point
+ 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 9, 9,
+};
+
+static inline unsigned char search_script_safe_escape(search_state *search)
+{
+ while (search->ptr < search->end) {
+ unsigned char ch = (unsigned char)*search->ptr;
+ unsigned char ch_len = script_safe_escape_table[ch];
+
+ if (RB_UNLIKELY(ch_len)) {
+ if (ch_len & ESCAPE_MASK) {
+ if (RB_UNLIKELY(ch_len == 11)) {
+ const unsigned char *uptr = (const unsigned char *)search->ptr;
+ if (!(uptr[1] == 0x80 && (uptr[2] >> 1) == 0x54)) {
+ search->ptr += 3;
+ continue;
}
}
+ search_flush(search);
+ return ch_len & CHAR_LENGTH_MASK;
+ } else {
+ search->ptr += ch_len;
}
- } else if (ch > UNI_MAX_UTF16) {
-#if UNI_STRICT_CONVERSION
- source -= (extraBytesToRead+1); /* return to the start */
- rb_raise(rb_path2class("JSON::GeneratorError"),
- "source sequence is illegal/malformed utf8");
-#else
- unicode_escape_to_buffer(buffer, buf, UNI_REPLACEMENT_CHAR);
-#endif
} else {
- /* target is a character in range 0xFFFF - 0x10FFFF. */
- ch -= halfBase;
- unicode_escape_to_buffer(buffer, buf, (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START));
- unicode_escape_to_buffer(buffer, buf, (UTF16)((ch & halfMask) + UNI_SUR_LOW_START));
+ search->ptr++;
}
}
- RB_GC_GUARD(string);
-}
-
-/* Converts string to a JSON string in FBuffer buffer, where only the
- * characters required by the JSON standard are JSON escaped. The remaining
- * characters (should be UTF8) are just passed through and appended to the
- * result. */
-static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char script_safe)
-{
- const char *ptr = RSTRING_PTR(string), *p;
- unsigned long len = RSTRING_LEN(string), start = 0, end = 0;
- const char *escape = NULL;
- int escape_len;
- unsigned char c;
- char buf[6] = { '\\', 'u' };
- int ascii_only = rb_enc_str_asciionly_p(string);
-
- for (start = 0, end = 0; end < len;) {
- p = ptr + end;
- c = (unsigned char) *p;
- if (c < 0x20) {
- switch (c) {
- case '\n':
- escape = "\\n";
- escape_len = 2;
- break;
- case '\r':
- escape = "\\r";
- escape_len = 2;
- break;
- case '\t':
- escape = "\\t";
- escape_len = 2;
- break;
- case '\f':
- escape = "\\f";
- escape_len = 2;
- break;
- case '\b':
- escape = "\\b";
- escape_len = 2;
- break;
- default:
- unicode_escape(buf, (UTF16) *p);
- escape = buf;
- escape_len = 6;
+ search_flush(search);
+ return 0;
+}
+
+static void convert_UTF8_to_script_safe_JSON(search_state *search)
+{
+ unsigned char ch_len;
+ while ((ch_len = search_script_safe_escape(search))) {
+ escape_UTF8_char(search, ch_len);
+ }
+}
+
+static const unsigned char ascii_only_escape_table[256] = {
+ // ASCII Control Characters
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ // ASCII Characters
+ 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // '"'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, // '\\'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ // Continuation byte
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ // First byte of a 2-byte code point
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ // First byte of a 3-byte code point
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ //First byte of a 4+ byte code point
+ 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 9, 9,
+};
+
+static inline unsigned char search_ascii_only_escape(search_state *search, const unsigned char escape_table[256])
+{
+ while (search->ptr < search->end) {
+ unsigned char ch = (unsigned char)*search->ptr;
+ unsigned char ch_len = escape_table[ch];
+
+ if (RB_UNLIKELY(ch_len)) {
+ search_flush(search);
+ return ch_len & CHAR_LENGTH_MASK;
+ } else {
+ search->ptr++;
+ }
+ }
+ search_flush(search);
+ return 0;
+}
+
+static inline void full_escape_UTF8_char(search_state *search, unsigned char ch_len)
+{
+ const unsigned char ch = (unsigned char)*search->ptr;
+ switch (ch_len) {
+ case 1: {
+ switch (ch) {
+ case '"': fbuffer_append(search->buffer, "\\\"", 2); break;
+ case '\\': fbuffer_append(search->buffer, "\\\\", 2); break;
+ case '/': fbuffer_append(search->buffer, "\\/", 2); break;
+ case '\b': fbuffer_append(search->buffer, "\\b", 2); break;
+ case '\f': fbuffer_append(search->buffer, "\\f", 2); break;
+ case '\n': fbuffer_append(search->buffer, "\\n", 2); break;
+ case '\r': fbuffer_append(search->buffer, "\\r", 2); break;
+ case '\t': fbuffer_append(search->buffer, "\\t", 2); break;
+ default: {
+ const char *hexdig = "0123456789abcdef";
+ char scratch[6] = { '\\', 'u', '0', '0', 0, 0 };
+ scratch[4] = hexdig[(ch >> 4) & 0xf];
+ scratch[5] = hexdig[ch & 0xf];
+ fbuffer_append(search->buffer, scratch, 6);
break;
+ }
}
- } else {
- switch (c) {
- case '\\':
- escape = "\\\\";
- escape_len = 2;
+ break;
+ }
+ default: {
+ const char *hexdig = "0123456789abcdef";
+ char scratch[12] = { '\\', 'u', 0, 0, 0, 0, '\\', 'u' };
+
+ uint32_t wchar = 0;
+
+ switch (ch_len) {
+ case 2:
+ wchar = ch & 0x1F;
break;
- case '"':
- escape = "\\\"";
- escape_len = 2;
+ case 3:
+ wchar = ch & 0x0F;
break;
- case '/':
- if(script_safe) {
- escape = "\\/";
- escape_len = 2;
- break;
- }
- default:
- {
- unsigned short clen = 1;
- if (!ascii_only) {
- clen += trailingBytesForUTF8[c];
- if (end + clen > len) {
- rb_raise(rb_path2class("JSON::GeneratorError"),
- "partial character in source, but hit end");
- }
-
- if (script_safe && c == 0xE2) {
- unsigned char c2 = (unsigned char) *(p+1);
- unsigned char c3 = (unsigned char) *(p+2);
- if (c2 == 0x80 && (c3 == 0xA8 || c3 == 0xA9)) {
- fbuffer_append(buffer, ptr + start, end - start);
- start = end = (end + clen);
- if (c3 == 0xA8) {
- fbuffer_append(buffer, "\\u2028", 6);
- } else {
- fbuffer_append(buffer, "\\u2029", 6);
- }
- continue;
- }
- }
-
- if (!isLegalUTF8((UTF8 *) p, clen)) {
- rb_raise(rb_path2class("JSON::GeneratorError"),
- "source sequence is illegal/malformed utf-8");
- }
- }
- end += clen;
- }
- continue;
+ case 4:
+ wchar = ch & 0x07;
break;
}
+
+ for (short i = 1; i < ch_len; i++) {
+ wchar = (wchar << 6) | (search->ptr[i] & 0x3F);
+ }
+
+ if (wchar <= 0xFFFF) {
+ scratch[2] = hexdig[wchar >> 12];
+ scratch[3] = hexdig[(wchar >> 8) & 0xf];
+ scratch[4] = hexdig[(wchar >> 4) & 0xf];
+ scratch[5] = hexdig[wchar & 0xf];
+ fbuffer_append(search->buffer, scratch, 6);
+ } else {
+ uint16_t hi, lo;
+ wchar -= 0x10000;
+ hi = 0xD800 + (uint16_t)(wchar >> 10);
+ lo = 0xDC00 + (uint16_t)(wchar & 0x3FF);
+
+ scratch[2] = hexdig[hi >> 12];
+ scratch[3] = hexdig[(hi >> 8) & 0xf];
+ scratch[4] = hexdig[(hi >> 4) & 0xf];
+ scratch[5] = hexdig[hi & 0xf];
+
+ scratch[8] = hexdig[lo >> 12];
+ scratch[9] = hexdig[(lo >> 8) & 0xf];
+ scratch[10] = hexdig[(lo >> 4) & 0xf];
+ scratch[11] = hexdig[lo & 0xf];
+
+ fbuffer_append(search->buffer, scratch, 12);
+ }
+
+ break;
}
- fbuffer_append(buffer, ptr + start, end - start);
- fbuffer_append(buffer, escape, escape_len);
- start = ++end;
- escape = NULL;
}
- fbuffer_append(buffer, ptr + start, end - start);
+ search->cursor = (search->ptr += ch_len);
}
-static char *fstrndup(const char *ptr, unsigned long len) {
- char *result;
- if (len <= 0) return NULL;
- result = ALLOC_N(char, len);
- memcpy(result, ptr, len);
- return result;
+static void convert_UTF8_to_ASCII_only_JSON(search_state *search, const unsigned char escape_table[256])
+{
+ unsigned char ch_len;
+ while ((ch_len = search_ascii_only_escape(search, escape_table))) {
+ full_escape_UTF8_char(search, ch_len);
+ }
}
/*
@@ -429,7 +795,9 @@ static char *fstrndup(const char *ptr, unsigned long len) {
*/
static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
{
- GENERATE_JSON(object);
+ rb_check_arity(argc, 0, 1);
+ VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
+ return cState_partial_generate(Vstate, self, generate_json_object, Qfalse);
}
/*
@@ -440,8 +808,11 @@ static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self)
* _state_ is a JSON::State object, that can also be used to configure the
* produced JSON string output further.
*/
-static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
- GENERATE_JSON(array);
+static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self)
+{
+ rb_check_arity(argc, 0, 1);
+ VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
+ return cState_partial_generate(Vstate, self, generate_json_array, Qfalse);
}
#ifdef RUBY_INTEGER_UNIFICATION
@@ -452,7 +823,9 @@ static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) {
*/
static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
{
- GENERATE_JSON(integer);
+ rb_check_arity(argc, 0, 1);
+ VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
+ return cState_partial_generate(Vstate, self, generate_json_integer, Qfalse);
}
#else
@@ -463,7 +836,9 @@ static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self)
*/
static VALUE mFixnum_to_json(int argc, VALUE *argv, VALUE self)
{
- GENERATE_JSON(fixnum);
+ rb_check_arity(argc, 0, 1);
+ VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
+ return cState_partial_generate(Vstate, self, generate_json_fixnum, Qfalse);
}
/*
@@ -473,7 +848,9 @@ static VALUE mFixnum_to_json(int argc, VALUE *argv, VALUE self)
*/
static VALUE mBignum_to_json(int argc, VALUE *argv, VALUE self)
{
- GENERATE_JSON(bignum);
+ rb_check_arity(argc, 0, 1);
+ VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
+ return cState_partial_generate(Vstate, self, generate_json_bignum, Qfalse);
}
#endif
@@ -484,18 +861,9 @@ static VALUE mBignum_to_json(int argc, VALUE *argv, VALUE self)
*/
static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self)
{
- GENERATE_JSON(float);
-}
-
-/*
- * call-seq: String.included(modul)
- *
- * Extends _modul_ with the String::Extend module.
- */
-static VALUE mString_included_s(VALUE self, VALUE modul) {
- VALUE result = rb_funcall(modul, i_extend, 1, mString_Extend);
- rb_call_super(1, &modul);
- return result;
+ rb_check_arity(argc, 0, 1);
+ VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
+ return cState_partial_generate(Vstate, self, generate_json_float, Qfalse);
}
/*
@@ -507,52 +875,9 @@ static VALUE mString_included_s(VALUE self, VALUE modul) {
*/
static VALUE mString_to_json(int argc, VALUE *argv, VALUE self)
{
- GENERATE_JSON(string);
-}
-
-/*
- * call-seq: to_json_raw_object()
- *
- * This method creates a raw object hash, that can be nested into
- * other data structures and will be generated as a raw string. This
- * method should be used, if you want to convert raw strings to JSON
- * instead of UTF-8 strings, e. g. binary data.
- */
-static VALUE mString_to_json_raw_object(VALUE self)
-{
- VALUE ary;
- VALUE result = rb_hash_new();
- rb_hash_aset(result, rb_funcall(mJSON, i_create_id, 0), rb_class_name(rb_obj_class(self)));
- ary = rb_funcall(self, i_unpack, 1, rb_str_new2("C*"));
- rb_hash_aset(result, rb_str_new2("raw"), ary);
- return result;
-}
-
-/*
- * call-seq: to_json_raw(*args)
- *
- * This method creates a JSON text from the result of a call to
- * to_json_raw_object of this String.
- */
-static VALUE mString_to_json_raw(int argc, VALUE *argv, VALUE self)
-{
- VALUE obj = mString_to_json_raw_object(self);
- Check_Type(obj, T_HASH);
- return mHash_to_json(argc, argv, obj);
-}
-
-/*
- * call-seq: json_create(o)
- *
- * Raw Strings are JSON Objects (the raw bytes are stored in an array for the
- * key "raw"). The Ruby String can be created by this module method.
- */
-static VALUE mString_Extend_json_create(VALUE self, VALUE o)
-{
- VALUE ary;
- Check_Type(o, T_HASH);
- ary = rb_hash_aref(o, rb_str_new2("raw"));
- return rb_funcall(ary, i_pack, 1, rb_str_new2("C*"));
+ rb_check_arity(argc, 0, 1);
+ VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil);
+ return cState_partial_generate(Vstate, self, generate_json_string, Qfalse);
}
/*
@@ -562,7 +887,8 @@ static VALUE mString_Extend_json_create(VALUE self, VALUE o)
*/
static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
{
- GENERATE_JSON(true);
+ rb_check_arity(argc, 0, 1);
+ return rb_utf8_str_new("true", 4);
}
/*
@@ -572,7 +898,8 @@ static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self)
*/
static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
{
- GENERATE_JSON(false);
+ rb_check_arity(argc, 0, 1);
+ return rb_utf8_str_new("false", 5);
}
/*
@@ -582,7 +909,8 @@ static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self)
*/
static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self)
{
- GENERATE_JSON(null);
+ rb_check_arity(argc, 0, 1);
+ return rb_utf8_str_new("null", 4);
}
/*
@@ -599,584 +927,641 @@ static VALUE mObject_to_json(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "01", &state);
Check_Type(string, T_STRING);
state = cState_from_state_s(cState, state);
- return cState_partial_generate(state, string);
+ return cState_partial_generate(state, string, generate_json_string, Qfalse);
+}
+
+static void State_mark(void *ptr)
+{
+ JSON_Generator_State *state = ptr;
+ rb_gc_mark_movable(state->indent);
+ rb_gc_mark_movable(state->space);
+ rb_gc_mark_movable(state->space_before);
+ rb_gc_mark_movable(state->object_nl);
+ rb_gc_mark_movable(state->array_nl);
+ rb_gc_mark_movable(state->as_json);
+}
+
+static void State_compact(void *ptr)
+{
+ JSON_Generator_State *state = ptr;
+ state->indent = rb_gc_location(state->indent);
+ state->space = rb_gc_location(state->space);
+ state->space_before = rb_gc_location(state->space_before);
+ state->object_nl = rb_gc_location(state->object_nl);
+ state->array_nl = rb_gc_location(state->array_nl);
+ state->as_json = rb_gc_location(state->as_json);
}
static void State_free(void *ptr)
{
JSON_Generator_State *state = ptr;
- if (state->indent) ruby_xfree(state->indent);
- if (state->space) ruby_xfree(state->space);
- if (state->space_before) ruby_xfree(state->space_before);
- if (state->object_nl) ruby_xfree(state->object_nl);
- if (state->array_nl) ruby_xfree(state->array_nl);
- if (state->array_delim) fbuffer_free(state->array_delim);
- if (state->object_delim) fbuffer_free(state->object_delim);
- if (state->object_delim2) fbuffer_free(state->object_delim2);
ruby_xfree(state);
}
static size_t State_memsize(const void *ptr)
{
- const JSON_Generator_State *state = ptr;
- size_t size = sizeof(*state);
- if (state->indent) size += state->indent_len + 1;
- if (state->space) size += state->space_len + 1;
- if (state->space_before) size += state->space_before_len + 1;
- if (state->object_nl) size += state->object_nl_len + 1;
- if (state->array_nl) size += state->array_nl_len + 1;
- if (state->array_delim) size += FBUFFER_CAPA(state->array_delim);
- if (state->object_delim) size += FBUFFER_CAPA(state->object_delim);
- if (state->object_delim2) size += FBUFFER_CAPA(state->object_delim2);
- return size;
-}
-
-#ifndef HAVE_RB_EXT_RACTOR_SAFE
-# undef RUBY_TYPED_FROZEN_SHAREABLE
-# define RUBY_TYPED_FROZEN_SHAREABLE 0
-#endif
+ return sizeof(JSON_Generator_State);
+}
-#ifdef NEW_TYPEDDATA_WRAPPER
static const rb_data_type_t JSON_Generator_State_type = {
"JSON/Generator/State",
- {NULL, State_free, State_memsize,},
-#ifdef RUBY_TYPED_FREE_IMMEDIATELY
+ {
+ .dmark = State_mark,
+ .dfree = State_free,
+ .dsize = State_memsize,
+ .dcompact = State_compact,
+ },
0, 0,
- RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE,
-#endif
+ RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE,
};
-#endif
+
+static void state_init(JSON_Generator_State *state)
+{
+ state->max_nesting = 100;
+ state->buffer_initial_length = FBUFFER_INITIAL_LENGTH_DEFAULT;
+}
static VALUE cState_s_allocate(VALUE klass)
{
JSON_Generator_State *state;
- return TypedData_Make_Struct(klass, JSON_Generator_State,
- &JSON_Generator_State_type, state);
+ VALUE obj = TypedData_Make_Struct(klass, JSON_Generator_State, &JSON_Generator_State_type, state);
+ state_init(state);
+ return obj;
}
-/*
- * call-seq: configure(opts)
- *
- * Configure this State instance with the Hash _opts_, and return
- * itself.
- */
-static VALUE cState_configure(VALUE self, VALUE opts)
+static void vstate_spill(struct generate_json_data *data)
{
- VALUE tmp;
- GET_STATE(self);
- tmp = rb_check_convert_type(opts, T_HASH, "Hash", "to_hash");
- if (NIL_P(tmp)) tmp = rb_convert_type(opts, T_HASH, "Hash", "to_h");
- opts = tmp;
- tmp = rb_hash_aref(opts, ID2SYM(i_indent));
- if (RTEST(tmp)) {
- unsigned long len;
- Check_Type(tmp, T_STRING);
- len = RSTRING_LEN(tmp);
- state->indent = fstrndup(RSTRING_PTR(tmp), len + 1);
- state->indent_len = len;
- }
- tmp = rb_hash_aref(opts, ID2SYM(i_space));
- if (RTEST(tmp)) {
- unsigned long len;
- Check_Type(tmp, T_STRING);
- len = RSTRING_LEN(tmp);
- state->space = fstrndup(RSTRING_PTR(tmp), len + 1);
- state->space_len = len;
+ VALUE vstate = cState_s_allocate(cState);
+ GET_STATE(vstate);
+ MEMCPY(state, data->state, JSON_Generator_State, 1);
+ data->state = state;
+ data->vstate = vstate;
+ RB_OBJ_WRITTEN(vstate, Qundef, state->indent);
+ RB_OBJ_WRITTEN(vstate, Qundef, state->space);
+ RB_OBJ_WRITTEN(vstate, Qundef, state->space_before);
+ RB_OBJ_WRITTEN(vstate, Qundef, state->object_nl);
+ RB_OBJ_WRITTEN(vstate, Qundef, state->array_nl);
+ RB_OBJ_WRITTEN(vstate, Qundef, state->as_json);
+}
+
+static inline VALUE json_call_to_json(struct generate_json_data *data, VALUE obj)
+{
+ if (RB_UNLIKELY(!data->vstate)) {
+ vstate_spill(data);
}
- tmp = rb_hash_aref(opts, ID2SYM(i_space_before));
- if (RTEST(tmp)) {
- unsigned long len;
- Check_Type(tmp, T_STRING);
- len = RSTRING_LEN(tmp);
- state->space_before = fstrndup(RSTRING_PTR(tmp), len + 1);
- state->space_before_len = len;
+ GET_STATE(data->vstate);
+ state->depth = data->depth;
+ VALUE tmp = rb_funcall(obj, i_to_json, 1, data->vstate);
+ // no need to restore state->depth, vstate is just a temporary State
+ return tmp;
+}
+
+static VALUE
+json_call_as_json(JSON_Generator_State *state, VALUE object, VALUE is_key)
+{
+ VALUE proc_args[2] = {object, is_key};
+ return rb_proc_call_with_block(state->as_json, 2, proc_args, Qnil);
+}
+
+static VALUE
+convert_string_subclass(VALUE key)
+{
+ VALUE key_to_s = rb_funcall(key, i_to_s, 0);
+
+ if (RB_UNLIKELY(!RB_TYPE_P(key_to_s, T_STRING))) {
+ VALUE cname = rb_obj_class(key);
+ rb_raise(rb_eTypeError,
+ "can't convert %"PRIsVALUE" to %s (%"PRIsVALUE"#%s gives %"PRIsVALUE")",
+ cname, "String", cname, "to_s", rb_obj_class(key_to_s));
}
- tmp = rb_hash_aref(opts, ID2SYM(i_array_nl));
- if (RTEST(tmp)) {
- unsigned long len;
- Check_Type(tmp, T_STRING);
- len = RSTRING_LEN(tmp);
- state->array_nl = fstrndup(RSTRING_PTR(tmp), len + 1);
- state->array_nl_len = len;
+
+ return key_to_s;
+}
+
+static bool enc_utf8_compatible_p(int enc_idx)
+{
+ if (enc_idx == usascii_encindex) return true;
+ if (enc_idx == utf8_encindex) return true;
+ return false;
+}
+
+static VALUE encode_json_string_try(VALUE str)
+{
+ return rb_funcall(str, i_encode, 1, Encoding_UTF_8);
+}
+
+static VALUE encode_json_string_rescue(VALUE str, VALUE exception)
+{
+ raise_generator_error_str(str, rb_funcall(exception, rb_intern("message"), 0));
+ return Qundef;
+}
+
+static inline bool valid_json_string_p(VALUE str)
+{
+ int coderange = rb_enc_str_coderange(str);
+
+ if (RB_LIKELY(coderange == ENC_CODERANGE_7BIT)) {
+ return true;
}
- tmp = rb_hash_aref(opts, ID2SYM(i_object_nl));
- if (RTEST(tmp)) {
- unsigned long len;
- Check_Type(tmp, T_STRING);
- len = RSTRING_LEN(tmp);
- state->object_nl = fstrndup(RSTRING_PTR(tmp), len + 1);
- state->object_nl_len = len;
+
+ if (RB_LIKELY(coderange == ENC_CODERANGE_VALID)) {
+ return enc_utf8_compatible_p(RB_ENCODING_GET_INLINED(str));
}
- tmp = ID2SYM(i_max_nesting);
- state->max_nesting = 100;
- if (option_given_p(opts, tmp)) {
- VALUE max_nesting = rb_hash_aref(opts, tmp);
- if (RTEST(max_nesting)) {
- Check_Type(max_nesting, T_FIXNUM);
- state->max_nesting = FIX2LONG(max_nesting);
- } else {
- state->max_nesting = 0;
- }
+
+ return false;
+}
+
+static inline VALUE ensure_valid_encoding(struct generate_json_data *data, VALUE str, bool as_json_called, bool is_key)
+{
+ if (RB_LIKELY(valid_json_string_p(str))) {
+ return str;
}
- tmp = ID2SYM(i_depth);
- state->depth = 0;
- if (option_given_p(opts, tmp)) {
- VALUE depth = rb_hash_aref(opts, tmp);
- if (RTEST(depth)) {
- Check_Type(depth, T_FIXNUM);
- state->depth = FIX2LONG(depth);
- } else {
- state->depth = 0;
+
+ if (!as_json_called && data->state->strict && RTEST(data->state->as_json)) {
+ VALUE coerced_str = json_call_as_json(data->state, str, Qfalse);
+ if (coerced_str != str) {
+ if (RB_TYPE_P(coerced_str, T_STRING)) {
+ if (!valid_json_string_p(coerced_str)) {
+ raise_generator_error(str, "source sequence is illegal/malformed utf-8");
+ }
+ } else {
+ // as_json could return another type than T_STRING
+ if (is_key) {
+ raise_generator_error(coerced_str, "%"PRIsVALUE" not allowed as object key in JSON", CLASS_OF(coerced_str));
+ }
+ }
+
+ return coerced_str;
}
}
- tmp = ID2SYM(i_buffer_initial_length);
- if (option_given_p(opts, tmp)) {
- VALUE buffer_initial_length = rb_hash_aref(opts, tmp);
- if (RTEST(buffer_initial_length)) {
- long initial_length;
- Check_Type(buffer_initial_length, T_FIXNUM);
- initial_length = FIX2LONG(buffer_initial_length);
- if (initial_length > 0) state->buffer_initial_length = initial_length;
+
+ if (RB_ENCODING_GET_INLINED(str) == binary_encindex) {
+ VALUE utf8_string = rb_enc_associate_index(rb_str_dup(str), utf8_encindex);
+ switch (rb_enc_str_coderange(utf8_string)) {
+ case ENC_CODERANGE_7BIT:
+ return utf8_string;
+ case ENC_CODERANGE_VALID:
+ // For historical reason, we silently reinterpret binary strings as UTF-8 if it would work.
+ // TODO: Raise in 3.0.0
+ rb_warn("JSON.generate: UTF-8 string passed as BINARY, this will raise an encoding error in json 3.0");
+ return utf8_string;
+ break;
}
}
- tmp = rb_hash_aref(opts, ID2SYM(i_allow_nan));
- state->allow_nan = RTEST(tmp);
- tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only));
- state->ascii_only = RTEST(tmp);
- tmp = rb_hash_aref(opts, ID2SYM(i_script_safe));
- state->script_safe = RTEST(tmp);
- if (!state->script_safe) {
- tmp = rb_hash_aref(opts, ID2SYM(i_escape_slash));
- state->script_safe = RTEST(tmp);
- }
- tmp = rb_hash_aref(opts, ID2SYM(i_strict));
- state->strict = RTEST(tmp);
- return self;
+
+ return rb_rescue(encode_json_string_try, str, encode_json_string_rescue, str);
}
-static void set_state_ivars(VALUE hash, VALUE state)
+static void raw_generate_json_string(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
{
- VALUE ivars = rb_obj_instance_variables(state);
- int i = 0;
- for (i = 0; i < RARRAY_LEN(ivars); i++) {
- VALUE key = rb_funcall(rb_ary_entry(ivars, i), i_to_s, 0);
- long key_len = RSTRING_LEN(key);
- VALUE value = rb_iv_get(state, StringValueCStr(key));
- rb_hash_aset(hash, rb_str_intern(rb_str_substr(key, 1, key_len - 1)), value);
+ fbuffer_append_char(buffer, '"');
+
+ long len;
+ search_state search;
+ search.buffer = buffer;
+ RSTRING_GETMEM(obj, search.ptr, len);
+ search.cursor = search.ptr;
+ search.end = search.ptr + len;
+
+#ifdef HAVE_SIMD
+ search.matches_mask = 0;
+ search.has_matches = false;
+ search.chunk_base = NULL;
+ search.chunk_end = NULL;
+#endif /* HAVE_SIMD */
+
+ switch (rb_enc_str_coderange(obj)) {
+ case ENC_CODERANGE_7BIT:
+ case ENC_CODERANGE_VALID:
+ if (RB_UNLIKELY(data->state->ascii_only)) {
+ convert_UTF8_to_ASCII_only_JSON(&search, data->state->script_safe ? script_safe_escape_table : ascii_only_escape_table);
+ } else if (RB_UNLIKELY(data->state->script_safe)) {
+ convert_UTF8_to_script_safe_JSON(&search);
+ } else {
+ convert_UTF8_to_JSON(&search);
+ }
+ break;
+ default:
+ raise_generator_error(obj, "source sequence is illegal/malformed utf-8");
+ break;
}
+ fbuffer_append_char(buffer, '"');
}
-/*
- * call-seq: to_h
- *
- * Returns the configuration instance variables as a hash, that can be
- * passed to the configure method.
- */
-static VALUE cState_to_h(VALUE self)
+static void generate_json_string(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
{
- VALUE result = rb_hash_new();
- GET_STATE(self);
- set_state_ivars(result, self);
- rb_hash_aset(result, ID2SYM(i_indent), rb_str_new(state->indent, state->indent_len));
- rb_hash_aset(result, ID2SYM(i_space), rb_str_new(state->space, state->space_len));
- rb_hash_aset(result, ID2SYM(i_space_before), rb_str_new(state->space_before, state->space_before_len));
- rb_hash_aset(result, ID2SYM(i_object_nl), rb_str_new(state->object_nl, state->object_nl_len));
- rb_hash_aset(result, ID2SYM(i_array_nl), rb_str_new(state->array_nl, state->array_nl_len));
- rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse);
- rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse);
- rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting));
- rb_hash_aset(result, ID2SYM(i_script_safe), state->script_safe ? Qtrue : Qfalse);
- rb_hash_aset(result, ID2SYM(i_strict), state->strict ? 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;
+ obj = ensure_valid_encoding(data, obj, false, false);
+ raw_generate_json_string(buffer, data, obj);
}
-/*
-* call-seq: [](name)
-*
-* Returns the value returned by method +name+.
-*/
-static VALUE cState_aref(VALUE self, VALUE name)
-{
- name = rb_funcall(name, i_to_s, 0);
- if (RTEST(rb_funcall(self, i_respond_to_p, 1, name))) {
- return rb_funcall(self, i_send, 1, name);
- } else {
- return rb_attr_get(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)));
- }
-}
+struct hash_foreach_arg {
+ VALUE hash;
+ struct generate_json_data *data;
+ int first_key_type;
+ bool first;
+ bool mixed_keys_encountered;
+};
-/*
-* call-seq: []=(name, value)
-*
-* Sets the attribute name to value.
-*/
-static VALUE cState_aset(VALUE self, VALUE name, VALUE value)
+NOINLINE(static) void
+json_inspect_hash_with_mixed_keys(struct hash_foreach_arg *arg)
{
- VALUE name_writer;
+ if (arg->mixed_keys_encountered) {
+ return;
+ }
+ arg->mixed_keys_encountered = true;
- name = rb_funcall(name, i_to_s, 0);
- name_writer = rb_str_cat2(rb_str_dup(name), "=");
- if (RTEST(rb_funcall(self, i_respond_to_p, 1, name_writer))) {
- return rb_funcall(self, i_send, 2, name_writer, value);
- } else {
- rb_ivar_set(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)), value);
+ JSON_Generator_State *state = arg->data->state;
+ if (state->on_duplicate_key != JSON_IGNORE) {
+ VALUE do_raise = state->on_duplicate_key == JSON_RAISE ? Qtrue : Qfalse;
+ rb_funcall(mJSON, rb_intern("on_mixed_keys_hash"), 2, arg->hash, do_raise);
}
- return Qnil;
}
-struct hash_foreach_arg {
- FBuffer *buffer;
- JSON_Generator_State *state;
- VALUE Vstate;
- int iter;
-};
-
static int
json_object_i(VALUE key, VALUE val, VALUE _arg)
{
struct hash_foreach_arg *arg = (struct hash_foreach_arg *)_arg;
- FBuffer *buffer = arg->buffer;
- JSON_Generator_State *state = arg->state;
- VALUE Vstate = arg->Vstate;
-
- char *object_nl = state->object_nl;
- long object_nl_len = state->object_nl_len;
- char *indent = state->indent;
- long indent_len = state->indent_len;
- char *delim = FBUFFER_PTR(state->object_delim);
- long delim_len = FBUFFER_LEN(state->object_delim);
- char *delim2 = FBUFFER_PTR(state->object_delim2);
- long delim2_len = FBUFFER_LEN(state->object_delim2);
- long depth = state->depth;
- int j;
- VALUE klass, key_to_s;
-
- if (arg->iter > 0) fbuffer_append(buffer, delim, delim_len);
- if (object_nl) {
- fbuffer_append(buffer, object_nl, object_nl_len);
+ struct generate_json_data *data = arg->data;
+
+ FBuffer *buffer = data->buffer;
+ JSON_Generator_State *state = data->state;
+
+ long depth = data->depth;
+ int key_type = rb_type(key);
+
+ if (arg->first) {
+ arg->first = false;
+ arg->first_key_type = key_type;
}
- if (indent) {
- for (j = 0; j < depth; j++) {
- fbuffer_append(buffer, indent, indent_len);
- }
+ else {
+ fbuffer_append_char(buffer, ',');
+ }
+
+ if (RB_UNLIKELY(data->state->object_nl)) {
+ fbuffer_append_str(buffer, data->state->object_nl);
+ }
+ if (RB_UNLIKELY(data->state->indent)) {
+ fbuffer_append_str_repeat(buffer, data->state->indent, depth);
}
- klass = CLASS_OF(key);
- if (klass == rb_cString) {
- key_to_s = key;
- } else if (klass == rb_cSymbol) {
- key_to_s = rb_sym2str(key);
+ VALUE key_to_s;
+ bool as_json_called = false;
+
+ start:
+ switch (key_type) {
+ case T_STRING:
+ if (RB_UNLIKELY(arg->first_key_type != T_STRING)) {
+ json_inspect_hash_with_mixed_keys(arg);
+ }
+
+ if (RB_LIKELY(RBASIC_CLASS(key) == rb_cString)) {
+ key_to_s = key;
+ } else {
+ key_to_s = convert_string_subclass(key);
+ }
+ break;
+ case T_SYMBOL:
+ if (RB_UNLIKELY(arg->first_key_type != T_SYMBOL)) {
+ json_inspect_hash_with_mixed_keys(arg);
+ }
+
+ key_to_s = rb_sym2str(key);
+ break;
+ default:
+ if (data->state->strict) {
+ if (RTEST(data->state->as_json) && !as_json_called) {
+ key = json_call_as_json(data->state, key, Qtrue);
+ key_type = rb_type(key);
+ as_json_called = true;
+ goto start;
+ } else {
+ raise_generator_error(key, "%"PRIsVALUE" not allowed as object key in JSON", CLASS_OF(key));
+ }
+ }
+ key_to_s = rb_convert_type(key, T_STRING, "String", "to_s");
+ break;
+ }
+
+ key_to_s = ensure_valid_encoding(data, key_to_s, as_json_called, true);
+
+ if (RB_LIKELY(RBASIC_CLASS(key_to_s) == rb_cString)) {
+ raw_generate_json_string(buffer, data, key_to_s);
} else {
- key_to_s = rb_funcall(key, i_to_s, 0);
+ generate_json(buffer, data, key_to_s);
}
- Check_Type(key_to_s, T_STRING);
- generate_json(buffer, Vstate, state, key_to_s);
- fbuffer_append(buffer, delim2, delim2_len);
- generate_json(buffer, Vstate, state, val);
+ if (RB_UNLIKELY(state->space_before)) fbuffer_append_str(buffer, data->state->space_before);
+ fbuffer_append_char(buffer, ':');
+ if (RB_UNLIKELY(state->space)) fbuffer_append_str(buffer, data->state->space);
+ generate_json(buffer, data, val);
- arg->iter++;
return ST_CONTINUE;
}
-static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
+static inline long increase_depth(struct generate_json_data *data)
+{
+ JSON_Generator_State *state = data->state;
+ long depth = ++data->depth;
+ if (RB_UNLIKELY(depth > state->max_nesting && state->max_nesting)) {
+ rb_raise(eNestingError, "nesting of %ld is too deep. Did you try to serialize objects with circular references?", --data->depth);
+ }
+ return depth;
+}
+
+static void generate_json_object(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
{
- char *object_nl = state->object_nl;
- long object_nl_len = state->object_nl_len;
- char *indent = state->indent;
- long indent_len = state->indent_len;
- long max_nesting = state->max_nesting;
- long depth = ++state->depth;
- int j;
- struct hash_foreach_arg arg;
+ long depth = increase_depth(data);
- if (max_nesting != 0 && depth > max_nesting) {
- rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
+ if (RHASH_SIZE(obj) == 0) {
+ fbuffer_append(buffer, "{}", 2);
+ --data->depth;
+ return;
}
+
fbuffer_append_char(buffer, '{');
- arg.buffer = buffer;
- arg.state = state;
- arg.Vstate = Vstate;
- arg.iter = 0;
+ struct hash_foreach_arg arg = {
+ .hash = obj,
+ .data = data,
+ .first = true,
+ };
rb_hash_foreach(obj, json_object_i, (VALUE)&arg);
- depth = --state->depth;
- if (object_nl) {
- fbuffer_append(buffer, object_nl, object_nl_len);
- if (indent) {
- for (j = 0; j < depth; j++) {
- fbuffer_append(buffer, indent, indent_len);
- }
+ depth = --data->depth;
+ if (RB_UNLIKELY(data->state->object_nl)) {
+ fbuffer_append_str(buffer, data->state->object_nl);
+ if (RB_UNLIKELY(data->state->indent)) {
+ fbuffer_append_str_repeat(buffer, data->state->indent, depth);
}
}
fbuffer_append_char(buffer, '}');
}
-static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
+static void generate_json_array(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
{
- char *array_nl = state->array_nl;
- long array_nl_len = state->array_nl_len;
- char *indent = state->indent;
- long indent_len = state->indent_len;
- long max_nesting = state->max_nesting;
- char *delim = FBUFFER_PTR(state->array_delim);
- long delim_len = FBUFFER_LEN(state->array_delim);
- long depth = ++state->depth;
- int i, j;
- if (max_nesting != 0 && depth > max_nesting) {
- rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth);
+ long depth = increase_depth(data);
+
+ if (RARRAY_LEN(obj) == 0) {
+ fbuffer_append(buffer, "[]", 2);
+ --data->depth;
+ return;
}
+
fbuffer_append_char(buffer, '[');
- if (array_nl) fbuffer_append(buffer, array_nl, array_nl_len);
- for(i = 0; i < RARRAY_LEN(obj); i++) {
- if (i > 0) fbuffer_append(buffer, delim, delim_len);
- if (indent) {
- for (j = 0; j < depth; j++) {
- fbuffer_append(buffer, indent, indent_len);
- }
+ if (RB_UNLIKELY(data->state->array_nl)) fbuffer_append_str(buffer, data->state->array_nl);
+ for (int i = 0; i < RARRAY_LEN(obj); i++) {
+ if (i > 0) {
+ fbuffer_append_char(buffer, ',');
+ if (RB_UNLIKELY(data->state->array_nl)) fbuffer_append_str(buffer, data->state->array_nl);
}
- generate_json(buffer, Vstate, state, rb_ary_entry(obj, i));
+ if (RB_UNLIKELY(data->state->indent)) {
+ fbuffer_append_str_repeat(buffer, data->state->indent, depth);
+ }
+ generate_json(buffer, data, RARRAY_AREF(obj, i));
}
- state->depth = --depth;
- if (array_nl) {
- fbuffer_append(buffer, array_nl, array_nl_len);
- if (indent) {
- for (j = 0; j < depth; j++) {
- fbuffer_append(buffer, indent, indent_len);
- }
+ data->depth = --depth;
+ if (RB_UNLIKELY(data->state->array_nl)) {
+ fbuffer_append_str(buffer, data->state->array_nl);
+ if (RB_UNLIKELY(data->state->indent)) {
+ fbuffer_append_str_repeat(buffer, data->state->indent, depth);
}
}
fbuffer_append_char(buffer, ']');
}
-#ifdef HAVE_RUBY_ENCODING_H
-static int enc_utf8_compatible_p(rb_encoding *enc)
+static void generate_json_fallback(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
{
- if (enc == rb_usascii_encoding()) return 1;
- if (enc == rb_utf8_encoding()) return 1;
- return 0;
+ VALUE tmp;
+ if (rb_respond_to(obj, i_to_json)) {
+ tmp = json_call_to_json(data, obj);
+ Check_Type(tmp, T_STRING);
+ fbuffer_append_str(buffer, tmp);
+ } else {
+ tmp = rb_funcall(obj, i_to_s, 0);
+ Check_Type(tmp, T_STRING);
+ generate_json_string(buffer, data, tmp);
+ }
}
-#endif
-static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
+static inline void generate_json_symbol(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
{
- fbuffer_append_char(buffer, '"');
-#ifdef HAVE_RUBY_ENCODING_H
- if (!enc_utf8_compatible_p(rb_enc_get(obj))) {
- obj = rb_str_export_to_enc(obj, rb_utf8_encoding());
- }
-#endif
- if (state->ascii_only) {
- convert_UTF8_to_JSON_ASCII(buffer, obj, state->script_safe);
+ if (data->state->strict) {
+ generate_json_string(buffer, data, rb_sym2str(obj));
} else {
- convert_UTF8_to_JSON(buffer, obj, state->script_safe);
+ generate_json_fallback(buffer, data, obj);
}
- fbuffer_append_char(buffer, '"');
}
-static void generate_json_null(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
+static void generate_json_null(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
{
fbuffer_append(buffer, "null", 4);
}
-static void generate_json_false(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
+static void generate_json_false(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
{
fbuffer_append(buffer, "false", 5);
}
-static void generate_json_true(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
+static void generate_json_true(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
{
fbuffer_append(buffer, "true", 4);
}
-static void generate_json_fixnum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
+static void generate_json_fixnum(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
{
fbuffer_append_long(buffer, FIX2LONG(obj));
}
-static void generate_json_bignum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
+static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
{
VALUE tmp = rb_funcall(obj, i_to_s, 0);
fbuffer_append_str(buffer, tmp);
}
#ifdef RUBY_INTEGER_UNIFICATION
-static void generate_json_integer(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
+static void generate_json_integer(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
{
if (FIXNUM_P(obj))
- generate_json_fixnum(buffer, Vstate, state, obj);
+ generate_json_fixnum(buffer, data, obj);
else
- generate_json_bignum(buffer, Vstate, state, obj);
+ generate_json_bignum(buffer, data, obj);
}
#endif
-static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
+
+static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
{
double value = RFLOAT_VALUE(obj);
- char allow_nan = state->allow_nan;
- VALUE tmp = rb_funcall(obj, i_to_s, 0);
- if (!allow_nan) {
- if (isinf(value)) {
- rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(tmp));
- } else if (isnan(value)) {
- rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(tmp));
+ char allow_nan = data->state->allow_nan;
+ if (isinf(value) || isnan(value)) {
+ /* for NaN and Infinity values we either raise an error or rely on Float#to_s. */
+ if (!allow_nan) {
+ if (data->state->strict && data->state->as_json) {
+ VALUE casted_obj = json_call_as_json(data->state, obj, Qfalse);
+ if (casted_obj != obj) {
+ increase_depth(data);
+ generate_json(buffer, data, casted_obj);
+ data->depth--;
+ return;
+ }
+ }
+ raise_generator_error(obj, "%"PRIsVALUE" not allowed in JSON", rb_funcall(obj, i_to_s, 0));
}
- }
- fbuffer_append_str(buffer, tmp);
-}
-static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj)
-{
- VALUE tmp;
- VALUE klass = CLASS_OF(obj);
- if (klass == rb_cHash) {
- generate_json_object(buffer, Vstate, state, obj);
- } else if (klass == rb_cArray) {
- generate_json_array(buffer, Vstate, state, obj);
- } else if (klass == rb_cString) {
- generate_json_string(buffer, Vstate, state, obj);
- } else if (obj == Qnil) {
- generate_json_null(buffer, Vstate, state, obj);
- } else if (obj == Qfalse) {
- generate_json_false(buffer, Vstate, state, obj);
- } else if (obj == Qtrue) {
- generate_json_true(buffer, Vstate, state, obj);
- } else if (FIXNUM_P(obj)) {
- generate_json_fixnum(buffer, Vstate, state, obj);
- } else if (RB_TYPE_P(obj, T_BIGNUM)) {
- generate_json_bignum(buffer, Vstate, state, obj);
- } else if (klass == rb_cFloat) {
- generate_json_float(buffer, Vstate, state, obj);
- } else if (state->strict) {
- rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(CLASS_OF(obj)));
- } else if (rb_respond_to(obj, i_to_json)) {
- tmp = rb_funcall(obj, i_to_json, 1, Vstate);
- Check_Type(tmp, T_STRING);
+ VALUE tmp = rb_funcall(obj, i_to_s, 0);
fbuffer_append_str(buffer, tmp);
- } else {
- tmp = rb_funcall(obj, i_to_s, 0);
- Check_Type(tmp, T_STRING);
- generate_json_string(buffer, Vstate, state, tmp);
+ return;
}
+
+ /* This implementation writes directly into the buffer. We reserve
+ * the 32 characters that fpconv_dtoa states as its maximum.
+ */
+ fbuffer_inc_capa(buffer, 32);
+ char* d = buffer->ptr + buffer->len;
+ int len = fpconv_dtoa(value, d);
+ /* fpconv_dtoa converts a float to its shortest string representation,
+ * but it adds a ".0" if this is a plain integer.
+ */
+ fbuffer_consumed(buffer, len);
}
-static FBuffer *cState_prepare_buffer(VALUE self)
+static void generate_json_fragment(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
{
- FBuffer *buffer;
- GET_STATE(self);
- buffer = fbuffer_alloc(state->buffer_initial_length);
-
- if (state->object_delim) {
- fbuffer_clear(state->object_delim);
- } else {
- state->object_delim = fbuffer_alloc(16);
- }
- fbuffer_append_char(state->object_delim, ',');
- if (state->object_delim2) {
- fbuffer_clear(state->object_delim2);
- } else {
- state->object_delim2 = fbuffer_alloc(16);
- }
- if (state->space_before) fbuffer_append(state->object_delim2, state->space_before, state->space_before_len);
- fbuffer_append_char(state->object_delim2, ':');
- if (state->space) fbuffer_append(state->object_delim2, state->space, state->space_len);
+ VALUE fragment = RSTRUCT_GET(obj, 0);
+ Check_Type(fragment, T_STRING);
+ fbuffer_append_str(buffer, fragment);
+}
- if (state->array_delim) {
- fbuffer_clear(state->array_delim);
+static void generate_json(FBuffer *buffer, struct generate_json_data *data, VALUE obj)
+{
+ bool as_json_called = false;
+start:
+ if (obj == Qnil) {
+ generate_json_null(buffer, data, obj);
+ } else if (obj == Qfalse) {
+ generate_json_false(buffer, data, obj);
+ } else if (obj == Qtrue) {
+ generate_json_true(buffer, data, obj);
+ } else if (RB_SPECIAL_CONST_P(obj)) {
+ if (RB_FIXNUM_P(obj)) {
+ generate_json_fixnum(buffer, data, obj);
+ } else if (RB_FLONUM_P(obj)) {
+ generate_json_float(buffer, data, obj);
+ } else if (RB_STATIC_SYM_P(obj)) {
+ generate_json_symbol(buffer, data, obj);
+ } else {
+ goto general;
+ }
} else {
- state->array_delim = fbuffer_alloc(16);
+ VALUE klass = RBASIC_CLASS(obj);
+ switch (RB_BUILTIN_TYPE(obj)) {
+ case T_BIGNUM:
+ generate_json_bignum(buffer, data, obj);
+ break;
+ case T_HASH:
+ if (klass != rb_cHash) goto general;
+ generate_json_object(buffer, data, obj);
+ break;
+ case T_ARRAY:
+ if (klass != rb_cArray) goto general;
+ generate_json_array(buffer, data, obj);
+ break;
+ case T_STRING:
+ if (klass != rb_cString) goto general;
+
+ if (RB_LIKELY(valid_json_string_p(obj))) {
+ raw_generate_json_string(buffer, data, obj);
+ } else if (as_json_called) {
+ raise_generator_error(obj, "source sequence is illegal/malformed utf-8");
+ } else {
+ obj = ensure_valid_encoding(data, obj, false, false);
+ as_json_called = true;
+ goto start;
+ }
+ break;
+ case T_SYMBOL:
+ generate_json_symbol(buffer, data, obj);
+ break;
+ case T_FLOAT:
+ if (klass != rb_cFloat) goto general;
+ generate_json_float(buffer, data, obj);
+ break;
+ case T_STRUCT:
+ if (klass != cFragment) goto general;
+ generate_json_fragment(buffer, data, obj);
+ break;
+ default:
+ general:
+ if (data->state->strict) {
+ if (RTEST(data->state->as_json) && !as_json_called) {
+ obj = json_call_as_json(data->state, obj, Qfalse);
+ as_json_called = true;
+ goto start;
+ } else {
+ raise_generator_error(obj, "%"PRIsVALUE" not allowed in JSON", CLASS_OF(obj));
+ }
+ } else {
+ generate_json_fallback(buffer, data, obj);
+ }
+ }
}
- fbuffer_append_char(state->array_delim, ',');
- if (state->array_nl) fbuffer_append(state->array_delim, state->array_nl, state->array_nl_len);
- return buffer;
}
-struct generate_json_data {
- FBuffer *buffer;
- VALUE vstate;
- JSON_Generator_State *state;
- VALUE obj;
-};
-
static VALUE generate_json_try(VALUE d)
{
struct generate_json_data *data = (struct generate_json_data *)d;
- generate_json(data->buffer, data->vstate, data->state, data->obj);
+ data->func(data->buffer, data, data->obj);
- return Qnil;
+ return fbuffer_finalize(data->buffer);
}
-static VALUE generate_json_rescue(VALUE d, VALUE exc)
+static VALUE generate_json_ensure(VALUE d)
{
struct generate_json_data *data = (struct generate_json_data *)d;
fbuffer_free(data->buffer);
- rb_exc_raise(exc);
-
return Qundef;
}
-static VALUE cState_partial_generate(VALUE self, VALUE obj)
+static VALUE cState_partial_generate(VALUE self, VALUE obj, generator_func func, VALUE io)
{
- FBuffer *buffer = cState_prepare_buffer(self);
GET_STATE(self);
+ char stack_buffer[FBUFFER_STACK_SIZE];
+ FBuffer buffer = {
+ .io = RTEST(io) ? io : Qfalse,
+ };
+ fbuffer_stack_init(&buffer, state->buffer_initial_length, stack_buffer, FBUFFER_STACK_SIZE);
+
struct generate_json_data data = {
- .buffer = buffer,
- .vstate = self,
+ .buffer = &buffer,
+ .vstate = Qfalse, // don't use self as it may be frozen and its depth is mutated when calling to_json
.state = state,
- .obj = obj
+ .depth = state->depth,
+ .obj = obj,
+ .func = func
};
- rb_rescue(generate_json_try, (VALUE)&data, generate_json_rescue, (VALUE)&data);
-
- return fbuffer_to_s(buffer);
+ return rb_ensure(generate_json_try, (VALUE)&data, generate_json_ensure, (VALUE)&data);
}
-/*
- * call-seq: generate(obj)
+/* call-seq:
+ * generate(obj) -> String
+ * generate(obj, anIO) -> anIO
*
* Generates a valid JSON document from object +obj+ and returns the
* result. If no valid JSON document can be created this method raises a
* GeneratorError exception.
*/
-static VALUE cState_generate(VALUE self, VALUE obj)
+static VALUE cState_generate(int argc, VALUE *argv, VALUE self)
{
- VALUE result = cState_partial_generate(self, obj);
- GET_STATE(self);
- (void)state;
- return result;
+ rb_check_arity(argc, 1, 2);
+ VALUE obj = argv[0];
+ VALUE io = argc > 1 ? argv[1] : Qnil;
+ return cState_partial_generate(self, obj, generate_json, io);
}
-/*
- * call-seq: new(opts = {})
- *
- * Instantiates a new State object, configured by _opts_.
- *
- * _opts_ can have the following keys:
- *
- * * *indent*: a string used to indent levels (default: ''),
- * * *space*: a string that is put after, a : or , delimiter (default: ''),
- * * *space_before*: a string that is put before a : pair delimiter (default: ''),
- * * *object_nl*: a string that is put at the end of a JSON object (default: ''),
- * * *array_nl*: a string that is put at the end of a JSON array (default: ''),
- * * *allow_nan*: true if NaN, Infinity, and -Infinity should be
- * generated, otherwise an exception is thrown, if these values are
- * encountered. This options defaults to false.
- * * *ascii_only*: true if only ASCII characters should be generated. This
- * option defaults to false.
- * * *buffer_initial_length*: sets the initial length of the generator's
- * internal buffer.
- */
static VALUE cState_initialize(int argc, VALUE *argv, VALUE self)
{
- VALUE opts;
- GET_STATE(self);
- state->max_nesting = 100;
- state->buffer_initial_length = FBUFFER_INITIAL_LENGTH_DEFAULT;
- rb_scan_args(argc, argv, "01", &opts);
- if (!NIL_P(opts)) cState_configure(self, opts);
+ rb_warn("The json gem extension was loaded with the stdlib ruby code. You should upgrade rubygems with `gem update --system`");
return self;
}
@@ -1196,14 +1581,12 @@ static VALUE cState_init_copy(VALUE obj, VALUE orig)
if (!objState) rb_raise(rb_eArgError, "unallocated JSON::State");
MEMCPY(objState, origState, JSON_Generator_State, 1);
- objState->indent = fstrndup(origState->indent, origState->indent_len);
- objState->space = fstrndup(origState->space, origState->space_len);
- objState->space_before = fstrndup(origState->space_before, origState->space_before_len);
- objState->object_nl = fstrndup(origState->object_nl, origState->object_nl_len);
- objState->array_nl = fstrndup(origState->array_nl, origState->array_nl_len);
- if (origState->array_delim) objState->array_delim = fbuffer_dup(origState->array_delim);
- if (origState->object_delim) objState->object_delim = fbuffer_dup(origState->object_delim);
- if (origState->object_delim2) objState->object_delim2 = fbuffer_dup(origState->object_delim2);
+ objState->indent = origState->indent;
+ objState->space = origState->space;
+ objState->space_before = origState->space_before;
+ objState->object_nl = origState->object_nl;
+ objState->array_nl = origState->array_nl;
+ objState->as_json = origState->as_json;
return obj;
}
@@ -1233,7 +1616,18 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts)
static VALUE cState_indent(VALUE self)
{
GET_STATE(self);
- return state->indent ? rb_str_new(state->indent, state->indent_len) : rb_str_new2("");
+ return state->indent ? state->indent : rb_str_freeze(rb_utf8_str_new("", 0));
+}
+
+static VALUE string_config(VALUE config)
+{
+ if (RTEST(config)) {
+ Check_Type(config, T_STRING);
+ if (RSTRING_LEN(config)) {
+ return rb_str_new_frozen(config);
+ }
+ }
+ return Qfalse;
}
/*
@@ -1243,21 +1637,9 @@ static VALUE cState_indent(VALUE self)
*/
static VALUE cState_indent_set(VALUE self, VALUE indent)
{
- unsigned long len;
+ rb_check_frozen(self);
GET_STATE(self);
- Check_Type(indent, T_STRING);
- len = RSTRING_LEN(indent);
- if (len == 0) {
- if (state->indent) {
- ruby_xfree(state->indent);
- state->indent = NULL;
- state->indent_len = 0;
- }
- } else {
- if (state->indent) ruby_xfree(state->indent);
- state->indent = fstrndup(RSTRING_PTR(indent), len);
- state->indent_len = len;
- }
+ RB_OBJ_WRITE(self, &state->indent, string_config(indent));
return Qnil;
}
@@ -1270,7 +1652,7 @@ static VALUE cState_indent_set(VALUE self, VALUE indent)
static VALUE cState_space(VALUE self)
{
GET_STATE(self);
- return state->space ? rb_str_new(state->space, state->space_len) : rb_str_new2("");
+ return state->space ? state->space : rb_str_freeze(rb_utf8_str_new("", 0));
}
/*
@@ -1281,21 +1663,9 @@ static VALUE cState_space(VALUE self)
*/
static VALUE cState_space_set(VALUE self, VALUE space)
{
- unsigned long len;
+ rb_check_frozen(self);
GET_STATE(self);
- Check_Type(space, T_STRING);
- len = RSTRING_LEN(space);
- if (len == 0) {
- if (state->space) {
- ruby_xfree(state->space);
- state->space = NULL;
- state->space_len = 0;
- }
- } else {
- if (state->space) ruby_xfree(state->space);
- state->space = fstrndup(RSTRING_PTR(space), len);
- state->space_len = len;
- }
+ RB_OBJ_WRITE(self, &state->space, string_config(space));
return Qnil;
}
@@ -1307,7 +1677,7 @@ static VALUE cState_space_set(VALUE self, VALUE space)
static VALUE cState_space_before(VALUE self)
{
GET_STATE(self);
- return state->space_before ? rb_str_new(state->space_before, state->space_before_len) : rb_str_new2("");
+ return state->space_before ? state->space_before : rb_str_freeze(rb_utf8_str_new("", 0));
}
/*
@@ -1317,21 +1687,9 @@ static VALUE cState_space_before(VALUE self)
*/
static VALUE cState_space_before_set(VALUE self, VALUE space_before)
{
- unsigned long len;
+ rb_check_frozen(self);
GET_STATE(self);
- Check_Type(space_before, T_STRING);
- len = RSTRING_LEN(space_before);
- if (len == 0) {
- if (state->space_before) {
- ruby_xfree(state->space_before);
- state->space_before = NULL;
- state->space_before_len = 0;
- }
- } else {
- if (state->space_before) ruby_xfree(state->space_before);
- state->space_before = fstrndup(RSTRING_PTR(space_before), len);
- state->space_before_len = len;
- }
+ RB_OBJ_WRITE(self, &state->space_before, string_config(space_before));
return Qnil;
}
@@ -1344,7 +1702,7 @@ static VALUE cState_space_before_set(VALUE self, VALUE space_before)
static VALUE cState_object_nl(VALUE self)
{
GET_STATE(self);
- return state->object_nl ? rb_str_new(state->object_nl, state->object_nl_len) : rb_str_new2("");
+ return state->object_nl ? state->object_nl : rb_str_freeze(rb_utf8_str_new("", 0));
}
/*
@@ -1355,20 +1713,9 @@ static VALUE cState_object_nl(VALUE self)
*/
static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
{
- unsigned long len;
+ rb_check_frozen(self);
GET_STATE(self);
- Check_Type(object_nl, T_STRING);
- len = RSTRING_LEN(object_nl);
- if (len == 0) {
- if (state->object_nl) {
- ruby_xfree(state->object_nl);
- state->object_nl = NULL;
- }
- } else {
- if (state->object_nl) ruby_xfree(state->object_nl);
- state->object_nl = fstrndup(RSTRING_PTR(object_nl), len);
- state->object_nl_len = len;
- }
+ RB_OBJ_WRITE(self, &state->object_nl, string_config(object_nl));
return Qnil;
}
@@ -1380,7 +1727,7 @@ static VALUE cState_object_nl_set(VALUE self, VALUE object_nl)
static VALUE cState_array_nl(VALUE self)
{
GET_STATE(self);
- return state->array_nl ? rb_str_new(state->array_nl, state->array_nl_len) : rb_str_new2("");
+ return state->array_nl ? state->array_nl : rb_str_freeze(rb_utf8_str_new("", 0));
}
/*
@@ -1390,23 +1737,35 @@ static VALUE cState_array_nl(VALUE self)
*/
static VALUE cState_array_nl_set(VALUE self, VALUE array_nl)
{
- unsigned long len;
+ rb_check_frozen(self);
GET_STATE(self);
- Check_Type(array_nl, T_STRING);
- len = RSTRING_LEN(array_nl);
- if (len == 0) {
- if (state->array_nl) {
- ruby_xfree(state->array_nl);
- state->array_nl = NULL;
- }
- } else {
- if (state->array_nl) ruby_xfree(state->array_nl);
- state->array_nl = fstrndup(RSTRING_PTR(array_nl), len);
- state->array_nl_len = len;
- }
+ RB_OBJ_WRITE(self, &state->array_nl, string_config(array_nl));
return Qnil;
}
+/*
+ * call-seq: as_json()
+ *
+ * This string is put at the end of a line that holds a JSON array.
+ */
+static VALUE cState_as_json(VALUE self)
+{
+ GET_STATE(self);
+ return state->as_json;
+}
+
+/*
+ * call-seq: as_json=(as_json)
+ *
+ * This string is put at the end of a line that holds a JSON array.
+ */
+static VALUE cState_as_json_set(VALUE self, VALUE as_json)
+{
+ rb_check_frozen(self);
+ GET_STATE(self);
+ RB_OBJ_WRITE(self, &state->as_json, rb_convert_type(as_json, T_DATA, "Proc", "to_proc"));
+ return Qnil;
+}
/*
* call-seq: check_circular?
@@ -1432,6 +1791,11 @@ static VALUE cState_max_nesting(VALUE self)
return LONG2FIX(state->max_nesting);
}
+static long long_config(VALUE num)
+{
+ return RTEST(num) ? FIX2LONG(num) : 0;
+}
+
/*
* call-seq: max_nesting=(depth)
*
@@ -1440,9 +1804,10 @@ static VALUE cState_max_nesting(VALUE self)
*/
static VALUE cState_max_nesting_set(VALUE self, VALUE depth)
{
+ rb_check_frozen(self);
GET_STATE(self);
- Check_Type(depth, T_FIXNUM);
- return state->max_nesting = FIX2LONG(depth);
+ state->max_nesting = long_config(depth);
+ return Qnil;
}
/*
@@ -1465,6 +1830,7 @@ static VALUE cState_script_safe(VALUE self)
*/
static VALUE cState_script_safe_set(VALUE self, VALUE enable)
{
+ rb_check_frozen(self);
GET_STATE(self);
state->script_safe = RTEST(enable);
return Qnil;
@@ -1496,6 +1862,7 @@ static VALUE cState_strict(VALUE self)
*/
static VALUE cState_strict_set(VALUE self, VALUE enable)
{
+ rb_check_frozen(self);
GET_STATE(self);
state->strict = RTEST(enable);
return Qnil;
@@ -1514,6 +1881,19 @@ static VALUE cState_allow_nan_p(VALUE self)
}
/*
+ * call-seq: allow_nan=(enable)
+ *
+ * This sets whether or not to serialize NaN, Infinity, and -Infinity
+ */
+static VALUE cState_allow_nan_set(VALUE self, VALUE enable)
+{
+ rb_check_frozen(self);
+ GET_STATE(self);
+ state->allow_nan = RTEST(enable);
+ return Qnil;
+}
+
+/*
* call-seq: ascii_only?
*
* Returns true, if only ASCII characters should be generated. Otherwise
@@ -1526,6 +1906,32 @@ static VALUE cState_ascii_only_p(VALUE self)
}
/*
+ * call-seq: ascii_only=(enable)
+ *
+ * This sets whether only ASCII characters should be generated.
+ */
+static VALUE cState_ascii_only_set(VALUE self, VALUE enable)
+{
+ rb_check_frozen(self);
+ GET_STATE(self);
+ state->ascii_only = RTEST(enable);
+ return Qnil;
+}
+
+static VALUE cState_allow_duplicate_key_p(VALUE self)
+{
+ GET_STATE(self);
+ switch (state->on_duplicate_key) {
+ case JSON_IGNORE:
+ return Qtrue;
+ case JSON_DEPRECATED:
+ return Qnil;
+ default:
+ return Qfalse;
+ }
+}
+
+/*
* call-seq: depth
*
* This integer returns the current depth of data structure nesting.
@@ -1544,9 +1950,9 @@ static VALUE cState_depth(VALUE self)
*/
static VALUE cState_depth_set(VALUE self, VALUE depth)
{
+ rb_check_frozen(self);
GET_STATE(self);
- Check_Type(depth, T_FIXNUM);
- state->depth = FIX2LONG(depth);
+ state->depth = long_config(depth);
return Qnil;
}
@@ -1561,6 +1967,15 @@ static VALUE cState_buffer_initial_length(VALUE self)
return LONG2FIX(state->buffer_initial_length);
}
+static void buffer_initial_length_set(JSON_Generator_State *state, VALUE buffer_initial_length)
+{
+ Check_Type(buffer_initial_length, T_FIXNUM);
+ long initial_length = FIX2LONG(buffer_initial_length);
+ if (initial_length > 0) {
+ state->buffer_initial_length = initial_length;
+ }
+}
+
/*
* call-seq: buffer_initial_length=(length)
*
@@ -1569,16 +1984,102 @@ static VALUE cState_buffer_initial_length(VALUE self)
*/
static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_length)
{
- long initial_length;
+ rb_check_frozen(self);
GET_STATE(self);
- Check_Type(buffer_initial_length, T_FIXNUM);
- initial_length = FIX2LONG(buffer_initial_length);
- if (initial_length > 0) {
- state->buffer_initial_length = initial_length;
- }
+ buffer_initial_length_set(state, buffer_initial_length);
return Qnil;
}
+struct configure_state_data {
+ JSON_Generator_State *state;
+ VALUE vstate; // Ruby object that owns the state, or Qfalse if stack-allocated
+};
+
+static inline void state_write_value(struct configure_state_data *data, VALUE *field, VALUE value)
+{
+ if (RTEST(data->vstate)) {
+ RB_OBJ_WRITE(data->vstate, field, value);
+ } else {
+ *field = value;
+ }
+}
+
+static int configure_state_i(VALUE key, VALUE val, VALUE _arg)
+{
+ struct configure_state_data *data = (struct configure_state_data *)_arg;
+ JSON_Generator_State *state = data->state;
+
+ if (key == sym_indent) { state_write_value(data, &state->indent, string_config(val)); }
+ else if (key == sym_space) { state_write_value(data, &state->space, string_config(val)); }
+ else if (key == sym_space_before) { state_write_value(data, &state->space_before, string_config(val)); }
+ else if (key == sym_object_nl) { state_write_value(data, &state->object_nl, string_config(val)); }
+ else if (key == sym_array_nl) { state_write_value(data, &state->array_nl, string_config(val)); }
+ else if (key == sym_max_nesting) { state->max_nesting = long_config(val); }
+ else if (key == sym_allow_nan) { state->allow_nan = RTEST(val); }
+ else if (key == sym_ascii_only) { state->ascii_only = RTEST(val); }
+ else if (key == sym_depth) { state->depth = long_config(val); }
+ else if (key == sym_buffer_initial_length) { buffer_initial_length_set(state, val); }
+ else if (key == sym_script_safe) { state->script_safe = RTEST(val); }
+ else if (key == sym_escape_slash) { state->script_safe = RTEST(val); }
+ else if (key == sym_strict) { state->strict = RTEST(val); }
+ else if (key == sym_allow_duplicate_key) { state->on_duplicate_key = RTEST(val) ? JSON_IGNORE : JSON_RAISE; }
+ else if (key == sym_as_json) {
+ VALUE proc = RTEST(val) ? rb_convert_type(val, T_DATA, "Proc", "to_proc") : Qfalse;
+ state->as_json_single_arg = proc && rb_proc_arity(proc) == 1;
+ state_write_value(data, &state->as_json, proc);
+ }
+ return ST_CONTINUE;
+}
+
+static void configure_state(JSON_Generator_State *state, VALUE vstate, VALUE config)
+{
+ if (!RTEST(config)) return;
+
+ Check_Type(config, T_HASH);
+
+ if (!RHASH_SIZE(config)) return;
+
+ struct configure_state_data data = {
+ .state = state,
+ .vstate = vstate
+ };
+
+ // We assume in most cases few keys are set so it's faster to go over
+ // the provided keys than to check all possible keys.
+ rb_hash_foreach(config, configure_state_i, (VALUE)&data);
+}
+
+static VALUE cState_configure(VALUE self, VALUE opts)
+{
+ rb_check_frozen(self);
+ GET_STATE(self);
+ configure_state(state, self, opts);
+ return self;
+}
+
+static VALUE cState_m_generate(VALUE klass, VALUE obj, VALUE opts, VALUE io)
+{
+ JSON_Generator_State state = {0};
+ state_init(&state);
+ configure_state(&state, Qfalse, opts);
+
+ char stack_buffer[FBUFFER_STACK_SIZE];
+ FBuffer buffer = {
+ .io = RTEST(io) ? io : Qfalse,
+ };
+ fbuffer_stack_init(&buffer, state.buffer_initial_length, stack_buffer, FBUFFER_STACK_SIZE);
+
+ struct generate_json_data data = {
+ .buffer = &buffer,
+ .vstate = Qfalse,
+ .state = &state,
+ .depth = state.depth,
+ .obj = obj,
+ .func = generate_json,
+ };
+ return rb_ensure(generate_json_try, (VALUE)&data, generate_json_ensure, (VALUE)&data);
+}
+
/*
*
*/
@@ -1592,18 +2093,26 @@ void Init_generator(void)
rb_require("json/common");
mJSON = rb_define_module("JSON");
- mExt = rb_define_module_under(mJSON, "Ext");
- mGenerator = rb_define_module_under(mExt, "Generator");
+ rb_global_variable(&cFragment);
+ cFragment = rb_const_get(mJSON, rb_intern("Fragment"));
+
+ VALUE mExt = rb_define_module_under(mJSON, "Ext");
+ VALUE mGenerator = rb_define_module_under(mExt, "Generator");
+
+ rb_global_variable(&eGeneratorError);
eGeneratorError = rb_path2class("JSON::GeneratorError");
+
+ rb_global_variable(&eNestingError);
eNestingError = rb_path2class("JSON::NestingError");
- rb_gc_register_mark_object(eGeneratorError);
- rb_gc_register_mark_object(eNestingError);
cState = rb_define_class_under(mGenerator, "State", rb_cObject);
rb_define_alloc_func(cState, cState_s_allocate);
rb_define_singleton_method(cState, "from_state", cState_from_state_s, 1);
rb_define_method(cState, "initialize", cState_initialize, -1);
+ rb_define_alias(cState, "initialize", "initialize"); // avoid method redefinition warnings
+ rb_define_private_method(cState, "_configure", cState_configure, 1);
+
rb_define_method(cState, "initialize_copy", cState_init_copy, 1);
rb_define_method(cState, "indent", cState_indent, 0);
rb_define_method(cState, "indent=", cState_indent_set, 1);
@@ -1615,6 +2124,8 @@ void Init_generator(void)
rb_define_method(cState, "object_nl=", cState_object_nl_set, 1);
rb_define_method(cState, "array_nl", cState_array_nl, 0);
rb_define_method(cState, "array_nl=", cState_array_nl_set, 1);
+ rb_define_method(cState, "as_json", cState_as_json, 0);
+ rb_define_method(cState, "as_json=", cState_as_json_set, 1);
rb_define_method(cState, "max_nesting", cState_max_nesting, 0);
rb_define_method(cState, "max_nesting=", cState_max_nesting_set, 1);
rb_define_method(cState, "script_safe", cState_script_safe, 0);
@@ -1628,76 +2139,84 @@ void Init_generator(void)
rb_define_method(cState, "strict=", cState_strict_set, 1);
rb_define_method(cState, "check_circular?", cState_check_circular_p, 0);
rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0);
+ rb_define_method(cState, "allow_nan=", cState_allow_nan_set, 1);
rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0);
+ rb_define_method(cState, "ascii_only=", cState_ascii_only_set, 1);
rb_define_method(cState, "depth", cState_depth, 0);
rb_define_method(cState, "depth=", cState_depth_set, 1);
rb_define_method(cState, "buffer_initial_length", cState_buffer_initial_length, 0);
rb_define_method(cState, "buffer_initial_length=", cState_buffer_initial_length_set, 1);
- rb_define_method(cState, "configure", cState_configure, 1);
- rb_define_alias(cState, "merge", "configure");
- rb_define_method(cState, "to_h", cState_to_h, 0);
- rb_define_alias(cState, "to_hash", "to_h");
- rb_define_method(cState, "[]", cState_aref, 1);
- rb_define_method(cState, "[]=", cState_aset, 2);
- rb_define_method(cState, "generate", cState_generate, 1);
-
- mGeneratorMethods = rb_define_module_under(mGenerator, "GeneratorMethods");
- mObject = rb_define_module_under(mGeneratorMethods, "Object");
+ rb_define_method(cState, "generate", cState_generate, -1);
+
+ rb_define_private_method(cState, "allow_duplicate_key?", cState_allow_duplicate_key_p, 0);
+
+ rb_define_singleton_method(cState, "generate", cState_m_generate, 3);
+
+ VALUE mGeneratorMethods = rb_define_module_under(mGenerator, "GeneratorMethods");
+
+ VALUE mObject = rb_define_module_under(mGeneratorMethods, "Object");
rb_define_method(mObject, "to_json", mObject_to_json, -1);
- mHash = rb_define_module_under(mGeneratorMethods, "Hash");
+
+ VALUE mHash = rb_define_module_under(mGeneratorMethods, "Hash");
rb_define_method(mHash, "to_json", mHash_to_json, -1);
- mArray = rb_define_module_under(mGeneratorMethods, "Array");
+
+ VALUE mArray = rb_define_module_under(mGeneratorMethods, "Array");
rb_define_method(mArray, "to_json", mArray_to_json, -1);
+
#ifdef RUBY_INTEGER_UNIFICATION
- mInteger = rb_define_module_under(mGeneratorMethods, "Integer");
+ VALUE mInteger = rb_define_module_under(mGeneratorMethods, "Integer");
rb_define_method(mInteger, "to_json", mInteger_to_json, -1);
#else
- mFixnum = rb_define_module_under(mGeneratorMethods, "Fixnum");
+ VALUE mFixnum = rb_define_module_under(mGeneratorMethods, "Fixnum");
rb_define_method(mFixnum, "to_json", mFixnum_to_json, -1);
- mBignum = rb_define_module_under(mGeneratorMethods, "Bignum");
+
+ VALUE mBignum = rb_define_module_under(mGeneratorMethods, "Bignum");
rb_define_method(mBignum, "to_json", mBignum_to_json, -1);
#endif
- mFloat = rb_define_module_under(mGeneratorMethods, "Float");
+ VALUE mFloat = rb_define_module_under(mGeneratorMethods, "Float");
rb_define_method(mFloat, "to_json", mFloat_to_json, -1);
- mString = rb_define_module_under(mGeneratorMethods, "String");
- rb_define_singleton_method(mString, "included", mString_included_s, 1);
+
+ VALUE mString = rb_define_module_under(mGeneratorMethods, "String");
rb_define_method(mString, "to_json", mString_to_json, -1);
- rb_define_method(mString, "to_json_raw", mString_to_json_raw, -1);
- rb_define_method(mString, "to_json_raw_object", mString_to_json_raw_object, 0);
- mString_Extend = rb_define_module_under(mString, "Extend");
- rb_define_method(mString_Extend, "json_create", mString_Extend_json_create, 1);
- mTrueClass = rb_define_module_under(mGeneratorMethods, "TrueClass");
+
+ VALUE mTrueClass = rb_define_module_under(mGeneratorMethods, "TrueClass");
rb_define_method(mTrueClass, "to_json", mTrueClass_to_json, -1);
- mFalseClass = rb_define_module_under(mGeneratorMethods, "FalseClass");
+
+ VALUE mFalseClass = rb_define_module_under(mGeneratorMethods, "FalseClass");
rb_define_method(mFalseClass, "to_json", mFalseClass_to_json, -1);
- mNilClass = rb_define_module_under(mGeneratorMethods, "NilClass");
+
+ VALUE mNilClass = rb_define_module_under(mGeneratorMethods, "NilClass");
rb_define_method(mNilClass, "to_json", mNilClass_to_json, -1);
+ rb_global_variable(&Encoding_UTF_8);
+ Encoding_UTF_8 = rb_const_get(rb_path2class("Encoding"), rb_intern("UTF_8"));
+
i_to_s = rb_intern("to_s");
i_to_json = rb_intern("to_json");
i_new = rb_intern("new");
- i_indent = rb_intern("indent");
- i_space = rb_intern("space");
- i_space_before = rb_intern("space_before");
- i_object_nl = rb_intern("object_nl");
- i_array_nl = rb_intern("array_nl");
- i_max_nesting = rb_intern("max_nesting");
- i_script_safe = rb_intern("script_safe");
- i_escape_slash = rb_intern("escape_slash");
- i_strict = rb_intern("strict");
- i_allow_nan = rb_intern("allow_nan");
- i_ascii_only = rb_intern("ascii_only");
- i_depth = rb_intern("depth");
- i_buffer_initial_length = rb_intern("buffer_initial_length");
- i_pack = rb_intern("pack");
- i_unpack = rb_intern("unpack");
- i_create_id = rb_intern("create_id");
- i_extend = rb_intern("extend");
- i_key_p = rb_intern("key?");
- i_aref = rb_intern("[]");
- i_send = rb_intern("__send__");
- i_respond_to_p = rb_intern("respond_to?");
- i_match = rb_intern("match");
- i_keys = rb_intern("keys");
- i_dup = rb_intern("dup");
+ i_encode = rb_intern("encode");
+
+ sym_indent = ID2SYM(rb_intern("indent"));
+ sym_space = ID2SYM(rb_intern("space"));
+ sym_space_before = ID2SYM(rb_intern("space_before"));
+ sym_object_nl = ID2SYM(rb_intern("object_nl"));
+ sym_array_nl = ID2SYM(rb_intern("array_nl"));
+ sym_max_nesting = ID2SYM(rb_intern("max_nesting"));
+ sym_allow_nan = ID2SYM(rb_intern("allow_nan"));
+ sym_ascii_only = ID2SYM(rb_intern("ascii_only"));
+ sym_depth = ID2SYM(rb_intern("depth"));
+ sym_buffer_initial_length = ID2SYM(rb_intern("buffer_initial_length"));
+ sym_script_safe = ID2SYM(rb_intern("script_safe"));
+ sym_escape_slash = ID2SYM(rb_intern("escape_slash"));
+ sym_strict = ID2SYM(rb_intern("strict"));
+ sym_as_json = ID2SYM(rb_intern("as_json"));
+ sym_allow_duplicate_key = ID2SYM(rb_intern("allow_duplicate_key"));
+
+ usascii_encindex = rb_usascii_encindex();
+ utf8_encindex = rb_utf8_encindex();
+ binary_encindex = rb_ascii8bit_encindex();
+
+ rb_require("json/ext/generator/state");
+
+ simd_impl = find_simd_implementation();
}
diff --git a/ext/json/generator/generator.h b/ext/json/generator/generator.h
deleted file mode 100644
index 1a736b84dd..0000000000
--- a/ext/json/generator/generator.h
+++ /dev/null
@@ -1,177 +0,0 @@
-#ifndef _GENERATOR_H_
-#define _GENERATOR_H_
-
-#include <math.h>
-#include <ctype.h>
-
-#include "ruby.h"
-
-#ifdef HAVE_RUBY_RE_H
-#include "ruby/re.h"
-#else
-#include "re.h"
-#endif
-
-#ifndef rb_intern_str
-#define rb_intern_str(string) SYM2ID(rb_str_intern(string))
-#endif
-
-#ifndef rb_obj_instance_variables
-#define rb_obj_instance_variables(object) rb_funcall(object, rb_intern("instance_variables"), 0)
-#endif
-
-#define option_given_p(opts, key) RTEST(rb_funcall(opts, i_key_p, 1, key))
-
-/* unicode definitions */
-
-#define UNI_STRICT_CONVERSION 1
-
-typedef unsigned long UTF32; /* at least 32 bits */
-typedef unsigned short UTF16; /* at least 16 bits */
-typedef unsigned char UTF8; /* typically 8 bits */
-
-#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
-#define UNI_MAX_BMP (UTF32)0x0000FFFF
-#define UNI_MAX_UTF16 (UTF32)0x0010FFFF
-#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
-#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
-
-#define UNI_SUR_HIGH_START (UTF32)0xD800
-#define UNI_SUR_HIGH_END (UTF32)0xDBFF
-#define UNI_SUR_LOW_START (UTF32)0xDC00
-#define UNI_SUR_LOW_END (UTF32)0xDFFF
-
-static const int halfShift = 10; /* used for shifting by 10 bits */
-
-static const UTF32 halfBase = 0x0010000UL;
-static const UTF32 halfMask = 0x3FFUL;
-
-static unsigned char isLegalUTF8(const UTF8 *source, unsigned long length);
-static void unicode_escape(char *buf, UTF16 character);
-static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16 character);
-static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char script_safe);
-static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char script_safe);
-static char *fstrndup(const char *ptr, unsigned long len);
-
-/* ruby api and some helpers */
-
-typedef struct JSON_Generator_StateStruct {
- char *indent;
- long indent_len;
- char *space;
- long space_len;
- char *space_before;
- long space_before_len;
- char *object_nl;
- long object_nl_len;
- char *array_nl;
- long array_nl_len;
- FBuffer *array_delim;
- FBuffer *object_delim;
- FBuffer *object_delim2;
- long max_nesting;
- char allow_nan;
- char ascii_only;
- char script_safe;
- char strict;
- long depth;
- long buffer_initial_length;
-} JSON_Generator_State;
-
-#define GET_STATE_TO(self, state) \
- TypedData_Get_Struct(self, JSON_Generator_State, &JSON_Generator_State_type, state)
-
-#define GET_STATE(self) \
- JSON_Generator_State *state; \
- GET_STATE_TO(self, state)
-
-#define GENERATE_JSON(type) \
- FBuffer *buffer; \
- VALUE Vstate; \
- JSON_Generator_State *state; \
- \
- rb_scan_args(argc, argv, "01", &Vstate); \
- Vstate = cState_from_state_s(cState, Vstate); \
- TypedData_Get_Struct(Vstate, JSON_Generator_State, &JSON_Generator_State_type, state); \
- buffer = cState_prepare_buffer(Vstate); \
- generate_json_##type(buffer, Vstate, state, self); \
- return fbuffer_to_s(buffer)
-
-static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self);
-static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self);
-#ifdef RUBY_INTEGER_UNIFICATION
-static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self);
-#else
-static VALUE mFixnum_to_json(int argc, VALUE *argv, VALUE self);
-static VALUE mBignum_to_json(int argc, VALUE *argv, VALUE self);
-#endif
-static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self);
-static VALUE mString_included_s(VALUE self, VALUE modul);
-static VALUE mString_to_json(int argc, VALUE *argv, VALUE self);
-static VALUE mString_to_json_raw_object(VALUE self);
-static VALUE mString_to_json_raw(int argc, VALUE *argv, VALUE self);
-static VALUE mString_Extend_json_create(VALUE self, VALUE o);
-static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self);
-static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self);
-static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self);
-static VALUE mObject_to_json(int argc, VALUE *argv, VALUE self);
-static void State_free(void *state);
-static VALUE cState_s_allocate(VALUE klass);
-static VALUE cState_configure(VALUE self, VALUE opts);
-static VALUE cState_to_h(VALUE self);
-static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
-static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
-static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
-static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
-static void generate_json_null(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
-static void generate_json_false(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
-static void generate_json_true(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
-#ifdef RUBY_INTEGER_UNIFICATION
-static void generate_json_integer(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
-#endif
-static void generate_json_fixnum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
-static void generate_json_bignum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
-static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj);
-static VALUE cState_partial_generate(VALUE self, VALUE obj);
-static VALUE cState_generate(VALUE self, VALUE obj);
-static VALUE cState_initialize(int argc, VALUE *argv, VALUE self);
-static VALUE cState_from_state_s(VALUE self, VALUE opts);
-static VALUE cState_indent(VALUE self);
-static VALUE cState_indent_set(VALUE self, VALUE indent);
-static VALUE cState_space(VALUE self);
-static VALUE cState_space_set(VALUE self, VALUE space);
-static VALUE cState_space_before(VALUE self);
-static VALUE cState_space_before_set(VALUE self, VALUE space_before);
-static VALUE cState_object_nl(VALUE self);
-static VALUE cState_object_nl_set(VALUE self, VALUE object_nl);
-static VALUE cState_array_nl(VALUE self);
-static VALUE cState_array_nl_set(VALUE self, VALUE array_nl);
-static VALUE cState_max_nesting(VALUE self);
-static VALUE cState_max_nesting_set(VALUE self, VALUE depth);
-static VALUE cState_allow_nan_p(VALUE self);
-static VALUE cState_ascii_only_p(VALUE self);
-static VALUE cState_depth(VALUE self);
-static VALUE cState_depth_set(VALUE self, VALUE depth);
-static VALUE cState_script_safe(VALUE self);
-static VALUE cState_script_safe_set(VALUE self, VALUE depth);
-static VALUE cState_strict(VALUE self);
-static VALUE cState_strict_set(VALUE self, VALUE strict);
-static FBuffer *cState_prepare_buffer(VALUE self);
-#ifndef ZALLOC
-#define ZALLOC(type) ((type *)ruby_zalloc(sizeof(type)))
-static inline void *ruby_zalloc(size_t n)
-{
- void *p = ruby_xmalloc(n);
- memset(p, 0, n);
- return p;
-}
-#endif
-#ifdef TypedData_Make_Struct
-static const rb_data_type_t JSON_Generator_State_type;
-#define NEW_TYPEDDATA_WRAPPER 1
-#else
-#define TypedData_Make_Struct(klass, type, ignore, json) Data_Make_Struct(klass, type, NULL, State_free, json)
-#define TypedData_Get_Struct(self, JSON_Generator_State, ignore, json) Data_Get_Struct(self, JSON_Generator_State, json)
-#endif
-
-#endif
diff --git a/ext/json/json.gemspec b/ext/json/json.gemspec
index 64d0c81391..5575731025 100644
--- a/ext/json/json.gemspec
+++ b/ext/json/json.gemspec
@@ -1,68 +1,62 @@
+# frozen_string_literal: true
+
version = File.foreach(File.join(__dir__, "lib/json/version.rb")) do |line|
/^\s*VERSION\s*=\s*'(.*)'/ =~ line and break $1
end rescue nil
-Gem::Specification.new do |s|
+spec = Gem::Specification.new do |s|
+ java_ext = Gem::Platform === s.platform && s.platform =~ 'java' || RUBY_ENGINE == 'jruby'
+
s.name = "json"
s.version = version
s.summary = "JSON Implementation for Ruby"
- s.description = "This is a JSON implementation as a Ruby extension in C."
+ s.homepage = "https://github.com/ruby/json"
+ s.metadata = {
+ 'bug_tracker_uri' => 'https://github.com/ruby/json/issues',
+ 'changelog_uri' => 'https://github.com/ruby/json/blob/master/CHANGES.md',
+ 'documentation_uri' => 'https://docs.ruby-lang.org/en/master/JSON.html',
+ 'homepage_uri' => s.homepage,
+ 'source_code_uri' => 'https://github.com/ruby/json',
+ }
+
+ s.required_ruby_version = Gem::Requirement.new(">= 2.7")
+
+ if java_ext
+ s.description = "A JSON implementation as a JRuby extension."
+ s.author = "Daniel Luz"
+ s.email = "dev+ruby@mernen.com"
+ else
+ s.description = "This is a JSON implementation as a Ruby extension in C."
+ s.authors = ["Florian Frank"]
+ s.email = "flori@ping.de"
+ end
+
s.licenses = ["Ruby"]
- s.authors = ["Florian Frank"]
- s.email = "flori@ping.de"
- s.extensions = ["ext/json/ext/generator/extconf.rb", "ext/json/ext/parser/extconf.rb", "ext/json/extconf.rb"]
s.extra_rdoc_files = ["README.md"]
s.rdoc_options = ["--title", "JSON implementation for Ruby", "--main", "README.md"]
+
s.files = [
"CHANGES.md",
- "LICENSE",
+ "COPYING",
+ "BSDL",
+ "LEGAL",
"README.md",
- "ext/json/ext/fbuffer/fbuffer.h",
- "ext/json/ext/generator/depend",
- "ext/json/ext/generator/extconf.rb",
- "ext/json/ext/generator/generator.c",
- "ext/json/ext/generator/generator.h",
- "ext/json/ext/parser/depend",
- "ext/json/ext/parser/extconf.rb",
- "ext/json/ext/parser/parser.c",
- "ext/json/ext/parser/parser.h",
- "ext/json/ext/parser/parser.rl",
- "ext/json/extconf.rb",
"json.gemspec",
- "lib/json.rb",
- "lib/json/add/bigdecimal.rb",
- "lib/json/add/complex.rb",
- "lib/json/add/core.rb",
- "lib/json/add/date.rb",
- "lib/json/add/date_time.rb",
- "lib/json/add/exception.rb",
- "lib/json/add/ostruct.rb",
- "lib/json/add/range.rb",
- "lib/json/add/rational.rb",
- "lib/json/add/regexp.rb",
- "lib/json/add/set.rb",
- "lib/json/add/struct.rb",
- "lib/json/add/symbol.rb",
- "lib/json/add/time.rb",
- "lib/json/common.rb",
- "lib/json/ext.rb",
- "lib/json/generic_object.rb",
- "lib/json/pure.rb",
- "lib/json/pure/generator.rb",
- "lib/json/pure/parser.rb",
- "lib/json/version.rb",
- ]
- s.homepage = "https://flori.github.io/json"
- s.metadata = {
- 'bug_tracker_uri' => 'https://github.com/flori/json/issues',
- 'changelog_uri' => 'https://github.com/flori/json/blob/master/CHANGES.md',
- 'documentation_uri' => 'https://flori.github.io/json/doc/index.html',
- 'homepage_uri' => s.homepage,
- 'source_code_uri' => 'https://github.com/flori/json',
- 'wiki_uri' => 'https://github.com/flori/json/wiki'
- }
+ ] + Dir.glob("lib/**/*.rb", base: File.expand_path("..", __FILE__))
+
+ if java_ext
+ s.platform = 'java'
+ s.files += Dir["lib/json/ext/**/*.jar"]
+ else
+ s.extensions = Dir["ext/json/**/extconf.rb"]
+ s.files += Dir["ext/json/**/*.{c,h,rb}"]
+ end
+end
- s.required_ruby_version = Gem::Requirement.new(">= 2.3")
+if RUBY_ENGINE == 'jruby' && $0 == __FILE__
+ Gem::Builder.new(spec).build
+else
+ spec
end
diff --git a/ext/json/json.h b/ext/json/json.h
new file mode 100644
index 0000000000..9379d7ae7f
--- /dev/null
+++ b/ext/json/json.h
@@ -0,0 +1,101 @@
+#ifndef _JSON_H_
+#define _JSON_H_
+
+#include "ruby.h"
+#include "ruby/encoding.h"
+#include <stdint.h>
+
+#ifndef RBIMPL_ASSERT_OR_ASSUME
+# define RBIMPL_ASSERT_OR_ASSUME(x)
+#endif
+
+#if defined(RUBY_DEBUG) && RUBY_DEBUG
+# define JSON_ASSERT RUBY_ASSERT
+#else
+# ifdef JSON_DEBUG
+# include <assert.h>
+# define JSON_ASSERT(x) assert(x)
+# else
+# define JSON_ASSERT(x)
+# endif
+#endif
+
+/* shims */
+
+#if SIZEOF_UINT64_T == SIZEOF_LONG_LONG
+# define INT64T2NUM(x) LL2NUM(x)
+# define UINT64T2NUM(x) ULL2NUM(x)
+#elif SIZEOF_UINT64_T == SIZEOF_LONG
+# define INT64T2NUM(x) LONG2NUM(x)
+# define UINT64T2NUM(x) ULONG2NUM(x)
+#else
+# error No uint64_t conversion
+#endif
+
+/* This is the fallback definition from Ruby 3.4 */
+#ifndef RBIMPL_STDBOOL_H
+#if defined(__cplusplus)
+# if defined(HAVE_STDBOOL_H) && (__cplusplus >= 201103L)
+# include <cstdbool>
+# endif
+#elif defined(HAVE_STDBOOL_H)
+# include <stdbool.h>
+#elif !defined(HAVE__BOOL)
+typedef unsigned char _Bool;
+# define bool _Bool
+# define true ((_Bool)+1)
+# define false ((_Bool)+0)
+# define __bool_true_false_are_defined
+#endif
+#endif
+
+#ifndef HAVE_RB_EXT_RACTOR_SAFE
+# undef RUBY_TYPED_FROZEN_SHAREABLE
+# define RUBY_TYPED_FROZEN_SHAREABLE 0
+#endif
+
+#ifndef NORETURN
+#define NORETURN(x) x
+#endif
+
+#ifndef NOINLINE
+#if defined(__has_attribute) && __has_attribute(noinline)
+#define NOINLINE(x) __attribute__((noinline)) x
+#else
+#define NOINLINE(x) x
+#endif
+#endif
+
+#ifndef ALWAYS_INLINE
+#if defined(__has_attribute) && __has_attribute(always_inline)
+#define ALWAYS_INLINE(x) inline __attribute__((always_inline)) x
+#else
+#define ALWAYS_INLINE(x) inline x
+#endif
+#endif
+
+#ifndef RB_UNLIKELY
+#define RB_UNLIKELY(expr) expr
+#endif
+
+#ifndef RB_LIKELY
+#define RB_LIKELY(expr) expr
+#endif
+
+#ifndef MAYBE_UNUSED
+# define MAYBE_UNUSED(x) x
+#endif
+
+#ifdef RUBY_DEBUG
+#ifndef JSON_DEBUG
+#define JSON_DEBUG RUBY_DEBUG
+#endif
+#endif
+
+#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && INTPTR_MAX == INT64_MAX
+#define JSON_CPU_LITTLE_ENDIAN_64BITS 1
+#else
+#define JSON_CPU_LITTLE_ENDIAN_64BITS 0
+#endif
+
+#endif // _JSON_H_
diff --git a/ext/json/lib/json.rb b/ext/json/lib/json.rb
index 807488ffef..f619d93252 100644
--- a/ext/json/lib/json.rb
+++ b/ext/json/lib/json.rb
@@ -1,4 +1,4 @@
-#frozen_string_literal: false
+# frozen_string_literal: true
require 'json/common'
##
@@ -127,6 +127,24 @@ require 'json/common'
#
# ---
#
+# Option +allow_duplicate_key+ specifies whether duplicate keys in objects
+# should be ignored or cause an error to be raised:
+#
+# When not specified:
+# # The last value is used and a deprecation warning emitted.
+# JSON.parse('{"a": 1, "a":2}') => {"a" => 2}
+# # warning: detected duplicate keys in JSON object.
+# # This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`
+#
+# When set to `+true+`
+# # The last value is used.
+# JSON.parse('{"a": 1, "a":2}') => {"a" => 2}
+#
+# When set to `+false+`, the future default:
+# JSON.parse('{"a": 1, "a":2}') => duplicate key at line 1 column 1 (JSON::ParserError)
+#
+# ---
+#
# Option +allow_nan+ (boolean) specifies whether to allow
# NaN, Infinity, and MinusInfinity in +source+;
# defaults to +false+.
@@ -143,8 +161,35 @@ require 'json/common'
# ruby = JSON.parse(source, {allow_nan: true})
# ruby # => [NaN, Infinity, -Infinity]
#
+# ---
+#
+# Option +allow_trailing_comma+ (boolean) specifies whether to allow
+# trailing commas in objects and arrays;
+# defaults to +false+.
+#
+# With the default, +false+:
+# JSON.parse('[1,]') # unexpected character: ']' at line 1 column 4 (JSON::ParserError)
+#
+# When enabled:
+# JSON.parse('[1,]', allow_trailing_comma: true) # => [1]
+#
+# ---
+#
+# Option +allow_control_characters+ (boolean) specifies whether to allow
+# unescaped ASCII control characters, such as newlines, in strings;
+# defaults to +false+.
+#
+# With the default, +false+:
+# JSON.parse(%{"Hello\nWorld"}) # invalid ASCII control character in string (JSON::ParserError)
+#
+# When enabled:
+# JSON.parse(%{"Hello\nWorld"}, allow_control_characters: true) # => "Hello\nWorld"
+#
# ====== Output Options
#
+# Option +freeze+ (boolean) specifies whether the returned objects will be frozen;
+# defaults to +false+.
+#
# Option +symbolize_names+ (boolean) specifies whether returned \Hash keys
# should be Symbols;
# defaults to +false+ (use Strings).
@@ -274,6 +319,25 @@ require 'json/common'
#
# ---
#
+# Option +allow_duplicate_key+ (boolean) specifies whether
+# hashes with duplicate keys should be allowed or produce an error.
+# defaults to emit a deprecation warning.
+#
+# With the default, (not set):
+# Warning[:deprecated] = true
+# JSON.generate({ foo: 1, "foo" => 2 })
+# # warning: detected duplicate key "foo" in {foo: 1, "foo" => 2}.
+# # This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`
+# # => '{"foo":1,"foo":2}'
+#
+# With <tt>false</tt>
+# JSON.generate({ foo: 1, "foo" => 2 }, allow_duplicate_key: false)
+# # detected duplicate key "foo" in {foo: 1, "foo" => 2} (JSON::GeneratorError)
+#
+# In version 3.0, <tt>false</tt> will become the default.
+#
+# ---
+#
# Option +max_nesting+ (\Integer) specifies the maximum nesting depth
# in +obj+; defaults to +100+.
#
@@ -351,6 +415,9 @@ require 'json/common'
#
# == \JSON Additions
#
+# Note that JSON Additions must only be used with trusted data, and is
+# deprecated.
+#
# 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)
@@ -378,13 +445,13 @@ require 'json/common'
# json1 = JSON.generate(ruby)
# ruby1 = JSON.parse(json1, create_additions: true)
# # Make a nice display.
-# display = <<EOT
-# Generated JSON:
-# Without addition: #{json0} (#{json0.class})
-# With addition: #{json1} (#{json1.class})
-# Parsed JSON:
-# Without addition: #{ruby0.inspect} (#{ruby0.class})
-# With addition: #{ruby1.inspect} (#{ruby1.class})
+# display = <<~EOT
+# Generated JSON:
+# Without addition: #{json0} (#{json0.class})
+# With addition: #{json1} (#{json1.class})
+# Parsed JSON:
+# Without addition: #{ruby0.inspect} (#{ruby0.class})
+# With addition: #{ruby1.inspect} (#{ruby1.class})
# EOT
# puts display
#
@@ -562,13 +629,13 @@ require 'json/common'
# json1 = JSON.generate(foo1)
# obj1 = JSON.parse(json1, create_additions: true)
# # Make a nice display.
-# display = <<EOT
-# Generated JSON:
-# Without custom addition: #{json0} (#{json0.class})
-# With custom addition: #{json1} (#{json1.class})
-# Parsed JSON:
-# Without custom addition: #{obj0.inspect} (#{obj0.class})
-# With custom addition: #{obj1.inspect} (#{obj1.class})
+# display = <<~EOT
+# Generated JSON:
+# Without custom addition: #{json0} (#{json0.class})
+# With custom addition: #{json1} (#{json1.class})
+# Parsed JSON:
+# Without custom addition: #{obj0.inspect} (#{obj0.class})
+# With custom addition: #{obj1.inspect} (#{obj1.class})
# EOT
# puts display
#
@@ -583,10 +650,5 @@ require 'json/common'
#
module JSON
require 'json/version'
-
- begin
- require 'json/ext'
- rescue LoadError
- require 'json/pure'
- end
+ require 'json/ext'
end
diff --git a/ext/json/lib/json/add/bigdecimal.rb b/ext/json/lib/json/add/bigdecimal.rb
index b1d0cfa043..dc84572f31 100644
--- a/ext/json/lib/json/add/bigdecimal.rb
+++ b/ext/json/lib/json/add/bigdecimal.rb
@@ -1,4 +1,4 @@
-#frozen_string_literal: false
+# frozen_string_literal: true
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
require 'json'
end
@@ -35,7 +35,7 @@ class BigDecimal
def as_json(*)
{
JSON.create_id => self.class.name,
- 'b' => _dump,
+ 'b' => _dump.force_encoding(Encoding::UTF_8),
}
end
diff --git a/ext/json/lib/json/add/complex.rb b/ext/json/lib/json/add/complex.rb
index ef48c554c6..9e3c6f2d0a 100644
--- a/ext/json/lib/json/add/complex.rb
+++ b/ext/json/lib/json/add/complex.rb
@@ -1,4 +1,4 @@
-#frozen_string_literal: false
+# frozen_string_literal: true
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
require 'json'
end
diff --git a/ext/json/lib/json/add/core.rb b/ext/json/lib/json/add/core.rb
index bfb017c460..61ff454212 100644
--- a/ext/json/lib/json/add/core.rb
+++ b/ext/json/lib/json/add/core.rb
@@ -1,4 +1,4 @@
-#frozen_string_literal: false
+# frozen_string_literal: true
# This file requires the implementations of ruby core's custom objects for
# serialisation/deserialisation.
@@ -7,6 +7,7 @@ require 'json/add/date_time'
require 'json/add/exception'
require 'json/add/range'
require 'json/add/regexp'
+require 'json/add/string'
require 'json/add/struct'
require 'json/add/symbol'
require 'json/add/time'
diff --git a/ext/json/lib/json/add/date.rb b/ext/json/lib/json/add/date.rb
index 19688f751b..88a098b637 100644
--- a/ext/json/lib/json/add/date.rb
+++ b/ext/json/lib/json/add/date.rb
@@ -1,4 +1,4 @@
-#frozen_string_literal: false
+# frozen_string_literal: true
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
require 'json'
end
diff --git a/ext/json/lib/json/add/date_time.rb b/ext/json/lib/json/add/date_time.rb
index d7d42591cf..8b0bb5d181 100644
--- a/ext/json/lib/json/add/date_time.rb
+++ b/ext/json/lib/json/add/date_time.rb
@@ -1,4 +1,4 @@
-#frozen_string_literal: false
+# frozen_string_literal: true
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
require 'json'
end
diff --git a/ext/json/lib/json/add/exception.rb b/ext/json/lib/json/add/exception.rb
index 71d8deb0ea..e85d404982 100644
--- a/ext/json/lib/json/add/exception.rb
+++ b/ext/json/lib/json/add/exception.rb
@@ -1,4 +1,4 @@
-#frozen_string_literal: false
+# frozen_string_literal: true
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
require 'json'
end
diff --git a/ext/json/lib/json/add/ostruct.rb b/ext/json/lib/json/add/ostruct.rb
index 1e6f408248..7750498144 100644
--- a/ext/json/lib/json/add/ostruct.rb
+++ b/ext/json/lib/json/add/ostruct.rb
@@ -1,4 +1,4 @@
-#frozen_string_literal: false
+# frozen_string_literal: true
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
require 'json'
end
diff --git a/ext/json/lib/json/add/range.rb b/ext/json/lib/json/add/range.rb
index 53f54ac372..408d2c32f6 100644
--- a/ext/json/lib/json/add/range.rb
+++ b/ext/json/lib/json/add/range.rb
@@ -1,4 +1,4 @@
-#frozen_string_literal: false
+# frozen_string_literal: true
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
require 'json'
end
diff --git a/ext/json/lib/json/add/rational.rb b/ext/json/lib/json/add/rational.rb
index 8c39a7db55..c95812ea8e 100644
--- a/ext/json/lib/json/add/rational.rb
+++ b/ext/json/lib/json/add/rational.rb
@@ -1,4 +1,4 @@
-#frozen_string_literal: false
+# frozen_string_literal: true
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
require 'json'
end
diff --git a/ext/json/lib/json/add/regexp.rb b/ext/json/lib/json/add/regexp.rb
index b63f49608f..aebfb2db5c 100644
--- a/ext/json/lib/json/add/regexp.rb
+++ b/ext/json/lib/json/add/regexp.rb
@@ -1,4 +1,4 @@
-#frozen_string_literal: false
+# frozen_string_literal: true
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
require 'json'
end
diff --git a/ext/json/lib/json/add/string.rb b/ext/json/lib/json/add/string.rb
new file mode 100644
index 0000000000..9c3bde27fb
--- /dev/null
+++ b/ext/json/lib/json/add/string.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
+ require 'json'
+end
+
+class String
+ # call-seq: json_create(o)
+ #
+ # Raw Strings are JSON Objects (the raw bytes are stored in an array for the
+ # key "raw"). The Ruby String can be created by this class method.
+ def self.json_create(object)
+ object["raw"].pack("C*")
+ end
+
+ # call-seq: to_json_raw_object()
+ #
+ # This method creates a raw object hash, that can be nested into
+ # other data structures and will be generated as a raw string. This
+ # method should be used, if you want to convert raw strings to JSON
+ # instead of UTF-8 strings, e. g. binary data.
+ def to_json_raw_object
+ {
+ JSON.create_id => self.class.name,
+ "raw" => unpack("C*"),
+ }
+ end
+
+ # call-seq: to_json_raw(*args)
+ #
+ # This method creates a JSON text from the result of a call to
+ # to_json_raw_object of this String.
+ def to_json_raw(...)
+ to_json_raw_object.to_json(...)
+ end
+end
diff --git a/ext/json/lib/json/add/struct.rb b/ext/json/lib/json/add/struct.rb
index 86847762ac..6760c3d86c 100644
--- a/ext/json/lib/json/add/struct.rb
+++ b/ext/json/lib/json/add/struct.rb
@@ -1,4 +1,4 @@
-#frozen_string_literal: false
+# frozen_string_literal: true
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
require 'json'
end
diff --git a/ext/json/lib/json/add/symbol.rb b/ext/json/lib/json/add/symbol.rb
index b5f3623158..806be4f025 100644
--- a/ext/json/lib/json/add/symbol.rb
+++ b/ext/json/lib/json/add/symbol.rb
@@ -1,5 +1,4 @@
-
-#frozen_string_literal: false
+# frozen_string_literal: true
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
require 'json'
end
@@ -37,8 +36,13 @@ class Symbol
#
# # {"json_class":"Symbol","s":"foo"}
#
- def to_json(*a)
- as_json.to_json(*a)
+ def to_json(state = nil, *a)
+ state = ::JSON::State.from_state(state)
+ if state.strict?
+ super
+ else
+ as_json.to_json(state, *a)
+ end
end
# See #as_json.
diff --git a/ext/json/lib/json/add/time.rb b/ext/json/lib/json/add/time.rb
index 599ed9e24b..b03d4ff251 100644
--- a/ext/json/lib/json/add/time.rb
+++ b/ext/json/lib/json/add/time.rb
@@ -1,4 +1,4 @@
-#frozen_string_literal: false
+# frozen_string_literal: true
unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED
require 'json'
end
@@ -10,11 +10,7 @@ class Time
if usec = object.delete('u') # used to be tv_usec -> tv_nsec
object['n'] = usec * 1000
end
- if method_defined?(:tv_nsec)
- at(object['s'], Rational(object['n'], 1000))
- else
- at(object['s'], object['n'] / 1000)
- end
+ at(object['s'], Rational(object['n'], 1000))
end
# Methods <tt>Time#as_json</tt> and +Time.json_create+ may be used
@@ -34,13 +30,10 @@ class Time
# # => 2023-11-25 11:00:56.472846644 -0600
#
def as_json(*)
- nanoseconds = [ tv_usec * 1000 ]
- respond_to?(:tv_nsec) and nanoseconds << tv_nsec
- nanoseconds = nanoseconds.max
{
JSON.create_id => self.class.name,
's' => tv_sec,
- 'n' => nanoseconds,
+ 'n' => tv_nsec,
}
end
diff --git a/ext/json/lib/json/common.rb b/ext/json/lib/json/common.rb
index 95098d3bb4..877b96814e 100644
--- a/ext/json/lib/json/common.rb
+++ b/ext/json/lib/json/common.rb
@@ -1,13 +1,123 @@
-#frozen_string_literal: false
+# frozen_string_literal: true
+
require 'json/version'
module JSON
autoload :GenericObject, 'json/generic_object'
- NOT_SET = Object.new.freeze
- private_constant :NOT_SET
+ module ParserOptions # :nodoc:
+ class << self
+ def prepare(opts)
+ if opts[:object_class] || opts[:array_class]
+ opts = opts.dup
+ on_load = opts[:on_load]
+
+ on_load = object_class_proc(opts[:object_class], on_load) if opts[:object_class]
+ on_load = array_class_proc(opts[:array_class], on_load) if opts[:array_class]
+ opts[:on_load] = on_load
+ end
+
+ if opts.fetch(:create_additions, false) != false
+ opts = create_additions_proc(opts)
+ end
+
+ opts
+ end
+
+ private
+
+ def object_class_proc(object_class, on_load)
+ ->(obj) do
+ if Hash === obj
+ object = object_class.new
+ obj.each { |k, v| object[k] = v }
+ obj = object
+ end
+ on_load.nil? ? obj : on_load.call(obj)
+ end
+ end
+
+ def array_class_proc(array_class, on_load)
+ ->(obj) do
+ if Array === obj
+ array = array_class.new
+ obj.each { |v| array << v }
+ obj = array
+ end
+ on_load.nil? ? obj : on_load.call(obj)
+ end
+ end
+
+ # TODO: extract :create_additions support to another gem for version 3.0
+ def create_additions_proc(opts)
+ if opts[:symbolize_names]
+ raise ArgumentError, "options :symbolize_names and :create_additions cannot be used in conjunction"
+ end
+
+ opts = opts.dup
+ create_additions = opts.fetch(:create_additions, false)
+ on_load = opts[:on_load]
+ object_class = opts[:object_class] || Hash
+
+ opts[:on_load] = ->(object) do
+ case object
+ when String
+ opts[:match_string]&.each do |pattern, klass|
+ if match = pattern.match(object)
+ create_additions_warning if create_additions.nil?
+ object = klass.json_create(object)
+ break
+ end
+ end
+ when object_class
+ if opts[:create_additions] != false
+ if class_path = object[JSON.create_id]
+ klass = begin
+ Object.const_get(class_path)
+ rescue NameError => e
+ raise ArgumentError, "can't get const #{class_path}: #{e}"
+ end
+
+ if klass.respond_to?(:json_creatable?) ? klass.json_creatable? : klass.respond_to?(:json_create)
+ create_additions_warning if create_additions.nil?
+ object = klass.json_create(object)
+ end
+ end
+ end
+ end
+
+ on_load.nil? ? object : on_load.call(object)
+ end
+
+ opts
+ end
+
+ def create_additions_warning
+ JSON.deprecation_warning "JSON.load implicit support for `create_additions: true` is deprecated " \
+ "and will be removed in 3.0, use JSON.unsafe_load or explicitly " \
+ "pass `create_additions: true`"
+ end
+ end
+ end
class << self
+ def deprecation_warning(message, uplevel = 3) # :nodoc:
+ gem_root = File.expand_path("..", __dir__) + "/"
+ caller_locations(uplevel, 10).each do |frame|
+ if frame.path.nil? || frame.path.start_with?(gem_root) || frame.path.end_with?("/truffle/cext_ruby.rb", ".c")
+ uplevel += 1
+ else
+ break
+ end
+ end
+
+ if RUBY_VERSION >= "3.0"
+ warn(message, uplevel: uplevel, category: :deprecated)
+ else
+ warn(message, uplevel: uplevel)
+ end
+ end
+
# :call-seq:
# JSON[object] -> new_array or new_string
#
@@ -19,17 +129,20 @@ module JSON
# Otherwise, calls JSON.generate with +object+ and +opts+ (see method #generate):
# ruby = [0, 1, nil]
# JSON[ruby] # => '[0,1,null]'
- def [](object, opts = {})
- if object.respond_to? :to_str
- JSON.parse(object.to_str, opts)
- else
- JSON.generate(object, opts)
+ def [](object, opts = nil)
+ if object.is_a?(String)
+ return JSON.parse(object, opts)
+ elsif object.respond_to?(:to_str)
+ str = object.to_str
+ if str.is_a?(String)
+ return JSON.parse(str, opts)
+ end
end
+
+ JSON.generate(object, opts)
end
- # Returns the JSON parser class that is used by JSON. This is either
- # JSON::Ext::Parser or JSON::Pure::Parser:
- # JSON.parser # => JSON::Ext::Parser
+ # Returns the JSON parser class that is used by JSON.
attr_reader :parser
# Set the JSON parser class _parser_ to be used by JSON.
@@ -39,32 +152,13 @@ module JSON
const_set :Parser, parser
end
- # Return the constant located at _path_. The format of _path_ has to be
- # either ::A::B::C or A::B::C. In any case, A has to be located at the top
- # level (absolute namespace path?). If there doesn't exist a constant at
- # the given path, an ArgumentError is raised.
- def deep_const_get(path) # :nodoc:
- path.to_s.split(/::/).inject(Object) do |p, c|
- case
- when c.empty? then p
- when p.const_defined?(c, true) then p.const_get(c)
- else
- begin
- p.const_missing(c)
- rescue NameError => e
- raise ArgumentError, "can't get const #{path}: #{e}"
- end
- end
- end
- end
-
# Set the module _generator_ to be used by JSON.
def generator=(generator) # :nodoc:
old, $VERBOSE = $VERBOSE, nil
@generator = generator
generator_methods = generator::GeneratorMethods
for const in generator_methods.constants
- klass = deep_const_get(const)
+ klass = const_get(const)
modul = generator_methods.const_get(const)
klass.class_eval do
instance_methods(false).each do |m|
@@ -74,97 +168,135 @@ module JSON
end
end
self.state = generator::State
- const_set :State, self.state
- const_set :SAFE_STATE_PROTOTYPE, State.new # for JRuby
- const_set :FAST_STATE_PROTOTYPE, create_fast_state
- const_set :PRETTY_STATE_PROTOTYPE, create_pretty_state
+ const_set :State, state
ensure
$VERBOSE = old
end
- def create_fast_state
- State.new(
- :indent => '',
- :space => '',
- :object_nl => "",
- :array_nl => "",
- :max_nesting => false
- )
- end
-
- def create_pretty_state
- State.new(
- :indent => ' ',
- :space => ' ',
- :object_nl => "\n",
- :array_nl => "\n"
- )
- end
-
- # Returns the JSON generator module that is used by JSON. This is
- # either JSON::Ext::Generator or JSON::Pure::Generator:
- # JSON.generator # => JSON::Ext::Generator
+ # Returns the JSON generator module that is used by JSON.
attr_reader :generator
- # Sets or Returns the JSON generator state class that is used by JSON. This is
- # either JSON::Ext::Generator::State or JSON::Pure::Generator::State:
- # JSON.state # => JSON::Ext::Generator::State
+ # Sets or Returns the JSON generator state class that is used by JSON.
attr_accessor :state
- end
- DEFAULT_CREATE_ID = 'json_class'.freeze
- private_constant :DEFAULT_CREATE_ID
+ private
- CREATE_ID_TLS_KEY = "JSON.create_id".freeze
- private_constant :CREATE_ID_TLS_KEY
+ # Called from the extension when a hash has both string and symbol keys
+ def on_mixed_keys_hash(hash, do_raise)
+ set = {}
+ hash.each_key do |key|
+ key_str = key.to_s
+
+ if set[key_str]
+ message = "detected duplicate key #{key_str.inspect} in #{hash.inspect}"
+ if do_raise
+ raise GeneratorError, message
+ else
+ deprecation_warning("#{message}.\nThis will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`")
+ end
+ else
+ set[key_str] = true
+ end
+ end
+ end
+
+ def deprecated_singleton_attr_accessor(*attrs)
+ args = RUBY_VERSION >= "3.0" ? ", category: :deprecated" : ""
+ attrs.each do |attr|
+ singleton_class.class_eval <<~RUBY
+ def #{attr}
+ warn "JSON.#{attr} is deprecated and will be removed in json 3.0.0", uplevel: 1 #{args}
+ @#{attr}
+ end
+
+ def #{attr}=(val)
+ warn "JSON.#{attr}= is deprecated and will be removed in json 3.0.0", uplevel: 1 #{args}
+ @#{attr} = val
+ end
+
+ def _#{attr}
+ @#{attr}
+ end
+ RUBY
+ end
+ end
+ end
# Sets create identifier, which is used to decide if the _json_create_
# hook of a class should be called; initial value is +json_class+:
# JSON.create_id # => 'json_class'
def self.create_id=(new_value)
- Thread.current[CREATE_ID_TLS_KEY] = new_value.dup.freeze
+ Thread.current[:"JSON.create_id"] = new_value.dup.freeze
end
# Returns the current create identifier.
# See also JSON.create_id=.
def self.create_id
- Thread.current[CREATE_ID_TLS_KEY] || DEFAULT_CREATE_ID
+ Thread.current[:"JSON.create_id"] || 'json_class'
end
- NaN = 0.0/0
+ NaN = Float::NAN
- Infinity = 1.0/0
+ Infinity = Float::INFINITY
MinusInfinity = -Infinity
# The base exception for JSON errors.
- class JSONError < StandardError
- def self.wrap(exception)
- obj = new("Wrapped(#{exception.class}): #{exception.message.inspect}")
- obj.set_backtrace exception.backtrace
- obj
- end
- end
+ class JSONError < StandardError; end
# This exception is raised if a parser error occurs.
- class ParserError < JSONError; end
+ class ParserError < JSONError
+ attr_reader :line, :column
+ end
# This exception is raised if the nesting of parsed data structures is too
# deep.
class NestingError < ParserError; end
- # :stopdoc:
- class CircularDatastructure < NestingError; end
- # :startdoc:
-
# This exception is raised if a generator or unparser error occurs.
- class GeneratorError < JSONError; end
- # For backwards compatibility
- UnparserError = GeneratorError # :nodoc:
+ class GeneratorError < JSONError
+ attr_reader :invalid_object
+
+ def initialize(message, invalid_object = nil)
+ super(message)
+ @invalid_object = invalid_object
+ end
+
+ def detailed_message(...)
+ # Exception#detailed_message doesn't exist until Ruby 3.2
+ super_message = defined?(super) ? super : message
+
+ if @invalid_object.nil?
+ super_message
+ else
+ "#{super_message}\nInvalid object: #{@invalid_object.inspect}"
+ end
+ end
+ end
+
+ # Fragment of JSON document that is to be included as is:
+ # fragment = JSON::Fragment.new("[1, 2, 3]")
+ # JSON.generate({ count: 3, items: fragments })
+ #
+ # This allows to easily assemble multiple JSON fragments that have
+ # been persisted somewhere without having to parse them nor resorting
+ # to string interpolation.
+ #
+ # Note: no validation is performed on the provided string. It is the
+ # responsibility of the caller to ensure the string contains valid JSON.
+ Fragment = Struct.new(:json) do
+ def initialize(json)
+ unless string = String.try_convert(json)
+ raise TypeError, " no implicit conversion of #{json.class} into String"
+ end
+
+ super(string)
+ end
- # This exception is raised if the required unicode support is missing on the
- # system. Usually this means that the iconv library is not installed.
- class MissingUnicodeSupport < JSONError; end
+ def to_json(state = nil, *)
+ json
+ end
+ end
module_function
@@ -196,17 +328,17 @@ module JSON
# {Parsing \JSON}[#module-JSON-label-Parsing+JSON].
#
# Parses nested JSON objects:
- # source = <<-EOT
- # {
- # "name": "Dave",
- # "age" :40,
- # "hats": [
- # "Cattleman's",
- # "Panama",
- # "Tophat"
- # ]
- # }
- # EOT
+ # source = <<~JSON
+ # {
+ # "name": "Dave",
+ # "age" :40,
+ # "hats": [
+ # "Cattleman's",
+ # "Panama",
+ # "Tophat"
+ # ]
+ # }
+ # JSON
# ruby = JSON.parse(source)
# ruby # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
#
@@ -216,10 +348,17 @@ module JSON
# # Raises JSON::ParserError (783: unexpected token at ''):
# JSON.parse('')
#
- def parse(source, opts = {})
- Parser.new(source, **(opts||{})).parse
+ def parse(source, opts = nil)
+ opts = ParserOptions.prepare(opts) unless opts.nil?
+ Parser.parse(source, opts)
end
+ PARSE_L_OPTIONS = {
+ max_nesting: false,
+ allow_nan: true,
+ }.freeze
+ private_constant :PARSE_L_OPTIONS
+
# :call-seq:
# JSON.parse!(source, opts) -> object
#
@@ -231,12 +370,12 @@ module JSON
# - Option +max_nesting+, if not provided, defaults to +false+,
# which disables checking for nesting depth.
# - Option +allow_nan+, if not provided, defaults to +true+.
- def parse!(source, opts = {})
- opts = {
- :max_nesting => false,
- :allow_nan => true
- }.merge(opts)
- Parser.new(source, **(opts||{})).parse
+ def parse!(source, opts = nil)
+ if opts.nil?
+ parse(source, PARSE_L_OPTIONS)
+ else
+ parse(source, PARSE_L_OPTIONS.merge(opts))
+ end
end
# :call-seq:
@@ -246,8 +385,8 @@ module JSON
# parse(File.read(path), opts)
#
# See method #parse.
- def load_file(filespec, opts = {})
- parse(File.read(filespec), opts)
+ def load_file(filespec, opts = nil)
+ parse(File.read(filespec, encoding: Encoding::UTF_8), opts)
end
# :call-seq:
@@ -257,8 +396,8 @@ module JSON
# JSON.parse!(File.read(path, opts))
#
# See method #parse!
- def load_file!(filespec, opts = {})
- parse!(File.read(filespec), opts)
+ def load_file!(filespec, opts = nil)
+ parse!(File.read(filespec, encoding: Encoding::UTF_8), opts)
end
# :call-seq:
@@ -266,7 +405,7 @@ module JSON
#
# Returns a \String containing the generated \JSON data.
#
- # See also JSON.fast_generate, JSON.pretty_generate.
+ # See also JSON.pretty_generate.
#
# Argument +obj+ is the Ruby object to be converted to \JSON.
#
@@ -299,20 +438,12 @@ module JSON
#
def generate(obj, opts = nil)
if State === opts
- state = opts
+ opts.generate(obj)
else
- state = State.new(opts)
+ State.generate(obj, opts, nil)
end
- state.generate(obj)
end
- # :stopdoc:
- # I want to deprecate these later, so I'll first be silent about them, and
- # later delete them.
- alias unparse generate
- module_function :unparse
- # :startdoc:
-
# :call-seq:
# JSON.fast_generate(obj, opts) -> new_string
#
@@ -327,19 +458,21 @@ module JSON
# # Raises SystemStackError (stack level too deep):
# JSON.fast_generate(a)
def fast_generate(obj, opts = nil)
- if State === opts
- state = opts
+ if RUBY_VERSION >= "3.0"
+ warn "JSON.fast_generate is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1, category: :deprecated
else
- state = JSON.create_fast_state.configure(opts)
+ warn "JSON.fast_generate is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1
end
- state.generate(obj)
+ generate(obj, opts)
end
- # :stopdoc:
- # I want to deprecate these later, so I'll first be silent about them, and later delete them.
- alias fast_unparse fast_generate
- module_function :fast_unparse
- # :startdoc:
+ PRETTY_GENERATE_OPTIONS = {
+ indent: ' ',
+ space: ' ',
+ object_nl: "\n",
+ array_nl: "\n",
+ }.freeze
+ private_constant :PRETTY_GENERATE_OPTIONS
# :call-seq:
# JSON.pretty_generate(obj, opts = nil) -> new_string
@@ -372,49 +505,60 @@ module JSON
# }
#
def pretty_generate(obj, opts = nil)
- if State === opts
- state, opts = opts, nil
- else
- state = JSON.create_pretty_state
- end
+ return opts.generate(obj) if State === opts
+
+ options = PRETTY_GENERATE_OPTIONS
+
if opts
- if opts.respond_to? :to_hash
- opts = opts.to_hash
- elsif opts.respond_to? :to_h
- opts = opts.to_h
- else
- raise TypeError, "can't convert #{opts.class} into Hash"
+ unless opts.is_a?(Hash)
+ if opts.respond_to? :to_hash
+ opts = opts.to_hash
+ elsif opts.respond_to? :to_h
+ opts = opts.to_h
+ else
+ raise TypeError, "can't convert #{opts.class} into Hash"
+ end
end
- state.configure(opts)
+ options = options.merge(opts)
end
- state.generate(obj)
+
+ State.generate(obj, options, nil)
end
- # :stopdoc:
- # I want to deprecate these later, so I'll first be silent about them, and later delete them.
- alias pretty_unparse pretty_generate
- module_function :pretty_unparse
- # :startdoc:
+ # Sets or returns default options for the JSON.unsafe_load method.
+ # Initially:
+ # opts = JSON.load_default_options
+ # opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true}
+ deprecated_singleton_attr_accessor :unsafe_load_default_options
- class << self
- # Sets or returns default options for the JSON.load method.
- # Initially:
- # opts = JSON.load_default_options
- # opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true}
- attr_accessor :load_default_options
- end
- self.load_default_options = {
+ @unsafe_load_default_options = {
:max_nesting => false,
:allow_nan => true,
- :allow_blank => true,
+ :allow_blank => true,
:create_additions => true,
}
+ # Sets or returns default options for the JSON.load method.
+ # Initially:
+ # opts = JSON.load_default_options
+ # opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true}
+ deprecated_singleton_attr_accessor :load_default_options
+
+ @load_default_options = {
+ :allow_nan => true,
+ :allow_blank => true,
+ :create_additions => nil,
+ }
# :call-seq:
- # JSON.load(source, proc = nil, options = {}) -> object
+ # JSON.unsafe_load(source, options = {}) -> object
+ # JSON.unsafe_load(source, proc = nil, options = {}) -> object
#
# Returns the Ruby objects created by parsing the given +source+.
#
+ # BEWARE: This method is meant to serialise data from trusted user input,
+ # like from your own database server or clients under your control, it could
+ # be dangerous to allow untrusted users to pass JSON sources into it.
+ #
# - Argument +source+ must be, or be convertible to, a \String:
# - If +source+ responds to instance method +to_str+,
# <tt>source.to_str</tt> becomes the source.
@@ -429,12 +573,9 @@ module JSON
# - Argument +proc+, if given, must be a \Proc that accepts one argument.
# It will be called recursively with each result (depth-first order).
# See details below.
- # BEWARE: This method is meant to serialise data from trusted user input,
- # like from your own database server or clients under your control, it could
- # be dangerous to allow untrusted users to pass JSON sources into it.
# - Argument +opts+, if given, contains a \Hash of options for the parsing.
# See {Parsing Options}[#module-JSON-label-Parsing+Options].
- # The default options can be changed via method JSON.load_default_options=.
+ # The default options can be changed via method JSON.unsafe_load_default_options=.
#
# ---
#
@@ -442,17 +583,188 @@ module JSON
# <tt>parse(source, opts)</tt>; see #parse.
#
# Source for following examples:
- # source = <<-EOT
+ # source = <<~JSON
+ # {
+ # "name": "Dave",
+ # "age" :40,
+ # "hats": [
+ # "Cattleman's",
+ # "Panama",
+ # "Tophat"
+ # ]
+ # }
+ # JSON
+ #
+ # Load a \String:
+ # ruby = JSON.unsafe_load(source)
+ # ruby # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
+ #
+ # Load an \IO object:
+ # require 'stringio'
+ # object = JSON.unsafe_load(StringIO.new(source))
+ # object # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
+ #
+ # Load a \File object:
+ # path = 't.json'
+ # File.write(path, source)
+ # File.open(path) do |file|
+ # JSON.unsafe_load(file)
+ # end # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]}
+ #
+ # ---
+ #
+ # When +proc+ is given:
+ # - Modifies +source+ as above.
+ # - Gets the +result+ from calling <tt>parse(source, opts)</tt>.
+ # - Recursively calls <tt>proc(result)</tt>.
+ # - Returns the final result.
+ #
+ # Example:
+ # require 'json'
+ #
+ # # Some classes for the example.
+ # class Base
+ # def initialize(attributes)
+ # @attributes = attributes
+ # end
+ # end
+ # class User < Base; end
+ # class Account < Base; end
+ # class Admin < Base; end
+ # # The JSON source.
+ # json = <<-EOF
# {
- # "name": "Dave",
- # "age" :40,
- # "hats": [
- # "Cattleman's",
- # "Panama",
- # "Tophat"
- # ]
+ # "users": [
+ # {"type": "User", "username": "jane", "email": "jane@example.com"},
+ # {"type": "User", "username": "john", "email": "john@example.com"}
+ # ],
+ # "accounts": [
+ # {"account": {"type": "Account", "paid": true, "account_id": "1234"}},
+ # {"account": {"type": "Account", "paid": false, "account_id": "1235"}}
+ # ],
+ # "admins": {"type": "Admin", "password": "0wn3d"}
# }
- # EOT
+ # EOF
+ # # Deserializer method.
+ # def deserialize_obj(obj, safe_types = %w(User Account Admin))
+ # type = obj.is_a?(Hash) && obj["type"]
+ # safe_types.include?(type) ? Object.const_get(type).new(obj) : obj
+ # end
+ # # Call to JSON.unsafe_load
+ # ruby = JSON.unsafe_load(json, proc {|obj|
+ # case obj
+ # when Hash
+ # obj.each {|k, v| obj[k] = deserialize_obj v }
+ # when Array
+ # obj.map! {|v| deserialize_obj v }
+ # end
+ # obj
+ # })
+ # pp ruby
+ # Output:
+ # {"users"=>
+ # [#<User:0x00000000064c4c98
+ # @attributes=
+ # {"type"=>"User", "username"=>"jane", "email"=>"jane@example.com"}>,
+ # #<User:0x00000000064c4bd0
+ # @attributes=
+ # {"type"=>"User", "username"=>"john", "email"=>"john@example.com"}>],
+ # "accounts"=>
+ # [{"account"=>
+ # #<Account:0x00000000064c4928
+ # @attributes={"type"=>"Account", "paid"=>true, "account_id"=>"1234"}>},
+ # {"account"=>
+ # #<Account:0x00000000064c4680
+ # @attributes={"type"=>"Account", "paid"=>false, "account_id"=>"1235"}>}],
+ # "admins"=>
+ # #<Admin:0x00000000064c41f8
+ # @attributes={"type"=>"Admin", "password"=>"0wn3d"}>}
+ #
+ def unsafe_load(source, proc = nil, options = nil)
+ opts = if options.nil?
+ if proc && proc.is_a?(Hash)
+ options, proc = proc, nil
+ options
+ else
+ _unsafe_load_default_options
+ end
+ else
+ _unsafe_load_default_options.merge(options)
+ end
+
+ unless source.is_a?(String)
+ if source.respond_to? :to_str
+ source = source.to_str
+ elsif source.respond_to? :to_io
+ source = source.to_io.read
+ elsif source.respond_to?(:read)
+ source = source.read
+ end
+ end
+
+ if opts[:allow_blank] && (source.nil? || source.empty?)
+ source = 'null'
+ end
+
+ if proc
+ opts = opts.dup
+ opts[:on_load] = proc.to_proc
+ end
+
+ parse(source, opts)
+ end
+
+ # :call-seq:
+ # JSON.load(source, options = {}) -> object
+ # JSON.load(source, proc = nil, options = {}) -> object
+ #
+ # Returns the Ruby objects created by parsing the given +source+.
+ #
+ # BEWARE: This method is meant to serialise data from trusted user input,
+ # like from your own database server or clients under your control, it could
+ # be dangerous to allow untrusted users to pass JSON sources into it.
+ # If you must use it, use JSON.unsafe_load instead to make it clear.
+ #
+ # Since JSON version 2.8.0, `load` emits a deprecation warning when a
+ # non native type is deserialized, without `create_additions` being explicitly
+ # enabled, and in JSON version 3.0, `load` will have `create_additions` disabled
+ # by default.
+ #
+ # - Argument +source+ must be, or be convertible to, a \String:
+ # - If +source+ responds to instance method +to_str+,
+ # <tt>source.to_str</tt> becomes the source.
+ # - If +source+ responds to instance method +to_io+,
+ # <tt>source.to_io.read</tt> becomes the source.
+ # - If +source+ responds to instance method +read+,
+ # <tt>source.read</tt> becomes the source.
+ # - If both of the following are true, source becomes the \String <tt>'null'</tt>:
+ # - Option +allow_blank+ specifies a truthy value.
+ # - The source, as defined above, is +nil+ or the empty \String <tt>''</tt>.
+ # - Otherwise, +source+ remains the source.
+ # - Argument +proc+, if given, must be a \Proc that accepts one argument.
+ # It will be called recursively with each result (depth-first order).
+ # See details below.
+ # - Argument +opts+, if given, contains a \Hash of options for the parsing.
+ # See {Parsing Options}[#module-JSON-label-Parsing+Options].
+ # The default options can be changed via method JSON.load_default_options=.
+ #
+ # ---
+ #
+ # When no +proc+ is given, modifies +source+ as above and returns the result of
+ # <tt>parse(source, opts)</tt>; see #parse.
+ #
+ # Source for following examples:
+ # source = <<~JSON
+ # {
+ # "name": "Dave",
+ # "age" :40,
+ # "hats": [
+ # "Cattleman's",
+ # "Panama",
+ # "Tophat"
+ # ]
+ # }
+ # JSON
#
# Load a \String:
# ruby = JSON.load(source)
@@ -517,6 +829,7 @@ module JSON
# when Array
# obj.map! {|v| deserialize_obj v }
# end
+ # obj
# })
# pp ruby
# Output:
@@ -538,51 +851,53 @@ module JSON
# #<Admin:0x00000000064c41f8
# @attributes={"type"=>"Admin", "password"=>"0wn3d"}>}
#
- def load(source, proc = nil, options = {})
- opts = load_default_options.merge options
- if source.respond_to? :to_str
- source = source.to_str
- elsif source.respond_to? :to_io
- source = source.to_io.read
- elsif source.respond_to?(:read)
- source = source.read
+ def load(source, proc = nil, options = nil)
+ if proc && options.nil? && proc.is_a?(Hash)
+ options = proc
+ proc = nil
end
+
+ opts = if options.nil?
+ if proc && proc.is_a?(Hash)
+ options, proc = proc, nil
+ options
+ else
+ _load_default_options
+ end
+ else
+ _load_default_options.merge(options)
+ end
+
+ unless source.is_a?(String)
+ if source.respond_to? :to_str
+ source = source.to_str
+ elsif source.respond_to? :to_io
+ source = source.to_io.read
+ elsif source.respond_to?(:read)
+ source = source.read
+ end
+ end
+
if opts[:allow_blank] && (source.nil? || source.empty?)
source = 'null'
end
- result = parse(source, opts)
- recurse_proc(result, &proc) if proc
- result
- end
- # Recursively calls passed _Proc_ if the parsed data structure is an _Array_ or _Hash_
- def recurse_proc(result, &proc) # :nodoc:
- case result
- when Array
- result.each { |x| recurse_proc x, &proc }
- proc.call result
- when Hash
- result.each { |x, y| recurse_proc x, &proc; recurse_proc y, &proc }
- proc.call result
- else
- proc.call result
+ if proc
+ opts = opts.dup
+ opts[:on_load] = proc.to_proc
end
- end
-
- alias restore load
- module_function :restore
- class << self
- # Sets or returns the default options for the JSON.dump method.
- # Initially:
- # opts = JSON.dump_default_options
- # opts # => {:max_nesting=>false, :allow_nan=>true, :script_safe=>false}
- attr_accessor :dump_default_options
+ parse(source, opts)
end
- self.dump_default_options = {
+
+ # Sets or returns the default options for the JSON.dump method.
+ # Initially:
+ # opts = JSON.dump_default_options
+ # opts # => {:max_nesting=>false, :allow_nan=>true}
+ deprecated_singleton_attr_accessor :dump_default_options
+ @dump_default_options = {
:max_nesting => false,
:allow_nan => true,
- :script_safe => false,
}
# :call-seq:
@@ -613,40 +928,172 @@ module JSON
# Output:
# {"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"}
def dump(obj, anIO = nil, limit = nil, kwargs = nil)
- io_limit_opt = [anIO, limit, kwargs].compact
- kwargs = io_limit_opt.pop if io_limit_opt.last.is_a?(Hash)
- anIO, limit = io_limit_opt
- if anIO.respond_to?(:to_io)
- anIO = anIO.to_io
- elsif limit.nil? && !anIO.respond_to?(:write)
- anIO, limit = nil, anIO
- end
- opts = JSON.dump_default_options
+ if kwargs.nil?
+ if limit.nil?
+ if anIO.is_a?(Hash)
+ kwargs = anIO
+ anIO = nil
+ end
+ elsif limit.is_a?(Hash)
+ kwargs = limit
+ limit = nil
+ end
+ end
+
+ unless anIO.nil?
+ if anIO.respond_to?(:to_io)
+ anIO = anIO.to_io
+ elsif limit.nil? && !anIO.respond_to?(:write)
+ anIO, limit = nil, anIO
+ end
+ end
+
+ opts = JSON._dump_default_options
opts = opts.merge(:max_nesting => limit) if limit
- opts = merge_dump_options(opts, **kwargs) if kwargs
- result = generate(obj, opts)
- if anIO
- anIO.write result
- anIO
+ opts = opts.merge(kwargs) if kwargs
+
+ begin
+ State.generate(obj, opts, anIO)
+ rescue JSON::NestingError
+ raise ArgumentError, "exceed depth limit"
+ end
+ end
+
+ # :stopdoc:
+ # All these were meant to be deprecated circa 2009, but were just set as undocumented
+ # so usage still exist in the wild.
+ def unparse(...)
+ if RUBY_VERSION >= "3.0"
+ warn "JSON.unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1, category: :deprecated
else
- result
+ warn "JSON.unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1
end
- rescue JSON::NestingError
- raise ArgumentError, "exceed depth limit"
+ generate(...)
end
+ module_function :unparse
- # Encodes string using String.encode.
- def self.iconv(to, from, string)
- string.encode(to, from)
+ def fast_unparse(...)
+ if RUBY_VERSION >= "3.0"
+ warn "JSON.fast_unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1, category: :deprecated
+ else
+ warn "JSON.fast_unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1
+ end
+ generate(...)
end
+ module_function :fast_unparse
- def merge_dump_options(opts, strict: NOT_SET)
- opts = opts.merge(strict: strict) if NOT_SET != strict
- opts
+ def pretty_unparse(...)
+ if RUBY_VERSION >= "3.0"
+ warn "JSON.pretty_unparse is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1, category: :deprecated
+ else
+ warn "JSON.pretty_unparse is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1
+ end
+ pretty_generate(...)
+ end
+ module_function :fast_unparse
+
+ def restore(...)
+ if RUBY_VERSION >= "3.0"
+ warn "JSON.restore is deprecated and will be removed in json 3.0.0, just use JSON.load", uplevel: 1, category: :deprecated
+ else
+ warn "JSON.restore is deprecated and will be removed in json 3.0.0, just use JSON.load", uplevel: 1
+ end
+ load(...)
end
+ module_function :restore
class << self
- private :merge_dump_options
+ private
+
+ def const_missing(const_name)
+ case const_name
+ when :PRETTY_STATE_PROTOTYPE
+ if RUBY_VERSION >= "3.0"
+ warn "JSON::PRETTY_STATE_PROTOTYPE is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1, category: :deprecated
+ else
+ warn "JSON::PRETTY_STATE_PROTOTYPE is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1
+ end
+ state.new(PRETTY_GENERATE_OPTIONS)
+ else
+ super
+ end
+ end
+ end
+ # :startdoc:
+
+ # JSON::Coder holds a parser and generator configuration.
+ #
+ # module MyApp
+ # JSONC_CODER = JSON::Coder.new(
+ # allow_trailing_comma: true
+ # )
+ # end
+ #
+ # MyApp::JSONC_CODER.load(document)
+ #
+ class Coder
+ # :call-seq:
+ # JSON.new(options = nil, &block)
+ #
+ # Argument +options+, if given, contains a \Hash of options for both parsing and generating.
+ # See {Parsing Options}[#module-JSON-label-Parsing+Options], and {Generating Options}[#module-JSON-label-Generating+Options].
+ #
+ # For generation, the <tt>strict: true</tt> option is always set. When a Ruby object with no native \JSON counterpart is
+ # encountered, the block provided to the initialize method is invoked, and must return a Ruby object that has a native
+ # \JSON counterpart:
+ #
+ # module MyApp
+ # API_JSON_CODER = JSON::Coder.new do |object|
+ # case object
+ # when Time
+ # object.iso8601(3)
+ # else
+ # object # Unknown type, will raise
+ # end
+ # end
+ # end
+ #
+ # puts MyApp::API_JSON_CODER.dump(Time.now.utc) # => "2025-01-21T08:41:44.286Z"
+ #
+ def initialize(options = nil, &as_json)
+ if options.nil?
+ options = { strict: true }
+ else
+ options = options.dup
+ options[:strict] = true
+ end
+ options[:as_json] = as_json if as_json
+
+ @state = State.new(options).freeze
+ @parser_config = Ext::Parser::Config.new(ParserOptions.prepare(options)).freeze
+ end
+
+ # call-seq:
+ # dump(object) -> String
+ # dump(object, io) -> io
+ #
+ # Serialize the given object into a \JSON document.
+ def dump(object, io = nil)
+ @state.generate(object, io)
+ end
+ alias_method :generate, :dump
+
+ # call-seq:
+ # load(string) -> Object
+ #
+ # Parse the given \JSON document and return an equivalent Ruby object.
+ def load(source)
+ @parser_config.parse(source)
+ end
+ alias_method :parse, :load
+
+ # call-seq:
+ # load(path) -> Object
+ #
+ # Parse the given \JSON document and return an equivalent Ruby object.
+ def load_file(path)
+ load(File.read(path, encoding: Encoding::UTF_8))
+ end
end
end
@@ -656,8 +1103,14 @@ module ::Kernel
# Outputs _objs_ to STDOUT as JSON strings in the shortest form, that is in
# one line.
def j(*objs)
+ if RUBY_VERSION >= "3.0"
+ warn "Kernel#j is deprecated and will be removed in json 3.0.0", uplevel: 1, category: :deprecated
+ else
+ warn "Kernel#j is deprecated and will be removed in json 3.0.0", uplevel: 1
+ end
+
objs.each do |obj|
- puts JSON::generate(obj, :allow_nan => true, :max_nesting => false)
+ puts JSON.generate(obj, :allow_nan => true, :max_nesting => false)
end
nil
end
@@ -665,8 +1118,14 @@ module ::Kernel
# Outputs _objs_ to STDOUT as JSON strings in a pretty format, with
# indentation and over many lines.
def jj(*objs)
+ if RUBY_VERSION >= "3.0"
+ warn "Kernel#jj is deprecated and will be removed in json 3.0.0", uplevel: 1, category: :deprecated
+ else
+ warn "Kernel#jj is deprecated and will be removed in json 3.0.0", uplevel: 1
+ end
+
objs.each do |obj|
- puts JSON::pretty_generate(obj, :allow_nan => true, :max_nesting => false)
+ puts JSON.pretty_generate(obj, :allow_nan => true, :max_nesting => false)
end
nil
end
@@ -677,22 +1136,7 @@ module ::Kernel
#
# The _opts_ argument is passed through to generate/parse respectively. See
# generate and parse for their documentation.
- def JSON(object, *args)
- if object.respond_to? :to_str
- JSON.parse(object.to_str, args.first)
- else
- JSON.generate(object, args.first)
- end
- end
-end
-
-# Extends any Class to include _json_creatable?_ method.
-class ::Class
- # Returns true if this class can be used to create an instance
- # from a serialised JSON string. The class has to implement a class
- # method _json_create_ that expects a hash as first parameter. The hash
- # should include the required data.
- def json_creatable?
- respond_to?(:json_create)
+ def JSON(object, opts = nil)
+ JSON[object, opts]
end
end
diff --git a/ext/json/lib/json/ext.rb b/ext/json/lib/json/ext.rb
index 7264a857fa..5bacc5e371 100644
--- a/ext/json/lib/json/ext.rb
+++ b/ext/json/lib/json/ext.rb
@@ -1,15 +1,45 @@
+# frozen_string_literal: true
+
require 'json/common'
module JSON
# This module holds all the modules/classes that implement JSON's
# functionality as C extensions.
module Ext
+ class Parser
+ class << self
+ def parse(...)
+ new(...).parse
+ end
+ alias_method :parse, :parse # Allow redefinition by extensions
+ end
+
+ def initialize(source, opts = nil)
+ @source = source
+ @config = Config.new(opts)
+ end
+
+ def source
+ @source.dup
+ end
+
+ def parse
+ @config.parse(@source)
+ end
+ end
+
require 'json/ext/parser'
- require 'json/ext/generator'
- $DEBUG and warn "Using Ext extension for JSON."
- JSON.parser = Parser
- JSON.generator = Generator
+ Ext::Parser::Config = Ext::ParserConfig
+ JSON.parser = Ext::Parser
+
+ if RUBY_ENGINE == 'truffleruby'
+ require 'json/truffle_ruby/generator'
+ JSON.generator = JSON::TruffleRuby::Generator
+ else
+ require 'json/ext/generator'
+ JSON.generator = Generator
+ end
end
- JSON_LOADED = true unless defined?(::JSON::JSON_LOADED)
+ JSON_LOADED = true unless defined?(JSON::JSON_LOADED)
end
diff --git a/ext/json/lib/json/ext/generator/state.rb b/ext/json/lib/json/ext/generator/state.rb
new file mode 100644
index 0000000000..ce5c185cab
--- /dev/null
+++ b/ext/json/lib/json/ext/generator/state.rb
@@ -0,0 +1,103 @@
+# frozen_string_literal: true
+
+module JSON
+ module Ext
+ module Generator
+ class State
+ # call-seq: new(opts = {})
+ #
+ # Instantiates a new State object, configured by _opts_.
+ #
+ # Argument +opts+, if given, contains a \Hash of options for the generation.
+ # See {Generating Options}[#module-JSON-label-Generating+Options].
+ def initialize(opts = nil)
+ if opts && !opts.empty?
+ configure(opts)
+ end
+ end
+
+ # call-seq: configure(opts)
+ #
+ # Configure this State instance with the Hash _opts_, and return
+ # itself.
+ def configure(opts)
+ unless opts.is_a?(Hash)
+ if opts.respond_to?(:to_hash)
+ opts = opts.to_hash
+ elsif opts.respond_to?(:to_h)
+ opts = opts.to_h
+ else
+ raise TypeError, "can't convert #{opts.class} into Hash"
+ end
+ end
+ _configure(opts)
+ end
+
+ alias_method :merge, :configure
+
+ # call-seq: to_h
+ #
+ # Returns the configuration instance variables as a hash, that can be
+ # passed to the configure method.
+ def to_h
+ result = {
+ indent: indent,
+ space: space,
+ space_before: space_before,
+ object_nl: object_nl,
+ array_nl: array_nl,
+ as_json: as_json,
+ allow_nan: allow_nan?,
+ ascii_only: ascii_only?,
+ max_nesting: max_nesting,
+ script_safe: script_safe?,
+ strict: strict?,
+ depth: depth,
+ buffer_initial_length: buffer_initial_length,
+ }
+
+ allow_duplicate_key = allow_duplicate_key?
+ unless allow_duplicate_key.nil?
+ result[:allow_duplicate_key] = allow_duplicate_key
+ end
+
+ instance_variables.each do |iv|
+ iv = iv.to_s[1..-1]
+ result[iv.to_sym] = self[iv]
+ end
+
+ result
+ end
+
+ alias_method :to_hash, :to_h
+
+ # call-seq: [](name)
+ #
+ # Returns the value returned by method +name+.
+ def [](name)
+ ::JSON.deprecation_warning("JSON::State#[] is deprecated and will be removed in json 3.0.0")
+
+ if respond_to?(name)
+ __send__(name)
+ else
+ instance_variable_get("@#{name}") if
+ instance_variables.include?("@#{name}".to_sym) # avoid warning
+ end
+ end
+
+ # call-seq: []=(name, value)
+ #
+ # Sets the attribute name to value.
+ def []=(name, value)
+ ::JSON.deprecation_warning("JSON::State#[]= is deprecated and will be removed in json 3.0.0")
+
+ if respond_to?(name_writer = "#{name}=")
+ __send__ name_writer, value
+ else
+ instance_variable_set "@#{name}", value
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/ext/json/lib/json/generic_object.rb b/ext/json/lib/json/generic_object.rb
index 56efda6495..5c8ace354b 100644
--- a/ext/json/lib/json/generic_object.rb
+++ b/ext/json/lib/json/generic_object.rb
@@ -1,4 +1,4 @@
-#frozen_string_literal: false
+# frozen_string_literal: true
begin
require 'ostruct'
rescue LoadError
@@ -52,14 +52,6 @@ module JSON
table
end
- def [](name)
- __send__(name)
- end unless method_defined?(:[])
-
- def []=(name, value)
- __send__("#{name}=", value)
- end unless method_defined?(:[]=)
-
def |(other)
self.class[other.to_hash.merge(to_hash)]
end
diff --git a/ext/json/lib/json/version.rb b/ext/json/lib/json/version.rb
index 836f47edf4..631beba83e 100644
--- a/ext/json/lib/json/version.rb
+++ b/ext/json/lib/json/version.rb
@@ -1,9 +1,5 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
+
module JSON
- # JSON version
- VERSION = '2.7.2'
- VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc:
- VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
- VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
- VERSION_BUILD = VERSION_ARRAY[2] # :nodoc:
+ VERSION = '2.18.0'
end
diff --git a/ext/json/parser/depend b/ext/json/parser/depend
index f3422b4f84..d4737b1dfb 100644
--- a/ext/json/parser/depend
+++ b/ext/json/parser/depend
@@ -1,5 +1,5 @@
$(OBJS): $(ruby_headers)
-parser.o: parser.c parser.h $(srcdir)/../fbuffer/fbuffer.h
+parser.o: parser.c $(srcdir)/../fbuffer/fbuffer.h
# AUTOGENERATED DEPENDENCIES START
parser.o: $(RUBY_EXTCONF_H)
@@ -141,6 +141,7 @@ parser.o: $(hdrdir)/ruby/internal/intern/re.h
parser.o: $(hdrdir)/ruby/internal/intern/ruby.h
parser.o: $(hdrdir)/ruby/internal/intern/select.h
parser.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+parser.o: $(hdrdir)/ruby/internal/intern/set.h
parser.o: $(hdrdir)/ruby/internal/intern/signal.h
parser.o: $(hdrdir)/ruby/internal/intern/sprintf.h
parser.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -174,7 +175,8 @@ parser.o: $(hdrdir)/ruby/ruby.h
parser.o: $(hdrdir)/ruby/st.h
parser.o: $(hdrdir)/ruby/subst.h
parser.o: $(srcdir)/../fbuffer/fbuffer.h
+parser.o: $(srcdir)/../json.h
+parser.o: $(srcdir)/../simd/simd.h
+parser.o: $(srcdir)/../vendor/ryu.h
parser.o: parser.c
-parser.o: parser.h
-parser.o: parser.rl
# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/json/parser/extconf.rb b/ext/json/parser/extconf.rb
index feb586e1b4..2440e66d8b 100644
--- a/ext/json/parser/extconf.rb
+++ b/ext/json/parser/extconf.rb
@@ -1,32 +1,16 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require 'mkmf'
-have_func("rb_enc_raise", "ruby.h")
-have_func("rb_enc_interned_str", "ruby.h")
+$defs << "-DJSON_DEBUG" if ENV.fetch("JSON_DEBUG", "0") != "0"
+have_func("rb_enc_interned_str", "ruby/encoding.h") # RUBY_VERSION >= 3.0
+have_func("rb_str_to_interned_str", "ruby.h") # RUBY_VERSION >= 3.0
+have_func("rb_hash_new_capa", "ruby.h") # RUBY_VERSION >= 3.2
+have_func("rb_hash_bulk_insert", "ruby.h") # Missing on TruffleRuby
-# checking if String#-@ (str_uminus) dedupes... '
-begin
- a = -(%w(t e s t).join)
- b = -(%w(t e s t).join)
- if a.equal?(b)
- $CFLAGS << ' -DSTR_UMINUS_DEDUPE=1 '
- else
- $CFLAGS << ' -DSTR_UMINUS_DEDUPE=0 '
- end
-rescue NoMethodError
- $CFLAGS << ' -DSTR_UMINUS_DEDUPE=0 '
-end
+append_cflags("-std=c99")
-# checking if String#-@ (str_uminus) directly interns frozen strings... '
-begin
- s = rand.to_s.freeze
- if (-s).equal?(s) && (-s.dup).equal?(s)
- $CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=1 '
- else
- $CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=0 '
- end
-rescue NoMethodError
- $CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=0 '
+if enable_config('parser-use-simd', default=!ENV["JSON_DISABLE_SIMD"])
+ load __dir__ + "/../simd/conf.rb"
end
create_makefile 'json/ext/parser'
diff --git a/ext/json/parser/parser.c b/ext/json/parser/parser.c
index 57f87432b6..f1ea1b6abb 100644
--- a/ext/json/parser/parser.c
+++ b/ext/json/parser/parser.c
@@ -1,69 +1,301 @@
-/* This file is automatically generated from parser.rl by using ragel */
-#line 1 "parser.rl"
-#include "../fbuffer/fbuffer.h"
-#include "parser.h"
-
-#if defined HAVE_RUBY_ENCODING_H
-# define EXC_ENCODING rb_utf8_encoding(),
-# ifndef HAVE_RB_ENC_RAISE
+#include "../json.h"
+#include "../vendor/ryu.h"
+#include "../simd/simd.h"
+
+static VALUE mJSON, eNestingError, Encoding_UTF_8;
+static VALUE CNaN, CInfinity, CMinusInfinity;
+
+static ID i_new, i_try_convert, i_uminus, i_encode;
+
+static VALUE sym_max_nesting, sym_allow_nan, sym_allow_trailing_comma, sym_allow_control_characters, sym_symbolize_names, sym_freeze,
+ sym_decimal_class, sym_on_load, sym_allow_duplicate_key;
+
+static int binary_encindex;
+static int utf8_encindex;
+
+#ifndef HAVE_RB_HASH_BULK_INSERT
+// For TruffleRuby
static void
-enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
+rb_hash_bulk_insert(long count, const VALUE *pairs, VALUE hash)
{
- va_list args;
- VALUE mesg;
+ long index = 0;
+ while (index < count) {
+ VALUE name = pairs[index++];
+ VALUE value = pairs[index++];
+ rb_hash_aset(hash, name, value);
+ }
+ RB_GC_GUARD(hash);
+}
+#endif
- va_start(args, fmt);
- mesg = rb_enc_vsprintf(enc, fmt, args);
- va_end(args);
+#ifndef HAVE_RB_HASH_NEW_CAPA
+#define rb_hash_new_capa(n) rb_hash_new()
+#endif
- rb_exc_raise(rb_exc_new3(exc, mesg));
+#ifndef HAVE_RB_STR_TO_INTERNED_STR
+static VALUE rb_str_to_interned_str(VALUE str)
+{
+ return rb_funcall(rb_str_freeze(str), i_uminus, 0);
}
-# define rb_enc_raise enc_raise
+#endif
+
+/* name cache */
+
+#include <string.h>
+#include <ctype.h>
+
+// Object names are likely to be repeated, and are frozen.
+// As such we can re-use them if we keep a cache of the ones we've seen so far,
+// and save much more expensive lookups into the global fstring table.
+// This cache implementation is deliberately simple, as we're optimizing for compactness,
+// to be able to fit safely on the stack.
+// As such, binary search into a sorted array gives a good tradeoff between compactness and
+// performance.
+#define JSON_RVALUE_CACHE_CAPA 63
+typedef struct rvalue_cache_struct {
+ int length;
+ VALUE entries[JSON_RVALUE_CACHE_CAPA];
+} rvalue_cache;
+
+static rb_encoding *enc_utf8;
+
+#define JSON_RVALUE_CACHE_MAX_ENTRY_LENGTH 55
+
+static inline VALUE build_interned_string(const char *str, const long length)
+{
+# ifdef HAVE_RB_ENC_INTERNED_STR
+ return rb_enc_interned_str(str, length, enc_utf8);
+# else
+ VALUE rstring = rb_utf8_str_new(str, length);
+ return rb_funcall(rb_str_freeze(rstring), i_uminus, 0);
# endif
-#else
-# define EXC_ENCODING /* nothing */
-# define rb_enc_raise rb_raise
+}
+
+static inline VALUE build_symbol(const char *str, const long length)
+{
+ return rb_str_intern(build_interned_string(str, length));
+}
+
+static void rvalue_cache_insert_at(rvalue_cache *cache, int index, VALUE rstring)
+{
+ MEMMOVE(&cache->entries[index + 1], &cache->entries[index], VALUE, cache->length - index);
+ cache->length++;
+ cache->entries[index] = rstring;
+}
+
+#define rstring_cache_memcmp memcmp
+
+#if JSON_CPU_LITTLE_ENDIAN_64BITS
+#if __has_builtin(__builtin_bswap64)
+#undef rstring_cache_memcmp
+ALWAYS_INLINE(static) int rstring_cache_memcmp(const char *str, const char *rptr, const long length)
+{
+ // The libc memcmp has numerous complex optimizations, but in this particular case,
+ // we know the string is small (JSON_RVALUE_CACHE_MAX_ENTRY_LENGTH), so being able to
+ // inline a simpler memcmp outperforms calling the libc version.
+ long i = 0;
+
+ for (; i + 8 <= length; i += 8) {
+ uint64_t a, b;
+ memcpy(&a, str + i, 8);
+ memcpy(&b, rptr + i, 8);
+ if (a != b) {
+ a = __builtin_bswap64(a);
+ b = __builtin_bswap64(b);
+ return (a < b) ? -1 : 1;
+ }
+ }
+
+ for (; i < length; i++) {
+ if (str[i] != rptr[i]) {
+ return (str[i] < rptr[i]) ? -1 : 1;
+ }
+ }
+
+ return 0;
+}
+#endif
#endif
-/* unicode */
+ALWAYS_INLINE(static) int rstring_cache_cmp(const char *str, const long length, VALUE rstring)
+{
+ const char *rstring_ptr;
+ long rstring_length;
-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
+ RSTRING_GETMEM(rstring, rstring_ptr, rstring_length);
+
+ if (length == rstring_length) {
+ return rstring_cache_memcmp(str, rstring_ptr, length);
+ } else {
+ return (int)(length - rstring_length);
+ }
+}
+
+ALWAYS_INLINE(static) VALUE rstring_cache_fetch(rvalue_cache *cache, const char *str, const long length)
+{
+ int low = 0;
+ int high = cache->length - 1;
+
+ while (low <= high) {
+ int mid = (high + low) >> 1;
+ VALUE entry = cache->entries[mid];
+ int cmp = rstring_cache_cmp(str, length, entry);
+
+ if (cmp == 0) {
+ return entry;
+ } else if (cmp > 0) {
+ low = mid + 1;
+ } else {
+ high = mid - 1;
+ }
+ }
+
+ VALUE rstring = build_interned_string(str, length);
+
+ if (cache->length < JSON_RVALUE_CACHE_CAPA) {
+ rvalue_cache_insert_at(cache, low, rstring);
+ }
+ return rstring;
+}
+
+static VALUE rsymbol_cache_fetch(rvalue_cache *cache, const char *str, const long length)
+{
+ int low = 0;
+ int high = cache->length - 1;
+
+ while (low <= high) {
+ int mid = (high + low) >> 1;
+ VALUE entry = cache->entries[mid];
+ int cmp = rstring_cache_cmp(str, length, rb_sym2str(entry));
+
+ if (cmp == 0) {
+ return entry;
+ } else if (cmp > 0) {
+ low = mid + 1;
+ } else {
+ high = mid - 1;
+ }
+ }
+
+ VALUE rsymbol = build_symbol(str, length);
+
+ if (cache->length < JSON_RVALUE_CACHE_CAPA) {
+ rvalue_cache_insert_at(cache, low, rsymbol);
+ }
+ return rsymbol;
+}
+
+/* rvalue stack */
+
+#define RVALUE_STACK_INITIAL_CAPA 128
+
+enum rvalue_stack_type {
+ RVALUE_STACK_HEAP_ALLOCATED = 0,
+ RVALUE_STACK_STACK_ALLOCATED = 1,
};
-static UTF32 unescape_unicode(const unsigned char *p)
+typedef struct rvalue_stack_struct {
+ enum rvalue_stack_type type;
+ long capa;
+ long head;
+ VALUE *ptr;
+} rvalue_stack;
+
+static rvalue_stack *rvalue_stack_spill(rvalue_stack *old_stack, VALUE *handle, rvalue_stack **stack_ref);
+
+static rvalue_stack *rvalue_stack_grow(rvalue_stack *stack, VALUE *handle, rvalue_stack **stack_ref)
{
- signed char b;
- UTF32 result = 0;
- b = digit_values[p[0]];
- if (b < 0) return UNI_REPLACEMENT_CHAR;
- result = (result << 4) | (unsigned char)b;
- b = digit_values[p[1]];
- if (b < 0) return UNI_REPLACEMENT_CHAR;
- result = (result << 4) | (unsigned char)b;
- b = digit_values[p[2]];
- if (b < 0) return UNI_REPLACEMENT_CHAR;
- result = (result << 4) | (unsigned char)b;
- b = digit_values[p[3]];
- if (b < 0) return UNI_REPLACEMENT_CHAR;
- result = (result << 4) | (unsigned char)b;
- return result;
+ long required = stack->capa * 2;
+
+ if (stack->type == RVALUE_STACK_STACK_ALLOCATED) {
+ stack = rvalue_stack_spill(stack, handle, stack_ref);
+ } else {
+ REALLOC_N(stack->ptr, VALUE, required);
+ stack->capa = required;
+ }
+ return stack;
}
-static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
+static VALUE rvalue_stack_push(rvalue_stack *stack, VALUE value, VALUE *handle, rvalue_stack **stack_ref)
+{
+ if (RB_UNLIKELY(stack->head >= stack->capa)) {
+ stack = rvalue_stack_grow(stack, handle, stack_ref);
+ }
+ stack->ptr[stack->head] = value;
+ stack->head++;
+ return value;
+}
+
+static inline VALUE *rvalue_stack_peek(rvalue_stack *stack, long count)
+{
+ return stack->ptr + (stack->head - count);
+}
+
+static inline void rvalue_stack_pop(rvalue_stack *stack, long count)
+{
+ stack->head -= count;
+}
+
+static void rvalue_stack_mark(void *ptr)
+{
+ rvalue_stack *stack = (rvalue_stack *)ptr;
+ long index;
+ for (index = 0; index < stack->head; index++) {
+ rb_gc_mark(stack->ptr[index]);
+ }
+}
+
+static void rvalue_stack_free(void *ptr)
+{
+ rvalue_stack *stack = (rvalue_stack *)ptr;
+ if (stack) {
+ ruby_xfree(stack->ptr);
+ ruby_xfree(stack);
+ }
+}
+
+static size_t rvalue_stack_memsize(const void *ptr)
+{
+ const rvalue_stack *stack = (const rvalue_stack *)ptr;
+ return sizeof(rvalue_stack) + sizeof(VALUE) * stack->capa;
+}
+
+static const rb_data_type_t JSON_Parser_rvalue_stack_type = {
+ "JSON::Ext::Parser/rvalue_stack",
+ {
+ .dmark = rvalue_stack_mark,
+ .dfree = rvalue_stack_free,
+ .dsize = rvalue_stack_memsize,
+ },
+ 0, 0,
+ RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+static rvalue_stack *rvalue_stack_spill(rvalue_stack *old_stack, VALUE *handle, rvalue_stack **stack_ref)
+{
+ rvalue_stack *stack;
+ *handle = TypedData_Make_Struct(0, rvalue_stack, &JSON_Parser_rvalue_stack_type, stack);
+ *stack_ref = stack;
+ MEMCPY(stack, old_stack, rvalue_stack, 1);
+
+ stack->capa = old_stack->capa << 1;
+ stack->ptr = ALLOC_N(VALUE, stack->capa);
+ stack->type = RVALUE_STACK_HEAP_ALLOCATED;
+ MEMCPY(stack->ptr, old_stack->ptr, VALUE, old_stack->head);
+ return stack;
+}
+
+static void rvalue_stack_eagerly_release(VALUE handle)
+{
+ if (handle) {
+ rvalue_stack *stack;
+ TypedData_Get_Struct(handle, rvalue_stack, &JSON_Parser_rvalue_stack_type, stack);
+ RTYPEDDATA_DATA(handle) = NULL;
+ rvalue_stack_free(stack);
+ }
+}
+
+static int convert_UTF32_to_UTF8(char *buf, uint32_t ch)
{
int len = 1;
if (ch <= 0x7F) {
@@ -89,1677 +321,1079 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
return len;
}
-static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
-static VALUE CNaN, CInfinity, CMinusInfinity;
+enum duplicate_key_action {
+ JSON_DEPRECATED = 0,
+ JSON_IGNORE,
+ JSON_RAISE,
+};
-static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
- i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
- i_object_class, i_array_class, i_decimal_class, i_key_p,
- i_deep_const_get, i_match, i_match_string, i_aset, i_aref,
- i_leftshift, i_new, i_try_convert, i_freeze, i_uminus;
+typedef struct JSON_ParserStruct {
+ VALUE on_load_proc;
+ VALUE decimal_class;
+ ID decimal_method_id;
+ enum duplicate_key_action on_duplicate_key;
+ int max_nesting;
+ bool allow_nan;
+ bool allow_trailing_comma;
+ bool allow_control_characters;
+ bool symbolize_names;
+ bool freeze;
+} JSON_ParserConfig;
+
+typedef struct JSON_ParserStateStruct {
+ VALUE stack_handle;
+ const char *start;
+ const char *cursor;
+ const char *end;
+ rvalue_stack *stack;
+ rvalue_cache name_cache;
+ int in_array;
+ int current_nesting;
+} JSON_ParserState;
+
+static inline size_t rest(JSON_ParserState *state) {
+ return state->end - state->cursor;
+}
+static inline bool eos(JSON_ParserState *state) {
+ return state->cursor >= state->end;
+}
-#line 125 "parser.rl"
+static inline char peek(JSON_ParserState *state)
+{
+ if (RB_UNLIKELY(eos(state))) {
+ return 0;
+ }
+ return *state->cursor;
+}
+static void cursor_position(JSON_ParserState *state, long *line_out, long *column_out)
+{
+ const char *cursor = state->cursor;
+ long column = 0;
+ long line = 1;
+
+ while (cursor >= state->start) {
+ if (*cursor-- == '\n') {
+ break;
+ }
+ column++;
+ }
+
+ while (cursor >= state->start) {
+ if (*cursor-- == '\n') {
+ line++;
+ }
+ }
+ *line_out = line;
+ *column_out = column;
+}
+
+static void emit_parse_warning(const char *message, JSON_ParserState *state)
+{
+ long line, column;
+ cursor_position(state, &line, &column);
+
+ VALUE warning = rb_sprintf("%s at line %ld column %ld", message, line, column);
+ rb_funcall(mJSON, rb_intern("deprecation_warning"), 1, warning);
+}
+
+#define PARSE_ERROR_FRAGMENT_LEN 32
+
+#ifdef RBIMPL_ATTR_NORETURN
+RBIMPL_ATTR_NORETURN()
+#endif
+static void raise_parse_error(const char *format, JSON_ParserState *state)
+{
+ unsigned char buffer[PARSE_ERROR_FRAGMENT_LEN + 3];
+ long line, column;
+ cursor_position(state, &line, &column);
+
+ const char *ptr = "EOF";
+ if (state->cursor && state->cursor < state->end) {
+ ptr = state->cursor;
+ size_t len = 0;
+ while (len < PARSE_ERROR_FRAGMENT_LEN) {
+ char ch = ptr[len];
+ if (!ch || ch == '\n' || ch == ' ' || ch == '\t' || ch == '\r') {
+ break;
+ }
+ len++;
+ }
+ if (len) {
+ buffer[0] = '\'';
+ MEMCPY(buffer + 1, ptr, char, len);
-#line 107 "parser.c"
-enum {JSON_object_start = 1};
-enum {JSON_object_first_final = 27};
-enum {JSON_object_error = 0};
+ while (buffer[len] >= 0x80 && buffer[len] < 0xC0) { // Is continuation byte
+ len--;
+ }
-enum {JSON_object_en_main = 1};
+ if (buffer[len] >= 0xC0) { // multibyte character start
+ len--;
+ }
+ buffer[len + 1] = '\'';
+ buffer[len + 2] = '\0';
+ ptr = (const char *)buffer;
+ }
+ }
-#line 167 "parser.rl"
+ VALUE msg = rb_sprintf(format, ptr);
+ VALUE message = rb_enc_sprintf(enc_utf8, "%s at line %ld column %ld", RSTRING_PTR(msg), line, column);
+ RB_GC_GUARD(msg);
+ VALUE exc = rb_exc_new_str(rb_path2class("JSON::ParserError"), message);
+ rb_ivar_set(exc, rb_intern("@line"), LONG2NUM(line));
+ rb_ivar_set(exc, rb_intern("@column"), LONG2NUM(column));
+ rb_exc_raise(exc);
+}
-static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
+#ifdef RBIMPL_ATTR_NORETURN
+RBIMPL_ATTR_NORETURN()
+#endif
+static void raise_parse_error_at(const char *format, JSON_ParserState *state, const char *at)
{
- int cs = EVIL;
- VALUE last_name = Qnil;
- VALUE object_class = json->object_class;
+ state->cursor = at;
+ raise_parse_error(format, state);
+}
+
+/* unicode */
- if (json->max_nesting && current_nesting > json->max_nesting) {
- rb_raise(eNestingError, "nesting of %d is too deep", current_nesting);
+static const signed char digit_values[256] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1,
+ -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1
+};
+
+static uint32_t unescape_unicode(JSON_ParserState *state, const char *sp, const char *spe)
+{
+ if (RB_UNLIKELY(sp > spe - 4)) {
+ raise_parse_error_at("incomplete unicode character escape sequence at %s", state, sp - 2);
}
- *result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class);
-
-
-#line 131 "parser.c"
- {
- cs = JSON_object_start;
- }
-
-#line 182 "parser.rl"
-
-#line 138 "parser.c"
- {
- if ( p == pe )
- goto _test_eof;
- switch ( cs )
- {
-case 1:
- if ( (*p) == 123 )
- goto st2;
- goto st0;
-st0:
-cs = 0;
- goto _out;
-st2:
- if ( ++p == pe )
- goto _test_eof2;
-case 2:
- switch( (*p) ) {
- case 13: goto st2;
- case 32: goto st2;
- case 34: goto tr2;
- case 47: goto st23;
- case 125: goto tr4;
- }
- if ( 9 <= (*p) && (*p) <= 10 )
- goto st2;
- goto st0;
-tr2:
-#line 149 "parser.rl"
- {
- char *np;
- json->parsing_name = 1;
- np = JSON_parse_string(json, p, pe, &last_name);
- json->parsing_name = 0;
- if (np == NULL) { p--; {p++; cs = 3; goto _out;} } else {p = (( np))-1;}
+ const unsigned char *p = (const unsigned char *)sp;
+
+ const signed char b0 = digit_values[p[0]];
+ const signed char b1 = digit_values[p[1]];
+ const signed char b2 = digit_values[p[2]];
+ const signed char b3 = digit_values[p[3]];
+
+ if (RB_UNLIKELY((signed char)(b0 | b1 | b2 | b3) < 0)) {
+ raise_parse_error_at("incomplete unicode character escape sequence at %s", state, sp - 2);
}
- goto st3;
-st3:
- if ( ++p == pe )
- goto _test_eof3;
-case 3:
-#line 179 "parser.c"
- switch( (*p) ) {
- case 13: goto st3;
- case 32: goto st3;
- case 47: goto st4;
- case 58: goto st8;
- }
- if ( 9 <= (*p) && (*p) <= 10 )
- goto st3;
- goto st0;
-st4:
- if ( ++p == pe )
- goto _test_eof4;
-case 4:
- switch( (*p) ) {
- case 42: goto st5;
- case 47: goto st7;
- }
- goto st0;
-st5:
- if ( ++p == pe )
- goto _test_eof5;
-case 5:
- if ( (*p) == 42 )
- goto st6;
- goto st5;
-st6:
- if ( ++p == pe )
- goto _test_eof6;
-case 6:
- switch( (*p) ) {
- case 42: goto st6;
- case 47: goto st3;
- }
- goto st5;
-st7:
- if ( ++p == pe )
- goto _test_eof7;
-case 7:
- if ( (*p) == 10 )
- goto st3;
- goto st7;
-st8:
- if ( ++p == pe )
- goto _test_eof8;
-case 8:
- switch( (*p) ) {
- case 13: goto st8;
- case 32: goto st8;
- case 34: goto tr11;
- case 45: goto tr11;
- case 47: goto st19;
- case 73: goto tr11;
- case 78: goto tr11;
- case 91: goto tr11;
- case 102: goto tr11;
- case 110: goto tr11;
- case 116: goto tr11;
- case 123: goto tr11;
- }
- if ( (*p) > 10 ) {
- if ( 48 <= (*p) && (*p) <= 57 )
- goto tr11;
- } else if ( (*p) >= 9 )
- goto st8;
- goto st0;
-tr11:
-#line 133 "parser.rl"
- {
- VALUE v = Qnil;
- char *np = JSON_parse_value(json, p, pe, &v, current_nesting);
- if (np == NULL) {
- p--; {p++; cs = 9; goto _out;}
- } else {
- if (NIL_P(json->object_class)) {
- OBJ_FREEZE(last_name);
- rb_hash_aset(*result, last_name, v);
+
+ return ((uint32_t)b0 << 12) | ((uint32_t)b1 << 8) | ((uint32_t)b2 << 4) | (uint32_t)b3;
+}
+
+#define GET_PARSER_CONFIG \
+ JSON_ParserConfig *config; \
+ TypedData_Get_Struct(self, JSON_ParserConfig, &JSON_ParserConfig_type, config)
+
+static const rb_data_type_t JSON_ParserConfig_type;
+
+static void
+json_eat_comments(JSON_ParserState *state)
+{
+ const char *start = state->cursor;
+ state->cursor++;
+
+ switch (peek(state)) {
+ case '/': {
+ state->cursor = memchr(state->cursor, '\n', state->end - state->cursor);
+ if (!state->cursor) {
+ state->cursor = state->end;
} else {
- rb_funcall(*result, i_aset, 2, last_name, v);
+ state->cursor++;
}
- {p = (( np))-1;}
+ break;
}
- }
- goto st9;
-st9:
- if ( ++p == pe )
- goto _test_eof9;
-case 9:
-#line 267 "parser.c"
- switch( (*p) ) {
- case 13: goto st9;
- case 32: goto st9;
- case 44: goto st10;
- case 47: goto st15;
- case 125: goto tr4;
- }
- if ( 9 <= (*p) && (*p) <= 10 )
- goto st9;
- goto st0;
-st10:
- if ( ++p == pe )
- goto _test_eof10;
-case 10:
- switch( (*p) ) {
- case 13: goto st10;
- case 32: goto st10;
- case 34: goto tr2;
- case 47: goto st11;
- }
- if ( 9 <= (*p) && (*p) <= 10 )
- goto st10;
- goto st0;
-st11:
- if ( ++p == pe )
- goto _test_eof11;
-case 11:
- switch( (*p) ) {
- case 42: goto st12;
- case 47: goto st14;
- }
- goto st0;
-st12:
- if ( ++p == pe )
- goto _test_eof12;
-case 12:
- if ( (*p) == 42 )
- goto st13;
- goto st12;
-st13:
- if ( ++p == pe )
- goto _test_eof13;
-case 13:
- switch( (*p) ) {
- case 42: goto st13;
- case 47: goto st10;
- }
- goto st12;
-st14:
- if ( ++p == pe )
- goto _test_eof14;
-case 14:
- if ( (*p) == 10 )
- goto st10;
- goto st14;
-st15:
- if ( ++p == pe )
- goto _test_eof15;
-case 15:
- switch( (*p) ) {
- case 42: goto st16;
- case 47: goto st18;
- }
- goto st0;
-st16:
- if ( ++p == pe )
- goto _test_eof16;
-case 16:
- if ( (*p) == 42 )
- goto st17;
- goto st16;
-st17:
- if ( ++p == pe )
- goto _test_eof17;
-case 17:
- switch( (*p) ) {
- case 42: goto st17;
- case 47: goto st9;
- }
- goto st16;
-st18:
- if ( ++p == pe )
- goto _test_eof18;
-case 18:
- if ( (*p) == 10 )
- goto st9;
- goto st18;
-tr4:
-#line 157 "parser.rl"
- { p--; {p++; cs = 27; goto _out;} }
- goto st27;
-st27:
- if ( ++p == pe )
- goto _test_eof27;
-case 27:
-#line 363 "parser.c"
- goto st0;
-st19:
- if ( ++p == pe )
- goto _test_eof19;
-case 19:
- switch( (*p) ) {
- case 42: goto st20;
- case 47: goto st22;
- }
- goto st0;
-st20:
- if ( ++p == pe )
- goto _test_eof20;
-case 20:
- if ( (*p) == 42 )
- goto st21;
- goto st20;
-st21:
- if ( ++p == pe )
- goto _test_eof21;
-case 21:
- switch( (*p) ) {
- case 42: goto st21;
- case 47: goto st8;
- }
- goto st20;
-st22:
- if ( ++p == pe )
- goto _test_eof22;
-case 22:
- if ( (*p) == 10 )
- goto st8;
- goto st22;
-st23:
- if ( ++p == pe )
- goto _test_eof23;
-case 23:
- switch( (*p) ) {
- case 42: goto st24;
- case 47: goto st26;
- }
- goto st0;
-st24:
- if ( ++p == pe )
- goto _test_eof24;
-case 24:
- if ( (*p) == 42 )
- goto st25;
- goto st24;
-st25:
- if ( ++p == pe )
- goto _test_eof25;
-case 25:
- switch( (*p) ) {
- case 42: goto st25;
- case 47: goto st2;
- }
- goto st24;
-st26:
- if ( ++p == pe )
- goto _test_eof26;
-case 26:
- if ( (*p) == 10 )
- goto st2;
- goto st26;
- }
- _test_eof2: cs = 2; goto _test_eof;
- _test_eof3: cs = 3; goto _test_eof;
- _test_eof4: cs = 4; goto _test_eof;
- _test_eof5: cs = 5; goto _test_eof;
- _test_eof6: cs = 6; goto _test_eof;
- _test_eof7: cs = 7; goto _test_eof;
- _test_eof8: cs = 8; goto _test_eof;
- _test_eof9: cs = 9; goto _test_eof;
- _test_eof10: cs = 10; goto _test_eof;
- _test_eof11: cs = 11; goto _test_eof;
- _test_eof12: cs = 12; goto _test_eof;
- _test_eof13: cs = 13; goto _test_eof;
- _test_eof14: cs = 14; goto _test_eof;
- _test_eof15: cs = 15; goto _test_eof;
- _test_eof16: cs = 16; goto _test_eof;
- _test_eof17: cs = 17; goto _test_eof;
- _test_eof18: cs = 18; goto _test_eof;
- _test_eof27: cs = 27; goto _test_eof;
- _test_eof19: cs = 19; goto _test_eof;
- _test_eof20: cs = 20; goto _test_eof;
- _test_eof21: cs = 21; goto _test_eof;
- _test_eof22: cs = 22; goto _test_eof;
- _test_eof23: cs = 23; goto _test_eof;
- _test_eof24: cs = 24; goto _test_eof;
- _test_eof25: cs = 25; goto _test_eof;
- _test_eof26: cs = 26; goto _test_eof;
-
- _test_eof: {}
- _out: {}
- }
-
-#line 183 "parser.rl"
-
- if (cs >= JSON_object_first_final) {
- if (json->create_additions) {
- VALUE klassname;
- if (NIL_P(json->object_class)) {
- klassname = rb_hash_aref(*result, json->create_id);
- } else {
- klassname = rb_funcall(*result, i_aref, 1, json->create_id);
- }
- if (!NIL_P(klassname)) {
- VALUE klass = rb_funcall(mJSON, i_deep_const_get, 1, klassname);
- if (RTEST(rb_funcall(klass, i_json_creatable_p, 0))) {
- *result = rb_funcall(klass, i_json_create, 1, *result);
+ case '*': {
+ state->cursor++;
+
+ while (true) {
+ const char *next_match = memchr(state->cursor, '*', state->end - state->cursor);
+ if (!next_match) {
+ raise_parse_error_at("unterminated comment, expected closing '*/'", state, start);
+ }
+
+ state->cursor = next_match + 1;
+ if (peek(state) == '/') {
+ state->cursor++;
+ break;
}
}
+ break;
}
- return p + 1;
- } else {
- return NULL;
+ default:
+ raise_parse_error_at("unexpected token %s", state, start);
+ break;
}
}
+ALWAYS_INLINE(static) void
+json_eat_whitespace(JSON_ParserState *state)
+{
+ while (true) {
+ switch (peek(state)) {
+ case ' ':
+ state->cursor++;
+ break;
+ case '\n':
+ state->cursor++;
+
+ // Heuristic: if we see a newline, there is likely consecutive spaces after it.
+#if JSON_CPU_LITTLE_ENDIAN_64BITS
+ while (rest(state) > 8) {
+ uint64_t chunk;
+ memcpy(&chunk, state->cursor, sizeof(uint64_t));
+ if (chunk == 0x2020202020202020) {
+ state->cursor += 8;
+ continue;
+ }
+ uint32_t consecutive_spaces = trailing_zeros64(chunk ^ 0x2020202020202020) / CHAR_BIT;
+ state->cursor += consecutive_spaces;
+ break;
+ }
+#endif
+ break;
+ case '\t':
+ case '\r':
+ state->cursor++;
+ break;
+ case '/':
+ json_eat_comments(state);
+ break;
+
+ default:
+ return;
+ }
+ }
+}
-#line 486 "parser.c"
-enum {JSON_value_start = 1};
-enum {JSON_value_first_final = 29};
-enum {JSON_value_error = 0};
+static inline VALUE build_string(const char *start, const char *end, bool intern, bool symbolize)
+{
+ if (symbolize) {
+ intern = true;
+ }
+ VALUE result;
+# ifdef HAVE_RB_ENC_INTERNED_STR
+ if (intern) {
+ result = rb_enc_interned_str(start, (long)(end - start), enc_utf8);
+ } else {
+ result = rb_utf8_str_new(start, (long)(end - start));
+ }
+# else
+ result = rb_utf8_str_new(start, (long)(end - start));
+ if (intern) {
+ result = rb_funcall(rb_str_freeze(result), i_uminus, 0);
+ }
+# endif
+
+ if (symbolize) {
+ result = rb_str_intern(result);
+ }
+
+ return result;
+}
+
+static inline bool json_string_cacheable_p(const char *string, size_t length)
+{
+ // We mostly want to cache strings that are likely to be repeated.
+ // Simple heuristics:
+ // - Common names aren't likely to be very long. So we just don't cache names above an arbitrary threshold.
+ // - If the first character isn't a letter, we're much less likely to see this string again.
+ return length <= JSON_RVALUE_CACHE_MAX_ENTRY_LENGTH && rb_isalpha(string[0]);
+}
+
+static inline VALUE json_string_fastpath(JSON_ParserState *state, JSON_ParserConfig *config, const char *string, const char *stringEnd, bool is_name)
+{
+ bool intern = is_name || config->freeze;
+ bool symbolize = is_name && config->symbolize_names;
+ size_t bufferSize = stringEnd - string;
-enum {JSON_value_en_main = 1};
+ if (is_name && state->in_array && RB_LIKELY(json_string_cacheable_p(string, bufferSize))) {
+ VALUE cached_key;
+ if (RB_UNLIKELY(symbolize)) {
+ cached_key = rsymbol_cache_fetch(&state->name_cache, string, bufferSize);
+ } else {
+ cached_key = rstring_cache_fetch(&state->name_cache, string, bufferSize);
+ }
+ if (RB_LIKELY(cached_key)) {
+ return cached_key;
+ }
+ }
-#line 283 "parser.rl"
+ return build_string(string, stringEnd, intern, symbolize);
+}
+#define JSON_MAX_UNESCAPE_POSITIONS 16
+typedef struct _json_unescape_positions {
+ long size;
+ const char **positions;
+ unsigned long additional_backslashes;
+} JSON_UnescapePositions;
-static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
+static inline const char *json_next_backslash(const char *pe, const char *stringEnd, JSON_UnescapePositions *positions)
{
- int cs = EVIL;
-
-
-#line 502 "parser.c"
- {
- cs = JSON_value_start;
- }
-
-#line 290 "parser.rl"
-
-#line 509 "parser.c"
- {
- if ( p == pe )
- goto _test_eof;
- switch ( cs )
- {
-st1:
- if ( ++p == pe )
- goto _test_eof1;
-case 1:
- switch( (*p) ) {
- case 13: goto st1;
- case 32: goto st1;
- case 34: goto tr2;
- case 45: goto tr3;
- case 47: goto st6;
- case 73: goto st10;
- case 78: goto st17;
- case 91: goto tr7;
- case 102: goto st19;
- case 110: goto st23;
- case 116: goto st26;
- case 123: goto tr11;
- }
- if ( (*p) > 10 ) {
- if ( 48 <= (*p) && (*p) <= 57 )
- goto tr3;
- } else if ( (*p) >= 9 )
- goto st1;
- goto st0;
-st0:
-cs = 0;
- goto _out;
-tr2:
-#line 235 "parser.rl"
- {
- char *np = JSON_parse_string(json, p, pe, result);
- if (np == NULL) { p--; {p++; cs = 29; goto _out;} } else {p = (( np))-1;}
+ while (positions->size) {
+ positions->size--;
+ const char *next_position = positions->positions[0];
+ positions->positions++;
+ if (next_position >= pe) {
+ return next_position;
+ }
}
- goto st29;
-tr3:
-#line 240 "parser.rl"
- {
- char *np;
- if(pe > p + 8 && !strncmp(MinusInfinity, p, 9)) {
- if (json->allow_nan) {
- *result = CMinusInfinity;
- {p = (( p + 10))-1;}
- p--; {p++; cs = 29; goto _out;}
- } else {
- rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p);
+
+ if (positions->additional_backslashes) {
+ positions->additional_backslashes--;
+ return memchr(pe, '\\', stringEnd - pe);
+ }
+
+ return NULL;
+}
+
+NOINLINE(static) VALUE json_string_unescape(JSON_ParserState *state, JSON_ParserConfig *config, const char *string, const char *stringEnd, bool is_name, JSON_UnescapePositions *positions)
+{
+ bool intern = is_name || config->freeze;
+ bool symbolize = is_name && config->symbolize_names;
+ size_t bufferSize = stringEnd - string;
+ const char *p = string, *pe = string, *bufferStart;
+ char *buffer;
+
+ VALUE result = rb_str_buf_new(bufferSize);
+ rb_enc_associate_index(result, utf8_encindex);
+ buffer = RSTRING_PTR(result);
+ bufferStart = buffer;
+
+#define APPEND_CHAR(chr) *buffer++ = chr; p = ++pe;
+
+ while (pe < stringEnd && (pe = json_next_backslash(pe, stringEnd, positions))) {
+ if (pe > p) {
+ MEMCPY(buffer, p, char, pe - p);
+ buffer += pe - p;
+ }
+ switch (*++pe) {
+ case '"':
+ case '/':
+ p = pe; // nothing to unescape just need to skip the backslash
+ break;
+ case '\\':
+ APPEND_CHAR('\\');
+ break;
+ case 'n':
+ APPEND_CHAR('\n');
+ break;
+ case 'r':
+ APPEND_CHAR('\r');
+ break;
+ case 't':
+ APPEND_CHAR('\t');
+ break;
+ case 'b':
+ APPEND_CHAR('\b');
+ break;
+ case 'f':
+ APPEND_CHAR('\f');
+ break;
+ case 'u': {
+ uint32_t ch = unescape_unicode(state, ++pe, stringEnd);
+ pe += 3;
+ /* To handle values above U+FFFF, we take a sequence of
+ * \uXXXX escapes in the U+D800..U+DBFF then
+ * U+DC00..U+DFFF ranges, take the low 10 bits from each
+ * to make a 20-bit number, then add 0x10000 to get the
+ * final codepoint.
+ *
+ * See Unicode 15: 3.8 "Surrogates", 5.3 "Handling
+ * Surrogate Pairs in UTF-16", and 23.6 "Surrogates
+ * Area".
+ */
+ if ((ch & 0xFC00) == 0xD800) {
+ pe++;
+ if (RB_LIKELY((pe <= stringEnd - 6) && memcmp(pe, "\\u", 2) == 0)) {
+ uint32_t sur = unescape_unicode(state, pe + 2, stringEnd);
+
+ if (RB_UNLIKELY((sur & 0xFC00) != 0xDC00)) {
+ raise_parse_error_at("invalid surrogate pair at %s", state, p);
+ }
+
+ ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16) | (sur & 0x3FF));
+ pe += 5;
+ } else {
+ raise_parse_error_at("incomplete surrogate pair at %s", state, p);
+ break;
+ }
+ }
+
+ int unescape_len = convert_UTF32_to_UTF8(buffer, ch);
+ buffer += unescape_len;
+ p = ++pe;
+ break;
}
+ default:
+ if ((unsigned char)*pe < 0x20) {
+ if (!config->allow_control_characters) {
+ if (*pe == '\n') {
+ raise_parse_error_at("Invalid unescaped newline character (\\n) in string: %s", state, pe - 1);
+ }
+ raise_parse_error_at("invalid ASCII control character in string: %s", state, pe - 1);
+ }
+ } else {
+ raise_parse_error_at("invalid escape character in string: %s", state, pe - 1);
+ }
+ break;
}
- 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;}
+#undef APPEND_CHAR
+
+ if (stringEnd > p) {
+ MEMCPY(buffer, p, char, stringEnd - p);
+ buffer += stringEnd - p;
}
- goto st29;
-tr25:
-#line 228 "parser.rl"
- {
- if (json->allow_nan) {
- *result = CInfinity;
- } else {
- rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 7);
- }
+ rb_str_set_len(result, buffer - bufferStart);
+
+ if (symbolize) {
+ result = rb_str_intern(result);
+ } else if (intern) {
+ result = rb_str_to_interned_str(result);
}
- goto st29;
-tr27:
-#line 221 "parser.rl"
- {
- if (json->allow_nan) {
- *result = CNaN;
- } else {
- rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 2);
+
+ return result;
+}
+
+#define MAX_FAST_INTEGER_SIZE 18
+
+static VALUE json_decode_large_integer(const char *start, long len)
+{
+ VALUE buffer_v;
+ char *buffer = RB_ALLOCV_N(char, buffer_v, len + 1);
+ MEMCPY(buffer, start, char, len);
+ buffer[len] = '\0';
+ VALUE number = rb_cstr2inum(buffer, 10);
+ RB_ALLOCV_END(buffer_v);
+ return number;
+}
+
+static inline VALUE
+json_decode_integer(uint64_t mantissa, int mantissa_digits, bool negative, const char *start, const char *end)
+{
+ if (RB_LIKELY(mantissa_digits < MAX_FAST_INTEGER_SIZE)) {
+ if (negative) {
+ return INT64T2NUM(-((int64_t)mantissa));
}
+ return UINT64T2NUM(mantissa);
}
- goto st29;
-tr31:
-#line 215 "parser.rl"
- {
- *result = Qfalse;
+
+ return json_decode_large_integer(start, end - start);
+}
+
+static VALUE json_decode_large_float(const char *start, long len)
+{
+ if (RB_LIKELY(len < 64)) {
+ char buffer[64];
+ MEMCPY(buffer, start, char, len);
+ buffer[len] = '\0';
+ return DBL2NUM(rb_cstr_to_dbl(buffer, 1));
}
- goto st29;
-tr34:
-#line 212 "parser.rl"
- {
- *result = Qnil;
+
+ VALUE buffer_v;
+ char *buffer = RB_ALLOCV_N(char, buffer_v, len + 1);
+ MEMCPY(buffer, start, char, len);
+ buffer[len] = '\0';
+ VALUE number = DBL2NUM(rb_cstr_to_dbl(buffer, 1));
+ RB_ALLOCV_END(buffer_v);
+ return number;
+}
+
+/* Ruby JSON optimized float decoder using vendored Ryu algorithm
+ * Accepts pre-extracted mantissa and exponent from first-pass validation
+ */
+static inline VALUE json_decode_float(JSON_ParserConfig *config, uint64_t mantissa, int mantissa_digits, int32_t exponent, bool negative,
+ const char *start, const char *end)
+{
+ if (RB_UNLIKELY(config->decimal_class)) {
+ VALUE text = rb_str_new(start, end - start);
+ return rb_funcallv(config->decimal_class, config->decimal_method_id, 1, &text);
}
- goto st29;
-tr37:
-#line 218 "parser.rl"
- {
- *result = Qtrue;
+
+ // Fall back to rb_cstr_to_dbl for potential subnormals (rare edge case)
+ // Ryu has rounding issues with subnormals around 1e-310 (< 2.225e-308)
+ if (RB_UNLIKELY(mantissa_digits > 17 || mantissa_digits + exponent < -307)) {
+ return json_decode_large_float(start, end - start);
}
- goto st29;
-st29:
- if ( ++p == pe )
- goto _test_eof29;
-case 29:
-#line 270 "parser.rl"
- { p--; {p++; cs = 29; goto _out;} }
-#line 629 "parser.c"
- switch( (*p) ) {
- case 13: goto st29;
- case 32: goto st29;
- case 47: goto st2;
- }
- if ( 9 <= (*p) && (*p) <= 10 )
- goto st29;
- goto st0;
-st2:
- if ( ++p == pe )
- goto _test_eof2;
-case 2:
- switch( (*p) ) {
- case 42: goto st3;
- case 47: goto st5;
- }
- goto st0;
-st3:
- if ( ++p == pe )
- goto _test_eof3;
-case 3:
- if ( (*p) == 42 )
- goto st4;
- goto st3;
-st4:
- if ( ++p == pe )
- goto _test_eof4;
-case 4:
- switch( (*p) ) {
- case 42: goto st4;
- case 47: goto st29;
- }
- goto st3;
-st5:
- if ( ++p == pe )
- goto _test_eof5;
-case 5:
- if ( (*p) == 10 )
- goto st29;
- goto st5;
-st6:
- if ( ++p == pe )
- goto _test_eof6;
-case 6:
- switch( (*p) ) {
- case 42: goto st7;
- case 47: goto st9;
- }
- goto st0;
-st7:
- if ( ++p == pe )
- goto _test_eof7;
-case 7:
- if ( (*p) == 42 )
- goto st8;
- goto st7;
-st8:
- if ( ++p == pe )
- goto _test_eof8;
-case 8:
- switch( (*p) ) {
- case 42: goto st8;
- case 47: goto st1;
- }
- goto st7;
-st9:
- if ( ++p == pe )
- goto _test_eof9;
-case 9:
- if ( (*p) == 10 )
- goto st1;
- goto st9;
-st10:
- if ( ++p == pe )
- goto _test_eof10;
-case 10:
- if ( (*p) == 110 )
- goto st11;
- goto st0;
-st11:
- if ( ++p == pe )
- goto _test_eof11;
-case 11:
- if ( (*p) == 102 )
- goto st12;
- goto st0;
-st12:
- if ( ++p == pe )
- goto _test_eof12;
-case 12:
- if ( (*p) == 105 )
- goto st13;
- goto st0;
-st13:
- if ( ++p == pe )
- goto _test_eof13;
-case 13:
- if ( (*p) == 110 )
- goto st14;
- goto st0;
-st14:
- if ( ++p == pe )
- goto _test_eof14;
-case 14:
- if ( (*p) == 105 )
- goto st15;
- goto st0;
-st15:
- if ( ++p == pe )
- goto _test_eof15;
-case 15:
- if ( (*p) == 116 )
- goto st16;
- goto st0;
-st16:
- if ( ++p == pe )
- goto _test_eof16;
-case 16:
- if ( (*p) == 121 )
- goto tr25;
- goto st0;
-st17:
- if ( ++p == pe )
- goto _test_eof17;
-case 17:
- if ( (*p) == 97 )
- goto st18;
- goto st0;
-st18:
- if ( ++p == pe )
- goto _test_eof18;
-case 18:
- if ( (*p) == 78 )
- goto tr27;
- goto st0;
-st19:
- if ( ++p == pe )
- goto _test_eof19;
-case 19:
- if ( (*p) == 97 )
- goto st20;
- goto st0;
-st20:
- if ( ++p == pe )
- goto _test_eof20;
-case 20:
- if ( (*p) == 108 )
- goto st21;
- goto st0;
-st21:
- if ( ++p == pe )
- goto _test_eof21;
-case 21:
- if ( (*p) == 115 )
- goto st22;
- goto st0;
-st22:
- if ( ++p == pe )
- goto _test_eof22;
-case 22:
- if ( (*p) == 101 )
- goto tr31;
- goto st0;
-st23:
- if ( ++p == pe )
- goto _test_eof23;
-case 23:
- if ( (*p) == 117 )
- goto st24;
- goto st0;
-st24:
- if ( ++p == pe )
- goto _test_eof24;
-case 24:
- if ( (*p) == 108 )
- goto st25;
- goto st0;
-st25:
- if ( ++p == pe )
- goto _test_eof25;
-case 25:
- if ( (*p) == 108 )
- goto tr34;
- goto st0;
-st26:
- if ( ++p == pe )
- goto _test_eof26;
-case 26:
- if ( (*p) == 114 )
- goto st27;
- goto st0;
-st27:
- if ( ++p == pe )
- goto _test_eof27;
-case 27:
- if ( (*p) == 117 )
- goto st28;
- goto st0;
-st28:
- if ( ++p == pe )
- goto _test_eof28;
-case 28:
- if ( (*p) == 101 )
- goto tr37;
- goto st0;
- }
- _test_eof1: cs = 1; goto _test_eof;
- _test_eof29: cs = 29; goto _test_eof;
- _test_eof2: cs = 2; goto _test_eof;
- _test_eof3: cs = 3; goto _test_eof;
- _test_eof4: cs = 4; goto _test_eof;
- _test_eof5: cs = 5; goto _test_eof;
- _test_eof6: cs = 6; goto _test_eof;
- _test_eof7: cs = 7; goto _test_eof;
- _test_eof8: cs = 8; goto _test_eof;
- _test_eof9: cs = 9; goto _test_eof;
- _test_eof10: cs = 10; goto _test_eof;
- _test_eof11: cs = 11; goto _test_eof;
- _test_eof12: cs = 12; goto _test_eof;
- _test_eof13: cs = 13; goto _test_eof;
- _test_eof14: cs = 14; goto _test_eof;
- _test_eof15: cs = 15; goto _test_eof;
- _test_eof16: cs = 16; goto _test_eof;
- _test_eof17: cs = 17; goto _test_eof;
- _test_eof18: cs = 18; goto _test_eof;
- _test_eof19: cs = 19; goto _test_eof;
- _test_eof20: cs = 20; goto _test_eof;
- _test_eof21: cs = 21; goto _test_eof;
- _test_eof22: cs = 22; goto _test_eof;
- _test_eof23: cs = 23; goto _test_eof;
- _test_eof24: cs = 24; goto _test_eof;
- _test_eof25: cs = 25; goto _test_eof;
- _test_eof26: cs = 26; goto _test_eof;
- _test_eof27: cs = 27; goto _test_eof;
- _test_eof28: cs = 28; goto _test_eof;
-
- _test_eof: {}
- _out: {}
- }
-
-#line 291 "parser.rl"
-
- if (json->freeze) {
- OBJ_FREEZE(*result);
+
+ return DBL2NUM(ryu_s2d_from_parts(mantissa, mantissa_digits, exponent, negative));
+}
+
+static inline VALUE json_decode_array(JSON_ParserState *state, JSON_ParserConfig *config, long count)
+{
+ VALUE array = rb_ary_new_from_values(count, rvalue_stack_peek(state->stack, count));
+ rvalue_stack_pop(state->stack, count);
+
+ if (config->freeze) {
+ RB_OBJ_FREEZE(array);
}
- if (cs >= JSON_value_first_final) {
- return p;
- } else {
- return NULL;
+ return array;
+}
+
+static VALUE json_find_duplicated_key(size_t count, const VALUE *pairs)
+{
+ VALUE set = rb_hash_new_capa(count / 2);
+ for (size_t index = 0; index < count; index += 2) {
+ size_t before = RHASH_SIZE(set);
+ VALUE key = pairs[index];
+ rb_hash_aset(set, key, Qtrue);
+ if (RHASH_SIZE(set) == before) {
+ if (RB_SYMBOL_P(key)) {
+ return rb_sym2str(key);
+ }
+ return key;
+ }
}
+ return Qfalse;
+}
+
+static void emit_duplicate_key_warning(JSON_ParserState *state, VALUE duplicate_key)
+{
+ VALUE message = rb_sprintf(
+ "detected duplicate key %"PRIsVALUE" in JSON object. This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`",
+ rb_inspect(duplicate_key)
+ );
+
+ emit_parse_warning(RSTRING_PTR(message), state);
+ RB_GC_GUARD(message);
}
+#ifdef RBIMPL_ATTR_NORETURN
+RBIMPL_ATTR_NORETURN()
+#endif
+static void raise_duplicate_key_error(JSON_ParserState *state, VALUE duplicate_key)
+{
+ VALUE message = rb_sprintf(
+ "duplicate key %"PRIsVALUE,
+ rb_inspect(duplicate_key)
+ );
-#line 884 "parser.c"
-enum {JSON_integer_start = 1};
-enum {JSON_integer_first_final = 3};
-enum {JSON_integer_error = 0};
+ raise_parse_error(RSTRING_PTR(message), state);
+ RB_GC_GUARD(message);
+}
-enum {JSON_integer_en_main = 1};
+static inline VALUE json_decode_object(JSON_ParserState *state, JSON_ParserConfig *config, size_t count)
+{
+ size_t entries_count = count / 2;
+ VALUE object = rb_hash_new_capa(entries_count);
+ const VALUE *pairs = rvalue_stack_peek(state->stack, count);
+ rb_hash_bulk_insert(count, pairs, object);
+
+ if (RB_UNLIKELY(RHASH_SIZE(object) < entries_count)) {
+ switch (config->on_duplicate_key) {
+ case JSON_IGNORE:
+ break;
+ case JSON_DEPRECATED:
+ emit_duplicate_key_warning(state, json_find_duplicated_key(count, pairs));
+ break;
+ case JSON_RAISE:
+ raise_duplicate_key_error(state, json_find_duplicated_key(count, pairs));
+ break;
+ }
+ }
+ rvalue_stack_pop(state->stack, count);
-#line 311 "parser.rl"
+ if (config->freeze) {
+ RB_OBJ_FREEZE(object);
+ }
+ return object;
+}
-static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
+static inline VALUE json_push_value(JSON_ParserState *state, JSON_ParserConfig *config, VALUE value)
{
- int cs = EVIL;
-
-
-#line 900 "parser.c"
- {
- cs = JSON_integer_start;
- }
-
-#line 318 "parser.rl"
- json->memo = p;
-
-#line 908 "parser.c"
- {
- if ( p == pe )
- goto _test_eof;
- switch ( cs )
- {
-case 1:
- switch( (*p) ) {
- case 45: goto st2;
- case 48: goto st3;
- }
- if ( 49 <= (*p) && (*p) <= 57 )
- goto st5;
- goto st0;
-st0:
-cs = 0;
- goto _out;
-st2:
- if ( ++p == pe )
- goto _test_eof2;
-case 2:
- if ( (*p) == 48 )
- goto st3;
- if ( 49 <= (*p) && (*p) <= 57 )
- goto st5;
- goto st0;
-st3:
- if ( ++p == pe )
- goto _test_eof3;
-case 3:
- if ( 48 <= (*p) && (*p) <= 57 )
- goto st0;
- goto tr4;
-tr4:
-#line 308 "parser.rl"
- { p--; {p++; cs = 4; goto _out;} }
- goto st4;
-st4:
- if ( ++p == pe )
- goto _test_eof4;
-case 4:
-#line 949 "parser.c"
- goto st0;
-st5:
- if ( ++p == pe )
- goto _test_eof5;
-case 5:
- if ( 48 <= (*p) && (*p) <= 57 )
- goto st5;
- goto tr4;
- }
- _test_eof2: cs = 2; goto _test_eof;
- _test_eof3: cs = 3; goto _test_eof;
- _test_eof4: cs = 4; goto _test_eof;
- _test_eof5: cs = 5; goto _test_eof;
-
- _test_eof: {}
- _out: {}
- }
-
-#line 320 "parser.rl"
-
- if (cs >= JSON_integer_first_final) {
- long len = p - json->memo;
- fbuffer_clear(json->fbuffer);
- fbuffer_append(json->fbuffer, json->memo, len);
- fbuffer_append_char(json->fbuffer, '\0');
- *result = rb_cstr2inum(FBUFFER_PTR(json->fbuffer), 10);
- return p + 1;
- } else {
- return NULL;
+ if (RB_UNLIKELY(config->on_load_proc)) {
+ value = rb_proc_call_with_block(config->on_load_proc, 1, &value, Qnil);
}
+ rvalue_stack_push(state->stack, value, &state->stack_handle, &state->stack);
+ return value;
}
+static const bool string_scan_table[256] = {
+ // ASCII Control Characters
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ // ASCII Characters
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // '"'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, // '\\'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
-#line 983 "parser.c"
-enum {JSON_float_start = 1};
-enum {JSON_float_first_final = 8};
-enum {JSON_float_error = 0};
+#ifdef HAVE_SIMD
+static SIMD_Implementation simd_impl = SIMD_NONE;
+#endif /* HAVE_SIMD */
-enum {JSON_float_en_main = 1};
+ALWAYS_INLINE(static) bool string_scan(JSON_ParserState *state)
+{
+#ifdef HAVE_SIMD
+#if defined(HAVE_SIMD_NEON)
+ uint64_t mask = 0;
+ if (string_scan_simd_neon(&state->cursor, state->end, &mask)) {
+ state->cursor += trailing_zeros64(mask) >> 2;
+ return true;
+ }
-#line 345 "parser.rl"
+#elif defined(HAVE_SIMD_SSE2)
+ if (simd_impl == SIMD_SSE2) {
+ int mask = 0;
+ if (string_scan_simd_sse2(&state->cursor, state->end, &mask)) {
+ state->cursor += trailing_zeros(mask);
+ return true;
+ }
+ }
+#endif /* HAVE_SIMD_NEON or HAVE_SIMD_SSE2 */
+#endif /* HAVE_SIMD */
+ while (!eos(state)) {
+ if (RB_UNLIKELY(string_scan_table[(unsigned char)*state->cursor])) {
+ return true;
+ }
+ state->cursor++;
+ }
+ return false;
+}
-static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
+static VALUE json_parse_escaped_string(JSON_ParserState *state, JSON_ParserConfig *config, bool is_name, const char *start)
{
- int cs = EVIL;
-
-
-#line 999 "parser.c"
- {
- cs = JSON_float_start;
- }
-
-#line 352 "parser.rl"
- json->memo = p;
-
-#line 1007 "parser.c"
- {
- if ( p == pe )
- goto _test_eof;
- switch ( cs )
- {
-case 1:
- switch( (*p) ) {
- case 45: goto st2;
- case 48: goto st3;
- }
- if ( 49 <= (*p) && (*p) <= 57 )
- goto st7;
- goto st0;
-st0:
-cs = 0;
- goto _out;
-st2:
- if ( ++p == pe )
- goto _test_eof2;
-case 2:
- if ( (*p) == 48 )
- goto st3;
- if ( 49 <= (*p) && (*p) <= 57 )
- goto st7;
- goto st0;
-st3:
- if ( ++p == pe )
- goto _test_eof3;
-case 3:
- switch( (*p) ) {
- case 46: goto st4;
- case 69: goto st5;
- case 101: goto st5;
- }
- goto st0;
-st4:
- if ( ++p == pe )
- goto _test_eof4;
-case 4:
- if ( 48 <= (*p) && (*p) <= 57 )
- goto st8;
- goto st0;
-st8:
- if ( ++p == pe )
- goto _test_eof8;
-case 8:
- switch( (*p) ) {
- case 69: goto st5;
- case 101: goto st5;
- }
- if ( (*p) > 46 ) {
- if ( 48 <= (*p) && (*p) <= 57 )
- goto st8;
- } else if ( (*p) >= 45 )
- goto st0;
- goto tr9;
-tr9:
-#line 339 "parser.rl"
- { p--; {p++; cs = 9; goto _out;} }
- goto st9;
-st9:
- if ( ++p == pe )
- goto _test_eof9;
-case 9:
-#line 1072 "parser.c"
- goto st0;
-st5:
- if ( ++p == pe )
- goto _test_eof5;
-case 5:
- switch( (*p) ) {
- case 43: goto st6;
- case 45: goto st6;
- }
- if ( 48 <= (*p) && (*p) <= 57 )
- goto st10;
- goto st0;
-st6:
- if ( ++p == pe )
- goto _test_eof6;
-case 6:
- if ( 48 <= (*p) && (*p) <= 57 )
- goto st10;
- goto st0;
-st10:
- if ( ++p == pe )
- goto _test_eof10;
-case 10:
- switch( (*p) ) {
- case 69: goto st0;
- case 101: goto st0;
- }
- if ( (*p) > 46 ) {
- if ( 48 <= (*p) && (*p) <= 57 )
- goto st10;
- } else if ( (*p) >= 45 )
- goto st0;
- goto tr9;
-st7:
- if ( ++p == pe )
- goto _test_eof7;
-case 7:
- switch( (*p) ) {
- case 46: goto st4;
- case 69: goto st5;
- case 101: goto st5;
- }
- if ( 48 <= (*p) && (*p) <= 57 )
- goto st7;
- goto st0;
- }
- _test_eof2: cs = 2; goto _test_eof;
- _test_eof3: cs = 3; goto _test_eof;
- _test_eof4: cs = 4; goto _test_eof;
- _test_eof8: cs = 8; goto _test_eof;
- _test_eof9: cs = 9; goto _test_eof;
- _test_eof5: cs = 5; goto _test_eof;
- _test_eof6: cs = 6; goto _test_eof;
- _test_eof10: cs = 10; goto _test_eof;
- _test_eof7: cs = 7; goto _test_eof;
-
- _test_eof: {}
- _out: {}
- }
-
-#line 354 "parser.rl"
-
- if (cs >= JSON_float_first_final) {
- VALUE mod = Qnil;
- ID method_id = 0;
- if (rb_respond_to(json->decimal_class, i_try_convert)) {
- mod = json->decimal_class;
- method_id = i_try_convert;
- } else if (rb_respond_to(json->decimal_class, i_new)) {
- mod = json->decimal_class;
- method_id = i_new;
- } else if (RB_TYPE_P(json->decimal_class, T_CLASS)) {
- VALUE name = rb_class_name(json->decimal_class);
- const char *name_cstr = RSTRING_PTR(name);
- const char *last_colon = strrchr(name_cstr, ':');
- if (last_colon) {
- const char *mod_path_end = last_colon - 1;
- VALUE mod_path = rb_str_substr(name, 0, mod_path_end - name_cstr);
- mod = rb_path_to_class(mod_path);
-
- const char *method_name_beg = last_colon + 1;
- long before_len = method_name_beg - name_cstr;
- long len = RSTRING_LEN(name) - before_len;
- VALUE method_name = rb_str_substr(name, before_len, len);
- method_id = SYM2ID(rb_str_intern(method_name));
- } else {
- mod = rb_mKernel;
- method_id = SYM2ID(rb_str_intern(name));
+ const char *backslashes[JSON_MAX_UNESCAPE_POSITIONS];
+ JSON_UnescapePositions positions = {
+ .size = 0,
+ .positions = backslashes,
+ .additional_backslashes = 0,
+ };
+
+ do {
+ switch (*state->cursor) {
+ case '"': {
+ VALUE string = json_string_unescape(state, config, start, state->cursor, is_name, &positions);
+ state->cursor++;
+ return json_push_value(state, config, string);
}
+ case '\\': {
+ if (RB_LIKELY(positions.size < JSON_MAX_UNESCAPE_POSITIONS)) {
+ backslashes[positions.size] = state->cursor;
+ positions.size++;
+ } else {
+ positions.additional_backslashes++;
+ }
+ state->cursor++;
+ break;
+ }
+ default:
+ if (!config->allow_control_characters) {
+ raise_parse_error("invalid ASCII control character in string: %s", state);
+ }
+ break;
}
- long len = p - json->memo;
- fbuffer_clear(json->fbuffer);
- fbuffer_append(json->fbuffer, json->memo, len);
- fbuffer_append_char(json->fbuffer, '\0');
+ state->cursor++;
+ } while (string_scan(state));
- 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));
- }
+ raise_parse_error("unexpected end of input, expected closing \"", state);
+ return Qfalse;
+}
- return p + 1;
- } else {
- return NULL;
+ALWAYS_INLINE(static) VALUE json_parse_string(JSON_ParserState *state, JSON_ParserConfig *config, bool is_name)
+{
+ state->cursor++;
+ const char *start = state->cursor;
+
+ if (RB_UNLIKELY(!string_scan(state))) {
+ raise_parse_error("unexpected end of input, expected closing \"", state);
+ }
+
+ if (RB_LIKELY(*state->cursor == '"')) {
+ VALUE string = json_string_fastpath(state, config, start, state->cursor, is_name);
+ state->cursor++;
+ return json_push_value(state, config, string);
}
+ return json_parse_escaped_string(state, config, is_name, start);
+}
+
+#if JSON_CPU_LITTLE_ENDIAN_64BITS
+// From: https://lemire.me/blog/2022/01/21/swar-explained-parsing-eight-digits/
+// Additional References:
+// https://johnnylee-sde.github.io/Fast-numeric-string-to-int/
+// http://0x80.pl/notesen/2014-10-12-parsing-decimal-numbers-part-1-swar.html
+static inline uint64_t decode_8digits_unrolled(uint64_t val) {
+ const uint64_t mask = 0x000000FF000000FF;
+ const uint64_t mul1 = 0x000F424000000064; // 100 + (1000000ULL << 32)
+ const uint64_t mul2 = 0x0000271000000001; // 1 + (10000ULL << 32)
+ val -= 0x3030303030303030;
+ val = (val * 10) + (val >> 8); // val = (val * 2561) >> 8;
+ val = (((val & mask) * mul1) + (((val >> 16) & mask) * mul2)) >> 32;
+ return val;
+}
+
+static inline uint64_t decode_4digits_unrolled(uint32_t val) {
+ const uint32_t mask = 0x000000FF;
+ const uint32_t mul1 = 100;
+ val -= 0x30303030;
+ val = (val * 10) + (val >> 8); // val = (val * 2561) >> 8;
+ val = ((val & mask) * mul1) + (((val >> 16) & mask));
+ return val;
}
+#endif
+static inline int json_parse_digits(JSON_ParserState *state, uint64_t *accumulator)
+{
+ const char *start = state->cursor;
+
+#if JSON_CPU_LITTLE_ENDIAN_64BITS
+ while (rest(state) >= sizeof(uint64_t)) {
+ uint64_t next_8bytes;
+ memcpy(&next_8bytes, state->cursor, sizeof(uint64_t));
+ // From: https://github.com/simdjson/simdjson/blob/32b301893c13d058095a07d9868edaaa42ee07aa/include/simdjson/generic/numberparsing.h#L333
+ // Branchless version of: http://0x80.pl/articles/swar-digits-validate.html
+ uint64_t match = (next_8bytes & 0xF0F0F0F0F0F0F0F0) | (((next_8bytes + 0x0606060606060606) & 0xF0F0F0F0F0F0F0F0) >> 4);
-#line 1184 "parser.c"
-enum {JSON_array_start = 1};
-enum {JSON_array_first_final = 17};
-enum {JSON_array_error = 0};
+ if (match == 0x3333333333333333) { // 8 consecutive digits
+ *accumulator = (*accumulator * 100000000) + decode_8digits_unrolled(next_8bytes);
+ state->cursor += 8;
+ continue;
+ }
-enum {JSON_array_en_main = 1};
+ uint32_t consecutive_digits = trailing_zeros64(match ^ 0x3333333333333333) / CHAR_BIT;
+ if (consecutive_digits >= 4) {
+ *accumulator = (*accumulator * 10000) + decode_4digits_unrolled((uint32_t)next_8bytes);
+ state->cursor += 4;
+ consecutive_digits -= 4;
+ }
-#line 432 "parser.rl"
+ while (consecutive_digits) {
+ *accumulator = *accumulator * 10 + (*state->cursor - '0');
+ consecutive_digits--;
+ state->cursor++;
+ }
+ return (int)(state->cursor - start);
+ }
+#endif
-static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
+ char next_char;
+ while (rb_isdigit(next_char = peek(state))) {
+ *accumulator = *accumulator * 10 + (next_char - '0');
+ state->cursor++;
+ }
+ return (int)(state->cursor - start);
+}
+
+static inline VALUE json_parse_number(JSON_ParserState *state, JSON_ParserConfig *config, bool negative, const char *start)
{
- int cs = EVIL;
- VALUE array_class = json->array_class;
+ bool integer = true;
+ const char first_digit = *state->cursor;
+
+ // Variables for Ryu optimization - extract digits during parsing
+ int32_t exponent = 0;
+ int decimal_point_pos = -1;
+ uint64_t mantissa = 0;
+
+ // Parse integer part and extract mantissa digits
+ int mantissa_digits = json_parse_digits(state, &mantissa);
- if (json->max_nesting && current_nesting > json->max_nesting) {
- rb_raise(eNestingError, "nesting of %d is too deep", current_nesting);
+ if (RB_UNLIKELY((first_digit == '0' && mantissa_digits > 1) || (negative && mantissa_digits == 0))) {
+ raise_parse_error_at("invalid number: %s", state, start);
}
- *result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
-
-
-#line 1206 "parser.c"
- {
- cs = JSON_array_start;
- }
-
-#line 445 "parser.rl"
-
-#line 1213 "parser.c"
- {
- if ( p == pe )
- goto _test_eof;
- switch ( cs )
- {
-case 1:
- if ( (*p) == 91 )
- goto st2;
- goto st0;
-st0:
-cs = 0;
- goto _out;
-st2:
- if ( ++p == pe )
- goto _test_eof2;
-case 2:
- switch( (*p) ) {
- case 13: goto st2;
- case 32: goto st2;
- case 34: goto tr2;
- case 45: goto tr2;
- case 47: goto st13;
- case 73: goto tr2;
- case 78: goto tr2;
- case 91: goto tr2;
- case 93: goto tr4;
- case 102: goto tr2;
- case 110: goto tr2;
- case 116: goto tr2;
- case 123: goto tr2;
- }
- if ( (*p) > 10 ) {
- if ( 48 <= (*p) && (*p) <= 57 )
- goto tr2;
- } else if ( (*p) >= 9 )
- goto st2;
- goto st0;
-tr2:
-#line 409 "parser.rl"
- {
- VALUE v = Qnil;
- char *np = JSON_parse_value(json, p, pe, &v, current_nesting);
- if (np == NULL) {
- p--; {p++; cs = 3; goto _out;}
- } else {
- if (NIL_P(json->array_class)) {
- rb_ary_push(*result, v);
- } else {
- rb_funcall(*result, i_leftshift, 1, v);
- }
- {p = (( np))-1;}
+
+ // Parse fractional part
+ if (peek(state) == '.') {
+ integer = false;
+ decimal_point_pos = mantissa_digits; // Remember position of decimal point
+ state->cursor++;
+
+ int fractional_digits = json_parse_digits(state, &mantissa);
+ mantissa_digits += fractional_digits;
+
+ if (RB_UNLIKELY(!fractional_digits)) {
+ raise_parse_error_at("invalid number: %s", state, start);
}
}
- goto st3;
-st3:
- if ( ++p == pe )
- goto _test_eof3;
-case 3:
-#line 1272 "parser.c"
- switch( (*p) ) {
- case 13: goto st3;
- case 32: goto st3;
- case 44: goto st4;
- case 47: goto st9;
- case 93: goto tr4;
- }
- if ( 9 <= (*p) && (*p) <= 10 )
- goto st3;
- goto st0;
-st4:
- if ( ++p == pe )
- goto _test_eof4;
-case 4:
- switch( (*p) ) {
- case 13: goto st4;
- case 32: goto st4;
- case 34: goto tr2;
- case 45: goto tr2;
- case 47: goto st5;
- case 73: goto tr2;
- case 78: goto tr2;
- case 91: goto tr2;
- case 102: goto tr2;
- case 110: goto tr2;
- case 116: goto tr2;
- case 123: goto tr2;
- }
- if ( (*p) > 10 ) {
- if ( 48 <= (*p) && (*p) <= 57 )
- goto tr2;
- } else if ( (*p) >= 9 )
- goto st4;
- goto st0;
-st5:
- if ( ++p == pe )
- goto _test_eof5;
-case 5:
- switch( (*p) ) {
- case 42: goto st6;
- case 47: goto st8;
- }
- goto st0;
-st6:
- if ( ++p == pe )
- goto _test_eof6;
-case 6:
- if ( (*p) == 42 )
- goto st7;
- goto st6;
-st7:
- if ( ++p == pe )
- goto _test_eof7;
-case 7:
- switch( (*p) ) {
- case 42: goto st7;
- case 47: goto st4;
- }
- goto st6;
-st8:
- if ( ++p == pe )
- goto _test_eof8;
-case 8:
- if ( (*p) == 10 )
- goto st4;
- goto st8;
-st9:
- if ( ++p == pe )
- goto _test_eof9;
-case 9:
- switch( (*p) ) {
- case 42: goto st10;
- case 47: goto st12;
- }
- goto st0;
-st10:
- if ( ++p == pe )
- goto _test_eof10;
-case 10:
- if ( (*p) == 42 )
- goto st11;
- goto st10;
-st11:
- if ( ++p == pe )
- goto _test_eof11;
-case 11:
- switch( (*p) ) {
- case 42: goto st11;
- case 47: goto st3;
- }
- goto st10;
-st12:
- if ( ++p == pe )
- goto _test_eof12;
-case 12:
- if ( (*p) == 10 )
- goto st3;
- goto st12;
-tr4:
-#line 424 "parser.rl"
- { p--; {p++; cs = 17; goto _out;} }
- goto st17;
-st17:
- if ( ++p == pe )
- goto _test_eof17;
-case 17:
-#line 1379 "parser.c"
- goto st0;
-st13:
- if ( ++p == pe )
- goto _test_eof13;
-case 13:
- switch( (*p) ) {
- case 42: goto st14;
- case 47: goto st16;
- }
- goto st0;
-st14:
- if ( ++p == pe )
- goto _test_eof14;
-case 14:
- if ( (*p) == 42 )
- goto st15;
- goto st14;
-st15:
- if ( ++p == pe )
- goto _test_eof15;
-case 15:
- switch( (*p) ) {
- case 42: goto st15;
- case 47: goto st2;
- }
- goto st14;
-st16:
- if ( ++p == pe )
- goto _test_eof16;
-case 16:
- if ( (*p) == 10 )
- goto st2;
- goto st16;
- }
- _test_eof2: cs = 2; goto _test_eof;
- _test_eof3: cs = 3; goto _test_eof;
- _test_eof4: cs = 4; goto _test_eof;
- _test_eof5: cs = 5; goto _test_eof;
- _test_eof6: cs = 6; goto _test_eof;
- _test_eof7: cs = 7; goto _test_eof;
- _test_eof8: cs = 8; goto _test_eof;
- _test_eof9: cs = 9; goto _test_eof;
- _test_eof10: cs = 10; goto _test_eof;
- _test_eof11: cs = 11; goto _test_eof;
- _test_eof12: cs = 12; goto _test_eof;
- _test_eof17: cs = 17; goto _test_eof;
- _test_eof13: cs = 13; goto _test_eof;
- _test_eof14: cs = 14; goto _test_eof;
- _test_eof15: cs = 15; goto _test_eof;
- _test_eof16: cs = 16; goto _test_eof;
-
- _test_eof: {}
- _out: {}
- }
-
-#line 446 "parser.rl"
-
- if(cs >= JSON_array_first_final) {
- return p + 1;
- } else {
- rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p);
- return NULL;
+
+ // Parse exponent
+ if (rb_tolower(peek(state)) == 'e') {
+ integer = false;
+ state->cursor++;
+
+ bool negative_exponent = false;
+ const char next_char = peek(state);
+ if (next_char == '-' || next_char == '+') {
+ negative_exponent = next_char == '-';
+ state->cursor++;
+ }
+
+ uint64_t abs_exponent = 0;
+ int exponent_digits = json_parse_digits(state, &abs_exponent);
+
+ if (RB_UNLIKELY(!exponent_digits)) {
+ raise_parse_error_at("invalid number: %s", state, start);
+ }
+
+ exponent = negative_exponent ? -((int32_t)abs_exponent) : ((int32_t)abs_exponent);
+ }
+
+ if (integer) {
+ return json_decode_integer(mantissa, mantissa_digits, negative, start, state->cursor);
+ }
+
+ // Adjust exponent based on decimal point position
+ if (decimal_point_pos >= 0) {
+ exponent -= (mantissa_digits - decimal_point_pos);
}
+
+ return json_decode_float(config, mantissa, mantissa_digits, exponent, negative, start, state->cursor);
}
-static const size_t MAX_STACK_BUFFER_SIZE = 128;
-static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int symbolize)
+static inline VALUE json_parse_positive_number(JSON_ParserState *state, JSON_ParserConfig *config)
{
- VALUE result = Qnil;
- size_t bufferSize = stringEnd - string;
- char *p = string, *pe = string, *unescape, *bufferStart, *buffer;
- int unescape_len;
- char buf[4];
+ return json_parse_number(state, config, false, state->cursor);
+}
- if (bufferSize > MAX_STACK_BUFFER_SIZE) {
-# ifdef HAVE_RB_ENC_INTERNED_STR
- bufferStart = buffer = ALLOC_N(char, bufferSize ? bufferSize : 1);
-# else
- bufferStart = buffer = ALLOC_N(char, bufferSize);
-# endif
- } else {
-# ifdef HAVE_RB_ENC_INTERNED_STR
- bufferStart = buffer = ALLOCA_N(char, bufferSize ? bufferSize : 1);
-# else
- bufferStart = buffer = ALLOCA_N(char, bufferSize);
-# endif
- }
+static inline VALUE json_parse_negative_number(JSON_ParserState *state, JSON_ParserConfig *config)
+{
+ const char *start = state->cursor;
+ state->cursor++;
+ return json_parse_number(state, config, true, start);
+}
- while (pe < stringEnd) {
- if (*pe == '\\') {
- unescape = (char *) "?";
- unescape_len = 1;
- if (pe > p) {
- MEMCPY(buffer, p, char, pe - p);
- buffer += pe - p;
+static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config)
+{
+ json_eat_whitespace(state);
+
+ switch (peek(state)) {
+ case 'n':
+ if (rest(state) >= 4 && (memcmp(state->cursor, "null", 4) == 0)) {
+ state->cursor += 4;
+ return json_push_value(state, config, Qnil);
}
- 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) {
- ruby_xfree(bufferStart);
- }
- rb_enc_raise(
- EXC_ENCODING eParserError,
- "incomplete unicode character escape sequence at '%s'", p
- );
- } else {
- UTF32 ch = unescape_unicode((unsigned char *) ++pe);
- pe += 3;
- if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
- pe++;
- if (pe > stringEnd - 6) {
- if (bufferSize > MAX_STACK_BUFFER_SIZE) {
- ruby_xfree(bufferStart);
- }
- rb_enc_raise(
- EXC_ENCODING eParserError,
- "incomplete surrogate pair at '%s'", p
- );
- }
- if (pe[0] == '\\' && pe[1] == 'u') {
- UTF32 sur = unescape_unicode((unsigned char *) pe + 2);
- ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16)
- | (sur & 0x3FF));
- pe += 5;
- } else {
- unescape = (char *) "?";
- break;
- }
+
+ raise_parse_error("unexpected token %s", state);
+ break;
+ case 't':
+ if (rest(state) >= 4 && (memcmp(state->cursor, "true", 4) == 0)) {
+ state->cursor += 4;
+ return json_push_value(state, config, Qtrue);
+ }
+
+ raise_parse_error("unexpected token %s", state);
+ break;
+ case 'f':
+ // Note: memcmp with a small power of two compile to an integer comparison
+ if (rest(state) >= 5 && (memcmp(state->cursor + 1, "alse", 4) == 0)) {
+ state->cursor += 5;
+ return json_push_value(state, config, Qfalse);
+ }
+
+ raise_parse_error("unexpected token %s", state);
+ break;
+ case 'N':
+ // Note: memcmp with a small power of two compile to an integer comparison
+ if (config->allow_nan && rest(state) >= 3 && (memcmp(state->cursor + 1, "aN", 2) == 0)) {
+ state->cursor += 3;
+ return json_push_value(state, config, CNaN);
+ }
+
+ raise_parse_error("unexpected token %s", state);
+ break;
+ case 'I':
+ if (config->allow_nan && rest(state) >= 8 && (memcmp(state->cursor, "Infinity", 8) == 0)) {
+ state->cursor += 8;
+ return json_push_value(state, config, CInfinity);
+ }
+
+ raise_parse_error("unexpected token %s", state);
+ break;
+ case '-': {
+ // Note: memcmp with a small power of two compile to an integer comparison
+ if (rest(state) >= 9 && (memcmp(state->cursor + 1, "Infinity", 8) == 0)) {
+ if (config->allow_nan) {
+ state->cursor += 9;
+ return json_push_value(state, config, CMinusInfinity);
+ } else {
+ raise_parse_error("unexpected token %s", state);
+ }
+ }
+ return json_push_value(state, config, json_parse_negative_number(state, config));
+ break;
+ }
+ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
+ return json_push_value(state, config, json_parse_positive_number(state, config));
+ break;
+ case '"': {
+ // %r{\A"[^"\\\t\n\x00]*(?:\\[bfnrtu\\/"][^"\\]*)*"}
+ return json_parse_string(state, config, false);
+ break;
+ }
+ case '[': {
+ state->cursor++;
+ json_eat_whitespace(state);
+ long stack_head = state->stack->head;
+
+ if (peek(state) == ']') {
+ state->cursor++;
+ return json_push_value(state, config, json_decode_array(state, config, 0));
+ } else {
+ state->current_nesting++;
+ if (RB_UNLIKELY(config->max_nesting && (config->max_nesting < state->current_nesting))) {
+ rb_raise(eNestingError, "nesting of %d is too deep", state->current_nesting);
+ }
+ state->in_array++;
+ json_parse_any(state, config);
+ }
+
+ while (true) {
+ json_eat_whitespace(state);
+
+ const char next_char = peek(state);
+
+ if (RB_LIKELY(next_char == ',')) {
+ state->cursor++;
+ if (config->allow_trailing_comma) {
+ json_eat_whitespace(state);
+ if (peek(state) == ']') {
+ continue;
}
- unescape_len = convert_UTF32_to_UTF8(buf, ch);
- unescape = buf;
}
- break;
- default:
- p = pe;
+ json_parse_any(state, config);
continue;
+ }
+
+ if (next_char == ']') {
+ state->cursor++;
+ long count = state->stack->head - stack_head;
+ state->current_nesting--;
+ state->in_array--;
+ return json_push_value(state, config, json_decode_array(state, config, count));
+ }
+
+ raise_parse_error("expected ',' or ']' after array value", state);
}
- MEMCPY(buffer, unescape, char, unescape_len);
- buffer += unescape_len;
- p = ++pe;
- } else {
- pe++;
+ break;
}
- }
+ case '{': {
+ const char *object_start_cursor = state->cursor;
- if (pe > p) {
- MEMCPY(buffer, p, char, pe - p);
- buffer += pe - p;
- }
+ state->cursor++;
+ json_eat_whitespace(state);
+ long stack_head = state->stack->head;
-# ifdef HAVE_RB_ENC_INTERNED_STR
- if (intern) {
- result = rb_enc_interned_str(bufferStart, (long)(buffer - bufferStart), rb_utf8_encoding());
- } else {
- result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
- }
- if (bufferSize > MAX_STACK_BUFFER_SIZE) {
- ruby_xfree(bufferStart);
- }
-# else
- result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
+ if (peek(state) == '}') {
+ state->cursor++;
+ return json_push_value(state, config, json_decode_object(state, config, 0));
+ } else {
+ state->current_nesting++;
+ if (RB_UNLIKELY(config->max_nesting && (config->max_nesting < state->current_nesting))) {
+ rb_raise(eNestingError, "nesting of %d is too deep", state->current_nesting);
+ }
- if (bufferSize > MAX_STACK_BUFFER_SIZE) {
- ruby_xfree(bufferStart);
- }
+ if (peek(state) != '"') {
+ raise_parse_error("expected object key, got %s", state);
+ }
+ json_parse_string(state, config, true);
- if (intern) {
- # if STR_UMINUS_DEDUPE_FROZEN
- // Starting from MRI 2.8 it is preferable to freeze the string
- // before deduplication so that it can be interned directly
- // otherwise it would be duplicated first which is wasteful.
- result = rb_funcall(rb_str_freeze(result), i_uminus, 0);
- # elif STR_UMINUS_DEDUPE
- // MRI 2.5 and older do not deduplicate strings that are already
- // frozen.
- result = rb_funcall(result, i_uminus, 0);
- # else
- result = rb_str_freeze(result);
- # endif
- }
-# endif
+ json_eat_whitespace(state);
+ if (peek(state) != ':') {
+ raise_parse_error("expected ':' after object key", state);
+ }
+ state->cursor++;
- if (symbolize) {
- result = rb_str_intern(result);
- }
+ json_parse_any(state, config);
+ }
- return result;
-}
+ while (true) {
+ json_eat_whitespace(state);
+ const char next_char = peek(state);
+ if (next_char == '}') {
+ state->cursor++;
+ state->current_nesting--;
+ size_t count = state->stack->head - stack_head;
-#line 1592 "parser.c"
-enum {JSON_string_start = 1};
-enum {JSON_string_first_final = 8};
-enum {JSON_string_error = 0};
+ // Temporary rewind cursor in case an error is raised
+ const char *final_cursor = state->cursor;
+ state->cursor = object_start_cursor;
+ VALUE object = json_decode_object(state, config, count);
+ state->cursor = final_cursor;
-enum {JSON_string_en_main = 1};
+ return json_push_value(state, config, object);
+ }
+ if (next_char == ',') {
+ state->cursor++;
+ json_eat_whitespace(state);
-#line 620 "parser.rl"
+ if (config->allow_trailing_comma) {
+ if (peek(state) == '}') {
+ continue;
+ }
+ }
+ if (RB_UNLIKELY(peek(state) != '"')) {
+ raise_parse_error("expected object key, got: %s", state);
+ }
+ json_parse_string(state, config, true);
-static int
-match_i(VALUE regexp, VALUE klass, VALUE memo)
-{
- if (regexp == Qundef) return ST_STOP;
- if (RTEST(rb_funcall(klass, i_json_creatable_p, 0)) &&
- RTEST(rb_funcall(regexp, i_match, 1, rb_ary_entry(memo, 0)))) {
- rb_ary_push(memo, klass);
- return ST_STOP;
- }
- return ST_CONTINUE;
-}
+ json_eat_whitespace(state);
+ if (RB_UNLIKELY(peek(state) != ':')) {
+ raise_parse_error("expected ':' after object key, got: %s", state);
+ }
+ state->cursor++;
-static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result)
-{
- int cs = EVIL;
- VALUE match_string;
-
-
-#line 1621 "parser.c"
- {
- cs = JSON_string_start;
- }
-
-#line 640 "parser.rl"
- json->memo = p;
-
-#line 1629 "parser.c"
- {
- if ( p == pe )
- goto _test_eof;
- switch ( cs )
- {
-case 1:
- if ( (*p) == 34 )
- goto st2;
- goto st0;
-st0:
-cs = 0;
- goto _out;
-st2:
- if ( ++p == pe )
- goto _test_eof2;
-case 2:
- switch( (*p) ) {
- case 34: goto tr2;
- case 92: goto st3;
- }
- if ( 0 <= (signed char)(*(p)) && (*(p)) <= 31 )
- goto st0;
- goto st2;
-tr2:
-#line 607 "parser.rl"
- {
- *result = json_string_unescape(json->memo + 1, p, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names);
- if (NIL_P(*result)) {
- p--;
- {p++; cs = 8; goto _out;}
- } else {
- {p = (( p + 1))-1;}
+ json_parse_any(state, config);
+
+ continue;
+ }
+
+ raise_parse_error("expected ',' or '}' after object value, got: %s", state);
+ }
+ break;
}
- }
-#line 617 "parser.rl"
- { p--; {p++; cs = 8; goto _out;} }
- goto st8;
-st8:
- if ( ++p == pe )
- goto _test_eof8;
-case 8:
-#line 1671 "parser.c"
- goto st0;
-st3:
- if ( ++p == pe )
- goto _test_eof3;
-case 3:
- if ( (*p) == 117 )
- goto st4;
- if ( 0 <= (signed char)(*(p)) && (*(p)) <= 31 )
- goto st0;
- goto st2;
-st4:
- if ( ++p == pe )
- goto _test_eof4;
-case 4:
- if ( (*p) < 65 ) {
- if ( 48 <= (*p) && (*p) <= 57 )
- goto st5;
- } else if ( (*p) > 70 ) {
- if ( 97 <= (*p) && (*p) <= 102 )
- goto st5;
- } else
- goto st5;
- goto st0;
-st5:
- if ( ++p == pe )
- goto _test_eof5;
-case 5:
- if ( (*p) < 65 ) {
- if ( 48 <= (*p) && (*p) <= 57 )
- goto st6;
- } else if ( (*p) > 70 ) {
- if ( 97 <= (*p) && (*p) <= 102 )
- goto st6;
- } else
- goto st6;
- goto st0;
-st6:
- if ( ++p == pe )
- goto _test_eof6;
-case 6:
- if ( (*p) < 65 ) {
- if ( 48 <= (*p) && (*p) <= 57 )
- goto st7;
- } else if ( (*p) > 70 ) {
- if ( 97 <= (*p) && (*p) <= 102 )
- goto st7;
- } else
- goto st7;
- goto st0;
-st7:
- if ( ++p == pe )
- goto _test_eof7;
-case 7:
- if ( (*p) < 65 ) {
- if ( 48 <= (*p) && (*p) <= 57 )
- goto st2;
- } else if ( (*p) > 70 ) {
- if ( 97 <= (*p) && (*p) <= 102 )
- goto st2;
- } else
- goto st2;
- goto st0;
- }
- _test_eof2: cs = 2; goto _test_eof;
- _test_eof8: cs = 8; goto _test_eof;
- _test_eof3: cs = 3; goto _test_eof;
- _test_eof4: cs = 4; goto _test_eof;
- _test_eof5: cs = 5; goto _test_eof;
- _test_eof6: cs = 6; goto _test_eof;
- _test_eof7: cs = 7; goto _test_eof;
-
- _test_eof: {}
- _out: {}
- }
-
-#line 642 "parser.rl"
-
- if (json->create_additions && RTEST(match_string = json->match_string)) {
- VALUE klass;
- VALUE memo = rb_ary_new2(2);
- rb_ary_push(memo, *result);
- rb_hash_foreach(match_string, match_i, memo);
- klass = rb_ary_entry(memo, 1);
- if (RTEST(klass)) {
- *result = rb_funcall(klass, i_json_create, 1, *result);
- }
+
+ case 0:
+ raise_parse_error("unexpected end of input", state);
+ break;
+
+ default:
+ raise_parse_error("unexpected character: %s", state);
+ break;
}
- if (cs >= JSON_string_first_final) {
- return p + 1;
- } else {
- return NULL;
+ raise_parse_error("unreachable: %s", state);
+ return Qundef;
+}
+
+static void json_ensure_eof(JSON_ParserState *state)
+{
+ json_eat_whitespace(state);
+ if (!eos(state)) {
+ raise_parse_error("unexpected token at end of stream %s", state);
}
}
@@ -1777,24 +1411,84 @@ case 7:
static VALUE convert_encoding(VALUE source)
{
-#ifdef HAVE_RUBY_ENCODING_H
- rb_encoding *enc = rb_enc_get(source);
- if (enc == rb_ascii8bit_encoding()) {
- if (OBJ_FROZEN(source)) {
- source = rb_str_dup(source);
- }
- FORCE_UTF8(source);
- } else {
- source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding());
- }
-#endif
+ int encindex = RB_ENCODING_GET(source);
+
+ if (RB_LIKELY(encindex == utf8_encindex)) {
return source;
+ }
+
+ if (encindex == binary_encindex) {
+ // For historical reason, we silently reinterpret binary strings as UTF-8
+ return rb_enc_associate_index(rb_str_dup(source), utf8_encindex);
+ }
+
+ return rb_funcall(source, i_encode, 1, Encoding_UTF_8);
+}
+
+static int parser_config_init_i(VALUE key, VALUE val, VALUE data)
+{
+ JSON_ParserConfig *config = (JSON_ParserConfig *)data;
+
+ if (key == sym_max_nesting) { config->max_nesting = RTEST(val) ? FIX2INT(val) : 0; }
+ else if (key == sym_allow_nan) { config->allow_nan = RTEST(val); }
+ else if (key == sym_allow_trailing_comma) { config->allow_trailing_comma = RTEST(val); }
+ else if (key == sym_allow_control_characters) { config->allow_control_characters = RTEST(val); }
+ else if (key == sym_symbolize_names) { config->symbolize_names = RTEST(val); }
+ else if (key == sym_freeze) { config->freeze = RTEST(val); }
+ else if (key == sym_on_load) { config->on_load_proc = RTEST(val) ? val : Qfalse; }
+ else if (key == sym_allow_duplicate_key) { config->on_duplicate_key = RTEST(val) ? JSON_IGNORE : JSON_RAISE; }
+ else if (key == sym_decimal_class) {
+ if (RTEST(val)) {
+ if (rb_respond_to(val, i_try_convert)) {
+ config->decimal_class = val;
+ config->decimal_method_id = i_try_convert;
+ } else if (rb_respond_to(val, i_new)) {
+ config->decimal_class = val;
+ config->decimal_method_id = i_new;
+ } else if (RB_TYPE_P(val, T_CLASS)) {
+ VALUE name = rb_class_name(val);
+ const char *name_cstr = RSTRING_PTR(name);
+ const char *last_colon = strrchr(name_cstr, ':');
+ if (last_colon) {
+ const char *mod_path_end = last_colon - 1;
+ VALUE mod_path = rb_str_substr(name, 0, mod_path_end - name_cstr);
+ config->decimal_class = rb_path_to_class(mod_path);
+
+ const char *method_name_beg = last_colon + 1;
+ long before_len = method_name_beg - name_cstr;
+ long len = RSTRING_LEN(name) - before_len;
+ VALUE method_name = rb_str_substr(name, before_len, len);
+ config->decimal_method_id = SYM2ID(rb_str_intern(method_name));
+ } else {
+ config->decimal_class = rb_mKernel;
+ config->decimal_method_id = SYM2ID(rb_str_intern(name));
+ }
+ }
+ }
+ }
+
+ return ST_CONTINUE;
+}
+
+static void parser_config_init(JSON_ParserConfig *config, VALUE opts)
+{
+ config->max_nesting = 100;
+
+ if (!NIL_P(opts)) {
+ Check_Type(opts, T_HASH);
+ if (RHASH_SIZE(opts) > 0) {
+ // We assume in most cases few keys are set so it's faster to go over
+ // the provided keys than to check all possible keys.
+ rb_hash_foreach(opts, parser_config_init_i, (VALUE)config);
+ }
+
+ }
}
/*
- * call-seq: new(source, opts => {})
+ * call-seq: new(opts => {})
*
- * Creates a new JSON::Ext::Parser instance for the string _source_.
+ * Creates a new JSON::Ext::ParserConfig instance.
*
* It will be configured by the _opts_ hash. _opts_ can have the following
* keys:
@@ -1810,343 +1504,115 @@ static VALUE convert_encoding(VALUE source)
* (keys) in a JSON object. Otherwise strings are returned, which is
* also the default. It's not possible to use this option in
* conjunction with the *create_additions* option.
- * * *create_additions*: If set to false, the Parser doesn't create
- * additions even if a matching class and create_id was found. This option
- * defaults to false.
- * * *object_class*: Defaults to Hash
- * * *array_class*: Defaults to Array
+ * * *decimal_class*: Specifies which class to use instead of the default
+ * (Float) when parsing decimal numbers. This class must accept a single
+ * string argument in its constructor.
*/
-static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
+static VALUE cParserConfig_initialize(VALUE self, VALUE opts)
{
- VALUE source, opts;
- GET_PARSER_INIT;
+ rb_check_frozen(self);
+ GET_PARSER_CONFIG;
+
+ parser_config_init(config, opts);
+
+ RB_OBJ_WRITTEN(self, Qundef, config->decimal_class);
- if (json->Vsource) {
- rb_raise(rb_eTypeError, "already initialized instance");
- }
- rb_scan_args(argc, argv, "1:", &source, &opts);
- if (!NIL_P(opts)) {
- VALUE tmp = ID2SYM(i_max_nesting);
- if (option_given_p(opts, tmp)) {
- VALUE max_nesting = rb_hash_aref(opts, tmp);
- if (RTEST(max_nesting)) {
- Check_Type(max_nesting, T_FIXNUM);
- json->max_nesting = FIX2INT(max_nesting);
- } else {
- json->max_nesting = 0;
- }
- } else {
- json->max_nesting = 100;
- }
- tmp = ID2SYM(i_allow_nan);
- if (option_given_p(opts, tmp)) {
- json->allow_nan = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
- } else {
- json->allow_nan = 0;
- }
- tmp = ID2SYM(i_symbolize_names);
- if (option_given_p(opts, tmp)) {
- json->symbolize_names = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
- } else {
- json->symbolize_names = 0;
- }
- tmp = ID2SYM(i_freeze);
- if (option_given_p(opts, tmp)) {
- json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
- } else {
- json->freeze = 0;
- }
- tmp = ID2SYM(i_create_additions);
- if (option_given_p(opts, tmp)) {
- json->create_additions = RTEST(rb_hash_aref(opts, tmp));
- } else {
- json->create_additions = 0;
- }
- if (json->symbolize_names && json->create_additions) {
- rb_raise(rb_eArgError,
- "options :symbolize_names and :create_additions cannot be "
- " used in conjunction");
- }
- tmp = ID2SYM(i_create_id);
- if (option_given_p(opts, tmp)) {
- json->create_id = rb_hash_aref(opts, tmp);
- } else {
- json->create_id = rb_funcall(mJSON, i_create_id, 0);
- }
- tmp = ID2SYM(i_object_class);
- if (option_given_p(opts, tmp)) {
- json->object_class = rb_hash_aref(opts, tmp);
- } else {
- json->object_class = Qnil;
- }
- tmp = ID2SYM(i_array_class);
- if (option_given_p(opts, tmp)) {
- json->array_class = rb_hash_aref(opts, tmp);
- } else {
- json->array_class = Qnil;
- }
- tmp = ID2SYM(i_decimal_class);
- if (option_given_p(opts, tmp)) {
- json->decimal_class = rb_hash_aref(opts, tmp);
- } else {
- json->decimal_class = Qnil;
- }
- tmp = ID2SYM(i_match_string);
- if (option_given_p(opts, tmp)) {
- VALUE match_string = rb_hash_aref(opts, tmp);
- json->match_string = RTEST(match_string) ? match_string : Qnil;
- } else {
- json->match_string = Qnil;
- }
- } else {
- json->max_nesting = 100;
- json->allow_nan = 0;
- json->create_additions = 0;
- json->create_id = Qnil;
- json->object_class = Qnil;
- json->array_class = Qnil;
- json->decimal_class = Qnil;
- }
- source = convert_encoding(StringValue(source));
- StringValue(source);
- json->len = RSTRING_LEN(source);
- json->source = RSTRING_PTR(source);;
- json->Vsource = source;
return self;
}
+static VALUE cParser_parse(JSON_ParserConfig *config, VALUE Vsource)
+{
+ Vsource = convert_encoding(StringValue(Vsource));
+ StringValue(Vsource);
+
+ VALUE rvalue_stack_buffer[RVALUE_STACK_INITIAL_CAPA];
+ rvalue_stack stack = {
+ .type = RVALUE_STACK_STACK_ALLOCATED,
+ .ptr = rvalue_stack_buffer,
+ .capa = RVALUE_STACK_INITIAL_CAPA,
+ };
-#line 1920 "parser.c"
-enum {JSON_start = 1};
-enum {JSON_first_final = 10};
-enum {JSON_error = 0};
+ long len;
+ const char *start;
+ RSTRING_GETMEM(Vsource, start, len);
-enum {JSON_en_main = 1};
+ JSON_ParserState _state = {
+ .start = start,
+ .cursor = start,
+ .end = start + len,
+ .stack = &stack,
+ };
+ JSON_ParserState *state = &_state;
+ VALUE result = json_parse_any(state, config);
-#line 828 "parser.rl"
+ // This may be skipped in case of exception, but
+ // it won't cause a leak.
+ rvalue_stack_eagerly_release(state->stack_handle);
+ json_ensure_eof(state);
+
+ return result;
+}
/*
- * call-seq: parse()
+ * call-seq: parse(source)
*
* Parses the current JSON text _source_ and returns the complete data
* structure as a result.
* It raises JSON::ParserError if fail to parse.
*/
-static VALUE cParser_parse(VALUE self)
+static VALUE cParserConfig_parse(VALUE self, VALUE Vsource)
{
- char *p, *pe;
- int cs = EVIL;
- VALUE result = Qnil;
- GET_PARSER;
-
-
-#line 1946 "parser.c"
- {
- cs = JSON_start;
- }
-
-#line 845 "parser.rl"
- p = json->source;
- pe = p + json->len;
-
-#line 1955 "parser.c"
- {
- if ( p == pe )
- goto _test_eof;
- switch ( cs )
- {
-st1:
- if ( ++p == pe )
- goto _test_eof1;
-case 1:
- switch( (*p) ) {
- case 13: goto st1;
- case 32: goto st1;
- case 34: goto tr2;
- case 45: goto tr2;
- case 47: goto st6;
- case 73: goto tr2;
- case 78: goto tr2;
- case 91: goto tr2;
- case 102: goto tr2;
- case 110: goto tr2;
- case 116: goto tr2;
- case 123: goto tr2;
- }
- if ( (*p) > 10 ) {
- if ( 48 <= (*p) && (*p) <= 57 )
- goto tr2;
- } else if ( (*p) >= 9 )
- goto st1;
- goto st0;
-st0:
-cs = 0;
- goto _out;
-tr2:
-#line 820 "parser.rl"
- {
- char *np = JSON_parse_value(json, p, pe, &result, 0);
- if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;}
- }
- goto st10;
-st10:
- if ( ++p == pe )
- goto _test_eof10;
-case 10:
-#line 1999 "parser.c"
- switch( (*p) ) {
- case 13: goto st10;
- case 32: goto st10;
- case 47: goto st2;
- }
- if ( 9 <= (*p) && (*p) <= 10 )
- goto st10;
- goto st0;
-st2:
- if ( ++p == pe )
- goto _test_eof2;
-case 2:
- switch( (*p) ) {
- case 42: goto st3;
- case 47: goto st5;
- }
- goto st0;
-st3:
- if ( ++p == pe )
- goto _test_eof3;
-case 3:
- if ( (*p) == 42 )
- goto st4;
- goto st3;
-st4:
- if ( ++p == pe )
- goto _test_eof4;
-case 4:
- switch( (*p) ) {
- case 42: goto st4;
- case 47: goto st10;
- }
- goto st3;
-st5:
- if ( ++p == pe )
- goto _test_eof5;
-case 5:
- if ( (*p) == 10 )
- goto st10;
- goto st5;
-st6:
- if ( ++p == pe )
- goto _test_eof6;
-case 6:
- switch( (*p) ) {
- case 42: goto st7;
- case 47: goto st9;
- }
- goto st0;
-st7:
- if ( ++p == pe )
- goto _test_eof7;
-case 7:
- if ( (*p) == 42 )
- goto st8;
- goto st7;
-st8:
- if ( ++p == pe )
- goto _test_eof8;
-case 8:
- switch( (*p) ) {
- case 42: goto st8;
- case 47: goto st1;
- }
- goto st7;
-st9:
- if ( ++p == pe )
- goto _test_eof9;
-case 9:
- if ( (*p) == 10 )
- goto st1;
- goto st9;
- }
- _test_eof1: cs = 1; goto _test_eof;
- _test_eof10: cs = 10; goto _test_eof;
- _test_eof2: cs = 2; goto _test_eof;
- _test_eof3: cs = 3; goto _test_eof;
- _test_eof4: cs = 4; goto _test_eof;
- _test_eof5: cs = 5; goto _test_eof;
- _test_eof6: cs = 6; goto _test_eof;
- _test_eof7: cs = 7; goto _test_eof;
- _test_eof8: cs = 8; goto _test_eof;
- _test_eof9: cs = 9; goto _test_eof;
-
- _test_eof: {}
- _out: {}
- }
-
-#line 848 "parser.rl"
-
- if (cs >= JSON_first_final && p == pe) {
- return result;
- } else {
- rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p);
- return Qnil;
- }
+ GET_PARSER_CONFIG;
+ return cParser_parse(config, Vsource);
}
-static void JSON_mark(void *ptr)
+static VALUE cParser_m_parse(VALUE klass, VALUE Vsource, VALUE opts)
{
- JSON_Parser *json = ptr;
- rb_gc_mark_maybe(json->Vsource);
- rb_gc_mark_maybe(json->create_id);
- rb_gc_mark_maybe(json->object_class);
- rb_gc_mark_maybe(json->array_class);
- rb_gc_mark_maybe(json->decimal_class);
- rb_gc_mark_maybe(json->match_string);
+ Vsource = convert_encoding(StringValue(Vsource));
+ StringValue(Vsource);
+
+ JSON_ParserConfig _config = {0};
+ JSON_ParserConfig *config = &_config;
+ parser_config_init(config, opts);
+
+ return cParser_parse(config, Vsource);
+}
+
+static void JSON_ParserConfig_mark(void *ptr)
+{
+ JSON_ParserConfig *config = ptr;
+ rb_gc_mark(config->on_load_proc);
+ rb_gc_mark(config->decimal_class);
}
-static void JSON_free(void *ptr)
+static void JSON_ParserConfig_free(void *ptr)
{
- JSON_Parser *json = ptr;
- fbuffer_free(json->fbuffer);
- ruby_xfree(json);
+ JSON_ParserConfig *config = ptr;
+ ruby_xfree(config);
}
-static size_t JSON_memsize(const void *ptr)
+static size_t JSON_ParserConfig_memsize(const void *ptr)
{
- const JSON_Parser *json = ptr;
- return sizeof(*json) + FBUFFER_CAPA(json->fbuffer);
+ return sizeof(JSON_ParserConfig);
}
-#ifdef NEW_TYPEDDATA_WRAPPER
-static const rb_data_type_t JSON_Parser_type = {
- "JSON/Parser",
- {JSON_mark, JSON_free, JSON_memsize,},
-#ifdef RUBY_TYPED_FREE_IMMEDIATELY
+static const rb_data_type_t JSON_ParserConfig_type = {
+ "JSON::Ext::Parser/ParserConfig",
+ {
+ JSON_ParserConfig_mark,
+ JSON_ParserConfig_free,
+ JSON_ParserConfig_memsize,
+ },
0, 0,
- RUBY_TYPED_FREE_IMMEDIATELY,
-#endif
+ RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE,
};
-#endif
static VALUE cJSON_parser_s_allocate(VALUE klass)
{
- JSON_Parser *json;
- VALUE obj = TypedData_Make_Struct(klass, JSON_Parser, &JSON_Parser_type, json);
- json->fbuffer = fbuffer_alloc(0);
- return obj;
-}
-
-/*
- * call-seq: source()
- *
- * Returns a copy of the current _source_ string, that was used to construct
- * this Parser.
- */
-static VALUE cParser_source(VALUE self)
-{
- GET_PARSER;
- return rb_str_dup(json->Vsource);
+ JSON_ParserConfig *config;
+ return TypedData_Make_Struct(klass, JSON_ParserConfig, &JSON_ParserConfig_type, config);
}
void Init_parser(void)
@@ -2158,16 +1624,16 @@ void Init_parser(void)
#undef rb_intern
rb_require("json/common");
mJSON = rb_define_module("JSON");
- mExt = rb_define_module_under(mJSON, "Ext");
- cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
- eParserError = rb_path2class("JSON::ParserError");
+ VALUE mExt = rb_define_module_under(mJSON, "Ext");
+ VALUE cParserConfig = rb_define_class_under(mExt, "ParserConfig", rb_cObject);
eNestingError = rb_path2class("JSON::NestingError");
- rb_gc_register_mark_object(eParserError);
rb_gc_register_mark_object(eNestingError);
- rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
- rb_define_method(cParser, "initialize", cParser_initialize, -1);
- rb_define_method(cParser, "parse", cParser_parse, 0);
- rb_define_method(cParser, "source", cParser_source, 0);
+ rb_define_alloc_func(cParserConfig, cJSON_parser_s_allocate);
+ rb_define_method(cParserConfig, "initialize", cParserConfig_initialize, 1);
+ rb_define_method(cParserConfig, "parse", cParserConfig_parse, 1);
+
+ VALUE cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
+ rb_define_singleton_method(cParser, "parse", cParser_m_parse, 2);
CNaN = rb_const_get(mJSON, rb_intern("NaN"));
rb_gc_register_mark_object(CNaN);
@@ -2178,34 +1644,29 @@ void Init_parser(void)
CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
rb_gc_register_mark_object(CMinusInfinity);
- i_json_creatable_p = rb_intern("json_creatable?");
- i_json_create = rb_intern("json_create");
- i_create_id = rb_intern("create_id");
- i_create_additions = rb_intern("create_additions");
- 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("<<");
+ rb_global_variable(&Encoding_UTF_8);
+ Encoding_UTF_8 = rb_const_get(rb_path2class("Encoding"), rb_intern("UTF_8"));
+
+ sym_max_nesting = ID2SYM(rb_intern("max_nesting"));
+ sym_allow_nan = ID2SYM(rb_intern("allow_nan"));
+ sym_allow_trailing_comma = ID2SYM(rb_intern("allow_trailing_comma"));
+ sym_allow_control_characters = ID2SYM(rb_intern("allow_control_characters"));
+ sym_symbolize_names = ID2SYM(rb_intern("symbolize_names"));
+ sym_freeze = ID2SYM(rb_intern("freeze"));
+ sym_on_load = ID2SYM(rb_intern("on_load"));
+ sym_decimal_class = ID2SYM(rb_intern("decimal_class"));
+ sym_allow_duplicate_key = ID2SYM(rb_intern("allow_duplicate_key"));
+
i_new = rb_intern("new");
i_try_convert = rb_intern("try_convert");
- i_freeze = rb_intern("freeze");
i_uminus = rb_intern("-@");
-}
+ i_encode = rb_intern("encode");
-/*
- * Local variables:
- * mode: c
- * c-file-style: ruby
- * indent-tabs-mode: nil
- * End:
- */
+ binary_encindex = rb_ascii8bit_encindex();
+ utf8_encindex = rb_utf8_encindex();
+ enc_utf8 = rb_utf8_encoding();
+
+#ifdef HAVE_SIMD
+ simd_impl = find_simd_implementation();
+#endif
+}
diff --git a/ext/json/parser/parser.h b/ext/json/parser/parser.h
deleted file mode 100644
index 92ed3fdc5d..0000000000
--- a/ext/json/parser/parser.h
+++ /dev/null
@@ -1,96 +0,0 @@
-#ifndef _PARSER_H_
-#define _PARSER_H_
-
-#include "ruby.h"
-
-#ifndef HAVE_RUBY_RE_H
-#include "re.h"
-#endif
-
-#ifdef HAVE_RUBY_ST_H
-#include "ruby/st.h"
-#else
-#include "st.h"
-#endif
-
-#ifndef MAYBE_UNUSED
-# define MAYBE_UNUSED(x) x
-#endif
-
-#define option_given_p(opts, key) RTEST(rb_funcall(opts, i_key_p, 1, key))
-
-/* unicode */
-
-typedef unsigned long UTF32; /* at least 32 bits */
-typedef unsigned short UTF16; /* at least 16 bits */
-typedef unsigned char UTF8; /* typically 8 bits */
-
-#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
-#define UNI_SUR_HIGH_START (UTF32)0xD800
-#define UNI_SUR_HIGH_END (UTF32)0xDBFF
-#define UNI_SUR_LOW_START (UTF32)0xDC00
-#define UNI_SUR_LOW_END (UTF32)0xDFFF
-
-typedef struct JSON_ParserStruct {
- VALUE Vsource;
- char *source;
- long len;
- char *memo;
- VALUE create_id;
- int max_nesting;
- int allow_nan;
- int parsing_name;
- int symbolize_names;
- int freeze;
- VALUE object_class;
- VALUE array_class;
- VALUE decimal_class;
- int create_additions;
- VALUE match_string;
- FBuffer *fbuffer;
-} JSON_Parser;
-
-#define GET_PARSER \
- GET_PARSER_INIT; \
- if (!json->Vsource) rb_raise(rb_eTypeError, "uninitialized instance")
-#define GET_PARSER_INIT \
- JSON_Parser *json; \
- TypedData_Get_Struct(self, JSON_Parser, &JSON_Parser_type, json)
-
-#define MinusInfinity "-Infinity"
-#define EVIL 0x666
-
-static UTF32 unescape_unicode(const unsigned char *p);
-static int convert_UTF32_to_UTF8(char *buf, UTF32 ch);
-static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting);
-static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting);
-static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result);
-static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result);
-static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting);
-static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int symbolize);
-static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result);
-static VALUE convert_encoding(VALUE source);
-static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self);
-static VALUE cParser_parse(VALUE self);
-static void JSON_mark(void *json);
-static void JSON_free(void *json);
-static VALUE cJSON_parser_s_allocate(VALUE klass);
-static VALUE cParser_source(VALUE self);
-#ifndef ZALLOC
-#define ZALLOC(type) ((type *)ruby_zalloc(sizeof(type)))
-static inline void *ruby_zalloc(size_t n)
-{
- void *p = ruby_xmalloc(n);
- memset(p, 0, n);
- return p;
-}
-#endif
-#ifdef TypedData_Make_Struct
-static const rb_data_type_t JSON_Parser_type;
-#define NEW_TYPEDDATA_WRAPPER 1
-#else
-#define TypedData_Make_Struct(klass, type, ignore, json) Data_Make_Struct(klass, type, NULL, JSON_free, json)
-#define TypedData_Get_Struct(self, JSON_Parser, ignore, json) Data_Get_Struct(self, JSON_Parser, json)
-#endif
-
-#endif
diff --git a/ext/json/parser/parser.rl b/ext/json/parser/parser.rl
deleted file mode 100644
index af190e7500..0000000000
--- a/ext/json/parser/parser.rl
+++ /dev/null
@@ -1,971 +0,0 @@
-#include "../fbuffer/fbuffer.h"
-#include "parser.h"
-
-#if defined HAVE_RUBY_ENCODING_H
-# define EXC_ENCODING rb_utf8_encoding(),
-# ifndef HAVE_RB_ENC_RAISE
-static void
-enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...)
-{
- va_list args;
- VALUE mesg;
-
- va_start(args, fmt);
- mesg = rb_enc_vsprintf(enc, fmt, args);
- va_end(args);
-
- rb_exc_raise(rb_exc_new3(exc, mesg));
-}
-# define rb_enc_raise enc_raise
-# endif
-#else
-# define EXC_ENCODING /* nothing */
-# define rb_enc_raise rb_raise
-#endif
-
-/* unicode */
-
-static const signed char digit_values[256] = {
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1,
- -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1
-};
-
-static UTF32 unescape_unicode(const unsigned char *p)
-{
- signed char b;
- UTF32 result = 0;
- b = digit_values[p[0]];
- if (b < 0) return UNI_REPLACEMENT_CHAR;
- result = (result << 4) | (unsigned char)b;
- b = digit_values[p[1]];
- if (b < 0) return UNI_REPLACEMENT_CHAR;
- result = (result << 4) | (unsigned char)b;
- b = digit_values[p[2]];
- if (b < 0) return UNI_REPLACEMENT_CHAR;
- result = (result << 4) | (unsigned char)b;
- b = digit_values[p[3]];
- if (b < 0) return UNI_REPLACEMENT_CHAR;
- result = (result << 4) | (unsigned char)b;
- return result;
-}
-
-static int convert_UTF32_to_UTF8(char *buf, UTF32 ch)
-{
- int len = 1;
- if (ch <= 0x7F) {
- buf[0] = (char) ch;
- } else if (ch <= 0x07FF) {
- buf[0] = (char) ((ch >> 6) | 0xC0);
- buf[1] = (char) ((ch & 0x3F) | 0x80);
- len++;
- } else if (ch <= 0xFFFF) {
- buf[0] = (char) ((ch >> 12) | 0xE0);
- buf[1] = (char) (((ch >> 6) & 0x3F) | 0x80);
- buf[2] = (char) ((ch & 0x3F) | 0x80);
- len += 2;
- } else if (ch <= 0x1fffff) {
- buf[0] =(char) ((ch >> 18) | 0xF0);
- buf[1] =(char) (((ch >> 12) & 0x3F) | 0x80);
- buf[2] =(char) (((ch >> 6) & 0x3F) | 0x80);
- buf[3] =(char) ((ch & 0x3F) | 0x80);
- len += 3;
- } else {
- buf[0] = '?';
- }
- return len;
-}
-
-static VALUE mJSON, mExt, cParser, eParserError, eNestingError;
-static VALUE CNaN, CInfinity, CMinusInfinity;
-
-static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions,
- i_chr, i_max_nesting, i_allow_nan, i_symbolize_names,
- i_object_class, i_array_class, i_decimal_class, i_key_p,
- i_deep_const_get, i_match, i_match_string, i_aset, i_aref,
- i_leftshift, i_new, i_try_convert, i_freeze, i_uminus;
-
-%%{
- machine JSON_common;
-
- cr = '\n';
- cr_neg = [^\n];
- ws = [ \t\r\n];
- c_comment = '/*' ( any* - (any* '*/' any* ) ) '*/';
- cpp_comment = '//' cr_neg* cr;
- comment = c_comment | cpp_comment;
- ignore = ws | comment;
- name_separator = ':';
- value_separator = ',';
- Vnull = 'null';
- Vfalse = 'false';
- Vtrue = 'true';
- VNaN = 'NaN';
- VInfinity = 'Infinity';
- VMinusInfinity = '-Infinity';
- begin_value = [nft\"\-\[\{NI] | digit;
- begin_object = '{';
- end_object = '}';
- begin_array = '[';
- end_array = ']';
- begin_string = '"';
- begin_name = begin_string;
- begin_number = digit | '-';
-}%%
-
-%%{
- machine JSON_object;
- include JSON_common;
-
- write data;
-
- action parse_value {
- VALUE v = Qnil;
- char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting);
- if (np == NULL) {
- fhold; fbreak;
- } else {
- if (NIL_P(json->object_class)) {
- OBJ_FREEZE(last_name);
- rb_hash_aset(*result, last_name, v);
- } else {
- rb_funcall(*result, i_aset, 2, last_name, v);
- }
- fexec np;
- }
- }
-
- action parse_name {
- char *np;
- json->parsing_name = 1;
- np = JSON_parse_string(json, fpc, pe, &last_name);
- json->parsing_name = 0;
- if (np == NULL) { fhold; fbreak; } else fexec np;
- }
-
- action exit { fhold; fbreak; }
-
- pair = ignore* begin_name >parse_name ignore* name_separator ignore* begin_value >parse_value;
- next_pair = ignore* value_separator pair;
-
- main := (
- begin_object
- (pair (next_pair)*)? ignore*
- end_object
- ) @exit;
-}%%
-
-static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
-{
- int cs = EVIL;
- VALUE last_name = Qnil;
- VALUE object_class = json->object_class;
-
- if (json->max_nesting && current_nesting > json->max_nesting) {
- rb_raise(eNestingError, "nesting of %d is too deep", current_nesting);
- }
-
- *result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class);
-
- %% write init;
- %% write exec;
-
- if (cs >= JSON_object_first_final) {
- if (json->create_additions) {
- VALUE klassname;
- if (NIL_P(json->object_class)) {
- klassname = rb_hash_aref(*result, json->create_id);
- } else {
- klassname = rb_funcall(*result, i_aref, 1, json->create_id);
- }
- if (!NIL_P(klassname)) {
- VALUE klass = rb_funcall(mJSON, i_deep_const_get, 1, klassname);
- if (RTEST(rb_funcall(klass, i_json_creatable_p, 0))) {
- *result = rb_funcall(klass, i_json_create, 1, *result);
- }
- }
- }
- return p + 1;
- } else {
- return NULL;
- }
-}
-
-
-%%{
- machine JSON_value;
- include JSON_common;
-
- write data;
-
- action parse_null {
- *result = Qnil;
- }
- action parse_false {
- *result = Qfalse;
- }
- action parse_true {
- *result = Qtrue;
- }
- action parse_nan {
- if (json->allow_nan) {
- *result = CNaN;
- } else {
- rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 2);
- }
- }
- action parse_infinity {
- if (json->allow_nan) {
- *result = CInfinity;
- } else {
- rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 7);
- }
- }
- action parse_string {
- char *np = JSON_parse_string(json, fpc, pe, result);
- if (np == NULL) { fhold; fbreak; } else fexec np;
- }
-
- action parse_number {
- char *np;
- if(pe > fpc + 8 && !strncmp(MinusInfinity, fpc, 9)) {
- if (json->allow_nan) {
- *result = CMinusInfinity;
- fexec p + 10;
- fhold; fbreak;
- } else {
- rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p);
- }
- }
- np = JSON_parse_float(json, fpc, pe, result);
- if (np != NULL) fexec np;
- np = JSON_parse_integer(json, fpc, pe, result);
- if (np != NULL) fexec np;
- fhold; fbreak;
- }
-
- action parse_array {
- char *np;
- np = JSON_parse_array(json, fpc, pe, result, current_nesting + 1);
- if (np == NULL) { fhold; fbreak; } else fexec np;
- }
-
- action parse_object {
- char *np;
- np = JSON_parse_object(json, fpc, pe, result, current_nesting + 1);
- if (np == NULL) { fhold; fbreak; } else fexec np;
- }
-
- action exit { fhold; fbreak; }
-
-main := ignore* (
- Vnull @parse_null |
- Vfalse @parse_false |
- Vtrue @parse_true |
- VNaN @parse_nan |
- VInfinity @parse_infinity |
- begin_number >parse_number |
- begin_string >parse_string |
- begin_array >parse_array |
- begin_object >parse_object
- ) ignore* %*exit;
-}%%
-
-static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
-{
- int cs = EVIL;
-
- %% write init;
- %% write exec;
-
- if (json->freeze) {
- OBJ_FREEZE(*result);
- }
-
- if (cs >= JSON_value_first_final) {
- return p;
- } else {
- return NULL;
- }
-}
-
-%%{
- machine JSON_integer;
-
- write data;
-
- action exit { fhold; fbreak; }
-
- main := '-'? ('0' | [1-9][0-9]*) (^[0-9]? @exit);
-}%%
-
-static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result)
-{
- int cs = EVIL;
-
- %% write init;
- json->memo = p;
- %% write exec;
-
- if (cs >= JSON_integer_first_final) {
- long len = p - json->memo;
- fbuffer_clear(json->fbuffer);
- fbuffer_append(json->fbuffer, json->memo, len);
- fbuffer_append_char(json->fbuffer, '\0');
- *result = rb_cstr2inum(FBUFFER_PTR(json->fbuffer), 10);
- return p + 1;
- } else {
- return NULL;
- }
-}
-
-%%{
- machine JSON_float;
- include JSON_common;
-
- write data;
-
- action exit { fhold; fbreak; }
-
- main := '-'? (
- (('0' | [1-9][0-9]*) '.' [0-9]+ ([Ee] [+\-]?[0-9]+)?)
- | (('0' | [1-9][0-9]*) ([Ee] [+\-]?[0-9]+))
- ) (^[0-9Ee.\-]? @exit );
-}%%
-
-static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result)
-{
- int cs = EVIL;
-
- %% write init;
- json->memo = p;
- %% write exec;
-
- if (cs >= JSON_float_first_final) {
- VALUE mod = Qnil;
- ID method_id = 0;
- if (rb_respond_to(json->decimal_class, i_try_convert)) {
- mod = json->decimal_class;
- method_id = i_try_convert;
- } else if (rb_respond_to(json->decimal_class, i_new)) {
- mod = json->decimal_class;
- method_id = i_new;
- } else if (RB_TYPE_P(json->decimal_class, T_CLASS)) {
- VALUE name = rb_class_name(json->decimal_class);
- const char *name_cstr = RSTRING_PTR(name);
- const char *last_colon = strrchr(name_cstr, ':');
- if (last_colon) {
- const char *mod_path_end = last_colon - 1;
- VALUE mod_path = rb_str_substr(name, 0, mod_path_end - name_cstr);
- mod = rb_path_to_class(mod_path);
-
- const char *method_name_beg = last_colon + 1;
- long before_len = method_name_beg - name_cstr;
- long len = RSTRING_LEN(name) - before_len;
- VALUE method_name = rb_str_substr(name, before_len, len);
- method_id = SYM2ID(rb_str_intern(method_name));
- } else {
- mod = rb_mKernel;
- method_id = SYM2ID(rb_str_intern(name));
- }
- }
-
- long len = p - json->memo;
- fbuffer_clear(json->fbuffer);
- fbuffer_append(json->fbuffer, json->memo, len);
- fbuffer_append_char(json->fbuffer, '\0');
-
- if (method_id) {
- VALUE text = rb_str_new2(FBUFFER_PTR(json->fbuffer));
- *result = rb_funcallv(mod, method_id, 1, &text);
- } else {
- *result = DBL2NUM(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1));
- }
-
- return p + 1;
- } else {
- return NULL;
- }
-}
-
-
-%%{
- machine JSON_array;
- include JSON_common;
-
- write data;
-
- action parse_value {
- VALUE v = Qnil;
- char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting);
- if (np == NULL) {
- fhold; fbreak;
- } else {
- if (NIL_P(json->array_class)) {
- rb_ary_push(*result, v);
- } else {
- rb_funcall(*result, i_leftshift, 1, v);
- }
- fexec np;
- }
- }
-
- action exit { fhold; fbreak; }
-
- next_element = value_separator ignore* begin_value >parse_value;
-
- main := begin_array ignore*
- ((begin_value >parse_value ignore*)
- (ignore* next_element ignore*)*)?
- end_array @exit;
-}%%
-
-static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting)
-{
- int cs = EVIL;
- VALUE array_class = json->array_class;
-
- if (json->max_nesting && current_nesting > json->max_nesting) {
- rb_raise(eNestingError, "nesting of %d is too deep", current_nesting);
- }
- *result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class);
-
- %% write init;
- %% write exec;
-
- if(cs >= JSON_array_first_final) {
- return p + 1;
- } else {
- rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p);
- return NULL;
- }
-}
-
-static const size_t MAX_STACK_BUFFER_SIZE = 128;
-static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int symbolize)
-{
- VALUE result = Qnil;
- size_t bufferSize = stringEnd - string;
- char *p = string, *pe = string, *unescape, *bufferStart, *buffer;
- int unescape_len;
- char buf[4];
-
- if (bufferSize > MAX_STACK_BUFFER_SIZE) {
-# ifdef HAVE_RB_ENC_INTERNED_STR
- bufferStart = buffer = ALLOC_N(char, bufferSize ? bufferSize : 1);
-# else
- bufferStart = buffer = ALLOC_N(char, bufferSize);
-# endif
- } else {
-# ifdef HAVE_RB_ENC_INTERNED_STR
- bufferStart = buffer = ALLOCA_N(char, bufferSize ? bufferSize : 1);
-# else
- bufferStart = buffer = ALLOCA_N(char, bufferSize);
-# endif
- }
-
- while (pe < stringEnd) {
- if (*pe == '\\') {
- unescape = (char *) "?";
- unescape_len = 1;
- if (pe > p) {
- MEMCPY(buffer, p, char, pe - p);
- buffer += pe - p;
- }
- switch (*++pe) {
- case 'n':
- unescape = (char *) "\n";
- break;
- case 'r':
- unescape = (char *) "\r";
- break;
- case 't':
- unescape = (char *) "\t";
- break;
- case '"':
- unescape = (char *) "\"";
- break;
- case '\\':
- unescape = (char *) "\\";
- break;
- case 'b':
- unescape = (char *) "\b";
- break;
- case 'f':
- unescape = (char *) "\f";
- break;
- case 'u':
- if (pe > stringEnd - 4) {
- if (bufferSize > MAX_STACK_BUFFER_SIZE) {
- ruby_xfree(bufferStart);
- }
- rb_enc_raise(
- EXC_ENCODING eParserError,
- "incomplete unicode character escape sequence at '%s'", p
- );
- } else {
- UTF32 ch = unescape_unicode((unsigned char *) ++pe);
- pe += 3;
- if (UNI_SUR_HIGH_START == (ch & 0xFC00)) {
- pe++;
- if (pe > stringEnd - 6) {
- if (bufferSize > MAX_STACK_BUFFER_SIZE) {
- ruby_xfree(bufferStart);
- }
- rb_enc_raise(
- EXC_ENCODING eParserError,
- "incomplete surrogate pair at '%s'", p
- );
- }
- if (pe[0] == '\\' && pe[1] == 'u') {
- UTF32 sur = unescape_unicode((unsigned char *) pe + 2);
- ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16)
- | (sur & 0x3FF));
- pe += 5;
- } else {
- unescape = (char *) "?";
- break;
- }
- }
- unescape_len = convert_UTF32_to_UTF8(buf, ch);
- unescape = buf;
- }
- break;
- default:
- p = pe;
- continue;
- }
- MEMCPY(buffer, unescape, char, unescape_len);
- buffer += unescape_len;
- p = ++pe;
- } else {
- pe++;
- }
- }
-
- if (pe > p) {
- MEMCPY(buffer, p, char, pe - p);
- buffer += pe - p;
- }
-
-# ifdef HAVE_RB_ENC_INTERNED_STR
- if (intern) {
- result = rb_enc_interned_str(bufferStart, (long)(buffer - bufferStart), rb_utf8_encoding());
- } else {
- result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
- }
- if (bufferSize > MAX_STACK_BUFFER_SIZE) {
- ruby_xfree(bufferStart);
- }
-# else
- result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart));
-
- if (bufferSize > MAX_STACK_BUFFER_SIZE) {
- ruby_xfree(bufferStart);
- }
-
- if (intern) {
- # if STR_UMINUS_DEDUPE_FROZEN
- // Starting from MRI 2.8 it is preferable to freeze the string
- // before deduplication so that it can be interned directly
- // otherwise it would be duplicated first which is wasteful.
- result = rb_funcall(rb_str_freeze(result), i_uminus, 0);
- # elif STR_UMINUS_DEDUPE
- // MRI 2.5 and older do not deduplicate strings that are already
- // frozen.
- result = rb_funcall(result, i_uminus, 0);
- # else
- result = rb_str_freeze(result);
- # endif
- }
-# endif
-
- if (symbolize) {
- result = rb_str_intern(result);
- }
-
- return result;
-}
-
-%%{
- machine JSON_string;
- include JSON_common;
-
- write data;
-
- action parse_string {
- *result = json_string_unescape(json->memo + 1, p, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names);
- if (NIL_P(*result)) {
- fhold;
- fbreak;
- } else {
- fexec p + 1;
- }
- }
-
- action exit { fhold; fbreak; }
-
- main := '"' ((^([\"\\] | 0..0x1f) | '\\'[\"\\/bfnrt] | '\\u'[0-9a-fA-F]{4} | '\\'^([\"\\/bfnrtu]|0..0x1f))* %parse_string) '"' @exit;
-}%%
-
-static int
-match_i(VALUE regexp, VALUE klass, VALUE memo)
-{
- if (regexp == Qundef) return ST_STOP;
- if (RTEST(rb_funcall(klass, i_json_creatable_p, 0)) &&
- RTEST(rb_funcall(regexp, i_match, 1, rb_ary_entry(memo, 0)))) {
- rb_ary_push(memo, klass);
- return ST_STOP;
- }
- return ST_CONTINUE;
-}
-
-static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result)
-{
- int cs = EVIL;
- VALUE match_string;
-
- %% write init;
- json->memo = p;
- %% write exec;
-
- if (json->create_additions && RTEST(match_string = json->match_string)) {
- VALUE klass;
- VALUE memo = rb_ary_new2(2);
- rb_ary_push(memo, *result);
- rb_hash_foreach(match_string, match_i, memo);
- klass = rb_ary_entry(memo, 1);
- if (RTEST(klass)) {
- *result = rb_funcall(klass, i_json_create, 1, *result);
- }
- }
-
- if (cs >= JSON_string_first_final) {
- return p + 1;
- } else {
- return NULL;
- }
-}
-
-/*
- * Document-class: JSON::Ext::Parser
- *
- * This is the JSON parser implemented as a C extension. It can be configured
- * to be used by setting
- *
- * JSON.parser = JSON::Ext::Parser
- *
- * with the method parser= in JSON.
- *
- */
-
-static VALUE convert_encoding(VALUE source)
-{
-#ifdef HAVE_RUBY_ENCODING_H
- rb_encoding *enc = rb_enc_get(source);
- if (enc == rb_ascii8bit_encoding()) {
- if (OBJ_FROZEN(source)) {
- source = rb_str_dup(source);
- }
- FORCE_UTF8(source);
- } else {
- source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding());
- }
-#endif
- return source;
-}
-
-/*
- * call-seq: new(source, opts => {})
- *
- * Creates a new JSON::Ext::Parser instance for the string _source_.
- *
- * It will be configured by the _opts_ hash. _opts_ can have the following
- * keys:
- *
- * _opts_ can have the following keys:
- * * *max_nesting*: The maximum depth of nesting allowed in the parsed data
- * structures. Disable depth checking with :max_nesting => false|nil|0, it
- * defaults to 100.
- * * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
- * defiance of RFC 4627 to be parsed by the Parser. This option defaults to
- * false.
- * * *symbolize_names*: If set to true, returns symbols for the names
- * (keys) in a JSON object. Otherwise strings are returned, which is
- * also the default. It's not possible to use this option in
- * conjunction with the *create_additions* option.
- * * *create_additions*: If set to false, the Parser doesn't create
- * additions even if a matching class and create_id was found. This option
- * defaults to false.
- * * *object_class*: Defaults to Hash
- * * *array_class*: Defaults to Array
- */
-static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
-{
- VALUE source, opts;
- GET_PARSER_INIT;
-
- if (json->Vsource) {
- rb_raise(rb_eTypeError, "already initialized instance");
- }
- rb_scan_args(argc, argv, "1:", &source, &opts);
- if (!NIL_P(opts)) {
- VALUE tmp = ID2SYM(i_max_nesting);
- if (option_given_p(opts, tmp)) {
- VALUE max_nesting = rb_hash_aref(opts, tmp);
- if (RTEST(max_nesting)) {
- Check_Type(max_nesting, T_FIXNUM);
- json->max_nesting = FIX2INT(max_nesting);
- } else {
- json->max_nesting = 0;
- }
- } else {
- json->max_nesting = 100;
- }
- tmp = ID2SYM(i_allow_nan);
- if (option_given_p(opts, tmp)) {
- json->allow_nan = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
- } else {
- json->allow_nan = 0;
- }
- tmp = ID2SYM(i_symbolize_names);
- if (option_given_p(opts, tmp)) {
- json->symbolize_names = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
- } else {
- json->symbolize_names = 0;
- }
- tmp = ID2SYM(i_freeze);
- if (option_given_p(opts, tmp)) {
- json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0;
- } else {
- json->freeze = 0;
- }
- tmp = ID2SYM(i_create_additions);
- if (option_given_p(opts, tmp)) {
- json->create_additions = RTEST(rb_hash_aref(opts, tmp));
- } else {
- json->create_additions = 0;
- }
- if (json->symbolize_names && json->create_additions) {
- rb_raise(rb_eArgError,
- "options :symbolize_names and :create_additions cannot be "
- " used in conjunction");
- }
- tmp = ID2SYM(i_create_id);
- if (option_given_p(opts, tmp)) {
- json->create_id = rb_hash_aref(opts, tmp);
- } else {
- json->create_id = rb_funcall(mJSON, i_create_id, 0);
- }
- tmp = ID2SYM(i_object_class);
- if (option_given_p(opts, tmp)) {
- json->object_class = rb_hash_aref(opts, tmp);
- } else {
- json->object_class = Qnil;
- }
- tmp = ID2SYM(i_array_class);
- if (option_given_p(opts, tmp)) {
- json->array_class = rb_hash_aref(opts, tmp);
- } else {
- json->array_class = Qnil;
- }
- tmp = ID2SYM(i_decimal_class);
- if (option_given_p(opts, tmp)) {
- json->decimal_class = rb_hash_aref(opts, tmp);
- } else {
- json->decimal_class = Qnil;
- }
- tmp = ID2SYM(i_match_string);
- if (option_given_p(opts, tmp)) {
- VALUE match_string = rb_hash_aref(opts, tmp);
- json->match_string = RTEST(match_string) ? match_string : Qnil;
- } else {
- json->match_string = Qnil;
- }
- } else {
- json->max_nesting = 100;
- json->allow_nan = 0;
- json->create_additions = 0;
- json->create_id = Qnil;
- json->object_class = Qnil;
- json->array_class = Qnil;
- json->decimal_class = Qnil;
- }
- source = convert_encoding(StringValue(source));
- StringValue(source);
- json->len = RSTRING_LEN(source);
- json->source = RSTRING_PTR(source);;
- json->Vsource = source;
- return self;
-}
-
-%%{
- machine JSON;
-
- write data;
-
- include JSON_common;
-
- action parse_value {
- char *np = JSON_parse_value(json, fpc, pe, &result, 0);
- if (np == NULL) { fhold; fbreak; } else fexec np;
- }
-
- main := ignore* (
- begin_value >parse_value
- ) ignore*;
-}%%
-
-/*
- * call-seq: parse()
- *
- * Parses the current JSON text _source_ and returns the complete data
- * structure as a result.
- * It raises JSON::ParserError if fail to parse.
- */
-static VALUE cParser_parse(VALUE self)
-{
- char *p, *pe;
- int cs = EVIL;
- VALUE result = Qnil;
- GET_PARSER;
-
- %% write init;
- p = json->source;
- pe = p + json->len;
- %% write exec;
-
- if (cs >= JSON_first_final && p == pe) {
- return result;
- } else {
- rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p);
- return Qnil;
- }
-}
-
-static void JSON_mark(void *ptr)
-{
- JSON_Parser *json = ptr;
- rb_gc_mark_maybe(json->Vsource);
- rb_gc_mark_maybe(json->create_id);
- rb_gc_mark_maybe(json->object_class);
- rb_gc_mark_maybe(json->array_class);
- rb_gc_mark_maybe(json->decimal_class);
- rb_gc_mark_maybe(json->match_string);
-}
-
-static void JSON_free(void *ptr)
-{
- JSON_Parser *json = ptr;
- fbuffer_free(json->fbuffer);
- ruby_xfree(json);
-}
-
-static size_t JSON_memsize(const void *ptr)
-{
- const JSON_Parser *json = ptr;
- return sizeof(*json) + FBUFFER_CAPA(json->fbuffer);
-}
-
-#ifdef NEW_TYPEDDATA_WRAPPER
-static const rb_data_type_t JSON_Parser_type = {
- "JSON/Parser",
- {JSON_mark, JSON_free, JSON_memsize,},
-#ifdef RUBY_TYPED_FREE_IMMEDIATELY
- 0, 0,
- RUBY_TYPED_FREE_IMMEDIATELY,
-#endif
-};
-#endif
-
-static VALUE cJSON_parser_s_allocate(VALUE klass)
-{
- JSON_Parser *json;
- VALUE obj = TypedData_Make_Struct(klass, JSON_Parser, &JSON_Parser_type, json);
- json->fbuffer = fbuffer_alloc(0);
- return obj;
-}
-
-/*
- * call-seq: source()
- *
- * Returns a copy of the current _source_ string, that was used to construct
- * this Parser.
- */
-static VALUE cParser_source(VALUE self)
-{
- GET_PARSER;
- return rb_str_dup(json->Vsource);
-}
-
-void Init_parser(void)
-{
-#ifdef HAVE_RB_EXT_RACTOR_SAFE
- rb_ext_ractor_safe(true);
-#endif
-
-#undef rb_intern
- rb_require("json/common");
- mJSON = rb_define_module("JSON");
- mExt = rb_define_module_under(mJSON, "Ext");
- cParser = rb_define_class_under(mExt, "Parser", rb_cObject);
- eParserError = rb_path2class("JSON::ParserError");
- eNestingError = rb_path2class("JSON::NestingError");
- rb_gc_register_mark_object(eParserError);
- rb_gc_register_mark_object(eNestingError);
- rb_define_alloc_func(cParser, cJSON_parser_s_allocate);
- rb_define_method(cParser, "initialize", cParser_initialize, -1);
- rb_define_method(cParser, "parse", cParser_parse, 0);
- rb_define_method(cParser, "source", cParser_source, 0);
-
- CNaN = rb_const_get(mJSON, rb_intern("NaN"));
- rb_gc_register_mark_object(CNaN);
-
- CInfinity = rb_const_get(mJSON, rb_intern("Infinity"));
- rb_gc_register_mark_object(CInfinity);
-
- CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity"));
- rb_gc_register_mark_object(CMinusInfinity);
-
- i_json_creatable_p = rb_intern("json_creatable?");
- i_json_create = rb_intern("json_create");
- i_create_id = rb_intern("create_id");
- i_create_additions = rb_intern("create_additions");
- i_chr = rb_intern("chr");
- i_max_nesting = rb_intern("max_nesting");
- i_allow_nan = rb_intern("allow_nan");
- i_symbolize_names = rb_intern("symbolize_names");
- i_object_class = rb_intern("object_class");
- i_array_class = rb_intern("array_class");
- i_decimal_class = rb_intern("decimal_class");
- i_match = rb_intern("match");
- i_match_string = rb_intern("match_string");
- i_key_p = rb_intern("key?");
- i_deep_const_get = rb_intern("deep_const_get");
- i_aset = rb_intern("[]=");
- i_aref = rb_intern("[]");
- i_leftshift = rb_intern("<<");
- i_new = rb_intern("new");
- i_try_convert = rb_intern("try_convert");
- i_freeze = rb_intern("freeze");
- i_uminus = rb_intern("-@");
-}
-
-/*
- * Local variables:
- * mode: c
- * c-file-style: ruby
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/ext/json/parser/prereq.mk b/ext/json/parser/prereq.mk
deleted file mode 100644
index fc59169056..0000000000
--- a/ext/json/parser/prereq.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-RAGEL = ragel
-
-.SUFFIXES: .rl
-
-.rl.c:
- $(RAGEL) -G2 $<
- $(BASERUBY) -pli -e '$$_.sub!(/[ \t]+$$/, "")' \
- -e '$$_.sub!(/^static const int (JSON_.*=.*);$$/, "enum {\\1};")' \
- -e '$$_.sub!(/^(static const char) (_JSON(?:_\w+)?_nfa_\w+)(?=\[\] =)/, "\\1 MAYBE_UNUSED(\\2)")' \
- -e '$$_.sub!(/0 <= ([\( ]+\*[\( ]*p\)+) && \1 <= 31/, "0 <= (signed char)(*(p)) && (*(p)) <= 31")' \
- -e '$$_ = "/* This file is automatically generated from parser.rl by using ragel */\n" + $$_ if $$. == 1' $@
-
-parser.c:
diff --git a/ext/json/simd/conf.rb b/ext/json/simd/conf.rb
new file mode 100644
index 0000000000..76f774bc97
--- /dev/null
+++ b/ext/json/simd/conf.rb
@@ -0,0 +1,24 @@
+case RbConfig::CONFIG['host_cpu']
+when /^(arm|aarch64)/
+ # Try to compile a small program using NEON instructions
+ header, type, init, extra = 'arm_neon.h', 'uint8x16_t', 'vdupq_n_u8(32)', nil
+when /^(x86_64|x64)/
+ header, type, init, extra = 'x86intrin.h', '__m128i', '_mm_set1_epi8(32)', 'if (__builtin_cpu_supports("sse2")) { printf("OK"); }'
+end
+if header
+ if have_header(header) && try_compile(<<~SRC, '-Werror=implicit-function-declaration')
+ #{cpp_include(header)}
+ int main(int argc, char **argv) {
+ #{type} test = #{init};
+ #{extra}
+ if (argc > 100000) printf("%p", &test);
+ return 0;
+ }
+ SRC
+ $defs.push("-DJSON_ENABLE_SIMD")
+ else
+ puts "Disable SIMD"
+ end
+end
+
+have_header('cpuid.h')
diff --git a/ext/json/simd/simd.h b/ext/json/simd/simd.h
new file mode 100644
index 0000000000..3bb86acdec
--- /dev/null
+++ b/ext/json/simd/simd.h
@@ -0,0 +1,218 @@
+#include "../json.h"
+
+typedef enum {
+ SIMD_NONE,
+ SIMD_NEON,
+ SIMD_SSE2
+} SIMD_Implementation;
+
+#ifndef __has_builtin // Optional of course.
+ #define __has_builtin(x) 0 // Compatibility with non-clang compilers.
+#endif
+
+#ifdef __clang__
+# if __has_builtin(__builtin_ctzll)
+# define HAVE_BUILTIN_CTZLL 1
+# else
+# define HAVE_BUILTIN_CTZLL 0
+# endif
+#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
+# define HAVE_BUILTIN_CTZLL 1
+#else
+# define HAVE_BUILTIN_CTZLL 0
+#endif
+
+static inline uint32_t trailing_zeros64(uint64_t input)
+{
+ JSON_ASSERT(input > 0); // __builtin_ctz(0) is undefined behavior
+
+#if HAVE_BUILTIN_CTZLL
+ return __builtin_ctzll(input);
+#else
+ uint32_t trailing_zeros = 0;
+ uint64_t temp = input;
+ while ((temp & 1) == 0 && temp > 0) {
+ trailing_zeros++;
+ temp >>= 1;
+ }
+ return trailing_zeros;
+#endif
+}
+
+static inline int trailing_zeros(int input)
+{
+ JSON_ASSERT(input > 0); // __builtin_ctz(0) is undefined behavior
+
+#if HAVE_BUILTIN_CTZLL
+ return __builtin_ctz(input);
+#else
+ int trailing_zeros = 0;
+ int temp = input;
+ while ((temp & 1) == 0 && temp > 0) {
+ trailing_zeros++;
+ temp >>= 1;
+ }
+ return trailing_zeros;
+#endif
+}
+
+#ifdef JSON_ENABLE_SIMD
+
+#define SIMD_MINIMUM_THRESHOLD 4
+
+ALWAYS_INLINE(static) void json_fast_memcpy16(char *dst, const char *src, size_t len)
+{
+ RBIMPL_ASSERT_OR_ASSUME(len < 16);
+ RBIMPL_ASSERT_OR_ASSUME(len >= SIMD_MINIMUM_THRESHOLD); // 4
+#if defined(__has_builtin) && __has_builtin(__builtin_memcpy)
+ // If __builtin_memcpy is available, use it to copy between SIMD_MINIMUM_THRESHOLD (4) and vec_len-1 (15) bytes.
+ // These copies overlap. The first copy will copy the first 8 (or 4) bytes. The second copy will copy
+ // the last 8 (or 4) bytes but overlap with the first copy. The overlapping bytes will be in the correct
+ // position in both copies.
+
+ // Please do not attempt to replace __builtin_memcpy with memcpy without profiling and/or looking at the
+ // generated assembly. On clang-specifically (tested on Apple clang version 17.0.0 (clang-1700.0.13.3)),
+ // when using memcpy, the compiler will notice the only difference is a 4 or 8 and generate a conditional
+ // select instruction instead of direct loads and stores with a branch. This ends up slower than the branch
+ // plus two loads and stores generated when using __builtin_memcpy.
+ if (len >= 8) {
+ __builtin_memcpy(dst, src, 8);
+ __builtin_memcpy(dst + len - 8, src + len - 8, 8);
+ } else {
+ __builtin_memcpy(dst, src, 4);
+ __builtin_memcpy(dst + len - 4, src + len - 4, 4);
+ }
+#else
+ MEMCPY(dst, src, char, len);
+#endif
+}
+
+#if defined(__ARM_NEON) || defined(__ARM_NEON__) || defined(__aarch64__) || defined(_M_ARM64)
+#include <arm_neon.h>
+
+#define FIND_SIMD_IMPLEMENTATION_DEFINED 1
+static inline SIMD_Implementation find_simd_implementation(void)
+{
+ return SIMD_NEON;
+}
+
+#define HAVE_SIMD 1
+#define HAVE_SIMD_NEON 1
+
+// See: https://community.arm.com/arm-community-blogs/b/servers-and-cloud-computing-blog/posts/porting-x86-vector-bitmask-optimizations-to-arm-neon
+ALWAYS_INLINE(static) uint64_t neon_match_mask(uint8x16_t matches)
+{
+ const uint8x8_t res = vshrn_n_u16(vreinterpretq_u16_u8(matches), 4);
+ const uint64_t mask = vget_lane_u64(vreinterpret_u64_u8(res), 0);
+ return mask & 0x8888888888888888ull;
+}
+
+ALWAYS_INLINE(static) uint64_t compute_chunk_mask_neon(const char *ptr)
+{
+ uint8x16_t chunk = vld1q_u8((const unsigned char *)ptr);
+
+ // Trick: c < 32 || c == 34 can be factored as c ^ 2 < 33
+ // https://lemire.me/blog/2025/04/13/detect-control-characters-quotes-and-backslashes-efficiently-using-swar/
+ const uint8x16_t too_low_or_dbl_quote = vcltq_u8(veorq_u8(chunk, vdupq_n_u8(2)), vdupq_n_u8(33));
+
+ uint8x16_t has_backslash = vceqq_u8(chunk, vdupq_n_u8('\\'));
+ uint8x16_t needs_escape = vorrq_u8(too_low_or_dbl_quote, has_backslash);
+ return neon_match_mask(needs_escape);
+}
+
+ALWAYS_INLINE(static) int string_scan_simd_neon(const char **ptr, const char *end, uint64_t *mask)
+{
+ while (*ptr + sizeof(uint8x16_t) <= end) {
+ uint64_t chunk_mask = compute_chunk_mask_neon(*ptr);
+ if (chunk_mask) {
+ *mask = chunk_mask;
+ return 1;
+ }
+ *ptr += sizeof(uint8x16_t);
+ }
+ return 0;
+}
+
+static inline uint8x16x4_t load_uint8x16_4(const unsigned char *table)
+{
+ uint8x16x4_t tab;
+ tab.val[0] = vld1q_u8(table);
+ tab.val[1] = vld1q_u8(table+16);
+ tab.val[2] = vld1q_u8(table+32);
+ tab.val[3] = vld1q_u8(table+48);
+ return tab;
+}
+
+#endif /* ARM Neon Support.*/
+
+#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
+
+#ifdef HAVE_X86INTRIN_H
+#include <x86intrin.h>
+
+#define HAVE_SIMD 1
+#define HAVE_SIMD_SSE2 1
+
+#ifdef HAVE_CPUID_H
+#define FIND_SIMD_IMPLEMENTATION_DEFINED 1
+
+#if defined(__clang__) || defined(__GNUC__)
+#define TARGET_SSE2 __attribute__((target("sse2")))
+#else
+#define TARGET_SSE2
+#endif
+
+#define _mm_cmpge_epu8(a, b) _mm_cmpeq_epi8(_mm_max_epu8(a, b), a)
+#define _mm_cmple_epu8(a, b) _mm_cmpge_epu8(b, a)
+#define _mm_cmpgt_epu8(a, b) _mm_xor_si128(_mm_cmple_epu8(a, b), _mm_set1_epi8(-1))
+#define _mm_cmplt_epu8(a, b) _mm_cmpgt_epu8(b, a)
+
+ALWAYS_INLINE(static) TARGET_SSE2 int compute_chunk_mask_sse2(const char *ptr)
+{
+ __m128i chunk = _mm_loadu_si128((__m128i const*)ptr);
+ // Trick: c < 32 || c == 34 can be factored as c ^ 2 < 33
+ // https://lemire.me/blog/2025/04/13/detect-control-characters-quotes-and-backslashes-efficiently-using-swar/
+ __m128i too_low_or_dbl_quote = _mm_cmplt_epu8(_mm_xor_si128(chunk, _mm_set1_epi8(2)), _mm_set1_epi8(33));
+ __m128i has_backslash = _mm_cmpeq_epi8(chunk, _mm_set1_epi8('\\'));
+ __m128i needs_escape = _mm_or_si128(too_low_or_dbl_quote, has_backslash);
+ return _mm_movemask_epi8(needs_escape);
+}
+
+ALWAYS_INLINE(static) TARGET_SSE2 int string_scan_simd_sse2(const char **ptr, const char *end, int *mask)
+{
+ while (*ptr + sizeof(__m128i) <= end) {
+ int chunk_mask = compute_chunk_mask_sse2(*ptr);
+ if (chunk_mask) {
+ *mask = chunk_mask;
+ return 1;
+ }
+ *ptr += sizeof(__m128i);
+ }
+
+ return 0;
+}
+
+#include <cpuid.h>
+#endif /* HAVE_CPUID_H */
+
+static inline SIMD_Implementation find_simd_implementation(void)
+{
+ // TODO Revisit. I think the SSE version now only uses SSE2 instructions.
+ if (__builtin_cpu_supports("sse2")) {
+ return SIMD_SSE2;
+ }
+
+ return SIMD_NONE;
+}
+
+#endif /* HAVE_X86INTRIN_H */
+#endif /* X86_64 Support */
+
+#endif /* JSON_ENABLE_SIMD */
+
+#ifndef FIND_SIMD_IMPLEMENTATION_DEFINED
+static inline SIMD_Implementation find_simd_implementation(void)
+{
+ return SIMD_NONE;
+}
+#endif
diff --git a/ext/json/vendor/fpconv.c b/ext/json/vendor/fpconv.c
new file mode 100644
index 0000000000..6c9bc2c103
--- /dev/null
+++ b/ext/json/vendor/fpconv.c
@@ -0,0 +1,480 @@
+// Boost Software License - Version 1.0 - August 17th, 2003
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+// The contents of this file is extracted from https://github.com/night-shift/fpconv
+// It was slightly modified to append ".0" to plain floats, for use with the https://github.com/ruby/json package.
+
+#include <stdbool.h>
+#include <string.h>
+#include <stdint.h>
+
+#if JSON_DEBUG
+#include <assert.h>
+#endif
+
+#define npowers 87
+#define steppowers 8
+#define firstpower -348 /* 10 ^ -348 */
+
+#define expmax -32
+#define expmin -60
+
+typedef struct Fp {
+ uint64_t frac;
+ int exp;
+} Fp;
+
+static const Fp powers_ten[] = {
+ { 18054884314459144840U, -1220 }, { 13451937075301367670U, -1193 },
+ { 10022474136428063862U, -1166 }, { 14934650266808366570U, -1140 },
+ { 11127181549972568877U, -1113 }, { 16580792590934885855U, -1087 },
+ { 12353653155963782858U, -1060 }, { 18408377700990114895U, -1034 },
+ { 13715310171984221708U, -1007 }, { 10218702384817765436U, -980 },
+ { 15227053142812498563U, -954 }, { 11345038669416679861U, -927 },
+ { 16905424996341287883U, -901 }, { 12595523146049147757U, -874 },
+ { 9384396036005875287U, -847 }, { 13983839803942852151U, -821 },
+ { 10418772551374772303U, -794 }, { 15525180923007089351U, -768 },
+ { 11567161174868858868U, -741 }, { 17236413322193710309U, -715 },
+ { 12842128665889583758U, -688 }, { 9568131466127621947U, -661 },
+ { 14257626930069360058U, -635 }, { 10622759856335341974U, -608 },
+ { 15829145694278690180U, -582 }, { 11793632577567316726U, -555 },
+ { 17573882009934360870U, -529 }, { 13093562431584567480U, -502 },
+ { 9755464219737475723U, -475 }, { 14536774485912137811U, -449 },
+ { 10830740992659433045U, -422 }, { 16139061738043178685U, -396 },
+ { 12024538023802026127U, -369 }, { 17917957937422433684U, -343 },
+ { 13349918974505688015U, -316 }, { 9946464728195732843U, -289 },
+ { 14821387422376473014U, -263 }, { 11042794154864902060U, -236 },
+ { 16455045573212060422U, -210 }, { 12259964326927110867U, -183 },
+ { 18268770466636286478U, -157 }, { 13611294676837538539U, -130 },
+ { 10141204801825835212U, -103 }, { 15111572745182864684U, -77 },
+ { 11258999068426240000U, -50 }, { 16777216000000000000U, -24 },
+ { 12500000000000000000U, 3 }, { 9313225746154785156U, 30 },
+ { 13877787807814456755U, 56 }, { 10339757656912845936U, 83 },
+ { 15407439555097886824U, 109 }, { 11479437019748901445U, 136 },
+ { 17105694144590052135U, 162 }, { 12744735289059618216U, 189 },
+ { 9495567745759798747U, 216 }, { 14149498560666738074U, 242 },
+ { 10542197943230523224U, 269 }, { 15709099088952724970U, 295 },
+ { 11704190886730495818U, 322 }, { 17440603504673385349U, 348 },
+ { 12994262207056124023U, 375 }, { 9681479787123295682U, 402 },
+ { 14426529090290212157U, 428 }, { 10748601772107342003U, 455 },
+ { 16016664761464807395U, 481 }, { 11933345169920330789U, 508 },
+ { 17782069995880619868U, 534 }, { 13248674568444952270U, 561 },
+ { 9871031767461413346U, 588 }, { 14708983551653345445U, 614 },
+ { 10959046745042015199U, 641 }, { 16330252207878254650U, 667 },
+ { 12166986024289022870U, 694 }, { 18130221999122236476U, 720 },
+ { 13508068024458167312U, 747 }, { 10064294952495520794U, 774 },
+ { 14996968138956309548U, 800 }, { 11173611982879273257U, 827 },
+ { 16649979327439178909U, 853 }, { 12405201291620119593U, 880 },
+ { 9242595204427927429U, 907 }, { 13772540099066387757U, 933 },
+ { 10261342003245940623U, 960 }, { 15290591125556738113U, 986 },
+ { 11392378155556871081U, 1013 }, { 16975966327722178521U, 1039 },
+ { 12648080533535911531U, 1066 }
+};
+
+static Fp find_cachedpow10(int exp, int* k)
+{
+ const double one_log_ten = 0.30102999566398114;
+
+ int approx = (int)(-(exp + npowers) * one_log_ten);
+ int idx = (approx - firstpower) / steppowers;
+
+ while(1) {
+ int current = exp + powers_ten[idx].exp + 64;
+
+ if(current < expmin) {
+ idx++;
+ continue;
+ }
+
+ if(current > expmax) {
+ idx--;
+ continue;
+ }
+
+ *k = (firstpower + idx * steppowers);
+
+ return powers_ten[idx];
+ }
+}
+
+#define fracmask 0x000FFFFFFFFFFFFFU
+#define expmask 0x7FF0000000000000U
+#define hiddenbit 0x0010000000000000U
+#define signmask 0x8000000000000000U
+#define expbias (1023 + 52)
+
+#define absv(n) ((n) < 0 ? -(n) : (n))
+#define minv(a, b) ((a) < (b) ? (a) : (b))
+
+static const uint64_t tens[] = {
+ 10000000000000000000U, 1000000000000000000U, 100000000000000000U,
+ 10000000000000000U, 1000000000000000U, 100000000000000U,
+ 10000000000000U, 1000000000000U, 100000000000U,
+ 10000000000U, 1000000000U, 100000000U,
+ 10000000U, 1000000U, 100000U,
+ 10000U, 1000U, 100U,
+ 10U, 1U
+};
+
+static inline uint64_t get_dbits(double d)
+{
+ union {
+ double dbl;
+ uint64_t i;
+ } dbl_bits = { d };
+
+ return dbl_bits.i;
+}
+
+static Fp build_fp(double d)
+{
+ uint64_t bits = get_dbits(d);
+
+ Fp fp;
+ fp.frac = bits & fracmask;
+ fp.exp = (bits & expmask) >> 52;
+
+ if(fp.exp) {
+ fp.frac += hiddenbit;
+ fp.exp -= expbias;
+
+ } else {
+ fp.exp = -expbias + 1;
+ }
+
+ return fp;
+}
+
+static void normalize(Fp* fp)
+{
+ while ((fp->frac & hiddenbit) == 0) {
+ fp->frac <<= 1;
+ fp->exp--;
+ }
+
+ int shift = 64 - 52 - 1;
+ fp->frac <<= shift;
+ fp->exp -= shift;
+}
+
+static void get_normalized_boundaries(Fp* fp, Fp* lower, Fp* upper)
+{
+ upper->frac = (fp->frac << 1) + 1;
+ upper->exp = fp->exp - 1;
+
+ while ((upper->frac & (hiddenbit << 1)) == 0) {
+ upper->frac <<= 1;
+ upper->exp--;
+ }
+
+ int u_shift = 64 - 52 - 2;
+
+ upper->frac <<= u_shift;
+ upper->exp = upper->exp - u_shift;
+
+
+ int l_shift = fp->frac == hiddenbit ? 2 : 1;
+
+ lower->frac = (fp->frac << l_shift) - 1;
+ lower->exp = fp->exp - l_shift;
+
+
+ lower->frac <<= lower->exp - upper->exp;
+ lower->exp = upper->exp;
+}
+
+static Fp multiply(Fp* a, Fp* b)
+{
+ const uint64_t lomask = 0x00000000FFFFFFFF;
+
+ uint64_t ah_bl = (a->frac >> 32) * (b->frac & lomask);
+ uint64_t al_bh = (a->frac & lomask) * (b->frac >> 32);
+ uint64_t al_bl = (a->frac & lomask) * (b->frac & lomask);
+ uint64_t ah_bh = (a->frac >> 32) * (b->frac >> 32);
+
+ uint64_t tmp = (ah_bl & lomask) + (al_bh & lomask) + (al_bl >> 32);
+ /* round up */
+ tmp += 1U << 31;
+
+ Fp fp = {
+ ah_bh + (ah_bl >> 32) + (al_bh >> 32) + (tmp >> 32),
+ a->exp + b->exp + 64
+ };
+
+ return fp;
+}
+
+static void round_digit(char* digits, int ndigits, uint64_t delta, uint64_t rem, uint64_t kappa, uint64_t frac)
+{
+ while (rem < frac && delta - rem >= kappa &&
+ (rem + kappa < frac || frac - rem > rem + kappa - frac)) {
+
+ digits[ndigits - 1]--;
+ rem += kappa;
+ }
+}
+
+static int generate_digits(Fp* fp, Fp* upper, Fp* lower, char* digits, int* K)
+{
+ uint64_t wfrac = upper->frac - fp->frac;
+ uint64_t delta = upper->frac - lower->frac;
+
+ Fp one;
+ one.frac = 1ULL << -upper->exp;
+ one.exp = upper->exp;
+
+ uint64_t part1 = upper->frac >> -one.exp;
+ uint64_t part2 = upper->frac & (one.frac - 1);
+
+ int idx = 0, kappa = 10;
+ const uint64_t* divp;
+ /* 1000000000 */
+ for(divp = tens + 10; kappa > 0; divp++) {
+
+ uint64_t div = *divp;
+ unsigned digit = (unsigned) (part1 / div);
+
+ if (digit || idx) {
+ digits[idx++] = digit + '0';
+ }
+
+ part1 -= digit * div;
+ kappa--;
+
+ uint64_t tmp = (part1 <<-one.exp) + part2;
+ if (tmp <= delta) {
+ *K += kappa;
+ round_digit(digits, idx, delta, tmp, div << -one.exp, wfrac);
+
+ return idx;
+ }
+ }
+
+ /* 10 */
+ const uint64_t* unit = tens + 18;
+
+ while(true) {
+ part2 *= 10;
+ delta *= 10;
+ kappa--;
+
+ unsigned digit = (unsigned) (part2 >> -one.exp);
+ if (digit || idx) {
+ digits[idx++] = digit + '0';
+ }
+
+ part2 &= one.frac - 1;
+ if (part2 < delta) {
+ *K += kappa;
+ round_digit(digits, idx, delta, part2, one.frac, wfrac * *unit);
+
+ return idx;
+ }
+
+ unit--;
+ }
+}
+
+static int grisu2(double d, char* digits, int* K)
+{
+ Fp w = build_fp(d);
+
+ Fp lower, upper;
+ get_normalized_boundaries(&w, &lower, &upper);
+
+ normalize(&w);
+
+ int k;
+ Fp cp = find_cachedpow10(upper.exp, &k);
+
+ w = multiply(&w, &cp);
+ upper = multiply(&upper, &cp);
+ lower = multiply(&lower, &cp);
+
+ lower.frac++;
+ upper.frac--;
+
+ *K = -k;
+
+ return generate_digits(&w, &upper, &lower, digits, K);
+}
+
+static int emit_digits(char* digits, int ndigits, char* dest, int K, bool neg)
+{
+ int exp = absv(K + ndigits - 1);
+
+ if(K >= 0 && exp < 15) {
+ memcpy(dest, digits, ndigits);
+ memset(dest + ndigits, '0', K);
+
+ /* add a .0 to mark this as a float. */
+ dest[ndigits + K] = '.';
+ dest[ndigits + K + 1] = '0';
+
+ return ndigits + K + 2;
+ }
+
+ /* write decimal w/o scientific notation */
+ if(K < 0 && (K > -7 || exp < 10)) {
+ int offset = ndigits - absv(K);
+ /* fp < 1.0 -> write leading zero */
+ if(offset <= 0) {
+ offset = -offset;
+ dest[0] = '0';
+ dest[1] = '.';
+ memset(dest + 2, '0', offset);
+ memcpy(dest + offset + 2, digits, ndigits);
+
+ return ndigits + 2 + offset;
+
+ /* fp > 1.0 */
+ } else {
+ memcpy(dest, digits, offset);
+ dest[offset] = '.';
+ memcpy(dest + offset + 1, digits + offset, ndigits - offset);
+
+ return ndigits + 1;
+ }
+ }
+
+ /* write decimal w/ scientific notation */
+ ndigits = minv(ndigits, 18 - neg);
+
+ int idx = 0;
+ dest[idx++] = digits[0];
+
+ if(ndigits > 1) {
+ dest[idx++] = '.';
+ memcpy(dest + idx, digits + 1, ndigits - 1);
+ idx += ndigits - 1;
+ }
+
+ dest[idx++] = 'e';
+
+ char sign = K + ndigits - 1 < 0 ? '-' : '+';
+ dest[idx++] = sign;
+
+ int cent = 0;
+
+ if(exp > 99) {
+ cent = exp / 100;
+ dest[idx++] = cent + '0';
+ exp -= cent * 100;
+ }
+ if(exp > 9) {
+ int dec = exp / 10;
+ dest[idx++] = dec + '0';
+ exp -= dec * 10;
+
+ } else if(cent) {
+ dest[idx++] = '0';
+ }
+
+ dest[idx++] = exp % 10 + '0';
+
+ return idx;
+}
+
+static int filter_special(double fp, char* dest)
+{
+ if(fp == 0.0) {
+ dest[0] = '0';
+ dest[1] = '.';
+ dest[2] = '0';
+ return 3;
+ }
+
+ uint64_t bits = get_dbits(fp);
+
+ bool nan = (bits & expmask) == expmask;
+
+ if(!nan) {
+ return 0;
+ }
+
+ if(bits & fracmask) {
+ dest[0] = 'n'; dest[1] = 'a'; dest[2] = 'n';
+
+ } else {
+ dest[0] = 'i'; dest[1] = 'n'; dest[2] = 'f';
+ }
+
+ return 3;
+}
+
+/* Fast and accurate double to string conversion based on Florian Loitsch's
+ * Grisu-algorithm[1].
+ *
+ * Input:
+ * fp -> the double to convert, dest -> destination buffer.
+ * The generated string will never be longer than 32 characters.
+ * Make sure to pass a pointer to at least 32 bytes of memory.
+ * The emitted string will not be null terminated.
+ *
+ *
+ *
+ * Output:
+ * The number of written characters.
+ *
+ * Exemplary usage:
+ *
+ * void print(double d)
+ * {
+ * char buf[28 + 1] // plus null terminator
+ * int str_len = fpconv_dtoa(d, buf);
+ *
+ * buf[str_len] = '\0';
+ * printf("%s", buf);
+ * }
+ *
+ */
+static int fpconv_dtoa(double d, char dest[32])
+{
+ char digits[18];
+
+ int str_len = 0;
+ bool neg = false;
+
+ if(get_dbits(d) & signmask) {
+ dest[0] = '-';
+ str_len++;
+ neg = true;
+ }
+
+ int spec = filter_special(d, dest + str_len);
+
+ if(spec) {
+ return str_len + spec;
+ }
+
+ int K = 0;
+ int ndigits = grisu2(d, digits, &K);
+
+ str_len += emit_digits(digits, ndigits, dest + str_len, K, neg);
+#if JSON_DEBUG
+ assert(str_len <= 32);
+#endif
+
+ return str_len;
+}
diff --git a/ext/json/vendor/jeaiii-ltoa.h b/ext/json/vendor/jeaiii-ltoa.h
new file mode 100644
index 0000000000..ba4f497fc8
--- /dev/null
+++ b/ext/json/vendor/jeaiii-ltoa.h
@@ -0,0 +1,267 @@
+/*
+
+This file is released under the terms of the MIT License. It is based on the
+work of James Edward Anhalt III, with the original license listed below.
+
+MIT License
+
+Copyright (c) 2024,2025 Enrico Thierbach - https://github.com/radiospiel
+Copyright (c) 2022 James Edward Anhalt III - https://github.com/jeaiii/itoa
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+#ifndef JEAIII_TO_TEXT_H_
+#define JEAIII_TO_TEXT_H_
+
+#include <stdint.h>
+
+typedef uint_fast32_t u32_t;
+typedef uint_fast64_t u64_t;
+
+#define u32(x) ((u32_t)(x))
+#define u64(x) ((u64_t)(x))
+
+struct digit_pair
+{
+ char dd[2];
+};
+
+static const struct digit_pair *digits_dd = (struct digit_pair *)(
+ "00" "01" "02" "03" "04" "05" "06" "07" "08" "09"
+ "10" "11" "12" "13" "14" "15" "16" "17" "18" "19"
+ "20" "21" "22" "23" "24" "25" "26" "27" "28" "29"
+ "30" "31" "32" "33" "34" "35" "36" "37" "38" "39"
+ "40" "41" "42" "43" "44" "45" "46" "47" "48" "49"
+ "50" "51" "52" "53" "54" "55" "56" "57" "58" "59"
+ "60" "61" "62" "63" "64" "65" "66" "67" "68" "69"
+ "70" "71" "72" "73" "74" "75" "76" "77" "78" "79"
+ "80" "81" "82" "83" "84" "85" "86" "87" "88" "89"
+ "90" "91" "92" "93" "94" "95" "96" "97" "98" "99"
+);
+
+static const struct digit_pair *digits_fd = (struct digit_pair *)(
+ "0_" "1_" "2_" "3_" "4_" "5_" "6_" "7_" "8_" "9_"
+ "10" "11" "12" "13" "14" "15" "16" "17" "18" "19"
+ "20" "21" "22" "23" "24" "25" "26" "27" "28" "29"
+ "30" "31" "32" "33" "34" "35" "36" "37" "38" "39"
+ "40" "41" "42" "43" "44" "45" "46" "47" "48" "49"
+ "50" "51" "52" "53" "54" "55" "56" "57" "58" "59"
+ "60" "61" "62" "63" "64" "65" "66" "67" "68" "69"
+ "70" "71" "72" "73" "74" "75" "76" "77" "78" "79"
+ "80" "81" "82" "83" "84" "85" "86" "87" "88" "89"
+ "90" "91" "92" "93" "94" "95" "96" "97" "98" "99"
+);
+
+static const u64_t mask24 = (u64(1) << 24) - 1;
+static const u64_t mask32 = (u64(1) << 32) - 1;
+static const u64_t mask57 = (u64(1) << 57) - 1;
+
+#define COPY(buffer, digits) memcpy(buffer, &(digits), sizeof(struct digit_pair))
+
+static char *
+jeaiii_ultoa(char *b, u64_t n)
+{
+ if (n < u32(1e2)) {
+ COPY(b, digits_fd[n]);
+ return n < 10 ? b + 1 : b + 2;
+ }
+
+ if (n < u32(1e6)) {
+ if (n < u32(1e4)) {
+ u32_t f0 = u32((10 * (1 << 24) / 1e3 + 1) * n);
+ COPY(b, digits_fd[f0 >> 24]);
+
+ b -= n < u32(1e3);
+ u32_t f2 = (f0 & mask24) * 100;
+ COPY(b + 2, digits_dd[f2 >> 24]);
+
+ return b + 4;
+ }
+
+ u64_t f0 = u64(10 * (1ull << 32ull)/ 1e5 + 1) * n;
+ COPY(b, digits_fd[f0 >> 32]);
+
+ b -= n < u32(1e5);
+ u64_t f2 = (f0 & mask32) * 100;
+ COPY(b + 2, digits_dd[f2 >> 32]);
+
+ u64_t f4 = (f2 & mask32) * 100;
+ COPY(b + 4, digits_dd[f4 >> 32]);
+ return b + 6;
+ }
+
+ if (n < u64(1ull << 32ull)) {
+ if (n < u32(1e8)) {
+ u64_t f0 = u64(10 * (1ull << 48ull) / 1e7 + 1) * n >> 16;
+ COPY(b, digits_fd[f0 >> 32]);
+
+ b -= n < u32(1e7);
+ u64_t f2 = (f0 & mask32) * 100;
+ COPY(b + 2, digits_dd[f2 >> 32]);
+
+ u64_t f4 = (f2 & mask32) * 100;
+ COPY(b + 4, digits_dd[f4 >> 32]);
+
+ u64_t f6 = (f4 & mask32) * 100;
+ COPY(b + 6, digits_dd[f6 >> 32]);
+
+ return b + 8;
+ }
+
+ u64_t f0 = u64(10 * (1ull << 57ull) / 1e9 + 1) * n;
+ COPY(b, digits_fd[f0 >> 57]);
+
+ b -= n < u32(1e9);
+ u64_t f2 = (f0 & mask57) * 100;
+ COPY(b + 2, digits_dd[f2 >> 57]);
+
+ u64_t f4 = (f2 & mask57) * 100;
+ COPY(b + 4, digits_dd[f4 >> 57]);
+
+ u64_t f6 = (f4 & mask57) * 100;
+ COPY(b + 6, digits_dd[f6 >> 57]);
+
+ u64_t f8 = (f6 & mask57) * 100;
+ COPY(b + 8, digits_dd[f8 >> 57]);
+
+ return b + 10;
+ }
+
+ // if we get here U must be u64 but some compilers don't know that, so reassign n to a u64 to avoid warnings
+ u32_t z = n % u32(1e8);
+ u64_t u = n / u32(1e8);
+
+ if (u < u32(1e2)) {
+ // u can't be 1 digit (if u < 10 it would have been handled above as a 9 digit 32bit number)
+ COPY(b, digits_dd[u]);
+ b += 2;
+ }
+ else if (u < u32(1e6)) {
+ if (u < u32(1e4)) {
+ u32_t f0 = u32((10 * (1 << 24) / 1e3 + 1) * u);
+ COPY(b, digits_fd[f0 >> 24]);
+
+ b -= u < u32(1e3);
+ u32_t f2 = (f0 & mask24) * 100;
+ COPY(b + 2, digits_dd[f2 >> 24]);
+ b += 4;
+ }
+ else {
+ u64_t f0 = u64(10 * (1ull << 32ull) / 1e5 + 1) * u;
+ COPY(b, digits_fd[f0 >> 32]);
+
+ b -= u < u32(1e5);
+ u64_t f2 = (f0 & mask32) * 100;
+ COPY(b + 2, digits_dd[f2 >> 32]);
+
+ u64_t f4 = (f2 & mask32) * 100;
+ COPY(b + 4, digits_dd[f4 >> 32]);
+ b += 6;
+ }
+ }
+ else if (u < u32(1e8)) {
+ u64_t f0 = u64(10 * (1ull << 48ull) / 1e7 + 1) * u >> 16;
+ COPY(b, digits_fd[f0 >> 32]);
+
+ b -= u < u32(1e7);
+ u64_t f2 = (f0 & mask32) * 100;
+ COPY(b + 2, digits_dd[f2 >> 32]);
+
+ u64_t f4 = (f2 & mask32) * 100;
+ COPY(b + 4, digits_dd[f4 >> 32]);
+
+ u64_t f6 = (f4 & mask32) * 100;
+ COPY(b + 6, digits_dd[f6 >> 32]);
+
+ b += 8;
+ }
+ else if (u < u64(1ull << 32ull)) {
+ u64_t f0 = u64(10 * (1ull << 57ull) / 1e9 + 1) * u;
+ COPY(b, digits_fd[f0 >> 57]);
+
+ b -= u < u32(1e9);
+ u64_t f2 = (f0 & mask57) * 100;
+ COPY(b + 2, digits_dd[f2 >> 57]);
+
+ u64_t f4 = (f2 & mask57) * 100;
+ COPY(b + 4, digits_dd[f4 >> 57]);
+
+ u64_t f6 = (f4 & mask57) * 100;
+ COPY(b + 6, digits_dd[f6 >> 57]);
+
+ u64_t f8 = (f6 & mask57) * 100;
+ COPY(b + 8, digits_dd[f8 >> 57]);
+ b += 10;
+ }
+ else {
+ u32_t y = u % u32(1e8);
+ u /= u32(1e8);
+
+ // u is 2, 3, or 4 digits (if u < 10 it would have been handled above)
+ if (u < u32(1e2)) {
+ COPY(b, digits_dd[u]);
+ b += 2;
+ }
+ else {
+ u32_t f0 = u32((10 * (1 << 24) / 1e3 + 1) * u);
+ COPY(b, digits_fd[f0 >> 24]);
+
+ b -= u < u32(1e3);
+ u32_t f2 = (f0 & mask24) * 100;
+ COPY(b + 2, digits_dd[f2 >> 24]);
+
+ b += 4;
+ }
+ // do 8 digits
+ u64_t f0 = (u64((1ull << 48ull) / 1e6 + 1) * y >> 16) + 1;
+ COPY(b, digits_dd[f0 >> 32]);
+
+ u64_t f2 = (f0 & mask32) * 100;
+ COPY(b + 2, digits_dd[f2 >> 32]);
+
+ u64_t f4 = (f2 & mask32) * 100;
+ COPY(b + 4, digits_dd[f4 >> 32]);
+
+ u64_t f6 = (f4 & mask32) * 100;
+ COPY(b + 6, digits_dd[f6 >> 32]);
+ b += 8;
+ }
+
+ // do 8 digits
+ u64_t f0 = (u64((1ull << 48ull) / 1e6 + 1) * z >> 16) + 1;
+ COPY(b, digits_dd[f0 >> 32]);
+
+ u64_t f2 = (f0 & mask32) * 100;
+ COPY(b + 2, digits_dd[f2 >> 32]);
+
+ u64_t f4 = (f2 & mask32) * 100;
+ COPY(b + 4, digits_dd[f4 >> 32]);
+
+ u64_t f6 = (f4 & mask32) * 100;
+ COPY(b + 6, digits_dd[f6 >> 32]);
+
+ return b + 8;
+}
+
+#undef u32
+#undef u64
+#undef COPY
+
+#endif // JEAIII_TO_TEXT_H_
diff --git a/ext/json/vendor/ryu.h b/ext/json/vendor/ryu.h
new file mode 100644
index 0000000000..f06ec814b4
--- /dev/null
+++ b/ext/json/vendor/ryu.h
@@ -0,0 +1,819 @@
+// Copyright 2018 Ulf Adams
+//
+// The contents of this file may be used under the terms of the Apache License,
+// Version 2.0.
+//
+// Alternatively, the contents of this file may be used under the terms of
+// the Boost Software License, Version 1.0.
+//
+// Unless required by applicable law or agreed to in writing, this software
+// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.
+//
+// ---
+//
+// Apache License
+// Version 2.0, January 2004
+// http://www.apache.org/licenses/
+//
+// TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+//
+// 1. Definitions.
+//
+// "License" shall mean the terms and conditions for use, reproduction,
+// and distribution as defined by Sections 1 through 9 of this document.
+//
+// "Licensor" shall mean the copyright owner or entity authorized by
+// the copyright owner that is granting the License.
+//
+// "Legal Entity" shall mean the union of the acting entity and all
+// other entities that control, are controlled by, or are under common
+// control with that entity. For the purposes of this definition,
+// "control" means (i) the power, direct or indirect, to cause the
+// direction or management of such entity, whether by contract or
+// otherwise, or (ii) ownership of fifty percent (50%) or more of the
+// outstanding shares, or (iii) beneficial ownership of such entity.
+//
+// "You" (or "Your") shall mean an individual or Legal Entity
+// exercising permissions granted by this License.
+//
+// "Source" form shall mean the preferred form for making modifications,
+// including but not limited to software source code, documentation
+// source, and configuration files.
+//
+// "Object" form shall mean any form resulting from mechanical
+// transformation or translation of a Source form, including but
+// not limited to compiled object code, generated documentation,
+// and conversions to other media types.
+//
+// "Work" shall mean the work of authorship, whether in Source or
+// Object form, made available under the License, as indicated by a
+// copyright notice that is included in or attached to the work
+// (an example is provided in the Appendix below).
+//
+// "Derivative Works" shall mean any work, whether in Source or Object
+// form, that is based on (or derived from) the Work and for which the
+// editorial revisions, annotations, elaborations, or other modifications
+// represent, as a whole, an original work of authorship. For the purposes
+// of this License, Derivative Works shall not include works that remain
+// separable from, or merely link (or bind by name) to the interfaces of,
+// the Work and Derivative Works thereof.
+//
+// "Contribution" shall mean any work of authorship, including
+// the original version of the Work and any modifications or additions
+// to that Work or Derivative Works thereof, that is intentionally
+// submitted to Licensor for inclusion in the Work by the copyright owner
+// or by an individual or Legal Entity authorized to submit on behalf of
+// the copyright owner. For the purposes of this definition, "submitted"
+// means any form of electronic, verbal, or written communication sent
+// to the Licensor or its representatives, including but not limited to
+// communication on electronic mailing lists, source code control systems,
+// and issue tracking systems that are managed by, or on behalf of, the
+// Licensor for the purpose of discussing and improving the Work, but
+// excluding communication that is conspicuously marked or otherwise
+// designated in writing by the copyright owner as "Not a Contribution."
+//
+// "Contributor" shall mean Licensor and any individual or Legal Entity
+// on behalf of whom a Contribution has been received by Licensor and
+// subsequently incorporated within the Work.
+//
+// 2. Grant of Copyright License. Subject to the terms and conditions of
+// this License, each Contributor hereby grants to You a perpetual,
+// worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+// copyright license to reproduce, prepare Derivative Works of,
+// publicly display, publicly perform, sublicense, and distribute the
+// Work and such Derivative Works in Source or Object form.
+//
+// 3. Grant of Patent License. Subject to the terms and conditions of
+// this License, each Contributor hereby grants to You a perpetual,
+// worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+// (except as stated in this section) patent license to make, have made,
+// use, offer to sell, sell, import, and otherwise transfer the Work,
+// where such license applies only to those patent claims licensable
+// by such Contributor that are necessarily infringed by their
+// Contribution(s) alone or by combination of their Contribution(s)
+// with the Work to which such Contribution(s) was submitted. If You
+// institute patent litigation against any entity (including a
+// cross-claim or counterclaim in a lawsuit) alleging that the Work
+// or a Contribution incorporated within the Work constitutes direct
+// or contributory patent infringement, then any patent licenses
+// granted to You under this License for that Work shall terminate
+// as of the date such litigation is filed.
+//
+// 4. Redistribution. You may reproduce and distribute copies of the
+// Work or Derivative Works thereof in any medium, with or without
+// modifications, and in Source or Object form, provided that You
+// meet the following conditions:
+//
+// (a) You must give any other recipients of the Work or
+// Derivative Works a copy of this License; and
+//
+// (b) You must cause any modified files to carry prominent notices
+// stating that You changed the files; and
+//
+// (c) You must retain, in the Source form of any Derivative Works
+// that You distribute, all copyright, patent, trademark, and
+// attribution notices from the Source form of the Work,
+// excluding those notices that do not pertain to any part of
+// the Derivative Works; and
+//
+// (d) If the Work includes a "NOTICE" text file as part of its
+// distribution, then any Derivative Works that You distribute must
+// include a readable copy of the attribution notices contained
+// within such NOTICE file, excluding those notices that do not
+// pertain to any part of the Derivative Works, in at least one
+// of the following places: within a NOTICE text file distributed
+// as part of the Derivative Works; within the Source form or
+// documentation, if provided along with the Derivative Works; or,
+// within a display generated by the Derivative Works, if and
+// wherever such third-party notices normally appear. The contents
+// of the NOTICE file are for informational purposes only and
+// do not modify the License. You may add Your own attribution
+// notices within Derivative Works that You distribute, alongside
+// or as an addendum to the NOTICE text from the Work, provided
+// that such additional attribution notices cannot be construed
+// as modifying the License.
+//
+// You may add Your own copyright statement to Your modifications and
+// may provide additional or different license terms and conditions
+// for use, reproduction, or distribution of Your modifications, or
+// for any such Derivative Works as a whole, provided Your use,
+// reproduction, and distribution of the Work otherwise complies with
+// the conditions stated in this License.
+//
+// 5. Submission of Contributions. Unless You explicitly state otherwise,
+// any Contribution intentionally submitted for inclusion in the Work
+// by You to the Licensor shall be under the terms and conditions of
+// this License, without any additional terms or conditions.
+// Notwithstanding the above, nothing herein shall supersede or modify
+// the terms of any separate license agreement you may have executed
+// with Licensor regarding such Contributions.
+//
+// 6. Trademarks. This License does not grant permission to use the trade
+// names, trademarks, service marks, or product names of the Licensor,
+// except as required for reasonable and customary use in describing the
+// origin of the Work and reproducing the content of the NOTICE file.
+//
+// 7. Disclaimer of Warranty. Unless required by applicable law or
+// agreed to in writing, Licensor provides the Work (and each
+// Contributor provides its Contributions) on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+// implied, including, without limitation, any warranties or conditions
+// of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+// PARTICULAR PURPOSE. You are solely responsible for determining the
+// appropriateness of using or redistributing the Work and assume any
+// risks associated with Your exercise of permissions under this License.
+//
+// 8. Limitation of Liability. In no event and under no legal theory,
+// whether in tort (including negligence), contract, or otherwise,
+// unless required by applicable law (such as deliberate and grossly
+// negligent acts) or agreed to in writing, shall any Contributor be
+// liable to You for damages, including any direct, indirect, special,
+// incidental, or consequential damages of any character arising as a
+// result of this License or out of the use or inability to use the
+// Work (including but not limited to damages for loss of goodwill,
+// work stoppage, computer failure or malfunction, or any and all
+// other commercial damages or losses), even if such Contributor
+// has been advised of the possibility of such damages.
+//
+// 9. Accepting Warranty or Additional Liability. While redistributing
+// the Work or Derivative Works thereof, You may choose to offer,
+// and charge a fee for, acceptance of support, warranty, indemnity,
+// or other liability obligations and/or rights consistent with this
+// License. However, in accepting such obligations, You may act only
+// on Your own behalf and on Your sole responsibility, not on behalf
+// of any other Contributor, and only if You agree to indemnify,
+// defend, and hold each Contributor harmless for any liability
+// incurred by, or claims asserted against, such Contributor by reason
+// of your accepting any such warranty or additional liability.
+//
+// END OF TERMS AND CONDITIONS
+//
+// APPENDIX: How to apply the Apache License to your work.
+//
+// To apply the Apache License to your work, attach the following
+// boilerplate notice, with the fields enclosed by brackets "[]"
+// replaced with your own identifying information. (Don't include
+// the brackets!) The text should be enclosed in the appropriate
+// comment syntax for the file format. We also recommend that a
+// file or class name and description of purpose be included on the
+// same "printed page" as the copyright notice for easier
+// identification within third-party archives.
+//
+// Copyright [yyyy] [name of copyright owner]
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+// ---
+//
+// Boost Software License - Version 1.0 - August 17th, 2003
+//
+// Permission is hereby granted, free of charge, to any person or organization
+// obtaining a copy of the software and accompanying documentation covered by
+// this license (the "Software") to use, reproduce, display, distribute,
+// execute, and transmit the Software, and to prepare derivative works of the
+// Software, and to permit third-parties to whom the Software is furnished to
+// do so, all subject to the following:
+//
+// The copyright notices in the Software and this entire statement, including
+// the above license grant, this restriction and the following disclaimer,
+// must be included in all copies of the Software, in whole or in part, and
+// all derivative works of the Software, unless such copies or derivative
+// works are solely in the form of machine-executable object code generated by
+// a source language processor.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+//
+// ---
+// Minimal Ryu implementation adapted for Ruby JSON gem by Josef Šimánek
+// Optimized for pre-extracted mantissa/exponent from JSON parsing
+// This is a stripped-down version containing only what's needed for
+// converting decimal mantissa+exponent to IEEE 754 double precision.
+
+#ifndef RYU_H
+#define RYU_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+
+// Detect __builtin_clzll availability (for floor_log2)
+// Note: MSVC doesn't have __builtin_clzll, so we provide a fallback
+#ifdef __clang__
+ #if __has_builtin(__builtin_clzll)
+ #define RYU_HAVE_BUILTIN_CLZLL 1
+ #else
+ #define RYU_HAVE_BUILTIN_CLZLL 0
+ #endif
+#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
+ #define RYU_HAVE_BUILTIN_CLZLL 1
+#else
+ #define RYU_HAVE_BUILTIN_CLZLL 0
+#endif
+
+// Count leading zeros (for floor_log2)
+static inline uint32_t ryu_leading_zeros64(uint64_t input)
+{
+#if RYU_HAVE_BUILTIN_CLZLL
+ return __builtin_clzll(input);
+#else
+ // Fallback: binary search for the highest set bit
+ // This works on MSVC and other compilers without __builtin_clzll
+ if (input == 0) return 64;
+ uint32_t n = 0;
+ if (input <= 0x00000000FFFFFFFFULL) { n += 32; input <<= 32; }
+ if (input <= 0x0000FFFFFFFFFFFFULL) { n += 16; input <<= 16; }
+ if (input <= 0x00FFFFFFFFFFFFFFULL) { n += 8; input <<= 8; }
+ if (input <= 0x0FFFFFFFFFFFFFFFULL) { n += 4; input <<= 4; }
+ if (input <= 0x3FFFFFFFFFFFFFFFULL) { n += 2; input <<= 2; }
+ if (input <= 0x7FFFFFFFFFFFFFFFULL) { n += 1; }
+ return n;
+#endif
+}
+
+// These tables are generated by PrintDoubleLookupTable.
+#define DOUBLE_POW5_INV_BITCOUNT 125
+#define DOUBLE_POW5_BITCOUNT 125
+
+#define DOUBLE_POW5_INV_TABLE_SIZE 342
+#define DOUBLE_POW5_TABLE_SIZE 326
+
+static const uint64_t DOUBLE_POW5_INV_SPLIT[DOUBLE_POW5_INV_TABLE_SIZE][2] = {
+ { 1u, 2305843009213693952u }, { 11068046444225730970u, 1844674407370955161u },
+ { 5165088340638674453u, 1475739525896764129u }, { 7821419487252849886u, 1180591620717411303u },
+ { 8824922364862649494u, 1888946593147858085u }, { 7059937891890119595u, 1511157274518286468u },
+ { 13026647942995916322u, 1208925819614629174u }, { 9774590264567735146u, 1934281311383406679u },
+ { 11509021026396098440u, 1547425049106725343u }, { 16585914450600699399u, 1237940039285380274u },
+ { 15469416676735388068u, 1980704062856608439u }, { 16064882156130220778u, 1584563250285286751u },
+ { 9162556910162266299u, 1267650600228229401u }, { 7281393426775805432u, 2028240960365167042u },
+ { 16893161185646375315u, 1622592768292133633u }, { 2446482504291369283u, 1298074214633706907u },
+ { 7603720821608101175u, 2076918743413931051u }, { 2393627842544570617u, 1661534994731144841u },
+ { 16672297533003297786u, 1329227995784915872u }, { 11918280793837635165u, 2126764793255865396u },
+ { 5845275820328197809u, 1701411834604692317u }, { 15744267100488289217u, 1361129467683753853u },
+ { 3054734472329800808u, 2177807148294006166u }, { 17201182836831481939u, 1742245718635204932u },
+ { 6382248639981364905u, 1393796574908163946u }, { 2832900194486363201u, 2230074519853062314u },
+ { 5955668970331000884u, 1784059615882449851u }, { 1075186361522890384u, 1427247692705959881u },
+ { 12788344622662355584u, 2283596308329535809u }, { 13920024512871794791u, 1826877046663628647u },
+ { 3757321980813615186u, 1461501637330902918u }, { 10384555214134712795u, 1169201309864722334u },
+ { 5547241898389809503u, 1870722095783555735u }, { 4437793518711847602u, 1496577676626844588u },
+ { 10928932444453298728u, 1197262141301475670u }, { 17486291911125277965u, 1915619426082361072u },
+ { 6610335899416401726u, 1532495540865888858u }, { 12666966349016942027u, 1225996432692711086u },
+ { 12888448528943286597u, 1961594292308337738u }, { 17689456452638449924u, 1569275433846670190u },
+ { 14151565162110759939u, 1255420347077336152u }, { 7885109000409574610u, 2008672555323737844u },
+ { 9997436015069570011u, 1606938044258990275u }, { 7997948812055656009u, 1285550435407192220u },
+ { 12796718099289049614u, 2056880696651507552u }, { 2858676849947419045u, 1645504557321206042u },
+ { 13354987924183666206u, 1316403645856964833u }, { 17678631863951955605u, 2106245833371143733u },
+ { 3074859046935833515u, 1684996666696914987u }, { 13527933681774397782u, 1347997333357531989u },
+ { 10576647446613305481u, 2156795733372051183u }, { 15840015586774465031u, 1725436586697640946u },
+ { 8982663654677661702u, 1380349269358112757u }, { 18061610662226169046u, 2208558830972980411u },
+ { 10759939715039024913u, 1766847064778384329u }, { 12297300586773130254u, 1413477651822707463u },
+ { 15986332124095098083u, 2261564242916331941u }, { 9099716884534168143u, 1809251394333065553u },
+ { 14658471137111155161u, 1447401115466452442u }, { 4348079280205103483u, 1157920892373161954u },
+ { 14335624477811986218u, 1852673427797059126u }, { 7779150767507678651u, 1482138742237647301u },
+ { 2533971799264232598u, 1185710993790117841u }, { 15122401323048503126u, 1897137590064188545u },
+ { 12097921058438802501u, 1517710072051350836u }, { 5988988032009131678u, 1214168057641080669u },
+ { 16961078480698431330u, 1942668892225729070u }, { 13568862784558745064u, 1554135113780583256u },
+ { 7165741412905085728u, 1243308091024466605u }, { 11465186260648137165u, 1989292945639146568u },
+ { 16550846638002330379u, 1591434356511317254u }, { 16930026125143774626u, 1273147485209053803u },
+ { 4951948911778577463u, 2037035976334486086u }, { 272210314680951647u, 1629628781067588869u },
+ { 3907117066486671641u, 1303703024854071095u }, { 6251387306378674625u, 2085924839766513752u },
+ { 16069156289328670670u, 1668739871813211001u }, { 9165976216721026213u, 1334991897450568801u },
+ { 7286864317269821294u, 2135987035920910082u }, { 16897537898041588005u, 1708789628736728065u },
+ { 13518030318433270404u, 1367031702989382452u }, { 6871453250525591353u, 2187250724783011924u },
+ { 9186511415162383406u, 1749800579826409539u }, { 11038557946871817048u, 1399840463861127631u },
+ { 10282995085511086630u, 2239744742177804210u }, { 8226396068408869304u, 1791795793742243368u },
+ { 13959814484210916090u, 1433436634993794694u }, { 11267656730511734774u, 2293498615990071511u },
+ { 5324776569667477496u, 1834798892792057209u }, { 7949170070475892320u, 1467839114233645767u },
+ { 17427382500606444826u, 1174271291386916613u }, { 5747719112518849781u, 1878834066219066582u },
+ { 15666221734240810795u, 1503067252975253265u }, { 12532977387392648636u, 1202453802380202612u },
+ { 5295368560860596524u, 1923926083808324180u }, { 4236294848688477220u, 1539140867046659344u },
+ { 7078384693692692099u, 1231312693637327475u }, { 11325415509908307358u, 1970100309819723960u },
+ { 9060332407926645887u, 1576080247855779168u }, { 14626963555825137356u, 1260864198284623334u },
+ { 12335095245094488799u, 2017382717255397335u }, { 9868076196075591040u, 1613906173804317868u },
+ { 15273158586344293478u, 1291124939043454294u }, { 13369007293925138595u, 2065799902469526871u },
+ { 7005857020398200553u, 1652639921975621497u }, { 16672732060544291412u, 1322111937580497197u },
+ { 11918976037903224966u, 2115379100128795516u }, { 5845832015580669650u, 1692303280103036413u },
+ { 12055363241948356366u, 1353842624082429130u }, { 841837113407818570u, 2166148198531886609u },
+ { 4362818505468165179u, 1732918558825509287u }, { 14558301248600263113u, 1386334847060407429u },
+ { 12225235553534690011u, 2218135755296651887u }, { 2401490813343931363u, 1774508604237321510u },
+ { 1921192650675145090u, 1419606883389857208u }, { 17831303500047873437u, 2271371013423771532u },
+ { 6886345170554478103u, 1817096810739017226u }, { 1819727321701672159u, 1453677448591213781u },
+ { 16213177116328979020u, 1162941958872971024u }, { 14873036941900635463u, 1860707134196753639u },
+ { 15587778368262418694u, 1488565707357402911u }, { 8780873879868024632u, 1190852565885922329u },
+ { 2981351763563108441u, 1905364105417475727u }, { 13453127855076217722u, 1524291284333980581u },
+ { 7073153469319063855u, 1219433027467184465u }, { 11317045550910502167u, 1951092843947495144u },
+ { 12742985255470312057u, 1560874275157996115u }, { 10194388204376249646u, 1248699420126396892u },
+ { 1553625868034358140u, 1997919072202235028u }, { 8621598323911307159u, 1598335257761788022u },
+ { 17965325103354776697u, 1278668206209430417u }, { 13987124906400001422u, 2045869129935088668u },
+ { 121653480894270168u, 1636695303948070935u }, { 97322784715416134u, 1309356243158456748u },
+ { 14913111714512307107u, 2094969989053530796u }, { 8241140556867935363u, 1675975991242824637u },
+ { 17660958889720079260u, 1340780792994259709u }, { 17189487779326395846u, 2145249268790815535u },
+ { 13751590223461116677u, 1716199415032652428u }, { 18379969808252713988u, 1372959532026121942u },
+ { 14650556434236701088u, 2196735251241795108u }, { 652398703163629901u, 1757388200993436087u },
+ { 11589965406756634890u, 1405910560794748869u }, { 7475898206584884855u, 2249456897271598191u },
+ { 2291369750525997561u, 1799565517817278553u }, { 9211793429904618695u, 1439652414253822842u },
+ { 18428218302589300235u, 2303443862806116547u }, { 7363877012587619542u, 1842755090244893238u },
+ { 13269799239553916280u, 1474204072195914590u }, { 10615839391643133024u, 1179363257756731672u },
+ { 2227947767661371545u, 1886981212410770676u }, { 16539753473096738529u, 1509584969928616540u },
+ { 13231802778477390823u, 1207667975942893232u }, { 6413489186596184024u, 1932268761508629172u },
+ { 16198837793502678189u, 1545815009206903337u }, { 5580372605318321905u, 1236652007365522670u },
+ { 8928596168509315048u, 1978643211784836272u }, { 18210923379033183008u, 1582914569427869017u },
+ { 7190041073742725760u, 1266331655542295214u }, { 436019273762630246u, 2026130648867672343u },
+ { 7727513048493924843u, 1620904519094137874u }, { 9871359253537050198u, 1296723615275310299u },
+ { 4726128361433549347u, 2074757784440496479u }, { 7470251503888749801u, 1659806227552397183u },
+ { 13354898832594820487u, 1327844982041917746u }, { 13989140502667892133u, 2124551971267068394u },
+ { 14880661216876224029u, 1699641577013654715u }, { 11904528973500979224u, 1359713261610923772u },
+ { 4289851098633925465u, 2175541218577478036u }, { 18189276137874781665u, 1740432974861982428u },
+ { 3483374466074094362u, 1392346379889585943u }, { 1884050330976640656u, 2227754207823337509u },
+ { 5196589079523222848u, 1782203366258670007u }, { 15225317707844309248u, 1425762693006936005u },
+ { 5913764258841343181u, 2281220308811097609u }, { 8420360221814984868u, 1824976247048878087u },
+ { 17804334621677718864u, 1459980997639102469u }, { 17932816512084085415u, 1167984798111281975u },
+ { 10245762345624985047u, 1868775676978051161u }, { 4507261061758077715u, 1495020541582440929u },
+ { 7295157664148372495u, 1196016433265952743u }, { 7982903447895485668u, 1913626293225524389u },
+ { 10075671573058298858u, 1530901034580419511u }, { 4371188443704728763u, 1224720827664335609u },
+ { 14372599139411386667u, 1959553324262936974u }, { 15187428126271019657u, 1567642659410349579u },
+ { 15839291315758726049u, 1254114127528279663u }, { 3206773216762499739u, 2006582604045247462u },
+ { 13633465017635730761u, 1605266083236197969u }, { 14596120828850494932u, 1284212866588958375u },
+ { 4907049252451240275u, 2054740586542333401u }, { 236290587219081897u, 1643792469233866721u },
+ { 14946427728742906810u, 1315033975387093376u }, { 16535586736504830250u, 2104054360619349402u },
+ { 5849771759720043554u, 1683243488495479522u }, { 15747863852001765813u, 1346594790796383617u },
+ { 10439186904235184007u, 2154551665274213788u }, { 15730047152871967852u, 1723641332219371030u },
+ { 12584037722297574282u, 1378913065775496824u }, { 9066413911450387881u, 2206260905240794919u },
+ { 10942479943902220628u, 1765008724192635935u }, { 8753983955121776503u, 1412006979354108748u },
+ { 10317025513452932081u, 2259211166966573997u }, { 874922781278525018u, 1807368933573259198u },
+ { 8078635854506640661u, 1445895146858607358u }, { 13841606313089133175u, 1156716117486885886u },
+ { 14767872471458792434u, 1850745787979017418u }, { 746251532941302978u, 1480596630383213935u },
+ { 597001226353042382u, 1184477304306571148u }, { 15712597221132509104u, 1895163686890513836u },
+ { 8880728962164096960u, 1516130949512411069u }, { 10793931984473187891u, 1212904759609928855u },
+ { 17270291175157100626u, 1940647615375886168u }, { 2748186495899949531u, 1552518092300708935u },
+ { 2198549196719959625u, 1242014473840567148u }, { 18275073973719576693u, 1987223158144907436u },
+ { 10930710364233751031u, 1589778526515925949u }, { 12433917106128911148u, 1271822821212740759u },
+ { 8826220925580526867u, 2034916513940385215u }, { 7060976740464421494u, 1627933211152308172u },
+ { 16716827836597268165u, 1302346568921846537u }, { 11989529279587987770u, 2083754510274954460u },
+ { 9591623423670390216u, 1667003608219963568u }, { 15051996368420132820u, 1333602886575970854u },
+ { 13015147745246481542u, 2133764618521553367u }, { 3033420566713364587u, 1707011694817242694u },
+ { 6116085268112601993u, 1365609355853794155u }, { 9785736428980163188u, 2184974969366070648u },
+ { 15207286772667951197u, 1747979975492856518u }, { 1097782973908629988u, 1398383980394285215u },
+ { 1756452758253807981u, 2237414368630856344u }, { 5094511021344956708u, 1789931494904685075u },
+ { 4075608817075965366u, 1431945195923748060u }, { 6520974107321544586u, 2291112313477996896u },
+ { 1527430471115325346u, 1832889850782397517u }, { 12289990821117991246u, 1466311880625918013u },
+ { 17210690286378213644u, 1173049504500734410u }, { 9090360384495590213u, 1876879207201175057u },
+ { 18340334751822203140u, 1501503365760940045u }, { 14672267801457762512u, 1201202692608752036u },
+ { 16096930852848599373u, 1921924308174003258u }, { 1809498238053148529u, 1537539446539202607u },
+ { 12515645034668249793u, 1230031557231362085u }, { 1578287981759648052u, 1968050491570179337u },
+ { 12330676829633449412u, 1574440393256143469u }, { 13553890278448669853u, 1259552314604914775u },
+ { 3239480371808320148u, 2015283703367863641u }, { 17348979556414297411u, 1612226962694290912u },
+ { 6500486015647617283u, 1289781570155432730u }, { 10400777625036187652u, 2063650512248692368u },
+ { 15699319729512770768u, 1650920409798953894u }, { 16248804598352126938u, 1320736327839163115u },
+ { 7551343283653851484u, 2113178124542660985u }, { 6041074626923081187u, 1690542499634128788u },
+ { 12211557331022285596u, 1352433999707303030u }, { 1091747655926105338u, 2163894399531684849u },
+ { 4562746939482794594u, 1731115519625347879u }, { 7339546366328145998u, 1384892415700278303u },
+ { 8053925371383123274u, 2215827865120445285u }, { 6443140297106498619u, 1772662292096356228u },
+ { 12533209867169019542u, 1418129833677084982u }, { 5295740528502789974u, 2269007733883335972u },
+ { 15304638867027962949u, 1815206187106668777u }, { 4865013464138549713u, 1452164949685335022u },
+ { 14960057215536570740u, 1161731959748268017u }, { 9178696285890871890u, 1858771135597228828u },
+ { 14721654658196518159u, 1487016908477783062u }, { 4398626097073393881u, 1189613526782226450u },
+ { 7037801755317430209u, 1903381642851562320u }, { 5630241404253944167u, 1522705314281249856u },
+ { 814844308661245011u, 1218164251424999885u }, { 1303750893857992017u, 1949062802279999816u },
+ { 15800395974054034906u, 1559250241823999852u }, { 5261619149759407279u, 1247400193459199882u },
+ { 12107939454356961969u, 1995840309534719811u }, { 5997002748743659252u, 1596672247627775849u },
+ { 8486951013736837725u, 1277337798102220679u }, { 2511075177753209390u, 2043740476963553087u },
+ { 13076906586428298482u, 1634992381570842469u }, { 14150874083884549109u, 1307993905256673975u },
+ { 4194654460505726958u, 2092790248410678361u }, { 18113118827372222859u, 1674232198728542688u },
+ { 3422448617672047318u, 1339385758982834151u }, { 16543964232501006678u, 2143017214372534641u },
+ { 9545822571258895019u, 1714413771498027713u }, { 15015355686490936662u, 1371531017198422170u },
+ { 5577825024675947042u, 2194449627517475473u }, { 11840957649224578280u, 1755559702013980378u },
+ { 16851463748863483271u, 1404447761611184302u }, { 12204946739213931940u, 2247116418577894884u },
+ { 13453306206113055875u, 1797693134862315907u }, { 3383947335406624054u, 1438154507889852726u },
+ { 16482362180876329456u, 2301047212623764361u }, { 9496540929959153242u, 1840837770099011489u },
+ { 11286581558709232917u, 1472670216079209191u }, { 5339916432225476010u, 1178136172863367353u },
+ { 4854517476818851293u, 1885017876581387765u }, { 3883613981455081034u, 1508014301265110212u },
+ { 14174937629389795797u, 1206411441012088169u }, { 11611853762797942306u, 1930258305619341071u },
+ { 5600134195496443521u, 1544206644495472857u }, { 15548153800622885787u, 1235365315596378285u },
+ { 6430302007287065643u, 1976584504954205257u }, { 16212288050055383484u, 1581267603963364205u },
+ { 12969830440044306787u, 1265014083170691364u }, { 9683682259845159889u, 2024022533073106183u },
+ { 15125643437359948558u, 1619218026458484946u }, { 8411165935146048523u, 1295374421166787957u },
+ { 17147214310975587960u, 2072599073866860731u }, { 10028422634038560045u, 1658079259093488585u },
+ { 8022738107230848036u, 1326463407274790868u }, { 9147032156827446534u, 2122341451639665389u },
+ { 11006974540203867551u, 1697873161311732311u }, { 5116230817421183718u, 1358298529049385849u },
+ { 15564666937357714594u, 2173277646479017358u }, { 1383687105660440706u, 1738622117183213887u },
+ { 12174996128754083534u, 1390897693746571109u }, { 8411947361780802685u, 2225436309994513775u },
+ { 6729557889424642148u, 1780349047995611020u }, { 5383646311539713719u, 1424279238396488816u },
+ { 1235136468979721303u, 2278846781434382106u }, { 15745504434151418335u, 1823077425147505684u },
+ { 16285752362063044992u, 1458461940118004547u }, { 5649904260166615347u, 1166769552094403638u },
+ { 5350498001524674232u, 1866831283351045821u }, { 591049586477829062u, 1493465026680836657u },
+ { 11540886113407994219u, 1194772021344669325u }, { 18673707743239135u, 1911635234151470921u },
+ { 14772334225162232601u, 1529308187321176736u }, { 8128518565387875758u, 1223446549856941389u },
+ { 1937583260394870242u, 1957514479771106223u }, { 8928764237799716840u, 1566011583816884978u },
+ { 14521709019723594119u, 1252809267053507982u }, { 8477339172590109297u, 2004494827285612772u },
+ { 17849917782297818407u, 1603595861828490217u }, { 6901236596354434079u, 1282876689462792174u },
+ { 18420676183650915173u, 2052602703140467478u }, { 3668494502695001169u, 1642082162512373983u },
+ { 10313493231639821582u, 1313665730009899186u }, { 9122891541139893884u, 2101865168015838698u },
+ { 14677010862395735754u, 1681492134412670958u }, { 673562245690857633u, 1345193707530136767u }
+};
+
+static const uint64_t DOUBLE_POW5_SPLIT[DOUBLE_POW5_TABLE_SIZE][2] = {
+ { 0u, 1152921504606846976u }, { 0u, 1441151880758558720u },
+ { 0u, 1801439850948198400u }, { 0u, 2251799813685248000u },
+ { 0u, 1407374883553280000u }, { 0u, 1759218604441600000u },
+ { 0u, 2199023255552000000u }, { 0u, 1374389534720000000u },
+ { 0u, 1717986918400000000u }, { 0u, 2147483648000000000u },
+ { 0u, 1342177280000000000u }, { 0u, 1677721600000000000u },
+ { 0u, 2097152000000000000u }, { 0u, 1310720000000000000u },
+ { 0u, 1638400000000000000u }, { 0u, 2048000000000000000u },
+ { 0u, 1280000000000000000u }, { 0u, 1600000000000000000u },
+ { 0u, 2000000000000000000u }, { 0u, 1250000000000000000u },
+ { 0u, 1562500000000000000u }, { 0u, 1953125000000000000u },
+ { 0u, 1220703125000000000u }, { 0u, 1525878906250000000u },
+ { 0u, 1907348632812500000u }, { 0u, 1192092895507812500u },
+ { 0u, 1490116119384765625u }, { 4611686018427387904u, 1862645149230957031u },
+ { 9799832789158199296u, 1164153218269348144u }, { 12249790986447749120u, 1455191522836685180u },
+ { 15312238733059686400u, 1818989403545856475u }, { 14528612397897220096u, 2273736754432320594u },
+ { 13692068767113150464u, 1421085471520200371u }, { 12503399940464050176u, 1776356839400250464u },
+ { 15629249925580062720u, 2220446049250313080u }, { 9768281203487539200u, 1387778780781445675u },
+ { 7598665485932036096u, 1734723475976807094u }, { 274959820560269312u, 2168404344971008868u },
+ { 9395221924704944128u, 1355252715606880542u }, { 2520655369026404352u, 1694065894508600678u },
+ { 12374191248137781248u, 2117582368135750847u }, { 14651398557727195136u, 1323488980084844279u },
+ { 13702562178731606016u, 1654361225106055349u }, { 3293144668132343808u, 2067951531382569187u },
+ { 18199116482078572544u, 1292469707114105741u }, { 8913837547316051968u, 1615587133892632177u },
+ { 15753982952572452864u, 2019483917365790221u }, { 12152082354571476992u, 1262177448353618888u },
+ { 15190102943214346240u, 1577721810442023610u }, { 9764256642163156992u, 1972152263052529513u },
+ { 17631875447420442880u, 1232595164407830945u }, { 8204786253993389888u, 1540743955509788682u },
+ { 1032610780636961552u, 1925929944387235853u }, { 2951224747111794922u, 1203706215242022408u },
+ { 3689030933889743652u, 1504632769052528010u }, { 13834660704216955373u, 1880790961315660012u },
+ { 17870034976990372916u, 1175494350822287507u }, { 17725857702810578241u, 1469367938527859384u },
+ { 3710578054803671186u, 1836709923159824231u }, { 26536550077201078u, 2295887403949780289u },
+ { 11545800389866720434u, 1434929627468612680u }, { 14432250487333400542u, 1793662034335765850u },
+ { 8816941072311974870u, 2242077542919707313u }, { 17039803216263454053u, 1401298464324817070u },
+ { 12076381983474541759u, 1751623080406021338u }, { 5872105442488401391u, 2189528850507526673u },
+ { 15199280947623720629u, 1368455531567204170u }, { 9775729147674874978u, 1710569414459005213u },
+ { 16831347453020981627u, 2138211768073756516u }, { 1296220121283337709u, 1336382355046097823u },
+ { 15455333206886335848u, 1670477943807622278u }, { 10095794471753144002u, 2088097429759527848u },
+ { 6309871544845715001u, 1305060893599704905u }, { 12499025449484531656u, 1631326116999631131u },
+ { 11012095793428276666u, 2039157646249538914u }, { 11494245889320060820u, 1274473528905961821u },
+ { 532749306367912313u, 1593091911132452277u }, { 5277622651387278295u, 1991364888915565346u },
+ { 7910200175544436838u, 1244603055572228341u }, { 14499436237857933952u, 1555753819465285426u },
+ { 8900923260467641632u, 1944692274331606783u }, { 12480606065433357876u, 1215432671457254239u },
+ { 10989071563364309441u, 1519290839321567799u }, { 9124653435777998898u, 1899113549151959749u },
+ { 8008751406574943263u, 1186945968219974843u }, { 5399253239791291175u, 1483682460274968554u },
+ { 15972438586593889776u, 1854603075343710692u }, { 759402079766405302u, 1159126922089819183u },
+ { 14784310654990170340u, 1448908652612273978u }, { 9257016281882937117u, 1811135815765342473u },
+ { 16182956370781059300u, 2263919769706678091u }, { 7808504722524468110u, 1414949856066673807u },
+ { 5148944884728197234u, 1768687320083342259u }, { 1824495087482858639u, 2210859150104177824u },
+ { 1140309429676786649u, 1381786968815111140u }, { 1425386787095983311u, 1727233711018888925u },
+ { 6393419502297367043u, 2159042138773611156u }, { 13219259225790630210u, 1349401336733506972u },
+ { 16524074032238287762u, 1686751670916883715u }, { 16043406521870471799u, 2108439588646104644u },
+ { 803757039314269066u, 1317774742903815403u }, { 14839754354425000045u, 1647218428629769253u },
+ { 4714634887749086344u, 2059023035787211567u }, { 9864175832484260821u, 1286889397367007229u },
+ { 16941905809032713930u, 1608611746708759036u }, { 2730638187581340797u, 2010764683385948796u },
+ { 10930020904093113806u, 1256727927116217997u }, { 18274212148543780162u, 1570909908895272496u },
+ { 4396021111970173586u, 1963637386119090621u }, { 5053356204195052443u, 1227273366324431638u },
+ { 15540067292098591362u, 1534091707905539547u }, { 14813398096695851299u, 1917614634881924434u },
+ { 13870059828862294966u, 1198509146801202771u }, { 12725888767650480803u, 1498136433501503464u },
+ { 15907360959563101004u, 1872670541876879330u }, { 14553786618154326031u, 1170419088673049581u },
+ { 4357175217410743827u, 1463023860841311977u }, { 10058155040190817688u, 1828779826051639971u },
+ { 7961007781811134206u, 2285974782564549964u }, { 14199001900486734687u, 1428734239102843727u },
+ { 13137066357181030455u, 1785917798878554659u }, { 11809646928048900164u, 2232397248598193324u },
+ { 16604401366885338411u, 1395248280373870827u }, { 16143815690179285109u, 1744060350467338534u },
+ { 10956397575869330579u, 2180075438084173168u }, { 6847748484918331612u, 1362547148802608230u },
+ { 17783057643002690323u, 1703183936003260287u }, { 17617136035325974999u, 2128979920004075359u },
+ { 17928239049719816230u, 1330612450002547099u }, { 17798612793722382384u, 1663265562503183874u },
+ { 13024893955298202172u, 2079081953128979843u }, { 5834715712847682405u, 1299426220705612402u },
+ { 16516766677914378815u, 1624282775882015502u }, { 11422586310538197711u, 2030353469852519378u },
+ { 11750802462513761473u, 1268970918657824611u }, { 10076817059714813937u, 1586213648322280764u },
+ { 12596021324643517422u, 1982767060402850955u }, { 5566670318688504437u, 1239229412751781847u },
+ { 2346651879933242642u, 1549036765939727309u }, { 7545000868343941206u, 1936295957424659136u },
+ { 4715625542714963254u, 1210184973390411960u }, { 5894531928393704067u, 1512731216738014950u },
+ { 16591536947346905892u, 1890914020922518687u }, { 17287239619732898039u, 1181821263076574179u },
+ { 16997363506238734644u, 1477276578845717724u }, { 2799960309088866689u, 1846595723557147156u },
+ { 10973347230035317489u, 1154122327223216972u }, { 13716684037544146861u, 1442652909029021215u },
+ { 12534169028502795672u, 1803316136286276519u }, { 11056025267201106687u, 2254145170357845649u },
+ { 18439230838069161439u, 1408840731473653530u }, { 13825666510731675991u, 1761050914342066913u },
+ { 3447025083132431277u, 2201313642927583642u }, { 6766076695385157452u, 1375821026829739776u },
+ { 8457595869231446815u, 1719776283537174720u }, { 10571994836539308519u, 2149720354421468400u },
+ { 6607496772837067824u, 1343575221513417750u }, { 17482743002901110588u, 1679469026891772187u },
+ { 17241742735199000331u, 2099336283614715234u }, { 15387775227926763111u, 1312085177259197021u },
+ { 5399660979626290177u, 1640106471573996277u }, { 11361262242960250625u, 2050133089467495346u },
+ { 11712474920277544544u, 1281333180917184591u }, { 10028907631919542777u, 1601666476146480739u },
+ { 7924448521472040567u, 2002083095183100924u }, { 14176152362774801162u, 1251301934489438077u },
+ { 3885132398186337741u, 1564127418111797597u }, { 9468101516160310080u, 1955159272639746996u },
+ { 15140935484454969608u, 1221974545399841872u }, { 479425281859160394u, 1527468181749802341u },
+ { 5210967620751338397u, 1909335227187252926u }, { 17091912818251750210u, 1193334516992033078u },
+ { 12141518985959911954u, 1491668146240041348u }, { 15176898732449889943u, 1864585182800051685u },
+ { 11791404716994875166u, 1165365739250032303u }, { 10127569877816206054u, 1456707174062540379u },
+ { 8047776328842869663u, 1820883967578175474u }, { 836348374198811271u, 2276104959472719343u },
+ { 7440246761515338900u, 1422565599670449589u }, { 13911994470321561530u, 1778206999588061986u },
+ { 8166621051047176104u, 2222758749485077483u }, { 2798295147690791113u, 1389224218428173427u },
+ { 17332926989895652603u, 1736530273035216783u }, { 17054472718942177850u, 2170662841294020979u },
+ { 8353202440125167204u, 1356664275808763112u }, { 10441503050156459005u, 1695830344760953890u },
+ { 3828506775840797949u, 2119787930951192363u }, { 86973725686804766u, 1324867456844495227u },
+ { 13943775212390669669u, 1656084321055619033u }, { 3594660960206173375u, 2070105401319523792u },
+ { 2246663100128858359u, 1293815875824702370u }, { 12031700912015848757u, 1617269844780877962u },
+ { 5816254103165035138u, 2021587305976097453u }, { 5941001823691840913u, 1263492066235060908u },
+ { 7426252279614801142u, 1579365082793826135u }, { 4671129331091113523u, 1974206353492282669u },
+ { 5225298841145639904u, 1233878970932676668u }, { 6531623551432049880u, 1542348713665845835u },
+ { 3552843420862674446u, 1927935892082307294u }, { 16055585193321335241u, 1204959932551442058u },
+ { 10846109454796893243u, 1506199915689302573u }, { 18169322836923504458u, 1882749894611628216u },
+ { 11355826773077190286u, 1176718684132267635u }, { 9583097447919099954u, 1470898355165334544u },
+ { 11978871809898874942u, 1838622943956668180u }, { 14973589762373593678u, 2298278679945835225u },
+ { 2440964573842414192u, 1436424174966147016u }, { 3051205717303017741u, 1795530218707683770u },
+ { 13037379183483547984u, 2244412773384604712u }, { 8148361989677217490u, 1402757983365377945u },
+ { 14797138505523909766u, 1753447479206722431u }, { 13884737113477499304u, 2191809349008403039u },
+ { 15595489723564518921u, 1369880843130251899u }, { 14882676136028260747u, 1712351053912814874u },
+ { 9379973133180550126u, 2140438817391018593u }, { 17391698254306313589u, 1337774260869386620u },
+ { 3292878744173340370u, 1672217826086733276u }, { 4116098430216675462u, 2090272282608416595u },
+ { 266718509671728212u, 1306420176630260372u }, { 333398137089660265u, 1633025220787825465u },
+ { 5028433689789463235u, 2041281525984781831u }, { 10060300083759496378u, 1275800953740488644u },
+ { 12575375104699370472u, 1594751192175610805u }, { 1884160825592049379u, 1993438990219513507u },
+ { 17318501580490888525u, 1245899368887195941u }, { 7813068920331446945u, 1557374211108994927u },
+ { 5154650131986920777u, 1946717763886243659u }, { 915813323278131534u, 1216698602428902287u },
+ { 14979824709379828129u, 1520873253036127858u }, { 9501408849870009354u, 1901091566295159823u },
+ { 12855909558809837702u, 1188182228934474889u }, { 2234828893230133415u, 1485227786168093612u },
+ { 2793536116537666769u, 1856534732710117015u }, { 8663489100477123587u, 1160334207943823134u },
+ { 1605989338741628675u, 1450417759929778918u }, { 11230858710281811652u, 1813022199912223647u },
+ { 9426887369424876662u, 2266277749890279559u }, { 12809333633531629769u, 1416423593681424724u },
+ { 16011667041914537212u, 1770529492101780905u }, { 6179525747111007803u, 2213161865127226132u },
+ { 13085575628799155685u, 1383226165704516332u }, { 16356969535998944606u, 1729032707130645415u },
+ { 15834525901571292854u, 2161290883913306769u }, { 2979049660840976177u, 1350806802445816731u },
+ { 17558870131333383934u, 1688508503057270913u }, { 8113529608884566205u, 2110635628821588642u },
+ { 9682642023980241782u, 1319147268013492901u }, { 16714988548402690132u, 1648934085016866126u },
+ { 11670363648648586857u, 2061167606271082658u }, { 11905663298832754689u, 1288229753919426661u },
+ { 1047021068258779650u, 1610287192399283327u }, { 15143834390605638274u, 2012858990499104158u },
+ { 4853210475701136017u, 1258036869061940099u }, { 1454827076199032118u, 1572546086327425124u },
+ { 1818533845248790147u, 1965682607909281405u }, { 3442426662494187794u, 1228551629943300878u },
+ { 13526405364972510550u, 1535689537429126097u }, { 3072948650933474476u, 1919611921786407622u },
+ { 15755650962115585259u, 1199757451116504763u }, { 15082877684217093670u, 1499696813895630954u },
+ { 9630225068416591280u, 1874621017369538693u }, { 8324733676974063502u, 1171638135855961683u },
+ { 5794231077790191473u, 1464547669819952104u }, { 7242788847237739342u, 1830684587274940130u },
+ { 18276858095901949986u, 2288355734093675162u }, { 16034722328366106645u, 1430222333808546976u },
+ { 1596658836748081690u, 1787777917260683721u }, { 6607509564362490017u, 2234722396575854651u },
+ { 1823850468512862308u, 1396701497859909157u }, { 6891499104068465790u, 1745876872324886446u },
+ { 17837745916940358045u, 2182346090406108057u }, { 4231062170446641922u, 1363966306503817536u },
+ { 5288827713058302403u, 1704957883129771920u }, { 6611034641322878003u, 2131197353912214900u },
+ { 13355268687681574560u, 1331998346195134312u }, { 16694085859601968200u, 1664997932743917890u },
+ { 11644235287647684442u, 2081247415929897363u }, { 4971804045566108824u, 1300779634956185852u },
+ { 6214755056957636030u, 1625974543695232315u }, { 3156757802769657134u, 2032468179619040394u },
+ { 6584659645158423613u, 1270292612261900246u }, { 17454196593302805324u, 1587865765327375307u },
+ { 17206059723201118751u, 1984832206659219134u }, { 6142101308573311315u, 1240520129162011959u },
+ { 3065940617289251240u, 1550650161452514949u }, { 8444111790038951954u, 1938312701815643686u },
+ { 665883850346957067u, 1211445438634777304u }, { 832354812933696334u, 1514306798293471630u },
+ { 10263815553021896226u, 1892883497866839537u }, { 17944099766707154901u, 1183052186166774710u },
+ { 13206752671529167818u, 1478815232708468388u }, { 16508440839411459773u, 1848519040885585485u },
+ { 12623618533845856310u, 1155324400553490928u }, { 15779523167307320387u, 1444155500691863660u },
+ { 1277659885424598868u, 1805194375864829576u }, { 1597074856780748586u, 2256492969831036970u },
+ { 5609857803915355770u, 1410308106144398106u }, { 16235694291748970521u, 1762885132680497632u },
+ { 1847873790976661535u, 2203606415850622041u }, { 12684136165428883219u, 1377254009906638775u },
+ { 11243484188358716120u, 1721567512383298469u }, { 219297180166231438u, 2151959390479123087u },
+ { 7054589765244976505u, 1344974619049451929u }, { 13429923224983608535u, 1681218273811814911u },
+ { 12175718012802122765u, 2101522842264768639u }, { 14527352785642408584u, 1313451776415480399u },
+ { 13547504963625622826u, 1641814720519350499u }, { 12322695186104640628u, 2052268400649188124u },
+ { 16925056528170176201u, 1282667750405742577u }, { 7321262604930556539u, 1603334688007178222u },
+ { 18374950293017971482u, 2004168360008972777u }, { 4566814905495150320u, 1252605225005607986u },
+ { 14931890668723713708u, 1565756531257009982u }, { 9441491299049866327u, 1957195664071262478u },
+ { 1289246043478778550u, 1223247290044539049u }, { 6223243572775861092u, 1529059112555673811u },
+ { 3167368447542438461u, 1911323890694592264u }, { 1979605279714024038u, 1194577431684120165u },
+ { 7086192618069917952u, 1493221789605150206u }, { 18081112809442173248u, 1866527237006437757u },
+ { 13606538515115052232u, 1166579523129023598u }, { 7784801107039039482u, 1458224403911279498u },
+ { 507629346944023544u, 1822780504889099373u }, { 5246222702107417334u, 2278475631111374216u },
+ { 3278889188817135834u, 1424047269444608885u }, { 8710297504448807696u, 1780059086805761106u }
+};
+
+// IEEE 754 double precision constants
+#define DOUBLE_MANTISSA_BITS 52
+#define DOUBLE_EXPONENT_BITS 11
+#define DOUBLE_EXPONENT_BIAS 1023
+
+// Helper: floor(log2(value)) using ryu_leading_zeros64
+static inline uint32_t floor_log2(const uint64_t value) {
+ return 63 - ryu_leading_zeros64(value);
+}
+
+// Helper: log2(5^e) approximation
+static inline int32_t log2pow5(const int32_t e) {
+ return (int32_t) ((((uint32_t) e) * 1217359) >> 19);
+}
+
+// Helper: ceil(log2(5^e))
+static inline int32_t ceil_log2pow5(const int32_t e) {
+ return log2pow5(e) + 1;
+}
+
+// Helper: max of two int32
+static inline int32_t max32(int32_t a, int32_t b) {
+ return a < b ? b : a;
+}
+
+// Helper: convert uint64 bits to double
+static inline double int64Bits2Double(uint64_t bits) {
+ double f;
+ memcpy(&f, &bits, sizeof(double));
+ return f;
+}
+
+// Check if value is multiple of 2^p
+static inline bool multipleOfPowerOf2(const uint64_t value, const uint32_t p) {
+ return (value & ((1ull << p) - 1)) == 0;
+}
+
+// Count how many times value is divisible by 5
+// Uses modular inverse to avoid expensive division
+static inline uint32_t pow5Factor(uint64_t value) {
+ const uint64_t m_inv_5 = 14757395258967641293u; // 5 * m_inv_5 = 1 (mod 2^64)
+ const uint64_t n_div_5 = 3689348814741910323u; // 2^64 / 5
+ uint32_t count = 0;
+ for (;;) {
+ value *= m_inv_5;
+ if (value > n_div_5)
+ break;
+ ++count;
+ }
+ return count;
+}
+
+// Check if value is multiple of 5^p
+// Optimized: uses modular inverse instead of division
+static inline bool multipleOfPowerOf5(const uint64_t value, const uint32_t p) {
+ return pow5Factor(value) >= p;
+}
+
+// 128-bit multiplication with shift
+// This is the core operation for converting decimal to binary
+#if defined(__SIZEOF_INT128__)
+// Use native 128-bit integers if available (GCC/Clang)
+static inline uint64_t mulShift64(const uint64_t m, const uint64_t* const mul, const int32_t j) {
+ const unsigned __int128 b0 = ((unsigned __int128) m) * mul[0];
+ const unsigned __int128 b2 = ((unsigned __int128) m) * mul[1];
+ return (uint64_t) (((b0 >> 64) + b2) >> (j - 64));
+}
+#else
+// Fallback for systems without 128-bit integers
+static inline uint64_t umul128(const uint64_t a, const uint64_t b, uint64_t* const productHi) {
+ const uint32_t aLo = (uint32_t)a;
+ const uint32_t aHi = (uint32_t)(a >> 32);
+ const uint32_t bLo = (uint32_t)b;
+ const uint32_t bHi = (uint32_t)(b >> 32);
+
+ const uint64_t b00 = (uint64_t)aLo * bLo;
+ const uint64_t b01 = (uint64_t)aLo * bHi;
+ const uint64_t b10 = (uint64_t)aHi * bLo;
+ const uint64_t b11 = (uint64_t)aHi * bHi;
+
+ const uint32_t b00Lo = (uint32_t)b00;
+ const uint32_t b00Hi = (uint32_t)(b00 >> 32);
+
+ const uint64_t mid1 = b10 + b00Hi;
+ const uint32_t mid1Lo = (uint32_t)(mid1);
+ const uint32_t mid1Hi = (uint32_t)(mid1 >> 32);
+
+ const uint64_t mid2 = b01 + mid1Lo;
+ const uint32_t mid2Lo = (uint32_t)(mid2);
+ const uint32_t mid2Hi = (uint32_t)(mid2 >> 32);
+
+ const uint64_t pHi = b11 + mid1Hi + mid2Hi;
+ const uint64_t pLo = ((uint64_t)mid2Lo << 32) | b00Lo;
+
+ *productHi = pHi;
+ return pLo;
+}
+
+static inline uint64_t shiftright128(const uint64_t lo, const uint64_t hi, const uint32_t dist) {
+ return (hi << (64 - dist)) | (lo >> dist);
+}
+
+static inline uint64_t mulShift64(const uint64_t m, const uint64_t* const mul, const int32_t j) {
+ uint64_t high1;
+ const uint64_t low1 = umul128(m, mul[1], &high1);
+ uint64_t high0;
+ umul128(m, mul[0], &high0);
+ const uint64_t sum = high0 + low1;
+ if (sum < high0) {
+ ++high1;
+ }
+ return shiftright128(sum, high1, j - 64);
+}
+#endif
+
+// Main conversion function: decimal mantissa+exponent to IEEE 754 double
+// Optimized for JSON parsing with fast paths for edge cases
+static inline double ryu_s2d_from_parts(uint64_t m10, int m10digits, int32_t e10, bool signedM) {
+ // Fast path: handle zero explicitly (e.g., "0.0", "0e0")
+ if (m10 == 0) {
+ return int64Bits2Double(((uint64_t) signedM) << 63);
+ }
+
+ // Fast path: handle overflow/underflow early
+ if (m10digits + e10 <= -324) {
+ // Underflow to zero
+ return int64Bits2Double(((uint64_t) signedM) << 63);
+ }
+
+ if (m10digits + e10 >= 310) {
+ // Overflow to infinity
+ return int64Bits2Double((((uint64_t) signedM) << 63) | 0x7ff0000000000000ULL);
+ }
+
+ // Convert decimal to binary: m10 * 10^e10 = m2 * 2^e2
+ int32_t e2;
+ uint64_t m2;
+ bool trailingZeros;
+
+ if (e10 >= 0) {
+ // Positive exponent: multiply by 5^e10 and adjust binary exponent
+ e2 = floor_log2(m10) + e10 + log2pow5(e10) - (DOUBLE_MANTISSA_BITS + 1);
+ int j = e2 - e10 - ceil_log2pow5(e10) + DOUBLE_POW5_BITCOUNT;
+ m2 = mulShift64(m10, DOUBLE_POW5_SPLIT[e10], j);
+ trailingZeros = e2 < e10 || (e2 - e10 < 64 && multipleOfPowerOf2(m10, e2 - e10));
+ } else {
+ // Negative exponent: divide by 5^(-e10)
+ e2 = floor_log2(m10) + e10 - ceil_log2pow5(-e10) - (DOUBLE_MANTISSA_BITS + 1);
+ int j = e2 - e10 + ceil_log2pow5(-e10) - 1 + DOUBLE_POW5_INV_BITCOUNT;
+ m2 = mulShift64(m10, DOUBLE_POW5_INV_SPLIT[-e10], j);
+ trailingZeros = multipleOfPowerOf5(m10, -e10);
+ }
+
+ // Compute IEEE 754 exponent
+ uint32_t ieee_e2 = (uint32_t) max32(0, e2 + DOUBLE_EXPONENT_BIAS + floor_log2(m2));
+
+ if (ieee_e2 > 0x7fe) {
+ // Overflow to infinity
+ return int64Bits2Double((((uint64_t) signedM) << 63) | 0x7ff0000000000000ULL);
+ }
+
+ // Compute shift amount for rounding
+ int32_t shift = (ieee_e2 == 0 ? 1 : ieee_e2) - e2 - DOUBLE_EXPONENT_BIAS - DOUBLE_MANTISSA_BITS;
+
+ // IEEE 754 round-to-even (banker's rounding)
+ trailingZeros &= (m2 & ((1ull << (shift - 1)) - 1)) == 0;
+ uint64_t lastRemovedBit = (m2 >> (shift - 1)) & 1;
+ bool roundUp = (lastRemovedBit != 0) && (!trailingZeros || (((m2 >> shift) & 1) != 0));
+
+ uint64_t ieee_m2 = (m2 >> shift) + roundUp;
+ ieee_m2 &= (1ull << DOUBLE_MANTISSA_BITS) - 1;
+
+ if (ieee_m2 == 0 && roundUp) {
+ ieee_e2++;
+ }
+
+ // Pack sign, exponent, and mantissa into IEEE 754 format
+ // Match original Ryu: group sign+exponent, then shift and add mantissa
+ uint64_t ieee = (((((uint64_t) signedM) << DOUBLE_EXPONENT_BITS) | (uint64_t)ieee_e2) << DOUBLE_MANTISSA_BITS) | ieee_m2;
+ return int64Bits2Double(ieee);
+}
+
+#endif // RYU_H
diff --git a/ext/monitor/depend b/ext/monitor/depend
index bc7ead0d32..0c7d54afc8 100644
--- a/ext/monitor/depend
+++ b/ext/monitor/depend
@@ -127,6 +127,7 @@ monitor.o: $(hdrdir)/ruby/internal/intern/re.h
monitor.o: $(hdrdir)/ruby/internal/intern/ruby.h
monitor.o: $(hdrdir)/ruby/internal/intern/select.h
monitor.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+monitor.o: $(hdrdir)/ruby/internal/intern/set.h
monitor.o: $(hdrdir)/ruby/internal/intern/signal.h
monitor.o: $(hdrdir)/ruby/internal/intern/sprintf.h
monitor.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/monitor/lib/monitor.rb b/ext/monitor/lib/monitor.rb
index 31d6d2b3c4..82d0a75c56 100644
--- a/ext/monitor/lib/monitor.rb
+++ b/ext/monitor/lib/monitor.rb
@@ -143,13 +143,13 @@ module MonitorMixin
private
- def initialize(monitor)
+ def initialize(monitor) # :nodoc:
@monitor = monitor
@cond = Thread::ConditionVariable.new
end
end
- def self.extend_object(obj)
+ def self.extend_object(obj) # :nodoc:
super(obj)
obj.__send__(:mon_initialize)
end
@@ -238,6 +238,8 @@ module MonitorMixin
@mon_data_owner_object_id = self.object_id
end
+ # Ensures that the MonitorMixin is owned by the current thread,
+ # otherwise raises an exception.
def mon_check_owner
@mon_data.mon_check_owner
end
@@ -254,6 +256,10 @@ end
# end
#
class Monitor
+ #
+ # Creates a new MonitorMixin::ConditionVariable associated with the
+ # Monitor object.
+ #
def new_cond
::MonitorMixin::ConditionVariable.new(self)
end
diff --git a/ext/monitor/monitor.c b/ext/monitor/monitor.c
index 86613f6ade..c43751c4e2 100644
--- a/ext/monitor/monitor.c
+++ b/ext/monitor/monitor.c
@@ -4,28 +4,35 @@
struct rb_monitor {
long count;
- const VALUE owner;
- const VALUE mutex;
+ VALUE owner;
+ VALUE mutex;
};
static void
monitor_mark(void *ptr)
{
struct rb_monitor *mc = ptr;
- rb_gc_mark(mc->owner);
- rb_gc_mark(mc->mutex);
+ rb_gc_mark_movable(mc->owner);
+ rb_gc_mark_movable(mc->mutex);
}
-static size_t
-monitor_memsize(const void *ptr)
+static void
+monitor_compact(void *ptr)
{
- return sizeof(struct rb_monitor);
+ struct rb_monitor *mc = ptr;
+ mc->owner = rb_gc_location(mc->owner);
+ mc->mutex = rb_gc_location(mc->mutex);
}
static const rb_data_type_t monitor_data_type = {
- "monitor",
- {monitor_mark, RUBY_TYPED_DEFAULT_FREE, monitor_memsize,},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED
+ .wrap_struct_name = "monitor",
+ .function = {
+ .dmark = monitor_mark,
+ .dfree = RUBY_TYPED_DEFAULT_FREE,
+ .dsize = NULL, // Fully embeded
+ .dcompact = monitor_compact,
+ },
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE,
};
static VALUE
@@ -50,68 +57,124 @@ monitor_ptr(VALUE monitor)
return mc;
}
-static int
-mc_owner_p(struct rb_monitor *mc)
+static bool
+mc_owner_p(struct rb_monitor *mc, VALUE current_fiber)
{
- return mc->owner == rb_fiber_current();
+ return mc->owner == current_fiber;
}
+/*
+ * call-seq:
+ * try_enter -> true or false
+ *
+ * Attempts to enter exclusive section. Returns +false+ if lock fails.
+ */
static VALUE
monitor_try_enter(VALUE monitor)
{
struct rb_monitor *mc = monitor_ptr(monitor);
- if (!mc_owner_p(mc)) {
+ VALUE current_fiber = rb_fiber_current();
+ if (!mc_owner_p(mc, current_fiber)) {
if (!rb_mutex_trylock(mc->mutex)) {
return Qfalse;
}
- RB_OBJ_WRITE(monitor, &mc->owner, rb_fiber_current());
+ RB_OBJ_WRITE(monitor, &mc->owner, current_fiber);
mc->count = 0;
}
mc->count += 1;
return Qtrue;
}
+
+struct monitor_args {
+ VALUE monitor;
+ struct rb_monitor *mc;
+ VALUE current_fiber;
+};
+
+static inline void
+monitor_args_init(struct monitor_args *args, VALUE monitor)
+{
+ args->monitor = monitor;
+ args->mc = monitor_ptr(monitor);
+ args->current_fiber = rb_fiber_current();
+}
+
+static void
+monitor_enter0(struct monitor_args *args)
+{
+ if (!mc_owner_p(args->mc, args->current_fiber)) {
+ rb_mutex_lock(args->mc->mutex);
+ RB_OBJ_WRITE(args->monitor, &args->mc->owner, args->current_fiber);
+ args->mc->count = 0;
+ }
+ args->mc->count++;
+}
+
+/*
+ * call-seq:
+ * enter -> nil
+ *
+ * Enters exclusive section.
+ */
static VALUE
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_fiber_current());
- mc->count = 0;
- }
- mc->count++;
+ struct monitor_args args;
+ monitor_args_init(&args, monitor);
+ monitor_enter0(&args);
return Qnil;
}
-static VALUE
-monitor_check_owner(VALUE monitor)
+static inline void
+monitor_check_owner0(struct monitor_args *args)
{
- struct rb_monitor *mc = monitor_ptr(monitor);
- if (!mc_owner_p(mc)) {
+ if (!mc_owner_p(args->mc, args->current_fiber)) {
rb_raise(rb_eThreadError, "current fiber not owner");
}
- return Qnil;
}
+/* :nodoc: */
static VALUE
-monitor_exit(VALUE monitor)
+monitor_check_owner(VALUE monitor)
{
- monitor_check_owner(monitor);
+ struct monitor_args args;
+ monitor_args_init(&args, monitor);
+ monitor_check_owner0(&args);
+ return Qnil;
+}
- struct rb_monitor *mc = monitor_ptr(monitor);
+static void
+monitor_exit0(struct monitor_args *args)
+{
+ monitor_check_owner0(args);
- if (mc->count <= 0) rb_bug("monitor_exit: count:%d", (int)mc->count);
- mc->count--;
+ if (args->mc->count <= 0) rb_bug("monitor_exit: count:%d", (int)args->mc->count);
+ args->mc->count--;
- if (mc->count == 0) {
- RB_OBJ_WRITE(monitor, &mc->owner, Qnil);
- rb_mutex_unlock(mc->mutex);
+ if (args->mc->count == 0) {
+ RB_OBJ_WRITE(args->monitor, &args->mc->owner, Qnil);
+ rb_mutex_unlock(args->mc->mutex);
}
+}
+
+/*
+ * call-seq:
+ * exit -> nil
+ *
+ * Leaves exclusive section.
+ */
+static VALUE
+monitor_exit(VALUE monitor)
+{
+ struct monitor_args args;
+ monitor_args_init(&args, monitor);
+ monitor_exit0(&args);
return Qnil;
}
+/* :nodoc: */
static VALUE
monitor_locked_p(VALUE monitor)
{
@@ -119,11 +182,12 @@ monitor_locked_p(VALUE monitor)
return rb_mutex_locked_p(mc->mutex);
}
+/* :nodoc: */
static VALUE
monitor_owned_p(VALUE monitor)
{
struct rb_monitor *mc = monitor_ptr(monitor);
- return (rb_mutex_locked_p(mc->mutex) && mc_owner_p(mc)) ? Qtrue : Qfalse;
+ return rb_mutex_locked_p(mc->mutex) && mc_owner_p(mc, rb_fiber_current()) ? Qtrue : Qfalse;
}
static VALUE
@@ -166,6 +230,7 @@ monitor_enter_for_cond(VALUE v)
return Qnil;
}
+/* :nodoc: */
static VALUE
monitor_wait_for_cond(VALUE monitor, VALUE cond, VALUE timeout)
{
@@ -188,16 +253,27 @@ monitor_sync_body(VALUE monitor)
}
static VALUE
-monitor_sync_ensure(VALUE monitor)
+monitor_sync_ensure(VALUE v_args)
{
- return monitor_exit(monitor);
+ monitor_exit0((struct monitor_args *)v_args);
+ return Qnil;
}
+/*
+ * call-seq:
+ * synchronize { } -> result of the block
+ *
+ * Enters exclusive section and executes the block. Leaves the exclusive
+ * section automatically when the block exits. See example under
+ * +MonitorMixin+.
+ */
static VALUE
monitor_synchronize(VALUE monitor)
{
- monitor_enter(monitor);
- return rb_ensure(monitor_sync_body, monitor, monitor_sync_ensure, monitor);
+ struct monitor_args args;
+ monitor_args_init(&args, monitor);
+ monitor_enter0(&args);
+ return rb_ensure(monitor_sync_body, (VALUE)&args, monitor_sync_ensure, (VALUE)&args);
}
void
diff --git a/ext/objspace/depend b/ext/objspace/depend
index a02168b06a..d9dfc0c42b 100644
--- a/ext/objspace/depend
+++ b/ext/objspace/depend
@@ -140,6 +140,7 @@ object_tracing.o: $(hdrdir)/ruby/internal/intern/re.h
object_tracing.o: $(hdrdir)/ruby/internal/intern/ruby.h
object_tracing.o: $(hdrdir)/ruby/internal/intern/select.h
object_tracing.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+object_tracing.o: $(hdrdir)/ruby/internal/intern/set.h
object_tracing.o: $(hdrdir)/ruby/internal/intern/signal.h
object_tracing.o: $(hdrdir)/ruby/internal/intern/sprintf.h
object_tracing.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -177,14 +178,17 @@ object_tracing.o: $(top_srcdir)/ccan/check_type/check_type.h
object_tracing.o: $(top_srcdir)/ccan/container_of/container_of.h
object_tracing.o: $(top_srcdir)/ccan/list/list.h
object_tracing.o: $(top_srcdir)/ccan/str/str.h
+object_tracing.o: $(top_srcdir)/id_table.h
object_tracing.o: $(top_srcdir)/internal.h
object_tracing.o: $(top_srcdir)/internal/array.h
object_tracing.o: $(top_srcdir)/internal/basic_operators.h
+object_tracing.o: $(top_srcdir)/internal/box.h
object_tracing.o: $(top_srcdir)/internal/compilers.h
object_tracing.o: $(top_srcdir)/internal/gc.h
object_tracing.o: $(top_srcdir)/internal/imemo.h
object_tracing.o: $(top_srcdir)/internal/sanitizers.h
object_tracing.o: $(top_srcdir)/internal/serial.h
+object_tracing.o: $(top_srcdir)/internal/set_table.h
object_tracing.o: $(top_srcdir)/internal/static_assert.h
object_tracing.o: $(top_srcdir)/internal/vm.h
object_tracing.o: $(top_srcdir)/internal/warnings.h
@@ -340,6 +344,7 @@ objspace.o: $(hdrdir)/ruby/internal/intern/re.h
objspace.o: $(hdrdir)/ruby/internal/intern/ruby.h
objspace.o: $(hdrdir)/ruby/internal/intern/select.h
objspace.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+objspace.o: $(hdrdir)/ruby/internal/intern/set.h
objspace.o: $(hdrdir)/ruby/internal/intern/signal.h
objspace.o: $(hdrdir)/ruby/internal/intern/sprintf.h
objspace.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -386,6 +391,7 @@ 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/basic_operators.h
+objspace.o: $(top_srcdir)/internal/box.h
objspace.o: $(top_srcdir)/internal/class.h
objspace.o: $(top_srcdir)/internal/compilers.h
objspace.o: $(top_srcdir)/internal/gc.h
@@ -393,7 +399,9 @@ 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/set_table.h
objspace.o: $(top_srcdir)/internal/static_assert.h
+objspace.o: $(top_srcdir)/internal/struct.h
objspace.o: $(top_srcdir)/internal/variable.h
objspace.o: $(top_srcdir)/internal/vm.h
objspace.o: $(top_srcdir)/internal/warnings.h
@@ -552,6 +560,7 @@ objspace_dump.o: $(hdrdir)/ruby/internal/intern/re.h
objspace_dump.o: $(hdrdir)/ruby/internal/intern/ruby.h
objspace_dump.o: $(hdrdir)/ruby/internal/intern/select.h
objspace_dump.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+objspace_dump.o: $(hdrdir)/ruby/internal/intern/set.h
objspace_dump.o: $(hdrdir)/ruby/internal/intern/signal.h
objspace_dump.o: $(hdrdir)/ruby/internal/intern/sprintf.h
objspace_dump.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -593,10 +602,12 @@ objspace_dump.o: $(top_srcdir)/ccan/list/list.h
objspace_dump.o: $(top_srcdir)/ccan/str/str.h
objspace_dump.o: $(top_srcdir)/constant.h
objspace_dump.o: $(top_srcdir)/debug_counter.h
+objspace_dump.o: $(top_srcdir)/encindex.h
objspace_dump.o: $(top_srcdir)/id_table.h
objspace_dump.o: $(top_srcdir)/internal.h
objspace_dump.o: $(top_srcdir)/internal/array.h
objspace_dump.o: $(top_srcdir)/internal/basic_operators.h
+objspace_dump.o: $(top_srcdir)/internal/box.h
objspace_dump.o: $(top_srcdir)/internal/class.h
objspace_dump.o: $(top_srcdir)/internal/compilers.h
objspace_dump.o: $(top_srcdir)/internal/gc.h
@@ -605,8 +616,10 @@ objspace_dump.o: $(top_srcdir)/internal/imemo.h
objspace_dump.o: $(top_srcdir)/internal/io.h
objspace_dump.o: $(top_srcdir)/internal/sanitizers.h
objspace_dump.o: $(top_srcdir)/internal/serial.h
+objspace_dump.o: $(top_srcdir)/internal/set_table.h
objspace_dump.o: $(top_srcdir)/internal/static_assert.h
objspace_dump.o: $(top_srcdir)/internal/string.h
+objspace_dump.o: $(top_srcdir)/internal/struct.h
objspace_dump.o: $(top_srcdir)/internal/variable.h
objspace_dump.o: $(top_srcdir)/internal/vm.h
objspace_dump.o: $(top_srcdir)/internal/warnings.h
diff --git a/ext/objspace/object_tracing.c b/ext/objspace/object_tracing.c
index c1c93c51f5..c06f1f68dd 100644
--- a/ext/objspace/object_tracing.c
+++ b/ext/objspace/object_tracing.c
@@ -53,6 +53,14 @@ make_unique_str(st_table *tbl, const char *str, long len)
}
}
+static int
+delete_unique_str_dec(st_data_t *key, st_data_t *value, st_data_t arg, int existing)
+{
+ assert(existing);
+ *value = arg;
+ return ST_CONTINUE;
+}
+
static void
delete_unique_str(st_table *tbl, const char *str)
{
@@ -66,7 +74,7 @@ delete_unique_str(st_table *tbl, const char *str)
ruby_xfree((char *)n);
}
else {
- st_insert(tbl, (st_data_t)str, n-1);
+ st_update(tbl, (st_data_t)str, delete_unique_str_dec, (st_data_t)(n-1));
}
}
}
@@ -190,22 +198,25 @@ allocation_info_tracer_memsize(const void *ptr)
}
static int
-hash_foreach_should_replace_key(st_data_t key, st_data_t value, st_data_t argp, int error)
+allocation_info_tracer_compact_update_object_table_i(st_data_t key, st_data_t value, st_data_t data)
{
- VALUE allocated_object;
+ st_table *table = (st_table *)data;
- allocated_object = (VALUE)value;
- if (allocated_object != rb_gc_location(allocated_object)) {
- return ST_REPLACE;
+ if (!rb_gc_pointer_to_heap_p(key)) {
+ struct allocation_info *info = (struct allocation_info *)value;
+ xfree(info);
+ return ST_DELETE;
}
- return ST_CONTINUE;
-}
+ if (key != rb_gc_location(key)) {
+ DURING_GC_COULD_MALLOC_REGION_START();
+ {
+ st_insert(table, rb_gc_location(key), value);
+ }
+ DURING_GC_COULD_MALLOC_REGION_END();
-static int
-hash_replace_key(st_data_t *key, st_data_t *value, st_data_t argp, int existing)
-{
- *key = rb_gc_location((VALUE)*key);
+ return ST_DELETE;
+ }
return ST_CONTINUE;
}
@@ -216,7 +227,10 @@ allocation_info_tracer_compact(void *ptr)
struct traceobj_arg *trace_arg = (struct traceobj_arg *)ptr;
if (trace_arg->object_table &&
- st_foreach_with_replace(trace_arg->object_table, hash_foreach_should_replace_key, hash_replace_key, 0)) {
+ st_foreach(
+ trace_arg->object_table,
+ allocation_info_tracer_compact_update_object_table_i,
+ (st_data_t)trace_arg->object_table)) {
rb_raise(rb_eRuntimeError, "hash modified during iteration");
}
}
@@ -399,6 +413,13 @@ object_allocations_reporter(FILE *out, void *ptr)
fprintf(out, "== object_allocations_reporter: END\n");
}
+/*
+ * call-seq: trace_object_allocations_debug_start
+ *
+ * Starts tracing object allocations for GC debugging.
+ * If you encounter the BUG "... is T_NONE" (and so on) on your
+ * application, please try this method at the beginning of your app.
+ */
static VALUE
trace_object_allocations_debug_start(VALUE self)
{
diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c
index 24d7bd419f..457ffc2789 100644
--- a/ext/objspace/objspace.c
+++ b/ext/objspace/objspace.c
@@ -38,10 +38,11 @@
* information as only a *HINT*. Especially, the size of +T_DATA+ may not be
* correct.
*
- * This method is only expected to work with C Ruby.
+ * This method is only expected to work with CRuby.
*
- * From Ruby 2.2, memsize_of(obj) returns a memory size includes
- * sizeof(RVALUE).
+ * From Ruby 3.2 with Variable Width Allocation, it returns the actual slot
+ * size used plus any additional memory allocated outside the slot (such
+ * as external strings, arrays, or hash tables).
*/
static VALUE
@@ -81,15 +82,15 @@ heap_iter(void *vstart, void *vend, size_t stride, void *ptr)
VALUE v;
for (v = (VALUE)vstart; v != (VALUE)vend; v += stride) {
- void *poisoned = asan_poisoned_object_p(v);
- asan_unpoison_object(v, false);
+ void *poisoned = rb_asan_poisoned_object_p(v);
+ rb_asan_unpoison_object(v, false);
if (RBASIC(v)->flags) {
(*ctx->cb)(v, ctx->data);
}
if (poisoned) {
- asan_poison_object(v);
+ rb_asan_poison_object(v);
}
}
@@ -107,28 +108,24 @@ each_object_with_flags(each_obj_with_flags cb, void *ctx)
/*
* call-seq:
- * ObjectSpace.memsize_of_all([klass]) -> Integer
+ * ObjectSpace.memsize_of_all(klass = nil) -> integer
*
- * Return consuming memory size of all living objects in bytes.
+ * Returns the total 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.
+ * ObjectSpace.memsize_of_all # => 12502001
*
- * Note that the returned size is incomplete. You need to deal with this
- * information as only a *HINT*. Especially, the size of +T_DATA+ may not be
- * correct.
+ * If +klass+ is given (which must be a Class or Module), returns the total
+ * memory size of objects whose class is, or is a subclass, of +klass+.
*
- * Note that this method does *NOT* return total malloc'ed memory size.
+ * class MyClass; end
+ * ObjectSpace.memsize_of_all(MyClass) # => 0
+ * o = MyClass.new
+ * ObjectSpace.memsize_of_all(MyClass) # => 40
*
- * This method can be defined by the following Ruby code:
- *
- * def memsize_of_all klass = false
- * total = 0
- * ObjectSpace.each_object{|e|
- * total += ObjectSpace.memsize_of(e) if klass == false || e.kind_of?(klass)
- * }
- * total
- * end
+ * Note that the value returned may be an underestimate of the actual amount
+ * of memory used. Therefore, the value returned should only be used as a hint,
+ * rather than a source of truth. In particular, the size of +T_DATA+ objects may
+ * not be correct.
*
* This method is only expected to work with C Ruby.
*/
@@ -294,28 +291,27 @@ size_t rb_sym_immortal_count(void);
/*
* call-seq:
- * ObjectSpace.count_symbols([result_hash]) -> hash
- *
- * Counts symbols for each Symbol type.
+ * ObjectSpace.count_symbols(result_hash = nil) -> hash
*
- * This method is only for MRI developers interested in performance and memory
- * usage of Ruby programs.
+ * Returns a hash containing the number of objects for each Symbol type.
*
- * If the optional argument, result_hash, is given, it is overwritten and
- * returned. This is intended to avoid probe effect.
+ * The types of Symbols are the following:
*
- * Note:
- * The contents of the returned hash is implementation defined.
- * It may be changed in future.
+ * - +mortal_dynamic_symbol+: Symbols that are garbage collectable.
+ * - +immortal_dynamic_symbol+: Symbols that are objects allocated from the
+ * garbage collector, but are not garbage collectable.
+ * - +immortal_static_symbol+: Symbols that are not allocated from the
+ * garbage collector, and are thus not garbage collectable.
+ * - +immortal_symbol+: the sum of +immortal_dynamic_symbol+ and +immortal_static_symbol+.
*
- * This method is only expected to work with C Ruby.
+ * If the optional argument +result_hash+ is given, it is overwritten and
+ * returned. This is intended to avoid the probe effect.
*
- * On this version of MRI, they have 3 types of Symbols (and 1 total counts).
+ * This method is intended for developers interested in performance and memory
+ * usage of Ruby programs. The contents of the returned hash is implementation
+ * specific and may change in the future.
*
- * * mortal_dynamic_symbol: GC target symbols (collected by GC)
- * * immortal_dynamic_symbol: Immortal symbols promoted from dynamic symbols (do not collected by GC)
- * * immortal_static_symbol: Immortal symbols (do not collected by GC)
- * * immortal_symbol: total immortal symbols (immortal_dynamic_symbol+immortal_static_symbol)
+ * This method is only expected to work with C Ruby.
*/
static VALUE
@@ -335,35 +331,6 @@ count_symbols(int argc, VALUE *argv, VALUE os)
return hash;
}
-/*
- * call-seq:
- * ObjectSpace.count_nodes([result_hash]) -> hash
- *
- * Counts nodes for each node type.
- *
- * This method is only for MRI developers interested in performance and memory
- * usage of Ruby programs.
- *
- * It returns a hash as:
- *
- * {:NODE_METHOD=>2027, :NODE_FBODY=>1927, :NODE_CFUNC=>1798, ...}
- *
- * If the optional argument, result_hash, is given, it is overwritten and
- * returned. This is intended to avoid probe effect.
- *
- * Note:
- * The contents of the returned hash is implementation defined.
- * It may be changed in future.
- *
- * This method is only expected to work with C Ruby.
- */
-
-static VALUE
-count_nodes(int argc, VALUE *argv, VALUE os)
-{
- return setup_hash(argc, argv);
-}
-
static void
cto_i(VALUE v, void *data)
{
@@ -393,32 +360,22 @@ cto_i(VALUE v, void *data)
/*
* call-seq:
- * ObjectSpace.count_tdata_objects([result_hash]) -> hash
+ * ObjectSpace.count_tdata_objects(result_hash = nil) -> hash
*
- * Counts objects for each +T_DATA+ type.
+ * Returns a hash containing the number of objects for each +T_DATA+ type.
+ * The keys are Class objects when the +T_DATA+ object has an associated class,
+ * or Symbol objects of the name defined in the +rb_data_type_struct+ for internal
+ * +T_DATA+ objects.
*
- * This method is only for MRI developers interested in performance and memory
- * usage of Ruby programs.
+ * ObjectSpace.count_tdata_objects
+ * # => {RBS::Location => 39255, marshal_compat_table: 1, Encoding => 103, mutex: 1, ... }
*
- * It returns a hash as:
- *
- * {RubyVM::InstructionSequence=>504, :parser=>5, :barrier=>6,
- * :mutex=>6, Proc=>60, RubyVM::Env=>57, Mutex=>1, Encoding=>99,
- * ThreadGroup=>1, Binding=>1, Thread=>1, RubyVM=>1, :iseq=>1,
- * Random=>1, ARGF.class=>1, Data=>1, :autoload=>3, Time=>2}
- * # T_DATA objects existing at startup on r32276.
- *
- * If the optional argument, result_hash, is given, it is overwritten and
- * returned. This is intended to avoid probe effect.
- *
- * The contents of the returned hash is implementation specific and may change
- * in the future.
- *
- * In this version, keys are Class object or Symbol object.
+ * If the optional argument +result_hash+ is given, it is overwritten and
+ * returned. This is intended to avoid the probe effect.
*
- * If object is kind of normal (accessible) object, the key is Class object.
- * If object is not a kind of normal (internal) object, the key is symbol
- * name, registered by rb_data_type_struct.
+ * This method is intended for developers interested in performance and memory
+ * usage of Ruby programs. The contents of the returned hash is implementation
+ * specific and may change in the future.
*
* This method is only expected to work with C Ruby.
*/
@@ -457,28 +414,22 @@ count_imemo_objects_i(VALUE v, void *data)
/*
* call-seq:
- * ObjectSpace.count_imemo_objects([result_hash]) -> hash
- *
- * Counts objects for each +T_IMEMO+ type.
- *
- * This method is only for MRI developers interested in performance and memory
- * usage of Ruby programs.
- *
- * It returns a hash as:
+ * ObjectSpace.count_imemo_objects(result_hash = nil) -> hash
*
- * {:imemo_ifunc=>8,
- * :imemo_svar=>7,
- * :imemo_cref=>509,
- * :imemo_memo=>1,
- * :imemo_throw_data=>1}
+ * Returns a hash containing the number of objects for each +T_IMEMO+ type.
+ * The keys are Symbol objects of the +T_IMEMO+ type name.
+ * +T_IMEMO+ objects are Ruby internal objects that are not visible to Ruby
+ * programs.
*
- * If the optional argument, result_hash, is given, it is overwritten and
- * returned. This is intended to avoid probe effect.
+ * ObjectSpace.count_imemo_objects
+ * # => {imemo_callcache: 5482, imemo_constcache: 1258, imemo_ment: 13906, ... }
*
- * The contents of the returned hash is implementation specific and may change
- * in the future.
+ * If the optional argument +result_hash+ is given, it is overwritten and
+ * returned. This is intended to avoid the probe effect.
*
- * In this version, keys are symbol objects.
+ * This method is intended for developers interested in performance and memory
+ * usage of Ruby programs. The contents of the returned hash is implementation
+ * specific and may change in the future.
*
* This method is only expected to work with C Ruby.
*/
@@ -499,11 +450,10 @@ count_imemo_objects(int argc, VALUE *argv, VALUE self)
INIT_IMEMO_TYPE_ID(imemo_ment);
INIT_IMEMO_TYPE_ID(imemo_iseq);
INIT_IMEMO_TYPE_ID(imemo_tmpbuf);
- INIT_IMEMO_TYPE_ID(imemo_ast);
- INIT_IMEMO_TYPE_ID(imemo_parser_strterm);
INIT_IMEMO_TYPE_ID(imemo_callinfo);
INIT_IMEMO_TYPE_ID(imemo_callcache);
INIT_IMEMO_TYPE_ID(imemo_constcache);
+ INIT_IMEMO_TYPE_ID(imemo_fields);
#undef INIT_IMEMO_TYPE_ID
}
@@ -577,7 +527,7 @@ reachable_object_from_i(VALUE obj, void *data_ptr)
VALUE key = obj;
VALUE val = obj;
- if (rb_objspace_markable_object_p(obj)) {
+ if (!rb_objspace_garbage_object_p(obj)) {
if (NIL_P(rb_hash_lookup(data->refs, key))) {
rb_hash_aset(data->refs, key, Qtrue);
@@ -643,7 +593,7 @@ collect_values(st_data_t key, st_data_t value, st_data_t data)
static VALUE
reachable_objects_from(VALUE self, VALUE obj)
{
- if (rb_objspace_markable_object_p(obj)) {
+ if (!RB_SPECIAL_CONST_P(obj)) {
struct rof_data data;
if (rb_typeddata_is_kind_of(obj, &iow_data_type)) {
@@ -690,7 +640,7 @@ reachable_object_from_root_i(const char *category, VALUE obj, void *ptr)
rb_hash_aset(data->categories, category_str, category_objects);
}
- if (rb_objspace_markable_object_p(obj) &&
+ if (!rb_objspace_garbage_object_p(obj) &&
obj != data->categories &&
obj != data->last_category_objects) {
if (rb_objspace_internal_object_p(obj)) {
@@ -792,7 +742,7 @@ objspace_internal_super_of(VALUE self, VALUE obj)
case T_MODULE:
case T_CLASS:
case T_ICLASS:
- super = RCLASS_SUPER(obj);
+ super = rb_class_super_of(obj);
break;
default:
rb_raise(rb_eArgError, "class or module is expected");
@@ -834,7 +784,6 @@ Init_objspace(void)
rb_define_module_function(rb_mObjSpace, "count_objects_size", count_objects_size, -1);
rb_define_module_function(rb_mObjSpace, "count_symbols", count_symbols, -1);
- rb_define_module_function(rb_mObjSpace, "count_nodes", count_nodes, -1);
rb_define_module_function(rb_mObjSpace, "count_tdata_objects", count_tdata_objects, -1);
rb_define_module_function(rb_mObjSpace, "count_imemo_objects", count_imemo_objects, -1);
diff --git a/ext/objspace/objspace_dump.c b/ext/objspace/objspace_dump.c
index bb479b91c5..da64698346 100644
--- a/ext/objspace/objspace_dump.c
+++ b/ext/objspace/objspace_dump.c
@@ -29,16 +29,17 @@
#include "ruby/util.h"
#include "ruby/io.h"
#include "vm_callinfo.h"
-#include "vm_core.h"
+#include "vm_sync.h"
RUBY_EXTERN const char ruby_hexdigits[];
#define BUFFER_CAPACITY 4096
struct dump_config {
- VALUE type;
- VALUE stream;
+ VALUE given_output;
+ VALUE output_io;
VALUE string;
+ FILE *stream;
const char *root_category;
VALUE cur_obj;
VALUE cur_obj_klass;
@@ -58,7 +59,7 @@ dump_flush(struct dump_config *dc)
{
if (dc->buffer_len) {
if (dc->stream) {
- size_t written = rb_io_bufwrite(dc->stream, dc->buffer, dc->buffer_len);
+ size_t written = fwrite(dc->buffer, sizeof(dc->buffer[0]), dc->buffer_len, dc->stream);
if (written < dc->buffer_len) {
MEMMOVE(dc->buffer, dc->buffer + written, char, dc->buffer_len - written);
dc->buffer_len -= written;
@@ -384,8 +385,6 @@ dump_object(VALUE obj, struct dump_config *dc)
size_t memsize;
struct allocation_info *ainfo = objspace_lookup_allocation_info(obj);
rb_io_t *fptr;
- ID flags[RB_OBJ_GC_FLAGS_MAX];
- size_t n, i;
ID mid;
if (SPECIAL_CONST_P(obj)) {
@@ -395,9 +394,10 @@ dump_object(VALUE obj, struct dump_config *dc)
dc->cur_obj = obj;
dc->cur_obj_references = 0;
- if (BUILTIN_TYPE(obj) == T_NODE || BUILTIN_TYPE(obj) == T_IMEMO) {
+ if (BUILTIN_TYPE(obj) == T_NODE || (BUILTIN_TYPE(obj) == T_IMEMO && !IMEMO_TYPE_P(obj, imemo_fields))) {
dc->cur_obj_klass = 0;
- } else {
+ }
+ else {
dc->cur_obj_klass = RBASIC_CLASS(obj);
}
@@ -415,9 +415,11 @@ dump_object(VALUE obj, struct dump_config *dc)
dump_append(dc, obj_type(obj));
dump_append(dc, "\"");
- size_t shape_id = rb_shape_get_shape_id(obj);
- dump_append(dc, ", \"shape_id\":");
- dump_append_sizet(dc, shape_id);
+ if (BUILTIN_TYPE(obj) != T_IMEMO || IMEMO_TYPE_P(obj, imemo_fields)) {
+ size_t shape_id = rb_obj_shape_id(obj) & SHAPE_ID_OFFSET_MASK;
+ dump_append(dc, ", \"shape_id\":");
+ dump_append_sizet(dc, shape_id);
+ }
dump_append(dc, ", \"slot_size\":");
dump_append_sizet(dc, dc->cur_page_slot_size);
@@ -449,13 +451,16 @@ dump_object(VALUE obj, struct dump_config *dc)
break;
case imemo_callcache:
- mid = vm_cc_cme((const struct rb_callcache *)obj)->called_id;
- if (mid != 0) {
- dump_append(dc, ", \"called_id\":");
- dump_append_id(dc, mid);
-
+ {
VALUE klass = ((const struct rb_callcache *)obj)->klass;
- if (klass != 0) {
+ if (klass != Qundef) {
+ mid = vm_cc_cme((const struct rb_callcache *)obj)->called_id;
+ if (mid != 0) {
+ dump_append(dc, ", \"called_id\":");
+ dump_append_id(dc, mid);
+
+ }
+
dump_append(dc, ", \"receiver_class\":");
dump_append_ref(dc, klass);
}
@@ -538,7 +543,7 @@ dump_object(VALUE obj, struct dump_config *dc)
case T_CLASS:
dump_append(dc, ", \"variation_count\":");
- dump_append_d(dc, RCLASS_EXT(obj)->variation_count);
+ dump_append_d(dc, rb_class_variation_count(obj));
case T_MODULE:
if (rb_class_get_superclass(obj)) {
@@ -549,9 +554,8 @@ dump_object(VALUE obj, struct dump_config *dc)
if (dc->cur_obj_klass) {
VALUE mod_name = rb_mod_name(obj);
if (!NIL_P(mod_name)) {
- dump_append(dc, ", \"name\":\"");
- dump_append(dc, RSTRING_PTR(mod_name));
- dump_append(dc, "\"");
+ dump_append(dc, ", \"name\":");
+ dump_append_string_value(dc, mod_name);
}
else {
VALUE real_mod_name = rb_mod_name(rb_class_real(obj));
@@ -562,7 +566,7 @@ dump_object(VALUE obj, struct dump_config *dc)
}
}
- if (RCLASS_SINGLETON_P(obj)) {
+ if (rb_class_singleton_p(obj)) {
dump_append(dc, ", \"singleton\":true");
}
}
@@ -583,13 +587,13 @@ dump_object(VALUE obj, struct dump_config *dc)
break;
case T_OBJECT:
- if (FL_TEST(obj, ROBJECT_EMBED)) {
+ if (!FL_TEST_RAW(obj, ROBJECT_HEAP)) {
dump_append(dc, ", \"embedded\":true");
}
dump_append(dc, ", \"ivars\":");
- dump_append_lu(dc, ROBJECT_IV_COUNT(obj));
- if (rb_shape_obj_too_complex(obj)) {
+ dump_append_lu(dc, ROBJECT_FIELDS_COUNT(obj));
+ if (rb_shape_obj_too_complex_p(obj)) {
dump_append(dc, ", \"too_complex_shape\":true");
}
break;
@@ -638,14 +642,24 @@ dump_object(VALUE obj, struct dump_config *dc)
dump_append_sizet(dc, memsize);
}
- if ((n = rb_obj_gc_flags(obj, flags, sizeof(flags))) > 0) {
- dump_append(dc, ", \"flags\":{");
- for (i=0; i<n; i++) {
- dump_append(dc, "\"");
- dump_append(dc, rb_id2name(flags[i]));
- dump_append(dc, "\":true");
- if (i != n-1) dump_append(dc, ", ");
+ struct rb_gc_object_metadata_entry *gc_metadata = rb_gc_object_metadata(obj);
+ for (int i = 0; gc_metadata[i].name != 0; i++) {
+ if (i == 0) {
+ dump_append(dc, ", \"flags\":{");
}
+ else {
+ dump_append(dc, ", ");
+ }
+
+ dump_append(dc, "\"");
+ dump_append(dc, rb_id2name(gc_metadata[i].name));
+ dump_append(dc, "\":");
+ dump_append_special_const(dc, gc_metadata[i].val);
+ }
+
+ /* If rb_gc_object_metadata had any entries, we need to close the opening
+ * `"flags":{`. */
+ if (gc_metadata[0].name != 0) {
dump_append(dc, "}");
}
@@ -658,15 +672,15 @@ heap_i(void *vstart, void *vend, size_t stride, void *data)
struct dump_config *dc = (struct dump_config *)data;
VALUE v = (VALUE)vstart;
for (; v != (VALUE)vend; v += stride) {
- void *ptr = asan_poisoned_object_p(v);
- asan_unpoison_object(v, false);
+ void *ptr = rb_asan_poisoned_object_p(v);
+ rb_asan_unpoison_object(v, false);
dc->cur_page_slot_size = stride;
if (dc->full_heap || RBASIC(v)->flags)
dump_object(v, dc);
if (ptr) {
- asan_poison_object(v);
+ rb_asan_poison_object(v);
}
}
return 0;
@@ -697,16 +711,34 @@ root_obj_i(const char *category, VALUE obj, void *data)
static void
dump_output(struct dump_config *dc, VALUE output, VALUE full, VALUE since, VALUE shapes)
{
-
+ dc->given_output = output;
dc->full_heap = 0;
dc->buffer_len = 0;
if (TYPE(output) == T_STRING) {
- dc->stream = Qfalse;
+ dc->stream = NULL;
dc->string = output;
}
else {
- dc->stream = output;
+ rb_io_t *fptr;
+ // Output should be an IO, typecheck and get a FILE* for writing.
+ // We cannot write with the usual IO code here because writes
+ // interleave with calls to rb_gc_mark(). The usual IO code can
+ // cause a thread switch, raise exceptions, and even run arbitrary
+ // ruby code through the fiber scheduler.
+ //
+ // Mark functions generally can't handle these possibilities so
+ // the usual IO code is unsafe in this context. (For example,
+ // there are many ways to crash when ruby code runs and mutates
+ // the execution context while rb_execution_context_mark() is in
+ // progress.)
+ //
+ // Using FILE* isn't perfect, but it avoids the most acute problems.
+ output = rb_io_get_io(output);
+ dc->output_io = rb_io_get_write_io(output);
+ rb_io_flush(dc->output_io);
+ GetOpenFile(dc->output_io, fptr);
+ dc->stream = rb_io_stdio_file(fptr);
dc->string = Qfalse;
}
@@ -730,24 +762,25 @@ dump_result(struct dump_config *dc)
{
dump_flush(dc);
+ if (dc->stream) {
+ fflush(dc->stream);
+ }
if (dc->string) {
return dc->string;
}
- else {
- rb_io_flush(dc->stream);
- return dc->stream;
- }
+ return dc->given_output;
}
-/* :nodoc: */
static VALUE
-objspace_dump(VALUE os, VALUE obj, VALUE output)
+dump_locked(void *args_p)
{
struct dump_config dc = {0,};
+ VALUE obj = ((VALUE*)args_p)[0];
+ VALUE output = ((VALUE*)args_p)[1];
+
if (!RB_SPECIAL_CONST_P(obj)) {
dc.cur_page_slot_size = rb_gc_obj_slot_size(obj);
}
-
dump_output(&dc, output, Qnil, Qnil, Qnil);
dump_object(obj, &dc);
@@ -755,69 +788,73 @@ objspace_dump(VALUE os, VALUE obj, VALUE output)
return dump_result(&dc);
}
+/* :nodoc: */
+static VALUE
+objspace_dump(VALUE os, VALUE obj, VALUE output)
+{
+ VALUE args[2];
+ args[0] = obj;
+ args[1] = output;
+ return rb_vm_lock_with_barrier(dump_locked, (void*)args);
+}
+
static void
-shape_i(rb_shape_t *shape, void *data)
+shape_id_i(shape_id_t shape_id, void *data)
{
struct dump_config *dc = (struct dump_config *)data;
- size_t shape_id = rb_shape_id(shape);
if (shape_id < dc->shapes_since) {
return;
}
dump_append(dc, "{\"address\":");
- dump_append_ref(dc, (VALUE)shape);
+ dump_append_ref(dc, (VALUE)RSHAPE(shape_id));
dump_append(dc, ", \"type\":\"SHAPE\", \"id\":");
dump_append_sizet(dc, shape_id);
- if (shape->type != SHAPE_ROOT) {
+ if (RSHAPE_TYPE(shape_id) != SHAPE_ROOT) {
dump_append(dc, ", \"parent_id\":");
- dump_append_lu(dc, shape->parent_id);
+ dump_append_lu(dc, RSHAPE_PARENT_RAW_ID(shape_id));
}
dump_append(dc, ", \"depth\":");
- dump_append_sizet(dc, rb_shape_depth(shape));
+ dump_append_sizet(dc, rb_shape_depth(shape_id));
- dump_append(dc, ", \"shape_type\":");
- switch((enum shape_type)shape->type) {
+ switch (RSHAPE_TYPE(shape_id)) {
case SHAPE_ROOT:
- dump_append(dc, "\"ROOT\"");
+ dump_append(dc, ", \"shape_type\":\"ROOT\"");
break;
case SHAPE_IVAR:
- dump_append(dc, "\"IVAR\"");
+ dump_append(dc, ", \"shape_type\":\"IVAR\"");
dump_append(dc, ",\"edge_name\":");
- dump_append_id(dc, shape->edge_name);
+ dump_append_id(dc, RSHAPE_EDGE_NAME(shape_id));
break;
- case SHAPE_FROZEN:
- dump_append(dc, "\"FROZEN\"");
+ case SHAPE_OBJ_ID:
+ dump_append(dc, ", \"shape_type\":\"OBJ_ID\"");
break;
- case SHAPE_T_OBJECT:
- dump_append(dc, "\"T_OBJECT\"");
- break;
- case SHAPE_OBJ_TOO_COMPLEX:
- dump_append(dc, "\"OBJ_TOO_COMPLEX\"");
- break;
- default:
- rb_bug("[objspace] unexpected shape type");
}
dump_append(dc, ", \"edges\":");
- dump_append_sizet(dc, rb_shape_edges_count(shape));
+ dump_append_sizet(dc, rb_shape_edges_count(shape_id));
dump_append(dc, ", \"memsize\":");
- dump_append_sizet(dc, rb_shape_memsize(shape));
+ dump_append_sizet(dc, rb_shape_memsize(shape_id));
dump_append(dc, "}\n");
}
-/* :nodoc: */
static VALUE
-objspace_dump_all(VALUE os, VALUE output, VALUE full, VALUE since, VALUE shapes)
+dump_all_locked(void *args_p)
{
struct dump_config dc = {0,};
+ VALUE output = ((VALUE*)args_p)[0];
+ VALUE full = ((VALUE*)args_p)[1];
+ VALUE since = ((VALUE*)args_p)[2];
+ VALUE shapes = ((VALUE*)args_p)[3];
+
dump_output(&dc, output, full, since, shapes);
if (!dc.partial_dump || dc.since == 0) {
@@ -827,7 +864,7 @@ objspace_dump_all(VALUE os, VALUE output, VALUE full, VALUE since, VALUE shapes)
}
if (RTEST(shapes)) {
- rb_shape_each_shape(shape_i, &dc);
+ rb_shape_each_shape_id(shape_id_i, &dc);
}
/* dump all objects */
@@ -838,17 +875,41 @@ objspace_dump_all(VALUE os, VALUE output, VALUE full, VALUE since, VALUE shapes)
/* :nodoc: */
static VALUE
-objspace_dump_shapes(VALUE os, VALUE output, VALUE shapes)
+objspace_dump_all(VALUE os, VALUE output, VALUE full, VALUE since, VALUE shapes)
+{
+ VALUE args[4];
+ args[0] = output;
+ args[1] = full;
+ args[2] = since;
+ args[3] = shapes;
+ return rb_vm_lock_with_barrier(dump_all_locked, (void*)args);
+}
+
+static VALUE
+dump_shapes_locked(void *args_p)
{
struct dump_config dc = {0,};
+ VALUE output = ((VALUE*)args_p)[0];
+ VALUE shapes = ((VALUE*)args_p)[1];
+
dump_output(&dc, output, Qfalse, Qnil, shapes);
if (RTEST(shapes)) {
- rb_shape_each_shape(shape_i, &dc);
+ rb_shape_each_shape_id(shape_id_i, &dc);
}
return dump_result(&dc);
}
+/* :nodoc: */
+static VALUE
+objspace_dump_shapes(VALUE os, VALUE output, VALUE shapes)
+{
+ VALUE args[2];
+ args[0] = output;
+ args[1] = shapes;
+ return rb_vm_lock_with_barrier(dump_shapes_locked, (void*)args);
+}
+
void
Init_objspace_dump(VALUE rb_mObjSpace)
{
@@ -856,11 +917,11 @@ Init_objspace_dump(VALUE rb_mObjSpace)
#if 0
rb_mObjSpace = rb_define_module("ObjectSpace"); /* let rdoc know */
#endif
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ RB_EXT_RACTOR_SAFE(true);
+#endif
rb_define_module_function(rb_mObjSpace, "_dump", objspace_dump, 2);
rb_define_module_function(rb_mObjSpace, "_dump_all", objspace_dump_all, 4);
rb_define_module_function(rb_mObjSpace, "_dump_shapes", objspace_dump_shapes, 2);
-
- /* force create static IDs */
- rb_obj_gc_flags(rb_mObjSpace, 0, 0);
}
diff --git a/ext/openssl/History.md b/ext/openssl/History.md
index 3249f6617a..419237ff16 100644
--- a/ext/openssl/History.md
+++ b/ext/openssl/History.md
@@ -1,3 +1,194 @@
+Version 4.0.0
+=============
+
+Compatibility
+-------------
+
+* Ruby >= 2.7
+* OpenSSL >= 1.1.1, LibreSSL >= 3.9, and AWS-LC 1.66.0
+ - Removed support for OpenSSL 1.0.2-1.1.0 and LibreSSL 3.1-3.8.
+ [[GitHub #835]](https://github.com/ruby/openssl/issues/835)
+ - Added support for AWS-LC.
+ [[GitHub #833]](https://github.com/ruby/openssl/issues/833)
+
+
+Notable changes
+---------------
+
+* `OpenSSL::SSL`
+ - Reduce overhead when writing to `OpenSSL::SSL::SSLSocket`. `#syswrite` no
+ longer creates a temporary String object.
+ [[GitHub #831]](https://github.com/ruby/openssl/pull/831)
+ - Make `OpenSSL::SSL::SSLContext#min_version=` and `#max_version=` wrap the
+ corresponding OpenSSL APIs directly, and remove the fallback to SSL options.
+ [[GitHub #849]](https://github.com/ruby/openssl/pull/849)
+ - Add `OpenSSL::SSL::SSLContext#sigalgs=` and `#client_sigalgs=` for
+ specifying signature algorithms to use for connections.
+ [[GitHub #895]](https://github.com/ruby/openssl/pull/895)
+ - Rename `OpenSSL::SSL::SSLContext#ecdh_curves=` to `#groups=` following
+ the underlying OpenSSL API rename. This method is no longer specific to
+ ECDHE. The old method remains as an alias.
+ [[GitHub #900]](https://github.com/ruby/openssl/pull/900)
+ - Add `OpenSSL::SSL::SSLSocket#sigalg`, `#peer_sigalg`, and `#group` for
+ getting the signature algorithm and the key agreement group used in the
+ current connection.
+ [[GitHub #908]](https://github.com/ruby/openssl/pull/908)
+ - Enable `SSL_CTX_set_dh_auto()` for servers by default.
+ [[GitHub #924]](https://github.com/ruby/openssl/pull/924)
+ - Improve Ractor compatibility. Note that the internal-use constant
+ `OpenSSL::SSL::SSLContext::DEFAULT_PARAMS` is now frozen.
+ [[GitHub #925]](https://github.com/ruby/openssl/pull/925)
+* `OpenSSL::PKey`
+ - Remove `OpenSSL::PKey::EC::Point#mul` support with array arguments. The
+ underlying OpenSSL API has been removed, and the method has been deprecated
+ since ruby/openssl v3.0.0.
+ [[GitHub #843]](https://github.com/ruby/openssl/pull/843)
+ - `OpenSSL::PKey::{RSA,DSA,DH}#params` uses `nil` to indicate missing fields
+ instead of the number `0`.
+ [[GitHub #774]](https://github.com/ruby/openssl/pull/774)
+ - Unify `OpenSSL::PKey::PKeyError` classes. The former subclasses
+ `OpenSSL::PKey::DHError`, `OpenSSL::PKey::DSAError`,
+ `OpenSSL::PKey::ECError`, and `OpenSSL::PKey::RSAError` have been merged
+ into a single class.
+ [[GitHub #929]](https://github.com/ruby/openssl/pull/929)
+* `OpenSSL::Cipher`
+ - `OpenSSL::Cipher#encrypt` and `#decrypt` no longer accept arguments.
+ Passing passwords has been deprecated since Ruby 1.8.2 (released in 2004).
+ [[GitHub #887]](https://github.com/ruby/openssl/pull/887)
+ - `OpenSSL::Cipher#final` raises `OpenSSL::Cipher::AuthTagError` when the
+ integrity check fails for AEAD ciphers. `OpenSSL::Cipher::AuthTagError` is a
+ new subclass of `OpenSSL::Cipher::CipherError`, which was previously raised.
+ [[GitHub #939]](https://github.com/ruby/openssl/pull/939)
+ - `OpenSSL::Cipher.new` now raises `OpenSSL::Cipher::CipherError` instead of
+ `RuntimeError` when OpenSSL does not recognize the algorithm.
+ [[GitHub #958]](https://github.com/ruby/openssl/pull/958)
+ - Add support for "fetched" cipher algorithms with OpenSSL 3.0 or later.
+ [[GitHub #958]](https://github.com/ruby/openssl/pull/958)
+* `OpenSSL::Digest`
+ - `OpenSSL::Digest.new` now raises `OpenSSL::Digest::DigestError` instead of
+ `RuntimeError` when OpenSSL does not recognize the algorithm.
+ [[GitHub #958]](https://github.com/ruby/openssl/pull/958)
+ - Add support for "fetched" digest algorithms with OpenSSL 3.0 or later.
+ [[GitHub #958]](https://github.com/ruby/openssl/pull/958)
+* `OpenSSL::ASN1.decode` now assumes a 1950-2049 year range for `UTCTime`
+ according to RFC 5280. It previously used a 1969-2068 range. The encoder
+ has always used the 1950-2049 range.
+ [[GitHub #909]](https://github.com/ruby/openssl/pull/909)
+* `OpenSSL::OpenSSLError`, the base class for all ruby/openssl errors, carry
+ an additional attribute `#errors` to keep the content of OpenSSL's error
+ queue. Also, add `#detailed_message` for Ruby 3.2 or later.
+ [[GitHub #976]](https://github.com/ruby/openssl/pull/976)
+* `OpenSSL::PKCS7.new` raises `OpenSSL::PKCS7::PKCS7Error` instead of
+ `ArgumentError` on error to be consistent with other constructors.
+ [[GitHub #983]](https://github.com/ruby/openssl/pull/983)
+
+
+Version 3.3.2
+=============
+
+Merged changes in 3.1.3 and 3.2.3.
+
+
+Version 3.3.1
+=============
+
+Merged changes in 3.1.2 and 3.2.2.
+
+
+Version 3.3.0
+=============
+
+Compatibility
+-------------
+
+* Ruby version: 2.7 or later
+* OpenSSL version: OpenSSL 1.0.2 or later, and LibreSSL 3.1 or later
+
+Notable changes
+---------------
+
+* `OpenSSL::SSL`
+ - `OpenSSL::SSL::SSLSocket#set_params` no longer sets `#min_version=` to TLS
+ 1.0 except when OpenSSL 1.0.2 is used. This has been done to disable
+ SSL 3.0, which is not supported by default in OpenSSL 1.1.0 or later, or in
+ LibreSSL. This lets it respect the system default if the system-wide
+ configuration file specifies a higher minimum protocol version.
+ [[GitHub #710]](https://github.com/ruby/openssl/pull/710)
+ - `OpenSSL::SSL::SSLSocket.new` no longer enables the `OpenSSL::SSL::OP_ALL`
+ SSL options by default and follows the system default.
+ [[GitHub #767]](https://github.com/ruby/openssl/pull/767)
+ - Add the following IO methods to `OpenSSL::SSL::SSLSocket`, which will pass
+ along to the underlying socket: `#local_address`, `#remote_address`,
+ `#close_on_exec=`, `#close_on_exec?`, `#wait`, `#wait_readable`, and
+ `#wait_writable`.
+ [[GitHub #708]](https://github.com/ruby/openssl/pull/708)
+ - Update `OpenSSL::SSL::SSLSocket#gets` to take the `chomp` keyword argument.
+ [[GitHub #708]](https://github.com/ruby/openssl/pull/708)
+ - Make `OpenSSL::SSL::SSLSocket` respect the `IO#timeout` value of the
+ underlying socket on Ruby 3.2 or later. `#timeout` and `#timeout=` methods
+ are also added.
+ [[GitHub #714]](https://github.com/ruby/openssl/pull/714)
+ - Add `OpenSSL::SSL::SSLSocket#close_read` and `#close_write`.
+ [[GitHub #743]](https://github.com/ruby/openssl/pull/743)
+ - Add `OpenSSL::Digest.digests` to get a list of all available digest
+ algorithms.
+ [[GitHub #726]](https://github.com/ruby/openssl/pull/726)
+ - Fix `OpenSSL::SSL::SSLSocket#read_nonblock` clearing the passed String
+ buffer when nothing can be read from the connection.
+ [[GitHub #739]](https://github.com/ruby/openssl/pull/739)
+* Add `#to_text` methods to `OpenSSL::Timestamp::Response`,
+ `OpenSSL::Timestamp::Request`, `OpenSSL::Timestamp::TokenInfo`, and
+ `OpenSSL::PKCS7` to get a human-readable representation of the object.
+ [[GitHub #756]](https://github.com/ruby/openssl/pull/756)
+* Add `OpenSSL::X509::Certificate#tbs_bytes` to get the DER encoding of the
+ TBSCertificate.
+ [[GitHub #753]](https://github.com/ruby/openssl/pull/753)
+* Allow passing `nil` as the digest algorithm to `#sign` methods on
+ `OpenSSL::X509::Certificate`, `OpenSSL::X509::Request`, and
+ `OpenSSL::X509::CRL`. This adds supports for signing with EdDSA keys.
+ [[GitHub #761]](https://github.com/ruby/openssl/pull/761)
+ [[GitHub #804]](https://github.com/ruby/openssl/pull/804)
+* Add `OpenSSL::SSL::SSLSocket#readbyte`.
+ [[GitHub #771]](https://github.com/ruby/openssl/pull/771)
+* Change `OpenSSL::X509::Store#time=` to set the time to the `X509_VERIFY_PARAM`
+ in the `X509_STORE`. This allows `OpenSSL::Timestamp::Response#verify` to
+ verify a signature with the specified timestamp.
+ [[GitHub #770]](https://github.com/ruby/openssl/pull/770)
+* Make `OpenSSL::PKCS7.encrypt`'s third parameter `cipher` mandatory. It had
+ an undocumented default value "RC2-40-CBC", which is not only insecure, but
+ also not supported in OpenSSL 3.0 or later.
+ [[GitHub #796]](https://github.com/ruby/openssl/pull/796)
+* Make `OpenSSL::BN` shareable between ractors when frozen.
+ [[GitHub #808]](https://github.com/ruby/openssl/pull/808)
+* Make `OpenSSL::Config` instances frozen by default, and make it shareable
+ between ractors. `OpenSSL::Config::DEFAULT_CONFIG_FILE` is also frozen.
+ [[GitHub #809]](https://github.com/ruby/openssl/pull/809)
+* Add `OpenSSL::PKCS12#set_mac` to configure the MAC parameters and recalculate
+ a MAC for the content.
+ [[GitHub #788]](https://github.com/ruby/openssl/pull/788)
+
+And various non-user-visible changes and bug fixes. Please see the commit
+history for more details.
+
+
+Version 3.2.3
+=============
+
+Merged changes in 3.1.3.
+
+
+Version 3.2.2
+=============
+
+Merged changes in 3.1.2.
+
+
+Version 3.2.1
+=============
+
+Merged changes in 3.0.3.
+
+
Version 3.2.0
=============
@@ -38,6 +229,39 @@ Notable changes
[[GitHub #141]](https://github.com/ruby/openssl/pull/141)
+Version 3.1.3
+=============
+
+Bug fixes
+---------
+
+* Fix missing NULL check for `EVP_PKEY_get0()` functions with OpenSSL 3.x.
+ [[GitHub #957]](https://github.com/ruby/openssl/pull/957)
+
+
+Version 3.1.2
+=============
+
+Bug fixes
+---------
+
+* Fix crash when attempting to export an incomplete `OpenSSL::PKey::DSA` key.
+ [[GitHub #845]](https://github.com/ruby/openssl/issues/845)
+ [[GitHub #847]](https://github.com/ruby/openssl/pull/847)
+* Remove the `OpenSSL::X509::V_FLAG_CRL_CHECK_ALL` flag from the default store
+ used by `OpenSSL::SSL::SSLContext#set_params`. It causes certificate
+ verification to fail with OpenSSL 3.6.0. It has no effect with any other
+ OpenSSL versions.
+ [[GitHub #949]](https://github.com/ruby/openssl/issues/949)
+ [[GitHub #950]](https://github.com/ruby/openssl/pull/950)
+
+
+Version 3.1.1
+=============
+
+Merged changes in 3.0.3.
+
+
Version 3.1.0
=============
@@ -74,6 +298,31 @@ Notable changes
LibreSSL 3.6 and Ed25519 support in LibreSSL 3.7.
+Version 3.0.3
+=============
+
+Bug fixes
+---------
+
+* Fix a performance regression introduced in v2.1.3 on a buffered write to
+ `SSLSocket`.
+ [[GitHub #706]](https://github.com/ruby/openssl/pull/706)
+* Fix `OpenSSL::PKCS7` to handle PKCS#7 structures without content.
+ [[GitHub #690]](https://github.com/ruby/openssl/pull/690)
+ [[GitHub #752]](https://github.com/ruby/openssl/pull/752)
+* Fix `OpenSSL::ASN1::ObjectId#==` with OIDs without a known name.
+ [[GitHub #791]](https://github.com/ruby/openssl/issues/791)
+ [[GitHub #792]](https://github.com/ruby/openssl/pull/792)
+* Fix `OpenSSL::X509::Certificate#crl_uris` to handle CDP with multiple CRL
+ URIs.
+ [[GitHub #775]](https://github.com/ruby/openssl/issues/775)
+ [[GitHub #776]](https://github.com/ruby/openssl/pull/776)
+* Fix `OpenSSL::Cipher#update` to always make the output buffer `String`
+ independent.
+ [[Bug #20937]](https://bugs.ruby-lang.org/issues/20937)
+ [[GitHub #824]](https://github.com/ruby/openssl/pull/824)
+
+
Version 3.0.2
=============
diff --git a/ext/openssl/depend b/ext/openssl/depend
index 12c6793939..435f4a1c68 100644
--- a/ext/openssl/depend
+++ b/ext/openssl/depend
@@ -142,6 +142,7 @@ ossl.o: $(hdrdir)/ruby/internal/intern/re.h
ossl.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl.o: $(hdrdir)/ruby/internal/intern/select.h
ossl.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl.o: $(hdrdir)/ruby/internal/intern/set.h
ossl.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -172,6 +173,7 @@ ossl.o: $(hdrdir)/ruby/io.h
ossl.o: $(hdrdir)/ruby/missing.h
ossl.o: $(hdrdir)/ruby/onigmo.h
ossl.o: $(hdrdir)/ruby/oniguruma.h
+ossl.o: $(hdrdir)/ruby/ractor.h
ossl.o: $(hdrdir)/ruby/ruby.h
ossl.o: $(hdrdir)/ruby/st.h
ossl.o: $(hdrdir)/ruby/subst.h
@@ -337,6 +339,7 @@ ossl_asn1.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_asn1.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_asn1.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_asn1.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_asn1.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_asn1.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_asn1.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_asn1.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -367,6 +370,7 @@ ossl_asn1.o: $(hdrdir)/ruby/io.h
ossl_asn1.o: $(hdrdir)/ruby/missing.h
ossl_asn1.o: $(hdrdir)/ruby/onigmo.h
ossl_asn1.o: $(hdrdir)/ruby/oniguruma.h
+ossl_asn1.o: $(hdrdir)/ruby/ractor.h
ossl_asn1.o: $(hdrdir)/ruby/ruby.h
ossl_asn1.o: $(hdrdir)/ruby/st.h
ossl_asn1.o: $(hdrdir)/ruby/subst.h
@@ -532,6 +536,7 @@ ossl_bio.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_bio.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_bio.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_bio.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_bio.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_bio.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_bio.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_bio.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -562,6 +567,7 @@ ossl_bio.o: $(hdrdir)/ruby/io.h
ossl_bio.o: $(hdrdir)/ruby/missing.h
ossl_bio.o: $(hdrdir)/ruby/onigmo.h
ossl_bio.o: $(hdrdir)/ruby/oniguruma.h
+ossl_bio.o: $(hdrdir)/ruby/ractor.h
ossl_bio.o: $(hdrdir)/ruby/ruby.h
ossl_bio.o: $(hdrdir)/ruby/st.h
ossl_bio.o: $(hdrdir)/ruby/subst.h
@@ -727,6 +733,7 @@ ossl_bn.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_bn.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_bn.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_bn.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_bn.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_bn.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_bn.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_bn.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -923,6 +930,7 @@ ossl_cipher.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_cipher.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_cipher.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_cipher.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_cipher.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_cipher.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_cipher.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_cipher.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -953,6 +961,7 @@ ossl_cipher.o: $(hdrdir)/ruby/io.h
ossl_cipher.o: $(hdrdir)/ruby/missing.h
ossl_cipher.o: $(hdrdir)/ruby/onigmo.h
ossl_cipher.o: $(hdrdir)/ruby/oniguruma.h
+ossl_cipher.o: $(hdrdir)/ruby/ractor.h
ossl_cipher.o: $(hdrdir)/ruby/ruby.h
ossl_cipher.o: $(hdrdir)/ruby/st.h
ossl_cipher.o: $(hdrdir)/ruby/subst.h
@@ -1118,6 +1127,7 @@ ossl_config.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_config.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_config.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_config.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_config.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_config.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_config.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_config.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -1148,6 +1158,7 @@ ossl_config.o: $(hdrdir)/ruby/io.h
ossl_config.o: $(hdrdir)/ruby/missing.h
ossl_config.o: $(hdrdir)/ruby/onigmo.h
ossl_config.o: $(hdrdir)/ruby/oniguruma.h
+ossl_config.o: $(hdrdir)/ruby/ractor.h
ossl_config.o: $(hdrdir)/ruby/ruby.h
ossl_config.o: $(hdrdir)/ruby/st.h
ossl_config.o: $(hdrdir)/ruby/subst.h
@@ -1313,6 +1324,7 @@ ossl_digest.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_digest.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_digest.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_digest.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_digest.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_digest.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_digest.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_digest.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -1343,6 +1355,7 @@ ossl_digest.o: $(hdrdir)/ruby/io.h
ossl_digest.o: $(hdrdir)/ruby/missing.h
ossl_digest.o: $(hdrdir)/ruby/onigmo.h
ossl_digest.o: $(hdrdir)/ruby/oniguruma.h
+ossl_digest.o: $(hdrdir)/ruby/ractor.h
ossl_digest.o: $(hdrdir)/ruby/ruby.h
ossl_digest.o: $(hdrdir)/ruby/st.h
ossl_digest.o: $(hdrdir)/ruby/subst.h
@@ -1508,6 +1521,7 @@ ossl_engine.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_engine.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_engine.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_engine.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_engine.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_engine.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_engine.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_engine.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -1538,6 +1552,7 @@ ossl_engine.o: $(hdrdir)/ruby/io.h
ossl_engine.o: $(hdrdir)/ruby/missing.h
ossl_engine.o: $(hdrdir)/ruby/onigmo.h
ossl_engine.o: $(hdrdir)/ruby/oniguruma.h
+ossl_engine.o: $(hdrdir)/ruby/ractor.h
ossl_engine.o: $(hdrdir)/ruby/ruby.h
ossl_engine.o: $(hdrdir)/ruby/st.h
ossl_engine.o: $(hdrdir)/ruby/subst.h
@@ -1703,6 +1718,7 @@ ossl_hmac.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_hmac.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_hmac.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_hmac.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_hmac.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_hmac.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_hmac.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_hmac.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -1733,6 +1749,7 @@ ossl_hmac.o: $(hdrdir)/ruby/io.h
ossl_hmac.o: $(hdrdir)/ruby/missing.h
ossl_hmac.o: $(hdrdir)/ruby/onigmo.h
ossl_hmac.o: $(hdrdir)/ruby/oniguruma.h
+ossl_hmac.o: $(hdrdir)/ruby/ractor.h
ossl_hmac.o: $(hdrdir)/ruby/ruby.h
ossl_hmac.o: $(hdrdir)/ruby/st.h
ossl_hmac.o: $(hdrdir)/ruby/subst.h
@@ -1898,6 +1915,7 @@ ossl_kdf.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_kdf.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_kdf.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_kdf.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_kdf.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_kdf.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_kdf.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_kdf.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -1928,6 +1946,7 @@ ossl_kdf.o: $(hdrdir)/ruby/io.h
ossl_kdf.o: $(hdrdir)/ruby/missing.h
ossl_kdf.o: $(hdrdir)/ruby/onigmo.h
ossl_kdf.o: $(hdrdir)/ruby/oniguruma.h
+ossl_kdf.o: $(hdrdir)/ruby/ractor.h
ossl_kdf.o: $(hdrdir)/ruby/ruby.h
ossl_kdf.o: $(hdrdir)/ruby/st.h
ossl_kdf.o: $(hdrdir)/ruby/subst.h
@@ -2093,6 +2112,7 @@ ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -2123,6 +2143,7 @@ ossl_ns_spki.o: $(hdrdir)/ruby/io.h
ossl_ns_spki.o: $(hdrdir)/ruby/missing.h
ossl_ns_spki.o: $(hdrdir)/ruby/onigmo.h
ossl_ns_spki.o: $(hdrdir)/ruby/oniguruma.h
+ossl_ns_spki.o: $(hdrdir)/ruby/ractor.h
ossl_ns_spki.o: $(hdrdir)/ruby/ruby.h
ossl_ns_spki.o: $(hdrdir)/ruby/st.h
ossl_ns_spki.o: $(hdrdir)/ruby/subst.h
@@ -2288,6 +2309,7 @@ ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -2318,6 +2340,7 @@ ossl_ocsp.o: $(hdrdir)/ruby/io.h
ossl_ocsp.o: $(hdrdir)/ruby/missing.h
ossl_ocsp.o: $(hdrdir)/ruby/onigmo.h
ossl_ocsp.o: $(hdrdir)/ruby/oniguruma.h
+ossl_ocsp.o: $(hdrdir)/ruby/ractor.h
ossl_ocsp.o: $(hdrdir)/ruby/ruby.h
ossl_ocsp.o: $(hdrdir)/ruby/st.h
ossl_ocsp.o: $(hdrdir)/ruby/subst.h
@@ -2483,6 +2506,7 @@ ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -2513,6 +2537,7 @@ ossl_pkcs12.o: $(hdrdir)/ruby/io.h
ossl_pkcs12.o: $(hdrdir)/ruby/missing.h
ossl_pkcs12.o: $(hdrdir)/ruby/onigmo.h
ossl_pkcs12.o: $(hdrdir)/ruby/oniguruma.h
+ossl_pkcs12.o: $(hdrdir)/ruby/ractor.h
ossl_pkcs12.o: $(hdrdir)/ruby/ruby.h
ossl_pkcs12.o: $(hdrdir)/ruby/st.h
ossl_pkcs12.o: $(hdrdir)/ruby/subst.h
@@ -2678,6 +2703,7 @@ ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -2708,6 +2734,7 @@ ossl_pkcs7.o: $(hdrdir)/ruby/io.h
ossl_pkcs7.o: $(hdrdir)/ruby/missing.h
ossl_pkcs7.o: $(hdrdir)/ruby/onigmo.h
ossl_pkcs7.o: $(hdrdir)/ruby/oniguruma.h
+ossl_pkcs7.o: $(hdrdir)/ruby/ractor.h
ossl_pkcs7.o: $(hdrdir)/ruby/ruby.h
ossl_pkcs7.o: $(hdrdir)/ruby/st.h
ossl_pkcs7.o: $(hdrdir)/ruby/subst.h
@@ -2873,6 +2900,7 @@ ossl_pkey.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_pkey.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_pkey.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_pkey.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_pkey.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_pkey.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_pkey.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_pkey.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -2903,6 +2931,7 @@ ossl_pkey.o: $(hdrdir)/ruby/io.h
ossl_pkey.o: $(hdrdir)/ruby/missing.h
ossl_pkey.o: $(hdrdir)/ruby/onigmo.h
ossl_pkey.o: $(hdrdir)/ruby/oniguruma.h
+ossl_pkey.o: $(hdrdir)/ruby/ractor.h
ossl_pkey.o: $(hdrdir)/ruby/ruby.h
ossl_pkey.o: $(hdrdir)/ruby/st.h
ossl_pkey.o: $(hdrdir)/ruby/subst.h
@@ -3068,6 +3097,7 @@ ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -3098,6 +3128,7 @@ ossl_pkey_dh.o: $(hdrdir)/ruby/io.h
ossl_pkey_dh.o: $(hdrdir)/ruby/missing.h
ossl_pkey_dh.o: $(hdrdir)/ruby/onigmo.h
ossl_pkey_dh.o: $(hdrdir)/ruby/oniguruma.h
+ossl_pkey_dh.o: $(hdrdir)/ruby/ractor.h
ossl_pkey_dh.o: $(hdrdir)/ruby/ruby.h
ossl_pkey_dh.o: $(hdrdir)/ruby/st.h
ossl_pkey_dh.o: $(hdrdir)/ruby/subst.h
@@ -3263,6 +3294,7 @@ ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -3293,6 +3325,7 @@ ossl_pkey_dsa.o: $(hdrdir)/ruby/io.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/missing.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/onigmo.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/oniguruma.h
+ossl_pkey_dsa.o: $(hdrdir)/ruby/ractor.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/ruby.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/st.h
ossl_pkey_dsa.o: $(hdrdir)/ruby/subst.h
@@ -3458,6 +3491,7 @@ ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -3488,6 +3522,7 @@ ossl_pkey_ec.o: $(hdrdir)/ruby/io.h
ossl_pkey_ec.o: $(hdrdir)/ruby/missing.h
ossl_pkey_ec.o: $(hdrdir)/ruby/onigmo.h
ossl_pkey_ec.o: $(hdrdir)/ruby/oniguruma.h
+ossl_pkey_ec.o: $(hdrdir)/ruby/ractor.h
ossl_pkey_ec.o: $(hdrdir)/ruby/ruby.h
ossl_pkey_ec.o: $(hdrdir)/ruby/st.h
ossl_pkey_ec.o: $(hdrdir)/ruby/subst.h
@@ -3653,6 +3688,7 @@ ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -3683,6 +3719,7 @@ ossl_pkey_rsa.o: $(hdrdir)/ruby/io.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/missing.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/onigmo.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/oniguruma.h
+ossl_pkey_rsa.o: $(hdrdir)/ruby/ractor.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/ruby.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/st.h
ossl_pkey_rsa.o: $(hdrdir)/ruby/subst.h
@@ -3848,6 +3885,7 @@ ossl_provider.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_provider.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_provider.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_provider.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_provider.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_provider.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_provider.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_provider.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -3878,6 +3916,7 @@ ossl_provider.o: $(hdrdir)/ruby/io.h
ossl_provider.o: $(hdrdir)/ruby/missing.h
ossl_provider.o: $(hdrdir)/ruby/onigmo.h
ossl_provider.o: $(hdrdir)/ruby/oniguruma.h
+ossl_provider.o: $(hdrdir)/ruby/ractor.h
ossl_provider.o: $(hdrdir)/ruby/ruby.h
ossl_provider.o: $(hdrdir)/ruby/st.h
ossl_provider.o: $(hdrdir)/ruby/subst.h
@@ -4043,6 +4082,7 @@ ossl_rand.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_rand.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_rand.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_rand.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_rand.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_rand.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_rand.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_rand.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -4073,6 +4113,7 @@ ossl_rand.o: $(hdrdir)/ruby/io.h
ossl_rand.o: $(hdrdir)/ruby/missing.h
ossl_rand.o: $(hdrdir)/ruby/onigmo.h
ossl_rand.o: $(hdrdir)/ruby/oniguruma.h
+ossl_rand.o: $(hdrdir)/ruby/ractor.h
ossl_rand.o: $(hdrdir)/ruby/ruby.h
ossl_rand.o: $(hdrdir)/ruby/st.h
ossl_rand.o: $(hdrdir)/ruby/subst.h
@@ -4238,6 +4279,7 @@ ossl_ssl.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_ssl.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_ssl.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_ssl.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_ssl.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_ssl.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_ssl.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_ssl.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -4268,6 +4310,7 @@ ossl_ssl.o: $(hdrdir)/ruby/io.h
ossl_ssl.o: $(hdrdir)/ruby/missing.h
ossl_ssl.o: $(hdrdir)/ruby/onigmo.h
ossl_ssl.o: $(hdrdir)/ruby/oniguruma.h
+ossl_ssl.o: $(hdrdir)/ruby/ractor.h
ossl_ssl.o: $(hdrdir)/ruby/ruby.h
ossl_ssl.o: $(hdrdir)/ruby/st.h
ossl_ssl.o: $(hdrdir)/ruby/subst.h
@@ -4433,6 +4476,7 @@ ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -4463,6 +4507,7 @@ ossl_ssl_session.o: $(hdrdir)/ruby/io.h
ossl_ssl_session.o: $(hdrdir)/ruby/missing.h
ossl_ssl_session.o: $(hdrdir)/ruby/onigmo.h
ossl_ssl_session.o: $(hdrdir)/ruby/oniguruma.h
+ossl_ssl_session.o: $(hdrdir)/ruby/ractor.h
ossl_ssl_session.o: $(hdrdir)/ruby/ruby.h
ossl_ssl_session.o: $(hdrdir)/ruby/st.h
ossl_ssl_session.o: $(hdrdir)/ruby/subst.h
@@ -4628,6 +4673,7 @@ ossl_ts.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_ts.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_ts.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_ts.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_ts.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_ts.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_ts.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_ts.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -4658,6 +4704,7 @@ ossl_ts.o: $(hdrdir)/ruby/io.h
ossl_ts.o: $(hdrdir)/ruby/missing.h
ossl_ts.o: $(hdrdir)/ruby/onigmo.h
ossl_ts.o: $(hdrdir)/ruby/oniguruma.h
+ossl_ts.o: $(hdrdir)/ruby/ractor.h
ossl_ts.o: $(hdrdir)/ruby/ruby.h
ossl_ts.o: $(hdrdir)/ruby/st.h
ossl_ts.o: $(hdrdir)/ruby/subst.h
@@ -4823,6 +4870,7 @@ ossl_x509.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_x509.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_x509.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_x509.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_x509.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_x509.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_x509.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -4853,6 +4901,7 @@ ossl_x509.o: $(hdrdir)/ruby/io.h
ossl_x509.o: $(hdrdir)/ruby/missing.h
ossl_x509.o: $(hdrdir)/ruby/onigmo.h
ossl_x509.o: $(hdrdir)/ruby/oniguruma.h
+ossl_x509.o: $(hdrdir)/ruby/ractor.h
ossl_x509.o: $(hdrdir)/ruby/ruby.h
ossl_x509.o: $(hdrdir)/ruby/st.h
ossl_x509.o: $(hdrdir)/ruby/subst.h
@@ -5018,6 +5067,7 @@ ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -5048,6 +5098,7 @@ ossl_x509attr.o: $(hdrdir)/ruby/io.h
ossl_x509attr.o: $(hdrdir)/ruby/missing.h
ossl_x509attr.o: $(hdrdir)/ruby/onigmo.h
ossl_x509attr.o: $(hdrdir)/ruby/oniguruma.h
+ossl_x509attr.o: $(hdrdir)/ruby/ractor.h
ossl_x509attr.o: $(hdrdir)/ruby/ruby.h
ossl_x509attr.o: $(hdrdir)/ruby/st.h
ossl_x509attr.o: $(hdrdir)/ruby/subst.h
@@ -5213,6 +5264,7 @@ ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -5243,6 +5295,7 @@ ossl_x509cert.o: $(hdrdir)/ruby/io.h
ossl_x509cert.o: $(hdrdir)/ruby/missing.h
ossl_x509cert.o: $(hdrdir)/ruby/onigmo.h
ossl_x509cert.o: $(hdrdir)/ruby/oniguruma.h
+ossl_x509cert.o: $(hdrdir)/ruby/ractor.h
ossl_x509cert.o: $(hdrdir)/ruby/ruby.h
ossl_x509cert.o: $(hdrdir)/ruby/st.h
ossl_x509cert.o: $(hdrdir)/ruby/subst.h
@@ -5408,6 +5461,7 @@ ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -5438,6 +5492,7 @@ ossl_x509crl.o: $(hdrdir)/ruby/io.h
ossl_x509crl.o: $(hdrdir)/ruby/missing.h
ossl_x509crl.o: $(hdrdir)/ruby/onigmo.h
ossl_x509crl.o: $(hdrdir)/ruby/oniguruma.h
+ossl_x509crl.o: $(hdrdir)/ruby/ractor.h
ossl_x509crl.o: $(hdrdir)/ruby/ruby.h
ossl_x509crl.o: $(hdrdir)/ruby/st.h
ossl_x509crl.o: $(hdrdir)/ruby/subst.h
@@ -5603,6 +5658,7 @@ ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -5633,6 +5689,7 @@ ossl_x509ext.o: $(hdrdir)/ruby/io.h
ossl_x509ext.o: $(hdrdir)/ruby/missing.h
ossl_x509ext.o: $(hdrdir)/ruby/onigmo.h
ossl_x509ext.o: $(hdrdir)/ruby/oniguruma.h
+ossl_x509ext.o: $(hdrdir)/ruby/ractor.h
ossl_x509ext.o: $(hdrdir)/ruby/ruby.h
ossl_x509ext.o: $(hdrdir)/ruby/st.h
ossl_x509ext.o: $(hdrdir)/ruby/subst.h
@@ -5798,6 +5855,7 @@ ossl_x509name.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_x509name.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_x509name.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_x509name.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509name.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_x509name.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_x509name.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_x509name.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -5828,6 +5886,7 @@ ossl_x509name.o: $(hdrdir)/ruby/io.h
ossl_x509name.o: $(hdrdir)/ruby/missing.h
ossl_x509name.o: $(hdrdir)/ruby/onigmo.h
ossl_x509name.o: $(hdrdir)/ruby/oniguruma.h
+ossl_x509name.o: $(hdrdir)/ruby/ractor.h
ossl_x509name.o: $(hdrdir)/ruby/ruby.h
ossl_x509name.o: $(hdrdir)/ruby/st.h
ossl_x509name.o: $(hdrdir)/ruby/subst.h
@@ -5993,6 +6052,7 @@ ossl_x509req.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_x509req.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_x509req.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_x509req.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509req.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_x509req.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_x509req.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_x509req.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -6023,6 +6083,7 @@ ossl_x509req.o: $(hdrdir)/ruby/io.h
ossl_x509req.o: $(hdrdir)/ruby/missing.h
ossl_x509req.o: $(hdrdir)/ruby/onigmo.h
ossl_x509req.o: $(hdrdir)/ruby/oniguruma.h
+ossl_x509req.o: $(hdrdir)/ruby/ractor.h
ossl_x509req.o: $(hdrdir)/ruby/ruby.h
ossl_x509req.o: $(hdrdir)/ruby/st.h
ossl_x509req.o: $(hdrdir)/ruby/subst.h
@@ -6188,6 +6249,7 @@ ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -6218,6 +6280,7 @@ ossl_x509revoked.o: $(hdrdir)/ruby/io.h
ossl_x509revoked.o: $(hdrdir)/ruby/missing.h
ossl_x509revoked.o: $(hdrdir)/ruby/onigmo.h
ossl_x509revoked.o: $(hdrdir)/ruby/oniguruma.h
+ossl_x509revoked.o: $(hdrdir)/ruby/ractor.h
ossl_x509revoked.o: $(hdrdir)/ruby/ruby.h
ossl_x509revoked.o: $(hdrdir)/ruby/st.h
ossl_x509revoked.o: $(hdrdir)/ruby/subst.h
@@ -6383,6 +6446,7 @@ ossl_x509store.o: $(hdrdir)/ruby/internal/intern/re.h
ossl_x509store.o: $(hdrdir)/ruby/internal/intern/ruby.h
ossl_x509store.o: $(hdrdir)/ruby/internal/intern/select.h
ossl_x509store.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ossl_x509store.o: $(hdrdir)/ruby/internal/intern/set.h
ossl_x509store.o: $(hdrdir)/ruby/internal/intern/signal.h
ossl_x509store.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ossl_x509store.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -6413,6 +6477,7 @@ ossl_x509store.o: $(hdrdir)/ruby/io.h
ossl_x509store.o: $(hdrdir)/ruby/missing.h
ossl_x509store.o: $(hdrdir)/ruby/onigmo.h
ossl_x509store.o: $(hdrdir)/ruby/oniguruma.h
+ossl_x509store.o: $(hdrdir)/ruby/ractor.h
ossl_x509store.o: $(hdrdir)/ruby/ruby.h
ossl_x509store.o: $(hdrdir)/ruby/st.h
ossl_x509store.o: $(hdrdir)/ruby/subst.h
diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb
index dd3732d0a8..a897c86b65 100644
--- a/ext/openssl/extconf.rb
+++ b/ext/openssl/extconf.rb
@@ -8,7 +8,7 @@
= Licence
This program is licensed under the same licence as Ruby.
- (See the file 'LICENCE'.)
+ (See the file 'COPYING'.)
=end
require "mkmf"
@@ -34,14 +34,16 @@ if ssl_ldir&.split(File::PATH_SEPARATOR)&.none? { |dir| File.directory?(dir) }
"library directories."
end
-dir_config("kerberos")
-
Logging::message "=== OpenSSL for Ruby configurator ===\n"
$defs.push("-D""OPENSSL_SUPPRESS_DEPRECATED")
-have_func("rb_io_descriptor")
-have_func("rb_io_maybe_wait(0, Qnil, Qnil, Qnil)", "ruby/io.h") # Ruby 3.1
+# Missing in TruffleRuby
+have_func("rb_call_super_kw(0, NULL, 0)", "ruby.h")
+# Ruby 3.1
+have_func("rb_io_descriptor", "ruby/io.h")
+have_func("rb_io_maybe_wait(0, Qnil, Qnil, Qnil)", "ruby/io.h")
+# Ruby 3.2
have_func("rb_io_timeout", "ruby/io.h")
Logging::message "=== Checking for system dependent stuff... ===\n"
@@ -60,7 +62,6 @@ end
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
@@ -77,12 +78,6 @@ def find_openssl_library
return true
end
- # OpenSSL <= 1.0.2: libeay32.lib and ssleay32.lib.
- if have_library("libeay32", "CRYPTO_malloc") &&
- have_library("ssleay32", "SSL_new")
- return true
- end
-
# LibreSSL: libcrypto-##.lib and libssl-##.lib, where ## is the ABI version
# number. We have to find the version number out by scanning libpath.
libpath = $LIBPATH.dup
@@ -120,14 +115,15 @@ 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") }
+ checking_for("LibreSSL version >= 3.9.0") {
+ try_static_assert("LIBRESSL_VERSION_NUMBER >= 0x30900000L", "openssl/opensslv.h") }
else
- checking_for("OpenSSL version >= 1.0.2") {
- try_static_assert("OPENSSL_VERSION_NUMBER >= 0x10002000L", "openssl/opensslv.h") }
+ is_openssl = true
+ checking_for("OpenSSL version >= 1.1.1") {
+ try_static_assert("OPENSSL_VERSION_NUMBER >= 0x10101000L", "openssl/opensslv.h") }
end
unless version_ok
- raise "OpenSSL >= 1.0.2 or LibreSSL >= 3.1.0 is required"
+ raise "OpenSSL >= 1.1.1 or LibreSSL >= 3.9.0 is required"
end
# Prevent wincrypt.h from being included, which defines conflicting macro with openssl/x509.h
@@ -137,66 +133,26 @@ end
Logging::message "=== Checking for OpenSSL features... ===\n"
evp_h = "openssl/evp.h".freeze
-x509_h = "openssl/x509.h".freeze
ts_h = "openssl/ts.h".freeze
ssl_h = "openssl/ssl.h".freeze
# compile options
have_func("RAND_egd()", "openssl/rand.h")
-engines = %w{dynamic 4758cca aep atalla chil
- cswift nuron sureware ubsec padlock capi gmp gost cryptodev}
-engines.each { |name|
- have_func("ENGINE_load_#{name}()", "openssl/engine.h")
-}
-
-# added in 1.1.0
-if !have_struct_member("SSL", "ctx", "openssl/ssl.h") || is_libressl
- $defs.push("-DHAVE_OPAQUE_OPENSSL")
-end
-have_func("EVP_MD_CTX_new()", evp_h)
-have_func("EVP_MD_CTX_free(NULL)", evp_h)
-have_func("EVP_MD_CTX_pkey_ctx(NULL)", evp_h)
-have_func("X509_STORE_get_ex_data(NULL, 0)", x509_h)
-have_func("X509_STORE_set_ex_data(NULL, 0, NULL)", x509_h)
-have_func("X509_STORE_get_ex_new_index(0, NULL, NULL, NULL, NULL)", x509_h)
-have_func("X509_CRL_get0_signature(NULL, NULL, NULL)", x509_h)
-have_func("X509_REQ_get0_signature(NULL, NULL, NULL)", x509_h)
-have_func("X509_REVOKED_get0_serialNumber(NULL)", x509_h)
-have_func("X509_REVOKED_get0_revocationDate(NULL)", x509_h)
-have_func("X509_get0_tbs_sigalg(NULL)", x509_h)
-have_func("X509_STORE_CTX_get0_untrusted(NULL)", x509_h)
-have_func("X509_STORE_CTX_get0_cert(NULL)", x509_h)
-have_func("X509_STORE_CTX_get0_chain(NULL)", x509_h)
-have_func("OCSP_SINGLERESP_get0_id(NULL)", "openssl/ocsp.h")
-have_func("SSL_CTX_get_ciphers(NULL)", ssl_h)
-have_func("X509_up_ref(NULL)", x509_h)
-have_func("X509_CRL_up_ref(NULL)", x509_h)
-have_func("X509_STORE_up_ref(NULL)", x509_h)
-have_func("SSL_SESSION_up_ref(NULL)", ssl_h)
-have_func("EVP_PKEY_up_ref(NULL)", evp_h)
-have_func("SSL_CTX_set_min_proto_version(NULL, 0)", ssl_h)
-have_func("SSL_CTX_get_security_level(NULL)", ssl_h)
-have_func("X509_get0_notBefore(NULL)", x509_h)
-have_func("SSL_SESSION_get_protocol_version(NULL)", ssl_h)
-have_func("TS_STATUS_INFO_get0_status(NULL)", ts_h)
-have_func("TS_STATUS_INFO_get0_text(NULL)", ts_h)
-have_func("TS_STATUS_INFO_get0_failure_info(NULL)", ts_h)
-have_func("TS_VERIFY_CTS_set_certs(NULL, NULL)", ts_h)
-have_func("TS_VERIFY_CTX_set_store(NULL, NULL)", ts_h)
-have_func("TS_VERIFY_CTX_add_flags(NULL, 0)", ts_h)
-have_func("TS_RESP_CTX_set_time_cb(NULL, NULL, NULL)", ts_h)
+
+# added in OpenSSL 1.0.2, not in LibreSSL yet
+have_func("SSL_CTX_set1_sigalgs_list(NULL, NULL)", ssl_h)
+# added in OpenSSL 1.0.2, not in LibreSSL or AWS-LC yet
+have_func("SSL_CTX_set1_client_sigalgs_list(NULL, NULL)", ssl_h)
+
+# added in 1.1.0, currently not in LibreSSL
have_func("EVP_PBE_scrypt(\"\", 0, (unsigned char *)\"\", 0, 0, 0, 0, 0, NULL, 0)", evp_h)
-have_func("SSL_CTX_set_post_handshake_auth(NULL, 0)", ssl_h)
-# added in 1.1.1
+# added in OpenSSL 1.1.1 and LibreSSL 3.5.0, then removed in LibreSSL 4.0.0
have_func("EVP_PKEY_check(NULL)", evp_h)
-have_func("EVP_PKEY_new_raw_private_key(0, NULL, (unsigned char *)\"\", 0)", evp_h)
-have_func("SSL_CTX_set_ciphersuites(NULL, \"\")", ssl_h)
# added in 3.0.0
-have_func("SSL_set0_tmp_dh_pkey(NULL, NULL)", ssl_h)
+have_func("SSL_CTX_set0_tmp_dh_pkey(NULL, NULL)", ssl_h)
have_func("ERR_get_error_all(NULL, NULL, NULL, NULL, NULL)", "openssl/err.h")
-have_func("TS_VERIFY_CTX_set_certs(NULL, NULL)", ts_h)
have_func("SSL_CTX_load_verify_file(NULL, \"\")", ssl_h)
have_func("BN_check_prime(NULL, NULL, NULL)", "openssl/bn.h")
have_func("EVP_MD_CTX_get0_md(NULL)", evp_h)
@@ -204,6 +160,15 @@ have_func("EVP_MD_CTX_get_pkey_ctx(NULL)", evp_h)
have_func("EVP_PKEY_eq(NULL, NULL)", evp_h)
have_func("EVP_PKEY_dup(NULL)", evp_h)
+# added in 3.2.0
+have_func("SSL_get0_group_name(NULL)", ssl_h)
+
+# added in 3.4.0
+have_func("TS_VERIFY_CTX_set0_certs(NULL, NULL)", ts_h)
+
+# added in 3.5.0
+have_func("SSL_get0_peer_signature_name(NULL, NULL)", ssl_h)
+
Logging::message "=== Checking done. ===\n"
# Append flags from environment variables.
diff --git a/ext/openssl/lib/openssl.rb b/ext/openssl/lib/openssl.rb
index 8a342f15b6..98fa8d39f2 100644
--- a/ext/openssl/lib/openssl.rb
+++ b/ext/openssl/lib/openssl.rb
@@ -7,28 +7,32 @@
= Licence
This program is licensed under the same licence as Ruby.
- (See the file 'LICENCE'.)
+ (See the file 'COPYING'.)
=end
require 'openssl.so'
require_relative 'openssl/bn'
-require_relative 'openssl/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/pkey'
+require_relative 'openssl/ssl'
require_relative 'openssl/version'
+require_relative 'openssl/x509'
module OpenSSL
- # call-seq:
- # OpenSSL.secure_compare(string, string) -> boolean
+ # :call-seq:
+ # OpenSSL.secure_compare(string, string) -> true or false
#
# 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.
+ #
+ # This method is expensive due to the SHA-256 hashing. In most cases, where
+ # the input lengths are known to be equal or are not sensitive,
+ # OpenSSL.fixed_length_secure_compare should be used instead.
def self.secure_compare(a, b)
hashed_a = OpenSSL::Digest.digest('SHA256', a)
hashed_b = OpenSSL::Digest.digest('SHA256', b)
diff --git a/ext/openssl/lib/openssl/bn.rb b/ext/openssl/lib/openssl/bn.rb
index 0a5e11b4c2..e4889a140c 100644
--- a/ext/openssl/lib/openssl/bn.rb
+++ b/ext/openssl/lib/openssl/bn.rb
@@ -10,7 +10,7 @@
#
# = Licence
# This program is licensed under the same licence as Ruby.
-# (See the file 'LICENCE'.)
+# (See the file 'COPYING'.)
#++
module OpenSSL
diff --git a/ext/openssl/lib/openssl/buffering.rb b/ext/openssl/lib/openssl/buffering.rb
index 216c51e3be..1464a4292d 100644
--- a/ext/openssl/lib/openssl/buffering.rb
+++ b/ext/openssl/lib/openssl/buffering.rb
@@ -8,7 +8,7 @@
#
#= Licence
# This program is licensed under the same licence as Ruby.
-# (See the file 'LICENCE'.)
+# (See the file 'COPYING'.)
#++
##
@@ -24,25 +24,21 @@ module OpenSSL::Buffering
# A buffer which will retain binary encoding.
class Buffer < String
- BINARY = Encoding::BINARY
-
- def initialize
- super
-
- force_encoding(BINARY)
- end
+ unless String.method_defined?(:append_as_bytes)
+ alias_method :_append, :<<
+ def append_as_bytes(string)
+ if string.encoding == Encoding::BINARY
+ _append(string)
+ else
+ _append(string.b)
+ end
- def << string
- if string.encoding == BINARY
- super(string)
- else
- super(string.b)
+ self
end
-
- return self
end
- alias concat <<
+ undef_method :concat
+ undef_method :<<
end
##
@@ -77,7 +73,7 @@ module OpenSSL::Buffering
def fill_rbuff
begin
- @rbuffer << self.sysread(BLOCK_SIZE)
+ @rbuffer.append_as_bytes(self.sysread(BLOCK_SIZE))
rescue Errno::EAGAIN
retry
rescue EOFError
@@ -107,6 +103,12 @@ module OpenSSL::Buffering
read(1)&.ord
end
+ # Get the next 8bit byte. Raises EOFError on EOF
+ def readbyte
+ raise EOFError if eof?
+ getbyte
+ end
+
##
# Reads _size_ bytes from the stream. If _buf_ is provided it must
# reference a string which will receive the data.
@@ -346,22 +348,32 @@ module OpenSSL::Buffering
def do_write(s)
@wbuffer = Buffer.new unless defined? @wbuffer
- @wbuffer << s
- @wbuffer.force_encoding(Encoding::BINARY)
+ @wbuffer.append_as_bytes(s)
+
@sync ||= false
- buffer_size = @wbuffer.size
+ buffer_size = @wbuffer.bytesize
if @sync or buffer_size > BLOCK_SIZE
nwrote = 0
begin
while nwrote < buffer_size do
begin
- nwrote += syswrite(@wbuffer[nwrote, buffer_size - nwrote])
+ chunk = if nwrote > 0
+ @wbuffer.byteslice(nwrote, @wbuffer.bytesize)
+ else
+ @wbuffer
+ end
+
+ nwrote += syswrite(chunk)
rescue Errno::EAGAIN
retry
end
end
ensure
- @wbuffer[0, nwrote] = ""
+ if nwrote < @wbuffer.bytesize
+ @wbuffer[0, nwrote] = ""
+ else
+ @wbuffer.clear
+ end
end
end
end
@@ -438,10 +450,10 @@ module OpenSSL::Buffering
def puts(*args)
s = Buffer.new
if args.empty?
- s << "\n"
+ s.append_as_bytes("\n")
end
args.each{|arg|
- s << arg.to_s
+ s.append_as_bytes(arg.to_s)
s.sub!(/(?<!\n)\z/, "\n")
}
do_write(s)
@@ -455,7 +467,7 @@ module OpenSSL::Buffering
def print(*args)
s = Buffer.new
- args.each{ |arg| s << arg.to_s }
+ args.each{ |arg| s.append_as_bytes(arg.to_s) }
do_write(s)
nil
end
diff --git a/ext/openssl/lib/openssl/cipher.rb b/ext/openssl/lib/openssl/cipher.rb
index 8ad8c35dd3..ab75ac8e1a 100644
--- a/ext/openssl/lib/openssl/cipher.rb
+++ b/ext/openssl/lib/openssl/cipher.rb
@@ -9,7 +9,7 @@
#
# = Licence
# This program is licensed under the same licence as Ruby.
-# (See the file 'LICENCE'.)
+# (See the file 'COPYING'.)
#++
module OpenSSL
diff --git a/ext/openssl/lib/openssl/digest.rb b/ext/openssl/lib/openssl/digest.rb
index 0f35ddadd3..46ddfd6021 100644
--- a/ext/openssl/lib/openssl/digest.rb
+++ b/ext/openssl/lib/openssl/digest.rb
@@ -9,7 +9,7 @@
#
# = Licence
# This program is licensed under the same licence as Ruby.
-# (See the file 'LICENCE'.)
+# (See the file 'COPYING'.)
#++
module OpenSSL
@@ -57,7 +57,7 @@ module OpenSSL
# OpenSSL::Digest("MD5")
# # => OpenSSL::Digest::MD5
#
- # Digest("Foo")
+ # OpenSSL::Digest("Foo")
# # => NameError: wrong constant name Foo
def Digest(name)
diff --git a/ext/openssl/lib/openssl/marshal.rb b/ext/openssl/lib/openssl/marshal.rb
index af5647192a..eb8eda4748 100644
--- a/ext/openssl/lib/openssl/marshal.rb
+++ b/ext/openssl/lib/openssl/marshal.rb
@@ -9,7 +9,7 @@
#
# = Licence
# This program is licensed under the same licence as Ruby.
-# (See the file 'LICENCE'.)
+# (See the file 'COPYING'.)
#++
module OpenSSL
module Marshal
diff --git a/ext/openssl/lib/openssl/pkey.rb b/ext/openssl/lib/openssl/pkey.rb
index 0414658a10..39871e15dd 100644
--- a/ext/openssl/lib/openssl/pkey.rb
+++ b/ext/openssl/lib/openssl/pkey.rb
@@ -7,6 +7,9 @@
require_relative 'marshal'
module OpenSSL::PKey
+ # Alias of PKeyError. Before version 4.0.0, this was a subclass of PKeyError.
+ DHError = PKeyError
+
class DH
include OpenSSL::Marshal
@@ -35,6 +38,18 @@ module OpenSSL::PKey
end
# :call-seq:
+ # dh.params -> hash
+ #
+ # Stores all parameters of key to a Hash.
+ #
+ # The hash has keys 'p', 'q', 'g', 'pub_key', and 'priv_key'.
+ def params
+ %w{p q g pub_key priv_key}.map { |name|
+ [name, send(name)]
+ }.to_h
+ end
+
+ # :call-seq:
# dh.compute_key(pub_bn) -> string
#
# Returns a String containing a shared secret computed from the other
@@ -90,7 +105,7 @@ module OpenSSL::PKey
# 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; " \
+ raise PKeyError, "OpenSSL::PKey::DH is immutable on OpenSSL 3.0; " \
"use OpenSSL::PKey.generate_key instead"
end
@@ -135,6 +150,9 @@ module OpenSSL::PKey
end
end
+ # Alias of PKeyError. Before version 4.0.0, this was a subclass of PKeyError.
+ DSAError = PKeyError
+
class DSA
include OpenSSL::Marshal
@@ -154,6 +172,18 @@ module OpenSSL::PKey
OpenSSL::PKey.read(public_to_der)
end
+ # :call-seq:
+ # dsa.params -> hash
+ #
+ # Stores all parameters of key to a Hash.
+ #
+ # The hash has keys 'p', 'q', 'g', 'pub_key', and 'priv_key'.
+ def params
+ %w{p q g pub_key priv_key}.map { |name|
+ [name, send(name)]
+ }.to_h
+ end
+
class << self
# :call-seq:
# DSA.generate(size) -> dsa
@@ -218,13 +248,9 @@ module OpenSSL::PKey
# 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
+ q or raise PKeyError, "incomplete DSA"
+ private? or raise PKeyError, "Private DSA key needed!"
+ sign_raw(nil, string)
end
# :call-seq:
@@ -242,12 +268,13 @@ module OpenSSL::PKey
# 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)
+ # Alias of PKeyError. Before version 4.0.0, this was a subclass of PKeyError.
+ ECError = PKeyError
+
class EC
include OpenSSL::Marshal
@@ -258,8 +285,6 @@ module OpenSSL::PKey
# 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:
@@ -269,8 +294,6 @@ module OpenSSL::PKey
# 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:
@@ -310,6 +333,9 @@ module OpenSSL::PKey
end
end
+ # Alias of PKeyError. Before version 4.0.0, this was a subclass of PKeyError.
+ RSAError = PKeyError
+
class RSA
include OpenSSL::Marshal
@@ -328,6 +354,18 @@ module OpenSSL::PKey
OpenSSL::PKey.read(public_to_der)
end
+ # :call-seq:
+ # rsa.params -> hash
+ #
+ # Stores all parameters of key to a Hash.
+ #
+ # The hash has keys 'n', 'e', 'd', 'p', 'q', 'dmp1', 'dmq1', and 'iqmp'.
+ def params
+ %w{n e d p q dmp1 dmq1 iqmp}.map { |name|
+ [name, send(name)]
+ }.to_h
+ end
+
class << self
# :call-seq:
# RSA.generate(size, exponent = 65537) -> RSA
@@ -371,15 +409,11 @@ module OpenSSL::PKey
# 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
+ n or raise PKeyError, "incomplete RSA"
+ private? or raise PKeyError, "private key needed."
+ sign_raw(nil, string, {
+ "rsa_padding_mode" => translate_padding_mode(padding),
+ })
end
# :call-seq:
@@ -394,14 +428,10 @@ module OpenSSL::PKey
# 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
+ n or raise PKeyError, "incomplete RSA"
+ verify_recover(nil, string, {
+ "rsa_padding_mode" => translate_padding_mode(padding),
+ })
end
# :call-seq:
@@ -416,14 +446,10 @@ module OpenSSL::PKey
# <b>Deprecated in version 3.0</b>.
# 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
+ n or raise PKeyError, "incomplete RSA"
+ encrypt(data, {
+ "rsa_padding_mode" => translate_padding_mode(padding),
+ })
end
# :call-seq:
@@ -437,15 +463,11 @@ module OpenSSL::PKey
# <b>Deprecated in version 3.0</b>.
# 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
+ n or raise PKeyError, "incomplete RSA"
+ private? or raise PKeyError, "private key needed."
+ decrypt(data, {
+ "rsa_padding_mode" => translate_padding_mode(padding),
+ })
end
PKCS1_PADDING = 1
@@ -464,7 +486,7 @@ module OpenSSL::PKey
when PKCS1_OAEP_PADDING
"oaep"
else
- raise OpenSSL::PKey::PKeyError, "unsupported padding mode"
+ raise PKeyError, "unsupported padding mode"
end
end
end
diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb
index d28bf1a374..3268c126b9 100644
--- a/ext/openssl/lib/openssl/ssl.rb
+++ b/ext/openssl/lib/openssl/ssl.rb
@@ -7,7 +7,7 @@
= Licence
This program is licensed under the same licence as Ruby.
- (See the file 'LICENCE'.)
+ (See the file 'COPYING'.)
=end
require "openssl/buffering"
@@ -32,27 +32,7 @@ module OpenSSL
}.call
}
- if defined?(OpenSSL::PKey::DH)
- DH_ffdhe2048 = OpenSSL::PKey::DH.new <<-_end_of_pem_
------BEGIN DH PARAMETERS-----
-MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
-+8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
-87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
-YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
-7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
-ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
------END DH PARAMETERS-----
- _end_of_pem_
- private_constant :DH_ffdhe2048
-
- DEFAULT_TMP_DH_CALLBACK = lambda { |ctx, is_export, keylen| # :nodoc:
- warn "using default DH parameters." if $VERBOSE
- DH_ffdhe2048
- }
- end
-
- if !(OpenSSL::OPENSSL_VERSION.start_with?("OpenSSL") &&
- OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10100000)
+ if !OpenSSL::OPENSSL_VERSION.start_with?("OpenSSL")
DEFAULT_PARAMS.merge!(
min_version: OpenSSL::SSL::TLS1_VERSION,
ciphers: %w{
@@ -86,26 +66,13 @@ ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
AES256-SHA256
AES128-SHA
AES256-SHA
- }.join(":"),
+ }.join(":").freeze,
)
end
+ DEFAULT_PARAMS.freeze
DEFAULT_CERT_STORE = OpenSSL::X509::Store.new # :nodoc:
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 for ephemeral DH key
- # exchange.
- #
- # 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.
- #
- # <b>Deprecated in version 3.0.</b> Use #tmp_dh= instead.
- attr_accessor :tmp_dh_callback
# A callback invoked at connect time to distinguish between multiple
# server names.
@@ -125,7 +92,6 @@ ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
# that this form is deprecated. New applications should use #min_version=
# and #max_version= as necessary.
def initialize(version = nil)
- self.options |= OpenSSL::SSL::OP_ALL
self.ssl_version = version if version
self.verify_mode = OpenSSL::SSL::VERIFY_NONE
self.verify_hostname = false
@@ -145,54 +111,24 @@ ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
# used.
def set_params(params={})
params = DEFAULT_PARAMS.merge(params)
- self.options = params.delete(:options) # set before min_version/max_version
+ self.options |= params.delete(:options) # set before min_version/max_version
params.each{|name, value| self.__send__("#{name}=", value) }
if self.verify_mode != OpenSSL::SSL::VERIFY_NONE
unless self.ca_file or self.ca_path or self.cert_store
- self.cert_store = DEFAULT_CERT_STORE
+ if not defined?(Ractor) or Ractor.current == Ractor.main
+ self.cert_store = DEFAULT_CERT_STORE
+ else
+ self.cert_store = Ractor.current[:__openssl_default_store__] ||=
+ OpenSSL::X509::Store.new.tap { |store|
+ store.set_default_paths
+ }
+ end
end
end
return params
end
# call-seq:
- # ctx.min_version = OpenSSL::SSL::TLS1_2_VERSION
- # ctx.min_version = :TLS1_2
- # ctx.min_version = nil
- #
- # Sets the lower bound on the supported SSL/TLS protocol version. The
- # version may be specified by an integer constant named
- # OpenSSL::SSL::*_VERSION, a Symbol, or +nil+ which means "any version".
- #
- # Be careful that you don't overwrite OpenSSL::SSL::OP_NO_{SSL,TLS}v*
- # options by #options= once you have called #min_version= or
- # #max_version=.
- #
- # === Example
- # ctx = OpenSSL::SSL::SSLContext.new
- # ctx.min_version = OpenSSL::SSL::TLS1_1_VERSION
- # ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
- #
- # sock = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx)
- # sock.connect # Initiates a connection using either TLS 1.1 or TLS 1.2
- def min_version=(version)
- set_minmax_proto_version(version, @max_proto_version ||= nil)
- @min_proto_version = version
- end
-
- # call-seq:
- # ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
- # ctx.max_version = :TLS1_2
- # ctx.max_version = nil
- #
- # Sets the upper bound of the supported SSL/TLS protocol version. See
- # #min_version= for the possible values.
- def max_version=(version)
- set_minmax_proto_version(@min_proto_version ||= nil, version)
- @max_proto_version = version
- end
-
- # call-seq:
# ctx.ssl_version = :TLSv1
# ctx.ssl_version = "SSLv23"
#
@@ -216,8 +152,7 @@ ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
end
version = METHODS_MAP[meth.intern] or
raise ArgumentError, "unknown SSL method `%s'" % meth
- set_minmax_proto_version(version, version)
- @min_proto_version = @max_proto_version = version
+ self.min_version = self.max_version = version
end
METHODS_MAP = {
@@ -497,10 +432,6 @@ ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
@context.client_cert_cb
end
- def tmp_dh_callback
- @context.tmp_dh_callback || OpenSSL::SSL::SSLContext::DEFAULT_TMP_DH_CALLBACK
- end
-
def session_new_cb
@context.session_new_cb
end
diff --git a/ext/openssl/lib/openssl/version.rb b/ext/openssl/lib/openssl/version.rb
index 9315a79381..88570562e2 100644
--- a/ext/openssl/lib/openssl/version.rb
+++ b/ext/openssl/lib/openssl/version.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
module OpenSSL
- VERSION = "3.2.0"
+ # The version string of Ruby/OpenSSL.
+ VERSION = "4.0.0"
end
diff --git a/ext/openssl/lib/openssl/x509.rb b/ext/openssl/lib/openssl/x509.rb
index f973f4f4dc..66765ffeab 100644
--- a/ext/openssl/lib/openssl/x509.rb
+++ b/ext/openssl/lib/openssl/x509.rb
@@ -9,7 +9,7 @@
#
# = Licence
# This program is licensed under the same licence as Ruby.
-# (See the file 'LICENCE'.)
+# (See the file 'COPYING'.)
#++
require_relative 'marshal'
@@ -122,8 +122,8 @@ module OpenSSL
include Helpers
# Get the distributionPoint fullName URI from the certificate's CRL
- # distribution points extension, as described in RFC5280 Section
- # 4.2.1.13
+ # distribution points extension, as described in RFC 5280 Section
+ # 4.2.1.13.
#
# Returns an array of strings or nil or raises ASN1::ASN1Error.
def crl_uris
@@ -135,19 +135,19 @@ module OpenSSL
raise ASN1::ASN1Error, "invalid extension"
end
- crl_uris = cdp_asn1.map do |crl_distribution_point|
+ crl_uris = cdp_asn1.flat_map do |crl_distribution_point|
distribution_point = crl_distribution_point.value.find do |v|
v.tag_class == :CONTEXT_SPECIFIC && v.tag == 0
end
full_name = distribution_point&.value&.find do |v|
v.tag_class == :CONTEXT_SPECIFIC && v.tag == 0
end
- full_name&.value&.find do |v|
+ full_name&.value&.select do |v|
v.tag_class == :CONTEXT_SPECIFIC && v.tag == 6 # uniformResourceIdentifier
end
end
- crl_uris&.map(&:value)
+ crl_uris.empty? ? nil : crl_uris.map(&:value)
end
end
@@ -346,6 +346,15 @@ module OpenSSL
include Extension::CRLDistributionPoints
include Extension::AuthorityInfoAccess
+ def inspect
+ "#<#{self.class}: " \
+ "subject=#{subject.inspect}, " \
+ "issuer=#{issuer.inspect}, " \
+ "serial=#{serial.inspect}, " \
+ "not_before=#{not_before.inspect rescue "(error)"}, " \
+ "not_after=#{not_after.inspect rescue "(error)"}>"
+ end
+
def pretty_print(q)
q.object_group(self) {
q.breakable
diff --git a/ext/openssl/openssl.gemspec b/ext/openssl/openssl.gemspec
index 2765f55401..7072d599d8 100644
--- a/ext/openssl/openssl.gemspec
+++ b/ext/openssl/openssl.gemspec
@@ -1,19 +1,20 @@
Gem::Specification.new do |spec|
spec.name = "openssl"
- spec.version = "3.2.0"
+ spec.version = "4.0.0"
spec.authors = ["Martin Bosslet", "SHIBATA Hiroshi", "Zachary Scott", "Kazuki Yamaguchi"]
spec.email = ["ruby-core@ruby-lang.org"]
spec.summary = %q{SSL/TLS and general-purpose cryptography for Ruby}
spec.description = %q{OpenSSL for Ruby provides access to SSL/TLS and general-purpose cryptography based on the OpenSSL library.}
spec.homepage = "https://github.com/ruby/openssl"
- spec.license = "Ruby"
+ spec.licenses = ["Ruby", "BSD-2-Clause"]
if Gem::Platform === spec.platform and spec.platform =~ 'java' or RUBY_ENGINE == 'jruby'
spec.platform = "java"
spec.files = []
spec.add_runtime_dependency('jruby-openssl', '~> 0.14')
else
- spec.files = Dir["lib/**/*.rb", "ext/**/*.{c,h,rb}", "*.md", "BSDL", "LICENSE.txt"]
+ spec.files = Dir.glob(["lib/**/*.rb", "ext/**/*.{c,h,rb}", "*.md"], base: File.expand_path("..", __FILE__)) +
+ ["BSDL", "COPYING"]
spec.require_paths = ["lib"]
spec.extensions = ["ext/openssl/extconf.rb"]
end
diff --git a/ext/openssl/openssl_missing.c b/ext/openssl/openssl_missing.c
deleted file mode 100644
index 4415703db4..0000000000
--- a/ext/openssl/openssl_missing.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 'OpenSSL for Ruby' project
- * Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
- * All rights reserved.
- */
-/*
- * This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
- */
-#include RUBY_EXTCONF_H
-
-#include <string.h> /* memcpy() */
-#include <openssl/x509_vfy.h>
-
-#include "openssl_missing.h"
-
-/*** added in 1.1.0 ***/
-#if !defined(HAVE_X509_CRL_GET0_SIGNATURE)
-void
-ossl_X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig,
- const X509_ALGOR **palg)
-{
- if (psig != NULL)
- *psig = crl->signature;
- if (palg != NULL)
- *palg = crl->sig_alg;
-}
-#endif
-
-#if !defined(HAVE_X509_REQ_GET0_SIGNATURE)
-void
-ossl_X509_REQ_get0_signature(const X509_REQ *req, const ASN1_BIT_STRING **psig,
- const X509_ALGOR **palg)
-{
- if (psig != NULL)
- *psig = req->signature;
- if (palg != NULL)
- *palg = req->sig_alg;
-}
-#endif
diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h
index 8629bfe505..6592f9ccea 100644
--- a/ext/openssl/openssl_missing.h
+++ b/ext/openssl/openssl_missing.h
@@ -5,216 +5,14 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_OPENSSL_MISSING_H_)
#define _OSSL_OPENSSL_MISSING_H_
#include "ruby/config.h"
-/* added in 1.1.0 */
-#if !defined(HAVE_EVP_MD_CTX_NEW)
-# define EVP_MD_CTX_new EVP_MD_CTX_create
-#endif
-
-#if !defined(HAVE_EVP_MD_CTX_FREE)
-# define EVP_MD_CTX_free EVP_MD_CTX_destroy
-#endif
-
-#if !defined(HAVE_X509_STORE_GET_EX_DATA)
-# define X509_STORE_get_ex_data(x, idx) \
- CRYPTO_get_ex_data(&(x)->ex_data, (idx))
-#endif
-
-#if !defined(HAVE_X509_STORE_SET_EX_DATA)
-# define X509_STORE_set_ex_data(x, idx, data) \
- CRYPTO_set_ex_data(&(x)->ex_data, (idx), (data))
-#endif
-
-#if !defined(HAVE_X509_STORE_GET_EX_NEW_INDEX) && !defined(X509_STORE_get_ex_new_index)
-# define X509_STORE_get_ex_new_index(l, p, newf, dupf, freef) \
- CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE, (l), (p), \
- (newf), (dupf), (freef))
-#endif
-
-#if !defined(HAVE_X509_CRL_GET0_SIGNATURE)
-void ossl_X509_CRL_get0_signature(const X509_CRL *, const ASN1_BIT_STRING **, const X509_ALGOR **);
-# define X509_CRL_get0_signature ossl_X509_CRL_get0_signature
-#endif
-
-#if !defined(HAVE_X509_REQ_GET0_SIGNATURE)
-void ossl_X509_REQ_get0_signature(const X509_REQ *, const ASN1_BIT_STRING **, const X509_ALGOR **);
-# define X509_REQ_get0_signature ossl_X509_REQ_get0_signature
-#endif
-
-#if !defined(HAVE_X509_REVOKED_GET0_SERIALNUMBER)
-# define X509_REVOKED_get0_serialNumber(x) ((x)->serialNumber)
-#endif
-
-#if !defined(HAVE_X509_REVOKED_GET0_REVOCATIONDATE)
-# define X509_REVOKED_get0_revocationDate(x) ((x)->revocationDate)
-#endif
-
-#if !defined(HAVE_X509_GET0_TBS_SIGALG)
-# define X509_get0_tbs_sigalg(x) ((x)->cert_info->signature)
-#endif
-
-#if !defined(HAVE_X509_STORE_CTX_GET0_UNTRUSTED)
-# define X509_STORE_CTX_get0_untrusted(x) ((x)->untrusted)
-#endif
-
-#if !defined(HAVE_X509_STORE_CTX_GET0_CERT)
-# define X509_STORE_CTX_get0_cert(x) ((x)->cert)
-#endif
-
-#if !defined(HAVE_X509_STORE_CTX_GET0_CHAIN)
-# define X509_STORE_CTX_get0_chain(ctx) X509_STORE_CTX_get_chain(ctx)
-#endif
-
-#if !defined(HAVE_OCSP_SINGLERESP_GET0_ID)
-# define OCSP_SINGLERESP_get0_id(s) ((s)->certId)
-#endif
-
-#if !defined(HAVE_SSL_CTX_GET_CIPHERS)
-# define SSL_CTX_get_ciphers(ctx) ((ctx)->cipher_list)
-#endif
-
-#if !defined(HAVE_X509_UP_REF)
-# define X509_up_ref(x) \
- CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_X509)
-#endif
-
-#if !defined(HAVE_X509_CRL_UP_REF)
-# define X509_CRL_up_ref(x) \
- CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_X509_CRL);
-#endif
-
-#if !defined(HAVE_X509_STORE_UP_REF)
-# define X509_STORE_up_ref(x) \
- CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_X509_STORE);
-#endif
-
-#if !defined(HAVE_SSL_SESSION_UP_REF)
-# define SSL_SESSION_up_ref(x) \
- CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_SSL_SESSION);
-#endif
-
-#if !defined(HAVE_EVP_PKEY_UP_REF)
-# define EVP_PKEY_up_ref(x) \
- CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_EVP_PKEY);
-#endif
-
-#if !defined(HAVE_OPAQUE_OPENSSL)
-#define IMPL_PKEY_GETTER(_type, _name) \
-static inline _type *EVP_PKEY_get0_##_type(EVP_PKEY *pkey) { \
- return pkey->pkey._name; }
-#define IMPL_KEY_ACCESSOR2(_type, _group, a1, a2, _fail_cond) \
-static inline void _type##_get0_##_group(const _type *obj, const BIGNUM **a1, const BIGNUM **a2) { \
- if (a1) *a1 = obj->a1; \
- if (a2) *a2 = obj->a2; } \
-static inline int _type##_set0_##_group(_type *obj, BIGNUM *a1, BIGNUM *a2) { \
- if (_fail_cond) return 0; \
- BN_clear_free(obj->a1); obj->a1 = a1; \
- BN_clear_free(obj->a2); obj->a2 = a2; \
- return 1; }
-#define IMPL_KEY_ACCESSOR3(_type, _group, a1, a2, a3, _fail_cond) \
-static inline void _type##_get0_##_group(const _type *obj, const BIGNUM **a1, const BIGNUM **a2, const BIGNUM **a3) { \
- if (a1) *a1 = obj->a1; \
- if (a2) *a2 = obj->a2; \
- if (a3) *a3 = obj->a3; } \
-static inline int _type##_set0_##_group(_type *obj, BIGNUM *a1, BIGNUM *a2, BIGNUM *a3) { \
- if (_fail_cond) return 0; \
- BN_clear_free(obj->a1); obj->a1 = a1; \
- BN_clear_free(obj->a2); obj->a2 = a2; \
- BN_clear_free(obj->a3); obj->a3 = a3; \
- return 1; }
-
-#if !defined(OPENSSL_NO_RSA)
-IMPL_PKEY_GETTER(RSA, rsa)
-IMPL_KEY_ACCESSOR3(RSA, key, n, e, d, (n == obj->n || e == obj->e || (obj->d && d == obj->d)))
-IMPL_KEY_ACCESSOR2(RSA, factors, p, q, (p == obj->p || q == obj->q))
-IMPL_KEY_ACCESSOR3(RSA, crt_params, dmp1, dmq1, iqmp, (dmp1 == obj->dmp1 || dmq1 == obj->dmq1 || iqmp == obj->iqmp))
-#endif
-
-#if !defined(OPENSSL_NO_DSA)
-IMPL_PKEY_GETTER(DSA, dsa)
-IMPL_KEY_ACCESSOR2(DSA, key, pub_key, priv_key, (pub_key == obj->pub_key || (obj->priv_key && priv_key == obj->priv_key)))
-IMPL_KEY_ACCESSOR3(DSA, pqg, p, q, g, (p == obj->p || q == obj->q || g == obj->g))
-#endif
-
-#if !defined(OPENSSL_NO_DH)
-IMPL_PKEY_GETTER(DH, dh)
-IMPL_KEY_ACCESSOR2(DH, key, pub_key, priv_key, (pub_key == obj->pub_key || (obj->priv_key && priv_key == obj->priv_key)))
-IMPL_KEY_ACCESSOR3(DH, pqg, p, q, g, (p == obj->p || (obj->q && q == obj->q) || g == obj->g))
-static inline ENGINE *DH_get0_engine(DH *dh) { return dh->engine; }
-#endif
-
-#if !defined(OPENSSL_NO_EC)
-IMPL_PKEY_GETTER(EC_KEY, ec)
-#endif
-
-#undef IMPL_PKEY_GETTER
-#undef IMPL_KEY_ACCESSOR2
-#undef IMPL_KEY_ACCESSOR3
-#endif /* HAVE_OPAQUE_OPENSSL */
-
-#if !defined(EVP_CTRL_AEAD_GET_TAG)
-# define EVP_CTRL_AEAD_GET_TAG EVP_CTRL_GCM_GET_TAG
-# define EVP_CTRL_AEAD_SET_TAG EVP_CTRL_GCM_SET_TAG
-# define EVP_CTRL_AEAD_SET_IVLEN EVP_CTRL_GCM_SET_IVLEN
-#endif
-
-#if !defined(HAVE_X509_GET0_NOTBEFORE)
-# define X509_get0_notBefore(x) X509_get_notBefore(x)
-# define X509_get0_notAfter(x) X509_get_notAfter(x)
-# define X509_CRL_get0_lastUpdate(x) X509_CRL_get_lastUpdate(x)
-# define X509_CRL_get0_nextUpdate(x) X509_CRL_get_nextUpdate(x)
-# define X509_set1_notBefore(x, t) X509_set_notBefore(x, t)
-# define X509_set1_notAfter(x, t) X509_set_notAfter(x, t)
-# define X509_CRL_set1_lastUpdate(x, t) X509_CRL_set_lastUpdate(x, t)
-# define X509_CRL_set1_nextUpdate(x, t) X509_CRL_set_nextUpdate(x, t)
-#endif
-
-#if !defined(HAVE_SSL_SESSION_GET_PROTOCOL_VERSION)
-# define SSL_SESSION_get_protocol_version(s) ((s)->ssl_version)
-#endif
-
-#if !defined(HAVE_TS_STATUS_INFO_GET0_STATUS)
-# define TS_STATUS_INFO_get0_status(a) ((a)->status)
-#endif
-
-#if !defined(HAVE_TS_STATUS_INFO_GET0_TEXT)
-# define TS_STATUS_INFO_get0_text(a) ((a)->text)
-#endif
-
-#if !defined(HAVE_TS_STATUS_INFO_GET0_FAILURE_INFO)
-# define TS_STATUS_INFO_get0_failure_info(a) ((a)->failure_info)
-#endif
-
-#if !defined(HAVE_TS_VERIFY_CTS_SET_CERTS)
-# define TS_VERIFY_CTS_set_certs(ctx, crts) ((ctx)->certs=(crts))
-#endif
-
-#if !defined(HAVE_TS_VERIFY_CTX_SET_STORE)
-# define TS_VERIFY_CTX_set_store(ctx, str) ((ctx)->store=(str))
-#endif
-
-#if !defined(HAVE_TS_VERIFY_CTX_ADD_FLAGS)
-# define TS_VERIFY_CTX_add_flags(ctx, f) ((ctx)->flags |= (f))
-#endif
-
-#if !defined(HAVE_TS_RESP_CTX_SET_TIME_CB)
-# define TS_RESP_CTX_set_time_cb(ctx, callback, dta) do { \
- (ctx)->time_cb = (callback); \
- (ctx)->time_cb_data = (dta); \
- } while (0)
-#endif
-
/* added in 3.0.0 */
-#if !defined(HAVE_TS_VERIFY_CTX_SET_CERTS)
-# define TS_VERIFY_CTX_set_certs(ctx, crts) TS_VERIFY_CTS_set_certs(ctx, crts)
-#endif
-
#ifndef HAVE_EVP_MD_CTX_GET0_MD
# define EVP_MD_CTX_get0_md(ctx) EVP_MD_CTX_md(ctx)
#endif
@@ -224,11 +22,7 @@ IMPL_PKEY_GETTER(EC_KEY, ec)
* EVP_MD_CTX_get_pkey_ctx(x) in OpenSSL 3.0.
*/
#ifndef HAVE_EVP_MD_CTX_GET_PKEY_CTX
-# ifdef HAVE_EVP_MD_CTX_PKEY_CTX
# define EVP_MD_CTX_get_pkey_ctx(x) EVP_MD_CTX_pkey_ctx(x)
-# else
-# define EVP_MD_CTX_get_pkey_ctx(x) (x)->pctx
-# endif
#endif
#ifndef HAVE_EVP_PKEY_EQ
diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c
index 00eded55cb..98127fcba0 100644
--- a/ext/openssl/ossl.c
+++ b/ext/openssl/ossl.c
@@ -5,93 +5,79 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
#include <stdarg.h> /* for ossl_raise */
-/* OpenSSL >= 1.1.0 and LibreSSL >= 2.9.0 */
-#if defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER >= 0x10100000
-# define HAVE_OPENSSL_110_THREADING_API
-#else
-# include <ruby/thread_native.h>
-#endif
-
/*
* Data Conversion
*/
-#define OSSL_IMPL_ARY2SK(name, type, expected_class, dup) \
-VALUE \
-ossl_##name##_ary2sk0(VALUE ary) \
-{ \
- STACK_OF(type) *sk; \
- VALUE val; \
- type *x; \
- int i; \
- \
- Check_Type(ary, T_ARRAY); \
- sk = sk_##type##_new_null(); \
- if (!sk) ossl_raise(eOSSLError, NULL); \
- \
- for (i = 0; i < RARRAY_LEN(ary); i++) { \
- val = rb_ary_entry(ary, i); \
- if (!rb_obj_is_kind_of(val, expected_class)) { \
- sk_##type##_pop_free(sk, type##_free); \
- ossl_raise(eOSSLError, "object in array not" \
- " of class ##type##"); \
- } \
- x = dup(val); /* NEED TO DUP */ \
- sk_##type##_push(sk, x); \
- } \
- return (VALUE)sk; \
-} \
- \
-STACK_OF(type) * \
-ossl_protect_##name##_ary2sk(VALUE ary, int *status) \
-{ \
- return (STACK_OF(type)*)rb_protect( \
- (VALUE (*)(VALUE))ossl_##name##_ary2sk0, \
- ary, \
- status); \
-} \
- \
-STACK_OF(type) * \
-ossl_##name##_ary2sk(VALUE ary) \
-{ \
- STACK_OF(type) *sk; \
- int status = 0; \
- \
- sk = ossl_protect_##name##_ary2sk(ary, &status); \
- if (status) rb_jump_tag(status); \
- \
- return sk; \
+#define OSSL_IMPL_ARY2SK(name, type, expected_class, dup) \
+VALUE \
+ossl_##name##_ary2sk0(VALUE ary) \
+{ \
+ STACK_OF(type) *sk; \
+ VALUE val; \
+ type *x; \
+ int i; \
+ \
+ Check_Type(ary, T_ARRAY); \
+ sk = sk_##type##_new_null(); \
+ if (!sk) ossl_raise(eOSSLError, NULL); \
+ \
+ for (i = 0; i < RARRAY_LEN(ary); i++) { \
+ val = rb_ary_entry(ary, i); \
+ if (!rb_obj_is_kind_of(val, expected_class)) { \
+ sk_##type##_pop_free(sk, type##_free); \
+ ossl_raise(eOSSLError, "object in array not" \
+ " of class ##type##"); \
+ } \
+ x = dup(val); /* NEED TO DUP */ \
+ sk_##type##_push(sk, x); \
+ } \
+ return (VALUE)sk; \
+} \
+ \
+STACK_OF(type) * \
+ossl_protect_##name##_ary2sk(VALUE ary, int *status) \
+{ \
+ return (STACK_OF(type)*)rb_protect( \
+ (VALUE (*)(VALUE))ossl_##name##_ary2sk0, \
+ ary, \
+ status); \
+} \
+ \
+STACK_OF(type) * \
+ossl_##name##_ary2sk(VALUE ary) \
+{ \
+ STACK_OF(type) *sk; \
+ int status = 0; \
+ \
+ sk = ossl_protect_##name##_ary2sk(ary, &status); \
+ if (status) rb_jump_tag(status); \
+ \
+ return sk; \
}
OSSL_IMPL_ARY2SK(x509, X509, cX509Cert, DupX509CertPtr)
-#define OSSL_IMPL_SK2ARY(name, type) \
-VALUE \
-ossl_##name##_sk2ary(const STACK_OF(type) *sk) \
-{ \
- type *t; \
- int i, num; \
- VALUE ary; \
- \
- if (!sk) { \
- OSSL_Debug("empty sk!"); \
- return Qnil; \
- } \
- num = sk_##type##_num(sk); \
- if (num < 0) { \
- OSSL_Debug("items in sk < -1???"); \
- return rb_ary_new(); \
- } \
- ary = rb_ary_new2(num); \
- \
- for (i=0; i<num; i++) { \
- t = sk_##type##_value(sk, i); \
- rb_ary_push(ary, ossl_##name##_new(t)); \
- } \
- return ary; \
+#define OSSL_IMPL_SK2ARY(name, type) \
+VALUE \
+ossl_##name##_sk2ary(const STACK_OF(type) *sk) \
+{ \
+ type *t; \
+ int i, num; \
+ VALUE ary; \
+ \
+ RUBY_ASSERT(sk != NULL); \
+ num = sk_##type##_num(sk); \
+ ary = rb_ary_new_capa(num); \
+ \
+ for (i=0; i<num; i++) { \
+ t = sk_##type##_value(sk, i); \
+ rb_ary_push(ary, ossl_##name##_new(t)); \
+ } \
+ return ary; \
}
OSSL_IMPL_SK2ARY(x509, X509)
OSSL_IMPL_SK2ARY(x509crl, X509_CRL)
@@ -111,14 +97,14 @@ ossl_str_new(const char *ptr, long len, int *pstate)
str = rb_protect(ossl_str_new_i, len, &state);
if (pstate)
- *pstate = state;
+ *pstate = state;
if (state) {
- if (!pstate)
- rb_set_errinfo(Qnil);
- return Qnil;
+ if (!pstate)
+ rb_set_errinfo(Qnil);
+ return Qnil;
}
if (ptr)
- memcpy(RSTRING_PTR(str), ptr, len);
+ memcpy(RSTRING_PTR(str), ptr, len);
return str;
}
@@ -131,22 +117,22 @@ ossl_buf2str(char *buf, int len)
str = ossl_str_new(buf, len, &state);
OPENSSL_free(buf);
if (state)
- rb_jump_tag(state);
+ rb_jump_tag(state);
return str;
}
void
-ossl_bin2hex(unsigned char *in, char *out, size_t inlen)
+ossl_bin2hex(const unsigned char *in, char *out, size_t inlen)
{
const char *hex = "0123456789abcdef";
size_t i;
assert(inlen <= LONG_MAX / 2);
for (i = 0; i < inlen; i++) {
- unsigned char p = in[i];
+ unsigned char p = in[i];
- out[i * 2 + 0] = hex[p >> 4];
- out[i * 2 + 1] = hex[p & 0x0f];
+ out[i * 2 + 0] = hex[p >> 4];
+ out[i * 2 + 1] = hex[p & 0x0f];
}
}
@@ -157,14 +143,14 @@ VALUE
ossl_pem_passwd_value(VALUE pass)
{
if (NIL_P(pass))
- return Qnil;
+ return Qnil;
StringValue(pass);
/* PEM_BUFSIZE is currently used as the second argument of pem_password_cb,
* that is +max_len+ of ossl_pem_passwd_cb() */
if (RSTRING_LEN(pass) > PEM_BUFSIZE)
- ossl_raise(eOSSLError, "password must not be longer than %d bytes", PEM_BUFSIZE);
+ ossl_raise(eOSSLError, "password must not be longer than %d bytes", PEM_BUFSIZE);
return pass;
}
@@ -174,7 +160,7 @@ ossl_pem_passwd_cb0(VALUE flag)
{
VALUE pass = rb_yield(flag);
if (NIL_P(pass))
- return Qnil;
+ return Qnil;
StringValue(pass);
return pass;
}
@@ -187,46 +173,46 @@ ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd_)
VALUE rflag, pass = (VALUE)pwd_;
if (RTEST(pass)) {
- /* PEM_def_callback(buf, max_len, flag, StringValueCStr(pass)) does not
- * work because it does not allow NUL characters and truncates to 1024
- * bytes silently if the input is over 1024 bytes */
- if (RB_TYPE_P(pass, T_STRING)) {
- len = RSTRING_LEN(pass);
- if (len <= max_len) {
- memcpy(buf, RSTRING_PTR(pass), len);
- return (int)len;
- }
- }
- OSSL_Debug("passed data is not valid String???");
- return -1;
+ /* PEM_def_callback(buf, max_len, flag, StringValueCStr(pass)) does not
+ * work because it does not allow NUL characters and truncates to 1024
+ * bytes silently if the input is over 1024 bytes */
+ if (RB_TYPE_P(pass, T_STRING)) {
+ len = RSTRING_LEN(pass);
+ if (len <= max_len) {
+ memcpy(buf, RSTRING_PTR(pass), len);
+ return (int)len;
+ }
+ }
+ OSSL_Debug("passed data is not valid String???");
+ return -1;
}
if (!rb_block_given_p()) {
- return PEM_def_callback(buf, max_len, flag, NULL);
+ return PEM_def_callback(buf, max_len, flag, NULL);
}
while (1) {
- /*
- * when the flag is nonzero, this password
- * will be used to perform encryption; otherwise it will
- * be used to perform decryption.
- */
- rflag = flag ? Qtrue : Qfalse;
- pass = rb_protect(ossl_pem_passwd_cb0, rflag, &status);
- if (status) {
- /* ignore an exception raised. */
- rb_set_errinfo(Qnil);
- return -1;
- }
- if (NIL_P(pass))
- return -1;
- len = RSTRING_LEN(pass);
- if (len > max_len) {
- rb_warning("password must not be longer than %d bytes", max_len);
- continue;
- }
- memcpy(buf, RSTRING_PTR(pass), len);
- break;
+ /*
+ * when the flag is nonzero, this password
+ * will be used to perform encryption; otherwise it will
+ * be used to perform decryption.
+ */
+ rflag = flag ? Qtrue : Qfalse;
+ pass = rb_protect(ossl_pem_passwd_cb0, rflag, &status);
+ if (status) {
+ /* ignore an exception raised. */
+ rb_set_errinfo(Qnil);
+ return -1;
+ }
+ if (NIL_P(pass))
+ return -1;
+ len = RSTRING_LEN(pass);
+ if (len > max_len) {
+ rb_warning("password must not be longer than %d bytes", max_len);
+ continue;
+ }
+ memcpy(buf, RSTRING_PTR(pass), len);
+ break;
}
return (int)len;
}
@@ -261,19 +247,24 @@ VALUE
ossl_to_der_if_possible(VALUE obj)
{
if(rb_respond_to(obj, ossl_s_to_der))
- return ossl_to_der(obj);
+ return ossl_to_der(obj);
return obj;
}
/*
* Errors
*/
+static ID id_i_errors;
+
+static void collect_errors_into(VALUE ary);
+
VALUE
ossl_make_error(VALUE exc, VALUE str)
{
unsigned long e;
const char *data;
int flags;
+ VALUE errors = rb_ary_new();
if (NIL_P(str))
str = rb_str_new(NULL, 0);
@@ -290,10 +281,12 @@ ossl_make_error(VALUE exc, VALUE str)
rb_str_cat_cstr(str, msg ? msg : "(null)");
if (flags & ERR_TXT_STRING && data)
rb_str_catf(str, " (%s)", data);
- ossl_clear_error();
+ collect_errors_into(errors);
}
- return rb_exc_new_str(exc, str);
+ VALUE obj = rb_exc_new_str(exc, str);
+ rb_ivar_set(obj, id_i_errors, errors);
+ return obj;
}
void
@@ -303,24 +296,23 @@ ossl_raise(VALUE exc, const char *fmt, ...)
VALUE err;
if (fmt) {
- va_start(args, fmt);
- err = rb_vsprintf(fmt, args);
- va_end(args);
+ va_start(args, fmt);
+ err = rb_vsprintf(fmt, args);
+ va_end(args);
}
else {
- err = Qnil;
+ err = Qnil;
}
rb_exc_raise(ossl_make_error(exc, err));
}
-void
-ossl_clear_error(void)
+static void
+collect_errors_into(VALUE ary)
{
- if (dOSSL == Qtrue) {
+ if (dOSSL == Qtrue || !NIL_P(ary)) {
unsigned long e;
const char *file, *data, *func, *lib, *reason;
- char append[256] = "";
int line, flags;
#ifdef HAVE_ERR_GET_ERROR_ALL
@@ -332,13 +324,18 @@ ossl_clear_error(void)
lib = ERR_lib_error_string(e);
reason = ERR_reason_error_string(e);
+ VALUE str = rb_sprintf("error:%08lX:%s:%s:%s", e, lib ? lib : "",
+ func ? func : "", reason ? reason : "");
if (flags & ERR_TXT_STRING) {
if (!data)
data = "(null)";
- snprintf(append, sizeof(append), " (%s)", data);
+ rb_str_catf(str, " (%s)", data);
}
- rb_warn("error on stack: error:%08lX:%s:%s:%s%s", e, lib ? lib : "",
- func ? func : "", reason ? reason : "", append);
+
+ if (dOSSL == Qtrue)
+ rb_warn("error on stack: %"PRIsVALUE, str);
+ if (!NIL_P(ary))
+ rb_ary_push(ary, str);
}
}
else {
@@ -346,16 +343,61 @@ ossl_clear_error(void)
}
}
+void
+ossl_clear_error(void)
+{
+ collect_errors_into(Qnil);
+}
+
+/*
+ * call-seq:
+ * ossl_error.detailed_message(**) -> string
+ *
+ * Returns the exception message decorated with the captured \OpenSSL error
+ * queue entries.
+ */
+static VALUE
+osslerror_detailed_message(int argc, VALUE *argv, VALUE self)
+{
+ VALUE str;
+#ifdef HAVE_RB_CALL_SUPER_KW
+ // Ruby >= 3.2
+ if (RTEST(rb_funcall(rb_eException, rb_intern("method_defined?"), 1,
+ ID2SYM(rb_intern("detailed_message")))))
+ str = rb_call_super_kw(argc, argv, RB_PASS_CALLED_KEYWORDS);
+ else
+#endif
+ str = rb_funcall(self, rb_intern("message"), 0);
+ VALUE errors = rb_attr_get(self, id_i_errors);
+
+ // OpenSSLError was not created by ossl_make_error()
+ if (!RB_TYPE_P(errors, T_ARRAY))
+ return str;
+
+ str = rb_str_resurrect(str);
+ rb_str_catf(str, "\nOpenSSL error queue reported %ld errors:",
+ RARRAY_LEN(errors));
+ for (long i = 0; i < RARRAY_LEN(errors); i++) {
+ VALUE err = RARRAY_AREF(errors, i);
+ rb_str_catf(str, "\n%"PRIsVALUE, err);
+ }
+ return str;
+}
+
/*
* call-seq:
* OpenSSL.errors -> [String...]
*
- * See any remaining errors held in queue.
+ * Returns any remaining errors held in the \OpenSSL thread-local error queue
+ * and clears the queue. This should normally return an empty array.
+ *
+ * This is intended for debugging Ruby/OpenSSL. If you see any errors here,
+ * it likely indicates a bug in the extension. Please file an issue at
+ * https://github.com/ruby/openssl.
*
- * Any errors you see here are probably due to a bug in Ruby's OpenSSL
- * implementation.
+ * For debugging your program, OpenSSL.debug= may be useful.
*/
-VALUE
+static VALUE
ossl_get_errors(VALUE _)
{
VALUE ary;
@@ -377,6 +419,8 @@ VALUE dOSSL;
/*
* call-seq:
* OpenSSL.debug -> true | false
+ *
+ * Returns whether Ruby/OpenSSL's debug mode is currently enabled.
*/
static VALUE
ossl_debug_get(VALUE self)
@@ -386,9 +430,9 @@ ossl_debug_get(VALUE self)
/*
* call-seq:
- * OpenSSL.debug = boolean -> boolean
+ * OpenSSL.debug = boolean
*
- * Turns on or off debug mode. With debug mode, all errors 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
@@ -402,6 +446,8 @@ ossl_debug_set(VALUE self, VALUE val)
/*
* call-seq:
* OpenSSL.fips_mode -> true | false
+ *
+ * Returns whether the FIPS mode is currently enabled.
*/
static VALUE
ossl_fips_mode_get(VALUE self)
@@ -411,7 +457,7 @@ ossl_fips_mode_get(VALUE self)
VALUE enabled;
enabled = EVP_default_properties_is_fips_enabled(NULL) ? Qtrue : Qfalse;
return enabled;
-#elif defined(OPENSSL_FIPS)
+#elif defined(OPENSSL_FIPS) || defined(OPENSSL_IS_AWSLC)
VALUE enabled;
enabled = FIPS_mode() ? Qtrue : Qfalse;
return enabled;
@@ -422,10 +468,10 @@ ossl_fips_mode_get(VALUE self)
/*
* call-seq:
- * OpenSSL.fips_mode = boolean -> boolean
+ * OpenSSL.fips_mode = boolean
*
* Turns FIPS mode on or off. Turning on FIPS mode will obviously only have an
- * effect for FIPS-capable installations of the OpenSSL library. Trying to do
+ * effect for FIPS-capable installations of the \OpenSSL library. Trying to do
* so otherwise will result in an error.
*
* === Examples
@@ -446,123 +492,32 @@ ossl_fips_mode_set(VALUE self, VALUE enabled)
}
}
return enabled;
-#elif defined(OPENSSL_FIPS)
+#elif defined(OPENSSL_FIPS) || defined(OPENSSL_IS_AWSLC)
if (RTEST(enabled)) {
- int mode = FIPS_mode();
- if(!mode && !FIPS_mode_set(1)) /* turning on twice leads to an error */
- ossl_raise(eOSSLError, "Turning on FIPS mode failed");
+ int mode = FIPS_mode();
+ if(!mode && !FIPS_mode_set(1)) /* turning on twice leads to an error */
+ ossl_raise(eOSSLError, "Turning on FIPS mode failed");
} else {
- if(!FIPS_mode_set(0)) /* turning off twice is OK */
- ossl_raise(eOSSLError, "Turning off FIPS mode failed");
+ if(!FIPS_mode_set(0)) /* turning off twice is OK */
+ ossl_raise(eOSSLError, "Turning off FIPS mode failed");
}
return enabled;
#else
if (RTEST(enabled))
- ossl_raise(eOSSLError, "This version of OpenSSL does not support FIPS mode");
+ ossl_raise(eOSSLError, "This version of OpenSSL does not support FIPS mode");
return enabled;
#endif
}
-#if !defined(HAVE_OPENSSL_110_THREADING_API)
-/**
- * Stores locks needed for OpenSSL thread safety
- */
-struct CRYPTO_dynlock_value {
- rb_nativethread_lock_t lock;
- rb_nativethread_id_t owner;
- size_t count;
-};
-
-static void
-ossl_lock_init(struct CRYPTO_dynlock_value *l)
-{
- rb_nativethread_lock_initialize(&l->lock);
- l->count = 0;
-}
-
-static void
-ossl_lock_unlock(int mode, struct CRYPTO_dynlock_value *l)
-{
- if (mode & CRYPTO_LOCK) {
- /* TODO: rb_nativethread_id_t is not necessarily compared with ==. */
- rb_nativethread_id_t tid = rb_nativethread_self();
- if (l->count && l->owner == tid) {
- l->count++;
- return;
- }
- rb_nativethread_lock_lock(&l->lock);
- l->owner = tid;
- l->count = 1;
- } else {
- if (!--l->count)
- rb_nativethread_lock_unlock(&l->lock);
- }
-}
-
-static struct CRYPTO_dynlock_value *
-ossl_dyn_create_callback(const char *file, int line)
-{
- /* Do not use xmalloc() here, since it may raise NoMemoryError */
- struct CRYPTO_dynlock_value *dynlock =
- OPENSSL_malloc(sizeof(struct CRYPTO_dynlock_value));
- if (dynlock)
- ossl_lock_init(dynlock);
- return dynlock;
-}
-
-static void
-ossl_dyn_lock_callback(int mode, struct CRYPTO_dynlock_value *l, const char *file, int line)
-{
- ossl_lock_unlock(mode, l);
-}
-
-static void
-ossl_dyn_destroy_callback(struct CRYPTO_dynlock_value *l, const char *file, int line)
-{
- rb_nativethread_lock_destroy(&l->lock);
- OPENSSL_free(l);
-}
-
-static void ossl_threadid_func(CRYPTO_THREADID *id)
-{
- /* register native thread id */
- CRYPTO_THREADID_set_pointer(id, (void *)rb_nativethread_self());
-}
-
-static struct CRYPTO_dynlock_value *ossl_locks;
-
-static void
-ossl_lock_callback(int mode, int type, const char *file, int line)
-{
- ossl_lock_unlock(mode, &ossl_locks[type]);
-}
-
-static void Init_ossl_locks(void)
-{
- int i;
- int num_locks = CRYPTO_num_locks();
-
- ossl_locks = ALLOC_N(struct CRYPTO_dynlock_value, num_locks);
- for (i = 0; i < num_locks; i++)
- ossl_lock_init(&ossl_locks[i]);
-
- CRYPTO_THREADID_set_callback(ossl_threadid_func);
- CRYPTO_set_locking_callback(ossl_lock_callback);
- CRYPTO_set_dynlock_create_callback(ossl_dyn_create_callback);
- CRYPTO_set_dynlock_lock_callback(ossl_dyn_lock_callback);
- CRYPTO_set_dynlock_destroy_callback(ossl_dyn_destroy_callback);
-}
-#endif /* !HAVE_OPENSSL_110_THREADING_API */
-
/*
* call-seq:
- * OpenSSL.fixed_length_secure_compare(string, string) -> boolean
+ * OpenSSL.fixed_length_secure_compare(string, string) -> true or false
*
* Constant time memory comparison for fixed length strings, such as results
- * of HMAC calculations.
+ * 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
+ * length but not identical. If the length is different, ArgumentError is
* raised.
*/
static VALUE
@@ -578,13 +533,13 @@ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2)
}
switch (CRYPTO_memcmp(p1, p2, len1)) {
- case 0: return Qtrue;
- default: return Qfalse;
+ case 0: return Qtrue;
+ default: return Qfalse;
}
}
/*
- * OpenSSL provides SSL, TLS and general purpose cryptography. It wraps the
+ * OpenSSL provides \SSL, TLS and general purpose cryptography. It wraps the
* OpenSSL[https://www.openssl.org/] library.
*
* = Examples
@@ -639,7 +594,7 @@ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2)
*
* === Loading an Encrypted Key
*
- * OpenSSL will prompt you for your password when loading an encrypted key.
+ * \OpenSSL will prompt you for your password when loading an encrypted key.
* If you will not be able to type in the password you may provide it when
* loading the key:
*
@@ -702,7 +657,7 @@ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2)
*
* == PBKDF2 Password-based Encryption
*
- * If supported by the underlying OpenSSL version used, Password-based
+ * If supported by the underlying \OpenSSL version used, Password-based
* Encryption should use the features of PKCS5. If not supported or if
* required by legacy applications, the older, less secure methods specified
* in RFC 2898 are also supported (see below).
@@ -761,7 +716,7 @@ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2)
* decrypted = cipher.update encrypted
* decrypted << cipher.final
*
- * == X509 Certificates
+ * == \X509 Certificates
*
* === Creating a Certificate
*
@@ -798,7 +753,7 @@ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2)
* extension_factory.create_extension('subjectKeyIdentifier', 'hash')
*
* The list of supported extensions (and in some cases their possible values)
- * can be derived from the "objects.h" file in the OpenSSL source code.
+ * can be derived from the "objects.h" file in the \OpenSSL source code.
*
* === Signing a Certificate
*
@@ -952,23 +907,23 @@ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2)
* io.write csr_cert.to_pem
* end
*
- * == SSL and TLS Connections
+ * == \SSL and TLS Connections
*
- * Using our created key and certificate we can create an SSL or TLS connection.
- * An SSLContext is used to set up an SSL session.
+ * Using our created key and certificate we can create an \SSL or TLS
+ * connection. An OpenSSL::SSL::SSLContext is used to set up an \SSL session.
*
* context = OpenSSL::SSL::SSLContext.new
*
- * === SSL Server
+ * === \SSL Server
*
- * An SSL server requires the certificate and private key to communicate
+ * An \SSL server requires the certificate and private key to communicate
* securely with its clients:
*
* context.cert = cert
* context.key = key
*
- * Then create an SSLServer with a TCP server socket and the context. Use the
- * SSLServer like an ordinary TCP server.
+ * Then create an OpenSSL::SSL::SSLServer with a TCP server socket and the
+ * context. Use the SSLServer like an ordinary TCP server.
*
* require 'socket'
*
@@ -987,14 +942,15 @@ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2)
* ssl_connection.close
* end
*
- * === SSL client
+ * === \SSL client
*
- * An SSL client is created with a TCP socket and the context.
- * SSLSocket#connect must be called to initiate the SSL handshake and start
- * encryption. A key and certificate are not required for the client socket.
+ * An \SSL client is created with a TCP socket and the context.
+ * OpenSSL::SSL::SSLSocket#connect must be called to initiate the \SSL handshake
+ * and start encryption. A key and certificate are not required for the client
+ * socket.
*
- * Note that SSLSocket#close doesn't close the underlying socket by default. Set
- * SSLSocket#sync_close to true if you want.
+ * Note that OpenSSL::SSL::SSLSocket#close doesn't close the underlying socket
+ * by default. Set OpenSSL::SSL::SSLSocket#sync_close to true if you want.
*
* require 'socket'
*
@@ -1010,7 +966,7 @@ ossl_crypto_fixed_length_secure_compare(VALUE dummy, VALUE str1, VALUE str2)
*
* === Peer Verification
*
- * An unverified SSL connection does not provide much security. For enhanced
+ * An unverified \SSL connection does not provide much security. For enhanced
* security the client or server can verify the certificate of its peer.
*
* The client can be modified to verify the server's certificate against the
@@ -1050,15 +1006,8 @@ Init_openssl(void)
/*
* Init all digests, ciphers
*/
-#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000
if (!OPENSSL_init_ssl(0, NULL))
rb_raise(rb_eRuntimeError, "OPENSSL_init_ssl");
-#else
- OpenSSL_add_ssl_algorithms();
- OpenSSL_add_all_algorithms();
- ERR_load_crypto_strings();
- SSL_load_error_strings();
-#endif
/*
* Init main module
@@ -1068,26 +1017,34 @@ Init_openssl(void)
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
+ * \OpenSSL library version string used to compile the Ruby/OpenSSL
+ * extension. This may differ from the version used at runtime.
*/
- rb_define_const(mOSSL, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT));
+ rb_define_const(mOSSL, "OPENSSL_VERSION",
+ rb_obj_freeze(rb_str_new_cstr(OPENSSL_VERSION_TEXT)));
/*
- * Version of OpenSSL the ruby OpenSSL extension is running with
+ * \OpenSSL library version string currently used at runtime.
*/
-#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000
- rb_define_const(mOSSL, "OPENSSL_LIBRARY_VERSION", rb_str_new2(OpenSSL_version(OPENSSL_VERSION)));
-#else
- rb_define_const(mOSSL, "OPENSSL_LIBRARY_VERSION", rb_str_new2(SSLeay_version(SSLEAY_VERSION)));
-#endif
+ rb_define_const(
+ mOSSL,
+ "OPENSSL_LIBRARY_VERSION",
+ rb_obj_freeze(rb_str_new_cstr(OpenSSL_version(OPENSSL_VERSION)))
+ );
/*
- * Version number of OpenSSL the ruby OpenSSL extension was built with
- * (base 16). The formats are below.
+ * \OpenSSL library version number used to compile the Ruby/OpenSSL
+ * extension. This may differ from the version used at runtime.
+ *
+ * The version number is encoded into a single integer value. The number
+ * follows the format:
*
- * [OpenSSL 3] <tt>0xMNN00PP0 (major minor 00 patch 0)</tt>
- * [OpenSSL before 3] <tt>0xMNNFFPPS (major minor fix patch status)</tt>
- * [LibreSSL] <tt>0x20000000 (fixed value)</tt>
+ * [\OpenSSL 3.0.0 or later]
+ * <tt>0xMNN00PP0</tt> (major minor 00 patch 0)
+ * [\OpenSSL 1.1.1 or earlier]
+ * <tt>0xMNNFFPPS</tt> (major minor fix patch status)
+ * [LibreSSL]
+ * <tt>0x20000000</tt> (a fixed value)
*
* See also the man page OPENSSL_VERSION_NUMBER(3).
*/
@@ -1095,9 +1052,12 @@ Init_openssl(void)
#if defined(LIBRESSL_VERSION_NUMBER)
/*
- * Version number of LibreSSL the ruby OpenSSL extension was built with
- * (base 16). The format is <tt>0xMNNFF00f (major minor fix 00
- * status)</tt>. This constant is only defined in LibreSSL cases.
+ * LibreSSL library version number used to compile the Ruby/OpenSSL
+ * extension. This may differ from the version used at runtime.
+ *
+ * This constant is only defined if the extension was compiled against
+ * LibreSSL. The number follows the format:
+ * <tt>0xMNNFF00f</tt> (major minor fix 00 status).
*
* See also the man page LIBRESSL_VERSION_NUMBER(3).
*/
@@ -1105,28 +1065,50 @@ Init_openssl(void)
#endif
/*
- * Boolean indicating whether OpenSSL is FIPS-capable or not
+ * Boolean indicating whether the \OpenSSL library is FIPS-capable or not.
+ * Always <tt>true</tt> for \OpenSSL 3.0 and later.
+ *
+ * This is obsolete and will be removed in the future.
+ * See also OpenSSL.fips_mode.
*/
rb_define_const(mOSSL, "OPENSSL_FIPS",
/* OpenSSL 3 is FIPS-capable even when it is installed without fips option */
#if OSSL_OPENSSL_PREREQ(3, 0, 0)
Qtrue
#elif defined(OPENSSL_FIPS)
- Qtrue
+ Qtrue
+#elif defined(OPENSSL_IS_AWSLC) // AWS-LC FIPS can only be enabled during compile time.
+ FIPS_mode() ? Qtrue : Qfalse
#else
- Qfalse
+ Qfalse
#endif
- );
+ );
rb_define_module_function(mOSSL, "fips_mode", ossl_fips_mode_get, 0);
rb_define_module_function(mOSSL, "fips_mode=", ossl_fips_mode_set, 1);
rb_global_variable(&eOSSLError);
/*
- * Generic error,
- * common for all classes under OpenSSL module
+ * Generic error class for OpenSSL. All error classes in this library
+ * inherit from this class.
+ *
+ * This class indicates that an error was reported by the underlying
+ * \OpenSSL library.
+ */
+ eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
+ /*
+ * \OpenSSL error queue entries captured at the time the exception was
+ * raised. The same information is printed to stderr if OpenSSL.debug is
+ * set to +true+.
+ *
+ * This is an array of zero or more strings, ordered from the oldest to the
+ * newest. The format of the strings is not stable and may vary across
+ * versions of \OpenSSL or versions of this Ruby extension.
+ *
+ * See also the man page ERR_get_error(3).
*/
- eOSSLError = rb_define_class_under(mOSSL,"OpenSSLError",rb_eStandardError);
+ rb_attr(eOSSLError, rb_intern_const("errors"), 1, 0, 0);
+ rb_define_method(eOSSLError, "detailed_message", osslerror_detailed_message, -1);
/*
* Init debug core
@@ -1142,32 +1124,27 @@ Init_openssl(void)
* Get ID of to_der
*/
ossl_s_to_der = rb_intern("to_der");
-
-#if !defined(HAVE_OPENSSL_110_THREADING_API)
- Init_ossl_locks();
-#endif
+ id_i_errors = rb_intern("@errors");
/*
* Init components
*/
+ Init_ossl_asn1();
Init_ossl_bn();
Init_ossl_cipher();
Init_ossl_config();
Init_ossl_digest();
+ Init_ossl_engine();
Init_ossl_hmac();
+ Init_ossl_kdf();
Init_ossl_ns_spki();
+ Init_ossl_ocsp();
Init_ossl_pkcs12();
Init_ossl_pkcs7();
Init_ossl_pkey();
+ Init_ossl_provider();
Init_ossl_rand();
Init_ossl_ssl();
-#ifndef OPENSSL_NO_TS
Init_ossl_ts();
-#endif
Init_ossl_x509();
- Init_ossl_ocsp();
- Init_ossl_engine();
- Init_ossl_provider();
- Init_ossl_asn1();
- Init_ossl_kdf();
}
diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h
index 68d42b71e2..0b479a7200 100644
--- a/ext/openssl/ossl.h
+++ b/ext/openssl/ossl.h
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_H_)
#define _OSSL_H_
@@ -17,6 +17,12 @@
#include <errno.h>
#include <ruby/io.h>
#include <ruby/thread.h>
+#ifdef HAVE_RUBY_RACTOR_H
+#include <ruby/ractor.h>
+#else
+#define RUBY_TYPED_FROZEN_SHAREABLE 0
+#endif
+
#include <openssl/opensslv.h>
#include <openssl/err.h>
@@ -39,6 +45,7 @@
#include <openssl/dsa.h>
#include <openssl/evp.h>
#include <openssl/dh.h>
+#include "openssl_missing.h"
#ifndef LIBRESSL_VERSION_NUMBER
# define OSSL_IS_LIBRESSL 0
@@ -64,6 +71,11 @@
#if OSSL_OPENSSL_PREREQ(3, 0, 0)
# define OSSL_USE_PROVIDER
+# include <openssl/provider.h>
+#endif
+
+#if OSSL_OPENSSL_PREREQ(3, 0, 0)
+# define OSSL_HAVE_IMMUTABLE_PKEY
#endif
/*
@@ -80,10 +92,10 @@ extern VALUE eOSSLError;
* CheckTypes
*/
#define OSSL_Check_Kind(obj, klass) do {\
- if (!rb_obj_is_kind_of((obj), (klass))) {\
- ossl_raise(rb_eTypeError, "wrong argument (%"PRIsVALUE")! (Expected kind of %"PRIsVALUE")",\
- rb_obj_class(obj), (klass));\
- }\
+ if (!rb_obj_is_kind_of((obj), (klass))) {\
+ ossl_raise(rb_eTypeError, "wrong argument (%"PRIsVALUE")! (Expected kind of %"PRIsVALUE")",\
+ rb_obj_class(obj), (klass));\
+ }\
} while (0)
/*
@@ -119,7 +131,7 @@ do{\
* Convert binary string to hex string. The caller is responsible for
* ensuring out has (2 * len) bytes of capacity.
*/
-void ossl_bin2hex(unsigned char *in, char *out, size_t len);
+void ossl_bin2hex(const unsigned char *in, char *out, size_t len);
/*
* Our default PEM callback
@@ -162,38 +174,35 @@ VALUE ossl_to_der_if_possible(VALUE);
extern VALUE dOSSL;
#define OSSL_Debug(...) do { \
- if (dOSSL == Qtrue) { \
- fprintf(stderr, "OSSL_DEBUG: "); \
- fprintf(stderr, __VA_ARGS__); \
- fprintf(stderr, " [%s:%d]\n", __FILE__, __LINE__); \
- } \
+ if (dOSSL == Qtrue) { \
+ fprintf(stderr, "OSSL_DEBUG: "); \
+ fprintf(stderr, __VA_ARGS__); \
+ fprintf(stderr, " [%s:%d]\n", __FILE__, __LINE__); \
+ } \
} while (0)
/*
* Include all parts
*/
-#include "openssl_missing.h"
#include "ossl_asn1.h"
#include "ossl_bio.h"
#include "ossl_bn.h"
#include "ossl_cipher.h"
#include "ossl_config.h"
#include "ossl_digest.h"
+#include "ossl_engine.h"
#include "ossl_hmac.h"
+#include "ossl_kdf.h"
#include "ossl_ns_spki.h"
#include "ossl_ocsp.h"
#include "ossl_pkcs12.h"
#include "ossl_pkcs7.h"
#include "ossl_pkey.h"
+#include "ossl_provider.h"
#include "ossl_rand.h"
#include "ossl_ssl.h"
-#ifndef OPENSSL_NO_TS
- #include "ossl_ts.h"
-#endif
+#include "ossl_ts.h"
#include "ossl_x509.h"
-#include "ossl_engine.h"
-#include "ossl_provider.h"
-#include "ossl_kdf.h"
void Init_openssl(void);
diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c
index 0533342077..71a87f0463 100644
--- a/ext/openssl/ossl_asn1.c
+++ b/ext/openssl/ossl_asn1.c
@@ -5,68 +5,85 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
-static VALUE ossl_asn1_decode0(unsigned char **pp, long length, long *offset,
- int depth, int yield, long *num_read);
-static VALUE ossl_asn1_initialize(int argc, VALUE *argv, VALUE self);
+/********/
+/*
+ * ASN1 module
+ */
+#define ossl_asn1_get_value(o) rb_attr_get((o),sivVALUE)
+#define ossl_asn1_get_tag(o) rb_attr_get((o),sivTAG)
+#define ossl_asn1_get_tagging(o) rb_attr_get((o),sivTAGGING)
+#define ossl_asn1_get_tag_class(o) rb_attr_get((o),sivTAG_CLASS)
+#define ossl_asn1_get_indefinite_length(o) rb_attr_get((o),sivINDEFINITE_LENGTH)
+
+#define ossl_asn1_set_value(o,v) rb_ivar_set((o),sivVALUE,(v))
+#define ossl_asn1_set_tag(o,v) rb_ivar_set((o),sivTAG,(v))
+#define ossl_asn1_set_tagging(o,v) rb_ivar_set((o),sivTAGGING,(v))
+#define ossl_asn1_set_tag_class(o,v) rb_ivar_set((o),sivTAG_CLASS,(v))
+#define ossl_asn1_set_indefinite_length(o,v) rb_ivar_set((o),sivINDEFINITE_LENGTH,(v))
+
+VALUE mASN1;
+static VALUE eASN1Error;
+
+VALUE cASN1Data;
+static VALUE cASN1Primitive;
+static VALUE cASN1Constructive;
+
+static VALUE cASN1EndOfContent;
+static VALUE cASN1Boolean; /* BOOLEAN */
+static VALUE cASN1Integer, cASN1Enumerated; /* INTEGER */
+static VALUE cASN1BitString; /* BIT STRING */
+static VALUE cASN1OctetString, cASN1UTF8String; /* STRINGs */
+static VALUE cASN1NumericString, cASN1PrintableString;
+static VALUE cASN1T61String, cASN1VideotexString;
+static VALUE cASN1IA5String, cASN1GraphicString;
+static VALUE cASN1ISO64String, cASN1GeneralString;
+static VALUE cASN1UniversalString, cASN1BMPString;
+static VALUE cASN1Null; /* NULL */
+static VALUE cASN1ObjectId; /* OBJECT IDENTIFIER */
+static VALUE cASN1UTCTime, cASN1GeneralizedTime; /* TIME */
+static VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */
+
+static VALUE sym_IMPLICIT, sym_EXPLICIT;
+static VALUE sym_UNIVERSAL, sym_APPLICATION, sym_CONTEXT_SPECIFIC, sym_PRIVATE;
+static ID sivVALUE, sivTAG, sivTAG_CLASS, sivTAGGING, sivINDEFINITE_LENGTH, sivUNUSED_BITS;
+static ID id_each;
/*
* DATE conversion
*/
+static VALUE
+time_utc_new(VALUE args)
+{
+ return rb_funcallv(rb_cTime, rb_intern("utc"), 6, (VALUE *)args);
+}
+
+static VALUE
+time_utc_new_rescue(VALUE args, VALUE exc)
+{
+ rb_raise(eASN1Error, "invalid time");
+}
+
VALUE
asn1time_to_time(const ASN1_TIME *time)
{
struct tm tm;
- VALUE argv[6];
- int count;
-
- memset(&tm, 0, sizeof(struct tm));
-
- switch (time->type) {
- case V_ASN1_UTCTIME:
- count = sscanf((const char *)time->data, "%2d%2d%2d%2d%2d%2dZ",
- &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min,
- &tm.tm_sec);
-
- if (count == 5) {
- tm.tm_sec = 0;
- } else if (count != 6) {
- ossl_raise(rb_eTypeError, "bad UTCTIME format: \"%s\"",
- time->data);
- }
- if (tm.tm_year < 69) {
- tm.tm_year += 2000;
- } else {
- tm.tm_year += 1900;
- }
- break;
- case V_ASN1_GENERALIZEDTIME:
- count = sscanf((const char *)time->data, "%4d%2d%2d%2d%2d%2dZ",
- &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min,
- &tm.tm_sec);
- if (count == 5) {
- tm.tm_sec = 0;
- }
- else if (count != 6) {
- ossl_raise(rb_eTypeError, "bad GENERALIZEDTIME format: \"%s\"",
- time->data);
- }
- break;
- default:
- rb_warning("unknown time format");
- return Qnil;
- }
- argv[0] = INT2NUM(tm.tm_year);
- argv[1] = INT2NUM(tm.tm_mon);
- argv[2] = INT2NUM(tm.tm_mday);
- argv[3] = INT2NUM(tm.tm_hour);
- argv[4] = INT2NUM(tm.tm_min);
- argv[5] = INT2NUM(tm.tm_sec);
-
- return rb_funcall2(rb_cTime, rb_intern("utc"), 6, argv);
+ if (!ASN1_TIME_to_tm(time, &tm))
+ ossl_raise(eASN1Error, "ASN1_TIME_to_tm");
+
+ VALUE args[] = {
+ INT2NUM(tm.tm_year + 1900),
+ INT2NUM(tm.tm_mon + 1),
+ INT2NUM(tm.tm_mday),
+ INT2NUM(tm.tm_hour),
+ INT2NUM(tm.tm_min),
+ INT2NUM(tm.tm_sec),
+ };
+ return rb_rescue2(time_utc_new, (VALUE)args, time_utc_new_rescue, Qnil,
+ rb_eArgError, 0);
}
static VALUE
@@ -81,13 +98,13 @@ ossl_time_split(VALUE time, time_t *sec, int *days)
VALUE num = rb_Integer(time);
if (FIXNUM_P(num)) {
- time_t t = FIX2LONG(num);
- *sec = t % 86400;
- *days = rb_long2int(t / 86400);
+ time_t t = FIX2LONG(num);
+ *sec = t % 86400;
+ *days = rb_long2int(t / 86400);
}
else {
- *days = NUM2INT(rb_funcall(num, rb_intern("/"), 1, INT2FIX(86400)));
- *sec = NUM2TIMET(rb_funcall(num, rb_intern("%"), 1, INT2FIX(86400)));
+ *days = NUM2INT(rb_funcall(num, rb_intern("/"), 1, INT2FIX(86400)));
+ *sec = NUM2TIMET(rb_funcall(num, rb_intern("%"), 1, INT2FIX(86400)));
}
}
@@ -97,7 +114,8 @@ ossl_time_split(VALUE time, time_t *sec, int *days)
VALUE
asn1str_to_str(const ASN1_STRING *str)
{
- return rb_str_new((const char *)str->data, str->length);
+ return rb_str_new((const char *)ASN1_STRING_get0_data(str),
+ ASN1_STRING_length(str));
}
/*
@@ -110,16 +128,15 @@ asn1integer_to_num(const ASN1_INTEGER *ai)
VALUE num;
if (!ai) {
- ossl_raise(rb_eTypeError, "ASN1_INTEGER is NULL!");
+ ossl_raise(rb_eTypeError, "ASN1_INTEGER is NULL!");
}
- if (ai->type == V_ASN1_ENUMERATED)
- /* const_cast: workaround for old OpenSSL */
- bn = ASN1_ENUMERATED_to_BN((ASN1_ENUMERATED *)ai, NULL);
+ if (ASN1_STRING_type(ai) == V_ASN1_ENUMERATED)
+ bn = ASN1_ENUMERATED_to_BN(ai, NULL);
else
- bn = ASN1_INTEGER_to_BN(ai, NULL);
+ bn = ASN1_INTEGER_to_BN(ai, NULL);
if (!bn)
- ossl_raise(eOSSLError, NULL);
+ ossl_raise(eOSSLError, NULL);
num = ossl_bn_new(bn);
BN_free(bn);
@@ -132,12 +149,12 @@ num_to_asn1integer(VALUE obj, ASN1_INTEGER *ai)
BIGNUM *bn;
if (NIL_P(obj))
- ossl_raise(rb_eTypeError, "Can't convert nil into Integer");
+ ossl_raise(rb_eTypeError, "Can't convert nil into Integer");
bn = GetBNPtr(obj);
if (!(ai = BN_to_ASN1_INTEGER(bn, ai)))
- ossl_raise(eOSSLError, NULL);
+ ossl_raise(eOSSLError, NULL);
return ai;
}
@@ -148,48 +165,47 @@ asn1integer_to_num_i(VALUE arg)
return asn1integer_to_num((ASN1_INTEGER *)arg);
}
-/********/
/*
- * ASN1 module
+ * ASN1_OBJECT conversions
*/
-#define ossl_asn1_get_value(o) rb_attr_get((o),sivVALUE)
-#define ossl_asn1_get_tag(o) rb_attr_get((o),sivTAG)
-#define ossl_asn1_get_tagging(o) rb_attr_get((o),sivTAGGING)
-#define ossl_asn1_get_tag_class(o) rb_attr_get((o),sivTAG_CLASS)
-#define ossl_asn1_get_indefinite_length(o) rb_attr_get((o),sivINDEFINITE_LENGTH)
-
-#define ossl_asn1_set_value(o,v) rb_ivar_set((o),sivVALUE,(v))
-#define ossl_asn1_set_tag(o,v) rb_ivar_set((o),sivTAG,(v))
-#define ossl_asn1_set_tagging(o,v) rb_ivar_set((o),sivTAGGING,(v))
-#define ossl_asn1_set_tag_class(o,v) rb_ivar_set((o),sivTAG_CLASS,(v))
-#define ossl_asn1_set_indefinite_length(o,v) rb_ivar_set((o),sivINDEFINITE_LENGTH,(v))
+VALUE
+ossl_asn1obj_to_string_oid(const ASN1_OBJECT *a1obj)
+{
+ VALUE str;
+ int len;
-VALUE mASN1;
-VALUE eASN1Error;
+ str = rb_usascii_str_new(NULL, 127);
+ len = OBJ_obj2txt(RSTRING_PTR(str), RSTRING_LENINT(str), a1obj, 1);
+ if (len <= 0 || len == INT_MAX)
+ ossl_raise(eOSSLError, "OBJ_obj2txt");
+ if (len > RSTRING_LEN(str)) {
+ /* +1 is for the \0 terminator added by OBJ_obj2txt() */
+ rb_str_resize(str, len + 1);
+ len = OBJ_obj2txt(RSTRING_PTR(str), len + 1, a1obj, 1);
+ if (len <= 0)
+ ossl_raise(eOSSLError, "OBJ_obj2txt");
+ }
+ rb_str_set_len(str, len);
+ return str;
+}
-VALUE cASN1Data;
-VALUE cASN1Primitive;
-VALUE cASN1Constructive;
-
-VALUE cASN1EndOfContent;
-VALUE cASN1Boolean; /* BOOLEAN */
-VALUE cASN1Integer, cASN1Enumerated; /* INTEGER */
-VALUE cASN1BitString; /* BIT STRING */
-VALUE cASN1OctetString, cASN1UTF8String; /* STRINGs */
-VALUE cASN1NumericString, cASN1PrintableString;
-VALUE cASN1T61String, cASN1VideotexString;
-VALUE cASN1IA5String, cASN1GraphicString;
-VALUE cASN1ISO64String, cASN1GeneralString;
-VALUE cASN1UniversalString, cASN1BMPString;
-VALUE cASN1Null; /* NULL */
-VALUE cASN1ObjectId; /* OBJECT IDENTIFIER */
-VALUE cASN1UTCTime, cASN1GeneralizedTime; /* TIME */
-VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */
+VALUE
+ossl_asn1obj_to_string(const ASN1_OBJECT *obj)
+{
+ int nid = OBJ_obj2nid(obj);
+ if (nid != NID_undef)
+ return rb_str_new_cstr(OBJ_nid2sn(nid));
+ return ossl_asn1obj_to_string_oid(obj);
+}
-static VALUE sym_IMPLICIT, sym_EXPLICIT;
-static VALUE sym_UNIVERSAL, sym_APPLICATION, sym_CONTEXT_SPECIFIC, sym_PRIVATE;
-static ID sivVALUE, sivTAG, sivTAG_CLASS, sivTAGGING, sivINDEFINITE_LENGTH, sivUNUSED_BITS;
-static ID id_each;
+VALUE
+ossl_asn1obj_to_string_long_name(const ASN1_OBJECT *obj)
+{
+ int nid = OBJ_obj2nid(obj);
+ if (nid != NID_undef)
+ return rb_str_new_cstr(OBJ_nid2ln(nid));
+ return ossl_asn1obj_to_string_oid(obj);
+}
/*
* Ruby to ASN1 converters
@@ -198,9 +214,9 @@ static ASN1_BOOLEAN
obj_to_asn1bool(VALUE obj)
{
if (NIL_P(obj))
- ossl_raise(rb_eTypeError, "Can't convert nil into Boolean");
+ ossl_raise(rb_eTypeError, "Can't convert nil into Boolean");
- return RTEST(obj) ? 0xff : 0x0;
+ return RTEST(obj) ? 0xff : 0x0;
}
static ASN1_INTEGER*
@@ -215,11 +231,11 @@ obj_to_asn1bstr(VALUE obj, long unused_bits)
ASN1_BIT_STRING *bstr;
if (unused_bits < 0 || unused_bits > 7)
- ossl_raise(eASN1Error, "unused_bits for a bitstring value must be in "\
- "the range 0 to 7");
+ ossl_raise(eASN1Error, "unused_bits for a bitstring value must be in "\
+ "the range 0 to 7");
StringValue(obj);
if(!(bstr = ASN1_BIT_STRING_new()))
- ossl_raise(eASN1Error, NULL);
+ ossl_raise(eASN1Error, NULL);
ASN1_BIT_STRING_set(bstr, (unsigned char *)RSTRING_PTR(obj), RSTRING_LENINT(obj));
bstr->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear */
bstr->flags |= ASN1_STRING_FLAG_BITS_LEFT | unused_bits;
@@ -234,7 +250,7 @@ obj_to_asn1str(VALUE obj)
StringValue(obj);
if(!(str = ASN1_STRING_new()))
- ossl_raise(eASN1Error, NULL);
+ ossl_raise(eASN1Error, NULL);
ASN1_STRING_set(str, RSTRING_PTR(obj), RSTRING_LENINT(obj));
return str;
@@ -246,15 +262,15 @@ obj_to_asn1null(VALUE obj)
ASN1_NULL *null;
if(!NIL_P(obj))
- ossl_raise(eASN1Error, "nil expected");
+ ossl_raise(eASN1Error, "nil expected");
if(!(null = ASN1_NULL_new()))
- ossl_raise(eASN1Error, NULL);
+ ossl_raise(eASN1Error, NULL);
return null;
}
-static ASN1_OBJECT*
-obj_to_asn1obj(VALUE obj)
+ASN1_OBJECT *
+ossl_to_asn1obj(VALUE obj)
{
ASN1_OBJECT *a1obj;
@@ -276,7 +292,7 @@ obj_to_asn1utime(VALUE time)
ossl_time_split(time, &sec, &off_days);
if (!(t = ASN1_UTCTIME_adj(NULL, sec, off_days, 0)))
- ossl_raise(eASN1Error, NULL);
+ ossl_raise(eASN1Error, NULL);
return t;
}
@@ -291,7 +307,7 @@ obj_to_asn1gtime(VALUE time)
ossl_time_split(time, &sec, &off_days);
if (!(t = ASN1_GENERALIZEDTIME_adj(NULL, sec, off_days, 0)))
- ossl_raise(eASN1Error, NULL);
+ ossl_raise(eASN1Error, NULL);
return t;
}
@@ -304,7 +320,7 @@ obj_to_asn1derstr(VALUE obj)
str = ossl_to_der(obj);
if(!(a1str = ASN1_STRING_new()))
- ossl_raise(eASN1Error, NULL);
+ ossl_raise(eASN1Error, NULL);
ASN1_STRING_set(a1str, RSTRING_PTR(str), RSTRING_LENINT(str));
return a1str;
@@ -319,9 +335,9 @@ decode_bool(unsigned char* der, long length)
const unsigned char *p = der;
if (length != 3)
- ossl_raise(eASN1Error, "invalid length for BOOLEAN");
+ ossl_raise(eASN1Error, "invalid length for BOOLEAN");
if (p[0] != 1 || p[1] != 1)
- ossl_raise(eASN1Error, "invalid BOOLEAN");
+ ossl_raise(eASN1Error, "invalid BOOLEAN");
return p[2] ? Qtrue : Qfalse;
}
@@ -336,9 +352,9 @@ decode_int(unsigned char* der, long length)
p = der;
if(!(ai = d2i_ASN1_INTEGER(NULL, &p, length)))
- ossl_raise(eASN1Error, NULL);
+ ossl_raise(eASN1Error, NULL);
ret = rb_protect(asn1integer_to_num_i,
- (VALUE)ai, &status);
+ (VALUE)ai, &status);
ASN1_INTEGER_free(ai);
if(status) rb_jump_tag(status);
@@ -355,11 +371,11 @@ decode_bstr(unsigned char* der, long length, long *unused_bits)
p = der;
if(!(bstr = d2i_ASN1_BIT_STRING(NULL, &p, length)))
- ossl_raise(eASN1Error, NULL);
+ ossl_raise(eASN1Error, NULL);
len = bstr->length;
*unused_bits = 0;
if(bstr->flags & ASN1_STRING_FLAG_BITS_LEFT)
- *unused_bits = bstr->flags & 0x07;
+ *unused_bits = bstr->flags & 0x07;
ret = rb_str_new((const char *)bstr->data, len);
ASN1_BIT_STRING_free(bstr);
@@ -376,9 +392,9 @@ decode_enum(unsigned char* der, long length)
p = der;
if(!(ai = d2i_ASN1_ENUMERATED(NULL, &p, length)))
- ossl_raise(eASN1Error, NULL);
+ ossl_raise(eASN1Error, NULL);
ret = rb_protect(asn1integer_to_num_i,
- (VALUE)ai, &status);
+ (VALUE)ai, &status);
ASN1_ENUMERATED_free(ai);
if(status) rb_jump_tag(status);
@@ -393,38 +409,33 @@ decode_null(unsigned char* der, long length)
p = der;
if(!(null = d2i_ASN1_NULL(NULL, &p, length)))
- ossl_raise(eASN1Error, NULL);
+ ossl_raise(eASN1Error, NULL);
ASN1_NULL_free(null);
return Qnil;
}
+VALUE
+asn1obj_to_string_i(VALUE arg)
+{
+ return ossl_asn1obj_to_string((const ASN1_OBJECT *)arg);
+}
+
static VALUE
decode_obj(unsigned char* der, long length)
{
ASN1_OBJECT *obj;
const unsigned char *p;
VALUE ret;
- int nid;
- BIO *bio;
+ int state;
p = der;
- if(!(obj = d2i_ASN1_OBJECT(NULL, &p, length)))
- ossl_raise(eASN1Error, NULL);
- if((nid = OBJ_obj2nid(obj)) != NID_undef){
- ASN1_OBJECT_free(obj);
- ret = rb_str_new2(OBJ_nid2sn(nid));
- }
- else{
- if(!(bio = BIO_new(BIO_s_mem()))){
- ASN1_OBJECT_free(obj);
- ossl_raise(eASN1Error, NULL);
- }
- i2a_ASN1_OBJECT(bio, obj);
- ASN1_OBJECT_free(obj);
- ret = ossl_membio2str(bio);
- }
-
+ if (!(obj = d2i_ASN1_OBJECT(NULL, &p, length)))
+ ossl_raise(eASN1Error, "d2i_ASN1_OBJECT");
+ ret = rb_protect(asn1obj_to_string_i, (VALUE)obj, &state);
+ ASN1_OBJECT_free(obj);
+ if (state)
+ rb_jump_tag(state);
return ret;
}
@@ -438,9 +449,9 @@ decode_time(unsigned char* der, long length)
p = der;
if(!(time = d2i_ASN1_TIME(NULL, &p, length)))
- ossl_raise(eASN1Error, NULL);
+ ossl_raise(eASN1Error, NULL);
ret = rb_protect(asn1time_to_time_i,
- (VALUE)time, &status);
+ (VALUE)time, &status);
ASN1_TIME_free(time);
if(status) rb_jump_tag(status);
@@ -451,7 +462,7 @@ static VALUE
decode_eoc(unsigned char *der, long length)
{
if (length != 2 || !(der[0] == 0x00 && der[1] == 0x00))
- ossl_raise(eASN1Error, NULL);
+ ossl_raise(eASN1Error, NULL);
return rb_str_new("", 0);
}
@@ -503,7 +514,7 @@ static VALUE class_tag_map;
static int ossl_asn1_default_tag(VALUE obj);
-ASN1_TYPE*
+static ASN1_TYPE *
ossl_asn1_get_asn1type(VALUE obj)
{
ASN1_TYPE *ret;
@@ -516,62 +527,62 @@ ossl_asn1_get_asn1type(VALUE obj)
tag = ossl_asn1_default_tag(obj);
value = ossl_asn1_get_value(obj);
switch(tag){
- case V_ASN1_BOOLEAN:
- ptr = (void*)(VALUE)obj_to_asn1bool(value);
- free_func = NULL;
- break;
- case V_ASN1_INTEGER: /* FALLTHROUGH */
- case V_ASN1_ENUMERATED:
- ptr = obj_to_asn1int(value);
- free_func = (free_func_type *)ASN1_INTEGER_free;
- break;
- case V_ASN1_BIT_STRING:
+ case V_ASN1_BOOLEAN:
+ ptr = (void*)(VALUE)obj_to_asn1bool(value);
+ free_func = NULL;
+ break;
+ case V_ASN1_INTEGER: /* FALLTHROUGH */
+ case V_ASN1_ENUMERATED:
+ ptr = obj_to_asn1int(value);
+ free_func = (free_func_type *)ASN1_INTEGER_free;
+ break;
+ case V_ASN1_BIT_STRING:
rflag = rb_attr_get(obj, sivUNUSED_BITS);
- ptr = obj_to_asn1bstr(value, NUM2INT(rflag));
- free_func = (free_func_type *)ASN1_BIT_STRING_free;
- break;
- case V_ASN1_NULL:
- ptr = obj_to_asn1null(value);
- free_func = (free_func_type *)ASN1_NULL_free;
- break;
- case V_ASN1_OCTET_STRING: /* FALLTHROUGH */
- case V_ASN1_UTF8STRING: /* FALLTHROUGH */
- case V_ASN1_NUMERICSTRING: /* FALLTHROUGH */
- case V_ASN1_PRINTABLESTRING: /* FALLTHROUGH */
- case V_ASN1_T61STRING: /* FALLTHROUGH */
- case V_ASN1_VIDEOTEXSTRING: /* FALLTHROUGH */
- case V_ASN1_IA5STRING: /* FALLTHROUGH */
- case V_ASN1_GRAPHICSTRING: /* FALLTHROUGH */
- case V_ASN1_ISO64STRING: /* FALLTHROUGH */
- case V_ASN1_GENERALSTRING: /* FALLTHROUGH */
- case V_ASN1_UNIVERSALSTRING: /* FALLTHROUGH */
- case V_ASN1_BMPSTRING:
- ptr = obj_to_asn1str(value);
- free_func = (free_func_type *)ASN1_STRING_free;
- break;
- case V_ASN1_OBJECT:
- ptr = obj_to_asn1obj(value);
- free_func = (free_func_type *)ASN1_OBJECT_free;
- break;
- case V_ASN1_UTCTIME:
- ptr = obj_to_asn1utime(value);
- free_func = (free_func_type *)ASN1_TIME_free;
- break;
- case V_ASN1_GENERALIZEDTIME:
- ptr = obj_to_asn1gtime(value);
- free_func = (free_func_type *)ASN1_TIME_free;
- break;
- case V_ASN1_SET: /* FALLTHROUGH */
- case V_ASN1_SEQUENCE:
- ptr = obj_to_asn1derstr(obj);
- free_func = (free_func_type *)ASN1_STRING_free;
- break;
- default:
- ossl_raise(eASN1Error, "unsupported ASN.1 type");
+ ptr = obj_to_asn1bstr(value, NUM2INT(rflag));
+ free_func = (free_func_type *)ASN1_BIT_STRING_free;
+ break;
+ case V_ASN1_NULL:
+ ptr = obj_to_asn1null(value);
+ free_func = (free_func_type *)ASN1_NULL_free;
+ break;
+ case V_ASN1_OCTET_STRING: /* FALLTHROUGH */
+ case V_ASN1_UTF8STRING: /* FALLTHROUGH */
+ case V_ASN1_NUMERICSTRING: /* FALLTHROUGH */
+ case V_ASN1_PRINTABLESTRING: /* FALLTHROUGH */
+ case V_ASN1_T61STRING: /* FALLTHROUGH */
+ case V_ASN1_VIDEOTEXSTRING: /* FALLTHROUGH */
+ case V_ASN1_IA5STRING: /* FALLTHROUGH */
+ case V_ASN1_GRAPHICSTRING: /* FALLTHROUGH */
+ case V_ASN1_ISO64STRING: /* FALLTHROUGH */
+ case V_ASN1_GENERALSTRING: /* FALLTHROUGH */
+ case V_ASN1_UNIVERSALSTRING: /* FALLTHROUGH */
+ case V_ASN1_BMPSTRING:
+ ptr = obj_to_asn1str(value);
+ free_func = (free_func_type *)ASN1_STRING_free;
+ break;
+ case V_ASN1_OBJECT:
+ ptr = ossl_to_asn1obj(value);
+ free_func = (free_func_type *)ASN1_OBJECT_free;
+ break;
+ case V_ASN1_UTCTIME:
+ ptr = obj_to_asn1utime(value);
+ free_func = (free_func_type *)ASN1_TIME_free;
+ break;
+ case V_ASN1_GENERALIZEDTIME:
+ ptr = obj_to_asn1gtime(value);
+ free_func = (free_func_type *)ASN1_TIME_free;
+ break;
+ case V_ASN1_SET: /* FALLTHROUGH */
+ case V_ASN1_SEQUENCE:
+ ptr = obj_to_asn1derstr(obj);
+ free_func = (free_func_type *)ASN1_STRING_free;
+ break;
+ default:
+ ossl_raise(eASN1Error, "unsupported ASN.1 type");
}
if(!(ret = OPENSSL_malloc(sizeof(ASN1_TYPE)))){
- if(free_func) free_func(ptr);
- ossl_raise(eASN1Error, "ASN1_TYPE alloc failure");
+ if(free_func) free_func(ptr);
+ ossl_raise(eASN1Error, "ASN1_TYPE alloc failure");
}
memset(ret, 0, sizeof(ASN1_TYPE));
ASN1_TYPE_set(ret, tag, ptr);
@@ -586,10 +597,10 @@ ossl_asn1_default_tag(VALUE obj)
tmp_class = CLASS_OF(obj);
while (!NIL_P(tmp_class)) {
- tag = rb_hash_lookup(class_tag_map, tmp_class);
- if (tag != Qnil)
- return NUM2INT(tag);
- tmp_class = rb_class_superclass(tmp_class);
+ tag = rb_hash_lookup(class_tag_map, tmp_class);
+ if (tag != Qnil)
+ return NUM2INT(tag);
+ tmp_class = rb_class_superclass(tmp_class);
}
return -1;
@@ -602,7 +613,7 @@ ossl_asn1_tag(VALUE obj)
tag = ossl_asn1_get_tag(obj);
if(NIL_P(tag))
- ossl_raise(eASN1Error, "tag number not specified");
+ ossl_raise(eASN1Error, "tag number not specified");
return NUM2INT(tag);
}
@@ -614,28 +625,28 @@ ossl_asn1_tag_class(VALUE obj)
s = ossl_asn1_get_tag_class(obj);
if (NIL_P(s) || s == sym_UNIVERSAL)
- return V_ASN1_UNIVERSAL;
+ return V_ASN1_UNIVERSAL;
else if (s == sym_APPLICATION)
- return V_ASN1_APPLICATION;
+ return V_ASN1_APPLICATION;
else if (s == sym_CONTEXT_SPECIFIC)
- return V_ASN1_CONTEXT_SPECIFIC;
+ return V_ASN1_CONTEXT_SPECIFIC;
else if (s == sym_PRIVATE)
- return V_ASN1_PRIVATE;
+ return V_ASN1_PRIVATE;
else
- ossl_raise(eASN1Error, "invalid tag class");
+ ossl_raise(eASN1Error, "invalid tag class");
}
static VALUE
ossl_asn1_class2sym(int tc)
{
if((tc & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
- return sym_PRIVATE;
+ return sym_PRIVATE;
else if((tc & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
- return sym_CONTEXT_SPECIFIC;
+ return sym_CONTEXT_SPECIFIC;
else if((tc & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
- return sym_APPLICATION;
+ return sym_APPLICATION;
else
- return sym_UNIVERSAL;
+ return sym_UNIVERSAL;
}
/*
@@ -658,7 +669,7 @@ static VALUE
ossl_asn1data_initialize(VALUE self, VALUE value, VALUE tag, VALUE tag_class)
{
if(!SYMBOL_P(tag_class))
- ossl_raise(eASN1Error, "invalid tag class");
+ ossl_raise(eASN1Error, "invalid tag class");
ossl_asn1_set_tag(self, tag);
ossl_asn1_set_value(self, value);
ossl_asn1_set_tag_class(self, tag_class);
@@ -680,35 +691,35 @@ to_der_internal(VALUE self, int constructed, int indef_len, VALUE body)
body_length = RSTRING_LENINT(body);
if (ossl_asn1_get_tagging(self) == sym_EXPLICIT) {
- int inner_length, e_encoding = indef_len ? 2 : 1;
-
- if (default_tag_number == -1)
- ossl_raise(eASN1Error, "explicit tagging of unknown tag");
-
- inner_length = ASN1_object_size(encoding, body_length, default_tag_number);
- total_length = ASN1_object_size(e_encoding, inner_length, tag_number);
- str = rb_str_new(NULL, total_length);
- p = (unsigned char *)RSTRING_PTR(str);
- /* Put explicit tag */
- ASN1_put_object(&p, e_encoding, inner_length, tag_number, tag_class);
- /* Append inner object */
- ASN1_put_object(&p, encoding, body_length, default_tag_number, V_ASN1_UNIVERSAL);
- memcpy(p, RSTRING_PTR(body), body_length);
- p += body_length;
- if (indef_len) {
- ASN1_put_eoc(&p); /* For inner object */
- ASN1_put_eoc(&p); /* For wrapper object */
- }
+ int inner_length, e_encoding = indef_len ? 2 : 1;
+
+ if (default_tag_number == -1)
+ ossl_raise(eASN1Error, "explicit tagging of unknown tag");
+
+ inner_length = ASN1_object_size(encoding, body_length, default_tag_number);
+ total_length = ASN1_object_size(e_encoding, inner_length, tag_number);
+ str = rb_str_new(NULL, total_length);
+ p = (unsigned char *)RSTRING_PTR(str);
+ /* Put explicit tag */
+ ASN1_put_object(&p, e_encoding, inner_length, tag_number, tag_class);
+ /* Append inner object */
+ ASN1_put_object(&p, encoding, body_length, default_tag_number, V_ASN1_UNIVERSAL);
+ memcpy(p, RSTRING_PTR(body), body_length);
+ p += body_length;
+ if (indef_len) {
+ ASN1_put_eoc(&p); /* For inner object */
+ ASN1_put_eoc(&p); /* For wrapper object */
+ }
}
else {
- total_length = ASN1_object_size(encoding, body_length, tag_number);
- str = rb_str_new(NULL, total_length);
- p = (unsigned char *)RSTRING_PTR(str);
- ASN1_put_object(&p, encoding, body_length, tag_number, tag_class);
- memcpy(p, RSTRING_PTR(body), body_length);
- p += body_length;
- if (indef_len)
- ASN1_put_eoc(&p);
+ total_length = ASN1_object_size(encoding, body_length, tag_number);
+ str = rb_str_new(NULL, total_length);
+ p = (unsigned char *)RSTRING_PTR(str);
+ ASN1_put_object(&p, encoding, body_length, tag_number, tag_class);
+ memcpy(p, RSTRING_PTR(body), body_length);
+ p += body_length;
+ if (indef_len)
+ ASN1_put_eoc(&p);
}
assert(p - (unsigned char *)RSTRING_PTR(str) == total_length);
return str;
@@ -731,18 +742,22 @@ ossl_asn1data_to_der(VALUE self)
VALUE value = ossl_asn1_get_value(self);
if (rb_obj_is_kind_of(value, rb_cArray))
- return ossl_asn1cons_to_der(self);
+ return ossl_asn1cons_to_der(self);
else {
- if (RTEST(ossl_asn1_get_indefinite_length(self)))
- ossl_raise(eASN1Error, "indefinite length form cannot be used " \
- "with primitive encoding");
- return ossl_asn1prim_to_der(self);
+ if (RTEST(ossl_asn1_get_indefinite_length(self)))
+ ossl_raise(eASN1Error, "indefinite length form cannot be used " \
+ "with primitive encoding");
+ return ossl_asn1prim_to_der(self);
}
}
+static VALUE ossl_asn1_initialize(int argc, VALUE *argv, VALUE self);
+static VALUE ossl_asn1_decode0(unsigned char **pp, long length, long *offset,
+ int depth, int yield, long *num_read);
+
static VALUE
int_ossl_asn1_decode0_prim(unsigned char **pp, long length, long hlen, int tag,
- VALUE tc, long *num_read)
+ VALUE tc, long *num_read)
{
VALUE value, asn1data;
unsigned char *p;
@@ -751,64 +766,64 @@ int_ossl_asn1_decode0_prim(unsigned char **pp, long length, long hlen, int tag,
p = *pp;
if(tc == sym_UNIVERSAL && tag < ossl_asn1_info_size) {
- switch(tag){
- case V_ASN1_EOC:
- value = decode_eoc(p, hlen+length);
- break;
- case V_ASN1_BOOLEAN:
- value = decode_bool(p, hlen+length);
- break;
- case V_ASN1_INTEGER:
- value = decode_int(p, hlen+length);
- break;
- case V_ASN1_BIT_STRING:
- value = decode_bstr(p, hlen+length, &flag);
- break;
- case V_ASN1_NULL:
- value = decode_null(p, hlen+length);
- break;
- case V_ASN1_ENUMERATED:
- value = decode_enum(p, hlen+length);
- break;
- case V_ASN1_OBJECT:
- value = decode_obj(p, hlen+length);
- break;
- case V_ASN1_UTCTIME: /* FALLTHROUGH */
- case V_ASN1_GENERALIZEDTIME:
- value = decode_time(p, hlen+length);
- break;
- default:
- /* use original value */
- p += hlen;
- value = rb_str_new((const char *)p, length);
- break;
- }
+ switch(tag){
+ case V_ASN1_EOC:
+ value = decode_eoc(p, hlen+length);
+ break;
+ case V_ASN1_BOOLEAN:
+ value = decode_bool(p, hlen+length);
+ break;
+ case V_ASN1_INTEGER:
+ value = decode_int(p, hlen+length);
+ break;
+ case V_ASN1_BIT_STRING:
+ value = decode_bstr(p, hlen+length, &flag);
+ break;
+ case V_ASN1_NULL:
+ value = decode_null(p, hlen+length);
+ break;
+ case V_ASN1_ENUMERATED:
+ value = decode_enum(p, hlen+length);
+ break;
+ case V_ASN1_OBJECT:
+ value = decode_obj(p, hlen+length);
+ break;
+ case V_ASN1_UTCTIME: /* FALLTHROUGH */
+ case V_ASN1_GENERALIZEDTIME:
+ value = decode_time(p, hlen+length);
+ break;
+ default:
+ /* use original value */
+ p += hlen;
+ value = rb_str_new((const char *)p, length);
+ break;
+ }
}
else {
- p += hlen;
- value = rb_str_new((const char *)p, length);
+ p += hlen;
+ value = rb_str_new((const char *)p, length);
}
*pp += hlen + length;
*num_read = hlen + length;
if (tc == sym_UNIVERSAL &&
- tag < ossl_asn1_info_size && ossl_asn1_info[tag].klass) {
- VALUE klass = *ossl_asn1_info[tag].klass;
- VALUE args[4];
- args[0] = value;
- args[1] = INT2NUM(tag);
- args[2] = Qnil;
- args[3] = tc;
- asn1data = rb_obj_alloc(klass);
- ossl_asn1_initialize(4, args, asn1data);
- if(tag == V_ASN1_BIT_STRING){
- rb_ivar_set(asn1data, sivUNUSED_BITS, LONG2NUM(flag));
- }
+ tag < ossl_asn1_info_size && ossl_asn1_info[tag].klass) {
+ VALUE klass = *ossl_asn1_info[tag].klass;
+ VALUE args[4];
+ args[0] = value;
+ args[1] = INT2NUM(tag);
+ args[2] = Qnil;
+ args[3] = tc;
+ asn1data = rb_obj_alloc(klass);
+ ossl_asn1_initialize(4, args, asn1data);
+ if(tag == V_ASN1_BIT_STRING){
+ rb_ivar_set(asn1data, sivUNUSED_BITS, LONG2NUM(flag));
+ }
}
else {
- asn1data = rb_obj_alloc(cASN1Data);
- ossl_asn1data_initialize(asn1data, value, INT2NUM(tag), tc);
+ asn1data = rb_obj_alloc(cASN1Data);
+ ossl_asn1data_initialize(asn1data, value, INT2NUM(tag), tc);
}
return asn1data;
@@ -816,8 +831,8 @@ int_ossl_asn1_decode0_prim(unsigned char **pp, long length, long hlen, int tag,
static VALUE
int_ossl_asn1_decode0_cons(unsigned char **pp, long max_len, long length,
- long *offset, int depth, int yield, int j,
- int tag, VALUE tc, long *num_read)
+ long *offset, int depth, int yield, int j,
+ int tag, VALUE tc, long *num_read)
{
VALUE value, asn1data, ary;
int indefinite;
@@ -828,40 +843,42 @@ int_ossl_asn1_decode0_cons(unsigned char **pp, long max_len, long length,
available_len = indefinite ? max_len : length;
while (available_len > 0) {
- long inner_read = 0;
- value = ossl_asn1_decode0(pp, available_len, &off, depth + 1, yield, &inner_read);
- *num_read += inner_read;
- available_len -= inner_read;
-
- if (indefinite &&
- ossl_asn1_tag(value) == V_ASN1_EOC &&
- ossl_asn1_get_tag_class(value) == sym_UNIVERSAL) {
- break;
- }
- rb_ary_push(ary, value);
+ long inner_read = 0;
+ value = ossl_asn1_decode0(pp, available_len, &off, depth + 1, yield, &inner_read);
+ *num_read += inner_read;
+ available_len -= inner_read;
+
+ if (indefinite) {
+ if (ossl_asn1_tag(value) == V_ASN1_EOC &&
+ ossl_asn1_get_tag_class(value) == sym_UNIVERSAL)
+ break;
+ if (available_len == 0)
+ ossl_raise(eASN1Error, "EOC missing in indefinite length encoding");
+ }
+ rb_ary_push(ary, value);
}
if (tc == sym_UNIVERSAL) {
- VALUE args[4];
- if (tag == V_ASN1_SEQUENCE || tag == V_ASN1_SET)
- asn1data = rb_obj_alloc(*ossl_asn1_info[tag].klass);
- else
- asn1data = rb_obj_alloc(cASN1Constructive);
- args[0] = ary;
- args[1] = INT2NUM(tag);
- args[2] = Qnil;
- args[3] = tc;
- ossl_asn1_initialize(4, args, asn1data);
+ VALUE args[4];
+ if (tag == V_ASN1_SEQUENCE || tag == V_ASN1_SET)
+ asn1data = rb_obj_alloc(*ossl_asn1_info[tag].klass);
+ else
+ asn1data = rb_obj_alloc(cASN1Constructive);
+ args[0] = ary;
+ args[1] = INT2NUM(tag);
+ args[2] = Qnil;
+ args[3] = tc;
+ ossl_asn1_initialize(4, args, asn1data);
}
else {
- asn1data = rb_obj_alloc(cASN1Data);
- ossl_asn1data_initialize(asn1data, ary, INT2NUM(tag), tc);
+ asn1data = rb_obj_alloc(cASN1Data);
+ ossl_asn1data_initialize(asn1data, ary, INT2NUM(tag), tc);
}
if (indefinite)
- ossl_asn1_set_indefinite_length(asn1data, Qtrue);
+ ossl_asn1_set_indefinite_length(asn1data, Qtrue);
else
- ossl_asn1_set_indefinite_length(asn1data, Qfalse);
+ ossl_asn1_set_indefinite_length(asn1data, Qfalse);
*offset = off;
return asn1data;
@@ -869,7 +886,7 @@ int_ossl_asn1_decode0_cons(unsigned char **pp, long max_len, long length,
static VALUE
ossl_asn1_decode0(unsigned char **pp, long length, long *offset, int depth,
- int yield, long *num_read)
+ int yield, long *num_read)
{
unsigned char *start, *p;
const unsigned char *p0;
@@ -885,46 +902,46 @@ ossl_asn1_decode0(unsigned char **pp, long length, long *offset, int depth,
if(j & 0x80) ossl_raise(eASN1Error, NULL);
if(len > length) ossl_raise(eASN1Error, "value is too short");
if((tc & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
- tag_class = sym_PRIVATE;
+ tag_class = sym_PRIVATE;
else if((tc & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
- tag_class = sym_CONTEXT_SPECIFIC;
+ tag_class = sym_CONTEXT_SPECIFIC;
else if((tc & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
- tag_class = sym_APPLICATION;
+ tag_class = sym_APPLICATION;
else
- tag_class = sym_UNIVERSAL;
+ tag_class = sym_UNIVERSAL;
hlen = p - start;
if(yield) {
- VALUE arg = rb_ary_new();
- rb_ary_push(arg, LONG2NUM(depth));
- rb_ary_push(arg, LONG2NUM(*offset));
- rb_ary_push(arg, LONG2NUM(hlen));
- rb_ary_push(arg, LONG2NUM(len));
- rb_ary_push(arg, (j & V_ASN1_CONSTRUCTED) ? Qtrue : Qfalse);
- rb_ary_push(arg, ossl_asn1_class2sym(tc));
- rb_ary_push(arg, INT2NUM(tag));
- rb_yield(arg);
+ VALUE arg = rb_ary_new();
+ rb_ary_push(arg, LONG2NUM(depth));
+ rb_ary_push(arg, LONG2NUM(*offset));
+ rb_ary_push(arg, LONG2NUM(hlen));
+ rb_ary_push(arg, LONG2NUM(len));
+ rb_ary_push(arg, (j & V_ASN1_CONSTRUCTED) ? Qtrue : Qfalse);
+ rb_ary_push(arg, ossl_asn1_class2sym(tc));
+ rb_ary_push(arg, INT2NUM(tag));
+ rb_yield(arg);
}
if(j & V_ASN1_CONSTRUCTED) {
- *pp += hlen;
- off += hlen;
- asn1data = int_ossl_asn1_decode0_cons(pp, length - hlen, len, &off, depth, yield, j, tag, tag_class, &inner_read);
- inner_read += hlen;
+ *pp += hlen;
+ off += hlen;
+ asn1data = int_ossl_asn1_decode0_cons(pp, length - hlen, len, &off, depth, yield, j, tag, tag_class, &inner_read);
+ inner_read += hlen;
}
else {
- if ((j & 0x01) && (len == 0))
- ossl_raise(eASN1Error, "indefinite length for primitive value");
- asn1data = int_ossl_asn1_decode0_prim(pp, len, hlen, tag, tag_class, &inner_read);
- off += hlen + len;
+ if ((j & 0x01) && (len == 0))
+ ossl_raise(eASN1Error, "indefinite length for primitive value");
+ asn1data = int_ossl_asn1_decode0_prim(pp, len, hlen, tag, tag_class, &inner_read);
+ off += hlen + len;
}
if (num_read)
- *num_read = inner_read;
+ *num_read = inner_read;
if (len != 0 && inner_read != hlen + len) {
- ossl_raise(eASN1Error,
- "Type mismatch. Bytes read: %ld Bytes available: %ld",
- inner_read, hlen + len);
+ ossl_raise(eASN1Error,
+ "Type mismatch. Bytes read: %ld Bytes available: %ld",
+ inner_read, hlen + len);
}
*offset = off;
@@ -935,9 +952,9 @@ static void
int_ossl_decode_sanity_check(long len, long read, long offset)
{
if (len != 0 && (read != len || offset != len)) {
- ossl_raise(eASN1Error,
- "Type mismatch. Total bytes read: %ld Bytes available: %ld Offset: %ld",
- read, len, offset);
+ ossl_raise(eASN1Error,
+ "Type mismatch. Total bytes read: %ld Bytes available: %ld Offset: %ld",
+ read, len, offset);
}
}
@@ -1037,11 +1054,11 @@ ossl_asn1_decode_all(VALUE self, VALUE obj)
tmp_len = len;
ary = rb_ary_new();
while (tmp_len > 0) {
- long tmp_read = 0;
- val = ossl_asn1_decode0(&p, tmp_len, &offset, 0, 0, &tmp_read);
- rb_ary_push(ary, val);
- read += tmp_read;
- tmp_len -= tmp_read;
+ long tmp_read = 0;
+ val = ossl_asn1_decode0(&p, tmp_len, &offset, 0, 0, &tmp_read);
+ rb_ary_push(ary, val);
+ read += tmp_read;
+ tmp_len -= tmp_read;
}
RB_GC_GUARD(tmp);
int_ossl_decode_sanity_check(len, read, offset);
@@ -1081,23 +1098,23 @@ ossl_asn1_initialize(int argc, VALUE *argv, VALUE self)
default_tag = ossl_asn1_default_tag(self);
if (default_tag == -1 || argc > 1) {
- if(NIL_P(tag))
- ossl_raise(eASN1Error, "must specify tag number");
- if(!NIL_P(tagging) && !SYMBOL_P(tagging))
- ossl_raise(eASN1Error, "invalid tagging method");
- if(NIL_P(tag_class)) {
- if (NIL_P(tagging))
- tag_class = sym_UNIVERSAL;
- else
- tag_class = sym_CONTEXT_SPECIFIC;
- }
- if(!SYMBOL_P(tag_class))
- ossl_raise(eASN1Error, "invalid tag class");
+ if(NIL_P(tag))
+ ossl_raise(eASN1Error, "must specify tag number");
+ if(!NIL_P(tagging) && !SYMBOL_P(tagging))
+ ossl_raise(eASN1Error, "invalid tagging method");
+ if(NIL_P(tag_class)) {
+ if (NIL_P(tagging))
+ tag_class = sym_UNIVERSAL;
+ else
+ tag_class = sym_CONTEXT_SPECIFIC;
+ }
+ if(!SYMBOL_P(tag_class))
+ ossl_raise(eASN1Error, "invalid tag class");
}
else{
- tag = INT2NUM(default_tag);
- tagging = Qnil;
- tag_class = sym_UNIVERSAL;
+ tag = INT2NUM(default_tag);
+ tagging = Qnil;
+ tag_class = sym_UNIVERSAL;
}
ossl_asn1_set_tag(self, tag);
ossl_asn1_set_value(self, value);
@@ -1105,7 +1122,7 @@ ossl_asn1_initialize(int argc, VALUE *argv, VALUE self)
ossl_asn1_set_tag_class(self, tag_class);
ossl_asn1_set_indefinite_length(self, Qfalse);
if (default_tag == V_ASN1_BIT_STRING)
- rb_ivar_set(self, sivUNUSED_BITS, INT2FIX(0));
+ rb_ivar_set(self, sivUNUSED_BITS, INT2FIX(0));
return self;
}
@@ -1147,20 +1164,20 @@ ossl_asn1prim_to_der(VALUE self)
VALUE str;
if (ossl_asn1_default_tag(self) == -1) {
- str = ossl_asn1_get_value(self);
- return to_der_internal(self, 0, 0, StringValue(str));
+ str = ossl_asn1_get_value(self);
+ return to_der_internal(self, 0, 0, StringValue(str));
}
asn1 = ossl_asn1_get_asn1type(self);
alllen = i2d_ASN1_TYPE(asn1, NULL);
if (alllen < 0) {
- ASN1_TYPE_free(asn1);
- ossl_raise(eASN1Error, "i2d_ASN1_TYPE");
+ ASN1_TYPE_free(asn1);
+ ossl_raise(eASN1Error, "i2d_ASN1_TYPE");
}
str = ossl_str_new(NULL, alllen, &state);
if (state) {
- ASN1_TYPE_free(asn1);
- rb_jump_tag(state);
+ ASN1_TYPE_free(asn1);
+ rb_jump_tag(state);
}
p0 = p1 = (unsigned char *)RSTRING_PTR(str);
if (i2d_ASN1_TYPE(asn1, &p0) < 0) {
@@ -1173,7 +1190,7 @@ ossl_asn1prim_to_der(VALUE self)
/* Strip header since to_der_internal() wants only the payload */
j = ASN1_get_object((const unsigned char **)&p1, &bodylen, &tag, &tc, alllen);
if (j & 0x80)
- ossl_raise(eASN1Error, "ASN1_get_object"); /* should not happen */
+ ossl_raise(eASN1Error, "ASN1_get_object"); /* should not happen */
return to_der_internal(self, 0, 0, rb_str_drop_bytes(str, alllen - bodylen));
}
@@ -1195,22 +1212,22 @@ ossl_asn1cons_to_der(VALUE self)
ary = rb_convert_type(ossl_asn1_get_value(self), T_ARRAY, "Array", "to_a");
str = rb_str_new(NULL, 0);
for (i = 0; i < RARRAY_LEN(ary); i++) {
- VALUE item = RARRAY_AREF(ary, i);
-
- if (indef_len && rb_obj_is_kind_of(item, cASN1EndOfContent)) {
- if (i != RARRAY_LEN(ary) - 1)
- ossl_raise(eASN1Error, "illegal EOC octets in value");
-
- /*
- * EOC is not really part of the content, but we required to add one
- * at the end in the past.
- */
- break;
- }
-
- item = ossl_to_der_if_possible(item);
- StringValue(item);
- rb_str_append(str, item);
+ VALUE item = RARRAY_AREF(ary, i);
+
+ if (indef_len && rb_obj_is_kind_of(item, cASN1EndOfContent)) {
+ if (i != RARRAY_LEN(ary) - 1)
+ ossl_raise(eASN1Error, "illegal EOC octets in value");
+
+ /*
+ * EOC is not really part of the content, but we required to add one
+ * at the end in the past.
+ */
+ break;
+ }
+
+ item = ossl_to_der_if_possible(item);
+ StringValue(item);
+ rb_str_append(str, item);
}
return to_der_internal(self, 1, indef_len, str);
@@ -1256,7 +1273,7 @@ ossl_asn1obj_s_register(VALUE self, VALUE oid, VALUE sn, VALUE ln)
StringValueCStr(ln);
if(!OBJ_create(RSTRING_PTR(oid), RSTRING_PTR(sn), RSTRING_PTR(ln)))
- ossl_raise(eASN1Error, NULL);
+ ossl_raise(eASN1Error, NULL);
return Qtrue;
}
@@ -1276,7 +1293,7 @@ ossl_asn1obj_get_sn(VALUE self)
val = ossl_asn1_get_value(self);
if ((nid = OBJ_txt2nid(StringValueCStr(val))) != NID_undef)
- ret = rb_str_new2(OBJ_nid2sn(nid));
+ ret = rb_str_new2(OBJ_nid2sn(nid));
return ret;
}
@@ -1296,55 +1313,15 @@ ossl_asn1obj_get_ln(VALUE self)
val = ossl_asn1_get_value(self);
if ((nid = OBJ_txt2nid(StringValueCStr(val))) != NID_undef)
- ret = rb_str_new2(OBJ_nid2ln(nid));
+ ret = rb_str_new2(OBJ_nid2ln(nid));
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)
{
- ASN1_OBJECT *a1obj = (void *)vobj;
- VALUE str;
- int len;
-
- str = rb_usascii_str_new(NULL, 127);
- len = OBJ_obj2txt(RSTRING_PTR(str), RSTRING_LENINT(str), a1obj, 1);
- if (len <= 0 || len == INT_MAX)
- ossl_raise(eASN1Error, "OBJ_obj2txt");
- if (len > RSTRING_LEN(str)) {
- /* +1 is for the \0 terminator added by OBJ_obj2txt() */
- rb_str_resize(str, len + 1);
- len = OBJ_obj2txt(RSTRING_PTR(str), len + 1, a1obj, 1);
- if (len <= 0)
- ossl_raise(eASN1Error, "OBJ_obj2txt");
- }
- rb_str_set_len(str, len);
- return str;
+ return ossl_asn1obj_to_string_oid((const ASN1_OBJECT *)vobj);
}
/*
@@ -1361,14 +1338,33 @@ ossl_asn1obj_get_oid(VALUE self)
ASN1_OBJECT *a1obj;
int state;
- a1obj = obj_to_asn1obj(ossl_asn1_get_value(self));
+ a1obj = ossl_to_asn1obj(ossl_asn1_get_value(self));
str = rb_protect(asn1obj_get_oid_i, (VALUE)a1obj, &state);
ASN1_OBJECT_free(a1obj);
if (state)
- rb_jump_tag(state);
+ rb_jump_tag(state);
return str;
}
+/*
+ * call-seq:
+ * oid == other_oid => true or false
+ *
+ * Returns +true+ if _other_oid_ is the same as _oid_.
+ */
+static VALUE
+ossl_asn1obj_eq(VALUE self, VALUE other)
+{
+ VALUE oid1, oid2;
+
+ if (!rb_obj_is_kind_of(other, cASN1ObjectId))
+ return Qfalse;
+
+ oid1 = ossl_asn1obj_get_oid(self);
+ oid2 = ossl_asn1obj_get_oid(other);
+ return rb_str_equal(oid1, oid2);
+}
+
#define OSSL_ASN1_IMPL_FACTORY_METHOD(klass) \
static VALUE ossl_asn1_##klass(int argc, VALUE *argv, VALUE self)\
{ return rb_funcall3(cASN1##klass, rb_intern("new"), argc, argv); }
@@ -1401,13 +1397,6 @@ void
Init_ossl_asn1(void)
{
#undef rb_intern
- VALUE ary;
- int i;
-
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
-#endif
sym_UNIVERSAL = ID2SYM(rb_intern_const("UNIVERSAL"));
sym_CONTEXT_SPECIFIC = ID2SYM(rb_intern_const("CONTEXT_SPECIFIC"));
@@ -1557,17 +1546,20 @@ Init_ossl_asn1(void)
rb_define_module_function(mASN1, "traverse", ossl_asn1_traverse, 1);
rb_define_module_function(mASN1, "decode", ossl_asn1_decode, 1);
rb_define_module_function(mASN1, "decode_all", ossl_asn1_decode_all, 1);
- ary = rb_ary_new();
+ VALUE ary = rb_ary_new_capa(ossl_asn1_info_size);
+ for (int i = 0; i < ossl_asn1_info_size; i++) {
+ const char *name = ossl_asn1_info[i].name;
+ if (name[0] == '[')
+ continue;
+ rb_define_const(mASN1, name, INT2NUM(i));
+ rb_ary_store(ary, i, rb_obj_freeze(rb_str_new_cstr(name)));
+ }
+ rb_obj_freeze(ary);
/*
* Array storing tag names at the tag's index.
*/
rb_define_const(mASN1, "UNIVERSAL_TAG_NAME", ary);
- for(i = 0; i < ossl_asn1_info_size; i++){
- if(ossl_asn1_info[i].name[0] == '[') continue;
- rb_define_const(mASN1, ossl_asn1_info[i].name, INT2NUM(i));
- rb_ary_store(ary, i, rb_str_new2(ossl_asn1_info[i].name));
- }
/* Document-class: OpenSSL::ASN1::ASN1Data
*
@@ -1889,6 +1881,7 @@ do{\
rb_hash_aset(class_tag_map, cASN1GeneralString, INT2NUM(V_ASN1_GENERALSTRING));
rb_hash_aset(class_tag_map, cASN1UniversalString, INT2NUM(V_ASN1_UNIVERSALSTRING));
rb_hash_aset(class_tag_map, cASN1BMPString, INT2NUM(V_ASN1_BMPSTRING));
+ rb_obj_freeze(class_tag_map);
id_each = rb_intern_const("each");
}
diff --git a/ext/openssl/ossl_asn1.h b/ext/openssl/ossl_asn1.h
index 939a96ce74..b605df8f3f 100644
--- a/ext/openssl/ossl_asn1.h
+++ b/ext/openssl/ossl_asn1.h
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_ASN1_H_)
#define _OSSL_ASN1_H_
@@ -32,30 +32,26 @@ VALUE asn1integer_to_num(const ASN1_INTEGER *);
ASN1_INTEGER *num_to_asn1integer(VALUE, ASN1_INTEGER *);
/*
+ * ASN1_OBJECT conversions
+ */
+ASN1_OBJECT *ossl_to_asn1obj(VALUE obj);
+/*
+ * Returns the short name if available, the dotted decimal notation otherwise.
+ * This is the most common way to return ASN1_OBJECT to Ruby.
+ */
+VALUE ossl_asn1obj_to_string(const ASN1_OBJECT *a1obj);
+/*
+ * However, some places use long names instead. This is likely unintentional,
+ * but we keep the current behavior in existing methods.
+ */
+VALUE ossl_asn1obj_to_string_long_name(const ASN1_OBJECT *a1obj);
+
+/*
* ASN1 module
*/
extern VALUE mASN1;
-extern VALUE eASN1Error;
extern VALUE cASN1Data;
-extern VALUE cASN1Primitive;
-extern VALUE cASN1Constructive;
-
-extern VALUE cASN1Boolean; /* BOOLEAN */
-extern VALUE cASN1Integer, cASN1Enumerated; /* INTEGER */
-extern VALUE cASN1BitString; /* BIT STRING */
-extern VALUE cASN1OctetString, cASN1UTF8String; /* STRINGs */
-extern VALUE cASN1NumericString, cASN1PrintableString;
-extern VALUE cASN1T61String, cASN1VideotexString;
-extern VALUE cASN1IA5String, cASN1GraphicString;
-extern VALUE cASN1ISO64String, cASN1GeneralString;
-extern VALUE cASN1UniversalString, cASN1BMPString;
-extern VALUE cASN1Null; /* NULL */
-extern VALUE cASN1ObjectId; /* OBJECT IDENTIFIER */
-extern VALUE cASN1UTCTime, cASN1GeneralizedTime; /* TIME */
-extern VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */
-
-ASN1_TYPE *ossl_asn1_get_asn1type(VALUE);
void Init_ossl_asn1(void);
diff --git a/ext/openssl/ossl_bio.c b/ext/openssl/ossl_bio.c
index 42833d901a..4edde5091d 100644
--- a/ext/openssl/ossl_bio.c
+++ b/ext/openssl/ossl_bio.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -16,11 +16,11 @@ ossl_obj2bio(volatile VALUE *pobj)
BIO *bio;
if (RB_TYPE_P(obj, T_FILE))
- obj = rb_funcallv(obj, rb_intern("read"), 0, NULL);
+ obj = rb_funcallv(obj, rb_intern("read"), 0, NULL);
StringValue(obj);
bio = BIO_new_mem_buf(RSTRING_PTR(obj), RSTRING_LENINT(obj));
if (!bio)
- ossl_raise(eOSSLError, "BIO_new_mem_buf");
+ ossl_raise(eOSSLError, "BIO_new_mem_buf");
*pobj = obj;
return bio;
}
@@ -36,7 +36,7 @@ ossl_membio2str(BIO *bio)
ret = ossl_str_new(buf->data, buf->length, &state);
BIO_free(bio);
if (state)
- rb_jump_tag(state);
+ rb_jump_tag(state);
return ret;
}
diff --git a/ext/openssl/ossl_bio.h b/ext/openssl/ossl_bio.h
index da68c5e5a2..1b871f1cd7 100644
--- a/ext/openssl/ossl_bio.h
+++ b/ext/openssl/ossl_bio.h
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_BIO_H_)
#define _OSSL_BIO_H_
diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c
index ce0d3ec7ee..9014f2df2b 100644
--- a/ext/openssl/ossl_bn.c
+++ b/ext/openssl/ossl_bn.c
@@ -5,29 +5,25 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
/* modified by Michal Rokos <m.rokos@sh.cvut.cz> */
#include "ossl.h"
-#ifdef HAVE_RB_EXT_RACTOR_SAFE
-#include <ruby/ractor.h>
-#endif
-
#define NewBN(klass) \
- TypedData_Wrap_Struct((klass), &ossl_bn_type, 0)
+ TypedData_Wrap_Struct((klass), &ossl_bn_type, 0)
#define SetBN(obj, bn) do { \
- if (!(bn)) { \
- ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \
- } \
- RTYPEDDATA_DATA(obj) = (bn); \
+ if (!(bn)) { \
+ ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \
+ } \
+ RTYPEDDATA_DATA(obj) = (bn); \
} while (0)
#define GetBN(obj, bn) do { \
- TypedData_Get_Struct((obj), BIGNUM, &ossl_bn_type, (bn)); \
- if (!(bn)) { \
- ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \
- } \
+ TypedData_Get_Struct((obj), BIGNUM, &ossl_bn_type, (bn)); \
+ if (!(bn)) { \
+ ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \
+ } \
} while (0)
static void
@@ -39,9 +35,9 @@ ossl_bn_free(void *ptr)
static const rb_data_type_t ossl_bn_type = {
"OpenSSL/BN",
{
- 0, ossl_bn_free,
+ 0, ossl_bn_free,
},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE,
};
/*
@@ -53,7 +49,7 @@ VALUE cBN;
*
* Generic Error for all of OpenSSL::BN (big num)
*/
-VALUE eBNError;
+static VALUE eBNError;
/*
* Public
@@ -65,10 +61,9 @@ ossl_bn_new(const BIGNUM *bn)
VALUE obj;
obj = NewBN(cBN);
- newbn = bn ? BN_dup(bn) : BN_new();
- if (!newbn) {
- ossl_raise(eBNError, NULL);
- }
+ newbn = BN_dup(bn);
+ if (!newbn)
+ ossl_raise(eBNError, "BN_dup");
SetBN(obj, newbn);
return obj;
@@ -80,40 +75,40 @@ integer_to_bnptr(VALUE obj, BIGNUM *orig)
BIGNUM *bn;
if (FIXNUM_P(obj)) {
- long i;
- unsigned char bin[sizeof(long)];
- long n = FIX2LONG(obj);
- unsigned long un = labs(n);
-
- for (i = sizeof(long) - 1; 0 <= i; i--) {
- bin[i] = un & 0xff;
- un >>= 8;
- }
-
- bn = BN_bin2bn(bin, sizeof(bin), orig);
- if (!bn)
- ossl_raise(eBNError, "BN_bin2bn");
- if (n < 0)
- BN_set_negative(bn, 1);
+ long i;
+ unsigned char bin[sizeof(long)];
+ long n = FIX2LONG(obj);
+ unsigned long un = labs(n);
+
+ for (i = sizeof(long) - 1; 0 <= i; i--) {
+ bin[i] = un & 0xff;
+ un >>= 8;
+ }
+
+ bn = BN_bin2bn(bin, sizeof(bin), orig);
+ if (!bn)
+ ossl_raise(eBNError, "BN_bin2bn");
+ if (n < 0)
+ BN_set_negative(bn, 1);
}
else { /* assuming Bignum */
- size_t len = rb_absint_size(obj, NULL);
- unsigned char *bin;
- VALUE buf;
- int sign;
-
- if (INT_MAX < len) {
- rb_raise(eBNError, "bignum too long");
- }
- bin = (unsigned char*)ALLOCV_N(unsigned char, buf, len);
- sign = rb_integer_pack(obj, bin, len, 1, 0, INTEGER_PACK_BIG_ENDIAN);
-
- bn = BN_bin2bn(bin, (int)len, orig);
- ALLOCV_END(buf);
- if (!bn)
- ossl_raise(eBNError, "BN_bin2bn");
- if (sign < 0)
- BN_set_negative(bn, 1);
+ size_t len = rb_absint_size(obj, NULL);
+ unsigned char *bin;
+ VALUE buf;
+ int sign;
+
+ if (INT_MAX < len) {
+ rb_raise(eBNError, "bignum too long");
+ }
+ bin = (unsigned char*)ALLOCV_N(unsigned char, buf, len);
+ sign = rb_integer_pack(obj, bin, len, 1, 0, INTEGER_PACK_BIG_ENDIAN);
+
+ bn = BN_bin2bn(bin, (int)len, orig);
+ ALLOCV_END(buf);
+ if (!bn)
+ ossl_raise(eBNError, "BN_bin2bn");
+ if (sign < 0)
+ BN_set_negative(bn, 1);
}
return bn;
@@ -126,11 +121,11 @@ try_convert_to_bn(VALUE obj)
VALUE newobj = Qnil;
if (rb_obj_is_kind_of(obj, cBN))
- return obj;
+ return obj;
if (RB_INTEGER_TYPE_P(obj)) {
- newobj = NewBN(cBN); /* Handle potential mem leaks */
- bn = integer_to_bnptr(obj, NULL);
- SetBN(newobj, bn);
+ newobj = NewBN(cBN); /* Handle potential mem leaks */
+ bn = integer_to_bnptr(obj, NULL);
+ SetBN(newobj, bn);
}
return newobj;
@@ -144,7 +139,7 @@ ossl_bn_value_ptr(volatile VALUE *ptr)
tmp = try_convert_to_bn(*ptr);
if (NIL_P(tmp))
- ossl_raise(rb_eTypeError, "Cannot convert into OpenSSL::BN");
+ ossl_raise(rb_eTypeError, "Cannot convert into OpenSSL::BN");
GetBN(tmp, bn);
*ptr = tmp;
@@ -156,19 +151,19 @@ ossl_bn_value_ptr(volatile VALUE *ptr)
*/
#ifdef HAVE_RB_EXT_RACTOR_SAFE
-void
+static void
ossl_bn_ctx_free(void *ptr)
{
BN_CTX *ctx = (BN_CTX *)ptr;
BN_CTX_free(ctx);
}
-struct rb_ractor_local_storage_type ossl_bn_ctx_key_type = {
+static struct rb_ractor_local_storage_type ossl_bn_ctx_key_type = {
NULL, // mark
ossl_bn_ctx_free,
};
-rb_ractor_local_key_t ossl_bn_ctx_key;
+static rb_ractor_local_key_t ossl_bn_ctx_key;
BN_CTX *
ossl_bn_ctx_get(void)
@@ -214,7 +209,7 @@ ossl_bn_alloc(VALUE klass)
VALUE obj = NewBN(klass);
if (!(bn = BN_new())) {
- ossl_raise(eBNError, NULL);
+ ossl_raise(eBNError, NULL);
}
SetBN(obj, bn);
@@ -244,7 +239,7 @@ ossl_bn_alloc(VALUE klass)
* number.
* - +10+ - Decimal number representation, with a leading '-' for a negative
* number.
- * - +16+ - Hexadeciaml number representation, with a leading '-' for a
+ * - +16+ - Hexadecimal number representation, with a leading '-' for a
* negative number.
*/
static VALUE
@@ -256,57 +251,58 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
char *ptr;
if (rb_scan_args(argc, argv, "11", &str, &bs) == 2) {
- base = NUM2INT(bs);
+ base = NUM2INT(bs);
}
if (NIL_P(str)) {
ossl_raise(rb_eArgError, "invalid argument");
}
+ rb_check_frozen(self);
if (RB_INTEGER_TYPE_P(str)) {
- GetBN(self, bn);
- integer_to_bnptr(str, bn);
+ GetBN(self, bn);
+ integer_to_bnptr(str, bn);
- return self;
+ return self;
}
if (RTEST(rb_obj_is_kind_of(str, cBN))) {
- BIGNUM *other;
-
- GetBN(self, bn);
- GetBN(str, other); /* Safe - we checked kind_of? above */
- if (!BN_copy(bn, other)) {
- ossl_raise(eBNError, NULL);
- }
- return self;
+ BIGNUM *other;
+
+ GetBN(self, bn);
+ GetBN(str, other); /* Safe - we checked kind_of? above */
+ if (!BN_copy(bn, other)) {
+ ossl_raise(eBNError, NULL);
+ }
+ return self;
}
GetBN(self, bn);
switch (base) {
- case 0:
+ case 0:
ptr = StringValuePtr(str);
if (!BN_mpi2bn((unsigned char *)ptr, RSTRING_LENINT(str), bn)) {
- ossl_raise(eBNError, NULL);
- }
- break;
- case 2:
+ ossl_raise(eBNError, NULL);
+ }
+ break;
+ case 2:
ptr = StringValuePtr(str);
if (!BN_bin2bn((unsigned char *)ptr, RSTRING_LENINT(str), bn)) {
- ossl_raise(eBNError, NULL);
- }
- break;
- case 10:
- if (!BN_dec2bn(&bn, StringValueCStr(str))) {
- ossl_raise(eBNError, NULL);
- }
- break;
- case 16:
- if (!BN_hex2bn(&bn, StringValueCStr(str))) {
- ossl_raise(eBNError, NULL);
- }
- break;
- default:
- ossl_raise(rb_eArgError, "invalid radix %d", base);
+ ossl_raise(eBNError, NULL);
+ }
+ break;
+ case 10:
+ if (!BN_dec2bn(&bn, StringValueCStr(str))) {
+ ossl_raise(eBNError, NULL);
+ }
+ break;
+ case 16:
+ if (!BN_hex2bn(&bn, StringValueCStr(str))) {
+ ossl_raise(eBNError, NULL);
+ }
+ break;
+ default:
+ ossl_raise(rb_eArgError, "invalid radix %d", base);
}
return self;
}
@@ -326,7 +322,7 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
* the bignum is ignored.
* - +10+ - Decimal number representation, with a leading '-' for a negative
* bignum.
- * - +16+ - Hexadeciaml number representation, with a leading '-' for a
+ * - +16+ - Hexadecimal number representation, with a leading '-' for a
* negative bignum.
*/
static VALUE
@@ -338,32 +334,32 @@ ossl_bn_to_s(int argc, VALUE *argv, VALUE self)
char *buf;
if (rb_scan_args(argc, argv, "01", &bs) == 1) {
- base = NUM2INT(bs);
+ base = NUM2INT(bs);
}
GetBN(self, bn);
switch (base) {
- case 0:
- len = BN_bn2mpi(bn, NULL);
+ case 0:
+ len = BN_bn2mpi(bn, NULL);
str = rb_str_new(0, len);
- if (BN_bn2mpi(bn, (unsigned char *)RSTRING_PTR(str)) != len)
- ossl_raise(eBNError, NULL);
- break;
- case 2:
- len = BN_num_bytes(bn);
+ if (BN_bn2mpi(bn, (unsigned char *)RSTRING_PTR(str)) != len)
+ ossl_raise(eBNError, NULL);
+ break;
+ case 2:
+ len = BN_num_bytes(bn);
str = rb_str_new(0, len);
- if (BN_bn2bin(bn, (unsigned char *)RSTRING_PTR(str)) != len)
- ossl_raise(eBNError, NULL);
- break;
- case 10:
- if (!(buf = BN_bn2dec(bn))) ossl_raise(eBNError, NULL);
- str = ossl_buf2str(buf, rb_long2int(strlen(buf)));
- break;
- case 16:
- if (!(buf = BN_bn2hex(bn))) ossl_raise(eBNError, NULL);
- str = ossl_buf2str(buf, rb_long2int(strlen(buf)));
- break;
- default:
- ossl_raise(rb_eArgError, "invalid radix %d", base);
+ if (BN_bn2bin(bn, (unsigned char *)RSTRING_PTR(str)) != len)
+ ossl_raise(eBNError, NULL);
+ break;
+ case 10:
+ if (!(buf = BN_bn2dec(bn))) ossl_raise(eBNError, NULL);
+ str = ossl_buf2str(buf, rb_long2int(strlen(buf)));
+ break;
+ case 16:
+ if (!(buf = BN_bn2hex(bn))) ossl_raise(eBNError, NULL);
+ str = ossl_buf2str(buf, rb_long2int(strlen(buf)));
+ break;
+ default:
+ ossl_raise(rb_eArgError, "invalid radix %d", base);
}
return str;
@@ -383,7 +379,7 @@ ossl_bn_to_i(VALUE self)
GetBN(self, bn);
if (!(txt = BN_bn2hex(bn))) {
- ossl_raise(eBNError, NULL);
+ ossl_raise(eBNError, NULL);
}
num = rb_cstr_to_inum(txt, 16, Qtrue);
OPENSSL_free(txt);
@@ -401,31 +397,31 @@ static VALUE
ossl_bn_coerce(VALUE self, VALUE other)
{
switch(TYPE(other)) {
- case T_STRING:
- self = ossl_bn_to_s(0, NULL, self);
- break;
- case T_FIXNUM:
- case T_BIGNUM:
- self = ossl_bn_to_i(self);
- break;
- default:
- if (!RTEST(rb_obj_is_kind_of(other, cBN))) {
- ossl_raise(rb_eTypeError, "Don't know how to coerce");
- }
+ case T_STRING:
+ self = ossl_bn_to_s(0, NULL, self);
+ break;
+ case T_FIXNUM:
+ case T_BIGNUM:
+ self = ossl_bn_to_i(self);
+ break;
+ default:
+ if (!RTEST(rb_obj_is_kind_of(other, cBN))) {
+ ossl_raise(rb_eTypeError, "Don't know how to coerce");
+ }
}
return rb_assoc_new(other, self);
}
-#define BIGNUM_BOOL1(func) \
- static VALUE \
- ossl_bn_##func(VALUE self) \
- { \
- BIGNUM *bn; \
- GetBN(self, bn); \
- if (BN_##func(bn)) { \
- return Qtrue; \
- } \
- return Qfalse; \
+#define BIGNUM_BOOL1(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self) \
+ { \
+ BIGNUM *bn; \
+ GetBN(self, bn); \
+ if (BN_##func(bn)) { \
+ return Qtrue; \
+ } \
+ return Qfalse; \
}
/*
@@ -460,27 +456,27 @@ ossl_bn_is_negative(VALUE self)
GetBN(self, bn);
if (BN_is_zero(bn))
- return Qfalse;
+ return Qfalse;
return BN_is_negative(bn) ? Qtrue : Qfalse;
}
-#define BIGNUM_1c(func) \
- static VALUE \
- ossl_bn_##func(VALUE self) \
- { \
- BIGNUM *bn, *result; \
- VALUE obj; \
- GetBN(self, bn); \
- obj = NewBN(rb_obj_class(self)); \
- if (!(result = BN_new())) { \
- ossl_raise(eBNError, NULL); \
- } \
- if (BN_##func(result, bn, ossl_bn_ctx) <= 0) { \
- BN_free(result); \
- ossl_raise(eBNError, NULL); \
- } \
- SetBN(obj, result); \
- return obj; \
+#define BIGNUM_1c(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self) \
+ { \
+ BIGNUM *bn, *result; \
+ VALUE obj; \
+ GetBN(self, bn); \
+ obj = NewBN(rb_obj_class(self)); \
+ if (!(result = BN_new())) { \
+ ossl_raise(eBNError, NULL); \
+ } \
+ if (BN_##func(result, bn, ossl_bn_ctx) <= 0) { \
+ BN_free(result); \
+ ossl_raise(eBNError, NULL); \
+ } \
+ SetBN(obj, result); \
+ return obj; \
}
/*
@@ -490,23 +486,23 @@ ossl_bn_is_negative(VALUE self)
*/
BIGNUM_1c(sqr)
-#define BIGNUM_2(func) \
- static VALUE \
- ossl_bn_##func(VALUE self, VALUE other) \
- { \
- BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \
- VALUE obj; \
- GetBN(self, bn1); \
- obj = NewBN(rb_obj_class(self)); \
- if (!(result = BN_new())) { \
- ossl_raise(eBNError, NULL); \
- } \
- if (BN_##func(result, bn1, bn2) <= 0) { \
- BN_free(result); \
- ossl_raise(eBNError, NULL); \
- } \
- SetBN(obj, result); \
- return obj; \
+#define BIGNUM_2(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self, VALUE other) \
+ { \
+ BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \
+ VALUE obj; \
+ GetBN(self, bn1); \
+ obj = NewBN(rb_obj_class(self)); \
+ if (!(result = BN_new())) { \
+ ossl_raise(eBNError, NULL); \
+ } \
+ if (BN_##func(result, bn1, bn2) <= 0) { \
+ BN_free(result); \
+ ossl_raise(eBNError, NULL); \
+ } \
+ SetBN(obj, result); \
+ return obj; \
}
/*
@@ -523,23 +519,23 @@ BIGNUM_2(add)
*/
BIGNUM_2(sub)
-#define BIGNUM_2c(func) \
- static VALUE \
- ossl_bn_##func(VALUE self, VALUE other) \
- { \
- BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \
- VALUE obj; \
- GetBN(self, bn1); \
- obj = NewBN(rb_obj_class(self)); \
- if (!(result = BN_new())) { \
- ossl_raise(eBNError, NULL); \
- } \
- if (BN_##func(result, bn1, bn2, ossl_bn_ctx) <= 0) { \
- BN_free(result); \
- ossl_raise(eBNError, NULL); \
- } \
- SetBN(obj, result); \
- return obj; \
+#define BIGNUM_2c(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self, VALUE other) \
+ { \
+ BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \
+ VALUE obj; \
+ GetBN(self, bn1); \
+ obj = NewBN(rb_obj_class(self)); \
+ if (!(result = BN_new())) { \
+ ossl_raise(eBNError, NULL); \
+ } \
+ if (BN_##func(result, bn1, bn2, ossl_bn_ctx) <= 0) { \
+ BN_free(result); \
+ ossl_raise(eBNError, NULL); \
+ } \
+ SetBN(obj, result); \
+ return obj; \
}
/*
@@ -577,18 +573,18 @@ BIGNUM_2c(gcd)
*/
BIGNUM_2c(mod_sqr)
-#define BIGNUM_2cr(func) \
- static VALUE \
- ossl_bn_##func(VALUE self, VALUE other) \
- { \
- BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \
- VALUE obj; \
- GetBN(self, bn1); \
- obj = NewBN(rb_obj_class(self)); \
- if (!(result = BN_##func(NULL, bn1, bn2, ossl_bn_ctx))) \
- ossl_raise(eBNError, NULL); \
- SetBN(obj, result); \
- return obj; \
+#define BIGNUM_2cr(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self, VALUE other) \
+ { \
+ BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \
+ VALUE obj; \
+ GetBN(self, bn1); \
+ obj = NewBN(rb_obj_class(self)); \
+ if (!(result = BN_##func(NULL, bn1, bn2, ossl_bn_ctx))) \
+ ossl_raise(eBNError, NULL); \
+ SetBN(obj, result); \
+ return obj; \
}
/*
@@ -623,16 +619,16 @@ ossl_bn_div(VALUE self, VALUE other)
obj1 = NewBN(klass);
obj2 = NewBN(klass);
if (!(r1 = BN_new())) {
- ossl_raise(eBNError, NULL);
+ ossl_raise(eBNError, NULL);
}
if (!(r2 = BN_new())) {
- BN_free(r1);
- ossl_raise(eBNError, NULL);
+ BN_free(r1);
+ ossl_raise(eBNError, NULL);
}
if (!BN_div(r1, r2, bn1, bn2, ossl_bn_ctx)) {
- BN_free(r1);
- BN_free(r2);
- ossl_raise(eBNError, NULL);
+ BN_free(r1);
+ BN_free(r2);
+ ossl_raise(eBNError, NULL);
}
SetBN(obj1, r1);
SetBN(obj2, r2);
@@ -640,24 +636,24 @@ ossl_bn_div(VALUE self, VALUE other)
return rb_ary_new3(2, obj1, obj2);
}
-#define BIGNUM_3c(func) \
- static VALUE \
- ossl_bn_##func(VALUE self, VALUE other1, VALUE other2) \
- { \
- BIGNUM *bn1, *bn2 = GetBNPtr(other1); \
- BIGNUM *bn3 = GetBNPtr(other2), *result; \
- VALUE obj; \
- GetBN(self, bn1); \
- obj = NewBN(rb_obj_class(self)); \
- if (!(result = BN_new())) { \
- ossl_raise(eBNError, NULL); \
- } \
- if (BN_##func(result, bn1, bn2, bn3, ossl_bn_ctx) <= 0) { \
- BN_free(result); \
- ossl_raise(eBNError, NULL); \
- } \
- SetBN(obj, result); \
- return obj; \
+#define BIGNUM_3c(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self, VALUE other1, VALUE other2) \
+ { \
+ BIGNUM *bn1, *bn2 = GetBNPtr(other1); \
+ BIGNUM *bn3 = GetBNPtr(other2), *result; \
+ VALUE obj; \
+ GetBN(self, bn1); \
+ obj = NewBN(rb_obj_class(self)); \
+ if (!(result = BN_new())) { \
+ ossl_raise(eBNError, NULL); \
+ } \
+ if (BN_##func(result, bn1, bn2, bn3, ossl_bn_ctx) <= 0) { \
+ BN_free(result); \
+ ossl_raise(eBNError, NULL); \
+ } \
+ SetBN(obj, result); \
+ return obj; \
}
/*
@@ -688,16 +684,17 @@ BIGNUM_3c(mod_mul)
*/
BIGNUM_3c(mod_exp)
-#define BIGNUM_BIT(func) \
- static VALUE \
- ossl_bn_##func(VALUE self, VALUE bit) \
- { \
- BIGNUM *bn; \
- GetBN(self, bn); \
- if (BN_##func(bn, NUM2INT(bit)) <= 0) { \
- ossl_raise(eBNError, NULL); \
- } \
- return self; \
+#define BIGNUM_BIT(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self, VALUE bit) \
+ { \
+ BIGNUM *bn; \
+ rb_check_frozen(self); \
+ GetBN(self, bn); \
+ if (BN_##func(bn, NUM2INT(bit)) <= 0) { \
+ ossl_raise(eBNError, NULL); \
+ } \
+ return self; \
}
/*
@@ -736,30 +733,30 @@ ossl_bn_is_bit_set(VALUE self, VALUE bit)
b = NUM2INT(bit);
GetBN(self, bn);
if (BN_is_bit_set(bn, b)) {
- return Qtrue;
+ return Qtrue;
}
return Qfalse;
}
-#define BIGNUM_SHIFT(func) \
- static VALUE \
- ossl_bn_##func(VALUE self, VALUE bits) \
- { \
- BIGNUM *bn, *result; \
- int b; \
- VALUE obj; \
- b = NUM2INT(bits); \
- GetBN(self, bn); \
- obj = NewBN(rb_obj_class(self)); \
- if (!(result = BN_new())) { \
- ossl_raise(eBNError, NULL); \
- } \
- if (BN_##func(result, bn, b) <= 0) { \
- BN_free(result); \
- ossl_raise(eBNError, NULL); \
- } \
- SetBN(obj, result); \
- return obj; \
+#define BIGNUM_SHIFT(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self, VALUE bits) \
+ { \
+ BIGNUM *bn, *result; \
+ int b; \
+ VALUE obj; \
+ b = NUM2INT(bits); \
+ GetBN(self, bn); \
+ obj = NewBN(rb_obj_class(self)); \
+ if (!(result = BN_new())) { \
+ ossl_raise(eBNError, NULL); \
+ } \
+ if (BN_##func(result, bn, b) <= 0) { \
+ BN_free(result); \
+ ossl_raise(eBNError, NULL); \
+ } \
+ SetBN(obj, result); \
+ return obj; \
}
/*
@@ -776,17 +773,18 @@ BIGNUM_SHIFT(lshift)
*/
BIGNUM_SHIFT(rshift)
-#define BIGNUM_SELF_SHIFT(func) \
- static VALUE \
- ossl_bn_self_##func(VALUE self, VALUE bits) \
- { \
- BIGNUM *bn; \
- int b; \
- b = NUM2INT(bits); \
- GetBN(self, bn); \
- if (BN_##func(bn, bn, b) <= 0) \
- ossl_raise(eBNError, NULL); \
- return self; \
+#define BIGNUM_SELF_SHIFT(func) \
+ static VALUE \
+ ossl_bn_self_##func(VALUE self, VALUE bits) \
+ { \
+ BIGNUM *bn; \
+ int b; \
+ rb_check_frozen(self); \
+ b = NUM2INT(bits); \
+ GetBN(self, bn); \
+ if (BN_##func(bn, bn, b) <= 0) \
+ ossl_raise(eBNError, NULL); \
+ return self; \
}
/*
@@ -888,32 +886,32 @@ ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass)
num = NUM2INT(vnum);
if (vsafe == Qfalse) {
- safe = 0;
+ safe = 0;
}
if (!NIL_P(vadd)) {
- add = GetBNPtr(vadd);
- rem = NIL_P(vrem) ? NULL : GetBNPtr(vrem);
+ add = GetBNPtr(vadd);
+ rem = NIL_P(vrem) ? NULL : GetBNPtr(vrem);
}
obj = NewBN(klass);
if (!(result = BN_new())) {
- ossl_raise(eBNError, NULL);
+ ossl_raise(eBNError, NULL);
}
if (!BN_generate_prime_ex(result, num, safe, add, rem, NULL)) {
- BN_free(result);
- ossl_raise(eBNError, NULL);
+ BN_free(result);
+ ossl_raise(eBNError, NULL);
}
SetBN(obj, result);
return obj;
}
-#define BIGNUM_NUM(func) \
- static VALUE \
- ossl_bn_##func(VALUE self) \
- { \
- BIGNUM *bn; \
- GetBN(self, bn); \
- return INT2NUM(BN_##func(bn)); \
+#define BIGNUM_NUM(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self) \
+ { \
+ BIGNUM *bn; \
+ GetBN(self, bn); \
+ return INT2NUM(BN_##func(bn)); \
}
/*
@@ -930,6 +928,7 @@ BIGNUM_NUM(num_bytes)
*/
BIGNUM_NUM(num_bits)
+/* :nodoc: */
static VALUE
ossl_bn_copy(VALUE self, VALUE other)
{
@@ -943,7 +942,7 @@ ossl_bn_copy(VALUE self, VALUE other)
bn2 = GetBNPtr(other);
if (!BN_copy(bn1, bn2)) {
- ossl_raise(eBNError, NULL);
+ ossl_raise(eBNError, NULL);
}
return self;
}
@@ -962,7 +961,7 @@ ossl_bn_uplus(VALUE self)
obj = NewBN(cBN);
bn2 = BN_dup(bn1);
if (!bn2)
- ossl_raise(eBNError, "BN_dup");
+ ossl_raise(eBNError, "BN_dup");
SetBN(obj, bn2);
return obj;
@@ -982,7 +981,7 @@ ossl_bn_uminus(VALUE self)
obj = NewBN(cBN);
bn2 = BN_dup(bn1);
if (!bn2)
- ossl_raise(eBNError, "BN_dup");
+ ossl_raise(eBNError, "BN_dup");
SetBN(obj, bn2);
BN_set_negative(bn2, !BN_is_negative(bn2));
@@ -1007,13 +1006,13 @@ ossl_bn_abs(VALUE self)
}
}
-#define BIGNUM_CMP(func) \
- static VALUE \
- ossl_bn_##func(VALUE self, VALUE other) \
- { \
- BIGNUM *bn1, *bn2 = GetBNPtr(other); \
- GetBN(self, bn1); \
- return INT2NUM(BN_##func(bn1, bn2)); \
+#define BIGNUM_CMP(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self, VALUE other) \
+ { \
+ BIGNUM *bn1, *bn2 = GetBNPtr(other); \
+ GetBN(self, bn1); \
+ return INT2NUM(BN_##func(bn1, bn2)); \
}
/*
@@ -1050,11 +1049,11 @@ ossl_bn_eq(VALUE self, VALUE other)
GetBN(self, bn1);
other = try_convert_to_bn(other);
if (NIL_P(other))
- return Qfalse;
+ return Qfalse;
GetBN(other, bn2);
if (!BN_cmp(bn1, bn2)) {
- return Qtrue;
+ return Qtrue;
}
return Qfalse;
}
@@ -1073,7 +1072,7 @@ ossl_bn_eql(VALUE self, VALUE other)
BIGNUM *bn1, *bn2;
if (!rb_obj_is_kind_of(other, cBN))
- return Qfalse;
+ return Qfalse;
GetBN(self, bn1);
GetBN(other, bn2);
@@ -1100,8 +1099,8 @@ ossl_bn_hash(VALUE self)
len = BN_num_bytes(bn);
buf = ALLOCV(tmp, len);
if (BN_bn2bin(bn, buf) != len) {
- ALLOCV_END(tmp);
- ossl_raise(eBNError, "BN_bn2bin");
+ ALLOCV_END(tmp);
+ ossl_raise(eBNError, "BN_bn2bin");
}
hash = ST2FIX(rb_memhash(buf, len));
@@ -1191,6 +1190,7 @@ ossl_bn_set_flags(VALUE self, VALUE arg)
BIGNUM *bn;
GetBN(self, bn);
+ rb_check_frozen(self);
BN_set_flags(bn, NUM2INT(arg));
return Qnil;
}
@@ -1202,11 +1202,6 @@ ossl_bn_set_flags(VALUE self, VALUE arg)
void
Init_ossl_bn(void)
{
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
-#endif
-
#ifdef HAVE_RB_EXT_RACTOR_SAFE
ossl_bn_ctx_key = rb_ractor_local_storage_ptr_newkey(&ossl_bn_ctx_key_type);
#else
diff --git a/ext/openssl/ossl_bn.h b/ext/openssl/ossl_bn.h
index 1cc041fc22..0c186bd1c5 100644
--- a/ext/openssl/ossl_bn.h
+++ b/ext/openssl/ossl_bn.h
@@ -5,13 +5,12 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_BN_H_)
#define _OSSL_BN_H_
extern VALUE cBN;
-extern VALUE eBNError;
BN_CTX *ossl_bn_ctx_get(void);
#define ossl_bn_ctx ossl_bn_ctx_get()
diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c
index 6f74c925c0..f3cd247c8f 100644
--- a/ext/openssl/ossl_cipher.c
+++ b/ext/openssl/ossl_cipher.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -14,7 +14,7 @@
#define AllocCipher(obj, ctx) do { \
(ctx) = EVP_CIPHER_CTX_new(); \
if (!(ctx)) \
- ossl_raise(rb_eRuntimeError, NULL); \
+ ossl_raise(rb_eRuntimeError, NULL); \
RTYPEDDATA_DATA(obj) = (ctx); \
} while (0)
#define GetCipherInit(obj, ctx) do { \
@@ -23,16 +23,17 @@
#define GetCipher(obj, ctx) do { \
GetCipherInit((obj), (ctx)); \
if (!(ctx)) { \
- ossl_raise(rb_eRuntimeError, "Cipher not initialized!"); \
+ ossl_raise(rb_eRuntimeError, "Cipher not initialized!"); \
} \
} while (0)
/*
* Classes
*/
-VALUE cCipher;
-VALUE eCipherError;
-static ID id_auth_tag_len, id_key_set;
+static VALUE cCipher;
+static VALUE eCipherError;
+static VALUE eAuthTagError;
+static ID id_auth_tag_len, id_key_set, id_cipher_holder;
static VALUE ossl_cipher_alloc(VALUE klass);
static void ossl_cipher_free(void *ptr);
@@ -40,35 +41,63 @@ static void ossl_cipher_free(void *ptr);
static const rb_data_type_t ossl_cipher_type = {
"OpenSSL/Cipher",
{
- 0, ossl_cipher_free,
+ 0, ossl_cipher_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
+#ifdef OSSL_USE_PROVIDER
+static void
+ossl_evp_cipher_free(void *ptr)
+{
+ // This is safe to call against const EVP_CIPHER * returned by
+ // EVP_get_cipherbyname()
+ EVP_CIPHER_free(ptr);
+}
+
+static const rb_data_type_t ossl_evp_cipher_holder_type = {
+ "OpenSSL/EVP_CIPHER",
+ {
+ .dfree = ossl_evp_cipher_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+#endif
+
/*
* PUBLIC
*/
const EVP_CIPHER *
-ossl_evp_get_cipherbyname(VALUE obj)
+ossl_evp_cipher_fetch(VALUE obj, volatile VALUE *holder)
{
+ *holder = Qnil;
if (rb_obj_is_kind_of(obj, cCipher)) {
- EVP_CIPHER_CTX *ctx;
-
- GetCipher(obj, ctx);
-
- return EVP_CIPHER_CTX_cipher(ctx);
+ EVP_CIPHER_CTX *ctx;
+ GetCipher(obj, ctx);
+ EVP_CIPHER *cipher = (EVP_CIPHER *)EVP_CIPHER_CTX_cipher(ctx);
+#ifdef OSSL_USE_PROVIDER
+ *holder = TypedData_Wrap_Struct(0, &ossl_evp_cipher_holder_type, NULL);
+ if (!EVP_CIPHER_up_ref(cipher))
+ ossl_raise(eCipherError, "EVP_CIPHER_up_ref");
+ RTYPEDDATA_DATA(*holder) = cipher;
+#endif
+ return cipher;
}
- else {
- const EVP_CIPHER *cipher;
- StringValueCStr(obj);
- cipher = EVP_get_cipherbyname(RSTRING_PTR(obj));
- if (!cipher)
- ossl_raise(rb_eArgError,
- "unsupported cipher algorithm: %"PRIsVALUE, obj);
-
- return cipher;
+ const char *name = StringValueCStr(obj);
+ EVP_CIPHER *cipher = (EVP_CIPHER *)EVP_get_cipherbyname(name);
+#ifdef OSSL_USE_PROVIDER
+ if (!cipher) {
+ ossl_clear_error();
+ *holder = TypedData_Wrap_Struct(0, &ossl_evp_cipher_holder_type, NULL);
+ cipher = EVP_CIPHER_fetch(NULL, name, NULL);
+ RTYPEDDATA_DATA(*holder) = cipher;
}
+#endif
+ if (!cipher)
+ ossl_raise(eCipherError, "unsupported cipher algorithm: %"PRIsVALUE,
+ obj);
+ return cipher;
}
VALUE
@@ -77,10 +106,13 @@ ossl_cipher_new(const EVP_CIPHER *cipher)
VALUE ret;
EVP_CIPHER_CTX *ctx;
+ // NOTE: This does not set id_cipher_holder because this function should
+ // only be called from ossl_engine.c, which will not use any
+ // reference-counted ciphers.
ret = ossl_cipher_alloc(cCipher);
AllocCipher(ret, ctx);
if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, -1) != 1)
- ossl_raise(eCipherError, NULL);
+ ossl_raise(eCipherError, NULL);
return ret;
}
@@ -113,23 +145,22 @@ ossl_cipher_initialize(VALUE self, VALUE str)
{
EVP_CIPHER_CTX *ctx;
const EVP_CIPHER *cipher;
- char *name;
+ VALUE cipher_holder;
- name = StringValueCStr(str);
GetCipherInit(self, ctx);
if (ctx) {
- ossl_raise(rb_eRuntimeError, "Cipher already initialized!");
+ ossl_raise(rb_eRuntimeError, "Cipher already initialized!");
}
+ cipher = ossl_evp_cipher_fetch(str, &cipher_holder);
AllocCipher(self, ctx);
- if (!(cipher = EVP_get_cipherbyname(name))) {
- ossl_raise(rb_eRuntimeError, "unsupported cipher algorithm (%"PRIsVALUE")", str);
- }
if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, -1) != 1)
- ossl_raise(eCipherError, NULL);
+ ossl_raise(eCipherError, "EVP_CipherInit_ex");
+ rb_ivar_set(self, id_cipher_holder, cipher_holder);
return self;
}
+/* :nodoc: */
static VALUE
ossl_cipher_copy(VALUE self, VALUE other)
{
@@ -140,11 +171,11 @@ ossl_cipher_copy(VALUE self, VALUE other)
GetCipherInit(self, ctx1);
if (!ctx1) {
- AllocCipher(self, ctx1);
+ AllocCipher(self, ctx1);
}
GetCipher(other, ctx2);
if (EVP_CIPHER_CTX_copy(ctx1, ctx2) != 1)
- ossl_raise(eCipherError, NULL);
+ ossl_raise(eCipherError, NULL);
return self;
}
@@ -169,8 +200,8 @@ ossl_s_ciphers(VALUE self)
ary = rb_ary_new();
OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH,
- add_cipher_name_to_ary,
- (void*)ary);
+ add_cipher_name_to_ary,
+ (void*)ary);
return ary;
}
@@ -191,53 +222,22 @@ ossl_cipher_reset(VALUE self)
GetCipher(self, ctx);
if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, -1) != 1)
- ossl_raise(eCipherError, NULL);
+ ossl_raise(eCipherError, NULL);
return self;
}
static VALUE
-ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode)
+ossl_cipher_init(VALUE self, int enc)
{
EVP_CIPHER_CTX *ctx;
- unsigned char key[EVP_MAX_KEY_LENGTH], *p_key = NULL;
- unsigned char iv[EVP_MAX_IV_LENGTH], *p_iv = NULL;
- VALUE pass, init_v;
-
- if(rb_scan_args(argc, argv, "02", &pass, &init_v) > 0){
- /*
- * oops. this code mistakes salt for IV.
- * We deprecated the arguments for this method, but we decided
- * keeping this behaviour for backward compatibility.
- */
- VALUE cname = rb_class_path(rb_obj_class(self));
- rb_warn("arguments for %"PRIsVALUE"#encrypt and %"PRIsVALUE"#decrypt were deprecated; "
- "use %"PRIsVALUE"#pkcs5_keyivgen to derive key and IV",
- cname, cname, cname);
- StringValue(pass);
- GetCipher(self, ctx);
- if (NIL_P(init_v)) memcpy(iv, "OpenSSL for Ruby rulez!", sizeof(iv));
- else{
- StringValue(init_v);
- if (EVP_MAX_IV_LENGTH > RSTRING_LEN(init_v)) {
- memset(iv, 0, EVP_MAX_IV_LENGTH);
- memcpy(iv, RSTRING_PTR(init_v), RSTRING_LEN(init_v));
- }
- else memcpy(iv, RSTRING_PTR(init_v), sizeof(iv));
- }
- EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), EVP_md5(), iv,
- (unsigned char *)RSTRING_PTR(pass), RSTRING_LENINT(pass), 1, key, NULL);
- p_key = key;
- p_iv = iv;
- }
- else {
- GetCipher(self, ctx);
- }
- if (EVP_CipherInit_ex(ctx, NULL, NULL, p_key, p_iv, mode) != 1) {
- ossl_raise(eCipherError, NULL);
+
+ GetCipher(self, ctx);
+ if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, enc) != 1) {
+ ossl_raise(eCipherError, "EVP_CipherInit_ex");
}
- rb_ivar_set(self, id_key_set, p_key ? Qtrue : Qfalse);
+ rb_ivar_set(self, id_key_set, Qfalse);
return self;
}
@@ -248,16 +248,15 @@ ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode)
*
* Initializes the Cipher for encryption.
*
- * Make sure to call Cipher#encrypt or Cipher#decrypt before using any of the
- * following methods:
- * * [#key=, #iv=, #random_key, #random_iv, #pkcs5_keyivgen]
+ * Make sure to call either #encrypt or #decrypt before using the Cipher for
+ * any operation or setting any parameters.
*
* Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 1).
*/
static VALUE
-ossl_cipher_encrypt(int argc, VALUE *argv, VALUE self)
+ossl_cipher_encrypt(VALUE self)
{
- return ossl_cipher_init(argc, argv, self, 1);
+ return ossl_cipher_init(self, 1);
}
/*
@@ -266,16 +265,15 @@ ossl_cipher_encrypt(int argc, VALUE *argv, VALUE self)
*
* Initializes the Cipher for decryption.
*
- * Make sure to call Cipher#encrypt or Cipher#decrypt before using any of the
- * following methods:
- * * [#key=, #iv=, #random_key, #random_iv, #pkcs5_keyivgen]
+ * Make sure to call either #encrypt or #decrypt before using the Cipher for
+ * any operation or setting any parameters.
*
* Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 0).
*/
static VALUE
-ossl_cipher_decrypt(int argc, VALUE *argv, VALUE self)
+ossl_cipher_decrypt(VALUE self)
{
- return ossl_cipher_init(argc, argv, self, 0);
+ return ossl_cipher_init(self, 0);
}
/*
@@ -284,46 +282,42 @@ ossl_cipher_decrypt(int argc, VALUE *argv, VALUE self)
*
* Generates and sets the key/IV based on a password.
*
- * *WARNING*: This method is only PKCS5 v1.5 compliant when using RC2, RC4-40,
- * or DES with MD5 or SHA1. Using anything else (like AES) will generate the
- * key/iv using an OpenSSL specific method. This method is deprecated and
- * should no longer be used. Use a PKCS5 v2 key generation method from
- * OpenSSL::PKCS5 instead.
+ * *WARNING*: This method is deprecated and should not be used. This method
+ * corresponds to EVP_BytesToKey(), a non-standard OpenSSL extension of the
+ * legacy PKCS #5 v1.5 key derivation function. See OpenSSL::KDF for other
+ * options to derive keys from passwords.
*
* === Parameters
* * _salt_ must be an 8 byte string if provided.
* * _iterations_ is an integer with a default of 2048.
* * _digest_ is a Digest object that defaults to 'MD5'
- *
- * A minimum of 1000 iterations is recommended.
- *
*/
static VALUE
ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self)
{
EVP_CIPHER_CTX *ctx;
const EVP_MD *digest;
- VALUE vpass, vsalt, viter, vdigest;
+ VALUE vpass, vsalt, viter, vdigest, md_holder;
unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH], *salt = NULL;
int iter;
rb_scan_args(argc, argv, "13", &vpass, &vsalt, &viter, &vdigest);
StringValue(vpass);
if(!NIL_P(vsalt)){
- StringValue(vsalt);
- if(RSTRING_LEN(vsalt) != PKCS5_SALT_LEN)
- ossl_raise(eCipherError, "salt must be an 8-octet string");
- salt = (unsigned char *)RSTRING_PTR(vsalt);
+ StringValue(vsalt);
+ if(RSTRING_LEN(vsalt) != PKCS5_SALT_LEN)
+ ossl_raise(eCipherError, "salt must be an 8-octet string");
+ salt = (unsigned char *)RSTRING_PTR(vsalt);
}
iter = NIL_P(viter) ? 2048 : NUM2INT(viter);
if (iter <= 0)
- rb_raise(rb_eArgError, "iterations must be a positive integer");
- digest = NIL_P(vdigest) ? EVP_md5() : ossl_evp_get_digestbyname(vdigest);
+ rb_raise(rb_eArgError, "iterations must be a positive integer");
+ digest = NIL_P(vdigest) ? EVP_md5() : ossl_evp_md_fetch(vdigest, &md_holder);
GetCipher(self, ctx);
EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), digest, salt,
- (unsigned char *)RSTRING_PTR(vpass), RSTRING_LENINT(vpass), iter, key, iv);
+ (unsigned char *)RSTRING_PTR(vpass), RSTRING_LENINT(vpass), iter, key, iv);
if (EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, -1) != 1)
- ossl_raise(eCipherError, NULL);
+ ossl_raise(eCipherError, NULL);
OPENSSL_cleanse(key, sizeof key);
OPENSSL_cleanse(iv, sizeof iv);
@@ -334,25 +328,25 @@ ossl_cipher_pkcs5_keyivgen(int argc, VALUE *argv, VALUE self)
static int
ossl_cipher_update_long(EVP_CIPHER_CTX *ctx, unsigned char *out, long *out_len_ptr,
- const unsigned char *in, long in_len)
+ const unsigned char *in, long in_len)
{
int out_part_len;
int limit = INT_MAX / 2 + 1;
long out_len = 0;
do {
- int in_part_len = in_len > limit ? limit : (int)in_len;
+ int in_part_len = in_len > limit ? limit : (int)in_len;
- if (!EVP_CipherUpdate(ctx, out ? (out + out_len) : 0,
- &out_part_len, in, in_part_len))
- return 0;
+ if (!EVP_CipherUpdate(ctx, out ? (out + out_len) : 0,
+ &out_part_len, in, in_part_len))
+ return 0;
- out_len += out_part_len;
- in += in_part_len;
+ out_len += out_part_len;
+ in += in_part_len;
} while ((in_len -= limit) > 0);
if (out_len_ptr)
- *out_len_ptr = out_len;
+ *out_len_ptr = out_len;
return 1;
}
@@ -368,6 +362,9 @@ ossl_cipher_update_long(EVP_CIPHER_CTX *ctx, unsigned char *out, long *out_len_p
*
* If _buffer_ is given, the encryption/decryption result will be written to
* it. _buffer_ will be resized automatically.
+ *
+ * *NOTE*: When decrypting using an AEAD cipher, the integrity of the output
+ * is not verified until #final has been called.
*/
static VALUE
ossl_cipher_update(int argc, VALUE *argv, VALUE self)
@@ -380,7 +377,7 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "11", &data, &str);
if (!RTEST(rb_attr_get(self, id_key_set)))
- ossl_raise(eCipherError, "key not set");
+ ossl_raise(eCipherError, "key not set");
StringValue(data);
in = (unsigned char *)RSTRING_PTR(data);
@@ -399,21 +396,24 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self)
* currently implemented in OpenSSL, but this can change in the future.
*/
if (in_len > LONG_MAX - EVP_MAX_BLOCK_LENGTH) {
- ossl_raise(rb_eRangeError,
- "data too big to make output buffer: %ld bytes", in_len);
+ ossl_raise(rb_eRangeError,
+ "data too big to make output buffer: %ld bytes", in_len);
}
out_len = in_len + EVP_MAX_BLOCK_LENGTH;
- if (NIL_P(str)) {
- str = rb_str_new(0, out_len);
- } else {
+ if (NIL_P(str))
+ str = rb_str_buf_new(out_len);
+ else {
StringValue(str);
- rb_str_resize(str, out_len);
+ if ((long)rb_str_capacity(str) >= out_len)
+ rb_str_modify(str);
+ else
+ rb_str_modify_expand(str, out_len - RSTRING_LEN(str));
}
- if (!ossl_cipher_update_long(ctx, (unsigned char *)RSTRING_PTR(str), &out_len, in, in_len))
- ossl_raise(eCipherError, NULL);
- assert(out_len <= RSTRING_LEN(str));
+ if (!ossl_cipher_update_long(ctx, (unsigned char *)RSTRING_PTR(str),
+ &out_len, in, in_len))
+ ossl_raise(eCipherError, "EVP_CipherUpdate");
rb_str_set_len(str, out_len);
return str;
@@ -424,14 +424,17 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self)
* cipher.final -> string
*
* Returns the remaining data held in the cipher object. Further calls to
- * Cipher#update or Cipher#final will return garbage. This call should always
+ * Cipher#update or Cipher#final are invalid. This call should always
* be made as the last call of an encryption or decryption operation, after
* having fed the entire plaintext or ciphertext to the Cipher instance.
*
- * If an authenticated cipher was used, a CipherError is raised if the tag
- * could not be authenticated successfully. Only call this method after
- * setting the authentication tag and passing the entire contents of the
- * ciphertext into the cipher.
+ * When encrypting using an AEAD cipher, the authentication tag can be
+ * retrieved by #auth_tag after #final has been called.
+ *
+ * When decrypting using an AEAD cipher, this method will verify the integrity
+ * of the ciphertext and the associated data with the authentication tag,
+ * which must be set by #auth_tag= prior to calling this method.
+ * If the verification fails, CipherError will be raised.
*/
static VALUE
ossl_cipher_final(VALUE self)
@@ -442,9 +445,17 @@ ossl_cipher_final(VALUE self)
GetCipher(self, ctx);
str = rb_str_new(0, EVP_CIPHER_CTX_block_size(ctx));
- if (!EVP_CipherFinal_ex(ctx, (unsigned char *)RSTRING_PTR(str), &out_len))
- ossl_raise(eCipherError, NULL);
- assert(out_len <= RSTRING_LEN(str));
+ if (!EVP_CipherFinal_ex(ctx, (unsigned char *)RSTRING_PTR(str), &out_len)) {
+ /* For AEAD ciphers, this is likely an authentication failure */
+ if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER) {
+ /* For AEAD ciphers, EVP_CipherFinal_ex failures are authentication tag verification failures */
+ ossl_raise(eAuthTagError, "AEAD authentication tag verification failed");
+ }
+ else {
+ /* For non-AEAD ciphers */
+ ossl_raise(eCipherError, "cipher final failed");
+ }
+ }
rb_str_set_len(str, out_len);
return str;
@@ -469,7 +480,7 @@ ossl_cipher_name(VALUE self)
/*
* call-seq:
- * cipher.key = string -> string
+ * cipher.key = string
*
* Sets the cipher key. To generate a key, you should either use a secure
* random byte string or, if the key is to be derived from a password, you
@@ -477,6 +488,8 @@ ossl_cipher_name(VALUE self)
* generate a secure random-based key, Cipher#random_key may be used.
*
* Only call this method after calling Cipher#encrypt or Cipher#decrypt.
+ *
+ * See also the man page EVP_CipherInit_ex(3).
*/
static VALUE
ossl_cipher_set_key(VALUE self, VALUE key)
@@ -489,10 +502,10 @@ ossl_cipher_set_key(VALUE self, VALUE key)
key_len = EVP_CIPHER_CTX_key_length(ctx);
if (RSTRING_LEN(key) != key_len)
- ossl_raise(rb_eArgError, "key must be %d bytes", key_len);
+ ossl_raise(rb_eArgError, "key must be %d bytes", key_len);
if (EVP_CipherInit_ex(ctx, NULL, NULL, (unsigned char *)RSTRING_PTR(key), NULL, -1) != 1)
- ossl_raise(eCipherError, NULL);
+ ossl_raise(eCipherError, NULL);
rb_ivar_set(self, id_key_set, Qtrue);
@@ -501,15 +514,21 @@ ossl_cipher_set_key(VALUE self, VALUE key)
/*
* call-seq:
- * cipher.iv = string -> string
+ * cipher.iv = string
*
* Sets the cipher IV. Please note that since you should never be using ECB
* mode, an IV is always explicitly required and should be set prior to
- * encryption. The IV itself can be safely transmitted in public, but it
- * should be unpredictable to prevent certain kinds of attacks. You may use
- * Cipher#random_iv to create a secure random IV.
+ * encryption. The IV itself can be safely transmitted in public.
*
- * Only call this method after calling Cipher#encrypt or Cipher#decrypt.
+ * This method expects the String to have the length equal to #iv_len. To use
+ * a different IV length with an AEAD cipher, #iv_len= must be set prior to
+ * calling this method.
+ *
+ * *NOTE*: In OpenSSL API conventions, the IV value may correspond to the
+ * "nonce" instead in some cipher modes. Refer to the OpenSSL man pages for
+ * details.
+ *
+ * See also the man page EVP_CipherInit_ex(3).
*/
static VALUE
ossl_cipher_set_iv(VALUE self, VALUE iv)
@@ -521,14 +540,14 @@ ossl_cipher_set_iv(VALUE self, VALUE iv)
GetCipher(self, ctx);
if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER)
- iv_len = (int)(VALUE)EVP_CIPHER_CTX_get_app_data(ctx);
+ iv_len = (int)(VALUE)EVP_CIPHER_CTX_get_app_data(ctx);
if (!iv_len)
- iv_len = EVP_CIPHER_CTX_iv_length(ctx);
+ iv_len = EVP_CIPHER_CTX_iv_length(ctx);
if (RSTRING_LEN(iv) != iv_len)
- ossl_raise(rb_eArgError, "iv must be %d bytes", iv_len);
+ ossl_raise(rb_eArgError, "iv must be %d bytes", iv_len);
if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, (unsigned char *)RSTRING_PTR(iv), -1) != 1)
- ossl_raise(eCipherError, NULL);
+ ossl_raise(eCipherError, NULL);
return iv;
}
@@ -537,8 +556,7 @@ ossl_cipher_set_iv(VALUE self, VALUE iv)
* call-seq:
* cipher.authenticated? -> true | false
*
- * Indicated whether this Cipher instance uses an Authenticated Encryption
- * mode.
+ * Indicates whether this Cipher instance uses an AEAD mode.
*/
static VALUE
ossl_cipher_is_authenticated(VALUE self)
@@ -552,21 +570,23 @@ ossl_cipher_is_authenticated(VALUE self)
/*
* call-seq:
- * cipher.auth_data = string -> string
+ * cipher.auth_data = string
+ *
+ * Sets additional authenticated data (AAD), also called associated data, for
+ * this Cipher. This method is available for AEAD ciphers.
*
- * Sets the cipher's additional authenticated data. This field must be
- * set when using AEAD cipher modes such as GCM or CCM. If no associated
- * data shall be used, this method must *still* be called with a value of "".
* The contents of this field should be non-sensitive data which will be
* added to the ciphertext to generate the authentication tag which validates
* the contents of the ciphertext.
*
- * The AAD must be set prior to encryption or decryption. In encryption mode,
- * it must be set after calling Cipher#encrypt and setting Cipher#key= and
- * Cipher#iv=. When decrypting, the authenticated data must be set after key,
- * iv and especially *after* the authentication tag has been set. I.e. set it
- * only after calling Cipher#decrypt, Cipher#key=, Cipher#iv= and
- * Cipher#auth_tag= first.
+ * This method must be called after #key= and #iv= have been set, but before
+ * starting actual encryption or decryption with #update. In some cipher modes,
+ * #auth_tag_len= and #ccm_data_len= may also need to be called before this
+ * method.
+ *
+ * See also the "AEAD Interface" section of the man page EVP_EncryptInit(3).
+ * This method internally calls EVP_CipherUpdate() with the output buffer
+ * set to NULL.
*/
static VALUE
ossl_cipher_set_auth_data(VALUE self, VALUE data)
@@ -582,7 +602,7 @@ ossl_cipher_set_auth_data(VALUE self, VALUE data)
GetCipher(self, ctx);
if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER))
- ossl_raise(eCipherError, "AEAD not supported by this cipher");
+ ossl_raise(eCipherError, "AEAD not supported by this cipher");
if (!ossl_cipher_update_long(ctx, NULL, &out_len, in, in_len))
ossl_raise(eCipherError, "couldn't set additional authenticated data");
@@ -594,16 +614,17 @@ ossl_cipher_set_auth_data(VALUE self, VALUE data)
* call-seq:
* cipher.auth_tag(tag_len = 16) -> String
*
- * Gets the authentication tag generated by Authenticated Encryption Cipher
- * modes (GCM for example). This tag may be stored along with the ciphertext,
- * then set on the decryption cipher to authenticate the contents of the
- * ciphertext against changes. If the optional integer parameter _tag_len_ is
- * given, the returned tag will be _tag_len_ bytes long. If the parameter is
- * omitted, the default length of 16 bytes or the length previously set by
- * #auth_tag_len= will be used. For maximum security, the longest possible
- * should be chosen.
+ * Gets the generated authentication tag. This method is available for AEAD
+ * ciphers, and should be called after encryption has been finalized by calling
+ * #final.
+ *
+ * The returned tag will be _tag_len_ bytes long. Some cipher modes require
+ * the desired length in advance using a separate call to #auth_tag_len=,
+ * before starting encryption.
*
- * The tag may only be retrieved after calling Cipher#final.
+ * See also the "AEAD Interface" section of the man page EVP_EncryptInit(3).
+ * This method internally calls EVP_CIPHER_CTX_ctrl() with
+ * EVP_CTRL_AEAD_GET_TAG.
*/
static VALUE
ossl_cipher_get_auth_tag(int argc, VALUE *argv, VALUE self)
@@ -614,34 +635,42 @@ ossl_cipher_get_auth_tag(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "01", &vtag_len);
if (NIL_P(vtag_len))
- vtag_len = rb_attr_get(self, id_auth_tag_len);
+ vtag_len = rb_attr_get(self, id_auth_tag_len);
if (!NIL_P(vtag_len))
- tag_len = NUM2INT(vtag_len);
+ tag_len = NUM2INT(vtag_len);
GetCipher(self, ctx);
if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER))
- ossl_raise(eCipherError, "authentication tag not supported by this cipher");
+ ossl_raise(eCipherError, "authentication tag not supported by this cipher");
ret = rb_str_new(NULL, tag_len);
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, tag_len, RSTRING_PTR(ret)))
- ossl_raise(eCipherError, "retrieving the authentication tag failed");
+ ossl_raise(eCipherError, "retrieving the authentication tag failed");
return ret;
}
/*
* call-seq:
- * cipher.auth_tag = string -> string
+ * cipher.auth_tag = string
*
* Sets the authentication tag to verify the integrity of the ciphertext.
- * This can be called only when the cipher supports AE. The tag must be set
- * after calling Cipher#decrypt, Cipher#key= and Cipher#iv=, but before
- * calling Cipher#final. After all decryption is performed, the tag is
- * verified automatically in the call to Cipher#final.
*
- * For OCB mode, the tag length must be supplied with #auth_tag_len=
- * beforehand.
+ * The authentication tag must be set before #final is called. The tag is
+ * verified during the #final call.
+ *
+ * Note that, for CCM mode and OCB mode, the expected length of the tag must
+ * be set before starting decryption by a separate call to #auth_tag_len=.
+ * The content of the tag can be provided at any time before #final is called.
+ *
+ * *NOTE*: The caller must ensure that the String passed to this method has
+ * the desired length. Some cipher modes support variable tag lengths, and
+ * this method may accept a truncated tag without raising an exception.
+ *
+ * See also the "AEAD Interface" section of the man page EVP_EncryptInit(3).
+ * This method internally calls EVP_CIPHER_CTX_ctrl() with
+ * EVP_CTRL_AEAD_SET_TAG.
*/
static VALUE
ossl_cipher_set_auth_tag(VALUE self, VALUE vtag)
@@ -656,24 +685,27 @@ ossl_cipher_set_auth_tag(VALUE self, VALUE vtag)
GetCipher(self, ctx);
if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER))
- ossl_raise(eCipherError, "authentication tag not supported by this cipher");
+ ossl_raise(eCipherError, "authentication tag not supported by this cipher");
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, tag))
- ossl_raise(eCipherError, "unable to set AEAD tag");
+ ossl_raise(eCipherError, "unable to set AEAD tag");
return vtag;
}
/*
* call-seq:
- * cipher.auth_tag_len = Integer -> Integer
+ * cipher.auth_tag_len = integer
+ *
+ * Sets the length of the expected authentication tag for this Cipher. This
+ * method is available for some of AEAD ciphers that require the length to be
+ * set before starting encryption or decryption, such as CCM mode or OCB mode.
*
- * Sets the length of the authentication tag to be generated or to be given for
- * AEAD ciphers that requires it as in input parameter. Note that not all AEAD
- * ciphers support this method.
+ * For CCM mode and OCB mode, the tag length must be set before #iv= is set.
*
- * In OCB mode, the length must be supplied both when encrypting and when
- * decrypting, and must be before specifying an IV.
+ * See also the "AEAD Interface" section of the man page EVP_EncryptInit(3).
+ * This method internally calls EVP_CIPHER_CTX_ctrl() with
+ * EVP_CTRL_AEAD_SET_TAG and a NULL buffer.
*/
static VALUE
ossl_cipher_set_auth_tag_len(VALUE self, VALUE vlen)
@@ -683,10 +715,10 @@ ossl_cipher_set_auth_tag_len(VALUE self, VALUE vlen)
GetCipher(self, ctx);
if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER))
- ossl_raise(eCipherError, "AEAD not supported by this cipher");
+ ossl_raise(eCipherError, "AEAD not supported by this cipher");
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, NULL))
- ossl_raise(eCipherError, "unable to set authentication tag length");
+ ossl_raise(eCipherError, "unable to set authentication tag length");
/* for #auth_tag */
rb_ivar_set(self, id_auth_tag_len, INT2NUM(tag_len));
@@ -696,11 +728,16 @@ ossl_cipher_set_auth_tag_len(VALUE self, VALUE vlen)
/*
* call-seq:
- * cipher.iv_len = integer -> integer
+ * cipher.iv_len = integer
*
- * Sets the IV/nonce length of the Cipher. Normally block ciphers don't allow
- * changing the IV length, but some make use of IV for 'nonce'. You may need
- * this for interoperability with other applications.
+ * Sets the IV/nonce length for this Cipher. This method is available for AEAD
+ * ciphers that support variable IV lengths. This method can be called if a
+ * different IV length than OpenSSL's default is desired, prior to calling
+ * #iv=.
+ *
+ * See also the "AEAD Interface" section of the man page EVP_EncryptInit(3).
+ * This method internally calls EVP_CIPHER_CTX_ctrl() with
+ * EVP_CTRL_AEAD_SET_IVLEN.
*/
static VALUE
ossl_cipher_set_iv_length(VALUE self, VALUE iv_length)
@@ -710,10 +747,10 @@ ossl_cipher_set_iv_length(VALUE self, VALUE iv_length)
GetCipher(self, ctx);
if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER))
- ossl_raise(eCipherError, "cipher does not support AEAD");
+ ossl_raise(eCipherError, "cipher does not support AEAD");
if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, len, NULL))
- ossl_raise(eCipherError, "unable to set IV length");
+ ossl_raise(eCipherError, "unable to set IV length");
/*
* EVP_CIPHER_CTX_iv_length() returns the default length. So we need to save
@@ -726,13 +763,14 @@ ossl_cipher_set_iv_length(VALUE self, VALUE iv_length)
/*
* call-seq:
- * cipher.key_len = integer -> integer
+ * cipher.key_len = integer
*
* Sets the key length of the cipher. If the cipher is a fixed length cipher
* then attempting to set the key length to any value other than the fixed
* value is an error.
*
- * Under normal circumstances you do not need to call this method (and probably shouldn't).
+ * Under normal circumstances you do not need to call this method (and
+ * probably shouldn't).
*
* See EVP_CIPHER_CTX_set_key_length for further information.
*/
@@ -749,13 +787,16 @@ ossl_cipher_set_key_length(VALUE self, VALUE key_length)
return key_length;
}
+// TODO: Should #padding= take a boolean value instead?
/*
* call-seq:
- * cipher.padding = integer -> integer
+ * cipher.padding = 1 or 0
*
- * Enables or disables padding. By default encryption operations are padded using standard block padding and the
- * padding is checked and removed when decrypting. If the pad parameter is zero then no padding is performed, the
- * total amount of data encrypted or decrypted must then be a multiple of the block size or an error will occur.
+ * Enables or disables padding. By default encryption operations are padded
+ * using standard block padding and the padding is checked and removed when
+ * decrypting. If the pad parameter is zero then no padding is performed, the
+ * total amount of data encrypted or decrypted must then be a multiple of the
+ * block size or an error will occur.
*
* See EVP_CIPHER_CTX_set_padding for further information.
*/
@@ -767,7 +808,7 @@ ossl_cipher_set_padding(VALUE self, VALUE padding)
GetCipher(self, ctx);
if (EVP_CIPHER_CTX_set_padding(ctx, pad) != 1)
- ossl_raise(eCipherError, NULL);
+ ossl_raise(eCipherError, NULL);
return padding;
}
@@ -801,9 +842,9 @@ ossl_cipher_iv_length(VALUE self)
GetCipher(self, ctx);
if (EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_FLAG_AEAD_CIPHER)
- len = (int)(VALUE)EVP_CIPHER_CTX_get_app_data(ctx);
+ len = (int)(VALUE)EVP_CIPHER_CTX_get_app_data(ctx);
if (!len)
- len = EVP_CIPHER_CTX_iv_length(ctx);
+ len = EVP_CIPHER_CTX_iv_length(ctx);
return INT2NUM(len);
}
@@ -826,13 +867,17 @@ ossl_cipher_block_size(VALUE self)
/*
* call-seq:
- * cipher.ccm_data_len = integer -> integer
+ * cipher.ccm_data_len = 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=.
+ * Sets the total length of the plaintext / ciphertext message that will be
+ * processed by #update in CCM mode.
*
- * Only call this method after calling Cipher#encrypt or Cipher#decrypt.
+ * Make sure to call this method after #key= and #iv= have been set, and
+ * before #auth_data= or #update are called.
+ *
+ * This method is only available for CCM mode ciphers.
+ *
+ * See also the "AEAD Interface" section of the man page EVP_EncryptInit(3).
*/
static VALUE
ossl_cipher_set_ccm_data_len(VALUE self, VALUE data_len)
@@ -855,11 +900,6 @@ ossl_cipher_set_ccm_data_len(VALUE self, VALUE data_len)
void
Init_ossl_cipher(void)
{
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
-#endif
-
/* Document-class: OpenSSL::Cipher
*
* Provides symmetric algorithms for encryption and decryption. The
@@ -1015,24 +1055,28 @@ Init_ossl_cipher(void)
* could otherwise be exploited to modify ciphertexts in ways beneficial to
* potential attackers.
*
- * An associated data is used where there is additional information, such as
+ * Associated data, also called additional authenticated data (AAD), is
+ * optionally used where there is additional information, such as
* headers or some metadata, that must be also authenticated but not
- * necessarily need to be encrypted. If no associated data is needed for
- * encryption and later decryption, the OpenSSL library still requires a
- * value to be set - "" may be used in case none is available.
+ * necessarily need to be encrypted.
*
* An example using the GCM (Galois/Counter Mode). You have 16 bytes _key_,
* 12 bytes (96 bits) _nonce_ and the associated data _auth_data_. Be sure
* not to reuse the _key_ and _nonce_ pair. Reusing an nonce ruins the
* security guarantees of GCM mode.
*
+ * key = OpenSSL::Random.random_bytes(16)
+ * nonce = OpenSSL::Random.random_bytes(12)
+ * auth_data = "authenticated but unencrypted data"
+ * data = "encrypted data"
+ *
* cipher = OpenSSL::Cipher.new('aes-128-gcm').encrypt
* cipher.key = key
* cipher.iv = nonce
* cipher.auth_data = auth_data
*
* encrypted = cipher.update(data) + cipher.final
- * tag = cipher.auth_tag # produces 16 bytes tag by default
+ * tag = cipher.auth_tag(16)
*
* Now you are the receiver. You know the _key_ and have received _nonce_,
* _auth_data_, _encrypted_ and _tag_ through an untrusted network. Note
@@ -1045,23 +1089,29 @@ Init_ossl_cipher(void)
* decipher = OpenSSL::Cipher.new('aes-128-gcm').decrypt
* decipher.key = key
* decipher.iv = nonce
- * decipher.auth_tag = tag
+ * decipher.auth_tag = tag # could be called at any time before #final
* decipher.auth_data = auth_data
*
* decrypted = decipher.update(encrypted) + decipher.final
*
* puts data == decrypted #=> true
+ *
+ * Note that other AEAD ciphers may require additional steps, such as
+ * setting the expected tag length (#auth_tag_len=) or the total data
+ * length (#ccm_data_len=) in advance. Make sure to read the relevant man
+ * page for details.
*/
cCipher = rb_define_class_under(mOSSL, "Cipher", rb_cObject);
eCipherError = rb_define_class_under(cCipher, "CipherError", eOSSLError);
+ eAuthTagError = rb_define_class_under(cCipher, "AuthTagError", eCipherError);
rb_define_alloc_func(cCipher, ossl_cipher_alloc);
rb_define_method(cCipher, "initialize_copy", ossl_cipher_copy, 1);
rb_define_module_function(cCipher, "ciphers", ossl_s_ciphers, 0);
rb_define_method(cCipher, "initialize", ossl_cipher_initialize, 1);
rb_define_method(cCipher, "reset", ossl_cipher_reset, 0);
- rb_define_method(cCipher, "encrypt", ossl_cipher_encrypt, -1);
- rb_define_method(cCipher, "decrypt", ossl_cipher_decrypt, -1);
+ rb_define_method(cCipher, "encrypt", ossl_cipher_encrypt, 0);
+ rb_define_method(cCipher, "decrypt", ossl_cipher_decrypt, 0);
rb_define_method(cCipher, "pkcs5_keyivgen", ossl_cipher_pkcs5_keyivgen, -1);
rb_define_method(cCipher, "update", ossl_cipher_update, -1);
rb_define_method(cCipher, "final", ossl_cipher_final, 0);
@@ -1083,4 +1133,5 @@ Init_ossl_cipher(void)
id_auth_tag_len = rb_intern_const("auth_tag_len");
id_key_set = rb_intern_const("key_set");
+ id_cipher_holder = rb_intern_const("EVP_CIPHER_holder");
}
diff --git a/ext/openssl/ossl_cipher.h b/ext/openssl/ossl_cipher.h
index 2392d41c6a..fba63a140f 100644
--- a/ext/openssl/ossl_cipher.h
+++ b/ext/openssl/ossl_cipher.h
@@ -5,15 +5,21 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_CIPHER_H_)
#define _OSSL_CIPHER_H_
-extern VALUE cCipher;
-extern VALUE eCipherError;
-
-const EVP_CIPHER *ossl_evp_get_cipherbyname(VALUE);
+/*
+ * Gets EVP_CIPHER from a String or an OpenSSL::Digest instance (discouraged,
+ * but still supported for compatibility). A holder object is created if the
+ * EVP_CIPHER is a "fetched" algorithm.
+ */
+const EVP_CIPHER *ossl_evp_cipher_fetch(VALUE obj, volatile VALUE *holder);
+/*
+ * This is meant for OpenSSL::Engine#cipher. EVP_CIPHER must not be a fetched
+ * one.
+ */
VALUE ossl_cipher_new(const EVP_CIPHER *);
void Init_ossl_cipher(void);
diff --git a/ext/openssl/ossl_config.c b/ext/openssl/ossl_config.c
index 0e598b4d51..274875a978 100644
--- a/ext/openssl/ossl_config.c
+++ b/ext/openssl/ossl_config.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -22,7 +22,7 @@ static const rb_data_type_t ossl_config_type = {
{
0, nconf_free,
},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE,
};
CONF *
@@ -87,6 +87,7 @@ config_s_parse(VALUE klass, VALUE str)
bio = ossl_obj2bio(&str);
config_load_bio(conf, bio); /* Consumes BIO */
+ rb_obj_freeze(obj);
return obj;
}
@@ -144,6 +145,7 @@ config_initialize(int argc, VALUE *argv, VALUE self)
ossl_raise(eConfigError, "BIO_new_file");
config_load_bio(conf, bio); /* Consumes BIO */
}
+ rb_obj_freeze(self);
return self;
}
@@ -158,6 +160,7 @@ config_initialize_copy(VALUE self, VALUE other)
rb_check_frozen(self);
bio = ossl_obj2bio(&str);
config_load_bio(conf, bio); /* Consumes BIO */
+ rb_obj_freeze(self);
return self;
}
@@ -305,18 +308,16 @@ static IMPLEMENT_LHASH_DOALL_ARG_FN(dump_conf_value, CONF_VALUE, VALUE)
*
* Gets the parsable form of the current configuration.
*
- * Given the following configuration being created:
+ * Given the following configuration file being loaded:
*
- * config = OpenSSL::Config.new
- * #=> #<OpenSSL::Config sections=[]>
- * config['default'] = {"foo"=>"bar","baz"=>"buz"}
- * #=> {"foo"=>"bar", "baz"=>"buz"}
+ * config = OpenSSL::Config.load('baz.cnf')
+ * #=> #<OpenSSL::Config sections=["default"]>
* puts config.to_s
* #=> [ default ]
* # foo=bar
* # baz=buz
*
- * You can parse get the serialized configuration using #to_s and then parse
+ * You can get the serialized configuration using #to_s and then parse
* it later:
*
* serialized_config = config.to_s
@@ -412,11 +413,6 @@ Init_ossl_config(void)
char *path;
VALUE path_str;
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
-#endif
-
/* Document-class: OpenSSL::Config
*
* Configuration for the openssl library.
@@ -425,7 +421,7 @@ Init_ossl_config(void)
* 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
+ * See also https://docs.openssl.org/master/man5/config/
*/
cConfig = rb_define_class_under(mOSSL, "Config", rb_cObject);
@@ -455,6 +451,6 @@ Init_ossl_config(void)
* The default system configuration file for OpenSSL.
*/
path = CONF_get1_default_config_file();
- path_str = ossl_buf2str(path, rb_long2int(strlen(path)));
+ path_str = rb_obj_freeze(ossl_buf2str(path, rb_long2int(strlen(path))));
rb_define_const(cConfig, "DEFAULT_CONFIG_FILE", path_str);
}
diff --git a/ext/openssl/ossl_config.h b/ext/openssl/ossl_config.h
index 4e604f1aed..a254360c2c 100644
--- a/ext/openssl/ossl_config.h
+++ b/ext/openssl/ossl_config.h
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#ifndef OSSL_CONFIG_H
#define OSSL_CONFIG_H
diff --git a/ext/openssl/ossl_digest.c b/ext/openssl/ossl_digest.c
index 1ae26a2355..e23968b1e3 100644
--- a/ext/openssl/ossl_digest.c
+++ b/ext/openssl/ossl_digest.c
@@ -5,22 +5,23 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
#define GetDigest(obj, ctx) do { \
TypedData_Get_Struct((obj), EVP_MD_CTX, &ossl_digest_type, (ctx)); \
if (!(ctx)) { \
- ossl_raise(rb_eRuntimeError, "Digest CTX wasn't initialized!"); \
+ ossl_raise(rb_eRuntimeError, "Digest CTX wasn't initialized!"); \
} \
} while (0)
/*
* Classes
*/
-VALUE cDigest;
-VALUE eDigestError;
+static VALUE cDigest;
+static VALUE eDigestError;
+static ID id_md_holder;
static VALUE ossl_digest_alloc(VALUE klass);
@@ -33,39 +34,67 @@ ossl_digest_free(void *ctx)
static const rb_data_type_t ossl_digest_type = {
"OpenSSL/Digest",
{
- 0, ossl_digest_free,
+ 0, ossl_digest_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
+#ifdef OSSL_USE_PROVIDER
+static void
+ossl_evp_md_free(void *ptr)
+{
+ // This is safe to call against const EVP_MD * returned by
+ // EVP_get_digestbyname()
+ EVP_MD_free(ptr);
+}
+
+static const rb_data_type_t ossl_evp_md_holder_type = {
+ "OpenSSL/EVP_MD",
+ {
+ .dfree = ossl_evp_md_free,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+#endif
+
/*
* Public
*/
const EVP_MD *
-ossl_evp_get_digestbyname(VALUE obj)
+ossl_evp_md_fetch(VALUE obj, volatile VALUE *holder)
{
- const EVP_MD *md;
- ASN1_OBJECT *oid = NULL;
-
- if (RB_TYPE_P(obj, T_STRING)) {
- const char *name = StringValueCStr(obj);
-
- md = EVP_get_digestbyname(name);
- if (!md) {
- oid = OBJ_txt2obj(name, 0);
- md = EVP_get_digestbyobj(oid);
- ASN1_OBJECT_free(oid);
- }
- if(!md)
- ossl_raise(rb_eRuntimeError, "Unsupported digest algorithm (%"PRIsVALUE").", obj);
- } else {
+ *holder = Qnil;
+ if (rb_obj_is_kind_of(obj, cDigest)) {
EVP_MD_CTX *ctx;
-
GetDigest(obj, ctx);
-
- md = EVP_MD_CTX_get0_md(ctx);
+ EVP_MD *md = (EVP_MD *)EVP_MD_CTX_get0_md(ctx);
+#ifdef OSSL_USE_PROVIDER
+ *holder = TypedData_Wrap_Struct(0, &ossl_evp_md_holder_type, NULL);
+ if (!EVP_MD_up_ref(md))
+ ossl_raise(eDigestError, "EVP_MD_up_ref");
+ RTYPEDDATA_DATA(*holder) = md;
+#endif
+ return md;
}
+ const char *name = StringValueCStr(obj);
+ EVP_MD *md = (EVP_MD *)EVP_get_digestbyname(name);
+ if (!md) {
+ ASN1_OBJECT *oid = OBJ_txt2obj(name, 0);
+ md = (EVP_MD *)EVP_get_digestbyobj(oid);
+ ASN1_OBJECT_free(oid);
+ }
+#ifdef OSSL_USE_PROVIDER
+ if (!md) {
+ ossl_clear_error();
+ *holder = TypedData_Wrap_Struct(0, &ossl_evp_md_holder_type, NULL);
+ md = EVP_MD_fetch(NULL, name, NULL);
+ RTYPEDDATA_DATA(*holder) = md;
+ }
+#endif
+ if (!md)
+ ossl_raise(eDigestError, "unsupported digest algorithm: %"PRIsVALUE,
+ obj);
return md;
}
@@ -75,14 +104,17 @@ ossl_digest_new(const EVP_MD *md)
VALUE ret;
EVP_MD_CTX *ctx;
+ // NOTE: This does not set id_md_holder because this function should
+ // only be called from ossl_engine.c, which will not use any
+ // reference-counted digests.
ret = ossl_digest_alloc(cDigest);
ctx = EVP_MD_CTX_new();
if (!ctx)
- ossl_raise(eDigestError, "EVP_MD_CTX_new");
+ ossl_raise(eDigestError, "EVP_MD_CTX_new");
RTYPEDDATA_DATA(ret) = ctx;
if (!EVP_DigestInit_ex(ctx, md, NULL))
- ossl_raise(eDigestError, "Digest initialization failed");
+ ossl_raise(eDigestError, "Digest initialization failed");
return ret;
}
@@ -96,7 +128,7 @@ ossl_digest_alloc(VALUE klass)
return TypedData_Wrap_Struct(klass, &ossl_digest_type, 0);
}
-VALUE ossl_digest_update(VALUE, VALUE);
+static VALUE ossl_digest_update(VALUE, VALUE);
/*
* call-seq:
@@ -121,26 +153,28 @@ ossl_digest_initialize(int argc, VALUE *argv, VALUE self)
{
EVP_MD_CTX *ctx;
const EVP_MD *md;
- VALUE type, data;
+ VALUE type, data, md_holder;
rb_scan_args(argc, argv, "11", &type, &data);
- md = ossl_evp_get_digestbyname(type);
+ md = ossl_evp_md_fetch(type, &md_holder);
if (!NIL_P(data)) StringValue(data);
TypedData_Get_Struct(self, EVP_MD_CTX, &ossl_digest_type, ctx);
if (!ctx) {
- RTYPEDDATA_DATA(self) = ctx = EVP_MD_CTX_new();
- if (!ctx)
- ossl_raise(eDigestError, "EVP_MD_CTX_new");
+ RTYPEDDATA_DATA(self) = ctx = EVP_MD_CTX_new();
+ if (!ctx)
+ ossl_raise(eDigestError, "EVP_MD_CTX_new");
}
if (!EVP_DigestInit_ex(ctx, md, NULL))
- ossl_raise(eDigestError, "Digest initialization failed");
+ ossl_raise(eDigestError, "Digest initialization failed");
+ rb_ivar_set(self, id_md_holder, md_holder);
if (!NIL_P(data)) return ossl_digest_update(self, data);
return self;
}
+/* :nodoc: */
static VALUE
ossl_digest_copy(VALUE self, VALUE other)
{
@@ -151,14 +185,14 @@ ossl_digest_copy(VALUE self, VALUE other)
TypedData_Get_Struct(self, EVP_MD_CTX, &ossl_digest_type, ctx1);
if (!ctx1) {
- RTYPEDDATA_DATA(self) = ctx1 = EVP_MD_CTX_new();
- if (!ctx1)
- ossl_raise(eDigestError, "EVP_MD_CTX_new");
+ RTYPEDDATA_DATA(self) = ctx1 = EVP_MD_CTX_new();
+ if (!ctx1)
+ ossl_raise(eDigestError, "EVP_MD_CTX_new");
}
GetDigest(other, ctx2);
if (!EVP_MD_CTX_copy(ctx1, ctx2)) {
- ossl_raise(eDigestError, NULL);
+ ossl_raise(eDigestError, NULL);
}
return self;
}
@@ -183,8 +217,8 @@ ossl_s_digests(VALUE self)
ary = rb_ary_new();
OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH,
- add_digest_name_to_ary,
- (void*)ary);
+ add_digest_name_to_ary,
+ (void*)ary);
return ary;
}
@@ -204,7 +238,7 @@ ossl_digest_reset(VALUE self)
GetDigest(self, ctx);
if (EVP_DigestInit_ex(ctx, EVP_MD_CTX_get0_md(ctx), NULL) != 1) {
- ossl_raise(eDigestError, "Digest initialization failed.");
+ ossl_raise(eDigestError, "Digest initialization failed.");
}
return self;
@@ -225,7 +259,7 @@ ossl_digest_reset(VALUE self)
* result = digest.digest
*
*/
-VALUE
+static VALUE
ossl_digest_update(VALUE self, VALUE data)
{
EVP_MD_CTX *ctx;
@@ -234,7 +268,7 @@ ossl_digest_update(VALUE self, VALUE data)
GetDigest(self, ctx);
if (!EVP_DigestUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)))
- ossl_raise(eDigestError, "EVP_DigestUpdate");
+ ossl_raise(eDigestError, "EVP_DigestUpdate");
return self;
}
@@ -245,25 +279,15 @@ ossl_digest_update(VALUE self, VALUE data)
*
*/
static VALUE
-ossl_digest_finish(int argc, VALUE *argv, VALUE self)
+ossl_digest_finish(VALUE self)
{
EVP_MD_CTX *ctx;
VALUE str;
- int out_len;
GetDigest(self, ctx);
- rb_scan_args(argc, argv, "01", &str);
- out_len = EVP_MD_CTX_size(ctx);
-
- if (NIL_P(str)) {
- str = rb_str_new(NULL, out_len);
- } else {
- StringValue(str);
- rb_str_resize(str, out_len);
- }
-
+ str = rb_str_new(NULL, EVP_MD_CTX_size(ctx));
if (!EVP_DigestFinal_ex(ctx, (unsigned char *)RSTRING_PTR(str), NULL))
- ossl_raise(eDigestError, "EVP_DigestFinal_ex");
+ ossl_raise(eDigestError, "EVP_DigestFinal_ex");
return str;
}
@@ -341,11 +365,6 @@ ossl_digest_block_length(VALUE self)
void
Init_ossl_digest(void)
{
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
-#endif
-
/* Document-class: OpenSSL::Digest
*
* OpenSSL::Digest allows you to compute message digests (sometimes
@@ -446,9 +465,11 @@ Init_ossl_digest(void)
rb_define_method(cDigest, "reset", ossl_digest_reset, 0);
rb_define_method(cDigest, "update", ossl_digest_update, 1);
rb_define_alias(cDigest, "<<", "update");
- rb_define_private_method(cDigest, "finish", ossl_digest_finish, -1);
+ rb_define_private_method(cDigest, "finish", ossl_digest_finish, 0);
rb_define_method(cDigest, "digest_length", ossl_digest_size, 0);
rb_define_method(cDigest, "block_length", ossl_digest_block_length, 0);
rb_define_method(cDigest, "name", ossl_digest_name, 0);
+
+ id_md_holder = rb_intern_const("EVP_MD_holder");
}
diff --git a/ext/openssl/ossl_digest.h b/ext/openssl/ossl_digest.h
index 50bf5666a3..9c3bb2b149 100644
--- a/ext/openssl/ossl_digest.h
+++ b/ext/openssl/ossl_digest.h
@@ -5,15 +5,20 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_DIGEST_H_)
#define _OSSL_DIGEST_H_
-extern VALUE cDigest;
-extern VALUE eDigestError;
-
-const EVP_MD *ossl_evp_get_digestbyname(VALUE);
+/*
+ * Gets EVP_MD from a String or an OpenSSL::Digest instance (discouraged, but
+ * still supported for compatibility). A holder object is created if the EVP_MD
+ * is a "fetched" algorithm.
+ */
+const EVP_MD *ossl_evp_md_fetch(VALUE obj, volatile VALUE *holder);
+/*
+ * This is meant for OpenSSL::Engine#digest. EVP_MD must not be a fetched one.
+ */
VALUE ossl_digest_new(const EVP_MD *);
void Init_ossl_digest(void);
diff --git a/ext/openssl/ossl_engine.c b/ext/openssl/ossl_engine.c
index 9e86321d06..a2bcb07ea4 100644
--- a/ext/openssl/ossl_engine.c
+++ b/ext/openssl/ossl_engine.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -16,7 +16,7 @@
TypedData_Wrap_Struct((klass), &ossl_engine_type, 0)
#define SetEngine(obj, engine) do { \
if (!(engine)) { \
- ossl_raise(rb_eRuntimeError, "ENGINE wasn't initialized."); \
+ ossl_raise(rb_eRuntimeError, "ENGINE wasn't initialized."); \
} \
RTYPEDDATA_DATA(obj) = (engine); \
} while(0)
@@ -37,35 +37,25 @@
*
* See also, https://www.openssl.org/docs/crypto/engine.html
*/
-VALUE cEngine;
+static VALUE cEngine;
/* Document-class: OpenSSL::Engine::EngineError
*
* This is the generic exception for OpenSSL::Engine related errors
*/
-VALUE eEngineError;
+static VALUE eEngineError;
/*
* Private
*/
-#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000
#define OSSL_ENGINE_LOAD_IF_MATCH(engine_name, x) \
do{\
- if(!strcmp(#engine_name, RSTRING_PTR(name))){\
- if (OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_##x, NULL))\
- return Qtrue;\
- else\
- ossl_raise(eEngineError, "OPENSSL_init_crypto"); \
- }\
-}while(0)
-#else
-#define OSSL_ENGINE_LOAD_IF_MATCH(engine_name, x) \
-do{\
- if(!strcmp(#engine_name, RSTRING_PTR(name))){\
- ENGINE_load_##engine_name();\
- return Qtrue;\
- }\
+ if(!strcmp(#engine_name, RSTRING_PTR(name))){\
+ if (OPENSSL_init_crypto(OPENSSL_INIT_ENGINE_##x, NULL))\
+ return Qtrue;\
+ else\
+ ossl_raise(eEngineError, "OPENSSL_init_crypto"); \
+ }\
}while(0)
-#endif
static void
ossl_engine_free(void *engine)
@@ -76,7 +66,7 @@ ossl_engine_free(void *engine)
static const rb_data_type_t ossl_engine_type = {
"OpenSSL/Engine",
{
- 0, ossl_engine_free,
+ 0, ossl_engine_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
@@ -102,50 +92,10 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
return Qtrue;
}
StringValueCStr(name);
-#ifdef HAVE_ENGINE_LOAD_DYNAMIC
OSSL_ENGINE_LOAD_IF_MATCH(dynamic, DYNAMIC);
-#endif
-#ifndef OPENSSL_NO_STATIC_ENGINE
-#ifdef HAVE_ENGINE_LOAD_4758CCA
- OSSL_ENGINE_LOAD_IF_MATCH(4758cca, 4758CCA);
-#endif
-#ifdef HAVE_ENGINE_LOAD_AEP
- OSSL_ENGINE_LOAD_IF_MATCH(aep, AEP);
-#endif
-#ifdef HAVE_ENGINE_LOAD_ATALLA
- OSSL_ENGINE_LOAD_IF_MATCH(atalla, ATALLA);
-#endif
-#ifdef HAVE_ENGINE_LOAD_CHIL
- OSSL_ENGINE_LOAD_IF_MATCH(chil, CHIL);
-#endif
-#ifdef HAVE_ENGINE_LOAD_CSWIFT
- OSSL_ENGINE_LOAD_IF_MATCH(cswift, CSWIFT);
-#endif
-#ifdef HAVE_ENGINE_LOAD_NURON
- OSSL_ENGINE_LOAD_IF_MATCH(nuron, NURON);
-#endif
-#ifdef HAVE_ENGINE_LOAD_SUREWARE
- OSSL_ENGINE_LOAD_IF_MATCH(sureware, SUREWARE);
-#endif
-#ifdef HAVE_ENGINE_LOAD_UBSEC
- OSSL_ENGINE_LOAD_IF_MATCH(ubsec, UBSEC);
-#endif
-#ifdef HAVE_ENGINE_LOAD_PADLOCK
OSSL_ENGINE_LOAD_IF_MATCH(padlock, PADLOCK);
-#endif
-#ifdef HAVE_ENGINE_LOAD_CAPI
OSSL_ENGINE_LOAD_IF_MATCH(capi, CAPI);
-#endif
-#ifdef HAVE_ENGINE_LOAD_GMP
- OSSL_ENGINE_LOAD_IF_MATCH(gmp, GMP);
-#endif
-#ifdef HAVE_ENGINE_LOAD_GOST
- OSSL_ENGINE_LOAD_IF_MATCH(gost, GOST);
-#endif
-#endif
-#ifdef HAVE_ENGINE_LOAD_CRYPTODEV
OSSL_ENGINE_LOAD_IF_MATCH(cryptodev, CRYPTODEV);
-#endif
OSSL_ENGINE_LOAD_IF_MATCH(openssl, OPENSSL);
rb_warning("no such builtin loader for `%"PRIsVALUE"'", name);
return Qnil;
@@ -163,9 +113,6 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass)
static VALUE
ossl_engine_s_cleanup(VALUE self)
{
-#if defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000
- ENGINE_cleanup();
-#endif
return Qnil;
}
@@ -183,12 +130,12 @@ ossl_engine_s_engines(VALUE klass)
ary = rb_ary_new();
for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)){
- obj = NewEngine(klass);
- /* Need a ref count of two here because of ENGINE_free being
- * called internally by OpenSSL when moving to the next ENGINE
- * and by us when releasing the ENGINE reference */
- ENGINE_up_ref(e);
- SetEngine(obj, e);
+ obj = NewEngine(klass);
+ /* Need a ref count of two here because of ENGINE_free being
+ * called internally by OpenSSL when moving to the next ENGINE
+ * and by us when releasing the ENGINE reference */
+ ENGINE_up_ref(e);
+ SetEngine(obj, e);
rb_ary_push(ary, obj);
}
@@ -216,13 +163,13 @@ ossl_engine_s_by_id(VALUE klass, VALUE id)
ossl_engine_s_load(1, &id, klass);
obj = NewEngine(klass);
if(!(e = ENGINE_by_id(RSTRING_PTR(id))))
- ossl_raise(eEngineError, NULL);
+ ossl_raise(eEngineError, NULL);
SetEngine(obj, e);
if(rb_block_given_p()) rb_yield(obj);
if(!ENGINE_init(e))
- ossl_raise(eEngineError, NULL);
+ ossl_raise(eEngineError, NULL);
ENGINE_ctrl(e, ENGINE_CTRL_SET_PASSWORD_CALLBACK,
- 0, NULL, (void(*)(void))ossl_pem_passwd_cb);
+ 0, NULL, (void(*)(void))ossl_pem_passwd_cb);
ossl_clear_error();
return obj;
@@ -237,7 +184,7 @@ ossl_engine_s_by_id(VALUE klass, VALUE id)
* OpenSSL::Engine.load
* OpenSSL::Engine.engines #=> [#<OpenSSL::Engine#>, ...]
* OpenSSL::Engine.engines.first.id
- * #=> "rsax"
+ * #=> "rsax"
*/
static VALUE
ossl_engine_get_id(VALUE self)
@@ -256,7 +203,7 @@ ossl_engine_get_id(VALUE self)
* OpenSSL::Engine.load
* OpenSSL::Engine.engines #=> [#<OpenSSL::Engine#>, ...]
* OpenSSL::Engine.engines.first.name
- * #=> "RSAX engine support"
+ * #=> "RSAX engine support"
*
*/
static VALUE
@@ -327,11 +274,11 @@ ossl_engine_get_cipher(VALUE self, VALUE name)
* Will raise an EngineError if the digest is unavailable.
*
* e = OpenSSL::Engine.by_id("openssl")
- * #=> #<OpenSSL::Engine id="openssl" name="Software engine support">
+ * #=> #<OpenSSL::Engine id="openssl" name="Software engine support">
* e.digest("SHA1")
- * #=> #<OpenSSL::Digest: da39a3ee5e6b4b0d3255bfef95601890afd80709>
+ * #=> #<OpenSSL::Digest: da39a3ee5e6b4b0d3255bfef95601890afd80709>
* e.digest("zomg")
- * #=> OpenSSL::Engine::EngineError: no such digest `zomg'
+ * #=> OpenSSL::Engine::EngineError: no such digest `zomg'
*/
static VALUE
ossl_engine_get_digest(VALUE self, VALUE name)
@@ -373,7 +320,7 @@ ossl_engine_load_privkey(int argc, VALUE *argv, VALUE self)
GetEngine(self, e);
pkey = ENGINE_load_private_key(e, sid, NULL, sdata);
if (!pkey) ossl_raise(eEngineError, NULL);
- obj = ossl_pkey_new(pkey);
+ obj = ossl_pkey_wrap(pkey);
OSSL_PKEY_SET_PRIVATE(obj);
return obj;
@@ -403,7 +350,7 @@ ossl_engine_load_pubkey(int argc, VALUE *argv, VALUE self)
pkey = ENGINE_load_public_key(e, sid, NULL, sdata);
if (!pkey) ossl_raise(eEngineError, NULL);
- return ossl_pkey_new(pkey);
+ return ossl_pkey_wrap(pkey);
}
/*
@@ -418,7 +365,7 @@ ossl_engine_load_pubkey(int argc, VALUE *argv, VALUE self)
* your OS.
*
* [All flags] 0xFFFF
- * [No flags] 0x0000
+ * [No flags] 0x0000
*
* See also <openssl/engine.h>
*/
@@ -452,7 +399,7 @@ ossl_engine_ctrl_cmd(int argc, VALUE *argv, VALUE self)
GetEngine(self, e);
rb_scan_args(argc, argv, "11", &cmd, &val);
ret = ENGINE_ctrl_cmd_string(e, StringValueCStr(cmd),
- NIL_P(val) ? NULL : StringValueCStr(val), 0);
+ NIL_P(val) ? NULL : StringValueCStr(val), 0);
if (!ret) ossl_raise(eEngineError, NULL);
return self;
@@ -462,11 +409,11 @@ static VALUE
ossl_engine_cmd_flag_to_name(int flag)
{
switch(flag){
- case ENGINE_CMD_FLAG_NUMERIC: return rb_str_new2("NUMERIC");
- case ENGINE_CMD_FLAG_STRING: return rb_str_new2("STRING");
- case ENGINE_CMD_FLAG_NO_INPUT: return rb_str_new2("NO_INPUT");
- case ENGINE_CMD_FLAG_INTERNAL: return rb_str_new2("INTERNAL");
- default: return rb_str_new2("UNKNOWN");
+ case ENGINE_CMD_FLAG_NUMERIC: return rb_str_new2("NUMERIC");
+ case ENGINE_CMD_FLAG_STRING: return rb_str_new2("STRING");
+ case ENGINE_CMD_FLAG_NO_INPUT: return rb_str_new2("NO_INPUT");
+ case ENGINE_CMD_FLAG_INTERNAL: return rb_str_new2("INTERNAL");
+ default: return rb_str_new2("UNKNOWN");
}
}
@@ -486,13 +433,13 @@ ossl_engine_get_cmds(VALUE self)
GetEngine(self, e);
ary = rb_ary_new();
if ((defn = ENGINE_get_cmd_defns(e)) != NULL){
- for (p = defn; p->cmd_num > 0; p++){
- tmp = rb_ary_new();
- rb_ary_push(tmp, rb_str_new2(p->cmd_name));
- rb_ary_push(tmp, rb_str_new2(p->cmd_desc));
- rb_ary_push(tmp, ossl_engine_cmd_flag_to_name(p->cmd_flags));
- rb_ary_push(ary, tmp);
- }
+ for (p = defn; p->cmd_num > 0; p++){
+ tmp = rb_ary_new();
+ rb_ary_push(tmp, rb_str_new2(p->cmd_name));
+ rb_ary_push(tmp, rb_str_new2(p->cmd_desc));
+ rb_ary_push(tmp, ossl_engine_cmd_flag_to_name(p->cmd_flags));
+ rb_ary_push(ary, tmp);
+ }
}
return ary;
@@ -511,7 +458,7 @@ ossl_engine_inspect(VALUE self)
GetEngine(self, e);
return rb_sprintf("#<%"PRIsVALUE" id=\"%s\" name=\"%s\">",
- rb_obj_class(self), ENGINE_get_id(e), ENGINE_get_name(e));
+ rb_obj_class(self), ENGINE_get_id(e), ENGINE_get_name(e));
}
#define DefEngineConst(x) rb_define_const(cEngine, #x, INT2NUM(ENGINE_##x))
@@ -519,11 +466,6 @@ ossl_engine_inspect(VALUE self)
void
Init_ossl_engine(void)
{
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
-#endif
-
cEngine = rb_define_class_under(mOSSL, "Engine", rb_cObject);
eEngineError = rb_define_class_under(cEngine, "EngineError", eOSSLError);
@@ -549,12 +491,6 @@ Init_ossl_engine(void)
DefEngineConst(METHOD_DSA);
DefEngineConst(METHOD_DH);
DefEngineConst(METHOD_RAND);
-#ifdef ENGINE_METHOD_BN_MOD_EXP
- DefEngineConst(METHOD_BN_MOD_EXP);
-#endif
-#ifdef ENGINE_METHOD_BN_MOD_EXP_CRT
- DefEngineConst(METHOD_BN_MOD_EXP_CRT);
-#endif
DefEngineConst(METHOD_CIPHERS);
DefEngineConst(METHOD_DIGESTS);
DefEngineConst(METHOD_ALL);
diff --git a/ext/openssl/ossl_engine.h b/ext/openssl/ossl_engine.h
index cd548beea3..cedcebb772 100644
--- a/ext/openssl/ossl_engine.h
+++ b/ext/openssl/ossl_engine.h
@@ -6,14 +6,11 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(OSSL_ENGINE_H)
#define OSSL_ENGINE_H
-extern VALUE cEngine;
-extern VALUE eEngineError;
-
void Init_ossl_engine(void);
#endif /* OSSL_ENGINE_H */
diff --git a/ext/openssl/ossl_hmac.c b/ext/openssl/ossl_hmac.c
index c485ba7e67..ddcc6a5f8d 100644
--- a/ext/openssl/ossl_hmac.c
+++ b/ext/openssl/ossl_hmac.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -14,15 +14,16 @@
#define GetHMAC(obj, ctx) do { \
TypedData_Get_Struct((obj), EVP_MD_CTX, &ossl_hmac_type, (ctx)); \
if (!(ctx)) { \
- ossl_raise(rb_eRuntimeError, "HMAC wasn't initialized"); \
+ ossl_raise(rb_eRuntimeError, "HMAC wasn't initialized"); \
} \
} while (0)
/*
* Classes
*/
-VALUE cHMAC;
-VALUE eHMACError;
+static VALUE cHMAC;
+static VALUE eHMACError;
+static ID id_md_holder;
/*
* Public
@@ -40,7 +41,7 @@ ossl_hmac_free(void *ctx)
static const rb_data_type_t ossl_hmac_type = {
"OpenSSL/HMAC",
{
- 0, ossl_hmac_free,
+ 0, ossl_hmac_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
@@ -73,17 +74,17 @@ ossl_hmac_alloc(VALUE klass)
*
* === Example
*
- * key = 'key'
- * instance = OpenSSL::HMAC.new(key, 'SHA1')
- * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
- * instance.class
- * #=> OpenSSL::HMAC
+ * key = 'key'
+ * instance = OpenSSL::HMAC.new(key, 'SHA1')
+ * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
+ * instance.class
+ * #=> OpenSSL::HMAC
*
* === A note about comparisons
*
* Two instances can be securely compared with #== in constant time:
*
- * other_instance = OpenSSL::HMAC.new('key', 'SHA1')
+ * other_instance = OpenSSL::HMAC.new('key', 'SHA1')
* #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
* instance == other_instance
* #=> true
@@ -94,33 +95,29 @@ ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest)
{
EVP_MD_CTX *ctx;
EVP_PKEY *pkey;
+ const EVP_MD *md;
+ VALUE md_holder;
GetHMAC(self, ctx);
StringValue(key);
-#ifdef HAVE_EVP_PKEY_NEW_RAW_PRIVATE_KEY
+ md = ossl_evp_md_fetch(digest, &md_holder);
pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
(unsigned char *)RSTRING_PTR(key),
RSTRING_LENINT(key));
if (!pkey)
ossl_raise(eHMACError, "EVP_PKEY_new_raw_private_key");
-#else
- pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL,
- (unsigned char *)RSTRING_PTR(key),
- RSTRING_LENINT(key));
- if (!pkey)
- ossl_raise(eHMACError, "EVP_PKEY_new_mac_key");
-#endif
- if (EVP_DigestSignInit(ctx, NULL, ossl_evp_get_digestbyname(digest),
- NULL, pkey) != 1) {
+ if (EVP_DigestSignInit(ctx, NULL, md, NULL, pkey) != 1) {
EVP_PKEY_free(pkey);
ossl_raise(eHMACError, "EVP_DigestSignInit");
}
+ rb_ivar_set(self, id_md_holder, md_holder);
/* Decrement reference counter; EVP_MD_CTX still keeps it */
EVP_PKEY_free(pkey);
return self;
}
+/* :nodoc: */
static VALUE
ossl_hmac_copy(VALUE self, VALUE other)
{
@@ -145,13 +142,13 @@ ossl_hmac_copy(VALUE self, VALUE other)
*
* === Example
*
- * first_chunk = 'The quick brown fox jumps '
- * second_chunk = 'over the lazy dog'
+ * first_chunk = 'The quick brown fox jumps '
+ * second_chunk = 'over the lazy dog'
*
- * instance.update(first_chunk)
- * #=> 5b9a8038a65d571076d97fe783989e52278a492a
- * instance.update(second_chunk)
- * #=> de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9
+ * instance.update(first_chunk)
+ * #=> 5b9a8038a65d571076d97fe783989e52278a492a
+ * instance.update(second_chunk)
+ * #=> de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9
*
*/
static VALUE
@@ -229,14 +226,14 @@ ossl_hmac_hexdigest(VALUE self)
*
* === Example
*
- * data = "The quick brown fox jumps over the lazy dog"
- * instance = OpenSSL::HMAC.new('key', 'SHA1')
- * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
+ * data = "The quick brown fox jumps over the lazy dog"
+ * instance = OpenSSL::HMAC.new('key', 'SHA1')
+ * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
*
- * instance.update(data)
- * #=> de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9
- * instance.reset
- * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
+ * instance.update(data)
+ * #=> de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9
+ * instance.reset
+ * #=> f42bb0eeb018ebbd4597ae7213711ec60760843f
*
*/
static VALUE
@@ -259,11 +256,6 @@ ossl_hmac_reset(VALUE self)
void
Init_ossl_hmac(void)
{
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
-#endif
-
/*
* Document-class: OpenSSL::HMAC
*
@@ -307,4 +299,6 @@ Init_ossl_hmac(void)
rb_define_method(cHMAC, "hexdigest", ossl_hmac_hexdigest, 0);
rb_define_alias(cHMAC, "inspect", "hexdigest");
rb_define_alias(cHMAC, "to_s", "hexdigest");
+
+ id_md_holder = rb_intern_const("EVP_MD_holder");
}
diff --git a/ext/openssl/ossl_hmac.h b/ext/openssl/ossl_hmac.h
index 7c51f4722d..e5bed37c9f 100644
--- a/ext/openssl/ossl_hmac.h
+++ b/ext/openssl/ossl_hmac.h
@@ -5,14 +5,11 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_HMAC_H_)
#define _OSSL_HMAC_H_
-extern VALUE cHMAC;
-extern VALUE eHMACError;
-
void Init_ossl_hmac(void);
#endif /* _OSSL_HMAC_H_ */
diff --git a/ext/openssl/ossl_kdf.c b/ext/openssl/ossl_kdf.c
index ba197a659e..1f28016440 100644
--- a/ext/openssl/ossl_kdf.c
+++ b/ext/openssl/ossl_kdf.c
@@ -3,9 +3,7 @@
* Copyright (C) 2007, 2017 Ruby/OpenSSL Project Authors
*/
#include "ossl.h"
-#if OSSL_OPENSSL_PREREQ(1, 1, 0) || OSSL_LIBRESSL_PREREQ(3, 6, 0)
-# include <openssl/kdf.h>
-#endif
+#include <openssl/kdf.h>
static VALUE mKDF, eKDF;
@@ -37,16 +35,16 @@ static VALUE mKDF, eKDF;
static VALUE
kdf_pbkdf2_hmac(int argc, VALUE *argv, VALUE self)
{
- VALUE pass, salt, opts, kwargs[4], str;
+ VALUE pass, salt, opts, kwargs[4], str, md_holder;
static ID kwargs_ids[4];
int iters, len;
const EVP_MD *md;
if (!kwargs_ids[0]) {
- kwargs_ids[0] = rb_intern_const("salt");
- kwargs_ids[1] = rb_intern_const("iterations");
- kwargs_ids[2] = rb_intern_const("length");
- kwargs_ids[3] = rb_intern_const("hash");
+ kwargs_ids[0] = rb_intern_const("salt");
+ kwargs_ids[1] = rb_intern_const("iterations");
+ kwargs_ids[2] = rb_intern_const("length");
+ kwargs_ids[3] = rb_intern_const("hash");
}
rb_scan_args(argc, argv, "1:", &pass, &opts);
rb_get_kwargs(opts, kwargs_ids, 4, 0, kwargs);
@@ -55,14 +53,14 @@ kdf_pbkdf2_hmac(int argc, VALUE *argv, VALUE self)
salt = StringValue(kwargs[0]);
iters = NUM2INT(kwargs[1]);
len = NUM2INT(kwargs[2]);
- md = ossl_evp_get_digestbyname(kwargs[3]);
+ md = ossl_evp_md_fetch(kwargs[3], &md_holder);
str = rb_str_new(0, len);
if (!PKCS5_PBKDF2_HMAC(RSTRING_PTR(pass), RSTRING_LENINT(pass),
- (unsigned char *)RSTRING_PTR(salt),
- RSTRING_LENINT(salt), iters, md, len,
- (unsigned char *)RSTRING_PTR(str)))
- ossl_raise(eKDF, "PKCS5_PBKDF2_HMAC");
+ (unsigned char *)RSTRING_PTR(salt),
+ RSTRING_LENINT(salt), iters, md, len,
+ (unsigned char *)RSTRING_PTR(str)))
+ ossl_raise(eKDF, "PKCS5_PBKDF2_HMAC");
return str;
}
@@ -109,11 +107,11 @@ kdf_scrypt(int argc, VALUE *argv, VALUE self)
uint64_t N, r, p, maxmem;
if (!kwargs_ids[0]) {
- kwargs_ids[0] = rb_intern_const("salt");
- kwargs_ids[1] = rb_intern_const("N");
- kwargs_ids[2] = rb_intern_const("r");
- kwargs_ids[3] = rb_intern_const("p");
- kwargs_ids[4] = rb_intern_const("length");
+ kwargs_ids[0] = rb_intern_const("salt");
+ kwargs_ids[1] = rb_intern_const("N");
+ kwargs_ids[2] = rb_intern_const("r");
+ kwargs_ids[3] = rb_intern_const("p");
+ kwargs_ids[4] = rb_intern_const("length");
}
rb_scan_args(argc, argv, "1:", &pass, &opts);
rb_get_kwargs(opts, kwargs_ids, 5, 0, kwargs);
@@ -133,15 +131,14 @@ kdf_scrypt(int argc, VALUE *argv, VALUE self)
str = rb_str_new(0, len);
if (!EVP_PBE_scrypt(RSTRING_PTR(pass), RSTRING_LEN(pass),
- (unsigned char *)RSTRING_PTR(salt), RSTRING_LEN(salt),
- N, r, p, maxmem, (unsigned char *)RSTRING_PTR(str), len))
- ossl_raise(eKDF, "EVP_PBE_scrypt");
+ (unsigned char *)RSTRING_PTR(salt), RSTRING_LEN(salt),
+ N, r, p, maxmem, (unsigned char *)RSTRING_PTR(str), len))
+ ossl_raise(eKDF, "EVP_PBE_scrypt");
return str;
}
#endif
-#if OSSL_OPENSSL_PREREQ(1, 1, 0) || OSSL_LIBRESSL_PREREQ(3, 6, 0)
/*
* call-seq:
* KDF.hkdf(ikm, salt:, info:, length:, hash:) -> String
@@ -175,7 +172,7 @@ kdf_scrypt(int argc, VALUE *argv, VALUE self)
static VALUE
kdf_hkdf(int argc, VALUE *argv, VALUE self)
{
- VALUE ikm, salt, info, opts, kwargs[4], str;
+ VALUE ikm, salt, info, opts, kwargs[4], str, md_holder;
static ID kwargs_ids[4];
int saltlen, ikmlen, infolen;
size_t len;
@@ -183,10 +180,10 @@ kdf_hkdf(int argc, VALUE *argv, VALUE self)
EVP_PKEY_CTX *pctx;
if (!kwargs_ids[0]) {
- kwargs_ids[0] = rb_intern_const("salt");
- kwargs_ids[1] = rb_intern_const("info");
- kwargs_ids[2] = rb_intern_const("length");
- kwargs_ids[3] = rb_intern_const("hash");
+ kwargs_ids[0] = rb_intern_const("salt");
+ kwargs_ids[1] = rb_intern_const("info");
+ kwargs_ids[2] = rb_intern_const("length");
+ kwargs_ids[3] = rb_intern_const("hash");
}
rb_scan_args(argc, argv, "1:", &ikm, &opts);
rb_get_kwargs(opts, kwargs_ids, 4, 0, kwargs);
@@ -199,55 +196,49 @@ kdf_hkdf(int argc, VALUE *argv, VALUE self)
infolen = RSTRING_LENINT(info);
len = (size_t)NUM2LONG(kwargs[2]);
if (len > LONG_MAX)
- rb_raise(rb_eArgError, "length must be non-negative");
- md = ossl_evp_get_digestbyname(kwargs[3]);
+ rb_raise(rb_eArgError, "length must be non-negative");
+ md = ossl_evp_md_fetch(kwargs[3], &md_holder);
str = rb_str_new(NULL, (long)len);
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL);
if (!pctx)
- ossl_raise(eKDF, "EVP_PKEY_CTX_new_id");
+ ossl_raise(eKDF, "EVP_PKEY_CTX_new_id");
if (EVP_PKEY_derive_init(pctx) <= 0) {
- EVP_PKEY_CTX_free(pctx);
- ossl_raise(eKDF, "EVP_PKEY_derive_init");
+ EVP_PKEY_CTX_free(pctx);
+ ossl_raise(eKDF, "EVP_PKEY_derive_init");
}
if (EVP_PKEY_CTX_set_hkdf_md(pctx, md) <= 0) {
- EVP_PKEY_CTX_free(pctx);
- ossl_raise(eKDF, "EVP_PKEY_CTX_set_hkdf_md");
+ EVP_PKEY_CTX_free(pctx);
+ ossl_raise(eKDF, "EVP_PKEY_CTX_set_hkdf_md");
}
if (EVP_PKEY_CTX_set1_hkdf_salt(pctx, (unsigned char *)RSTRING_PTR(salt),
- saltlen) <= 0) {
- EVP_PKEY_CTX_free(pctx);
- ossl_raise(eKDF, "EVP_PKEY_CTX_set_hkdf_salt");
+ saltlen) <= 0) {
+ EVP_PKEY_CTX_free(pctx);
+ ossl_raise(eKDF, "EVP_PKEY_CTX_set_hkdf_salt");
}
if (EVP_PKEY_CTX_set1_hkdf_key(pctx, (unsigned char *)RSTRING_PTR(ikm),
- ikmlen) <= 0) {
- EVP_PKEY_CTX_free(pctx);
- ossl_raise(eKDF, "EVP_PKEY_CTX_set_hkdf_key");
+ ikmlen) <= 0) {
+ EVP_PKEY_CTX_free(pctx);
+ ossl_raise(eKDF, "EVP_PKEY_CTX_set_hkdf_key");
}
if (EVP_PKEY_CTX_add1_hkdf_info(pctx, (unsigned char *)RSTRING_PTR(info),
- infolen) <= 0) {
- EVP_PKEY_CTX_free(pctx);
- ossl_raise(eKDF, "EVP_PKEY_CTX_set_hkdf_info");
+ infolen) <= 0) {
+ EVP_PKEY_CTX_free(pctx);
+ ossl_raise(eKDF, "EVP_PKEY_CTX_set_hkdf_info");
}
if (EVP_PKEY_derive(pctx, (unsigned char *)RSTRING_PTR(str), &len) <= 0) {
- EVP_PKEY_CTX_free(pctx);
- ossl_raise(eKDF, "EVP_PKEY_derive");
+ EVP_PKEY_CTX_free(pctx);
+ ossl_raise(eKDF, "EVP_PKEY_derive");
}
rb_str_set_len(str, (long)len);
EVP_PKEY_CTX_free(pctx);
return str;
}
-#endif
void
Init_ossl_kdf(void)
{
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
-#endif
-
/*
* Document-module: OpenSSL::KDF
*
@@ -305,7 +296,5 @@ Init_ossl_kdf(void)
#if defined(HAVE_EVP_PBE_SCRYPT)
rb_define_module_function(mKDF, "scrypt", kdf_scrypt, -1);
#endif
-#if OSSL_OPENSSL_PREREQ(1, 1, 0) || OSSL_LIBRESSL_PREREQ(3, 6, 0)
rb_define_module_function(mKDF, "hkdf", kdf_hkdf, -1);
-#endif
}
diff --git a/ext/openssl/ossl_ns_spki.c b/ext/openssl/ossl_ns_spki.c
index 9d70b5d87a..8440c2ee82 100644
--- a/ext/openssl/ossl_ns_spki.c
+++ b/ext/openssl/ossl_ns_spki.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -13,23 +13,23 @@
TypedData_Wrap_Struct((klass), &ossl_netscape_spki_type, 0)
#define SetSPKI(obj, spki) do { \
if (!(spki)) { \
- ossl_raise(rb_eRuntimeError, "SPKI wasn't initialized!"); \
+ ossl_raise(rb_eRuntimeError, "SPKI wasn't initialized!"); \
} \
RTYPEDDATA_DATA(obj) = (spki); \
} while (0)
#define GetSPKI(obj, spki) do { \
TypedData_Get_Struct((obj), NETSCAPE_SPKI, &ossl_netscape_spki_type, (spki)); \
if (!(spki)) { \
- ossl_raise(rb_eRuntimeError, "SPKI wasn't initialized!"); \
+ ossl_raise(rb_eRuntimeError, "SPKI wasn't initialized!"); \
} \
} while (0)
/*
* Classes
*/
-VALUE mNetscape;
-VALUE cSPKI;
-VALUE eSPKIError;
+static VALUE mNetscape;
+static VALUE cSPKI;
+static VALUE eSPKIError;
/*
* Public functions
@@ -48,7 +48,7 @@ ossl_netscape_spki_free(void *spki)
static const rb_data_type_t ossl_netscape_spki_type = {
"OpenSSL/NETSCAPE_SPKI",
{
- 0, ossl_netscape_spki_free,
+ 0, ossl_netscape_spki_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
@@ -61,7 +61,7 @@ ossl_spki_alloc(VALUE klass)
obj = NewSPKI(klass);
if (!(spki = NETSCAPE_SPKI_new())) {
- ossl_raise(eSPKIError, NULL);
+ ossl_raise(eSPKIError, NULL);
}
SetSPKI(obj, spki);
@@ -83,15 +83,15 @@ ossl_spki_initialize(int argc, VALUE *argv, VALUE self)
const unsigned char *p;
if (rb_scan_args(argc, argv, "01", &buffer) == 0) {
- return self;
+ return self;
}
StringValue(buffer);
if (!(spki = NETSCAPE_SPKI_b64_decode(RSTRING_PTR(buffer), RSTRING_LENINT(buffer)))) {
- ossl_clear_error();
- p = (unsigned char *)RSTRING_PTR(buffer);
- if (!(spki = d2i_NETSCAPE_SPKI(NULL, &p, RSTRING_LEN(buffer)))) {
- ossl_raise(eSPKIError, NULL);
- }
+ ossl_clear_error();
+ p = (unsigned char *)RSTRING_PTR(buffer);
+ if (!(spki = d2i_NETSCAPE_SPKI(NULL, &p, RSTRING_LEN(buffer)))) {
+ ossl_raise(eSPKIError, NULL);
+ }
}
NETSCAPE_SPKI_free(DATA_PTR(self));
SetSPKI(self, spki);
@@ -115,11 +115,11 @@ ossl_spki_to_der(VALUE self)
GetSPKI(self, spki);
if ((len = i2d_NETSCAPE_SPKI(spki, NULL)) <= 0)
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eSPKIError, "i2d_NETSCAPE_SPKI");
str = rb_str_new(0, len);
p = (unsigned char *)RSTRING_PTR(str);
if (i2d_NETSCAPE_SPKI(spki, &p) <= 0)
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eSPKIError, "i2d_NETSCAPE_SPKI");
ossl_str_adjust(str, p);
return str;
@@ -140,7 +140,7 @@ ossl_spki_to_pem(VALUE self)
GetSPKI(self, spki);
if (!(data = NETSCAPE_SPKI_b64_encode(spki))) {
- ossl_raise(eSPKIError, NULL);
+ ossl_raise(eSPKIError, NULL);
}
str = ossl_buf2str(data, rb_long2int(strlen(data)));
@@ -162,11 +162,11 @@ ossl_spki_print(VALUE self)
GetSPKI(self, spki);
if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eSPKIError, NULL);
+ ossl_raise(eSPKIError, NULL);
}
if (!NETSCAPE_SPKI_print(out, spki)) {
- BIO_free(out);
- ossl_raise(eSPKIError, NULL);
+ BIO_free(out);
+ ossl_raise(eSPKIError, NULL);
}
return ossl_membio2str(out);
@@ -187,10 +187,10 @@ ossl_spki_get_public_key(VALUE self)
GetSPKI(self, spki);
if (!(pkey = NETSCAPE_SPKI_get_pubkey(spki))) { /* adds an reference */
- ossl_raise(eSPKIError, NULL);
+ ossl_raise(eSPKIError, NULL);
}
- return ossl_pkey_new(pkey); /* NO DUP - OK */
+ return ossl_pkey_wrap(pkey);
}
/*
@@ -214,7 +214,7 @@ ossl_spki_set_public_key(VALUE self, VALUE key)
pkey = GetPKeyPtr(key);
ossl_pkey_check_public_key(pkey);
if (!NETSCAPE_SPKI_set_pubkey(spki, pkey))
- ossl_raise(eSPKIError, "NETSCAPE_SPKI_set_pubkey");
+ ossl_raise(eSPKIError, "NETSCAPE_SPKI_set_pubkey");
return key;
}
@@ -230,13 +230,12 @@ ossl_spki_get_challenge(VALUE self)
NETSCAPE_SPKI *spki;
GetSPKI(self, spki);
- if (spki->spkac->challenge->length <= 0) {
- OSSL_Debug("Challenge.length <= 0?");
- return rb_str_new(0, 0);
+ if (ASN1_STRING_length(spki->spkac->challenge) <= 0) {
+ OSSL_Debug("Challenge.length <= 0?");
+ return rb_str_new(0, 0);
}
- return rb_str_new((const char *)spki->spkac->challenge->data,
- spki->spkac->challenge->length);
+ return asn1str_to_str(spki->spkac->challenge);
}
/*
@@ -257,8 +256,8 @@ ossl_spki_set_challenge(VALUE self, VALUE str)
StringValue(str);
GetSPKI(self, spki);
if (!ASN1_STRING_set(spki->spkac->challenge, RSTRING_PTR(str),
- RSTRING_LENINT(str))) {
- ossl_raise(eSPKIError, NULL);
+ RSTRING_LENINT(str))) {
+ ossl_raise(eSPKIError, NULL);
}
return str;
@@ -283,13 +282,13 @@ ossl_spki_sign(VALUE self, VALUE key, VALUE digest)
NETSCAPE_SPKI *spki;
EVP_PKEY *pkey;
const EVP_MD *md;
+ VALUE md_holder;
pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
- md = ossl_evp_get_digestbyname(digest);
+ md = ossl_evp_md_fetch(digest, &md_holder);
GetSPKI(self, spki);
- if (!NETSCAPE_SPKI_sign(spki, pkey, md)) {
- ossl_raise(eSPKIError, NULL);
- }
+ if (!NETSCAPE_SPKI_sign(spki, pkey, md))
+ ossl_raise(eSPKIError, "NETSCAPE_SPKI_sign");
return self;
}
@@ -315,12 +314,12 @@ ossl_spki_verify(VALUE self, VALUE key)
ossl_pkey_check_public_key(pkey);
switch (NETSCAPE_SPKI_verify(spki, pkey)) {
case 0:
- ossl_clear_error();
- return Qfalse;
+ ossl_clear_error();
+ return Qfalse;
case 1:
- return Qtrue;
+ return Qtrue;
default:
- ossl_raise(eSPKIError, "NETSCAPE_SPKI_verify");
+ ossl_raise(eSPKIError, "NETSCAPE_SPKI_verify");
}
}
@@ -378,11 +377,6 @@ ossl_spki_verify(VALUE self, VALUE key)
void
Init_ossl_ns_spki(void)
{
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
-#endif
-
mNetscape = rb_define_module_under(mOSSL, "Netscape");
eSPKIError = rb_define_class_under(mNetscape, "SPKIError", eOSSLError);
diff --git a/ext/openssl/ossl_ns_spki.h b/ext/openssl/ossl_ns_spki.h
index 62ba8cb163..043b6cdb66 100644
--- a/ext/openssl/ossl_ns_spki.h
+++ b/ext/openssl/ossl_ns_spki.h
@@ -5,15 +5,11 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_NS_SPKI_H_)
#define _OSSL_NS_SPKI_H_
-extern VALUE mNetscape;
-extern VALUE cSPKI;
-extern VALUE eSPKIError;
-
void Init_ossl_ns_spki(void);
#endif /* _OSSL_NS_SPKI_H_ */
diff --git a/ext/openssl/ossl_ocsp.c b/ext/openssl/ossl_ocsp.c
index df986bb3ee..93d8bc8567 100644
--- a/ext/openssl/ossl_ocsp.c
+++ b/ext/openssl/ossl_ocsp.c
@@ -6,7 +6,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -67,13 +67,13 @@
if(!(cid)) ossl_raise(rb_eRuntimeError, "Cert ID wasn't initialized!"); \
} while (0)
-VALUE mOCSP;
-VALUE eOCSPError;
-VALUE cOCSPReq;
-VALUE cOCSPRes;
-VALUE cOCSPBasicRes;
-VALUE cOCSPSingleRes;
-VALUE cOCSPCertId;
+static VALUE mOCSP;
+static VALUE eOCSPError;
+static VALUE cOCSPReq;
+static VALUE cOCSPRes;
+static VALUE cOCSPBasicRes;
+static VALUE cOCSPSingleRes;
+static VALUE cOCSPCertId;
static void
ossl_ocsp_request_free(void *ptr)
@@ -84,7 +84,7 @@ ossl_ocsp_request_free(void *ptr)
static const rb_data_type_t ossl_ocsp_request_type = {
"OpenSSL/OCSP/REQUEST",
{
- 0, ossl_ocsp_request_free,
+ 0, ossl_ocsp_request_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
@@ -98,7 +98,7 @@ ossl_ocsp_response_free(void *ptr)
static const rb_data_type_t ossl_ocsp_response_type = {
"OpenSSL/OCSP/RESPONSE",
{
- 0, ossl_ocsp_response_free,
+ 0, ossl_ocsp_response_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
@@ -112,7 +112,7 @@ ossl_ocsp_basicresp_free(void *ptr)
static const rb_data_type_t ossl_ocsp_basicresp_type = {
"OpenSSL/OCSP/BASICRESP",
{
- 0, ossl_ocsp_basicresp_free,
+ 0, ossl_ocsp_basicresp_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
@@ -126,7 +126,7 @@ ossl_ocsp_singleresp_free(void *ptr)
static const rb_data_type_t ossl_ocsp_singleresp_type = {
"OpenSSL/OCSP/SINGLERESP",
{
- 0, ossl_ocsp_singleresp_free,
+ 0, ossl_ocsp_singleresp_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
@@ -140,7 +140,7 @@ ossl_ocsp_certid_free(void *ptr)
static const rb_data_type_t ossl_ocsp_certid_type = {
"OpenSSL/OCSP/CERTID",
{
- 0, ossl_ocsp_certid_free,
+ 0, ossl_ocsp_certid_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
@@ -149,10 +149,14 @@ static const rb_data_type_t ossl_ocsp_certid_type = {
* Public
*/
static VALUE
-ossl_ocspcertid_new(OCSP_CERTID *cid)
+ossl_ocspcid_new(const OCSP_CERTID *cid)
{
VALUE obj = NewOCSPCertId(cOCSPCertId);
- SetOCSPCertId(obj, cid);
+ /* OpenSSL 1.1.1 takes a non-const pointer */
+ OCSP_CERTID *cid_new = OCSP_CERTID_dup((OCSP_CERTID *)cid);
+ if (!cid_new)
+ ossl_raise(eOCSPError, "OCSP_CERTID_dup");
+ SetOCSPCertId(obj, cid_new);
return obj;
}
@@ -167,12 +171,13 @@ ossl_ocspreq_alloc(VALUE klass)
obj = NewOCSPReq(klass);
if (!(req = OCSP_REQUEST_new()))
- ossl_raise(eOCSPError, NULL);
+ ossl_raise(eOCSPError, NULL);
SetOCSPReq(obj, req);
return obj;
}
+/* :nodoc: */
static VALUE
ossl_ocspreq_initialize_copy(VALUE self, VALUE other)
{
@@ -184,7 +189,7 @@ ossl_ocspreq_initialize_copy(VALUE self, VALUE other)
req_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_REQUEST), req);
if (!req_new)
- ossl_raise(eOCSPError, "ASN1_item_dup");
+ ossl_raise(eOCSPError, "ASN1_item_dup");
SetOCSPReq(self, req_new);
OCSP_REQUEST_free(req_old);
@@ -210,15 +215,15 @@ ossl_ocspreq_initialize(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "01", &arg);
if(!NIL_P(arg)){
- GetOCSPReq(self, req);
- arg = ossl_to_der_if_possible(arg);
- StringValue(arg);
- p = (unsigned char *)RSTRING_PTR(arg);
- req_new = d2i_OCSP_REQUEST(NULL, &p, RSTRING_LEN(arg));
- if (!req_new)
- ossl_raise(eOCSPError, "d2i_OCSP_REQUEST");
- SetOCSPReq(self, req_new);
- OCSP_REQUEST_free(req);
+ GetOCSPReq(self, req);
+ arg = ossl_to_der_if_possible(arg);
+ StringValue(arg);
+ p = (unsigned char *)RSTRING_PTR(arg);
+ req_new = d2i_OCSP_REQUEST(NULL, &p, RSTRING_LEN(arg));
+ if (!req_new)
+ ossl_raise(eOCSPError, "d2i_OCSP_REQUEST");
+ SetOCSPReq(self, req_new);
+ OCSP_REQUEST_free(req);
}
return self;
@@ -244,13 +249,13 @@ ossl_ocspreq_add_nonce(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "01", &val);
if(NIL_P(val)) {
- GetOCSPReq(self, req);
- ret = OCSP_request_add1_nonce(req, NULL, -1);
+ GetOCSPReq(self, req);
+ ret = OCSP_request_add1_nonce(req, NULL, -1);
}
else{
- StringValue(val);
- GetOCSPReq(self, req);
- ret = OCSP_request_add1_nonce(req, (unsigned char *)RSTRING_PTR(val), RSTRING_LENINT(val));
+ StringValue(val);
+ GetOCSPReq(self, req);
+ ret = OCSP_request_add1_nonce(req, (unsigned char *)RSTRING_PTR(val), RSTRING_LENINT(val));
}
if(!ret) ossl_raise(eOCSPError, NULL);
@@ -307,10 +312,10 @@ ossl_ocspreq_add_certid(VALUE self, VALUE certid)
GetOCSPCertId(certid, id);
if (!(id_new = OCSP_CERTID_dup(id)))
- ossl_raise(eOCSPError, "OCSP_CERTID_dup");
+ ossl_raise(eOCSPError, "OCSP_CERTID_dup");
if (!OCSP_request_add0_id(req, id_new)) {
- OCSP_CERTID_free(id_new);
- ossl_raise(eOCSPError, "OCSP_request_add0_id");
+ OCSP_CERTID_free(id_new);
+ ossl_raise(eOCSPError, "OCSP_request_add0_id");
}
return self;
@@ -327,21 +332,19 @@ static VALUE
ossl_ocspreq_get_certid(VALUE self)
{
OCSP_REQUEST *req;
- OCSP_ONEREQ *one;
- OCSP_CERTID *id;
- VALUE ary, tmp;
- int i, count;
GetOCSPReq(self, req);
- count = OCSP_request_onereq_count(req);
- ary = (count > 0) ? rb_ary_new() : Qnil;
- for(i = 0; i < count; i++){
- one = OCSP_request_onereq_get0(req, i);
- tmp = NewOCSPCertId(cOCSPCertId);
- if(!(id = OCSP_CERTID_dup(OCSP_onereq_get0_id(one))))
- ossl_raise(eOCSPError, NULL);
- SetOCSPCertId(tmp, id);
- rb_ary_push(ary, tmp);
+ int count = OCSP_request_onereq_count(req);
+ if (count < 0)
+ ossl_raise(eOCSPError, "OCSP_request_onereq_count");
+ if (count == 0)
+ return Qnil;
+
+ VALUE ary = rb_ary_new_capa(count);
+ for (int i = 0; i < count; i++) {
+ OCSP_ONEREQ *one = OCSP_request_onereq_get0(req, i);
+ OCSP_CERTID *cid = OCSP_onereq_get0_id(one);
+ rb_ary_push(ary, ossl_ocspcid_new(cid));
}
return ary;
@@ -366,7 +369,7 @@ ossl_ocspreq_get_certid(VALUE self)
static VALUE
ossl_ocspreq_sign(int argc, VALUE *argv, VALUE self)
{
- VALUE signer_cert, signer_key, certs, flags, digest;
+ VALUE signer_cert, signer_key, certs, flags, digest, md_holder;
OCSP_REQUEST *req;
X509 *signer;
EVP_PKEY *key;
@@ -380,19 +383,17 @@ ossl_ocspreq_sign(int argc, VALUE *argv, VALUE self)
signer = GetX509CertPtr(signer_cert);
key = GetPrivPKeyPtr(signer_key);
if (!NIL_P(flags))
- flg = NUM2INT(flags);
- if (NIL_P(digest))
- md = NULL;
- else
- md = ossl_evp_get_digestbyname(digest);
+ flg = NUM2INT(flags);
+ md = NIL_P(digest) ? NULL : ossl_evp_md_fetch(digest, &md_holder);
if (NIL_P(certs))
- flg |= OCSP_NOCERTS;
+ flg |= OCSP_NOCERTS;
else
- x509s = ossl_x509_ary2sk(certs);
+ x509s = ossl_x509_ary2sk(certs);
ret = OCSP_request_sign(req, signer, key, md, x509s, flg);
sk_X509_pop_free(x509s, X509_free);
- if (!ret) ossl_raise(eOCSPError, NULL);
+ if (!ret)
+ ossl_raise(eOCSPError, "OCSP_request_sign");
return self;
}
@@ -426,7 +427,7 @@ ossl_ocspreq_verify(int argc, VALUE *argv, VALUE self)
result = OCSP_request_verify(req, x509s, x509st, flg);
sk_X509_pop_free(x509s, X509_free);
if (result <= 0)
- ossl_clear_error();
+ ossl_clear_error();
return result > 0 ? Qtrue : Qfalse;
}
@@ -445,11 +446,11 @@ ossl_ocspreq_to_der(VALUE self)
GetOCSPReq(self, req);
if((len = i2d_OCSP_REQUEST(req, NULL)) <= 0)
- ossl_raise(eOCSPError, NULL);
+ ossl_raise(eOCSPError, NULL);
str = rb_str_new(0, len);
p = (unsigned char *)RSTRING_PTR(str);
if(i2d_OCSP_REQUEST(req, &p) <= 0)
- ossl_raise(eOCSPError, NULL);
+ ossl_raise(eOCSPError, NULL);
ossl_str_adjust(str, p);
return str;
@@ -493,7 +494,7 @@ ossl_ocspres_s_create(VALUE klass, VALUE status, VALUE basic_resp)
else GetOCSPBasicRes(basic_resp, bs); /* NO NEED TO DUP */
obj = NewOCSPRes(klass);
if(!(res = OCSP_response_create(st, bs)))
- ossl_raise(eOCSPError, NULL);
+ ossl_raise(eOCSPError, NULL);
SetOCSPRes(obj, res);
return obj;
@@ -507,12 +508,13 @@ ossl_ocspres_alloc(VALUE klass)
obj = NewOCSPRes(klass);
if(!(res = OCSP_RESPONSE_new()))
- ossl_raise(eOCSPError, NULL);
+ ossl_raise(eOCSPError, NULL);
SetOCSPRes(obj, res);
return obj;
}
+/* :nodoc: */
static VALUE
ossl_ocspres_initialize_copy(VALUE self, VALUE other)
{
@@ -524,7 +526,7 @@ ossl_ocspres_initialize_copy(VALUE self, VALUE other)
res_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_RESPONSE), res);
if (!res_new)
- ossl_raise(eOCSPError, "ASN1_item_dup");
+ ossl_raise(eOCSPError, "ASN1_item_dup");
SetOCSPRes(self, res_new);
OCSP_RESPONSE_free(res_old);
@@ -550,15 +552,15 @@ ossl_ocspres_initialize(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "01", &arg);
if(!NIL_P(arg)){
- GetOCSPRes(self, res);
- arg = ossl_to_der_if_possible(arg);
- StringValue(arg);
- p = (unsigned char *)RSTRING_PTR(arg);
- res_new = d2i_OCSP_RESPONSE(NULL, &p, RSTRING_LEN(arg));
- if (!res_new)
- ossl_raise(eOCSPError, "d2i_OCSP_RESPONSE");
- SetOCSPRes(self, res_new);
- OCSP_RESPONSE_free(res);
+ GetOCSPRes(self, res);
+ arg = ossl_to_der_if_possible(arg);
+ StringValue(arg);
+ p = (unsigned char *)RSTRING_PTR(arg);
+ res_new = d2i_OCSP_RESPONSE(NULL, &p, RSTRING_LEN(arg));
+ if (!res_new)
+ ossl_raise(eOCSPError, "d2i_OCSP_RESPONSE");
+ SetOCSPRes(self, res_new);
+ OCSP_RESPONSE_free(res);
}
return self;
@@ -619,7 +621,7 @@ ossl_ocspres_get_basic(VALUE self)
GetOCSPRes(self, res);
ret = NewOCSPBasicRes(cOCSPBasicRes);
if(!(bs = OCSP_response_get1_basic(res)))
- return Qnil;
+ return Qnil;
SetOCSPBasicRes(ret, bs);
return ret;
@@ -642,11 +644,11 @@ ossl_ocspres_to_der(VALUE self)
GetOCSPRes(self, res);
if((len = i2d_OCSP_RESPONSE(res, NULL)) <= 0)
- ossl_raise(eOCSPError, NULL);
+ ossl_raise(eOCSPError, NULL);
str = rb_str_new(0, len);
p = (unsigned char *)RSTRING_PTR(str);
if(i2d_OCSP_RESPONSE(res, &p) <= 0)
- ossl_raise(eOCSPError, NULL);
+ ossl_raise(eOCSPError, NULL);
ossl_str_adjust(str, p);
return str;
@@ -663,12 +665,13 @@ ossl_ocspbres_alloc(VALUE klass)
obj = NewOCSPBasicRes(klass);
if(!(bs = OCSP_BASICRESP_new()))
- ossl_raise(eOCSPError, NULL);
+ ossl_raise(eOCSPError, NULL);
SetOCSPBasicRes(obj, bs);
return obj;
}
+/* :nodoc: */
static VALUE
ossl_ocspbres_initialize_copy(VALUE self, VALUE other)
{
@@ -680,7 +683,7 @@ ossl_ocspbres_initialize_copy(VALUE self, VALUE other)
bs_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_BASICRESP), bs);
if (!bs_new)
- ossl_raise(eOCSPError, "ASN1_item_dup");
+ ossl_raise(eOCSPError, "ASN1_item_dup");
SetOCSPBasicRes(self, bs_new);
OCSP_BASICRESP_free(bs_old);
@@ -705,15 +708,15 @@ ossl_ocspbres_initialize(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "01", &arg);
if (!NIL_P(arg)) {
- GetOCSPBasicRes(self, res);
- arg = ossl_to_der_if_possible(arg);
- StringValue(arg);
- p = (unsigned char *)RSTRING_PTR(arg);
- res_new = d2i_OCSP_BASICRESP(NULL, &p, RSTRING_LEN(arg));
- if (!res_new)
- ossl_raise(eOCSPError, "d2i_OCSP_BASICRESP");
- SetOCSPBasicRes(self, res_new);
- OCSP_BASICRESP_free(res);
+ GetOCSPBasicRes(self, res);
+ arg = ossl_to_der_if_possible(arg);
+ StringValue(arg);
+ p = (unsigned char *)RSTRING_PTR(arg);
+ res_new = d2i_OCSP_BASICRESP(NULL, &p, RSTRING_LEN(arg));
+ if (!res_new)
+ ossl_raise(eOCSPError, "d2i_OCSP_BASICRESP");
+ SetOCSPBasicRes(self, res_new);
+ OCSP_BASICRESP_free(res);
}
return self;
@@ -758,13 +761,13 @@ ossl_ocspbres_add_nonce(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "01", &val);
if(NIL_P(val)) {
- GetOCSPBasicRes(self, bs);
- ret = OCSP_basic_add1_nonce(bs, NULL, -1);
+ GetOCSPBasicRes(self, bs);
+ ret = OCSP_basic_add1_nonce(bs, NULL, -1);
}
else{
- StringValue(val);
- GetOCSPBasicRes(self, bs);
- ret = OCSP_basic_add1_nonce(bs, (unsigned char *)RSTRING_PTR(val), RSTRING_LENINT(val));
+ StringValue(val);
+ GetOCSPBasicRes(self, bs);
+ ret = OCSP_basic_add1_nonce(bs, (unsigned char *)RSTRING_PTR(val), RSTRING_LENINT(val));
}
if(!ret) ossl_raise(eOCSPError, NULL);
@@ -777,12 +780,12 @@ add_status_convert_time(VALUE obj)
ASN1_TIME *time;
if (RB_INTEGER_TYPE_P(obj))
- time = X509_gmtime_adj(NULL, NUM2INT(obj));
+ time = X509_gmtime_adj(NULL, NUM2INT(obj));
else
- time = ossl_x509_time_adjust(NULL, obj);
+ time = ossl_x509_time_adjust(NULL, obj);
if (!time)
- ossl_raise(eOCSPError, NULL);
+ ossl_raise(eOCSPError, NULL);
return (VALUE)time;
}
@@ -816,8 +819,8 @@ add_status_convert_time(VALUE obj)
*/
static VALUE
ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status,
- VALUE reason, VALUE revtime,
- VALUE thisupd, VALUE nextupd, VALUE ext)
+ VALUE reason, VALUE revtime,
+ VALUE thisupd, VALUE nextupd, VALUE ext)
{
OCSP_BASICRESP *bs;
OCSP_SINGLERESP *single;
@@ -831,16 +834,16 @@ ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status,
GetOCSPCertId(cid, id);
st = NUM2INT(status);
if (!NIL_P(ext)) { /* All ext's members must be X509::Extension */
- ext = rb_check_array_type(ext);
- for (i = 0; i < RARRAY_LEN(ext); i++)
- OSSL_Check_Kind(RARRAY_AREF(ext, i), cX509Ext);
+ ext = rb_check_array_type(ext);
+ for (i = 0; i < RARRAY_LEN(ext); i++)
+ OSSL_Check_Kind(RARRAY_AREF(ext, i), cX509Ext);
}
if (st == V_OCSP_CERTSTATUS_REVOKED) {
- rsn = NUM2INT(reason);
- tmp = rb_protect(add_status_convert_time, revtime, &rstatus);
- if (rstatus) goto err;
- rev = (ASN1_TIME *)tmp;
+ rsn = NUM2INT(reason);
+ tmp = rb_protect(add_status_convert_time, revtime, &rstatus);
+ if (rstatus) goto err;
+ rev = (ASN1_TIME *)tmp;
}
tmp = rb_protect(add_status_convert_time, thisupd, &rstatus);
@@ -848,29 +851,29 @@ ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status,
ths = (ASN1_TIME *)tmp;
if (!NIL_P(nextupd)) {
- tmp = rb_protect(add_status_convert_time, nextupd, &rstatus);
- if (rstatus) goto err;
- nxt = (ASN1_TIME *)tmp;
+ tmp = rb_protect(add_status_convert_time, nextupd, &rstatus);
+ if (rstatus) goto err;
+ nxt = (ASN1_TIME *)tmp;
}
if(!(single = OCSP_basic_add1_status(bs, id, st, rsn, rev, ths, nxt))){
- error = 1;
- goto err;
+ error = 1;
+ goto err;
}
if(!NIL_P(ext)){
- X509_EXTENSION *x509ext;
-
- for(i = 0; i < RARRAY_LEN(ext); i++){
- x509ext = GetX509ExtPtr(RARRAY_AREF(ext, i));
- if(!OCSP_SINGLERESP_add_ext(single, x509ext, -1)){
- error = 1;
- goto err;
- }
- }
+ X509_EXTENSION *x509ext;
+
+ for(i = 0; i < RARRAY_LEN(ext); i++){
+ x509ext = GetX509ExtPtr(RARRAY_AREF(ext, i));
+ if(!OCSP_SINGLERESP_add_ext(single, x509ext, -1)){
+ error = 1;
+ goto err;
+ }
+ }
}
- err:
+ err:
ASN1_TIME_free(ths);
ASN1_TIME_free(nxt);
ASN1_TIME_free(rev);
@@ -896,48 +899,40 @@ static VALUE
ossl_ocspbres_get_status(VALUE self)
{
OCSP_BASICRESP *bs;
- OCSP_SINGLERESP *single;
- OCSP_CERTID *cid;
- ASN1_TIME *revtime, *thisupd, *nextupd;
- int status, reason;
- X509_EXTENSION *x509ext;
- VALUE ret, ary, ext;
- int count, ext_count, i, j;
GetOCSPBasicRes(self, bs);
- ret = rb_ary_new();
- count = OCSP_resp_count(bs);
- for(i = 0; i < count; i++){
- single = OCSP_resp_get0(bs, i);
- if(!single) continue;
-
- revtime = thisupd = nextupd = NULL;
- status = OCSP_single_get0_status(single, &reason, &revtime,
- &thisupd, &nextupd);
- if(status < 0) continue;
- if(!(cid = OCSP_CERTID_dup((OCSP_CERTID *)OCSP_SINGLERESP_get0_id(single)))) /* FIXME */
- ossl_raise(eOCSPError, NULL);
- ary = rb_ary_new();
- rb_ary_push(ary, ossl_ocspcertid_new(cid));
- rb_ary_push(ary, INT2NUM(status));
- rb_ary_push(ary, INT2NUM(reason));
- rb_ary_push(ary, revtime ? asn1time_to_time(revtime) : Qnil);
- rb_ary_push(ary, thisupd ? asn1time_to_time(thisupd) : Qnil);
- rb_ary_push(ary, nextupd ? asn1time_to_time(nextupd) : Qnil);
- ext = rb_ary_new();
- ext_count = OCSP_SINGLERESP_get_ext_count(single);
- for(j = 0; j < ext_count; j++){
- x509ext = OCSP_SINGLERESP_get_ext(single, j);
- rb_ary_push(ext, ossl_x509ext_new(x509ext));
- }
- rb_ary_push(ary, ext);
- rb_ary_push(ret, ary);
+ VALUE ret = rb_ary_new();
+ int count = OCSP_resp_count(bs);
+ for (int i = 0; i < count; i++) {
+ OCSP_SINGLERESP *single = OCSP_resp_get0(bs, i);
+ ASN1_TIME *revtime, *thisupd, *nextupd;
+ int reason;
+
+ int status = OCSP_single_get0_status(single, &reason, &revtime, &thisupd, &nextupd);
+ if (status < 0)
+ ossl_raise(eOCSPError, "OCSP_single_get0_status");
+
+ VALUE ary = rb_ary_new();
+ rb_ary_push(ary, ossl_ocspcid_new(OCSP_SINGLERESP_get0_id(single)));
+ rb_ary_push(ary, INT2NUM(status));
+ rb_ary_push(ary, INT2NUM(reason));
+ rb_ary_push(ary, revtime ? asn1time_to_time(revtime) : Qnil);
+ rb_ary_push(ary, thisupd ? asn1time_to_time(thisupd) : Qnil);
+ rb_ary_push(ary, nextupd ? asn1time_to_time(nextupd) : Qnil);
+ VALUE ext = rb_ary_new();
+ int ext_count = OCSP_SINGLERESP_get_ext_count(single);
+ for (int j = 0; j < ext_count; j++) {
+ X509_EXTENSION *x509ext = OCSP_SINGLERESP_get_ext(single, j);
+ rb_ary_push(ext, ossl_x509ext_new(x509ext));
+ }
+ rb_ary_push(ary, ext);
+ rb_ary_push(ret, ary);
}
return ret;
}
-static VALUE ossl_ocspsres_new(OCSP_SINGLERESP *);
+static VALUE ossl_ocspsres_new(const OCSP_SINGLERESP *);
/*
* call-seq:
@@ -955,17 +950,10 @@ ossl_ocspbres_get_responses(VALUE self)
GetOCSPBasicRes(self, bs);
count = OCSP_resp_count(bs);
- ret = rb_ary_new2(count);
+ ret = rb_ary_new_capa(count);
for (i = 0; i < count; i++) {
- OCSP_SINGLERESP *sres, *sres_new;
-
- sres = OCSP_resp_get0(bs, i);
- sres_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_SINGLERESP), sres);
- if (!sres_new)
- ossl_raise(eOCSPError, "ASN1_item_dup");
-
- rb_ary_push(ret, ossl_ocspsres_new(sres_new));
+ rb_ary_push(ret, ossl_ocspsres_new(OCSP_resp_get0(bs, i)));
}
return ret;
@@ -983,7 +971,6 @@ static VALUE
ossl_ocspbres_find_response(VALUE self, VALUE target)
{
OCSP_BASICRESP *bs;
- OCSP_SINGLERESP *sres, *sres_new;
OCSP_CERTID *id;
int n;
@@ -991,14 +978,8 @@ ossl_ocspbres_find_response(VALUE self, VALUE target)
GetOCSPBasicRes(self, bs);
if ((n = OCSP_resp_find(bs, id, -1)) == -1)
- return Qnil;
-
- sres = OCSP_resp_get0(bs, n);
- sres_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_SINGLERESP), sres);
- if (!sres_new)
- ossl_raise(eOCSPError, "ASN1_item_dup");
-
- return ossl_ocspsres_new(sres_new);
+ return Qnil;
+ return ossl_ocspsres_new(OCSP_resp_get0(bs, n));
}
/*
@@ -1017,7 +998,7 @@ ossl_ocspbres_find_response(VALUE self, VALUE target)
static VALUE
ossl_ocspbres_sign(int argc, VALUE *argv, VALUE self)
{
- VALUE signer_cert, signer_key, certs, flags, digest;
+ VALUE signer_cert, signer_key, certs, flags, digest, md_holder;
OCSP_BASICRESP *bs;
X509 *signer;
EVP_PKEY *key;
@@ -1031,19 +1012,17 @@ ossl_ocspbres_sign(int argc, VALUE *argv, VALUE self)
signer = GetX509CertPtr(signer_cert);
key = GetPrivPKeyPtr(signer_key);
if (!NIL_P(flags))
- flg = NUM2INT(flags);
- if (NIL_P(digest))
- md = NULL;
- else
- md = ossl_evp_get_digestbyname(digest);
+ flg = NUM2INT(flags);
+ md = NIL_P(digest) ? NULL : ossl_evp_md_fetch(digest, &md_holder);
if (NIL_P(certs))
- flg |= OCSP_NOCERTS;
+ flg |= OCSP_NOCERTS;
else
- x509s = ossl_x509_ary2sk(certs);
+ x509s = ossl_x509_ary2sk(certs);
ret = OCSP_basic_sign(bs, signer, key, md, x509s, flg);
sk_X509_pop_free(x509s, X509_free);
- if (!ret) ossl_raise(eOCSPError, NULL);
+ if (!ret)
+ ossl_raise(eOCSPError, "OCSP_basic_sign");
return self;
}
@@ -1072,7 +1051,7 @@ ossl_ocspbres_verify(int argc, VALUE *argv, VALUE self)
result = OCSP_basic_verify(bs, x509s, x509st, flg);
sk_X509_pop_free(x509s, X509_free);
if (result <= 0)
- ossl_clear_error();
+ ossl_clear_error();
return result > 0 ? Qtrue : Qfalse;
}
@@ -1093,11 +1072,11 @@ ossl_ocspbres_to_der(VALUE self)
GetOCSPBasicRes(self, res);
if ((len = i2d_OCSP_BASICRESP(res, NULL)) <= 0)
- ossl_raise(eOCSPError, NULL);
+ ossl_raise(eOCSPError, NULL);
str = rb_str_new(0, len);
p = (unsigned char *)RSTRING_PTR(str);
if (i2d_OCSP_BASICRESP(res, &p) <= 0)
- ossl_raise(eOCSPError, NULL);
+ ossl_raise(eOCSPError, NULL);
ossl_str_adjust(str, p);
return str;
@@ -1107,12 +1086,18 @@ ossl_ocspbres_to_der(VALUE self)
* OCSP::SingleResponse
*/
static VALUE
-ossl_ocspsres_new(OCSP_SINGLERESP *sres)
+ossl_ocspsres_new(const OCSP_SINGLERESP *sres)
{
VALUE obj;
+ OCSP_SINGLERESP *sres_new;
obj = NewOCSPSingleRes(cOCSPSingleRes);
- SetOCSPSingleRes(obj, sres);
+ /* OpenSSL 1.1.1 takes a non-const pointer */
+ sres_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_SINGLERESP),
+ (OCSP_SINGLERESP *)sres);
+ if (!sres_new)
+ ossl_raise(eOCSPError, "ASN1_item_dup");
+ SetOCSPSingleRes(obj, sres_new);
return obj;
}
@@ -1125,7 +1110,7 @@ ossl_ocspsres_alloc(VALUE klass)
obj = NewOCSPSingleRes(klass);
if (!(sres = OCSP_SINGLERESP_new()))
- ossl_raise(eOCSPError, NULL);
+ ossl_raise(eOCSPError, NULL);
SetOCSPSingleRes(obj, sres);
return obj;
@@ -1150,13 +1135,14 @@ ossl_ocspsres_initialize(VALUE self, VALUE arg)
p = (unsigned char*)RSTRING_PTR(arg);
res_new = d2i_OCSP_SINGLERESP(NULL, &p, RSTRING_LEN(arg));
if (!res_new)
- ossl_raise(eOCSPError, "d2i_OCSP_SINGLERESP");
+ ossl_raise(eOCSPError, "d2i_OCSP_SINGLERESP");
SetOCSPSingleRes(self, res_new);
OCSP_SINGLERESP_free(res);
return self;
}
+/* :nodoc: */
static VALUE
ossl_ocspsres_initialize_copy(VALUE self, VALUE other)
{
@@ -1168,7 +1154,7 @@ ossl_ocspsres_initialize_copy(VALUE self, VALUE other)
sres_new = ASN1_item_dup(ASN1_ITEM_rptr(OCSP_SINGLERESP), sres);
if (!sres_new)
- ossl_raise(eOCSPError, "ASN1_item_dup");
+ ossl_raise(eOCSPError, "ASN1_item_dup");
SetOCSPSingleRes(self, sres_new);
OCSP_SINGLERESP_free(sres_old);
@@ -1207,15 +1193,15 @@ ossl_ocspsres_check_validity(int argc, VALUE *argv, VALUE self)
GetOCSPSingleRes(self, sres);
status = OCSP_single_get0_status(sres, NULL, NULL, &this_update, &next_update);
if (status < 0)
- ossl_raise(eOCSPError, "OCSP_single_get0_status");
+ ossl_raise(eOCSPError, "OCSP_single_get0_status");
ret = OCSP_check_validity(this_update, next_update, nsec, maxsec);
if (ret)
- return Qtrue;
+ return Qtrue;
else {
- ossl_clear_error();
- return Qfalse;
+ ossl_clear_error();
+ return Qfalse;
}
}
@@ -1229,12 +1215,9 @@ static VALUE
ossl_ocspsres_get_certid(VALUE self)
{
OCSP_SINGLERESP *sres;
- OCSP_CERTID *id;
GetOCSPSingleRes(self, sres);
- id = OCSP_CERTID_dup((OCSP_CERTID *)OCSP_SINGLERESP_get0_id(sres)); /* FIXME */
-
- return ossl_ocspcertid_new(id);
+ return ossl_ocspcid_new(OCSP_SINGLERESP_get0_id(sres));
}
/*
@@ -1260,7 +1243,7 @@ ossl_ocspsres_get_cert_status(VALUE self)
GetOCSPSingleRes(self, sres);
status = OCSP_single_get0_status(sres, NULL, NULL, NULL, NULL);
if (status < 0)
- ossl_raise(eOCSPError, "OCSP_single_get0_status");
+ ossl_raise(eOCSPError, "OCSP_single_get0_status");
return INT2NUM(status);
}
@@ -1279,9 +1262,9 @@ ossl_ocspsres_get_this_update(VALUE self)
GetOCSPSingleRes(self, sres);
status = OCSP_single_get0_status(sres, NULL, NULL, &time, NULL);
if (status < 0)
- ossl_raise(eOCSPError, "OCSP_single_get0_status");
+ ossl_raise(eOCSPError, "OCSP_single_get0_status");
if (!time)
- return Qnil;
+ return Qnil;
return asn1time_to_time(time);
}
@@ -1300,9 +1283,9 @@ ossl_ocspsres_get_next_update(VALUE self)
GetOCSPSingleRes(self, sres);
status = OCSP_single_get0_status(sres, NULL, NULL, NULL, &time);
if (status < 0)
- ossl_raise(eOCSPError, "OCSP_single_get0_status");
+ ossl_raise(eOCSPError, "OCSP_single_get0_status");
if (!time)
- return Qnil;
+ return Qnil;
return asn1time_to_time(time);
}
@@ -1321,11 +1304,11 @@ ossl_ocspsres_get_revocation_time(VALUE self)
GetOCSPSingleRes(self, sres);
status = OCSP_single_get0_status(sres, NULL, &time, NULL, NULL);
if (status < 0)
- ossl_raise(eOCSPError, "OCSP_single_get0_status");
+ ossl_raise(eOCSPError, "OCSP_single_get0_status");
if (status != V_OCSP_CERTSTATUS_REVOKED)
- ossl_raise(eOCSPError, "certificate is not revoked");
+ ossl_raise(eOCSPError, "certificate is not revoked");
if (!time)
- return Qnil;
+ return Qnil;
return asn1time_to_time(time);
}
@@ -1343,9 +1326,9 @@ ossl_ocspsres_get_revocation_reason(VALUE self)
GetOCSPSingleRes(self, sres);
status = OCSP_single_get0_status(sres, &reason, NULL, NULL, NULL);
if (status < 0)
- ossl_raise(eOCSPError, "OCSP_single_get0_status");
+ ossl_raise(eOCSPError, "OCSP_single_get0_status");
if (status != V_OCSP_CERTSTATUS_REVOKED)
- ossl_raise(eOCSPError, "certificate is not revoked");
+ ossl_raise(eOCSPError, "certificate is not revoked");
return INT2NUM(reason);
}
@@ -1367,8 +1350,8 @@ ossl_ocspsres_get_extensions(VALUE self)
count = OCSP_SINGLERESP_get_ext_count(sres);
ary = rb_ary_new2(count);
for (i = 0; i < count; i++) {
- ext = OCSP_SINGLERESP_get_ext(sres, i);
- rb_ary_push(ary, ossl_x509ext_new(ext)); /* will dup */
+ ext = OCSP_SINGLERESP_get_ext(sres, i);
+ rb_ary_push(ary, ossl_x509ext_new(ext)); /* will dup */
}
return ary;
@@ -1390,11 +1373,11 @@ ossl_ocspsres_to_der(VALUE self)
GetOCSPSingleRes(self, sres);
if ((len = i2d_OCSP_SINGLERESP(sres, NULL)) <= 0)
- ossl_raise(eOCSPError, NULL);
+ ossl_raise(eOCSPError, NULL);
str = rb_str_new(0, len);
p = (unsigned char *)RSTRING_PTR(str);
if (i2d_OCSP_SINGLERESP(sres, &p) <= 0)
- ossl_raise(eOCSPError, NULL);
+ ossl_raise(eOCSPError, NULL);
ossl_str_adjust(str, p);
return str;
@@ -1412,12 +1395,13 @@ ossl_ocspcid_alloc(VALUE klass)
obj = NewOCSPCertId(klass);
if(!(id = OCSP_CERTID_new()))
- ossl_raise(eOCSPError, NULL);
+ ossl_raise(eOCSPError, NULL);
SetOCSPCertId(obj, id);
return obj;
}
+/* :nodoc: */
static VALUE
ossl_ocspcid_initialize_copy(VALUE self, VALUE other)
{
@@ -1429,7 +1413,7 @@ ossl_ocspcid_initialize_copy(VALUE self, VALUE other)
cid_new = OCSP_CERTID_dup(cid);
if (!cid_new)
- ossl_raise(eOCSPError, "OCSP_CERTID_dup");
+ ossl_raise(eOCSPError, "OCSP_CERTID_dup");
SetOCSPCertId(self, cid_new);
OCSP_CERTID_free(cid_old);
@@ -1459,27 +1443,28 @@ ossl_ocspcid_initialize(int argc, VALUE *argv, VALUE self)
GetOCSPCertId(self, id);
if (rb_scan_args(argc, argv, "12", &subject, &issuer, &digest) == 1) {
- VALUE arg;
- const unsigned char *p;
-
- arg = ossl_to_der_if_possible(subject);
- StringValue(arg);
- p = (unsigned char *)RSTRING_PTR(arg);
- newid = d2i_OCSP_CERTID(NULL, &p, RSTRING_LEN(arg));
- if (!newid)
- ossl_raise(eOCSPError, "d2i_OCSP_CERTID");
+ VALUE arg;
+ const unsigned char *p;
+
+ arg = ossl_to_der_if_possible(subject);
+ StringValue(arg);
+ p = (unsigned char *)RSTRING_PTR(arg);
+ newid = d2i_OCSP_CERTID(NULL, &p, RSTRING_LEN(arg));
+ if (!newid)
+ ossl_raise(eOCSPError, "d2i_OCSP_CERTID");
}
else {
- X509 *x509s, *x509i;
- const EVP_MD *md;
+ X509 *x509s, *x509i;
+ const EVP_MD *md;
+ VALUE md_holder;
- x509s = GetX509CertPtr(subject); /* NO NEED TO DUP */
- x509i = GetX509CertPtr(issuer); /* NO NEED TO DUP */
- md = !NIL_P(digest) ? ossl_evp_get_digestbyname(digest) : NULL;
+ x509s = GetX509CertPtr(subject); /* NO NEED TO DUP */
+ x509i = GetX509CertPtr(issuer); /* NO NEED TO DUP */
+ md = NIL_P(digest) ? NULL : ossl_evp_md_fetch(digest, &md_holder);
- newid = OCSP_cert_to_id(md, x509s, x509i);
- if (!newid)
- ossl_raise(eOCSPError, "OCSP_cert_to_id");
+ newid = OCSP_cert_to_id(md, x509s, x509i);
+ if (!newid)
+ ossl_raise(eOCSPError, "OCSP_cert_to_id");
}
SetOCSPCertId(self, newid);
@@ -1565,8 +1550,9 @@ ossl_ocspcid_get_issuer_name_hash(VALUE self)
GetOCSPCertId(self, id);
OCSP_id_get0_info(&name_hash, NULL, NULL, NULL, id);
- ret = rb_str_new(NULL, name_hash->length * 2);
- ossl_bin2hex(name_hash->data, RSTRING_PTR(ret), name_hash->length);
+ ret = rb_str_new(NULL, ASN1_STRING_length(name_hash) * 2);
+ ossl_bin2hex(ASN1_STRING_get0_data(name_hash), RSTRING_PTR(ret),
+ ASN1_STRING_length(name_hash));
return ret;
}
@@ -1588,8 +1574,9 @@ ossl_ocspcid_get_issuer_key_hash(VALUE self)
GetOCSPCertId(self, id);
OCSP_id_get0_info(NULL, NULL, &key_hash, NULL, id);
- ret = rb_str_new(NULL, key_hash->length * 2);
- ossl_bin2hex(key_hash->data, RSTRING_PTR(ret), key_hash->length);
+ ret = rb_str_new(NULL, ASN1_STRING_length(key_hash) * 2);
+ ossl_bin2hex(ASN1_STRING_get0_data(key_hash), RSTRING_PTR(ret),
+ ASN1_STRING_length(key_hash));
return ret;
}
@@ -1606,19 +1593,10 @@ ossl_ocspcid_get_hash_algorithm(VALUE self)
{
OCSP_CERTID *id;
ASN1_OBJECT *oid;
- BIO *out;
GetOCSPCertId(self, id);
OCSP_id_get0_info(NULL, &oid, NULL, NULL, id);
-
- if (!(out = BIO_new(BIO_s_mem())))
- ossl_raise(eOCSPError, "BIO_new");
-
- if (!i2a_ASN1_OBJECT(out, oid)) {
- BIO_free(out);
- ossl_raise(eOCSPError, "i2a_ASN1_OBJECT");
- }
- return ossl_membio2str(out);
+ return ossl_asn1obj_to_string_long_name(oid);
}
/*
@@ -1637,11 +1615,11 @@ ossl_ocspcid_to_der(VALUE self)
GetOCSPCertId(self, id);
if ((len = i2d_OCSP_CERTID(id, NULL)) <= 0)
- ossl_raise(eOCSPError, NULL);
+ ossl_raise(eOCSPError, NULL);
str = rb_str_new(0, len);
p = (unsigned char *)RSTRING_PTR(str);
if (i2d_OCSP_CERTID(id, &p) <= 0)
- ossl_raise(eOCSPError, NULL);
+ ossl_raise(eOCSPError, NULL);
ossl_str_adjust(str, p);
return str;
@@ -1650,11 +1628,6 @@ ossl_ocspcid_to_der(VALUE self)
void
Init_ossl_ocsp(void)
{
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
-#endif
-
/*
* OpenSSL::OCSP implements Online Certificate Status Protocol requests
* and responses.
diff --git a/ext/openssl/ossl_ocsp.h b/ext/openssl/ossl_ocsp.h
index 6d2aac8657..becd70ffed 100644
--- a/ext/openssl/ossl_ocsp.h
+++ b/ext/openssl/ossl_ocsp.h
@@ -6,18 +6,11 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_OCSP_H_)
#define _OSSL_OCSP_H_
-#if !defined(OPENSSL_NO_OCSP)
-extern VALUE mOCSP;
-extern VALUE cOCSPReq;
-extern VALUE cOCSPRes;
-extern VALUE cOCSPBasicRes;
-#endif
-
void Init_ossl_ocsp(void);
#endif /* _OSSL_OCSP_H_ */
diff --git a/ext/openssl/ossl_pkcs12.c b/ext/openssl/ossl_pkcs12.c
index 164b2da465..32b82a881c 100644
--- a/ext/openssl/ossl_pkcs12.c
+++ b/ext/openssl/ossl_pkcs12.c
@@ -1,6 +1,6 @@
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -27,8 +27,8 @@
/*
* Classes
*/
-VALUE cPKCS12;
-VALUE ePKCS12Error;
+static VALUE cPKCS12;
+static VALUE ePKCS12Error;
/*
* Private
@@ -42,7 +42,7 @@ ossl_pkcs12_free(void *ptr)
static const rb_data_type_t ossl_pkcs12_type = {
"OpenSSL/PKCS12",
{
- 0, ossl_pkcs12_free,
+ 0, ossl_pkcs12_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
@@ -60,6 +60,7 @@ ossl_pkcs12_s_allocate(VALUE klass)
return obj;
}
+/* :nodoc: */
static VALUE
ossl_pkcs12_initialize_copy(VALUE self, VALUE other)
{
@@ -71,7 +72,7 @@ ossl_pkcs12_initialize_copy(VALUE self, VALUE other)
p12_new = ASN1_dup((i2d_of_void *)i2d_PKCS12, (d2i_of_void *)d2i_PKCS12, (char *)p12);
if (!p12_new)
- ossl_raise(ePKCS12Error, "ASN1_dup");
+ ossl_raise(ePKCS12Error, "ASN1_dup");
SetPKCS12(self, p12_new);
PKCS12_free(p12_old);
@@ -121,11 +122,11 @@ ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self)
/* TODO: make a VALUE to nid function */
if (!NIL_P(key_nid)) {
if ((nkey = OBJ_txt2nid(StringValueCStr(key_nid))) == NID_undef)
- ossl_raise(rb_eArgError, "Unknown PBE algorithm %"PRIsVALUE, key_nid);
+ ossl_raise(rb_eArgError, "Unknown PBE algorithm %"PRIsVALUE, key_nid);
}
if (!NIL_P(cert_nid)) {
if ((ncert = OBJ_txt2nid(StringValueCStr(cert_nid))) == NID_undef)
- ossl_raise(rb_eArgError, "Unknown PBE algorithm %"PRIsVALUE, cert_nid);
+ ossl_raise(rb_eArgError, "Unknown PBE algorithm %"PRIsVALUE, cert_nid);
}
if (!NIL_P(key_iter))
kiter = NUM2INT(key_iter);
@@ -134,6 +135,16 @@ ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self)
if (!NIL_P(keytype))
ktype = NUM2INT(keytype);
+#if defined(OPENSSL_IS_AWSLC)
+ if (ktype != 0) {
+ ossl_raise(rb_eArgError, "Unknown key usage type %"PRIsVALUE, INT2NUM(ktype));
+ }
+#else
+ if (ktype != 0 && ktype != KEY_SIG && ktype != KEY_EX) {
+ ossl_raise(rb_eArgError, "Unknown key usage type %"PRIsVALUE, INT2NUM(ktype));
+ }
+#endif
+
obj = NewPKCS12(cPKCS12);
x509s = NIL_P(ca) ? NULL : ossl_x509_ary2sk(ca);
p12 = PKCS12_create(passphrase, friendlyname, key, x509, x509s,
@@ -150,9 +161,9 @@ ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self)
}
static VALUE
-ossl_pkey_new_i(VALUE arg)
+ossl_pkey_wrap_i(VALUE arg)
{
- return ossl_pkey_new((EVP_PKEY *)arg);
+ return ossl_pkey_wrap((EVP_PKEY *)arg);
}
static VALUE
@@ -197,23 +208,19 @@ ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self)
BIO_free(in);
pkey = cert = ca = Qnil;
- /* OpenSSL's bug; PKCS12_parse() puts errors even if it succeeds.
- * Fixed in OpenSSL 1.0.0t, 1.0.1p, 1.0.2d */
- ERR_set_mark();
if(!PKCS12_parse(pkcs, passphrase, &key, &x509, &x509s))
- ossl_raise(ePKCS12Error, "PKCS12_parse");
- ERR_pop_to_mark();
+ ossl_raise(ePKCS12Error, "PKCS12_parse");
if (key) {
- pkey = rb_protect(ossl_pkey_new_i, (VALUE)key, &st);
- if (st) goto err;
+ pkey = rb_protect(ossl_pkey_wrap_i, (VALUE)key, &st);
+ if (st) goto err;
}
if (x509) {
- cert = rb_protect(ossl_x509_new_i, (VALUE)x509, &st);
- if (st) goto err;
+ cert = rb_protect(ossl_x509_new_i, (VALUE)x509, &st);
+ if (st) goto err;
}
if (x509s) {
- ca = rb_protect(ossl_x509_sk2ary_i, (VALUE)x509s, &st);
- if (st) goto err;
+ ca = rb_protect(ossl_x509_sk2ary_i, (VALUE)x509s, &st);
+ if (st) goto err;
}
err:
@@ -237,25 +244,62 @@ ossl_pkcs12_to_der(VALUE self)
GetPKCS12(self, p12);
if((len = i2d_PKCS12(p12, NULL)) <= 0)
- ossl_raise(ePKCS12Error, NULL);
+ ossl_raise(ePKCS12Error, NULL);
str = rb_str_new(0, len);
p = (unsigned char *)RSTRING_PTR(str);
if(i2d_PKCS12(p12, &p) <= 0)
- ossl_raise(ePKCS12Error, NULL);
+ ossl_raise(ePKCS12Error, NULL);
ossl_str_adjust(str, p);
return str;
}
+/*
+ * call-seq:
+ * pkcs12.set_mac(pass, salt = nil, iter = nil, md_type = nil)
+ *
+ * Sets MAC parameters and generates MAC over the PKCS #12 structure.
+ *
+ * This method uses HMAC and the PKCS #12 specific password-based KDF as
+ * specified in the original PKCS #12.
+ *
+ * See also the man page PKCS12_set_mac(3).
+ *
+ * Added in version 3.3.0.
+ */
+static VALUE
+pkcs12_set_mac(int argc, VALUE *argv, VALUE self)
+{
+ PKCS12 *p12;
+ VALUE pass, salt, iter, md_name, md_holder = Qnil;
+ int iter_i = 0;
+ const EVP_MD *md_type = NULL;
+
+ rb_scan_args(argc, argv, "13", &pass, &salt, &iter, &md_name);
+ rb_check_frozen(self);
+ GetPKCS12(self, p12);
+
+ StringValue(pass);
+ if (!NIL_P(salt))
+ StringValue(salt);
+ if (!NIL_P(iter))
+ iter_i = NUM2INT(iter);
+ if (!NIL_P(md_name))
+ md_type = ossl_evp_md_fetch(md_name, &md_holder);
+
+ if (!PKCS12_set_mac(p12, RSTRING_PTR(pass), RSTRING_LENINT(pass),
+ !NIL_P(salt) ? (unsigned char *)RSTRING_PTR(salt) : NULL,
+ !NIL_P(salt) ? RSTRING_LENINT(salt) : 0,
+ iter_i, md_type))
+ ossl_raise(ePKCS12Error, "PKCS12_set_mac");
+
+ return Qnil;
+}
+
void
Init_ossl_pkcs12(void)
{
#undef rb_intern
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
-#endif
-
/*
* Defines a file format commonly used to store private keys with
* accompanying public key certificates, protected with a password-based
@@ -272,4 +316,11 @@ Init_ossl_pkcs12(void)
rb_attr(cPKCS12, rb_intern("ca_certs"), 1, 0, Qfalse);
rb_define_method(cPKCS12, "initialize", ossl_pkcs12_initialize, -1);
rb_define_method(cPKCS12, "to_der", ossl_pkcs12_to_der, 0);
+ rb_define_method(cPKCS12, "set_mac", pkcs12_set_mac, -1);
+
+#if !defined(OPENSSL_IS_AWSLC)
+ /* MSIE specific PKCS12 key usage extensions */
+ rb_define_const(cPKCS12, "KEY_EX", INT2NUM(KEY_EX));
+ rb_define_const(cPKCS12, "KEY_SIG", INT2NUM(KEY_SIG));
+#endif
}
diff --git a/ext/openssl/ossl_pkcs12.h b/ext/openssl/ossl_pkcs12.h
index fe4f15ef60..6d2cd901cb 100644
--- a/ext/openssl/ossl_pkcs12.h
+++ b/ext/openssl/ossl_pkcs12.h
@@ -1,13 +1,10 @@
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_PKCS12_H_)
#define _OSSL_PKCS12_H_
-extern VALUE cPKCS12;
-extern VALUE ePKCS12Error;
-
void Init_ossl_pkcs12(void);
#endif /* _OSSL_PKCS12_H_ */
diff --git a/ext/openssl/ossl_pkcs7.c b/ext/openssl/ossl_pkcs7.c
index 446df4c075..6e51fd42b9 100644
--- a/ext/openssl/ossl_pkcs7.c
+++ b/ext/openssl/ossl_pkcs7.c
@@ -5,22 +5,37 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
+#define NewPKCS7(klass) \
+ TypedData_Wrap_Struct((klass), &ossl_pkcs7_type, 0)
+#define SetPKCS7(obj, pkcs7) do { \
+ if (!(pkcs7)) { \
+ ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \
+ } \
+ RTYPEDDATA_DATA(obj) = (pkcs7); \
+} while (0)
+#define GetPKCS7(obj, pkcs7) do { \
+ TypedData_Get_Struct((obj), PKCS7, &ossl_pkcs7_type, (pkcs7)); \
+ if (!(pkcs7)) { \
+ ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \
+ } \
+} while (0)
+
#define NewPKCS7si(klass) \
TypedData_Wrap_Struct((klass), &ossl_pkcs7_signer_info_type, 0)
#define SetPKCS7si(obj, p7si) do { \
if (!(p7si)) { \
- ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \
+ ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \
} \
RTYPEDDATA_DATA(obj) = (p7si); \
} while (0)
#define GetPKCS7si(obj, p7si) do { \
TypedData_Get_Struct((obj), PKCS7_SIGNER_INFO, &ossl_pkcs7_signer_info_type, (p7si)); \
if (!(p7si)) { \
- ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \
+ ossl_raise(rb_eRuntimeError, "PKCS7si wasn't initialized."); \
} \
} while (0)
@@ -28,14 +43,14 @@
TypedData_Wrap_Struct((klass), &ossl_pkcs7_recip_info_type, 0)
#define SetPKCS7ri(obj, p7ri) do { \
if (!(p7ri)) { \
- ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \
+ ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \
} \
RTYPEDDATA_DATA(obj) = (p7ri); \
} while (0)
#define GetPKCS7ri(obj, p7ri) do { \
TypedData_Get_Struct((obj), PKCS7_RECIP_INFO, &ossl_pkcs7_recip_info_type, (p7ri)); \
if (!(p7ri)) { \
- ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \
+ ossl_raise(rb_eRuntimeError, "PKCS7ri wasn't initialized."); \
} \
} while (0)
@@ -49,10 +64,11 @@
/*
* Classes
*/
-VALUE cPKCS7;
-VALUE cPKCS7Signer;
-VALUE cPKCS7Recipient;
-VALUE ePKCS7Error;
+static VALUE cPKCS7;
+static VALUE cPKCS7Signer;
+static VALUE cPKCS7Recipient;
+static VALUE ePKCS7Error;
+static ID id_md_holder, id_cipher_holder;
static void
ossl_pkcs7_free(void *ptr)
@@ -60,14 +76,28 @@ ossl_pkcs7_free(void *ptr)
PKCS7_free(ptr);
}
-const rb_data_type_t ossl_pkcs7_type = {
+static const rb_data_type_t ossl_pkcs7_type = {
"OpenSSL/PKCS7",
{
- 0, ossl_pkcs7_free,
+ 0, ossl_pkcs7_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
+VALUE
+ossl_pkcs7_new(PKCS7 *p7)
+{
+ PKCS7 *new;
+ VALUE obj = NewPKCS7(cPKCS7);
+
+ new = PKCS7_dup(p7);
+ if (!new)
+ ossl_raise(ePKCS7Error, "PKCS7_dup");
+ SetPKCS7(obj, new);
+
+ return obj;
+}
+
static void
ossl_pkcs7_signer_info_free(void *ptr)
{
@@ -77,7 +107,7 @@ ossl_pkcs7_signer_info_free(void *ptr)
static const rb_data_type_t ossl_pkcs7_signer_info_type = {
"OpenSSL/PKCS7/SIGNER_INFO",
{
- 0, ossl_pkcs7_signer_info_free,
+ 0, ossl_pkcs7_signer_info_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
@@ -91,7 +121,7 @@ ossl_pkcs7_recip_info_free(void *ptr)
static const rb_data_type_t ossl_pkcs7_recip_info_type = {
"OpenSSL/PKCS7/RECIP_INFO",
{
- 0, ossl_pkcs7_recip_info_free,
+ 0, ossl_pkcs7_recip_info_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
@@ -114,23 +144,32 @@ ossl_PKCS7_SIGNER_INFO_dup(PKCS7_SIGNER_INFO *si)
}
static PKCS7_RECIP_INFO *
-ossl_PKCS7_RECIP_INFO_dup(PKCS7_RECIP_INFO *si)
+ossl_PKCS7_RECIP_INFO_dup(PKCS7_RECIP_INFO *ri)
{
- return ASN1_dup((i2d_of_void *)i2d_PKCS7_RECIP_INFO,
- (d2i_of_void *)d2i_PKCS7_RECIP_INFO,
- si);
+ PKCS7_RECIP_INFO *ri_new = ASN1_dup((i2d_of_void *)i2d_PKCS7_RECIP_INFO,
+ (d2i_of_void *)d2i_PKCS7_RECIP_INFO,
+ ri);
+ if (ri_new && ri->cert) {
+ if (!X509_up_ref(ri->cert)) {
+ PKCS7_RECIP_INFO_free(ri_new);
+ return NULL;
+ }
+ ri_new->cert = ri->cert;
+ }
+ return ri_new;
}
static VALUE
ossl_pkcs7si_new(PKCS7_SIGNER_INFO *p7si)
{
- PKCS7_SIGNER_INFO *pkcs7;
+ PKCS7_SIGNER_INFO *p7si_new;
VALUE obj;
obj = NewPKCS7si(cPKCS7Signer);
- pkcs7 = p7si ? ossl_PKCS7_SIGNER_INFO_dup(p7si) : PKCS7_SIGNER_INFO_new();
- if (!pkcs7) ossl_raise(ePKCS7Error, NULL);
- SetPKCS7si(obj, pkcs7);
+ p7si_new = ossl_PKCS7_SIGNER_INFO_dup(p7si);
+ if (!p7si_new)
+ ossl_raise(ePKCS7Error, "ASN1_dup");
+ SetPKCS7si(obj, p7si_new);
return obj;
}
@@ -138,13 +177,14 @@ ossl_pkcs7si_new(PKCS7_SIGNER_INFO *p7si)
static VALUE
ossl_pkcs7ri_new(PKCS7_RECIP_INFO *p7ri)
{
- PKCS7_RECIP_INFO *pkcs7;
+ PKCS7_RECIP_INFO *p7ri_new;
VALUE obj;
obj = NewPKCS7ri(cPKCS7Recipient);
- pkcs7 = p7ri ? ossl_PKCS7_RECIP_INFO_dup(p7ri) : PKCS7_RECIP_INFO_new();
- if (!pkcs7) ossl_raise(ePKCS7Error, NULL);
- SetPKCS7ri(obj, pkcs7);
+ p7ri_new = ossl_PKCS7_RECIP_INFO_dup(p7ri);
+ if (!p7ri_new)
+ ossl_raise(ePKCS7Error,"ASN1_dup");
+ SetPKCS7ri(obj, p7ri_new);
return obj;
}
@@ -167,8 +207,10 @@ ossl_pkcs7_s_read_smime(VALUE klass, VALUE arg)
BIO_free(in);
if (!pkcs7)
ossl_raise(ePKCS7Error, "Could not parse the PKCS7");
- if (!pkcs7->d.ptr)
+ if (!pkcs7->d.ptr) {
+ PKCS7_free(pkcs7);
ossl_raise(ePKCS7Error, "No content in PKCS7");
+ }
data = out ? ossl_membio2str(out) : Qnil;
SetPKCS7(ret, pkcs7);
@@ -196,7 +238,7 @@ ossl_pkcs7_s_write_smime(int argc, VALUE *argv, VALUE klass)
if(NIL_P(data)) data = ossl_pkcs7_get_data(pkcs7);
GetPKCS7(pkcs7, p7);
if(!NIL_P(data) && PKCS7_is_detached(p7))
- flg |= PKCS7_DETACHED;
+ flg |= PKCS7_DETACHED;
in = NIL_P(data) ? NULL : ossl_obj2bio(&data);
if(!(out = BIO_new(BIO_s_mem()))){
BIO_free(in);
@@ -237,16 +279,16 @@ ossl_pkcs7_s_sign(int argc, VALUE *argv, VALUE klass)
in = ossl_obj2bio(&data);
if(NIL_P(certs)) x509s = NULL;
else{
- x509s = ossl_protect_x509_ary2sk(certs, &status);
- if(status){
- BIO_free(in);
- rb_jump_tag(status);
- }
+ x509s = ossl_protect_x509_ary2sk(certs, &status);
+ if(status){
+ BIO_free(in);
+ rb_jump_tag(status);
+ }
}
if(!(pkcs7 = PKCS7_sign(x509, pkey, x509s, in, flg))){
- BIO_free(in);
- sk_X509_pop_free(x509s, X509_free);
- ossl_raise(ePKCS7Error, NULL);
+ BIO_free(in);
+ sk_X509_pop_free(x509s, X509_free);
+ ossl_raise(ePKCS7Error, NULL);
}
SetPKCS7(ret, pkcs7);
ossl_pkcs7_set_data(ret, data);
@@ -259,12 +301,19 @@ ossl_pkcs7_s_sign(int argc, VALUE *argv, VALUE klass)
/*
* call-seq:
- * PKCS7.encrypt(certs, data, [, cipher [, flags]]) => pkcs7
+ * PKCS7.encrypt(certs, data, cipher, flags = 0) => pkcs7
+ *
+ * Creates a PKCS #7 enveloped-data structure.
+ *
+ * Before version 3.3.0, +cipher+ was optional and defaulted to
+ * <tt>"RC2-40-CBC"</tt>.
+ *
+ * See also the man page PKCS7_encrypt(3).
*/
static VALUE
ossl_pkcs7_s_encrypt(int argc, VALUE *argv, VALUE klass)
{
- VALUE certs, data, cipher, flags;
+ VALUE certs, data, cipher, flags, cipher_holder;
STACK_OF(X509) *x509s;
BIO *in;
const EVP_CIPHER *ciph;
@@ -273,37 +322,29 @@ ossl_pkcs7_s_encrypt(int argc, VALUE *argv, VALUE klass)
PKCS7 *p7;
rb_scan_args(argc, argv, "22", &certs, &data, &cipher, &flags);
- if(NIL_P(cipher)){
-#if !defined(OPENSSL_NO_RC2)
- ciph = EVP_rc2_40_cbc();
-#elif !defined(OPENSSL_NO_DES)
- ciph = EVP_des_ede3_cbc();
-#elif !defined(OPENSSL_NO_RC2)
- ciph = EVP_rc2_40_cbc();
-#elif !defined(OPENSSL_NO_AES)
- ciph = EVP_EVP_aes_128_cbc();
-#else
- ossl_raise(ePKCS7Error, "Must specify cipher");
-#endif
-
+ if (NIL_P(cipher)) {
+ rb_raise(rb_eArgError,
+ "cipher must be specified. Before version 3.3, " \
+ "the default cipher was RC2-40-CBC.");
}
- else ciph = ossl_evp_get_cipherbyname(cipher);
+ ciph = ossl_evp_cipher_fetch(cipher, &cipher_holder);
flg = NIL_P(flags) ? 0 : NUM2INT(flags);
ret = NewPKCS7(cPKCS7);
in = ossl_obj2bio(&data);
x509s = ossl_protect_x509_ary2sk(certs, &status);
if(status){
- BIO_free(in);
- rb_jump_tag(status);
+ BIO_free(in);
+ rb_jump_tag(status);
}
- if(!(p7 = PKCS7_encrypt(x509s, in, (EVP_CIPHER*)ciph, flg))){
- BIO_free(in);
- sk_X509_pop_free(x509s, X509_free);
- ossl_raise(ePKCS7Error, NULL);
+ if (!(p7 = PKCS7_encrypt(x509s, in, ciph, flg))) {
+ BIO_free(in);
+ sk_X509_pop_free(x509s, X509_free);
+ ossl_raise(ePKCS7Error, NULL);
}
BIO_free(in);
SetPKCS7(ret, p7);
ossl_pkcs7_set_data(ret, data);
+ rb_ivar_set(ret, id_cipher_holder, cipher_holder);
sk_X509_pop_free(x509s, X509_free);
return ret;
@@ -317,7 +358,7 @@ ossl_pkcs7_alloc(VALUE klass)
obj = NewPKCS7(klass);
if (!(pkcs7 = PKCS7_new())) {
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
}
SetPKCS7(obj, pkcs7);
@@ -339,7 +380,7 @@ ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self)
VALUE arg;
if(rb_scan_args(argc, argv, "01", &arg) == 0)
- return self;
+ return self;
arg = ossl_to_der_if_possible(arg);
in = ossl_obj2bio(&arg);
p7 = d2i_PKCS7_bio(in, NULL);
@@ -349,9 +390,11 @@ ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self)
}
BIO_free(in);
if (!p7)
- ossl_raise(rb_eArgError, "Could not parse the PKCS7");
- if (!p7->d.ptr)
- ossl_raise(rb_eArgError, "No content in PKCS7");
+ ossl_raise(ePKCS7Error, "Could not parse the PKCS7");
+ if (!p7->d.ptr) {
+ PKCS7_free(p7);
+ ossl_raise(ePKCS7Error, "No content in PKCS7");
+ }
RTYPEDDATA_DATA(self) = p7;
PKCS7_free(p7_orig);
@@ -361,6 +404,7 @@ ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+/* :nodoc: */
static VALUE
ossl_pkcs7_copy(VALUE self, VALUE other)
{
@@ -374,7 +418,7 @@ ossl_pkcs7_copy(VALUE self, VALUE other)
pkcs7 = PKCS7_dup(b);
if (!pkcs7) {
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
}
DATA_PTR(self) = pkcs7;
PKCS7_free(a);
@@ -406,13 +450,13 @@ ossl_pkcs7_sym2typeid(VALUE sym)
RSTRING_GETMEM(sym, s, l);
for(i = 0; ; i++){
- if(i == numberof(p7_type_tab))
- ossl_raise(ePKCS7Error, "unknown type \"%"PRIsVALUE"\"", sym);
- if(strlen(p7_type_tab[i].name) != l) continue;
- if(strcmp(p7_type_tab[i].name, s) == 0){
- ret = p7_type_tab[i].nid;
- break;
- }
+ if(i == numberof(p7_type_tab))
+ ossl_raise(ePKCS7Error, "unknown type \"%"PRIsVALUE"\"", sym);
+ if(strlen(p7_type_tab[i].name) != l) continue;
+ if(strcmp(p7_type_tab[i].name, s) == 0){
+ ret = p7_type_tab[i].nid;
+ break;
+ }
}
return ret;
@@ -429,7 +473,7 @@ ossl_pkcs7_set_type(VALUE self, VALUE type)
GetPKCS7(self, p7);
if(!PKCS7_set_type(p7, ossl_pkcs7_sym2typeid(type)))
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
return type;
}
@@ -445,15 +489,15 @@ ossl_pkcs7_get_type(VALUE self)
GetPKCS7(self, p7);
if(PKCS7_type_is_signed(p7))
- return ID2SYM(rb_intern("signed"));
+ return ID2SYM(rb_intern("signed"));
if(PKCS7_type_is_encrypted(p7))
- return ID2SYM(rb_intern("encrypted"));
+ return ID2SYM(rb_intern("encrypted"));
if(PKCS7_type_is_enveloped(p7))
- return ID2SYM(rb_intern("enveloped"));
+ return ID2SYM(rb_intern("enveloped"));
if(PKCS7_type_is_signedAndEnveloped(p7))
- return ID2SYM(rb_intern("signedAndEnveloped"));
+ return ID2SYM(rb_intern("signedAndEnveloped"));
if(PKCS7_type_is_data(p7))
- return ID2SYM(rb_intern("data"));
+ return ID2SYM(rb_intern("data"));
return Qnil;
}
@@ -464,9 +508,9 @@ ossl_pkcs7_set_detached(VALUE self, VALUE flag)
GetPKCS7(self, p7);
if(flag != Qtrue && flag != Qfalse)
- ossl_raise(ePKCS7Error, "must specify a boolean");
+ ossl_raise(ePKCS7Error, "must specify a boolean");
if(!PKCS7_set_detached(p7, flag == Qtrue ? 1 : 0))
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
return flag;
}
@@ -476,6 +520,8 @@ ossl_pkcs7_get_detached(VALUE self)
{
PKCS7 *p7;
GetPKCS7(self, p7);
+ if (!PKCS7_type_is_signed(p7))
+ return Qfalse;
return PKCS7_get_detached(p7) ? Qtrue : Qfalse;
}
@@ -491,11 +537,14 @@ static VALUE
ossl_pkcs7_set_cipher(VALUE self, VALUE cipher)
{
PKCS7 *pkcs7;
+ const EVP_CIPHER *ciph;
+ VALUE cipher_holder;
GetPKCS7(self, pkcs7);
- if (!PKCS7_set_cipher(pkcs7, ossl_evp_get_cipherbyname(cipher))) {
- ossl_raise(ePKCS7Error, NULL);
- }
+ ciph = ossl_evp_cipher_fetch(cipher, &cipher_holder);
+ if (!PKCS7_set_cipher(pkcs7, ciph))
+ ossl_raise(ePKCS7Error, "PKCS7_set_cipher");
+ rb_ivar_set(self, id_cipher_holder, cipher_holder);
return cipher;
}
@@ -526,22 +575,17 @@ ossl_pkcs7_get_signer(VALUE self)
{
PKCS7 *pkcs7;
STACK_OF(PKCS7_SIGNER_INFO) *sk;
- PKCS7_SIGNER_INFO *si;
int num, i;
VALUE ary;
GetPKCS7(self, pkcs7);
- if (!(sk = PKCS7_get_signer_info(pkcs7))) {
- OSSL_Debug("OpenSSL::PKCS7#get_signer_info == NULL!");
- return rb_ary_new();
- }
- if ((num = sk_PKCS7_SIGNER_INFO_num(sk)) < 0) {
- ossl_raise(ePKCS7Error, "Negative number of signers!");
- }
- ary = rb_ary_new2(num);
+ if (!(sk = PKCS7_get_signer_info(pkcs7)))
+ return rb_ary_new();
+ num = sk_PKCS7_SIGNER_INFO_num(sk);
+ ary = rb_ary_new_capa(num);
for (i=0; i<num; i++) {
- si = sk_PKCS7_SIGNER_INFO_value(sk, i);
- rb_ary_push(ary, ossl_pkcs7si_new(si));
+ PKCS7_SIGNER_INFO *si = sk_PKCS7_SIGNER_INFO_value(sk, i);
+ rb_ary_push(ary, ossl_pkcs7si_new(si));
}
return ary;
@@ -573,24 +617,21 @@ ossl_pkcs7_get_recipient(VALUE self)
{
PKCS7 *pkcs7;
STACK_OF(PKCS7_RECIP_INFO) *sk;
- PKCS7_RECIP_INFO *si;
int num, i;
VALUE ary;
GetPKCS7(self, pkcs7);
if (PKCS7_type_is_enveloped(pkcs7))
- sk = pkcs7->d.enveloped->recipientinfo;
+ sk = pkcs7->d.enveloped->recipientinfo;
else if (PKCS7_type_is_signedAndEnveloped(pkcs7))
- sk = pkcs7->d.signed_and_enveloped->recipientinfo;
+ sk = pkcs7->d.signed_and_enveloped->recipientinfo;
else sk = NULL;
if (!sk) return rb_ary_new();
- if ((num = sk_PKCS7_RECIP_INFO_num(sk)) < 0) {
- ossl_raise(ePKCS7Error, "Negative number of recipient!");
- }
- ary = rb_ary_new2(num);
+ num = sk_PKCS7_RECIP_INFO_num(sk);
+ ary = rb_ary_new_capa(num);
for (i=0; i<num; i++) {
- si = sk_PKCS7_RECIP_INFO_value(sk, i);
- rb_ary_push(ary, ossl_pkcs7ri_new(si));
+ PKCS7_RECIP_INFO *ri = sk_PKCS7_RECIP_INFO_value(sk, i);
+ rb_ary_push(ary, ossl_pkcs7ri_new(ri));
}
return ary;
@@ -605,7 +646,7 @@ ossl_pkcs7_add_certificate(VALUE self, VALUE cert)
GetPKCS7(self, pkcs7);
x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
if (!PKCS7_add_certificate(pkcs7, x509)){
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
}
return self;
@@ -621,13 +662,13 @@ pkcs7_get_certs(VALUE self)
GetPKCS7(self, pkcs7);
i = OBJ_obj2nid(pkcs7->type);
switch(i){
- case NID_pkcs7_signed:
+ case NID_pkcs7_signed:
certs = pkcs7->d.sign->cert;
break;
- case NID_pkcs7_signedAndEnveloped:
+ case NID_pkcs7_signedAndEnveloped:
certs = pkcs7->d.signed_and_enveloped->cert;
break;
- default:
+ default:
certs = NULL;
}
@@ -644,13 +685,13 @@ pkcs7_get_crls(VALUE self)
GetPKCS7(self, pkcs7);
i = OBJ_obj2nid(pkcs7->type);
switch(i){
- case NID_pkcs7_signed:
+ case NID_pkcs7_signed:
crls = pkcs7->d.sign->crl;
break;
- case NID_pkcs7_signedAndEnveloped:
+ case NID_pkcs7_signedAndEnveloped:
crls = pkcs7->d.signed_and_enveloped->crl;
break;
- default:
+ default:
crls = NULL;
}
@@ -670,7 +711,10 @@ ossl_pkcs7_set_certificates(VALUE self, VALUE ary)
X509 *cert;
certs = pkcs7_get_certs(self);
- while((cert = sk_X509_pop(certs))) X509_free(cert);
+ if (certs) {
+ while ((cert = sk_X509_pop(certs)))
+ X509_free(cert);
+ }
rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_certs_i, self);
return ary;
@@ -679,7 +723,10 @@ ossl_pkcs7_set_certificates(VALUE self, VALUE ary)
static VALUE
ossl_pkcs7_get_certificates(VALUE self)
{
- return ossl_x509_sk2ary(pkcs7_get_certs(self));
+ STACK_OF(X509) *certs = pkcs7_get_certs(self);
+ if (!certs)
+ return Qnil;
+ return ossl_x509_sk2ary(certs);
}
static VALUE
@@ -691,7 +738,7 @@ ossl_pkcs7_add_crl(VALUE self, VALUE crl)
GetPKCS7(self, pkcs7); /* NO DUP needed! */
x509crl = GetX509CRLPtr(crl);
if (!PKCS7_add_crl(pkcs7, x509crl)) {
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
}
return self;
@@ -710,7 +757,10 @@ ossl_pkcs7_set_crls(VALUE self, VALUE ary)
X509_CRL *crl;
crls = pkcs7_get_crls(self);
- while((crl = sk_X509_CRL_pop(crls))) X509_CRL_free(crl);
+ if (crls) {
+ while ((crl = sk_X509_CRL_pop(crls)))
+ X509_CRL_free(crl);
+ }
rb_block_call(ary, rb_intern("each"), 0, 0, ossl_pkcs7_set_crls_i, self);
return ary;
@@ -719,7 +769,10 @@ ossl_pkcs7_set_crls(VALUE self, VALUE ary)
static VALUE
ossl_pkcs7_get_crls(VALUE self)
{
- return ossl_x509crl_sk2ary(pkcs7_get_crls(self));
+ STACK_OF(X509_CRL) *crls = pkcs7_get_crls(self);
+ if (!crls)
+ return Qnil;
+ return ossl_x509crl_sk2ary(crls);
}
static VALUE
@@ -732,7 +785,6 @@ ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self)
BIO *in, *out;
PKCS7 *p7;
VALUE data;
- const char *msg;
GetPKCS7(self, p7);
rb_scan_args(argc, argv, "22", &certs, &store, &indata, &flags);
@@ -742,28 +794,30 @@ ossl_pkcs7_verify(int argc, VALUE *argv, VALUE self)
in = NIL_P(indata) ? NULL : ossl_obj2bio(&indata);
if(NIL_P(certs)) x509s = NULL;
else{
- x509s = ossl_protect_x509_ary2sk(certs, &status);
- if(status){
- BIO_free(in);
- rb_jump_tag(status);
- }
+ x509s = ossl_protect_x509_ary2sk(certs, &status);
+ if(status){
+ BIO_free(in);
+ rb_jump_tag(status);
+ }
}
if(!(out = BIO_new(BIO_s_mem()))){
- BIO_free(in);
- sk_X509_pop_free(x509s, X509_free);
- ossl_raise(ePKCS7Error, NULL);
+ BIO_free(in);
+ sk_X509_pop_free(x509s, X509_free);
+ ossl_raise(ePKCS7Error, NULL);
}
ok = PKCS7_verify(p7, x509s, x509st, in, out, flg);
BIO_free(in);
sk_X509_pop_free(x509s, X509_free);
- if (ok < 0) ossl_raise(ePKCS7Error, "PKCS7_verify");
- msg = ERR_reason_error_string(ERR_peek_error());
- ossl_pkcs7_set_err_string(self, msg ? rb_str_new2(msg) : Qnil);
- ossl_clear_error();
data = ossl_membio2str(out);
ossl_pkcs7_set_data(self, data);
-
- return (ok == 1) ? Qtrue : Qfalse;
+ if (ok != 1) {
+ const char *msg = ERR_reason_error_string(ERR_peek_error());
+ ossl_pkcs7_set_err_string(self, msg ? rb_str_new_cstr(msg) : Qnil);
+ ossl_clear_error();
+ return Qfalse;
+ }
+ ossl_pkcs7_set_err_string(self, Qnil);
+ return Qtrue;
}
static VALUE
@@ -783,10 +837,10 @@ ossl_pkcs7_decrypt(int argc, VALUE *argv, VALUE self)
flg = NIL_P(flags) ? 0 : NUM2INT(flags);
GetPKCS7(self, p7);
if(!(out = BIO_new(BIO_s_mem())))
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
if(!PKCS7_decrypt(p7, key, x509, out, flg)){
- BIO_free(out);
- ossl_raise(ePKCS7Error, NULL);
+ BIO_free(out);
+ ossl_raise(ePKCS7Error, NULL);
}
str = ossl_membio2str(out); /* out will be free */
@@ -799,30 +853,38 @@ ossl_pkcs7_add_data(VALUE self, VALUE data)
PKCS7 *pkcs7;
BIO *out, *in;
char buf[4096];
- int len;
+ int len, ret;
GetPKCS7(self, pkcs7);
- if(PKCS7_type_is_signed(pkcs7)){
- if(!PKCS7_content_new(pkcs7, NID_pkcs7_data))
- ossl_raise(ePKCS7Error, NULL);
+ if (PKCS7_type_is_signed(pkcs7)) {
+ if (!PKCS7_content_new(pkcs7, NID_pkcs7_data))
+ ossl_raise(ePKCS7Error, "PKCS7_content_new");
}
in = ossl_obj2bio(&data);
- if(!(out = PKCS7_dataInit(pkcs7, NULL))) goto err;
- for(;;){
- if((len = BIO_read(in, buf, sizeof(buf))) <= 0)
- break;
- if(BIO_write(out, buf, len) != len)
- goto err;
+ if (!(out = PKCS7_dataInit(pkcs7, NULL))) {
+ BIO_free(in);
+ ossl_raise(ePKCS7Error, "PKCS7_dataInit");
}
- if(!PKCS7_dataFinal(pkcs7, out)) goto err;
- ossl_pkcs7_set_data(self, Qnil);
-
- err:
+ for (;;) {
+ if ((len = BIO_read(in, buf, sizeof(buf))) <= 0)
+ break;
+ if (BIO_write(out, buf, len) != len) {
+ BIO_free_all(out);
+ BIO_free(in);
+ ossl_raise(ePKCS7Error, "BIO_write");
+ }
+ }
+ if (BIO_flush(out) <= 0) {
+ BIO_free_all(out);
+ BIO_free(in);
+ ossl_raise(ePKCS7Error, "BIO_flush");
+ }
+ ret = PKCS7_dataFinal(pkcs7, out);
BIO_free_all(out);
BIO_free(in);
- if(ERR_peek_error()){
- ossl_raise(ePKCS7Error, NULL);
- }
+ if (!ret)
+ ossl_raise(ePKCS7Error, "PKCS7_dataFinal");
+ ossl_pkcs7_set_data(self, Qnil);
return data;
}
@@ -837,11 +899,11 @@ ossl_pkcs7_to_der(VALUE self)
GetPKCS7(self, pkcs7);
if((len = i2d_PKCS7(pkcs7, NULL)) <= 0)
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
str = rb_str_new(0, len);
p = (unsigned char *)RSTRING_PTR(str);
if(i2d_PKCS7(pkcs7, &p) <= 0)
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
ossl_str_adjust(str, p);
return str;
@@ -875,11 +937,11 @@ ossl_pkcs7_to_pem(VALUE self)
GetPKCS7(self, pkcs7);
if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
}
if (!PEM_write_bio_PKCS7(out, pkcs7)) {
- BIO_free(out);
- ossl_raise(ePKCS7Error, NULL);
+ BIO_free(out);
+ ossl_raise(ePKCS7Error, NULL);
}
str = ossl_membio2str(out);
@@ -897,7 +959,7 @@ ossl_pkcs7si_alloc(VALUE klass)
obj = NewPKCS7si(klass);
if (!(p7si = PKCS7_SIGNER_INFO_new())) {
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
}
SetPKCS7si(obj, p7si);
@@ -911,14 +973,15 @@ ossl_pkcs7si_initialize(VALUE self, VALUE cert, VALUE key, VALUE digest)
EVP_PKEY *pkey;
X509 *x509;
const EVP_MD *md;
+ VALUE md_holder;
pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
- md = ossl_evp_get_digestbyname(digest);
+ md = ossl_evp_md_fetch(digest, &md_holder);
GetPKCS7si(self, p7si);
- if (!(PKCS7_SIGNER_INFO_set(p7si, x509, pkey, (EVP_MD*)md))) {
- ossl_raise(ePKCS7Error, NULL);
- }
+ if (!(PKCS7_SIGNER_INFO_set(p7si, x509, pkey, md)))
+ ossl_raise(ePKCS7Error, "PKCS7_SIGNER_INFO_set");
+ rb_ivar_set(self, id_md_holder, md_holder);
return self;
}
@@ -952,10 +1015,10 @@ ossl_pkcs7si_get_signed_time(VALUE self)
GetPKCS7si(self, p7si);
if (!(asn1obj = PKCS7_get_signed_attribute(p7si, NID_pkcs9_signingTime))) {
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
}
if (asn1obj->type == V_ASN1_UTCTIME) {
- return asn1time_to_time(asn1obj->value.utctime);
+ return asn1time_to_time(asn1obj->value.utctime);
}
/*
* OR
@@ -977,7 +1040,7 @@ ossl_pkcs7ri_alloc(VALUE klass)
obj = NewPKCS7ri(klass);
if (!(p7ri = PKCS7_RECIP_INFO_new())) {
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
}
SetPKCS7ri(obj, p7ri);
@@ -993,7 +1056,7 @@ ossl_pkcs7ri_initialize(VALUE self, VALUE cert)
x509 = GetX509CertPtr(cert); /* NO NEED TO DUP */
GetPKCS7ri(self, p7ri);
if (!PKCS7_RECIP_INFO_set(p7ri, x509)) {
- ossl_raise(ePKCS7Error, NULL);
+ ossl_raise(ePKCS7Error, NULL);
}
return self;
@@ -1036,11 +1099,6 @@ void
Init_ossl_pkcs7(void)
{
#undef rb_intern
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
-#endif
-
cPKCS7 = rb_define_class_under(mOSSL, "PKCS7", rb_cObject);
ePKCS7Error = rb_define_class_under(cPKCS7, "PKCS7Error", eOSSLError);
rb_define_singleton_method(cPKCS7, "read_smime", ossl_pkcs7_s_read_smime, 1);
@@ -1104,4 +1162,7 @@ Init_ossl_pkcs7(void)
DefPKCS7Const(BINARY);
DefPKCS7Const(NOATTR);
DefPKCS7Const(NOSMIMECAP);
+
+ id_md_holder = rb_intern_const("EVP_MD_holder");
+ id_cipher_holder = rb_intern_const("EVP_CIPHER_holder");
}
diff --git a/ext/openssl/ossl_pkcs7.h b/ext/openssl/ossl_pkcs7.h
index 3e1b094670..140fda1835 100644
--- a/ext/openssl/ossl_pkcs7.h
+++ b/ext/openssl/ossl_pkcs7.h
@@ -5,32 +5,12 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#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;
-extern VALUE ePKCS7Error;
-
+VALUE ossl_pkcs7_new(PKCS7 *p7);
void Init_ossl_pkcs7(void);
#endif /* _OSSL_PKCS7_H_ */
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c
index 013412c27f..d2fd5b29c3 100644
--- a/ext/openssl/ossl_pkey.c
+++ b/ext/openssl/ossl_pkey.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -33,13 +33,13 @@ ossl_evp_pkey_free(void *ptr)
const rb_data_type_t ossl_evp_pkey_type = {
"OpenSSL/EVP_PKEY",
{
- 0, ossl_evp_pkey_free,
+ 0, ossl_evp_pkey_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
static VALUE
-pkey_new0(VALUE arg)
+pkey_wrap0(VALUE arg)
{
EVP_PKEY *pkey = (EVP_PKEY *)arg;
VALUE klass, obj;
@@ -65,15 +65,15 @@ pkey_new0(VALUE arg)
}
VALUE
-ossl_pkey_new(EVP_PKEY *pkey)
+ossl_pkey_wrap(EVP_PKEY *pkey)
{
VALUE obj;
int status;
- obj = rb_protect(pkey_new0, (VALUE)pkey, &status);
+ obj = rb_protect(pkey_wrap0, (VALUE)pkey, &status);
if (status) {
- EVP_PKEY_free(pkey);
- rb_jump_tag(status);
+ EVP_PKEY_free(pkey);
+ rb_jump_tag(status);
}
return obj;
@@ -94,7 +94,8 @@ ossl_pkey_read(BIO *bio, const char *input_type, int selection, VALUE pass)
selection, NULL, NULL);
if (!dctx)
goto out;
- if (OSSL_DECODER_CTX_set_pem_password_cb(dctx, ossl_pem_passwd_cb,
+ if (selection == EVP_PKEY_KEYPAIR &&
+ OSSL_DECODER_CTX_set_pem_password_cb(dctx, ossl_pem_passwd_cb,
ppass) != 1)
goto out;
while (1) {
@@ -187,23 +188,23 @@ ossl_pkey_read_generic(BIO *bio, VALUE pass)
EVP_PKEY *pkey;
if ((pkey = d2i_PrivateKey_bio(bio, NULL)))
- goto out;
+ goto out;
OSSL_BIO_reset(bio);
if ((pkey = d2i_PKCS8PrivateKey_bio(bio, NULL, ossl_pem_passwd_cb, ppass)))
- goto out;
+ goto out;
OSSL_BIO_reset(bio);
if ((pkey = d2i_PUBKEY_bio(bio, NULL)))
- goto out;
+ 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;
+ goto out;
OSSL_BIO_reset(bio);
if ((pkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL)))
- goto out;
+ goto out;
OSSL_BIO_reset(bio);
if ((pkey = PEM_read_bio_Parameters(bio, NULL)))
- goto out;
+ goto out;
out:
return pkey;
@@ -238,8 +239,8 @@ ossl_pkey_new_from_data(int argc, VALUE *argv, VALUE self)
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);
+ ossl_raise(ePKeyError, "Could not parse PKey");
+ return ossl_pkey_wrap(pkey);
}
static VALUE
@@ -443,7 +444,7 @@ pkey_generate(int argc, VALUE *argv, VALUE self, int genparam)
}
}
- return ossl_pkey_new(gen_arg.pkey);
+ return ossl_pkey_wrap(gen_arg.pkey);
}
/*
@@ -507,7 +508,7 @@ ossl_pkey_s_generate_key(int argc, VALUE *argv, VALUE self)
void
ossl_pkey_check_public_key(const EVP_PKEY *pkey)
{
-#if OSSL_OPENSSL_PREREQ(3, 0, 0)
+#ifdef OSSL_HAVE_IMMUTABLE_PKEY
if (EVP_PKEY_missing_parameters(pkey))
ossl_raise(ePKeyError, "parameters missing");
#else
@@ -515,35 +516,34 @@ ossl_pkey_check_public_key(const EVP_PKEY *pkey)
const BIGNUM *n, *e, *pubkey;
if (EVP_PKEY_missing_parameters(pkey))
- ossl_raise(ePKeyError, "parameters missing");
+ ossl_raise(ePKeyError, "parameters missing");
- /* OpenSSL < 1.1.0 takes non-const pointer */
- ptr = EVP_PKEY_get0((EVP_PKEY *)pkey);
+ ptr = EVP_PKEY_get0(pkey);
switch (EVP_PKEY_base_id(pkey)) {
case EVP_PKEY_RSA:
- RSA_get0_key(ptr, &n, &e, NULL);
- if (n && e)
- return;
- break;
+ RSA_get0_key(ptr, &n, &e, NULL);
+ if (n && e)
+ return;
+ break;
case EVP_PKEY_DSA:
- DSA_get0_key(ptr, &pubkey, NULL);
- if (pubkey)
- return;
- break;
+ DSA_get0_key(ptr, &pubkey, NULL);
+ if (pubkey)
+ return;
+ break;
case EVP_PKEY_DH:
- DH_get0_key(ptr, &pubkey, NULL);
- if (pubkey)
- return;
- break;
+ DH_get0_key(ptr, &pubkey, NULL);
+ if (pubkey)
+ return;
+ break;
#if !defined(OPENSSL_NO_EC)
case EVP_PKEY_EC:
- if (EC_KEY_get0_public_key(ptr))
- return;
- break;
+ if (EC_KEY_get0_public_key(ptr))
+ return;
+ break;
#endif
default:
- /* unsupported type; assuming ok */
- return;
+ /* unsupported type; assuming ok */
+ return;
}
ossl_raise(ePKeyError, "public key missing");
#endif
@@ -610,12 +610,13 @@ static VALUE
ossl_pkey_initialize(VALUE self)
{
if (rb_obj_is_instance_of(self, cPKey)) {
- ossl_raise(rb_eTypeError, "OpenSSL::PKey::PKey can't be instantiated directly");
+ ossl_raise(rb_eTypeError, "OpenSSL::PKey::PKey can't be instantiated directly");
}
return self;
}
#ifdef HAVE_EVP_PKEY_DUP
+/* :nodoc: */
static VALUE
ossl_pkey_initialize_copy(VALUE self, VALUE other)
{
@@ -635,7 +636,29 @@ ossl_pkey_initialize_copy(VALUE self, VALUE other)
}
#endif
-#ifdef HAVE_EVP_PKEY_NEW_RAW_PRIVATE_KEY
+#ifndef OSSL_USE_PROVIDER
+static int
+lookup_pkey_type(VALUE type)
+{
+ const EVP_PKEY_ASN1_METHOD *ameth;
+ int pkey_id;
+
+ StringValue(type);
+ /*
+ * XXX: EVP_PKEY_asn1_find_str() looks up a PEM type string. Should we use
+ * OBJ_txt2nid() instead (and then somehow check if the NID is an acceptable
+ * EVP_PKEY type)?
+ * It is probably fine, though, since it can handle all algorithms that
+ * support raw keys in 1.1.1: { X25519, X448, ED25519, ED448, HMAC }.
+ */
+ ameth = EVP_PKEY_asn1_find_str(NULL, RSTRING_PTR(type), RSTRING_LENINT(type));
+ if (!ameth)
+ ossl_raise(ePKeyError, "algorithm %"PRIsVALUE" not found", type);
+ EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth);
+ return pkey_id;
+}
+#endif
+
/*
* call-seq:
* OpenSSL::PKey.new_raw_private_key(algo, string) -> PKey
@@ -647,28 +670,27 @@ static VALUE
ossl_pkey_new_raw_private_key(VALUE self, VALUE type, VALUE key)
{
EVP_PKEY *pkey;
- const EVP_PKEY_ASN1_METHOD *ameth;
- int pkey_id;
size_t keylen;
- StringValue(type);
StringValue(key);
- ameth = EVP_PKEY_asn1_find_str(NULL, RSTRING_PTR(type), RSTRING_LENINT(type));
- if (!ameth)
- ossl_raise(ePKeyError, "algorithm %"PRIsVALUE" not found", type);
- EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth);
-
keylen = RSTRING_LEN(key);
+#ifdef OSSL_USE_PROVIDER
+ pkey = EVP_PKEY_new_raw_private_key_ex(NULL, StringValueCStr(type), NULL,
+ (unsigned char *)RSTRING_PTR(key),
+ keylen);
+ if (!pkey)
+ ossl_raise(ePKeyError, "EVP_PKEY_new_raw_private_key_ex");
+#else
+ int pkey_id = lookup_pkey_type(type);
pkey = EVP_PKEY_new_raw_private_key(pkey_id, NULL, (unsigned char *)RSTRING_PTR(key), keylen);
if (!pkey)
ossl_raise(ePKeyError, "EVP_PKEY_new_raw_private_key");
+#endif
- return ossl_pkey_new(pkey);
+ return ossl_pkey_wrap(pkey);
}
-#endif
-#ifdef HAVE_EVP_PKEY_NEW_RAW_PRIVATE_KEY
/*
* call-seq:
* OpenSSL::PKey.new_raw_public_key(algo, string) -> PKey
@@ -680,26 +702,26 @@ static VALUE
ossl_pkey_new_raw_public_key(VALUE self, VALUE type, VALUE key)
{
EVP_PKEY *pkey;
- const EVP_PKEY_ASN1_METHOD *ameth;
- int pkey_id;
size_t keylen;
- StringValue(type);
StringValue(key);
- ameth = EVP_PKEY_asn1_find_str(NULL, RSTRING_PTR(type), RSTRING_LENINT(type));
- if (!ameth)
- ossl_raise(ePKeyError, "algorithm %"PRIsVALUE" not found", type);
- EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth);
-
keylen = RSTRING_LEN(key);
+#ifdef OSSL_USE_PROVIDER
+ pkey = EVP_PKEY_new_raw_public_key_ex(NULL, StringValueCStr(type), NULL,
+ (unsigned char *)RSTRING_PTR(key),
+ keylen);
+ if (!pkey)
+ ossl_raise(ePKeyError, "EVP_PKEY_new_raw_public_key_ex");
+#else
+ int pkey_id = lookup_pkey_type(type);
pkey = EVP_PKEY_new_raw_public_key(pkey_id, NULL, (unsigned char *)RSTRING_PTR(key), keylen);
if (!pkey)
ossl_raise(ePKeyError, "EVP_PKEY_new_raw_public_key");
+#endif
- return ossl_pkey_new(pkey);
+ return ossl_pkey_wrap(pkey);
}
-#endif
/*
* call-seq:
@@ -715,6 +737,10 @@ ossl_pkey_oid(VALUE self)
GetPKey(self, pkey);
nid = EVP_PKEY_id(pkey);
+#ifdef OSSL_USE_PROVIDER
+ if (nid == EVP_PKEY_KEYMGMT)
+ ossl_raise(ePKeyError, "EVP_PKEY_id");
+#endif
return rb_str_new_cstr(OBJ_nid2sn(nid));
}
@@ -728,13 +754,23 @@ static VALUE
ossl_pkey_inspect(VALUE self)
{
EVP_PKEY *pkey;
- int nid;
GetPKey(self, pkey);
- nid = EVP_PKEY_id(pkey);
- return rb_sprintf("#<%"PRIsVALUE":%p oid=%s>",
- rb_class_name(CLASS_OF(self)), (void *)self,
- OBJ_nid2sn(nid));
+ VALUE str = rb_sprintf("#<%"PRIsVALUE":%p",
+ rb_obj_class(self), (void *)self);
+ int nid = EVP_PKEY_id(pkey);
+#ifdef OSSL_USE_PROVIDER
+ if (nid != EVP_PKEY_KEYMGMT)
+#endif
+ rb_str_catf(str, " oid=%s", OBJ_nid2sn(nid));
+#ifdef OSSL_USE_PROVIDER
+ rb_str_catf(str, " type_name=%s", EVP_PKEY_get0_type_name(pkey));
+ const OSSL_PROVIDER *prov = EVP_PKEY_get0_provider(pkey);
+ if (prov)
+ rb_str_catf(str, " provider=%s", OSSL_PROVIDER_get0_name(prov));
+#endif
+ rb_str_catf(str, ">");
+ return str;
}
/*
@@ -778,44 +814,33 @@ VALUE
ossl_pkey_export_traditional(int argc, VALUE *argv, VALUE self, int to_der)
{
EVP_PKEY *pkey;
- VALUE cipher, pass;
+ VALUE cipher, pass, cipher_holder;
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);
+ enc = ossl_evp_cipher_fetch(cipher, &cipher_holder);
+ pass = ossl_pem_passwd_value(pass);
}
bio = BIO_new(BIO_s_mem());
if (!bio)
- ossl_raise(ePKeyError, "BIO_new");
+ ossl_raise(ePKeyError, "BIO_new");
if (to_der) {
- if (!i2d_PrivateKey_bio(bio, pkey)) {
- BIO_free(bio);
- ossl_raise(ePKeyError, "i2d_PrivateKey_bio");
- }
+ if (!i2d_PrivateKey_bio(bio, pkey)) {
+ BIO_free(bio);
+ ossl_raise(ePKeyError, "i2d_PrivateKey_bio");
+ }
}
else {
-#if OSSL_OPENSSL_PREREQ(1, 1, 0) || OSSL_LIBRESSL_PREREQ(3, 5, 0)
- if (!PEM_write_bio_PrivateKey_traditional(bio, pkey, enc, NULL, 0,
- ossl_pem_passwd_cb,
- (void *)pass)) {
-#else
- char pem_str[80];
- const char *aname;
-
- EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, &aname, pkey->ameth);
- snprintf(pem_str, sizeof(pem_str), "%s PRIVATE KEY", aname);
- if (!PEM_ASN1_write_bio((i2d_of_void *)i2d_PrivateKey, pem_str, bio,
- pkey, enc, NULL, 0, ossl_pem_passwd_cb,
- (void *)pass)) {
-#endif
- BIO_free(bio);
- ossl_raise(ePKeyError, "PEM_write_bio_PrivateKey_traditional");
- }
+ if (!PEM_write_bio_PrivateKey_traditional(bio, pkey, enc, NULL, 0,
+ ossl_pem_passwd_cb,
+ (void *)pass)) {
+ BIO_free(bio);
+ ossl_raise(ePKeyError, "PEM_write_bio_PrivateKey_traditional");
+ }
}
return ossl_membio2str(bio);
}
@@ -824,37 +849,37 @@ static VALUE
do_pkcs8_export(int argc, VALUE *argv, VALUE self, int to_der)
{
EVP_PKEY *pkey;
- VALUE cipher, pass;
+ VALUE cipher, pass, cipher_holder;
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);
+ /*
+ * TODO: EncryptedPrivateKeyInfo actually has more options.
+ * Should they be exposed?
+ */
+ enc = ossl_evp_cipher_fetch(cipher, &cipher_holder);
+ pass = ossl_pem_passwd_value(pass);
}
bio = BIO_new(BIO_s_mem());
if (!bio)
- ossl_raise(ePKeyError, "BIO_new");
+ 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");
- }
+ 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");
- }
+ 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);
}
@@ -901,7 +926,6 @@ ossl_pkey_private_to_pem(int argc, VALUE *argv, VALUE self)
return do_pkcs8_export(argc, argv, self, 0);
}
-#ifdef HAVE_EVP_PKEY_NEW_RAW_PRIVATE_KEY
/*
* call-seq:
* pkey.raw_private_key => string
@@ -928,7 +952,6 @@ ossl_pkey_raw_private_key(VALUE self)
return str;
}
-#endif
VALUE
ossl_pkey_export_spki(VALUE self, int to_der)
@@ -937,20 +960,21 @@ ossl_pkey_export_spki(VALUE self, int to_der)
BIO *bio;
GetPKey(self, pkey);
+ ossl_pkey_check_public_key(pkey);
bio = BIO_new(BIO_s_mem());
if (!bio)
- ossl_raise(ePKeyError, "BIO_new");
+ ossl_raise(ePKeyError, "BIO_new");
if (to_der) {
- if (!i2d_PUBKEY_bio(bio, pkey)) {
- BIO_free(bio);
- ossl_raise(ePKeyError, "i2d_PUBKEY_bio");
- }
+ 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");
- }
+ if (!PEM_write_bio_PUBKEY(bio, pkey)) {
+ BIO_free(bio);
+ ossl_raise(ePKeyError, "PEM_write_bio_PUBKEY");
+ }
}
return ossl_membio2str(bio);
}
@@ -985,7 +1009,6 @@ ossl_pkey_public_to_pem(VALUE self)
return ossl_pkey_export_spki(self, 0);
}
-#ifdef HAVE_EVP_PKEY_NEW_RAW_PRIVATE_KEY
/*
* call-seq:
* pkey.raw_public_key => string
@@ -1012,7 +1035,6 @@ ossl_pkey_raw_public_key(VALUE self)
return str;
}
-#endif
/*
* call-seq:
@@ -1089,7 +1111,7 @@ static VALUE
ossl_pkey_sign(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
- VALUE digest, data, options, sig;
+ VALUE digest, data, options, sig, md_holder;
const EVP_MD *md = NULL;
EVP_MD_CTX *ctx;
EVP_PKEY_CTX *pctx;
@@ -1099,7 +1121,7 @@ ossl_pkey_sign(int argc, VALUE *argv, VALUE self)
pkey = GetPrivPKeyPtr(self);
rb_scan_args(argc, argv, "21", &digest, &data, &options);
if (!NIL_P(digest))
- md = ossl_evp_get_digestbyname(digest);
+ md = ossl_evp_md_fetch(digest, &md_holder);
StringValue(data);
ctx = EVP_MD_CTX_new();
@@ -1116,7 +1138,6 @@ ossl_pkey_sign(int argc, VALUE *argv, VALUE self)
rb_jump_tag(state);
}
}
-#if OSSL_OPENSSL_PREREQ(1, 1, 1) || OSSL_LIBRESSL_PREREQ(3, 4, 0)
if (EVP_DigestSign(ctx, NULL, &siglen, (unsigned char *)RSTRING_PTR(data),
RSTRING_LEN(data)) < 1) {
EVP_MD_CTX_free(ctx);
@@ -1137,30 +1158,6 @@ ossl_pkey_sign(int argc, VALUE *argv, VALUE self)
EVP_MD_CTX_free(ctx);
ossl_raise(ePKeyError, "EVP_DigestSign");
}
-#else
- if (EVP_DigestSignUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)) < 1) {
- EVP_MD_CTX_free(ctx);
- ossl_raise(ePKeyError, "EVP_DigestSignUpdate");
- }
- if (EVP_DigestSignFinal(ctx, NULL, &siglen) < 1) {
- EVP_MD_CTX_free(ctx);
- ossl_raise(ePKeyError, "EVP_DigestSignFinal");
- }
- if (siglen > LONG_MAX) {
- EVP_MD_CTX_free(ctx);
- rb_raise(ePKeyError, "signature would be too large");
- }
- sig = ossl_str_new(NULL, (long)siglen, &state);
- if (state) {
- EVP_MD_CTX_free(ctx);
- rb_jump_tag(state);
- }
- if (EVP_DigestSignFinal(ctx, (unsigned char *)RSTRING_PTR(sig),
- &siglen) < 1) {
- EVP_MD_CTX_free(ctx);
- ossl_raise(ePKeyError, "EVP_DigestSignFinal");
- }
-#endif
EVP_MD_CTX_free(ctx);
rb_str_set_len(sig, siglen);
return sig;
@@ -1193,7 +1190,7 @@ static VALUE
ossl_pkey_verify(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
- VALUE digest, sig, data, options;
+ VALUE digest, sig, data, options, md_holder;
const EVP_MD *md = NULL;
EVP_MD_CTX *ctx;
EVP_PKEY_CTX *pctx;
@@ -1203,7 +1200,7 @@ ossl_pkey_verify(int argc, VALUE *argv, VALUE self)
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);
+ md = ossl_evp_md_fetch(digest, &md_holder);
StringValue(sig);
StringValue(data);
@@ -1221,24 +1218,12 @@ ossl_pkey_verify(int argc, VALUE *argv, VALUE self)
rb_jump_tag(state);
}
}
-#if OSSL_OPENSSL_PREREQ(1, 1, 1) || OSSL_LIBRESSL_PREREQ(3, 4, 0)
ret = EVP_DigestVerify(ctx, (unsigned char *)RSTRING_PTR(sig),
RSTRING_LEN(sig), (unsigned char *)RSTRING_PTR(data),
RSTRING_LEN(data));
EVP_MD_CTX_free(ctx);
if (ret < 0)
ossl_raise(ePKeyError, "EVP_DigestVerify");
-#else
- if (EVP_DigestVerifyUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)) < 1) {
- EVP_MD_CTX_free(ctx);
- ossl_raise(ePKeyError, "EVP_DigestVerifyUpdate");
- }
- ret = EVP_DigestVerifyFinal(ctx, (unsigned char *)RSTRING_PTR(sig),
- RSTRING_LEN(sig));
- EVP_MD_CTX_free(ctx);
- if (ret < 0)
- ossl_raise(ePKeyError, "EVP_DigestVerifyFinal");
-#endif
if (ret)
return Qtrue;
else {
@@ -1284,7 +1269,7 @@ static VALUE
ossl_pkey_sign_raw(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
- VALUE digest, data, options, sig;
+ VALUE digest, data, options, sig, md_holder;
const EVP_MD *md = NULL;
EVP_PKEY_CTX *ctx;
size_t outlen;
@@ -1293,7 +1278,7 @@ ossl_pkey_sign_raw(int argc, VALUE *argv, VALUE self)
GetPKey(self, pkey);
rb_scan_args(argc, argv, "21", &digest, &data, &options);
if (!NIL_P(digest))
- md = ossl_evp_get_digestbyname(digest);
+ md = ossl_evp_md_fetch(digest, &md_holder);
StringValue(data);
ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
@@ -1360,7 +1345,7 @@ static VALUE
ossl_pkey_verify_raw(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
- VALUE digest, sig, data, options;
+ VALUE digest, sig, data, options, md_holder;
const EVP_MD *md = NULL;
EVP_PKEY_CTX *ctx;
int state, ret;
@@ -1369,7 +1354,7 @@ ossl_pkey_verify_raw(int argc, VALUE *argv, VALUE self)
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);
+ md = ossl_evp_md_fetch(digest, &md_holder);
StringValue(sig);
StringValue(data);
@@ -1423,7 +1408,7 @@ static VALUE
ossl_pkey_verify_recover(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
- VALUE digest, sig, options, out;
+ VALUE digest, sig, options, out, md_holder;
const EVP_MD *md = NULL;
EVP_PKEY_CTX *ctx;
int state;
@@ -1433,7 +1418,7 @@ ossl_pkey_verify_recover(int argc, VALUE *argv, VALUE self)
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);
+ md = ossl_evp_md_fetch(digest, &md_holder);
StringValue(sig);
ctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
@@ -1673,11 +1658,6 @@ void
Init_ossl_pkey(void)
{
#undef rb_intern
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
-#endif
-
/* Document-module: OpenSSL::PKey
*
* == Asymmetric Public Key Algorithms
@@ -1733,7 +1713,16 @@ Init_ossl_pkey(void)
/* Document-class: OpenSSL::PKey::PKeyError
*
- *Raised when errors occur during PKey#sign or PKey#verify.
+ * Raised when errors occur during PKey#sign or PKey#verify.
+ *
+ * Before version 4.0.0, OpenSSL::PKey::PKeyError had the following
+ * subclasses. These subclasses have been removed and the constants are
+ * now defined as aliases of OpenSSL::PKey::PKeyError.
+ *
+ * * OpenSSL::PKey::DHError
+ * * OpenSSL::PKey::DSAError
+ * * OpenSSL::PKey::ECError
+ * * OpenSSL::PKey::RSAError
*/
ePKeyError = rb_define_class_under(mPKey, "PKeyError", eOSSLError);
@@ -1751,10 +1740,8 @@ Init_ossl_pkey(void)
rb_define_module_function(mPKey, "read", ossl_pkey_new_from_data, -1);
rb_define_module_function(mPKey, "generate_parameters", ossl_pkey_s_generate_parameters, -1);
rb_define_module_function(mPKey, "generate_key", ossl_pkey_s_generate_key, -1);
-#ifdef HAVE_EVP_PKEY_NEW_RAW_PRIVATE_KEY
rb_define_module_function(mPKey, "new_raw_private_key", ossl_pkey_new_raw_private_key, 2);
rb_define_module_function(mPKey, "new_raw_public_key", ossl_pkey_new_raw_public_key, 2);
-#endif
rb_define_alloc_func(cPKey, ossl_pkey_alloc);
rb_define_method(cPKey, "initialize", ossl_pkey_initialize, 0);
@@ -1770,10 +1757,8 @@ Init_ossl_pkey(void)
rb_define_method(cPKey, "private_to_pem", ossl_pkey_private_to_pem, -1);
rb_define_method(cPKey, "public_to_der", ossl_pkey_public_to_der, 0);
rb_define_method(cPKey, "public_to_pem", ossl_pkey_public_to_pem, 0);
-#ifdef HAVE_EVP_PKEY_NEW_RAW_PRIVATE_KEY
rb_define_method(cPKey, "raw_private_key", ossl_pkey_raw_private_key, 0);
rb_define_method(cPKey, "raw_public_key", ossl_pkey_raw_public_key, 0);
-#endif
rb_define_method(cPKey, "compare?", ossl_pkey_compare, 1);
rb_define_method(cPKey, "sign", ossl_pkey_sign, -1);
diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h
index 10669b824c..023361b90f 100644
--- a/ext/openssl/ossl_pkey.h
+++ b/ext/openssl/ossl_pkey.h
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(OSSL_PKEY_H)
#define OSSL_PKEY_H
@@ -22,12 +22,12 @@ extern const rb_data_type_t ossl_evp_pkey_type;
#define GetPKey(obj, pkey) do {\
TypedData_Get_Struct((obj), EVP_PKEY, &ossl_evp_pkey_type, (pkey)); \
if (!(pkey)) { \
- rb_raise(rb_eRuntimeError, "PKEY wasn't initialized!");\
+ rb_raise(rb_eRuntimeError, "PKEY wasn't initialized!");\
} \
} while (0)
/* Takes ownership of the EVP_PKEY */
-VALUE ossl_pkey_new(EVP_PKEY *);
+VALUE ossl_pkey_wrap(EVP_PKEY *);
void ossl_pkey_check_public_key(const EVP_PKEY *);
EVP_PKEY *ossl_pkey_read_generic(BIO *, VALUE);
EVP_PKEY *GetPKeyPtr(VALUE);
@@ -45,7 +45,7 @@ VALUE ossl_pkey_export_spki(VALUE self, int to_der);
* #to_der.
*/
VALUE ossl_pkey_export_traditional(int argc, VALUE *argv, VALUE self,
- int to_der);
+ int to_der);
void Init_ossl_pkey(void);
@@ -53,152 +53,141 @@ void Init_ossl_pkey(void);
* RSA
*/
extern VALUE cRSA;
-extern VALUE eRSAError;
-
void Init_ossl_rsa(void);
/*
* DSA
*/
extern VALUE cDSA;
-extern VALUE eDSAError;
-
void Init_ossl_dsa(void);
/*
* DH
*/
extern VALUE cDH;
-extern VALUE eDHError;
-
void Init_ossl_dh(void);
/*
* EC
*/
extern VALUE cEC;
-extern VALUE eECError;
-extern VALUE cEC_GROUP;
-extern VALUE eEC_GROUP;
-extern VALUE cEC_POINT;
-extern VALUE eEC_POINT;
VALUE ossl_ec_new(EVP_PKEY *);
void Init_ossl_ec(void);
-#define OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, _name, _get) \
-/* \
- * call-seq: \
- * _keytype##.##_name -> aBN \
- */ \
-static VALUE ossl_##_keytype##_get_##_name(VALUE self) \
-{ \
- const _type *obj; \
- const BIGNUM *bn; \
- \
- Get##_type(self, obj); \
- _get; \
- if (bn == NULL) \
- return Qnil; \
- return ossl_bn_new(bn); \
+#define OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, _name, _get) \
+/* \
+ * call-seq: \
+ * _keytype##.##_name -> aBN \
+ */ \
+static VALUE ossl_##_keytype##_get_##_name(VALUE self) \
+{ \
+ const _type *obj; \
+ const BIGNUM *bn; \
+ \
+ Get##_type(self, obj); \
+ _get; \
+ if (bn == NULL) \
+ return Qnil; \
+ return ossl_bn_new(bn); \
}
-#define OSSL_PKEY_BN_DEF_GETTER3(_keytype, _type, _group, a1, a2, a3) \
- OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a1, \
- _type##_get0_##_group(obj, &bn, NULL, NULL)) \
- OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a2, \
- _type##_get0_##_group(obj, NULL, &bn, NULL)) \
- OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a3, \
- _type##_get0_##_group(obj, NULL, NULL, &bn))
-
-#define OSSL_PKEY_BN_DEF_GETTER2(_keytype, _type, _group, a1, a2) \
- OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a1, \
- _type##_get0_##_group(obj, &bn, NULL)) \
- 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: \
- * _keytype##.set_##_group(a1, a2, a3) -> self \
- */ \
+#define OSSL_PKEY_BN_DEF_GETTER3(_keytype, _type, _group, a1, a2, a3) \
+ OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a1, \
+ _type##_get0_##_group(obj, &bn, NULL, NULL)) \
+ OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a2, \
+ _type##_get0_##_group(obj, NULL, &bn, NULL)) \
+ OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a3, \
+ _type##_get0_##_group(obj, NULL, NULL, &bn))
+
+#define OSSL_PKEY_BN_DEF_GETTER2(_keytype, _type, _group, a1, a2) \
+ OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a1, \
+ _type##_get0_##_group(obj, &bn, NULL)) \
+ OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a2, \
+ _type##_get0_##_group(obj, NULL, &bn))
+
+#ifndef OSSL_HAVE_IMMUTABLE_PKEY
+#define OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3) \
+/* \
+ * call-seq: \
+ * _keytype##.set_##_group(a1, a2, a3) -> self \
+ */ \
static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2, VALUE v3) \
-{ \
- _type *obj; \
- BIGNUM *bn1 = NULL, *orig_bn1 = NIL_P(v1) ? NULL : GetBNPtr(v1);\
- BIGNUM *bn2 = NULL, *orig_bn2 = NIL_P(v2) ? NULL : GetBNPtr(v2);\
- BIGNUM *bn3 = NULL, *orig_bn3 = NIL_P(v3) ? NULL : GetBNPtr(v3);\
- \
- Get##_type(self, obj); \
- if ((orig_bn1 && !(bn1 = BN_dup(orig_bn1))) || \
- (orig_bn2 && !(bn2 = BN_dup(orig_bn2))) || \
- (orig_bn3 && !(bn3 = BN_dup(orig_bn3)))) { \
- BN_clear_free(bn1); \
- BN_clear_free(bn2); \
- BN_clear_free(bn3); \
- ossl_raise(eBNError, NULL); \
- } \
- \
- if (!_type##_set0_##_group(obj, bn1, bn2, bn3)) { \
- BN_clear_free(bn1); \
- BN_clear_free(bn2); \
- BN_clear_free(bn3); \
- ossl_raise(ePKeyError, #_type"_set0_"#_group); \
- } \
- return self; \
+{ \
+ _type *obj; \
+ BIGNUM *bn1 = NULL, *orig_bn1 = NIL_P(v1) ? NULL : GetBNPtr(v1);\
+ BIGNUM *bn2 = NULL, *orig_bn2 = NIL_P(v2) ? NULL : GetBNPtr(v2);\
+ BIGNUM *bn3 = NULL, *orig_bn3 = NIL_P(v3) ? NULL : GetBNPtr(v3);\
+ \
+ Get##_type(self, obj); \
+ if ((orig_bn1 && !(bn1 = BN_dup(orig_bn1))) || \
+ (orig_bn2 && !(bn2 = BN_dup(orig_bn2))) || \
+ (orig_bn3 && !(bn3 = BN_dup(orig_bn3)))) { \
+ BN_clear_free(bn1); \
+ BN_clear_free(bn2); \
+ BN_clear_free(bn3); \
+ ossl_raise(ePKeyError, "BN_dup"); \
+ } \
+ \
+ if (!_type##_set0_##_group(obj, bn1, bn2, bn3)) { \
+ BN_clear_free(bn1); \
+ BN_clear_free(bn2); \
+ BN_clear_free(bn3); \
+ ossl_raise(ePKeyError, #_type"_set0_"#_group); \
+ } \
+ return self; \
}
-#define OSSL_PKEY_BN_DEF_SETTER2(_keytype, _type, _group, a1, a2) \
-/* \
- * call-seq: \
- * _keytype##.set_##_group(a1, a2) -> self \
- */ \
+#define OSSL_PKEY_BN_DEF_SETTER2(_keytype, _type, _group, a1, a2) \
+/* \
+ * call-seq: \
+ * _keytype##.set_##_group(a1, a2) -> self \
+ */ \
static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2) \
-{ \
- _type *obj; \
- BIGNUM *bn1 = NULL, *orig_bn1 = NIL_P(v1) ? NULL : GetBNPtr(v1);\
- BIGNUM *bn2 = NULL, *orig_bn2 = NIL_P(v2) ? NULL : GetBNPtr(v2);\
- \
- Get##_type(self, obj); \
- if ((orig_bn1 && !(bn1 = BN_dup(orig_bn1))) || \
- (orig_bn2 && !(bn2 = BN_dup(orig_bn2)))) { \
- BN_clear_free(bn1); \
- BN_clear_free(bn2); \
- ossl_raise(eBNError, NULL); \
- } \
- \
- if (!_type##_set0_##_group(obj, bn1, bn2)) { \
- BN_clear_free(bn1); \
- BN_clear_free(bn2); \
- ossl_raise(ePKeyError, #_type"_set0_"#_group); \
- } \
- return self; \
+{ \
+ _type *obj; \
+ BIGNUM *bn1 = NULL, *orig_bn1 = NIL_P(v1) ? NULL : GetBNPtr(v1);\
+ BIGNUM *bn2 = NULL, *orig_bn2 = NIL_P(v2) ? NULL : GetBNPtr(v2);\
+ \
+ Get##_type(self, obj); \
+ if ((orig_bn1 && !(bn1 = BN_dup(orig_bn1))) || \
+ (orig_bn2 && !(bn2 = BN_dup(orig_bn2)))) { \
+ BN_clear_free(bn1); \
+ BN_clear_free(bn2); \
+ ossl_raise(ePKeyError, "BN_dup"); \
+ } \
+ \
+ if (!_type##_set0_##_group(obj, bn1, bn2)) { \
+ BN_clear_free(bn1); \
+ BN_clear_free(bn2); \
+ ossl_raise(ePKeyError, #_type"_set0_"#_group); \
+ } \
+ return self; \
}
#else
-#define OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3) \
+#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, \
+{ \
+ rb_raise(ePKeyError, \
#_keytype"#set_"#_group"= is incompatible with OpenSSL 3.0"); \
}
-#define OSSL_PKEY_BN_DEF_SETTER2(_keytype, _type, _group, a1, a2) \
+#define OSSL_PKEY_BN_DEF_SETTER2(_keytype, _type, _group, a1, a2) \
static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2) \
-{ \
- rb_raise(ePKeyError, \
+{ \
+ rb_raise(ePKeyError, \
#_keytype"#set_"#_group"= is incompatible with OpenSSL 3.0"); \
}
#endif
-#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)
+#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)
-#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)
+#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)
-#define DEF_OSSL_PKEY_BN(class, keytype, name) \
- rb_define_method((class), #name, ossl_##keytype##_get_##name, 0)
+#define DEF_OSSL_PKEY_BN(class, keytype, name) \
+ rb_define_method((class), #name, ossl_##keytype##_get_##name, 0)
#endif /* OSSL_PKEY_H */
diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c
index a231814a99..3f2975c5a3 100644
--- a/ext/openssl/ossl_pkey_dh.c
+++ b/ext/openssl/ossl_pkey_dh.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -14,20 +14,21 @@
#define GetPKeyDH(obj, pkey) do { \
GetPKey((obj), (pkey)); \
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DH) { /* PARANOIA? */ \
- ossl_raise(rb_eRuntimeError, "THIS IS NOT A DH!") ; \
+ ossl_raise(rb_eRuntimeError, "THIS IS NOT A DH!") ; \
} \
} while (0)
#define GetDH(obj, dh) do { \
EVP_PKEY *_pkey; \
GetPKeyDH((obj), _pkey); \
(dh) = EVP_PKEY_get0_DH(_pkey); \
+ if ((dh) == NULL) \
+ ossl_raise(ePKeyError, "failed to get DH from EVP_PKEY"); \
} while (0)
/*
* Classes
*/
VALUE cDH;
-VALUE eDHError;
/*
* Private
@@ -43,6 +44,7 @@ VALUE eDHError;
* 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).
+ * This form is not compatible with OpenSSL 3.0 or later.
*
* 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.
@@ -58,14 +60,15 @@ VALUE eDHError;
*
* Examples:
* # Creating an instance from scratch
- * # Note that this is deprecated and will not work on OpenSSL 3.0 or later.
+ * # Note that this is deprecated and will result in ArgumentError when
+ * # using OpenSSL 3.0 or later.
* dh = OpenSSL::PKey::DH.new
* dh.set_pqg(bn_p, nil, bn_g)
*
* # Generating a parameters and a key pair
* dh = OpenSSL::PKey::DH.new(2048) # An alias of OpenSSL::PKey::DH.generate(2048)
*
- * # Reading DH parameters
+ * # Reading DH parameters from a PEM-encoded string
* dh_params = OpenSSL::PKey::DH.new(File.read('parameters.pem')) # loads parameters only
* dh = OpenSSL::PKey.generate_key(dh_params) # generates a key pair
*/
@@ -84,10 +87,15 @@ ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
/* The DH.new(size, generator) form is handled by lib/openssl/pkey.rb */
if (rb_scan_args(argc, argv, "01", &arg) == 0) {
+#ifdef OSSL_HAVE_IMMUTABLE_PKEY
+ rb_raise(rb_eArgError, "OpenSSL::PKey::DH.new cannot be called " \
+ "without arguments; pkeys are immutable with OpenSSL 3.0");
+#else
dh = DH_new();
if (!dh)
- ossl_raise(eDHError, "DH_new");
+ ossl_raise(ePKeyError, "DH_new");
goto legacy;
+#endif
}
arg = ossl_to_der_if_possible(arg);
@@ -105,12 +113,12 @@ ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
pkey = ossl_pkey_read_generic(in, Qnil);
BIO_free(in);
if (!pkey)
- ossl_raise(eDHError, "could not parse pkey");
+ ossl_raise(ePKeyError, "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));
+ rb_raise(ePKeyError, "incorrect pkey type: %s", OBJ_nid2sn(type));
}
RTYPEDDATA_DATA(self) = pkey;
return self;
@@ -121,13 +129,14 @@ ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
if (!pkey || EVP_PKEY_assign_DH(pkey, dh) != 1) {
EVP_PKEY_free(pkey);
DH_free(dh);
- ossl_raise(eDHError, "EVP_PKEY_assign_DH");
+ ossl_raise(ePKeyError, "EVP_PKEY_assign_DH");
}
RTYPEDDATA_DATA(self) = pkey;
return self;
}
#ifndef HAVE_EVP_PKEY_DUP
+/* :nodoc: */
static VALUE
ossl_dh_initialize_copy(VALUE self, VALUE other)
{
@@ -142,26 +151,26 @@ ossl_dh_initialize_copy(VALUE self, VALUE other)
dh = DHparams_dup(dh_other);
if (!dh)
- ossl_raise(eDHError, "DHparams_dup");
+ ossl_raise(ePKeyError, "DHparams_dup");
DH_get0_key(dh_other, &pub, &priv);
if (pub) {
- BIGNUM *pub2 = BN_dup(pub);
- BIGNUM *priv2 = BN_dup(priv);
+ BIGNUM *pub2 = BN_dup(pub);
+ BIGNUM *priv2 = BN_dup(priv);
if (!pub2 || (priv && !priv2)) {
- BN_clear_free(pub2);
- BN_clear_free(priv2);
- ossl_raise(eDHError, "BN_dup");
- }
- DH_set0_key(dh, pub2, priv2);
+ BN_clear_free(pub2);
+ BN_clear_free(priv2);
+ ossl_raise(ePKeyError, "BN_dup");
+ }
+ 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");
+ ossl_raise(ePKeyError, "EVP_PKEY_assign_DH");
}
RTYPEDDATA_DATA(self) = pkey;
return self;
@@ -240,11 +249,11 @@ ossl_dh_export(VALUE self)
GetDH(self, dh);
if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eDHError, NULL);
+ ossl_raise(ePKeyError, NULL);
}
if (!PEM_write_bio_DHparams(out, dh)) {
- BIO_free(out);
- ossl_raise(eDHError, NULL);
+ BIO_free(out);
+ ossl_raise(ePKeyError, NULL);
}
str = ossl_membio2str(out);
@@ -274,11 +283,11 @@ ossl_dh_to_der(VALUE self)
GetDH(self, dh);
if((len = i2d_DHparams(dh, NULL)) <= 0)
- ossl_raise(eDHError, NULL);
+ ossl_raise(ePKeyError, NULL);
str = rb_str_new(0, len);
p = (unsigned char *)RSTRING_PTR(str);
if(i2d_DHparams(dh, &p) < 0)
- ossl_raise(eDHError, NULL);
+ ossl_raise(ePKeyError, NULL);
ossl_str_adjust(str, p);
return str;
@@ -286,35 +295,6 @@ ossl_dh_to_der(VALUE self)
/*
* call-seq:
- * dh.params -> hash
- *
- * Stores all parameters of key to the hash
- * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
- * Don't use :-)) (I's up to you)
- */
-static VALUE
-ossl_dh_get_params(VALUE self)
-{
- OSSL_3_const DH *dh;
- VALUE hash;
- const BIGNUM *p, *q, *g, *pub_key, *priv_key;
-
- GetDH(self, dh);
- DH_get0_pqg(dh, &p, &q, &g);
- DH_get0_key(dh, &pub_key, &priv_key);
-
- hash = rb_hash_new();
- rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(p));
- rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(q));
- rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(g));
- rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pub_key));
- rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(priv_key));
-
- return hash;
-}
-
-/*
- * call-seq:
* dh.params_ok? -> true | false
*
* Validates the Diffie-Hellman parameters associated with this instance.
@@ -334,7 +314,7 @@ ossl_dh_check_params(VALUE self)
GetPKey(self, pkey);
pctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
if (!pctx)
- ossl_raise(eDHError, "EVP_PKEY_CTX_new");
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
ret = EVP_PKEY_param_check(pctx);
EVP_PKEY_CTX_free(pctx);
#else
@@ -377,19 +357,6 @@ OSSL_PKEY_BN_DEF2(dh, DH, key, pub_key, priv_key)
void
Init_ossl_dh(void)
{
-#if 0
- mPKey = rb_define_module_under(mOSSL, "PKey");
- cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject);
- ePKeyError = rb_define_class_under(mPKey, "PKeyError", eOSSLError);
-#endif
-
- /* Document-class: OpenSSL::PKey::DHError
- *
- * Generic exception that is raised if an operation on a DH PKey
- * fails unexpectedly or in case an instantiation of an instance of DH
- * fails due to non-conformant input data.
- */
- eDHError = rb_define_class_under(mPKey, "DHError", ePKeyError);
/* Document-class: OpenSSL::PKey::DH
*
* An implementation of the Diffie-Hellman key exchange protocol based on
@@ -443,8 +410,6 @@ Init_ossl_dh(void)
DEF_OSSL_PKEY_BN(cDH, dh, priv_key);
rb_define_method(cDH, "set_pqg", ossl_dh_set_pqg, 3);
rb_define_method(cDH, "set_key", ossl_dh_set_key, 2);
-
- rb_define_method(cDH, "params", ossl_dh_get_params, 0);
}
#else /* defined NO_DH */
diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c
index 058ce73888..041646a058 100644
--- a/ext/openssl/ossl_pkey_dsa.c
+++ b/ext/openssl/ossl_pkey_dsa.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -14,13 +14,15 @@
#define GetPKeyDSA(obj, pkey) do { \
GetPKey((obj), (pkey)); \
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_DSA) { /* PARANOIA? */ \
- ossl_raise(rb_eRuntimeError, "THIS IS NOT A DSA!"); \
+ ossl_raise(rb_eRuntimeError, "THIS IS NOT A DSA!"); \
} \
} while (0)
#define GetDSA(obj, dsa) do { \
EVP_PKEY *_pkey; \
GetPKeyDSA((obj), _pkey); \
(dsa) = EVP_PKEY_get0_DSA(_pkey); \
+ if ((dsa) == NULL) \
+ ossl_raise(ePKeyError, "failed to get DSA from EVP_PKEY"); \
} while (0)
static inline int
@@ -41,7 +43,6 @@ DSA_PRIVATE(VALUE obj, OSSL_3_const DSA *dsa)
* Classes
*/
VALUE cDSA;
-VALUE eDSAError;
/*
* Private
@@ -56,6 +57,7 @@ VALUE eDSAError;
*
* If called without arguments, creates a new instance with no key components
* set. They can be set individually by #set_pqg and #set_key.
+ * This form is not compatible with OpenSSL 3.0 or later.
*
* 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.
@@ -96,10 +98,15 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
/* The DSA.new(size, generator) form is handled by lib/openssl/pkey.rb */
rb_scan_args(argc, argv, "02", &arg, &pass);
if (argc == 0) {
+#ifdef OSSL_HAVE_IMMUTABLE_PKEY
+ rb_raise(rb_eArgError, "OpenSSL::PKey::DSA.new cannot be called " \
+ "without arguments; pkeys are immutable with OpenSSL 3.0");
+#else
dsa = DSA_new();
if (!dsa)
- ossl_raise(eDSAError, "DSA_new");
+ ossl_raise(ePKeyError, "DSA_new");
goto legacy;
+#endif
}
pass = ossl_pem_passwd_value(pass);
@@ -117,12 +124,12 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
pkey = ossl_pkey_read_generic(in, pass);
BIO_free(in);
if (!pkey)
- ossl_raise(eDSAError, "Neither PUB key nor PRIV key");
+ ossl_raise(ePKeyError, "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));
+ rb_raise(ePKeyError, "incorrect pkey type: %s", OBJ_nid2sn(type));
}
RTYPEDDATA_DATA(self) = pkey;
return self;
@@ -133,13 +140,14 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
if (!pkey || EVP_PKEY_assign_DSA(pkey, dsa) != 1) {
EVP_PKEY_free(pkey);
DSA_free(dsa);
- ossl_raise(eDSAError, "EVP_PKEY_assign_DSA");
+ ossl_raise(ePKeyError, "EVP_PKEY_assign_DSA");
}
RTYPEDDATA_DATA(self) = pkey;
return self;
}
#ifndef HAVE_EVP_PKEY_DUP
+/* :nodoc: */
static VALUE
ossl_dsa_initialize_copy(VALUE self, VALUE other)
{
@@ -155,13 +163,13 @@ ossl_dsa_initialize_copy(VALUE self, VALUE other)
(d2i_of_void *)d2i_DSAPrivateKey,
(char *)dsa);
if (!dsa_new)
- ossl_raise(eDSAError, "ASN1_dup");
+ ossl_raise(ePKeyError, "ASN1_dup");
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");
+ ossl_raise(ePKeyError, "EVP_PKEY_assign_DSA");
}
RTYPEDDATA_DATA(self) = pkey;
@@ -304,35 +312,6 @@ ossl_dsa_to_der(VALUE self)
/*
- * call-seq:
- * dsa.params -> hash
- *
- * Stores all parameters of key to the hash
- * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!!
- * Don't use :-)) (I's up to you)
- */
-static VALUE
-ossl_dsa_get_params(VALUE self)
-{
- OSSL_3_const DSA *dsa;
- VALUE hash;
- const BIGNUM *p, *q, *g, *pub_key, *priv_key;
-
- GetDSA(self, dsa);
- DSA_get0_pqg(dsa, &p, &q, &g);
- DSA_get0_key(dsa, &pub_key, &priv_key);
-
- hash = rb_hash_new();
- rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(p));
- rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(q));
- rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(g));
- rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pub_key));
- rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(priv_key));
-
- return hash;
-}
-
-/*
* Document-method: OpenSSL::PKey::DSA#set_pqg
* call-seq:
* dsa.set_pqg(p, q, g) -> self
@@ -355,20 +334,6 @@ OSSL_PKEY_BN_DEF2(dsa, DSA, key, pub_key, priv_key)
void
Init_ossl_dsa(void)
{
-#if 0
- mPKey = rb_define_module_under(mOSSL, "PKey");
- cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject);
- ePKeyError = rb_define_class_under(mPKey, "PKeyError", eOSSLError);
-#endif
-
- /* Document-class: OpenSSL::PKey::DSAError
- *
- * Generic exception that is raised if an operation on a DSA PKey
- * fails unexpectedly or in case an instantiation of an instance of DSA
- * fails due to non-conformant input data.
- */
- eDSAError = rb_define_class_under(mPKey, "DSAError", ePKeyError);
-
/* Document-class: OpenSSL::PKey::DSA
*
* DSA, the Digital Signature Algorithm, is specified in NIST's
@@ -396,8 +361,6 @@ Init_ossl_dsa(void)
DEF_OSSL_PKEY_BN(cDSA, dsa, priv_key);
rb_define_method(cDSA, "set_pqg", ossl_dsa_set_pqg, 3);
rb_define_method(cDSA, "set_key", ossl_dsa_set_key, 2);
-
- rb_define_method(cDSA, "params", ossl_dsa_get_params, 0);
}
#else /* defined NO_DSA */
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
index 4b3a1fd0fe..35f031819d 100644
--- a/ext/openssl/ossl_pkey_ec.c
+++ b/ext/openssl/ossl_pkey_ec.c
@@ -15,25 +15,27 @@ static const rb_data_type_t ossl_ec_point_type;
#define GetPKeyEC(obj, pkey) do { \
GetPKey((obj), (pkey)); \
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) { \
- ossl_raise(rb_eRuntimeError, "THIS IS NOT A EC PKEY!"); \
+ ossl_raise(rb_eRuntimeError, "THIS IS NOT A EC PKEY!"); \
} \
} while (0)
#define GetEC(obj, key) do { \
EVP_PKEY *_pkey; \
GetPKeyEC(obj, _pkey); \
(key) = EVP_PKEY_get0_EC_KEY(_pkey); \
+ if ((key) == NULL) \
+ ossl_raise(ePKeyError, "failed to get EC_KEY from EVP_PKEY"); \
} while (0)
#define GetECGroup(obj, group) do { \
TypedData_Get_Struct(obj, EC_GROUP, &ossl_ec_group_type, group); \
if ((group) == NULL) \
- ossl_raise(eEC_GROUP, "EC_GROUP is not initialized"); \
+ ossl_raise(eEC_GROUP, "EC_GROUP is not initialized"); \
} while (0)
#define GetECPoint(obj, point) do { \
TypedData_Get_Struct(obj, EC_POINT, &ossl_ec_point_type, point); \
if ((point) == NULL) \
- ossl_raise(eEC_POINT, "EC_POINT is not initialized"); \
+ ossl_raise(eEC_POINT, "EC_POINT is not initialized"); \
} while (0)
#define GetECPointGroup(obj, group) do { \
VALUE _group = rb_attr_get(obj, id_i_group); \
@@ -41,17 +43,13 @@ static const rb_data_type_t ossl_ec_point_type;
} while (0)
VALUE cEC;
-VALUE eECError;
-VALUE cEC_GROUP;
-VALUE eEC_GROUP;
-VALUE cEC_POINT;
-VALUE eEC_POINT;
+static VALUE cEC_GROUP;
+static VALUE eEC_GROUP;
+static VALUE cEC_POINT;
+static VALUE eEC_POINT;
-static ID s_GFp, s_GF2m;
-
-static ID ID_uncompressed;
-static ID ID_compressed;
-static ID ID_hybrid;
+static VALUE sym_GFp, sym_GF2m;
+static VALUE sym_uncompressed, sym_compressed, sym_hybrid;
static ID id_i_group;
@@ -68,27 +66,27 @@ ec_key_new_from_group(VALUE arg)
EC_KEY *ec;
if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
- EC_GROUP *group;
+ EC_GROUP *group;
- GetECGroup(arg, group);
- if (!(ec = EC_KEY_new()))
- ossl_raise(eECError, NULL);
+ GetECGroup(arg, group);
+ if (!(ec = EC_KEY_new()))
+ ossl_raise(ePKeyError, NULL);
- if (!EC_KEY_set_group(ec, group)) {
- EC_KEY_free(ec);
- ossl_raise(eECError, NULL);
- }
+ if (!EC_KEY_set_group(ec, group)) {
+ EC_KEY_free(ec);
+ ossl_raise(ePKeyError, NULL);
+ }
} else {
- int nid = OBJ_sn2nid(StringValueCStr(arg));
+ int nid = OBJ_sn2nid(StringValueCStr(arg));
- if (nid == NID_undef)
- ossl_raise(eECError, "invalid curve name");
+ if (nid == NID_undef)
+ ossl_raise(ePKeyError, "invalid curve name");
- if (!(ec = EC_KEY_new_by_curve_name(nid)))
- ossl_raise(eECError, NULL);
+ if (!(ec = EC_KEY_new_by_curve_name(nid)))
+ ossl_raise(ePKeyError, NULL);
- EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
- EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED);
+ EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
+ EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED);
}
return ec;
@@ -115,12 +113,12 @@ ossl_ec_key_s_generate(VALUE klass, VALUE arg)
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");
+ ossl_raise(ePKeyError, "EVP_PKEY_assign_EC_KEY");
}
RTYPEDDATA_DATA(obj) = pkey;
if (!EC_KEY_generate_key(ec))
- ossl_raise(eECError, "EC_KEY_generate_key");
+ ossl_raise(ePKeyError, "EC_KEY_generate_key");
return obj;
}
@@ -150,9 +148,14 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "02", &arg, &pass);
if (NIL_P(arg)) {
+#ifdef OSSL_HAVE_IMMUTABLE_PKEY
+ rb_raise(rb_eArgError, "OpenSSL::PKey::EC.new cannot be called " \
+ "without arguments; pkeys are immutable with OpenSSL 3.0");
+#else
if (!(ec = EC_KEY_new()))
- ossl_raise(eECError, "EC_KEY_new");
+ ossl_raise(ePKeyError, "EC_KEY_new");
goto legacy;
+#endif
}
else if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
ec = ec_key_new_from_group(arg);
@@ -174,7 +177,7 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
type = EVP_PKEY_base_id(pkey);
if (type != EVP_PKEY_EC) {
EVP_PKEY_free(pkey);
- rb_raise(eDSAError, "incorrect pkey type: %s", OBJ_nid2sn(type));
+ rb_raise(ePKeyError, "incorrect pkey type: %s", OBJ_nid2sn(type));
}
RTYPEDDATA_DATA(self) = pkey;
return self;
@@ -184,13 +187,14 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
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");
+ ossl_raise(ePKeyError, "EVP_PKEY_assign_EC_KEY");
}
RTYPEDDATA_DATA(self) = pkey;
return self;
}
#ifndef HAVE_EVP_PKEY_DUP
+/* :nodoc: */
static VALUE
ossl_ec_key_initialize_copy(VALUE self, VALUE other)
{
@@ -204,12 +208,12 @@ ossl_ec_key_initialize_copy(VALUE self, VALUE other)
ec_new = EC_KEY_dup(ec);
if (!ec_new)
- ossl_raise(eECError, "EC_KEY_dup");
+ ossl_raise(ePKeyError, "EC_KEY_dup");
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");
+ ossl_raise(ePKeyError, "EVP_PKEY_assign_EC_KEY");
}
RTYPEDDATA_DATA(self) = pkey;
@@ -233,7 +237,7 @@ ossl_ec_key_get_group(VALUE self)
GetEC(self, ec);
group = EC_KEY_get0_group(ec);
if (!group)
- return Qnil;
+ return Qnil;
return ec_group_new(group);
}
@@ -248,7 +252,7 @@ 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)
+#ifdef OSSL_HAVE_IMMUTABLE_PKEY
rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
#else
EC_KEY *ec;
@@ -258,7 +262,7 @@ ossl_ec_key_set_group(VALUE self, VALUE group_v)
GetECGroup(group_v, group);
if (EC_KEY_set_group(ec, group) != 1)
- ossl_raise(eECError, "EC_KEY_set_group");
+ ossl_raise(ePKeyError, "EC_KEY_set_group");
return group_v;
#endif
@@ -290,7 +294,7 @@ 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)
+#ifdef OSSL_HAVE_IMMUTABLE_PKEY
rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
#else
EC_KEY *ec;
@@ -301,14 +305,14 @@ static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key)
bn = GetBNPtr(private_key);
switch (EC_KEY_set_private_key(ec, bn)) {
- case 1:
+ case 1:
break;
- case 0:
+ case 0:
if (bn == NULL)
break;
- /* fallthrough */
- default:
- ossl_raise(eECError, "EC_KEY_set_private_key");
+ /* fallthrough */
+ default:
+ ossl_raise(ePKeyError, "EC_KEY_set_private_key");
}
return private_key;
@@ -341,7 +345,7 @@ 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)
+#ifdef OSSL_HAVE_IMMUTABLE_PKEY
rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
#else
EC_KEY *ec;
@@ -352,14 +356,14 @@ static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key)
GetECPoint(public_key, point);
switch (EC_KEY_set_public_key(ec, point)) {
- case 1:
+ case 1:
break;
- case 0:
+ case 0:
if (point == NULL)
break;
- /* fallthrough */
- default:
- ossl_raise(eECError, "EC_KEY_set_public_key");
+ /* fallthrough */
+ default:
+ ossl_raise(ePKeyError, "EC_KEY_set_public_key");
}
return public_key;
@@ -463,7 +467,7 @@ ossl_ec_key_export(int argc, VALUE *argv, VALUE self)
GetEC(self, ec);
if (EC_KEY_get0_public_key(ec) == NULL)
- ossl_raise(eECError, "can't export - no public key set");
+ ossl_raise(ePKeyError, "can't export - no public key set");
if (EC_KEY_get0_private_key(ec))
return ossl_pkey_export_traditional(argc, argv, self, 0);
else
@@ -491,7 +495,7 @@ ossl_ec_key_to_der(VALUE self)
GetEC(self, ec);
if (EC_KEY_get0_public_key(ec) == NULL)
- ossl_raise(eECError, "can't export - no public key set");
+ ossl_raise(ePKeyError, "can't export - no public key set");
if (EC_KEY_get0_private_key(ec))
return ossl_pkey_export_traditional(0, NULL, self, 1);
else
@@ -513,14 +517,14 @@ ossl_ec_key_to_der(VALUE self)
*/
static VALUE ossl_ec_key_generate_key(VALUE self)
{
-#if OSSL_OPENSSL_PREREQ(3, 0, 0)
+#ifdef OSSL_HAVE_IMMUTABLE_PKEY
rb_raise(ePKeyError, "pkeys are immutable on OpenSSL 3.0");
#else
EC_KEY *ec;
GetEC(self, ec);
if (EC_KEY_generate_key(ec) != 1)
- ossl_raise(eECError, "EC_KEY_generate_key");
+ ossl_raise(ePKeyError, "EC_KEY_generate_key");
return self;
#endif
@@ -545,18 +549,18 @@ static VALUE ossl_ec_key_check_key(VALUE self)
GetEC(self, ec);
pctx = EVP_PKEY_CTX_new(pkey, /* engine */NULL);
if (!pctx)
- ossl_raise(eECError, "EVP_PKEY_CTX_new");
+ ossl_raise(ePKeyError, "EVP_PKEY_CTX_new");
if (EC_KEY_get0_private_key(ec) != NULL) {
if (EVP_PKEY_check(pctx) != 1) {
EVP_PKEY_CTX_free(pctx);
- ossl_raise(eECError, "EVP_PKEY_check");
+ ossl_raise(ePKeyError, "EVP_PKEY_check");
}
}
else {
if (EVP_PKEY_public_check(pctx) != 1) {
EVP_PKEY_CTX_free(pctx);
- ossl_raise(eECError, "EVP_PKEY_public_check");
+ ossl_raise(ePKeyError, "EVP_PKEY_public_check");
}
}
@@ -566,7 +570,7 @@ static VALUE ossl_ec_key_check_key(VALUE self)
GetEC(self, ec);
if (EC_KEY_check_key(ec) != 1)
- ossl_raise(eECError, "EC_KEY_check_key");
+ ossl_raise(ePKeyError, "EC_KEY_check_key");
#endif
return Qtrue;
@@ -584,7 +588,7 @@ ossl_ec_group_free(void *ptr)
static const rb_data_type_t ossl_ec_group_type = {
"OpenSSL/ec_group",
{
- 0, ossl_ec_group_free,
+ 0, ossl_ec_group_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
@@ -604,7 +608,7 @@ ec_group_new(const EC_GROUP *group)
obj = ossl_ec_group_alloc(cEC_GROUP);
group_new = EC_GROUP_dup(group);
if (!group_new)
- ossl_raise(eEC_GROUP, "EC_GROUP_dup");
+ ossl_raise(eEC_GROUP, "EC_GROUP_dup");
RTYPEDDATA_DATA(obj) = group_new;
return obj;
@@ -632,7 +636,7 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
ossl_raise(rb_eRuntimeError, "EC_GROUP is already initialized");
switch (rb_scan_args(argc, argv, "13", &arg1, &arg2, &arg3, &arg4)) {
- case 1:
+ case 1:
if (rb_obj_is_kind_of(arg1, cEC_GROUP)) {
const EC_GROUP *arg1_group;
@@ -644,7 +648,7 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL);
if (!group) {
- OSSL_BIO_reset(in);
+ OSSL_BIO_reset(in);
group = d2i_ECPKParameters_bio(in, NULL);
}
@@ -654,11 +658,14 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
const char *name = StringValueCStr(arg1);
int nid = OBJ_sn2nid(name);
- ossl_clear_error(); /* ignore errors in d2i_ECPKParameters_bio() */
+ ossl_clear_error(); /* ignore errors in d2i_ECPKParameters_bio() */
if (nid == NID_undef)
ossl_raise(eEC_GROUP, "unknown curve name (%"PRIsVALUE")", arg1);
-
+#if !defined(OPENSSL_IS_AWSLC)
group = EC_GROUP_new_by_curve_name(nid);
+#else /* EC_GROUPs are static and immutable by default in AWS-LC. */
+ group = EC_GROUP_new_by_curve_name_mutable(nid);
+#endif
if (group == NULL)
ossl_raise(eEC_GROUP, "unable to create curve (%"PRIsVALUE")", arg1);
@@ -668,33 +675,34 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
}
break;
- case 4:
+ case 4:
if (SYMBOL_P(arg1)) {
- ID id = SYM2ID(arg1);
EC_GROUP *(*new_curve)(const BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *) = NULL;
const BIGNUM *p = GetBNPtr(arg2);
const BIGNUM *a = GetBNPtr(arg3);
const BIGNUM *b = GetBNPtr(arg4);
- if (id == s_GFp) {
+ if (arg1 == sym_GFp) {
new_curve = EC_GROUP_new_curve_GFp;
+ }
#if !defined(OPENSSL_NO_EC2M)
- } else if (id == s_GF2m) {
+ else if (arg1 == sym_GF2m) {
new_curve = EC_GROUP_new_curve_GF2m;
+ }
#endif
- } else {
+ else {
ossl_raise(rb_eArgError, "unknown symbol, must be :GFp or :GF2m");
}
if ((group = new_curve(p, a, b, ossl_bn_ctx)) == NULL)
ossl_raise(eEC_GROUP, "EC_GROUP_new_by_GF*");
} else {
- ossl_raise(rb_eArgError, "unknown argument, must be :GFp or :GF2m");
+ ossl_raise(rb_eArgError, "unknown argument, must be :GFp or :GF2m");
}
break;
- default:
- ossl_raise(rb_eArgError, "wrong number of arguments");
+ default:
+ ossl_raise(rb_eArgError, "wrong number of arguments (given %d, expected 1 or 4)", argc);
}
ASSUME(group);
@@ -703,6 +711,7 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+/* :nodoc: */
static VALUE
ossl_ec_group_initialize_copy(VALUE self, VALUE other)
{
@@ -710,12 +719,12 @@ ossl_ec_group_initialize_copy(VALUE self, VALUE other)
TypedData_Get_Struct(self, EC_GROUP, &ossl_ec_group_type, group_new);
if (group_new)
- ossl_raise(eEC_GROUP, "EC::Group already initialized");
+ ossl_raise(eEC_GROUP, "EC::Group already initialized");
GetECGroup(other, group);
group_new = EC_GROUP_dup(group);
if (!group_new)
- ossl_raise(eEC_GROUP, "EC_GROUP_dup");
+ ossl_raise(eEC_GROUP, "EC_GROUP_dup");
RTYPEDDATA_DATA(self) = group_new;
return self;
@@ -737,9 +746,9 @@ static VALUE ossl_ec_group_eql(VALUE a, VALUE b)
GetECGroup(b, group2);
switch (EC_GROUP_cmp(group1, group2, ossl_bn_ctx)) {
- case 0: return Qtrue;
- case 1: return Qfalse;
- default: ossl_raise(eEC_GROUP, "EC_GROUP_cmp");
+ case 0: return Qtrue;
+ case 1: return Qfalse;
+ default: ossl_raise(eEC_GROUP, "EC_GROUP_cmp");
}
}
@@ -759,7 +768,7 @@ static VALUE ossl_ec_group_get_generator(VALUE self)
GetECGroup(self, group);
generator = EC_GROUP_get0_generator(group);
if (!generator)
- return Qnil;
+ return Qnil;
return ec_point_new(generator, group);
}
@@ -802,11 +811,10 @@ static VALUE ossl_ec_group_get_order(VALUE self)
{
VALUE bn_obj;
BIGNUM *bn;
- EC_GROUP *group = NULL;
+ EC_GROUP *group;
GetECGroup(self, group);
-
- bn_obj = ossl_bn_new(NULL);
+ bn_obj = ossl_bn_new(BN_value_one());
bn = GetBNPtr(bn_obj);
if (EC_GROUP_get_order(group, bn, ossl_bn_ctx) != 1)
@@ -827,11 +835,10 @@ static VALUE ossl_ec_group_get_cofactor(VALUE self)
{
VALUE bn_obj;
BIGNUM *bn;
- EC_GROUP *group = NULL;
+ EC_GROUP *group;
GetECGroup(self, group);
-
- bn_obj = ossl_bn_new(NULL);
+ bn_obj = ossl_bn_new(BN_value_one());
bn = GetBNPtr(bn_obj);
if (EC_GROUP_get_cofactor(group, bn, ossl_bn_ctx) != 1)
@@ -842,25 +849,23 @@ static VALUE ossl_ec_group_get_cofactor(VALUE self)
/*
* call-seq:
- * group.curve_name => String
+ * group.curve_name -> string or nil
*
- * Returns the curve name (sn).
+ * Returns the curve name (short name) corresponding to this group, or +nil+
+ * if \OpenSSL does not have an OID associated with the group.
*
* See the OpenSSL documentation for EC_GROUP_get_curve_name()
*/
static VALUE ossl_ec_group_get_curve_name(VALUE self)
{
- EC_GROUP *group = NULL;
+ EC_GROUP *group;
int nid;
GetECGroup(self, group);
- if (group == NULL)
- return Qnil;
-
nid = EC_GROUP_get_curve_name(group);
-
-/* BUG: an nid or asn1 object should be returned, maybe. */
- return rb_str_new2(OBJ_nid2sn(nid));
+ if (nid == NID_undef)
+ return Qnil;
+ return rb_str_new_cstr(OBJ_nid2sn(nid));
}
/*
@@ -953,37 +958,36 @@ static VALUE ossl_ec_group_set_asn1_flag(VALUE self, VALUE flag_v)
*/
static VALUE ossl_ec_group_get_point_conversion_form(VALUE self)
{
- EC_GROUP *group = NULL;
+ EC_GROUP *group;
point_conversion_form_t form;
- VALUE ret;
GetECGroup(self, group);
form = EC_GROUP_get_point_conversion_form(group);
switch (form) {
- case POINT_CONVERSION_UNCOMPRESSED: ret = ID_uncompressed; break;
- case POINT_CONVERSION_COMPRESSED: ret = ID_compressed; break;
- case POINT_CONVERSION_HYBRID: ret = ID_hybrid; break;
- default: ossl_raise(eEC_GROUP, "unsupported point conversion form: %d, this module should be updated", form);
+ case POINT_CONVERSION_UNCOMPRESSED:
+ return sym_uncompressed;
+ case POINT_CONVERSION_COMPRESSED:
+ return sym_compressed;
+ case POINT_CONVERSION_HYBRID:
+ return sym_hybrid;
+ default:
+ ossl_raise(eEC_GROUP, "unsupported point conversion form: %d, " \
+ "this module should be updated", form);
}
-
- return ID2SYM(ret);
}
static point_conversion_form_t
parse_point_conversion_form_symbol(VALUE sym)
{
- ID id = SYM2ID(sym);
-
- if (id == ID_uncompressed)
- return POINT_CONVERSION_UNCOMPRESSED;
- else if (id == ID_compressed)
- return POINT_CONVERSION_COMPRESSED;
- else if (id == ID_hybrid)
- return POINT_CONVERSION_HYBRID;
- else
- ossl_raise(rb_eArgError, "unsupported point conversion form %+"PRIsVALUE
- " (expected :compressed, :uncompressed, or :hybrid)", sym);
+ if (sym == sym_uncompressed)
+ return POINT_CONVERSION_UNCOMPRESSED;
+ if (sym == sym_compressed)
+ return POINT_CONVERSION_COMPRESSED;
+ if (sym == sym_hybrid)
+ return POINT_CONVERSION_HYBRID;
+ ossl_raise(rb_eArgError, "unsupported point conversion form %+"PRIsVALUE
+ " (expected :compressed, :uncompressed, or :hybrid)", sym);
}
/*
@@ -1088,20 +1092,20 @@ static VALUE ossl_ec_group_to_string(VALUE self, int format)
ossl_raise(eEC_GROUP, "BIO_new(BIO_s_mem())");
switch(format) {
- case EXPORT_PEM:
+ case EXPORT_PEM:
i = PEM_write_bio_ECPKParameters(out, group);
- break;
- case EXPORT_DER:
+ break;
+ case EXPORT_DER:
i = i2d_ECPKParameters_bio(out, group);
- break;
- default:
+ break;
+ default:
BIO_free(out);
- ossl_raise(rb_eRuntimeError, "unknown format (internal error)");
+ ossl_raise(rb_eRuntimeError, "unknown format (internal error)");
}
if (i != 1) {
BIO_free(out);
- ossl_raise(eECError, NULL);
+ ossl_raise(ePKeyError, NULL);
}
str = ossl_membio2str(out);
@@ -1145,11 +1149,11 @@ static VALUE ossl_ec_group_to_text(VALUE self)
GetECGroup(self, group);
if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eEC_GROUP, "BIO_new(BIO_s_mem())");
+ ossl_raise(eEC_GROUP, "BIO_new(BIO_s_mem())");
}
if (!ECPKParameters_print(out, group, 0)) {
- BIO_free(out);
- ossl_raise(eEC_GROUP, NULL);
+ BIO_free(out);
+ ossl_raise(eEC_GROUP, NULL);
}
str = ossl_membio2str(out);
@@ -1169,7 +1173,7 @@ ossl_ec_point_free(void *ptr)
static const rb_data_type_t ossl_ec_point_type = {
"OpenSSL/EC_POINT",
{
- 0, ossl_ec_point_free,
+ 0, ossl_ec_point_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
@@ -1189,7 +1193,7 @@ ec_point_new(const EC_POINT *point, const EC_GROUP *group)
obj = ossl_ec_point_alloc(cEC_POINT);
point_new = EC_POINT_dup(point, group);
if (!point_new)
- ossl_raise(eEC_POINT, "EC_POINT_dup");
+ ossl_raise(eEC_POINT, "EC_POINT_dup");
RTYPEDDATA_DATA(obj) = point_new;
rb_ivar_set(obj, id_i_group, ec_group_new(group));
@@ -1217,39 +1221,39 @@ static VALUE ossl_ec_point_initialize(int argc, VALUE *argv, VALUE self)
TypedData_Get_Struct(self, EC_POINT, &ossl_ec_point_type, point);
if (point)
- rb_raise(eEC_POINT, "EC_POINT already initialized");
+ rb_raise(eEC_POINT, "EC_POINT already initialized");
rb_scan_args(argc, argv, "11", &group_v, &arg2);
if (rb_obj_is_kind_of(group_v, cEC_POINT)) {
- if (argc != 1)
- rb_raise(rb_eArgError, "invalid second argument");
- return ossl_ec_point_initialize_copy(self, group_v);
+ if (argc != 1)
+ rb_raise(rb_eArgError, "invalid second argument");
+ return ossl_ec_point_initialize_copy(self, group_v);
}
GetECGroup(group_v, group);
if (argc == 1) {
- point = EC_POINT_new(group);
- if (!point)
- ossl_raise(eEC_POINT, "EC_POINT_new");
+ point = EC_POINT_new(group);
+ if (!point)
+ ossl_raise(eEC_POINT, "EC_POINT_new");
}
else {
- if (rb_obj_is_kind_of(arg2, cBN)) {
- point = EC_POINT_bn2point(group, GetBNPtr(arg2), NULL, ossl_bn_ctx);
- if (!point)
- ossl_raise(eEC_POINT, "EC_POINT_bn2point");
- }
- else {
- StringValue(arg2);
- point = EC_POINT_new(group);
- if (!point)
- ossl_raise(eEC_POINT, "EC_POINT_new");
- if (!EC_POINT_oct2point(group, point,
- (unsigned char *)RSTRING_PTR(arg2),
- RSTRING_LEN(arg2), ossl_bn_ctx)) {
- EC_POINT_free(point);
- ossl_raise(eEC_POINT, "EC_POINT_oct2point");
- }
- }
+ if (rb_obj_is_kind_of(arg2, cBN)) {
+ point = EC_POINT_bn2point(group, GetBNPtr(arg2), NULL, ossl_bn_ctx);
+ if (!point)
+ ossl_raise(eEC_POINT, "EC_POINT_bn2point");
+ }
+ else {
+ StringValue(arg2);
+ point = EC_POINT_new(group);
+ if (!point)
+ ossl_raise(eEC_POINT, "EC_POINT_new");
+ if (!EC_POINT_oct2point(group, point,
+ (unsigned char *)RSTRING_PTR(arg2),
+ RSTRING_LEN(arg2), ossl_bn_ctx)) {
+ EC_POINT_free(point);
+ ossl_raise(eEC_POINT, "EC_POINT_oct2point");
+ }
+ }
}
RTYPEDDATA_DATA(self) = point;
@@ -1258,6 +1262,7 @@ static VALUE ossl_ec_point_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+/* :nodoc: */
static VALUE
ossl_ec_point_initialize_copy(VALUE self, VALUE other)
{
@@ -1267,7 +1272,7 @@ ossl_ec_point_initialize_copy(VALUE self, VALUE other)
TypedData_Get_Struct(self, EC_POINT, &ossl_ec_point_type, point_new);
if (point_new)
- ossl_raise(eEC_POINT, "EC::Point already initialized");
+ ossl_raise(eEC_POINT, "EC::Point already initialized");
GetECPoint(other, point);
group_v = rb_obj_dup(rb_attr_get(other, id_i_group));
@@ -1275,7 +1280,7 @@ ossl_ec_point_initialize_copy(VALUE self, VALUE other)
point_new = EC_POINT_dup(point, group);
if (!point_new)
- ossl_raise(eEC_POINT, "EC_POINT_dup");
+ ossl_raise(eEC_POINT, "EC_POINT_dup");
RTYPEDDATA_DATA(self) = point_new;
rb_ivar_set(self, id_i_group, group_v);
@@ -1302,9 +1307,9 @@ static VALUE ossl_ec_point_eql(VALUE a, VALUE b)
GetECGroup(group_v1, group);
switch (EC_POINT_cmp(group, point1, point2, ossl_bn_ctx)) {
- case 0: return Qtrue;
- case 1: return Qfalse;
- default: ossl_raise(eEC_POINT, "EC_POINT_cmp");
+ case 0: return Qtrue;
+ case 1: return Qfalse;
+ default: ossl_raise(eEC_POINT, "EC_POINT_cmp");
}
UNREACHABLE;
@@ -1323,9 +1328,9 @@ static VALUE ossl_ec_point_is_at_infinity(VALUE self)
GetECPointGroup(self, group);
switch (EC_POINT_is_at_infinity(group, point)) {
- case 1: return Qtrue;
- case 0: return Qfalse;
- default: ossl_raise(eEC_POINT, "EC_POINT_is_at_infinity");
+ case 1: return Qtrue;
+ case 0: return Qfalse;
+ default: ossl_raise(eEC_POINT, "EC_POINT_is_at_infinity");
}
UNREACHABLE;
@@ -1344,9 +1349,9 @@ static VALUE ossl_ec_point_is_on_curve(VALUE self)
GetECPointGroup(self, group);
switch (EC_POINT_is_on_curve(group, point, ossl_bn_ctx)) {
- case 1: return Qtrue;
- case 0: return Qfalse;
- default: ossl_raise(eEC_POINT, "EC_POINT_is_on_curve");
+ case 1: return Qtrue;
+ case 0: return Qfalse;
+ default: ossl_raise(eEC_POINT, "EC_POINT_is_on_curve");
}
UNREACHABLE;
@@ -1367,7 +1372,7 @@ static VALUE ossl_ec_point_make_affine(VALUE self)
GetECPointGroup(self, group);
rb_warn("OpenSSL::PKey::EC::Point#make_affine! is deprecated");
-#if !OSSL_OPENSSL_PREREQ(3, 0, 0)
+#if !defined(OSSL_HAVE_IMMUTABLE_PKEY) && !defined(OPENSSL_IS_AWSLC)
if (EC_POINT_make_affine(group, point, ossl_bn_ctx) != 1)
ossl_raise(eEC_POINT, "EC_POINT_make_affine");
#endif
@@ -1438,12 +1443,12 @@ ossl_ec_point_to_octet_string(VALUE self, VALUE conversion_form)
len = EC_POINT_point2oct(group, point, form, NULL, 0, ossl_bn_ctx);
if (!len)
- ossl_raise(eEC_POINT, "EC_POINT_point2oct");
+ ossl_raise(eEC_POINT, "EC_POINT_point2oct");
str = rb_str_new(NULL, (long)len);
if (!EC_POINT_point2oct(group, point, form,
- (unsigned char *)RSTRING_PTR(str), len,
- ossl_bn_ctx))
- ossl_raise(eEC_POINT, "EC_POINT_point2oct");
+ (unsigned char *)RSTRING_PTR(str), len,
+ ossl_bn_ctx))
+ ossl_raise(eEC_POINT, "EC_POINT_point2oct");
return str;
}
@@ -1478,7 +1483,6 @@ static VALUE ossl_ec_point_add(VALUE self, VALUE other)
/*
* call-seq:
* point.mul(bn1 [, bn2]) => point
- * point.mul(bns, points [, bn2]) => point
*
* Performs elliptic curve point multiplication.
*
@@ -1486,11 +1490,9 @@ static VALUE ossl_ec_point_add(VALUE self, VALUE other)
* generator of the group of _point_. _bn2_ may be omitted, and in that case,
* the result is just <tt>bn1 * point</tt>.
*
- * The second form calculates <tt>bns[0] * point + bns[1] * points[0] + ...
- * + bns[-1] * points[-1] + bn2 * G</tt>. _bn2_ may be omitted. _bns_ must be
- * an array of OpenSSL::BN. _points_ must be an array of
- * OpenSSL::PKey::EC::Point. Please note that <tt>points[0]</tt> is not
- * multiplied by <tt>bns[0]</tt>, but <tt>bns[1]</tt>.
+ * Before version 4.0.0, and when compiled with OpenSSL 1.1.1 or older, this
+ * method allowed another form:
+ * point.mul(bns, points [, bn2]) => point
*/
static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self)
{
@@ -1508,62 +1510,15 @@ static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self)
GetECPoint(result, point_result);
rb_scan_args(argc, argv, "12", &arg1, &arg2, &arg3);
- if (!RB_TYPE_P(arg1, T_ARRAY)) {
- BIGNUM *bn = GetBNPtr(arg1);
+ if (RB_TYPE_P(arg1, T_ARRAY) || argc > 2)
+ rb_raise(rb_eNotImpError, "OpenSSL::PKey::EC::Point#mul with arrays " \
+ "is no longer supported");
- if (!NIL_P(arg2))
- bn_g = GetBNPtr(arg2);
- if (EC_POINT_mul(group, point_result, bn_g, point_self, bn, ossl_bn_ctx) != 1)
- ossl_raise(eEC_POINT, NULL);
- } else {
-#if (defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3) || defined(LIBRESSL_VERSION_NUMBER)
- rb_raise(rb_eNotImpError, "calling #mul with arrays is not" \
- "supported by this OpenSSL version");
-#else
- /*
- * bignums | arg1[0] | arg1[1] | arg1[2] | ...
- * points | self | arg2[0] | arg2[1] | ...
- */
- long i, num;
- VALUE bns_tmp, tmp_p, tmp_b;
- const EC_POINT **points;
- const BIGNUM **bignums;
-
- Check_Type(arg1, T_ARRAY);
- Check_Type(arg2, T_ARRAY);
- if (RARRAY_LEN(arg1) != RARRAY_LEN(arg2) + 1) /* arg2 must be 1 larger */
- ossl_raise(rb_eArgError, "bns must be 1 longer than points; see the documentation");
-
- rb_warning("OpenSSL::PKey::EC::Point#mul(ary, ary) is deprecated; " \
- "use #mul(bn) form instead");
-
- num = RARRAY_LEN(arg1);
- bns_tmp = rb_ary_tmp_new(num);
- bignums = ALLOCV_N(const BIGNUM *, tmp_b, num);
- for (i = 0; i < num; i++) {
- VALUE item = RARRAY_AREF(arg1, i);
- bignums[i] = GetBNPtr(item);
- rb_ary_push(bns_tmp, item);
- }
-
- points = ALLOCV_N(const EC_POINT *, tmp_p, num);
- points[0] = point_self; /* self */
- for (i = 0; i < num - 1; i++)
- GetECPoint(RARRAY_AREF(arg2, i), points[i + 1]);
-
- if (!NIL_P(arg3))
- bn_g = GetBNPtr(arg3);
-
- if (EC_POINTs_mul(group, point_result, bn_g, num, points, bignums, ossl_bn_ctx) != 1) {
- ALLOCV_END(tmp_b);
- ALLOCV_END(tmp_p);
- ossl_raise(eEC_POINT, NULL);
- }
-
- ALLOCV_END(tmp_b);
- ALLOCV_END(tmp_p);
-#endif
- }
+ BIGNUM *bn = GetBNPtr(arg1);
+ if (!NIL_P(arg2))
+ bn_g = GetBNPtr(arg2);
+ if (EC_POINT_mul(group, point_result, bn_g, point_self, bn, ossl_bn_ctx) != 1)
+ ossl_raise(eEC_POINT, NULL);
return result;
}
@@ -1571,15 +1526,6 @@ static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self)
void Init_ossl_ec(void)
{
#undef rb_intern
-#if 0
- mPKey = rb_define_module_under(mOSSL, "PKey");
- cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject);
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
- ePKeyError = rb_define_class_under(mPKey, "PKeyError", eOSSLError);
-#endif
-
- eECError = rb_define_class_under(mPKey, "ECError", ePKeyError);
-
/*
* Document-class: OpenSSL::PKey::EC
*
@@ -1601,17 +1547,15 @@ void Init_ossl_ec(void)
eEC_GROUP = rb_define_class_under(cEC_GROUP, "Error", eOSSLError);
eEC_POINT = rb_define_class_under(cEC_POINT, "Error", eOSSLError);
- s_GFp = rb_intern("GFp");
- s_GF2m = rb_intern("GF2m");
+ sym_GFp = ID2SYM(rb_intern_const("GFp"));
+ sym_GF2m = ID2SYM(rb_intern_const("GF2m"));
- ID_uncompressed = rb_intern("uncompressed");
- ID_compressed = rb_intern("compressed");
- ID_hybrid = rb_intern("hybrid");
+ sym_uncompressed = ID2SYM(rb_intern_const("uncompressed"));
+ sym_compressed = ID2SYM(rb_intern_const("compressed"));
+ sym_hybrid = ID2SYM(rb_intern_const("hybrid"));
rb_define_const(cEC, "NAMED_CURVE", INT2NUM(OPENSSL_EC_NAMED_CURVE));
-#if defined(OPENSSL_EC_EXPLICIT_CURVE)
rb_define_const(cEC, "EXPLICIT_CURVE", INT2NUM(OPENSSL_EC_EXPLICIT_CURVE));
-#endif
rb_define_singleton_method(cEC, "builtin_curves", ossl_s_builtin_curves, 0);
diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c
index 389f76f309..039b2c6a34 100644
--- a/ext/openssl/ossl_pkey_rsa.c
+++ b/ext/openssl/ossl_pkey_rsa.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -14,13 +14,15 @@
#define GetPKeyRSA(obj, pkey) do { \
GetPKey((obj), (pkey)); \
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA) { /* PARANOIA? */ \
- ossl_raise(rb_eRuntimeError, "THIS IS NOT A RSA!") ; \
+ ossl_raise(rb_eRuntimeError, "THIS IS NOT A RSA!") ; \
} \
} while (0)
#define GetRSA(obj, rsa) do { \
EVP_PKEY *_pkey; \
GetPKeyRSA((obj), _pkey); \
(rsa) = EVP_PKEY_get0_RSA(_pkey); \
+ if ((rsa) == NULL) \
+ ossl_raise(ePKeyError, "failed to get RSA from EVP_PKEY"); \
} while (0)
static inline int
@@ -42,7 +44,6 @@ RSA_PRIVATE(VALUE obj, OSSL_3_const RSA *rsa)
* Classes
*/
VALUE cRSA;
-VALUE eRSAError;
/*
* Private
@@ -59,6 +60,7 @@ VALUE eRSAError;
* 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.
+ * This form is not compatible with OpenSSL 3.0 or later.
*
* If called with a String, tries to parse as DER or PEM encoding of an \RSA key.
* Note that if _password_ is not specified, but the key is encrypted with a
@@ -89,10 +91,15 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
/* 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();
+#ifdef OSSL_HAVE_IMMUTABLE_PKEY
+ rb_raise(rb_eArgError, "OpenSSL::PKey::RSA.new cannot be called " \
+ "without arguments; pkeys are immutable with OpenSSL 3.0");
+#else
+ rsa = RSA_new();
if (!rsa)
- ossl_raise(eRSAError, "RSA_new");
+ ossl_raise(ePKeyError, "RSA_new");
goto legacy;
+#endif
}
pass = ossl_pem_passwd_value(pass);
@@ -113,12 +120,12 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
pkey = ossl_pkey_read_generic(in, pass);
BIO_free(in);
if (!pkey)
- ossl_raise(eRSAError, "Neither PUB key nor PRIV key");
+ ossl_raise(ePKeyError, "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));
+ rb_raise(ePKeyError, "incorrect pkey type: %s", OBJ_nid2sn(type));
}
RTYPEDDATA_DATA(self) = pkey;
return self;
@@ -129,13 +136,14 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
if (!pkey || EVP_PKEY_assign_RSA(pkey, rsa) != 1) {
EVP_PKEY_free(pkey);
RSA_free(rsa);
- ossl_raise(eRSAError, "EVP_PKEY_assign_RSA");
+ ossl_raise(ePKeyError, "EVP_PKEY_assign_RSA");
}
RTYPEDDATA_DATA(self) = pkey;
return self;
}
#ifndef HAVE_EVP_PKEY_DUP
+/* :nodoc: */
static VALUE
ossl_rsa_initialize_copy(VALUE self, VALUE other)
{
@@ -151,12 +159,12 @@ ossl_rsa_initialize_copy(VALUE self, VALUE other)
(d2i_of_void *)d2i_RSAPrivateKey,
(char *)rsa);
if (!rsa_new)
- ossl_raise(eRSAError, "ASN1_dup");
+ ossl_raise(ePKeyError, "ASN1_dup");
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");
+ ossl_raise(ePKeyError, "EVP_PKEY_assign_RSA");
}
RTYPEDDATA_DATA(self) = pkey;
@@ -311,7 +319,7 @@ ossl_rsa_to_der(VALUE self)
* Signs _data_ using the Probabilistic Signature Scheme (RSA-PSS) and returns
* the calculated signature.
*
- * RSAError will be raised if an error occurs.
+ * PKeyError will be raised if an error occurs.
*
* See #verify_pss for the verification operation.
*
@@ -340,7 +348,7 @@ ossl_rsa_to_der(VALUE self)
static VALUE
ossl_rsa_sign_pss(int argc, VALUE *argv, VALUE self)
{
- VALUE digest, data, options, kwargs[2], signature;
+ VALUE digest, data, options, kwargs[2], signature, mgf1md_holder, md_holder;
static ID kwargs_ids[2];
EVP_PKEY *pkey;
EVP_PKEY_CTX *pkey_ctx;
@@ -350,46 +358,46 @@ ossl_rsa_sign_pss(int argc, VALUE *argv, VALUE self)
int salt_len;
if (!kwargs_ids[0]) {
- kwargs_ids[0] = rb_intern_const("salt_length");
- kwargs_ids[1] = rb_intern_const("mgf1_hash");
+ kwargs_ids[0] = rb_intern_const("salt_length");
+ kwargs_ids[1] = rb_intern_const("mgf1_hash");
}
rb_scan_args(argc, argv, "2:", &digest, &data, &options);
rb_get_kwargs(options, kwargs_ids, 2, 0, kwargs);
if (kwargs[0] == ID2SYM(rb_intern("max")))
- salt_len = -2; /* RSA_PSS_SALTLEN_MAX_SIGN */
+ salt_len = -2; /* RSA_PSS_SALTLEN_MAX_SIGN */
else if (kwargs[0] == ID2SYM(rb_intern("digest")))
- salt_len = -1; /* RSA_PSS_SALTLEN_DIGEST */
+ salt_len = -1; /* RSA_PSS_SALTLEN_DIGEST */
else
- salt_len = NUM2INT(kwargs[0]);
- mgf1md = ossl_evp_get_digestbyname(kwargs[1]);
+ salt_len = NUM2INT(kwargs[0]);
+ mgf1md = ossl_evp_md_fetch(kwargs[1], &mgf1md_holder);
pkey = GetPrivPKeyPtr(self);
buf_len = EVP_PKEY_size(pkey);
- md = ossl_evp_get_digestbyname(digest);
+ md = ossl_evp_md_fetch(digest, &md_holder);
StringValue(data);
signature = rb_str_new(NULL, (long)buf_len);
md_ctx = EVP_MD_CTX_new();
if (!md_ctx)
- goto err;
+ goto err;
if (EVP_DigestSignInit(md_ctx, &pkey_ctx, md, NULL, pkey) != 1)
- goto err;
+ goto err;
if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1)
- goto err;
+ goto err;
if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len) != 1)
- goto err;
+ goto err;
if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1md) != 1)
- goto err;
+ goto err;
if (EVP_DigestSignUpdate(md_ctx, RSTRING_PTR(data), RSTRING_LEN(data)) != 1)
- goto err;
+ goto err;
if (EVP_DigestSignFinal(md_ctx, (unsigned char *)RSTRING_PTR(signature), &buf_len) != 1)
- goto err;
+ goto err;
rb_str_set_len(signature, (long)buf_len);
@@ -398,7 +406,7 @@ ossl_rsa_sign_pss(int argc, VALUE *argv, VALUE self)
err:
EVP_MD_CTX_free(md_ctx);
- ossl_raise(eRSAError, NULL);
+ ossl_raise(ePKeyError, NULL);
}
/*
@@ -408,7 +416,7 @@ ossl_rsa_sign_pss(int argc, VALUE *argv, VALUE self)
* Verifies _data_ using the Probabilistic Signature Scheme (RSA-PSS).
*
* The return value is +true+ if the signature is valid, +false+ otherwise.
- * RSAError will be raised if an error occurs.
+ * PKeyError will be raised if an error occurs.
*
* See #sign_pss for the signing operation and an example code.
*
@@ -427,7 +435,7 @@ ossl_rsa_sign_pss(int argc, VALUE *argv, VALUE self)
static VALUE
ossl_rsa_verify_pss(int argc, VALUE *argv, VALUE self)
{
- VALUE digest, signature, data, options, kwargs[2];
+ VALUE digest, signature, data, options, kwargs[2], mgf1md_holder, md_holder;
static ID kwargs_ids[2];
EVP_PKEY *pkey;
EVP_PKEY_CTX *pkey_ctx;
@@ -436,98 +444,61 @@ ossl_rsa_verify_pss(int argc, VALUE *argv, VALUE self)
int result, salt_len;
if (!kwargs_ids[0]) {
- kwargs_ids[0] = rb_intern_const("salt_length");
- kwargs_ids[1] = rb_intern_const("mgf1_hash");
+ kwargs_ids[0] = rb_intern_const("salt_length");
+ kwargs_ids[1] = rb_intern_const("mgf1_hash");
}
rb_scan_args(argc, argv, "3:", &digest, &signature, &data, &options);
rb_get_kwargs(options, kwargs_ids, 2, 0, kwargs);
if (kwargs[0] == ID2SYM(rb_intern("auto")))
- salt_len = -2; /* RSA_PSS_SALTLEN_AUTO */
+ salt_len = -2; /* RSA_PSS_SALTLEN_AUTO */
else if (kwargs[0] == ID2SYM(rb_intern("digest")))
- salt_len = -1; /* RSA_PSS_SALTLEN_DIGEST */
+ salt_len = -1; /* RSA_PSS_SALTLEN_DIGEST */
else
- salt_len = NUM2INT(kwargs[0]);
- mgf1md = ossl_evp_get_digestbyname(kwargs[1]);
+ salt_len = NUM2INT(kwargs[0]);
+ mgf1md = ossl_evp_md_fetch(kwargs[1], &mgf1md_holder);
GetPKey(self, pkey);
- md = ossl_evp_get_digestbyname(digest);
+ md = ossl_evp_md_fetch(digest, &md_holder);
StringValue(signature);
StringValue(data);
md_ctx = EVP_MD_CTX_new();
if (!md_ctx)
- goto err;
+ goto err;
if (EVP_DigestVerifyInit(md_ctx, &pkey_ctx, md, NULL, pkey) != 1)
- goto err;
+ goto err;
if (EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) != 1)
- goto err;
+ goto err;
if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, salt_len) != 1)
- goto err;
+ goto err;
if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, mgf1md) != 1)
- goto err;
+ goto err;
if (EVP_DigestVerifyUpdate(md_ctx, RSTRING_PTR(data), RSTRING_LEN(data)) != 1)
- goto err;
+ goto err;
result = EVP_DigestVerifyFinal(md_ctx,
- (unsigned char *)RSTRING_PTR(signature),
- RSTRING_LEN(signature));
+ (unsigned char *)RSTRING_PTR(signature),
+ RSTRING_LEN(signature));
+ EVP_MD_CTX_free(md_ctx);
switch (result) {
case 0:
- ossl_clear_error();
- EVP_MD_CTX_free(md_ctx);
- return Qfalse;
+ ossl_clear_error();
+ return Qfalse;
case 1:
- EVP_MD_CTX_free(md_ctx);
- return Qtrue;
+ return Qtrue;
default:
- goto err;
+ ossl_raise(ePKeyError, "EVP_DigestVerifyFinal");
}
err:
EVP_MD_CTX_free(md_ctx);
- ossl_raise(eRSAError, NULL);
-}
-
-/*
- * call-seq:
- * rsa.params => hash
- *
- * THIS METHOD IS INSECURE, PRIVATE INFORMATION CAN LEAK OUT!!!
- *
- * Stores all parameters of key to the hash. The hash has keys 'n', 'e', 'd',
- * 'p', 'q', 'dmp1', 'dmq1', 'iqmp'.
- *
- * Don't use :-)) (It's up to you)
- */
-static VALUE
-ossl_rsa_get_params(VALUE self)
-{
- OSSL_3_const RSA *rsa;
- VALUE hash;
- const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp;
-
- GetRSA(self, rsa);
- RSA_get0_key(rsa, &n, &e, &d);
- RSA_get0_factors(rsa, &p, &q);
- RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
-
- hash = rb_hash_new();
- rb_hash_aset(hash, rb_str_new2("n"), ossl_bn_new(n));
- rb_hash_aset(hash, rb_str_new2("e"), ossl_bn_new(e));
- rb_hash_aset(hash, rb_str_new2("d"), ossl_bn_new(d));
- rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(p));
- rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(q));
- rb_hash_aset(hash, rb_str_new2("dmp1"), ossl_bn_new(dmp1));
- rb_hash_aset(hash, rb_str_new2("dmq1"), ossl_bn_new(dmq1));
- rb_hash_aset(hash, rb_str_new2("iqmp"), ossl_bn_new(iqmp));
-
- return hash;
+ ossl_raise(ePKeyError, NULL);
}
/*
@@ -565,20 +536,6 @@ OSSL_PKEY_BN_DEF3(rsa, RSA, crt_params, dmp1, dmq1, iqmp)
void
Init_ossl_rsa(void)
{
-#if 0
- mPKey = rb_define_module_under(mOSSL, "PKey");
- cPKey = rb_define_class_under(mPKey, "PKey", rb_cObject);
- ePKeyError = rb_define_class_under(mPKey, "PKeyError", eOSSLError);
-#endif
-
- /* Document-class: OpenSSL::PKey::RSAError
- *
- * Generic exception that is raised if an operation on an RSA PKey
- * fails unexpectedly or in case an instantiation of an instance of RSA
- * fails due to non-conformant input data.
- */
- eRSAError = rb_define_class_under(mPKey, "RSAError", ePKeyError);
-
/* Document-class: OpenSSL::PKey::RSA
*
* RSA is an asymmetric public key algorithm that has been formalized in
@@ -617,8 +574,6 @@ Init_ossl_rsa(void)
rb_define_method(cRSA, "set_factors", ossl_rsa_set_factors, 2);
rb_define_method(cRSA, "set_crt_params", ossl_rsa_set_crt_params, 3);
- rb_define_method(cRSA, "params", ossl_rsa_get_params, 0);
-
/*
* TODO: Test it
rb_define_method(cRSA, "blinding_on!", ossl_rsa_blinding_on, 0);
diff --git a/ext/openssl/ossl_provider.c b/ext/openssl/ossl_provider.c
index 981c6ccdc7..ea5abb8e48 100644
--- a/ext/openssl/ossl_provider.c
+++ b/ext/openssl/ossl_provider.c
@@ -1,12 +1,10 @@
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
#ifdef OSSL_USE_PROVIDER
-# include <openssl/provider.h>
-
#define NewProvider(klass) \
TypedData_Wrap_Struct((klass), &ossl_provider_type, 0)
#define SetProvider(obj, provider) do { \
@@ -187,11 +185,6 @@ ossl_provider_inspect(VALUE self)
void
Init_ossl_provider(void)
{
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
-#endif
-
cProvider = rb_define_class_under(mOSSL, "Provider", rb_cObject);
eProviderError = rb_define_class_under(cProvider, "ProviderError", eOSSLError);
diff --git a/ext/openssl/ossl_rand.c b/ext/openssl/ossl_rand.c
index 659dc818b6..753f8b25f7 100644
--- a/ext/openssl/ossl_rand.c
+++ b/ext/openssl/ossl_rand.c
@@ -5,12 +5,12 @@
* All rights reserved.
*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
-VALUE mRandom;
-VALUE eRandomError;
+static VALUE mRandom;
+static VALUE eRandomError;
/*
* call-seq:
@@ -68,7 +68,7 @@ static VALUE
ossl_rand_load_file(VALUE self, VALUE filename)
{
if(!RAND_load_file(StringValueCStr(filename), -1)) {
- ossl_raise(eRandomError, NULL);
+ ossl_raise(eRandomError, NULL);
}
return Qtrue;
}
@@ -85,14 +85,14 @@ static VALUE
ossl_rand_write_file(VALUE self, VALUE filename)
{
if (RAND_write_file(StringValueCStr(filename)) == -1) {
- ossl_raise(eRandomError, NULL);
+ ossl_raise(eRandomError, NULL);
}
return Qtrue;
}
/*
* call-seq:
- * random_bytes(length) -> string
+ * random_bytes(length) -> string
*
* Generates a String with _length_ number of cryptographically strong
* pseudo-random bytes.
@@ -112,9 +112,9 @@ ossl_rand_bytes(VALUE self, VALUE len)
str = rb_str_new(0, n);
ret = RAND_bytes((unsigned char *)RSTRING_PTR(str), n);
if (ret == 0) {
- ossl_raise(eRandomError, "RAND_bytes");
+ ossl_raise(eRandomError, "RAND_bytes");
} else if (ret == -1) {
- ossl_raise(eRandomError, "RAND_bytes is not supported");
+ ossl_raise(eRandomError, "RAND_bytes is not supported");
}
return str;
@@ -131,7 +131,7 @@ static VALUE
ossl_rand_egd(VALUE self, VALUE filename)
{
if (RAND_egd(StringValueCStr(filename)) == -1) {
- ossl_raise(eRandomError, NULL);
+ ossl_raise(eRandomError, NULL);
}
return Qtrue;
}
@@ -151,7 +151,7 @@ ossl_rand_egd_bytes(VALUE self, VALUE filename, VALUE len)
int n = NUM2INT(len);
if (RAND_egd_bytes(StringValueCStr(filename), n) == -1) {
- ossl_raise(eRandomError, NULL);
+ ossl_raise(eRandomError, NULL);
}
return Qtrue;
}
@@ -175,11 +175,6 @@ ossl_rand_status(VALUE self)
void
Init_ossl_rand(void)
{
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
-#endif
-
mRandom = rb_define_module_under(mOSSL, "Random");
eRandomError = rb_define_class_under(mRandom, "RandomError", eOSSLError);
@@ -189,9 +184,7 @@ Init_ossl_rand(void)
rb_define_module_function(mRandom, "load_random_file", ossl_rand_load_file, 1);
rb_define_module_function(mRandom, "write_random_file", ossl_rand_write_file, 1);
rb_define_module_function(mRandom, "random_bytes", ossl_rand_bytes, 1);
-#if OPENSSL_VERSION_NUMBER < 0x10101000 || defined(LIBRESSL_VERSION_NUMBER)
rb_define_alias(rb_singleton_class(mRandom), "pseudo_bytes", "random_bytes");
-#endif
#ifdef HAVE_RAND_EGD
rb_define_module_function(mRandom, "egd", ossl_rand_egd, 1);
rb_define_module_function(mRandom, "egd_bytes", ossl_rand_egd_bytes, 2);
diff --git a/ext/openssl/ossl_rand.h b/ext/openssl/ossl_rand.h
index 8f77a3b239..294986d017 100644
--- a/ext/openssl/ossl_rand.h
+++ b/ext/openssl/ossl_rand.h
@@ -5,14 +5,11 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_RAND_H_)
#define _OSSL_RAND_H_
-extern VALUE mRandom;
-extern VALUE eRandomError;
-
void Init_ossl_rand(void);
#endif /* _OSSL_RAND_H_ */
diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c
index d68c64d5fb..630d46e43f 100644
--- a/ext/openssl/ossl_ssl.c
+++ b/ext/openssl/ossl_ssl.c
@@ -7,7 +7,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -18,11 +18,6 @@
# define OSSL_USE_NEXTPROTONEG
#endif
-#if !defined(TLS1_3_VERSION) && \
- OSSL_LIBRESSL_PREREQ(3, 2, 0) && !OSSL_LIBRESSL_PREREQ(3, 4, 0)
-# define TLS1_3_VERSION 0x0304
-#endif
-
#ifdef _WIN32
# define TO_SOCKET(s) _get_osfhandle(s)
#else
@@ -30,32 +25,30 @@
#endif
#define GetSSLCTX(obj, ctx) do { \
- TypedData_Get_Struct((obj), SSL_CTX, &ossl_sslctx_type, (ctx)); \
+ TypedData_Get_Struct((obj), SSL_CTX, &ossl_sslctx_type, (ctx)); \
} while (0)
VALUE mSSL;
static VALUE eSSLError;
-VALUE cSSLContext;
+static VALUE cSSLContext;
VALUE cSSLSocket;
static VALUE eSSLErrorWaitReadable;
static VALUE eSSLErrorWaitWritable;
-static ID id_call, ID_callback_state, id_tmp_dh_callback,
- id_npn_protocols_encoded, id_each;
+static ID id_call, ID_callback_state, 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_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,
- id_i_verify_hostname, id_i_keylog_cb;
+ 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_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,
+ id_i_verify_hostname, id_i_keylog_cb, id_i_tmp_dh_callback;
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;
@@ -85,127 +78,24 @@ ossl_sslctx_s_alloc(VALUE klass)
{
SSL_CTX *ctx;
long mode = 0 |
- SSL_MODE_ENABLE_PARTIAL_WRITE |
- SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
- SSL_MODE_RELEASE_BUFFERS;
+ SSL_MODE_ENABLE_PARTIAL_WRITE |
+ SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
+ SSL_MODE_RELEASE_BUFFERS;
VALUE obj;
obj = TypedData_Wrap_Struct(klass, &ossl_sslctx_type, 0);
-#if OPENSSL_VERSION_NUMBER >= 0x10100000 || defined(LIBRESSL_VERSION_NUMBER)
ctx = SSL_CTX_new(TLS_method());
-#else
- ctx = SSL_CTX_new(SSLv23_method());
-#endif
if (!ctx) {
ossl_raise(eSSLError, "SSL_CTX_new");
}
SSL_CTX_set_mode(ctx, mode);
+ SSL_CTX_set_dh_auto(ctx, 1);
RTYPEDDATA_DATA(obj) = ctx;
SSL_CTX_set_ex_data(ctx, ossl_sslctx_ex_ptr_idx, (void *)obj);
-#if !defined(OPENSSL_NO_EC) && OPENSSL_VERSION_NUMBER < 0x10100000 && \
- !defined(LIBRESSL_VERSION_NUMBER)
- /* We use SSL_CTX_set1_curves_list() to specify the curve used in ECDH. It
- * allows to specify multiple curve names and OpenSSL will select
- * automatically from them. In OpenSSL 1.0.2, the automatic selection has to
- * be enabled explicitly. OpenSSL 1.1.0 and LibreSSL 2.6.1 removed the knob
- * and it is always enabled. To uniform the behavior, we enable the
- * automatic selection also in 1.0.2. Users can still disable ECDH by
- * removing ECDH cipher suites by SSLContext#ciphers=. */
- if (!SSL_CTX_set_ecdh_auto(ctx, 1))
- ossl_raise(eSSLError, "SSL_CTX_set_ecdh_auto");
-#endif
-
return obj;
}
-static int
-parse_proto_version(VALUE str)
-{
- int i;
- static const struct {
- const char *name;
- int version;
- } map[] = {
- { "SSL2", SSL2_VERSION },
- { "SSL3", SSL3_VERSION },
- { "TLS1", TLS1_VERSION },
- { "TLS1_1", TLS1_1_VERSION },
- { "TLS1_2", TLS1_2_VERSION },
-#ifdef TLS1_3_VERSION
- { "TLS1_3", TLS1_3_VERSION },
-#endif
- };
-
- if (NIL_P(str))
- return 0;
- if (RB_INTEGER_TYPE_P(str))
- return NUM2INT(str);
-
- if (SYMBOL_P(str))
- str = rb_sym2str(str);
- StringValue(str);
- for (i = 0; i < numberof(map); i++)
- if (!strncmp(map[i].name, RSTRING_PTR(str), RSTRING_LEN(str)))
- return map[i].version;
- rb_raise(rb_eArgError, "unrecognized version %+"PRIsVALUE, str);
-}
-
-/*
- * call-seq:
- * ctx.set_minmax_proto_version(min, max) -> nil
- *
- * Sets the minimum and maximum supported protocol versions. See #min_version=
- * and #max_version=.
- */
-static VALUE
-ossl_sslctx_set_minmax_proto_version(VALUE self, VALUE min_v, VALUE max_v)
-{
- SSL_CTX *ctx;
- int min, max;
-
- GetSSLCTX(self, ctx);
- min = parse_proto_version(min_v);
- max = parse_proto_version(max_v);
-
-#ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION
- if (!SSL_CTX_set_min_proto_version(ctx, min))
- ossl_raise(eSSLError, "SSL_CTX_set_min_proto_version");
- if (!SSL_CTX_set_max_proto_version(ctx, max))
- ossl_raise(eSSLError, "SSL_CTX_set_max_proto_version");
-#else
- {
- unsigned long sum = 0, opts = 0;
- int i;
- static const struct {
- int ver;
- unsigned long opts;
- } options_map[] = {
- { SSL2_VERSION, SSL_OP_NO_SSLv2 },
- { SSL3_VERSION, SSL_OP_NO_SSLv3 },
- { TLS1_VERSION, SSL_OP_NO_TLSv1 },
- { TLS1_1_VERSION, SSL_OP_NO_TLSv1_1 },
- { TLS1_2_VERSION, SSL_OP_NO_TLSv1_2 },
-# if defined(TLS1_3_VERSION)
- { TLS1_3_VERSION, SSL_OP_NO_TLSv1_3 },
-# endif
- };
-
- for (i = 0; i < numberof(options_map); i++) {
- sum |= options_map[i].opts;
- if ((min && min > options_map[i].ver) ||
- (max && max < options_map[i].ver)) {
- opts |= options_map[i].opts;
- }
- }
- SSL_CTX_clear_options(ctx, sum);
- SSL_CTX_set_options(ctx, opts);
- }
-#endif
-
- return Qnil;
-}
-
static VALUE
ossl_call_client_cert_cb(VALUE obj)
{
@@ -214,7 +104,7 @@ ossl_call_client_cert_cb(VALUE obj)
ctx_obj = rb_attr_get(obj, id_i_context);
cb = rb_attr_get(ctx_obj, id_i_client_cert_cb);
if (NIL_P(cb))
- return Qnil;
+ return Qnil;
ary = rb_funcallv(cb, id_call, 1, &obj);
Check_Type(ary, T_ARRAY);
@@ -232,7 +122,7 @@ ossl_client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
ret = rb_protect(ossl_call_client_cert_cb, obj, NULL);
if (NIL_P(ret))
- return 0;
+ return 0;
*x509 = DupX509CertPtr(RARRAY_AREF(ret, 0));
*pkey = DupPKeyPtr(RARRAY_AREF(ret, 1));
@@ -243,8 +133,6 @@ ossl_client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
#if !defined(OPENSSL_NO_DH)
struct tmp_dh_callback_args {
VALUE ssl_obj;
- ID id;
- int type;
int is_export;
int keylength;
};
@@ -253,48 +141,36 @@ 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;
+ VALUE ctx_obj, cb, obj;
+ const DH *dh;
- cb = rb_funcall(args->ssl_obj, args->id, 0);
+ ctx_obj = rb_attr_get(args->ssl_obj, id_i_context);
+ cb = rb_attr_get(ctx_obj, id_i_tmp_dh_callback);
if (NIL_P(cb))
- 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 (VALUE)NULL;
+ return (VALUE)NULL;
+
+ obj = rb_funcall(cb, id_call, 3, args->ssl_obj, INT2NUM(args->is_export),
+ INT2NUM(args->keylength));
+ // TODO: We should riase if obj is not DH
+ dh = EVP_PKEY_get0_DH(GetPKeyPtr(obj));
+ if (!dh)
+ ossl_clear_error();
- return (VALUE)pkey;
+ return (VALUE)dh;
}
-#endif
-#if !defined(OPENSSL_NO_DH)
static DH *
ossl_tmp_dh_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_dh_callback;
- args.is_export = is_export;
- args.keylength = keylength;
- args.type = EVP_PKEY_DH;
-
- pkey = (EVP_PKEY *)rb_protect(ossl_call_tmp_dh_callback,
- (VALUE)&args, &state);
+ VALUE rb_ssl = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
+ struct tmp_dh_callback_args args = {rb_ssl, is_export, keylength};
+ VALUE ret = rb_protect(ossl_call_tmp_dh_callback, (VALUE)&args, &state);
if (state) {
- rb_ivar_set(rb_ssl, ID_callback_state, INT2NUM(state));
- return NULL;
+ rb_ivar_set(rb_ssl, ID_callback_state, INT2NUM(state));
+ return NULL;
}
- if (!pkey)
- return NULL;
-
- return (DH *)EVP_PKEY_get0_DH(pkey);
+ return (DH *)ret;
}
#endif /* OPENSSL_NO_DH */
@@ -310,13 +186,13 @@ call_verify_certificate_identity(VALUE ctx_v)
hostname = rb_attr_get(ssl_obj, id_i_hostname);
if (!RTEST(hostname)) {
- rb_warning("verify_hostname requires hostname to be set");
- return Qtrue;
+ rb_warning("verify_hostname requires hostname to be set");
+ return Qtrue;
}
cert_obj = ossl_x509_new(X509_STORE_CTX_get_current_cert(ctx));
return rb_funcall(mSSL, rb_intern("verify_certificate_identity"), 2,
- cert_obj, hostname);
+ cert_obj, hostname);
}
static int
@@ -327,25 +203,21 @@ ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
int status;
ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
- cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_vcb_idx);
ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
sslctx_obj = rb_attr_get(ssl_obj, id_i_context);
+ cb = rb_attr_get(sslctx_obj, id_i_verify_callback);
verify_hostname = rb_attr_get(sslctx_obj, id_i_verify_hostname);
if (preverify_ok && RTEST(verify_hostname) && !SSL_is_server(ssl) &&
- !X509_STORE_CTX_get_error_depth(ctx)) {
- ret = rb_protect(call_verify_certificate_identity, (VALUE)ctx, &status);
- if (status) {
- rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(status));
- return 0;
- }
+ !X509_STORE_CTX_get_error_depth(ctx)) {
+ ret = rb_protect(call_verify_certificate_identity, (VALUE)ctx, &status);
+ if (status) {
+ rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(status));
+ return 0;
+ }
if (ret != Qtrue) {
preverify_ok = 0;
-#if defined(X509_V_ERR_HOSTNAME_MISMATCH)
X509_STORE_CTX_set_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH);
-#else
- X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
-#endif
}
}
@@ -367,11 +239,7 @@ ossl_call_session_get_cb(VALUE ary)
}
static SSL_SESSION *
-#if defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER >= 0x10100000
ossl_sslctx_session_get_cb(SSL *ssl, const unsigned char *buf, int len, int *copy)
-#else
-ossl_sslctx_session_get_cb(SSL *ssl, unsigned char *buf, int len, int *copy)
-#endif
{
VALUE ary, ssl_obj, ret_obj;
SSL_SESSION *sess;
@@ -444,7 +312,7 @@ ossl_sslctx_session_new_cb(SSL *ssl, SSL_SESSION *sess)
return 0;
}
-#if OPENSSL_VERSION_NUMBER >= 0x10101000 && !defined(LIBRESSL_VERSION_NUMBER)
+#if !OSSL_IS_LIBRESSL
/*
* It is only compatible with OpenSSL >= 1.1.1. Even if LibreSSL implements
* SSL_CTX_set_keylog_callback() from v3.4.2, it does nothing (see
@@ -517,7 +385,7 @@ ossl_sslctx_session_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess)
* when SSL_CTX_free() is called.
*/
if (rb_during_gc())
- return;
+ return;
OSSL_Debug("SSL SESSION remove callback entered");
@@ -548,8 +416,9 @@ ossl_sslctx_add_extra_chain_cert_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arg))
GetSSLCTX(arg, ctx);
x509 = DupX509CertPtr(i);
- if(!SSL_CTX_add_extra_chain_cert(ctx, x509)){
- ossl_raise(eSSLError, NULL);
+ if (!SSL_CTX_add_extra_chain_cert(ctx, x509)) {
+ X509_free(x509);
+ ossl_raise(eSSLError, "SSL_CTX_add_extra_chain_cert");
}
return i;
@@ -558,52 +427,42 @@ ossl_sslctx_add_extra_chain_cert_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arg))
static VALUE ossl_sslctx_setup(VALUE self);
static VALUE
-ossl_call_servername_cb(VALUE ary)
+ossl_call_servername_cb(VALUE arg)
{
- VALUE ssl_obj, sslctx_obj, cb, ret_obj;
-
- Check_Type(ary, T_ARRAY);
- ssl_obj = rb_ary_entry(ary, 0);
+ SSL *ssl = (void *)arg;
+ const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
+ if (!servername)
+ return Qnil;
- sslctx_obj = rb_attr_get(ssl_obj, id_i_context);
- cb = rb_attr_get(sslctx_obj, id_i_servername_cb);
- if (NIL_P(cb)) return Qnil;
+ VALUE ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
+ VALUE sslctx_obj = rb_attr_get(ssl_obj, id_i_context);
+ VALUE cb = rb_attr_get(sslctx_obj, id_i_servername_cb);
+ VALUE ary = rb_assoc_new(ssl_obj, rb_str_new_cstr(servername));
- ret_obj = rb_funcallv(cb, id_call, 1, &ary);
+ VALUE ret_obj = rb_funcallv(cb, id_call, 1, &ary);
if (rb_obj_is_kind_of(ret_obj, cSSLContext)) {
- SSL *ssl;
SSL_CTX *ctx2;
-
ossl_sslctx_setup(ret_obj);
- GetSSL(ssl_obj, ssl);
GetSSLCTX(ret_obj, ctx2);
- SSL_set_SSL_CTX(ssl, ctx2);
+ if (!SSL_set_SSL_CTX(ssl, ctx2))
+ ossl_raise(eSSLError, "SSL_set_SSL_CTX");
rb_ivar_set(ssl_obj, id_i_context, ret_obj);
} else if (!NIL_P(ret_obj)) {
- ossl_raise(rb_eArgError, "servername_cb must return an "
- "OpenSSL::SSL::SSLContext object or nil");
+ ossl_raise(rb_eArgError, "servername_cb must return an "
+ "OpenSSL::SSL::SSLContext object or nil");
}
- return ret_obj;
+ return Qnil;
}
static int
ssl_servername_cb(SSL *ssl, int *ad, void *arg)
{
- VALUE ary, ssl_obj;
- int state = 0;
- const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
-
- if (!servername)
- return SSL_TLSEXT_ERR_OK;
-
- ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
- ary = rb_ary_new2(2);
- rb_ary_push(ary, ssl_obj);
- rb_ary_push(ary, rb_str_new2(servername));
+ int state;
- rb_protect(ossl_call_servername_cb, ary, &state);
+ rb_protect(ossl_call_servername_cb, (VALUE)ssl, &state);
if (state) {
+ VALUE ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state));
return SSL_TLSEXT_ERR_ALERT_FATAL;
}
@@ -630,7 +489,7 @@ ssl_npn_encode_protocol_i(RB_BLOCK_CALL_FUNC_ARGLIST(cur, encoded))
int len = RSTRING_LENINT(cur);
char len_byte;
if (len < 1 || len > 255)
- ossl_raise(eSSLError, "Advertised protocol must have length 1..255");
+ ossl_raise(eSSLError, "Advertised protocol must have length 1..255");
/* Encode the length byte */
len_byte = len;
rb_str_buf_cat(encoded, &len_byte, 1);
@@ -664,16 +523,16 @@ npn_select_cb_common_i(VALUE tmp)
/* assume OpenSSL verifies this format */
/* The format is len_1|proto_1|...|len_n|proto_n */
while (in < in_end) {
- l = *in++;
- rb_ary_push(protocols, rb_str_new((const char *)in, l));
- in += l;
+ l = *in++;
+ rb_ary_push(protocols, rb_str_new((const char *)in, l));
+ in += l;
}
selected = rb_funcallv(args->cb, id_call, 1, &protocols);
StringValue(selected);
len = RSTRING_LEN(selected);
if (len < 1 || len >= 256) {
- ossl_raise(eSSLError, "Selected protocol name must have length 1..255");
+ ossl_raise(eSSLError, "Selected protocol name must have length 1..255");
}
return selected;
@@ -681,8 +540,8 @@ npn_select_cb_common_i(VALUE tmp)
static int
ssl_npn_select_cb_common(SSL *ssl, VALUE cb, const unsigned char **out,
- unsigned char *outlen, const unsigned char *in,
- unsigned int inlen)
+ unsigned char *outlen, const unsigned char *in,
+ unsigned int inlen)
{
VALUE selected;
int status;
@@ -694,10 +553,10 @@ ssl_npn_select_cb_common(SSL *ssl, VALUE cb, const unsigned char **out,
selected = rb_protect(npn_select_cb_common_i, (VALUE)&args, &status);
if (status) {
- VALUE ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
+ VALUE ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx);
- rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(status));
- return SSL_TLSEXT_ERR_ALERT_FATAL;
+ rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(status));
+ return SSL_TLSEXT_ERR_ALERT_FATAL;
}
*out = (unsigned char *)RSTRING_PTR(selected);
@@ -709,7 +568,7 @@ ssl_npn_select_cb_common(SSL *ssl, VALUE cb, const unsigned char **out,
#ifdef OSSL_USE_NEXTPROTONEG
static int
ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen,
- void *arg)
+ void *arg)
{
VALUE protocols = rb_attr_get((VALUE)arg, id_npn_protocols_encoded);
@@ -721,7 +580,7 @@ ssl_npn_advertise_cb(SSL *ssl, const unsigned char **out, unsigned int *outlen,
static int
ssl_npn_select_cb(SSL *ssl, unsigned char **out, unsigned char *outlen,
- const unsigned char *in, unsigned int inlen, void *arg)
+ const unsigned char *in, unsigned int inlen, void *arg)
{
VALUE sslctx_obj, cb;
@@ -729,13 +588,13 @@ ssl_npn_select_cb(SSL *ssl, unsigned char **out, unsigned char *outlen,
cb = rb_attr_get(sslctx_obj, id_i_npn_select_cb);
return ssl_npn_select_cb_common(ssl, cb, (const unsigned char **)out,
- outlen, in, inlen);
+ outlen, in, inlen);
}
#endif
static int
ssl_alpn_select_cb(SSL *ssl, const unsigned char **out, unsigned char *outlen,
- const unsigned char *in, unsigned int inlen, void *arg)
+ const unsigned char *in, unsigned int inlen, void *arg)
{
VALUE sslctx_obj, cb;
@@ -752,12 +611,15 @@ ssl_info_cb(const SSL *ssl, int where, int val)
int is_server = SSL_is_server((SSL *)ssl);
if (is_server && where & SSL_CB_HANDSHAKE_START) {
- ssl_renegotiation_cb(ssl);
+ ssl_renegotiation_cb(ssl);
}
}
/*
- * Gets various OpenSSL options.
+ * call-seq:
+ * ctx.options -> integer
+ *
+ * Gets various \OpenSSL options.
*/
static VALUE
ossl_sslctx_get_options(VALUE self)
@@ -772,7 +634,17 @@ ossl_sslctx_get_options(VALUE self)
}
/*
- * Sets various OpenSSL options.
+ * call-seq:
+ * ctx.options = integer
+ *
+ * Sets various \OpenSSL options. The options are a bit field and can be
+ * combined with the bitwise OR operator (<tt>|</tt>). Available options are
+ * defined as constants in OpenSSL::SSL that begin with +OP_+.
+ *
+ * For backwards compatibility, passing +nil+ has the same effect as passing
+ * OpenSSL::SSL::OP_ALL.
+ *
+ * See also man page SSL_CTX_set_options(3).
*/
static VALUE
ossl_sslctx_set_options(VALUE self, VALUE options)
@@ -785,9 +657,9 @@ ossl_sslctx_set_options(VALUE self, VALUE options)
SSL_CTX_clear_options(ctx, SSL_CTX_get_options(ctx));
if (NIL_P(options)) {
- SSL_CTX_set_options(ctx, SSL_OP_ALL);
+ SSL_CTX_set_options(ctx, SSL_OP_ALL);
} else {
- SSL_CTX_set_options(ctx, NUM2ULONG(options));
+ SSL_CTX_set_options(ctx, NUM2ULONG(options));
}
return self;
@@ -817,23 +689,26 @@ ossl_sslctx_setup(VALUE self)
GetSSLCTX(self, ctx);
#if !defined(OPENSSL_NO_DH)
- SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback);
+ if (!NIL_P(rb_attr_get(self, id_i_tmp_dh_callback))) {
+ SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback);
+ SSL_CTX_set_dh_auto(ctx, 0);
+ }
#endif
-#ifdef HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH
+#if !defined(OPENSSL_IS_AWSLC) /* AWS-LC has no support for TLS 1.3 PHA. */
SSL_CTX_set_post_handshake_auth(ctx, 1);
#endif
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);
- X509_STORE_up_ref(store);
+ X509_STORE *store = GetX509StorePtr(val); /* NO NEED TO DUP */
+ SSL_CTX_set_cert_store(ctx, store);
+ X509_STORE_up_ref(store);
}
val = rb_attr_get(self, id_i_extra_chain_cert);
if(!NIL_P(val)){
- rb_block_call(val, rb_intern("each"), 0, 0, ossl_sslctx_add_extra_chain_cert_i, self);
+ rb_block_call(val, rb_intern("each"), 0, 0, ossl_sslctx_add_extra_chain_cert_i, self);
}
/* private key may be bundled in certificate file. */
@@ -857,22 +732,22 @@ ossl_sslctx_setup(VALUE self)
val = rb_attr_get(self, id_i_client_ca);
if(!NIL_P(val)){
- if (RB_TYPE_P(val, T_ARRAY)) {
- for(i = 0; i < RARRAY_LEN(val); i++){
- client_ca = GetX509CertPtr(RARRAY_AREF(val, i));
- if (!SSL_CTX_add_client_CA(ctx, client_ca)){
- /* Copies X509_NAME => FREE it. */
- ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
- }
- }
+ if (RB_TYPE_P(val, T_ARRAY)) {
+ for(i = 0; i < RARRAY_LEN(val); i++){
+ client_ca = GetX509CertPtr(RARRAY_AREF(val, i));
+ if (!SSL_CTX_add_client_CA(ctx, client_ca)){
+ /* Copies X509_NAME => FREE it. */
+ ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
+ }
+ }
}
- else{
- client_ca = GetX509CertPtr(val); /* NO DUP NEEDED. */
+ else{
+ client_ca = GetX509CertPtr(val); /* NO DUP NEEDED. */
if (!SSL_CTX_add_client_CA(ctx, client_ca)){
- /* Copies X509_NAME => FREE it. */
- ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
+ /* Copies X509_NAME => FREE it. */
+ ossl_raise(eSSLError, "SSL_CTX_add_client_CA");
}
- }
+ }
}
val = rb_attr_get(self, id_i_ca_file);
@@ -895,7 +770,7 @@ ossl_sslctx_setup(VALUE self)
verify_mode = NIL_P(val) ? SSL_VERIFY_NONE : NUM2INT(val);
SSL_CTX_set_verify(ctx, verify_mode, ossl_ssl_verify_callback);
if (RTEST(rb_attr_get(self, id_i_client_cert_cb)))
- SSL_CTX_set_client_cert_cb(ctx, ossl_client_cert_cb);
+ SSL_CTX_set_client_cert_cb(ctx, ossl_client_cert_cb);
val = rb_attr_get(self, id_i_timeout);
if(!NIL_P(val)) SSL_CTX_set_timeout(ctx, NUM2LONG(val));
@@ -906,63 +781,63 @@ ossl_sslctx_setup(VALUE self)
#ifdef OSSL_USE_NEXTPROTONEG
val = rb_attr_get(self, id_i_npn_protocols);
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 *)self);
- OSSL_Debug("SSL NPN advertise callback added");
+ 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 *)self);
+ OSSL_Debug("SSL NPN advertise callback added");
}
if (RTEST(rb_attr_get(self, id_i_npn_select_cb))) {
- SSL_CTX_set_next_proto_select_cb(ctx, ssl_npn_select_cb, (void *) self);
- OSSL_Debug("SSL NPN select callback added");
+ SSL_CTX_set_next_proto_select_cb(ctx, ssl_npn_select_cb, (void *) self);
+ OSSL_Debug("SSL NPN select callback added");
}
#endif
val = rb_attr_get(self, id_i_alpn_protocols);
if (!NIL_P(val)) {
- VALUE rprotos = ssl_encode_npn_protocols(val);
+ VALUE rprotos = ssl_encode_npn_protocols(val);
- /* returns 0 on success */
- if (SSL_CTX_set_alpn_protos(ctx, (unsigned char *)RSTRING_PTR(rprotos),
- RSTRING_LENINT(rprotos)))
- ossl_raise(eSSLError, "SSL_CTX_set_alpn_protos");
- OSSL_Debug("SSL ALPN values added");
+ /* returns 0 on success */
+ if (SSL_CTX_set_alpn_protos(ctx, (unsigned char *)RSTRING_PTR(rprotos),
+ RSTRING_LENINT(rprotos)))
+ ossl_raise(eSSLError, "SSL_CTX_set_alpn_protos");
+ OSSL_Debug("SSL ALPN values added");
}
if (RTEST(rb_attr_get(self, id_i_alpn_select_cb))) {
- SSL_CTX_set_alpn_select_cb(ctx, ssl_alpn_select_cb, (void *) self);
- OSSL_Debug("SSL ALPN select callback added");
+ SSL_CTX_set_alpn_select_cb(ctx, ssl_alpn_select_cb, (void *) self);
+ OSSL_Debug("SSL ALPN select callback added");
}
rb_obj_freeze(self);
val = rb_attr_get(self, id_i_session_id_context);
if (!NIL_P(val)){
- StringValue(val);
- if (!SSL_CTX_set_session_id_context(ctx, (unsigned char *)RSTRING_PTR(val),
- RSTRING_LENINT(val))){
- ossl_raise(eSSLError, "SSL_CTX_set_session_id_context");
- }
+ StringValue(val);
+ if (!SSL_CTX_set_session_id_context(ctx, (unsigned char *)RSTRING_PTR(val),
+ RSTRING_LENINT(val))){
+ ossl_raise(eSSLError, "SSL_CTX_set_session_id_context");
+ }
}
if (RTEST(rb_attr_get(self, id_i_session_get_cb))) {
- SSL_CTX_sess_set_get_cb(ctx, ossl_sslctx_session_get_cb);
- OSSL_Debug("SSL SESSION get callback added");
+ SSL_CTX_sess_set_get_cb(ctx, ossl_sslctx_session_get_cb);
+ OSSL_Debug("SSL SESSION get callback added");
}
if (RTEST(rb_attr_get(self, id_i_session_new_cb))) {
- SSL_CTX_sess_set_new_cb(ctx, ossl_sslctx_session_new_cb);
- OSSL_Debug("SSL SESSION new callback added");
+ SSL_CTX_sess_set_new_cb(ctx, ossl_sslctx_session_new_cb);
+ OSSL_Debug("SSL SESSION new callback added");
}
if (RTEST(rb_attr_get(self, id_i_session_remove_cb))) {
- SSL_CTX_sess_set_remove_cb(ctx, ossl_sslctx_session_remove_cb);
- OSSL_Debug("SSL SESSION remove callback added");
+ SSL_CTX_sess_set_remove_cb(ctx, ossl_sslctx_session_remove_cb);
+ OSSL_Debug("SSL SESSION remove callback added");
}
val = rb_attr_get(self, id_i_servername_cb);
if (!NIL_P(val)) {
SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
- OSSL_Debug("SSL TLSEXT servername callback added");
+ OSSL_Debug("SSL TLSEXT servername callback added");
}
-#if OPENSSL_VERSION_NUMBER >= 0x10101000 && !defined(LIBRESSL_VERSION_NUMBER)
+#if !OSSL_IS_LIBRESSL
/*
* It is only compatible with OpenSSL >= 1.1.1. Even if LibreSSL implements
* SSL_CTX_set_keylog_callback() from v3.4.2, it does nothing (see
@@ -977,6 +852,93 @@ ossl_sslctx_setup(VALUE self)
return Qtrue;
}
+static int
+parse_proto_version(VALUE str)
+{
+ int i;
+ static const struct {
+ const char *name;
+ int version;
+ } map[] = {
+ { "SSL2", SSL2_VERSION },
+ { "SSL3", SSL3_VERSION },
+ { "TLS1", TLS1_VERSION },
+ { "TLS1_1", TLS1_1_VERSION },
+ { "TLS1_2", TLS1_2_VERSION },
+ { "TLS1_3", TLS1_3_VERSION },
+ };
+
+ if (NIL_P(str))
+ return 0;
+ if (RB_INTEGER_TYPE_P(str))
+ return NUM2INT(str);
+
+ if (SYMBOL_P(str))
+ str = rb_sym2str(str);
+ StringValue(str);
+ for (i = 0; i < numberof(map); i++)
+ if (!strncmp(map[i].name, RSTRING_PTR(str), RSTRING_LEN(str)))
+ return map[i].version;
+ rb_raise(rb_eArgError, "unrecognized version %+"PRIsVALUE, str);
+}
+
+/*
+ * call-seq:
+ * ctx.min_version = OpenSSL::SSL::TLS1_2_VERSION
+ * ctx.min_version = :TLS1_2
+ * ctx.min_version = nil
+ *
+ * Sets the lower bound on the supported SSL/TLS protocol version. The
+ * version may be specified by an integer constant named
+ * OpenSSL::SSL::*_VERSION, a Symbol, or +nil+ which means "any version".
+ *
+ * === Example
+ * ctx = OpenSSL::SSL::SSLContext.new
+ * ctx.min_version = OpenSSL::SSL::TLS1_1_VERSION
+ * ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
+ *
+ * sock = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx)
+ * sock.connect # Initiates a connection using either TLS 1.1 or TLS 1.2
+ */
+static VALUE
+ossl_sslctx_set_min_version(VALUE self, VALUE v)
+{
+ SSL_CTX *ctx;
+ int version;
+
+ rb_check_frozen(self);
+ GetSSLCTX(self, ctx);
+ version = parse_proto_version(v);
+
+ if (!SSL_CTX_set_min_proto_version(ctx, version))
+ ossl_raise(eSSLError, "SSL_CTX_set_min_proto_version");
+ return v;
+}
+
+/*
+ * call-seq:
+ * ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
+ * ctx.max_version = :TLS1_2
+ * ctx.max_version = nil
+ *
+ * Sets the upper bound of the supported SSL/TLS protocol version. See
+ * #min_version= for the possible values.
+ */
+static VALUE
+ossl_sslctx_set_max_version(VALUE self, VALUE v)
+{
+ SSL_CTX *ctx;
+ int version;
+
+ rb_check_frozen(self);
+ GetSSLCTX(self, ctx);
+ version = parse_proto_version(v);
+
+ if (!SSL_CTX_set_max_proto_version(ctx, version))
+ ossl_raise(eSSLError, "SSL_CTX_set_max_proto_version");
+ return v;
+}
+
static VALUE
ossl_ssl_cipher_to_ary(const SSL_CIPHER *cipher)
{
@@ -1026,11 +988,10 @@ static VALUE
build_cipher_string(VALUE v)
{
VALUE str, elem;
- int i;
if (RB_TYPE_P(v, T_ARRAY)) {
str = rb_str_new(0, 0);
- for (i = 0; i < RARRAY_LEN(v); i++) {
+ for (long i = 0; i < RARRAY_LEN(v); i++) {
elem = rb_ary_entry(v, i);
if (RB_TYPE_P(elem, T_ARRAY)) elem = rb_ary_entry(elem, 0);
elem = rb_String(elem);
@@ -1051,9 +1012,14 @@ build_cipher_string(VALUE v)
* ctx.ciphers = [name, ...]
* ctx.ciphers = [[name, version, bits, alg_bits], ...]
*
- * Sets the list of available cipher suites for this context. Note in a server
- * context some ciphers require the appropriate certificates. For example, an
- * RSA cipher suite can only be chosen when an RSA certificate is available.
+ * Sets the list of available cipher suites for TLS 1.2 and below for this
+ * context.
+ *
+ * Note in a server context some ciphers require the appropriate certificates.
+ * For example, an RSA cipher suite can only be chosen when an RSA certificate
+ * is available.
+ *
+ * This method does not affect TLS 1.3 connections. See also #ciphersuites=.
*/
static VALUE
ossl_sslctx_set_ciphers(VALUE self, VALUE v)
@@ -1062,6 +1028,7 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v)
VALUE str;
rb_check_frozen(self);
+ // Assigning nil is a no-op for compatibility
if (NIL_P(v))
return v;
@@ -1074,14 +1041,12 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v)
return v;
}
-#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
/*
* call-seq:
* ctx.ciphersuites = "cipher1:cipher2:..."
* ctx.ciphersuites = [name, ...]
- * ctx.ciphersuites = [[name, version, bits, alg_bits], ...]
*
- * Sets the list of available TLSv1.3 cipher suites for this context.
+ * Sets the list of available TLS 1.3 cipher suites for this context.
*/
static VALUE
ossl_sslctx_set_ciphersuites(VALUE self, VALUE v)
@@ -1090,6 +1055,7 @@ ossl_sslctx_set_ciphersuites(VALUE self, VALUE v)
VALUE str;
rb_check_frozen(self);
+ // Assigning nil is a no-op for compatibility
if (NIL_P(v))
return v;
@@ -1101,6 +1067,62 @@ ossl_sslctx_set_ciphersuites(VALUE self, VALUE v)
return v;
}
+
+#ifdef HAVE_SSL_CTX_SET1_SIGALGS_LIST
+/*
+ * call-seq:
+ * ctx.sigalgs = "sigalg1:sigalg2:..."
+ *
+ * Sets the list of "supported signature algorithms" for this context.
+ *
+ * For a TLS client, the list is used in the "signature_algorithms" extension
+ * in the ClientHello message. For a server, the list is used by OpenSSL to
+ * determine the set of shared signature algorithms. OpenSSL will pick the most
+ * appropriate one from it.
+ *
+ * See also #client_sigalgs= for the client authentication equivalent.
+ */
+static VALUE
+ossl_sslctx_set_sigalgs(VALUE self, VALUE v)
+{
+ SSL_CTX *ctx;
+
+ rb_check_frozen(self);
+ GetSSLCTX(self, ctx);
+
+ if (!SSL_CTX_set1_sigalgs_list(ctx, StringValueCStr(v)))
+ ossl_raise(eSSLError, "SSL_CTX_set1_sigalgs_list");
+
+ return v;
+}
+#endif
+
+#ifdef HAVE_SSL_CTX_SET1_CLIENT_SIGALGS_LIST
+/*
+ * call-seq:
+ * ctx.client_sigalgs = "sigalg1:sigalg2:..."
+ *
+ * Sets the list of "supported signature algorithms" for client authentication
+ * for this context.
+ *
+ * For a TLS server, the list is sent to the client as part of the
+ * CertificateRequest message.
+ *
+ * See also #sigalgs= for the server authentication equivalent.
+ */
+static VALUE
+ossl_sslctx_set_client_sigalgs(VALUE self, VALUE v)
+{
+ SSL_CTX *ctx;
+
+ rb_check_frozen(self);
+ GetSSLCTX(self, ctx);
+
+ if (!SSL_CTX_set1_client_sigalgs_list(ctx, StringValueCStr(v)))
+ ossl_raise(eSSLError, "SSL_CTX_set1_client_sigalgs_list");
+
+ return v;
+}
#endif
#ifndef OPENSSL_NO_DH
@@ -1115,7 +1137,7 @@ ossl_sslctx_set_ciphersuites(VALUE self, VALUE v)
* 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).
+ * Added in version 3.0. See also the man page SSL_CTX_set0_tmp_dh_pkey(3).
*
* Example:
* ctx = OpenSSL::SSL::SSLContext.new
@@ -1136,7 +1158,7 @@ ossl_sslctx_set_tmp_dh(VALUE self, VALUE 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
+#ifdef HAVE_SSL_CTX_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);
@@ -1145,29 +1167,36 @@ ossl_sslctx_set_tmp_dh(VALUE self, VALUE arg)
ossl_raise(eSSLError, "SSL_CTX_set_tmp_dh");
#endif
+ // Turn off the "auto" DH parameters set by ossl_sslctx_s_alloc()
+ SSL_CTX_set_dh_auto(ctx, 0);
+
return arg;
}
#endif
-#if !defined(OPENSSL_NO_EC)
/*
* call-seq:
- * ctx.ecdh_curves = curve_list -> curve_list
+ * ctx.groups = groups_list
+ * ctx.ecdh_curves = groups_list
+ *
+ * Sets the list of supported groups for key agreement for this context.
+ *
+ * For a TLS client, the list is directly used in the "supported_groups"
+ * extension. For a server, the list is used by OpenSSL to determine the set of
+ * shared supported groups. OpenSSL will pick the most appropriate one from it.
*
- * Sets the list of "supported elliptic curves" for this context.
+ * #ecdh_curves= is a deprecated alias for #groups=.
*
- * For a TLS client, the list is directly used in the Supported Elliptic Curves
- * Extension. For a server, the list is used by OpenSSL to determine the set of
- * shared curves. OpenSSL will pick the most appropriate one from it.
+ * See also the man page SSL_CTX_set1_groups_list(3).
*
* === Example
* ctx1 = OpenSSL::SSL::SSLContext.new
- * ctx1.ecdh_curves = "X25519:P-256:P-224"
+ * ctx1.groups = "X25519:P-256:P-224"
* svr = OpenSSL::SSL::SSLServer.new(tcp_svr, ctx1)
* Thread.new { svr.accept }
*
* ctx2 = OpenSSL::SSL::SSLContext.new
- * ctx2.ecdh_curves = "P-256"
+ * ctx2.groups = "P-256"
* cli = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx2)
* cli.connect
*
@@ -1175,7 +1204,7 @@ ossl_sslctx_set_tmp_dh(VALUE self, VALUE arg)
* # => "prime256v1" (is an alias for NIST P-256)
*/
static VALUE
-ossl_sslctx_set_ecdh_curves(VALUE self, VALUE arg)
+ossl_sslctx_set_groups(VALUE self, VALUE arg)
{
SSL_CTX *ctx;
@@ -1183,13 +1212,10 @@ ossl_sslctx_set_ecdh_curves(VALUE self, VALUE arg)
GetSSLCTX(self, ctx);
StringValueCStr(arg);
- if (!SSL_CTX_set1_curves_list(ctx, RSTRING_PTR(arg)))
- ossl_raise(eSSLError, NULL);
+ if (!SSL_CTX_set1_groups_list(ctx, RSTRING_PTR(arg)))
+ ossl_raise(eSSLError, "SSL_CTX_set1_groups_list");
return arg;
}
-#else
-#define ossl_sslctx_set_ecdh_curves rb_f_notimplement
-#endif
/*
* call-seq:
@@ -1206,12 +1232,7 @@ ossl_sslctx_get_security_level(VALUE self)
GetSSLCTX(self, ctx);
-#if defined(HAVE_SSL_CTX_GET_SECURITY_LEVEL)
return INT2NUM(SSL_CTX_get_security_level(ctx));
-#else
- (void)ctx;
- return INT2FIX(0);
-#endif
}
/*
@@ -1241,14 +1262,7 @@ ossl_sslctx_set_security_level(VALUE self, VALUE value)
rb_check_frozen(self);
GetSSLCTX(self, ctx);
-#if defined(HAVE_SSL_CTX_GET_SECURITY_LEVEL)
SSL_CTX_set_security_level(ctx, NUM2INT(value));
-#else
- (void)ctx;
- if (NUM2INT(value) != 0)
- ossl_raise(rb_eNotImpError, "setting security level to other than 0 is "
- "not supported in this version of OpenSSL");
-#endif
return value;
}
@@ -1330,20 +1344,20 @@ ossl_sslctx_add_certificate(int argc, VALUE *argv, VALUE self)
pub_pkey = X509_get_pubkey(x509);
EVP_PKEY_free(pub_pkey);
if (!pub_pkey)
- rb_raise(rb_eArgError, "certificate does not contain public key");
+ rb_raise(rb_eArgError, "certificate does not contain public key");
if (EVP_PKEY_eq(pub_pkey, pkey) != 1)
- rb_raise(rb_eArgError, "public key mismatch");
+ rb_raise(rb_eArgError, "public key mismatch");
if (argc >= 3)
- extra_chain = ossl_x509_ary2sk(extra_chain_ary);
+ extra_chain = ossl_x509_ary2sk(extra_chain_ary);
if (!SSL_CTX_use_certificate(ctx, x509)) {
- sk_X509_pop_free(extra_chain, X509_free);
- ossl_raise(eSSLError, "SSL_CTX_use_certificate");
+ sk_X509_pop_free(extra_chain, X509_free);
+ ossl_raise(eSSLError, "SSL_CTX_use_certificate");
}
if (!SSL_CTX_use_PrivateKey(ctx, pkey)) {
- sk_X509_pop_free(extra_chain, X509_free);
- ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey");
+ sk_X509_pop_free(extra_chain, X509_free);
+ ossl_raise(eSSLError, "SSL_CTX_use_PrivateKey");
}
if (extra_chain && !SSL_CTX_set0_chain(ctx, extra_chain)) {
sk_X509_pop_free(extra_chain, X509_free);
@@ -1553,11 +1567,6 @@ ossl_ssl_mark(void *ptr)
{
SSL *ssl = ptr;
rb_gc_mark((VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx));
-
- // Note: this reference is stored as @verify_callback so we don't need to mark it.
- // However we do need to ensure GC compaction won't move it, hence why
- // we call rb_gc_mark here.
- rb_gc_mark((VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_vcb_idx));
}
static void
@@ -1622,37 +1631,33 @@ peeraddr_ip_str(VALUE self)
static VALUE
ossl_ssl_initialize(int argc, VALUE *argv, VALUE self)
{
- VALUE io, v_ctx, verify_cb;
+ VALUE io, v_ctx;
SSL *ssl;
SSL_CTX *ctx;
TypedData_Get_Struct(self, SSL, &ossl_ssl_type, ssl);
if (ssl)
- ossl_raise(eSSLError, "SSL already initialized");
+ ossl_raise(eSSLError, "SSL already initialized");
if (rb_scan_args(argc, argv, "11", &io, &v_ctx) == 1)
- v_ctx = rb_funcall(cSSLContext, rb_intern("new"), 0);
+ v_ctx = rb_funcall(cSSLContext, rb_intern("new"), 0);
GetSSLCTX(v_ctx, ctx);
rb_ivar_set(self, id_i_context, v_ctx);
ossl_sslctx_setup(v_ctx);
if (rb_respond_to(io, rb_intern("nonblock=")))
- rb_funcall(io, rb_intern("nonblock="), 1, Qtrue);
+ 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);
if (!ssl)
- ossl_raise(eSSLError, NULL);
+ ossl_raise(eSSLError, NULL);
RTYPEDDATA_DATA(self) = ssl;
SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void *)self);
SSL_set_info_callback(ssl, ssl_info_cb);
- verify_cb = rb_attr_get(v_ctx, id_i_verify_callback);
- // We don't need to trigger a write barrier because it's already
- // an instance variable of this object.
- SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void *)verify_cb);
rb_call_super(0, NULL);
@@ -1679,7 +1684,7 @@ ossl_ssl_setup(VALUE self)
GetSSL(self, ssl);
if (ssl_started(ssl))
- return Qtrue;
+ return Qtrue;
io = rb_attr_get(self, id_i_io);
GetOpenFile(io, fptr);
@@ -1701,14 +1706,14 @@ static void
write_would_block(int nonblock)
{
if (nonblock)
- ossl_raise(eSSLErrorWaitWritable, "write would block");
+ ossl_raise(eSSLErrorWaitWritable, "write would block");
}
static void
read_would_block(int nonblock)
{
if (nonblock)
- ossl_raise(eSSLErrorWaitReadable, "read would block");
+ ossl_raise(eSSLErrorWaitReadable, "read would block");
}
static int
@@ -1716,7 +1721,7 @@ no_exception_p(VALUE opts)
{
if (RB_TYPE_P(opts, T_HASH) &&
rb_hash_lookup2(opts, sym_exception, Qundef) == Qfalse)
- return 1;
+ return 1;
return 0;
}
@@ -1936,13 +1941,13 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
{
SSL *ssl;
int ilen;
- VALUE len, str;
+ VALUE len, str, cb_state;
VALUE opts = Qnil;
if (nonblock) {
- rb_scan_args(argc, argv, "11:", &len, &str, &opts);
+ rb_scan_args(argc, argv, "11:", &len, &str, &opts);
} else {
- rb_scan_args(argc, argv, "11", &len, &str);
+ rb_scan_args(argc, argv, "11", &len, &str);
}
GetSSL(self, ssl);
if (!ssl_started(ssl))
@@ -1950,13 +1955,13 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
ilen = NUM2INT(len);
if (NIL_P(str))
- str = rb_str_new(0, ilen);
+ str = rb_str_new(0, ilen);
else {
- StringValue(str);
- if (RSTRING_LEN(str) >= ilen)
- rb_str_modify(str);
- else
- rb_str_modify_expand(str, ilen - RSTRING_LEN(str));
+ StringValue(str);
+ if (RSTRING_LEN(str) >= ilen)
+ rb_str_modify(str);
+ else
+ rb_str_modify_expand(str, ilen - RSTRING_LEN(str));
}
if (ilen == 0) {
@@ -1966,37 +1971,41 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
VALUE io = rb_attr_get(self, id_i_io);
- rb_str_locktmp(str);
for (;;) {
+ rb_str_locktmp(str);
int nread = SSL_read(ssl, RSTRING_PTR(str), ilen);
+ rb_str_unlocktmp(str);
+
+ cb_state = rb_attr_get(self, ID_callback_state);
+ if (!NIL_P(cb_state)) {
+ rb_ivar_set(self, ID_callback_state, Qnil);
+ ossl_clear_error();
+ rb_jump_tag(NUM2INT(cb_state));
+ }
+
switch (ssl_get_error(ssl, nread)) {
case SSL_ERROR_NONE:
- rb_str_unlocktmp(str);
rb_str_set_len(str, nread);
return str;
case SSL_ERROR_ZERO_RETURN:
- rb_str_unlocktmp(str);
if (no_exception_p(opts)) { return Qnil; }
rb_eof_error();
case SSL_ERROR_WANT_WRITE:
if (nonblock) {
- rb_str_unlocktmp(str);
if (no_exception_p(opts)) { return sym_wait_writable; }
write_would_block(nonblock);
}
io_wait_writable(io);
- continue;
+ break;
case SSL_ERROR_WANT_READ:
if (nonblock) {
- rb_str_unlocktmp(str);
if (no_exception_p(opts)) { return sym_wait_readable; }
read_would_block(nonblock);
}
io_wait_readable(io);
- continue;
+ break;
case SSL_ERROR_SYSCALL:
if (!ERR_peek_error()) {
- rb_str_unlocktmp(str);
if (errno)
rb_sys_fail(0);
else {
@@ -2013,9 +2022,13 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock)
}
/* fall through */
default:
- rb_str_unlocktmp(str);
ossl_raise(eSSLError, "SSL_read");
}
+
+ // Ensure the buffer is not modified during io_wait_*able()
+ rb_str_modify(str);
+ if (rb_str_capacity(str) < (size_t)ilen)
+ rb_raise(eSSLError, "read buffer was modified");
}
}
@@ -2053,28 +2066,40 @@ ossl_ssl_read_nonblock(int argc, VALUE *argv, VALUE self)
}
static VALUE
-ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
+ossl_ssl_write_internal_safe(VALUE _args)
{
+ VALUE *args = (VALUE*)_args;
+ VALUE self = args[0];
+ VALUE str = args[1];
+ VALUE opts = args[2];
+
SSL *ssl;
rb_io_t *fptr;
int num, nonblock = opts != Qfalse;
- VALUE tmp;
+ VALUE cb_state;
GetSSL(self, ssl);
if (!ssl_started(ssl))
rb_raise(eSSLError, "SSL session is not started yet");
- tmp = rb_str_new_frozen(StringValue(str));
VALUE io = rb_attr_get(self, id_i_io);
GetOpenFile(io, fptr);
/* SSL_write(3ssl) manpage states num == 0 is undefined */
- num = RSTRING_LENINT(tmp);
+ num = RSTRING_LENINT(str);
if (num == 0)
return INT2FIX(0);
for (;;) {
- int nwritten = SSL_write(ssl, RSTRING_PTR(tmp), num);
+ int nwritten = SSL_write(ssl, RSTRING_PTR(str), num);
+
+ cb_state = rb_attr_get(self, ID_callback_state);
+ if (!NIL_P(cb_state)) {
+ rb_ivar_set(self, ID_callback_state, Qnil);
+ ossl_clear_error();
+ rb_jump_tag(NUM2INT(cb_state));
+ }
+
switch (ssl_get_error(ssl, nwritten)) {
case SSL_ERROR_NONE:
return INT2NUM(nwritten);
@@ -2107,6 +2132,28 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
}
}
+
+static VALUE
+ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts)
+{
+ StringValue(str);
+ int frozen = RB_OBJ_FROZEN(str);
+ if (!frozen) {
+ rb_str_locktmp(str);
+ }
+ int state;
+ VALUE args[3] = {self, str, opts};
+ VALUE result = rb_protect(ossl_ssl_write_internal_safe, (VALUE)args, &state);
+ if (!frozen) {
+ rb_str_unlocktmp(str);
+ }
+
+ if (state) {
+ rb_jump_tag(state);
+ }
+ return result;
+}
+
/*
* call-seq:
* ssl.syswrite(string) => Integer
@@ -2151,12 +2198,12 @@ ossl_ssl_stop(VALUE self)
GetSSL(self, ssl);
if (!ssl_started(ssl))
- return Qnil;
+ return Qnil;
ret = SSL_shutdown(ssl);
if (ret == 1) /* Have already received close_notify */
- return Qnil;
+ return Qnil;
if (ret == 0) /* Sent close_notify, but we don't wait for reply */
- return Qnil;
+ return Qnil;
/*
* XXX: Something happened. Possibly it failed because the underlying socket
@@ -2242,20 +2289,20 @@ ossl_ssl_get_peer_cert_chain(VALUE self)
num = sk_X509_num(chain);
ary = rb_ary_new2(num);
for (i = 0; i < num; i++){
- cert = sk_X509_value(chain, i);
- rb_ary_push(ary, ossl_x509_new(cert));
+ cert = sk_X509_value(chain, i);
+ rb_ary_push(ary, ossl_x509_new(cert));
}
return ary;
}
/*
-* call-seq:
-* ssl.ssl_version => String
-*
-* Returns a String representing the SSL/TLS version that was negotiated
-* for the connection, for example "TLSv1.2".
-*/
+ * call-seq:
+ * ssl.ssl_version => String
+ *
+ * Returns a String representing the SSL/TLS version that was negotiated
+ * for the connection, for example "TLSv1.2".
+ */
static VALUE
ossl_ssl_get_version(VALUE self)
{
@@ -2376,10 +2423,10 @@ ossl_ssl_set_hostname(VALUE self, VALUE arg)
GetSSL(self, ssl);
if (!NIL_P(arg))
- hostname = StringValueCStr(arg);
+ hostname = StringValueCStr(arg);
if (!SSL_set_tlsext_host_name(ssl, hostname))
- ossl_raise(eSSLError, NULL);
+ ossl_raise(eSSLError, NULL);
/* for SSLSocket#hostname */
rb_ivar_set(self, id_i_hostname, arg);
@@ -2458,7 +2505,7 @@ ossl_ssl_get_peer_finished(VALUE self)
/*
* call-seq:
- * ssl.client_ca => [x509name, ...]
+ * ssl.client_ca => [x509name, ...] or nil
*
* Returns the list of client CAs. Please note that in contrast to
* SSLContext#client_ca= no array of X509::Certificate is returned but
@@ -2476,6 +2523,8 @@ ossl_ssl_get_client_ca_list(VALUE self)
GetSSL(self, ssl);
ca = SSL_get_client_CA_list(ssl);
+ if (!ca)
+ return Qnil;
return ossl_x509name_sk2ary(ca);
}
@@ -2498,9 +2547,9 @@ ossl_ssl_npn_protocol(VALUE self)
SSL_get0_next_proto_negotiated(ssl, &out, &outlen);
if (!outlen)
- return Qnil;
+ return Qnil;
else
- return rb_str_new((const char *) out, outlen);
+ return rb_str_new((const char *) out, outlen);
}
# endif
@@ -2522,9 +2571,9 @@ ossl_ssl_alpn_protocol(VALUE self)
SSL_get0_alpn_selected(ssl, &out, &outlen);
if (!outlen)
- return Qnil;
+ return Qnil;
else
- return rb_str_new((const char *) out, outlen);
+ return rb_str_new((const char *) out, outlen);
}
/*
@@ -2557,15 +2606,15 @@ ossl_ssl_export_keying_material(int argc, VALUE *argv, VALUE self)
str = rb_str_new(0, len);
p = (unsigned char *)RSTRING_PTR(str);
if (!NIL_P(context)) {
- use_ctx = 1;
- StringValue(context);
- ctx = (unsigned char *)RSTRING_PTR(context);
- ctx_len = RSTRING_LEN(context);
+ use_ctx = 1;
+ StringValue(context);
+ ctx = (unsigned char *)RSTRING_PTR(context);
+ ctx_len = RSTRING_LEN(context);
}
ret = SSL_export_keying_material(ssl, p, len, (char *)RSTRING_PTR(label),
- RSTRING_LENINT(label), ctx, ctx_len, use_ctx);
+ RSTRING_LENINT(label), ctx, ctx_len, use_ctx);
if (ret == 0 || ret == -1) {
- ossl_raise(eSSLError, "SSL_export_keying_material");
+ ossl_raise(eSSLError, "SSL_export_keying_material");
}
return str;
}
@@ -2584,17 +2633,77 @@ ossl_ssl_tmp_key(VALUE self)
GetSSL(self, ssl);
if (!SSL_get_server_tmp_key(ssl, &key))
- return Qnil;
- return ossl_pkey_new(key);
+ return Qnil;
+ return ossl_pkey_wrap(key);
+}
+
+#ifdef HAVE_SSL_GET0_PEER_SIGNATURE_NAME
+/*
+ * call-seq:
+ * ssl.sigalg => String or nil
+ *
+ * Returns the signature algorithm name, the IANA name of the signature scheme
+ * used by the local to sign the TLS handshake.
+ */
+static VALUE
+ossl_ssl_get_sigalg(VALUE self)
+{
+ SSL *ssl;
+ const char *name;
+
+ GetSSL(self, ssl);
+ if (!SSL_get0_signature_name(ssl, &name))
+ return Qnil;
+ return rb_str_new_cstr(name);
+}
+
+/*
+ * call-seq:
+ * ssl.peer_sigalg => String or nil
+ *
+ * Returns the signature algorithm name, the IANA name of the signature scheme
+ * used by the peer to sign the TLS handshake.
+ */
+static VALUE
+ossl_ssl_get_peer_sigalg(VALUE self)
+{
+ SSL *ssl;
+ const char *name;
+
+ GetSSL(self, ssl);
+ if (!SSL_get0_peer_signature_name(ssl, &name))
+ return Qnil;
+ return rb_str_new_cstr(name);
+}
+#endif
+
+#ifdef HAVE_SSL_GET0_GROUP_NAME
+/*
+ * call-seq:
+ * ssl.group => String or nil
+ *
+ * Returns the name of the group that was used for the key agreement of the
+ * current TLS session establishment.
+ */
+static VALUE
+ossl_ssl_get_group(VALUE self)
+{
+ SSL *ssl;
+ const char *name;
+
+ GetSSL(self, ssl);
+ if (!(name = SSL_get0_group_name(ssl)))
+ return Qnil;
+ return rb_str_new_cstr(name);
}
+#endif
+
#endif /* !defined(OPENSSL_NO_SOCK) */
void
Init_ossl_ssl(void)
{
#if 0
- mOSSL = rb_define_module("OpenSSL");
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
rb_mWaitReadable = rb_define_module_under(rb_cIO, "WaitReadable");
rb_mWaitWritable = rb_define_module_under(rb_cIO, "WaitWritable");
#endif
@@ -2603,15 +2712,12 @@ Init_ossl_ssl(void)
id_call = rb_intern_const("call");
ID_callback_state = rb_intern_const("callback_state");
- ossl_ssl_ex_vcb_idx = SSL_get_ex_new_index(0, (void *)"ossl_ssl_ex_vcb_idx", 0, 0, 0);
- if (ossl_ssl_ex_vcb_idx < 0)
- ossl_raise(rb_eRuntimeError, "SSL_get_ex_new_index");
ossl_ssl_ex_ptr_idx = SSL_get_ex_new_index(0, (void *)"ossl_ssl_ex_ptr_idx", 0, 0, 0);
if (ossl_ssl_ex_ptr_idx < 0)
- ossl_raise(rb_eRuntimeError, "SSL_get_ex_new_index");
+ ossl_raise(rb_eRuntimeError, "SSL_get_ex_new_index");
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");
+ ossl_raise(rb_eRuntimeError, "SSL_CTX_get_ex_new_index");
/* Document-module: OpenSSL::SSL
*
@@ -2749,6 +2855,23 @@ Init_ossl_ssl(void)
*/
rb_attr(cSSLContext, rb_intern_const("client_cert_cb"), 1, 1, Qfalse);
+#ifndef OPENSSL_NO_DH
+ /*
+ * A callback invoked when DH parameters are required for ephemeral DH key
+ * exchange.
+ *
+ * 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.
+ *
+ * <b>Deprecated in version 3.0.</b> Use #tmp_dh= instead.
+ */
+ rb_attr(cSSLContext, rb_intern_const("tmp_dh_callback"), 1, 1, Qfalse);
+#endif
+
/*
* Sets the context in which a session can be reused. This allows
* sessions for multiple applications to be distinguished, for example, by
@@ -2891,17 +3014,22 @@ Init_ossl_ssl(void)
rb_define_alias(cSSLContext, "ssl_timeout", "timeout");
rb_define_alias(cSSLContext, "ssl_timeout=", "timeout=");
- rb_define_private_method(cSSLContext, "set_minmax_proto_version",
- ossl_sslctx_set_minmax_proto_version, 2);
+ rb_define_method(cSSLContext, "min_version=", ossl_sslctx_set_min_version, 1);
+ rb_define_method(cSSLContext, "max_version=", ossl_sslctx_set_max_version, 1);
rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0);
rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1);
-#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES
rb_define_method(cSSLContext, "ciphersuites=", ossl_sslctx_set_ciphersuites, 1);
+#ifdef HAVE_SSL_CTX_SET1_SIGALGS_LIST // Not in LibreSSL yet
+ rb_define_method(cSSLContext, "sigalgs=", ossl_sslctx_set_sigalgs, 1);
+#endif
+#ifdef HAVE_SSL_CTX_SET1_CLIENT_SIGALGS_LIST // Not in LibreSSL or AWS-LC yet
+ rb_define_method(cSSLContext, "client_sigalgs=", ossl_sslctx_set_client_sigalgs, 1);
#endif
#ifndef OPENSSL_NO_DH
rb_define_method(cSSLContext, "tmp_dh=", ossl_sslctx_set_tmp_dh, 1);
#endif
- rb_define_method(cSSLContext, "ecdh_curves=", ossl_sslctx_set_ecdh_curves, 1);
+ rb_define_method(cSSLContext, "groups=", ossl_sslctx_set_groups, 1);
+ rb_define_alias(cSSLContext, "ecdh_curves=", "groups=");
rb_define_method(cSSLContext, "security_level", ossl_sslctx_get_security_level, 0);
rb_define_method(cSSLContext, "security_level=", ossl_sslctx_set_security_level, 1);
#ifdef SSL_MODE_SEND_FALLBACK_SCSV
@@ -3008,6 +3136,13 @@ Init_ossl_ssl(void)
# ifdef OSSL_USE_NEXTPROTONEG
rb_define_method(cSSLSocket, "npn_protocol", ossl_ssl_npn_protocol, 0);
# endif
+#ifdef HAVE_SSL_GET0_PEER_SIGNATURE_NAME
+ rb_define_method(cSSLSocket, "sigalg", ossl_ssl_get_sigalg, 0);
+ rb_define_method(cSSLSocket, "peer_sigalg", ossl_ssl_get_peer_sigalg, 0);
+#endif
+#ifdef HAVE_SSL_GET0_GROUP_NAME
+ rb_define_method(cSSLSocket, "group", ossl_ssl_get_group, 0);
+#endif
rb_define_const(mSSL, "VERIFY_NONE", INT2NUM(SSL_VERIFY_NONE));
rb_define_const(mSSL, "VERIFY_PEER", INT2NUM(SSL_VERIFY_PEER));
@@ -3033,7 +3168,7 @@ Init_ossl_ssl(void)
#ifdef SSL_OP_DISABLE_TLSEXT_CA_NAMES /* OpenSSL 3.0 */
rb_define_const(mSSL, "OP_DISABLE_TLSEXT_CA_NAMES", ULONG2NUM(SSL_OP_DISABLE_TLSEXT_CA_NAMES));
#endif
-#ifdef SSL_OP_ALLOW_NO_DHE_KEX /* OpenSSL 1.1.1 */
+#ifdef SSL_OP_ALLOW_NO_DHE_KEX /* OpenSSL 1.1.1, missing in LibreSSL */
rb_define_const(mSSL, "OP_ALLOW_NO_DHE_KEX", ULONG2NUM(SSL_OP_ALLOW_NO_DHE_KEX));
#endif
rb_define_const(mSSL, "OP_DONT_INSERT_EMPTY_FRAGMENTS", ULONG2NUM(SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS));
@@ -3041,28 +3176,26 @@ Init_ossl_ssl(void)
rb_define_const(mSSL, "OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION", ULONG2NUM(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION));
rb_define_const(mSSL, "OP_NO_COMPRESSION", ULONG2NUM(SSL_OP_NO_COMPRESSION));
rb_define_const(mSSL, "OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION", ULONG2NUM(SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION));
-#ifdef SSL_OP_NO_ENCRYPT_THEN_MAC /* OpenSSL 1.1.1 */
+#ifdef SSL_OP_NO_ENCRYPT_THEN_MAC /* OpenSSL 1.1.1, missing in LibreSSL */
rb_define_const(mSSL, "OP_NO_ENCRYPT_THEN_MAC", ULONG2NUM(SSL_OP_NO_ENCRYPT_THEN_MAC));
#endif
-#ifdef SSL_OP_ENABLE_MIDDLEBOX_COMPAT /* OpenSSL 1.1.1 */
+#ifdef SSL_OP_ENABLE_MIDDLEBOX_COMPAT /* OpenSSL 1.1.1, missing in LibreSSL */
rb_define_const(mSSL, "OP_ENABLE_MIDDLEBOX_COMPAT", ULONG2NUM(SSL_OP_ENABLE_MIDDLEBOX_COMPAT));
#endif
-#ifdef SSL_OP_PRIORITIZE_CHACHA /* OpenSSL 1.1.1 */
+#ifdef SSL_OP_PRIORITIZE_CHACHA /* OpenSSL 1.1.1, missing in LibreSSL */
rb_define_const(mSSL, "OP_PRIORITIZE_CHACHA", ULONG2NUM(SSL_OP_PRIORITIZE_CHACHA));
#endif
-#ifdef SSL_OP_NO_ANTI_REPLAY /* OpenSSL 1.1.1 */
+#ifdef SSL_OP_NO_ANTI_REPLAY /* OpenSSL 1.1.1, missing in LibreSSL */
rb_define_const(mSSL, "OP_NO_ANTI_REPLAY", ULONG2NUM(SSL_OP_NO_ANTI_REPLAY));
#endif
rb_define_const(mSSL, "OP_NO_SSLv3", ULONG2NUM(SSL_OP_NO_SSLv3));
rb_define_const(mSSL, "OP_NO_TLSv1", ULONG2NUM(SSL_OP_NO_TLSv1));
rb_define_const(mSSL, "OP_NO_TLSv1_1", ULONG2NUM(SSL_OP_NO_TLSv1_1));
rb_define_const(mSSL, "OP_NO_TLSv1_2", ULONG2NUM(SSL_OP_NO_TLSv1_2));
-#ifdef SSL_OP_NO_TLSv1_3 /* OpenSSL 1.1.1 */
rb_define_const(mSSL, "OP_NO_TLSv1_3", ULONG2NUM(SSL_OP_NO_TLSv1_3));
-#endif
rb_define_const(mSSL, "OP_CIPHER_SERVER_PREFERENCE", ULONG2NUM(SSL_OP_CIPHER_SERVER_PREFERENCE));
rb_define_const(mSSL, "OP_TLS_ROLLBACK_BUG", ULONG2NUM(SSL_OP_TLS_ROLLBACK_BUG));
-#ifdef SSL_OP_NO_RENEGOTIATION /* OpenSSL 1.1.1 */
+#ifdef SSL_OP_NO_RENEGOTIATION /* OpenSSL 1.1.1, missing in LibreSSL */
rb_define_const(mSSL, "OP_NO_RENEGOTIATION", ULONG2NUM(SSL_OP_NO_RENEGOTIATION));
#endif
rb_define_const(mSSL, "OP_CRYPTOPRO_TLSEXT_BUG", ULONG2NUM(SSL_OP_CRYPTOPRO_TLSEXT_BUG));
@@ -3124,17 +3257,14 @@ Init_ossl_ssl(void)
rb_define_const(mSSL, "TLS1_1_VERSION", INT2NUM(TLS1_1_VERSION));
/* TLS 1.2 */
rb_define_const(mSSL, "TLS1_2_VERSION", INT2NUM(TLS1_2_VERSION));
-#ifdef TLS1_3_VERSION /* OpenSSL 1.1.1 */
/* TLS 1.3 */
rb_define_const(mSSL, "TLS1_3_VERSION", INT2NUM(TLS1_3_VERSION));
-#endif
sym_exception = ID2SYM(rb_intern_const("exception"));
sym_wait_readable = ID2SYM(rb_intern_const("wait_readable"));
sym_wait_writable = ID2SYM(rb_intern_const("wait_writable"));
- 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");
@@ -3165,6 +3295,7 @@ Init_ossl_ssl(void)
DefIVarID(servername_cb);
DefIVarID(verify_hostname);
DefIVarID(keylog_cb);
+ DefIVarID(tmp_dh_callback);
DefIVarID(io);
DefIVarID(context);
diff --git a/ext/openssl/ossl_ssl.h b/ext/openssl/ossl_ssl.h
index 535c56097c..a87e62d450 100644
--- a/ext/openssl/ossl_ssl.h
+++ b/ext/openssl/ossl_ssl.h
@@ -5,23 +5,23 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_SSL_H_)
#define _OSSL_SSL_H_
#define GetSSL(obj, ssl) do { \
- TypedData_Get_Struct((obj), SSL, &ossl_ssl_type, (ssl)); \
- if (!(ssl)) { \
- ossl_raise(rb_eRuntimeError, "SSL is not initialized"); \
- } \
+ TypedData_Get_Struct((obj), SSL, &ossl_ssl_type, (ssl)); \
+ if (!(ssl)) { \
+ ossl_raise(rb_eRuntimeError, "SSL is not initialized"); \
+ } \
} while (0)
#define GetSSLSession(obj, sess) do { \
- TypedData_Get_Struct((obj), SSL_SESSION, &ossl_ssl_session_type, (sess)); \
- if (!(sess)) { \
- ossl_raise(rb_eRuntimeError, "SSL Session wasn't initialized."); \
- } \
+ TypedData_Get_Struct((obj), SSL_SESSION, &ossl_ssl_session_type, (sess)); \
+ if (!(sess)) { \
+ ossl_raise(rb_eRuntimeError, "SSL Session wasn't initialized."); \
+ } \
} while (0)
extern const rb_data_type_t ossl_ssl_type;
diff --git a/ext/openssl/ossl_ssl_session.c b/ext/openssl/ossl_ssl_session.c
index c5df902c60..8a2fbf4100 100644
--- a/ext/openssl/ossl_ssl_session.c
+++ b/ext/openssl/ossl_ssl_session.c
@@ -17,14 +17,14 @@ ossl_ssl_session_free(void *ptr)
const rb_data_type_t ossl_ssl_session_type = {
"OpenSSL/SSL/Session",
{
- 0, ossl_ssl_session_free,
+ 0, ossl_ssl_session_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
static VALUE ossl_ssl_session_alloc(VALUE klass)
{
- return TypedData_Wrap_Struct(klass, &ossl_ssl_session_type, NULL);
+ return TypedData_Wrap_Struct(klass, &ossl_ssl_session_type, NULL);
}
/*
@@ -69,6 +69,7 @@ ossl_ssl_session_initialize(VALUE self, VALUE arg1)
return self;
}
+/* :nodoc: */
static VALUE
ossl_ssl_session_initialize_copy(VALUE self, VALUE other)
{
@@ -79,9 +80,9 @@ ossl_ssl_session_initialize_copy(VALUE self, VALUE other)
GetSSLSession(other, sess_other);
sess_new = ASN1_dup((i2d_of_void *)i2d_SSL_SESSION, (d2i_of_void *)d2i_SSL_SESSION,
- (char *)sess_other);
+ (char *)sess_other);
if (!sess_new)
- ossl_raise(eSSLSession, "ASN1_dup");
+ ossl_raise(eSSLSession, "ASN1_dup");
RTYPEDDATA_DATA(self) = sess_new;
SSL_SESSION_free(sess);
@@ -98,9 +99,9 @@ ossl_SSL_SESSION_cmp(const SSL_SESSION *a, const SSL_SESSION *b)
const unsigned char *b_sid = SSL_SESSION_get_id(b, &b_len);
if (SSL_SESSION_get_protocol_version(a) != SSL_SESSION_get_protocol_version(b))
- return 1;
+ return 1;
if (a_len != b_len)
- return 1;
+ return 1;
return CRYPTO_memcmp(a_sid, b_sid, a_len);
}
@@ -113,15 +114,15 @@ ossl_SSL_SESSION_cmp(const SSL_SESSION *a, const SSL_SESSION *b)
*/
static VALUE ossl_ssl_session_eq(VALUE val1, VALUE val2)
{
- SSL_SESSION *ctx1, *ctx2;
+ SSL_SESSION *ctx1, *ctx2;
- GetSSLSession(val1, ctx1);
- GetSSLSession(val2, ctx2);
+ GetSSLSession(val1, ctx1);
+ GetSSLSession(val2, ctx2);
- switch (ossl_SSL_SESSION_cmp(ctx1, ctx2)) {
- case 0: return Qtrue;
- default: return Qfalse;
- }
+ switch (ossl_SSL_SESSION_cmp(ctx1, ctx2)) {
+ case 0: return Qtrue;
+ default: return Qfalse;
+ }
}
/*
@@ -139,7 +140,7 @@ ossl_ssl_session_get_time(VALUE self)
GetSSLSession(self, ctx);
t = SSL_SESSION_get_time(ctx);
if (t == 0)
- return Qnil;
+ return Qnil;
return rb_funcall(rb_cTime, rb_intern("at"), 1, LONG2NUM(t));
}
@@ -174,16 +175,16 @@ ossl_ssl_session_get_timeout(VALUE self)
*/
static VALUE ossl_ssl_session_set_time(VALUE self, VALUE time_v)
{
- SSL_SESSION *ctx;
- long t;
-
- GetSSLSession(self, ctx);
- if (rb_obj_is_instance_of(time_v, rb_cTime)) {
- time_v = rb_funcall(time_v, rb_intern("to_i"), 0);
- }
- t = NUM2LONG(time_v);
- SSL_SESSION_set_time(ctx, t);
- return ossl_ssl_session_get_time(self);
+ SSL_SESSION *ctx;
+ long t;
+
+ GetSSLSession(self, ctx);
+ if (rb_obj_is_instance_of(time_v, rb_cTime)) {
+ time_v = rb_funcall(time_v, rb_intern("to_i"), 0);
+ }
+ t = NUM2LONG(time_v);
+ SSL_SESSION_set_time(ctx, t);
+ return ossl_ssl_session_get_time(self);
}
/*
@@ -194,13 +195,13 @@ static VALUE ossl_ssl_session_set_time(VALUE self, VALUE time_v)
*/
static VALUE ossl_ssl_session_set_timeout(VALUE self, VALUE time_v)
{
- SSL_SESSION *ctx;
- long t;
+ SSL_SESSION *ctx;
+ long t;
- GetSSLSession(self, ctx);
- t = NUM2LONG(time_v);
- SSL_SESSION_set_timeout(ctx, t);
- return ossl_ssl_session_get_timeout(self);
+ GetSSLSession(self, ctx);
+ t = NUM2LONG(time_v);
+ SSL_SESSION_set_timeout(ctx, t);
+ return ossl_ssl_session_get_timeout(self);
}
/*
@@ -208,18 +209,18 @@ static VALUE ossl_ssl_session_set_timeout(VALUE self, VALUE time_v)
* session.id -> String
*
* Returns the Session ID.
-*/
+ */
static VALUE ossl_ssl_session_get_id(VALUE self)
{
- SSL_SESSION *ctx;
- const unsigned char *p = NULL;
- unsigned int i = 0;
+ SSL_SESSION *ctx;
+ const unsigned char *p = NULL;
+ unsigned int i = 0;
- GetSSLSession(self, ctx);
+ GetSSLSession(self, ctx);
- p = SSL_SESSION_get_id(ctx, &i);
+ p = SSL_SESSION_get_id(ctx, &i);
- return rb_str_new((const char *) p, i);
+ return rb_str_new((const char *) p, i);
}
/*
@@ -230,22 +231,22 @@ static VALUE ossl_ssl_session_get_id(VALUE self)
*/
static VALUE ossl_ssl_session_to_der(VALUE self)
{
- SSL_SESSION *ctx;
- unsigned char *p;
- int len;
- VALUE str;
-
- GetSSLSession(self, ctx);
- len = i2d_SSL_SESSION(ctx, NULL);
- if (len <= 0) {
- ossl_raise(eSSLSession, "i2d_SSL_SESSION");
- }
-
- str = rb_str_new(0, len);
- p = (unsigned char *)RSTRING_PTR(str);
- i2d_SSL_SESSION(ctx, &p);
- ossl_str_adjust(str, p);
- return str;
+ SSL_SESSION *ctx;
+ unsigned char *p;
+ int len;
+ VALUE str;
+
+ GetSSLSession(self, ctx);
+ len = i2d_SSL_SESSION(ctx, NULL);
+ if (len <= 0) {
+ ossl_raise(eSSLSession, "i2d_SSL_SESSION");
+ }
+
+ str = rb_str_new(0, len);
+ p = (unsigned char *)RSTRING_PTR(str);
+ i2d_SSL_SESSION(ctx, &p);
+ ossl_str_adjust(str, p);
+ return str;
}
/*
@@ -256,22 +257,22 @@ static VALUE ossl_ssl_session_to_der(VALUE self)
*/
static VALUE ossl_ssl_session_to_pem(VALUE self)
{
- SSL_SESSION *ctx;
- BIO *out;
+ SSL_SESSION *ctx;
+ BIO *out;
- GetSSLSession(self, ctx);
+ GetSSLSession(self, ctx);
- if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eSSLSession, "BIO_s_mem()");
- }
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eSSLSession, "BIO_s_mem()");
+ }
- if (!PEM_write_bio_SSL_SESSION(out, ctx)) {
- BIO_free(out);
- ossl_raise(eSSLSession, "SSL_SESSION_print()");
- }
+ if (!PEM_write_bio_SSL_SESSION(out, ctx)) {
+ BIO_free(out);
+ ossl_raise(eSSLSession, "SSL_SESSION_print()");
+ }
- return ossl_membio2str(out);
+ return ossl_membio2str(out);
}
@@ -283,49 +284,44 @@ static VALUE ossl_ssl_session_to_pem(VALUE self)
*/
static VALUE ossl_ssl_session_to_text(VALUE self)
{
- SSL_SESSION *ctx;
- BIO *out;
+ SSL_SESSION *ctx;
+ BIO *out;
- GetSSLSession(self, ctx);
+ GetSSLSession(self, ctx);
- if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eSSLSession, "BIO_s_mem()");
- }
+ if (!(out = BIO_new(BIO_s_mem()))) {
+ ossl_raise(eSSLSession, "BIO_s_mem()");
+ }
- if (!SSL_SESSION_print(out, ctx)) {
- BIO_free(out);
- ossl_raise(eSSLSession, "SSL_SESSION_print()");
- }
+ if (!SSL_SESSION_print(out, ctx)) {
+ BIO_free(out);
+ ossl_raise(eSSLSession, "SSL_SESSION_print()");
+ }
- return ossl_membio2str(out);
+ return ossl_membio2str(out);
}
#endif /* !defined(OPENSSL_NO_SOCK) */
void Init_ossl_ssl_session(void)
{
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- mSSL = rb_define_module_under(mOSSL, "SSL");
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
-#endif
#ifndef OPENSSL_NO_SOCK
- cSSLSession = rb_define_class_under(mSSL, "Session", rb_cObject);
- eSSLSession = rb_define_class_under(cSSLSession, "SessionError", eOSSLError);
-
- rb_define_alloc_func(cSSLSession, ossl_ssl_session_alloc);
- rb_define_method(cSSLSession, "initialize", ossl_ssl_session_initialize, 1);
- rb_define_method(cSSLSession, "initialize_copy", ossl_ssl_session_initialize_copy, 1);
-
- rb_define_method(cSSLSession, "==", ossl_ssl_session_eq, 1);
-
- rb_define_method(cSSLSession, "time", ossl_ssl_session_get_time, 0);
- rb_define_method(cSSLSession, "time=", ossl_ssl_session_set_time, 1);
- rb_define_method(cSSLSession, "timeout", ossl_ssl_session_get_timeout, 0);
- rb_define_method(cSSLSession, "timeout=", ossl_ssl_session_set_timeout, 1);
- rb_define_method(cSSLSession, "id", ossl_ssl_session_get_id, 0);
- rb_define_method(cSSLSession, "to_der", ossl_ssl_session_to_der, 0);
- rb_define_method(cSSLSession, "to_pem", ossl_ssl_session_to_pem, 0);
- rb_define_method(cSSLSession, "to_text", ossl_ssl_session_to_text, 0);
+ cSSLSession = rb_define_class_under(mSSL, "Session", rb_cObject);
+ eSSLSession = rb_define_class_under(cSSLSession, "SessionError", eOSSLError);
+
+ rb_define_alloc_func(cSSLSession, ossl_ssl_session_alloc);
+ rb_define_method(cSSLSession, "initialize", ossl_ssl_session_initialize, 1);
+ rb_define_method(cSSLSession, "initialize_copy", ossl_ssl_session_initialize_copy, 1);
+
+ rb_define_method(cSSLSession, "==", ossl_ssl_session_eq, 1);
+
+ rb_define_method(cSSLSession, "time", ossl_ssl_session_get_time, 0);
+ rb_define_method(cSSLSession, "time=", ossl_ssl_session_set_time, 1);
+ rb_define_method(cSSLSession, "timeout", ossl_ssl_session_get_timeout, 0);
+ rb_define_method(cSSLSession, "timeout=", ossl_ssl_session_set_timeout, 1);
+ rb_define_method(cSSLSession, "id", ossl_ssl_session_get_id, 0);
+ rb_define_method(cSSLSession, "to_der", ossl_ssl_session_to_der, 0);
+ rb_define_method(cSSLSession, "to_pem", ossl_ssl_session_to_pem, 0);
+ rb_define_method(cSSLSession, "to_text", ossl_ssl_session_to_text, 0);
#endif /* !defined(OPENSSL_NO_SOCK) */
}
diff --git a/ext/openssl/ossl_ts.c b/ext/openssl/ossl_ts.c
index b18a86aad9..b31a854a63 100644
--- a/ext/openssl/ossl_ts.c
+++ b/ext/openssl/ossl_ts.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -103,7 +103,7 @@ static const rb_data_type_t ossl_ts_resp_type = {
static void
ossl_ts_token_info_free(void *ptr)
{
- TS_TST_INFO_free(ptr);
+ TS_TST_INFO_free(ptr);
}
static const rb_data_type_t ossl_ts_token_info_type = {
@@ -132,41 +132,10 @@ asn1_to_der(void *template, int (*i2d)(void *template, unsigned char **pp))
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;
+ return (VALUE)ossl_to_asn1obj(obj);
}
static VALUE
@@ -233,11 +202,13 @@ ossl_ts_req_get_algorithm(VALUE self)
TS_REQ *req;
TS_MSG_IMPRINT *mi;
X509_ALGOR *algor;
+ const ASN1_OBJECT *obj;
GetTSRequest(self, req);
mi = TS_REQ_get_msg_imprint(req);
algor = TS_MSG_IMPRINT_get_algo(mi);
- return get_asn1obj(algor->algorithm);
+ X509_ALGOR_get0(&obj, NULL, NULL, algor);
+ return ossl_asn1obj_to_string(obj);
}
/*
@@ -259,7 +230,7 @@ ossl_ts_req_set_algorithm(VALUE self, VALUE algo)
X509_ALGOR *algor;
GetTSRequest(self, req);
- obj = obj_to_asn1obj(algo);
+ obj = ossl_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)) {
@@ -288,7 +259,7 @@ ossl_ts_req_get_msg_imprint(VALUE self)
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);
+ ret = asn1str_to_str(hashed_msg);
return ret;
}
@@ -366,7 +337,7 @@ ossl_ts_req_get_policy_id(VALUE self)
GetTSRequest(self, req);
if (!TS_REQ_get_policy_id(req))
return Qnil;
- return get_asn1obj(TS_REQ_get_policy_id(req));
+ return ossl_asn1obj_to_string(TS_REQ_get_policy_id(req));
}
/*
@@ -389,7 +360,7 @@ ossl_ts_req_set_policy_id(VALUE self, VALUE oid)
int ok;
GetTSRequest(self, req);
- obj = obj_to_asn1obj(oid);
+ obj = ossl_to_asn1obj(oid);
ok = TS_REQ_set_policy_id(req, obj);
ASN1_OBJECT_free(obj);
if (!ok)
@@ -487,17 +458,19 @@ ossl_ts_req_to_der(VALUE self)
TS_REQ *req;
TS_MSG_IMPRINT *mi;
X509_ALGOR *algo;
+ const ASN1_OBJECT *obj;
ASN1_OCTET_STRING *hashed_msg;
GetTSRequest(self, req);
mi = TS_REQ_get_msg_imprint(req);
algo = TS_MSG_IMPRINT_get_algo(mi);
- if (OBJ_obj2nid(algo->algorithm) == NID_undef)
+ X509_ALGOR_get0(&obj, NULL, NULL, algo);
+ if (OBJ_obj2nid(obj) == NID_undef)
ossl_raise(eTimestampError, "Message imprint missing algorithm");
hashed_msg = TS_MSG_IMPRINT_get_msg(mi);
- if (!hashed_msg->length)
+ if (!ASN1_STRING_length(hashed_msg))
ossl_raise(eTimestampError, "Message imprint missing hashed message");
return asn1_to_der((void *)req, (int (*)(void *, unsigned char **))i2d_TS_REQ);
@@ -617,14 +590,7 @@ ossl_ts_resp_get_failure_info(VALUE self)
{
TS_RESP *resp;
TS_STATUS_INFO *si;
-
- /* The ASN1_BIT_STRING_get_bit changed from 1.0.0. to 1.1.0, making this
- * const. */
- #if defined(HAVE_TS_STATUS_INFO_GET0_FAILURE_INFO)
const ASN1_BIT_STRING *fi;
- #else
- ASN1_BIT_STRING *fi;
- #endif
GetTSResponse(self, resp);
si = TS_RESP_get_status_info(resp);
@@ -691,21 +657,12 @@ static VALUE
ossl_ts_resp_get_token(VALUE self)
{
TS_RESP *resp;
- PKCS7 *p7, *copy;
- VALUE obj;
+ PKCS7 *p7;
GetTSResponse(self, resp);
if (!(p7 = TS_RESP_get_token(resp)))
return Qnil;
-
- obj = NewPKCS7(cPKCS7);
-
- if (!(copy = PKCS7_dup(p7)))
- ossl_raise(eTimestampError, NULL);
-
- SetPKCS7(obj, copy);
-
- return obj;
+ return ossl_pkcs7_new(p7);
}
/*
@@ -864,16 +821,26 @@ ossl_ts_resp_verify(int argc, VALUE *argv, VALUE self)
X509_up_ref(cert);
}
+ if (!X509_STORE_up_ref(x509st)) {
+ sk_X509_pop_free(x509inter, X509_free);
+ TS_VERIFY_CTX_free(ctx);
+ ossl_raise(eTimestampError, "X509_STORE_up_ref");
+ }
+
+#ifdef HAVE_TS_VERIFY_CTX_SET0_CERTS
+ TS_VERIFY_CTX_set0_certs(ctx, x509inter);
+ TS_VERIFY_CTX_set0_store(ctx, x509st);
+#else
+# if OSSL_OPENSSL_PREREQ(3, 0, 0) || OSSL_IS_LIBRESSL
TS_VERIFY_CTX_set_certs(ctx, x509inter);
- TS_VERIFY_CTX_add_flags(ctx, TS_VFY_SIGNATURE);
+# else
+ TS_VERIFY_CTS_set_certs(ctx, x509inter);
+# endif
TS_VERIFY_CTX_set_store(ctx, x509st);
+#endif
+ TS_VERIFY_CTX_add_flags(ctx, TS_VFY_SIGNATURE);
ok = TS_RESP_verify_response(ctx, resp);
- /*
- * TS_VERIFY_CTX_set_store() call above does not increment the reference
- * counter, so it must be unset before TS_VERIFY_CTX_free() is called.
- */
- TS_VERIFY_CTX_set_store(ctx, NULL);
TS_VERIFY_CTX_free(ctx);
if (!ok)
@@ -960,7 +927,7 @@ 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));
+ return ossl_asn1obj_to_string(TS_TST_INFO_get_policy_id(info));
}
/*
@@ -982,11 +949,13 @@ ossl_ts_token_info_get_algorithm(VALUE self)
TS_TST_INFO *info;
TS_MSG_IMPRINT *mi;
X509_ALGOR *algo;
+ const ASN1_OBJECT *obj;
GetTSTokenInfo(self, info);
mi = TS_TST_INFO_get_msg_imprint(info);
algo = TS_MSG_IMPRINT_get_algo(mi);
- return get_asn1obj(algo->algorithm);
+ X509_ALGOR_get0(&obj, NULL, NULL, algo);
+ return ossl_asn1obj_to_string(obj);
}
/*
@@ -1012,7 +981,7 @@ ossl_ts_token_info_get_msg_imprint(VALUE self)
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);
+ ret = asn1str_to_str(hashed_msg);
return ret;
}
@@ -1152,9 +1121,14 @@ ossl_tsfac_time_cb(struct TS_resp_ctx *ctx, void *data, time_t *sec, long *usec)
}
static VALUE
-ossl_evp_get_digestbyname_i(VALUE arg)
+ossl_evp_md_fetch_i(VALUE args_)
{
- return (VALUE)ossl_evp_get_digestbyname(arg);
+ VALUE *args = (VALUE *)args_, md_holder;
+ const EVP_MD *md;
+
+ md = ossl_evp_md_fetch(args[1], &md_holder);
+ rb_ary_push(args[0], md_holder);
+ return (VALUE)md;
}
static VALUE
@@ -1190,7 +1164,8 @@ ossl_obj2bio_i(VALUE arg)
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 serial_number, def_policy_id, gen_time, additional_certs,
+ allowed_digests, allowed_digests_tmp = Qnil;
VALUE str;
STACK_OF(X509) *inter_certs;
VALUE tsresp, ret = Qnil;
@@ -1251,7 +1226,7 @@ ossl_tsfac_create_ts(VALUE self, VALUE key, VALUE certificate, VALUE request)
if (rb_obj_is_kind_of(additional_certs, rb_cArray)) {
inter_certs = ossl_protect_x509_ary2sk(additional_certs, &status);
if (status)
- goto end;
+ goto end;
/* this dups the sk_X509 and ups each cert's ref count */
TS_RESP_CTX_set_certs(ctx, inter_certs);
@@ -1267,16 +1242,18 @@ ossl_tsfac_create_ts(VALUE self, VALUE key, VALUE certificate, VALUE request)
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);
+ allowed_digests_tmp = rb_ary_new_capa(RARRAY_LEN(allowed_digests));
+ for (long i = 0; i < RARRAY_LEN(allowed_digests); i++) {
+ VALUE args[] = {
+ allowed_digests_tmp,
+ rb_ary_entry(allowed_digests, i),
+ };
+ const EVP_MD *md = (const EVP_MD *)rb_protect(ossl_evp_md_fetch_i,
+ (VALUE)args, &status);
if (status)
goto end;
- TS_RESP_CTX_add_md(ctx, md);
+ if (!TS_RESP_CTX_add_md(ctx, md))
+ goto end;
}
}
@@ -1290,6 +1267,7 @@ ossl_tsfac_create_ts(VALUE self, VALUE key, VALUE certificate, VALUE request)
response = TS_RESP_create_response(ctx, req_bio);
BIO_free(req_bio);
+ RB_GC_GUARD(allowed_digests_tmp);
if (!response) {
err_msg = "Error during response generation";
@@ -1303,7 +1281,7 @@ ossl_tsfac_create_ts(VALUE self, VALUE key, VALUE certificate, VALUE request)
SetTSResponse(tsresp, response);
ret = tsresp;
-end:
+ end:
ASN1_INTEGER_free(asn1_serial);
ASN1_OBJECT_free(def_policy_id_obj);
TS_RESP_CTX_free(ctx);
@@ -1320,10 +1298,6 @@ end:
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
@@ -1533,67 +1507,45 @@ Init_ossl_ts(void)
* 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
+ */
+ cTimestampFactory = rb_define_class_under(mTimestamp, "Factory", rb_cObject);
+ /*
+ * The list of 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.
+ */
+ rb_attr(cTimestampFactory, rb_intern_const("allowed_digests"), 1, 1, 0);
+ /*
+ * A String representing the default policy object identifier, or +nil+.
*
* 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.
+ * 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);
+ /*
+ * The serial number to be used for timestamp creation. Must be present for
+ * timestamp creation. Must be an instance of OpenSSL::BN or Integer.
+ */
rb_attr(cTimestampFactory, rb_intern_const("serial_number"), 1, 1, 0);
+ /*
+ * The Time value to be used in the Response. Must be present for timestamp
+ * creation.
+ */
rb_attr(cTimestampFactory, rb_intern_const("gen_time"), 1, 1, 0);
+ /*
+ * 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, or +nil+.
+ */
rb_attr(cTimestampFactory, rb_intern_const("additional_certs"), 1, 1, 0);
rb_define_method(cTimestampFactory, "create_timestamp", ossl_tsfac_create_ts, 3);
}
-
+#else /* OPENSSL_NO_TS */
+void
+Init_ossl_ts(void)
+{
+}
#endif
diff --git a/ext/openssl/ossl_ts.h b/ext/openssl/ossl_ts.h
index 25fb0e1d64..eeca3046eb 100644
--- a/ext/openssl/ossl_ts.h
+++ b/ext/openssl/ossl_ts.h
@@ -5,7 +5,7 @@
*/
/*
* This program is licenced under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_TS_H_)
diff --git a/ext/openssl/ossl_x509.c b/ext/openssl/ossl_x509.c
index f8470703fc..bc3914fda2 100644
--- a/ext/openssl/ossl_x509.c
+++ b/ext/openssl/ossl_x509.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -13,7 +13,8 @@ VALUE mX509;
#define DefX509Const(x) rb_define_const(mX509, #x, INT2NUM(X509_##x))
#define DefX509Default(x,i) \
- rb_define_const(mX509, "DEFAULT_" #x, rb_str_new2(X509_get_default_##i()))
+ rb_define_const(mX509, "DEFAULT_" #x, \
+ rb_obj_freeze(rb_str_new_cstr(X509_get_default_##i())))
ASN1_TIME *
ossl_x509_time_adjust(ASN1_TIME *s, VALUE time)
@@ -29,10 +30,6 @@ ossl_x509_time_adjust(ASN1_TIME *s, VALUE time)
void
Init_ossl_x509(void)
{
-#if 0
- mOSSL = rb_define_module("OpenSSL");
-#endif
-
mX509 = rb_define_module_under(mOSSL, "X509");
Init_ossl_x509attr();
@@ -48,9 +45,7 @@ Init_ossl_x509(void)
/* Certificate verification error code */
DefX509Const(V_OK);
-#if defined(X509_V_ERR_UNSPECIFIED) /* 1.0.1r, 1.0.2f, 1.1.0 */
DefX509Const(V_ERR_UNSPECIFIED);
-#endif
DefX509Const(V_ERR_UNABLE_TO_GET_ISSUER_CERT);
DefX509Const(V_ERR_UNABLE_TO_GET_CRL);
DefX509Const(V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE);
@@ -104,10 +99,10 @@ Init_ossl_x509(void)
DefX509Const(V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX);
DefX509Const(V_ERR_UNSUPPORTED_NAME_SYNTAX);
DefX509Const(V_ERR_CRL_PATH_VALIDATION_ERROR);
-#if defined(X509_V_ERR_PATH_LOOP)
+#if defined(X509_V_ERR_PATH_LOOP) /* OpenSSL 1.1.0, missing in LibreSSL */
DefX509Const(V_ERR_PATH_LOOP);
#endif
-#if defined(X509_V_ERR_SUITE_B_INVALID_VERSION)
+#if defined(X509_V_ERR_SUITE_B_INVALID_VERSION) /* OpenSSL 1.1.0, missing in LibreSSL */
DefX509Const(V_ERR_SUITE_B_INVALID_VERSION);
DefX509Const(V_ERR_SUITE_B_INVALID_ALGORITHM);
DefX509Const(V_ERR_SUITE_B_INVALID_CURVE);
@@ -118,27 +113,21 @@ Init_ossl_x509(void)
DefX509Const(V_ERR_HOSTNAME_MISMATCH);
DefX509Const(V_ERR_EMAIL_MISMATCH);
DefX509Const(V_ERR_IP_ADDRESS_MISMATCH);
-#if defined(X509_V_ERR_DANE_NO_MATCH)
+#if defined(X509_V_ERR_DANE_NO_MATCH) /* OpenSSL 1.1.0, missing in LibreSSL */
DefX509Const(V_ERR_DANE_NO_MATCH);
#endif
-#if defined(X509_V_ERR_EE_KEY_TOO_SMALL)
DefX509Const(V_ERR_EE_KEY_TOO_SMALL);
DefX509Const(V_ERR_CA_KEY_TOO_SMALL);
DefX509Const(V_ERR_CA_MD_TOO_WEAK);
-#endif
-#if defined(X509_V_ERR_INVALID_CALL)
DefX509Const(V_ERR_INVALID_CALL);
-#endif
-#if defined(X509_V_ERR_STORE_LOOKUP)
DefX509Const(V_ERR_STORE_LOOKUP);
-#endif
-#if defined(X509_V_ERR_NO_VALID_SCTS)
+#if defined(X509_V_ERR_NO_VALID_SCTS) /* OpenSSL 1.1.0, missing in LibreSSL */
DefX509Const(V_ERR_NO_VALID_SCTS);
#endif
-#if defined(X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION)
+#if defined(X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION) /* OpenSSL 1.1.0, missing in LibreSSL */
DefX509Const(V_ERR_PROXY_SUBJECT_NAME_VIOLATION);
#endif
-#if defined(X509_V_ERR_OCSP_VERIFY_NEEDED)
+#if defined(X509_V_ERR_OCSP_VERIFY_NEEDED) /* OpenSSL 1.1.1, missing in LibreSSL */
DefX509Const(V_ERR_OCSP_VERIFY_NEEDED);
DefX509Const(V_ERR_OCSP_VERIFY_FAILED);
DefX509Const(V_ERR_OCSP_CERT_UNKNOWN);
@@ -189,17 +178,13 @@ Init_ossl_x509(void)
* certificate chain, search the Store first for the issuer certificate.
* Enabled by default in OpenSSL >= 1.1.0. */
DefX509Const(V_FLAG_TRUSTED_FIRST);
-#if defined(X509_V_FLAG_SUITEB_128_LOS_ONLY)
+#if defined(X509_V_FLAG_SUITEB_128_LOS_ONLY) /* OpenSSL 1.1.0, missing in LibreSSL */
/* Set by Store#flags= and StoreContext#flags=.
* Enables Suite B 128 bit only mode. */
DefX509Const(V_FLAG_SUITEB_128_LOS_ONLY);
-#endif
-#if defined(X509_V_FLAG_SUITEB_192_LOS)
/* Set by Store#flags= and StoreContext#flags=.
* Enables Suite B 192 bit only mode. */
DefX509Const(V_FLAG_SUITEB_192_LOS);
-#endif
-#if defined(X509_V_FLAG_SUITEB_128_LOS)
/* Set by Store#flags= and StoreContext#flags=.
* Enables Suite B 128 bit mode allowing 192 bit algorithms. */
DefX509Const(V_FLAG_SUITEB_128_LOS);
@@ -207,17 +192,13 @@ Init_ossl_x509(void)
/* Set by Store#flags= and StoreContext#flags=.
* Allows partial chains if at least one certificate is in trusted store. */
DefX509Const(V_FLAG_PARTIAL_CHAIN);
-#if defined(X509_V_FLAG_NO_ALT_CHAINS)
/* Set by Store#flags= and StoreContext#flags=. Suppresses searching for
* a alternative chain. No effect in OpenSSL >= 1.1.0. */
DefX509Const(V_FLAG_NO_ALT_CHAINS);
-#endif
-#if defined(X509_V_FLAG_NO_CHECK_TIME)
/* Set by Store#flags= and StoreContext#flags=. Suppresses checking the
* validity period of certificates and CRLs. No effect when the current
* time is explicitly set by Store#time= or StoreContext#time=. */
DefX509Const(V_FLAG_NO_CHECK_TIME);
-#endif
/* Set by Store#purpose=. SSL/TLS client. */
DefX509Const(PURPOSE_SSL_CLIENT);
diff --git a/ext/openssl/ossl_x509.h b/ext/openssl/ossl_x509.h
index 4fadfa6b82..d25167ee7b 100644
--- a/ext/openssl/ossl_x509.h
+++ b/ext/openssl/ossl_x509.h
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#if !defined(_OSSL_X509_H_)
#define _OSSL_X509_H_
@@ -28,7 +28,6 @@ void Init_ossl_x509(void);
* X509Attr
*/
extern VALUE cX509Attr;
-extern VALUE eX509AttrError;
VALUE ossl_x509attr_new(X509_ATTRIBUTE *);
X509_ATTRIBUTE *GetX509AttrPtr(VALUE);
@@ -38,7 +37,6 @@ void Init_ossl_x509attr(void);
* X509Cert
*/
extern VALUE cX509Cert;
-extern VALUE eX509CertError;
VALUE ossl_x509_new(X509 *);
X509 *GetX509CertPtr(VALUE);
@@ -48,9 +46,6 @@ void Init_ossl_x509cert(void);
/*
* X509CRL
*/
-extern VALUE cX509CRL;
-extern VALUE eX509CRLError;
-
VALUE ossl_x509crl_new(X509_CRL *);
X509_CRL *GetX509CRLPtr(VALUE);
void Init_ossl_x509crl(void);
@@ -59,8 +54,6 @@ void Init_ossl_x509crl(void);
* X509Extension
*/
extern VALUE cX509Ext;
-extern VALUE cX509ExtFactory;
-extern VALUE eX509ExtError;
VALUE ossl_x509ext_new(X509_EXTENSION *);
X509_EXTENSION *GetX509ExtPtr(VALUE);
@@ -69,9 +62,6 @@ void Init_ossl_x509ext(void);
/*
* X509Name
*/
-extern VALUE cX509Name;
-extern VALUE eX509NameError;
-
VALUE ossl_x509name_new(X509_NAME *);
X509_NAME *GetX509NamePtr(VALUE);
void Init_ossl_x509name(void);
@@ -79,9 +69,6 @@ void Init_ossl_x509name(void);
/*
* X509Request
*/
-extern VALUE cX509Req;
-extern VALUE eX509ReqError;
-
X509_REQ *GetX509ReqPtr(VALUE);
void Init_ossl_x509req(void);
@@ -89,7 +76,6 @@ void Init_ossl_x509req(void);
* X509Revoked
*/
extern VALUE cX509Rev;
-extern VALUE eX509RevError;
VALUE ossl_x509revoked_new(X509_REVOKED *);
X509_REVOKED *DupX509RevokedPtr(VALUE);
@@ -98,12 +84,7 @@ void Init_ossl_x509revoked(void);
/*
* X509Store and X509StoreContext
*/
-extern VALUE cX509Store;
-extern VALUE cX509StoreContext;
-extern VALUE eX509StoreError;
-
X509_STORE *GetX509StorePtr(VALUE);
-
void Init_ossl_x509store(void);
/*
diff --git a/ext/openssl/ossl_x509attr.c b/ext/openssl/ossl_x509attr.c
index d1d8bb5e95..4769e56e1e 100644
--- a/ext/openssl/ossl_x509attr.c
+++ b/ext/openssl/ossl_x509attr.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -13,14 +13,14 @@
TypedData_Wrap_Struct((klass), &ossl_x509attr_type, 0)
#define SetX509Attr(obj, attr) do { \
if (!(attr)) { \
- ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \
+ ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \
} \
RTYPEDDATA_DATA(obj) = (attr); \
} while (0)
#define GetX509Attr(obj, attr) do { \
TypedData_Get_Struct((obj), X509_ATTRIBUTE, &ossl_x509attr_type, (attr)); \
if (!(attr)) { \
- ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \
+ ossl_raise(rb_eRuntimeError, "ATTR wasn't initialized!"); \
} \
} while (0)
@@ -28,7 +28,7 @@
* Classes
*/
VALUE cX509Attr;
-VALUE eX509AttrError;
+static VALUE eX509AttrError;
static void
ossl_x509attr_free(void *ptr)
@@ -39,7 +39,7 @@ ossl_x509attr_free(void *ptr)
static const rb_data_type_t ossl_x509attr_type = {
"OpenSSL/X509/ATTRIBUTE",
{
- 0, ossl_x509attr_free,
+ 0, ossl_x509attr_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
@@ -54,14 +54,9 @@ ossl_x509attr_new(X509_ATTRIBUTE *attr)
VALUE obj;
obj = NewX509Attr(cX509Attr);
- if (!attr) {
- new = X509_ATTRIBUTE_new();
- } else {
- new = X509_ATTRIBUTE_dup(attr);
- }
- if (!new) {
- ossl_raise(eX509AttrError, NULL);
- }
+ new = X509_ATTRIBUTE_dup(attr);
+ if (!new)
+ ossl_raise(eX509AttrError, "X509_ATTRIBUTE_dup");
SetX509Attr(obj, new);
return obj;
@@ -88,7 +83,7 @@ ossl_x509attr_alloc(VALUE klass)
obj = NewX509Attr(klass);
if (!(attr = X509_ATTRIBUTE_new()))
- ossl_raise(eX509AttrError, NULL);
+ ossl_raise(eX509AttrError, NULL);
SetX509Attr(obj, attr);
return obj;
@@ -107,15 +102,15 @@ ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self)
GetX509Attr(self, attr);
if(rb_scan_args(argc, argv, "11", &oid, &value) == 1){
- oid = ossl_to_der_if_possible(oid);
- StringValue(oid);
- p = (unsigned char *)RSTRING_PTR(oid);
- x = d2i_X509_ATTRIBUTE(&attr, &p, RSTRING_LEN(oid));
- DATA_PTR(self) = attr;
- if(!x){
- ossl_raise(eX509AttrError, NULL);
- }
- return self;
+ oid = ossl_to_der_if_possible(oid);
+ StringValue(oid);
+ p = (unsigned char *)RSTRING_PTR(oid);
+ x = d2i_X509_ATTRIBUTE(&attr, &p, RSTRING_LEN(oid));
+ DATA_PTR(self) = attr;
+ if(!x){
+ ossl_raise(eX509AttrError, NULL);
+ }
+ return self;
}
rb_funcall(self, rb_intern("oid="), 1, oid);
rb_funcall(self, rb_intern("value="), 1, value);
@@ -123,6 +118,7 @@ ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+/* :nodoc: */
static VALUE
ossl_x509attr_initialize_copy(VALUE self, VALUE other)
{
@@ -134,7 +130,7 @@ ossl_x509attr_initialize_copy(VALUE self, VALUE other)
attr_new = X509_ATTRIBUTE_dup(attr_other);
if (!attr_new)
- ossl_raise(eX509AttrError, "X509_ATTRIBUTE_dup");
+ ossl_raise(eX509AttrError, "X509_ATTRIBUTE_dup");
SetX509Attr(self, attr_new);
X509_ATTRIBUTE_free(attr);
@@ -158,8 +154,8 @@ ossl_x509attr_set_oid(VALUE self, VALUE oid)
obj = OBJ_txt2obj(s, 0);
if(!obj) ossl_raise(eX509AttrError, NULL);
if (!X509_ATTRIBUTE_set1_object(attr, obj)) {
- ASN1_OBJECT_free(obj);
- ossl_raise(eX509AttrError, "X509_ATTRIBUTE_set1_object");
+ ASN1_OBJECT_free(obj);
+ ossl_raise(eX509AttrError, "X509_ATTRIBUTE_set1_object");
}
ASN1_OBJECT_free(obj);
@@ -168,29 +164,18 @@ ossl_x509attr_set_oid(VALUE self, VALUE oid)
/*
* call-seq:
- * attr.oid => string
+ * attr.oid -> string
+ *
+ * Returns the OID of the attribute. Returns the short name or the dotted
+ * decimal notation.
*/
static VALUE
ossl_x509attr_get_oid(VALUE self)
{
X509_ATTRIBUTE *attr;
- ASN1_OBJECT *oid;
- BIO *out;
- VALUE ret;
- int nid;
GetX509Attr(self, attr);
- oid = X509_ATTRIBUTE_get0_object(attr);
- if ((nid = OBJ_obj2nid(oid)) != 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, oid);
- ret = ossl_membio2str(out);
- }
-
- return ret;
+ return ossl_asn1obj_to_string(X509_ATTRIBUTE_get0_object(attr));
}
/*
@@ -201,37 +186,36 @@ static VALUE
ossl_x509attr_set_value(VALUE self, VALUE value)
{
X509_ATTRIBUTE *attr;
- VALUE asn1_value;
- int i, asn1_tag;
+ GetX509Attr(self, attr);
OSSL_Check_Kind(value, cASN1Data);
- asn1_tag = NUM2INT(rb_attr_get(value, rb_intern("@tag")));
- asn1_value = rb_attr_get(value, rb_intern("@value"));
- if (asn1_tag != V_ASN1_SET)
- ossl_raise(eASN1Error, "argument must be ASN1::Set");
- if (!RB_TYPE_P(asn1_value, T_ARRAY))
- ossl_raise(eASN1Error, "ASN1::Set has non-array value");
+ VALUE der = ossl_to_der(value);
+ const unsigned char *p = (const unsigned char *)RSTRING_PTR(der);
+ STACK_OF(ASN1_TYPE) *sk = d2i_ASN1_SET_ANY(NULL, &p, RSTRING_LEN(der));
+ if (!sk)
+ ossl_raise(eX509AttrError, "attribute value must be ASN1::Set");
- GetX509Attr(self, attr);
if (X509_ATTRIBUTE_count(attr)) { /* populated, reset first */
- ASN1_OBJECT *obj = X509_ATTRIBUTE_get0_object(attr);
- X509_ATTRIBUTE *new_attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, 0, NULL, -1);
- if (!new_attr)
- ossl_raise(eX509AttrError, NULL);
- SetX509Attr(self, new_attr);
- X509_ATTRIBUTE_free(attr);
- attr = new_attr;
+ ASN1_OBJECT *obj = X509_ATTRIBUTE_get0_object(attr);
+ X509_ATTRIBUTE *new_attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, 0, NULL, -1);
+ if (!new_attr) {
+ sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free);
+ ossl_raise(eX509AttrError, "X509_ATTRIBUTE_create_by_OBJ");
+ }
+ SetX509Attr(self, new_attr);
+ X509_ATTRIBUTE_free(attr);
+ attr = new_attr;
}
- for (i = 0; i < RARRAY_LEN(asn1_value); i++) {
- ASN1_TYPE *a1type = ossl_asn1_get_asn1type(RARRAY_AREF(asn1_value, i));
- if (!X509_ATTRIBUTE_set1_data(attr, ASN1_TYPE_get(a1type),
- a1type->value.ptr, -1)) {
- ASN1_TYPE_free(a1type);
- ossl_raise(eX509AttrError, NULL);
- }
- ASN1_TYPE_free(a1type);
+ for (int i = 0; i < sk_ASN1_TYPE_num(sk); i++) {
+ ASN1_TYPE *a1type = sk_ASN1_TYPE_value(sk, i);
+ if (!X509_ATTRIBUTE_set1_data(attr, ASN1_TYPE_get(a1type),
+ a1type->value.ptr, -1)) {
+ sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free);
+ ossl_raise(eX509AttrError, "X509_ATTRIBUTE_set1_data");
+ }
}
+ sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free);
return value;
}
@@ -252,21 +236,21 @@ ossl_x509attr_get_value(VALUE self)
GetX509Attr(self, attr);
/* there is no X509_ATTRIBUTE_get0_set() :( */
if (!(sk = sk_ASN1_TYPE_new_null()))
- ossl_raise(eX509AttrError, "sk_new");
+ ossl_raise(eX509AttrError, "sk_new");
count = X509_ATTRIBUTE_count(attr);
for (i = 0; i < count; i++)
- sk_ASN1_TYPE_push(sk, X509_ATTRIBUTE_get0_type(attr, i));
+ sk_ASN1_TYPE_push(sk, X509_ATTRIBUTE_get0_type(attr, i));
if ((len = i2d_ASN1_SET_ANY(sk, NULL)) <= 0) {
- sk_ASN1_TYPE_free(sk);
- ossl_raise(eX509AttrError, NULL);
+ sk_ASN1_TYPE_free(sk);
+ ossl_raise(eX509AttrError, NULL);
}
str = rb_str_new(0, len);
p = (unsigned char *)RSTRING_PTR(str);
if (i2d_ASN1_SET_ANY(sk, &p) <= 0) {
- sk_ASN1_TYPE_free(sk);
- ossl_raise(eX509AttrError, NULL);
+ sk_ASN1_TYPE_free(sk);
+ ossl_raise(eX509AttrError, NULL);
}
ossl_str_adjust(str, p);
sk_ASN1_TYPE_free(sk);
@@ -288,11 +272,11 @@ ossl_x509attr_to_der(VALUE self)
GetX509Attr(self, attr);
if((len = i2d_X509_ATTRIBUTE(attr, NULL)) <= 0)
- ossl_raise(eX509AttrError, NULL);
+ ossl_raise(eX509AttrError, NULL);
str = rb_str_new(0, len);
p = (unsigned char *)RSTRING_PTR(str);
if(i2d_X509_ATTRIBUTE(attr, &p) <= 0)
- ossl_raise(eX509AttrError, NULL);
+ ossl_raise(eX509AttrError, NULL);
ossl_str_adjust(str, p);
return str;
@@ -304,12 +288,6 @@ ossl_x509attr_to_der(VALUE self)
void
Init_ossl_x509attr(void)
{
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
- mX509 = rb_define_module_under(mOSSL, "X509");
-#endif
-
eX509AttrError = rb_define_class_under(mX509, "AttributeError", eOSSLError);
cX509Attr = rb_define_class_under(mX509, "Attribute", rb_cObject);
diff --git a/ext/openssl/ossl_x509cert.c b/ext/openssl/ossl_x509cert.c
index aa6b9bb7ce..95679c7d24 100644
--- a/ext/openssl/ossl_x509cert.c
+++ b/ext/openssl/ossl_x509cert.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -13,14 +13,14 @@
TypedData_Wrap_Struct((klass), &ossl_x509_type, 0)
#define SetX509(obj, x509) do { \
if (!(x509)) { \
- ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \
+ ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \
} \
RTYPEDDATA_DATA(obj) = (x509); \
} while (0)
#define GetX509(obj, x509) do { \
TypedData_Get_Struct((obj), X509, &ossl_x509_type, (x509)); \
if (!(x509)) { \
- ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \
+ ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \
} \
} while (0)
@@ -28,7 +28,7 @@
* Classes
*/
VALUE cX509Cert;
-VALUE eX509CertError;
+static VALUE eX509CertError;
static void
ossl_x509_free(void *ptr)
@@ -39,7 +39,7 @@ ossl_x509_free(void *ptr)
static const rb_data_type_t ossl_x509_type = {
"OpenSSL/X509",
{
- 0, ossl_x509_free,
+ 0, ossl_x509_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
@@ -54,14 +54,9 @@ ossl_x509_new(X509 *x509)
VALUE obj;
obj = NewX509(cX509Cert);
- if (!x509) {
- new = X509_new();
- } else {
- new = X509_dup(x509);
- }
- if (!new) {
- ossl_raise(eX509CertError, NULL);
- }
+ new = X509_dup(x509);
+ if (!new)
+ ossl_raise(eX509CertError, "X509_dup");
SetX509(obj, new);
return obj;
@@ -120,8 +115,8 @@ ossl_x509_initialize(int argc, VALUE *argv, VALUE self)
rb_check_frozen(self);
if (rb_scan_args(argc, argv, "01", &arg) == 0) {
- /* create just empty X509Cert */
- return self;
+ /* create just empty X509Cert */
+ return self;
}
arg = ossl_to_der_if_possible(arg);
in = ossl_obj2bio(&arg);
@@ -140,6 +135,7 @@ ossl_x509_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+/* :nodoc: */
static VALUE
ossl_x509_copy(VALUE self, VALUE other)
{
@@ -174,11 +170,11 @@ ossl_x509_to_der(VALUE self)
GetX509(self, x509);
if ((len = i2d_X509(x509, NULL)) <= 0)
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eX509CertError, NULL);
str = rb_str_new(0, len);
p = (unsigned char *)RSTRING_PTR(str);
if (i2d_X509(x509, &p) <= 0)
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eX509CertError, NULL);
ossl_str_adjust(str, p);
return str;
@@ -200,8 +196,8 @@ ossl_x509_to_pem(VALUE self)
if (!out) ossl_raise(eX509CertError, NULL);
if (!PEM_write_bio_X509(out, x509)) {
- BIO_free(out);
- ossl_raise(eX509CertError, NULL);
+ BIO_free(out);
+ ossl_raise(eX509CertError, NULL);
}
str = ossl_membio2str(out);
@@ -225,8 +221,8 @@ ossl_x509_to_text(VALUE self)
if (!out) ossl_raise(eX509CertError, NULL);
if (!X509_print(out, x509)) {
- BIO_free(out);
- ossl_raise(eX509CertError, NULL);
+ BIO_free(out);
+ ossl_raise(eX509CertError, NULL);
}
str = ossl_membio2str(out);
@@ -246,7 +242,7 @@ ossl_x509_to_req(VALUE self)
GetX509(self, x509);
if (!(req = X509_to_X509_REQ(x509, NULL, EVP_md5()))) {
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eX509CertError, NULL);
}
obj = ossl_x509req_new(req);
X509_REQ_free(req);
@@ -280,11 +276,11 @@ ossl_x509_set_version(VALUE self, VALUE version)
long ver;
if ((ver = NUM2LONG(version)) < 0) {
- ossl_raise(eX509CertError, "version must be >= 0!");
+ ossl_raise(eX509CertError, "version must be >= 0!");
}
GetX509(self, x509);
if (!X509_set_version(x509, ver)) {
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eX509CertError, NULL);
}
return version;
@@ -322,25 +318,23 @@ ossl_x509_set_serial(VALUE self, VALUE num)
/*
* call-seq:
* cert.signature_algorithm => string
+ *
+ * Returns the signature algorithm used to sign this certificate. This returns
+ * the algorithm name found in the TBSCertificate structure, not the outer
+ * \Certificate structure.
+ *
+ * Returns the long name of the signature algorithm, or the dotted decimal
+ * notation if \OpenSSL does not define a long name for it.
*/
static VALUE
ossl_x509_get_signature_algorithm(VALUE self)
{
X509 *x509;
- BIO *out;
- VALUE str;
+ const ASN1_OBJECT *obj;
GetX509(self, x509);
- out = BIO_new(BIO_s_mem());
- if (!out) ossl_raise(eX509CertError, NULL);
-
- if (!i2a_ASN1_OBJECT(out, X509_get0_tbs_sigalg(x509)->algorithm)) {
- BIO_free(out);
- ossl_raise(eX509CertError, NULL);
- }
- str = ossl_membio2str(out);
-
- return str;
+ X509_ALGOR_get0(&obj, NULL, NULL, X509_get0_tbs_sigalg(x509));
+ return ossl_asn1obj_to_string_long_name(obj);
}
/*
@@ -355,7 +349,7 @@ ossl_x509_get_subject(VALUE self)
GetX509(self, x509);
if (!(name = X509_get_subject_name(x509))) { /* NO DUP - don't free! */
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eX509CertError, NULL);
}
return ossl_x509name_new(name);
@@ -372,7 +366,7 @@ ossl_x509_set_subject(VALUE self, VALUE subject)
GetX509(self, x509);
if (!X509_set_subject_name(x509, GetX509NamePtr(subject))) { /* DUPs name */
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eX509CertError, NULL);
}
return subject;
@@ -390,7 +384,7 @@ ossl_x509_get_issuer(VALUE self)
GetX509(self, x509);
if(!(name = X509_get_issuer_name(x509))) { /* NO DUP - don't free! */
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eX509CertError, NULL);
}
return ossl_x509name_new(name);
@@ -407,7 +401,7 @@ ossl_x509_set_issuer(VALUE self, VALUE issuer)
GetX509(self, x509);
if (!X509_set_issuer_name(x509, GetX509NamePtr(issuer))) { /* DUPs name */
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eX509CertError, NULL);
}
return issuer;
@@ -425,7 +419,7 @@ ossl_x509_get_not_before(VALUE self)
GetX509(self, x509);
if (!(asn1time = X509_get0_notBefore(x509))) {
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eX509CertError, NULL);
}
return asn1time_to_time(asn1time);
@@ -444,8 +438,8 @@ ossl_x509_set_not_before(VALUE self, VALUE time)
GetX509(self, x509);
asn1time = ossl_x509_time_adjust(NULL, time);
if (!X509_set1_notBefore(x509, asn1time)) {
- ASN1_TIME_free(asn1time);
- ossl_raise(eX509CertError, "X509_set_notBefore");
+ ASN1_TIME_free(asn1time);
+ ossl_raise(eX509CertError, "X509_set_notBefore");
}
ASN1_TIME_free(asn1time);
@@ -464,7 +458,7 @@ ossl_x509_get_not_after(VALUE self)
GetX509(self, x509);
if (!(asn1time = X509_get0_notAfter(x509))) {
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eX509CertError, NULL);
}
return asn1time_to_time(asn1time);
@@ -483,8 +477,8 @@ ossl_x509_set_not_after(VALUE self, VALUE time)
GetX509(self, x509);
asn1time = ossl_x509_time_adjust(NULL, time);
if (!X509_set1_notAfter(x509, asn1time)) {
- ASN1_TIME_free(asn1time);
- ossl_raise(eX509CertError, "X509_set_notAfter");
+ ASN1_TIME_free(asn1time);
+ ossl_raise(eX509CertError, "X509_set_notAfter");
}
ASN1_TIME_free(asn1time);
@@ -503,10 +497,10 @@ ossl_x509_get_public_key(VALUE self)
GetX509(self, x509);
if (!(pkey = X509_get_pubkey(x509))) { /* adds an reference */
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eX509CertError, NULL);
}
- return ossl_pkey_new(pkey); /* NO DUP - OK */
+ return ossl_pkey_wrap(pkey);
}
/*
@@ -523,7 +517,7 @@ ossl_x509_set_public_key(VALUE self, VALUE key)
pkey = GetPKeyPtr(key);
ossl_pkey_check_public_key(pkey);
if (!X509_set_pubkey(x509, pkey))
- ossl_raise(eX509CertError, "X509_set_pubkey");
+ ossl_raise(eX509CertError, "X509_set_pubkey");
return key;
}
@@ -537,13 +531,14 @@ ossl_x509_sign(VALUE self, VALUE key, VALUE digest)
X509 *x509;
EVP_PKEY *pkey;
const EVP_MD *md;
+ VALUE md_holder;
pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
- md = ossl_evp_get_digestbyname(digest);
+ /* NULL needed for some key types, e.g. Ed25519 */
+ md = NIL_P(digest) ? NULL : ossl_evp_md_fetch(digest, &md_holder);
GetX509(self, x509);
- if (!X509_sign(x509, pkey, md)) {
- ossl_raise(eX509CertError, NULL);
- }
+ if (!X509_sign(x509, pkey, md))
+ ossl_raise(eX509CertError, "X509_sign");
return self;
}
@@ -566,12 +561,12 @@ ossl_x509_verify(VALUE self, VALUE key)
ossl_pkey_check_public_key(pkey);
switch (X509_verify(x509, pkey)) {
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, NULL);
}
}
@@ -592,8 +587,8 @@ ossl_x509_check_private_key(VALUE self, VALUE key)
pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
GetX509(self, x509);
if (!X509_check_private_key(x509, pkey)) {
- ossl_clear_error();
- return Qfalse;
+ ossl_clear_error();
+ return Qfalse;
}
return Qtrue;
@@ -613,13 +608,10 @@ ossl_x509_get_extensions(VALUE self)
GetX509(self, x509);
count = X509_get_ext_count(x509);
- if (count < 0) {
- return rb_ary_new();
- }
- ary = rb_ary_new2(count);
+ ary = rb_ary_new_capa(count);
for (i=0; i<count; i++) {
- ext = X509_get_ext(x509, i); /* NO DUP - don't free! */
- rb_ary_push(ary, ossl_x509ext_new(ext));
+ ext = X509_get_ext(x509, i); /* NO DUP - don't free! */
+ rb_ary_push(ary, ossl_x509ext_new(ext));
}
return ary;
@@ -639,16 +631,16 @@ ossl_x509_set_extensions(VALUE self, VALUE ary)
Check_Type(ary, T_ARRAY);
/* All ary's members should be X509Extension */
for (i=0; i<RARRAY_LEN(ary); i++) {
- OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext);
+ OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext);
}
GetX509(self, x509);
for (i = X509_get_ext_count(x509); i > 0; i--)
X509_EXTENSION_free(X509_delete_ext(x509, 0));
for (i=0; i<RARRAY_LEN(ary); i++) {
- ext = GetX509ExtPtr(RARRAY_AREF(ary, i));
- if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext */
- ossl_raise(eX509CertError, "X509_add_ext");
- }
+ ext = GetX509ExtPtr(RARRAY_AREF(ary, i));
+ if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext */
+ ossl_raise(eX509CertError, "X509_add_ext");
+ }
}
return ary;
@@ -667,32 +659,24 @@ ossl_x509_add_extension(VALUE self, VALUE extension)
GetX509(self, x509);
ext = GetX509ExtPtr(extension);
if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext - FREE it */
- ossl_raise(eX509CertError, NULL);
+ ossl_raise(eX509CertError, NULL);
}
return extension;
}
-static VALUE
-ossl_x509_inspect(VALUE self)
-{
- return rb_sprintf("#<%"PRIsVALUE": subject=%+"PRIsVALUE", "
- "issuer=%+"PRIsVALUE", serial=%+"PRIsVALUE", "
- "not_before=%+"PRIsVALUE", not_after=%+"PRIsVALUE">",
- rb_obj_class(self),
- ossl_x509_get_subject(self),
- ossl_x509_get_issuer(self),
- ossl_x509_get_serial(self),
- ossl_x509_get_not_before(self),
- ossl_x509_get_not_after(self));
-}
-
/*
* call-seq:
* cert1 == cert2 -> true | false
*
* Compares the two certificates. Note that this takes into account all fields,
* not just the issuer name and the serial number.
+ *
+ * This method uses X509_cmp() from OpenSSL, which compares certificates based
+ * on their cached DER encodings. The comparison can be unreliable if a
+ * certificate is incomplete.
+ *
+ * See also the man page X509_cmp(3).
*/
static VALUE
ossl_x509_eq(VALUE self, VALUE other)
@@ -701,12 +685,42 @@ ossl_x509_eq(VALUE self, VALUE other)
GetX509(self, a);
if (!rb_obj_is_kind_of(other, cX509Cert))
- return Qfalse;
+ return Qfalse;
GetX509(other, b);
return !X509_cmp(a, b) ? Qtrue : Qfalse;
}
+/*
+ * call-seq:
+ * cert.tbs_bytes => string
+ *
+ * Returns the DER-encoded bytes of the certificate's to be signed certificate.
+ * This is mainly useful for validating embedded certificate transparency signatures.
+ */
+static VALUE
+ossl_x509_tbs_bytes(VALUE self)
+{
+ X509 *x509;
+ int len;
+ unsigned char *p0;
+ VALUE str;
+
+ GetX509(self, x509);
+ len = i2d_re_X509_tbs(x509, NULL);
+ if (len <= 0) {
+ ossl_raise(eX509CertError, "i2d_re_X509_tbs");
+ }
+ str = rb_str_new(NULL, len);
+ p0 = (unsigned char *)RSTRING_PTR(str);
+ if (i2d_re_X509_tbs(x509, &p0) <= 0) {
+ ossl_raise(eX509CertError, "i2d_re_X509_tbs");
+ }
+ ossl_str_adjust(str, p0);
+
+ return str;
+}
+
struct load_chained_certificates_arguments {
VALUE certificates;
X509 *certificate;
@@ -766,7 +780,7 @@ load_chained_certificates_PEM(BIO *in) {
certificates = load_chained_certificates_append(Qnil, certificate);
while ((certificate = PEM_read_bio_X509(in, NULL, NULL, NULL))) {
- load_chained_certificates_append(certificates, certificate);
+ load_chained_certificates_append(certificates, certificate);
}
/* We tried to read one more certificate but could not read start line: */
@@ -864,12 +878,6 @@ ossl_x509_load(VALUE klass, VALUE buffer)
void
Init_ossl_x509cert(void)
{
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
- mX509 = rb_define_module_under(mOSSL, "X509");
-#endif
-
eX509CertError = rb_define_class_under(mX509, "CertificateError", eOSSLError);
/* Document-class: OpenSSL::X509::Certificate
@@ -997,6 +1005,6 @@ Init_ossl_x509cert(void)
rb_define_method(cX509Cert, "extensions", ossl_x509_get_extensions, 0);
rb_define_method(cX509Cert, "extensions=", ossl_x509_set_extensions, 1);
rb_define_method(cX509Cert, "add_extension", ossl_x509_add_extension, 1);
- rb_define_method(cX509Cert, "inspect", ossl_x509_inspect, 0);
rb_define_method(cX509Cert, "==", ossl_x509_eq, 1);
+ rb_define_method(cX509Cert, "tbs_bytes", ossl_x509_tbs_bytes, 0);
}
diff --git a/ext/openssl/ossl_x509crl.c b/ext/openssl/ossl_x509crl.c
index 80e29f9df2..a221429c34 100644
--- a/ext/openssl/ossl_x509crl.c
+++ b/ext/openssl/ossl_x509crl.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -13,22 +13,22 @@
TypedData_Wrap_Struct((klass), &ossl_x509crl_type, 0)
#define SetX509CRL(obj, crl) do { \
if (!(crl)) { \
- ossl_raise(rb_eRuntimeError, "CRL wasn't initialized!"); \
+ ossl_raise(rb_eRuntimeError, "CRL wasn't initialized!"); \
} \
RTYPEDDATA_DATA(obj) = (crl); \
} while (0)
#define GetX509CRL(obj, crl) do { \
TypedData_Get_Struct((obj), X509_CRL, &ossl_x509crl_type, (crl)); \
if (!(crl)) { \
- ossl_raise(rb_eRuntimeError, "CRL wasn't initialized!"); \
+ ossl_raise(rb_eRuntimeError, "CRL wasn't initialized!"); \
} \
} while (0)
/*
* Classes
*/
-VALUE cX509CRL;
-VALUE eX509CRLError;
+static VALUE cX509CRL;
+static VALUE eX509CRLError;
static void
ossl_x509crl_free(void *ptr)
@@ -39,7 +39,7 @@ ossl_x509crl_free(void *ptr)
static const rb_data_type_t ossl_x509crl_type = {
"OpenSSL/X509/CRL",
{
- 0, ossl_x509crl_free,
+ 0, ossl_x509crl_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
@@ -64,8 +64,9 @@ ossl_x509crl_new(X509_CRL *crl)
VALUE obj;
obj = NewX509CRL(cX509CRL);
- tmp = crl ? X509_CRL_dup(crl) : X509_CRL_new();
- if(!tmp) ossl_raise(eX509CRLError, NULL);
+ tmp = X509_CRL_dup(crl);
+ if (!tmp)
+ ossl_raise(eX509CRLError, "X509_CRL_dup");
SetX509CRL(obj, tmp);
return obj;
@@ -82,7 +83,7 @@ ossl_x509crl_alloc(VALUE klass)
obj = NewX509CRL(klass);
if (!(crl = X509_CRL_new())) {
- ossl_raise(eX509CRLError, NULL);
+ ossl_raise(eX509CRLError, NULL);
}
SetX509CRL(obj, crl);
@@ -98,7 +99,7 @@ ossl_x509crl_initialize(int argc, VALUE *argv, VALUE self)
rb_check_frozen(self);
if (rb_scan_args(argc, argv, "01", &arg) == 0) {
- return self;
+ return self;
}
arg = ossl_to_der_if_possible(arg);
in = ossl_obj2bio(&arg);
@@ -117,6 +118,7 @@ ossl_x509crl_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+/* :nodoc: */
static VALUE
ossl_x509crl_copy(VALUE self, VALUE other)
{
@@ -127,7 +129,7 @@ ossl_x509crl_copy(VALUE self, VALUE other)
GetX509CRL(self, a);
GetX509CRL(other, b);
if (!(crl = X509_CRL_dup(b))) {
- ossl_raise(eX509CRLError, NULL);
+ ossl_raise(eX509CRLError, NULL);
}
X509_CRL_free(a);
DATA_PTR(self) = crl;
@@ -154,34 +156,36 @@ ossl_x509crl_set_version(VALUE self, VALUE version)
long ver;
if ((ver = NUM2LONG(version)) < 0) {
- ossl_raise(eX509CRLError, "version must be >= 0!");
+ ossl_raise(eX509CRLError, "version must be >= 0!");
}
GetX509CRL(self, crl);
if (!X509_CRL_set_version(crl, ver)) {
- ossl_raise(eX509CRLError, NULL);
+ ossl_raise(eX509CRLError, NULL);
}
return version;
}
+/*
+ * call-seq:
+ * crl.signature_algorithm -> string
+ *
+ * Returns the signature algorithm used to sign this CRL.
+ *
+ * Returns the long name of the signature algorithm, or the dotted decimal
+ * notation if \OpenSSL does not define a long name for it.
+ */
static VALUE
ossl_x509crl_get_signature_algorithm(VALUE self)
{
X509_CRL *crl;
const X509_ALGOR *alg;
- BIO *out;
+ const ASN1_OBJECT *obj;
GetX509CRL(self, crl);
- if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eX509CRLError, NULL);
- }
X509_CRL_get0_signature(crl, NULL, &alg);
- if (!i2a_ASN1_OBJECT(out, alg->algorithm)) {
- BIO_free(out);
- ossl_raise(eX509CRLError, NULL);
- }
-
- return ossl_membio2str(out);
+ X509_ALGOR_get0(&obj, NULL, NULL, alg);
+ return ossl_asn1obj_to_string_long_name(obj);
}
static VALUE
@@ -202,7 +206,7 @@ ossl_x509crl_set_issuer(VALUE self, VALUE issuer)
GetX509CRL(self, crl);
if (!X509_CRL_set_issuer_name(crl, GetX509NamePtr(issuer))) { /* DUPs name */
- ossl_raise(eX509CRLError, NULL);
+ ossl_raise(eX509CRLError, NULL);
}
return issuer;
}
@@ -216,7 +220,7 @@ ossl_x509crl_get_last_update(VALUE self)
GetX509CRL(self, crl);
time = X509_CRL_get0_lastUpdate(crl);
if (!time)
- return Qnil;
+ return Qnil;
return asn1time_to_time(time);
}
@@ -230,8 +234,8 @@ ossl_x509crl_set_last_update(VALUE self, VALUE time)
GetX509CRL(self, crl);
asn1time = ossl_x509_time_adjust(NULL, time);
if (!X509_CRL_set1_lastUpdate(crl, asn1time)) {
- ASN1_TIME_free(asn1time);
- ossl_raise(eX509CRLError, "X509_CRL_set_lastUpdate");
+ ASN1_TIME_free(asn1time);
+ ossl_raise(eX509CRLError, "X509_CRL_set_lastUpdate");
}
ASN1_TIME_free(asn1time);
@@ -247,7 +251,7 @@ ossl_x509crl_get_next_update(VALUE self)
GetX509CRL(self, crl);
time = X509_CRL_get0_nextUpdate(crl);
if (!time)
- return Qnil;
+ return Qnil;
return asn1time_to_time(time);
}
@@ -261,8 +265,8 @@ ossl_x509crl_set_next_update(VALUE self, VALUE time)
GetX509CRL(self, crl);
asn1time = ossl_x509_time_adjust(NULL, time);
if (!X509_CRL_set1_nextUpdate(crl, asn1time)) {
- ASN1_TIME_free(asn1time);
- ossl_raise(eX509CRLError, "X509_CRL_set_nextUpdate");
+ ASN1_TIME_free(asn1time);
+ ossl_raise(eX509CRLError, "X509_CRL_set_nextUpdate");
}
ASN1_TIME_free(asn1time);
@@ -274,21 +278,19 @@ ossl_x509crl_get_revoked(VALUE self)
{
X509_CRL *crl;
int i, num;
- X509_REVOKED *rev;
- VALUE ary, revoked;
+ STACK_OF(X509_REVOKED) *sk;
+ VALUE ary;
GetX509CRL(self, crl);
- num = sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl));
- if (num < 0) {
- OSSL_Debug("num < 0???");
- return rb_ary_new();
- }
- ary = rb_ary_new2(num);
+ sk = X509_CRL_get_REVOKED(crl);
+ if (!sk)
+ return rb_ary_new();
+
+ num = sk_X509_REVOKED_num(sk);
+ ary = rb_ary_new_capa(num);
for(i=0; i<num; i++) {
- /* NO DUP - don't free! */
- rev = sk_X509_REVOKED_value(X509_CRL_get_REVOKED(crl), i);
- revoked = ossl_x509revoked_new(rev);
- rb_ary_push(ary, revoked);
+ X509_REVOKED *rev = sk_X509_REVOKED_value(sk, i);
+ rb_ary_push(ary, ossl_x509revoked_new(rev));
}
return ary;
@@ -305,19 +307,19 @@ ossl_x509crl_set_revoked(VALUE self, VALUE ary)
Check_Type(ary, T_ARRAY);
/* All ary members should be X509 Revoked */
for (i=0; i<RARRAY_LEN(ary); i++) {
- OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Rev);
+ OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Rev);
}
GetX509CRL(self, crl);
if ((sk = X509_CRL_get_REVOKED(crl))) {
- while ((rev = sk_X509_REVOKED_pop(sk)))
- X509_REVOKED_free(rev);
+ while ((rev = sk_X509_REVOKED_pop(sk)))
+ X509_REVOKED_free(rev);
}
for (i=0; i<RARRAY_LEN(ary); i++) {
- rev = DupX509RevokedPtr(RARRAY_AREF(ary, i));
- if (!X509_CRL_add0_revoked(crl, rev)) { /* NO DUP - don't free! */
- X509_REVOKED_free(rev);
- ossl_raise(eX509CRLError, "X509_CRL_add0_revoked");
- }
+ rev = DupX509RevokedPtr(RARRAY_AREF(ary, i));
+ if (!X509_CRL_add0_revoked(crl, rev)) { /* NO DUP - don't free! */
+ X509_REVOKED_free(rev);
+ ossl_raise(eX509CRLError, "X509_CRL_add0_revoked");
+ }
}
X509_CRL_sort(crl);
@@ -333,8 +335,8 @@ ossl_x509crl_add_revoked(VALUE self, VALUE revoked)
GetX509CRL(self, crl);
rev = DupX509RevokedPtr(revoked);
if (!X509_CRL_add0_revoked(crl, rev)) { /* NO DUP - don't free! */
- X509_REVOKED_free(rev);
- ossl_raise(eX509CRLError, "X509_CRL_add0_revoked");
+ X509_REVOKED_free(rev);
+ ossl_raise(eX509CRLError, "X509_CRL_add0_revoked");
}
X509_CRL_sort(crl);
@@ -347,13 +349,14 @@ ossl_x509crl_sign(VALUE self, VALUE key, VALUE digest)
X509_CRL *crl;
EVP_PKEY *pkey;
const EVP_MD *md;
+ VALUE md_holder;
GetX509CRL(self, crl);
pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
- md = ossl_evp_get_digestbyname(digest);
- if (!X509_CRL_sign(crl, pkey, md)) {
- ossl_raise(eX509CRLError, NULL);
- }
+ /* NULL needed for some key types, e.g. Ed25519 */
+ md = NIL_P(digest) ? NULL : ossl_evp_md_fetch(digest, &md_holder);
+ if (!X509_CRL_sign(crl, pkey, md))
+ ossl_raise(eX509CRLError, "X509_CRL_sign");
return self;
}
@@ -369,12 +372,12 @@ ossl_x509crl_verify(VALUE self, VALUE key)
ossl_pkey_check_public_key(pkey);
switch (X509_CRL_verify(crl, pkey)) {
case 1:
- return Qtrue;
+ return Qtrue;
case 0:
- ossl_clear_error();
- return Qfalse;
+ ossl_clear_error();
+ return Qfalse;
default:
- ossl_raise(eX509CRLError, NULL);
+ ossl_raise(eX509CRLError, NULL);
}
}
@@ -386,11 +389,11 @@ ossl_x509crl_to_der(VALUE self)
GetX509CRL(self, crl);
if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eX509CRLError, NULL);
+ ossl_raise(eX509CRLError, NULL);
}
if (!i2d_X509_CRL_bio(out, crl)) {
- BIO_free(out);
- ossl_raise(eX509CRLError, NULL);
+ BIO_free(out);
+ ossl_raise(eX509CRLError, NULL);
}
return ossl_membio2str(out);
@@ -404,11 +407,11 @@ ossl_x509crl_to_pem(VALUE self)
GetX509CRL(self, crl);
if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eX509CRLError, NULL);
+ ossl_raise(eX509CRLError, NULL);
}
if (!PEM_write_bio_X509_CRL(out, crl)) {
- BIO_free(out);
- ossl_raise(eX509CRLError, NULL);
+ BIO_free(out);
+ ossl_raise(eX509CRLError, NULL);
}
return ossl_membio2str(out);
@@ -422,11 +425,11 @@ ossl_x509crl_to_text(VALUE self)
GetX509CRL(self, crl);
if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eX509CRLError, NULL);
+ ossl_raise(eX509CRLError, NULL);
}
if (!X509_CRL_print(out, crl)) {
- BIO_free(out);
- ossl_raise(eX509CRLError, NULL);
+ BIO_free(out);
+ ossl_raise(eX509CRLError, NULL);
}
return ossl_membio2str(out);
@@ -445,14 +448,10 @@ ossl_x509crl_get_extensions(VALUE self)
GetX509CRL(self, crl);
count = X509_CRL_get_ext_count(crl);
- if (count < 0) {
- OSSL_Debug("count < 0???");
- return rb_ary_new();
- }
- ary = rb_ary_new2(count);
+ ary = rb_ary_new_capa(count);
for (i=0; i<count; i++) {
- ext = X509_CRL_get_ext(crl, i); /* NO DUP - don't free! */
- rb_ary_push(ary, ossl_x509ext_new(ext));
+ ext = X509_CRL_get_ext(crl, i); /* NO DUP - don't free! */
+ rb_ary_push(ary, ossl_x509ext_new(ext));
}
return ary;
@@ -471,16 +470,16 @@ ossl_x509crl_set_extensions(VALUE self, VALUE ary)
Check_Type(ary, T_ARRAY);
/* All ary members should be X509 Extensions */
for (i=0; i<RARRAY_LEN(ary); i++) {
- OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext);
+ OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext);
}
GetX509CRL(self, crl);
for (i = X509_CRL_get_ext_count(crl); i > 0; i--)
X509_EXTENSION_free(X509_CRL_delete_ext(crl, 0));
for (i=0; i<RARRAY_LEN(ary); i++) {
- ext = GetX509ExtPtr(RARRAY_AREF(ary, i)); /* NO NEED TO DUP */
- if (!X509_CRL_add_ext(crl, ext, -1)) {
- ossl_raise(eX509CRLError, "X509_CRL_add_ext");
- }
+ ext = GetX509ExtPtr(RARRAY_AREF(ary, i)); /* NO NEED TO DUP */
+ if (!X509_CRL_add_ext(crl, ext, -1)) {
+ ossl_raise(eX509CRLError, "X509_CRL_add_ext");
+ }
}
return ary;
@@ -495,7 +494,7 @@ ossl_x509crl_add_extension(VALUE self, VALUE extension)
GetX509CRL(self, crl);
ext = GetX509ExtPtr(extension);
if (!X509_CRL_add_ext(crl, ext, -1)) {
- ossl_raise(eX509CRLError, NULL);
+ ossl_raise(eX509CRLError, NULL);
}
return extension;
@@ -507,12 +506,6 @@ ossl_x509crl_add_extension(VALUE self, VALUE extension)
void
Init_ossl_x509crl(void)
{
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
- mX509 = rb_define_module_under(mOSSL, "X509");
-#endif
-
eX509CRLError = rb_define_class_under(mX509, "CRLError", eOSSLError);
cX509CRL = rb_define_class_under(mX509, "CRL", rb_cObject);
diff --git a/ext/openssl/ossl_x509ext.c b/ext/openssl/ossl_x509ext.c
index 192d09bd3f..ef66ecc3fe 100644
--- a/ext/openssl/ossl_x509ext.c
+++ b/ext/openssl/ossl_x509ext.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -13,14 +13,14 @@
TypedData_Wrap_Struct((klass), &ossl_x509ext_type, 0)
#define SetX509Ext(obj, ext) do { \
if (!(ext)) { \
- ossl_raise(rb_eRuntimeError, "EXT wasn't initialized!"); \
+ ossl_raise(rb_eRuntimeError, "EXT wasn't initialized!"); \
} \
RTYPEDDATA_DATA(obj) = (ext); \
} while (0)
#define GetX509Ext(obj, ext) do { \
TypedData_Get_Struct((obj), X509_EXTENSION, &ossl_x509ext_type, (ext)); \
if (!(ext)) { \
- ossl_raise(rb_eRuntimeError, "EXT wasn't initialized!"); \
+ ossl_raise(rb_eRuntimeError, "EXT wasn't initialized!"); \
} \
} while (0)
#define MakeX509ExtFactory(klass, obj, ctx) do { \
@@ -33,7 +33,7 @@
#define GetX509ExtFactory(obj, ctx) do { \
TypedData_Get_Struct((obj), X509V3_CTX, &ossl_x509extfactory_type, (ctx)); \
if (!(ctx)) { \
- ossl_raise(rb_eRuntimeError, "CTX wasn't initialized!"); \
+ ossl_raise(rb_eRuntimeError, "CTX wasn't initialized!"); \
} \
} while (0)
@@ -41,8 +41,8 @@
* Classes
*/
VALUE cX509Ext;
-VALUE cX509ExtFactory;
-VALUE eX509ExtError;
+static VALUE cX509ExtFactory;
+static VALUE eX509ExtError;
static void
ossl_x509ext_free(void *ptr)
@@ -53,7 +53,7 @@ ossl_x509ext_free(void *ptr)
static const rb_data_type_t ossl_x509ext_type = {
"OpenSSL/X509/EXTENSION",
{
- 0, ossl_x509ext_free,
+ 0, ossl_x509ext_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
@@ -68,14 +68,9 @@ ossl_x509ext_new(X509_EXTENSION *ext)
VALUE obj;
obj = NewX509Ext(cX509Ext);
- if (!ext) {
- new = X509_EXTENSION_new();
- } else {
- new = X509_EXTENSION_dup(ext);
- }
- if (!new) {
- ossl_raise(eX509ExtError, NULL);
- }
+ new = X509_EXTENSION_dup(ext);
+ if (!new)
+ ossl_raise(eX509ExtError, "X509_EXTENSION_dup");
SetX509Ext(obj, new);
return obj;
@@ -106,7 +101,7 @@ ossl_x509extfactory_free(void *ctx)
static const rb_data_type_t ossl_x509extfactory_type = {
"OpenSSL/X509/EXTENSION/Factory",
{
- 0, ossl_x509extfactory_free,
+ 0, ossl_x509extfactory_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
@@ -180,15 +175,15 @@ ossl_x509extfactory_initialize(int argc, VALUE *argv, VALUE self)
/*GetX509ExtFactory(self, ctx);*/
rb_scan_args(argc, argv, "04",
- &issuer_cert, &subject_cert, &subject_req, &crl);
+ &issuer_cert, &subject_cert, &subject_req, &crl);
if (!NIL_P(issuer_cert))
- ossl_x509extfactory_set_issuer_cert(self, issuer_cert);
+ ossl_x509extfactory_set_issuer_cert(self, issuer_cert);
if (!NIL_P(subject_cert))
- ossl_x509extfactory_set_subject_cert(self, subject_cert);
+ ossl_x509extfactory_set_subject_cert(self, subject_cert);
if (!NIL_P(subject_req))
- ossl_x509extfactory_set_subject_req(self, subject_req);
+ ossl_x509extfactory_set_subject_req(self, subject_req);
if (!NIL_P(crl))
- ossl_x509extfactory_set_crl(self, crl);
+ ossl_x509extfactory_set_crl(self, crl);
return self;
}
@@ -218,7 +213,7 @@ ossl_x509extfactory_create_ext(int argc, VALUE *argv, VALUE self)
oid_cstr = StringValueCStr(oid);
nid = OBJ_ln2nid(oid_cstr);
if (nid != NID_undef)
- oid_cstr = OBJ_nid2sn(nid);
+ oid_cstr = OBJ_nid2sn(nid);
valstr = rb_str_new2(RTEST(critical) ? "critical," : "");
rb_str_append(valstr, value);
@@ -230,14 +225,10 @@ ossl_x509extfactory_create_ext(int argc, VALUE *argv, VALUE self)
conf = NIL_P(rconf) ? NULL : GetConfig(rconf);
X509V3_set_nconf(ctx, conf);
-#if OSSL_OPENSSL_PREREQ(1, 1, 0) || OSSL_IS_LIBRESSL
ext = X509V3_EXT_nconf(conf, ctx, oid_cstr, RSTRING_PTR(valstr));
-#else
- ext = X509V3_EXT_nconf(conf, ctx, (char *)oid_cstr, RSTRING_PTR(valstr));
-#endif
X509V3_set_ctx_nodb(ctx);
if (!ext){
- ossl_raise(eX509ExtError, "%"PRIsVALUE" = %"PRIsVALUE, oid, valstr);
+ ossl_raise(eX509ExtError, "%"PRIsVALUE" = %"PRIsVALUE, oid, valstr);
}
SetX509Ext(obj, ext);
@@ -255,7 +246,7 @@ ossl_x509ext_alloc(VALUE klass)
obj = NewX509Ext(klass);
if(!(ext = X509_EXTENSION_new())){
- ossl_raise(eX509ExtError, NULL);
+ ossl_raise(eX509ExtError, NULL);
}
SetX509Ext(obj, ext);
@@ -283,14 +274,14 @@ ossl_x509ext_initialize(int argc, VALUE *argv, VALUE self)
GetX509Ext(self, ext);
if(rb_scan_args(argc, argv, "12", &oid, &value, &critical) == 1){
- oid = ossl_to_der_if_possible(oid);
- StringValue(oid);
- p = (unsigned char *)RSTRING_PTR(oid);
- x = d2i_X509_EXTENSION(&ext, &p, RSTRING_LEN(oid));
- DATA_PTR(self) = ext;
- if(!x)
- ossl_raise(eX509ExtError, NULL);
- return self;
+ oid = ossl_to_der_if_possible(oid);
+ StringValue(oid);
+ p = (unsigned char *)RSTRING_PTR(oid);
+ x = d2i_X509_EXTENSION(&ext, &p, RSTRING_LEN(oid));
+ DATA_PTR(self) = ext;
+ if(!x)
+ ossl_raise(eX509ExtError, NULL);
+ return self;
}
rb_funcall(self, rb_intern("oid="), 1, oid);
rb_funcall(self, rb_intern("value="), 1, value);
@@ -299,6 +290,7 @@ ossl_x509ext_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+/* :nodoc: */
static VALUE
ossl_x509ext_initialize_copy(VALUE self, VALUE other)
{
@@ -310,7 +302,7 @@ ossl_x509ext_initialize_copy(VALUE self, VALUE other)
ext_new = X509_EXTENSION_dup(ext_other);
if (!ext_new)
- ossl_raise(eX509ExtError, "X509_EXTENSION_dup");
+ ossl_raise(eX509ExtError, "X509_EXTENSION_dup");
SetX509Ext(self, ext_new);
X509_EXTENSION_free(ext);
@@ -327,10 +319,10 @@ ossl_x509ext_set_oid(VALUE self, VALUE oid)
GetX509Ext(self, ext);
obj = OBJ_txt2obj(StringValueCStr(oid), 0);
if (!obj)
- ossl_raise(eX509ExtError, "OBJ_txt2obj");
+ ossl_raise(eX509ExtError, "OBJ_txt2obj");
if (!X509_EXTENSION_set_object(ext, obj)) {
- ASN1_OBJECT_free(obj);
- ossl_raise(eX509ExtError, "X509_EXTENSION_set_object");
+ ASN1_OBJECT_free(obj);
+ ossl_raise(eX509ExtError, "X509_EXTENSION_set_object");
}
ASN1_OBJECT_free(obj);
@@ -349,8 +341,8 @@ ossl_x509ext_set_value(VALUE self, VALUE data)
asn1s = X509_EXTENSION_get_data(ext);
if (!ASN1_OCTET_STRING_set(asn1s, (unsigned char *)RSTRING_PTR(data),
- RSTRING_LENINT(data))) {
- ossl_raise(eX509ExtError, "ASN1_OCTET_STRING_set");
+ RSTRING_LENINT(data))) {
+ ossl_raise(eX509ExtError, "ASN1_OCTET_STRING_set");
}
return data;
@@ -367,27 +359,20 @@ ossl_x509ext_set_critical(VALUE self, VALUE flag)
return flag;
}
+/*
+ * call-seq:
+ * ext.oid -> string
+ *
+ * Returns the OID of the extension. Returns the short name or the dotted
+ * decimal notation.
+ */
static VALUE
ossl_x509ext_get_oid(VALUE obj)
{
X509_EXTENSION *ext;
- ASN1_OBJECT *extobj;
- BIO *out;
- VALUE ret;
- int nid;
GetX509Ext(obj, ext);
- extobj = X509_EXTENSION_get_object(ext);
- if ((nid = OBJ_obj2nid(extobj)) != NID_undef)
- ret = rb_str_new2(OBJ_nid2sn(nid));
- else{
- if (!(out = BIO_new(BIO_s_mem())))
- ossl_raise(eX509ExtError, NULL);
- i2a_ASN1_OBJECT(out, extobj);
- ret = ossl_membio2str(out);
- }
-
- return ret;
+ return ossl_asn1obj_to_string(X509_EXTENSION_get_object(ext));
}
static VALUE
@@ -399,9 +384,9 @@ ossl_x509ext_get_value(VALUE obj)
GetX509Ext(obj, ext);
if (!(out = BIO_new(BIO_s_mem())))
- ossl_raise(eX509ExtError, NULL);
+ ossl_raise(eX509ExtError, NULL);
if (!X509V3_EXT_print(out, ext, 0, 0))
- ASN1_STRING_print(out, (ASN1_STRING *)X509_EXTENSION_get_data(ext));
+ ASN1_STRING_print(out, (ASN1_STRING *)X509_EXTENSION_get_data(ext));
ret = ossl_membio2str(out);
return ret;
@@ -415,9 +400,9 @@ ossl_x509ext_get_value_der(VALUE obj)
GetX509Ext(obj, ext);
if ((value = X509_EXTENSION_get_data(ext)) == NULL)
- ossl_raise(eX509ExtError, NULL);
+ ossl_raise(eX509ExtError, NULL);
- return rb_str_new((const char *)value->data, value->length);
+ return asn1str_to_str(value);
}
static VALUE
@@ -439,11 +424,11 @@ ossl_x509ext_to_der(VALUE obj)
GetX509Ext(obj, ext);
if((len = i2d_X509_EXTENSION(ext, NULL)) <= 0)
- ossl_raise(eX509ExtError, NULL);
+ ossl_raise(eX509ExtError, NULL);
str = rb_str_new(0, len);
p = (unsigned char *)RSTRING_PTR(str);
if(i2d_X509_EXTENSION(ext, &p) < 0)
- ossl_raise(eX509ExtError, NULL);
+ ossl_raise(eX509ExtError, NULL);
ossl_str_adjust(str, p);
return str;
@@ -456,12 +441,6 @@ void
Init_ossl_x509ext(void)
{
#undef rb_intern
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
- mX509 = rb_define_module_under(mOSSL, "X509");
-#endif
-
eX509ExtError = rb_define_class_under(mX509, "ExtensionError", eOSSLError);
cX509ExtFactory = rb_define_class_under(mX509, "ExtensionFactory", rb_cObject);
diff --git a/ext/openssl/ossl_x509name.c b/ext/openssl/ossl_x509name.c
index 9591912f70..5b3c3f7261 100644
--- a/ext/openssl/ossl_x509name.c
+++ b/ext/openssl/ossl_x509name.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -13,27 +13,27 @@
TypedData_Wrap_Struct((klass), &ossl_x509name_type, 0)
#define SetX509Name(obj, name) do { \
if (!(name)) { \
- ossl_raise(rb_eRuntimeError, "Name wasn't initialized."); \
+ ossl_raise(rb_eRuntimeError, "Name wasn't initialized."); \
} \
RTYPEDDATA_DATA(obj) = (name); \
} while (0)
#define GetX509Name(obj, name) do { \
TypedData_Get_Struct((obj), X509_NAME, &ossl_x509name_type, (name)); \
if (!(name)) { \
- ossl_raise(rb_eRuntimeError, "Name wasn't initialized."); \
+ ossl_raise(rb_eRuntimeError, "Name wasn't initialized."); \
} \
} while (0)
#define OBJECT_TYPE_TEMPLATE \
- rb_const_get(cX509Name, rb_intern("OBJECT_TYPE_TEMPLATE"))
+ rb_const_get(cX509Name, rb_intern("OBJECT_TYPE_TEMPLATE"))
#define DEFAULT_OBJECT_TYPE \
- rb_const_get(cX509Name, rb_intern("DEFAULT_OBJECT_TYPE"))
+ rb_const_get(cX509Name, rb_intern("DEFAULT_OBJECT_TYPE"))
/*
* Classes
*/
-VALUE cX509Name;
-VALUE eX509NameError;
+static VALUE cX509Name;
+static VALUE eX509NameError;
static void
ossl_x509name_free(void *ptr)
@@ -44,7 +44,7 @@ ossl_x509name_free(void *ptr)
static const rb_data_type_t ossl_x509name_type = {
"OpenSSL/X509/NAME",
{
- 0, ossl_x509name_free,
+ 0, ossl_x509name_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
@@ -59,14 +59,9 @@ ossl_x509name_new(X509_NAME *name)
VALUE obj;
obj = NewX509Name(cX509Name);
- if (!name) {
- new = X509_NAME_new();
- } else {
- new = X509_NAME_dup(name);
- }
- if (!new) {
- ossl_raise(eX509NameError, NULL);
- }
+ new = X509_NAME_dup(name);
+ if (!new)
+ ossl_raise(eX509NameError, "X509_NAME_dup");
SetX509Name(obj, new);
return obj;
@@ -93,7 +88,7 @@ ossl_x509name_alloc(VALUE klass)
obj = NewX509Name(klass);
if (!(name = X509_NAME_new())) {
- ossl_raise(eX509NameError, NULL);
+ ossl_raise(eX509NameError, NULL);
}
SetX509Name(obj, name);
@@ -150,33 +145,34 @@ ossl_x509name_initialize(int argc, VALUE *argv, VALUE self)
GetX509Name(self, name);
if (rb_scan_args(argc, argv, "02", &arg, &template) == 0) {
- return self;
+ return self;
}
else {
- VALUE tmp = rb_check_array_type(arg);
- if (!NIL_P(tmp)) {
- VALUE args;
- if(NIL_P(template)) template = OBJECT_TYPE_TEMPLATE;
- args = rb_ary_new3(2, self, template);
- rb_block_call(tmp, rb_intern("each"), 0, 0, ossl_x509name_init_i, args);
- }
- else{
- const unsigned char *p;
- VALUE str = ossl_to_der_if_possible(arg);
- X509_NAME *x;
- StringValue(str);
- p = (unsigned char *)RSTRING_PTR(str);
- x = d2i_X509_NAME(&name, &p, RSTRING_LEN(str));
- DATA_PTR(self) = name;
- if(!x){
- ossl_raise(eX509NameError, NULL);
- }
- }
+ VALUE tmp = rb_check_array_type(arg);
+ if (!NIL_P(tmp)) {
+ VALUE args;
+ if(NIL_P(template)) template = OBJECT_TYPE_TEMPLATE;
+ args = rb_ary_new3(2, self, template);
+ rb_block_call(tmp, rb_intern("each"), 0, 0, ossl_x509name_init_i, args);
+ }
+ else{
+ const unsigned char *p;
+ VALUE str = ossl_to_der_if_possible(arg);
+ X509_NAME *x;
+ StringValue(str);
+ p = (unsigned char *)RSTRING_PTR(str);
+ x = d2i_X509_NAME(&name, &p, RSTRING_LEN(str));
+ DATA_PTR(self) = name;
+ if(!x){
+ ossl_raise(eX509NameError, NULL);
+ }
+ }
}
return self;
}
+/* :nodoc: */
static VALUE
ossl_x509name_initialize_copy(VALUE self, VALUE other)
{
@@ -188,7 +184,7 @@ ossl_x509name_initialize_copy(VALUE self, VALUE other)
name_new = X509_NAME_dup(name_other);
if (!name_new)
- ossl_raise(eX509NameError, "X509_NAME_dup");
+ ossl_raise(eX509NameError, "X509_NAME_dup");
SetX509Name(self, name_new);
X509_NAME_free(name);
@@ -225,8 +221,8 @@ VALUE ossl_x509name_add_entry(int argc, VALUE *argv, VALUE self)
int loc = -1, set = 0;
if (!kwargs_ids[0]) {
- kwargs_ids[0] = rb_intern_const("loc");
- kwargs_ids[1] = rb_intern_const("set");
+ kwargs_ids[0] = rb_intern_const("loc");
+ kwargs_ids[1] = rb_intern_const("set");
}
rb_scan_args(argc, argv, "21:", &oid, &value, &type, &opts);
rb_get_kwargs(opts, kwargs_ids, 0, 2, kwargs);
@@ -234,14 +230,14 @@ VALUE ossl_x509name_add_entry(int argc, VALUE *argv, VALUE self)
StringValue(value);
if(NIL_P(type)) type = rb_aref(OBJECT_TYPE_TEMPLATE, oid);
if (kwargs[0] != Qundef)
- loc = NUM2INT(kwargs[0]);
+ loc = NUM2INT(kwargs[0]);
if (kwargs[1] != Qundef)
- set = NUM2INT(kwargs[1]);
+ set = NUM2INT(kwargs[1]);
GetX509Name(self, name);
if (!X509_NAME_add_entry_by_txt(name, oid_name, NUM2INT(type),
- (unsigned char *)RSTRING_PTR(value),
- RSTRING_LENINT(value), loc, set))
- ossl_raise(eX509NameError, "X509_NAME_add_entry_by_txt");
+ (unsigned char *)RSTRING_PTR(value),
+ RSTRING_LENINT(value), loc, set))
+ ossl_raise(eX509NameError, "X509_NAME_add_entry_by_txt");
return self;
}
@@ -254,7 +250,7 @@ ossl_x509name_to_s_old(VALUE self)
GetX509Name(self, name);
buf = X509_NAME_oneline(name, NULL, 0);
if (!buf)
- ossl_raise(eX509NameError, "X509_NAME_oneline");
+ ossl_raise(eX509NameError, "X509_NAME_oneline");
return ossl_buf2str(buf, rb_long2int(strlen(buf)));
}
@@ -268,11 +264,11 @@ x509name_print(VALUE self, unsigned long iflag)
GetX509Name(self, name);
out = BIO_new(BIO_s_mem());
if (!out)
- ossl_raise(eX509NameError, NULL);
+ ossl_raise(eX509NameError, NULL);
ret = X509_NAME_print_ex(out, name, 0, iflag);
if (ret < 0 || (iflag == XN_FLAG_COMPAT && ret == 0)) {
- BIO_free(out);
- ossl_raise(eX509NameError, "X509_NAME_print_ex");
+ BIO_free(out);
+ ossl_raise(eX509NameError, "X509_NAME_print_ex");
}
return ossl_membio2str(out);
}
@@ -306,9 +302,9 @@ ossl_x509name_to_s(int argc, VALUE *argv, VALUE self)
rb_check_arity(argc, 0, 1);
/* name.to_s(nil) was allowed */
if (!argc || NIL_P(argv[0]))
- return ossl_x509name_to_s_old(self);
+ return ossl_x509name_to_s_old(self);
else
- return x509name_print(self, NUM2ULONG(argv[0]));
+ return x509name_print(self, NUM2ULONG(argv[0]));
}
/*
@@ -331,7 +327,7 @@ static VALUE
ossl_x509name_inspect(VALUE self)
{
return rb_enc_sprintf(rb_utf8_encoding(), "#<%"PRIsVALUE" %"PRIsVALUE">",
- rb_obj_class(self), ossl_x509name_to_utf8(self));
+ rb_obj_class(self), ossl_x509name_to_utf8(self));
}
/*
@@ -345,38 +341,22 @@ static VALUE
ossl_x509name_to_a(VALUE self)
{
X509_NAME *name;
- X509_NAME_ENTRY *entry;
- int i,entries,nid;
- char long_name[512];
- const char *short_name;
- VALUE ary, vname, ret;
- ASN1_STRING *value;
+ int entries;
+ VALUE ret;
GetX509Name(self, name);
entries = X509_NAME_entry_count(name);
- if (entries < 0) {
- OSSL_Debug("name entries < 0!");
- return rb_ary_new();
- }
- ret = rb_ary_new2(entries);
- for (i=0; i<entries; i++) {
- if (!(entry = X509_NAME_get_entry(name, i))) {
- ossl_raise(eX509NameError, NULL);
- }
- if (!i2t_ASN1_OBJECT(long_name, sizeof(long_name),
- X509_NAME_ENTRY_get_object(entry))) {
- ossl_raise(eX509NameError, NULL);
- }
- nid = OBJ_ln2nid(long_name);
- if (nid == NID_undef) {
- vname = rb_str_new2((const char *) &long_name);
- } else {
- short_name = OBJ_nid2sn(nid);
- vname = rb_str_new2(short_name); /*do not free*/
- }
- value = X509_NAME_ENTRY_get_data(entry);
- ary = rb_ary_new3(3, vname, asn1str_to_str(value), INT2NUM(value->type));
- rb_ary_push(ret, ary);
+ ret = rb_ary_new_capa(entries);
+ for (int i = 0; i < entries; i++) {
+ const X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i);
+ if (!entry)
+ ossl_raise(eX509NameError, "X509_NAME_get_entry");
+ const ASN1_OBJECT *obj = X509_NAME_ENTRY_get_object(entry);
+ VALUE vname = ossl_asn1obj_to_string(obj);
+ const ASN1_STRING *data = X509_NAME_ENTRY_get_data(entry);
+ VALUE vdata = asn1str_to_str(data);
+ VALUE type = INT2NUM(ASN1_STRING_type(data));
+ rb_ary_push(ret, rb_ary_new_from_args(3, vname, vdata, type));
}
return ret;
}
@@ -407,7 +387,7 @@ ossl_x509name_cmp(VALUE self, VALUE other)
int result;
if (!rb_obj_is_kind_of(other, cX509Name))
- return Qnil;
+ return Qnil;
result = ossl_x509name_cmp0(self, other);
if (result < 0) return INT2FIX(-1);
@@ -426,7 +406,7 @@ static VALUE
ossl_x509name_eql(VALUE self, VALUE other)
{
if (!rb_obj_is_kind_of(other, cX509Name))
- return Qfalse;
+ return Qfalse;
return ossl_x509name_cmp0(self, other) == 0 ? Qtrue : Qfalse;
}
@@ -486,11 +466,11 @@ ossl_x509name_to_der(VALUE self)
GetX509Name(self, name);
if((len = i2d_X509_NAME(name, NULL)) <= 0)
- ossl_raise(eX509NameError, NULL);
+ ossl_raise(eX509NameError, NULL);
str = rb_str_new(0, len);
p = (unsigned char *)RSTRING_PTR(str);
if(i2d_X509_NAME(name, &p) <= 0)
- ossl_raise(eX509NameError, NULL);
+ ossl_raise(eX509NameError, NULL);
ossl_str_adjust(str, p);
return str;
@@ -516,12 +496,6 @@ Init_ossl_x509name(void)
#undef rb_intern
VALUE utf8str, ptrstr, ia5str, hash;
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
- mX509 = rb_define_module_under(mOSSL, "X509");
-#endif
-
id_aref = rb_intern("[]");
eX509NameError = rb_define_class_under(mX509, "NameError", eOSSLError);
cX509Name = rb_define_class_under(mX509, "Name", rb_cObject);
@@ -560,6 +534,7 @@ Init_ossl_x509name(void)
rb_hash_aset(hash, rb_str_new2("DC"), ia5str);
rb_hash_aset(hash, rb_str_new2("domainComponent"), ia5str);
rb_hash_aset(hash, rb_str_new2("emailAddress"), ia5str);
+ rb_obj_freeze(hash);
/*
* The default object type template for name entries.
diff --git a/ext/openssl/ossl_x509req.c b/ext/openssl/ossl_x509req.c
index f058185151..433cc461a9 100644
--- a/ext/openssl/ossl_x509req.c
+++ b/ext/openssl/ossl_x509req.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -13,22 +13,22 @@
TypedData_Wrap_Struct((klass), &ossl_x509req_type, 0)
#define SetX509Req(obj, req) do { \
if (!(req)) { \
- ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \
+ ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \
} \
RTYPEDDATA_DATA(obj) = (req); \
} while (0)
#define GetX509Req(obj, req) do { \
TypedData_Get_Struct((obj), X509_REQ, &ossl_x509req_type, (req)); \
if (!(req)) { \
- ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \
+ ossl_raise(rb_eRuntimeError, "Req wasn't initialized!"); \
} \
} while (0)
/*
* Classes
*/
-VALUE cX509Req;
-VALUE eX509ReqError;
+static VALUE cX509Req;
+static VALUE eX509ReqError;
static void
ossl_x509req_free(void *ptr)
@@ -39,7 +39,7 @@ ossl_x509req_free(void *ptr)
static const rb_data_type_t ossl_x509req_type = {
"OpenSSL/X509/REQ",
{
- 0, ossl_x509req_free,
+ 0, ossl_x509req_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
@@ -68,7 +68,7 @@ ossl_x509req_alloc(VALUE klass)
obj = NewX509Req(klass);
if (!(req = X509_REQ_new())) {
- ossl_raise(eX509ReqError, NULL);
+ ossl_raise(eX509ReqError, NULL);
}
SetX509Req(obj, req);
@@ -84,7 +84,7 @@ ossl_x509req_initialize(int argc, VALUE *argv, VALUE self)
rb_check_frozen(self);
if (rb_scan_args(argc, argv, "01", &arg) == 0) {
- return self;
+ return self;
}
arg = ossl_to_der_if_possible(arg);
in = ossl_obj2bio(&arg);
@@ -103,6 +103,7 @@ ossl_x509req_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+/* :nodoc: */
static VALUE
ossl_x509req_copy(VALUE self, VALUE other)
{
@@ -113,7 +114,7 @@ ossl_x509req_copy(VALUE self, VALUE other)
GetX509Req(self, a);
GetX509Req(other, b);
if (!(req = X509_REQ_dup(b))) {
- ossl_raise(eX509ReqError, NULL);
+ ossl_raise(eX509ReqError, NULL);
}
X509_REQ_free(a);
DATA_PTR(self) = req;
@@ -129,11 +130,11 @@ ossl_x509req_to_pem(VALUE self)
GetX509Req(self, req);
if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eX509ReqError, NULL);
+ ossl_raise(eX509ReqError, NULL);
}
if (!PEM_write_bio_X509_REQ(out, req)) {
- BIO_free(out);
- ossl_raise(eX509ReqError, NULL);
+ BIO_free(out);
+ ossl_raise(eX509ReqError, NULL);
}
return ossl_membio2str(out);
@@ -149,11 +150,11 @@ ossl_x509req_to_der(VALUE self)
GetX509Req(self, req);
if ((len = i2d_X509_REQ(req, NULL)) <= 0)
- ossl_raise(eX509ReqError, NULL);
+ ossl_raise(eX509ReqError, NULL);
str = rb_str_new(0, len);
p = (unsigned char *)RSTRING_PTR(str);
if (i2d_X509_REQ(req, &p) <= 0)
- ossl_raise(eX509ReqError, NULL);
+ ossl_raise(eX509ReqError, NULL);
ossl_str_adjust(str, p);
return str;
@@ -167,11 +168,11 @@ ossl_x509req_to_text(VALUE self)
GetX509Req(self, req);
if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eX509ReqError, NULL);
+ ossl_raise(eX509ReqError, NULL);
}
if (!X509_REQ_print(out, req)) {
- BIO_free(out);
- ossl_raise(eX509ReqError, NULL);
+ BIO_free(out);
+ ossl_raise(eX509ReqError, NULL);
}
return ossl_membio2str(out);
@@ -190,7 +191,7 @@ ossl_x509req_to_x509(VALUE self, VALUE days, VALUE key)
GetX509Req(self, req);
...
if (!(x509 = X509_REQ_to_X509(req, d, pkey))) {
- ossl_raise(eX509ReqError, NULL);
+ ossl_raise(eX509ReqError, NULL);
}
return ossl_x509_new(x509);
@@ -216,11 +217,11 @@ ossl_x509req_set_version(VALUE self, VALUE version)
long ver;
if ((ver = NUM2LONG(version)) < 0) {
- ossl_raise(eX509ReqError, "version must be >= 0!");
+ ossl_raise(eX509ReqError, "version must be >= 0!");
}
GetX509Req(self, req);
if (!X509_REQ_set_version(req, ver)) {
- ossl_raise(eX509ReqError, "X509_REQ_set_version");
+ ossl_raise(eX509ReqError, "X509_REQ_set_version");
}
return version;
@@ -234,7 +235,7 @@ ossl_x509req_get_subject(VALUE self)
GetX509Req(self, req);
if (!(name = X509_REQ_get_subject_name(req))) { /* NO DUP - don't free */
- ossl_raise(eX509ReqError, NULL);
+ ossl_raise(eX509ReqError, NULL);
}
return ossl_x509name_new(name);
@@ -248,31 +249,32 @@ ossl_x509req_set_subject(VALUE self, VALUE subject)
GetX509Req(self, req);
/* DUPs name */
if (!X509_REQ_set_subject_name(req, GetX509NamePtr(subject))) {
- ossl_raise(eX509ReqError, NULL);
+ ossl_raise(eX509ReqError, NULL);
}
return subject;
}
+/*
+ * call-seq:
+ * req.signature_algorithm -> string
+ *
+ * Returns the signature algorithm used to sign this request.
+ *
+ * Returns the long name of the signature algorithm, or the dotted decimal
+ * notation if \OpenSSL does not define a long name for it.
+ */
static VALUE
ossl_x509req_get_signature_algorithm(VALUE self)
{
X509_REQ *req;
const X509_ALGOR *alg;
- BIO *out;
+ const ASN1_OBJECT *obj;
GetX509Req(self, req);
-
- if (!(out = BIO_new(BIO_s_mem()))) {
- ossl_raise(eX509ReqError, NULL);
- }
X509_REQ_get0_signature(req, NULL, &alg);
- if (!i2a_ASN1_OBJECT(out, alg->algorithm)) {
- BIO_free(out);
- ossl_raise(eX509ReqError, NULL);
- }
-
- return ossl_membio2str(out);
+ X509_ALGOR_get0(&obj, NULL, NULL, alg);
+ return ossl_asn1obj_to_string_long_name(obj);
}
static VALUE
@@ -283,10 +285,10 @@ ossl_x509req_get_public_key(VALUE self)
GetX509Req(self, req);
if (!(pkey = X509_REQ_get_pubkey(req))) { /* adds reference */
- ossl_raise(eX509ReqError, NULL);
+ ossl_raise(eX509ReqError, NULL);
}
- return ossl_pkey_new(pkey); /* NO DUP - OK */
+ return ossl_pkey_wrap(pkey);
}
static VALUE
@@ -299,7 +301,7 @@ ossl_x509req_set_public_key(VALUE self, VALUE key)
pkey = GetPKeyPtr(key);
ossl_pkey_check_public_key(pkey);
if (!X509_REQ_set_pubkey(req, pkey))
- ossl_raise(eX509ReqError, "X509_REQ_set_pubkey");
+ ossl_raise(eX509ReqError, "X509_REQ_set_pubkey");
return key;
}
@@ -309,13 +311,14 @@ ossl_x509req_sign(VALUE self, VALUE key, VALUE digest)
X509_REQ *req;
EVP_PKEY *pkey;
const EVP_MD *md;
+ VALUE md_holder;
GetX509Req(self, req);
pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
- md = ossl_evp_get_digestbyname(digest);
- if (!X509_REQ_sign(req, pkey, md)) {
- ossl_raise(eX509ReqError, NULL);
- }
+ /* NULL needed for some key types, e.g. Ed25519 */
+ md = NIL_P(digest) ? NULL : ossl_evp_md_fetch(digest, &md_holder);
+ if (!X509_REQ_sign(req, pkey, md))
+ ossl_raise(eX509ReqError, "X509_REQ_sign");
return self;
}
@@ -334,12 +337,12 @@ ossl_x509req_verify(VALUE self, VALUE key)
ossl_pkey_check_public_key(pkey);
switch (X509_REQ_verify(req, pkey)) {
case 1:
- return Qtrue;
+ return Qtrue;
case 0:
- ossl_clear_error();
- return Qfalse;
+ ossl_clear_error();
+ return Qfalse;
default:
- ossl_raise(eX509ReqError, NULL);
+ ossl_raise(eX509ReqError, NULL);
}
}
@@ -355,13 +358,13 @@ ossl_x509req_get_attributes(VALUE self)
count = X509_REQ_get_attr_count(req);
if (count < 0) {
- OSSL_Debug("count < 0???");
- return rb_ary_new();
+ OSSL_Debug("count < 0???");
+ return rb_ary_new();
}
ary = rb_ary_new2(count);
for (i=0; i<count; i++) {
- attr = X509_REQ_get_attr(req, i);
- rb_ary_push(ary, ossl_x509attr_new(attr));
+ attr = X509_REQ_get_attr(req, i);
+ rb_ary_push(ary, ossl_x509attr_new(attr));
}
return ary;
@@ -377,17 +380,17 @@ ossl_x509req_set_attributes(VALUE self, VALUE ary)
Check_Type(ary, T_ARRAY);
for (i=0;i<RARRAY_LEN(ary); i++) {
- OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Attr);
+ OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Attr);
}
GetX509Req(self, req);
for (i = X509_REQ_get_attr_count(req); i > 0; i--)
X509_ATTRIBUTE_free(X509_REQ_delete_attr(req, 0));
for (i=0;i<RARRAY_LEN(ary); i++) {
- item = RARRAY_AREF(ary, i);
- attr = GetX509AttrPtr(item);
- if (!X509_REQ_add1_attr(req, attr)) {
- ossl_raise(eX509ReqError, "X509_REQ_add1_attr");
- }
+ item = RARRAY_AREF(ary, i);
+ attr = GetX509AttrPtr(item);
+ if (!X509_REQ_add1_attr(req, attr)) {
+ ossl_raise(eX509ReqError, "X509_REQ_add1_attr");
+ }
}
return ary;
}
@@ -399,7 +402,7 @@ ossl_x509req_add_attribute(VALUE self, VALUE attr)
GetX509Req(self, req);
if (!X509_REQ_add1_attr(req, GetX509AttrPtr(attr))) {
- ossl_raise(eX509ReqError, NULL);
+ ossl_raise(eX509ReqError, NULL);
}
return attr;
@@ -411,12 +414,6 @@ ossl_x509req_add_attribute(VALUE self, VALUE attr)
void
Init_ossl_x509req(void)
{
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
- mX509 = rb_define_module_under(mOSSL, "X509");
-#endif
-
eX509ReqError = rb_define_class_under(mX509, "RequestError", eOSSLError);
cX509Req = rb_define_class_under(mX509, "Request", rb_cObject);
diff --git a/ext/openssl/ossl_x509revoked.c b/ext/openssl/ossl_x509revoked.c
index 108447c868..b88c390c72 100644
--- a/ext/openssl/ossl_x509revoked.c
+++ b/ext/openssl/ossl_x509revoked.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -13,14 +13,14 @@
TypedData_Wrap_Struct((klass), &ossl_x509rev_type, 0)
#define SetX509Rev(obj, rev) do { \
if (!(rev)) { \
- ossl_raise(rb_eRuntimeError, "REV wasn't initialized!"); \
+ ossl_raise(rb_eRuntimeError, "REV wasn't initialized!"); \
} \
RTYPEDDATA_DATA(obj) = (rev); \
} while (0)
#define GetX509Rev(obj, rev) do { \
TypedData_Get_Struct((obj), X509_REVOKED, &ossl_x509rev_type, (rev)); \
if (!(rev)) { \
- ossl_raise(rb_eRuntimeError, "REV wasn't initialized!"); \
+ ossl_raise(rb_eRuntimeError, "REV wasn't initialized!"); \
} \
} while (0)
@@ -28,7 +28,7 @@
* Classes
*/
VALUE cX509Rev;
-VALUE eX509RevError;
+static VALUE eX509RevError;
static void
ossl_x509rev_free(void *ptr)
@@ -39,7 +39,7 @@ ossl_x509rev_free(void *ptr)
static const rb_data_type_t ossl_x509rev_type = {
"OpenSSL/X509/REV",
{
- 0, ossl_x509rev_free,
+ 0, ossl_x509rev_free,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
@@ -54,14 +54,9 @@ ossl_x509revoked_new(X509_REVOKED *rev)
VALUE obj;
obj = NewX509Rev(cX509Rev);
- if (!rev) {
- new = X509_REVOKED_new();
- } else {
- new = X509_REVOKED_dup(rev);
- }
- if (!new) {
- ossl_raise(eX509RevError, NULL);
- }
+ new = X509_REVOKED_dup(rev);
+ if (!new)
+ ossl_raise(eX509RevError, "X509_REVOKED_dup");
SetX509Rev(obj, new);
return obj;
@@ -74,7 +69,7 @@ DupX509RevokedPtr(VALUE obj)
GetX509Rev(obj, rev);
if (!(new = X509_REVOKED_dup(rev))) {
- ossl_raise(eX509RevError, NULL);
+ ossl_raise(eX509RevError, NULL);
}
return new;
@@ -91,7 +86,7 @@ ossl_x509revoked_alloc(VALUE klass)
obj = NewX509Rev(klass);
if (!(rev = X509_REVOKED_new())) {
- ossl_raise(eX509RevError, NULL);
+ ossl_raise(eX509RevError, NULL);
}
SetX509Rev(obj, rev);
@@ -105,6 +100,7 @@ ossl_x509revoked_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+/* :nodoc: */
static VALUE
ossl_x509revoked_initialize_copy(VALUE self, VALUE other)
{
@@ -116,7 +112,7 @@ ossl_x509revoked_initialize_copy(VALUE self, VALUE other)
rev_new = X509_REVOKED_dup(rev_other);
if (!rev_new)
- ossl_raise(eX509RevError, "X509_REVOKED_dup");
+ ossl_raise(eX509RevError, "X509_REVOKED_dup");
SetX509Rev(self, rev_new);
X509_REVOKED_free(rev);
@@ -143,8 +139,8 @@ ossl_x509revoked_set_serial(VALUE self, VALUE num)
GetX509Rev(self, rev);
asn1int = num_to_asn1integer(num, NULL);
if (!X509_REVOKED_set_serialNumber(rev, asn1int)) {
- ASN1_INTEGER_free(asn1int);
- ossl_raise(eX509RevError, "X509_REVOKED_set_serialNumber");
+ ASN1_INTEGER_free(asn1int);
+ ossl_raise(eX509RevError, "X509_REVOKED_set_serialNumber");
}
ASN1_INTEGER_free(asn1int);
@@ -160,7 +156,7 @@ ossl_x509revoked_get_time(VALUE self)
GetX509Rev(self, rev);
time = X509_REVOKED_get0_revocationDate(rev);
if (!time)
- return Qnil;
+ return Qnil;
return asn1time_to_time(time);
}
@@ -174,8 +170,8 @@ ossl_x509revoked_set_time(VALUE self, VALUE time)
GetX509Rev(self, rev);
asn1time = ossl_x509_time_adjust(NULL, time);
if (!X509_REVOKED_set_revocationDate(rev, asn1time)) {
- ASN1_TIME_free(asn1time);
- ossl_raise(eX509RevError, "X509_REVOKED_set_revocationDate");
+ ASN1_TIME_free(asn1time);
+ ossl_raise(eX509RevError, "X509_REVOKED_set_revocationDate");
}
ASN1_TIME_free(asn1time);
@@ -194,14 +190,10 @@ ossl_x509revoked_get_extensions(VALUE self)
GetX509Rev(self, rev);
count = X509_REVOKED_get_ext_count(rev);
- if (count < 0) {
- OSSL_Debug("count < 0???");
- return rb_ary_new();
- }
- ary = rb_ary_new2(count);
+ ary = rb_ary_new_capa(count);
for (i=0; i<count; i++) {
- ext = X509_REVOKED_get_ext(rev, i);
- rb_ary_push(ary, ossl_x509ext_new(ext));
+ ext = X509_REVOKED_get_ext(rev, i);
+ rb_ary_push(ary, ossl_x509ext_new(ext));
}
return ary;
@@ -220,17 +212,17 @@ ossl_x509revoked_set_extensions(VALUE self, VALUE ary)
Check_Type(ary, T_ARRAY);
for (i=0; i<RARRAY_LEN(ary); i++) {
- OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext);
+ OSSL_Check_Kind(RARRAY_AREF(ary, i), cX509Ext);
}
GetX509Rev(self, rev);
for (i = X509_REVOKED_get_ext_count(rev); i > 0; i--)
X509_EXTENSION_free(X509_REVOKED_delete_ext(rev, 0));
for (i=0; i<RARRAY_LEN(ary); i++) {
- item = RARRAY_AREF(ary, i);
- ext = GetX509ExtPtr(item);
- if(!X509_REVOKED_add_ext(rev, ext, -1)) {
- ossl_raise(eX509RevError, "X509_REVOKED_add_ext");
- }
+ item = RARRAY_AREF(ary, i);
+ ext = GetX509ExtPtr(item);
+ if(!X509_REVOKED_add_ext(rev, ext, -1)) {
+ ossl_raise(eX509RevError, "X509_REVOKED_add_ext");
+ }
}
return ary;
@@ -243,7 +235,7 @@ ossl_x509revoked_add_extension(VALUE self, VALUE ext)
GetX509Rev(self, rev);
if (!X509_REVOKED_add_ext(rev, GetX509ExtPtr(ext), -1)) {
- ossl_raise(eX509RevError, NULL);
+ ossl_raise(eX509RevError, NULL);
}
return ext;
@@ -260,11 +252,11 @@ ossl_x509revoked_to_der(VALUE self)
GetX509Rev(self, rev);
len = i2d_X509_REVOKED(rev, NULL);
if (len <= 0)
- ossl_raise(eX509RevError, "i2d_X509_REVOKED");
+ ossl_raise(eX509RevError, "i2d_X509_REVOKED");
str = rb_str_new(NULL, len);
p = (unsigned char *)RSTRING_PTR(str);
if (i2d_X509_REVOKED(rev, &p) <= 0)
- ossl_raise(eX509RevError, "i2d_X509_REVOKED");
+ ossl_raise(eX509RevError, "i2d_X509_REVOKED");
ossl_str_adjust(str, p);
return str;
}
@@ -275,12 +267,6 @@ ossl_x509revoked_to_der(VALUE self)
void
Init_ossl_x509revoked(void)
{
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
- mX509 = rb_define_module_under(mOSSL, "X509");
-#endif
-
eX509RevError = rb_define_class_under(mX509, "RevokedError", eOSSLError);
cX509Rev = rb_define_class_under(mX509, "Revoked", rb_cObject);
diff --git a/ext/openssl/ossl_x509store.c b/ext/openssl/ossl_x509store.c
index f27381ca90..be1458cec5 100644
--- a/ext/openssl/ossl_x509store.c
+++ b/ext/openssl/ossl_x509store.c
@@ -5,7 +5,7 @@
*/
/*
* This program is licensed under the same licence as Ruby.
- * (See the file 'LICENCE'.)
+ * (See the file 'COPYING'.)
*/
#include "ossl.h"
@@ -13,14 +13,14 @@
TypedData_Wrap_Struct((klass), &ossl_x509store_type, 0)
#define SetX509Store(obj, st) do { \
if (!(st)) { \
- ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
+ ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
} \
RTYPEDDATA_DATA(obj) = (st); \
} while (0)
#define GetX509Store(obj, st) do { \
TypedData_Get_Struct((obj), X509_STORE, &ossl_x509store_type, (st)); \
if (!(st)) { \
- ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
+ ossl_raise(rb_eRuntimeError, "STORE wasn't initialized!"); \
} \
} while (0)
@@ -28,14 +28,14 @@
TypedData_Wrap_Struct((klass), &ossl_x509stctx_type, 0)
#define SetX509StCtx(obj, ctx) do { \
if (!(ctx)) { \
- ossl_raise(rb_eRuntimeError, "STORE_CTX wasn't initialized!"); \
+ ossl_raise(rb_eRuntimeError, "STORE_CTX wasn't initialized!"); \
} \
RTYPEDDATA_DATA(obj) = (ctx); \
} while (0)
#define GetX509StCtx(obj, ctx) do { \
TypedData_Get_Struct((obj), X509_STORE_CTX, &ossl_x509stctx_type, (ctx)); \
if (!(ctx)) { \
- ossl_raise(rb_eRuntimeError, "STORE_CTX is out of scope!"); \
+ ossl_raise(rb_eRuntimeError, "STORE_CTX is out of scope!"); \
} \
} while (0)
@@ -62,7 +62,7 @@ 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);
+ args->preverify_ok, args->store_ctx);
}
int
@@ -73,33 +73,33 @@ ossl_verify_cb_call(VALUE proc, int ok, X509_STORE_CTX *ctx)
int state;
if (NIL_P(proc))
- return ok;
+ return ok;
ret = Qfalse;
rctx = rb_protect(ossl_x509stctx_new_i, (VALUE)ctx, &state);
if (state) {
- rb_set_errinfo(Qnil);
- rb_warn("StoreContext initialization failure");
+ rb_set_errinfo(Qnil);
+ rb_warn("StoreContext initialization failure");
}
else {
- args.proc = proc;
- args.preverify_ok = ok ? Qtrue : Qfalse;
- args.store_ctx = rctx;
- ret = rb_protect(call_verify_cb_proc, (VALUE)&args, &state);
- if (state) {
- rb_set_errinfo(Qnil);
- rb_warn("exception in verify_callback is ignored");
- }
- RTYPEDDATA_DATA(rctx) = NULL;
+ args.proc = proc;
+ args.preverify_ok = ok ? Qtrue : Qfalse;
+ args.store_ctx = rctx;
+ ret = rb_protect(call_verify_cb_proc, (VALUE)&args, &state);
+ if (state) {
+ rb_set_errinfo(Qnil);
+ rb_warn("exception in verify_callback is ignored");
+ }
+ RTYPEDDATA_DATA(rctx) = NULL;
}
if (ret == Qtrue) {
- X509_STORE_CTX_set_error(ctx, X509_V_OK);
- ok = 1;
+ X509_STORE_CTX_set_error(ctx, X509_V_OK);
+ ok = 1;
}
else {
- if (X509_STORE_CTX_get_error(ctx) == X509_V_OK)
- X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
- ok = 0;
+ if (X509_STORE_CTX_get_error(ctx) == X509_V_OK)
+ X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
+ ok = 0;
}
return ok;
@@ -108,9 +108,9 @@ ossl_verify_cb_call(VALUE proc, int ok, X509_STORE_CTX *ctx)
/*
* Classes
*/
-VALUE cX509Store;
-VALUE cX509StoreContext;
-VALUE eX509StoreError;
+static VALUE cX509Store;
+static VALUE cX509StoreContext;
+static VALUE eX509StoreError;
static void
ossl_x509store_mark(void *ptr)
@@ -159,10 +159,10 @@ x509store_verify_cb(int ok, X509_STORE_CTX *ctx)
proc = (VALUE)X509_STORE_CTX_get_ex_data(ctx, stctx_ex_verify_cb_idx);
if (!proc)
- proc = (VALUE)X509_STORE_get_ex_data(X509_STORE_CTX_get0_store(ctx),
- store_ex_verify_cb_idx);
+ proc = (VALUE)X509_STORE_get_ex_data(X509_STORE_CTX_get0_store(ctx),
+ store_ex_verify_cb_idx);
if (!proc)
- return ok;
+ return ok;
return ossl_verify_cb_call(proc, ok, ctx);
}
@@ -191,8 +191,8 @@ ossl_x509store_set_vfy_cb(VALUE self, VALUE cb)
GetX509Store(self, store);
rb_iv_set(self, "@verify_callback", cb);
- // We don't need to trigger a write barrier because `rb_iv_set` did it.
X509_STORE_set_ex_data(store, store_ex_verify_cb_idx, (void *)cb);
+ RB_OBJ_WRITTEN(self, Qundef, cb);
return cb;
}
@@ -212,10 +212,6 @@ ossl_x509store_initialize(int argc, VALUE *argv, VALUE self)
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;
-#endif
X509_STORE_set_verify_cb(store, x509store_verify_cb);
ossl_x509store_set_vfy_cb(self, Qnil);
@@ -223,7 +219,6 @@ ossl_x509store_initialize(int argc, VALUE *argv, VALUE self)
rb_iv_set(self, "@error", Qnil);
rb_iv_set(self, "@error_string", Qnil);
rb_iv_set(self, "@chain", Qnil);
- rb_iv_set(self, "@time", Qnil);
return self;
}
@@ -329,7 +324,12 @@ ossl_x509store_set_trust(VALUE self, VALUE trust)
static VALUE
ossl_x509store_set_time(VALUE self, VALUE time)
{
- rb_iv_set(self, "@time", time);
+ X509_STORE *store;
+ X509_VERIFY_PARAM *param;
+
+ GetX509Store(self, store);
+ param = X509_STORE_get0_param(store);
+ X509_VERIFY_PARAM_set_time(param, NUM2LONG(rb_Integer(time)));
return time;
}
@@ -357,15 +357,6 @@ ossl_x509store_add_file(VALUE self, VALUE file)
ossl_raise(eX509StoreError, "X509_STORE_add_lookup");
if (X509_LOOKUP_load_file(lookup, path, X509_FILETYPE_PEM) != 1)
ossl_raise(eX509StoreError, "X509_LOOKUP_load_file");
-#if OPENSSL_VERSION_NUMBER < 0x10101000 || defined(LIBRESSL_VERSION_NUMBER)
- /*
- * X509_load_cert_crl_file() which is called from X509_LOOKUP_load_file()
- * did not check the return value of X509_STORE_add_{cert,crl}(), leaking
- * "cert already in hash table" errors on the error queue, if duplicate
- * certificates are found. This will be fixed by OpenSSL 1.1.1.
- */
- ossl_clear_error();
-#endif
return self;
}
@@ -493,7 +484,7 @@ ossl_x509store_verify(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "11", &cert, &chain);
ctx = rb_funcall(cX509StoreContext, rb_intern("new"), 3, self, cert, chain);
proc = rb_block_given_p() ? rb_block_proc() :
- rb_iv_get(self, "@verify_callback");
+ rb_iv_get(self, "@verify_callback");
rb_iv_set(ctx, "@verify_callback", proc);
result = rb_funcall(ctx, rb_intern("verify"), 0);
@@ -522,9 +513,9 @@ ossl_x509stctx_free(void *ptr)
{
X509_STORE_CTX *ctx = ptr;
if (X509_STORE_CTX_get0_untrusted(ctx))
- sk_X509_pop_free(X509_STORE_CTX_get0_untrusted(ctx), X509_free);
+ sk_X509_pop_free(X509_STORE_CTX_get0_untrusted(ctx), X509_free);
if (X509_STORE_CTX_get0_cert(ctx))
- X509_free(X509_STORE_CTX_get0_cert(ctx));
+ X509_free(X509_STORE_CTX_get0_cert(ctx));
X509_STORE_CTX_free(ctx);
}
@@ -564,7 +555,6 @@ ossl_x509stctx_new(X509_STORE_CTX *ctx)
static VALUE ossl_x509stctx_set_flags(VALUE, VALUE);
static VALUE ossl_x509stctx_set_purpose(VALUE, VALUE);
static VALUE ossl_x509stctx_set_trust(VALUE, VALUE);
-static VALUE ossl_x509stctx_set_time(VALUE, VALUE);
/*
* call-seq:
@@ -575,7 +565,7 @@ static VALUE ossl_x509stctx_set_time(VALUE, VALUE);
static VALUE
ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self)
{
- VALUE store, cert, chain, t;
+ VALUE store, cert, chain;
X509_STORE_CTX *ctx;
X509_STORE *x509st;
X509 *x509 = NULL;
@@ -599,8 +589,6 @@ ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self)
sk_X509_pop_free(x509s, X509_free);
ossl_raise(eX509StoreError, "X509_STORE_CTX_init");
}
- if (!NIL_P(t = rb_iv_get(store, "@time")))
- ossl_x509stctx_set_time(self, t);
rb_iv_set(self, "@verify_callback", rb_iv_get(store, "@verify_callback"));
rb_iv_set(self, "@cert", cert);
@@ -623,6 +611,7 @@ ossl_x509stctx_verify(VALUE self)
GetX509StCtx(self, ctx);
VALUE cb = rb_iv_get(self, "@verify_callback");
X509_STORE_CTX_set_ex_data(ctx, stctx_ex_verify_cb_idx, (void *)cb);
+ RB_OBJ_WRITTEN(self, Qundef, cb);
switch (X509_verify_cert(ctx)) {
case 1:
@@ -631,7 +620,7 @@ ossl_x509stctx_verify(VALUE self)
ossl_clear_error();
return Qfalse;
default:
- ossl_raise(eX509CertError, "X509_verify_cert");
+ ossl_raise(eX509StoreError, "X509_verify_cert");
}
}
@@ -747,10 +736,14 @@ static VALUE
ossl_x509stctx_get_curr_cert(VALUE self)
{
X509_STORE_CTX *ctx;
+ X509 *x509;
GetX509StCtx(self, ctx);
+ x509 = X509_STORE_CTX_get_current_cert(ctx);
+ if (!x509)
+ return Qnil;
- return ossl_x509_new(X509_STORE_CTX_get_current_cert(ctx));
+ return ossl_x509_new(x509);
}
/*
@@ -770,7 +763,7 @@ ossl_x509stctx_get_curr_crl(VALUE self)
GetX509StCtx(self, ctx);
crl = X509_STORE_CTX_get0_current_crl(ctx);
if (!crl)
- return Qnil;
+ return Qnil;
return ossl_x509crl_new(crl);
}
@@ -866,19 +859,13 @@ void
Init_ossl_x509store(void)
{
#undef rb_intern
-#if 0
- mOSSL = rb_define_module("OpenSSL");
- eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
- mX509 = rb_define_module_under(mOSSL, "X509");
-#endif
-
/* Register ext_data slot for verify callback Proc */
stctx_ex_verify_cb_idx = X509_STORE_CTX_get_ex_new_index(0, (void *)"stctx_ex_verify_cb_idx", 0, 0, 0);
if (stctx_ex_verify_cb_idx < 0)
- ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index");
+ ossl_raise(eOSSLError, "X509_STORE_CTX_get_ex_new_index");
store_ex_verify_cb_idx = X509_STORE_get_ex_new_index(0, (void *)"store_ex_verify_cb_idx", 0, 0, 0);
if (store_ex_verify_cb_idx < 0)
- ossl_raise(eOSSLError, "X509_STORE_get_ex_new_index");
+ ossl_raise(eOSSLError, "X509_STORE_get_ex_new_index");
eX509StoreError = rb_define_class_under(mX509, "StoreError", eOSSLError);
diff --git a/ext/pathname/depend b/ext/pathname/depend
deleted file mode 100644
index cca7877dad..0000000000
--- a/ext/pathname/depend
+++ /dev/null
@@ -1,174 +0,0 @@
-# AUTOGENERATED DEPENDENCIES START
-pathname.o: $(RUBY_EXTCONF_H)
-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/abi.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/packed_struct.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/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/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/stdckdint.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
-pathname.o: $(hdrdir)/ruby/ruby.h
-pathname.o: $(hdrdir)/ruby/st.h
-pathname.o: $(hdrdir)/ruby/subst.h
-pathname.o: pathname.c
-# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/pathname/extconf.rb b/ext/pathname/extconf.rb
deleted file mode 100644
index b4e1617b9e..0000000000
--- a/ext/pathname/extconf.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-# frozen_string_literal: false
-require 'mkmf'
-create_makefile('pathname')
diff --git a/ext/pathname/lib/pathname.rb b/ext/pathname/lib/pathname.rb
deleted file mode 100644
index dc639174d5..0000000000
--- a/ext/pathname/lib/pathname.rb
+++ /dev/null
@@ -1,605 +0,0 @@
-# frozen_string_literal: true
-#
-# = pathname.rb
-#
-# Object-Oriented Pathname Class
-#
-# Author:: Tanaka Akira <akr@m17n.org>
-# Documentation:: Author and Gavin Sinclair
-#
-# For documentation, see class Pathname.
-#
-
-require 'pathname.so'
-
-class Pathname
-
- VERSION = "0.3.0"
-
- # :stopdoc:
-
- # to_path is implemented so Pathname objects are usable with File.open, etc.
- TO_PATH = :to_path
-
- SAME_PATHS = if File::FNM_SYSCASE.nonzero?
- # Avoid #zero? here because #casecmp can return nil.
- proc {|a, b| a.casecmp(b) == 0}
- else
- proc {|a, b| a == b}
- end
-
-
- if File::ALT_SEPARATOR
- SEPARATOR_LIST = "#{Regexp.quote File::ALT_SEPARATOR}#{Regexp.quote File::SEPARATOR}"
- SEPARATOR_PAT = /[#{SEPARATOR_LIST}]/
- else
- SEPARATOR_LIST = "#{Regexp.quote File::SEPARATOR}"
- 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
- def chop_basename(path) # :nodoc:
- base = File.basename(path)
- if /\A#{SEPARATOR_PAT}?\z/o.match?(base)
- return nil
- else
- return path[0, path.rindex(base)], base
- end
- end
- private :chop_basename
-
- # split_names(path) -> prefix, [name, ...]
- def split_names(path) # :nodoc:
- names = []
- while r = chop_basename(path)
- path, basename = r
- names.unshift basename
- end
- return path, names
- end
- private :split_names
-
- def prepend_prefix(prefix, relpath) # :nodoc:
- if relpath.empty?
- File.dirname(prefix)
- elsif /#{SEPARATOR_PAT}/o.match?(prefix)
- prefix = File.dirname(prefix)
- prefix = File.join(prefix, "") if File.basename(prefix + 'a') != 'a'
- prefix + relpath
- else
- prefix + relpath
- end
- end
- private :prepend_prefix
-
- # Returns clean pathname of +self+ with consecutive slashes and useless dots
- # removed. The filesystem is not accessed.
- #
- # If +consider_symlink+ is +true+, then a more conservative algorithm is used
- # to avoid breaking symbolic linkages. This may retain more +..+
- # entries than absolutely necessary, but without accessing the filesystem,
- # this can't be avoided.
- #
- # See Pathname#realpath.
- #
- def cleanpath(consider_symlink=false)
- if consider_symlink
- cleanpath_conservative
- else
- cleanpath_aggressive
- end
- end
-
- #
- # Clean the path simply by resolving and removing excess +.+ and +..+ entries.
- # Nothing more, nothing less.
- #
- def cleanpath_aggressive # :nodoc:
- path = @path
- names = []
- pre = path
- while r = chop_basename(pre)
- pre, base = r
- case base
- when '.'
- when '..'
- names.unshift base
- else
- if names[0] == '..'
- names.shift
- else
- names.unshift base
- end
- end
- end
- pre.tr!(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
- if /#{SEPARATOR_PAT}/o.match?(File.basename(pre))
- names.shift while names[0] == '..'
- end
- self.class.new(prepend_prefix(pre, File.join(*names)))
- end
- private :cleanpath_aggressive
-
- # has_trailing_separator?(path) -> bool
- def has_trailing_separator?(path) # :nodoc:
- if r = chop_basename(path)
- pre, basename = r
- pre.length + basename.length < path.length
- else
- false
- end
- end
- private :has_trailing_separator?
-
- # add_trailing_separator(path) -> path
- def add_trailing_separator(path) # :nodoc:
- if File.basename(path + 'a') == 'a'
- path
- else
- File.join(path, "") # xxx: Is File.join is appropriate to add separator?
- end
- end
- private :add_trailing_separator
-
- def del_trailing_separator(path) # :nodoc:
- if r = chop_basename(path)
- pre, basename = r
- pre + basename
- elsif /#{SEPARATOR_PAT}+\z/o =~ path
- $` + File.dirname(path)[/#{SEPARATOR_PAT}*\z/o]
- else
- path
- end
- end
- private :del_trailing_separator
-
- def cleanpath_conservative # :nodoc:
- path = @path
- names = []
- pre = path
- while r = chop_basename(pre)
- pre, base = r
- names.unshift base if base != '.'
- end
- pre.tr!(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
- if /#{SEPARATOR_PAT}/o.match?(File.basename(pre))
- names.shift while names[0] == '..'
- end
- if names.empty?
- self.class.new(File.dirname(pre))
- else
- if names.last != '..' && File.basename(path) == '.'
- names << '.'
- end
- result = prepend_prefix(pre, File.join(*names))
- if /\A(?:\.|\.\.)\z/ !~ names.last && has_trailing_separator?(path)
- self.class.new(add_trailing_separator(result))
- else
- self.class.new(result)
- end
- end
- end
- private :cleanpath_conservative
-
- # Returns the parent directory.
- #
- # This is same as <code>self + '..'</code>.
- def parent
- self + '..'
- end
-
- # Returns +true+ if +self+ points to a mountpoint.
- def mountpoint?
- begin
- stat1 = self.lstat
- stat2 = self.parent.lstat
- stat1.dev != stat2.dev || stat1.ino == stat2.ino
- rescue Errno::ENOENT
- false
- end
- end
-
- #
- # Predicate method for root directories. Returns +true+ if the
- # pathname consists of consecutive slashes.
- #
- # It doesn't access the filesystem. So it may return +false+ for some
- # pathnames which points to roots such as <tt>/usr/..</tt>.
- #
- def root?
- chop_basename(@path) == nil && /#{SEPARATOR_PAT}/o.match?(@path)
- end
-
- # Predicate method for testing whether a path is absolute.
- #
- # It returns +true+ if the pathname begins with a slash.
- #
- # p = Pathname.new('/im/sure')
- # p.absolute?
- # #=> true
- #
- # p = Pathname.new('not/so/sure')
- # p.absolute?
- # #=> false
- def absolute?
- ABSOLUTE_PATH.match? @path
- end
-
- # The opposite of Pathname#absolute?
- #
- # It returns +false+ if the pathname begins with a slash.
- #
- # p = Pathname.new('/im/sure')
- # p.relative?
- # #=> false
- #
- # p = Pathname.new('not/so/sure')
- # p.relative?
- # #=> true
- def relative?
- !absolute?
- end
-
- #
- # Iterates over each component of the path.
- #
- # Pathname.new("/usr/bin/ruby").each_filename {|filename| ... }
- # # yields "usr", "bin", and "ruby".
- #
- # Returns an Enumerator if no block was given.
- #
- # enum = Pathname.new("/usr/bin/ruby").each_filename
- # # ... do stuff ...
- # enum.each { |e| ... }
- # # yields "usr", "bin", and "ruby".
- #
- def each_filename # :yield: filename
- return to_enum(__method__) unless block_given?
- _, names = split_names(@path)
- names.each {|filename| yield filename }
- nil
- end
-
- # Iterates over and yields a new Pathname object
- # for each element in the given path in descending order.
- #
- # Pathname.new('/path/to/some/file.rb').descend {|v| p v}
- # #<Pathname:/>
- # #<Pathname:/path>
- # #<Pathname:/path/to>
- # #<Pathname:/path/to/some>
- # #<Pathname:/path/to/some/file.rb>
- #
- # Pathname.new('path/to/some/file.rb').descend {|v| p v}
- # #<Pathname:path>
- # #<Pathname:path/to>
- # #<Pathname:path/to/some>
- # #<Pathname:path/to/some/file.rb>
- #
- # Returns an Enumerator if no block was given.
- #
- # enum = Pathname.new("/usr/bin/ruby").descend
- # # ... do stuff ...
- # enum.each { |e| ... }
- # # yields Pathnames /, /usr, /usr/bin, and /usr/bin/ruby.
- #
- # It doesn't access the filesystem.
- #
- def descend
- return to_enum(__method__) unless block_given?
- vs = []
- ascend {|v| vs << v }
- vs.reverse_each {|v| yield v }
- nil
- end
-
- # Iterates over and yields a new Pathname object
- # for each element in the given path in ascending order.
- #
- # Pathname.new('/path/to/some/file.rb').ascend {|v| p v}
- # #<Pathname:/path/to/some/file.rb>
- # #<Pathname:/path/to/some>
- # #<Pathname:/path/to>
- # #<Pathname:/path>
- # #<Pathname:/>
- #
- # Pathname.new('path/to/some/file.rb').ascend {|v| p v}
- # #<Pathname:path/to/some/file.rb>
- # #<Pathname:path/to/some>
- # #<Pathname:path/to>
- # #<Pathname:path>
- #
- # Returns an Enumerator if no block was given.
- #
- # enum = Pathname.new("/usr/bin/ruby").ascend
- # # ... do stuff ...
- # enum.each { |e| ... }
- # # yields Pathnames /usr/bin/ruby, /usr/bin, /usr, and /.
- #
- # It doesn't access the filesystem.
- #
- def ascend
- return to_enum(__method__) unless block_given?
- path = @path
- yield self
- while r = chop_basename(path)
- path, = r
- break if path.empty?
- yield self.class.new(del_trailing_separator(path))
- end
- end
-
- #
- # Appends a pathname fragment to +self+ to produce a new Pathname object.
- # Since +other+ is considered as a path relative to +self+, if +other+ is
- # an absolute path, the new Pathname object is created from just +other+.
- #
- # p1 = Pathname.new("/usr") # Pathname:/usr
- # p2 = p1 + "bin/ruby" # Pathname:/usr/bin/ruby
- # p3 = p1 + "/etc/passwd" # Pathname:/etc/passwd
- #
- # # / is aliased to +.
- # p4 = p1 / "bin/ruby" # Pathname:/usr/bin/ruby
- # p5 = p1 / "/etc/passwd" # Pathname:/etc/passwd
- #
- # This method doesn't access the file system; it is pure string manipulation.
- #
- def +(other)
- other = Pathname.new(other) unless Pathname === other
- Pathname.new(plus(@path, other.to_s))
- end
- alias / +
-
- def plus(path1, path2) # -> path # :nodoc:
- prefix2 = path2
- index_list2 = []
- basename_list2 = []
- while r2 = chop_basename(prefix2)
- prefix2, basename2 = r2
- index_list2.unshift prefix2.length
- basename_list2.unshift basename2
- end
- return path2 if prefix2 != ''
- prefix1 = path1
- while true
- while !basename_list2.empty? && basename_list2.first == '.'
- index_list2.shift
- basename_list2.shift
- end
- break unless r1 = chop_basename(prefix1)
- prefix1, basename1 = r1
- next if basename1 == '.'
- if basename1 == '..' || basename_list2.empty? || basename_list2.first != '..'
- prefix1 = prefix1 + basename1
- break
- end
- index_list2.shift
- basename_list2.shift
- end
- r1 = chop_basename(prefix1)
- if !r1 && (r1 = /#{SEPARATOR_PAT}/o.match?(File.basename(prefix1)))
- while !basename_list2.empty? && basename_list2.first == '..'
- index_list2.shift
- basename_list2.shift
- end
- end
- if !basename_list2.empty?
- suffix2 = path2[index_list2.first..-1]
- r1 ? File.join(prefix1, suffix2) : prefix1 + suffix2
- else
- r1 ? prefix1 : File.dirname(prefix1)
- end
- end
- private :plus
-
- #
- # Joins the given pathnames onto +self+ to create a new Pathname object.
- # This is effectively the same as using Pathname#+ to append +self+ and
- # all arguments sequentially.
- #
- # path0 = Pathname.new("/usr") # Pathname:/usr
- # path0 = path0.join("bin/ruby") # Pathname:/usr/bin/ruby
- # # is the same as
- # path1 = Pathname.new("/usr") + "bin/ruby" # Pathname:/usr/bin/ruby
- # path0 == path1
- # #=> true
- #
- def join(*args)
- return self if args.empty?
- result = args.pop
- result = Pathname.new(result) unless Pathname === result
- return result if result.absolute?
- args.reverse_each {|arg|
- arg = Pathname.new(arg) unless Pathname === arg
- result = arg + result
- return result if result.absolute?
- }
- self + result
- end
-
- #
- # Returns the children of the directory (files and subdirectories, not
- # recursive) as an array of Pathname objects.
- #
- # By default, the returned pathnames will have enough information to access
- # the files. If you set +with_directory+ to +false+, then the returned
- # pathnames will contain the filename only.
- #
- # For example:
- # pn = Pathname("/usr/lib/ruby/1.8")
- # pn.children
- # # -> [ Pathname:/usr/lib/ruby/1.8/English.rb,
- # Pathname:/usr/lib/ruby/1.8/Env.rb,
- # Pathname:/usr/lib/ruby/1.8/abbrev.rb, ... ]
- # pn.children(false)
- # # -> [ Pathname:English.rb, Pathname:Env.rb, Pathname:abbrev.rb, ... ]
- #
- # Note that the results never contain the entries +.+ and +..+ in
- # the directory because they are not children.
- #
- def children(with_directory=true)
- with_directory = false if @path == '.'
- result = []
- Dir.foreach(@path) {|e|
- next if e == '.' || e == '..'
- if with_directory
- result << self.class.new(File.join(@path, e))
- else
- result << self.class.new(e)
- end
- }
- result
- end
-
- # Iterates over the children of the directory
- # (files and subdirectories, not recursive).
- #
- # It yields Pathname object for each child.
- #
- # By default, the yielded pathnames will have enough information to access
- # the files.
- #
- # If you set +with_directory+ to +false+, then the returned pathnames will
- # contain the filename only.
- #
- # Pathname("/usr/local").each_child {|f| p f }
- # #=> #<Pathname:/usr/local/share>
- # # #<Pathname:/usr/local/bin>
- # # #<Pathname:/usr/local/games>
- # # #<Pathname:/usr/local/lib>
- # # #<Pathname:/usr/local/include>
- # # #<Pathname:/usr/local/sbin>
- # # #<Pathname:/usr/local/src>
- # # #<Pathname:/usr/local/man>
- #
- # Pathname("/usr/local").each_child(false) {|f| p f }
- # #=> #<Pathname:share>
- # # #<Pathname:bin>
- # # #<Pathname:games>
- # # #<Pathname:lib>
- # # #<Pathname:include>
- # # #<Pathname:sbin>
- # # #<Pathname:src>
- # # #<Pathname:man>
- #
- # Note that the results never contain the entries +.+ and +..+ in
- # the directory because they are not children.
- #
- # See Pathname#children
- #
- def each_child(with_directory=true, &b)
- children(with_directory).each(&b)
- end
-
- #
- # Returns a relative path from the given +base_directory+ to the receiver.
- #
- # If +self+ is absolute, then +base_directory+ must be absolute too.
- #
- # If +self+ is relative, then +base_directory+ must be relative too.
- #
- # This method doesn't access the filesystem. It assumes no symlinks.
- #
- # 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
- base_directory = base_directory.cleanpath.to_s
- dest_prefix = dest_directory
- dest_names = []
- while r = chop_basename(dest_prefix)
- dest_prefix, basename = r
- dest_names.unshift basename if basename != '.'
- end
- base_prefix = base_directory
- base_names = []
- while r = chop_basename(base_prefix)
- base_prefix, basename = r
- base_names.unshift basename if basename != '.'
- end
- unless SAME_PATHS[dest_prefix, base_prefix]
- raise ArgumentError, "different prefix: #{dest_prefix.inspect} and #{base_directory.inspect}"
- end
- while !dest_names.empty? &&
- !base_names.empty? &&
- SAME_PATHS[dest_names.first, base_names.first]
- dest_names.shift
- base_names.shift
- end
- if base_names.include? '..'
- raise ArgumentError, "base_directory has ..: #{base_directory.inspect}"
- end
- base_names.fill('..')
- relpath_names = base_names + dest_names
- if relpath_names.empty?
- Pathname.new('.')
- else
- Pathname.new(File.join(*relpath_names))
- end
- end
-end
-
-
-class Pathname # * Find *
- #
- # Iterates over the directory tree in a depth first manner, yielding a
- # Pathname for each file under "this" directory.
- #
- # Returns an Enumerator if no block is given.
- #
- # Since it is implemented by the standard library module Find, Find.prune can
- # be used to control the traversal.
- #
- # If +self+ is +.+, yielded pathnames begin with a filename in the
- # current directory, not +./+.
- #
- # See Find.find
- #
- def find(ignore_error: true) # :yield: pathname
- return to_enum(__method__, ignore_error: ignore_error) unless block_given?
- require 'find'
- if @path == '.'
- Find.find(@path, ignore_error: ignore_error) {|f| yield self.class.new(f.sub(%r{\A\./}, '')) }
- else
- Find.find(@path, ignore_error: ignore_error) {|f| yield self.class.new(f) }
- end
- end
-end
-
-
-class Pathname # * FileUtils *
- # Creates a full path, including any intermediate directories that don't yet
- # exist.
- #
- # See FileUtils.mkpath and FileUtils.mkdir_p
- def mkpath(mode: nil)
- require 'fileutils'
- FileUtils.mkpath(@path, mode: mode)
- nil
- end
-
- # Recursively deletes a directory, including all directories beneath it.
- #
- # See FileUtils.rm_rf
- def rmtree(noop: nil, verbose: nil, secure: nil)
- # The name "rmtree" is borrowed from File::Path of Perl.
- # File::Path provides "mkpath" and "rmtree".
- require 'fileutils'
- FileUtils.rm_rf(@path, noop: noop, verbose: verbose, secure: secure)
- nil
- end
-end
-
diff --git a/ext/pathname/pathname.c b/ext/pathname/pathname.c
deleted file mode 100644
index cdecb3f897..0000000000
--- a/ext/pathname/pathname.c
+++ /dev/null
@@ -1,1668 +0,0 @@
-#include "ruby.h"
-#include "ruby/encoding.h"
-
-static VALUE rb_cPathname;
-static ID id_ENOTDIR;
-static ID id_at_path;
-static ID id_atime;
-static ID id_base;
-static ID id_basename;
-static ID id_binread;
-static ID id_binwrite;
-static ID id_birthtime;
-static ID id_blockdev_p;
-static ID id_chardev_p;
-static ID id_chmod;
-static ID id_chown;
-static ID id_ctime;
-static ID id_directory_p;
-static ID id_dirname;
-static ID id_empty_p;
-static ID id_entries;
-static ID id_executable_p;
-static ID id_executable_real_p;
-static ID id_exist_p;
-static ID id_expand_path;
-static ID id_extname;
-static ID id_file_p;
-static ID id_fnmatch;
-static ID id_foreach;
-static ID id_ftype;
-static ID id_getwd;
-static ID id_glob;
-static ID id_grpowned_p;
-static ID id_lchmod;
-static ID id_lchown;
-static ID id_link;
-static ID id_lstat;
-static ID id_lutime;
-static ID id_mkdir;
-static ID id_mtime;
-static ID id_open;
-static ID id_owned_p;
-static ID id_pipe_p;
-static ID id_read;
-static ID id_readable_p;
-static ID id_readable_real_p;
-static ID id_readlines;
-static ID id_readlink;
-static ID id_realdirpath;
-static ID id_realpath;
-static ID id_rename;
-static ID id_rmdir;
-static ID id_setgid_p;
-static ID id_setuid_p;
-static ID id_size;
-static ID id_size_p;
-static ID id_socket_p;
-static ID id_split;
-static ID id_stat;
-static ID id_sticky_p;
-static ID id_sub;
-static ID id_symlink;
-static ID id_symlink_p;
-static ID id_sysopen;
-static ID id_to_path;
-static ID id_truncate;
-static ID id_unlink;
-static ID id_utime;
-static ID id_world_readable_p;
-static ID id_world_writable_p;
-static ID id_writable_p;
-static ID id_writable_real_p;
-static ID id_write;
-static ID id_zero_p;
-
-static VALUE
-get_strpath(VALUE obj)
-{
- VALUE strpath;
- strpath = rb_ivar_get(obj, id_at_path);
- if (!RB_TYPE_P(strpath, T_STRING))
- rb_raise(rb_eTypeError, "unexpected @path");
- return strpath;
-}
-
-static void
-set_strpath(VALUE obj, VALUE val)
-{
- rb_ivar_set(obj, id_at_path, val);
-}
-
-/*
- * Create a Pathname object from the given String (or String-like object).
- * If +path+ contains a NULL character (<tt>\0</tt>), an ArgumentError is raised.
- */
-static VALUE
-path_initialize(VALUE self, VALUE arg)
-{
- VALUE str;
- if (RB_TYPE_P(arg, T_STRING)) {
- str = arg;
- }
- else {
- str = rb_check_funcall(arg, id_to_path, 0, NULL);
- if (str == Qundef)
- str = arg;
- StringValue(str);
- }
- if (memchr(RSTRING_PTR(str), '\0', RSTRING_LEN(str)))
- rb_raise(rb_eArgError, "pathname contains null byte");
- str = rb_obj_dup(str);
-
- set_strpath(self, str);
- return self;
-}
-
-/*
- * call-seq:
- * pathname.freeze -> obj
- *
- * Freezes this Pathname.
- *
- * See Object.freeze.
- */
-static VALUE
-path_freeze(VALUE self)
-{
- rb_call_super(0, 0);
- rb_str_freeze(get_strpath(self));
- return self;
-}
-
-/*
- * Compare this pathname with +other+. The comparison is string-based.
- * Be aware that two different paths (<tt>foo.txt</tt> and <tt>./foo.txt</tt>)
- * can refer to the same file.
- */
-static VALUE
-path_eq(VALUE self, VALUE other)
-{
- if (!rb_obj_is_kind_of(other, rb_cPathname))
- return Qfalse;
- return rb_str_equal(get_strpath(self), get_strpath(other));
-}
-
-/*
- * Provides a case-sensitive comparison operator for pathnames.
- *
- * Pathname.new('/usr') <=> Pathname.new('/usr/bin')
- * #=> -1
- * Pathname.new('/usr/bin') <=> Pathname.new('/usr/bin')
- * #=> 0
- * Pathname.new('/usr/bin') <=> Pathname.new('/USR/BIN')
- * #=> 1
- *
- * It will return +-1+, +0+ or +1+ depending on the value of the left argument
- * relative to the right argument. Or it will return +nil+ if the arguments
- * are not comparable.
- */
-static VALUE
-path_cmp(VALUE self, VALUE other)
-{
- VALUE s1, s2;
- char *p1, *p2;
- char *e1, *e2;
- if (!rb_obj_is_kind_of(other, rb_cPathname))
- return Qnil;
- s1 = get_strpath(self);
- s2 = get_strpath(other);
- p1 = RSTRING_PTR(s1);
- p2 = RSTRING_PTR(s2);
- e1 = p1 + RSTRING_LEN(s1);
- e2 = p2 + RSTRING_LEN(s2);
- while (p1 < e1 && p2 < e2) {
- int c1, c2;
- c1 = (unsigned char)*p1++;
- c2 = (unsigned char)*p2++;
- if (c1 == '/') c1 = '\0';
- if (c2 == '/') c2 = '\0';
- if (c1 != c2) {
- if (c1 < c2)
- return INT2FIX(-1);
- else
- return INT2FIX(1);
- }
- }
- if (p1 < e1)
- return INT2FIX(1);
- if (p2 < e2)
- return INT2FIX(-1);
- return INT2FIX(0);
-}
-
-#ifndef ST2FIX
-#define ST2FIX(h) LONG2FIX((long)(h))
-#endif
-
-/* :nodoc: */
-static VALUE
-path_hash(VALUE self)
-{
- return ST2FIX(rb_str_hash(get_strpath(self)));
-}
-
-/*
- * call-seq:
- * pathname.to_s -> string
- * pathname.to_path -> string
- *
- * Return the path as a String.
- *
- * to_path is implemented so Pathname objects are usable with File.open, etc.
- */
-static VALUE
-path_to_s(VALUE self)
-{
- return rb_obj_dup(get_strpath(self));
-}
-
-/* :nodoc: */
-static VALUE
-path_inspect(VALUE self)
-{
- const char *c = rb_obj_classname(self);
- VALUE str = get_strpath(self);
- return rb_sprintf("#<%s:%"PRIsVALUE">", c, str);
-}
-
-/*
- * Return a pathname which is substituted by String#sub.
- *
- * path1 = Pathname.new('/usr/bin/perl')
- * path1.sub('perl', 'ruby')
- * #=> #<Pathname:/usr/bin/ruby>
- */
-static VALUE
-path_sub(int argc, VALUE *argv, VALUE self)
-{
- VALUE str = get_strpath(self);
-
- if (rb_block_given_p()) {
- str = rb_block_call(str, id_sub, argc, argv, 0, 0);
- }
- else {
- str = rb_funcallv(str, id_sub, argc, argv);
- }
- return rb_class_new_instance(1, &str, rb_obj_class(self));
-}
-
-/*
- * Return a pathname with +repl+ added as a suffix to the basename.
- *
- * If self has no extension part, +repl+ is appended.
- *
- * Pathname.new('/usr/bin/shutdown').sub_ext('.rb')
- * #=> #<Pathname:/usr/bin/shutdown.rb>
- */
-static VALUE
-path_sub_ext(VALUE self, VALUE repl)
-{
- VALUE str = get_strpath(self);
- VALUE str2;
- long extlen;
- const char *ext;
- const char *p;
-
- StringValue(repl);
- p = RSTRING_PTR(str);
- extlen = RSTRING_LEN(str);
- ext = ruby_enc_find_extname(p, &extlen, rb_enc_get(str));
- if (ext == NULL) {
- ext = p + RSTRING_LEN(str);
- }
- else if (extlen <= 1) {
- ext += extlen;
- }
- str2 = rb_str_subseq(str, 0, ext-p);
- rb_str_append(str2, repl);
- return rb_class_new_instance(1, &str2, rb_obj_class(self));
-}
-
-/* Facade for File */
-
-/*
- * Returns the real (absolute) pathname for +self+ in the actual
- * filesystem.
- *
- * Does not contain symlinks or useless dots, +..+ and +.+.
- *
- * All components of the pathname must exist when this method is
- * called.
- *
- */
-static VALUE
-path_realpath(int argc, VALUE *argv, VALUE self)
-{
- VALUE basedir, str;
- rb_scan_args(argc, argv, "01", &basedir);
- str = rb_funcall(rb_cFile, id_realpath, 2, get_strpath(self), basedir);
- return rb_class_new_instance(1, &str, rb_obj_class(self));
-}
-
-/*
- * Returns the real (absolute) pathname of +self+ in the actual filesystem.
- *
- * Does not contain symlinks or useless dots, +..+ and +.+.
- *
- * The last component of the real pathname can be nonexistent.
- */
-static VALUE
-path_realdirpath(int argc, VALUE *argv, VALUE self)
-{
- VALUE basedir, str;
- rb_scan_args(argc, argv, "01", &basedir);
- str = rb_funcall(rb_cFile, id_realdirpath, 2, get_strpath(self), basedir);
- return rb_class_new_instance(1, &str, rb_obj_class(self));
-}
-
-/*
- * call-seq:
- * pathname.each_line {|line| ... }
- * pathname.each_line(sep=$/ [, open_args]) {|line| block } -> nil
- * pathname.each_line(limit [, open_args]) {|line| block } -> nil
- * pathname.each_line(sep, limit [, open_args]) {|line| block } -> nil
- * pathname.each_line(...) -> an_enumerator
- *
- * Iterates over each line in the file and yields a String object for each.
- */
-static VALUE
-path_each_line(int argc, VALUE *argv, VALUE self)
-{
- VALUE args[4];
- int n;
-
- 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_kw(rb_cFile, id_foreach, 1+n, args, 0, 0, RB_PASS_CALLED_KEYWORDS);
- }
- else {
- return rb_funcallv_kw(rb_cFile, id_foreach, 1+n, args, RB_PASS_CALLED_KEYWORDS);
- }
-}
-
-/*
- * call-seq:
- * pathname.read([length [, offset]]) -> string
- * pathname.read([length [, offset]], open_args) -> string
- *
- * Returns all data from the file, or the first +N+ bytes if specified.
- *
- * See File.read.
- *
- */
-static VALUE
-path_read(int argc, VALUE *argv, VALUE self)
-{
- VALUE args[4];
- int n;
-
- args[0] = get_strpath(self);
- n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]);
- return rb_funcallv_kw(rb_cFile, id_read, 1+n, args, RB_PASS_CALLED_KEYWORDS);
-}
-
-/*
- * call-seq:
- * pathname.binread([length [, offset]]) -> string
- *
- * Returns all the bytes from the file, or the first +N+ if specified.
- *
- * See File.binread.
- *
- */
-static VALUE
-path_binread(int argc, VALUE *argv, VALUE self)
-{
- VALUE args[3];
- int n;
-
- args[0] = get_strpath(self);
- n = rb_scan_args(argc, argv, "02", &args[1], &args[2]);
- return rb_funcallv(rb_cFile, id_binread, 1+n, args);
-}
-
-/*
- * call-seq:
- * pathname.write(string, [offset] ) => fixnum
- * pathname.write(string, [offset], open_args ) => fixnum
- *
- * Writes +contents+ to the file.
- *
- * See File.write.
- *
- */
-static VALUE
-path_write(int argc, VALUE *argv, VALUE self)
-{
- VALUE args[4];
- int n;
-
- args[0] = get_strpath(self);
- n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]);
- return rb_funcallv_kw(rb_cFile, id_write, 1+n, args, RB_PASS_CALLED_KEYWORDS);
-}
-
-/*
- * call-seq:
- * pathname.binwrite(string, [offset] ) => fixnum
- * pathname.binwrite(string, [offset], open_args ) => fixnum
- *
- * Writes +contents+ to the file, opening it in binary mode.
- *
- * See File.binwrite.
- *
- */
-static VALUE
-path_binwrite(int argc, VALUE *argv, VALUE self)
-{
- VALUE args[4];
- int n;
-
- args[0] = get_strpath(self);
- n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]);
- return rb_funcallv_kw(rb_cFile, id_binwrite, 1+n, args, RB_PASS_CALLED_KEYWORDS);
-}
-
-/*
- * call-seq:
- * pathname.readlines(sep=$/ [, open_args]) -> array
- * pathname.readlines(limit [, open_args]) -> array
- * pathname.readlines(sep, limit [, open_args]) -> array
- *
- * Returns all the lines from the file.
- *
- * See File.readlines.
- *
- */
-static VALUE
-path_readlines(int argc, VALUE *argv, VALUE self)
-{
- VALUE args[4];
- int n;
-
- args[0] = get_strpath(self);
- n = rb_scan_args(argc, argv, "03", &args[1], &args[2], &args[3]);
- return rb_funcallv_kw(rb_cFile, id_readlines, 1+n, args, RB_PASS_CALLED_KEYWORDS);
-}
-
-/*
- * call-seq:
- * pathname.sysopen([mode, [perm]]) -> fixnum
- *
- * See IO.sysopen.
- *
- */
-static VALUE
-path_sysopen(int argc, VALUE *argv, VALUE self)
-{
- VALUE args[3];
- int n;
-
- args[0] = get_strpath(self);
- n = rb_scan_args(argc, argv, "02", &args[1], &args[2]);
- return rb_funcallv(rb_cIO, id_sysopen, 1+n, args);
-}
-
-/*
- * call-seq:
- * pathname.atime -> time
- *
- * Returns the last access time for the file.
- *
- * See File.atime.
- */
-static VALUE
-path_atime(VALUE self)
-{
- return rb_funcall(rb_cFile, id_atime, 1, get_strpath(self));
-}
-
-/*
- * call-seq:
- * pathname.birthtime -> time
- *
- * Returns the birth time for the file.
- * If the platform doesn't have birthtime, raises NotImplementedError.
- *
- * See File.birthtime.
- */
-static VALUE
-path_birthtime(VALUE self)
-{
- return rb_funcall(rb_cFile, id_birthtime, 1, get_strpath(self));
-}
-
-/*
- * call-seq:
- * pathname.ctime -> time
- *
- * Returns the last change time, using directory information, not the file itself.
- *
- * See File.ctime.
- */
-static VALUE
-path_ctime(VALUE self)
-{
- return rb_funcall(rb_cFile, id_ctime, 1, get_strpath(self));
-}
-
-/*
- * call-seq:
- * pathname.mtime -> time
- *
- * Returns the last modified time of the file.
- *
- * See File.mtime.
- */
-static VALUE
-path_mtime(VALUE self)
-{
- return rb_funcall(rb_cFile, id_mtime, 1, get_strpath(self));
-}
-
-/*
- * call-seq:
- * pathname.chmod(mode_int) -> integer
- *
- * Changes file permissions.
- *
- * See File.chmod.
- */
-static VALUE
-path_chmod(VALUE self, VALUE mode)
-{
- return rb_funcall(rb_cFile, id_chmod, 2, mode, get_strpath(self));
-}
-
-/*
- * call-seq:
- * pathname.lchmod(mode_int) -> integer
- *
- * Same as Pathname.chmod, but does not follow symbolic links.
- *
- * See File.lchmod.
- */
-static VALUE
-path_lchmod(VALUE self, VALUE mode)
-{
- return rb_funcall(rb_cFile, id_lchmod, 2, mode, get_strpath(self));
-}
-
-/*
- * call-seq:
- * pathname.chown(owner_int, group_int) -> integer
- *
- * Change owner and group of the file.
- *
- * See File.chown.
- */
-static VALUE
-path_chown(VALUE self, VALUE owner, VALUE group)
-{
- return rb_funcall(rb_cFile, id_chown, 3, owner, group, get_strpath(self));
-}
-
-/*
- * call-seq:
- * pathname.lchown(owner_int, group_int) -> integer
- *
- * Same as Pathname.chown, but does not follow symbolic links.
- *
- * See File.lchown.
- */
-static VALUE
-path_lchown(VALUE self, VALUE owner, VALUE group)
-{
- return rb_funcall(rb_cFile, id_lchown, 3, owner, group, get_strpath(self));
-}
-
-/*
- * call-seq:
- * pathname.fnmatch(pattern, [flags]) -> true or false
- * pathname.fnmatch?(pattern, [flags]) -> true or false
- *
- * Return +true+ if the receiver matches the given pattern.
- *
- * See File.fnmatch.
- */
-static VALUE
-path_fnmatch(int argc, VALUE *argv, VALUE self)
-{
- VALUE str = get_strpath(self);
- VALUE pattern, flags;
- if (rb_scan_args(argc, argv, "11", &pattern, &flags) == 1)
- return rb_funcall(rb_cFile, id_fnmatch, 2, pattern, str);
- else
- return rb_funcall(rb_cFile, id_fnmatch, 3, pattern, str, flags);
-}
-
-/*
- * call-seq:
- * pathname.ftype -> string
- *
- * Returns "type" of file ("file", "directory", etc).
- *
- * See File.ftype.
- */
-static VALUE
-path_ftype(VALUE self)
-{
- return rb_funcall(rb_cFile, id_ftype, 1, get_strpath(self));
-}
-
-/*
- * call-seq:
- * pathname.make_link(old)
- *
- * Creates a hard link at _pathname_.
- *
- * See File.link.
- */
-static VALUE
-path_make_link(VALUE self, VALUE old)
-{
- return rb_funcall(rb_cFile, id_link, 2, old, get_strpath(self));
-}
-
-/*
- * 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.
- */
-static VALUE
-path_open(int argc, VALUE *argv, VALUE self)
-{
- VALUE args[4];
- int n;
-
- 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_kw(rb_cFile, id_open, 1+n, args, 0, 0, RB_PASS_CALLED_KEYWORDS);
- }
- else {
- return rb_funcallv_kw(rb_cFile, id_open, 1+n, args, RB_PASS_CALLED_KEYWORDS);
- }
-}
-
-/*
- * Read symbolic link.
- *
- * See File.readlink.
- */
-static VALUE
-path_readlink(VALUE self)
-{
- VALUE str;
- str = rb_funcall(rb_cFile, id_readlink, 1, get_strpath(self));
- return rb_class_new_instance(1, &str, rb_obj_class(self));
-}
-
-/*
- * Rename the file.
- *
- * See File.rename.
- */
-static VALUE
-path_rename(VALUE self, VALUE to)
-{
- return rb_funcall(rb_cFile, id_rename, 2, get_strpath(self), to);
-}
-
-/*
- * Returns a File::Stat object.
- *
- * See File.stat.
- */
-static VALUE
-path_stat(VALUE self)
-{
- return rb_funcall(rb_cFile, id_stat, 1, get_strpath(self));
-}
-
-/*
- * See File.lstat.
- */
-static VALUE
-path_lstat(VALUE self)
-{
- return rb_funcall(rb_cFile, id_lstat, 1, get_strpath(self));
-}
-
-/*
- * call-seq:
- * pathname.make_symlink(old)
- *
- * Creates a symbolic link.
- *
- * See File.symlink.
- */
-static VALUE
-path_make_symlink(VALUE self, VALUE old)
-{
- return rb_funcall(rb_cFile, id_symlink, 2, old, get_strpath(self));
-}
-
-/*
- * Truncates the file to +length+ bytes.
- *
- * See File.truncate.
- */
-static VALUE
-path_truncate(VALUE self, VALUE length)
-{
- return rb_funcall(rb_cFile, id_truncate, 2, get_strpath(self), length);
-}
-
-/*
- * Update the access and modification times of the file.
- *
- * See File.utime.
- */
-static VALUE
-path_utime(VALUE self, VALUE atime, VALUE mtime)
-{
- return rb_funcall(rb_cFile, id_utime, 3, atime, mtime, get_strpath(self));
-}
-
-/*
- * Update the access and modification times of the file.
- *
- * Same as Pathname#utime, but does not follow symbolic links.
- *
- * See File.lutime.
- */
-static VALUE
-path_lutime(VALUE self, VALUE atime, VALUE mtime)
-{
- return rb_funcall(rb_cFile, id_lutime, 3, atime, mtime, get_strpath(self));
-}
-
-/*
- * Returns the last component of the path.
- *
- * See File.basename.
- */
-static VALUE
-path_basename(int argc, VALUE *argv, VALUE self)
-{
- VALUE str = get_strpath(self);
- VALUE fext;
- if (rb_scan_args(argc, argv, "01", &fext) == 0)
- str = rb_funcall(rb_cFile, id_basename, 1, str);
- else
- str = rb_funcall(rb_cFile, id_basename, 2, str, fext);
- return rb_class_new_instance(1, &str, rb_obj_class(self));
-}
-
-/*
- * Returns all but the last component of the path.
- *
- * See File.dirname.
- */
-static VALUE
-path_dirname(VALUE self)
-{
- VALUE str = get_strpath(self);
- str = rb_funcall(rb_cFile, id_dirname, 1, str);
- return rb_class_new_instance(1, &str, rb_obj_class(self));
-}
-
-/*
- * Returns the file's extension.
- *
- * See File.extname.
- */
-static VALUE
-path_extname(VALUE self)
-{
- VALUE str = get_strpath(self);
- return rb_funcall(rb_cFile, id_extname, 1, str);
-}
-
-/*
- * Returns the absolute path for the file.
- *
- * See File.expand_path.
- */
-static VALUE
-path_expand_path(int argc, VALUE *argv, VALUE self)
-{
- VALUE str = get_strpath(self);
- VALUE dname;
- if (rb_scan_args(argc, argv, "01", &dname) == 0)
- str = rb_funcall(rb_cFile, id_expand_path, 1, str);
- else
- str = rb_funcall(rb_cFile, id_expand_path, 2, str, dname);
- return rb_class_new_instance(1, &str, rb_obj_class(self));
-}
-
-/*
- * Returns the #dirname and the #basename in an Array.
- *
- * See File.split.
- */
-static VALUE
-path_split(VALUE self)
-{
- VALUE str = get_strpath(self);
- VALUE ary, dirname, basename;
- ary = rb_funcall(rb_cFile, id_split, 1, str);
- 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));
- basename = rb_class_new_instance(1, &basename, rb_obj_class(self));
- return rb_ary_new3(2, dirname, basename);
-}
-
-/*
- * See FileTest.blockdev?.
- */
-static VALUE
-path_blockdev_p(VALUE self)
-{
- return rb_funcall(rb_mFileTest, id_blockdev_p, 1, get_strpath(self));
-}
-
-/*
- * See FileTest.chardev?.
- */
-static VALUE
-path_chardev_p(VALUE self)
-{
- return rb_funcall(rb_mFileTest, id_chardev_p, 1, get_strpath(self));
-}
-
-/*
- * See FileTest.executable?.
- */
-static VALUE
-path_executable_p(VALUE self)
-{
- return rb_funcall(rb_mFileTest, id_executable_p, 1, get_strpath(self));
-}
-
-/*
- * See FileTest.executable_real?.
- */
-static VALUE
-path_executable_real_p(VALUE self)
-{
- return rb_funcall(rb_mFileTest, id_executable_real_p, 1, get_strpath(self));
-}
-
-/*
- * See FileTest.exist?.
- */
-static VALUE
-path_exist_p(VALUE self)
-{
- return rb_funcall(rb_mFileTest, id_exist_p, 1, get_strpath(self));
-}
-
-/*
- * See FileTest.grpowned?.
- */
-static VALUE
-path_grpowned_p(VALUE self)
-{
- return rb_funcall(rb_mFileTest, id_grpowned_p, 1, get_strpath(self));
-}
-
-/*
- * See FileTest.directory?.
- */
-static VALUE
-path_directory_p(VALUE self)
-{
- return rb_funcall(rb_mFileTest, id_directory_p, 1, get_strpath(self));
-}
-
-/*
- * See FileTest.file?.
- */
-static VALUE
-path_file_p(VALUE self)
-{
- return rb_funcall(rb_mFileTest, id_file_p, 1, get_strpath(self));
-}
-
-/*
- * See FileTest.pipe?.
- */
-static VALUE
-path_pipe_p(VALUE self)
-{
- return rb_funcall(rb_mFileTest, id_pipe_p, 1, get_strpath(self));
-}
-
-/*
- * See FileTest.socket?.
- */
-static VALUE
-path_socket_p(VALUE self)
-{
- return rb_funcall(rb_mFileTest, id_socket_p, 1, get_strpath(self));
-}
-
-/*
- * See FileTest.owned?.
- */
-static VALUE
-path_owned_p(VALUE self)
-{
- return rb_funcall(rb_mFileTest, id_owned_p, 1, get_strpath(self));
-}
-
-/*
- * See FileTest.readable?.
- */
-static VALUE
-path_readable_p(VALUE self)
-{
- return rb_funcall(rb_mFileTest, id_readable_p, 1, get_strpath(self));
-}
-
-/*
- * See FileTest.world_readable?.
- */
-static VALUE
-path_world_readable_p(VALUE self)
-{
- return rb_funcall(rb_mFileTest, id_world_readable_p, 1, get_strpath(self));
-}
-
-/*
- * See FileTest.readable_real?.
- */
-static VALUE
-path_readable_real_p(VALUE self)
-{
- return rb_funcall(rb_mFileTest, id_readable_real_p, 1, get_strpath(self));
-}
-
-/*
- * See FileTest.setuid?.
- */
-static VALUE
-path_setuid_p(VALUE self)
-{
- return rb_funcall(rb_mFileTest, id_setuid_p, 1, get_strpath(self));
-}
-
-/*
- * See FileTest.setgid?.
- */
-static VALUE
-path_setgid_p(VALUE self)
-{
- return rb_funcall(rb_mFileTest, id_setgid_p, 1, get_strpath(self));
-}
-
-/*
- * See FileTest.size.
- */
-static VALUE
-path_size(VALUE self)
-{
- return rb_funcall(rb_mFileTest, id_size, 1, get_strpath(self));
-}
-
-/*
- * See FileTest.size?.
- */
-static VALUE
-path_size_p(VALUE self)
-{
- return rb_funcall(rb_mFileTest, id_size_p, 1, get_strpath(self));
-}
-
-/*
- * See FileTest.sticky?.
- */
-static VALUE
-path_sticky_p(VALUE self)
-{
- return rb_funcall(rb_mFileTest, id_sticky_p, 1, get_strpath(self));
-}
-
-/*
- * See FileTest.symlink?.
- */
-static VALUE
-path_symlink_p(VALUE self)
-{
- return rb_funcall(rb_mFileTest, id_symlink_p, 1, get_strpath(self));
-}
-
-/*
- * See FileTest.writable?.
- */
-static VALUE
-path_writable_p(VALUE self)
-{
- return rb_funcall(rb_mFileTest, id_writable_p, 1, get_strpath(self));
-}
-
-/*
- * See FileTest.world_writable?.
- */
-static VALUE
-path_world_writable_p(VALUE self)
-{
- return rb_funcall(rb_mFileTest, id_world_writable_p, 1, get_strpath(self));
-}
-
-/*
- * See FileTest.writable_real?.
- */
-static VALUE
-path_writable_real_p(VALUE self)
-{
- return rb_funcall(rb_mFileTest, id_writable_real_p, 1, get_strpath(self));
-}
-
-/*
- * See FileTest.zero?.
- */
-static VALUE
-path_zero_p(VALUE self)
-{
- return rb_funcall(rb_mFileTest, id_zero_p, 1, get_strpath(self));
-}
-
-/*
- * Tests the file is empty.
- *
- * See Dir#empty? and FileTest.empty?.
- */
-static VALUE
-path_empty_p(VALUE self)
-{
-
- VALUE path = get_strpath(self);
- if (RTEST(rb_funcall(rb_mFileTest, id_directory_p, 1, path)))
- return rb_funcall(rb_cDir, id_empty_p, 1, path);
- else
- return rb_funcall(rb_mFileTest, id_empty_p, 1, path);
-}
-
-static VALUE
-s_glob_i(RB_BLOCK_CALL_FUNC_ARGLIST(elt, klass))
-{
- return rb_yield(rb_class_new_instance(1, &elt, klass));
-}
-
-/*
- * Returns or yields Pathname objects.
- *
- * Pathname.glob("lib/i*.rb")
- * #=> [#<Pathname:lib/ipaddr.rb>, #<Pathname:lib/irb.rb>]
- *
- * See Dir.glob.
- */
-static VALUE
-path_s_glob(int argc, VALUE *argv, VALUE klass)
-{
- VALUE args[3];
- int n;
-
- n = rb_scan_args(argc, argv, "12", &args[0], &args[1], &args[2]);
- if (rb_block_given_p()) {
- return rb_block_call_kw(rb_cDir, id_glob, n, args, s_glob_i, klass, RB_PASS_CALLED_KEYWORDS);
- }
- else {
- VALUE ary;
- long i;
- ary = rb_funcallv_kw(rb_cDir, id_glob, n, args, RB_PASS_CALLED_KEYWORDS);
- ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- VALUE elt = RARRAY_AREF(ary, i);
- elt = rb_class_new_instance(1, &elt, klass);
- rb_ary_store(ary, i, elt);
- }
- return ary;
- }
-}
-
-static VALUE
-glob_i(RB_BLOCK_CALL_FUNC_ARGLIST(elt, self))
-{
- elt = rb_funcall(self, '+', 1, elt);
- return rb_yield(elt);
-}
-
-/*
- * Returns or yields Pathname objects.
- *
- * Pathname("ruby-2.4.2").glob("R*.md")
- * #=> [#<Pathname:ruby-2.4.2/README.md>, #<Pathname:ruby-2.4.2/README.ja.md>]
- *
- * See Dir.glob.
- * This method uses the +base+ keyword argument of Dir.glob.
- */
-static VALUE
-path_glob(int argc, VALUE *argv, VALUE self)
-{
- VALUE args[3];
- int n;
-
- n = rb_scan_args(argc, argv, "11", &args[0], &args[1]);
- if (n == 1)
- args[1] = INT2FIX(0);
-
- args[2] = rb_hash_new();
- rb_hash_aset(args[2], ID2SYM(id_base), get_strpath(self));
-
- n = 3;
-
- if (rb_block_given_p()) {
- return rb_block_call_kw(rb_cDir, id_glob, n, args, glob_i, self, RB_PASS_KEYWORDS);
- }
- else {
- VALUE ary;
- long i;
- ary = rb_funcallv_kw(rb_cDir, id_glob, n, args, RB_PASS_KEYWORDS);
- ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- VALUE elt = RARRAY_AREF(ary, i);
- elt = rb_funcall(self, '+', 1, elt);
- rb_ary_store(ary, i, elt);
- }
- return ary;
- }
-}
-
-/*
- * Returns the current working directory as a Pathname.
- *
- * Pathname.getwd
- * #=> #<Pathname:/home/zzak/projects/ruby>
- *
- * See Dir.getwd.
- */
-static VALUE
-path_s_getwd(VALUE klass)
-{
- VALUE str;
- str = rb_funcall(rb_cDir, id_getwd, 0);
- return rb_class_new_instance(1, &str, klass);
-}
-
-/*
- * Return the entries (files and subdirectories) in the directory, each as a
- * Pathname object.
- *
- * The results contains just the names in the directory, without any trailing
- * slashes or recursive look-up.
- *
- * pp Pathname.new('/usr/local').entries
- * #=> [#<Pathname:share>,
- * # #<Pathname:lib>,
- * # #<Pathname:..>,
- * # #<Pathname:include>,
- * # #<Pathname:etc>,
- * # #<Pathname:bin>,
- * # #<Pathname:man>,
- * # #<Pathname:games>,
- * # #<Pathname:.>,
- * # #<Pathname:sbin>,
- * # #<Pathname:src>]
- *
- * The result may contain the current directory <code>#<Pathname:.></code> and
- * the parent directory <code>#<Pathname:..></code>.
- *
- * If you don't want +.+ and +..+ and
- * want directories, consider Pathname#children.
- */
-static VALUE
-path_entries(VALUE self)
-{
- VALUE klass, str, ary;
- long i;
- klass = rb_obj_class(self);
- str = get_strpath(self);
- ary = rb_funcall(rb_cDir, id_entries, 1, str);
- ary = rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
- for (i = 0; i < RARRAY_LEN(ary); i++) {
- VALUE elt = RARRAY_AREF(ary, i);
- elt = rb_class_new_instance(1, &elt, klass);
- rb_ary_store(ary, i, elt);
- }
- return ary;
-}
-
-/*
- * Create the referenced directory.
- *
- * See Dir.mkdir.
- */
-static VALUE
-path_mkdir(int argc, VALUE *argv, VALUE self)
-{
- VALUE str = get_strpath(self);
- VALUE vmode;
- if (rb_scan_args(argc, argv, "01", &vmode) == 0)
- return rb_funcall(rb_cDir, id_mkdir, 1, str);
- else
- return rb_funcall(rb_cDir, id_mkdir, 2, str, vmode);
-}
-
-/*
- * Remove the referenced directory.
- *
- * See Dir.rmdir.
- */
-static VALUE
-path_rmdir(VALUE self)
-{
- return rb_funcall(rb_cDir, id_rmdir, 1, get_strpath(self));
-}
-
-/*
- * Opens the referenced directory.
- *
- * See Dir.open.
- */
-static VALUE
-path_opendir(VALUE self)
-{
- VALUE args[1];
-
- args[0] = get_strpath(self);
- return rb_block_call(rb_cDir, id_open, 1, args, 0, 0);
-}
-
-static VALUE
-each_entry_i(RB_BLOCK_CALL_FUNC_ARGLIST(elt, klass))
-{
- return rb_yield(rb_class_new_instance(1, &elt, klass));
-}
-
-/*
- * Iterates over the entries (files and subdirectories) in the directory,
- * yielding a Pathname object for each entry.
- */
-static VALUE
-path_each_entry(VALUE self)
-{
- VALUE args[1];
- RETURN_ENUMERATOR(self, 0, 0);
-
- args[0] = get_strpath(self);
- return rb_block_call(rb_cDir, id_foreach, 1, args, each_entry_i, rb_obj_class(self));
-}
-
-static VALUE
-unlink_body(VALUE str)
-{
- return rb_funcall(rb_cDir, id_unlink, 1, str);
-}
-
-static VALUE
-unlink_rescue(VALUE str, VALUE errinfo)
-{
- return rb_funcall(rb_cFile, id_unlink, 1, str);
-}
-
-/*
- * Removes a file or directory, using File.unlink if +self+ is a file, or
- * Dir.unlink as necessary.
- */
-static VALUE
-path_unlink(VALUE self)
-{
- VALUE eENOTDIR = rb_const_get_at(rb_mErrno, id_ENOTDIR);
- VALUE str = get_strpath(self);
- return rb_rescue2(unlink_body, str, unlink_rescue, str, eENOTDIR, (VALUE)0);
-}
-
-/*
- * :call-seq:
- * Pathname(path) -> pathname
- *
- * Creates a new Pathname object from the given string, +path+, and returns
- * pathname object.
- *
- * In order to use this constructor, you must first require the Pathname
- * standard library extension.
- *
- * require 'pathname'
- * Pathname("/home/zzak")
- * #=> #<Pathname:/home/zzak>
- *
- * See also Pathname::new for more information.
- */
-static VALUE
-path_f_pathname(VALUE self, VALUE str)
-{
- if (CLASS_OF(str) == rb_cPathname)
- return str;
- return rb_class_new_instance(1, &str, rb_cPathname);
-}
-
-/*
- *
- * Pathname represents the name of a file or directory on the filesystem,
- * but not the file itself.
- *
- * The pathname depends on the Operating System: Unix, Windows, etc.
- * This library works with pathnames of local OS, however non-Unix pathnames
- * are supported experimentally.
- *
- * A Pathname can be relative or absolute. It's not until you try to
- * reference the file that it even matters whether the file exists or not.
- *
- * Pathname is immutable. It has no method for destructive update.
- *
- * The goal of this class is to manipulate file path information in a neater
- * way than standard Ruby provides. The examples below demonstrate the
- * difference.
- *
- * *All* functionality from File, FileTest, and some from Dir and FileUtils is
- * included, in an unsurprising way. It is essentially a facade for all of
- * these, and more.
- *
- * == Examples
- *
- * === Example 1: Using Pathname
- *
- * require 'pathname'
- * pn = Pathname.new("/usr/bin/ruby")
- * size = pn.size # 27662
- * isdir = pn.directory? # false
- * dir = pn.dirname # Pathname:/usr/bin
- * base = pn.basename # Pathname:ruby
- * dir, base = pn.split # [Pathname:/usr/bin, Pathname:ruby]
- * data = pn.read
- * pn.open { |f| _ }
- * pn.each_line { |line| _ }
- *
- * === Example 2: Using standard Ruby
- *
- * pn = "/usr/bin/ruby"
- * size = File.size(pn) # 27662
- * isdir = File.directory?(pn) # false
- * dir = File.dirname(pn) # "/usr/bin"
- * base = File.basename(pn) # "ruby"
- * dir, base = File.split(pn) # ["/usr/bin", "ruby"]
- * data = File.read(pn)
- * File.open(pn) { |f| _ }
- * File.foreach(pn) { |line| _ }
- *
- * === Example 3: Special features
- *
- * p1 = Pathname.new("/usr/lib") # Pathname:/usr/lib
- * p2 = p1 + "ruby/1.8" # Pathname:/usr/lib/ruby/1.8
- * p3 = p1.parent # Pathname:/usr
- * p4 = p2.relative_path_from(p3) # Pathname:lib/ruby/1.8
- * pwd = Pathname.pwd # Pathname:/home/gavin
- * pwd.absolute? # true
- * p5 = Pathname.new "." # Pathname:.
- * p5 = p5 + "music/../articles" # Pathname:music/../articles
- * p5.cleanpath # Pathname:articles
- * p5.realpath # Pathname:/home/gavin/articles
- * p5.children # [Pathname:/home/gavin/articles/linux, ...]
- *
- * == Breakdown of functionality
- *
- * === Core methods
- *
- * These methods are effectively manipulating a String, because that's
- * all a path is. None of these access the file system except for
- * #mountpoint?, #children, #each_child, #realdirpath and #realpath.
- *
- * - +
- * - #join
- * - #parent
- * - #root?
- * - #absolute?
- * - #relative?
- * - #relative_path_from
- * - #each_filename
- * - #cleanpath
- * - #realpath
- * - #realdirpath
- * - #children
- * - #each_child
- * - #mountpoint?
- *
- * === File status predicate methods
- *
- * These methods are a facade for FileTest:
- * - #blockdev?
- * - #chardev?
- * - #directory?
- * - #executable?
- * - #executable_real?
- * - #exist?
- * - #file?
- * - #grpowned?
- * - #owned?
- * - #pipe?
- * - #readable?
- * - #world_readable?
- * - #readable_real?
- * - #setgid?
- * - #setuid?
- * - #size
- * - #size?
- * - #socket?
- * - #sticky?
- * - #symlink?
- * - #writable?
- * - #world_writable?
- * - #writable_real?
- * - #zero?
- *
- * === File property and manipulation methods
- *
- * These methods are a facade for File:
- * - #atime
- * - #birthtime
- * - #ctime
- * - #mtime
- * - #chmod(mode)
- * - #lchmod(mode)
- * - #chown(owner, group)
- * - #lchown(owner, group)
- * - #fnmatch(pattern, *args)
- * - #fnmatch?(pattern, *args)
- * - #ftype
- * - #make_link(old)
- * - #open(*args, &block)
- * - #readlink
- * - #rename(to)
- * - #stat
- * - #lstat
- * - #make_symlink(old)
- * - #truncate(length)
- * - #utime(atime, mtime)
- * - #lutime(atime, mtime)
- * - #basename(*args)
- * - #dirname
- * - #extname
- * - #expand_path(*args)
- * - #split
- *
- * === Directory methods
- *
- * These methods are a facade for Dir:
- * - Pathname.glob(*args)
- * - Pathname.getwd / Pathname.pwd
- * - #rmdir
- * - #entries
- * - #each_entry(&block)
- * - #mkdir(*args)
- * - #opendir(*args)
- *
- * === IO
- *
- * These methods are a facade for IO:
- * - #each_line(*args, &block)
- * - #read(*args)
- * - #binread(*args)
- * - #readlines(*args)
- * - #sysopen(*args)
- * - #write(*args)
- * - #binwrite(*args)
- *
- * === Utilities
- *
- * These methods are a mixture of Find, FileUtils, and others:
- * - #find(&block)
- * - #mkpath
- * - #rmtree
- * - #unlink / #delete
- *
- *
- * == Method documentation
- *
- * As the above section shows, most of the methods in Pathname are facades. The
- * documentation for these methods generally just says, for instance, "See
- * FileTest.writable?", as you should be familiar with the original method
- * anyway, and its documentation (e.g. through +ri+) will contain more
- * information. In some cases, a brief description will follow.
- */
-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);
- rb_define_method(rb_cPathname, "initialize", path_initialize, 1);
- rb_define_method(rb_cPathname, "freeze", path_freeze, 0);
- rb_define_method(rb_cPathname, "==", path_eq, 1);
- rb_define_method(rb_cPathname, "===", path_eq, 1);
- rb_define_method(rb_cPathname, "eql?", path_eq, 1);
- rb_define_method(rb_cPathname, "<=>", path_cmp, 1);
- rb_define_method(rb_cPathname, "hash", path_hash, 0);
- rb_define_method(rb_cPathname, "to_s", path_to_s, 0);
- rb_define_method(rb_cPathname, "to_path", path_to_s, 0);
- rb_define_method(rb_cPathname, "inspect", path_inspect, 0);
- rb_define_method(rb_cPathname, "sub", path_sub, -1);
- rb_define_method(rb_cPathname, "sub_ext", path_sub_ext, 1);
- rb_define_method(rb_cPathname, "realpath", path_realpath, -1);
- rb_define_method(rb_cPathname, "realdirpath", path_realdirpath, -1);
- rb_define_method(rb_cPathname, "each_line", path_each_line, -1);
- rb_define_method(rb_cPathname, "read", path_read, -1);
- rb_define_method(rb_cPathname, "binread", path_binread, -1);
- rb_define_method(rb_cPathname, "readlines", path_readlines, -1);
- rb_define_method(rb_cPathname, "write", path_write, -1);
- rb_define_method(rb_cPathname, "binwrite", path_binwrite, -1);
- rb_define_method(rb_cPathname, "sysopen", path_sysopen, -1);
- rb_define_method(rb_cPathname, "atime", path_atime, 0);
- rb_define_method(rb_cPathname, "birthtime", path_birthtime, 0);
- rb_define_method(rb_cPathname, "ctime", path_ctime, 0);
- rb_define_method(rb_cPathname, "mtime", path_mtime, 0);
- rb_define_method(rb_cPathname, "chmod", path_chmod, 1);
- rb_define_method(rb_cPathname, "lchmod", path_lchmod, 1);
- rb_define_method(rb_cPathname, "chown", path_chown, 2);
- rb_define_method(rb_cPathname, "lchown", path_lchown, 2);
- rb_define_method(rb_cPathname, "fnmatch", path_fnmatch, -1);
- rb_define_method(rb_cPathname, "fnmatch?", path_fnmatch, -1);
- rb_define_method(rb_cPathname, "ftype", path_ftype, 0);
- rb_define_method(rb_cPathname, "make_link", path_make_link, 1);
- rb_define_method(rb_cPathname, "open", path_open, -1);
- rb_define_method(rb_cPathname, "readlink", path_readlink, 0);
- rb_define_method(rb_cPathname, "rename", path_rename, 1);
- rb_define_method(rb_cPathname, "stat", path_stat, 0);
- rb_define_method(rb_cPathname, "lstat", path_lstat, 0);
- rb_define_method(rb_cPathname, "make_symlink", path_make_symlink, 1);
- rb_define_method(rb_cPathname, "truncate", path_truncate, 1);
- rb_define_method(rb_cPathname, "utime", path_utime, 2);
- rb_define_method(rb_cPathname, "lutime", path_lutime, 2);
- rb_define_method(rb_cPathname, "basename", path_basename, -1);
- rb_define_method(rb_cPathname, "dirname", path_dirname, 0);
- rb_define_method(rb_cPathname, "extname", path_extname, 0);
- rb_define_method(rb_cPathname, "expand_path", path_expand_path, -1);
- rb_define_method(rb_cPathname, "split", path_split, 0);
- rb_define_method(rb_cPathname, "blockdev?", path_blockdev_p, 0);
- rb_define_method(rb_cPathname, "chardev?", path_chardev_p, 0);
- rb_define_method(rb_cPathname, "executable?", path_executable_p, 0);
- rb_define_method(rb_cPathname, "executable_real?", path_executable_real_p, 0);
- rb_define_method(rb_cPathname, "exist?", path_exist_p, 0);
- rb_define_method(rb_cPathname, "grpowned?", path_grpowned_p, 0);
- rb_define_method(rb_cPathname, "directory?", path_directory_p, 0);
- rb_define_method(rb_cPathname, "file?", path_file_p, 0);
- rb_define_method(rb_cPathname, "pipe?", path_pipe_p, 0);
- rb_define_method(rb_cPathname, "socket?", path_socket_p, 0);
- rb_define_method(rb_cPathname, "owned?", path_owned_p, 0);
- rb_define_method(rb_cPathname, "readable?", path_readable_p, 0);
- rb_define_method(rb_cPathname, "world_readable?", path_world_readable_p, 0);
- rb_define_method(rb_cPathname, "readable_real?", path_readable_real_p, 0);
- rb_define_method(rb_cPathname, "setuid?", path_setuid_p, 0);
- rb_define_method(rb_cPathname, "setgid?", path_setgid_p, 0);
- rb_define_method(rb_cPathname, "size", path_size, 0);
- rb_define_method(rb_cPathname, "size?", path_size_p, 0);
- rb_define_method(rb_cPathname, "sticky?", path_sticky_p, 0);
- rb_define_method(rb_cPathname, "symlink?", path_symlink_p, 0);
- rb_define_method(rb_cPathname, "writable?", path_writable_p, 0);
- rb_define_method(rb_cPathname, "world_writable?", path_world_writable_p, 0);
- rb_define_method(rb_cPathname, "writable_real?", path_writable_real_p, 0);
- rb_define_method(rb_cPathname, "zero?", path_zero_p, 0);
- rb_define_method(rb_cPathname, "empty?", path_empty_p, 0);
- rb_define_singleton_method(rb_cPathname, "glob", path_s_glob, -1);
- rb_define_singleton_method(rb_cPathname, "getwd", path_s_getwd, 0);
- rb_define_singleton_method(rb_cPathname, "pwd", path_s_getwd, 0);
- rb_define_method(rb_cPathname, "glob", path_glob, -1);
- rb_define_method(rb_cPathname, "entries", path_entries, 0);
- rb_define_method(rb_cPathname, "mkdir", path_mkdir, -1);
- rb_define_method(rb_cPathname, "rmdir", path_rmdir, 0);
- rb_define_method(rb_cPathname, "opendir", path_opendir, 0);
- rb_define_method(rb_cPathname, "each_entry", path_each_entry, 0);
- rb_define_method(rb_cPathname, "unlink", path_unlink, 0);
- rb_define_method(rb_cPathname, "delete", path_unlink, 0);
- rb_undef_method(rb_cPathname, "=~");
- rb_define_global_function("Pathname", path_f_pathname, 1);
-}
-
-void
-InitVM_pathname(void)
-{
-#undef rb_intern
- id_at_path = rb_intern("@path");
- id_to_path = rb_intern("to_path");
- id_ENOTDIR = rb_intern("ENOTDIR");
- id_atime = rb_intern("atime");
- id_basename = rb_intern("basename");
- id_base = rb_intern("base");
- id_binread = rb_intern("binread");
- id_binwrite = rb_intern("binwrite");
- id_birthtime = rb_intern("birthtime");
- id_blockdev_p = rb_intern("blockdev?");
- id_chardev_p = rb_intern("chardev?");
- id_chmod = rb_intern("chmod");
- id_chown = rb_intern("chown");
- id_ctime = rb_intern("ctime");
- id_directory_p = rb_intern("directory?");
- id_dirname = rb_intern("dirname");
- id_empty_p = rb_intern("empty?");
- id_entries = rb_intern("entries");
- id_executable_p = rb_intern("executable?");
- id_executable_real_p = rb_intern("executable_real?");
- id_exist_p = rb_intern("exist?");
- id_expand_path = rb_intern("expand_path");
- id_extname = rb_intern("extname");
- id_file_p = rb_intern("file?");
- id_fnmatch = rb_intern("fnmatch");
- id_foreach = rb_intern("foreach");
- id_ftype = rb_intern("ftype");
- id_getwd = rb_intern("getwd");
- id_glob = rb_intern("glob");
- id_grpowned_p = rb_intern("grpowned?");
- id_lchmod = rb_intern("lchmod");
- id_lchown = rb_intern("lchown");
- id_link = rb_intern("link");
- id_lstat = rb_intern("lstat");
- id_lutime = rb_intern("lutime");
- id_mkdir = rb_intern("mkdir");
- id_mtime = rb_intern("mtime");
- id_open = rb_intern("open");
- id_owned_p = rb_intern("owned?");
- id_pipe_p = rb_intern("pipe?");
- id_read = rb_intern("read");
- id_readable_p = rb_intern("readable?");
- id_readable_real_p = rb_intern("readable_real?");
- id_readlines = rb_intern("readlines");
- id_readlink = rb_intern("readlink");
- id_realdirpath = rb_intern("realdirpath");
- id_realpath = rb_intern("realpath");
- id_rename = rb_intern("rename");
- id_rmdir = rb_intern("rmdir");
- id_setgid_p = rb_intern("setgid?");
- id_setuid_p = rb_intern("setuid?");
- id_size = rb_intern("size");
- id_size_p = rb_intern("size?");
- id_socket_p = rb_intern("socket?");
- id_split = rb_intern("split");
- id_stat = rb_intern("stat");
- id_sticky_p = rb_intern("sticky?");
- id_sub = rb_intern("sub");
- id_symlink = rb_intern("symlink");
- id_symlink_p = rb_intern("symlink?");
- id_sysopen = rb_intern("sysopen");
- id_truncate = rb_intern("truncate");
- id_unlink = rb_intern("unlink");
- id_utime = rb_intern("utime");
- id_world_readable_p = rb_intern("world_readable?");
- id_world_writable_p = rb_intern("world_writable?");
- id_writable_p = rb_intern("writable?");
- id_writable_real_p = rb_intern("writable_real?");
- id_write = rb_intern("write");
- id_zero_p = rb_intern("zero?");
-}
diff --git a/ext/pathname/pathname.gemspec b/ext/pathname/pathname.gemspec
deleted file mode 100644
index 890bc2fde9..0000000000
--- a/ext/pathname/pathname.gemspec
+++ /dev/null
@@ -1,32 +0,0 @@
-name = File.basename(__FILE__, ".gemspec")
-version = ["lib", "ext/lib"].find do |dir|
- break File.foreach(File.join(__dir__, dir, "#{name}.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 = ["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.7.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/ext/psych/depend b/ext/psych/depend
index a4d9ca9a6a..95175841a2 100644
--- a/ext/psych/depend
+++ b/ext/psych/depend
@@ -152,6 +152,7 @@ psych.o: $(hdrdir)/ruby/internal/intern/re.h
psych.o: $(hdrdir)/ruby/internal/intern/ruby.h
psych.o: $(hdrdir)/ruby/internal/intern/select.h
psych.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+psych.o: $(hdrdir)/ruby/internal/intern/set.h
psych.o: $(hdrdir)/ruby/internal/intern/signal.h
psych.o: $(hdrdir)/ruby/internal/intern/sprintf.h
psych.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -329,6 +330,7 @@ psych_emitter.o: $(hdrdir)/ruby/internal/intern/re.h
psych_emitter.o: $(hdrdir)/ruby/internal/intern/ruby.h
psych_emitter.o: $(hdrdir)/ruby/internal/intern/select.h
psych_emitter.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+psych_emitter.o: $(hdrdir)/ruby/internal/intern/set.h
psych_emitter.o: $(hdrdir)/ruby/internal/intern/signal.h
psych_emitter.o: $(hdrdir)/ruby/internal/intern/sprintf.h
psych_emitter.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -506,6 +508,7 @@ psych_parser.o: $(hdrdir)/ruby/internal/intern/re.h
psych_parser.o: $(hdrdir)/ruby/internal/intern/ruby.h
psych_parser.o: $(hdrdir)/ruby/internal/intern/select.h
psych_parser.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+psych_parser.o: $(hdrdir)/ruby/internal/intern/set.h
psych_parser.o: $(hdrdir)/ruby/internal/intern/signal.h
psych_parser.o: $(hdrdir)/ruby/internal/intern/sprintf.h
psych_parser.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -683,6 +686,7 @@ psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/re.h
psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/ruby.h
psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/select.h
psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/set.h
psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/signal.h
psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/sprintf.h
psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -860,6 +864,7 @@ psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/re.h
psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/ruby.h
psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/select.h
psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/set.h
psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/signal.h
psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/sprintf.h
psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/psych/extconf.rb b/ext/psych/extconf.rb
index e7dd0bb60a..589e201c1c 100644
--- a/ext/psych/extconf.rb
+++ b/ext/psych/extconf.rb
@@ -36,8 +36,11 @@ if yaml_source
libyaml = "libyaml.#$LIBEXT"
$cleanfiles << libyaml
$LOCAL_LIBS.prepend("$(LIBYAML) ")
-else # default to pre-installed libyaml
- pkg_config('yaml-0.1')
+
+ # default to pre-installed libyaml
+elsif pkg_config('yaml-0.1')
+ # found with pkg-config
+else
dir_config('libyaml')
find_header('yaml.h') or abort "yaml.h not found"
find_library('yaml', 'yaml_get_version') or abort "libyaml not found"
diff --git a/ext/psych/lib/psych.rb b/ext/psych/lib/psych.rb
index d87bd9040a..850a6d1937 100644
--- a/ext/psych/lib/psych.rb
+++ b/ext/psych/lib/psych.rb
@@ -1,4 +1,6 @@
# frozen_string_literal: true
+require 'date'
+
require_relative 'psych/versions'
case RUBY_ENGINE
when 'jruby'
@@ -21,7 +23,6 @@ require_relative 'psych/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'
@@ -84,7 +85,7 @@ require_relative 'psych/class_loader'
# Psych.safe_load_file("data.yml", permitted_classes: [Date])
# Psych.load_file("trusted_database.yml")
#
-# ==== Exception handling
+# ==== \Exception handling
#
# begin
# # The second argument changes only the exception contents
@@ -148,7 +149,7 @@ require_relative 'psych/class_loader'
# # Returns Psych::Nodes::Document
# Psych.parse_file('database.yml')
#
-# ==== Exception handling
+# ==== \Exception handling
#
# begin
# # The second argument changes only the exception contents
@@ -268,10 +269,10 @@ module Psych
# YAML documents that are supplied via user input. Instead, please use the
# load method or the safe_load method.
#
- def self.unsafe_load yaml, filename: nil, fallback: false, symbolize_names: false, freeze: false, strict_integer: false
+ def self.unsafe_load yaml, filename: nil, fallback: false, symbolize_names: false, freeze: false, strict_integer: false, parse_symbols: true
result = parse(yaml, filename: filename)
return fallback unless result
- result.to_ruby(symbolize_names: symbolize_names, freeze: freeze, strict_integer: strict_integer)
+ result.to_ruby(symbolize_names: symbolize_names, freeze: freeze, strict_integer: strict_integer, parse_symbols: parse_symbols)
end
###
@@ -319,13 +320,13 @@ module Psych
# Psych.safe_load("---\n foo: bar") # => {"foo"=>"bar"}
# Psych.safe_load("---\n foo: bar", symbolize_names: true) # => {:foo=>"bar"}
#
- def self.safe_load yaml, permitted_classes: [], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false, strict_integer: false
+ def self.safe_load yaml, permitted_classes: [], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false, strict_integer: false, parse_symbols: true
result = parse(yaml, filename: filename)
return fallback unless result
class_loader = ClassLoader::Restricted.new(permitted_classes.map(&:to_s),
permitted_symbols.map(&:to_s))
- scanner = ScalarScanner.new class_loader, strict_integer: strict_integer
+ scanner = ScalarScanner.new class_loader, strict_integer: strict_integer, parse_symbols: parse_symbols
visitor = if aliases
Visitors::ToRuby.new scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze
else
@@ -340,7 +341,7 @@ module Psych
# provided, the object contained in the first document will be returned.
# +filename+ will be used in the exception message if any exception
# is raised while parsing. If +yaml+ is empty, it returns
- # the specified +fallback+ return value, which defaults to +false+.
+ # the specified +fallback+ return value, which defaults to +nil+.
#
# Raises a Psych::SyntaxError when a YAML syntax error is detected.
#
@@ -365,7 +366,7 @@ module Psych
# 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, strict_integer: false
+ def self.load yaml, permitted_classes: [Symbol], permitted_symbols: [], aliases: false, filename: nil, fallback: nil, symbolize_names: false, freeze: false, strict_integer: false, parse_symbols: true
safe_load yaml, permitted_classes: permitted_classes,
permitted_symbols: permitted_symbols,
aliases: aliases,
@@ -373,7 +374,8 @@ module Psych
fallback: fallback,
symbolize_names: symbolize_names,
freeze: freeze,
- strict_integer: strict_integer
+ strict_integer: strict_integer,
+ parse_symbols: parse_symbols
end
###
@@ -479,6 +481,7 @@ module Psych
#
# Default: <tt>2</tt>.
# [<tt>:line_width</tt>] Max character to wrap line at.
+ # For unlimited line width use <tt>-1</tt>.
#
# Default: <tt>0</tt> (meaning "wrap at 81").
# [<tt>:canonical</tt>] Write "canonical" YAML form (very verbose, yet
@@ -559,6 +562,7 @@ module Psych
#
# Default: <tt>2</tt>.
# [<tt>:line_width</tt>] Max character to wrap line at.
+ # For unlimited line width use <tt>-1</tt>.
#
# Default: <tt>0</tt> (meaning "wrap at 81").
# [<tt>:canonical</tt>] Write "canonical" YAML form (very verbose, yet
@@ -651,6 +655,35 @@ module Psych
end
###
+ # Load multiple documents given in +yaml+. Returns the parsed documents
+ # as a list.
+ #
+ # Example:
+ #
+ # Psych.safe_load_stream("--- foo\n...\n--- bar\n...") # => ['foo', 'bar']
+ #
+ # list = []
+ # Psych.safe_load_stream("--- foo\n...\n--- bar\n...") do |ruby|
+ # list << ruby
+ # end
+ # list # => ['foo', 'bar']
+ #
+ def self.safe_load_stream yaml, filename: nil, permitted_classes: [], aliases: false
+ documents = parse_stream(yaml, filename: filename).children.map do |child|
+ stream = Psych::Nodes::Stream.new
+ stream.children << child
+ safe_load(stream.to_yaml, permitted_classes: permitted_classes, aliases: aliases)
+ end
+
+ if block_given?
+ documents.each { |doc| yield doc }
+ nil
+ else
+ documents
+ end
+ end
+
+ ###
# Load the document contained in +filename+. Returns the yaml contained in
# +filename+ as a Ruby object, or if the file is empty, it returns
# the specified +fallback+ return value, which defaults to +false+.
@@ -667,7 +700,7 @@ module Psych
###
# Safely loads the document contained in +filename+. Returns the yaml contained in
# +filename+ as a Ruby object, or if the file is empty, it returns
- # the specified +fallback+ return value, which defaults to +false+.
+ # the specified +fallback+ return value, which defaults to +nil+.
# See safe_load for options.
def self.safe_load_file filename, **kwargs
File.open(filename, 'r:bom|utf-8') { |f|
@@ -678,7 +711,7 @@ module Psych
###
# Loads the document contained in +filename+. Returns the yaml contained in
# +filename+ as a Ruby object, or if the file is empty, it returns
- # the specified +fallback+ return value, which defaults to +false+.
+ # the specified +fallback+ return value, which defaults to +nil+.
# See load for options.
def self.load_file filename, **kwargs
File.open(filename, 'r:bom|utf-8') { |f|
@@ -757,3 +790,5 @@ module Psych
self.domain_types = {}
# :startdoc:
end
+
+require_relative 'psych/core_ext'
diff --git a/ext/psych/lib/psych/class_loader.rb b/ext/psych/lib/psych/class_loader.rb
index 50efc35ee2..c8f509720a 100644
--- a/ext/psych/lib/psych/class_loader.rb
+++ b/ext/psych/lib/psych/class_loader.rb
@@ -6,6 +6,7 @@ module Psych
class ClassLoader # :nodoc:
BIG_DECIMAL = 'BigDecimal'
COMPLEX = 'Complex'
+ DATA = 'Data' unless RUBY_VERSION < "3.2"
DATE = 'Date'
DATE_TIME = 'DateTime'
EXCEPTION = 'Exception'
diff --git a/ext/psych/lib/psych/core_ext.rb b/ext/psych/lib/psych/core_ext.rb
index 0721a133c3..6dfd0f1696 100644
--- a/ext/psych/lib/psych/core_ext.rb
+++ b/ext/psych/lib/psych/core_ext.rb
@@ -14,6 +14,23 @@ class Object
end
end
-if defined?(::IRB)
- require_relative 'y'
+# Up to Ruby 3.4, Set was a regular object and was dumped as such
+# by Pysch.
+# Starting from Ruby 4.0 it's a core class written in C, so we have to implement
+# #encode_with / #init_with to preserve backward compatibility.
+if defined?(::Set) && Set.new.instance_variables.empty?
+ class Set
+ def encode_with(coder)
+ hash = {}
+ each do |m|
+ hash[m] = true
+ end
+ coder["hash"] = hash
+ coder
+ end
+
+ def init_with(coder)
+ replace(coder["hash"].keys)
+ end
+ end
end
diff --git a/ext/psych/lib/psych/nodes/node.rb b/ext/psych/lib/psych/nodes/node.rb
index f44fce5f05..fc27448f2e 100644
--- a/ext/psych/lib/psych/nodes/node.rb
+++ b/ext/psych/lib/psych/nodes/node.rb
@@ -1,5 +1,4 @@
# frozen_string_literal: true
-require 'stringio'
require_relative '../class_loader'
require_relative '../scalar_scanner'
@@ -46,8 +45,8 @@ module Psych
# Convert this node to Ruby.
#
# See also Psych::Visitors::ToRuby
- def to_ruby(symbolize_names: false, freeze: false, strict_integer: false)
- Visitors::ToRuby.create(symbolize_names: symbolize_names, freeze: freeze, strict_integer: strict_integer).accept(self)
+ def to_ruby(symbolize_names: false, freeze: false, strict_integer: false, parse_symbols: true)
+ Visitors::ToRuby.create(symbolize_names: symbolize_names, freeze: freeze, strict_integer: strict_integer, parse_symbols: parse_symbols).accept(self)
end
alias :transform :to_ruby
@@ -56,6 +55,8 @@ module Psych
#
# See also Psych::Visitors::Emitter
def yaml io = nil, options = {}
+ require "stringio" unless defined?(StringIO)
+
real_io = io || StringIO.new(''.encode('utf-8'))
Visitors::Emitter.new(real_io, options).accept self
diff --git a/ext/psych/lib/psych/scalar_scanner.rb b/ext/psych/lib/psych/scalar_scanner.rb
index 3cb4bf3c7e..6a556fb3b8 100644
--- a/ext/psych/lib/psych/scalar_scanner.rb
+++ b/ext/psych/lib/psych/scalar_scanner.rb
@@ -11,26 +11,27 @@ module Psych
# Base 60, [-+]inf and NaN are handled separately
FLOAT = /^(?:[-+]?([0-9][0-9_,]*)?\.[0-9]*([eE][-+][0-9]+)?(?# base 10))$/x
- # Taken from http://yaml.org/type/int.html
- INTEGER_STRICT = /^(?:[-+]?0b[0-1_]+ (?# base 2)
- |[-+]?0[0-7_]+ (?# base 8)
- |[-+]?(0|[1-9][0-9_]*) (?# base 10)
- |[-+]?0x[0-9a-fA-F_]+ (?# base 16))$/x
+ # Taken from http://yaml.org/type/int.html and modified to ensure at least one numerical symbol exists
+ INTEGER_STRICT = /^(?:[-+]?0b[_]*[0-1][0-1_]* (?# base 2)
+ |[-+]?0[_]*[0-7][0-7_]* (?# base 8)
+ |[-+]?(0|[1-9][0-9_]*) (?# base 10)
+ |[-+]?0x[_]*[0-9a-fA-F][0-9a-fA-F_]* (?# base 16))$/x
# Same as above, but allows commas.
# Not to YML spec, but kept for backwards compatibility
- INTEGER_LEGACY = /^(?:[-+]?0b[0-1_,]+ (?# base 2)
- |[-+]?0[0-7_,]+ (?# base 8)
+ INTEGER_LEGACY = /^(?:[-+]?0b[_,]*[0-1][0-1_,]* (?# base 2)
+ |[-+]?0[_,]*[0-7][0-7_,]* (?# base 8)
|[-+]?(?:0|[1-9](?:[0-9]|,[0-9]|_[0-9])*) (?# base 10)
- |[-+]?0x[0-9a-fA-F_,]+ (?# base 16))$/x
+ |[-+]?0x[_,]*[0-9a-fA-F][0-9a-fA-F_,]* (?# base 16))$/x
attr_reader :class_loader
# Create a new scanner
- def initialize class_loader, strict_integer: false
+ def initialize class_loader, strict_integer: false, parse_symbols: true
@symbol_cache = {}
@class_loader = class_loader
@strict_integer = strict_integer
+ @parse_symbols = parse_symbols
end
# Tokenize +string+ returning the Ruby object
@@ -61,7 +62,6 @@ module Psych
string
end
elsif string.match?(/^\d{4}-(?:1[012]|0\d|\d)-(?:[12]\d|3[01]|0\d|\d)$/)
- require 'date'
begin
class_loader.date.strptime(string, '%F', Date::GREGORIAN)
rescue ArgumentError
@@ -73,7 +73,7 @@ module Psych
-Float::INFINITY
elsif string.match?(/^\.nan$/i)
Float::NAN
- elsif string.match?(/^:./)
+ elsif @parse_symbols && string.match?(/^:./)
if string =~ /^:(["'])(.*)\1/
@symbol_cache[string] = class_loader.symbolize($2.sub(/^:/, ''))
else
diff --git a/ext/psych/lib/psych/versions.rb b/ext/psych/lib/psych/versions.rb
index b9e8d9ef11..4c7a80d5c8 100644
--- a/ext/psych/lib/psych/versions.rb
+++ b/ext/psych/lib/psych/versions.rb
@@ -2,9 +2,9 @@
module Psych
# The version of Psych you are using
- VERSION = '5.1.2'
+ VERSION = '5.3.1'
if RUBY_ENGINE == 'jruby'
- DEFAULT_SNAKEYAML_VERSION = '2.7'.freeze
+ DEFAULT_SNAKEYAML_VERSION = '2.10'.freeze
end
end
diff --git a/ext/psych/lib/psych/visitors/to_ruby.rb b/ext/psych/lib/psych/visitors/to_ruby.rb
index f0fda9bdbc..475444e589 100644
--- a/ext/psych/lib/psych/visitors/to_ruby.rb
+++ b/ext/psych/lib/psych/visitors/to_ruby.rb
@@ -12,9 +12,13 @@ module Psych
###
# This class walks a YAML AST, converting each node to Ruby
class ToRuby < Psych::Visitors::Visitor
- def self.create(symbolize_names: false, freeze: false, strict_integer: false)
+ unless RUBY_VERSION < "3.2"
+ DATA_INITIALIZE = Data.instance_method(:initialize)
+ end
+
+ def self.create(symbolize_names: false, freeze: false, strict_integer: false, parse_symbols: true)
class_loader = ClassLoader.new
- scanner = ScalarScanner.new class_loader, strict_integer: strict_integer
+ scanner = ScalarScanner.new class_loader, strict_integer: strict_integer, parse_symbols: parse_symbols
new(scanner, class_loader, symbolize_names: symbolize_names, freeze: freeze)
end
@@ -36,7 +40,7 @@ module Psych
unless @domain_types.empty? || !target.tag
key = target.tag.sub(/^[!\/]*/, '').sub(/(,\d+)\//, '\1:')
- key = "tag:#{key}" unless key =~ /^(?:tag:|x-private)/
+ key = "tag:#{key}" unless key.match?(/^(?:tag:|x-private)/)
if @domain_types.key? key
value, block = @domain_types[key]
@@ -79,7 +83,6 @@ module Psych
class_loader.big_decimal._load o.value
when "!ruby/object:DateTime"
class_loader.date_time
- require 'date' unless defined? DateTime
t = @ss.parse_time(o.value)
DateTime.civil(*t.to_a[0, 6].reverse, Rational(t.utc_offset, 86400)) +
(t.subsec/86400)
@@ -97,11 +100,11 @@ module Psych
Float(@ss.tokenize(o.value))
when "!ruby/regexp"
klass = class_loader.regexp
- o.value =~ /^\/(.*)\/([mixn]*)$/m
- source = $1
+ matches = /^\/(?<string>.*)\/(?<options>[mixn]*)$/m.match(o.value)
+ source = matches[:string].gsub('\/', '/')
options = 0
lang = nil
- $2&.each_char do |option|
+ matches[:options].each_char do |option|
case option
when 'x' then options |= Regexp::EXTENDED
when 'i' then options |= Regexp::IGNORECASE
@@ -198,6 +201,32 @@ module Psych
s
end
+ when /^!ruby\/data(-with-ivars)?(?::(.*))?$/
+ data = register(o, resolve_class($2).allocate) if $2
+ members = {}
+
+ if $1 # data-with-ivars
+ ivars = {}
+ o.children.each_slice(2) do |type, vars|
+ case accept(type)
+ when 'members'
+ revive_data_members(members, vars)
+ data ||= allocate_anon_data(o, members)
+ when 'ivars'
+ revive_hash(ivars, vars)
+ end
+ end
+ ivars.each do |ivar, v|
+ data.instance_variable_set ivar, v
+ end
+ else
+ revive_data_members(members, o)
+ end
+ data ||= allocate_anon_data(o, members)
+ DATA_INITIALIZE.bind_call(data, **members)
+ data.freeze
+ data
+
when /^!ruby\/object:?(.*)?$/
name = $1 || 'Object'
@@ -341,6 +370,20 @@ module Psych
list
end
+ def allocate_anon_data node, members
+ klass = class_loader.data.define(*members.keys)
+ register(node, klass.allocate)
+ end
+
+ def revive_data_members hash, o
+ o.children.each_slice(2) do |k,v|
+ name = accept(k)
+ value = accept(v)
+ hash[class_loader.symbolize(name)] = value
+ end
+ hash
+ end
+
def revive_hash hash, o, tagged= false
o.children.each_slice(2) { |k,v|
key = accept(k)
diff --git a/ext/psych/lib/psych/visitors/yaml_tree.rb b/ext/psych/lib/psych/visitors/yaml_tree.rb
index a2ebc4d781..b6c86f4c94 100644
--- a/ext/psych/lib/psych/visitors/yaml_tree.rb
+++ b/ext/psych/lib/psych/visitors/yaml_tree.rb
@@ -73,7 +73,7 @@ module Psych
method = respond_to?(method) ? method : h[klass.superclass]
- raise(TypeError, "Can't dump #{target.class}") unless method
+ raise(TypeError, "can't dump #{klass.name}") unless method
h[klass] = method
end.compare_by_identity
@@ -162,6 +162,44 @@ module Psych
alias :visit_Delegator :visit_Object
+ def visit_Data o
+ ivars = o.instance_variables
+ if ivars.empty?
+ tag = ['!ruby/data', o.class.name].compact.join(':')
+ register o, @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK)
+ o.members.each do |member|
+ @emitter.scalar member.to_s, nil, nil, true, false, Nodes::Scalar::ANY
+ accept o.send member
+ end
+ @emitter.end_mapping
+
+ else
+ tag = ['!ruby/data-with-ivars', o.class.name].compact.join(':')
+ node = @emitter.start_mapping(nil, tag, false, Psych::Nodes::Mapping::BLOCK)
+ register(o, node)
+
+ # Dump the members
+ accept 'members'
+ @emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK
+ o.members.each do |member|
+ @emitter.scalar member.to_s, nil, nil, true, false, Nodes::Scalar::ANY
+ accept o.send member
+ end
+ @emitter.end_mapping
+
+ # Dump the ivars
+ accept 'ivars'
+ @emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK
+ ivars.each do |ivar|
+ accept ivar.to_s
+ accept o.instance_variable_get ivar
+ end
+ @emitter.end_mapping
+
+ @emitter.end_mapping
+ end
+ end unless RUBY_VERSION < "3.2"
+
def visit_Struct o
tag = ['!ruby/struct', o.class.name].compact.join(':')
@@ -189,7 +227,8 @@ module Psych
end
def visit_Date o
- register o, visit_Integer(o.gregorian)
+ formatted = format_date o
+ register o, @emitter.scalar(formatted, nil, nil, true, false, Nodes::Scalar::ANY)
end
def visit_DateTime o
@@ -261,7 +300,7 @@ module Psych
style = Nodes::Scalar::LITERAL
plain = false
quote = false
- elsif o =~ /\n(?!\Z)/ # match \n except blank line at the end of string
+ elsif o.match?(/\n(?!\Z)/) # match \n except blank line at the end of string
style = Nodes::Scalar::LITERAL
elsif o == '<<'
style = Nodes::Scalar::SINGLE_QUOTED
@@ -272,9 +311,9 @@ module Psych
style = Nodes::Scalar::DOUBLE_QUOTED
elsif @line_width && o.length > @line_width
style = Nodes::Scalar::FOLDED
- elsif o =~ /^[^[:word:]][^"]*$/
+ elsif o.match?(/^[^[:word:]][^"]*$/)
style = Nodes::Scalar::DOUBLE_QUOTED
- elsif not String === @ss.tokenize(o) or /\A0[0-7]*[89]/ =~ o
+ elsif not String === @ss.tokenize(o) or /\A0[0-7]*[89]/.match?(o)
style = Nodes::Scalar::SINGLE_QUOTED
end
@@ -486,6 +525,10 @@ module Psych
end
end
+ def format_date date
+ date.strftime("%Y-%m-%d")
+ end
+
def register target, yaml_obj
@st.register target, yaml_obj
yaml_obj
diff --git a/ext/psych/psych.c b/ext/psych/psych.c
index 8af0bb6a5a..afbd7a3571 100644
--- a/ext/psych/psych.c
+++ b/ext/psych/psych.c
@@ -23,7 +23,7 @@ VALUE mPsych;
void Init_psych(void)
{
#ifdef HAVE_RB_EXT_RACTOR_SAFE
- RB_EXT_RACTOR_SAFE(true);
+ RB_EXT_RACTOR_SAFE(true);
#endif
mPsych = rb_define_module("Psych");
@@ -34,4 +34,3 @@ void Init_psych(void)
Init_psych_to_ruby();
Init_psych_yaml_tree();
}
-/* vim: set noet sws=4 sw=4: */
diff --git a/ext/psych/psych.gemspec b/ext/psych/psych.gemspec
index a3fc53a8b9..a32f79bc16 100644
--- a/ext/psych/psych.gemspec
+++ b/ext/psych/psych.gemspec
@@ -75,6 +75,8 @@ DESCRIPTION
s.add_dependency 'stringio'
end
+ s.add_dependency 'date'
+
s.metadata['msys2_mingw_dependencies'] = 'libyaml'
s.metadata['changelog_uri'] = s.homepage + '/releases'
end
diff --git a/ext/psych/psych_emitter.c b/ext/psych/psych_emitter.c
index 022ffa0946..624ab7c528 100644
--- a/ext/psych/psych_emitter.c
+++ b/ext/psych/psych_emitter.c
@@ -17,7 +17,7 @@ static ID id_canonical;
static void emit(yaml_emitter_t * emitter, yaml_event_t * event)
{
if(!yaml_emitter_emit(emitter, event))
- rb_raise(rb_eRuntimeError, "%s", emitter->problem);
+ rb_raise(rb_eRuntimeError, "%s", emitter->problem);
}
static int writer(void *ctx, unsigned char *buffer, size_t size)
@@ -82,13 +82,13 @@ static VALUE initialize(int argc, VALUE *argv, VALUE self)
TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter);
if (rb_scan_args(argc, argv, "11", &io, &options) == 2) {
- line_width = rb_funcall(options, id_line_width, 0);
- indent = rb_funcall(options, id_indentation, 0);
- canonical = rb_funcall(options, id_canonical, 0);
+ line_width = rb_funcall(options, id_line_width, 0);
+ indent = rb_funcall(options, id_indentation, 0);
+ canonical = rb_funcall(options, id_canonical, 0);
- yaml_emitter_set_width(emitter, NUM2INT(line_width));
- yaml_emitter_set_indent(emitter, NUM2INT(indent));
- yaml_emitter_set_canonical(emitter, Qtrue == canonical ? 1 : 0);
+ yaml_emitter_set_width(emitter, NUM2INT(line_width));
+ yaml_emitter_set_indent(emitter, NUM2INT(indent));
+ yaml_emitter_set_canonical(emitter, Qtrue == canonical ? 1 : 0);
}
rb_ivar_set(self, id_io, io);
@@ -136,84 +136,118 @@ static VALUE end_stream(VALUE self)
return self;
}
-/* call-seq: emitter.start_document(version, tags, implicit)
- *
- * Start a document emission with YAML +version+, +tags+, and an +implicit+
- * start.
- *
- * See Psych::Handler#start_document
- */
-static VALUE start_document(VALUE self, VALUE version, VALUE tags, VALUE imp)
+struct start_document_data {
+ VALUE self;
+ VALUE version;
+ VALUE tags;
+ VALUE imp;
+
+ yaml_tag_directive_t * head;
+};
+
+static VALUE start_document_try(VALUE d)
{
+ struct start_document_data * data = (struct start_document_data *)d;
+ VALUE self = data->self;
+ VALUE version = data->version;
+ VALUE tags = data->tags;
+ VALUE imp = data->imp;
+
yaml_emitter_t * emitter;
- yaml_tag_directive_t * head = NULL;
yaml_tag_directive_t * tail = NULL;
yaml_event_t event;
yaml_version_directive_t version_directive;
TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter);
-
Check_Type(version, T_ARRAY);
if(RARRAY_LEN(version) > 0) {
- VALUE major = rb_ary_entry(version, (long)0);
- VALUE minor = rb_ary_entry(version, (long)1);
+ VALUE major = rb_ary_entry(version, (long)0);
+ VALUE minor = rb_ary_entry(version, (long)1);
- version_directive.major = NUM2INT(major);
- version_directive.minor = NUM2INT(minor);
+ version_directive.major = NUM2INT(major);
+ version_directive.minor = NUM2INT(minor);
}
if(RTEST(tags)) {
- long i = 0;
- long len;
- rb_encoding * encoding = rb_utf8_encoding();
-
- Check_Type(tags, T_ARRAY);
-
- len = RARRAY_LEN(tags);
- head = xcalloc((size_t)len, sizeof(yaml_tag_directive_t));
- tail = head;
-
- for(i = 0; i < len && i < RARRAY_LEN(tags); i++) {
- VALUE tuple = RARRAY_AREF(tags, i);
- VALUE name;
- VALUE value;
-
- Check_Type(tuple, T_ARRAY);
-
- if(RARRAY_LEN(tuple) < 2) {
- xfree(head);
- rb_raise(rb_eRuntimeError, "tag tuple must be of length 2");
- }
- name = RARRAY_AREF(tuple, 0);
- value = RARRAY_AREF(tuple, 1);
- StringValue(name);
- StringValue(value);
- name = rb_str_export_to_enc(name, encoding);
- value = rb_str_export_to_enc(value, encoding);
-
- tail->handle = (yaml_char_t *)StringValueCStr(name);
- tail->prefix = (yaml_char_t *)StringValueCStr(value);
-
- tail++;
- }
+ long i = 0;
+ long len;
+ rb_encoding * encoding = rb_utf8_encoding();
+
+ Check_Type(tags, T_ARRAY);
+
+ len = RARRAY_LEN(tags);
+ data->head = xcalloc((size_t)len, sizeof(yaml_tag_directive_t));
+ tail = data->head;
+
+ for(i = 0; i < len && i < RARRAY_LEN(tags); i++) {
+ VALUE tuple = RARRAY_AREF(tags, i);
+ VALUE name;
+ VALUE value;
+
+ Check_Type(tuple, T_ARRAY);
+
+ if(RARRAY_LEN(tuple) < 2) {
+ rb_raise(rb_eRuntimeError, "tag tuple must be of length 2");
+ }
+
+ name = RARRAY_AREF(tuple, 0);
+ value = RARRAY_AREF(tuple, 1);
+ StringValue(name);
+ StringValue(value);
+ name = rb_str_export_to_enc(name, encoding);
+ value = rb_str_export_to_enc(value, encoding);
+
+ tail->handle = (yaml_char_t *)StringValueCStr(name);
+ tail->prefix = (yaml_char_t *)StringValueCStr(value);
+
+ tail++;
+ }
}
yaml_document_start_event_initialize(
- &event,
- (RARRAY_LEN(version) > 0) ? &version_directive : NULL,
- head,
- tail,
- imp ? 1 : 0
- );
+ &event,
+ (RARRAY_LEN(version) > 0) ? &version_directive : NULL,
+ data->head,
+ tail,
+ imp ? 1 : 0
+ );
emit(emitter, &event);
- if(head) xfree(head);
-
return self;
}
+static VALUE start_document_ensure(VALUE d)
+{
+ struct start_document_data * data = (struct start_document_data *)d;
+
+ xfree(data->head);
+
+ return Qnil;
+}
+
+/* call-seq: emitter.start_document(version, tags, implicit)
+ *
+ * Start a document emission with YAML +version+, +tags+, and an +implicit+
+ * start.
+ *
+ * See Psych::Handler#start_document
+ */
+static VALUE start_document(VALUE self, VALUE version, VALUE tags, VALUE imp)
+{
+ struct start_document_data data = {
+ .self = self,
+ .version = version,
+ .tags = tags,
+ .imp = imp,
+
+ .head = NULL,
+ };
+
+ return rb_ensure(start_document_try, (VALUE)&data, start_document_ensure, (VALUE)&data);
+}
+
/* call-seq: emitter.end_document(implicit)
*
* End a document emission with an +implicit+ ending.
@@ -241,14 +275,14 @@ static VALUE end_document(VALUE self, VALUE imp)
* See Psych::Handler#scalar
*/
static VALUE scalar(
- VALUE self,
- VALUE value,
- VALUE anchor,
- VALUE tag,
- VALUE plain,
- VALUE quoted,
- VALUE style
- ) {
+ VALUE self,
+ VALUE value,
+ VALUE anchor,
+ VALUE tag,
+ VALUE plain,
+ VALUE quoted,
+ VALUE style
+ ) {
yaml_emitter_t * emitter;
yaml_event_t event;
rb_encoding *encoding;
@@ -261,25 +295,26 @@ static VALUE scalar(
value = rb_str_export_to_enc(value, encoding);
if(!NIL_P(anchor)) {
- Check_Type(anchor, T_STRING);
- anchor = rb_str_export_to_enc(anchor, encoding);
+ Check_Type(anchor, T_STRING);
+ anchor = rb_str_export_to_enc(anchor, encoding);
}
if(!NIL_P(tag)) {
- Check_Type(tag, T_STRING);
- tag = rb_str_export_to_enc(tag, encoding);
+ Check_Type(tag, T_STRING);
+ tag = rb_str_export_to_enc(tag, encoding);
}
+ const char *value_ptr = StringValuePtr(value);
yaml_scalar_event_initialize(
- &event,
- (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor)),
- (yaml_char_t *)(NIL_P(tag) ? NULL : StringValueCStr(tag)),
- (yaml_char_t*)StringValuePtr(value),
- (int)RSTRING_LEN(value),
- plain ? 1 : 0,
- quoted ? 1 : 0,
- (yaml_scalar_style_t)NUM2INT(style)
- );
+ &event,
+ (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor)),
+ (yaml_char_t *)(NIL_P(tag) ? NULL : StringValueCStr(tag)),
+ (yaml_char_t*)value_ptr,
+ (int)RSTRING_LEN(value),
+ plain ? 1 : 0,
+ quoted ? 1 : 0,
+ (yaml_scalar_style_t)NUM2INT(style)
+ );
emit(emitter, &event);
@@ -294,36 +329,36 @@ static VALUE scalar(
* See Psych::Handler#start_sequence
*/
static VALUE start_sequence(
- VALUE self,
- VALUE anchor,
- VALUE tag,
- VALUE implicit,
- VALUE style
- ) {
+ VALUE self,
+ VALUE anchor,
+ VALUE tag,
+ VALUE implicit,
+ VALUE style
+ ) {
yaml_emitter_t * emitter;
yaml_event_t event;
rb_encoding * encoding = rb_utf8_encoding();
if(!NIL_P(anchor)) {
- Check_Type(anchor, T_STRING);
- anchor = rb_str_export_to_enc(anchor, encoding);
+ Check_Type(anchor, T_STRING);
+ anchor = rb_str_export_to_enc(anchor, encoding);
}
if(!NIL_P(tag)) {
- Check_Type(tag, T_STRING);
- tag = rb_str_export_to_enc(tag, encoding);
+ Check_Type(tag, T_STRING);
+ tag = rb_str_export_to_enc(tag, encoding);
}
TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter);
yaml_sequence_start_event_initialize(
- &event,
- (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor)),
- (yaml_char_t *)(NIL_P(tag) ? NULL : StringValueCStr(tag)),
- implicit ? 1 : 0,
- (yaml_sequence_style_t)NUM2INT(style)
- );
+ &event,
+ (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor)),
+ (yaml_char_t *)(NIL_P(tag) ? NULL : StringValueCStr(tag)),
+ implicit ? 1 : 0,
+ (yaml_sequence_style_t)NUM2INT(style)
+ );
emit(emitter, &event);
@@ -357,12 +392,12 @@ static VALUE end_sequence(VALUE self)
* See Psych::Handler#start_mapping
*/
static VALUE start_mapping(
- VALUE self,
- VALUE anchor,
- VALUE tag,
- VALUE implicit,
- VALUE style
- ) {
+ VALUE self,
+ VALUE anchor,
+ VALUE tag,
+ VALUE implicit,
+ VALUE style
+ ) {
yaml_emitter_t * emitter;
yaml_event_t event;
rb_encoding *encoding;
@@ -372,22 +407,22 @@ static VALUE start_mapping(
encoding = rb_utf8_encoding();
if(!NIL_P(anchor)) {
- Check_Type(anchor, T_STRING);
- anchor = rb_str_export_to_enc(anchor, encoding);
+ Check_Type(anchor, T_STRING);
+ anchor = rb_str_export_to_enc(anchor, encoding);
}
if(!NIL_P(tag)) {
- Check_Type(tag, T_STRING);
- tag = rb_str_export_to_enc(tag, encoding);
+ Check_Type(tag, T_STRING);
+ tag = rb_str_export_to_enc(tag, encoding);
}
yaml_mapping_start_event_initialize(
- &event,
- (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor)),
- (yaml_char_t *)(NIL_P(tag) ? NULL : StringValueCStr(tag)),
- implicit ? 1 : 0,
- (yaml_mapping_style_t)NUM2INT(style)
- );
+ &event,
+ (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor)),
+ (yaml_char_t *)(NIL_P(tag) ? NULL : StringValueCStr(tag)),
+ implicit ? 1 : 0,
+ (yaml_mapping_style_t)NUM2INT(style)
+ );
emit(emitter, &event);
@@ -426,14 +461,14 @@ static VALUE alias(VALUE self, VALUE anchor)
TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter);
if(!NIL_P(anchor)) {
- Check_Type(anchor, T_STRING);
- anchor = rb_str_export_to_enc(anchor, rb_utf8_encoding());
+ Check_Type(anchor, T_STRING);
+ anchor = rb_str_export_to_enc(anchor, rb_utf8_encoding());
}
yaml_alias_event_initialize(
- &event,
- (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor))
- );
+ &event,
+ (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor))
+ );
emit(emitter, &event);
@@ -552,4 +587,3 @@ void Init_psych_emitter(void)
id_indentation = rb_intern("indentation");
id_canonical = rb_intern("canonical");
}
-/* vim: set noet sws=4 sw=4: */
diff --git a/ext/psych/psych_parser.c b/ext/psych/psych_parser.c
index 9c5179cc44..d973496284 100644
--- a/ext/psych/psych_parser.c
+++ b/ext/psych/psych_parser.c
@@ -32,9 +32,9 @@ static int io_reader(void * data, unsigned char *buf, size_t size, size_t *read)
*read = 0;
if(! NIL_P(string)) {
- void * str = (void *)StringValuePtr(string);
- *read = (size_t)RSTRING_LEN(string);
- memcpy(buf, str, *read);
+ void * str = (void *)StringValuePtr(string);
+ *read = (size_t)RSTRING_LEN(string);
+ memcpy(buf, str, *read);
}
return 1;
@@ -80,23 +80,23 @@ static VALUE allocate(VALUE klass)
static VALUE make_exception(yaml_parser_t * parser, VALUE path)
{
if (parser->error == YAML_MEMORY_ERROR) {
- return rb_eNoMemError;
+ return rb_eNoMemError;
} else {
- size_t line, column;
- VALUE ePsychSyntaxError;
+ size_t line, column;
+ VALUE ePsychSyntaxError;
- line = parser->context_mark.line + 1;
- column = parser->context_mark.column + 1;
+ line = parser->context_mark.line + 1;
+ column = parser->context_mark.column + 1;
- ePsychSyntaxError = rb_const_get(mPsych, rb_intern("SyntaxError"));
+ ePsychSyntaxError = rb_const_get(mPsych, rb_intern("SyntaxError"));
- return rb_funcall(ePsychSyntaxError, rb_intern("new"), 6,
- path,
- SIZET2NUM(line),
- SIZET2NUM(column),
- SIZET2NUM(parser->problem_offset),
- parser->problem ? rb_usascii_str_new2(parser->problem) : Qnil,
- parser->context ? rb_usascii_str_new2(parser->context) : Qnil);
+ return rb_funcall(ePsychSyntaxError, rb_intern("new"), 6,
+ path,
+ SIZET2NUM(line),
+ SIZET2NUM(column),
+ SIZET2NUM(parser->problem_offset),
+ parser->problem ? rb_usascii_str_new2(parser->problem) : Qnil,
+ parser->context ? rb_usascii_str_new2(parser->context) : Qnil);
}
}
@@ -108,18 +108,18 @@ static VALUE transcode_string(VALUE src, int * parser_encoding)
int source_encoding = rb_enc_get_index(src);
if (source_encoding == utf8) {
- *parser_encoding = YAML_UTF8_ENCODING;
- return src;
+ *parser_encoding = YAML_UTF8_ENCODING;
+ return src;
}
if (source_encoding == utf16le) {
- *parser_encoding = YAML_UTF16LE_ENCODING;
- return src;
+ *parser_encoding = YAML_UTF16LE_ENCODING;
+ return src;
}
if (source_encoding == utf16be) {
- *parser_encoding = YAML_UTF16BE_ENCODING;
- return src;
+ *parser_encoding = YAML_UTF16BE_ENCODING;
+ return src;
}
src = rb_str_export_to_enc(src, rb_utf8_encoding());
@@ -138,36 +138,36 @@ static VALUE transcode_io(VALUE src, int * parser_encoding)
/* if no encoding is returned, assume ascii8bit. */
if (NIL_P(io_external_encoding)) {
- io_external_enc_index = rb_ascii8bit_encindex();
+ io_external_enc_index = rb_ascii8bit_encindex();
} else {
- io_external_enc_index = rb_to_encoding_index(io_external_encoding);
+ io_external_enc_index = rb_to_encoding_index(io_external_encoding);
}
/* Treat US-ASCII as utf_8 */
if (io_external_enc_index == rb_usascii_encindex()) {
- *parser_encoding = YAML_UTF8_ENCODING;
- return src;
+ *parser_encoding = YAML_UTF8_ENCODING;
+ return src;
}
if (io_external_enc_index == rb_utf8_encindex()) {
- *parser_encoding = YAML_UTF8_ENCODING;
- return src;
+ *parser_encoding = YAML_UTF8_ENCODING;
+ return src;
}
if (io_external_enc_index == rb_enc_find_index("UTF-16LE")) {
- *parser_encoding = YAML_UTF16LE_ENCODING;
- return src;
+ *parser_encoding = YAML_UTF16LE_ENCODING;
+ return src;
}
if (io_external_enc_index == rb_enc_find_index("UTF-16BE")) {
- *parser_encoding = YAML_UTF16BE_ENCODING;
- return src;
+ *parser_encoding = YAML_UTF16BE_ENCODING;
+ return src;
}
/* Just guess on ASCII-8BIT */
if (io_external_enc_index == rb_ascii8bit_encindex()) {
- *parser_encoding = YAML_ANY_ENCODING;
- return src;
+ *parser_encoding = YAML_ANY_ENCODING;
+ return src;
}
/* If the external encoding is something we don't know how to handle,
@@ -261,238 +261,238 @@ static VALUE parse(VALUE self, VALUE handler, VALUE yaml, VALUE path)
yaml_parser_initialize(parser);
if (rb_respond_to(yaml, id_read)) {
- yaml = transcode_io(yaml, &parser_encoding);
- yaml_parser_set_encoding(parser, parser_encoding);
- yaml_parser_set_input(parser, io_reader, (void *)yaml);
+ yaml = transcode_io(yaml, &parser_encoding);
+ yaml_parser_set_encoding(parser, parser_encoding);
+ yaml_parser_set_input(parser, io_reader, (void *)yaml);
} else {
- StringValue(yaml);
- yaml = transcode_string(yaml, &parser_encoding);
- yaml_parser_set_encoding(parser, parser_encoding);
- yaml_parser_set_input_string(
- parser,
- (const unsigned char *)RSTRING_PTR(yaml),
- (size_t)RSTRING_LEN(yaml)
- );
+ StringValue(yaml);
+ yaml = transcode_string(yaml, &parser_encoding);
+ yaml_parser_set_encoding(parser, parser_encoding);
+ yaml_parser_set_input_string(
+ parser,
+ (const unsigned char *)RSTRING_PTR(yaml),
+ (size_t)RSTRING_LEN(yaml)
+ );
}
while(!done) {
- VALUE event_args[5];
- VALUE start_line, start_column, end_line, end_column;
-
- if(parser->error || !yaml_parser_parse(parser, &event)) {
- VALUE exception;
-
- exception = make_exception(parser, path);
- yaml_parser_delete(parser);
- yaml_parser_initialize(parser);
-
- rb_exc_raise(exception);
- }
-
- start_line = SIZET2NUM(event.start_mark.line);
- start_column = SIZET2NUM(event.start_mark.column);
- end_line = SIZET2NUM(event.end_mark.line);
- end_column = SIZET2NUM(event.end_mark.column);
-
- event_args[0] = handler;
- event_args[1] = start_line;
- event_args[2] = start_column;
- event_args[3] = end_line;
- event_args[4] = end_column;
- rb_protect(protected_event_location, (VALUE)event_args, &state);
-
- switch(event.type) {
- case YAML_STREAM_START_EVENT:
- {
- VALUE args[2];
-
- args[0] = handler;
- args[1] = INT2NUM(event.data.stream_start.encoding);
- rb_protect(protected_start_stream, (VALUE)args, &state);
- }
- break;
- case YAML_DOCUMENT_START_EVENT:
- {
- VALUE args[4];
- /* Get a list of tag directives (if any) */
- VALUE tag_directives = rb_ary_new();
- /* Grab the document version */
- VALUE version = event.data.document_start.version_directive ?
- rb_ary_new3(
- (long)2,
- INT2NUM(event.data.document_start.version_directive->major),
- INT2NUM(event.data.document_start.version_directive->minor)
- ) : rb_ary_new();
-
- if(event.data.document_start.tag_directives.start) {
- yaml_tag_directive_t *start =
- event.data.document_start.tag_directives.start;
- yaml_tag_directive_t *end =
- event.data.document_start.tag_directives.end;
- for(; start != end; start++) {
- VALUE handle = Qnil;
- VALUE prefix = Qnil;
- if(start->handle) {
- handle = rb_str_new2((const char *)start->handle);
- PSYCH_TRANSCODE(handle, encoding, internal_enc);
- }
-
- if(start->prefix) {
- prefix = rb_str_new2((const char *)start->prefix);
- PSYCH_TRANSCODE(prefix, encoding, internal_enc);
- }
-
- rb_ary_push(tag_directives, rb_ary_new3((long)2, handle, prefix));
- }
- }
- args[0] = handler;
- args[1] = version;
- args[2] = tag_directives;
- args[3] = event.data.document_start.implicit == 1 ? Qtrue : Qfalse;
- rb_protect(protected_start_document, (VALUE)args, &state);
- }
- break;
- case YAML_DOCUMENT_END_EVENT:
- {
- VALUE args[2];
-
- args[0] = handler;
- args[1] = event.data.document_end.implicit == 1 ? Qtrue : Qfalse;
- rb_protect(protected_end_document, (VALUE)args, &state);
- }
- break;
- case YAML_ALIAS_EVENT:
- {
- VALUE args[2];
- VALUE alias = Qnil;
- if(event.data.alias.anchor) {
- alias = rb_str_new2((const char *)event.data.alias.anchor);
- PSYCH_TRANSCODE(alias, encoding, internal_enc);
- }
-
- args[0] = handler;
- args[1] = alias;
- rb_protect(protected_alias, (VALUE)args, &state);
- }
- break;
- case YAML_SCALAR_EVENT:
- {
- VALUE args[7];
- VALUE anchor = Qnil;
- VALUE tag = Qnil;
- VALUE plain_implicit, quoted_implicit, style;
- VALUE val = rb_str_new(
- (const char *)event.data.scalar.value,
- (long)event.data.scalar.length
- );
-
- PSYCH_TRANSCODE(val, encoding, internal_enc);
-
- if(event.data.scalar.anchor) {
- anchor = rb_str_new2((const char *)event.data.scalar.anchor);
- PSYCH_TRANSCODE(anchor, encoding, internal_enc);
- }
-
- if(event.data.scalar.tag) {
- tag = rb_str_new2((const char *)event.data.scalar.tag);
- PSYCH_TRANSCODE(tag, encoding, internal_enc);
- }
-
- plain_implicit =
- event.data.scalar.plain_implicit == 0 ? Qfalse : Qtrue;
-
- quoted_implicit =
- event.data.scalar.quoted_implicit == 0 ? Qfalse : Qtrue;
-
- style = INT2NUM(event.data.scalar.style);
-
- args[0] = handler;
- args[1] = val;
- args[2] = anchor;
- args[3] = tag;
- args[4] = plain_implicit;
- args[5] = quoted_implicit;
- args[6] = style;
- rb_protect(protected_scalar, (VALUE)args, &state);
- }
- break;
- case YAML_SEQUENCE_START_EVENT:
- {
- VALUE args[5];
- VALUE anchor = Qnil;
- VALUE tag = Qnil;
- VALUE implicit, style;
- if(event.data.sequence_start.anchor) {
- anchor = rb_str_new2((const char *)event.data.sequence_start.anchor);
- PSYCH_TRANSCODE(anchor, encoding, internal_enc);
- }
-
- tag = Qnil;
- if(event.data.sequence_start.tag) {
- tag = rb_str_new2((const char *)event.data.sequence_start.tag);
- PSYCH_TRANSCODE(tag, encoding, internal_enc);
- }
-
- implicit =
- event.data.sequence_start.implicit == 0 ? Qfalse : Qtrue;
-
- style = INT2NUM(event.data.sequence_start.style);
-
- args[0] = handler;
- args[1] = anchor;
- args[2] = tag;
- args[3] = implicit;
- args[4] = style;
-
- rb_protect(protected_start_sequence, (VALUE)args, &state);
- }
- break;
- case YAML_SEQUENCE_END_EVENT:
- rb_protect(protected_end_sequence, handler, &state);
- break;
- case YAML_MAPPING_START_EVENT:
- {
- VALUE args[5];
- VALUE anchor = Qnil;
- VALUE tag = Qnil;
- VALUE implicit, style;
- if(event.data.mapping_start.anchor) {
- anchor = rb_str_new2((const char *)event.data.mapping_start.anchor);
- PSYCH_TRANSCODE(anchor, encoding, internal_enc);
- }
-
- if(event.data.mapping_start.tag) {
- tag = rb_str_new2((const char *)event.data.mapping_start.tag);
- PSYCH_TRANSCODE(tag, encoding, internal_enc);
- }
-
- implicit =
- event.data.mapping_start.implicit == 0 ? Qfalse : Qtrue;
-
- style = INT2NUM(event.data.mapping_start.style);
-
- args[0] = handler;
- args[1] = anchor;
- args[2] = tag;
- args[3] = implicit;
- args[4] = style;
-
- rb_protect(protected_start_mapping, (VALUE)args, &state);
- }
- break;
- case YAML_MAPPING_END_EVENT:
- rb_protect(protected_end_mapping, handler, &state);
- break;
- case YAML_NO_EVENT:
- rb_protect(protected_empty, handler, &state);
- break;
- case YAML_STREAM_END_EVENT:
- rb_protect(protected_end_stream, handler, &state);
- done = 1;
- break;
- }
- yaml_event_delete(&event);
- if (state) rb_jump_tag(state);
+ VALUE event_args[5];
+ VALUE start_line, start_column, end_line, end_column;
+
+ if(parser->error || !yaml_parser_parse(parser, &event)) {
+ VALUE exception;
+
+ exception = make_exception(parser, path);
+ yaml_parser_delete(parser);
+ yaml_parser_initialize(parser);
+
+ rb_exc_raise(exception);
+ }
+
+ start_line = SIZET2NUM(event.start_mark.line);
+ start_column = SIZET2NUM(event.start_mark.column);
+ end_line = SIZET2NUM(event.end_mark.line);
+ end_column = SIZET2NUM(event.end_mark.column);
+
+ event_args[0] = handler;
+ event_args[1] = start_line;
+ event_args[2] = start_column;
+ event_args[3] = end_line;
+ event_args[4] = end_column;
+ rb_protect(protected_event_location, (VALUE)event_args, &state);
+
+ switch(event.type) {
+ case YAML_STREAM_START_EVENT:
+ {
+ VALUE args[2];
+
+ args[0] = handler;
+ args[1] = INT2NUM(event.data.stream_start.encoding);
+ rb_protect(protected_start_stream, (VALUE)args, &state);
+ }
+ break;
+ case YAML_DOCUMENT_START_EVENT:
+ {
+ VALUE args[4];
+ /* Get a list of tag directives (if any) */
+ VALUE tag_directives = rb_ary_new();
+ /* Grab the document version */
+ VALUE version = event.data.document_start.version_directive ?
+ rb_ary_new3(
+ (long)2,
+ INT2NUM(event.data.document_start.version_directive->major),
+ INT2NUM(event.data.document_start.version_directive->minor)
+ ) : rb_ary_new();
+
+ if(event.data.document_start.tag_directives.start) {
+ yaml_tag_directive_t *start =
+ event.data.document_start.tag_directives.start;
+ yaml_tag_directive_t *end =
+ event.data.document_start.tag_directives.end;
+ for(; start != end; start++) {
+ VALUE handle = Qnil;
+ VALUE prefix = Qnil;
+ if(start->handle) {
+ handle = rb_str_new2((const char *)start->handle);
+ PSYCH_TRANSCODE(handle, encoding, internal_enc);
+ }
+
+ if(start->prefix) {
+ prefix = rb_str_new2((const char *)start->prefix);
+ PSYCH_TRANSCODE(prefix, encoding, internal_enc);
+ }
+
+ rb_ary_push(tag_directives, rb_ary_new3((long)2, handle, prefix));
+ }
+ }
+ args[0] = handler;
+ args[1] = version;
+ args[2] = tag_directives;
+ args[3] = event.data.document_start.implicit == 1 ? Qtrue : Qfalse;
+ rb_protect(protected_start_document, (VALUE)args, &state);
+ }
+ break;
+ case YAML_DOCUMENT_END_EVENT:
+ {
+ VALUE args[2];
+
+ args[0] = handler;
+ args[1] = event.data.document_end.implicit == 1 ? Qtrue : Qfalse;
+ rb_protect(protected_end_document, (VALUE)args, &state);
+ }
+ break;
+ case YAML_ALIAS_EVENT:
+ {
+ VALUE args[2];
+ VALUE alias = Qnil;
+ if(event.data.alias.anchor) {
+ alias = rb_str_new2((const char *)event.data.alias.anchor);
+ PSYCH_TRANSCODE(alias, encoding, internal_enc);
+ }
+
+ args[0] = handler;
+ args[1] = alias;
+ rb_protect(protected_alias, (VALUE)args, &state);
+ }
+ break;
+ case YAML_SCALAR_EVENT:
+ {
+ VALUE args[7];
+ VALUE anchor = Qnil;
+ VALUE tag = Qnil;
+ VALUE plain_implicit, quoted_implicit, style;
+ VALUE val = rb_str_new(
+ (const char *)event.data.scalar.value,
+ (long)event.data.scalar.length
+ );
+
+ PSYCH_TRANSCODE(val, encoding, internal_enc);
+
+ if(event.data.scalar.anchor) {
+ anchor = rb_str_new2((const char *)event.data.scalar.anchor);
+ PSYCH_TRANSCODE(anchor, encoding, internal_enc);
+ }
+
+ if(event.data.scalar.tag) {
+ tag = rb_str_new2((const char *)event.data.scalar.tag);
+ PSYCH_TRANSCODE(tag, encoding, internal_enc);
+ }
+
+ plain_implicit =
+ event.data.scalar.plain_implicit == 0 ? Qfalse : Qtrue;
+
+ quoted_implicit =
+ event.data.scalar.quoted_implicit == 0 ? Qfalse : Qtrue;
+
+ style = INT2NUM(event.data.scalar.style);
+
+ args[0] = handler;
+ args[1] = val;
+ args[2] = anchor;
+ args[3] = tag;
+ args[4] = plain_implicit;
+ args[5] = quoted_implicit;
+ args[6] = style;
+ rb_protect(protected_scalar, (VALUE)args, &state);
+ }
+ break;
+ case YAML_SEQUENCE_START_EVENT:
+ {
+ VALUE args[5];
+ VALUE anchor = Qnil;
+ VALUE tag = Qnil;
+ VALUE implicit, style;
+ if(event.data.sequence_start.anchor) {
+ anchor = rb_str_new2((const char *)event.data.sequence_start.anchor);
+ PSYCH_TRANSCODE(anchor, encoding, internal_enc);
+ }
+
+ tag = Qnil;
+ if(event.data.sequence_start.tag) {
+ tag = rb_str_new2((const char *)event.data.sequence_start.tag);
+ PSYCH_TRANSCODE(tag, encoding, internal_enc);
+ }
+
+ implicit =
+ event.data.sequence_start.implicit == 0 ? Qfalse : Qtrue;
+
+ style = INT2NUM(event.data.sequence_start.style);
+
+ args[0] = handler;
+ args[1] = anchor;
+ args[2] = tag;
+ args[3] = implicit;
+ args[4] = style;
+
+ rb_protect(protected_start_sequence, (VALUE)args, &state);
+ }
+ break;
+ case YAML_SEQUENCE_END_EVENT:
+ rb_protect(protected_end_sequence, handler, &state);
+ break;
+ case YAML_MAPPING_START_EVENT:
+ {
+ VALUE args[5];
+ VALUE anchor = Qnil;
+ VALUE tag = Qnil;
+ VALUE implicit, style;
+ if(event.data.mapping_start.anchor) {
+ anchor = rb_str_new2((const char *)event.data.mapping_start.anchor);
+ PSYCH_TRANSCODE(anchor, encoding, internal_enc);
+ }
+
+ if(event.data.mapping_start.tag) {
+ tag = rb_str_new2((const char *)event.data.mapping_start.tag);
+ PSYCH_TRANSCODE(tag, encoding, internal_enc);
+ }
+
+ implicit =
+ event.data.mapping_start.implicit == 0 ? Qfalse : Qtrue;
+
+ style = INT2NUM(event.data.mapping_start.style);
+
+ args[0] = handler;
+ args[1] = anchor;
+ args[2] = tag;
+ args[3] = implicit;
+ args[4] = style;
+
+ rb_protect(protected_start_mapping, (VALUE)args, &state);
+ }
+ break;
+ case YAML_MAPPING_END_EVENT:
+ rb_protect(protected_end_mapping, handler, &state);
+ break;
+ case YAML_NO_EVENT:
+ rb_protect(protected_empty, handler, &state);
+ break;
+ case YAML_STREAM_END_EVENT:
+ rb_protect(protected_end_stream, handler, &state);
+ done = 1;
+ break;
+ }
+ yaml_event_delete(&event);
+ if (state) rb_jump_tag(state);
}
return self;
@@ -562,4 +562,3 @@ void Init_psych_parser(void)
id_end_mapping = rb_intern("end_mapping");
id_event_location = rb_intern("event_location");
}
-/* vim: set noet sws=4 sw=4: */
diff --git a/ext/psych/psych_to_ruby.c b/ext/psych/psych_to_ruby.c
index b388ff7754..3ab0138b52 100644
--- a/ext/psych/psych_to_ruby.c
+++ b/ext/psych/psych_to_ruby.c
@@ -10,7 +10,11 @@ static VALUE build_exception(VALUE self, VALUE klass, VALUE mesg)
{
VALUE e = rb_obj_alloc(klass);
+#ifdef TRUFFLERUBY
+ rb_exc_set_message(e, mesg);
+#else
rb_iv_set(e, "mesg", mesg);
+#endif
return e;
}
@@ -36,4 +40,3 @@ void Init_psych_to_ruby(void)
rb_define_private_method(cPsychVisitorsToRuby, "build_exception", build_exception, 2);
rb_define_private_method(class_loader, "path2class", path2class, 1);
}
-/* vim: set noet sws=4 sw=4: */
diff --git a/ext/psych/psych_yaml_tree.c b/ext/psych/psych_yaml_tree.c
index 225655d127..bbd93f874d 100644
--- a/ext/psych/psych_yaml_tree.c
+++ b/ext/psych/psych_yaml_tree.c
@@ -9,4 +9,3 @@ void Init_psych_yaml_tree(void)
VALUE visitor = rb_define_class_under(visitors, "Visitor", rb_cObject);
cPsychVisitorsYamlTree = rb_define_class_under(visitors, "YAMLTree", visitor);
}
-/* vim: set noet sws=4 sw=4: */
diff --git a/ext/pty/depend b/ext/pty/depend
index adecfff862..8fa018d084 100644
--- a/ext/pty/depend
+++ b/ext/pty/depend
@@ -138,6 +138,7 @@ pty.o: $(hdrdir)/ruby/internal/intern/re.h
pty.o: $(hdrdir)/ruby/internal/intern/ruby.h
pty.o: $(hdrdir)/ruby/internal/intern/select.h
pty.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+pty.o: $(hdrdir)/ruby/internal/intern/set.h
pty.o: $(hdrdir)/ruby/internal/intern/signal.h
pty.o: $(hdrdir)/ruby/internal/intern/sprintf.h
pty.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -172,6 +173,7 @@ pty.o: $(hdrdir)/ruby/ruby.h
pty.o: $(hdrdir)/ruby/st.h
pty.o: $(hdrdir)/ruby/subst.h
pty.o: $(hdrdir)/ruby/util.h
+pty.o: $(top_srcdir)/id_table.h
pty.o: $(top_srcdir)/internal.h
pty.o: $(top_srcdir)/internal/array.h
pty.o: $(top_srcdir)/internal/compilers.h
diff --git a/ext/pty/pty.c b/ext/pty/pty.c
index 5ca55e41d6..7c79f81e33 100644
--- a/ext/pty/pty.c
+++ b/ext/pty/pty.c
@@ -94,7 +94,7 @@ static void getDevice(int*, int*, char [DEVICELEN], int);
static int start_new_session(char *errbuf, size_t errbuf_len);
static int obtain_ctty(int master, int slave, const char *slavename, char *errbuf, size_t errbuf_len);
-static int drop_privilige(char *errbuf, size_t errbuf_len);
+static int drop_privilege(char *errbuf, size_t errbuf_len);
struct child_info {
int master, slave;
@@ -117,7 +117,7 @@ chfunc(void *data, char *errbuf, size_t errbuf_len)
if (obtain_ctty(master, slave, slavename, errbuf, errbuf_len))
return -1;
- if (drop_privilige(errbuf, errbuf_len))
+ if (drop_privilege(errbuf, errbuf_len))
return -1;
return rb_exec_async_signal_safe(carg->eargp, errbuf, errbuf_len);
@@ -180,12 +180,12 @@ obtain_ctty(int master, int slave, const char *slavename, char *errbuf, size_t e
dup2(slave,0);
dup2(slave,1);
dup2(slave,2);
- if (slave < 0 || slave > 2) (void)!close(slave);
+ if (slave > 2) (void)!close(slave);
return 0;
}
static int
-drop_privilige(char *errbuf, size_t errbuf_len)
+drop_privilege(char *errbuf, size_t errbuf_len)
{
#if defined(HAVE_SETEUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRESUID)
if (seteuid(getuid())) ERROR_EXIT("seteuid()");
@@ -215,9 +215,13 @@ establishShell(int argc, VALUE *argv, struct pty_info *info,
else {
#if defined HAVE_PWD_H
const char *username = getenv("USER");
- struct passwd *pwent = getpwnam(username ? username : getlogin());
- if (pwent && pwent->pw_shell)
- shellname = pwent->pw_shell;
+ if (username == NULL)
+ username = getlogin();
+ if (username != NULL) {
+ struct passwd *pwent = getpwnam(username);
+ if (pwent && pwent->pw_shell)
+ shellname = pwent->pw_shell;
+ }
#endif
}
v = rb_str_new2(shellname);
@@ -606,9 +610,17 @@ pty_detach_process(VALUE v)
* +env+ is an optional hash that provides additional environment variables to the spawned pty.
*
* # sets FOO to "bar"
- * PTY.spawn({"FOO"=>"bar"}, "printenv", "FOO") { |r,w,pid| p r.read } #=> "bar\r\n"
+ * PTY.spawn({"FOO"=>"bar"}, "printenv", "FOO") do |r, w, pid|
+ * p r.read #=> "bar\r\n"
+ * ensure
+ * r.close; w.close; Process.wait(pid)
+ * end
* # unsets FOO
- * PTY.spawn({"FOO"=>nil}, "printenv", "FOO") { |r,w,pid| p r.read } #=> ""
+ * PTY.spawn({"FOO"=>nil}, "printenv", "FOO") do |r, w, pid|
+ * p r.read #=> ""
+ * ensure
+ * r.close; w.close; Process.wait(pid)
+ * end
*
* +command+ and +command_line+ are the full commands to run, given a String.
* Any additional +arguments+ will be passed to the command.
@@ -624,6 +636,15 @@ pty_detach_process(VALUE v)
* standard output and standard error
* +w+:: A writable IO that is the command's standard input
* +pid+:: The process identifier for the command.
+ *
+ * === Clean up
+ *
+ * This method does not clean up like closing IOs or waiting for child
+ * process, except that the process is detached in the block form to
+ * prevent it from becoming a zombie (see Process.detach). Any other
+ * cleanup is the responsibility of the caller. If waiting for +pid+,
+ * be sure to close both +r+ and +w+ before doing so; doing it in the
+ * reverse order may cause deadlock on some OSes.
*/
static VALUE
pty_getpty(int argc, VALUE *argv, VALUE self)
diff --git a/ext/rbconfig/sizeof/depend b/ext/rbconfig/sizeof/depend
index 5f75fa8c76..7e6c950769 100644
--- a/ext/rbconfig/sizeof/depend
+++ b/ext/rbconfig/sizeof/depend
@@ -142,6 +142,7 @@ limits.o: $(hdrdir)/ruby/internal/intern/re.h
limits.o: $(hdrdir)/ruby/internal/intern/ruby.h
limits.o: $(hdrdir)/ruby/internal/intern/select.h
limits.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+limits.o: $(hdrdir)/ruby/internal/intern/set.h
limits.o: $(hdrdir)/ruby/internal/intern/signal.h
limits.o: $(hdrdir)/ruby/internal/intern/sprintf.h
limits.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -301,6 +302,7 @@ sizes.o: $(hdrdir)/ruby/internal/intern/re.h
sizes.o: $(hdrdir)/ruby/internal/intern/ruby.h
sizes.o: $(hdrdir)/ruby/internal/intern/select.h
sizes.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+sizes.o: $(hdrdir)/ruby/internal/intern/set.h
sizes.o: $(hdrdir)/ruby/internal/intern/signal.h
sizes.o: $(hdrdir)/ruby/internal/intern/sprintf.h
sizes.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/ripper/depend b/ext/ripper/depend
index fe6bd872bd..944da25ee9 100644
--- a/ext/ripper/depend
+++ b/ext/ripper/depend
@@ -1,7 +1,7 @@
GEN = $(srcdir)/tools/generate.rb
SRC1 = $(top_srcdir)/parse.y
SRC2 = $(srcdir)/eventids2.c
-BISON = $(BASERUBY) $(top_srcdir)/tool/lrama/exe/lrama
+LRAMA = $(BASERUBY) $(top_srcdir)/tool/lrama/exe/lrama
.SUFFIXES: .y
@@ -12,7 +12,7 @@ ripper.o: ripper.c
.y.c:
$(ECHO) compiling compiler $<
- $(Q) $(BISON) -t -v -o$@ - $< < $<
+ $(Q) $(LRAMA) -o$@ - $< < $<
all: check
static: check
@@ -181,6 +181,7 @@ eventids1.o: $(hdrdir)/ruby/internal/intern/re.h
eventids1.o: $(hdrdir)/ruby/internal/intern/ruby.h
eventids1.o: $(hdrdir)/ruby/internal/intern/select.h
eventids1.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+eventids1.o: $(hdrdir)/ruby/internal/intern/set.h
eventids1.o: $(hdrdir)/ruby/internal/intern/signal.h
eventids1.o: $(hdrdir)/ruby/internal/intern/sprintf.h
eventids1.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -352,6 +353,7 @@ eventids2.o: $(hdrdir)/ruby/internal/intern/re.h
eventids2.o: $(hdrdir)/ruby/internal/intern/ruby.h
eventids2.o: $(hdrdir)/ruby/internal/intern/select.h
eventids2.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+eventids2.o: $(hdrdir)/ruby/internal/intern/set.h
eventids2.o: $(hdrdir)/ruby/internal/intern/signal.h
eventids2.o: $(hdrdir)/ruby/internal/intern/sprintf.h
eventids2.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -532,6 +534,7 @@ ripper.o: $(hdrdir)/ruby/internal/intern/re.h
ripper.o: $(hdrdir)/ruby/internal/intern/ruby.h
ripper.o: $(hdrdir)/ruby/internal/intern/select.h
ripper.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ripper.o: $(hdrdir)/ruby/internal/intern/set.h
ripper.o: $(hdrdir)/ruby/internal/intern/signal.h
ripper.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ripper.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -575,12 +578,14 @@ ripper.o: $(top_srcdir)/ccan/container_of/container_of.h
ripper.o: $(top_srcdir)/ccan/list/list.h
ripper.o: $(top_srcdir)/ccan/str/str.h
ripper.o: $(top_srcdir)/constant.h
+ripper.o: $(top_srcdir)/encindex.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/basic_operators.h
ripper.o: $(top_srcdir)/internal/bignum.h
ripper.o: $(top_srcdir)/internal/bits.h
+ripper.o: $(top_srcdir)/internal/box.h
ripper.o: $(top_srcdir)/internal/compile.h
ripper.o: $(top_srcdir)/internal/compilers.h
ripper.o: $(top_srcdir)/internal/complex.h
@@ -598,8 +603,10 @@ ripper.o: $(top_srcdir)/internal/re.h
ripper.o: $(top_srcdir)/internal/ruby_parser.h
ripper.o: $(top_srcdir)/internal/sanitizers.h
ripper.o: $(top_srcdir)/internal/serial.h
+ripper.o: $(top_srcdir)/internal/set_table.h
ripper.o: $(top_srcdir)/internal/static_assert.h
ripper.o: $(top_srcdir)/internal/string.h
+ripper.o: $(top_srcdir)/internal/struct.h
ripper.o: $(top_srcdir)/internal/symbol.h
ripper.o: $(top_srcdir)/internal/thread.h
ripper.o: $(top_srcdir)/internal/variable.h
@@ -770,6 +777,7 @@ ripper_init.o: $(hdrdir)/ruby/internal/intern/re.h
ripper_init.o: $(hdrdir)/ruby/internal/intern/ruby.h
ripper_init.o: $(hdrdir)/ruby/internal/intern/select.h
ripper_init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+ripper_init.o: $(hdrdir)/ruby/internal/intern/set.h
ripper_init.o: $(hdrdir)/ruby/internal/intern/signal.h
ripper_init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
ripper_init.o: $(hdrdir)/ruby/internal/intern/string.h
diff --git a/ext/ripper/eventids2.c b/ext/ripper/eventids2.c
index 439663f0fd..87f2f588ec 100644
--- a/ext/ripper/eventids2.c
+++ b/ext/ripper/eventids2.c
@@ -255,7 +255,6 @@ ripper_token2eventid(enum yytokentype tok)
[tRATIONAL] = O(rational),
[tREGEXP_BEG] = O(regexp_beg),
[tREGEXP_END] = O(regexp_end),
- [tRPAREN] = O(rparen),
[tRSHFT] = O(op),
[tSTAR] = O(op),
[tDSTAR] = O(op),
diff --git a/ext/ripper/lib/ripper/lexer.rb b/ext/ripper/lib/ripper/lexer.rb
index 6a3c04af30..9b849dfeae 100644
--- a/ext/ripper/lib/ripper/lexer.rb
+++ b/ext/ripper/lib/ripper/lexer.rb
@@ -53,6 +53,7 @@ class Ripper
end
class Lexer < ::Ripper #:nodoc: internal use only
+ # :stopdoc:
class State
attr_reader :to_int, :to_s
@@ -67,7 +68,7 @@ class Ripper
when 0, :to_int
@to_int
when 1, :to_s
- @event
+ @to_s
else
nil
end
@@ -242,7 +243,12 @@ class Ripper
end
def on_error2(mesg, elem)
- @errors.push Elem.new(elem.pos, __callee__, elem.tok, elem.state, mesg)
+ if elem
+ elem = Elem.new(elem.pos, __callee__, elem.tok, elem.state, mesg)
+ else
+ elem = Elem.new([lineno(), column()], __callee__, token(), state(), mesg)
+ end
+ @errors.push elem
end
PARSER_EVENTS.grep(/_error\z/) do |e|
arity = PARSER_EVENT_TABLE.fetch(e)
@@ -253,6 +259,7 @@ class Ripper
(SCANNER_EVENTS.map {|event|:"on_#{event}"} - private_instance_methods(false)).each do |event|
alias_method event, :_push_token
end
+ # :startdoc:
end
# [EXPERIMENTAL]
diff --git a/ext/ripper/ripper_init.c.tmpl b/ext/ripper/ripper_init.c.tmpl
index fc98c067b8..11e432423d 100644
--- a/ext/ripper/ripper_init.c.tmpl
+++ b/ext/ripper/ripper_init.c.tmpl
@@ -252,6 +252,18 @@ ripper_parser_set_debug_output(VALUE self, VALUE output)
return output;
}
+static int
+ripper_parser_dedent_string(struct parser_params *p, VALUE string, int width)
+{
+ int col;
+ rb_parser_string_t *str;
+ str = rb_str_to_parser_string(p, string);
+ col = rb_ruby_ripper_dedent_string(p, str, width);
+ rb_str_replace(string, rb_str_new_parser_string(str));
+ rb_parser_string_free(p, str);
+ return col;
+}
+
#ifdef UNIVERSAL_PARSER
struct dedent_string_arg {
struct parser_params *p;
@@ -267,7 +279,7 @@ parser_dedent_string0(VALUE a)
StringValue(arg->input);
wid = NUM2UINT(arg->width);
- col = rb_ruby_ripper_dedent_string(arg->p, arg->input, wid);
+ col = ripper_parser_dedent_string(arg->p, arg->input, wid);
return INT2NUM(col);
}
@@ -312,7 +324,7 @@ parser_dedent_string(VALUE self, VALUE input, VALUE width)
StringValue(input);
wid = NUM2UINT(width);
- col = rb_ruby_ripper_dedent_string(0, input, wid);
+ col = ripper_parser_dedent_string(0, input, wid);
return INT2NUM(col);
}
#endif
diff --git a/ext/ripper/tools/generate.rb b/ext/ripper/tools/generate.rb
index 92ced37f04..57ecac0b39 100644
--- a/ext/ripper/tools/generate.rb
+++ b/ext/ripper/tools/generate.rb
@@ -75,6 +75,7 @@ def generate_eventids1_h(ids)
buf << %Q[#ifndef RIPPER_EVENTIDS1\n]
buf << %Q[#define RIPPER_EVENTIDS1\n]
buf << %Q[\n]
+ buf << %Q[#define RIPPER_ID(n) ripper_parser_ids.id_ ## n\n]
buf << %Q[void ripper_init_eventids1(void);\n]
buf << %Q[void ripper_init_eventids1_table(VALUE self);\n]
buf << %Q[\n]
@@ -84,9 +85,6 @@ def generate_eventids1_h(ids)
end
buf << %Q[};\n]
buf << %Q[\n]
- ids.each do |id, arity|
- buf << %Q[#define ripper_id_#{id} ripper_parser_ids.id_#{id}\n]
- end
buf << %Q[#endif /* RIPPER_EVENTIDS1 */\n]
buf << %Q[\n]
end
@@ -101,7 +99,7 @@ def generate_eventids1(ids)
buf << %Q[void\n]
buf << %Q[ripper_init_eventids1(void)\n]
buf << %Q[{\n]
- buf << %Q[#define set_id1(name) ripper_id_##name = rb_intern_const("on_"#name)\n]
+ buf << %Q[#define set_id1(name) RIPPER_ID(name) = rb_intern_const("on_"#name)\n]
ids.each do |id, arity|
buf << %Q[ set_id1(#{id});\n]
end
diff --git a/ext/socket/ancdata.c b/ext/socket/ancdata.c
index 6ef040b692..f1e9e42524 100644
--- a/ext/socket/ancdata.c
+++ b/ext/socket/ancdata.c
@@ -1643,14 +1643,14 @@ bsock_recvmsg_internal(VALUE sock,
rb_obj_reveal(dat_str, rb_cString);
}
- ret = rb_ary_new3(3, dat_str,
- rsock_io_socket_addrinfo(sock, mh.msg_name, mh.msg_namelen),
#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
- INT2NUM(mh.msg_flags)
+ VALUE msg_flags = INT2NUM(mh.msg_flags);
#else
- Qnil
+ VALUE msg_flags = Qnil;
#endif
- );
+ ret = rb_ary_new3(3, dat_str,
+ rsock_io_socket_addrinfo(sock, mh.msg_name, mh.msg_namelen),
+ msg_flags);
#if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
family = rsock_getfamily(fptr);
diff --git a/ext/socket/basicsocket.c b/ext/socket/basicsocket.c
index 54c369f6fc..2fcae8eb54 100644
--- a/ext/socket/basicsocket.c
+++ b/ext/socket/basicsocket.c
@@ -124,7 +124,7 @@ bsock_close_read(VALUE sock)
rb_io_t *fptr;
GetOpenFile(sock, fptr);
- shutdown(fptr->fd, 0);
+ shutdown(fptr->fd, SHUT_RD);
if (!(fptr->mode & FMODE_WRITABLE)) {
return rb_io_close(sock);
}
@@ -157,7 +157,7 @@ bsock_close_write(VALUE sock)
if (!(fptr->mode & FMODE_READABLE)) {
return rb_io_close(sock);
}
- shutdown(fptr->fd, 1);
+ shutdown(fptr->fd, SHUT_WR);
fptr->mode &= ~FMODE_WRITABLE;
return Qnil;
@@ -597,7 +597,7 @@ rsock_bsock_send(int argc, VALUE *argv, VALUE socket)
rb_io_wait(socket, RB_INT2NUM(RUBY_IO_WRITABLE), Qnil);
#endif
- ssize_t n = (ssize_t)BLOCKING_REGION_FD(func, &arg);
+ ssize_t n = (ssize_t)rb_io_blocking_region(fptr, func, &arg);
if (n >= 0) return SSIZET2NUM(n);
diff --git a/ext/socket/depend b/ext/socket/depend
index 750bb0734f..77f6239a3d 100644
--- a/ext/socket/depend
+++ b/ext/socket/depend
@@ -151,6 +151,7 @@ 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/set.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
@@ -192,9 +193,12 @@ ancdata.o: $(top_srcdir)/ccan/check_type/check_type.h
ancdata.o: $(top_srcdir)/ccan/container_of/container_of.h
ancdata.o: $(top_srcdir)/ccan/list/list.h
ancdata.o: $(top_srcdir)/ccan/str/str.h
+ancdata.o: $(top_srcdir)/encindex.h
+ancdata.o: $(top_srcdir)/id_table.h
ancdata.o: $(top_srcdir)/internal.h
ancdata.o: $(top_srcdir)/internal/array.h
ancdata.o: $(top_srcdir)/internal/basic_operators.h
+ancdata.o: $(top_srcdir)/internal/box.h
ancdata.o: $(top_srcdir)/internal/compilers.h
ancdata.o: $(top_srcdir)/internal/error.h
ancdata.o: $(top_srcdir)/internal/gc.h
@@ -202,6 +206,7 @@ ancdata.o: $(top_srcdir)/internal/imemo.h
ancdata.o: $(top_srcdir)/internal/io.h
ancdata.o: $(top_srcdir)/internal/sanitizers.h
ancdata.o: $(top_srcdir)/internal/serial.h
+ancdata.o: $(top_srcdir)/internal/set_table.h
ancdata.o: $(top_srcdir)/internal/static_assert.h
ancdata.o: $(top_srcdir)/internal/string.h
ancdata.o: $(top_srcdir)/internal/thread.h
@@ -362,6 +367,7 @@ 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/set.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
@@ -403,9 +409,12 @@ basicsocket.o: $(top_srcdir)/ccan/check_type/check_type.h
basicsocket.o: $(top_srcdir)/ccan/container_of/container_of.h
basicsocket.o: $(top_srcdir)/ccan/list/list.h
basicsocket.o: $(top_srcdir)/ccan/str/str.h
+basicsocket.o: $(top_srcdir)/encindex.h
+basicsocket.o: $(top_srcdir)/id_table.h
basicsocket.o: $(top_srcdir)/internal.h
basicsocket.o: $(top_srcdir)/internal/array.h
basicsocket.o: $(top_srcdir)/internal/basic_operators.h
+basicsocket.o: $(top_srcdir)/internal/box.h
basicsocket.o: $(top_srcdir)/internal/compilers.h
basicsocket.o: $(top_srcdir)/internal/error.h
basicsocket.o: $(top_srcdir)/internal/gc.h
@@ -413,6 +422,7 @@ basicsocket.o: $(top_srcdir)/internal/imemo.h
basicsocket.o: $(top_srcdir)/internal/io.h
basicsocket.o: $(top_srcdir)/internal/sanitizers.h
basicsocket.o: $(top_srcdir)/internal/serial.h
+basicsocket.o: $(top_srcdir)/internal/set_table.h
basicsocket.o: $(top_srcdir)/internal/static_assert.h
basicsocket.o: $(top_srcdir)/internal/string.h
basicsocket.o: $(top_srcdir)/internal/thread.h
@@ -573,6 +583,7 @@ 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/set.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
@@ -614,9 +625,12 @@ constants.o: $(top_srcdir)/ccan/check_type/check_type.h
constants.o: $(top_srcdir)/ccan/container_of/container_of.h
constants.o: $(top_srcdir)/ccan/list/list.h
constants.o: $(top_srcdir)/ccan/str/str.h
+constants.o: $(top_srcdir)/encindex.h
+constants.o: $(top_srcdir)/id_table.h
constants.o: $(top_srcdir)/internal.h
constants.o: $(top_srcdir)/internal/array.h
constants.o: $(top_srcdir)/internal/basic_operators.h
+constants.o: $(top_srcdir)/internal/box.h
constants.o: $(top_srcdir)/internal/compilers.h
constants.o: $(top_srcdir)/internal/error.h
constants.o: $(top_srcdir)/internal/gc.h
@@ -624,6 +638,7 @@ constants.o: $(top_srcdir)/internal/imemo.h
constants.o: $(top_srcdir)/internal/io.h
constants.o: $(top_srcdir)/internal/sanitizers.h
constants.o: $(top_srcdir)/internal/serial.h
+constants.o: $(top_srcdir)/internal/set_table.h
constants.o: $(top_srcdir)/internal/static_assert.h
constants.o: $(top_srcdir)/internal/string.h
constants.o: $(top_srcdir)/internal/thread.h
@@ -785,6 +800,7 @@ 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/set.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
@@ -826,9 +842,12 @@ ifaddr.o: $(top_srcdir)/ccan/check_type/check_type.h
ifaddr.o: $(top_srcdir)/ccan/container_of/container_of.h
ifaddr.o: $(top_srcdir)/ccan/list/list.h
ifaddr.o: $(top_srcdir)/ccan/str/str.h
+ifaddr.o: $(top_srcdir)/encindex.h
+ifaddr.o: $(top_srcdir)/id_table.h
ifaddr.o: $(top_srcdir)/internal.h
ifaddr.o: $(top_srcdir)/internal/array.h
ifaddr.o: $(top_srcdir)/internal/basic_operators.h
+ifaddr.o: $(top_srcdir)/internal/box.h
ifaddr.o: $(top_srcdir)/internal/compilers.h
ifaddr.o: $(top_srcdir)/internal/error.h
ifaddr.o: $(top_srcdir)/internal/gc.h
@@ -836,6 +855,7 @@ ifaddr.o: $(top_srcdir)/internal/imemo.h
ifaddr.o: $(top_srcdir)/internal/io.h
ifaddr.o: $(top_srcdir)/internal/sanitizers.h
ifaddr.o: $(top_srcdir)/internal/serial.h
+ifaddr.o: $(top_srcdir)/internal/set_table.h
ifaddr.o: $(top_srcdir)/internal/static_assert.h
ifaddr.o: $(top_srcdir)/internal/string.h
ifaddr.o: $(top_srcdir)/internal/thread.h
@@ -996,6 +1016,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h
init.o: $(hdrdir)/ruby/internal/intern/ruby.h
init.o: $(hdrdir)/ruby/internal/intern/select.h
init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h
+init.o: $(hdrdir)/ruby/internal/intern/set.h
init.o: $(hdrdir)/ruby/internal/intern/signal.h
init.o: $(hdrdir)/ruby/internal/intern/sprintf.h
init.o: $(hdrdir)/ruby/internal/intern/string.h
@@ -1037,9 +1058,12 @@ init.o: $(top_srcdir)/ccan/check_type/check_type.h
init.o: $(top_srcdir)/ccan/container_of/container_of.h
init.o: $(top_srcdir)/ccan/list/list.h
init.o: $(top_srcdir)/ccan/str/str.h
+init.o: $(top_srcdir)/encindex.h
+init.o: $(top_srcdir)/id_table.h
init.o: $(top_srcdir)/internal.h
init.o: $(top_srcdir)/internal/array.h
init.o: $(top_srcdir)/internal/basic_operators.h
+init.o: $(top_srcdir)/internal/box.h
init.o: $(top_srcdir)/internal/compilers.h
init.o: $(top_srcdir)/internal/error.h
init.o: $(top_srcdir)/internal/gc.h
@@ -1047,6 +1071,7 @@ init.o: $(top_srcdir)/internal/imemo.h
init.o: $(top_srcdir)/internal/io.h
init.o: $(top_srcdir)/internal/sanitizers.h
init.o: $(top_srcdir)/internal/serial.h
+init.o: $(top_srcdir)/internal/set_table.h
init.o: $(top_srcdir)/internal/static_assert.h
init.o: $(top_srcdir)/internal/string.h
init.o: $(top_srcdir)/internal/thread.h
@@ -1207,6 +1232,7 @@ 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/set.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
@@ -1248,9 +1274,12 @@ ipsocket.o: $(top_srcdir)/ccan/check_type/check_type.h
ipsocket.o: $(top_srcdir)/ccan/container_of/container_of.h
ipsocket.o: $(top_srcdir)/ccan/list/list.h
ipsocket.o: $(top_srcdir)/ccan/str/str.h
+ipsocket.o: $(top_srcdir)/encindex.h
+ipsocket.o: $(top_srcdir)/id_table.h
ipsocket.o: $(top_srcdir)/internal.h
ipsocket.o: $(top_srcdir)/internal/array.h
ipsocket.o: $(top_srcdir)/internal/basic_operators.h
+ipsocket.o: $(top_srcdir)/internal/box.h
ipsocket.o: $(top_srcdir)/internal/compilers.h
ipsocket.o: $(top_srcdir)/internal/error.h
ipsocket.o: $(top_srcdir)/internal/gc.h
@@ -1258,6 +1287,7 @@ ipsocket.o: $(top_srcdir)/internal/imemo.h
ipsocket.o: $(top_srcdir)/internal/io.h
ipsocket.o: $(top_srcdir)/internal/sanitizers.h
ipsocket.o: $(top_srcdir)/internal/serial.h
+ipsocket.o: $(top_srcdir)/internal/set_table.h
ipsocket.o: $(top_srcdir)/internal/static_assert.h
ipsocket.o: $(top_srcdir)/internal/string.h
ipsocket.o: $(top_srcdir)/internal/thread.h
@@ -1418,6 +1448,7 @@ 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/set.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
@@ -1459,9 +1490,12 @@ option.o: $(top_srcdir)/ccan/check_type/check_type.h
option.o: $(top_srcdir)/ccan/container_of/container_of.h
option.o: $(top_srcdir)/ccan/list/list.h
option.o: $(top_srcdir)/ccan/str/str.h
+option.o: $(top_srcdir)/encindex.h
+option.o: $(top_srcdir)/id_table.h
option.o: $(top_srcdir)/internal.h
option.o: $(top_srcdir)/internal/array.h
option.o: $(top_srcdir)/internal/basic_operators.h
+option.o: $(top_srcdir)/internal/box.h
option.o: $(top_srcdir)/internal/compilers.h
option.o: $(top_srcdir)/internal/error.h
option.o: $(top_srcdir)/internal/gc.h
@@ -1469,6 +1503,7 @@ option.o: $(top_srcdir)/internal/imemo.h
option.o: $(top_srcdir)/internal/io.h
option.o: $(top_srcdir)/internal/sanitizers.h
option.o: $(top_srcdir)/internal/serial.h
+option.o: $(top_srcdir)/internal/set_table.h
option.o: $(top_srcdir)/internal/static_assert.h
option.o: $(top_srcdir)/internal/string.h
option.o: $(top_srcdir)/internal/thread.h
@@ -1629,6 +1664,7 @@ 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/set.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
@@ -1670,9 +1706,12 @@ raddrinfo.o: $(top_srcdir)/ccan/check_type/check_type.h
raddrinfo.o: $(top_srcdir)/ccan/container_of/container_of.h
raddrinfo.o: $(top_srcdir)/ccan/list/list.h
raddrinfo.o: $(top_srcdir)/ccan/str/str.h
+raddrinfo.o: $(top_srcdir)/encindex.h
+raddrinfo.o: $(top_srcdir)/id_table.h
raddrinfo.o: $(top_srcdir)/internal.h
raddrinfo.o: $(top_srcdir)/internal/array.h
raddrinfo.o: $(top_srcdir)/internal/basic_operators.h
+raddrinfo.o: $(top_srcdir)/internal/box.h
raddrinfo.o: $(top_srcdir)/internal/compilers.h
raddrinfo.o: $(top_srcdir)/internal/error.h
raddrinfo.o: $(top_srcdir)/internal/gc.h
@@ -1680,6 +1719,7 @@ raddrinfo.o: $(top_srcdir)/internal/imemo.h
raddrinfo.o: $(top_srcdir)/internal/io.h
raddrinfo.o: $(top_srcdir)/internal/sanitizers.h
raddrinfo.o: $(top_srcdir)/internal/serial.h
+raddrinfo.o: $(top_srcdir)/internal/set_table.h
raddrinfo.o: $(top_srcdir)/internal/static_assert.h
raddrinfo.o: $(top_srcdir)/internal/string.h
raddrinfo.o: $(top_srcdir)/internal/thread.h
@@ -1840,6 +1880,7 @@ 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/set.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
@@ -1881,9 +1922,12 @@ socket.o: $(top_srcdir)/ccan/check_type/check_type.h
socket.o: $(top_srcdir)/ccan/container_of/container_of.h
socket.o: $(top_srcdir)/ccan/list/list.h
socket.o: $(top_srcdir)/ccan/str/str.h
+socket.o: $(top_srcdir)/encindex.h
+socket.o: $(top_srcdir)/id_table.h
socket.o: $(top_srcdir)/internal.h
socket.o: $(top_srcdir)/internal/array.h
socket.o: $(top_srcdir)/internal/basic_operators.h
+socket.o: $(top_srcdir)/internal/box.h
socket.o: $(top_srcdir)/internal/compilers.h
socket.o: $(top_srcdir)/internal/error.h
socket.o: $(top_srcdir)/internal/gc.h
@@ -1891,6 +1935,7 @@ socket.o: $(top_srcdir)/internal/imemo.h
socket.o: $(top_srcdir)/internal/io.h
socket.o: $(top_srcdir)/internal/sanitizers.h
socket.o: $(top_srcdir)/internal/serial.h
+socket.o: $(top_srcdir)/internal/set_table.h
socket.o: $(top_srcdir)/internal/static_assert.h
socket.o: $(top_srcdir)/internal/string.h
socket.o: $(top_srcdir)/internal/thread.h
@@ -2051,6 +2096,7 @@ 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/set.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
@@ -2092,9 +2138,12 @@ sockssocket.o: $(top_srcdir)/ccan/check_type/check_type.h
sockssocket.o: $(top_srcdir)/ccan/container_of/container_of.h
sockssocket.o: $(top_srcdir)/ccan/list/list.h
sockssocket.o: $(top_srcdir)/ccan/str/str.h
+sockssocket.o: $(top_srcdir)/encindex.h
+sockssocket.o: $(top_srcdir)/id_table.h
sockssocket.o: $(top_srcdir)/internal.h
sockssocket.o: $(top_srcdir)/internal/array.h
sockssocket.o: $(top_srcdir)/internal/basic_operators.h
+sockssocket.o: $(top_srcdir)/internal/box.h
sockssocket.o: $(top_srcdir)/internal/compilers.h
sockssocket.o: $(top_srcdir)/internal/error.h
sockssocket.o: $(top_srcdir)/internal/gc.h
@@ -2102,6 +2151,7 @@ sockssocket.o: $(top_srcdir)/internal/imemo.h
sockssocket.o: $(top_srcdir)/internal/io.h
sockssocket.o: $(top_srcdir)/internal/sanitizers.h
sockssocket.o: $(top_srcdir)/internal/serial.h
+sockssocket.o: $(top_srcdir)/internal/set_table.h
sockssocket.o: $(top_srcdir)/internal/static_assert.h
sockssocket.o: $(top_srcdir)/internal/string.h
sockssocket.o: $(top_srcdir)/internal/thread.h
@@ -2262,6 +2312,7 @@ 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/set.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
@@ -2303,9 +2354,12 @@ tcpserver.o: $(top_srcdir)/ccan/check_type/check_type.h
tcpserver.o: $(top_srcdir)/ccan/container_of/container_of.h
tcpserver.o: $(top_srcdir)/ccan/list/list.h
tcpserver.o: $(top_srcdir)/ccan/str/str.h
+tcpserver.o: $(top_srcdir)/encindex.h
+tcpserver.o: $(top_srcdir)/id_table.h
tcpserver.o: $(top_srcdir)/internal.h
tcpserver.o: $(top_srcdir)/internal/array.h
tcpserver.o: $(top_srcdir)/internal/basic_operators.h
+tcpserver.o: $(top_srcdir)/internal/box.h
tcpserver.o: $(top_srcdir)/internal/compilers.h
tcpserver.o: $(top_srcdir)/internal/error.h
tcpserver.o: $(top_srcdir)/internal/gc.h
@@ -2313,6 +2367,7 @@ tcpserver.o: $(top_srcdir)/internal/imemo.h
tcpserver.o: $(top_srcdir)/internal/io.h
tcpserver.o: $(top_srcdir)/internal/sanitizers.h
tcpserver.o: $(top_srcdir)/internal/serial.h
+tcpserver.o: $(top_srcdir)/internal/set_table.h
tcpserver.o: $(top_srcdir)/internal/static_assert.h
tcpserver.o: $(top_srcdir)/internal/string.h
tcpserver.o: $(top_srcdir)/internal/thread.h
@@ -2473,6 +2528,7 @@ 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/set.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
@@ -2514,9 +2570,12 @@ tcpsocket.o: $(top_srcdir)/ccan/check_type/check_type.h
tcpsocket.o: $(top_srcdir)/ccan/container_of/container_of.h
tcpsocket.o: $(top_srcdir)/ccan/list/list.h
tcpsocket.o: $(top_srcdir)/ccan/str/str.h
+tcpsocket.o: $(top_srcdir)/encindex.h
+tcpsocket.o: $(top_srcdir)/id_table.h
tcpsocket.o: $(top_srcdir)/internal.h
tcpsocket.o: $(top_srcdir)/internal/array.h
tcpsocket.o: $(top_srcdir)/internal/basic_operators.h
+tcpsocket.o: $(top_srcdir)/internal/box.h
tcpsocket.o: $(top_srcdir)/internal/compilers.h
tcpsocket.o: $(top_srcdir)/internal/error.h
tcpsocket.o: $(top_srcdir)/internal/gc.h
@@ -2524,6 +2583,7 @@ tcpsocket.o: $(top_srcdir)/internal/imemo.h
tcpsocket.o: $(top_srcdir)/internal/io.h
tcpsocket.o: $(top_srcdir)/internal/sanitizers.h
tcpsocket.o: $(top_srcdir)/internal/serial.h
+tcpsocket.o: $(top_srcdir)/internal/set_table.h
tcpsocket.o: $(top_srcdir)/internal/static_assert.h
tcpsocket.o: $(top_srcdir)/internal/string.h
tcpsocket.o: $(top_srcdir)/internal/thread.h
@@ -2684,6 +2744,7 @@ 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/set.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
@@ -2725,9 +2786,12 @@ udpsocket.o: $(top_srcdir)/ccan/check_type/check_type.h
udpsocket.o: $(top_srcdir)/ccan/container_of/container_of.h
udpsocket.o: $(top_srcdir)/ccan/list/list.h
udpsocket.o: $(top_srcdir)/ccan/str/str.h
+udpsocket.o: $(top_srcdir)/encindex.h
+udpsocket.o: $(top_srcdir)/id_table.h
udpsocket.o: $(top_srcdir)/internal.h
udpsocket.o: $(top_srcdir)/internal/array.h
udpsocket.o: $(top_srcdir)/internal/basic_operators.h
+udpsocket.o: $(top_srcdir)/internal/box.h
udpsocket.o: $(top_srcdir)/internal/compilers.h
udpsocket.o: $(top_srcdir)/internal/error.h
udpsocket.o: $(top_srcdir)/internal/gc.h
@@ -2735,6 +2799,7 @@ udpsocket.o: $(top_srcdir)/internal/imemo.h
udpsocket.o: $(top_srcdir)/internal/io.h
udpsocket.o: $(top_srcdir)/internal/sanitizers.h
udpsocket.o: $(top_srcdir)/internal/serial.h
+udpsocket.o: $(top_srcdir)/internal/set_table.h
udpsocket.o: $(top_srcdir)/internal/static_assert.h
udpsocket.o: $(top_srcdir)/internal/string.h
udpsocket.o: $(top_srcdir)/internal/thread.h
@@ -2895,6 +2960,7 @@ 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/set.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
@@ -2936,9 +3002,12 @@ unixserver.o: $(top_srcdir)/ccan/check_type/check_type.h
unixserver.o: $(top_srcdir)/ccan/container_of/container_of.h
unixserver.o: $(top_srcdir)/ccan/list/list.h
unixserver.o: $(top_srcdir)/ccan/str/str.h
+unixserver.o: $(top_srcdir)/encindex.h
+unixserver.o: $(top_srcdir)/id_table.h
unixserver.o: $(top_srcdir)/internal.h
unixserver.o: $(top_srcdir)/internal/array.h
unixserver.o: $(top_srcdir)/internal/basic_operators.h
+unixserver.o: $(top_srcdir)/internal/box.h
unixserver.o: $(top_srcdir)/internal/compilers.h
unixserver.o: $(top_srcdir)/internal/error.h
unixserver.o: $(top_srcdir)/internal/gc.h
@@ -2946,6 +3015,7 @@ unixserver.o: $(top_srcdir)/internal/imemo.h
unixserver.o: $(top_srcdir)/internal/io.h
unixserver.o: $(top_srcdir)/internal/sanitizers.h
unixserver.o: $(top_srcdir)/internal/serial.h
+unixserver.o: $(top_srcdir)/internal/set_table.h
unixserver.o: $(top_srcdir)/internal/static_assert.h
unixserver.o: $(top_srcdir)/internal/string.h
unixserver.o: $(top_srcdir)/internal/thread.h
@@ -3106,6 +3176,7 @@ 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/set.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
@@ -3147,9 +3218,12 @@ unixsocket.o: $(top_srcdir)/ccan/check_type/check_type.h
unixsocket.o: $(top_srcdir)/ccan/container_of/container_of.h
unixsocket.o: $(top_srcdir)/ccan/list/list.h
unixsocket.o: $(top_srcdir)/ccan/str/str.h
+unixsocket.o: $(top_srcdir)/encindex.h
+unixsocket.o: $(top_srcdir)/id_table.h
unixsocket.o: $(top_srcdir)/internal.h
unixsocket.o: $(top_srcdir)/internal/array.h
unixsocket.o: $(top_srcdir)/internal/basic_operators.h
+unixsocket.o: $(top_srcdir)/internal/box.h
unixsocket.o: $(top_srcdir)/internal/compilers.h
unixsocket.o: $(top_srcdir)/internal/error.h
unixsocket.o: $(top_srcdir)/internal/gc.h
@@ -3157,6 +3231,7 @@ unixsocket.o: $(top_srcdir)/internal/imemo.h
unixsocket.o: $(top_srcdir)/internal/io.h
unixsocket.o: $(top_srcdir)/internal/sanitizers.h
unixsocket.o: $(top_srcdir)/internal/serial.h
+unixsocket.o: $(top_srcdir)/internal/set_table.h
unixsocket.o: $(top_srcdir)/internal/static_assert.h
unixsocket.o: $(top_srcdir)/internal/string.h
unixsocket.o: $(top_srcdir)/internal/thread.h
diff --git a/ext/socket/extconf.rb b/ext/socket/extconf.rb
index d44ce31b0a..a814e21c3a 100644
--- a/ext/socket/extconf.rb
+++ b/ext/socket/extconf.rb
@@ -704,6 +704,7 @@ SRC
have_func("pthread_create")
have_func("pthread_detach")
+ have_func("pthread_attr_setdetachstate")
$VPATH << '$(topdir)' << '$(top_srcdir)'
create_makefile("socket")
diff --git a/ext/socket/getaddrinfo.c b/ext/socket/getaddrinfo.c
index bf0d90129f..9a65490b1d 100644
--- a/ext/socket/getaddrinfo.c
+++ b/ext/socket/getaddrinfo.c
@@ -62,9 +62,6 @@
#endif
#include <unistd.h>
#else
-#if defined(_MSC_VER) && _MSC_VER <= 1200
-#include <windows.h>
-#endif
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
@@ -171,9 +168,7 @@ static const char *const ai_errlist[] = {
#define GET_CANONNAME(ai, str) \
if (pai->ai_flags & AI_CANONNAME) {\
- if (((ai)->ai_canonname = (char *)malloc(strlen(str) + 1)) != NULL) {\
- strcpy((ai)->ai_canonname, (str));\
- } else {\
+ if (((ai)->ai_canonname = strdup(str)) == NULL) {\
error = EAI_MEMORY;\
goto free;\
}\
diff --git a/ext/socket/getnameinfo.c b/ext/socket/getnameinfo.c
index ae5284fab6..98da8c1647 100644
--- a/ext/socket/getnameinfo.c
+++ b/ext/socket/getnameinfo.c
@@ -55,9 +55,6 @@
#endif
#endif
#ifdef _WIN32
-#if defined(_MSC_VER) && _MSC_VER <= 1200
-#include <windows.h>
-#endif
#include <winsock2.h>
#include <ws2tcpip.h>
#define snprintf _snprintf
@@ -158,16 +155,14 @@ getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_t ho
/* what we should do? */
} else if (flags & NI_NUMERICSERV) {
snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
- if (strlen(numserv) + 1 > servlen)
+ if (strlcpy(serv, numserv, servlen) >= servlen)
return ENI_MEMORY;
- strcpy(serv, numserv);
} else {
#if defined(HAVE_GETSERVBYPORT)
struct servent *sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp");
if (sp) {
- if (strlen(sp->s_name) + 1 > servlen)
+ if (strlcpy(serv, sp->s_name, servlen) >= servlen)
return ENI_MEMORY;
- strcpy(serv, sp->s_name);
} else
return ENI_NOSERVNAME;
#else
@@ -202,9 +197,8 @@ getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_t ho
if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
== NULL)
return ENI_SYSTEM;
- if (strlen(numaddr) > hostlen)
+ if (strlcpy(host, numaddr, hostlen) >= hostlen)
return ENI_MEMORY;
- strcpy(host, numaddr);
} else {
#ifdef INET6
hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
@@ -218,13 +212,12 @@ getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_t ho
p = strchr(hp->h_name, '.');
if (p) *p = '\0';
}
- if (strlen(hp->h_name) + 1 > hostlen) {
+ if (strlcpy(host, hp->h_name, hostlen) >= hostlen) {
#ifdef INET6
freehostent(hp);
#endif
return ENI_MEMORY;
}
- strcpy(host, hp->h_name);
#ifdef INET6
freehostent(hp);
#endif
@@ -234,9 +227,8 @@ getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, socklen_t ho
if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
== NULL)
return ENI_NOHOSTNAME;
- if (strlen(numaddr) > hostlen)
+ if (strlcpy(host, numaddr, hostlen) >= hostlen)
return ENI_MEMORY;
- strcpy(host, numaddr);
}
}
return SUCCESS;
diff --git a/ext/socket/ifaddr.c b/ext/socket/ifaddr.c
index ab163dcc8f..3596c40a11 100644
--- a/ext/socket/ifaddr.c
+++ b/ext/socket/ifaddr.c
@@ -177,6 +177,8 @@ ifaddr_ifindex(VALUE self)
* ifaddr.flags => integer
*
* Returns the flags of _ifaddr_.
+ *
+ * The value is bitwise-or of Socket::IFF_* constants such as Socket::IFF_LOOPBACK.
*/
static VALUE
diff --git a/ext/socket/init.c b/ext/socket/init.c
index 0e312b540e..b761d601c3 100644
--- a/ext/socket/init.c
+++ b/ext/socket/init.c
@@ -107,6 +107,7 @@ rsock_send_blocking(void *data)
}
struct recvfrom_arg {
+ rb_io_t *fptr;
int fd, flags;
VALUE str;
size_t length;
@@ -151,7 +152,7 @@ recvfrom_locktmp(VALUE v)
{
struct recvfrom_arg *arg = (struct recvfrom_arg *)v;
- return rb_thread_io_blocking_region(recvfrom_blocking, arg, arg->fd);
+ return rb_io_blocking_region(arg->fptr, recvfrom_blocking, arg);
}
int
@@ -192,6 +193,7 @@ rsock_s_recvfrom(VALUE socket, int argc, VALUE *argv, enum sock_recv_type from)
rb_raise(rb_eIOError, "recv for buffered IO");
}
+ arg.fptr = fptr;
arg.fd = fptr->fd;
arg.alen = (socklen_t)sizeof(arg.buf);
arg.str = str;
@@ -471,10 +473,11 @@ rsock_socket(int domain, int type, int proto)
/* emulate blocking connect behavior on EINTR or non-blocking socket */
static int
-wait_connectable(int fd, struct timeval *timeout)
+wait_connectable(VALUE self, VALUE timeout, const struct sockaddr *sockaddr, int len)
{
- int sockerr, revents;
+ int sockerr;
socklen_t sockerrlen;
+ int fd = rb_io_descriptor(self);
sockerrlen = (socklen_t)sizeof(sockerr);
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&sockerr, &sockerrlen) < 0)
@@ -508,7 +511,16 @@ wait_connectable(int fd, struct timeval *timeout)
*
* Note: rb_wait_for_single_fd already retries on EINTR/ERESTART
*/
- revents = rb_wait_for_single_fd(fd, RB_WAITFD_IN|RB_WAITFD_OUT, timeout);
+ VALUE result = rb_io_wait(self, RB_INT2NUM(RUBY_IO_READABLE|RUBY_IO_WRITABLE), timeout);
+
+ if (result == Qfalse) {
+ VALUE rai = rsock_addrinfo_new((struct sockaddr *)sockaddr, len, PF_UNSPEC, 0, 0, Qnil, Qnil);
+ VALUE addr_str = rsock_addrinfo_inspect_sockaddr(rai);
+ VALUE message = rb_sprintf("user specified timeout for %" PRIsVALUE, addr_str);
+ rb_raise(rb_eIOTimeoutError, "%" PRIsVALUE, message);
+ }
+
+ int revents = RB_NUM2INT(result);
if (revents < 0)
return -1;
@@ -523,12 +535,6 @@ wait_connectable(int fd, struct timeval *timeout)
* 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:
@@ -576,19 +582,19 @@ socks_connect_blocking(void *data)
#endif
int
-rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks, struct timeval *timeout)
+rsock_connect(VALUE self, const struct sockaddr *sockaddr, int len, int socks, VALUE timeout)
{
- int status;
+ int descriptor = rb_io_descriptor(self);
rb_blocking_function_t *func = connect_blocking;
- struct connect_arg arg;
+ struct connect_arg arg = {.fd = descriptor, .sockaddr = sockaddr, .len = len};
+
+ rb_io_t *fptr;
+ RB_IO_POINTER(self, fptr);
- arg.fd = fd;
- arg.sockaddr = sockaddr;
- arg.len = len;
#if defined(SOCKS) && !defined(SOCKS5)
if (socks) func = socks_connect_blocking;
#endif
- status = (int)BLOCKING_REGION_FD(func, &arg);
+ int status = (int)rb_io_blocking_region(fptr, func, &arg);
if (status < 0) {
switch (errno) {
@@ -600,7 +606,7 @@ rsock_connect(int fd, const struct sockaddr *sockaddr, int len, int socks, struc
#ifdef EINPROGRESS
case EINPROGRESS:
#endif
- return wait_connectable(fd, timeout);
+ return wait_connectable(self, timeout, sockaddr, len);
}
}
return status;
@@ -719,7 +725,7 @@ rsock_s_accept(VALUE klass, VALUE io, struct sockaddr *sockaddr, socklen_t *len)
#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);
+ peer = (int)rb_io_blocking_region(fptr, accept_blocking, &accept_arg);
if (peer < 0) {
int error = errno;
@@ -783,7 +789,17 @@ rsock_getfamily(rb_io_t *fptr)
* call-seq:
* error_code -> integer
*
- * Returns the raw error code occurred at name resolution.
+ * Returns the raw error code indicating the cause of the hostname resolution failure.
+ *
+ * begin
+ * Addrinfo.getaddrinfo("ruby-lang.org", nil)
+ * rescue Socket::ResolutionError => e
+ * if e.error_code == Socket::EAI_AGAIN
+ * puts "Temporary failure in name resolution."
+ * end
+ * end
+ *
+ * Note that error codes depend on the operating system.
*/
static VALUE
sock_resolv_error_code(VALUE self)
@@ -799,7 +815,7 @@ rsock_init_socket_init(void)
*/
rb_eSocket = rb_define_class("SocketError", rb_eStandardError);
/*
- * ResolutionError is the error class for socket name resolution.
+ * Socket::ResolutionError is the error class for hostname resolution.
*/
rb_eResolution = rb_define_class_under(rb_cSocket, "ResolutionError", rb_eSocket);
rb_define_method(rb_eResolution, "error_code", sock_resolv_error_code, 0);
diff --git a/ext/socket/ipsocket.c b/ext/socket/ipsocket.c
index 0c13620258..931a1a629c 100644
--- a/ext/socket/ipsocket.c
+++ b/ext/socket/ipsocket.c
@@ -9,20 +9,39 @@
************************************************/
#include "rubysocket.h"
+#include <stdio.h>
struct inetsock_arg
{
- VALUE sock;
+ VALUE self;
+ VALUE io;
+
struct {
VALUE host, serv;
struct rb_addrinfo *res;
} remote, local;
int type;
- int fd;
VALUE resolv_timeout;
VALUE connect_timeout;
+ VALUE open_timeout;
};
+void
+rsock_raise_user_specified_timeout(struct addrinfo *ai, VALUE host, VALUE port)
+{
+ VALUE message;
+
+ if (ai && ai->ai_addr) {
+ VALUE rai = rsock_addrinfo_new((struct sockaddr *)ai->ai_addr, (socklen_t)ai->ai_addrlen, PF_UNSPEC, 0, 0, Qnil, Qnil);
+ VALUE addr_str = rsock_addrinfo_inspect_sockaddr(rai);
+ message = rb_sprintf("user specified timeout for %" PRIsVALUE, addr_str);
+ } else {
+ message = rb_sprintf("user specified timeout for %" PRIsVALUE " port %" PRIsVALUE, host, port);
+ }
+
+ rb_raise(rb_eIOTimeoutError, "%" PRIsVALUE, message);
+}
+
static VALUE
inetsock_cleanup(VALUE v)
{
@@ -35,35 +54,42 @@ inetsock_cleanup(VALUE v)
rb_freeaddrinfo(arg->local.res);
arg->local.res = 0;
}
- if (arg->fd >= 0) {
- close(arg->fd);
+ if (arg->io != Qnil) {
+ rb_io_close(arg->io);
+ arg->io = Qnil;
}
return Qnil;
}
static VALUE
+current_clocktime(void)
+{
+ VALUE clock_monotnic_const = rb_const_get(rb_mProcess, rb_intern("CLOCK_MONOTONIC"));
+ return rb_funcall(rb_mProcess, rb_intern("clock_gettime"), 1, clock_monotnic_const);
+}
+
+static VALUE
init_inetsock_internal(VALUE v)
{
struct inetsock_arg *arg = (void *)v;
int error = 0;
int type = arg->type;
struct addrinfo *res, *lres;
- int fd, status = 0, local = 0;
+ int status = 0, local = 0;
int family = AF_UNSPEC;
const char *syscall = 0;
+ VALUE resolv_timeout = arg->resolv_timeout;
VALUE connect_timeout = arg->connect_timeout;
- struct timeval tv_storage;
- struct timeval *tv = NULL;
+ VALUE open_timeout = arg->open_timeout;
+ VALUE timeout;
+ VALUE starts_at;
- if (!NIL_P(connect_timeout)) {
- tv_storage = rb_time_interval(connect_timeout);
- tv = &tv_storage;
- }
+ timeout = NIL_P(open_timeout) ? resolv_timeout : open_timeout;
+ starts_at = current_clocktime();
arg->remote.res = rsock_addrinfo(arg->remote.host, arg->remote.serv,
family, SOCK_STREAM,
- (type == INET_SERVER) ? AI_PASSIVE : 0);
-
+ (type == INET_SERVER) ? AI_PASSIVE : 0, timeout);
/*
* Maybe also accept a local address
@@ -71,10 +97,11 @@ init_inetsock_internal(VALUE v)
if (type != INET_SERVER && (!NIL_P(arg->local.host) || !NIL_P(arg->local.serv))) {
arg->local.res = rsock_addrinfo(arg->local.host, arg->local.serv,
- family, SOCK_STREAM, 0);
+ family, SOCK_STREAM, 0, timeout);
}
- arg->fd = fd = -1;
+ VALUE io = Qnil;
+
for (res = arg->remote.res->ai; res; res = res->ai_next) {
#if !defined(INET6) && defined(AF_INET6)
if (res->ai_family == AF_INET6)
@@ -96,12 +123,14 @@ init_inetsock_internal(VALUE v)
}
status = rsock_socket(res->ai_family,res->ai_socktype,res->ai_protocol);
syscall = "socket(2)";
- fd = status;
- if (fd < 0) {
+ if (status < 0) {
error = errno;
continue;
}
- arg->fd = fd;
+
+ int fd = status;
+ io = arg->io = rsock_init_sock(arg->self, fd);
+
if (type == INET_SERVER) {
#if !defined(_WIN32) && !defined(__CYGWIN__)
status = 1;
@@ -123,21 +152,33 @@ init_inetsock_internal(VALUE v)
syscall = "bind(2)";
}
+ if (NIL_P(open_timeout)) {
+ timeout = connect_timeout;
+ } else {
+ VALUE elapsed = rb_funcall(current_clocktime(), '-', 1, starts_at);
+ timeout = rb_funcall(open_timeout, '-', 1, elapsed);
+ if (rb_funcall(timeout, '<', 1, INT2FIX(0)) == Qtrue) {
+ rsock_raise_user_specified_timeout(res, arg->remote.host, arg->remote.serv);
+ }
+ }
+
if (status >= 0) {
- status = rsock_connect(fd, res->ai_addr, res->ai_addrlen,
- (type == INET_SOCKS), tv);
+ status = rsock_connect(io, res->ai_addr, res->ai_addrlen, (type == INET_SOCKS), timeout);
syscall = "connect(2)";
}
}
if (status < 0) {
error = errno;
- close(fd);
- arg->fd = fd = -1;
+ arg->io = Qnil;
+ rb_io_close(io);
+ io = Qnil;
continue;
- } else
+ } else {
break;
+ }
}
+
if (status < 0) {
VALUE host, port;
@@ -152,28 +193,38 @@ init_inetsock_internal(VALUE v)
rsock_syserr_fail_host_port(error, syscall, host, port);
}
- arg->fd = -1;
+ // Don't close the socket in `inetsock_cleanup` if we are returning it:
+ arg->io = Qnil;
- if (type == INET_SERVER) {
- status = listen(fd, SOMAXCONN);
+ if (type == INET_SERVER && io != Qnil) {
+ status = listen(rb_io_descriptor(io), SOMAXCONN);
if (status < 0) {
error = errno;
- close(fd);
+ rb_io_close(io);
rb_syserr_fail(error, "listen(2)");
}
}
/* create new instance */
- return rsock_init_sock(arg->sock, fd);
+ return io;
}
+#if FAST_FALLBACK_INIT_INETSOCK_IMPL == 0
+
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)
+rsock_init_inetsock(
+ VALUE self, VALUE remote_host, VALUE remote_serv,
+ VALUE local_host, VALUE local_serv, int type,
+ VALUE resolv_timeout, VALUE connect_timeout, VALUE open_timeout,
+ VALUE _fast_fallback, VALUE _test_mode_settings)
{
+ if (!NIL_P(open_timeout) && (!NIL_P(resolv_timeout) || !NIL_P(connect_timeout))) {
+ rb_raise(rb_eArgError, "Cannot specify open_timeout along with connect_timeout or resolv_timeout");
+ }
+
struct inetsock_arg arg;
- arg.sock = sock;
+ arg.self = self;
+ arg.io = Qnil;
arg.remote.host = remote_host;
arg.remote.serv = remote_serv;
arg.remote.res = 0;
@@ -181,13 +232,1205 @@ rsock_init_inetsock(VALUE sock, VALUE remote_host, VALUE remote_serv,
arg.local.serv = local_serv;
arg.local.res = 0;
arg.type = type;
- arg.fd = -1;
arg.resolv_timeout = resolv_timeout;
arg.connect_timeout = connect_timeout;
+ arg.open_timeout = open_timeout;
return rb_ensure(init_inetsock_internal, (VALUE)&arg,
inetsock_cleanup, (VALUE)&arg);
}
+#elif FAST_FALLBACK_INIT_INETSOCK_IMPL == 1
+
+#define IPV6_ENTRY_POS 0
+#define IPV4_ENTRY_POS 1
+#define RESOLUTION_ERROR 0
+#define SYSCALL_ERROR 1
+
+static int
+is_specified_ip_address(const char *hostname)
+{
+ if (!hostname) return false;
+
+ struct in_addr ipv4addr;
+ struct in6_addr ipv6addr;
+
+ return (inet_pton(AF_INET6, hostname, &ipv6addr) == 1 ||
+ inet_pton(AF_INET, hostname, &ipv4addr) == 1);
+}
+
+static int
+is_local_port_fixed(const char *portp)
+{
+ if (!portp) return 0;
+
+ char *endp;
+ errno = 0;
+ long port = strtol(portp, &endp, 10);
+
+ if (endp == portp) return 0;
+ if (errno == ERANGE) return 0;
+
+ return port > 0;
+}
+
+struct fast_fallback_inetsock_arg
+{
+ VALUE self;
+ VALUE io;
+
+ struct {
+ VALUE host, serv;
+ struct rb_addrinfo *res;
+ } remote, local;
+ int type;
+ VALUE resolv_timeout;
+ VALUE connect_timeout;
+ VALUE open_timeout;
+
+ const char *hostp, *portp;
+ int *families;
+ int family_size;
+ int additional_flags;
+ struct fast_fallback_getaddrinfo_entry *getaddrinfo_entries[2];
+ struct fast_fallback_getaddrinfo_shared *getaddrinfo_shared;
+ rb_fdset_t readfds, writefds;
+ int wait;
+ int connection_attempt_fds_size;
+ int *connection_attempt_fds;
+ VALUE test_mode_settings;
+};
+
+static struct fast_fallback_getaddrinfo_shared *
+allocate_fast_fallback_getaddrinfo_shared(int family_size)
+{
+ struct fast_fallback_getaddrinfo_shared *shared;
+
+ shared = (struct fast_fallback_getaddrinfo_shared *)calloc(
+ 1,
+ sizeof(struct fast_fallback_getaddrinfo_shared) + (family_size == 1 ? 0 : 2) * sizeof(struct fast_fallback_getaddrinfo_entry)
+ );
+
+ return shared;
+}
+
+static void
+allocate_fast_fallback_getaddrinfo_hints(struct addrinfo *hints, int family, int remote_addrinfo_hints, int additional_flags)
+{
+ MEMZERO(hints, struct addrinfo, 1);
+ hints->ai_family = family;
+ hints->ai_socktype = SOCK_STREAM;
+ hints->ai_protocol = IPPROTO_TCP;
+ hints->ai_flags = remote_addrinfo_hints;
+ hints->ai_flags |= additional_flags;
+}
+
+static int*
+allocate_connection_attempt_fds(int additional_capacity)
+{
+ int *fds = (int *)malloc(additional_capacity * sizeof(int));
+ if (!fds) rb_syserr_fail(errno, "malloc(3)");
+ for (int i = 0; i < additional_capacity; i++) fds[i] = -1;
+ return fds;
+}
+
+static int
+reallocate_connection_attempt_fds(int **fds, int current_capacity, int additional_capacity)
+{
+ int new_capacity = current_capacity + additional_capacity;
+ int *new_fds;
+
+ new_fds = realloc(*fds, new_capacity * sizeof(int));
+ if (new_fds == NULL) {
+ rb_syserr_fail(errno, "realloc(3)");
+ }
+ *fds = new_fds;
+
+ for (int i = current_capacity; i < new_capacity; i++) (*fds)[i] = -1;
+ return new_capacity;
+}
+
+struct hostname_resolution_result
+{
+ struct addrinfo *ai;
+ int finished;
+ int has_error;
+};
+
+struct hostname_resolution_store
+{
+ struct hostname_resolution_result v6;
+ struct hostname_resolution_result v4;
+ int is_all_finished;
+};
+
+static int
+any_addrinfos(struct hostname_resolution_store *resolution_store)
+{
+ return resolution_store->v6.ai || resolution_store->v4.ai;
+}
+
+static struct timespec
+current_clocktime_ts(void)
+{
+ struct timespec ts;
+ if ((clock_gettime(CLOCK_MONOTONIC, &ts)) < 0) {
+ rb_syserr_fail(errno, "clock_gettime(2)");
+ }
+ return ts;
+}
+
+static void
+set_timeout_tv(struct timeval *tv, long ms, struct timespec from)
+{
+ long sec = ms / 1000;
+ long nsec = (ms % 1000) * 1000000;
+ long result_sec = from.tv_sec + sec;
+ long result_nsec = from.tv_nsec + nsec;
+
+ result_sec += result_nsec / 1000000000;
+ result_nsec = result_nsec % 1000000000;
+
+ tv->tv_sec = result_sec;
+ tv->tv_usec = (int)(result_nsec / 1000);
+}
+
+static struct timeval
+add_ts_to_tv(struct timeval tv, struct timespec ts)
+{
+ long ts_usec = ts.tv_nsec / 1000;
+ tv.tv_sec += ts.tv_sec;
+ tv.tv_usec += ts_usec;
+
+ if (tv.tv_usec >= 1000000) {
+ tv.tv_sec += tv.tv_usec / 1000000;
+ tv.tv_usec = tv.tv_usec % 1000000;
+ }
+
+ return tv;
+}
+
+static VALUE
+tv_to_seconds(struct timeval *timeout) {
+ if (timeout == NULL) return Qnil;
+
+ double seconds = (double)timeout->tv_sec + (double)timeout->tv_usec / 1000000.0;
+
+ return DBL2NUM(seconds);
+}
+
+static int
+is_infinity(struct timeval tv)
+{
+ // { -1, -1 } as infinity
+ return tv.tv_sec == -1 || tv.tv_usec == -1;
+}
+
+static int
+is_timeout_tv(struct timeval *timeout_tv, struct timespec now) {
+ if (!timeout_tv) return false;
+ if (timeout_tv->tv_sec == -1 && timeout_tv->tv_usec == -1) return false;
+
+ struct timespec ts;
+ ts.tv_sec = timeout_tv->tv_sec;
+ ts.tv_nsec = timeout_tv->tv_usec * 1000;
+
+ if (now.tv_sec > ts.tv_sec) return true;
+ if (now.tv_sec == ts.tv_sec && now.tv_nsec >= ts.tv_nsec) return true;
+ return false;
+}
+
+static struct timeval *
+select_expires_at(
+ struct hostname_resolution_store *resolution_store,
+ struct timeval *resolution_delay,
+ struct timeval *connection_attempt_delay,
+ struct timeval *user_specified_resolv_timeout_at,
+ struct timeval *user_specified_connect_timeout_at,
+ struct timeval *user_specified_open_timeout_at)
+{
+ if (any_addrinfos(resolution_store)) {
+ struct timeval *delay;
+ delay = resolution_delay ? resolution_delay : connection_attempt_delay;
+
+ if (user_specified_open_timeout_at &&
+ timercmp(user_specified_open_timeout_at, delay, <)) {
+ return user_specified_open_timeout_at;
+ }
+ return delay;
+ }
+
+ if (user_specified_open_timeout_at) return user_specified_open_timeout_at;
+
+ struct timeval *timeout = NULL;
+
+ if (user_specified_resolv_timeout_at) {
+ if (is_infinity(*user_specified_resolv_timeout_at)) return NULL;
+ timeout = user_specified_resolv_timeout_at;
+ }
+
+ if (user_specified_connect_timeout_at) {
+ if (is_infinity(*user_specified_connect_timeout_at)) return NULL;
+ if (!timeout || timercmp(user_specified_connect_timeout_at, timeout, >)) {
+ return user_specified_connect_timeout_at;
+ }
+ }
+
+ return timeout;
+}
+
+static struct timeval
+tv_to_timeout(struct timeval *ends_at, struct timespec now)
+{
+ struct timeval delay;
+ struct timespec expires_at;
+ expires_at.tv_sec = ends_at->tv_sec;
+ expires_at.tv_nsec = ends_at->tv_usec * 1000;
+
+ struct timespec diff;
+ diff.tv_sec = expires_at.tv_sec - now.tv_sec;
+
+ if (expires_at.tv_nsec >= now.tv_nsec) {
+ diff.tv_nsec = expires_at.tv_nsec - now.tv_nsec;
+ } else {
+ diff.tv_sec -= 1;
+ diff.tv_nsec = (1000000000 + expires_at.tv_nsec) - now.tv_nsec;
+ }
+
+ delay.tv_sec = diff.tv_sec;
+ delay.tv_usec = (int)diff.tv_nsec / 1000;
+
+ return delay;
+}
+
+static struct addrinfo *
+pick_addrinfo(struct hostname_resolution_store *resolution_store, int last_family)
+{
+ int priority_on_v6[2] = { AF_INET6, AF_INET };
+ int priority_on_v4[2] = { AF_INET, AF_INET6 };
+ int *precedences = last_family == AF_INET6 ? priority_on_v4 : priority_on_v6;
+ struct addrinfo *selected_ai = NULL;
+
+ for (int i = 0; i < 2; i++) {
+ if (precedences[i] == AF_INET6) {
+ selected_ai = resolution_store->v6.ai;
+ if (selected_ai) {
+ resolution_store->v6.ai = selected_ai->ai_next;
+ break;
+ }
+ } else {
+ selected_ai = resolution_store->v4.ai;
+ if (selected_ai) {
+ resolution_store->v4.ai = selected_ai->ai_next;
+ break;
+ }
+ }
+ }
+ return selected_ai;
+}
+
+static void
+socket_nonblock_set(int fd)
+{
+ int flags = fcntl(fd, F_GETFL);
+
+ if (flags < 0) rb_syserr_fail(errno, "fcntl(2)");
+ if ((flags & O_NONBLOCK) != 0) return;
+
+ flags |= O_NONBLOCK;
+
+ if (fcntl(fd, F_SETFL, flags) < 0) rb_syserr_fail(errno, "fcntl(2)");
+ return;
+}
+
+static int
+in_progress_fds(int fds_size)
+{
+ return fds_size > 0;
+}
+
+static void
+remove_connection_attempt_fd(int *fds, int *fds_size, int removing_fd)
+{
+ int i, j;
+
+ for (i = 0; i < *fds_size; i++) {
+ if (fds[i] != removing_fd) continue;
+
+ for (j = i; j < *fds_size - 1; j++) {
+ fds[j] = fds[j + 1];
+ }
+
+ (*fds_size)--;
+ fds[*fds_size] = -1;
+ break;
+ }
+}
+
+struct fast_fallback_error
+{
+ int type;
+ int ecode;
+};
+
+static VALUE
+init_fast_fallback_inetsock_internal(VALUE v)
+{
+ struct fast_fallback_inetsock_arg *arg = (void *)v;
+ VALUE io = arg->io;
+ VALUE resolv_timeout = arg->resolv_timeout;
+ VALUE connect_timeout = arg->connect_timeout;
+ VALUE open_timeout = arg->open_timeout;
+ VALUE test_mode_settings = arg->test_mode_settings;
+ struct addrinfo *remote_ai = NULL, *local_ai = NULL;
+ int connected_fd = -1, status = 0, local_status = 0;
+ int remote_addrinfo_hints = 0;
+ struct fast_fallback_error last_error = { 0, 0 };
+ const char *syscall = 0;
+ VALUE host, serv;
+
+ #ifdef HAVE_CONST_AI_ADDRCONFIG
+ remote_addrinfo_hints |= AI_ADDRCONFIG;
+ #endif
+
+ pthread_t threads[arg->family_size];
+ char resolved_type[2];
+ ssize_t resolved_type_size;
+ int hostname_resolution_waiter = -1, hostname_resolution_notifier = -1;
+ int pipefd[2];
+
+ int nfds = 0;
+ struct timeval *ends_at = NULL;
+ struct timeval delay = (struct timeval){ -1, -1 };
+ struct timeval *delay_p = NULL;
+
+ struct hostname_resolution_store resolution_store;
+ resolution_store.is_all_finished = false;
+ resolution_store.v6.ai = NULL;
+ resolution_store.v6.finished = false;
+ resolution_store.v6.has_error = false;
+ resolution_store.v4.ai = NULL;
+ resolution_store.v4.finished = false;
+ resolution_store.v4.has_error = false;
+
+ int last_family = 0;
+ int additional_capacity = 10;
+ int current_capacity = additional_capacity;
+ arg->connection_attempt_fds = allocate_connection_attempt_fds(additional_capacity);
+ arg->connection_attempt_fds_size = 0;
+
+ struct timeval resolution_delay_storage;
+ struct timeval *resolution_delay_expires_at = NULL;
+ struct timeval connection_attempt_delay_strage;
+ struct timeval *connection_attempt_delay_expires_at = NULL;
+ struct timeval user_specified_resolv_timeout_storage;
+ struct timeval *user_specified_resolv_timeout_at = NULL;
+ struct timeval user_specified_connect_timeout_storage;
+ struct timeval *user_specified_connect_timeout_at = NULL;
+ struct timeval user_specified_open_timeout_storage;
+ struct timeval *user_specified_open_timeout_at = NULL;
+ struct timespec now = current_clocktime_ts();
+ VALUE starts_at = current_clocktime();
+
+ if (!NIL_P(open_timeout)) {
+ struct timeval open_timeout_tv = rb_time_interval(open_timeout);
+ user_specified_open_timeout_storage = add_ts_to_tv(open_timeout_tv, now);
+ user_specified_open_timeout_at = &user_specified_open_timeout_storage;
+ }
+
+ /* start of hostname resolution */
+ if (arg->family_size == 1) {
+ arg->wait = -1;
+ arg->getaddrinfo_shared = NULL;
+
+ int family = arg->families[0];
+ VALUE t = NIL_P(open_timeout) ? resolv_timeout : open_timeout;
+
+ arg->remote.res = rsock_addrinfo(
+ arg->remote.host,
+ arg->remote.serv,
+ family,
+ SOCK_STREAM,
+ 0,
+ t
+ );
+
+ if (family == AF_INET6) {
+ resolution_store.v6.ai = arg->remote.res->ai;
+ resolution_store.v6.finished = true;
+ resolution_store.v4.finished = true;
+ } else if (family == AF_INET) {
+ resolution_store.v4.ai = arg->remote.res->ai;
+ resolution_store.v4.finished = true;
+ resolution_store.v6.finished = true;
+ }
+ resolution_store.is_all_finished = true;
+ } else {
+ if (pipe(pipefd) != 0) rb_syserr_fail(errno, "pipe(2)");
+ hostname_resolution_waiter = pipefd[0];
+ int waiter_flags = fcntl(hostname_resolution_waiter, F_GETFL, 0);
+ if (waiter_flags < 0) rb_syserr_fail(errno, "fcntl(2)");
+ if ((fcntl(hostname_resolution_waiter, F_SETFL, waiter_flags | O_NONBLOCK)) < 0) {
+ rb_syserr_fail(errno, "fcntl(2)");
+ }
+ arg->wait = hostname_resolution_waiter;
+ hostname_resolution_notifier = pipefd[1];
+
+ arg->getaddrinfo_shared = allocate_fast_fallback_getaddrinfo_shared(arg->family_size);
+ if (!arg->getaddrinfo_shared) rb_syserr_fail(errno, "calloc(3)");
+
+ rb_nativethread_lock_initialize(&arg->getaddrinfo_shared->lock);
+ arg->getaddrinfo_shared->notify = hostname_resolution_notifier;
+
+ arg->getaddrinfo_shared->node = arg->hostp ? ruby_strdup(arg->hostp) : NULL;
+ arg->getaddrinfo_shared->service = arg->portp ? ruby_strdup(arg->portp) : NULL;
+ arg->getaddrinfo_shared->refcount = arg->family_size + 1;
+
+ for (int i = 0; i < arg->family_size; i++) {
+ arg->getaddrinfo_entries[i] = &arg->getaddrinfo_shared->getaddrinfo_entries[i];
+ arg->getaddrinfo_entries[i]->shared = arg->getaddrinfo_shared;
+
+ struct addrinfo getaddrinfo_hints[arg->family_size];
+
+ allocate_fast_fallback_getaddrinfo_hints(
+ &getaddrinfo_hints[i],
+ arg->families[i],
+ remote_addrinfo_hints,
+ arg->additional_flags
+ );
+
+ arg->getaddrinfo_entries[i]->hints = getaddrinfo_hints[i];
+ arg->getaddrinfo_entries[i]->ai = NULL;
+ arg->getaddrinfo_entries[i]->family = arg->families[i];
+ arg->getaddrinfo_entries[i]->refcount = 2;
+ arg->getaddrinfo_entries[i]->has_syserr = false;
+ arg->getaddrinfo_entries[i]->test_sleep_ms = 0;
+ arg->getaddrinfo_entries[i]->test_ecode = 0;
+
+ /* for testing HEv2 */
+ if (!NIL_P(test_mode_settings) && RB_TYPE_P(test_mode_settings, T_HASH)) {
+ const char *family_sym = arg->families[i] == AF_INET6 ? "ipv6" : "ipv4";
+
+ VALUE test_delay_setting = rb_hash_aref(test_mode_settings, ID2SYM(rb_intern("delay")));
+ if (!NIL_P(test_delay_setting)) {
+ VALUE rb_test_delay_ms = rb_hash_aref(test_delay_setting, ID2SYM(rb_intern(family_sym)));
+ long test_delay_ms = NIL_P(rb_test_delay_ms) ? 0 : rb_test_delay_ms;
+ arg->getaddrinfo_entries[i]->test_sleep_ms = test_delay_ms;
+ }
+
+ VALUE test_error_setting = rb_hash_aref(test_mode_settings, ID2SYM(rb_intern("error")));
+ if (!NIL_P(test_error_setting)) {
+ VALUE rb_test_ecode = rb_hash_aref(test_error_setting, ID2SYM(rb_intern(family_sym)));
+ if (!NIL_P(rb_test_ecode)) {
+ arg->getaddrinfo_entries[i]->test_ecode = NUM2INT(rb_test_ecode);
+ }
+ }
+ }
+
+ if (raddrinfo_pthread_create(&threads[i], fork_safe_do_fast_fallback_getaddrinfo, arg->getaddrinfo_entries[i]) != 0) {
+ rsock_raise_resolution_error("getaddrinfo(3)", EAI_AGAIN);
+ }
+ }
+
+ if (NIL_P(resolv_timeout)) {
+ user_specified_resolv_timeout_storage = (struct timeval){ -1, -1 };
+ } else {
+ struct timeval resolv_timeout_tv = rb_time_interval(resolv_timeout);
+ user_specified_resolv_timeout_storage = add_ts_to_tv(resolv_timeout_tv, now);
+ }
+ user_specified_resolv_timeout_at = &user_specified_resolv_timeout_storage;
+ }
+
+ while (true) {
+ /* start of connection */
+ if (any_addrinfos(&resolution_store) &&
+ !resolution_delay_expires_at &&
+ !connection_attempt_delay_expires_at) {
+ while ((remote_ai = pick_addrinfo(&resolution_store, last_family))) {
+ int fd = -1;
+
+ #if !defined(INET6) && defined(AF_INET6)
+ if (remote_ai->ai_family == AF_INET6) {
+ if (any_addrinfos(&resolution_store)) continue;
+ if (!in_progress_fds(arg->connection_attempt_fds_size)) break;
+ if (resolution_store.is_all_finished) break;
+
+ if (local_status < 0) {
+ host = arg->local.host;
+ serv = arg->local.serv;
+ } else {
+ host = arg->remote.host;
+ serv = arg->remote.serv;
+ }
+ if (last_error.type == RESOLUTION_ERROR) {
+ rsock_raise_resolution_error(syscall, last_error.ecode);
+ } else {
+ rsock_syserr_fail_host_port(last_error.ecode, syscall, host, serv);
+ }
+ }
+ #endif
+
+ local_ai = NULL;
+
+ if (arg->local.res) {
+ for (local_ai = arg->local.res->ai; local_ai; local_ai = local_ai->ai_next) {
+ if (local_ai->ai_family == remote_ai->ai_family) break;
+ }
+ if (!local_ai) {
+ if (any_addrinfos(&resolution_store)) continue;
+ if (in_progress_fds(arg->connection_attempt_fds_size)) break;
+ if (!resolution_store.is_all_finished) break;
+
+ /* Use a different family local address if no choice, this
+ * will cause EAFNOSUPPORT. */
+ rsock_syserr_fail_host_port(EAFNOSUPPORT, syscall, arg->local.host, arg->local.serv);
+ }
+ }
+
+ status = rsock_socket(remote_ai->ai_family, remote_ai->ai_socktype, remote_ai->ai_protocol);
+ syscall = "socket(2)";
+
+ if (status < 0) {
+ last_error.type = SYSCALL_ERROR;
+ last_error.ecode = errno;
+
+ if (any_addrinfos(&resolution_store)) continue;
+ if (in_progress_fds(arg->connection_attempt_fds_size)) break;
+ if (!resolution_store.is_all_finished) break;
+
+ if (local_status < 0) {
+ host = arg->local.host;
+ serv = arg->local.serv;
+ } else {
+ host = arg->remote.host;
+ serv = arg->remote.serv;
+ }
+ if (last_error.type == RESOLUTION_ERROR) {
+ rsock_raise_resolution_error(syscall, last_error.ecode);
+ } else {
+ rsock_syserr_fail_host_port(last_error.ecode, syscall, host, serv);
+ }
+ }
+
+ fd = status;
+
+ if (local_ai) {
+ #if !defined(_WIN32) && !defined(__CYGWIN__)
+ status = 1;
+ if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&status, (socklen_t)sizeof(status))) < 0) {
+ rb_syserr_fail(errno, "setsockopt(2)");
+ }
+ #endif
+ status = bind(fd, local_ai->ai_addr, local_ai->ai_addrlen);
+ local_status = status;
+ syscall = "bind(2)";
+
+ if (status < 0) {
+ last_error.type = SYSCALL_ERROR;
+ last_error.ecode = errno;
+ close(fd);
+
+ if (any_addrinfos(&resolution_store)) continue;
+ if (in_progress_fds(arg->connection_attempt_fds_size)) break;
+ if (!resolution_store.is_all_finished) break;
+
+ if (local_status < 0) {
+ host = arg->local.host;
+ serv = arg->local.serv;
+ } else {
+ host = arg->remote.host;
+ serv = arg->remote.serv;
+ }
+ if (last_error.type == RESOLUTION_ERROR) {
+ rsock_raise_resolution_error(syscall, last_error.ecode);
+ } else {
+ rsock_syserr_fail_host_port(last_error.ecode, syscall, host, serv);
+ }
+ }
+ }
+
+ syscall = "connect(2)";
+
+ if (any_addrinfos(&resolution_store) ||
+ in_progress_fds(arg->connection_attempt_fds_size) ||
+ !resolution_store.is_all_finished) {
+ socket_nonblock_set(fd);
+ status = connect(fd, remote_ai->ai_addr, remote_ai->ai_addrlen);
+ last_family = remote_ai->ai_family;
+ } else {
+ VALUE timeout = Qnil;
+
+ if (!NIL_P(open_timeout)) {
+ VALUE elapsed = rb_funcall(current_clocktime(), '-', 1, starts_at);
+ timeout = rb_funcall(open_timeout, '-', 1, elapsed);
+
+ if (rb_funcall(timeout, '<', 1, INT2FIX(0)) == Qtrue) {
+ rsock_raise_user_specified_timeout(NULL, arg->remote.host, arg->remote.serv);
+ }
+ }
+ if (NIL_P(timeout)) {
+ if (!NIL_P(connect_timeout)) {
+ user_specified_connect_timeout_storage = rb_time_interval(connect_timeout);
+ user_specified_connect_timeout_at = &user_specified_connect_timeout_storage;
+ }
+ timeout =
+ (user_specified_connect_timeout_at && is_infinity(*user_specified_connect_timeout_at)) ?
+ Qnil : tv_to_seconds(user_specified_connect_timeout_at);
+ }
+
+ io = arg->io = rsock_init_sock(arg->self, fd);
+ status = rsock_connect(io, remote_ai->ai_addr, remote_ai->ai_addrlen, 0, timeout);
+ }
+
+ if (status == 0) {
+ connected_fd = fd;
+ break;
+ }
+
+ if (errno == EINPROGRESS) {
+ if (current_capacity == arg->connection_attempt_fds_size) {
+ current_capacity = reallocate_connection_attempt_fds(
+ &arg->connection_attempt_fds,
+ current_capacity,
+ additional_capacity
+ );
+ }
+ arg->connection_attempt_fds[arg->connection_attempt_fds_size] = fd;
+ (arg->connection_attempt_fds_size)++;
+
+ set_timeout_tv(&connection_attempt_delay_strage, 250, now);
+ connection_attempt_delay_expires_at = &connection_attempt_delay_strage;
+
+ if (!any_addrinfos(&resolution_store)) {
+ if (NIL_P(connect_timeout)) {
+ user_specified_connect_timeout_storage = (struct timeval){ -1, -1 };
+ } else {
+ struct timeval connect_timeout_tv = rb_time_interval(connect_timeout);
+ user_specified_connect_timeout_storage = add_ts_to_tv(connect_timeout_tv, now);
+ }
+ user_specified_connect_timeout_at = &user_specified_connect_timeout_storage;
+ }
+
+ break;
+ }
+
+ last_error.type = SYSCALL_ERROR;
+ last_error.ecode = errno;
+
+ if (NIL_P(io)) {
+ close(fd);
+ } else {
+ rb_io_close(io);
+ }
+
+ if (any_addrinfos(&resolution_store)) continue;
+ if (in_progress_fds(arg->connection_attempt_fds_size)) break;
+ if (!resolution_store.is_all_finished) break;
+
+ if (local_status < 0) {
+ host = arg->local.host;
+ serv = arg->local.serv;
+ } else {
+ host = arg->remote.host;
+ serv = arg->remote.serv;
+ }
+ if (last_error.type == RESOLUTION_ERROR) {
+ rsock_raise_resolution_error(syscall, last_error.ecode);
+ } else {
+ rsock_syserr_fail_host_port(last_error.ecode, syscall, host, serv);
+ }
+ }
+ }
+
+ if (connected_fd >= 0) break;
+
+ ends_at = select_expires_at(
+ &resolution_store,
+ resolution_delay_expires_at,
+ connection_attempt_delay_expires_at,
+ user_specified_resolv_timeout_at,
+ user_specified_connect_timeout_at,
+ user_specified_open_timeout_at
+ );
+ if (ends_at) {
+ delay = tv_to_timeout(ends_at, now);
+ delay_p = &delay;
+ } else {
+ if (((resolution_store.v6.finished && !resolution_store.v4.finished) ||
+ (resolution_store.v4.finished && !resolution_store.v6.finished)) &&
+ !any_addrinfos(&resolution_store) &&
+ !in_progress_fds(arg->connection_attempt_fds_size)) {
+ /* A limited timeout is introduced to prevent select(2) from hanging when it is exclusively
+ * waiting for name resolution and write(2) failure occurs in a child thread. */
+ delay.tv_sec = 0;
+ delay.tv_usec = 50000;
+ delay_p = &delay;
+ } else {
+ delay_p = NULL;
+ }
+ }
+
+ nfds = 0;
+ rb_fd_zero(&arg->writefds);
+ if (in_progress_fds(arg->connection_attempt_fds_size)) {
+ int n = 0;
+ for (int i = 0; i < arg->connection_attempt_fds_size; i++) {
+ int cfd = arg->connection_attempt_fds[i];
+ if (cfd < 0) continue;
+ if (cfd > n) n = cfd;
+ rb_fd_set(cfd, &arg->writefds);
+ }
+ if (n > 0) n++;
+ nfds = n;
+ }
+
+ rb_fd_zero(&arg->readfds);
+ if (arg->family_size > 1) {
+ rb_fd_set(hostname_resolution_waiter, &arg->readfds);
+
+ if ((hostname_resolution_waiter + 1) > nfds) {
+ nfds = hostname_resolution_waiter + 1;
+ }
+ }
+
+ status = rb_thread_fd_select(nfds, &arg->readfds, &arg->writefds, NULL, delay_p);
+
+ now = current_clocktime_ts();
+ if (is_timeout_tv(resolution_delay_expires_at, now)) {
+ resolution_delay_expires_at = NULL;
+ }
+ if (is_timeout_tv(connection_attempt_delay_expires_at, now)) {
+ connection_attempt_delay_expires_at = NULL;
+ }
+
+ if (status < 0 && (errno && errno != EINTR)) rb_syserr_fail(errno, "select(2)");
+
+ if (status > 0) {
+ /* check for connection */
+ if (in_progress_fds(arg->connection_attempt_fds_size)) {
+ for (int i = 0; i < arg->connection_attempt_fds_size; i++) {
+ int fd = arg->connection_attempt_fds[i];
+ if (fd < 0 || !rb_fd_isset(fd, &arg->writefds)) continue;
+
+ int err;
+ socklen_t len = sizeof(err);
+
+ status = getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &len);
+
+ if (status < 0) {
+ last_error.type = SYSCALL_ERROR;
+ last_error.ecode = errno;
+ close(fd);
+
+ if (any_addrinfos(&resolution_store)) continue;
+ if (in_progress_fds(arg->connection_attempt_fds_size)) break;
+ if (!resolution_store.is_all_finished) break;
+
+ if (local_status < 0) {
+ host = arg->local.host;
+ serv = arg->local.serv;
+ } else {
+ host = arg->remote.host;
+ serv = arg->remote.serv;
+ }
+ if (last_error.type == RESOLUTION_ERROR) {
+ rsock_raise_resolution_error(syscall, last_error.ecode);
+ } else {
+ rsock_syserr_fail_host_port(last_error.ecode, syscall, host, serv);
+ }
+ }
+
+ if (err == 0) { /* success */
+ remove_connection_attempt_fd(
+ arg->connection_attempt_fds,
+ &arg->connection_attempt_fds_size,
+ fd
+ );
+ connected_fd = fd;
+ break;
+ } else { /* fail */
+ close(fd);
+ remove_connection_attempt_fd(
+ arg->connection_attempt_fds,
+ &arg->connection_attempt_fds_size,
+ fd
+ );
+ last_error.type = SYSCALL_ERROR;
+ last_error.ecode = err;
+ }
+ }
+
+ if (connected_fd >= 0) break;
+
+ if (!in_progress_fds(arg->connection_attempt_fds_size)) {
+ if (!any_addrinfos(&resolution_store) && resolution_store.is_all_finished) {
+ if (local_status < 0) {
+ host = arg->local.host;
+ serv = arg->local.serv;
+ } else {
+ host = arg->remote.host;
+ serv = arg->remote.serv;
+ }
+ if (last_error.type == RESOLUTION_ERROR) {
+ rsock_raise_resolution_error(syscall, last_error.ecode);
+ } else {
+ rsock_syserr_fail_host_port(last_error.ecode, syscall, host, serv);
+ }
+ }
+ connection_attempt_delay_expires_at = NULL;
+ user_specified_connect_timeout_at = NULL;
+ }
+ }
+
+ /* check for hostname resolution */
+ if (!resolution_store.is_all_finished && rb_fd_isset(hostname_resolution_waiter, &arg->readfds)) {
+ while (true) {
+ resolved_type_size = read(
+ hostname_resolution_waiter,
+ resolved_type,
+ sizeof(resolved_type) - 1
+ );
+
+ if (resolved_type_size > 0) {
+ resolved_type[resolved_type_size] = '\0';
+
+ if (resolved_type[0] == IPV6_HOSTNAME_RESOLVED) {
+ resolution_store.v6.finished = true;
+
+ if (arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err &&
+ arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err != EAI_ADDRFAMILY) {
+ if (!resolution_store.v4.finished || resolution_store.v4.has_error) {
+ last_error.type = RESOLUTION_ERROR;
+ last_error.ecode = arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err;
+ syscall = "getaddrinfo(3)";
+ }
+ resolution_store.v6.has_error = true;
+ } else {
+ resolution_store.v6.ai = arg->getaddrinfo_entries[IPV6_ENTRY_POS]->ai;
+ }
+ if (resolution_store.v4.finished) {
+ resolution_store.is_all_finished = true;
+ resolution_delay_expires_at = NULL;
+ user_specified_resolv_timeout_at = NULL;
+ break;
+ }
+ } else if (resolved_type[0] == IPV4_HOSTNAME_RESOLVED) {
+ resolution_store.v4.finished = true;
+
+ if (arg->getaddrinfo_entries[IPV4_ENTRY_POS]->err) {
+ if (!resolution_store.v6.finished || resolution_store.v6.has_error) {
+ last_error.type = RESOLUTION_ERROR;
+ last_error.ecode = arg->getaddrinfo_entries[IPV4_ENTRY_POS]->err;
+ syscall = "getaddrinfo(3)";
+ }
+ resolution_store.v4.has_error = true;
+ } else {
+ resolution_store.v4.ai = arg->getaddrinfo_entries[IPV4_ENTRY_POS]->ai;
+ }
+
+ if (resolution_store.v6.finished) {
+ resolution_store.is_all_finished = true;
+ resolution_delay_expires_at = NULL;
+ user_specified_resolv_timeout_at = NULL;
+ break;
+ }
+ } else {
+ /* Retry to read from hostname_resolution_waiter */
+ }
+ } else if (resolved_type_size < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
+ errno = 0;
+ break;
+ } else {
+ /* Retry to read from hostname_resolution_waiter */
+ }
+
+ if (!resolution_store.v6.finished &&
+ resolution_store.v4.finished &&
+ !resolution_store.v4.has_error) {
+ set_timeout_tv(&resolution_delay_storage, 50, now);
+ resolution_delay_expires_at = &resolution_delay_storage;
+ }
+ }
+ }
+
+ status = 0;
+ }
+
+ /* For cases where write(2) fails in child threads */
+ if (!resolution_store.is_all_finished) {
+ if (!resolution_store.v6.finished && arg->getaddrinfo_entries[IPV6_ENTRY_POS]->has_syserr) {
+ resolution_store.v6.finished = true;
+
+ if (arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err) {
+ if (!resolution_store.v4.finished || resolution_store.v4.has_error) {
+ last_error.type = RESOLUTION_ERROR;
+ last_error.ecode = arg->getaddrinfo_entries[IPV6_ENTRY_POS]->err;
+ syscall = "getaddrinfo(3)";
+ }
+ resolution_store.v6.has_error = true;
+ } else {
+ resolution_store.v6.ai = arg->getaddrinfo_entries[IPV6_ENTRY_POS]->ai;
+ }
+
+ if (resolution_store.v4.finished) {
+ resolution_store.is_all_finished = true;
+ resolution_delay_expires_at = NULL;
+ user_specified_resolv_timeout_at = NULL;
+ }
+ }
+ if (!resolution_store.v4.finished && arg->getaddrinfo_entries[IPV4_ENTRY_POS]->has_syserr) {
+ resolution_store.v4.finished = true;
+
+ if (arg->getaddrinfo_entries[IPV4_ENTRY_POS]->err) {
+ if (!resolution_store.v6.finished || resolution_store.v6.has_error) {
+ last_error.type = RESOLUTION_ERROR;
+ last_error.ecode = arg->getaddrinfo_entries[IPV4_ENTRY_POS]->err;
+ syscall = "getaddrinfo(3)";
+ }
+ resolution_store.v4.has_error = true;
+ } else {
+ resolution_store.v4.ai = arg->getaddrinfo_entries[IPV4_ENTRY_POS]->ai;
+ }
+
+ if (resolution_store.v6.finished) {
+ resolution_store.is_all_finished = true;
+ resolution_delay_expires_at = NULL;
+ user_specified_resolv_timeout_at = NULL;
+ } else {
+ set_timeout_tv(&resolution_delay_storage, 50, now);
+ resolution_delay_expires_at = &resolution_delay_storage;
+ }
+ }
+ }
+
+ if (is_timeout_tv(user_specified_open_timeout_at, now)) {
+ rsock_raise_user_specified_timeout(NULL, arg->remote.host, arg->remote.serv);
+ }
+
+ if (!any_addrinfos(&resolution_store)) {
+ if (!in_progress_fds(arg->connection_attempt_fds_size) &&
+ resolution_store.is_all_finished) {
+ if (local_status < 0) {
+ host = arg->local.host;
+ serv = arg->local.serv;
+ } else {
+ host = arg->remote.host;
+ serv = arg->remote.serv;
+ }
+ if (last_error.type == RESOLUTION_ERROR) {
+ rsock_raise_resolution_error(syscall, last_error.ecode);
+ } else {
+ rsock_syserr_fail_host_port(last_error.ecode, syscall, host, serv);
+ }
+ }
+
+ if ((is_timeout_tv(user_specified_resolv_timeout_at, now) ||
+ resolution_store.is_all_finished) &&
+ (is_timeout_tv(user_specified_connect_timeout_at, now) ||
+ !in_progress_fds(arg->connection_attempt_fds_size))) {
+ rsock_raise_user_specified_timeout(NULL, arg->remote.host, arg->remote.serv);
+ }
+ }
+ }
+
+ if (NIL_P(arg->io)) {
+ /* create new instance */
+ arg->io = rsock_init_sock(arg->self, connected_fd);
+ }
+
+ return arg->io;
+}
+
+static VALUE
+fast_fallback_inetsock_cleanup(VALUE v)
+{
+ struct fast_fallback_inetsock_arg *arg = (void *)v;
+ struct fast_fallback_getaddrinfo_shared *getaddrinfo_shared = arg->getaddrinfo_shared;
+
+ if (arg->remote.res) {
+ rb_freeaddrinfo(arg->remote.res);
+ arg->remote.res = 0;
+ }
+ if (arg->local.res) {
+ rb_freeaddrinfo(arg->local.res);
+ arg->local.res = 0;
+ }
+
+ if (arg->wait != -1) close(arg->wait);
+
+ if (getaddrinfo_shared) {
+ if (getaddrinfo_shared->notify != -1) close(getaddrinfo_shared->notify);
+ getaddrinfo_shared->notify = -1;
+
+ int shared_need_free = 0;
+ struct addrinfo *ais[arg->family_size];
+ for (int i = 0; i < arg->family_size; i++) ais[i] = NULL;
+
+ rb_nativethread_lock_lock(&getaddrinfo_shared->lock);
+ {
+ for (int i = 0; i < arg->family_size; i++) {
+ struct fast_fallback_getaddrinfo_entry *getaddrinfo_entry = arg->getaddrinfo_entries[i];
+
+ if (!getaddrinfo_entry) continue;
+
+ if (--(getaddrinfo_entry->refcount) == 0) {
+ ais[i] = getaddrinfo_entry->ai;
+ getaddrinfo_entry->ai = NULL;
+ }
+ }
+ if (--(getaddrinfo_shared->refcount) == 0) {
+ shared_need_free = 1;
+ }
+ }
+ rb_nativethread_lock_unlock(&getaddrinfo_shared->lock);
+
+ for (int i = 0; i < arg->family_size; i++) {
+ if (ais[i]) freeaddrinfo(ais[i]);
+ }
+ if (getaddrinfo_shared && shared_need_free) {
+ free_fast_fallback_getaddrinfo_shared(&getaddrinfo_shared);
+ }
+ }
+
+ int connection_attempt_fd;
+
+ for (int i = 0; i < arg->connection_attempt_fds_size; i++) {
+ connection_attempt_fd = arg->connection_attempt_fds[i];
+
+ if (connection_attempt_fd >= 0) {
+ int error = 0;
+ socklen_t len = sizeof(error);
+ getsockopt(connection_attempt_fd, SOL_SOCKET, SO_ERROR, &error, &len);
+ if (error == 0) shutdown(connection_attempt_fd, SHUT_RDWR);
+ close(connection_attempt_fd);
+ }
+ }
+
+ if (arg->readfds.fdset) rb_fd_term(&arg->readfds);
+ if (arg->writefds.fdset) rb_fd_term(&arg->writefds);
+
+ if (arg->connection_attempt_fds) {
+ free(arg->connection_attempt_fds);
+ arg->connection_attempt_fds = NULL;
+ }
+
+ return Qnil;
+}
+
+VALUE
+rsock_init_inetsock(
+ VALUE self, VALUE remote_host, VALUE remote_serv,
+ VALUE local_host, VALUE local_serv, int type,
+ VALUE resolv_timeout, VALUE connect_timeout, VALUE open_timeout,
+ VALUE fast_fallback, VALUE test_mode_settings)
+{
+ if (!NIL_P(open_timeout) && (!NIL_P(resolv_timeout) || !NIL_P(connect_timeout))) {
+ rb_raise(rb_eArgError, "Cannot specify open_timeout along with connect_timeout or resolv_timeout");
+ }
+
+ if (type == INET_CLIENT && FAST_FALLBACK_INIT_INETSOCK_IMPL == 1 && RTEST(fast_fallback)) {
+ struct rb_addrinfo *local_res = NULL;
+ char *hostp, *portp, *local_portp;
+ char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV], local_pbuf[NI_MAXSERV];
+ int additional_flags = 0;
+ int local_flags = 0;
+ hostp = raddrinfo_host_str(remote_host, hbuf, sizeof(hbuf), &additional_flags);
+ portp = raddrinfo_port_str(remote_serv, pbuf, sizeof(pbuf), &additional_flags);
+ local_portp = raddrinfo_port_str(local_serv, local_pbuf, sizeof(local_pbuf), &local_flags);
+
+ if (!is_specified_ip_address(hostp) && !is_local_port_fixed(local_portp)) {
+ int target_families[2] = { 0, 0 };
+ int resolving_family_size = 0;
+
+ /*
+ * Maybe also accept a local address
+ */
+ if (!NIL_P(local_host) || !NIL_P(local_serv)) {
+ VALUE t = NIL_P(open_timeout) ? resolv_timeout : open_timeout;
+ local_res = rsock_addrinfo(
+ local_host,
+ local_serv,
+ AF_UNSPEC,
+ SOCK_STREAM,
+ 0,
+ t
+ );
+
+ struct addrinfo *tmp_p = local_res->ai;
+ for (; tmp_p != NULL; tmp_p = tmp_p->ai_next) {
+ if (target_families[0] == 0 && tmp_p->ai_family == AF_INET6) {
+ target_families[0] = AF_INET6;
+ resolving_family_size++;
+ }
+ if (target_families[1] == 0 && tmp_p->ai_family == AF_INET) {
+ target_families[1] = AF_INET;
+ resolving_family_size++;
+ }
+ }
+ } else {
+ resolving_family_size = 2;
+ target_families[0] = AF_INET6;
+ target_families[1] = AF_INET;
+ }
+
+ struct fast_fallback_inetsock_arg fast_fallback_arg;
+ memset(&fast_fallback_arg, 0, sizeof(fast_fallback_arg));
+
+ fast_fallback_arg.self = self;
+ fast_fallback_arg.io = Qnil;
+ fast_fallback_arg.remote.host = remote_host;
+ fast_fallback_arg.remote.serv = remote_serv;
+ fast_fallback_arg.remote.res = 0;
+ fast_fallback_arg.local.host = local_host;
+ fast_fallback_arg.local.serv = local_serv;
+ fast_fallback_arg.local.res = local_res;
+ fast_fallback_arg.type = type;
+ fast_fallback_arg.resolv_timeout = resolv_timeout;
+ fast_fallback_arg.connect_timeout = connect_timeout;
+ fast_fallback_arg.open_timeout = open_timeout;
+ fast_fallback_arg.hostp = hostp;
+ fast_fallback_arg.portp = portp;
+ fast_fallback_arg.additional_flags = additional_flags;
+
+ int resolving_families[resolving_family_size];
+ int resolving_family_index = 0;
+ for (int i = 0; 2 > i; i++) {
+ if (target_families[i] != 0) {
+ resolving_families[resolving_family_index] = target_families[i];
+ resolving_family_index++;
+ }
+ }
+ fast_fallback_arg.families = resolving_families;
+ fast_fallback_arg.family_size = resolving_family_size;
+ fast_fallback_arg.test_mode_settings = test_mode_settings;
+
+ rb_fd_init(&fast_fallback_arg.readfds);
+ rb_fd_init(&fast_fallback_arg.writefds);
+
+ return rb_ensure(init_fast_fallback_inetsock_internal, (VALUE)&fast_fallback_arg,
+ fast_fallback_inetsock_cleanup, (VALUE)&fast_fallback_arg);
+ }
+ }
+
+ struct inetsock_arg arg;
+ arg.self = self;
+ arg.io = Qnil;
+ arg.remote.host = remote_host;
+ arg.remote.serv = remote_serv;
+ arg.remote.res = 0;
+ arg.local.host = local_host;
+ arg.local.serv = local_serv;
+ arg.local.res = 0;
+ arg.type = type;
+ arg.resolv_timeout = resolv_timeout;
+ arg.connect_timeout = connect_timeout;
+ arg.open_timeout = open_timeout;
+
+ return rb_ensure(init_inetsock_internal, (VALUE)&arg,
+ inetsock_cleanup, (VALUE)&arg);
+}
+
+#endif
+
static ID id_numeric, id_hostname;
int
@@ -274,16 +1517,13 @@ ip_inspect(VALUE sock)
static VALUE
ip_addr(int argc, VALUE *argv, VALUE sock)
{
- rb_io_t *fptr;
union_sockaddr addr;
socklen_t len = (socklen_t)sizeof addr;
int norevlookup;
- GetOpenFile(sock, fptr);
-
if (argc < 1 || !rsock_revlookup_flag(argv[0], &norevlookup))
- norevlookup = fptr->mode & FMODE_NOREVLOOKUP;
- if (getsockname(fptr->fd, &addr.addr, &len) < 0)
+ norevlookup = rb_io_mode(sock) & FMODE_NOREVLOOKUP;
+ if (getsockname(rb_io_descriptor(sock), &addr.addr, &len) < 0)
rb_sys_fail("getsockname(2)");
return rsock_ipaddr(&addr.addr, len, norevlookup);
}
@@ -315,16 +1555,13 @@ ip_addr(int argc, VALUE *argv, VALUE sock)
static VALUE
ip_peeraddr(int argc, VALUE *argv, VALUE sock)
{
- rb_io_t *fptr;
union_sockaddr addr;
socklen_t len = (socklen_t)sizeof addr;
int norevlookup;
- GetOpenFile(sock, fptr);
-
if (argc < 1 || !rsock_revlookup_flag(argv[0], &norevlookup))
- norevlookup = fptr->mode & FMODE_NOREVLOOKUP;
- if (getpeername(fptr->fd, &addr.addr, &len) < 0)
+ norevlookup = rb_io_mode(sock) & FMODE_NOREVLOOKUP;
+ if (getpeername(rb_io_descriptor(sock), &addr.addr, &len) < 0)
rb_sys_fail("getpeername(2)");
return rsock_ipaddr(&addr.addr, len, norevlookup);
}
@@ -372,7 +1609,7 @@ static VALUE
ip_s_getaddress(VALUE obj, VALUE host)
{
union_sockaddr addr;
- struct rb_addrinfo *res = rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, 0);
+ struct rb_addrinfo *res = rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, 0, Qnil);
socklen_t len = res->ai->ai_addrlen;
/* just take the first one */
diff --git a/ext/socket/lib/socket.rb b/ext/socket/lib/socket.rb
index e953077fe6..36fcceaee9 100644
--- a/ext/socket/lib/socket.rb
+++ b/ext/socket/lib/socket.rb
@@ -62,7 +62,7 @@ class Addrinfo
break
when :wait_writable
sock.wait_writable(timeout) or
- raise Errno::ETIMEDOUT, 'user specified timeout'
+ raise Errno::ETIMEDOUT, "user specified timeout for #{self.ip_address}:#{self.ip_port}"
end while true
else
sock.connect(self)
@@ -599,6 +599,7 @@ class Socket < BasicSocket
__accept_nonblock(exception)
end
+ # :stopdoc:
RESOLUTION_DELAY = 0.05
private_constant :RESOLUTION_DELAY
@@ -614,14 +615,9 @@ class Socket < BasicSocket
HOSTNAME_RESOLUTION_QUEUE_UPDATED = 0
private_constant :HOSTNAME_RESOLUTION_QUEUE_UPDATED
- IPV6_ADRESS_FORMAT = /(?i)(?:(?:[0-9A-F]{1,4}:){7}(?:[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){6}(?:[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,5}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){5}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,4}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){4}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,3}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){3}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,2}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){2}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:)[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){1}(?::[0-9A-F]{1,4}::[0-9A-F]{1,4}|::(?:[0-9A-F]{1,4}:){1,5}[0-9A-F]{1,4}|:)|::(?:[0-9A-F]{1,4}::[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,6}[0-9A-F]{1,4}|:))(?:%.+)?/
- private_constant :IPV6_ADRESS_FORMAT
-
- @tcp_fast_fallback = true
-
- class << self
- attr_accessor :tcp_fast_fallback
- end
+ IPV6_ADDRESS_FORMAT = /\A(?i:(?:(?:[0-9A-F]{1,4}:){7}(?:[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){6}(?:[0-9A-F]{1,4}|:(?:[0-9A-F]{1,4}:){1,5}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){5}(?:(?::[0-9A-F]{1,4}){1,2}|:(?:[0-9A-F]{1,4}:){1,4}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){4}(?:(?::[0-9A-F]{1,4}){1,3}|:(?:[0-9A-F]{1,4}:){1,3}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){3}(?:(?::[0-9A-F]{1,4}){1,4}|:(?:[0-9A-F]{1,4}:){1,2}[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){2}(?:(?::[0-9A-F]{1,4}){1,5}|:(?:[0-9A-F]{1,4}:)[0-9A-F]{1,4}|:)|(?:[0-9A-F]{1,4}:){1}(?:(?::[0-9A-F]{1,4}){1,6}|:(?:[0-9A-F]{1,4}:){0,5}[0-9A-F]{1,4}|:)|(?:::(?:[0-9A-F]{1,4}:){0,7}[0-9A-F]{1,4}|::)))(?:%.+)?\z/
+ private_constant :IPV6_ADDRESS_FORMAT
+ # :startdoc:
# :call-seq:
# Socket.tcp(host, port, local_host=nil, local_port=nil, [opts]) {|socket| ... }
@@ -629,13 +625,28 @@ class Socket < BasicSocket
#
# creates a new socket object connected to host:port using TCP/IP.
#
+ # Starting from Ruby 3.4, this method operates according to the
+ # Happy Eyeballs Version 2 ({RFC 8305}[https://datatracker.ietf.org/doc/html/rfc8305])
+ # algorithm by default.
+ #
+ # For details on Happy Eyeballs Version 2,
+ # see {Socket.tcp_fast_fallback=}[rdoc-ref:Socket.tcp_fast_fallback=].
+ #
+ # To make it behave the same as in Ruby 3.3 and earlier,
+ # explicitly specify the option fast_fallback:false.
+ # Or, setting Socket.tcp_fast_fallback=false will disable
+ # Happy Eyeballs Version 2 not only for this method but for all Socket globally.
+ #
# If local_host:local_port is given,
# the socket is bound to it.
#
# The optional last argument _opts_ is options represented by a hash.
# _opts_ may have following options:
#
- # [:connect_timeout] specify the timeout in seconds.
+ # [:resolv_timeout] Specifies the timeout in seconds from when the hostname resolution starts.
+ # [:connect_timeout] This method sequentially attempts connecting to all candidate destination addresses.<br>The +connect_timeout+ specifies the timeout in seconds from the start of the connection attempt to the last candidate.<br>By default, all connection attempts continue until the timeout occurs.<br>When +fast_fallback:false+ is explicitly specified,<br>a timeout is set for each connection attempt and any connection attempt that exceeds its timeout will be canceled.
+ # [:open_timeout] Specifies the timeout in seconds from the start of the method execution.<br>If this timeout is reached while there are still addresses that have not yet been attempted for connection, no further attempts will be made.<br>If this option is specified together with other timeout options, an +ArgumentError+ will be raised.
+ # [:fast_fallback] Enables the Happy Eyeballs Version 2 algorithm (enabled by default).
#
# If a block is given, the block is called with the socket.
# The value of the block is returned.
@@ -648,537 +659,472 @@ class Socket < BasicSocket
# sock.close_write
# puts sock.read
# }
- def self.tcp(host, port, local_host = nil, local_port = nil, connect_timeout: nil, resolv_timeout: nil, fast_fallback: tcp_fast_fallback, &block) # :yield: socket
- unless fast_fallback
- return tcp_without_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:, &block)
+ def self.tcp(host, port, local_host = nil, local_port = nil, connect_timeout: nil, resolv_timeout: nil, open_timeout: nil, fast_fallback: tcp_fast_fallback, &) # :yield: socket
+ if open_timeout && (connect_timeout || resolv_timeout)
+ raise ArgumentError, "Cannot specify open_timeout along with connect_timeout or resolv_timeout"
end
- # Happy Eyeballs' states
- # - :start
- # - :v6c
- # - :v4w
- # - :v4c
- # - :v46c
- # - :v46w
- # - :success
- # - :failure
- # - :timeout
-
- specified_family_name = nil
- hostname_resolution_threads = []
- hostname_resolution_queue = nil
- hostname_resolution_waiting = nil
- hostname_resolution_expires_at = nil
- selectable_addrinfos = SelectableAddrinfos.new
- connecting_sockets = ConnectingSockets.new
- local_addrinfos = []
- connection_attempt_delay_expires_at = nil
- connection_attempt_started_at = nil
- state = :start
- connected_socket = nil
- last_error = nil
- is_windows_environment ||= (RUBY_PLATFORM =~ /mswin|mingw|cygwin/)
+ sock = if fast_fallback && !(host && ip_address?(host)) && !(local_port && local_port.to_i != 0)
+ tcp_with_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:, open_timeout:)
+ else
+ tcp_without_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:, open_timeout:)
+ end
- ret = loop do
- case state
- when :start
- specified_family_name, next_state = host && specified_family_name_and_next_state(host)
+ if block_given?
+ begin
+ yield sock
+ ensure
+ sock.close
+ end
+ else
+ sock
+ end
+ end
- if local_host && local_port
- specified_family_name, next_state = specified_family_name_and_next_state(local_host) unless specified_family_name
- local_addrinfos = Addrinfo.getaddrinfo(local_host, local_port, ADDRESS_FAMILIES[specified_family_name], :STREAM, timeout: resolv_timeout)
- end
+ # :stopdoc:
+ def self.tcp_with_fast_fallback(host, port, local_host = nil, local_port = nil, connect_timeout: nil, resolv_timeout: nil, open_timeout: nil)
+ if local_host || local_port
+ local_addrinfos = Addrinfo.getaddrinfo(local_host, local_port, nil, :STREAM, timeout: open_timeout || resolv_timeout)
+ resolving_family_names = local_addrinfos.map { |lai| ADDRESS_FAMILIES.key(lai.afamily) }.uniq
+ else
+ local_addrinfos = []
+ resolving_family_names = ADDRESS_FAMILIES.keys
+ end
- if specified_family_name
- addrinfos = Addrinfo.getaddrinfo(host, port, ADDRESS_FAMILIES[specified_family_name], :STREAM, timeout: resolv_timeout)
- selectable_addrinfos.add(specified_family_name, addrinfos)
- hostname_resolution_queue = NoHostnameResolutionQueue.new
- state = next_state
- next
- end
+ hostname_resolution_threads = []
+ resolution_store = HostnameResolutionStore.new(resolving_family_names)
+ connecting_sockets = {}
+ is_windows_environment ||= (RUBY_PLATFORM =~ /mswin|mingw|cygwin/)
- resolving_family_names = ADDRESS_FAMILIES.keys
- hostname_resolution_queue = HostnameResolutionQueue.new(resolving_family_names.size)
- hostname_resolution_waiting = hostname_resolution_queue.waiting_pipe
- hostname_resolution_started_at = current_clocktime if resolv_timeout
- hostname_resolution_args = [host, port, hostname_resolution_queue]
-
- hostname_resolution_threads.concat(
- resolving_family_names.map { |family|
- thread_args = [family, *hostname_resolution_args]
- thread = Thread.new(*thread_args) { |*thread_args| hostname_resolution(*thread_args) }
- Thread.pass
- thread
- }
- )
-
- hostname_resolution_retry_count = resolving_family_names.size - 1
- hostname_resolution_expires_at = hostname_resolution_started_at + resolv_timeout if resolv_timeout
-
- while hostname_resolution_retry_count >= 0
- remaining = resolv_timeout ? second_to_timeout(hostname_resolution_started_at + resolv_timeout) : nil
- hostname_resolved, _, = IO.select(hostname_resolution_waiting, nil, nil, remaining)
-
- unless hostname_resolved
- state = :timeout
- break
- end
+ now = current_clock_time
+ starts_at = now
+ resolution_delay_expires_at = nil
+ connection_attempt_delay_expires_at = nil
+ user_specified_connect_timeout_at = nil
+ user_specified_open_timeout_at = open_timeout ? now + open_timeout : nil
+ last_error = nil
+ last_error_from_thread = false
+
+ if resolving_family_names.size == 1
+ family_name = resolving_family_names.first
+ addrinfos = Addrinfo.getaddrinfo(host, port, ADDRESS_FAMILIES[:family_name], :STREAM, timeout: open_timeout || resolv_timeout)
+ resolution_store.add_resolved(family_name, addrinfos)
+ hostname_resolution_result = nil
+ hostname_resolution_notifier = nil
+ user_specified_resolv_timeout_at = nil
+ else
+ hostname_resolution_result = HostnameResolutionResult.new(resolving_family_names.size)
+ hostname_resolution_notifier = hostname_resolution_result.notifier
+
+ hostname_resolution_threads.concat(
+ resolving_family_names.map { |family|
+ thread_args = [family, host, port, hostname_resolution_result]
+ thread = Thread.new(*thread_args) { |*thread_args| resolve_hostname(*thread_args) }
+ Thread.pass
+ thread
+ }
+ )
+ user_specified_resolv_timeout_at = resolv_timeout ? now + resolv_timeout : Float::INFINITY
+ end
- family_name, res = hostname_resolution_queue.get
+ loop do
+ if resolution_store.any_addrinfos? &&
+ !resolution_delay_expires_at &&
+ !connection_attempt_delay_expires_at
+ while (addrinfo = resolution_store.get_addrinfo)
+ if local_addrinfos.any?
+ local_addrinfo = local_addrinfos.find { |lai| lai.afamily == addrinfo.afamily }
+
+ if local_addrinfo.nil?
+ if resolution_store.any_addrinfos?
+ # Try other Addrinfo in next "while"
+ next
+ elsif connecting_sockets.any? || resolution_store.any_unresolved_family?
+ # Exit this "while" and wait for connections to be established or hostname resolution in next loop
+ # Or exit this "while" and wait for hostname resolution in next loop
+ break
+ else
+ raise SocketError.new 'no appropriate local address'
+ end
+ end
+ end
- if res.is_a? Exception
- unless (Socket.const_defined?(:EAI_ADDRFAMILY)) &&
- (res.is_a?(Socket::ResolutionError)) &&
- (res.error_code == Socket::EAI_ADDRFAMILY)
- last_error = res
+ begin
+ if resolution_store.any_addrinfos? ||
+ connecting_sockets.any? ||
+ resolution_store.any_unresolved_family?
+ socket = Socket.new(addrinfo.pfamily, addrinfo.socktype, addrinfo.protocol)
+ socket.bind(local_addrinfo) if local_addrinfo
+ result = socket.connect_nonblock(addrinfo, exception: false)
+ else
+ timeout =
+ if open_timeout
+ t = open_timeout - (current_clock_time - starts_at)
+ t.negative? ? 0 : t
+ else
+ connect_timeout
+ end
+ result = socket = local_addrinfo ?
+ addrinfo.connect_from(local_addrinfo, timeout:) :
+ addrinfo.connect(timeout:)
end
- if hostname_resolution_retry_count.zero?
- state = :failure
+ if result == :wait_writable
+ connection_attempt_delay_expires_at = now + CONNECTION_ATTEMPT_DELAY
+ if resolution_store.empty_addrinfos?
+ user_specified_connect_timeout_at = connect_timeout ? now + connect_timeout : Float::INFINITY
+ end
+
+ connecting_sockets[socket] = addrinfo
break
+ else
+ return socket # connection established
+ end
+ rescue SystemCallError => e
+ socket&.close
+ last_error = e
+
+ if resolution_store.any_addrinfos?
+ # Try other Addrinfo in next "while"
+ next
+ elsif connecting_sockets.any? || resolution_store.any_unresolved_family?
+ # Exit this "while" and wait for connections to be established or hostname resolution in next loop
+ # Or exit this "while" and wait for hostname resolution in next loop
+ break
+ else
+ raise last_error
end
- hostname_resolution_retry_count -= 1
- else
- state = case family_name
- when :ipv6 then :v6c
- when :ipv4 then hostname_resolution_queue.closed? ? :v4c : :v4w
- end
- selectable_addrinfos.add(family_name, res)
- last_error = nil
- break
end
end
+ end
- next
- when :v4w
- ipv6_resolved, _, = IO.select(hostname_resolution_waiting, nil, nil, RESOLUTION_DELAY)
-
- if ipv6_resolved
- family_name, res = hostname_resolution_queue.get
- selectable_addrinfos.add(family_name, res) unless res.is_a? Exception
- state = :v46c
+ ends_at =
+ if resolution_store.any_addrinfos?
+ [(resolution_delay_expires_at || connection_attempt_delay_expires_at),
+ user_specified_open_timeout_at].compact.min
+ elsif user_specified_open_timeout_at
+ user_specified_open_timeout_at
else
- state = :v4c
+ [user_specified_resolv_timeout_at, user_specified_connect_timeout_at].compact.max
end
- next
- when :v4c, :v6c, :v46c
- connection_attempt_started_at = current_clocktime unless connection_attempt_started_at
- addrinfo = selectable_addrinfos.get
-
- if local_addrinfos.any?
- local_addrinfo = local_addrinfos.find { |lai| lai.afamily == addrinfo.afamily }
-
- if local_addrinfo.nil?
- if selectable_addrinfos.empty? && connecting_sockets.empty? && hostname_resolution_queue.closed?
- last_error = SocketError.new 'no appropriate local address'
- state = :failure
- elsif selectable_addrinfos.any?
- # Try other Addrinfo in next loop
+ hostname_resolved, writable_sockets, except_sockets = IO.select(
+ hostname_resolution_notifier,
+ connecting_sockets.keys,
+ # Use errorfds to wait for non-blocking connect failures on Windows
+ is_windows_environment ? connecting_sockets.keys : nil,
+ second_to_timeout(current_clock_time, ends_at),
+ )
+ now = current_clock_time
+ resolution_delay_expires_at = nil if expired?(now, resolution_delay_expires_at)
+ connection_attempt_delay_expires_at = nil if expired?(now, connection_attempt_delay_expires_at)
+
+ if writable_sockets&.any?
+ while (writable_socket = writable_sockets.pop)
+ is_connected = is_windows_environment || (
+ sockopt = writable_socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_ERROR)
+ sockopt.int.zero?
+ )
+
+ if is_connected
+ connecting_sockets.delete writable_socket
+ return writable_socket
+ else
+ failed_ai = connecting_sockets.delete writable_socket
+ writable_socket.close
+ ip_address = failed_ai.ipv6? ? "[#{failed_ai.ip_address}]" : failed_ai.ip_address
+ last_error = SystemCallError.new("connect(2) for #{ip_address}:#{failed_ai.ip_port}", sockopt.int)
+
+ if writable_sockets.any? || connecting_sockets.any?
+ # Try other writable socket in next "while"
+ # Or exit this "while" and wait for connections to be established or hostname resolution in next loop
+ elsif resolution_store.any_addrinfos? || resolution_store.any_unresolved_family?
+ # Exit this "while" and try other connection attempt
+ # Or exit this "while" and wait for hostname resolution in next loop
+ connection_attempt_delay_expires_at = nil
+ user_specified_connect_timeout_at = nil
else
- if resolv_timeout && hostname_resolution_queue.opened? &&
- (current_clocktime >= hostname_resolution_expires_at)
- state = :timeout
- else
- # Wait for connection to be established or hostname resolution in next loop
- connection_attempt_delay_expires_at = nil
- state = :v46w
- end
+ raise last_error
end
- next
end
end
+ end
- connection_attempt_delay_expires_at = current_clocktime + CONNECTION_ATTEMPT_DELAY
-
- begin
- result = if specified_family_name && selectable_addrinfos.empty? &&
- connecting_sockets.empty? && hostname_resolution_queue.closed?
- local_addrinfo ?
- addrinfo.connect_from(local_addrinfo, timeout: connect_timeout) :
- addrinfo.connect(timeout: connect_timeout)
- else
- socket = Socket.new(addrinfo.pfamily, addrinfo.socktype, addrinfo.protocol)
- socket.bind(local_addrinfo) if local_addrinfo
- socket.connect_nonblock(addrinfo, exception: false)
- end
-
- case result
- when 0
- connected_socket = socket
- state = :success
- when Socket
- connected_socket = result
- state = :success
- when :wait_writable
- connecting_sockets.add(socket, addrinfo)
- state = :v46w
- end
- rescue SystemCallError => e
- last_error = e
- socket.close if socket && !socket.closed?
-
- if selectable_addrinfos.empty? && connecting_sockets.empty? && hostname_resolution_queue.closed?
- state = :failure
- elsif selectable_addrinfos.any?
- # Try other Addrinfo in next loop
+ if except_sockets&.any?
+ except_sockets.each do |except_socket|
+ failed_ai = connecting_sockets.delete except_socket
+ sockopt = except_socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_ERROR)
+ except_socket.close
+ ip_address = failed_ai.ipv6? ? "[#{failed_ai.ip_address}]" : failed_ai.ip_address
+ last_error = SystemCallError.new("connect(2) for #{ip_address}:#{failed_ai.ip_port}", sockopt.int)
+
+ if except_sockets.any? || connecting_sockets.any?
+ # Cleanup other except socket in next "each"
+ # Or exit this "while" and wait for connections to be established or hostname resolution in next loop
+ elsif resolution_store.any_addrinfos? || resolution_store.any_unresolved_family?
+ # Exit this "while" and try other connection attempt
+ # Or exit this "while" and wait for hostname resolution in next loop
+ connection_attempt_delay_expires_at = nil
+ user_specified_connect_timeout_at = nil
else
- if resolv_timeout && hostname_resolution_queue.opened? &&
- (current_clocktime >= hostname_resolution_expires_at)
- state = :timeout
- else
- # Wait for connection to be established or hostname resolution in next loop
- connection_attempt_delay_expires_at = nil
- state = :v46w
- end
+ raise last_error
end
end
+ end
- next
- when :v46w
- if connect_timeout && second_to_timeout(connection_attempt_started_at + connect_timeout).zero?
- state = :timeout
- next
- end
-
- remaining = second_to_timeout(connection_attempt_delay_expires_at)
- hostname_resolution_waiting = hostname_resolution_waiting && hostname_resolution_queue.closed? ? nil : hostname_resolution_waiting
- hostname_resolved, connectable_sockets, = IO.select(hostname_resolution_waiting, connecting_sockets.all, nil, remaining)
-
- if connectable_sockets&.any?
- while (connectable_socket = connectable_sockets.pop)
- is_connected =
- if is_windows_environment
- sockopt = connectable_socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_CONNECT_TIME)
- sockopt.unpack('i').first >= 0
- else
- sockopt = connectable_socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_ERROR)
- sockopt.int.zero?
- end
-
- if is_connected
- connected_socket = connectable_socket
- connecting_sockets.delete connectable_socket
- connectable_sockets.each do |other_connectable_socket|
- other_connectable_socket.close unless other_connectable_socket.closed?
- end
- state = :success
- break
- else
- failed_ai = connecting_sockets.delete connectable_socket
- inspected_ip_address = failed_ai.ipv6? ? "[#{failed_ai.ip_address}]" : failed_ai.ip_address
- last_error = SystemCallError.new("connect(2) for #{inspected_ip_address}:#{failed_ai.ip_port}", sockopt.int)
- connectable_socket.close unless connectable_socket.closed?
+ if hostname_resolved&.any?
+ while (family_and_result = hostname_resolution_result.get)
+ family_name, result = family_and_result
- next if connectable_sockets.any?
+ if result.is_a? Exception
+ resolution_store.add_error(family_name, result)
- if selectable_addrinfos.empty? && connecting_sockets.empty? && hostname_resolution_queue.closed?
- state = :failure
- elsif selectable_addrinfos.any?
- # Wait for connection attempt delay timeout in next loop
- else
- if resolv_timeout && hostname_resolution_queue.opened? &&
- (current_clocktime >= hostname_resolution_expires_at)
- state = :timeout
- else
- # Wait for connection to be established or hostname resolution in next loop
- connection_attempt_delay_expires_at = nil
- end
+ unless (Socket.const_defined?(:EAI_ADDRFAMILY)) &&
+ (result.is_a?(Socket::ResolutionError)) &&
+ (result.error_code == Socket::EAI_ADDRFAMILY)
+ other = family_name == :ipv6 ? :ipv4 : :ipv6
+ if !resolution_store.resolved?(other) || !resolution_store.resolved_successfully?(other)
+ last_error = result
+ last_error_from_thread = true
end
end
- end
- elsif hostname_resolved&.any?
- family_name, res = hostname_resolution_queue.get
- selectable_addrinfos.add(family_name, res) unless res.is_a? Exception
- else
- if selectable_addrinfos.empty? && connecting_sockets.empty? && hostname_resolution_queue.closed?
- state = :failure
- elsif selectable_addrinfos.any?
- # Try other Addrinfo in next loop
- state = :v46c
else
- if resolv_timeout && hostname_resolution_queue.opened? &&
- (current_clocktime >= hostname_resolution_expires_at)
- state = :timeout
- else
- # Wait for connection to be established or hostname resolution in next loop
- connection_attempt_delay_expires_at = nil
- end
+ resolution_store.add_resolved(family_name, result)
end
end
- next
- when :success
- break connected_socket
- when :failure
- raise last_error
- when :timeout
- raise Errno::ETIMEDOUT, 'user specified timeout'
+ if resolution_store.resolved?(:ipv4)
+ if resolution_store.resolved?(:ipv6)
+ hostname_resolution_notifier = nil
+ resolution_delay_expires_at = nil
+ user_specified_resolv_timeout_at = nil
+ elsif resolution_store.resolved_successfully?(:ipv4)
+ resolution_delay_expires_at = now + RESOLUTION_DELAY
+ end
+ end
end
- end
- if block_given?
- begin
- yield ret
- ensure
- ret.close
- end
- else
- ret
- end
- ensure
- if fast_fallback
- hostname_resolution_threads.each do |thread|
- thread&.exit
+ if expired?(now, user_specified_open_timeout_at)
+ raise(IO::TimeoutError, "user specified timeout for #{host}:#{port}")
end
- hostname_resolution_queue&.close_all
+ if resolution_store.empty_addrinfos?
+ if connecting_sockets.empty? && resolution_store.resolved_all_families?
+ if last_error_from_thread
+ raise last_error.class, last_error.message, cause: last_error
+ else
+ raise last_error
+ end
+ end
- connecting_sockets.each do |connecting_socket|
- connecting_socket.close unless connecting_socket.closed?
+ if (expired?(now, user_specified_resolv_timeout_at) || resolution_store.resolved_all_families?) &&
+ (expired?(now, user_specified_connect_timeout_at) || connecting_sockets.empty?)
+ raise(IO::TimeoutError, "user specified timeout for #{host}:#{port}")
+ end
end
end
- end
-
- def self.specified_family_name_and_next_state(hostname)
- if hostname.match?(IPV6_ADRESS_FORMAT) then [:ipv6, :v6c]
- elsif hostname.match?(/^([0-9]{1,3}\.){3}[0-9]{1,3}$/) then [:ipv4, :v4c]
- end
- end
- private_class_method :specified_family_name_and_next_state
-
- def self.hostname_resolution(family, host, port, hostname_resolution_queue)
- begin
- resolved_addrinfos = Addrinfo.getaddrinfo(host, port, ADDRESS_FAMILIES[family], :STREAM)
- hostname_resolution_queue.add_resolved(family, resolved_addrinfos)
- rescue => e
- hostname_resolution_queue.add_error(family, e)
+ ensure
+ hostname_resolution_threads.each do |thread|
+ thread.exit
end
- end
- private_class_method :hostname_resolution
- def self.second_to_timeout(ends_at)
- return 0 unless ends_at
-
- remaining = (ends_at - current_clocktime)
- remaining.negative? ? 0 : remaining
- end
- private_class_method :second_to_timeout
+ hostname_resolution_result&.close
- def self.current_clocktime
- Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ connecting_sockets.each_key do |connecting_socket|
+ connecting_socket.close
+ end
end
- private_class_method :current_clocktime
+ private_class_method :tcp_with_fast_fallback
- class SelectableAddrinfos
- PRIORITY_ON_V6 = [:ipv6, :ipv4]
- PRIORITY_ON_V4 = [:ipv4, :ipv6]
-
- def initialize
- @addrinfo_dict = {}
- @last_family = nil
- end
+ def self.tcp_without_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:, open_timeout:)
+ last_error = nil
+ ret = nil
- def add(family_name, addrinfos)
- @addrinfo_dict[family_name] = addrinfos
+ local_addr_list = nil
+ if local_host != nil || local_port != nil
+ local_addr_list = Addrinfo.getaddrinfo(local_host, local_port, nil, :STREAM, nil, timeout: open_timeout || resolv_timeout)
end
- def get
- return nil if empty?
+ timeout = open_timeout ? open_timeout : resolv_timeout
+ starts_at = current_clock_time
- if @addrinfo_dict.size == 1
- @addrinfo_dict.each { |_, addrinfos| return addrinfos.shift }
+ Addrinfo.foreach(host, port, nil, :STREAM, timeout:) {|ai|
+ if local_addr_list
+ local_addr = local_addr_list.find {|local_ai| local_ai.afamily == ai.afamily }
+ next unless local_addr
+ else
+ local_addr = nil
end
+ begin
+ timeout =
+ if open_timeout
+ t = open_timeout - (current_clock_time - starts_at)
+ t.negative? ? 0 : t
+ else
+ connect_timeout
+ end
- precedences = case @last_family
- when :ipv4, nil then PRIORITY_ON_V6
- when :ipv6 then PRIORITY_ON_V4
- end
-
- precedences.each do |family_name|
- addrinfo = @addrinfo_dict[family_name]&.shift
- next unless addrinfo
-
- @last_family = family_name
- return addrinfo
+ sock = local_addr ?
+ ai.connect_from(local_addr, timeout:) :
+ ai.connect(timeout:)
+ rescue SystemCallError
+ last_error = $!
+ next
+ end
+ ret = sock
+ break
+ }
+ unless ret
+ if last_error
+ raise last_error
+ else
+ raise SocketError, "no appropriate local address"
end
end
- def empty?
- @addrinfo_dict.all? { |_, addrinfos| addrinfos.empty? }
- end
-
- def any?
- !empty?
- end
+ ret
end
- private_constant :SelectableAddrinfos
-
- class NoHostnameResolutionQueue
- def waiting_pipe
- nil
- end
+ private_class_method :tcp_without_fast_fallback
- def add_resolved(_, _)
- raise StandardError, "This #{self.class} cannot respond to:"
- end
+ def self.ip_address?(hostname)
+ hostname.match?(IPV6_ADDRESS_FORMAT) || hostname.match?(/\A([0-9]{1,3}\.){3}[0-9]{1,3}\z/)
+ end
+ private_class_method :ip_address?
- def add_error(_, _)
- raise StandardError, "This #{self.class} cannot respond to:"
+ def self.resolve_hostname(family, host, port, hostname_resolution_result)
+ begin
+ resolved_addrinfos = Addrinfo.getaddrinfo(host, port, ADDRESS_FAMILIES[family], :STREAM)
+ hostname_resolution_result.add(family, resolved_addrinfos)
+ rescue => e
+ hostname_resolution_result.add(family, e)
end
+ end
+ private_class_method :resolve_hostname
- def get
- nil
- end
+ def self.current_clock_time
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ end
+ private_class_method :current_clock_time
- def opened?
- false
- end
+ def self.second_to_timeout(started_at, ends_at)
+ return nil if ends_at == Float::INFINITY || ends_at.nil?
- def closed?
- true
- end
+ remaining = (ends_at - started_at)
+ remaining.negative? ? 0 : remaining
+ end
+ private_class_method :second_to_timeout
- def close_all
- # Do nothing
- end
+ def self.expired?(started_at, ends_at)
+ second_to_timeout(started_at, ends_at)&.zero?
end
- private_constant :NoHostnameResolutionQueue
+ private_class_method :expired?
- class HostnameResolutionQueue
+ class HostnameResolutionResult
def initialize(size)
@size = size
@taken_count = 0
@rpipe, @wpipe = IO.pipe
- @queue = Queue.new
+ @results = []
@mutex = Mutex.new
end
- def waiting_pipe
+ def notifier
[@rpipe]
end
- def add_resolved(family, resolved_addrinfos)
+ def add(family, result)
@mutex.synchronize do
- @queue.push [family, resolved_addrinfos]
- @wpipe.putc HOSTNAME_RESOLUTION_QUEUE_UPDATED
- end
- end
-
- def add_error(family, error)
- @mutex.synchronize do
- @queue.push [family, error]
+ @results.push [family, result]
@wpipe.putc HOSTNAME_RESOLUTION_QUEUE_UPDATED
end
end
def get
- return nil if @queue.empty?
+ return nil if @results.empty?
res = nil
@mutex.synchronize do
@rpipe.getbyte
- res = @queue.pop
+ res = @results.shift
end
@taken_count += 1
- close_all if @taken_count == @size
+ close if @taken_count == @size
res
end
- def closed?
- @rpipe.closed?
+ def close
+ @rpipe.close
+ @wpipe.close
end
+ end
+ private_constant :HostnameResolutionResult
- def opened?
- !closed?
- end
+ class HostnameResolutionStore
+ PRIORITY_ON_V6 = [:ipv6, :ipv4].freeze
+ PRIORITY_ON_V4 = [:ipv4, :ipv6].freeze
- def close_all
- @queue.close unless @queue.closed?
- @rpipe.close unless @rpipe.closed?
- @wpipe.close unless @wpipe.closed?
+ def initialize(family_names)
+ @family_names = family_names
+ @addrinfo_dict = {}
+ @error_dict = {}
+ @last_family = nil
end
- end
- private_constant :HostnameResolutionQueue
- class ConnectingSockets
- def initialize
- @socket_dict = {}
+ def add_resolved(family_name, addrinfos)
+ @addrinfo_dict[family_name] = addrinfos
end
- def all
- @socket_dict.keys
+ def add_error(family_name, error)
+ @addrinfo_dict[family_name] = []
+ @error_dict[family_name] = error
end
- def add(socket, addrinfo)
- @socket_dict[socket] = addrinfo
- end
+ def get_addrinfo
+ precedences =
+ case @last_family
+ when :ipv4, nil then PRIORITY_ON_V6
+ when :ipv6 then PRIORITY_ON_V4
+ end
+
+ precedences.each do |family_name|
+ addrinfo = @addrinfo_dict[family_name]&.shift
+ next unless addrinfo
+
+ @last_family = family_name
+ return addrinfo
+ end
- def delete(socket)
- @socket_dict.delete socket
+ nil
end
- def empty?
- @socket_dict.empty?
+ def empty_addrinfos?
+ @addrinfo_dict.all? { |_, addrinfos| addrinfos.empty? }
end
- def each
- @socket_dict.keys.each do |socket|
- yield socket
- end
+ def any_addrinfos?
+ !empty_addrinfos?
end
- end
- private_constant :ConnectingSockets
- def self.tcp_without_fast_fallback(host, port, local_host, local_port, connect_timeout:, resolv_timeout:, &block)
- last_error = nil
- ret = nil
+ def resolved?(family)
+ @addrinfo_dict.has_key? family
+ end
- local_addr_list = nil
- if local_host != nil || local_port != nil
- local_addr_list = Addrinfo.getaddrinfo(local_host, local_port, nil, :STREAM, nil)
+ def resolved_successfully?(family)
+ resolved?(family) && !@error_dict[family]
end
- Addrinfo.foreach(host, port, nil, :STREAM, timeout: resolv_timeout) {|ai|
- if local_addr_list
- local_addr = local_addr_list.find {|local_ai| local_ai.afamily == ai.afamily }
- next unless local_addr
- else
- local_addr = nil
- end
- begin
- sock = local_addr ?
- ai.connect_from(local_addr, timeout: connect_timeout) :
- ai.connect(timeout: connect_timeout)
- rescue SystemCallError
- last_error = $!
- next
- end
- ret = sock
- break
- }
- unless ret
- if last_error
- raise last_error
- else
- raise SocketError, "no appropriate local address"
- end
+ def resolved_all_families?
+ (@family_names - @addrinfo_dict.keys).empty?
end
- if block_given?
- begin
- yield ret
- ensure
- ret.close
- end
- else
- ret
+
+ def any_unresolved_family?
+ !resolved_all_families?
end
end
- private_class_method :tcp_without_fast_fallback
+ private_constant :HostnameResolutionStore
- # :stopdoc:
def self.ip_sockets_port0(ai_list, reuseaddr)
sockets = []
begin
@@ -1211,9 +1157,7 @@ class Socket < BasicSocket
end
sockets
end
- class << self
- private :ip_sockets_port0
- end
+ private_class_method :ip_sockets_port0
def self.tcp_server_sockets_port0(host)
ai_list = Addrinfo.getaddrinfo(host, 0, nil, :STREAM, nil, Socket::AI_PASSIVE)
@@ -1641,13 +1585,18 @@ class Socket < BasicSocket
end
end
- class << self
- private
-
- def unix_socket_abstract_name?(path)
- /linux/ =~ RUBY_PLATFORM && /\A(\0|\z)/ =~ path
+ # :stopdoc:
+ if RUBY_PLATFORM.include?("linux")
+ def self.unix_socket_abstract_name?(path)
+ path.empty? or path.start_with?("\0")
+ end
+ else
+ def self.unix_socket_abstract_name?(path)
+ false
end
end
+ private_class_method :unix_socket_abstract_name?
+ # :startdoc:
# creates a UNIX socket server on _path_.
# It calls the block for each socket accepted.
@@ -1687,7 +1636,7 @@ class Socket < BasicSocket
# Returns 0 if successful, otherwise an exception is raised.
#
# === Parameter
- # # +remote_sockaddr+ - the +struct+ sockaddr contained in a string or Addrinfo object
+ # * +remote_sockaddr+ - the +struct+ sockaddr contained in a string or Addrinfo object
#
# === Example:
# # Pull down Google's web page
@@ -1722,7 +1671,7 @@ class Socket < BasicSocket
# return the symbol +:wait_writable+ instead.
#
# === See
- # # Socket#connect
+ # * Socket#connect
def connect_nonblock(addr, exception: true)
__connect_nonblock(addr, exception)
end
diff --git a/ext/socket/raddrinfo.c b/ext/socket/raddrinfo.c
index 4ca06021ba..6cdf5c6abc 100644
--- a/ext/socket/raddrinfo.c
+++ b/ext/socket/raddrinfo.c
@@ -277,8 +277,9 @@ numeric_getaddrinfo(const char *node, const char *service,
void
rb_freeaddrinfo(struct rb_addrinfo *ai)
{
- if (!ai->allocated_by_malloc)
- freeaddrinfo(ai->ai);
+ if (!ai->allocated_by_malloc) {
+ if (ai->ai) freeaddrinfo(ai->ai);
+ }
else {
struct addrinfo *ai1, *ai2;
ai1 = ai->ai;
@@ -292,10 +293,22 @@ rb_freeaddrinfo(struct rb_addrinfo *ai)
xfree(ai);
}
+static int
+rsock_value_timeout_to_msec(VALUE timeout)
+{
+ double seconds = NUM2DBL(timeout);
+ if (seconds < 0) rb_raise(rb_eArgError, "timeout must not be negative");
+
+ double msec = seconds * 1000.0;
+ if (msec > UINT_MAX) rb_raise(rb_eArgError, "timeout too large");
+
+ return (unsigned int)(msec + 0.5);
+}
+
#if GETADDRINFO_IMPL == 0
static int
-rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hints, struct addrinfo **ai)
+rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hints, struct addrinfo **ai, int _timeout)
{
return getaddrinfo(hostp, portp, hints, ai);
}
@@ -326,8 +339,14 @@ nogvl_getaddrinfo(void *arg)
return (void *)(VALUE)ret;
}
+static void *
+fork_safe_getaddrinfo(void *arg)
+{
+ return rb_thread_prevent_fork(nogvl_getaddrinfo, arg);
+}
+
static int
-rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hints, struct addrinfo **ai)
+rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hints, struct addrinfo **ai, int _timeout)
{
struct getaddrinfo_arg arg;
MEMZERO(&arg, struct getaddrinfo_arg, 1);
@@ -335,7 +354,7 @@ rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hint
arg.service = portp;
arg.hints = hints;
arg.res = ai;
- return (int)(VALUE)rb_thread_call_without_gvl(nogvl_getaddrinfo, &arg, RUBY_UBF_IO, 0);
+ return (int)(VALUE)rb_thread_call_without_gvl(fork_safe_getaddrinfo, &arg, RUBY_UBF_IO, 0);
}
#elif GETADDRINFO_IMPL == 2
@@ -345,13 +364,14 @@ struct getaddrinfo_arg
char *node, *service;
struct addrinfo hints;
struct addrinfo *ai;
- int err, gai_errno, refcount, done, cancelled;
+ int err, gai_errno, refcount, done, cancelled, timedout;
rb_nativethread_lock_t lock;
rb_nativethread_cond_t cond;
+ int timeout;
};
static struct getaddrinfo_arg *
-allocate_getaddrinfo_arg(const char *hostp, const char *portp, const struct addrinfo *hints)
+allocate_getaddrinfo_arg(const char *hostp, const char *portp, const struct addrinfo *hints, int timeout)
{
size_t hostp_offset = sizeof(struct getaddrinfo_arg);
size_t portp_offset = hostp_offset + (hostp ? strlen(hostp) + 1 : 0);
@@ -367,7 +387,7 @@ allocate_getaddrinfo_arg(const char *hostp, const char *portp, const struct addr
if (hostp) {
arg->node = buf + hostp_offset;
- strcpy(arg->node, hostp);
+ memcpy(arg->node, hostp, portp_offset - hostp_offset);
}
else {
arg->node = NULL;
@@ -375,7 +395,7 @@ allocate_getaddrinfo_arg(const char *hostp, const char *portp, const struct addr
if (portp) {
arg->service = buf + portp_offset;
- strcpy(arg->service, portp);
+ memcpy(arg->service, portp, bufsize - portp_offset);
}
else {
arg->service = NULL;
@@ -385,7 +405,8 @@ allocate_getaddrinfo_arg(const char *hostp, const char *portp, const struct addr
arg->ai = NULL;
arg->refcount = 2;
- arg->done = arg->cancelled = 0;
+ arg->done = arg->cancelled = arg->timedout = 0;
+ arg->timeout = timeout;
rb_nativethread_lock_initialize(&arg->lock);
rb_native_cond_initialize(&arg->cond);
@@ -423,7 +444,7 @@ do_getaddrinfo(void *ptr)
arg->err = err;
arg->gai_errno = gai_errno;
if (arg->cancelled) {
- freeaddrinfo(arg->ai);
+ if (arg->ai) freeaddrinfo(arg->ai);
}
else {
arg->done = 1;
@@ -444,7 +465,19 @@ wait_getaddrinfo(void *ptr)
struct getaddrinfo_arg *arg = (struct getaddrinfo_arg *)ptr;
rb_nativethread_lock_lock(&arg->lock);
while (!arg->done && !arg->cancelled) {
- rb_native_cond_wait(&arg->cond, &arg->lock);
+ long msec = arg->timeout;
+ if (msec == 0) {
+ arg->cancelled = 1;
+ arg->timedout = 1;
+ } else if (msec > 0) {
+ rb_native_cond_timedwait(&arg->cond, &arg->lock, msec);
+ if (!arg->done) {
+ arg->cancelled = 1;
+ arg->timedout = 1;
+ }
+ } else {
+ rb_native_cond_wait(&arg->cond, &arg->lock);
+ }
}
rb_nativethread_lock_unlock(&arg->lock);
return 0;
@@ -462,41 +495,84 @@ cancel_getaddrinfo(void *ptr)
rb_nativethread_lock_unlock(&arg->lock);
}
-static int
-do_pthread_create(pthread_t *th, void *(*start_routine) (void *), void *arg)
+int
+raddrinfo_pthread_create(pthread_t *th, void *(*start_routine) (void *), void *arg)
{
int limit = 3, ret;
+ int saved_errno;
+#ifdef HAVE_PTHREAD_ATTR_SETDETACHSTATE
+ pthread_attr_t attr;
+ pthread_attr_t *attr_p = &attr;
+ int err;
+ int init_retries = 0;
+ int init_retries_max = 3;
+retry_attr_init:
+ if ((err = pthread_attr_init(attr_p)) != 0) {
+ if (err == ENOMEM && init_retries < init_retries_max) {
+ init_retries++;
+ rb_gc();
+ goto retry_attr_init;
+ }
+ return err;
+ }
+ if ((err = pthread_attr_setdetachstate(attr_p, PTHREAD_CREATE_DETACHED)) != 0) {
+ saved_errno = errno;
+ pthread_attr_destroy(attr_p);
+ errno = saved_errno;
+ return err; // EINVAL - shouldn't happen
+ }
+#else
+ pthread_attr_t *attr_p = NULL;
+#endif
do {
// It is said that pthread_create may fail spuriously, so we follow the JDK and retry several times.
//
// https://bugs.openjdk.org/browse/JDK-8268605
// https://github.com/openjdk/jdk/commit/e35005d5ce383ddd108096a3079b17cb0bcf76f1
- ret = pthread_create(th, 0, start_routine, arg);
+ ret = pthread_create(th, attr_p, start_routine, arg);
} while (ret == EAGAIN && limit-- > 0);
+#ifdef HAVE_PTHREAD_ATTR_SETDETACHSTATE
+ saved_errno = errno;
+ pthread_attr_destroy(attr_p);
+ if (ret != 0) {
+ errno = saved_errno;
+ }
+#else
+ if (ret == 0) {
+ pthread_detach(th); // this can race with shutdown routine of thread in some glibc versions
+ }
+#endif
return ret;
}
+static void *
+fork_safe_do_getaddrinfo(void *ptr)
+{
+ return rb_thread_prevent_fork(do_getaddrinfo, ptr);
+}
+
static int
-rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hints, struct addrinfo **ai)
+rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hints, struct addrinfo **ai, int timeout)
{
int retry;
struct getaddrinfo_arg *arg;
- int err = 0, gai_errno = 0;
+ int err = 0, gai_errno = 0, timedout = 0;
start:
retry = 0;
- arg = allocate_getaddrinfo_arg(hostp, portp, hints);
+ arg = allocate_getaddrinfo_arg(hostp, portp, hints, timeout);
if (!arg) {
return EAI_MEMORY;
}
pthread_t th;
- if (do_pthread_create(&th, do_getaddrinfo, arg) != 0) {
+ if (raddrinfo_pthread_create(&th, fork_safe_do_getaddrinfo, arg) != 0) {
+ int err = errno;
free_getaddrinfo_arg(arg);
- return EAI_AGAIN;
+ errno = err;
+ return EAI_SYSTEM;
}
- pthread_detach(th);
rb_thread_call_without_gvl2(wait_getaddrinfo, arg, cancel_getaddrinfo, arg);
@@ -509,7 +585,8 @@ start:
if (err == 0) *ai = arg->ai;
}
else if (arg->cancelled) {
- err = EAI_AGAIN;
+ retry = 1;
+ timedout = arg->timedout;
}
else {
// If already interrupted, rb_thread_call_without_gvl2 may return without calling wait_getaddrinfo.
@@ -523,6 +600,16 @@ start:
if (need_free) free_getaddrinfo_arg(arg);
+ if (timedout) {
+ if (arg->ai) {
+ rsock_raise_user_specified_timeout(arg->ai, Qnil, Qnil);
+ } else {
+ VALUE host = rb_str_new_cstr(hostp);
+ VALUE port = rb_str_new_cstr(portp);
+ rsock_raise_user_specified_timeout(NULL, host, port);
+ }
+ }
+
// If the current thread is interrupted by asynchronous exception, the following raises the exception.
// But if the current thread is interrupted by timer thread, the following returns; we need to manually retry.
rb_thread_check_ints();
@@ -537,6 +624,10 @@ start:
#endif
+#define GETNAMEINFO_WONT_BLOCK(host, serv, flags) \
+ ((!(host) || ((flags) & NI_NUMERICHOST)) && \
+ (!(serv) || ((flags) & NI_NUMERICSERV)))
+
#if GETADDRINFO_IMPL == 0
int
@@ -544,7 +635,7 @@ rb_getnameinfo(const struct sockaddr *sa, socklen_t salen,
char *host, size_t hostlen,
char *serv, size_t servlen, int flags)
{
- return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
+ return getnameinfo(sa, salen, host, (socklen_t)hostlen, serv, (socklen_t)servlen, flags);
}
#elif GETADDRINFO_IMPL == 1
@@ -574,6 +665,10 @@ rb_getnameinfo(const struct sockaddr *sa, socklen_t salen,
char *host, size_t hostlen,
char *serv, size_t servlen, int flags)
{
+ if (GETNAMEINFO_WONT_BLOCK(host, serv, flags)) {
+ return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
+ }
+
struct getnameinfo_arg arg;
int ret;
arg.sa = sa;
@@ -700,7 +795,11 @@ rb_getnameinfo(const struct sockaddr *sa, socklen_t salen,
{
int retry;
struct getnameinfo_arg *arg;
- int err, gni_errno = 0;
+ int err = 0, gni_errno = 0;
+
+ if (GETNAMEINFO_WONT_BLOCK(host, serv, flags)) {
+ return getnameinfo(sa, salen, host, (socklen_t)hostlen, serv, (socklen_t)servlen, flags);
+ }
start:
retry = 0;
@@ -711,11 +810,12 @@ start:
}
pthread_t th;
- if (do_pthread_create(&th, do_getnameinfo, arg) != 0) {
+ if (raddrinfo_pthread_create(&th, do_getnameinfo, arg) != 0) {
+ int err = errno;
free_getnameinfo_arg(arg);
- return EAI_AGAIN;
+ errno = err;
+ return EAI_SYSTEM;
}
- pthread_detach(th);
rb_thread_call_without_gvl2(wait_getnameinfo, arg, cancel_getnameinfo, arg);
@@ -730,7 +830,7 @@ start:
}
}
else if (arg->cancelled) {
- err = EAI_AGAIN;
+ retry = 1;
}
else {
// If already interrupted, rb_thread_call_without_gvl2 may return without calling wait_getnameinfo.
@@ -805,8 +905,8 @@ str_is_number(const char *p)
((ptr)[0] == name[0] && \
rb_strlen_lit(name) == (len) && memcmp(ptr, name, len) == 0)
-static char*
-host_str(VALUE host, char *hbuf, size_t hbuflen, int *flags_ptr)
+char*
+raddrinfo_host_str(VALUE host, char *hbuf, size_t hbuflen, int *flags_ptr)
{
if (NIL_P(host)) {
return NULL;
@@ -844,8 +944,8 @@ host_str(VALUE host, char *hbuf, size_t hbuflen, int *flags_ptr)
}
}
-static char*
-port_str(VALUE port, char *pbuf, size_t pbuflen, int *flags_ptr)
+char*
+raddrinfo_port_str(VALUE port, char *pbuf, size_t pbuflen, int *flags_ptr)
{
if (NIL_P(port)) {
return 0;
@@ -897,7 +997,7 @@ rb_scheduler_getaddrinfo(VALUE scheduler, VALUE host, const char *service,
for(i=0; i<len; i++) {
ip_address = rb_ary_entry(ip_addresses_array, i);
- hostp = host_str(ip_address, _hbuf, sizeof(_hbuf), &_additional_flags);
+ hostp = raddrinfo_host_str(ip_address, _hbuf, sizeof(_hbuf), &_additional_flags);
error = numeric_getaddrinfo(hostp, service, hints, &ai);
if (error == 0) {
if (!res_allocated) {
@@ -924,7 +1024,7 @@ rb_scheduler_getaddrinfo(VALUE scheduler, VALUE host, const char *service,
}
struct rb_addrinfo*
-rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack)
+rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack, VALUE timeout)
{
struct rb_addrinfo* res = NULL;
struct addrinfo *ai;
@@ -933,8 +1033,8 @@ rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_h
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);
+ hostp = raddrinfo_host_str(host, hbuf, sizeof(hbuf), &additional_flags);
+ portp = raddrinfo_port_str(port, pbuf, sizeof(pbuf), &additional_flags);
if (socktype_hack && hints->ai_socktype == 0 && str_is_number(portp)) {
hints->ai_socktype = SOCK_DGRAM;
@@ -959,7 +1059,8 @@ rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_h
}
if (!resolved) {
- error = rb_getaddrinfo(hostp, portp, hints, &ai);
+ int t = NIL_P(timeout) ? -1 : rsock_value_timeout_to_msec(timeout);
+ error = rb_getaddrinfo(hostp, portp, hints, &ai, t);
if (error == 0) {
res = (struct rb_addrinfo *)xmalloc(sizeof(struct rb_addrinfo));
res->allocated_by_malloc = 0;
@@ -992,7 +1093,7 @@ rsock_fd_family(int fd)
}
struct rb_addrinfo*
-rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags)
+rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags, VALUE timeout)
{
struct addrinfo hints;
@@ -1000,7 +1101,7 @@ rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags)
hints.ai_family = family;
hints.ai_socktype = socktype;
hints.ai_flags = flags;
- return rsock_getaddrinfo(host, port, &hints, 1);
+ return rsock_getaddrinfo(host, port, &hints, 1, timeout);
}
VALUE
@@ -1120,7 +1221,7 @@ make_hostent_internal(VALUE v)
hostp = addr->ai_canonname;
}
else {
- hostp = host_str(host, hbuf, sizeof(hbuf), NULL);
+ hostp = raddrinfo_host_str(host, hbuf, sizeof(hbuf), NULL);
}
rb_ary_push(ary, rb_str_new2(hostp));
@@ -1194,6 +1295,7 @@ addrinfo_memsize(const void *ptr)
static const rb_data_type_t addrinfo_type = {
"socket/addrinfo",
{addrinfo_mark, addrinfo_free, addrinfo_memsize,},
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE | RUBY_TYPED_WB_PROTECTED,
};
static VALUE
@@ -1231,7 +1333,7 @@ alloc_addrinfo(void)
}
static void
-init_addrinfo(rb_addrinfo_t *rai, struct sockaddr *sa, socklen_t len,
+init_addrinfo(VALUE self, rb_addrinfo_t *rai, struct sockaddr *sa, socklen_t len,
int pfamily, int socktype, int protocol,
VALUE canonname, VALUE inspectname)
{
@@ -1243,8 +1345,8 @@ init_addrinfo(rb_addrinfo_t *rai, struct sockaddr *sa, socklen_t len,
rai->pfamily = pfamily;
rai->socktype = socktype;
rai->protocol = protocol;
- rai->canonname = canonname;
- rai->inspectname = inspectname;
+ RB_OBJ_WRITE(self, &rai->canonname, canonname);
+ RB_OBJ_WRITE(self, &rai->inspectname, inspectname);
}
VALUE
@@ -1257,7 +1359,7 @@ rsock_addrinfo_new(struct sockaddr *addr, socklen_t len,
a = addrinfo_s_allocate(rb_cAddrinfo);
DATA_PTR(a) = rai = alloc_addrinfo();
- init_addrinfo(rai, addr, len, family, socktype, protocol, canonname, inspectname);
+ init_addrinfo(a, rai, addr, len, family, socktype, protocol, canonname, inspectname);
return a;
}
@@ -1282,7 +1384,7 @@ call_getaddrinfo(VALUE node, VALUE service,
hints.ai_flags = NUM2INT(flags);
}
- res = rsock_getaddrinfo(node, service, &hints, socktype_hack);
+ res = rsock_getaddrinfo(node, service, &hints, socktype_hack, timeout);
if (res == NULL)
rb_raise(rb_eSocket, "host not found");
@@ -1292,7 +1394,7 @@ call_getaddrinfo(VALUE node, VALUE service,
static VALUE make_inspectname(VALUE node, VALUE service, struct addrinfo *res);
static void
-init_addrinfo_getaddrinfo(rb_addrinfo_t *rai, VALUE node, VALUE service,
+init_addrinfo_getaddrinfo(VALUE self, rb_addrinfo_t *rai, VALUE node, VALUE service,
VALUE family, VALUE socktype, VALUE protocol, VALUE flags,
VALUE inspectnode, VALUE inspectservice)
{
@@ -1306,7 +1408,7 @@ init_addrinfo_getaddrinfo(rb_addrinfo_t *rai, VALUE node, VALUE service,
OBJ_FREEZE(canonname);
}
- init_addrinfo(rai, res->ai->ai_addr, res->ai->ai_addrlen,
+ init_addrinfo(self, rai, res->ai->ai_addr, res->ai->ai_addrlen,
NUM2INT(family), NUM2INT(socktype), NUM2INT(protocol),
canonname, inspectname);
@@ -1418,7 +1520,7 @@ addrinfo_list_new(VALUE node, VALUE service, VALUE family, VALUE socktype, VALUE
#ifdef HAVE_TYPE_STRUCT_SOCKADDR_UN
static void
-init_unix_addrinfo(rb_addrinfo_t *rai, VALUE path, int socktype)
+init_unix_addrinfo(VALUE self, rb_addrinfo_t *rai, VALUE path, int socktype)
{
struct sockaddr_un un;
socklen_t len;
@@ -1434,7 +1536,7 @@ init_unix_addrinfo(rb_addrinfo_t *rai, VALUE path, int socktype)
memcpy((void*)&un.sun_path, RSTRING_PTR(path), RSTRING_LEN(path));
len = rsock_unix_sockaddr_len(path);
- init_addrinfo(rai, (struct sockaddr *)&un, len,
+ init_addrinfo(self, rai, (struct sockaddr *)&un, len,
PF_UNIX, socktype, 0, Qnil, Qnil);
}
@@ -1538,7 +1640,7 @@ addrinfo_initialize(int argc, VALUE *argv, VALUE self)
flags |= AI_NUMERICSERV;
#endif
- init_addrinfo_getaddrinfo(rai, numericnode, service,
+ init_addrinfo_getaddrinfo(self, rai, numericnode, service,
INT2NUM(i_pfamily ? i_pfamily : af), INT2NUM(i_socktype), INT2NUM(i_protocol),
INT2NUM(flags),
nodename, service);
@@ -1550,7 +1652,7 @@ addrinfo_initialize(int argc, VALUE *argv, VALUE self)
{
VALUE path = rb_ary_entry(sockaddr_ary, 1);
StringValue(path);
- init_unix_addrinfo(rai, path, SOCK_STREAM);
+ init_unix_addrinfo(self, rai, path, SOCK_STREAM);
break;
}
#endif
@@ -1563,7 +1665,7 @@ addrinfo_initialize(int argc, VALUE *argv, VALUE self)
StringValue(sockaddr_arg);
sockaddr_ptr = (struct sockaddr *)RSTRING_PTR(sockaddr_arg);
sockaddr_len = RSTRING_SOCKLEN(sockaddr_arg);
- init_addrinfo(rai, sockaddr_ptr, sockaddr_len,
+ init_addrinfo(self, rai, sockaddr_ptr, sockaddr_len,
i_pfamily, i_socktype, i_protocol,
canonname, inspectname);
}
@@ -2152,7 +2254,7 @@ addrinfo_mload(VALUE self, VALUE ary)
}
DATA_PTR(self) = rai = alloc_addrinfo();
- init_addrinfo(rai, &ss.addr, len,
+ init_addrinfo(self, rai, &ss.addr, len,
pfamily, socktype, protocol,
canonname, inspectname);
return self;
@@ -2920,7 +3022,7 @@ addrinfo_s_unix(int argc, VALUE *argv, VALUE self)
addr = addrinfo_s_allocate(rb_cAddrinfo);
DATA_PTR(addr) = rai = alloc_addrinfo();
- init_unix_addrinfo(rai, path, socktype);
+ init_unix_addrinfo(self, rai, path, socktype);
return addr;
}
@@ -3007,6 +3109,99 @@ rsock_io_socket_addrinfo(VALUE io, struct sockaddr *addr, socklen_t len)
UNREACHABLE_RETURN(Qnil);
}
+#if FAST_FALLBACK_INIT_INETSOCK_IMPL == 1
+
+void
+free_fast_fallback_getaddrinfo_shared(struct fast_fallback_getaddrinfo_shared **shared)
+{
+ xfree((*shared)->node);
+ (*shared)->node = NULL;
+ xfree((*shared)->service);
+ (*shared)->service = NULL;
+ rb_nativethread_lock_destroy(&(*shared)->lock);
+ free(*shared);
+ *shared = NULL;
+}
+
+static void *
+do_fast_fallback_getaddrinfo(void *ptr)
+{
+ struct fast_fallback_getaddrinfo_entry *entry = (struct fast_fallback_getaddrinfo_entry *)ptr;
+ struct fast_fallback_getaddrinfo_shared *shared = entry->shared;
+ int err = 0, shared_need_free = 0;
+ struct addrinfo *ai = NULL;
+
+ sigset_t set;
+ sigemptyset(&set);
+ sigaddset(&set, SIGPIPE);
+ pthread_sigmask(SIG_BLOCK, &set, NULL);
+
+ err = numeric_getaddrinfo(shared->node, shared->service, &entry->hints, &entry->ai);
+
+ if (err != 0) {
+ err = getaddrinfo(shared->node, shared->service, &entry->hints, &entry->ai);
+ #ifdef __linux__
+ /* On Linux (mainly Ubuntu 13.04) /etc/nsswitch.conf has mdns4 and
+ * it cause getaddrinfo to return EAI_SYSTEM/ENOENT. [ruby-list:49420]
+ */
+ if (err == EAI_SYSTEM && errno == ENOENT)
+ err = EAI_NONAME;
+ #endif
+ }
+
+ /* for testing HEv2 */
+ if (entry->test_sleep_ms > 0) {
+ struct timespec sleep_ts;
+ sleep_ts.tv_sec = entry->test_sleep_ms / 1000;
+ sleep_ts.tv_nsec = (entry->test_sleep_ms % 1000) * 1000000L;
+ if (sleep_ts.tv_nsec >= 1000000000L) {
+ sleep_ts.tv_sec += sleep_ts.tv_nsec / 1000000000L;
+ sleep_ts.tv_nsec = sleep_ts.tv_nsec % 1000000000L;
+ }
+ nanosleep(&sleep_ts, NULL);
+ }
+ if (entry->test_ecode != 0) {
+ err = entry->test_ecode;
+ if (entry->ai) {
+ freeaddrinfo(entry->ai);
+ entry->ai = NULL;
+ }
+ }
+
+ rb_nativethread_lock_lock(&shared->lock);
+ {
+ entry->err = err;
+ const char notification = entry->family == AF_INET6 ?
+ IPV6_HOSTNAME_RESOLVED : IPV4_HOSTNAME_RESOLVED;
+
+ if (shared->notify != -1 && (write(shared->notify, &notification, 1)) < 0) {
+ entry->err = errno;
+ entry->has_syserr = true;
+ }
+ if (--(entry->refcount) == 0) {
+ ai = entry->ai;
+ entry->ai = NULL;
+ }
+ if (--(shared->refcount) == 0) shared_need_free = 1;
+ }
+ rb_nativethread_lock_unlock(&shared->lock);
+
+ if (ai) freeaddrinfo(ai);
+ if (shared_need_free && shared) {
+ free_fast_fallback_getaddrinfo_shared(&shared);
+ }
+
+ return 0;
+}
+
+void *
+fork_safe_do_fast_fallback_getaddrinfo(void *ptr)
+{
+ return rb_thread_prevent_fork(do_fast_fallback_getaddrinfo, ptr);
+}
+
+#endif
+
/*
* Addrinfo class
*/
diff --git a/ext/socket/rubysocket.h b/ext/socket/rubysocket.h
index f486db4262..2ec3ab335a 100644
--- a/ext/socket/rubysocket.h
+++ b/ext/socket/rubysocket.h
@@ -138,6 +138,7 @@
#include "internal.h"
#include "internal/array.h"
+#include "internal/compilers.h"
#include "internal/error.h"
#include "internal/gc.h"
#include "internal/io.h"
@@ -291,15 +292,13 @@ extern VALUE rb_eResolution;
#ifdef SOCKS
extern VALUE rb_cSOCKSSocket;
# ifndef SOCKS5
-void SOCKSinit();
-int Rconnect();
+void SOCKSinit(char *);
+int Rconnect(int, const struct sockaddr *, socklen_t);
# endif
#endif
#include "constdefs.h"
-#define BLOCKING_REGION_FD(func, arg) (long)rb_thread_io_blocking_region((func), (arg), (arg)->fd)
-
#define SockAddrStringValue(v) rsock_sockaddr_string_value(&(v))
#define SockAddrStringValuePtr(v) rsock_sockaddr_string_value_ptr(&(v))
#define SockAddrStringValueWithAddrinfo(v, rai_ret) rsock_sockaddr_string_value_with_addrinfo(&(v), &(rai_ret))
@@ -328,8 +327,8 @@ 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);
+struct rb_addrinfo *rsock_addrinfo(VALUE host, VALUE port, int family, int socktype, int flags, VALUE timeout);
+struct rb_addrinfo *rsock_getaddrinfo(VALUE host, VALUE port, struct addrinfo *hints, int socktype_hack, VALUE timeout);
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);
@@ -356,7 +355,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 resolv_timeout, VALUE connect_timeout);
+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 open_timeout, VALUE fast_fallback, VALUE test_mode_settings);
VALUE rsock_init_unixsock(VALUE sock, VALUE path, int server);
struct rsock_send_arg {
@@ -381,7 +380,7 @@ 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, struct timeval *timeout);
+int rsock_connect(VALUE self, const struct sockaddr *sockaddr, int len, int socks, VALUE timeout);
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,
@@ -415,6 +414,47 @@ ssize_t rsock_recvmsg(int socket, struct msghdr *message, int flags);
void rsock_discard_cmsg_resource(struct msghdr *mh, int msg_peek_p);
#endif
+char *raddrinfo_host_str(VALUE host, char *hbuf, size_t hbuflen, int *flags_ptr);
+char *raddrinfo_port_str(VALUE port, char *pbuf, size_t pbuflen, int *flags_ptr);
+
+#ifndef FAST_FALLBACK_INIT_INETSOCK_IMPL
+# if !defined(HAVE_PTHREAD_CREATE) || !defined(HAVE_PTHREAD_DETACH) || defined(__MINGW32__) || defined(__MINGW64__)
+# define FAST_FALLBACK_INIT_INETSOCK_IMPL 0
+# else
+# include "ruby/thread_native.h"
+# define FAST_FALLBACK_INIT_INETSOCK_IMPL 1
+# define IPV6_HOSTNAME_RESOLVED '1'
+# define IPV4_HOSTNAME_RESOLVED '2'
+# define SELECT_CANCELLED '3'
+
+struct fast_fallback_getaddrinfo_entry
+{
+ int family, err, refcount;
+ struct addrinfo hints;
+ struct addrinfo *ai;
+ struct fast_fallback_getaddrinfo_shared *shared;
+ int has_syserr;
+ long test_sleep_ms;
+ int test_ecode;
+};
+
+struct fast_fallback_getaddrinfo_shared
+{
+ int notify, refcount;
+ char *node, *service;
+ rb_nativethread_lock_t lock;
+ struct fast_fallback_getaddrinfo_entry getaddrinfo_entries[FLEX_ARY_LEN];
+};
+
+int raddrinfo_pthread_create(pthread_t *th, void *(*start_routine) (void *), void *arg);
+void *fork_safe_do_fast_fallback_getaddrinfo(void *ptr);
+void free_fast_fallback_getaddrinfo_entry(struct fast_fallback_getaddrinfo_entry **entry);
+void free_fast_fallback_getaddrinfo_shared(struct fast_fallback_getaddrinfo_shared **shared);
+# endif
+#endif
+
+NORETURN(void rsock_raise_user_specified_timeout(struct addrinfo *ai, VALUE host, VALUE port));
+
void rsock_init_basicsocket(void);
void rsock_init_ipsocket(void);
void rsock_init_tcpsocket(void);
@@ -463,12 +503,12 @@ void rsock_make_fd_nonblock(int fd);
int rsock_is_dgram(rb_io_t *fptr);
+extern ID tcp_fast_fallback;
+
#if !defined HAVE_INET_NTOP && ! defined _WIN32
const char *inet_ntop(int, const void *, char *, size_t);
#elif defined __MINGW32__
# define inet_ntop(f,a,n,l) rb_w32_inet_ntop(f,a,n,l)
-#elif defined _MSC_VER && RUBY_MSVCRT_VERSION < 90
-const char *WSAAPI inet_ntop(int, const void *, char *, size_t);
#endif
#endif
diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index c780d77cf6..a8e5ae8119 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -14,6 +14,8 @@ static VALUE sym_wait_writable;
static VALUE sock_s_unpack_sockaddr_in(VALUE, VALUE);
+ID tcp_fast_fallback;
+
void
rsock_sys_fail_host_port(const char *mesg, VALUE host, VALUE port)
{
@@ -387,22 +389,20 @@ rsock_sock_s_socketpair(int argc, VALUE *argv, VALUE klass)
* * connect function in Microsoft's Winsock functions reference
*/
static VALUE
-sock_connect(VALUE sock, VALUE addr)
+sock_connect(VALUE self, VALUE addr)
{
VALUE rai;
- rb_io_t *fptr;
- int fd, n;
SockAddrStringValueWithAddrinfo(addr, rai);
addr = rb_str_new4(addr);
- GetOpenFile(sock, fptr);
- fd = fptr->fd;
- n = rsock_connect(fd, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr), 0, NULL);
- if (n < 0) {
+
+ int result = rsock_connect(self, (struct sockaddr*)RSTRING_PTR(addr), RSTRING_SOCKLEN(addr), 0, RUBY_IO_TIMEOUT_DEFAULT);
+
+ if (result < 0) {
rsock_sys_fail_raddrinfo_or_sockaddr("connect(2)", addr, rai);
}
- return INT2FIX(n);
+ return INT2FIX(result);
}
/* :nodoc: */
@@ -965,7 +965,7 @@ 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);
+ rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, AI_CANONNAME, Qnil);
return rsock_make_hostent(host, res, sock_sockaddr);
}
@@ -1183,7 +1183,7 @@ sock_s_getaddrinfo(int argc, VALUE *argv, VALUE _)
norevlookup = rsock_do_not_reverse_lookup;
}
- res = rsock_getaddrinfo(host, port, &hints, 0);
+ res = rsock_getaddrinfo(host, port, &hints, 0, Qnil);
ret = make_addrinfo(res, norevlookup);
rb_freeaddrinfo(res);
@@ -1279,7 +1279,7 @@ sock_s_getnameinfo(int argc, VALUE *argv, VALUE _)
hints.ai_socktype = (fl & NI_DGRAM) ? SOCK_DGRAM : SOCK_STREAM;
/* af */
hints.ai_family = NIL_P(af) ? PF_UNSPEC : rsock_family_arg(af);
- res = rsock_getaddrinfo(host, port, &hints, 0);
+ res = rsock_getaddrinfo(host, port, &hints, 0, Qnil);
sap = res->ai->ai_addr;
salen = res->ai->ai_addrlen;
}
@@ -1335,7 +1335,7 @@ sock_s_getnameinfo(int argc, VALUE *argv, VALUE _)
static VALUE
sock_s_pack_sockaddr_in(VALUE self, VALUE port, VALUE host)
{
- struct rb_addrinfo *res = rsock_addrinfo(host, port, AF_UNSPEC, 0, 0);
+ struct rb_addrinfo *res = rsock_addrinfo(host, port, AF_UNSPEC, 0, 0, Qnil);
VALUE addr = rb_str_new((char*)res->ai->ai_addr, res->ai->ai_addrlen);
rb_freeaddrinfo(res);
@@ -1856,6 +1856,67 @@ socket_s_ip_address_list(VALUE self)
#define socket_s_ip_address_list rb_f_notimplement
#endif
+/*
+ * call-seq:
+ * Socket.tcp_fast_fallback -> true or false
+ *
+ * Returns whether Happy Eyeballs Version 2 ({RFC 8305}[https://datatracker.ietf.org/doc/html/rfc8305]),
+ * which is provided starting from Ruby 3.4 when using TCPSocket.new and Socket.tcp,
+ * is enabled or disabled.
+ *
+ * If true, it is enabled for TCPSocket.new and Socket.tcp.
+ * (Note: Happy Eyeballs Version 2 is not provided when using TCPSocket.new on Windows.)
+ *
+ * If false, Happy Eyeballs Version 2 is disabled.
+ *
+ * For details on Happy Eyeballs Version 2,
+ * see {Socket.tcp_fast_fallback=}[rdoc-ref:Socket.tcp_fast_fallback=].
+ */
+VALUE socket_s_tcp_fast_fallback(VALUE self) {
+ return rb_ivar_get(rb_cSocket, tcp_fast_fallback);
+}
+
+/*
+ * call-seq:
+ * Socket.tcp_fast_fallback= -> true or false
+ *
+ * Enable or disable Happy Eyeballs Version 2 ({RFC 8305}[https://datatracker.ietf.org/doc/html/rfc8305])
+ * globally, which is provided starting from Ruby 3.4 when using TCPSocket.new and Socket.tcp.
+ *
+ * When set to true, the feature is enabled for both `TCPSocket.new` and `Socket.tcp`.
+ * (Note: This feature is not available when using TCPSocket.new on Windows.)
+ *
+ * When set to false, the behavior reverts to that of Ruby 3.3 or earlier.
+ *
+ * The default value is true if no value is explicitly set by calling this method.
+ * However, when the environment variable RUBY_TCP_NO_FAST_FALLBACK=1 is set,
+ * the default is false.
+ *
+ * To control the setting on a per-method basis, use the fast_fallback keyword argument for each method.
+ *
+ * === Happy Eyeballs Version 2
+ * Happy Eyeballs Version 2 ({RFC 8305}[https://datatracker.ietf.org/doc/html/rfc8305])
+ * is an algorithm designed to improve client socket connectivity.<br>
+ * It aims for more reliable and efficient connections by performing hostname resolution
+ * and connection attempts in parallel, instead of serially.
+ *
+ * Starting from Ruby 3.4, this method operates as follows with this algorithm:
+ *
+ * 1. Start resolving both IPv6 and IPv4 addresses concurrently.
+ * 2. Start connecting to the one of the addresses that are obtained first.<br>If IPv4 addresses are obtained first,
+ * the method waits 50 ms for IPv6 name resolution to prioritize IPv6 connections.
+ * 3. After starting a connection attempt, wait 250 ms for the connection to be established.<br>
+ * If no connection is established within this time, a new connection is started every 250 ms<br>
+ * until a connection is established or there are no more candidate addresses.<br>
+ * (Although RFC 8305 strictly specifies sorting addresses,<br>
+ * this method only alternates between IPv6 / IPv4 addresses due to the performance concerns)
+ * 4. Once a connection is established, all remaining connection attempts are canceled.
+ */
+VALUE socket_s_tcp_fast_fallback_set(VALUE self, VALUE value) {
+ rb_ivar_set(rb_cSocket, tcp_fast_fallback, value);
+ return value;
+}
+
void
Init_socket(void)
{
@@ -1984,6 +2045,16 @@ Init_socket(void)
rsock_init_socket_init();
+ const char *tcp_no_fast_fallback_config = getenv("RUBY_TCP_NO_FAST_FALLBACK");
+ VALUE fast_fallback_default;
+ if (tcp_no_fast_fallback_config == NULL || strcmp(tcp_no_fast_fallback_config, "0") == 0) {
+ fast_fallback_default = Qtrue;
+ } else {
+ fast_fallback_default = Qfalse;
+ }
+ tcp_fast_fallback = rb_intern_const("tcp_fast_fallback");
+ rb_ivar_set(rb_cSocket, tcp_fast_fallback, fast_fallback_default);
+
rb_define_method(rb_cSocket, "initialize", sock_initialize, -1);
rb_define_method(rb_cSocket, "connect", sock_connect, 1);
@@ -2027,6 +2098,9 @@ Init_socket(void)
rb_define_singleton_method(rb_cSocket, "ip_address_list", socket_s_ip_address_list, 0);
+ rb_define_singleton_method(rb_cSocket, "tcp_fast_fallback", socket_s_tcp_fast_fallback, 0);
+ rb_define_singleton_method(rb_cSocket, "tcp_fast_fallback=", socket_s_tcp_fast_fallback_set, 1);
+
#undef rb_intern
sym_wait_writable = ID2SYM(rb_intern("wait_writable"));
}
diff --git a/ext/socket/sockssocket.c b/ext/socket/sockssocket.c
index f263ac3804..30860ea257 100644
--- a/ext/socket/sockssocket.c
+++ b/ext/socket/sockssocket.c
@@ -30,11 +30,12 @@ socks_init(VALUE sock, VALUE host, VALUE port)
static int init = 0;
if (init == 0) {
- SOCKSinit("ruby");
+ char progname[] = "ruby";
+ SOCKSinit(progname);
init = 1;
}
- return rsock_init_inetsock(sock, host, port, Qnil, Qnil, INET_SOCKS, Qnil, Qnil);
+ return rsock_init_inetsock(sock, host, port, Qnil, Qnil, INET_SOCKS, Qnil, Qnil, Qnil, Qfalse, Qnil);
}
#ifdef SOCKS5
@@ -48,7 +49,7 @@ socks_s_close(VALUE sock)
rb_io_t *fptr;
GetOpenFile(sock, fptr);
- shutdown(fptr->fd, 2);
+ shutdown(fptr->fd, SHUT_RDWR);
return rb_io_close(sock);
}
#endif
diff --git a/ext/socket/tcpserver.c b/ext/socket/tcpserver.c
index 04e5a0bb51..0069f3c703 100644
--- a/ext/socket/tcpserver.c
+++ b/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, Qnil, Qnil);
+ return rsock_init_inetsock(sock, hostname, port, Qnil, Qnil, INET_SERVER, Qnil, Qnil, Qnil, Qfalse, Qnil);
}
/*
diff --git a/ext/socket/tcpsocket.c b/ext/socket/tcpsocket.c
index 03787272f3..7ce536e0af 100644
--- a/ext/socket/tcpsocket.c
+++ b/ext/socket/tcpsocket.c
@@ -12,13 +12,31 @@
/*
* call-seq:
- * TCPSocket.new(remote_host, remote_port, local_host=nil, local_port=nil, connect_timeout: nil)
+ * TCPSocket.new(remote_host, remote_port, local_host=nil, local_port=nil, resolv_timeout: nil, connect_timeout: nil, open_timeout: nil, fast_fallback: true)
*
* 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.
+ * Starting from Ruby 3.4, this method operates according to the
+ * Happy Eyeballs Version 2 ({RFC 8305}[https://datatracker.ietf.org/doc/html/rfc8305])
+ * algorithm by default, except on Windows.
+ *
+ * For details on Happy Eyeballs Version 2,
+ * see {Socket.tcp_fast_fallback=}[rdoc-ref:Socket.tcp_fast_fallback=].
+ *
+ * To make it behave the same as in Ruby 3.3 and earlier,
+ * explicitly specify the option fast_fallback:false.
+ * Or, setting Socket.tcp_fast_fallback=false will disable
+ * Happy Eyeballs Version 2 not only for this method but for all Socket globally.
+ *
+ * When using TCPSocket.new on Windows, Happy Eyeballs Version 2 is not provided,
+ * and it behaves the same as in Ruby 3.3 and earlier.
+ *
+ * [:resolv_timeout] Specifies the timeout in seconds from when the hostname resolution starts.
+ * [:connect_timeout] This method sequentially attempts connecting to all candidate destination addresses.<br>The +connect_timeout+ specifies the timeout in seconds from the start of the connection attempt to the last candidate.<br>By default, all connection attempts continue until the timeout occurs.<br>When +fast_fallback:false+ is explicitly specified,<br>a timeout is set for each connection attempt and any connection attempt that exceeds its timeout will be canceled.
+ * [:open_timeout] Specifies the timeout in seconds from the start of the method execution.<br>If this timeout is reached while there are still addresses that have not yet been attempted for connection, no further attempts will be made.<br>If this option is specified together with other timeout options, an +ArgumentError+ will be raised.
+ * [:fast_fallback] Enables the Happy Eyeballs Version 2 algorithm (enabled by default).
*/
static VALUE
tcp_init(int argc, VALUE *argv, VALUE sock)
@@ -26,28 +44,43 @@ 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];
+ static ID keyword_ids[5];
+ VALUE kwargs[5];
VALUE resolv_timeout = Qnil;
VALUE connect_timeout = Qnil;
+ VALUE open_timeout = Qnil;
+ VALUE fast_fallback = Qnil;
+ VALUE test_mode_settings = Qnil;
if (!keyword_ids[0]) {
CONST_ID(keyword_ids[0], "resolv_timeout");
CONST_ID(keyword_ids[1], "connect_timeout");
+ CONST_ID(keyword_ids[2], "open_timeout");
+ CONST_ID(keyword_ids[3], "fast_fallback");
+ CONST_ID(keyword_ids[4], "test_mode_settings");
}
rb_scan_args(argc, argv, "22:", &remote_host, &remote_serv,
&local_host, &local_serv, &opt);
if (!NIL_P(opt)) {
- rb_get_kwargs(opt, keyword_ids, 0, 2, kwargs);
+ rb_get_kwargs(opt, keyword_ids, 0, 5, kwargs);
if (kwargs[0] != Qundef) { resolv_timeout = kwargs[0]; }
if (kwargs[1] != Qundef) { connect_timeout = kwargs[1]; }
+ if (kwargs[2] != Qundef) { open_timeout = kwargs[2]; }
+ if (kwargs[3] != Qundef) { fast_fallback = kwargs[3]; }
+ if (kwargs[4] != Qundef) { test_mode_settings = kwargs[4]; }
+ }
+
+ if (fast_fallback == Qnil) {
+ fast_fallback = rb_ivar_get(rb_cSocket, tcp_fast_fallback);
+ if (fast_fallback == Qnil) fast_fallback = Qtrue;
}
return rsock_init_inetsock(sock, remote_host, remote_serv,
local_host, local_serv, INET_CLIENT,
- resolv_timeout, connect_timeout);
+ resolv_timeout, connect_timeout, open_timeout,
+ fast_fallback, test_mode_settings);
}
static VALUE
@@ -80,7 +113,7 @@ 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);
+ rsock_addrinfo(host, Qnil, AF_UNSPEC, SOCK_STREAM, AI_CANONNAME, Qnil);
return rsock_make_hostent(host, res, tcp_sockaddr);
}
diff --git a/ext/socket/udpsocket.c b/ext/socket/udpsocket.c
index 5224e48a96..b2bc925538 100644
--- a/ext/socket/udpsocket.c
+++ b/ext/socket/udpsocket.c
@@ -45,22 +45,18 @@ udp_init(int argc, VALUE *argv, VALUE sock)
struct udp_arg
{
+ VALUE io;
struct rb_addrinfo *res;
- rb_io_t *fptr;
};
static VALUE
udp_connect_internal(VALUE v)
{
struct udp_arg *arg = (void *)v;
- rb_io_t *fptr;
- int fd;
struct addrinfo *res;
- 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, NULL) >= 0) {
+ if (rsock_connect(arg->io, res->ai_addr, res->ai_addrlen, 0, RUBY_IO_TIMEOUT_DEFAULT) >= 0) {
return Qtrue;
}
}
@@ -84,16 +80,17 @@ udp_connect_internal(VALUE v)
*
*/
static VALUE
-udp_connect(VALUE sock, VALUE host, VALUE port)
+udp_connect(VALUE self, VALUE host, VALUE port)
{
- struct udp_arg arg;
- VALUE ret;
+ struct udp_arg arg = {.io = self};
+
+ arg.res = rsock_addrinfo(host, port, rsock_fd_family(rb_io_descriptor(self)), SOCK_DGRAM, 0, Qnil);
+
+ int result = (int)rb_ensure(udp_connect_internal, (VALUE)&arg, rsock_freeaddrinfo, (VALUE)arg.res);
+ if (!result) {
+ rsock_sys_fail_host_port("connect(2)", host, port);
+ }
- GetOpenFile(sock, arg.fptr);
- arg.res = rsock_addrinfo(host, port, rsock_fd_family(arg.fptr->fd), SOCK_DGRAM, 0);
- ret = rb_ensure(udp_connect_internal, (VALUE)&arg,
- rsock_freeaddrinfo, (VALUE)arg.res);
- if (!ret) rsock_sys_fail_host_port("connect(2)", host, port);
return INT2FIX(0);
}
@@ -101,14 +98,13 @@ static VALUE
udp_bind_internal(VALUE v)
{
struct udp_arg *arg = (void *)v;
- rb_io_t *fptr;
- int fd;
struct addrinfo *res;
- rb_io_check_closed(fptr = arg->fptr);
- fd = fptr->fd;
+ rb_io_t *fptr;
+ RB_IO_POINTER(arg->io, fptr);
+
for (res = arg->res->ai; res; res = res->ai_next) {
- if (bind(fd, res->ai_addr, res->ai_addrlen) < 0) {
+ if (bind(fptr->fd, res->ai_addr, res->ai_addrlen) < 0) {
continue;
}
return Qtrue;
@@ -129,22 +125,23 @@ udp_bind_internal(VALUE v)
*
*/
static VALUE
-udp_bind(VALUE sock, VALUE host, VALUE port)
+udp_bind(VALUE self, VALUE host, VALUE port)
{
- struct udp_arg arg;
- VALUE ret;
+ struct udp_arg arg = {.io = self};
+
+ arg.res = rsock_addrinfo(host, port, rsock_fd_family(rb_io_descriptor(self)), SOCK_DGRAM, 0, Qnil);
+
+ VALUE result = rb_ensure(udp_bind_internal, (VALUE)&arg, rsock_freeaddrinfo, (VALUE)arg.res);
+ if (!result) {
+ rsock_sys_fail_host_port("bind(2)", host, port);
+ }
- GetOpenFile(sock, arg.fptr);
- arg.res = rsock_addrinfo(host, port, rsock_fd_family(arg.fptr->fd), SOCK_DGRAM, 0);
- ret = rb_ensure(udp_bind_internal, (VALUE)&arg,
- rsock_freeaddrinfo, (VALUE)arg.res);
- if (!ret) rsock_sys_fail_host_port("bind(2)", host, port);
return INT2FIX(0);
}
struct udp_send_arg {
- struct rb_addrinfo *res;
rb_io_t *fptr;
+ struct rb_addrinfo *res;
struct rsock_send_arg sarg;
};
@@ -166,7 +163,7 @@ udp_send_internal(VALUE v)
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);
+ ssize_t n = (ssize_t)rb_io_blocking_region(fptr, rsock_sendto_blocking, &arg->sarg);
if (n >= 0) return RB_SSIZE2NUM(n);
@@ -215,7 +212,7 @@ udp_send(int argc, VALUE *argv, VALUE sock)
GetOpenFile(sock, arg.fptr);
arg.sarg.fd = arg.fptr->fd;
arg.sarg.flags = NUM2INT(flags);
- arg.res = rsock_addrinfo(host, port, rsock_fd_family(arg.fptr->fd), SOCK_DGRAM, 0);
+ arg.res = rsock_addrinfo(host, port, rsock_fd_family(arg.fptr->fd), SOCK_DGRAM, 0, Qnil);
ret = rb_ensure(udp_send_internal, (VALUE)&arg,
rsock_freeaddrinfo, (VALUE)arg.res);
if (!ret) rsock_sys_fail_host_port("sendto(2)", host, port);
diff --git a/ext/socket/unixsocket.c b/ext/socket/unixsocket.c
index a8475e3e60..2ec9376074 100644
--- a/ext/socket/unixsocket.c
+++ b/ext/socket/unixsocket.c
@@ -14,15 +14,14 @@
struct unixsock_arg {
struct sockaddr_un *sockaddr;
socklen_t sockaddrlen;
- int fd;
+ VALUE io;
};
static VALUE
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, NULL);
+ return (VALUE)rsock_connect(arg->io, (struct sockaddr*)arg->sockaddr, arg->sockaddrlen, 0, RUBY_IO_TIMEOUT_DEFAULT);
}
static VALUE
@@ -43,15 +42,16 @@ unixsock_path_value(VALUE path)
}
}
#endif
+ path = rb_get_path(path);
#ifdef _WIN32
/* UNIXSocket requires UTF-8 per spec. */
path = rb_str_export_to_enc(path, rb_utf8_encoding());
#endif
- return rb_get_path(path);
+ return path;
}
VALUE
-rsock_init_unixsock(VALUE sock, VALUE path, int server)
+rsock_init_unixsock(VALUE self, VALUE path, int server)
{
struct sockaddr_un sockaddr;
socklen_t sockaddrlen;
@@ -73,43 +73,46 @@ rsock_init_unixsock(VALUE sock, VALUE path, int server)
rsock_sys_fail_path("socket(2)", path);
}
+ VALUE io = rsock_init_sock(self, fd);
+ RB_IO_POINTER(io, fptr);
+
if (server) {
status = bind(fd, (struct sockaddr*)&sockaddr, sockaddrlen);
}
else {
- int prot;
+ int error_tag;
struct unixsock_arg arg;
arg.sockaddr = &sockaddr;
arg.sockaddrlen = sockaddrlen;
- arg.fd = fd;
- status = (int)rb_protect(unixsock_connect_internal, (VALUE)&arg, &prot);
- if (prot) {
- close(fd);
- rb_jump_tag(prot);
+ arg.io = io;
+
+ status = (int)rb_protect(unixsock_connect_internal, (VALUE)&arg, &error_tag);
+
+ if (error_tag) {
+ rb_io_close(io);
+ rb_jump_tag(error_tag);
}
}
if (status < 0) {
int e = errno;
- close(fd);
+ rb_io_close(io);
rsock_syserr_fail_path(e, "connect(2)", path);
}
if (server) {
if (listen(fd, SOMAXCONN) < 0) {
int e = errno;
- close(fd);
+ rb_io_close(io);
rsock_syserr_fail_path(e, "listen(2)", path);
}
}
- rsock_init_sock(sock, fd);
if (server) {
- GetOpenFile(sock, fptr);
fptr->pathv = rb_str_new_frozen(path);
}
- return sock;
+ return io;
}
/*
@@ -125,9 +128,9 @@ rsock_init_unixsock(VALUE sock, VALUE path, int server)
*
*/
static VALUE
-unix_init(VALUE sock, VALUE path)
+unix_init(VALUE self, VALUE path)
{
- return rsock_init_unixsock(sock, path, 0);
+ return rsock_init_unixsock(self, path, 0);
}
/*
@@ -288,7 +291,7 @@ unix_send_io(VALUE sock, VALUE val)
#endif
arg.fd = fptr->fd;
- while ((int)BLOCKING_REGION_FD(sendmsg_blocking, &arg) == -1) {
+ while ((int)rb_io_blocking_region(fptr, sendmsg_blocking, &arg) == -1) {
if (!rb_io_wait_writable(arg.fd))
rsock_sys_fail_path("sendmsg(2)", fptr->pathv);
}
@@ -390,7 +393,7 @@ retry:
#endif
arg.fd = fptr->fd;
- while ((int)BLOCKING_REGION_FD(recvmsg_blocking, &arg) == -1) {
+ while ((int)rb_io_blocking_region(fptr, recvmsg_blocking, &arg) == -1) {
int e = errno;
if (e == EMSGSIZE && !(gc_reason & GC_REASON_EMSGSIZE)) {
/* FreeBSD gets here when we're out of FDs */
diff --git a/ext/stringio/depend b/ext/stringio/depend
index b9fba7e9fa..3a82ad0a11 100644
--- a/ext/stringio/depend
+++ b/ext/stringio/depend
@@ -138,6 +138,7 @@ 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/set.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
@@ -171,5 +172,6 @@ stringio.o: $(hdrdir)/ruby/oniguruma.h
stringio.o: $(hdrdir)/ruby/ruby.h
stringio.o: $(hdrdir)/ruby/st.h
stringio.o: $(hdrdir)/ruby/subst.h
+stringio.o: $(hdrdir)/ruby/version.h
stringio.o: stringio.c
# AUTOGENERATED DEPENDENCIES END
diff --git a/ext/stringio/extconf.rb b/ext/stringio/extconf.rb
index 553732f79c..0089766983 100644
--- a/ext/stringio/extconf.rb
+++ b/ext/stringio/extconf.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: false
require 'mkmf'
if RUBY_ENGINE == 'ruby'
+ have_type("rb_io_mode_t", "ruby/io.h")
+
create_makefile('stringio')
else
File.write('Makefile', dummy_makefile("").join)
diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c
index c149811e05..cc2294a795 100644
--- a/ext/stringio/stringio.c
+++ b/ext/stringio/stringio.c
@@ -13,13 +13,14 @@
**********************************************************************/
static const char *const
-STRINGIO_VERSION = "3.1.1";
+STRINGIO_VERSION = "3.2.1.dev";
#include <stdbool.h>
#include "ruby.h"
#include "ruby/io.h"
#include "ruby/encoding.h"
+#include "ruby/version.h"
#if defined(HAVE_FCNTL_H) || defined(_WIN32)
#include <fcntl.h>
#elif defined(HAVE_SYS_FCNTL_H)
@@ -35,12 +36,29 @@ STRINGIO_VERSION = "3.1.1";
# define rb_class_new_instance_kw(argc, argv, klass, kw_splat) rb_class_new_instance(argc, argv, klass)
#endif
+static inline bool
+str_chilled_p(VALUE str)
+{
+#if (RUBY_API_VERSION_MAJOR == 3 && RUBY_API_VERSION_MINOR >= 4) || RUBY_API_VERSION_MAJOR >= 4
+ // Do not attempt to modify chilled strings on Ruby 3.4+
+ // RUBY_FL_USER2 == STR_CHILLED_LITERAL
+ // RUBY_FL_USER3 == STR_CHILLED_SYMBOL_TO_S
+ return FL_TEST_RAW(str, RUBY_FL_USER2 | RUBY_FL_USER3);
+#else
+ return false;
+#endif
+}
+
+#ifndef HAVE_TYPE_RB_IO_MODE_T
+typedef int rb_io_mode_t;
+#endif
+
struct StringIO {
VALUE string;
rb_encoding *enc;
long pos;
long lineno;
- int flags;
+ rb_io_mode_t flags;
int count;
};
@@ -180,6 +198,21 @@ check_modifiable(struct StringIO *ptr)
else if (OBJ_FROZEN_RAW(ptr->string)) {
rb_raise(rb_eIOError, "not modifiable string");
}
+ else {
+ rb_str_modify(ptr->string);
+ }
+}
+
+static inline bool
+outside_p(struct StringIO *ptr, long pos)
+{
+ return NIL_P(ptr->string) || pos >= RSTRING_LEN(ptr->string);
+}
+
+static inline bool
+eos_p(struct StringIO *ptr)
+{
+ return outside_p(ptr, ptr->pos);
}
static VALUE
@@ -192,17 +225,32 @@ strio_s_allocate(VALUE klass)
* call-seq:
* StringIO.new(string = '', mode = 'r+') -> new_stringio
*
- * Note that +mode+ defaults to <tt>'r'</tt> if +string+ is frozen.
- *
* Returns a new \StringIO instance formed from +string+ and +mode+;
- * see {Access Modes}[rdoc-ref:File@Access+Modes]:
+ * the instance should be closed when no longer needed:
*
- * strio = StringIO.new # => #<StringIO>
+ * strio = StringIO.new
+ * strio.string # => ""
+ * strio.closed_read? # => false
+ * strio.closed_write? # => false
* strio.close
*
- * The instance should be closed when no longer needed.
+ * If +string+ is frozen, the default +mode+ is <tt>'r'</tt>:
*
- * Related: StringIO.open (accepts block; closes automatically).
+ * strio = StringIO.new('foo'.freeze)
+ * strio.string # => "foo"
+ * strio.closed_read? # => false
+ * strio.closed_write? # => true
+ * strio.close
+ *
+ * Argument +mode+ must be a valid
+ * {Access Mode}[rdoc-ref:File@Access+Modes],
+ * which may be a string or an integer constant:
+ *
+ * StringIO.new('foo', 'w+')
+ * StringIO.new('foo', File::RDONLY)
+ *
+ * Related: StringIO.open
+ * (passes the \StringIO object to the block; closes the object automatically on block exit).
*/
static VALUE
strio_initialize(int argc, VALUE *argv, VALUE self)
@@ -337,23 +385,20 @@ strio_finalize(VALUE self)
/*
* call-seq:
- * StringIO.open(string = '', mode = 'r+') {|strio| ... }
+ * StringIO.open(string = '', mode = 'r+') -> new_stringio
+ * StringIO.open(string = '', mode = 'r+') {|strio| ... } -> object
*
- * Note that +mode+ defaults to <tt>'r'</tt> if +string+ is frozen.
+ * Creates new \StringIO instance by calling <tt>StringIO.new(string, mode)</tt>.
*
- * Creates a new \StringIO instance formed from +string+ and +mode+;
- * see {Access Modes}[rdoc-ref:File@Access+Modes].
- *
- * With no block, returns the new instance:
+ * With no block given, returns the new instance:
*
* strio = StringIO.open # => #<StringIO>
*
- * With a block, calls the block with the new instance
+ * With a block given, calls the block with the new instance
* and returns the block's value;
- * closes the instance on block exit.
+ * closes the instance on block exit:
*
- * StringIO.open {|strio| p strio }
- * # => #<StringIO>
+ * StringIO.open('foo') {|strio| strio.string.upcase } # => "FOO"
*
* Related: StringIO.new.
*/
@@ -379,7 +424,7 @@ strio_s_new(int argc, VALUE *argv, VALUE klass)
}
/*
- * Returns +false+. Just for compatibility to IO.
+ * Returns +false+; for compatibility with IO.
*/
static VALUE
strio_false(VALUE self)
@@ -389,7 +434,7 @@ strio_false(VALUE self)
}
/*
- * Returns +nil+. Just for compatibility to IO.
+ * Returns +nil+; for compatibility with IO.
*/
static VALUE
strio_nil(VALUE self)
@@ -399,7 +444,7 @@ strio_nil(VALUE self)
}
/*
- * Returns an object itself. Just for compatibility to IO.
+ * Returns +self+; for compatibility with IO.
*/
static VALUE
strio_self(VALUE self)
@@ -409,7 +454,7 @@ strio_self(VALUE self)
}
/*
- * Returns 0. Just for compatibility to IO.
+ * Returns 0; for compatibility with IO.
*/
static VALUE
strio_0(VALUE self)
@@ -469,7 +514,7 @@ strio_get_string(VALUE self)
* call-seq:
* string = other_string -> other_string
*
- * Assigns the underlying string as +other_string+, and sets position to zero;
+ * Replaces the stored string with +other_string+, and sets the position to zero;
* returns +other_string+:
*
* StringIO.open('foo') do |strio|
@@ -483,7 +528,7 @@ strio_get_string(VALUE self)
* "foo"
* "bar"
*
- * Related: StringIO#string (returns the underlying string).
+ * Related: StringIO#string (returns the stored string).
*/
static VALUE
strio_set_string(VALUE self, VALUE string)
@@ -504,11 +549,16 @@ strio_set_string(VALUE self, VALUE string)
* call-seq:
* close -> nil
*
- * Closes +self+ for both reading and writing.
+ * Closes +self+ for both reading and writing; returns +nil+:
*
- * Raises IOError if reading or writing is attempted.
+ * strio = StringIO.new
+ * strio.closed? # => false
+ * strio.close # => nil
+ * strio.closed? # => true
+ * strio.read # Raises IOError: not opened for reading
+ * strio.write # Raises IOError: not opened for writing
*
- * Related: StringIO#close_read, StringIO#close_write.
+ * Related: StringIO#close_read, StringIO#close_write, StringIO.closed?.
*/
static VALUE
strio_close(VALUE self)
@@ -522,9 +572,16 @@ strio_close(VALUE self)
* call-seq:
* close_read -> nil
*
- * Closes +self+ for reading; closed-write setting remains unchanged.
+ * Closes +self+ for reading;
+ * closed-write setting remains unchanged;
+ * returns +nil+:
*
- * Raises IOError if reading is attempted.
+ * strio = StringIO.new
+ * strio.closed_read? # => false
+ * strio.close_read # => nil
+ * strio.closed_read? # => true
+ * strio.closed_write? # => false
+ * strio.read # Raises IOError: not opened for reading
*
* Related: StringIO#close, StringIO#close_write.
*/
@@ -543,11 +600,16 @@ strio_close_read(VALUE self)
* call-seq:
* close_write -> nil
*
- * Closes +self+ for writing; closed-read setting remains unchanged.
+ * Closes +self+ for writing; closed-read setting remains unchanged; returns +nil+:
*
- * Raises IOError if writing is attempted.
+ * strio = StringIO.new
+ * strio.closed_write? # => false
+ * strio.close_write # => nil
+ * strio.closed_write? # => true
+ * strio.closed_read? # => false
+ * strio.write('foo') # Raises IOError: not opened for writing
*
- * Related: StringIO#close, StringIO#close_read.
+ * Related: StringIO#close, StringIO#close_read, StringIO#closed_write?.
*/
static VALUE
strio_close_write(VALUE self)
@@ -564,8 +626,16 @@ strio_close_write(VALUE self)
* call-seq:
* closed? -> true or false
*
- * Returns +true+ if +self+ is closed for both reading and writing,
- * +false+ otherwise.
+ * Returns whether +self+ is closed for both reading and writing:
+ *
+ * strio = StringIO.new
+ * strio.closed? # => false # Open for reading and writing.
+ * strio.close_read
+ * strio.closed? # => false # Still open for writing.
+ * strio.close_write
+ * strio.closed? # => true # Now closed for both.
+ *
+ * Related: StringIO.closed_read?, StringIO.closed_write?.
*/
static VALUE
strio_closed(VALUE self)
@@ -579,7 +649,14 @@ strio_closed(VALUE self)
* call-seq:
* closed_read? -> true or false
*
- * Returns +true+ if +self+ is closed for reading, +false+ otherwise.
+ * Returns whether +self+ is closed for reading:
+ *
+ * strio = StringIO.new
+ * strio.closed_read? # => false
+ * strio.close_read
+ * strio.closed_read? # => true
+ *
+ * Related: StringIO#closed?, StringIO#closed_write?, StringIO#close_read.
*/
static VALUE
strio_closed_read(VALUE self)
@@ -593,7 +670,14 @@ strio_closed_read(VALUE self)
* call-seq:
* closed_write? -> true or false
*
- * Returns +true+ if +self+ is closed for writing, +false+ otherwise.
+ * Returns whether +self+ is closed for writing:
+ *
+ * strio = StringIO.new
+ * strio.closed_write? # => false
+ * strio.close_write
+ * strio.closed_write? # => true
+ *
+ * Related: StringIO#close_write, StringIO#closed?, StringIO#closed_read?.
*/
static VALUE
strio_closed_write(VALUE self)
@@ -607,19 +691,26 @@ static struct StringIO *
strio_to_read(VALUE self)
{
struct StringIO *ptr = readable(self);
- if (NIL_P(ptr->string)) return NULL;
- if (ptr->pos < RSTRING_LEN(ptr->string)) return ptr;
- return NULL;
+ if (eos_p(ptr)) return NULL;
+ return ptr;
}
/*
* call-seq:
* eof? -> true or false
*
- * Returns +true+ if positioned at end-of-stream, +false+ otherwise;
- * see {Position}[rdoc-ref:IO@Position].
+ * Returns whether +self+ is positioned at end-of-stream:
*
- * Raises IOError if the stream is not opened for reading.
+ * strio = StringIO.new('foo')
+ * strio.pos # => 0
+ * strio.eof? # => false
+ * strio.read # => "foo"
+ * strio.pos # => 3
+ * strio.eof? # => true
+ * strio.close_read
+ * strio.eof? # Raises IOError: not opened for reading
+ *
+ * Related: StringIO#pos.
*/
static VALUE
strio_eof(VALUE self)
@@ -656,7 +747,7 @@ strio_copy(VALUE copy, VALUE orig)
* lineno -> current_line_number
*
* Returns the current line number in +self+;
- * see {Line Number}[rdoc-ref:IO@Line+Number].
+ * see {Line Number}[rdoc-ref:StringIO@Line+Number].
*/
static VALUE
strio_get_lineno(VALUE self)
@@ -669,7 +760,7 @@ strio_get_lineno(VALUE self)
* lineno = new_line_number -> new_line_number
*
* Sets the current line number in +self+ to the given +new_line_number+;
- * see {Line Number}[rdoc-ref:IO@Line+Number].
+ * see {Line Number}[rdoc-ref:StringIO@Line+Number].
*/
static VALUE
strio_set_lineno(VALUE self, VALUE lineno)
@@ -683,7 +774,7 @@ strio_set_lineno(VALUE self, VALUE lineno)
* binmode -> self
*
* Sets the data mode in +self+ to binary mode;
- * see {Data Mode}[rdoc-ref:File@Data+Mode].
+ * see {Data Mode}[rdoc-ref:StringIO@Data+Mode].
*
*/
static VALUE
@@ -744,7 +835,7 @@ strio_reopen(int argc, VALUE *argv, VALUE self)
* pos -> stream_position
*
* Returns the current position (in bytes);
- * see {Position}[rdoc-ref:IO@Position].
+ * see {Position}[rdoc-ref:StringIO@Position].
*/
static VALUE
strio_get_pos(VALUE self)
@@ -757,7 +848,7 @@ strio_get_pos(VALUE self)
* pos = new_position -> new_position
*
* Sets the current position (in bytes);
- * see {Position}[rdoc-ref:IO@Position].
+ * see {Position}[rdoc-ref:StringIO@Position].
*/
static VALUE
strio_set_pos(VALUE self, VALUE pos)
@@ -792,9 +883,9 @@ strio_rewind(VALUE self)
* call-seq:
* seek(offset, whence = SEEK_SET) -> 0
*
- * Sets the current position to the given integer +offset+ (in bytes),
+ * Sets the position to the given integer +offset+ (in bytes),
* with respect to a given constant +whence+;
- * see {Position}[rdoc-ref:IO@Position].
+ * see {IO#seek}[rdoc-ref:IO#seek].
*/
static VALUE
strio_seek(int argc, VALUE *argv, VALUE self)
@@ -816,7 +907,11 @@ strio_seek(int argc, VALUE *argv, VALUE self)
offset = ptr->pos;
break;
case 2:
- offset = RSTRING_LEN(ptr->string);
+ if (NIL_P(ptr->string)) {
+ offset = 0;
+ } else {
+ offset = RSTRING_LEN(ptr->string);
+ }
break;
default:
error_inval("invalid whence");
@@ -849,10 +944,9 @@ strio_get_sync(VALUE self)
* call-seq:
* each_byte {|byte| ... } -> self
*
- * With a block given, calls the block with each remaining byte in the stream;
- * see {Byte IO}[rdoc-ref:IO@Byte+IO].
+ * :include: stringio/each_byte.rdoc
*
- * With no block given, returns an enumerator.
+ * Related: StringIO#each_char, StringIO#each_codepoint, StringIO#each_line.
*/
static VALUE
strio_each_byte(VALUE self)
@@ -870,10 +964,10 @@ strio_each_byte(VALUE self)
/*
* call-seq:
- * getc -> character or nil
+ * getc -> character, byte, or nil
+ *
+ * :include: stringio/getc.rdoc
*
- * Reads and returns the next character from the stream;
- * see {Character IO}[rdoc-ref:IO@Character+IO].
*/
static VALUE
strio_getc(VALUE self)
@@ -885,7 +979,7 @@ strio_getc(VALUE self)
int len;
char *p;
- if (NIL_P(str) || pos >= RSTRING_LEN(str)) {
+ if (eos_p(ptr)) {
return Qnil;
}
p = RSTRING_PTR(str)+pos;
@@ -896,17 +990,17 @@ strio_getc(VALUE self)
/*
* call-seq:
- * getbyte -> byte or nil
+ * getbyte -> integer or nil
+ *
+ * :include: stringio/getbyte.rdoc
*
- * Reads and returns the next 8-bit byte from the stream;
- * see {Byte IO}[rdoc-ref:IO@Byte+IO].
*/
static VALUE
strio_getbyte(VALUE self)
{
struct StringIO *ptr = readable(self);
int c;
- if (NIL_P(ptr->string) || ptr->pos >= RSTRING_LEN(ptr->string)) {
+ if (eos_p(ptr)) {
return Qnil;
}
c = RSTRING_PTR(ptr->string)[ptr->pos++];
@@ -930,6 +1024,18 @@ strio_extend(struct StringIO *ptr, long pos, long len)
}
}
+static void
+strio_unget_string(struct StringIO *ptr, VALUE c)
+{
+ const char *cp = NULL;
+ long cl = RSTRING_LEN(c);
+ if (cl > 0) {
+ if (c != ptr->string) cp = RSTRING_PTR(c);
+ strio_unget_bytes(ptr, cp, cl);
+ RB_GC_GUARD(c);
+ }
+}
+
/*
* call-seq:
* ungetc(character) -> nil
@@ -952,19 +1058,22 @@ strio_ungetc(VALUE self, VALUE c)
enc = rb_enc_get(ptr->string);
len = rb_enc_codelen(cc, enc);
- if (len <= 0) rb_enc_uint_chr(cc, enc);
+ if (len <= 0) {
+ rb_enc_uint_chr(cc, enc); /* to raise an exception */
+ UNREACHABLE;
+ }
rb_enc_mbcput(cc, buf, enc);
return strio_unget_bytes(ptr, buf, len);
}
else {
- SafeStringValue(c);
+ StringValue(c);
+ if (RSTRING_LEN(c) == 0) return Qnil;
enc = rb_enc_get(ptr->string);
enc2 = rb_enc_get(c);
if (enc != enc2 && enc != rb_ascii8bit_encoding()) {
c = rb_str_conv_enc(c, enc2, enc);
}
- strio_unget_bytes(ptr, RSTRING_PTR(c), RSTRING_LEN(c));
- RB_GC_GUARD(c);
+ strio_unget_string(ptr, c);
return Qnil;
}
}
@@ -991,13 +1100,8 @@ strio_ungetbyte(VALUE self, VALUE c)
strio_unget_bytes(ptr, &cc, 1);
}
else {
- long cl;
- SafeStringValue(c);
- cl = RSTRING_LEN(c);
- if (cl > 0) {
- strio_unget_bytes(ptr, RSTRING_PTR(c), cl);
- RB_GC_GUARD(c);
- }
+ StringValue(c);
+ strio_unget_string(ptr, c);
}
return Qnil;
}
@@ -1028,7 +1132,7 @@ strio_unget_bytes(struct StringIO *ptr, const char *cp, long cl)
if (rest > cl) memset(s + len, 0, rest - cl);
pos -= cl;
}
- memcpy(s + pos, cp, cl);
+ memcpy(s + pos, (cp ? cp : s), cl);
ptr->pos = pos;
return Qnil;
}
@@ -1065,12 +1169,11 @@ strio_readbyte(VALUE self)
/*
* call-seq:
- * each_char {|c| ... } -> self
+ * each_char {|char| ... } -> self
*
- * With a block given, calls the block with each remaining character in the stream;
- * see {Character IO}[rdoc-ref:IO@Character+IO].
+ * :include: stringio/each_char.rdoc
*
- * With no block given, returns an enumerator.
+ * Related: StringIO#each_byte, StringIO#each_codepoint, StringIO#each_line.
*/
static VALUE
strio_each_char(VALUE self)
@@ -1089,10 +1192,9 @@ strio_each_char(VALUE self)
* call-seq:
* each_codepoint {|codepoint| ... } -> self
*
- * With a block given, calls the block with each remaining codepoint in the stream;
- * see {Codepoint IO}[rdoc-ref:IO@Codepoint+IO].
+ * :include: stringio/each_codepoint.rdoc
*
- * With no block given, returns an enumerator.
+ * Related: StringIO#each_byte, StringIO#each_char, StringIO#each_line.
*/
static VALUE
strio_each_codepoint(VALUE self)
@@ -1326,9 +1428,8 @@ strio_getline(struct getline_arg *arg, struct StringIO *ptr)
* gets(limit, chomp: false) -> string or nil
* gets(sep, limit, chomp: false) -> string or nil
*
- * Reads and returns a line from the stream;
- * assigns the return value to <tt>$_</tt>;
- * see {Line IO}[rdoc-ref:IO@Line+IO].
+ * :include: stringio/gets.rdoc
+ *
*/
static VALUE
strio_gets(int argc, VALUE *argv, VALUE self)
@@ -1365,15 +1466,15 @@ strio_readline(int argc, VALUE *argv, VALUE self)
}
/*
+ * :markup: markdown
+ *
* call-seq:
* each_line(sep = $/, chomp: false) {|line| ... } -> self
* each_line(limit, chomp: false) {|line| ... } -> self
* each_line(sep, limit, chomp: false) {|line| ... } -> self
*
- * Calls the block with each remaining line read from the stream;
- * does nothing if already at end-of-file;
- * returns +self+.
- * See {Line IO}[rdoc-ref:IO@Line+IO].
+ * :include: stringio/each_line.md
+ *
*/
static VALUE
strio_each(int argc, VALUE *argv, VALUE self)
@@ -1514,9 +1615,10 @@ strio_write(VALUE self, VALUE str)
/*
* call-seq:
- * strio.putc(obj) -> obj
+ * putc(object) -> object
+ *
+ * :include: stringio/putc.rdoc
*
- * See IO#putc.
*/
static VALUE
strio_putc(VALUE self, VALUE ch)
@@ -1548,9 +1650,10 @@ strio_putc(VALUE self, VALUE ch)
/*
* call-seq:
- * strio.read([length [, outbuf]]) -> string, outbuf, or nil
+ * read(maxlen = nil, out_string = nil) → new_string, out_string, or nil
+ *
+ * :include: stringio/read.rdoc
*
- * See IO#read.
*/
static VALUE
strio_read(int argc, VALUE *argv, VALUE self)
@@ -1574,10 +1677,9 @@ strio_read(int argc, VALUE *argv, VALUE self)
if (len < 0) {
rb_raise(rb_eArgError, "negative length %ld given", len);
}
- if (len > 0 &&
- (NIL_P(ptr->string) || ptr->pos >= RSTRING_LEN(ptr->string))) {
+ if (eos_p(ptr)) {
if (!NIL_P(str)) rb_str_resize(str, 0);
- return Qnil;
+ return len > 0 ? Qnil : rb_str_new(0, 0);
}
binary = 1;
break;
@@ -1623,10 +1725,10 @@ strio_read(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * pread(maxlen, offset) -> string
- * pread(maxlen, offset, out_string) -> string
+ * pread(maxlen, offset, out_string = nil) -> new_string or out_string
+ *
+ * :include: stringio/pread.rdoc
*
- * See IO#pread.
*/
static VALUE
strio_pread(int argc, VALUE *argv, VALUE self)
@@ -1653,7 +1755,7 @@ strio_pread(int argc, VALUE *argv, VALUE self)
struct StringIO *ptr = readable(self);
- if (offset >= RSTRING_LEN(ptr->string)) {
+ if (outside_p(ptr, offset)) {
rb_eof_error();
}
@@ -1743,10 +1845,10 @@ strio_syswrite_nonblock(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * strio.length -> integer
- * strio.size -> integer
+ * size -> integer
+ *
+ * :include: stringio/size.rdoc
*
- * Returns the size of the buffer string.
*/
static VALUE
strio_size(VALUE self)
@@ -1784,12 +1886,20 @@ strio_truncate(VALUE self, VALUE len)
}
/*
- * call-seq:
- * strio.external_encoding => encoding
+ * call-seq:
+ * external_encoding -> encoding or nil
+ *
+ * Returns an Encoding object that represents the encoding of the string;
+ * see {Encodings}[rdoc-ref:StringIO@Encodings]:
+ *
+ * strio = StringIO.new('foo')
+ * strio.external_encoding # => #<Encoding:UTF-8>
+ *
+ * Returns +nil+ if +self+ has no string and is in write mode:
+ *
+ * strio = StringIO.new(nil, 'w+')
+ * strio.external_encoding # => nil
*
- * Returns the Encoding object that represents the encoding of the file.
- * If the stream is write mode and no encoding is specified, returns
- * +nil+.
*/
static VALUE
@@ -1801,10 +1911,9 @@ strio_external_encoding(VALUE self)
/*
* call-seq:
- * strio.internal_encoding => encoding
+ * internal_encoding -> nil
*
- * Returns the Encoding of the internal string if conversion is
- * specified. Otherwise returns +nil+.
+ * Returns +nil+; for compatibility with IO.
*/
static VALUE
@@ -1839,14 +1948,15 @@ strio_set_encoding(int argc, VALUE *argv, VALUE self)
enc = rb_find_encoding(ext_enc);
if (!enc) {
rb_io_enc_t convconfig;
- int oflags, fmode;
+ int oflags;
+ rb_io_mode_t fmode;
VALUE vmode = rb_str_append(rb_str_new_cstr("r:"), ext_enc);
rb_io_extract_modeenc(&vmode, 0, Qnil, &oflags, &fmode, &convconfig);
enc = convconfig.enc2;
}
}
ptr->enc = enc;
- if (!NIL_P(ptr->string) && WRITABLE(self)) {
+ if (!NIL_P(ptr->string) && WRITABLE(self) && !str_chilled_p(ptr->string)) {
rb_enc_associate(ptr->string, enc);
}
@@ -1872,16 +1982,9 @@ strio_set_encoding_by_bom(VALUE self)
}
/*
- * \IO streams for strings, with access similar to
- * {IO}[rdoc-ref:IO];
- * see {IO}[rdoc-ref:IO].
- *
- * === About the Examples
- *
- * Examples on this page assume that \StringIO has been required:
- *
- * require 'stringio'
+ * :markup: markdown
*
+ * :include: stringio/stringio.md
*/
void
Init_stringio(void)
@@ -1889,7 +1992,7 @@ Init_stringio(void)
#undef rb_intern
#ifdef HAVE_RB_EXT_RACTOR_SAFE
- rb_ext_ractor_safe(true);
+ rb_ext_ractor_safe(true);
#endif
VALUE StringIO = rb_define_class("StringIO", rb_cObject);
@@ -1981,7 +2084,9 @@ Init_stringio(void)
rb_define_method(StringIO, "set_encoding_by_bom", strio_set_encoding_by_bom, 0);
{
+ /* :stopdoc: */
VALUE mReadable = rb_define_module_under(rb_cIO, "generic_readable");
+ /* :startdoc: */
rb_define_method(mReadable, "readchar", strio_readchar, 0);
rb_define_method(mReadable, "readbyte", strio_readbyte, 0);
rb_define_method(mReadable, "readline", strio_readline, -1);
@@ -1991,7 +2096,9 @@ Init_stringio(void)
rb_include_module(StringIO, mReadable);
}
{
+ /* :stopdoc: */
VALUE mWritable = rb_define_module_under(rb_cIO, "generic_writable");
+ /* :startdoc: */
rb_define_method(mWritable, "<<", strio_addstr, 1);
rb_define_method(mWritable, "print", strio_print, -1);
rb_define_method(mWritable, "printf", strio_printf, -1);
diff --git a/ext/stringio/stringio.gemspec b/ext/stringio/stringio.gemspec
index b40b7fc824..f9a0742049 100644
--- a/ext/stringio/stringio.gemspec
+++ b/ext/stringio/stringio.gemspec
@@ -39,6 +39,8 @@ Gem::Specification.new do |s|
s.required_ruby_version = ">= 2.7"
s.summary = "Pseudo IO on String"
+ s.metadata["changelog_uri"] = "#{s.homepage}/releases/tag/v#{s.version}"
+
# s.cert_chain = %w[certs/nobu.pem]
# s.signing_key = File.expand_path("~/.ssh/gem-private_key.pem") if $0 =~ /gem\z/
end
diff --git a/ext/strscan/depend b/ext/strscan/depend
index 8dbae206d4..b40a025230 100644
--- a/ext/strscan/depend
+++ b/ext/strscan/depend
@@ -138,6 +138,7 @@ 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/set.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
diff --git a/ext/strscan/extconf.rb b/ext/strscan/extconf.rb
index bd65606a4e..d2e9343cbc 100644
--- a/ext/strscan/extconf.rb
+++ b/ext/strscan/extconf.rb
@@ -2,8 +2,9 @@
require 'mkmf'
if RUBY_ENGINE == 'ruby'
$INCFLAGS << " -I$(top_srcdir)" if $extmk
- have_func("onig_region_memsize", "ruby.h")
- have_func("rb_reg_onig_match", "ruby.h")
+ have_func("onig_region_memsize(NULL)")
+ have_func("rb_reg_onig_match", "ruby/re.h")
+ have_func("rb_deprecate_constant")
create_makefile 'strscan'
else
File.write('Makefile', dummy_makefile("").join)
diff --git a/ext/strscan/lib/strscan/strscan.rb b/ext/strscan/lib/strscan/strscan.rb
new file mode 100644
index 0000000000..46acc7ea82
--- /dev/null
+++ b/ext/strscan/lib/strscan/strscan.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class StringScanner
+ # call-seq:
+ # scan_integer(base: 10)
+ #
+ # If `base` isn't provided or is `10`, then it is equivalent to calling `#scan` with a `[+-]?\d+` pattern,
+ # and returns an Integer or nil.
+ #
+ # If `base` is `16`, then it is equivalent to calling `#scan` with a `[+-]?(0x)?[0-9a-fA-F]+` pattern,
+ # and returns an Integer or nil.
+ #
+ # The scanned string must be encoded with an ASCII compatible encoding, otherwise
+ # Encoding::CompatibilityError will be raised.
+ def scan_integer(base: 10)
+ case base
+ when 10
+ scan_base10_integer
+ when 16
+ scan_base16_integer
+ else
+ raise ArgumentError, "Unsupported integer base: #{base.inspect}, expected 10 or 16"
+ end
+ end
+end
diff --git a/ext/strscan/strscan.c b/ext/strscan/strscan.c
index 70a3ce5260..935fce19df 100644
--- a/ext/strscan/strscan.c
+++ b/ext/strscan/strscan.c
@@ -22,7 +22,15 @@ extern size_t onig_region_memsize(const struct re_registers *regs);
#include <stdbool.h>
-#define STRSCAN_VERSION "3.1.1"
+#define STRSCAN_VERSION "3.1.7.dev"
+
+
+#ifdef HAVE_RB_DEPRECATE_CONSTANT
+/* In ruby 3.0, defined but exposed in external headers */
+extern void rb_deprecate_constant(VALUE mod, const char *name);
+#else
+# define rb_deprecate_constant(mod, name) ((void)0)
+#endif
/* =======================================================================
Data Type Definitions
@@ -30,7 +38,8 @@ extern size_t onig_region_memsize(const struct re_registers *regs);
static VALUE StringScanner;
static VALUE ScanError;
-static ID id_byteslice;
+
+static int usascii_encindex, utf8_encindex, binary_encindex;
struct strscanner
{
@@ -56,8 +65,13 @@ struct strscanner
};
#define MATCHED_P(s) ((s)->flags & FLAG_MATCHED)
-#define MATCHED(s) (s)->flags |= FLAG_MATCHED
-#define CLEAR_MATCH_STATUS(s) (s)->flags &= ~FLAG_MATCHED
+#define MATCHED(s) ((s)->flags |= FLAG_MATCHED)
+#define CLEAR_MATCHED(s) ((s)->flags &= ~FLAG_MATCHED)
+#define CLEAR_NAMED_CAPTURES(s) ((s)->regex = Qnil)
+#define CLEAR_MATCH_STATUS(s) do {\
+ CLEAR_MATCHED(s);\
+ CLEAR_NAMED_CAPTURES(s);\
+} while (0)
#define S_PBEG(s) (RSTRING_PTR((s)->str))
#define S_LEN(s) (RSTRING_LEN((s)->str))
@@ -90,7 +104,6 @@ static VALUE strscan_init_copy _((VALUE vself, VALUE vorig));
static VALUE strscan_s_mustc _((VALUE self));
static VALUE strscan_terminate _((VALUE self));
-static VALUE strscan_clear _((VALUE self));
static VALUE strscan_get_string _((VALUE self));
static VALUE strscan_set_string _((VALUE self, VALUE str));
static VALUE strscan_concat _((VALUE self, VALUE str));
@@ -112,13 +125,11 @@ static VALUE strscan_search_full _((VALUE self, VALUE re,
static void adjust_registers_to_matched _((struct strscanner *p));
static VALUE strscan_getch _((VALUE self));
static VALUE strscan_get_byte _((VALUE self));
-static VALUE strscan_getbyte _((VALUE self));
static VALUE strscan_peek _((VALUE self, VALUE len));
-static VALUE strscan_peep _((VALUE self, VALUE len));
+static VALUE strscan_scan_base10_integer _((VALUE self));
static VALUE strscan_unscan _((VALUE self));
static VALUE strscan_bol_p _((VALUE self));
static VALUE strscan_eos_p _((VALUE self));
-static VALUE strscan_empty_p _((VALUE self));
static VALUE strscan_rest_p _((VALUE self));
static VALUE strscan_matched_p _((VALUE self));
static VALUE strscan_matched _((VALUE self));
@@ -201,7 +212,7 @@ strscan_memsize(const void *ptr)
static const rb_data_type_t strscanner_type = {
"StringScanner",
{strscan_mark, strscan_free, strscan_memsize},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
};
static VALUE
@@ -213,21 +224,32 @@ strscan_s_allocate(VALUE klass)
CLEAR_MATCH_STATUS(p);
onig_region_init(&(p->regs));
p->str = Qnil;
- p->regex = Qnil;
return obj;
}
/*
- * call-seq:
- * StringScanner.new(string, fixed_anchor: false)
- * StringScanner.new(string, dup = false)
- *
- * Creates a new StringScanner object to scan over the given +string+.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
*
- * If +fixed_anchor+ is +true+, +\A+ always matches the beginning of
- * the string. Otherwise, +\A+ always matches the current position.
+ * call-seq:
+ * StringScanner.new(string, fixed_anchor: false) -> string_scanner
+ *
+ * Returns a new `StringScanner` object whose [stored string][1]
+ * is the given `string`;
+ * sets the [fixed-anchor property][10]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.string # => "foobarbaz"
+ * scanner.fixed_anchor? # => false
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 0
+ * # charpos: 0
+ * # rest: "foobarbaz"
+ * # rest_size: 9
+ * ```
*
- * +dup+ argument is obsolete and not used now.
*/
static VALUE
strscan_initialize(int argc, VALUE *argv, VALUE self)
@@ -254,7 +276,7 @@ strscan_initialize(int argc, VALUE *argv, VALUE self)
p->fixed_anchor_p = false;
}
StringValue(str);
- p->str = str;
+ RB_OBJ_WRITE(self, &p->str, str);
return self;
}
@@ -266,11 +288,14 @@ check_strscan(VALUE obj)
}
/*
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
* call-seq:
- * dup
- * clone
+ * dup -> shallow_copy
*
- * Duplicates a StringScanner object.
+ * Returns a shallow copy of `self`;
+ * the [stored string][1] in the copy is the same string as in `self`.
*/
static VALUE
strscan_init_copy(VALUE vself, VALUE vorig)
@@ -281,7 +306,7 @@ strscan_init_copy(VALUE vself, VALUE vorig)
orig = check_strscan(vorig);
if (self != orig) {
self->flags = orig->flags;
- self->str = orig->str;
+ RB_OBJ_WRITE(vself, &self->str, orig->str);
self->prev = orig->prev;
self->curr = orig->curr;
if (rb_reg_region_copy(&self->regs, &orig->regs))
@@ -297,10 +322,13 @@ strscan_init_copy(VALUE vself, VALUE vorig)
======================================================================= */
/*
- * call-seq: StringScanner.must_C_version
+ * call-seq:
+ * StringScanner.must_C_version -> self
*
- * This method is defined for backward compatibility.
+ * Returns +self+; defined for backward compatibility.
*/
+
+ /* :nodoc: */
static VALUE
strscan_s_mustc(VALUE self)
{
@@ -308,7 +336,30 @@ strscan_s_mustc(VALUE self)
}
/*
- * Reset the scan pointer (index 0) and clear matching data.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * reset -> self
+ *
+ * Sets both [byte position][2] and [character position][7] to zero,
+ * and clears [match values][9];
+ * returns +self+:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.exist?(/bar/) # => 6
+ * scanner.reset # => #<StringScanner 0/9 @ "fooba...">
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 0
+ * # charpos: 0
+ * # rest: "foobarbaz"
+ * # rest_size: 9
+ * # => nil
+ * match_values_cleared?(scanner) # => true
+ * ```
+ *
*/
static VALUE
strscan_reset(VALUE self)
@@ -322,11 +373,9 @@ strscan_reset(VALUE self)
}
/*
- * call-seq:
- * terminate
- * clear
- *
- * Sets the scan pointer to the end of the string and clear matching data.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/terminate.md
*/
static VALUE
strscan_terminate(VALUE self)
@@ -340,18 +389,21 @@ strscan_terminate(VALUE self)
}
/*
- * Equivalent to #terminate.
- * This method is obsolete; use #terminate instead.
- */
-static VALUE
-strscan_clear(VALUE self)
-{
- rb_warning("StringScanner#clear is obsolete; use #terminate instead");
- return strscan_terminate(self);
-}
-
-/*
- * Returns the string being scanned.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * string -> stored_string
+ *
+ * Returns the [stored string][1]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobar')
+ * scanner.string # => "foobar"
+ * scanner.concat('baz')
+ * scanner.string # => "foobarbaz"
+ * ```
+ *
*/
static VALUE
strscan_get_string(VALUE self)
@@ -363,10 +415,39 @@ strscan_get_string(VALUE self)
}
/*
- * call-seq: string=(str)
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * string = other_string -> other_string
+ *
+ * Replaces the [stored string][1] with the given `other_string`:
+ *
+ * - Sets both [positions][11] to zero.
+ * - Clears [match values][9].
+ * - Returns `other_string`.
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobar')
+ * scanner.scan(/foo/)
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 3
+ * # charpos: 3
+ * # rest: "bar"
+ * # rest_size: 3
+ * match_values_cleared?(scanner) # => false
+ *
+ * scanner.string = 'baz' # => "baz"
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 0
+ * # charpos: 0
+ * # rest: "baz"
+ * # rest_size: 3
+ * match_values_cleared?(scanner) # => true
+ * ```
*
- * Changes the string being scanned to +str+ and resets the scanner.
- * Returns +str+.
*/
static VALUE
strscan_set_string(VALUE self, VALUE str)
@@ -374,25 +455,40 @@ strscan_set_string(VALUE self, VALUE str)
struct strscanner *p = check_strscan(self);
StringValue(str);
- p->str = str;
+ RB_OBJ_WRITE(self, &p->str, str);
p->curr = 0;
CLEAR_MATCH_STATUS(p);
return str;
}
/*
- * call-seq:
- * concat(str)
- * <<(str)
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
*
- * Appends +str+ to the string being scanned.
- * This method does not affect scan pointer.
+ * call-seq:
+ * concat(more_string) -> self
+ *
+ * - Appends the given `more_string`
+ * to the [stored string][1].
+ * - Returns `self`.
+ * - Does not affect the [positions][11]
+ * or [match values][9].
+ *
+ *
+ * ```rb
+ * scanner = StringScanner.new('foo')
+ * scanner.string # => "foo"
+ * scanner.terminate
+ * scanner.concat('barbaz') # => #<StringScanner 3/9 "foo" @ "barba...">
+ * scanner.string # => "foobarbaz"
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 3
+ * # charpos: 3
+ * # rest: "barbaz"
+ * # rest_size: 6
+ * ```
*
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.scan(/Fri /)
- * s << " +1000 GMT"
- * s.string # -> "Fri Dec 12 1975 14:39 +1000 GMT"
- * s.scan(/Dec/) # -> "Dec"
*/
static VALUE
strscan_concat(VALUE self, VALUE str)
@@ -406,18 +502,9 @@ strscan_concat(VALUE self, VALUE str)
}
/*
- * Returns the byte position of the scan pointer. In the 'reset' position, this
- * value is zero. In the 'terminated' position (i.e. the string is exhausted),
- * this value is the bytesize of the string.
- *
- * In short, it's a 0-based index into bytes of the string.
- *
- * s = StringScanner.new('test string')
- * s.pos # -> 0
- * s.scan_until /str/ # -> "test str"
- * s.pos # -> 8
- * s.terminate # -> #<StringScanner fin>
- * s.pos # -> 11
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/get_pos.md
*/
static VALUE
strscan_get_pos(VALUE self)
@@ -425,21 +512,13 @@ strscan_get_pos(VALUE self)
struct strscanner *p;
GET_SCANNER(self, p);
- return INT2FIX(p->curr);
+ return LONG2NUM(p->curr);
}
/*
- * Returns the character position of the scan pointer. In the 'reset' position, this
- * value is zero. In the 'terminated' position (i.e. the string is exhausted),
- * this value is the size of the string.
- *
- * In short, it's a 0-based index into the string.
- *
- * s = StringScanner.new("abc\u00e4def\u00f6ghi")
- * s.charpos # -> 0
- * s.scan_until(/\u00e4/) # -> "abc\u00E4"
- * s.pos # -> 5
- * s.charpos # -> 4
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/get_charpos.md
*/
static VALUE
strscan_get_charpos(VALUE self)
@@ -452,13 +531,9 @@ strscan_get_charpos(VALUE self)
}
/*
- * call-seq: pos=(n)
- *
- * Sets the byte position of the scan pointer.
- *
- * s = StringScanner.new('test string')
- * s.pos = 7 # -> 7
- * s.rest # -> "ring"
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/set_pos.md
*/
static VALUE
strscan_set_pos(VALUE self, VALUE v)
@@ -467,7 +542,7 @@ strscan_set_pos(VALUE self, VALUE v)
long i;
GET_SCANNER(self, p);
- i = NUM2INT(v);
+ i = NUM2LONG(v);
if (i < 0) i += S_LEN(p);
if (i < 0) rb_raise(rb_eRangeError, "index out of range");
if (i > S_LEN(p)) rb_raise(rb_eRangeError, "index out of range");
@@ -488,19 +563,20 @@ match_target(struct strscanner *p)
}
static inline void
-set_registers(struct strscanner *p, size_t length)
+set_registers(struct strscanner *p, size_t pos, size_t length)
{
const int at = 0;
OnigRegion *regs = &(p->regs);
onig_region_clear(regs);
if (onig_region_set(regs, at, 0, 0)) return;
if (p->fixed_anchor_p) {
- regs->beg[at] = p->curr;
- regs->end[at] = p->curr + length;
+ regs->beg[at] = pos + p->curr;
+ regs->end[at] = pos + p->curr + length;
}
else
{
- regs->end[at] = length;
+ regs->beg[at] = pos;
+ regs->end[at] = pos + length;
}
}
@@ -546,12 +622,13 @@ rb_reg_onig_match(VALUE re, VALUE str,
OnigPosition (*match)(regex_t *reg, VALUE str, struct re_registers *regs, void *args),
void *args, struct re_registers *regs)
{
+ OnigPosition result;
regex_t *reg = rb_reg_prepare_re(re, str);
bool tmpreg = reg != RREGEXP_PTR(re);
if (!tmpreg) RREGEXP(re)->usecnt++;
- OnigPosition result = match(reg, str, regs, args);
+ result = match(reg, str, regs, args);
if (!tmpreg) RREGEXP(re)->usecnt--;
if (tmpreg) {
@@ -601,19 +678,19 @@ strscan_search(regex_t *reg, VALUE str, struct re_registers *regs, void *args_pt
ONIG_OPTION_NONE);
}
+static void
+strscan_enc_check(VALUE str1, VALUE str2)
+{
+ if (RB_ENCODING_GET(str1) != RB_ENCODING_GET(str2)) {
+ rb_enc_check(str1, str2);
+ }
+}
+
static VALUE
strscan_do_scan(VALUE self, VALUE pattern, int succptr, int getstr, int headonly)
{
struct strscanner *p;
- if (headonly) {
- if (!RB_TYPE_P(pattern, T_REGEXP)) {
- StringValue(pattern);
- }
- }
- else {
- Check_Type(pattern, T_REGEXP);
- }
GET_SCANNER(self, p);
CLEAR_MATCH_STATUS(p);
@@ -622,26 +699,42 @@ strscan_do_scan(VALUE self, VALUE pattern, int succptr, int getstr, int headonly
}
if (RB_TYPE_P(pattern, T_REGEXP)) {
- p->regex = pattern;
- OnigPosition ret = rb_reg_onig_match(pattern,
- p->str,
- headonly ? strscan_match : strscan_search,
- (void *)p,
- &(p->regs));
+ OnigPosition ret;
+ RB_OBJ_WRITE(self, &p->regex, pattern);
+ ret = rb_reg_onig_match(p->regex,
+ p->str,
+ headonly ? strscan_match : strscan_search,
+ (void *)p,
+ &(p->regs));
if (ret == ONIG_MISMATCH) {
return Qnil;
}
}
else {
- rb_enc_check(p->str, pattern);
+ StringValue(pattern);
if (S_RESTLEN(p) < RSTRING_LEN(pattern)) {
+ strscan_enc_check(p->str, pattern);
return Qnil;
}
- if (memcmp(CURPTR(p), RSTRING_PTR(pattern), RSTRING_LEN(pattern)) != 0) {
- return Qnil;
+
+ if (headonly) {
+ strscan_enc_check(p->str, pattern);
+
+ if (memcmp(CURPTR(p), RSTRING_PTR(pattern), RSTRING_LEN(pattern)) != 0) {
+ return Qnil;
+ }
+ set_registers(p, 0, RSTRING_LEN(pattern));
+ }
+ else {
+ rb_encoding *enc = rb_enc_check(p->str, pattern);
+ long pos = rb_memsearch(RSTRING_PTR(pattern), RSTRING_LEN(pattern),
+ CURPTR(p), S_RESTLEN(p), enc);
+ if (pos == -1) {
+ return Qnil;
+ }
+ set_registers(p, pos, RSTRING_LEN(pattern));
}
- set_registers(p, RSTRING_LEN(pattern));
}
MATCHED(p);
@@ -662,20 +755,9 @@ strscan_do_scan(VALUE self, VALUE pattern, int succptr, int getstr, int headonly
}
/*
- * call-seq: scan(pattern) => String
- *
- * Tries to match with +pattern+ at the current position. If there's a match,
- * the scanner advances the "scan pointer" and returns the matched string.
- * Otherwise, the scanner returns +nil+.
- *
- * s = StringScanner.new('test string')
- * p s.scan(/\w+/) # -> "test"
- * p s.scan(/\w+/) # -> nil
- * p s.scan(/\s+/) # -> " "
- * p s.scan("str") # -> "str"
- * p s.scan(/\w+/) # -> "ing"
- * p s.scan(/./) # -> nil
- *
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/scan.md
*/
static VALUE
strscan_scan(VALUE self, VALUE re)
@@ -684,16 +766,60 @@ strscan_scan(VALUE self, VALUE re)
}
/*
- * call-seq: match?(pattern)
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
*
- * Tests whether the given +pattern+ is matched from the current scan pointer.
- * Returns the length of the match, or +nil+. The scan pointer is not advanced.
+ * call-seq:
+ * match?(pattern) -> updated_position or nil
+ *
+ * Attempts to [match][17] the given `pattern`
+ * at the beginning of the [target substring][3];
+ * does not modify the [positions][11].
+ *
+ * If the match succeeds:
+ *
+ * - Sets [match values][9].
+ * - Returns the size in bytes of the matched substring.
+ *
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.pos = 3
+ * scanner.match?(/bar/) => 3
+ * put_match_values(scanner)
+ * # Basic match values:
+ * # matched?: true
+ * # matched_size: 3
+ * # pre_match: "foo"
+ * # matched : "bar"
+ * # post_match: "baz"
+ * # Captured match values:
+ * # size: 1
+ * # captures: []
+ * # named_captures: {}
+ * # values_at: ["bar", nil]
+ * # []:
+ * # [0]: "bar"
+ * # [1]: nil
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 3
+ * # charpos: 3
+ * # rest: "barbaz"
+ * # rest_size: 6
+ * ```
+ *
+ * If the match fails:
+ *
+ * - Clears match values.
+ * - Returns `nil`.
+ * - Does not increment positions.
+ *
+ * ```rb
+ * scanner.match?(/nope/) # => nil
+ * match_values_cleared?(scanner) # => true
+ * ```
*
- * s = StringScanner.new('test string')
- * p s.match?(/\w+/) # -> 4
- * p s.match?(/\w+/) # -> 4
- * p s.match?("test") # -> 4
- * p s.match?(/\s+/) # -> nil
*/
static VALUE
strscan_match_p(VALUE self, VALUE re)
@@ -702,22 +828,9 @@ strscan_match_p(VALUE self, VALUE re)
}
/*
- * call-seq: skip(pattern)
- *
- * Attempts to skip over the given +pattern+ beginning with the scan pointer.
- * If it matches, the scan pointer is advanced to the end of the match, and the
- * length of the match is returned. Otherwise, +nil+ is returned.
- *
- * It's similar to #scan, but without returning the matched string.
- *
- * s = StringScanner.new('test string')
- * p s.skip(/\w+/) # -> 4
- * p s.skip(/\w+/) # -> nil
- * p s.skip(/\s+/) # -> 1
- * p s.skip("st") # -> 2
- * p s.skip(/\w+/) # -> 4
- * p s.skip(/./) # -> nil
- *
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/skip.md
*/
static VALUE
strscan_skip(VALUE self, VALUE re)
@@ -726,19 +839,59 @@ strscan_skip(VALUE self, VALUE re)
}
/*
- * call-seq: check(pattern)
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
*
- * This returns the value that #scan would return, without advancing the scan
- * pointer. The match register is affected, though.
- *
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.check /Fri/ # -> "Fri"
- * s.pos # -> 0
- * s.matched # -> "Fri"
- * s.check /12/ # -> nil
- * s.matched # -> nil
+ * call-seq:
+ * check(pattern) -> matched_substring or nil
+ *
+ * Attempts to [match][17] the given `pattern`
+ * at the beginning of the [target substring][3];
+ * does not modify the [positions][11].
+ *
+ * If the match succeeds:
+ *
+ * - Returns the matched substring.
+ * - Sets all [match values][9].
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.pos = 3
+ * scanner.check('bar') # => "bar"
+ * put_match_values(scanner)
+ * # Basic match values:
+ * # matched?: true
+ * # matched_size: 3
+ * # pre_match: "foo"
+ * # matched : "bar"
+ * # post_match: "baz"
+ * # Captured match values:
+ * # size: 1
+ * # captures: []
+ * # named_captures: {}
+ * # values_at: ["bar", nil]
+ * # []:
+ * # [0]: "bar"
+ * # [1]: nil
+ * # => 0..1
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 3
+ * # charpos: 3
+ * # rest: "barbaz"
+ * # rest_size: 6
+ * ```
+ *
+ * If the match fails:
+ *
+ * - Returns `nil`.
+ * - Clears all [match values][9].
+ *
+ * ```rb
+ * scanner.check(/nope/) # => nil
+ * match_values_cleared?(scanner) # => true
+ * ```
*
- * Mnemonic: it "checks" to see whether a #scan will return a value.
*/
static VALUE
strscan_check(VALUE self, VALUE re)
@@ -747,15 +900,24 @@ strscan_check(VALUE self, VALUE re)
}
/*
- * call-seq: scan_full(pattern, advance_pointer_p, return_string_p)
+ * call-seq:
+ * scan_full(pattern, advance_pointer_p, return_string_p) -> matched_substring or nil
+ *
+ * Equivalent to one of the following:
+ *
+ * - +advance_pointer_p+ +true+:
*
- * Tests whether the given +pattern+ is matched from the current scan pointer.
- * Advances the scan pointer if +advance_pointer_p+ is true.
- * Returns the matched string if +return_string_p+ is true.
- * The match register is affected.
+ * - +return_string_p+ +true+: StringScanner#scan(pattern).
+ * - +return_string_p+ +false+: StringScanner#skip(pattern).
+ *
+ * - +advance_pointer_p+ +false+:
+ *
+ * - +return_string_p+ +true+: StringScanner#check(pattern).
+ * - +return_string_p+ +false+: StringScanner#match?(pattern).
*
- * "full" means "#scan with full parameters".
*/
+
+ /* :nodoc: */
static VALUE
strscan_scan_full(VALUE self, VALUE re, VALUE s, VALUE f)
{
@@ -763,16 +925,9 @@ strscan_scan_full(VALUE self, VALUE re, VALUE s, VALUE f)
}
/*
- * call-seq: scan_until(pattern)
- *
- * Scans the string _until_ the +pattern+ is matched. Returns the substring up
- * to and including the end of the match, advancing the scan pointer to that
- * location. If there is no match, +nil+ is returned.
- *
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.scan_until(/1/) # -> "Fri Dec 1"
- * s.pre_match # -> "Fri Dec "
- * s.scan_until(/XYZ/) # -> nil
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/scan_until.md
*/
static VALUE
strscan_scan_until(VALUE self, VALUE re)
@@ -781,17 +936,61 @@ strscan_scan_until(VALUE self, VALUE re)
}
/*
- * call-seq: exist?(pattern)
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
*
- * Looks _ahead_ to see if the +pattern+ exists _anywhere_ in the string,
- * without advancing the scan pointer. This predicates whether a #scan_until
- * will return a value.
+ * call-seq:
+ * exist?(pattern) -> byte_offset or nil
+ *
+ * Attempts to [match][17] the given `pattern`
+ * anywhere (at any [position][2])
+ * n the [target substring][3];
+ * does not modify the [positions][11].
+ *
+ * If the match succeeds:
+ *
+ * - Returns a byte offset:
+ * the distance in bytes between the current [position][2]
+ * and the end of the matched substring.
+ * - Sets all [match values][9].
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbazbatbam')
+ * scanner.pos = 6
+ * scanner.exist?(/bat/) # => 6
+ * put_match_values(scanner)
+ * # Basic match values:
+ * # matched?: true
+ * # matched_size: 3
+ * # pre_match: "foobarbaz"
+ * # matched : "bat"
+ * # post_match: "bam"
+ * # Captured match values:
+ * # size: 1
+ * # captures: []
+ * # named_captures: {}
+ * # values_at: ["bat", nil]
+ * # []:
+ * # [0]: "bat"
+ * # [1]: nil
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 6
+ * # charpos: 6
+ * # rest: "bazbatbam"
+ * # rest_size: 9
+ * ```
+ *
+ * If the match fails:
+ *
+ * - Returns `nil`.
+ * - Clears all [match values][9].
+ *
+ * ```rb
+ * scanner.exist?(/nope/) # => nil
+ * match_values_cleared?(scanner) # => true
+ * ```
*
- * s = StringScanner.new('test string')
- * s.exist? /s/ # -> 3
- * s.scan /test/ # -> "test"
- * s.exist? /s/ # -> 2
- * s.exist? /e/ # -> nil
*/
static VALUE
strscan_exist_p(VALUE self, VALUE re)
@@ -800,20 +999,9 @@ strscan_exist_p(VALUE self, VALUE re)
}
/*
- * call-seq: skip_until(pattern)
- *
- * Advances the scan pointer until +pattern+ is matched and consumed. Returns
- * the number of bytes advanced, or +nil+ if no match was found.
- *
- * Look ahead to match +pattern+, and advance the scan pointer to the _end_
- * of the match. Return the number of characters advanced, or +nil+ if the
- * match was unsuccessful.
- *
- * It's similar to #scan_until, but without returning the intervening string.
- *
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.skip_until /12/ # -> 10
- * s #
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/skip_until.md
*/
static VALUE
strscan_skip_until(VALUE self, VALUE re)
@@ -822,17 +1010,61 @@ strscan_skip_until(VALUE self, VALUE re)
}
/*
- * call-seq: check_until(pattern)
- *
- * This returns the value that #scan_until would return, without advancing the
- * scan pointer. The match register is affected, though.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
*
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.check_until /12/ # -> "Fri Dec 12"
- * s.pos # -> 0
- * s.matched # -> 12
+ * call-seq:
+ * check_until(pattern) -> substring or nil
+ *
+ * Attempts to [match][17] the given `pattern`
+ * anywhere (at any [position][2])
+ * in the [target substring][3];
+ * does not modify the [positions][11].
+ *
+ * If the match succeeds:
+ *
+ * - Sets all [match values][9].
+ * - Returns the matched substring,
+ * which extends from the current [position][2]
+ * to the end of the matched substring.
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbazbatbam')
+ * scanner.pos = 6
+ * scanner.check_until(/bat/) # => "bazbat"
+ * put_match_values(scanner)
+ * # Basic match values:
+ * # matched?: true
+ * # matched_size: 3
+ * # pre_match: "foobarbaz"
+ * # matched : "bat"
+ * # post_match: "bam"
+ * # Captured match values:
+ * # size: 1
+ * # captures: []
+ * # named_captures: {}
+ * # values_at: ["bat", nil]
+ * # []:
+ * # [0]: "bat"
+ * # [1]: nil
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 6
+ * # charpos: 6
+ * # rest: "bazbatbam"
+ * # rest_size: 9
+ * ```
+ *
+ * If the match fails:
+ *
+ * - Clears all [match values][9].
+ * - Returns `nil`.
+ *
+ * ```rb
+ * scanner.check_until(/nope/) # => nil
+ * match_values_cleared?(scanner) # => true
+ * ```
*
- * Mnemonic: it "checks" to see whether a #scan_until will return a value.
*/
static VALUE
strscan_check_until(VALUE self, VALUE re)
@@ -841,14 +1073,24 @@ strscan_check_until(VALUE self, VALUE re)
}
/*
- * call-seq: search_full(pattern, advance_pointer_p, return_string_p)
+ * call-seq:
+ * search_full(pattern, advance_pointer_p, return_string_p) -> matched_substring or position_delta or nil
+ *
+ * Equivalent to one of the following:
+ *
+ * - +advance_pointer_p+ +true+:
+ *
+ * - +return_string_p+ +true+: StringScanner#scan_until(pattern).
+ * - +return_string_p+ +false+: StringScanner#skip_until(pattern).
+ *
+ * - +advance_pointer_p+ +false+:
+ *
+ * - +return_string_p+ +true+: StringScanner#check_until(pattern).
+ * - +return_string_p+ +false+: StringScanner#exist?(pattern).
*
- * Scans the string _until_ the +pattern+ is matched.
- * Advances the scan pointer if +advance_pointer_p+, otherwise not.
- * Returns the matched string if +return_string_p+ is true, otherwise
- * returns the number of bytes advanced.
- * This method does affect the match register.
*/
+
+ /* :nodoc: */
static VALUE
strscan_search_full(VALUE self, VALUE re, VALUE s, VALUE f)
{
@@ -868,17 +1110,9 @@ adjust_registers_to_matched(struct strscanner *p)
}
/*
- * Scans one character and returns it.
- * This method is multibyte character sensitive.
- *
- * s = StringScanner.new("ab")
- * s.getch # => "a"
- * s.getch # => "b"
- * s.getch # => nil
- *
- * s = StringScanner.new("\244\242".force_encoding("euc-jp"))
- * s.getch # => "\x{A4A2}" # Japanese hira-kana "A" in EUC-JP
- * s.getch # => nil
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/getch.md
*/
static VALUE
strscan_getch(VALUE self)
@@ -903,31 +1137,26 @@ strscan_getch(VALUE self)
}
/*
+ * call-seq:
+ * scan_byte -> integer_byte
+ *
* Scans one byte and returns it as an integer.
* This method is not multibyte character sensitive.
* See also: #getch.
*
- * s = StringScanner.new('ab')
- * s.scan_byte # => 97
- * s.scan_byte # => 98
- * s.scan_byte # => nil
- *
- * s = StringScanner.new("\244\242".force_encoding("euc-jp"))
- * s.scan_byte # => 0xA4
- * s.scan_byte # => 0xA2
- * s.scan_byte # => nil
*/
static VALUE
strscan_scan_byte(VALUE self)
{
struct strscanner *p;
+ VALUE byte;
GET_SCANNER(self, p);
CLEAR_MATCH_STATUS(p);
if (EOS_P(p))
return Qnil;
- VALUE byte = INT2FIX((unsigned char)*CURPTR(p));
+ byte = INT2FIX((unsigned char)*CURPTR(p));
p->prev = p->curr;
p->curr++;
MATCHED(p);
@@ -954,19 +1183,9 @@ strscan_peek_byte(VALUE self)
}
/*
- * Scans one byte and returns it.
- * This method is not multibyte character sensitive.
- * See also: #getch.
- *
- * s = StringScanner.new('ab')
- * s.get_byte # => "a"
- * s.get_byte # => "b"
- * s.get_byte # => nil
- *
- * s = StringScanner.new("\244\242".force_encoding("euc-jp"))
- * s.get_byte # => "\xA4"
- * s.get_byte # => "\xA2"
- * s.get_byte # => nil
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ * :include: strscan/methods/get_byte.md
*/
static VALUE
strscan_get_byte(VALUE self)
@@ -988,25 +1207,22 @@ strscan_get_byte(VALUE self)
}
/*
- * Equivalent to #get_byte.
- * This method is obsolete; use #get_byte instead.
- */
-static VALUE
-strscan_getbyte(VALUE self)
-{
- rb_warning("StringScanner#getbyte is obsolete; use #get_byte instead");
- return strscan_get_byte(self);
-}
-
-/*
- * call-seq: peek(len)
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
*
- * Extracts a string corresponding to <tt>string[pos,len]</tt>, without
- * advancing the scan pointer.
+ * call-seq:
+ * peek(length) -> substring
*
- * s = StringScanner.new('test string')
- * s.peek(7) # => "test st"
- * s.peek(7) # => "test st"
+ * Returns the substring `string[pos, length]`;
+ * does not update [match values][9] or [positions][11]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.pos = 3
+ * scanner.peek(3) # => "bar"
+ * scanner.terminate
+ * scanner.peek(3) # => ""
+ * ```
*
*/
static VALUE
@@ -1025,27 +1241,160 @@ strscan_peek(VALUE self, VALUE vlen)
return extract_beg_len(p, p->curr, len);
}
-/*
- * Equivalent to #peek.
- * This method is obsolete; use #peek instead.
- */
static VALUE
-strscan_peep(VALUE self, VALUE vlen)
+strscan_parse_integer(struct strscanner *p, int base, long len)
{
- rb_warning("StringScanner#peep is obsolete; use #peek instead");
- return strscan_peek(self, vlen);
+ VALUE buffer_v, integer;
+
+ char *buffer = RB_ALLOCV_N(char, buffer_v, len + 1);
+
+ MEMCPY(buffer, CURPTR(p), char, len);
+ buffer[len] = '\0';
+ integer = rb_cstr2inum(buffer, base);
+ RB_ALLOCV_END(buffer_v);
+ p->curr += len;
+
+ MATCHED(p);
+ adjust_registers_to_matched(p);
+
+ return integer;
+}
+
+static inline bool
+strscan_ascii_compat_fastpath(VALUE str) {
+ int encindex = ENCODING_GET_INLINED(str);
+ // The overwhelming majority of strings are in one of these 3 encodings.
+ return encindex == utf8_encindex || encindex == binary_encindex || encindex == usascii_encindex;
+}
+
+static inline void
+strscan_must_ascii_compat(VALUE str)
+{
+ // The overwhelming majority of strings are in one of these 3 encodings.
+ if (RB_LIKELY(strscan_ascii_compat_fastpath(str))) {
+ return;
+ }
+
+ rb_must_asciicompat(str);
+}
+
+/* :nodoc: */
+static VALUE
+strscan_scan_base10_integer(VALUE self)
+{
+ char *ptr;
+ long len = 0, remaining_len;
+ struct strscanner *p;
+
+ GET_SCANNER(self, p);
+ CLEAR_MATCH_STATUS(p);
+
+ strscan_must_ascii_compat(p->str);
+
+ ptr = CURPTR(p);
+
+ remaining_len = S_RESTLEN(p);
+
+ if (remaining_len <= 0) {
+ return Qnil;
+ }
+
+ if (ptr[len] == '-' || ptr[len] == '+') {
+ len++;
+ }
+
+ if (!rb_isdigit(ptr[len])) {
+ return Qnil;
+ }
+
+ p->prev = p->curr;
+
+ while (len < remaining_len && rb_isdigit(ptr[len])) {
+ len++;
+ }
+
+ return strscan_parse_integer(p, 10, len);
+}
+
+/* :nodoc: */
+static VALUE
+strscan_scan_base16_integer(VALUE self)
+{
+ char *ptr;
+ long len = 0, remaining_len;
+ struct strscanner *p;
+
+ GET_SCANNER(self, p);
+ CLEAR_MATCH_STATUS(p);
+
+ strscan_must_ascii_compat(p->str);
+
+ ptr = CURPTR(p);
+
+ remaining_len = S_RESTLEN(p);
+
+ if (remaining_len <= 0) {
+ return Qnil;
+ }
+
+ if (ptr[len] == '-' || ptr[len] == '+') {
+ len++;
+ }
+
+ if ((remaining_len >= (len + 3)) && ptr[len] == '0' && ptr[len + 1] == 'x' && rb_isxdigit(ptr[len + 2])) {
+ len += 2;
+ }
+
+ if (len >= remaining_len || !rb_isxdigit(ptr[len])) {
+ return Qnil;
+ }
+
+ p->prev = p->curr;
+
+ while (len < remaining_len && rb_isxdigit(ptr[len])) {
+ len++;
+ }
+
+ return strscan_parse_integer(p, 16, len);
}
/*
- * Sets the scan pointer to the previous position. Only one previous position is
- * remembered, and it changes with each scanning operation.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * unscan -> self
+ *
+ * Sets the [position][2] to its value previous to the recent successful
+ * [match][17] attempt:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.scan(/foo/)
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 3
+ * # charpos: 3
+ * # rest: "barbaz"
+ * # rest_size: 6
+ * scanner.unscan
+ * # => #<StringScanner 0/9 @ "fooba...">
+ * put_situation(scanner)
+ * # Situation:
+ * # pos: 0
+ * # charpos: 0
+ * # rest: "foobarbaz"
+ * # rest_size: 9
+ * ```
+ *
+ * Raises an exception if match values are clear:
+ *
+ * ```rb
+ * scanner.scan(/nope/) # => nil
+ * match_values_cleared?(scanner) # => true
+ * scanner.unscan # Raises StringScanner::Error.
+ * ```
*
- * s = StringScanner.new('test string')
- * s.scan(/\w+/) # => "test"
- * s.unscan
- * s.scan(/../) # => "te"
- * s.scan(/\d/) # => nil
- * s.unscan # ScanError: unscan failed: previous match record not exist
*/
static VALUE
strscan_unscan(VALUE self)
@@ -1061,16 +1410,37 @@ strscan_unscan(VALUE self)
}
/*
- * 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
- * s.scan(/te/)
- * s.bol? # => false
- * s.scan(/st\n/)
- * s.bol? # => true
- * s.terminate
- * s.bol? # => true
+ *
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * beginning_of_line? -> true or false
+ *
+ * Returns whether the [position][2] is at the beginning of a line;
+ * that is, at the beginning of the [stored string][1]
+ * or immediately after a newline:
+ *
+ * scanner = StringScanner.new(MULTILINE_TEXT)
+ * scanner.string
+ * # => "Go placidly amid the noise and haste,\nand remember what peace there may be in silence.\n"
+ * scanner.pos # => 0
+ * scanner.beginning_of_line? # => true
+ *
+ * scanner.scan_until(/,/) # => "Go placidly amid the noise and haste,"
+ * scanner.beginning_of_line? # => false
+ *
+ * scanner.scan(/\n/) # => "\n"
+ * scanner.beginning_of_line? # => true
+ *
+ * scanner.terminate
+ * scanner.beginning_of_line? # => true
+ *
+ * scanner.concat('x')
+ * scanner.terminate
+ * scanner.beginning_of_line? # => false
+ *
+ * StringScanner#bol? is an alias for StringScanner#beginning_of_line?.
*/
static VALUE
strscan_bol_p(VALUE self)
@@ -1084,14 +1454,24 @@ strscan_bol_p(VALUE self)
}
/*
- * Returns +true+ if the scan pointer is at the end of the string.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * eos? -> true or false
+ *
+ * Returns whether the [position][2]
+ * is at the end of the [stored string][1]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.eos? # => false
+ * pos = 3
+ * scanner.eos? # => false
+ * scanner.terminate
+ * scanner.eos? # => true
+ * ```
*
- * s = StringScanner.new('test string')
- * p s.eos? # => false
- * s.scan(/test/)
- * p s.eos? # => false
- * s.terminate
- * p s.eos? # => true
*/
static VALUE
strscan_eos_p(VALUE self)
@@ -1103,25 +1483,18 @@ strscan_eos_p(VALUE self)
}
/*
- * Equivalent to #eos?.
- * This method is obsolete, use #eos? instead.
- */
-static VALUE
-strscan_empty_p(VALUE self)
-{
- rb_warning("StringScanner#empty? is obsolete; use #eos? instead");
- return strscan_eos_p(self);
-}
-
-/*
+ * call-seq:
+ * rest?
+ *
* 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')
* # These two are opposites
* s.eos? # => false
* s.rest? # => true
*/
+
+ /* :nodoc: */
static VALUE
strscan_rest_p(VALUE self)
{
@@ -1132,13 +1505,26 @@ strscan_rest_p(VALUE self)
}
/*
- * Returns +true+ if and only if the last match was successful.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * matched? -> true or false
+ *
+ * Returns `true` of the most recent [match attempt][17] was successful,
+ * `false` otherwise;
+ * see [Basic Matched Values][18]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.matched? # => false
+ * scanner.pos = 3
+ * scanner.exist?(/baz/) # => 6
+ * scanner.matched? # => true
+ * scanner.exist?(/nope/) # => nil
+ * scanner.matched? # => false
+ * ```
*
- * s = StringScanner.new('test string')
- * s.match?(/\w+/) # => 4
- * s.matched? # => true
- * s.match?(/\d+/) # => nil
- * s.matched? # => false
*/
static VALUE
strscan_matched_p(VALUE self)
@@ -1150,11 +1536,27 @@ strscan_matched_p(VALUE self)
}
/*
- * Returns the last matched string.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * matched -> matched_substring or nil
+ *
+ * Returns the matched substring from the most recent [match][17] attempt
+ * if it was successful,
+ * or `nil` otherwise;
+ * see [Basic Matched Values][18]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.matched # => nil
+ * scanner.pos = 3
+ * scanner.match?(/bar/) # => 3
+ * scanner.matched # => "bar"
+ * scanner.match?(/nope/) # => nil
+ * scanner.matched # => nil
+ * ```
*
- * s = StringScanner.new('test string')
- * s.match?(/\w+/) # -> 4
- * s.matched # -> "test"
*/
static VALUE
strscan_matched(VALUE self)
@@ -1169,15 +1571,29 @@ strscan_matched(VALUE self)
}
/*
- * Returns the size of the most recent match in bytes, or +nil+ if there
- * was no recent match. This is different than <tt>matched.size</tt>,
- * which will return the size in characters.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * matched_size -> substring_size or nil
+ *
+ * Returns the size (in bytes) of the matched substring
+ * from the most recent match [match attempt][17] if it was successful,
+ * or `nil` otherwise;
+ * see [Basic Matched Values][18]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.matched_size # => nil
+ *
+ * pos = 3
+ * scanner.exist?(/baz/) # => 9
+ * scanner.matched_size # => 3
+ *
+ * scanner.exist?(/nope/) # => nil
+ * scanner.matched_size # => nil
+ * ```
*
- * s = StringScanner.new('test string')
- * s.check /\w+/ # -> "test"
- * s.matched_size # -> 4
- * s.check /\d+/ # -> nil
- * s.matched_size # -> nil
*/
static VALUE
strscan_matched_size(VALUE self)
@@ -1192,46 +1608,89 @@ strscan_matched_size(VALUE self)
static int
name_to_backref_number(struct re_registers *regs, VALUE regexp, const char* name, const char* name_end, rb_encoding *enc)
{
- int num;
-
- num = onig_name_to_backref_number(RREGEXP_PTR(regexp),
- (const unsigned char* )name, (const unsigned char* )name_end, regs);
- if (num >= 1) {
- return num;
- }
- else {
- rb_enc_raise(enc, rb_eIndexError, "undefined group name reference: %.*s",
- rb_long2int(name_end - name), name);
+ if (RTEST(regexp)) {
+ int num = onig_name_to_backref_number(RREGEXP_PTR(regexp),
+ (const unsigned char* )name,
+ (const unsigned char* )name_end,
+ regs);
+ if (num >= 1) {
+ return num;
+ }
}
-
- UNREACHABLE;
+ rb_enc_raise(enc, rb_eIndexError, "undefined group name reference: %.*s",
+ rb_long2int(name_end - name), name);
}
/*
- * call-seq: [](n)
- *
- * Returns the n-th subgroup in the most recent match.
- *
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.scan(/(\w+) (\w+) (\d+) /) # -> "Fri Dec 12 "
- * s[0] # -> "Fri Dec 12 "
- * s[1] # -> "Fri"
- * s[2] # -> "Dec"
- * s[3] # -> "12"
- * s.post_match # -> "1975 14:39"
- * s.pre_match # -> ""
- *
- * s.reset
- * s.scan(/(?<wday>\w+) (?<month>\w+) (?<day>\d+) /) # -> "Fri Dec 12 "
- * s[0] # -> "Fri Dec 12 "
- * s[1] # -> "Fri"
- * s[2] # -> "Dec"
- * s[3] # -> "12"
- * s[:wday] # -> "Fri"
- * s[:month] # -> "Dec"
- * s[:day] # -> "12"
- * s.post_match # -> "1975 14:39"
- * s.pre_match # -> ""
+ *
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * [](specifier) -> substring or nil
+ *
+ * Returns a captured substring or `nil`;
+ * see [Captured Match Values][13].
+ *
+ * When there are captures:
+ *
+ * ```rb
+ * scanner = StringScanner.new('Fri Dec 12 1975 14:39')
+ * scanner.scan(/(?<wday>\w+) (?<month>\w+) (?<day>\d+) /)
+ * ```
+ *
+ * - `specifier` zero: returns the entire matched substring:
+ *
+ * ```rb
+ * scanner[0] # => "Fri Dec 12 "
+ * scanner.pre_match # => ""
+ * scanner.post_match # => "1975 14:39"
+ * ```
+ *
+ * - `specifier` positive integer. returns the `n`th capture, or `nil` if out of range:
+ *
+ * ```rb
+ * scanner[1] # => "Fri"
+ * scanner[2] # => "Dec"
+ * scanner[3] # => "12"
+ * scanner[4] # => nil
+ * ```
+ *
+ * - `specifier` negative integer. counts backward from the last subgroup:
+ *
+ * ```rb
+ * scanner[-1] # => "12"
+ * scanner[-4] # => "Fri Dec 12 "
+ * scanner[-5] # => nil
+ * ```
+ *
+ * - `specifier` symbol or string. returns the named subgroup, or `nil` if no such:
+ *
+ * ```rb
+ * scanner[:wday] # => "Fri"
+ * scanner['wday'] # => "Fri"
+ * scanner[:month] # => "Dec"
+ * scanner[:day] # => "12"
+ * scanner[:nope] # => nil
+ * ```
+ *
+ * When there are no captures, only `[0]` returns non-`nil`:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.exist?(/bar/)
+ * scanner[0] # => "bar"
+ * scanner[1] # => nil
+ * ```
+ *
+ * For a failed match, even `[0]` returns `nil`:
+ *
+ * ```rb
+ * scanner.scan(/nope/) # => nil
+ * scanner[0] # => nil
+ * scanner[1] # => nil
+ * ```
+ *
*/
static VALUE
strscan_aref(VALUE self, VALUE idx)
@@ -1248,7 +1707,6 @@ strscan_aref(VALUE self, VALUE idx)
idx = rb_sym2str(idx);
/* fall through */
case T_STRING:
- 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;
@@ -1268,14 +1726,28 @@ strscan_aref(VALUE self, VALUE idx)
}
/*
- * call-seq: size
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * size -> captures_count
+ *
+ * Returns the count of captures if the most recent match attempt succeeded, `nil` otherwise;
+ * see [Captures Match Values][13]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('Fri Dec 12 1975 14:39')
+ * scanner.size # => nil
*
- * Returns the amount of subgroups in the most recent match.
- * The full match counts as a subgroup.
+ * pattern = /(?<wday>\w+) (?<month>\w+) (?<day>\d+) /
+ * scanner.match?(pattern)
+ * scanner.values_at(*0..scanner.size) # => ["Fri Dec 12 ", "Fri", "Dec", "12", nil]
+ * scanner.size # => 4
+ *
+ * scanner.match?(/nope/) # => nil
+ * scanner.size # => nil
+ * ```
*
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.scan(/(\w+) (\w+) (\d+) /) # -> "Fri Dec 12 "
- * s.size # -> 4
*/
static VALUE
strscan_size(VALUE self)
@@ -1288,16 +1760,30 @@ strscan_size(VALUE self)
}
/*
- * call-seq: captures
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * captures -> substring_array or nil
+ *
+ * Returns the array of [captured match values][13] at indexes `(1..)`
+ * if the most recent match attempt succeeded, or `nil` otherwise:
+ *
+ * ```rb
+ * scanner = StringScanner.new('Fri Dec 12 1975 14:39')
+ * scanner.captures # => nil
*
- * Returns the subgroups in the most recent match (not including the full match).
- * If nothing was priorly matched, it returns nil.
+ * scanner.exist?(/(?<wday>\w+) (?<month>\w+) (?<day>\d+) /)
+ * scanner.captures # => ["Fri", "Dec", "12"]
+ * scanner.values_at(*0..4) # => ["Fri Dec 12 ", "Fri", "Dec", "12", nil]
+ *
+ * scanner.exist?(/Fri/)
+ * scanner.captures # => []
+ *
+ * scanner.scan(/nope/)
+ * scanner.captures # => nil
+ * ```
*
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.scan(/(\w+) (\w+) (\d+) (1980)?/) # -> "Fri Dec 12 "
- * s.captures # -> ["Fri", "Dec", "12", nil]
- * s.scan(/(\w+) (\w+) (\d+) (1980)?/) # -> nil
- * s.captures # -> nil
*/
static VALUE
strscan_captures(VALUE self)
@@ -1327,17 +1813,25 @@ strscan_captures(VALUE self)
}
/*
- * call-seq:
- * scanner.values_at( i1, i2, ... iN ) -> an_array
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * values_at(*specifiers) -> array_of_captures or nil
+ *
+ * Returns an array of captured substrings, or `nil` of none.
*
- * Returns the subgroups in the most recent match at the given indices.
- * If nothing was priorly matched, it returns nil.
+ * For each `specifier`, the returned substring is `[specifier]`;
+ * see #[].
+ *
+ * ```rb
+ * scanner = StringScanner.new('Fri Dec 12 1975 14:39')
+ * pattern = /(?<wday>\w+) (?<month>\w+) (?<day>\d+) /
+ * scanner.match?(pattern)
+ * scanner.values_at(*0..3) # => ["Fri Dec 12 ", "Fri", "Dec", "12"]
+ * scanner.values_at(*%i[wday month day]) # => ["Fri", "Dec", "12"]
+ * ```
*
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.scan(/(\w+) (\w+) (\d+) /) # -> "Fri Dec 12 "
- * s.values_at 0, -1, 5, 2 # -> ["Fri Dec 12 ", "12", nil, "Dec"]
- * s.scan(/(\w+) (\w+) (\d+) /) # -> nil
- * s.values_at 0, -1, 5, 2 # -> nil
*/
static VALUE
@@ -1359,13 +1853,29 @@ strscan_values_at(int argc, VALUE *argv, VALUE self)
}
/*
- * Returns the <i><b>pre</b>-match</i> (in the regular expression sense) of the last scan.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * pre_match -> substring
+ *
+ * Returns the substring that precedes the matched substring
+ * from the most recent match attempt if it was successful,
+ * or `nil` otherwise;
+ * see [Basic Match Values][18]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.pre_match # => nil
+ *
+ * scanner.pos = 3
+ * scanner.exist?(/baz/) # => 6
+ * scanner.pre_match # => "foobar" # Substring of entire string, not just target string.
+ *
+ * scanner.exist?(/nope/) # => nil
+ * scanner.pre_match # => nil
+ * ```
*
- * s = StringScanner.new('test string')
- * s.scan(/\w+/) # -> "test"
- * s.scan(/\s+/) # -> " "
- * s.pre_match # -> "test"
- * s.post_match # -> "string"
*/
static VALUE
strscan_pre_match(VALUE self)
@@ -1380,13 +1890,29 @@ strscan_pre_match(VALUE self)
}
/*
- * Returns the <i><b>post</b>-match</i> (in the regular expression sense) of the last scan.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * post_match -> substring
+ *
+ * Returns the substring that follows the matched substring
+ * from the most recent match attempt if it was successful,
+ * or `nil` otherwise;
+ * see [Basic Match Values][18]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.post_match # => nil
+ *
+ * scanner.pos = 3
+ * scanner.match?(/bar/) # => 3
+ * scanner.post_match # => "baz"
+ *
+ * scanner.match?(/nope/) # => nil
+ * scanner.post_match # => nil
+ * ```
*
- * s = StringScanner.new('test string')
- * s.scan(/\w+/) # -> "test"
- * s.scan(/\s+/) # -> " "
- * s.pre_match # -> "test"
- * s.post_match # -> "string"
*/
static VALUE
strscan_post_match(VALUE self)
@@ -1401,8 +1927,24 @@ strscan_post_match(VALUE self)
}
/*
- * Returns the "rest" of the string (i.e. everything after the scan pointer).
- * If there is no more data (eos? = true), it returns <tt>""</tt>.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * rest -> target_substring
+ *
+ * Returns the 'rest' of the [stored string][1] (all after the current [position][2]),
+ * which is the [target substring][3]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.rest # => "foobarbaz"
+ * scanner.pos = 3
+ * scanner.rest # => "barbaz"
+ * scanner.terminate
+ * scanner.rest # => ""
+ * ```
+ *
*/
static VALUE
strscan_rest(VALUE self)
@@ -1417,7 +1959,26 @@ strscan_rest(VALUE self)
}
/*
- * <tt>s.rest_size</tt> is equivalent to <tt>s.rest.size</tt>.
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * rest_size -> integer
+ *
+ * Returns the size (in bytes) of the #rest of the [stored string][1]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('foobarbaz')
+ * scanner.rest # => "foobarbaz"
+ * scanner.rest_size # => 9
+ * scanner.pos = 3
+ * scanner.rest # => "barbaz"
+ * scanner.rest_size # => 6
+ * scanner.terminate
+ * scanner.rest # => ""
+ * scanner.rest_size # => 0
+ * ```
+ *
*/
static VALUE
strscan_rest_size(VALUE self)
@@ -1433,29 +1994,42 @@ strscan_rest_size(VALUE self)
return INT2FIX(i);
}
-/*
- * <tt>s.restsize</tt> is equivalent to <tt>s.rest_size</tt>.
- * This method is obsolete; use #rest_size instead.
- */
-static VALUE
-strscan_restsize(VALUE self)
-{
- rb_warning("StringScanner#restsize is obsolete; use #rest_size instead");
- return strscan_rest_size(self);
-}
-
#define INSPECT_LENGTH 5
/*
- * Returns a string that represents the StringScanner object, showing:
- * - the current position
- * - the size of the string
- * - the characters surrounding the scan pointer
- *
- * s = StringScanner.new("Fri Dec 12 1975 14:39")
- * s.inspect # -> '#<StringScanner 0/21 @ "Fri D...">'
- * s.scan_until /12/ # -> "Fri Dec 12"
- * s.inspect # -> '#<StringScanner 10/21 "...ec 12" @ " 1975...">'
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
+ * call-seq:
+ * inspect -> string
+ *
+ * Returns a string representation of `self` that may show:
+ *
+ * 1. The current [position][2].
+ * 2. The size (in bytes) of the [stored string][1].
+ * 3. The substring preceding the current position.
+ * 4. The substring following the current position (which is also the [target substring][3]).
+ *
+ * ```rb
+ * scanner = StringScanner.new("Fri Dec 12 1975 14:39")
+ * scanner.pos = 11
+ * scanner.inspect # => "#<StringScanner 11/21 \"...c 12 \" @ \"1975 ...\">"
+ * ```
+ *
+ * If at beginning-of-string, item 4 above (following substring) is omitted:
+ *
+ * ```rb
+ * scanner.reset
+ * scanner.inspect # => "#<StringScanner 0/21 @ \"Fri D...\">"
+ * ```
+ *
+ * If at end-of-string, all items above are omitted:
+ *
+ * ```rb
+ * scanner.terminate
+ * scanner.inspect # => "#<StringScanner fin>"
+ * ```
+ *
*/
static VALUE
strscan_inspect(VALUE self)
@@ -1527,13 +2101,13 @@ inspect2(struct strscanner *p)
}
/*
- * call-seq:
- * scanner.fixed_anchor? -> true or false
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
*
- * Whether +scanner+ uses fixed anchor mode or not.
+ * call-seq:
+ * fixed_anchor? -> true or false
*
- * If fixed anchor mode is used, +\A+ always matches the beginning of
- * the string. Otherwise, +\A+ always matches the current position.
+ * Returns whether the [fixed-anchor property][10] is set.
*/
static VALUE
strscan_fixed_anchor_p(VALUE self)
@@ -1562,28 +2136,49 @@ named_captures_iter(const OnigUChar *name,
VALUE value = RUBY_Qnil;
int i;
for (i = 0; i < back_num; i++) {
- value = strscan_aref(data->self, INT2NUM(back_refs[i]));
+ VALUE v = strscan_aref(data->self, INT2NUM(back_refs[i]));
+ if (!RB_NIL_P(v)) {
+ value = v;
+ }
}
rb_hash_aset(data->captures, key, value);
return 0;
}
/*
+ * :markup: markdown
+ * :include: strscan/link_refs.txt
+ *
* call-seq:
- * scanner.named_captures -> hash
+ * named_captures -> hash
*
- * Returns a hash of string variables matching the regular expression.
+ * Returns the array of captured match values at indexes (1..)
+ * if the most recent match attempt succeeded, or nil otherwise;
+ * see [Captured Match Values][13]:
+ *
+ * ```rb
+ * scanner = StringScanner.new('Fri Dec 12 1975 14:39')
+ * scanner.named_captures # => {}
+ *
+ * pattern = /(?<wday>\w+) (?<month>\w+) (?<day>\d+) /
+ * scanner.match?(pattern)
+ * scanner.named_captures # => {"wday"=>"Fri", "month"=>"Dec", "day"=>"12"}
+ *
+ * scanner.string = 'nope'
+ * scanner.match?(pattern)
+ * scanner.named_captures # => {"wday"=>nil, "month"=>nil, "day"=>nil}
+ *
+ * scanner.match?(/nosuch/)
+ * scanner.named_captures # => {}
+ * ```
*
- * scan = StringScanner.new('foobarbaz')
- * scan.match?(/(?<f>foo)(?<r>bar)(?<z>baz)/)
- * scan.named_captures # -> {"f"=>"foo", "r"=>"bar", "z"=>"baz"}
*/
static VALUE
strscan_named_captures(VALUE self)
{
struct strscanner *p;
- GET_SCANNER(self, p);
named_captures_data data;
+ GET_SCANNER(self, p);
data.self = self;
data.captures = rb_hash_new();
if (!RB_NIL_P(p->regex)) {
@@ -1598,111 +2193,20 @@ strscan_named_captures(VALUE self)
======================================================================= */
/*
+ * Document-class: StringScanner::Error
+ *
+ * The error class for StringScanner.
+ * See StringScanner#unscan.
+ */
+
+/*
* Document-class: StringScanner
*
- * StringScanner provides for lexical scanning operations on a String. Here is
- * an example of its usage:
- *
- * require 'strscan'
- *
- * s = StringScanner.new('This is an example string')
- * s.eos? # -> false
- *
- * p s.scan(/\w+/) # -> "This"
- * p s.scan(/\w+/) # -> nil
- * p s.scan(/\s+/) # -> " "
- * p s.scan(/\s+/) # -> nil
- * p s.scan(/\w+/) # -> "is"
- * s.eos? # -> false
- *
- * p s.scan(/\s+/) # -> " "
- * p s.scan(/\w+/) # -> "an"
- * p s.scan(/\s+/) # -> " "
- * p s.scan(/\w+/) # -> "example"
- * p s.scan(/\s+/) # -> " "
- * p s.scan(/\w+/) # -> "string"
- * s.eos? # -> true
- *
- * p s.scan(/\s+/) # -> nil
- * p s.scan(/\w+/) # -> nil
- *
- * Scanning a string means remembering the position of a <i>scan pointer</i>,
- * which is just an index. The point of scanning is to move forward a bit at
- * a time, so matches are sought after the scan pointer; usually immediately
- * after it.
- *
- * Given the string "test string", here are the pertinent scan pointer
- * positions:
- *
- * t e s t s t r i n g
- * 0 1 2 ... 1
- * 0
- *
- * When you #scan for a pattern (a regular expression), the match must occur
- * at the character after the scan pointer. If you use #scan_until, then the
- * match can occur anywhere after the scan pointer. In both cases, the scan
- * pointer moves <i>just beyond</i> the last character of the match, ready to
- * scan again from the next character onwards. This is demonstrated by the
- * example above.
- *
- * == Method Categories
- *
- * There are other methods besides the plain scanners. You can look ahead in
- * the string without actually scanning. You can access the most recent match.
- * You can modify the string being scanned, reset or terminate the scanner,
- * find out or change the position of the scan pointer, skip ahead, and so on.
- *
- * === Advancing the Scan Pointer
- *
- * - #getch
- * - #get_byte
- * - #scan_byte
- * - #scan
- * - #scan_until
- * - #skip
- * - #skip_until
- *
- * === Looking Ahead
- *
- * - #check
- * - #check_until
- * - #exist?
- * - #match?
- * - #peek
- * - #peek_byte
- *
- * === Finding Where we Are
- *
- * - #beginning_of_line? (<tt>#bol?</tt>)
- * - #eos?
- * - #rest?
- * - #rest_size
- * - #pos
- *
- * === Setting Where we Are
- *
- * - #reset
- * - #terminate
- * - #pos=
- *
- * === Match Data
- *
- * - #matched
- * - #matched?
- * - #matched_size
- * - <tt>#[]</tt>
- * - #pre_match
- * - #post_match
- *
- * === Miscellaneous
- *
- * - <tt><<</tt>
- * - #concat
- * - #string
- * - #string=
- * - #unscan
- *
- * There are aliases to several of the methods.
+ * :markup: markdown
+ *
+ * :include: strscan/link_refs.txt
+ * :include: strscan/strscan.md
+ *
*/
void
Init_strscan(void)
@@ -1715,12 +2219,15 @@ Init_strscan(void)
ID id_scanerr = rb_intern("ScanError");
VALUE tmp;
- id_byteslice = rb_intern("byteslice");
+ usascii_encindex = rb_usascii_encindex();
+ utf8_encindex = rb_utf8_encindex();
+ binary_encindex = rb_ascii8bit_encindex();
StringScanner = rb_define_class("StringScanner", rb_cObject);
ScanError = rb_define_class_under(StringScanner, "Error", rb_eStandardError);
if (!rb_const_defined(rb_cObject, id_scanerr)) {
rb_const_set(rb_cObject, id_scanerr, ScanError);
+ rb_deprecate_constant(rb_cObject, "ScanError");
}
tmp = rb_str_new2(STRSCAN_VERSION);
rb_obj_freeze(tmp);
@@ -1728,6 +2235,7 @@ Init_strscan(void)
tmp = rb_str_new2("$Id$");
rb_obj_freeze(tmp);
rb_const_set(StringScanner, rb_intern("Id"), tmp);
+ rb_deprecate_constant(StringScanner, "Id");
rb_define_alloc_func(StringScanner, strscan_s_allocate);
rb_define_private_method(StringScanner, "initialize", strscan_initialize, -1);
@@ -1735,7 +2243,6 @@ Init_strscan(void)
rb_define_singleton_method(StringScanner, "must_C_version", strscan_s_mustc, 0);
rb_define_method(StringScanner, "reset", strscan_reset, 0);
rb_define_method(StringScanner, "terminate", strscan_terminate, 0);
- rb_define_method(StringScanner, "clear", strscan_clear, 0);
rb_define_method(StringScanner, "string", strscan_get_string, 0);
rb_define_method(StringScanner, "string=", strscan_set_string, 1);
rb_define_method(StringScanner, "concat", strscan_concat, 1);
@@ -1760,18 +2267,18 @@ Init_strscan(void)
rb_define_method(StringScanner, "getch", strscan_getch, 0);
rb_define_method(StringScanner, "get_byte", strscan_get_byte, 0);
- rb_define_method(StringScanner, "getbyte", strscan_getbyte, 0);
rb_define_method(StringScanner, "scan_byte", strscan_scan_byte, 0);
rb_define_method(StringScanner, "peek", strscan_peek, 1);
rb_define_method(StringScanner, "peek_byte", strscan_peek_byte, 0);
- rb_define_method(StringScanner, "peep", strscan_peep, 1);
+
+ rb_define_private_method(StringScanner, "scan_base10_integer", strscan_scan_base10_integer, 0);
+ rb_define_private_method(StringScanner, "scan_base16_integer", strscan_scan_base16_integer, 0);
rb_define_method(StringScanner, "unscan", strscan_unscan, 0);
rb_define_method(StringScanner, "beginning_of_line?", strscan_bol_p, 0);
rb_alias(StringScanner, rb_intern("bol?"), rb_intern("beginning_of_line?"));
rb_define_method(StringScanner, "eos?", strscan_eos_p, 0);
- rb_define_method(StringScanner, "empty?", strscan_empty_p, 0);
rb_define_method(StringScanner, "rest?", strscan_rest_p, 0);
rb_define_method(StringScanner, "matched?", strscan_matched_p, 0);
@@ -1786,11 +2293,12 @@ Init_strscan(void)
rb_define_method(StringScanner, "rest", strscan_rest, 0);
rb_define_method(StringScanner, "rest_size", strscan_rest_size, 0);
- rb_define_method(StringScanner, "restsize", strscan_restsize, 0);
rb_define_method(StringScanner, "inspect", strscan_inspect, 0);
rb_define_method(StringScanner, "fixed_anchor?", strscan_fixed_anchor_p, 0);
rb_define_method(StringScanner, "named_captures", strscan_named_captures, 0);
+
+ rb_require("strscan/strscan");
}
diff --git a/ext/strscan/strscan.gemspec b/ext/strscan/strscan.gemspec
index 8a61c7abe6..47180bb8d8 100644
--- a/ext/strscan/strscan.gemspec
+++ b/ext/strscan/strscan.gemspec
@@ -19,16 +19,24 @@ Gem::Specification.new do |s|
files = [
"COPYING",
"LICENSE.txt",
+ "lib/strscan/strscan.rb"
]
+
+ s.require_paths = %w{lib}
+
if RUBY_ENGINE == "jruby"
- s.require_paths = %w{ext/jruby/lib lib}
- files << "ext/jruby/lib/strscan.rb"
files << "lib/strscan.jar"
+ files << "ext/jruby/lib/strscan.rb"
+ s.require_paths += %w{ext/jruby/lib}
s.platform = "java"
else
- s.require_paths = %w{lib}
files << "ext/strscan/extconf.rb"
files << "ext/strscan/strscan.c"
+ s.rdoc_options << "-idoc"
+ s.extra_rdoc_files = [
+ ".rdoc_options",
+ *Dir.glob("doc/strscan/**/*")
+ ]
s.extensions = %w{ext/strscan/extconf.rb}
end
s.files = files
diff --git a/ext/win32/lib/win32/registry.rb b/ext/win32/lib/win32/registry.rb
index 92b95d1bf7..734d6987a2 100644
--- a/ext/win32/lib/win32/registry.rb
+++ b/ext/win32/lib/win32/registry.rb
@@ -2,83 +2,74 @@
require 'fiddle/import'
module Win32
-
-=begin rdoc
-= Win32 Registry
-
-win32/registry is registry accessor library for Win32 platform.
-It uses importer to call Win32 Registry APIs.
-
-== example
- Win32::Registry::HKEY_CURRENT_USER.open('SOFTWARE\foo') do |reg|
- value = reg['foo'] # read a value
- value = reg['foo', Win32::Registry::REG_SZ] # read a value with type
- type, value = reg.read('foo') # read a value
- reg['foo'] = 'bar' # write a value
- reg['foo', Win32::Registry::REG_SZ] = 'bar' # write a value with type
- reg.write('foo', Win32::Registry::REG_SZ, 'bar') # write a value
-
- reg.each_value { |name, type, data| ... } # Enumerate values
- reg.each_key { |key, wtime| ... } # Enumerate subkeys
-
- reg.delete_value(name) # Delete a value
- reg.delete_key(name) # Delete a subkey
- reg.delete_key(name, true) # Delete a subkey recursively
- end
-
-= Reference
-
-== Win32::Registry class
-
---- info
-
---- num_keys
-
---- max_key_length
-
---- num_values
-
---- max_value_name_length
-
---- max_value_length
-
---- descriptor_length
-
---- wtime
- Returns an item of key information.
-
-=== constants
---- HKEY_CLASSES_ROOT
-
---- HKEY_CURRENT_USER
-
---- HKEY_LOCAL_MACHINE
-
---- HKEY_PERFORMANCE_DATA
-
---- HKEY_CURRENT_CONFIG
-
---- HKEY_DYN_DATA
-
- Win32::Registry object whose key is predefined key.
-For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/predefined_keys.asp] article.
-
-=end rdoc
-
+ # :stopdoc:
WCHAR = Encoding::UTF_16LE
WCHAR_NUL = "\0".encode(WCHAR).freeze
WCHAR_CR = "\r".encode(WCHAR).freeze
WCHAR_SIZE = WCHAR_NUL.bytesize
- LOCALE = Encoding.find(Encoding.locale_charmap)
-
+ LOCALE = Encoding::UTF_8
+
+ # :startdoc:
+
+ # win32/registry is registry accessor library for Win32 platform.
+ # It uses importer to call Win32 Registry APIs.
+ #
+ # == example
+ # Win32::Registry::HKEY_CURRENT_USER.open('SOFTWARE\foo') do |reg|
+ # value = reg['foo'] # read a value
+ # value = reg['foo', Win32::Registry::REG_SZ] # read a value with type
+ # type, value = reg.read('foo') # read a value
+ # reg['foo'] = 'bar' # write a value
+ # reg['foo', Win32::Registry::REG_SZ] = 'bar' # write a value with type
+ # reg.write('foo', Win32::Registry::REG_SZ, 'bar') # write a value
+ #
+ # reg.each_value { |name, type, data| ... } # Enumerate values
+ # reg.each_key { |key, wtime| ... } # Enumerate subkeys
+ #
+ # reg.delete_value(name) # Delete a value
+ # reg.delete_key(name) # Delete a subkey
+ # reg.delete_key(name, true) # Delete a subkey recursively
+ # end
+ #
+ # == Predefined keys
+ #
+ # * +HKEY_CLASSES_ROOT+
+ # * +HKEY_CURRENT_USER+
+ # * +HKEY_LOCAL_MACHINE+
+ # * +HKEY_PERFORMANCE_DATA+
+ # * +HKEY_CURRENT_CONFIG+
+ # * +HKEY_DYN_DATA+
+ #
+ # Win32::Registry object whose key is predefined key.
+ # For detail, see the article[https://learn.microsoft.com/en-us/windows/win32/sysinfo/predefined-keys].
+ #
+ # == Value types
+ #
+ # * +REG_NONE+
+ # * +REG_SZ+
+ # * +REG_EXPAND_SZ+
+ # * +REG_BINARY+
+ # * +REG_DWORD+
+ # * +REG_DWORD_BIG_ENDIAN+
+ # * +REG_LINK+
+ # * +REG_MULTI_SZ+
+ # * +REG_RESOURCE_LIST+
+ # * +REG_FULL_RESOURCE_DESCRIPTOR+
+ # * +REG_RESOURCE_REQUIREMENTS_LIST+
+ # * +REG_QWORD+
+ #
+ # For detail, see the article[https://learn.microsoft.com/en-us/windows/win32/sysinfo/registry-value-types].
+ #
class Registry
+ # :stopdoc:
+
#
# For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/registry.asp].
#
# --- HKEY_*
#
- # Predefined key ((*handle*)).
+ # Predefined key *handle*.
# These are Integer, not Win32::Registry.
#
# --- REG_*
@@ -100,6 +91,7 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
# If the key is created newly or opened existing key.
# See also Registry#disposition method.
module Constants
+ # :stopdoc:
HKEY_CLASSES_ROOT = 0x80000000
HKEY_CURRENT_USER = 0x80000001
HKEY_LOCAL_MACHINE = 0x80000002
@@ -115,7 +107,6 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
REG_EXPAND_SZ = 2
REG_BINARY = 3
REG_DWORD = 4
- REG_DWORD_LITTLE_ENDIAN = 4
REG_DWORD_BIG_ENDIAN = 5
REG_LINK = 6
REG_MULTI_SZ = 7
@@ -163,22 +154,29 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
end
include Constants
include Enumerable
+ # :startdoc:
#
# Error
#
class Error < ::StandardError
+ # :stopdoc:
module Kernel32
extend Fiddle::Importer
dlload "kernel32.dll"
end
FormatMessageW = Kernel32.extern "int FormatMessageW(int, void *, int, int, void *, int, void *)", :stdcall
+ # :startdoc:
+
+ # new(code) -> error object
+ #
+ # Initializes the message for Win32 API error +code+.
def initialize(code)
@code = code
buff = WCHAR_NUL * 1024
lang = 0
begin
- len = FormatMessageW.call(0x1200, 0, code, lang, buff, 1024, 0)
+ len = FormatMessageW.call(0x1200, nil, code, lang, buff, 1024, nil)
msg = buff.byteslice(0, len * WCHAR_SIZE)
msg.delete!(WCHAR_CR)
msg.chomp!
@@ -190,6 +188,8 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
end
super msg
end
+
+ # Win32 API error code.
attr_reader :code
end
@@ -197,8 +197,9 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
# Predefined Keys
#
class PredefinedKey < Registry
+ # :stopdoc:
def initialize(hkey, keyname)
- @hkey = hkey
+ @hkey = Fiddle::Pointer.new(hkey)
@parent = nil
@keyname = keyname
@disposition = REG_OPENED_EXISTING_KEY
@@ -224,6 +225,7 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
# Win32 APIs
#
module API
+ # :stopdoc:
include Constants
extend Fiddle::Importer
dlload "advapi32.dll"
@@ -238,7 +240,7 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
"long RegDeleteKeyW(void *, void *)",
"long RegFlushKey(void *)",
"long RegCloseKey(void *)",
- "long RegQueryInfoKey(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *)",
+ "long RegQueryInfoKeyW(void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *, void *)",
].each do |fn|
cfunc = extern fn, :stdcall
const_set cfunc.name.intern, cfunc
@@ -285,7 +287,7 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
end
def make_wstr(str)
- str.encode(WCHAR)
+ (str+"\0").encode(WCHAR)
end
def OpenKey(hkey, name, opt, desired)
@@ -298,14 +300,14 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
result = packhandle(0)
disp = packdw(0)
check RegCreateKeyExW.call(hkey, make_wstr(name), 0, 0, opt, desired,
- 0, result, disp)
+ nil, result, disp)
[ unpackhandle(result), unpackdw(disp) ]
end
def EnumValue(hkey, index)
name = WCHAR_NUL * Constants::MAX_KEY_LENGTH
size = packdw(Constants::MAX_KEY_LENGTH)
- check RegEnumValueW.call(hkey, index, name, size, 0, 0, 0, 0)
+ check RegEnumValueW.call(hkey, index, name, size, nil, nil, nil, nil)
name.byteslice(0, unpackdw(size) * WCHAR_SIZE)
end
@@ -313,7 +315,7 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
name = WCHAR_NUL * Constants::MAX_KEY_LENGTH
size = packdw(Constants::MAX_KEY_LENGTH)
wtime = ' ' * 8
- check RegEnumKeyExW.call(hkey, index, name, size, 0, 0, 0, wtime)
+ check RegEnumKeyExW.call(hkey, index, name, size, nil, nil, nil, wtime)
[ name.byteslice(0, unpackdw(size) * WCHAR_SIZE), unpackqw(wtime) ]
end
@@ -321,9 +323,9 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
type = packdw(0)
size = packdw(0)
name = make_wstr(name)
- check RegQueryValueExW.call(hkey, name, 0, type, 0, size)
+ check RegQueryValueExW.call(hkey, name, nil, type, nil, size)
data = "\0".b * unpackdw(size)
- check RegQueryValueExW.call(hkey, name, 0, type, data, size)
+ check RegQueryValueExW.call(hkey, name, nil, type, data, size)
[ unpackdw(type), data[0, unpackdw(size)] ]
end
@@ -360,19 +362,21 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
maxvaluelen = packdw(0)
secdescs = packdw(0)
wtime = ' ' * 8
- check RegQueryInfoKey.call(hkey, 0, 0, 0, subkeys, maxsubkeylen, 0,
+ check RegQueryInfoKeyW.call(hkey, 0, 0, 0, subkeys, maxsubkeylen, 0,
values, maxvaluenamelen, maxvaluelen, secdescs, wtime)
[ unpackdw(subkeys), unpackdw(maxsubkeylen), unpackdw(values),
unpackdw(maxvaluenamelen), unpackdw(maxvaluelen),
unpackdw(secdescs), unpackqw(wtime) ]
end
end
+ # :startdoc:
#
- # Replace %\w+% into the environment value of what is contained between the %'s
+ # Replace <tt>%</tt>-enclosed substrings in +str+ into the
+ # environment value of what is contained between the <tt>%</tt>s.
# This method is used for REG_EXPAND_SZ.
#
- # For detail, see expandEnvironmentStrings[http://msdn.microsoft.com/library/en-us/sysinfo/base/expandenvironmentstrings.asp] \Win32 \API.
+ # For detail, see ExpandEnvironmentStrings[https://learn.microsoft.com/en-us/windows/win32/api/processenv/nf-processenv-expandenvironmentstringsw] \Win32 \API.
#
def self.expand_environ(str)
str.gsub(Regexp.compile("%([^%]+)%".encode(str.encoding))) {
@@ -392,21 +396,21 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
end.freeze
#
- # Convert registry type value to readable string.
+ # Convert registry type value +type+ to readable string.
#
def self.type2name(type)
@@type2name[type] || type.to_s
end
#
- # Convert 64-bit FILETIME integer into Time object.
+ # Convert 64-bit FILETIME integer +wtime+ into Time object.
#
def self.wtime2time(wtime)
Time.at((wtime - 116444736000000000) / 10000000)
end
#
- # Convert Time object or Integer object into 64-bit FILETIME.
+ # Convert Time object or Integer object +time+ into 64-bit FILETIME.
#
def self.time2wtime(time)
time.to_i * 10000000 + 116444736000000000
@@ -418,19 +422,22 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
private_class_method :new
#
- # --- Registry.open(key, subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED)
+ # call-seq:
+ # open(key, subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED)
+ # open(key, subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED) { |reg| ... }
#
- # --- Registry.open(key, subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED) { |reg| ... }
+ # Open the registry key +subkey+ under +key+.
+ # +key+ is Win32::Registry object of parent key.
+ # You can use {predefined key}[rdoc-ref:Win32::Registry@Predefined+keys] +HKEY_+*.
+ # +desired+ and +opt+ is access mask and key option.
#
- # Open the registry key subkey under key.
- # key is Win32::Registry object of parent key.
- # You can use predefined key HKEY_* (see Constants)
- # desired and opt is access mask and key option.
# For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/regopenkeyex.asp].
- # If block is given, the key is closed automatically.
+ #
+ # If block is given, the key +reg+ is yielded and closed
+ # automatically after the block exists.
def self.open(hkey, subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED)
subkey = subkey.chomp('\\')
- newkey = API.OpenKey(hkey.hkey, subkey, opt, desired)
+ newkey = API.OpenKey(hkey.instance_variable_get(:@hkey), subkey, opt, desired)
obj = new(newkey, hkey, subkey, REG_OPENED_EXISTING_KEY)
if block_given?
begin
@@ -444,20 +451,22 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
end
#
- # --- Registry.create(key, subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED)
- #
- # --- Registry.create(key, subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED) { |reg| ... }
+ # call-seq:
+ # create(key, subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED)
+ # create(key, subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED) { |reg| ... }
#
- # Create or open the registry key subkey under key.
- # You can use predefined key HKEY_* (see Constants)
+ # Create or open the registry key +subkey+ under +key+.
+ # You can use {predefined key}[rdoc-ref:Win32::Registry@Predefined+keys] +HKEY_+*.
+ # +desired+ and +opt+ is access mask and key option.
#
- # If subkey is already exists, key is opened and Registry#created?
+ # If +subkey+ is already exists, key is opened and Registry#created?
# method will return false.
#
- # If block is given, the key is closed automatically.
+ # If block is given, the key +reg+ is yielded and closed
+ # automatically after the block exists.
#
def self.create(hkey, subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED)
- newkey, disp = API.CreateKey(hkey.hkey, subkey, opt, desired)
+ newkey, disp = API.CreateKey(hkey.instance_variable_get(:@hkey), subkey, opt, desired)
obj = new(newkey, hkey, subkey, disp)
if block_given?
begin
@@ -476,10 +485,12 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
@@final = proc { |hkey| proc { API.CloseKey(hkey[0]) if hkey[0] } }
#
- # initialize
+ # :nodoc:
+ #
+ # Use self.open, self.create, #open and #create.
#
def initialize(hkey, parent, keyname, disposition)
- @hkey = hkey
+ @hkey = Fiddle::Pointer.new(hkey)
@parent = parent
@keyname = keyname
@disposition = disposition
@@ -487,9 +498,7 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
ObjectSpace.define_finalizer self, @@final.call(@hkeyfinal)
end
- # Returns key handle value.
- attr_reader :hkey
- # Win32::Registry object of parent key, or nil if predefeined key.
+ # Win32::Registry object of parent key, or nil if predefined key.
attr_reader :parent
# Same as subkey value of Registry.open or
# Registry.create method.
@@ -497,8 +506,13 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
# Disposition value (REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY).
attr_reader :disposition
+ # Returns key handle value.
+ def hkey
+ @hkey.to_i
+ end
+
#
- # Returns if key is created ((*newly*)).
+ # Returns +true+ if key is created *newly*.
# (see Registry.create) -- basically you call create
# then when you call created? on the instance returned
# it will tell if it was successful or not
@@ -515,7 +529,7 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
end
#
- # Full path of key such as 'HKEY_CURRENT_USER\SOFTWARE\foo\bar'.
+ # Full path of key such as <tt>'HKEY_CURRENT_USER\SOFTWARE\foo\bar'</tt>.
#
def name
parent = self
@@ -526,6 +540,9 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
name
end
+ #
+ # Retruns inspected string
+ #
def inspect
"\#<Win32::Registry key=#{name.inspect}>"
end
@@ -538,14 +555,14 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
end
#
- # Same as Win32::Registry.open (self, subkey, desired, opt)
+ # Same as Win32::Registry.open(self, subkey, desired, opt)
#
def open(subkey, desired = KEY_READ, opt = REG_OPTION_RESERVED, &blk)
self.class.open(self, subkey, desired, opt, &blk)
end
#
- # Same as Win32::Registry.create (self, subkey, desired, opt)
+ # Same as Win32::Registry.create(self, subkey, desired, opt)
#
def create(subkey, desired = KEY_ALL_ACCESS, opt = REG_OPTION_RESERVED, &blk)
self.class.create(self, subkey, desired, opt, &blk)
@@ -563,9 +580,16 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
end
#
- # Enumerate values.
+ # Enumerate all values in this registry path.
+ #
+ # For each value it yields key, type and data.
+ #
+ # key is a String which contains name of key.
+ # type is a type constant kind of +Win32::Registry::REG_+*
+ # data is the value of this key.
#
def each_value
+ return enum_for(:each_value) unless block_given?
index = 0
while true
begin
@@ -596,13 +620,16 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
end
#
- # Enumerate subkeys.
+ # Enumerate all subkeys.
+ #
+ # For each subkey it yields subkey and wtime.
#
# subkey is String which contains name of subkey.
# wtime is last write time as FILETIME (64-bit integer).
# (see Registry.wtime2time)
#
def each_key
+ return enum_for(:each_key) unless block_given?
index = 0
while true
begin
@@ -627,21 +654,23 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
end
# Read a registry value named name and return array of
- # [ type, data ].
- # When name is nil, the `default' value is read.
- # type is value type. (see Win32::Registry::Constants module)
- # data is value data, its class is:
- # :REG_SZ, REG_EXPAND_SZ
+ # <tt>[ type, data ]</tt>.
+ # When name is +nil+, the `default' value is read.
+ #
+ # +type+ is {value type}[rdoc-ref:Win32::Registry@Value+types].
+ #
+ # +data+ is value data, its class is:
+ # REG_SZ, REG_EXPAND_SZ::
# String
- # :REG_MULTI_SZ
+ # REG_MULTI_SZ::
# Array of String
- # :REG_DWORD, REG_DWORD_BIG_ENDIAN, REG_QWORD
+ # REG_DWORD, REG_DWORD_BIG_ENDIAN, REG_QWORD::
# Integer
- # :REG_BINARY, REG_NONE
+ # REG_BINARY, REG_NONE::
# String (contains binary data)
#
- # When rtype is specified, the value type must be included by
- # rtype array, or TypeError is raised.
+ # When _rtype_ is specified, the value type must be included by
+ # _rtype_ array, or +TypeError+ is raised.
def read(name, *rtype)
type, data = API.QueryValue(@hkey, name)
unless rtype.empty? or rtype.include?(type)
@@ -674,9 +703,9 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
# 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.
+ # REG_DWORD_BIG_ENDIAN, nor REG_QWORD, +TypeError+ is raised.
#
- # The meaning of rtype is the same as for the #read method.
+ # The meaning of _rtype_ is the same as for the #read method.
#
def [](name, *rtype)
type, data = read(name, *rtype)
@@ -693,7 +722,7 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
# Read a REG_SZ(read_s), REG_DWORD(read_i), or REG_BINARY(read_bin)
# registry value named name.
#
- # If the values type does not match, TypeError is raised.
+ # If the values type does not match, +TypeError+ is raised.
def read_s(name)
read(name, REG_SZ)[1]
end
@@ -702,7 +731,7 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
# Read a REG_SZ or REG_EXPAND_SZ registry value named name.
#
# If the value type is REG_EXPAND_SZ, environment variables are replaced.
- # Unless the value type is REG_SZ or REG_EXPAND_SZ, TypeError is raised.
+ # Unless the value type is REG_SZ or REG_EXPAND_SZ, +TypeError+ is raised.
#
def read_s_expand(name)
type, data = read(name, REG_SZ, REG_EXPAND_SZ)
@@ -717,7 +746,7 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
# Read a REG_SZ(read_s), REG_DWORD(read_i), or REG_BINARY(read_bin)
# registry value named name.
#
- # If the values type does not match, TypeError is raised.
+ # If the values type does not match, +TypeError+ is raised.
#
def read_i(name)
read(name, REG_DWORD, REG_DWORD_BIG_ENDIAN, REG_QWORD)[1]
@@ -727,7 +756,7 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
# Read a REG_SZ(read_s), REG_DWORD(read_i), or REG_BINARY(read_bin)
# registry value named name.
#
- # If the values type does not match, TypeError is raised.
+ # If the values type does not match, +TypeError+ is raised.
#
def read_bin(name)
read(name, REG_BINARY)[1]
@@ -737,7 +766,7 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
# Write data to a registry value named name.
# When name is nil, write to the `default' value.
#
- # type is type value. (see Registry::Constants module)
+ # +type+ is {value type}[rdoc-ref:Win32::Registry@Value+types].
# Class of data must be same as which #read
# method returns.
#
@@ -766,11 +795,12 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
#
# If wtype is specified, the value type is it.
# Otherwise, the value type is depend on class of value:
- # :Integer
+ #
+ # Integer::
# REG_DWORD
- # :String
+ # String::
# REG_SZ
- # :Array
+ # Array::
# REG_MULTI_SZ
#
def []=(name, rtype, value = nil)
@@ -867,19 +897,19 @@ For detail, see the MSDN[http://msdn.microsoft.com/library/en-us/sysinfo/base/pr
#
# Returns key information as Array of:
- # :num_keys
+ # num_keys::
# The number of subkeys.
- # :max_key_length
+ # max_key_length::
# Maximum length of name of subkeys.
- # :num_values
+ # num_values::
# The number of values.
- # :max_value_name_length
+ # max_value_name_length::
# Maximum length of name of values.
- # :max_value_length
+ # max_value_length::
# Maximum length of value of values.
- # :descriptor_length
+ # descriptor_length::
# Length of security descriptor.
- # :wtime
+ # wtime::
# Last write time as FILETIME(64-bit integer)
#
# For detail, see RegQueryInfoKey[http://msdn.microsoft.com/library/en-us/sysinfo/base/regqueryinfokey.asp] Win32 API.
diff --git a/ext/win32/lib/win32/resolv.rb b/ext/win32/lib/win32/resolv.rb
index d06658f0aa..8d631a2140 100644
--- a/ext/win32/lib/win32/resolv.rb
+++ b/ext/win32/lib/win32/resolv.rb
@@ -4,12 +4,22 @@
=end
-require 'win32/registry'
+require 'win32/resolv.so'
module Win32
module Resolv
- API = Registry::API
- Error = Registry::Error
+ # Error at Win32 API
+ class Error < StandardError
+ # +code+ Win32 Error code
+ # +message+ Formatted message for +code+
+ def initialize(code, message)
+ super(message)
+ @code = code
+ end
+
+ # Win32 error code
+ attr_reader :code
+ end
def self.get_hosts_path
path = get_hosts_dir
@@ -34,98 +44,59 @@ module Win32
end
[ search, nameserver ]
end
- end
-end
-
-begin
- require 'win32/resolv.so'
-rescue LoadError
-end
-
-module Win32
-#====================================================================
-# Windows NT
-#====================================================================
- module Resolv
- module SZ
- refine Registry do
- # ad hoc workaround for broken registry
- def read_s(key)
- type, str = read(key)
- unless type == Registry::REG_SZ
- warn "Broken registry, #{name}\\#{key} was #{Registry.type2name(type)}, ignored"
- return String.new
- end
- str
- end
- end
- end
- using SZ
-
- TCPIP_NT = 'SYSTEM\CurrentControlSet\Services\Tcpip\Parameters'
class << self
private
def get_hosts_dir
- Registry::HKEY_LOCAL_MACHINE.open(TCPIP_NT) do |reg|
- reg.read_s_expand('DataBasePath')
+ tcpip_params do |params|
+ params.value('DataBasePath')
end
end
def get_info
search = nil
nameserver = get_dns_server_list
- Registry::HKEY_LOCAL_MACHINE.open(TCPIP_NT) do |reg|
- begin
- slist = reg.read_s('SearchList')
- search = slist.split(/,\s*/) unless slist.empty?
- rescue Registry::Error
- end
+
+ tcpip_params do |params|
+ slist = params.value('SearchList')
+ search = slist.split(/,\s*/) if slist and !slist.empty?
if add_search = search.nil?
search = []
- begin
- nvdom = reg.read_s('NV Domain')
- unless nvdom.empty?
- @search = [ nvdom ]
- if reg.read_i('UseDomainNameDevolution') != 0
- if /^\w+\./ =~ nvdom
- devo = $'
- end
+ domain = params.value('Domain')
+
+ if domain and !domain.empty?
+ search = [ domain ]
+ udmnd = params.value('UseDomainNameDevolution')
+ if udmnd&.nonzero?
+ if /^\w+\./ =~ domain
+ devo = $'
end
end
- rescue Registry::Error
end
end
- reg.open('Interfaces') do |h|
- h.each_key do |iface, |
- h.open(iface) do |regif|
- next unless ns = %w[NameServer DhcpNameServer].find do |key|
- begin
- ns = regif.read_s(key)
- rescue Registry::Error
- else
- break ns.split(/[,\s]\s*/) unless ns.empty?
- end
- end
- next if (nameserver & ns).empty?
+ params.open('Interfaces') do |reg|
+ reg.each_key do |iface|
+ next unless ns = %w[NameServer DhcpNameServer].find do |key|
+ ns = iface.value(key)
+ break ns.split(/[,\s]\s*/) if ns and !ns.empty?
+ end
+
+ next if (nameserver & ns).empty?
- if add_search
- begin
- [ 'Domain', 'DhcpDomain' ].each do |key|
- dom = regif.read_s(key)
- unless dom.empty?
- search.concat(dom.split(/,\s*/))
- break
- end
- end
- rescue Registry::Error
+ if add_search
+ [ 'Domain', 'DhcpDomain' ].each do |key|
+ dom = iface.value(key)
+ if dom and !dom.empty?
+ search.concat(dom.split(/,\s*/))
+ break
end
end
end
end
end
+
search << devo if add_search and devo
end
[ search.uniq, nameserver.uniq ]
diff --git a/ext/win32/lib/win32/sspi.rb b/ext/win32/lib/win32/sspi.rb
deleted file mode 100644
index 20205fd4d6..0000000000
--- a/ext/win32/lib/win32/sspi.rb
+++ /dev/null
@@ -1,338 +0,0 @@
-# frozen_string_literal: false
-#
-# = win32/sspi.rb
-#
-# Copyright (c) 2006-2007 Justin Bailey
-#
-# Written and maintained by Justin Bailey <jgbailey@gmail.com>.
-#
-# This program is free software. You can re-distribute and/or
-# modify this program under the same terms of ruby itself ---
-# Ruby Distribution License or GNU General Public License.
-#
-
-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
- 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 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 <token>" 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::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
diff --git a/ext/win32/resolv/extconf.rb b/ext/win32/resolv/extconf.rb
index 01f3df730a..5ee4c0d7c4 100644
--- a/ext/win32/resolv/extconf.rb
+++ b/ext/win32/resolv/extconf.rb
@@ -1,3 +1,7 @@
-if have_library('iphlpapi', 'GetNetworkParams')
+require 'mkmf'
+if RUBY_ENGINE == "ruby" and have_library('iphlpapi', 'GetNetworkParams', ['windows.h', 'iphlpapi.h'])
+ have_library('advapi32', 'RegGetValueW', ['windows.h'])
create_makefile('win32/resolv')
+else
+ File.write('Makefile', "all clean install:\n\t@echo Done: $(@)\n")
end
diff --git a/ext/win32/resolv/resolv.c b/ext/win32/resolv/resolv.c
index 8a50ef7824..b2d377df9f 100644
--- a/ext/win32/resolv/resolv.c
+++ b/ext/win32/resolv/resolv.c
@@ -1,22 +1,56 @@
#include <ruby.h>
#include <ruby/encoding.h>
#include <windows.h>
+#include <windns.h>
#ifndef NTDDI_VERSION
#define NTDDI_VERSION 0x06000000
#endif
#include <iphlpapi.h>
+#ifndef numberof
+#define numberof(array) ((int)(sizeof(array) / sizeof((array)[0])))
+#endif
+
static VALUE
w32error_make_error(DWORD e)
{
- VALUE code = ULONG2NUM(e);
- return rb_class_new_instance(1, &code, rb_path2class("Win32::Resolv::Error"));
+ char buffer[512], *p;
+ DWORD source = 0;
+ VALUE args[2];
+ if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS, &source, e,
+ MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
+ buffer, sizeof(buffer), NULL)) {
+ snprintf(buffer, sizeof(buffer), "Unknown Error %lu", (unsigned long)e);
+ }
+ p = buffer;
+ while ((p = strpbrk(p, "\r\n")) != NULL) {
+ memmove(p, p + 1, strlen(p));
+ if (!p[1]) {
+ p[0] = '\0';
+ break;
+ }
+ }
+ args[0] = ULONG2NUM(e);
+ args[1] = rb_str_new_cstr(buffer);
+ return rb_class_new_instance(2, args, rb_path2class("Win32::Resolv::Error"));
}
static void
-w32error_raise(DWORD e)
+w32error_check(DWORD e)
+{
+ if (e != NO_ERROR) {
+ rb_exc_raise(w32error_make_error(e));
+ }
+}
+
+static VALUE
+wchar_to_utf8(const WCHAR *w, int n)
{
- rb_exc_raise(w32error_make_error(e));
+ int clen = WideCharToMultiByte(CP_UTF8, 0, w, n, NULL, 0, NULL, NULL);
+ VALUE str = rb_enc_str_new(NULL, clen, rb_utf8_encoding());
+ WideCharToMultiByte(CP_UTF8, 0, w, n, RSTRING_PTR(str), clen, NULL, NULL);
+ return str;
}
static VALUE
@@ -28,9 +62,7 @@ get_dns_server_list(VALUE self)
VALUE buf, nameservers = Qnil;
ret = GetNetworkParams(NULL, &buflen);
- if (ret != NO_ERROR && ret != ERROR_BUFFER_OVERFLOW) {
- w32error_raise(ret);
- }
+ if (ret != ERROR_BUFFER_OVERFLOW) w32error_check(ret);
fixedinfo = ALLOCV(buf, buflen);
ret = GetNetworkParams(fixedinfo, &buflen);
if (ret == NO_ERROR) {
@@ -44,18 +76,181 @@ get_dns_server_list(VALUE self)
} while ((ipaddr = ipaddr->Next) != NULL);
}
ALLOCV_END(buf);
- if (ret != NO_ERROR) w32error_raise(ret);
+ w32error_check(ret);
return nameservers;
}
+
+static const WCHAR TCPIP_Params[] = L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters";
+
+static void
+hkey_finalize(void *p)
+{
+ RegCloseKey((HKEY)p);
+}
+
+static const rb_data_type_t hkey_type = {
+ "RegKey",
+ {0, hkey_finalize},
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
+};
+
+static VALUE
+hkey_close(VALUE self)
+{
+ RegCloseKey((HKEY)DATA_PTR(self));
+ DATA_PTR(self) = 0;
+ return self;
+}
+
+static VALUE reg_key_class;
+
+static VALUE
+reg_open_key(VALUE klass, HKEY hkey, const WCHAR *wname)
+{
+ VALUE k = TypedData_Wrap_Struct(klass, &hkey_type, NULL);
+ DWORD e = RegOpenKeyExW(hkey, wname, 0, KEY_READ, (HKEY *)&DATA_PTR(k));
+ if (e == ERROR_FILE_NOT_FOUND) return Qnil;
+ w32error_check(e);
+ return rb_ensure(rb_yield, k, hkey_close, k);
+}
+
+static VALUE
+tcpip_params_open(VALUE klass)
+{
+ return reg_open_key(reg_key_class, HKEY_LOCAL_MACHINE, TCPIP_Params);
+}
+
+static int
+to_wname(VALUE *name, WCHAR *wname, int wlen)
+{
+ const char *n = StringValueCStr(*name);
+ int nlen = RSTRING_LEN(*name);
+ int len = MultiByteToWideChar(CP_UTF8, 0, n, nlen, wname, wlen - 1);
+ if (len == 0) w32error_check(GetLastError());
+ if (len >= wlen) rb_raise(rb_eArgError, "too long name");
+ wname[len] = L'\0';
+ return len;
+}
+
+static VALUE
+reg_open(VALUE self, VALUE name)
+{
+ HKEY hkey = DATA_PTR(self);
+ WCHAR wname[256];
+ to_wname(&name, wname, numberof(wname));
+ return reg_open_key(CLASS_OF(self), hkey, wname);
+}
+
+
+static VALUE
+reg_each_key(VALUE self)
+{
+ WCHAR wname[256];
+ HKEY hkey = DATA_PTR(self);
+ VALUE k = TypedData_Wrap_Struct(CLASS_OF(self), &hkey_type, NULL);
+ DWORD i, e, n;
+ for (i = 0; n = numberof(wname), (e = RegEnumKeyExW(hkey, i, wname, &n, NULL, NULL, NULL, NULL)) == ERROR_SUCCESS; i++) {
+ e = RegOpenKeyExW(hkey, wname, 0, KEY_READ, (HKEY *)&DATA_PTR(k));
+ w32error_check(e);
+ rb_ensure(rb_yield, k, hkey_close, k);
+ }
+ if (e != ERROR_NO_MORE_ITEMS) w32error_check(e);
+ return self;
+}
+
+static inline DWORD
+swap_dw(DWORD x)
+{
+#if defined(_MSC_VER)
+ return _byteswap_ulong(x);
+#else
+ return __builtin_bswap32(x);
+#endif
+}
+
+static VALUE
+reg_value(VALUE self, VALUE name)
+{
+ HKEY hkey = DATA_PTR(self);
+ DWORD type = 0, size = 0, e;
+ VALUE result, value_buffer;
+ void *buffer;
+ WCHAR wname[256];
+ to_wname(&name, wname, numberof(wname));
+ e = RegGetValueW(hkey, NULL, wname, RRF_RT_ANY, &type, NULL, &size);
+ if (e == ERROR_FILE_NOT_FOUND) return Qnil;
+ w32error_check(e);
+# define get_value_2nd(data, dsize) do { \
+ DWORD type2 = type; \
+ w32error_check(RegGetValueW(hkey, NULL, wname, RRF_RT_ANY, &type2, data, dsize)); \
+ if (type != type2) { \
+ rb_raise(rb_eRuntimeError, "registry value type changed %lu -> %lu", \
+ (unsigned long)type, (unsigned long)type2); \
+ } \
+ } while (0)
+
+ switch (type) {
+ case REG_DWORD: case REG_DWORD_BIG_ENDIAN:
+ {
+ DWORD d;
+ if (size != sizeof(d)) rb_raise(rb_eRuntimeError, "invalid size returned: %lu", (unsigned long)size);
+ w32error_check(RegGetValueW(hkey, NULL, wname, RRF_RT_REG_DWORD, &type, &d, &size));
+ if (type == REG_DWORD_BIG_ENDIAN) d = swap_dw(d);
+ return ULONG2NUM(d);
+ }
+ case REG_QWORD:
+ {
+ QWORD q;
+ if (size != sizeof(q)) rb_raise(rb_eRuntimeError, "invalid size returned: %lu", (unsigned long)size);
+ w32error_check(RegGetValueW(hkey, NULL, wname, RRF_RT_REG_QWORD, &type, &q, &size));
+ return ULL2NUM(q);
+ }
+ case REG_SZ: case REG_MULTI_SZ: case REG_EXPAND_SZ:
+ if (size % sizeof(WCHAR)) rb_raise(rb_eRuntimeError, "invalid size returned: %lu", (unsigned long)size);
+ buffer = ALLOCV_N(char, value_buffer, size);
+ get_value_2nd(buffer, &size);
+ if (type == REG_MULTI_SZ) {
+ const WCHAR *w = (WCHAR *)buffer;
+ result = rb_ary_new();
+ size /= sizeof(WCHAR);
+ size -= 1;
+ for (size_t i = 0; i < size; ++i) {
+ int n = lstrlenW(w+i);
+ rb_ary_push(result, wchar_to_utf8(w+i, n));
+ i += n;
+ }
+ }
+ else {
+ result = wchar_to_utf8((WCHAR *)buffer, lstrlenW((WCHAR *)buffer));
+ }
+ ALLOCV_END(value_buffer);
+ break;
+ default:
+ result = rb_str_new(0, size);
+ get_value_2nd(RSTRING_PTR(result), &size);
+ rb_str_set_len(result, size);
+ break;
+ }
+ return result;
+}
+
void
InitVM_resolv(void)
{
VALUE mWin32 = rb_define_module("Win32");
VALUE resolv = rb_define_module_under(mWin32, "Resolv");
VALUE singl = rb_singleton_class(resolv);
+ VALUE regkey = rb_define_class_under(resolv, "registry key", rb_cObject);
+
+ reg_key_class = regkey;
+ rb_undef_alloc_func(regkey);
rb_define_private_method(singl, "get_dns_server_list", get_dns_server_list, 0);
+ rb_define_private_method(singl, "tcpip_params", tcpip_params_open, 0);
+ rb_define_method(regkey, "open", reg_open, 1);
+ rb_define_method(regkey, "each_key", reg_each_key, 0);
+ rb_define_method(regkey, "value", reg_value, 1);
}
void
diff --git a/ext/win32/win32-registry.gemspec b/ext/win32/win32-registry.gemspec
new file mode 100644
index 0000000000..9bd57bd7d1
--- /dev/null
+++ b/ext/win32/win32-registry.gemspec
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+Gem::Specification.new do |spec|
+ spec.name = "win32-registry"
+ spec.version = "0.1.2"
+ spec.authors = ["U.Nakamura"]
+ spec.email = ["usa@garbagecollect.jp"]
+
+ spec.summary = %q{Provides an interface to the Windows Registry in Ruby}
+ spec.description = spec.summary
+ spec.homepage = "https://github.com/ruby/win32-registry"
+ spec.required_ruby_version = ">= 2.6.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.
+ excludes = %w[
+ bin/ test/ spec/ features/ rakelib/
+ .git* .mailmap appveyor Rakefile Gemfile
+ ]
+ git_files = %w[git ls-files -z --] + excludes.map {|x| ":^/#{x}"}
+ spec.files = IO.popen(git_files, chdir: __dir__, &:read).split("\x0")
+ spec.bindir = "exe"
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
+ spec.require_paths = ["lib"]
+
+ spec.add_dependency "fiddle", "~> 1.0"
+end
diff --git a/ext/win32ole/.document b/ext/win32ole/.document
deleted file mode 100644
index decba0135a..0000000000
--- a/ext/win32ole/.document
+++ /dev/null
@@ -1 +0,0 @@
-*.[ch]
diff --git a/ext/win32ole/depend b/ext/win32ole/depend
deleted file mode 100644
index c8445ad5fa..0000000000
--- a/ext/win32ole/depend
+++ /dev/null
@@ -1,12 +0,0 @@
-WIN32OLE_HEADERS = $(HDRS) $(ruby_headers)
-win32ole.o : win32ole.c $(WIN32OLE_HEADERS)
-win32ole_variant_m.o : win32ole_variant_m.c $(WIN32OLE_HEADERS)
-win32ole_typelib.o : win32ole_typelib.c $(WIN32OLE_HEADERS)
-win32ole_type.o : win32ole_type.c $(WIN32OLE_HEADERS)
-win32ole_variable.o : win32ole_variable.c $(WIN32OLE_HEADERS)
-win32ole_method.o : win32ole_method.c $(WIN32OLE_HEADERS)
-win32ole_param.o : win32ole_param.c $(WIN32OLE_HEADERS)
-win32ole_variant.o : win32ole_variant.c $(WIN32OLE_HEADERS)
-win32ole_event.o : win32ole_event.c $(WIN32OLE_HEADERS)
-win32ole_record.o : win32ole_record.c $(WIN32OLE_HEADERS)
-win32ole_error.o : win32ole_error.c $(WIN32OLE_HEADERS)
diff --git a/ext/win32ole/extconf.rb b/ext/win32ole/extconf.rb
deleted file mode 100644
index d2044663a9..0000000000
--- a/ext/win32ole/extconf.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: false
-#----------------------------------
-# extconf.rb
-# $Revision$
-#----------------------------------
-require 'mkmf'
-
-case RUBY_PLATFORM
-when /cygwin/
- inc = nil
- lib = '/usr/lib/w32api'
-end
-
-dir_config("win32", inc, lib)
-
-def create_win32ole_makefile
- if have_library("ole32") and
- have_library("oleaut32") and
- have_library("uuid", "&CLSID_CMultiLanguage", "mlang.h") and
- have_library("user32") and
- have_library("kernel32") and
- have_library("advapi32") and
- have_header("windows.h")
- unless have_type("IMultiLanguage2", "mlang.h")
- have_type("IMultiLanguage", "mlang.h")
- end
- spec = nil
- checking_for('thread_specific', '%s') do
- spec = %w[__declspec(thread) __thread].find {|th|
- try_compile("#{th} int foo;", "", :werror => true)
- }
- spec or 'no'
- end
- $defs << "-DRB_THREAD_SPECIFIC=#{spec}" if spec
- create_makefile("win32ole")
- end
-end
-
-
-case RUBY_PLATFORM
-when /mswin/
- $CFLAGS.sub!(/((?:\A|\s)[-\/])W\d(?=\z|\s)/, '\1W3') or
- $CFLAGS += ' -W3'
-end
-create_win32ole_makefile
diff --git a/ext/win32ole/lib/win32ole.rb b/ext/win32ole/lib/win32ole.rb
deleted file mode 100644
index f5c8a52c4a..0000000000
--- a/ext/win32ole/lib/win32ole.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-begin
- require 'win32ole.so'
-rescue LoadError
- # do nothing
-end
-
-if defined?(WIN32OLE)
- class WIN32OLE
-
- #
- # By overriding Object#methods, WIN32OLE might
- # work well with did_you_mean gem.
- # This is experimental.
- #
- # require 'win32ole'
- # dict = WIN32OLE.new('Scripting.Dictionary')
- # dict.Ade('a', 1)
- # #=> Did you mean? Add
- #
- def methods(*args)
- super + ole_methods_safely.map(&:name).map(&:to_sym)
- end
-
- private
-
- def ole_methods_safely
- ole_methods
- rescue WIN32OLE::QueryInterfaceError
- []
- end
- end
-end
diff --git a/ext/win32ole/lib/win32ole/property.rb b/ext/win32ole/lib/win32ole/property.rb
deleted file mode 100644
index 558056b32b..0000000000
--- a/ext/win32ole/lib/win32ole/property.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: false
-
-class WIN32OLE
-end
-
-# OLEProperty is a helper class of Property with arguments, used by
-# `olegen.rb`-generated files.
-class WIN32OLE::Property
- # :stopdoc:
- def initialize(obj, dispid, gettypes, settypes)
- @obj = obj
- @dispid = dispid
- @gettypes = gettypes
- @settypes = settypes
- end
- def [](*args)
- @obj._getproperty(@dispid, args, @gettypes)
- end
- def []=(*args)
- @obj._setproperty(@dispid, args, @settypes)
- end
- # :stopdoc:
-end
-
-module WIN32OLE::VariantType
- # Alias for `olegen.rb`-generated files, that should include
- # WIN32OLE::VARIANT.
- OLEProperty = WIN32OLE::Property
-end
diff --git a/ext/win32ole/win32ole.c b/ext/win32ole/win32ole.c
deleted file mode 100644
index e0342d1e9d..0000000000
--- a/ext/win32ole/win32ole.c
+++ /dev/null
@@ -1,4142 +0,0 @@
-/*
- * (c) 1995 Microsoft Corporation. All rights reserved.
- * Developed by ActiveWare Internet Corp., now known as
- * ActiveState Tool Corp., http://www.ActiveState.com
- *
- * Other modifications Copyright (c) 1997, 1998 by Gurusamy Sarathy
- * <gsar@umich.edu> and Jan Dubois <jan.dubois@ibm.net>
- *
- * You may distribute under the terms of either the GNU General Public
- * License or the Artistic License, as specified in the README file
- * of the Perl distribution.
- *
- */
-
-/*
- modified for win32ole (ruby) by Masaki.Suketa <masaki.suketa@nifty.ne.jp>
- */
-
-#include "win32ole.h"
-
-/*
- * unfortunately IID_IMultiLanguage2 is not included in any libXXX.a
- * in Cygwin(mingw32).
- */
-#if defined(__CYGWIN__) || defined(__MINGW32__)
-#undef IID_IMultiLanguage2
-const IID IID_IMultiLanguage2 = {0xDCCFC164, 0x2B38, 0x11d2, {0xB7, 0xEC, 0x00, 0xC0, 0x4F, 0x8F, 0x5D, 0x9A}};
-#endif
-
-#define WIN32OLE_VERSION "1.8.10"
-
-typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX)
- (REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*);
-
-typedef HWND (WINAPI FNHTMLHELP)(HWND hwndCaller, LPCSTR pszFile,
- UINT uCommand, DWORD dwData);
-typedef BOOL (FNENUMSYSEMCODEPAGES) (CODEPAGE_ENUMPROC, DWORD);
-VALUE cWIN32OLE;
-
-#if defined(RB_THREAD_SPECIFIC) && (defined(__CYGWIN__))
-static RB_THREAD_SPECIFIC BOOL g_ole_initialized;
-# define g_ole_initialized_init() ((void)0)
-# define g_ole_initialized_set(val) (g_ole_initialized = (val))
-#else
-static volatile DWORD g_ole_initialized_key = TLS_OUT_OF_INDEXES;
-# define g_ole_initialized (TlsGetValue(g_ole_initialized_key)!=0)
-# define g_ole_initialized_init() (g_ole_initialized_key = TlsAlloc())
-# define g_ole_initialized_set(val) TlsSetValue(g_ole_initialized_key, (void*)(val))
-#endif
-
-static BOOL g_uninitialize_hooked = FALSE;
-static BOOL g_cp_installed = FALSE;
-static BOOL g_lcid_installed = FALSE;
-static BOOL g_running_nano = FALSE;
-static HINSTANCE ghhctrl = NULL;
-static HINSTANCE gole32 = NULL;
-static FNCOCREATEINSTANCEEX *gCoCreateInstanceEx = NULL;
-static VALUE com_hash;
-static VALUE enc2cp_hash;
-static IDispatchVtbl com_vtbl;
-static UINT cWIN32OLE_cp = CP_ACP;
-static rb_encoding *cWIN32OLE_enc;
-static UINT g_cp_to_check = CP_ACP;
-static char g_lcid_to_check[8 + 1];
-static VARTYPE g_nil_to = VT_ERROR;
-static IMessageFilterVtbl message_filter;
-static IMessageFilter imessage_filter = { &message_filter };
-static IMessageFilter* previous_filter;
-
-#if defined(HAVE_TYPE_IMULTILANGUAGE2)
-static IMultiLanguage2 *pIMultiLanguage = NULL;
-#elif defined(HAVE_TYPE_IMULTILANGUAGE)
-static IMultiLanguage *pIMultiLanguage = NULL;
-#else
-#define pIMultiLanguage NULL /* dummy */
-#endif
-
-struct oleparam {
- DISPPARAMS dp;
- OLECHAR** pNamedArgs;
-};
-
-static HRESULT ( STDMETHODCALLTYPE QueryInterface )(IDispatch __RPC_FAR *, REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject);
-static ULONG ( STDMETHODCALLTYPE AddRef )(IDispatch __RPC_FAR * This);
-static ULONG ( STDMETHODCALLTYPE Release )(IDispatch __RPC_FAR * This);
-static HRESULT ( STDMETHODCALLTYPE GetTypeInfoCount )(IDispatch __RPC_FAR * This, UINT __RPC_FAR *pctinfo);
-static HRESULT ( STDMETHODCALLTYPE GetTypeInfo )(IDispatch __RPC_FAR * This, UINT iTInfo, LCID lcid, ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo);
-static HRESULT ( STDMETHODCALLTYPE GetIDsOfNames )(IDispatch __RPC_FAR * This, REFIID riid, LPOLESTR __RPC_FAR *rgszNames, UINT cNames, LCID lcid, DISPID __RPC_FAR *rgDispId);
-static HRESULT ( STDMETHODCALLTYPE Invoke )( IDispatch __RPC_FAR * This, DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS __RPC_FAR *pDispParams, VARIANT __RPC_FAR *pVarResult, EXCEPINFO __RPC_FAR *pExcepInfo, UINT __RPC_FAR *puArgErr);
-static IDispatch* val2dispatch(VALUE val);
-static double rbtime2vtdate(VALUE tmobj);
-static VALUE vtdate2rbtime(double date);
-static rb_encoding *ole_cp2encoding(UINT cp);
-static UINT ole_encoding2cp(rb_encoding *enc);
-NORETURN(static void failed_load_conv51932(void));
-#ifndef pIMultiLanguage
-static void load_conv_function51932(void);
-#endif
-static UINT ole_init_cp(void);
-static void ole_freeexceptinfo(EXCEPINFO *pExInfo);
-static VALUE ole_excepinfo2msg(EXCEPINFO *pExInfo);
-static void ole_free(void *ptr);
-static size_t ole_size(const void *ptr);
-static LPWSTR ole_mb2wc(char *pm, int len, UINT cp);
-static VALUE ole_ary_m_entry(VALUE val, LONG *pid);
-static VALUE is_all_index_under(LONG *pid, long *pub, long dim);
-static void * get_ptr_of_variant(VARIANT *pvar);
-static void ole_set_safe_array(long n, SAFEARRAY *psa, LONG *pid, long *pub, VALUE val, long dim, VARTYPE vt);
-static long dimension(VALUE val);
-static long ary_len_of_dim(VALUE ary, long dim);
-static VALUE ole_set_member(VALUE self, IDispatch *dispatch);
-static VALUE fole_s_allocate(VALUE klass);
-static VALUE create_win32ole_object(VALUE klass, IDispatch *pDispatch, int argc, VALUE *argv);
-static VALUE ary_new_dim(VALUE myary, LONG *pid, LONG *plb, LONG dim);
-static void ary_store_dim(VALUE myary, LONG *pid, LONG *plb, LONG dim, VALUE val);
-static void ole_const_load(ITypeLib *pTypeLib, VALUE klass, VALUE self);
-static HRESULT clsid_from_remote(VALUE host, VALUE com, CLSID *pclsid);
-static VALUE ole_create_dcom(VALUE self, VALUE ole, VALUE host, VALUE others);
-static VALUE ole_bind_obj(VALUE moniker, int argc, VALUE *argv, VALUE self);
-static VALUE fole_s_connect(int argc, VALUE *argv, VALUE self);
-static VALUE fole_s_const_load(int argc, VALUE *argv, VALUE self);
-static ULONG reference_count(struct oledata * pole);
-static VALUE fole_s_reference_count(VALUE self, VALUE obj);
-static VALUE fole_s_free(VALUE self, VALUE obj);
-static HWND ole_show_help(VALUE helpfile, VALUE helpcontext);
-static VALUE fole_s_show_help(int argc, VALUE *argv, VALUE self);
-static VALUE fole_s_get_code_page(VALUE self);
-static BOOL CALLBACK installed_code_page_proc(LPTSTR str);
-static BOOL code_page_installed(UINT cp);
-static VALUE fole_s_set_code_page(VALUE self, VALUE vcp);
-static VALUE fole_s_get_locale(VALUE self);
-static BOOL CALLBACK installed_lcid_proc(LPTSTR str);
-static BOOL lcid_installed(LCID lcid);
-static VALUE fole_s_set_locale(VALUE self, VALUE vlcid);
-static VALUE fole_s_create_guid(VALUE self);
-static VALUE fole_s_ole_initialize(VALUE self);
-static VALUE fole_s_ole_uninitialize(VALUE self);
-static VALUE fole_initialize(int argc, VALUE *argv, VALUE self);
-static int hash2named_arg(VALUE key, VALUE val, VALUE pop);
-static VALUE set_argv(VARIANTARG* realargs, unsigned int beg, unsigned int end);
-static VALUE ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket);
-static VALUE fole_invoke(int argc, VALUE *argv, VALUE self);
-static VALUE ole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types, USHORT dispkind);
-static VALUE fole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types);
-static VALUE fole_getproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types);
-static VALUE fole_setproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types);
-static VALUE fole_setproperty_with_bracket(int argc, VALUE *argv, VALUE self);
-static VALUE fole_setproperty(int argc, VALUE *argv, VALUE self);
-static VALUE fole_getproperty_with_bracket(int argc, VALUE *argv, VALUE self);
-static VALUE ole_propertyput(VALUE self, VALUE property, VALUE value);
-static VALUE fole_free(VALUE self);
-static VALUE ole_each_sub(VALUE pEnumV);
-static VALUE ole_ienum_free(VALUE pEnumV);
-static VALUE fole_each(VALUE self);
-static VALUE fole_missing(int argc, VALUE *argv, VALUE self);
-static HRESULT typeinfo_from_ole(struct oledata *pole, ITypeInfo **ppti);
-static VALUE ole_methods(VALUE self, int mask);
-static VALUE fole_methods(VALUE self);
-static VALUE fole_get_methods(VALUE self);
-static VALUE fole_put_methods(VALUE self);
-static VALUE fole_func_methods(VALUE self);
-static VALUE fole_type(VALUE self);
-static VALUE fole_typelib(VALUE self);
-static VALUE fole_query_interface(VALUE self, VALUE str_iid);
-static VALUE fole_respond_to(VALUE self, VALUE method);
-static VALUE ole_usertype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails);
-static VALUE ole_ptrtype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails);
-static VALUE fole_method_help(VALUE self, VALUE cmdname);
-static VALUE fole_activex_initialize(VALUE self);
-
-static void com_hash_free(void *ptr);
-static void com_hash_mark(void *ptr);
-static size_t com_hash_size(const void *ptr);
-static void check_nano_server(void);
-
-static const rb_data_type_t ole_datatype = {
- "win32ole",
- {NULL, ole_free, ole_size,},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
-};
-
-static const rb_data_type_t win32ole_hash_datatype = {
- "win32ole_hash",
- {com_hash_mark, com_hash_free, com_hash_size,},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
-};
-
-static HRESULT (STDMETHODCALLTYPE mf_QueryInterface)(
- IMessageFilter __RPC_FAR * This,
- /* [in] */ REFIID riid,
- /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
-{
- if (MEMCMP(riid, &IID_IUnknown, GUID, 1) == 0
- || MEMCMP(riid, &IID_IMessageFilter, GUID, 1) == 0)
- {
- *ppvObject = &message_filter;
- return S_OK;
- }
- return E_NOINTERFACE;
-}
-
-static ULONG (STDMETHODCALLTYPE mf_AddRef)(
- IMessageFilter __RPC_FAR * This)
-{
- return 1;
-}
-
-static ULONG (STDMETHODCALLTYPE mf_Release)(
- IMessageFilter __RPC_FAR * This)
-{
- return 1;
-}
-
-static DWORD (STDMETHODCALLTYPE mf_HandleInComingCall)(
- IMessageFilter __RPC_FAR * pThis,
- DWORD dwCallType, //Type of incoming call
- HTASK threadIDCaller, //Task handle calling this task
- DWORD dwTickCount, //Elapsed tick count
- LPINTERFACEINFO lpInterfaceInfo //Pointer to INTERFACEINFO structure
- )
-{
-#ifdef DEBUG_MESSAGEFILTER
- printf("incoming %08X, %08X, %d\n", dwCallType, threadIDCaller, dwTickCount);
- fflush(stdout);
-#endif
- switch (dwCallType)
- {
- case CALLTYPE_ASYNC:
- case CALLTYPE_TOPLEVEL_CALLPENDING:
- case CALLTYPE_ASYNC_CALLPENDING:
- if (rb_during_gc()) {
- return SERVERCALL_RETRYLATER;
- }
- break;
- default:
- break;
- }
- if (previous_filter) {
- return previous_filter->lpVtbl->HandleInComingCall(previous_filter,
- dwCallType,
- threadIDCaller,
- dwTickCount,
- lpInterfaceInfo);
- }
- return SERVERCALL_ISHANDLED;
-}
-
-static DWORD (STDMETHODCALLTYPE mf_RetryRejectedCall)(
- IMessageFilter* pThis,
- HTASK threadIDCallee, //Server task handle
- DWORD dwTickCount, //Elapsed tick count
- DWORD dwRejectType //Returned rejection message
- )
-{
- if (previous_filter) {
- return previous_filter->lpVtbl->RetryRejectedCall(previous_filter,
- threadIDCallee,
- dwTickCount,
- dwRejectType);
- }
- return 1000;
-}
-
-static DWORD (STDMETHODCALLTYPE mf_MessagePending)(
- IMessageFilter* pThis,
- HTASK threadIDCallee, //Called applications task handle
- DWORD dwTickCount, //Elapsed tick count
- DWORD dwPendingType //Call type
- )
-{
- if (rb_during_gc()) {
- return PENDINGMSG_WAITNOPROCESS;
- }
- if (previous_filter) {
- return previous_filter->lpVtbl->MessagePending(previous_filter,
- threadIDCallee,
- dwTickCount,
- dwPendingType);
- }
- return PENDINGMSG_WAITNOPROCESS;
-}
-
-typedef struct _Win32OLEIDispatch
-{
- IDispatch dispatch;
- ULONG refcount;
- VALUE obj;
-} Win32OLEIDispatch;
-
-static HRESULT ( STDMETHODCALLTYPE QueryInterface )(
- IDispatch __RPC_FAR * This,
- /* [in] */ REFIID riid,
- /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
-{
- if (MEMCMP(riid, &IID_IUnknown, GUID, 1) == 0
- || MEMCMP(riid, &IID_IDispatch, GUID, 1) == 0)
- {
- Win32OLEIDispatch* p = (Win32OLEIDispatch*)This;
- p->refcount++;
- *ppvObject = This;
- return S_OK;
- }
- return E_NOINTERFACE;
-}
-
-static ULONG ( STDMETHODCALLTYPE AddRef )(
- IDispatch __RPC_FAR * This)
-{
- Win32OLEIDispatch* p = (Win32OLEIDispatch*)This;
- return ++(p->refcount);
-}
-
-static ULONG ( STDMETHODCALLTYPE Release )(
- IDispatch __RPC_FAR * This)
-{
- Win32OLEIDispatch* p = (Win32OLEIDispatch*)This;
- ULONG u = --(p->refcount);
- if (u == 0) {
- st_data_t key = p->obj;
- st_delete(DATA_PTR(com_hash), &key, 0);
- free(p);
- }
- return u;
-}
-
-static HRESULT ( STDMETHODCALLTYPE GetTypeInfoCount )(
- IDispatch __RPC_FAR * This,
- /* [out] */ UINT __RPC_FAR *pctinfo)
-{
- return E_NOTIMPL;
-}
-
-static HRESULT ( STDMETHODCALLTYPE GetTypeInfo )(
- IDispatch __RPC_FAR * This,
- /* [in] */ UINT iTInfo,
- /* [in] */ LCID lcid,
- /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo)
-{
- return E_NOTIMPL;
-}
-
-
-static HRESULT ( STDMETHODCALLTYPE GetIDsOfNames )(
- IDispatch __RPC_FAR * This,
- /* [in] */ REFIID riid,
- /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
- /* [in] */ UINT cNames,
- /* [in] */ LCID lcid,
- /* [size_is][out] */ DISPID __RPC_FAR *rgDispId)
-{
- /*
- Win32OLEIDispatch* p = (Win32OLEIDispatch*)This;
- */
- char* psz = ole_wc2mb(*rgszNames); // support only one method
- ID nameid = rb_check_id_cstr(psz, (long)strlen(psz), cWIN32OLE_enc);
- free(psz);
- if ((ID)(DISPID)nameid != nameid) return E_NOINTERFACE;
- *rgDispId = (DISPID)nameid;
- return S_OK;
-}
-
-static /* [local] */ HRESULT ( STDMETHODCALLTYPE Invoke )(
- IDispatch __RPC_FAR * This,
- /* [in] */ DISPID dispIdMember,
- /* [in] */ REFIID riid,
- /* [in] */ LCID lcid,
- /* [in] */ WORD wFlags,
- /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
- /* [out] */ VARIANT __RPC_FAR *pVarResult,
- /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
- /* [out] */ UINT __RPC_FAR *puArgErr)
-{
- VALUE v;
- int i;
- int args = pDispParams->cArgs;
- Win32OLEIDispatch* p = (Win32OLEIDispatch*)This;
- VALUE* parg = ALLOCA_N(VALUE, args);
- ID mid = (ID)dispIdMember;
- for (i = 0; i < args; i++) {
- *(parg + i) = ole_variant2val(&pDispParams->rgvarg[args - i - 1]);
- }
- if (dispIdMember == DISPID_VALUE) {
- if (wFlags == DISPATCH_METHOD) {
- mid = rb_intern("call");
- } else if (wFlags & DISPATCH_PROPERTYGET) {
- mid = rb_intern("value");
- }
- }
- v = rb_funcallv(p->obj, mid, args, parg);
- ole_val2variant(v, pVarResult);
- return S_OK;
-}
-
-BOOL
-ole_initialized(void)
-{
- return g_ole_initialized;
-}
-
-static IDispatch*
-val2dispatch(VALUE val)
-{
- struct st_table *tbl = DATA_PTR(com_hash);
- Win32OLEIDispatch* pdisp;
- st_data_t data;
- if (st_lookup(tbl, val, &data)) {
- pdisp = (Win32OLEIDispatch *)(data & ~FIXNUM_FLAG);
- pdisp->refcount++;
- }
- else {
- pdisp = ALLOC(Win32OLEIDispatch);
- pdisp->dispatch.lpVtbl = &com_vtbl;
- pdisp->refcount = 1;
- pdisp->obj = val;
- st_insert(tbl, val, (VALUE)pdisp | FIXNUM_FLAG);
- }
- return &pdisp->dispatch;
-}
-
-static double
-rbtime2vtdate(VALUE tmobj)
-{
- SYSTEMTIME st;
- double t;
- double nsec;
-
- st.wYear = RB_FIX2INT(rb_funcall(tmobj, rb_intern("year"), 0));
- st.wMonth = RB_FIX2INT(rb_funcall(tmobj, rb_intern("month"), 0));
- st.wDay = RB_FIX2INT(rb_funcall(tmobj, rb_intern("mday"), 0));
- st.wHour = RB_FIX2INT(rb_funcall(tmobj, rb_intern("hour"), 0));
- st.wMinute = RB_FIX2INT(rb_funcall(tmobj, rb_intern("min"), 0));
- st.wSecond = RB_FIX2INT(rb_funcall(tmobj, rb_intern("sec"), 0));
- st.wMilliseconds = 0;
- SystemTimeToVariantTime(&st, &t);
-
- /*
- * Unfortunately SystemTimeToVariantTime function always ignores the
- * wMilliseconds of SYSTEMTIME struct.
- * So, we need to calculate milliseconds by ourselves.
- */
- nsec = RB_FIX2INT(rb_funcall(tmobj, rb_intern("nsec"), 0));
- nsec /= 1000000.0;
- nsec /= (24.0 * 3600.0);
- nsec /= 1000;
- return t + nsec;
-}
-
-static VALUE
-vtdate2rbtime(double date)
-{
- SYSTEMTIME st;
- VALUE v;
- double msec;
- double sec;
- VariantTimeToSystemTime(date, &st);
- v = rb_funcall(rb_cTime, rb_intern("new"), 6,
- RB_INT2FIX(st.wYear),
- RB_INT2FIX(st.wMonth),
- RB_INT2FIX(st.wDay),
- RB_INT2FIX(st.wHour),
- RB_INT2FIX(st.wMinute),
- RB_INT2FIX(st.wSecond));
- st.wYear = RB_FIX2INT(rb_funcall(v, rb_intern("year"), 0));
- st.wMonth = RB_FIX2INT(rb_funcall(v, rb_intern("month"), 0));
- st.wDay = RB_FIX2INT(rb_funcall(v, rb_intern("mday"), 0));
- st.wHour = RB_FIX2INT(rb_funcall(v, rb_intern("hour"), 0));
- st.wMinute = RB_FIX2INT(rb_funcall(v, rb_intern("min"), 0));
- st.wSecond = RB_FIX2INT(rb_funcall(v, rb_intern("sec"), 0));
- st.wMilliseconds = 0;
- SystemTimeToVariantTime(&st, &sec);
- /*
- * Unfortunately VariantTimeToSystemTime always ignores the
- * wMilliseconds of SYSTEMTIME struct(The wMilliseconds is 0).
- * So, we need to calculate milliseconds by ourselves.
- */
- msec = date - sec;
- msec *= 24 * 60;
- msec -= floor(msec);
- msec *= 60;
- if (msec >= 59) {
- msec -= 60;
- }
- if (msec != 0) {
- return rb_funcall(v, rb_intern("+"), 1, rb_float_new(msec));
- }
- return v;
-}
-
-#define ENC_MACHING_CP(enc,encname,cp) if(strcasecmp(rb_enc_name((enc)),(encname)) == 0) return cp
-
-static UINT ole_encoding2cp(rb_encoding *enc)
-{
- /*
- * Is there any better solution to convert
- * Ruby encoding to Windows codepage???
- */
- ENC_MACHING_CP(enc, "Big5", 950);
- ENC_MACHING_CP(enc, "CP51932", 51932);
- ENC_MACHING_CP(enc, "CP850", 850);
- ENC_MACHING_CP(enc, "CP852", 852);
- ENC_MACHING_CP(enc, "CP855", 855);
- ENC_MACHING_CP(enc, "CP949", 949);
- ENC_MACHING_CP(enc, "EUC-JP", 20932);
- ENC_MACHING_CP(enc, "EUC-KR", 51949);
- ENC_MACHING_CP(enc, "EUC-TW", 51950);
- ENC_MACHING_CP(enc, "GB18030", 54936);
- 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);
- ENC_MACHING_CP(enc, "IBM855", 855);
- ENC_MACHING_CP(enc, "IBM857", 857);
- ENC_MACHING_CP(enc, "IBM860", 860);
- ENC_MACHING_CP(enc, "IBM861", 861);
- ENC_MACHING_CP(enc, "IBM862", 862);
- ENC_MACHING_CP(enc, "IBM863", 863);
- ENC_MACHING_CP(enc, "IBM864", 864);
- ENC_MACHING_CP(enc, "IBM865", 865);
- ENC_MACHING_CP(enc, "IBM866", 866);
- ENC_MACHING_CP(enc, "IBM869", 869);
- ENC_MACHING_CP(enc, "ISO-2022-JP", 50220);
- ENC_MACHING_CP(enc, "ISO-8859-1", 28591);
- ENC_MACHING_CP(enc, "ISO-8859-15", 28605);
- ENC_MACHING_CP(enc, "ISO-8859-2", 28592);
- ENC_MACHING_CP(enc, "ISO-8859-3", 28593);
- ENC_MACHING_CP(enc, "ISO-8859-4", 28594);
- ENC_MACHING_CP(enc, "ISO-8859-5", 28595);
- ENC_MACHING_CP(enc, "ISO-8859-6", 28596);
- ENC_MACHING_CP(enc, "ISO-8859-7", 28597);
- ENC_MACHING_CP(enc, "ISO-8859-8", 28598);
- ENC_MACHING_CP(enc, "ISO-8859-9", 28599);
- ENC_MACHING_CP(enc, "KOI8-R", 20866);
- ENC_MACHING_CP(enc, "KOI8-U", 21866);
- ENC_MACHING_CP(enc, "Shift_JIS", 932);
- ENC_MACHING_CP(enc, "UTF-16BE", 1201);
- ENC_MACHING_CP(enc, "UTF-16LE", 1200);
- ENC_MACHING_CP(enc, "UTF-7", 65000);
- ENC_MACHING_CP(enc, "UTF-8", 65001);
- ENC_MACHING_CP(enc, "Windows-1250", 1250);
- ENC_MACHING_CP(enc, "Windows-1251", 1251);
- ENC_MACHING_CP(enc, "Windows-1252", 1252);
- ENC_MACHING_CP(enc, "Windows-1253", 1253);
- ENC_MACHING_CP(enc, "Windows-1254", 1254);
- ENC_MACHING_CP(enc, "Windows-1255", 1255);
- ENC_MACHING_CP(enc, "Windows-1256", 1256);
- ENC_MACHING_CP(enc, "Windows-1257", 1257);
- ENC_MACHING_CP(enc, "Windows-1258", 1258);
- ENC_MACHING_CP(enc, "Windows-31J", 932);
- ENC_MACHING_CP(enc, "Windows-874", 874);
- ENC_MACHING_CP(enc, "eucJP-ms", 20932);
- return CP_ACP;
-}
-
-static void
-failed_load_conv51932(void)
-{
- rb_raise(eWIN32OLERuntimeError, "fail to load convert function for CP51932");
-}
-
-#ifndef pIMultiLanguage
-static void
-load_conv_function51932(void)
-{
- HRESULT hr = E_NOINTERFACE;
- void *p;
- if (!pIMultiLanguage) {
-#if defined(HAVE_TYPE_IMULTILANGUAGE2)
- hr = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER,
- &IID_IMultiLanguage2, &p);
-#elif defined(HAVE_TYPE_IMULTILANGUAGE)
- hr = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER,
- &IID_IMultiLanguage, &p);
-#endif
- if (FAILED(hr)) {
- failed_load_conv51932();
- }
- pIMultiLanguage = p;
- }
-}
-#define need_conv_function51932() (load_conv_function51932(), 1)
-#else
-#define load_conv_function51932() failed_load_conv51932()
-#define need_conv_function51932() (failed_load_conv51932(), 0)
-#endif
-
-#define conv_51932(cp) ((cp) == 51932 && need_conv_function51932())
-
-static void
-set_ole_codepage(UINT cp)
-{
- if (code_page_installed(cp)) {
- cWIN32OLE_cp = cp;
- } else {
- switch(cp) {
- case CP_ACP:
- case CP_OEMCP:
- case CP_MACCP:
- case CP_THREAD_ACP:
- case CP_SYMBOL:
- case CP_UTF7:
- case CP_UTF8:
- cWIN32OLE_cp = cp;
- break;
- case 51932:
- cWIN32OLE_cp = cp;
- load_conv_function51932();
- break;
- default:
- rb_raise(eWIN32OLERuntimeError, "codepage should be WIN32OLE::CP_ACP, WIN32OLE::CP_OEMCP, WIN32OLE::CP_MACCP, WIN32OLE::CP_THREAD_ACP, WIN32OLE::CP_SYMBOL, WIN32OLE::CP_UTF7, WIN32OLE::CP_UTF8, or installed codepage.");
- break;
- }
- }
- cWIN32OLE_enc = ole_cp2encoding(cWIN32OLE_cp);
-}
-
-
-static UINT
-ole_init_cp(void)
-{
- UINT cp;
- rb_encoding *encdef;
- encdef = rb_default_internal_encoding();
- if (!encdef) {
- encdef = rb_default_external_encoding();
- }
- cp = ole_encoding2cp(encdef);
- set_ole_codepage(cp);
- return cp;
-}
-
-struct myCPINFOEX {
- UINT MaxCharSize;
- BYTE DefaultChar[2];
- BYTE LeadByte[12];
- WCHAR UnicodeDefaultChar;
- UINT CodePage;
- char CodePageName[MAX_PATH];
-};
-
-static rb_encoding *
-ole_cp2encoding(UINT cp)
-{
- static BOOL (*pGetCPInfoEx)(UINT, DWORD, struct myCPINFOEX *) = NULL;
- struct myCPINFOEX* buf;
- VALUE enc_name;
- char *enc_cstr;
- int idx;
-
- if (!code_page_installed(cp)) {
- switch(cp) {
- case CP_ACP:
- cp = GetACP();
- break;
- case CP_OEMCP:
- cp = GetOEMCP();
- break;
- case CP_MACCP:
- case CP_THREAD_ACP:
- if (!pGetCPInfoEx) {
- pGetCPInfoEx = (BOOL (*)(UINT, DWORD, struct myCPINFOEX *))
- GetProcAddress(GetModuleHandle("kernel32"), "GetCPInfoEx");
- if (!pGetCPInfoEx) {
- pGetCPInfoEx = (void*)-1;
- }
- }
- buf = ALLOCA_N(struct myCPINFOEX, 1);
- ZeroMemory(buf, sizeof(struct myCPINFOEX));
- if (pGetCPInfoEx == (void*)-1 || !pGetCPInfoEx(cp, 0, buf)) {
- rb_raise(eWIN32OLERuntimeError, "cannot map codepage to encoding.");
- break; /* never reach here */
- }
- cp = buf->CodePage;
- break;
- case CP_SYMBOL:
- case CP_UTF7:
- case CP_UTF8:
- break;
- case 51932:
- load_conv_function51932();
- break;
- default:
- rb_raise(eWIN32OLERuntimeError, "codepage should be WIN32OLE::CP_ACP, WIN32OLE::CP_OEMCP, WIN32OLE::CP_MACCP, WIN32OLE::CP_THREAD_ACP, WIN32OLE::CP_SYMBOL, WIN32OLE::CP_UTF7, WIN32OLE::CP_UTF8, or installed codepage.");
- break;
- }
- }
-
- enc_name = rb_sprintf("CP%d", cp);
- idx = rb_enc_find_index(enc_cstr = StringValueCStr(enc_name));
- if (idx < 0)
- idx = rb_define_dummy_encoding(enc_cstr);
- return rb_enc_from_index(idx);
-}
-
-#ifndef pIMultiLanguage
-static HRESULT
-ole_ml_wc2mb_conv0(LPWSTR pw, LPSTR pm, UINT *size)
-{
- DWORD dw = 0;
- return pIMultiLanguage->lpVtbl->ConvertStringFromUnicode(pIMultiLanguage,
- &dw, cWIN32OLE_cp, pw, NULL, pm, size);
-}
-#define ole_ml_wc2mb_conv(pw, pm, size, onfailure) do { \
- HRESULT hr = ole_ml_wc2mb_conv0(pw, pm, &size); \
- if (FAILED(hr)) { \
- onfailure; \
- ole_raise(hr, eWIN32OLERuntimeError, "fail to convert Unicode to CP%d", cWIN32OLE_cp); \
- } \
- } while (0)
-#endif
-
-#define ole_wc2mb_conv(pw, pm, size) WideCharToMultiByte(cWIN32OLE_cp, 0, (pw), -1, (pm), (size), NULL, NULL)
-
-static char *
-ole_wc2mb_alloc(LPWSTR pw, char *(alloc)(UINT size, void *arg), void *arg)
-{
- LPSTR pm;
- UINT size = 0;
- if (conv_51932(cWIN32OLE_cp)) {
-#ifndef pIMultiLanguage
- ole_ml_wc2mb_conv(pw, NULL, size, {});
- pm = alloc(size, arg);
- if (size) ole_ml_wc2mb_conv(pw, pm, size, xfree(pm));
- pm[size] = '\0';
- return pm;
-#endif
- }
- size = ole_wc2mb_conv(pw, NULL, 0);
- pm = alloc(size, arg);
- if (size) ole_wc2mb_conv(pw, pm, size);
- pm[size] = '\0';
- return pm;
-}
-
-static char *
-ole_alloc_str(UINT size, void *arg)
-{
- return ALLOC_N(char, size + 1);
-}
-
-char *
-ole_wc2mb(LPWSTR pw)
-{
- return ole_wc2mb_alloc(pw, ole_alloc_str, NULL);
-}
-
-static void
-ole_freeexceptinfo(EXCEPINFO *pExInfo)
-{
- SysFreeString(pExInfo->bstrDescription);
- SysFreeString(pExInfo->bstrSource);
- SysFreeString(pExInfo->bstrHelpFile);
-}
-
-static VALUE
-ole_excepinfo2msg(EXCEPINFO *pExInfo)
-{
- char error_code[40];
- char *pSource = NULL;
- char *pDescription = NULL;
- VALUE error_msg;
- if(pExInfo->pfnDeferredFillIn != NULL) {
- (*pExInfo->pfnDeferredFillIn)(pExInfo);
- }
- if (pExInfo->bstrSource != NULL) {
- pSource = ole_wc2mb(pExInfo->bstrSource);
- }
- if (pExInfo->bstrDescription != NULL) {
- pDescription = ole_wc2mb(pExInfo->bstrDescription);
- }
- if(pExInfo->wCode == 0) {
- sprintf(error_code, "\n OLE error code:%lX in ", (unsigned long)pExInfo->scode);
- }
- else{
- sprintf(error_code, "\n OLE error code:%u in ", pExInfo->wCode);
- }
- error_msg = rb_str_new2(error_code);
- if(pSource != NULL) {
- rb_str_cat2(error_msg, pSource);
- }
- else {
- rb_str_cat(error_msg, "<Unknown>", 9);
- }
- rb_str_cat2(error_msg, "\n ");
- if(pDescription != NULL) {
- rb_str_cat2(error_msg, pDescription);
- }
- else {
- rb_str_cat2(error_msg, "<No Description>");
- }
- if(pSource) free(pSource);
- if(pDescription) free(pDescription);
- ole_freeexceptinfo(pExInfo);
- return error_msg;
-}
-
-void
-ole_uninitialize(void)
-{
- if (!g_ole_initialized) return;
- OleUninitialize();
- g_ole_initialized_set(FALSE);
-}
-
-static void
-ole_uninitialize_hook(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE klass)
-{
- ole_uninitialize();
-}
-
-void
-ole_initialize(void)
-{
- HRESULT hr;
-
- if(!g_uninitialize_hooked) {
- rb_add_event_hook(ole_uninitialize_hook, RUBY_EVENT_THREAD_END, Qnil);
- g_uninitialize_hooked = TRUE;
- }
-
- if(g_ole_initialized == FALSE) {
- if(g_running_nano) {
- hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
- } else {
- hr = OleInitialize(NULL);
- }
- if(FAILED(hr)) {
- ole_raise(hr, rb_eRuntimeError, "fail: OLE initialize");
- }
- g_ole_initialized_set(TRUE);
-
- if (g_running_nano == FALSE) {
- hr = CoRegisterMessageFilter(&imessage_filter, &previous_filter);
- if(FAILED(hr)) {
- previous_filter = NULL;
- ole_raise(hr, rb_eRuntimeError, "fail: install OLE MessageFilter");
- }
- }
- }
-}
-
-static void
-ole_free(void *ptr)
-{
- struct oledata *pole = ptr;
- OLE_FREE(pole->pDispatch);
- free(pole);
-}
-
-static size_t ole_size(const void *ptr)
-{
- return ptr ? sizeof(struct oledata) : 0;
-}
-
-struct oledata *
-oledata_get_struct(VALUE ole)
-{
- struct oledata *pole;
- TypedData_Get_Struct(ole, struct oledata, &ole_datatype, pole);
- return pole;
-}
-
-LPWSTR
-ole_vstr2wc(VALUE vstr)
-{
- rb_encoding *enc;
- int cp;
- LPWSTR pw;
- st_data_t data;
- struct st_table *tbl = DATA_PTR(enc2cp_hash);
-
- /* do not type-conversion here to prevent from other arguments
- * changing (if exist) */
- Check_Type(vstr, T_STRING);
- if (RSTRING_LEN(vstr) == 0) {
- return NULL;
- }
-
- enc = rb_enc_get(vstr);
-
- if (st_lookup(tbl, (VALUE)enc | FIXNUM_FLAG, &data)) {
- cp = RB_FIX2INT((VALUE)data);
- } else {
- cp = ole_encoding2cp(enc);
- if (code_page_installed(cp) ||
- cp == CP_ACP ||
- cp == CP_OEMCP ||
- cp == CP_MACCP ||
- cp == CP_THREAD_ACP ||
- cp == CP_SYMBOL ||
- cp == CP_UTF7 ||
- cp == CP_UTF8 ||
- cp == 51932) {
- st_insert(tbl, (VALUE)enc | FIXNUM_FLAG, RB_INT2FIX(cp));
- } else {
- rb_raise(eWIN32OLERuntimeError, "not installed Windows codepage(%d) according to `%s'", cp, rb_enc_name(enc));
- }
- }
- pw = ole_mb2wc(RSTRING_PTR(vstr), RSTRING_LENINT(vstr), cp);
- RB_GC_GUARD(vstr);
- return pw;
-}
-
-static LPWSTR
-ole_mb2wc(char *pm, int len, UINT cp)
-{
- UINT size = 0;
- LPWSTR pw;
-
- if (conv_51932(cp)) {
-#ifndef pIMultiLanguage
- DWORD dw = 0;
- UINT n = len;
- HRESULT hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage,
- &dw, cp, pm, &n, NULL, &size);
- if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cp);
- }
- pw = SysAllocStringLen(NULL, size);
- n = len;
- hr = pIMultiLanguage->lpVtbl->ConvertStringToUnicode(pIMultiLanguage,
- &dw, cp, pm, &n, pw, &size);
- if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLERuntimeError, "fail to convert CP%d to Unicode", cp);
- }
- return pw;
-#endif
- }
- size = MultiByteToWideChar(cp, 0, pm, len, NULL, 0);
- pw = SysAllocStringLen(NULL, size);
- pw[size-1] = 0;
- MultiByteToWideChar(cp, 0, pm, len, pw, size);
- return pw;
-}
-
-static char *
-ole_alloc_vstr(UINT size, void *arg)
-{
- VALUE str = rb_enc_str_new(NULL, size, cWIN32OLE_enc);
- *(VALUE *)arg = str;
- return RSTRING_PTR(str);
-}
-
-VALUE
-ole_wc2vstr(LPWSTR pw, BOOL isfree)
-{
- VALUE vstr;
- ole_wc2mb_alloc(pw, ole_alloc_vstr, &vstr);
- rb_str_set_len(vstr, (long)strlen(RSTRING_PTR(vstr)));
- if(isfree)
- SysFreeString(pw);
- return vstr;
-}
-
-static VALUE
-ole_ary_m_entry(VALUE val, LONG *pid)
-{
- VALUE obj = Qnil;
- int i = 0;
- obj = val;
- while(RB_TYPE_P(obj, T_ARRAY)) {
- obj = rb_ary_entry(obj, pid[i]);
- i++;
- }
- return obj;
-}
-
-static VALUE
-is_all_index_under(LONG *pid, long *pub, long dim)
-{
- long i = 0;
- for (i = 0; i < dim; i++) {
- if (pid[i] > pub[i]) {
- return Qfalse;
- }
- }
- return Qtrue;
-}
-
-void
-ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt)
-{
- if (val == Qnil) {
- if (vt == VT_VARIANT) {
- ole_val2variant2(val, var);
- } else {
- V_VT(var) = (vt & ~VT_BYREF);
- if (V_VT(var) == VT_DISPATCH) {
- V_DISPATCH(var) = NULL;
- } else if (V_VT(var) == VT_UNKNOWN) {
- V_UNKNOWN(var) = NULL;
- }
- }
- return;
- }
-#if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__CYGWIN__) || defined(__MINGW32__)
- switch(vt & ~VT_BYREF) {
- case VT_I8:
- V_VT(var) = VT_I8;
- V_I8(var) = NUM2I8 (val);
- break;
- case VT_UI8:
- V_VT(var) = VT_UI8;
- V_UI8(var) = NUM2UI8(val);
- break;
- default:
- ole_val2variant2(val, var);
- break;
- }
-#else /* (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__CYGWIN__) || defined(__MINGW32__) */
- ole_val2variant2(val, var);
-#endif
-}
-
-VOID *
-val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt)
-{
- VOID *p = NULL;
- HRESULT hr = S_OK;
- ole_val2variant_ex(val, var, vt);
- if ((vt & ~VT_BYREF) == VT_VARIANT) {
- p = var;
- } else {
- if ( (vt & ~VT_BYREF) != V_VT(var)) {
- hr = VariantChangeTypeEx(var, var,
- cWIN32OLE_lcid, 0, (VARTYPE)(vt & ~VT_BYREF));
- if (FAILED(hr)) {
- ole_raise(hr, rb_eRuntimeError, "failed to change type");
- }
- }
- p = get_ptr_of_variant(var);
- }
- if (p == NULL) {
- rb_raise(rb_eRuntimeError, "failed to get pointer of variant");
- }
- return p;
-}
-
-static void *
-get_ptr_of_variant(VARIANT *pvar)
-{
- switch(V_VT(pvar)) {
- case VT_UI1:
- return &V_UI1(pvar);
- break;
- case VT_I2:
- return &V_I2(pvar);
- break;
- case VT_UI2:
- return &V_UI2(pvar);
- break;
- case VT_I4:
- return &V_I4(pvar);
- break;
- case VT_UI4:
- return &V_UI4(pvar);
- break;
- case VT_R4:
- return &V_R4(pvar);
- break;
- case VT_R8:
- return &V_R8(pvar);
- break;
-#if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__CYGWIN__) || defined(__MINGW32__)
- case VT_I8:
- return &V_I8(pvar);
- break;
- case VT_UI8:
- return &V_UI8(pvar);
- break;
-#endif
- case VT_INT:
- return &V_INT(pvar);
- break;
- case VT_UINT:
- return &V_UINT(pvar);
- break;
- case VT_CY:
- return &V_CY(pvar);
- break;
- case VT_DATE:
- return &V_DATE(pvar);
- break;
- case VT_BSTR:
- return V_BSTR(pvar);
- break;
- case VT_DISPATCH:
- return V_DISPATCH(pvar);
- break;
- case VT_ERROR:
- return &V_ERROR(pvar);
- break;
- case VT_BOOL:
- return &V_BOOL(pvar);
- break;
- case VT_UNKNOWN:
- return V_UNKNOWN(pvar);
- break;
- case VT_ARRAY:
- return &V_ARRAY(pvar);
- break;
- default:
- return NULL;
- break;
- }
-}
-
-static void
-ole_set_safe_array(long n, SAFEARRAY *psa, LONG *pid, long *pub, VALUE val, long dim, VARTYPE vt)
-{
- VALUE val1;
- HRESULT hr = S_OK;
- VARIANT var;
- VOID *p = NULL;
- long i = n;
- while(i >= 0) {
- val1 = ole_ary_m_entry(val, pid);
- VariantInit(&var);
- p = val2variant_ptr(val1, &var, vt);
- if (is_all_index_under(pid, pub, dim) == Qtrue) {
- if ((V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == NULL) ||
- (V_VT(&var) == VT_UNKNOWN && V_UNKNOWN(&var) == NULL)) {
- rb_raise(eWIN32OLERuntimeError, "element of array does not have IDispatch or IUnknown Interface");
- }
- hr = SafeArrayPutElement(psa, pid, p);
- }
- if (FAILED(hr)) {
- ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayPutElement");
- }
- pid[i] += 1;
- if (pid[i] > pub[i]) {
- pid[i] = 0;
- i -= 1;
- } else {
- i = dim - 1;
- }
- }
-}
-
-static long
-dimension(VALUE val) {
- long dim = 0;
- long dim1 = 0;
- long len = 0;
- long i = 0;
- if (RB_TYPE_P(val, T_ARRAY)) {
- len = RARRAY_LEN(val);
- for (i = 0; i < len; i++) {
- dim1 = dimension(rb_ary_entry(val, i));
- if (dim < dim1) {
- dim = dim1;
- }
- }
- dim += 1;
- }
- return dim;
-}
-
-static long
-ary_len_of_dim(VALUE ary, long dim) {
- long ary_len = 0;
- long ary_len1 = 0;
- long len = 0;
- long i = 0;
- VALUE val;
- if (dim == 0) {
- if (RB_TYPE_P(ary, T_ARRAY)) {
- ary_len = RARRAY_LEN(ary);
- }
- } else {
- if (RB_TYPE_P(ary, T_ARRAY)) {
- len = RARRAY_LEN(ary);
- for (i = 0; i < len; i++) {
- val = rb_ary_entry(ary, i);
- ary_len1 = ary_len_of_dim(val, dim-1);
- if (ary_len < ary_len1) {
- ary_len = ary_len1;
- }
- }
- }
- }
- return ary_len;
-}
-
-HRESULT
-ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vt)
-{
- long dim = 0;
- int i = 0;
- HRESULT hr = S_OK;
-
- SAFEARRAYBOUND *psab = NULL;
- SAFEARRAY *psa = NULL;
- long *pub;
- LONG *pid;
-
- Check_Type(val, T_ARRAY);
-
- dim = dimension(val);
-
- psab = ALLOC_N(SAFEARRAYBOUND, dim);
- pub = ALLOC_N(long, dim);
- pid = ALLOC_N(LONG, dim);
-
- if(!psab || !pub || !pid) {
- if(pub) free(pub);
- if(psab) free(psab);
- if(pid) free(pid);
- rb_raise(rb_eRuntimeError, "memory allocation error");
- }
-
- for (i = 0; i < dim; i++) {
- psab[i].cElements = ary_len_of_dim(val, i);
- psab[i].lLbound = 0;
- pub[i] = psab[i].cElements - 1;
- pid[i] = 0;
- }
- /* Create and fill VARIANT array */
- if ((vt & ~VT_BYREF) == VT_ARRAY) {
- vt = (vt | VT_VARIANT);
- }
- psa = SafeArrayCreate((VARTYPE)(vt & VT_TYPEMASK), dim, psab);
- if (psa == NULL)
- hr = E_OUTOFMEMORY;
- else
- hr = SafeArrayLock(psa);
- if (SUCCEEDED(hr)) {
- ole_set_safe_array(dim-1, psa, pid, pub, val, dim, (VARTYPE)(vt & VT_TYPEMASK));
- hr = SafeArrayUnlock(psa);
- }
-
- if(pub) free(pub);
- if(psab) free(psab);
- if(pid) free(pid);
-
- if (SUCCEEDED(hr)) {
- V_VT(var) = vt;
- V_ARRAY(var) = psa;
- }
- else {
- if (psa != NULL)
- SafeArrayDestroy(psa);
- }
- return hr;
-}
-
-void
-ole_val2variant(VALUE val, VARIANT *var)
-{
- struct oledata *pole = NULL;
- if(rb_obj_is_kind_of(val, cWIN32OLE)) {
- pole = oledata_get_struct(val);
- OLE_ADDREF(pole->pDispatch);
- V_VT(var) = VT_DISPATCH;
- V_DISPATCH(var) = pole->pDispatch;
- return;
- }
- if (rb_obj_is_kind_of(val, cWIN32OLE_VARIANT)) {
- ole_variant2variant(val, var);
- return;
- }
- if (rb_obj_is_kind_of(val, cWIN32OLE_RECORD)) {
- ole_rec2variant(val, var);
- return;
- }
- if (rb_obj_is_kind_of(val, rb_cTime)) {
- V_VT(var) = VT_DATE;
- V_DATE(var) = rbtime2vtdate(val);
- return;
- }
- switch (TYPE(val)) {
- case T_ARRAY:
- ole_val_ary2variant_ary(val, var, VT_VARIANT|VT_ARRAY);
- break;
- case T_STRING:
- V_VT(var) = VT_BSTR;
- V_BSTR(var) = ole_vstr2wc(val);
- break;
- case T_FIXNUM:
- V_VT(var) = VT_I4;
- {
- long v = RB_NUM2LONG(val);
- V_I4(var) = (LONG)v;
-#if SIZEOF_LONG > 4
- if (V_I4(var) != v) {
- V_I8(var) = v;
- V_VT(var) = VT_I8;
- }
-#endif
- }
- break;
- case T_BIGNUM:
- V_VT(var) = VT_R8;
- V_R8(var) = rb_big2dbl(val);
- break;
- case T_FLOAT:
- V_VT(var) = VT_R8;
- V_R8(var) = NUM2DBL(val);
- break;
- case T_TRUE:
- V_VT(var) = VT_BOOL;
- V_BOOL(var) = VARIANT_TRUE;
- break;
- case T_FALSE:
- V_VT(var) = VT_BOOL;
- V_BOOL(var) = VARIANT_FALSE;
- break;
- case T_NIL:
- if (g_nil_to == VT_ERROR) {
- V_VT(var) = VT_ERROR;
- V_ERROR(var) = DISP_E_PARAMNOTFOUND;
- }else {
- V_VT(var) = VT_EMPTY;
- }
- break;
- default:
- V_VT(var) = VT_DISPATCH;
- V_DISPATCH(var) = val2dispatch(val);
- break;
- }
-}
-
-void
-ole_val2variant2(VALUE val, VARIANT *var)
-{
- g_nil_to = VT_EMPTY;
- ole_val2variant(val, var);
- g_nil_to = VT_ERROR;
-}
-
-VALUE
-make_inspect(const char *class_name, VALUE detail)
-{
- VALUE str;
- str = rb_str_new2("#<");
- rb_str_cat2(str, class_name);
- rb_str_cat2(str, ":");
- rb_str_concat(str, detail);
- rb_str_cat2(str, ">");
- return str;
-}
-
-VALUE
-default_inspect(VALUE self, const char *class_name)
-{
- VALUE detail = rb_funcall(self, rb_intern("to_s"), 0);
- return make_inspect(class_name, detail);
-}
-
-static VALUE
-ole_set_member(VALUE self, IDispatch *dispatch)
-{
- struct oledata *pole = NULL;
- pole = oledata_get_struct(self);
- if (pole->pDispatch) {
- OLE_RELEASE(pole->pDispatch);
- pole->pDispatch = NULL;
- }
- pole->pDispatch = dispatch;
- return self;
-}
-
-
-static VALUE
-fole_s_allocate(VALUE klass)
-{
- struct oledata *pole;
- VALUE obj;
- ole_initialize();
- obj = TypedData_Make_Struct(klass, struct oledata, &ole_datatype, pole);
- pole->pDispatch = NULL;
- return obj;
-}
-
-static VALUE
-create_win32ole_object(VALUE klass, IDispatch *pDispatch, int argc, VALUE *argv)
-{
- VALUE obj = fole_s_allocate(klass);
- ole_set_member(obj, pDispatch);
- return obj;
-}
-
-static VALUE
-ary_new_dim(VALUE myary, LONG *pid, LONG *plb, LONG dim) {
- long i;
- VALUE obj = Qnil;
- VALUE pobj = Qnil;
- long *ids = ALLOC_N(long, dim);
- if (!ids) {
- rb_raise(rb_eRuntimeError, "memory allocation error");
- }
- for(i = 0; i < dim; i++) {
- ids[i] = pid[i] - plb[i];
- }
- obj = myary;
- pobj = myary;
- for(i = 0; i < dim-1; i++) {
- obj = rb_ary_entry(pobj, ids[i]);
- if (obj == Qnil) {
- rb_ary_store(pobj, ids[i], rb_ary_new());
- }
- obj = rb_ary_entry(pobj, ids[i]);
- pobj = obj;
- }
- if (ids) free(ids);
- return obj;
-}
-
-static void
-ary_store_dim(VALUE myary, LONG *pid, LONG *plb, LONG dim, VALUE val) {
- long id = pid[dim - 1] - plb[dim - 1];
- VALUE obj = ary_new_dim(myary, pid, plb, dim);
- rb_ary_store(obj, id, val);
-}
-
-VALUE
-ole_variant2val(VARIANT *pvar)
-{
- VALUE obj = Qnil;
- VARTYPE vt = V_VT(pvar);
- HRESULT hr;
- while ( vt == (VT_BYREF | VT_VARIANT) ) {
- pvar = V_VARIANTREF(pvar);
- vt = V_VT(pvar);
- }
-
- if(V_ISARRAY(pvar)) {
- VARTYPE vt_base = vt & VT_TYPEMASK;
- SAFEARRAY *psa = V_ISBYREF(pvar) ? *V_ARRAYREF(pvar) : V_ARRAY(pvar);
- UINT i = 0;
- LONG *pid, *plb, *pub;
- VARIANT variant;
- VALUE val;
- UINT dim = 0;
- if (!psa) {
- return obj;
- }
- dim = SafeArrayGetDim(psa);
- pid = ALLOC_N(LONG, dim);
- plb = ALLOC_N(LONG, dim);
- pub = ALLOC_N(LONG, dim);
-
- if(!pid || !plb || !pub) {
- if(pid) free(pid);
- if(plb) free(plb);
- if(pub) free(pub);
- rb_raise(rb_eRuntimeError, "memory allocation error");
- }
-
- for(i = 0; i < dim; ++i) {
- SafeArrayGetLBound(psa, i+1, &plb[i]);
- SafeArrayGetLBound(psa, i+1, &pid[i]);
- SafeArrayGetUBound(psa, i+1, &pub[i]);
- }
- hr = SafeArrayLock(psa);
- if (SUCCEEDED(hr)) {
- obj = rb_ary_new();
- i = 0;
- VariantInit(&variant);
- V_VT(&variant) = vt_base | VT_BYREF;
- if (vt_base == VT_RECORD) {
- hr = SafeArrayGetRecordInfo(psa, &V_RECORDINFO(&variant));
- if (SUCCEEDED(hr)) {
- V_VT(&variant) = VT_RECORD;
- }
- }
- while (i < dim) {
- ary_new_dim(obj, pid, plb, dim);
- if (vt_base == VT_RECORD)
- hr = SafeArrayPtrOfIndex(psa, pid, &V_RECORD(&variant));
- else
- hr = SafeArrayPtrOfIndex(psa, pid, &V_BYREF(&variant));
- if (SUCCEEDED(hr)) {
- val = ole_variant2val(&variant);
- ary_store_dim(obj, pid, plb, dim, val);
- }
- for (i = 0; i < dim; ++i) {
- if (++pid[i] <= pub[i])
- break;
- pid[i] = plb[i];
- }
- }
- SafeArrayUnlock(psa);
- }
- if(pid) free(pid);
- if(plb) free(plb);
- if(pub) free(pub);
- return obj;
- }
- switch(V_VT(pvar) & ~VT_BYREF){
- case VT_EMPTY:
- break;
- case VT_NULL:
- break;
- case VT_I1:
- if(V_ISBYREF(pvar))
- obj = RB_INT2NUM((long)*V_I1REF(pvar));
- else
- obj = RB_INT2NUM((long)V_I1(pvar));
- break;
-
- case VT_UI1:
- if(V_ISBYREF(pvar))
- obj = RB_INT2NUM((long)*V_UI1REF(pvar));
- else
- obj = RB_INT2NUM((long)V_UI1(pvar));
- break;
-
- case VT_I2:
- if(V_ISBYREF(pvar))
- obj = RB_INT2NUM((long)*V_I2REF(pvar));
- else
- obj = RB_INT2NUM((long)V_I2(pvar));
- break;
-
- case VT_UI2:
- if(V_ISBYREF(pvar))
- obj = RB_INT2NUM((long)*V_UI2REF(pvar));
- else
- obj = RB_INT2NUM((long)V_UI2(pvar));
- break;
-
- case VT_I4:
- if(V_ISBYREF(pvar))
- obj = RB_INT2NUM((long)*V_I4REF(pvar));
- else
- obj = RB_INT2NUM((long)V_I4(pvar));
- break;
-
- case VT_UI4:
- if(V_ISBYREF(pvar))
- obj = RB_INT2NUM((long)*V_UI4REF(pvar));
- else
- obj = RB_INT2NUM((long)V_UI4(pvar));
- break;
-
- case VT_INT:
- if(V_ISBYREF(pvar))
- obj = RB_INT2NUM((long)*V_INTREF(pvar));
- else
- obj = RB_INT2NUM((long)V_INT(pvar));
- break;
-
- case VT_UINT:
- if(V_ISBYREF(pvar))
- obj = RB_INT2NUM((long)*V_UINTREF(pvar));
- else
- obj = RB_INT2NUM((long)V_UINT(pvar));
- break;
-
-#if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__CYGWIN__) || defined(__MINGW32__)
- case VT_I8:
- if(V_ISBYREF(pvar))
-#if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__CYGWIN__) || defined(__MINGW32__)
-#ifdef V_I8REF
- obj = I8_2_NUM(*V_I8REF(pvar));
-#endif
-#else
- obj = Qnil;
-#endif
- else
- obj = I8_2_NUM(V_I8(pvar));
- break;
- case VT_UI8:
- if(V_ISBYREF(pvar))
-#if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__CYGWIN__) || defined(__MINGW32__)
-#ifdef V_UI8REF
- obj = UI8_2_NUM(*V_UI8REF(pvar));
-#endif
-#else
- obj = Qnil;
-#endif
- else
- obj = UI8_2_NUM(V_UI8(pvar));
- break;
-#endif /* (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__CYGWIN__) || defined(__MINGW32__) */
-
- case VT_R4:
- if(V_ISBYREF(pvar))
- obj = rb_float_new(*V_R4REF(pvar));
- else
- obj = rb_float_new(V_R4(pvar));
- break;
-
- case VT_R8:
- if(V_ISBYREF(pvar))
- obj = rb_float_new(*V_R8REF(pvar));
- else
- obj = rb_float_new(V_R8(pvar));
- break;
-
- case VT_BSTR:
- {
- BSTR bstr;
- if(V_ISBYREF(pvar))
- bstr = *V_BSTRREF(pvar);
- else
- bstr = V_BSTR(pvar);
- obj = (SysStringLen(bstr) == 0)
- ? rb_str_new2("")
- : ole_wc2vstr(bstr, FALSE);
- break;
- }
-
- case VT_ERROR:
- if(V_ISBYREF(pvar))
- obj = RB_INT2NUM(*V_ERRORREF(pvar));
- else
- obj = RB_INT2NUM(V_ERROR(pvar));
- break;
-
- case VT_BOOL:
- if (V_ISBYREF(pvar))
- obj = (*V_BOOLREF(pvar) ? Qtrue : Qfalse);
- else
- obj = (V_BOOL(pvar) ? Qtrue : Qfalse);
- break;
-
- case VT_DISPATCH:
- {
- IDispatch *pDispatch;
-
- if (V_ISBYREF(pvar))
- pDispatch = *V_DISPATCHREF(pvar);
- else
- pDispatch = V_DISPATCH(pvar);
-
- if (pDispatch != NULL ) {
- OLE_ADDREF(pDispatch);
- obj = create_win32ole_object(cWIN32OLE, pDispatch, 0, 0);
- }
- break;
- }
-
- case VT_UNKNOWN:
- {
- /* get IDispatch interface from IUnknown interface */
- IUnknown *punk;
- IDispatch *pDispatch;
- void *p;
- HRESULT hr;
-
- if (V_ISBYREF(pvar))
- punk = *V_UNKNOWNREF(pvar);
- else
- punk = V_UNKNOWN(pvar);
-
- if(punk != NULL) {
- hr = punk->lpVtbl->QueryInterface(punk, &IID_IDispatch, &p);
- if(SUCCEEDED(hr)) {
- pDispatch = p;
- obj = create_win32ole_object(cWIN32OLE, pDispatch, 0, 0);
- }
- }
- break;
- }
-
- case VT_DATE:
- {
- DATE date;
- if(V_ISBYREF(pvar))
- date = *V_DATEREF(pvar);
- else
- date = V_DATE(pvar);
-
- obj = vtdate2rbtime(date);
- break;
- }
-
- case VT_RECORD:
- {
- IRecordInfo *pri = V_RECORDINFO(pvar);
- void *prec = V_RECORD(pvar);
- obj = create_win32ole_record(pri, prec);
- break;
- }
-
- case VT_CY:
- default:
- {
- HRESULT hr;
- VARIANT variant;
- VariantInit(&variant);
- hr = VariantChangeTypeEx(&variant, pvar,
- cWIN32OLE_lcid, 0, VT_BSTR);
- if (SUCCEEDED(hr) && V_VT(&variant) == VT_BSTR) {
- obj = ole_wc2vstr(V_BSTR(&variant), FALSE);
- }
- VariantClear(&variant);
- break;
- }
- }
- return obj;
-}
-
-LONG
-reg_open_key(HKEY hkey, const char *name, HKEY *phkey)
-{
- return RegOpenKeyEx(hkey, name, 0, KEY_READ, phkey);
-}
-
-LONG
-reg_open_vkey(HKEY hkey, VALUE key, HKEY *phkey)
-{
- return reg_open_key(hkey, StringValuePtr(key), phkey);
-}
-
-VALUE
-reg_enum_key(HKEY hkey, DWORD i)
-{
- char buf[BUFSIZ + 1];
- DWORD size_buf = sizeof(buf);
- FILETIME ft;
- LONG err = RegEnumKeyEx(hkey, i, buf, &size_buf,
- NULL, NULL, NULL, &ft);
- if(err == ERROR_SUCCESS) {
- buf[BUFSIZ] = '\0';
- return rb_str_new2(buf);
- }
- return Qnil;
-}
-
-VALUE
-reg_get_val(HKEY hkey, const char *subkey)
-{
- char *pbuf;
- DWORD dwtype = 0;
- DWORD size = 0;
- VALUE val = Qnil;
- LONG err = RegQueryValueEx(hkey, subkey, NULL, &dwtype, NULL, &size);
-
- if (err == ERROR_SUCCESS) {
- pbuf = ALLOC_N(char, size + 1);
- err = RegQueryValueEx(hkey, subkey, NULL, &dwtype, (BYTE *)pbuf, &size);
- if (err == ERROR_SUCCESS) {
- pbuf[size] = '\0';
- if (dwtype == REG_EXPAND_SZ) {
- char* pbuf2 = (char *)pbuf;
- DWORD len = ExpandEnvironmentStrings(pbuf2, NULL, 0);
- pbuf = ALLOC_N(char, len + 1);
- ExpandEnvironmentStrings(pbuf2, pbuf, len + 1);
- free(pbuf2);
- }
- val = rb_str_new2((char *)pbuf);
- }
- free(pbuf);
- }
- return val;
-}
-
-VALUE
-reg_get_val2(HKEY hkey, const char *subkey)
-{
- HKEY hsubkey;
- LONG err;
- VALUE val = Qnil;
- err = RegOpenKeyEx(hkey, subkey, 0, KEY_READ, &hsubkey);
- if (err == ERROR_SUCCESS) {
- val = reg_get_val(hsubkey, NULL);
- RegCloseKey(hsubkey);
- }
- if (val == Qnil) {
- val = reg_get_val(hkey, subkey);
- }
- return val;
-}
-
-static void
-ole_const_load(ITypeLib *pTypeLib, VALUE klass, VALUE self)
-{
- unsigned int count;
- unsigned int index;
- int iVar;
- ITypeInfo *pTypeInfo;
- TYPEATTR *pTypeAttr;
- VARDESC *pVarDesc;
- HRESULT hr;
- unsigned int len;
- BSTR bstr;
- char *pName = NULL;
- VALUE val;
- VALUE constant;
- ID id;
- constant = rb_hash_new();
- count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
- for (index = 0; index < count; index++) {
- hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, index, &pTypeInfo);
- if (FAILED(hr))
- continue;
- hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
- if(FAILED(hr)) {
- OLE_RELEASE(pTypeInfo);
- continue;
- }
- for(iVar = 0; iVar < pTypeAttr->cVars; iVar++) {
- hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, iVar, &pVarDesc);
- if(FAILED(hr))
- continue;
- if(pVarDesc->varkind == VAR_CONST &&
- !(pVarDesc->wVarFlags & (VARFLAG_FHIDDEN |
- VARFLAG_FRESTRICTED |
- VARFLAG_FNONBROWSABLE))) {
- hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pVarDesc->memid, &bstr,
- 1, &len);
- if(FAILED(hr) || len == 0 || !bstr)
- continue;
- pName = ole_wc2mb(bstr);
- val = ole_variant2val(V_UNION1(pVarDesc, lpvarValue));
- *pName = toupper((int)*pName);
- id = rb_intern(pName);
- if (rb_is_const_id(id)) {
- if(!rb_const_defined_at(klass, id)) {
- rb_define_const(klass, pName, val);
- }
- }
- else {
- rb_hash_aset(constant, rb_str_new2(pName), val);
- }
- SysFreeString(bstr);
- if(pName) {
- free(pName);
- pName = NULL;
- }
- }
- pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
- }
- pTypeInfo->lpVtbl->ReleaseTypeAttr(pTypeInfo, pTypeAttr);
- OLE_RELEASE(pTypeInfo);
- }
- rb_define_const(klass, "CONSTANTS", constant);
-}
-
-static HRESULT
-clsid_from_remote(VALUE host, VALUE com, CLSID *pclsid)
-{
- HKEY hlm;
- HKEY hpid;
- VALUE subkey;
- LONG err;
- char clsid[100];
- OLECHAR *pbuf;
- DWORD len;
- DWORD dwtype;
- HRESULT hr = S_OK;
- err = RegConnectRegistry(StringValuePtr(host), HKEY_LOCAL_MACHINE, &hlm);
- if (err != ERROR_SUCCESS)
- return HRESULT_FROM_WIN32(err);
- subkey = rb_str_new2("SOFTWARE\\Classes\\");
- rb_str_concat(subkey, com);
- rb_str_cat2(subkey, "\\CLSID");
- err = RegOpenKeyEx(hlm, StringValuePtr(subkey), 0, KEY_READ, &hpid);
- if (err != ERROR_SUCCESS)
- hr = HRESULT_FROM_WIN32(err);
- else {
- len = sizeof(clsid);
- err = RegQueryValueEx(hpid, "", NULL, &dwtype, (BYTE *)clsid, &len);
- if (err == ERROR_SUCCESS && dwtype == REG_SZ) {
- pbuf = ole_mb2wc(clsid, -1, cWIN32OLE_cp);
- hr = CLSIDFromString(pbuf, pclsid);
- SysFreeString(pbuf);
- }
- else {
- hr = HRESULT_FROM_WIN32(err);
- }
- RegCloseKey(hpid);
- }
- RegCloseKey(hlm);
- return hr;
-}
-
-static VALUE
-ole_create_dcom(VALUE self, VALUE ole, VALUE host, VALUE others)
-{
- HRESULT hr;
- CLSID clsid;
- OLECHAR *pbuf;
-
- COSERVERINFO serverinfo;
- MULTI_QI multi_qi;
- DWORD clsctx = CLSCTX_REMOTE_SERVER;
-
- if (!gole32)
- gole32 = LoadLibrary("OLE32");
- if (!gole32)
- rb_raise(rb_eRuntimeError, "failed to load OLE32");
- if (!gCoCreateInstanceEx)
- gCoCreateInstanceEx = (FNCOCREATEINSTANCEEX*)
- GetProcAddress(gole32, "CoCreateInstanceEx");
- if (!gCoCreateInstanceEx)
- rb_raise(rb_eRuntimeError, "CoCreateInstanceEx is not supported in this environment");
-
- pbuf = ole_vstr2wc(ole);
- hr = CLSIDFromProgID(pbuf, &clsid);
- if (FAILED(hr))
- hr = clsid_from_remote(host, ole, &clsid);
- if (FAILED(hr))
- hr = CLSIDFromString(pbuf, &clsid);
- SysFreeString(pbuf);
- if (FAILED(hr))
- ole_raise(hr, eWIN32OLERuntimeError,
- "unknown OLE server: `%s'",
- StringValuePtr(ole));
- memset(&serverinfo, 0, sizeof(COSERVERINFO));
- serverinfo.pwszName = ole_vstr2wc(host);
- memset(&multi_qi, 0, sizeof(MULTI_QI));
- multi_qi.pIID = &IID_IDispatch;
- hr = gCoCreateInstanceEx(&clsid, NULL, clsctx, &serverinfo, 1, &multi_qi);
- SysFreeString(serverinfo.pwszName);
- if (FAILED(hr))
- ole_raise(hr, eWIN32OLERuntimeError,
- "failed to create DCOM server `%s' in `%s'",
- StringValuePtr(ole),
- StringValuePtr(host));
-
- ole_set_member(self, (IDispatch*)multi_qi.pItf);
- return self;
-}
-
-static VALUE
-ole_bind_obj(VALUE moniker, int argc, VALUE *argv, VALUE self)
-{
- IBindCtx *pBindCtx;
- IMoniker *pMoniker;
- IDispatch *pDispatch;
- void *p;
- HRESULT hr;
- OLECHAR *pbuf;
- ULONG eaten = 0;
-
- ole_initialize();
-
- hr = CreateBindCtx(0, &pBindCtx);
- if(FAILED(hr)) {
- ole_raise(hr, eWIN32OLERuntimeError,
- "failed to create bind context");
- }
-
- pbuf = ole_vstr2wc(moniker);
- hr = MkParseDisplayName(pBindCtx, pbuf, &eaten, &pMoniker);
- SysFreeString(pbuf);
- if(FAILED(hr)) {
- OLE_RELEASE(pBindCtx);
- ole_raise(hr, eWIN32OLERuntimeError,
- "failed to parse display name of moniker `%s'",
- StringValuePtr(moniker));
- }
- hr = pMoniker->lpVtbl->BindToObject(pMoniker, pBindCtx, NULL,
- &IID_IDispatch, &p);
- pDispatch = p;
- OLE_RELEASE(pMoniker);
- OLE_RELEASE(pBindCtx);
-
- if(FAILED(hr)) {
- ole_raise(hr, eWIN32OLERuntimeError,
- "failed to bind moniker `%s'",
- StringValuePtr(moniker));
- }
- return create_win32ole_object(self, pDispatch, argc, argv);
-}
-
-/*
- * call-seq:
- * connect(ole) --> aWIN32OLE
- *
- * Returns running OLE Automation object or WIN32OLE object from moniker.
- * 1st argument should be OLE program id or class id or moniker.
- *
- * WIN32OLE.connect('Excel.Application') # => WIN32OLE object which represents running Excel.
- */
-static VALUE
-fole_s_connect(int argc, VALUE *argv, VALUE self)
-{
- VALUE svr_name;
- VALUE others;
- HRESULT hr;
- CLSID clsid;
- OLECHAR *pBuf;
- IDispatch *pDispatch;
- void *p;
- IUnknown *pUnknown;
-
- /* initialize to use OLE */
- ole_initialize();
-
- rb_scan_args(argc, argv, "1*", &svr_name, &others);
- StringValue(svr_name);
-
- /* get CLSID from OLE server name */
- pBuf = ole_vstr2wc(svr_name);
- hr = CLSIDFromProgID(pBuf, &clsid);
- if(FAILED(hr)) {
- hr = CLSIDFromString(pBuf, &clsid);
- }
- SysFreeString(pBuf);
- if(FAILED(hr)) {
- return ole_bind_obj(svr_name, argc, argv, self);
- }
-
- hr = GetActiveObject(&clsid, 0, &pUnknown);
- if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLERuntimeError,
- "OLE server `%s' not running", StringValuePtr(svr_name));
- }
- hr = pUnknown->lpVtbl->QueryInterface(pUnknown, &IID_IDispatch, &p);
- pDispatch = p;
- if(FAILED(hr)) {
- OLE_RELEASE(pUnknown);
- ole_raise(hr, eWIN32OLERuntimeError,
- "failed to create WIN32OLE server `%s'",
- StringValuePtr(svr_name));
- }
-
- OLE_RELEASE(pUnknown);
-
- return create_win32ole_object(self, pDispatch, argc, argv);
-}
-
-/*
- * call-seq:
- * const_load(ole, mod = WIN32OLE)
- *
- * Defines the constants of OLE Automation server as mod's constants.
- * The first argument is WIN32OLE object or type library name.
- * If 2nd argument is omitted, the default is WIN32OLE.
- * The first letter of Ruby's constant variable name is upper case,
- * so constant variable name of WIN32OLE object is capitalized.
- * For example, the 'xlTop' constant of Excel is changed to 'XlTop'
- * in WIN32OLE.
- * If the first letter of constant variable is not [A-Z], then
- * the constant is defined as CONSTANTS hash element.
- *
- * module EXCEL_CONST
- * end
- * excel = WIN32OLE.new('Excel.Application')
- * WIN32OLE.const_load(excel, EXCEL_CONST)
- * puts EXCEL_CONST::XlTop # => -4160
- * puts EXCEL_CONST::CONSTANTS['_xlDialogChartSourceData'] # => 541
- *
- * WIN32OLE.const_load(excel)
- * puts WIN32OLE::XlTop # => -4160
- *
- * module MSO
- * end
- * WIN32OLE.const_load('Microsoft Office 9.0 Object Library', MSO)
- * puts MSO::MsoLineSingle # => 1
- */
-static VALUE
-fole_s_const_load(int argc, VALUE *argv, VALUE self)
-{
- VALUE ole;
- VALUE klass;
- struct oledata *pole = NULL;
- ITypeInfo *pTypeInfo;
- ITypeLib *pTypeLib;
- unsigned int index;
- HRESULT hr;
- OLECHAR *pBuf;
- VALUE file;
- LCID lcid = cWIN32OLE_lcid;
-
- rb_scan_args(argc, argv, "11", &ole, &klass);
- if (!RB_TYPE_P(klass, T_CLASS) &&
- !RB_TYPE_P(klass, T_MODULE) &&
- !RB_TYPE_P(klass, T_NIL)) {
- rb_raise(rb_eTypeError, "2nd parameter must be Class or Module");
- }
- if (rb_obj_is_kind_of(ole, cWIN32OLE)) {
- pole = oledata_get_struct(ole);
- hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch,
- 0, lcid, &pTypeInfo);
- if(FAILED(hr)) {
- ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to GetTypeInfo");
- }
- hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &index);
- if(FAILED(hr)) {
- OLE_RELEASE(pTypeInfo);
- ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to GetContainingTypeLib");
- }
- OLE_RELEASE(pTypeInfo);
- if(!RB_TYPE_P(klass, T_NIL)) {
- ole_const_load(pTypeLib, klass, self);
- }
- else {
- ole_const_load(pTypeLib, cWIN32OLE, self);
- }
- OLE_RELEASE(pTypeLib);
- }
- else if(RB_TYPE_P(ole, T_STRING)) {
- file = typelib_file(ole);
- if (file == Qnil) {
- file = ole;
- }
- pBuf = ole_vstr2wc(file);
- hr = LoadTypeLibEx(pBuf, REGKIND_NONE, &pTypeLib);
- SysFreeString(pBuf);
- if (FAILED(hr))
- ole_raise(hr, eWIN32OLERuntimeError, "failed to LoadTypeLibEx");
- if(!RB_TYPE_P(klass, T_NIL)) {
- ole_const_load(pTypeLib, klass, self);
- }
- else {
- ole_const_load(pTypeLib, cWIN32OLE, self);
- }
- OLE_RELEASE(pTypeLib);
- }
- else {
- rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE instance");
- }
- return Qnil;
-}
-
-static ULONG
-reference_count(struct oledata * pole)
-{
- ULONG n = 0;
- if(pole->pDispatch) {
- OLE_ADDREF(pole->pDispatch);
- n = OLE_RELEASE(pole->pDispatch);
- }
- return n;
-}
-
-/*
- * call-seq:
- * ole_reference_count(aWIN32OLE) --> number
- *
- * Returns reference counter of Dispatch interface of WIN32OLE object.
- * You should not use this method because this method
- * exists only for debugging WIN32OLE.
- */
-static VALUE
-fole_s_reference_count(VALUE self, VALUE obj)
-{
- struct oledata * pole = NULL;
- pole = oledata_get_struct(obj);
- return RB_INT2NUM(reference_count(pole));
-}
-
-/*
- * call-seq:
- * ole_free(aWIN32OLE) --> number
- *
- * Invokes Release method of Dispatch interface of WIN32OLE object.
- * You should not use this method because this method
- * exists only for debugging WIN32OLE.
- * The return value is reference counter of OLE object.
- */
-static VALUE
-fole_s_free(VALUE self, VALUE obj)
-{
- ULONG n = 0;
- struct oledata * pole = NULL;
- pole = oledata_get_struct(obj);
- if(pole->pDispatch) {
- if (reference_count(pole) > 0) {
- n = OLE_RELEASE(pole->pDispatch);
- }
- }
- return RB_INT2NUM(n);
-}
-
-static HWND
-ole_show_help(VALUE helpfile, VALUE helpcontext)
-{
- FNHTMLHELP *pfnHtmlHelp;
- HWND hwnd = 0;
-
- if(!ghhctrl)
- ghhctrl = LoadLibrary("HHCTRL.OCX");
- if (!ghhctrl)
- return hwnd;
- pfnHtmlHelp = (FNHTMLHELP*)GetProcAddress(ghhctrl, "HtmlHelpA");
- if (!pfnHtmlHelp)
- return hwnd;
- hwnd = pfnHtmlHelp(GetDesktopWindow(), StringValuePtr(helpfile),
- 0x0f, RB_NUM2INT(helpcontext));
- if (hwnd == 0)
- hwnd = pfnHtmlHelp(GetDesktopWindow(), StringValuePtr(helpfile),
- 0, RB_NUM2INT(helpcontext));
- return hwnd;
-}
-
-/*
- * call-seq:
- * ole_show_help(obj [,helpcontext])
- *
- * Displays helpfile. The 1st argument specifies WIN32OLE::Type
- * object or WIN32OLE::Method object or helpfile.
- *
- * excel = WIN32OLE.new('Excel.Application')
- * typeobj = excel.ole_type
- * WIN32OLE.ole_show_help(typeobj)
- */
-static VALUE
-fole_s_show_help(int argc, VALUE *argv, VALUE self)
-{
- VALUE target;
- VALUE helpcontext;
- VALUE helpfile;
- VALUE name;
- HWND hwnd;
- rb_scan_args(argc, argv, "11", &target, &helpcontext);
- if (rb_obj_is_kind_of(target, cWIN32OLE_TYPE) ||
- rb_obj_is_kind_of(target, cWIN32OLE_METHOD)) {
- helpfile = rb_funcall(target, rb_intern("helpfile"), 0);
- if(strlen(StringValuePtr(helpfile)) == 0) {
- name = rb_ivar_get(target, rb_intern("name"));
- rb_raise(rb_eRuntimeError, "no helpfile of `%s'",
- StringValuePtr(name));
- }
- helpcontext = rb_funcall(target, rb_intern("helpcontext"), 0);
- } else {
- helpfile = target;
- }
- if (!RB_TYPE_P(helpfile, T_STRING)) {
- rb_raise(rb_eTypeError, "1st parameter must be (String|WIN32OLE::Type|WIN32OLE::Method)");
- }
- hwnd = ole_show_help(helpfile, helpcontext);
- if(hwnd == 0) {
- rb_raise(rb_eRuntimeError, "failed to open help file `%s'",
- StringValuePtr(helpfile));
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * codepage
- *
- * Returns current codepage.
- * WIN32OLE.codepage # => WIN32OLE::CP_ACP
- */
-static VALUE
-fole_s_get_code_page(VALUE self)
-{
- return RB_INT2FIX(cWIN32OLE_cp);
-}
-
-static BOOL CALLBACK
-installed_code_page_proc(LPTSTR str) {
- if (strtoul(str, NULL, 10) == g_cp_to_check) {
- g_cp_installed = TRUE;
- return FALSE;
- }
- return TRUE;
-}
-
-static BOOL
-code_page_installed(UINT cp)
-{
- g_cp_installed = FALSE;
- g_cp_to_check = cp;
- EnumSystemCodePages(installed_code_page_proc, CP_INSTALLED);
- return g_cp_installed;
-}
-
-/*
- * call-seq:
- * codepage = CP
- *
- * Sets current codepage.
- * The WIN32OLE.codepage is initialized according to
- * Encoding.default_internal.
- * If Encoding.default_internal is nil then WIN32OLE.codepage
- * is initialized according to Encoding.default_external.
- *
- * WIN32OLE.codepage = WIN32OLE::CP_UTF8
- * WIN32OLE.codepage = 65001
- */
-static VALUE
-fole_s_set_code_page(VALUE self, VALUE vcp)
-{
- UINT cp = RB_FIX2INT(vcp);
- set_ole_codepage(cp);
- /*
- * Should this method return old codepage?
- */
- return Qnil;
-}
-
-/*
- * call-seq:
- * locale -> locale id.
- *
- * Returns current locale id (lcid). The default locale is
- * WIN32OLE::LOCALE_SYSTEM_DEFAULT.
- *
- * lcid = WIN32OLE.locale
- */
-static VALUE
-fole_s_get_locale(VALUE self)
-{
- return RB_INT2FIX(cWIN32OLE_lcid);
-}
-
-static BOOL
-CALLBACK installed_lcid_proc(LPTSTR str)
-{
- if (strcmp(str, g_lcid_to_check) == 0) {
- g_lcid_installed = TRUE;
- return FALSE;
- }
- return TRUE;
-}
-
-static BOOL
-lcid_installed(LCID lcid)
-{
- g_lcid_installed = FALSE;
- snprintf(g_lcid_to_check, sizeof(g_lcid_to_check), "%08lx", (unsigned long)lcid);
- EnumSystemLocales(installed_lcid_proc, LCID_INSTALLED);
- return g_lcid_installed;
-}
-
-/*
- * call-seq:
- * locale = lcid
- *
- * Sets current locale id (lcid).
- *
- * WIN32OLE.locale = 1033 # set locale English(U.S)
- * obj = WIN32OLE::Variant.new("$100,000", WIN32OLE::VARIANT::VT_CY)
- *
- */
-static VALUE
-fole_s_set_locale(VALUE self, VALUE vlcid)
-{
- LCID lcid = RB_FIX2INT(vlcid);
- if (lcid_installed(lcid)) {
- cWIN32OLE_lcid = lcid;
- } else {
- switch (lcid) {
- case LOCALE_SYSTEM_DEFAULT:
- case LOCALE_USER_DEFAULT:
- cWIN32OLE_lcid = lcid;
- break;
- default:
- rb_raise(eWIN32OLERuntimeError, "not installed locale: %u", (unsigned int)lcid);
- }
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * create_guid
- *
- * Creates GUID.
- * WIN32OLE.create_guid # => {1CB530F1-F6B1-404D-BCE6-1959BF91F4A8}
- */
-static VALUE
-fole_s_create_guid(VALUE self)
-{
- GUID guid;
- HRESULT hr;
- OLECHAR bstr[80];
- int len = 0;
- hr = CoCreateGuid(&guid);
- if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLERuntimeError, "failed to create GUID");
- }
- len = StringFromGUID2(&guid, bstr, sizeof(bstr)/sizeof(OLECHAR));
- if (len == 0) {
- rb_raise(rb_eRuntimeError, "failed to create GUID(buffer over)");
- }
- return ole_wc2vstr(bstr, FALSE);
-}
-
-/*
- * WIN32OLE.ole_initialize and WIN32OLE.ole_uninitialize
- * are used in win32ole.rb to fix the issue bug #2618 (ruby-core:27634).
- * You must not use these method.
- */
-
-/* :nodoc: */
-static VALUE
-fole_s_ole_initialize(VALUE self)
-{
- ole_initialize();
- return Qnil;
-}
-
-/* :nodoc: */
-static VALUE
-fole_s_ole_uninitialize(VALUE self)
-{
- ole_uninitialize();
- return Qnil;
-}
-
-/*
- * Document-class: WIN32OLE
- *
- * +WIN32OLE+ objects represent OLE Automation object in Ruby.
- *
- * By using +WIN32OLE+, you can access OLE server like VBScript.
- *
- * Here is sample script.
- *
- * require 'win32ole'
- *
- * excel = WIN32OLE.new('Excel.Application')
- * excel.visible = true
- * workbook = excel.Workbooks.Add();
- * worksheet = workbook.Worksheets(1);
- * worksheet.Range("A1:D1").value = ["North","South","East","West"];
- * worksheet.Range("A2:B2").value = [5.2, 10];
- * worksheet.Range("C2").value = 8;
- * worksheet.Range("D2").value = 20;
- *
- * range = worksheet.Range("A1:D2");
- * range.select
- * chart = workbook.Charts.Add;
- *
- * workbook.saved = true;
- *
- * excel.ActiveWorkbook.Close(0);
- * excel.Quit();
- *
- * Unfortunately, +WIN32OLE+ doesn't support the argument passed by
- * reference directly.
- * Instead, +WIN32OLE+ provides WIN32OLE::ARGV or WIN32OLE::Variant object.
- * If you want to get the result value of argument passed by reference,
- * you can use WIN32OLE::ARGV or WIN32OLE::Variant.
- *
- * oleobj.method(arg1, arg2, refargv3)
- * puts WIN32OLE::ARGV[2] # the value of refargv3 after called oleobj.method
- *
- * or
- *
- * refargv3 = WIN32OLE::Variant.new(XXX,
- * WIN32OLE::VARIANT::VT_BYREF|WIN32OLE::VARIANT::VT_XXX)
- * oleobj.method(arg1, arg2, refargv3)
- * p refargv3.value # the value of refargv3 after called oleobj.method.
- *
- */
-
-/*
- * call-seq:
- * new(server, [host]) -> WIN32OLE object
- * WIN32OLE.new(server, license: 'key') -> WIN32OLE object
- *
- * Returns a new WIN32OLE object(OLE Automation object).
- * The first argument server specifies OLE Automation server.
- * The first argument should be CLSID or PROGID.
- * If second argument host specified, then returns OLE Automation
- * object on host.
- * If :license keyword argument is provided,
- * IClassFactory2::CreateInstanceLic is used to create instance of
- * licensed server.
- *
- * WIN32OLE.new('Excel.Application') # => Excel OLE Automation WIN32OLE object.
- * WIN32OLE.new('{00024500-0000-0000-C000-000000000046}') # => Excel OLE Automation WIN32OLE object.
- */
-static VALUE
-fole_initialize(int argc, VALUE *argv, VALUE self)
-{
- VALUE svr_name;
- VALUE host;
- VALUE others;
- VALUE opts;
- HRESULT hr;
- CLSID clsid;
- OLECHAR *pBuf;
- OLECHAR *key_buf;
- IDispatch *pDispatch;
- IClassFactory2 * pIClassFactory2;
- void *p;
- static ID keyword_ids[1];
- VALUE kwargs[1];
-
- rb_call_super(0, 0);
- rb_scan_args(argc, argv, "11*:", &svr_name, &host, &others, &opts);
-
- StringValue(svr_name);
- if (!NIL_P(host)) {
- StringValue(host);
- return ole_create_dcom(self, svr_name, host, others);
- }
-
- /* get CLSID from OLE server name */
- pBuf = ole_vstr2wc(svr_name);
- hr = CLSIDFromProgID(pBuf, &clsid);
- if(FAILED(hr)) {
- hr = CLSIDFromString(pBuf, &clsid);
- }
- SysFreeString(pBuf);
- if(FAILED(hr)) {
- ole_raise(hr, eWIN32OLERuntimeError,
- "unknown OLE server: `%s'",
- StringValuePtr(svr_name));
- }
-
- if (!keyword_ids[0]) {
- keyword_ids[0] = rb_intern_const("license");
- }
- rb_get_kwargs(opts, keyword_ids, 0, 1, kwargs);
-
- if (kwargs[0] == Qundef) {
- /* get IDispatch interface */
- hr = CoCreateInstance(
- &clsid,
- NULL,
- CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
- &IID_IDispatch,
- &p
- );
- } else {
- hr = CoGetClassObject(
- &clsid,
- CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
- NULL,
- &IID_IClassFactory2,
- (LPVOID)&pIClassFactory2
- );
- if (hr == S_OK) {
- key_buf = ole_vstr2wc(kwargs[0]);
- hr = pIClassFactory2->lpVtbl->CreateInstanceLic(pIClassFactory2, NULL, NULL, &IID_IDispatch, key_buf, &p);
- SysFreeString(key_buf);
- OLE_RELEASE(pIClassFactory2);
- }
- }
- if(FAILED(hr)) {
- ole_raise(hr, eWIN32OLERuntimeError,
- "failed to create WIN32OLE object from `%s'",
- StringValuePtr(svr_name));
- }
- pDispatch = p;
-
- ole_set_member(self, pDispatch);
- return self;
-}
-
-static int
-hash2named_arg(VALUE key, VALUE val, VALUE pop)
-{
- struct oleparam* pOp = (struct oleparam *)pop;
- unsigned int index, i;
- index = pOp->dp.cNamedArgs;
- /*---------------------------------------------
- the data-type of key must be String or Symbol
- -----------------------------------------------*/
- if(!RB_TYPE_P(key, T_STRING) && !RB_TYPE_P(key, T_SYMBOL)) {
- /* clear name of dispatch parameters */
- for(i = 1; i < index + 1; i++) {
- SysFreeString(pOp->pNamedArgs[i]);
- }
- /* clear dispatch parameters */
- for(i = 0; i < index; i++ ) {
- VariantClear(&(pOp->dp.rgvarg[i]));
- }
- /* raise an exception */
- rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
- }
- if (RB_TYPE_P(key, T_SYMBOL)) {
- key = rb_sym2str(key);
- }
-
- /* pNamedArgs[0] is <method name>, so "index + 1" */
- pOp->pNamedArgs[index + 1] = ole_vstr2wc(key);
-
- VariantInit(&(pOp->dp.rgvarg[index]));
- ole_val2variant(val, &(pOp->dp.rgvarg[index]));
-
- pOp->dp.cNamedArgs += 1;
- return ST_CONTINUE;
-}
-
-static VALUE
-set_argv(VARIANTARG* realargs, unsigned int beg, unsigned int end)
-{
- VALUE argv = rb_const_get(cWIN32OLE, rb_intern("ARGV"));
-
- Check_Type(argv, T_ARRAY);
- rb_ary_clear(argv);
- while (end-- > beg) {
- rb_ary_push(argv, ole_variant2val(&realargs[end]));
- if (V_VT(&realargs[end]) != VT_RECORD) {
- VariantClear(&realargs[end]);
- }
- }
- return argv;
-}
-
-static VALUE
-ole_invoke(int argc, VALUE *argv, VALUE self, USHORT wFlags, BOOL is_bracket)
-{
- LCID lcid = cWIN32OLE_lcid;
- struct oledata *pole = NULL;
- HRESULT hr;
- VALUE cmd;
- VALUE paramS;
- VALUE param;
- VALUE obj;
- VALUE v;
-
- BSTR wcmdname;
-
- DISPID DispID;
- DISPID* pDispID;
- EXCEPINFO excepinfo;
- VARIANT result;
- VARIANTARG* realargs = NULL;
- unsigned int argErr = 0;
- unsigned int i;
- unsigned int cNamedArgs;
- int n;
- struct oleparam op;
- memset(&excepinfo, 0, sizeof(EXCEPINFO));
-
- VariantInit(&result);
-
- op.dp.rgvarg = NULL;
- op.dp.rgdispidNamedArgs = NULL;
- op.dp.cNamedArgs = 0;
- op.dp.cArgs = 0;
-
- rb_scan_args(argc, argv, "1*", &cmd, &paramS);
- if(!RB_TYPE_P(cmd, T_STRING) && !RB_TYPE_P(cmd, T_SYMBOL) && !is_bracket) {
- rb_raise(rb_eTypeError, "method is wrong type (expected String or Symbol)");
- }
- if (RB_TYPE_P(cmd, T_SYMBOL)) {
- cmd = rb_sym2str(cmd);
- }
- pole = oledata_get_struct(self);
- if(!pole->pDispatch) {
- rb_raise(rb_eRuntimeError, "failed to get dispatch interface");
- }
- if (is_bracket) {
- DispID = DISPID_VALUE;
- argc += 1;
- rb_ary_unshift(paramS, cmd);
- } else {
- wcmdname = ole_vstr2wc(cmd);
- hr = pole->pDispatch->lpVtbl->GetIDsOfNames( pole->pDispatch, &IID_NULL,
- &wcmdname, 1, lcid, &DispID);
- SysFreeString(wcmdname);
- if(FAILED(hr)) {
- return rb_eNoMethodError;
- }
- }
-
- /* pick up last argument of method */
- param = rb_ary_entry(paramS, argc-2);
-
- op.dp.cNamedArgs = 0;
-
- /* if last arg is hash object */
- if(RB_TYPE_P(param, T_HASH)) {
- /*------------------------------------------
- hash object ==> named dispatch parameters
- --------------------------------------------*/
- 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);
-
- rb_hash_foreach(param, hash2named_arg, (VALUE)&op);
-
- pDispID = ALLOCA_N(DISPID, cNamedArgs + 1);
- op.pNamedArgs[0] = ole_vstr2wc(cmd);
- hr = pole->pDispatch->lpVtbl->GetIDsOfNames(pole->pDispatch,
- &IID_NULL,
- op.pNamedArgs,
- op.dp.cNamedArgs + 1,
- lcid, pDispID);
- for(i = 0; i < op.dp.cNamedArgs + 1; i++) {
- SysFreeString(op.pNamedArgs[i]);
- op.pNamedArgs[i] = NULL;
- }
- if(FAILED(hr)) {
- /* clear dispatch parameters */
- for(i = 0; i < op.dp.cArgs; i++ ) {
- VariantClear(&op.dp.rgvarg[i]);
- }
- ole_raise(hr, eWIN32OLERuntimeError,
- "failed to get named argument info: `%s'",
- StringValuePtr(cmd));
- }
- op.dp.rgdispidNamedArgs = &(pDispID[1]);
- }
- else {
- cNamedArgs = 0;
- op.dp.cArgs = argc - 1;
- op.pNamedArgs = ALLOCA_N(OLECHAR*, cNamedArgs + 1);
- if (op.dp.cArgs > 0) {
- op.dp.rgvarg = ALLOCA_N(VARIANTARG, op.dp.cArgs);
- }
- }
- /*--------------------------------------
- non hash args ==> dispatch parameters
- ----------------------------------------*/
- if(op.dp.cArgs > cNamedArgs) {
- realargs = ALLOCA_N(VARIANTARG, op.dp.cArgs-cNamedArgs+1);
- for(i = cNamedArgs; i < op.dp.cArgs; i++) {
- n = op.dp.cArgs - i + cNamedArgs - 1;
- VariantInit(&realargs[n]);
- VariantInit(&op.dp.rgvarg[n]);
- param = rb_ary_entry(paramS, i-cNamedArgs);
- if (rb_obj_is_kind_of(param, cWIN32OLE_VARIANT)) {
- ole_variant2variant(param, &op.dp.rgvarg[n]);
- } else if (rb_obj_is_kind_of(param, cWIN32OLE_RECORD)) {
- ole_val2variant(param, &realargs[n]);
- op.dp.rgvarg[n] = realargs[n];
- V_VT(&op.dp.rgvarg[n]) = VT_RECORD | VT_BYREF;
- } else {
- ole_val2variant(param, &realargs[n]);
- V_VT(&op.dp.rgvarg[n]) = VT_VARIANT | VT_BYREF;
- V_VARIANTREF(&op.dp.rgvarg[n]) = &realargs[n];
- }
- }
- }
- /* apparent you need to call propput, you need this */
- if (wFlags & DISPATCH_PROPERTYPUT) {
- if (op.dp.cArgs == 0)
- ole_raise(ResultFromScode(E_INVALIDARG), eWIN32OLERuntimeError, "argument error");
-
- op.dp.cNamedArgs = 1;
- op.dp.rgdispidNamedArgs = ALLOCA_N( DISPID, 1 );
- op.dp.rgdispidNamedArgs[0] = DISPID_PROPERTYPUT;
- }
- hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID,
- &IID_NULL, lcid, wFlags, &op.dp,
- &result, &excepinfo, &argErr);
-
- if (FAILED(hr)) {
- /* retry to call args by value */
- if(op.dp.cArgs >= cNamedArgs) {
- for(i = cNamedArgs; i < op.dp.cArgs; i++) {
- n = op.dp.cArgs - i + cNamedArgs - 1;
- param = rb_ary_entry(paramS, i-cNamedArgs);
- ole_val2variant(param, &op.dp.rgvarg[n]);
- }
- if (hr == DISP_E_EXCEPTION) {
- ole_freeexceptinfo(&excepinfo);
- }
- memset(&excepinfo, 0, sizeof(EXCEPINFO));
- VariantInit(&result);
- hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID,
- &IID_NULL, lcid, wFlags,
- &op.dp, &result,
- &excepinfo, &argErr);
-
- /* mega kludge. if a method in WORD is called and we ask
- * for a result when one is not returned then
- * hResult == DISP_E_EXCEPTION. this only happens on
- * functions whose DISPID > 0x8000 */
- if ((hr == DISP_E_EXCEPTION || hr == DISP_E_MEMBERNOTFOUND) && DispID > 0x8000) {
- if (hr == DISP_E_EXCEPTION) {
- ole_freeexceptinfo(&excepinfo);
- }
- memset(&excepinfo, 0, sizeof(EXCEPINFO));
- hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID,
- &IID_NULL, lcid, wFlags,
- &op.dp, NULL,
- &excepinfo, &argErr);
-
- }
- for(i = cNamedArgs; i < op.dp.cArgs; i++) {
- n = op.dp.cArgs - i + cNamedArgs - 1;
- if (V_VT(&op.dp.rgvarg[n]) != VT_RECORD) {
- VariantClear(&op.dp.rgvarg[n]);
- }
- }
- }
-
- if (FAILED(hr)) {
- /* retry after converting nil to VT_EMPTY */
- if (op.dp.cArgs > cNamedArgs) {
- for(i = cNamedArgs; i < op.dp.cArgs; i++) {
- n = op.dp.cArgs - i + cNamedArgs - 1;
- param = rb_ary_entry(paramS, i-cNamedArgs);
- ole_val2variant2(param, &op.dp.rgvarg[n]);
- }
- if (hr == DISP_E_EXCEPTION) {
- ole_freeexceptinfo(&excepinfo);
- }
- memset(&excepinfo, 0, sizeof(EXCEPINFO));
- VariantInit(&result);
- hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DispID,
- &IID_NULL, lcid, wFlags,
- &op.dp, &result,
- &excepinfo, &argErr);
- for(i = cNamedArgs; i < op.dp.cArgs; i++) {
- n = op.dp.cArgs - i + cNamedArgs - 1;
- if (V_VT(&op.dp.rgvarg[n]) != VT_RECORD) {
- VariantClear(&op.dp.rgvarg[n]);
- }
- }
- }
- }
-
- }
- /* clear dispatch parameter */
- if(op.dp.cArgs > cNamedArgs) {
- for(i = cNamedArgs; i < op.dp.cArgs; i++) {
- n = op.dp.cArgs - i + cNamedArgs - 1;
- param = rb_ary_entry(paramS, i-cNamedArgs);
- if (rb_obj_is_kind_of(param, cWIN32OLE_VARIANT)) {
- ole_val2variant(param, &realargs[n]);
- } else if ( rb_obj_is_kind_of(param, cWIN32OLE_RECORD) &&
- V_VT(&realargs[n]) == VT_RECORD ) {
- olerecord_set_ivar(param, V_RECORDINFO(&realargs[n]), V_RECORD(&realargs[n]));
- }
- }
- set_argv(realargs, cNamedArgs, op.dp.cArgs);
- }
- else {
- for(i = 0; i < op.dp.cArgs; i++) {
- VariantClear(&op.dp.rgvarg[i]);
- }
- }
-
- if (FAILED(hr)) {
- v = ole_excepinfo2msg(&excepinfo);
- ole_raise(hr, eWIN32OLERuntimeError, "(in OLE method `%s': )%s",
- StringValuePtr(cmd),
- StringValuePtr(v));
- }
- obj = ole_variant2val(&result);
- VariantClear(&result);
- return obj;
-}
-
-/*
- * call-seq:
- * invoke(method, [arg1,...]) => return value of method.
- *
- * Runs OLE method.
- * The first argument specifies the method name of OLE Automation object.
- * The others specify argument of the <i>method</i>.
- * If you can not execute <i>method</i> directly, then use this method instead.
- *
- * excel = WIN32OLE.new('Excel.Application')
- * excel.invoke('Quit') # => same as excel.Quit
- *
- */
-static VALUE
-fole_invoke(int argc, VALUE *argv, VALUE self)
-{
- VALUE v = ole_invoke(argc, argv, self, DISPATCH_METHOD|DISPATCH_PROPERTYGET, FALSE);
- if (v == rb_eNoMethodError) {
- return rb_call_super(argc, argv);
- }
- return v;
-}
-
-static VALUE
-ole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types, USHORT dispkind)
-{
- HRESULT hr;
- struct oledata *pole = NULL;
- unsigned int argErr = 0;
- EXCEPINFO excepinfo;
- VARIANT result;
- DISPPARAMS dispParams;
- VARIANTARG* realargs = NULL;
- int i, j; VALUE obj = Qnil;
- VALUE tp, param;
- VALUE v;
- VARTYPE vt;
-
- Check_Type(args, T_ARRAY);
- Check_Type(types, T_ARRAY);
-
- memset(&excepinfo, 0, sizeof(EXCEPINFO));
- memset(&dispParams, 0, sizeof(DISPPARAMS));
- VariantInit(&result);
- pole = oledata_get_struct(self);
-
- dispParams.cArgs = RARRAY_LEN(args);
- dispParams.rgvarg = ALLOCA_N(VARIANTARG, dispParams.cArgs);
- realargs = ALLOCA_N(VARIANTARG, dispParams.cArgs);
- for (i = 0, j = dispParams.cArgs - 1; i < (int)dispParams.cArgs; i++, j--)
- {
- VariantInit(&realargs[i]);
- VariantInit(&dispParams.rgvarg[i]);
- tp = rb_ary_entry(types, j);
- vt = (VARTYPE)RB_FIX2INT(tp);
- V_VT(&dispParams.rgvarg[i]) = vt;
- param = rb_ary_entry(args, j);
- if (param == Qnil)
- {
-
- V_VT(&dispParams.rgvarg[i]) = V_VT(&realargs[i]) = VT_ERROR;
- V_ERROR(&dispParams.rgvarg[i]) = V_ERROR(&realargs[i]) = DISP_E_PARAMNOTFOUND;
- }
- else
- {
- if (vt & VT_ARRAY)
- {
- int ent;
- LPBYTE pb;
- short* ps;
- LPLONG pl;
- VARIANT* pv;
- CY *py;
- VARTYPE v;
- SAFEARRAYBOUND rgsabound[1];
- Check_Type(param, T_ARRAY);
- rgsabound[0].lLbound = 0;
- rgsabound[0].cElements = RARRAY_LEN(param);
- v = vt & ~(VT_ARRAY | VT_BYREF);
- V_ARRAY(&realargs[i]) = SafeArrayCreate(v, 1, rgsabound);
- V_VT(&realargs[i]) = VT_ARRAY | v;
- SafeArrayLock(V_ARRAY(&realargs[i]));
- pb = V_ARRAY(&realargs[i])->pvData;
- ps = V_ARRAY(&realargs[i])->pvData;
- pl = V_ARRAY(&realargs[i])->pvData;
- py = V_ARRAY(&realargs[i])->pvData;
- pv = V_ARRAY(&realargs[i])->pvData;
- for (ent = 0; ent < (int)rgsabound[0].cElements; ent++)
- {
- VARIANT velem;
- VALUE elem = rb_ary_entry(param, ent);
- ole_val2variant(elem, &velem);
- if (v != VT_VARIANT)
- {
- VariantChangeTypeEx(&velem, &velem,
- cWIN32OLE_lcid, 0, v);
- }
- switch (v)
- {
- /* 128 bits */
- case VT_VARIANT:
- *pv++ = velem;
- break;
- /* 64 bits */
- case VT_R8:
- case VT_CY:
- case VT_DATE:
- *py++ = V_CY(&velem);
- break;
- /* 16 bits */
- case VT_BOOL:
- case VT_I2:
- case VT_UI2:
- *ps++ = V_I2(&velem);
- break;
- /* 8 bites */
- case VT_UI1:
- case VT_I1:
- *pb++ = V_UI1(&velem);
- break;
- /* 32 bits */
- default:
- *pl++ = V_I4(&velem);
- break;
- }
- }
- SafeArrayUnlock(V_ARRAY(&realargs[i]));
- }
- else
- {
- ole_val2variant(param, &realargs[i]);
- if ((vt & (~VT_BYREF)) != VT_VARIANT)
- {
- hr = VariantChangeTypeEx(&realargs[i], &realargs[i],
- cWIN32OLE_lcid, 0,
- (VARTYPE)(vt & (~VT_BYREF)));
- if (hr != S_OK)
- {
- rb_raise(rb_eTypeError, "not valid value");
- }
- }
- }
- if ((vt & VT_BYREF) || vt == VT_VARIANT)
- {
- if (vt == VT_VARIANT)
- V_VT(&dispParams.rgvarg[i]) = VT_VARIANT | VT_BYREF;
- switch (vt & (~VT_BYREF))
- {
- /* 128 bits */
- case VT_VARIANT:
- V_VARIANTREF(&dispParams.rgvarg[i]) = &realargs[i];
- break;
- /* 64 bits */
- case VT_R8:
- case VT_CY:
- case VT_DATE:
- V_CYREF(&dispParams.rgvarg[i]) = &V_CY(&realargs[i]);
- break;
- /* 16 bits */
- case VT_BOOL:
- case VT_I2:
- case VT_UI2:
- V_I2REF(&dispParams.rgvarg[i]) = &V_I2(&realargs[i]);
- break;
- /* 8 bites */
- case VT_UI1:
- case VT_I1:
- V_UI1REF(&dispParams.rgvarg[i]) = &V_UI1(&realargs[i]);
- break;
- /* 32 bits */
- default:
- V_I4REF(&dispParams.rgvarg[i]) = &V_I4(&realargs[i]);
- break;
- }
- }
- else
- {
- /* copy 64 bits of data */
- V_CY(&dispParams.rgvarg[i]) = V_CY(&realargs[i]);
- }
- }
- }
-
- if (dispkind & DISPATCH_PROPERTYPUT) {
- dispParams.cNamedArgs = 1;
- dispParams.rgdispidNamedArgs = ALLOCA_N( DISPID, 1 );
- dispParams.rgdispidNamedArgs[0] = DISPID_PROPERTYPUT;
- }
-
- hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, RB_NUM2INT(dispid),
- &IID_NULL, cWIN32OLE_lcid,
- dispkind,
- &dispParams, &result,
- &excepinfo, &argErr);
-
- if (FAILED(hr)) {
- v = ole_excepinfo2msg(&excepinfo);
- ole_raise(hr, eWIN32OLERuntimeError, "(in OLE method `<dispatch id:%d>': )%s",
- RB_NUM2INT(dispid),
- StringValuePtr(v));
- }
-
- /* clear dispatch parameter */
- if(dispParams.cArgs > 0) {
- set_argv(realargs, 0, dispParams.cArgs);
- }
-
- obj = ole_variant2val(&result);
- VariantClear(&result);
- return obj;
-}
-
-/*
- * call-seq:
- * _invoke(dispid, args, types)
- *
- * Runs the early binding method.
- * The 1st argument specifies dispatch ID,
- * the 2nd argument specifies the array of arguments,
- * the 3rd argument specifies the array of the type of arguments.
- *
- * excel = WIN32OLE.new('Excel.Application')
- * excel._invoke(302, [], []) # same effect as excel.Quit
- */
-static VALUE
-fole_invoke2(VALUE self, VALUE dispid, VALUE args, VALUE types)
-{
- return ole_invoke2(self, dispid, args, types, DISPATCH_METHOD);
-}
-
-/*
- * call-seq:
- * _getproperty(dispid, args, types)
- *
- * Runs the early binding method to get property.
- * The 1st argument specifies dispatch ID,
- * the 2nd argument specifies the array of arguments,
- * the 3rd argument specifies the array of the type of arguments.
- *
- * excel = WIN32OLE.new('Excel.Application')
- * puts excel._getproperty(558, [], []) # same effect as puts excel.visible
- */
-static VALUE
-fole_getproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types)
-{
- return ole_invoke2(self, dispid, args, types, DISPATCH_PROPERTYGET);
-}
-
-/*
- * call-seq:
- * _setproperty(dispid, args, types)
- *
- * Runs the early binding method to set property.
- * The 1st argument specifies dispatch ID,
- * the 2nd argument specifies the array of arguments,
- * the 3rd argument specifies the array of the type of arguments.
- *
- * excel = WIN32OLE.new('Excel.Application')
- * excel._setproperty(558, [true], [WIN32OLE::VARIANT::VT_BOOL]) # same effect as excel.visible = true
- */
-static VALUE
-fole_setproperty2(VALUE self, VALUE dispid, VALUE args, VALUE types)
-{
- return ole_invoke2(self, dispid, args, types, DISPATCH_PROPERTYPUT);
-}
-
-/*
- * call-seq:
- * WIN32OLE[a1, a2, ...]=val
- *
- * Sets the value to WIN32OLE object specified by a1, a2, ...
- *
- * dict = WIN32OLE.new('Scripting.Dictionary')
- * dict.add('ruby', 'RUBY')
- * dict['ruby'] = 'Ruby'
- * puts dict['ruby'] # => 'Ruby'
- *
- * Remark: You can not use this method to set the property value.
- *
- * excel = WIN32OLE.new('Excel.Application')
- * # excel['Visible'] = true # This is error !!!
- * excel.Visible = true # You should to use this style to set the property.
- *
- */
-static VALUE
-fole_setproperty_with_bracket(int argc, VALUE *argv, VALUE self)
-{
- VALUE v = ole_invoke(argc, argv, self, DISPATCH_PROPERTYPUT, TRUE);
- if (v == rb_eNoMethodError) {
- return rb_call_super(argc, argv);
- }
- return v;
-}
-
-/*
- * call-seq:
- * setproperty('property', [arg1, arg2,...] val)
- *
- * Sets property of OLE object.
- * When you want to set property with argument, you can use this method.
- *
- * excel = WIN32OLE.new('Excel.Application')
- * excel.Visible = true
- * book = excel.workbooks.add
- * sheet = book.worksheets(1)
- * sheet.setproperty('Cells', 1, 2, 10) # => The B1 cell value is 10.
- */
-static VALUE
-fole_setproperty(int argc, VALUE *argv, VALUE self)
-{
- VALUE v = ole_invoke(argc, argv, self, DISPATCH_PROPERTYPUT, FALSE);
- if (v == rb_eNoMethodError) {
- return rb_call_super(argc, argv);
- }
- return v;
-}
-
-/*
- * call-seq:
- * WIN32OLE[a1,a2,...]
- *
- * Returns the value of Collection specified by a1, a2,....
- *
- * dict = WIN32OLE.new('Scripting.Dictionary')
- * dict.add('ruby', 'Ruby')
- * puts dict['ruby'] # => 'Ruby' (same as `puts dict.item('ruby')')
- *
- * Remark: You can not use this method to get the property.
- * excel = WIN32OLE.new('Excel.Application')
- * # puts excel['Visible'] This is error !!!
- * puts excel.Visible # You should to use this style to get the property.
- *
- */
-static VALUE
-fole_getproperty_with_bracket(int argc, VALUE *argv, VALUE self)
-{
- VALUE v = ole_invoke(argc, argv, self, DISPATCH_PROPERTYGET, TRUE);
- if (v == rb_eNoMethodError) {
- return rb_call_super(argc, argv);
- }
- return v;
-}
-
-static VALUE
-ole_propertyput(VALUE self, VALUE property, VALUE value)
-{
- struct oledata *pole = NULL;
- unsigned argErr;
- unsigned int index;
- HRESULT hr;
- EXCEPINFO excepinfo;
- DISPID dispID = DISPID_VALUE;
- DISPID dispIDParam = DISPID_PROPERTYPUT;
- USHORT wFlags = DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF;
- DISPPARAMS dispParams;
- VARIANTARG propertyValue[2];
- OLECHAR* pBuf[1];
- VALUE v;
- LCID lcid = cWIN32OLE_lcid;
- dispParams.rgdispidNamedArgs = &dispIDParam;
- dispParams.rgvarg = propertyValue;
- dispParams.cNamedArgs = 1;
- dispParams.cArgs = 1;
-
- VariantInit(&propertyValue[0]);
- VariantInit(&propertyValue[1]);
- memset(&excepinfo, 0, sizeof(excepinfo));
-
- pole = oledata_get_struct(self);
-
- /* get ID from property name */
- pBuf[0] = ole_vstr2wc(property);
- hr = pole->pDispatch->lpVtbl->GetIDsOfNames(pole->pDispatch, &IID_NULL,
- pBuf, 1, lcid, &dispID);
- SysFreeString(pBuf[0]);
- pBuf[0] = NULL;
-
- if(FAILED(hr)) {
- ole_raise(hr, eWIN32OLERuntimeError,
- "unknown property or method: `%s'",
- StringValuePtr(property));
- }
- /* set property value */
- ole_val2variant(value, &propertyValue[0]);
- hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, dispID, &IID_NULL,
- lcid, wFlags, &dispParams,
- NULL, &excepinfo, &argErr);
-
- for(index = 0; index < dispParams.cArgs; ++index) {
- VariantClear(&propertyValue[index]);
- }
- if (FAILED(hr)) {
- v = ole_excepinfo2msg(&excepinfo);
- ole_raise(hr, eWIN32OLERuntimeError, "(in setting property `%s': )%s",
- StringValuePtr(property),
- StringValuePtr(v));
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * ole_free
- *
- * invokes Release method of Dispatch interface of WIN32OLE object.
- * Usually, you do not need to call this method because Release method
- * called automatically when WIN32OLE object garbaged.
- *
- */
-static VALUE
-fole_free(VALUE self)
-{
- struct oledata *pole = NULL;
- pole = oledata_get_struct(self);
- OLE_FREE(pole->pDispatch);
- pole->pDispatch = NULL;
- return Qnil;
-}
-
-static VALUE
-ole_each_sub(VALUE pEnumV)
-{
- VARIANT variant;
- VALUE obj = Qnil;
- IEnumVARIANT *pEnum = (IEnumVARIANT *)pEnumV;
- VariantInit(&variant);
- while(pEnum->lpVtbl->Next(pEnum, 1, &variant, NULL) == S_OK) {
- obj = ole_variant2val(&variant);
- VariantClear(&variant);
- VariantInit(&variant);
- rb_yield(obj);
- }
- return Qnil;
-}
-
-static VALUE
-ole_ienum_free(VALUE pEnumV)
-{
- IEnumVARIANT *pEnum = (IEnumVARIANT *)pEnumV;
- OLE_RELEASE(pEnum);
- return Qnil;
-}
-
-/*
- * call-seq:
- * each {|i|...}
- *
- * Iterates over each item of OLE collection which has IEnumVARIANT interface.
- *
- * excel = WIN32OLE.new('Excel.Application')
- * book = excel.workbooks.add
- * sheets = book.worksheets(1)
- * cells = sheets.cells("A1:A5")
- * cells.each do |cell|
- * cell.value = 10
- * end
- */
-static VALUE
-fole_each(VALUE self)
-{
- LCID lcid = cWIN32OLE_lcid;
-
- struct oledata *pole = NULL;
-
- unsigned int argErr;
- EXCEPINFO excepinfo;
- DISPPARAMS dispParams;
- VARIANT result;
- HRESULT hr;
- IEnumVARIANT *pEnum = NULL;
- void *p;
-
- RETURN_ENUMERATOR(self, 0, 0);
-
- VariantInit(&result);
- dispParams.rgvarg = NULL;
- dispParams.rgdispidNamedArgs = NULL;
- dispParams.cNamedArgs = 0;
- dispParams.cArgs = 0;
- memset(&excepinfo, 0, sizeof(excepinfo));
-
- pole = oledata_get_struct(self);
- hr = pole->pDispatch->lpVtbl->Invoke(pole->pDispatch, DISPID_NEWENUM,
- &IID_NULL, lcid,
- DISPATCH_METHOD | DISPATCH_PROPERTYGET,
- &dispParams, &result,
- &excepinfo, &argErr);
-
- if (FAILED(hr)) {
- VariantClear(&result);
- ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to get IEnum Interface");
- }
-
- if (V_VT(&result) == VT_UNKNOWN) {
- hr = V_UNKNOWN(&result)->lpVtbl->QueryInterface(V_UNKNOWN(&result),
- &IID_IEnumVARIANT,
- &p);
- pEnum = p;
- } else if (V_VT(&result) == VT_DISPATCH) {
- hr = V_DISPATCH(&result)->lpVtbl->QueryInterface(V_DISPATCH(&result),
- &IID_IEnumVARIANT,
- &p);
- pEnum = p;
- }
- if (FAILED(hr) || !pEnum) {
- VariantClear(&result);
- ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to get IEnum Interface");
- }
-
- VariantClear(&result);
- rb_ensure(ole_each_sub, (VALUE)pEnum, ole_ienum_free, (VALUE)pEnum);
- return Qnil;
-}
-
-/*
- * call-seq:
- * method_missing(id [,arg1, arg2, ...])
- *
- * Calls WIN32OLE#invoke method.
- */
-static VALUE
-fole_missing(int argc, VALUE *argv, VALUE self)
-{
- VALUE mid, org_mid, sym, v;
- const char* mname;
- long n;
- rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
- mid = org_mid = argv[0];
- sym = rb_check_symbol(&mid);
- if (!NIL_P(sym)) mid = rb_sym2str(sym);
- mname = StringValueCStr(mid);
- if(!mname) {
- rb_raise(rb_eRuntimeError, "fail: unknown method or property");
- }
- n = RSTRING_LEN(mid);
- if(mname[n-1] == '=') {
- rb_check_arity(argc, 2, 2);
- argv[0] = rb_enc_associate(rb_str_subseq(mid, 0, n-1), cWIN32OLE_enc);
-
- return ole_propertyput(self, argv[0], argv[1]);
- }
- else {
- argv[0] = rb_enc_associate(rb_str_dup(mid), cWIN32OLE_enc);
- v = ole_invoke(argc, argv, self, DISPATCH_METHOD|DISPATCH_PROPERTYGET, FALSE);
- if (v == rb_eNoMethodError) {
- argv[0] = org_mid;
- return rb_call_super(argc, argv);
- }
- return v;
- }
-}
-
-static HRESULT
-typeinfo_from_ole(struct oledata *pole, ITypeInfo **ppti)
-{
- ITypeInfo *pTypeInfo;
- ITypeLib *pTypeLib;
- BSTR bstr;
- VALUE type;
- UINT i;
- UINT count;
- LCID lcid = cWIN32OLE_lcid;
- HRESULT hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch,
- 0, lcid, &pTypeInfo);
- if(FAILED(hr)) {
- ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to GetTypeInfo");
- }
- hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo,
- -1,
- &bstr,
- NULL, NULL, NULL);
- type = WC2VSTR(bstr);
- hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &i);
- OLE_RELEASE(pTypeInfo);
- if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to GetContainingTypeLib");
- }
- count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
- for (i = 0; i < count; i++) {
- hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i,
- &bstr, NULL, NULL, NULL);
- if (SUCCEEDED(hr) && rb_str_cmp(WC2VSTR(bstr), type) == 0) {
- hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo);
- if (SUCCEEDED(hr)) {
- *ppti = pTypeInfo;
- break;
- }
- }
- }
- OLE_RELEASE(pTypeLib);
- return hr;
-}
-
-static VALUE
-ole_methods(VALUE self, int mask)
-{
- ITypeInfo *pTypeInfo;
- HRESULT hr;
- VALUE methods;
- struct oledata *pole = NULL;
-
- pole = oledata_get_struct(self);
- methods = rb_ary_new();
-
- hr = typeinfo_from_ole(pole, &pTypeInfo);
- if(FAILED(hr))
- return methods;
- rb_ary_concat(methods, ole_methods_from_typeinfo(pTypeInfo, mask));
- OLE_RELEASE(pTypeInfo);
- return methods;
-}
-
-/*
- * call-seq:
- * ole_methods
- *
- * Returns the array of WIN32OLE::Method object.
- * The element is OLE method of WIN32OLE object.
- *
- * excel = WIN32OLE.new('Excel.Application')
- * methods = excel.ole_methods
- *
- */
-static VALUE
-fole_methods(VALUE self)
-{
- return ole_methods( self, INVOKE_FUNC | INVOKE_PROPERTYGET | INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF);
-}
-
-/*
- * call-seq:
- * ole_get_methods
- *
- * Returns the array of WIN32OLE::Method object .
- * The element of the array is property (gettable) of WIN32OLE object.
- *
- * excel = WIN32OLE.new('Excel.Application')
- * properties = excel.ole_get_methods
- */
-static VALUE
-fole_get_methods(VALUE self)
-{
- return ole_methods( self, INVOKE_PROPERTYGET);
-}
-
-/*
- * call-seq:
- * ole_put_methods
- *
- * Returns the array of WIN32OLE::Method object .
- * The element of the array is property (settable) of WIN32OLE object.
- *
- * excel = WIN32OLE.new('Excel.Application')
- * properties = excel.ole_put_methods
- */
-static VALUE
-fole_put_methods(VALUE self)
-{
- return ole_methods( self, INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF);
-}
-
-/*
- * call-seq:
- * ole_func_methods
- *
- * Returns the array of WIN32OLE::Method object .
- * The element of the array is property (settable) of WIN32OLE object.
- *
- * excel = WIN32OLE.new('Excel.Application')
- * properties = excel.ole_func_methods
- *
- */
-static VALUE
-fole_func_methods(VALUE self)
-{
- return ole_methods( self, INVOKE_FUNC);
-}
-
-/*
- * call-seq:
- * ole_type
- *
- * Returns WIN32OLE::Type object.
- *
- * excel = WIN32OLE.new('Excel.Application')
- * tobj = excel.ole_type
- */
-static VALUE
-fole_type(VALUE self)
-{
- ITypeInfo *pTypeInfo;
- HRESULT hr;
- struct oledata *pole = NULL;
- LCID lcid = cWIN32OLE_lcid;
- VALUE type = Qnil;
-
- pole = oledata_get_struct(self);
-
- hr = pole->pDispatch->lpVtbl->GetTypeInfo( pole->pDispatch, 0, lcid, &pTypeInfo );
- if(FAILED(hr)) {
- ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to GetTypeInfo");
- }
- type = ole_type_from_itypeinfo(pTypeInfo);
- OLE_RELEASE(pTypeInfo);
- if (type == Qnil) {
- rb_raise(rb_eRuntimeError, "failed to create WIN32OLE::Type obj from ITypeInfo");
- }
- return type;
-}
-
-/*
- * call-seq:
- * ole_typelib -> The WIN32OLE_TYPELIB object
- *
- * Returns the WIN32OLE::TypeLib object. The object represents the
- * type library which contains the WIN32OLE object.
- *
- * excel = WIN32OLE.new('Excel.Application')
- * tlib = excel.ole_typelib
- * puts tlib.name # -> 'Microsoft Excel 9.0 Object Library'
- */
-static VALUE
-fole_typelib(VALUE self)
-{
- struct oledata *pole = NULL;
- HRESULT hr;
- ITypeInfo *pTypeInfo;
- LCID lcid = cWIN32OLE_lcid;
- VALUE vtlib = Qnil;
-
- pole = oledata_get_struct(self);
- hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch,
- 0, lcid, &pTypeInfo);
- if(FAILED(hr)) {
- ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to GetTypeInfo");
- }
- vtlib = ole_typelib_from_itypeinfo(pTypeInfo);
- OLE_RELEASE(pTypeInfo);
- if (vtlib == Qnil) {
- rb_raise(rb_eRuntimeError, "failed to get type library info.");
- }
- return vtlib;
-}
-
-/*
- * call-seq:
- * ole_query_interface(iid) -> WIN32OLE object
- *
- * Returns WIN32OLE object for a specific dispatch or dual
- * interface specified by iid.
- *
- * ie = WIN32OLE.new('InternetExplorer.Application')
- * ie_web_app = ie.ole_query_interface('{0002DF05-0000-0000-C000-000000000046}') # => WIN32OLE object for dispinterface IWebBrowserApp
- */
-static VALUE
-fole_query_interface(VALUE self, VALUE str_iid)
-{
- HRESULT hr;
- OLECHAR *pBuf;
- IID iid;
- struct oledata *pole = NULL;
- IDispatch *pDispatch;
- void *p;
-
- pBuf = ole_vstr2wc(str_iid);
- hr = CLSIDFromString(pBuf, &iid);
- SysFreeString(pBuf);
- if(FAILED(hr)) {
- ole_raise(hr, eWIN32OLERuntimeError,
- "invalid iid: `%s'",
- StringValuePtr(str_iid));
- }
-
- pole = oledata_get_struct(self);
- if(!pole->pDispatch) {
- rb_raise(rb_eRuntimeError, "failed to get dispatch interface");
- }
-
- hr = pole->pDispatch->lpVtbl->QueryInterface(pole->pDispatch, &iid,
- &p);
- if(FAILED(hr)) {
- ole_raise(hr, eWIN32OLEQueryInterfaceError,
- "failed to get interface `%s'",
- StringValuePtr(str_iid));
- }
-
- pDispatch = p;
- return create_win32ole_object(cWIN32OLE, pDispatch, 0, 0);
-}
-
-/*
- * call-seq:
- * ole_respond_to?(method) -> true or false
- *
- * Returns true when OLE object has OLE method, otherwise returns false.
- *
- * ie = WIN32OLE.new('InternetExplorer.Application')
- * ie.ole_respond_to?("gohome") => true
- */
-static VALUE
-fole_respond_to(VALUE self, VALUE method)
-{
- struct oledata *pole = NULL;
- BSTR wcmdname;
- DISPID DispID;
- HRESULT hr;
- if(!RB_TYPE_P(method, T_STRING) && !RB_TYPE_P(method, T_SYMBOL)) {
- rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
- }
- if (RB_TYPE_P(method, T_SYMBOL)) {
- method = rb_sym2str(method);
- }
- pole = oledata_get_struct(self);
- wcmdname = ole_vstr2wc(method);
- hr = pole->pDispatch->lpVtbl->GetIDsOfNames( pole->pDispatch, &IID_NULL,
- &wcmdname, 1, cWIN32OLE_lcid, &DispID);
- SysFreeString(wcmdname);
- return SUCCEEDED(hr) ? Qtrue : Qfalse;
-}
-
-HRESULT
-ole_docinfo_from_type(ITypeInfo *pTypeInfo, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile)
-{
- HRESULT hr;
- ITypeLib *pTypeLib;
- UINT i;
-
- hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &i);
- if (FAILED(hr)) {
- return hr;
- }
-
- hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i,
- name, helpstr,
- helpcontext, helpfile);
- if (FAILED(hr)) {
- OLE_RELEASE(pTypeLib);
- return hr;
- }
- OLE_RELEASE(pTypeLib);
- return hr;
-}
-
-static VALUE
-ole_usertype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails)
-{
- HRESULT hr;
- BSTR bstr;
- ITypeInfo *pRefTypeInfo;
- VALUE type = Qnil;
-
- hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo,
- V_UNION1(pTypeDesc, hreftype),
- &pRefTypeInfo);
- if(FAILED(hr))
- return Qnil;
- hr = ole_docinfo_from_type(pRefTypeInfo, &bstr, NULL, NULL, NULL);
- if(FAILED(hr)) {
- OLE_RELEASE(pRefTypeInfo);
- return Qnil;
- }
- OLE_RELEASE(pRefTypeInfo);
- type = WC2VSTR(bstr);
- if(typedetails != Qnil)
- rb_ary_push(typedetails, type);
- return type;
-}
-
-static VALUE
-ole_ptrtype2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails)
-{
- TYPEDESC *p = pTypeDesc;
- VALUE type = rb_str_new2("");
-
- if (p->vt == VT_PTR || p->vt == VT_SAFEARRAY) {
- p = V_UNION1(p, lptdesc);
- type = ole_typedesc2val(pTypeInfo, p, typedetails);
- }
- return type;
-}
-
-VALUE
-ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails)
-{
- VALUE str;
- VALUE typestr = Qnil;
- switch(pTypeDesc->vt) {
- case VT_I2:
- typestr = rb_str_new2("I2");
- break;
- case VT_I4:
- typestr = rb_str_new2("I4");
- break;
- case VT_R4:
- typestr = rb_str_new2("R4");
- break;
- case VT_R8:
- typestr = rb_str_new2("R8");
- break;
- case VT_CY:
- typestr = rb_str_new2("CY");
- break;
- case VT_DATE:
- typestr = rb_str_new2("DATE");
- break;
- case VT_BSTR:
- typestr = rb_str_new2("BSTR");
- break;
- case VT_BOOL:
- typestr = rb_str_new2("BOOL");
- break;
- case VT_VARIANT:
- typestr = rb_str_new2("VARIANT");
- break;
- case VT_DECIMAL:
- typestr = rb_str_new2("DECIMAL");
- break;
- case VT_I1:
- typestr = rb_str_new2("I1");
- break;
- case VT_UI1:
- typestr = rb_str_new2("UI1");
- break;
- case VT_UI2:
- typestr = rb_str_new2("UI2");
- break;
- case VT_UI4:
- typestr = rb_str_new2("UI4");
- break;
-#if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__CYGWIN__) || defined(__MINGW32__)
- case VT_I8:
- typestr = rb_str_new2("I8");
- break;
- case VT_UI8:
- typestr = rb_str_new2("UI8");
- break;
-#endif
- case VT_INT:
- typestr = rb_str_new2("INT");
- break;
- case VT_UINT:
- typestr = rb_str_new2("UINT");
- break;
- case VT_VOID:
- typestr = rb_str_new2("VOID");
- break;
- case VT_HRESULT:
- typestr = rb_str_new2("HRESULT");
- break;
- case VT_PTR:
- typestr = rb_str_new2("PTR");
- if(typedetails != Qnil)
- rb_ary_push(typedetails, typestr);
- return ole_ptrtype2val(pTypeInfo, pTypeDesc, typedetails);
- case VT_SAFEARRAY:
- typestr = rb_str_new2("SAFEARRAY");
- if(typedetails != Qnil)
- rb_ary_push(typedetails, typestr);
- return ole_ptrtype2val(pTypeInfo, pTypeDesc, typedetails);
- case VT_CARRAY:
- typestr = rb_str_new2("CARRAY");
- break;
- case VT_USERDEFINED:
- typestr = rb_str_new2("USERDEFINED");
- if (typedetails != Qnil)
- rb_ary_push(typedetails, typestr);
- str = ole_usertype2val(pTypeInfo, pTypeDesc, typedetails);
- if (str != Qnil) {
- return str;
- }
- return typestr;
- case VT_UNKNOWN:
- typestr = rb_str_new2("UNKNOWN");
- break;
- case VT_DISPATCH:
- typestr = rb_str_new2("DISPATCH");
- break;
- case VT_ERROR:
- typestr = rb_str_new2("ERROR");
- break;
- case VT_LPWSTR:
- typestr = rb_str_new2("LPWSTR");
- break;
- case VT_LPSTR:
- typestr = rb_str_new2("LPSTR");
- break;
- case VT_RECORD:
- typestr = rb_str_new2("RECORD");
- break;
- default:
- typestr = rb_str_new2("Unknown Type ");
- rb_str_concat(typestr, rb_fix2str(RB_INT2FIX(pTypeDesc->vt), 10));
- break;
- }
- if (typedetails != Qnil)
- rb_ary_push(typedetails, typestr);
- return typestr;
-}
-
-/*
- * call-seq:
- * ole_method_help(method)
- *
- * Returns WIN32OLE::Method object corresponding with method
- * specified by 1st argument.
- *
- * excel = WIN32OLE.new('Excel.Application')
- * method = excel.ole_method_help('Quit')
- *
- */
-static VALUE
-fole_method_help(VALUE self, VALUE cmdname)
-{
- ITypeInfo *pTypeInfo;
- HRESULT hr;
- struct oledata *pole = NULL;
- VALUE obj;
-
- SafeStringValue(cmdname);
- pole = oledata_get_struct(self);
- hr = typeinfo_from_ole(pole, &pTypeInfo);
- if(FAILED(hr))
- ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to get ITypeInfo");
-
- obj = create_win32ole_method(pTypeInfo, cmdname);
-
- OLE_RELEASE(pTypeInfo);
- if (obj == Qnil)
- rb_raise(eWIN32OLERuntimeError, "not found %s",
- StringValuePtr(cmdname));
- return obj;
-}
-
-/*
- * call-seq:
- * ole_activex_initialize() -> Qnil
- *
- * Initialize WIN32OLE object(ActiveX Control) by calling
- * IPersistMemory::InitNew.
- *
- * Before calling OLE method, some kind of the ActiveX controls
- * created with MFC should be initialized by calling
- * IPersistXXX::InitNew.
- *
- * If and only if you received the exception "HRESULT error code:
- * 0x8000ffff catastrophic failure", try this method before
- * invoking any ole_method.
- *
- * obj = WIN32OLE.new("ProgID_or_GUID_of_ActiveX_Control")
- * obj.ole_activex_initialize
- * obj.method(...)
- *
- */
-static VALUE
-fole_activex_initialize(VALUE self)
-{
- struct oledata *pole = NULL;
- IPersistMemory *pPersistMemory;
- void *p;
-
- HRESULT hr = S_OK;
-
- pole = oledata_get_struct(self);
-
- hr = pole->pDispatch->lpVtbl->QueryInterface(pole->pDispatch, &IID_IPersistMemory, &p);
- pPersistMemory = p;
- if (SUCCEEDED(hr)) {
- hr = pPersistMemory->lpVtbl->InitNew(pPersistMemory);
- OLE_RELEASE(pPersistMemory);
- if (SUCCEEDED(hr)) {
- return Qnil;
- }
- }
-
- if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLERuntimeError, "fail to initialize ActiveX control");
- }
-
- return Qnil;
-}
-
-HRESULT
-typelib_from_val(VALUE obj, ITypeLib **pTypeLib)
-{
- LCID lcid = cWIN32OLE_lcid;
- HRESULT hr;
- struct oledata *pole = NULL;
- unsigned int index;
- ITypeInfo *pTypeInfo;
- pole = oledata_get_struct(obj);
- hr = pole->pDispatch->lpVtbl->GetTypeInfo(pole->pDispatch,
- 0, lcid, &pTypeInfo);
- if (FAILED(hr)) {
- return hr;
- }
- hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, pTypeLib, &index);
- OLE_RELEASE(pTypeInfo);
- return hr;
-}
-
-static void
-com_hash_free(void *ptr)
-{
- st_table *tbl = ptr;
- st_free_table(tbl);
-}
-
-static void
-com_hash_mark(void *ptr)
-{
- st_table *tbl = ptr;
- rb_mark_hash(tbl);
-}
-
-static size_t
-com_hash_size(const void *ptr)
-{
- const st_table *tbl = ptr;
- return st_memsize(tbl);
-}
-
-static void
-check_nano_server(void)
-{
- HKEY hsubkey;
- LONG err;
- const char * subkey = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Server\\ServerLevels";
- const char * regval = "NanoServer";
-
- err = RegOpenKeyEx(HKEY_LOCAL_MACHINE, subkey, 0, KEY_READ, &hsubkey);
- if (err == ERROR_SUCCESS) {
- err = RegQueryValueEx(hsubkey, regval, NULL, NULL, NULL, NULL);
- if (err == ERROR_SUCCESS) {
- g_running_nano = TRUE;
- }
- RegCloseKey(hsubkey);
- }
-}
-
-LCID cWIN32OLE_lcid;
-
-void
-Init_win32ole(void)
-{
- cWIN32OLE_lcid = LOCALE_SYSTEM_DEFAULT;
- g_ole_initialized_init();
- check_nano_server();
-
- com_vtbl.QueryInterface = QueryInterface;
- com_vtbl.AddRef = AddRef;
- com_vtbl.Release = Release;
- com_vtbl.GetTypeInfoCount = GetTypeInfoCount;
- com_vtbl.GetTypeInfo = GetTypeInfo;
- com_vtbl.GetIDsOfNames = GetIDsOfNames;
- com_vtbl.Invoke = Invoke;
-
- message_filter.QueryInterface = mf_QueryInterface;
- message_filter.AddRef = mf_AddRef;
- message_filter.Release = mf_Release;
- message_filter.HandleInComingCall = mf_HandleInComingCall;
- message_filter.RetryRejectedCall = mf_RetryRejectedCall;
- message_filter.MessagePending = mf_MessagePending;
-
- enc2cp_hash = TypedData_Wrap_Struct(0, &win32ole_hash_datatype, 0);
- RTYPEDDATA_DATA(enc2cp_hash) = st_init_numtable();
- rb_gc_register_mark_object(enc2cp_hash);
-
- com_hash = TypedData_Wrap_Struct(0, &win32ole_hash_datatype, 0);
- RTYPEDDATA_DATA(com_hash) = st_init_numtable();
- rb_gc_register_mark_object(com_hash);
-
- cWIN32OLE = rb_define_class("WIN32OLE", rb_cObject);
-
- rb_define_alloc_func(cWIN32OLE, fole_s_allocate);
-
- rb_define_method(cWIN32OLE, "initialize", fole_initialize, -1);
-
- rb_define_singleton_method(cWIN32OLE, "connect", fole_s_connect, -1);
- rb_define_singleton_method(cWIN32OLE, "const_load", fole_s_const_load, -1);
-
- rb_define_singleton_method(cWIN32OLE, "ole_free", fole_s_free, 1);
- rb_define_singleton_method(cWIN32OLE, "ole_reference_count", fole_s_reference_count, 1);
- rb_define_singleton_method(cWIN32OLE, "ole_show_help", fole_s_show_help, -1);
- rb_define_singleton_method(cWIN32OLE, "codepage", fole_s_get_code_page, 0);
- rb_define_singleton_method(cWIN32OLE, "codepage=", fole_s_set_code_page, 1);
- rb_define_singleton_method(cWIN32OLE, "locale", fole_s_get_locale, 0);
- rb_define_singleton_method(cWIN32OLE, "locale=", fole_s_set_locale, 1);
- rb_define_singleton_method(cWIN32OLE, "create_guid", fole_s_create_guid, 0);
- rb_define_singleton_method(cWIN32OLE, "ole_initialize", fole_s_ole_initialize, 0);
- rb_define_singleton_method(cWIN32OLE, "ole_uninitialize", fole_s_ole_uninitialize, 0);
-
- rb_define_method(cWIN32OLE, "invoke", fole_invoke, -1);
- rb_define_method(cWIN32OLE, "[]", fole_getproperty_with_bracket, -1);
- rb_define_method(cWIN32OLE, "_invoke", fole_invoke2, 3);
- rb_define_method(cWIN32OLE, "_getproperty", fole_getproperty2, 3);
- rb_define_method(cWIN32OLE, "_setproperty", fole_setproperty2, 3);
-
- /* support propput method that takes an argument */
- rb_define_method(cWIN32OLE, "[]=", fole_setproperty_with_bracket, -1);
-
- rb_define_method(cWIN32OLE, "ole_free", fole_free, 0);
-
- rb_define_method(cWIN32OLE, "each", fole_each, 0);
- rb_define_method(cWIN32OLE, "method_missing", fole_missing, -1);
-
- /* support setproperty method much like Perl ;-) */
- rb_define_method(cWIN32OLE, "setproperty", fole_setproperty, -1);
-
- rb_define_method(cWIN32OLE, "ole_methods", fole_methods, 0);
- rb_define_method(cWIN32OLE, "ole_get_methods", fole_get_methods, 0);
- rb_define_method(cWIN32OLE, "ole_put_methods", fole_put_methods, 0);
- rb_define_method(cWIN32OLE, "ole_func_methods", fole_func_methods, 0);
-
- rb_define_method(cWIN32OLE, "ole_method", fole_method_help, 1);
- rb_define_alias(cWIN32OLE, "ole_method_help", "ole_method");
- rb_define_method(cWIN32OLE, "ole_activex_initialize", fole_activex_initialize, 0);
- rb_define_method(cWIN32OLE, "ole_type", fole_type, 0);
- rb_define_alias(cWIN32OLE, "ole_obj_help", "ole_type");
- rb_define_method(cWIN32OLE, "ole_typelib", fole_typelib, 0);
- rb_define_method(cWIN32OLE, "ole_query_interface", fole_query_interface, 1);
- rb_define_method(cWIN32OLE, "ole_respond_to?", fole_respond_to, 1);
-
- /* Constants definition */
-
- /*
- * Version string of WIN32OLE.
- */
- rb_define_const(cWIN32OLE, "VERSION", rb_str_new2(WIN32OLE_VERSION));
-
- /*
- * After invoking OLE methods with reference arguments, you can access
- * the value of arguments by using ARGV.
- *
- * If the method of OLE(COM) server written by C#.NET is following:
- *
- * void calcsum(int a, int b, out int c) {
- * c = a + b;
- * }
- *
- * then, the Ruby OLE(COM) client script to retrieve the value of
- * argument c after invoking calcsum method is following:
- *
- * a = 10
- * b = 20
- * c = 0
- * comserver.calcsum(a, b, c)
- * p c # => 0
- * p WIN32OLE::ARGV # => [10, 20, 30]
- *
- * You can use WIN32OLE::Variant object to retrieve the value of reference
- * arguments instead of referring WIN32OLE::ARGV.
- *
- */
- rb_define_const(cWIN32OLE, "ARGV", rb_ary_new());
-
- /*
- * 0: ANSI code page. See WIN32OLE.codepage and WIN32OLE.codepage=.
- */
- rb_define_const(cWIN32OLE, "CP_ACP", RB_INT2FIX(CP_ACP));
-
- /*
- * 1: OEM code page. See WIN32OLE.codepage and WIN32OLE.codepage=.
- */
- rb_define_const(cWIN32OLE, "CP_OEMCP", RB_INT2FIX(CP_OEMCP));
-
- /*
- * 2
- */
- rb_define_const(cWIN32OLE, "CP_MACCP", RB_INT2FIX(CP_MACCP));
-
- /*
- * 3: current thread ANSI code page. See WIN32OLE.codepage and
- * WIN32OLE.codepage=.
- */
- rb_define_const(cWIN32OLE, "CP_THREAD_ACP", RB_INT2FIX(CP_THREAD_ACP));
-
- /*
- * 42: symbol code page. See WIN32OLE.codepage and WIN32OLE.codepage=.
- */
- rb_define_const(cWIN32OLE, "CP_SYMBOL", RB_INT2FIX(CP_SYMBOL));
-
- /*
- * 65000: UTF-7 code page. See WIN32OLE.codepage and WIN32OLE.codepage=.
- */
- rb_define_const(cWIN32OLE, "CP_UTF7", RB_INT2FIX(CP_UTF7));
-
- /*
- * 65001: UTF-8 code page. See WIN32OLE.codepage and WIN32OLE.codepage=.
- */
- rb_define_const(cWIN32OLE, "CP_UTF8", RB_INT2FIX(CP_UTF8));
-
- /*
- * 0x0800: default locale for the operating system. See WIN32OLE.locale
- * and WIN32OLE.locale=.
- */
- rb_define_const(cWIN32OLE, "LOCALE_SYSTEM_DEFAULT", RB_INT2FIX(LOCALE_SYSTEM_DEFAULT));
-
- /*
- * 0x0400: default locale for the user or process. See WIN32OLE.locale
- * and WIN32OLE.locale=.
- */
- rb_define_const(cWIN32OLE, "LOCALE_USER_DEFAULT", RB_INT2FIX(LOCALE_USER_DEFAULT));
-
- Init_win32ole_variant_m();
- Init_win32ole_typelib();
- Init_win32ole_type();
- Init_win32ole_variable();
- Init_win32ole_method();
- Init_win32ole_param();
- Init_win32ole_event();
- Init_win32ole_variant();
- Init_win32ole_record();
- Init_win32ole_error();
-
- ole_init_cp();
-}
diff --git a/ext/win32ole/win32ole.gemspec b/ext/win32ole/win32ole.gemspec
deleted file mode 100644
index 625916ae17..0000000000
--- a/ext/win32ole/win32ole.gemspec
+++ /dev/null
@@ -1,34 +0,0 @@
-source_version = ["", "ext/win32ole/"].find do |dir|
- begin
- break File.open(File.join(__dir__, "#{dir}win32ole.c")) {|f|
- f.gets("\n#define WIN32OLE_VERSION ")
- f.gets[/\s*"(.+)"/, 1]
- }
- rescue Errno::ENOENT
- end
-end
-
-Gem::Specification.new do |spec|
- spec.name = "win32ole"
- spec.version = source_version
- 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
-
- pathspecs = %W[
- :(exclude,literal)#{File.basename(__FILE__)}
- :^/bin/ :^/test/ :^/rakelib/ :^/.git* :^/Gemfile* :^/Rakefile*
- ]
- spec.files = IO.popen(%w[git ls-files -z --] + pathspecs, chdir: __dir__, err: IO::NULL, exception: false, &:read).split("\x0")
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
- spec.require_paths = ["lib"]
-end
diff --git a/ext/win32ole/win32ole.h b/ext/win32ole/win32ole.h
deleted file mode 100644
index cd627ef765..0000000000
--- a/ext/win32ole/win32ole.h
+++ /dev/null
@@ -1,155 +0,0 @@
-#ifndef WIN32OLE_H
-#define WIN32OLE_H 1
-#include "ruby/ruby.h"
-#include "ruby/st.h"
-#include "ruby/encoding.h"
-
-#define GNUC_OLDER_3_4_4 \
- ((__GNUC__ < 3) || \
- ((__GNUC__ <= 3) && (__GNUC_MINOR__ < 4)) || \
- ((__GNUC__ <= 3) && (__GNUC_MINOR__ <= 4) && (__GNUC_PATCHLEVEL__ <= 4)))
-
-#if (defined(__GNUC__)) && (GNUC_OLDER_3_4_4)
-#ifndef NONAMELESSUNION
-#define NONAMELESSUNION 1
-#endif
-#endif
-
-#include <ctype.h>
-
-#include <windows.h>
-#include <ocidl.h>
-#include <olectl.h>
-#include <ole2.h>
-#if defined(HAVE_TYPE_IMULTILANGUAGE2) || defined(HAVE_TYPE_IMULTILANGUAGE)
-#include <mlang.h>
-#endif
-#include <stdlib.h>
-#include <math.h>
-#ifdef HAVE_STDARG_PROTOTYPES
-#include <stdarg.h>
-#define va_init_list(a,b) va_start(a,b)
-#else
-#include <varargs.h>
-#define va_init_list(a,b) va_start(a)
-#endif
-#include <objidl.h>
-
-#define DOUT fprintf(stderr,"%s(%d)\n", __FILE__, __LINE__)
-#define DOUTS(x) fprintf(stderr,"%s(%d):" #x "=%s\n",__FILE__, __LINE__,x)
-#define DOUTMSG(x) fprintf(stderr, "%s(%d):" #x "\n",__FILE__, __LINE__)
-#define DOUTI(x) fprintf(stderr, "%s(%d):" #x "=%d\n",__FILE__, __LINE__,x)
-#define DOUTD(x) fprintf(stderr, "%s(%d):" #x "=%f\n",__FILE__, __LINE__,x)
-
-#if (defined(__GNUC__)) && (GNUC_OLDER_3_4_4)
-#define V_UNION1(X, Y) ((X)->u.Y)
-#else
-#define V_UNION1(X, Y) ((X)->Y)
-#endif
-
-#if (defined(__GNUC__)) && (GNUC_OLDER_3_4_4)
-#undef V_UNION
-#define V_UNION(X,Y) ((X)->n1.n2.n3.Y)
-
-#undef V_VT
-#define V_VT(X) ((X)->n1.n2.vt)
-
-#undef V_BOOL
-#define V_BOOL(X) V_UNION(X,boolVal)
-#endif
-
-#ifndef V_I1REF
-#define V_I1REF(X) V_UNION(X, pcVal)
-#endif
-
-#ifndef V_UI2REF
-#define V_UI2REF(X) V_UNION(X, puiVal)
-#endif
-
-#ifndef V_INT
-#define V_INT(X) V_UNION(X, intVal)
-#endif
-
-#ifndef V_INTREF
-#define V_INTREF(X) V_UNION(X, pintVal)
-#endif
-
-#ifndef V_UINT
-#define V_UINT(X) V_UNION(X, uintVal)
-#endif
-
-#ifndef V_UINTREF
-#define V_UINTREF(X) V_UNION(X, puintVal)
-#endif
-
-#ifdef HAVE_LONG_LONG
-#define I8_2_NUM LL2NUM
-#define UI8_2_NUM ULL2NUM
-#define NUM2I8 RB_NUM2LL
-#define NUM2UI8 RB_NUM2ULL
-#else
-#define I8_2_NUM RB_INT2NUM
-#define UI8_2_NUM RB_UINT2NUM
-#define NUM2I8 RB_NUM2INT
-#define NUM2UI8 RB_NUM2UINT
-#endif
-
-#define OLE_ADDREF(X) (X) ? ((X)->lpVtbl->AddRef(X)) : 0
-#define OLE_RELEASE(X) (X) ? ((X)->lpVtbl->Release(X)) : 0
-#define OLE_FREE(x) {\
- if(ole_initialized() == TRUE) {\
- if(x) {\
- OLE_RELEASE(x);\
- (x) = 0;\
- }\
- }\
-}
-
-#define OLE_GET_TYPEATTR(X, Y) ((X)->lpVtbl->GetTypeAttr((X), (Y)))
-#define OLE_RELEASE_TYPEATTR(X, Y) ((X)->lpVtbl->ReleaseTypeAttr((X), (Y)))
-
-struct oledata {
- IDispatch *pDispatch;
-};
-
-extern VALUE cWIN32OLE;
-extern LCID cWIN32OLE_lcid;
-
-struct oledata *oledata_get_struct(VALUE obj);
-LPWSTR ole_vstr2wc(VALUE vstr);
-LONG reg_open_key(HKEY hkey, const char *name, HKEY *phkey);
-LONG reg_open_vkey(HKEY hkey, VALUE key, HKEY *phkey);
-VALUE reg_enum_key(HKEY hkey, DWORD i);
-VALUE reg_get_val(HKEY hkey, const char *subkey);
-VALUE reg_get_val2(HKEY hkey, const char *subkey);
-void ole_initialize(void);
-VALUE default_inspect(VALUE self, const char *class_name);
-char *ole_wc2mb(LPWSTR pw);
-VALUE ole_wc2vstr(LPWSTR pw, BOOL isfree);
-
-#define WC2VSTR(x) ole_wc2vstr((x), TRUE)
-
-BOOL ole_initialized(void);
-HRESULT ole_docinfo_from_type(ITypeInfo *pTypeInfo, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile);
-VALUE ole_typedesc2val(ITypeInfo *pTypeInfo, TYPEDESC *pTypeDesc, VALUE typedetails);
-VALUE make_inspect(const char *class_name, VALUE detail);
-void ole_val2variant(VALUE val, VARIANT *var);
-void ole_val2variant2(VALUE val, VARIANT *var);
-void ole_val2variant_ex(VALUE val, VARIANT *var, VARTYPE vt);
-VALUE ole_variant2val(VARIANT *pvar);
-HRESULT ole_val_ary2variant_ary(VALUE val, VARIANT *var, VARTYPE vt);
-VOID *val2variant_ptr(VALUE val, VARIANT *var, VARTYPE vt);
-HRESULT typelib_from_val(VALUE obj, ITypeLib **pTypeLib);
-
-#include "win32ole_variant_m.h"
-#include "win32ole_typelib.h"
-#include "win32ole_type.h"
-#include "win32ole_variable.h"
-#include "win32ole_method.h"
-#include "win32ole_param.h"
-#include "win32ole_event.h"
-#include "win32ole_variant.h"
-#include "win32ole_record.h"
-#include "win32ole_error.h"
-
-#endif
diff --git a/ext/win32ole/win32ole_error.c b/ext/win32ole/win32ole_error.c
deleted file mode 100644
index 66b5136dee..0000000000
--- a/ext/win32ole/win32ole_error.c
+++ /dev/null
@@ -1,96 +0,0 @@
-#include "win32ole.h"
-
-static VALUE ole_hresult2msg(HRESULT hr);
-
-static VALUE
-ole_hresult2msg(HRESULT hr)
-{
- VALUE msg = Qnil;
- char *p_msg = NULL;
- char *term = NULL;
- DWORD dwCount;
-
- char strhr[100];
- sprintf(strhr, " HRESULT error code:0x%08x\n ", (unsigned)hr);
- msg = rb_str_new2(strhr);
- dwCount = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, hr,
- MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
- (LPTSTR)&p_msg, 0, NULL);
- if (dwCount == 0) {
- dwCount = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, hr, cWIN32OLE_lcid,
- (LPTSTR)&p_msg, 0, NULL);
- }
- if (dwCount > 0) {
- term = p_msg + strlen(p_msg);
- while (p_msg < term) {
- term--;
- if (*term == '\r' || *term == '\n')
- *term = '\0';
- else break;
- }
- if (p_msg[0] != '\0') {
- rb_str_cat2(msg, p_msg);
- }
- }
- LocalFree(p_msg);
- return msg;
-}
-
-void
-ole_raise(HRESULT hr, VALUE ecs, const char *fmt, ...)
-{
- va_list args;
- VALUE msg;
- VALUE err_msg;
- va_init_list(args, fmt);
- msg = rb_vsprintf(fmt, args);
- va_end(args);
-
- err_msg = ole_hresult2msg(hr);
- if(err_msg != Qnil) {
- rb_str_cat2(msg, "\n");
- rb_str_append(msg, err_msg);
- }
- rb_exc_raise(rb_exc_new_str(ecs, msg));
-}
-
-VALUE eWIN32OLERuntimeError;
-VALUE eWIN32OLEQueryInterfaceError;
-
-void
-Init_win32ole_error(void)
-{
- /*
- * Document-class: WIN32OLE::RuntimeError
- *
- * Raised when OLE processing failed.
- *
- * EX:
- *
- * obj = WIN32OLE.new("NonExistProgID")
- *
- * raises the exception:
- *
- * WIN32OLE::RuntimeError: unknown OLE server: `NonExistProgID'
- * HRESULT error code:0x800401f3
- * Invalid class string
- *
- */
- eWIN32OLERuntimeError = rb_define_class_under(cWIN32OLE, "RuntimeError", rb_eRuntimeError);
- /* Alias of WIN32OLE::RuntimeError, for the backward compatibility */
- rb_define_const(rb_cObject, "WIN32OLERuntimeError", eWIN32OLERuntimeError);
- /*
- * Document-class: WIN32OLE::QueryInterfaceError
- *
- * Raised when OLE query failed.
- */
- eWIN32OLEQueryInterfaceError = rb_define_class_under(cWIN32OLE, "QueryInterfaceError", eWIN32OLERuntimeError);
- /* Alias of WIN32OLE::QueryInterfaceError, for the backward compatibility */
- rb_define_const(rb_cObject, "WIN32OLEQueryInterfaceError", eWIN32OLEQueryInterfaceError);
-}
diff --git a/ext/win32ole/win32ole_error.h b/ext/win32ole/win32ole_error.h
deleted file mode 100644
index a2f329856f..0000000000
--- a/ext/win32ole/win32ole_error.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef WIN32OLE_ERROR_H
-#define WIN32OLE_ERROR_H 1
-
-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);
-
-#endif
diff --git a/ext/win32ole/win32ole_event.c b/ext/win32ole/win32ole_event.c
deleted file mode 100644
index ff6835e3e4..0000000000
--- a/ext/win32ole/win32ole_event.c
+++ /dev/null
@@ -1,1279 +0,0 @@
-#include "win32ole.h"
-
-/*
- * Document-class: WIN32OLE::Event
- *
- * +WIN32OLE::Event+ objects controls OLE event.
- */
-
-RUBY_EXTERN void rb_write_error_str(VALUE mesg);
-
-typedef struct {
- struct IEventSinkVtbl * lpVtbl;
-} IEventSink, *PEVENTSINK;
-
-typedef struct IEventSinkVtbl IEventSinkVtbl;
-
-struct IEventSinkVtbl {
- STDMETHOD(QueryInterface)(
- PEVENTSINK,
- REFIID,
- LPVOID *);
- STDMETHOD_(ULONG, AddRef)(PEVENTSINK);
- STDMETHOD_(ULONG, Release)(PEVENTSINK);
-
- STDMETHOD(GetTypeInfoCount)(
- PEVENTSINK,
- UINT *);
- STDMETHOD(GetTypeInfo)(
- PEVENTSINK,
- UINT,
- LCID,
- ITypeInfo **);
- STDMETHOD(GetIDsOfNames)(
- PEVENTSINK,
- REFIID,
- OLECHAR **,
- UINT,
- LCID,
- DISPID *);
- STDMETHOD(Invoke)(
- PEVENTSINK,
- DISPID,
- REFIID,
- LCID,
- WORD,
- DISPPARAMS *,
- VARIANT *,
- EXCEPINFO *,
- UINT *);
-};
-
-typedef struct tagIEVENTSINKOBJ {
- const IEventSinkVtbl *lpVtbl;
- DWORD m_cRef;
- IID m_iid;
- long m_event_id;
- ITypeInfo *pTypeInfo;
-}IEVENTSINKOBJ, *PIEVENTSINKOBJ;
-
-struct oleeventdata {
- DWORD dwCookie;
- IConnectionPoint *pConnectionPoint;
- IDispatch *pDispatch;
- long event_id;
-};
-
-static VALUE ary_ole_event;
-static ID id_events;
-
-VALUE cWIN32OLE_EVENT;
-
-STDMETHODIMP EVENTSINK_QueryInterface(PEVENTSINK, REFIID, LPVOID*);
-STDMETHODIMP_(ULONG) EVENTSINK_AddRef(PEVENTSINK);
-STDMETHODIMP_(ULONG) EVENTSINK_Release(PEVENTSINK);
-STDMETHODIMP EVENTSINK_GetTypeInfoCount(PEVENTSINK, UINT*);
-STDMETHODIMP EVENTSINK_GetTypeInfo(PEVENTSINK, UINT, LCID, ITypeInfo**);
-STDMETHODIMP EVENTSINK_GetIDsOfNames(PEVENTSINK, REFIID, OLECHAR**, UINT, LCID, DISPID*);
-STDMETHODIMP EVENTSINK_Invoke(PEVENTSINK, DISPID, REFIID, LCID, WORD, DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT*);
-
-static const IEventSinkVtbl vtEventSink = {
- EVENTSINK_QueryInterface,
- EVENTSINK_AddRef,
- EVENTSINK_Release,
- EVENTSINK_GetTypeInfoCount,
- EVENTSINK_GetTypeInfo,
- EVENTSINK_GetIDsOfNames,
- EVENTSINK_Invoke,
-};
-
-void EVENTSINK_Destructor(PIEVENTSINKOBJ);
-static void ole_val2ptr_variant(VALUE val, VARIANT *var);
-static void hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams);
-static VALUE hash2result(VALUE hash);
-static void ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams);
-static VALUE exec_callback(VALUE arg);
-static VALUE rescue_callback(VALUE arg);
-static HRESULT find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo);
-static HRESULT find_coclass(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **pTypeInfo2, TYPEATTR **pTypeAttr2);
-static HRESULT find_default_source_from_typeinfo(ITypeInfo *pTypeInfo, TYPEATTR *pTypeAttr, ITypeInfo **ppTypeInfo);
-static HRESULT find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo);
-static long ole_search_event_at(VALUE ary, VALUE ev);
-static VALUE ole_search_event(VALUE ary, VALUE ev, BOOL *is_default);
-static VALUE ole_search_handler_method(VALUE handler, VALUE ev, BOOL *is_default_handler);
-static void ole_delete_event(VALUE ary, VALUE ev);
-static void oleevent_free(void *ptr);
-static size_t oleevent_size(const void *ptr);
-static VALUE fev_s_allocate(VALUE klass);
-static VALUE ev_advise(int argc, VALUE *argv, VALUE self);
-static VALUE fev_initialize(int argc, VALUE *argv, VALUE self);
-static void ole_msg_loop(void);
-static VALUE fev_s_msg_loop(VALUE klass);
-static void add_event_call_back(VALUE obj, VALUE event, VALUE data);
-static VALUE ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg);
-static VALUE fev_on_event(int argc, VALUE *argv, VALUE self);
-static VALUE fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self);
-static VALUE fev_off_event(int argc, VALUE *argv, VALUE self);
-static VALUE fev_unadvise(VALUE self);
-static VALUE fev_set_handler(VALUE self, VALUE val);
-static VALUE fev_get_handler(VALUE self);
-static VALUE evs_push(VALUE ev);
-static VALUE evs_delete(long i);
-static VALUE evs_entry(long i);
-static long evs_length(void);
-
-
-static const rb_data_type_t oleevent_datatype = {
- "win32ole_event",
- {NULL, oleevent_free, oleevent_size,},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
-};
-
-STDMETHODIMP EVENTSINK_Invoke(
- PEVENTSINK pEventSink,
- DISPID dispid,
- REFIID riid,
- LCID lcid,
- WORD wFlags,
- DISPPARAMS *pdispparams,
- VARIANT *pvarResult,
- EXCEPINFO *pexcepinfo,
- UINT *puArgErr
- ) {
-
- HRESULT hr;
- BSTR bstr;
- unsigned int count;
- unsigned int i;
- ITypeInfo *pTypeInfo;
- VARIANT *pvar;
- VALUE ary, obj, event, args, outargv, ev, result;
- VALUE handler = Qnil;
- VALUE arg[3];
- VALUE mid;
- VALUE is_outarg = Qfalse;
- BOOL is_default_handler = FALSE;
- int state;
-
- PIEVENTSINKOBJ pEV = (PIEVENTSINKOBJ)pEventSink;
- pTypeInfo = pEV->pTypeInfo;
- obj = evs_entry(pEV->m_event_id);
- if (!rb_obj_is_kind_of(obj, cWIN32OLE_EVENT)) {
- return NOERROR;
- }
-
- ary = rb_ivar_get(obj, id_events);
- if (NIL_P(ary) || !RB_TYPE_P(ary, T_ARRAY)) {
- return NOERROR;
- }
- hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid,
- &bstr, 1, &count);
- if (FAILED(hr)) {
- return NOERROR;
- }
- ev = WC2VSTR(bstr);
- event = ole_search_event(ary, ev, &is_default_handler);
- if (RB_TYPE_P(event, T_ARRAY)) {
- handler = rb_ary_entry(event, 0);
- mid = rb_intern("call");
- is_outarg = rb_ary_entry(event, 3);
- } else {
- handler = rb_ivar_get(obj, rb_intern("handler"));
- if (handler == Qnil) {
- return NOERROR;
- }
- mid = ole_search_handler_method(handler, ev, &is_default_handler);
- }
- if (handler == Qnil || mid == Qnil) {
- return NOERROR;
- }
-
- args = rb_ary_new();
- if (is_default_handler) {
- rb_ary_push(args, ev);
- }
-
- /* make argument of event handler */
- for (i = 0; i < pdispparams->cArgs; ++i) {
- pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
- rb_ary_push(args, ole_variant2val(pvar));
- }
- outargv = Qnil;
- if (is_outarg == Qtrue) {
- outargv = rb_ary_new();
- rb_ary_push(args, outargv);
- }
-
- /*
- * if exception raised in event callback,
- * then you receive cfp consistency error.
- * to avoid this error we use begin rescue end.
- * and the exception raised then error message print
- * and exit ruby process by Win32OLE itself.
- */
- arg[0] = handler;
- arg[1] = mid;
- arg[2] = args;
- result = rb_protect(exec_callback, (VALUE)arg, &state);
- if (state != 0) {
- rescue_callback(Qnil);
- }
- if(RB_TYPE_P(result, T_HASH)) {
- hash2ptr_dispparams(result, pTypeInfo, dispid, pdispparams);
- result = hash2result(result);
- }else if (is_outarg == Qtrue && RB_TYPE_P(outargv, T_ARRAY)) {
- ary2ptr_dispparams(outargv, pdispparams);
- }
-
- if (pvarResult) {
- VariantInit(pvarResult);
- ole_val2variant(result, pvarResult);
- }
-
- return NOERROR;
-}
-
-STDMETHODIMP
-EVENTSINK_QueryInterface(
- PEVENTSINK pEV,
- REFIID iid,
- LPVOID* ppv
- ) {
- if (IsEqualIID(iid, &IID_IUnknown) ||
- IsEqualIID(iid, &IID_IDispatch) ||
- IsEqualIID(iid, &((PIEVENTSINKOBJ)pEV)->m_iid)) {
- *ppv = pEV;
- }
- else {
- *ppv = NULL;
- return E_NOINTERFACE;
- }
- ((LPUNKNOWN)*ppv)->lpVtbl->AddRef((LPUNKNOWN)*ppv);
- return NOERROR;
-}
-
-STDMETHODIMP_(ULONG)
-EVENTSINK_AddRef(
- PEVENTSINK pEV
- ){
- PIEVENTSINKOBJ pEVObj = (PIEVENTSINKOBJ)pEV;
- return ++pEVObj->m_cRef;
-}
-
-STDMETHODIMP_(ULONG) EVENTSINK_Release(
- PEVENTSINK pEV
- ) {
- PIEVENTSINKOBJ pEVObj = (PIEVENTSINKOBJ)pEV;
- --pEVObj->m_cRef;
- if(pEVObj->m_cRef != 0)
- return pEVObj->m_cRef;
- EVENTSINK_Destructor(pEVObj);
- return 0;
-}
-
-STDMETHODIMP EVENTSINK_GetTypeInfoCount(
- PEVENTSINK pEV,
- UINT *pct
- ) {
- *pct = 0;
- return NOERROR;
-}
-
-STDMETHODIMP EVENTSINK_GetTypeInfo(
- PEVENTSINK pEV,
- UINT info,
- LCID lcid,
- ITypeInfo **pInfo
- ) {
- *pInfo = NULL;
- return DISP_E_BADINDEX;
-}
-
-STDMETHODIMP EVENTSINK_GetIDsOfNames(
- PEVENTSINK pEventSink,
- REFIID riid,
- OLECHAR **szNames,
- UINT cNames,
- LCID lcid,
- DISPID *pDispID
- ) {
- ITypeInfo *pTypeInfo;
- PIEVENTSINKOBJ pEV = (PIEVENTSINKOBJ)pEventSink;
- pTypeInfo = pEV->pTypeInfo;
- if (pTypeInfo) {
- return pTypeInfo->lpVtbl->GetIDsOfNames(pTypeInfo, szNames, cNames, pDispID);
- }
- return DISP_E_UNKNOWNNAME;
-}
-
-PIEVENTSINKOBJ
-EVENTSINK_Constructor(void)
-{
- PIEVENTSINKOBJ pEv;
- pEv = ALLOC_N(IEVENTSINKOBJ, 1);
- if(pEv == NULL) return NULL;
- pEv->lpVtbl = &vtEventSink;
- pEv->m_cRef = 0;
- pEv->m_event_id = 0;
- pEv->pTypeInfo = NULL;
- return pEv;
-}
-
-void
-EVENTSINK_Destructor(
- PIEVENTSINKOBJ pEVObj
- ) {
- if(pEVObj != NULL) {
- OLE_RELEASE(pEVObj->pTypeInfo);
- free(pEVObj);
- pEVObj = NULL;
- }
-}
-
-static void
-ole_val2ptr_variant(VALUE val, VARIANT *var)
-{
- switch (TYPE(val)) {
- case T_STRING:
- if (V_VT(var) == (VT_BSTR | VT_BYREF)) {
- *V_BSTRREF(var) = ole_vstr2wc(val);
- }
- break;
- case T_FIXNUM:
- switch(V_VT(var)) {
- case (VT_UI1 | VT_BYREF) :
- *V_UI1REF(var) = RB_NUM2CHR(val);
- break;
- case (VT_I2 | VT_BYREF) :
- *V_I2REF(var) = (short)RB_NUM2INT(val);
- break;
- case (VT_I4 | VT_BYREF) :
- *V_I4REF(var) = RB_NUM2INT(val);
- break;
- case (VT_R4 | VT_BYREF) :
- *V_R4REF(var) = (float)RB_NUM2INT(val);
- break;
- case (VT_R8 | VT_BYREF) :
- *V_R8REF(var) = RB_NUM2INT(val);
- break;
- default:
- break;
- }
- break;
- case T_FLOAT:
- switch(V_VT(var)) {
- case (VT_I2 | VT_BYREF) :
- *V_I2REF(var) = (short)RB_NUM2INT(val);
- break;
- case (VT_I4 | VT_BYREF) :
- *V_I4REF(var) = RB_NUM2INT(val);
- break;
- case (VT_R4 | VT_BYREF) :
- *V_R4REF(var) = (float)NUM2DBL(val);
- break;
- case (VT_R8 | VT_BYREF) :
- *V_R8REF(var) = NUM2DBL(val);
- break;
- default:
- break;
- }
- break;
- case T_BIGNUM:
- if (V_VT(var) == (VT_R8 | VT_BYREF)) {
- *V_R8REF(var) = rb_big2dbl(val);
- }
- break;
- case T_TRUE:
- if (V_VT(var) == (VT_BOOL | VT_BYREF)) {
- *V_BOOLREF(var) = VARIANT_TRUE;
- }
- break;
- case T_FALSE:
- if (V_VT(var) == (VT_BOOL | VT_BYREF)) {
- *V_BOOLREF(var) = VARIANT_FALSE;
- }
- break;
- default:
- break;
- }
-}
-
-static void
-hash2ptr_dispparams(VALUE hash, ITypeInfo *pTypeInfo, DISPID dispid, DISPPARAMS *pdispparams)
-{
- BSTR *bstrs;
- HRESULT hr;
- UINT len, i;
- VARIANT *pvar;
- VALUE val;
- VALUE key;
- len = 0;
- bstrs = ALLOCA_N(BSTR, pdispparams->cArgs + 1);
- hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, dispid,
- bstrs, pdispparams->cArgs + 1,
- &len);
- if (FAILED(hr))
- return;
-
- for (i = 0; i < len - 1; i++) {
- key = WC2VSTR(bstrs[i + 1]);
- val = rb_hash_aref(hash, RB_UINT2NUM(i));
- if (val == Qnil)
- val = rb_hash_aref(hash, key);
- if (val == Qnil)
- val = rb_hash_aref(hash, rb_str_intern(key));
- pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
- ole_val2ptr_variant(val, pvar);
- }
-}
-
-static VALUE
-hash2result(VALUE hash)
-{
- VALUE ret = Qnil;
- ret = rb_hash_aref(hash, rb_str_new2("return"));
- if (ret == Qnil)
- ret = rb_hash_aref(hash, rb_str_intern(rb_str_new2("return")));
- return ret;
-}
-
-static void
-ary2ptr_dispparams(VALUE ary, DISPPARAMS *pdispparams)
-{
- int i;
- VALUE v;
- VARIANT *pvar;
- for(i = 0; i < RARRAY_LEN(ary) && (unsigned int) i < pdispparams->cArgs; i++) {
- v = rb_ary_entry(ary, i);
- pvar = &pdispparams->rgvarg[pdispparams->cArgs-i-1];
- ole_val2ptr_variant(v, pvar);
- }
-}
-
-static VALUE
-exec_callback(VALUE arg)
-{
- VALUE *parg = (VALUE *)arg;
- VALUE handler = parg[0];
- VALUE mid = parg[1];
- VALUE args = parg[2];
- return rb_apply(handler, mid, args);
-}
-
-static VALUE
-rescue_callback(VALUE arg)
-{
-
- VALUE error;
- VALUE e = rb_errinfo();
- VALUE bt = rb_funcall(e, rb_intern("backtrace"), 0);
- VALUE msg = rb_funcall(e, rb_intern("message"), 0);
- bt = rb_ary_entry(bt, 0);
- error = rb_sprintf("%"PRIsVALUE": %"PRIsVALUE" (%s)\n", bt, msg, rb_obj_classname(e));
- rb_write_error_str(error);
- rb_backtrace();
- ruby_finalize();
- exit(-1);
-
- return Qnil;
-}
-
-static HRESULT
-find_iid(VALUE ole, char *pitf, IID *piid, ITypeInfo **ppTypeInfo)
-{
- HRESULT hr;
- IDispatch *pDispatch;
- ITypeInfo *pTypeInfo;
- ITypeLib *pTypeLib;
- TYPEATTR *pTypeAttr;
- HREFTYPE RefType;
- ITypeInfo *pImplTypeInfo;
- TYPEATTR *pImplTypeAttr;
-
- struct oledata *pole = NULL;
- unsigned int index;
- unsigned int count;
- int type;
- BSTR bstr;
- char *pstr;
-
- BOOL is_found = FALSE;
- LCID lcid = cWIN32OLE_lcid;
-
- pole = oledata_get_struct(ole);
-
- pDispatch = pole->pDispatch;
-
- hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0, lcid, &pTypeInfo);
- if (FAILED(hr))
- return hr;
-
- hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo,
- &pTypeLib,
- &index);
- OLE_RELEASE(pTypeInfo);
- if (FAILED(hr))
- return hr;
-
- if (!pitf) {
- hr = pTypeLib->lpVtbl->GetTypeInfoOfGuid(pTypeLib,
- piid,
- ppTypeInfo);
- OLE_RELEASE(pTypeLib);
- return hr;
- }
- count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
- for (index = 0; index < count; index++) {
- hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib,
- index,
- &pTypeInfo);
- if (FAILED(hr))
- break;
- hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
-
- if(FAILED(hr)) {
- OLE_RELEASE(pTypeInfo);
- break;
- }
- if(pTypeAttr->typekind == TKIND_COCLASS) {
- for (type = 0; type < pTypeAttr->cImplTypes; type++) {
- hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo,
- type,
- &RefType);
- if (FAILED(hr))
- break;
- hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo,
- RefType,
- &pImplTypeInfo);
- if (FAILED(hr))
- break;
-
- hr = pImplTypeInfo->lpVtbl->GetDocumentation(pImplTypeInfo,
- -1,
- &bstr,
- NULL, NULL, NULL);
- if (FAILED(hr)) {
- OLE_RELEASE(pImplTypeInfo);
- break;
- }
- pstr = ole_wc2mb(bstr);
- if (strcmp(pitf, pstr) == 0) {
- hr = pImplTypeInfo->lpVtbl->GetTypeAttr(pImplTypeInfo,
- &pImplTypeAttr);
- if (SUCCEEDED(hr)) {
- is_found = TRUE;
- *piid = pImplTypeAttr->guid;
- if (ppTypeInfo) {
- *ppTypeInfo = pImplTypeInfo;
- (*ppTypeInfo)->lpVtbl->AddRef((*ppTypeInfo));
- }
- pImplTypeInfo->lpVtbl->ReleaseTypeAttr(pImplTypeInfo,
- pImplTypeAttr);
- }
- }
- free(pstr);
- OLE_RELEASE(pImplTypeInfo);
- if (is_found || FAILED(hr))
- break;
- }
- }
-
- OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
- OLE_RELEASE(pTypeInfo);
- if (is_found || FAILED(hr))
- break;
- }
- OLE_RELEASE(pTypeLib);
- if(!is_found)
- return E_NOINTERFACE;
- return hr;
-}
-
-static HRESULT
-find_coclass(
- ITypeInfo *pTypeInfo,
- TYPEATTR *pTypeAttr,
- ITypeInfo **pCOTypeInfo,
- TYPEATTR **pCOTypeAttr)
-{
- HRESULT hr = E_NOINTERFACE;
- ITypeLib *pTypeLib;
- int count;
- BOOL found = FALSE;
- ITypeInfo *pTypeInfo2;
- TYPEATTR *pTypeAttr2;
- int flags;
- int i,j;
- HREFTYPE href;
- ITypeInfo *pRefTypeInfo;
- TYPEATTR *pRefTypeAttr;
-
- hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, NULL);
- if (FAILED(hr)) {
- return hr;
- }
- count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
- for (i = 0; i < count && !found; i++) {
- hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo2);
- if (FAILED(hr))
- continue;
- hr = OLE_GET_TYPEATTR(pTypeInfo2, &pTypeAttr2);
- if (FAILED(hr)) {
- OLE_RELEASE(pTypeInfo2);
- continue;
- }
- if (pTypeAttr2->typekind != TKIND_COCLASS) {
- OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2);
- OLE_RELEASE(pTypeInfo2);
- continue;
- }
- for (j = 0; j < pTypeAttr2->cImplTypes && !found; j++) {
- hr = pTypeInfo2->lpVtbl->GetImplTypeFlags(pTypeInfo2, j, &flags);
- if (FAILED(hr))
- continue;
- if (!(flags & IMPLTYPEFLAG_FDEFAULT))
- continue;
- hr = pTypeInfo2->lpVtbl->GetRefTypeOfImplType(pTypeInfo2, j, &href);
- if (FAILED(hr))
- continue;
- hr = pTypeInfo2->lpVtbl->GetRefTypeInfo(pTypeInfo2, href, &pRefTypeInfo);
- if (FAILED(hr))
- continue;
- hr = OLE_GET_TYPEATTR(pRefTypeInfo, &pRefTypeAttr);
- if (FAILED(hr)) {
- OLE_RELEASE(pRefTypeInfo);
- continue;
- }
- if (IsEqualGUID(&(pTypeAttr->guid), &(pRefTypeAttr->guid))) {
- found = TRUE;
- }
- }
- if (!found) {
- OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2);
- OLE_RELEASE(pTypeInfo2);
- }
- }
- OLE_RELEASE(pTypeLib);
- if (found) {
- *pCOTypeInfo = pTypeInfo2;
- *pCOTypeAttr = pTypeAttr2;
- hr = S_OK;
- } else {
- hr = E_NOINTERFACE;
- }
- return hr;
-}
-
-static HRESULT
-find_default_source_from_typeinfo(
- ITypeInfo *pTypeInfo,
- TYPEATTR *pTypeAttr,
- ITypeInfo **ppTypeInfo)
-{
- int i = 0;
- HRESULT hr = E_NOINTERFACE;
- int flags;
- HREFTYPE hRefType;
- /* Enumerate all implemented types of the COCLASS */
- for (i = 0; i < pTypeAttr->cImplTypes; i++) {
- hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags);
- if (FAILED(hr))
- continue;
-
- /*
- looking for the [default] [source]
- we just hope that it is a dispinterface :-)
- */
- if ((flags & IMPLTYPEFLAG_FDEFAULT) &&
- (flags & IMPLTYPEFLAG_FSOURCE)) {
-
- hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo,
- i, &hRefType);
- if (FAILED(hr))
- continue;
- hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo,
- hRefType, ppTypeInfo);
- if (SUCCEEDED(hr))
- break;
- }
- }
- return hr;
-}
-
-static HRESULT
-find_default_source(VALUE ole, IID *piid, ITypeInfo **ppTypeInfo)
-{
- HRESULT hr;
- IProvideClassInfo2 *pProvideClassInfo2;
- IProvideClassInfo *pProvideClassInfo;
- void *p;
-
- IDispatch *pDispatch;
- ITypeInfo *pTypeInfo;
- ITypeInfo *pTypeInfo2 = NULL;
- TYPEATTR *pTypeAttr;
- TYPEATTR *pTypeAttr2 = NULL;
-
- struct oledata *pole = NULL;
-
- pole = oledata_get_struct(ole);
- pDispatch = pole->pDispatch;
- hr = pDispatch->lpVtbl->QueryInterface(pDispatch,
- &IID_IProvideClassInfo2,
- &p);
- if (SUCCEEDED(hr)) {
- pProvideClassInfo2 = p;
- hr = pProvideClassInfo2->lpVtbl->GetGUID(pProvideClassInfo2,
- GUIDKIND_DEFAULT_SOURCE_DISP_IID,
- piid);
- OLE_RELEASE(pProvideClassInfo2);
- if (SUCCEEDED(hr)) {
- hr = find_iid(ole, NULL, piid, ppTypeInfo);
- }
- }
- if (SUCCEEDED(hr)) {
- return hr;
- }
- hr = pDispatch->lpVtbl->QueryInterface(pDispatch,
- &IID_IProvideClassInfo,
- &p);
- if (SUCCEEDED(hr)) {
- pProvideClassInfo = p;
- hr = pProvideClassInfo->lpVtbl->GetClassInfo(pProvideClassInfo,
- &pTypeInfo);
- OLE_RELEASE(pProvideClassInfo);
- }
- if (FAILED(hr)) {
- hr = pDispatch->lpVtbl->GetTypeInfo(pDispatch, 0, cWIN32OLE_lcid, &pTypeInfo );
- }
- if (FAILED(hr))
- return hr;
- hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
- if (FAILED(hr)) {
- OLE_RELEASE(pTypeInfo);
- return hr;
- }
-
- *ppTypeInfo = 0;
- hr = find_default_source_from_typeinfo(pTypeInfo, pTypeAttr, ppTypeInfo);
- if (!*ppTypeInfo) {
- hr = find_coclass(pTypeInfo, pTypeAttr, &pTypeInfo2, &pTypeAttr2);
- if (SUCCEEDED(hr)) {
- hr = find_default_source_from_typeinfo(pTypeInfo2, pTypeAttr2, ppTypeInfo);
- OLE_RELEASE_TYPEATTR(pTypeInfo2, pTypeAttr2);
- OLE_RELEASE(pTypeInfo2);
- }
- }
- OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
- OLE_RELEASE(pTypeInfo);
- /* Now that would be a bad surprise, if we didn't find it, wouldn't it? */
- if (!*ppTypeInfo) {
- if (SUCCEEDED(hr))
- hr = E_UNEXPECTED;
- return hr;
- }
-
- /* Determine IID of default source interface */
- hr = (*ppTypeInfo)->lpVtbl->GetTypeAttr(*ppTypeInfo, &pTypeAttr);
- if (SUCCEEDED(hr)) {
- *piid = pTypeAttr->guid;
- (*ppTypeInfo)->lpVtbl->ReleaseTypeAttr(*ppTypeInfo, pTypeAttr);
- }
- else
- OLE_RELEASE(*ppTypeInfo);
-
- return hr;
-}
-
-static long
-ole_search_event_at(VALUE ary, VALUE ev)
-{
- VALUE event;
- VALUE event_name;
- long i, len;
- long ret = -1;
- len = RARRAY_LEN(ary);
- for(i = 0; i < len; i++) {
- event = rb_ary_entry(ary, i);
- event_name = rb_ary_entry(event, 1);
- if(NIL_P(event_name) && NIL_P(ev)) {
- ret = i;
- break;
- }
- else if (RB_TYPE_P(ev, T_STRING) &&
- RB_TYPE_P(event_name, T_STRING) &&
- rb_str_cmp(ev, event_name) == 0) {
- ret = i;
- break;
- }
- }
- return ret;
-}
-
-static VALUE
-ole_search_event(VALUE ary, VALUE ev, BOOL *is_default)
-{
- VALUE event;
- VALUE def_event;
- VALUE event_name;
- int i, len;
- *is_default = FALSE;
- def_event = Qnil;
- len = RARRAY_LEN(ary);
- for(i = 0; i < len; i++) {
- event = rb_ary_entry(ary, i);
- event_name = rb_ary_entry(event, 1);
- if(NIL_P(event_name)) {
- *is_default = TRUE;
- def_event = event;
- }
- else if (rb_str_cmp(ev, event_name) == 0) {
- *is_default = FALSE;
- return event;
- }
- }
- return def_event;
-}
-
-static VALUE
-ole_search_handler_method(VALUE handler, VALUE ev, BOOL *is_default_handler)
-{
- VALUE mid;
-
- *is_default_handler = FALSE;
- mid = rb_to_id(rb_sprintf("on%"PRIsVALUE, ev));
- if (rb_respond_to(handler, mid)) {
- return mid;
- }
- mid = rb_intern("method_missing");
- if (rb_respond_to(handler, mid)) {
- *is_default_handler = TRUE;
- return mid;
- }
- return Qnil;
-}
-
-static void
-ole_delete_event(VALUE ary, VALUE ev)
-{
- long at = -1;
- at = ole_search_event_at(ary, ev);
- if (at >= 0) {
- rb_ary_delete_at(ary, at);
- }
-}
-
-
-static void
-oleevent_free(void *ptr)
-{
- struct oleeventdata *poleev = ptr;
- if (poleev->pConnectionPoint) {
- poleev->pConnectionPoint->lpVtbl->Unadvise(poleev->pConnectionPoint, poleev->dwCookie);
- OLE_RELEASE(poleev->pConnectionPoint);
- poleev->pConnectionPoint = NULL;
- }
- OLE_RELEASE(poleev->pDispatch);
- free(poleev);
-}
-
-static size_t
-oleevent_size(const void *ptr)
-{
- return ptr ? sizeof(struct oleeventdata) : 0;
-}
-
-static VALUE
-fev_s_allocate(VALUE klass)
-{
- VALUE obj;
- struct oleeventdata *poleev;
- obj = TypedData_Make_Struct(klass, struct oleeventdata, &oleevent_datatype, poleev);
- poleev->dwCookie = 0;
- poleev->pConnectionPoint = NULL;
- poleev->event_id = 0;
- poleev->pDispatch = NULL;
- return obj;
-}
-
-static VALUE
-ev_advise(int argc, VALUE *argv, VALUE self)
-{
-
- VALUE ole, itf;
- struct oledata *pole = NULL;
- char *pitf;
- HRESULT hr;
- IID iid;
- ITypeInfo *pTypeInfo = 0;
- IDispatch *pDispatch;
- IConnectionPointContainer *pContainer;
- IConnectionPoint *pConnectionPoint;
- IEVENTSINKOBJ *pIEV;
- DWORD dwCookie;
- struct oleeventdata *poleev;
- void *p;
-
- rb_scan_args(argc, argv, "11", &ole, &itf);
-
- if (!rb_obj_is_kind_of(ole, cWIN32OLE)) {
- rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE object");
- }
-
- if(!RB_TYPE_P(itf, T_NIL)) {
- pitf = StringValuePtr(itf);
- hr = find_iid(ole, pitf, &iid, &pTypeInfo);
- }
- else {
- hr = find_default_source(ole, &iid, &pTypeInfo);
- }
- if (FAILED(hr)) {
- ole_raise(hr, rb_eRuntimeError, "interface not found");
- }
-
- pole = oledata_get_struct(ole);
- pDispatch = pole->pDispatch;
- hr = pDispatch->lpVtbl->QueryInterface(pDispatch,
- &IID_IConnectionPointContainer,
- &p);
- if (FAILED(hr)) {
- OLE_RELEASE(pTypeInfo);
- ole_raise(hr, eWIN32OLEQueryInterfaceError,
- "failed to query IConnectionPointContainer");
- }
- pContainer = p;
-
- hr = pContainer->lpVtbl->FindConnectionPoint(pContainer,
- &iid,
- &pConnectionPoint);
- OLE_RELEASE(pContainer);
- if (FAILED(hr)) {
- OLE_RELEASE(pTypeInfo);
- ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to query IConnectionPoint");
- }
- pIEV = EVENTSINK_Constructor();
- pIEV->m_iid = iid;
- hr = pConnectionPoint->lpVtbl->Advise(pConnectionPoint,
- (IUnknown*)pIEV,
- &dwCookie);
- if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLEQueryInterfaceError, "Advise Error");
- }
-
- TypedData_Get_Struct(self, struct oleeventdata, &oleevent_datatype, poleev);
- pIEV->m_event_id = evs_length();
- pIEV->pTypeInfo = pTypeInfo;
- poleev->dwCookie = dwCookie;
- poleev->pConnectionPoint = pConnectionPoint;
- poleev->event_id = pIEV->m_event_id;
- poleev->pDispatch = pDispatch;
- OLE_ADDREF(pDispatch);
-
- return self;
-}
-
-/*
- * call-seq:
- * new(ole, event) #=> WIN32OLE::Event object.
- *
- * Returns OLE event object.
- * The first argument specifies WIN32OLE object.
- * The second argument specifies OLE event name.
- * ie = WIN32OLE.new('InternetExplorer.Application')
- * ev = WIN32OLE::Event.new(ie, 'DWebBrowserEvents')
- */
-static VALUE
-fev_initialize(int argc, VALUE *argv, VALUE self)
-{
- ev_advise(argc, argv, self);
- evs_push(self);
- rb_ivar_set(self, id_events, rb_ary_new());
- fev_set_handler(self, Qnil);
- return self;
-}
-
-static void
-ole_msg_loop(void)
-{
- MSG msg;
- while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
-}
-
-/*
- * call-seq:
- * message_loop
- *
- * Translates and dispatches Windows message.
- */
-static VALUE
-fev_s_msg_loop(VALUE klass)
-{
- ole_msg_loop();
- return Qnil;
-}
-
-static void
-add_event_call_back(VALUE obj, VALUE event, VALUE data)
-{
- VALUE events = rb_ivar_get(obj, id_events);
- if (NIL_P(events) || !RB_TYPE_P(events, T_ARRAY)) {
- events = rb_ary_new();
- rb_ivar_set(obj, id_events, events);
- }
- ole_delete_event(events, event);
- rb_ary_push(events, data);
-}
-
-static VALUE
-ev_on_event(int argc, VALUE *argv, VALUE self, VALUE is_ary_arg)
-{
- struct oleeventdata *poleev;
- VALUE event, args, data;
- TypedData_Get_Struct(self, struct oleeventdata, &oleevent_datatype, poleev);
- if (poleev->pConnectionPoint == NULL) {
- rb_raise(eWIN32OLERuntimeError, "IConnectionPoint not found. You must call advise at first.");
- }
- rb_scan_args(argc, argv, "01*", &event, &args);
- if(!NIL_P(event)) {
- if(!RB_TYPE_P(event, T_STRING) && !RB_TYPE_P(event, T_SYMBOL)) {
- rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
- }
- if (RB_TYPE_P(event, T_SYMBOL)) {
- event = rb_sym2str(event);
- }
- }
- data = rb_ary_new3(4, rb_block_proc(), event, args, is_ary_arg);
- add_event_call_back(self, event, data);
- return Qnil;
-}
-
-/*
- * call-seq:
- * on_event([event]){...}
- *
- * Defines the callback event.
- * If argument is omitted, this method defines the callback of all events.
- * If you want to modify reference argument in callback, return hash in
- * callback. If you want to return value to OLE server as result of callback
- * use `return' or :return.
- *
- * ie = WIN32OLE.new('InternetExplorer.Application')
- * ev = WIN32OLE::Event.new(ie)
- * ev.on_event("NavigateComplete") {|url| puts url}
- * ev.on_event() {|ev, *args| puts "#{ev} fired"}
- *
- * ev.on_event("BeforeNavigate2") {|*args|
- * # ...
- * # set true to BeforeNavigate reference argument `Cancel'.
- * # Cancel is 7-th argument of BeforeNavigate,
- * # so you can use 6 as key of hash instead of 'Cancel'.
- * # The argument is counted from 0.
- * # The hash key of 0 means first argument.)
- * {:Cancel => true} # or {'Cancel' => true} or {6 => true}
- * }
- *
- * ev.on_event(event_name) {|*args|
- * {:return => 1, :xxx => yyy}
- * }
- */
-static VALUE
-fev_on_event(int argc, VALUE *argv, VALUE self)
-{
- return ev_on_event(argc, argv, self, Qfalse);
-}
-
-/*
- * call-seq:
- * on_event_with_outargs([event]){...}
- *
- * Defines the callback of event.
- * If you want modify argument in callback,
- * you could use this method instead of WIN32OLE::Event#on_event.
- *
- * ie = WIN32OLE.new('InternetExplorer.Application')
- * ev = WIN32OLE::Event.new(ie)
- * ev.on_event_with_outargs('BeforeNavigate2') {|*args|
- * args.last[6] = true
- * }
- */
-static VALUE
-fev_on_event_with_outargs(int argc, VALUE *argv, VALUE self)
-{
- return ev_on_event(argc, argv, self, Qtrue);
-}
-
-/*
- * call-seq:
- * off_event([event])
- *
- * removes the callback of event.
- *
- * ie = WIN32OLE.new('InternetExplorer.Application')
- * ev = WIN32OLE::Event.new(ie)
- * ev.on_event('BeforeNavigate2') {|*args|
- * args.last[6] = true
- * }
- * # ...
- * ev.off_event('BeforeNavigate2')
- * # ...
- */
-static VALUE
-fev_off_event(int argc, VALUE *argv, VALUE self)
-{
- VALUE event = Qnil;
- VALUE events;
-
- rb_scan_args(argc, argv, "01", &event);
- if(!NIL_P(event)) {
- if(!RB_TYPE_P(event, T_STRING) && !RB_TYPE_P(event, T_SYMBOL)) {
- rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
- }
- if (RB_TYPE_P(event, T_SYMBOL)) {
- event = rb_sym2str(event);
- }
- }
- events = rb_ivar_get(self, id_events);
- if (NIL_P(events)) {
- return Qnil;
- }
- ole_delete_event(events, event);
- return Qnil;
-}
-
-/*
- * call-seq:
- * unadvise -> nil
- *
- * disconnects OLE server. If this method called, then the WIN32OLE::Event object
- * does not receive the OLE server event any more.
- * This method is trial implementation.
- *
- * ie = WIN32OLE.new('InternetExplorer.Application')
- * ev = WIN32OLE::Event.new(ie)
- * ev.on_event() { something }
- * # ...
- * ev.unadvise
- *
- */
-static VALUE
-fev_unadvise(VALUE self)
-{
- struct oleeventdata *poleev;
- TypedData_Get_Struct(self, struct oleeventdata, &oleevent_datatype, poleev);
- if (poleev->pConnectionPoint) {
- ole_msg_loop();
- evs_delete(poleev->event_id);
- poleev->pConnectionPoint->lpVtbl->Unadvise(poleev->pConnectionPoint, poleev->dwCookie);
- OLE_RELEASE(poleev->pConnectionPoint);
- poleev->pConnectionPoint = NULL;
- }
- OLE_FREE(poleev->pDispatch);
- return Qnil;
-}
-
-static VALUE
-evs_push(VALUE ev)
-{
- return rb_ary_push(ary_ole_event, ev);
-}
-
-static VALUE
-evs_delete(long i)
-{
- rb_ary_store(ary_ole_event, i, Qnil);
- return Qnil;
-}
-
-static VALUE
-evs_entry(long i)
-{
- return rb_ary_entry(ary_ole_event, i);
-}
-
-static long
-evs_length(void)
-{
- return RARRAY_LEN(ary_ole_event);
-}
-
-/*
- * call-seq:
- * handler=
- *
- * sets event handler object. If handler object has onXXX
- * method according to XXX event, then onXXX method is called
- * when XXX event occurs.
- *
- * If handler object has method_missing and there is no
- * method according to the event, then method_missing
- * called and 1-st argument is event name.
- *
- * If handler object has onXXX method and there is block
- * defined by <code>on_event('XXX'){}</code>,
- * then block is executed but handler object method is not called
- * when XXX event occurs.
- *
- * class Handler
- * def onStatusTextChange(text)
- * puts "StatusTextChanged"
- * end
- * def onPropertyChange(prop)
- * puts "PropertyChanged"
- * end
- * def method_missing(ev, *arg)
- * puts "other event #{ev}"
- * end
- * end
- *
- * handler = Handler.new
- * ie = WIN32OLE.new('InternetExplorer.Application')
- * ev = WIN32OLE::Event.new(ie)
- * ev.on_event("StatusTextChange") {|*args|
- * puts "this block executed."
- * puts "handler.onStatusTextChange method is not called."
- * }
- * ev.handler = handler
- *
- */
-static VALUE
-fev_set_handler(VALUE self, VALUE val)
-{
- return rb_ivar_set(self, rb_intern("handler"), val);
-}
-
-/*
- * call-seq:
- * handler
- *
- * returns handler object.
- *
- */
-static VALUE
-fev_get_handler(VALUE self)
-{
- return rb_ivar_get(self, rb_intern("handler"));
-}
-
-void
-Init_win32ole_event(void)
-{
-#undef rb_intern
- ary_ole_event = rb_ary_new();
- rb_gc_register_mark_object(ary_ole_event);
- id_events = rb_intern("events");
- cWIN32OLE_EVENT = rb_define_class_under(cWIN32OLE, "Event", rb_cObject);
- /* Alias of WIN32OLE::Event, for the backward compatibility */
- rb_define_const(rb_cObject, "WIN32OLE_EVENT", cWIN32OLE_EVENT);
- rb_define_singleton_method(cWIN32OLE_EVENT, "message_loop", fev_s_msg_loop, 0);
- rb_define_alloc_func(cWIN32OLE_EVENT, fev_s_allocate);
- rb_define_method(cWIN32OLE_EVENT, "initialize", fev_initialize, -1);
- rb_define_method(cWIN32OLE_EVENT, "on_event", fev_on_event, -1);
- rb_define_method(cWIN32OLE_EVENT, "on_event_with_outargs", fev_on_event_with_outargs, -1);
- rb_define_method(cWIN32OLE_EVENT, "off_event", fev_off_event, -1);
- rb_define_method(cWIN32OLE_EVENT, "unadvise", fev_unadvise, 0);
- rb_define_method(cWIN32OLE_EVENT, "handler=", fev_set_handler, 1);
- rb_define_method(cWIN32OLE_EVENT, "handler", fev_get_handler, 0);
-}
diff --git a/ext/win32ole/win32ole_event.h b/ext/win32ole/win32ole_event.h
deleted file mode 100644
index f1a5aa234d..0000000000
--- a/ext/win32ole/win32ole_event.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef WIN32OLE_EVENT_H
-#define WIN32OLE_EVENT_H 1
-
-void Init_win32ole_event(void);
-
-#endif
diff --git a/ext/win32ole/win32ole_method.c b/ext/win32ole/win32ole_method.c
deleted file mode 100644
index a0278729f0..0000000000
--- a/ext/win32ole/win32ole_method.c
+++ /dev/null
@@ -1,954 +0,0 @@
-#include "win32ole.h"
-
-static void olemethod_free(void *ptr);
-static size_t olemethod_size(const void *ptr);
-static VALUE ole_method_sub(VALUE self, ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE name);
-static VALUE olemethod_from_typeinfo(VALUE self, ITypeInfo *pTypeInfo, VALUE name);
-static VALUE ole_methods_sub(ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE methods, int mask);
-static VALUE olemethod_set_member(VALUE self, ITypeInfo *pTypeInfo, ITypeInfo *pOwnerTypeInfo, int index, VALUE name);
-static VALUE folemethod_initialize(VALUE self, VALUE oletype, VALUE method);
-static VALUE folemethod_name(VALUE self);
-static VALUE ole_method_return_type(ITypeInfo *pTypeInfo, UINT method_index);
-static VALUE folemethod_return_type(VALUE self);
-static VALUE ole_method_return_vtype(ITypeInfo *pTypeInfo, UINT method_index);
-static VALUE folemethod_return_vtype(VALUE self);
-static VALUE ole_method_return_type_detail(ITypeInfo *pTypeInfo, UINT method_index);
-static VALUE folemethod_return_type_detail(VALUE self);
-static VALUE ole_method_invkind(ITypeInfo *pTypeInfo, UINT method_index);
-static VALUE ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index);
-static VALUE folemethod_invkind(VALUE self);
-static VALUE folemethod_invoke_kind(VALUE self);
-static VALUE ole_method_visible(ITypeInfo *pTypeInfo, UINT method_index);
-static VALUE folemethod_visible(VALUE self);
-static VALUE ole_method_event(ITypeInfo *pTypeInfo, UINT method_index, VALUE method_name);
-static VALUE folemethod_event(VALUE self);
-static VALUE folemethod_event_interface(VALUE self);
-static HRESULT ole_method_docinfo_from_type(ITypeInfo *pTypeInfo, UINT method_index, BSTR *name, BSTR *helpstr, DWORD *helpcontext, BSTR *helpfile);
-static VALUE ole_method_helpstring(ITypeInfo *pTypeInfo, UINT method_index);
-static VALUE folemethod_helpstring(VALUE self);
-static VALUE ole_method_helpfile(ITypeInfo *pTypeInfo, UINT method_index);
-static VALUE folemethod_helpfile(VALUE self);
-static VALUE ole_method_helpcontext(ITypeInfo *pTypeInfo, UINT method_index);
-static VALUE folemethod_helpcontext(VALUE self);
-static VALUE ole_method_dispid(ITypeInfo *pTypeInfo, UINT method_index);
-static VALUE folemethod_dispid(VALUE self);
-static VALUE ole_method_offset_vtbl(ITypeInfo *pTypeInfo, UINT method_index);
-static VALUE folemethod_offset_vtbl(VALUE self);
-static VALUE ole_method_size_params(ITypeInfo *pTypeInfo, UINT method_index);
-static VALUE folemethod_size_params(VALUE self);
-static VALUE ole_method_size_opt_params(ITypeInfo *pTypeInfo, UINT method_index);
-static VALUE folemethod_size_opt_params(VALUE self);
-static VALUE ole_method_params(ITypeInfo *pTypeInfo, UINT method_index);
-static VALUE folemethod_params(VALUE self);
-static VALUE folemethod_inspect(VALUE self);
-
-static const rb_data_type_t olemethod_datatype = {
- "win32ole_method",
- {NULL, olemethod_free, olemethod_size,},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
-};
-
-static void
-olemethod_free(void *ptr)
-{
- struct olemethoddata *polemethod = ptr;
- OLE_FREE(polemethod->pTypeInfo);
- OLE_FREE(polemethod->pOwnerTypeInfo);
- free(polemethod);
-}
-
-static size_t
-olemethod_size(const void *ptr)
-{
- return ptr ? sizeof(struct olemethoddata) : 0;
-}
-
-struct olemethoddata *
-olemethod_data_get_struct(VALUE obj)
-{
- struct olemethoddata *pmethod;
- TypedData_Get_Struct(obj, struct olemethoddata, &olemethod_datatype, pmethod);
- return pmethod;
-}
-
-static VALUE
-ole_method_sub(VALUE self, ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE name)
-{
- HRESULT hr;
- TYPEATTR *pTypeAttr;
- BSTR bstr;
- FUNCDESC *pFuncDesc;
- WORD i;
- VALUE fname;
- VALUE method = Qnil;
- hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
- if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to GetTypeAttr");
- }
- for(i = 0; i < pTypeAttr->cFuncs && method == Qnil; i++) {
- hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, i, &pFuncDesc);
- if (FAILED(hr))
- continue;
-
- hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid,
- &bstr, NULL, NULL, NULL);
- if (FAILED(hr)) {
- pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
- continue;
- }
- fname = WC2VSTR(bstr);
- if (strcasecmp(StringValuePtr(name), StringValuePtr(fname)) == 0) {
- olemethod_set_member(self, pTypeInfo, pOwnerTypeInfo, i, fname);
- method = self;
- }
- pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
- pFuncDesc=NULL;
- }
- OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
- return method;
-}
-
-VALUE
-ole_methods_from_typeinfo(ITypeInfo *pTypeInfo, int mask)
-{
- HRESULT hr;
- TYPEATTR *pTypeAttr;
- WORD i;
- HREFTYPE href;
- ITypeInfo *pRefTypeInfo;
- VALUE methods = rb_ary_new();
- hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
- if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to GetTypeAttr");
- }
-
- ole_methods_sub(0, pTypeInfo, methods, mask);
- for(i=0; i < pTypeAttr->cImplTypes; i++){
- hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href);
- if(FAILED(hr))
- continue;
- hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo);
- if (FAILED(hr))
- continue;
- ole_methods_sub(pTypeInfo, pRefTypeInfo, methods, mask);
- OLE_RELEASE(pRefTypeInfo);
- }
- OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
- return methods;
-}
-
-static VALUE
-olemethod_from_typeinfo(VALUE self, ITypeInfo *pTypeInfo, VALUE name)
-{
- HRESULT hr;
- TYPEATTR *pTypeAttr;
- WORD i;
- HREFTYPE href;
- ITypeInfo *pRefTypeInfo;
- VALUE method = Qnil;
- hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
- if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to GetTypeAttr");
- }
- method = ole_method_sub(self, 0, pTypeInfo, name);
- if (method != Qnil) {
- return method;
- }
- for(i=0; i < pTypeAttr->cImplTypes && method == Qnil; i++){
- hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href);
- if(FAILED(hr))
- continue;
- hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo);
- if (FAILED(hr))
- continue;
- method = ole_method_sub(self, pTypeInfo, pRefTypeInfo, name);
- OLE_RELEASE(pRefTypeInfo);
- }
- OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
- return method;
-}
-
-static VALUE
-ole_methods_sub(ITypeInfo *pOwnerTypeInfo, ITypeInfo *pTypeInfo, VALUE methods, int mask)
-{
- HRESULT hr;
- TYPEATTR *pTypeAttr;
- BSTR bstr;
- FUNCDESC *pFuncDesc;
- VALUE method;
- WORD i;
- hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
- if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to GetTypeAttr");
- }
- for(i = 0; i < pTypeAttr->cFuncs; i++) {
- hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, i, &pFuncDesc);
- if (FAILED(hr))
- continue;
-
- hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid,
- &bstr, NULL, NULL, NULL);
- if (FAILED(hr)) {
- pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
- continue;
- }
- if(pFuncDesc->invkind & mask) {
- method = folemethod_s_allocate(cWIN32OLE_METHOD);
- olemethod_set_member(method, pTypeInfo, pOwnerTypeInfo,
- i, WC2VSTR(bstr));
- rb_ary_push(methods, method);
- }
- pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
- pFuncDesc=NULL;
- }
- OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
-
- return methods;
-}
-
-VALUE
-create_win32ole_method(ITypeInfo *pTypeInfo, VALUE name)
-{
-
- VALUE method = folemethod_s_allocate(cWIN32OLE_METHOD);
- VALUE obj = olemethod_from_typeinfo(method, pTypeInfo, name);
- return obj;
-}
-
-/*
- * Document-class: WIN32OLE::Method
- *
- * +WIN32OLE::Method+ objects represent OLE method information.
- */
-
-static VALUE
-olemethod_set_member(VALUE self, ITypeInfo *pTypeInfo, ITypeInfo *pOwnerTypeInfo, int index, VALUE name)
-{
- struct olemethoddata *pmethod;
- TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
- pmethod->pTypeInfo = pTypeInfo;
- OLE_ADDREF(pTypeInfo);
- pmethod->pOwnerTypeInfo = pOwnerTypeInfo;
- OLE_ADDREF(pOwnerTypeInfo);
- pmethod->index = index;
- rb_ivar_set(self, rb_intern("name"), name);
- return self;
-}
-
-VALUE
-folemethod_s_allocate(VALUE klass)
-{
- struct olemethoddata *pmethod;
- VALUE obj;
- obj = TypedData_Make_Struct(klass,
- struct olemethoddata,
- &olemethod_datatype, pmethod);
- pmethod->pTypeInfo = NULL;
- pmethod->pOwnerTypeInfo = NULL;
- pmethod->index = 0;
- return obj;
-}
-
-/*
- * call-seq:
- * WIN32OLE::Method.new(ole_type, method) -> WIN32OLE::Method object
- *
- * Returns a new WIN32OLE::Method object which represents the information
- * about OLE method.
- * The first argument <i>ole_type</i> specifies WIN32OLE::Type object.
- * The second argument <i>method</i> specifies OLE method name defined OLE class
- * which represents WIN32OLE::Type object.
- *
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook')
- * method = WIN32OLE::Method.new(tobj, 'SaveAs')
- */
-static VALUE
-folemethod_initialize(VALUE self, VALUE oletype, VALUE method)
-{
- VALUE obj = Qnil;
- ITypeInfo *pTypeInfo;
- if (rb_obj_is_kind_of(oletype, cWIN32OLE_TYPE)) {
- SafeStringValue(method);
- pTypeInfo = itypeinfo(oletype);
- obj = olemethod_from_typeinfo(self, pTypeInfo, method);
- if (obj == Qnil) {
- rb_raise(eWIN32OLERuntimeError, "not found %s",
- StringValuePtr(method));
- }
- }
- else {
- rb_raise(rb_eTypeError, "1st argument should be WIN32OLE::Type object");
- }
- return obj;
-}
-
-/*
- * call-seq:
- * name
- *
- * Returns the name of the method.
- *
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook')
- * method = WIN32OLE::Method.new(tobj, 'SaveAs')
- * puts method.name # => SaveAs
- *
- */
-static VALUE
-folemethod_name(VALUE self)
-{
- return rb_ivar_get(self, rb_intern("name"));
-}
-
-static VALUE
-ole_method_return_type(ITypeInfo *pTypeInfo, UINT method_index)
-{
- FUNCDESC *pFuncDesc;
- HRESULT hr;
- VALUE type;
-
- hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
- if (FAILED(hr))
- ole_raise(hr, eWIN32OLEQueryInterfaceError, "failed to GetFuncDesc");
-
- type = ole_typedesc2val(pTypeInfo, &(pFuncDesc->elemdescFunc.tdesc), Qnil);
- pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
- return type;
-}
-
-/*
- * call-seq:
- * return_type
- *
- * Returns string of return value type of method.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
- * method = WIN32OLE::Method.new(tobj, 'Add')
- * puts method.return_type # => Workbook
- *
- */
-static VALUE
-folemethod_return_type(VALUE self)
-{
- struct olemethoddata *pmethod;
- TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
- return ole_method_return_type(pmethod->pTypeInfo, pmethod->index);
-}
-
-static VALUE
-ole_method_return_vtype(ITypeInfo *pTypeInfo, UINT method_index)
-{
- FUNCDESC *pFuncDesc;
- HRESULT hr;
- VALUE vvt;
-
- hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
- if (FAILED(hr))
- ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc");
-
- vvt = RB_INT2FIX(pFuncDesc->elemdescFunc.tdesc.vt);
- pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
- return vvt;
-}
-
-/*
- * call-seq:
- * return_vtype
- *
- * Returns number of return value type of method.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
- * method = WIN32OLE::Method.new(tobj, 'Add')
- * puts method.return_vtype # => 26
- *
- */
-static VALUE
-folemethod_return_vtype(VALUE self)
-{
- struct olemethoddata *pmethod;
- TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
- return ole_method_return_vtype(pmethod->pTypeInfo, pmethod->index);
-}
-
-static VALUE
-ole_method_return_type_detail(ITypeInfo *pTypeInfo, UINT method_index)
-{
- FUNCDESC *pFuncDesc;
- HRESULT hr;
- VALUE type = rb_ary_new();
-
- hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
- if (FAILED(hr))
- return type;
-
- ole_typedesc2val(pTypeInfo, &(pFuncDesc->elemdescFunc.tdesc), type);
- pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
- return type;
-}
-
-/*
- * call-seq:
- * return_type_detail
- *
- * Returns detail information of return value type of method.
- * The information is array.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
- * method = WIN32OLE::Method.new(tobj, 'Add')
- * p method.return_type_detail # => ["PTR", "USERDEFINED", "Workbook"]
- */
-static VALUE
-folemethod_return_type_detail(VALUE self)
-{
- struct olemethoddata *pmethod;
- TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
- return ole_method_return_type_detail(pmethod->pTypeInfo, pmethod->index);
-}
-
-static VALUE
-ole_method_invkind(ITypeInfo *pTypeInfo, UINT method_index)
-{
- FUNCDESC *pFuncDesc;
- HRESULT hr;
- VALUE invkind;
- hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
- if(FAILED(hr))
- ole_raise(hr, eWIN32OLERuntimeError, "failed to GetFuncDesc");
- invkind = RB_INT2FIX(pFuncDesc->invkind);
- pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
- return invkind;
-}
-
-static VALUE
-ole_method_invoke_kind(ITypeInfo *pTypeInfo, UINT method_index)
-{
- VALUE type = rb_str_new2("UNKNOWN");
- VALUE invkind = ole_method_invkind(pTypeInfo, method_index);
- if((RB_FIX2INT(invkind) & INVOKE_PROPERTYGET) &&
- (RB_FIX2INT(invkind) & INVOKE_PROPERTYPUT) ) {
- type = rb_str_new2("PROPERTY");
- } else if(RB_FIX2INT(invkind) & INVOKE_PROPERTYGET) {
- type = rb_str_new2("PROPERTYGET");
- } else if(RB_FIX2INT(invkind) & INVOKE_PROPERTYPUT) {
- type = rb_str_new2("PROPERTYPUT");
- } else if(RB_FIX2INT(invkind) & INVOKE_PROPERTYPUTREF) {
- type = rb_str_new2("PROPERTYPUTREF");
- } else if(RB_FIX2INT(invkind) & INVOKE_FUNC) {
- type = rb_str_new2("FUNC");
- }
- return type;
-}
-
-/*
- * call-seq:
- * invkind
- *
- * Returns the method invoke kind.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
- * method = WIN32OLE::Method.new(tobj, 'Add')
- * puts method.invkind # => 1
- *
- */
-static VALUE
-folemethod_invkind(VALUE self)
-{
- struct olemethoddata *pmethod;
- TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
- return ole_method_invkind(pmethod->pTypeInfo, pmethod->index);
-}
-
-/*
- * call-seq:
- * invoke_kind
- *
- * Returns the method kind string. The string is "UNKNOWN" or "PROPERTY"
- * or "PROPERTY" or "PROPERTYGET" or "PROPERTYPUT" or "PROPERTYPPUTREF"
- * or "FUNC".
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
- * method = WIN32OLE::Method.new(tobj, 'Add')
- * puts method.invoke_kind # => "FUNC"
- */
-static VALUE
-folemethod_invoke_kind(VALUE self)
-{
- struct olemethoddata *pmethod;
- TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
- return ole_method_invoke_kind(pmethod->pTypeInfo, pmethod->index);
-}
-
-static VALUE
-ole_method_visible(ITypeInfo *pTypeInfo, UINT method_index)
-{
- FUNCDESC *pFuncDesc;
- HRESULT hr;
- VALUE visible;
- hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
- if(FAILED(hr))
- return Qfalse;
- if (pFuncDesc->wFuncFlags & (FUNCFLAG_FRESTRICTED |
- FUNCFLAG_FHIDDEN |
- FUNCFLAG_FNONBROWSABLE)) {
- visible = Qfalse;
- } else {
- visible = Qtrue;
- }
- pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
- return visible;
-}
-
-/*
- * call-seq:
- * visible?
- *
- * Returns true if the method is public.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
- * method = WIN32OLE::Method.new(tobj, 'Add')
- * puts method.visible? # => true
- */
-static VALUE
-folemethod_visible(VALUE self)
-{
- struct olemethoddata *pmethod;
- TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
- return ole_method_visible(pmethod->pTypeInfo, pmethod->index);
-}
-
-static VALUE
-ole_method_event(ITypeInfo *pTypeInfo, UINT method_index, VALUE method_name)
-{
- TYPEATTR *pTypeAttr;
- HRESULT hr;
- WORD i;
- int flags;
- HREFTYPE href;
- ITypeInfo *pRefTypeInfo;
- FUNCDESC *pFuncDesc;
- BSTR bstr;
- VALUE name;
- VALUE event = Qfalse;
-
- hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
- if (FAILED(hr))
- return event;
- if(pTypeAttr->typekind != TKIND_COCLASS) {
- pTypeInfo->lpVtbl->ReleaseTypeAttr(pTypeInfo, pTypeAttr);
- return event;
- }
- for (i = 0; i < pTypeAttr->cImplTypes; i++) {
- hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags);
- if (FAILED(hr))
- continue;
-
- if (flags & IMPLTYPEFLAG_FSOURCE) {
- hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo,
- i, &href);
- if (FAILED(hr))
- continue;
- hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo,
- href, &pRefTypeInfo);
- if (FAILED(hr))
- continue;
- hr = pRefTypeInfo->lpVtbl->GetFuncDesc(pRefTypeInfo, method_index,
- &pFuncDesc);
- if (FAILED(hr)) {
- OLE_RELEASE(pRefTypeInfo);
- continue;
- }
-
- hr = pRefTypeInfo->lpVtbl->GetDocumentation(pRefTypeInfo,
- pFuncDesc->memid,
- &bstr, NULL, NULL, NULL);
- if (FAILED(hr)) {
- pRefTypeInfo->lpVtbl->ReleaseFuncDesc(pRefTypeInfo, pFuncDesc);
- OLE_RELEASE(pRefTypeInfo);
- continue;
- }
-
- name = WC2VSTR(bstr);
- pRefTypeInfo->lpVtbl->ReleaseFuncDesc(pRefTypeInfo, pFuncDesc);
- OLE_RELEASE(pRefTypeInfo);
- if (rb_str_cmp(method_name, name) == 0) {
- event = Qtrue;
- break;
- }
- }
- }
- OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
- return event;
-}
-
-/*
- * call-seq:
- * event?
- *
- * Returns true if the method is event.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook')
- * method = WIN32OLE::Method.new(tobj, 'SheetActivate')
- * puts method.event? # => true
- *
- */
-static VALUE
-folemethod_event(VALUE self)
-{
- struct olemethoddata *pmethod;
- TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
- if (!pmethod->pOwnerTypeInfo)
- return Qfalse;
- return ole_method_event(pmethod->pOwnerTypeInfo,
- pmethod->index,
- rb_ivar_get(self, rb_intern("name")));
-}
-
-/*
- * call-seq:
- * event_interface
- *
- * Returns event interface name if the method is event.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook')
- * method = WIN32OLE::Method.new(tobj, 'SheetActivate')
- * puts method.event_interface # => WorkbookEvents
- */
-static VALUE
-folemethod_event_interface(VALUE self)
-{
- BSTR name;
- struct olemethoddata *pmethod;
- HRESULT hr;
- TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
- if(folemethod_event(self) == Qtrue) {
- hr = ole_docinfo_from_type(pmethod->pTypeInfo, &name, NULL, NULL, NULL);
- if(SUCCEEDED(hr))
- return WC2VSTR(name);
- }
- return Qnil;
-}
-
-static HRESULT
-ole_method_docinfo_from_type(
- ITypeInfo *pTypeInfo,
- UINT method_index,
- BSTR *name,
- BSTR *helpstr,
- DWORD *helpcontext,
- BSTR *helpfile
- )
-{
- FUNCDESC *pFuncDesc;
- HRESULT hr;
- hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
- if (FAILED(hr))
- return hr;
- hr = pTypeInfo->lpVtbl->GetDocumentation(pTypeInfo, pFuncDesc->memid,
- name, helpstr,
- helpcontext, helpfile);
- pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
- return hr;
-}
-
-static VALUE
-ole_method_helpstring(ITypeInfo *pTypeInfo, UINT method_index)
-{
- HRESULT hr;
- BSTR bhelpstring;
- hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, &bhelpstring,
- NULL, NULL);
- if (FAILED(hr))
- return Qnil;
- return WC2VSTR(bhelpstring);
-}
-
-/*
- * call-seq:
- * helpstring
- *
- * Returns help string of OLE method. If the help string is not found,
- * then the method returns nil.
- * tobj = WIN32OLE::Type.new('Microsoft Internet Controls', 'IWebBrowser')
- * method = WIN32OLE::Method.new(tobj, 'Navigate')
- * puts method.helpstring # => Navigates to a URL or file.
- *
- */
-static VALUE
-folemethod_helpstring(VALUE self)
-{
- struct olemethoddata *pmethod;
- TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
- return ole_method_helpstring(pmethod->pTypeInfo, pmethod->index);
-}
-
-static VALUE
-ole_method_helpfile(ITypeInfo *pTypeInfo, UINT method_index)
-{
- HRESULT hr;
- BSTR bhelpfile;
- hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, NULL,
- NULL, &bhelpfile);
- if (FAILED(hr))
- return Qnil;
- return WC2VSTR(bhelpfile);
-}
-
-/*
- * call-seq:
- * helpfile
- *
- * Returns help file. If help file is not found, then
- * the method returns nil.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
- * method = WIN32OLE::Method.new(tobj, 'Add')
- * puts method.helpfile # => C:\...\VBAXL9.CHM
- */
-static VALUE
-folemethod_helpfile(VALUE self)
-{
- struct olemethoddata *pmethod;
- TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
-
- return ole_method_helpfile(pmethod->pTypeInfo, pmethod->index);
-}
-
-static VALUE
-ole_method_helpcontext(ITypeInfo *pTypeInfo, UINT method_index)
-{
- HRESULT hr;
- DWORD helpcontext = 0;
- hr = ole_method_docinfo_from_type(pTypeInfo, method_index, NULL, NULL,
- &helpcontext, NULL);
- if (FAILED(hr))
- return Qnil;
- return RB_INT2FIX(helpcontext);
-}
-
-/*
- * call-seq:
- * helpcontext
- *
- * Returns help context.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
- * method = WIN32OLE::Method.new(tobj, 'Add')
- * puts method.helpcontext # => 65717
- */
-static VALUE
-folemethod_helpcontext(VALUE self)
-{
- struct olemethoddata *pmethod;
- TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
- return ole_method_helpcontext(pmethod->pTypeInfo, pmethod->index);
-}
-
-static VALUE
-ole_method_dispid(ITypeInfo *pTypeInfo, UINT method_index)
-{
- FUNCDESC *pFuncDesc;
- HRESULT hr;
- VALUE dispid = Qnil;
- hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
- if (FAILED(hr))
- return dispid;
- dispid = RB_INT2NUM(pFuncDesc->memid);
- pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
- return dispid;
-}
-
-/*
- * call-seq:
- * dispid
- *
- * Returns dispatch ID.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
- * method = WIN32OLE::Method.new(tobj, 'Add')
- * puts method.dispid # => 181
- */
-static VALUE
-folemethod_dispid(VALUE self)
-{
- struct olemethoddata *pmethod;
- TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
- return ole_method_dispid(pmethod->pTypeInfo, pmethod->index);
-}
-
-static VALUE
-ole_method_offset_vtbl(ITypeInfo *pTypeInfo, UINT method_index)
-{
- FUNCDESC *pFuncDesc;
- HRESULT hr;
- VALUE offset_vtbl = Qnil;
- hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
- if (FAILED(hr))
- return offset_vtbl;
- offset_vtbl = RB_INT2FIX(pFuncDesc->oVft);
- pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
- return offset_vtbl;
-}
-
-/*
- * call-seq:
- * offset_vtbl
- *
- * Returns the offset ov VTBL.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbooks')
- * method = WIN32OLE::Method.new(tobj, 'Add')
- * puts method.offset_vtbl # => 40
- */
-static VALUE
-folemethod_offset_vtbl(VALUE self)
-{
- struct olemethoddata *pmethod;
- TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
- return ole_method_offset_vtbl(pmethod->pTypeInfo, pmethod->index);
-}
-
-static VALUE
-ole_method_size_params(ITypeInfo *pTypeInfo, UINT method_index)
-{
- FUNCDESC *pFuncDesc;
- HRESULT hr;
- VALUE size_params = Qnil;
- hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
- if (FAILED(hr))
- return size_params;
- size_params = RB_INT2FIX(pFuncDesc->cParams);
- pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
- return size_params;
-}
-
-/*
- * call-seq:
- * size_params
- *
- * Returns the size of arguments of the method.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook')
- * method = WIN32OLE::Method.new(tobj, 'SaveAs')
- * puts method.size_params # => 11
- *
- */
-static VALUE
-folemethod_size_params(VALUE self)
-{
- struct olemethoddata *pmethod;
- TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
- return ole_method_size_params(pmethod->pTypeInfo, pmethod->index);
-}
-
-static VALUE
-ole_method_size_opt_params(ITypeInfo *pTypeInfo, UINT method_index)
-{
- FUNCDESC *pFuncDesc;
- HRESULT hr;
- VALUE size_opt_params = Qnil;
- hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
- if (FAILED(hr))
- return size_opt_params;
- size_opt_params = RB_INT2FIX(pFuncDesc->cParamsOpt);
- pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
- return size_opt_params;
-}
-
-/*
- * call-seq:
- * size_opt_params
- *
- * Returns the size of optional parameters.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook')
- * method = WIN32OLE::Method.new(tobj, 'SaveAs')
- * puts method.size_opt_params # => 4
- */
-static VALUE
-folemethod_size_opt_params(VALUE self)
-{
- struct olemethoddata *pmethod;
- TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
- return ole_method_size_opt_params(pmethod->pTypeInfo, pmethod->index);
-}
-
-static VALUE
-ole_method_params(ITypeInfo *pTypeInfo, UINT method_index)
-{
- FUNCDESC *pFuncDesc;
- HRESULT hr;
- BSTR *bstrs;
- UINT len, i;
- VALUE param;
- VALUE params = rb_ary_new();
- hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
- if (FAILED(hr))
- return params;
-
- len = 0;
- bstrs = ALLOCA_N(BSTR, pFuncDesc->cParams + 1);
- hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pFuncDesc->memid,
- bstrs, pFuncDesc->cParams + 1,
- &len);
- if (FAILED(hr)) {
- pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
- return params;
- }
- SysFreeString(bstrs[0]);
- if (pFuncDesc->cParams > 0) {
- for(i = 1; i < len; i++) {
- param = create_win32ole_param(pTypeInfo, method_index, i-1, WC2VSTR(bstrs[i]));
- rb_ary_push(params, param);
- }
- }
- pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
- return params;
-}
-
-/*
- * call-seq:
- * params
- *
- * returns array of WIN32OLE::Param object corresponding with method parameters.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook')
- * method = WIN32OLE::Method.new(tobj, 'SaveAs')
- * p method.params # => [Filename, FileFormat, Password, WriteResPassword,
- * ReadOnlyRecommended, CreateBackup, AccessMode,
- * ConflictResolution, AddToMru, TextCodepage,
- * TextVisualLayout]
- */
-static VALUE
-folemethod_params(VALUE self)
-{
- struct olemethoddata *pmethod;
- TypedData_Get_Struct(self, struct olemethoddata, &olemethod_datatype, pmethod);
- return ole_method_params(pmethod->pTypeInfo, pmethod->index);
-}
-
-/*
- * call-seq:
- * inspect -> String
- *
- * Returns the method name with class name.
- *
- */
-static VALUE
-folemethod_inspect(VALUE self)
-{
- return default_inspect(self, "WIN32OLE::Method");
-}
-
-VALUE cWIN32OLE_METHOD;
-
-void Init_win32ole_method(void)
-{
- cWIN32OLE_METHOD = rb_define_class_under(cWIN32OLE, "Method", rb_cObject);
- /* Alias of WIN32OLE::Method, for the backward compatibility */
- rb_define_const(rb_cObject, "WIN32OLE_METHOD", cWIN32OLE_METHOD);
- rb_define_alloc_func(cWIN32OLE_METHOD, folemethod_s_allocate);
- rb_define_method(cWIN32OLE_METHOD, "initialize", folemethod_initialize, 2);
- rb_define_method(cWIN32OLE_METHOD, "name", folemethod_name, 0);
- rb_define_method(cWIN32OLE_METHOD, "return_type", folemethod_return_type, 0);
- rb_define_method(cWIN32OLE_METHOD, "return_vtype", folemethod_return_vtype, 0);
- rb_define_method(cWIN32OLE_METHOD, "return_type_detail", folemethod_return_type_detail, 0);
- rb_define_method(cWIN32OLE_METHOD, "invoke_kind", folemethod_invoke_kind, 0);
- rb_define_method(cWIN32OLE_METHOD, "invkind", folemethod_invkind, 0);
- rb_define_method(cWIN32OLE_METHOD, "visible?", folemethod_visible, 0);
- rb_define_method(cWIN32OLE_METHOD, "event?", folemethod_event, 0);
- rb_define_method(cWIN32OLE_METHOD, "event_interface", folemethod_event_interface, 0);
- rb_define_method(cWIN32OLE_METHOD, "helpstring", folemethod_helpstring, 0);
- rb_define_method(cWIN32OLE_METHOD, "helpfile", folemethod_helpfile, 0);
- rb_define_method(cWIN32OLE_METHOD, "helpcontext", folemethod_helpcontext, 0);
- rb_define_method(cWIN32OLE_METHOD, "dispid", folemethod_dispid, 0);
- rb_define_method(cWIN32OLE_METHOD, "offset_vtbl", folemethod_offset_vtbl, 0);
- rb_define_method(cWIN32OLE_METHOD, "size_params", folemethod_size_params, 0);
- rb_define_method(cWIN32OLE_METHOD, "size_opt_params", folemethod_size_opt_params, 0);
- rb_define_method(cWIN32OLE_METHOD, "params", folemethod_params, 0);
- rb_define_alias(cWIN32OLE_METHOD, "to_s", "name");
- rb_define_method(cWIN32OLE_METHOD, "inspect", folemethod_inspect, 0);
-}
diff --git a/ext/win32ole/win32ole_method.h b/ext/win32ole/win32ole_method.h
deleted file mode 100644
index ef907d2fac..0000000000
--- a/ext/win32ole/win32ole_method.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#ifndef WIN32OLE_METHOD_H
-#define WIN32OLE_METHOD_H 1
-
-struct olemethoddata {
- ITypeInfo *pOwnerTypeInfo;
- ITypeInfo *pTypeInfo;
- UINT index;
-};
-
-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);
-struct olemethoddata *olemethod_data_get_struct(VALUE obj);
-void Init_win32ole_method(void);
-#endif
diff --git a/ext/win32ole/win32ole_param.c b/ext/win32ole/win32ole_param.c
deleted file mode 100644
index 0c4b185921..0000000000
--- a/ext/win32ole/win32ole_param.c
+++ /dev/null
@@ -1,440 +0,0 @@
-#include "win32ole.h"
-
-VALUE cWIN32OLE_PARAM;
-
-struct oleparamdata {
- ITypeInfo *pTypeInfo;
- UINT method_index;
- UINT index;
-};
-
-static void oleparam_free(void *ptr);
-static size_t oleparam_size(const void *ptr);
-static VALUE foleparam_s_allocate(VALUE klass);
-static VALUE oleparam_ole_param_from_index(VALUE self, ITypeInfo *pTypeInfo, UINT method_index, int param_index);
-static VALUE oleparam_ole_param(VALUE self, VALUE olemethod, int n);
-static VALUE foleparam_initialize(VALUE self, VALUE olemethod, VALUE n);
-static VALUE foleparam_name(VALUE self);
-static VALUE ole_param_ole_type(ITypeInfo *pTypeInfo, UINT method_index, UINT index);
-static VALUE foleparam_ole_type(VALUE self);
-static VALUE ole_param_ole_type_detail(ITypeInfo *pTypeInfo, UINT method_index, UINT index);
-static VALUE foleparam_ole_type_detail(VALUE self);
-static VALUE ole_param_flag_mask(ITypeInfo *pTypeInfo, UINT method_index, UINT index, USHORT mask);
-static VALUE foleparam_input(VALUE self);
-static VALUE foleparam_output(VALUE self);
-static VALUE foleparam_optional(VALUE self);
-static VALUE foleparam_retval(VALUE self);
-static VALUE ole_param_default(ITypeInfo *pTypeInfo, UINT method_index, UINT index);
-static VALUE foleparam_default(VALUE self);
-static VALUE foleparam_inspect(VALUE self);
-
-static const rb_data_type_t oleparam_datatype = {
- "win32ole_param",
- {NULL, oleparam_free, oleparam_size,},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
-};
-
-static void
-oleparam_free(void *ptr)
-{
- struct oleparamdata *pole = ptr;
- OLE_FREE(pole->pTypeInfo);
- free(pole);
-}
-
-static size_t
-oleparam_size(const void *ptr)
-{
- return ptr ? sizeof(struct oleparamdata) : 0;
-}
-
-VALUE
-create_win32ole_param(ITypeInfo *pTypeInfo, UINT method_index, UINT index, VALUE name)
-{
- struct oleparamdata *pparam;
- VALUE obj = foleparam_s_allocate(cWIN32OLE_PARAM);
- TypedData_Get_Struct(obj, struct oleparamdata, &oleparam_datatype, pparam);
-
- pparam->pTypeInfo = pTypeInfo;
- OLE_ADDREF(pTypeInfo);
- pparam->method_index = method_index;
- pparam->index = index;
- rb_ivar_set(obj, rb_intern("name"), name);
- return obj;
-}
-
-/*
- * Document-class: WIN32OLE::Param
- *
- * +WIN32OLE::Param+ objects represent param information of
- * the OLE method.
- */
-static VALUE
-foleparam_s_allocate(VALUE klass)
-{
- struct oleparamdata *pparam;
- VALUE obj;
- obj = TypedData_Make_Struct(klass,
- struct oleparamdata,
- &oleparam_datatype, pparam);
- pparam->pTypeInfo = NULL;
- pparam->method_index = 0;
- pparam->index = 0;
- return obj;
-}
-
-static VALUE
-oleparam_ole_param_from_index(VALUE self, ITypeInfo *pTypeInfo, UINT method_index, int param_index)
-{
- FUNCDESC *pFuncDesc;
- HRESULT hr;
- BSTR *bstrs;
- UINT len;
- struct oleparamdata *pparam;
- hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
- if (FAILED(hr))
- ole_raise(hr, rb_eRuntimeError, "fail to ITypeInfo::GetFuncDesc");
-
- len = 0;
- bstrs = ALLOCA_N(BSTR, pFuncDesc->cParams + 1);
- hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pFuncDesc->memid,
- bstrs, pFuncDesc->cParams + 1,
- &len);
- if (FAILED(hr)) {
- pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
- ole_raise(hr, rb_eRuntimeError, "fail to ITypeInfo::GetNames");
- }
- SysFreeString(bstrs[0]);
- if (param_index < 1 || len <= (UINT)param_index)
- {
- pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
- rb_raise(rb_eIndexError, "index of param must be in 1..%d", len);
- }
-
- TypedData_Get_Struct(self, struct oleparamdata, &oleparam_datatype, pparam);
- pparam->pTypeInfo = pTypeInfo;
- OLE_ADDREF(pTypeInfo);
- pparam->method_index = method_index;
- pparam->index = param_index - 1;
- rb_ivar_set(self, rb_intern("name"), WC2VSTR(bstrs[param_index]));
-
- pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
- return self;
-}
-
-static VALUE
-oleparam_ole_param(VALUE self, VALUE olemethod, int n)
-{
- struct olemethoddata *pmethod = olemethod_data_get_struct(olemethod);
- return oleparam_ole_param_from_index(self, pmethod->pTypeInfo, pmethod->index, n);
-}
-
-/*
- * call-seq:
- * new(method, n) -> WIN32OLE::Param object
- *
- * Returns WIN32OLE::Param object which represents OLE parameter information.
- * 1st argument should be WIN32OLE::Method object.
- * 2nd argument `n' is n-th parameter of the method specified by 1st argument.
- *
- * tobj = WIN32OLE::Type.new('Microsoft Scripting Runtime', 'IFileSystem')
- * method = WIN32OLE::Method.new(tobj, 'CreateTextFile')
- * param = WIN32OLE::Param.new(method, 2) # => #<WIN32OLE::Param:Overwrite=true>
- *
- */
-static VALUE
-foleparam_initialize(VALUE self, VALUE olemethod, VALUE n)
-{
- int idx;
- if (!rb_obj_is_kind_of(olemethod, cWIN32OLE_METHOD)) {
- rb_raise(rb_eTypeError, "1st parameter must be WIN32OLE::Method object");
- }
- idx = RB_FIX2INT(n);
- return oleparam_ole_param(self, olemethod, idx);
-}
-
-/*
- * call-seq:
- * name
- *
- * Returns name.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook')
- * method = WIN32OLE::Method.new(tobj, 'SaveAs')
- * param1 = method.params[0]
- * puts param1.name # => Filename
- */
-static VALUE
-foleparam_name(VALUE self)
-{
- return rb_ivar_get(self, rb_intern("name"));
-}
-
-static VALUE
-ole_param_ole_type(ITypeInfo *pTypeInfo, UINT method_index, UINT index)
-{
- FUNCDESC *pFuncDesc;
- HRESULT hr;
- VALUE type = rb_str_new2("unknown type");
- hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
- if (FAILED(hr))
- return type;
- type = ole_typedesc2val(pTypeInfo,
- &(pFuncDesc->lprgelemdescParam[index].tdesc), Qnil);
- pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
- return type;
-}
-
-/*
- * call-seq:
- * ole_type
- *
- * Returns OLE type of WIN32OLE::Param object(parameter of OLE method).
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook')
- * method = WIN32OLE::Method.new(tobj, 'SaveAs')
- * param1 = method.params[0]
- * puts param1.ole_type # => VARIANT
- */
-static VALUE
-foleparam_ole_type(VALUE self)
-{
- struct oleparamdata *pparam;
- TypedData_Get_Struct(self, struct oleparamdata, &oleparam_datatype, pparam);
- return ole_param_ole_type(pparam->pTypeInfo, pparam->method_index,
- pparam->index);
-}
-
-static VALUE
-ole_param_ole_type_detail(ITypeInfo *pTypeInfo, UINT method_index, UINT index)
-{
- FUNCDESC *pFuncDesc;
- HRESULT hr;
- VALUE typedetail = rb_ary_new();
- hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
- if (FAILED(hr))
- return typedetail;
- ole_typedesc2val(pTypeInfo,
- &(pFuncDesc->lprgelemdescParam[index].tdesc), typedetail);
- pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
- return typedetail;
-}
-
-/*
- * call-seq:
- * ole_type_detail
- *
- * Returns detail information of type of argument.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'IWorksheetFunction')
- * method = WIN32OLE::Method.new(tobj, 'SumIf')
- * param1 = method.params[0]
- * p param1.ole_type_detail # => ["PTR", "USERDEFINED", "Range"]
- */
-static VALUE
-foleparam_ole_type_detail(VALUE self)
-{
- struct oleparamdata *pparam;
- TypedData_Get_Struct(self, struct oleparamdata, &oleparam_datatype, pparam);
- return ole_param_ole_type_detail(pparam->pTypeInfo, pparam->method_index,
- pparam->index);
-}
-
-static VALUE
-ole_param_flag_mask(ITypeInfo *pTypeInfo, UINT method_index, UINT index, USHORT mask)
-{
- FUNCDESC *pFuncDesc;
- HRESULT hr;
- VALUE ret = Qfalse;
- hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
- if(FAILED(hr))
- return ret;
- if (V_UNION1((&(pFuncDesc->lprgelemdescParam[index])), paramdesc).wParamFlags &mask)
- ret = Qtrue;
- pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
- return ret;
-}
-
-/*
- * call-seq:
- * input?
- *
- * Returns true if the parameter is input.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook')
- * method = WIN32OLE::Method.new(tobj, 'SaveAs')
- * param1 = method.params[0]
- * puts param1.input? # => true
- */
-static VALUE
-foleparam_input(VALUE self)
-{
- struct oleparamdata *pparam;
- TypedData_Get_Struct(self, struct oleparamdata, &oleparam_datatype, pparam);
- return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index,
- pparam->index, PARAMFLAG_FIN);
-}
-
-/*
- * call-seq:
- * output?
- *
- * Returns true if argument is output.
- * tobj = WIN32OLE::Type.new('Microsoft Internet Controls', 'DWebBrowserEvents')
- * method = WIN32OLE::Method.new(tobj, 'NewWindow')
- * method.params.each do |param|
- * puts "#{param.name} #{param.output?}"
- * end
- *
- * The result of above script is following:
- * URL false
- * Flags false
- * TargetFrameName false
- * PostData false
- * Headers false
- * Processed true
- */
-static VALUE
-foleparam_output(VALUE self)
-{
- struct oleparamdata *pparam;
- TypedData_Get_Struct(self, struct oleparamdata, &oleparam_datatype, pparam);
- return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index,
- pparam->index, PARAMFLAG_FOUT);
-}
-
-/*
- * call-seq:
- * optional?
- *
- * Returns true if argument is optional.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook')
- * method = WIN32OLE::Method.new(tobj, 'SaveAs')
- * param1 = method.params[0]
- * puts "#{param1.name} #{param1.optional?}" # => Filename true
- */
-static VALUE
-foleparam_optional(VALUE self)
-{
- struct oleparamdata *pparam;
- TypedData_Get_Struct(self, struct oleparamdata, &oleparam_datatype, pparam);
- return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index,
- pparam->index, PARAMFLAG_FOPT);
-}
-
-/*
- * call-seq:
- * retval?
- *
- * Returns true if argument is return value.
- * tobj = WIN32OLE::Type.new('DirectX 7 for Visual Basic Type Library',
- * 'DirectPlayLobbyConnection')
- * method = WIN32OLE::Method.new(tobj, 'GetPlayerShortName')
- * param = method.params[0]
- * puts "#{param.name} #{param.retval?}" # => name true
- */
-static VALUE
-foleparam_retval(VALUE self)
-{
- struct oleparamdata *pparam;
- TypedData_Get_Struct(self, struct oleparamdata, &oleparam_datatype, pparam);
- return ole_param_flag_mask(pparam->pTypeInfo, pparam->method_index,
- pparam->index, PARAMFLAG_FRETVAL);
-}
-
-static VALUE
-ole_param_default(ITypeInfo *pTypeInfo, UINT method_index, UINT index)
-{
- FUNCDESC *pFuncDesc;
- ELEMDESC *pElemDesc;
- PARAMDESCEX * pParamDescEx;
- HRESULT hr;
- USHORT wParamFlags;
- USHORT mask = PARAMFLAG_FOPT|PARAMFLAG_FHASDEFAULT;
- VALUE defval = Qnil;
- hr = pTypeInfo->lpVtbl->GetFuncDesc(pTypeInfo, method_index, &pFuncDesc);
- if (FAILED(hr))
- return defval;
- pElemDesc = &pFuncDesc->lprgelemdescParam[index];
- wParamFlags = V_UNION1(pElemDesc, paramdesc).wParamFlags;
- if ((wParamFlags & mask) == mask) {
- pParamDescEx = V_UNION1(pElemDesc, paramdesc).pparamdescex;
- defval = ole_variant2val(&pParamDescEx->varDefaultValue);
- }
- pTypeInfo->lpVtbl->ReleaseFuncDesc(pTypeInfo, pFuncDesc);
- return defval;
-}
-
-/*
- * call-seq:
- * default
- *
- * Returns default value. If the default value does not exist,
- * this method returns nil.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Workbook')
- * method = WIN32OLE::Method.new(tobj, 'SaveAs')
- * method.params.each do |param|
- * if param.default
- * puts "#{param.name} (= #{param.default})"
- * else
- * puts "#{param}"
- * end
- * end
- *
- * The above script result is following:
- * Filename
- * FileFormat
- * Password
- * WriteResPassword
- * ReadOnlyRecommended
- * CreateBackup
- * AccessMode (= 1)
- * ConflictResolution
- * AddToMru
- * TextCodepage
- * TextVisualLayout
- */
-static VALUE
-foleparam_default(VALUE self)
-{
- struct oleparamdata *pparam;
- TypedData_Get_Struct(self, struct oleparamdata, &oleparam_datatype, pparam);
- return ole_param_default(pparam->pTypeInfo, pparam->method_index,
- pparam->index);
-}
-
-/*
- * call-seq:
- * inspect -> String
- *
- * Returns the parameter name with class name. If the parameter has default value,
- * then returns name=value string with class name.
- *
- */
-static VALUE
-foleparam_inspect(VALUE self)
-{
- VALUE detail = foleparam_name(self);
- VALUE defval = foleparam_default(self);
- if (defval != Qnil) {
- rb_str_cat2(detail, "=");
- rb_str_concat(detail, rb_inspect(defval));
- }
- return make_inspect("WIN32OLE::Param", detail);
-}
-
-void
-Init_win32ole_param(void)
-{
- cWIN32OLE_PARAM = rb_define_class_under(cWIN32OLE, "Param", rb_cObject);
- /* Alias of WIN32OLE::Param, for the backward compatibility */
- rb_define_const(rb_cObject, "WIN32OLE_PARAM", cWIN32OLE_PARAM);
- rb_define_alloc_func(cWIN32OLE_PARAM, foleparam_s_allocate);
- rb_define_method(cWIN32OLE_PARAM, "initialize", foleparam_initialize, 2);
- rb_define_method(cWIN32OLE_PARAM, "name", foleparam_name, 0);
- rb_define_method(cWIN32OLE_PARAM, "ole_type", foleparam_ole_type, 0);
- rb_define_method(cWIN32OLE_PARAM, "ole_type_detail", foleparam_ole_type_detail, 0);
- rb_define_method(cWIN32OLE_PARAM, "input?", foleparam_input, 0);
- rb_define_method(cWIN32OLE_PARAM, "output?", foleparam_output, 0);
- rb_define_method(cWIN32OLE_PARAM, "optional?", foleparam_optional, 0);
- rb_define_method(cWIN32OLE_PARAM, "retval?", foleparam_retval, 0);
- rb_define_method(cWIN32OLE_PARAM, "default", foleparam_default, 0);
- rb_define_alias(cWIN32OLE_PARAM, "to_s", "name");
- rb_define_method(cWIN32OLE_PARAM, "inspect", foleparam_inspect, 0);
-}
diff --git a/ext/win32ole/win32ole_param.h b/ext/win32ole/win32ole_param.h
deleted file mode 100644
index 7e2650cb44..0000000000
--- a/ext/win32ole/win32ole_param.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef WIN32OLE_PARAM_H
-#define WIN32OLE_PARAM_H
-
-VALUE create_win32ole_param(ITypeInfo *pTypeInfo, UINT method_index, UINT index, VALUE name);
-void Init_win32ole_param(void);
-
-#endif
-
diff --git a/ext/win32ole/win32ole_record.c b/ext/win32ole/win32ole_record.c
deleted file mode 100644
index 02f05a3fa7..0000000000
--- a/ext/win32ole/win32ole_record.c
+++ /dev/null
@@ -1,608 +0,0 @@
-#include "win32ole.h"
-
-struct olerecorddata {
- IRecordInfo *pri;
- void *pdata;
-};
-
-static HRESULT recordinfo_from_itypelib(ITypeLib *pTypeLib, VALUE name, IRecordInfo **ppri);
-static int hash2olerec(VALUE key, VALUE val, VALUE rec);
-static void olerecord_free(void *pvar);
-static size_t olerecord_size(const void *ptr);
-static VALUE folerecord_s_allocate(VALUE klass);
-static VALUE folerecord_initialize(VALUE self, VALUE typename, VALUE oleobj);
-static VALUE folerecord_to_h(VALUE self);
-static VALUE folerecord_typename(VALUE self);
-static VALUE olerecord_ivar_get(VALUE self, VALUE name);
-static VALUE olerecord_ivar_set(VALUE self, VALUE name, VALUE val);
-static VALUE folerecord_method_missing(int argc, VALUE *argv, VALUE self);
-static VALUE folerecord_ole_instance_variable_get(VALUE self, VALUE name);
-static VALUE folerecord_ole_instance_variable_set(VALUE self, VALUE name, VALUE val);
-static VALUE folerecord_inspect(VALUE self);
-
-static const rb_data_type_t olerecord_datatype = {
- "win32ole_record",
- {NULL, olerecord_free, olerecord_size,},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
-};
-
-static HRESULT
-recordinfo_from_itypelib(ITypeLib *pTypeLib, VALUE name, IRecordInfo **ppri)
-{
-
- unsigned int count;
- unsigned int i;
- ITypeInfo *pTypeInfo;
- HRESULT hr = OLE_E_LAST;
- BSTR bstr;
-
- count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
- for (i = 0; i < count; i++) {
- hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i,
- &bstr, NULL, NULL, NULL);
- if (FAILED(hr))
- continue;
-
- hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo);
- if (FAILED(hr))
- continue;
-
- if (rb_str_cmp(WC2VSTR(bstr), name) == 0) {
- hr = GetRecordInfoFromTypeInfo(pTypeInfo, ppri);
- OLE_RELEASE(pTypeInfo);
- return hr;
- }
- OLE_RELEASE(pTypeInfo);
- }
- hr = OLE_E_LAST;
- return hr;
-}
-
-static int
-hash2olerec(VALUE key, VALUE val, VALUE rec)
-{
- VARIANT var;
- OLECHAR *pbuf;
- struct olerecorddata *prec;
- IRecordInfo *pri;
- HRESULT hr;
-
- if (val != Qnil) {
- TypedData_Get_Struct(rec, struct olerecorddata, &olerecord_datatype, prec);
- pri = prec->pri;
- VariantInit(&var);
- ole_val2variant(val, &var);
- pbuf = ole_vstr2wc(key);
- hr = pri->lpVtbl->PutField(pri, INVOKE_PROPERTYPUT, prec->pdata, pbuf, &var);
- SysFreeString(pbuf);
- VariantClear(&var);
- if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLERuntimeError, "failed to putfield of `%s`", StringValuePtr(key));
- }
- }
- return ST_CONTINUE;
-}
-
-void
-ole_rec2variant(VALUE rec, VARIANT *var)
-{
- struct olerecorddata *prec;
- ULONG size = 0;
- IRecordInfo *pri;
- HRESULT hr;
- VALUE fields;
- TypedData_Get_Struct(rec, struct olerecorddata, &olerecord_datatype, prec);
- pri = prec->pri;
- if (pri) {
- hr = pri->lpVtbl->GetSize(pri, &size);
- if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLERuntimeError, "failed to get size for allocation of VT_RECORD object");
- }
- if (prec->pdata) {
- free(prec->pdata);
- }
- prec->pdata = ALLOC_N(char, size);
- if (!prec->pdata) {
- rb_raise(rb_eRuntimeError, "failed to memory allocation of %lu bytes", (unsigned long)size);
- }
- hr = pri->lpVtbl->RecordInit(pri, prec->pdata);
- if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLERuntimeError, "failed to initialize VT_RECORD object");
- }
- fields = folerecord_to_h(rec);
- rb_hash_foreach(fields, hash2olerec, rec);
- V_RECORDINFO(var) = pri;
- V_RECORD(var) = prec->pdata;
- V_VT(var) = VT_RECORD;
- } else {
- rb_raise(eWIN32OLERuntimeError, "failed to retrieve IRecordInfo interface");
- }
-}
-
-void
-olerecord_set_ivar(VALUE obj, IRecordInfo *pri, void *prec)
-{
- HRESULT hr;
- BSTR bstr;
- BSTR *bstrs;
- ULONG count = 0;
- ULONG i;
- VALUE fields;
- VALUE val;
- VARIANT var;
- void *pdata = NULL;
- struct olerecorddata *pvar;
-
- TypedData_Get_Struct(obj, struct olerecorddata, &olerecord_datatype, pvar);
- OLE_ADDREF(pri);
- OLE_RELEASE(pvar->pri);
- pvar->pri = pri;
-
- hr = pri->lpVtbl->GetName(pri, &bstr);
- if (SUCCEEDED(hr)) {
- rb_ivar_set(obj, rb_intern("typename"), WC2VSTR(bstr));
- }
-
- hr = pri->lpVtbl->GetFieldNames(pri, &count, NULL);
- if (FAILED(hr) || count == 0)
- return;
- bstrs = ALLOCA_N(BSTR, count);
- hr = pri->lpVtbl->GetFieldNames(pri, &count, bstrs);
- if (FAILED(hr)) {
- return;
- }
-
- fields = rb_hash_new();
- rb_ivar_set(obj, rb_intern("fields"), fields);
- for (i = 0; i < count; i++) {
- pdata = NULL;
- VariantInit(&var);
- val = Qnil;
- if (prec) {
- hr = pri->lpVtbl->GetFieldNoCopy(pri, prec, bstrs[i], &var, &pdata);
- if (SUCCEEDED(hr)) {
- val = ole_variant2val(&var);
- }
- }
- rb_hash_aset(fields, WC2VSTR(bstrs[i]), val);
- }
-}
-
-VALUE
-create_win32ole_record(IRecordInfo *pri, void *prec)
-{
- VALUE obj = folerecord_s_allocate(cWIN32OLE_RECORD);
- olerecord_set_ivar(obj, pri, prec);
- return obj;
-}
-
-/*
- * Document-class: WIN32OLE::Record
- *
- * +WIN32OLE::Record+ objects represents VT_RECORD OLE variant.
- * Win32OLE returns WIN32OLE::Record object if the result value of invoking
- * OLE methods.
- *
- * If COM server in VB.NET ComServer project is the following:
- *
- * Imports System.Runtime.InteropServices
- * Public Class ComClass
- * Public Structure Book
- * <MarshalAs(UnmanagedType.BStr)> _
- * Public title As String
- * Public cost As Integer
- * End Structure
- * Public Function getBook() As Book
- * Dim book As New Book
- * book.title = "The Ruby Book"
- * book.cost = 20
- * Return book
- * End Function
- * End Class
- *
- * then, you can retrieve getBook return value from the following
- * Ruby script:
- *
- * require 'win32ole'
- * obj = WIN32OLE.new('ComServer.ComClass')
- * book = obj.getBook
- * book.class # => WIN32OLE::Record
- * book.title # => "The Ruby Book"
- * book.cost # => 20
- *
- */
-
-static void
-olerecord_free(void *ptr) {
- struct olerecorddata *pvar = ptr;
- OLE_FREE(pvar->pri);
- if (pvar->pdata) {
- free(pvar->pdata);
- }
- free(pvar);
-}
-
-static size_t
-olerecord_size(const void *ptr)
-{
- const struct olerecorddata *pvar = ptr;
- size_t s = 0;
- ULONG size = 0;
- HRESULT hr;
- if (ptr) {
- s += sizeof(struct olerecorddata);
- if (pvar->pri) {
- hr = pvar->pri->lpVtbl->GetSize(pvar->pri, &size);
- if (SUCCEEDED(hr)) {
- s += size;
- }
- }
- }
- return s;
-}
-
-static VALUE
-folerecord_s_allocate(VALUE klass) {
- VALUE obj = Qnil;
- struct olerecorddata *pvar;
- obj = TypedData_Make_Struct(klass, struct olerecorddata, &olerecord_datatype, pvar);
- pvar->pri = NULL;
- pvar->pdata = NULL;
- return obj;
-}
-
-/*
- * call-seq:
- * new(typename, obj) -> WIN32OLE::Record object
- *
- * Returns WIN32OLE::Record object. The first argument is struct name (String
- * or Symbol).
- * The second parameter obj should be WIN32OLE object or WIN32OLE::TypeLib object.
- * If COM server in VB.NET ComServer project is the following:
- *
- * Imports System.Runtime.InteropServices
- * Public Class ComClass
- * Public Structure Book
- * <MarshalAs(UnmanagedType.BStr)> _
- * Public title As String
- * Public cost As Integer
- * End Structure
- * End Class
- *
- * then, you can create WIN32OLE::Record object is as following:
- *
- * require 'win32ole'
- * obj = WIN32OLE.new('ComServer.ComClass')
- * book1 = WIN32OLE::Record.new('Book', obj) # => WIN32OLE::Record object
- * tlib = obj.ole_typelib
- * book2 = WIN32OLE::Record.new('Book', tlib) # => WIN32OLE::Record object
- *
- */
-static VALUE
-folerecord_initialize(VALUE self, VALUE typename, VALUE oleobj) {
- HRESULT hr;
- ITypeLib *pTypeLib = NULL;
- IRecordInfo *pri = NULL;
-
- if (!RB_TYPE_P(typename, T_STRING) && !RB_TYPE_P(typename, T_SYMBOL)) {
- rb_raise(rb_eArgError, "1st argument should be String or Symbol");
- }
- if (RB_TYPE_P(typename, T_SYMBOL)) {
- typename = rb_sym2str(typename);
- }
-
- hr = S_OK;
- if(rb_obj_is_kind_of(oleobj, cWIN32OLE)) {
- hr = typelib_from_val(oleobj, &pTypeLib);
- } else if (rb_obj_is_kind_of(oleobj, cWIN32OLE_TYPELIB)) {
- pTypeLib = itypelib(oleobj);
- OLE_ADDREF(pTypeLib);
- if (pTypeLib) {
- hr = S_OK;
- } else {
- hr = E_FAIL;
- }
- } else {
- rb_raise(rb_eArgError, "2nd argument should be WIN32OLE object or WIN32OLE::TypeLib object");
- }
-
- if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLERuntimeError, "fail to query ITypeLib interface");
- }
-
- hr = recordinfo_from_itypelib(pTypeLib, typename, &pri);
- OLE_RELEASE(pTypeLib);
- if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLERuntimeError, "fail to query IRecordInfo interface for `%s'", StringValuePtr(typename));
- }
-
- olerecord_set_ivar(self, pri, NULL);
-
- return self;
-}
-
-/*
- * call-seq:
- * WIN32OLE::Record#to_h #=> Ruby Hash object.
- *
- * Returns Ruby Hash object which represents VT_RECORD variable.
- * The keys of Hash object are member names of VT_RECORD OLE variable and
- * the values of Hash object are values of VT_RECORD OLE variable.
- *
- * If COM server in VB.NET ComServer project is the following:
- *
- * Imports System.Runtime.InteropServices
- * Public Class ComClass
- * Public Structure Book
- * <MarshalAs(UnmanagedType.BStr)> _
- * Public title As String
- * Public cost As Integer
- * End Structure
- * Public Function getBook() As Book
- * Dim book As New Book
- * book.title = "The Ruby Book"
- * book.cost = 20
- * Return book
- * End Function
- * End Class
- *
- * then, the result of WIN32OLE::Record#to_h is the following:
- *
- * require 'win32ole'
- * obj = WIN32OLE.new('ComServer.ComClass')
- * book = obj.getBook
- * book.to_h # => {"title"=>"The Ruby Book", "cost"=>20}
- *
- */
-static VALUE
-folerecord_to_h(VALUE self)
-{
- return rb_ivar_get(self, rb_intern("fields"));
-}
-
-/*
- * call-seq:
- * typename #=> String object
- *
- * Returns the type name of VT_RECORD OLE variable.
- *
- * If COM server in VB.NET ComServer project is the following:
- *
- * Imports System.Runtime.InteropServices
- * Public Class ComClass
- * Public Structure Book
- * <MarshalAs(UnmanagedType.BStr)> _
- * Public title As String
- * Public cost As Integer
- * End Structure
- * Public Function getBook() As Book
- * Dim book As New Book
- * book.title = "The Ruby Book"
- * book.cost = 20
- * Return book
- * End Function
- * End Class
- *
- * then, the result of WIN32OLE::Record#typename is the following:
- *
- * require 'win32ole'
- * obj = WIN32OLE.new('ComServer.ComClass')
- * book = obj.getBook
- * book.typename # => "Book"
- *
- */
-static VALUE
-folerecord_typename(VALUE self)
-{
- return rb_ivar_get(self, rb_intern("typename"));
-}
-
-static VALUE
-olerecord_ivar_get(VALUE self, VALUE name)
-{
- VALUE fields;
- fields = rb_ivar_get(self, rb_intern("fields"));
- return rb_hash_fetch(fields, name);
-}
-
-static VALUE
-olerecord_ivar_set(VALUE self, VALUE name, VALUE val)
-{
- long len;
- char *p;
- VALUE fields;
- len = RSTRING_LEN(name);
- p = RSTRING_PTR(name);
- if (p[len-1] == '=') {
- name = rb_str_subseq(name, 0, len-1);
- }
- fields = rb_ivar_get(self, rb_intern("fields"));
- rb_hash_fetch(fields, name);
- return rb_hash_aset(fields, name, val);
-}
-
-/*
- * call-seq:
- * method_missing(name)
- *
- * Returns value specified by the member name of VT_RECORD OLE variable.
- * Or sets value specified by the member name of VT_RECORD OLE variable.
- * If the member name is not correct, KeyError exception is raised.
- *
- * If COM server in VB.NET ComServer project is the following:
- *
- * Imports System.Runtime.InteropServices
- * Public Class ComClass
- * Public Structure Book
- * <MarshalAs(UnmanagedType.BStr)> _
- * Public title As String
- * Public cost As Integer
- * End Structure
- * End Class
- *
- * Then getting/setting value from Ruby is as the following:
- *
- * obj = WIN32OLE.new('ComServer.ComClass')
- * book = WIN32OLE::Record.new('Book', obj)
- * book.title # => nil ( book.method_missing(:title) is invoked. )
- * book.title = "Ruby" # ( book.method_missing(:title=, "Ruby") is invoked. )
- */
-static VALUE
-folerecord_method_missing(int argc, VALUE *argv, VALUE self)
-{
- VALUE name;
- rb_check_arity(argc, 1, 2);
- name = rb_sym2str(argv[0]);
-
-#if SIZEOF_SIZE_T > SIZEOF_LONG
- {
- size_t n = strlen(StringValueCStr(name));
- if (n >= LONG_MAX) {
- rb_raise(rb_eRuntimeError, "too long member name");
- }
- }
-#endif
-
- if (argc == 1) {
- return olerecord_ivar_get(self, name);
- } else if (argc == 2) {
- return olerecord_ivar_set(self, name, argv[1]);
- }
- return Qnil;
-}
-
-/*
- * call-seq:
- * ole_instance_variable_get(name)
- *
- * Returns value specified by the member name of VT_RECORD OLE object.
- * If the member name is not correct, KeyError exception is raised.
- * If you can't access member variable of VT_RECORD OLE object directly,
- * use this method.
- *
- * If COM server in VB.NET ComServer project is the following:
- *
- * Imports System.Runtime.InteropServices
- * Public Class ComClass
- * Public Structure ComObject
- * Public object_id As Ineger
- * End Structure
- * End Class
- *
- * and Ruby Object class has title attribute:
- *
- * then accessing object_id of ComObject from Ruby is as the following:
- *
- * srver = WIN32OLE.new('ComServer.ComClass')
- * obj = WIN32OLE::Record.new('ComObject', server)
- * # obj.object_id returns Ruby Object#object_id
- * obj.ole_instance_variable_get(:object_id) # => nil
- *
- */
-static VALUE
-folerecord_ole_instance_variable_get(VALUE self, VALUE name)
-{
- VALUE sname;
- if(!RB_TYPE_P(name, T_STRING) && !RB_TYPE_P(name, T_SYMBOL)) {
- rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
- }
- sname = name;
- if (RB_TYPE_P(name, T_SYMBOL)) {
- sname = rb_sym2str(name);
- }
- return olerecord_ivar_get(self, sname);
-}
-
-/*
- * call-seq:
- * ole_instance_variable_set(name, val)
- *
- * Sets value specified by the member name of VT_RECORD OLE object.
- * If the member name is not correct, KeyError exception is raised.
- * If you can't set value of member of VT_RECORD OLE object directly,
- * use this method.
- *
- * If COM server in VB.NET ComServer project is the following:
- *
- * Imports System.Runtime.InteropServices
- * Public Class ComClass
- * <MarshalAs(UnmanagedType.BStr)> _
- * Public title As String
- * Public cost As Integer
- * End Class
- *
- * then setting value of the `title' member is as following:
- *
- * srver = WIN32OLE.new('ComServer.ComClass')
- * obj = WIN32OLE::Record.new('Book', server)
- * obj.ole_instance_variable_set(:title, "The Ruby Book")
- *
- */
-static VALUE
-folerecord_ole_instance_variable_set(VALUE self, VALUE name, VALUE val)
-{
- VALUE sname;
- if(!RB_TYPE_P(name, T_STRING) && !RB_TYPE_P(name, T_SYMBOL)) {
- rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
- }
- sname = name;
- if (RB_TYPE_P(name, T_SYMBOL)) {
- sname = rb_sym2str(name);
- }
- return olerecord_ivar_set(self, sname, val);
-}
-
-/*
- * call-seq:
- * inspect -> String
- *
- * Returns the OLE struct name and member name and the value of member
- *
- * If COM server in VB.NET ComServer project is the following:
- *
- * Imports System.Runtime.InteropServices
- * Public Class ComClass
- * <MarshalAs(UnmanagedType.BStr)> _
- * Public title As String
- * Public cost As Integer
- * End Class
- *
- * then
- *
- * srver = WIN32OLE.new('ComServer.ComClass')
- * obj = WIN32OLE::Record.new('Book', server)
- * obj.inspect # => <WIN32OLE::Record(ComClass) {"title" => nil, "cost" => nil}>
- *
- */
-static VALUE
-folerecord_inspect(VALUE self)
-{
- VALUE tname;
- VALUE field;
- tname = folerecord_typename(self);
- if (tname == Qnil) {
- tname = rb_inspect(tname);
- }
- field = rb_inspect(folerecord_to_h(self));
- return rb_sprintf("#<WIN32OLE::Record(%"PRIsVALUE") %"PRIsVALUE">",
- tname,
- field);
-}
-
-VALUE cWIN32OLE_RECORD;
-
-void
-Init_win32ole_record(void)
-{
- cWIN32OLE_RECORD = rb_define_class_under(cWIN32OLE, "Record", rb_cObject);
- /* Alias of WIN32OLE::Record, for the backward compatibility */
- rb_define_const(rb_cObject, "WIN32OLE_RECORD", cWIN32OLE_RECORD);
- rb_define_alloc_func(cWIN32OLE_RECORD, folerecord_s_allocate);
- rb_define_method(cWIN32OLE_RECORD, "initialize", folerecord_initialize, 2);
- rb_define_method(cWIN32OLE_RECORD, "to_h", folerecord_to_h, 0);
- rb_define_method(cWIN32OLE_RECORD, "typename", folerecord_typename, 0);
- rb_define_method(cWIN32OLE_RECORD, "method_missing", folerecord_method_missing, -1);
- rb_define_method(cWIN32OLE_RECORD, "ole_instance_variable_get", folerecord_ole_instance_variable_get, 1);
- rb_define_method(cWIN32OLE_RECORD, "ole_instance_variable_set", folerecord_ole_instance_variable_set, 2);
- rb_define_method(cWIN32OLE_RECORD, "inspect", folerecord_inspect, 0);
-}
diff --git a/ext/win32ole/win32ole_record.h b/ext/win32ole/win32ole_record.h
deleted file mode 100644
index ab1df0ee7f..0000000000
--- a/ext/win32ole/win32ole_record.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef WIN32OLE_RECORD_H
-#define WIN32OLE_RECORD_H 1
-
-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);
-void Init_win32ole_record(void);
-
-#endif
diff --git a/ext/win32ole/win32ole_type.c b/ext/win32ole/win32ole_type.c
deleted file mode 100644
index 45b16d6722..0000000000
--- a/ext/win32ole/win32ole_type.c
+++ /dev/null
@@ -1,922 +0,0 @@
-#include "win32ole.h"
-
-struct oletypedata {
- ITypeInfo *pTypeInfo;
-};
-
-static void oletype_free(void *ptr);
-static size_t oletype_size(const void *ptr);
-static VALUE foletype_s_ole_classes(VALUE self, VALUE typelib);
-static VALUE foletype_s_typelibs(VALUE self);
-static VALUE foletype_s_progids(VALUE self);
-static VALUE oletype_set_member(VALUE self, ITypeInfo *pTypeInfo, VALUE name);
-static VALUE foletype_s_allocate(VALUE klass);
-static VALUE oleclass_from_typelib(VALUE self, ITypeLib *pTypeLib, VALUE oleclass);
-static VALUE foletype_initialize(VALUE self, VALUE typelib, VALUE oleclass);
-static VALUE foletype_name(VALUE self);
-static VALUE ole_ole_type(ITypeInfo *pTypeInfo);
-static VALUE foletype_ole_type(VALUE self);
-static VALUE ole_type_guid(ITypeInfo *pTypeInfo);
-static VALUE foletype_guid(VALUE self);
-static VALUE ole_type_progid(ITypeInfo *pTypeInfo);
-static VALUE foletype_progid(VALUE self);
-static VALUE ole_type_visible(ITypeInfo *pTypeInfo);
-static VALUE foletype_visible(VALUE self);
-static VALUE ole_type_major_version(ITypeInfo *pTypeInfo);
-static VALUE foletype_major_version(VALUE self);
-static VALUE ole_type_minor_version(ITypeInfo *pTypeInfo);
-static VALUE foletype_minor_version(VALUE self);
-static VALUE ole_type_typekind(ITypeInfo *pTypeInfo);
-static VALUE foletype_typekind(VALUE self);
-static VALUE ole_type_helpstring(ITypeInfo *pTypeInfo);
-static VALUE foletype_helpstring(VALUE self);
-static VALUE ole_type_src_type(ITypeInfo *pTypeInfo);
-static VALUE foletype_src_type(VALUE self);
-static VALUE ole_type_helpfile(ITypeInfo *pTypeInfo);
-static VALUE foletype_helpfile(VALUE self);
-static VALUE ole_type_helpcontext(ITypeInfo *pTypeInfo);
-static VALUE foletype_helpcontext(VALUE self);
-static VALUE ole_variables(ITypeInfo *pTypeInfo);
-static VALUE foletype_variables(VALUE self);
-static VALUE foletype_methods(VALUE self);
-static VALUE foletype_ole_typelib(VALUE self);
-static VALUE ole_type_impl_ole_types(ITypeInfo *pTypeInfo, int implflags);
-static VALUE foletype_impl_ole_types(VALUE self);
-static VALUE foletype_source_ole_types(VALUE self);
-static VALUE foletype_default_event_sources(VALUE self);
-static VALUE foletype_default_ole_types(VALUE self);
-static VALUE foletype_inspect(VALUE self);
-
-static const rb_data_type_t oletype_datatype = {
- "win32ole_type",
- {NULL, oletype_free, oletype_size,},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
-};
-
-/*
- * Document-class: WIN32OLE::Type
- *
- * +WIN32OLE::Type+ objects represent OLE type library information.
- */
-
-static void
-oletype_free(void *ptr)
-{
- struct oletypedata *poletype = ptr;
- OLE_FREE(poletype->pTypeInfo);
- free(poletype);
-}
-
-static size_t
-oletype_size(const void *ptr)
-{
- return ptr ? sizeof(struct oletypedata) : 0;
-}
-
-ITypeInfo *itypeinfo(VALUE self)
-{
- struct oletypedata *ptype;
- TypedData_Get_Struct(self, struct oletypedata, &oletype_datatype, ptype);
- return ptype->pTypeInfo;
-}
-
-VALUE
-ole_type_from_itypeinfo(ITypeInfo *pTypeInfo)
-{
- ITypeLib *pTypeLib;
- VALUE type = Qnil;
- HRESULT hr;
- unsigned int index;
- BSTR bstr;
-
- hr = pTypeInfo->lpVtbl->GetContainingTypeLib( pTypeInfo, &pTypeLib, &index );
- if(FAILED(hr)) {
- return Qnil;
- }
- hr = pTypeLib->lpVtbl->GetDocumentation( pTypeLib, index,
- &bstr, NULL, NULL, NULL);
- OLE_RELEASE(pTypeLib);
- if (FAILED(hr)) {
- return Qnil;
- }
- type = create_win32ole_type(pTypeInfo, WC2VSTR(bstr));
- return type;
-}
-
-
-/*
- * call-seq:
- * ole_classes(typelib)
- *
- * Returns array of WIN32OLE::Type objects defined by the <i>typelib</i> type library.
- *
- * This method will be OBSOLETE.
- * Use <code>WIN32OLE::TypeLib.new(typelib).ole_classes</code> instead.
- */
-static VALUE
-foletype_s_ole_classes(VALUE self, VALUE typelib)
-{
- VALUE obj;
-
- /*
- rb_warn("%s is obsolete; use %s instead.",
- "WIN32OLE::Type.ole_classes",
- "WIN32OLE::TypeLib.new(typelib).ole_types");
- */
- obj = rb_funcall(cWIN32OLE_TYPELIB, rb_intern("new"), 1, typelib);
- return rb_funcall(obj, rb_intern("ole_types"), 0);
-}
-
-/*
- * call-seq:
- * typelibs
- *
- * Returns array of type libraries.
- *
- * This method will be OBSOLETE.
- * Use <code>WIN32OLE::TypeLib.typelibs.collect{|t| t.name}</code> instead.
- *
- */
-static VALUE
-foletype_s_typelibs(VALUE self)
-{
- /*
- rb_warn("%s is obsolete. use %s instead.",
- "WIN32OLE::Type.typelibs",
- "WIN32OLE::TypeLib.typelibs.collect{t|t.name}");
- */
- return rb_eval_string("WIN32OLE::TypeLib.typelibs.collect{|t|t.name}");
-}
-
-/*
- * call-seq:
- * progids
- *
- * Returns array of ProgID.
- */
-static VALUE
-foletype_s_progids(VALUE self)
-{
- HKEY hclsids, hclsid;
- DWORD i;
- LONG err;
- VALUE clsid;
- VALUE v = rb_str_new2("");
- VALUE progids = rb_ary_new();
-
- err = reg_open_key(HKEY_CLASSES_ROOT, "CLSID", &hclsids);
- if(err != ERROR_SUCCESS) {
- return progids;
- }
- for(i = 0; ; i++) {
- clsid = reg_enum_key(hclsids, i);
- if (clsid == Qnil)
- break;
- err = reg_open_vkey(hclsids, clsid, &hclsid);
- if (err != ERROR_SUCCESS)
- continue;
- if ((v = reg_get_val2(hclsid, "ProgID")) != Qnil)
- rb_ary_push(progids, v);
- if ((v = reg_get_val2(hclsid, "VersionIndependentProgID")) != Qnil)
- rb_ary_push(progids, v);
- RegCloseKey(hclsid);
- }
- RegCloseKey(hclsids);
- return progids;
-}
-
-static VALUE
-oletype_set_member(VALUE self, ITypeInfo *pTypeInfo, VALUE name)
-{
- struct oletypedata *ptype;
- TypedData_Get_Struct(self, struct oletypedata, &oletype_datatype, ptype);
- rb_ivar_set(self, rb_intern("name"), name);
- ptype->pTypeInfo = pTypeInfo;
- OLE_ADDREF(pTypeInfo);
- return self;
-}
-
-static VALUE
-foletype_s_allocate(VALUE klass)
-{
- struct oletypedata *poletype;
- VALUE obj;
- ole_initialize();
- obj = TypedData_Make_Struct(klass,struct oletypedata, &oletype_datatype, poletype);
- poletype->pTypeInfo = NULL;
- return obj;
-}
-
-VALUE
-create_win32ole_type(ITypeInfo *pTypeInfo, VALUE name)
-{
- VALUE obj = foletype_s_allocate(cWIN32OLE_TYPE);
- oletype_set_member(obj, pTypeInfo, name);
- return obj;
-}
-
-static VALUE
-oleclass_from_typelib(VALUE self, ITypeLib *pTypeLib, VALUE oleclass)
-{
- long count;
- int i;
- HRESULT hr;
- BSTR bstr;
- VALUE typelib;
- ITypeInfo *pTypeInfo;
-
- VALUE found = Qfalse;
-
- count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
- for (i = 0; i < count && found == Qfalse; i++) {
- hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo);
- if (FAILED(hr))
- continue;
- hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i,
- &bstr, NULL, NULL, NULL);
- if (FAILED(hr))
- continue;
- typelib = WC2VSTR(bstr);
- if (rb_str_cmp(oleclass, typelib) == 0) {
- oletype_set_member(self, pTypeInfo, typelib);
- found = Qtrue;
- }
- OLE_RELEASE(pTypeInfo);
- }
- return found;
-}
-
-/*
- * call-seq:
- * new(typelib, ole_class) -> WIN32OLE::Type object
- *
- * Returns a new WIN32OLE::Type object.
- * The first argument <i>typelib</i> specifies OLE type library name.
- * The second argument specifies OLE class name.
- *
- * WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Application')
- * # => WIN32OLE::Type object of Application class of Excel.
- */
-static VALUE
-foletype_initialize(VALUE self, VALUE typelib, VALUE oleclass)
-{
- VALUE file;
- OLECHAR * pbuf;
- ITypeLib *pTypeLib;
- HRESULT hr;
-
- SafeStringValue(oleclass);
- SafeStringValue(typelib);
- file = typelib_file(typelib);
- if (file == Qnil) {
- file = typelib;
- }
- pbuf = ole_vstr2wc(file);
- hr = LoadTypeLibEx(pbuf, REGKIND_NONE, &pTypeLib);
- if (FAILED(hr))
- ole_raise(hr, eWIN32OLERuntimeError, "failed to LoadTypeLibEx");
- SysFreeString(pbuf);
- if (oleclass_from_typelib(self, pTypeLib, oleclass) == Qfalse) {
- OLE_RELEASE(pTypeLib);
- rb_raise(eWIN32OLERuntimeError, "not found `%s` in `%s`",
- StringValuePtr(oleclass), StringValuePtr(typelib));
- }
- OLE_RELEASE(pTypeLib);
- return self;
-}
-
-/*
- * call-seq:
- * name #=> OLE type name
- *
- * Returns OLE type name.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Application')
- * puts tobj.name # => Application
- */
-static VALUE
-foletype_name(VALUE self)
-{
- return rb_ivar_get(self, rb_intern("name"));
-}
-
-static VALUE
-ole_ole_type(ITypeInfo *pTypeInfo)
-{
- HRESULT hr;
- TYPEATTR *pTypeAttr;
- VALUE type = Qnil;
- hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
- if(FAILED(hr)){
- return type;
- }
- switch(pTypeAttr->typekind) {
- case TKIND_ENUM:
- type = rb_str_new2("Enum");
- break;
- case TKIND_RECORD:
- type = rb_str_new2("Record");
- break;
- case TKIND_MODULE:
- type = rb_str_new2("Module");
- break;
- case TKIND_INTERFACE:
- type = rb_str_new2("Interface");
- break;
- case TKIND_DISPATCH:
- type = rb_str_new2("Dispatch");
- break;
- case TKIND_COCLASS:
- type = rb_str_new2("Class");
- break;
- case TKIND_ALIAS:
- type = rb_str_new2("Alias");
- break;
- case TKIND_UNION:
- type = rb_str_new2("Union");
- break;
- case TKIND_MAX:
- type = rb_str_new2("Max");
- break;
- default:
- type = Qnil;
- break;
- }
- OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
- return type;
-}
-
-/*
- * call-seq:
- * ole_type #=> OLE type string.
- *
- * returns type of OLE class.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Application')
- * puts tobj.ole_type # => Class
- */
-static VALUE
-foletype_ole_type(VALUE self)
-{
- ITypeInfo *pTypeInfo = itypeinfo(self);
- return ole_ole_type(pTypeInfo);
-}
-
-static VALUE
-ole_type_guid(ITypeInfo *pTypeInfo)
-{
- HRESULT hr;
- TYPEATTR *pTypeAttr;
- int len;
- OLECHAR bstr[80];
- VALUE guid = Qnil;
- hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
- if (FAILED(hr))
- return guid;
- len = StringFromGUID2(&pTypeAttr->guid, bstr, sizeof(bstr)/sizeof(OLECHAR));
- if (len > 3) {
- guid = ole_wc2vstr(bstr, FALSE);
- }
- OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
- return guid;
-}
-
-/*
- * call-seq:
- * guid #=> GUID
- *
- * Returns GUID.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Application')
- * puts tobj.guid # => {00024500-0000-0000-C000-000000000046}
- */
-static VALUE
-foletype_guid(VALUE self)
-{
- ITypeInfo *pTypeInfo = itypeinfo(self);
- return ole_type_guid(pTypeInfo);
-}
-
-static VALUE
-ole_type_progid(ITypeInfo *pTypeInfo)
-{
- HRESULT hr;
- TYPEATTR *pTypeAttr;
- OLECHAR *pbuf;
- VALUE progid = Qnil;
- hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
- if (FAILED(hr))
- return progid;
- hr = ProgIDFromCLSID(&pTypeAttr->guid, &pbuf);
- if (SUCCEEDED(hr)) {
- progid = ole_wc2vstr(pbuf, FALSE);
- CoTaskMemFree(pbuf);
- }
- OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
- return progid;
-}
-
-/*
- * call-seq:
- * progid #=> ProgID
- *
- * Returns ProgID if it exists. If not found, then returns nil.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Application')
- * puts tobj.progid # => Excel.Application.9
- */
-static VALUE
-foletype_progid(VALUE self)
-{
- ITypeInfo *pTypeInfo = itypeinfo(self);
- return ole_type_progid(pTypeInfo);
-}
-
-
-static VALUE
-ole_type_visible(ITypeInfo *pTypeInfo)
-{
- HRESULT hr;
- TYPEATTR *pTypeAttr;
- VALUE visible;
- hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
- if (FAILED(hr))
- return Qtrue;
- if (pTypeAttr->wTypeFlags & (TYPEFLAG_FHIDDEN | TYPEFLAG_FRESTRICTED)) {
- visible = Qfalse;
- } else {
- visible = Qtrue;
- }
- OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
- return visible;
-}
-
-/*
- * call-seq:
- * visible? #=> true or false
- *
- * Returns true if the OLE class is public.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Application')
- * puts tobj.visible # => true
- */
-static VALUE
-foletype_visible(VALUE self)
-{
- ITypeInfo *pTypeInfo = itypeinfo(self);
- return ole_type_visible(pTypeInfo);
-}
-
-static VALUE
-ole_type_major_version(ITypeInfo *pTypeInfo)
-{
- VALUE ver;
- TYPEATTR *pTypeAttr;
- HRESULT hr;
- hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
- if (FAILED(hr))
- ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
- ver = RB_INT2FIX(pTypeAttr->wMajorVerNum);
- OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
- return ver;
-}
-
-/*
- * call-seq:
- * major_version
- *
- * Returns major version.
- * tobj = WIN32OLE::Type.new('Microsoft Word 10.0 Object Library', 'Documents')
- * puts tobj.major_version # => 8
- */
-static VALUE
-foletype_major_version(VALUE self)
-{
- ITypeInfo *pTypeInfo = itypeinfo(self);
- return ole_type_major_version(pTypeInfo);
-}
-
-static VALUE
-ole_type_minor_version(ITypeInfo *pTypeInfo)
-{
- VALUE ver;
- TYPEATTR *pTypeAttr;
- HRESULT hr;
- hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
- if (FAILED(hr))
- ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
- ver = RB_INT2FIX(pTypeAttr->wMinorVerNum);
- OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
- return ver;
-}
-
-/*
- * call-seq:
- * minor_version #=> OLE minor version
- *
- * Returns minor version.
- * tobj = WIN32OLE::Type.new('Microsoft Word 10.0 Object Library', 'Documents')
- * puts tobj.minor_version # => 2
- */
-static VALUE
-foletype_minor_version(VALUE self)
-{
- ITypeInfo *pTypeInfo = itypeinfo(self);
- return ole_type_minor_version(pTypeInfo);
-}
-
-static VALUE
-ole_type_typekind(ITypeInfo *pTypeInfo)
-{
- VALUE typekind;
- TYPEATTR *pTypeAttr;
- HRESULT hr;
- hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
- if (FAILED(hr))
- ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
- typekind = RB_INT2FIX(pTypeAttr->typekind);
- OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
- return typekind;
-}
-
-/*
- * call-seq:
- * typekind #=> number of type.
- *
- * Returns number which represents type.
- * tobj = WIN32OLE::Type.new('Microsoft Word 10.0 Object Library', 'Documents')
- * puts tobj.typekind # => 4
- *
- */
-static VALUE
-foletype_typekind(VALUE self)
-{
- ITypeInfo *pTypeInfo = itypeinfo(self);
- return ole_type_typekind(pTypeInfo);
-}
-
-static VALUE
-ole_type_helpstring(ITypeInfo *pTypeInfo)
-{
- HRESULT hr;
- BSTR bhelpstr;
- hr = ole_docinfo_from_type(pTypeInfo, NULL, &bhelpstr, NULL, NULL);
- if(FAILED(hr)) {
- return Qnil;
- }
- return WC2VSTR(bhelpstr);
-}
-
-/*
- * call-seq:
- * helpstring #=> help string.
- *
- * Returns help string.
- * tobj = WIN32OLE::Type.new('Microsoft Internet Controls', 'IWebBrowser')
- * puts tobj.helpstring # => Web Browser interface
- */
-static VALUE
-foletype_helpstring(VALUE self)
-{
- ITypeInfo *pTypeInfo = itypeinfo(self);
- return ole_type_helpstring(pTypeInfo);
-}
-
-static VALUE
-ole_type_src_type(ITypeInfo *pTypeInfo)
-{
- HRESULT hr;
- TYPEATTR *pTypeAttr;
- VALUE alias = Qnil;
- hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
- if (FAILED(hr))
- return alias;
- if(pTypeAttr->typekind != TKIND_ALIAS) {
- OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
- return alias;
- }
- alias = ole_typedesc2val(pTypeInfo, &(pTypeAttr->tdescAlias), Qnil);
- OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
- return alias;
-}
-
-/*
- * call-seq:
- * src_type #=> OLE source class
- *
- * Returns source class when the OLE class is 'Alias'.
- * tobj = WIN32OLE::Type.new('Microsoft Office 9.0 Object Library', 'MsoRGBType')
- * puts tobj.src_type # => I4
- *
- */
-static VALUE
-foletype_src_type(VALUE self)
-{
- ITypeInfo *pTypeInfo = itypeinfo(self);
- return ole_type_src_type(pTypeInfo);
-}
-
-static VALUE
-ole_type_helpfile(ITypeInfo *pTypeInfo)
-{
- HRESULT hr;
- BSTR bhelpfile;
- hr = ole_docinfo_from_type(pTypeInfo, NULL, NULL, NULL, &bhelpfile);
- if(FAILED(hr)) {
- return Qnil;
- }
- return WC2VSTR(bhelpfile);
-}
-
-/*
- * call-seq:
- * helpfile
- *
- * Returns helpfile path. If helpfile is not found, then returns nil.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
- * puts tobj.helpfile # => C:\...\VBAXL9.CHM
- *
- */
-static VALUE
-foletype_helpfile(VALUE self)
-{
- ITypeInfo *pTypeInfo = itypeinfo(self);
- return ole_type_helpfile(pTypeInfo);
-}
-
-static VALUE
-ole_type_helpcontext(ITypeInfo *pTypeInfo)
-{
- HRESULT hr;
- DWORD helpcontext;
- hr = ole_docinfo_from_type(pTypeInfo, NULL, NULL,
- &helpcontext, NULL);
- if(FAILED(hr))
- return Qnil;
- return RB_INT2FIX(helpcontext);
-}
-
-/*
- * call-seq:
- * helpcontext
- *
- * Returns helpcontext. If helpcontext is not found, then returns nil.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
- * puts tobj.helpfile # => 131185
- */
-static VALUE
-foletype_helpcontext(VALUE self)
-{
- ITypeInfo *pTypeInfo = itypeinfo(self);
- return ole_type_helpcontext(pTypeInfo);
-}
-
-static VALUE
-ole_variables(ITypeInfo *pTypeInfo)
-{
- HRESULT hr;
- TYPEATTR *pTypeAttr;
- WORD i;
- UINT len;
- BSTR bstr;
- VARDESC *pVarDesc;
- VALUE var;
- VALUE variables = rb_ary_new();
- hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
- if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLERuntimeError, "failed to GetTypeAttr");
- }
-
- for(i = 0; i < pTypeAttr->cVars; i++) {
- hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, i, &pVarDesc);
- if(FAILED(hr))
- continue;
- len = 0;
- hr = pTypeInfo->lpVtbl->GetNames(pTypeInfo, pVarDesc->memid, &bstr,
- 1, &len);
- if(FAILED(hr) || len == 0 || !bstr)
- continue;
-
- var = create_win32ole_variable(pTypeInfo, i, WC2VSTR(bstr));
- rb_ary_push(variables, var);
-
- pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
- pVarDesc = NULL;
- }
- OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
- return variables;
-}
-
-/*
- * call-seq:
- * variables
- *
- * Returns array of WIN32OLE::Variable objects which represent variables
- * defined in OLE class.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
- * vars = tobj.variables
- * vars.each do |v|
- * puts "#{v.name} = #{v.value}"
- * end
- *
- * The result of above sample script is follows:
- * xlChart = -4109
- * xlDialogSheet = -4116
- * xlExcel4IntlMacroSheet = 4
- * xlExcel4MacroSheet = 3
- * xlWorksheet = -4167
- *
- */
-static VALUE
-foletype_variables(VALUE self)
-{
- ITypeInfo *pTypeInfo = itypeinfo(self);
- return ole_variables(pTypeInfo);
-}
-
-/*
- * call-seq:
- * ole_methods # the array of WIN32OLE::Method objects.
- *
- * Returns array of WIN32OLE::Method objects which represent OLE method defined in
- * OLE type library.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
- * methods = tobj.ole_methods.collect{|m|
- * m.name
- * }
- * # => ['Activate', 'Copy', 'Delete',....]
- */
-static VALUE
-foletype_methods(VALUE self)
-{
- ITypeInfo *pTypeInfo = itypeinfo(self);
- return ole_methods_from_typeinfo(pTypeInfo, INVOKE_FUNC | INVOKE_PROPERTYGET | INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF);
-}
-
-/*
- * call-seq:
- * ole_typelib
- *
- * Returns the WIN32OLE::TypeLib object which is including the WIN32OLE::Type
- * object. If it is not found, then returns nil.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
- * puts tobj.ole_typelib # => 'Microsoft Excel 9.0 Object Library'
- */
-static VALUE
-foletype_ole_typelib(VALUE self)
-{
- ITypeInfo *pTypeInfo = itypeinfo(self);
- return ole_typelib_from_itypeinfo(pTypeInfo);
-}
-
-static VALUE
-ole_type_impl_ole_types(ITypeInfo *pTypeInfo, int implflags)
-{
- HRESULT hr;
- ITypeInfo *pRefTypeInfo;
- HREFTYPE href;
- WORD i;
- VALUE type;
- TYPEATTR *pTypeAttr;
- int flags;
-
- VALUE types = rb_ary_new();
- hr = OLE_GET_TYPEATTR(pTypeInfo, &pTypeAttr);
- if (FAILED(hr)) {
- return types;
- }
- for (i = 0; i < pTypeAttr->cImplTypes; i++) {
- hr = pTypeInfo->lpVtbl->GetImplTypeFlags(pTypeInfo, i, &flags);
- if (FAILED(hr))
- continue;
-
- hr = pTypeInfo->lpVtbl->GetRefTypeOfImplType(pTypeInfo, i, &href);
- if (FAILED(hr))
- continue;
- hr = pTypeInfo->lpVtbl->GetRefTypeInfo(pTypeInfo, href, &pRefTypeInfo);
- if (FAILED(hr))
- continue;
-
- if ((flags & implflags) == implflags) {
- type = ole_type_from_itypeinfo(pRefTypeInfo);
- if (type != Qnil) {
- rb_ary_push(types, type);
- }
- }
-
- OLE_RELEASE(pRefTypeInfo);
- }
- OLE_RELEASE_TYPEATTR(pTypeInfo, pTypeAttr);
- return types;
-}
-
-/*
- * call-seq:
- * implemented_ole_types
- *
- * Returns the array of WIN32OLE::Type object which is implemented by the WIN32OLE::Type
- * object.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'Worksheet')
- * p tobj.implemented_ole_types # => [_Worksheet, DocEvents]
- */
-static VALUE
-foletype_impl_ole_types(VALUE self)
-{
- ITypeInfo *pTypeInfo = itypeinfo(self);
- return ole_type_impl_ole_types(pTypeInfo, 0);
-}
-
-/*
- * call-seq:
- * source_ole_types
- *
- * Returns the array of WIN32OLE::Type object which is implemented by the WIN32OLE::Type
- * object and having IMPLTYPEFLAG_FSOURCE.
- * tobj = WIN32OLE::Type.new('Microsoft Internet Controls', "InternetExplorer")
- * p tobj.source_ole_types
- * # => [#<WIN32OLE::Type:DWebBrowserEvents2>, #<WIN32OLE::Type:DWebBrowserEvents>]
- */
-static VALUE
-foletype_source_ole_types(VALUE self)
-{
- ITypeInfo *pTypeInfo = itypeinfo(self);
- return ole_type_impl_ole_types(pTypeInfo, IMPLTYPEFLAG_FSOURCE);
-}
-
-/*
- * call-seq:
- * default_event_sources
- *
- * Returns the array of WIN32OLE::Type object which is implemented by the WIN32OLE::Type
- * object and having IMPLTYPEFLAG_FSOURCE and IMPLTYPEFLAG_FDEFAULT.
- * tobj = WIN32OLE::Type.new('Microsoft Internet Controls', "InternetExplorer")
- * p tobj.default_event_sources # => [#<WIN32OLE::Type:DWebBrowserEvents2>]
- */
-static VALUE
-foletype_default_event_sources(VALUE self)
-{
- ITypeInfo *pTypeInfo = itypeinfo(self);
- return ole_type_impl_ole_types(pTypeInfo, IMPLTYPEFLAG_FSOURCE|IMPLTYPEFLAG_FDEFAULT);
-}
-
-/*
- * call-seq:
- * default_ole_types
- *
- * Returns the array of WIN32OLE::Type object which is implemented by the WIN32OLE::Type
- * object and having IMPLTYPEFLAG_FDEFAULT.
- * tobj = WIN32OLE::Type.new('Microsoft Internet Controls', "InternetExplorer")
- * p tobj.default_ole_types
- * # => [#<WIN32OLE::Type:IWebBrowser2>, #<WIN32OLE::Type:DWebBrowserEvents2>]
- */
-static VALUE
-foletype_default_ole_types(VALUE self)
-{
- ITypeInfo *pTypeInfo = itypeinfo(self);
- return ole_type_impl_ole_types(pTypeInfo, IMPLTYPEFLAG_FDEFAULT);
-}
-
-/*
- * call-seq:
- * inspect -> String
- *
- * Returns the type name with class name.
- *
- * ie = WIN32OLE.new('InternetExplorer.Application')
- * ie.ole_type.inspect => #<WIN32OLE::Type:IWebBrowser2>
- */
-static VALUE
-foletype_inspect(VALUE self)
-{
- return default_inspect(self, "WIN32OLE::Type");
-}
-
-VALUE cWIN32OLE_TYPE;
-
-void Init_win32ole_type(void)
-{
- cWIN32OLE_TYPE = rb_define_class_under(cWIN32OLE, "Type", rb_cObject);
- /* Alias of WIN32OLE::Type, for the backward compatibility */
- rb_define_const(rb_cObject, "WIN32OLE_TYPE", cWIN32OLE_TYPE);
- rb_define_singleton_method(cWIN32OLE_TYPE, "ole_classes", foletype_s_ole_classes, 1);
- rb_define_singleton_method(cWIN32OLE_TYPE, "typelibs", foletype_s_typelibs, 0);
- rb_define_singleton_method(cWIN32OLE_TYPE, "progids", foletype_s_progids, 0);
- rb_define_alloc_func(cWIN32OLE_TYPE, foletype_s_allocate);
- rb_define_method(cWIN32OLE_TYPE, "initialize", foletype_initialize, 2);
- rb_define_method(cWIN32OLE_TYPE, "name", foletype_name, 0);
- rb_define_method(cWIN32OLE_TYPE, "ole_type", foletype_ole_type, 0);
- rb_define_method(cWIN32OLE_TYPE, "guid", foletype_guid, 0);
- rb_define_method(cWIN32OLE_TYPE, "progid", foletype_progid, 0);
- rb_define_method(cWIN32OLE_TYPE, "visible?", foletype_visible, 0);
- rb_define_alias(cWIN32OLE_TYPE, "to_s", "name");
- rb_define_method(cWIN32OLE_TYPE, "major_version", foletype_major_version, 0);
- rb_define_method(cWIN32OLE_TYPE, "minor_version", foletype_minor_version, 0);
- rb_define_method(cWIN32OLE_TYPE, "typekind", foletype_typekind, 0);
- rb_define_method(cWIN32OLE_TYPE, "helpstring", foletype_helpstring, 0);
- rb_define_method(cWIN32OLE_TYPE, "src_type", foletype_src_type, 0);
- rb_define_method(cWIN32OLE_TYPE, "helpfile", foletype_helpfile, 0);
- rb_define_method(cWIN32OLE_TYPE, "helpcontext", foletype_helpcontext, 0);
- rb_define_method(cWIN32OLE_TYPE, "variables", foletype_variables, 0);
- rb_define_method(cWIN32OLE_TYPE, "ole_methods", foletype_methods, 0);
- rb_define_method(cWIN32OLE_TYPE, "ole_typelib", foletype_ole_typelib, 0);
- rb_define_method(cWIN32OLE_TYPE, "implemented_ole_types", foletype_impl_ole_types, 0);
- rb_define_method(cWIN32OLE_TYPE, "source_ole_types", foletype_source_ole_types, 0);
- rb_define_method(cWIN32OLE_TYPE, "default_event_sources", foletype_default_event_sources, 0);
- rb_define_method(cWIN32OLE_TYPE, "default_ole_types", foletype_default_ole_types, 0);
- rb_define_method(cWIN32OLE_TYPE, "inspect", foletype_inspect, 0);
-}
diff --git a/ext/win32ole/win32ole_type.h b/ext/win32ole/win32ole_type.h
deleted file mode 100644
index 87b551e502..0000000000
--- a/ext/win32ole/win32ole_type.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef WIN32OLE_TYPE_H
-#define WIN32OLE_TYPE_H 1
-extern VALUE cWIN32OLE_TYPE;
-VALUE create_win32ole_type(ITypeInfo *pTypeInfo, VALUE name);
-ITypeInfo *itypeinfo(VALUE self);
-VALUE ole_type_from_itypeinfo(ITypeInfo *pTypeInfo);
-void Init_win32ole_type(void);
-#endif
diff --git a/ext/win32ole/win32ole_typelib.c b/ext/win32ole/win32ole_typelib.c
deleted file mode 100644
index e5eda07e76..0000000000
--- a/ext/win32ole/win32ole_typelib.c
+++ /dev/null
@@ -1,848 +0,0 @@
-#include "win32ole.h"
-
-struct oletypelibdata {
- ITypeLib *pTypeLib;
-};
-
-static VALUE reg_get_typelib_file_path(HKEY hkey);
-static VALUE oletypelib_path(VALUE guid, VALUE version);
-static HRESULT oletypelib_from_guid(VALUE guid, VALUE version, ITypeLib **ppTypeLib);
-static VALUE foletypelib_s_typelibs(VALUE self);
-static VALUE oletypelib_set_member(VALUE self, ITypeLib *pTypeLib);
-static void oletypelib_free(void *ptr);
-static size_t oletypelib_size(const void *ptr);
-static VALUE foletypelib_s_allocate(VALUE klass);
-static VALUE oletypelib_search_registry(VALUE self, VALUE typelib);
-static void oletypelib_get_libattr(ITypeLib *pTypeLib, TLIBATTR **ppTLibAttr);
-static VALUE oletypelib_search_registry2(VALUE self, VALUE args);
-static VALUE foletypelib_initialize(VALUE self, VALUE args);
-static VALUE foletypelib_guid(VALUE self);
-static VALUE foletypelib_name(VALUE self);
-static VALUE make_version_str(VALUE major, VALUE minor);
-static VALUE foletypelib_version(VALUE self);
-static VALUE foletypelib_major_version(VALUE self);
-static VALUE foletypelib_minor_version(VALUE self);
-static VALUE foletypelib_path(VALUE self);
-static VALUE foletypelib_visible(VALUE self);
-static VALUE foletypelib_library_name(VALUE self);
-static VALUE ole_types_from_typelib(ITypeLib *pTypeLib, VALUE classes);
-static VALUE typelib_file_from_typelib(VALUE ole);
-static VALUE typelib_file_from_clsid(VALUE ole);
-static VALUE foletypelib_ole_types(VALUE self);
-static VALUE foletypelib_inspect(VALUE self);
-
-static const rb_data_type_t oletypelib_datatype = {
- "win32ole_typelib",
- {NULL, oletypelib_free, oletypelib_size,},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
-};
-
-static VALUE
-reg_get_typelib_file_path(HKEY hkey)
-{
- VALUE path = Qnil;
- path = reg_get_val2(hkey, "win64");
- if (path != Qnil) {
- return path;
- }
- path = reg_get_val2(hkey, "win32");
- if (path != Qnil) {
- return path;
- }
- path = reg_get_val2(hkey, "win16");
- return path;
-}
-
-static VALUE
-oletypelib_path(VALUE guid, VALUE version)
-{
- int k;
- LONG err;
- HKEY hkey;
- HKEY hlang;
- VALUE lang;
- VALUE path = Qnil;
-
- VALUE key = rb_str_new2("TypeLib\\");
- rb_str_concat(key, guid);
- rb_str_cat2(key, "\\");
- rb_str_concat(key, version);
-
- err = reg_open_vkey(HKEY_CLASSES_ROOT, key, &hkey);
- if (err != ERROR_SUCCESS) {
- return Qnil;
- }
- for(k = 0; path == Qnil; k++) {
- lang = reg_enum_key(hkey, k);
- if (lang == Qnil)
- break;
- err = reg_open_vkey(hkey, lang, &hlang);
- if (err == ERROR_SUCCESS) {
- path = reg_get_typelib_file_path(hlang);
- RegCloseKey(hlang);
- }
- }
- RegCloseKey(hkey);
- return path;
-}
-
-static HRESULT
-oletypelib_from_guid(VALUE guid, VALUE version, ITypeLib **ppTypeLib)
-{
- VALUE path;
- OLECHAR *pBuf;
- HRESULT hr;
- path = oletypelib_path(guid, version);
- if (path == Qnil) {
- return E_UNEXPECTED;
- }
- pBuf = ole_vstr2wc(path);
- hr = LoadTypeLibEx(pBuf, REGKIND_NONE, ppTypeLib);
- SysFreeString(pBuf);
- return hr;
-}
-
-ITypeLib *
-itypelib(VALUE self)
-{
- struct oletypelibdata *ptlib;
- TypedData_Get_Struct(self, struct oletypelibdata, &oletypelib_datatype, ptlib);
- return ptlib->pTypeLib;
-}
-
-VALUE
-ole_typelib_from_itypeinfo(ITypeInfo *pTypeInfo)
-{
- HRESULT hr;
- ITypeLib *pTypeLib;
- unsigned int index;
- VALUE retval = Qnil;
-
- hr = pTypeInfo->lpVtbl->GetContainingTypeLib(pTypeInfo, &pTypeLib, &index);
- if(FAILED(hr)) {
- return Qnil;
- }
- retval = create_win32ole_typelib(pTypeLib);
- return retval;
-}
-
-/*
- * Document-class: WIN32OLE::TypeLib
- *
- * +WIN32OLE::TypeLib+ objects represent OLE tyblib information.
- */
-
-/*
- * call-seq:
- *
- * typelibs
- *
- * Returns the array of WIN32OLE::TypeLib object.
- *
- * tlibs = WIN32OLE::TypeLib.typelibs
- *
- */
-static VALUE
-foletypelib_s_typelibs(VALUE self)
-{
- HKEY htypelib, hguid;
- DWORD i, j;
- LONG err;
- VALUE guid;
- VALUE version;
- VALUE name = Qnil;
- VALUE typelibs = rb_ary_new();
- VALUE typelib = Qnil;
- HRESULT hr;
- ITypeLib *pTypeLib;
-
- err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib);
- if(err != ERROR_SUCCESS) {
- return typelibs;
- }
- for(i = 0; ; i++) {
- guid = reg_enum_key(htypelib, i);
- if (guid == Qnil)
- break;
- err = reg_open_vkey(htypelib, guid, &hguid);
- if (err != ERROR_SUCCESS)
- continue;
- for(j = 0; ; j++) {
- version = reg_enum_key(hguid, j);
- if (version == Qnil)
- break;
- if ( (name = reg_get_val2(hguid, StringValuePtr(version))) != Qnil ) {
- hr = oletypelib_from_guid(guid, version, &pTypeLib);
- if (SUCCEEDED(hr)) {
- typelib = create_win32ole_typelib(pTypeLib);
- rb_ary_push(typelibs, typelib);
- }
- }
- }
- RegCloseKey(hguid);
- }
- RegCloseKey(htypelib);
- return typelibs;
-}
-
-static VALUE
-oletypelib_set_member(VALUE self, ITypeLib *pTypeLib)
-{
- struct oletypelibdata *ptlib;
- TypedData_Get_Struct(self, struct oletypelibdata, &oletypelib_datatype, ptlib);
- ptlib->pTypeLib = pTypeLib;
- return self;
-}
-
-static void
-oletypelib_free(void *ptr)
-{
- struct oletypelibdata *poletypelib = ptr;
- OLE_FREE(poletypelib->pTypeLib);
- free(poletypelib);
-}
-
-static size_t
-oletypelib_size(const void *ptr)
-{
- return ptr ? sizeof(struct oletypelibdata) : 0;
-}
-
-static VALUE
-foletypelib_s_allocate(VALUE klass)
-{
- struct oletypelibdata *poletypelib;
- VALUE obj;
- ole_initialize();
- obj = TypedData_Make_Struct(klass, struct oletypelibdata, &oletypelib_datatype, poletypelib);
- poletypelib->pTypeLib = NULL;
- return obj;
-}
-
-VALUE
-create_win32ole_typelib(ITypeLib *pTypeLib)
-{
- VALUE obj = foletypelib_s_allocate(cWIN32OLE_TYPELIB);
- oletypelib_set_member(obj, pTypeLib);
- return obj;
-}
-
-static VALUE
-oletypelib_search_registry(VALUE self, VALUE typelib)
-{
- HKEY htypelib, hguid, hversion;
- DWORD i, j;
- LONG err;
- VALUE found = Qfalse;
- VALUE tlib;
- VALUE guid;
- VALUE ver;
- HRESULT hr;
- ITypeLib *pTypeLib;
-
- err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib);
- if(err != ERROR_SUCCESS) {
- return Qfalse;
- }
- for(i = 0; !found; i++) {
- guid = reg_enum_key(htypelib, i);
- if (guid == Qnil)
- break;
- err = reg_open_vkey(htypelib, guid, &hguid);
- if (err != ERROR_SUCCESS)
- continue;
- for(j = 0; found == Qfalse; j++) {
- ver = reg_enum_key(hguid, j);
- if (ver == Qnil)
- break;
- err = reg_open_vkey(hguid, ver, &hversion);
- if (err != ERROR_SUCCESS)
- continue;
- tlib = reg_get_val(hversion, NULL);
- if (tlib == Qnil) {
- RegCloseKey(hversion);
- continue;
- }
- if (rb_str_cmp(typelib, tlib) == 0) {
- hr = oletypelib_from_guid(guid, ver, &pTypeLib);
- if (SUCCEEDED(hr)) {
- oletypelib_set_member(self, pTypeLib);
- found = Qtrue;
- }
- }
- RegCloseKey(hversion);
- }
- RegCloseKey(hguid);
- }
- RegCloseKey(htypelib);
- return found;
-}
-
-static void
-oletypelib_get_libattr(ITypeLib *pTypeLib, TLIBATTR **ppTLibAttr)
-{
- HRESULT hr;
- hr = pTypeLib->lpVtbl->GetLibAttr(pTypeLib, ppTLibAttr);
- if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLERuntimeError,
- "failed to get library attribute(TLIBATTR) from ITypeLib");
- }
-}
-
-static VALUE
-oletypelib_search_registry2(VALUE self, VALUE args)
-{
- HKEY htypelib, hguid, hversion;
- double fver;
- DWORD j;
- LONG err;
- VALUE found = Qfalse;
- VALUE tlib;
- VALUE ver;
- VALUE version_str;
- VALUE version = Qnil;
- VALUE typelib = Qnil;
- HRESULT hr;
- ITypeLib *pTypeLib;
-
- VALUE guid = rb_ary_entry(args, 0);
- version_str = make_version_str(rb_ary_entry(args, 1), rb_ary_entry(args, 2));
-
- err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib);
- if(err != ERROR_SUCCESS) {
- return Qfalse;
- }
- err = reg_open_vkey(htypelib, guid, &hguid);
- if (err != ERROR_SUCCESS) {
- RegCloseKey(htypelib);
- return Qfalse;
- }
- if (version_str != Qnil) {
- err = reg_open_vkey(hguid, version_str, &hversion);
- if (err == ERROR_SUCCESS) {
- tlib = reg_get_val(hversion, NULL);
- if (tlib != Qnil) {
- typelib = tlib;
- version = version_str;
- }
- }
- RegCloseKey(hversion);
- } else {
- fver = 0.0;
- for(j = 0; ;j++) {
- ver = reg_enum_key(hguid, j);
- if (ver == Qnil)
- break;
- err = reg_open_vkey(hguid, ver, &hversion);
- if (err != ERROR_SUCCESS)
- continue;
- tlib = reg_get_val(hversion, NULL);
- if (tlib == Qnil) {
- RegCloseKey(hversion);
- continue;
- }
- if (fver < atof(StringValuePtr(ver))) {
- fver = atof(StringValuePtr(ver));
- version = ver;
- typelib = tlib;
- }
- RegCloseKey(hversion);
- }
- }
- RegCloseKey(hguid);
- RegCloseKey(htypelib);
- if (typelib != Qnil) {
- hr = oletypelib_from_guid(guid, version, &pTypeLib);
- if (SUCCEEDED(hr)) {
- found = Qtrue;
- oletypelib_set_member(self, pTypeLib);
- }
- }
- return found;
-}
-
-
-/*
- * call-seq:
- * new(typelib [, version1, version2]) -> WIN32OLE::TypeLib object
- *
- * Returns a new WIN32OLE::TypeLib object.
- *
- * The first argument <i>typelib</i> specifies OLE type library name or GUID or
- * OLE library file.
- * The second argument is major version or version of the type library.
- * The third argument is minor version.
- * The second argument and third argument are optional.
- * If the first argument is type library name, then the second and third argument
- * are ignored.
- *
- * tlib1 = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library')
- * tlib2 = WIN32OLE::TypeLib.new('{00020813-0000-0000-C000-000000000046}')
- * tlib3 = WIN32OLE::TypeLib.new('{00020813-0000-0000-C000-000000000046}', 1.3)
- * tlib4 = WIN32OLE::TypeLib.new('{00020813-0000-0000-C000-000000000046}', 1, 3)
- * tlib5 = WIN32OLE::TypeLib.new("C:\\WINNT\\SYSTEM32\\SHELL32.DLL")
- * puts tlib1.name # -> 'Microsoft Excel 9.0 Object Library'
- * puts tlib2.name # -> 'Microsoft Excel 9.0 Object Library'
- * puts tlib3.name # -> 'Microsoft Excel 9.0 Object Library'
- * puts tlib4.name # -> 'Microsoft Excel 9.0 Object Library'
- * puts tlib5.name # -> 'Microsoft Shell Controls And Automation'
- *
- */
-static VALUE
-foletypelib_initialize(VALUE self, VALUE args)
-{
- VALUE found = Qfalse;
- VALUE typelib = Qnil;
- int len = 0;
- OLECHAR * pbuf;
- ITypeLib *pTypeLib;
- HRESULT hr = S_OK;
-
- len = RARRAY_LEN(args);
- rb_check_arity(len, 1, 3);
-
- typelib = rb_ary_entry(args, 0);
-
- SafeStringValue(typelib);
-
- found = oletypelib_search_registry(self, typelib);
- if (found == Qfalse) {
- found = oletypelib_search_registry2(self, args);
- }
- if (found == Qfalse) {
- pbuf = ole_vstr2wc(typelib);
- hr = LoadTypeLibEx(pbuf, REGKIND_NONE, &pTypeLib);
- SysFreeString(pbuf);
- if (SUCCEEDED(hr)) {
- found = Qtrue;
- oletypelib_set_member(self, pTypeLib);
- }
- }
-
- if (found == Qfalse) {
- rb_raise(eWIN32OLERuntimeError, "not found type library `%s`",
- StringValuePtr(typelib));
- }
- return self;
-}
-
-/*
- * call-seq:
- * guid -> The guid string.
- *
- * Returns guid string which specifies type library.
- *
- * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library')
- * guid = tlib.guid # -> '{00020813-0000-0000-C000-000000000046}'
- */
-static VALUE
-foletypelib_guid(VALUE self)
-{
- ITypeLib *pTypeLib;
- OLECHAR bstr[80];
- VALUE guid = Qnil;
- int len;
- TLIBATTR *pTLibAttr;
-
- pTypeLib = itypelib(self);
- oletypelib_get_libattr(pTypeLib, &pTLibAttr);
- len = StringFromGUID2(&pTLibAttr->guid, bstr, sizeof(bstr)/sizeof(OLECHAR));
- if (len > 3) {
- guid = ole_wc2vstr(bstr, FALSE);
- }
- pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
- return guid;
-}
-
-/*
- * call-seq:
- * name -> The type library name
- *
- * Returns the type library name.
- *
- * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library')
- * name = tlib.name # -> 'Microsoft Excel 9.0 Object Library'
- */
-static VALUE
-foletypelib_name(VALUE self)
-{
- ITypeLib *pTypeLib;
- HRESULT hr;
- BSTR bstr;
- VALUE name;
- pTypeLib = itypelib(self);
- hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, -1,
- NULL, &bstr, NULL, NULL);
-
- if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLERuntimeError, "failed to get name from ITypeLib");
- }
- name = WC2VSTR(bstr);
- return name;
-}
-
-static VALUE
-make_version_str(VALUE major, VALUE minor)
-{
- VALUE version_str = Qnil;
- VALUE minor_str = Qnil;
- if (major == Qnil) {
- return Qnil;
- }
- version_str = rb_String(major);
- if (minor != Qnil) {
- minor_str = rb_String(minor);
- rb_str_cat2(version_str, ".");
- rb_str_append(version_str, minor_str);
- }
- return version_str;
-}
-
-/*
- * call-seq:
- * version -> The type library version String object.
- *
- * Returns the type library version.
- *
- * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library')
- * puts tlib.version #-> "1.3"
- */
-static VALUE
-foletypelib_version(VALUE self)
-{
- TLIBATTR *pTLibAttr;
- ITypeLib *pTypeLib;
- VALUE version;
-
- pTypeLib = itypelib(self);
- oletypelib_get_libattr(pTypeLib, &pTLibAttr);
- version = rb_sprintf("%d.%d", pTLibAttr->wMajorVerNum, pTLibAttr->wMinorVerNum);
- pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
- return version;
-}
-
-/*
- * call-seq:
- * major_version -> The type library major version.
- *
- * Returns the type library major version.
- *
- * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library')
- * puts tlib.major_version # -> 1
- */
-static VALUE
-foletypelib_major_version(VALUE self)
-{
- TLIBATTR *pTLibAttr;
- VALUE major;
- ITypeLib *pTypeLib;
- pTypeLib = itypelib(self);
- oletypelib_get_libattr(pTypeLib, &pTLibAttr);
-
- major = RB_INT2NUM(pTLibAttr->wMajorVerNum);
- pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
- return major;
-}
-
-/*
- * call-seq:
- * minor_version -> The type library minor version.
- *
- * Returns the type library minor version.
- *
- * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library')
- * puts tlib.minor_version # -> 3
- */
-static VALUE
-foletypelib_minor_version(VALUE self)
-{
- TLIBATTR *pTLibAttr;
- VALUE minor;
- ITypeLib *pTypeLib;
- pTypeLib = itypelib(self);
- oletypelib_get_libattr(pTypeLib, &pTLibAttr);
- minor = RB_INT2NUM(pTLibAttr->wMinorVerNum);
- pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
- return minor;
-}
-
-/*
- * call-seq:
- * path -> The type library file path.
- *
- * Returns the type library file path.
- *
- * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library')
- * puts tlib.path #-> 'C:\...\EXCEL9.OLB'
- */
-static VALUE
-foletypelib_path(VALUE self)
-{
- TLIBATTR *pTLibAttr;
- HRESULT hr = S_OK;
- BSTR bstr;
- LCID lcid = cWIN32OLE_lcid;
- VALUE path;
- ITypeLib *pTypeLib;
-
- pTypeLib = itypelib(self);
- oletypelib_get_libattr(pTypeLib, &pTLibAttr);
- hr = QueryPathOfRegTypeLib(&pTLibAttr->guid,
- pTLibAttr->wMajorVerNum,
- pTLibAttr->wMinorVerNum,
- lcid,
- &bstr);
- if (FAILED(hr)) {
- pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
- ole_raise(hr, eWIN32OLERuntimeError, "failed to QueryPathOfRegTypeTypeLib");
- }
-
- pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
- path = WC2VSTR(bstr);
- return path;
-}
-
-/*
- * call-seq:
- * visible?
- *
- * Returns true if the type library information is not hidden.
- * If wLibFlags of TLIBATTR is 0 or LIBFLAG_FRESTRICTED or LIBFLAG_FHIDDEN,
- * the method returns false, otherwise, returns true.
- * If the method fails to access the TLIBATTR information, then
- * WIN32OLE::RuntimeError is raised.
- *
- * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library')
- * tlib.visible? # => true
- */
-static VALUE
-foletypelib_visible(VALUE self)
-{
- ITypeLib *pTypeLib = NULL;
- VALUE visible = Qtrue;
- TLIBATTR *pTLibAttr;
-
- pTypeLib = itypelib(self);
- oletypelib_get_libattr(pTypeLib, &pTLibAttr);
-
- if ((pTLibAttr->wLibFlags == 0) ||
- (pTLibAttr->wLibFlags & LIBFLAG_FRESTRICTED) ||
- (pTLibAttr->wLibFlags & LIBFLAG_FHIDDEN)) {
- visible = Qfalse;
- }
- pTypeLib->lpVtbl->ReleaseTLibAttr(pTypeLib, pTLibAttr);
- return visible;
-}
-
-/*
- * call-seq:
- * library_name
- *
- * Returns library name.
- * If the method fails to access library name, WIN32OLE::RuntimeError is raised.
- *
- * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library')
- * tlib.library_name # => Excel
- */
-static VALUE
-foletypelib_library_name(VALUE self)
-{
- HRESULT hr;
- ITypeLib *pTypeLib = NULL;
- VALUE libname = Qnil;
- BSTR bstr;
-
- pTypeLib = itypelib(self);
- hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, -1,
- &bstr, NULL, NULL, NULL);
- if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLERuntimeError, "failed to get library name");
- }
- libname = WC2VSTR(bstr);
- return libname;
-}
-
-static VALUE
-ole_types_from_typelib(ITypeLib *pTypeLib, VALUE classes)
-{
- long count;
- int i;
- HRESULT hr;
- BSTR bstr;
- ITypeInfo *pTypeInfo;
- VALUE type;
-
- count = pTypeLib->lpVtbl->GetTypeInfoCount(pTypeLib);
- for (i = 0; i < count; i++) {
- hr = pTypeLib->lpVtbl->GetDocumentation(pTypeLib, i,
- &bstr, NULL, NULL, NULL);
- if (FAILED(hr))
- continue;
-
- hr = pTypeLib->lpVtbl->GetTypeInfo(pTypeLib, i, &pTypeInfo);
- if (FAILED(hr))
- continue;
-
- type = create_win32ole_type(pTypeInfo, WC2VSTR(bstr));
-
- rb_ary_push(classes, type);
- OLE_RELEASE(pTypeInfo);
- }
- return classes;
-}
-
-static VALUE
-typelib_file_from_typelib(VALUE ole)
-{
- HKEY htypelib, hclsid, hversion, hlang;
- double fver;
- DWORD i, j, k;
- LONG err;
- BOOL found = FALSE;
- VALUE typelib;
- VALUE file = Qnil;
- VALUE clsid;
- VALUE ver;
- VALUE lang;
-
- err = reg_open_key(HKEY_CLASSES_ROOT, "TypeLib", &htypelib);
- if(err != ERROR_SUCCESS) {
- return Qnil;
- }
- for(i = 0; !found; i++) {
- clsid = reg_enum_key(htypelib, i);
- if (clsid == Qnil)
- break;
- err = reg_open_vkey(htypelib, clsid, &hclsid);
- if (err != ERROR_SUCCESS)
- continue;
- fver = 0;
- for(j = 0; !found; j++) {
- ver = reg_enum_key(hclsid, j);
- if (ver == Qnil)
- break;
- err = reg_open_vkey(hclsid, ver, &hversion);
- if (err != ERROR_SUCCESS || fver > atof(StringValuePtr(ver)))
- continue;
- fver = atof(StringValuePtr(ver));
- typelib = reg_get_val(hversion, NULL);
- if (typelib == Qnil)
- continue;
- if (rb_str_cmp(typelib, ole) == 0) {
- for(k = 0; !found; k++) {
- lang = reg_enum_key(hversion, k);
- if (lang == Qnil)
- break;
- err = reg_open_vkey(hversion, lang, &hlang);
- if (err == ERROR_SUCCESS) {
- if ((file = reg_get_typelib_file_path(hlang)) != Qnil)
- found = TRUE;
- RegCloseKey(hlang);
- }
- }
- }
- RegCloseKey(hversion);
- }
- RegCloseKey(hclsid);
- }
- RegCloseKey(htypelib);
- return file;
-}
-
-static VALUE
-typelib_file_from_clsid(VALUE ole)
-{
- HKEY hroot, hclsid;
- LONG err;
- VALUE typelib;
- char path[MAX_PATH + 1];
-
- err = reg_open_key(HKEY_CLASSES_ROOT, "CLSID", &hroot);
- if (err != ERROR_SUCCESS) {
- return Qnil;
- }
- err = reg_open_key(hroot, StringValuePtr(ole), &hclsid);
- if (err != ERROR_SUCCESS) {
- RegCloseKey(hroot);
- return Qnil;
- }
- typelib = reg_get_val2(hclsid, "InprocServer32");
- RegCloseKey(hroot);
- RegCloseKey(hclsid);
- if (typelib != Qnil) {
- ExpandEnvironmentStrings(StringValuePtr(typelib), path, sizeof(path));
- path[MAX_PATH] = '\0';
- typelib = rb_str_new2(path);
- }
- return typelib;
-}
-
-VALUE
-typelib_file(VALUE ole)
-{
- VALUE file = typelib_file_from_clsid(ole);
- if (file != Qnil) {
- return file;
- }
- return typelib_file_from_typelib(ole);
-}
-
-
-/*
- * call-seq:
- * ole_types -> The array of WIN32OLE::Type object included the type library.
- *
- * Returns the type library file path.
- *
- * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library')
- * classes = tlib.ole_types.collect{|k| k.name} # -> ['AddIn', 'AddIns' ...]
- */
-static VALUE
-foletypelib_ole_types(VALUE self)
-{
- ITypeLib *pTypeLib = NULL;
- VALUE classes = rb_ary_new();
- pTypeLib = itypelib(self);
- ole_types_from_typelib(pTypeLib, classes);
- return classes;
-}
-
-/*
- * call-seq:
- * inspect -> String
- *
- * Returns the type library name with class name.
- *
- * tlib = WIN32OLE::TypeLib.new('Microsoft Excel 9.0 Object Library')
- * tlib.inspect # => "<#WIN32OLE::TypeLib:Microsoft Excel 9.0 Object Library>"
- */
-static VALUE
-foletypelib_inspect(VALUE self)
-{
- return default_inspect(self, "WIN32OLE::TypeLib");
-}
-
-VALUE cWIN32OLE_TYPELIB;
-
-void
-Init_win32ole_typelib(void)
-{
- cWIN32OLE_TYPELIB = rb_define_class_under(cWIN32OLE, "TypeLib", rb_cObject);
- /* Alias of WIN32OLE::TypeLib, for the backward compatibility */
- rb_define_const(rb_cObject, "WIN32OLE_TYPELIB", cWIN32OLE_TYPELIB);
- rb_define_singleton_method(cWIN32OLE_TYPELIB, "typelibs", foletypelib_s_typelibs, 0);
- rb_define_alloc_func(cWIN32OLE_TYPELIB, foletypelib_s_allocate);
- rb_define_method(cWIN32OLE_TYPELIB, "initialize", foletypelib_initialize, -2);
- rb_define_method(cWIN32OLE_TYPELIB, "guid", foletypelib_guid, 0);
- rb_define_method(cWIN32OLE_TYPELIB, "name", foletypelib_name, 0);
- rb_define_method(cWIN32OLE_TYPELIB, "version", foletypelib_version, 0);
- rb_define_method(cWIN32OLE_TYPELIB, "major_version", foletypelib_major_version, 0);
- rb_define_method(cWIN32OLE_TYPELIB, "minor_version", foletypelib_minor_version, 0);
- rb_define_method(cWIN32OLE_TYPELIB, "path", foletypelib_path, 0);
- rb_define_method(cWIN32OLE_TYPELIB, "ole_types", foletypelib_ole_types, 0);
- rb_define_alias(cWIN32OLE_TYPELIB, "ole_classes", "ole_types");
- rb_define_method(cWIN32OLE_TYPELIB, "visible?", foletypelib_visible, 0);
- rb_define_method(cWIN32OLE_TYPELIB, "library_name", foletypelib_library_name, 0);
- rb_define_alias(cWIN32OLE_TYPELIB, "to_s", "name");
- rb_define_method(cWIN32OLE_TYPELIB, "inspect", foletypelib_inspect, 0);
-}
diff --git a/ext/win32ole/win32ole_typelib.h b/ext/win32ole/win32ole_typelib.h
deleted file mode 100644
index 2c2730bb58..0000000000
--- a/ext/win32ole/win32ole_typelib.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef WIN32OLE_TYPELIB_H
-#define WIN32OLE_TYPELIB_H 1
-
-extern VALUE cWIN32OLE_TYPELIB;
-
-void Init_win32ole_typelib(void);
-ITypeLib * itypelib(VALUE self);
-VALUE typelib_file(VALUE ole);
-VALUE create_win32ole_typelib(ITypeLib *pTypeLib);
-VALUE ole_typelib_from_itypeinfo(ITypeInfo *pTypeInfo);
-#endif
diff --git a/ext/win32ole/win32ole_variable.c b/ext/win32ole/win32ole_variable.c
deleted file mode 100644
index 34435301d4..0000000000
--- a/ext/win32ole/win32ole_variable.c
+++ /dev/null
@@ -1,385 +0,0 @@
-#include "win32ole.h"
-
-struct olevariabledata {
- ITypeInfo *pTypeInfo;
- UINT index;
-};
-
-static void olevariable_free(void *ptr);
-static size_t olevariable_size(const void *ptr);
-static VALUE folevariable_name(VALUE self);
-static VALUE ole_variable_ole_type(ITypeInfo *pTypeInfo, UINT var_index);
-static VALUE folevariable_ole_type(VALUE self);
-static VALUE ole_variable_ole_type_detail(ITypeInfo *pTypeInfo, UINT var_index);
-static VALUE folevariable_ole_type_detail(VALUE self);
-static VALUE ole_variable_value(ITypeInfo *pTypeInfo, UINT var_index);
-static VALUE folevariable_value(VALUE self);
-static VALUE ole_variable_visible(ITypeInfo *pTypeInfo, UINT var_index);
-static VALUE folevariable_visible(VALUE self);
-static VALUE ole_variable_kind(ITypeInfo *pTypeInfo, UINT var_index);
-static VALUE folevariable_variable_kind(VALUE self);
-static VALUE ole_variable_varkind(ITypeInfo *pTypeInfo, UINT var_index);
-static VALUE folevariable_varkind(VALUE self);
-static VALUE folevariable_inspect(VALUE self);
-
-static const rb_data_type_t olevariable_datatype = {
- "win32ole_variable",
- {NULL, olevariable_free, olevariable_size,},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
-};
-
-static void
-olevariable_free(void *ptr)
-{
- struct olevariabledata *polevar = ptr;
- OLE_FREE(polevar->pTypeInfo);
- free(polevar);
-}
-
-static size_t
-olevariable_size(const void *ptr)
-{
- return ptr ? sizeof(struct olevariabledata) : 0;
-}
-
-/*
- * Document-class: WIN32OLE::Variable
- *
- * +WIN32OLE::Variable+ objects represent OLE variable information.
- */
-
-VALUE
-create_win32ole_variable(ITypeInfo *pTypeInfo, UINT index, VALUE name)
-{
- struct olevariabledata *pvar;
- VALUE obj = TypedData_Make_Struct(cWIN32OLE_VARIABLE, struct olevariabledata,
- &olevariable_datatype, pvar);
- pvar->pTypeInfo = pTypeInfo;
- OLE_ADDREF(pTypeInfo);
- pvar->index = index;
- rb_ivar_set(obj, rb_intern("name"), name);
- return obj;
-}
-
-/*
- * call-seq:
- * name
- *
- * Returns the name of variable.
- *
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
- * variables = tobj.variables
- * variables.each do |variable|
- * puts "#{variable.name}"
- * end
- *
- * The result of above script is following:
- * xlChart
- * xlDialogSheet
- * xlExcel4IntlMacroSheet
- * xlExcel4MacroSheet
- * xlWorksheet
- *
- */
-static VALUE
-folevariable_name(VALUE self)
-{
- return rb_ivar_get(self, rb_intern("name"));
-}
-
-static VALUE
-ole_variable_ole_type(ITypeInfo *pTypeInfo, UINT var_index)
-{
- VARDESC *pVarDesc;
- HRESULT hr;
- VALUE type;
- hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
- if (FAILED(hr))
- ole_raise(hr, eWIN32OLERuntimeError, "failed to GetVarDesc");
- type = ole_typedesc2val(pTypeInfo, &(pVarDesc->elemdescVar.tdesc), Qnil);
- pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
- return type;
-}
-
-/*
- * call-seq:
- * ole_type
- *
- * Returns OLE type string.
- *
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
- * variables = tobj.variables
- * variables.each do |variable|
- * puts "#{variable.ole_type} #{variable.name}"
- * end
- *
- * The result of above script is following:
- * INT xlChart
- * INT xlDialogSheet
- * INT xlExcel4IntlMacroSheet
- * INT xlExcel4MacroSheet
- * INT xlWorksheet
- *
- */
-static VALUE
-folevariable_ole_type(VALUE self)
-{
- struct olevariabledata *pvar;
- TypedData_Get_Struct(self, struct olevariabledata, &olevariable_datatype, pvar);
- return ole_variable_ole_type(pvar->pTypeInfo, pvar->index);
-}
-
-static VALUE
-ole_variable_ole_type_detail(ITypeInfo *pTypeInfo, UINT var_index)
-{
- VARDESC *pVarDesc;
- HRESULT hr;
- VALUE type = rb_ary_new();
- hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
- if (FAILED(hr))
- ole_raise(hr, eWIN32OLERuntimeError, "failed to GetVarDesc");
- ole_typedesc2val(pTypeInfo, &(pVarDesc->elemdescVar.tdesc), type);
- pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
- return type;
-}
-
-/*
- * call-seq:
- * ole_type_detail
- *
- * Returns detail information of type. The information is array of type.
- *
- * tobj = WIN32OLE::Type.new('DirectX 7 for Visual Basic Type Library', 'D3DCLIPSTATUS')
- * variable = tobj.variables.find {|variable| variable.name == 'lFlags'}
- * tdetail = variable.ole_type_detail
- * p tdetail # => ["USERDEFINED", "CONST_D3DCLIPSTATUSFLAGS"]
- *
- */
-static VALUE
-folevariable_ole_type_detail(VALUE self)
-{
- struct olevariabledata *pvar;
- TypedData_Get_Struct(self, struct olevariabledata, &olevariable_datatype, pvar);
- return ole_variable_ole_type_detail(pvar->pTypeInfo, pvar->index);
-}
-
-static VALUE
-ole_variable_value(ITypeInfo *pTypeInfo, UINT var_index)
-{
- VARDESC *pVarDesc;
- HRESULT hr;
- VALUE val = Qnil;
- hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
- if (FAILED(hr))
- return Qnil;
- if(pVarDesc->varkind == VAR_CONST)
- val = ole_variant2val(V_UNION1(pVarDesc, lpvarValue));
- pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
- return val;
-}
-
-/*
- * call-seq:
- * value
- *
- * Returns value if value is exists. If the value does not exist,
- * this method returns nil.
- *
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
- * variables = tobj.variables
- * variables.each do |variable|
- * puts "#{variable.name} #{variable.value}"
- * end
- *
- * The result of above script is following:
- * xlChart = -4109
- * xlDialogSheet = -4116
- * xlExcel4IntlMacroSheet = 4
- * xlExcel4MacroSheet = 3
- * xlWorksheet = -4167
- *
- */
-static VALUE
-folevariable_value(VALUE self)
-{
- struct olevariabledata *pvar;
- TypedData_Get_Struct(self, struct olevariabledata, &olevariable_datatype, pvar);
- return ole_variable_value(pvar->pTypeInfo, pvar->index);
-}
-
-static VALUE
-ole_variable_visible(ITypeInfo *pTypeInfo, UINT var_index)
-{
- VARDESC *pVarDesc;
- HRESULT hr;
- VALUE visible = Qfalse;
- hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
- if (FAILED(hr))
- return visible;
- if (!(pVarDesc->wVarFlags & (VARFLAG_FHIDDEN |
- VARFLAG_FRESTRICTED |
- VARFLAG_FNONBROWSABLE))) {
- visible = Qtrue;
- }
- pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
- return visible;
-}
-
-/*
- * call-seq:
- * visible?
- *
- * Returns true if the variable is public.
- *
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
- * variables = tobj.variables
- * variables.each do |variable|
- * puts "#{variable.name} #{variable.visible?}"
- * end
- *
- * The result of above script is following:
- * xlChart true
- * xlDialogSheet true
- * xlExcel4IntlMacroSheet true
- * xlExcel4MacroSheet true
- * xlWorksheet true
- *
- */
-static VALUE
-folevariable_visible(VALUE self)
-{
- struct olevariabledata *pvar;
- TypedData_Get_Struct(self, struct olevariabledata, &olevariable_datatype, pvar);
- return ole_variable_visible(pvar->pTypeInfo, pvar->index);
-}
-
-static VALUE
-ole_variable_kind(ITypeInfo *pTypeInfo, UINT var_index)
-{
- VARDESC *pVarDesc;
- HRESULT hr;
- VALUE kind = rb_str_new2("UNKNOWN");
- hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
- if (FAILED(hr))
- return kind;
- switch(pVarDesc->varkind) {
- case VAR_PERINSTANCE:
- kind = rb_str_new2("PERINSTANCE");
- break;
- case VAR_STATIC:
- kind = rb_str_new2("STATIC");
- break;
- case VAR_CONST:
- kind = rb_str_new2("CONSTANT");
- break;
- case VAR_DISPATCH:
- kind = rb_str_new2("DISPATCH");
- break;
- default:
- break;
- }
- pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
- return kind;
-}
-
-/*
- * call-seq:
- * variable_kind
- *
- * Returns variable kind string.
- *
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
- * variables = tobj.variables
- * variables.each do |variable|
- * puts "#{variable.name} #{variable.variable_kind}"
- * end
- *
- * The result of above script is following:
- * xlChart CONSTANT
- * xlDialogSheet CONSTANT
- * xlExcel4IntlMacroSheet CONSTANT
- * xlExcel4MacroSheet CONSTANT
- * xlWorksheet CONSTANT
- */
-static VALUE
-folevariable_variable_kind(VALUE self)
-{
- struct olevariabledata *pvar;
- TypedData_Get_Struct(self, struct olevariabledata, &olevariable_datatype, pvar);
- return ole_variable_kind(pvar->pTypeInfo, pvar->index);
-}
-
-static VALUE
-ole_variable_varkind(ITypeInfo *pTypeInfo, UINT var_index)
-{
- VARDESC *pVarDesc;
- HRESULT hr;
- VALUE kind = Qnil;
- hr = pTypeInfo->lpVtbl->GetVarDesc(pTypeInfo, var_index, &pVarDesc);
- if (FAILED(hr))
- return kind;
- pTypeInfo->lpVtbl->ReleaseVarDesc(pTypeInfo, pVarDesc);
- kind = RB_INT2FIX(pVarDesc->varkind);
- return kind;
-}
-
-/*
- * call-seq:
- * varkind
- *
- * Returns the number which represents variable kind.
- * tobj = WIN32OLE::Type.new('Microsoft Excel 9.0 Object Library', 'XlSheetType')
- * variables = tobj.variables
- * variables.each do |variable|
- * puts "#{variable.name} #{variable.varkind}"
- * end
- *
- * The result of above script is following:
- * xlChart 2
- * xlDialogSheet 2
- * xlExcel4IntlMacroSheet 2
- * xlExcel4MacroSheet 2
- * xlWorksheet 2
- */
-static VALUE
-folevariable_varkind(VALUE self)
-{
- struct olevariabledata *pvar;
- TypedData_Get_Struct(self, struct olevariabledata, &olevariable_datatype, pvar);
- return ole_variable_varkind(pvar->pTypeInfo, pvar->index);
-}
-
-/*
- * call-seq:
- * inspect -> String
- *
- * Returns the OLE variable name and the value with class name.
- *
- */
-static VALUE
-folevariable_inspect(VALUE self)
-{
- VALUE v = rb_inspect(folevariable_value(self));
- VALUE n = folevariable_name(self);
- VALUE detail = rb_sprintf("%"PRIsVALUE"=%"PRIsVALUE, n, v);
- return make_inspect("WIN32OLE::Variable", detail);
-}
-
-VALUE cWIN32OLE_VARIABLE;
-
-void Init_win32ole_variable(void)
-{
- cWIN32OLE_VARIABLE = rb_define_class_under(cWIN32OLE, "Variable", rb_cObject);
- /* Alias of WIN32OLE::Variable, for the backward compatibility */
- rb_define_const(rb_cObject, "WIN32OLE_VARIABLE", cWIN32OLE_VARIABLE);
- rb_undef_alloc_func(cWIN32OLE_VARIABLE);
- rb_define_method(cWIN32OLE_VARIABLE, "name", folevariable_name, 0);
- rb_define_method(cWIN32OLE_VARIABLE, "ole_type", folevariable_ole_type, 0);
- rb_define_method(cWIN32OLE_VARIABLE, "ole_type_detail", folevariable_ole_type_detail, 0);
- rb_define_method(cWIN32OLE_VARIABLE, "value", folevariable_value, 0);
- rb_define_method(cWIN32OLE_VARIABLE, "visible?", folevariable_visible, 0);
- rb_define_method(cWIN32OLE_VARIABLE, "variable_kind", folevariable_variable_kind, 0);
- rb_define_method(cWIN32OLE_VARIABLE, "varkind", folevariable_varkind, 0);
- rb_define_method(cWIN32OLE_VARIABLE, "inspect", folevariable_inspect, 0);
- rb_define_alias(cWIN32OLE_VARIABLE, "to_s", "name");
-}
diff --git a/ext/win32ole/win32ole_variable.h b/ext/win32ole/win32ole_variable.h
deleted file mode 100644
index 209613fd44..0000000000
--- a/ext/win32ole/win32ole_variable.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef WIN32OLE_VARIABLE_H
-#define WIN32OLE_VARIABLE_H 1
-
-extern VALUE cWIN32OLE_VARIABLE;
-VALUE create_win32ole_variable(ITypeInfo *pTypeInfo, UINT index, VALUE name);
-void Init_win32ole_variable(void);
-
-#endif
diff --git a/ext/win32ole/win32ole_variant.c b/ext/win32ole/win32ole_variant.c
deleted file mode 100644
index 45c70b1dc3..0000000000
--- a/ext/win32ole/win32ole_variant.c
+++ /dev/null
@@ -1,737 +0,0 @@
-#include "win32ole.h"
-
-struct olevariantdata {
- VARIANT realvar;
- VARIANT var;
-};
-
-static void olevariant_free(void *ptr);
-static size_t olevariant_size(const void *ptr);
-static void ole_val2olevariantdata(VALUE val, VARTYPE vt, struct olevariantdata *pvar);
-static void ole_val2variant_err(VALUE val, VARIANT *var);
-static void ole_set_byref(VARIANT *realvar, VARIANT *var, VARTYPE vt);
-static VALUE folevariant_s_allocate(VALUE klass);
-static VALUE folevariant_s_array(VALUE klass, VALUE dims, VALUE vvt);
-static void check_type_val2variant(VALUE val);
-static VALUE folevariant_initialize(VALUE self, VALUE args);
-static LONG *ary2safe_array_index(int ary_size, VALUE *ary, SAFEARRAY *psa);
-static void unlock_safe_array(SAFEARRAY *psa);
-static SAFEARRAY *get_locked_safe_array(VALUE val);
-static VALUE folevariant_ary_aref(int argc, VALUE *argv, VALUE self);
-static VALUE folevariant_ary_aset(int argc, VALUE *argv, VALUE self);
-static VALUE folevariant_value(VALUE self);
-static VALUE folevariant_vartype(VALUE self);
-static VALUE folevariant_set_value(VALUE self, VALUE val);
-
-static const rb_data_type_t olevariant_datatype = {
- "win32ole_variant",
- {NULL, olevariant_free, olevariant_size,},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
-};
-
-static void
-olevariant_free(void *ptr)
-{
- struct olevariantdata *pvar = ptr;
- VariantClear(&(pvar->realvar));
- VariantClear(&(pvar->var));
- free(pvar);
-}
-
-static size_t
-olevariant_size(const void *ptr)
-{
- return ptr ? sizeof(struct olevariantdata) : 0;
-}
-
-static void
-ole_val2olevariantdata(VALUE val, VARTYPE vt, struct olevariantdata *pvar)
-{
- HRESULT hr = S_OK;
-
- if (((vt & ~VT_BYREF) == (VT_ARRAY | VT_UI1)) && RB_TYPE_P(val, T_STRING)) {
- long len = RSTRING_LEN(val);
- void *pdest = NULL;
- SAFEARRAY *p = NULL;
- SAFEARRAY *psa = SafeArrayCreateVector(VT_UI1, 0, len);
- if (!psa) {
- rb_raise(rb_eRuntimeError, "fail to SafeArrayCreateVector");
- }
- hr = SafeArrayAccessData(psa, &pdest);
- if (SUCCEEDED(hr)) {
- memcpy(pdest, RSTRING_PTR(val), len);
- SafeArrayUnaccessData(psa);
- V_VT(&(pvar->realvar)) = (vt & ~VT_BYREF);
- p = V_ARRAY(&(pvar->realvar));
- if (p != NULL) {
- SafeArrayDestroy(p);
- }
- V_ARRAY(&(pvar->realvar)) = psa;
- if (vt & VT_BYREF) {
- V_VT(&(pvar->var)) = vt;
- V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
- } else {
- hr = VariantCopy(&(pvar->var), &(pvar->realvar));
- }
- } else {
- if (psa)
- SafeArrayDestroy(psa);
- }
- } else if (vt & VT_ARRAY) {
- if (val == Qnil) {
- V_VT(&(pvar->var)) = vt;
- if (vt & VT_BYREF) {
- V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
- }
- } else {
- hr = ole_val_ary2variant_ary(val, &(pvar->realvar), (VARTYPE)(vt & ~VT_BYREF));
- if (SUCCEEDED(hr)) {
- if (vt & VT_BYREF) {
- V_VT(&(pvar->var)) = vt;
- V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
- } else {
- hr = VariantCopy(&(pvar->var), &(pvar->realvar));
- }
- }
- }
-#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));
- V_VT(&(pvar->var)) = vt;
- if (vt & VT_BYREF) {
- ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
- }
-#endif
- } else if ( (vt & ~VT_BYREF) == VT_ERROR) {
- ole_val2variant_err(val, &(pvar->realvar));
- if (vt & VT_BYREF) {
- ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
- } else {
- hr = VariantCopy(&(pvar->var), &(pvar->realvar));
- }
- } else {
- if (val == Qnil) {
- V_VT(&(pvar->var)) = vt;
- if (vt == (VT_BYREF | VT_VARIANT)) {
- ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
- } else {
- V_VT(&(pvar->realvar)) = vt & ~VT_BYREF;
- if (vt & VT_BYREF) {
- ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
- }
- }
- } else {
- ole_val2variant_ex(val, &(pvar->realvar), (VARTYPE)(vt & ~VT_BYREF));
- if (vt == (VT_BYREF | VT_VARIANT)) {
- ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
- } else if (vt & VT_BYREF) {
- if ( (vt & ~VT_BYREF) != V_VT(&(pvar->realvar))) {
- hr = VariantChangeTypeEx(&(pvar->realvar), &(pvar->realvar),
- cWIN32OLE_lcid, 0, (VARTYPE)(vt & ~VT_BYREF));
- }
- if (SUCCEEDED(hr)) {
- ole_set_byref(&(pvar->realvar), &(pvar->var), vt);
- }
- } else {
- if (vt == V_VT(&(pvar->realvar))) {
- hr = VariantCopy(&(pvar->var), &(pvar->realvar));
- } else {
- hr = VariantChangeTypeEx(&(pvar->var), &(pvar->realvar),
- cWIN32OLE_lcid, 0, vt);
- }
- }
- }
- }
- if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLERuntimeError, "failed to change type");
- }
-}
-
-static void
-ole_val2variant_err(VALUE val, VARIANT *var)
-{
- VALUE v = val;
- if (rb_obj_is_kind_of(v, cWIN32OLE_VARIANT)) {
- v = folevariant_value(v);
- }
- if (!(FIXNUM_P(v) || RB_TYPE_P(v, T_BIGNUM) || v == Qnil)) {
- rb_raise(eWIN32OLERuntimeError, "failed to convert VT_ERROR VARIANT:`%"PRIsVALUE"'", rb_inspect(v));
- }
- V_VT(var) = VT_ERROR;
- if (v != Qnil) {
- V_ERROR(var) = RB_NUM2LONG(val);
- } else {
- V_ERROR(var) = 0;
- }
-}
-
-static void
-ole_set_byref(VARIANT *realvar, VARIANT *var, VARTYPE vt)
-{
- V_VT(var) = vt;
- if (vt == (VT_VARIANT|VT_BYREF)) {
- V_VARIANTREF(var) = realvar;
- } else {
- if (V_VT(realvar) != (vt & ~VT_BYREF)) {
- rb_raise(eWIN32OLERuntimeError, "variant type mismatch");
- }
- switch(vt & ~VT_BYREF) {
- case VT_I1:
- V_I1REF(var) = &V_I1(realvar);
- break;
- case VT_UI1:
- V_UI1REF(var) = &V_UI1(realvar);
- break;
- case VT_I2:
- V_I2REF(var) = &V_I2(realvar);
- break;
- case VT_UI2:
- V_UI2REF(var) = &V_UI2(realvar);
- break;
- case VT_I4:
- V_I4REF(var) = &V_I4(realvar);
- break;
- case VT_UI4:
- V_UI4REF(var) = &V_UI4(realvar);
- break;
- case VT_R4:
- V_R4REF(var) = &V_R4(realvar);
- break;
- case VT_R8:
- V_R8REF(var) = &V_R8(realvar);
- break;
-
-#if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__CYGWIN__) || defined(__MINGW32__)
-#ifdef V_I8REF
- case VT_I8:
- V_I8REF(var) = &V_I8(realvar);
- break;
-#endif
-#ifdef V_UI8REF
- case VT_UI8:
- V_UI8REF(var) = &V_UI8(realvar);
- break;
-#endif
-#endif
- case VT_INT:
- V_INTREF(var) = &V_INT(realvar);
- break;
-
- case VT_UINT:
- V_UINTREF(var) = &V_UINT(realvar);
- break;
-
- case VT_CY:
- V_CYREF(var) = &V_CY(realvar);
- break;
- case VT_DATE:
- V_DATEREF(var) = &V_DATE(realvar);
- break;
- case VT_BSTR:
- V_BSTRREF(var) = &V_BSTR(realvar);
- break;
- case VT_DISPATCH:
- V_DISPATCHREF(var) = &V_DISPATCH(realvar);
- break;
- case VT_ERROR:
- V_ERRORREF(var) = &V_ERROR(realvar);
- break;
- case VT_BOOL:
- V_BOOLREF(var) = &V_BOOL(realvar);
- break;
- case VT_UNKNOWN:
- V_UNKNOWNREF(var) = &V_UNKNOWN(realvar);
- break;
- case VT_ARRAY:
- V_ARRAYREF(var) = &V_ARRAY(realvar);
- break;
- default:
- rb_raise(eWIN32OLERuntimeError, "unknown type specified(setting BYREF):%d", vt);
- break;
- }
- }
-}
-
-static VALUE
-folevariant_s_allocate(VALUE klass)
-{
- struct olevariantdata *pvar;
- VALUE obj;
- ole_initialize();
- obj = TypedData_Make_Struct(klass, struct olevariantdata, &olevariant_datatype, pvar);
- VariantInit(&(pvar->var));
- VariantInit(&(pvar->realvar));
- return obj;
-}
-
-/*
- * call-seq:
- * array(ary, vt)
- *
- * Returns Ruby object wrapping OLE variant whose variant type is VT_ARRAY.
- * The first argument should be Array object which specifies dimensions
- * and each size of dimensions of OLE array.
- * The second argument specifies variant type of the element of OLE array.
- *
- * The following create 2 dimensions OLE array. The first dimensions size
- * is 3, and the second is 4.
- *
- * ole_ary = WIN32OLE::Variant.array([3,4], VT_I4)
- * ruby_ary = ole_ary.value # => [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
- *
- */
-static VALUE
-folevariant_s_array(VALUE klass, VALUE elems, VALUE vvt)
-{
- VALUE obj = Qnil;
- VARTYPE vt;
- struct olevariantdata *pvar;
- SAFEARRAYBOUND *psab = NULL;
- SAFEARRAY *psa = NULL;
- UINT dim = 0;
- UINT i = 0;
-
- ole_initialize();
-
- vt = RB_NUM2UINT(vvt);
- vt = (vt | VT_ARRAY);
- Check_Type(elems, T_ARRAY);
- obj = folevariant_s_allocate(klass);
-
- TypedData_Get_Struct(obj, struct olevariantdata, &olevariant_datatype, pvar);
- dim = RARRAY_LEN(elems);
-
- psab = ALLOC_N(SAFEARRAYBOUND, dim);
-
- if(!psab) {
- rb_raise(rb_eRuntimeError, "memory allocation error");
- }
-
- for (i = 0; i < dim; i++) {
- psab[i].cElements = RB_FIX2INT(rb_ary_entry(elems, i));
- psab[i].lLbound = 0;
- }
-
- psa = SafeArrayCreate((VARTYPE)(vt & VT_TYPEMASK), dim, psab);
- if (psa == NULL) {
- if (psab) free(psab);
- rb_raise(rb_eRuntimeError, "memory allocation error(SafeArrayCreate)");
- }
-
- V_VT(&(pvar->var)) = vt;
- if (vt & VT_BYREF) {
- V_VT(&(pvar->realvar)) = (vt & ~VT_BYREF);
- V_ARRAY(&(pvar->realvar)) = psa;
- V_ARRAYREF(&(pvar->var)) = &(V_ARRAY(&(pvar->realvar)));
- } else {
- V_ARRAY(&(pvar->var)) = psa;
- }
- if (psab) free(psab);
- return obj;
-}
-
-static void
-check_type_val2variant(VALUE val)
-{
- VALUE elem;
- int len = 0;
- int i = 0;
- if(!rb_obj_is_kind_of(val, cWIN32OLE) &&
- !rb_obj_is_kind_of(val, cWIN32OLE_VARIANT) &&
- !rb_obj_is_kind_of(val, rb_cTime)) {
- switch (TYPE(val)) {
- case T_ARRAY:
- len = RARRAY_LEN(val);
- for(i = 0; i < len; i++) {
- elem = rb_ary_entry(val, i);
- check_type_val2variant(elem);
- }
- break;
- case T_STRING:
- case T_FIXNUM:
- case T_BIGNUM:
- case T_FLOAT:
- case T_TRUE:
- case T_FALSE:
- case T_NIL:
- break;
- default:
- rb_raise(rb_eTypeError, "can not convert WIN32OLE::Variant from type %s",
- rb_obj_classname(val));
- }
- }
-}
-
-/*
- * Document-class: WIN32OLE::Variant
- *
- * +WIN32OLE::Variant+ objects represents OLE variant.
- *
- * 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 specified variant type by using WIN32OLE::Variant class.
- *
- * param = WIN32OLE::Variant.new(10, WIN32OLE::VARIANT::VT_R4)
- * oleobj.method(param)
- *
- * WIN32OLE::Variant does not support VT_RECORD variant. Use WIN32OLE::Record
- * class instead of WIN32OLE::Variant if the VT_RECORD variant is needed.
- */
-
-/*
- * call-seq:
- * new(val, vartype) #=> WIN32OLE::Variant object.
- *
- * Returns Ruby object wrapping OLE variant.
- * The first argument specifies Ruby object to convert OLE variant variable.
- * The second argument specifies VARIANT type.
- * In some situation, you need the WIN32OLE::Variant object to pass OLE method
- *
- * shell = WIN32OLE.new("Shell.Application")
- * folder = shell.NameSpace("C:\\Windows")
- * item = folder.ParseName("tmp.txt")
- * # You can't use Ruby String object to call FolderItem.InvokeVerb.
- * # Instead, you have to use WIN32OLE::Variant object to call the method.
- * shortcut = WIN32OLE::Variant.new("Create Shortcut(\&S)")
- * item.invokeVerb(shortcut)
- *
- */
-static VALUE
-folevariant_initialize(VALUE self, VALUE args)
-{
- int len = 0;
- VARIANT var;
- VALUE val;
- VALUE vvt;
- VARTYPE vt;
- struct olevariantdata *pvar;
-
- len = RARRAY_LEN(args);
- rb_check_arity(len, 1, 3);
- VariantInit(&var);
- val = rb_ary_entry(args, 0);
-
- check_type_val2variant(val);
-
- TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, pvar);
- if (len == 1) {
- ole_val2variant(val, &(pvar->var));
- } else {
- vvt = rb_ary_entry(args, 1);
- vt = RB_NUM2INT(vvt);
- if ((vt & VT_TYPEMASK) == VT_RECORD) {
- rb_raise(rb_eArgError, "not supported VT_RECORD WIN32OLE::Variant object");
- }
- ole_val2olevariantdata(val, vt, pvar);
- }
- return self;
-}
-
-static SAFEARRAY *
-get_locked_safe_array(VALUE val)
-{
- struct olevariantdata *pvar;
- SAFEARRAY *psa = NULL;
- HRESULT hr;
- TypedData_Get_Struct(val, struct olevariantdata, &olevariant_datatype, pvar);
- if (!(V_VT(&(pvar->var)) & VT_ARRAY)) {
- rb_raise(rb_eTypeError, "variant type is not VT_ARRAY.");
- }
- psa = V_ISBYREF(&(pvar->var)) ? *V_ARRAYREF(&(pvar->var)) : V_ARRAY(&(pvar->var));
- if (psa == NULL) {
- return psa;
- }
- hr = SafeArrayLock(psa);
- if (FAILED(hr)) {
- ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayLock");
- }
- return psa;
-}
-
-static LONG *
-ary2safe_array_index(int ary_size, VALUE *ary, SAFEARRAY *psa)
-{
- long dim;
- LONG *pid;
- long i;
- dim = SafeArrayGetDim(psa);
- if (dim != ary_size) {
- rb_raise(rb_eArgError, "unmatch number of indices");
- }
- pid = ALLOC_N(LONG, dim);
- if (pid == NULL) {
- rb_raise(rb_eRuntimeError, "failed to allocate memory for indices");
- }
- for (i = 0; i < dim; i++) {
- pid[i] = RB_NUM2INT(ary[i]);
- }
- return pid;
-}
-
-static void
-unlock_safe_array(SAFEARRAY *psa)
-{
- HRESULT hr;
- hr = SafeArrayUnlock(psa);
- if (FAILED(hr)) {
- ole_raise(hr, rb_eRuntimeError, "failed to SafeArrayUnlock");
- }
-}
-
-/*
- * call-seq:
- * variant[i,j,...] #=> element of OLE array.
- *
- * Returns the element of WIN32OLE::Variant object(OLE array).
- * This method is available only when the variant type of
- * WIN32OLE::Variant object is VT_ARRAY.
- *
- * REMARK:
- * The all indices should be 0 or natural number and
- * lower than or equal to max indices.
- * (This point is different with Ruby Array indices.)
- *
- * obj = WIN32OLE::Variant.new([[1,2,3],[4,5,6]])
- * p obj[0,0] # => 1
- * p obj[1,0] # => 4
- * p obj[2,0] # => WIN32OLE::RuntimeError
- * p obj[0, -1] # => WIN32OLE::RuntimeError
- *
- */
-static VALUE
-folevariant_ary_aref(int argc, VALUE *argv, VALUE self)
-{
- struct olevariantdata *pvar;
- SAFEARRAY *psa;
- VALUE val = Qnil;
- VARIANT variant;
- LONG *pid;
- HRESULT hr;
-
- TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, pvar);
- if (!V_ISARRAY(&(pvar->var))) {
- rb_raise(eWIN32OLERuntimeError,
- "`[]' is not available for this variant type object");
- }
- psa = get_locked_safe_array(self);
- if (psa == NULL) {
- return val;
- }
-
- pid = ary2safe_array_index(argc, argv, psa);
-
- VariantInit(&variant);
- V_VT(&variant) = (V_VT(&(pvar->var)) & ~VT_ARRAY) | VT_BYREF;
- hr = SafeArrayPtrOfIndex(psa, pid, &V_BYREF(&variant));
- if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLERuntimeError, "failed to SafeArrayPtrOfIndex");
- }
- val = ole_variant2val(&variant);
-
- unlock_safe_array(psa);
- if (pid) free(pid);
- return val;
-}
-
-/*
- * call-seq:
- * variant[i,j,...] = val #=> set the element of OLE array
- *
- * Set the element of WIN32OLE::Variant object(OLE array) to val.
- * This method is available only when the variant type of
- * WIN32OLE::Variant object is VT_ARRAY.
- *
- * REMARK:
- * The all indices should be 0 or natural number and
- * lower than or equal to max indices.
- * (This point is different with Ruby Array indices.)
- *
- * obj = WIN32OLE::Variant.new([[1,2,3],[4,5,6]])
- * obj[0,0] = 7
- * obj[1,0] = 8
- * p obj.value # => [[7,2,3], [8,5,6]]
- * obj[2,0] = 9 # => WIN32OLE::RuntimeError
- * obj[0, -1] = 9 # => WIN32OLE::RuntimeError
- *
- */
-static VALUE
-folevariant_ary_aset(int argc, VALUE *argv, VALUE self)
-{
- struct olevariantdata *pvar;
- SAFEARRAY *psa;
- VARIANT var;
- VARTYPE vt;
- LONG *pid;
- HRESULT hr;
- VOID *p = NULL;
-
- TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, pvar);
- if (!V_ISARRAY(&(pvar->var))) {
- rb_raise(eWIN32OLERuntimeError,
- "`[]' is not available for this variant type object");
- }
- psa = get_locked_safe_array(self);
- if (psa == NULL) {
- rb_raise(rb_eRuntimeError, "failed to get SafeArray pointer");
- }
-
- pid = ary2safe_array_index(argc-1, argv, psa);
-
- VariantInit(&var);
- vt = (V_VT(&(pvar->var)) & ~VT_ARRAY);
- p = val2variant_ptr(argv[argc-1], &var, vt);
- if ((V_VT(&var) == VT_DISPATCH && V_DISPATCH(&var) == NULL) ||
- (V_VT(&var) == VT_UNKNOWN && V_UNKNOWN(&var) == NULL)) {
- rb_raise(eWIN32OLERuntimeError, "argument does not have IDispatch or IUnknown Interface");
- }
- hr = SafeArrayPutElement(psa, pid, p);
- if (FAILED(hr)) {
- ole_raise(hr, eWIN32OLERuntimeError, "failed to SafeArrayPutElement");
- }
-
- unlock_safe_array(psa);
- if (pid) free(pid);
- return argv[argc-1];
-}
-
-/*
- * call-seq:
- * value #=> Ruby object.
- *
- * Returns Ruby object value from OLE variant.
- * obj = WIN32OLE::Variant.new(1, WIN32OLE::VARIANT::VT_BSTR)
- * obj.value # => "1" (not Integer object, but String object "1")
- *
- */
-static VALUE
-folevariant_value(VALUE self)
-{
- struct olevariantdata *pvar;
- VALUE val = Qnil;
- VARTYPE vt;
- int dim;
- SAFEARRAY *psa;
- TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, pvar);
-
- val = ole_variant2val(&(pvar->var));
- vt = V_VT(&(pvar->var));
-
- if ((vt & ~VT_BYREF) == (VT_UI1|VT_ARRAY)) {
- if (vt & VT_BYREF) {
- psa = *V_ARRAYREF(&(pvar->var));
- } else {
- psa = V_ARRAY(&(pvar->var));
- }
- if (!psa) {
- return val;
- }
- dim = SafeArrayGetDim(psa);
- if (dim == 1) {
- val = rb_funcall(val, rb_intern("pack"), 1, rb_str_new2("C*"));
- }
- }
- return val;
-}
-
-/*
- * call-seq:
- * vartype #=> OLE variant type.
- *
- * Returns OLE variant type.
- * obj = WIN32OLE::Variant.new("string")
- * obj.vartype # => WIN32OLE::VARIANT::VT_BSTR
- *
- */
-static VALUE
-folevariant_vartype(VALUE self)
-{
- struct olevariantdata *pvar;
- TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, pvar);
- return RB_INT2FIX(V_VT(&pvar->var));
-}
-
-/*
- * call-seq:
- * variant.value = val #=> set WIN32OLE::Variant value to val.
- *
- * Sets variant value to val. If the val type does not match variant value
- * type(vartype), then val is changed to match variant value type(vartype)
- * before setting val.
- * This method is not available when vartype is VT_ARRAY(except VT_UI1|VT_ARRAY).
- * If the vartype is VT_UI1|VT_ARRAY, the val should be String object.
- *
- * obj = WIN32OLE::Variant.new(1) # obj.vartype is WIN32OLE::VARIANT::VT_I4
- * obj.value = 3.2 # 3.2 is changed to 3 when setting value.
- * p obj.value # => 3
- */
-static VALUE
-folevariant_set_value(VALUE self, VALUE val)
-{
- struct olevariantdata *pvar;
- VARTYPE vt;
- TypedData_Get_Struct(self, struct olevariantdata, &olevariant_datatype, pvar);
- vt = V_VT(&(pvar->var));
- if (V_ISARRAY(&(pvar->var)) && ((vt & ~VT_BYREF) != (VT_UI1|VT_ARRAY) || !RB_TYPE_P(val, T_STRING))) {
- rb_raise(eWIN32OLERuntimeError,
- "`value=' is not available for this variant type object");
- }
- ole_val2olevariantdata(val, vt, pvar);
- return Qnil;
-}
-
-void
-ole_variant2variant(VALUE val, VARIANT *var)
-{
- struct olevariantdata *pvar;
- TypedData_Get_Struct(val, struct olevariantdata, &olevariant_datatype, pvar);
- VariantCopy(var, &(pvar->var));
-}
-
-VALUE cWIN32OLE_VARIANT;
-
-void
-Init_win32ole_variant(void)
-{
-#undef rb_intern
- cWIN32OLE_VARIANT = rb_define_class_under(cWIN32OLE, "Variant", rb_cObject);
- /* Alias of WIN32OLE::Variant, for the backward compatibility */
- rb_define_const(rb_cObject, "WIN32OLE_VARIANT", cWIN32OLE_VARIANT);
- rb_define_alloc_func(cWIN32OLE_VARIANT, folevariant_s_allocate);
- rb_define_singleton_method(cWIN32OLE_VARIANT, "array", folevariant_s_array, 2);
- rb_define_method(cWIN32OLE_VARIANT, "initialize", folevariant_initialize, -2);
- rb_define_method(cWIN32OLE_VARIANT, "value", folevariant_value, 0);
- rb_define_method(cWIN32OLE_VARIANT, "value=", folevariant_set_value, 1);
- rb_define_method(cWIN32OLE_VARIANT, "vartype", folevariant_vartype, 0);
- rb_define_method(cWIN32OLE_VARIANT, "[]", folevariant_ary_aref, -1);
- rb_define_method(cWIN32OLE_VARIANT, "[]=", folevariant_ary_aset, -1);
-
- /*
- * represents VT_EMPTY OLE object.
- */
- rb_define_const(cWIN32OLE_VARIANT, "Empty",
- rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, RB_INT2FIX(VT_EMPTY)));
-
- /*
- * represents VT_NULL OLE object.
- */
- rb_define_const(cWIN32OLE_VARIANT, "Null",
- rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, RB_INT2FIX(VT_NULL)));
-
- /*
- * represents Nothing of VB.NET or VB.
- */
- rb_define_const(cWIN32OLE_VARIANT, "Nothing",
- rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, Qnil, RB_INT2FIX(VT_DISPATCH)));
-
- /*
- * represents VT_ERROR variant with DISP_E_PARAMNOTFOUND.
- * This constants is used for not specified parameter.
- *
- * fso = WIN32OLE.new("Scripting.FileSystemObject")
- * fso.openTextFile(filename, WIN32OLE::Variant::NoParam, false)
- */
- rb_define_const(cWIN32OLE_VARIANT, "NoParam",
- rb_funcall(cWIN32OLE_VARIANT, rb_intern("new"), 2, INT2NUM(DISP_E_PARAMNOTFOUND), RB_INT2FIX(VT_ERROR)));
-}
diff --git a/ext/win32ole/win32ole_variant.h b/ext/win32ole/win32ole_variant.h
deleted file mode 100644
index 4bd3b0aeea..0000000000
--- a/ext/win32ole/win32ole_variant.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef WIN32OLE_VARIANT_H
-#define WIN32OLE_VARIANT_H 1
-
-extern VALUE cWIN32OLE_VARIANT;
-void ole_variant2variant(VALUE val, VARIANT *var);
-void Init_win32ole_variant(void);
-
-#endif
-
diff --git a/ext/win32ole/win32ole_variant_m.c b/ext/win32ole/win32ole_variant_m.c
deleted file mode 100644
index d879506be3..0000000000
--- a/ext/win32ole/win32ole_variant_m.c
+++ /dev/null
@@ -1,153 +0,0 @@
-#include "win32ole.h"
-
-VALUE mWIN32OLE_VARIANT;
-
-void Init_win32ole_variant_m(void)
-{
- /*
- * Document-module: WIN32OLE::VariantType
- *
- * The +WIN32OLE::VariantType+ module includes constants of VARIANT type constants.
- * The constants is used when creating WIN32OLE::Variant object.
- *
- * obj = WIN32OLE::Variant.new("2e3", WIN32OLE::VARIANT::VT_R4)
- * obj.value # => 2000.0
- *
- */
- mWIN32OLE_VARIANT = rb_define_module_under(cWIN32OLE, "VariantType");
- /* Alias of WIN32OLE::VariantType, for the backward compatibility */
- rb_define_const(cWIN32OLE, "VARIANT", mWIN32OLE_VARIANT);
-
- /*
- * represents VT_EMPTY type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_EMPTY", RB_INT2FIX(VT_EMPTY));
-
- /*
- * represents VT_NULL type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_NULL", RB_INT2FIX(VT_NULL));
-
- /*
- * represents VT_I2 type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_I2", RB_INT2FIX(VT_I2));
-
- /*
- * represents VT_I4 type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_I4", RB_INT2FIX(VT_I4));
-
- /*
- * represents VT_R4 type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_R4", RB_INT2FIX(VT_R4));
-
- /*
- * represents VT_R8 type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_R8", RB_INT2FIX(VT_R8));
-
- /*
- * represents VT_CY type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_CY", RB_INT2FIX(VT_CY));
-
- /*
- * represents VT_DATE type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_DATE", RB_INT2FIX(VT_DATE));
-
- /*
- * represents VT_BSTR type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_BSTR", RB_INT2FIX(VT_BSTR));
-
- /*
- * represents VT_USERDEFINED type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_USERDEFINED", RB_INT2FIX(VT_USERDEFINED));
-
- /*
- * represents VT_PTR type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_PTR", RB_INT2FIX(VT_PTR));
-
- /*
- * represents VT_DISPATCH type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_DISPATCH", RB_INT2FIX(VT_DISPATCH));
-
- /*
- * represents VT_ERROR type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_ERROR", RB_INT2FIX(VT_ERROR));
-
- /*
- * represents VT_BOOL type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_BOOL", RB_INT2FIX(VT_BOOL));
-
- /*
- * represents VT_VARIANT type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_VARIANT", RB_INT2FIX(VT_VARIANT));
-
- /*
- * represents VT_UNKNOWN type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_UNKNOWN", RB_INT2FIX(VT_UNKNOWN));
-
- /*
- * represents VT_I1 type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_I1", RB_INT2FIX(VT_I1));
-
- /*
- * represents VT_UI1 type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_UI1", RB_INT2FIX(VT_UI1));
-
- /*
- * represents VT_UI2 type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_UI2", RB_INT2FIX(VT_UI2));
-
- /*
- * represents VT_UI4 type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_UI4", RB_INT2FIX(VT_UI4));
-
-#if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__CYGWIN__) || defined(__MINGW32__)
- /*
- * represents VT_I8 type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_I8", RB_INT2FIX(VT_I8));
-
- /*
- * represents VT_UI8 type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_UI8", RB_INT2FIX(VT_UI8));
-#endif
-
- /*
- * represents VT_INT type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_INT", RB_INT2FIX(VT_INT));
-
- /*
- * represents VT_UINT type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_UINT", RB_INT2FIX(VT_UINT));
-
- /*
- * represents VT_ARRAY type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_ARRAY", RB_INT2FIX(VT_ARRAY));
-
- /*
- * represents VT_BYREF type constant.
- */
- rb_define_const(mWIN32OLE_VARIANT, "VT_BYREF", RB_INT2FIX(VT_BYREF));
-
-}
diff --git a/ext/win32ole/win32ole_variant_m.h b/ext/win32ole/win32ole_variant_m.h
deleted file mode 100644
index 6272a6578f..0000000000
--- a/ext/win32ole/win32ole_variant_m.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef WIN32OLE_VARIANT_M_H
-#define WIN32OLE_VARIANT_M_H 1
-
-extern VALUE mWIN32OLE_VARIANT;
-void Init_win32ole_variant_m(void);
-
-#endif
diff --git a/ext/zlib/depend b/ext/zlib/depend
index bdce420264..22e9ca867a 100644
--- a/ext/zlib/depend
+++ b/ext/zlib/depend
@@ -138,6 +138,7 @@ 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/set.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
diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
index aad9f8d28a..7e319cae0d 100644
--- a/ext/zlib/zlib.c
+++ b/ext/zlib/zlib.c
@@ -25,7 +25,7 @@
# define VALGRIND_MAKE_MEM_UNDEFINED(p, n) 0
#endif
-#define RUBY_ZLIB_VERSION "3.1.0"
+#define RUBY_ZLIB_VERSION "3.2.2"
#ifndef RB_PASS_CALLED_KEYWORDS
# define rb_class_new_instance_kw(argc, argv, klass, kw_splat) rb_class_new_instance(argc, argv, klass)
@@ -674,9 +674,7 @@ zstream_expand_buffer(struct zstream *z)
rb_obj_reveal(z->buf, rb_cString);
}
- rb_mutex_unlock(z->mutex);
- rb_protect(rb_yield, z->buf, &state);
- rb_mutex_lock(z->mutex);
+ rb_protect(rb_yield, z->buf, &state);
if (ZSTREAM_REUSE_BUFFER_P(z)) {
rb_str_modify(z->buf);
@@ -720,15 +718,14 @@ zstream_expand_buffer_into(struct zstream *z, unsigned long size)
}
}
-static void *
-zstream_expand_buffer_protect(void *ptr)
+static int
+zstream_expand_buffer_protect(struct zstream *z)
{
- struct zstream *z = (struct zstream *)ptr;
int state = 0;
rb_protect((VALUE (*)(VALUE))zstream_expand_buffer, (VALUE)z, &state);
- return (void *)(VALUE)state;
+ return state;
}
static int
@@ -1023,57 +1020,14 @@ zstream_ensure_end(VALUE v)
}
static void *
-zstream_run_func(void *ptr)
+zstream_run_once(void *_arguments)
{
- struct zstream_run_args *args = (struct zstream_run_args *)ptr;
- int err, state, flush = args->flush;
- struct zstream *z = args->z;
- uInt n;
-
- err = Z_OK;
- while (!args->interrupt) {
- n = z->stream.avail_out;
- err = z->func->run(&z->stream, flush);
- rb_str_set_len(z->buf, ZSTREAM_BUF_FILLED(z) + (n - z->stream.avail_out));
-
- if (err == Z_STREAM_END) {
- z->flags &= ~ZSTREAM_FLAG_IN_STREAM;
- z->flags |= ZSTREAM_FLAG_FINISHED;
- break;
- }
+ struct zstream_run_args *arguments = (struct zstream_run_args *)_arguments;
+ struct zstream *z = arguments->z;
- if (err != Z_OK && err != Z_BUF_ERROR)
- break;
-
- if (z->stream.avail_out > 0) {
- z->flags |= ZSTREAM_FLAG_IN_STREAM;
- break;
- }
-
- if (z->stream.avail_in == 0 && z->func == &inflate_funcs) {
- /* break here because inflate() return Z_BUF_ERROR when avail_in == 0. */
- /* but deflate() could be called with avail_in == 0 (there's hidden buffer
- in zstream->state) */
- z->flags |= ZSTREAM_FLAG_IN_STREAM;
- break;
- }
-
- if (args->stream_output) {
- state = (int)(VALUE)rb_thread_call_with_gvl(zstream_expand_buffer_protect,
- (void *)z);
- }
- else {
- state = zstream_expand_buffer_non_stream(z);
- }
-
- if (state) {
- err = Z_OK; /* buffer expanded but stream processing was stopped */
- args->jump_state = state;
- break;
- }
- }
+ uintptr_t error = z->func->run(&z->stream, arguments->flush);
- return (void *)(VALUE)err;
+ return (void*)error;
}
/*
@@ -1088,6 +1042,91 @@ zstream_unblock_func(void *ptr)
args->interrupt = 1;
}
+#ifndef RB_NOGVL_OFFLOAD_SAFE
+// Default to no-op if it's not defined:
+#define RB_NOGVL_OFFLOAD_SAFE 0
+#endif
+
+static VALUE
+zstream_run_once_begin(VALUE _arguments)
+{
+ struct zstream_run_args *arguments = (struct zstream_run_args *)_arguments;
+ struct zstream *z = arguments->z;
+
+ rb_str_locktmp(z->buf);
+
+#ifndef RB_NOGVL_UBF_ASYNC_SAFE
+ return (VALUE)rb_thread_call_without_gvl(zstream_run_once, (void *)arguments, zstream_unblock_func, (void *)arguments);
+#else
+ return (VALUE)rb_nogvl(zstream_run_once, (void *)arguments, zstream_unblock_func, (void *)arguments, RB_NOGVL_UBF_ASYNC_SAFE | RB_NOGVL_OFFLOAD_SAFE);
+#endif
+}
+
+static VALUE
+zstream_run_once_ensure(VALUE _arguments)
+{
+ struct zstream_run_args *arguments = (struct zstream_run_args *)_arguments;
+ struct zstream *z = arguments->z;
+
+ rb_str_unlocktmp(z->buf);
+
+ return Qnil;
+}
+
+static int
+zstream_run_func(struct zstream_run_args *args)
+{
+ struct zstream *z = args->z;
+ int state;
+ uInt n;
+
+ int err = Z_OK;
+ while (!args->interrupt) {
+ n = z->stream.avail_out;
+
+ err = (int)(VALUE)rb_ensure(zstream_run_once_begin, (VALUE)args, zstream_run_once_ensure, (VALUE)args);
+
+ rb_str_set_len(z->buf, ZSTREAM_BUF_FILLED(z) + (n - z->stream.avail_out));
+
+ if (err == Z_STREAM_END) {
+ z->flags &= ~ZSTREAM_FLAG_IN_STREAM;
+ z->flags |= ZSTREAM_FLAG_FINISHED;
+ break;
+ }
+
+ if (err != Z_OK && err != Z_BUF_ERROR)
+ break;
+
+ if (z->stream.avail_out > 0) {
+ z->flags |= ZSTREAM_FLAG_IN_STREAM;
+ break;
+ }
+
+ if (z->stream.avail_in == 0 && z->func == &inflate_funcs) {
+ /* break here because inflate() return Z_BUF_ERROR when avail_in == 0. */
+ /* but deflate() could be called with avail_in == 0 (there's hidden buffer
+ in zstream->state) */
+ z->flags |= ZSTREAM_FLAG_IN_STREAM;
+ break;
+ }
+
+ if (args->stream_output) {
+ state = zstream_expand_buffer_protect(z);
+ }
+ else {
+ state = zstream_expand_buffer_non_stream(z);
+ }
+
+ if (state) {
+ err = Z_OK; /* buffer expanded but stream processing was stopped */
+ args->jump_state = state;
+ break;
+ }
+ }
+
+ return err;
+}
+
static VALUE
zstream_run_try(VALUE value_arg)
{
@@ -1100,6 +1139,12 @@ zstream_run_try(VALUE value_arg)
int err;
VALUE old_input = Qnil;
+ /* Cannot start zstream while it is in progress. */
+ if (z->flags & ZSTREAM_IN_PROGRESS) {
+ rb_raise(cInProgressError, "zlib stream is in progress");
+ }
+ z->flags |= ZSTREAM_IN_PROGRESS;
+
if (NIL_P(z->input) && len == 0) {
z->stream.next_in = (Bytef*)"";
z->stream.avail_in = 0;
@@ -1120,14 +1165,7 @@ zstream_run_try(VALUE value_arg)
}
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);
-#else
- err = (int)(VALUE)rb_nogvl(zstream_run_func, (void *)args,
- zstream_unblock_func, (void *)args,
- RB_NOGVL_UBF_ASYNC_SAFE);
-#endif
+ err = zstream_run_func(args);
/* retry if no exception is thrown */
if (err == Z_OK && args->interrupt) {
@@ -1167,9 +1205,6 @@ loop:
rb_str_resize(old_input, 0);
}
- if (args->jump_state)
- rb_jump_tag(args->jump_state);
-
return Qnil;
}
@@ -1177,25 +1212,10 @@ static VALUE
zstream_run_ensure(VALUE value_arg)
{
struct zstream_run_args *args = (struct zstream_run_args *)value_arg;
+ struct zstream *z = args->z;
/* 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);
+ z->flags &= ~ZSTREAM_IN_PROGRESS;
return Qnil;
}
@@ -1212,7 +1232,10 @@ zstream_run(struct zstream *z, Bytef *src, long len, int flush)
.jump_state = 0,
.stream_output = !ZSTREAM_IS_GZFILE(z) && rb_block_given_p(),
};
- rb_mutex_synchronize(z->mutex, zstream_run_synchronized, (VALUE)&args);
+
+ rb_ensure(zstream_run_try, (VALUE)&args, zstream_run_ensure, (VALUE)&args);
+ if (args.jump_state)
+ rb_jump_tag(args.jump_state);
}
static VALUE
@@ -1433,6 +1456,7 @@ rb_zstream_finish(VALUE obj)
* call-seq:
* flush_next_in -> input
*
+ * Flushes input buffer and returns all data in that buffer.
*/
static VALUE
rb_zstream_flush_next_in(VALUE obj)
@@ -1521,7 +1545,7 @@ rb_zstream_total_out(VALUE obj)
}
/*
- * Guesses the type of the data which have been inputed into the stream. The
+ * Guesses the type of the data which have been inputted into the stream. The
* returned value is either <tt>BINARY</tt>, <tt>ASCII</tt>, or
* <tt>UNKNOWN</tt>.
*/
@@ -1778,6 +1802,22 @@ do_deflate(struct zstream *z, VALUE src, int flush)
}
}
+struct rb_zlib_deflate_arguments {
+ struct zstream *z;
+ VALUE src;
+ int flush;
+};
+
+static VALUE
+rb_deflate_deflate_body(VALUE args)
+{
+ struct rb_zlib_deflate_arguments *arguments = (struct rb_zlib_deflate_arguments *)args;
+
+ do_deflate(arguments->z, arguments->src, arguments->flush);
+
+ return zstream_detach_buffer(arguments->z);
+}
+
/*
* Document-method: Zlib::Deflate#deflate
*
@@ -1809,11 +1849,10 @@ rb_deflate_deflate(int argc, VALUE *argv, VALUE obj)
{
struct zstream *z = get_zstream(obj);
VALUE src, flush;
-
rb_scan_args(argc, argv, "11", &src, &flush);
- do_deflate(z, src, ARG_FLUSH(flush));
+ struct rb_zlib_deflate_arguments arguments = {z, src, ARG_FLUSH(flush)};
- return zstream_detach_buffer(z);
+ return rb_mutex_synchronize(z->mutex, rb_deflate_deflate_body, (VALUE)&arguments);
}
/*
@@ -2109,56 +2148,19 @@ rb_inflate_add_dictionary(VALUE obj, VALUE dictionary)
return obj;
}
-/*
- * Document-method: Zlib::Inflate#inflate
- *
- * call-seq:
- * 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
- * the stream are flushed. If string is +nil+, this method finishes the
- * stream, just like Zlib::ZStream#finish.
- *
- * 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:
- *
- * inflater = Zlib::Inflate.new
- *
- * begin
- * out = inflater.inflate compressed
- * rescue Zlib::NeedDict
- * # ensure the dictionary matches the stream's required dictionary
- * raise unless inflater.adler == Zlib.adler32(dictionary)
- *
- * inflater.set_dictionary dictionary
- * inflater.inflate ''
- * end
- *
- * # ...
- *
- * inflater.close
- *
- * See also Zlib::Inflate.new
- */
+struct rb_zlib_inflate_arguments {
+ struct zstream *z;
+ int argc;
+ VALUE *argv;
+};
+
static VALUE
-rb_inflate_inflate(int argc, VALUE* argv, VALUE obj)
+rb_inflate_inflate_body(VALUE _arguments)
{
- struct zstream *z = get_zstream(obj);
+ struct rb_zlib_inflate_arguments *arguments = (struct rb_zlib_inflate_arguments*)_arguments;
+ struct zstream *z = arguments->z;
+ int argc = arguments->argc;
+ VALUE *argv = arguments->argv;
VALUE dst, src, opts, buffer = Qnil;
if (OPTHASH_GIVEN_P(opts)) {
@@ -2214,6 +2216,60 @@ rb_inflate_inflate(int argc, VALUE* argv, VALUE obj)
}
/*
+ * Document-method: Zlib::Inflate#inflate
+ *
+ * call-seq:
+ * 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
+ * the stream are flushed. If string is +nil+, this method finishes the
+ * stream, just like Zlib::ZStream#finish.
+ *
+ * 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:
+ *
+ * inflater = Zlib::Inflate.new
+ *
+ * begin
+ * out = inflater.inflate compressed
+ * rescue Zlib::NeedDict
+ * # ensure the dictionary matches the stream's required dictionary
+ * raise unless inflater.adler == Zlib.adler32(dictionary)
+ *
+ * inflater.set_dictionary dictionary
+ * inflater.inflate ''
+ * end
+ *
+ * # ...
+ *
+ * inflater.close
+ *
+ * See also Zlib::Inflate.new
+ */
+static VALUE
+rb_inflate_inflate(int argc, VALUE* argv, VALUE obj)
+{
+ struct zstream *z = get_zstream(obj);
+ struct rb_zlib_inflate_arguments arguments = {z, argc, argv};
+ return rb_mutex_synchronize(z->mutex, rb_inflate_inflate_body, (VALUE)&arguments);
+}
+
+/*
* call-seq: << string
*
* Inputs +string+ into the inflate stream just like Zlib::Inflate#inflate, but
@@ -2389,17 +2445,16 @@ struct gzfile {
#define GZFILE_READ_SIZE 2048
+enum { read_raw_arg_len, read_raw_arg_buf, read_raw_arg__count};
struct read_raw_arg {
VALUE io;
- union {
- const VALUE argv[2]; /* for rb_funcallv */
- struct {
- VALUE len;
- VALUE buf;
- } in;
- } as;
+ const VALUE argv[read_raw_arg__count]; /* for rb_funcallv */
};
+#define read_raw_arg_argc(ra) \
+ ((int)read_raw_arg__count - NIL_P((ra)->argv[read_raw_arg__count - 1]))
+#define read_raw_arg_init(io, len, buf) { io, { len, buf } }
+
static void
gzfile_mark(void *p)
{
@@ -2525,9 +2580,9 @@ gzfile_read_raw_partial(VALUE arg)
{
struct read_raw_arg *ra = (struct read_raw_arg *)arg;
VALUE str;
- int argc = NIL_P(ra->as.argv[1]) ? 1 : 2;
+ int argc = read_raw_arg_argc(ra);
- str = rb_funcallv(ra->io, id_readpartial, argc, ra->as.argv);
+ str = rb_funcallv(ra->io, id_readpartial, argc, ra->argv);
Check_Type(str, T_STRING);
return str;
}
@@ -2538,8 +2593,8 @@ gzfile_read_raw_rescue(VALUE arg, VALUE _)
struct read_raw_arg *ra = (struct read_raw_arg *)arg;
VALUE str = Qnil;
if (rb_obj_is_kind_of(rb_errinfo(), rb_eNoMethodError)) {
- int argc = NIL_P(ra->as.argv[1]) ? 1 : 2;
- str = rb_funcallv(ra->io, id_read, argc, ra->as.argv);
+ int argc = read_raw_arg_argc(ra);
+ str = rb_funcallv(ra->io, id_read, argc, ra->argv);
if (!NIL_P(str)) {
Check_Type(str, T_STRING);
}
@@ -2550,11 +2605,8 @@ gzfile_read_raw_rescue(VALUE arg, VALUE _)
static VALUE
gzfile_read_raw(struct gzfile *gz, VALUE outbuf)
{
- struct read_raw_arg ra;
-
- ra.io = gz->io;
- ra.as.in.len = INT2FIX(GZFILE_READ_SIZE);
- ra.as.in.buf = outbuf;
+ struct read_raw_arg ra =
+ read_raw_arg_init(gz->io, INT2FIX(GZFILE_READ_SIZE), outbuf);
return rb_rescue2(gzfile_read_raw_partial, (VALUE)&ra,
gzfile_read_raw_rescue, (VALUE)&ra,
@@ -4054,7 +4106,7 @@ rb_gzreader_read(int argc, VALUE *argv, VALUE obj)
* call-seq:
* gzipreader.readpartial(maxlen [, outbuf]) => string, outbuf
*
- * Reads at most <i>maxlen</i> bytes from the gziped stream but
+ * Reads at most <i>maxlen</i> bytes from the gzipped stream but
* it blocks only if <em>gzipreader</em> has no data immediately available.
* If the optional <i>outbuf</i> argument is present,
* it must reference a String, which will receive the data.
@@ -4229,6 +4281,7 @@ gzreader_skip_linebreaks(struct gzfile *gz)
while (n++, *(p++) == '\n') {
if (n >= ZSTREAM_BUF_FILLED(&gz->z)) {
str = zstream_detach_buffer(&gz->z);
+ ASSUME(!NIL_P(str));
gzfile_calc_crc(gz, str);
while (ZSTREAM_BUF_FILLED(&gz->z) == 0) {
if (GZFILE_IS_FINISHED(gz)) return;
@@ -4637,6 +4690,7 @@ zlib_gunzip_run(VALUE arg)
gzfile_read_header(gz, Qnil);
dst = zstream_detach_buffer(&gz->z);
+ ASSUME(!NIL_P(dst));
gzfile_calc_crc(gz, dst);
if (!ZSTREAM_IS_FINISHED(&gz->z)) {
rb_raise(cGzError, "unexpected end of file");
diff --git a/file.c b/file.c
index 835f19e541..809253fab0 100644
--- a/file.c
+++ b/file.c
@@ -12,6 +12,7 @@
**********************************************************************/
#include "ruby/internal/config.h"
+#include "ruby/internal/attr/nonstring.h"
#ifdef _WIN32
# include "missing/file.h"
@@ -131,6 +132,14 @@ int flock(int, int);
# define STAT(p, s) stat((p), (s))
#endif /* _WIN32 */
+#ifdef HAVE_STRUCT_STATX_STX_BTIME
+# define ST_(name) stx_ ## name
+typedef struct statx_timestamp stat_timestamp;
+#else
+# define ST_(name) st_ ## name
+typedef struct timespec stat_timestamp;
+#endif
+
#if defined _WIN32 || defined __APPLE__
# define USE_OSPATH 1
# define TO_OSPATH(str) rb_str_encode_ospath(str)
@@ -160,6 +169,7 @@ int flock(int, int);
#include "internal.h"
#include "internal/compilers.h"
#include "internal/dir.h"
+#include "internal/encoding.h"
#include "internal/error.h"
#include "internal/file.h"
#include "internal/io.h"
@@ -172,6 +182,13 @@ int flock(int, int);
#include "ruby/thread.h"
#include "ruby/util.h"
+#define UIANY2NUM(x) \
+ ((sizeof(x) <= sizeof(unsigned int)) ? \
+ UINT2NUM((unsigned)(x)) : \
+ (sizeof(x) <= sizeof(unsigned long)) ? \
+ ULONG2NUM((unsigned long)(x)) : \
+ ULL2NUM((unsigned LONG_LONG)(x)))
+
VALUE rb_cFile;
VALUE rb_mFileTest;
VALUE rb_cStat;
@@ -271,6 +288,18 @@ rb_str_encode_ospath(VALUE path)
# define NORMALIZE_UTF8PATH 1
# ifdef HAVE_WORKING_FORK
+static CFMutableStringRef
+mutable_CFString_new(CFStringRef *s, const char *ptr, long len)
+{
+ const CFAllocatorRef alloc = kCFAllocatorDefault;
+ *s = CFStringCreateWithBytesNoCopy(alloc, (const UInt8 *)ptr, len,
+ kCFStringEncodingUTF8, FALSE,
+ kCFAllocatorNull);
+ return CFStringCreateMutableCopy(alloc, len, *s);
+}
+
+# define mutable_CFString_release(m, s) (CFRelease(m), CFRelease(s))
+
static void
rb_CFString_class_initialize_before_fork(void)
{
@@ -297,15 +326,17 @@ rb_CFString_class_initialize_before_fork(void)
/* Enough small but non-empty ASCII string to fit in NSTaggedPointerString. */
const char small_str[] = "/";
long len = sizeof(small_str) - 1;
-
- const CFAllocatorRef alloc = kCFAllocatorDefault;
- CFStringRef s = CFStringCreateWithBytesNoCopy(alloc,
- (const UInt8 *)small_str,
- len, kCFStringEncodingUTF8,
- FALSE, kCFAllocatorNull);
- CFMutableStringRef m = CFStringCreateMutableCopy(alloc, len, s);
- CFRelease(m);
- CFRelease(s);
+ CFStringRef s;
+ /*
+ * Touch `CFStringCreateWithBytesNoCopy` *twice* because the implementation
+ * shipped with macOS 15.0 24A5331b does not return `NSTaggedPointerString`
+ * instance for the first call (totally not sure why). CoreFoundation
+ * shipped with macOS 15.1 does not have this issue.
+ */
+ for (int i = 0; i < 2; i++) {
+ CFMutableStringRef m = mutable_CFString_new(&s, small_str, len);
+ mutable_CFString_release(m, s);
+ }
}
# endif /* HAVE_WORKING_FORK */
@@ -314,11 +345,8 @@ rb_str_append_normalized_ospath(VALUE str, const char *ptr, long len)
{
CFIndex buflen = 0;
CFRange all;
- CFStringRef s = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault,
- (const UInt8 *)ptr, len,
- kCFStringEncodingUTF8, FALSE,
- kCFAllocatorNull);
- CFMutableStringRef m = CFStringCreateMutableCopy(kCFAllocatorDefault, len, s);
+ CFStringRef s;
+ CFMutableStringRef m = mutable_CFString_new(&s, ptr, len);
long oldlen = RSTRING_LEN(str);
CFStringNormalize(m, kCFStringNormalizationFormC);
@@ -328,8 +356,7 @@ rb_str_append_normalized_ospath(VALUE str, const char *ptr, long len)
CFStringGetBytes(m, all, kCFStringEncodingUTF8, '?', FALSE,
(UInt8 *)(RSTRING_PTR(str) + oldlen), buflen, &buflen);
rb_str_set_len(str, oldlen + buflen);
- CFRelease(m);
- CFRelease(s);
+ mutable_CFString_release(m, s);
return str;
}
@@ -348,7 +375,7 @@ rb_str_normalize_ospath(const char *ptr, long len)
int r = rb_enc_precise_mbclen(p, e, enc);
if (!MBCLEN_CHARFOUND_P(r)) {
/* invalid byte shall not happen but */
- static const char invalid[3] = "\xEF\xBF\xBD";
+ RBIMPL_ATTR_NONSTRING() static const char invalid[3] = "\xEF\xBF\xBD";
rb_str_append_normalized_ospath(str, p1, p-p1);
rb_str_cat(str, invalid, sizeof(invalid));
p += 1;
@@ -483,6 +510,10 @@ apply2files(int (*func)(const char *, void *), int argc, VALUE *argv, void *arg)
return LONG2FIX(argc);
}
+static stat_timestamp stat_atimespec(const struct stat *st);
+static stat_timestamp stat_mtimespec(const struct stat *st);
+static stat_timestamp stat_ctimespec(const struct stat *st);
+
static const rb_data_type_t stat_data_type = {
"stat",
{
@@ -494,29 +525,67 @@ static const rb_data_type_t stat_data_type = {
};
struct rb_stat {
- struct stat stat;
+ rb_io_stat_data stat;
bool initialized;
};
-static VALUE
-stat_new_0(VALUE klass, const struct stat *st)
+static struct rb_stat *
+stat_alloc(VALUE klass, VALUE *obj)
{
struct rb_stat *rb_st;
- VALUE obj = TypedData_Make_Struct(klass, struct rb_stat, &stat_data_type, rb_st);
+ *obj = TypedData_Make_Struct(klass, struct rb_stat, &stat_data_type, rb_st);
+ return rb_st;
+}
+
+VALUE
+rb_stat_new(const struct stat *st)
+{
+ VALUE obj;
+ struct rb_stat *rb_st = stat_alloc(rb_cStat, &obj);
if (st) {
+#if RUBY_USE_STATX
+# define CP(m) .stx_ ## m = st->st_ ## m
+# define CP_32(m) .stx_ ## m = (uint32_t)st->st_ ## m
+# define CP_TS(m) .stx_ ## m = stat_ ## m ## spec(st)
+ rb_st->stat = (struct statx){
+ .stx_mask = STATX_BASIC_STATS,
+ CP(mode),
+ CP_32(nlink),
+ CP(uid),
+ CP(gid),
+ CP_TS(atime),
+ CP_TS(mtime),
+ CP_TS(ctime),
+ CP(ino),
+ CP(size),
+ CP(blocks),
+ };
+# undef CP
+# undef CP_TS
+#else
rb_st->stat = *st;
+#endif
rb_st->initialized = true;
}
+
return obj;
}
+#ifndef rb_statx_new
VALUE
-rb_stat_new(const struct stat *st)
+rb_statx_new(const rb_io_stat_data *st)
{
- return stat_new_0(rb_cStat, st);
+ VALUE obj;
+ struct rb_stat *rb_st = stat_alloc(rb_cStat, &obj);
+ if (st) {
+ rb_st->stat = *st;
+ rb_st->initialized = true;
+ }
+ return obj;
}
+#endif
-static struct stat*
+static rb_io_stat_data*
get_stat(VALUE self)
{
struct rb_stat* rb_st;
@@ -525,29 +594,51 @@ get_stat(VALUE self)
return &rb_st->stat;
}
-static struct timespec stat_mtimespec(const struct stat *st);
+#if RUBY_USE_STATX
+static stat_timestamp
+statx_mtimespec(const rb_io_stat_data *st)
+{
+ return st->stx_mtime;
+}
+#else
+# define statx_mtimespec stat_mtimespec
+#endif
/*
* call-seq:
- * stat <=> other_stat -> -1, 0, 1, nil
+ * self <=> other -> -1, 0, 1, or nil
+ *
+ * Compares +self+ and +other+, by comparing their modification times;
+ * that is, by comparing <tt>self.mtime</tt> and <tt>other.mtime</tt>.
*
- * Compares File::Stat objects by comparing their respective modification
- * times.
+ * Returns:
*
- * +nil+ is returned if +other_stat+ is not a File::Stat object
+ * - +-1+, if <tt>self.mtime</tt> is earlier.
+ * - +0+, if the two values are equal.
+ * - +1+, if <tt>self.mtime</tt> is later.
+ * - +nil+, if +other+ is not a File::Stat object.
+ *
+ * Examples:
*
- * f1 = File.new("f1", "w")
- * sleep 1
- * f2 = File.new("f2", "w")
- * f1.stat <=> f2.stat #=> -1
+ * stat0 = File.stat('README.md')
+ * stat1 = File.stat('NEWS.md')
+ * stat0.mtime # => 2025-12-20 15:33:05.6972341 -0600
+ * stat1.mtime # => 2025-12-20 16:02:08.2672945 -0600
+ * stat0 <=> stat1 # => -1
+ * stat0 <=> stat0.dup # => 0
+ * stat1 <=> stat0 # => 1
+ * stat0 <=> :foo # => nil
+ *
+ * \Class \File::Stat includes module Comparable,
+ * each of whose methods uses File::Stat#<=> for comparison.
*/
static VALUE
rb_stat_cmp(VALUE self, VALUE other)
{
if (rb_obj_is_kind_of(other, rb_obj_class(self))) {
- struct timespec ts1 = stat_mtimespec(get_stat(self));
- struct timespec ts2 = stat_mtimespec(get_stat(other));
+ stat_timestamp ts1 = statx_mtimespec(get_stat(self));
+ stat_timestamp ts2 = statx_mtimespec(get_stat(other));
if (ts1.tv_sec == ts2.tv_sec) {
if (ts1.tv_nsec == ts2.tv_nsec) return INT2FIX(0);
if (ts1.tv_nsec < ts2.tv_nsec) return INT2FIX(-1);
@@ -584,7 +675,11 @@ rb_stat_cmp(VALUE self, VALUE other)
static VALUE
rb_stat_dev(VALUE self)
{
-#if SIZEOF_STRUCT_STAT_ST_DEV <= SIZEOF_DEV_T
+#if RUBY_USE_STATX
+ unsigned int m = get_stat(self)->stx_dev_major;
+ unsigned int n = get_stat(self)->stx_dev_minor;
+ return ULL2NUM(makedev(m, n));
+#elif 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);
@@ -607,7 +702,9 @@ rb_stat_dev(VALUE self)
static VALUE
rb_stat_dev_major(VALUE self)
{
-#if defined(major)
+#if RUBY_USE_STATX
+ return UINT2NUM(get_stat(self)->stx_dev_major);
+#elif defined(major)
return UINT2NUM(major(get_stat(self)->st_dev));
#else
return Qnil;
@@ -628,7 +725,9 @@ rb_stat_dev_major(VALUE self)
static VALUE
rb_stat_dev_minor(VALUE self)
{
-#if defined(minor)
+#if RUBY_USE_STATX
+ return UINT2NUM(get_stat(self)->stx_dev_minor);
+#elif defined(minor)
return UINT2NUM(minor(get_stat(self)->st_dev));
#else
return Qnil;
@@ -648,16 +747,15 @@ rb_stat_dev_minor(VALUE self)
static VALUE
rb_stat_ino(VALUE self)
{
+ rb_io_stat_data *ptr = get_stat(self);
#ifdef HAVE_STRUCT_STAT_ST_INOHIGH
/* assume INTEGER_PACK_LSWORD_FIRST and st_inohigh is just next of st_ino */
- return rb_integer_unpack(&get_stat(self)->st_ino, 2,
+ return rb_integer_unpack(&ptr->st_ino, 2,
SIZEOF_STRUCT_STAT_ST_INO, 0,
INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER|
INTEGER_PACK_2COMP);
-#elif SIZEOF_STRUCT_STAT_ST_INO > SIZEOF_LONG
- return ULL2NUM(get_stat(self)->st_ino);
#else
- return ULONG2NUM(get_stat(self)->st_ino);
+ return UIANY2NUM(ptr->ST_(ino));
#endif
}
@@ -677,7 +775,7 @@ rb_stat_ino(VALUE self)
static VALUE
rb_stat_mode(VALUE self)
{
- return UINT2NUM(ST2UINT(get_stat(self)->st_mode));
+ return UINT2NUM(ST2UINT(get_stat(self)->ST_(mode)));
}
/*
@@ -696,20 +794,9 @@ static VALUE
rb_stat_nlink(VALUE self)
{
/* struct stat::st_nlink is nlink_t in POSIX. Not the case for Windows. */
- const struct stat *ptr = get_stat(self);
+ const rb_io_stat_data *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");
- }
+ return UIANY2NUM(ptr->ST_(nlink));
}
/*
@@ -725,7 +812,7 @@ rb_stat_nlink(VALUE self)
static VALUE
rb_stat_uid(VALUE self)
{
- return UIDT2NUM(get_stat(self)->st_uid);
+ return UIDT2NUM(get_stat(self)->ST_(uid));
}
/*
@@ -741,7 +828,7 @@ rb_stat_uid(VALUE self)
static VALUE
rb_stat_gid(VALUE self)
{
- return GIDT2NUM(get_stat(self)->st_gid);
+ return GIDT2NUM(get_stat(self)->ST_(gid));
}
/*
@@ -759,16 +846,18 @@ rb_stat_gid(VALUE self)
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
+#if RUBY_USE_STATX
+ unsigned int m = get_stat(self)->stx_rdev_major;
+ unsigned int n = get_stat(self)->stx_rdev_minor;
+ return ULL2NUM(makedev(m, n));
+#elif !defined(HAVE_STRUCT_STAT_ST_RDEV)
return Qnil;
+#elif 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
}
@@ -786,8 +875,10 @@ rb_stat_rdev(VALUE self)
static VALUE
rb_stat_rdev_major(VALUE self)
{
-#if defined(HAVE_STRUCT_STAT_ST_RDEV) && defined(major)
- return UINT2NUM(major(get_stat(self)->st_rdev));
+#if RUBY_USE_STATX
+ return UINT2NUM(get_stat(self)->stx_rdev_major);
+#elif defined(HAVE_STRUCT_STAT_ST_RDEV) && defined(major)
+ return UINT2NUM(major(get_stat(self)->ST_(rdev)));
#else
return Qnil;
#endif
@@ -807,8 +898,10 @@ rb_stat_rdev_major(VALUE self)
static VALUE
rb_stat_rdev_minor(VALUE self)
{
-#if defined(HAVE_STRUCT_STAT_ST_RDEV) && defined(minor)
- return UINT2NUM(minor(get_stat(self)->st_rdev));
+#if RUBY_USE_STATX
+ return UINT2NUM(get_stat(self)->stx_rdev_minor);
+#elif defined(HAVE_STRUCT_STAT_ST_RDEV) && defined(minor)
+ return UINT2NUM(minor(get_stat(self)->ST_(rdev)));
#else
return Qnil;
#endif
@@ -826,7 +919,7 @@ rb_stat_rdev_minor(VALUE self)
static VALUE
rb_stat_size(VALUE self)
{
- return OFFT2NUM(get_stat(self)->st_size);
+ return OFFT2NUM(get_stat(self)->ST_(size));
}
/*
@@ -844,7 +937,7 @@ static VALUE
rb_stat_blksize(VALUE self)
{
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
- return ULONG2NUM(get_stat(self)->st_blksize);
+ return ULONG2NUM(get_stat(self)->ST_(blksize));
#else
return Qnil;
#endif
@@ -866,34 +959,44 @@ rb_stat_blocks(VALUE self)
{
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
# if SIZEOF_STRUCT_STAT_ST_BLOCKS > SIZEOF_LONG
- return ULL2NUM(get_stat(self)->st_blocks);
+ return ULL2NUM(get_stat(self)->ST_(blocks));
# else
- return ULONG2NUM(get_stat(self)->st_blocks);
+ return ULONG2NUM(get_stat(self)->ST_(blocks));
# endif
#else
return Qnil;
#endif
}
-static struct timespec
+static stat_timestamp
stat_atimespec(const struct stat *st)
{
- struct timespec ts;
+ stat_timestamp ts;
ts.tv_sec = st->st_atime;
#if defined(HAVE_STRUCT_STAT_ST_ATIM)
- ts.tv_nsec = st->st_atim.tv_nsec;
+ ts.tv_nsec = (uint32_t)st->st_atim.tv_nsec;
#elif defined(HAVE_STRUCT_STAT_ST_ATIMESPEC)
- ts.tv_nsec = st->st_atimespec.tv_nsec;
+ ts.tv_nsec = (uint32_t)st->st_atimespec.tv_nsec;
#elif defined(HAVE_STRUCT_STAT_ST_ATIMENSEC)
- ts.tv_nsec = (long)st->st_atimensec;
+ ts.tv_nsec = (uint32_t)st->st_atimensec;
#else
- ts.tv_nsec = 0;
+ ts.tv_nsec = 0
#endif
return ts;
}
+#if RUBY_USE_STATX
+static stat_timestamp
+statx_atimespec(const rb_io_stat_data *st)
+{
+ return st->stx_atime;
+}
+#else
+# define statx_atimespec stat_atimespec
+#endif
+
static VALUE
-stat_time(const struct timespec ts)
+stat_time(const stat_timestamp ts)
{
return rb_time_nano_new(ts.tv_sec, ts.tv_nsec);
}
@@ -904,17 +1007,17 @@ stat_atime(const struct stat *st)
return stat_time(stat_atimespec(st));
}
-static struct timespec
+static stat_timestamp
stat_mtimespec(const struct stat *st)
{
- struct timespec ts;
+ stat_timestamp ts;
ts.tv_sec = st->st_mtime;
#if defined(HAVE_STRUCT_STAT_ST_MTIM)
- ts.tv_nsec = st->st_mtim.tv_nsec;
+ ts.tv_nsec = (uint32_t)st->st_mtim.tv_nsec;
#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC)
- ts.tv_nsec = st->st_mtimespec.tv_nsec;
+ ts.tv_nsec = (uint32_t)st->st_mtimespec.tv_nsec;
#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
- ts.tv_nsec = (long)st->st_mtimensec;
+ ts.tv_nsec = (uint32_t)st->st_mtimensec;
#else
ts.tv_nsec = 0;
#endif
@@ -927,23 +1030,33 @@ stat_mtime(const struct stat *st)
return stat_time(stat_mtimespec(st));
}
-static struct timespec
+static stat_timestamp
stat_ctimespec(const struct stat *st)
{
- struct timespec ts;
+ stat_timestamp ts;
ts.tv_sec = st->st_ctime;
#if defined(HAVE_STRUCT_STAT_ST_CTIM)
- ts.tv_nsec = st->st_ctim.tv_nsec;
+ ts.tv_nsec = (uint32_t)st->st_ctim.tv_nsec;
#elif defined(HAVE_STRUCT_STAT_ST_CTIMESPEC)
- ts.tv_nsec = st->st_ctimespec.tv_nsec;
+ ts.tv_nsec = (uint32_t)st->st_ctimespec.tv_nsec;
#elif defined(HAVE_STRUCT_STAT_ST_CTIMENSEC)
- ts.tv_nsec = (long)st->st_ctimensec;
+ ts.tv_nsec = (uint32_t)st->st_ctimensec;
#else
ts.tv_nsec = 0;
#endif
return ts;
}
+#if RUBY_USE_STATX
+static stat_timestamp
+statx_ctimespec(const rb_io_stat_data *st)
+{
+ return st->stx_ctime;
+}
+#else
+# define statx_ctimespec stat_ctimespec
+#endif
+
static VALUE
stat_ctime(const struct stat *st)
{
@@ -952,16 +1065,16 @@ stat_ctime(const struct stat *st)
#define HAVE_STAT_BIRTHTIME
#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC)
-typedef struct stat statx_data;
static VALUE
-stat_birthtime(const struct stat *st)
+statx_birthtime(const rb_io_stat_data *st)
{
- const struct timespec *ts = &st->st_birthtimespec;
+ const stat_timestamp *ts = &st->ST_(birthtimespec);
return rb_time_nano_new(ts->tv_sec, ts->tv_nsec);
}
+#elif defined(HAVE_STRUCT_STATX_STX_BTIME)
+static VALUE statx_birthtime(const rb_io_stat_data *st);
#elif defined(_WIN32)
-typedef struct stat statx_data;
-# define stat_birthtime stat_ctime
+# define statx_birthtime stat_ctime
#else
# undef HAVE_STAT_BIRTHTIME
#endif /* defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC) */
@@ -980,7 +1093,7 @@ typedef struct stat statx_data;
static VALUE
rb_stat_atime(VALUE self)
{
- return stat_atime(get_stat(self));
+ return stat_time(statx_atimespec(get_stat(self)));
}
/*
@@ -996,7 +1109,7 @@ rb_stat_atime(VALUE self)
static VALUE
rb_stat_mtime(VALUE self)
{
- return stat_mtime(get_stat(self));
+ return stat_time(statx_mtimespec(get_stat(self)));
}
/*
@@ -1016,7 +1129,7 @@ rb_stat_mtime(VALUE self)
static VALUE
rb_stat_ctime(VALUE self)
{
- return stat_ctime(get_stat(self));
+ return stat_time(statx_ctimespec(get_stat(self)));
}
#if defined(HAVE_STAT_BIRTHTIME)
@@ -1045,7 +1158,7 @@ rb_stat_ctime(VALUE self)
static VALUE
rb_stat_birthtime(VALUE self)
{
- return stat_birthtime(get_stat(self));
+ return statx_birthtime(get_stat(self));
}
#else
# define rb_stat_birthtime rb_f_notimplement
@@ -1143,14 +1256,14 @@ no_gvl_fstat(void *data)
}
static int
-fstat_without_gvl(int fd, struct stat *st)
+fstat_without_gvl(rb_io_t *fptr, struct stat *st)
{
no_gvl_stat_data data;
- data.file.fd = fd;
+ data.file.fd = fptr->fd;
data.st = st;
- return (int)(VALUE)rb_thread_io_blocking_region(no_gvl_fstat, &data, fd);
+ return (int)rb_io_blocking_region(fptr, no_gvl_fstat, &data);
}
static void *
@@ -1174,6 +1287,8 @@ stat_without_gvl(const char *path, struct stat *st)
#if !defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC) && \
defined(HAVE_STRUCT_STATX_STX_BTIME)
+# define STATX(path, st, mask) statx(AT_FDCWD, path, 0, mask, st)
+
# ifndef HAVE_STATX
# ifdef HAVE_SYSCALL_H
# include <syscall.h>
@@ -1191,18 +1306,18 @@ statx(int dirfd, const char *pathname, int flags,
# endif /* __linux__ */
# endif /* HAVE_STATX */
-typedef struct no_gvl_statx_data {
+typedef struct no_gvl_rb_io_stat_data {
struct statx *stx;
int fd;
const char *path;
int flags;
unsigned int mask;
-} no_gvl_statx_data;
+} no_gvl_rb_io_stat_data;
static VALUE
io_blocking_statx(void *data)
{
- no_gvl_statx_data *arg = data;
+ no_gvl_rb_io_stat_data *arg = data;
return (VALUE)statx(arg->fd, arg->path, arg->flags, arg->mask, arg->stx);
}
@@ -1213,23 +1328,34 @@ no_gvl_statx(void *data)
}
static int
-statx_without_gvl(const char *path, struct statx *stx, unsigned int mask)
+statx_without_gvl(const char *path, rb_io_stat_data *stx, unsigned int mask)
+{
+ no_gvl_rb_io_stat_data data = {stx, AT_FDCWD, path, 0, mask};
+
+ /* call statx(2) with pathname */
+ return IO_WITHOUT_GVL_INT(no_gvl_statx, &data);
+}
+
+static int
+lstatx_without_gvl(const char *path, rb_io_stat_data *stx, unsigned int mask)
{
- no_gvl_statx_data data = {stx, AT_FDCWD, path, 0, mask};
+ no_gvl_rb_io_stat_data data = {stx, AT_FDCWD, path, AT_SYMLINK_NOFOLLOW, mask};
/* call statx(2) with pathname */
return IO_WITHOUT_GVL_INT(no_gvl_statx, &data);
}
static int
-fstatx_without_gvl(int fd, struct statx *stx, unsigned int mask)
+fstatx_without_gvl(rb_io_t *fptr, rb_io_stat_data *stx, unsigned int mask)
{
- no_gvl_statx_data data = {stx, fd, "", AT_EMPTY_PATH, mask};
+ no_gvl_rb_io_stat_data data = {stx, fptr->fd, "", AT_EMPTY_PATH, mask};
/* call statx(2) with fd */
- return (int)rb_thread_io_blocking_region(io_blocking_statx, &data, fd);
+ return (int)rb_io_blocking_region(fptr, io_blocking_statx, &data);
}
+#define FSTATX(fd, st) statx(fd, "", AT_EMPTY_PATH, STATX_ALL, st)
+
static int
rb_statx(VALUE file, struct statx *stx, unsigned int mask)
{
@@ -1239,8 +1365,9 @@ rb_statx(VALUE file, struct statx *stx, unsigned int mask)
tmp = rb_check_convert_type_with_id(file, T_FILE, "IO", idTo_io);
if (!NIL_P(tmp)) {
rb_io_t *fptr;
+
GetOpenFile(tmp, fptr);
- result = fstatx_without_gvl(fptr->fd, stx, mask);
+ result = fstatx_without_gvl(fptr, stx, mask);
file = tmp;
}
else {
@@ -1267,7 +1394,7 @@ statx_notimplement(const char *field_name)
}
static VALUE
-statx_birthtime(const struct statx *stx, VALUE fname)
+statx_birthtime(const rb_io_stat_data *stx)
{
if (!statx_has_birthtime(stx)) {
/* birthtime is not supported on the filesystem */
@@ -1276,20 +1403,27 @@ statx_birthtime(const struct statx *stx, VALUE fname)
return rb_time_nano_new((time_t)stx->stx_btime.tv_sec, stx->stx_btime.tv_nsec);
}
-typedef struct statx statx_data;
-# define HAVE_STAT_BIRTHTIME
+#else
-#elif defined(HAVE_STAT_BIRTHTIME)
# define statx_without_gvl(path, st, mask) stat_without_gvl(path, st)
-# define fstatx_without_gvl(fd, st, mask) fstat_without_gvl(fd, st)
-# define statx_birthtime(st, fname) stat_birthtime(st)
+# define fstatx_without_gvl(fptr, st, mask) fstat_without_gvl(fptr, st)
+# define lstatx_without_gvl(path, st, mask) lstat_without_gvl(path, st)
+# define rb_statx(file, stx, mask) rb_stat(file, stx)
+# define STATX(path, st, mask) STAT(path, st)
+
+#if defined(HAVE_STAT_BIRTHTIME)
# define statx_has_birthtime(st) 1
-# define rb_statx(file, st, mask) rb_stat(file, st)
#else
# define statx_has_birthtime(st) 0
+#endif
+
#endif /* !defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC) && \
defined(HAVE_STRUCT_STATX_STX_BTIME) */
+#ifndef FSTAT
+# define FSTAT(fd, st) fstat(fd, st)
+#endif
+
static int
rb_stat(VALUE file, struct stat *st)
{
@@ -1301,7 +1435,7 @@ rb_stat(VALUE file, struct stat *st)
rb_io_t *fptr;
GetOpenFile(tmp, fptr);
- result = fstat_without_gvl(fptr->fd, st);
+ result = fstat_without_gvl(fptr, st);
file = tmp;
}
else {
@@ -1326,14 +1460,14 @@ rb_stat(VALUE file, struct stat *st)
static VALUE
rb_file_s_stat(VALUE klass, VALUE fname)
{
- struct stat st;
+ rb_io_stat_data st;
FilePathValue(fname);
fname = rb_str_encode_ospath(fname);
- if (stat_without_gvl(RSTRING_PTR(fname), &st) < 0) {
+ if (statx_without_gvl(RSTRING_PTR(fname), &st, STATX_ALL) < 0) {
rb_sys_fail_path(fname);
}
- return rb_stat_new(&st);
+ return rb_statx_new(&st);
}
/*
@@ -1355,13 +1489,13 @@ static VALUE
rb_io_stat(VALUE obj)
{
rb_io_t *fptr;
- struct stat st;
+ rb_io_stat_data st;
GetOpenFile(obj, fptr);
- if (fstat(fptr->fd, &st) == -1) {
+ if (fstatx_without_gvl(fptr, &st, STATX_ALL) == -1) {
rb_sys_fail_path(fptr->pathv);
}
- return rb_stat_new(&st);
+ return rb_statx_new(&st);
}
#ifdef HAVE_LSTAT
@@ -1401,14 +1535,14 @@ static VALUE
rb_file_s_lstat(VALUE klass, VALUE fname)
{
#ifdef HAVE_LSTAT
- struct stat st;
+ rb_io_stat_data st;
FilePathValue(fname);
fname = rb_str_encode_ospath(fname);
- if (lstat_without_gvl(StringValueCStr(fname), &st) == -1) {
+ if (lstatx_without_gvl(StringValueCStr(fname), &st, STATX_ALL) == -1) {
rb_sys_fail_path(fname);
}
- return rb_stat_new(&st);
+ return rb_statx_new(&st);
#else
return rb_file_s_stat(klass, fname);
#endif
@@ -1433,16 +1567,16 @@ rb_file_lstat(VALUE obj)
{
#ifdef HAVE_LSTAT
rb_io_t *fptr;
- struct stat st;
+ rb_io_stat_data st;
VALUE path;
GetOpenFile(obj, fptr);
if (NIL_P(fptr->pathv)) return Qnil;
path = rb_str_encode_ospath(fptr->pathv);
- if (lstat_without_gvl(RSTRING_PTR(path), &st) == -1) {
+ if (lstatx_without_gvl(RSTRING_PTR(path), &st, STATX_ALL) == -1) {
rb_sys_fail_path(fptr->pathv);
}
- return rb_stat_new(&st);
+ return rb_statx_new(&st);
#else
return rb_io_stat(obj);
#endif
@@ -2053,7 +2187,7 @@ rb_file_size_p(VALUE obj, VALUE fname)
* File.owned?(file_name) -> true or false
*
* Returns <code>true</code> if the named file exists and the
- * effective used id of the calling process is the owner of
+ * effective user id of the calling process is the owner of
* the file.
*
* _file_name_ can be an IO object.
@@ -2227,36 +2361,36 @@ rb_file_s_size(VALUE klass, VALUE fname)
}
static VALUE
-rb_file_ftype(const struct stat *st)
+rb_file_ftype(mode_t mode)
{
const char *t;
- if (S_ISREG(st->st_mode)) {
+ if (S_ISREG(mode)) {
t = "file";
}
- else if (S_ISDIR(st->st_mode)) {
+ else if (S_ISDIR(mode)) {
t = "directory";
}
- else if (S_ISCHR(st->st_mode)) {
+ else if (S_ISCHR(mode)) {
t = "characterSpecial";
}
#ifdef S_ISBLK
- else if (S_ISBLK(st->st_mode)) {
+ else if (S_ISBLK(mode)) {
t = "blockSpecial";
}
#endif
#ifdef S_ISFIFO
- else if (S_ISFIFO(st->st_mode)) {
+ else if (S_ISFIFO(mode)) {
t = "fifo";
}
#endif
#ifdef S_ISLNK
- else if (S_ISLNK(st->st_mode)) {
+ else if (S_ISLNK(mode)) {
t = "link";
}
#endif
#ifdef S_ISSOCK
- else if (S_ISSOCK(st->st_mode)) {
+ else if (S_ISSOCK(mode)) {
t = "socket";
}
#endif
@@ -2293,7 +2427,7 @@ rb_file_s_ftype(VALUE klass, VALUE fname)
rb_sys_fail_path(fname);
}
- return rb_file_ftype(&st);
+ return rb_file_ftype(st.st_mode);
}
/*
@@ -2318,7 +2452,7 @@ rb_file_s_atime(VALUE klass, VALUE fname)
FilePathValue(fname);
rb_syserr_fail_path(e, fname);
}
- return stat_atime(&st);
+ return stat_time(stat_atimespec(&st));
}
/*
@@ -2342,7 +2476,7 @@ rb_file_atime(VALUE obj)
if (fstat(fptr->fd, &st) == -1) {
rb_sys_fail_path(fptr->pathv);
}
- return stat_atime(&st);
+ return stat_time(stat_atimespec(&st));
}
/*
@@ -2367,7 +2501,7 @@ rb_file_s_mtime(VALUE klass, VALUE fname)
FilePathValue(fname);
rb_syserr_fail_path(e, fname);
}
- return stat_mtime(&st);
+ return stat_time(stat_mtimespec(&st));
}
/*
@@ -2390,7 +2524,7 @@ rb_file_mtime(VALUE obj)
if (fstat(fptr->fd, &st) == -1) {
rb_sys_fail_path(fptr->pathv);
}
- return stat_mtime(&st);
+ return stat_time(stat_mtimespec(&st));
}
/*
@@ -2419,7 +2553,7 @@ rb_file_s_ctime(VALUE klass, VALUE fname)
FilePathValue(fname);
rb_syserr_fail_path(e, fname);
}
- return stat_ctime(&st);
+ return stat_time(stat_ctimespec(&st));
}
/*
@@ -2445,7 +2579,7 @@ rb_file_ctime(VALUE obj)
if (fstat(fptr->fd, &st) == -1) {
rb_sys_fail_path(fptr->pathv);
}
- return stat_ctime(&st);
+ return stat_time(stat_ctimespec(&st));
}
#if defined(HAVE_STAT_BIRTHTIME)
@@ -2466,14 +2600,14 @@ rb_file_ctime(VALUE obj)
VALUE
rb_file_s_birthtime(VALUE klass, VALUE fname)
{
- statx_data st;
+ rb_io_stat_data st;
if (rb_statx(fname, &st, STATX_BTIME) < 0) {
int e = errno;
FilePathValue(fname);
rb_syserr_fail_path(e, fname);
}
- return statx_birthtime(&st, fname);
+ return statx_birthtime(&st);
}
#else
# define rb_file_s_birthtime rb_f_notimplement
@@ -2496,13 +2630,13 @@ static VALUE
rb_file_birthtime(VALUE obj)
{
rb_io_t *fptr;
- statx_data st;
+ rb_io_stat_data st;
GetOpenFile(obj, fptr);
- if (fstatx_without_gvl(fptr->fd, &st, STATX_BTIME) == -1) {
+ if (fstatx_without_gvl(fptr, &st, STATX_BTIME) == -1) {
rb_sys_fail_path(fptr->pathv);
}
- return statx_birthtime(&st, fptr->pathv);
+ return statx_birthtime(&st);
}
#else
# define rb_file_birthtime rb_f_notimplement
@@ -2615,11 +2749,11 @@ io_blocking_fchmod(void *ptr)
}
static int
-rb_fchmod(int fd, mode_t mode)
+rb_fchmod(struct rb_io* io, mode_t mode)
{
(void)rb_chmod; /* suppress unused-function warning when HAVE_FCHMOD */
- struct nogvl_fchmod_data data = {.fd = fd, .mode = mode};
- return (int)rb_thread_io_blocking_region(io_blocking_fchmod, &data, fd);
+ struct nogvl_fchmod_data data = {.fd = io->fd, .mode = mode};
+ return (int)rb_thread_io_blocking_region(io, io_blocking_fchmod, &data);
}
#endif
@@ -2649,7 +2783,7 @@ rb_file_chmod(VALUE obj, VALUE vmode)
GetOpenFile(obj, fptr);
#ifdef HAVE_FCHMOD
- if (rb_fchmod(fptr->fd, mode) == -1) {
+ if (rb_fchmod(fptr, mode) == -1) {
if (HAVE_FCHMOD || errno != ENOSYS)
rb_sys_fail_path(fptr->pathv);
}
@@ -2930,7 +3064,7 @@ utime_failed(struct apply_arg *aa)
# elif defined(__APPLE__) && \
(!defined(MAC_OS_X_VERSION_13_0) || (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_13_0))
-# if defined(__has_attribute) && __has_attribute(availability)
+# if __has_attribute(availability) && __has_warning("-Wunguarded-availability-new")
typedef int utimensat_func(int, const char *, const struct timespec [2], int);
RBIMPL_WARNING_PUSH()
@@ -2945,7 +3079,7 @@ RBIMPL_WARNING_POP()
# define utimensat rb_utimensat()
# else /* __API_AVAILABLE macro does nothing on gcc */
__attribute__((weak)) int utimensat(int, const char *, const struct timespec [2], int);
-# endif /* defined(__has_attribute) && __has_attribute(availability) */
+# endif /* utimesat availability */
# endif /* __APPLE__ && < MAC_OS_X_VERSION_13_0 */
static int
@@ -3018,7 +3152,7 @@ static int
utime_internal(const char *path, void *arg)
{
struct utime_args *v = arg;
- const struct timespec *tsp = v->tsp;
+ const stat_timestamp *tsp = v->tsp;
struct utimbuf utbuf, *utp = NULL;
if (tsp) {
utbuf.actime = tsp[0].tv_sec;
@@ -3590,7 +3724,7 @@ rb_enc_path_end(const char *path, const char *end, rb_encoding *enc)
static rb_encoding *
fs_enc_check(VALUE path1, VALUE path2)
{
- rb_encoding *enc = rb_enc_check(path1, path2);
+ rb_encoding *enc = rb_enc_check_str(path1, path2);
int encidx = rb_enc_to_index(enc);
if (encidx == ENCINDEX_US_ASCII) {
encidx = rb_enc_get_index(path1);
@@ -3694,12 +3828,16 @@ VALUE
rb_home_dir_of(VALUE user, VALUE result)
{
#ifdef HAVE_PWD_H
- struct passwd *pwPtr;
+ VALUE dirname = rb_getpwdirnam_for_login(user);
+ if (dirname == Qnil) {
+ rb_raise(rb_eArgError, "user %"PRIsVALUE" doesn't exist", user);
+ }
+ const char *dir = RSTRING_PTR(dirname);
#else
extern char *getlogin(void);
const char *pwPtr = 0;
+ const char *login;
# define endpwent() ((void)0)
-#endif
const char *dir, *username = RSTRING_PTR(user);
rb_encoding *enc = rb_enc_get(user);
#if defined _WIN32
@@ -3711,21 +3849,13 @@ rb_home_dir_of(VALUE user, VALUE result)
dir = username = RSTRING_PTR(rb_str_conv_enc(user, enc, fsenc));
}
-#ifdef HAVE_PWD_H
- pwPtr = getpwnam(username);
-#else
- if (strcasecmp(username, getlogin()) == 0)
+ if ((login = getlogin()) && strcasecmp(username, login) == 0)
dir = pwPtr = getenv("HOME");
-#endif
if (!pwPtr) {
- endpwent();
rb_raise(rb_eArgError, "user %"PRIsVALUE" doesn't exist", user);
}
-#ifdef HAVE_PWD_H
- dir = pwPtr->pw_dir;
#endif
copy_home_path(result, dir);
- endpwent();
return result;
}
@@ -4522,7 +4652,7 @@ rb_check_realpath_emulate(VALUE basedir, VALUE path, rb_encoding *origenc, enum
return resolved;
}
-static VALUE rb_file_join(VALUE ary);
+static VALUE rb_file_join(long argc, VALUE *args);
#ifndef HAVE_REALPATH
static VALUE
@@ -4537,6 +4667,11 @@ rb_check_realpath_emulate_rescue(VALUE arg, VALUE exc)
{
return Qnil;
}
+#elif !defined(NEEDS_REALPATH_BUFFER) && defined(__APPLE__) && \
+ (!defined(MAC_OS_X_VERSION_10_6) || (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6))
+/* realpath() on OSX < 10.6 doesn't implement automatic allocation */
+# include <sys/syslimits.h>
+# define NEEDS_REALPATH_BUFFER 1
#endif /* HAVE_REALPATH */
static VALUE
@@ -4546,6 +4681,11 @@ rb_check_realpath_internal(VALUE basedir, VALUE path, rb_encoding *origenc, enum
VALUE unresolved_path;
char *resolved_ptr = NULL;
VALUE resolved;
+# if defined(NEEDS_REALPATH_BUFFER) && NEEDS_REALPATH_BUFFER
+ char resolved_buffer[PATH_MAX];
+# else
+ char *const resolved_buffer = NULL;
+# endif
if (mode == RB_REALPATH_DIR) {
return rb_check_realpath_emulate(basedir, path, origenc, mode);
@@ -4553,17 +4693,22 @@ rb_check_realpath_internal(VALUE basedir, VALUE path, rb_encoding *origenc, enum
unresolved_path = rb_str_dup_frozen(path);
if (*RSTRING_PTR(unresolved_path) != '/' && !NIL_P(basedir)) {
- unresolved_path = rb_file_join(rb_assoc_new(basedir, unresolved_path));
+ VALUE paths[2] = {basedir, unresolved_path};
+ unresolved_path = rb_file_join(2, paths);
}
if (origenc) unresolved_path = TO_OSPATH(unresolved_path);
- if ((resolved_ptr = realpath(RSTRING_PTR(unresolved_path), NULL)) == NULL) {
- /* glibc realpath(3) does not allow /path/to/file.rb/../other_file.rb,
+ if ((resolved_ptr = realpath(RSTRING_PTR(unresolved_path), resolved_buffer)) == NULL) {
+ /*
+ wasi-libc 22 and later support realpath(3) but return ENOTSUP
+ when the underlying host syscall returns it.
+ glibc realpath(3) does not allow /path/to/file.rb/../other_file.rb,
returning ENOTDIR in that case.
glibc realpath(3) can also return ENOENT for paths that exist,
such as /dev/fd/5.
Fallback to the emulated approach in either of those cases. */
- if (errno == ENOTDIR ||
+ if (errno == ENOTSUP ||
+ errno == ENOTDIR ||
(errno == ENOENT && rb_file_exist_p(0, unresolved_path))) {
return rb_check_realpath_emulate(basedir, path, origenc, mode);
@@ -4574,9 +4719,11 @@ rb_check_realpath_internal(VALUE basedir, VALUE path, rb_encoding *origenc, enum
rb_sys_fail_path(unresolved_path);
}
resolved = ospath_new(resolved_ptr, strlen(resolved_ptr), rb_filesystem_encoding());
+# if !(defined(NEEDS_REALPATH_BUFFER) && NEEDS_REALPATH_BUFFER)
free(resolved_ptr);
+# endif
-# if !defined(__LINUX__) && !defined(__APPLE__)
+# if !defined(__linux__) && !defined(__APPLE__)
/* As `resolved` is a String in the filesystem encoding, no
* conversion is needed */
struct stat st;
@@ -4586,7 +4733,7 @@ rb_check_realpath_internal(VALUE basedir, VALUE path, rb_encoding *origenc, enum
}
rb_sys_fail_path(unresolved_path);
}
-# endif /* !defined(__LINUX__) && !defined(__APPLE__) */
+# endif /* !defined(__linux__) && !defined(__APPLE__) */
if (origenc && origenc != rb_enc_get(resolved)) {
if (!rb_enc_str_asciionly_p(resolved)) {
@@ -4929,8 +5076,11 @@ rb_file_dirname_n(VALUE fname, int n)
break;
}
}
- if (p == name)
- return rb_usascii_str_new2(".");
+ if (p == name) {
+ dirname = rb_str_new(".", 1);
+ rb_enc_copy(dirname, fname);
+ return dirname;
+ }
#ifdef DOSISH_DRIVE_LETTER
if (has_drive_letter(name) && isdirsep(*(name + 2))) {
const char *top = skiproot(name + 2, end, enc);
@@ -5065,6 +5215,22 @@ rb_file_s_extname(VALUE klass, VALUE fname)
* File.path(File::NULL) #=> "/dev/null"
* File.path(Pathname.new("/tmp")) #=> "/tmp"
*
+ * If +path+ is not a String:
+ *
+ * 1. If it has the +to_path+ method, that method will be called to
+ * coerce to a String.
+ *
+ * 2. Otherwise, or if the coerced result is not a String too, the
+ * standard coersion using +to_str+ method will take place on that
+ * object. (See also String.try_convert)
+ *
+ * The coerced string must satisfy the following conditions:
+ *
+ * 1. It must be in an ASCII-compatible encoding; otherwise, an
+ * Encoding::CompatibilityError is raised.
+ *
+ * 2. It must not contain the NUL character (<tt>\0</tt>); otherwise,
+ * an ArgumentError is raised.
*/
static VALUE
@@ -5091,15 +5257,17 @@ rb_file_s_split(VALUE klass, VALUE path)
return rb_assoc_new(rb_file_dirname(path), rb_file_s_basename(1,&path,Qundef));
}
+static VALUE rb_file_join_ary(VALUE ary);
+
static VALUE
file_inspect_join(VALUE ary, VALUE arg, int recur)
{
if (recur || ary == arg) rb_raise(rb_eArgError, "recursive array");
- return rb_file_join(arg);
+ return rb_file_join_ary(arg);
}
static VALUE
-rb_file_join(VALUE ary)
+rb_file_join_ary(VALUE ary)
{
long len, i;
VALUE result, tmp;
@@ -5164,6 +5332,77 @@ rb_file_join(VALUE ary)
return result;
}
+static inline VALUE
+rb_file_join_fastpath(long argc, VALUE *args)
+{
+ long size = argc;
+
+ long i;
+ for (i = 0; i < argc; i++) {
+ VALUE tmp = args[i];
+ if (RB_LIKELY(RB_TYPE_P(tmp, T_STRING) && rb_str_enc_fastpath(tmp))) {
+ size += RSTRING_LEN(tmp);
+ }
+ else {
+ return 0;
+ }
+ }
+
+ VALUE result = rb_str_buf_new(size);
+
+ int encidx = ENCODING_GET_INLINED(args[0]);
+ ENCODING_SET_INLINED(result, encidx);
+ rb_str_buf_append(result, args[0]);
+
+ const char *name = RSTRING_PTR(result);
+ for (i = 1; i < argc; i++) {
+ VALUE tmp = args[i];
+ long len = RSTRING_LEN(result);
+
+ const char *tmp_s;
+ long tmp_len;
+ RSTRING_GETMEM(tmp, tmp_s, tmp_len);
+
+ if (isdirsep(tmp_s[0])) {
+ // right side has a leading separator, remove left side separators.
+ long trailing_seps = 0;
+ while (isdirsep(name[len - trailing_seps - 1])) {
+ trailing_seps++;
+ }
+ rb_str_set_len(result, len - trailing_seps);
+ }
+ else if (!isdirsep(name[len - 1])) {
+ // neither side have a separator, append one;
+ rb_str_cat(result, "/", 1);
+ }
+
+ if (RB_UNLIKELY(ENCODING_GET_INLINED(tmp) != encidx)) {
+ rb_encoding *new_enc = fs_enc_check(result, tmp);
+ rb_enc_associate(result, new_enc);
+ encidx = rb_enc_to_index(new_enc);
+ }
+
+ rb_str_buf_cat(result, tmp_s, tmp_len);
+ }
+
+ rb_str_null_check(result);
+ return result;
+}
+
+static inline VALUE
+rb_file_join(long argc, VALUE *args)
+{
+ if (RB_UNLIKELY(argc == 0)) {
+ return rb_str_new(0, 0);
+ }
+
+ VALUE result = rb_file_join_fastpath(argc, args);
+ if (RB_LIKELY(result)) {
+ return result;
+ }
+
+ return rb_file_join_ary(rb_ary_new_from_values(argc, args));
+}
/*
* call-seq:
* File.join(string, ...) -> string
@@ -5176,9 +5415,9 @@ rb_file_join(VALUE ary)
*/
static VALUE
-rb_file_s_join(VALUE klass, VALUE args)
+rb_file_s_join(int argc, VALUE *argv, VALUE klass)
{
- return rb_file_join(args);
+ return rb_file_join(argc, argv);
}
#if defined(HAVE_TRUNCATE)
@@ -5270,7 +5509,7 @@ rb_file_truncate(VALUE obj, VALUE len)
}
rb_io_flush_raw(obj, 0);
fa.fd = fptr->fd;
- if ((int)rb_thread_io_blocking_region(nogvl_ftruncate, &fa, fa.fd) < 0) {
+ if ((int)rb_io_blocking_region(fptr, nogvl_ftruncate, &fa) < 0) {
rb_sys_fail_path(fptr->pathv);
}
return INT2FIX(0);
@@ -5318,7 +5557,7 @@ rb_thread_flock(void *data)
* call-seq:
* flock(locking_constant) -> 0 or false
*
- * Locks or unlocks file +self+ according to the given `locking_constant`,
+ * Locks or unlocks file `self` according to the given `locking_constant`,
* a bitwise OR of the values in the table below.
*
* Not available on all platforms.
@@ -5326,16 +5565,12 @@ rb_thread_flock(void *data)
* Returns `false` if `File::LOCK_NB` is specified and the operation would have blocked;
* otherwise returns `0`.
*
- * <br>
- *
* | Constant | Lock | Effect
- * |-----------------|--------------|-------------------------------------------------------------------
- * | +File::LOCK_EX+ | Exclusive | Only one process may hold an exclusive lock for +self+ at a time.
- * | +File::LOCK_NB+ | Non-blocking | No blocking; may be combined with +File::LOCK_SH+ or +File::LOCK_EX+ using the bitwise OR operator <tt>\|</tt>.
- * | +File::LOCK_SH+ | Shared | Multiple processes may each hold a shared lock for +self+ at the same time.
- * | +File::LOCK_UN+ | Unlock | Remove an existing lock held by this process.
- *
- * <br>
+ * |-----------------|--------------|-----------------------------------------------------------------------------------------------------------------|
+ * | `File::LOCK_EX` | Exclusive | Only one process may hold an exclusive lock for `self` at a time. |
+ * | `File::LOCK_NB` | Non-blocking | No blocking; may be combined with `File::LOCK_SH` or `File::LOCK_EX` using the bitwise OR operator <tt>\|</tt>. |
+ * | `File::LOCK_SH` | Shared | Multiple processes may each hold a shared lock for `self` at the same time. |
+ * | `File::LOCK_UN` | Unlock | Remove an existing lock held by this process. |
*
* Example:
*
@@ -5374,7 +5609,7 @@ rb_file_flock(VALUE obj, VALUE operation)
if (fptr->mode & FMODE_WRITABLE) {
rb_io_flush_raw(obj, 0);
}
- while ((int)rb_thread_io_blocking_region(rb_thread_flock, op, fptr->fd) < 0) {
+ while ((int)rb_io_blocking_region(fptr, rb_thread_flock, op) < 0) {
int e = errno;
switch (e) {
case EAGAIN:
@@ -5451,22 +5686,22 @@ test_check(int n, int argc, VALUE *argv)
* | <tt>'o'</tt> | Whether the entity is owned by the caller's effective uid. |
* | <tt>'O'</tt> | Like <tt>'o'</tt>, but uses the real uid (not the effective uid). |
* | <tt>'p'</tt> | Whether the entity is a FIFO device (named pipe). |
- * | <tt>'r'</tt> | Whether the entity is readable by the caller's effecive uid/gid. |
+ * | <tt>'r'</tt> | Whether the entity is readable by the caller's effective uid/gid. |
* | <tt>'R'</tt> | Like <tt>'r'</tt>, but uses the real uid/gid (not the effective uid/gid). |
* | <tt>'S'</tt> | Whether the entity is a socket. |
* | <tt>'u'</tt> | Whether the entity's setuid bit is set. |
* | <tt>'w'</tt> | Whether the entity is writable by the caller's effective uid/gid. |
* | <tt>'W'</tt> | Like <tt>'w'</tt>, but uses the real uid/gid (not the effective uid/gid). |
* | <tt>'x'</tt> | Whether the entity is executable by the caller's effective uid/gid. |
- * | <tt>'X'</tt> | Like <tt>'x'</tt>, but uses the real uid/gid (not the effecive uid/git). |
+ * | <tt>'X'</tt> | Like <tt>'x'</tt>, but uses the real uid/gid (not the effective uid/git). |
* | <tt>'z'</tt> | Whether the entity exists and is of length zero. |
*
* - This test operates only on the entity at `path0`,
- * and returns an integer size or +nil+:
+ * and returns an integer size or `nil`:
*
* | Character | Test |
* |:------------:|:---------------------------------------------------------------------------------------------|
- * | <tt>'s'</tt> | Returns positive integer size if the entity exists and has non-zero length, +nil+ otherwise. |
+ * | <tt>'s'</tt> | Returns positive integer size if the entity exists and has non-zero length, `nil` otherwise. |
*
* - Each of these tests operates only on the entity at `path0`,
* and returns a Time object;
@@ -5608,7 +5843,7 @@ rb_f_test(int argc, VALUE *argv, VALUE _)
if (strchr("=<>", cmd)) {
struct stat st1, st2;
- struct timespec t1, t2;
+ stat_timestamp t1, t2;
CHECK(2);
if (rb_stat(argv[1], &st1) < 0) return Qfalse;
@@ -5660,12 +5895,13 @@ rb_f_test(int argc, VALUE *argv, VALUE _)
static VALUE
rb_stat_s_alloc(VALUE klass)
{
- return stat_new_0(klass, 0);
+ VALUE obj;
+ stat_alloc(rb_cStat, &obj);
+ return obj;
}
/*
* call-seq:
- *
* File::Stat.new(file_name) -> stat
*
* Create a File::Stat object for the given file name (raising an
@@ -5675,11 +5911,11 @@ rb_stat_s_alloc(VALUE klass)
static VALUE
rb_stat_init(VALUE obj, VALUE fname)
{
- struct stat st;
+ rb_io_stat_data st;
FilePathValue(fname);
fname = rb_str_encode_ospath(fname);
- if (STAT(StringValueCStr(fname), &st) == -1) {
+ if (STATX(StringValueCStr(fname), &st, STATX_ALL) == -1) {
rb_sys_fail_path(fname);
}
@@ -5725,7 +5961,7 @@ rb_stat_init_copy(VALUE copy, VALUE orig)
static VALUE
rb_stat_ftype(VALUE obj)
{
- return rb_file_ftype(get_stat(obj));
+ return rb_file_ftype(get_stat(obj)->ST_(mode));
}
/*
@@ -5742,7 +5978,7 @@ rb_stat_ftype(VALUE obj)
static VALUE
rb_stat_d(VALUE obj)
{
- if (S_ISDIR(get_stat(obj)->st_mode)) return Qtrue;
+ if (S_ISDIR(get_stat(obj)->ST_(mode))) return Qtrue;
return Qfalse;
}
@@ -5758,7 +5994,7 @@ static VALUE
rb_stat_p(VALUE obj)
{
#ifdef S_IFIFO
- if (S_ISFIFO(get_stat(obj)->st_mode)) return Qtrue;
+ if (S_ISFIFO(get_stat(obj)->ST_(mode))) return Qtrue;
#endif
return Qfalse;
@@ -5784,7 +6020,7 @@ static VALUE
rb_stat_l(VALUE obj)
{
#ifdef S_ISLNK
- if (S_ISLNK(get_stat(obj)->st_mode)) return Qtrue;
+ if (S_ISLNK(get_stat(obj)->ST_(mode))) return Qtrue;
#endif
return Qfalse;
}
@@ -5805,7 +6041,7 @@ static VALUE
rb_stat_S(VALUE obj)
{
#ifdef S_ISSOCK
- if (S_ISSOCK(get_stat(obj)->st_mode)) return Qtrue;
+ if (S_ISSOCK(get_stat(obj)->ST_(mode))) return Qtrue;
#endif
return Qfalse;
@@ -5828,7 +6064,7 @@ static VALUE
rb_stat_b(VALUE obj)
{
#ifdef S_ISBLK
- if (S_ISBLK(get_stat(obj)->st_mode)) return Qtrue;
+ if (S_ISBLK(get_stat(obj)->ST_(mode))) return Qtrue;
#endif
return Qfalse;
@@ -5849,7 +6085,7 @@ rb_stat_b(VALUE obj)
static VALUE
rb_stat_c(VALUE obj)
{
- if (S_ISCHR(get_stat(obj)->st_mode)) return Qtrue;
+ if (S_ISCHR(get_stat(obj)->ST_(mode))) return Qtrue;
return Qfalse;
}
@@ -5869,14 +6105,14 @@ rb_stat_c(VALUE obj)
static VALUE
rb_stat_owned(VALUE obj)
{
- if (get_stat(obj)->st_uid == geteuid()) return Qtrue;
+ if (get_stat(obj)->ST_(uid) == geteuid()) return Qtrue;
return Qfalse;
}
static VALUE
rb_stat_rowned(VALUE obj)
{
- if (get_stat(obj)->st_uid == getuid()) return Qtrue;
+ if (get_stat(obj)->ST_(uid) == getuid()) return Qtrue;
return Qfalse;
}
@@ -5896,7 +6132,7 @@ static VALUE
rb_stat_grpowned(VALUE obj)
{
#ifndef _WIN32
- if (rb_group_member(get_stat(obj)->st_gid)) return Qtrue;
+ if (rb_group_member(get_stat(obj)->ST_(gid))) return Qtrue;
#endif
return Qfalse;
}
@@ -5915,21 +6151,21 @@ rb_stat_grpowned(VALUE obj)
static VALUE
rb_stat_r(VALUE obj)
{
- struct stat *st = get_stat(obj);
+ rb_io_stat_data *st = get_stat(obj);
#ifdef USE_GETEUID
if (geteuid() == 0) return Qtrue;
#endif
#ifdef S_IRUSR
if (rb_stat_owned(obj))
- return RBOOL(st->st_mode & S_IRUSR);
+ return RBOOL(st->ST_(mode) & S_IRUSR);
#endif
#ifdef S_IRGRP
if (rb_stat_grpowned(obj))
- return RBOOL(st->st_mode & S_IRGRP);
+ return RBOOL(st->ST_(mode) & S_IRGRP);
#endif
#ifdef S_IROTH
- if (!(st->st_mode & S_IROTH)) return Qfalse;
+ if (!(st->ST_(mode) & S_IROTH)) return Qfalse;
#endif
return Qtrue;
}
@@ -5948,21 +6184,21 @@ rb_stat_r(VALUE obj)
static VALUE
rb_stat_R(VALUE obj)
{
- struct stat *st = get_stat(obj);
+ rb_io_stat_data *st = get_stat(obj);
#ifdef USE_GETEUID
if (getuid() == 0) return Qtrue;
#endif
#ifdef S_IRUSR
if (rb_stat_rowned(obj))
- return RBOOL(st->st_mode & S_IRUSR);
+ return RBOOL(st->ST_(mode) & S_IRUSR);
#endif
#ifdef S_IRGRP
- if (rb_group_member(get_stat(obj)->st_gid))
- return RBOOL(st->st_mode & S_IRGRP);
+ if (rb_group_member(get_stat(obj)->ST_(gid)))
+ return RBOOL(st->ST_(mode) & S_IRGRP);
#endif
#ifdef S_IROTH
- if (!(st->st_mode & S_IROTH)) return Qfalse;
+ if (!(st->ST_(mode) & S_IROTH)) return Qfalse;
#endif
return Qtrue;
}
@@ -5984,9 +6220,9 @@ static VALUE
rb_stat_wr(VALUE obj)
{
#ifdef S_IROTH
- struct stat *st = get_stat(obj);
- if ((st->st_mode & (S_IROTH)) == S_IROTH) {
- return UINT2NUM(st->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
+ rb_io_stat_data *st = get_stat(obj);
+ if ((st->ST_(mode) & (S_IROTH)) == S_IROTH) {
+ return UINT2NUM(st->ST_(mode) & (S_IRUGO|S_IWUGO|S_IXUGO));
}
#endif
return Qnil;
@@ -6006,21 +6242,21 @@ rb_stat_wr(VALUE obj)
static VALUE
rb_stat_w(VALUE obj)
{
- struct stat *st = get_stat(obj);
+ rb_io_stat_data *st = get_stat(obj);
#ifdef USE_GETEUID
if (geteuid() == 0) return Qtrue;
#endif
#ifdef S_IWUSR
if (rb_stat_owned(obj))
- return RBOOL(st->st_mode & S_IWUSR);
+ return RBOOL(st->ST_(mode) & S_IWUSR);
#endif
#ifdef S_IWGRP
if (rb_stat_grpowned(obj))
- return RBOOL(st->st_mode & S_IWGRP);
+ return RBOOL(st->ST_(mode) & S_IWGRP);
#endif
#ifdef S_IWOTH
- if (!(st->st_mode & S_IWOTH)) return Qfalse;
+ if (!(st->ST_(mode) & S_IWOTH)) return Qfalse;
#endif
return Qtrue;
}
@@ -6039,21 +6275,21 @@ rb_stat_w(VALUE obj)
static VALUE
rb_stat_W(VALUE obj)
{
- struct stat *st = get_stat(obj);
+ rb_io_stat_data *st = get_stat(obj);
#ifdef USE_GETEUID
if (getuid() == 0) return Qtrue;
#endif
#ifdef S_IWUSR
if (rb_stat_rowned(obj))
- return RBOOL(st->st_mode & S_IWUSR);
+ return RBOOL(st->ST_(mode) & S_IWUSR);
#endif
#ifdef S_IWGRP
- if (rb_group_member(get_stat(obj)->st_gid))
- return RBOOL(st->st_mode & S_IWGRP);
+ if (rb_group_member(get_stat(obj)->ST_(gid)))
+ return RBOOL(st->ST_(mode) & S_IWGRP);
#endif
#ifdef S_IWOTH
- if (!(st->st_mode & S_IWOTH)) return Qfalse;
+ if (!(st->ST_(mode) & S_IWOTH)) return Qfalse;
#endif
return Qtrue;
}
@@ -6075,9 +6311,9 @@ static VALUE
rb_stat_ww(VALUE obj)
{
#ifdef S_IWOTH
- struct stat *st = get_stat(obj);
- if ((st->st_mode & (S_IWOTH)) == S_IWOTH) {
- return UINT2NUM(st->st_mode & (S_IRUGO|S_IWUGO|S_IXUGO));
+ rb_io_stat_data *st = get_stat(obj);
+ if ((st->ST_(mode) & (S_IWOTH)) == S_IWOTH) {
+ return UINT2NUM(st->ST_(mode) & (S_IRUGO|S_IWUGO|S_IXUGO));
}
#endif
return Qnil;
@@ -6099,23 +6335,23 @@ rb_stat_ww(VALUE obj)
static VALUE
rb_stat_x(VALUE obj)
{
- struct stat *st = get_stat(obj);
+ rb_io_stat_data *st = get_stat(obj);
#ifdef USE_GETEUID
if (geteuid() == 0) {
- return RBOOL(st->st_mode & S_IXUGO);
+ return RBOOL(st->ST_(mode) & S_IXUGO);
}
#endif
#ifdef S_IXUSR
if (rb_stat_owned(obj))
- return RBOOL(st->st_mode & S_IXUSR);
+ return RBOOL(st->ST_(mode) & S_IXUSR);
#endif
#ifdef S_IXGRP
if (rb_stat_grpowned(obj))
- return RBOOL(st->st_mode & S_IXGRP);
+ return RBOOL(st->ST_(mode) & S_IXGRP);
#endif
#ifdef S_IXOTH
- if (!(st->st_mode & S_IXOTH)) return Qfalse;
+ if (!(st->ST_(mode) & S_IXOTH)) return Qfalse;
#endif
return Qtrue;
}
@@ -6131,23 +6367,23 @@ rb_stat_x(VALUE obj)
static VALUE
rb_stat_X(VALUE obj)
{
- struct stat *st = get_stat(obj);
+ rb_io_stat_data *st = get_stat(obj);
#ifdef USE_GETEUID
if (getuid() == 0) {
- return RBOOL(st->st_mode & S_IXUGO);
+ return RBOOL(st->ST_(mode) & S_IXUGO);
}
#endif
#ifdef S_IXUSR
if (rb_stat_rowned(obj))
- return RBOOL(st->st_mode & S_IXUSR);
+ return RBOOL(st->ST_(mode) & S_IXUSR);
#endif
#ifdef S_IXGRP
- if (rb_group_member(get_stat(obj)->st_gid))
- return RBOOL(st->st_mode & S_IXGRP);
+ if (rb_group_member(get_stat(obj)->ST_(gid)))
+ return RBOOL(st->ST_(mode) & S_IXGRP);
#endif
#ifdef S_IXOTH
- if (!(st->st_mode & S_IXOTH)) return Qfalse;
+ if (!(st->ST_(mode) & S_IXOTH)) return Qfalse;
#endif
return Qtrue;
}
@@ -6166,7 +6402,7 @@ rb_stat_X(VALUE obj)
static VALUE
rb_stat_f(VALUE obj)
{
- if (S_ISREG(get_stat(obj)->st_mode)) return Qtrue;
+ if (S_ISREG(get_stat(obj)->ST_(mode))) return Qtrue;
return Qfalse;
}
@@ -6184,7 +6420,7 @@ rb_stat_f(VALUE obj)
static VALUE
rb_stat_z(VALUE obj)
{
- if (get_stat(obj)->st_size == 0) return Qtrue;
+ if (get_stat(obj)->ST_(size) == 0) return Qtrue;
return Qfalse;
}
@@ -6203,7 +6439,7 @@ rb_stat_z(VALUE obj)
static VALUE
rb_stat_s(VALUE obj)
{
- rb_off_t size = get_stat(obj)->st_size;
+ rb_off_t size = get_stat(obj)->ST_(size);
if (size == 0) return Qnil;
return OFFT2NUM(size);
@@ -6224,7 +6460,7 @@ static VALUE
rb_stat_suid(VALUE obj)
{
#ifdef S_ISUID
- if (get_stat(obj)->st_mode & S_ISUID) return Qtrue;
+ if (get_stat(obj)->ST_(mode) & S_ISUID) return Qtrue;
#endif
return Qfalse;
}
@@ -6245,7 +6481,7 @@ static VALUE
rb_stat_sgid(VALUE obj)
{
#ifdef S_ISGID
- if (get_stat(obj)->st_mode & S_ISGID) return Qtrue;
+ if (get_stat(obj)->ST_(mode) & S_ISGID) return Qtrue;
#endif
return Qfalse;
}
@@ -6266,7 +6502,7 @@ static VALUE
rb_stat_sticky(VALUE obj)
{
#ifdef S_ISVTX
- if (get_stat(obj)->st_mode & S_ISVTX) return Qtrue;
+ if (get_stat(obj)->ST_(mode) & S_ISVTX) return Qtrue;
#endif
return Qfalse;
}
@@ -6347,95 +6583,6 @@ rb_is_absolute_path(const char *path)
return 0;
}
-#ifndef ENABLE_PATH_CHECK
-# if defined DOSISH || defined __CYGWIN__
-# define ENABLE_PATH_CHECK 0
-# else
-# define ENABLE_PATH_CHECK 1
-# endif
-#endif
-
-#if ENABLE_PATH_CHECK
-static int
-path_check_0(VALUE path)
-{
- struct stat st;
- const char *p0 = StringValueCStr(path);
- const char *e0;
- rb_encoding *enc;
- char *p = 0, *s;
-
- if (!rb_is_absolute_path(p0)) {
- char *buf = ruby_getcwd();
- VALUE newpath;
-
- newpath = rb_str_new2(buf);
- xfree(buf);
-
- rb_str_cat2(newpath, "/");
- rb_str_cat2(newpath, p0);
- path = newpath;
- p0 = RSTRING_PTR(path);
- }
- e0 = p0 + RSTRING_LEN(path);
- enc = rb_enc_get(path);
- for (;;) {
-#ifndef S_IWOTH
-# define S_IWOTH 002
-#endif
- if (STAT(p0, &st) == 0 && S_ISDIR(st.st_mode) && (st.st_mode & S_IWOTH)
-#ifdef S_ISVTX
- && !(p && (st.st_mode & S_ISVTX))
-#endif
- && !access(p0, W_OK)) {
- rb_enc_warn(enc, "Insecure world writable dir %s in PATH, mode 0%"
-#if SIZEOF_DEV_T > SIZEOF_INT
- PRI_MODET_PREFIX"o",
-#else
- "o",
-#endif
- p0, st.st_mode);
- if (p) *p = '/';
- RB_GC_GUARD(path);
- return 0;
- }
- s = strrdirsep(p0, e0, enc);
- if (p) *p = '/';
- if (!s || s == p0) return 1;
- p = s;
- e0 = p;
- *p = '\0';
- }
-}
-#endif
-
-int
-rb_path_check(const char *path)
-{
-#if ENABLE_PATH_CHECK
- const char *p0, *p, *pend;
- const char sep = PATH_SEP_CHAR;
-
- if (!path) return 1;
-
- pend = path + strlen(path);
- p0 = path;
- p = strchr(path, sep);
- if (!p) p = pend;
-
- for (;;) {
- if (!path_check_0(rb_str_new(p0, p - p0))) {
- return 0; /* not safe */
- }
- p0 = p + 1;
- if (p0 > pend) break;
- p = strchr(p0, sep);
- if (!p) p = pend;
- }
-#endif
- return 1;
-}
-
int
ruby_is_fd_loadable(int fd)
{
@@ -6638,7 +6785,7 @@ const char ruby_null_device[] =
/*
* A \File object is a representation of a file in the underlying platform.
*
- * \Class \File extends module FileTest, supporting such singleton methods
+ * Class \File extends module FileTest, supporting such singleton methods
* as <tt>File.exist?</tt>.
*
* == About the Examples
@@ -7295,7 +7442,7 @@ const char ruby_null_device[] =
*
* == What's Here
*
- * First, what's elsewhere. \Class \File:
+ * First, what's elsewhere. Class \File:
*
* - Inherits from {class IO}[rdoc-ref:IO@What-27s+Here],
* in particular, methods for creating, reading, and writing files
@@ -7512,7 +7659,7 @@ Init_File(void)
/* separates directory parts in path */
rb_define_const(rb_cFile, "SEPARATOR", separator);
rb_define_singleton_method(rb_cFile, "split", rb_file_s_split, 1);
- rb_define_singleton_method(rb_cFile, "join", rb_file_s_join, -2);
+ rb_define_singleton_method(rb_cFile, "join", rb_file_s_join, -1);
#ifdef DOSISH
/* platform specific alternative separator */
@@ -7541,7 +7688,7 @@ Init_File(void)
/*
* Document-module: File::Constants
*
- * \Module +File::Constants+ defines file-related constants.
+ * Module +File::Constants+ defines file-related constants.
*
* There are two families of constants here:
*
@@ -7816,11 +7963,11 @@ Init_File(void)
*
* ==== File::FNM_EXTGLOB
*
- * Flag File::FNM_EXTGLOB enables pattern <tt>'{_a_,_b_}'</tt>,
+ * Flag File::FNM_EXTGLOB enables pattern <tt>'{a,b}'</tt>,
* which matches pattern '_a_' and pattern '_b_';
* behaves like
* a {regexp union}[rdoc-ref:Regexp.union]
- * (e.g., <tt>'(?:_a_|_b_)'</tt>):
+ * (e.g., <tt>'(?:a|b)'</tt>):
*
* pattern = '{LEGAL,BSDL}'
* Dir.glob(pattern) # => ["LEGAL", "BSDL"]
diff --git a/gc.c b/gc.c
index f47f20fa57..ab0539cd33 100644
--- a/gc.c
+++ b/gc.c
@@ -11,21 +11,11 @@
**********************************************************************/
-#define rb_data_object_alloc rb_data_object_alloc
-#define rb_data_typed_object_alloc rb_data_typed_object_alloc
-
#include "ruby/internal/config.h"
#ifdef _WIN32
# include "ruby/ruby.h"
#endif
-#include <signal.h>
-
-#ifndef _WIN32
-#include <unistd.h>
-#include <sys/mman.h>
-#endif
-
#if defined(__wasm__) && !defined(__EMSCRIPTEN__)
# include "wasm/setjmp.h"
# include "wasm/machine.h"
@@ -58,19 +48,6 @@
# endif
#endif
-#ifdef HAVE_MALLOC_TRIM
-# include <malloc.h>
-
-# ifdef __EMSCRIPTEN__
-/* malloc_trim is defined in emscripten/emmalloc.h on emscripten. */
-# include <emscripten/emmalloc.h>
-# endif
-#endif
-
-#if !defined(PAGE_SIZE) && defined(HAVE_SYS_USER_H)
-/* LIST_HEAD conflicts with sys/queue.h on macOS */
-# include <sys/user.h>
-#endif
/* MALLOC_HEADERS_END */
#ifdef HAVE_SYS_TIME_H
@@ -94,22 +71,24 @@
#include <emscripten.h>
#endif
-#ifdef HAVE_MACH_TASK_EXCEPTION_PORTS
-# include <mach/task.h>
-# include <mach/mach_init.h>
-# include <mach/mach_port.h>
+/* For ruby_annotate_mmap */
+#ifdef HAVE_SYS_PRCTL_H
+#include <sys/prctl.h>
#endif
+
#undef LIST_HEAD /* ccan/list conflicts with BSD-origin sys/queue.h. */
#include "constant.h"
#include "darray.h"
#include "debug_counter.h"
#include "eval_intern.h"
+#include "gc/gc.h"
#include "id_table.h"
#include "internal.h"
#include "internal/class.h"
#include "internal/compile.h"
#include "internal/complex.h"
+#include "internal/concurrent_set.h"
#include "internal/cont.h"
#include "internal/error.h"
#include "internal/eval.h"
@@ -127,7 +106,6 @@
#include "internal/thread.h"
#include "internal/variable.h"
#include "internal/warnings.h"
-#include "rjit.h"
#include "probes.h"
#include "regint.h"
#include "ruby/debug.h"
@@ -136,17 +114,282 @@
#include "ruby/st.h"
#include "ruby/thread.h"
#include "ruby/util.h"
+#include "ruby/vm.h"
#include "ruby_assert.h"
#include "ruby_atomic.h"
#include "symbol.h"
+#include "variable.h"
#include "vm_core.h"
#include "vm_sync.h"
#include "vm_callinfo.h"
#include "ractor_core.h"
+#include "yjit.h"
+#include "zjit.h"
#include "builtin.h"
#include "shape.h"
+// TODO: Don't export this function in modular GC, instead MMTk should figure out
+// how to combine GC thread backtrace with mutator thread backtrace.
+void
+rb_gc_print_backtrace(void)
+{
+ rb_print_backtrace(stderr);
+}
+
+unsigned int
+rb_gc_vm_lock(const char *file, int line)
+{
+ unsigned int lev = 0;
+ rb_vm_lock_enter(&lev, file, line);
+ return lev;
+}
+
+void
+rb_gc_vm_unlock(unsigned int lev, const char *file, int line)
+{
+ rb_vm_lock_leave(&lev, file, line);
+}
+
+unsigned int
+rb_gc_cr_lock(const char *file, int line)
+{
+ unsigned int lev;
+ rb_vm_lock_enter_cr(GET_RACTOR(), &lev, file, line);
+ return lev;
+}
+
+void
+rb_gc_cr_unlock(unsigned int lev, const char *file, int line)
+{
+ rb_vm_lock_leave_cr(GET_RACTOR(), &lev, file, line);
+}
+
+unsigned int
+rb_gc_vm_lock_no_barrier(const char *file, int line)
+{
+ unsigned int lev = 0;
+ rb_vm_lock_enter_nb(&lev, file, line);
+ return lev;
+}
+
+void
+rb_gc_vm_unlock_no_barrier(unsigned int lev, const char *file, int line)
+{
+ rb_vm_lock_leave_nb(&lev, file, line);
+}
+
+void
+rb_gc_vm_barrier(void)
+{
+ rb_vm_barrier();
+}
+
+void *
+rb_gc_get_ractor_newobj_cache(void)
+{
+ return GET_RACTOR()->newobj_cache;
+}
+
+#if USE_MODULAR_GC
+void
+rb_gc_initialize_vm_context(struct rb_gc_vm_context *context)
+{
+ rb_native_mutex_initialize(&context->lock);
+ context->ec = GET_EC();
+}
+
+void
+rb_gc_worker_thread_set_vm_context(struct rb_gc_vm_context *context)
+{
+ rb_native_mutex_lock(&context->lock);
+
+ GC_ASSERT(rb_current_execution_context(false) == NULL);
+
+#ifdef RB_THREAD_LOCAL_SPECIFIER
+ rb_current_ec_set(context->ec);
+#else
+ native_tls_set(ruby_current_ec_key, context->ec);
+#endif
+}
+
+void
+rb_gc_worker_thread_unset_vm_context(struct rb_gc_vm_context *context)
+{
+ rb_native_mutex_unlock(&context->lock);
+
+ GC_ASSERT(rb_current_execution_context(true) == context->ec);
+
+#ifdef RB_THREAD_LOCAL_SPECIFIER
+ rb_current_ec_set(NULL);
+#else
+ native_tls_set(ruby_current_ec_key, NULL);
+#endif
+}
+#endif
+
+bool
+rb_gc_event_hook_required_p(rb_event_flag_t event)
+{
+ return ruby_vm_event_flags & event;
+}
+
+void
+rb_gc_event_hook(VALUE obj, rb_event_flag_t event)
+{
+ if (LIKELY(!rb_gc_event_hook_required_p(event))) return;
+
+ rb_execution_context_t *ec = GET_EC();
+ if (!ec->cfp) return;
+
+ EXEC_EVENT_HOOK(ec, event, ec->cfp->self, 0, 0, 0, obj);
+}
+
+void *
+rb_gc_get_objspace(void)
+{
+ return GET_VM()->gc.objspace;
+}
+
+
+void
+rb_gc_ractor_newobj_cache_foreach(void (*func)(void *cache, void *data), void *data)
+{
+ rb_ractor_t *r = NULL;
+ if (RB_LIKELY(ruby_single_main_ractor)) {
+ GC_ASSERT(
+ ccan_list_empty(&GET_VM()->ractor.set) ||
+ (ccan_list_top(&GET_VM()->ractor.set, rb_ractor_t, vmlr_node) == ruby_single_main_ractor &&
+ ccan_list_tail(&GET_VM()->ractor.set, rb_ractor_t, vmlr_node) == ruby_single_main_ractor)
+ );
+
+ func(ruby_single_main_ractor->newobj_cache, data);
+ }
+ else {
+ ccan_list_for_each(&GET_VM()->ractor.set, r, vmlr_node) {
+ func(r->newobj_cache, data);
+ }
+ }
+}
+
+void
+rb_gc_run_obj_finalizer(VALUE objid, long count, VALUE (*callback)(long i, void *data), void *data)
+{
+ volatile struct {
+ VALUE errinfo;
+ VALUE final;
+ rb_control_frame_t *cfp;
+ VALUE *sp;
+ long finished;
+ } saved;
+
+ rb_execution_context_t * volatile ec = GET_EC();
+#define RESTORE_FINALIZER() (\
+ ec->cfp = saved.cfp, \
+ ec->cfp->sp = saved.sp, \
+ ec->errinfo = saved.errinfo)
+
+ saved.errinfo = ec->errinfo;
+ saved.cfp = ec->cfp;
+ saved.sp = ec->cfp->sp;
+ saved.finished = 0;
+ saved.final = Qundef;
+
+ ASSERT_vm_unlocking();
+ rb_ractor_ignore_belonging(true);
+ EC_PUSH_TAG(ec);
+ enum ruby_tag_type state = EC_EXEC_TAG();
+ if (state != TAG_NONE) {
+ ++saved.finished; /* skip failed finalizer */
+
+ VALUE failed_final = saved.final;
+ saved.final = Qundef;
+ if (!UNDEF_P(failed_final) && !NIL_P(ruby_verbose)) {
+ rb_warn("Exception in finalizer %+"PRIsVALUE, failed_final);
+ rb_ec_error_print(ec, ec->errinfo);
+ }
+ }
+
+ for (long i = saved.finished; RESTORE_FINALIZER(), i < count; saved.finished = ++i) {
+ saved.final = callback(i, data);
+ rb_check_funcall(saved.final, idCall, 1, &objid);
+ }
+ EC_POP_TAG();
+ rb_ractor_ignore_belonging(false);
+#undef RESTORE_FINALIZER
+}
+
+void
+rb_gc_set_pending_interrupt(void)
+{
+ rb_execution_context_t *ec = GET_EC();
+ ec->interrupt_mask |= PENDING_INTERRUPT_MASK;
+}
+
+void
+rb_gc_unset_pending_interrupt(void)
+{
+ rb_execution_context_t *ec = GET_EC();
+ ec->interrupt_mask &= ~PENDING_INTERRUPT_MASK;
+}
+
+bool
+rb_gc_multi_ractor_p(void)
+{
+ return rb_multi_ractor_p();
+}
+
+bool
+rb_gc_shutdown_call_finalizer_p(VALUE obj)
+{
+ switch (BUILTIN_TYPE(obj)) {
+ case T_DATA:
+ if (!ruby_free_at_exit_p() && (!DATA_PTR(obj) || !RDATA(obj)->dfree)) return false;
+ if (rb_obj_is_thread(obj)) return false;
+ if (rb_obj_is_mutex(obj)) return false;
+ if (rb_obj_is_fiber(obj)) return false;
+ if (rb_ractor_p(obj)) return false;
+ if (rb_obj_is_fstring_table(obj)) return false;
+ if (rb_obj_is_symbol_table(obj)) return false;
+
+ return true;
+
+ case T_FILE:
+ return true;
+
+ case T_SYMBOL:
+ return true;
+
+ case T_NONE:
+ return false;
+
+ default:
+ return ruby_free_at_exit_p();
+ }
+}
+
+uint32_t
+rb_gc_get_shape(VALUE obj)
+{
+ return (uint32_t)rb_obj_shape_id(obj);
+}
+
+void
+rb_gc_set_shape(VALUE obj, uint32_t shape_id)
+{
+ RBASIC_SET_SHAPE_ID(obj, (uint32_t)shape_id);
+}
+
+uint32_t
+rb_gc_rebuild_shape(VALUE obj, size_t heap_id)
+{
+ RUBY_ASSERT(RB_TYPE_P(obj, T_OBJECT));
+
+ return (uint32_t)rb_shape_transition_heap(obj, heap_id);
+}
+
+void rb_vm_update_references(void *ptr);
+
#define rb_setjmp(env) RUBY_SETJMP(env)
#define rb_jmp_buf rb_jmpbuf_t
#undef rb_data_object_wrap
@@ -155,6 +398,35 @@
#define MAP_ANONYMOUS MAP_ANON
#endif
+#define unless_objspace(objspace) \
+ void *objspace; \
+ rb_vm_t *unless_objspace_vm = GET_VM(); \
+ if (unless_objspace_vm) objspace = unless_objspace_vm->gc.objspace; \
+ else /* return; or objspace will be warned uninitialized */
+
+#define RMOVED(obj) ((struct RMoved *)(obj))
+
+#define TYPED_UPDATE_IF_MOVED(_objspace, _type, _thing) do { \
+ if (gc_object_moved_p_internal((_objspace), (VALUE)(_thing))) { \
+ *(_type *)&(_thing) = (_type)gc_location_internal(_objspace, (VALUE)_thing); \
+ } \
+} while (0)
+
+#define UPDATE_IF_MOVED(_objspace, _thing) TYPED_UPDATE_IF_MOVED(_objspace, VALUE, _thing)
+
+#if RUBY_MARK_FREE_DEBUG
+int ruby_gc_debug_indent = 0;
+#endif
+
+#ifndef RGENGC_OBJ_INFO
+# define RGENGC_OBJ_INFO RGENGC_CHECK_MODE
+#endif
+
+#ifndef CALC_EXACT_MALLOC_SIZE
+# define CALC_EXACT_MALLOC_SIZE 0
+#endif
+
+VALUE rb_mGC;
static size_t malloc_offset = 0;
#if defined(HAVE_MALLOC_USABLE_SIZE)
@@ -217,49 +489,21 @@ rb_malloc_grow_capa(size_t current, size_t type_size)
return new_capacity;
}
-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(ckd_add)
- p = ckd_add(&z, x, y);
-
-#elif __has_builtin(__builtin_add_overflow)
- p = __builtin_add_overflow(x, y, &z);
-
-#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;
-
-#else
- z = x + y;
- p = z < y;
-
-#endif
- return (struct rbimpl_size_mul_overflow_tag) { p, z, };
-}
-
-static inline struct rbimpl_size_mul_overflow_tag
+static inline struct rbimpl_size_overflow_tag
size_mul_add_overflow(size_t x, size_t y, size_t z) /* x * y + z */
{
- 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 };
+ struct rbimpl_size_overflow_tag t = rbimpl_size_mul_overflow(x, y);
+ struct rbimpl_size_overflow_tag u = rbimpl_size_add_overflow(t.result, z);
+ return (struct rbimpl_size_overflow_tag) { t.overflowed || u.overflowed, u.result };
}
-static inline struct rbimpl_size_mul_overflow_tag
+static inline struct rbimpl_size_overflow_tag
size_mul_add_mul_overflow(size_t x, size_t y, size_t z, size_t w) /* x * y + z * w */
{
- 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 };
+ struct rbimpl_size_overflow_tag t = rbimpl_size_mul_overflow(x, y);
+ struct rbimpl_size_overflow_tag u = rbimpl_size_mul_overflow(z, w);
+ struct rbimpl_size_overflow_tag v = rbimpl_size_add_overflow(t.result, u.result);
+ return (struct rbimpl_size_overflow_tag) { t.overflowed || u.overflowed || v.overflowed, v.result };
}
PRINTF_ARGS(NORETURN(static void gc_raise(VALUE, const char*, ...)), 2, 3);
@@ -267,9 +511,9 @@ 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 rbimpl_size_mul_overflow_tag t = rbimpl_size_mul_overflow(x, y);
- if (LIKELY(!t.left)) {
- return t.right;
+ struct rbimpl_size_overflow_tag t = rbimpl_size_mul_overflow(x, y);
+ if (LIKELY(!t.overflowed)) {
+ return t.result;
}
else if (rb_during_gc()) {
rb_memerror(); /* or...? */
@@ -293,9 +537,9 @@ 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 rbimpl_size_mul_overflow_tag t = size_mul_add_overflow(x, y, z);
- if (LIKELY(!t.left)) {
- return t.right;
+ struct rbimpl_size_overflow_tag t = size_mul_add_overflow(x, y, z);
+ if (LIKELY(!t.overflowed)) {
+ return t.result;
}
else if (rb_during_gc()) {
rb_memerror(); /* or...? */
@@ -320,9 +564,9 @@ 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 rbimpl_size_mul_overflow_tag t = size_mul_add_mul_overflow(x, y, z, w);
- if (LIKELY(!t.left)) {
- return t.right;
+ struct rbimpl_size_overflow_tag t = size_mul_add_mul_overflow(x, y, z, w);
+ if (LIKELY(!t.overflowed)) {
+ return t.result;
}
else if (rb_during_gc()) {
rb_memerror(); /* or...? */
@@ -351,2619 +595,475 @@ rb_gc_guarded_ptr_val(volatile VALUE *ptr, VALUE val)
}
#endif
-#ifndef GC_HEAP_INIT_SLOTS
-#define GC_HEAP_INIT_SLOTS 10000
-#endif
-#ifndef GC_HEAP_FREE_SLOTS
-#define GC_HEAP_FREE_SLOTS 4096
-#endif
-#ifndef GC_HEAP_GROWTH_FACTOR
-#define GC_HEAP_GROWTH_FACTOR 1.8
-#endif
-#ifndef GC_HEAP_GROWTH_MAX_SLOTS
-#define GC_HEAP_GROWTH_MAX_SLOTS 0 /* 0 is disable */
-#endif
-#ifndef GC_HEAP_REMEMBERED_WB_UNPROTECTED_OBJECTS_LIMIT_RATIO
-# define GC_HEAP_REMEMBERED_WB_UNPROTECTED_OBJECTS_LIMIT_RATIO 0.01
-#endif
-#ifndef GC_HEAP_OLDOBJECT_LIMIT_FACTOR
-#define GC_HEAP_OLDOBJECT_LIMIT_FACTOR 2.0
-#endif
-
-#ifndef GC_HEAP_FREE_SLOTS_MIN_RATIO
-#define GC_HEAP_FREE_SLOTS_MIN_RATIO 0.20
-#endif
-#ifndef GC_HEAP_FREE_SLOTS_GOAL_RATIO
-#define GC_HEAP_FREE_SLOTS_GOAL_RATIO 0.40
-#endif
-#ifndef GC_HEAP_FREE_SLOTS_MAX_RATIO
-#define GC_HEAP_FREE_SLOTS_MAX_RATIO 0.65
-#endif
-
-#ifndef GC_MALLOC_LIMIT_MIN
-#define GC_MALLOC_LIMIT_MIN (16 * 1024 * 1024 /* 16MB */)
-#endif
-#ifndef GC_MALLOC_LIMIT_MAX
-#define GC_MALLOC_LIMIT_MAX (32 * 1024 * 1024 /* 32MB */)
-#endif
-#ifndef GC_MALLOC_LIMIT_GROWTH_FACTOR
-#define GC_MALLOC_LIMIT_GROWTH_FACTOR 1.4
-#endif
-
-#ifndef GC_OLDMALLOC_LIMIT_MIN
-#define GC_OLDMALLOC_LIMIT_MIN (16 * 1024 * 1024 /* 16MB */)
-#endif
-#ifndef GC_OLDMALLOC_LIMIT_GROWTH_FACTOR
-#define GC_OLDMALLOC_LIMIT_GROWTH_FACTOR 1.2
-#endif
-#ifndef GC_OLDMALLOC_LIMIT_MAX
-#define GC_OLDMALLOC_LIMIT_MAX (128 * 1024 * 1024 /* 128MB */)
-#endif
-
-#ifndef GC_CAN_COMPILE_COMPACTION
-#if defined(__wasi__) /* WebAssembly doesn't support signals */
-# define GC_CAN_COMPILE_COMPACTION 0
-#else
-# define GC_CAN_COMPILE_COMPACTION 1
-#endif
-#endif
-
-#ifndef PRINT_MEASURE_LINE
-#define PRINT_MEASURE_LINE 0
-#endif
-#ifndef PRINT_ENTER_EXIT_TICK
-#define PRINT_ENTER_EXIT_TICK 0
-#endif
-#ifndef PRINT_ROOT_TICKS
-#define PRINT_ROOT_TICKS 0
-#endif
-
-#define USE_TICK_T (PRINT_ENTER_EXIT_TICK || PRINT_MEASURE_LINE || PRINT_ROOT_TICKS)
-
-typedef struct {
- size_t size_pool_init_slots[SIZE_POOL_COUNT];
- size_t heap_free_slots;
- double growth_factor;
- size_t growth_max_slots;
-
- double heap_free_slots_min_ratio;
- double heap_free_slots_goal_ratio;
- double heap_free_slots_max_ratio;
- double uncollectible_wb_unprotected_objects_limit_ratio;
- double oldobject_limit_factor;
-
- size_t malloc_limit_min;
- size_t malloc_limit_max;
- double malloc_limit_growth_factor;
-
- size_t oldmalloc_limit_min;
- size_t oldmalloc_limit_max;
- double oldmalloc_limit_growth_factor;
-} ruby_gc_params_t;
-
-static ruby_gc_params_t gc_params = {
- { 0 },
- GC_HEAP_FREE_SLOTS,
- GC_HEAP_GROWTH_FACTOR,
- GC_HEAP_GROWTH_MAX_SLOTS,
-
- GC_HEAP_FREE_SLOTS_MIN_RATIO,
- GC_HEAP_FREE_SLOTS_GOAL_RATIO,
- GC_HEAP_FREE_SLOTS_MAX_RATIO,
- GC_HEAP_REMEMBERED_WB_UNPROTECTED_OBJECTS_LIMIT_RATIO,
- GC_HEAP_OLDOBJECT_LIMIT_FACTOR,
-
- GC_MALLOC_LIMIT_MIN,
- GC_MALLOC_LIMIT_MAX,
- GC_MALLOC_LIMIT_GROWTH_FACTOR,
-
- GC_OLDMALLOC_LIMIT_MIN,
- GC_OLDMALLOC_LIMIT_MAX,
- GC_OLDMALLOC_LIMIT_GROWTH_FACTOR,
-};
-
-/* GC_DEBUG:
- * enable to embed GC debugging information.
- */
-#ifndef GC_DEBUG
-#define GC_DEBUG 0
-#endif
-
-/* RGENGC_DEBUG:
- * 1: basic information
- * 2: remember set operation
- * 3: mark
- * 4:
- * 5: sweep
- */
-#ifndef RGENGC_DEBUG
-#ifdef RUBY_DEVEL
-#define RGENGC_DEBUG -1
-#else
-#define RGENGC_DEBUG 0
-#endif
-#endif
-#if RGENGC_DEBUG < 0 && !defined(_MSC_VER)
-# define RGENGC_DEBUG_ENABLED(level) (-(RGENGC_DEBUG) >= (level) && ruby_rgengc_debug >= (level))
-#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;
-
-/* RGENGC_CHECK_MODE
- * 0: disable all assertions
- * 1: enable assertions (to debug RGenGC)
- * 2: enable internal consistency check at each GC (for debugging)
- * 3: enable internal consistency check at each GC steps (for debugging)
- * 4: enable liveness check
- * 5: show all references
- */
-#ifndef RGENGC_CHECK_MODE
-#define RGENGC_CHECK_MODE 0
-#endif
-
-// Note: using RUBY_ASSERT_WHEN() extend a macro in expr (info by nobu).
-#define GC_ASSERT(expr) RUBY_ASSERT_MESG_WHEN(RGENGC_CHECK_MODE > 0, expr, #expr)
-
-/* RGENGC_PROFILE
- * 0: disable RGenGC profiling
- * 1: enable profiling for basic information
- * 2: enable profiling for each types
- */
-#ifndef RGENGC_PROFILE
-#define RGENGC_PROFILE 0
-#endif
-
-/* RGENGC_ESTIMATE_OLDMALLOC
- * Enable/disable to estimate increase size of malloc'ed size by old objects.
- * If estimation exceeds threshold, then will invoke full GC.
- * 0: disable estimation.
- * 1: enable estimation.
- */
-#ifndef RGENGC_ESTIMATE_OLDMALLOC
-#define RGENGC_ESTIMATE_OLDMALLOC 1
-#endif
-
-/* RGENGC_FORCE_MAJOR_GC
- * Force major/full GC if this macro is not 0.
- */
-#ifndef RGENGC_FORCE_MAJOR_GC
-#define RGENGC_FORCE_MAJOR_GC 0
-#endif
-
-#ifndef GC_PROFILE_MORE_DETAIL
-#define GC_PROFILE_MORE_DETAIL 0
-#endif
-#ifndef GC_PROFILE_DETAIL_MEMORY
-#define GC_PROFILE_DETAIL_MEMORY 0
-#endif
-#ifndef GC_ENABLE_LAZY_SWEEP
-#define GC_ENABLE_LAZY_SWEEP 1
-#endif
-#ifndef CALC_EXACT_MALLOC_SIZE
-#define CALC_EXACT_MALLOC_SIZE USE_GC_MALLOC_OBJ_INFO_DETAILS
-#endif
-#if defined(HAVE_MALLOC_USABLE_SIZE) || CALC_EXACT_MALLOC_SIZE > 0
-#ifndef MALLOC_ALLOCATED_SIZE
-#define MALLOC_ALLOCATED_SIZE 0
-#endif
-#else
-#define MALLOC_ALLOCATED_SIZE 0
-#endif
-#ifndef MALLOC_ALLOCATED_SIZE_CHECK
-#define MALLOC_ALLOCATED_SIZE_CHECK 0
-#endif
-
-#ifndef GC_DEBUG_STRESS_TO_CLASS
-#define GC_DEBUG_STRESS_TO_CLASS RUBY_DEBUG
-#endif
-
-#ifndef RGENGC_OBJ_INFO
-#define RGENGC_OBJ_INFO (RGENGC_DEBUG | RGENGC_CHECK_MODE)
-#endif
-
-typedef enum {
- GPR_FLAG_NONE = 0x000,
- /* major reason */
- GPR_FLAG_MAJOR_BY_NOFREE = 0x001,
- GPR_FLAG_MAJOR_BY_OLDGEN = 0x002,
- GPR_FLAG_MAJOR_BY_SHADY = 0x004,
- GPR_FLAG_MAJOR_BY_FORCE = 0x008,
-#if RGENGC_ESTIMATE_OLDMALLOC
- GPR_FLAG_MAJOR_BY_OLDMALLOC = 0x020,
-#endif
- GPR_FLAG_MAJOR_MASK = 0x0ff,
-
- /* gc reason */
- GPR_FLAG_NEWOBJ = 0x100,
- GPR_FLAG_MALLOC = 0x200,
- GPR_FLAG_METHOD = 0x400,
- GPR_FLAG_CAPI = 0x800,
- GPR_FLAG_STRESS = 0x1000,
-
- /* others */
- GPR_FLAG_IMMEDIATE_SWEEP = 0x2000,
- 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 |
- GPR_FLAG_IMMEDIATE_SWEEP | GPR_FLAG_CAPI),
-} gc_profile_record_flag;
-
-typedef struct gc_profile_record {
- unsigned int flags;
-
- double gc_time;
- double gc_invoke_time;
-
- 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;
- double gc_sweep_time;
-
- size_t heap_use_pages;
- size_t heap_live_objects;
- size_t heap_free_objects;
-
- size_t allocate_increase;
- size_t allocate_limit;
-
- double prepare_time;
- size_t removing_objects;
- size_t empty_objects;
-#if GC_PROFILE_DETAIL_MEMORY
- long maxrss;
- long minflt;
- long majflt;
-#endif
-#endif
-#if MALLOC_ALLOCATED_SIZE
- size_t allocated_size;
-#endif
-
-#if RGENGC_PROFILE > 0
- size_t old_objects;
- size_t remembered_normal_objects;
- size_t remembered_shady_objects;
-#endif
-} gc_profile_record;
-
-struct RMoved {
- VALUE flags;
- VALUE dummy;
- VALUE destination;
- shape_id_t original_shape_id;
-};
-
-#define RMOVED(obj) ((struct RMoved *)(obj))
-
-typedef struct RVALUE {
- union {
- struct {
- VALUE flags; /* always 0 for freed obj */
- struct RVALUE *next;
- } free;
- struct RMoved moved;
- struct RBasic basic;
- struct RObject object;
- struct RClass klass;
- struct RFloat flonum;
- struct RString string;
- struct RArray array;
- struct RRegexp regexp;
- struct RHash hash;
- struct RData data;
- struct RTypedData typeddata;
- struct RStruct rstruct;
- struct RBignum bignum;
- struct RFile file;
- struct RMatch match;
- struct RRational rational;
- struct RComplex complex;
- struct RSymbol symbol;
- union {
- rb_cref_t cref;
- struct vm_svar svar;
- struct vm_throw_data throw_data;
- struct vm_ifunc ifunc;
- struct MEMO memo;
- struct rb_method_entry_struct ment;
- const rb_iseq_t iseq;
- rb_env_t env;
- struct rb_imemo_tmpbuf_struct alloc;
- rb_ast_t ast;
- } imemo;
- struct {
- struct RBasic basic;
- VALUE v1;
- VALUE v2;
- VALUE v3;
- } values;
- } as;
-} RVALUE;
-
-/* These members ae located at the end of the slot that the object is in. */
-#if RACTOR_CHECK_MODE || GC_DEBUG
-struct rvalue_overhead {
-# if RACTOR_CHECK_MODE
- uint32_t _ractor_belonging_id;
-# endif
-# if GC_DEBUG
- const char *file;
- int line;
-# endif
-};
-
-// Make sure that RVALUE_OVERHEAD aligns to sizeof(VALUE)
-# define RVALUE_OVERHEAD (sizeof(struct { \
- union { \
- struct rvalue_overhead overhead; \
- VALUE value; \
- }; \
-}))
-# define GET_RVALUE_OVERHEAD(obj) ((struct rvalue_overhead *)((uintptr_t)obj + rb_gc_obj_slot_size(obj)))
-#else
-# define RVALUE_OVERHEAD 0
-#endif
-
-STATIC_ASSERT(sizeof_rvalue, sizeof(RVALUE) == (SIZEOF_VALUE * 5));
-STATIC_ASSERT(alignof_rvalue, RUBY_ALIGNOF(RVALUE) == SIZEOF_VALUE);
-
-typedef uintptr_t bits_t;
-enum {
- BITS_SIZE = sizeof(bits_t),
- BITS_BITLENGTH = ( BITS_SIZE * CHAR_BIT )
-};
-
-struct heap_page_header {
- struct heap_page *page;
-};
-
-struct heap_page_body {
- struct heap_page_header header;
- /* char gap[]; */
- /* RVALUE values[]; */
-};
-
-#define STACK_CHUNK_SIZE 500
-
-typedef struct stack_chunk {
- VALUE data[STACK_CHUNK_SIZE];
- struct stack_chunk *next;
-} stack_chunk_t;
-
-typedef struct mark_stack {
- stack_chunk_t *chunk;
- stack_chunk_t *cache;
- int index;
- int limit;
- size_t cache_size;
- size_t unused_cache_size;
-} mark_stack_t;
-
-#define SIZE_POOL_EDEN_HEAP(size_pool) (&(size_pool)->eden_heap)
-#define SIZE_POOL_TOMB_HEAP(size_pool) (&(size_pool)->tomb_heap)
-
-typedef int (*gc_compact_compare_func)(const void *l, const void *r, void *d);
-
-typedef struct rb_heap_struct {
- struct heap_page *free_pages;
- struct ccan_list_head pages;
- struct heap_page *sweeping_page; /* iterator for .pages */
- struct heap_page *compact_cursor;
- uintptr_t compact_cursor_index;
- struct heap_page *pooled_pages;
- size_t total_pages; /* total page count in a heap */
- 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;
-
- /* Basic statistics */
- size_t total_allocated_pages;
- size_t total_freed_pages;
- size_t force_major_gc_count;
- size_t force_incremental_marking_finish_count;
- size_t total_allocated_objects;
- size_t total_freed_objects;
-
- /* Sweeping statistics */
- size_t freed_slots;
- size_t empty_slots;
-
- rb_heap_t eden_heap;
- rb_heap_t tomb_heap;
-} rb_size_pool_t;
-
-enum gc_mode {
- gc_mode_none,
- gc_mode_marking,
- gc_mode_sweeping,
- gc_mode_compacting,
-};
-
-typedef struct rb_objspace {
- struct {
- size_t limit;
- size_t increase;
-#if MALLOC_ALLOCATED_SIZE
- size_t allocated_size;
- size_t allocations;
-#endif
-
- } malloc_params;
-
- struct {
- unsigned int mode : 2;
- unsigned int immediate_sweep : 1;
- unsigned int dont_gc : 1;
- unsigned int dont_incremental : 1;
- unsigned int during_gc : 1;
- unsigned int during_compacting : 1;
- unsigned int during_reference_updating : 1;
- unsigned int gc_stressful: 1;
- unsigned int has_newobj_hook: 1;
- unsigned int during_minor_gc : 1;
- unsigned int during_incremental_marking : 1;
- unsigned int measure_gc : 1;
- } flags;
-
- rb_event_flag_t hook_events;
- unsigned long long next_object_id;
-
- rb_size_pool_t size_pools[SIZE_POOL_COUNT];
-
- struct {
- rb_atomic_t finalizing;
- } atomic_flags;
-
- mark_stack_t mark_stack;
- size_t marked_slots;
-
- struct {
- struct heap_page **sorted;
- size_t allocated_pages;
- size_t allocatable_pages;
- size_t sorted_length;
- uintptr_t range[2];
- size_t freeable_pages;
-
- /* final */
- size_t final_slots;
- VALUE deferred_final;
- } heap_pages;
-
- st_table *finalizer_table;
-
- struct {
- int run;
- unsigned int latest_gc_info;
- gc_profile_record *records;
- gc_profile_record *current_record;
- size_t next_index;
- size_t size;
-
-#if GC_PROFILE_MORE_DETAIL
- double prepare_time;
-#endif
- double invoke_time;
-
- 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;
- size_t total_shade_operation_count;
- size_t total_promoted_count;
- size_t total_remembered_normal_object_count;
- size_t total_remembered_shady_object_count;
-
-#if RGENGC_PROFILE >= 2
- size_t generated_normal_object_count_types[RUBY_T_MASK];
- size_t generated_shady_object_count_types[RUBY_T_MASK];
- size_t shade_operation_count_types[RUBY_T_MASK];
- size_t promoted_types[RUBY_T_MASK];
- size_t remembered_normal_object_count_types[RUBY_T_MASK];
- size_t remembered_shady_object_count_types[RUBY_T_MASK];
-#endif
-#endif /* RGENGC_PROFILE */
-
- /* temporary profiling space */
- double gc_sweep_start_time;
- size_t total_allocated_objects_at_gc_start;
- size_t heap_used_at_gc_start;
-
- /* basic statistics */
- size_t count;
- uint64_t marking_time_ns;
- struct timespec marking_start_time;
- uint64_t sweeping_time_ns;
- struct timespec sweeping_start_time;
-
- /* Weak references */
- size_t weak_references_count;
- size_t retained_weak_references_count;
- } profile;
-
- VALUE gc_stress_mode;
-
- struct {
- VALUE parent_object;
- int need_major_gc;
- size_t last_major_gc;
- size_t uncollectible_wb_unprotected_objects;
- size_t uncollectible_wb_unprotected_objects_limit;
- size_t old_objects;
- size_t old_objects_limit;
-
-#if RGENGC_ESTIMATE_OLDMALLOC
- size_t oldmalloc_increase;
- size_t oldmalloc_increase_limit;
-#endif
-
-#if RGENGC_CHECK_MODE >= 2
- struct st_table *allrefs_table;
- size_t error_count;
-#endif
- } rgengc;
-
- struct {
- size_t considered_count_table[T_MASK];
- size_t moved_count_table[T_MASK];
- size_t moved_up_count_table[T_MASK];
- size_t moved_down_count_table[T_MASK];
- size_t total_moved;
-
- /* This function will be used, if set, to sort the heap prior to compaction */
- gc_compact_compare_func compare_func;
- } rcompactor;
-
- struct {
- size_t pooled_slots;
- size_t step_slots;
- } rincgc;
-
- st_table *id_to_obj_tbl;
- st_table *obj_to_id_tbl;
-
-#if GC_DEBUG_STRESS_TO_CLASS
- VALUE stress_to_class;
-#endif
-
- rb_darray(VALUE *) weak_references;
- rb_postponed_job_handle_t finalize_deferred_pjob;
-
-#ifdef RUBY_ASAN_ENABLED
- const rb_execution_context_t *marking_machine_context_ec;
-#endif
-
-} rb_objspace_t;
-
-
-#ifndef HEAP_PAGE_ALIGN_LOG
-/* default tiny heap size: 64KiB */
-#define HEAP_PAGE_ALIGN_LOG 16
-#endif
-
-#define BASE_SLOT_SIZE (sizeof(RVALUE) + RVALUE_OVERHEAD)
-
-#define CEILDIV(i, mod) roomof(i, mod)
-enum {
- HEAP_PAGE_ALIGN = (1UL << HEAP_PAGE_ALIGN_LOG),
- HEAP_PAGE_ALIGN_MASK = (~(~0UL << HEAP_PAGE_ALIGN_LOG)),
- HEAP_PAGE_SIZE = HEAP_PAGE_ALIGN,
- HEAP_PAGE_OBJ_LIMIT = (unsigned int)((HEAP_PAGE_SIZE - sizeof(struct heap_page_header)) / BASE_SLOT_SIZE),
- HEAP_PAGE_BITMAP_LIMIT = CEILDIV(CEILDIV(HEAP_PAGE_SIZE, BASE_SLOT_SIZE), BITS_BITLENGTH),
- HEAP_PAGE_BITMAP_SIZE = (BITS_SIZE * HEAP_PAGE_BITMAP_LIMIT),
-};
-#define HEAP_PAGE_ALIGN (1 << HEAP_PAGE_ALIGN_LOG)
-#define HEAP_PAGE_SIZE HEAP_PAGE_ALIGN
-
-#if !defined(INCREMENTAL_MARK_STEP_ALLOCATIONS)
-# define INCREMENTAL_MARK_STEP_ALLOCATIONS 500
-#endif
-
-#undef INIT_HEAP_PAGE_ALLOC_USE_MMAP
-/* Must define either HEAP_PAGE_ALLOC_USE_MMAP or
- * INIT_HEAP_PAGE_ALLOC_USE_MMAP. */
-
-#ifndef HAVE_MMAP
-/* We can't use mmap of course, if it is not available. */
-static const bool HEAP_PAGE_ALLOC_USE_MMAP = false;
-
-#elif defined(__wasm__)
-/* wasmtime does not have proper support for mmap.
- * See https://github.com/bytecodealliance/wasmtime/blob/main/docs/WASI-rationale.md#why-no-mmap-and-friends
- */
-static const bool HEAP_PAGE_ALLOC_USE_MMAP = false;
-
-#elif HAVE_CONST_PAGE_SIZE
-/* If we have the PAGE_SIZE and it is a constant, then we can directly use it. */
-static const bool HEAP_PAGE_ALLOC_USE_MMAP = (PAGE_SIZE <= HEAP_PAGE_SIZE);
-
-#elif defined(PAGE_MAX_SIZE) && (PAGE_MAX_SIZE <= HEAP_PAGE_SIZE)
-/* If we can use the maximum page size. */
-static const bool HEAP_PAGE_ALLOC_USE_MMAP = true;
-
-#elif defined(PAGE_SIZE)
-/* If the PAGE_SIZE macro can be used dynamically. */
-# define INIT_HEAP_PAGE_ALLOC_USE_MMAP (PAGE_SIZE <= HEAP_PAGE_SIZE)
-
-#elif defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
-/* If we can use sysconf to determine the page size. */
-# define INIT_HEAP_PAGE_ALLOC_USE_MMAP (sysconf(_SC_PAGE_SIZE) <= HEAP_PAGE_SIZE)
-
-#else
-/* Otherwise we can't determine the system page size, so don't use mmap. */
-static const bool HEAP_PAGE_ALLOC_USE_MMAP = false;
-#endif
-
-#ifdef INIT_HEAP_PAGE_ALLOC_USE_MMAP
-/* We can determine the system page size at runtime. */
-# define HEAP_PAGE_ALLOC_USE_MMAP (heap_page_alloc_use_mmap != false)
-
-static bool heap_page_alloc_use_mmap;
-#endif
-
-#define RVALUE_AGE_BIT_COUNT 2
-#define RVALUE_AGE_BIT_MASK (((bits_t)1 << RVALUE_AGE_BIT_COUNT) - 1)
-
-struct heap_page {
- short slot_size;
- short total_slots;
- short free_slots;
- short final_slots;
- short pinned_slots;
- struct {
- unsigned int before_sweep : 1;
- unsigned int has_remembered_objects : 1;
- unsigned int has_uncollectible_wb_unprotected_objects : 1;
- unsigned int in_tomb : 1;
- } flags;
-
- rb_size_pool_t *size_pool;
-
- struct heap_page *free_next;
- uintptr_t start;
- RVALUE *freelist;
- struct ccan_list_node page_node;
-
- bits_t wb_unprotected_bits[HEAP_PAGE_BITMAP_LIMIT];
- /* the following three bitmaps are cleared at the beginning of full GC */
- bits_t mark_bits[HEAP_PAGE_BITMAP_LIMIT];
- bits_t uncollectible_bits[HEAP_PAGE_BITMAP_LIMIT];
- bits_t marking_bits[HEAP_PAGE_BITMAP_LIMIT];
-
- bits_t remembered_bits[HEAP_PAGE_BITMAP_LIMIT];
-
- /* If set, the object is not movable */
- bits_t pinned_bits[HEAP_PAGE_BITMAP_LIMIT];
- bits_t age_bits[HEAP_PAGE_BITMAP_LIMIT * RVALUE_AGE_BIT_COUNT];
-};
-
-/*
- * When asan is enabled, this will prohibit writing to the freelist until it is unlocked
- */
-static void
-asan_lock_freelist(struct heap_page *page)
-{
- asan_poison_memory_region(&page->freelist, sizeof(RVALUE*));
-}
-
-/*
- * When asan is enabled, this will enable the ability to write to the freelist
- */
-static void
-asan_unlock_freelist(struct heap_page *page)
-{
- asan_unpoison_memory_region(&page->freelist, sizeof(RVALUE*), false);
-}
-
-#define GET_PAGE_BODY(x) ((struct heap_page_body *)((bits_t)(x) & ~(HEAP_PAGE_ALIGN_MASK)))
-#define GET_PAGE_HEADER(x) (&GET_PAGE_BODY(x)->header)
-#define GET_HEAP_PAGE(x) (GET_PAGE_HEADER(x)->page)
-
-#define NUM_IN_PAGE(p) (((bits_t)(p) & HEAP_PAGE_ALIGN_MASK) / BASE_SLOT_SIZE)
-#define BITMAP_INDEX(p) (NUM_IN_PAGE(p) / BITS_BITLENGTH )
-#define BITMAP_OFFSET(p) (NUM_IN_PAGE(p) & (BITS_BITLENGTH-1))
-#define BITMAP_BIT(p) ((bits_t)1 << BITMAP_OFFSET(p))
-
-/* Bitmap Operations */
-#define MARKED_IN_BITMAP(bits, p) ((bits)[BITMAP_INDEX(p)] & BITMAP_BIT(p))
-#define MARK_IN_BITMAP(bits, p) ((bits)[BITMAP_INDEX(p)] = (bits)[BITMAP_INDEX(p)] | BITMAP_BIT(p))
-#define CLEAR_IN_BITMAP(bits, p) ((bits)[BITMAP_INDEX(p)] = (bits)[BITMAP_INDEX(p)] & ~BITMAP_BIT(p))
-
-/* 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])
-#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])
-
-#define GC_SWEEP_PAGES_FREEABLE_PER_STEP 3
-
-#define RVALUE_AGE_BITMAP_INDEX(n) (NUM_IN_PAGE(n) / (BITS_BITLENGTH / RVALUE_AGE_BIT_COUNT))
-#define RVALUE_AGE_BITMAP_OFFSET(n) ((NUM_IN_PAGE(n) % (BITS_BITLENGTH / RVALUE_AGE_BIT_COUNT)) * RVALUE_AGE_BIT_COUNT)
-
-#define RVALUE_OLD_AGE 3
-
-static int
-RVALUE_AGE_GET(VALUE obj)
-{
- bits_t *age_bits = GET_HEAP_PAGE(obj)->age_bits;
- return (int)(age_bits[RVALUE_AGE_BITMAP_INDEX(obj)] >> RVALUE_AGE_BITMAP_OFFSET(obj)) & RVALUE_AGE_BIT_MASK;
-}
-
-static void
-RVALUE_AGE_SET(VALUE obj, int age)
-{
- RUBY_ASSERT(age <= RVALUE_OLD_AGE);
- bits_t *age_bits = GET_HEAP_PAGE(obj)->age_bits;
- // clear the bits
- age_bits[RVALUE_AGE_BITMAP_INDEX(obj)] &= ~(RVALUE_AGE_BIT_MASK << (RVALUE_AGE_BITMAP_OFFSET(obj)));
- // shift the correct value in
- age_bits[RVALUE_AGE_BITMAP_INDEX(obj)] |= ((bits_t)age << RVALUE_AGE_BITMAP_OFFSET(obj));
- if (age == RVALUE_OLD_AGE) {
- RB_FL_SET_RAW(obj, RUBY_FL_PROMOTED);
- }
- else {
- RB_FL_UNSET_RAW(obj, RUBY_FL_PROMOTED);
- }
-}
-
-/* Aliases */
-#define rb_objspace (*rb_objspace_of(GET_VM()))
-#define rb_objspace_of(vm) ((vm)->objspace)
-#define unless_objspace(objspace) \
- rb_objspace_t *objspace; \
- rb_vm_t *unless_objspace_vm = GET_VM(); \
- if (unless_objspace_vm) objspace = unless_objspace_vm->objspace; \
- else /* return; or objspace will be warned uninitialized */
-
-#define malloc_limit objspace->malloc_params.limit
-#define malloc_increase objspace->malloc_params.increase
-#define malloc_allocated_size objspace->malloc_params.allocated_size
-#define heap_pages_sorted objspace->heap_pages.sorted
-#define heap_allocated_pages objspace->heap_pages.allocated_pages
-#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_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 size_pools objspace->size_pools
-#define during_gc objspace->flags.during_gc
-#define finalizing objspace->atomic_flags.finalizing
-#define finalizer_table objspace->finalizer_table
-#define ruby_gc_stressful objspace->flags.gc_stressful
-#define ruby_gc_stress_mode objspace->gc_stress_mode
-#if GC_DEBUG_STRESS_TO_CLASS
-#define stress_to_class objspace->stress_to_class
-#define set_stress_to_class(c) (stress_to_class = (c))
-#else
-#define stress_to_class (objspace, 0)
-#define set_stress_to_class(c) (objspace, (c))
-#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)
-{
-#if RGENGC_CHECK_MODE > 0
- switch (mode) {
- case gc_mode_none:
- case gc_mode_marking:
- case gc_mode_sweeping:
- case gc_mode_compacting:
- break;
- default:
- rb_bug("gc_mode_verify: unreachable (%d)", (int)mode);
- }
-#endif
- 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 / BASE_SLOT_SIZE;
- count += size_pool->allocatable_pages * HEAP_PAGE_OBJ_LIMIT / slot_size_multiple;
- }
- return count;
-}
-
-static inline size_t
-total_allocated_pages(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];
- count += size_pool->total_allocated_pages;
- }
- return count;
-}
-
-static inline size_t
-total_freed_pages(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];
- count += size_pool->total_freed_pages;
- }
- return count;
-}
-
-static inline size_t
-total_allocated_objects(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];
- count += size_pool->total_allocated_objects;
- }
- return count;
-}
-
-static inline size_t
-total_freed_objects(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];
- count += size_pool->total_freed_objects;
- }
- return count;
-}
-
-#define gc_mode(objspace) gc_mode_verify((enum gc_mode)(objspace)->flags.mode)
-#define gc_mode_set(objspace, m) ((objspace)->flags.mode = (unsigned int)gc_mode_verify(m))
-#define gc_needs_major_flags objspace->rgengc.need_major_gc
-
-#define is_marking(objspace) (gc_mode(objspace) == gc_mode_marking)
-#define is_sweeping(objspace) (gc_mode(objspace) == gc_mode_sweeping)
-#define is_full_marking(objspace) ((objspace)->flags.during_minor_gc == FALSE)
-#define is_incremental_marking(objspace) ((objspace)->flags.during_incremental_marking != FALSE)
-#define will_be_incremental_marking(objspace) ((objspace)->rgengc.need_major_gc != GPR_FLAG_NONE)
-#define GC_INCREMENTAL_SWEEP_SLOT_COUNT 2048
-#define GC_INCREMENTAL_SWEEP_POOL_SLOT_COUNT 1024
-#define is_lazy_sweeping(objspace) (GC_ENABLE_LAZY_SWEEP && has_sweeping_pages(objspace))
-
-#if SIZEOF_LONG == SIZEOF_VOIDP
-# define obj_id_to_ref(objid) ((objid) ^ FIXNUM_FLAG) /* unset FIXNUM_FLAG */
-#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
-# define obj_id_to_ref(objid) (FIXNUM_P(objid) ? \
- ((objid) ^ FIXNUM_FLAG) : (NUM2PTR(objid) << 1))
-#else
-# error not supported
-#endif
-
-#define RANY(o) ((RVALUE*)(o))
-
-struct RZombie {
- struct RBasic basic;
- VALUE next;
- void (*dfree)(void *);
- void *data;
-};
-
-#define RZOMBIE(o) ((struct RZombie *)(o))
-
-#define nomem_error GET_VM()->special_exceptions[ruby_error_nomemory]
-
-#if RUBY_MARK_FREE_DEBUG
-int ruby_gc_debug_indent = 0;
-#endif
-VALUE rb_mGC;
-int ruby_disable_gc = 0;
-int ruby_enable_autocompact = 0;
-#if RGENGC_CHECK_MODE
-gc_compact_compare_func ruby_autocompact_compare_func;
-#endif
-
-void rb_vm_update_references(void *ptr);
-
-void rb_gcdebug_print_obj_condition(VALUE obj);
-
-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 garbage_collect(rb_objspace_t *, unsigned int reason);
-
-static int gc_start(rb_objspace_t *objspace, unsigned int reason);
-static void gc_rest(rb_objspace_t *objspace);
-
-enum gc_enter_event {
- gc_enter_event_start,
- gc_enter_event_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_marking_enter(rb_objspace_t *objspace);
-static void gc_marking_exit(rb_objspace_t *objspace);
-static void gc_sweeping_enter(rb_objspace_t *objspace);
-static void gc_sweeping_exit(rb_objspace_t *objspace);
-static bool 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_finish_size_pool(rb_objspace_t *objspace, rb_size_pool_t *size_pool);
-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);
-static inline void gc_mark_and_pin(rb_objspace_t *objspace, VALUE ptr);
-NO_SANITIZE("memory", static void gc_mark_maybe(rb_objspace_t *objspace, VALUE ptr));
-
-static int gc_mark_stacked_objects_incremental(rb_objspace_t *, size_t count);
-NO_SANITIZE("memory", static inline int is_pointer_to_heap(rb_objspace_t *objspace, const void *ptr));
-
-static size_t obj_memsize_of(VALUE obj, int use_all_types);
-static void gc_verify_internal_consistency(rb_objspace_t *objspace);
-
-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, 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 *);
-static inline void gc_prof_mark_timer_stop(rb_objspace_t *);
-static inline void gc_prof_sweep_timer_start(rb_objspace_t *);
-static inline void gc_prof_sweep_timer_stop(rb_objspace_t *);
-static inline void gc_prof_set_malloc_info(rb_objspace_t *);
-static inline void gc_prof_set_heap_info(rb_objspace_t *);
-
-#define TYPED_UPDATE_IF_MOVED(_objspace, _type, _thing) do { \
- if (gc_object_moved_p((_objspace), (VALUE)(_thing))) { \
- *(_type *)&(_thing) = (_type)RMOVED(_thing)->destination; \
- } \
-} while (0)
-
-#define UPDATE_IF_MOVED(_objspace, _thing) TYPED_UPDATE_IF_MOVED(_objspace, VALUE, _thing)
-
-#define gc_prof_record(objspace) (objspace)->profile.current_record
-#define gc_prof_enabled(objspace) ((objspace)->profile.run && (objspace)->profile.current_record)
-
-#ifdef HAVE_VA_ARGS_MACRO
-# define gc_report(level, objspace, ...) \
- if (!RGENGC_DEBUG_ENABLED(level)) {} else gc_report_body(level, objspace, __VA_ARGS__)
-#else
-# define gc_report if (!RGENGC_DEBUG_ENABLED(0)) {} else gc_report_body
-#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);
-static const char *obj_info_basic(VALUE obj);
static const char *obj_type_name(VALUE obj);
-
-static void gc_finalize_deferred(void *dmy);
-
-#if USE_TICK_T
-/* the following code is only for internal tuning. */
-
-/* Source code to use RDTSC is quoted and modified from
- * https://www.mcs.anl.gov/~kazutomo/rdtsc.html
- * written by Kazutomo Yoshii <kazutomo@mcs.anl.gov>
- */
-
-#if defined(__GNUC__) && defined(__i386__)
-typedef unsigned long long tick_t;
-#define PRItick "llu"
-static inline tick_t
-tick(void)
-{
- unsigned long long int x;
- __asm__ __volatile__ ("rdtsc" : "=A" (x));
- return x;
-}
-
-#elif defined(__GNUC__) && defined(__x86_64__)
-typedef unsigned long long tick_t;
-#define PRItick "llu"
-
-static __inline__ tick_t
-tick(void)
-{
- unsigned long hi, lo;
- __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
- return ((unsigned long long)lo)|( ((unsigned long long)hi)<<32);
-}
-
-#elif defined(__powerpc64__) && (GCC_VERSION_SINCE(4,8,0) || defined(__clang__))
-typedef unsigned long long tick_t;
-#define PRItick "llu"
-
-static __inline__ tick_t
-tick(void)
-{
- unsigned long long val = __builtin_ppc_get_timebase();
- return val;
-}
-
-/* Implementation for macOS PPC by @nobu
- * See: https://github.com/ruby/ruby/pull/5975#discussion_r890045558
- */
-#elif defined(__POWERPC__) && defined(__APPLE__)
-typedef unsigned long long tick_t;
-#define PRItick "llu"
-
-static __inline__ tick_t
-tick(void)
-{
- unsigned long int upper, lower, tmp;
- # define mftbu(r) __asm__ volatile("mftbu %0" : "=r"(r))
- # define mftb(r) __asm__ volatile("mftb %0" : "=r"(r))
- do {
- mftbu(upper);
- mftb(lower);
- mftbu(tmp);
- } while (tmp != upper);
- return ((tick_t)upper << 32) | lower;
-}
-
-#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 <intrin.h>
-typedef unsigned __int64 tick_t;
-#define PRItick "llu"
-
-static inline tick_t
-tick(void)
-{
- return __rdtsc();
-}
-
-#else /* use clock */
-typedef clock_t tick_t;
-#define PRItick "llu"
-
-static inline tick_t
-tick(void)
-{
- return clock();
-}
-#endif /* TSC */
-#else /* USE_TICK_T */
-#define MEASURE_LINE(expr) expr
-#endif /* USE_TICK_T */
-
-#define asan_unpoisoning_object(obj) \
- for (void *poisoned = asan_unpoison_object_temporary(obj), \
- *unpoisoning = &poisoned; /* flag to loop just once */ \
- unpoisoning; \
- unpoisoning = asan_poison_object_restore(obj, poisoned))
-
-#define FL_CHECK2(name, x, pred) \
- ((RGENGC_CHECK_MODE && SPECIAL_CONST_P(x)) ? \
- (rb_bug(name": SPECIAL_CONST (%p)", (void *)(x)), 0) : (pred))
-#define FL_TEST2(x,f) FL_CHECK2("FL_TEST2", x, FL_TEST_RAW((x),(f)) != 0)
-#define FL_SET2(x,f) FL_CHECK2("FL_SET2", x, RBASIC(x)->flags |= (f))
-#define FL_UNSET2(x,f) FL_CHECK2("FL_UNSET2", x, RBASIC(x)->flags &= ~(f))
-
-#define RVALUE_MARK_BITMAP(obj) MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(obj), (obj))
-#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))
-
-#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))
-
-#define RVALUE_PAGE_WB_UNPROTECTED(page, obj) MARKED_IN_BITMAP((page)->wb_unprotected_bits, (obj))
-#define RVALUE_PAGE_UNCOLLECTIBLE(page, obj) MARKED_IN_BITMAP((page)->uncollectible_bits, (obj))
-#define RVALUE_PAGE_MARKING(page, obj) MARKED_IN_BITMAP((page)->marking_bits, (obj))
-
-static int rgengc_remember(rb_objspace_t *objspace, VALUE obj);
-static void rgengc_mark_and_rememberset_clear(rb_objspace_t *objspace, rb_heap_t *heap);
-static void rgengc_rememberset_mark(rb_objspace_t *objspace, rb_heap_t *heap);
-
-static int
-check_rvalue_consistency_force(const VALUE obj, int terminate)
-{
- int err = 0;
- rb_objspace_t *objspace = &rb_objspace;
-
- 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++;
- }
- 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];
- ccan_list_for_each(&size_pool->tomb_heap.pages, page, page_node) {
- if (page->start <= (uintptr_t)obj &&
- (uintptr_t)obj < (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;
- }
+#include "gc/default/default.c"
+
+#if USE_MODULAR_GC && !defined(HAVE_DLOPEN)
+# error "Modular GC requires dlopen"
+#elif USE_MODULAR_GC
+#include <dlfcn.h>
+
+typedef struct gc_function_map {
+ // Bootup
+ void *(*objspace_alloc)(void);
+ void (*objspace_init)(void *objspace_ptr);
+ void *(*ractor_cache_alloc)(void *objspace_ptr, void *ractor);
+ void (*set_params)(void *objspace_ptr);
+ void (*init)(void);
+ size_t *(*heap_sizes)(void *objspace_ptr);
+ // Shutdown
+ void (*shutdown_free_objects)(void *objspace_ptr);
+ void (*objspace_free)(void *objspace_ptr);
+ void (*ractor_cache_free)(void *objspace_ptr, void *cache);
+ // GC
+ void (*start)(void *objspace_ptr, bool full_mark, bool immediate_mark, bool immediate_sweep, bool compact);
+ bool (*during_gc_p)(void *objspace_ptr);
+ void (*prepare_heap)(void *objspace_ptr);
+ void (*gc_enable)(void *objspace_ptr);
+ void (*gc_disable)(void *objspace_ptr, bool finish_current_gc);
+ bool (*gc_enabled_p)(void *objspace_ptr);
+ VALUE (*config_get)(void *objpace_ptr);
+ void (*config_set)(void *objspace_ptr, VALUE hash);
+ void (*stress_set)(void *objspace_ptr, VALUE flag);
+ VALUE (*stress_get)(void *objspace_ptr);
+ // Object allocation
+ VALUE (*new_obj)(void *objspace_ptr, void *cache_ptr, VALUE klass, VALUE flags, bool wb_protected, size_t alloc_size);
+ size_t (*obj_slot_size)(VALUE obj);
+ size_t (*heap_id_for_size)(void *objspace_ptr, size_t size);
+ bool (*size_allocatable_p)(size_t size);
+ // Malloc
+ void *(*malloc)(void *objspace_ptr, size_t size, bool gc_allowed);
+ void *(*calloc)(void *objspace_ptr, size_t size, bool gc_allowed);
+ void *(*realloc)(void *objspace_ptr, void *ptr, size_t new_size, size_t old_size, bool gc_allowed);
+ void (*free)(void *objspace_ptr, void *ptr, size_t old_size);
+ void (*adjust_memory_usage)(void *objspace_ptr, ssize_t diff);
+ // Marking
+ void (*mark)(void *objspace_ptr, VALUE obj);
+ void (*mark_and_move)(void *objspace_ptr, VALUE *ptr);
+ void (*mark_and_pin)(void *objspace_ptr, VALUE obj);
+ void (*mark_maybe)(void *objspace_ptr, VALUE obj);
+ // Weak references
+ void (*declare_weak_references)(void *objspace_ptr, VALUE obj);
+ bool (*handle_weak_references_alive_p)(void *objspace_ptr, VALUE obj);
+ // Compaction
+ void (*register_pinning_obj)(void *objspace_ptr, VALUE obj);
+ bool (*object_moved_p)(void *objspace_ptr, VALUE obj);
+ VALUE (*location)(void *objspace_ptr, VALUE value);
+ // Write barriers
+ void (*writebarrier)(void *objspace_ptr, VALUE a, VALUE b);
+ void (*writebarrier_unprotect)(void *objspace_ptr, VALUE obj);
+ void (*writebarrier_remember)(void *objspace_ptr, VALUE obj);
+ // Heap walking
+ void (*each_objects)(void *objspace_ptr, int (*callback)(void *, void *, size_t, void *), void *data);
+ void (*each_object)(void *objspace_ptr, void (*func)(VALUE obj, void *data), void *data);
+ // Finalizers
+ void (*make_zombie)(void *objspace_ptr, VALUE obj, void (*dfree)(void *), void *data);
+ VALUE (*define_finalizer)(void *objspace_ptr, VALUE obj, VALUE block);
+ void (*undefine_finalizer)(void *objspace_ptr, VALUE obj);
+ void (*copy_finalizer)(void *objspace_ptr, VALUE dest, VALUE obj);
+ void (*shutdown_call_finalizer)(void *objspace_ptr);
+ // Forking
+ void (*before_fork)(void *objspace_ptr);
+ void (*after_fork)(void *objspace_ptr, rb_pid_t pid);
+ // Statistics
+ void (*set_measure_total_time)(void *objspace_ptr, VALUE flag);
+ bool (*get_measure_total_time)(void *objspace_ptr);
+ unsigned long long (*get_total_time)(void *objspace_ptr);
+ size_t (*gc_count)(void *objspace_ptr);
+ VALUE (*latest_gc_info)(void *objspace_ptr, VALUE key);
+ VALUE (*stat)(void *objspace_ptr, VALUE hash_or_sym);
+ VALUE (*stat_heap)(void *objspace_ptr, VALUE heap_name, VALUE hash_or_sym);
+ const char *(*active_gc_name)(void);
+ // Miscellaneous
+ struct rb_gc_object_metadata_entry *(*object_metadata)(void *objspace_ptr, VALUE obj);
+ bool (*pointer_to_heap_p)(void *objspace_ptr, const void *ptr);
+ bool (*garbage_object_p)(void *objspace_ptr, VALUE obj);
+ void (*set_event_hook)(void *objspace_ptr, const rb_event_flag_t event);
+ void (*copy_attributes)(void *objspace_ptr, VALUE dest, VALUE obj);
+
+ bool modular_gc_loaded_p;
+} rb_gc_function_map_t;
+
+static rb_gc_function_map_t rb_gc_functions;
+
+# define RUBY_GC_LIBRARY "RUBY_GC_LIBRARY"
+# define MODULAR_GC_DIR STRINGIZE(modular_gc_dir)
+
+static void
+ruby_modular_gc_init(void)
+{
+ // Assert that the directory path ends with a /
+ RUBY_ASSERT_ALWAYS(MODULAR_GC_DIR[sizeof(MODULAR_GC_DIR) - 2] == '/');
+
+ const char *gc_so_file = getenv(RUBY_GC_LIBRARY);
+
+ rb_gc_function_map_t gc_functions = { 0 };
+
+ char *gc_so_path = NULL;
+ void *handle = NULL;
+ if (gc_so_file) {
+ /* Check to make sure that gc_so_file matches /[\w-_]+/ so that it does
+ * not load a shared object outside of the directory. */
+ for (size_t i = 0; i < strlen(gc_so_file); i++) {
+ char c = gc_so_file[i];
+ if (isalnum(c)) continue;
+ switch (c) {
+ case '-':
+ case '_':
+ break;
+ default:
+ fprintf(stderr, "Only alphanumeric, dash, and underscore is allowed in "RUBY_GC_LIBRARY"\n");
+ exit(1);
+ }
+ }
+
+ size_t gc_so_path_size = strlen(MODULAR_GC_DIR "librubygc." DLEXT) + strlen(gc_so_file) + 1;
+#ifdef LOAD_RELATIVE
+ Dl_info dli;
+ size_t prefix_len = 0;
+ if (dladdr((void *)(uintptr_t)ruby_modular_gc_init, &dli)) {
+ const char *base = strrchr(dli.dli_fname, '/');
+ if (base) {
+ size_t tail = 0;
+# define end_with_p(lit) \
+ (prefix_len >= (tail = rb_strlen_lit(lit)) && \
+ memcmp(base - tail, lit, tail) == 0)
+
+ prefix_len = base - dli.dli_fname;
+ if (end_with_p("/bin") || end_with_p("/lib")) {
+ prefix_len -= tail;
}
+ prefix_len += MODULAR_GC_DIR[0] != '/';
+ gc_so_path_size += prefix_len;
}
- 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;
- const int remembered_bit = MARKED_IN_BITMAP(GET_HEAP_PAGE(obj)->remembered_bits, obj) != 0;
- const int age = RVALUE_AGE_GET((VALUE)obj);
-
- 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++;
- }
-
- 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);
- 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++;
- }
-
- 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++;
- }
+#endif
+ gc_so_path = alloca(gc_so_path_size);
+ {
+ size_t gc_so_path_idx = 0;
+#define GC_SO_PATH_APPEND(str) do { \
+ gc_so_path_idx += strlcpy(gc_so_path + gc_so_path_idx, str, gc_so_path_size - gc_so_path_idx); \
+} while (0)
+#ifdef LOAD_RELATIVE
+ if (prefix_len > 0) {
+ memcpy(gc_so_path, dli.dli_fname, prefix_len);
+ gc_so_path_idx = prefix_len;
}
- }
- }
- RB_VM_LOCK_LEAVE_NO_BARRIER();
-
- if (err > 0 && terminate) {
- rb_bug("check_rvalue_consistency_force: there is %d errors.", err);
- }
- return err;
-}
-
-#if RGENGC_CHECK_MODE == 0
-static inline VALUE
-check_rvalue_consistency(const VALUE obj)
-{
- return obj;
-}
-#else
-static VALUE
-check_rvalue_consistency(const VALUE obj)
-{
- check_rvalue_consistency_force(obj, TRUE);
- return obj;
-}
#endif
-
-static inline int
-gc_object_moved_p(rb_objspace_t * objspace, VALUE obj)
-{
- if (RB_SPECIAL_CONST_P(obj)) {
- return FALSE;
- }
- else {
- void *poisoned = asan_unpoison_object_temporary(obj);
-
- int ret = BUILTIN_TYPE(obj) == T_MOVED;
- /* Re-poison slot if it's not the one we want */
- if (poisoned) {
- GC_ASSERT(BUILTIN_TYPE(obj) == T_NONE);
- asan_poison_object(obj);
+ GC_SO_PATH_APPEND(MODULAR_GC_DIR "librubygc.");
+ GC_SO_PATH_APPEND(gc_so_file);
+ GC_SO_PATH_APPEND(DLEXT);
+ GC_ASSERT(gc_so_path_idx == gc_so_path_size - 1);
+#undef GC_SO_PATH_APPEND
}
- return ret;
- }
-}
-
-static inline int
-RVALUE_MARKED(VALUE obj)
-{
- check_rvalue_consistency(obj);
- return RVALUE_MARK_BITMAP(obj) != 0;
-}
-
-static inline int
-RVALUE_PINNED(VALUE obj)
-{
- check_rvalue_consistency(obj);
- return RVALUE_PIN_BITMAP(obj) != 0;
-}
-
-static inline int
-RVALUE_WB_UNPROTECTED(VALUE obj)
-{
- check_rvalue_consistency(obj);
- return RVALUE_WB_UNPROTECTED_BITMAP(obj) != 0;
-}
-
-static inline int
-RVALUE_MARKING(VALUE obj)
-{
- check_rvalue_consistency(obj);
- return RVALUE_MARKING_BITMAP(obj) != 0;
-}
-
-static inline int
-RVALUE_REMEMBERED(VALUE obj)
-{
- check_rvalue_consistency(obj);
- return MARKED_IN_BITMAP(GET_HEAP_PAGE(obj)->remembered_bits, obj) != 0;
-}
-
-static inline int
-RVALUE_UNCOLLECTIBLE(VALUE obj)
-{
- check_rvalue_consistency(obj);
- return RVALUE_UNCOLLECTIBLE_BITMAP(obj) != 0;
-}
-
-static inline int
-RVALUE_OLD_P(VALUE obj)
-{
- GC_ASSERT(!RB_SPECIAL_CONST_P(obj));
- check_rvalue_consistency(obj);
- // Because this will only ever be called on GC controlled objects,
- // we can use the faster _RAW function here
- return RB_OBJ_PROMOTED_RAW(obj);
-}
-
-static inline void
-RVALUE_PAGE_OLD_UNCOLLECTIBLE_SET(rb_objspace_t *objspace, struct heap_page *page, VALUE obj)
-{
- MARK_IN_BITMAP(&page->uncollectible_bits[0], obj);
- objspace->rgengc.old_objects++;
-
-#if RGENGC_PROFILE >= 2
- objspace->profile.total_promoted_count++;
- objspace->profile.promoted_types[BUILTIN_TYPE(obj)]++;
-#endif
-}
-
-static inline void
-RVALUE_OLD_UNCOLLECTIBLE_SET(rb_objspace_t *objspace, VALUE obj)
-{
- RB_DEBUG_COUNTER_INC(obj_promote);
- RVALUE_PAGE_OLD_UNCOLLECTIBLE_SET(objspace, GET_HEAP_PAGE(obj), obj);
-}
-
-/* set age to age+1 */
-static inline void
-RVALUE_AGE_INC(rb_objspace_t *objspace, VALUE obj)
-{
- int age = RVALUE_AGE_GET((VALUE)obj);
-
- if (RGENGC_CHECK_MODE && age == RVALUE_OLD_AGE) {
- rb_bug("RVALUE_AGE_INC: can not increment age of OLD object %s.", obj_info(obj));
- }
-
- age++;
- RVALUE_AGE_SET(obj, age);
-
- if (age == RVALUE_OLD_AGE) {
- RVALUE_OLD_UNCOLLECTIBLE_SET(objspace, obj);
- }
-
- check_rvalue_consistency(obj);
-}
-
-static inline void
-RVALUE_AGE_SET_CANDIDATE(rb_objspace_t *objspace, VALUE obj)
-{
- check_rvalue_consistency(obj);
- GC_ASSERT(!RVALUE_OLD_P(obj));
- RVALUE_AGE_SET(obj, RVALUE_OLD_AGE - 1);
- check_rvalue_consistency(obj);
-}
-
-static inline void
-RVALUE_AGE_RESET(VALUE obj)
-{
- RVALUE_AGE_SET(obj, 0);
-}
-
-static inline void
-RVALUE_DEMOTE(rb_objspace_t *objspace, VALUE obj)
-{
- check_rvalue_consistency(obj);
- GC_ASSERT(RVALUE_OLD_P(obj));
-
- if (!is_incremental_marking(objspace) && RVALUE_REMEMBERED(obj)) {
- CLEAR_IN_BITMAP(GET_HEAP_PAGE(obj)->remembered_bits, obj);
- }
-
- CLEAR_IN_BITMAP(GET_HEAP_UNCOLLECTIBLE_BITS(obj), obj);
- RVALUE_AGE_RESET(obj);
-
- if (RVALUE_MARKED(obj)) {
- objspace->rgengc.old_objects--;
- }
-
- check_rvalue_consistency(obj);
-}
-
-static inline int
-RVALUE_BLACK_P(VALUE obj)
-{
- return RVALUE_MARKED(obj) && !RVALUE_MARKING(obj);
-}
-
-#if 0
-static inline int
-RVALUE_GREY_P(VALUE obj)
-{
- return RVALUE_MARKED(obj) && RVALUE_MARKING(obj);
-}
-#endif
-
-static inline int
-RVALUE_WHITE_P(VALUE obj)
-{
- return RVALUE_MARKED(obj) == FALSE;
-}
-
-/*
- --------------------------- ObjectSpace -----------------------------
-*/
-
-static inline void *
-calloc1(size_t n)
-{
- return calloc(1, n);
-}
-
-static VALUE initial_stress = Qfalse;
-void
-rb_gc_initial_stress_set(VALUE flag)
-{
- initial_stress = flag;
-}
-
-static void *rb_gc_impl_objspace_alloc(void);
-
-#if USE_SHARED_GC
-# include "dln.h"
-
-# define RUBY_GC_LIBRARY_PATH "RUBY_GC_LIBRARY_PATH"
-
-void
-ruby_external_gc_init(void)
-{
- char *gc_so_path = getenv(RUBY_GC_LIBRARY_PATH);
- void *handle = NULL;
- if (gc_so_path && dln_supported_p()) {
- char error[1024];
- handle = dln_open(gc_so_path, error, sizeof(error));
+ handle = dlopen(gc_so_path, RTLD_LAZY | RTLD_GLOBAL);
if (!handle) {
- fprintf(stderr, "%s", error);
- rb_bug("ruby_external_gc_init: Shared library %s cannot be opened", gc_so_path);
+ fprintf(stderr, "ruby_modular_gc_init: Shared library %s cannot be opened: %s\n", gc_so_path, dlerror());
+ exit(1);
}
+
+ gc_functions.modular_gc_loaded_p = true;
}
-# define load_external_gc_func(name) do { \
+# define load_modular_gc_func(name) do { \
if (handle) { \
- rb_gc_functions->name = dln_symbol(handle, "rb_gc_impl_" #name); \
- if (!rb_gc_functions->name) { \
- rb_bug("ruby_external_gc_init: " #name " func not exported by library %s", gc_so_path); \
+ const char *func_name = "rb_gc_impl_" #name; \
+ gc_functions.name = dlsym(handle, func_name); \
+ if (!gc_functions.name) { \
+ fprintf(stderr, "ruby_modular_gc_init: %s function not exported by library %s\n", func_name, gc_so_path); \
+ exit(1); \
} \
} \
else { \
- rb_gc_functions->name = rb_gc_impl_##name; \
+ gc_functions.name = rb_gc_impl_##name; \
} \
} while (0)
- load_external_gc_func(objspace_alloc);
-
-# undef load_external_gc_func
-}
-
-# define rb_gc_impl_objspace_alloc rb_gc_functions->objspace_alloc
+ // Bootup
+ load_modular_gc_func(objspace_alloc);
+ load_modular_gc_func(objspace_init);
+ load_modular_gc_func(ractor_cache_alloc);
+ load_modular_gc_func(set_params);
+ load_modular_gc_func(init);
+ load_modular_gc_func(heap_sizes);
+ // Shutdown
+ load_modular_gc_func(shutdown_free_objects);
+ load_modular_gc_func(objspace_free);
+ load_modular_gc_func(ractor_cache_free);
+ // GC
+ load_modular_gc_func(start);
+ load_modular_gc_func(during_gc_p);
+ load_modular_gc_func(prepare_heap);
+ load_modular_gc_func(gc_enable);
+ load_modular_gc_func(gc_disable);
+ load_modular_gc_func(gc_enabled_p);
+ load_modular_gc_func(config_set);
+ load_modular_gc_func(config_get);
+ load_modular_gc_func(stress_set);
+ load_modular_gc_func(stress_get);
+ // Object allocation
+ load_modular_gc_func(new_obj);
+ load_modular_gc_func(obj_slot_size);
+ load_modular_gc_func(heap_id_for_size);
+ load_modular_gc_func(size_allocatable_p);
+ // Malloc
+ load_modular_gc_func(malloc);
+ load_modular_gc_func(calloc);
+ load_modular_gc_func(realloc);
+ load_modular_gc_func(free);
+ load_modular_gc_func(adjust_memory_usage);
+ // Marking
+ load_modular_gc_func(mark);
+ load_modular_gc_func(mark_and_move);
+ load_modular_gc_func(mark_and_pin);
+ load_modular_gc_func(mark_maybe);
+ // Weak references
+ load_modular_gc_func(declare_weak_references);
+ load_modular_gc_func(handle_weak_references_alive_p);
+ // Compaction
+ load_modular_gc_func(register_pinning_obj);
+ load_modular_gc_func(object_moved_p);
+ load_modular_gc_func(location);
+ // Write barriers
+ load_modular_gc_func(writebarrier);
+ load_modular_gc_func(writebarrier_unprotect);
+ load_modular_gc_func(writebarrier_remember);
+ // Heap walking
+ load_modular_gc_func(each_objects);
+ load_modular_gc_func(each_object);
+ // Finalizers
+ load_modular_gc_func(make_zombie);
+ load_modular_gc_func(define_finalizer);
+ load_modular_gc_func(undefine_finalizer);
+ load_modular_gc_func(copy_finalizer);
+ load_modular_gc_func(shutdown_call_finalizer);
+ // Forking
+ load_modular_gc_func(before_fork);
+ load_modular_gc_func(after_fork);
+ // Statistics
+ load_modular_gc_func(set_measure_total_time);
+ load_modular_gc_func(get_measure_total_time);
+ load_modular_gc_func(get_total_time);
+ load_modular_gc_func(gc_count);
+ load_modular_gc_func(latest_gc_info);
+ load_modular_gc_func(stat);
+ load_modular_gc_func(stat_heap);
+ load_modular_gc_func(active_gc_name);
+ // Miscellaneous
+ load_modular_gc_func(object_metadata);
+ load_modular_gc_func(pointer_to_heap_p);
+ load_modular_gc_func(garbage_object_p);
+ load_modular_gc_func(set_event_hook);
+ load_modular_gc_func(copy_attributes);
+
+# undef load_modular_gc_func
+
+ rb_gc_functions = gc_functions;
+}
+
+// Bootup
+# define rb_gc_impl_objspace_alloc rb_gc_functions.objspace_alloc
+# define rb_gc_impl_objspace_init rb_gc_functions.objspace_init
+# define rb_gc_impl_ractor_cache_alloc rb_gc_functions.ractor_cache_alloc
+# define rb_gc_impl_set_params rb_gc_functions.set_params
+# define rb_gc_impl_init rb_gc_functions.init
+# define rb_gc_impl_heap_sizes rb_gc_functions.heap_sizes
+// Shutdown
+# define rb_gc_impl_shutdown_free_objects rb_gc_functions.shutdown_free_objects
+# define rb_gc_impl_objspace_free rb_gc_functions.objspace_free
+# define rb_gc_impl_ractor_cache_free rb_gc_functions.ractor_cache_free
+// GC
+# define rb_gc_impl_start rb_gc_functions.start
+# define rb_gc_impl_during_gc_p rb_gc_functions.during_gc_p
+# define rb_gc_impl_prepare_heap rb_gc_functions.prepare_heap
+# define rb_gc_impl_gc_enable rb_gc_functions.gc_enable
+# define rb_gc_impl_gc_disable rb_gc_functions.gc_disable
+# define rb_gc_impl_gc_enabled_p rb_gc_functions.gc_enabled_p
+# define rb_gc_impl_config_get rb_gc_functions.config_get
+# define rb_gc_impl_config_set rb_gc_functions.config_set
+# define rb_gc_impl_stress_set rb_gc_functions.stress_set
+# define rb_gc_impl_stress_get rb_gc_functions.stress_get
+// Object allocation
+# define rb_gc_impl_new_obj rb_gc_functions.new_obj
+# define rb_gc_impl_obj_slot_size rb_gc_functions.obj_slot_size
+# define rb_gc_impl_heap_id_for_size rb_gc_functions.heap_id_for_size
+# define rb_gc_impl_size_allocatable_p rb_gc_functions.size_allocatable_p
+// Malloc
+# define rb_gc_impl_malloc rb_gc_functions.malloc
+# define rb_gc_impl_calloc rb_gc_functions.calloc
+# define rb_gc_impl_realloc rb_gc_functions.realloc
+# define rb_gc_impl_free rb_gc_functions.free
+# define rb_gc_impl_adjust_memory_usage rb_gc_functions.adjust_memory_usage
+// Marking
+# define rb_gc_impl_mark rb_gc_functions.mark
+# define rb_gc_impl_mark_and_move rb_gc_functions.mark_and_move
+# define rb_gc_impl_mark_and_pin rb_gc_functions.mark_and_pin
+# define rb_gc_impl_mark_maybe rb_gc_functions.mark_maybe
+// Weak references
+# define rb_gc_impl_declare_weak_references rb_gc_functions.declare_weak_references
+# define rb_gc_impl_handle_weak_references_alive_p rb_gc_functions.handle_weak_references_alive_p
+// Compaction
+# define rb_gc_impl_register_pinning_obj rb_gc_functions.register_pinning_obj
+# define rb_gc_impl_object_moved_p rb_gc_functions.object_moved_p
+# define rb_gc_impl_location rb_gc_functions.location
+// Write barriers
+# define rb_gc_impl_writebarrier rb_gc_functions.writebarrier
+# define rb_gc_impl_writebarrier_unprotect rb_gc_functions.writebarrier_unprotect
+# define rb_gc_impl_writebarrier_remember rb_gc_functions.writebarrier_remember
+// Heap walking
+# define rb_gc_impl_each_objects rb_gc_functions.each_objects
+# define rb_gc_impl_each_object rb_gc_functions.each_object
+// Finalizers
+# define rb_gc_impl_make_zombie rb_gc_functions.make_zombie
+# define rb_gc_impl_define_finalizer rb_gc_functions.define_finalizer
+# define rb_gc_impl_undefine_finalizer rb_gc_functions.undefine_finalizer
+# define rb_gc_impl_copy_finalizer rb_gc_functions.copy_finalizer
+# define rb_gc_impl_shutdown_call_finalizer rb_gc_functions.shutdown_call_finalizer
+// Forking
+# define rb_gc_impl_before_fork rb_gc_functions.before_fork
+# define rb_gc_impl_after_fork rb_gc_functions.after_fork
+// Statistics
+# define rb_gc_impl_set_measure_total_time rb_gc_functions.set_measure_total_time
+# define rb_gc_impl_get_measure_total_time rb_gc_functions.get_measure_total_time
+# define rb_gc_impl_get_total_time rb_gc_functions.get_total_time
+# define rb_gc_impl_gc_count rb_gc_functions.gc_count
+# define rb_gc_impl_latest_gc_info rb_gc_functions.latest_gc_info
+# define rb_gc_impl_stat rb_gc_functions.stat
+# define rb_gc_impl_stat_heap rb_gc_functions.stat_heap
+# define rb_gc_impl_active_gc_name rb_gc_functions.active_gc_name
+// Miscellaneous
+# define rb_gc_impl_object_metadata rb_gc_functions.object_metadata
+# define rb_gc_impl_pointer_to_heap_p rb_gc_functions.pointer_to_heap_p
+# define rb_gc_impl_garbage_object_p rb_gc_functions.garbage_object_p
+# define rb_gc_impl_set_event_hook rb_gc_functions.set_event_hook
+# define rb_gc_impl_copy_attributes rb_gc_functions.copy_attributes
#endif
-rb_objspace_t *
-rb_objspace_alloc(void)
-{
-#if USE_SHARED_GC
- ruby_external_gc_init();
-#endif
- return (rb_objspace_t *)rb_gc_impl_objspace_alloc();
-}
-
-#if USE_SHARED_GC
-# undef rb_gc_impl_objspace_alloc
-#endif
-
-static void free_stack_chunks(mark_stack_t *);
-static void mark_stack_free_cache(mark_stack_t *);
-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(objspace))
- rb_bug("lazy sweeping underway when freeing object space");
-
- free(objspace->profile.records);
- objspace->profile.records = NULL;
-
- if (heap_pages_sorted) {
- size_t i;
- size_t total_heap_pages = heap_allocated_pages;
- for (i = 0; i < total_heap_pages; ++i) {
- heap_page_free(objspace, heap_pages_sorted[i]);
- }
- free(heap_pages_sorted);
- heap_allocated_pages = 0;
- heap_pages_sorted_length = 0;
- heap_pages_lomem = 0;
- heap_pages_himem = 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);
-
- free_stack_chunks(&objspace->mark_stack);
- mark_stack_free_cache(&objspace->mark_stack);
-
- rb_darray_free(objspace->weak_references);
-
- free(objspace);
-}
-
-static void
-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: %"PRIdSIZE", size: %"PRIdSIZE"\n",
- next_length, size);
-
- if (heap_pages_sorted_length > 0) {
- sorted = (struct heap_page **)realloc(heap_pages_sorted, size);
- if (sorted) heap_pages_sorted = sorted;
- }
- else {
- sorted = heap_pages_sorted = (struct heap_page **)malloc(size);
- }
-
- if (sorted == 0) {
- rb_memerror();
- }
-
- heap_pages_sorted_length = next_length;
-}
-
-static void
-heap_pages_expand_sorted(rb_objspace_t *objspace)
-{
- /* usually heap_allocatable_pages + heap_eden->total_pages == heap_pages_sorted_length
- * because heap_allocatable_pages contains heap_tomb->total_pages (recycle heap_tomb pages).
- * 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(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(objspace) + heap_eden_total_pages(objspace) <= heap_pages_sorted_length);
- GC_ASSERT(heap_allocated_pages <= heap_pages_sorted_length);
-}
-
-static void
-size_pool_allocatable_pages_set(rb_objspace_t *objspace, rb_size_pool_t *size_pool, size_t 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_unlock_freelist(page);
-
- p->as.free.flags = 0;
- p->as.free.next = page->freelist;
- page->freelist = p;
- asan_lock_freelist(page);
-
- RVALUE_AGE_RESET(obj);
-
- if (RGENGC_CHECK_MODE &&
- /* obj should belong to page */
- !(page->start <= (uintptr_t)obj &&
- (uintptr_t)obj < ((uintptr_t)page->start + (page->total_slots * page->slot_size)) &&
- obj % BASE_SLOT_SIZE == 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);
-}
-
-static inline void
-heap_add_freepage(rb_heap_t *heap, struct heap_page *page)
-{
- asan_unlock_freelist(page);
- GC_ASSERT(page->free_slots != 0);
- 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_lock_freelist(page);
-}
-
-static inline void
-heap_add_poolpage(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *page)
-{
- asan_unlock_freelist(page);
- GC_ASSERT(page->free_slots != 0);
- GC_ASSERT(page->freelist != NULL);
-
- page->free_next = heap->pooled_pages;
- heap->pooled_pages = page;
- objspace->rincgc.pooled_slots += page->free_slots;
-
- asan_lock_freelist(page);
-}
-
-static void
-heap_unlink_page(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *page)
-{
- ccan_list_del(&page->page_node);
- heap->total_pages--;
- heap->total_slots -= page->total_slots;
-}
-
-static void rb_aligned_free(void *ptr, size_t size);
-
+#ifdef RUBY_ASAN_ENABLED
static void
-heap_page_body_free(struct heap_page_body *page_body)
+asan_death_callback(void)
{
- GC_ASSERT((uintptr_t)page_body % HEAP_PAGE_ALIGN == 0);
-
- if (HEAP_PAGE_ALLOC_USE_MMAP) {
-#ifdef HAVE_MMAP
- GC_ASSERT(HEAP_PAGE_SIZE % sysconf(_SC_PAGE_SIZE) == 0);
- if (munmap(page_body, HEAP_PAGE_SIZE)) {
- rb_bug("heap_page_body_free: munmap failed");
- }
-#endif
- }
- else {
- rb_aligned_free(page_body, HEAP_PAGE_SIZE);
+ if (GET_VM()) {
+ rb_bug_without_die("ASAN error");
}
}
-
-static void
-heap_page_free(rb_objspace_t *objspace, struct heap_page *page)
-{
- heap_allocated_pages--;
- page->size_pool->total_freed_pages++;
- heap_page_body_free(GET_PAGE_BODY(page->start));
- free(page);
-}
-
-static void *
-rb_aligned_malloc(size_t alignment, size_t size)
-{
- /* alignment must be a power of 2 */
- GC_ASSERT(((alignment - 1) & alignment) == 0);
- GC_ASSERT(alignment % sizeof(void*) == 0);
-
- void *res;
-
-#if defined __MINGW32__
- res = __mingw_aligned_malloc(size, alignment);
-#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 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
- GC_ASSERT((uintptr_t)res % alignment == 0);
-
- return res;
-}
-
-static void
-heap_pages_free_unused_pages(rb_objspace_t *objspace)
-{
- size_t i, j;
-
- bool has_pages_in_tomb_heap = FALSE;
- for (i = 0; i < SIZE_POOL_COUNT; i++) {
- if (!ccan_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 = 0; 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 <= heap_pages_himem);
- heap_pages_himem = himem;
-
- struct heap_page *lopage = heap_pages_sorted[0];
- uintptr_t lomem = (uintptr_t)lopage->start;
- GC_ASSERT(lomem >= heap_pages_lomem);
- heap_pages_lomem = lomem;
-
- GC_ASSERT(j == heap_allocated_pages);
- }
-}
+static VALUE initial_stress = Qfalse;
-static struct heap_page_body *
-heap_page_body_allocate(void)
+void *
+rb_objspace_alloc(void)
{
- struct heap_page_body *page_body;
-
- if (HEAP_PAGE_ALLOC_USE_MMAP) {
-#ifdef HAVE_MMAP
- GC_ASSERT(HEAP_PAGE_ALIGN % sysconf(_SC_PAGE_SIZE) == 0);
-
- char *ptr = mmap(NULL, HEAP_PAGE_ALIGN + HEAP_PAGE_SIZE,
- PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (ptr == MAP_FAILED) {
- return NULL;
- }
-
- char *aligned = ptr + HEAP_PAGE_ALIGN;
- aligned -= ((VALUE)aligned & (HEAP_PAGE_ALIGN - 1));
- GC_ASSERT(aligned > ptr);
- GC_ASSERT(aligned <= ptr + HEAP_PAGE_ALIGN);
-
- 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("heap_page_body_allocate: munmap failed for start");
- }
- }
-
- size_t end_out_of_range_size = HEAP_PAGE_ALIGN - 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 + HEAP_PAGE_SIZE, end_out_of_range_size)) {
- rb_bug("heap_page_body_allocate: munmap failed for end");
- }
- }
-
- page_body = (struct heap_page_body *)aligned;
+#if USE_MODULAR_GC
+ ruby_modular_gc_init();
#endif
- }
- else {
- page_body = rb_aligned_malloc(HEAP_PAGE_ALIGN, HEAP_PAGE_SIZE);
- }
-
- GC_ASSERT((uintptr_t)page_body % HEAP_PAGE_ALIGN == 0);
-
- return page_body;
-}
-
-static struct heap_page *
-heap_page_allocate(rb_objspace_t *objspace, rb_size_pool_t *size_pool)
-{
- uintptr_t start, end, p;
- struct heap_page *page;
- 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) */
- struct heap_page_body *page_body = heap_page_body_allocate();
- if (page_body == 0) {
- rb_memerror();
- }
-
- /* assign heap_page entry */
- page = calloc1(sizeof(struct heap_page));
- if (page == 0) {
- heap_page_body_free(page_body);
- rb_memerror();
- }
-
- /* adjust obj_limit (object number available in this page) */
- start = (uintptr_t)((VALUE)page_body + sizeof(struct heap_page_header));
-
- if (start % BASE_SLOT_SIZE != 0) {
- int delta = BASE_SLOT_SIZE - (start % BASE_SLOT_SIZE);
- 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 - BASE_SLOT_SIZE;
- }
-
- GC_ASSERT(NUM_IN_PAGE(start) * BASE_SLOT_SIZE % stride == 0);
-
- limit = (HEAP_PAGE_SIZE - (int)(start - (uintptr_t)page_body))/(int)stride;
- }
- end = start + (limit * (int)stride);
-
- /* setup heap_pages_sorted */
- lo = 0;
- 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 ((uintptr_t)mid_page->start < start) {
- lo = mid + 1;
- }
- else if ((uintptr_t)mid_page->start > start) {
- hi = mid;
- }
- else {
- rb_bug("same heap page is allocated: %p at %"PRIuVALUE, (void *)page_body, (VALUE)mid);
- }
- }
-
- 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);
- }
-
- heap_pages_sorted[hi] = page;
-
- heap_allocated_pages++;
- 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);
+ void *objspace = rb_gc_impl_objspace_alloc();
+ ruby_current_vm_ptr->gc.objspace = objspace;
+ rb_gc_impl_objspace_init(objspace);
+ rb_gc_impl_stress_set(objspace, initial_stress);
- size_pool->total_allocated_pages++;
-
- if (heap_allocated_pages > heap_pages_sorted_length) {
- rb_bug("heap_page_allocate: allocated(%"PRIdSIZE") > sorted(%"PRIdSIZE")",
- 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;
-
- page->start = 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 += stride) {
- gc_report(3, objspace, "assign_heap_page: %p is added to freelist\n", (void *)p);
- heap_page_add_freeobj(objspace, page, (VALUE)p);
- }
- page->free_slots = limit;
-
- asan_lock_freelist(page);
- return page;
-}
-
-static struct heap_page *
-heap_page_resurrect(rb_objspace_t *objspace, rb_size_pool_t *size_pool)
-{
- struct heap_page *page = 0, *next;
-
- ccan_list_for_each_safe(&SIZE_POOL_TOMB_HEAP(size_pool)->pages, page, next, page_node) {
- asan_unlock_freelist(page);
- if (page->freelist != NULL) {
- heap_unlink_page(objspace, &size_pool->tomb_heap, page);
- asan_lock_freelist(page);
- return page;
- }
- }
-
- return NULL;
-}
-
-static struct heap_page *
-heap_page_create(rb_objspace_t *objspace, rb_size_pool_t *size_pool)
-{
- struct heap_page *page;
- const char *method = "recycle";
-
- size_pool->allocatable_pages--;
-
- page = heap_page_resurrect(objspace, size_pool);
-
- if (page == NULL) {
- page = heap_page_allocate(objspace, size_pool);
- method = "allocate";
- }
- 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_size_pool_t *size_pool, rb_heap_t *heap, struct heap_page *page)
-{
- /* 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));
- ccan_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_size_pool_t *size_pool, rb_heap_t *heap)
-{
- struct heap_page *page = heap_page_create(objspace, size_pool);
- heap_add_page(objspace, size_pool, heap, page);
- heap_add_freepage(heap, page);
-}
-
-#if GC_CAN_COMPILE_COMPACTION
-static void
-heap_add_pages(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap, size_t add)
-{
- size_t i;
-
- size_pool_allocatable_pages_set(objspace, size_pool, add);
-
- for (i = 0; i < add; i++) {
- heap_assign_page(objspace, size_pool, heap);
- }
-
- GC_ASSERT(size_pool->allocatable_pages == 0);
-}
+#ifdef RUBY_ASAN_ENABLED
+ __sanitizer_set_death_callback(asan_death_callback);
#endif
-static size_t
-slots_to_pages_for_size_pool(rb_objspace_t *objspace, rb_size_pool_t *size_pool, size_t slots)
-{
- size_t multiple = size_pool->slot_size / BASE_SLOT_SIZE;
- /* Due to alignment, heap pages may have one less slot. We should
- * ensure there is enough pages to guarantee that we will have at
- * least the required number of slots after allocating all the pages. */
- size_t slots_per_page = (HEAP_PAGE_OBJ_LIMIT / multiple) - 1;
- return CEILDIV(slots, slots_per_page);
-}
-
-static size_t
-minimum_pages_for_size_pool(rb_objspace_t *objspace, rb_size_pool_t *size_pool)
-{
- size_t size_pool_idx = size_pool - size_pools;
- size_t init_slots = gc_params.size_pool_init_slots[size_pool_idx];
- return slots_to_pages_for_size_pool(objspace, size_pool, init_slots);
-}
-
-static size_t
-heap_extend_pages(rb_objspace_t *objspace, rb_size_pool_t *size_pool, size_t free_slots, size_t total_slots, size_t used)
-{
- double goal_ratio = gc_params.heap_free_slots_goal_ratio;
- size_t next_used;
-
- if (goal_ratio == 0.0) {
- next_used = (size_t)(used * gc_params.growth_factor);
- }
- else if (total_slots == 0) {
- next_used = minimum_pages_for_size_pool(objspace, size_pool);
- }
- else {
- /* Find `f' where free_slots = f * total_slots * goal_ratio
- * => f = (total_slots - free_slots) / ((1 - goal_ratio) * total_slots)
- */
- double f = (double)(total_slots - free_slots) / ((1 - goal_ratio) * total_slots);
-
- if (f > gc_params.growth_factor) f = gc_params.growth_factor;
- if (f < 1.0) f = 1.1;
-
- next_used = (size_t)(f * used);
-
- if (0) {
- fprintf(stderr,
- "free_slots(%8"PRIuSIZE")/total_slots(%8"PRIuSIZE")=%1.2f,"
- " G(%1.2f), f(%1.2f),"
- " used(%8"PRIuSIZE") => next_used(%8"PRIuSIZE")\n",
- free_slots, total_slots, free_slots/(double)total_slots,
- goal_ratio, f, used, next_used);
- }
- }
-
- if (gc_params.growth_max_slots > 0) {
- size_t max_used = (size_t)(used + gc_params.growth_max_slots/HEAP_PAGE_OBJ_LIMIT);
- if (next_used > max_used) next_used = max_used;
- }
-
- size_t extend_page_count = next_used - used;
- /* Extend by at least 1 page. */
- if (extend_page_count == 0) extend_page_count = 1;
-
- return extend_page_count;
-}
-
-static int
-heap_increment(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap)
-{
- 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(objspace) + heap_eden_total_pages(objspace) <= heap_pages_sorted_length);
- GC_ASSERT(heap_allocated_pages <= heap_pages_sorted_length);
-
- heap_assign_page(objspace, size_pool, heap);
- return TRUE;
- }
- return FALSE;
-}
-
-static void
-gc_continue(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap)
-{
- unsigned int lock_lev;
- gc_enter(objspace, gc_enter_event_continue, &lock_lev);
-
- /* Continue marking if in incremental marking. */
- if (is_incremental_marking(objspace)) {
- if (gc_marks_continue(objspace, size_pool, heap)) {
- gc_sweep(objspace);
- }
- }
-
- /* Continue sweeping if in lazy sweeping or the previous incremental
- * marking finished and did not yield a free page. */
- if (heap->free_pages == NULL && is_lazy_sweeping(objspace)) {
- gc_sweep_continue(objspace, size_pool, heap);
- }
-
- gc_exit(objspace, gc_enter_event_continue, &lock_lev);
-}
-
-static void
-heap_prepare(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap)
-{
- GC_ASSERT(heap->free_pages == NULL);
-
- /* Continue incremental marking or lazy sweeping, if in any of those steps. */
- gc_continue(objspace, size_pool, heap);
-
- /* If we still don't have a free page and not allowed to create a new page,
- * we should start a new GC cycle. */
- if (heap->free_pages == NULL &&
- (will_be_incremental_marking(objspace) ||
- (heap_increment(objspace, size_pool, heap) == FALSE))) {
- if (gc_start(objspace, GPR_FLAG_NEWOBJ) == FALSE) {
- rb_memerror();
- }
- else {
- /* Do steps of incremental marking or lazy sweeping if the GC run permits. */
- gc_continue(objspace, size_pool, heap);
-
- /* If we're not incremental marking (e.g. a minor GC) or finished
- * sweeping and still don't have a free page, then
- * gc_sweep_finish_size_pool should allow us to create a new page. */
- if (heap->free_pages == NULL && !heap_increment(objspace, size_pool, heap)) {
- if (gc_needs_major_flags == GPR_FLAG_NONE) {
- rb_bug("cannot create a new page after GC");
- }
- else { // Major GC is required, which will allow us to create new page
- if (gc_start(objspace, GPR_FLAG_NEWOBJ) == FALSE) {
- rb_memerror();
- }
- else {
- /* Do steps of incremental marking or lazy sweeping. */
- gc_continue(objspace, size_pool, heap);
-
- if (heap->free_pages == NULL &&
- !heap_increment(objspace, size_pool, heap)) {
- rb_bug("cannot create a new page after major GC");
- }
- }
- }
- }
- }
- }
-
- GC_ASSERT(heap->free_pages != NULL);
+ return objspace;
}
void
-rb_objspace_set_event_hook(const rb_event_flag_t event)
+rb_objspace_free(void *objspace)
{
- rb_objspace_t *objspace = &rb_objspace;
- objspace->hook_events = event & RUBY_INTERNAL_EVENT_OBJSPACE_MASK;
- objspace->flags.has_newobj_hook = !!(objspace->hook_events & RUBY_INTERNAL_EVENT_NEWOBJ);
-}
-
-static void
-gc_event_hook_body(rb_execution_context_t *ec, rb_objspace_t *objspace, const rb_event_flag_t event, VALUE data)
-{
- if (UNLIKELY(!ec->cfp)) return;
- EXEC_EVENT_HOOK(ec, event, ec->cfp->self, 0, 0, 0, data);
-}
-
-#define gc_event_newobj_hook_needed_p(objspace) ((objspace)->flags.has_newobj_hook)
-#define gc_event_hook_needed_p(objspace, event) ((objspace)->hook_events & (event))
-
-#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, 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;
-
- int t = flags & RUBY_T_MASK;
- if (t == T_CLASS || t == T_MODULE || t == T_ICLASS) {
- RVALUE_AGE_SET_CANDIDATE(objspace, obj);
- }
-
-#if RACTOR_CHECK_MODE
- rb_ractor_setup_belonging(obj);
-#endif
-
-#if RGENGC_CHECK_MODE
- p->as.values.v1 = p->as.values.v2 = p->as.values.v3 = 0;
-
- 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 (RVALUE_REMEMBERED((VALUE)obj)) rb_bug("newobj: %s is remembered.", obj_info(obj));
- }
- RB_VM_LOCK_LEAVE_NO_BARRIER();
-#endif
-
- if (UNLIKELY(wb_protected == FALSE)) {
- ASSERT_vm_locking();
- MARK_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(obj), obj);
- }
-
-#if RGENGC_PROFILE
- if (wb_protected) {
- objspace->profile.total_generated_normal_object_count++;
-#if RGENGC_PROFILE >= 2
- objspace->profile.generated_normal_object_count_types[BUILTIN_TYPE(obj)]++;
-#endif
- }
- else {
- objspace->profile.total_generated_shady_object_count++;
-#if RGENGC_PROFILE >= 2
- objspace->profile.generated_shady_object_count_types[BUILTIN_TYPE(obj)]++;
-#endif
- }
-#endif
-
-#if GC_DEBUG
- GET_RVALUE_OVERHEAD(obj)->file = rb_source_location_cstr(&GET_RVALUE_OVERHEAD(obj)->line);
- GC_ASSERT(!SPECIAL_CONST_P(obj)); /* check alignment */
-#endif
-
- gc_report(5, objspace, "newobj: %s\n", obj_info_basic(obj));
-
- // RUBY_DEBUG_LOG("obj:%p (%s)", (void *)obj, obj_type_name(obj));
- return obj;
+ rb_gc_impl_objspace_free(objspace);
}
size_t
rb_gc_obj_slot_size(VALUE obj)
{
- return GET_HEAP_PAGE(obj)->slot_size - RVALUE_OVERHEAD;
-}
-
-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) * BASE_SLOT_SIZE;
-
-#if RGENGC_CHECK_MODE
- rb_objspace_t *objspace = &rb_objspace;
- GC_ASSERT(size_pools[pool_id].slot_size == (short)slot_size);
-#endif
-
- slot_size -= RVALUE_OVERHEAD;
-
- return slot_size;
-}
-
-bool
-rb_gc_size_allocatable_p(size_t size)
-{
- return size <= size_pool_slot_size(SIZE_POOL_COUNT - 1);
-}
-
-static size_t size_pool_sizes[SIZE_POOL_COUNT + 1] = { 0 };
-
-size_t *
-rb_gc_size_pool_sizes(void)
-{
- if (size_pool_sizes[0] == 0) {
- for (unsigned char i = 0; i < SIZE_POOL_COUNT; i++) {
- size_pool_sizes[i] = size_pool_slot_size(i);
- }
- }
-
- return size_pool_sizes;
-}
-
-size_t
-rb_gc_size_pool_id_for_size(size_t size)
-{
- size += RVALUE_OVERHEAD;
-
- size_t slot_count = CEILDIV(size, BASE_SLOT_SIZE);
-
- /* 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("rb_gc_size_pool_id_for_size: allocation size too large "
- "(size=%"PRIuSIZE"u, size_pool_idx=%"PRIuSIZE"u)", size, size_pool_idx);
- }
-
-#if RGENGC_CHECK_MODE
- rb_objspace_t *objspace = &rb_objspace;
- GC_ASSERT(size <= (size_t)size_pools[size_pool_idx].slot_size);
- if (size_pool_idx > 0) GC_ASSERT(size > (size_t)size_pools[size_pool_idx - 1].slot_size);
-#endif
-
- return size_pool_idx;
+ return rb_gc_impl_obj_slot_size(obj);
}
-static inline VALUE
-ractor_cache_allocate_slot(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache,
- size_t size_pool_idx)
+static inline void
+gc_validate_pc(VALUE obj)
{
- rb_ractor_newobj_size_pool_cache_t *size_pool_cache = &cache->size_pool_caches[size_pool_idx];
- RVALUE *p = size_pool_cache->freelist;
-
- if (is_incremental_marking(objspace)) {
- // Not allowed to allocate without running an incremental marking step
- if (cache->incremental_mark_step_allocated_slots >= INCREMENTAL_MARK_STEP_ALLOCATIONS) {
- return Qfalse;
- }
+#if RUBY_DEBUG
+ // IMEMOs and objects without a class (e.g managed id table) are not traceable
+ if (RB_TYPE_P(obj, T_IMEMO) || !CLASS_OF(obj)) return;
- if (p) {
- cache->incremental_mark_step_allocated_slots++;
- }
+ rb_execution_context_t *ec = GET_EC();
+ const rb_control_frame_t *cfp = ec->cfp;
+ if (cfp && VM_FRAME_RUBYFRAME_P(cfp) && cfp->pc) {
+ const VALUE *iseq_encoded = ISEQ_BODY(cfp->iseq)->iseq_encoded;
+ const VALUE *iseq_encoded_end = iseq_encoded + ISEQ_BODY(cfp->iseq)->iseq_size;
+ RUBY_ASSERT(cfp->pc >= iseq_encoded, "PC not set when allocating, breaking tracing");
+ RUBY_ASSERT(cfp->pc <= iseq_encoded_end, "PC not set when allocating, breaking tracing");
}
-
- if (p) {
- VALUE obj = (VALUE)p;
- MAYBE_UNUSED(const size_t) stride = size_pool_slot_size(size_pool_idx);
- size_pool_cache->freelist = p->as.free.next;
- asan_unpoison_memory_region(p, stride, true);
-#if RGENGC_CHECK_MODE
- GC_ASSERT(rb_gc_obj_slot_size(obj) == stride);
- // zero clear
- MEMZERO((char *)obj, char, stride);
#endif
- return obj;
- }
- else {
- return Qfalse;
- }
-}
-
-static struct heap_page *
-heap_next_free_page(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap)
-{
- ASSERT_vm_locking();
-
- struct heap_page *page;
-
- if (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_unlock_freelist(page);
-
- return page;
-}
-
-static inline void
-ractor_cache_set_page(rb_ractor_newobj_cache_t *cache, size_t size_pool_idx,
- struct heap_page *page)
-{
- 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 *size_pool_cache = &cache->size_pool_caches[size_pool_idx];
-
- GC_ASSERT(size_pool_cache->freelist == NULL);
- GC_ASSERT(page->free_slots != 0);
- GC_ASSERT(page->freelist != NULL);
-
- size_pool_cache->using_page = page;
- size_pool_cache->freelist = page->freelist;
- page->free_slots = 0;
- page->freelist = NULL;
-
- asan_unpoison_object((VALUE)size_pool_cache->freelist, false);
- GC_ASSERT(RB_TYPE_P((VALUE)size_pool_cache->freelist, T_NONE));
- asan_poison_object((VALUE)size_pool_cache->freelist);
}
static inline VALUE
-newobj_fill(VALUE obj, VALUE v1, VALUE v2, VALUE v3)
+newobj_of(rb_ractor_t *cr, VALUE klass, VALUE flags, shape_id_t shape_id, bool wb_protected, size_t size)
{
- RVALUE *p = (RVALUE *)obj;
- p->as.values.v1 = v1;
- p->as.values.v2 = v2;
- p->as.values.v3 = v3;
- return obj;
-}
+ VALUE obj = rb_gc_impl_new_obj(rb_gc_get_objspace(), cr->newobj_cache, klass, flags, wb_protected, size);
+ RBASIC_SET_SHAPE_ID_NO_CHECKS(obj, shape_id);
-static VALUE
-newobj_alloc(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t size_pool_idx, bool vm_locked)
-{
- rb_size_pool_t *size_pool = &size_pools[size_pool_idx];
- rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(size_pool);
-
- VALUE obj = ractor_cache_allocate_slot(objspace, cache, size_pool_idx);
-
- if (UNLIKELY(obj == Qfalse)) {
- unsigned int lev;
- bool unlock_vm = false;
-
- if (!vm_locked) {
- RB_VM_LOCK_ENTER_CR_LEV(GET_RACTOR(), &lev);
- vm_locked = true;
- unlock_vm = true;
- }
+ gc_validate_pc(obj);
+ if (UNLIKELY(rb_gc_event_hook_required_p(RUBY_INTERNAL_EVENT_NEWOBJ))) {
+ int lev = RB_GC_VM_LOCK_NO_BARRIER();
{
- ASSERT_vm_locking();
-
- if (is_incremental_marking(objspace)) {
- gc_continue(objspace, size_pool, heap);
- cache->incremental_mark_step_allocated_slots = 0;
-
- // Retry allocation after resetting incremental_mark_step_allocated_slots
- obj = ractor_cache_allocate_slot(objspace, cache, size_pool_idx);
+ size_t slot_size = rb_gc_obj_slot_size(obj);
+ if (slot_size > RVALUE_SIZE) {
+ memset((char *)obj + RVALUE_SIZE, 0, slot_size - RVALUE_SIZE);
}
- if (obj == Qfalse) {
- // Get next free page (possibly running GC)
- struct heap_page *page = heap_next_free_page(objspace, size_pool, heap);
- ractor_cache_set_page(cache, size_pool_idx, page);
-
- // Retry allocation after moving to new page
- obj = ractor_cache_allocate_slot(objspace, cache, size_pool_idx);
+ /* We must disable GC here because the callback could call xmalloc
+ * which could potentially trigger a GC, and a lot of code is unsafe
+ * to trigger a GC right after an object has been allocated because
+ * they perform initialization for the object and assume that the
+ * GC does not trigger before then. */
+ bool gc_disabled = RTEST(rb_gc_disable_no_rest());
+ {
+ rb_gc_event_hook(obj, RUBY_INTERNAL_EVENT_NEWOBJ);
}
+ if (!gc_disabled) rb_gc_enable();
}
-
- if (unlock_vm) {
- RB_VM_LOCK_LEAVE_CR_LEV(GET_RACTOR(), &lev);
- }
-
- if (UNLIKELY(obj == Qfalse)) {
- rb_memerror();
- }
+ RB_GC_VM_UNLOCK_NO_BARRIER(lev);
}
- size_pool->total_allocated_objects++;
-
- return obj;
-}
-
-static void
-newobj_zero_slot(VALUE obj)
-{
- memset((char *)obj + sizeof(struct RBasic), 0, rb_gc_obj_slot_size(obj) - sizeof(struct RBasic));
-}
-
-ALWAYS_INLINE(static VALUE newobj_slowpath(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, int wb_protected, size_t size_pool_idx));
-
-static inline VALUE
-newobj_slowpath(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, int wb_protected, size_t size_pool_idx)
-{
- VALUE obj;
- unsigned int lev;
-
- RB_VM_LOCK_ENTER_CR_LEV(GET_RACTOR(), &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();
- }
- }
- }
-
- obj = newobj_alloc(objspace, cache, size_pool_idx, true);
- newobj_init(klass, flags, wb_protected, objspace, obj);
+#if RGENGC_CHECK_MODE
+# ifndef GC_DEBUG_SLOT_FILL_SPECIAL_VALUE
+# define GC_DEBUG_SLOT_FILL_SPECIAL_VALUE 255
+# endif
- gc_event_hook_prep(objspace, RUBY_INTERNAL_EVENT_NEWOBJ, obj, newobj_zero_slot(obj));
- }
- RB_VM_LOCK_LEAVE_CR_LEV(GET_RACTOR(), &lev);
+ memset(
+ (void *)(obj + sizeof(struct RBasic)),
+ GC_DEBUG_SLOT_FILL_SPECIAL_VALUE,
+ rb_gc_obj_slot_size(obj) - sizeof(struct RBasic)
+ );
+#endif
return obj;
}
-NOINLINE(static VALUE newobj_slowpath_wb_protected(VALUE klass, VALUE flags,
- rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t size_pool_idx));
-NOINLINE(static VALUE newobj_slowpath_wb_unprotected(VALUE klass, VALUE flags,
- rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t size_pool_idx));
-
-static VALUE
-newobj_slowpath_wb_protected(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t size_pool_idx)
-{
- return newobj_slowpath(klass, flags, objspace, cache, TRUE, size_pool_idx);
-}
-
-static VALUE
-newobj_slowpath_wb_unprotected(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t size_pool_idx)
-{
- return newobj_slowpath(klass, flags, objspace, cache, FALSE, size_pool_idx);
-}
-
-static inline VALUE
-newobj_of(rb_ractor_t *cr, VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, int wb_protected, size_t alloc_size)
+VALUE
+rb_wb_unprotected_newobj_of(VALUE klass, VALUE flags, shape_id_t shape_id, size_t size)
{
- 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);
-
- if (UNLIKELY(stress_to_class)) {
- long i, cnt = RARRAY_LEN(stress_to_class);
- for (i = 0; i < cnt; ++i) {
- if (klass == RARRAY_AREF(stress_to_class, i)) rb_memerror();
- }
- }
-
- size_t size_pool_idx = rb_gc_size_pool_id_for_size(alloc_size);
-
- rb_ractor_newobj_cache_t *cache = &cr->newobj_cache;
-
- if (!UNLIKELY(during_gc ||
- ruby_gc_stressful ||
- gc_event_newobj_hook_needed_p(objspace)) &&
- wb_protected) {
- obj = newobj_alloc(objspace, cache, size_pool_idx, false);
- newobj_init(klass, flags, wb_protected, objspace, obj);
- }
- else {
- RB_DEBUG_COUNTER_INC(obj_newobj_slowpath);
-
- obj = wb_protected ?
- newobj_slowpath_wb_protected(klass, flags, objspace, cache, size_pool_idx) :
- newobj_slowpath_wb_unprotected(klass, flags, objspace, cache, size_pool_idx);
- }
-
- return newobj_fill(obj, v1, v2, v3);
+ GC_ASSERT((flags & FL_WB_PROTECTED) == 0);
+ return newobj_of(GET_RACTOR(), klass, flags, shape_id, FALSE, size);
}
VALUE
-rb_wb_unprotected_newobj_of(VALUE klass, VALUE flags, size_t size)
+rb_wb_protected_newobj_of(rb_execution_context_t *ec, VALUE klass, VALUE flags, shape_id_t shape_id, size_t size)
{
GC_ASSERT((flags & FL_WB_PROTECTED) == 0);
- return newobj_of(GET_RACTOR(), klass, flags, 0, 0, 0, FALSE, size);
+ return newobj_of(rb_ec_ractor_ptr(ec), klass, flags, shape_id, TRUE, size);
}
-VALUE
-rb_wb_protected_newobj_of(rb_execution_context_t *ec, VALUE klass, VALUE flags, size_t size)
+void
+rb_gc_register_pinning_obj(VALUE obj)
{
- GC_ASSERT((flags & FL_WB_PROTECTED) == 0);
- return newobj_of(rb_ec_ractor_ptr(ec), klass, flags, 0, 0, 0, TRUE, size);
+ rb_gc_impl_register_pinning_obj(rb_gc_get_objspace(), obj);
}
#define UNEXPECTED_NODE(func) \
@@ -2984,7 +1084,16 @@ rb_data_object_wrap(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FU
{
RUBY_ASSERT_ALWAYS(dfree != (RUBY_DATA_FUNC)1);
if (klass) rb_data_object_check(klass);
- return newobj_of(GET_RACTOR(), klass, T_DATA, (VALUE)dmark, (VALUE)dfree, (VALUE)datap, !dmark, sizeof(struct RTypedData));
+ VALUE obj = newobj_of(GET_RACTOR(), klass, T_DATA, ROOT_SHAPE_ID, !dmark, sizeof(struct RTypedData));
+
+ rb_gc_register_pinning_obj(obj);
+
+ struct RData *data = (struct RData *)obj;
+ data->dmark = dmark;
+ data->dfree = dfree;
+ data->data = datap;
+
+ return obj;
}
VALUE
@@ -2995,19 +1104,32 @@ rb_data_object_zalloc(VALUE klass, size_t size, RUBY_DATA_FUNC dmark, RUBY_DATA_
return obj;
}
+#define RTYPEDDATA_EMBEDDED_P rbimpl_typeddata_embedded_p
+#define RB_DATA_TYPE_EMBEDDABLE_P(type) ((type)->flags & RUBY_TYPED_EMBEDDABLE)
+#define RTYPEDDATA_EMBEDDABLE_P(obj) RB_DATA_TYPE_EMBEDDABLE_P(RTYPEDDATA_TYPE(obj))
+
static VALUE
typed_data_alloc(VALUE klass, VALUE typed_flag, void *datap, const rb_data_type_t *type, size_t size)
{
RBIMPL_NONNULL_ARG(type);
if (klass) rb_data_object_check(klass);
bool wb_protected = (type->flags & RUBY_FL_WB_PROTECTED) || !type->function.dmark;
- return newobj_of(GET_RACTOR(), klass, T_DATA, (VALUE)type, 1 | typed_flag, (VALUE)datap, wb_protected, size);
+ VALUE obj = newobj_of(GET_RACTOR(), klass, T_DATA | RUBY_TYPED_FL_IS_TYPED_DATA, ROOT_SHAPE_ID, wb_protected, size);
+
+ rb_gc_register_pinning_obj(obj);
+
+ struct RTypedData *data = (struct RTypedData *)obj;
+ data->fields_obj = 0;
+ *(VALUE *)&data->type = ((VALUE)type) | typed_flag;
+ data->data = datap;
+
+ return obj;
}
VALUE
rb_data_typed_object_wrap(VALUE klass, void *datap, const rb_data_type_t *type)
{
- if (UNLIKELY(type->flags & RUBY_TYPED_EMBEDDABLE)) {
+ if (UNLIKELY(RB_DATA_TYPE_EMBEDDABLE_P(type))) {
rb_raise(rb_eTypeError, "Cannot wrap an embeddable TypedData");
}
@@ -3017,7 +1139,7 @@ rb_data_typed_object_wrap(VALUE klass, void *datap, const rb_data_type_t *type)
VALUE
rb_data_typed_object_zalloc(VALUE klass, size_t size, const rb_data_type_t *type)
{
- if (type->flags & RUBY_TYPED_EMBEDDABLE) {
+ if (RB_DATA_TYPE_EMBEDDABLE_P(type)) {
if (!(type->flags & RUBY_TYPED_FREE_IMMEDIATELY)) {
rb_raise(rb_eTypeError, "Embeddable TypedData must be freed immediately");
}
@@ -3043,7 +1165,7 @@ rb_objspace_data_type_memsize(VALUE obj)
const rb_data_type_t *type = RTYPEDDATA_TYPE(obj);
const void *ptr = RTYPEDDATA_GET_DATA(obj);
- if (RTYPEDDATA_TYPE(obj)->flags & RUBY_TYPED_EMBEDDABLE && !RTYPEDDATA_EMBEDDED_P(obj)) {
+ if (RTYPEDDATA_EMBEDDABLE_P(obj) && !RTYPEDDATA_EMBEDDED_P(obj)) {
#ifdef HAVE_MALLOC_USABLE_SIZE
size += malloc_usable_size((void *)ptr);
#endif
@@ -3068,129 +1190,73 @@ rb_objspace_data_type_name(VALUE obj)
}
}
-static int
-ptr_in_page_body_p(const void *ptr, const void *memb)
+void
+rb_gc_declare_weak_references(VALUE obj)
{
- struct heap_page *page = *(struct heap_page **)memb;
- uintptr_t p_body = (uintptr_t)GET_PAGE_BODY(page->start);
-
- if ((uintptr_t)ptr >= p_body) {
- return (uintptr_t)ptr < (p_body + HEAP_PAGE_SIZE) ? 0 : 1;
- }
- else {
- return -1;
- }
+ rb_gc_impl_declare_weak_references(rb_gc_get_objspace(), obj);
}
-PUREFUNC(static inline struct heap_page * heap_page_for_ptr(rb_objspace_t *objspace, uintptr_t ptr);)
-static inline struct heap_page *
-heap_page_for_ptr(rb_objspace_t *objspace, uintptr_t ptr)
+bool
+rb_gc_handle_weak_references_alive_p(VALUE obj)
{
- struct heap_page **res;
-
- if (ptr < (uintptr_t)heap_pages_lomem ||
- ptr > (uintptr_t)heap_pages_himem) {
- return NULL;
- }
-
- res = bsearch((void *)ptr, heap_pages_sorted,
- (size_t)heap_allocated_pages, sizeof(struct heap_page *),
- ptr_in_page_body_p);
+ if (SPECIAL_CONST_P(obj)) return true;
- if (res) {
- return *res;
- }
- else {
- return NULL;
- }
+ return rb_gc_impl_handle_weak_references_alive_p(rb_gc_get_objspace(), obj);
}
-PUREFUNC(static inline int is_pointer_to_heap(rb_objspace_t *objspace, const void *ptr);)
-static inline int
-is_pointer_to_heap(rb_objspace_t *objspace, const void *ptr)
+void
+rb_gc_handle_weak_references(VALUE obj)
{
- register uintptr_t p = (uintptr_t)ptr;
- register struct heap_page *page;
-
- RB_DEBUG_COUNTER_INC(gc_isptr_trial);
-
- if (p < heap_pages_lomem || p > heap_pages_himem) return FALSE;
- RB_DEBUG_COUNTER_INC(gc_isptr_range);
-
- if (p % BASE_SLOT_SIZE != 0) return FALSE;
- RB_DEBUG_COUNTER_INC(gc_isptr_align);
+ switch (BUILTIN_TYPE(obj)) {
+ case T_DATA:
+ if (RTYPEDDATA_P(obj)) {
+ const rb_data_type_t *type = RTYPEDDATA_TYPE(obj);
- page = heap_page_for_ptr(objspace, (uintptr_t)ptr);
- if (page) {
- RB_DEBUG_COUNTER_INC(gc_isptr_maybe);
- if (page->flags.in_tomb) {
- return FALSE;
+ if (type->function.handle_weak_references) {
+ (type->function.handle_weak_references)(RTYPEDDATA_GET_DATA(obj));
+ }
+ else {
+ rb_bug(
+ "rb_gc_handle_weak_references: TypedData %s does not implement handle_weak_references",
+ RTYPEDDATA_TYPE(obj)->wrap_struct_name
+ );
+ }
}
else {
- if (p < page->start) return FALSE;
- if (p >= page->start + (page->total_slots * page->slot_size)) return FALSE;
- if ((NUM_IN_PAGE(p) * BASE_SLOT_SIZE) % page->slot_size != 0) return FALSE;
-
- return TRUE;
+ rb_bug("rb_gc_handle_weak_references: unknown T_DATA");
}
- }
- return FALSE;
-}
-
-static enum rb_id_table_iterator_result
-cvar_table_free_i(VALUE value, void *ctx)
-{
- xfree((void *)value);
- return ID_TABLE_CONTINUE;
-}
+ break;
-#define ZOMBIE_OBJ_KEPT_FLAGS (FL_SEEN_OBJ_ID | FL_FINALIZE)
+ case T_IMEMO: {
+ GC_ASSERT(imemo_type(obj) == imemo_callcache);
-static inline void
-make_zombie(rb_objspace_t *objspace, VALUE obj, void (*dfree)(void *), void *data)
-{
- struct RZombie *zombie = RZOMBIE(obj);
- zombie->basic.flags = T_ZOMBIE | (zombie->basic.flags & ZOMBIE_OBJ_KEPT_FLAGS);
- zombie->dfree = dfree;
- zombie->data = data;
- VALUE prev, next = heap_pages_deferred_final;
- do {
- zombie->next = prev = next;
- next = RUBY_ATOMIC_VALUE_CAS(heap_pages_deferred_final, prev, obj);
- } while (next != prev);
+ struct rb_callcache *cc = (struct rb_callcache *)obj;
+ if (!rb_gc_handle_weak_references_alive_p(cc->klass)) {
+ vm_cc_invalidate(cc);
+ }
- struct heap_page *page = GET_HEAP_PAGE(obj);
- page->final_slots++;
- heap_pages_final_slots++;
+ break;
+ }
+ default:
+ rb_bug("rb_gc_handle_weak_references: type not supported\n");
+ }
}
-static inline void
-make_io_zombie(rb_objspace_t *objspace, VALUE obj)
+static void
+io_fptr_finalize(void *fptr)
{
- rb_io_t *fptr = RANY(obj)->as.file.fptr;
- make_zombie(objspace, obj, rb_io_fptr_finalize_internal, fptr);
+ rb_io_fptr_finalize((struct rb_io *)fptr);
}
-static void
-obj_free_object_id(rb_objspace_t *objspace, VALUE obj)
+static inline void
+make_io_zombie(void *objspace, VALUE obj)
{
- 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, &o, &id)) {
- GC_ASSERT(id);
- st_delete(objspace->id_to_obj_tbl, &id, NULL);
- }
- else {
- rb_bug("Object ID seen, but not in mapping table: %s", obj_info(obj));
- }
+ rb_io_t *fptr = RFILE(obj)->fptr;
+ rb_gc_impl_make_zombie(objspace, obj, io_fptr_finalize, fptr);
}
static bool
-rb_data_free(rb_objspace_t *objspace, VALUE obj)
+rb_data_free(void *objspace, VALUE obj)
{
void *data = RTYPEDDATA_P(obj) ? RTYPEDDATA_GET_DATA(obj) : DATA_PTR(obj);
if (data) {
@@ -3198,30 +1264,30 @@ rb_data_free(rb_objspace_t *objspace, VALUE obj)
void (*dfree)(void *);
if (RTYPEDDATA_P(obj)) {
- free_immediately = (RANY(obj)->as.typeddata.type->flags & RUBY_TYPED_FREE_IMMEDIATELY) != 0;
- dfree = RANY(obj)->as.typeddata.type->function.dfree;
+ free_immediately = (RTYPEDDATA_TYPE(obj)->flags & RUBY_TYPED_FREE_IMMEDIATELY) != 0;
+ dfree = RTYPEDDATA_TYPE(obj)->function.dfree;
}
else {
- dfree = RANY(obj)->as.data.dfree;
+ dfree = RDATA(obj)->dfree;
}
if (dfree) {
if (dfree == RUBY_DEFAULT_FREE) {
- if (!RTYPEDDATA_EMBEDDED_P(obj)) {
+ if (!RTYPEDDATA_P(obj) || !RTYPEDDATA_EMBEDDED_P(obj)) {
xfree(data);
RB_DEBUG_COUNTER_INC(obj_data_xfree);
}
}
else if (free_immediately) {
(*dfree)(data);
- if (RTYPEDDATA_TYPE(obj)->flags & RUBY_TYPED_EMBEDDABLE && !RTYPEDDATA_EMBEDDED_P(obj)) {
+ if (RTYPEDDATA_EMBEDDABLE_P(obj) && !RTYPEDDATA_EMBEDDED_P(obj)) {
xfree(data);
}
RB_DEBUG_COUNTER_INC(obj_data_imm_free);
}
else {
- make_zombie(objspace, obj, dfree, data);
+ rb_gc_impl_make_zombie(objspace, obj, dfree, data);
RB_DEBUG_COUNTER_INC(obj_data_zombie);
return FALSE;
}
@@ -3234,13 +1300,33 @@ rb_data_free(rb_objspace_t *objspace, VALUE obj)
return true;
}
-static int
-obj_free(rb_objspace_t *objspace, VALUE obj)
+struct classext_foreach_args {
+ VALUE klass;
+ rb_objspace_t *objspace; // used for update_*
+};
+
+static void
+classext_free(rb_classext_t *ext, bool is_prime, VALUE box_value, void *arg)
{
- RB_DEBUG_COUNTER_INC(obj_free);
- // RUBY_DEBUG_LOG("obj:%p (%s)", (void *)obj, obj_type_name(obj));
+ struct classext_foreach_args *args = (struct classext_foreach_args *)arg;
+
+ rb_class_classext_free(args->klass, ext, is_prime);
+}
- gc_event_hook(objspace, RUBY_INTERNAL_EVENT_FREEOBJ, obj);
+static void
+classext_iclass_free(rb_classext_t *ext, bool is_prime, VALUE box_value, void *arg)
+{
+ struct classext_foreach_args *args = (struct classext_foreach_args *)arg;
+
+ rb_iclass_classext_free(args->klass, ext, is_prime);
+}
+
+bool
+rb_gc_obj_free(void *objspace, VALUE obj)
+{
+ struct classext_foreach_args args;
+
+ RB_DEBUG_COUNTER_INC(obj_free);
switch (BUILTIN_TYPE(obj)) {
case T_NIL:
@@ -3253,65 +1339,32 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
break;
}
- if (FL_TEST(obj, FL_EXIVAR)) {
- rb_free_generic_ivar((VALUE)obj);
- FL_UNSET(obj, FL_EXIVAR);
- }
-
- if (FL_TEST(obj, FL_SEEN_OBJ_ID) && !FL_TEST(obj, FL_FINALIZE)) {
- obj_free_object_id(objspace, obj);
- }
-
- if (RVALUE_WB_UNPROTECTED(obj)) CLEAR_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(obj), obj);
-
-#if RGENGC_CHECK_MODE
-#define CHECK(x) if (x(obj) != FALSE) rb_bug("obj_free: " #x "(%s) != FALSE", obj_info(obj))
- CHECK(RVALUE_WB_UNPROTECTED);
- CHECK(RVALUE_MARKED);
- CHECK(RVALUE_MARKING);
- CHECK(RVALUE_UNCOLLECTIBLE);
-#undef CHECK
-#endif
-
switch (BUILTIN_TYPE(obj)) {
case T_OBJECT:
- if (rb_shape_obj_too_complex(obj)) {
- RB_DEBUG_COUNTER_INC(obj_obj_too_complex);
- st_free_table(ROBJECT_IV_HASH(obj));
- }
- else if (RANY(obj)->as.basic.flags & ROBJECT_EMBED) {
- RB_DEBUG_COUNTER_INC(obj_obj_embed);
+ if (FL_TEST_RAW(obj, ROBJECT_HEAP)) {
+ if (rb_shape_obj_too_complex_p(obj)) {
+ RB_DEBUG_COUNTER_INC(obj_obj_too_complex);
+ st_free_table(ROBJECT_FIELDS_HASH(obj));
+ }
+ else {
+ xfree(ROBJECT(obj)->as.heap.fields);
+ RB_DEBUG_COUNTER_INC(obj_obj_ptr);
+ }
}
else {
- xfree(RANY(obj)->as.object.as.heap.ivptr);
- RB_DEBUG_COUNTER_INC(obj_obj_ptr);
+ RB_DEBUG_COUNTER_INC(obj_obj_embed);
}
break;
case T_MODULE:
case T_CLASS:
- rb_id_table_free(RCLASS_M_TBL(obj));
- rb_cc_table_free(obj);
- if (rb_shape_obj_too_complex(obj)) {
- st_free_table((st_table *)RCLASS_IVPTR(obj));
- }
- else {
- xfree(RCLASS_IVPTR(obj));
- }
-
- if (RCLASS_CONST_TBL(obj)) {
- rb_free_const_table(RCLASS_CONST_TBL(obj));
- }
- 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 (FL_TEST_RAW(obj, RCLASS_SUPERCLASSES_INCLUDE_SELF)) {
- xfree(RCLASS_SUPERCLASSES(obj));
+#if USE_ZJIT
+ rb_zjit_klass_free(obj);
+#endif
+ args.klass = obj;
+ rb_class_classext_foreach(obj, classext_free, (void *)&args);
+ if (RCLASS_CLASSEXT_TBL(obj)) {
+ st_free_table(RCLASS_CLASSEXT_TBL(obj));
}
-
(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);
break;
@@ -3366,8 +1419,8 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
rb_hash_free(obj);
break;
case T_REGEXP:
- if (RANY(obj)->as.regexp.ptr) {
- onig_free(RANY(obj)->as.regexp.ptr);
+ if (RREGEXP(obj)->ptr) {
+ onig_free(RREGEXP(obj)->ptr);
RB_DEBUG_COUNTER_INC(obj_regexp_ptr);
}
break;
@@ -3395,7 +1448,7 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
}
break;
case T_FILE:
- if (RANY(obj)->as.file.fptr) {
+ if (RFILE(obj)->fptr) {
make_io_zombie(objspace, obj);
RB_DEBUG_COUNTER_INC(obj_file_ptr);
return FALSE;
@@ -3410,18 +1463,12 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
case T_MOVED:
break;
case T_ICLASS:
- /* Basically , T_ICLASS shares table with the module */
- 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));
+ args.klass = obj;
+
+ rb_class_classext_foreach(obj, classext_iclass_free, (void *)&args);
+ if (RCLASS_CLASSEXT_TBL(obj)) {
+ st_free_table(RCLASS_CLASSEXT_TBL(obj));
}
- rb_class_remove_subclass_head(obj);
- rb_cc_table_free(obj);
- rb_class_remove_from_module_subclasses(obj);
- rb_class_remove_from_super_subclasses(obj);
RB_DEBUG_COUNTER_INC(obj_iclass_ptr);
break;
@@ -3446,20 +1493,17 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
case T_STRUCT:
if ((RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK) ||
- RANY(obj)->as.rstruct.as.heap.ptr == NULL) {
+ RSTRUCT(obj)->as.heap.ptr == NULL) {
RB_DEBUG_COUNTER_INC(obj_struct_embed);
}
else {
- xfree((void *)RANY(obj)->as.rstruct.as.heap.ptr);
+ xfree((void *)RSTRUCT(obj)->as.heap.ptr);
RB_DEBUG_COUNTER_INC(obj_struct_ptr);
}
break;
case T_SYMBOL:
- {
- rb_gc_free_dsymbol(obj);
- RB_DEBUG_COUNTER_INC(obj_symbol);
- }
+ RB_DEBUG_COUNTER_INC(obj_symbol);
break;
case T_IMEMO:
@@ -3471,313 +1515,27 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
BUILTIN_TYPE(obj), (void*)obj, RBASIC(obj)->flags);
}
- if (FL_TEST(obj, FL_FINALIZE)) {
- make_zombie(objspace, obj, 0, 0);
+ if (FL_TEST_RAW(obj, FL_FINALIZE)) {
+ rb_gc_impl_make_zombie(objspace, obj, 0, 0);
return FALSE;
}
else {
- RBASIC(obj)->flags = 0;
return TRUE;
}
}
-
-#define OBJ_ID_INCREMENT (BASE_SLOT_SIZE)
-#define OBJ_ID_INITIAL (OBJ_ID_INCREMENT)
-
-static int
-object_id_cmp(st_data_t x, st_data_t y)
-{
- if (RB_BIGNUM_TYPE_P(x)) {
- return !rb_big_eql(x, y);
- }
- else {
- return x != y;
- }
-}
-
-static st_index_t
-object_id_hash(st_data_t n)
-{
- if (RB_BIGNUM_TYPE_P(n)) {
- return FIX2LONG(rb_big_hash(n));
- }
- else {
- return st_numhash(n);
- }
-}
-static const struct st_hash_type object_id_hash_type = {
- object_id_cmp,
- object_id_hash,
-};
-
-static void *
-rb_gc_impl_objspace_alloc(void)
-{
- rb_objspace_t *objspace = calloc1(sizeof(rb_objspace_t));
- ruby_current_vm_ptr->objspace = objspace;
-
- objspace->flags.gc_stressful = RTEST(initial_stress);
- objspace->gc_stress_mode = initial_stress;
-
- objspace->flags.measure_gc = 1;
- malloc_limit = gc_params.malloc_limit_min;
- objspace->finalize_deferred_pjob = rb_postponed_job_preregister(0, gc_finalize_deferred, objspace);
- if (objspace->finalize_deferred_pjob == POSTPONED_JOB_HANDLE_INVALID) {
- rb_bug("Could not preregister postponed job for GC");
- }
-
- for (int i = 0; i < SIZE_POOL_COUNT; i++) {
- rb_size_pool_t *size_pool = &size_pools[i];
-
- size_pool->slot_size = (1 << i) * BASE_SLOT_SIZE;
-
- ccan_list_head_init(&SIZE_POOL_EDEN_HEAP(size_pool)->pages);
- ccan_list_head_init(&SIZE_POOL_TOMB_HEAP(size_pool)->pages);
- }
-
- rb_darray_make(&objspace->weak_references, 0);
-
- // TODO: debug why on Windows Ruby crashes on boot when GC is on.
-#ifdef _WIN32
- dont_gc_on();
-#endif
-
-#if defined(INIT_HEAP_PAGE_ALLOC_USE_MMAP)
- /* Need to determine if we can use mmap at runtime. */
- heap_page_alloc_use_mmap = INIT_HEAP_PAGE_ALLOC_USE_MMAP;
-#endif
-
- objspace->next_object_id = OBJ_ID_INITIAL;
- objspace->id_to_obj_tbl = st_init_table(&object_id_hash_type);
- objspace->obj_to_id_tbl = st_init_numtable();
-
-#if RGENGC_ESTIMATE_OLDMALLOC
- objspace->rgengc.oldmalloc_increase_limit = gc_params.oldmalloc_limit_min;
-#endif
-
- /* Set size pools allocatable pages. */
- for (int i = 0; i < SIZE_POOL_COUNT; i++) {
- rb_size_pool_t *size_pool = &size_pools[i];
-
- /* Set the default value of size_pool_init_slots. */
- gc_params.size_pool_init_slots[i] = GC_HEAP_INIT_SLOTS;
-
- size_pool->allocatable_pages = minimum_pages_for_size_pool(objspace, size_pool);
- }
- heap_pages_expand_sorted(objspace);
-
- init_mark_stack(&objspace->mark_stack);
-
- objspace->profile.invoke_time = getrusage_time();
- finalizer_table = st_init_numtable();
- return objspace;
-}
-
-typedef int each_obj_callback(void *, void *, size_t, void *);
-typedef int each_page_callback(struct heap_page *, void *);
-
-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_data {
- rb_objspace_t *objspace;
- bool reenable_incremental;
-
- each_obj_callback *each_obj_callback;
- each_page_callback *each_page_callback;
- void *data;
-
- struct heap_page **pages[SIZE_POOL_COUNT];
- size_t pages_counts[SIZE_POOL_COUNT];
-};
-
-static VALUE
-objspace_each_objects_ensure(VALUE arg)
-{
- struct each_obj_data *data = (struct each_obj_data *)arg;
- rb_objspace_t *objspace = data->objspace;
-
- /* Reenable incremental GC */
- if (data->reenable_incremental) {
- objspace->flags.dont_incremental = FALSE;
- }
-
- for (int i = 0; i < SIZE_POOL_COUNT; i++) {
- struct heap_page **pages = data->pages[i];
- free(pages);
- }
-
- return Qnil;
-}
-
-static VALUE
-objspace_each_objects_try(VALUE arg)
-{
- 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;
- ccan_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 = ccan_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->each_obj_callback &&
- (*data->each_obj_callback)((void *)pstart, (void *)pend, size_pool->slot_size, data->data)) {
- break;
- }
- if (data->each_page_callback &&
- (*data->each_page_callback)(page, data->data)) {
- break;
- }
-
- page = ccan_list_next(&SIZE_POOL_EDEN_HEAP(size_pool)->pages, page, page_node);
- }
- }
-
- return Qnil;
-}
-
-/*
- * rb_objspace_each_objects() is special C API to walk through
- * Ruby object space. This C API is too difficult to use it.
- * To be frank, you should not use it. Or you need to read the
- * source code of this function and understand what this function does.
- *
- * 'callback' will be called several times (the number of heap page,
- * at current implementation) with:
- * vstart: a pointer to the first living object of the heap_page.
- * vend: a pointer to next to the valid heap_page area.
- * stride: a distance to next VALUE.
- *
- * If callback() returns non-zero, the iteration will be stopped.
- *
- * This is a sample callback code to iterate liveness objects:
- *
- * static int
- * sample_callback(void *vstart, void *vend, int stride, void *data)
- * {
- * VALUE v = (VALUE)vstart;
- * for (; v != (VALUE)vend; v += stride) {
- * if (!rb_objspace_internal_object_p(v)) { // liveness check
- * // do something with live object 'v'
- * }
- * }
- * return 0; // continue to iteration
- * }
- *
- * Note: 'vstart' is not a top of heap_page. This point the first
- * living object to grasp at least one object to avoid GC issue.
- * This means that you can not walk through all Ruby object page
- * including freed object page.
- *
- * 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.
- */
void
-rb_objspace_each_objects(each_obj_callback *callback, void *data)
-{
- objspace_each_objects(&rb_objspace, callback, data, TRUE);
-}
-
-static void
-objspace_each_exec(bool protected, struct each_obj_data *each_obj_data)
-{
- /* Disable incremental GC */
- rb_objspace_t *objspace = each_obj_data->objspace;
- bool reenable_incremental = FALSE;
- if (protected) {
- reenable_incremental = !objspace->flags.dont_incremental;
-
- gc_rest(objspace);
- objspace->flags.dont_incremental = TRUE;
- }
-
- each_obj_data->reenable_incremental = reenable_incremental;
- memset(&each_obj_data->pages, 0, sizeof(each_obj_data->pages));
- memset(&each_obj_data->pages_counts, 0, sizeof(each_obj_data->pages_counts));
- rb_ensure(objspace_each_objects_try, (VALUE)each_obj_data,
- objspace_each_objects_ensure, (VALUE)each_obj_data);
-}
-
-static void
-objspace_each_objects(rb_objspace_t *objspace, each_obj_callback *callback, void *data, bool protected)
+rb_objspace_set_event_hook(const rb_event_flag_t event)
{
- struct each_obj_data each_obj_data = {
- .objspace = objspace,
- .each_obj_callback = callback,
- .each_page_callback = NULL,
- .data = data,
- };
- objspace_each_exec(protected, &each_obj_data);
+ rb_gc_impl_set_event_hook(rb_gc_get_objspace(), event);
}
-#if GC_CAN_COMPILE_COMPACTION
-static void
-objspace_each_pages(rb_objspace_t *objspace, each_page_callback *callback, void *data, bool protected)
-{
- struct each_obj_data each_obj_data = {
- .objspace = objspace,
- .each_obj_callback = NULL,
- .each_page_callback = callback,
- .data = data,
- };
- objspace_each_exec(protected, &each_obj_data);
-}
-#endif
-
-struct os_each_struct {
- size_t num;
- VALUE of;
-};
-
static int
internal_object_p(VALUE obj)
{
- RVALUE *p = (RVALUE *)obj;
void *ptr = asan_unpoison_object_temporary(obj);
- bool used_p = p->as.basic.flags;
- if (used_p) {
+ if (RBASIC(obj)->flags) {
switch (BUILTIN_TYPE(obj)) {
case T_NODE:
UNEXPECTED_NODE(internal_object_p);
@@ -3789,18 +1547,21 @@ internal_object_p(VALUE obj)
case T_ZOMBIE:
break;
case T_CLASS:
- if (!p->as.basic.klass) break;
+ if (obj == rb_mRubyVMFrozenCore)
+ return 1;
+
+ if (!RBASIC_CLASS(obj)) break;
if (RCLASS_SINGLETON_P(obj)) {
return rb_singleton_class_internal_p(obj);
}
return 0;
default:
- if (!p->as.basic.klass) break;
+ if (!RBASIC(obj)->klass) break;
return 0;
}
}
- if (ptr || ! used_p) {
- asan_poison_object(obj);
+ if (ptr || !RBASIC(obj)->flags) {
+ rb_asan_poison_object(obj);
}
return 1;
}
@@ -3811,6 +1572,11 @@ rb_objspace_internal_object_p(VALUE obj)
return internal_object_p(obj);
}
+struct os_each_struct {
+ size_t num;
+ VALUE of;
+};
+
static int
os_obj_of_i(void *vstart, void *vend, size_t stride, void *data)
{
@@ -3851,30 +1617,34 @@ os_obj_of(VALUE of)
* Ruby process. If <i>module</i> is specified, calls the block
* for only those classes or modules that match (or are a subclass of)
* <i>module</i>. Returns the number of objects found. Immediate
- * objects (<code>Fixnum</code>s, <code>Symbol</code>s
- * <code>true</code>, <code>false</code>, and <code>nil</code>) are
- * never returned. In the example below, #each_object returns both
- * the numbers we defined and several constants defined in the Math
- * module.
+ * objects (such as <code>Fixnum</code>s, static <code>Symbol</code>s
+ * <code>true</code>, <code>false</code> and <code>nil</code>) are
+ * never returned.
*
* If no block is given, an enumerator is returned instead.
*
- * a = 102.7
- * b = 95 # Won't be returned
- * c = 12345678987654321
- * count = ObjectSpace.each_object(Numeric) {|x| p x }
+ * Job = Class.new
+ * jobs = [Job.new, Job.new]
+ * count = ObjectSpace.each_object(Job) {|x| p x }
* puts "Total count: #{count}"
*
* <em>produces:</em>
*
- * 12345678987654321
- * 102.7
- * 2.71828182845905
- * 3.14159265358979
- * 2.22044604925031e-16
- * 1.7976931348623157e+308
- * 2.2250738585072e-308
- * Total count: 7
+ * #<Job:0x000000011d6cbbf0>
+ * #<Job:0x000000011d6cbc68>
+ * Total count: 2
+ *
+ * Due to a current Ractor implementation issue, this method does not yield
+ * Ractor-unshareable objects when the process is in multi-Ractor mode. Multi-ractor
+ * mode is enabled when <code>Ractor.new</code> has been called for the first time.
+ * See https://bugs.ruby-lang.org/issues/19387 for more information.
+ *
+ * a = 12345678987654321 # shareable
+ * b = [].freeze # shareable
+ * c = {} # not shareable
+ * ObjectSpace.each_object {|x| x } # yields a, b, and c
+ * Ractor.new {} # enter multi-Ractor mode
+ * ObjectSpace.each_object {|x| x } # does not yield c
*
*/
@@ -3905,11 +1675,10 @@ undefine_final(VALUE os, VALUE obj)
VALUE
rb_undefine_finalizer(VALUE obj)
{
- rb_objspace_t *objspace = &rb_objspace;
- st_data_t data = obj;
rb_check_frozen(obj);
- st_delete(finalizer_table, &data, 0);
- FL_UNSET(obj, FL_FINALIZE);
+
+ rb_gc_impl_undefine_finalizer(rb_gc_get_objspace(), obj);
+
return obj;
}
@@ -3932,104 +1701,76 @@ should_be_finalizable(VALUE obj)
rb_check_frozen(obj);
}
-static VALUE
-rb_define_finalizer_no_check(VALUE obj, VALUE block)
+void
+rb_gc_copy_finalizer(VALUE dest, VALUE obj)
{
- rb_objspace_t *objspace = &rb_objspace;
- VALUE table;
- st_data_t data;
-
- RBASIC(obj)->flags |= FL_FINALIZE;
-
- if (st_lookup(finalizer_table, obj, &data)) {
- table = (VALUE)data;
-
- /* avoid duplicate block, table is usually small */
- {
- long len = RARRAY_LEN(table);
- long i;
-
- for (i = 0; i < len; i++) {
- VALUE recv = RARRAY_AREF(table, i);
- if (rb_equal(recv, block)) {
- block = recv;
- goto end;
- }
- }
- }
-
- rb_ary_push(table, block);
- }
- else {
- table = rb_ary_new3(1, 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;
+ rb_gc_impl_copy_finalizer(rb_gc_get_objspace(), dest, obj);
}
/*
* call-seq:
- * ObjectSpace.define_finalizer(obj, aProc=proc())
+ * ObjectSpace.define_finalizer(obj) {|id| ... } -> array
+ * ObjectSpace.define_finalizer(obj, finalizer) -> array
*
- * Adds <i>aProc</i> as a finalizer, to be called after <i>obj</i>
- * was destroyed. The object ID of the <i>obj</i> will be passed
- * as an argument to <i>aProc</i>. If <i>aProc</i> is a lambda or
- * method, make sure it can be called with a single argument.
+ * Adds a new finalizer for +obj+ that is called when +obj+ is destroyed
+ * by the garbage collector or when Ruby shuts down (which ever comes first).
*
- * The return value is an array <code>[0, aProc]</code>.
+ * With a block given, uses the block as the callback. Without a block given,
+ * uses a callable object +finalizer+ as the callback. The callback is called
+ * when +obj+ is destroyed with a single argument +id+ which is the object
+ * ID of +obj+ (see Object#object_id).
*
- * 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.
+ * The return value is an array <code>[0, callback]</code>, where +callback+
+ * is a Proc created from the block if one was given or +finalizer+ otherwise.
*
- * class Foo
- * def initialize(data_needed_for_finalization)
- * ObjectSpace.define_finalizer(self, self.class.create_finalizer(data_needed_for_finalization))
- * end
+ * Note that defining a finalizer in an instance method of the object may prevent
+ * the object from being garbage collected since if the block or +finalizer+ refers
+ * to +obj+ then +obj+ will never be reclaimed by the garbage collector. For example,
+ * the following script demonstrates the issue:
*
- * def self.create_finalizer(data_needed_for_finalization)
- * proc {
- * puts "finalizing #{data_needed_for_finalization}"
- * }
+ * class Foo
+ * def define_final
+ * ObjectSpace.define_finalizer(self) do |id|
+ * puts "Running finalizer for #{id}!"
+ * end
* end
* end
*
- * class Bar
- * class Remover
- * def initialize(data_needed_for_finalization)
- * @data_needed_for_finalization = data_needed_for_finalization
- * end
+ * obj = Foo.new
+ * obj.define_final
*
- * def call(id)
- * puts "finalizing #{@data_needed_for_finalization}"
- * end
+ * There are two patterns to solve this issue:
+ *
+ * - Create the finalizer in a non-instance method so it can safely capture
+ * the needed state:
+ *
+ * class Foo
+ * def define_final
+ * ObjectSpace.define_finalizer(self, self.class.create_finalizer)
* end
*
- * def initialize(data_needed_for_finalization)
- * ObjectSpace.define_finalizer(self, Remover.new(data_needed_for_finalization))
+ * def self.create_finalizer
+ * proc do |id|
+ * puts "Running finalizer for #{id}!"
+ * end
* 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.
+ * - Use a callable object:
*
- * class CapturesSelf
- * def initialize(name)
- * ObjectSpace.define_finalizer(self, proc {
- * # this finalizer will only be run on exit
- * puts "finalizing #{name}"
- * })
+ * class Foo
+ * class Finalizer
+ * def call(id)
+ * puts "Running finalizer for #{id}!"
+ * end
+ * end
+ *
+ * def define_final
+ * ObjectSpace.define_finalizer(self, Finalizer.new)
* end
* end
*
- * Also note that finalization can be unpredictable and is never guaranteed
+ * Note that finalization can be unpredictable and is never guaranteed
* to be run except on exit.
*/
@@ -4039,19 +1780,15 @@ define_final(int argc, VALUE *argv, VALUE os)
VALUE obj, block;
rb_scan_args(argc, argv, "11", &obj, &block);
- should_be_finalizable(obj);
if (argc == 1) {
block = rb_block_proc();
}
- else {
- should_be_callable(block);
- }
if (rb_callable_receiver(block) == obj) {
rb_warn("finalizer references object to be finalized");
}
- return rb_define_finalizer_no_check(obj, block);
+ return rb_define_finalizer(obj, block);
}
VALUE
@@ -4059,411 +1796,388 @@ rb_define_finalizer(VALUE obj, VALUE block)
{
should_be_finalizable(obj);
should_be_callable(block);
- return rb_define_finalizer_no_check(obj, block);
+
+ block = rb_gc_impl_define_finalizer(rb_gc_get_objspace(), obj, block);
+
+ block = rb_ary_new3(2, INT2FIX(0), block);
+ OBJ_FREEZE(block);
+ return block;
}
void
-rb_gc_copy_finalizer(VALUE dest, VALUE obj)
+rb_objspace_call_finalizer(void)
{
- rb_objspace_t *objspace = &rb_objspace;
- VALUE table;
- st_data_t data;
-
- if (!FL_TEST(obj, FL_FINALIZE)) return;
-
- if (RB_LIKELY(st_lookup(finalizer_table, obj, &data))) {
- table = (VALUE)data;
- st_insert(finalizer_table, dest, table);
- FL_SET(dest, FL_FINALIZE);
- }
- else {
- rb_bug("rb_gc_copy_finalizer: FL_FINALIZE set but not found in finalizer_table: %s", obj_info(obj));
- }
+ rb_gc_impl_shutdown_call_finalizer(rb_gc_get_objspace());
}
-static VALUE
-run_single_final(VALUE cmd, VALUE objid)
+void
+rb_objspace_free_objects(void *objspace)
{
- return rb_check_funcall(cmd, idCall, 1, &objid);
+ rb_gc_impl_shutdown_free_objects(objspace);
}
-static void
-warn_exception_in_finalizer(rb_execution_context_t *ec, VALUE final)
+int
+rb_objspace_garbage_object_p(VALUE obj)
{
- if (!UNDEF_P(final) && !NIL_P(ruby_verbose)) {
- VALUE errinfo = ec->errinfo;
- rb_warn("Exception in finalizer %+"PRIsVALUE, final);
- rb_ec_error_print(ec, errinfo);
- }
+ return !SPECIAL_CONST_P(obj) && rb_gc_impl_garbage_object_p(rb_gc_get_objspace(), obj);
}
-static void
-run_finalizer(rb_objspace_t *objspace, VALUE obj, VALUE table)
+bool
+rb_gc_pointer_to_heap_p(VALUE obj)
{
- long i;
- enum ruby_tag_type state;
- volatile struct {
- VALUE errinfo;
- VALUE objid;
- VALUE final;
- rb_control_frame_t *cfp;
- VALUE *sp;
- long finished;
- } saved;
+ return rb_gc_impl_pointer_to_heap_p(rb_gc_get_objspace(), (void *)obj);
+}
- rb_execution_context_t * volatile ec = GET_EC();
-#define RESTORE_FINALIZER() (\
- ec->cfp = saved.cfp, \
- ec->cfp->sp = saved.sp, \
- ec->errinfo = saved.errinfo)
+#define OBJ_ID_INCREMENT (RUBY_IMMEDIATE_MASK + 1)
+#define LAST_OBJECT_ID() (object_id_counter * OBJ_ID_INCREMENT)
+static VALUE id2ref_value = 0;
+static st_table *id2ref_tbl = NULL;
- saved.errinfo = ec->errinfo;
- saved.objid = rb_obj_id(obj);
- saved.cfp = ec->cfp;
- saved.sp = ec->cfp->sp;
- saved.finished = 0;
- saved.final = Qundef;
+#if SIZEOF_SIZE_T == SIZEOF_LONG_LONG
+static size_t object_id_counter = 1;
+#else
+static unsigned long long object_id_counter = 1;
+#endif
- 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(), i<RARRAY_LEN(table);
- saved.finished = ++i) {
- run_single_final(saved.final = RARRAY_AREF(table, i), saved.objid);
- }
- EC_POP_TAG();
-#undef RESTORE_FINALIZER
+static inline VALUE
+generate_next_object_id(void)
+{
+#if SIZEOF_SIZE_T == SIZEOF_LONG_LONG
+ // 64bit atomics are available
+ return SIZET2NUM(RUBY_ATOMIC_SIZE_FETCH_ADD(object_id_counter, 1) * OBJ_ID_INCREMENT);
+#else
+ unsigned int lock_lev = RB_GC_VM_LOCK();
+ VALUE id = ULL2NUM(++object_id_counter * OBJ_ID_INCREMENT);
+ RB_GC_VM_UNLOCK(lock_lev);
+ return id;
+#endif
}
-static void
-run_final(rb_objspace_t *objspace, VALUE zombie)
+void
+rb_gc_obj_id_moved(VALUE obj)
{
- if (RZOMBIE(zombie)->dfree) {
- RZOMBIE(zombie)->dfree(RZOMBIE(zombie)->data);
+ if (UNLIKELY(id2ref_tbl)) {
+ st_insert(id2ref_tbl, (st_data_t)rb_obj_id(obj), (st_data_t)obj);
}
+}
- st_data_t key = (st_data_t)zombie;
- if (FL_TEST_RAW(zombie, FL_FINALIZE)) {
- FL_UNSET(zombie, FL_FINALIZE);
- st_data_t table;
- if (st_delete(finalizer_table, &key, &table)) {
- run_finalizer(objspace, zombie, (VALUE)table);
- }
- else {
- rb_bug("FL_FINALIZE flag is set, but finalizers are not found");
- }
+static int
+object_id_cmp(st_data_t x, st_data_t y)
+{
+ if (RB_TYPE_P(x, T_BIGNUM)) {
+ return !rb_big_eql(x, y);
}
else {
- GC_ASSERT(!st_lookup(finalizer_table, key, NULL));
+ return x != y;
}
}
-static void
-finalize_list(rb_objspace_t *objspace, VALUE zombie)
+static st_index_t
+object_id_hash(st_data_t n)
{
- while (zombie) {
- VALUE next_zombie;
- struct heap_page *page;
- asan_unpoison_object(zombie, false);
- next_zombie = RZOMBIE(zombie)->next;
- page = GET_HEAP_PAGE(zombie);
-
- run_final(objspace, zombie);
-
- RB_VM_LOCK_ENTER();
- {
- GC_ASSERT(BUILTIN_TYPE(zombie) == T_ZOMBIE);
- if (FL_TEST(zombie, FL_SEEN_OBJ_ID)) {
- obj_free_object_id(objspace, zombie);
- }
-
- GC_ASSERT(heap_pages_final_slots > 0);
- GC_ASSERT(page->final_slots > 0);
+ return FIX2LONG(rb_hash((VALUE)n));
+}
- heap_pages_final_slots--;
- page->final_slots--;
- page->free_slots++;
- heap_page_add_freeobj(objspace, page, zombie);
- page->size_pool->total_freed_objects++;
- }
- RB_VM_LOCK_LEAVE();
+static const struct st_hash_type object_id_hash_type = {
+ object_id_cmp,
+ object_id_hash,
+};
- zombie = next_zombie;
- }
-}
+static void gc_mark_tbl_no_pin(st_table *table);
static void
-finalize_deferred_heap_pages(rb_objspace_t *objspace)
+id2ref_tbl_mark(void *data)
{
- VALUE zombie;
- while ((zombie = ATOMIC_VALUE_EXCHANGE(heap_pages_deferred_final, 0)) != 0) {
- finalize_list(objspace, zombie);
+ st_table *table = (st_table *)data;
+ if (UNLIKELY(!RB_POSFIXABLE(LAST_OBJECT_ID()))) {
+ // It's very unlikely, but if enough object ids were generated, keys may be T_BIGNUM
+ rb_mark_set(table);
}
+ // We purposely don't mark values, as they are weak references.
+ // rb_gc_obj_free_vm_weak_references takes care of cleaning them up.
}
-static void
-finalize_deferred(rb_objspace_t *objspace)
+static size_t
+id2ref_tbl_memsize(const void *data)
{
- rb_execution_context_t *ec = GET_EC();
- ec->interrupt_mask |= PENDING_INTERRUPT_MASK;
- finalize_deferred_heap_pages(objspace);
- ec->interrupt_mask &= ~PENDING_INTERRUPT_MASK;
+ return rb_st_memsize(data);
}
static void
-gc_finalize_deferred(void *dmy)
+id2ref_tbl_free(void *data)
{
- rb_objspace_t *objspace = dmy;
- if (ATOMIC_EXCHANGE(finalizing, 1)) return;
-
- finalize_deferred(objspace);
- ATOMIC_SET(finalizing, 0);
+ id2ref_tbl = NULL; // clear global ref
+ st_table *table = (st_table *)data;
+ st_free_table(table);
}
-static void
-gc_finalize_deferred_register(rb_objspace_t *objspace)
+static const rb_data_type_t id2ref_tbl_type = {
+ .wrap_struct_name = "VM/_id2ref_table",
+ .function = {
+ .dmark = id2ref_tbl_mark,
+ .dfree = id2ref_tbl_free,
+ .dsize = id2ref_tbl_memsize,
+ // dcompact function not required because the table is reference updated
+ // in rb_gc_vm_weak_table_foreach
+ },
+ .flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY
+};
+
+static VALUE
+class_object_id(VALUE klass)
{
- /* will enqueue a call to gc_finalize_deferred */
- rb_postponed_job_trigger(objspace->finalize_deferred_pjob);
+ VALUE id = RUBY_ATOMIC_VALUE_LOAD(RCLASS(klass)->object_id);
+ if (!id) {
+ unsigned int lock_lev = RB_GC_VM_LOCK();
+ id = generate_next_object_id();
+ VALUE existing_id = RUBY_ATOMIC_VALUE_CAS(RCLASS(klass)->object_id, 0, id);
+ if (existing_id) {
+ id = existing_id;
+ }
+ else if (RB_UNLIKELY(id2ref_tbl)) {
+ st_insert(id2ref_tbl, id, klass);
+ }
+ RB_GC_VM_UNLOCK(lock_lev);
+ }
+ return id;
}
-static int pop_mark_stack(mark_stack_t *stack, VALUE *data);
-
-static void
-gc_abort(rb_objspace_t *objspace)
+static inline VALUE
+object_id_get(VALUE obj, shape_id_t shape_id)
{
- if (is_incremental_marking(objspace)) {
- /* Remove all objects from the mark stack. */
- VALUE obj;
- while (pop_mark_stack(&objspace->mark_stack, &obj));
-
- objspace->flags.during_incremental_marking = FALSE;
+ VALUE id;
+ if (rb_shape_too_complex_p(shape_id)) {
+ id = rb_obj_field_get(obj, ROOT_TOO_COMPLEX_WITH_OBJ_ID);
}
-
- if (is_lazy_sweeping(objspace)) {
- 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->sweeping_page = NULL;
- struct heap_page *page = NULL;
-
- ccan_list_for_each(&heap->pages, page, page_node) {
- page->flags.before_sweep = false;
- }
- }
+ else {
+ id = rb_obj_field_get(obj, rb_shape_object_id(shape_id));
}
- 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);
- rgengc_mark_and_rememberset_clear(objspace, heap);
+#if RUBY_DEBUG
+ if (!(FIXNUM_P(id) || RB_TYPE_P(id, T_BIGNUM))) {
+ rb_p(obj);
+ rb_bug("Object's shape includes object_id, but it's missing %s", rb_obj_info(obj));
}
+#endif
- gc_mode_set(objspace, gc_mode_none);
-}
-
-struct force_finalize_list {
- VALUE obj;
- VALUE table;
- struct force_finalize_list *next;
-};
-
-static int
-force_chain_object(st_data_t key, st_data_t val, st_data_t arg)
-{
- struct force_finalize_list **prev = (struct force_finalize_list **)arg;
- struct force_finalize_list *curr = ALLOC(struct force_finalize_list);
- curr->obj = key;
- curr->table = val;
- curr->next = *prev;
- *prev = curr;
- return ST_CONTINUE;
+ return id;
}
-static void
-gc_each_object(rb_objspace_t *objspace, void (*func)(VALUE obj, void *data), void *data)
+static VALUE
+object_id0(VALUE obj)
{
- for (size_t i = 0; i < heap_allocated_pages; i++) {
- struct heap_page *page = heap_pages_sorted[i];
- short stride = page->slot_size;
+ VALUE id = Qfalse;
+ shape_id_t shape_id = RBASIC_SHAPE_ID(obj);
- uintptr_t p = (uintptr_t)page->start;
- uintptr_t pend = p + page->total_slots * stride;
- for (; p < pend; p += stride) {
- VALUE obj = (VALUE)p;
+ if (rb_shape_has_object_id(shape_id)) {
+ return object_id_get(obj, shape_id);
+ }
- void *poisoned = asan_unpoison_object_temporary(obj);
+ shape_id_t object_id_shape_id = rb_shape_transition_object_id(obj);
- func(obj, data);
+ id = generate_next_object_id();
+ rb_obj_field_set(obj, object_id_shape_id, 0, id);
- if (poisoned) {
- GC_ASSERT(BUILTIN_TYPE(obj) == T_NONE);
- asan_poison_object(obj);
- }
+ RUBY_ASSERT(RBASIC_SHAPE_ID(obj) == object_id_shape_id);
+ RUBY_ASSERT(rb_shape_obj_has_id(obj));
+
+ if (RB_UNLIKELY(id2ref_tbl)) {
+ RB_VM_LOCKING() {
+ st_insert(id2ref_tbl, (st_data_t)id, (st_data_t)obj);
}
}
+ return id;
}
-bool rb_obj_is_main_ractor(VALUE gv);
-
-static void
-rb_objspace_free_objects_i(VALUE obj, void *data)
+static VALUE
+object_id(VALUE obj)
{
- rb_objspace_t *objspace = (rb_objspace_t *)data;
-
switch (BUILTIN_TYPE(obj)) {
- case T_NONE:
- case T_SYMBOL:
+ case T_CLASS:
+ case T_MODULE:
+ // With Ruby Box, classes and modules have different fields
+ // in different boxes, so we cannot store the object id
+ // in fields.
+ return class_object_id(obj);
+ case T_IMEMO:
+ RUBY_ASSERT(IMEMO_TYPE_P(obj, imemo_fields));
break;
default:
- obj_free(objspace, obj);
break;
}
-}
-void
-rb_objspace_free_objects(rb_objspace_t *objspace)
-{
- gc_each_object(objspace, rb_objspace_free_objects_i, objspace);
+ if (UNLIKELY(rb_gc_multi_ractor_p() && rb_ractor_shareable_p(obj))) {
+ unsigned int lock_lev = RB_GC_VM_LOCK();
+ VALUE id = object_id0(obj);
+ RB_GC_VM_UNLOCK(lock_lev);
+ return id;
+ }
+
+ return object_id0(obj);
}
static void
-rb_objspace_call_finalizer_i(VALUE obj, void *data)
+build_id2ref_i(VALUE obj, void *data)
{
- rb_objspace_t *objspace = (rb_objspace_t *)data;
+ st_table *id2ref_tbl = (st_table *)data;
switch (BUILTIN_TYPE(obj)) {
- case T_DATA:
- if (!rb_free_at_exit && (!DATA_PTR(obj) || !RANY(obj)->as.data.dfree)) break;
- if (rb_obj_is_thread(obj)) break;
- if (rb_obj_is_mutex(obj)) break;
- if (rb_obj_is_fiber(obj)) break;
- if (rb_obj_is_main_ractor(obj)) break;
-
- obj_free(objspace, obj);
+ case T_CLASS:
+ case T_MODULE:
+ RUBY_ASSERT(!rb_objspace_garbage_object_p(obj));
+ if (RCLASS(obj)->object_id) {
+ st_insert(id2ref_tbl, RCLASS(obj)->object_id, obj);
+ }
break;
- case T_FILE:
- obj_free(objspace, obj);
+ case T_IMEMO:
+ RUBY_ASSERT(!rb_objspace_garbage_object_p(obj));
+ if (IMEMO_TYPE_P(obj, imemo_fields) && rb_shape_obj_has_id(obj)) {
+ st_insert(id2ref_tbl, rb_obj_id(obj), rb_imemo_fields_owner(obj));
+ }
break;
- case T_SYMBOL:
- case T_ARRAY:
- case T_NONE:
+ case T_OBJECT:
+ RUBY_ASSERT(!rb_objspace_garbage_object_p(obj));
+ if (rb_shape_obj_has_id(obj)) {
+ st_insert(id2ref_tbl, rb_obj_id(obj), obj);
+ }
break;
default:
- if (rb_free_at_exit) {
- obj_free(objspace, obj);
- }
+ // For generic_fields, the T_IMEMO/fields is responsible for populating the entry.
break;
}
}
-void
-rb_objspace_call_finalizer(rb_objspace_t *objspace)
+static VALUE
+object_id_to_ref(void *objspace_ptr, VALUE object_id)
{
-#if RGENGC_CHECK_MODE >= 2
- gc_verify_internal_consistency(objspace);
-#endif
- if (ATOMIC_EXCHANGE(finalizing, 1)) return;
+ rb_objspace_t *objspace = objspace_ptr;
- /* run finalizers */
- finalize_deferred(objspace);
- GC_ASSERT(heap_pages_deferred_final == 0);
+ unsigned int lev = RB_GC_VM_LOCK();
- /* prohibit incremental GC */
- objspace->flags.dont_incremental = 1;
+ if (!id2ref_tbl) {
+ rb_gc_vm_barrier(); // stop other ractors
- /* force to run finalizer */
- while (finalizer_table->num_entries) {
- struct force_finalize_list *list = 0;
- st_foreach(finalizer_table, force_chain_object, (st_data_t)&list);
- while (list) {
- struct force_finalize_list *curr = list;
+ // GC Must not trigger while we build the table, otherwise if we end
+ // up freeing an object that had an ID, we might try to delete it from
+ // the table even though it wasn't inserted yet.
+ st_table *tmp_id2ref_tbl = st_init_table(&object_id_hash_type);
+ VALUE tmp_id2ref_value = TypedData_Wrap_Struct(0, &id2ref_tbl_type, tmp_id2ref_tbl);
- st_data_t obj = (st_data_t)curr->obj;
- st_delete(finalizer_table, &obj, 0);
- FL_UNSET(curr->obj, FL_FINALIZE);
-
- run_finalizer(objspace, curr->obj, curr->table);
+ // build_id2ref_i will most certainly malloc, which could trigger GC and sweep
+ // objects we just added to the table.
+ // By calling rb_gc_disable() we also save having to handle potentially garbage objects.
+ bool gc_disabled = RTEST(rb_gc_disable());
+ {
+ id2ref_tbl = tmp_id2ref_tbl;
+ id2ref_value = tmp_id2ref_value;
- list = curr->next;
- xfree(curr);
+ rb_gc_impl_each_object(objspace, build_id2ref_i, (void *)id2ref_tbl);
}
+ if (!gc_disabled) rb_gc_enable();
}
- /* Abort incremental marking and lazy sweeping to speed up shutdown. */
- gc_abort(objspace);
-
- /* prohibit GC because force T_DATA finalizers can break an object graph consistency */
- dont_gc_on();
-
- /* running data/file finalizers are part of garbage collection */
- unsigned int lock_lev;
- gc_enter(objspace, gc_enter_event_finalizer, &lock_lev);
-
- gc_each_object(objspace, rb_objspace_call_finalizer_i, objspace);
+ VALUE obj;
+ bool found = st_lookup(id2ref_tbl, object_id, &obj) && !rb_gc_impl_garbage_object_p(objspace, obj);
- gc_exit(objspace, gc_enter_event_finalizer, &lock_lev);
+ RB_GC_VM_UNLOCK(lev);
- finalize_deferred_heap_pages(objspace);
+ if (found) {
+ return obj;
+ }
- st_free_table(finalizer_table);
- finalizer_table = 0;
- ATOMIC_SET(finalizing, 0);
+ if (rb_funcall(object_id, rb_intern(">="), 1, ULL2NUM(LAST_OBJECT_ID()))) {
+ rb_raise(rb_eRangeError, "%+"PRIsVALUE" is not an id value", rb_funcall(object_id, rb_intern("to_s"), 1, INT2FIX(10)));
+ }
+ else {
+ rb_raise(rb_eRangeError, "%+"PRIsVALUE" is a recycled object", rb_funcall(object_id, rb_intern("to_s"), 1, INT2FIX(10)));
+ }
}
-/* garbage objects will be collected soon. */
-static inline bool
-is_garbage_object(rb_objspace_t *objspace, VALUE ptr)
+static inline void
+obj_free_object_id(VALUE obj)
{
- return is_lazy_sweeping(objspace) && GET_HEAP_PAGE(ptr)->flags.before_sweep &&
- !MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(ptr), ptr);
-}
+ VALUE obj_id = 0;
+ if (RB_UNLIKELY(id2ref_tbl)) {
+ switch (BUILTIN_TYPE(obj)) {
+ case T_CLASS:
+ case T_MODULE:
+ obj_id = RCLASS(obj)->object_id;
+ break;
+ case T_IMEMO:
+ if (!IMEMO_TYPE_P(obj, imemo_fields)) {
+ return;
+ }
+ // fallthrough
+ case T_OBJECT:
+ {
+ shape_id_t shape_id = RBASIC_SHAPE_ID(obj);
+ if (rb_shape_has_object_id(shape_id)) {
+ obj_id = object_id_get(obj, shape_id);
+ }
+ break;
+ }
+ default:
+ // For generic_fields, the T_IMEMO/fields is responsible for freeing the id.
+ return;
+ }
-static inline bool
-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 (RB_UNLIKELY(obj_id)) {
+ RUBY_ASSERT(FIXNUM_P(obj_id) || RB_TYPE_P(obj_id, T_BIGNUM));
- return !is_garbage_object(objspace, ptr);
+ if (!st_delete(id2ref_tbl, (st_data_t *)&obj_id, NULL)) {
+ // The the object is a T_IMEMO/fields, then it's possible the actual object
+ // has been garbage collected already.
+ if (!RB_TYPE_P(obj, T_IMEMO)) {
+ rb_bug("Object ID seen, but not in _id2ref table: object_id=%llu object=%s", NUM2ULL(obj_id), rb_obj_info(obj));
+ }
+ }
+ }
+ }
}
-static inline int
-is_markable_object(VALUE obj)
+void
+rb_gc_obj_free_vm_weak_references(VALUE obj)
{
- return !RB_SPECIAL_CONST_P(obj);
-}
+ ASSUME(!RB_SPECIAL_CONST_P(obj));
+ obj_free_object_id(obj);
-int
-rb_objspace_markable_object_p(VALUE obj)
-{
- rb_objspace_t *objspace = &rb_objspace;
- return is_markable_object(obj) && is_live_object(objspace, obj);
-}
+ if (rb_obj_gen_fields_p(obj)) {
+ rb_free_generic_ivar(obj);
+ }
-int
-rb_objspace_garbage_object_p(VALUE obj)
-{
- rb_objspace_t *objspace = &rb_objspace;
- return is_garbage_object(objspace, obj);
-}
+ switch (BUILTIN_TYPE(obj)) {
+ case T_STRING:
+ if (FL_TEST_RAW(obj, RSTRING_FSTR)) {
+ rb_gc_free_fstring(obj);
+ }
+ break;
+ case T_SYMBOL:
+ rb_gc_free_dsymbol(obj);
+ break;
+ case T_IMEMO:
+ switch (imemo_type(obj)) {
+ case imemo_callcache: {
+ const struct rb_callcache *cc = (const struct rb_callcache *)obj;
-bool
-rb_gc_is_ptr_to_obj(const void *ptr)
-{
- rb_objspace_t *objspace = &rb_objspace;
- return is_pointer_to_heap(objspace, ptr);
+ if (vm_cc_refinement_p(cc)) {
+ rb_vm_delete_cc_refinement(cc);
+ }
+
+ break;
+ }
+ case imemo_callinfo:
+ rb_vm_ci_free((const struct rb_callinfo *)obj);
+ break;
+ case imemo_ment:
+ rb_free_method_entry_vm_weak_references((const rb_method_entry_t *)obj);
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
}
/*
@@ -4479,21 +2193,16 @@ rb_gc_is_ptr_to_obj(const void *ptr)
*
* On multi-ractor mode, if the object is not shareable, it raises
* RangeError.
+ *
+ * This method is deprecated and should no longer be used.
*/
static VALUE
id2ref(VALUE objid)
{
-#if SIZEOF_LONG == SIZEOF_VOIDP
-#define NUM2PTR(x) NUM2ULONG(x)
-#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
-#define NUM2PTR(x) NUM2ULL(x)
-#endif
- rb_objspace_t *objspace = &rb_objspace;
-
objid = rb_to_int(objid);
if (FIXNUM_P(objid) || rb_big_size(objid) <= SIZEOF_VOIDP) {
- VALUE ptr = NUM2PTR(objid);
+ VALUE ptr = (VALUE)NUM2PTR(objid);
if (SPECIAL_CONST_P(ptr)) {
if (ptr == Qtrue) return Qtrue;
if (ptr == Qfalse) return Qfalse;
@@ -4507,30 +2216,20 @@ id2ref(VALUE objid)
return ptr;
}
else {
- rb_raise(rb_eRangeError, "%p is not symbol id value", (void *)ptr);
+ rb_raise(rb_eRangeError, "%p is not a symbol id value", (void *)ptr);
}
}
- rb_raise(rb_eRangeError, "%+"PRIsVALUE" is not id value", rb_int2str(objid, 10));
+ rb_raise(rb_eRangeError, "%+"PRIsVALUE" is not an id value", rb_int2str(objid, 10));
}
}
- VALUE orig;
- if (st_lookup(objspace->id_to_obj_tbl, objid, &orig) &&
- is_live_object(objspace, 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, ULL2NUM(objspace->next_object_id))) {
- rb_raise(rb_eRangeError, "%+"PRIsVALUE" is not id value", rb_int2str(objid, 10));
+ VALUE obj = object_id_to_ref(rb_gc_get_objspace(), objid);
+ if (!rb_multi_ractor_p() || rb_ractor_shareable_p(obj)) {
+ return obj;
}
else {
- rb_raise(rb_eRangeError, "%+"PRIsVALUE" is recycled object", rb_int2str(objid, 10));
+ rb_raise(rb_eRangeError, "%+"PRIsVALUE" is the id of an unshareable object on multi-ractor", rb_int2str(objid, 10));
}
}
@@ -4538,11 +2237,12 @@ id2ref(VALUE objid)
static VALUE
os_id2ref(VALUE os, VALUE objid)
{
+ rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "ObjectSpace._id2ref is deprecated");
return id2ref(objid);
}
static VALUE
-rb_find_object_id(VALUE obj, VALUE (*get_heap_object_id)(VALUE))
+rb_find_object_id(void *objspace, VALUE obj, VALUE (*get_heap_object_id)(VALUE))
{
if (SPECIAL_CONST_P(obj)) {
#if SIZEOF_LONG == SIZEOF_VOIDP
@@ -4556,33 +2256,6 @@ rb_find_object_id(VALUE obj, VALUE (*get_heap_object_id)(VALUE))
}
static VALUE
-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));
- }
- else {
- GC_ASSERT(!FL_TEST(obj, FL_SEEN_OBJ_ID));
-
- id = ULL2NUM(objspace->next_object_id);
- objspace->next_object_id += 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);
- }
- RB_VM_LOCK_LEAVE();
-
- return id;
-}
-
-static VALUE
nonspecial_obj_id(VALUE obj)
{
#if SIZEOF_LONG == SIZEOF_VOIDP
@@ -4597,7 +2270,7 @@ nonspecial_obj_id(VALUE obj)
VALUE
rb_memory_id(VALUE obj)
{
- return rb_find_object_id(obj, nonspecial_obj_id);
+ return rb_find_object_id(NULL, obj, nonspecial_obj_id);
}
/*
@@ -4630,58 +2303,84 @@ rb_memory_id(VALUE obj)
VALUE
rb_obj_id(VALUE obj)
{
- /*
- * 32-bit VALUE space
- * MSB ------------------------ LSB
- * false 00000000000000000000000000000000
- * true 00000000000000000000000000000010
- * nil 00000000000000000000000000000100
- * undef 00000000000000000000000000000110
- * symbol ssssssssssssssssssssssss00001110
- * object oooooooooooooooooooooooooooooo00 = 0 (mod sizeof(RVALUE))
- * fixnum fffffffffffffffffffffffffffffff1
- *
- * object_id space
- * LSB
- * false 00000000000000000000000000000000
- * true 00000000000000000000000000000010
- * nil 00000000000000000000000000000100
- * undef 00000000000000000000000000000110
- * symbol 000SSSSSSSSSSSSSSSSSSSSSSSSSSS0 S...S % A = 4 (S...S = s...s * A + 4)
- * object oooooooooooooooooooooooooooooo0 o...o % A = 0
- * fixnum fffffffffffffffffffffffffffffff1 bignum if required
- *
- * where A = sizeof(RVALUE)/4
- *
- * sizeof(RVALUE) is
- * 20 if 32-bit, double is 4-byte aligned
- * 24 if 32-bit, double is 8-byte aligned
- * 40 if 64-bit
- */
+ /* If obj is an immediate, the object ID is obj directly converted to a Numeric.
+ * Otherwise, the object ID is a Numeric that is a non-zero multiple of
+ * (RUBY_IMMEDIATE_MASK + 1) which guarantees that it does not collide with
+ * any immediates. */
+ return rb_find_object_id(rb_gc_get_objspace(), obj, object_id);
+}
- return rb_find_object_id(obj, cached_object_id);
+bool
+rb_obj_id_p(VALUE obj)
+{
+ return !RB_TYPE_P(obj, T_IMEMO) && rb_shape_obj_has_id(obj);
}
-static enum rb_id_table_iterator_result
-cc_table_memsize_i(VALUE ccs_ptr, void *data_ptr)
+/*
+ * GC implementations should call this function before the GC phase that updates references
+ * embedded in the machine code generated by JIT compilers. JIT compilers usually enforce the
+ * "W^X" policy and protect the code memory from being modified during execution. This function
+ * makes the code memory writeable.
+ */
+void
+rb_gc_before_updating_jit_code(void)
{
- 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;
+#if USE_YJIT
+ rb_yjit_mark_all_writeable();
+#endif
}
-static size_t
-cc_table_memsize(struct rb_id_table *cc_table)
+/*
+ * GC implementations should call this function before the GC phase that updates references
+ * embedded in the machine code generated by JIT compilers. This function makes the code memory
+ * executable again.
+ */
+void
+rb_gc_after_updating_jit_code(void)
{
- size_t total = rb_id_table_memsize(cc_table);
- rb_id_table_foreach_values(cc_table, cc_table_memsize_i, &total);
- return total;
+#if USE_YJIT
+ rb_yjit_mark_all_executable();
+#endif
}
-static size_t
-obj_memsize_of(VALUE obj, int use_all_types)
+static void
+classext_memsize(rb_classext_t *ext, bool prime, VALUE box_value, void *arg)
+{
+ size_t *size = (size_t *)arg;
+ size_t s = 0;
+
+ if (RCLASSEXT_M_TBL(ext)) {
+ s += rb_id_table_memsize(RCLASSEXT_M_TBL(ext));
+ }
+ if (RCLASSEXT_CVC_TBL(ext)) {
+ s += rb_id_table_memsize(RCLASSEXT_CVC_TBL(ext));
+ }
+ if (RCLASSEXT_CONST_TBL(ext)) {
+ s += rb_id_table_memsize(RCLASSEXT_CONST_TBL(ext));
+ }
+ if (RCLASSEXT_SUPERCLASSES_WITH_SELF(ext)) {
+ s += (RCLASSEXT_SUPERCLASS_DEPTH(ext) + 1) * sizeof(VALUE);
+ }
+ if (!prime) {
+ s += sizeof(rb_classext_t);
+ }
+ *size += s;
+}
+
+static void
+classext_superclasses_memsize(rb_classext_t *ext, bool prime, VALUE box_value, void *arg)
+{
+ size_t *size = (size_t *)arg;
+ size_t array_size;
+ if (RCLASSEXT_SUPERCLASSES_WITH_SELF(ext)) {
+ RUBY_ASSERT(prime);
+ array_size = RCLASSEXT_SUPERCLASS_DEPTH(ext) + 1;
+ *size += array_size * sizeof(VALUE);
+ }
+}
+
+size_t
+rb_obj_memsize_of(VALUE obj)
{
size_t size = 0;
@@ -4689,38 +2388,21 @@ obj_memsize_of(VALUE obj, int use_all_types)
return 0;
}
- if (FL_TEST(obj, FL_EXIVAR)) {
- size += rb_generic_ivar_memsize(obj);
- }
-
switch (BUILTIN_TYPE(obj)) {
case T_OBJECT:
- if (rb_shape_obj_too_complex(obj)) {
- size += rb_st_memsize(ROBJECT_IV_HASH(obj));
- }
- else if (!(RBASIC(obj)->flags & ROBJECT_EMBED)) {
- size += ROBJECT_IV_CAPACITY(obj) * sizeof(VALUE);
+ if (FL_TEST_RAW(obj, ROBJECT_HEAP)) {
+ if (rb_shape_obj_too_complex_p(obj)) {
+ size += rb_st_memsize(ROBJECT_FIELDS_HASH(obj));
+ }
+ else {
+ size += ROBJECT_FIELDS_CAPACITY(obj) * sizeof(VALUE);
+ }
}
break;
case T_MODULE:
case T_CLASS:
- if (RCLASS_M_TBL(obj)) {
- size += rb_id_table_memsize(RCLASS_M_TBL(obj));
- }
- // class IV sizes are allocated as powers of two
- size += SIZEOF_VALUE << bit_length(RCLASS_IV_COUNT(obj));
- if (RCLASS_CVC_TBL(obj)) {
- size += rb_id_table_memsize(RCLASS_CVC_TBL(obj));
- }
- 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 (FL_TEST_RAW(obj, RCLASS_SUPERCLASSES_INCLUDE_SELF)) {
- size += (RCLASS_SUPERCLASS_DEPTH(obj) + 1) * sizeof(VALUE);
- }
+ rb_class_classext_foreach(obj, classext_memsize, (void *)&size);
+ rb_class_classext_foreach(obj, classext_superclasses_memsize, (void *)&size);
break;
case T_ICLASS:
if (RICLASS_OWNS_M_TBL_P(obj)) {
@@ -4728,9 +2410,6 @@ obj_memsize_of(VALUE obj, int use_all_types)
size += rb_id_table_memsize(RCLASS_M_TBL(obj));
}
}
- if (RCLASS_CC_TBL(obj)) {
- size += cc_table_memsize(RCLASS_CC_TBL(obj));
- }
break;
case T_STRING:
size += rb_str_memsize(obj);
@@ -4751,7 +2430,7 @@ obj_memsize_of(VALUE obj, int use_all_types)
}
break;
case T_DATA:
- if (use_all_types) size += rb_objspace_data_type_memsize(obj);
+ size += rb_objspace_data_type_memsize(obj);
break;
case T_MATCH:
{
@@ -4787,9 +2466,8 @@ obj_memsize_of(VALUE obj, int use_all_types)
break;
case T_STRUCT:
- if ((RBASIC(obj)->flags & RSTRUCT_EMBED_LEN_MASK) == 0 &&
- RSTRUCT(obj)->as.heap.ptr) {
- size += sizeof(VALUE) * RSTRUCT_LEN(obj);
+ if (RSTRUCT_EMBED_LEN(obj) == 0) {
+ size += sizeof(VALUE) * RSTRUCT_LEN_RAW(obj);
}
break;
@@ -4805,12 +2483,6 @@ obj_memsize_of(VALUE obj, int use_all_types)
return size + rb_gc_obj_slot_size(obj);
}
-size_t
-rb_obj_memsize_of(VALUE obj)
-{
- return obj_memsize_of(obj, TRUE);
-}
-
static int
set_zero(st_data_t key, st_data_t val, st_data_t arg)
{
@@ -4820,43 +2492,6 @@ set_zero(st_data_t key, st_data_t val, st_data_t arg)
return ST_CONTINUE;
}
-static VALUE
-type_sym(size_t type)
-{
- switch (type) {
-#define COUNT_TYPE(t) case (t): return ID2SYM(rb_intern(#t)); break;
- COUNT_TYPE(T_NONE);
- COUNT_TYPE(T_OBJECT);
- COUNT_TYPE(T_CLASS);
- COUNT_TYPE(T_MODULE);
- COUNT_TYPE(T_FLOAT);
- COUNT_TYPE(T_STRING);
- COUNT_TYPE(T_REGEXP);
- COUNT_TYPE(T_ARRAY);
- COUNT_TYPE(T_HASH);
- COUNT_TYPE(T_STRUCT);
- COUNT_TYPE(T_BIGNUM);
- COUNT_TYPE(T_FILE);
- COUNT_TYPE(T_DATA);
- COUNT_TYPE(T_MATCH);
- COUNT_TYPE(T_COMPLEX);
- COUNT_TYPE(T_RATIONAL);
- COUNT_TYPE(T_NIL);
- COUNT_TYPE(T_TRUE);
- COUNT_TYPE(T_FALSE);
- COUNT_TYPE(T_SYMBOL);
- COUNT_TYPE(T_FIXNUM);
- COUNT_TYPE(T_IMEMO);
- COUNT_TYPE(T_UNDEF);
- COUNT_TYPE(T_NODE);
- COUNT_TYPE(T_ICLASS);
- COUNT_TYPE(T_ZOMBIE);
- COUNT_TYPE(T_MOVED);
-#undef COUNT_TYPE
- default: return SIZET2NUM(type); break;
- }
-}
-
struct count_objects_data {
size_t counts[T_MASK+1];
size_t freed;
@@ -4868,7 +2503,7 @@ count_objects_i(VALUE obj, void *d)
{
struct count_objects_data *data = (struct count_objects_data *)d;
- if (RANY(obj)->as.basic.flags) {
+ if (RBASIC(obj)->flags) {
data->counts[BUILTIN_TYPE(obj)]++;
}
else {
@@ -4916,9 +2551,9 @@ count_objects_i(VALUE obj, void *d)
static VALUE
count_objects(int argc, VALUE *argv, VALUE os)
{
- rb_objspace_t *objspace = &rb_objspace;
struct count_objects_data data = { 0 };
VALUE hash = Qnil;
+ VALUE types[T_MASK + 1];
if (rb_check_arity(argc, 0, 1) == 1) {
hash = argv[0];
@@ -4926,7 +2561,18 @@ count_objects(int argc, VALUE *argv, VALUE os)
rb_raise(rb_eTypeError, "non-hash given");
}
- gc_each_object(objspace, count_objects_i, &data);
+ for (size_t i = 0; i <= T_MASK; i++) {
+ // type_sym can allocate an object,
+ // so we need to create all key symbols in advance
+ // not to disturb the result
+ types[i] = type_sym(i);
+ }
+
+ // Same as type_sym, we need to create all key symbols in advance
+ VALUE total = ID2SYM(rb_intern("TOTAL"));
+ VALUE free = ID2SYM(rb_intern("FREE"));
+
+ rb_gc_impl_each_object(rb_gc_get_objspace(), count_objects_i, &data);
if (NIL_P(hash)) {
hash = rb_hash_new();
@@ -4934,1190 +2580,18 @@ count_objects(int argc, VALUE *argv, VALUE os)
else if (!RHASH_EMPTY_P(hash)) {
rb_hash_stlike_foreach(hash, set_zero, hash);
}
- rb_hash_aset(hash, ID2SYM(rb_intern("TOTAL")), SIZET2NUM(data.total));
- rb_hash_aset(hash, ID2SYM(rb_intern("FREE")), SIZET2NUM(data.freed));
+ rb_hash_aset(hash, total, SIZET2NUM(data.total));
+ rb_hash_aset(hash, free, SIZET2NUM(data.freed));
for (size_t i = 0; i <= T_MASK; i++) {
- VALUE type = type_sym(i);
- if (data.counts[i])
- rb_hash_aset(hash, type, SIZET2NUM(data.counts[i]));
- }
-
- return hash;
-}
-
-/*
- ------------------------ 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 total_allocated_objects(objspace) - total_freed_objects(objspace) - 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 src_slot_size, size_t slot_size);
-
-#if defined(_WIN32)
-enum {HEAP_PAGE_LOCK = PAGE_NOACCESS, HEAP_PAGE_UNLOCK = PAGE_READWRITE};
-
-static BOOL
-protect_page_body(struct heap_page_body *body, DWORD protect)
-{
- DWORD old_protect;
- return VirtualProtect(body, HEAP_PAGE_SIZE, protect, &old_protect) != 0;
-}
-#else
-enum {HEAP_PAGE_LOCK = PROT_NONE, HEAP_PAGE_UNLOCK = PROT_READ | PROT_WRITE};
-#define protect_page_body(body, protect) !mprotect((body), HEAP_PAGE_SIZE, (protect))
-#endif
-
-static void
-lock_page_body(rb_objspace_t *objspace, struct heap_page_body *body)
-{
- if (!protect_page_body(body, HEAP_PAGE_LOCK)) {
- 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 (!protect_page_body(body, HEAP_PAGE_UNLOCK)) {
- 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 bool
-try_move(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *free_page, VALUE src)
-{
- GC_ASSERT(gc_is_moveable_obj(objspace, src));
-
- struct heap_page *src_page = GET_HEAP_PAGE(src);
- if (!free_page) {
- return false;
- }
-
- /* We should return true if either src is successfully moved, or src is
- * unmoveable. A false return will cause the sweeping cursor to be
- * incremented to the next page, and src will attempt to move again */
- GC_ASSERT(MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(src), src));
-
- asan_unlock_freelist(free_page);
- VALUE dest = (VALUE)free_page->freelist;
- asan_lock_freelist(free_page);
- asan_unpoison_object(dest, false);
- if (!dest) {
- /* if we can't get something from the freelist then the page must be
- * full */
- return false;
- }
- asan_unlock_freelist(free_page);
- free_page->freelist = RANY(dest)->as.free.next;
- asan_lock_freelist(free_page);
-
- GC_ASSERT(RB_BUILTIN_TYPE(dest) == T_NONE);
-
- if (src_page->slot_size > free_page->slot_size) {
- objspace->rcompactor.moved_down_count_table[BUILTIN_TYPE(src)]++;
- }
- else if (free_page->slot_size > src_page->slot_size) {
- objspace->rcompactor.moved_up_count_table[BUILTIN_TYPE(src)]++;
- }
- objspace->rcompactor.moved_count_table[BUILTIN_TYPE(src)]++;
- objspace->rcompactor.total_moved++;
-
- gc_move(objspace, src, dest, src_page->slot_size, free_page->slot_size);
- gc_pin(objspace, src);
- free_page->free_slots--;
-
- return true;
-}
-
-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 = ccan_list_next(&heap->pages, cursor, page_node);
- }
-}
-
-static void gc_update_references(rb_objspace_t * objspace);
-#if GC_CAN_COMPILE_COMPACTION
-static void invalidate_moved_page(rb_objspace_t *objspace, struct heap_page *page);
-#endif
-
-#if defined(__MINGW32__) || defined(_WIN32)
-# define GC_COMPACTION_SUPPORTED 1
-#else
-/* If not MinGW, Windows, or does not have mmap, we cannot use mprotect for
- * the read barrier, so we must disable compaction. */
-# define GC_COMPACTION_SUPPORTED (GC_CAN_COMPILE_COMPACTION && HEAP_PAGE_ALLOC_USE_MMAP)
-#endif
-
-#if GC_CAN_COMPILE_COMPACTION
-static void
-read_barrier_handler(uintptr_t original_address)
-{
- VALUE obj;
- rb_objspace_t * objspace = &rb_objspace;
-
- /* Calculate address aligned to slots. */
- uintptr_t address = original_address - (original_address % BASE_SLOT_SIZE);
-
- obj = (VALUE)address;
-
- struct heap_page_body *page_body = GET_PAGE_BODY(obj);
-
- /* If the page_body is NULL, then mprotect cannot handle it and will crash
- * with "Cannot allocate memory". */
- if (page_body == NULL) {
- rb_bug("read_barrier_handler: segmentation fault at %p", (void *)original_address);
- }
-
- RB_VM_LOCK_ENTER();
- {
- unlock_page_body(objspace, page_body);
-
- objspace->profile.read_barrier_faults++;
-
- invalidate_moved_page(objspace, GET_HEAP_PAGE(obj));
- }
- RB_VM_LOCK_LEAVE();
-}
-#endif
-
-#if !GC_CAN_COMPILE_COMPACTION
-static void
-uninstall_handlers(void)
-{
- /* no-op */
-}
-
-static void
-install_handlers(void)
-{
- /* no-op */
-}
-#elif 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;
-
-#ifdef HAVE_MACH_TASK_EXCEPTION_PORTS
-static exception_mask_t old_exception_masks[32];
-static mach_port_t old_exception_ports[32];
-static exception_behavior_t old_exception_behaviors[32];
-static thread_state_flavor_t old_exception_flavors[32];
-static mach_msg_type_number_t old_exception_count;
-
-static void
-disable_mach_bad_access_exc(void)
-{
- old_exception_count = sizeof(old_exception_masks) / sizeof(old_exception_masks[0]);
- task_swap_exception_ports(
- mach_task_self(), EXC_MASK_BAD_ACCESS,
- MACH_PORT_NULL, EXCEPTION_DEFAULT, 0,
- old_exception_masks, &old_exception_count,
- old_exception_ports, old_exception_behaviors, old_exception_flavors
- );
-}
-
-static void
-restore_mach_bad_access_exc(void)
-{
- for (mach_msg_type_number_t i = 0; i < old_exception_count; i++) {
- task_set_exception_ports(
- mach_task_self(),
- old_exception_masks[i], old_exception_ports[i],
- old_exception_behaviors[i], old_exception_flavors[i]
- );
- }
-}
-#endif
-
-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);
-#ifdef HAVE_MACH_TASK_EXCEPTION_PORTS
- disable_mach_bad_access_exc();
-#endif
- // run handler
- read_barrier_handler((uintptr_t)info->si_addr);
-
- // reset SEGV/BUS handlers
-#ifdef HAVE_MACH_TASK_EXCEPTION_PORTS
- restore_mach_bad_access_exc();
-#endif
- sigaction(SIGBUS, &prev_sigbus, NULL);
- sigaction(SIGSEGV, &prev_sigsegv, NULL);
- sigprocmask(SIG_SETMASK, &prev_set, NULL);
-}
-
-static void
-uninstall_handlers(void)
-{
-#ifdef HAVE_MACH_TASK_EXCEPTION_PORTS
- restore_mach_bad_access_exc();
-#endif
- 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);
-#ifdef HAVE_MACH_TASK_EXCEPTION_PORTS
- disable_mach_bad_access_exc();
-#endif
-}
-#endif
-
-static void
-gc_compact_finish(rb_objspace_t *objspace)
-{
- 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();
-
- 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->free_pages = 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_sweep_plane(rb_objspace_t *objspace, rb_heap_t *heap, uintptr_t p, bits_t bitset, struct gc_sweep_context *ctx)
-{
- struct heap_page * sweep_page = ctx->page;
- short slot_size = sweep_page->slot_size;
- short slot_bits = slot_size / BASE_SLOT_SIZE;
- GC_ASSERT(slot_bits > 0);
-
- do {
- VALUE vp = (VALUE)p;
- GC_ASSERT(vp % BASE_SLOT_SIZE == 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 (RVALUE_REMEMBERED(vp)) rb_bug("page_sweep: %p - remembered.", (void *)p);
- }
-#endif
- if (obj_free(objspace, vp)) {
- // always add free slots back to the swept pages freelist,
- // so that if we're comapacting, we can re-use the slots
- (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, BASE_SLOT_SIZE);
- 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");
- }
- gc_report(3, objspace, "page_sweep: %s is added to freelist\n", obj_info(vp));
- ctx->empty_slots++;
- heap_page_add_freeobj(objspace, sweep_page, vp);
- break;
- case T_ZOMBIE:
- /* already counted */
- break;
- case T_NONE:
- ctx->empty_slots++; /* already freed */
- break;
- }
- }
- p += slot_size;
- bitset >>= slot_bits;
- } while (bitset);
-}
-
-static inline void
-gc_sweep_page(rb_objspace_t *objspace, rb_heap_t *heap, struct gc_sweep_context *ctx)
-{
- struct heap_page *sweep_page = ctx->page;
- GC_ASSERT(SIZE_POOL_EDEN_HEAP(sweep_page->size_pool) == heap);
-
- uintptr_t p;
- bits_t *bits, bitset;
-
- gc_report(2, objspace, "page_sweep: start.\n");
-
-#if RGENGC_CHECK_MODE
- if (!objspace->flags.immediate_sweep) {
- GC_ASSERT(sweep_page->flags.before_sweep == TRUE);
- }
-#endif
- sweep_page->flags.before_sweep = FALSE;
- sweep_page->free_slots = 0;
-
- p = (uintptr_t)sweep_page->start;
- bits = sweep_page->mark_bits;
-
- int page_rvalue_count = sweep_page->total_slots * (sweep_page->slot_size / BASE_SLOT_SIZE);
- 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);
- }
-
- /* The last bitmap plane may not be used if the last plane does not
- * have enough space for the slot_size. In that case, the last plane must
- * be skipped since none of the bits will be set. */
- int bitmap_plane_count = CEILDIV(NUM_IN_PAGE(p) + page_rvalue_count, BITS_BITLENGTH);
- GC_ASSERT(bitmap_plane_count == HEAP_PAGE_BITMAP_LIMIT - 1 ||
- bitmap_plane_count == HEAP_PAGE_BITMAP_LIMIT);
-
- // 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, p, bitset, ctx);
- }
- p += (BITS_BITLENGTH - NUM_IN_PAGE(p)) * BASE_SLOT_SIZE;
-
- for (int i = 1; i < bitmap_plane_count; i++) {
- bitset = ~bits[i];
- if (bitset) {
- gc_sweep_plane(objspace, heap, p, bitset, ctx);
- }
- p += BITS_BITLENGTH * BASE_SLOT_SIZE;
- }
-
- 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 += ctx->final_slots + ctx->freed_slots;
- record->empty_objects += ctx->empty_slots;
- }
-#endif
- 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 += ctx->freed_slots + ctx->empty_slots;
- sweep_page->size_pool->total_freed_objects += ctx->freed_slots;
-
- if (heap_pages_deferred_final && !finalizing) {
- gc_finalize_deferred_register(objspace);
- }
-
-#if RGENGC_CHECK_MODE
- short freelist_len = 0;
- asan_unlock_freelist(sweep_page);
- RVALUE *ptr = sweep_page->freelist;
- while (ptr) {
- freelist_len++;
- ptr = ptr->as.free.next;
- }
- asan_lock_freelist(sweep_page);
- if (freelist_len != sweep_page->free_slots) {
- rb_bug("inconsistent freelist length: expected %d but was %d", sweep_page->free_slots, freelist_len);
- }
-#endif
-
- gc_report(2, objspace, "page_sweep: end.\n");
-}
-
-static const char *
-gc_mode_name(enum gc_mode mode)
-{
- switch (mode) {
- case gc_mode_none: return "none";
- case gc_mode_marking: return "marking";
- case gc_mode_sweeping: return "sweeping";
- case gc_mode_compacting: return "compacting";
- default: rb_bug("gc_mode_name: unknown mode: %d", (int)mode);
- }
-}
-
-static void
-gc_mode_transition(rb_objspace_t *objspace, enum gc_mode mode)
-{
-#if RGENGC_CHECK_MODE
- enum gc_mode prev_mode = gc_mode(objspace);
- switch (prev_mode) {
- case gc_mode_none: GC_ASSERT(mode == gc_mode_marking); break;
- case gc_mode_marking: GC_ASSERT(mode == gc_mode_sweeping); break;
- case gc_mode_sweeping: GC_ASSERT(mode == gc_mode_none || mode == gc_mode_compacting); break;
- case gc_mode_compacting: GC_ASSERT(mode == gc_mode_none); break;
- }
-#endif
- if (0) fprintf(stderr, "gc_mode_transition: %s->%s\n", gc_mode_name(gc_mode(objspace)), gc_mode_name(mode));
- gc_mode_set(objspace, mode);
-}
-
-static void
-heap_page_freelist_append(struct heap_page *page, RVALUE *freelist)
-{
- if (freelist) {
- asan_unlock_freelist(page);
- 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_lock_freelist(page);
- }
-}
-
-static void
-gc_sweep_start_heap(rb_objspace_t *objspace, rb_heap_t *heap)
-{
- heap->sweeping_page = ccan_list_top(&heap->pages, struct heap_page, page_node);
- heap->free_pages = NULL;
- heap->pooled_pages = NULL;
- if (!objspace->flags.immediate_sweep) {
- struct heap_page *page = NULL;
-
- ccan_list_for_each(&heap->pages, page, page_node) {
- page->flags.before_sweep = TRUE;
- }
- }
-}
-
-#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 4
-__attribute__((noinline))
-#endif
-
-#if GC_CAN_COMPILE_COMPACTION
-static void gc_sort_heap_by_compare_func(rb_objspace_t *objspace, gc_compact_compare_func compare_func);
-static int compare_pinned_slots(const void *left, const void *right, void *d);
-#endif
-
-static void
-gc_sweep_start(rb_objspace_t *objspace)
-{
- gc_mode_transition(objspace, gc_mode_sweeping);
- objspace->rincgc.pooled_slots = 0;
-
-#if GC_CAN_COMPILE_COMPACTION
- if (objspace->flags.during_compacting) {
- gc_sort_heap_by_compare_func(
- objspace,
- objspace->rcompactor.compare_func ? objspace->rcompactor.compare_func : compare_pinned_slots
- );
- }
-#endif
-
- 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_sweep_start_heap(objspace, heap);
-
- /* We should call gc_sweep_finish_size_pool for size pools with no pages. */
- if (heap->sweeping_page == NULL) {
- GC_ASSERT(heap->total_pages == 0);
- GC_ASSERT(heap->total_slots == 0);
- gc_sweep_finish_size_pool(objspace, size_pool);
- }
- }
-
- rb_ractor_t *r = NULL;
- ccan_list_for_each(&GET_VM()->ractor.set, r, vmlr_node) {
- rb_gc_ractor_newobj_cache_clear(&r->newobj_cache);
- }
-}
-
-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 init_slots = gc_params.size_pool_init_slots[size_pool - size_pools];
- size_t min_free_slots = (size_t)(MAX(total_slots, init_slots) * gc_params.heap_free_slots_min_ratio);
-
- /* If we don't have enough slots and we have pages on the tomb heap, move
- * pages from the tomb heap to the eden heap. This may prevent page
- * creation thrashing (frequently allocating and deallocting pages) and
- * GC thrashing (running GC more frequently than required). */
- struct heap_page *resurrected_page;
- while (swept_slots < min_free_slots &&
- (resurrected_page = heap_page_resurrect(objspace, size_pool))) {
- swept_slots += resurrected_page->free_slots;
-
- heap_add_page(objspace, size_pool, heap, resurrected_page);
- heap_add_freepage(heap, resurrected_page);
- }
-
- if (swept_slots < min_free_slots) {
- bool grow_heap = is_full_marking(objspace);
-
- /* Consider growing or starting a major GC if we are not currently in a
- * major GC and we can't allocate any more pages. */
- if (!is_full_marking(objspace) && size_pool->allocatable_pages == 0) {
- /* 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;
-
- /* Grow this heap if we haven't run at least RVALUE_OLD_AGE minor
- * GC since the last major GC or if this heap is smaller than the
- * the configured initial size. */
- if (objspace->profile.count - objspace->rgengc.last_major_gc < RVALUE_OLD_AGE ||
- total_slots < init_slots) {
- grow_heap = TRUE;
- }
- else if (is_growth_heap) { /* Only growth heaps are allowed to start a major GC. */
- gc_needs_major_flags |= GPR_FLAG_MAJOR_BY_NOFREE;
- size_pool->force_major_gc_count++;
- }
- }
-
- if (grow_heap) {
- size_t extend_page_count = heap_extend_pages(objspace, size_pool, 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);
- }
- }
- }
-}
-
-static void
-gc_sweep_finish(rb_objspace_t *objspace)
-{
- gc_report(1, objspace, "gc_sweep_finish\n");
-
- gc_prof_set_heap_info(objspace);
- heap_pages_free_unused_pages(objspace);
-
- 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;
- }
-
- size_pool->freed_slots = 0;
- size_pool->empty_slots = 0;
-
- 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;
- }
- }
- heap_pages_expand_sorted(objspace);
-
- gc_event_hook(objspace, RUBY_INTERNAL_EVENT_GC_END_SWEEP, 0);
- gc_mode_transition(objspace, gc_mode_none);
-
-#if RGENGC_CHECK_MODE >= 2
- gc_verify_internal_consistency(objspace);
-#endif
-}
-
-static int
-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 = GC_SWEEP_PAGES_FREEABLE_PER_STEP;
- int swept_slots = 0;
- int pooled_slots = 0;
-
- if (sweep_page == NULL) return FALSE;
-
-#if GC_ENABLE_LAZY_SWEEP
- gc_prof_sweep_timer_start(objspace);
-#endif
-
- do {
- 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, heap, &ctx);
- int free_slots = ctx.freed_slots + ctx.empty_slots;
-
- heap->sweeping_page = ccan_list_next(&heap->pages, sweep_page, page_node);
-
- if (sweep_page->final_slots + free_slots == sweep_page->total_slots &&
- heap_pages_freeable_pages > 0 &&
- unlink_limit > 0) {
- heap_pages_freeable_pages--;
- unlink_limit--;
- /* there are no living objects -> move this page to tomb heap */
- heap_unlink_page(objspace, heap, sweep_page);
- heap_add_page(objspace, size_pool, SIZE_POOL_TOMB_HEAP(size_pool), sweep_page);
- }
- else if (free_slots > 0) {
- size_pool->freed_slots += ctx.freed_slots;
- size_pool->empty_slots += ctx.empty_slots;
-
- if (pooled_slots < GC_INCREMENTAL_SWEEP_POOL_SLOT_COUNT) {
- heap_add_poolpage(objspace, heap, sweep_page);
- pooled_slots += free_slots;
- }
- else {
- heap_add_freepage(heap, sweep_page);
- swept_slots += free_slots;
- if (swept_slots > GC_INCREMENTAL_SWEEP_SLOT_COUNT) {
- break;
- }
- }
- }
- else {
- sweep_page->free_next = NULL;
- }
- } while ((sweep_page = heap->sweeping_page));
-
- if (!heap->sweeping_page) {
- gc_sweep_finish_size_pool(objspace, size_pool);
-
- if (!has_sweeping_pages(objspace)) {
- gc_sweep_finish(objspace);
- }
- }
-
-#if GC_ENABLE_LAZY_SWEEP
- gc_prof_sweep_timer_stop(objspace);
-#endif
-
- return heap->free_pages != NULL;
-}
-
-static void
-gc_sweep_rest(rb_objspace_t *objspace)
-{
- for (int i = 0; i < SIZE_POOL_COUNT; i++) {
- rb_size_pool_t *size_pool = &size_pools[i];
-
- 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_size_pool_t *sweep_size_pool, rb_heap_t *heap)
-{
- GC_ASSERT(dont_gc_val() == FALSE);
- if (!GC_ENABLE_LAZY_SWEEP) return;
-
- gc_sweeping_enter(objspace);
-
- 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))) {
- /* 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;
- }
- }
+ if (data.counts[i]) {
+ rb_hash_aset(hash, types[i], SIZET2NUM(data.counts[i]));
}
}
- gc_sweeping_exit(objspace);
-}
-
-#if GC_CAN_COMPILE_COMPACTION
-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);
-
- object = rb_gc_location(forwarding_object);
-
- shape_id_t original_shape_id = 0;
- if (RB_TYPE_P(object, T_OBJECT)) {
- original_shape_id = RMOVED(forwarding_object)->original_shape_id;
- }
-
- gc_move(objspace, object, forwarding_object, GET_HEAP_PAGE(object)->slot_size, page->slot_size);
- /* forwarding_object is now our actual object, and "object"
- * is the free slot for the original page */
-
- if (original_shape_id) {
- ROBJECT_SET_SHAPE_ID(forwarding_object, original_shape_id);
- }
-
- struct heap_page *orig_page = GET_HEAP_PAGE(object);
- orig_page->free_slots++;
- 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 += BASE_SLOT_SIZE;
- 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;
-
- mark_bits = page->mark_bits;
- pin_bits = page->pinned_bits;
-
- uintptr_t 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, p, bitset);
- p += (BITS_BITLENGTH - NUM_IN_PAGE(p)) * BASE_SLOT_SIZE;
-
- 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, p, bitset);
- p += BITS_BITLENGTH * BASE_SLOT_SIZE;
- }
-}
-#endif
-
-static void
-gc_compact_start(rb_objspace_t *objspace)
-{
- struct heap_page *page = NULL;
- gc_mode_transition(objspace, gc_mode_compacting);
-
- for (int i = 0; i < SIZE_POOL_COUNT; i++) {
- rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(&size_pools[i]);
- ccan_list_for_each(&heap->pages, page, page_node) {
- page->flags.before_sweep = TRUE;
- }
-
- heap->compact_cursor = ccan_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));
- memset(objspace->rcompactor.moved_up_count_table, 0, T_MASK * sizeof(size_t));
- memset(objspace->rcompactor.moved_down_count_table, 0, T_MASK * sizeof(size_t));
-
- /* Set up read barrier for pages containing MOVED objects */
- install_handlers();
-}
-
-static void gc_sweep_compact(rb_objspace_t *objspace);
-
-static void
-gc_sweep(rb_objspace_t *objspace)
-{
- gc_sweeping_enter(objspace);
-
- const unsigned int immediate_sweep = objspace->flags.immediate_sweep;
-
- gc_report(1, objspace, "gc_sweep: immediate: %d\n", immediate_sweep);
-
- gc_sweep_start(objspace);
- if (objspace->flags.during_compacting) {
- gc_sweep_compact(objspace);
- }
-
- if (immediate_sweep) {
-#if !GC_ENABLE_LAZY_SWEEP
- gc_prof_sweep_timer_start(objspace);
-#endif
- gc_sweep_rest(objspace);
-#if !GC_ENABLE_LAZY_SWEEP
- gc_prof_sweep_timer_stop(objspace);
-#endif
- }
- else {
-
- /* 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_sweeping_exit(objspace);
-}
-
-/* Marking - Marking stack */
-
-static stack_chunk_t *
-stack_chunk_alloc(void)
-{
- stack_chunk_t *res;
-
- res = malloc(sizeof(stack_chunk_t));
- if (!res)
- rb_memerror();
-
- return res;
-}
-
-static inline int
-is_mark_stack_empty(mark_stack_t *stack)
-{
- return stack->chunk == NULL;
-}
-
-static size_t
-mark_stack_size(mark_stack_t *stack)
-{
- size_t size = stack->index;
- stack_chunk_t *chunk = stack->chunk ? stack->chunk->next : NULL;
-
- while (chunk) {
- size += stack->limit;
- chunk = chunk->next;
- }
- return size;
-}
-
-static void
-add_stack_chunk_cache(mark_stack_t *stack, stack_chunk_t *chunk)
-{
- chunk->next = stack->cache;
- stack->cache = chunk;
- stack->cache_size++;
-}
-
-static void
-shrink_stack_chunk_cache(mark_stack_t *stack)
-{
- stack_chunk_t *chunk;
-
- if (stack->unused_cache_size > (stack->cache_size/2)) {
- chunk = stack->cache;
- stack->cache = stack->cache->next;
- stack->cache_size--;
- free(chunk);
- }
- stack->unused_cache_size = stack->cache_size;
-}
-
-static void
-push_mark_stack_chunk(mark_stack_t *stack)
-{
- stack_chunk_t *next;
-
- GC_ASSERT(stack->index == stack->limit);
-
- if (stack->cache_size > 0) {
- next = stack->cache;
- stack->cache = stack->cache->next;
- stack->cache_size--;
- if (stack->unused_cache_size > stack->cache_size)
- stack->unused_cache_size = stack->cache_size;
- }
- else {
- next = stack_chunk_alloc();
- }
- next->next = stack->chunk;
- stack->chunk = next;
- stack->index = 0;
-}
-
-static void
-pop_mark_stack_chunk(mark_stack_t *stack)
-{
- stack_chunk_t *prev;
-
- prev = stack->chunk->next;
- GC_ASSERT(stack->index == 0);
- add_stack_chunk_cache(stack, stack->chunk);
- stack->chunk = prev;
- stack->index = stack->limit;
-}
-
-static void
-mark_stack_chunk_list_free(stack_chunk_t *chunk)
-{
- stack_chunk_t *next = NULL;
-
- while (chunk != NULL) {
- next = chunk->next;
- free(chunk);
- chunk = next;
- }
-}
-
-static void
-free_stack_chunks(mark_stack_t *stack)
-{
- mark_stack_chunk_list_free(stack->chunk);
-}
-
-static void
-mark_stack_free_cache(mark_stack_t *stack)
-{
- mark_stack_chunk_list_free(stack->cache);
- stack->cache_size = 0;
- stack->unused_cache_size = 0;
-}
-
-static void
-push_mark_stack(mark_stack_t *stack, VALUE obj)
-{
- 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++] = obj;
- 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;
- }
-
- rb_bug("rb_gc_mark(): unknown data type 0x%x(%p) %s",
- BUILTIN_TYPE(obj), (void *)obj,
- is_pointer_to_heap(&rb_objspace, (void *)obj) ? "corrupted object" : "non object");
-}
-
-static int
-pop_mark_stack(mark_stack_t *stack, VALUE *data)
-{
- if (is_mark_stack_empty(stack)) {
- return FALSE;
- }
- if (stack->index == 1) {
- *data = stack->chunk->data[--stack->index];
- pop_mark_stack_chunk(stack);
- }
- else {
- *data = stack->chunk->data[--stack->index];
- }
- return TRUE;
-}
-
-static void
-init_mark_stack(mark_stack_t *stack)
-{
- int i;
-
- MEMZERO(stack, mark_stack_t, 1);
- stack->index = stack->limit = STACK_CHUNK_SIZE;
-
- for (i=0; i < 4; i++) {
- add_stack_chunk_cache(stack, stack_chunk_alloc());
- }
- stack->unused_cache_size = stack->cache_size;
+ return hash;
}
-/* Marking */
-
#define SET_STACK_END SET_MACHINE_STACK_END(&ec->machine.stack_end)
#define STACK_START (ec->machine.stack_start)
@@ -6191,188 +2665,192 @@ ruby_stack_check(void)
return stack_check(GET_EC(), STACKFRAME_FOR_CALL_CFUNC);
}
-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
-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;
- cb(objspace, v);
- x++;
- }
-}
+/* ==================== Marking ==================== */
-static void
-gc_mark_locations(rb_objspace_t *objspace, const VALUE *start, const VALUE *end, void (*cb)(rb_objspace_t *, VALUE))
-{
- long n;
+#define RB_GC_MARK_OR_TRAVERSE(func, obj_or_ptr, obj, check_obj) do { \
+ if (!RB_SPECIAL_CONST_P(obj)) { \
+ rb_vm_t *vm = GET_VM(); \
+ void *objspace = vm->gc.objspace; \
+ if (LIKELY(vm->gc.mark_func_data == NULL)) { \
+ GC_ASSERT(rb_gc_impl_during_gc_p(objspace)); \
+ (func)(objspace, (obj_or_ptr)); \
+ } \
+ else if (check_obj ? \
+ rb_gc_impl_pointer_to_heap_p(objspace, (const void *)obj) && \
+ !rb_gc_impl_garbage_object_p(objspace, obj) : \
+ true) { \
+ GC_ASSERT(!rb_gc_impl_during_gc_p(objspace)); \
+ struct gc_mark_func_data_struct *mark_func_data = vm->gc.mark_func_data; \
+ vm->gc.mark_func_data = NULL; \
+ mark_func_data->mark_func((obj), mark_func_data->data); \
+ vm->gc.mark_func_data = mark_func_data; \
+ } \
+ } \
+} while (0)
- if (end <= start) return;
- n = end - start;
- each_location(objspace, start, n, cb);
+static inline void
+gc_mark_internal(VALUE obj)
+{
+ RB_GC_MARK_OR_TRAVERSE(rb_gc_impl_mark, obj, obj, false);
}
void
-rb_gc_mark_locations(const VALUE *start, const VALUE *end)
+rb_gc_mark_movable(VALUE obj)
{
- gc_mark_locations(&rb_objspace, start, end, gc_mark_maybe);
+ gc_mark_internal(obj);
}
void
-rb_gc_mark_values(long n, const VALUE *values)
+rb_gc_mark_and_move(VALUE *ptr)
{
- long i;
- rb_objspace_t *objspace = &rb_objspace;
+ RB_GC_MARK_OR_TRAVERSE(rb_gc_impl_mark_and_move, ptr, *ptr, false);
+}
- for (i=0; i<n; i++) {
- gc_mark(objspace, values[i]);
- }
+static inline void
+gc_mark_and_pin_internal(VALUE obj)
+{
+ RB_GC_MARK_OR_TRAVERSE(rb_gc_impl_mark_and_pin, obj, obj, false);
}
void
-rb_gc_mark_vm_stack_values(long n, const VALUE *values)
+rb_gc_mark(VALUE obj)
{
- rb_objspace_t *objspace = &rb_objspace;
+ gc_mark_and_pin_internal(obj);
+}
- for (long i = 0; i < n; i++) {
- gc_mark_and_pin(objspace, values[i]);
- }
+static inline void
+gc_mark_maybe_internal(VALUE obj)
+{
+ RB_GC_MARK_OR_TRAVERSE(rb_gc_impl_mark_maybe, obj, obj, true);
}
-static int
-mark_value(st_data_t key, st_data_t value, st_data_t data)
+void
+rb_gc_mark_maybe(VALUE obj)
{
- rb_objspace_t *objspace = (rb_objspace_t *)data;
- gc_mark(objspace, (VALUE)value);
- return ST_CONTINUE;
+ gc_mark_maybe_internal(obj);
}
-static int
-mark_value_pin(st_data_t key, st_data_t value, st_data_t data)
+ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(static void each_location(register const VALUE *x, register long n, void (*cb)(VALUE, void *), void *data));
+static void
+each_location(register const VALUE *x, register long n, void (*cb)(VALUE, void *), void *data)
{
- rb_objspace_t *objspace = (rb_objspace_t *)data;
- gc_mark_and_pin(objspace, (VALUE)value);
- return ST_CONTINUE;
+ VALUE v;
+ while (n--) {
+ v = *x;
+ cb(v, data);
+ x++;
+ }
}
static void
-mark_tbl_no_pin(rb_objspace_t *objspace, st_table *tbl)
+each_location_ptr(const VALUE *start, const VALUE *end, void (*cb)(VALUE, void *), void *data)
{
- if (!tbl || tbl->num_entries == 0) return;
- st_foreach(tbl, mark_value, (st_data_t)objspace);
+ if (end <= start) return;
+ each_location(start, end - start, cb, data);
}
static void
-mark_tbl(rb_objspace_t *objspace, st_table *tbl)
+gc_mark_maybe_each_location(VALUE obj, void *data)
{
- if (!tbl || tbl->num_entries == 0) return;
- st_foreach(tbl, mark_value_pin, (st_data_t)objspace);
+ gc_mark_maybe_internal(obj);
}
-static int
-mark_key(st_data_t key, st_data_t value, st_data_t data)
+void
+rb_gc_mark_locations(const VALUE *start, const VALUE *end)
{
- rb_objspace_t *objspace = (rb_objspace_t *)data;
- gc_mark_and_pin(objspace, (VALUE)key);
- return ST_CONTINUE;
+ each_location_ptr(start, end, gc_mark_maybe_each_location, NULL);
}
-static void
-mark_set(rb_objspace_t *objspace, st_table *tbl)
+void
+rb_gc_mark_values(long n, const VALUE *values)
{
- if (!tbl) return;
- st_foreach(tbl, mark_key, (st_data_t)objspace);
+ for (long i = 0; i < n; i++) {
+ gc_mark_internal(values[i]);
+ }
}
-static int
-pin_value(st_data_t key, st_data_t value, st_data_t data)
+void
+rb_gc_mark_vm_stack_values(long n, const VALUE *values)
{
- rb_objspace_t *objspace = (rb_objspace_t *)data;
- gc_mark_and_pin(objspace, (VALUE)value);
- return ST_CONTINUE;
+ for (long i = 0; i < n; i++) {
+ gc_mark_and_pin_internal(values[i]);
+ }
}
-static void
-mark_finalizer_tbl(rb_objspace_t *objspace, st_table *tbl)
+static int
+mark_key(st_data_t key, st_data_t value, st_data_t data)
{
- if (!tbl) return;
- st_foreach(tbl, pin_value, (st_data_t)objspace);
+ gc_mark_and_pin_internal((VALUE)key);
+
+ return ST_CONTINUE;
}
void
rb_mark_set(st_table *tbl)
{
- mark_set(&rb_objspace, tbl);
+ if (!tbl) return;
+
+ st_foreach(tbl, mark_key, (st_data_t)rb_gc_get_objspace());
}
static int
mark_keyvalue(st_data_t key, st_data_t value, st_data_t data)
{
- rb_objspace_t *objspace = (rb_objspace_t *)data;
+ gc_mark_internal((VALUE)key);
+ gc_mark_internal((VALUE)value);
- gc_mark(objspace, (VALUE)key);
- gc_mark(objspace, (VALUE)value);
return ST_CONTINUE;
}
static int
pin_key_pin_value(st_data_t key, st_data_t value, st_data_t data)
{
- rb_objspace_t *objspace = (rb_objspace_t *)data;
+ gc_mark_and_pin_internal((VALUE)key);
+ gc_mark_and_pin_internal((VALUE)value);
- gc_mark_and_pin(objspace, (VALUE)key);
- gc_mark_and_pin(objspace, (VALUE)value);
return ST_CONTINUE;
}
static int
pin_key_mark_value(st_data_t key, st_data_t value, st_data_t data)
{
- rb_objspace_t *objspace = (rb_objspace_t *)data;
+ gc_mark_and_pin_internal((VALUE)key);
+ gc_mark_internal((VALUE)value);
- gc_mark_and_pin(objspace, (VALUE)key);
- gc_mark(objspace, (VALUE)value);
return ST_CONTINUE;
}
static void
-mark_hash(rb_objspace_t *objspace, VALUE hash)
+mark_hash(VALUE hash)
{
if (rb_hash_compare_by_id_p(hash)) {
- rb_hash_stlike_foreach(hash, pin_key_mark_value, (st_data_t)objspace);
+ rb_hash_stlike_foreach(hash, pin_key_mark_value, 0);
}
else {
- rb_hash_stlike_foreach(hash, mark_keyvalue, (st_data_t)objspace);
+ rb_hash_stlike_foreach(hash, mark_keyvalue, 0);
}
- gc_mark(objspace, RHASH(hash)->ifnone);
-}
-
-static void
-mark_st(rb_objspace_t *objspace, st_table *tbl)
-{
- if (!tbl) return;
- st_foreach(tbl, pin_key_pin_value, (st_data_t)objspace);
+ gc_mark_internal(RHASH(hash)->ifnone);
}
void
rb_mark_hash(st_table *tbl)
{
- mark_st(&rb_objspace, tbl);
+ if (!tbl) return;
+
+ st_foreach(tbl, pin_key_pin_value, 0);
}
static enum rb_id_table_iterator_result
-mark_method_entry_i(VALUE me, void *data)
+mark_method_entry_i(VALUE me, void *objspace)
{
- rb_objspace_t *objspace = (rb_objspace_t *)data;
+ gc_mark_internal(me);
- gc_mark(objspace, me);
return ID_TABLE_CONTINUE;
}
static void
-mark_m_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl)
+mark_m_tbl(void *objspace, struct rb_id_table *tbl)
{
if (tbl) {
rb_id_table_foreach_values(tbl, mark_method_entry_i, objspace);
@@ -6380,13 +2858,14 @@ mark_m_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl)
}
static enum rb_id_table_iterator_result
-mark_const_entry_i(VALUE value, void *data)
+mark_const_entry_i(VALUE value, void *objspace)
{
const rb_const_entry_t *ce = (const rb_const_entry_t *)value;
- rb_objspace_t *objspace = data;
- gc_mark(objspace, ce->value);
- gc_mark(objspace, ce->file);
+ if (!rb_gc_checking_shareable()) {
+ gc_mark_internal(ce->value);
+ gc_mark_internal(ce->file); // TODO: ce->file should be shareable?
+ }
return ID_TABLE_CONTINUE;
}
@@ -6397,6 +2876,26 @@ mark_const_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl)
rb_id_table_foreach_values(tbl, mark_const_entry_i, objspace);
}
+static enum rb_id_table_iterator_result
+mark_cvc_tbl_i(VALUE cvc_entry, void *objspace)
+{
+ struct rb_cvar_class_tbl_entry *entry;
+
+ entry = (struct rb_cvar_class_tbl_entry *)cvc_entry;
+
+ RUBY_ASSERT(entry->cref == 0 || (BUILTIN_TYPE((VALUE)entry->cref) == T_IMEMO && IMEMO_TYPE_P(entry->cref, imemo_cref)));
+ gc_mark_internal((VALUE)entry->cref);
+
+ return ID_TABLE_CONTINUE;
+}
+
+static void
+mark_cvc_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl)
+{
+ if (!tbl) return;
+ rb_id_table_foreach_values(tbl, mark_cvc_tbl_i, objspace);
+}
+
#if STACK_GROW_DIRECTION < 0
#define GET_STACK_BOUNDS(start, end, appendix) ((start) = STACK_END, (end) = STACK_START)
#elif STACK_GROW_DIRECTION > 0
@@ -6407,16 +2906,13 @@ 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 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));
-
static void
-gc_mark_machine_stack_location_maybe(rb_objspace_t *objspace, VALUE obj)
+gc_mark_machine_stack_location_maybe(VALUE obj, void *data)
{
- gc_mark_maybe(objspace, obj);
+ gc_mark_maybe_internal(obj);
#ifdef RUBY_ASAN_ENABLED
- const rb_execution_context_t *ec = objspace->marking_machine_context_ec;
+ const rb_execution_context_t *ec = (const rb_execution_context_t *)data;
void *fake_frame_start;
void *fake_frame_end;
bool is_fake_frame = asan_get_fake_stack_extents(
@@ -6425,11 +2921,39 @@ gc_mark_machine_stack_location_maybe(rb_objspace_t *objspace, VALUE obj)
&fake_frame_start, &fake_frame_end
);
if (is_fake_frame) {
- each_stack_location(objspace, ec, fake_frame_start, fake_frame_end, gc_mark_maybe);
+ each_location_ptr(fake_frame_start, fake_frame_end, gc_mark_maybe_each_location, NULL);
}
#endif
}
+static bool
+gc_object_moved_p_internal(void *objspace, VALUE obj)
+{
+ if (SPECIAL_CONST_P(obj)) {
+ return false;
+ }
+
+ return rb_gc_impl_object_moved_p(objspace, obj);
+}
+
+static VALUE
+gc_location_internal(void *objspace, VALUE value)
+{
+ if (SPECIAL_CONST_P(value)) {
+ return value;
+ }
+
+ GC_ASSERT(rb_gc_impl_pointer_to_heap_p(objspace, (void *)value));
+
+ return rb_gc_impl_location(objspace, value);
+}
+
+VALUE
+rb_gc_location(VALUE value)
+{
+ return gc_location_internal(rb_gc_get_objspace(), value);
+}
+
#if defined(__wasm__)
@@ -6442,420 +2966,232 @@ rb_mark_locations(void *begin, void *end)
rb_stack_range_tmp[1] = end;
}
+void
+rb_gc_save_machine_context(void)
+{
+ // no-op
+}
+
# if defined(__EMSCRIPTEN__)
static void
-mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec)
+mark_current_machine_context(const rb_execution_context_t *ec)
{
emscripten_scan_stack(rb_mark_locations);
- each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe);
+ each_location_ptr(rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe_each_location, NULL);
emscripten_scan_registers(rb_mark_locations);
- each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe);
+ each_location_ptr(rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe_each_location, NULL);
}
# else // use Asyncify version
static void
-mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec)
+mark_current_machine_context(rb_execution_context_t *ec)
{
VALUE *stack_start, *stack_end;
SET_STACK_END;
GET_STACK_BOUNDS(stack_start, stack_end, 1);
- each_stack_location(objspace, ec, stack_start, stack_end, gc_mark_maybe);
+ each_location_ptr(stack_start, stack_end, gc_mark_maybe_each_location, NULL);
rb_wasm_scan_locals(rb_mark_locations);
- each_stack_location(objspace, ec, rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe);
+ each_location_ptr(rb_stack_range_tmp[0], rb_stack_range_tmp[1], gc_mark_maybe_each_location, NULL);
}
# endif
#else // !defined(__wasm__)
-static void
-mark_current_machine_context(rb_objspace_t *objspace, rb_execution_context_t *ec)
+void
+rb_gc_save_machine_context(void)
{
- union {
- rb_jmp_buf j;
- VALUE v[sizeof(rb_jmp_buf) / (sizeof(VALUE))];
- } save_regs_gc_mark;
- VALUE *stack_start, *stack_end;
-
- FLUSH_REGISTER_WINDOWS;
- memset(&save_regs_gc_mark, 0, sizeof(save_regs_gc_mark));
- /* This assumes that all registers are saved into the jmp_buf (and stack) */
- rb_setjmp(save_regs_gc_mark.j);
+ rb_thread_t *thread = GET_THREAD();
- /* SET_STACK_END must be called in this function because
- * the stack frame of this function may contain
- * callee save registers and they should be marked. */
- SET_STACK_END;
- GET_STACK_BOUNDS(stack_start, stack_end, 1);
-
-#ifdef RUBY_ASAN_ENABLED
- objspace->marking_machine_context_ec = ec;
-#endif
+ RB_VM_SAVE_MACHINE_CONTEXT(thread);
+}
- each_location(objspace, save_regs_gc_mark.v, numberof(save_regs_gc_mark.v), gc_mark_machine_stack_location_maybe);
- each_stack_location(objspace, ec, stack_start, stack_end, gc_mark_machine_stack_location_maybe);
-#ifdef RUBY_ASAN_ENABLED
- objspace->marking_machine_context_ec = NULL;
-#endif
+static void
+mark_current_machine_context(const rb_execution_context_t *ec)
+{
+ rb_gc_mark_machine_context(ec);
}
#endif
void
rb_gc_mark_machine_context(const rb_execution_context_t *ec)
{
- rb_objspace_t *objspace = &rb_objspace;
-#ifdef RUBY_ASAN_ENABLED
- objspace->marking_machine_context_ec = ec;
-#endif
-
VALUE *stack_start, *stack_end;
GET_STACK_BOUNDS(stack_start, stack_end, 0);
RUBY_DEBUG_LOG("ec->th:%u stack_start:%p stack_end:%p", rb_ec_thread_ptr(ec)->serial, stack_start, stack_end);
- each_stack_location(objspace, ec, stack_start, stack_end, gc_mark_machine_stack_location_maybe);
- int num_regs = sizeof(ec->machine.regs)/(sizeof(VALUE));
- each_location(objspace, (VALUE*)&ec->machine.regs, num_regs, gc_mark_machine_stack_location_maybe);
-
+ void *data =
#ifdef RUBY_ASAN_ENABLED
- objspace->marking_machine_context_ec = NULL;
+ /* gc_mark_machine_stack_location_maybe() uses data as const */
+ (rb_execution_context_t *)ec;
+#else
+ NULL;
#endif
+
+ each_location_ptr(stack_start, stack_end, gc_mark_machine_stack_location_maybe, data);
+ int num_regs = sizeof(ec->machine.regs)/(sizeof(VALUE));
+ each_location((VALUE*)&ec->machine.regs, num_regs, gc_mark_machine_stack_location_maybe, data);
}
-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))
+static int
+rb_mark_tbl_i(st_data_t key, st_data_t value, st_data_t data)
{
+ gc_mark_and_pin_internal((VALUE)value);
- 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), cb);
-#endif
+ return ST_CONTINUE;
}
void
rb_mark_tbl(st_table *tbl)
{
- mark_tbl(&rb_objspace, tbl);
-}
+ if (!tbl || tbl->num_entries == 0) return;
-void
-rb_mark_tbl_no_pin(st_table *tbl)
-{
- mark_tbl_no_pin(&rb_objspace, tbl);
+ st_foreach(tbl, rb_mark_tbl_i, 0);
}
static void
-gc_mark_maybe(rb_objspace_t *objspace, VALUE obj)
+gc_mark_tbl_no_pin(st_table *tbl)
{
- (void)VALGRIND_MAKE_MEM_DEFINED(&obj, sizeof(obj));
-
- if (is_pointer_to_heap(objspace, (void *)obj)) {
- void *ptr = asan_unpoison_object_temporary(obj);
-
- /* Garbage can live on the stack, so do not mark or pin */
- switch (BUILTIN_TYPE(obj)) {
- case T_ZOMBIE:
- case T_NONE:
- break;
- default:
- gc_mark_and_pin(objspace, obj);
- break;
- }
+ if (!tbl || tbl->num_entries == 0) return;
- if (ptr) {
- GC_ASSERT(BUILTIN_TYPE(obj) == T_NONE);
- asan_poison_object(obj);
- }
- }
+ st_foreach(tbl, gc_mark_tbl_no_pin_i, 0);
}
void
-rb_gc_mark_maybe(VALUE obj)
+rb_mark_tbl_no_pin(st_table *tbl)
{
- gc_mark_maybe(&rb_objspace, obj);
+ gc_mark_tbl_no_pin(tbl);
}
-static inline int
-gc_mark_set(rb_objspace_t *objspace, VALUE obj)
+static bool
+gc_declarative_marking_p(const rb_data_type_t *type)
{
- ASSERT_vm_locking();
- if (RVALUE_MARKED(obj)) return 0;
- MARK_IN_BITMAP(GET_HEAP_MARK_BITS(obj), obj);
- return 1;
+ return (type->flags & RUBY_TYPED_DECL_MARKING) != 0;
}
-static int
-gc_remember_unprotected(rb_objspace_t *objspace, VALUE obj)
+void
+rb_gc_mark_roots(void *objspace, const char **categoryp)
{
- struct heap_page *page = GET_HEAP_PAGE(obj);
- bits_t *uncollectible_bits = &page->uncollectible_bits[0];
+ rb_execution_context_t *ec = GET_EC();
+ rb_vm_t *vm = rb_ec_vm_ptr(ec);
- if (!MARKED_IN_BITMAP(uncollectible_bits, obj)) {
- page->flags.has_uncollectible_wb_unprotected_objects = TRUE;
- MARK_IN_BITMAP(uncollectible_bits, obj);
- objspace->rgengc.uncollectible_wb_unprotected_objects++;
+#define MARK_CHECKPOINT(category) do { \
+ if (categoryp) *categoryp = category; \
+} while (0)
-#if RGENGC_PROFILE > 0
- objspace->profile.total_remembered_shady_object_count++;
-#if RGENGC_PROFILE >= 2
- objspace->profile.remembered_shady_object_count_types[BUILTIN_TYPE(obj)]++;
-#endif
-#endif
- return TRUE;
- }
- else {
- return FALSE;
- }
-}
+ MARK_CHECKPOINT("vm");
+ rb_vm_mark(vm);
-static void
-rgengc_check_relation(rb_objspace_t *objspace, VALUE obj)
-{
- const VALUE old_parent = objspace->rgengc.parent_object;
+ MARK_CHECKPOINT("end_proc");
+ rb_mark_end_proc();
- if (old_parent) { /* parent object is old */
- if (RVALUE_WB_UNPROTECTED(obj) || !RVALUE_OLD_P(obj)) {
- rgengc_remember(objspace, old_parent);
- }
- }
+ MARK_CHECKPOINT("global_tbl");
+ rb_gc_mark_global_tbl();
- GC_ASSERT(old_parent == objspace->rgengc.parent_object);
-}
+#if USE_YJIT
+ void rb_yjit_root_mark(void); // in Rust
-static void
-gc_grey(rb_objspace_t *objspace, VALUE obj)
-{
-#if RGENGC_CHECK_MODE
- if (RVALUE_MARKED(obj) == FALSE) rb_bug("gc_grey: %s is not marked.", obj_info(obj));
- if (RVALUE_MARKING(obj) == TRUE) rb_bug("gc_grey: %s is marking/remembered.", obj_info(obj));
+ if (rb_yjit_enabled_p) {
+ MARK_CHECKPOINT("YJIT");
+ rb_yjit_root_mark();
+ }
#endif
- if (is_incremental_marking(objspace)) {
- MARK_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), obj);
+#if USE_ZJIT
+ void rb_zjit_root_mark(void);
+ if (rb_zjit_enabled_p) {
+ MARK_CHECKPOINT("ZJIT");
+ rb_zjit_root_mark();
}
+#endif
- push_mark_stack(&objspace->mark_stack, obj);
-}
-
-static void
-gc_aging(rb_objspace_t *objspace, VALUE obj)
-{
- struct heap_page *page = GET_HEAP_PAGE(obj);
+ MARK_CHECKPOINT("machine_context");
+ mark_current_machine_context(ec);
- GC_ASSERT(RVALUE_MARKING(obj) == FALSE);
- check_rvalue_consistency(obj);
+ MARK_CHECKPOINT("global_symbols");
+ rb_sym_global_symbols_mark_and_move();
- if (!RVALUE_PAGE_WB_UNPROTECTED(page, obj)) {
- if (!RVALUE_OLD_P(obj)) {
- gc_report(3, objspace, "gc_aging: YOUNG: %s\n", obj_info(obj));
- RVALUE_AGE_INC(objspace, obj);
- }
- else if (is_full_marking(objspace)) {
- GC_ASSERT(RVALUE_PAGE_UNCOLLECTIBLE(page, obj) == FALSE);
- RVALUE_PAGE_OLD_UNCOLLECTIBLE_SET(objspace, page, obj);
- }
- }
- check_rvalue_consistency(obj);
+ MARK_CHECKPOINT("finish");
- objspace->marked_slots++;
+#undef MARK_CHECKPOINT
}
-NOINLINE(static void gc_mark_ptr(rb_objspace_t *objspace, VALUE obj));
-static void reachable_objects_from_callback(VALUE obj);
+struct gc_mark_classext_foreach_arg {
+ rb_objspace_t *objspace;
+ VALUE obj;
+};
static void
-gc_mark_ptr(rb_objspace_t *objspace, VALUE obj)
+gc_mark_classext_module(rb_classext_t *ext, bool prime, VALUE box_value, void *arg)
{
- if (LIKELY(during_gc)) {
- rgengc_check_relation(objspace, obj);
- if (!gc_mark_set(objspace, obj)) return; /* already marked */
+ struct gc_mark_classext_foreach_arg *foreach_arg = (struct gc_mark_classext_foreach_arg *)arg;
+ rb_objspace_t *objspace = foreach_arg->objspace;
- 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);
+ if (RCLASSEXT_SUPER(ext)) {
+ gc_mark_internal(RCLASSEXT_SUPER(ext));
}
- else {
- reachable_objects_from_callback(obj);
- }
-}
+ mark_m_tbl(objspace, RCLASSEXT_M_TBL(ext));
-static inline void
-gc_pin(rb_objspace_t *objspace, VALUE obj)
-{
- GC_ASSERT(is_markable_object(obj));
- if (UNLIKELY(objspace->flags.during_compacting)) {
- if (LIKELY(during_gc)) {
- if (!MARKED_IN_BITMAP(GET_HEAP_PINNED_BITS(obj), obj)) {
- GC_ASSERT(GET_HEAP_PAGE(obj)->pinned_slots <= GET_HEAP_PAGE(obj)->total_slots);
- GET_HEAP_PAGE(obj)->pinned_slots++;
- MARK_IN_BITMAP(GET_HEAP_PINNED_BITS(obj), obj);
- }
- }
+ if (!rb_gc_checking_shareable()) {
+ // unshareable
+ gc_mark_internal(RCLASSEXT_FIELDS_OBJ(ext));
}
-}
-
-static inline void
-gc_mark_and_pin(rb_objspace_t *objspace, VALUE obj)
-{
- if (!is_markable_object(obj)) return;
- gc_pin(objspace, obj);
- gc_mark_ptr(objspace, obj);
-}
-static inline void
-gc_mark(rb_objspace_t *objspace, VALUE obj)
-{
- if (!is_markable_object(obj)) return;
- gc_mark_ptr(objspace, obj);
-}
-
-void
-rb_gc_mark_movable(VALUE ptr)
-{
- gc_mark(&rb_objspace, ptr);
-}
-
-void
-rb_gc_mark(VALUE ptr)
-{
- gc_mark_and_pin(&rb_objspace, ptr);
-}
-
-void
-rb_gc_mark_and_move(VALUE *ptr)
-{
- rb_objspace_t *objspace = &rb_objspace;
- if (RB_SPECIAL_CONST_P(*ptr)) return;
-
- if (UNLIKELY(objspace->flags.during_reference_updating)) {
- GC_ASSERT(objspace->flags.during_compacting);
- GC_ASSERT(during_gc);
-
- *ptr = rb_gc_location(*ptr);
- }
- else {
- gc_mark_ptr(objspace, *ptr);
+ if (!RCLASSEXT_SHARED_CONST_TBL(ext) && RCLASSEXT_CONST_TBL(ext)) {
+ mark_const_tbl(objspace, RCLASSEXT_CONST_TBL(ext));
}
+ mark_m_tbl(objspace, RCLASSEXT_CALLABLE_M_TBL(ext));
+ gc_mark_internal(RCLASSEXT_CC_TBL(ext));
+ mark_cvc_tbl(objspace, RCLASSEXT_CVC_TBL(ext));
+ gc_mark_internal(RCLASSEXT_CLASSPATH(ext));
}
-void
-rb_gc_mark_weak(VALUE *ptr)
+static void
+gc_mark_classext_iclass(rb_classext_t *ext, bool prime, VALUE box_value, void *arg)
{
- rb_objspace_t *objspace = &rb_objspace;
-
- if (UNLIKELY(!during_gc)) return;
+ struct gc_mark_classext_foreach_arg *foreach_arg = (struct gc_mark_classext_foreach_arg *)arg;
+ rb_objspace_t *objspace = foreach_arg->objspace;
- VALUE obj = *ptr;
- if (RB_SPECIAL_CONST_P(obj)) return;
-
- GC_ASSERT(objspace->rgengc.parent_object == 0 || FL_TEST(objspace->rgengc.parent_object, FL_WB_PROTECTED));
-
- if (UNLIKELY(RB_TYPE_P(obj, T_NONE))) {
- rp(obj);
- rb_bug("try to mark T_NONE object");
+ if (RCLASSEXT_SUPER(ext)) {
+ gc_mark_internal(RCLASSEXT_SUPER(ext));
}
-
- /* If we are in a minor GC and the other object is old, then obj should
- * already be marked and cannot be reclaimed in this GC cycle so we don't
- * need to add it to the weak refences list. */
- if (!is_full_marking(objspace) && RVALUE_OLD_P(obj)) {
- GC_ASSERT(RVALUE_MARKED(obj));
- GC_ASSERT(!objspace->flags.during_compacting);
-
- return;
+ if (RCLASSEXT_ICLASS_IS_ORIGIN(ext) && !RCLASSEXT_ICLASS_ORIGIN_SHARED_MTBL(ext)) {
+ mark_m_tbl(objspace, RCLASSEXT_M_TBL(ext));
}
-
- rgengc_check_relation(objspace, obj);
-
- DURING_GC_COULD_MALLOC_REGION_START();
- {
- rb_darray_append(&objspace->weak_references, ptr);
+ if (RCLASSEXT_INCLUDER(ext)) {
+ gc_mark_internal(RCLASSEXT_INCLUDER(ext));
}
- DURING_GC_COULD_MALLOC_REGION_END();
-
- objspace->profile.weak_references_count++;
+ mark_m_tbl(objspace, RCLASSEXT_CALLABLE_M_TBL(ext));
+ gc_mark_internal(RCLASSEXT_CC_TBL(ext));
}
-void
-rb_gc_remove_weak(VALUE parent_obj, VALUE *ptr)
-{
- rb_objspace_t *objspace = &rb_objspace;
-
- /* If we're not incremental marking, then the state of the objects can't
- * change so we don't need to do anything. */
- if (!is_incremental_marking(objspace)) return;
- /* If parent_obj has not been marked, then ptr has not yet been marked
- * weak, so we don't need to do anything. */
- if (!RVALUE_MARKED(parent_obj)) return;
-
- VALUE **ptr_ptr;
- rb_darray_foreach(objspace->weak_references, i, ptr_ptr) {
- if (*ptr_ptr == ptr) {
- *ptr_ptr = NULL;
- break;
- }
- }
-}
+#define TYPED_DATA_REFS_OFFSET_LIST(d) (size_t *)(uintptr_t)RTYPEDDATA_TYPE(d)->function.dmark
-static inline void
-gc_mark_set_parent(rb_objspace_t *objspace, VALUE obj)
+void
+rb_gc_move_obj_during_marking(VALUE from, VALUE to)
{
- if (RVALUE_OLD_P(obj)) {
- objspace->rgengc.parent_object = obj;
- }
- else {
- objspace->rgengc.parent_object = Qfalse;
+ if (rb_obj_using_gen_fields_table_p(to)) {
+ rb_mark_generic_ivar(from);
}
}
-static bool
-gc_declarative_marking_p(const rb_data_type_t *type)
-{
- return (type->flags & RUBY_TYPED_DECL_MARKING) != 0;
-}
-
-static void mark_cvc_tbl(rb_objspace_t *objspace, VALUE klass);
-
-static void
-gc_mark_children(rb_objspace_t *objspace, VALUE obj)
+void
+rb_gc_mark_children(void *objspace, VALUE obj)
{
- register RVALUE *any = RANY(obj);
- gc_mark_set_parent(objspace, obj);
+ struct gc_mark_classext_foreach_arg foreach_args;
- if (FL_TEST(obj, FL_EXIVAR)) {
+ if (rb_obj_using_gen_fields_table_p(obj)) {
rb_mark_generic_ivar(obj);
}
switch (BUILTIN_TYPE(obj)) {
case T_FLOAT:
case T_BIGNUM:
- case T_SYMBOL:
- /* Not immediates, but does not have references and singleton class.
- *
- * RSYMBOL(obj)->fstr intentionally not marked. See log for 96815f1e
- * ("symbol.c: remove rb_gc_mark_symbols()") */
return;
case T_NIL:
@@ -6875,1832 +3211,243 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)
break;
}
- gc_mark(objspace, any->as.basic.klass);
+ gc_mark_internal(RBASIC(obj)->klass);
switch (BUILTIN_TYPE(obj)) {
case T_CLASS:
- if (FL_TEST(obj, FL_SINGLETON)) {
- gc_mark(objspace, RCLASS_ATTACHED_OBJECT(obj));
+ if (FL_TEST_RAW(obj, FL_SINGLETON) &&
+ !rb_gc_checking_shareable()) {
+ gc_mark_internal(RCLASS_ATTACHED_OBJECT(obj));
}
// Continue to the shared T_CLASS/T_MODULE
case T_MODULE:
- if (RCLASS_SUPER(obj)) {
- gc_mark(objspace, RCLASS_SUPER(obj));
- }
-
- mark_m_tbl(objspace, RCLASS_M_TBL(obj));
- mark_cvc_tbl(objspace, obj);
- rb_cc_table_mark(obj);
- if (rb_shape_obj_too_complex(obj)) {
- mark_tbl_no_pin(objspace, (st_table *)RCLASS_IVPTR(obj));
+ foreach_args.objspace = objspace;
+ foreach_args.obj = obj;
+ rb_class_classext_foreach(obj, gc_mark_classext_module, (void *)&foreach_args);
+ if (BOX_USER_P(RCLASS_PRIME_BOX(obj))) {
+ gc_mark_internal(RCLASS_PRIME_BOX(obj)->box_object);
}
- else {
- for (attr_index_t i = 0; i < RCLASS_IV_COUNT(obj); i++) {
- gc_mark(objspace, RCLASS_IVPTR(obj)[i]);
- }
- }
- mark_const_tbl(objspace, RCLASS_CONST_TBL(obj));
-
- gc_mark(objspace, RCLASS_EXT(obj)->classpath);
break;
case T_ICLASS:
- if (RICLASS_OWNS_M_TBL_P(obj)) {
- mark_m_tbl(objspace, RCLASS_M_TBL(obj));
- }
- if (RCLASS_SUPER(obj)) {
- gc_mark(objspace, RCLASS_SUPER(obj));
+ foreach_args.objspace = objspace;
+ foreach_args.obj = obj;
+ rb_class_classext_foreach(obj, gc_mark_classext_iclass, (void *)&foreach_args);
+ if (BOX_USER_P(RCLASS_PRIME_BOX(obj))) {
+ gc_mark_internal(RCLASS_PRIME_BOX(obj)->box_object);
}
-
- if (RCLASS_INCLUDER(obj)) {
- gc_mark(objspace, RCLASS_INCLUDER(obj));
- }
- mark_m_tbl(objspace, RCLASS_CALLABLE_M_TBL(obj));
- rb_cc_table_mark(obj);
break;
case T_ARRAY:
if (ARY_SHARED_P(obj)) {
VALUE root = ARY_SHARED_ROOT(obj);
- gc_mark(objspace, root);
+ gc_mark_internal(root);
}
else {
- long i, len = RARRAY_LEN(obj);
+ long len = RARRAY_LEN(obj);
const VALUE *ptr = RARRAY_CONST_PTR(obj);
- for (i=0; i < len; i++) {
- gc_mark(objspace, ptr[i]);
+ for (long i = 0; i < len; i++) {
+ gc_mark_internal(ptr[i]);
}
}
break;
case T_HASH:
- mark_hash(objspace, obj);
+ mark_hash(obj);
+ break;
+
+ case T_SYMBOL:
+ gc_mark_internal(RSYMBOL(obj)->fstr);
break;
case T_STRING:
if (STR_SHARED_P(obj)) {
- if (STR_EMBED_P(any->as.string.as.heap.aux.shared)) {
+ if (STR_EMBED_P(RSTRING(obj)->as.heap.aux.shared)) {
/* Embedded shared strings cannot be moved because this string
* points into the slot of the shared string. There may be code
* using the RSTRING_PTR on the stack, which would pin this
* string but not pin the shared string, causing it to move. */
- gc_mark_and_pin(objspace, any->as.string.as.heap.aux.shared);
+ gc_mark_and_pin_internal(RSTRING(obj)->as.heap.aux.shared);
}
else {
- gc_mark(objspace, any->as.string.as.heap.aux.shared);
+ gc_mark_internal(RSTRING(obj)->as.heap.aux.shared);
}
}
break;
- case T_DATA:
- {
- void *const ptr = RTYPEDDATA_P(obj) ? RTYPEDDATA_GET_DATA(obj) : DATA_PTR(obj);
+ case T_DATA: {
+ bool typed_data = RTYPEDDATA_P(obj);
+ void *const ptr = typed_data ? RTYPEDDATA_GET_DATA(obj) : DATA_PTR(obj);
- if (ptr) {
- if (RTYPEDDATA_P(obj) && gc_declarative_marking_p(any->as.typeddata.type)) {
- size_t *offset_list = (size_t *)RANY(obj)->as.typeddata.type->function.dmark;
+ if (typed_data) {
+ gc_mark_internal(RTYPEDDATA(obj)->fields_obj);
+ }
- for (size_t offset = *offset_list; offset != RUBY_REF_END; offset = *offset_list++) {
- rb_gc_mark_movable(*(VALUE *)((char *)ptr + offset));
- }
- }
- else {
- RUBY_DATA_FUNC mark_func = RTYPEDDATA_P(obj) ?
- any->as.typeddata.type->function.dmark :
- any->as.data.dmark;
- if (mark_func) (*mark_func)(ptr);
+ if (ptr) {
+ if (typed_data && gc_declarative_marking_p(RTYPEDDATA_TYPE(obj))) {
+ size_t *offset_list = TYPED_DATA_REFS_OFFSET_LIST(obj);
+
+ for (size_t offset = *offset_list; offset != RUBY_REF_END; offset = *offset_list++) {
+ gc_mark_internal(*(VALUE *)((char *)ptr + offset));
}
}
+ else {
+ RUBY_DATA_FUNC mark_func = typed_data ?
+ RTYPEDDATA_TYPE(obj)->function.dmark :
+ RDATA(obj)->dmark;
+ if (mark_func) (*mark_func)(ptr);
+ }
}
+
break;
+ }
- case T_OBJECT:
- {
- rb_shape_t *shape = rb_shape_get_shape_by_id(ROBJECT_SHAPE_ID(obj));
- if (rb_shape_obj_too_complex(obj)) {
- mark_tbl_no_pin(objspace, ROBJECT_IV_HASH(obj));
- }
- else {
- const VALUE * const ptr = ROBJECT_IVPTR(obj);
+ case T_OBJECT: {
+ uint32_t len;
+ if (rb_shape_obj_too_complex_p(obj)) {
+ gc_mark_tbl_no_pin(ROBJECT_FIELDS_HASH(obj));
+ len = ROBJECT_FIELDS_COUNT_COMPLEX(obj);
+ }
+ else {
+ const VALUE * const ptr = ROBJECT_FIELDS(obj);
- uint32_t i, len = ROBJECT_IV_COUNT(obj);
- for (i = 0; i < len; i++) {
- gc_mark(objspace, ptr[i]);
- }
+ len = ROBJECT_FIELDS_COUNT_NOT_COMPLEX(obj);
+ for (uint32_t i = 0; i < len; i++) {
+ gc_mark_internal(ptr[i]);
}
- if (shape) {
- VALUE klass = RBASIC_CLASS(obj);
+ }
- // Increment max_iv_count if applicable, used to determine size pool allocation
- attr_index_t num_of_ivs = shape->next_iv_index;
- if (RCLASS_EXT(klass)->max_iv_count < num_of_ivs) {
- RCLASS_EXT(klass)->max_iv_count = num_of_ivs;
- }
+ attr_index_t fields_count = (attr_index_t)len;
+ if (fields_count) {
+ VALUE klass = RBASIC_CLASS(obj);
+
+ // Increment max_iv_count if applicable, used to determine size pool allocation
+ if (RCLASS_MAX_IV_COUNT(klass) < fields_count) {
+ RCLASS_SET_MAX_IV_COUNT(klass, fields_count);
}
}
+
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);
- gc_mark(objspace, any->as.file.fptr->writeconv_pre_ecopts);
- gc_mark(objspace, any->as.file.fptr->encs.ecopts);
- gc_mark(objspace, any->as.file.fptr->write_lock);
- gc_mark(objspace, any->as.file.fptr->timeout);
+ if (RFILE(obj)->fptr) {
+ gc_mark_internal(RFILE(obj)->fptr->self);
+ gc_mark_internal(RFILE(obj)->fptr->pathv);
+ gc_mark_internal(RFILE(obj)->fptr->tied_io_for_writing);
+ gc_mark_internal(RFILE(obj)->fptr->writeconv_asciicompat);
+ gc_mark_internal(RFILE(obj)->fptr->writeconv_pre_ecopts);
+ gc_mark_internal(RFILE(obj)->fptr->encs.ecopts);
+ gc_mark_internal(RFILE(obj)->fptr->write_lock);
+ gc_mark_internal(RFILE(obj)->fptr->timeout);
+ gc_mark_internal(RFILE(obj)->fptr->wakeup_mutex);
}
break;
case T_REGEXP:
- gc_mark(objspace, any->as.regexp.src);
+ gc_mark_internal(RREGEXP(obj)->src);
break;
case T_MATCH:
- gc_mark(objspace, any->as.match.regexp);
- if (any->as.match.str) {
- gc_mark(objspace, any->as.match.str);
+ gc_mark_internal(RMATCH(obj)->regexp);
+ if (RMATCH(obj)->str) {
+ gc_mark_internal(RMATCH(obj)->str);
}
break;
case T_RATIONAL:
- gc_mark(objspace, any->as.rational.num);
- gc_mark(objspace, any->as.rational.den);
+ gc_mark_internal(RRATIONAL(obj)->num);
+ gc_mark_internal(RRATIONAL(obj)->den);
break;
case T_COMPLEX:
- gc_mark(objspace, any->as.complex.real);
- gc_mark(objspace, any->as.complex.imag);
+ gc_mark_internal(RCOMPLEX(obj)->real);
+ gc_mark_internal(RCOMPLEX(obj)->imag);
break;
- case T_STRUCT:
- {
- long i;
- const long len = RSTRUCT_LEN(obj);
- const VALUE * const ptr = RSTRUCT_CONST_PTR(obj);
+ case T_STRUCT: {
+ const long len = RSTRUCT_LEN(obj);
+ const VALUE * const ptr = RSTRUCT_CONST_PTR(obj);
- for (i=0; i<len; i++) {
- gc_mark(objspace, ptr[i]);
- }
+ for (long i = 0; i < len; i++) {
+ gc_mark_internal(ptr[i]);
}
+
+ if (rb_shape_obj_has_fields(obj) && !FL_TEST_RAW(obj, RSTRUCT_GEN_FIELDS)) {
+ gc_mark_internal(RSTRUCT_FIELDS_OBJ(obj));
+ }
+
break;
+ }
default:
-#if GC_DEBUG
- rb_gcdebug_print_obj_condition((VALUE)obj);
-#endif
if (BUILTIN_TYPE(obj) == T_MOVED) rb_bug("rb_gc_mark(): %p is T_MOVED", (void *)obj);
if (BUILTIN_TYPE(obj) == T_NONE) rb_bug("rb_gc_mark(): %p is T_NONE", (void *)obj);
if (BUILTIN_TYPE(obj) == T_ZOMBIE) rb_bug("rb_gc_mark(): %p is T_ZOMBIE", (void *)obj);
rb_bug("rb_gc_mark(): unknown data type 0x%x(%p) %s",
- BUILTIN_TYPE(obj), (void *)any,
- is_pointer_to_heap(objspace, any) ? "corrupted object" : "non object");
+ BUILTIN_TYPE(obj), (void *)obj,
+ rb_gc_impl_pointer_to_heap_p(objspace, (void *)obj) ? "corrupted object" : "non object");
}
}
-/**
- * incremental: 0 -> not incremental (do all)
- * incremental: n -> mark at most `n' objects
- */
-static inline int
-gc_mark_stacked_objects(rb_objspace_t *objspace, int incremental, size_t count)
+size_t
+rb_gc_obj_optimal_size(VALUE obj)
{
- mark_stack_t *mstack = &objspace->mark_stack;
- VALUE obj;
- size_t marked_slots_at_the_beginning = objspace->marked_slots;
- size_t popped_count = 0;
-
- while (pop_mark_stack(mstack, &obj)) {
- if (UNDEF_P(obj)) continue; /* skip */
-
- if (RGENGC_CHECK_MODE && !RVALUE_MARKED(obj)) {
- rb_bug("gc_mark_stacked_objects: %s is not marked.", obj_info(obj));
- }
- gc_mark_children(objspace, obj);
-
- if (incremental) {
- if (RGENGC_CHECK_MODE && !RVALUE_MARKING(obj)) {
- rb_bug("gc_mark_stacked_objects: incremental, but marking bit is 0");
+ switch (BUILTIN_TYPE(obj)) {
+ case T_ARRAY:
+ {
+ size_t size = rb_ary_size_as_embedded(obj);
+ if (rb_gc_size_allocatable_p(size)) {
+ return size;
}
- CLEAR_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), obj);
- popped_count++;
-
- if (popped_count + (objspace->marked_slots - marked_slots_at_the_beginning) > count) {
- break;
+ else {
+ return sizeof(struct RArray);
}
}
- else {
- /* just ignore marking bits */
- }
- }
-
- if (RGENGC_CHECK_MODE >= 3) gc_verify_internal_consistency(objspace);
-
- if (is_mark_stack_empty(mstack)) {
- shrink_stack_chunk_cache(mstack);
- return TRUE;
- }
- else {
- return FALSE;
- }
-}
-
-static int
-gc_mark_stacked_objects_incremental(rb_objspace_t *objspace, size_t count)
-{
- return gc_mark_stacked_objects(objspace, TRUE, count);
-}
-
-static int
-gc_mark_stacked_objects_all(rb_objspace_t *objspace)
-{
- return gc_mark_stacked_objects(objspace, FALSE, 0);
-}
-
-#if PRINT_ROOT_TICKS
-#define MAX_TICKS 0x100
-static tick_t mark_ticks[MAX_TICKS];
-static const char *mark_ticks_categories[MAX_TICKS];
-
-static void
-show_mark_ticks(void)
-{
- int i;
- fprintf(stderr, "mark ticks result:\n");
- for (i=0; i<MAX_TICKS; i++) {
- const char *category = mark_ticks_categories[i];
- if (category) {
- fprintf(stderr, "%s\t%8lu\n", category, (unsigned long)mark_ticks[i]);
- }
- else {
- break;
- }
- }
-}
-
-#endif /* PRINT_ROOT_TICKS */
-
-static void
-gc_mark_roots(rb_objspace_t *objspace, const char **categoryp)
-{
- rb_execution_context_t *ec = GET_EC();
- rb_vm_t *vm = rb_ec_vm_ptr(ec);
-
-#if PRINT_ROOT_TICKS
- tick_t start_tick = tick();
- int tick_count = 0;
- const char *prev_category = 0;
-
- if (mark_ticks_categories[0] == 0) {
- atexit(show_mark_ticks);
- }
-#endif
-
- if (categoryp) *categoryp = "xxx";
-
- objspace->rgengc.parent_object = Qfalse;
-
-#if PRINT_ROOT_TICKS
-#define MARK_CHECKPOINT_PRINT_TICK(category) do { \
- if (prev_category) { \
- tick_t t = tick(); \
- mark_ticks[tick_count] = t - start_tick; \
- mark_ticks_categories[tick_count] = prev_category; \
- tick_count++; \
- } \
- prev_category = category; \
- start_tick = tick(); \
-} while (0)
-#else /* PRINT_ROOT_TICKS */
-#define MARK_CHECKPOINT_PRINT_TICK(category)
-#endif
-
-#define MARK_CHECKPOINT(category) do { \
- if (categoryp) *categoryp = category; \
- MARK_CHECKPOINT_PRINT_TICK(category); \
-} while (0)
-
- MARK_CHECKPOINT("vm");
- SET_STACK_END;
- rb_vm_mark(vm);
- if (vm->self) gc_mark(objspace, vm->self);
-
- MARK_CHECKPOINT("finalizers");
- mark_finalizer_tbl(objspace, finalizer_table);
-
- MARK_CHECKPOINT("machine_context");
- mark_current_machine_context(objspace, ec);
-
- /* mark protected global variables */
-
- MARK_CHECKPOINT("end_proc");
- rb_mark_end_proc();
-
- MARK_CHECKPOINT("global_tbl");
- rb_gc_mark_global_tbl();
- MARK_CHECKPOINT("object_id");
- mark_tbl_no_pin(objspace, objspace->obj_to_id_tbl); /* Only mark ids */
-
- if (stress_to_class) rb_gc_mark(stress_to_class);
-
- MARK_CHECKPOINT("finish");
-#undef MARK_CHECKPOINT
-}
-
-#if RGENGC_CHECK_MODE >= 4
-
-#define MAKE_ROOTSIG(obj) (((VALUE)(obj) << 1) | 0x01)
-#define IS_ROOTSIG(obj) ((VALUE)(obj) & 0x01)
-#define GET_ROOTSIG(obj) ((const char *)((VALUE)(obj) >> 1))
-
-struct reflist {
- VALUE *list;
- int pos;
- int size;
-};
-
-static struct reflist *
-reflist_create(VALUE obj)
-{
- struct reflist *refs = xmalloc(sizeof(struct reflist));
- refs->size = 1;
- refs->list = ALLOC_N(VALUE, refs->size);
- refs->list[0] = obj;
- refs->pos = 1;
- return refs;
-}
-
-static void
-reflist_destruct(struct reflist *refs)
-{
- xfree(refs->list);
- xfree(refs);
-}
-
-static void
-reflist_add(struct reflist *refs, VALUE obj)
-{
- if (refs->pos == refs->size) {
- refs->size *= 2;
- SIZED_REALLOC_N(refs->list, VALUE, refs->size, refs->size/2);
- }
-
- refs->list[refs->pos++] = obj;
-}
-
-static void
-reflist_dump(struct reflist *refs)
-{
- int i;
- for (i=0; i<refs->pos; i++) {
- VALUE obj = refs->list[i];
- if (IS_ROOTSIG(obj)) { /* root */
- fprintf(stderr, "<root@%s>", GET_ROOTSIG(obj));
- }
- else {
- fprintf(stderr, "<%s>", obj_info(obj));
- }
- if (i+1 < refs->pos) fprintf(stderr, ", ");
- }
-}
-
-static int
-reflist_referred_from_machine_context(struct reflist *refs)
-{
- int i;
- for (i=0; i<refs->pos; i++) {
- VALUE obj = refs->list[i];
- if (IS_ROOTSIG(obj) && strcmp(GET_ROOTSIG(obj), "machine_context") == 0) return 1;
- }
- return 0;
-}
-
-struct allrefs {
- rb_objspace_t *objspace;
- /* a -> obj1
- * b -> obj1
- * c -> obj1
- * c -> obj2
- * d -> obj3
- * #=> {obj1 => [a, b, c], obj2 => [c, d]}
- */
- struct st_table *references;
- const char *category;
- VALUE root_obj;
- mark_stack_t mark_stack;
-};
-
-static int
-allrefs_add(struct allrefs *data, VALUE obj)
-{
- struct reflist *refs;
- st_data_t r;
-
- if (st_lookup(data->references, obj, &r)) {
- refs = (struct reflist *)r;
- reflist_add(refs, data->root_obj);
- return 0;
- }
- else {
- refs = reflist_create(data->root_obj);
- st_insert(data->references, obj, (st_data_t)refs);
- return 1;
- }
-}
-
-static void
-allrefs_i(VALUE obj, void *ptr)
-{
- struct allrefs *data = (struct allrefs *)ptr;
-
- if (allrefs_add(data, obj)) {
- push_mark_stack(&data->mark_stack, obj);
- }
-}
-
-static void
-allrefs_roots_i(VALUE obj, void *ptr)
-{
- struct allrefs *data = (struct allrefs *)ptr;
- if (strlen(data->category) == 0) rb_bug("!!!");
- data->root_obj = MAKE_ROOTSIG(data->category);
-
- if (allrefs_add(data, obj)) {
- 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 gc_mark_func_data_struct mfd;
- VALUE obj;
- int prev_dont_gc = dont_gc_val();
- dont_gc_on();
-
- data.objspace = objspace;
- data.references = st_init_numtable();
- init_mark_stack(&data.mark_stack);
-
- mfd.mark_func = allrefs_roots_i;
- mfd.data = &data;
-
- /* traverse root objects */
- PUSH_MARK_FUNC_DATA(&mfd);
- GET_RACTOR()->mfd = &mfd;
- gc_mark_roots(objspace, &data.category);
- POP_MARK_FUNC_DATA();
-
- /* traverse rest objects reachable from root objects */
- while (pop_mark_stack(&data.mark_stack, &obj)) {
- rb_objspace_reachable_objects_from(data.root_obj = obj, allrefs_i, &data);
- }
- free_stack_chunks(&data.mark_stack);
-
- dont_gc_set(prev_dont_gc);
- return data.references;
-}
-
-static int
-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);
- return ST_CONTINUE;
-}
-
-static void
-objspace_allrefs_destruct(struct st_table *refs)
-{
- st_foreach(refs, objspace_allrefs_destruct_i, 0);
- st_free_table(refs);
-}
-
-#if RGENGC_CHECK_MODE >= 5
-static int
-allrefs_dump_i(st_data_t k, st_data_t v, st_data_t ptr)
-{
- VALUE obj = (VALUE)k;
- struct reflist *refs = (struct reflist *)v;
- fprintf(stderr, "[allrefs_dump_i] %s <- ", obj_info(obj));
- reflist_dump(refs);
- fprintf(stderr, "\n");
- return ST_CONTINUE;
-}
-
-static void
-allrefs_dump(rb_objspace_t *objspace)
-{
- 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, st_data_t ptr)
-{
- VALUE obj = k;
- struct reflist *refs = (struct reflist *)v;
- rb_objspace_t *objspace = (rb_objspace_t *)ptr;
-
- /* object should be marked or oldgen */
- if (!MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(obj), obj)) {
- fprintf(stderr, "gc_check_after_marks_i: %s is not marked and not oldgen.\n", obj_info(obj));
- fprintf(stderr, "gc_check_after_marks_i: %p is referred from ", (void *)obj);
- reflist_dump(refs);
-
- if (reflist_referred_from_machine_context(refs)) {
- fprintf(stderr, " (marked from machine stack).\n");
- /* marked from machine context can be false positive */
- }
- else {
- objspace->rgengc.error_count++;
- fprintf(stderr, "\n");
- }
- }
- return ST_CONTINUE;
-}
-
-static void
-gc_marks_check(rb_objspace_t *objspace, st_foreach_callback_func *checker_func, const char *checker_name)
-{
- size_t saved_malloc_increase = objspace->malloc_params.increase;
-#if RGENGC_ESTIMATE_OLDMALLOC
- size_t saved_oldmalloc_increase = objspace->rgengc.oldmalloc_increase;
-#endif
- VALUE already_disabled = rb_objspace_gc_disable(objspace);
-
- objspace->rgengc.allrefs_table = objspace_allrefs(objspace);
-
- if (checker_func) {
- st_foreach(objspace->rgengc.allrefs_table, checker_func, (st_data_t)objspace);
- }
-
- if (objspace->rgengc.error_count > 0) {
-#if RGENGC_CHECK_MODE >= 5
- allrefs_dump(objspace);
-#endif
- if (checker_name) rb_bug("%s: GC has problem.", checker_name);
- }
-
- objspace_allrefs_destruct(objspace->rgengc.allrefs_table);
- objspace->rgengc.allrefs_table = 0;
-
- if (already_disabled == Qfalse) rb_objspace_gc_enable(objspace);
- objspace->malloc_params.increase = saved_malloc_increase;
-#if RGENGC_ESTIMATE_OLDMALLOC
- objspace->rgengc.oldmalloc_increase = saved_oldmalloc_increase;
-#endif
-}
-#endif /* RGENGC_CHECK_MODE >= 4 */
-
-struct verify_internal_consistency_struct {
- rb_objspace_t *objspace;
- int err_count;
- size_t live_object_count;
- size_t zombie_object_count;
-
- VALUE parent;
- size_t old_object_count;
- size_t remembered_shady_count;
-};
-
-static void
-check_generation_i(const VALUE child, void *ptr)
-{
- struct verify_internal_consistency_struct *data = (struct verify_internal_consistency_struct *)ptr;
- const VALUE parent = data->parent;
-
- if (RGENGC_CHECK_MODE) GC_ASSERT(RVALUE_OLD_P(parent));
-
- if (!RVALUE_OLD_P(child)) {
- if (!RVALUE_REMEMBERED(parent) &&
- !RVALUE_REMEMBERED(child) &&
- !RVALUE_UNCOLLECTIBLE(child)) {
- fprintf(stderr, "verify_internal_consistency_reachable_i: WB miss (O->Y) %s -> %s\n", obj_info(parent), obj_info(child));
- data->err_count++;
- }
- }
-}
-
-static void
-check_color_i(const VALUE child, void *ptr)
-{
- struct verify_internal_consistency_struct *data = (struct verify_internal_consistency_struct *)ptr;
- const VALUE parent = data->parent;
-
- if (!RVALUE_WB_UNPROTECTED(parent) && RVALUE_WHITE_P(child)) {
- fprintf(stderr, "verify_internal_consistency_reachable_i: WB miss (B->W) - %s -> %s\n",
- obj_info(parent), obj_info(child));
- data->err_count++;
- }
-}
-
-static void
-check_children_i(const VALUE child, void *ptr)
-{
- struct verify_internal_consistency_struct *data = (struct verify_internal_consistency_struct *)ptr;
- if (check_rvalue_consistency_force(child, FALSE) != 0) {
- fprintf(stderr, "check_children_i: %s has error (referenced from %s)",
- obj_info(child), obj_info(data->parent));
- rb_print_backtrace(stderr); /* C backtrace will help to debug */
-
- data->err_count++;
- }
-}
-
-static int
-verify_internal_consistency_i(void *page_start, void *page_end, size_t stride,
- struct verify_internal_consistency_struct *data)
-{
- VALUE obj;
- rb_objspace_t *objspace = data->objspace;
-
- for (obj = (VALUE)page_start; obj != (VALUE)page_end; obj += stride) {
- void *poisoned = asan_unpoison_object_temporary(obj);
-
- if (is_live_object(objspace, obj)) {
- /* count objects */
- data->live_object_count++;
- data->parent = obj;
-
- /* Normally, we don't expect T_MOVED objects to be in the heap.
- * But they can stay alive on the stack, */
- if (!gc_object_moved_p(objspace, obj)) {
- /* moved slots don't have children */
- rb_objspace_reachable_objects_from(obj, check_children_i, (void *)data);
- }
-
- /* 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++;
-
- if (!is_marking(objspace) && RVALUE_OLD_P(obj)) {
- /* reachable objects from an oldgen object should be old or (young with remember) */
- data->parent = obj;
- rb_objspace_reachable_objects_from(obj, check_generation_i, (void *)data);
- }
-
- if (is_incremental_marking(objspace)) {
- if (RVALUE_BLACK_P(obj)) {
- /* reachable objects from black objects should be black or grey objects */
- data->parent = obj;
- rb_objspace_reachable_objects_from(obj, check_color_i, (void *)data);
- }
- }
+ case T_OBJECT:
+ if (rb_shape_obj_too_complex_p(obj)) {
+ return sizeof(struct RObject);
}
else {
- if (BUILTIN_TYPE(obj) == T_ZOMBIE) {
- data->zombie_object_count++;
-
- if ((RBASIC(obj)->flags & ~ZOMBIE_OBJ_KEPT_FLAGS) != T_ZOMBIE) {
- fprintf(stderr, "verify_internal_consistency_i: T_ZOMBIE has extra flags set: %s\n",
- obj_info(obj));
- data->err_count++;
- }
-
- if (!!FL_TEST(obj, FL_FINALIZE) != !!st_is_member(finalizer_table, obj)) {
- fprintf(stderr, "verify_internal_consistency_i: FL_FINALIZE %s but %s finalizer_table: %s\n",
- FL_TEST(obj, FL_FINALIZE) ? "set" : "not set", st_is_member(finalizer_table, obj) ? "in" : "not in",
- obj_info(obj));
- data->err_count++;
- }
+ size_t size = rb_obj_embedded_size(ROBJECT_FIELDS_CAPACITY(obj));
+ if (rb_gc_size_allocatable_p(size)) {
+ return size;
}
- }
- if (poisoned) {
- GC_ASSERT(BUILTIN_TYPE(obj) == T_NONE);
- asan_poison_object(obj);
- }
- }
-
- return 0;
-}
-
-static int
-gc_verify_heap_page(rb_objspace_t *objspace, struct heap_page *page, VALUE obj)
-{
- 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;
-
- short slot_size = page->slot_size;
- uintptr_t start = (uintptr_t)page->start;
- uintptr_t end = start + page->total_slots * slot_size;
-
- for (uintptr_t ptr = start; ptr < end; ptr += slot_size) {
- VALUE val = (VALUE)ptr;
- void *poisoned = asan_unpoison_object_temporary(val);
- enum ruby_value_type type = BUILTIN_TYPE(val);
-
- if (type == T_NONE) free_objects++;
- if (type == T_ZOMBIE) zombie_objects++;
- if (RVALUE_PAGE_UNCOLLECTIBLE(page, val) && RVALUE_PAGE_WB_UNPROTECTED(page, val)) {
- has_remembered_shady = TRUE;
- }
- if (RVALUE_PAGE_MARKING(page, val)) {
- has_remembered_old = TRUE;
- remembered_old_objects++;
- }
-
- if (poisoned) {
- GC_ASSERT(BUILTIN_TYPE(val) == T_NONE);
- asan_poison_object(val);
- }
- }
-
- if (!is_incremental_marking(objspace) &&
- page->flags.has_remembered_objects == FALSE && has_remembered_old == TRUE) {
-
- for (uintptr_t ptr = start; ptr < end; ptr += slot_size) {
- VALUE val = (VALUE)ptr;
- if (RVALUE_PAGE_MARKING(page, val)) {
- fprintf(stderr, "marking -> %s\n", obj_info(val));
- }
- }
- rb_bug("page %p's has_remembered_objects should be false, but there are remembered old objects (%d). %s",
- (void *)page, remembered_old_objects, obj ? obj_info(obj) : "");
- }
-
- if (page->flags.has_uncollectible_wb_unprotected_objects == FALSE && has_remembered_shady == TRUE) {
- rb_bug("page %p's has_remembered_shady should be false, but there are remembered shady objects. %s",
- (void *)page, obj ? obj_info(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", (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", (void *)page, page->final_slots, zombie_objects);
- }
-
- return remembered_old_objects;
-}
-
-static int
-gc_verify_heap_pages_(rb_objspace_t *objspace, struct ccan_list_head *head)
-{
- int remembered_old_objects = 0;
- struct heap_page *page = 0;
-
- ccan_list_for_each(head, page, page_node) {
- asan_unlock_freelist(page);
- RVALUE *p = page->freelist;
- while (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(prev);
- }
- asan_lock_freelist(page);
-
- if (page->flags.has_remembered_objects == FALSE) {
- remembered_old_objects += gc_verify_heap_page(objspace, page, Qfalse);
- }
- }
-
- return remembered_old_objects;
-}
-
-static int
-gc_verify_heap_pages(rb_objspace_t *objspace)
-{
- int remembered_old_objects = 0;
- 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;
-}
-
-/*
- * call-seq:
- * GC.verify_internal_consistency -> nil
- *
- * Verify internal consistency.
- *
- * This method is implementation specific.
- * Now this method checks generational consistency
- * if RGenGC is supported.
- */
-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)
-{
- struct verify_internal_consistency_struct data = {0};
-
- data.objspace = 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;
-
- 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
- objspace->rgengc.error_count = data.err_count;
- gc_marks_check(objspace, NULL, NULL);
- allrefs_dump(objspace);
-#endif
- rb_bug("gc_verify_internal_consistency: found internal inconsistency.");
- }
-
- /* check heap_page status */
- gc_verify_heap_pages(objspace);
-
- /* check counters */
-
- 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: %"PRIdSIZE", total_freed_objects: %"PRIdSIZE"\n",
- heap_pages_final_slots, total_freed_objects(objspace));
- rb_bug("inconsistent live slot number: expect %"PRIuSIZE", but %"PRIuSIZE".",
- objspace_live_slots(objspace), data.live_object_count);
- }
- }
-
- 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);
- }
- if (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);
- }
- }
-
- if (!finalizing) {
- size_t list_count = 0;
-
- {
- VALUE z = heap_pages_deferred_final;
- while (z) {
- list_count++;
- z = RZOMBIE(z)->next;
+ else {
+ return sizeof(struct RObject);
}
}
- 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);
- }
- }
-
- 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
+ case T_STRING:
{
- gc_verify_internal_consistency_(objspace);
- }
- during_gc = prev_during_gc;
- }
- RB_VM_LOCK_LEAVE();
-}
-
-void
-rb_gc_verify_internal_consistency(void)
-{
- gc_verify_internal_consistency(&rb_objspace);
-}
-
-static void
-heap_move_pooled_pages_to_free_pages(rb_heap_t *heap)
-{
- if (heap->pooled_pages) {
- if (heap->free_pages) {
- struct heap_page *free_pages_tail = heap->free_pages;
- while (free_pages_tail->free_next) {
- free_pages_tail = free_pages_tail->free_next;
- }
- free_pages_tail->free_next = heap->pooled_pages;
- }
- else {
- heap->free_pages = heap->pooled_pages;
- }
-
- heap->pooled_pages = NULL;
- }
-}
-
-/* marks */
-
-static void
-gc_marks_start(rb_objspace_t *objspace, int full_mark)
-{
- /* start marking */
- gc_report(1, objspace, "gc_marks_start: (%s)\n", full_mark ? "full" : "minor");
- gc_mode_transition(objspace, gc_mode_marking);
-
- if (full_mark) {
- size_t incremental_marking_steps = (objspace->rincgc.pooled_slots / INCREMENTAL_MARK_STEP_ALLOCATIONS) + 1;
- objspace->rincgc.step_slots = (objspace->marked_slots * 2) / incremental_marking_steps;
-
- 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);
- 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;
-
- 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);
- rgengc_mark_and_rememberset_clear(objspace, heap);
- heap_move_pooled_pages_to_free_pages(heap);
-
- if (objspace->flags.during_compacting) {
- struct heap_page *page = NULL;
-
- ccan_list_for_each(&heap->pages, page, page_node) {
- page->pinned_slots = 0;
- }
- }
- }
- }
- 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++;
-
- for (int i = 0; i < SIZE_POOL_COUNT; i++) {
- rgengc_rememberset_mark(objspace, SIZE_POOL_EDEN_HEAP(&size_pools[i]));
- }
- }
-
- gc_mark_roots(objspace, NULL);
-
- gc_report(1, objspace, "gc_marks_start: (%s) end, stack in %"PRIdSIZE"\n",
- full_mark ? "full" : "minor", mark_stack_size(&objspace->mark_stack));
-}
-
-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);
+ size_t size = rb_str_size_as_embedded(obj);
+ if (rb_gc_size_allocatable_p(size)) {
+ return size;
}
- p += BASE_SLOT_SIZE;
- bits >>= 1;
- } while (bits);
- }
-}
-
-static void
-gc_marks_wb_unprotected_objects(rb_objspace_t *objspace, rb_heap_t *heap)
-{
- struct heap_page *page = 0;
-
- ccan_list_for_each(&heap->pages, page, page_node) {
- bits_t *mark_bits = page->mark_bits;
- bits_t *wbun_bits = page->wb_unprotected_bits;
- uintptr_t p = page->start;
- size_t j;
-
- bits_t bits = mark_bits[0] & wbun_bits[0];
- bits >>= NUM_IN_PAGE(p);
- gc_marks_wb_unprotected_objects_plane(objspace, p, bits);
- p += (BITS_BITLENGTH - NUM_IN_PAGE(p)) * BASE_SLOT_SIZE;
-
- for (j=1; j<HEAP_PAGE_BITMAP_LIMIT; j++) {
- bits_t bits = mark_bits[j] & wbun_bits[j];
-
- gc_marks_wb_unprotected_objects_plane(objspace, p, bits);
- p += BITS_BITLENGTH * BASE_SLOT_SIZE;
- }
- }
-
- gc_mark_stacked_objects_all(objspace);
-}
-
-static void
-gc_update_weak_references(rb_objspace_t *objspace)
-{
- size_t retained_weak_references_count = 0;
- VALUE **ptr_ptr;
- rb_darray_foreach(objspace->weak_references, i, ptr_ptr) {
- if (!*ptr_ptr) continue;
-
- VALUE obj = **ptr_ptr;
-
- if (RB_SPECIAL_CONST_P(obj)) continue;
-
- if (!RVALUE_MARKED(obj)) {
- **ptr_ptr = Qundef;
- }
- else {
- retained_weak_references_count++;
- }
- }
-
- objspace->profile.retained_weak_references_count = retained_weak_references_count;
-
- rb_darray_clear(objspace->weak_references);
-
- DURING_GC_COULD_MALLOC_REGION_START();
- {
- rb_darray_resize_capa(&objspace->weak_references, retained_weak_references_count);
- }
- DURING_GC_COULD_MALLOC_REGION_END();
-}
-
-static void
-gc_marks_finish(rb_objspace_t *objspace)
-{
- /* finish incremental GC */
- if (is_incremental_marking(objspace)) {
- if (RGENGC_CHECK_MODE && is_mark_stack_empty(&objspace->mark_stack) == 0) {
- rb_bug("gc_marks_finish: mark stack is not empty (%"PRIdSIZE").",
- mark_stack_size(&objspace->mark_stack));
- }
-
- gc_mark_roots(objspace, 0);
- while (gc_mark_stacked_objects_incremental(objspace, INT_MAX) == false);
-
-#if RGENGC_CHECK_MODE >= 2
- if (gc_verify_heap_pages(objspace) != 0) {
- rb_bug("gc_marks_finish (incremental): there are remembered old objects.");
- }
-#endif
-
- objspace->flags.during_incremental_marking = FALSE;
- /* check children of all marked wb-unprotected objects */
- for (int i = 0; i < SIZE_POOL_COUNT; i++) {
- gc_marks_wb_unprotected_objects(objspace, SIZE_POOL_EDEN_HEAP(&size_pools[i]));
- }
- }
-
- gc_update_weak_references(objspace);
-
-#if RGENGC_CHECK_MODE >= 2
- gc_verify_internal_consistency(objspace);
-#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 */
- 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_eden_total_slots(objspace) >= objspace->marked_slots);
-
- /* Setup freeable slots. */
- size_t total_init_slots = 0;
- for (int i = 0; i < SIZE_POOL_COUNT; i++) {
- total_init_slots += gc_params.size_pool_init_slots[i] * r_mul;
- }
-
- if (max_free_slots < total_init_slots) {
- max_free_slots = total_init_slots;
- }
-
- if (sweep_slots > max_free_slots) {
- heap_pages_freeable_pages = (sweep_slots - max_free_slots) / HEAP_PAGE_OBJ_LIMIT;
- }
- else {
- heap_pages_freeable_pages = 0;
- }
-
- /* 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 (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; */
- }
- else {
- gc_report(1, objspace, "gc_marks_finish: next is full GC!!)\n");
- gc_needs_major_flags |= GPR_FLAG_MAJOR_BY_NOFREE;
- }
+ else {
+ return sizeof(struct RString);
}
}
- if (full_marking) {
- /* 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 = MAX(
- (size_t)(objspace->rgengc.uncollectible_wb_unprotected_objects * r),
- (size_t)(objspace->rgengc.old_objects * gc_params.uncollectible_wb_unprotected_objects_limit_ratio)
- );
- objspace->rgengc.old_objects_limit = (size_t)(objspace->rgengc.old_objects * r);
- }
-
- if (objspace->rgengc.uncollectible_wb_unprotected_objects > objspace->rgengc.uncollectible_wb_unprotected_objects_limit) {
- gc_needs_major_flags |= GPR_FLAG_MAJOR_BY_SHADY;
- }
- if (objspace->rgengc.old_objects > objspace->rgengc.old_objects_limit) {
- gc_needs_major_flags |= GPR_FLAG_MAJOR_BY_OLDGEN;
- }
- if (RGENGC_FORCE_MAJOR_GC) {
- gc_needs_major_flags = GPR_FLAG_MAJOR_BY_FORCE;
- }
-
- 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),
- gc_needs_major_flags ? "major" : "minor");
- }
-
- rb_ractor_finish_marking();
-
- gc_event_hook(objspace, RUBY_INTERNAL_EVENT_GC_END_MARK, 0);
-}
-
-static bool
-gc_compact_heap_cursors_met_p(rb_heap_t *heap)
-{
- return heap->sweeping_page == heap->compact_cursor;
-}
-
-static rb_size_pool_t *
-gc_compact_destination_pool(rb_objspace_t *objspace, rb_size_pool_t *src_pool, VALUE src)
-{
- size_t obj_size;
- size_t idx = 0;
-
- switch (BUILTIN_TYPE(src)) {
- case T_ARRAY:
- obj_size = rb_ary_size_as_embedded(src);
- break;
-
- case T_OBJECT:
- if (rb_shape_obj_too_complex(src)) {
- return &size_pools[0];
- }
- else {
- obj_size = rb_obj_embedded_size(ROBJECT_IV_CAPACITY(src));
- }
- break;
-
- case T_STRING:
- obj_size = rb_str_size_as_embedded(src);
- break;
-
case T_HASH:
- obj_size = sizeof(struct RHash) + (RHASH_ST_TABLE_P(src) ? sizeof(st_table) : sizeof(ar_table));
- break;
+ return sizeof(struct RHash) + (RHASH_ST_TABLE_P(obj) ? sizeof(st_table) : sizeof(ar_table));
default:
- return src_pool;
- }
-
- if (rb_gc_size_allocatable_p(obj_size)){
- idx = rb_gc_size_pool_id_for_size(obj_size);
- }
- return &size_pools[idx];
-}
-
-static bool
-gc_compact_move(rb_objspace_t *objspace, rb_heap_t *heap, rb_size_pool_t *size_pool, VALUE src)
-{
- GC_ASSERT(BUILTIN_TYPE(src) != T_MOVED);
- GC_ASSERT(gc_is_moveable_obj(objspace, src));
-
- rb_size_pool_t *dest_pool = gc_compact_destination_pool(objspace, size_pool, src);
- rb_heap_t *dheap = SIZE_POOL_EDEN_HEAP(dest_pool);
- rb_shape_t *new_shape = NULL;
- rb_shape_t *orig_shape = NULL;
-
- if (gc_compact_heap_cursors_met_p(dheap)) {
- return dheap != heap;
- }
-
- if (RB_TYPE_P(src, T_OBJECT)) {
- orig_shape = rb_shape_get_shape(src);
- if (dheap != heap && !rb_shape_obj_too_complex(src)) {
- rb_shape_t *initial_shape = rb_shape_get_shape_by_id((shape_id_t)((dest_pool - size_pools) + FIRST_T_OBJECT_SHAPE_ID));
- new_shape = rb_shape_traverse_from_new_root(initial_shape, orig_shape);
-
- if (!new_shape) {
- dest_pool = size_pool;
- dheap = heap;
- }
- }
- }
-
- while (!try_move(objspace, dheap, dheap->free_pages, src)) {
- struct gc_sweep_context ctx = {
- .page = dheap->sweeping_page,
- .final_slots = 0,
- .freed_slots = 0,
- .empty_slots = 0,
- };
-
- /* The page of src could be partially compacted, so it may contain
- * T_MOVED. Sweeping a page may read objects on this page, so we
- * need to lock the page. */
- lock_page_body(objspace, GET_PAGE_BODY(src));
- gc_sweep_page(objspace, dheap, &ctx);
- unlock_page_body(objspace, GET_PAGE_BODY(src));
-
- if (dheap->sweeping_page->free_slots > 0) {
- heap_add_freepage(dheap, dheap->sweeping_page);
- }
-
- dheap->sweeping_page = ccan_list_next(&dheap->pages, dheap->sweeping_page, page_node);
- if (gc_compact_heap_cursors_met_p(dheap)) {
- return dheap != heap;
- }
- }
-
- if (orig_shape) {
- if (new_shape) {
- VALUE dest = rb_gc_location(src);
- rb_shape_set_shape(dest, new_shape);
- }
- RMOVED(src)->original_shape_id = rb_shape_id(orig_shape);
- }
-
- return true;
-}
-
-static bool
-gc_compact_plane(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap, uintptr_t p, bits_t bitset, struct heap_page *page)
-{
- short slot_size = page->slot_size;
- short slot_bits = slot_size / BASE_SLOT_SIZE;
- GC_ASSERT(slot_bits > 0);
-
- do {
- VALUE vp = (VALUE)p;
- GC_ASSERT(vp % BASE_SLOT_SIZE == 0);
-
- if (bitset & 1) {
- objspace->rcompactor.considered_count_table[BUILTIN_TYPE(vp)]++;
-
- if (gc_is_moveable_obj(objspace, vp)) {
- if (!gc_compact_move(objspace, heap, size_pool, vp)) {
- //the cursors met. bubble up
- return false;
- }
- }
- }
- p += slot_size;
- bitset >>= slot_bits;
- } while (bitset);
-
- return true;
-}
-
-// Iterate up all the objects in page, moving them to where they want to go
-static bool
-gc_compact_page(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap, struct heap_page *page)
-{
- GC_ASSERT(page == heap->compact_cursor);
-
- bits_t *mark_bits, *pin_bits;
- bits_t bitset;
- uintptr_t p = page->start;
-
- mark_bits = page->mark_bits;
- pin_bits = page->pinned_bits;
-
- // objects that can be moved are marked and not pinned
- bitset = (mark_bits[0] & ~pin_bits[0]);
- bitset >>= NUM_IN_PAGE(p);
- if (bitset) {
- if (!gc_compact_plane(objspace, size_pool, heap, (uintptr_t)p, bitset, page))
- return false;
- }
- p += (BITS_BITLENGTH - NUM_IN_PAGE(p)) * BASE_SLOT_SIZE;
-
- for (int j = 1; j < HEAP_PAGE_BITMAP_LIMIT; j++) {
- bitset = (mark_bits[j] & ~pin_bits[j]);
- if (bitset) {
- if (!gc_compact_plane(objspace, size_pool, heap, (uintptr_t)p, bitset, page))
- return false;
- }
- p += BITS_BITLENGTH * BASE_SLOT_SIZE;
- }
-
- return true;
-}
-
-static bool
-gc_compact_all_compacted_p(rb_objspace_t *objspace)
-{
- 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);
-
- if (heap->total_pages > 0 &&
- !gc_compact_heap_cursors_met_p(heap)) {
- return false;
- }
- }
-
- return true;
-}
-
-static void
-gc_sweep_compact(rb_objspace_t *objspace)
-{
- gc_compact_start(objspace);
-#if RGENGC_CHECK_MODE >= 2
- gc_verify_internal_consistency(objspace);
-#endif
-
- while (!gc_compact_all_compacted_p(objspace)) {
- 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);
-
- if (gc_compact_heap_cursors_met_p(heap)) {
- continue;
- }
-
- struct heap_page *start_page = heap->compact_cursor;
-
- if (!gc_compact_page(objspace, size_pool, heap, start_page)) {
- lock_page_body(objspace, GET_PAGE_BODY(start_page->start));
-
- continue;
- }
-
- // If we get here, we've finished moving all objects on the compact_cursor page
- // So we can lock it and move the cursor on to the next one.
- lock_page_body(objspace, GET_PAGE_BODY(start_page->start));
- heap->compact_cursor = ccan_list_prev(&heap->pages, heap->compact_cursor, page_node);
- }
- }
-
- gc_compact_finish(objspace);
-
-#if RGENGC_CHECK_MODE >= 2
- gc_verify_internal_consistency(objspace);
-#endif
-}
-
-static void
-gc_marks_rest(rb_objspace_t *objspace)
-{
- gc_report(1, objspace, "gc_marks_rest\n");
-
- for (int i = 0; i < SIZE_POOL_COUNT; i++) {
- SIZE_POOL_EDEN_HEAP(&size_pools[i])->pooled_pages = NULL;
- }
-
- if (is_incremental_marking(objspace)) {
- while (gc_mark_stacked_objects_incremental(objspace, INT_MAX) == FALSE);
- }
- else {
- gc_mark_stacked_objects_all(objspace);
- }
-
- gc_marks_finish(objspace);
-}
-
-static bool
-gc_marks_step(rb_objspace_t *objspace, size_t slots)
-{
- bool marking_finished = false;
-
- GC_ASSERT(is_marking(objspace));
- if (gc_mark_stacked_objects_incremental(objspace, slots)) {
- gc_marks_finish(objspace);
-
- marking_finished = true;
- }
-
- return marking_finished;
-}
-
-static bool
-gc_marks_continue(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap)
-{
- GC_ASSERT(dont_gc_val() == FALSE);
- bool marking_finished = true;
-
- gc_marking_enter(objspace);
-
- if (heap->free_pages) {
- gc_report(2, objspace, "gc_marks_continue: has pooled pages");
-
- marking_finished = 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));
- size_pool->force_incremental_marking_finish_count++;
- gc_marks_rest(objspace);
- }
-
- gc_marking_exit(objspace);
-
- return marking_finished;
-}
-
-static bool
-gc_marks(rb_objspace_t *objspace, int full_mark)
-{
- gc_prof_mark_timer_start(objspace);
- gc_marking_enter(objspace);
-
- bool marking_finished = false;
-
- /* setup marking */
-
- gc_marks_start(objspace, full_mark);
- if (!is_incremental_marking(objspace)) {
- gc_marks_rest(objspace);
- marking_finished = true;
- }
-
-#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
-
- gc_marking_exit(objspace);
- gc_prof_mark_timer_stop(objspace);
-
- return marking_finished;
-}
-
-/* RGENGC */
-
-static void
-gc_report_body(int level, rb_objspace_t *objspace, const char *fmt, ...)
-{
- if (level <= RGENGC_DEBUG) {
- char buf[1024];
- FILE *out = stderr;
- va_list args;
- const char *status = " ";
-
- if (during_gc) {
- status = is_full_marking(objspace) ? "+" : "-";
- }
- else {
- if (is_lazy_sweeping(objspace)) {
- status = "S";
- }
- if (is_incremental_marking(objspace)) {
- status = "M";
- }
- }
-
- va_start(args, fmt);
- vsnprintf(buf, 1024, fmt, args);
- va_end(args);
-
- fprintf(out, "%s|", status);
- fputs(buf, out);
- }
-}
-
-/* bit operations */
-
-static int
-rgengc_remembersetbits_set(rb_objspace_t *objspace, VALUE obj)
-{
- struct heap_page *page = GET_HEAP_PAGE(obj);
- bits_t *bits = &page->remembered_bits[0];
-
- if (MARKED_IN_BITMAP(bits, obj)) {
- return FALSE;
- }
- else {
- page->flags.has_remembered_objects = TRUE;
- MARK_IN_BITMAP(bits, obj);
- return TRUE;
- }
-}
-
-/* wb, etc */
-
-/* return FALSE if already remembered */
-static int
-rgengc_remember(rb_objspace_t *objspace, VALUE obj)
-{
- gc_report(6, objspace, "rgengc_remember: %s %s\n", obj_info(obj),
- RVALUE_REMEMBERED(obj) ? "was already remembered" : "is remembered now");
-
- check_rvalue_consistency(obj);
-
- if (RGENGC_CHECK_MODE) {
- if (RVALUE_WB_UNPROTECTED(obj)) rb_bug("rgengc_remember: %s is not wb protected.", obj_info(obj));
- }
-
-#if RGENGC_PROFILE > 0
- if (!RVALUE_REMEMBERED(obj)) {
- if (RVALUE_WB_UNPROTECTED(obj) == 0) {
- objspace->profile.total_remembered_normal_object_count++;
-#if RGENGC_PROFILE >= 2
- objspace->profile.remembered_normal_object_count_types[BUILTIN_TYPE(obj)]++;
-#endif
- }
- }
-#endif /* RGENGC_PROFILE > 0 */
-
- return rgengc_remembersetbits_set(objspace, obj);
-}
-
-#ifndef PROFILE_REMEMBERSET_MARK
-#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 += BASE_SLOT_SIZE;
- bitset >>= 1;
- } while (bitset);
- }
-}
-
-static void
-rgengc_rememberset_mark(rb_objspace_t *objspace, rb_heap_t *heap)
-{
- size_t j;
- struct heap_page *page = 0;
-#if PROFILE_REMEMBERSET_MARK
- int has_old = 0, has_shady = 0, has_both = 0, skip = 0;
-#endif
- gc_report(1, objspace, "rgengc_rememberset_mark: start\n");
-
- ccan_list_for_each(&heap->pages, page, page_node) {
- if (page->flags.has_remembered_objects | page->flags.has_uncollectible_wb_unprotected_objects) {
- uintptr_t p = page->start;
- bits_t bitset, bits[HEAP_PAGE_BITMAP_LIMIT];
- bits_t *remembered_bits = page->remembered_bits;
- bits_t *uncollectible_bits = page->uncollectible_bits;
- bits_t *wb_unprotected_bits = page->wb_unprotected_bits;
-#if PROFILE_REMEMBERSET_MARK
- if (page->flags.has_remembered_objects && page->flags.has_uncollectible_wb_unprotected_objects) has_both++;
- else if (page->flags.has_remembered_objects) has_old++;
- else if (page->flags.has_uncollectible_wb_unprotected_objects) has_shady++;
-#endif
- for (j=0; j<HEAP_PAGE_BITMAP_LIMIT; j++) {
- bits[j] = remembered_bits[j] | (uncollectible_bits[j] & wb_unprotected_bits[j]);
- remembered_bits[j] = 0;
- }
- page->flags.has_remembered_objects = FALSE;
-
- bitset = bits[0];
- bitset >>= NUM_IN_PAGE(p);
- rgengc_rememberset_mark_plane(objspace, p, bitset);
- p += (BITS_BITLENGTH - NUM_IN_PAGE(p)) * BASE_SLOT_SIZE;
-
- for (j=1; j < HEAP_PAGE_BITMAP_LIMIT; j++) {
- bitset = bits[j];
- rgengc_rememberset_mark_plane(objspace, p, bitset);
- p += BITS_BITLENGTH * BASE_SLOT_SIZE;
- }
- }
-#if PROFILE_REMEMBERSET_MARK
- else {
- skip++;
- }
-#endif
- }
-
-#if PROFILE_REMEMBERSET_MARK
- fprintf(stderr, "%d\t%d\t%d\t%d\n", has_both, has_old, has_shady, skip);
-#endif
- gc_report(1, objspace, "rgengc_rememberset_mark: finished\n");
-}
-
-static void
-rgengc_mark_and_rememberset_clear(rb_objspace_t *objspace, rb_heap_t *heap)
-{
- struct heap_page *page = 0;
-
- ccan_list_for_each(&heap->pages, page, page_node) {
- memset(&page->mark_bits[0], 0, HEAP_PAGE_BITMAP_SIZE);
- memset(&page->uncollectible_bits[0], 0, HEAP_PAGE_BITMAP_SIZE);
- memset(&page->marking_bits[0], 0, HEAP_PAGE_BITMAP_SIZE);
- memset(&page->remembered_bits[0], 0, HEAP_PAGE_BITMAP_SIZE);
- memset(&page->pinned_bits[0], 0, HEAP_PAGE_BITMAP_SIZE);
- page->flags.has_uncollectible_wb_unprotected_objects = FALSE;
- page->flags.has_remembered_objects = FALSE;
- }
-}
-
-/* RGENGC: APIs */
-
-NOINLINE(static void gc_writebarrier_generational(VALUE a, VALUE b, rb_objspace_t *objspace));
-
-static void
-gc_writebarrier_generational(VALUE a, VALUE b, rb_objspace_t *objspace)
-{
- if (RGENGC_CHECK_MODE) {
- if (!RVALUE_OLD_P(a)) rb_bug("gc_writebarrier_generational: %s is not an old object.", obj_info(a));
- if ( RVALUE_OLD_P(b)) rb_bug("gc_writebarrier_generational: %s is an old object.", obj_info(b));
- if (is_incremental_marking(objspace)) rb_bug("gc_writebarrier_generational: called while incremental marking: %s -> %s", obj_info(a), obj_info(b));
- }
-
- /* mark `a' and remember (default behavior) */
- if (!RVALUE_REMEMBERED(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));
- }
-
- check_rvalue_consistency(a);
- check_rvalue_consistency(b);
-}
-
-static void
-gc_mark_from(rb_objspace_t *objspace, VALUE obj, VALUE parent)
-{
- gc_mark_set_parent(objspace, parent);
- rgengc_check_relation(objspace, obj);
- if (gc_mark_set(objspace, obj) == FALSE) return;
- gc_aging(objspace, obj);
- gc_grey(objspace, obj);
-}
-
-NOINLINE(static void gc_writebarrier_incremental(VALUE a, VALUE b, rb_objspace_t *objspace));
-
-static void
-gc_writebarrier_incremental(VALUE a, VALUE b, rb_objspace_t *objspace)
-{
- gc_report(2, objspace, "gc_writebarrier_incremental: [LG] %p -> %s\n", (void *)a, obj_info(b));
-
- if (RVALUE_BLACK_P(a)) {
- if (RVALUE_WHITE_P(b)) {
- if (!RVALUE_WB_UNPROTECTED(a)) {
- gc_report(2, objspace, "gc_writebarrier_incremental: [IN] %p -> %s\n", (void *)a, obj_info(b));
- gc_mark_from(objspace, b, a);
- }
- }
- else if (RVALUE_OLD_P(a) && !RVALUE_OLD_P(b)) {
- rgengc_remember(objspace, a);
- }
-
- if (UNLIKELY(objspace->flags.during_compacting)) {
- MARK_IN_BITMAP(GET_HEAP_PINNED_BITS(b), b);
- }
+ return 0;
}
}
void
rb_gc_writebarrier(VALUE a, VALUE b)
{
- rb_objspace_t *objspace = &rb_objspace;
-
- if (RGENGC_CHECK_MODE) {
- if (SPECIAL_CONST_P(a)) rb_bug("rb_gc_writebarrier: a is special const: %"PRIxVALUE, a);
- if (SPECIAL_CONST_P(b)) rb_bug("rb_gc_writebarrier: b is special const: %"PRIxVALUE, b);
- }
-
- retry:
- if (!is_incremental_marking(objspace)) {
- if (!RVALUE_OLD_P(a) || RVALUE_OLD_P(b)) {
- // do nothing
- }
- else {
- gc_writebarrier_generational(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;
+ rb_gc_impl_writebarrier(rb_gc_get_objspace(), a, b);
}
void
rb_gc_writebarrier_unprotect(VALUE obj)
{
- if (RVALUE_WB_UNPROTECTED(obj)) {
- return;
- }
- else {
- rb_objspace_t *objspace = &rb_objspace;
-
- gc_report(2, objspace, "rb_gc_writebarrier_unprotect: %s %s\n", obj_info(obj),
- RVALUE_REMEMBERED(obj) ? " (already remembered)" : "");
-
- RB_VM_LOCK_ENTER_NO_BARRIER();
- {
- if (RVALUE_OLD_P(obj)) {
- gc_report(1, objspace, "rb_gc_writebarrier_unprotect: %s\n", obj_info(obj));
- RVALUE_DEMOTE(objspace, obj);
- gc_mark_set(objspace, obj);
- gc_remember_unprotected(objspace, obj);
-
-#if RGENGC_PROFILE
- objspace->profile.total_shade_operation_count++;
-#if RGENGC_PROFILE >= 2
- objspace->profile.shade_operation_count_types[BUILTIN_TYPE(obj)]++;
-#endif /* RGENGC_PROFILE >= 2 */
-#endif /* RGENGC_PROFILE */
- }
- else {
- RVALUE_AGE_RESET(obj);
- }
-
- RB_DEBUG_COUNTER_INC(obj_wb_unprotect);
- MARK_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(obj), obj);
- }
- RB_VM_LOCK_LEAVE_NO_BARRIER();
- }
+ rb_gc_impl_writebarrier_unprotect(rb_gc_get_objspace(), obj);
}
/*
@@ -8709,83 +3456,63 @@ rb_gc_writebarrier_unprotect(VALUE obj)
void
rb_gc_writebarrier_remember(VALUE obj)
{
- rb_objspace_t *objspace = &rb_objspace;
-
- gc_report(1, objspace, "rb_gc_writebarrier_remember: %s\n", obj_info(obj));
-
- if (is_incremental_marking(objspace)) {
- if (RVALUE_BLACK_P(obj)) {
- gc_grey(objspace, obj);
- }
- }
- else {
- if (RVALUE_OLD_P(obj)) {
- rgengc_remember(objspace, obj);
- }
- }
+ rb_gc_impl_writebarrier_remember(rb_gc_get_objspace(), obj);
}
void
rb_gc_copy_attributes(VALUE dest, VALUE obj)
{
- if (RVALUE_WB_UNPROTECTED(obj)) {
- rb_gc_writebarrier_unprotect(dest);
- }
- rb_gc_copy_finalizer(dest, obj);
+ rb_gc_impl_copy_attributes(rb_gc_get_objspace(), dest, obj);
}
-size_t
-rb_obj_gc_flags(VALUE obj, ID* flags, size_t max)
+int
+rb_gc_modular_gc_loaded_p(void)
{
- size_t n = 0;
- static ID ID_marked;
- static ID ID_wb_protected, ID_old, ID_marking, ID_uncollectible, ID_pinned;
+#if USE_MODULAR_GC
+ return rb_gc_functions.modular_gc_loaded_p;
+#else
+ return false;
+#endif
+}
- if (!ID_marked) {
-#define I(s) ID_##s = rb_intern(#s);
- I(marked);
- I(wb_protected);
- I(old);
- I(marking);
- I(uncollectible);
- I(pinned);
-#undef I
+const char *
+rb_gc_active_gc_name(void)
+{
+ const char *gc_name = rb_gc_impl_active_gc_name();
+
+ const size_t len = strlen(gc_name);
+ if (len > RB_GC_MAX_NAME_LEN) {
+ rb_bug("GC should have a name no more than %d chars long. Currently: %zu (%s)",
+ RB_GC_MAX_NAME_LEN, len, gc_name);
}
- if (RVALUE_WB_UNPROTECTED(obj) == 0 && n<max) flags[n++] = ID_wb_protected;
- if (RVALUE_OLD_P(obj) && n<max) flags[n++] = ID_old;
- if (RVALUE_UNCOLLECTIBLE(obj) && n<max) flags[n++] = ID_uncollectible;
- if (MARKED_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), obj) && n<max) flags[n++] = ID_marking;
- if (MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(obj), obj) && n<max) flags[n++] = ID_marked;
- if (MARKED_IN_BITMAP(GET_HEAP_PINNED_BITS(obj), obj) && n<max) flags[n++] = ID_pinned;
- return n;
+ return gc_name;
}
-/* GC */
-
-void
-rb_gc_ractor_newobj_cache_clear(rb_ractor_newobj_cache_t *newobj_cache)
+struct rb_gc_object_metadata_entry *
+rb_gc_object_metadata(VALUE obj)
{
- newobj_cache->incremental_mark_step_allocated_slots = 0;
-
- for (size_t size_pool_idx = 0; size_pool_idx < SIZE_POOL_COUNT; size_pool_idx++) {
- rb_ractor_newobj_size_pool_cache_t *cache = &newobj_cache->size_pool_caches[size_pool_idx];
+ return rb_gc_impl_object_metadata(rb_gc_get_objspace(), 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);
+/* GC */
- heap_page_freelist_append(page, freelist);
+void *
+rb_gc_ractor_cache_alloc(rb_ractor_t *ractor)
+{
+ return rb_gc_impl_ractor_cache_alloc(rb_gc_get_objspace(), ractor);
+}
- cache->using_page = NULL;
- cache->freelist = NULL;
- }
+void
+rb_gc_ractor_cache_free(void *cache)
+{
+ rb_gc_impl_ractor_cache_free(rb_gc_get_objspace(), cache);
}
void
rb_gc_register_mark_object(VALUE obj)
{
- if (!is_pointer_to_heap(&rb_objspace, (void *)obj))
+ if (!rb_gc_impl_pointer_to_heap_p(rb_gc_get_objspace(), (void *)obj))
return;
rb_vm_register_global_object(obj);
@@ -8844,1290 +3571,656 @@ rb_global_variable(VALUE *var)
rb_gc_register_address(var);
}
-enum {
- gc_stress_no_major,
- gc_stress_no_immediate_sweep,
- gc_stress_full_mark_after_malloc,
- gc_stress_max
-};
-
-#define gc_stress_full_mark_after_malloc_p() \
- (FIXNUM_P(ruby_gc_stress_mode) && (FIX2LONG(ruby_gc_stress_mode) & (1<<gc_stress_full_mark_after_malloc)))
-
-static void
-heap_ready_to_gc(rb_objspace_t *objspace, rb_size_pool_t *size_pool, rb_heap_t *heap)
+static VALUE
+gc_start_internal(rb_execution_context_t *ec, VALUE self, VALUE full_mark, VALUE immediate_mark, VALUE immediate_sweep, VALUE compact)
{
- 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);
- }
- }
+ rb_gc_impl_start(rb_gc_get_objspace(), RTEST(full_mark), RTEST(immediate_mark), RTEST(immediate_sweep), RTEST(compact));
+
+ return Qnil;
}
-static int
-ready_to_gc(rb_objspace_t *objspace)
+/*
+ * rb_objspace_each_objects() is special C API to walk through
+ * Ruby object space. This C API is too difficult to use it.
+ * To be frank, you should not use it. Or you need to read the
+ * source code of this function and understand what this function does.
+ *
+ * 'callback' will be called several times (the number of heap page,
+ * at current implementation) with:
+ * vstart: a pointer to the first living object of the heap_page.
+ * vend: a pointer to next to the valid heap_page area.
+ * stride: a distance to next VALUE.
+ *
+ * If callback() returns non-zero, the iteration will be stopped.
+ *
+ * This is a sample callback code to iterate liveness objects:
+ *
+ * static int
+ * sample_callback(void *vstart, void *vend, int stride, void *data)
+ * {
+ * VALUE v = (VALUE)vstart;
+ * for (; v != (VALUE)vend; v += stride) {
+ * if (!rb_objspace_internal_object_p(v)) { // liveness check
+ * // do something with live object 'v'
+ * }
+ * }
+ * return 0; // continue to iteration
+ * }
+ *
+ * Note: 'vstart' is not a top of heap_page. This point the first
+ * living object to grasp at least one object to avoid GC issue.
+ * This means that you can not walk through all Ruby object page
+ * including freed object page.
+ *
+ * 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.
+ */
+void
+rb_objspace_each_objects(int (*callback)(void *, void *, size_t, void *), void *data)
{
- 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;
- }
+ rb_gc_impl_each_objects(rb_gc_get_objspace(), callback, data);
}
static void
-gc_reset_malloc_info(rb_objspace_t *objspace, bool full_mark)
+gc_ref_update_array(void *objspace, VALUE v)
{
- gc_prof_set_malloc_info(objspace);
- {
- size_t inc = ATOMIC_SIZE_EXCHANGE(malloc_increase, 0);
- size_t old_limit = malloc_limit;
+ if (ARY_SHARED_P(v)) {
+ VALUE old_root = RARRAY(v)->as.heap.aux.shared_root;
- if (inc > malloc_limit) {
- malloc_limit = (size_t)(inc * gc_params.malloc_limit_growth_factor);
- if (malloc_limit > gc_params.malloc_limit_max) {
- malloc_limit = gc_params.malloc_limit_max;
- }
- }
- else {
- malloc_limit = (size_t)(malloc_limit * 0.98); /* magic number */
- if (malloc_limit < gc_params.malloc_limit_min) {
- malloc_limit = gc_params.malloc_limit_min;
- }
- }
+ UPDATE_IF_MOVED(objspace, RARRAY(v)->as.heap.aux.shared_root);
- if (0) {
- if (old_limit != malloc_limit) {
- fprintf(stderr, "[%"PRIuSIZE"] malloc_limit: %"PRIuSIZE" -> %"PRIuSIZE"\n",
- rb_gc_count(), old_limit, malloc_limit);
- }
- else {
- fprintf(stderr, "[%"PRIuSIZE"] malloc_limit: not changed (%"PRIuSIZE")\n",
- rb_gc_count(), malloc_limit);
- }
+ VALUE new_root = RARRAY(v)->as.heap.aux.shared_root;
+ // If the root is embedded and its location has changed
+ if (ARY_EMBED_P(new_root) && new_root != old_root) {
+ size_t offset = (size_t)(RARRAY(v)->as.heap.ptr - RARRAY(old_root)->as.ary);
+ GC_ASSERT(RARRAY(v)->as.heap.ptr >= RARRAY(old_root)->as.ary);
+ RARRAY(v)->as.heap.ptr = RARRAY(new_root)->as.ary + offset;
}
}
+ else {
+ long len = RARRAY_LEN(v);
- /* reset oldmalloc info */
-#if RGENGC_ESTIMATE_OLDMALLOC
- if (!full_mark) {
- if (objspace->rgengc.oldmalloc_increase > objspace->rgengc.oldmalloc_increase_limit) {
- gc_needs_major_flags |= GPR_FLAG_MAJOR_BY_OLDMALLOC;
- objspace->rgengc.oldmalloc_increase_limit =
- (size_t)(objspace->rgengc.oldmalloc_increase_limit * gc_params.oldmalloc_limit_growth_factor);
-
- if (objspace->rgengc.oldmalloc_increase_limit > gc_params.oldmalloc_limit_max) {
- objspace->rgengc.oldmalloc_increase_limit = gc_params.oldmalloc_limit_max;
+ if (len > 0) {
+ VALUE *ptr = (VALUE *)RARRAY_CONST_PTR(v);
+ for (long i = 0; i < len; i++) {
+ UPDATE_IF_MOVED(objspace, ptr[i]);
}
}
- if (0) fprintf(stderr, "%"PRIdSIZE"\t%d\t%"PRIuSIZE"\t%"PRIuSIZE"\t%"PRIdSIZE"\n",
- rb_gc_count(),
- gc_needs_major_flags,
- objspace->rgengc.oldmalloc_increase,
- objspace->rgengc.oldmalloc_increase_limit,
- gc_params.oldmalloc_limit_max);
- }
- else {
- /* major GC */
- objspace->rgengc.oldmalloc_increase = 0;
-
- if ((objspace->profile.latest_gc_info & GPR_FLAG_MAJOR_BY_OLDMALLOC) == 0) {
- objspace->rgengc.oldmalloc_increase_limit =
- (size_t)(objspace->rgengc.oldmalloc_increase_limit / ((gc_params.oldmalloc_limit_growth_factor - 1)/10 + 1));
- if (objspace->rgengc.oldmalloc_increase_limit < gc_params.oldmalloc_limit_min) {
- objspace->rgengc.oldmalloc_increase_limit = gc_params.oldmalloc_limit_min;
+ if (rb_gc_obj_slot_size(v) >= rb_ary_size_as_embedded(v)) {
+ if (rb_ary_embeddable_p(v)) {
+ rb_ary_make_embedded(v);
}
}
}
-#endif
-}
-
-static int
-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();
-#endif
-
- gc_rest(objspace);
-
-#if GC_PROFILE_MORE_DETAIL
- objspace->profile.prepare_time = getrusage_time() - objspace->profile.prepare_time;
-#endif
-
- ret = gc_start(objspace, reason);
- }
- RB_VM_LOCK_LEAVE();
-
- return ret;
-}
-
-static int
-gc_start(rb_objspace_t *objspace, unsigned int reason)
-{
- unsigned int do_full_mark = !!(reason & GPR_FLAG_FULL_MARK);
-
- /* reason may be clobbered, later, so keep set immediate_sweep here */
- objspace->flags.immediate_sweep = !!(reason & GPR_FLAG_IMMEDIATE_SWEEP);
-
- if (!heap_allocated_pages) return TRUE; /* 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(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
-
- if (ruby_gc_stressful) {
- int flag = FIXNUM_P(ruby_gc_stress_mode) ? FIX2INT(ruby_gc_stress_mode) : 0;
-
- if ((flag & (1<<gc_stress_no_major)) == 0) {
- do_full_mark = TRUE;
- }
-
- objspace->flags.immediate_sweep = !(flag & (1<<gc_stress_no_immediate_sweep));
- }
-
- if (gc_needs_major_flags) {
- reason |= gc_needs_major_flags;
- do_full_mark = TRUE;
- }
- else if (RGENGC_FORCE_MAJOR_GC) {
- reason = GPR_FLAG_MAJOR_BY_FORCE;
- do_full_mark = TRUE;
- }
-
- gc_needs_major_flags = GPR_FLAG_NONE;
-
- if (do_full_mark && (reason & GPR_FLAG_MAJOR_MASK) == 0) {
- reason |= GPR_FLAG_MAJOR_BY_FORCE; /* GC by CAPI, METHOD, and so on. */
- }
-
- if (objspace->flags.dont_incremental ||
- reason & GPR_FLAG_IMMEDIATE_MARK ||
- ruby_gc_stressful) {
- objspace->flags.during_incremental_marking = FALSE;
- }
- else {
- objspace->flags.during_incremental_marking = do_full_mark;
- }
-
- /* Explicitly enable compaction (GC.compact) */
- if (do_full_mark && ruby_enable_autocompact) {
- objspace->flags.during_compacting = TRUE;
-#if RGENGC_CHECK_MODE
- objspace->rcompactor.compare_func = ruby_autocompact_compare_func;
-#endif
- }
- else {
- objspace->flags.during_compacting = !!(reason & GPR_FLAG_COMPACT);
- }
-
- if (!GC_ENABLE_LAZY_SWEEP || objspace->flags.dont_incremental) {
- objspace->flags.immediate_sweep = TRUE;
- }
-
- if (objspace->flags.immediate_sweep) reason |= GPR_FLAG_IMMEDIATE_SWEEP;
-
- gc_report(1, objspace, "gc_start(reason: %x) => %u, %d, %d\n",
- reason,
- do_full_mark, !is_incremental_marking(objspace), objspace->flags.immediate_sweep);
-
-#if USE_DEBUG_COUNTER
- RB_DEBUG_COUNTER_INC(gc_count);
-
- if (reason & GPR_FLAG_MAJOR_MASK) {
- (void)RB_DEBUG_COUNTER_INC_IF(gc_major_nofree, reason & GPR_FLAG_MAJOR_BY_NOFREE);
- (void)RB_DEBUG_COUNTER_INC_IF(gc_major_oldgen, reason & GPR_FLAG_MAJOR_BY_OLDGEN);
- (void)RB_DEBUG_COUNTER_INC_IF(gc_major_shady, reason & GPR_FLAG_MAJOR_BY_SHADY);
- (void)RB_DEBUG_COUNTER_INC_IF(gc_major_force, reason & GPR_FLAG_MAJOR_BY_FORCE);
-#if RGENGC_ESTIMATE_OLDMALLOC
- (void)RB_DEBUG_COUNTER_INC_IF(gc_major_oldmalloc, reason & GPR_FLAG_MAJOR_BY_OLDMALLOC);
-#endif
- }
- else {
- (void)RB_DEBUG_COUNTER_INC_IF(gc_minor_newobj, reason & GPR_FLAG_NEWOBJ);
- (void)RB_DEBUG_COUNTER_INC_IF(gc_minor_malloc, reason & GPR_FLAG_MALLOC);
- (void)RB_DEBUG_COUNTER_INC_IF(gc_minor_method, reason & GPR_FLAG_METHOD);
- (void)RB_DEBUG_COUNTER_INC_IF(gc_minor_capi, reason & GPR_FLAG_CAPI);
- (void)RB_DEBUG_COUNTER_INC_IF(gc_minor_stress, reason & GPR_FLAG_STRESS);
- }
-#endif
-
- objspace->profile.count++;
- objspace->profile.latest_gc_info = reason;
- objspace->profile.total_allocated_objects_at_gc_start = total_allocated_objects(objspace);
- objspace->profile.heap_used_at_gc_start = heap_allocated_pages;
- objspace->profile.weak_references_count = 0;
- objspace->profile.retained_weak_references_count = 0;
- gc_prof_setup_new_record(objspace, reason);
- gc_reset_malloc_info(objspace, do_full_mark);
-
- gc_event_hook(objspace, RUBY_INTERNAL_EVENT_GC_START, 0 /* TODO: pass minor/immediate flag? */);
- GC_ASSERT(during_gc);
-
- gc_prof_timer_start(objspace);
- {
- if (gc_marks(objspace, do_full_mark)) {
- gc_sweep(objspace);
- }
- }
- gc_prof_timer_stop(objspace);
-
- gc_exit(objspace, gc_enter_event_start, &lock_lev);
- return TRUE;
}
static void
-gc_rest(rb_objspace_t *objspace)
+gc_ref_update_object(void *objspace, VALUE v)
{
- if (is_incremental_marking(objspace) || is_lazy_sweeping(objspace)) {
- unsigned int lock_lev;
- gc_enter(objspace, gc_enter_event_rest, &lock_lev);
-
- if (RGENGC_CHECK_MODE >= 2) gc_verify_internal_consistency(objspace);
+ VALUE *ptr = ROBJECT_FIELDS(v);
- if (is_incremental_marking(objspace)) {
- gc_marking_enter(objspace);
- gc_marks_rest(objspace);
- gc_marking_exit(objspace);
-
- gc_sweep(objspace);
+ if (FL_TEST_RAW(v, ROBJECT_HEAP)) {
+ if (rb_shape_obj_too_complex_p(v)) {
+ gc_ref_update_table_values_only(ROBJECT_FIELDS_HASH(v));
+ return;
}
- if (is_lazy_sweeping(objspace)) {
- gc_sweeping_enter(objspace);
- gc_sweep_rest(objspace);
- gc_sweeping_exit(objspace);
+ size_t slot_size = rb_gc_obj_slot_size(v);
+ size_t embed_size = rb_obj_embedded_size(ROBJECT_FIELDS_CAPACITY(v));
+ if (slot_size >= embed_size) {
+ // Object can be re-embedded
+ memcpy(ROBJECT(v)->as.ary, ptr, sizeof(VALUE) * ROBJECT_FIELDS_COUNT(v));
+ FL_UNSET_RAW(v, ROBJECT_HEAP);
+ xfree(ptr);
+ ptr = ROBJECT(v)->as.ary;
}
-
- gc_exit(objspace, gc_enter_event_rest, &lock_lev);
}
-}
-
-struct objspace_and_reason {
- rb_objspace_t *objspace;
- unsigned int reason;
-};
-static void
-gc_current_status_fill(rb_objspace_t *objspace, char *buff)
-{
- int i = 0;
- if (is_marking(objspace)) {
- buff[i++] = 'M';
- if (is_full_marking(objspace)) buff[i++] = 'F';
- if (is_incremental_marking(objspace)) buff[i++] = 'I';
- }
- else if (is_sweeping(objspace)) {
- buff[i++] = 'S';
- if (is_lazy_sweeping(objspace)) buff[i++] = 'L';
- }
- else {
- buff[i++] = 'N';
+ for (uint32_t i = 0; i < ROBJECT_FIELDS_COUNT(v); i++) {
+ UPDATE_IF_MOVED(objspace, ptr[i]);
}
- buff[i] = '\0';
}
-static const char *
-gc_current_status(rb_objspace_t *objspace)
+void
+rb_gc_ref_update_table_values_only(st_table *tbl)
{
- static char buff[0x10];
- gc_current_status_fill(objspace, buff);
- return buff;
+ gc_ref_update_table_values_only(tbl);
}
-#if PRINT_ENTER_EXIT_TICK
-
-static tick_t last_exit_tick;
-static tick_t enter_tick;
-static int enter_count = 0;
-static char last_gc_status[0x10];
-
-static inline void
-gc_record(rb_objspace_t *objspace, int direction, const char *event)
-{
- if (direction == 0) { /* enter */
- enter_count++;
- enter_tick = tick();
- gc_current_status_fill(objspace, last_gc_status);
- }
- else { /* exit */
- tick_t exit_tick = tick();
- char current_gc_status[0x10];
- gc_current_status_fill(objspace, current_gc_status);
-#if 1
- /* [last mutator time] [gc time] [event] */
- fprintf(stderr, "%"PRItick"\t%"PRItick"\t%s\t[%s->%s|%c]\n",
- enter_tick - last_exit_tick,
- exit_tick - enter_tick,
- event,
- last_gc_status, current_gc_status,
- (objspace->profile.latest_gc_info & GPR_FLAG_MAJOR_MASK) ? '+' : '-');
- last_exit_tick = exit_tick;
-#else
- /* [enter_tick] [gc time] [event] */
- fprintf(stderr, "%"PRItick"\t%"PRItick"\t%s\t[%s->%s|%c]\n",
- enter_tick,
- exit_tick - enter_tick,
- event,
- last_gc_status, current_gc_status,
- (objspace->profile.latest_gc_info & GPR_FLAG_MAJOR_MASK) ? '+' : '-');
-#endif
- }
-}
-#else /* PRINT_ENTER_EXIT_TICK */
-static inline void
-gc_record(rb_objspace_t *objspace, int direction, const char *event)
+/* Update MOVED references in a VALUE=>VALUE st_table */
+void
+rb_gc_update_tbl_refs(st_table *ptr)
{
- /* null */
+ gc_update_table_refs(ptr);
}
-#endif /* PRINT_ENTER_EXIT_TICK */
-static const char *
-gc_enter_event_cstr(enum gc_enter_event event)
+static void
+gc_ref_update_hash(void *objspace, VALUE v)
{
- switch (event) {
- case gc_enter_event_start: return "start";
- case gc_enter_event_continue: return "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;
+ rb_hash_stlike_foreach_with_replace(v, hash_foreach_replace, hash_replace_ref, (st_data_t)objspace);
}
static void
-gc_enter_count(enum gc_enter_event event)
+gc_update_values(void *objspace, long n, VALUE *values)
{
- switch (event) {
- case gc_enter_event_start: RB_DEBUG_COUNTER_INC(gc_enter_start); break;
- case gc_enter_event_continue: RB_DEBUG_COUNTER_INC(gc_enter_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;
+ for (long i = 0; i < n; i++) {
+ UPDATE_IF_MOVED(objspace, values[i]);
}
}
-static bool current_process_time(struct timespec *ts);
-
-static void
-gc_clock_start(struct timespec *ts)
+void
+rb_gc_update_values(long n, VALUE *values)
{
- if (!current_process_time(ts)) {
- ts->tv_sec = 0;
- ts->tv_nsec = 0;
- }
+ gc_update_values(rb_gc_get_objspace(), n, values);
}
-static uint64_t
-gc_clock_end(struct timespec *ts)
+static enum rb_id_table_iterator_result
+check_id_table_move(VALUE value, void *data)
{
- struct timespec end_time;
+ void *objspace = (void *)data;
- if ((ts->tv_sec > 0 || ts->tv_nsec > 0) &&
- current_process_time(&end_time) &&
- end_time.tv_sec >= ts->tv_sec) {
- return (uint64_t)(end_time.tv_sec - ts->tv_sec) * (1000 * 1000 * 1000) +
- (end_time.tv_nsec - ts->tv_nsec);
+ if (gc_object_moved_p_internal(objspace, (VALUE)value)) {
+ return ID_TABLE_REPLACE;
}
- return 0;
+ return ID_TABLE_CONTINUE;
}
-static inline void
-gc_enter(rb_objspace_t *objspace, enum gc_enter_event event, unsigned int *lock_lev)
-{
- RB_VM_LOCK_ENTER_LEV(lock_lev);
-
- switch (event) {
- case gc_enter_event_rest:
- if (!is_marking(objspace)) break;
- // fall through
- case gc_enter_event_start:
- case gc_enter_event_continue:
- // stop other ractors
- rb_vm_barrier();
+void
+rb_gc_prepare_heap_process_object(VALUE obj)
+{
+ switch (BUILTIN_TYPE(obj)) {
+ case T_STRING:
+ // Precompute the string coderange. This both save time for when it will be
+ // eventually needed, and avoid mutating heap pages after a potential fork.
+ rb_enc_str_coderange(obj);
break;
default:
break;
}
-
- gc_enter_count(event);
- if (UNLIKELY(during_gc != 0)) rb_bug("during_gc != 0");
- if (RGENGC_CHECK_MODE >= 3 && (dont_gc_val() == 0)) gc_verify_internal_consistency(objspace);
-
- during_gc = TRUE;
- 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, 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 passed? */
- 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;
-
- RB_VM_LOCK_LEAVE_LEV(lock_lev);
-}
-
-#ifndef MEASURE_GC
-#define MEASURE_GC (objspace->flags.measure_gc)
-#endif
-
-static void
-gc_marking_enter(rb_objspace_t *objspace)
+void
+rb_gc_prepare_heap(void)
{
- GC_ASSERT(during_gc != 0);
-
- if (MEASURE_GC) {
- gc_clock_start(&objspace->profile.marking_start_time);
- }
+ rb_gc_impl_prepare_heap(rb_gc_get_objspace());
}
-static void
-gc_marking_exit(rb_objspace_t *objspace)
+size_t
+rb_gc_heap_id_for_size(size_t size)
{
- GC_ASSERT(during_gc != 0);
-
- if (MEASURE_GC) {
- objspace->profile.marking_time_ns += gc_clock_end(&objspace->profile.marking_start_time);
- }
+ return rb_gc_impl_heap_id_for_size(rb_gc_get_objspace(), size);
}
-static void
-gc_sweeping_enter(rb_objspace_t *objspace)
+bool
+rb_gc_size_allocatable_p(size_t size)
{
- GC_ASSERT(during_gc != 0);
-
- if (MEASURE_GC) {
- gc_clock_start(&objspace->profile.sweeping_start_time);
- }
+ return rb_gc_impl_size_allocatable_p(size);
}
-static void
-gc_sweeping_exit(rb_objspace_t *objspace)
+static enum rb_id_table_iterator_result
+update_id_table(VALUE *value, void *data, int existing)
{
- GC_ASSERT(during_gc != 0);
+ void *objspace = (void *)data;
- if (MEASURE_GC) {
- objspace->profile.sweeping_time_ns += gc_clock_end(&objspace->profile.sweeping_start_time);
+ if (gc_object_moved_p_internal(objspace, (VALUE)*value)) {
+ *value = gc_location_internal(objspace, (VALUE)*value);
}
-}
-
-static void *
-gc_with_gvl(void *ptr)
-{
- struct objspace_and_reason *oar = (struct objspace_and_reason *)ptr;
- return (void *)(VALUE)garbage_collect(oar->objspace, oar->reason);
-}
-static int
-garbage_collect_with_gvl(rb_objspace_t *objspace, unsigned int reason)
-{
- if (dont_gc_val()) return TRUE;
- if (ruby_thread_has_gvl_p()) {
- return garbage_collect(objspace, reason);
- }
- else {
- if (ruby_native_thread_p()) {
- struct objspace_and_reason oar;
- oar.objspace = objspace;
- oar.reason = reason;
- return (int)(VALUE)rb_thread_call_with_gvl(gc_with_gvl, (void *)&oar);
- }
- else {
- /* no ruby thread */
- fprintf(stderr, "[FATAL] failed to allocate memory\n");
- exit(EXIT_FAILURE);
- }
- }
+ return ID_TABLE_CONTINUE;
}
-static int
-gc_set_candidate_object_i(void *vstart, void *vend, size_t stride, void *data)
+static void
+update_m_tbl(void *objspace, struct rb_id_table *tbl)
{
- rb_objspace_t *objspace = &rb_objspace;
- VALUE v = (VALUE)vstart;
- for (; v != (VALUE)vend; v += stride) {
- asan_unpoisoning_object(v) {
- switch (BUILTIN_TYPE(v)) {
- case T_NONE:
- case T_ZOMBIE:
- break;
- case T_STRING:
- // precompute the string coderange. This both save time for when it will be
- // eventually needed, and avoid mutating heap pages after a potential fork.
- rb_enc_str_coderange(v);
- // fall through
- default:
- if (!RVALUE_OLD_P(v) && !RVALUE_WB_UNPROTECTED(v)) {
- RVALUE_AGE_SET_CANDIDATE(objspace, v);
- }
- }
- }
+ if (tbl) {
+ rb_id_table_foreach_values_with_replace(tbl, check_id_table_move, update_id_table, objspace);
}
-
- return 0;
}
-static VALUE
-gc_start_internal(rb_execution_context_t *ec, VALUE self, VALUE full_mark, VALUE immediate_mark, VALUE immediate_sweep, VALUE compact)
+static enum rb_id_table_iterator_result
+update_cvc_tbl_i(VALUE cvc_entry, void *objspace)
{
- rb_objspace_t *objspace = &rb_objspace;
- unsigned int reason = (GPR_FLAG_FULL_MARK |
- GPR_FLAG_IMMEDIATE_MARK |
- GPR_FLAG_IMMEDIATE_SWEEP |
- GPR_FLAG_METHOD);
+ struct rb_cvar_class_tbl_entry *entry;
- /* For now, compact implies full mark / sweep, so ignore other flags */
- if (RTEST(compact)) {
- GC_ASSERT(GC_COMPACTION_SUPPORTED);
+ entry = (struct rb_cvar_class_tbl_entry *)cvc_entry;
- 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;
+ if (entry->cref) {
+ TYPED_UPDATE_IF_MOVED(objspace, rb_cref_t *, entry->cref);
}
- garbage_collect(objspace, reason);
- gc_finalize_deferred(objspace);
+ entry->class_value = gc_location_internal(objspace, entry->class_value);
- return Qnil;
+ return ID_TABLE_CONTINUE;
}
static void
-free_empty_pages(void)
+update_cvc_tbl(void *objspace, struct rb_id_table *tbl)
{
- rb_objspace_t *objspace = &rb_objspace;
-
- for (int i = 0; i < SIZE_POOL_COUNT; i++) {
- /* Move all empty pages to the tomb heap for freeing. */
- rb_size_pool_t *size_pool = &size_pools[i];
- rb_heap_t *heap = SIZE_POOL_EDEN_HEAP(size_pool);
- rb_heap_t *tomb_heap = SIZE_POOL_TOMB_HEAP(size_pool);
-
- size_t freed_pages = 0;
-
- struct heap_page **next_page_ptr = &heap->free_pages;
- struct heap_page *page = heap->free_pages;
- while (page) {
- /* All finalizers should have been ran in gc_start_internal, so there
- * should be no objects that require finalization. */
- GC_ASSERT(page->final_slots == 0);
-
- struct heap_page *next_page = page->free_next;
-
- if (page->free_slots == page->total_slots) {
- heap_unlink_page(objspace, heap, page);
- heap_add_page(objspace, size_pool, tomb_heap, page);
- freed_pages++;
- }
- else {
- *next_page_ptr = page;
- next_page_ptr = &page->free_next;
- }
+ if (!tbl) return;
+ rb_id_table_foreach_values(tbl, update_cvc_tbl_i, objspace);
+}
- page = next_page;
- }
+static enum rb_id_table_iterator_result
+update_const_tbl_i(VALUE value, void *objspace)
+{
+ rb_const_entry_t *ce = (rb_const_entry_t *)value;
- *next_page_ptr = NULL;
+ if (gc_object_moved_p_internal(objspace, ce->value)) {
+ ce->value = gc_location_internal(objspace, ce->value);
+ }
- size_pool_allocatable_pages_set(objspace, size_pool, size_pool->allocatable_pages + freed_pages);
+ if (gc_object_moved_p_internal(objspace, ce->file)) {
+ ce->file = gc_location_internal(objspace, ce->file);
}
- heap_pages_free_unused_pages(objspace);
+ return ID_TABLE_CONTINUE;
}
-void
-rb_gc_prepare_heap(void)
+static void
+update_const_tbl(void *objspace, struct rb_id_table *tbl)
{
- rb_objspace_each_objects(gc_set_candidate_object_i, NULL);
- gc_start_internal(NULL, Qtrue, Qtrue, Qtrue, Qtrue, Qtrue);
- free_empty_pages();
-
-#if defined(HAVE_MALLOC_TRIM) && !defined(RUBY_ALTERNATIVE_MALLOC_HEADER)
- malloc_trim(0);
-#endif
+ if (!tbl) return;
+ rb_id_table_foreach_values(tbl, update_const_tbl_i, objspace);
}
-static int
-gc_is_moveable_obj(rb_objspace_t *objspace, VALUE obj)
+static void
+update_subclasses(void *objspace, rb_classext_t *ext)
{
- GC_ASSERT(!SPECIAL_CONST_P(obj));
-
- switch (BUILTIN_TYPE(obj)) {
- case T_NONE:
- case T_MOVED:
- case T_ZOMBIE:
- return FALSE;
- case T_SYMBOL:
- if (RSYMBOL(obj)->id & ~ID_SCOPE_MASK) {
- return FALSE;
- }
- /* fall through */
- case T_STRING:
- case T_OBJECT:
- case T_FLOAT:
- case T_IMEMO:
- case T_ARRAY:
- case T_BIGNUM:
- case T_ICLASS:
- case T_MODULE:
- case T_REGEXP:
- case T_DATA:
- case T_MATCH:
- case T_STRUCT:
- case T_HASH:
- case T_FILE:
- case T_COMPLEX:
- case T_RATIONAL:
- 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. */
- GC_ASSERT(st_is_member(finalizer_table, obj));
-
- return FALSE;
- }
- 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));
- break;
+ rb_subclass_entry_t *entry;
+ rb_subclass_anchor_t *anchor = RCLASSEXT_SUBCLASSES(ext);
+ if (!anchor) return;
+ entry = anchor->head;
+ while (entry) {
+ if (entry->klass)
+ UPDATE_IF_MOVED(objspace, entry->klass);
+ entry = entry->next;
}
-
- return FALSE;
}
-static VALUE
-gc_move(rb_objspace_t *objspace, VALUE scan, VALUE free, size_t src_slot_size, size_t slot_size)
+static void
+update_superclasses(rb_objspace_t *objspace, rb_classext_t *ext)
{
- int marked;
- int wb_unprotected;
- int uncollectible;
- int age;
- RVALUE *dest = (RVALUE *)free;
- RVALUE *src = (RVALUE *)scan;
-
- gc_report(4, objspace, "Moving object: %p -> %p\n", (void*)scan, (void *)free);
-
- GC_ASSERT(BUILTIN_TYPE(scan) != T_NONE);
- GC_ASSERT(!MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(free), free));
-
- GC_ASSERT(!RVALUE_MARKING((VALUE)src));
-
- /* Save off bits for current object. */
- marked = RVALUE_MARKED((VALUE)src);
- wb_unprotected = RVALUE_WB_UNPROTECTED((VALUE)src);
- uncollectible = RVALUE_UNCOLLECTIBLE((VALUE)src);
- bool remembered = RVALUE_REMEMBERED((VALUE)src);
- age = RVALUE_AGE_GET((VALUE)src);
-
- /* 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_PAGE((VALUE)src)->remembered_bits, (VALUE)src);
-
- if (FL_TEST((VALUE)src, FL_EXIVAR)) {
- /* Resizing the st table could cause a malloc */
- DURING_GC_COULD_MALLOC_REGION_START();
- {
- rb_mv_generic_ivar((VALUE)src, (VALUE)dest);
+ if (RCLASSEXT_SUPERCLASSES_WITH_SELF(ext)) {
+ size_t array_size = RCLASSEXT_SUPERCLASS_DEPTH(ext) + 1;
+ for (size_t i = 0; i < array_size; i++) {
+ UPDATE_IF_MOVED(objspace, RCLASSEXT_SUPERCLASSES(ext)[i]);
}
- DURING_GC_COULD_MALLOC_REGION_END();
}
-
- if (FL_TEST((VALUE)src, FL_SEEN_OBJ_ID)) {
- /* If the source object's object_id has been seen, we need to update
- * the object to object id mapping. */
- st_data_t srcid = (st_data_t)src, id;
-
- gc_report(4, objspace, "Moving object with seen id: %p -> %p\n", (void *)src, (void *)dest);
- /* Resizing the st table could cause a malloc */
- DURING_GC_COULD_MALLOC_REGION_START();
- {
- if (!st_delete(objspace->obj_to_id_tbl, &srcid, &id)) {
- rb_bug("gc_move: object ID seen, but not in mapping table: %s", obj_info((VALUE)src));
- }
-
- st_insert(objspace->obj_to_id_tbl, (st_data_t)dest, id);
- }
- DURING_GC_COULD_MALLOC_REGION_END();
- }
- else {
- GC_ASSERT(!st_lookup(objspace->obj_to_id_tbl, (st_data_t)src, NULL));
- }
-
- /* Move the object */
- memcpy(dest, src, MIN(src_slot_size, slot_size));
-
- if (RVALUE_OVERHEAD > 0) {
- void *dest_overhead = (void *)(((uintptr_t)dest) + slot_size - RVALUE_OVERHEAD);
- void *src_overhead = (void *)(((uintptr_t)src) + src_slot_size - RVALUE_OVERHEAD);
-
- memcpy(dest_overhead, src_overhead, RVALUE_OVERHEAD);
- }
-
- memset(src, 0, src_slot_size);
- RVALUE_AGE_RESET((VALUE)src);
-
- /* Set bits for object in new location */
- if (remembered) {
- MARK_IN_BITMAP(GET_HEAP_PAGE(dest)->remembered_bits, (VALUE)dest);
- }
- else {
- CLEAR_IN_BITMAP(GET_HEAP_PAGE(dest)->remembered_bits, (VALUE)dest);
- }
-
- if (marked) {
- MARK_IN_BITMAP(GET_HEAP_MARK_BITS((VALUE)dest), (VALUE)dest);
- }
- else {
- CLEAR_IN_BITMAP(GET_HEAP_MARK_BITS((VALUE)dest), (VALUE)dest);
- }
-
- if (wb_unprotected) {
- MARK_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS((VALUE)dest), (VALUE)dest);
- }
- else {
- CLEAR_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS((VALUE)dest), (VALUE)dest);
- }
-
- if (uncollectible) {
- MARK_IN_BITMAP(GET_HEAP_UNCOLLECTIBLE_BITS((VALUE)dest), (VALUE)dest);
- }
- else {
- CLEAR_IN_BITMAP(GET_HEAP_UNCOLLECTIBLE_BITS((VALUE)dest), (VALUE)dest);
- }
-
- RVALUE_AGE_SET((VALUE)dest, age);
- /* Assign forwarding address */
- src->as.moved.flags = T_MOVED;
- src->as.moved.dummy = Qundef;
- src->as.moved.destination = (VALUE)dest;
- GC_ASSERT(BUILTIN_TYPE((VALUE)dest) != T_NONE);
-
- return (VALUE)src;
-}
-
-#if GC_CAN_COMPILE_COMPACTION
-static int
-compare_pinned_slots(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 left_page->pinned_slots - right_page->pinned_slots;
-}
-
-static int
-compare_free_slots(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 left_page->free_slots - right_page->free_slots;
}
static void
-gc_sort_heap_by_compare_func(rb_objspace_t *objspace, gc_compact_compare_func compare_func)
+update_classext_values(rb_objspace_t *objspace, rb_classext_t *ext, bool is_iclass)
{
- for (int j = 0; j < SIZE_POOL_COUNT; j++) {
- rb_size_pool_t *size_pool = &size_pools[j];
-
- 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;
-
- SIZE_POOL_EDEN_HEAP(size_pool)->free_pages = NULL;
- ccan_list_for_each(&SIZE_POOL_EDEN_HEAP(size_pool)->pages, page, page_node) {
- page_list[i++] = page;
- GC_ASSERT(page);
- }
-
- GC_ASSERT((size_t)i == total_pages);
-
- /* 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_func, NULL);
-
- /* Reset the eden heap */
- ccan_list_head_init(&SIZE_POOL_EDEN_HEAP(size_pool)->pages);
-
- for (i = 0; i < total_pages; i++) {
- ccan_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]);
- }
- }
-
- free(page_list);
+ UPDATE_IF_MOVED(objspace, RCLASSEXT_ORIGIN(ext));
+ UPDATE_IF_MOVED(objspace, RCLASSEXT_REFINED_CLASS(ext));
+ UPDATE_IF_MOVED(objspace, RCLASSEXT_CLASSPATH(ext));
+ if (is_iclass) {
+ UPDATE_IF_MOVED(objspace, RCLASSEXT_INCLUDER(ext));
}
}
-#endif
static void
-gc_ref_update_array(rb_objspace_t * objspace, VALUE v)
+update_classext(rb_classext_t *ext, bool is_prime, VALUE box_value, void *arg)
{
- if (ARY_SHARED_P(v)) {
- VALUE old_root = RARRAY(v)->as.heap.aux.shared_root;
+ struct classext_foreach_args *args = (struct classext_foreach_args *)arg;
+ rb_objspace_t *objspace = args->objspace;
- UPDATE_IF_MOVED(objspace, RARRAY(v)->as.heap.aux.shared_root);
-
- VALUE new_root = RARRAY(v)->as.heap.aux.shared_root;
- // If the root is embedded and its location has changed
- if (ARY_EMBED_P(new_root) && new_root != old_root) {
- size_t offset = (size_t)(RARRAY(v)->as.heap.ptr - RARRAY(old_root)->as.ary);
- GC_ASSERT(RARRAY(v)->as.heap.ptr >= RARRAY(old_root)->as.ary);
- RARRAY(v)->as.heap.ptr = RARRAY(new_root)->as.ary + offset;
- }
+ if (RCLASSEXT_SUPER(ext)) {
+ UPDATE_IF_MOVED(objspace, RCLASSEXT_SUPER(ext));
}
- else {
- long len = RARRAY_LEN(v);
- if (len > 0) {
- VALUE *ptr = (VALUE *)RARRAY_CONST_PTR(v);
- for (long i = 0; i < len; i++) {
- UPDATE_IF_MOVED(objspace, ptr[i]);
- }
- }
+ update_m_tbl(objspace, RCLASSEXT_M_TBL(ext));
- if (rb_gc_obj_slot_size(v) >= rb_ary_size_as_embedded(v)) {
- if (rb_ary_embeddable_p(v)) {
- rb_ary_make_embedded(v);
- }
- }
+ UPDATE_IF_MOVED(objspace, ext->fields_obj);
+ if (!RCLASSEXT_SHARED_CONST_TBL(ext)) {
+ update_const_tbl(objspace, RCLASSEXT_CONST_TBL(ext));
}
-}
+ UPDATE_IF_MOVED(objspace, RCLASSEXT_CC_TBL(ext));
+ update_cvc_tbl(objspace, RCLASSEXT_CVC_TBL(ext));
+ update_superclasses(objspace, ext);
+ update_subclasses(objspace, ext);
-static void gc_ref_update_table_values_only(rb_objspace_t *objspace, st_table *tbl);
+ update_classext_values(objspace, ext, false);
+}
static void
-gc_ref_update_object(rb_objspace_t *objspace, VALUE v)
+update_iclass_classext(rb_classext_t *ext, bool is_prime, VALUE box_value, void *arg)
{
- VALUE *ptr = ROBJECT_IVPTR(v);
-
- if (rb_shape_obj_too_complex(v)) {
- gc_ref_update_table_values_only(objspace, ROBJECT_IV_HASH(v));
- return;
- }
+ struct classext_foreach_args *args = (struct classext_foreach_args *)arg;
+ rb_objspace_t *objspace = args->objspace;
- size_t slot_size = rb_gc_obj_slot_size(v);
- size_t embed_size = rb_obj_embedded_size(ROBJECT_IV_CAPACITY(v));
- if (slot_size >= embed_size && !RB_FL_TEST_RAW(v, ROBJECT_EMBED)) {
- // Object can be re-embedded
- memcpy(ROBJECT(v)->as.ary, ptr, sizeof(VALUE) * ROBJECT_IV_COUNT(v));
- RB_FL_SET_RAW(v, ROBJECT_EMBED);
- xfree(ptr);
- ptr = ROBJECT(v)->as.ary;
+ if (RCLASSEXT_SUPER(ext)) {
+ UPDATE_IF_MOVED(objspace, RCLASSEXT_SUPER(ext));
}
+ update_m_tbl(objspace, RCLASSEXT_M_TBL(ext));
+ update_m_tbl(objspace, RCLASSEXT_CALLABLE_M_TBL(ext));
+ UPDATE_IF_MOVED(objspace, RCLASSEXT_CC_TBL(ext));
+ update_subclasses(objspace, ext);
- for (uint32_t i = 0; i < ROBJECT_IV_COUNT(v); i++) {
- UPDATE_IF_MOVED(objspace, ptr[i]);
- }
+ update_classext_values(objspace, ext, true);
}
+struct global_vm_table_foreach_data {
+ vm_table_foreach_callback_func callback;
+ vm_table_update_callback_func update_callback;
+ void *data;
+ bool weak_only;
+};
+
static int
-hash_replace_ref(st_data_t *key, st_data_t *value, st_data_t argp, int existing)
+vm_weak_table_foreach_weak_key(st_data_t key, st_data_t value, st_data_t data, int error)
{
- rb_objspace_t *objspace = (rb_objspace_t *)argp;
+ struct global_vm_table_foreach_data *iter_data = (struct global_vm_table_foreach_data *)data;
- if (gc_object_moved_p(objspace, (VALUE)*key)) {
- *key = rb_gc_location((VALUE)*key);
- }
+ int ret = iter_data->callback((VALUE)key, iter_data->data);
+
+ if (!iter_data->weak_only) {
+ if (ret != ST_CONTINUE) return ret;
- if (gc_object_moved_p(objspace, (VALUE)*value)) {
- *value = rb_gc_location((VALUE)*value);
+ ret = iter_data->callback((VALUE)value, iter_data->data);
}
- return ST_CONTINUE;
+ return ret;
}
static int
-hash_foreach_replace(st_data_t key, st_data_t value, st_data_t argp, int error)
+vm_weak_table_foreach_update_weak_key(st_data_t *key, st_data_t *value, st_data_t data, int existing)
{
- rb_objspace_t *objspace;
+ struct global_vm_table_foreach_data *iter_data = (struct global_vm_table_foreach_data *)data;
- objspace = (rb_objspace_t *)argp;
+ int ret = iter_data->update_callback((VALUE *)key, iter_data->data);
- if (gc_object_moved_p(objspace, (VALUE)key)) {
- return ST_REPLACE;
- }
+ if (!iter_data->weak_only) {
+ if (ret != ST_CONTINUE) return ret;
- if (gc_object_moved_p(objspace, (VALUE)value)) {
- return ST_REPLACE;
+ ret = iter_data->update_callback((VALUE *)value, iter_data->data);
}
- return ST_CONTINUE;
+
+ return ret;
}
static int
-hash_replace_ref_value(st_data_t *key, st_data_t *value, st_data_t argp, int existing)
+vm_weak_table_cc_refinement_foreach(st_data_t key, st_data_t data, int error)
{
- rb_objspace_t *objspace = (rb_objspace_t *)argp;
+ struct global_vm_table_foreach_data *iter_data = (struct global_vm_table_foreach_data *)data;
- if (gc_object_moved_p(objspace, (VALUE)*value)) {
- *value = rb_gc_location((VALUE)*value);
- }
-
- return ST_CONTINUE;
+ return iter_data->callback((VALUE)key, iter_data->data);
}
static int
-hash_foreach_replace_value(st_data_t key, st_data_t value, st_data_t argp, int error)
+vm_weak_table_cc_refinement_foreach_update_update(st_data_t *key, st_data_t data, int existing)
{
- rb_objspace_t *objspace;
+ struct global_vm_table_foreach_data *iter_data = (struct global_vm_table_foreach_data *)data;
- objspace = (rb_objspace_t *)argp;
-
- if (gc_object_moved_p(objspace, (VALUE)value)) {
- return ST_REPLACE;
- }
- return ST_CONTINUE;
+ return iter_data->update_callback((VALUE *)key, iter_data->data);
}
-static void
-gc_ref_update_table_values_only(rb_objspace_t *objspace, st_table *tbl)
-{
- if (!tbl || tbl->num_entries == 0) return;
- if (st_foreach_with_replace(tbl, hash_foreach_replace_value, hash_replace_ref_value, (st_data_t)objspace)) {
- rb_raise(rb_eRuntimeError, "hash modified during iteration");
- }
-}
-
-void
-rb_gc_ref_update_table_values_only(st_table *tbl)
+static int
+vm_weak_table_sym_set_foreach(VALUE *sym_ptr, void *data)
{
- gc_ref_update_table_values_only(&rb_objspace, tbl);
-}
+ VALUE sym = *sym_ptr;
+ struct global_vm_table_foreach_data *iter_data = (struct global_vm_table_foreach_data *)data;
-static void
-gc_update_table_refs(rb_objspace_t * objspace, st_table *tbl)
-{
- if (!tbl || tbl->num_entries == 0) return;
+ if (RB_SPECIAL_CONST_P(sym)) return ST_CONTINUE;
- if (st_foreach_with_replace(tbl, hash_foreach_replace, hash_replace_ref, (st_data_t)objspace)) {
- rb_raise(rb_eRuntimeError, "hash modified during iteration");
+ int ret = iter_data->callback(sym, iter_data->data);
+
+ if (ret == ST_REPLACE) {
+ ret = iter_data->update_callback(sym_ptr, iter_data->data);
}
-}
-/* Update MOVED references in a VALUE=>VALUE st_table */
-void
-rb_gc_update_tbl_refs(st_table *ptr)
-{
- rb_objspace_t *objspace = &rb_objspace;
- gc_update_table_refs(objspace, ptr);
+ return ret;
}
-static void
-gc_ref_update_hash(rb_objspace_t * objspace, VALUE v)
-{
- rb_hash_stlike_foreach_with_replace(v, hash_foreach_replace, hash_replace_ref, (st_data_t)objspace);
-}
+struct st_table *rb_generic_fields_tbl_get(void);
-static void
-gc_update_values(rb_objspace_t *objspace, long n, VALUE *values)
+static int
+vm_weak_table_id2ref_foreach(st_data_t key, st_data_t value, st_data_t data, int error)
{
- long i;
+ struct global_vm_table_foreach_data *iter_data = (struct global_vm_table_foreach_data *)data;
- for (i=0; i<n; i++) {
- UPDATE_IF_MOVED(objspace, values[i]);
+ if (!iter_data->weak_only && !FIXNUM_P((VALUE)key)) {
+ int ret = iter_data->callback((VALUE)key, iter_data->data);
+ if (ret != ST_CONTINUE) return ret;
}
-}
-void
-rb_gc_update_values(long n, VALUE *values)
-{
- gc_update_values(&rb_objspace, n, values);
+ return iter_data->callback((VALUE)value, iter_data->data);
}
-static enum rb_id_table_iterator_result
-check_id_table_move(VALUE value, void *data)
+static int
+vm_weak_table_id2ref_foreach_update(st_data_t *key, st_data_t *value, st_data_t data, int existing)
{
- rb_objspace_t *objspace = (rb_objspace_t *)data;
+ struct global_vm_table_foreach_data *iter_data = (struct global_vm_table_foreach_data *)data;
- if (gc_object_moved_p(objspace, (VALUE)value)) {
- return ID_TABLE_REPLACE;
+ iter_data->update_callback((VALUE *)value, iter_data->data);
+
+ if (!iter_data->weak_only && !FIXNUM_P((VALUE)*key)) {
+ iter_data->update_callback((VALUE *)key, iter_data->data);
}
- return ID_TABLE_CONTINUE;
+ return ST_CONTINUE;
}
-/* Returns the new location of an object, if it moved. Otherwise returns
- * the existing location. */
-VALUE
-rb_gc_location(VALUE value)
+static int
+vm_weak_table_gen_fields_foreach(st_data_t key, st_data_t value, st_data_t data)
{
+ struct global_vm_table_foreach_data *iter_data = (struct global_vm_table_foreach_data *)data;
- VALUE destination;
-
- if (!SPECIAL_CONST_P(value)) {
- void *poisoned = asan_unpoison_object_temporary(value);
+ int ret = iter_data->callback((VALUE)key, iter_data->data);
- if (BUILTIN_TYPE(value) == T_MOVED) {
- destination = (VALUE)RMOVED(value)->destination;
- GC_ASSERT(BUILTIN_TYPE(destination) != T_NONE);
- }
- else {
- destination = value;
- }
+ VALUE new_value = (VALUE)value;
+ VALUE new_key = (VALUE)key;
- /* Re-poison slot if it's not the one we want */
- if (poisoned) {
- GC_ASSERT(BUILTIN_TYPE(value) == T_NONE);
- asan_poison_object(value);
- }
- }
- else {
- destination = value;
- }
+ switch (ret) {
+ case ST_CONTINUE:
+ break;
- return destination;
-}
+ case ST_DELETE:
+ RBASIC_SET_SHAPE_ID((VALUE)key, ROOT_SHAPE_ID);
+ return ST_DELETE;
-static enum rb_id_table_iterator_result
-update_id_table(VALUE *value, void *data, int existing)
-{
- rb_objspace_t *objspace = (rb_objspace_t *)data;
+ case ST_REPLACE: {
+ ret = iter_data->update_callback(&new_key, iter_data->data);
+ if (key != new_key) {
+ ret = ST_DELETE;
+ }
+ break;
+ }
- if (gc_object_moved_p(objspace, (VALUE)*value)) {
- *value = rb_gc_location((VALUE)*value);
+ default:
+ rb_bug("vm_weak_table_gen_fields_foreach: return value %d not supported", ret);
}
- return ID_TABLE_CONTINUE;
-}
-
-static void
-update_m_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl)
-{
- if (tbl) {
- rb_id_table_foreach_values_with_replace(tbl, check_id_table_move, update_id_table, objspace);
- }
-}
+ if (!iter_data->weak_only) {
+ int ivar_ret = iter_data->callback(new_value, iter_data->data);
+ switch (ivar_ret) {
+ case ST_CONTINUE:
+ break;
-static enum rb_id_table_iterator_result
-update_cc_tbl_i(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));
+ case ST_REPLACE:
+ iter_data->update_callback(&new_value, iter_data->data);
+ break;
- if (gc_object_moved_p(objspace, (VALUE)ccs->cme)) {
- ccs->cme = (const rb_callable_method_entry_t *)rb_gc_location((VALUE)ccs->cme);
+ default:
+ rb_bug("vm_weak_table_gen_fields_foreach: return value %d not supported", ivar_ret);
+ }
}
- for (int i=0; i<ccs->len; i++) {
- 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);
+ if (key != new_key || value != new_value) {
+ DURING_GC_COULD_MALLOC_REGION_START();
+ {
+ st_insert(rb_generic_fields_tbl_get(), (st_data_t)new_key, new_value);
}
+ DURING_GC_COULD_MALLOC_REGION_END();
}
- // 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_values(tbl, update_cc_tbl_i, objspace);
- }
+ return ret;
}
-static enum rb_id_table_iterator_result
-update_cvc_tbl_i(VALUE cvc_entry, void *data)
+static int
+vm_weak_table_frozen_strings_foreach(VALUE *str, void *data)
{
- struct rb_cvar_class_tbl_entry *entry;
- rb_objspace_t * objspace = (rb_objspace_t *)data;
+ // int retval = vm_weak_table_foreach_weak_key(key, value, data, error);
+ struct global_vm_table_foreach_data *iter_data = (struct global_vm_table_foreach_data *)data;
+ int retval = iter_data->callback(*str, iter_data->data);
- entry = (struct rb_cvar_class_tbl_entry *)cvc_entry;
-
- if (entry->cref) {
- TYPED_UPDATE_IF_MOVED(objspace, rb_cref_t *, entry->cref);
+ if (retval == ST_REPLACE) {
+ retval = iter_data->update_callback(str, iter_data->data);
}
- 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_values(tbl, update_cvc_tbl_i, objspace);
+ if (retval == ST_DELETE) {
+ FL_UNSET(*str, RSTRING_FSTR);
}
+
+ return retval;
}
-static enum rb_id_table_iterator_result
-mark_cvc_tbl_i(VALUE cvc_entry, void *data)
+void rb_fstring_foreach_with_replace(int (*callback)(VALUE *str, void *data), void *data);
+void
+rb_gc_vm_weak_table_foreach(vm_table_foreach_callback_func callback,
+ vm_table_update_callback_func update_callback,
+ void *data,
+ bool weak_only,
+ enum rb_gc_vm_weak_tables table)
{
- rb_objspace_t *objspace = (rb_objspace_t *)data;
- struct rb_cvar_class_tbl_entry *entry;
-
- entry = (struct rb_cvar_class_tbl_entry *)cvc_entry;
-
- RUBY_ASSERT(entry->cref == 0 || (BUILTIN_TYPE((VALUE)entry->cref) == T_IMEMO && IMEMO_TYPE_P(entry->cref, imemo_cref)));
- gc_mark(objspace, (VALUE) entry->cref);
+ rb_vm_t *vm = GET_VM();
- return ID_TABLE_CONTINUE;
-}
+ struct global_vm_table_foreach_data foreach_data = {
+ .callback = callback,
+ .update_callback = update_callback,
+ .data = data,
+ .weak_only = weak_only,
+ };
-static void
-mark_cvc_tbl(rb_objspace_t *objspace, VALUE klass)
-{
- struct rb_id_table *tbl = RCLASS_CVC_TBL(klass);
- if (tbl) {
- rb_id_table_foreach_values(tbl, mark_cvc_tbl_i, objspace);
+ switch (table) {
+ case RB_GC_VM_CI_TABLE: {
+ if (vm->ci_table) {
+ st_foreach_with_replace(
+ vm->ci_table,
+ vm_weak_table_foreach_weak_key,
+ vm_weak_table_foreach_update_weak_key,
+ (st_data_t)&foreach_data
+ );
+ }
+ break;
+ }
+ case RB_GC_VM_OVERLOADED_CME_TABLE: {
+ if (vm->overloaded_cme_table) {
+ st_foreach_with_replace(
+ vm->overloaded_cme_table,
+ vm_weak_table_foreach_weak_key,
+ vm_weak_table_foreach_update_weak_key,
+ (st_data_t)&foreach_data
+ );
+ }
+ break;
+ }
+ case RB_GC_VM_GLOBAL_SYMBOLS_TABLE: {
+ rb_sym_global_symbol_table_foreach_weak_reference(
+ vm_weak_table_sym_set_foreach,
+ &foreach_data
+ );
+ break;
+ }
+ case RB_GC_VM_ID2REF_TABLE: {
+ if (id2ref_tbl) {
+ st_foreach_with_replace(
+ id2ref_tbl,
+ vm_weak_table_id2ref_foreach,
+ vm_weak_table_id2ref_foreach_update,
+ (st_data_t)&foreach_data
+ );
+ }
+ break;
+ }
+ case RB_GC_VM_GENERIC_FIELDS_TABLE: {
+ st_table *generic_fields_tbl = rb_generic_fields_tbl_get();
+ if (generic_fields_tbl) {
+ st_foreach(
+ generic_fields_tbl,
+ vm_weak_table_gen_fields_foreach,
+ (st_data_t)&foreach_data
+ );
+ }
+ break;
+ }
+ case RB_GC_VM_FROZEN_STRINGS_TABLE: {
+ rb_fstring_foreach_with_replace(
+ vm_weak_table_frozen_strings_foreach,
+ &foreach_data
+ );
+ break;
+ }
+ case RB_GC_VM_CC_REFINEMENT_TABLE: {
+ if (vm->cc_refinement_table) {
+ set_foreach_with_replace(
+ vm->cc_refinement_table,
+ vm_weak_table_cc_refinement_foreach,
+ vm_weak_table_cc_refinement_foreach_update_update,
+ (st_data_t)&foreach_data
+ );
+ }
+ break;
+ }
+ case RB_GC_VM_WEAK_TABLE_COUNT:
+ rb_bug("Unreachable");
+ default:
+ rb_bug("rb_gc_vm_weak_table_foreach: unknown table %d", table);
}
}
-static enum rb_id_table_iterator_result
-update_const_table(VALUE value, void *data)
+void
+rb_gc_update_vm_references(void *objspace)
{
- rb_const_entry_t *ce = (rb_const_entry_t *)value;
- rb_objspace_t * objspace = (rb_objspace_t *)data;
-
- if (gc_object_moved_p(objspace, ce->value)) {
- ce->value = rb_gc_location(ce->value);
- }
-
- if (gc_object_moved_p(objspace, ce->file)) {
- ce->file = rb_gc_location(ce->file);
- }
+ rb_execution_context_t *ec = GET_EC();
+ rb_vm_t *vm = rb_ec_vm_ptr(ec);
- return ID_TABLE_CONTINUE;
-}
+ rb_vm_update_references(vm);
+ rb_gc_update_global_tbl();
+ rb_sym_global_symbols_mark_and_move();
-static void
-update_const_tbl(rb_objspace_t *objspace, struct rb_id_table *tbl)
-{
- if (!tbl) return;
- rb_id_table_foreach_values(tbl, update_const_table, objspace);
-}
+#if USE_YJIT
+ void rb_yjit_root_update_references(void); // in Rust
-static void
-update_subclass_entries(rb_objspace_t *objspace, rb_subclass_entry_t *entry)
-{
- while (entry) {
- UPDATE_IF_MOVED(objspace, entry->klass);
- entry = entry->next;
+ if (rb_yjit_enabled_p) {
+ rb_yjit_root_update_references();
}
-}
+#endif
-static void
-update_class_ext(rb_objspace_t *objspace, rb_classext_t *ext)
-{
- UPDATE_IF_MOVED(objspace, ext->origin_);
- UPDATE_IF_MOVED(objspace, ext->includer);
- UPDATE_IF_MOVED(objspace, ext->refined_class);
- update_subclass_entries(objspace, ext->subclasses);
-}
+#if USE_ZJIT
+ void rb_zjit_root_update_references(void); // in Rust
-static void
-update_superclasses(rb_objspace_t *objspace, VALUE obj)
-{
- if (FL_TEST_RAW(obj, RCLASS_SUPERCLASSES_INCLUDE_SELF)) {
- for (size_t i = 0; i < RCLASS_SUPERCLASS_DEPTH(obj) + 1; i++) {
- UPDATE_IF_MOVED(objspace, RCLASS_SUPERCLASSES(obj)[i]);
- }
+ if (rb_zjit_enabled_p) {
+ rb_zjit_root_update_references();
}
+#endif
}
-static void
-gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
+void
+rb_gc_update_object_references(void *objspace, VALUE obj)
{
- RVALUE *any = RANY(obj);
-
- gc_report(4, objspace, "update-refs: %p ->\n", (void *)obj);
-
- if (FL_TEST(obj, FL_EXIVAR)) {
- rb_ref_update_generic_ivar(obj);
- }
+ struct classext_foreach_args args;
switch (BUILTIN_TYPE(obj)) {
case T_CLASS:
- if (FL_TEST(obj, FL_SINGLETON)) {
+ if (FL_TEST_RAW(obj, FL_SINGLETON)) {
UPDATE_IF_MOVED(objspace, RCLASS_ATTACHED_OBJECT(obj));
}
// Continue to the shared T_CLASS/T_MODULE
case T_MODULE:
- if (RCLASS_SUPER((VALUE)obj)) {
- UPDATE_IF_MOVED(objspace, RCLASS(obj)->super);
- }
- update_m_tbl(objspace, RCLASS_M_TBL(obj));
- update_cc_tbl(objspace, obj);
- update_cvc_tbl(objspace, obj);
- update_superclasses(objspace, obj);
-
- if (rb_shape_obj_too_complex(obj)) {
- gc_ref_update_table_values_only(objspace, RCLASS_IV_HASH(obj));
- }
- else {
- for (attr_index_t i = 0; i < RCLASS_IV_COUNT(obj); i++) {
- UPDATE_IF_MOVED(objspace, RCLASS_IVPTR(obj)[i]);
- }
- }
-
- update_class_ext(objspace, RCLASS_EXT(obj));
- update_const_tbl(objspace, RCLASS_CONST_TBL(obj));
-
- UPDATE_IF_MOVED(objspace, RCLASS_EXT(obj)->classpath);
+ args.klass = obj;
+ args.objspace = objspace;
+ rb_class_classext_foreach(obj, update_classext, (void *)&args);
break;
case T_ICLASS:
- if (RICLASS_OWNS_M_TBL_P(obj)) {
- update_m_tbl(objspace, RCLASS_M_TBL(obj));
- }
- if (RCLASS_SUPER((VALUE)obj)) {
- UPDATE_IF_MOVED(objspace, RCLASS(obj)->super);
- }
- update_class_ext(objspace, RCLASS_EXT(obj));
- update_m_tbl(objspace, RCLASS_CALLABLE_M_TBL(obj));
- update_cc_tbl(objspace, obj);
+ args.objspace = objspace;
+ rb_class_classext_foreach(obj, update_iclass_classext, (void *)&args);
break;
case T_IMEMO:
@@ -10148,13 +4241,13 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
case T_HASH:
gc_ref_update_hash(objspace, obj);
- UPDATE_IF_MOVED(objspace, any->as.hash.ifnone);
+ UPDATE_IF_MOVED(objspace, RHASH(obj)->ifnone);
break;
case T_STRING:
{
if (STR_SHARED_P(obj)) {
- UPDATE_IF_MOVED(objspace, any->as.string.as.heap.aux.shared);
+ UPDATE_IF_MOVED(objspace, RSTRING(obj)->as.heap.aux.shared);
}
/* If, after move the string is not embedded, and can fit in the
@@ -10170,19 +4263,24 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
case T_DATA:
/* Call the compaction callback, if it exists */
{
- void *const ptr = RTYPEDDATA_P(obj) ? RTYPEDDATA_GET_DATA(obj) : DATA_PTR(obj);
+ bool typed_data = RTYPEDDATA_P(obj);
+ void *const ptr = typed_data ? RTYPEDDATA_GET_DATA(obj) : DATA_PTR(obj);
+
+ if (typed_data) {
+ UPDATE_IF_MOVED(objspace, RTYPEDDATA(obj)->fields_obj);
+ }
+
if (ptr) {
- if (RTYPEDDATA_P(obj) && gc_declarative_marking_p(any->as.typeddata.type)) {
- size_t *offset_list = (size_t *)RANY(obj)->as.typeddata.type->function.dmark;
+ if (typed_data && gc_declarative_marking_p(RTYPEDDATA_TYPE(obj))) {
+ size_t *offset_list = TYPED_DATA_REFS_OFFSET_LIST(obj);
for (size_t offset = *offset_list; offset != RUBY_REF_END; offset = *offset_list++) {
VALUE *ref = (VALUE *)((char *)ptr + offset);
- if (SPECIAL_CONST_P(*ref)) continue;
- *ref = rb_gc_location(*ref);
+ *ref = gc_location_internal(objspace, *ref);
}
}
- else if (RTYPEDDATA_P(obj)) {
- RUBY_DATA_FUNC compact_func = any->as.typeddata.type->function.dcompact;
+ else if (typed_data) {
+ RUBY_DATA_FUNC compact_func = RTYPEDDATA_TYPE(obj)->function.dcompact;
if (compact_func) (*compact_func)(ptr);
}
}
@@ -10194,22 +4292,24 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
break;
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);
- UPDATE_IF_MOVED(objspace, any->as.file.fptr->writeconv_pre_ecopts);
- UPDATE_IF_MOVED(objspace, any->as.file.fptr->encs.ecopts);
- UPDATE_IF_MOVED(objspace, any->as.file.fptr->write_lock);
+ if (RFILE(obj)->fptr) {
+ UPDATE_IF_MOVED(objspace, RFILE(obj)->fptr->self);
+ UPDATE_IF_MOVED(objspace, RFILE(obj)->fptr->pathv);
+ UPDATE_IF_MOVED(objspace, RFILE(obj)->fptr->tied_io_for_writing);
+ UPDATE_IF_MOVED(objspace, RFILE(obj)->fptr->writeconv_asciicompat);
+ UPDATE_IF_MOVED(objspace, RFILE(obj)->fptr->writeconv_pre_ecopts);
+ UPDATE_IF_MOVED(objspace, RFILE(obj)->fptr->encs.ecopts);
+ UPDATE_IF_MOVED(objspace, RFILE(obj)->fptr->write_lock);
+ UPDATE_IF_MOVED(objspace, RFILE(obj)->fptr->timeout);
+ UPDATE_IF_MOVED(objspace, RFILE(obj)->fptr->wakeup_mutex);
}
break;
case T_REGEXP:
- UPDATE_IF_MOVED(objspace, any->as.regexp.src);
+ UPDATE_IF_MOVED(objspace, RREGEXP(obj)->src);
break;
case T_SYMBOL:
- UPDATE_IF_MOVED(objspace, RSYMBOL(any)->fstr);
+ UPDATE_IF_MOVED(objspace, RSYMBOL(obj)->fstr);
break;
case T_FLOAT:
@@ -10217,21 +4317,21 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
break;
case T_MATCH:
- UPDATE_IF_MOVED(objspace, any->as.match.regexp);
+ UPDATE_IF_MOVED(objspace, RMATCH(obj)->regexp);
- if (any->as.match.str) {
- UPDATE_IF_MOVED(objspace, any->as.match.str);
+ if (RMATCH(obj)->str) {
+ UPDATE_IF_MOVED(objspace, RMATCH(obj)->str);
}
break;
case T_RATIONAL:
- UPDATE_IF_MOVED(objspace, any->as.rational.num);
- UPDATE_IF_MOVED(objspace, any->as.rational.den);
+ UPDATE_IF_MOVED(objspace, RRATIONAL(obj)->num);
+ UPDATE_IF_MOVED(objspace, RRATIONAL(obj)->den);
break;
case T_COMPLEX:
- UPDATE_IF_MOVED(objspace, any->as.complex.real);
- UPDATE_IF_MOVED(objspace, any->as.complex.imag);
+ UPDATE_IF_MOVED(objspace, RCOMPLEX(obj)->real);
+ UPDATE_IF_MOVED(objspace, RCOMPLEX(obj)->imag);
break;
@@ -10243,375 +4343,24 @@ gc_update_object_references(rb_objspace_t *objspace, VALUE obj)
for (i = 0; i < len; i++) {
UPDATE_IF_MOVED(objspace, ptr[i]);
}
- }
- break;
- default:
-#if GC_DEBUG
- rb_gcdebug_print_obj_condition((VALUE)obj);
- rb_obj_info_dump(obj);
- rb_bug("unreachable");
-#endif
- break;
-
- }
-
- UPDATE_IF_MOVED(objspace, RBASIC(obj)->klass);
-
- gc_report(4, objspace, "update-refs: %p <-\n", (void *)obj);
-}
-static int
-gc_ref_update(void *vstart, void *vend, size_t stride, rb_objspace_t * objspace, struct heap_page *page)
-{
- VALUE v = (VALUE)vstart;
- asan_unlock_freelist(page);
- asan_lock_freelist(page);
- page->flags.has_uncollectible_wb_unprotected_objects = FALSE;
- page->flags.has_remembered_objects = FALSE;
-
- /* For each object on the page */
- for (; v != (VALUE)vend; v += stride) {
- void *poisoned = asan_unpoison_object_temporary(v);
-
- switch (BUILTIN_TYPE(v)) {
- case T_NONE:
- case T_MOVED:
- case T_ZOMBIE:
- break;
- default:
- if (RVALUE_WB_UNPROTECTED(v)) {
- page->flags.has_uncollectible_wb_unprotected_objects = TRUE;
- }
- if (RVALUE_REMEMBERED(v)) {
- page->flags.has_remembered_objects = TRUE;
- }
- if (page->flags.before_sweep) {
- if (RVALUE_MARKED(v)) {
- gc_update_object_references(objspace, v);
+ if (RSTRUCT_EMBED_LEN(obj)) {
+ if (!FL_TEST_RAW(obj, RSTRUCT_GEN_FIELDS)) {
+ UPDATE_IF_MOVED(objspace, ptr[len]);
}
}
else {
- gc_update_object_references(objspace, v);
- }
- }
-
- if (poisoned) {
- asan_poison_object(v);
- }
- }
-
- return 0;
-}
-
-extern rb_symbols_t ruby_global_symbols;
-#define global_symbols ruby_global_symbols
-
-static void
-gc_update_references(rb_objspace_t *objspace)
-{
- objspace->flags.during_reference_updating = true;
-
- rb_execution_context_t *ec = GET_EC();
- rb_vm_t *vm = rb_ec_vm_ptr(ec);
-
- 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);
-
- ccan_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;
+ UPDATE_IF_MOVED(objspace, RSTRUCT(obj)->as.heap.fields_obj);
}
- if (should_set_mark_bits) {
- gc_setup_mark_bits(page);
- }
- }
- }
- rb_vm_update_references(vm);
- 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_ref_update_table_values_only(objspace, objspace->obj_to_id_tbl);
- gc_update_table_refs(objspace, objspace->id_to_obj_tbl);
- gc_update_table_refs(objspace, global_symbols.str_sym);
- gc_update_table_refs(objspace, finalizer_table);
-
- objspace->flags.during_reference_updating = false;
-}
-
-#if GC_CAN_COMPILE_COMPACTION
-/*
- * call-seq:
- * GC.latest_compact_info -> hash
- *
- * Returns information about object moved in the most recent \GC compaction.
- *
- * The returned +hash+ contains the following keys:
- *
- * [considered]
- * Hash containing the type of the object as the key and the number of
- * objects of that type that were considered for movement.
- * [moved]
- * Hash containing the type of the object as the key and the number of
- * objects of that type that were actually moved.
- * [moved_up]
- * Hash containing the type of the object as the key and the number of
- * objects of that type that were increased in size.
- * [moved_down]
- * Hash containing the type of the object as the key and the number of
- * objects of that type that were decreased in size.
- *
- * Some objects can't be moved (due to pinning) so these numbers can be used to
- * calculate compaction efficiency.
- */
-static VALUE
-gc_compact_stats(VALUE self)
-{
- size_t i;
- rb_objspace_t *objspace = &rb_objspace;
- VALUE h = rb_hash_new();
- VALUE considered = rb_hash_new();
- VALUE moved = rb_hash_new();
- VALUE moved_up = rb_hash_new();
- VALUE moved_down = rb_hash_new();
-
- for (i=0; i<T_MASK; i++) {
- if (objspace->rcompactor.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]));
- }
-
- if (objspace->rcompactor.moved_up_count_table[i]) {
- rb_hash_aset(moved_up, type_sym(i), SIZET2NUM(objspace->rcompactor.moved_up_count_table[i]));
- }
-
- if (objspace->rcompactor.moved_down_count_table[i]) {
- rb_hash_aset(moved_down, type_sym(i), SIZET2NUM(objspace->rcompactor.moved_down_count_table[i]));
- }
- }
-
- rb_hash_aset(h, ID2SYM(rb_intern("considered")), considered);
- rb_hash_aset(h, ID2SYM(rb_intern("moved")), moved);
- rb_hash_aset(h, ID2SYM(rb_intern("moved_up")), moved_up);
- rb_hash_aset(h, ID2SYM(rb_intern("moved_down")), moved_down);
-
- return h;
-}
-#else
-# define gc_compact_stats rb_f_notimplement
-#endif
-
-#if GC_CAN_COMPILE_COMPACTION
-static void
-root_obj_check_moved_i(const char *category, VALUE obj, void *data)
-{
- rb_objspace_t *objspace = data;
-
- if (gc_object_moved_p(objspace, obj)) {
- rb_bug("ROOT %s points to MOVED: %p -> %s", category, (void *)obj, obj_info(rb_gc_location(obj)));
- }
-}
-
-static void
-reachable_object_check_moved_i(VALUE ref, void *data)
-{
- VALUE parent = (VALUE)data;
- if (gc_object_moved_p(&rb_objspace, ref)) {
- rb_bug("Object %s points to MOVED: %p -> %s", obj_info(parent), (void *)ref, obj_info(rb_gc_location(ref)));
- }
-}
-
-static int
-heap_check_moved_i(void *vstart, void *vend, size_t stride, void *data)
-{
- rb_objspace_t *objspace = data;
-
- VALUE v = (VALUE)vstart;
- for (; v != (VALUE)vend; v += stride) {
- if (gc_object_moved_p(objspace, v)) {
- /* Moved object still on the heap, something may have a reference. */
- }
- else {
- void *poisoned = asan_unpoison_object_temporary(v);
-
- switch (BUILTIN_TYPE(v)) {
- case T_NONE:
- case T_ZOMBIE:
- break;
- default:
- if (!rb_objspace_garbage_object_p(v)) {
- rb_objspace_reachable_objects_from(v, reachable_object_check_moved_i, (void *)v);
- }
- }
-
- if (poisoned) {
- GC_ASSERT(BUILTIN_TYPE(v) == T_NONE);
- asan_poison_object(v);
- }
- }
- }
-
- return 0;
-}
-
-/*
- * call-seq:
- * GC.compact -> hash
- *
- * 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.
- *
- * The returned +hash+ contains statistics about the objects that were moved;
- * see GC.latest_compact_info.
- *
- * This method is only expected to work on CRuby.
- *
- * To test whether \GC compaction is supported, use the idiom:
- *
- * GC.respond_to?(:compact)
- */
-static VALUE
-gc_compact(VALUE self)
-{
- /* Run GC with compaction enabled */
- gc_start_internal(NULL, self, Qtrue, Qtrue, Qtrue, Qtrue);
-
- return gc_compact_stats(self);
-}
-#else
-# define gc_compact rb_f_notimplement
-#endif
-
-#if GC_CAN_COMPILE_COMPACTION
-
-struct desired_compaction_pages_i_data {
- rb_objspace_t *objspace;
- size_t required_slots[SIZE_POOL_COUNT];
-};
-
-static int
-desired_compaction_pages_i(struct heap_page *page, void *data)
-{
- struct desired_compaction_pages_i_data *tdata = data;
- rb_objspace_t *objspace = tdata->objspace;
- VALUE vstart = (VALUE)page->start;
- VALUE vend = vstart + (VALUE)(page->total_slots * page->size_pool->slot_size);
-
-
- for (VALUE v = vstart; v != vend; v += page->size_pool->slot_size) {
- /* skip T_NONEs; they won't be moved */
- void *poisoned = asan_unpoison_object_temporary(v);
- if (BUILTIN_TYPE(v) == T_NONE) {
- if (poisoned) {
- asan_poison_object(v);
- }
- continue;
- }
-
- rb_size_pool_t *dest_pool = gc_compact_destination_pool(objspace, page->size_pool, v);
- size_t dest_pool_idx = dest_pool - size_pools;
- tdata->required_slots[dest_pool_idx]++;
- }
-
- return 0;
-}
-
-static VALUE
-gc_verify_compaction_references(rb_execution_context_t *ec, VALUE self, VALUE double_heap, VALUE expand_heap, VALUE toward_empty)
-{
- rb_objspace_t *objspace = &rb_objspace;
-
- /* Clear the heap. */
- gc_start_internal(NULL, self, Qtrue, Qtrue, Qtrue, Qfalse);
-
- if (RTEST(double_heap)) {
- rb_warn("double_heap is deprecated, please use expand_heap instead");
- }
-
- RB_VM_LOCK_ENTER();
- {
- gc_rest(objspace);
-
- /* if both double_heap and expand_heap are set, expand_heap takes precedence */
- if (RTEST(expand_heap)) {
- struct desired_compaction_pages_i_data desired_compaction = {
- .objspace = objspace,
- .required_slots = {0},
- };
- /* Work out how many objects want to be in each size pool, taking account of moves */
- objspace_each_pages(objspace, desired_compaction_pages_i, &desired_compaction, TRUE);
-
- /* Find out which pool has the most pages */
- size_t max_existing_pages = 0;
- 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);
- max_existing_pages = MAX(max_existing_pages, heap->total_pages);
- }
- /* Add pages to each size pool so that compaction is guaranteed to move every object */
- 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);
-
- size_t pages_to_add = 0;
- /*
- * Step 1: Make sure every pool has the same number of pages, by adding empty pages
- * to smaller pools. This is required to make sure the compact cursor can advance
- * through all of the pools in `gc_sweep_compact` without hitting the "sweep &
- * compact cursors met" condition on some pools before fully compacting others
- */
- pages_to_add += max_existing_pages - heap->total_pages;
- /*
- * Step 2: Now add additional free pages to each size pool sufficient to hold all objects
- * that want to be in that size pool, whether moved into it or moved within it
- */
- pages_to_add += slots_to_pages_for_size_pool(objspace, size_pool, desired_compaction.required_slots[i]);
- /*
- * Step 3: Add two more pages so that the compact & sweep cursors will meet _after_ all objects
- * have been moved, and not on the last iteration of the `gc_sweep_compact` loop
- */
- pages_to_add += 2;
-
- heap_add_pages(objspace, size_pool, heap, pages_to_add);
- }
- }
- else 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);
- }
-
- }
-
- if (RTEST(toward_empty)) {
- objspace->rcompactor.compare_func = compare_free_slots;
}
+ break;
+ default:
+ rb_bug("unreachable");
+ break;
}
- RB_VM_LOCK_LEAVE();
- gc_start_internal(NULL, self, Qtrue, Qtrue, Qtrue, Qtrue);
-
- objspace_reachable_objects_from_root(objspace, root_obj_check_moved_i, objspace);
- objspace_each_objects(objspace, heap_check_moved_i, objspace, TRUE);
-
- objspace->rcompactor.compare_func = NULL;
- return gc_compact_stats(self);
+ UPDATE_IF_MOVED(objspace, RBASIC(obj)->klass);
}
-#else
-# define gc_verify_compaction_references (rb_builtin_arity3_function_type)rb_f_notimplement
-#endif
VALUE
rb_gc_start(void)
@@ -10624,38 +4373,22 @@ void
rb_gc(void)
{
unless_objspace(objspace) { return; }
- unsigned int reason = GPR_DEFAULT_REASON;
- garbage_collect(objspace, reason);
+
+ rb_gc_impl_start(objspace, true, true, true, false);
}
int
rb_during_gc(void)
{
unless_objspace(objspace) { return FALSE; }
- return during_gc;
-}
-
-#if RGENGC_PROFILE >= 2
-static const char *type_name(int type, VALUE obj);
-
-static void
-gc_count_add_each_types(VALUE hash, const char *name, const size_t *types)
-{
- VALUE result = rb_hash_new_with_size(T_MASK);
- int i;
- for (i=0; i<T_MASK; i++) {
- const char *type = type_name(i, 0);
- rb_hash_aset(result, ID2SYM(rb_intern(type)), SIZET2NUM(types[i]));
- }
- rb_hash_aset(hash, ID2SYM(rb_intern(name)), result);
+ return rb_gc_impl_during_gc_p(objspace);
}
-#endif
size_t
rb_gc_count(void)
{
- return rb_objspace.profile.count;
+ return rb_gc_impl_gc_count(rb_gc_get_objspace());
}
static VALUE
@@ -10664,542 +4397,155 @@ gc_count(rb_execution_context_t *ec, VALUE self)
return SIZET2NUM(rb_gc_count());
}
-static VALUE
-gc_info_decode(rb_objspace_t *objspace, const VALUE hash_or_key, const unsigned int orig_flags)
+VALUE
+rb_gc_latest_gc_info(VALUE key)
{
- static VALUE sym_major_by = Qnil, sym_gc_by, sym_immediate_sweep, sym_have_finalizer, sym_state, sym_need_major_by;
- static VALUE sym_nofree, sym_oldgen, sym_shady, sym_force, sym_stress;
-#if RGENGC_ESTIMATE_OLDMALLOC
- static VALUE sym_oldmalloc;
-#endif
- static VALUE sym_newobj, sym_malloc, sym_method, sym_capi;
- static VALUE sym_none, sym_marking, sym_sweeping;
- static VALUE sym_weak_references_count, sym_retained_weak_references_count;
- VALUE hash = Qnil, key = Qnil;
- VALUE major_by, need_major_by;
- unsigned int flags = orig_flags ? orig_flags : objspace->profile.latest_gc_info;
-
- if (SYMBOL_P(hash_or_key)) {
- key = hash_or_key;
- }
- else if (RB_TYPE_P(hash_or_key, T_HASH)) {
- hash = hash_or_key;
- }
- else {
+ if (!SYMBOL_P(key) && !RB_TYPE_P(key, T_HASH)) {
rb_raise(rb_eTypeError, "non-hash or symbol given");
}
- if (NIL_P(sym_major_by)) {
-#define S(s) sym_##s = ID2SYM(rb_intern_const(#s))
- S(major_by);
- S(gc_by);
- S(immediate_sweep);
- S(have_finalizer);
- S(state);
- S(need_major_by);
-
- S(stress);
- S(nofree);
- S(oldgen);
- S(shady);
- S(force);
-#if RGENGC_ESTIMATE_OLDMALLOC
- S(oldmalloc);
-#endif
- S(newobj);
- S(malloc);
- S(method);
- S(capi);
-
- S(none);
- S(marking);
- S(sweeping);
-
- S(weak_references_count);
- S(retained_weak_references_count);
-#undef S
- }
-
-#define SET(name, attr) \
- if (key == sym_##name) \
- return (attr); \
- else if (hash != Qnil) \
- rb_hash_aset(hash, sym_##name, (attr));
-
- major_by =
- (flags & GPR_FLAG_MAJOR_BY_NOFREE) ? sym_nofree :
- (flags & GPR_FLAG_MAJOR_BY_OLDGEN) ? sym_oldgen :
- (flags & GPR_FLAG_MAJOR_BY_SHADY) ? sym_shady :
- (flags & GPR_FLAG_MAJOR_BY_FORCE) ? sym_force :
-#if RGENGC_ESTIMATE_OLDMALLOC
- (flags & GPR_FLAG_MAJOR_BY_OLDMALLOC) ? sym_oldmalloc :
-#endif
- Qnil;
- SET(major_by, major_by);
-
- if (orig_flags == 0) { /* set need_major_by only if flags not set explicitly */
- unsigned int need_major_flags = gc_needs_major_flags;
- need_major_by =
- (need_major_flags & GPR_FLAG_MAJOR_BY_NOFREE) ? sym_nofree :
- (need_major_flags & GPR_FLAG_MAJOR_BY_OLDGEN) ? sym_oldgen :
- (need_major_flags & GPR_FLAG_MAJOR_BY_SHADY) ? sym_shady :
- (need_major_flags & GPR_FLAG_MAJOR_BY_FORCE) ? sym_force :
-#if RGENGC_ESTIMATE_OLDMALLOC
- (need_major_flags & GPR_FLAG_MAJOR_BY_OLDMALLOC) ? sym_oldmalloc :
-#endif
- Qnil;
- SET(need_major_by, need_major_by);
- }
-
- SET(gc_by,
- (flags & GPR_FLAG_NEWOBJ) ? sym_newobj :
- (flags & GPR_FLAG_MALLOC) ? sym_malloc :
- (flags & GPR_FLAG_METHOD) ? sym_method :
- (flags & GPR_FLAG_CAPI) ? sym_capi :
- (flags & GPR_FLAG_STRESS) ? sym_stress :
- Qnil
- );
-
- 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 :
- gc_mode(objspace) == gc_mode_marking ? sym_marking : sym_sweeping);
- }
+ VALUE val = rb_gc_impl_latest_gc_info(rb_gc_get_objspace(), key);
- SET(weak_references_count, LONG2FIX(objspace->profile.weak_references_count));
- SET(retained_weak_references_count, LONG2FIX(objspace->profile.retained_weak_references_count));
-#undef SET
-
- if (!NIL_P(key)) {/* matched key should return above */
+ if (val == Qundef) {
rb_raise(rb_eArgError, "unknown key: %"PRIsVALUE, rb_sym2str(key));
}
- return hash;
-}
-
-VALUE
-rb_gc_latest_gc_info(VALUE key)
-{
- rb_objspace_t *objspace = &rb_objspace;
- return gc_info_decode(objspace, key, 0);
+ return val;
}
static VALUE
-gc_latest_gc_info(rb_execution_context_t *ec, VALUE self, VALUE arg)
+gc_stat(rb_execution_context_t *ec, VALUE self, VALUE arg) // arg is (nil || hash || symbol)
{
- rb_objspace_t *objspace = &rb_objspace;
-
if (NIL_P(arg)) {
arg = rb_hash_new();
}
- else if (!SYMBOL_P(arg) && !RB_TYPE_P(arg, T_HASH)) {
+ else if (!RB_TYPE_P(arg, T_HASH) && !SYMBOL_P(arg)) {
rb_raise(rb_eTypeError, "non-hash or symbol given");
}
- return gc_info_decode(objspace, arg, 0);
-}
-
-enum gc_stat_sym {
- gc_stat_sym_count,
- gc_stat_sym_time,
- gc_stat_sym_marking_time,
- gc_stat_sym_sweeping_time,
- gc_stat_sym_heap_allocated_pages,
- gc_stat_sym_heap_sorted_length,
- gc_stat_sym_heap_allocatable_pages,
- gc_stat_sym_heap_available_slots,
- gc_stat_sym_heap_live_slots,
- gc_stat_sym_heap_free_slots,
- gc_stat_sym_heap_final_slots,
- gc_stat_sym_heap_marked_slots,
- gc_stat_sym_heap_eden_pages,
- gc_stat_sym_heap_tomb_pages,
- gc_stat_sym_total_allocated_pages,
- gc_stat_sym_total_freed_pages,
- gc_stat_sym_total_allocated_objects,
- gc_stat_sym_total_freed_objects,
- gc_stat_sym_malloc_increase_bytes,
- gc_stat_sym_malloc_increase_bytes_limit,
- 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,
- gc_stat_sym_old_objects_limit,
-#if RGENGC_ESTIMATE_OLDMALLOC
- gc_stat_sym_oldmalloc_increase_bytes,
- gc_stat_sym_oldmalloc_increase_bytes_limit,
-#endif
- gc_stat_sym_weak_references_count,
-#if RGENGC_PROFILE
- gc_stat_sym_total_generated_normal_object_count,
- gc_stat_sym_total_generated_shady_object_count,
- gc_stat_sym_total_shade_operation_count,
- gc_stat_sym_total_promoted_count,
- gc_stat_sym_total_remembered_normal_object_count,
- gc_stat_sym_total_remembered_shady_object_count,
-#endif
- gc_stat_sym_last
-};
+ VALUE ret = rb_gc_impl_stat(rb_gc_get_objspace(), arg);
-static VALUE gc_stat_symbols[gc_stat_sym_last];
+ if (ret == Qundef) {
+ GC_ASSERT(SYMBOL_P(arg));
-static void
-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(marking_time),
- S(sweeping_time),
- S(heap_allocated_pages);
- S(heap_sorted_length);
- S(heap_allocatable_pages);
- S(heap_available_slots);
- S(heap_live_slots);
- S(heap_free_slots);
- S(heap_final_slots);
- S(heap_marked_slots);
- S(heap_eden_pages);
- S(heap_tomb_pages);
- S(total_allocated_pages);
- S(total_freed_pages);
- S(total_allocated_objects);
- S(total_freed_objects);
- S(malloc_increase_bytes);
- S(malloc_increase_bytes_limit);
- 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);
- S(old_objects_limit);
-#if RGENGC_ESTIMATE_OLDMALLOC
- S(oldmalloc_increase_bytes);
- S(oldmalloc_increase_bytes_limit);
-#endif
- S(weak_references_count);
-#if RGENGC_PROFILE
- S(total_generated_normal_object_count);
- S(total_generated_shady_object_count);
- S(total_shade_operation_count);
- S(total_promoted_count);
- S(total_remembered_normal_object_count);
- S(total_remembered_shady_object_count);
-#endif /* RGENGC_PROFILE */
-#undef S
+ rb_raise(rb_eArgError, "unknown key: %"PRIsVALUE, rb_sym2str(arg));
}
-}
-static uint64_t
-ns_to_ms(uint64_t ns)
-{
- return ns / (1000 * 1000);
+ return ret;
}
-static size_t
-gc_stat_internal(VALUE hash_or_sym)
+size_t
+rb_gc_stat(VALUE arg)
{
- rb_objspace_t *objspace = &rb_objspace;
- VALUE hash = Qnil, key = Qnil;
-
- setup_gc_stat_symbols();
-
- if (RB_TYPE_P(hash_or_sym, T_HASH)) {
- hash = hash_or_sym;
- }
- else if (SYMBOL_P(hash_or_sym)) {
- key = hash_or_sym;
+ if (!RB_TYPE_P(arg, T_HASH) && !SYMBOL_P(arg)) {
+ rb_raise(rb_eTypeError, "non-hash or symbol given");
}
- else {
- rb_raise(rb_eTypeError, "non-hash or symbol argument");
- }
-
-#define SET(name, attr) \
- if (key == gc_stat_symbols[gc_stat_sym_##name]) \
- return attr; \
- else if (hash != Qnil) \
- rb_hash_aset(hash, gc_stat_symbols[gc_stat_sym_##name], SIZET2NUM(attr));
-
- SET(count, objspace->profile.count);
- SET(time, (size_t)ns_to_ms(objspace->profile.marking_time_ns + objspace->profile.sweeping_time_ns)); // TODO: UINT64T2NUM
- SET(marking_time, (size_t)ns_to_ms(objspace->profile.marking_time_ns));
- SET(sweeping_time, (size_t)ns_to_ms(objspace->profile.sweeping_time_ns));
-
- /* 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(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(objspace));
- SET(heap_tomb_pages, heap_tomb_total_pages(objspace));
- SET(total_allocated_pages, total_allocated_pages(objspace));
- SET(total_freed_pages, total_freed_pages(objspace));
- SET(total_allocated_objects, total_allocated_objects(objspace));
- SET(total_freed_objects, total_freed_objects(objspace));
- SET(malloc_increase_bytes, malloc_increase);
- SET(malloc_increase_bytes_limit, malloc_limit);
- 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);
- SET(old_objects_limit, objspace->rgengc.old_objects_limit);
-#if RGENGC_ESTIMATE_OLDMALLOC
- SET(oldmalloc_increase_bytes, objspace->rgengc.oldmalloc_increase);
- SET(oldmalloc_increase_bytes_limit, objspace->rgengc.oldmalloc_increase_limit);
-#endif
-#if RGENGC_PROFILE
- SET(total_generated_normal_object_count, objspace->profile.total_generated_normal_object_count);
- SET(total_generated_shady_object_count, objspace->profile.total_generated_shady_object_count);
- SET(total_shade_operation_count, objspace->profile.total_shade_operation_count);
- SET(total_promoted_count, objspace->profile.total_promoted_count);
- 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 */
-#undef SET
-
- if (!NIL_P(key)) { /* matched key should return above */
- rb_raise(rb_eArgError, "unknown key: %"PRIsVALUE, rb_sym2str(key));
- }
+ VALUE ret = rb_gc_impl_stat(rb_gc_get_objspace(), arg);
-#if defined(RGENGC_PROFILE) && RGENGC_PROFILE >= 2
- if (hash != Qnil) {
- gc_count_add_each_types(hash, "generated_normal_object_count_types", objspace->profile.generated_normal_object_count_types);
- gc_count_add_each_types(hash, "generated_shady_object_count_types", objspace->profile.generated_shady_object_count_types);
- gc_count_add_each_types(hash, "shade_operation_count_types", objspace->profile.shade_operation_count_types);
- gc_count_add_each_types(hash, "promoted_types", objspace->profile.promoted_types);
- gc_count_add_each_types(hash, "remembered_normal_object_count_types", objspace->profile.remembered_normal_object_count_types);
- gc_count_add_each_types(hash, "remembered_shady_object_count_types", objspace->profile.remembered_shady_object_count_types);
- }
-#endif
+ if (ret == Qundef) {
+ GC_ASSERT(SYMBOL_P(arg));
- return 0;
-}
-
-static VALUE
-gc_stat(rb_execution_context_t *ec, VALUE self, VALUE arg) // arg is (nil || hash || symbol)
-{
- if (NIL_P(arg)) {
- arg = rb_hash_new();
- }
- else if (SYMBOL_P(arg)) {
- size_t value = gc_stat_internal(arg);
- return SIZET2NUM(value);
- }
- else if (RB_TYPE_P(arg, T_HASH)) {
- // ok
- }
- else {
- rb_raise(rb_eTypeError, "non-hash or symbol given");
+ rb_raise(rb_eArgError, "unknown key: %"PRIsVALUE, rb_sym2str(arg));
}
- gc_stat_internal(arg);
- return arg;
-}
-
-size_t
-rb_gc_stat(VALUE key)
-{
- if (SYMBOL_P(key)) {
- size_t value = gc_stat_internal(key);
- return value;
+ if (SYMBOL_P(arg)) {
+ return NUM2SIZET(ret);
}
else {
- gc_stat_internal(key);
return 0;
}
}
-
-enum gc_stat_heap_sym {
- gc_stat_heap_sym_slot_size,
- gc_stat_heap_sym_heap_allocatable_pages,
- gc_stat_heap_sym_heap_eden_pages,
- gc_stat_heap_sym_heap_eden_slots,
- gc_stat_heap_sym_heap_tomb_pages,
- gc_stat_heap_sym_heap_tomb_slots,
- gc_stat_heap_sym_total_allocated_pages,
- gc_stat_heap_sym_total_freed_pages,
- gc_stat_heap_sym_force_major_gc_count,
- gc_stat_heap_sym_force_incremental_marking_finish_count,
- gc_stat_heap_sym_total_allocated_objects,
- gc_stat_heap_sym_total_freed_objects,
- gc_stat_heap_sym_last
-};
-
-static VALUE gc_stat_heap_symbols[gc_stat_heap_sym_last];
-
-static void
-setup_gc_stat_heap_symbols(void)
-{
- if (gc_stat_heap_symbols[0] == 0) {
-#define S(s) gc_stat_heap_symbols[gc_stat_heap_sym_##s] = ID2SYM(rb_intern_const(#s))
- S(slot_size);
- S(heap_allocatable_pages);
- S(heap_eden_pages);
- S(heap_eden_slots);
- S(heap_tomb_pages);
- S(heap_tomb_slots);
- S(total_allocated_pages);
- S(total_freed_pages);
- S(force_major_gc_count);
- S(force_incremental_marking_finish_count);
- S(total_allocated_objects);
- S(total_freed_objects);
-#undef S
- }
-}
-
-static size_t
-gc_stat_heap_internal(int size_pool_idx, VALUE hash_or_sym)
+static VALUE
+gc_stat_heap(rb_execution_context_t *ec, VALUE self, VALUE heap_name, VALUE arg)
{
- rb_objspace_t *objspace = &rb_objspace;
- VALUE hash = Qnil, key = Qnil;
-
- setup_gc_stat_heap_symbols();
+ if (NIL_P(arg)) {
+ arg = rb_hash_new();
+ }
- if (RB_TYPE_P(hash_or_sym, T_HASH)) {
- hash = hash_or_sym;
+ if (NIL_P(heap_name)) {
+ if (!RB_TYPE_P(arg, T_HASH)) {
+ rb_raise(rb_eTypeError, "non-hash given");
+ }
}
- else if (SYMBOL_P(hash_or_sym)) {
- key = hash_or_sym;
+ else if (FIXNUM_P(heap_name)) {
+ if (!SYMBOL_P(arg) && !RB_TYPE_P(arg, T_HASH)) {
+ rb_raise(rb_eTypeError, "non-hash or symbol given");
+ }
}
else {
- rb_raise(rb_eTypeError, "non-hash or symbol argument");
- }
-
- if (size_pool_idx < 0 || size_pool_idx >= SIZE_POOL_COUNT) {
- rb_raise(rb_eArgError, "size pool index out of range");
+ rb_raise(rb_eTypeError, "heap_name must be nil or an Integer");
}
- rb_size_pool_t *size_pool = &size_pools[size_pool_idx];
-
-#define SET(name, attr) \
- if (key == gc_stat_heap_symbols[gc_stat_heap_sym_##name]) \
- return attr; \
- else if (hash != Qnil) \
- rb_hash_aset(hash, gc_stat_heap_symbols[gc_stat_heap_sym_##name], SIZET2NUM(attr));
+ VALUE ret = rb_gc_impl_stat_heap(rb_gc_get_objspace(), heap_name, arg);
- SET(slot_size, size_pool->slot_size);
- SET(heap_allocatable_pages, size_pool->allocatable_pages);
- SET(heap_eden_pages, SIZE_POOL_EDEN_HEAP(size_pool)->total_pages);
- SET(heap_eden_slots, SIZE_POOL_EDEN_HEAP(size_pool)->total_slots);
- SET(heap_tomb_pages, SIZE_POOL_TOMB_HEAP(size_pool)->total_pages);
- SET(heap_tomb_slots, SIZE_POOL_TOMB_HEAP(size_pool)->total_slots);
- SET(total_allocated_pages, size_pool->total_allocated_pages);
- SET(total_freed_pages, size_pool->total_freed_pages);
- SET(force_major_gc_count, size_pool->force_major_gc_count);
- SET(force_incremental_marking_finish_count, size_pool->force_incremental_marking_finish_count);
- SET(total_allocated_objects, size_pool->total_allocated_objects);
- SET(total_freed_objects, size_pool->total_freed_objects);
-#undef SET
+ if (ret == Qundef) {
+ GC_ASSERT(SYMBOL_P(arg));
- if (!NIL_P(key)) { /* matched key should return above */
- rb_raise(rb_eArgError, "unknown key: %"PRIsVALUE, rb_sym2str(key));
+ rb_raise(rb_eArgError, "unknown key: %"PRIsVALUE, rb_sym2str(arg));
}
- return 0;
+ return ret;
}
static VALUE
-gc_stat_heap(rb_execution_context_t *ec, VALUE self, VALUE heap_name, VALUE arg)
+gc_config_get(rb_execution_context_t *ec, VALUE self)
{
- if (NIL_P(heap_name)) {
- if (NIL_P(arg)) {
- arg = rb_hash_new();
- }
- else if (RB_TYPE_P(arg, T_HASH)) {
- // ok
- }
- else {
- rb_raise(rb_eTypeError, "non-hash given");
- }
+ VALUE cfg_hash = rb_gc_impl_config_get(rb_gc_get_objspace());
+ rb_hash_aset(cfg_hash, sym("implementation"), rb_fstring_cstr(rb_gc_impl_active_gc_name()));
- for (int i = 0; i < SIZE_POOL_COUNT; i++) {
- VALUE hash = rb_hash_aref(arg, INT2FIX(i));
- if (NIL_P(hash)) {
- hash = rb_hash_new();
- rb_hash_aset(arg, INT2FIX(i), hash);
- }
- gc_stat_heap_internal(i, hash);
- }
- }
- else if (FIXNUM_P(heap_name)) {
- int size_pool_idx = FIX2INT(heap_name);
+ return cfg_hash;
+}
- if (NIL_P(arg)) {
- arg = rb_hash_new();
- }
- else if (SYMBOL_P(arg)) {
- size_t value = gc_stat_heap_internal(size_pool_idx, arg);
- return SIZET2NUM(value);
- }
- else if (RB_TYPE_P(arg, T_HASH)) {
- // ok
- }
- else {
- rb_raise(rb_eTypeError, "non-hash or symbol given");
- }
+static VALUE
+gc_config_set(rb_execution_context_t *ec, VALUE self, VALUE hash)
+{
+ void *objspace = rb_gc_get_objspace();
- gc_stat_heap_internal(size_pool_idx, arg);
- }
- else {
- rb_raise(rb_eTypeError, "heap_name must be nil or an Integer");
- }
+ rb_gc_impl_config_set(objspace, hash);
- return arg;
+ return Qnil;
}
static VALUE
gc_stress_get(rb_execution_context_t *ec, VALUE self)
{
- rb_objspace_t *objspace = &rb_objspace;
- return ruby_gc_stress_mode;
+ return rb_gc_impl_stress_get(rb_gc_get_objspace());
}
static VALUE
gc_stress_set_m(rb_execution_context_t *ec, VALUE self, VALUE flag)
{
- rb_objspace_t *objspace = &rb_objspace;
-
- objspace->flags.gc_stressful = RTEST(flag);
- objspace->gc_stress_mode = flag;
+ rb_gc_impl_stress_set(rb_gc_get_objspace(), flag);
return flag;
}
+void
+rb_gc_initial_stress_set(VALUE flag)
+{
+ initial_stress = flag;
+}
+
+size_t *
+rb_gc_heap_sizes(void)
+{
+ return rb_gc_impl_heap_sizes(rb_gc_get_objspace());
+}
+
VALUE
rb_gc_enable(void)
{
- rb_objspace_t *objspace = &rb_objspace;
- return rb_objspace_gc_enable(objspace);
+ return rb_objspace_gc_enable(rb_gc_get_objspace());
}
VALUE
-rb_objspace_gc_enable(rb_objspace_t *objspace)
+rb_objspace_gc_enable(void *objspace)
{
- int old = dont_gc_val();
-
- dont_gc_off();
- return RBOOL(old);
+ bool disabled = !rb_gc_impl_gc_enabled_p(objspace);
+ rb_gc_impl_gc_enable(objspace);
+ return RBOOL(disabled);
}
static VALUE
@@ -11208,33 +4554,32 @@ gc_enable(rb_execution_context_t *ec, VALUE _)
return rb_gc_enable();
}
-VALUE
-rb_gc_disable_no_rest(void)
+static VALUE
+gc_disable_no_rest(void *objspace)
{
- rb_objspace_t *objspace = &rb_objspace;
- return gc_disable_no_rest(objspace);
+ bool disabled = !rb_gc_impl_gc_enabled_p(objspace);
+ rb_gc_impl_gc_disable(objspace, false);
+ return RBOOL(disabled);
}
-static VALUE
-gc_disable_no_rest(rb_objspace_t *objspace)
+VALUE
+rb_gc_disable_no_rest(void)
{
- int old = dont_gc_val();
- dont_gc_on();
- return RBOOL(old);
+ return gc_disable_no_rest(rb_gc_get_objspace());
}
VALUE
rb_gc_disable(void)
{
- rb_objspace_t *objspace = &rb_objspace;
- return rb_objspace_gc_disable(objspace);
+ return rb_objspace_gc_disable(rb_gc_get_objspace());
}
VALUE
-rb_objspace_gc_disable(rb_objspace_t *objspace)
+rb_objspace_gc_disable(void *objspace)
{
- gc_rest(objspace);
- return gc_disable_no_rest(objspace);
+ bool disabled = !rb_gc_impl_gc_enabled_p(objspace);
+ rb_gc_impl_gc_disable(objspace, true);
+ return RBOOL(disabled);
}
static VALUE
@@ -11243,294 +4588,32 @@ gc_disable(rb_execution_context_t *ec, VALUE _)
return rb_gc_disable();
}
-#if GC_CAN_COMPILE_COMPACTION
-/*
- * 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.
- */
-static VALUE
-gc_set_auto_compact(VALUE _, VALUE v)
-{
- GC_ASSERT(GC_COMPACTION_SUPPORTED);
-
- ruby_enable_autocompact = RTEST(v);
-
-#if RGENGC_CHECK_MODE
- ruby_autocompact_compare_func = NULL;
-
- if (SYMBOL_P(v)) {
- ID id = RB_SYM2ID(v);
- if (id == rb_intern("empty")) {
- ruby_autocompact_compare_func = compare_free_slots;
- }
- }
-#endif
-
- return v;
-}
-#else
-# define gc_set_auto_compact rb_f_notimplement
-#endif
-
-#if GC_CAN_COMPILE_COMPACTION
-/*
- * call-seq:
- * GC.auto_compact -> true or false
- *
- * Returns whether or not automatic compaction has been enabled.
- */
-static VALUE
-gc_get_auto_compact(VALUE _)
-{
- return RBOOL(ruby_enable_autocompact);
-}
-#else
-# define gc_get_auto_compact rb_f_notimplement
-#endif
-
-static int
-get_envparam_size(const char *name, size_t *default_value, size_t lower_bound)
-{
- const char *ptr = getenv(name);
- ssize_t val;
-
- if (ptr != NULL && *ptr) {
- size_t unit = 0;
- char *end;
-#if SIZEOF_SIZE_T == SIZEOF_LONG_LONG
- val = strtoll(ptr, &end, 0);
-#else
- val = strtol(ptr, &end, 0);
-#endif
- switch (*end) {
- case 'k': case 'K':
- unit = 1024;
- ++end;
- break;
- case 'm': case 'M':
- unit = 1024*1024;
- ++end;
- break;
- case 'g': case 'G':
- unit = 1024*1024*1024;
- ++end;
- break;
- }
- while (*end && isspace((unsigned char)*end)) end++;
- if (*end) {
- if (RTEST(ruby_verbose)) fprintf(stderr, "invalid string for %s: %s\n", name, ptr);
- return 0;
- }
- if (unit > 0) {
- if (val < -(ssize_t)(SIZE_MAX / 2 / unit) || (ssize_t)(SIZE_MAX / 2 / unit) < val) {
- if (RTEST(ruby_verbose)) fprintf(stderr, "%s=%s is ignored because it overflows\n", name, ptr);
- return 0;
- }
- val *= unit;
- }
- if (val > 0 && (size_t)val > lower_bound) {
- if (RTEST(ruby_verbose)) {
- fprintf(stderr, "%s=%"PRIdSIZE" (default value: %"PRIuSIZE")\n", name, val, *default_value);
- }
- *default_value = (size_t)val;
- return 1;
- }
- else {
- if (RTEST(ruby_verbose)) {
- fprintf(stderr, "%s=%"PRIdSIZE" (default value: %"PRIuSIZE") is ignored because it must be greater than %"PRIuSIZE".\n",
- name, val, *default_value, lower_bound);
- }
- return 0;
- }
- }
- return 0;
-}
-
-static int
-get_envparam_double(const char *name, double *default_value, double lower_bound, double upper_bound, int accept_zero)
-{
- const char *ptr = getenv(name);
- double val;
-
- if (ptr != NULL && *ptr) {
- char *end;
- val = strtod(ptr, &end);
- if (!*ptr || *end) {
- if (RTEST(ruby_verbose)) fprintf(stderr, "invalid string for %s: %s\n", name, ptr);
- return 0;
- }
-
- if (accept_zero && val == 0.0) {
- goto accept;
- }
- else if (val <= lower_bound) {
- if (RTEST(ruby_verbose)) {
- fprintf(stderr, "%s=%f (default value: %f) is ignored because it must be greater than %f.\n",
- name, val, *default_value, lower_bound);
- }
- }
- else if (upper_bound != 0.0 && /* ignore upper_bound if it is 0.0 */
- val > upper_bound) {
- if (RTEST(ruby_verbose)) {
- fprintf(stderr, "%s=%f (default value: %f) is ignored because it must be lower than %f.\n",
- name, val, *default_value, upper_bound);
- }
- }
- else {
- 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
-gc_set_initial_pages(rb_objspace_t *objspace)
-{
- gc_rest(objspace);
-
- for (int i = 0; i < SIZE_POOL_COUNT; i++) {
- rb_size_pool_t *size_pool = &size_pools[i];
- char env_key[sizeof("RUBY_GC_HEAP_" "_INIT_SLOTS") + DECIMAL_SIZE_OF_BITS(sizeof(int) * CHAR_BIT)];
- snprintf(env_key, sizeof(env_key), "RUBY_GC_HEAP_%d_INIT_SLOTS", i);
-
- size_t size_pool_init_slots = gc_params.size_pool_init_slots[i];
- if (get_envparam_size(env_key, &size_pool_init_slots, 0)) {
- gc_params.size_pool_init_slots[i] = size_pool_init_slots;
- }
-
- if (size_pool_init_slots > size_pool->eden_heap.total_slots) {
- size_t slots = size_pool_init_slots - size_pool->eden_heap.total_slots;
- size_pool->allocatable_pages = slots_to_pages_for_size_pool(objspace, size_pool, slots);
- }
- else {
- /* We already have more slots than size_pool_init_slots allows, so
- * prevent creating more pages. */
- size_pool->allocatable_pages = 0;
- }
- }
- heap_pages_expand_sorted(objspace);
-}
-
-/*
- * GC tuning environment variables
- *
- * * RUBY_GC_HEAP_FREE_SLOTS
- * - Prepare at least this amount of slots after GC.
- * - Allocate slots if there are not enough slots.
- * * RUBY_GC_HEAP_GROWTH_FACTOR (new from 2.1)
- * - Allocate slots by this factor.
- * - (next slots number) = (current slots number) * (this factor)
- * * RUBY_GC_HEAP_GROWTH_MAX_SLOTS (new from 2.1)
- * - Allocation rate is limited to this number of slots.
- * * RUBY_GC_HEAP_FREE_SLOTS_MIN_RATIO (new from 2.4)
- * - Allocate additional pages when the number of free slots is
- * lower than the value (total_slots * (this ratio)).
- * * RUBY_GC_HEAP_FREE_SLOTS_GOAL_RATIO (new from 2.4)
- * - Allocate slots to satisfy this formula:
- * free_slots = total_slots * goal_ratio
- * - In other words, prepare (total_slots * goal_ratio) free slots.
- * - if this value is 0.0, then use RUBY_GC_HEAP_GROWTH_FACTOR directly.
- * * RUBY_GC_HEAP_FREE_SLOTS_MAX_RATIO (new from 2.4)
- * - Allow to free pages when the number of free slots is
- * greater than the value (total_slots * (this ratio)).
- * * RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR (new from 2.1.1)
- * - Do full GC when the number of old objects is more than R * N
- * where R is this factor and
- * N is the number of old objects just after last full GC.
- *
- * * obsolete
- * * RUBY_FREE_MIN -> RUBY_GC_HEAP_FREE_SLOTS (from 2.1)
- * * RUBY_HEAP_MIN_SLOTS -> RUBY_GC_HEAP_INIT_SLOTS (from 2.1)
- *
- * * RUBY_GC_MALLOC_LIMIT
- * * RUBY_GC_MALLOC_LIMIT_MAX (new from 2.1)
- * * RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR (new from 2.1)
- *
- * * RUBY_GC_OLDMALLOC_LIMIT (new from 2.1)
- * * RUBY_GC_OLDMALLOC_LIMIT_MAX (new from 2.1)
- * * RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR (new from 2.1)
- */
-
+// TODO: think about moving ruby_gc_set_params into Init_heap or Init_gc
void
ruby_gc_set_params(void)
{
- rb_objspace_t *objspace = &rb_objspace;
- /* RUBY_GC_HEAP_FREE_SLOTS */
- if (get_envparam_size("RUBY_GC_HEAP_FREE_SLOTS", &gc_params.heap_free_slots, 0)) {
- /* ok */
- }
-
- gc_set_initial_pages(objspace);
-
- 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);
- get_envparam_double("RUBY_GC_HEAP_FREE_SLOTS_MIN_RATIO", &gc_params.heap_free_slots_min_ratio,
- 0.0, 1.0, FALSE);
- get_envparam_double("RUBY_GC_HEAP_FREE_SLOTS_MAX_RATIO", &gc_params.heap_free_slots_max_ratio,
- gc_params.heap_free_slots_min_ratio, 1.0, FALSE);
- get_envparam_double("RUBY_GC_HEAP_FREE_SLOTS_GOAL_RATIO", &gc_params.heap_free_slots_goal_ratio,
- gc_params.heap_free_slots_min_ratio, gc_params.heap_free_slots_max_ratio, TRUE);
- get_envparam_double("RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR", &gc_params.oldobject_limit_factor, 0.0, 0.0, TRUE);
- get_envparam_double("RUBY_GC_HEAP_REMEMBERED_WB_UNPROTECTED_OBJECTS_LIMIT_RATIO", &gc_params.uncollectible_wb_unprotected_objects_limit_ratio, 0.0, 0.0, TRUE);
-
- if (get_envparam_size("RUBY_GC_MALLOC_LIMIT", &gc_params.malloc_limit_min, 0)) {
- malloc_limit = gc_params.malloc_limit_min;
- }
- get_envparam_size ("RUBY_GC_MALLOC_LIMIT_MAX", &gc_params.malloc_limit_max, 0);
- if (!gc_params.malloc_limit_max) { /* ignore max-check if 0 */
- gc_params.malloc_limit_max = SIZE_MAX;
- }
- get_envparam_double("RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR", &gc_params.malloc_limit_growth_factor, 1.0, 0.0, FALSE);
-
-#if RGENGC_ESTIMATE_OLDMALLOC
- if (get_envparam_size("RUBY_GC_OLDMALLOC_LIMIT", &gc_params.oldmalloc_limit_min, 0)) {
- objspace->rgengc.oldmalloc_increase_limit = gc_params.oldmalloc_limit_min;
- }
- get_envparam_size ("RUBY_GC_OLDMALLOC_LIMIT_MAX", &gc_params.oldmalloc_limit_max, 0);
- get_envparam_double("RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR", &gc_params.oldmalloc_limit_growth_factor, 1.0, 0.0, FALSE);
-#endif
-}
-
-static void
-reachable_objects_from_callback(VALUE obj)
-{
- rb_ractor_t *cr = GET_RACTOR();
- cr->mfd->mark_func(obj, cr->mfd->data);
+ rb_gc_impl_set_params(rb_gc_get_objspace());
}
void
rb_objspace_reachable_objects_from(VALUE obj, void (func)(VALUE, void *), void *data)
{
- rb_objspace_t *objspace = &rb_objspace;
+ RB_VM_LOCKING() {
+ if (rb_gc_impl_during_gc_p(rb_gc_get_objspace())) rb_bug("rb_objspace_reachable_objects_from() is not supported while during GC");
- RB_VM_LOCK_ENTER();
- {
- if (during_gc) rb_bug("rb_objspace_reachable_objects_from() is not supported while during_gc == true");
-
- if (is_markable_object(obj)) {
- rb_ractor_t *cr = GET_RACTOR();
+ if (!RB_SPECIAL_CONST_P(obj)) {
+ rb_vm_t *vm = GET_VM();
+ struct gc_mark_func_data_struct *prev_mfd = vm->gc.mark_func_data;
struct gc_mark_func_data_struct mfd = {
.mark_func = func,
.data = data,
- }, *prev_mfd = cr->mfd;
+ };
- cr->mfd = &mfd;
- gc_mark_children(objspace, obj);
- cr->mfd = prev_mfd;
+ vm->gc.mark_func_data = &mfd;
+ rb_gc_mark_children(rb_gc_get_objspace(), obj);
+ vm->gc.mark_func_data = prev_mfd;
}
}
- RB_VM_LOCK_LEAVE();
}
struct root_objects_data {
@@ -11549,1488 +4632,25 @@ root_objects_from(VALUE obj, void *ptr)
void
rb_objspace_reachable_objects_from_root(void (func)(const char *category, VALUE, void *), void *passing_data)
{
- rb_objspace_t *objspace = &rb_objspace;
- objspace_reachable_objects_from_root(objspace, func, passing_data);
-}
+ if (rb_gc_impl_during_gc_p(rb_gc_get_objspace())) rb_bug("rb_gc_impl_objspace_reachable_objects_from_root() is not supported while during GC");
-static void
-objspace_reachable_objects_from_root(rb_objspace_t *objspace, void (func)(const char *category, VALUE, void *), void *passing_data)
-{
- if (during_gc) rb_bug("objspace_reachable_objects_from_root() is not supported while during_gc == true");
+ rb_vm_t *vm = GET_VM();
- rb_ractor_t *cr = GET_RACTOR();
struct root_objects_data data = {
.func = func,
.data = passing_data,
};
+
+ struct gc_mark_func_data_struct *prev_mfd = vm->gc.mark_func_data;
struct gc_mark_func_data_struct mfd = {
.mark_func = root_objects_from,
.data = &data,
- }, *prev_mfd = cr->mfd;
-
- cr->mfd = &mfd;
- gc_mark_roots(objspace, &data.category);
- cr->mfd = prev_mfd;
-}
-
-/*
- ------------------------ Extended allocator ------------------------
-*/
-
-struct gc_raise_tag {
- VALUE exc;
- const char *fmt;
- va_list *ap;
-};
-
-static void *
-gc_vraise(void *ptr)
-{
- struct gc_raise_tag *argv = ptr;
- rb_vraise(argv->exc, argv->fmt, *argv->ap);
- UNREACHABLE_RETURN(NULL);
-}
-
-static void
-gc_raise(VALUE exc, const char *fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- struct gc_raise_tag argv = {
- exc, fmt, &ap,
};
- if (ruby_thread_has_gvl_p()) {
- gc_vraise(&argv);
- UNREACHABLE;
- }
- else if (ruby_native_thread_p()) {
- rb_thread_call_with_gvl(gc_vraise, &argv);
- UNREACHABLE;
- }
- else {
- /* Not in a ruby thread */
- fprintf(stderr, "%s", "[FATAL] ");
- vfprintf(stderr, fmt, ap);
- }
-
- va_end(ap);
- abort();
-}
-
-static void objspace_xfree(rb_objspace_t *objspace, void *ptr, size_t size);
-
-static void
-negative_size_allocation_error(const char *msg)
-{
- gc_raise(rb_eNoMemError, "%s", msg);
-}
-
-static void *
-ruby_memerror_body(void *dummy)
-{
- rb_memerror();
- return 0;
-}
-
-NORETURN(static void ruby_memerror(void));
-RBIMPL_ATTR_MAYBE_UNUSED()
-static void
-ruby_memerror(void)
-{
- if (ruby_thread_has_gvl_p()) {
- rb_memerror();
- }
- else {
- if (ruby_native_thread_p()) {
- rb_thread_call_with_gvl(ruby_memerror_body, 0);
- }
- else {
- /* no ruby thread */
- fprintf(stderr, "[FATAL] failed to allocate memory\n");
- }
- }
- exit(EXIT_FAILURE);
-}
-
-void
-rb_memerror(void)
-{
- rb_execution_context_t *ec = GET_EC();
- rb_objspace_t *objspace = rb_objspace_of(rb_ec_vm_ptr(ec));
- VALUE exc;
-
- if (0) {
- // Print out pid, sleep, so you can attach debugger to see what went wrong:
- fprintf(stderr, "rb_memerror pid=%"PRI_PIDT_PREFIX"d\n", getpid());
- sleep(60);
- }
-
- if (during_gc) {
- // TODO: OMG!! How to implement it?
- gc_exit(objspace, gc_enter_event_rb_memerror, NULL);
- }
-
- exc = nomem_error;
- if (!exc ||
- rb_ec_raised_p(ec, RAISED_NOMEMORY)) {
- fprintf(stderr, "[FATAL] failed to allocate memory\n");
- exit(EXIT_FAILURE);
- }
- if (rb_ec_raised_p(ec, RAISED_NOMEMORY)) {
- rb_ec_raised_clear(ec);
- }
- else {
- rb_ec_raised_set(ec, RAISED_NOMEMORY);
- exc = ruby_vm_special_exception_copy(exc);
- }
- ec->errinfo = exc;
- EC_JUMP_TAG(ec, TAG_RAISE);
-}
-
-static void
-rb_aligned_free(void *ptr, size_t size)
-{
-#if defined __MINGW32__
- __mingw_aligned_free(ptr);
-#elif defined _WIN32
- _aligned_free(ptr);
-#elif defined(HAVE_POSIX_MEMALIGN) || defined(HAVE_MEMALIGN)
- free(ptr);
-#else
- free(((void**)ptr)[-1]);
-#endif
-}
-
-static inline size_t
-objspace_malloc_size(rb_objspace_t *objspace, void *ptr, size_t hint)
-{
-#ifdef HAVE_MALLOC_USABLE_SIZE
- return malloc_usable_size(ptr);
-#else
- return hint;
-#endif
-}
-
-enum memop_type {
- MEMOP_TYPE_MALLOC = 0,
- MEMOP_TYPE_FREE,
- MEMOP_TYPE_REALLOC
-};
-
-static inline void
-atomic_sub_nounderflow(size_t *var, size_t sub)
-{
- if (sub == 0) return;
-
- while (1) {
- size_t val = *var;
- if (val < sub) sub = val;
- if (ATOMIC_SIZE_CAS(*var, val, val-sub) == val) break;
- }
-}
-
-static void
-objspace_malloc_gc_stress(rb_objspace_t *objspace)
-{
- if (ruby_gc_stressful && ruby_native_thread_p()) {
- 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;
- }
- garbage_collect_with_gvl(objspace, reason);
- }
-}
-
-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);
-#if RGENGC_ESTIMATE_OLDMALLOC
- ATOMIC_SIZE_ADD(objspace->rgengc.oldmalloc_increase, new_size - old_size);
-#endif
- }
- else {
- atomic_sub_nounderflow(&malloc_increase, old_size - new_size);
-#if RGENGC_ESTIMATE_OLDMALLOC
- atomic_sub_nounderflow(&objspace->rgengc.oldmalloc_increase, old_size - new_size);
-#endif
- }
-
- if (type == MEMOP_TYPE_MALLOC) {
- retry:
- 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;
- }
- garbage_collect_with_gvl(objspace, GPR_FLAG_MALLOC);
- }
- }
-
-#if MALLOC_ALLOCATED_SIZE
- if (new_size >= old_size) {
- ATOMIC_SIZE_ADD(objspace->malloc_params.allocated_size, new_size - old_size);
- }
- else {
- size_t dec_size = old_size - new_size;
- size_t allocated_size = objspace->malloc_params.allocated_size;
-
-#if MALLOC_ALLOCATED_SIZE_CHECK
- if (allocated_size < dec_size) {
- rb_bug("objspace_malloc_increase: underflow malloc_params.allocated_size.");
- }
-#endif
- atomic_sub_nounderflow(&objspace->malloc_params.allocated_size, dec_size);
- }
-
- switch (type) {
- case MEMOP_TYPE_MALLOC:
- ATOMIC_SIZE_INC(objspace->malloc_params.allocations);
- break;
- case MEMOP_TYPE_FREE:
- {
- size_t allocations = objspace->malloc_params.allocations;
- if (allocations > 0) {
- atomic_sub_nounderflow(&objspace->malloc_params.allocations, 1);
- }
-#if MALLOC_ALLOCATED_SIZE_CHECK
- else {
- GC_ASSERT(objspace->malloc_params.allocations > 0);
- }
-#endif
- }
- break;
- 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
- size_t gen;
- const char *file;
- size_t line;
-#endif
-};
-
-#if USE_GC_MALLOC_OBJ_INFO_DETAILS
-const char *ruby_malloc_info_file;
-int ruby_malloc_info_line;
-#endif
-
-static inline size_t
-objspace_malloc_prepare(rb_objspace_t *objspace, size_t size)
-{
- if (size == 0) size = 1;
-
-#if CALC_EXACT_MALLOC_SIZE
- size += sizeof(struct malloc_obj_info);
-#endif
-
- return size;
-}
-
-static bool
-malloc_during_gc_p(rb_objspace_t *objspace)
-{
- /* malloc is not allowed during GC when we're not using multiple ractors
- * (since ractors can run while another thread is sweeping) and when we
- * have the GVL (since if we don't have the GVL, we'll try to acquire the
- * GVL which will block and ensure the other thread finishes GC). */
- return during_gc && !dont_gc_val() && !rb_multi_ractor_p() && ruby_thread_has_gvl_p();
-}
-
-static inline void *
-objspace_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size)
-{
- size = objspace_malloc_size(objspace, mem, size);
- objspace_malloc_increase(objspace, mem, size, 0, MEMOP_TYPE_MALLOC) {}
-
-#if CALC_EXACT_MALLOC_SIZE
- {
- struct malloc_obj_info *info = mem;
- info->size = size;
-#if USE_GC_MALLOC_OBJ_INFO_DETAILS
- info->gen = objspace->profile.count;
- info->file = ruby_malloc_info_file;
- info->line = info->file ? ruby_malloc_info_line : 0;
-#endif
- mem = info + 1;
- }
-#endif
-
- return mem;
-}
-
-#if defined(__GNUC__) && RUBY_DEBUG
-#define RB_BUG_INSTEAD_OF_RB_MEMERROR 1
-#endif
-
-#ifndef RB_BUG_INSTEAD_OF_RB_MEMERROR
-# define RB_BUG_INSTEAD_OF_RB_MEMERROR 0
-#endif
-
-#define GC_MEMERROR(...) \
- ((RB_BUG_INSTEAD_OF_RB_MEMERROR+0) ? rb_bug("" __VA_ARGS__) : 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 */ \
- GC_MEMERROR("TRY_WITH_GC: could not GC"); \
- } \
- else if ((expr)) { \
- /* Success on 2nd try */ \
- } \
- else { \
- GC_MEMERROR("TRY_WITH_GC: could not allocate:" \
- "%"PRIdSIZE" bytes for %s", \
- siz, # expr); \
- } \
- } while (0)
-
-static void
-check_malloc_not_in_gc(rb_objspace_t *objspace, const char *msg)
-{
- if (UNLIKELY(malloc_during_gc_p(objspace))) {
- dont_gc_on();
- during_gc = false;
- rb_bug("Cannot %s during GC", msg);
- }
-}
-
-/* these shouldn't be called directly.
- * objspace_* functions do not check allocation size.
- */
-static void *
-objspace_xmalloc0(rb_objspace_t *objspace, size_t size)
-{
- check_malloc_not_in_gc(objspace, "malloc");
-
- void *mem;
-
- size = objspace_malloc_prepare(objspace, size);
- TRY_WITH_GC(size, mem = malloc(size));
- RB_DEBUG_COUNTER_INC(heap_xmalloc);
- return objspace_malloc_fixup(objspace, mem, size);
-}
-
-static inline size_t
-xmalloc2_size(const size_t count, const size_t elsize)
-{
- return size_mul_or_raise(count, elsize, rb_eArgError);
-}
-
-static void *
-objspace_xrealloc(rb_objspace_t *objspace, void *ptr, size_t new_size, size_t old_size)
-{
- check_malloc_not_in_gc(objspace, "realloc");
-
- void *mem;
-
- if (!ptr) return objspace_xmalloc0(objspace, new_size);
-
- /*
- * The behavior of realloc(ptr, 0) is implementation defined.
- * Therefore we don't use realloc(ptr, 0) for portability reason.
- * see http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_400.htm
- */
- if (new_size == 0) {
- if ((mem = objspace_xmalloc0(objspace, 0)) != NULL) {
- /*
- * - OpenBSD's malloc(3) man page says that when 0 is passed, it
- * returns a non-NULL pointer to an access-protected memory page.
- * The returned pointer cannot be read / written at all, but
- * still be a valid argument of free().
- *
- * https://man.openbsd.org/malloc.3
- *
- * - Linux's malloc(3) man page says that it _might_ perhaps return
- * a non-NULL pointer when its argument is 0. That return value
- * is safe (and is expected) to be passed to free().
- *
- * https://man7.org/linux/man-pages/man3/malloc.3.html
- *
- * - As I read the implementation jemalloc's malloc() returns fully
- * normal 16 bytes memory region when its argument is 0.
- *
- * - As I read the implementation musl libc's malloc() returns
- * fully normal 32 bytes memory region when its argument is 0.
- *
- * - Other malloc implementations can also return non-NULL.
- */
- objspace_xfree(objspace, ptr, old_size);
- return mem;
- }
- else {
- /*
- * It is dangerous to return NULL here, because that could lead to
- * RCE. Fallback to 1 byte instead of zero.
- *
- * https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-11932
- */
- new_size = 1;
- }
- }
-
-#if CALC_EXACT_MALLOC_SIZE
- {
- struct malloc_obj_info *info = (struct malloc_obj_info *)ptr - 1;
- new_size += sizeof(struct malloc_obj_info);
- ptr = info;
- old_size = info->size;
- }
-#endif
-
- old_size = objspace_malloc_size(objspace, ptr, old_size);
- TRY_WITH_GC(new_size, mem = RB_GNUC_EXTENSION_BLOCK(realloc(ptr, new_size)));
- new_size = objspace_malloc_size(objspace, mem, new_size);
-
-#if CALC_EXACT_MALLOC_SIZE
- {
- struct malloc_obj_info *info = mem;
- info->size = new_size;
- mem = info + 1;
- }
-#endif
-
- objspace_malloc_increase(objspace, mem, new_size, old_size, MEMOP_TYPE_REALLOC);
-
- RB_DEBUG_COUNTER_INC(heap_xrealloc);
- return mem;
-}
-
-#if CALC_EXACT_MALLOC_SIZE && USE_GC_MALLOC_OBJ_INFO_DETAILS
-
-#define MALLOC_INFO_GEN_SIZE 100
-#define MALLOC_INFO_SIZE_SIZE 10
-static size_t malloc_info_gen_cnt[MALLOC_INFO_GEN_SIZE];
-static size_t malloc_info_gen_size[MALLOC_INFO_GEN_SIZE];
-static size_t malloc_info_size[MALLOC_INFO_SIZE_SIZE+1];
-static st_table *malloc_info_file_table;
-
-static int
-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%"PRIdSIZE"\t%"PRIdSIZE"\n", file, data[0], data[1]);
-
- return ST_CONTINUE;
-}
-
-__attribute__((destructor))
-void
-rb_malloc_info_show_results(void)
-{
- int i;
-
- fprintf(stderr, "* malloc_info gen statistics\n");
- for (i=0; i<MALLOC_INFO_GEN_SIZE; i++) {
- if (i == MALLOC_INFO_GEN_SIZE-1) {
- fprintf(stderr, "more\t%"PRIdSIZE"\t%"PRIdSIZE"\n", malloc_info_gen_cnt[i], malloc_info_gen_size[i]);
- }
- else {
- fprintf(stderr, "%d\t%"PRIdSIZE"\t%"PRIdSIZE"\n", i, malloc_info_gen_cnt[i], malloc_info_gen_size[i]);
- }
- }
-
- fprintf(stderr, "* malloc_info size statistics\n");
- for (i=0; i<MALLOC_INFO_SIZE_SIZE; i++) {
- int s = 16 << i;
- fprintf(stderr, "%d\t%"PRIdSIZE"\n", s, malloc_info_size[i]);
- }
- fprintf(stderr, "more\t%"PRIdSIZE"\n", malloc_info_size[i]);
-
- if (malloc_info_file_table) {
- fprintf(stderr, "* malloc_info file statistics\n");
- st_foreach(malloc_info_file_table, mmalloc_info_file_i, 0);
- }
-}
-#else
-void
-rb_malloc_info_show_results(void)
-{
-}
-#endif
-
-static void
-objspace_xfree(rb_objspace_t *objspace, void *ptr, size_t old_size)
-{
- if (!ptr) {
- /*
- * ISO/IEC 9899 says "If ptr is a null pointer, no action occurs" since
- * its first version. We would better follow.
- */
- return;
- }
-#if CALC_EXACT_MALLOC_SIZE
- struct malloc_obj_info *info = (struct malloc_obj_info *)ptr - 1;
- ptr = info;
- old_size = info->size;
-
-#if USE_GC_MALLOC_OBJ_INFO_DETAILS
- {
- int gen = (int)(objspace->profile.count - info->gen);
- int gen_index = gen >= MALLOC_INFO_GEN_SIZE ? MALLOC_INFO_GEN_SIZE-1 : gen;
- int i;
-
- malloc_info_gen_cnt[gen_index]++;
- malloc_info_gen_size[gen_index] += info->size;
-
- for (i=0; i<MALLOC_INFO_SIZE_SIZE; i++) {
- size_t s = 16 << i;
- if (info->size <= s) {
- malloc_info_size[i]++;
- goto found;
- }
- }
- malloc_info_size[i]++;
- found:;
-
- {
- 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, &d)) {
- /* hit */
- data = (size_t *)d;
- }
- else {
- data = malloc(xmalloc2_size(2, sizeof(size_t)));
- if (data == NULL) rb_bug("objspace_xfree: can not allocate memory");
- data[0] = data[1] = 0;
- st_insert(malloc_info_file_table, key, (st_data_t)data);
- }
- data[0] ++;
- data[1] += info->size;
- };
- if (0 && gen >= 2) { /* verbose output */
- if (info->file) {
- fprintf(stderr, "free - size:%"PRIdSIZE", gen:%d, pos: %s:%"PRIdSIZE"\n",
- info->size, gen, info->file, info->line);
- }
- else {
- fprintf(stderr, "free - size:%"PRIdSIZE", gen:%d\n",
- info->size, gen);
- }
- }
- }
-#endif
-#endif
- old_size = objspace_malloc_size(objspace, ptr, old_size);
-
- objspace_malloc_increase(objspace, ptr, 0, old_size, MEMOP_TYPE_FREE) {
- free(ptr);
- ptr = NULL;
- RB_DEBUG_COUNTER_INC(heap_xfree);
- }
-}
-
-static void *
-ruby_xmalloc0(size_t size)
-{
- return objspace_xmalloc0(&rb_objspace, size);
-}
-
-void *
-ruby_xmalloc_body(size_t size)
-{
- if ((ssize_t)size < 0) {
- negative_size_allocation_error("too large allocation size");
- }
- return ruby_xmalloc0(size);
-}
-
-void
-ruby_malloc_size_overflow(size_t count, size_t elsize)
-{
- rb_raise(rb_eArgError,
- "malloc: possible integer overflow (%"PRIuSIZE"*%"PRIuSIZE")",
- count, elsize);
-}
-
-void *
-ruby_xmalloc2_body(size_t n, size_t size)
-{
- return objspace_xmalloc0(&rb_objspace, xmalloc2_size(n, size));
-}
-
-static void *
-objspace_xcalloc(rb_objspace_t *objspace, size_t size)
-{
- if (UNLIKELY(malloc_during_gc_p(objspace))) {
- rb_warn("calloc during GC detected, this could cause crashes if it triggers another GC");
-#if RGENGC_CHECK_MODE || RUBY_DEBUG
- rb_bug("Cannot calloc during GC");
-#endif
- }
-
- void *mem;
-
- size = objspace_malloc_prepare(objspace, size);
- TRY_WITH_GC(size, mem = calloc1(size));
- return objspace_malloc_fixup(objspace, mem, size);
-}
-
-void *
-ruby_xcalloc_body(size_t n, size_t size)
-{
- return objspace_xcalloc(&rb_objspace, xmalloc2_size(n, size));
-}
-
-#ifdef ruby_sized_xrealloc
-#undef ruby_sized_xrealloc
-#endif
-void *
-ruby_sized_xrealloc(void *ptr, size_t new_size, size_t old_size)
-{
- if ((ssize_t)new_size < 0) {
- negative_size_allocation_error("too large allocation size");
- }
-
- return objspace_xrealloc(&rb_objspace, ptr, new_size, old_size);
-}
-
-void *
-ruby_xrealloc_body(void *ptr, size_t new_size)
-{
- return ruby_sized_xrealloc(ptr, new_size, 0);
-}
-
-#ifdef ruby_sized_xrealloc2
-#undef ruby_sized_xrealloc2
-#endif
-void *
-ruby_sized_xrealloc2(void *ptr, size_t n, size_t size, size_t old_n)
-{
- size_t len = xmalloc2_size(n, size);
- return objspace_xrealloc(&rb_objspace, ptr, len, old_n * size);
-}
-
-void *
-ruby_xrealloc2_body(void *ptr, size_t n, size_t size)
-{
- return ruby_sized_xrealloc2(ptr, n, size, 0);
-}
-
-#ifdef ruby_sized_xfree
-#undef ruby_sized_xfree
-#endif
-void
-ruby_sized_xfree(void *x, size_t size)
-{
- if (LIKELY(x)) {
- /* It's possible for a C extension's pthread destructor function set by pthread_key_create
- * to be called after ruby_vm_destruct and attempt to free memory. Fall back to mimfree in
- * that case. */
- if (LIKELY(GET_VM())) {
- objspace_xfree(&rb_objspace, x, size);
- }
- else {
- ruby_mimfree(x);
- }
- }
-}
-
-void
-ruby_xfree(void *x)
-{
- ruby_sized_xfree(x, 0);
-}
-
-void *
-rb_xmalloc_mul_add(size_t x, size_t y, size_t z) /* x * y + z */
-{
- size_t w = size_mul_add_or_raise(x, y, z, rb_eArgError);
- return ruby_xmalloc(w);
-}
-
-void *
-rb_xcalloc_mul_add(size_t x, size_t y, size_t z) /* x * y + z */
-{
- size_t w = size_mul_add_or_raise(x, y, z, rb_eArgError);
- return ruby_xcalloc(w, 1);
-}
-
-void *
-rb_xrealloc_mul_add(const void *p, size_t x, size_t y, size_t z) /* x * y + z */
-{
- size_t w = size_mul_add_or_raise(x, y, z, rb_eArgError);
- return ruby_xrealloc((void *)p, w);
-}
-
-void *
-rb_xmalloc_mul_add_mul(size_t x, size_t y, size_t z, size_t w) /* x * y + z * w */
-{
- size_t u = size_mul_add_mul_or_raise(x, y, z, w, rb_eArgError);
- return ruby_xmalloc(u);
-}
-
-void *
-rb_xcalloc_mul_add_mul(size_t x, size_t y, size_t z, size_t w) /* x * y + z * w */
-{
- size_t u = size_mul_add_mul_or_raise(x, y, z, w, rb_eArgError);
- return ruby_xcalloc(u, 1);
-}
-
-/* Mimic ruby_xmalloc, but need not rb_objspace.
- * should return pointer suitable for ruby_xfree
- */
-void *
-ruby_mimmalloc(size_t size)
-{
- void *mem;
-#if CALC_EXACT_MALLOC_SIZE
- size += sizeof(struct malloc_obj_info);
-#endif
- mem = malloc(size);
-#if CALC_EXACT_MALLOC_SIZE
- if (!mem) {
- return NULL;
- }
- else
- /* set 0 for consistency of allocated_size/allocations */
- {
- struct malloc_obj_info *info = mem;
- info->size = 0;
-#if USE_GC_MALLOC_OBJ_INFO_DETAILS
- info->gen = 0;
- info->file = NULL;
- info->line = 0;
-#endif
- mem = info + 1;
- }
-#endif
- return mem;
-}
-
-void *
-ruby_mimcalloc(size_t num, size_t size)
-{
- void *mem;
-#if CALC_EXACT_MALLOC_SIZE
- struct rbimpl_size_mul_overflow_tag t = rbimpl_size_mul_overflow(num, size);
- if (UNLIKELY(t.left)) {
- return NULL;
- }
- size = t.right + sizeof(struct malloc_obj_info);
- mem = calloc1(size);
- if (!mem) {
- return NULL;
- }
- else
- /* set 0 for consistency of allocated_size/allocations */
- {
- struct malloc_obj_info *info = mem;
- info->size = 0;
-#if USE_GC_MALLOC_OBJ_INFO_DETAILS
- info->gen = 0;
- info->file = NULL;
- info->line = 0;
-#endif
- mem = info + 1;
- }
-#else
- mem = calloc(num, size);
-#endif
- return mem;
-}
-
-void
-ruby_mimfree(void *ptr)
-{
-#if CALC_EXACT_MALLOC_SIZE
- struct malloc_obj_info *info = (struct malloc_obj_info *)ptr - 1;
- ptr = info;
-#endif
- free(ptr);
-}
-
-#if MALLOC_ALLOCATED_SIZE
-/*
- * call-seq:
- * GC.malloc_allocated_size -> Integer
- *
- * Returns the size of memory allocated by malloc().
- *
- * Only available if ruby was built with +CALC_EXACT_MALLOC_SIZE+.
- */
-
-static VALUE
-gc_malloc_allocated_size(VALUE self)
-{
- return UINT2NUM(rb_objspace.malloc_params.allocated_size);
-}
-
-/*
- * call-seq:
- * GC.malloc_allocations -> Integer
- *
- * Returns the number of malloc() allocations.
- *
- * Only available if ruby was built with +CALC_EXACT_MALLOC_SIZE+.
- */
-
-static VALUE
-gc_malloc_allocations(VALUE self)
-{
- return UINT2NUM(rb_objspace.malloc_params.allocations);
-}
-#endif
-
-void
-rb_gc_adjust_memory_usage(ssize_t diff)
-{
- unless_objspace(objspace) { return; }
-
- if (diff > 0) {
- objspace_malloc_increase(objspace, 0, diff, 0, MEMOP_TYPE_REALLOC);
- }
- else if (diff < 0) {
- objspace_malloc_increase(objspace, 0, 0, -diff, MEMOP_TYPE_REALLOC);
- }
-}
-
-/*
- ------------------------------ GC profiler ------------------------------
-*/
-
-#define GC_PROFILE_RECORD_DEFAULT_SIZE 100
-
-static bool
-current_process_time(struct timespec *ts)
-{
-#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID)
- {
- static int try_clock_gettime = 1;
- if (try_clock_gettime && clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ts) == 0) {
- return true;
- }
- else {
- try_clock_gettime = 0;
- }
- }
-#endif
-
-#ifdef RUSAGE_SELF
- {
- struct rusage usage;
- struct timeval time;
- if (getrusage(RUSAGE_SELF, &usage) == 0) {
- time = usage.ru_utime;
- ts->tv_sec = time.tv_sec;
- ts->tv_nsec = (int32_t)time.tv_usec * 1000;
- return true;
- }
- }
-#endif
-
-#ifdef _WIN32
- {
- FILETIME creation_time, exit_time, kernel_time, user_time;
- ULARGE_INTEGER ui;
-
- if (GetProcessTimes(GetCurrentProcess(),
- &creation_time, &exit_time, &kernel_time, &user_time) != 0) {
- 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 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, unsigned int reason)
-{
- if (objspace->profile.run) {
- size_t index = objspace->profile.next_index;
- gc_profile_record *record;
-
- /* create new record */
- objspace->profile.next_index++;
-
- if (!objspace->profile.records) {
- objspace->profile.size = GC_PROFILE_RECORD_DEFAULT_SIZE;
- objspace->profile.records = malloc(xmalloc2_size(sizeof(gc_profile_record), objspace->profile.size));
- }
- if (index >= objspace->profile.size) {
- void *ptr;
- objspace->profile.size += 1000;
- ptr = realloc(objspace->profile.records, xmalloc2_size(sizeof(gc_profile_record), objspace->profile.size));
- if (!ptr) rb_memerror();
- objspace->profile.records = ptr;
- }
- if (!objspace->profile.records) {
- rb_bug("gc_profile malloc or realloc miss");
- }
- record = objspace->profile.current_record = &objspace->profile.records[objspace->profile.next_index - 1];
- MEMZERO(record, gc_profile_record, 1);
-
- /* setup before-GC parameter */
- record->flags = reason | (ruby_gc_stressful ? GPR_FLAG_STRESS : 0);
-#if MALLOC_ALLOCATED_SIZE
- record->allocated_size = malloc_allocated_size;
-#endif
-#if GC_PROFILE_MORE_DETAIL && GC_PROFILE_DETAIL_MEMORY
-#ifdef RUSAGE_SELF
- {
- struct rusage usage;
- if (getrusage(RUSAGE_SELF, &usage) == 0) {
- record->maxrss = usage.ru_maxrss;
- record->minflt = usage.ru_minflt;
- record->majflt = usage.ru_majflt;
- }
- }
-#endif
-#endif
- }
-}
-
-static inline void
-gc_prof_timer_start(rb_objspace_t *objspace)
-{
- if (gc_prof_enabled(objspace)) {
- gc_profile_record *record = gc_prof_record(objspace);
-#if GC_PROFILE_MORE_DETAIL
- record->prepare_time = objspace->profile.prepare_time;
-#endif
- record->gc_time = 0;
- record->gc_invoke_time = getrusage_time();
- }
-}
-
-static double
-elapsed_time_from(double time)
-{
- double now = getrusage_time();
- if (now > time) {
- return now - time;
- }
- else {
- return 0;
- }
-}
-
-static inline void
-gc_prof_timer_stop(rb_objspace_t *objspace)
-{
- if (gc_prof_enabled(objspace)) {
- gc_profile_record *record = gc_prof_record(objspace);
- record->gc_time = elapsed_time_from(record->gc_invoke_time);
- record->gc_invoke_time -= objspace->profile.invoke_time;
- }
-}
-
-#define RUBY_DTRACE_GC_HOOK(name) \
- do {if (RUBY_DTRACE_GC_##name##_ENABLED()) RUBY_DTRACE_GC_##name();} while (0)
-static inline void
-gc_prof_mark_timer_start(rb_objspace_t *objspace)
-{
- RUBY_DTRACE_GC_HOOK(MARK_BEGIN);
-#if GC_PROFILE_MORE_DETAIL
- if (gc_prof_enabled(objspace)) {
- gc_prof_record(objspace)->gc_mark_time = getrusage_time();
- }
-#endif
-}
-
-static inline void
-gc_prof_mark_timer_stop(rb_objspace_t *objspace)
-{
- RUBY_DTRACE_GC_HOOK(MARK_END);
-#if GC_PROFILE_MORE_DETAIL
- if (gc_prof_enabled(objspace)) {
- gc_profile_record *record = gc_prof_record(objspace);
- record->gc_mark_time = elapsed_time_from(record->gc_mark_time);
- }
-#endif
-}
-
-static inline void
-gc_prof_sweep_timer_start(rb_objspace_t *objspace)
-{
- RUBY_DTRACE_GC_HOOK(SWEEP_BEGIN);
- if (gc_prof_enabled(objspace)) {
- gc_profile_record *record = gc_prof_record(objspace);
-
- if (record->gc_time > 0 || GC_PROFILE_MORE_DETAIL) {
- objspace->profile.gc_sweep_start_time = getrusage_time();
- }
- }
-}
-
-static inline void
-gc_prof_sweep_timer_stop(rb_objspace_t *objspace)
-{
- RUBY_DTRACE_GC_HOOK(SWEEP_END);
-
- if (gc_prof_enabled(objspace)) {
- double sweep_time;
- gc_profile_record *record = gc_prof_record(objspace);
-
- if (record->gc_time > 0) {
- sweep_time = elapsed_time_from(objspace->profile.gc_sweep_start_time);
- /* need to accumulate GC time for lazy sweep after gc() */
- record->gc_time += sweep_time;
- }
- else if (GC_PROFILE_MORE_DETAIL) {
- sweep_time = elapsed_time_from(objspace->profile.gc_sweep_start_time);
- }
-
-#if GC_PROFILE_MORE_DETAIL
- record->gc_sweep_time += sweep_time;
- if (heap_pages_deferred_final) record->flags |= GPR_FLAG_HAVE_FINALIZE;
-#endif
- if (heap_pages_deferred_final) objspace->profile.latest_gc_info |= GPR_FLAG_HAVE_FINALIZE;
- }
-}
-
-static inline void
-gc_prof_set_malloc_info(rb_objspace_t *objspace)
-{
-#if GC_PROFILE_MORE_DETAIL
- if (gc_prof_enabled(objspace)) {
- gc_profile_record *record = gc_prof_record(objspace);
- record->allocate_increase = malloc_increase;
- record->allocate_limit = malloc_limit;
- }
-#endif
-}
-
-static inline void
-gc_prof_set_heap_info(rb_objspace_t *objspace)
-{
- if (gc_prof_enabled(objspace)) {
- gc_profile_record *record = gc_prof_record(objspace);
- size_t live = objspace->profile.total_allocated_objects_at_gc_start - total_freed_objects(objspace);
- size_t total = objspace->profile.heap_used_at_gc_start * HEAP_PAGE_OBJ_LIMIT;
-
-#if GC_PROFILE_MORE_DETAIL
- record->heap_use_pages = objspace->profile.heap_used_at_gc_start;
- record->heap_live_objects = live;
- record->heap_free_objects = total - live;
-#endif
-
- record->heap_total_objects = total;
- record->heap_use_size = live * sizeof(RVALUE);
- record->heap_total_size = total * sizeof(RVALUE);
- }
-}
-
-/*
- * call-seq:
- * GC::Profiler.clear -> nil
- *
- * Clears the \GC profiler data.
- *
- */
-
-static VALUE
-gc_profile_clear(VALUE _)
-{
- rb_objspace_t *objspace = &rb_objspace;
- void *p = objspace->profile.records;
- objspace->profile.records = NULL;
- objspace->profile.size = 0;
- objspace->profile.next_index = 0;
- objspace->profile.current_record = 0;
- free(p);
- return Qnil;
-}
-
-/*
- * call-seq:
- * GC::Profiler.raw_data -> [Hash, ...]
- *
- * Returns an Array of individual raw profile data Hashes ordered
- * from earliest to latest by +:GC_INVOKE_TIME+.
- *
- * For example:
- *
- * [
- * {
- * :GC_TIME=>1.3000000000000858e-05,
- * :GC_INVOKE_TIME=>0.010634999999999999,
- * :HEAP_USE_SIZE=>289640,
- * :HEAP_TOTAL_SIZE=>588960,
- * :HEAP_TOTAL_OBJECTS=>14724,
- * :GC_IS_MARKED=>false
- * },
- * # ...
- * ]
- *
- * The keys mean:
- *
- * +:GC_TIME+::
- * Time elapsed in seconds for this GC run
- * +:GC_INVOKE_TIME+::
- * Time elapsed in seconds from startup to when the GC was invoked
- * +:HEAP_USE_SIZE+::
- * Total bytes of heap used
- * +:HEAP_TOTAL_SIZE+::
- * Total size of heap in bytes
- * +:HEAP_TOTAL_OBJECTS+::
- * Total number of objects
- * +:GC_IS_MARKED+::
- * Returns +true+ if the GC is in mark phase
- *
- * If ruby was built with +GC_PROFILE_MORE_DETAIL+, you will also have access
- * to the following hash keys:
- *
- * +:GC_MARK_TIME+::
- * +:GC_SWEEP_TIME+::
- * +:ALLOCATE_INCREASE+::
- * +:ALLOCATE_LIMIT+::
- * +:HEAP_USE_PAGES+::
- * +:HEAP_LIVE_OBJECTS+::
- * +:HEAP_FREE_OBJECTS+::
- * +:HAVE_FINALIZE+::
- *
- */
-
-static VALUE
-gc_profile_record_get(VALUE _)
-{
- VALUE prof;
- VALUE gc_profile = rb_ary_new();
- size_t i;
- rb_objspace_t *objspace = (&rb_objspace);
-
- if (!objspace->profile.run) {
- return Qnil;
- }
-
- for (i =0; i < objspace->profile.next_index; i++) {
- gc_profile_record *record = &objspace->profile.records[i];
-
- prof = rb_hash_new();
- rb_hash_aset(prof, ID2SYM(rb_intern("GC_FLAGS")), gc_info_decode(objspace, rb_hash_new(), record->flags));
- rb_hash_aset(prof, ID2SYM(rb_intern("GC_TIME")), DBL2NUM(record->gc_time));
- rb_hash_aset(prof, ID2SYM(rb_intern("GC_INVOKE_TIME")), DBL2NUM(record->gc_invoke_time));
- 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));
- rb_hash_aset(prof, ID2SYM(rb_intern("GC_SWEEP_TIME")), DBL2NUM(record->gc_sweep_time));
- rb_hash_aset(prof, ID2SYM(rb_intern("ALLOCATE_INCREASE")), SIZET2NUM(record->allocate_increase));
- rb_hash_aset(prof, ID2SYM(rb_intern("ALLOCATE_LIMIT")), SIZET2NUM(record->allocate_limit));
- rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_USE_PAGES")), SIZET2NUM(record->heap_use_pages));
- rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_LIVE_OBJECTS")), SIZET2NUM(record->heap_live_objects));
- rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_FREE_OBJECTS")), SIZET2NUM(record->heap_free_objects));
-
- 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")), RBOOL(record->flags & GPR_FLAG_HAVE_FINALIZE));
-#endif
-
-#if RGENGC_PROFILE > 0
- rb_hash_aset(prof, ID2SYM(rb_intern("OLD_OBJECTS")), SIZET2NUM(record->old_objects));
- rb_hash_aset(prof, ID2SYM(rb_intern("REMEMBERED_NORMAL_OBJECTS")), SIZET2NUM(record->remembered_normal_objects));
- rb_hash_aset(prof, ID2SYM(rb_intern("REMEMBERED_SHADY_OBJECTS")), SIZET2NUM(record->remembered_shady_objects));
-#endif
- rb_ary_push(gc_profile, prof);
- }
-
- return gc_profile;
-}
-
-#if GC_PROFILE_MORE_DETAIL
-#define MAJOR_REASON_MAX 0x10
-
-static char *
-gc_profile_dump_major_reason(unsigned int flags, char *buff)
-{
- unsigned int reason = flags & GPR_FLAG_MAJOR_MASK;
- int i = 0;
-
- if (reason == GPR_FLAG_NONE) {
- buff[0] = '-';
- buff[1] = 0;
- }
- else {
-#define C(x, s) \
- if (reason & GPR_FLAG_MAJOR_BY_##x) { \
- buff[i++] = #x[0]; \
- if (i >= MAJOR_REASON_MAX) rb_bug("gc_profile_dump_major_reason: overflow"); \
- buff[i] = 0; \
- }
- C(NOFREE, N);
- C(OLDGEN, O);
- C(SHADY, S);
-#if RGENGC_ESTIMATE_OLDMALLOC
- C(OLDMALLOC, M);
-#endif
-#undef C
- }
- return buff;
-}
-#endif
-
-static void
-gc_profile_dump_on(VALUE out, VALUE (*append)(VALUE, VALUE))
-{
- rb_objspace_t *objspace = &rb_objspace;
- size_t count = objspace->profile.next_index;
-#ifdef MAJOR_REASON_MAX
- char reason_str[MAJOR_REASON_MAX];
-#endif
-
- if (objspace->profile.run && count /* > 1 */) {
- size_t i;
- const gc_profile_record *record;
-
- append(out, rb_sprintf("GC %"PRIuSIZE" invokes.\n", objspace->profile.count));
- append(out, rb_str_new_cstr("Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC Time(ms)\n"));
-
- for (i = 0; i < count; i++) {
- record = &objspace->profile.records[i];
- append(out, rb_sprintf("%5"PRIuSIZE" %19.3f %20"PRIuSIZE" %20"PRIuSIZE" %20"PRIuSIZE" %30.20f\n",
- i+1, record->gc_invoke_time, record->heap_use_size,
- record->heap_total_size, record->heap_total_objects, record->gc_time*1000));
- }
-
-#if GC_PROFILE_MORE_DETAIL
- const char *str = "\n\n" \
- "More detail.\n" \
- "Prepare Time = Previously GC's rest sweep time\n"
- "Index Flags Allocate Inc. Allocate Limit"
-#if CALC_EXACT_MALLOC_SIZE
- " Allocated Size"
-#endif
- " Use Page Mark Time(ms) Sweep Time(ms) Prepare Time(ms) LivingObj FreeObj RemovedObj EmptyObj"
-#if RGENGC_PROFILE
- " OldgenObj RemNormObj RemShadObj"
-#endif
-#if GC_PROFILE_DETAIL_MEMORY
- " MaxRSS(KB) MinorFLT MajorFLT"
-#endif
- "\n";
- append(out, rb_str_new_cstr(str));
-
- for (i = 0; i < count; i++) {
- record = &objspace->profile.records[i];
- append(out, rb_sprintf("%5"PRIuSIZE" %4s/%c/%6s%c %13"PRIuSIZE" %15"PRIuSIZE
-#if CALC_EXACT_MALLOC_SIZE
- " %15"PRIuSIZE
-#endif
- " %9"PRIuSIZE" %17.12f %17.12f %17.12f %10"PRIuSIZE" %10"PRIuSIZE" %10"PRIuSIZE" %10"PRIuSIZE
-#if RGENGC_PROFILE
- "%10"PRIuSIZE" %10"PRIuSIZE" %10"PRIuSIZE
-#endif
-#if GC_PROFILE_DETAIL_MEMORY
- "%11ld %8ld %8ld"
-#endif
-
- "\n",
- i+1,
- gc_profile_dump_major_reason(record->flags, reason_str),
- (record->flags & GPR_FLAG_HAVE_FINALIZE) ? 'F' : '.',
- (record->flags & GPR_FLAG_NEWOBJ) ? "NEWOBJ" :
- (record->flags & GPR_FLAG_MALLOC) ? "MALLOC" :
- (record->flags & GPR_FLAG_METHOD) ? "METHOD" :
- (record->flags & GPR_FLAG_CAPI) ? "CAPI__" : "??????",
- (record->flags & GPR_FLAG_STRESS) ? '!' : ' ',
- record->allocate_increase, record->allocate_limit,
-#if CALC_EXACT_MALLOC_SIZE
- record->allocated_size,
-#endif
- record->heap_use_pages,
- record->gc_mark_time*1000,
- record->gc_sweep_time*1000,
- record->prepare_time*1000,
-
- record->heap_live_objects,
- record->heap_free_objects,
- record->removing_objects,
- record->empty_objects
-#if RGENGC_PROFILE
- ,
- record->old_objects,
- record->remembered_normal_objects,
- record->remembered_shady_objects
-#endif
-#if GC_PROFILE_DETAIL_MEMORY
- ,
- record->maxrss / 1024,
- record->minflt,
- record->majflt
-#endif
-
- ));
- }
-#endif
- }
-}
-
-/*
- * call-seq:
- * GC::Profiler.result -> String
- *
- * Returns a profile data report such as:
- *
- * GC 1 invokes.
- * Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC time(ms)
- * 1 0.012 159240 212940 10647 0.00000000000001530000
- */
-
-static VALUE
-gc_profile_result(VALUE _)
-{
- VALUE str = rb_str_buf_new(0);
- gc_profile_dump_on(str, rb_str_buf_append);
- return str;
-}
-
-/*
- * call-seq:
- * GC::Profiler.report
- * GC::Profiler.report(io)
- *
- * Writes the GC::Profiler.result to <tt>$stdout</tt> or the given IO object.
- *
- */
-
-static VALUE
-gc_profile_report(int argc, VALUE *argv, VALUE self)
-{
- VALUE out;
-
- out = (!rb_check_arity(argc, 0, 1) ? rb_stdout : argv[0]);
- gc_profile_dump_on(out, rb_io_write);
-
- return Qnil;
-}
-
-/*
- * call-seq:
- * GC::Profiler.total_time -> float
- *
- * The total time used for garbage collection in seconds
- */
-
-static VALUE
-gc_profile_total_time(VALUE self)
-{
- double time = 0;
- rb_objspace_t *objspace = &rb_objspace;
-
- if (objspace->profile.run && objspace->profile.next_index > 0) {
- size_t i;
- size_t count = objspace->profile.next_index;
-
- for (i = 0; i < count; i++) {
- time += objspace->profile.records[i].gc_time;
- }
- }
- return DBL2NUM(time);
-}
-
-/*
- * call-seq:
- * GC::Profiler.enabled? -> true or false
- *
- * The current status of \GC profile mode.
- */
-
-static VALUE
-gc_profile_enable_get(VALUE self)
-{
- rb_objspace_t *objspace = &rb_objspace;
- return RBOOL(objspace->profile.run);
-}
-
-/*
- * call-seq:
- * GC::Profiler.enable -> nil
- *
- * Starts the \GC profiler.
- *
- */
-
-static VALUE
-gc_profile_enable(VALUE _)
-{
- rb_objspace_t *objspace = &rb_objspace;
- objspace->profile.run = TRUE;
- objspace->profile.current_record = 0;
- return Qnil;
-}
-
-/*
- * call-seq:
- * GC::Profiler.disable -> nil
- *
- * Stops the \GC profiler.
- *
- */
-
-static VALUE
-gc_profile_disable(VALUE _)
-{
- rb_objspace_t *objspace = &rb_objspace;
-
- objspace->profile.run = FALSE;
- objspace->profile.current_record = 0;
- return Qnil;
+ vm->gc.mark_func_data = &mfd;
+ rb_gc_save_machine_context();
+ rb_gc_mark_roots(vm->gc.objspace, &data.category);
+ vm->gc.mark_func_data = prev_mfd;
}
/*
@@ -13152,24 +4772,26 @@ rb_raw_obj_info_common(char *const buff, const size_t buff_size, const VALUE obj
}
}
else {
- const int age = RVALUE_AGE_GET(obj);
-
- if (is_pointer_to_heap(&rb_objspace, (void *)obj)) {
- APPEND_F("%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));
+ // const int age = RVALUE_AGE_GET(obj);
+
+ if (rb_gc_impl_pointer_to_heap_p(rb_gc_get_objspace(), (void *)obj)) {
+ APPEND_F("%p %s/", (void *)obj, obj_type_name(obj));
+ // TODO: fixme
+ // APPEND_F("%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 {
/* fake */
- APPEND_F("%p [%dXXXX] %s",
- (void *)obj, age,
- obj_type_name(obj));
+ // APPEND_F("%p [%dXXXX] %s",
+ // (void *)obj, age,
+ // obj_type_name(obj));
}
if (internal_object_p(obj)) {
@@ -13181,19 +4803,17 @@ rb_raw_obj_info_common(char *const buff, const size_t buff_size, const VALUE obj
else if (RTEST(RBASIC(obj)->klass)) {
VALUE class_path = rb_class_path_cached(RBASIC(obj)->klass);
if (!NIL_P(class_path)) {
- APPEND_F("(%s)", RSTRING_PTR(class_path));
+ APPEND_F("%s ", RSTRING_PTR(class_path));
}
}
-
-#if GC_DEBUG
- APPEND_F("@%s:%d", GET_RVALUE_OVERHEAD(obj)->file, GET_RVALUE_OVERHEAD(obj)->line);
-#endif
}
end:
return pos;
}
+const char *rb_raw_obj_info(char *const buff, const size_t buff_size, VALUE obj);
+
static size_t
rb_raw_obj_info_buitin_type(char *const buff, const size_t buff_size, const VALUE obj, size_t pos)
{
@@ -13209,22 +4829,29 @@ rb_raw_obj_info_buitin_type(char *const buff, const size_t buff_size, const VALU
APPEND_S("shared -> ");
rb_raw_obj_info(BUFF_ARGS, ARY_SHARED_ROOT(obj));
}
- else if (ARY_EMBED_P(obj)) {
- APPEND_F("[%s%s] len: %ld (embed)",
- C(ARY_EMBED_P(obj), "E"),
- C(ARY_SHARED_P(obj), "S"),
- RARRAY_LEN(obj));
- }
else {
- APPEND_F("[%s%s] len: %ld, capa:%ld ptr:%p",
- C(ARY_EMBED_P(obj), "E"),
+ APPEND_F("[%s%s%s] ",
+ C(ARY_EMBED_P(obj), "E"),
C(ARY_SHARED_P(obj), "S"),
- RARRAY_LEN(obj),
- ARY_EMBED_P(obj) ? -1L : RARRAY(obj)->as.heap.aux.capa,
- (void *)RARRAY_CONST_PTR(obj));
+ C(ARY_SHARED_ROOT_P(obj), "R"));
+
+ if (ARY_EMBED_P(obj)) {
+ APPEND_F("len: %ld (embed)",
+ RARRAY_LEN(obj));
+ }
+ else {
+ APPEND_F("len: %ld, capa:%ld ptr:%p",
+ RARRAY_LEN(obj),
+ RARRAY(obj)->as.heap.aux.capa,
+ (void *)RARRAY_CONST_PTR(obj));
+ }
}
break;
case T_STRING: {
+ APPEND_F("[%s%s] ",
+ C(FL_TEST(obj, RSTRING_FSTR), "F"),
+ C(RB_OBJ_FROZEN(obj), "R"));
+
if (STR_SHARED_P(obj)) {
APPEND_F(" [shared] len: %ld", RSTRING_LEN(obj));
}
@@ -13248,7 +4875,7 @@ rb_raw_obj_info_buitin_type(char *const buff, const size_t buff_size, const VALU
break;
}
case T_MOVED: {
- APPEND_F("-> %p", (void*)rb_gc_location(obj));
+ APPEND_F("-> %p", (void*)gc_location_internal(rb_gc_get_objspace(), obj));
break;
}
case T_HASH: {
@@ -13279,21 +4906,18 @@ rb_raw_obj_info_buitin_type(char *const buff, const size_t buff_size, const VALU
}
case T_OBJECT:
{
- if (rb_shape_obj_too_complex(obj)) {
- size_t hash_len = rb_st_table_size(ROBJECT_IV_HASH(obj));
- APPEND_F("(too_complex) len:%zu", hash_len);
- }
- else {
- uint32_t len = ROBJECT_IV_CAPACITY(obj);
-
- if (RANY(obj)->as.basic.flags & ROBJECT_EMBED) {
- APPEND_F("(embed) len:%d", len);
+ if (FL_TEST_RAW(obj, ROBJECT_HEAP)) {
+ if (rb_shape_obj_too_complex_p(obj)) {
+ size_t hash_len = rb_st_table_size(ROBJECT_FIELDS_HASH(obj));
+ APPEND_F("(too_complex) len:%zu", hash_len);
}
else {
- VALUE *ptr = ROBJECT_IVPTR(obj);
- APPEND_F("len:%d ptr:%p", len, (void *)ptr);
+ APPEND_F("(embed) len:%d capa:%d", RSHAPE_LEN(RBASIC_SHAPE_ID(obj)), ROBJECT_FIELDS_CAPACITY(obj));
}
}
+ else {
+ APPEND_F("len:%d capa:%d ptr:%p", RSHAPE_LEN(RBASIC_SHAPE_ID(obj)), ROBJECT_FIELDS_CAPACITY(obj), (void *)ROBJECT_FIELDS(obj));
+ }
}
break;
case T_DATA: {
@@ -13325,7 +4949,7 @@ rb_raw_obj_info_buitin_type(char *const buff, const size_t buff_size, const VALU
switch (imemo_type(obj)) {
case imemo_ment:
{
- const rb_method_entry_t *me = &RANY(obj)->as.imemo.ment;
+ const rb_method_entry_t *me = (const rb_method_entry_t *)obj;
APPEND_F(":%s (%s%s%s%s) type:%s aliased:%d owner:%p defined_class:%p",
rb_id2name(me->called_id),
@@ -13371,15 +4995,15 @@ rb_raw_obj_info_buitin_type(char *const buff, const size_t buff_size, const VALU
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;
+ VALUE class_path = vm_cc_valid(cc) ? rb_class_path_cached(cc->klass) : Qnil;
const rb_callable_method_entry_t *cme = vm_cc_cme(cc);
APPEND_F("(klass:%s cme:%s%s (%p) call:%p",
- NIL_P(class_path) ? (cc->klass ? "??" : "<NULL>") : RSTRING_PTR(class_path),
+ NIL_P(class_path) ? (vm_cc_valid(cc) ? "??" : "<NULL>") : RSTRING_PTR(class_path),
cme ? rb_id2name(cme->called_id) : "<NULL>",
cme ? (METHOD_ENTRY_INVALIDATED(cme) ? " [inv]" : "") : "",
(void *)cme,
- (void *)vm_cc_call(cc));
+ (void *)(uintptr_t)vm_cc_call(cc));
break;
}
default:
@@ -13397,15 +5021,58 @@ rb_raw_obj_info_buitin_type(char *const buff, const size_t buff_size, const VALU
#undef C
+#ifdef RUBY_ASAN_ENABLED
+void
+rb_asan_poison_object(VALUE obj)
+{
+ MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
+ asan_poison_memory_region(ptr, rb_gc_obj_slot_size(obj));
+}
+
+void
+rb_asan_unpoison_object(VALUE obj, bool newobj_p)
+{
+ MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
+ asan_unpoison_memory_region(ptr, rb_gc_obj_slot_size(obj), newobj_p);
+}
+
+void *
+rb_asan_poisoned_object_p(VALUE obj)
+{
+ MAYBE_UNUSED(struct RVALUE *) ptr = (void *)obj;
+ return __asan_region_is_poisoned(ptr, rb_gc_obj_slot_size(obj));
+}
+#endif
+
+static void
+raw_obj_info(char *const buff, const size_t buff_size, VALUE obj)
+{
+ size_t pos = rb_raw_obj_info_common(buff, buff_size, obj);
+ pos = rb_raw_obj_info_buitin_type(buff, buff_size, obj, pos);
+ if (pos >= buff_size) {} // truncated
+}
+
const char *
rb_raw_obj_info(char *const buff, const size_t buff_size, VALUE obj)
{
- asan_unpoisoning_object(obj) {
- size_t pos = rb_raw_obj_info_common(buff, buff_size, obj);
- pos = rb_raw_obj_info_buitin_type(buff, buff_size, obj, pos);
- if (pos >= buff_size) {} // truncated
- }
+ void *objspace = rb_gc_get_objspace();
+ if (SPECIAL_CONST_P(obj)) {
+ raw_obj_info(buff, buff_size, obj);
+ }
+ else if (!rb_gc_impl_pointer_to_heap_p(objspace, (const void *)obj)) {
+ snprintf(buff, buff_size, "out-of-heap:%p", (void *)obj);
+ }
+#if 0 // maybe no need to check it?
+ else if (0 && rb_gc_impl_garbage_object_p(objspace, obj)) {
+ snprintf(buff, buff_size, "garbage:%p", (void *)obj);
+ }
+#endif
+ else {
+ asan_unpoisoning_object(obj) {
+ raw_obj_info(buff, buff_size, obj);
+ }
+ }
return buff;
}
@@ -13413,19 +5080,13 @@ rb_raw_obj_info(char *const buff, const size_t buff_size, VALUE obj)
#undef APPEND_F
#undef BUFF_ARGS
-#if RGENGC_OBJ_INFO
-#define OBJ_INFO_BUFFERS_NUM 10
-#define OBJ_INFO_BUFFERS_SIZE 0x100
-static rb_atomic_t obj_info_buffers_index = 0;
-static char obj_info_buffers[OBJ_INFO_BUFFERS_NUM][OBJ_INFO_BUFFERS_SIZE];
-
/* Increments *var atomically and resets *var to 0 when maxval is
* reached. Returns the wraparound old *var value (0...maxval). */
static rb_atomic_t
atomic_inc_wraparound(rb_atomic_t *var, const rb_atomic_t maxval)
{
rb_atomic_t oldval = RUBY_ATOMIC_FETCH_ADD(*var, 1);
- if (UNLIKELY(oldval >= maxval - 1)) { // wraparound *var
+ if (RB_UNLIKELY(oldval >= maxval - 1)) { // wraparound *var
const rb_atomic_t newval = oldval + 1;
RUBY_ATOMIC_CAS(*var, newval, newval % maxval);
oldval %= maxval;
@@ -13436,37 +5097,395 @@ atomic_inc_wraparound(rb_atomic_t *var, const rb_atomic_t maxval)
static const char *
obj_info(VALUE obj)
{
- rb_atomic_t index = atomic_inc_wraparound(&obj_info_buffers_index, OBJ_INFO_BUFFERS_NUM);
- char *const buff = obj_info_buffers[index];
- return rb_raw_obj_info(buff, OBJ_INFO_BUFFERS_SIZE, obj);
+ if (RGENGC_OBJ_INFO) {
+ static struct {
+ rb_atomic_t index;
+ char buffers[10][0x100];
+ } info = {0};
+
+ rb_atomic_t index = atomic_inc_wraparound(&info.index, numberof(info.buffers));
+ char *const buff = info.buffers[index];
+ return rb_raw_obj_info(buff, sizeof(info.buffers[0]), obj);
+ }
+ return obj_type_name(obj);
}
-static const char *
-obj_info_basic(VALUE obj)
+/*
+ ------------------------ Extended allocator ------------------------
+*/
+
+struct gc_raise_tag {
+ VALUE exc;
+ const char *fmt;
+ va_list *ap;
+};
+
+static void *
+gc_vraise(void *ptr)
+{
+ struct gc_raise_tag *argv = ptr;
+ rb_vraise(argv->exc, argv->fmt, *argv->ap);
+ UNREACHABLE_RETURN(NULL);
+}
+
+static void
+gc_raise(VALUE exc, const char *fmt, ...)
{
- rb_atomic_t index = atomic_inc_wraparound(&obj_info_buffers_index, OBJ_INFO_BUFFERS_NUM);
- char *const buff = obj_info_buffers[index];
+ va_list ap;
+ va_start(ap, fmt);
+ struct gc_raise_tag argv = {
+ exc, fmt, &ap,
+ };
- asan_unpoisoning_object(obj) {
- rb_raw_obj_info_common(buff, OBJ_INFO_BUFFERS_SIZE, obj);
+ if (ruby_native_thread_p()) {
+ rb_thread_call_with_gvl(gc_vraise, &argv);
+ UNREACHABLE;
+ }
+ else {
+ /* Not in a ruby thread */
+ fprintf(stderr, "%s", "[FATAL] ");
+ vfprintf(stderr, fmt, ap);
}
- return buff;
+ va_end(ap);
+ abort();
}
-#else
-static const char *
-obj_info(VALUE obj)
+
+NORETURN(static void negative_size_allocation_error(const char *));
+static void
+negative_size_allocation_error(const char *msg)
{
- return obj_type_name(obj);
+ gc_raise(rb_eNoMemError, "%s", msg);
}
-static const char *
-obj_info_basic(VALUE obj)
+static void *
+ruby_memerror_body(void *dummy)
{
- return obj_type_name(obj);
+ rb_memerror();
+ return 0;
}
+NORETURN(static void ruby_memerror(void));
+RBIMPL_ATTR_MAYBE_UNUSED()
+static void
+ruby_memerror(void)
+{
+ if (ruby_thread_has_gvl_p()) {
+ rb_memerror();
+ }
+ else {
+ if (ruby_native_thread_p()) {
+ rb_thread_call_with_gvl(ruby_memerror_body, 0);
+ }
+ else {
+ /* no ruby thread */
+ fprintf(stderr, "[FATAL] failed to allocate memory\n");
+ }
+ }
+
+ /* We have discussions whether we should die here; */
+ /* We might rethink about it later. */
+ exit(EXIT_FAILURE);
+}
+
+void
+rb_memerror(void)
+{
+ /* the `GET_VM()->special_exceptions` below assumes that
+ * the VM is reachable from the current thread. We should
+ * definitely make sure of that. */
+ RUBY_ASSERT_ALWAYS(ruby_thread_has_gvl_p());
+
+ rb_execution_context_t *ec = GET_EC();
+ VALUE exc = GET_VM()->special_exceptions[ruby_error_nomemory];
+
+ if (!exc ||
+ rb_ec_raised_p(ec, RAISED_NOMEMORY) ||
+ rb_ec_vm_lock_rec(ec) != ec->tag->lock_rec) {
+ fprintf(stderr, "[FATAL] failed to allocate memory\n");
+ exit(EXIT_FAILURE);
+ }
+ if (rb_ec_raised_p(ec, RAISED_NOMEMORY)) {
+ rb_ec_raised_clear(ec);
+ }
+ else {
+ rb_ec_raised_set(ec, RAISED_NOMEMORY);
+ exc = ruby_vm_special_exception_copy(exc);
+ }
+ ec->errinfo = exc;
+ EC_JUMP_TAG(ec, TAG_RAISE);
+}
+
+bool
+rb_memerror_reentered(void)
+{
+ rb_execution_context_t *ec = GET_EC();
+ return (ec && rb_ec_raised_p(ec, RAISED_NOMEMORY));
+}
+
+static void *
+handle_malloc_failure(void *ptr)
+{
+ if (LIKELY(ptr)) {
+ return ptr;
+ }
+ else {
+ ruby_memerror();
+ UNREACHABLE_RETURN(ptr);
+ }
+}
+
+static void *ruby_xmalloc_body(size_t size);
+
+void *
+ruby_xmalloc(size_t size)
+{
+ return handle_malloc_failure(ruby_xmalloc_body(size));
+}
+
+static bool
+malloc_gc_allowed(void)
+{
+ rb_ractor_t *r = rb_current_ractor_raw(false);
+
+ return r == NULL || !r->malloc_gc_disabled;
+}
+
+static void *
+ruby_xmalloc_body(size_t size)
+{
+ if ((ssize_t)size < 0) {
+ negative_size_allocation_error("too large allocation size");
+ }
+
+ return rb_gc_impl_malloc(rb_gc_get_objspace(), size, malloc_gc_allowed());
+}
+
+void
+ruby_malloc_size_overflow(size_t count, size_t elsize)
+{
+ rb_raise(rb_eArgError,
+ "malloc: possible integer overflow (%"PRIuSIZE"*%"PRIuSIZE")",
+ count, elsize);
+}
+
+void
+ruby_malloc_add_size_overflow(size_t x, size_t y)
+{
+ rb_raise(rb_eArgError,
+ "malloc: possible integer overflow (%"PRIuSIZE"+%"PRIuSIZE")",
+ x, y);
+}
+
+static void *ruby_xmalloc2_body(size_t n, size_t size);
+
+void *
+ruby_xmalloc2(size_t n, size_t size)
+{
+ return handle_malloc_failure(ruby_xmalloc2_body(n, size));
+}
+
+static void *
+ruby_xmalloc2_body(size_t n, size_t size)
+{
+ return rb_gc_impl_malloc(rb_gc_get_objspace(), xmalloc2_size(n, size), malloc_gc_allowed());
+}
+
+static void *ruby_xcalloc_body(size_t n, size_t size);
+
+void *
+ruby_xcalloc(size_t n, size_t size)
+{
+ return handle_malloc_failure(ruby_xcalloc_body(n, size));
+}
+
+static void *
+ruby_xcalloc_body(size_t n, size_t size)
+{
+ return rb_gc_impl_calloc(rb_gc_get_objspace(), xmalloc2_size(n, size), malloc_gc_allowed());
+}
+
+static void *ruby_sized_xrealloc_body(void *ptr, size_t new_size, size_t old_size);
+
+#ifdef ruby_sized_xrealloc
+#undef ruby_sized_xrealloc
+#endif
+void *
+ruby_sized_xrealloc(void *ptr, size_t new_size, size_t old_size)
+{
+ return handle_malloc_failure(ruby_sized_xrealloc_body(ptr, new_size, old_size));
+}
+
+static void *
+ruby_sized_xrealloc_body(void *ptr, size_t new_size, size_t old_size)
+{
+ if ((ssize_t)new_size < 0) {
+ negative_size_allocation_error("too large allocation size");
+ }
+
+ return rb_gc_impl_realloc(rb_gc_get_objspace(), ptr, new_size, old_size, malloc_gc_allowed());
+}
+
+void *
+ruby_xrealloc(void *ptr, size_t new_size)
+{
+ return ruby_sized_xrealloc(ptr, new_size, 0);
+}
+
+static void *ruby_sized_xrealloc2_body(void *ptr, size_t n, size_t size, size_t old_n);
+
+#ifdef ruby_sized_xrealloc2
+#undef ruby_sized_xrealloc2
#endif
+void *
+ruby_sized_xrealloc2(void *ptr, size_t n, size_t size, size_t old_n)
+{
+ return handle_malloc_failure(ruby_sized_xrealloc2_body(ptr, n, size, old_n));
+}
+
+static void *
+ruby_sized_xrealloc2_body(void *ptr, size_t n, size_t size, size_t old_n)
+{
+ size_t len = xmalloc2_size(n, size);
+ return rb_gc_impl_realloc(rb_gc_get_objspace(), ptr, len, old_n * size, malloc_gc_allowed());
+}
+
+void *
+ruby_xrealloc2(void *ptr, size_t n, size_t size)
+{
+ return ruby_sized_xrealloc2(ptr, n, size, 0);
+}
+
+#ifdef ruby_sized_xfree
+#undef ruby_sized_xfree
+#endif
+void
+ruby_sized_xfree(void *x, size_t size)
+{
+ if (LIKELY(x)) {
+ /* It's possible for a C extension's pthread destructor function set by pthread_key_create
+ * to be called after ruby_vm_destruct and attempt to free memory. Fall back to mimfree in
+ * that case. */
+ if (LIKELY(GET_VM())) {
+ rb_gc_impl_free(rb_gc_get_objspace(), x, size);
+ }
+ else {
+ ruby_mimfree(x);
+ }
+ }
+}
+
+void
+ruby_xfree(void *x)
+{
+ ruby_sized_xfree(x, 0);
+}
+
+void *
+rb_xmalloc_mul_add(size_t x, size_t y, size_t z) /* x * y + z */
+{
+ size_t w = size_mul_add_or_raise(x, y, z, rb_eArgError);
+ return ruby_xmalloc(w);
+}
+
+void *
+rb_xcalloc_mul_add(size_t x, size_t y, size_t z) /* x * y + z */
+{
+ size_t w = size_mul_add_or_raise(x, y, z, rb_eArgError);
+ return ruby_xcalloc(w, 1);
+}
+
+void *
+rb_xrealloc_mul_add(const void *p, size_t x, size_t y, size_t z) /* x * y + z */
+{
+ size_t w = size_mul_add_or_raise(x, y, z, rb_eArgError);
+ return ruby_xrealloc((void *)p, w);
+}
+
+void *
+rb_xmalloc_mul_add_mul(size_t x, size_t y, size_t z, size_t w) /* x * y + z * w */
+{
+ size_t u = size_mul_add_mul_or_raise(x, y, z, w, rb_eArgError);
+ return ruby_xmalloc(u);
+}
+
+void *
+rb_xcalloc_mul_add_mul(size_t x, size_t y, size_t z, size_t w) /* x * y + z * w */
+{
+ size_t u = size_mul_add_mul_or_raise(x, y, z, w, rb_eArgError);
+ return ruby_xcalloc(u, 1);
+}
+
+/* Mimic ruby_xmalloc, but need not rb_objspace.
+ * should return pointer suitable for ruby_xfree
+ */
+void *
+ruby_mimmalloc(size_t size)
+{
+ void *mem;
+#if CALC_EXACT_MALLOC_SIZE
+ size += sizeof(struct malloc_obj_info);
+#endif
+ mem = malloc(size);
+#if CALC_EXACT_MALLOC_SIZE
+ if (!mem) {
+ return NULL;
+ }
+ else
+ /* set 0 for consistency of allocated_size/allocations */
+ {
+ struct malloc_obj_info *info = mem;
+ info->size = 0;
+ mem = info + 1;
+ }
+#endif
+ return mem;
+}
+
+void *
+ruby_mimcalloc(size_t num, size_t size)
+{
+ void *mem;
+#if CALC_EXACT_MALLOC_SIZE
+ struct rbimpl_size_overflow_tag t = rbimpl_size_mul_overflow(num, size);
+ if (UNLIKELY(t.overflowed)) {
+ return NULL;
+ }
+ size = t.result + sizeof(struct malloc_obj_info);
+ mem = calloc1(size);
+ if (!mem) {
+ return NULL;
+ }
+ else
+ /* set 0 for consistency of allocated_size/allocations */
+ {
+ struct malloc_obj_info *info = mem;
+ info->size = 0;
+ mem = info + 1;
+ }
+#else
+ mem = calloc(num, size);
+#endif
+ return mem;
+}
+
+void
+ruby_mimfree(void *ptr)
+{
+#if CALC_EXACT_MALLOC_SIZE
+ struct malloc_obj_info *info = (struct malloc_obj_info *)ptr - 1;
+ ptr = info;
+#endif
+ free(ptr);
+}
+
+void
+rb_gc_adjust_memory_usage(ssize_t diff)
+{
+ unless_objspace(objspace) { return; }
+
+ rb_gc_impl_adjust_memory_usage(objspace, diff);
+}
const char *
rb_obj_info(VALUE obj)
@@ -13488,104 +5507,90 @@ rb_obj_info_dump_loc(VALUE obj, const char *file, int line, const char *func)
fprintf(stderr, "<OBJ_INFO:%s@%s:%d> %s\n", func, file, line, rb_raw_obj_info(buff, 0x100, obj));
}
-#if GC_DEBUG
-
void
-rb_gcdebug_print_obj_condition(VALUE obj)
+rb_gc_before_fork(void)
{
- rb_objspace_t *objspace = &rb_objspace;
-
- fprintf(stderr, "created at: %s:%d\n", GET_RVALUE_OVERHEAD(obj)->file, GET_RVALUE_OVERHEAD(obj)->line);
-
- if (BUILTIN_TYPE(obj) == T_MOVED) {
- fprintf(stderr, "moved?: true\n");
- }
- else {
- fprintf(stderr, "moved?: false\n");
- }
- if (is_pointer_to_heap(objspace, (void *)obj)) {
- fprintf(stderr, "pointer to heap?: true\n");
- }
- else {
- fprintf(stderr, "pointer to heap?: false\n");
- return;
- }
-
- 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");
- fprintf(stderr, "age? : %d\n", RVALUE_AGE_GET(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");
+ rb_gc_impl_before_fork(rb_gc_get_objspace());
+}
- if (is_lazy_sweeping(objspace)) {
- fprintf(stderr, "lazy sweeping?: true\n");
- fprintf(stderr, "page swept?: %s\n", GET_HEAP_PAGE(obj)->flags.before_sweep ? "false" : "true");
- }
- else {
- fprintf(stderr, "lazy sweeping?: false\n");
- }
+void
+rb_gc_after_fork(rb_pid_t pid)
+{
+ rb_gc_impl_after_fork(rb_gc_get_objspace(), pid);
}
-static VALUE
-gcdebug_sentinel(RB_BLOCK_CALL_FUNC_ARGLIST(obj, name))
+bool
+rb_gc_obj_shareable_p(VALUE obj)
{
- fprintf(stderr, "WARNING: object %s(%p) is inadvertently collected\n", (char *)name, (void *)obj);
- return Qnil;
+ return RB_OBJ_SHAREABLE_P(obj);
}
void
-rb_gcdebug_sentinel(VALUE obj, const char *name)
+rb_gc_rp(VALUE obj)
{
- rb_define_finalizer(obj, rb_proc_new(gcdebug_sentinel, (VALUE)name));
+ rp(obj);
}
-#endif /* GC_DEBUG */
+struct check_shareable_data {
+ VALUE parent;
+ long err_count;
+};
-/* :nodoc:
- *
- * call-seq:
- * GC.add_stress_to_class(class[, ...])
- *
- * Raises NoMemoryError when allocating an instance of the given classes.
- *
- */
-static VALUE
-rb_gcdebug_add_stress_to_class(int argc, VALUE *argv, VALUE self)
+static void
+check_shareable_i(const VALUE child, void *ptr)
{
- rb_objspace_t *objspace = &rb_objspace;
+ struct check_shareable_data *data = (struct check_shareable_data *)ptr;
- if (!stress_to_class) {
- set_stress_to_class(rb_ary_hidden_new(argc));
+ if (!rb_gc_obj_shareable_p(child)) {
+ fprintf(stderr, "(a) ");
+ rb_gc_rp(data->parent);
+ fprintf(stderr, "(b) ");
+ rb_gc_rp(child);
+ fprintf(stderr, "check_shareable_i: shareable (a) -> unshareable (b)\n");
+
+ data->err_count++;
+ rb_bug("!! violate shareable constraint !!");
}
- rb_ary_cat(stress_to_class, argv, argc);
- return self;
}
-/* :nodoc:
- *
- * call-seq:
- * GC.remove_stress_to_class(class[, ...])
- *
- * No longer raises NoMemoryError when allocating an instance of the
- * given classes.
- *
- */
-static VALUE
-rb_gcdebug_remove_stress_to_class(int argc, VALUE *argv, VALUE self)
+static bool gc_checking_shareable = false;
+
+static void
+gc_verify_shareable(void *objspace, VALUE obj, void *data)
{
- rb_objspace_t *objspace = &rb_objspace;
- int i;
+ // while gc_checking_shareable is true,
+ // other Ractors should not run the GC, until the flag is not local.
+ // TODO: remove VM locking if the flag is Ractor local
- if (stress_to_class) {
- for (i = 0; i < argc; ++i) {
- rb_ary_delete_same(stress_to_class, argv[i]);
- }
- if (RARRAY_LEN(stress_to_class) == 0) {
- set_stress_to_class(0);
- }
+ unsigned int lev = RB_GC_VM_LOCK();
+ {
+ gc_checking_shareable = true;
+ rb_objspace_reachable_objects_from(obj, check_shareable_i, (void *)data);
+ gc_checking_shareable = false;
}
- return Qnil;
+ RB_GC_VM_UNLOCK(lev);
+}
+
+// TODO: only one level (non-recursive)
+void
+rb_gc_verify_shareable(VALUE obj)
+{
+ rb_objspace_t *objspace = rb_gc_get_objspace();
+ struct check_shareable_data data = {
+ .parent = obj,
+ .err_count = 0,
+ };
+ gc_verify_shareable(objspace, obj, &data);
+
+ if (data.err_count > 0) {
+ rb_bug("rb_gc_verify_shareable");
+ }
+}
+
+bool
+rb_gc_checking_shareable(void)
+{
+ return gc_checking_shareable;
}
/*
@@ -13638,50 +5643,14 @@ rb_gcdebug_remove_stress_to_class(int argc, VALUE *argv, VALUE self)
void
Init_GC(void)
{
-#if USE_SHARED_GC
- if (getenv(RUBY_GC_LIBRARY_PATH) != NULL && !dln_supported_p()) {
- rb_warn(RUBY_GC_LIBRARY_PATH " is ignored because this executable file can't load extension libraries");
- }
-#endif
-
#undef rb_intern
- malloc_offset = gc_compute_malloc_offset();
+ rb_gc_register_address(&id2ref_value);
- VALUE rb_mObjSpace;
- VALUE rb_mProfiler;
- VALUE gc_constants;
+ malloc_offset = gc_compute_malloc_offset();
rb_mGC = rb_define_module("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("BASE_SLOT_SIZE")), SIZET2NUM(BASE_SLOT_SIZE - RVALUE_OVERHEAD));
- rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVALUE_OVERHEAD")), SIZET2NUM(RVALUE_OVERHEAD));
- rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVALUE_SIZE")), SIZET2NUM(BASE_SLOT_SIZE));
- 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_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)));
- rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVALUE_OLD_AGE")), LONG2FIX(RVALUE_OLD_AGE));
- if (RB_BUG_INSTEAD_OF_RB_MEMERROR+0) {
- rb_hash_aset(gc_constants, ID2SYM(rb_intern("RB_BUG_INSTEAD_OF_RB_MEMERROR")), Qtrue);
- }
- OBJ_FREEZE(gc_constants);
- /* Internal constants in the garbage collector. */
- rb_define_const(rb_mGC, "INTERNAL_CONSTANTS", gc_constants);
-
- rb_mProfiler = rb_define_module_under(rb_mGC, "Profiler");
- rb_define_singleton_method(rb_mProfiler, "enabled?", gc_profile_enable_get, 0);
- rb_define_singleton_method(rb_mProfiler, "enable", gc_profile_enable, 0);
- rb_define_singleton_method(rb_mProfiler, "raw_data", gc_profile_record_get, 0);
- rb_define_singleton_method(rb_mProfiler, "disable", gc_profile_disable, 0);
- rb_define_singleton_method(rb_mProfiler, "clear", gc_profile_clear, 0);
- rb_define_singleton_method(rb_mProfiler, "result", gc_profile_result, 0);
- rb_define_singleton_method(rb_mProfiler, "report", gc_profile_report, -1);
- rb_define_singleton_method(rb_mProfiler, "total_time", gc_profile_total_time, 0);
-
- rb_mObjSpace = rb_define_module("ObjectSpace");
+ VALUE rb_mObjSpace = rb_define_module("ObjectSpace");
rb_define_module_function(rb_mObjSpace, "each_object", os_each_obj, -1);
@@ -13697,118 +5666,38 @@ Init_GC(void)
rb_define_module_function(rb_mObjSpace, "count_objects", count_objects, -1);
- /* internal methods */
- rb_define_singleton_method(rb_mGC, "verify_internal_consistency", gc_verify_internal_consistency_m, 0);
-#if MALLOC_ALLOCATED_SIZE
- rb_define_singleton_method(rb_mGC, "malloc_allocated_size", gc_malloc_allocated_size, 0);
- rb_define_singleton_method(rb_mGC, "malloc_allocations", gc_malloc_allocations, 0);
-#endif
-
- if (GC_COMPACTION_SUPPORTED) {
- rb_define_singleton_method(rb_mGC, "compact", gc_compact, 0);
- rb_define_singleton_method(rb_mGC, "auto_compact", gc_get_auto_compact, 0);
- rb_define_singleton_method(rb_mGC, "auto_compact=", gc_set_auto_compact, 1);
- rb_define_singleton_method(rb_mGC, "latest_compact_info", gc_compact_stats, 0);
- }
- else {
- rb_define_singleton_method(rb_mGC, "compact", rb_f_notimplement, 0);
- rb_define_singleton_method(rb_mGC, "auto_compact", rb_f_notimplement, 0);
- rb_define_singleton_method(rb_mGC, "auto_compact=", rb_f_notimplement, 1);
- rb_define_singleton_method(rb_mGC, "latest_compact_info", rb_f_notimplement, 0);
- /* When !GC_COMPACTION_SUPPORTED, this method is not defined in gc.rb */
- rb_define_singleton_method(rb_mGC, "verify_compaction_references", rb_f_notimplement, -1);
- }
-
- if (GC_DEBUG_STRESS_TO_CLASS) {
- rb_define_singleton_method(rb_mGC, "add_stress_to_class", rb_gcdebug_add_stress_to_class, -1);
- rb_define_singleton_method(rb_mGC, "remove_stress_to_class", rb_gcdebug_remove_stress_to_class, -1);
- }
-
- {
- VALUE opts;
- /* \GC build options */
- rb_define_const(rb_mGC, "OPTS", opts = rb_ary_new());
-#define OPT(o) if (o) rb_ary_push(opts, rb_fstring_lit(#o))
- OPT(GC_DEBUG);
- OPT(USE_RGENGC);
- OPT(RGENGC_DEBUG);
- OPT(RGENGC_CHECK_MODE);
- OPT(RGENGC_PROFILE);
- OPT(RGENGC_ESTIMATE_OLDMALLOC);
- OPT(GC_PROFILE_MORE_DETAIL);
- OPT(GC_ENABLE_LAZY_SWEEP);
- OPT(CALC_EXACT_MALLOC_SIZE);
- OPT(MALLOC_ALLOCATED_SIZE);
- OPT(MALLOC_ALLOCATED_SIZE_CHECK);
- OPT(GC_PROFILE_DETAIL_MEMORY);
- OPT(GC_COMPACTION_SUPPORTED);
-#undef OPT
- OBJ_FREEZE(opts);
- }
-}
-
-#ifdef ruby_xmalloc
-#undef ruby_xmalloc
-#endif
-#ifdef ruby_xmalloc2
-#undef ruby_xmalloc2
-#endif
-#ifdef ruby_xcalloc
-#undef ruby_xcalloc
-#endif
-#ifdef ruby_xrealloc
-#undef ruby_xrealloc
-#endif
-#ifdef ruby_xrealloc2
-#undef ruby_xrealloc2
-#endif
-
-void *
-ruby_xmalloc(size_t size)
-{
-#if USE_GC_MALLOC_OBJ_INFO_DETAILS
- ruby_malloc_info_file = __FILE__;
- ruby_malloc_info_line = __LINE__;
-#endif
- return ruby_xmalloc_body(size);
-}
-
-void *
-ruby_xmalloc2(size_t n, size_t size)
-{
-#if USE_GC_MALLOC_OBJ_INFO_DETAILS
- ruby_malloc_info_file = __FILE__;
- ruby_malloc_info_line = __LINE__;
-#endif
- return ruby_xmalloc2_body(n, size);
-}
-
-void *
-ruby_xcalloc(size_t n, size_t size)
-{
-#if USE_GC_MALLOC_OBJ_INFO_DETAILS
- ruby_malloc_info_file = __FILE__;
- ruby_malloc_info_line = __LINE__;
-#endif
- return ruby_xcalloc_body(n, size);
-}
-
-void *
-ruby_xrealloc(void *ptr, size_t new_size)
-{
-#if USE_GC_MALLOC_OBJ_INFO_DETAILS
- ruby_malloc_info_file = __FILE__;
- ruby_malloc_info_line = __LINE__;
-#endif
- return ruby_xrealloc_body(ptr, new_size);
-}
-
-void *
-ruby_xrealloc2(void *ptr, size_t n, size_t new_size)
-{
-#if USE_GC_MALLOC_OBJ_INFO_DETAILS
- ruby_malloc_info_file = __FILE__;
- ruby_malloc_info_line = __LINE__;
+ rb_gc_impl_init();
+}
+
+// Set a name for the anonymous virtual memory area. `addr` is the starting
+// address of the area and `size` is its length in bytes. `name` is a
+// NUL-terminated human-readable string.
+//
+// This function is usually called after calling `mmap()`. The human-readable
+// annotation helps developers identify the call site of `mmap()` that created
+// the memory mapping.
+//
+// This function currently only works on Linux 5.17 or higher. After calling
+// this function, we can see annotations in the form of "[anon:...]" in
+// `/proc/self/maps`, where `...` is the content of `name`. This function has
+// no effect when called on other platforms.
+void
+ruby_annotate_mmap(const void *addr, unsigned long size, const char *name)
+{
+#if defined(HAVE_SYS_PRCTL_H) && defined(PR_SET_VMA) && defined(PR_SET_VMA_ANON_NAME)
+ // The name length cannot exceed 80 (including the '\0').
+ RUBY_ASSERT(strlen(name) < 80);
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, (unsigned long)addr, size, name);
+ // We ignore errors in prctl. prctl may set errno to EINVAL for several
+ // reasons.
+ // 1. The attr (PR_SET_VMA_ANON_NAME) is not a valid attribute.
+ // 2. addr is an invalid address.
+ // 3. The string pointed by name is too long.
+ // The first error indicates PR_SET_VMA_ANON_NAME is not available, and may
+ // happen if we run the compiled binary on an old kernel. In theory, all
+ // other errors should result in a failure. But since EINVAL cannot tell
+ // the first error from others, and this function is mainly used for
+ // debugging, we silently ignore the error.
+ errno = 0;
#endif
- return ruby_xrealloc2_body(ptr, n, new_size);
}
diff --git a/gc.rb b/gc.rb
index 880aa46475..59adcbc62f 100644
--- a/gc.rb
+++ b/gc.rb
@@ -1,40 +1,45 @@
# for gc.c
-# The \GC module provides an interface to Ruby's mark and
-# sweep garbage collection mechanism.
+# The \GC module provides an interface to Ruby's mark-and-sweep garbage collection mechanism.
#
-# Some of the underlying methods are also available via the ObjectSpace
-# module.
+# Some of the underlying methods are also available via the ObjectSpace module.
#
-# You may obtain information about the operation of the \GC through
-# GC::Profiler.
+# You may obtain information about the operation of the \GC through GC::Profiler.
module GC
- # Initiates garbage collection, even if manually disabled.
- #
- # The +full_mark+ keyword argument determines whether or not to perform a
- # major garbage collection cycle. When set to +true+, a major garbage
- # collection cycle is ran, meaning all objects are marked. When set to
- # +false+, a minor garbage collection cycle is ran, meaning only young
- # objects are marked.
- #
- # The +immediate_mark+ keyword argument determines whether or not to perform
- # incremental marking. When set to +true+, marking is completed during the
- # call to this method. When set to +false+, marking is performed in steps
- # that is interleaved with future Ruby code execution, so marking might not
- # be completed during this method call. Note that if +full_mark+ is +false+
- # then marking will always be immediate, regardless of the value of
- # +immediate_mark+.
- #
- # The +immediate_sweep+ keyword argument determines whether or not to defer
- # sweeping (using lazy sweep). When set to +false+, sweeping is performed in
- # steps that is interleaved with future Ruby code execution, so sweeping might
- # not be completed during this method call. When set to +true+, sweeping is
- # completed during the call to this method.
- #
- # Note: These keyword arguments are implementation and version dependent. They
- # are not guaranteed to be future-compatible, and may be ignored if the
- # underlying implementation does not support them.
+ # Initiates garbage collection, even if explicitly disabled by GC.disable.
+ #
+ # Keyword arguments:
+ #
+ # - +full_mark+:
+ # its boolean value determines whether to perform a major garbage collection cycle:
+ #
+ # - +true+: initiates a major garbage collection cycle,
+ # meaning all objects (old and new) are marked.
+ # - +false+: initiates a minor garbage collection cycle,
+ # meaning only young objects are marked.
+ #
+ # - +immediate_mark+:
+ # its boolean value determines whether to perform incremental marking:
+ #
+ # - +true+: marking is completed before the method returns.
+ # - +false+: marking is performed by parts,
+ # interleaved with program execution both before the method returns and afterward;
+ # therefore marking may not be completed before the return.
+ # Note that if +full_mark+ is +false+, marking will always be immediate,
+ # regardless of the value of +immediate_mark+.
+ #
+ # - +immediate_sweep+:
+ # its boolean value determines whether to defer sweeping (using lazy sweep):
+ #
+ # - +true+: sweeping is completed before the method returns.
+ # - +false+: sweeping is performed by parts,
+ # interleaved with program execution both before the method returns and afterward;
+ # therefore sweeping may not be completed before the return.
+ #
+ # Note that these keyword arguments are implementation- and version-dependent,
+ # are not guaranteed to be future-compatible,
+ # and may be ignored in some implementations.
def self.start full_mark: true, immediate_mark: true, immediate_sweep: true
Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false
end
@@ -44,208 +49,340 @@ module GC
Primitive.gc_start_internal full_mark, immediate_mark, immediate_sweep, false
end
- # call-seq:
- # GC.enable -> true or false
+ # call-seq:
+ # GC.enable -> true or false
#
- # Enables garbage collection, returning +true+ if garbage
- # collection was previously disabled.
+ # Enables garbage collection;
+ # returns whether garbage collection was disabled:
#
- # GC.disable #=> false
- # GC.enable #=> true
- # GC.enable #=> false
+ # GC.disable
+ # GC.enable # => true
+ # GC.enable # => false
#
def self.enable
Primitive.gc_enable
end
- # call-seq:
- # GC.disable -> true or false
+ # call-seq:
+ # GC.disable -> true or false
+ #
+ # Disables garbage collection (but GC.start remains potent):
+ # returns whether garbage collection was already disabled.
#
- # Disables garbage collection, returning +true+ if garbage
- # collection was already disabled.
+ # GC.enable
+ # GC.disable # => false
+ # GC.disable # => true
#
- # GC.disable #=> false
- # GC.disable #=> true
def self.disable
Primitive.gc_disable
end
- # call-seq:
- # GC.stress -> integer, true or false
+ # call-seq:
+ # GC.stress -> setting
+ #
+ # Returns the current \GC stress-mode setting,
+ # which initially is +false+.
#
- # Returns current status of \GC stress mode.
+ # The stress mode may be set by method GC.stress=.
def self.stress
Primitive.gc_stress_get
end
- # call-seq:
- # GC.stress = flag -> flag
+ # call-seq:
+ # GC.stress = value -> value
+ #
+ # Enables or disables stress mode;
+ # enabling stress mode will degrade performance; it is only for debugging.
#
- # Updates the \GC stress mode.
+ # Sets the current \GC stress mode to the given value:
#
- # When stress mode is enabled, the \GC is invoked at every \GC opportunity:
- # all memory and object allocations.
+ # - If the value is +nil+ or +false+, disables stress mode.
+ # - If the value is an integer,
+ # enables stress mode with certain flags; see below.
+ # - Otherwise, enables stress mode;
+ # \GC is invoked at every \GC opportunity: all memory and object allocations.
#
- # Enabling stress mode will degrade performance, it is only for debugging.
+ # The flags are bits in the given integer:
+ #
+ # - +0x01+: No major \GC.
+ # - +0x02+: No immediate sweep.
+ # - +0x04+: Full mark after malloc/calloc/realloc.
#
- # flag can be true, false, or an integer bit-ORed following flags.
- # 0x01:: no major GC
- # 0x02:: no immediate sweep
- # 0x04:: full mark after malloc/calloc/realloc
def self.stress=(flag)
Primitive.gc_stress_set_m flag
end
- # call-seq:
- # GC.count -> Integer
+ # call-seq:
+ # self.count -> integer
#
- # The number of times \GC occurred.
+ # Returns the total number of times garbage collection has occurred:
+ #
+ # GC.count # => 385
+ # GC.start
+ # GC.count # => 386
#
- # It returns the number of times \GC occurred since the process started.
def self.count
Primitive.gc_count
end
- # call-seq:
- # GC.stat -> 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]
- # The total number of garbage collections ran since application start
- # (count includes both minor and major garbage collections)
- # [time]
- # The total time spent in garbage collections (in milliseconds)
- # [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
- # [compact_count]
- # The total number of compactions run since process start
- # [read_barrier_faults]
- # The total number of times the read barrier was triggered during
- # compaction
- # [total_moved_objects]
- # The total number of objects compaction has moved
- # [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.
+ # call-seq:
+ # GC.stat -> new_hash
+ # GC.stat(key) -> value
+ # GC.stat(hash) -> hash
+ #
+ # This method is implementation-specific to CRuby.
+ #
+ # Returns \GC statistics.
+ # The particular statistics are implementation-specific
+ # and may change in the future without notice.
+ #
+ # With no argument given,
+ # returns information about the most recent garbage collection:
+ #
+ # GC.stat
+ # # =>
+ # {count: 28,
+ # time: 1,
+ # marking_time: 1,
+ # sweeping_time: 0,
+ # heap_allocated_pages: 521,
+ # heap_empty_pages: 0,
+ # heap_allocatable_slots: 0,
+ # heap_available_slots: 539590,
+ # heap_live_slots: 422243,
+ # heap_free_slots: 117347,
+ # heap_final_slots: 0,
+ # heap_marked_slots: 264877,
+ # heap_eden_pages: 521,
+ # total_allocated_pages: 521,
+ # total_freed_pages: 0,
+ # total_allocated_objects: 2246376,
+ # total_freed_objects: 1824133,
+ # malloc_increase_bytes: 50982,
+ # malloc_increase_bytes_limit: 18535172,
+ # minor_gc_count: 18,
+ # major_gc_count: 10,
+ # compact_count: 0,
+ # read_barrier_faults: 0,
+ # total_moved_objects: 0,
+ # remembered_wb_unprotected_objects: 0,
+ # remembered_wb_unprotected_objects_limit: 2162,
+ # old_objects: 216365,
+ # old_objects_limit: 432540,
+ # oldmalloc_increase_bytes: 1654232,
+ # oldmalloc_increase_bytes_limit: 16846103}
+ #
+ # With symbol argument +key+ given,
+ # returns the value for that key:
+ #
+ # GC.stat(:count) # => 30
+ #
+ # With hash argument +hash+ given,
+ # returns that hash with GC statistics merged into its content;
+ # this form may be useful in minimizing {probe effects}[https://en.wikipedia.org/wiki/Probe_effect]:
+ #
+ # h = {foo: 0, bar: 1}
+ # GC.stat(h)
+ # h.keys.take(5) # => [:foo, :bar, :count, :time, :marking_time]
+ #
+ # The hash includes entries such as:
+ #
+ # - +:count+:
+ # The total number of garbage collections run since application start
+ # (count includes both minor and major garbage collections).
+ # - +:time+:
+ # The total time spent in garbage collections (in milliseconds).
+ # - +:heap_allocated_pages+:
+ # The total number of allocated pages.
+ # - +:heap_empty_pages+:
+ # The number of pages with no live objects, and that could be released to the system.
+ # - +: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.
+ # - +: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.
+ # - +:compact_count+:
+ # The total number of compactions run since process start.
+ # - +:read_barrier_faults+:
+ # The total number of times the read barrier was triggered during compaction.
+ # - +:total_moved_objects+:
+ # The total number of objects compaction has moved.
+ # - +: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 +:oldmalloc_increase_bytes+ crosses this limit, major \GC is triggered.
+ #
def self.stat hash_or_key = nil
Primitive.gc_stat hash_or_key
end
# call-seq:
- # GC.stat_heap -> Hash
- # GC.stat_heap(nil, hash) -> Hash
- # GC.stat_heap(heap_name) -> Hash
- # GC.stat_heap(heap_name, hash) -> Hash
- # GC.stat_heap(heap_name, :key) -> Numeric
- #
- # Returns information for heaps in the \GC.
- #
- # If the first optional argument, +heap_name+, is passed in and not +nil+, it
- # returns a +Hash+ containing information about the particular heap.
- # Otherwise, it will return a +Hash+ with heap names as keys and
- # a +Hash+ containing information about the heap as values.
- #
- # If the second optional argument, +hash_or_key+, is given as +Hash+, it will
- # be overwritten and returned. This is intended to avoid the probe effect.
- #
- # If both optional arguments are passed in and the second optional argument is
- # a symbol, it will return a +Numeric+ of the value for the particular heap.
- #
- # On CRuby, +heap_name+ is of the type +Integer+ but may be of type +String+
- # on other implementations.
- #
- # The contents of the hash are implementation specific and may change in
- # the future without notice.
- #
- # If the optional argument, hash, is given, it is overwritten and returned.
- #
- # This method is only expected to work on CRuby.
- #
- # The hash includes the following keys about the internal information in
- # the \GC:
- #
- # [slot_size]
+ # GC.stat_heap -> new_hash
+ # GC.stat_heap(heap_id) -> new_hash
+ # GC.stat_heap(heap_id, key) -> value
+ # GC.stat_heap(nil, hash) -> hash
+ # GC.stat_heap(heap_id, hash) -> hash
+ #
+ # This method is implementation-specific to CRuby.
+ #
+ # Returns statistics for \GC heaps.
+ # The particular statistics are implementation-specific
+ # and may change in the future without notice.
+ #
+ # With no argument given, returns statistics for all heaps:
+ #
+ # GC.stat_heap
+ # # =>
+ # {0 =>
+ # {slot_size: 40,
+ # heap_eden_pages: 246,
+ # heap_eden_slots: 402802,
+ # total_allocated_pages: 246,
+ # force_major_gc_count: 2,
+ # force_incremental_marking_finish_count: 1,
+ # total_allocated_objects: 33867152,
+ # total_freed_objects: 33520523},
+ # 1 =>
+ # {slot_size: 80,
+ # heap_eden_pages: 84,
+ # heap_eden_slots: 68746,
+ # total_allocated_pages: 84,
+ # force_major_gc_count: 1,
+ # force_incremental_marking_finish_count: 4,
+ # total_allocated_objects: 147491,
+ # total_freed_objects: 90699},
+ # 2 =>
+ # {slot_size: 160,
+ # heap_eden_pages: 157,
+ # heap_eden_slots: 64182,
+ # total_allocated_pages: 157,
+ # force_major_gc_count: 0,
+ # force_incremental_marking_finish_count: 0,
+ # total_allocated_objects: 211460,
+ # total_freed_objects: 190075},
+ # 3 =>
+ # {slot_size: 320,
+ # heap_eden_pages: 8,
+ # heap_eden_slots: 1631,
+ # total_allocated_pages: 8,
+ # force_major_gc_count: 0,
+ # force_incremental_marking_finish_count: 0,
+ # total_allocated_objects: 1422,
+ # total_freed_objects: 700},
+ # 4 =>
+ # {slot_size: 640,
+ # heap_eden_pages: 16,
+ # heap_eden_slots: 1628,
+ # total_allocated_pages: 16,
+ # force_major_gc_count: 0,
+ # force_incremental_marking_finish_count: 0,
+ # total_allocated_objects: 1230,
+ # total_freed_objects: 309}}
+ #
+ # In the example above, the keys in the outer hash are the heap identifiers:
+ #
+ # GC.stat_heap.keys # => [0, 1, 2, 3, 4]
+ #
+ # On CRuby, each heap identifier is an integer;
+ # on other implementations, a heap identifier may be a string.
+ #
+ # With only argument +heap_id+ given,
+ # returns statistics for the given heap identifier:
+ #
+ # GC.stat_heap(2)
+ # # =>
+ # {slot_size: 160,
+ # heap_eden_pages: 157,
+ # heap_eden_slots: 64182,
+ # total_allocated_pages: 157,
+ # force_major_gc_count: 0,
+ # force_incremental_marking_finish_count: 0,
+ # total_allocated_objects: 225018,
+ # total_freed_objects: 206647}
+ #
+ # With arguments +heap_id+ and +key+ given,
+ # returns the value for the given key in the given heap:
+ #
+ # GC.stat_heap(2, :slot_size) # => 160
+ #
+ # With arguments +nil+ and +hash+ given,
+ # merges the statistics for all heaps into the given hash:
+ #
+ # h = {foo: 0, bar: 1}
+ # GC.stat_heap(nil, h).keys # => [:foo, :bar, 0, 1, 2, 3, 4]
+ #
+ # With arguments +heap_id+ and +hash+ given,
+ # merges the statistics for the given heap into the given hash:
+ #
+ # h = {foo: 0, bar: 1}
+ # GC.stat_heap(2, h).keys
+ # # =>
+ # [:foo,
+ # :bar,
+ # :slot_size,
+ # :heap_eden_pages,
+ # :heap_eden_slots,
+ # :total_allocated_pages,
+ # :force_major_gc_count,
+ # :force_incremental_marking_finish_count,
+ # :total_allocated_objects,
+ # :total_freed_objects]
+ #
+ # The statistics for a heap may include:
+ #
+ # - +:slot_size+:
# The slot size of the heap in bytes.
- # [heap_allocatable_pages]
+ # - +:heap_allocatable_pages+:
# The number of pages that can be allocated without triggering a new
# garbage collection cycle.
- # [heap_eden_pages]
+ # - +:heap_eden_pages+:
# The number of pages in the eden heap.
- # [heap_eden_slots]
+ # - +:heap_eden_slots+:
# The total number of slots in all of the pages in the eden heap.
- # [heap_tomb_pages]
- # The number of pages in the tomb heap. The tomb heap only contains pages
- # that do not have any live objects.
- # [heap_tomb_slots]
- # The total number of slots in all of the pages in the tomb heap.
- # [total_allocated_pages]
+ # - +:total_allocated_pages+:
# The total number of pages that have been allocated in the heap.
- # [total_freed_pages]
+ # - +:total_freed_pages+:
# The total number of pages that have been freed and released back to the
# system in the heap.
- # [force_major_gc_count]
- # The number of times major garbage collection cycles this heap has forced
+ # - +:force_major_gc_count+:
+ # The number of times this heap has forced major garbage collection cycles
# to start due to running out of free slots.
- # [force_incremental_marking_finish_count]
+ # - +:force_incremental_marking_finish_count+:
# The number of times this heap has forced incremental marking to complete
# due to running out of pooled slots.
#
@@ -254,70 +391,200 @@ module GC
end
# call-seq:
- # GC.latest_gc_info -> hash
- # GC.latest_gc_info(hash) -> hash
- # GC.latest_gc_info(:major_by) -> :malloc
+ # GC.config -> hash
+ # GC.config(hash_to_merge) -> hash
#
- # Returns information about the most recent garbage collection.
+ # This method is implementation-specific to CRuby.
#
- # 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
- Primitive.gc_latest_gc_info hash_or_key
+ # Sets or gets information about the current \GC configuration.
+ #
+ # Configuration parameters are \GC implementation-specific and may change without notice.
+ #
+ # With no argument given, returns a hash containing the configuration:
+ #
+ # GC.config
+ # # => {rgengc_allow_full_mark: true, implementation: "default"}
+ #
+ # With argument +hash_to_merge+ given,
+ # merges that hash into the stored configuration hash;
+ # ignores unknown hash keys;
+ # returns the configuration hash:
+ #
+ # GC.config(rgengc_allow_full_mark: false)
+ # # => {rgengc_allow_full_mark: false, implementation: "default"}
+ # GC.config(foo: 'bar')
+ # # => {rgengc_allow_full_mark: false, implementation: "default"}
+ #
+ # <b>All-Implementations Configuration</b>
+ #
+ # The single read-only entry for all implementations is:
+ #
+ # - +:implementation+:
+ # the string name of the implementation;
+ # for the Ruby default implementation, <tt>'default'</tt>.
+ #
+ # <b>Implementation-Specific Configuration</b>
+ #
+ # A \GC implementation maintains its own implementation-specific configuration.
+ #
+ # For Ruby's default implementation the single entry is:
+ #
+ # - +:rgengc_allow_full_mark+:
+ # Controls whether the \GC is allowed to run a full mark (young & old objects):
+ #
+ # - +true+ (default): \GC interleaves major and minor collections.
+ # A flag is set to notify GC that a full mark has been requested.
+ # This flag is accessible via GC.latest_gc_info(:need_major_by).
+ # - +false+: \GC does not initiate a full marking cycle unless explicitly directed by user code;
+ # see GC.start.
+ # Setting this parameter to +false+ disables young-to-old promotion.
+ # For performance reasons, we recommended warming up the application using Process.warmup
+ # before setting this parameter to +false+.
+ #
+ def self.config hash = nil
+ if Primitive.cexpr!("RBOOL(RB_TYPE_P(hash, T_HASH))")
+ if hash.include?(:implementation)
+ raise ArgumentError, 'Attempting to set read-only key "Implementation"'
+ end
+
+ Primitive.gc_config_set hash
+ elsif hash != nil
+ raise ArgumentError
+ end
+
+ Primitive.gc_config_get
end
- if respond_to?(:compact)
- # 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 expands 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, expand_heap: false)
- Primitive.gc_verify_compaction_references(double_heap, expand_heap, toward == :empty)
+ # call-seq:
+ # GC.latest_gc_info -> new_hash
+ # GC.latest_gc_info(key) -> value
+ # GC.latest_gc_info(hash) -> hash
+ #
+ # With no argument given,
+ # returns information about the most recent garbage collection:
+ #
+ # GC.latest_gc_info
+ # # =>
+ # {major_by: :force,
+ # need_major_by: nil,
+ # gc_by: :method,
+ # have_finalizer: false,
+ # immediate_sweep: true,
+ # state: :none,
+ # weak_references_count: 0,
+ # retained_weak_references_count: 0}
+ #
+ # With symbol argument +key+ given,
+ # returns the value for that key:
+ #
+ # GC.latest_gc_info(:gc_by) # => :newobj
+ #
+ # With hash argument +hash+ given,
+ # returns that hash with GC information merged into its content;
+ # this form may be useful in minimizing {probe effects}[https://en.wikipedia.org/wiki/Probe_effect]:
+ #
+ # h = {foo: 0, bar: 1}
+ # GC.latest_gc_info(h)
+ # # =>
+ # {foo: 0,
+ # bar: 1,
+ # major_by: nil,
+ # need_major_by: nil,
+ # gc_by: :newobj,
+ # have_finalizer: false,
+ # immediate_sweep: false,
+ # state: :sweeping,
+ # weak_references_count: 0,
+ # retained_weak_references_count: 0}
+ #
+ def self.latest_gc_info hash_or_key = nil
+ if hash_or_key == nil
+ hash_or_key = {}
+ elsif Primitive.cexpr!("RBOOL(!SYMBOL_P(hash_or_key) && !RB_TYPE_P(hash_or_key, T_HASH))")
+ raise TypeError, "non-hash or symbol given"
end
+
+ Primitive.cstmt! %{
+ return rb_gc_latest_gc_info(hash_or_key);
+ }
end
# call-seq:
- # GC.measure_total_time = true/false
+ # GC.measure_total_time = setting -> setting
+ #
+ # Enables or disables \GC total time measurement;
+ # returns +setting+.
+ # See GC.total_time.
+ #
+ # When argument +object+ is +nil+ or +false+, disables total time measurement;
+ # GC.measure_total_time then returns +false+:
+ #
+ # GC.measure_total_time = nil # => nil
+ # GC.measure_total_time # => false
+ # GC.measure_total_time = false # => false
+ # GC.measure_total_time # => false
#
- # Enable to measure \GC time.
- # You can get the result with <tt>GC.stat(:time)</tt>.
- # Note that \GC time measurement can cause some performance overhead.
+ # Otherwise, enables total time measurement;
+ # GC.measure_total_time then returns +true+:
+ #
+ # GC.measure_total_time = true # => true
+ # GC.measure_total_time # => true
+ # GC.measure_total_time = :foo # => :foo
+ # GC.measure_total_time # => true
+ #
+ # Note that when enabled, total time measurement affects performance.
def self.measure_total_time=(flag)
Primitive.cstmt! %{
- rb_objspace.flags.measure_gc = RTEST(flag) ? TRUE : FALSE;
+ rb_gc_impl_set_measure_total_time(rb_gc_get_objspace(), flag);
return flag;
}
end
# call-seq:
- # GC.measure_total_time -> true/false
+ # GC.measure_total_time -> true or false
#
- # Return measure_total_time flag (default: +true+).
- # Note that measurement can affect the application performance.
+ # Returns the setting for \GC total time measurement;
+ # the initial setting is +true+.
+ # See GC.total_time.
def self.measure_total_time
Primitive.cexpr! %{
- RBOOL(rb_objspace.flags.measure_gc)
+ RBOOL(rb_gc_impl_get_measure_total_time(rb_gc_get_objspace()))
}
end
# call-seq:
- # GC.total_time -> int
+ # GC.total_time -> integer
+ #
+ # Returns the \GC total time in nanoseconds:
+ #
+ # GC.total_time # => 156250
+ #
+ # Note that total time accumulates
+ # only when total time measurement is enabled
+ # (that is, when GC.measure_total_time is +true+):
+ #
+ # GC.measure_total_time # => true
+ # GC.total_time # => 625000
+ # GC.start
+ # GC.total_time # => 937500
+ # GC.start
+ # GC.total_time # => 1093750
+ #
+ # GC.measure_total_time = false
+ # GC.total_time # => 1250000
+ # GC.start
+ # GC.total_time # => 1250000
+ # GC.start
+ # GC.total_time # => 1250000
+ #
+ # GC.measure_total_time = true
+ # GC.total_time # => 1250000
+ # GC.start
+ # GC.total_time # => 1406250
#
- # Return measured \GC total time in nano seconds.
def self.total_time
Primitive.cexpr! %{
- ULL2NUM(rb_objspace.profile.marking_time_ns + rb_objspace.profile.sweeping_time_ns)
+ ULL2NUM(rb_gc_impl_get_total_time(rb_gc_get_objspace()))
}
end
end
diff --git a/gc/README.md b/gc/README.md
new file mode 100644
index 0000000000..cb71357973
--- /dev/null
+++ b/gc/README.md
@@ -0,0 +1,37 @@
+# Ruby's Garbage Collectors
+
+This directory contains implementations for Ruby's garbage collector (GC). The GC implementations use the Modular GC API to interact with Ruby. For more details about this API, see the [Modular GC API](#modular-gc-api) section.
+
+Two GC implementations are included in Ruby:
+
+- Default: The GC implementation that is used by default in Ruby. This GC is stable and production ready. The implementation uses a mark-sweep-compact algorithm.
+- MMTk: An experimental implementation using the [MMTk](https://www.mmtk.io/) framework. The code lives in the [ruby/mmtk](https://github.com/ruby/mmtk) repository and is synchronized here. MMTk provides a [wide variety of GC algorithms](https://www.mmtk.io/status#implemented-collectors) to choose from. For usage instructions and current progress, refer to the [ruby/mmtk](https://github.com/ruby/mmtk) repository.
+
+## Building guide
+
+> [!TIP]
+> If you are not sure how to build Ruby, follow the [Building Ruby](https://docs.ruby-lang.org/en/master/contributing/building_ruby_md.html) guide.
+
+> [!IMPORTANT]
+> Ruby's modular GC feature is experimental and subject to change. There may be bugs or performance impacts. Use at your own risk.
+
+### Building Ruby with Modular GC
+
+1. Configure Ruby with the `--with-modular-gc=<dir>` option, where `dir` is the directory you want to place the built GC libraries into.
+2. Build Ruby as usual.
+
+### Building GC implementations shipped with Ruby
+
+1. Build your desired GC implementation with `make install-modular-gc MODULAR_GC=<impl>`. This will build the GC implementation and place the built library into the `dir` specified in step 1. `impl` can be one of:
+ - `default`: The default GC that Ruby ships with.
+ - `mmtk`: The GC that uses [MMTk](https://www.mmtk.io/) as the back-end. See Ruby-specific details in the [ruby/mmtk](https://github.com/ruby/mmtk) repository.
+2. Run your desired GC implementation by setting the `RUBY_GC_LIBRARY=<lib>` environment variable, where `lib` could be `default`, `mmtk`, or your own implementation (as long as you place it in the `dir` specified in step 1).
+
+## Modular GC API
+
+> [!WARNING]
+> The Modular GC API is experimental and subject to change without notice.
+
+GC implementations interact with Ruby via the Modular GC API. All implementations must provide the functions in [gc/gc_impl.h](https://github.com/ruby/ruby/blob/master/gc/gc_impl.h) for Ruby to hook into. GC implementations can use any public C API in Ruby, along with additional APIs defined in [gc/gc.h](https://github.com/ruby/ruby/blob/master/gc/gc.h).
+
+Additionally, create an extconf.rb file to build the GC library. This file must use [gc/extconf_base.rb](https://github.com/ruby/ruby/blob/master/gc/extconf_base.rb) and the `create_gc_makefile` method.
diff --git a/gc/default/default.c b/gc/default/default.c
new file mode 100644
index 0000000000..013c074994
--- /dev/null
+++ b/gc/default/default.c
@@ -0,0 +1,9602 @@
+#include "ruby/internal/config.h"
+
+#include <signal.h>
+
+#ifndef _WIN32
+# include <sys/mman.h>
+# include <unistd.h>
+# ifdef HAVE_SYS_PRCTL_H
+# include <sys/prctl.h>
+# endif
+#endif
+
+#if !defined(PAGE_SIZE) && defined(HAVE_SYS_USER_H)
+/* LIST_HEAD conflicts with sys/queue.h on macOS */
+# include <sys/user.h>
+#endif
+
+#ifdef BUILDING_MODULAR_GC
+# define nlz_int64(x) (x == 0 ? 64 : (unsigned int)__builtin_clzll((unsigned long long)x))
+#else
+# include "internal/bits.h"
+#endif
+
+#include "ruby/ruby.h"
+#include "ruby/atomic.h"
+#include "ruby/debug.h"
+#include "ruby/thread.h"
+#include "ruby/util.h"
+#include "ruby/vm.h"
+#include "ruby/internal/encoding/string.h"
+#include "ccan/list/list.h"
+#include "darray.h"
+#include "gc/gc.h"
+#include "gc/gc_impl.h"
+
+#ifndef BUILDING_MODULAR_GC
+# include "probes.h"
+#endif
+
+#ifdef BUILDING_MODULAR_GC
+# define RB_DEBUG_COUNTER_INC(_name) ((void)0)
+# define RB_DEBUG_COUNTER_INC_IF(_name, cond) (!!(cond))
+#else
+# include "debug_counter.h"
+#endif
+
+#ifdef BUILDING_MODULAR_GC
+# define rb_asan_poison_object(obj) ((void)(obj))
+# define rb_asan_unpoison_object(obj, newobj_p) ((void)(obj), (void)(newobj_p))
+# define asan_unpoisoning_object(obj) if ((obj) || true)
+# define asan_poison_memory_region(ptr, size) ((void)(ptr), (void)(size))
+# define asan_unpoison_memory_region(ptr, size, malloc_p) ((void)(ptr), (size), (malloc_p))
+# define asan_unpoisoning_memory_region(ptr, size) if ((ptr) || (size) || true)
+
+# define VALGRIND_MAKE_MEM_DEFINED(ptr, size) ((void)(ptr), (void)(size))
+# define VALGRIND_MAKE_MEM_UNDEFINED(ptr, size) ((void)(ptr), (void)(size))
+#else
+# include "internal/sanitizers.h"
+#endif
+
+/* MALLOC_HEADERS_BEGIN */
+#ifndef HAVE_MALLOC_USABLE_SIZE
+# ifdef _WIN32
+# 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)
+# endif
+#endif
+
+#ifdef HAVE_MALLOC_USABLE_SIZE
+# ifdef RUBY_ALTERNATIVE_MALLOC_HEADER
+/* Alternative malloc header is included in ruby/missing.h */
+# elif defined(HAVE_MALLOC_H)
+# include <malloc.h>
+# elif defined(HAVE_MALLOC_NP_H)
+# include <malloc_np.h>
+# elif defined(HAVE_MALLOC_MALLOC_H)
+# include <malloc/malloc.h>
+# endif
+#endif
+
+#ifdef HAVE_MALLOC_TRIM
+# include <malloc.h>
+
+# ifdef __EMSCRIPTEN__
+/* malloc_trim is defined in emscripten/emmalloc.h on emscripten. */
+# include <emscripten/emmalloc.h>
+# endif
+#endif
+
+#ifdef HAVE_MACH_TASK_EXCEPTION_PORTS
+# include <mach/task.h>
+# include <mach/mach_init.h>
+# include <mach/mach_port.h>
+#endif
+
+#ifndef VM_CHECK_MODE
+# define VM_CHECK_MODE RUBY_DEBUG
+#endif
+
+// From ractor_core.h
+#ifndef RACTOR_CHECK_MODE
+# define RACTOR_CHECK_MODE (VM_CHECK_MODE || RUBY_DEBUG) && (SIZEOF_UINT64_T == SIZEOF_VALUE)
+#endif
+
+#ifndef RUBY_DEBUG_LOG
+# define RUBY_DEBUG_LOG(...)
+#endif
+
+#ifndef GC_HEAP_INIT_SLOTS
+#define GC_HEAP_INIT_SLOTS 10000
+#endif
+#ifndef GC_HEAP_FREE_SLOTS
+#define GC_HEAP_FREE_SLOTS 4096
+#endif
+#ifndef GC_HEAP_GROWTH_FACTOR
+#define GC_HEAP_GROWTH_FACTOR 1.8
+#endif
+#ifndef GC_HEAP_GROWTH_MAX_SLOTS
+#define GC_HEAP_GROWTH_MAX_SLOTS 0 /* 0 is disable */
+#endif
+#ifndef GC_HEAP_REMEMBERED_WB_UNPROTECTED_OBJECTS_LIMIT_RATIO
+# define GC_HEAP_REMEMBERED_WB_UNPROTECTED_OBJECTS_LIMIT_RATIO 0.01
+#endif
+#ifndef GC_HEAP_OLDOBJECT_LIMIT_FACTOR
+#define GC_HEAP_OLDOBJECT_LIMIT_FACTOR 2.0
+#endif
+
+#ifndef GC_HEAP_FREE_SLOTS_MIN_RATIO
+#define GC_HEAP_FREE_SLOTS_MIN_RATIO 0.20
+#endif
+#ifndef GC_HEAP_FREE_SLOTS_GOAL_RATIO
+#define GC_HEAP_FREE_SLOTS_GOAL_RATIO 0.40
+#endif
+#ifndef GC_HEAP_FREE_SLOTS_MAX_RATIO
+#define GC_HEAP_FREE_SLOTS_MAX_RATIO 0.65
+#endif
+
+#ifndef GC_MALLOC_LIMIT_MIN
+#define GC_MALLOC_LIMIT_MIN (16 * 1024 * 1024 /* 16MB */)
+#endif
+#ifndef GC_MALLOC_LIMIT_MAX
+#define GC_MALLOC_LIMIT_MAX (32 * 1024 * 1024 /* 32MB */)
+#endif
+#ifndef GC_MALLOC_LIMIT_GROWTH_FACTOR
+#define GC_MALLOC_LIMIT_GROWTH_FACTOR 1.4
+#endif
+
+#ifndef GC_OLDMALLOC_LIMIT_MIN
+#define GC_OLDMALLOC_LIMIT_MIN (16 * 1024 * 1024 /* 16MB */)
+#endif
+#ifndef GC_OLDMALLOC_LIMIT_GROWTH_FACTOR
+#define GC_OLDMALLOC_LIMIT_GROWTH_FACTOR 1.2
+#endif
+#ifndef GC_OLDMALLOC_LIMIT_MAX
+#define GC_OLDMALLOC_LIMIT_MAX (128 * 1024 * 1024 /* 128MB */)
+#endif
+
+#ifndef GC_MALLOC_INCREASE_LOCAL_THRESHOLD
+#define GC_MALLOC_INCREASE_LOCAL_THRESHOLD (8 * 1024 /* 8KB */)
+#endif
+
+#ifdef RB_THREAD_LOCAL_SPECIFIER
+#define USE_MALLOC_INCREASE_LOCAL 1
+static RB_THREAD_LOCAL_SPECIFIER int malloc_increase_local;
+#else
+#define USE_MALLOC_INCREASE_LOCAL 0
+#endif
+
+#ifndef GC_CAN_COMPILE_COMPACTION
+#if defined(__wasi__) /* WebAssembly doesn't support signals */
+# define GC_CAN_COMPILE_COMPACTION 0
+#else
+# define GC_CAN_COMPILE_COMPACTION 1
+#endif
+#endif
+
+#ifndef PRINT_ENTER_EXIT_TICK
+# define PRINT_ENTER_EXIT_TICK 0
+#endif
+#ifndef PRINT_ROOT_TICKS
+#define PRINT_ROOT_TICKS 0
+#endif
+
+#define USE_TICK_T (PRINT_ENTER_EXIT_TICK || PRINT_ROOT_TICKS)
+
+#ifndef HEAP_COUNT
+# define HEAP_COUNT 5
+#endif
+
+typedef struct ractor_newobj_heap_cache {
+ struct free_slot *freelist;
+ struct heap_page *using_page;
+ size_t allocated_objects_count;
+} rb_ractor_newobj_heap_cache_t;
+
+typedef struct ractor_newobj_cache {
+ size_t incremental_mark_step_allocated_slots;
+ rb_ractor_newobj_heap_cache_t heap_caches[HEAP_COUNT];
+} rb_ractor_newobj_cache_t;
+
+typedef struct {
+ size_t heap_init_slots[HEAP_COUNT];
+ size_t heap_free_slots;
+ double growth_factor;
+ size_t growth_max_slots;
+
+ double heap_free_slots_min_ratio;
+ double heap_free_slots_goal_ratio;
+ double heap_free_slots_max_ratio;
+ double uncollectible_wb_unprotected_objects_limit_ratio;
+ double oldobject_limit_factor;
+
+ size_t malloc_limit_min;
+ size_t malloc_limit_max;
+ double malloc_limit_growth_factor;
+
+ size_t oldmalloc_limit_min;
+ size_t oldmalloc_limit_max;
+ double oldmalloc_limit_growth_factor;
+} ruby_gc_params_t;
+
+static ruby_gc_params_t gc_params = {
+ { GC_HEAP_INIT_SLOTS },
+ GC_HEAP_FREE_SLOTS,
+ GC_HEAP_GROWTH_FACTOR,
+ GC_HEAP_GROWTH_MAX_SLOTS,
+
+ GC_HEAP_FREE_SLOTS_MIN_RATIO,
+ GC_HEAP_FREE_SLOTS_GOAL_RATIO,
+ GC_HEAP_FREE_SLOTS_MAX_RATIO,
+ GC_HEAP_REMEMBERED_WB_UNPROTECTED_OBJECTS_LIMIT_RATIO,
+ GC_HEAP_OLDOBJECT_LIMIT_FACTOR,
+
+ GC_MALLOC_LIMIT_MIN,
+ GC_MALLOC_LIMIT_MAX,
+ GC_MALLOC_LIMIT_GROWTH_FACTOR,
+
+ GC_OLDMALLOC_LIMIT_MIN,
+ GC_OLDMALLOC_LIMIT_MAX,
+ GC_OLDMALLOC_LIMIT_GROWTH_FACTOR,
+};
+
+/* GC_DEBUG:
+ * enable to embed GC debugging information.
+ */
+#ifndef GC_DEBUG
+#define GC_DEBUG 0
+#endif
+
+/* RGENGC_DEBUG:
+ * 1: basic information
+ * 2: remember set operation
+ * 3: mark
+ * 4:
+ * 5: sweep
+ */
+#ifndef RGENGC_DEBUG
+#ifdef RUBY_DEVEL
+#define RGENGC_DEBUG -1
+#else
+#define RGENGC_DEBUG 0
+#endif
+#endif
+#if RGENGC_DEBUG < 0 && !defined(_MSC_VER)
+# define RGENGC_DEBUG_ENABLED(level) (-(RGENGC_DEBUG) >= (level) && ruby_rgengc_debug >= (level))
+#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;
+
+/* RGENGC_PROFILE
+ * 0: disable RGenGC profiling
+ * 1: enable profiling for basic information
+ * 2: enable profiling for each types
+ */
+#ifndef RGENGC_PROFILE
+# define RGENGC_PROFILE 0
+#endif
+
+/* RGENGC_ESTIMATE_OLDMALLOC
+ * Enable/disable to estimate increase size of malloc'ed size by old objects.
+ * If estimation exceeds threshold, then will invoke full GC.
+ * 0: disable estimation.
+ * 1: enable estimation.
+ */
+#ifndef RGENGC_ESTIMATE_OLDMALLOC
+# define RGENGC_ESTIMATE_OLDMALLOC 1
+#endif
+
+#ifndef GC_PROFILE_MORE_DETAIL
+# define GC_PROFILE_MORE_DETAIL 0
+#endif
+#ifndef GC_PROFILE_DETAIL_MEMORY
+# define GC_PROFILE_DETAIL_MEMORY 0
+#endif
+#ifndef GC_ENABLE_LAZY_SWEEP
+# define GC_ENABLE_LAZY_SWEEP 1
+#endif
+#ifndef CALC_EXACT_MALLOC_SIZE
+# define CALC_EXACT_MALLOC_SIZE 0
+#endif
+#if defined(HAVE_MALLOC_USABLE_SIZE) || CALC_EXACT_MALLOC_SIZE > 0
+# ifndef MALLOC_ALLOCATED_SIZE
+# define MALLOC_ALLOCATED_SIZE 0
+# endif
+#else
+# define MALLOC_ALLOCATED_SIZE 0
+#endif
+#ifndef MALLOC_ALLOCATED_SIZE_CHECK
+# define MALLOC_ALLOCATED_SIZE_CHECK 0
+#endif
+
+#ifndef GC_DEBUG_STRESS_TO_CLASS
+# define GC_DEBUG_STRESS_TO_CLASS RUBY_DEBUG
+#endif
+
+typedef enum {
+ GPR_FLAG_NONE = 0x000,
+ /* major reason */
+ GPR_FLAG_MAJOR_BY_NOFREE = 0x001,
+ GPR_FLAG_MAJOR_BY_OLDGEN = 0x002,
+ GPR_FLAG_MAJOR_BY_SHADY = 0x004,
+ GPR_FLAG_MAJOR_BY_FORCE = 0x008,
+#if RGENGC_ESTIMATE_OLDMALLOC
+ GPR_FLAG_MAJOR_BY_OLDMALLOC = 0x020,
+#endif
+ GPR_FLAG_MAJOR_MASK = 0x0ff,
+
+ /* gc reason */
+ GPR_FLAG_NEWOBJ = 0x100,
+ GPR_FLAG_MALLOC = 0x200,
+ GPR_FLAG_METHOD = 0x400,
+ GPR_FLAG_CAPI = 0x800,
+ GPR_FLAG_STRESS = 0x1000,
+
+ /* others */
+ GPR_FLAG_IMMEDIATE_SWEEP = 0x2000,
+ 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 |
+ GPR_FLAG_IMMEDIATE_SWEEP | GPR_FLAG_CAPI),
+} gc_profile_record_flag;
+
+typedef struct gc_profile_record {
+ unsigned int flags;
+
+ double gc_time;
+ double gc_invoke_time;
+
+ 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;
+ double gc_sweep_time;
+
+ size_t heap_use_pages;
+ size_t heap_live_objects;
+ size_t heap_free_objects;
+
+ size_t allocate_increase;
+ size_t allocate_limit;
+
+ double prepare_time;
+ size_t removing_objects;
+ size_t empty_objects;
+#if GC_PROFILE_DETAIL_MEMORY
+ long maxrss;
+ long minflt;
+ long majflt;
+#endif
+#endif
+#if MALLOC_ALLOCATED_SIZE
+ size_t allocated_size;
+#endif
+
+#if RGENGC_PROFILE > 0
+ size_t old_objects;
+ size_t remembered_normal_objects;
+ size_t remembered_shady_objects;
+#endif
+} gc_profile_record;
+
+struct RMoved {
+ VALUE flags;
+ VALUE dummy;
+ VALUE destination;
+ uint32_t original_shape_id;
+};
+
+#define RMOVED(obj) ((struct RMoved *)(obj))
+
+typedef uintptr_t bits_t;
+enum {
+ BITS_SIZE = sizeof(bits_t),
+ BITS_BITLENGTH = ( BITS_SIZE * CHAR_BIT )
+};
+
+struct heap_page_header {
+ struct heap_page *page;
+};
+
+struct heap_page_body {
+ struct heap_page_header header;
+ /* char gap[]; */
+ /* RVALUE values[]; */
+};
+
+#define STACK_CHUNK_SIZE 500
+
+typedef struct stack_chunk {
+ VALUE data[STACK_CHUNK_SIZE];
+ struct stack_chunk *next;
+} stack_chunk_t;
+
+typedef struct mark_stack {
+ stack_chunk_t *chunk;
+ stack_chunk_t *cache;
+ int index;
+ int limit;
+ size_t cache_size;
+ size_t unused_cache_size;
+} mark_stack_t;
+
+typedef int (*gc_compact_compare_func)(const void *l, const void *r, void *d);
+
+typedef struct rb_heap_struct {
+ short slot_size;
+ bits_t slot_bits_mask;
+
+ /* Basic statistics */
+ size_t total_allocated_pages;
+ size_t force_major_gc_count;
+ size_t force_incremental_marking_finish_count;
+ size_t total_allocated_objects;
+ size_t total_freed_objects;
+ size_t final_slots_count;
+
+ /* Sweeping statistics */
+ size_t freed_slots;
+ size_t empty_slots;
+
+ struct heap_page *free_pages;
+ struct ccan_list_head pages;
+ struct heap_page *sweeping_page; /* iterator for .pages */
+ struct heap_page *compact_cursor;
+ uintptr_t compact_cursor_index;
+ struct heap_page *pooled_pages;
+ size_t total_pages; /* total page count in a heap */
+ size_t total_slots; /* total slot count (about total_pages * HEAP_PAGE_OBJ_LIMIT) */
+
+} rb_heap_t;
+
+enum {
+ gc_stress_no_major,
+ gc_stress_no_immediate_sweep,
+ gc_stress_full_mark_after_malloc,
+ gc_stress_max
+};
+
+enum gc_mode {
+ gc_mode_none,
+ gc_mode_marking,
+ gc_mode_sweeping,
+ gc_mode_compacting,
+};
+
+typedef struct rb_objspace {
+ struct {
+ size_t increase;
+#if RGENGC_ESTIMATE_OLDMALLOC
+ size_t oldmalloc_increase;
+#endif
+ } malloc_counters;
+
+ struct {
+ size_t limit;
+#if MALLOC_ALLOCATED_SIZE
+ size_t allocated_size;
+ size_t allocations;
+#endif
+ } malloc_params;
+
+ struct rb_gc_config {
+ bool full_mark;
+ } gc_config;
+
+ struct {
+ unsigned int mode : 2;
+ unsigned int immediate_sweep : 1;
+ unsigned int dont_gc : 1;
+ unsigned int dont_incremental : 1;
+ unsigned int during_gc : 1;
+ unsigned int during_compacting : 1;
+ unsigned int during_reference_updating : 1;
+ unsigned int gc_stressful: 1;
+ unsigned int during_minor_gc : 1;
+ unsigned int during_incremental_marking : 1;
+ unsigned int measure_gc : 1;
+ } flags;
+
+ rb_event_flag_t hook_events;
+
+ rb_heap_t heaps[HEAP_COUNT];
+ size_t empty_pages_count;
+ struct heap_page *empty_pages;
+
+ struct {
+ rb_atomic_t finalizing;
+ } atomic_flags;
+
+ mark_stack_t mark_stack;
+ size_t marked_slots;
+
+ struct {
+ rb_darray(struct heap_page *) sorted;
+
+ size_t allocated_pages;
+ size_t freed_pages;
+ uintptr_t range[2];
+ size_t freeable_pages;
+
+ size_t allocatable_slots;
+
+ /* final */
+ VALUE deferred_final;
+ } heap_pages;
+
+ st_table *finalizer_table;
+
+ struct {
+ int run;
+ unsigned int latest_gc_info;
+ gc_profile_record *records;
+ gc_profile_record *current_record;
+ size_t next_index;
+ size_t size;
+
+#if GC_PROFILE_MORE_DETAIL
+ double prepare_time;
+#endif
+ double invoke_time;
+
+ 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;
+ size_t total_shade_operation_count;
+ size_t total_promoted_count;
+ size_t total_remembered_normal_object_count;
+ size_t total_remembered_shady_object_count;
+
+#if RGENGC_PROFILE >= 2
+ size_t generated_normal_object_count_types[RUBY_T_MASK];
+ size_t generated_shady_object_count_types[RUBY_T_MASK];
+ size_t shade_operation_count_types[RUBY_T_MASK];
+ size_t promoted_types[RUBY_T_MASK];
+ size_t remembered_normal_object_count_types[RUBY_T_MASK];
+ size_t remembered_shady_object_count_types[RUBY_T_MASK];
+#endif
+#endif /* RGENGC_PROFILE */
+
+ /* temporary profiling space */
+ double gc_sweep_start_time;
+ size_t total_allocated_objects_at_gc_start;
+ size_t heap_used_at_gc_start;
+
+ /* basic statistics */
+ size_t count;
+ unsigned long long marking_time_ns;
+ struct timespec marking_start_time;
+ unsigned long long sweeping_time_ns;
+ struct timespec sweeping_start_time;
+
+ /* Weak references */
+ size_t weak_references_count;
+ } profile;
+
+ VALUE gc_stress_mode;
+
+ struct {
+ bool parent_object_old_p;
+ VALUE parent_object;
+
+ int need_major_gc;
+ size_t last_major_gc;
+ size_t uncollectible_wb_unprotected_objects;
+ size_t uncollectible_wb_unprotected_objects_limit;
+ size_t old_objects;
+ size_t old_objects_limit;
+
+#if RGENGC_ESTIMATE_OLDMALLOC
+ size_t oldmalloc_increase_limit;
+#endif
+
+#if RGENGC_CHECK_MODE >= 2
+ struct st_table *allrefs_table;
+ size_t error_count;
+#endif
+ } rgengc;
+
+ struct {
+ size_t considered_count_table[T_MASK];
+ size_t moved_count_table[T_MASK];
+ size_t moved_up_count_table[T_MASK];
+ size_t moved_down_count_table[T_MASK];
+ size_t total_moved;
+
+ /* This function will be used, if set, to sort the heap prior to compaction */
+ gc_compact_compare_func compare_func;
+ } rcompactor;
+
+ struct {
+ size_t pooled_slots;
+ size_t step_slots;
+ } rincgc;
+
+#if GC_DEBUG_STRESS_TO_CLASS
+ VALUE stress_to_class;
+#endif
+
+ rb_darray(VALUE) weak_references;
+ rb_postponed_job_handle_t finalize_deferred_pjob;
+
+ unsigned long live_ractor_cache_count;
+
+ int fork_vm_lock_lev;
+} rb_objspace_t;
+
+#ifndef HEAP_PAGE_ALIGN_LOG
+/* default tiny heap size: 64KiB */
+#define HEAP_PAGE_ALIGN_LOG 16
+#endif
+
+#if RACTOR_CHECK_MODE || GC_DEBUG
+struct rvalue_overhead {
+# if RACTOR_CHECK_MODE
+ uint32_t _ractor_belonging_id;
+# endif
+# if GC_DEBUG
+ const char *file;
+ int line;
+# endif
+};
+
+// Make sure that RVALUE_OVERHEAD aligns to sizeof(VALUE)
+# define RVALUE_OVERHEAD (sizeof(struct { \
+ union { \
+ struct rvalue_overhead overhead; \
+ VALUE value; \
+ }; \
+}))
+size_t rb_gc_impl_obj_slot_size(VALUE obj);
+# define GET_RVALUE_OVERHEAD(obj) ((struct rvalue_overhead *)((uintptr_t)obj + rb_gc_impl_obj_slot_size(obj)))
+#else
+# ifndef RVALUE_OVERHEAD
+# define RVALUE_OVERHEAD 0
+# endif
+#endif
+
+#define BASE_SLOT_SIZE (sizeof(struct RBasic) + sizeof(VALUE[RBIMPL_RVALUE_EMBED_LEN_MAX]) + RVALUE_OVERHEAD)
+
+#ifndef MAX
+# define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+#ifndef MIN
+# define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#endif
+#define roomof(x, y) (((x) + (y) - 1) / (y))
+#define CEILDIV(i, mod) roomof(i, mod)
+enum {
+ HEAP_PAGE_ALIGN = (1UL << HEAP_PAGE_ALIGN_LOG),
+ HEAP_PAGE_ALIGN_MASK = (~(~0UL << HEAP_PAGE_ALIGN_LOG)),
+ HEAP_PAGE_SIZE = HEAP_PAGE_ALIGN,
+ HEAP_PAGE_OBJ_LIMIT = (unsigned int)((HEAP_PAGE_SIZE - sizeof(struct heap_page_header)) / BASE_SLOT_SIZE),
+ HEAP_PAGE_BITMAP_LIMIT = CEILDIV(CEILDIV(HEAP_PAGE_SIZE, BASE_SLOT_SIZE), BITS_BITLENGTH),
+ HEAP_PAGE_BITMAP_SIZE = (BITS_SIZE * HEAP_PAGE_BITMAP_LIMIT),
+};
+#define HEAP_PAGE_ALIGN (1 << HEAP_PAGE_ALIGN_LOG)
+#define HEAP_PAGE_SIZE HEAP_PAGE_ALIGN
+
+#if !defined(INCREMENTAL_MARK_STEP_ALLOCATIONS)
+# define INCREMENTAL_MARK_STEP_ALLOCATIONS 500
+#endif
+
+#undef INIT_HEAP_PAGE_ALLOC_USE_MMAP
+/* Must define either HEAP_PAGE_ALLOC_USE_MMAP or
+ * INIT_HEAP_PAGE_ALLOC_USE_MMAP. */
+
+#ifndef HAVE_MMAP
+/* We can't use mmap of course, if it is not available. */
+static const bool HEAP_PAGE_ALLOC_USE_MMAP = false;
+
+#elif defined(__wasm__)
+/* wasmtime does not have proper support for mmap.
+ * See https://github.com/bytecodealliance/wasmtime/blob/main/docs/WASI-rationale.md#why-no-mmap-and-friends
+ */
+static const bool HEAP_PAGE_ALLOC_USE_MMAP = false;
+
+#elif HAVE_CONST_PAGE_SIZE
+/* If we have the PAGE_SIZE and it is a constant, then we can directly use it. */
+static const bool HEAP_PAGE_ALLOC_USE_MMAP = (PAGE_SIZE <= HEAP_PAGE_SIZE);
+
+#elif defined(PAGE_MAX_SIZE) && (PAGE_MAX_SIZE <= HEAP_PAGE_SIZE)
+/* If we can use the maximum page size. */
+static const bool HEAP_PAGE_ALLOC_USE_MMAP = true;
+
+#elif defined(PAGE_SIZE)
+/* If the PAGE_SIZE macro can be used dynamically. */
+# define INIT_HEAP_PAGE_ALLOC_USE_MMAP (PAGE_SIZE <= HEAP_PAGE_SIZE)
+
+#elif defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
+/* If we can use sysconf to determine the page size. */
+# define INIT_HEAP_PAGE_ALLOC_USE_MMAP (sysconf(_SC_PAGE_SIZE) <= HEAP_PAGE_SIZE)
+
+#else
+/* Otherwise we can't determine the system page size, so don't use mmap. */
+static const bool HEAP_PAGE_ALLOC_USE_MMAP = false;
+#endif
+
+#ifdef INIT_HEAP_PAGE_ALLOC_USE_MMAP
+/* We can determine the system page size at runtime. */
+# define HEAP_PAGE_ALLOC_USE_MMAP (heap_page_alloc_use_mmap != false)
+
+static bool heap_page_alloc_use_mmap;
+#endif
+
+#define RVALUE_AGE_BIT_COUNT 2
+#define RVALUE_AGE_BIT_MASK (((bits_t)1 << RVALUE_AGE_BIT_COUNT) - 1)
+#define RVALUE_OLD_AGE 3
+
+struct free_slot {
+ VALUE flags; /* always 0 for freed obj */
+ struct free_slot *next;
+};
+
+struct heap_page {
+ unsigned short slot_size;
+ unsigned short total_slots;
+ unsigned short free_slots;
+ unsigned short final_slots;
+ unsigned short pinned_slots;
+ struct {
+ unsigned int before_sweep : 1;
+ unsigned int has_remembered_objects : 1;
+ unsigned int has_uncollectible_wb_unprotected_objects : 1;
+ } flags;
+
+ rb_heap_t *heap;
+
+ struct heap_page *free_next;
+ struct heap_page_body *body;
+ uintptr_t start;
+ struct free_slot *freelist;
+ struct ccan_list_node page_node;
+
+ bits_t wb_unprotected_bits[HEAP_PAGE_BITMAP_LIMIT];
+ /* the following three bitmaps are cleared at the beginning of full GC */
+ bits_t mark_bits[HEAP_PAGE_BITMAP_LIMIT];
+ bits_t uncollectible_bits[HEAP_PAGE_BITMAP_LIMIT];
+ bits_t marking_bits[HEAP_PAGE_BITMAP_LIMIT];
+
+ bits_t remembered_bits[HEAP_PAGE_BITMAP_LIMIT];
+
+ /* If set, the object is not movable */
+ bits_t pinned_bits[HEAP_PAGE_BITMAP_LIMIT];
+ bits_t age_bits[HEAP_PAGE_BITMAP_LIMIT * RVALUE_AGE_BIT_COUNT];
+};
+
+/*
+ * When asan is enabled, this will prohibit writing to the freelist until it is unlocked
+ */
+static void
+asan_lock_freelist(struct heap_page *page)
+{
+ asan_poison_memory_region(&page->freelist, sizeof(struct free_list *));
+}
+
+/*
+ * When asan is enabled, this will enable the ability to write to the freelist
+ */
+static void
+asan_unlock_freelist(struct heap_page *page)
+{
+ asan_unpoison_memory_region(&page->freelist, sizeof(struct free_list *), false);
+}
+
+static inline bool
+heap_page_in_global_empty_pages_pool(rb_objspace_t *objspace, struct heap_page *page)
+{
+ if (page->total_slots == 0) {
+ GC_ASSERT(page->start == 0);
+ GC_ASSERT(page->slot_size == 0);
+ GC_ASSERT(page->heap == NULL);
+ GC_ASSERT(page->free_slots == 0);
+ asan_unpoisoning_memory_region(&page->freelist, sizeof(&page->freelist)) {
+ GC_ASSERT(page->freelist == NULL);
+ }
+
+ return true;
+ }
+ else {
+ GC_ASSERT(page->start != 0);
+ GC_ASSERT(page->slot_size != 0);
+ GC_ASSERT(page->heap != NULL);
+
+ return false;
+ }
+}
+
+#define GET_PAGE_BODY(x) ((struct heap_page_body *)((bits_t)(x) & ~(HEAP_PAGE_ALIGN_MASK)))
+#define GET_PAGE_HEADER(x) (&GET_PAGE_BODY(x)->header)
+#define GET_HEAP_PAGE(x) (GET_PAGE_HEADER(x)->page)
+
+#define NUM_IN_PAGE(p) (((bits_t)(p) & HEAP_PAGE_ALIGN_MASK) / BASE_SLOT_SIZE)
+#define BITMAP_INDEX(p) (NUM_IN_PAGE(p) / BITS_BITLENGTH )
+#define BITMAP_OFFSET(p) (NUM_IN_PAGE(p) & (BITS_BITLENGTH-1))
+#define BITMAP_BIT(p) ((bits_t)1 << BITMAP_OFFSET(p))
+
+/* Bitmap Operations */
+#define MARKED_IN_BITMAP(bits, p) ((bits)[BITMAP_INDEX(p)] & BITMAP_BIT(p))
+#define MARK_IN_BITMAP(bits, p) ((bits)[BITMAP_INDEX(p)] = (bits)[BITMAP_INDEX(p)] | BITMAP_BIT(p))
+#define CLEAR_IN_BITMAP(bits, p) ((bits)[BITMAP_INDEX(p)] = (bits)[BITMAP_INDEX(p)] & ~BITMAP_BIT(p))
+
+/* 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])
+#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])
+
+#define RVALUE_AGE_BITMAP_INDEX(n) (NUM_IN_PAGE(n) / (BITS_BITLENGTH / RVALUE_AGE_BIT_COUNT))
+#define RVALUE_AGE_BITMAP_OFFSET(n) ((NUM_IN_PAGE(n) % (BITS_BITLENGTH / RVALUE_AGE_BIT_COUNT)) * RVALUE_AGE_BIT_COUNT)
+
+static int
+RVALUE_AGE_GET(VALUE obj)
+{
+ bits_t *age_bits = GET_HEAP_PAGE(obj)->age_bits;
+ return (int)(age_bits[RVALUE_AGE_BITMAP_INDEX(obj)] >> RVALUE_AGE_BITMAP_OFFSET(obj)) & RVALUE_AGE_BIT_MASK;
+}
+
+static void
+RVALUE_AGE_SET_BITMAP(VALUE obj, int age)
+{
+ RUBY_ASSERT(age <= RVALUE_OLD_AGE);
+ bits_t *age_bits = GET_HEAP_PAGE(obj)->age_bits;
+ // clear the bits
+ age_bits[RVALUE_AGE_BITMAP_INDEX(obj)] &= ~(RVALUE_AGE_BIT_MASK << (RVALUE_AGE_BITMAP_OFFSET(obj)));
+ // shift the correct value in
+ age_bits[RVALUE_AGE_BITMAP_INDEX(obj)] |= ((bits_t)age << RVALUE_AGE_BITMAP_OFFSET(obj));
+}
+
+static void
+RVALUE_AGE_SET(VALUE obj, int age)
+{
+ RVALUE_AGE_SET_BITMAP(obj, age);
+ if (age == RVALUE_OLD_AGE) {
+ RB_FL_SET_RAW(obj, RUBY_FL_PROMOTED);
+ }
+ else {
+ RB_FL_UNSET_RAW(obj, RUBY_FL_PROMOTED);
+ }
+}
+
+#define malloc_limit objspace->malloc_params.limit
+#define malloc_increase objspace->malloc_counters.increase
+#define malloc_allocated_size objspace->malloc_params.allocated_size
+#define heap_pages_lomem objspace->heap_pages.range[0]
+#define heap_pages_himem objspace->heap_pages.range[1]
+#define heap_pages_freeable_pages objspace->heap_pages.freeable_pages
+#define heap_pages_deferred_final objspace->heap_pages.deferred_final
+#define heaps objspace->heaps
+#define during_gc objspace->flags.during_gc
+#define finalizing objspace->atomic_flags.finalizing
+#define finalizer_table objspace->finalizer_table
+#define ruby_gc_stressful objspace->flags.gc_stressful
+#define ruby_gc_stress_mode objspace->gc_stress_mode
+#if GC_DEBUG_STRESS_TO_CLASS
+#define stress_to_class objspace->stress_to_class
+#define set_stress_to_class(c) (stress_to_class = (c))
+#else
+#define stress_to_class ((void)objspace, 0)
+#define set_stress_to_class(c) ((void)objspace, (c))
+#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__), objspace->flags.dont_gc = (int)(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) (objspace->flags.dont_gc = (int)(b))
+#define dont_gc_val() (objspace->flags.dont_gc)
+#endif
+
+#define gc_config_full_mark_set(b) (objspace->gc_config.full_mark = (int)(b))
+#define gc_config_full_mark_val (objspace->gc_config.full_mark)
+
+#ifndef DURING_GC_COULD_MALLOC_REGION_START
+# define DURING_GC_COULD_MALLOC_REGION_START() \
+ assert(rb_during_gc()); \
+ bool _prev_enabled = rb_gc_impl_gc_enabled_p(objspace); \
+ rb_gc_impl_gc_disable(objspace, false)
+#endif
+
+#ifndef DURING_GC_COULD_MALLOC_REGION_END
+# define DURING_GC_COULD_MALLOC_REGION_END() \
+ if (_prev_enabled) rb_gc_impl_gc_enable(objspace)
+#endif
+
+static inline enum gc_mode
+gc_mode_verify(enum gc_mode mode)
+{
+#if RGENGC_CHECK_MODE > 0
+ switch (mode) {
+ case gc_mode_none:
+ case gc_mode_marking:
+ case gc_mode_sweeping:
+ case gc_mode_compacting:
+ break;
+ default:
+ rb_bug("gc_mode_verify: unreachable (%d)", (int)mode);
+ }
+#endif
+ return mode;
+}
+
+static inline bool
+has_sweeping_pages(rb_objspace_t *objspace)
+{
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ if ((&heaps[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 < HEAP_COUNT; i++) {
+ count += (&heaps[i])->total_pages;
+ }
+ return count;
+}
+
+static inline size_t
+total_allocated_objects(rb_objspace_t *objspace)
+{
+ size_t count = 0;
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ rb_heap_t *heap = &heaps[i];
+ count += heap->total_allocated_objects;
+ }
+ return count;
+}
+
+static inline size_t
+total_freed_objects(rb_objspace_t *objspace)
+{
+ size_t count = 0;
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ rb_heap_t *heap = &heaps[i];
+ count += heap->total_freed_objects;
+ }
+ return count;
+}
+
+static inline size_t
+total_final_slots_count(rb_objspace_t *objspace)
+{
+ size_t count = 0;
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ rb_heap_t *heap = &heaps[i];
+ count += heap->final_slots_count;
+ }
+ return count;
+}
+
+#define gc_mode(objspace) gc_mode_verify((enum gc_mode)(objspace)->flags.mode)
+#define gc_mode_set(objspace, m) ((objspace)->flags.mode = (unsigned int)gc_mode_verify(m))
+#define gc_needs_major_flags objspace->rgengc.need_major_gc
+
+#define is_marking(objspace) (gc_mode(objspace) == gc_mode_marking)
+#define is_sweeping(objspace) (gc_mode(objspace) == gc_mode_sweeping)
+#define is_full_marking(objspace) ((objspace)->flags.during_minor_gc == FALSE)
+#define is_incremental_marking(objspace) ((objspace)->flags.during_incremental_marking != FALSE)
+#define will_be_incremental_marking(objspace) ((objspace)->rgengc.need_major_gc != GPR_FLAG_NONE)
+#define GC_INCREMENTAL_SWEEP_SLOT_COUNT 2048
+#define GC_INCREMENTAL_SWEEP_POOL_SLOT_COUNT 1024
+#define is_lazy_sweeping(objspace) (GC_ENABLE_LAZY_SWEEP && has_sweeping_pages(objspace))
+/* In lazy sweeping or the previous incremental marking finished and did not yield a free page. */
+#define needs_continue_sweeping(objspace, heap) \
+ ((heap)->free_pages == NULL && is_lazy_sweeping(objspace))
+
+#if SIZEOF_LONG == SIZEOF_VOIDP
+# define obj_id_to_ref(objid) ((objid) ^ FIXNUM_FLAG) /* unset FIXNUM_FLAG */
+#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
+# define obj_id_to_ref(objid) (FIXNUM_P(objid) ? \
+ ((objid) ^ FIXNUM_FLAG) : (NUM2PTR(objid) << 1))
+#else
+# error not supported
+#endif
+
+struct RZombie {
+ VALUE flags;
+ VALUE next;
+ void (*dfree)(void *);
+ void *data;
+};
+
+#define RZOMBIE(o) ((struct RZombie *)(o))
+
+static bool ruby_enable_autocompact = false;
+#if RGENGC_CHECK_MODE
+static gc_compact_compare_func ruby_autocompact_compare_func;
+#endif
+
+static void init_mark_stack(mark_stack_t *stack);
+static int garbage_collect(rb_objspace_t *, unsigned int reason);
+
+static int gc_start(rb_objspace_t *objspace, unsigned int reason);
+static void gc_rest(rb_objspace_t *objspace);
+
+enum gc_enter_event {
+ gc_enter_event_start,
+ gc_enter_event_continue,
+ gc_enter_event_rest,
+ gc_enter_event_finalizer,
+};
+
+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_marking_enter(rb_objspace_t *objspace);
+static void gc_marking_exit(rb_objspace_t *objspace);
+static void gc_sweeping_enter(rb_objspace_t *objspace);
+static void gc_sweeping_exit(rb_objspace_t *objspace);
+static bool gc_marks_continue(rb_objspace_t *objspace, rb_heap_t *heap);
+
+static void gc_sweep(rb_objspace_t *objspace);
+static void gc_sweep_finish_heap(rb_objspace_t *objspace, rb_heap_t *heap);
+static void gc_sweep_continue(rb_objspace_t *objspace, 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);
+static inline void gc_mark_and_pin(rb_objspace_t *objspace, VALUE ptr);
+
+static int gc_mark_stacked_objects_incremental(rb_objspace_t *, size_t count);
+NO_SANITIZE("memory", static inline bool is_pointer_to_heap(rb_objspace_t *objspace, const void *ptr));
+
+static void gc_verify_internal_consistency(void *objspace_ptr);
+
+static double getrusage_time(void);
+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 *);
+static inline void gc_prof_mark_timer_stop(rb_objspace_t *);
+static inline void gc_prof_sweep_timer_start(rb_objspace_t *);
+static inline void gc_prof_sweep_timer_stop(rb_objspace_t *);
+static inline void gc_prof_set_malloc_info(rb_objspace_t *);
+static inline void gc_prof_set_heap_info(rb_objspace_t *);
+
+#define gc_prof_record(objspace) (objspace)->profile.current_record
+#define gc_prof_enabled(objspace) ((objspace)->profile.run && (objspace)->profile.current_record)
+
+#ifdef HAVE_VA_ARGS_MACRO
+# define gc_report(level, objspace, ...) \
+ if (!RGENGC_DEBUG_ENABLED(level)) {} else gc_report_body(level, objspace, __VA_ARGS__)
+#else
+# define gc_report if (!RGENGC_DEBUG_ENABLED(0)) {} else gc_report_body
+#endif
+PRINTF_ARGS(static void gc_report_body(int level, rb_objspace_t *objspace, const char *fmt, ...), 3, 4);
+
+static void gc_finalize_deferred(void *dmy);
+
+#if USE_TICK_T
+
+/* the following code is only for internal tuning. */
+
+/* Source code to use RDTSC is quoted and modified from
+ * https://www.mcs.anl.gov/~kazutomo/rdtsc.html
+ * written by Kazutomo Yoshii <kazutomo@mcs.anl.gov>
+ */
+
+#if defined(__GNUC__) && defined(__i386__)
+typedef unsigned long long tick_t;
+#define PRItick "llu"
+static inline tick_t
+tick(void)
+{
+ unsigned long long int x;
+ __asm__ __volatile__ ("rdtsc" : "=A" (x));
+ return x;
+}
+
+#elif defined(__GNUC__) && defined(__x86_64__)
+typedef unsigned long long tick_t;
+#define PRItick "llu"
+
+static __inline__ tick_t
+tick(void)
+{
+ unsigned long hi, lo;
+ __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
+ return ((unsigned long long)lo)|( ((unsigned long long)hi)<<32);
+}
+
+#elif defined(__powerpc64__) && (GCC_VERSION_SINCE(4,8,0) || defined(__clang__))
+typedef unsigned long long tick_t;
+#define PRItick "llu"
+
+static __inline__ tick_t
+tick(void)
+{
+ unsigned long long val = __builtin_ppc_get_timebase();
+ return val;
+}
+
+#elif defined(__POWERPC__) && defined(__APPLE__)
+/* Implementation for macOS PPC by @nobu
+ * See: https://github.com/ruby/ruby/pull/5975#discussion_r890045558
+ */
+typedef unsigned long long tick_t;
+#define PRItick "llu"
+
+static __inline__ tick_t
+tick(void)
+{
+ unsigned long int upper, lower, tmp;
+ # define mftbu(r) __asm__ volatile("mftbu %0" : "=r"(r))
+ # define mftb(r) __asm__ volatile("mftb %0" : "=r"(r))
+ do {
+ mftbu(upper);
+ mftb(lower);
+ mftbu(tmp);
+ } while (tmp != upper);
+ return ((tick_t)upper << 32) | lower;
+}
+
+#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 <intrin.h>
+typedef unsigned __int64 tick_t;
+#define PRItick "llu"
+
+static inline tick_t
+tick(void)
+{
+ return __rdtsc();
+}
+
+#else /* use clock */
+typedef clock_t tick_t;
+#define PRItick "llu"
+
+static inline tick_t
+tick(void)
+{
+ return clock();
+}
+#endif /* TSC */
+#else /* USE_TICK_T */
+#define MEASURE_LINE(expr) expr
+#endif /* USE_TICK_T */
+
+static inline VALUE check_rvalue_consistency(rb_objspace_t *objspace, const VALUE obj);
+
+#define RVALUE_MARKED_BITMAP(obj) MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(obj), (obj))
+#define RVALUE_WB_UNPROTECTED_BITMAP(obj) MARKED_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(obj), (obj))
+#define RVALUE_MARKING_BITMAP(obj) MARKED_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), (obj))
+#define RVALUE_UNCOLLECTIBLE_BITMAP(obj) MARKED_IN_BITMAP(GET_HEAP_UNCOLLECTIBLE_BITS(obj), (obj))
+#define RVALUE_PINNED_BITMAP(obj) MARKED_IN_BITMAP(GET_HEAP_PINNED_BITS(obj), (obj))
+
+static inline int
+RVALUE_MARKED(rb_objspace_t *objspace, VALUE obj)
+{
+ check_rvalue_consistency(objspace, obj);
+ return RVALUE_MARKED_BITMAP(obj) != 0;
+}
+
+static inline int
+RVALUE_PINNED(rb_objspace_t *objspace, VALUE obj)
+{
+ check_rvalue_consistency(objspace, obj);
+ return RVALUE_PINNED_BITMAP(obj) != 0;
+}
+
+static inline int
+RVALUE_WB_UNPROTECTED(rb_objspace_t *objspace, VALUE obj)
+{
+ check_rvalue_consistency(objspace, obj);
+ return RVALUE_WB_UNPROTECTED_BITMAP(obj) != 0;
+}
+
+static inline int
+RVALUE_MARKING(rb_objspace_t *objspace, VALUE obj)
+{
+ check_rvalue_consistency(objspace, obj);
+ return RVALUE_MARKING_BITMAP(obj) != 0;
+}
+
+static inline int
+RVALUE_REMEMBERED(rb_objspace_t *objspace, VALUE obj)
+{
+ check_rvalue_consistency(objspace, obj);
+ return MARKED_IN_BITMAP(GET_HEAP_PAGE(obj)->remembered_bits, obj) != 0;
+}
+
+static inline int
+RVALUE_UNCOLLECTIBLE(rb_objspace_t *objspace, VALUE obj)
+{
+ check_rvalue_consistency(objspace, obj);
+ return RVALUE_UNCOLLECTIBLE_BITMAP(obj) != 0;
+}
+
+#define RVALUE_PAGE_WB_UNPROTECTED(page, obj) MARKED_IN_BITMAP((page)->wb_unprotected_bits, (obj))
+#define RVALUE_PAGE_UNCOLLECTIBLE(page, obj) MARKED_IN_BITMAP((page)->uncollectible_bits, (obj))
+#define RVALUE_PAGE_MARKING(page, obj) MARKED_IN_BITMAP((page)->marking_bits, (obj))
+
+static int rgengc_remember(rb_objspace_t *objspace, VALUE obj);
+static void rgengc_mark_and_rememberset_clear(rb_objspace_t *objspace, rb_heap_t *heap);
+static void rgengc_rememberset_mark(rb_objspace_t *objspace, rb_heap_t *heap);
+
+static int
+check_rvalue_consistency_force(rb_objspace_t *objspace, const VALUE obj, int terminate)
+{
+ int err = 0;
+
+ int lev = RB_GC_VM_LOCK_NO_BARRIER();
+ {
+ 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)) {
+ struct heap_page *empty_page = objspace->empty_pages;
+ while (empty_page) {
+ if ((uintptr_t)empty_page->body <= (uintptr_t)obj &&
+ (uintptr_t)obj < (uintptr_t)empty_page->body + HEAP_PAGE_SIZE) {
+ GC_ASSERT(heap_page_in_global_empty_pages_pool(objspace, empty_page));
+ fprintf(stderr, "check_rvalue_consistency: %p is in an empty page (%p).\n",
+ (void *)obj, (void *)empty_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_MARKED_BITMAP(obj) != 0;
+ const int marking_bit = RVALUE_MARKING_BITMAP(obj) != 0;
+ const int remembered_bit = MARKED_IN_BITMAP(GET_HEAP_PAGE(obj)->remembered_bits, obj) != 0;
+ const int age = RVALUE_AGE_GET((VALUE)obj);
+
+ if (heap_page_in_global_empty_pages_pool(objspace, GET_HEAP_PAGE(obj))) {
+ fprintf(stderr, "check_rvalue_consistency: %s is in tomb page.\n", rb_obj_info(obj));
+ err++;
+ }
+ if (BUILTIN_TYPE(obj) == T_NONE) {
+ fprintf(stderr, "check_rvalue_consistency: %s is T_NONE.\n", rb_obj_info(obj));
+ err++;
+ }
+ if (BUILTIN_TYPE(obj) == T_ZOMBIE) {
+ fprintf(stderr, "check_rvalue_consistency: %s is T_ZOMBIE.\n", rb_obj_info(obj));
+ err++;
+ }
+
+ if (BUILTIN_TYPE(obj) != T_DATA) {
+ rb_obj_memsize_of((VALUE)obj);
+ }
+
+ /* 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", rb_obj_info(obj), age);
+ err++;
+ }
+
+ if (!is_marking(objspace) && uncollectible_bit && !mark_bit) {
+ fprintf(stderr, "check_rvalue_consistency: %s is uncollectible, but is not marked while !gc.\n", rb_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",
+ rb_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",
+ rb_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", rb_obj_info(obj));
+ err++;
+ }
+ }
+ }
+ }
+ RB_GC_VM_UNLOCK_NO_BARRIER(lev);
+
+ if (err > 0 && terminate) {
+ rb_bug("check_rvalue_consistency_force: there is %d errors.", err);
+ }
+ return err;
+}
+
+#if RGENGC_CHECK_MODE == 0
+static inline VALUE
+check_rvalue_consistency(rb_objspace_t *objspace, const VALUE obj)
+{
+ return obj;
+}
+#else
+static VALUE
+check_rvalue_consistency(rb_objspace_t *objspace, const VALUE obj)
+{
+ check_rvalue_consistency_force(objspace, obj, TRUE);
+ return obj;
+}
+#endif
+
+static inline bool
+gc_object_moved_p(rb_objspace_t *objspace, VALUE obj)
+{
+
+ bool ret;
+ asan_unpoisoning_object(obj) {
+ ret = BUILTIN_TYPE(obj) == T_MOVED;
+ }
+ return ret;
+}
+
+static inline int
+RVALUE_OLD_P(rb_objspace_t *objspace, VALUE obj)
+{
+ GC_ASSERT(!RB_SPECIAL_CONST_P(obj));
+ check_rvalue_consistency(objspace, obj);
+ // Because this will only ever be called on GC controlled objects,
+ // we can use the faster _RAW function here
+ return RB_OBJ_PROMOTED_RAW(obj);
+}
+
+static inline void
+RVALUE_PAGE_OLD_UNCOLLECTIBLE_SET(rb_objspace_t *objspace, struct heap_page *page, VALUE obj)
+{
+ MARK_IN_BITMAP(&page->uncollectible_bits[0], obj);
+ objspace->rgengc.old_objects++;
+
+#if RGENGC_PROFILE >= 2
+ objspace->profile.total_promoted_count++;
+ objspace->profile.promoted_types[BUILTIN_TYPE(obj)]++;
+#endif
+}
+
+static inline void
+RVALUE_OLD_UNCOLLECTIBLE_SET(rb_objspace_t *objspace, VALUE obj)
+{
+ RB_DEBUG_COUNTER_INC(obj_promote);
+ RVALUE_PAGE_OLD_UNCOLLECTIBLE_SET(objspace, GET_HEAP_PAGE(obj), obj);
+}
+
+/* set age to age+1 */
+static inline void
+RVALUE_AGE_INC(rb_objspace_t *objspace, VALUE obj)
+{
+ int age = RVALUE_AGE_GET((VALUE)obj);
+
+ if (RGENGC_CHECK_MODE && age == RVALUE_OLD_AGE) {
+ rb_bug("RVALUE_AGE_INC: can not increment age of OLD object %s.", rb_obj_info(obj));
+ }
+
+ age++;
+ RVALUE_AGE_SET(obj, age);
+
+ if (age == RVALUE_OLD_AGE) {
+ RVALUE_OLD_UNCOLLECTIBLE_SET(objspace, obj);
+ }
+
+ check_rvalue_consistency(objspace, obj);
+}
+
+static inline void
+RVALUE_AGE_SET_CANDIDATE(rb_objspace_t *objspace, VALUE obj)
+{
+ check_rvalue_consistency(objspace, obj);
+ GC_ASSERT(!RVALUE_OLD_P(objspace, obj));
+ RVALUE_AGE_SET(obj, RVALUE_OLD_AGE - 1);
+ check_rvalue_consistency(objspace, obj);
+}
+
+static inline void
+RVALUE_AGE_RESET(VALUE obj)
+{
+ RVALUE_AGE_SET(obj, 0);
+}
+
+static inline void
+RVALUE_DEMOTE(rb_objspace_t *objspace, VALUE obj)
+{
+ check_rvalue_consistency(objspace, obj);
+ GC_ASSERT(RVALUE_OLD_P(objspace, obj));
+
+ if (!is_incremental_marking(objspace) && RVALUE_REMEMBERED(objspace, obj)) {
+ CLEAR_IN_BITMAP(GET_HEAP_PAGE(obj)->remembered_bits, obj);
+ }
+
+ CLEAR_IN_BITMAP(GET_HEAP_UNCOLLECTIBLE_BITS(obj), obj);
+ RVALUE_AGE_RESET(obj);
+
+ if (RVALUE_MARKED(objspace, obj)) {
+ objspace->rgengc.old_objects--;
+ }
+
+ check_rvalue_consistency(objspace, obj);
+}
+
+static inline int
+RVALUE_BLACK_P(rb_objspace_t *objspace, VALUE obj)
+{
+ return RVALUE_MARKED(objspace, obj) && !RVALUE_MARKING(objspace, obj);
+}
+
+static inline int
+RVALUE_WHITE_P(rb_objspace_t *objspace, VALUE obj)
+{
+ return !RVALUE_MARKED(objspace, obj);
+}
+
+bool
+rb_gc_impl_gc_enabled_p(void *objspace_ptr)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+ return !dont_gc_val();
+}
+
+void
+rb_gc_impl_gc_enable(void *objspace_ptr)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ dont_gc_off();
+}
+
+void
+rb_gc_impl_gc_disable(void *objspace_ptr, bool finish_current_gc)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ if (finish_current_gc) {
+ gc_rest(objspace);
+ }
+
+ dont_gc_on();
+}
+
+/*
+ --------------------------- ObjectSpace -----------------------------
+*/
+
+static inline void *
+calloc1(size_t n)
+{
+ return calloc(1, n);
+}
+
+void
+rb_gc_impl_set_event_hook(void *objspace_ptr, const rb_event_flag_t event)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+ objspace->hook_events = event & RUBY_INTERNAL_EVENT_OBJSPACE_MASK;
+}
+
+unsigned long long
+rb_gc_impl_get_total_time(void *objspace_ptr)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ unsigned long long marking_time = objspace->profile.marking_time_ns;
+ unsigned long long sweeping_time = objspace->profile.sweeping_time_ns;
+
+ return marking_time + sweeping_time;
+}
+
+void
+rb_gc_impl_set_measure_total_time(void *objspace_ptr, VALUE flag)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ objspace->flags.measure_gc = RTEST(flag) ? TRUE : FALSE;
+}
+
+bool
+rb_gc_impl_get_measure_total_time(void *objspace_ptr)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ return objspace->flags.measure_gc;
+}
+
+static size_t
+minimum_slots_for_heap(rb_objspace_t *objspace, rb_heap_t *heap)
+{
+ size_t heap_idx = heap - heaps;
+ return gc_params.heap_init_slots[heap_idx];
+}
+
+/* garbage objects will be collected soon. */
+bool
+rb_gc_impl_garbage_object_p(void *objspace_ptr, VALUE ptr)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ bool dead = false;
+
+ asan_unpoisoning_object(ptr) {
+ switch (BUILTIN_TYPE(ptr)) {
+ case T_NONE:
+ case T_MOVED:
+ case T_ZOMBIE:
+ dead = true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (dead) return true;
+ return is_lazy_sweeping(objspace) && GET_HEAP_PAGE(ptr)->flags.before_sweep &&
+ !RVALUE_MARKED(objspace, ptr);
+}
+
+static void free_stack_chunks(mark_stack_t *);
+static void mark_stack_free_cache(mark_stack_t *);
+static void heap_page_free(rb_objspace_t *objspace, struct heap_page *page);
+
+static inline void
+heap_page_add_freeobj(rb_objspace_t *objspace, struct heap_page *page, VALUE obj)
+{
+ rb_asan_unpoison_object(obj, false);
+
+ asan_unlock_freelist(page);
+
+ struct free_slot *slot = (struct free_slot *)obj;
+ slot->flags = 0;
+ slot->next = page->freelist;
+ page->freelist = slot;
+ asan_lock_freelist(page);
+
+ // Should have already been reset
+ GC_ASSERT(RVALUE_AGE_GET(obj) == 0);
+
+ if (RGENGC_CHECK_MODE &&
+ /* obj should belong to page */
+ !(page->start <= (uintptr_t)obj &&
+ (uintptr_t)obj < ((uintptr_t)page->start + (page->total_slots * page->slot_size)) &&
+ obj % BASE_SLOT_SIZE == 0)) {
+ rb_bug("heap_page_add_freeobj: %p is not rvalue.", (void *)obj);
+ }
+
+ rb_asan_poison_object(obj);
+ gc_report(3, objspace, "heap_page_add_freeobj: add %p to freelist\n", (void *)obj);
+}
+
+static void
+heap_allocatable_slots_expand(rb_objspace_t *objspace,
+ rb_heap_t *heap, size_t free_slots, size_t total_slots)
+{
+ double goal_ratio = gc_params.heap_free_slots_goal_ratio;
+ size_t target_total_slots;
+
+ if (goal_ratio == 0.0) {
+ target_total_slots = (size_t)(total_slots * gc_params.growth_factor);
+ }
+ else if (total_slots == 0) {
+ target_total_slots = minimum_slots_for_heap(objspace, heap);
+ }
+ else {
+ /* Find `f' where free_slots = f * total_slots * goal_ratio
+ * => f = (total_slots - free_slots) / ((1 - goal_ratio) * total_slots)
+ */
+ double f = (double)(total_slots - free_slots) / ((1 - goal_ratio) * total_slots);
+
+ if (f > gc_params.growth_factor) f = gc_params.growth_factor;
+ if (f < 1.0) f = 1.1;
+
+ target_total_slots = (size_t)(f * total_slots);
+
+ if (0) {
+ fprintf(stderr,
+ "free_slots(%8"PRIuSIZE")/total_slots(%8"PRIuSIZE")=%1.2f,"
+ " G(%1.2f), f(%1.2f),"
+ " total_slots(%8"PRIuSIZE") => target_total_slots(%8"PRIuSIZE")\n",
+ free_slots, total_slots, free_slots/(double)total_slots,
+ goal_ratio, f, total_slots, target_total_slots);
+ }
+ }
+
+ if (gc_params.growth_max_slots > 0) {
+ size_t max_total_slots = (size_t)(total_slots + gc_params.growth_max_slots);
+ if (target_total_slots > max_total_slots) target_total_slots = max_total_slots;
+ }
+
+ size_t extend_slot_count = target_total_slots - total_slots;
+ /* Extend by at least 1 page. */
+ if (extend_slot_count == 0) extend_slot_count = 1;
+
+ objspace->heap_pages.allocatable_slots += extend_slot_count;
+}
+
+static inline void
+heap_add_freepage(rb_heap_t *heap, struct heap_page *page)
+{
+ asan_unlock_freelist(page);
+ GC_ASSERT(page->free_slots != 0);
+ 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_lock_freelist(page);
+}
+
+static inline void
+heap_add_poolpage(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *page)
+{
+ asan_unlock_freelist(page);
+ GC_ASSERT(page->free_slots != 0);
+ GC_ASSERT(page->freelist != NULL);
+
+ page->free_next = heap->pooled_pages;
+ heap->pooled_pages = page;
+ objspace->rincgc.pooled_slots += page->free_slots;
+
+ asan_lock_freelist(page);
+}
+
+static void
+heap_unlink_page(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *page)
+{
+ ccan_list_del(&page->page_node);
+ heap->total_pages--;
+ heap->total_slots -= page->total_slots;
+}
+
+static void
+gc_aligned_free(void *ptr, size_t size)
+{
+#if defined __MINGW32__
+ __mingw_aligned_free(ptr);
+#elif defined _WIN32
+ _aligned_free(ptr);
+#elif defined(HAVE_POSIX_MEMALIGN) || defined(HAVE_MEMALIGN)
+ free(ptr);
+#else
+ free(((void**)ptr)[-1]);
+#endif
+}
+
+static void
+heap_page_body_free(struct heap_page_body *page_body)
+{
+ GC_ASSERT((uintptr_t)page_body % HEAP_PAGE_ALIGN == 0);
+
+ if (HEAP_PAGE_ALLOC_USE_MMAP) {
+#ifdef HAVE_MMAP
+ GC_ASSERT(HEAP_PAGE_SIZE % sysconf(_SC_PAGE_SIZE) == 0);
+ if (munmap(page_body, HEAP_PAGE_SIZE)) {
+ rb_bug("heap_page_body_free: munmap failed");
+ }
+#endif
+ }
+ else {
+ gc_aligned_free(page_body, HEAP_PAGE_SIZE);
+ }
+}
+
+static void
+heap_page_free(rb_objspace_t *objspace, struct heap_page *page)
+{
+ objspace->heap_pages.freed_pages++;
+ heap_page_body_free(page->body);
+ free(page);
+}
+
+static void
+heap_pages_free_unused_pages(rb_objspace_t *objspace)
+{
+ if (objspace->empty_pages != NULL && heap_pages_freeable_pages > 0) {
+ GC_ASSERT(objspace->empty_pages_count > 0);
+ objspace->empty_pages = NULL;
+ objspace->empty_pages_count = 0;
+
+ size_t i, j;
+ for (i = j = 0; i < rb_darray_size(objspace->heap_pages.sorted); i++) {
+ struct heap_page *page = rb_darray_get(objspace->heap_pages.sorted, i);
+
+ if (heap_page_in_global_empty_pages_pool(objspace, page) && heap_pages_freeable_pages > 0) {
+ heap_page_free(objspace, page);
+ heap_pages_freeable_pages--;
+ }
+ else {
+ if (heap_page_in_global_empty_pages_pool(objspace, page)) {
+ page->free_next = objspace->empty_pages;
+ objspace->empty_pages = page;
+ objspace->empty_pages_count++;
+ }
+
+ if (i != j) {
+ rb_darray_set(objspace->heap_pages.sorted, j, page);
+ }
+ j++;
+ }
+ }
+
+ rb_darray_pop(objspace->heap_pages.sorted, i - j);
+ GC_ASSERT(rb_darray_size(objspace->heap_pages.sorted) == j);
+
+ struct heap_page *hipage = rb_darray_get(objspace->heap_pages.sorted, rb_darray_size(objspace->heap_pages.sorted) - 1);
+ uintptr_t himem = (uintptr_t)hipage->body + HEAP_PAGE_SIZE;
+ GC_ASSERT(himem <= heap_pages_himem);
+ heap_pages_himem = himem;
+
+ struct heap_page *lopage = rb_darray_get(objspace->heap_pages.sorted, 0);
+ uintptr_t lomem = (uintptr_t)lopage->body + sizeof(struct heap_page_header);
+ GC_ASSERT(lomem >= heap_pages_lomem);
+ heap_pages_lomem = lomem;
+ }
+}
+
+static void *
+gc_aligned_malloc(size_t alignment, size_t size)
+{
+ /* alignment must be a power of 2 */
+ GC_ASSERT(((alignment - 1) & alignment) == 0);
+ GC_ASSERT(alignment % sizeof(void*) == 0);
+
+ void *res;
+
+#if defined __MINGW32__
+ res = __mingw_aligned_malloc(size, alignment);
+#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 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
+
+ GC_ASSERT((uintptr_t)res % alignment == 0);
+
+ return res;
+}
+
+static struct heap_page_body *
+heap_page_body_allocate(void)
+{
+ struct heap_page_body *page_body;
+
+ if (HEAP_PAGE_ALLOC_USE_MMAP) {
+#ifdef HAVE_MMAP
+ GC_ASSERT(HEAP_PAGE_ALIGN % sysconf(_SC_PAGE_SIZE) == 0);
+
+ size_t mmap_size = HEAP_PAGE_ALIGN + HEAP_PAGE_SIZE;
+ char *ptr = mmap(NULL, mmap_size,
+ PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (ptr == MAP_FAILED) {
+ return NULL;
+ }
+
+ // If we are building `default.c` as part of the ruby executable, we
+ // may just call `ruby_annotate_mmap`. But if we are building
+ // `default.c` as a shared library, we will not have access to private
+ // symbols, and we have to either call prctl directly or make our own
+ // wrapper.
+#if defined(HAVE_SYS_PRCTL_H) && defined(PR_SET_VMA) && defined(PR_SET_VMA_ANON_NAME)
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ptr, mmap_size, "Ruby:GC:default:heap_page_body_allocate");
+ errno = 0;
+#endif
+
+ char *aligned = ptr + HEAP_PAGE_ALIGN;
+ aligned -= ((VALUE)aligned & (HEAP_PAGE_ALIGN - 1));
+ GC_ASSERT(aligned > ptr);
+ GC_ASSERT(aligned <= ptr + HEAP_PAGE_ALIGN);
+
+ 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("heap_page_body_allocate: munmap failed for start");
+ }
+ }
+
+ size_t end_out_of_range_size = HEAP_PAGE_ALIGN - 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 + HEAP_PAGE_SIZE, end_out_of_range_size)) {
+ rb_bug("heap_page_body_allocate: munmap failed for end");
+ }
+ }
+
+ page_body = (struct heap_page_body *)aligned;
+#endif
+ }
+ else {
+ page_body = gc_aligned_malloc(HEAP_PAGE_ALIGN, HEAP_PAGE_SIZE);
+ }
+
+ GC_ASSERT((uintptr_t)page_body % HEAP_PAGE_ALIGN == 0);
+
+ return page_body;
+}
+
+static struct heap_page *
+heap_page_resurrect(rb_objspace_t *objspace)
+{
+ struct heap_page *page = NULL;
+ if (objspace->empty_pages == NULL) {
+ GC_ASSERT(objspace->empty_pages_count == 0);
+ }
+ else {
+ GC_ASSERT(objspace->empty_pages_count > 0);
+ objspace->empty_pages_count--;
+ page = objspace->empty_pages;
+ objspace->empty_pages = page->free_next;
+ }
+
+ return page;
+}
+
+static struct heap_page *
+heap_page_allocate(rb_objspace_t *objspace)
+{
+ struct heap_page_body *page_body = heap_page_body_allocate();
+ if (page_body == 0) {
+ rb_memerror();
+ }
+
+ struct heap_page *page = calloc1(sizeof(struct heap_page));
+ if (page == 0) {
+ heap_page_body_free(page_body);
+ rb_memerror();
+ }
+
+ uintptr_t start = (uintptr_t)page_body + sizeof(struct heap_page_header);
+ uintptr_t end = (uintptr_t)page_body + HEAP_PAGE_SIZE;
+
+ size_t lo = 0;
+ size_t hi = rb_darray_size(objspace->heap_pages.sorted);
+ while (lo < hi) {
+ struct heap_page *mid_page;
+
+ size_t mid = (lo + hi) / 2;
+ mid_page = rb_darray_get(objspace->heap_pages.sorted, mid);
+ if ((uintptr_t)mid_page->start < start) {
+ lo = mid + 1;
+ }
+ else if ((uintptr_t)mid_page->start > start) {
+ hi = mid;
+ }
+ else {
+ rb_bug("same heap page is allocated: %p at %"PRIuVALUE, (void *)page_body, (VALUE)mid);
+ }
+ }
+
+ rb_darray_insert_without_gc(&objspace->heap_pages.sorted, hi, page);
+
+ if (heap_pages_lomem == 0 || heap_pages_lomem > start) heap_pages_lomem = start;
+ if (heap_pages_himem < end) heap_pages_himem = end;
+
+ page->body = page_body;
+ page_body->header.page = page;
+
+ objspace->heap_pages.allocated_pages++;
+
+ return page;
+}
+
+static void
+heap_add_page(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *page)
+{
+ /* Adding to eden heap during incremental sweeping is forbidden */
+ GC_ASSERT(!heap->sweeping_page);
+ GC_ASSERT(heap_page_in_global_empty_pages_pool(objspace, page));
+
+ /* adjust obj_limit (object number available in this page) */
+ uintptr_t start = (uintptr_t)page->body + sizeof(struct heap_page_header);
+ if (start % BASE_SLOT_SIZE != 0) {
+ int delta = BASE_SLOT_SIZE - (start % BASE_SLOT_SIZE);
+ 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 += heap->slot_size - BASE_SLOT_SIZE;
+ }
+
+ GC_ASSERT(NUM_IN_PAGE(start) * BASE_SLOT_SIZE % heap->slot_size == 0);
+ }
+
+ int slot_count = (int)((HEAP_PAGE_SIZE - (start - (uintptr_t)page->body))/heap->slot_size);
+
+ page->start = start;
+ page->total_slots = slot_count;
+ page->slot_size = heap->slot_size;
+ page->heap = heap;
+
+ asan_unlock_freelist(page);
+ page->freelist = NULL;
+ asan_unpoison_memory_region(page->body, HEAP_PAGE_SIZE, false);
+ for (VALUE p = (VALUE)start; p < start + (slot_count * heap->slot_size); p += heap->slot_size) {
+ heap_page_add_freeobj(objspace, page, p);
+ }
+ asan_lock_freelist(page);
+
+ page->free_slots = slot_count;
+
+ heap->total_allocated_pages++;
+
+ ccan_list_add_tail(&heap->pages, &page->page_node);
+ heap->total_pages++;
+ heap->total_slots += page->total_slots;
+}
+
+static int
+heap_page_allocate_and_initialize(rb_objspace_t *objspace, rb_heap_t *heap)
+{
+ gc_report(1, objspace, "heap_page_allocate_and_initialize: rb_darray_size(objspace->heap_pages.sorted): %"PRIdSIZE", "
+ "allocatable_slots: %"PRIdSIZE", heap->total_pages: %"PRIdSIZE"\n",
+ rb_darray_size(objspace->heap_pages.sorted), objspace->heap_pages.allocatable_slots, heap->total_pages);
+
+ bool allocated = false;
+ struct heap_page *page = heap_page_resurrect(objspace);
+
+ if (page == NULL && objspace->heap_pages.allocatable_slots > 0) {
+ page = heap_page_allocate(objspace);
+ allocated = true;
+
+ GC_ASSERT(page != NULL);
+ }
+
+ if (page != NULL) {
+ heap_add_page(objspace, heap, page);
+ heap_add_freepage(heap, page);
+
+ if (allocated) {
+ if (objspace->heap_pages.allocatable_slots > (size_t)page->total_slots) {
+ objspace->heap_pages.allocatable_slots -= page->total_slots;
+ }
+ else {
+ objspace->heap_pages.allocatable_slots = 0;
+ }
+ }
+ }
+
+ return page != NULL;
+}
+
+static void
+heap_page_allocate_and_initialize_force(rb_objspace_t *objspace, rb_heap_t *heap)
+{
+ size_t prev_allocatable_slots = objspace->heap_pages.allocatable_slots;
+ // Set allocatable slots to 1 to force a page to be created.
+ objspace->heap_pages.allocatable_slots = 1;
+ heap_page_allocate_and_initialize(objspace, heap);
+ GC_ASSERT(heap->free_pages != NULL);
+ objspace->heap_pages.allocatable_slots = prev_allocatable_slots;
+}
+
+static void
+gc_continue(rb_objspace_t *objspace, rb_heap_t *heap)
+{
+ unsigned int lock_lev;
+ bool needs_gc = is_incremental_marking(objspace) || needs_continue_sweeping(objspace, heap);
+ if (!needs_gc) return;
+
+ gc_enter(objspace, gc_enter_event_continue, &lock_lev); // takes vm barrier, try to avoid
+
+ /* Continue marking if in incremental marking. */
+ if (is_incremental_marking(objspace)) {
+ if (gc_marks_continue(objspace, heap)) {
+ gc_sweep(objspace);
+ }
+ }
+
+ if (needs_continue_sweeping(objspace, heap)) {
+ gc_sweep_continue(objspace, heap);
+ }
+
+ gc_exit(objspace, gc_enter_event_continue, &lock_lev);
+}
+
+static void
+heap_prepare(rb_objspace_t *objspace, rb_heap_t *heap)
+{
+ GC_ASSERT(heap->free_pages == NULL);
+
+ if (heap->total_slots < gc_params.heap_init_slots[heap - heaps] &&
+ heap->sweeping_page == NULL) {
+ heap_page_allocate_and_initialize_force(objspace, heap);
+ GC_ASSERT(heap->free_pages != NULL);
+ return;
+ }
+
+ /* Continue incremental marking or lazy sweeping, if in any of those steps. */
+ gc_continue(objspace, heap);
+
+ if (heap->free_pages == NULL) {
+ heap_page_allocate_and_initialize(objspace, heap);
+ }
+
+ /* If we still don't have a free page and not allowed to create a new page,
+ * we should start a new GC cycle. */
+ if (heap->free_pages == NULL) {
+ GC_ASSERT(objspace->empty_pages_count == 0);
+ GC_ASSERT(objspace->heap_pages.allocatable_slots == 0);
+
+ if (gc_start(objspace, GPR_FLAG_NEWOBJ) == FALSE) {
+ rb_memerror();
+ }
+ else {
+ if (objspace->heap_pages.allocatable_slots == 0 && !gc_config_full_mark_val) {
+ heap_allocatable_slots_expand(objspace, heap,
+ heap->freed_slots + heap->empty_slots,
+ heap->total_slots);
+ GC_ASSERT(objspace->heap_pages.allocatable_slots > 0);
+ }
+ /* Do steps of incremental marking or lazy sweeping if the GC run permits. */
+ gc_continue(objspace, heap);
+
+ /* If we're not incremental marking (e.g. a minor GC) or finished
+ * sweeping and still don't have a free page, then
+ * gc_sweep_finish_heap should allow us to create a new page. */
+ if (heap->free_pages == NULL && !heap_page_allocate_and_initialize(objspace, heap)) {
+ if (gc_needs_major_flags == GPR_FLAG_NONE) {
+ rb_bug("cannot create a new page after GC");
+ }
+ else { // Major GC is required, which will allow us to create new page
+ if (gc_start(objspace, GPR_FLAG_NEWOBJ) == FALSE) {
+ rb_memerror();
+ }
+ else {
+ /* Do steps of incremental marking or lazy sweeping. */
+ gc_continue(objspace, heap);
+
+ if (heap->free_pages == NULL &&
+ !heap_page_allocate_and_initialize(objspace, heap)) {
+ rb_bug("cannot create a new page after major GC");
+ }
+ }
+ }
+ }
+ }
+ }
+
+ GC_ASSERT(heap->free_pages != NULL);
+}
+
+#if GC_DEBUG
+static inline const char*
+rb_gc_impl_source_location_cstr(int *ptr)
+{
+ /* We could directly refer `rb_source_location_cstr()` before, but not any
+ * longer. We have to heavy lift using our debugging API. */
+ if (! ptr) {
+ return NULL;
+ }
+ else if (! (*ptr = rb_sourceline())) {
+ return NULL;
+ }
+ else {
+ return rb_sourcefile();
+ }
+}
+#endif
+
+static inline VALUE
+newobj_init(VALUE klass, VALUE flags, int wb_protected, rb_objspace_t *objspace, VALUE obj)
+{
+ GC_ASSERT(BUILTIN_TYPE(obj) == T_NONE);
+ GC_ASSERT((flags & FL_WB_PROTECTED) == 0);
+ RBASIC(obj)->flags = flags;
+ *((VALUE *)&RBASIC(obj)->klass) = klass;
+#if RBASIC_SHAPE_ID_FIELD
+ RBASIC(obj)->shape_id = 0;
+#endif
+
+ int t = flags & RUBY_T_MASK;
+ if (t == T_CLASS || t == T_MODULE || t == T_ICLASS) {
+ RVALUE_AGE_SET_CANDIDATE(objspace, obj);
+ }
+
+#if RACTOR_CHECK_MODE
+ void rb_ractor_setup_belonging(VALUE obj);
+ rb_ractor_setup_belonging(obj);
+#endif
+
+#if RGENGC_CHECK_MODE
+ int lev = RB_GC_VM_LOCK_NO_BARRIER();
+ {
+ check_rvalue_consistency(objspace, obj);
+
+ GC_ASSERT(RVALUE_MARKED(objspace, obj) == FALSE);
+ GC_ASSERT(RVALUE_MARKING(objspace, obj) == FALSE);
+ GC_ASSERT(RVALUE_OLD_P(objspace, obj) == FALSE);
+ GC_ASSERT(RVALUE_WB_UNPROTECTED(objspace, obj) == FALSE);
+
+ if (RVALUE_REMEMBERED(objspace, obj)) rb_bug("newobj: %s is remembered.", rb_obj_info(obj));
+ }
+ RB_GC_VM_UNLOCK_NO_BARRIER(lev);
+#endif
+
+ if (RB_UNLIKELY(wb_protected == FALSE)) {
+ MARK_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(obj), obj);
+ }
+
+#if RGENGC_PROFILE
+ if (wb_protected) {
+ objspace->profile.total_generated_normal_object_count++;
+#if RGENGC_PROFILE >= 2
+ objspace->profile.generated_normal_object_count_types[BUILTIN_TYPE(obj)]++;
+#endif
+ }
+ else {
+ objspace->profile.total_generated_shady_object_count++;
+#if RGENGC_PROFILE >= 2
+ objspace->profile.generated_shady_object_count_types[BUILTIN_TYPE(obj)]++;
+#endif
+ }
+#endif
+
+#if GC_DEBUG
+ GET_RVALUE_OVERHEAD(obj)->file = rb_gc_impl_source_location_cstr(&GET_RVALUE_OVERHEAD(obj)->line);
+ GC_ASSERT(!SPECIAL_CONST_P(obj)); /* check alignment */
+#endif
+
+ gc_report(5, objspace, "newobj: %s\n", rb_obj_info(obj));
+
+ // RUBY_DEBUG_LOG("obj:%p (%s)", (void *)obj, rb_obj_info(obj));
+ return obj;
+}
+
+size_t
+rb_gc_impl_obj_slot_size(VALUE obj)
+{
+ return GET_HEAP_PAGE(obj)->slot_size - RVALUE_OVERHEAD;
+}
+
+static inline size_t
+heap_slot_size(unsigned char pool_id)
+{
+ GC_ASSERT(pool_id < HEAP_COUNT);
+
+ size_t slot_size = (1 << pool_id) * BASE_SLOT_SIZE;
+
+#if RGENGC_CHECK_MODE
+ rb_objspace_t *objspace = rb_gc_get_objspace();
+ GC_ASSERT(heaps[pool_id].slot_size == (short)slot_size);
+#endif
+
+ slot_size -= RVALUE_OVERHEAD;
+
+ return slot_size;
+}
+
+bool
+rb_gc_impl_size_allocatable_p(size_t size)
+{
+ return size <= heap_slot_size(HEAP_COUNT - 1);
+}
+
+static const size_t ALLOCATED_COUNT_STEP = 1024;
+static void
+ractor_cache_flush_count(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache)
+{
+ for (int heap_idx = 0; heap_idx < HEAP_COUNT; heap_idx++) {
+ rb_ractor_newobj_heap_cache_t *heap_cache = &cache->heap_caches[heap_idx];
+
+ rb_heap_t *heap = &heaps[heap_idx];
+ RUBY_ATOMIC_SIZE_ADD(heap->total_allocated_objects, heap_cache->allocated_objects_count);
+ heap_cache->allocated_objects_count = 0;
+ }
+}
+
+static inline VALUE
+ractor_cache_allocate_slot(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache,
+ size_t heap_idx)
+{
+ rb_ractor_newobj_heap_cache_t *heap_cache = &cache->heap_caches[heap_idx];
+ struct free_slot *p = heap_cache->freelist;
+
+ if (RB_UNLIKELY(is_incremental_marking(objspace))) {
+ // Not allowed to allocate without running an incremental marking step
+ if (cache->incremental_mark_step_allocated_slots >= INCREMENTAL_MARK_STEP_ALLOCATIONS) {
+ return Qfalse;
+ }
+
+ if (p) {
+ cache->incremental_mark_step_allocated_slots++;
+ }
+ }
+
+ if (RB_LIKELY(p)) {
+ VALUE obj = (VALUE)p;
+ rb_asan_unpoison_object(obj, true);
+ heap_cache->freelist = p->next;
+
+ heap_cache->allocated_objects_count++;
+ rb_heap_t *heap = &heaps[heap_idx];
+ if (heap_cache->allocated_objects_count >= ALLOCATED_COUNT_STEP) {
+ RUBY_ATOMIC_SIZE_ADD(heap->total_allocated_objects, heap_cache->allocated_objects_count);
+ heap_cache->allocated_objects_count = 0;
+ }
+
+#if RGENGC_CHECK_MODE
+ GC_ASSERT(rb_gc_impl_obj_slot_size(obj) == heap_slot_size(heap_idx));
+ // zero clear
+ MEMZERO((char *)obj, char, heap_slot_size(heap_idx));
+#endif
+ return obj;
+ }
+ else {
+ return Qfalse;
+ }
+}
+
+static struct heap_page *
+heap_next_free_page(rb_objspace_t *objspace, rb_heap_t *heap)
+{
+ struct heap_page *page;
+
+ if (heap->free_pages == NULL) {
+ heap_prepare(objspace, heap);
+ }
+
+ page = heap->free_pages;
+ heap->free_pages = page->free_next;
+
+ GC_ASSERT(page->free_slots != 0);
+
+ asan_unlock_freelist(page);
+
+ return page;
+}
+
+static inline void
+ractor_cache_set_page(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t heap_idx,
+ struct heap_page *page)
+{
+ gc_report(3, objspace, "ractor_set_cache: Using page %p\n", (void *)page->body);
+
+ rb_ractor_newobj_heap_cache_t *heap_cache = &cache->heap_caches[heap_idx];
+
+ GC_ASSERT(heap_cache->freelist == NULL);
+ GC_ASSERT(page->free_slots != 0);
+ GC_ASSERT(page->freelist != NULL);
+
+ heap_cache->using_page = page;
+ heap_cache->freelist = page->freelist;
+ page->free_slots = 0;
+ page->freelist = NULL;
+
+ rb_asan_unpoison_object((VALUE)heap_cache->freelist, false);
+ GC_ASSERT(RB_TYPE_P((VALUE)heap_cache->freelist, T_NONE));
+ rb_asan_poison_object((VALUE)heap_cache->freelist);
+}
+
+static inline size_t
+heap_idx_for_size(size_t size)
+{
+ size += RVALUE_OVERHEAD;
+
+ size_t slot_count = CEILDIV(size, BASE_SLOT_SIZE);
+
+ /* heap_idx is ceil(log2(slot_count)) */
+ size_t heap_idx = 64 - nlz_int64(slot_count - 1);
+
+ if (heap_idx >= HEAP_COUNT) {
+ rb_bug("heap_idx_for_size: allocation size too large "
+ "(size=%"PRIuSIZE"u, heap_idx=%"PRIuSIZE"u)", size, heap_idx);
+ }
+
+#if RGENGC_CHECK_MODE
+ rb_objspace_t *objspace = rb_gc_get_objspace();
+ GC_ASSERT(size <= (size_t)heaps[heap_idx].slot_size);
+ if (heap_idx > 0) GC_ASSERT(size > (size_t)heaps[heap_idx - 1].slot_size);
+#endif
+
+ return heap_idx;
+}
+
+size_t
+rb_gc_impl_heap_id_for_size(void *objspace_ptr, size_t size)
+{
+ return heap_idx_for_size(size);
+}
+
+
+static size_t heap_sizes[HEAP_COUNT + 1] = { 0 };
+
+size_t *
+rb_gc_impl_heap_sizes(void *objspace_ptr)
+{
+ if (heap_sizes[0] == 0) {
+ for (unsigned char i = 0; i < HEAP_COUNT; i++) {
+ heap_sizes[i] = heap_slot_size(i);
+ }
+ }
+
+ return heap_sizes;
+}
+
+NOINLINE(static VALUE newobj_cache_miss(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t heap_idx, bool vm_locked));
+
+static VALUE
+newobj_cache_miss(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t heap_idx, bool vm_locked)
+{
+ rb_heap_t *heap = &heaps[heap_idx];
+ VALUE obj = Qfalse;
+
+ unsigned int lev = 0;
+ bool unlock_vm = false;
+
+ if (!vm_locked) {
+ lev = RB_GC_CR_LOCK();
+ unlock_vm = true;
+ }
+
+ {
+ if (is_incremental_marking(objspace)) {
+ gc_continue(objspace, heap);
+ cache->incremental_mark_step_allocated_slots = 0;
+
+ // Retry allocation after resetting incremental_mark_step_allocated_slots
+ obj = ractor_cache_allocate_slot(objspace, cache, heap_idx);
+ }
+
+ if (obj == Qfalse) {
+ // Get next free page (possibly running GC)
+ struct heap_page *page = heap_next_free_page(objspace, heap);
+ ractor_cache_set_page(objspace, cache, heap_idx, page);
+
+ // Retry allocation after moving to new page
+ obj = ractor_cache_allocate_slot(objspace, cache, heap_idx);
+ }
+ }
+
+ if (unlock_vm) {
+ RB_GC_CR_UNLOCK(lev);
+ }
+
+ if (RB_UNLIKELY(obj == Qfalse)) {
+ rb_memerror();
+ }
+ return obj;
+}
+
+static VALUE
+newobj_alloc(rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t heap_idx, bool vm_locked)
+{
+ VALUE obj = ractor_cache_allocate_slot(objspace, cache, heap_idx);
+
+ if (RB_UNLIKELY(obj == Qfalse)) {
+ obj = newobj_cache_miss(objspace, cache, heap_idx, vm_locked);
+ }
+
+ return obj;
+}
+
+ALWAYS_INLINE(static VALUE newobj_slowpath(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, int wb_protected, size_t heap_idx));
+
+static inline VALUE
+newobj_slowpath(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, int wb_protected, size_t heap_idx)
+{
+ VALUE obj;
+ unsigned int lev;
+
+ lev = RB_GC_CR_LOCK();
+ {
+ if (RB_UNLIKELY(during_gc || ruby_gc_stressful)) {
+ if (during_gc) {
+ dont_gc_on();
+ during_gc = 0;
+ if (rb_memerror_reentered()) {
+ rb_memerror();
+ }
+ rb_bug("object allocation during garbage collection phase");
+ }
+
+ if (ruby_gc_stressful) {
+ if (!garbage_collect(objspace, GPR_FLAG_NEWOBJ)) {
+ rb_memerror();
+ }
+ }
+ }
+
+ obj = newobj_alloc(objspace, cache, heap_idx, true);
+ newobj_init(klass, flags, wb_protected, objspace, obj);
+ }
+ RB_GC_CR_UNLOCK(lev);
+
+ return obj;
+}
+
+NOINLINE(static VALUE newobj_slowpath_wb_protected(VALUE klass, VALUE flags,
+ rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t heap_idx));
+NOINLINE(static VALUE newobj_slowpath_wb_unprotected(VALUE klass, VALUE flags,
+ rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t heap_idx));
+
+static VALUE
+newobj_slowpath_wb_protected(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t heap_idx)
+{
+ return newobj_slowpath(klass, flags, objspace, cache, TRUE, heap_idx);
+}
+
+static VALUE
+newobj_slowpath_wb_unprotected(VALUE klass, VALUE flags, rb_objspace_t *objspace, rb_ractor_newobj_cache_t *cache, size_t heap_idx)
+{
+ return newobj_slowpath(klass, flags, objspace, cache, FALSE, heap_idx);
+}
+
+VALUE
+rb_gc_impl_new_obj(void *objspace_ptr, void *cache_ptr, VALUE klass, VALUE flags, bool wb_protected, size_t alloc_size)
+{
+ VALUE obj;
+ rb_objspace_t *objspace = objspace_ptr;
+
+ RB_DEBUG_COUNTER_INC(obj_newobj);
+ (void)RB_DEBUG_COUNTER_INC_IF(obj_newobj_wb_unprotected, !wb_protected);
+
+ if (RB_UNLIKELY(stress_to_class)) {
+ if (rb_hash_lookup2(stress_to_class, klass, Qundef) != Qundef) {
+ rb_memerror();
+ }
+ }
+
+ size_t heap_idx = heap_idx_for_size(alloc_size);
+
+ rb_ractor_newobj_cache_t *cache = (rb_ractor_newobj_cache_t *)cache_ptr;
+
+ if (!RB_UNLIKELY(during_gc || ruby_gc_stressful) &&
+ wb_protected) {
+ obj = newobj_alloc(objspace, cache, heap_idx, false);
+ newobj_init(klass, flags, wb_protected, objspace, obj);
+ }
+ else {
+ RB_DEBUG_COUNTER_INC(obj_newobj_slowpath);
+
+ obj = wb_protected ?
+ newobj_slowpath_wb_protected(klass, flags, objspace, cache, heap_idx) :
+ newobj_slowpath_wb_unprotected(klass, flags, objspace, cache, heap_idx);
+ }
+
+ return obj;
+}
+
+static int
+ptr_in_page_body_p(const void *ptr, const void *memb)
+{
+ struct heap_page *page = *(struct heap_page **)memb;
+ uintptr_t p_body = (uintptr_t)page->body;
+
+ if ((uintptr_t)ptr >= p_body) {
+ return (uintptr_t)ptr < (p_body + HEAP_PAGE_SIZE) ? 0 : 1;
+ }
+ else {
+ return -1;
+ }
+}
+
+PUREFUNC(static inline struct heap_page *heap_page_for_ptr(rb_objspace_t *objspace, uintptr_t ptr);)
+static inline struct heap_page *
+heap_page_for_ptr(rb_objspace_t *objspace, uintptr_t ptr)
+{
+ struct heap_page **res;
+
+ if (ptr < (uintptr_t)heap_pages_lomem ||
+ ptr > (uintptr_t)heap_pages_himem) {
+ return NULL;
+ }
+
+ res = bsearch((void *)ptr, rb_darray_ref(objspace->heap_pages.sorted, 0),
+ rb_darray_size(objspace->heap_pages.sorted), sizeof(struct heap_page *),
+ ptr_in_page_body_p);
+
+ if (res) {
+ return *res;
+ }
+ else {
+ return NULL;
+ }
+}
+
+PUREFUNC(static inline bool is_pointer_to_heap(rb_objspace_t *objspace, const void *ptr);)
+static inline bool
+is_pointer_to_heap(rb_objspace_t *objspace, const void *ptr)
+{
+ register uintptr_t p = (uintptr_t)ptr;
+ register struct heap_page *page;
+
+ RB_DEBUG_COUNTER_INC(gc_isptr_trial);
+
+ if (p < heap_pages_lomem || p > heap_pages_himem) return FALSE;
+ RB_DEBUG_COUNTER_INC(gc_isptr_range);
+
+ if (p % BASE_SLOT_SIZE != 0) return FALSE;
+ RB_DEBUG_COUNTER_INC(gc_isptr_align);
+
+ page = heap_page_for_ptr(objspace, (uintptr_t)ptr);
+ if (page) {
+ RB_DEBUG_COUNTER_INC(gc_isptr_maybe);
+ if (heap_page_in_global_empty_pages_pool(objspace, page)) {
+ return FALSE;
+ }
+ else {
+ if (p < page->start) return FALSE;
+ if (p >= page->start + (page->total_slots * page->slot_size)) return FALSE;
+ if ((NUM_IN_PAGE(p) * BASE_SLOT_SIZE) % page->slot_size != 0) return FALSE;
+
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+bool
+rb_gc_impl_pointer_to_heap_p(void *objspace_ptr, const void *ptr)
+{
+ return is_pointer_to_heap(objspace_ptr, ptr);
+}
+
+#define ZOMBIE_OBJ_KEPT_FLAGS (FL_FINALIZE)
+
+void
+rb_gc_impl_make_zombie(void *objspace_ptr, VALUE obj, void (*dfree)(void *), void *data)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ struct RZombie *zombie = RZOMBIE(obj);
+ zombie->flags = T_ZOMBIE | (zombie->flags & ZOMBIE_OBJ_KEPT_FLAGS);
+ zombie->dfree = dfree;
+ zombie->data = data;
+ VALUE prev, next = heap_pages_deferred_final;
+ do {
+ zombie->next = prev = next;
+ next = RUBY_ATOMIC_VALUE_CAS(heap_pages_deferred_final, prev, obj);
+ } while (next != prev);
+
+ struct heap_page *page = GET_HEAP_PAGE(obj);
+ page->final_slots++;
+ page->heap->final_slots_count++;
+}
+
+typedef int each_obj_callback(void *, void *, size_t, void *);
+typedef int each_page_callback(struct heap_page *, void *);
+
+struct each_obj_data {
+ rb_objspace_t *objspace;
+ bool reenable_incremental;
+
+ each_obj_callback *each_obj_callback;
+ each_page_callback *each_page_callback;
+ void *data;
+
+ struct heap_page **pages[HEAP_COUNT];
+ size_t pages_counts[HEAP_COUNT];
+};
+
+static VALUE
+objspace_each_objects_ensure(VALUE arg)
+{
+ struct each_obj_data *data = (struct each_obj_data *)arg;
+ rb_objspace_t *objspace = data->objspace;
+
+ /* Reenable incremental GC */
+ if (data->reenable_incremental) {
+ objspace->flags.dont_incremental = FALSE;
+ }
+
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ struct heap_page **pages = data->pages[i];
+ free(pages);
+ }
+
+ return Qnil;
+}
+
+static VALUE
+objspace_each_objects_try(VALUE arg)
+{
+ struct each_obj_data *data = (struct each_obj_data *)arg;
+ rb_objspace_t *objspace = data->objspace;
+
+ /* Copy pages from all heaps to their respective buffers. */
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ rb_heap_t *heap = &heaps[i];
+ size_t size = heap->total_pages * sizeof(struct heap_page *);
+
+ 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;
+ ccan_list_for_each(&heap->pages, page, page_node) {
+ pages[pages_count] = page;
+ pages_count++;
+ }
+ data->pages[i] = pages;
+ data->pages_counts[i] = pages_count;
+ GC_ASSERT(pages_count == heap->total_pages);
+ }
+
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ rb_heap_t *heap = &heaps[i];
+ size_t pages_count = data->pages_counts[i];
+ struct heap_page **pages = data->pages[i];
+
+ struct heap_page *page = ccan_list_top(&heap->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 * heap->slot_size);
+
+ if (data->each_obj_callback &&
+ (*data->each_obj_callback)((void *)pstart, (void *)pend, heap->slot_size, data->data)) {
+ break;
+ }
+ if (data->each_page_callback &&
+ (*data->each_page_callback)(page, data->data)) {
+ break;
+ }
+
+ page = ccan_list_next(&heap->pages, page, page_node);
+ }
+ }
+
+ return Qnil;
+}
+
+static void
+objspace_each_exec(bool protected, struct each_obj_data *each_obj_data)
+{
+ /* Disable incremental GC */
+ rb_objspace_t *objspace = each_obj_data->objspace;
+ bool reenable_incremental = FALSE;
+ if (protected) {
+ reenable_incremental = !objspace->flags.dont_incremental;
+
+ gc_rest(objspace);
+ objspace->flags.dont_incremental = TRUE;
+ }
+
+ each_obj_data->reenable_incremental = reenable_incremental;
+ memset(&each_obj_data->pages, 0, sizeof(each_obj_data->pages));
+ memset(&each_obj_data->pages_counts, 0, sizeof(each_obj_data->pages_counts));
+ rb_ensure(objspace_each_objects_try, (VALUE)each_obj_data,
+ objspace_each_objects_ensure, (VALUE)each_obj_data);
+}
+
+static void
+objspace_each_objects(rb_objspace_t *objspace, each_obj_callback *callback, void *data, bool protected)
+{
+ struct each_obj_data each_obj_data = {
+ .objspace = objspace,
+ .each_obj_callback = callback,
+ .each_page_callback = NULL,
+ .data = data,
+ };
+ objspace_each_exec(protected, &each_obj_data);
+}
+
+void
+rb_gc_impl_each_objects(void *objspace_ptr, each_obj_callback *callback, void *data)
+{
+ objspace_each_objects(objspace_ptr, callback, data, TRUE);
+}
+
+#if GC_CAN_COMPILE_COMPACTION
+static void
+objspace_each_pages(rb_objspace_t *objspace, each_page_callback *callback, void *data, bool protected)
+{
+ struct each_obj_data each_obj_data = {
+ .objspace = objspace,
+ .each_obj_callback = NULL,
+ .each_page_callback = callback,
+ .data = data,
+ };
+ objspace_each_exec(protected, &each_obj_data);
+}
+#endif
+
+VALUE
+rb_gc_impl_define_finalizer(void *objspace_ptr, VALUE obj, VALUE block)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+ VALUE table;
+ st_data_t data;
+
+ GC_ASSERT(!OBJ_FROZEN(obj));
+
+ RBASIC(obj)->flags |= FL_FINALIZE;
+
+ unsigned int lev = RB_GC_VM_LOCK();
+
+ if (st_lookup(finalizer_table, obj, &data)) {
+ table = (VALUE)data;
+ VALUE dup_table = rb_ary_dup(table);
+
+ RB_GC_VM_UNLOCK(lev);
+ /* avoid duplicate block, table is usually small */
+ {
+ long len = RARRAY_LEN(table);
+ long i;
+
+ for (i = 0; i < len; i++) {
+ VALUE recv = RARRAY_AREF(dup_table, i);
+ if (rb_equal(recv, block)) { // can't be called with VM lock held
+ return recv;
+ }
+ }
+ }
+ lev = RB_GC_VM_LOCK();
+ RB_GC_GUARD(dup_table);
+
+ rb_ary_push(table, block);
+ }
+ else {
+ table = rb_ary_new3(2, rb_obj_id(obj), block);
+ rb_obj_hide(table);
+ st_add_direct(finalizer_table, obj, table);
+ }
+
+ RB_GC_VM_UNLOCK(lev);
+
+ return block;
+}
+
+void
+rb_gc_impl_undefine_finalizer(void *objspace_ptr, VALUE obj)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ GC_ASSERT(!OBJ_FROZEN(obj));
+
+ st_data_t data = obj;
+
+ int lev = RB_GC_VM_LOCK();
+ st_delete(finalizer_table, &data, 0);
+ RB_GC_VM_UNLOCK(lev);
+
+ FL_UNSET(obj, FL_FINALIZE);
+}
+
+void
+rb_gc_impl_copy_finalizer(void *objspace_ptr, VALUE dest, VALUE obj)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+ VALUE table;
+ st_data_t data;
+
+ if (!FL_TEST(obj, FL_FINALIZE)) return;
+
+ int lev = RB_GC_VM_LOCK();
+ if (RB_LIKELY(st_lookup(finalizer_table, obj, &data))) {
+ table = rb_ary_dup((VALUE)data);
+ RARRAY_ASET(table, 0, rb_obj_id(dest));
+ st_insert(finalizer_table, dest, table);
+ FL_SET(dest, FL_FINALIZE);
+ }
+ else {
+ rb_bug("rb_gc_copy_finalizer: FL_FINALIZE set but not found in finalizer_table: %s", rb_obj_info(obj));
+ }
+ RB_GC_VM_UNLOCK(lev);
+}
+
+static VALUE
+get_final(long i, void *data)
+{
+ VALUE table = (VALUE)data;
+
+ return RARRAY_AREF(table, i + 1);
+}
+
+static unsigned int
+run_final(rb_objspace_t *objspace, VALUE zombie, unsigned int lev)
+{
+ if (RZOMBIE(zombie)->dfree) {
+ RZOMBIE(zombie)->dfree(RZOMBIE(zombie)->data);
+ }
+
+ st_data_t key = (st_data_t)zombie;
+ if (FL_TEST_RAW(zombie, FL_FINALIZE)) {
+ FL_UNSET(zombie, FL_FINALIZE);
+ st_data_t table;
+ if (st_delete(finalizer_table, &key, &table)) {
+ RB_GC_VM_UNLOCK(lev);
+ rb_gc_run_obj_finalizer(RARRAY_AREF(table, 0), RARRAY_LEN(table) - 1, get_final, (void *)table);
+ lev = RB_GC_VM_LOCK();
+ }
+ else {
+ rb_bug("FL_FINALIZE flag is set, but finalizers are not found");
+ }
+ }
+ else {
+ GC_ASSERT(!st_lookup(finalizer_table, key, NULL));
+ }
+ return lev;
+}
+
+static void
+finalize_list(rb_objspace_t *objspace, VALUE zombie)
+{
+ while (zombie) {
+ VALUE next_zombie;
+ struct heap_page *page;
+ rb_asan_unpoison_object(zombie, false);
+ next_zombie = RZOMBIE(zombie)->next;
+ page = GET_HEAP_PAGE(zombie);
+
+ unsigned int lev = RB_GC_VM_LOCK();
+
+ lev = run_final(objspace, zombie, lev);
+ {
+ GC_ASSERT(BUILTIN_TYPE(zombie) == T_ZOMBIE);
+ GC_ASSERT(page->heap->final_slots_count > 0);
+ GC_ASSERT(page->final_slots > 0);
+
+ page->heap->final_slots_count--;
+ page->final_slots--;
+ page->free_slots++;
+ RVALUE_AGE_SET_BITMAP(zombie, 0);
+ heap_page_add_freeobj(objspace, page, zombie);
+ page->heap->total_freed_objects++;
+ }
+ RB_GC_VM_UNLOCK(lev);
+
+ zombie = next_zombie;
+ }
+}
+
+static void
+finalize_deferred_heap_pages(rb_objspace_t *objspace)
+{
+ VALUE zombie;
+ while ((zombie = RUBY_ATOMIC_VALUE_EXCHANGE(heap_pages_deferred_final, 0)) != 0) {
+ finalize_list(objspace, zombie);
+ }
+}
+
+static void
+finalize_deferred(rb_objspace_t *objspace)
+{
+ rb_gc_set_pending_interrupt();
+ finalize_deferred_heap_pages(objspace);
+ rb_gc_unset_pending_interrupt();
+}
+
+static void
+gc_finalize_deferred(void *dmy)
+{
+ rb_objspace_t *objspace = dmy;
+ if (RUBY_ATOMIC_EXCHANGE(finalizing, 1)) return;
+
+ finalize_deferred(objspace);
+ RUBY_ATOMIC_SET(finalizing, 0);
+}
+
+static void
+gc_finalize_deferred_register(rb_objspace_t *objspace)
+{
+ /* will enqueue a call to gc_finalize_deferred */
+ rb_postponed_job_trigger(objspace->finalize_deferred_pjob);
+}
+
+static int pop_mark_stack(mark_stack_t *stack, VALUE *data);
+
+static void
+gc_abort(void *objspace_ptr)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ if (is_incremental_marking(objspace)) {
+ /* Remove all objects from the mark stack. */
+ VALUE obj;
+ while (pop_mark_stack(&objspace->mark_stack, &obj));
+
+ objspace->flags.during_incremental_marking = FALSE;
+ }
+
+ if (is_lazy_sweeping(objspace)) {
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ rb_heap_t *heap = &heaps[i];
+
+ heap->sweeping_page = NULL;
+ struct heap_page *page = NULL;
+
+ ccan_list_for_each(&heap->pages, page, page_node) {
+ page->flags.before_sweep = false;
+ }
+ }
+ }
+
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ rb_heap_t *heap = &heaps[i];
+ rgengc_mark_and_rememberset_clear(objspace, heap);
+ }
+
+ gc_mode_set(objspace, gc_mode_none);
+}
+
+void
+rb_gc_impl_shutdown_free_objects(void *objspace_ptr)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ for (size_t i = 0; i < rb_darray_size(objspace->heap_pages.sorted); i++) {
+ struct heap_page *page = rb_darray_get(objspace->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;
+ asan_unpoisoning_object(vp) {
+ if (RB_BUILTIN_TYPE(vp) != T_NONE) {
+ rb_gc_obj_free_vm_weak_references(vp);
+ if (rb_gc_obj_free(objspace, vp)) {
+ RBASIC(vp)->flags = 0;
+ }
+ }
+ }
+ }
+ }
+}
+
+static int
+rb_gc_impl_shutdown_call_finalizer_i(st_data_t key, st_data_t val, st_data_t _data)
+{
+ VALUE obj = (VALUE)key;
+ VALUE table = (VALUE)val;
+
+ GC_ASSERT(RB_FL_TEST(obj, FL_FINALIZE));
+ GC_ASSERT(RB_BUILTIN_TYPE(val) == T_ARRAY);
+
+ rb_gc_run_obj_finalizer(RARRAY_AREF(table, 0), RARRAY_LEN(table) - 1, get_final, (void *)table);
+
+ FL_UNSET(obj, FL_FINALIZE);
+
+ return ST_DELETE;
+}
+
+void
+rb_gc_impl_shutdown_call_finalizer(void *objspace_ptr)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+#if RGENGC_CHECK_MODE >= 2
+ gc_verify_internal_consistency(objspace);
+#endif
+
+ /* prohibit incremental GC */
+ objspace->flags.dont_incremental = 1;
+
+ if (RUBY_ATOMIC_EXCHANGE(finalizing, 1)) {
+ /* Abort incremental marking and lazy sweeping to speed up shutdown. */
+ gc_abort(objspace);
+ dont_gc_on();
+ return;
+ }
+
+ while (finalizer_table->num_entries) {
+ st_foreach(finalizer_table, rb_gc_impl_shutdown_call_finalizer_i, 0);
+ }
+
+ /* run finalizers */
+ finalize_deferred(objspace);
+ GC_ASSERT(heap_pages_deferred_final == 0);
+
+ /* Abort incremental marking and lazy sweeping to speed up shutdown. */
+ gc_abort(objspace);
+
+ /* prohibit GC because force T_DATA finalizers can break an object graph consistency */
+ dont_gc_on();
+
+ /* running data/file finalizers are part of garbage collection */
+ unsigned int lock_lev;
+ gc_enter(objspace, gc_enter_event_finalizer, &lock_lev);
+
+ /* run data/file object's finalizers */
+ for (size_t i = 0; i < rb_darray_size(objspace->heap_pages.sorted); i++) {
+ struct heap_page *page = rb_darray_get(objspace->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;
+ asan_unpoisoning_object(vp) {
+ if (rb_gc_shutdown_call_finalizer_p(vp)) {
+ rb_gc_obj_free_vm_weak_references(vp);
+ if (rb_gc_obj_free(objspace, vp)) {
+ RBASIC(vp)->flags = 0;
+ }
+ }
+ }
+ }
+ }
+
+ gc_exit(objspace, gc_enter_event_finalizer, &lock_lev);
+
+ finalize_deferred_heap_pages(objspace);
+
+ st_free_table(finalizer_table);
+ finalizer_table = 0;
+ RUBY_ATOMIC_SET(finalizing, 0);
+}
+
+void
+rb_gc_impl_each_object(void *objspace_ptr, void (*func)(VALUE obj, void *data), void *data)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ for (size_t i = 0; i < rb_darray_size(objspace->heap_pages.sorted); i++) {
+ struct heap_page *page = rb_darray_get(objspace->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 obj = (VALUE)p;
+
+ asan_unpoisoning_object(obj) {
+ func(obj, data);
+ }
+ }
+ }
+}
+
+/*
+ ------------------------ Garbage Collection ------------------------
+*/
+
+/* Sweeping */
+
+static size_t
+objspace_available_slots(rb_objspace_t *objspace)
+{
+ size_t total_slots = 0;
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ rb_heap_t *heap = &heaps[i];
+ total_slots += heap->total_slots;
+ }
+ return total_slots;
+}
+
+static size_t
+objspace_live_slots(rb_objspace_t *objspace)
+{
+ return total_allocated_objects(objspace) - total_freed_objects(objspace) - total_final_slots_count(objspace);
+}
+
+static size_t
+objspace_free_slots(rb_objspace_t *objspace)
+{
+ return objspace_available_slots(objspace) - objspace_live_slots(objspace) - total_final_slots_count(objspace);
+}
+
+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 src_slot_size, size_t slot_size);
+
+#if defined(_WIN32)
+enum {HEAP_PAGE_LOCK = PAGE_NOACCESS, HEAP_PAGE_UNLOCK = PAGE_READWRITE};
+
+static BOOL
+protect_page_body(struct heap_page_body *body, DWORD protect)
+{
+ DWORD old_protect;
+ return VirtualProtect(body, HEAP_PAGE_SIZE, protect, &old_protect) != 0;
+}
+#elif defined(__wasi__)
+// wasi-libc's mprotect emulation does not support PROT_NONE
+enum {HEAP_PAGE_LOCK, HEAP_PAGE_UNLOCK};
+#define protect_page_body(body, protect) 1
+#else
+enum {HEAP_PAGE_LOCK = PROT_NONE, HEAP_PAGE_UNLOCK = PROT_READ | PROT_WRITE};
+#define protect_page_body(body, protect) !mprotect((body), HEAP_PAGE_SIZE, (protect))
+#endif
+
+static void
+lock_page_body(rb_objspace_t *objspace, struct heap_page_body *body)
+{
+ if (!protect_page_body(body, HEAP_PAGE_LOCK)) {
+ 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 (!protect_page_body(body, HEAP_PAGE_UNLOCK)) {
+ 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 bool
+try_move(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *free_page, VALUE src)
+{
+ GC_ASSERT(gc_is_moveable_obj(objspace, src));
+
+ struct heap_page *src_page = GET_HEAP_PAGE(src);
+ if (!free_page) {
+ return false;
+ }
+
+ /* We should return true if either src is successfully moved, or src is
+ * unmoveable. A false return will cause the sweeping cursor to be
+ * incremented to the next page, and src will attempt to move again */
+ GC_ASSERT(RVALUE_MARKED(objspace, src));
+
+ asan_unlock_freelist(free_page);
+ VALUE dest = (VALUE)free_page->freelist;
+ asan_lock_freelist(free_page);
+ if (dest) {
+ rb_asan_unpoison_object(dest, false);
+ }
+ else {
+ /* if we can't get something from the freelist then the page must be
+ * full */
+ return false;
+ }
+ asan_unlock_freelist(free_page);
+ free_page->freelist = ((struct free_slot *)dest)->next;
+ asan_lock_freelist(free_page);
+
+ GC_ASSERT(RB_BUILTIN_TYPE(dest) == T_NONE);
+
+ if (src_page->slot_size > free_page->slot_size) {
+ objspace->rcompactor.moved_down_count_table[BUILTIN_TYPE(src)]++;
+ }
+ else if (free_page->slot_size > src_page->slot_size) {
+ objspace->rcompactor.moved_up_count_table[BUILTIN_TYPE(src)]++;
+ }
+ objspace->rcompactor.moved_count_table[BUILTIN_TYPE(src)]++;
+ objspace->rcompactor.total_moved++;
+
+ gc_move(objspace, src, dest, src_page->slot_size, free_page->slot_size);
+ gc_pin(objspace, src);
+ free_page->free_slots--;
+
+ return true;
+}
+
+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, cursor->body);
+ cursor = ccan_list_next(&heap->pages, cursor, page_node);
+ }
+}
+
+static void gc_update_references(rb_objspace_t *objspace);
+#if GC_CAN_COMPILE_COMPACTION
+static void invalidate_moved_page(rb_objspace_t *objspace, struct heap_page *page);
+#endif
+
+#if defined(__MINGW32__) || defined(_WIN32)
+# define GC_COMPACTION_SUPPORTED 1
+#else
+/* If not MinGW, Windows, or does not have mmap, we cannot use mprotect for
+ * the read barrier, so we must disable compaction. */
+# define GC_COMPACTION_SUPPORTED (GC_CAN_COMPILE_COMPACTION && HEAP_PAGE_ALLOC_USE_MMAP)
+#endif
+
+#if GC_CAN_COMPILE_COMPACTION
+static void
+read_barrier_handler(uintptr_t address)
+{
+ rb_objspace_t *objspace = (rb_objspace_t *)rb_gc_get_objspace();
+
+ struct heap_page_body *page_body = GET_PAGE_BODY(address);
+
+ /* If the page_body is NULL, then mprotect cannot handle it and will crash
+ * with "Cannot allocate memory". */
+ if (page_body == NULL) {
+ rb_bug("read_barrier_handler: segmentation fault at %p", (void *)address);
+ }
+
+ int lev = RB_GC_VM_LOCK();
+ {
+ unlock_page_body(objspace, page_body);
+
+ objspace->profile.read_barrier_faults++;
+
+ invalidate_moved_page(objspace, GET_HEAP_PAGE(address));
+ }
+ RB_GC_VM_UNLOCK(lev);
+}
+#endif
+
+#if !GC_CAN_COMPILE_COMPACTION
+static void
+uninstall_handlers(void)
+{
+ /* no-op */
+}
+
+static void
+install_handlers(void)
+{
+ /* no-op */
+}
+#elif 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;
+
+#ifdef HAVE_MACH_TASK_EXCEPTION_PORTS
+static exception_mask_t old_exception_masks[32];
+static mach_port_t old_exception_ports[32];
+static exception_behavior_t old_exception_behaviors[32];
+static thread_state_flavor_t old_exception_flavors[32];
+static mach_msg_type_number_t old_exception_count;
+
+static void
+disable_mach_bad_access_exc(void)
+{
+ old_exception_count = sizeof(old_exception_masks) / sizeof(old_exception_masks[0]);
+ task_swap_exception_ports(
+ mach_task_self(), EXC_MASK_BAD_ACCESS,
+ MACH_PORT_NULL, EXCEPTION_DEFAULT, 0,
+ old_exception_masks, &old_exception_count,
+ old_exception_ports, old_exception_behaviors, old_exception_flavors
+ );
+}
+
+static void
+restore_mach_bad_access_exc(void)
+{
+ for (mach_msg_type_number_t i = 0; i < old_exception_count; i++) {
+ task_set_exception_ports(
+ mach_task_self(),
+ old_exception_masks[i], old_exception_ports[i],
+ old_exception_behaviors[i], old_exception_flavors[i]
+ );
+ }
+}
+#endif
+
+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);
+#ifdef HAVE_MACH_TASK_EXCEPTION_PORTS
+ disable_mach_bad_access_exc();
+#endif
+ // run handler
+ read_barrier_handler((uintptr_t)info->si_addr);
+
+ // reset SEGV/BUS handlers
+#ifdef HAVE_MACH_TASK_EXCEPTION_PORTS
+ restore_mach_bad_access_exc();
+#endif
+ sigaction(SIGBUS, &prev_sigbus, NULL);
+ sigaction(SIGSEGV, &prev_sigsegv, NULL);
+ sigprocmask(SIG_SETMASK, &prev_set, NULL);
+}
+
+static void
+uninstall_handlers(void)
+{
+#ifdef HAVE_MACH_TASK_EXCEPTION_PORTS
+ restore_mach_bad_access_exc();
+#endif
+ 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);
+#ifdef HAVE_MACH_TASK_EXCEPTION_PORTS
+ disable_mach_bad_access_exc();
+#endif
+}
+#endif
+
+static void
+gc_compact_finish(rb_objspace_t *objspace)
+{
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ rb_heap_t *heap = &heaps[i];
+ gc_unprotect_pages(objspace, heap);
+ }
+
+ uninstall_handlers();
+
+ gc_update_references(objspace);
+ objspace->profile.compact_count++;
+
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ rb_heap_t *heap = &heaps[i];
+ heap->compact_cursor = NULL;
+ heap->free_pages = 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_sweep_plane(rb_objspace_t *objspace, rb_heap_t *heap, uintptr_t p, bits_t bitset, struct gc_sweep_context *ctx)
+{
+ struct heap_page *sweep_page = ctx->page;
+ short slot_size = sweep_page->slot_size;
+ short slot_bits = slot_size / BASE_SLOT_SIZE;
+ GC_ASSERT(slot_bits > 0);
+
+ do {
+ VALUE vp = (VALUE)p;
+ GC_ASSERT(vp % BASE_SLOT_SIZE == 0);
+
+ rb_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(objspace, vp)) rb_bug("page_sweep: %p - old while minor GC.", (void *)p);
+ if (RVALUE_REMEMBERED(objspace, vp)) rb_bug("page_sweep: %p - remembered.", (void *)p);
+ }
+#endif
+
+ if (RVALUE_WB_UNPROTECTED(objspace, vp)) CLEAR_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(vp), vp);
+
+#if RGENGC_CHECK_MODE
+#define CHECK(x) if (x(objspace, vp) != FALSE) rb_bug("obj_free: " #x "(%s) != FALSE", rb_obj_info(vp))
+ CHECK(RVALUE_WB_UNPROTECTED);
+ CHECK(RVALUE_MARKED);
+ CHECK(RVALUE_MARKING);
+ CHECK(RVALUE_UNCOLLECTIBLE);
+#undef CHECK
+#endif
+
+ rb_gc_event_hook(vp, RUBY_INTERNAL_EVENT_FREEOBJ);
+
+ rb_gc_obj_free_vm_weak_references(vp);
+ if (rb_gc_obj_free(objspace, vp)) {
+ // always add free slots back to the swept pages freelist,
+ // so that if we're compacting, we can re-use the slots
+ (void)VALGRIND_MAKE_MEM_UNDEFINED((void*)p, BASE_SLOT_SIZE);
+ RVALUE_AGE_SET_BITMAP(vp, 0);
+ heap_page_add_freeobj(objspace, sweep_page, vp);
+ gc_report(3, objspace, "page_sweep: %s is added to freelist\n", rb_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");
+ }
+ gc_report(3, objspace, "page_sweep: %s is added to freelist\n", rb_obj_info(vp));
+ ctx->empty_slots++;
+ RVALUE_AGE_SET_BITMAP(vp, 0);
+ heap_page_add_freeobj(objspace, sweep_page, vp);
+ break;
+ case T_ZOMBIE:
+ /* already counted */
+ break;
+ case T_NONE:
+ ctx->empty_slots++; /* already freed */
+ break;
+ }
+ }
+ p += slot_size;
+ bitset >>= slot_bits;
+ } while (bitset);
+}
+
+static inline void
+gc_sweep_page(rb_objspace_t *objspace, rb_heap_t *heap, struct gc_sweep_context *ctx)
+{
+ struct heap_page *sweep_page = ctx->page;
+ GC_ASSERT(sweep_page->heap == heap);
+
+ uintptr_t p;
+ bits_t *bits, bitset;
+
+ gc_report(2, objspace, "page_sweep: start.\n");
+
+#if RGENGC_CHECK_MODE
+ if (!objspace->flags.immediate_sweep) {
+ GC_ASSERT(sweep_page->flags.before_sweep == TRUE);
+ }
+#endif
+ sweep_page->flags.before_sweep = FALSE;
+ sweep_page->free_slots = 0;
+
+ p = (uintptr_t)sweep_page->start;
+ bits = sweep_page->mark_bits;
+
+ int page_rvalue_count = sweep_page->total_slots * (sweep_page->slot_size / BASE_SLOT_SIZE);
+ 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);
+ }
+
+ /* The last bitmap plane may not be used if the last plane does not
+ * have enough space for the slot_size. In that case, the last plane must
+ * be skipped since none of the bits will be set. */
+ int bitmap_plane_count = CEILDIV(NUM_IN_PAGE(p) + page_rvalue_count, BITS_BITLENGTH);
+ GC_ASSERT(bitmap_plane_count == HEAP_PAGE_BITMAP_LIMIT - 1 ||
+ bitmap_plane_count == HEAP_PAGE_BITMAP_LIMIT);
+
+ bits_t slot_mask = heap->slot_bits_mask;
+
+ // Skip out of range slots at the head of the page
+ bitset = ~bits[0];
+ bitset >>= NUM_IN_PAGE(p);
+ bitset &= slot_mask;
+ if (bitset) {
+ gc_sweep_plane(objspace, heap, p, bitset, ctx);
+ }
+ p += (BITS_BITLENGTH - NUM_IN_PAGE(p)) * BASE_SLOT_SIZE;
+
+ for (int i = 1; i < bitmap_plane_count; i++) {
+ bitset = ~bits[i];
+ bitset &= slot_mask;
+ if (bitset) {
+ gc_sweep_plane(objspace, heap, p, bitset, ctx);
+ }
+ p += BITS_BITLENGTH * BASE_SLOT_SIZE;
+ }
+
+ 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 += ctx->final_slots + ctx->freed_slots;
+ record->empty_objects += ctx->empty_slots;
+ }
+#endif
+ 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 += ctx->freed_slots + ctx->empty_slots;
+ sweep_page->heap->total_freed_objects += ctx->freed_slots;
+
+ if (heap_pages_deferred_final && !finalizing) {
+ gc_finalize_deferred_register(objspace);
+ }
+
+#if RGENGC_CHECK_MODE
+ short freelist_len = 0;
+ asan_unlock_freelist(sweep_page);
+ struct free_slot *ptr = sweep_page->freelist;
+ while (ptr) {
+ freelist_len++;
+ rb_asan_unpoison_object((VALUE)ptr, false);
+ struct free_slot *next = ptr->next;
+ rb_asan_poison_object((VALUE)ptr);
+ ptr = next;
+ }
+ asan_lock_freelist(sweep_page);
+ if (freelist_len != sweep_page->free_slots) {
+ rb_bug("inconsistent freelist length: expected %d but was %d", sweep_page->free_slots, freelist_len);
+ }
+#endif
+
+ gc_report(2, objspace, "page_sweep: end.\n");
+}
+
+static const char *
+gc_mode_name(enum gc_mode mode)
+{
+ switch (mode) {
+ case gc_mode_none: return "none";
+ case gc_mode_marking: return "marking";
+ case gc_mode_sweeping: return "sweeping";
+ case gc_mode_compacting: return "compacting";
+ default: rb_bug("gc_mode_name: unknown mode: %d", (int)mode);
+ }
+}
+
+static void
+gc_mode_transition(rb_objspace_t *objspace, enum gc_mode mode)
+{
+#if RGENGC_CHECK_MODE
+ enum gc_mode prev_mode = gc_mode(objspace);
+ switch (prev_mode) {
+ case gc_mode_none: GC_ASSERT(mode == gc_mode_marking); break;
+ case gc_mode_marking: GC_ASSERT(mode == gc_mode_sweeping); break;
+ case gc_mode_sweeping: GC_ASSERT(mode == gc_mode_none || mode == gc_mode_compacting); break;
+ case gc_mode_compacting: GC_ASSERT(mode == gc_mode_none); break;
+ }
+#endif
+ if (0) fprintf(stderr, "gc_mode_transition: %s->%s\n", gc_mode_name(gc_mode(objspace)), gc_mode_name(mode));
+ gc_mode_set(objspace, mode);
+}
+
+static void
+heap_page_freelist_append(struct heap_page *page, struct free_slot *freelist)
+{
+ if (freelist) {
+ asan_unlock_freelist(page);
+ if (page->freelist) {
+ struct free_slot *p = page->freelist;
+ rb_asan_unpoison_object((VALUE)p, false);
+ while (p->next) {
+ struct free_slot *prev = p;
+ p = p->next;
+ rb_asan_poison_object((VALUE)prev);
+ rb_asan_unpoison_object((VALUE)p, false);
+ }
+ p->next = freelist;
+ rb_asan_poison_object((VALUE)p);
+ }
+ else {
+ page->freelist = freelist;
+ }
+ asan_lock_freelist(page);
+ }
+}
+
+static void
+gc_sweep_start_heap(rb_objspace_t *objspace, rb_heap_t *heap)
+{
+ heap->sweeping_page = ccan_list_top(&heap->pages, struct heap_page, page_node);
+ heap->free_pages = NULL;
+ heap->pooled_pages = NULL;
+ if (!objspace->flags.immediate_sweep) {
+ struct heap_page *page = NULL;
+
+ ccan_list_for_each(&heap->pages, page, page_node) {
+ page->flags.before_sweep = TRUE;
+ }
+ }
+}
+
+#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 4
+__attribute__((noinline))
+#endif
+
+#if GC_CAN_COMPILE_COMPACTION
+static void gc_sort_heap_by_compare_func(rb_objspace_t *objspace, gc_compact_compare_func compare_func);
+static int compare_pinned_slots(const void *left, const void *right, void *d);
+#endif
+
+static void
+gc_ractor_newobj_cache_clear(void *c, void *data)
+{
+ rb_objspace_t *objspace = rb_gc_get_objspace();
+ rb_ractor_newobj_cache_t *newobj_cache = c;
+
+ newobj_cache->incremental_mark_step_allocated_slots = 0;
+
+ for (size_t heap_idx = 0; heap_idx < HEAP_COUNT; heap_idx++) {
+
+ rb_ractor_newobj_heap_cache_t *cache = &newobj_cache->heap_caches[heap_idx];
+
+ rb_heap_t *heap = &heaps[heap_idx];
+ RUBY_ATOMIC_SIZE_ADD(heap->total_allocated_objects, cache->allocated_objects_count);
+ cache->allocated_objects_count = 0;
+
+ struct heap_page *page = cache->using_page;
+ struct free_slot *freelist = cache->freelist;
+ RUBY_DEBUG_LOG("ractor using_page:%p freelist:%p", (void *)page, (void *)freelist);
+
+ heap_page_freelist_append(page, freelist);
+
+ cache->using_page = NULL;
+ cache->freelist = NULL;
+ }
+}
+
+static void
+gc_sweep_start(rb_objspace_t *objspace)
+{
+ gc_mode_transition(objspace, gc_mode_sweeping);
+ objspace->rincgc.pooled_slots = 0;
+
+#if GC_CAN_COMPILE_COMPACTION
+ if (objspace->flags.during_compacting) {
+ gc_sort_heap_by_compare_func(
+ objspace,
+ objspace->rcompactor.compare_func ? objspace->rcompactor.compare_func : compare_pinned_slots
+ );
+ }
+#endif
+
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ rb_heap_t *heap = &heaps[i];
+ gc_sweep_start_heap(objspace, heap);
+
+ /* We should call gc_sweep_finish_heap for size pools with no pages. */
+ if (heap->sweeping_page == NULL) {
+ GC_ASSERT(heap->total_pages == 0);
+ GC_ASSERT(heap->total_slots == 0);
+ gc_sweep_finish_heap(objspace, heap);
+ }
+ }
+
+ rb_gc_ractor_newobj_cache_foreach(gc_ractor_newobj_cache_clear, NULL);
+}
+
+static void
+gc_sweep_finish_heap(rb_objspace_t *objspace, rb_heap_t *heap)
+{
+ size_t total_slots = heap->total_slots;
+ size_t swept_slots = heap->freed_slots + heap->empty_slots;
+
+ size_t init_slots = gc_params.heap_init_slots[heap - heaps];
+ size_t min_free_slots = (size_t)(MAX(total_slots, init_slots) * gc_params.heap_free_slots_min_ratio);
+
+ if (swept_slots < min_free_slots &&
+ /* The heap is a growth heap if it freed more slots than had empty slots. */
+ ((heap->empty_slots == 0 && total_slots > 0) || heap->freed_slots > heap->empty_slots)) {
+ /* If we don't have enough slots and we have pages on the tomb heap, move
+ * pages from the tomb heap to the eden heap. This may prevent page
+ * creation thrashing (frequently allocating and deallocting pages) and
+ * GC thrashing (running GC more frequently than required). */
+ struct heap_page *resurrected_page;
+ while (swept_slots < min_free_slots &&
+ (resurrected_page = heap_page_resurrect(objspace))) {
+ heap_add_page(objspace, heap, resurrected_page);
+ heap_add_freepage(heap, resurrected_page);
+
+ swept_slots += resurrected_page->free_slots;
+ }
+
+ if (swept_slots < min_free_slots) {
+ /* Grow this heap if we are in a major GC or if we haven't run at least
+ * RVALUE_OLD_AGE minor GC since the last major GC. */
+ if (is_full_marking(objspace) ||
+ objspace->profile.count - objspace->rgengc.last_major_gc < RVALUE_OLD_AGE) {
+ if (objspace->heap_pages.allocatable_slots < min_free_slots) {
+ heap_allocatable_slots_expand(objspace, heap, swept_slots, heap->total_slots);
+ }
+ }
+ else if (objspace->heap_pages.allocatable_slots < (min_free_slots - swept_slots)) {
+ gc_needs_major_flags |= GPR_FLAG_MAJOR_BY_NOFREE;
+ heap->force_major_gc_count++;
+ }
+ }
+ }
+}
+
+static void
+gc_sweep_finish(rb_objspace_t *objspace)
+{
+ gc_report(1, objspace, "gc_sweep_finish\n");
+
+ gc_prof_set_heap_info(objspace);
+ heap_pages_free_unused_pages(objspace);
+
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ rb_heap_t *heap = &heaps[i];
+
+ heap->freed_slots = 0;
+ heap->empty_slots = 0;
+
+ if (!will_be_incremental_marking(objspace)) {
+ struct heap_page *end_page = heap->free_pages;
+ if (end_page) {
+ while (end_page->free_next) end_page = end_page->free_next;
+ end_page->free_next = heap->pooled_pages;
+ }
+ else {
+ heap->free_pages = heap->pooled_pages;
+ }
+ heap->pooled_pages = NULL;
+ objspace->rincgc.pooled_slots = 0;
+ }
+ }
+
+ rb_gc_event_hook(0, RUBY_INTERNAL_EVENT_GC_END_SWEEP);
+ gc_mode_transition(objspace, gc_mode_none);
+
+#if RGENGC_CHECK_MODE >= 2
+ gc_verify_internal_consistency(objspace);
+#endif
+}
+
+static int
+gc_sweep_step(rb_objspace_t *objspace, rb_heap_t *heap)
+{
+ struct heap_page *sweep_page = heap->sweeping_page;
+ int swept_slots = 0;
+ int pooled_slots = 0;
+
+ if (sweep_page == NULL) return FALSE;
+
+#if GC_ENABLE_LAZY_SWEEP
+ gc_prof_sweep_timer_start(objspace);
+#endif
+
+ do {
+ 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, heap, &ctx);
+ int free_slots = ctx.freed_slots + ctx.empty_slots;
+
+ heap->sweeping_page = ccan_list_next(&heap->pages, sweep_page, page_node);
+
+ if (free_slots == sweep_page->total_slots) {
+ /* There are no living objects, so move this page to the global empty pages. */
+ heap_unlink_page(objspace, heap, sweep_page);
+
+ sweep_page->start = 0;
+ sweep_page->total_slots = 0;
+ sweep_page->slot_size = 0;
+ sweep_page->heap = NULL;
+ sweep_page->free_slots = 0;
+
+ asan_unlock_freelist(sweep_page);
+ sweep_page->freelist = NULL;
+ asan_lock_freelist(sweep_page);
+
+ asan_poison_memory_region(sweep_page->body, HEAP_PAGE_SIZE);
+
+ objspace->empty_pages_count++;
+ sweep_page->free_next = objspace->empty_pages;
+ objspace->empty_pages = sweep_page;
+ }
+ else if (free_slots > 0) {
+ heap->freed_slots += ctx.freed_slots;
+ heap->empty_slots += ctx.empty_slots;
+
+ if (pooled_slots < GC_INCREMENTAL_SWEEP_POOL_SLOT_COUNT) {
+ heap_add_poolpage(objspace, heap, sweep_page);
+ pooled_slots += free_slots;
+ }
+ else {
+ heap_add_freepage(heap, sweep_page);
+ swept_slots += free_slots;
+ if (swept_slots > GC_INCREMENTAL_SWEEP_SLOT_COUNT) {
+ break;
+ }
+ }
+ }
+ else {
+ sweep_page->free_next = NULL;
+ }
+ } while ((sweep_page = heap->sweeping_page));
+
+ if (!heap->sweeping_page) {
+ gc_sweep_finish_heap(objspace, heap);
+
+ if (!has_sweeping_pages(objspace)) {
+ gc_sweep_finish(objspace);
+ }
+ }
+
+#if GC_ENABLE_LAZY_SWEEP
+ gc_prof_sweep_timer_stop(objspace);
+#endif
+
+ return heap->free_pages != NULL;
+}
+
+static void
+gc_sweep_rest(rb_objspace_t *objspace)
+{
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ rb_heap_t *heap = &heaps[i];
+
+ while (heap->sweeping_page) {
+ gc_sweep_step(objspace, heap);
+ }
+ }
+}
+
+static void
+gc_sweep_continue(rb_objspace_t *objspace, rb_heap_t *sweep_heap)
+{
+ GC_ASSERT(dont_gc_val() == FALSE || objspace->profile.latest_gc_info & GPR_FLAG_METHOD);
+ if (!GC_ENABLE_LAZY_SWEEP) return;
+
+ gc_sweeping_enter(objspace);
+
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ rb_heap_t *heap = &heaps[i];
+ if (gc_sweep_step(objspace, heap)) {
+ GC_ASSERT(heap->free_pages != NULL);
+ }
+ else if (heap == sweep_heap) {
+ if (objspace->empty_pages_count > 0 || objspace->heap_pages.allocatable_slots > 0) {
+ /* [Bug #21548]
+ *
+ * If this heap is the heap we want to sweep, but we weren't able
+ * to free any slots, but we also either have empty pages or could
+ * allocate new pages, then we want to preemptively claim a page
+ * because it's possible that sweeping another heap will call
+ * gc_sweep_finish_heap, which may use up all of the
+ * empty/allocatable pages. If other heaps are not finished sweeping
+ * then we do not finish this GC and we will end up triggering a new
+ * GC cycle during this GC phase. */
+ heap_page_allocate_and_initialize(objspace, heap);
+
+ GC_ASSERT(heap->free_pages != NULL);
+ }
+ else {
+ /* Not allowed to create a new page so finish sweeping. */
+ gc_sweep_rest(objspace);
+ GC_ASSERT(gc_mode(objspace) == gc_mode_none);
+ break;
+ }
+ }
+ }
+
+ gc_sweeping_exit(objspace);
+}
+
+VALUE
+rb_gc_impl_location(void *objspace_ptr, VALUE value)
+{
+ VALUE destination;
+
+ asan_unpoisoning_object(value) {
+ if (BUILTIN_TYPE(value) == T_MOVED) {
+ destination = (VALUE)RMOVED(value)->destination;
+ GC_ASSERT(BUILTIN_TYPE(destination) != T_NONE);
+ }
+ else {
+ destination = value;
+ }
+ }
+
+ return destination;
+}
+
+#if GC_CAN_COMPILE_COMPACTION
+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(RVALUE_PINNED(objspace, forwarding_object));
+ GC_ASSERT(!RVALUE_MARKED(objspace, forwarding_object));
+
+ CLEAR_IN_BITMAP(GET_HEAP_PINNED_BITS(forwarding_object), forwarding_object);
+
+ object = rb_gc_impl_location(objspace, forwarding_object);
+
+ uint32_t original_shape_id = 0;
+ if (RB_TYPE_P(object, T_OBJECT)) {
+ original_shape_id = RMOVED(forwarding_object)->original_shape_id;
+ }
+
+ gc_move(objspace, object, forwarding_object, GET_HEAP_PAGE(object)->slot_size, page->slot_size);
+ /* forwarding_object is now our actual object, and "object"
+ * is the free slot for the original page */
+
+ if (original_shape_id) {
+ rb_gc_set_shape(forwarding_object, original_shape_id);
+ }
+
+ struct heap_page *orig_page = GET_HEAP_PAGE(object);
+ orig_page->free_slots++;
+ RVALUE_AGE_SET_BITMAP(object, 0);
+ heap_page_add_freeobj(objspace, orig_page, object);
+
+ GC_ASSERT(RVALUE_MARKED(objspace, forwarding_object));
+ GC_ASSERT(BUILTIN_TYPE(forwarding_object) != T_MOVED);
+ GC_ASSERT(BUILTIN_TYPE(forwarding_object) != T_NONE);
+ }
+ }
+ p += BASE_SLOT_SIZE;
+ 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;
+
+ mark_bits = page->mark_bits;
+ pin_bits = page->pinned_bits;
+
+ uintptr_t 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, p, bitset);
+ p += (BITS_BITLENGTH - NUM_IN_PAGE(p)) * BASE_SLOT_SIZE;
+
+ 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, p, bitset);
+ p += BITS_BITLENGTH * BASE_SLOT_SIZE;
+ }
+}
+#endif
+
+static void
+gc_compact_start(rb_objspace_t *objspace)
+{
+ struct heap_page *page = NULL;
+ gc_mode_transition(objspace, gc_mode_compacting);
+
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ rb_heap_t *heap = &heaps[i];
+ ccan_list_for_each(&heap->pages, page, page_node) {
+ page->flags.before_sweep = TRUE;
+ }
+
+ heap->compact_cursor = ccan_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));
+ memset(objspace->rcompactor.moved_up_count_table, 0, T_MASK * sizeof(size_t));
+ memset(objspace->rcompactor.moved_down_count_table, 0, T_MASK * sizeof(size_t));
+
+ /* Set up read barrier for pages containing MOVED objects */
+ install_handlers();
+}
+
+static void gc_sweep_compact(rb_objspace_t *objspace);
+
+static void
+gc_sweep(rb_objspace_t *objspace)
+{
+ gc_sweeping_enter(objspace);
+
+ const unsigned int immediate_sweep = objspace->flags.immediate_sweep;
+
+ gc_report(1, objspace, "gc_sweep: immediate: %d\n", immediate_sweep);
+
+ gc_sweep_start(objspace);
+ if (objspace->flags.during_compacting) {
+ gc_sweep_compact(objspace);
+ }
+
+ if (immediate_sweep) {
+#if !GC_ENABLE_LAZY_SWEEP
+ gc_prof_sweep_timer_start(objspace);
+#endif
+ gc_sweep_rest(objspace);
+#if !GC_ENABLE_LAZY_SWEEP
+ gc_prof_sweep_timer_stop(objspace);
+#endif
+ }
+ else {
+
+ /* Sweep every size pool. */
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ rb_heap_t *heap = &heaps[i];
+ gc_sweep_step(objspace, heap);
+ }
+ }
+
+ gc_sweeping_exit(objspace);
+}
+
+/* Marking - Marking stack */
+
+static stack_chunk_t *
+stack_chunk_alloc(void)
+{
+ stack_chunk_t *res;
+
+ res = malloc(sizeof(stack_chunk_t));
+ if (!res)
+ rb_memerror();
+
+ return res;
+}
+
+static inline int
+is_mark_stack_empty(mark_stack_t *stack)
+{
+ return stack->chunk == NULL;
+}
+
+static size_t
+mark_stack_size(mark_stack_t *stack)
+{
+ size_t size = stack->index;
+ stack_chunk_t *chunk = stack->chunk ? stack->chunk->next : NULL;
+
+ while (chunk) {
+ size += stack->limit;
+ chunk = chunk->next;
+ }
+ return size;
+}
+
+static void
+add_stack_chunk_cache(mark_stack_t *stack, stack_chunk_t *chunk)
+{
+ chunk->next = stack->cache;
+ stack->cache = chunk;
+ stack->cache_size++;
+}
+
+static void
+shrink_stack_chunk_cache(mark_stack_t *stack)
+{
+ stack_chunk_t *chunk;
+
+ if (stack->unused_cache_size > (stack->cache_size/2)) {
+ chunk = stack->cache;
+ stack->cache = stack->cache->next;
+ stack->cache_size--;
+ free(chunk);
+ }
+ stack->unused_cache_size = stack->cache_size;
+}
+
+static void
+push_mark_stack_chunk(mark_stack_t *stack)
+{
+ stack_chunk_t *next;
+
+ GC_ASSERT(stack->index == stack->limit);
+
+ if (stack->cache_size > 0) {
+ next = stack->cache;
+ stack->cache = stack->cache->next;
+ stack->cache_size--;
+ if (stack->unused_cache_size > stack->cache_size)
+ stack->unused_cache_size = stack->cache_size;
+ }
+ else {
+ next = stack_chunk_alloc();
+ }
+ next->next = stack->chunk;
+ stack->chunk = next;
+ stack->index = 0;
+}
+
+static void
+pop_mark_stack_chunk(mark_stack_t *stack)
+{
+ stack_chunk_t *prev;
+
+ prev = stack->chunk->next;
+ GC_ASSERT(stack->index == 0);
+ add_stack_chunk_cache(stack, stack->chunk);
+ stack->chunk = prev;
+ stack->index = stack->limit;
+}
+
+static void
+mark_stack_chunk_list_free(stack_chunk_t *chunk)
+{
+ stack_chunk_t *next = NULL;
+
+ while (chunk != NULL) {
+ next = chunk->next;
+ free(chunk);
+ chunk = next;
+ }
+}
+
+static void
+free_stack_chunks(mark_stack_t *stack)
+{
+ mark_stack_chunk_list_free(stack->chunk);
+}
+
+static void
+mark_stack_free_cache(mark_stack_t *stack)
+{
+ mark_stack_chunk_list_free(stack->cache);
+ stack->cache_size = 0;
+ stack->unused_cache_size = 0;
+}
+
+static void
+push_mark_stack(mark_stack_t *stack, VALUE obj)
+{
+ 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++] = obj;
+ 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:
+ rb_bug("push_mark_stack: unexpected T_NODE object");
+ break;
+ }
+
+ rb_bug("rb_gc_mark(): unknown data type 0x%x(%p) %s",
+ BUILTIN_TYPE(obj), (void *)obj,
+ is_pointer_to_heap((rb_objspace_t *)rb_gc_get_objspace(), (void *)obj) ? "corrupted object" : "non object");
+}
+
+static int
+pop_mark_stack(mark_stack_t *stack, VALUE *data)
+{
+ if (is_mark_stack_empty(stack)) {
+ return FALSE;
+ }
+ if (stack->index == 1) {
+ *data = stack->chunk->data[--stack->index];
+ pop_mark_stack_chunk(stack);
+ }
+ else {
+ *data = stack->chunk->data[--stack->index];
+ }
+ return TRUE;
+}
+
+static void
+init_mark_stack(mark_stack_t *stack)
+{
+ int i;
+
+ MEMZERO(stack, mark_stack_t, 1);
+ stack->index = stack->limit = STACK_CHUNK_SIZE;
+
+ for (i=0; i < 4; i++) {
+ add_stack_chunk_cache(stack, stack_chunk_alloc());
+ }
+ stack->unused_cache_size = stack->cache_size;
+}
+
+/* Marking */
+
+static void
+rgengc_check_relation(rb_objspace_t *objspace, VALUE obj)
+{
+ if (objspace->rgengc.parent_object_old_p) {
+ if (RVALUE_WB_UNPROTECTED(objspace, obj) || !RVALUE_OLD_P(objspace, obj)) {
+ rgengc_remember(objspace, objspace->rgengc.parent_object);
+ }
+ }
+}
+
+static inline int
+gc_mark_set(rb_objspace_t *objspace, VALUE obj)
+{
+ if (RVALUE_MARKED(objspace, obj)) return 0;
+ MARK_IN_BITMAP(GET_HEAP_MARK_BITS(obj), obj);
+ return 1;
+}
+
+static void
+gc_aging(rb_objspace_t *objspace, VALUE obj)
+{
+ /* Disable aging if Major GC's are disabled. This will prevent longish lived
+ * objects filling up the heap at the expense of marking many more objects.
+ *
+ * We should always pre-warm our process when disabling majors, by running
+ * GC manually several times so that most objects likely to become oldgen
+ * are already oldgen.
+ */
+ if(!gc_config_full_mark_val)
+ return;
+
+ struct heap_page *page = GET_HEAP_PAGE(obj);
+
+ GC_ASSERT(RVALUE_MARKING(objspace, obj) == FALSE);
+ check_rvalue_consistency(objspace, obj);
+
+ if (!RVALUE_PAGE_WB_UNPROTECTED(page, obj)) {
+ if (!RVALUE_OLD_P(objspace, obj)) {
+ gc_report(3, objspace, "gc_aging: YOUNG: %s\n", rb_obj_info(obj));
+ RVALUE_AGE_INC(objspace, obj);
+ }
+ else if (is_full_marking(objspace)) {
+ GC_ASSERT(RVALUE_PAGE_UNCOLLECTIBLE(page, obj) == FALSE);
+ RVALUE_PAGE_OLD_UNCOLLECTIBLE_SET(objspace, page, obj);
+ }
+ }
+ check_rvalue_consistency(objspace, obj);
+
+ objspace->marked_slots++;
+}
+
+static void
+gc_grey(rb_objspace_t *objspace, VALUE obj)
+{
+#if RGENGC_CHECK_MODE
+ if (RVALUE_MARKED(objspace, obj) == FALSE) rb_bug("gc_grey: %s is not marked.", rb_obj_info(obj));
+ if (RVALUE_MARKING(objspace, obj) == TRUE) rb_bug("gc_grey: %s is marking/remembered.", rb_obj_info(obj));
+#endif
+
+ if (is_incremental_marking(objspace)) {
+ MARK_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), obj);
+ }
+
+ if (RB_FL_TEST_RAW(obj, RUBY_FL_WEAK_REFERENCE)) {
+ rb_darray_append_without_gc(&objspace->weak_references, obj);
+ }
+
+ push_mark_stack(&objspace->mark_stack, obj);
+}
+
+static inline void
+gc_mark_check_t_none(rb_objspace_t *objspace, VALUE obj)
+{
+ if (RB_UNLIKELY(BUILTIN_TYPE(obj) == T_NONE)) {
+ enum {info_size = 256};
+ char obj_info_buf[info_size];
+ rb_raw_obj_info(obj_info_buf, info_size, obj);
+
+ char parent_obj_info_buf[info_size];
+ rb_raw_obj_info(parent_obj_info_buf, info_size, objspace->rgengc.parent_object);
+
+ rb_bug("try to mark T_NONE object (obj: %s, parent: %s)", obj_info_buf, parent_obj_info_buf);
+ }
+}
+
+static void
+gc_mark(rb_objspace_t *objspace, VALUE obj)
+{
+ GC_ASSERT(during_gc);
+ GC_ASSERT(!objspace->flags.during_reference_updating);
+
+ rgengc_check_relation(objspace, obj);
+ if (!gc_mark_set(objspace, obj)) return; /* already marked */
+
+ if (0) { // for debug GC marking miss
+ 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));
+ }
+
+ gc_mark_check_t_none(objspace, obj);
+
+ gc_aging(objspace, obj);
+ gc_grey(objspace, obj);
+}
+
+static inline void
+gc_pin(rb_objspace_t *objspace, VALUE obj)
+{
+ GC_ASSERT(!SPECIAL_CONST_P(obj));
+ if (RB_UNLIKELY(objspace->flags.during_compacting)) {
+ if (RB_LIKELY(during_gc)) {
+ if (!RVALUE_PINNED(objspace, obj)) {
+ GC_ASSERT(GET_HEAP_PAGE(obj)->pinned_slots <= GET_HEAP_PAGE(obj)->total_slots);
+ GET_HEAP_PAGE(obj)->pinned_slots++;
+ MARK_IN_BITMAP(GET_HEAP_PINNED_BITS(obj), obj);
+ }
+ }
+ }
+}
+
+static inline void
+gc_mark_and_pin(rb_objspace_t *objspace, VALUE obj)
+{
+ gc_pin(objspace, obj);
+ gc_mark(objspace, obj);
+}
+
+void
+rb_gc_impl_mark_and_move(void *objspace_ptr, VALUE *ptr)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ if (RB_UNLIKELY(objspace->flags.during_reference_updating)) {
+ GC_ASSERT(objspace->flags.during_compacting);
+ GC_ASSERT(during_gc);
+
+ VALUE destination = rb_gc_impl_location(objspace, *ptr);
+ if (destination != *ptr) {
+ *ptr = destination;
+ }
+ }
+ else {
+ gc_mark(objspace, *ptr);
+ }
+}
+
+void
+rb_gc_impl_mark(void *objspace_ptr, VALUE obj)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ gc_mark(objspace, obj);
+}
+
+void
+rb_gc_impl_mark_and_pin(void *objspace_ptr, VALUE obj)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ gc_mark_and_pin(objspace, obj);
+}
+
+void
+rb_gc_impl_mark_maybe(void *objspace_ptr, VALUE obj)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ (void)VALGRIND_MAKE_MEM_DEFINED(&obj, sizeof(obj));
+
+ if (is_pointer_to_heap(objspace, (void *)obj)) {
+ asan_unpoisoning_object(obj) {
+ /* Garbage can live on the stack, so do not mark or pin */
+ switch (BUILTIN_TYPE(obj)) {
+ case T_ZOMBIE:
+ case T_NONE:
+ break;
+ default:
+ gc_mark_and_pin(objspace, obj);
+ break;
+ }
+ }
+ }
+}
+
+static int
+pin_value(st_data_t key, st_data_t value, st_data_t data)
+{
+ rb_gc_impl_mark_and_pin((void *)data, (VALUE)value);
+
+ return ST_CONTINUE;
+}
+
+static inline void
+gc_mark_set_parent_raw(rb_objspace_t *objspace, VALUE obj, bool old_p)
+{
+ asan_unpoison_memory_region(&objspace->rgengc.parent_object, sizeof(objspace->rgengc.parent_object), false);
+ asan_unpoison_memory_region(&objspace->rgengc.parent_object_old_p, sizeof(objspace->rgengc.parent_object_old_p), false);
+ objspace->rgengc.parent_object = obj;
+ objspace->rgengc.parent_object_old_p = old_p;
+}
+
+static inline void
+gc_mark_set_parent(rb_objspace_t *objspace, VALUE obj)
+{
+ gc_mark_set_parent_raw(objspace, obj, RVALUE_OLD_P(objspace, obj));
+}
+
+static inline void
+gc_mark_set_parent_invalid(rb_objspace_t *objspace)
+{
+ asan_poison_memory_region(&objspace->rgengc.parent_object, sizeof(objspace->rgengc.parent_object));
+ asan_poison_memory_region(&objspace->rgengc.parent_object_old_p, sizeof(objspace->rgengc.parent_object_old_p));
+}
+
+static void
+mark_roots(rb_objspace_t *objspace, const char **categoryp)
+{
+#define MARK_CHECKPOINT(category) do { \
+ if (categoryp) *categoryp = category; \
+} while (0)
+
+ MARK_CHECKPOINT("objspace");
+ gc_mark_set_parent_raw(objspace, Qundef, false);
+
+ if (finalizer_table != NULL) {
+ st_foreach(finalizer_table, pin_value, (st_data_t)objspace);
+ }
+
+ if (stress_to_class) rb_gc_mark(stress_to_class);
+
+ rb_gc_save_machine_context();
+ rb_gc_mark_roots(objspace, categoryp);
+ gc_mark_set_parent_invalid(objspace);
+}
+
+static void
+gc_mark_children(rb_objspace_t *objspace, VALUE obj)
+{
+ gc_mark_set_parent(objspace, obj);
+ rb_gc_mark_children(objspace, obj);
+ gc_mark_set_parent_invalid(objspace);
+}
+
+/**
+ * incremental: 0 -> not incremental (do all)
+ * incremental: n -> mark at most `n' objects
+ */
+static inline int
+gc_mark_stacked_objects(rb_objspace_t *objspace, int incremental, size_t count)
+{
+ mark_stack_t *mstack = &objspace->mark_stack;
+ VALUE obj;
+ size_t marked_slots_at_the_beginning = objspace->marked_slots;
+ size_t popped_count = 0;
+
+ while (pop_mark_stack(mstack, &obj)) {
+ if (obj == Qundef) continue; /* skip */
+
+ if (RGENGC_CHECK_MODE && !RVALUE_MARKED(objspace, obj)) {
+ rb_bug("gc_mark_stacked_objects: %s is not marked.", rb_obj_info(obj));
+ }
+ gc_mark_children(objspace, obj);
+
+ if (incremental) {
+ if (RGENGC_CHECK_MODE && !RVALUE_MARKING(objspace, obj)) {
+ rb_bug("gc_mark_stacked_objects: incremental, but marking bit is 0");
+ }
+ CLEAR_IN_BITMAP(GET_HEAP_MARKING_BITS(obj), obj);
+ popped_count++;
+
+ if (popped_count + (objspace->marked_slots - marked_slots_at_the_beginning) > count) {
+ break;
+ }
+ }
+ else {
+ /* just ignore marking bits */
+ }
+ }
+
+ if (RGENGC_CHECK_MODE >= 3) gc_verify_internal_consistency(objspace);
+
+ if (is_mark_stack_empty(mstack)) {
+ shrink_stack_chunk_cache(mstack);
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
+static int
+gc_mark_stacked_objects_incremental(rb_objspace_t *objspace, size_t count)
+{
+ return gc_mark_stacked_objects(objspace, TRUE, count);
+}
+
+static int
+gc_mark_stacked_objects_all(rb_objspace_t *objspace)
+{
+ return gc_mark_stacked_objects(objspace, FALSE, 0);
+}
+
+#if RGENGC_CHECK_MODE >= 4
+
+#define MAKE_ROOTSIG(obj) (((VALUE)(obj) << 1) | 0x01)
+#define IS_ROOTSIG(obj) ((VALUE)(obj) & 0x01)
+#define GET_ROOTSIG(obj) ((const char *)((VALUE)(obj) >> 1))
+
+struct reflist {
+ VALUE *list;
+ int pos;
+ int size;
+};
+
+static struct reflist *
+reflist_create(VALUE obj)
+{
+ struct reflist *refs = xmalloc(sizeof(struct reflist));
+ refs->size = 1;
+ refs->list = ALLOC_N(VALUE, refs->size);
+ refs->list[0] = obj;
+ refs->pos = 1;
+ return refs;
+}
+
+static void
+reflist_destruct(struct reflist *refs)
+{
+ xfree(refs->list);
+ xfree(refs);
+}
+
+static void
+reflist_add(struct reflist *refs, VALUE obj)
+{
+ if (refs->pos == refs->size) {
+ refs->size *= 2;
+ SIZED_REALLOC_N(refs->list, VALUE, refs->size, refs->size/2);
+ }
+
+ refs->list[refs->pos++] = obj;
+}
+
+static void
+reflist_dump(struct reflist *refs)
+{
+ int i;
+ for (i=0; i<refs->pos; i++) {
+ VALUE obj = refs->list[i];
+ if (IS_ROOTSIG(obj)) { /* root */
+ fprintf(stderr, "<root@%s>", GET_ROOTSIG(obj));
+ }
+ else {
+ fprintf(stderr, "<%s>", rb_obj_info(obj));
+ }
+ if (i+1 < refs->pos) fprintf(stderr, ", ");
+ }
+}
+
+static int
+reflist_referred_from_machine_context(struct reflist *refs)
+{
+ int i;
+ for (i=0; i<refs->pos; i++) {
+ VALUE obj = refs->list[i];
+ if (IS_ROOTSIG(obj) && strcmp(GET_ROOTSIG(obj), "machine_context") == 0) return 1;
+ }
+ return 0;
+}
+
+struct allrefs {
+ rb_objspace_t *objspace;
+ /* a -> obj1
+ * b -> obj1
+ * c -> obj1
+ * c -> obj2
+ * d -> obj3
+ * #=> {obj1 => [a, b, c], obj2 => [c, d]}
+ */
+ struct st_table *references;
+ const char *category;
+ VALUE root_obj;
+ mark_stack_t mark_stack;
+};
+
+static int
+allrefs_add(struct allrefs *data, VALUE obj)
+{
+ struct reflist *refs;
+ st_data_t r;
+
+ if (st_lookup(data->references, obj, &r)) {
+ refs = (struct reflist *)r;
+ reflist_add(refs, data->root_obj);
+ return 0;
+ }
+ else {
+ refs = reflist_create(data->root_obj);
+ st_insert(data->references, obj, (st_data_t)refs);
+ return 1;
+ }
+}
+
+static void
+allrefs_i(VALUE obj, void *ptr)
+{
+ struct allrefs *data = (struct allrefs *)ptr;
+
+ if (allrefs_add(data, obj)) {
+ push_mark_stack(&data->mark_stack, obj);
+ }
+}
+
+static void
+allrefs_roots_i(VALUE obj, void *ptr)
+{
+ struct allrefs *data = (struct allrefs *)ptr;
+ if (strlen(data->category) == 0) rb_bug("!!!");
+ data->root_obj = MAKE_ROOTSIG(data->category);
+
+ if (allrefs_add(data, obj)) {
+ 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_VM()->gc.mark_func_data; \
+ GET_VM()->gc.mark_func_data = (v);
+
+#define POP_MARK_FUNC_DATA() GET_VM()->gc.mark_func_data = prev_mark_func_data;} while (0)
+
+static st_table *
+objspace_allrefs(rb_objspace_t *objspace)
+{
+ struct allrefs data;
+ struct gc_mark_func_data_struct mfd;
+ VALUE obj;
+ int prev_dont_gc = dont_gc_val();
+ dont_gc_on();
+
+ data.objspace = objspace;
+ data.references = st_init_numtable();
+ init_mark_stack(&data.mark_stack);
+
+ mfd.mark_func = allrefs_roots_i;
+ mfd.data = &data;
+
+ /* traverse root objects */
+ PUSH_MARK_FUNC_DATA(&mfd);
+ GET_VM()->gc.mark_func_data = &mfd;
+ mark_roots(objspace, &data.category);
+ POP_MARK_FUNC_DATA();
+
+ /* traverse rest objects reachable from root objects */
+ while (pop_mark_stack(&data.mark_stack, &obj)) {
+ rb_objspace_reachable_objects_from(data.root_obj = obj, allrefs_i, &data);
+ }
+ free_stack_chunks(&data.mark_stack);
+
+ dont_gc_set(prev_dont_gc);
+ return data.references;
+}
+
+static int
+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);
+ return ST_CONTINUE;
+}
+
+static void
+objspace_allrefs_destruct(struct st_table *refs)
+{
+ st_foreach(refs, objspace_allrefs_destruct_i, 0);
+ st_free_table(refs);
+}
+
+#if RGENGC_CHECK_MODE >= 5
+static int
+allrefs_dump_i(st_data_t k, st_data_t v, st_data_t ptr)
+{
+ VALUE obj = (VALUE)k;
+ struct reflist *refs = (struct reflist *)v;
+ fprintf(stderr, "[allrefs_dump_i] %s <- ", rb_obj_info(obj));
+ reflist_dump(refs);
+ fprintf(stderr, "\n");
+ return ST_CONTINUE;
+}
+
+static void
+allrefs_dump(rb_objspace_t *objspace)
+{
+ 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, st_data_t ptr)
+{
+ VALUE obj = k;
+ struct reflist *refs = (struct reflist *)v;
+ rb_objspace_t *objspace = (rb_objspace_t *)ptr;
+
+ /* object should be marked or oldgen */
+ if (!RVALUE_MARKED(objspace, obj)) {
+ fprintf(stderr, "gc_check_after_marks_i: %s is not marked and not oldgen.\n", rb_obj_info(obj));
+ fprintf(stderr, "gc_check_after_marks_i: %p is referred from ", (void *)obj);
+ reflist_dump(refs);
+
+ if (reflist_referred_from_machine_context(refs)) {
+ fprintf(stderr, " (marked from machine stack).\n");
+ /* marked from machine context can be false positive */
+ }
+ else {
+ objspace->rgengc.error_count++;
+ fprintf(stderr, "\n");
+ }
+ }
+ return ST_CONTINUE;
+}
+
+static void
+gc_marks_check(rb_objspace_t *objspace, st_foreach_callback_func *checker_func, const char *checker_name)
+{
+ size_t saved_malloc_increase = objspace->malloc_params.increase;
+#if RGENGC_ESTIMATE_OLDMALLOC
+ size_t saved_oldmalloc_increase = objspace->malloc_counters.oldmalloc_increase;
+#endif
+ VALUE already_disabled = rb_objspace_gc_disable(objspace);
+
+ objspace->rgengc.allrefs_table = objspace_allrefs(objspace);
+
+ if (checker_func) {
+ st_foreach(objspace->rgengc.allrefs_table, checker_func, (st_data_t)objspace);
+ }
+
+ if (objspace->rgengc.error_count > 0) {
+#if RGENGC_CHECK_MODE >= 5
+ allrefs_dump(objspace);
+#endif
+ if (checker_name) rb_bug("%s: GC has problem.", checker_name);
+ }
+
+ objspace_allrefs_destruct(objspace->rgengc.allrefs_table);
+ objspace->rgengc.allrefs_table = 0;
+
+ if (already_disabled == Qfalse) rb_objspace_gc_enable(objspace);
+ objspace->malloc_params.increase = saved_malloc_increase;
+#if RGENGC_ESTIMATE_OLDMALLOC
+ objspace->malloc_counters.oldmalloc_increase = saved_oldmalloc_increase;
+#endif
+}
+#endif /* RGENGC_CHECK_MODE >= 4 */
+
+struct verify_internal_consistency_struct {
+ rb_objspace_t *objspace;
+ int err_count;
+ size_t live_object_count;
+ size_t zombie_object_count;
+
+ VALUE parent;
+ size_t old_object_count;
+ size_t remembered_shady_count;
+};
+
+static void
+check_generation_i(const VALUE child, void *ptr)
+{
+ struct verify_internal_consistency_struct *data = (struct verify_internal_consistency_struct *)ptr;
+ const VALUE parent = data->parent;
+
+ if (RGENGC_CHECK_MODE) GC_ASSERT(RVALUE_OLD_P(data->objspace, parent));
+
+ if (!RVALUE_OLD_P(data->objspace, child)) {
+ if (!RVALUE_REMEMBERED(data->objspace, parent) &&
+ !RVALUE_REMEMBERED(data->objspace, child) &&
+ !RVALUE_UNCOLLECTIBLE(data->objspace, child)) {
+ fprintf(stderr, "verify_internal_consistency_reachable_i: WB miss (O->Y) %s -> %s\n", rb_obj_info(parent), rb_obj_info(child));
+ data->err_count++;
+ }
+ }
+}
+
+static void
+check_color_i(const VALUE child, void *ptr)
+{
+ struct verify_internal_consistency_struct *data = (struct verify_internal_consistency_struct *)ptr;
+ const VALUE parent = data->parent;
+
+ if (!RVALUE_WB_UNPROTECTED(data->objspace, parent) && RVALUE_WHITE_P(data->objspace, child)) {
+ fprintf(stderr, "verify_internal_consistency_reachable_i: WB miss (B->W) - %s -> %s\n",
+ rb_obj_info(parent), rb_obj_info(child));
+ data->err_count++;
+ }
+}
+
+static void
+check_children_i(const VALUE child, void *ptr)
+{
+ struct verify_internal_consistency_struct *data = (struct verify_internal_consistency_struct *)ptr;
+ if (check_rvalue_consistency_force(data->objspace, child, FALSE) != 0) {
+ fprintf(stderr, "check_children_i: %s has error (referenced from %s)",
+ rb_obj_info(child), rb_obj_info(data->parent));
+
+ data->err_count++;
+ }
+}
+
+static int
+verify_internal_consistency_i(void *page_start, void *page_end, size_t stride,
+ struct verify_internal_consistency_struct *data)
+{
+ VALUE obj;
+ rb_objspace_t *objspace = data->objspace;
+
+ for (obj = (VALUE)page_start; obj != (VALUE)page_end; obj += stride) {
+ asan_unpoisoning_object(obj) {
+ if (!rb_gc_impl_garbage_object_p(objspace, obj)) {
+ /* count objects */
+ data->live_object_count++;
+ data->parent = obj;
+
+ /* Normally, we don't expect T_MOVED objects to be in the heap.
+ * But they can stay alive on the stack, */
+ if (!gc_object_moved_p(objspace, obj)) {
+ /* moved slots don't have children */
+ rb_objspace_reachable_objects_from(obj, check_children_i, (void *)data);
+ }
+
+ /* check health of children */
+ if (RVALUE_OLD_P(objspace, obj)) data->old_object_count++;
+ if (RVALUE_WB_UNPROTECTED(objspace, obj) && RVALUE_UNCOLLECTIBLE(objspace, obj)) data->remembered_shady_count++;
+
+ if (!is_marking(objspace) && RVALUE_OLD_P(objspace, obj)) {
+ /* reachable objects from an oldgen object should be old or (young with remember) */
+ data->parent = obj;
+ rb_objspace_reachable_objects_from(obj, check_generation_i, (void *)data);
+ }
+
+ if (!is_marking(objspace) && rb_gc_obj_shareable_p(obj)) {
+ rb_gc_verify_shareable(obj);
+ }
+
+ if (is_incremental_marking(objspace)) {
+ if (RVALUE_BLACK_P(objspace, obj)) {
+ /* reachable objects from black objects should be black or grey objects */
+ data->parent = obj;
+ rb_objspace_reachable_objects_from(obj, check_color_i, (void *)data);
+ }
+ }
+ }
+ else {
+ if (BUILTIN_TYPE(obj) == T_ZOMBIE) {
+ data->zombie_object_count++;
+
+ if ((RBASIC(obj)->flags & ~ZOMBIE_OBJ_KEPT_FLAGS) != T_ZOMBIE) {
+ fprintf(stderr, "verify_internal_consistency_i: T_ZOMBIE has extra flags set: %s\n",
+ rb_obj_info(obj));
+ data->err_count++;
+ }
+
+ if (!!FL_TEST(obj, FL_FINALIZE) != !!st_is_member(finalizer_table, obj)) {
+ fprintf(stderr, "verify_internal_consistency_i: FL_FINALIZE %s but %s finalizer_table: %s\n",
+ FL_TEST(obj, FL_FINALIZE) ? "set" : "not set", st_is_member(finalizer_table, obj) ? "in" : "not in",
+ rb_obj_info(obj));
+ data->err_count++;
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int
+gc_verify_heap_page(rb_objspace_t *objspace, struct heap_page *page, VALUE obj)
+{
+ 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;
+
+ short slot_size = page->slot_size;
+ uintptr_t start = (uintptr_t)page->start;
+ uintptr_t end = start + page->total_slots * slot_size;
+
+ for (uintptr_t ptr = start; ptr < end; ptr += slot_size) {
+ VALUE val = (VALUE)ptr;
+ asan_unpoisoning_object(val) {
+ enum ruby_value_type type = BUILTIN_TYPE(val);
+
+ if (type == T_NONE) free_objects++;
+ if (type == T_ZOMBIE) zombie_objects++;
+ if (RVALUE_PAGE_UNCOLLECTIBLE(page, val) && RVALUE_PAGE_WB_UNPROTECTED(page, val)) {
+ has_remembered_shady = TRUE;
+ }
+ if (RVALUE_PAGE_MARKING(page, val)) {
+ has_remembered_old = TRUE;
+ remembered_old_objects++;
+ }
+ }
+ }
+
+ if (!is_incremental_marking(objspace) &&
+ page->flags.has_remembered_objects == FALSE && has_remembered_old == TRUE) {
+
+ for (uintptr_t ptr = start; ptr < end; ptr += slot_size) {
+ VALUE val = (VALUE)ptr;
+ if (RVALUE_PAGE_MARKING(page, val)) {
+ fprintf(stderr, "marking -> %s\n", rb_obj_info(val));
+ }
+ }
+ rb_bug("page %p's has_remembered_objects should be false, but there are remembered old objects (%d). %s",
+ (void *)page, remembered_old_objects, obj ? rb_obj_info(obj) : "");
+ }
+
+ if (page->flags.has_uncollectible_wb_unprotected_objects == FALSE && has_remembered_shady == TRUE) {
+ rb_bug("page %p's has_remembered_shady should be false, but there are remembered shady objects. %s",
+ (void *)page, obj ? rb_obj_info(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", (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", (void *)page, page->final_slots, zombie_objects);
+ }
+
+ return remembered_old_objects;
+}
+
+static int
+gc_verify_heap_pages_(rb_objspace_t *objspace, struct ccan_list_head *head)
+{
+ int remembered_old_objects = 0;
+ struct heap_page *page = 0;
+
+ ccan_list_for_each(head, page, page_node) {
+ asan_unlock_freelist(page);
+ struct free_slot *p = page->freelist;
+ while (p) {
+ VALUE vp = (VALUE)p;
+ VALUE prev = vp;
+ rb_asan_unpoison_object(vp, false);
+ if (BUILTIN_TYPE(vp) != T_NONE) {
+ fprintf(stderr, "freelist slot expected to be T_NONE but was: %s\n", rb_obj_info(vp));
+ }
+ p = p->next;
+ rb_asan_poison_object(prev);
+ }
+ asan_lock_freelist(page);
+
+ if (page->flags.has_remembered_objects == FALSE) {
+ remembered_old_objects += gc_verify_heap_page(objspace, page, Qfalse);
+ }
+ }
+
+ return remembered_old_objects;
+}
+
+static int
+gc_verify_heap_pages(rb_objspace_t *objspace)
+{
+ int remembered_old_objects = 0;
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ remembered_old_objects += gc_verify_heap_pages_(objspace, &((&heaps[i])->pages));
+ }
+ return remembered_old_objects;
+}
+
+static void
+gc_verify_internal_consistency_(rb_objspace_t *objspace)
+{
+ struct verify_internal_consistency_struct data = {0};
+
+ data.objspace = objspace;
+ gc_report(5, objspace, "gc_verify_internal_consistency: start\n");
+
+ /* check relations */
+ for (size_t i = 0; i < rb_darray_size(objspace->heap_pages.sorted); i++) {
+ struct heap_page *page = rb_darray_get(objspace->heap_pages.sorted, i);
+ short slot_size = page->slot_size;
+
+ 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
+ objspace->rgengc.error_count = data.err_count;
+ gc_marks_check(objspace, NULL, NULL);
+ allrefs_dump(objspace);
+#endif
+ rb_bug("gc_verify_internal_consistency: found internal inconsistency.");
+ }
+
+ /* check heap_page status */
+ gc_verify_heap_pages(objspace);
+
+ /* check counters */
+
+ ractor_cache_flush_count(objspace, rb_gc_get_ractor_newobj_cache());
+
+ if (!is_lazy_sweeping(objspace) &&
+ !finalizing &&
+ !rb_gc_multi_ractor_p()) {
+ if (objspace_live_slots(objspace) != data.live_object_count) {
+ fprintf(stderr, "heap_pages_final_slots: %"PRIdSIZE", total_freed_objects: %"PRIdSIZE"\n",
+ total_final_slots_count(objspace), total_freed_objects(objspace));
+ rb_bug("inconsistent live slot number: expect %"PRIuSIZE", but %"PRIuSIZE".",
+ objspace_live_slots(objspace), data.live_object_count);
+ }
+ }
+
+ 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);
+ }
+ if (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);
+ }
+ }
+
+ if (!finalizing) {
+ size_t list_count = 0;
+
+ {
+ VALUE z = heap_pages_deferred_final;
+ while (z) {
+ list_count++;
+ z = RZOMBIE(z)->next;
+ }
+ }
+
+ if (total_final_slots_count(objspace) != data.zombie_object_count ||
+ total_final_slots_count(objspace) != list_count) {
+
+ rb_bug("inconsistent finalizing object count:\n"
+ " expect %"PRIuSIZE"\n"
+ " but %"PRIuSIZE" zombies\n"
+ " heap_pages_deferred_final list has %"PRIuSIZE" items.",
+ total_final_slots_count(objspace),
+ data.zombie_object_count,
+ list_count);
+ }
+ }
+
+ gc_report(5, objspace, "gc_verify_internal_consistency: OK\n");
+}
+
+static void
+gc_verify_internal_consistency(void *objspace_ptr)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ unsigned int lev = RB_GC_VM_LOCK();
+ {
+ rb_gc_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_GC_VM_UNLOCK(lev);
+}
+
+static void
+heap_move_pooled_pages_to_free_pages(rb_heap_t *heap)
+{
+ if (heap->pooled_pages) {
+ if (heap->free_pages) {
+ struct heap_page *free_pages_tail = heap->free_pages;
+ while (free_pages_tail->free_next) {
+ free_pages_tail = free_pages_tail->free_next;
+ }
+ free_pages_tail->free_next = heap->pooled_pages;
+ }
+ else {
+ heap->free_pages = heap->pooled_pages;
+ }
+
+ heap->pooled_pages = NULL;
+ }
+}
+
+static int
+gc_remember_unprotected(rb_objspace_t *objspace, VALUE obj)
+{
+ struct heap_page *page = GET_HEAP_PAGE(obj);
+ bits_t *uncollectible_bits = &page->uncollectible_bits[0];
+
+ if (!MARKED_IN_BITMAP(uncollectible_bits, obj)) {
+ page->flags.has_uncollectible_wb_unprotected_objects = TRUE;
+ MARK_IN_BITMAP(uncollectible_bits, obj);
+ objspace->rgengc.uncollectible_wb_unprotected_objects++;
+
+#if RGENGC_PROFILE > 0
+ objspace->profile.total_remembered_shady_object_count++;
+#if RGENGC_PROFILE >= 2
+ objspace->profile.remembered_shady_object_count_types[BUILTIN_TYPE(obj)]++;
+#endif
+#endif
+ return TRUE;
+ }
+ else {
+ return FALSE;
+ }
+}
+
+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", rb_obj_info((VALUE)p));
+ GC_ASSERT(RVALUE_WB_UNPROTECTED(objspace, (VALUE)p));
+ GC_ASSERT(RVALUE_MARKED(objspace, (VALUE)p));
+ gc_mark_children(objspace, (VALUE)p);
+ }
+ p += BASE_SLOT_SIZE;
+ bits >>= 1;
+ } while (bits);
+ }
+}
+
+static void
+gc_marks_wb_unprotected_objects(rb_objspace_t *objspace, rb_heap_t *heap)
+{
+ struct heap_page *page = 0;
+
+ ccan_list_for_each(&heap->pages, page, page_node) {
+ bits_t *mark_bits = page->mark_bits;
+ bits_t *wbun_bits = page->wb_unprotected_bits;
+ uintptr_t p = page->start;
+ size_t j;
+
+ bits_t bits = mark_bits[0] & wbun_bits[0];
+ bits >>= NUM_IN_PAGE(p);
+ gc_marks_wb_unprotected_objects_plane(objspace, p, bits);
+ p += (BITS_BITLENGTH - NUM_IN_PAGE(p)) * BASE_SLOT_SIZE;
+
+ for (j=1; j<HEAP_PAGE_BITMAP_LIMIT; j++) {
+ bits_t bits = mark_bits[j] & wbun_bits[j];
+
+ gc_marks_wb_unprotected_objects_plane(objspace, p, bits);
+ p += BITS_BITLENGTH * BASE_SLOT_SIZE;
+ }
+ }
+
+ gc_mark_stacked_objects_all(objspace);
+}
+
+void
+rb_gc_impl_declare_weak_references(void *objspace_ptr, VALUE obj)
+{
+ FL_SET_RAW(obj, RUBY_FL_WEAK_REFERENCE);
+}
+
+bool
+rb_gc_impl_handle_weak_references_alive_p(void *objspace_ptr, VALUE obj)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ bool marked = RVALUE_MARKED(objspace, obj);
+
+ if (marked) {
+ rgengc_check_relation(objspace, obj);
+ }
+
+ return marked;
+}
+
+static void
+gc_update_weak_references(rb_objspace_t *objspace)
+{
+ VALUE *obj_ptr;
+ rb_darray_foreach(objspace->weak_references, i, obj_ptr) {
+ gc_mark_set_parent(objspace, *obj_ptr);
+ rb_gc_handle_weak_references(*obj_ptr);
+ gc_mark_set_parent_invalid(objspace);
+ }
+
+ size_t capa = rb_darray_capa(objspace->weak_references);
+ size_t size = rb_darray_size(objspace->weak_references);
+
+ objspace->profile.weak_references_count = size;
+
+ rb_darray_clear(objspace->weak_references);
+
+ /* If the darray has capacity for more than four times the amount used, we
+ * shrink it down to half of that capacity. */
+ if (capa > size * 4) {
+ rb_darray_resize_capa_without_gc(&objspace->weak_references, size * 2);
+ }
+}
+
+static void
+gc_marks_finish(rb_objspace_t *objspace)
+{
+ /* finish incremental GC */
+ if (is_incremental_marking(objspace)) {
+ if (RGENGC_CHECK_MODE && is_mark_stack_empty(&objspace->mark_stack) == 0) {
+ rb_bug("gc_marks_finish: mark stack is not empty (%"PRIdSIZE").",
+ mark_stack_size(&objspace->mark_stack));
+ }
+
+ mark_roots(objspace, NULL);
+ while (gc_mark_stacked_objects_incremental(objspace, INT_MAX) == false);
+
+#if RGENGC_CHECK_MODE >= 2
+ if (gc_verify_heap_pages(objspace) != 0) {
+ rb_bug("gc_marks_finish (incremental): there are remembered old objects.");
+ }
+#endif
+
+ objspace->flags.during_incremental_marking = FALSE;
+ /* check children of all marked wb-unprotected objects */
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ gc_marks_wb_unprotected_objects(objspace, &heaps[i]);
+ }
+ }
+
+ gc_update_weak_references(objspace);
+
+#if RGENGC_CHECK_MODE >= 2
+ gc_verify_internal_consistency(objspace);
+#endif
+
+#if RGENGC_CHECK_MODE >= 4
+ during_gc = FALSE;
+ gc_marks_check(objspace, gc_check_after_marks_i, "after_marks");
+ during_gc = TRUE;
+#endif
+
+ {
+ const unsigned long r_mul = objspace->live_ractor_cache_count > 8 ? 8 : objspace->live_ractor_cache_count; // upto 8
+
+ size_t total_slots = objspace_available_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);
+ if (min_free_slots < gc_params.heap_free_slots * r_mul) {
+ min_free_slots = gc_params.heap_free_slots * r_mul;
+ }
+
+ int full_marking = is_full_marking(objspace);
+
+ GC_ASSERT(objspace_available_slots(objspace) >= objspace->marked_slots);
+
+ /* Setup freeable slots. */
+ size_t total_init_slots = 0;
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ total_init_slots += gc_params.heap_init_slots[i] * r_mul;
+ }
+
+ if (max_free_slots < total_init_slots) {
+ max_free_slots = total_init_slots;
+ }
+
+ if (sweep_slots > max_free_slots) {
+ heap_pages_freeable_pages = (sweep_slots - max_free_slots) / HEAP_PAGE_OBJ_LIMIT;
+ }
+ else {
+ heap_pages_freeable_pages = 0;
+ }
+
+ if (objspace->heap_pages.allocatable_slots == 0 && sweep_slots < min_free_slots) {
+ if (!full_marking) {
+ if (objspace->profile.count - objspace->rgengc.last_major_gc < RVALUE_OLD_AGE) {
+ full_marking = TRUE;
+ }
+ else {
+ gc_report(1, objspace, "gc_marks_finish: next is full GC!!)\n");
+ gc_needs_major_flags |= GPR_FLAG_MAJOR_BY_NOFREE;
+ }
+ }
+
+ if (full_marking) {
+ heap_allocatable_slots_expand(objspace, NULL, sweep_slots, total_slots);
+ }
+ }
+
+ if (full_marking) {
+ /* 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 = MAX(
+ (size_t)(objspace->rgengc.uncollectible_wb_unprotected_objects * r),
+ (size_t)(objspace->rgengc.old_objects * gc_params.uncollectible_wb_unprotected_objects_limit_ratio)
+ );
+ objspace->rgengc.old_objects_limit = (size_t)(objspace->rgengc.old_objects * r);
+ }
+
+ if (objspace->rgengc.uncollectible_wb_unprotected_objects > objspace->rgengc.uncollectible_wb_unprotected_objects_limit) {
+ gc_needs_major_flags |= GPR_FLAG_MAJOR_BY_SHADY;
+ }
+ if (objspace->rgengc.old_objects > objspace->rgengc.old_objects_limit) {
+ gc_needs_major_flags |= GPR_FLAG_MAJOR_BY_OLDGEN;
+ }
+
+ gc_report(1, objspace, "gc_marks_finish (marks %"PRIdSIZE" objects, "
+ "old %"PRIdSIZE" objects, total %"PRIdSIZE" slots, "
+ "sweep %"PRIdSIZE" slots, allocatable %"PRIdSIZE" slots, next GC: %s)\n",
+ objspace->marked_slots, objspace->rgengc.old_objects, objspace_available_slots(objspace), sweep_slots, objspace->heap_pages.allocatable_slots,
+ gc_needs_major_flags ? "major" : "minor");
+ }
+
+ // TODO: refactor so we don't need to call this
+ rb_ractor_finish_marking();
+
+ rb_gc_event_hook(0, RUBY_INTERNAL_EVENT_GC_END_MARK);
+}
+
+static bool
+gc_compact_heap_cursors_met_p(rb_heap_t *heap)
+{
+ return heap->sweeping_page == heap->compact_cursor;
+}
+
+
+static rb_heap_t *
+gc_compact_destination_pool(rb_objspace_t *objspace, rb_heap_t *src_pool, VALUE obj)
+{
+ size_t obj_size = rb_gc_obj_optimal_size(obj);
+ if (obj_size == 0) {
+ return src_pool;
+ }
+
+ GC_ASSERT(rb_gc_impl_size_allocatable_p(obj_size));
+
+ size_t idx = heap_idx_for_size(obj_size);
+
+ return &heaps[idx];
+}
+
+static bool
+gc_compact_move(rb_objspace_t *objspace, rb_heap_t *heap, VALUE src)
+{
+ GC_ASSERT(BUILTIN_TYPE(src) != T_MOVED);
+ GC_ASSERT(gc_is_moveable_obj(objspace, src));
+
+ rb_heap_t *dest_pool = gc_compact_destination_pool(objspace, heap, src);
+ uint32_t orig_shape = 0;
+ uint32_t new_shape = 0;
+
+ if (gc_compact_heap_cursors_met_p(dest_pool)) {
+ return dest_pool != heap;
+ }
+
+ if (RB_TYPE_P(src, T_OBJECT)) {
+ orig_shape = rb_gc_get_shape(src);
+
+ if (dest_pool != heap) {
+ new_shape = rb_gc_rebuild_shape(src, dest_pool - heaps);
+
+ if (new_shape == 0) {
+ dest_pool = heap;
+ }
+ }
+ }
+
+ while (!try_move(objspace, dest_pool, dest_pool->free_pages, src)) {
+ struct gc_sweep_context ctx = {
+ .page = dest_pool->sweeping_page,
+ .final_slots = 0,
+ .freed_slots = 0,
+ .empty_slots = 0,
+ };
+
+ /* The page of src could be partially compacted, so it may contain
+ * T_MOVED. Sweeping a page may read objects on this page, so we
+ * need to lock the page. */
+ lock_page_body(objspace, GET_PAGE_BODY(src));
+ gc_sweep_page(objspace, dest_pool, &ctx);
+ unlock_page_body(objspace, GET_PAGE_BODY(src));
+
+ if (dest_pool->sweeping_page->free_slots > 0) {
+ heap_add_freepage(dest_pool, dest_pool->sweeping_page);
+ }
+
+ dest_pool->sweeping_page = ccan_list_next(&dest_pool->pages, dest_pool->sweeping_page, page_node);
+ if (gc_compact_heap_cursors_met_p(dest_pool)) {
+ return dest_pool != heap;
+ }
+ }
+
+ if (orig_shape != 0) {
+ if (new_shape != 0) {
+ VALUE dest = rb_gc_impl_location(objspace, src);
+ rb_gc_set_shape(dest, new_shape);
+ }
+ RMOVED(src)->original_shape_id = orig_shape;
+ }
+
+ return true;
+}
+
+static bool
+gc_compact_plane(rb_objspace_t *objspace, rb_heap_t *heap, uintptr_t p, bits_t bitset, struct heap_page *page)
+{
+ short slot_size = page->slot_size;
+ short slot_bits = slot_size / BASE_SLOT_SIZE;
+ GC_ASSERT(slot_bits > 0);
+
+ do {
+ VALUE vp = (VALUE)p;
+ GC_ASSERT(vp % BASE_SLOT_SIZE == 0);
+
+ if (bitset & 1) {
+ objspace->rcompactor.considered_count_table[BUILTIN_TYPE(vp)]++;
+
+ if (gc_is_moveable_obj(objspace, vp)) {
+ if (!gc_compact_move(objspace, heap, vp)) {
+ //the cursors met. bubble up
+ return false;
+ }
+ }
+ }
+ p += slot_size;
+ bitset >>= slot_bits;
+ } while (bitset);
+
+ return true;
+}
+
+// Iterate up all the objects in page, moving them to where they want to go
+static bool
+gc_compact_page(rb_objspace_t *objspace, rb_heap_t *heap, struct heap_page *page)
+{
+ GC_ASSERT(page == heap->compact_cursor);
+
+ bits_t *mark_bits, *pin_bits;
+ bits_t bitset;
+ uintptr_t p = page->start;
+
+ mark_bits = page->mark_bits;
+ pin_bits = page->pinned_bits;
+
+ // objects that can be moved are marked and not pinned
+ bitset = (mark_bits[0] & ~pin_bits[0]);
+ bitset >>= NUM_IN_PAGE(p);
+ if (bitset) {
+ if (!gc_compact_plane(objspace, heap, (uintptr_t)p, bitset, page))
+ return false;
+ }
+ p += (BITS_BITLENGTH - NUM_IN_PAGE(p)) * BASE_SLOT_SIZE;
+
+ for (int j = 1; j < HEAP_PAGE_BITMAP_LIMIT; j++) {
+ bitset = (mark_bits[j] & ~pin_bits[j]);
+ if (bitset) {
+ if (!gc_compact_plane(objspace, heap, (uintptr_t)p, bitset, page))
+ return false;
+ }
+ p += BITS_BITLENGTH * BASE_SLOT_SIZE;
+ }
+
+ return true;
+}
+
+static bool
+gc_compact_all_compacted_p(rb_objspace_t *objspace)
+{
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ rb_heap_t *heap = &heaps[i];
+
+ if (heap->total_pages > 0 &&
+ !gc_compact_heap_cursors_met_p(heap)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static void
+gc_sweep_compact(rb_objspace_t *objspace)
+{
+ gc_compact_start(objspace);
+#if RGENGC_CHECK_MODE >= 2
+ gc_verify_internal_consistency(objspace);
+#endif
+
+ while (!gc_compact_all_compacted_p(objspace)) {
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ rb_heap_t *heap = &heaps[i];
+
+ if (gc_compact_heap_cursors_met_p(heap)) {
+ continue;
+ }
+
+ struct heap_page *start_page = heap->compact_cursor;
+
+ if (!gc_compact_page(objspace, heap, start_page)) {
+ lock_page_body(objspace, start_page->body);
+
+ continue;
+ }
+
+ // If we get here, we've finished moving all objects on the compact_cursor page
+ // So we can lock it and move the cursor on to the next one.
+ lock_page_body(objspace, start_page->body);
+ heap->compact_cursor = ccan_list_prev(&heap->pages, heap->compact_cursor, page_node);
+ }
+ }
+
+ gc_compact_finish(objspace);
+
+#if RGENGC_CHECK_MODE >= 2
+ gc_verify_internal_consistency(objspace);
+#endif
+}
+
+static void
+gc_marks_rest(rb_objspace_t *objspace)
+{
+ gc_report(1, objspace, "gc_marks_rest\n");
+
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ (&heaps[i])->pooled_pages = NULL;
+ }
+
+ if (is_incremental_marking(objspace)) {
+ while (gc_mark_stacked_objects_incremental(objspace, INT_MAX) == FALSE);
+ }
+ else {
+ gc_mark_stacked_objects_all(objspace);
+ }
+
+ gc_marks_finish(objspace);
+}
+
+static bool
+gc_marks_step(rb_objspace_t *objspace, size_t slots)
+{
+ bool marking_finished = false;
+
+ GC_ASSERT(is_marking(objspace));
+ if (gc_mark_stacked_objects_incremental(objspace, slots)) {
+ gc_marks_finish(objspace);
+
+ marking_finished = true;
+ }
+
+ return marking_finished;
+}
+
+static bool
+gc_marks_continue(rb_objspace_t *objspace, rb_heap_t *heap)
+{
+ GC_ASSERT(dont_gc_val() == FALSE || objspace->profile.latest_gc_info & GPR_FLAG_METHOD);
+ bool marking_finished = true;
+
+ gc_marking_enter(objspace);
+
+ if (heap->free_pages) {
+ gc_report(2, objspace, "gc_marks_continue: has pooled pages");
+
+ marking_finished = 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));
+ heap->force_incremental_marking_finish_count++;
+ gc_marks_rest(objspace);
+ }
+
+ gc_marking_exit(objspace);
+
+ return marking_finished;
+}
+
+static void
+gc_marks_start(rb_objspace_t *objspace, int full_mark)
+{
+ /* start marking */
+ gc_report(1, objspace, "gc_marks_start: (%s)\n", full_mark ? "full" : "minor");
+ gc_mode_transition(objspace, gc_mode_marking);
+
+ if (full_mark) {
+ size_t incremental_marking_steps = (objspace->rincgc.pooled_slots / INCREMENTAL_MARK_STEP_ALLOCATIONS) + 1;
+ objspace->rincgc.step_slots = (objspace->marked_slots * 2) / incremental_marking_steps;
+
+ 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);
+ 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;
+
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ rb_heap_t *heap = &heaps[i];
+ rgengc_mark_and_rememberset_clear(objspace, heap);
+ heap_move_pooled_pages_to_free_pages(heap);
+
+ if (objspace->flags.during_compacting) {
+ struct heap_page *page = NULL;
+
+ ccan_list_for_each(&heap->pages, page, page_node) {
+ page->pinned_slots = 0;
+ }
+ }
+ }
+ }
+ 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++;
+
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ rgengc_rememberset_mark(objspace, &heaps[i]);
+ }
+ }
+
+ mark_roots(objspace, NULL);
+
+ gc_report(1, objspace, "gc_marks_start: (%s) end, stack in %"PRIdSIZE"\n",
+ full_mark ? "full" : "minor", mark_stack_size(&objspace->mark_stack));
+}
+
+static bool
+gc_marks(rb_objspace_t *objspace, int full_mark)
+{
+ gc_prof_mark_timer_start(objspace);
+ gc_marking_enter(objspace);
+
+ bool marking_finished = false;
+
+ /* setup marking */
+
+ gc_marks_start(objspace, full_mark);
+ if (!is_incremental_marking(objspace)) {
+ gc_marks_rest(objspace);
+ marking_finished = true;
+ }
+
+#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
+
+ gc_marking_exit(objspace);
+ gc_prof_mark_timer_stop(objspace);
+
+ return marking_finished;
+}
+
+/* RGENGC */
+
+static void
+gc_report_body(int level, rb_objspace_t *objspace, const char *fmt, ...)
+{
+ if (level <= RGENGC_DEBUG) {
+ char buf[1024];
+ FILE *out = stderr;
+ va_list args;
+ const char *status = " ";
+
+ if (during_gc) {
+ status = is_full_marking(objspace) ? "+" : "-";
+ }
+ else {
+ if (is_lazy_sweeping(objspace)) {
+ status = "S";
+ }
+ if (is_incremental_marking(objspace)) {
+ status = "M";
+ }
+ }
+
+ va_start(args, fmt);
+ vsnprintf(buf, 1024, fmt, args);
+ va_end(args);
+
+ fprintf(out, "%s|", status);
+ fputs(buf, out);
+ }
+}
+
+/* bit operations */
+
+static int
+rgengc_remembersetbits_set(rb_objspace_t *objspace, VALUE obj)
+{
+ struct heap_page *page = GET_HEAP_PAGE(obj);
+ bits_t *bits = &page->remembered_bits[0];
+
+ if (MARKED_IN_BITMAP(bits, obj)) {
+ return FALSE;
+ }
+ else {
+ page->flags.has_remembered_objects = TRUE;
+ MARK_IN_BITMAP(bits, obj);
+ return TRUE;
+ }
+}
+
+/* wb, etc */
+
+/* return FALSE if already remembered */
+static int
+rgengc_remember(rb_objspace_t *objspace, VALUE obj)
+{
+ gc_report(6, objspace, "rgengc_remember: %s %s\n", rb_obj_info(obj),
+ RVALUE_REMEMBERED(objspace, obj) ? "was already remembered" : "is remembered now");
+
+ check_rvalue_consistency(objspace, obj);
+
+ if (RGENGC_CHECK_MODE) {
+ if (RVALUE_WB_UNPROTECTED(objspace, obj)) rb_bug("rgengc_remember: %s is not wb protected.", rb_obj_info(obj));
+ }
+
+#if RGENGC_PROFILE > 0
+ if (!RVALUE_REMEMBERED(objspace, obj)) {
+ if (RVALUE_WB_UNPROTECTED(objspace, obj) == 0) {
+ objspace->profile.total_remembered_normal_object_count++;
+#if RGENGC_PROFILE >= 2
+ objspace->profile.remembered_normal_object_count_types[BUILTIN_TYPE(obj)]++;
+#endif
+ }
+ }
+#endif /* RGENGC_PROFILE > 0 */
+
+ return rgengc_remembersetbits_set(objspace, obj);
+}
+
+#ifndef PROFILE_REMEMBERSET_MARK
+#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", rb_obj_info(obj));
+ GC_ASSERT(RVALUE_UNCOLLECTIBLE(objspace, obj));
+ GC_ASSERT(RVALUE_OLD_P(objspace, obj) || RVALUE_WB_UNPROTECTED(objspace, obj));
+
+ gc_mark_children(objspace, obj);
+
+ if (RB_FL_TEST_RAW(obj, RUBY_FL_WEAK_REFERENCE)) {
+ rb_darray_append_without_gc(&objspace->weak_references, obj);
+ }
+ }
+ p += BASE_SLOT_SIZE;
+ bitset >>= 1;
+ } while (bitset);
+ }
+}
+
+static void
+rgengc_rememberset_mark(rb_objspace_t *objspace, rb_heap_t *heap)
+{
+ size_t j;
+ struct heap_page *page = 0;
+#if PROFILE_REMEMBERSET_MARK
+ int has_old = 0, has_shady = 0, has_both = 0, skip = 0;
+#endif
+ gc_report(1, objspace, "rgengc_rememberset_mark: start\n");
+
+ ccan_list_for_each(&heap->pages, page, page_node) {
+ if (page->flags.has_remembered_objects | page->flags.has_uncollectible_wb_unprotected_objects) {
+ uintptr_t p = page->start;
+ bits_t bitset, bits[HEAP_PAGE_BITMAP_LIMIT];
+ bits_t *remembered_bits = page->remembered_bits;
+ bits_t *uncollectible_bits = page->uncollectible_bits;
+ bits_t *wb_unprotected_bits = page->wb_unprotected_bits;
+#if PROFILE_REMEMBERSET_MARK
+ if (page->flags.has_remembered_objects && page->flags.has_uncollectible_wb_unprotected_objects) has_both++;
+ else if (page->flags.has_remembered_objects) has_old++;
+ else if (page->flags.has_uncollectible_wb_unprotected_objects) has_shady++;
+#endif
+ for (j=0; j<HEAP_PAGE_BITMAP_LIMIT; j++) {
+ bits[j] = remembered_bits[j] | (uncollectible_bits[j] & wb_unprotected_bits[j]);
+ remembered_bits[j] = 0;
+ }
+ page->flags.has_remembered_objects = FALSE;
+
+ bitset = bits[0];
+ bitset >>= NUM_IN_PAGE(p);
+ rgengc_rememberset_mark_plane(objspace, p, bitset);
+ p += (BITS_BITLENGTH - NUM_IN_PAGE(p)) * BASE_SLOT_SIZE;
+
+ for (j=1; j < HEAP_PAGE_BITMAP_LIMIT; j++) {
+ bitset = bits[j];
+ rgengc_rememberset_mark_plane(objspace, p, bitset);
+ p += BITS_BITLENGTH * BASE_SLOT_SIZE;
+ }
+ }
+#if PROFILE_REMEMBERSET_MARK
+ else {
+ skip++;
+ }
+#endif
+ }
+
+#if PROFILE_REMEMBERSET_MARK
+ fprintf(stderr, "%d\t%d\t%d\t%d\n", has_both, has_old, has_shady, skip);
+#endif
+ gc_report(1, objspace, "rgengc_rememberset_mark: finished\n");
+}
+
+static void
+rgengc_mark_and_rememberset_clear(rb_objspace_t *objspace, rb_heap_t *heap)
+{
+ struct heap_page *page = 0;
+
+ ccan_list_for_each(&heap->pages, page, page_node) {
+ memset(&page->mark_bits[0], 0, HEAP_PAGE_BITMAP_SIZE);
+ memset(&page->uncollectible_bits[0], 0, HEAP_PAGE_BITMAP_SIZE);
+ memset(&page->marking_bits[0], 0, HEAP_PAGE_BITMAP_SIZE);
+ memset(&page->remembered_bits[0], 0, HEAP_PAGE_BITMAP_SIZE);
+ memset(&page->pinned_bits[0], 0, HEAP_PAGE_BITMAP_SIZE);
+ page->flags.has_uncollectible_wb_unprotected_objects = FALSE;
+ page->flags.has_remembered_objects = FALSE;
+ }
+}
+
+/* RGENGC: APIs */
+
+NOINLINE(static void gc_writebarrier_generational(VALUE a, VALUE b, rb_objspace_t *objspace));
+
+static void
+gc_writebarrier_generational(VALUE a, VALUE b, rb_objspace_t *objspace)
+{
+ if (RGENGC_CHECK_MODE) {
+ if (!RVALUE_OLD_P(objspace, a)) rb_bug("gc_writebarrier_generational: %s is not an old object.", rb_obj_info(a));
+ if ( RVALUE_OLD_P(objspace, b)) rb_bug("gc_writebarrier_generational: %s is an old object.", rb_obj_info(b));
+ if (is_incremental_marking(objspace)) rb_bug("gc_writebarrier_generational: called while incremental marking: %s -> %s", rb_obj_info(a), rb_obj_info(b));
+ }
+
+ /* mark `a' and remember (default behavior) */
+ if (!RVALUE_REMEMBERED(objspace, a)) {
+ int lev = RB_GC_VM_LOCK_NO_BARRIER();
+ {
+ rgengc_remember(objspace, a);
+ }
+ RB_GC_VM_UNLOCK_NO_BARRIER(lev);
+
+ gc_report(1, objspace, "gc_writebarrier_generational: %s (remembered) -> %s\n", rb_obj_info(a), rb_obj_info(b));
+ }
+
+ check_rvalue_consistency(objspace, a);
+ check_rvalue_consistency(objspace, b);
+}
+
+static void
+gc_mark_from(rb_objspace_t *objspace, VALUE obj, VALUE parent)
+{
+ gc_mark_set_parent(objspace, parent);
+ rgengc_check_relation(objspace, obj);
+ if (gc_mark_set(objspace, obj) != FALSE) {
+ gc_aging(objspace, obj);
+ gc_grey(objspace, obj);
+ }
+ gc_mark_set_parent_invalid(objspace);
+}
+
+NOINLINE(static void gc_writebarrier_incremental(VALUE a, VALUE b, rb_objspace_t *objspace));
+
+static void
+gc_writebarrier_incremental(VALUE a, VALUE b, rb_objspace_t *objspace)
+{
+ gc_report(2, objspace, "gc_writebarrier_incremental: [LG] %p -> %s\n", (void *)a, rb_obj_info(b));
+
+ if (RVALUE_BLACK_P(objspace, a)) {
+ if (RVALUE_WHITE_P(objspace, b)) {
+ if (!RVALUE_WB_UNPROTECTED(objspace, a)) {
+ gc_report(2, objspace, "gc_writebarrier_incremental: [IN] %p -> %s\n", (void *)a, rb_obj_info(b));
+ gc_mark_from(objspace, b, a);
+ }
+ }
+ else if (RVALUE_OLD_P(objspace, a) && !RVALUE_OLD_P(objspace, b)) {
+ rgengc_remember(objspace, a);
+ }
+
+ if (RB_UNLIKELY(objspace->flags.during_compacting)) {
+ MARK_IN_BITMAP(GET_HEAP_PINNED_BITS(b), b);
+ }
+ }
+}
+
+void
+rb_gc_impl_writebarrier(void *objspace_ptr, VALUE a, VALUE b)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+#if RGENGC_CHECK_MODE
+ if (SPECIAL_CONST_P(a)) rb_bug("rb_gc_writebarrier: a is special const: %"PRIxVALUE, a);
+ if (SPECIAL_CONST_P(b)) rb_bug("rb_gc_writebarrier: b is special const: %"PRIxVALUE, b);
+#else
+ RBIMPL_ASSERT_OR_ASSUME(!SPECIAL_CONST_P(a));
+ RBIMPL_ASSERT_OR_ASSUME(!SPECIAL_CONST_P(b));
+#endif
+
+ GC_ASSERT(!during_gc);
+ GC_ASSERT(RB_BUILTIN_TYPE(a) != T_NONE);
+ GC_ASSERT(RB_BUILTIN_TYPE(a) != T_MOVED);
+ GC_ASSERT(RB_BUILTIN_TYPE(a) != T_ZOMBIE);
+ GC_ASSERT(RB_BUILTIN_TYPE(b) != T_NONE);
+ GC_ASSERT(RB_BUILTIN_TYPE(b) != T_MOVED);
+ GC_ASSERT(RB_BUILTIN_TYPE(b) != T_ZOMBIE);
+
+ retry:
+ if (!is_incremental_marking(objspace)) {
+ if (!RVALUE_OLD_P(objspace, a) || RVALUE_OLD_P(objspace, b)) {
+ // do nothing
+ }
+ else {
+ gc_writebarrier_generational(a, b, objspace);
+ }
+ }
+ else {
+ bool retry = false;
+ /* slow path */
+ int lev = RB_GC_VM_LOCK_NO_BARRIER();
+ {
+ if (is_incremental_marking(objspace)) {
+ gc_writebarrier_incremental(a, b, objspace);
+ }
+ else {
+ retry = true;
+ }
+ }
+ RB_GC_VM_UNLOCK_NO_BARRIER(lev);
+
+ if (retry) goto retry;
+ }
+ return;
+}
+
+void
+rb_gc_impl_writebarrier_unprotect(void *objspace_ptr, VALUE obj)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ if (RVALUE_WB_UNPROTECTED(objspace, obj)) {
+ return;
+ }
+ else {
+ gc_report(2, objspace, "rb_gc_writebarrier_unprotect: %s %s\n", rb_obj_info(obj),
+ RVALUE_REMEMBERED(objspace, obj) ? " (already remembered)" : "");
+
+ unsigned int lev = RB_GC_VM_LOCK_NO_BARRIER();
+ {
+ if (RVALUE_OLD_P(objspace, obj)) {
+ gc_report(1, objspace, "rb_gc_writebarrier_unprotect: %s\n", rb_obj_info(obj));
+ RVALUE_DEMOTE(objspace, obj);
+ gc_mark_set(objspace, obj);
+ gc_remember_unprotected(objspace, obj);
+
+#if RGENGC_PROFILE
+ objspace->profile.total_shade_operation_count++;
+#if RGENGC_PROFILE >= 2
+ objspace->profile.shade_operation_count_types[BUILTIN_TYPE(obj)]++;
+#endif /* RGENGC_PROFILE >= 2 */
+#endif /* RGENGC_PROFILE */
+ }
+ else {
+ RVALUE_AGE_RESET(obj);
+ }
+
+ RB_DEBUG_COUNTER_INC(obj_wb_unprotect);
+ MARK_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(obj), obj);
+ }
+ RB_GC_VM_UNLOCK_NO_BARRIER(lev);
+ }
+}
+
+void
+rb_gc_impl_copy_attributes(void *objspace_ptr, VALUE dest, VALUE obj)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ if (RVALUE_WB_UNPROTECTED(objspace, obj)) {
+ rb_gc_impl_writebarrier_unprotect(objspace, dest);
+ }
+ rb_gc_impl_copy_finalizer(objspace, dest, obj);
+}
+
+const char *
+rb_gc_impl_active_gc_name(void)
+{
+ return "default";
+}
+
+void
+rb_gc_impl_writebarrier_remember(void *objspace_ptr, VALUE obj)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ gc_report(1, objspace, "rb_gc_writebarrier_remember: %s\n", rb_obj_info(obj));
+
+ if (is_incremental_marking(objspace) || RVALUE_OLD_P(objspace, obj)) {
+ int lev = RB_GC_VM_LOCK_NO_BARRIER();
+ {
+ if (is_incremental_marking(objspace)) {
+ if (RVALUE_BLACK_P(objspace, obj)) {
+ gc_grey(objspace, obj);
+ }
+ }
+ else if (RVALUE_OLD_P(objspace, obj)) {
+ rgengc_remember(objspace, obj);
+ }
+ }
+ RB_GC_VM_UNLOCK_NO_BARRIER(lev);
+ }
+}
+
+struct rb_gc_object_metadata_names {
+ // Must be ID only
+ ID ID_wb_protected, ID_age, ID_old, ID_uncollectible, ID_marking,
+ ID_marked, ID_pinned, ID_remembered, ID_object_id, ID_shareable;
+};
+
+#define RB_GC_OBJECT_METADATA_ENTRY_COUNT (sizeof(struct rb_gc_object_metadata_names) / sizeof(ID))
+static struct rb_gc_object_metadata_entry object_metadata_entries[RB_GC_OBJECT_METADATA_ENTRY_COUNT + 1];
+
+struct rb_gc_object_metadata_entry *
+rb_gc_impl_object_metadata(void *objspace_ptr, VALUE obj)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+ size_t n = 0;
+ static struct rb_gc_object_metadata_names names;
+
+ if (!names.ID_marked) {
+#define I(s) names.ID_##s = rb_intern(#s)
+ I(wb_protected);
+ I(age);
+ I(old);
+ I(uncollectible);
+ I(marking);
+ I(marked);
+ I(pinned);
+ I(remembered);
+ I(object_id);
+ I(shareable);
+#undef I
+ }
+
+#define SET_ENTRY(na, v) do { \
+ GC_ASSERT(n <= RB_GC_OBJECT_METADATA_ENTRY_COUNT); \
+ object_metadata_entries[n].name = names.ID_##na; \
+ object_metadata_entries[n].val = v; \
+ n++; \
+} while (0)
+
+ if (!RVALUE_WB_UNPROTECTED(objspace, obj)) SET_ENTRY(wb_protected, Qtrue);
+ SET_ENTRY(age, INT2FIX(RVALUE_AGE_GET(obj)));
+ if (RVALUE_OLD_P(objspace, obj)) SET_ENTRY(old, Qtrue);
+ if (RVALUE_UNCOLLECTIBLE(objspace, obj)) SET_ENTRY(uncollectible, Qtrue);
+ if (RVALUE_MARKING(objspace, obj)) SET_ENTRY(marking, Qtrue);
+ if (RVALUE_MARKED(objspace, obj)) SET_ENTRY(marked, Qtrue);
+ if (RVALUE_PINNED(objspace, obj)) SET_ENTRY(pinned, Qtrue);
+ if (RVALUE_REMEMBERED(objspace, obj)) SET_ENTRY(remembered, Qtrue);
+ if (rb_obj_id_p(obj)) SET_ENTRY(object_id, rb_obj_id(obj));
+ if (FL_TEST(obj, FL_SHAREABLE)) SET_ENTRY(shareable, Qtrue);
+
+ object_metadata_entries[n].name = 0;
+ object_metadata_entries[n].val = 0;
+#undef SET_ENTRY
+
+ return object_metadata_entries;
+}
+
+void *
+rb_gc_impl_ractor_cache_alloc(void *objspace_ptr, void *ractor)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ objspace->live_ractor_cache_count++;
+
+ return calloc1(sizeof(rb_ractor_newobj_cache_t));
+}
+
+void
+rb_gc_impl_ractor_cache_free(void *objspace_ptr, void *cache)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ objspace->live_ractor_cache_count--;
+ gc_ractor_newobj_cache_clear(cache, NULL);
+ free(cache);
+}
+
+static void
+heap_ready_to_gc(rb_objspace_t *objspace, rb_heap_t *heap)
+{
+ if (!heap->free_pages) {
+ if (!heap_page_allocate_and_initialize(objspace, heap)) {
+ objspace->heap_pages.allocatable_slots = 1;
+ heap_page_allocate_and_initialize(objspace, heap);
+ }
+ }
+}
+
+static int
+ready_to_gc(rb_objspace_t *objspace)
+{
+ if (dont_gc_val() || during_gc) {
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ rb_heap_t *heap = &heaps[i];
+ heap_ready_to_gc(objspace, heap);
+ }
+ return FALSE;
+ }
+ else {
+ return TRUE;
+ }
+}
+
+static void
+gc_reset_malloc_info(rb_objspace_t *objspace, bool full_mark)
+{
+ gc_prof_set_malloc_info(objspace);
+ {
+ size_t inc = RUBY_ATOMIC_SIZE_EXCHANGE(malloc_increase, 0);
+ size_t old_limit = malloc_limit;
+
+ if (inc > malloc_limit) {
+ malloc_limit = (size_t)(inc * gc_params.malloc_limit_growth_factor);
+ if (malloc_limit > gc_params.malloc_limit_max) {
+ malloc_limit = gc_params.malloc_limit_max;
+ }
+ }
+ else {
+ malloc_limit = (size_t)(malloc_limit * 0.98); /* magic number */
+ if (malloc_limit < gc_params.malloc_limit_min) {
+ malloc_limit = gc_params.malloc_limit_min;
+ }
+ }
+
+ if (0) {
+ if (old_limit != malloc_limit) {
+ fprintf(stderr, "[%"PRIuSIZE"] malloc_limit: %"PRIuSIZE" -> %"PRIuSIZE"\n",
+ rb_gc_count(), old_limit, malloc_limit);
+ }
+ else {
+ fprintf(stderr, "[%"PRIuSIZE"] malloc_limit: not changed (%"PRIuSIZE")\n",
+ rb_gc_count(), malloc_limit);
+ }
+ }
+ }
+
+ /* reset oldmalloc info */
+#if RGENGC_ESTIMATE_OLDMALLOC
+ if (!full_mark) {
+ if (objspace->malloc_counters.oldmalloc_increase > objspace->rgengc.oldmalloc_increase_limit) {
+ gc_needs_major_flags |= GPR_FLAG_MAJOR_BY_OLDMALLOC;
+ objspace->rgengc.oldmalloc_increase_limit =
+ (size_t)(objspace->rgengc.oldmalloc_increase_limit * gc_params.oldmalloc_limit_growth_factor);
+
+ if (objspace->rgengc.oldmalloc_increase_limit > gc_params.oldmalloc_limit_max) {
+ objspace->rgengc.oldmalloc_increase_limit = gc_params.oldmalloc_limit_max;
+ }
+ }
+
+ if (0) fprintf(stderr, "%"PRIdSIZE"\t%d\t%"PRIuSIZE"\t%"PRIuSIZE"\t%"PRIdSIZE"\n",
+ rb_gc_count(),
+ gc_needs_major_flags,
+ objspace->malloc_counters.oldmalloc_increase,
+ objspace->rgengc.oldmalloc_increase_limit,
+ gc_params.oldmalloc_limit_max);
+ }
+ else {
+ /* major GC */
+ objspace->malloc_counters.oldmalloc_increase = 0;
+
+ if ((objspace->profile.latest_gc_info & GPR_FLAG_MAJOR_BY_OLDMALLOC) == 0) {
+ objspace->rgengc.oldmalloc_increase_limit =
+ (size_t)(objspace->rgengc.oldmalloc_increase_limit / ((gc_params.oldmalloc_limit_growth_factor - 1)/10 + 1));
+ if (objspace->rgengc.oldmalloc_increase_limit < gc_params.oldmalloc_limit_min) {
+ objspace->rgengc.oldmalloc_increase_limit = gc_params.oldmalloc_limit_min;
+ }
+ }
+ }
+#endif
+}
+
+static int
+garbage_collect(rb_objspace_t *objspace, unsigned int reason)
+{
+ int ret;
+
+ int lev = RB_GC_VM_LOCK();
+ {
+#if GC_PROFILE_MORE_DETAIL
+ objspace->profile.prepare_time = getrusage_time();
+#endif
+
+ gc_rest(objspace);
+
+#if GC_PROFILE_MORE_DETAIL
+ objspace->profile.prepare_time = getrusage_time() - objspace->profile.prepare_time;
+#endif
+
+ ret = gc_start(objspace, reason);
+ }
+ RB_GC_VM_UNLOCK(lev);
+
+ return ret;
+}
+
+static int
+gc_start(rb_objspace_t *objspace, unsigned int reason)
+{
+ unsigned int do_full_mark = !!(reason & GPR_FLAG_FULL_MARK);
+
+ if (!rb_darray_size(objspace->heap_pages.sorted)) return TRUE; /* 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_mode is %s\n", gc_mode_name(gc_mode(objspace)));
+ 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);
+
+ /* reason may be clobbered, later, so keep set immediate_sweep here */
+ objspace->flags.immediate_sweep = !!(reason & GPR_FLAG_IMMEDIATE_SWEEP);
+
+#if RGENGC_CHECK_MODE >= 2
+ gc_verify_internal_consistency(objspace);
+#endif
+
+ if (ruby_gc_stressful) {
+ int flag = FIXNUM_P(ruby_gc_stress_mode) ? FIX2INT(ruby_gc_stress_mode) : 0;
+
+ if ((flag & (1 << gc_stress_no_major)) == 0) {
+ do_full_mark = TRUE;
+ }
+
+ objspace->flags.immediate_sweep = !(flag & (1<<gc_stress_no_immediate_sweep));
+ }
+
+ if (gc_needs_major_flags) {
+ reason |= gc_needs_major_flags;
+ do_full_mark = TRUE;
+ }
+
+ /* if major gc has been disabled, never do a full mark */
+ if (!gc_config_full_mark_val) {
+ do_full_mark = FALSE;
+ }
+ gc_needs_major_flags = GPR_FLAG_NONE;
+
+ if (do_full_mark && (reason & GPR_FLAG_MAJOR_MASK) == 0) {
+ reason |= GPR_FLAG_MAJOR_BY_FORCE; /* GC by CAPI, METHOD, and so on. */
+ }
+
+ if (objspace->flags.dont_incremental ||
+ reason & GPR_FLAG_IMMEDIATE_MARK ||
+ ruby_gc_stressful) {
+ objspace->flags.during_incremental_marking = FALSE;
+ }
+ else {
+ objspace->flags.during_incremental_marking = do_full_mark;
+ }
+
+ /* Explicitly enable compaction (GC.compact) */
+ if (do_full_mark && ruby_enable_autocompact) {
+ objspace->flags.during_compacting = TRUE;
+#if RGENGC_CHECK_MODE
+ objspace->rcompactor.compare_func = ruby_autocompact_compare_func;
+#endif
+ }
+ else {
+ objspace->flags.during_compacting = !!(reason & GPR_FLAG_COMPACT);
+ }
+
+ if (!GC_ENABLE_LAZY_SWEEP || objspace->flags.dont_incremental) {
+ objspace->flags.immediate_sweep = TRUE;
+ }
+
+ if (objspace->flags.immediate_sweep) reason |= GPR_FLAG_IMMEDIATE_SWEEP;
+
+ gc_report(1, objspace, "gc_start(reason: %x) => %u, %d, %d\n",
+ reason,
+ do_full_mark, !is_incremental_marking(objspace), objspace->flags.immediate_sweep);
+
+ RB_DEBUG_COUNTER_INC(gc_count);
+
+ if (reason & GPR_FLAG_MAJOR_MASK) {
+ (void)RB_DEBUG_COUNTER_INC_IF(gc_major_nofree, reason & GPR_FLAG_MAJOR_BY_NOFREE);
+ (void)RB_DEBUG_COUNTER_INC_IF(gc_major_oldgen, reason & GPR_FLAG_MAJOR_BY_OLDGEN);
+ (void)RB_DEBUG_COUNTER_INC_IF(gc_major_shady, reason & GPR_FLAG_MAJOR_BY_SHADY);
+ (void)RB_DEBUG_COUNTER_INC_IF(gc_major_force, reason & GPR_FLAG_MAJOR_BY_FORCE);
+#if RGENGC_ESTIMATE_OLDMALLOC
+ (void)RB_DEBUG_COUNTER_INC_IF(gc_major_oldmalloc, reason & GPR_FLAG_MAJOR_BY_OLDMALLOC);
+#endif
+ }
+ else {
+ (void)RB_DEBUG_COUNTER_INC_IF(gc_minor_newobj, reason & GPR_FLAG_NEWOBJ);
+ (void)RB_DEBUG_COUNTER_INC_IF(gc_minor_malloc, reason & GPR_FLAG_MALLOC);
+ (void)RB_DEBUG_COUNTER_INC_IF(gc_minor_method, reason & GPR_FLAG_METHOD);
+ (void)RB_DEBUG_COUNTER_INC_IF(gc_minor_capi, reason & GPR_FLAG_CAPI);
+ (void)RB_DEBUG_COUNTER_INC_IF(gc_minor_stress, reason & GPR_FLAG_STRESS);
+ }
+
+ objspace->profile.count++;
+ objspace->profile.latest_gc_info = reason;
+ objspace->profile.total_allocated_objects_at_gc_start = total_allocated_objects(objspace);
+ objspace->profile.heap_used_at_gc_start = rb_darray_size(objspace->heap_pages.sorted);
+ objspace->profile.weak_references_count = 0;
+ gc_prof_setup_new_record(objspace, reason);
+ gc_reset_malloc_info(objspace, do_full_mark);
+
+ rb_gc_event_hook(0, RUBY_INTERNAL_EVENT_GC_START);
+
+ GC_ASSERT(during_gc);
+
+ gc_prof_timer_start(objspace);
+ {
+ if (gc_marks(objspace, do_full_mark)) {
+ gc_sweep(objspace);
+ }
+ }
+ gc_prof_timer_stop(objspace);
+
+ gc_exit(objspace, gc_enter_event_start, &lock_lev);
+ return TRUE;
+}
+
+static void
+gc_rest(rb_objspace_t *objspace)
+{
+ if (is_incremental_marking(objspace) || is_lazy_sweeping(objspace)) {
+ 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)) {
+ gc_marking_enter(objspace);
+ gc_marks_rest(objspace);
+ gc_marking_exit(objspace);
+
+ gc_sweep(objspace);
+ }
+
+ if (is_lazy_sweeping(objspace)) {
+ gc_sweeping_enter(objspace);
+ gc_sweep_rest(objspace);
+ gc_sweeping_exit(objspace);
+ }
+
+ gc_exit(objspace, gc_enter_event_rest, &lock_lev);
+ }
+}
+
+struct objspace_and_reason {
+ rb_objspace_t *objspace;
+ unsigned int reason;
+};
+
+static void
+gc_current_status_fill(rb_objspace_t *objspace, char *buff)
+{
+ int i = 0;
+ if (is_marking(objspace)) {
+ buff[i++] = 'M';
+ if (is_full_marking(objspace)) buff[i++] = 'F';
+ if (is_incremental_marking(objspace)) buff[i++] = 'I';
+ }
+ else if (is_sweeping(objspace)) {
+ buff[i++] = 'S';
+ if (is_lazy_sweeping(objspace)) buff[i++] = 'L';
+ }
+ else {
+ buff[i++] = 'N';
+ }
+ buff[i] = '\0';
+}
+
+static const char *
+gc_current_status(rb_objspace_t *objspace)
+{
+ static char buff[0x10];
+ gc_current_status_fill(objspace, buff);
+ return buff;
+}
+
+#if PRINT_ENTER_EXIT_TICK
+
+static tick_t last_exit_tick;
+static tick_t enter_tick;
+static int enter_count = 0;
+static char last_gc_status[0x10];
+
+static inline void
+gc_record(rb_objspace_t *objspace, int direction, const char *event)
+{
+ if (direction == 0) { /* enter */
+ enter_count++;
+ enter_tick = tick();
+ gc_current_status_fill(objspace, last_gc_status);
+ }
+ else { /* exit */
+ tick_t exit_tick = tick();
+ char current_gc_status[0x10];
+ gc_current_status_fill(objspace, current_gc_status);
+#if 1
+ /* [last mutator time] [gc time] [event] */
+ fprintf(stderr, "%"PRItick"\t%"PRItick"\t%s\t[%s->%s|%c]\n",
+ enter_tick - last_exit_tick,
+ exit_tick - enter_tick,
+ event,
+ last_gc_status, current_gc_status,
+ (objspace->profile.latest_gc_info & GPR_FLAG_MAJOR_MASK) ? '+' : '-');
+ last_exit_tick = exit_tick;
+#else
+ /* [enter_tick] [gc time] [event] */
+ fprintf(stderr, "%"PRItick"\t%"PRItick"\t%s\t[%s->%s|%c]\n",
+ enter_tick,
+ exit_tick - enter_tick,
+ event,
+ last_gc_status, current_gc_status,
+ (objspace->profile.latest_gc_info & GPR_FLAG_MAJOR_MASK) ? '+' : '-');
+#endif
+ }
+}
+#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_continue: return "continue";
+ case gc_enter_event_rest: return "rest";
+ case gc_enter_event_finalizer: return "finalizer";
+ }
+ 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_continue: RB_DEBUG_COUNTER_INC(gc_enter_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;
+ }
+}
+
+static bool current_process_time(struct timespec *ts);
+
+static void
+gc_clock_start(struct timespec *ts)
+{
+ if (!current_process_time(ts)) {
+ ts->tv_sec = 0;
+ ts->tv_nsec = 0;
+ }
+}
+
+static unsigned long long
+gc_clock_end(struct timespec *ts)
+{
+ struct timespec end_time;
+
+ if ((ts->tv_sec > 0 || ts->tv_nsec > 0) &&
+ current_process_time(&end_time) &&
+ end_time.tv_sec >= ts->tv_sec) {
+ return (unsigned long long)(end_time.tv_sec - ts->tv_sec) * (1000 * 1000 * 1000) +
+ (end_time.tv_nsec - ts->tv_nsec);
+ }
+
+ return 0;
+}
+
+static inline void
+gc_enter(rb_objspace_t *objspace, enum gc_enter_event event, unsigned int *lock_lev)
+{
+ *lock_lev = RB_GC_VM_LOCK();
+
+ switch (event) {
+ case gc_enter_event_rest:
+ case gc_enter_event_start:
+ case gc_enter_event_continue:
+ // stop other ractors
+ rb_gc_vm_barrier();
+ break;
+ default:
+ break;
+ }
+
+ gc_enter_count(event);
+ if (RB_UNLIKELY(during_gc != 0)) rb_bug("during_gc != 0");
+ if (RGENGC_CHECK_MODE >= 3) gc_verify_internal_consistency(objspace);
+
+ during_gc = TRUE;
+ 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));
+
+ rb_gc_event_hook(0, RUBY_INTERNAL_EVENT_GC_ENTER);
+}
+
+static inline void
+gc_exit(rb_objspace_t *objspace, enum gc_enter_event event, unsigned int *lock_lev)
+{
+ GC_ASSERT(during_gc != 0);
+
+ rb_gc_event_hook(0, RUBY_INTERNAL_EVENT_GC_EXIT);
+
+ 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;
+
+ RB_GC_VM_UNLOCK(*lock_lev);
+}
+
+#ifndef MEASURE_GC
+#define MEASURE_GC (objspace->flags.measure_gc)
+#endif
+
+static void
+gc_marking_enter(rb_objspace_t *objspace)
+{
+ GC_ASSERT(during_gc != 0);
+
+ if (MEASURE_GC) {
+ gc_clock_start(&objspace->profile.marking_start_time);
+ }
+}
+
+static void
+gc_marking_exit(rb_objspace_t *objspace)
+{
+ GC_ASSERT(during_gc != 0);
+
+ if (MEASURE_GC) {
+ objspace->profile.marking_time_ns += gc_clock_end(&objspace->profile.marking_start_time);
+ }
+}
+
+static void
+gc_sweeping_enter(rb_objspace_t *objspace)
+{
+ GC_ASSERT(during_gc != 0);
+
+ if (MEASURE_GC) {
+ gc_clock_start(&objspace->profile.sweeping_start_time);
+ }
+}
+
+static void
+gc_sweeping_exit(rb_objspace_t *objspace)
+{
+ GC_ASSERT(during_gc != 0);
+
+ if (MEASURE_GC) {
+ objspace->profile.sweeping_time_ns += gc_clock_end(&objspace->profile.sweeping_start_time);
+ }
+}
+
+static void *
+gc_with_gvl(void *ptr)
+{
+ struct objspace_and_reason *oar = (struct objspace_and_reason *)ptr;
+ return (void *)(VALUE)garbage_collect(oar->objspace, oar->reason);
+}
+
+int ruby_thread_has_gvl_p(void);
+
+static int
+garbage_collect_with_gvl(rb_objspace_t *objspace, unsigned int reason)
+{
+ if (dont_gc_val()) {
+ return TRUE;
+ }
+ else if (!ruby_native_thread_p()) {
+ return TRUE;
+ }
+ else if (!ruby_thread_has_gvl_p()) {
+ void *ret;
+ struct objspace_and_reason oar;
+ oar.objspace = objspace;
+ oar.reason = reason;
+ ret = rb_thread_call_with_gvl(gc_with_gvl, (void *)&oar);
+
+ return !!ret;
+ }
+ else {
+ return garbage_collect(objspace, reason);
+ }
+}
+
+static int
+gc_set_candidate_object_i(void *vstart, void *vend, size_t stride, void *data)
+{
+ rb_objspace_t *objspace = (rb_objspace_t *)data;
+
+ VALUE v = (VALUE)vstart;
+ for (; v != (VALUE)vend; v += stride) {
+ asan_unpoisoning_object(v) {
+ switch (BUILTIN_TYPE(v)) {
+ case T_NONE:
+ case T_ZOMBIE:
+ break;
+ default:
+ rb_gc_prepare_heap_process_object(v);
+ if (!RVALUE_OLD_P(objspace, v) && !RVALUE_WB_UNPROTECTED(objspace, v)) {
+ RVALUE_AGE_SET_CANDIDATE(objspace, v);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+void
+rb_gc_impl_start(void *objspace_ptr, bool full_mark, bool immediate_mark, bool immediate_sweep, bool compact)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+ unsigned int reason = (GPR_FLAG_FULL_MARK |
+ GPR_FLAG_IMMEDIATE_MARK |
+ GPR_FLAG_IMMEDIATE_SWEEP |
+ GPR_FLAG_METHOD);
+
+ int full_marking_p = gc_config_full_mark_val;
+ gc_config_full_mark_set(TRUE);
+
+ /* For now, compact implies full mark / sweep, so ignore other flags */
+ if (compact) {
+ GC_ASSERT(GC_COMPACTION_SUPPORTED);
+
+ reason |= GPR_FLAG_COMPACT;
+ }
+ else {
+ if (!full_mark) reason &= ~GPR_FLAG_FULL_MARK;
+ if (!immediate_mark) reason &= ~GPR_FLAG_IMMEDIATE_MARK;
+ if (!immediate_sweep) reason &= ~GPR_FLAG_IMMEDIATE_SWEEP;
+ }
+
+ garbage_collect(objspace, reason);
+ gc_finalize_deferred(objspace);
+
+ gc_config_full_mark_set(full_marking_p);
+}
+
+void
+rb_gc_impl_prepare_heap(void *objspace_ptr)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ size_t orig_total_slots = objspace_available_slots(objspace);
+ size_t orig_allocatable_slots = objspace->heap_pages.allocatable_slots;
+
+ rb_gc_impl_each_objects(objspace, gc_set_candidate_object_i, objspace_ptr);
+
+ double orig_max_free_slots = gc_params.heap_free_slots_max_ratio;
+ /* Ensure that all empty pages are moved onto empty_pages. */
+ gc_params.heap_free_slots_max_ratio = 0.0;
+ rb_gc_impl_start(objspace, true, true, true, true);
+ gc_params.heap_free_slots_max_ratio = orig_max_free_slots;
+
+ objspace->heap_pages.allocatable_slots = 0;
+ heap_pages_freeable_pages = objspace->empty_pages_count;
+ heap_pages_free_unused_pages(objspace_ptr);
+ GC_ASSERT(heap_pages_freeable_pages == 0);
+ GC_ASSERT(objspace->empty_pages_count == 0);
+ objspace->heap_pages.allocatable_slots = orig_allocatable_slots;
+
+ size_t total_slots = objspace_available_slots(objspace);
+ if (orig_total_slots > total_slots) {
+ objspace->heap_pages.allocatable_slots += orig_total_slots - total_slots;
+ }
+
+#if defined(HAVE_MALLOC_TRIM) && !defined(RUBY_ALTERNATIVE_MALLOC_HEADER)
+ malloc_trim(0);
+#endif
+}
+
+static int
+gc_is_moveable_obj(rb_objspace_t *objspace, VALUE obj)
+{
+ GC_ASSERT(!SPECIAL_CONST_P(obj));
+
+ switch (BUILTIN_TYPE(obj)) {
+ case T_NONE:
+ case T_MOVED:
+ case T_ZOMBIE:
+ return FALSE;
+ case T_SYMBOL:
+ case T_STRING:
+ case T_OBJECT:
+ case T_FLOAT:
+ case T_IMEMO:
+ case T_ARRAY:
+ case T_BIGNUM:
+ case T_ICLASS:
+ case T_MODULE:
+ case T_REGEXP:
+ case T_DATA:
+ case T_MATCH:
+ case T_STRUCT:
+ case T_HASH:
+ case T_FILE:
+ case T_COMPLEX:
+ case T_RATIONAL:
+ case T_NODE:
+ case T_CLASS:
+ if (FL_TEST_RAW(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. */
+ GC_ASSERT(st_is_member(finalizer_table, obj));
+
+ return FALSE;
+ }
+ GC_ASSERT(RVALUE_MARKED(objspace, obj));
+ GC_ASSERT(!RVALUE_PINNED(objspace, obj));
+
+ return TRUE;
+
+ default:
+ rb_bug("gc_is_moveable_obj: unreachable (%d)", (int)BUILTIN_TYPE(obj));
+ break;
+ }
+
+ return FALSE;
+}
+
+void rb_mv_generic_ivar(VALUE src, VALUE dst);
+
+static VALUE
+gc_move(rb_objspace_t *objspace, VALUE src, VALUE dest, size_t src_slot_size, size_t slot_size)
+{
+ int marked;
+ int wb_unprotected;
+ int uncollectible;
+ int age;
+
+ gc_report(4, objspace, "Moving object: %p -> %p\n", (void *)src, (void *)dest);
+
+ GC_ASSERT(BUILTIN_TYPE(src) != T_NONE);
+ GC_ASSERT(!MARKED_IN_BITMAP(GET_HEAP_MARK_BITS(dest), dest));
+
+ GC_ASSERT(!RVALUE_MARKING(objspace, src));
+
+ /* Save off bits for current object. */
+ marked = RVALUE_MARKED(objspace, src);
+ wb_unprotected = RVALUE_WB_UNPROTECTED(objspace, src);
+ uncollectible = RVALUE_UNCOLLECTIBLE(objspace, src);
+ bool remembered = RVALUE_REMEMBERED(objspace, src);
+ age = RVALUE_AGE_GET(src);
+
+ /* Clear bits for eventual T_MOVED */
+ CLEAR_IN_BITMAP(GET_HEAP_MARK_BITS(src), src);
+ CLEAR_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(src), src);
+ CLEAR_IN_BITMAP(GET_HEAP_UNCOLLECTIBLE_BITS(src), src);
+ CLEAR_IN_BITMAP(GET_HEAP_PAGE(src)->remembered_bits, src);
+
+ /* Move the object */
+ memcpy((void *)dest, (void *)src, MIN(src_slot_size, slot_size));
+
+ if (RVALUE_OVERHEAD > 0) {
+ void *dest_overhead = (void *)(((uintptr_t)dest) + slot_size - RVALUE_OVERHEAD);
+ void *src_overhead = (void *)(((uintptr_t)src) + src_slot_size - RVALUE_OVERHEAD);
+
+ memcpy(dest_overhead, src_overhead, RVALUE_OVERHEAD);
+ }
+
+ memset((void *)src, 0, src_slot_size);
+ RVALUE_AGE_SET_BITMAP(src, 0);
+
+ /* Set bits for object in new location */
+ if (remembered) {
+ MARK_IN_BITMAP(GET_HEAP_PAGE(dest)->remembered_bits, dest);
+ }
+ else {
+ CLEAR_IN_BITMAP(GET_HEAP_PAGE(dest)->remembered_bits, dest);
+ }
+
+ if (marked) {
+ MARK_IN_BITMAP(GET_HEAP_MARK_BITS(dest), dest);
+ }
+ else {
+ CLEAR_IN_BITMAP(GET_HEAP_MARK_BITS(dest), dest);
+ }
+
+ if (wb_unprotected) {
+ MARK_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(dest), dest);
+ }
+ else {
+ CLEAR_IN_BITMAP(GET_HEAP_WB_UNPROTECTED_BITS(dest), dest);
+ }
+
+ if (uncollectible) {
+ MARK_IN_BITMAP(GET_HEAP_UNCOLLECTIBLE_BITS(dest), dest);
+ }
+ else {
+ CLEAR_IN_BITMAP(GET_HEAP_UNCOLLECTIBLE_BITS(dest), dest);
+ }
+
+ RVALUE_AGE_SET(dest, age);
+ /* Assign forwarding address */
+ RMOVED(src)->flags = T_MOVED;
+ RMOVED(src)->dummy = Qundef;
+ RMOVED(src)->destination = dest;
+ GC_ASSERT(BUILTIN_TYPE(dest) != T_NONE);
+
+ GET_HEAP_PAGE(src)->heap->total_freed_objects++;
+ GET_HEAP_PAGE(dest)->heap->total_allocated_objects++;
+
+ return src;
+}
+
+#if GC_CAN_COMPILE_COMPACTION
+static int
+compare_pinned_slots(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 left_page->pinned_slots - right_page->pinned_slots;
+}
+
+static int
+compare_free_slots(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 left_page->free_slots - right_page->free_slots;
+}
+
+static void
+gc_sort_heap_by_compare_func(rb_objspace_t *objspace, gc_compact_compare_func compare_func)
+{
+ for (int j = 0; j < HEAP_COUNT; j++) {
+ rb_heap_t *heap = &heaps[j];
+
+ size_t total_pages = heap->total_pages;
+ size_t size = rb_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;
+
+ heap->free_pages = NULL;
+ ccan_list_for_each(&heap->pages, page, page_node) {
+ page_list[i++] = page;
+ GC_ASSERT(page);
+ }
+
+ GC_ASSERT((size_t)i == total_pages);
+
+ /* 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_func, NULL);
+
+ /* Reset the eden heap */
+ ccan_list_head_init(&heap->pages);
+
+ for (i = 0; i < total_pages; i++) {
+ ccan_list_add(&heap->pages, &page_list[i]->page_node);
+ if (page_list[i]->free_slots != 0) {
+ heap_add_freepage(heap, page_list[i]);
+ }
+ }
+
+ free(page_list);
+ }
+}
+#endif
+
+void
+rb_gc_impl_register_pinning_obj(void *objspace_ptr, VALUE obj)
+{
+ /* no-op */
+}
+
+bool
+rb_gc_impl_object_moved_p(void *objspace_ptr, VALUE obj)
+{
+ return gc_object_moved_p(objspace_ptr, obj);
+}
+
+static int
+gc_ref_update(void *vstart, void *vend, size_t stride, rb_objspace_t *objspace, struct heap_page *page)
+{
+ VALUE v = (VALUE)vstart;
+
+ page->flags.has_uncollectible_wb_unprotected_objects = FALSE;
+ page->flags.has_remembered_objects = FALSE;
+
+ /* For each object on the page */
+ for (; v != (VALUE)vend; v += stride) {
+ asan_unpoisoning_object(v) {
+ switch (BUILTIN_TYPE(v)) {
+ case T_NONE:
+ case T_MOVED:
+ case T_ZOMBIE:
+ break;
+ default:
+ if (RVALUE_WB_UNPROTECTED(objspace, v)) {
+ page->flags.has_uncollectible_wb_unprotected_objects = TRUE;
+ }
+ if (RVALUE_REMEMBERED(objspace, v)) {
+ page->flags.has_remembered_objects = TRUE;
+ }
+ if (page->flags.before_sweep) {
+ if (RVALUE_MARKED(objspace, v)) {
+ rb_gc_update_object_references(objspace, v);
+ }
+ }
+ else {
+ rb_gc_update_object_references(objspace, v);
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+static int
+gc_update_references_weak_table_i(VALUE obj, void *data)
+{
+ int ret;
+ asan_unpoisoning_object(obj) {
+ ret = BUILTIN_TYPE(obj) == T_MOVED ? ST_REPLACE : ST_CONTINUE;
+ }
+ return ret;
+}
+
+static int
+gc_update_references_weak_table_replace_i(VALUE *obj, void *data)
+{
+ *obj = rb_gc_location(*obj);
+
+ return ST_CONTINUE;
+}
+
+static void
+gc_update_references(rb_objspace_t *objspace)
+{
+ objspace->flags.during_reference_updating = true;
+
+ rb_gc_before_updating_jit_code();
+
+ struct heap_page *page = NULL;
+
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ bool should_set_mark_bits = TRUE;
+ rb_heap_t *heap = &heaps[i];
+
+ ccan_list_for_each(&heap->pages, page, page_node) {
+ uintptr_t start = (uintptr_t)page->start;
+ uintptr_t end = start + (page->total_slots * heap->slot_size);
+
+ gc_ref_update((void *)start, (void *)end, heap->slot_size, objspace, page);
+ if (page == heap->sweeping_page) {
+ should_set_mark_bits = FALSE;
+ }
+ if (should_set_mark_bits) {
+ gc_setup_mark_bits(page);
+ }
+ }
+ }
+
+ gc_update_table_refs(finalizer_table);
+
+ rb_gc_update_vm_references((void *)objspace);
+
+ for (int table = 0; table < RB_GC_VM_WEAK_TABLE_COUNT; table++) {
+ rb_gc_vm_weak_table_foreach(
+ gc_update_references_weak_table_i,
+ gc_update_references_weak_table_replace_i,
+ NULL,
+ false,
+ table
+ );
+ }
+
+ rb_gc_after_updating_jit_code();
+
+ objspace->flags.during_reference_updating = false;
+}
+
+#if GC_CAN_COMPILE_COMPACTION
+static void
+root_obj_check_moved_i(const char *category, VALUE obj, void *data)
+{
+ rb_objspace_t *objspace = data;
+
+ if (gc_object_moved_p(objspace, obj)) {
+ rb_bug("ROOT %s points to MOVED: %p -> %s", category, (void *)obj, rb_obj_info(rb_gc_impl_location(objspace, obj)));
+ }
+}
+
+static void
+reachable_object_check_moved_i(VALUE ref, void *data)
+{
+ VALUE parent = (VALUE)data;
+ if (gc_object_moved_p(rb_gc_get_objspace(), ref)) {
+ rb_bug("Object %s points to MOVED: %p -> %s", rb_obj_info(parent), (void *)ref, rb_obj_info(rb_gc_impl_location(rb_gc_get_objspace(), ref)));
+ }
+}
+
+static int
+heap_check_moved_i(void *vstart, void *vend, size_t stride, void *data)
+{
+ rb_objspace_t *objspace = data;
+
+ VALUE v = (VALUE)vstart;
+ for (; v != (VALUE)vend; v += stride) {
+ if (gc_object_moved_p(objspace, v)) {
+ /* Moved object still on the heap, something may have a reference. */
+ }
+ else {
+ asan_unpoisoning_object(v) {
+ switch (BUILTIN_TYPE(v)) {
+ case T_NONE:
+ case T_ZOMBIE:
+ break;
+ default:
+ if (!rb_gc_impl_garbage_object_p(objspace, v)) {
+ rb_objspace_reachable_objects_from(v, reachable_object_check_moved_i, (void *)v);
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+#endif
+
+bool
+rb_gc_impl_during_gc_p(void *objspace_ptr)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ return during_gc;
+}
+
+#if RGENGC_PROFILE >= 2
+
+static const char*
+type_name(int type, VALUE obj)
+{
+ switch ((enum ruby_value_type)type) {
+ case RUBY_T_NONE: return "T_NONE";
+ case RUBY_T_OBJECT: return "T_OBJECT";
+ case RUBY_T_CLASS: return "T_CLASS";
+ case RUBY_T_MODULE: return "T_MODULE";
+ case RUBY_T_FLOAT: return "T_FLOAT";
+ case RUBY_T_STRING: return "T_STRING";
+ case RUBY_T_REGEXP: return "T_REGEXP";
+ case RUBY_T_ARRAY: return "T_ARRAY";
+ case RUBY_T_HASH: return "T_HASH";
+ case RUBY_T_STRUCT: return "T_STRUCT";
+ case RUBY_T_BIGNUM: return "T_BIGNUM";
+ case RUBY_T_FILE: return "T_FILE";
+ case RUBY_T_DATA: return "T_DATA";
+ case RUBY_T_MATCH: return "T_MATCH";
+ case RUBY_T_COMPLEX: return "T_COMPLEX";
+ case RUBY_T_RATIONAL: return "T_RATIONAL";
+ case RUBY_T_NIL: return "T_NIL";
+ case RUBY_T_TRUE: return "T_TRUE";
+ case RUBY_T_FALSE: return "T_FALSE";
+ case RUBY_T_SYMBOL: return "T_SYMBOL";
+ case RUBY_T_FIXNUM: return "T_FIXNUM";
+ case RUBY_T_UNDEF: return "T_UNDEF";
+ case RUBY_T_IMEMO: return "T_IMEMO";
+ case RUBY_T_NODE: return "T_NODE";
+ case RUBY_T_ICLASS: return "T_ICLASS";
+ case RUBY_T_ZOMBIE: return "T_ZOMBIE";
+ case RUBY_T_MOVED: return "T_MOVED";
+ default: return "unknown";
+ }
+}
+
+static void
+gc_count_add_each_types(VALUE hash, const char *name, const size_t *types)
+{
+ VALUE result = rb_hash_new_with_size(T_MASK);
+ int i;
+ for (i=0; i<T_MASK; i++) {
+ const char *type = type_name(i, 0);
+ rb_hash_aset(result, ID2SYM(rb_intern(type)), SIZET2NUM(types[i]));
+ }
+ rb_hash_aset(hash, ID2SYM(rb_intern(name)), result);
+}
+#endif
+
+size_t
+rb_gc_impl_gc_count(void *objspace_ptr)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ return objspace->profile.count;
+}
+
+static VALUE
+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, sym_need_major_by;
+ static VALUE sym_nofree, sym_oldgen, sym_shady, sym_force, sym_stress;
+#if RGENGC_ESTIMATE_OLDMALLOC
+ static VALUE sym_oldmalloc;
+#endif
+ static VALUE sym_newobj, sym_malloc, sym_method, sym_capi;
+ static VALUE sym_none, sym_marking, sym_sweeping;
+ static VALUE sym_weak_references_count;
+ VALUE hash = Qnil, key = Qnil;
+ VALUE major_by, need_major_by;
+ unsigned int flags = orig_flags ? orig_flags : objspace->profile.latest_gc_info;
+
+ if (SYMBOL_P(hash_or_key)) {
+ key = hash_or_key;
+ }
+ else if (RB_TYPE_P(hash_or_key, T_HASH)) {
+ hash = hash_or_key;
+ }
+ else {
+ rb_bug("gc_info_decode: non-hash or symbol given");
+ }
+
+ if (NIL_P(sym_major_by)) {
+#define S(s) sym_##s = ID2SYM(rb_intern_const(#s))
+ S(major_by);
+ S(gc_by);
+ S(immediate_sweep);
+ S(have_finalizer);
+ S(state);
+ S(need_major_by);
+
+ S(stress);
+ S(nofree);
+ S(oldgen);
+ S(shady);
+ S(force);
+#if RGENGC_ESTIMATE_OLDMALLOC
+ S(oldmalloc);
+#endif
+ S(newobj);
+ S(malloc);
+ S(method);
+ S(capi);
+
+ S(none);
+ S(marking);
+ S(sweeping);
+
+ S(weak_references_count);
+#undef S
+ }
+
+#define SET(name, attr) \
+ if (key == sym_##name) \
+ return (attr); \
+ else if (hash != Qnil) \
+ rb_hash_aset(hash, sym_##name, (attr));
+
+ major_by =
+ (flags & GPR_FLAG_MAJOR_BY_NOFREE) ? sym_nofree :
+ (flags & GPR_FLAG_MAJOR_BY_OLDGEN) ? sym_oldgen :
+ (flags & GPR_FLAG_MAJOR_BY_SHADY) ? sym_shady :
+ (flags & GPR_FLAG_MAJOR_BY_FORCE) ? sym_force :
+#if RGENGC_ESTIMATE_OLDMALLOC
+ (flags & GPR_FLAG_MAJOR_BY_OLDMALLOC) ? sym_oldmalloc :
+#endif
+ Qnil;
+ SET(major_by, major_by);
+
+ if (orig_flags == 0) { /* set need_major_by only if flags not set explicitly */
+ unsigned int need_major_flags = gc_needs_major_flags;
+ need_major_by =
+ (need_major_flags & GPR_FLAG_MAJOR_BY_NOFREE) ? sym_nofree :
+ (need_major_flags & GPR_FLAG_MAJOR_BY_OLDGEN) ? sym_oldgen :
+ (need_major_flags & GPR_FLAG_MAJOR_BY_SHADY) ? sym_shady :
+ (need_major_flags & GPR_FLAG_MAJOR_BY_FORCE) ? sym_force :
+#if RGENGC_ESTIMATE_OLDMALLOC
+ (need_major_flags & GPR_FLAG_MAJOR_BY_OLDMALLOC) ? sym_oldmalloc :
+#endif
+ Qnil;
+ SET(need_major_by, need_major_by);
+ }
+
+ SET(gc_by,
+ (flags & GPR_FLAG_NEWOBJ) ? sym_newobj :
+ (flags & GPR_FLAG_MALLOC) ? sym_malloc :
+ (flags & GPR_FLAG_METHOD) ? sym_method :
+ (flags & GPR_FLAG_CAPI) ? sym_capi :
+ (flags & GPR_FLAG_STRESS) ? sym_stress :
+ Qnil
+ );
+
+ SET(have_finalizer, (flags & GPR_FLAG_HAVE_FINALIZE) ? Qtrue : Qfalse);
+ SET(immediate_sweep, (flags & GPR_FLAG_IMMEDIATE_SWEEP) ? Qtrue : Qfalse);
+
+ if (orig_flags == 0) {
+ SET(state, gc_mode(objspace) == gc_mode_none ? sym_none :
+ gc_mode(objspace) == gc_mode_marking ? sym_marking : sym_sweeping);
+ }
+
+ SET(weak_references_count, LONG2FIX(objspace->profile.weak_references_count));
+#undef SET
+
+ if (!NIL_P(key)) {
+ // Matched key should return above
+ return Qundef;
+ }
+
+ return hash;
+}
+
+VALUE
+rb_gc_impl_latest_gc_info(void *objspace_ptr, VALUE key)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ return gc_info_decode(objspace, key, 0);
+}
+
+
+enum gc_stat_sym {
+ gc_stat_sym_count,
+ gc_stat_sym_time,
+ gc_stat_sym_marking_time,
+ gc_stat_sym_sweeping_time,
+ gc_stat_sym_heap_allocated_pages,
+ gc_stat_sym_heap_empty_pages,
+ gc_stat_sym_heap_allocatable_slots,
+ gc_stat_sym_heap_available_slots,
+ gc_stat_sym_heap_live_slots,
+ gc_stat_sym_heap_free_slots,
+ gc_stat_sym_heap_final_slots,
+ gc_stat_sym_heap_marked_slots,
+ gc_stat_sym_heap_eden_pages,
+ gc_stat_sym_total_allocated_pages,
+ gc_stat_sym_total_freed_pages,
+ gc_stat_sym_total_allocated_objects,
+ gc_stat_sym_total_freed_objects,
+ gc_stat_sym_malloc_increase_bytes,
+ gc_stat_sym_malloc_increase_bytes_limit,
+ 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,
+ gc_stat_sym_old_objects_limit,
+#if RGENGC_ESTIMATE_OLDMALLOC
+ gc_stat_sym_oldmalloc_increase_bytes,
+ gc_stat_sym_oldmalloc_increase_bytes_limit,
+#endif
+ gc_stat_sym_weak_references_count,
+#if RGENGC_PROFILE
+ gc_stat_sym_total_generated_normal_object_count,
+ gc_stat_sym_total_generated_shady_object_count,
+ gc_stat_sym_total_shade_operation_count,
+ gc_stat_sym_total_promoted_count,
+ gc_stat_sym_total_remembered_normal_object_count,
+ gc_stat_sym_total_remembered_shady_object_count,
+#endif
+ gc_stat_sym_last
+};
+
+static VALUE gc_stat_symbols[gc_stat_sym_last];
+
+static void
+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(marking_time),
+ S(sweeping_time),
+ S(heap_allocated_pages);
+ S(heap_empty_pages);
+ S(heap_allocatable_slots);
+ S(heap_available_slots);
+ S(heap_live_slots);
+ S(heap_free_slots);
+ S(heap_final_slots);
+ S(heap_marked_slots);
+ S(heap_eden_pages);
+ S(total_allocated_pages);
+ S(total_freed_pages);
+ S(total_allocated_objects);
+ S(total_freed_objects);
+ S(malloc_increase_bytes);
+ S(malloc_increase_bytes_limit);
+ 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);
+ S(old_objects_limit);
+#if RGENGC_ESTIMATE_OLDMALLOC
+ S(oldmalloc_increase_bytes);
+ S(oldmalloc_increase_bytes_limit);
+#endif
+ S(weak_references_count);
+#if RGENGC_PROFILE
+ S(total_generated_normal_object_count);
+ S(total_generated_shady_object_count);
+ S(total_shade_operation_count);
+ S(total_promoted_count);
+ S(total_remembered_normal_object_count);
+ S(total_remembered_shady_object_count);
+#endif /* RGENGC_PROFILE */
+#undef S
+ }
+}
+
+static uint64_t
+ns_to_ms(uint64_t ns)
+{
+ return ns / (1000 * 1000);
+}
+
+static void malloc_increase_local_flush(rb_objspace_t *objspace);
+
+VALUE
+rb_gc_impl_stat(void *objspace_ptr, VALUE hash_or_sym)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+ VALUE hash = Qnil, key = Qnil;
+
+ setup_gc_stat_symbols();
+
+ ractor_cache_flush_count(objspace, rb_gc_get_ractor_newobj_cache());
+ malloc_increase_local_flush(objspace);
+
+ if (RB_TYPE_P(hash_or_sym, T_HASH)) {
+ hash = hash_or_sym;
+ }
+ else if (SYMBOL_P(hash_or_sym)) {
+ key = hash_or_sym;
+ }
+ else {
+ rb_bug("non-hash or symbol given");
+ }
+
+#define SET(name, attr) \
+ if (key == gc_stat_symbols[gc_stat_sym_##name]) \
+ return SIZET2NUM(attr); \
+ else if (hash != Qnil) \
+ rb_hash_aset(hash, gc_stat_symbols[gc_stat_sym_##name], SIZET2NUM(attr));
+
+ SET(count, objspace->profile.count);
+ SET(time, (size_t)ns_to_ms(objspace->profile.marking_time_ns + objspace->profile.sweeping_time_ns)); // TODO: UINT64T2NUM
+ SET(marking_time, (size_t)ns_to_ms(objspace->profile.marking_time_ns));
+ SET(sweeping_time, (size_t)ns_to_ms(objspace->profile.sweeping_time_ns));
+
+ /* implementation dependent counters */
+ SET(heap_allocated_pages, rb_darray_size(objspace->heap_pages.sorted));
+ SET(heap_empty_pages, objspace->empty_pages_count)
+ SET(heap_allocatable_slots, objspace->heap_pages.allocatable_slots);
+ 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, total_final_slots_count(objspace));
+ SET(heap_marked_slots, objspace->marked_slots);
+ SET(heap_eden_pages, heap_eden_total_pages(objspace));
+ SET(total_allocated_pages, objspace->heap_pages.allocated_pages);
+ SET(total_freed_pages, objspace->heap_pages.freed_pages);
+ SET(total_allocated_objects, total_allocated_objects(objspace));
+ SET(total_freed_objects, total_freed_objects(objspace));
+ SET(malloc_increase_bytes, malloc_increase);
+ SET(malloc_increase_bytes_limit, malloc_limit);
+ 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);
+ SET(old_objects_limit, objspace->rgengc.old_objects_limit);
+#if RGENGC_ESTIMATE_OLDMALLOC
+ SET(oldmalloc_increase_bytes, objspace->malloc_counters.oldmalloc_increase);
+ SET(oldmalloc_increase_bytes_limit, objspace->rgengc.oldmalloc_increase_limit);
+#endif
+
+#if RGENGC_PROFILE
+ SET(total_generated_normal_object_count, objspace->profile.total_generated_normal_object_count);
+ SET(total_generated_shady_object_count, objspace->profile.total_generated_shady_object_count);
+ SET(total_shade_operation_count, objspace->profile.total_shade_operation_count);
+ SET(total_promoted_count, objspace->profile.total_promoted_count);
+ 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 */
+#undef SET
+
+ if (!NIL_P(key)) {
+ // Matched key should return above
+ return Qundef;
+ }
+
+#if defined(RGENGC_PROFILE) && RGENGC_PROFILE >= 2
+ if (hash != Qnil) {
+ gc_count_add_each_types(hash, "generated_normal_object_count_types", objspace->profile.generated_normal_object_count_types);
+ gc_count_add_each_types(hash, "generated_shady_object_count_types", objspace->profile.generated_shady_object_count_types);
+ gc_count_add_each_types(hash, "shade_operation_count_types", objspace->profile.shade_operation_count_types);
+ gc_count_add_each_types(hash, "promoted_types", objspace->profile.promoted_types);
+ gc_count_add_each_types(hash, "remembered_normal_object_count_types", objspace->profile.remembered_normal_object_count_types);
+ gc_count_add_each_types(hash, "remembered_shady_object_count_types", objspace->profile.remembered_shady_object_count_types);
+ }
+#endif
+
+ return hash;
+}
+
+enum gc_stat_heap_sym {
+ gc_stat_heap_sym_slot_size,
+ gc_stat_heap_sym_heap_live_slots,
+ gc_stat_heap_sym_heap_free_slots,
+ gc_stat_heap_sym_heap_final_slots,
+ gc_stat_heap_sym_heap_eden_pages,
+ gc_stat_heap_sym_heap_eden_slots,
+ gc_stat_heap_sym_total_allocated_pages,
+ gc_stat_heap_sym_force_major_gc_count,
+ gc_stat_heap_sym_force_incremental_marking_finish_count,
+ gc_stat_heap_sym_total_allocated_objects,
+ gc_stat_heap_sym_total_freed_objects,
+ gc_stat_heap_sym_last
+};
+
+static VALUE gc_stat_heap_symbols[gc_stat_heap_sym_last];
+
+static void
+setup_gc_stat_heap_symbols(void)
+{
+ if (gc_stat_heap_symbols[0] == 0) {
+#define S(s) gc_stat_heap_symbols[gc_stat_heap_sym_##s] = ID2SYM(rb_intern_const(#s))
+ S(slot_size);
+ S(heap_live_slots);
+ S(heap_free_slots);
+ S(heap_final_slots);
+ S(heap_eden_pages);
+ S(heap_eden_slots);
+ S(total_allocated_pages);
+ S(force_major_gc_count);
+ S(force_incremental_marking_finish_count);
+ S(total_allocated_objects);
+ S(total_freed_objects);
+#undef S
+ }
+}
+
+static VALUE
+stat_one_heap(rb_heap_t *heap, VALUE hash, VALUE key)
+{
+#define SET(name, attr) \
+ if (key == gc_stat_heap_symbols[gc_stat_heap_sym_##name]) \
+ return SIZET2NUM(attr); \
+ else if (hash != Qnil) \
+ rb_hash_aset(hash, gc_stat_heap_symbols[gc_stat_heap_sym_##name], SIZET2NUM(attr));
+
+ SET(slot_size, heap->slot_size);
+ SET(heap_live_slots, heap->total_allocated_objects - heap->total_freed_objects - heap->final_slots_count);
+ SET(heap_free_slots, heap->total_slots - (heap->total_allocated_objects - heap->total_freed_objects));
+ SET(heap_final_slots, heap->final_slots_count);
+ SET(heap_eden_pages, heap->total_pages);
+ SET(heap_eden_slots, heap->total_slots);
+ SET(total_allocated_pages, heap->total_allocated_pages);
+ SET(force_major_gc_count, heap->force_major_gc_count);
+ SET(force_incremental_marking_finish_count, heap->force_incremental_marking_finish_count);
+ SET(total_allocated_objects, heap->total_allocated_objects);
+ SET(total_freed_objects, heap->total_freed_objects);
+#undef SET
+
+ if (!NIL_P(key)) {
+ // Matched key should return above
+ return Qundef;
+ }
+
+ return hash;
+}
+
+VALUE
+rb_gc_impl_stat_heap(void *objspace_ptr, VALUE heap_name, VALUE hash_or_sym)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ ractor_cache_flush_count(objspace, rb_gc_get_ractor_newobj_cache());
+
+ setup_gc_stat_heap_symbols();
+
+ if (NIL_P(heap_name)) {
+ if (!RB_TYPE_P(hash_or_sym, T_HASH)) {
+ rb_bug("non-hash given");
+ }
+
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ VALUE hash = rb_hash_aref(hash_or_sym, INT2FIX(i));
+ if (NIL_P(hash)) {
+ hash = rb_hash_new();
+ rb_hash_aset(hash_or_sym, INT2FIX(i), hash);
+ }
+
+ stat_one_heap(&heaps[i], hash, Qnil);
+ }
+ }
+ else if (FIXNUM_P(heap_name)) {
+ int heap_idx = FIX2INT(heap_name);
+
+ if (heap_idx < 0 || heap_idx >= HEAP_COUNT) {
+ rb_raise(rb_eArgError, "size pool index out of range");
+ }
+
+ if (SYMBOL_P(hash_or_sym)) {
+ return stat_one_heap(&heaps[heap_idx], Qnil, hash_or_sym);
+ }
+ else if (RB_TYPE_P(hash_or_sym, T_HASH)) {
+ return stat_one_heap(&heaps[heap_idx], hash_or_sym, Qnil);
+ }
+ else {
+ rb_bug("non-hash or symbol given");
+ }
+ }
+ else {
+ rb_bug("heap_name must be nil or an Integer");
+ }
+
+ return hash_or_sym;
+}
+
+/* I could include internal.h for this, but doing so undefines some Array macros
+ * necessary for initialising objects, and I don't want to include all the array
+ * headers to get them back
+ * TODO: Investigate why RARRAY_AREF gets undefined in internal.h
+ */
+#ifndef RBOOL
+#define RBOOL(v) (v ? Qtrue : Qfalse)
+#endif
+
+VALUE
+rb_gc_impl_config_get(void *objspace_ptr)
+{
+#define sym(name) ID2SYM(rb_intern_const(name))
+ rb_objspace_t *objspace = objspace_ptr;
+ VALUE hash = rb_hash_new();
+
+ rb_hash_aset(hash, sym("rgengc_allow_full_mark"), RBOOL(gc_config_full_mark_val));
+
+ return hash;
+}
+
+static int
+gc_config_set_key(VALUE key, VALUE value, VALUE data)
+{
+ rb_objspace_t *objspace = (rb_objspace_t *)data;
+ if (rb_sym2id(key) == rb_intern("rgengc_allow_full_mark")) {
+ gc_rest(objspace);
+ gc_config_full_mark_set(RTEST(value));
+ }
+ return ST_CONTINUE;
+}
+
+void
+rb_gc_impl_config_set(void *objspace_ptr, VALUE hash)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ if (!RB_TYPE_P(hash, T_HASH)) {
+ rb_raise(rb_eArgError, "expected keyword arguments");
+ }
+
+ rb_hash_foreach(hash, gc_config_set_key, (st_data_t)objspace);
+}
+
+VALUE
+rb_gc_impl_stress_get(void *objspace_ptr)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+ return ruby_gc_stress_mode;
+}
+
+void
+rb_gc_impl_stress_set(void *objspace_ptr, VALUE flag)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ objspace->flags.gc_stressful = RTEST(flag);
+ objspace->gc_stress_mode = flag;
+}
+
+static int
+get_envparam_size(const char *name, size_t *default_value, size_t lower_bound)
+{
+ const char *ptr = getenv(name);
+ ssize_t val;
+
+ if (ptr != NULL && *ptr) {
+ size_t unit = 0;
+ char *end;
+#if SIZEOF_SIZE_T == SIZEOF_LONG_LONG
+ val = strtoll(ptr, &end, 0);
+#else
+ val = strtol(ptr, &end, 0);
+#endif
+ switch (*end) {
+ case 'k': case 'K':
+ unit = 1024;
+ ++end;
+ break;
+ case 'm': case 'M':
+ unit = 1024*1024;
+ ++end;
+ break;
+ case 'g': case 'G':
+ unit = 1024*1024*1024;
+ ++end;
+ break;
+ }
+ while (*end && isspace((unsigned char)*end)) end++;
+ if (*end) {
+ if (RTEST(ruby_verbose)) fprintf(stderr, "invalid string for %s: %s\n", name, ptr);
+ return 0;
+ }
+ if (unit > 0) {
+ if (val < -(ssize_t)(SIZE_MAX / 2 / unit) || (ssize_t)(SIZE_MAX / 2 / unit) < val) {
+ if (RTEST(ruby_verbose)) fprintf(stderr, "%s=%s is ignored because it overflows\n", name, ptr);
+ return 0;
+ }
+ val *= unit;
+ }
+ if (val > 0 && (size_t)val > lower_bound) {
+ if (RTEST(ruby_verbose)) {
+ fprintf(stderr, "%s=%"PRIdSIZE" (default value: %"PRIuSIZE")\n", name, val, *default_value);
+ }
+ *default_value = (size_t)val;
+ return 1;
+ }
+ else {
+ if (RTEST(ruby_verbose)) {
+ fprintf(stderr, "%s=%"PRIdSIZE" (default value: %"PRIuSIZE") is ignored because it must be greater than %"PRIuSIZE".\n",
+ name, val, *default_value, lower_bound);
+ }
+ return 0;
+ }
+ }
+ return 0;
+}
+
+static int
+get_envparam_double(const char *name, double *default_value, double lower_bound, double upper_bound, int accept_zero)
+{
+ const char *ptr = getenv(name);
+ double val;
+
+ if (ptr != NULL && *ptr) {
+ char *end;
+ val = strtod(ptr, &end);
+ if (!*ptr || *end) {
+ if (RTEST(ruby_verbose)) fprintf(stderr, "invalid string for %s: %s\n", name, ptr);
+ return 0;
+ }
+
+ if (accept_zero && val == 0.0) {
+ goto accept;
+ }
+ else if (val <= lower_bound) {
+ if (RTEST(ruby_verbose)) {
+ fprintf(stderr, "%s=%f (default value: %f) is ignored because it must be greater than %f.\n",
+ name, val, *default_value, lower_bound);
+ }
+ }
+ else if (upper_bound != 0.0 && /* ignore upper_bound if it is 0.0 */
+ val > upper_bound) {
+ if (RTEST(ruby_verbose)) {
+ fprintf(stderr, "%s=%f (default value: %f) is ignored because it must be lower than %f.\n",
+ name, val, *default_value, upper_bound);
+ }
+ }
+ else {
+ 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;
+}
+
+/*
+ * GC tuning environment variables
+ *
+ * * RUBY_GC_HEAP_FREE_SLOTS
+ * - Prepare at least this amount of slots after GC.
+ * - Allocate slots if there are not enough slots.
+ * * RUBY_GC_HEAP_GROWTH_FACTOR (new from 2.1)
+ * - Allocate slots by this factor.
+ * - (next slots number) = (current slots number) * (this factor)
+ * * RUBY_GC_HEAP_GROWTH_MAX_SLOTS (new from 2.1)
+ * - Allocation rate is limited to this number of slots.
+ * * RUBY_GC_HEAP_FREE_SLOTS_MIN_RATIO (new from 2.4)
+ * - Allocate additional pages when the number of free slots is
+ * lower than the value (total_slots * (this ratio)).
+ * * RUBY_GC_HEAP_FREE_SLOTS_GOAL_RATIO (new from 2.4)
+ * - Allocate slots to satisfy this formula:
+ * free_slots = total_slots * goal_ratio
+ * - In other words, prepare (total_slots * goal_ratio) free slots.
+ * - if this value is 0.0, then use RUBY_GC_HEAP_GROWTH_FACTOR directly.
+ * * RUBY_GC_HEAP_FREE_SLOTS_MAX_RATIO (new from 2.4)
+ * - Allow to free pages when the number of free slots is
+ * greater than the value (total_slots * (this ratio)).
+ * * RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR (new from 2.1.1)
+ * - Do full GC when the number of old objects is more than R * N
+ * where R is this factor and
+ * N is the number of old objects just after last full GC.
+ *
+ * * obsolete
+ * * RUBY_FREE_MIN -> RUBY_GC_HEAP_FREE_SLOTS (from 2.1)
+ * * RUBY_HEAP_MIN_SLOTS -> RUBY_GC_HEAP_INIT_SLOTS (from 2.1)
+ *
+ * * RUBY_GC_MALLOC_LIMIT
+ * * RUBY_GC_MALLOC_LIMIT_MAX (new from 2.1)
+ * * RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR (new from 2.1)
+ *
+ * * RUBY_GC_OLDMALLOC_LIMIT (new from 2.1)
+ * * RUBY_GC_OLDMALLOC_LIMIT_MAX (new from 2.1)
+ * * RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR (new from 2.1)
+ */
+
+void
+rb_gc_impl_set_params(void *objspace_ptr)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+ /* RUBY_GC_HEAP_FREE_SLOTS */
+ if (get_envparam_size("RUBY_GC_HEAP_FREE_SLOTS", &gc_params.heap_free_slots, 0)) {
+ /* ok */
+ }
+
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ char env_key[sizeof("RUBY_GC_HEAP_" "_INIT_SLOTS") + DECIMAL_SIZE_OF_BITS(sizeof(int) * CHAR_BIT)];
+ snprintf(env_key, sizeof(env_key), "RUBY_GC_HEAP_%d_INIT_SLOTS", i);
+
+ get_envparam_size(env_key, &gc_params.heap_init_slots[i], 0);
+ }
+
+ 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);
+ get_envparam_double("RUBY_GC_HEAP_FREE_SLOTS_MIN_RATIO", &gc_params.heap_free_slots_min_ratio,
+ 0.0, 1.0, FALSE);
+ get_envparam_double("RUBY_GC_HEAP_FREE_SLOTS_MAX_RATIO", &gc_params.heap_free_slots_max_ratio,
+ gc_params.heap_free_slots_min_ratio, 1.0, FALSE);
+ get_envparam_double("RUBY_GC_HEAP_FREE_SLOTS_GOAL_RATIO", &gc_params.heap_free_slots_goal_ratio,
+ gc_params.heap_free_slots_min_ratio, gc_params.heap_free_slots_max_ratio, TRUE);
+ get_envparam_double("RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR", &gc_params.oldobject_limit_factor, 0.0, 0.0, TRUE);
+ get_envparam_double("RUBY_GC_HEAP_REMEMBERED_WB_UNPROTECTED_OBJECTS_LIMIT_RATIO", &gc_params.uncollectible_wb_unprotected_objects_limit_ratio, 0.0, 0.0, TRUE);
+
+ if (get_envparam_size("RUBY_GC_MALLOC_LIMIT", &gc_params.malloc_limit_min, 0)) {
+ malloc_limit = gc_params.malloc_limit_min;
+ }
+ get_envparam_size ("RUBY_GC_MALLOC_LIMIT_MAX", &gc_params.malloc_limit_max, 0);
+ if (!gc_params.malloc_limit_max) { /* ignore max-check if 0 */
+ gc_params.malloc_limit_max = SIZE_MAX;
+ }
+ get_envparam_double("RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR", &gc_params.malloc_limit_growth_factor, 1.0, 0.0, FALSE);
+
+#if RGENGC_ESTIMATE_OLDMALLOC
+ if (get_envparam_size("RUBY_GC_OLDMALLOC_LIMIT", &gc_params.oldmalloc_limit_min, 0)) {
+ objspace->rgengc.oldmalloc_increase_limit = gc_params.oldmalloc_limit_min;
+ }
+ get_envparam_size ("RUBY_GC_OLDMALLOC_LIMIT_MAX", &gc_params.oldmalloc_limit_max, 0);
+ get_envparam_double("RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR", &gc_params.oldmalloc_limit_growth_factor, 1.0, 0.0, FALSE);
+#endif
+}
+
+static inline size_t
+objspace_malloc_size(rb_objspace_t *objspace, void *ptr, size_t hint)
+{
+#ifdef HAVE_MALLOC_USABLE_SIZE
+ if (!hint) {
+ hint = malloc_usable_size(ptr);
+ }
+#endif
+ return hint;
+}
+
+enum memop_type {
+ MEMOP_TYPE_MALLOC = 0,
+ MEMOP_TYPE_FREE,
+ MEMOP_TYPE_REALLOC
+};
+
+static inline void
+atomic_sub_nounderflow(size_t *var, size_t sub)
+{
+ if (sub == 0) return;
+
+ while (1) {
+ size_t val = *var;
+ if (val < sub) sub = val;
+ if (RUBY_ATOMIC_SIZE_CAS(*var, val, val-sub) == val) break;
+ }
+}
+
+#define gc_stress_full_mark_after_malloc_p() \
+ (FIXNUM_P(ruby_gc_stress_mode) && (FIX2LONG(ruby_gc_stress_mode) & (1<<gc_stress_full_mark_after_malloc)))
+
+static void
+objspace_malloc_gc_stress(rb_objspace_t *objspace)
+{
+ if (ruby_gc_stressful && ruby_native_thread_p()) {
+ 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;
+ }
+ garbage_collect_with_gvl(objspace, reason);
+ }
+}
+
+static void
+malloc_increase_commit(rb_objspace_t *objspace, size_t new_size, size_t old_size)
+{
+ if (new_size > old_size) {
+ RUBY_ATOMIC_SIZE_ADD(malloc_increase, new_size - old_size);
+#if RGENGC_ESTIMATE_OLDMALLOC
+ RUBY_ATOMIC_SIZE_ADD(objspace->malloc_counters.oldmalloc_increase, new_size - old_size);
+#endif
+ }
+ else {
+ atomic_sub_nounderflow(&malloc_increase, old_size - new_size);
+#if RGENGC_ESTIMATE_OLDMALLOC
+ atomic_sub_nounderflow(&objspace->malloc_counters.oldmalloc_increase, old_size - new_size);
+#endif
+ }
+}
+
+#if USE_MALLOC_INCREASE_LOCAL
+static void
+malloc_increase_local_flush(rb_objspace_t *objspace)
+{
+ int delta = malloc_increase_local;
+ if (delta == 0) return;
+
+ malloc_increase_local = 0;
+ if (delta > 0) {
+ malloc_increase_commit(objspace, (size_t)delta, 0);
+ }
+ else {
+ malloc_increase_commit(objspace, 0, (size_t)(-delta));
+ }
+}
+#else
+static void
+malloc_increase_local_flush(rb_objspace_t *objspace)
+{
+}
+#endif
+
+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, bool gc_allowed)
+{
+ 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, bool gc_allowed)
+{
+#if USE_MALLOC_INCREASE_LOCAL
+ if (new_size < GC_MALLOC_INCREASE_LOCAL_THRESHOLD &&
+ old_size < GC_MALLOC_INCREASE_LOCAL_THRESHOLD) {
+ malloc_increase_local += (int)new_size - (int)old_size;
+
+ if (malloc_increase_local >= GC_MALLOC_INCREASE_LOCAL_THRESHOLD ||
+ malloc_increase_local <= -GC_MALLOC_INCREASE_LOCAL_THRESHOLD) {
+ malloc_increase_local_flush(objspace);
+ }
+ }
+ else {
+ malloc_increase_local_flush(objspace);
+ malloc_increase_commit(objspace, new_size, old_size);
+ }
+#else
+ malloc_increase_commit(objspace, new_size, old_size);
+#endif
+
+ if (type == MEMOP_TYPE_MALLOC && gc_allowed) {
+ retry:
+ 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;
+ }
+ garbage_collect_with_gvl(objspace, GPR_FLAG_MALLOC);
+ }
+ }
+
+#if MALLOC_ALLOCATED_SIZE
+ if (new_size >= old_size) {
+ RUBY_ATOMIC_SIZE_ADD(objspace->malloc_params.allocated_size, new_size - old_size);
+ }
+ else {
+ size_t dec_size = old_size - new_size;
+
+#if MALLOC_ALLOCATED_SIZE_CHECK
+ size_t allocated_size = objspace->malloc_params.allocated_size;
+ if (allocated_size < dec_size) {
+ rb_bug("objspace_malloc_increase: underflow malloc_params.allocated_size.");
+ }
+#endif
+ atomic_sub_nounderflow(&objspace->malloc_params.allocated_size, dec_size);
+ }
+
+ switch (type) {
+ case MEMOP_TYPE_MALLOC:
+ RUBY_ATOMIC_SIZE_INC(objspace->malloc_params.allocations);
+ break;
+ case MEMOP_TYPE_FREE:
+ {
+ size_t allocations = objspace->malloc_params.allocations;
+ if (allocations > 0) {
+ atomic_sub_nounderflow(&objspace->malloc_params.allocations, 1);
+ }
+#if MALLOC_ALLOCATED_SIZE_CHECK
+ else {
+ GC_ASSERT(objspace->malloc_params.allocations > 0);
+ }
+#endif
+ }
+ break;
+ 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;
+};
+
+static inline size_t
+objspace_malloc_prepare(rb_objspace_t *objspace, size_t size)
+{
+ if (size == 0) size = 1;
+
+#if CALC_EXACT_MALLOC_SIZE
+ size += sizeof(struct malloc_obj_info);
+#endif
+
+ return size;
+}
+
+static bool
+malloc_during_gc_p(rb_objspace_t *objspace)
+{
+ /* malloc is not allowed during GC when we're not using multiple ractors
+ * (since ractors can run while another thread is sweeping) and when we
+ * have the GVL (since if we don't have the GVL, we'll try to acquire the
+ * GVL which will block and ensure the other thread finishes GC). */
+ return during_gc && !dont_gc_val() && !rb_gc_multi_ractor_p() && ruby_thread_has_gvl_p();
+}
+
+static inline void *
+objspace_malloc_fixup(rb_objspace_t *objspace, void *mem, size_t size, bool gc_allowed)
+{
+ size = objspace_malloc_size(objspace, mem, size);
+ objspace_malloc_increase(objspace, mem, size, 0, MEMOP_TYPE_MALLOC, gc_allowed) {}
+
+#if CALC_EXACT_MALLOC_SIZE
+ {
+ struct malloc_obj_info *info = mem;
+ info->size = size;
+ mem = info + 1;
+ }
+#endif
+
+ return mem;
+}
+
+#if defined(__GNUC__) && RUBY_DEBUG
+#define RB_BUG_INSTEAD_OF_RB_MEMERROR 1
+#endif
+
+#ifndef RB_BUG_INSTEAD_OF_RB_MEMERROR
+# define RB_BUG_INSTEAD_OF_RB_MEMERROR 0
+#endif
+
+#define GC_MEMERROR(...) \
+ ((RB_BUG_INSTEAD_OF_RB_MEMERROR+0) ? rb_bug("" __VA_ARGS__) : (void)0)
+
+#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 (RB_LIKELY((expr))) { \
+ /* Success on 1st try */ \
+ } \
+ else if (gc_allowed && !garbage_collect_with_gvl(objspace, gpr)) { \
+ /* @shyouhei thinks this doesn't happen */ \
+ GC_MEMERROR("TRY_WITH_GC: could not GC"); \
+ } \
+ else if ((expr)) { \
+ /* Success on 2nd try */ \
+ } \
+ else { \
+ GC_MEMERROR("TRY_WITH_GC: could not allocate:" \
+ "%"PRIdSIZE" bytes for %s", \
+ siz, # expr); \
+ } \
+ } while (0)
+
+static void
+check_malloc_not_in_gc(rb_objspace_t *objspace, const char *msg)
+{
+ if (RB_UNLIKELY(malloc_during_gc_p(objspace))) {
+ dont_gc_on();
+ during_gc = false;
+ rb_bug("Cannot %s during GC", msg);
+ }
+}
+
+void
+rb_gc_impl_free(void *objspace_ptr, void *ptr, size_t old_size)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ if (!ptr) {
+ /*
+ * ISO/IEC 9899 says "If ptr is a null pointer, no action occurs" since
+ * its first version. We would better follow.
+ */
+ return;
+ }
+#if CALC_EXACT_MALLOC_SIZE
+ struct malloc_obj_info *info = (struct malloc_obj_info *)ptr - 1;
+ ptr = info;
+ old_size = info->size;
+#endif
+ old_size = objspace_malloc_size(objspace, ptr, old_size);
+
+ objspace_malloc_increase(objspace, ptr, 0, old_size, MEMOP_TYPE_FREE, true) {
+ free(ptr);
+ ptr = NULL;
+ RB_DEBUG_COUNTER_INC(heap_xfree);
+ }
+}
+
+void *
+rb_gc_impl_malloc(void *objspace_ptr, size_t size, bool gc_allowed)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+ check_malloc_not_in_gc(objspace, "malloc");
+
+ void *mem;
+
+ size = objspace_malloc_prepare(objspace, size);
+ TRY_WITH_GC(size, mem = malloc(size));
+ RB_DEBUG_COUNTER_INC(heap_xmalloc);
+ if (!mem) return mem;
+ return objspace_malloc_fixup(objspace, mem, size, gc_allowed);
+}
+
+void *
+rb_gc_impl_calloc(void *objspace_ptr, size_t size, bool gc_allowed)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ if (RB_UNLIKELY(malloc_during_gc_p(objspace))) {
+ rb_warn("calloc during GC detected, this could cause crashes if it triggers another GC");
+#if RGENGC_CHECK_MODE || RUBY_DEBUG
+ rb_bug("Cannot calloc during GC");
+#endif
+ }
+
+ void *mem;
+
+ size = objspace_malloc_prepare(objspace, size);
+ TRY_WITH_GC(size, mem = calloc1(size));
+ if (!mem) return mem;
+ return objspace_malloc_fixup(objspace, mem, size, gc_allowed);
+}
+
+void *
+rb_gc_impl_realloc(void *objspace_ptr, void *ptr, size_t new_size, size_t old_size, bool gc_allowed)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ check_malloc_not_in_gc(objspace, "realloc");
+
+ void *mem;
+
+ if (!ptr) return rb_gc_impl_malloc(objspace, new_size, gc_allowed);
+
+ /*
+ * The behavior of realloc(ptr, 0) is implementation defined.
+ * Therefore we don't use realloc(ptr, 0) for portability reason.
+ * see http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_400.htm
+ */
+ if (new_size == 0) {
+ if ((mem = rb_gc_impl_malloc(objspace, 0, gc_allowed)) != NULL) {
+ /*
+ * - OpenBSD's malloc(3) man page says that when 0 is passed, it
+ * returns a non-NULL pointer to an access-protected memory page.
+ * The returned pointer cannot be read / written at all, but
+ * still be a valid argument of free().
+ *
+ * https://man.openbsd.org/malloc.3
+ *
+ * - Linux's malloc(3) man page says that it _might_ perhaps return
+ * a non-NULL pointer when its argument is 0. That return value
+ * is safe (and is expected) to be passed to free().
+ *
+ * https://man7.org/linux/man-pages/man3/malloc.3.html
+ *
+ * - As I read the implementation jemalloc's malloc() returns fully
+ * normal 16 bytes memory region when its argument is 0.
+ *
+ * - As I read the implementation musl libc's malloc() returns
+ * fully normal 32 bytes memory region when its argument is 0.
+ *
+ * - Other malloc implementations can also return non-NULL.
+ */
+ rb_gc_impl_free(objspace, ptr, old_size);
+ return mem;
+ }
+ else {
+ /*
+ * It is dangerous to return NULL here, because that could lead to
+ * RCE. Fallback to 1 byte instead of zero.
+ *
+ * https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-11932
+ */
+ new_size = 1;
+ }
+ }
+
+#if CALC_EXACT_MALLOC_SIZE
+ {
+ struct malloc_obj_info *info = (struct malloc_obj_info *)ptr - 1;
+ new_size += sizeof(struct malloc_obj_info);
+ ptr = info;
+ old_size = info->size;
+ }
+#endif
+
+ old_size = objspace_malloc_size(objspace, ptr, old_size);
+ TRY_WITH_GC(new_size, mem = RB_GNUC_EXTENSION_BLOCK(realloc(ptr, new_size)));
+ if (!mem) return mem;
+ new_size = objspace_malloc_size(objspace, mem, new_size);
+
+#if CALC_EXACT_MALLOC_SIZE
+ {
+ struct malloc_obj_info *info = mem;
+ info->size = new_size;
+ mem = info + 1;
+ }
+#endif
+
+ objspace_malloc_increase(objspace, mem, new_size, old_size, MEMOP_TYPE_REALLOC, gc_allowed);
+
+ RB_DEBUG_COUNTER_INC(heap_xrealloc);
+ return mem;
+}
+
+void
+rb_gc_impl_adjust_memory_usage(void *objspace_ptr, ssize_t diff)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ if (diff > 0) {
+ objspace_malloc_increase(objspace, 0, diff, 0, MEMOP_TYPE_REALLOC, true);
+ }
+ else if (diff < 0) {
+ objspace_malloc_increase(objspace, 0, 0, -diff, MEMOP_TYPE_REALLOC, true);
+ }
+}
+
+// TODO: move GC profiler stuff back into gc.c
+/*
+ ------------------------------ GC profiler ------------------------------
+*/
+
+#define GC_PROFILE_RECORD_DEFAULT_SIZE 100
+
+static bool
+current_process_time(struct timespec *ts)
+{
+#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_PROCESS_CPUTIME_ID)
+ {
+ static int try_clock_gettime = 1;
+ if (try_clock_gettime && clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ts) == 0) {
+ return true;
+ }
+ else {
+ try_clock_gettime = 0;
+ }
+ }
+#endif
+
+#ifdef RUSAGE_SELF
+ {
+ struct rusage usage;
+ struct timeval time;
+ if (getrusage(RUSAGE_SELF, &usage) == 0) {
+ time = usage.ru_utime;
+ ts->tv_sec = time.tv_sec;
+ ts->tv_nsec = (int32_t)time.tv_usec * 1000;
+ return true;
+ }
+ }
+#endif
+
+#ifdef _WIN32
+ {
+ FILETIME creation_time, exit_time, kernel_time, user_time;
+ ULARGE_INTEGER ui;
+
+ if (GetProcessTimes(GetCurrentProcess(),
+ &creation_time, &exit_time, &kernel_time, &user_time) != 0) {
+ 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 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, unsigned int reason)
+{
+ if (objspace->profile.run) {
+ size_t index = objspace->profile.next_index;
+ gc_profile_record *record;
+
+ /* create new record */
+ objspace->profile.next_index++;
+
+ if (!objspace->profile.records) {
+ objspace->profile.size = GC_PROFILE_RECORD_DEFAULT_SIZE;
+ objspace->profile.records = malloc(xmalloc2_size(sizeof(gc_profile_record), objspace->profile.size));
+ }
+ if (index >= objspace->profile.size) {
+ void *ptr;
+ objspace->profile.size += 1000;
+ ptr = realloc(objspace->profile.records, xmalloc2_size(sizeof(gc_profile_record), objspace->profile.size));
+ if (!ptr) rb_memerror();
+ objspace->profile.records = ptr;
+ }
+ if (!objspace->profile.records) {
+ rb_bug("gc_profile malloc or realloc miss");
+ }
+ record = objspace->profile.current_record = &objspace->profile.records[objspace->profile.next_index - 1];
+ MEMZERO(record, gc_profile_record, 1);
+
+ /* setup before-GC parameter */
+ record->flags = reason | (ruby_gc_stressful ? GPR_FLAG_STRESS : 0);
+#if MALLOC_ALLOCATED_SIZE
+ record->allocated_size = malloc_allocated_size;
+#endif
+#if GC_PROFILE_MORE_DETAIL && GC_PROFILE_DETAIL_MEMORY
+#ifdef RUSAGE_SELF
+ {
+ struct rusage usage;
+ if (getrusage(RUSAGE_SELF, &usage) == 0) {
+ record->maxrss = usage.ru_maxrss;
+ record->minflt = usage.ru_minflt;
+ record->majflt = usage.ru_majflt;
+ }
+ }
+#endif
+#endif
+ }
+}
+
+static inline void
+gc_prof_timer_start(rb_objspace_t *objspace)
+{
+ if (gc_prof_enabled(objspace)) {
+ gc_profile_record *record = gc_prof_record(objspace);
+#if GC_PROFILE_MORE_DETAIL
+ record->prepare_time = objspace->profile.prepare_time;
+#endif
+ record->gc_time = 0;
+ record->gc_invoke_time = getrusage_time();
+ }
+}
+
+static double
+elapsed_time_from(double time)
+{
+ double now = getrusage_time();
+ if (now > time) {
+ return now - time;
+ }
+ else {
+ return 0;
+ }
+}
+
+static inline void
+gc_prof_timer_stop(rb_objspace_t *objspace)
+{
+ if (gc_prof_enabled(objspace)) {
+ gc_profile_record *record = gc_prof_record(objspace);
+ record->gc_time = elapsed_time_from(record->gc_invoke_time);
+ record->gc_invoke_time -= objspace->profile.invoke_time;
+ }
+}
+
+#ifdef BUILDING_MODULAR_GC
+# define RUBY_DTRACE_GC_HOOK(name)
+#else
+# define RUBY_DTRACE_GC_HOOK(name) \
+ do {if (RUBY_DTRACE_GC_##name##_ENABLED()) RUBY_DTRACE_GC_##name();} while (0)
+#endif
+
+static inline void
+gc_prof_mark_timer_start(rb_objspace_t *objspace)
+{
+ RUBY_DTRACE_GC_HOOK(MARK_BEGIN);
+#if GC_PROFILE_MORE_DETAIL
+ if (gc_prof_enabled(objspace)) {
+ gc_prof_record(objspace)->gc_mark_time = getrusage_time();
+ }
+#endif
+}
+
+static inline void
+gc_prof_mark_timer_stop(rb_objspace_t *objspace)
+{
+ RUBY_DTRACE_GC_HOOK(MARK_END);
+#if GC_PROFILE_MORE_DETAIL
+ if (gc_prof_enabled(objspace)) {
+ gc_profile_record *record = gc_prof_record(objspace);
+ record->gc_mark_time = elapsed_time_from(record->gc_mark_time);
+ }
+#endif
+}
+
+static inline void
+gc_prof_sweep_timer_start(rb_objspace_t *objspace)
+{
+ RUBY_DTRACE_GC_HOOK(SWEEP_BEGIN);
+ if (gc_prof_enabled(objspace)) {
+ gc_profile_record *record = gc_prof_record(objspace);
+
+ if (record->gc_time > 0 || GC_PROFILE_MORE_DETAIL) {
+ objspace->profile.gc_sweep_start_time = getrusage_time();
+ }
+ }
+}
+
+static inline void
+gc_prof_sweep_timer_stop(rb_objspace_t *objspace)
+{
+ RUBY_DTRACE_GC_HOOK(SWEEP_END);
+
+ if (gc_prof_enabled(objspace)) {
+ double sweep_time;
+ gc_profile_record *record = gc_prof_record(objspace);
+
+ if (record->gc_time > 0) {
+ sweep_time = elapsed_time_from(objspace->profile.gc_sweep_start_time);
+ /* need to accumulate GC time for lazy sweep after gc() */
+ record->gc_time += sweep_time;
+ }
+ else if (GC_PROFILE_MORE_DETAIL) {
+ sweep_time = elapsed_time_from(objspace->profile.gc_sweep_start_time);
+ }
+
+#if GC_PROFILE_MORE_DETAIL
+ record->gc_sweep_time += sweep_time;
+ if (heap_pages_deferred_final) record->flags |= GPR_FLAG_HAVE_FINALIZE;
+#endif
+ if (heap_pages_deferred_final) objspace->profile.latest_gc_info |= GPR_FLAG_HAVE_FINALIZE;
+ }
+}
+
+static inline void
+gc_prof_set_malloc_info(rb_objspace_t *objspace)
+{
+#if GC_PROFILE_MORE_DETAIL
+ if (gc_prof_enabled(objspace)) {
+ gc_profile_record *record = gc_prof_record(objspace);
+ record->allocate_increase = malloc_increase;
+ record->allocate_limit = malloc_limit;
+ }
+#endif
+}
+
+static inline void
+gc_prof_set_heap_info(rb_objspace_t *objspace)
+{
+ if (gc_prof_enabled(objspace)) {
+ gc_profile_record *record = gc_prof_record(objspace);
+ size_t live = objspace->profile.total_allocated_objects_at_gc_start - total_freed_objects(objspace);
+ size_t total = objspace->profile.heap_used_at_gc_start * HEAP_PAGE_OBJ_LIMIT;
+
+#if GC_PROFILE_MORE_DETAIL
+ record->heap_use_pages = objspace->profile.heap_used_at_gc_start;
+ record->heap_live_objects = live;
+ record->heap_free_objects = total - live;
+#endif
+
+ record->heap_total_objects = total;
+ record->heap_use_size = live * BASE_SLOT_SIZE;
+ record->heap_total_size = total * BASE_SLOT_SIZE;
+ }
+}
+
+/*
+ * call-seq:
+ * GC::Profiler.clear -> nil
+ *
+ * Clears the \GC profiler data.
+ *
+ */
+
+static VALUE
+gc_profile_clear(VALUE _)
+{
+ rb_objspace_t *objspace = rb_gc_get_objspace();
+ void *p = objspace->profile.records;
+ objspace->profile.records = NULL;
+ objspace->profile.size = 0;
+ objspace->profile.next_index = 0;
+ objspace->profile.current_record = 0;
+ free(p);
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * GC::Profiler.raw_data -> [Hash, ...]
+ *
+ * Returns an Array of individual raw profile data Hashes ordered
+ * from earliest to latest by +:GC_INVOKE_TIME+.
+ *
+ * For example:
+ *
+ * [
+ * {
+ * :GC_TIME=>1.3000000000000858e-05,
+ * :GC_INVOKE_TIME=>0.010634999999999999,
+ * :HEAP_USE_SIZE=>289640,
+ * :HEAP_TOTAL_SIZE=>588960,
+ * :HEAP_TOTAL_OBJECTS=>14724,
+ * :GC_IS_MARKED=>false
+ * },
+ * # ...
+ * ]
+ *
+ * The keys mean:
+ *
+ * +:GC_TIME+::
+ * Time elapsed in seconds for this GC run
+ * +:GC_INVOKE_TIME+::
+ * Time elapsed in seconds from startup to when the GC was invoked
+ * +:HEAP_USE_SIZE+::
+ * Total bytes of heap used
+ * +:HEAP_TOTAL_SIZE+::
+ * Total size of heap in bytes
+ * +:HEAP_TOTAL_OBJECTS+::
+ * Total number of objects
+ * +:GC_IS_MARKED+::
+ * Returns +true+ if the GC is in mark phase
+ *
+ * If ruby was built with +GC_PROFILE_MORE_DETAIL+, you will also have access
+ * to the following hash keys:
+ *
+ * +:GC_MARK_TIME+::
+ * +:GC_SWEEP_TIME+::
+ * +:ALLOCATE_INCREASE+::
+ * +:ALLOCATE_LIMIT+::
+ * +:HEAP_USE_PAGES+::
+ * +:HEAP_LIVE_OBJECTS+::
+ * +:HEAP_FREE_OBJECTS+::
+ * +:HAVE_FINALIZE+::
+ *
+ */
+
+static VALUE
+gc_profile_record_get(VALUE _)
+{
+ VALUE prof;
+ VALUE gc_profile = rb_ary_new();
+ size_t i;
+ rb_objspace_t *objspace = rb_gc_get_objspace();
+
+ if (!objspace->profile.run) {
+ return Qnil;
+ }
+
+ for (i =0; i < objspace->profile.next_index; i++) {
+ gc_profile_record *record = &objspace->profile.records[i];
+
+ prof = rb_hash_new();
+ rb_hash_aset(prof, ID2SYM(rb_intern("GC_FLAGS")), gc_info_decode(objspace, rb_hash_new(), record->flags));
+ rb_hash_aset(prof, ID2SYM(rb_intern("GC_TIME")), DBL2NUM(record->gc_time));
+ rb_hash_aset(prof, ID2SYM(rb_intern("GC_INVOKE_TIME")), DBL2NUM(record->gc_invoke_time));
+ 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));
+ rb_hash_aset(prof, ID2SYM(rb_intern("GC_SWEEP_TIME")), DBL2NUM(record->gc_sweep_time));
+ rb_hash_aset(prof, ID2SYM(rb_intern("ALLOCATE_INCREASE")), SIZET2NUM(record->allocate_increase));
+ rb_hash_aset(prof, ID2SYM(rb_intern("ALLOCATE_LIMIT")), SIZET2NUM(record->allocate_limit));
+ rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_USE_PAGES")), SIZET2NUM(record->heap_use_pages));
+ rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_LIVE_OBJECTS")), SIZET2NUM(record->heap_live_objects));
+ rb_hash_aset(prof, ID2SYM(rb_intern("HEAP_FREE_OBJECTS")), SIZET2NUM(record->heap_free_objects));
+
+ 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);
+#endif
+
+#if RGENGC_PROFILE > 0
+ rb_hash_aset(prof, ID2SYM(rb_intern("OLD_OBJECTS")), SIZET2NUM(record->old_objects));
+ rb_hash_aset(prof, ID2SYM(rb_intern("REMEMBERED_NORMAL_OBJECTS")), SIZET2NUM(record->remembered_normal_objects));
+ rb_hash_aset(prof, ID2SYM(rb_intern("REMEMBERED_SHADY_OBJECTS")), SIZET2NUM(record->remembered_shady_objects));
+#endif
+ rb_ary_push(gc_profile, prof);
+ }
+
+ return gc_profile;
+}
+
+#if GC_PROFILE_MORE_DETAIL
+#define MAJOR_REASON_MAX 0x10
+
+static char *
+gc_profile_dump_major_reason(unsigned int flags, char *buff)
+{
+ unsigned int reason = flags & GPR_FLAG_MAJOR_MASK;
+ int i = 0;
+
+ if (reason == GPR_FLAG_NONE) {
+ buff[0] = '-';
+ buff[1] = 0;
+ }
+ else {
+#define C(x, s) \
+ if (reason & GPR_FLAG_MAJOR_BY_##x) { \
+ buff[i++] = #x[0]; \
+ if (i >= MAJOR_REASON_MAX) rb_bug("gc_profile_dump_major_reason: overflow"); \
+ buff[i] = 0; \
+ }
+ C(NOFREE, N);
+ C(OLDGEN, O);
+ C(SHADY, S);
+#if RGENGC_ESTIMATE_OLDMALLOC
+ C(OLDMALLOC, M);
+#endif
+#undef C
+ }
+ return buff;
+}
+#endif
+
+
+
+static void
+gc_profile_dump_on(VALUE out, VALUE (*append)(VALUE, VALUE))
+{
+ rb_objspace_t *objspace = rb_gc_get_objspace();
+ size_t count = objspace->profile.next_index;
+#ifdef MAJOR_REASON_MAX
+ char reason_str[MAJOR_REASON_MAX];
+#endif
+
+ if (objspace->profile.run && count /* > 1 */) {
+ size_t i;
+ const gc_profile_record *record;
+
+ append(out, rb_sprintf("GC %"PRIuSIZE" invokes.\n", objspace->profile.count));
+ append(out, rb_str_new_cstr("Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC Time(ms)\n"));
+
+ for (i = 0; i < count; i++) {
+ record = &objspace->profile.records[i];
+ append(out, rb_sprintf("%5"PRIuSIZE" %19.3f %20"PRIuSIZE" %20"PRIuSIZE" %20"PRIuSIZE" %30.20f\n",
+ i+1, record->gc_invoke_time, record->heap_use_size,
+ record->heap_total_size, record->heap_total_objects, record->gc_time*1000));
+ }
+
+#if GC_PROFILE_MORE_DETAIL
+ const char *str = "\n\n" \
+ "More detail.\n" \
+ "Prepare Time = Previously GC's rest sweep time\n"
+ "Index Flags Allocate Inc. Allocate Limit"
+#if CALC_EXACT_MALLOC_SIZE
+ " Allocated Size"
+#endif
+ " Use Page Mark Time(ms) Sweep Time(ms) Prepare Time(ms) LivingObj FreeObj RemovedObj EmptyObj"
+#if RGENGC_PROFILE
+ " OldgenObj RemNormObj RemShadObj"
+#endif
+#if GC_PROFILE_DETAIL_MEMORY
+ " MaxRSS(KB) MinorFLT MajorFLT"
+#endif
+ "\n";
+ append(out, rb_str_new_cstr(str));
+
+ for (i = 0; i < count; i++) {
+ record = &objspace->profile.records[i];
+ append(out, rb_sprintf("%5"PRIuSIZE" %4s/%c/%6s%c %13"PRIuSIZE" %15"PRIuSIZE
+#if CALC_EXACT_MALLOC_SIZE
+ " %15"PRIuSIZE
+#endif
+ " %9"PRIuSIZE" %17.12f %17.12f %17.12f %10"PRIuSIZE" %10"PRIuSIZE" %10"PRIuSIZE" %10"PRIuSIZE
+#if RGENGC_PROFILE
+ "%10"PRIuSIZE" %10"PRIuSIZE" %10"PRIuSIZE
+#endif
+#if GC_PROFILE_DETAIL_MEMORY
+ "%11ld %8ld %8ld"
+#endif
+
+ "\n",
+ i+1,
+ gc_profile_dump_major_reason(record->flags, reason_str),
+ (record->flags & GPR_FLAG_HAVE_FINALIZE) ? 'F' : '.',
+ (record->flags & GPR_FLAG_NEWOBJ) ? "NEWOBJ" :
+ (record->flags & GPR_FLAG_MALLOC) ? "MALLOC" :
+ (record->flags & GPR_FLAG_METHOD) ? "METHOD" :
+ (record->flags & GPR_FLAG_CAPI) ? "CAPI__" : "??????",
+ (record->flags & GPR_FLAG_STRESS) ? '!' : ' ',
+ record->allocate_increase, record->allocate_limit,
+#if CALC_EXACT_MALLOC_SIZE
+ record->allocated_size,
+#endif
+ record->heap_use_pages,
+ record->gc_mark_time*1000,
+ record->gc_sweep_time*1000,
+ record->prepare_time*1000,
+
+ record->heap_live_objects,
+ record->heap_free_objects,
+ record->removing_objects,
+ record->empty_objects
+#if RGENGC_PROFILE
+ ,
+ record->old_objects,
+ record->remembered_normal_objects,
+ record->remembered_shady_objects
+#endif
+#if GC_PROFILE_DETAIL_MEMORY
+ ,
+ record->maxrss / 1024,
+ record->minflt,
+ record->majflt
+#endif
+
+ ));
+ }
+#endif
+ }
+}
+
+/*
+ * call-seq:
+ * GC::Profiler.result -> String
+ *
+ * Returns a profile data report such as:
+ *
+ * GC 1 invokes.
+ * Index Invoke Time(sec) Use Size(byte) Total Size(byte) Total Object GC time(ms)
+ * 1 0.012 159240 212940 10647 0.00000000000001530000
+ */
+
+static VALUE
+gc_profile_result(VALUE _)
+{
+ VALUE str = rb_str_buf_new(0);
+ gc_profile_dump_on(str, rb_str_buf_append);
+ return str;
+}
+
+/*
+ * call-seq:
+ * GC::Profiler.report
+ * GC::Profiler.report(io)
+ *
+ * Writes the GC::Profiler.result to <tt>$stdout</tt> or the given IO object.
+ *
+ */
+
+static VALUE
+gc_profile_report(int argc, VALUE *argv, VALUE self)
+{
+ VALUE out;
+
+ out = (!rb_check_arity(argc, 0, 1) ? rb_stdout : argv[0]);
+ gc_profile_dump_on(out, rb_io_write);
+
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * GC::Profiler.total_time -> float
+ *
+ * The total time used for garbage collection in seconds
+ */
+
+static VALUE
+gc_profile_total_time(VALUE self)
+{
+ double time = 0;
+ rb_objspace_t *objspace = rb_gc_get_objspace();
+
+ if (objspace->profile.run && objspace->profile.next_index > 0) {
+ size_t i;
+ size_t count = objspace->profile.next_index;
+
+ for (i = 0; i < count; i++) {
+ time += objspace->profile.records[i].gc_time;
+ }
+ }
+ return DBL2NUM(time);
+}
+
+/*
+ * call-seq:
+ * GC::Profiler.enabled? -> true or false
+ *
+ * The current status of \GC profile mode.
+ */
+
+static VALUE
+gc_profile_enable_get(VALUE self)
+{
+ rb_objspace_t *objspace = rb_gc_get_objspace();
+ return objspace->profile.run ? Qtrue : Qfalse;
+}
+
+/*
+ * call-seq:
+ * GC::Profiler.enable -> nil
+ *
+ * Starts the \GC profiler.
+ *
+ */
+
+static VALUE
+gc_profile_enable(VALUE _)
+{
+ rb_objspace_t *objspace = rb_gc_get_objspace();
+ objspace->profile.run = TRUE;
+ objspace->profile.current_record = 0;
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * GC::Profiler.disable -> nil
+ *
+ * Stops the \GC profiler.
+ *
+ */
+
+static VALUE
+gc_profile_disable(VALUE _)
+{
+ rb_objspace_t *objspace = rb_gc_get_objspace();
+
+ objspace->profile.run = FALSE;
+ objspace->profile.current_record = 0;
+ return Qnil;
+}
+
+void
+rb_gc_verify_internal_consistency(void)
+{
+ gc_verify_internal_consistency(rb_gc_get_objspace());
+}
+
+/*
+ * call-seq:
+ * GC.verify_internal_consistency -> nil
+ *
+ * Verify internal consistency.
+ *
+ * This method is implementation specific.
+ * Now this method checks generational consistency
+ * if RGenGC is supported.
+ */
+static VALUE
+gc_verify_internal_consistency_m(VALUE dummy)
+{
+ rb_gc_verify_internal_consistency();
+ return Qnil;
+}
+
+#if GC_CAN_COMPILE_COMPACTION
+/*
+ * 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.
+ */
+static VALUE
+gc_set_auto_compact(VALUE _, VALUE v)
+{
+ GC_ASSERT(GC_COMPACTION_SUPPORTED);
+
+ ruby_enable_autocompact = RTEST(v);
+
+#if RGENGC_CHECK_MODE
+ ruby_autocompact_compare_func = NULL;
+
+ if (SYMBOL_P(v)) {
+ ID id = RB_SYM2ID(v);
+ if (id == rb_intern("empty")) {
+ ruby_autocompact_compare_func = compare_free_slots;
+ }
+ }
+#endif
+
+ return v;
+}
+#else
+# define gc_set_auto_compact rb_f_notimplement
+#endif
+
+#if GC_CAN_COMPILE_COMPACTION
+/*
+ * call-seq:
+ * GC.auto_compact -> true or false
+ *
+ * Returns whether or not automatic compaction has been enabled.
+ */
+static VALUE
+gc_get_auto_compact(VALUE _)
+{
+ return ruby_enable_autocompact ? Qtrue : Qfalse;
+}
+#else
+# define gc_get_auto_compact rb_f_notimplement
+#endif
+
+#if GC_CAN_COMPILE_COMPACTION
+/*
+ * call-seq:
+ * GC.latest_compact_info -> hash
+ *
+ * Returns information about object moved in the most recent \GC compaction.
+ *
+ * The returned +hash+ contains the following keys:
+ *
+ * [considered]
+ * Hash containing the type of the object as the key and the number of
+ * objects of that type that were considered for movement.
+ * [moved]
+ * Hash containing the type of the object as the key and the number of
+ * objects of that type that were actually moved.
+ * [moved_up]
+ * Hash containing the type of the object as the key and the number of
+ * objects of that type that were increased in size.
+ * [moved_down]
+ * Hash containing the type of the object as the key and the number of
+ * objects of that type that were decreased in size.
+ *
+ * Some objects can't be moved (due to pinning) so these numbers can be used to
+ * calculate compaction efficiency.
+ */
+static VALUE
+gc_compact_stats(VALUE self)
+{
+ rb_objspace_t *objspace = rb_gc_get_objspace();
+ VALUE h = rb_hash_new();
+ VALUE considered = rb_hash_new();
+ VALUE moved = rb_hash_new();
+ VALUE moved_up = rb_hash_new();
+ VALUE moved_down = rb_hash_new();
+
+ for (size_t i = 0; i < T_MASK; i++) {
+ if (objspace->rcompactor.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]));
+ }
+
+ if (objspace->rcompactor.moved_up_count_table[i]) {
+ rb_hash_aset(moved_up, type_sym(i), SIZET2NUM(objspace->rcompactor.moved_up_count_table[i]));
+ }
+
+ if (objspace->rcompactor.moved_down_count_table[i]) {
+ rb_hash_aset(moved_down, type_sym(i), SIZET2NUM(objspace->rcompactor.moved_down_count_table[i]));
+ }
+ }
+
+ rb_hash_aset(h, ID2SYM(rb_intern("considered")), considered);
+ rb_hash_aset(h, ID2SYM(rb_intern("moved")), moved);
+ rb_hash_aset(h, ID2SYM(rb_intern("moved_up")), moved_up);
+ rb_hash_aset(h, ID2SYM(rb_intern("moved_down")), moved_down);
+
+ return h;
+}
+#else
+# define gc_compact_stats rb_f_notimplement
+#endif
+
+#if GC_CAN_COMPILE_COMPACTION
+/*
+ * call-seq:
+ * GC.compact -> hash
+ *
+ * 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.
+ *
+ * The returned +hash+ contains statistics about the objects that were moved;
+ * see GC.latest_compact_info.
+ *
+ * This method is only expected to work on CRuby.
+ *
+ * To test whether \GC compaction is supported, use the idiom:
+ *
+ * GC.respond_to?(:compact)
+ */
+static VALUE
+gc_compact(VALUE self)
+{
+ rb_objspace_t *objspace = rb_gc_get_objspace();
+ int full_marking_p = gc_config_full_mark_val;
+ gc_config_full_mark_set(TRUE);
+
+ /* Run GC with compaction enabled */
+ rb_gc_impl_start(rb_gc_get_objspace(), true, true, true, true);
+ gc_config_full_mark_set(full_marking_p);
+
+ return gc_compact_stats(self);
+}
+#else
+# define gc_compact rb_f_notimplement
+#endif
+
+#if GC_CAN_COMPILE_COMPACTION
+struct desired_compaction_pages_i_data {
+ rb_objspace_t *objspace;
+ size_t required_slots[HEAP_COUNT];
+};
+
+static int
+desired_compaction_pages_i(struct heap_page *page, void *data)
+{
+ struct desired_compaction_pages_i_data *tdata = data;
+ rb_objspace_t *objspace = tdata->objspace;
+ VALUE vstart = (VALUE)page->start;
+ VALUE vend = vstart + (VALUE)(page->total_slots * page->heap->slot_size);
+
+
+ for (VALUE v = vstart; v != vend; v += page->heap->slot_size) {
+ asan_unpoisoning_object(v) {
+ /* skip T_NONEs; they won't be moved */
+ if (BUILTIN_TYPE(v) != T_NONE) {
+ rb_heap_t *dest_pool = gc_compact_destination_pool(objspace, page->heap, v);
+ size_t dest_pool_idx = dest_pool - heaps;
+ tdata->required_slots[dest_pool_idx]++;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/* 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 expands 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 self)
+{
+ static ID keywords[3] = {0};
+ if (!keywords[0]) {
+ keywords[0] = rb_intern("toward");
+ keywords[1] = rb_intern("double_heap");
+ keywords[2] = rb_intern("expand_heap");
+ }
+
+ VALUE options;
+ rb_scan_args_kw(rb_keyword_given_p(), argc, argv, ":", &options);
+
+ VALUE arguments[3] = { Qnil, Qfalse, Qfalse };
+ int kwarg_count = rb_get_kwargs(options, keywords, 0, 3, arguments);
+ bool toward_empty = kwarg_count > 0 && SYMBOL_P(arguments[0]) && SYM2ID(arguments[0]) == rb_intern("empty");
+ bool expand_heap = (kwarg_count > 1 && RTEST(arguments[1])) || (kwarg_count > 2 && RTEST(arguments[2]));
+
+ rb_objspace_t *objspace = rb_gc_get_objspace();
+
+ /* Clear the heap. */
+ rb_gc_impl_start(objspace, true, true, true, false);
+
+ unsigned int lev = RB_GC_VM_LOCK();
+ {
+ gc_rest(objspace);
+
+ /* if both double_heap and expand_heap are set, expand_heap takes precedence */
+ if (expand_heap) {
+ struct desired_compaction_pages_i_data desired_compaction = {
+ .objspace = objspace,
+ .required_slots = {0},
+ };
+ /* Work out how many objects want to be in each size pool, taking account of moves */
+ objspace_each_pages(objspace, desired_compaction_pages_i, &desired_compaction, TRUE);
+
+ /* Find out which pool has the most pages */
+ size_t max_existing_pages = 0;
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ rb_heap_t *heap = &heaps[i];
+ max_existing_pages = MAX(max_existing_pages, heap->total_pages);
+ }
+
+ /* Add pages to each size pool so that compaction is guaranteed to move every object */
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ rb_heap_t *heap = &heaps[i];
+
+ size_t pages_to_add = 0;
+ /*
+ * Step 1: Make sure every pool has the same number of pages, by adding empty pages
+ * to smaller pools. This is required to make sure the compact cursor can advance
+ * through all of the pools in `gc_sweep_compact` without hitting the "sweep &
+ * compact cursors met" condition on some pools before fully compacting others
+ */
+ pages_to_add += max_existing_pages - heap->total_pages;
+ /*
+ * Step 2: Now add additional free pages to each size pool sufficient to hold all objects
+ * that want to be in that size pool, whether moved into it or moved within it
+ */
+ objspace->heap_pages.allocatable_slots = desired_compaction.required_slots[i];
+ while (objspace->heap_pages.allocatable_slots > 0) {
+ heap_page_allocate_and_initialize(objspace, heap);
+ }
+ /*
+ * Step 3: Add two more pages so that the compact & sweep cursors will meet _after_ all objects
+ * have been moved, and not on the last iteration of the `gc_sweep_compact` loop
+ */
+ pages_to_add += 2;
+
+ for (; pages_to_add > 0; pages_to_add--) {
+ heap_page_allocate_and_initialize_force(objspace, heap);
+ }
+ }
+ }
+
+ if (toward_empty) {
+ objspace->rcompactor.compare_func = compare_free_slots;
+ }
+ }
+ RB_GC_VM_UNLOCK(lev);
+
+ rb_gc_impl_start(rb_gc_get_objspace(), true, true, true, true);
+
+ rb_objspace_reachable_objects_from_root(root_obj_check_moved_i, objspace);
+ objspace_each_objects(objspace, heap_check_moved_i, objspace, TRUE);
+
+ objspace->rcompactor.compare_func = NULL;
+
+ return gc_compact_stats(self);
+}
+#else
+# define gc_verify_compaction_references rb_f_notimplement
+#endif
+
+void
+rb_gc_impl_objspace_free(void *objspace_ptr)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ if (is_lazy_sweeping(objspace))
+ rb_bug("lazy sweeping underway when freeing object space");
+
+ free(objspace->profile.records);
+ objspace->profile.records = NULL;
+
+ for (size_t i = 0; i < rb_darray_size(objspace->heap_pages.sorted); i++) {
+ heap_page_free(objspace, rb_darray_get(objspace->heap_pages.sorted, i));
+ }
+ rb_darray_free_without_gc(objspace->heap_pages.sorted);
+ heap_pages_lomem = 0;
+ heap_pages_himem = 0;
+
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ rb_heap_t *heap = &heaps[i];
+ heap->total_pages = 0;
+ heap->total_slots = 0;
+ }
+
+ free_stack_chunks(&objspace->mark_stack);
+ mark_stack_free_cache(&objspace->mark_stack);
+
+ rb_darray_free_without_gc(objspace->weak_references);
+
+ free(objspace);
+}
+
+#if MALLOC_ALLOCATED_SIZE
+/*
+ * call-seq:
+ * GC.malloc_allocated_size -> Integer
+ *
+ * Returns the size of memory allocated by malloc().
+ *
+ * Only available if ruby was built with +CALC_EXACT_MALLOC_SIZE+.
+ */
+
+static VALUE
+gc_malloc_allocated_size(VALUE self)
+{
+ rb_objspace_t *objspace = (rb_objspace_t *)rb_gc_get_objspace();
+ return ULL2NUM(objspace->malloc_params.allocated_size);
+}
+
+/*
+ * call-seq:
+ * GC.malloc_allocations -> Integer
+ *
+ * Returns the number of malloc() allocations.
+ *
+ * Only available if ruby was built with +CALC_EXACT_MALLOC_SIZE+.
+ */
+
+static VALUE
+gc_malloc_allocations(VALUE self)
+{
+ rb_objspace_t *objspace = (rb_objspace_t *)rb_gc_get_objspace();
+ return ULL2NUM(objspace->malloc_params.allocations);
+}
+#endif
+
+void
+rb_gc_impl_before_fork(void *objspace_ptr)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ objspace->fork_vm_lock_lev = RB_GC_VM_LOCK();
+ rb_gc_vm_barrier();
+}
+
+void
+rb_gc_impl_after_fork(void *objspace_ptr, rb_pid_t pid)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ RB_GC_VM_UNLOCK(objspace->fork_vm_lock_lev);
+ objspace->fork_vm_lock_lev = 0;
+
+ if (pid == 0) { /* child process */
+ rb_gc_ractor_newobj_cache_foreach(gc_ractor_newobj_cache_clear, NULL);
+ }
+}
+
+VALUE rb_ident_hash_new_with_size(st_index_t size);
+
+#if GC_DEBUG_STRESS_TO_CLASS
+/*
+ * call-seq:
+ * GC.add_stress_to_class(class[, ...])
+ *
+ * Raises NoMemoryError when allocating an instance of the given classes.
+ *
+ */
+static VALUE
+rb_gcdebug_add_stress_to_class(int argc, VALUE *argv, VALUE self)
+{
+ rb_objspace_t *objspace = rb_gc_get_objspace();
+
+ if (!stress_to_class) {
+ set_stress_to_class(rb_ident_hash_new_with_size(argc));
+ }
+
+ for (int i = 0; i < argc; i++) {
+ VALUE klass = argv[i];
+ rb_hash_aset(stress_to_class, klass, Qtrue);
+ }
+
+ return self;
+}
+
+/*
+ * call-seq:
+ * GC.remove_stress_to_class(class[, ...])
+ *
+ * No longer raises NoMemoryError when allocating an instance of the
+ * given classes.
+ *
+ */
+static VALUE
+rb_gcdebug_remove_stress_to_class(int argc, VALUE *argv, VALUE self)
+{
+ rb_objspace_t *objspace = rb_gc_get_objspace();
+
+ if (stress_to_class) {
+ for (int i = 0; i < argc; ++i) {
+ rb_hash_delete(stress_to_class, argv[i]);
+ }
+
+ if (rb_hash_size(stress_to_class) == 0) {
+ stress_to_class = 0;
+ }
+ }
+
+ return Qnil;
+}
+#endif
+
+void *
+rb_gc_impl_objspace_alloc(void)
+{
+ rb_objspace_t *objspace = calloc1(sizeof(rb_objspace_t));
+
+ return objspace;
+}
+
+void
+rb_gc_impl_objspace_init(void *objspace_ptr)
+{
+ rb_objspace_t *objspace = objspace_ptr;
+
+ gc_config_full_mark_set(TRUE);
+
+ objspace->flags.measure_gc = true;
+ malloc_limit = gc_params.malloc_limit_min;
+ objspace->finalize_deferred_pjob = rb_postponed_job_preregister(0, gc_finalize_deferred, objspace);
+ if (objspace->finalize_deferred_pjob == POSTPONED_JOB_HANDLE_INVALID) {
+ rb_bug("Could not preregister postponed job for GC");
+ }
+
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ rb_heap_t *heap = &heaps[i];
+
+ heap->slot_size = (1 << i) * BASE_SLOT_SIZE;
+
+ // Bitmask with every (1 << i)th bit set, representing aligned slot positions
+ static const bits_t slot_bits_masks[] = {
+ ~(bits_t)0, // i=0: every 1st bit
+ (bits_t)0x5555555555555555ULL, // i=1: every 2nd bit
+ (bits_t)0x1111111111111111ULL, // i=2: every 4th bit
+ (bits_t)0x0101010101010101ULL, // i=3: every 8th bit
+ (bits_t)0x0001000100010001ULL, // i=4: every 16th bit
+ };
+ GC_ASSERT(HEAP_COUNT == sizeof(slot_bits_masks) / sizeof(slot_bits_masks[0]));
+ heap->slot_bits_mask = slot_bits_masks[i];
+
+ ccan_list_head_init(&heap->pages);
+ }
+
+ rb_darray_make_without_gc(&objspace->heap_pages.sorted, 0);
+ rb_darray_make_without_gc(&objspace->weak_references, 0);
+
+ // TODO: debug why on Windows Ruby crashes on boot when GC is on.
+#ifdef _WIN32
+ dont_gc_on();
+#endif
+
+#if defined(INIT_HEAP_PAGE_ALLOC_USE_MMAP)
+ /* Need to determine if we can use mmap at runtime. */
+ heap_page_alloc_use_mmap = INIT_HEAP_PAGE_ALLOC_USE_MMAP;
+#endif
+#if RGENGC_ESTIMATE_OLDMALLOC
+ objspace->rgengc.oldmalloc_increase_limit = gc_params.oldmalloc_limit_min;
+#endif
+ /* Set size pools allocatable pages. */
+ for (int i = 0; i < HEAP_COUNT; i++) {
+ /* Set the default value of heap_init_slots. */
+ gc_params.heap_init_slots[i] = GC_HEAP_INIT_SLOTS;
+ }
+
+ init_mark_stack(&objspace->mark_stack);
+
+ objspace->profile.invoke_time = getrusage_time();
+ finalizer_table = st_init_numtable();
+}
+
+void
+rb_gc_impl_init(void)
+{
+ VALUE gc_constants = rb_hash_new();
+ rb_hash_aset(gc_constants, ID2SYM(rb_intern("DEBUG")), GC_DEBUG ? Qtrue : Qfalse);
+ rb_hash_aset(gc_constants, ID2SYM(rb_intern("BASE_SLOT_SIZE")), SIZET2NUM(BASE_SLOT_SIZE - RVALUE_OVERHEAD));
+ rb_hash_aset(gc_constants, ID2SYM(rb_intern("RBASIC_SIZE")), SIZET2NUM(sizeof(struct RBasic)));
+ rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVALUE_OVERHEAD")), SIZET2NUM(RVALUE_OVERHEAD));
+ 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_SIZE")), SIZET2NUM(HEAP_PAGE_SIZE));
+ rb_hash_aset(gc_constants, ID2SYM(rb_intern("HEAP_COUNT")), LONG2FIX(HEAP_COUNT));
+ rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVARGC_MAX_ALLOCATE_SIZE")), LONG2FIX(heap_slot_size(HEAP_COUNT - 1)));
+ rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVALUE_OLD_AGE")), LONG2FIX(RVALUE_OLD_AGE));
+ if (RB_BUG_INSTEAD_OF_RB_MEMERROR+0) {
+ rb_hash_aset(gc_constants, ID2SYM(rb_intern("RB_BUG_INSTEAD_OF_RB_MEMERROR")), Qtrue);
+ }
+ OBJ_FREEZE(gc_constants);
+ /* Internal constants in the garbage collector. */
+ rb_define_const(rb_mGC, "INTERNAL_CONSTANTS", gc_constants);
+
+ if (GC_COMPACTION_SUPPORTED) {
+ rb_define_singleton_method(rb_mGC, "compact", gc_compact, 0);
+ rb_define_singleton_method(rb_mGC, "auto_compact", gc_get_auto_compact, 0);
+ rb_define_singleton_method(rb_mGC, "auto_compact=", gc_set_auto_compact, 1);
+ rb_define_singleton_method(rb_mGC, "latest_compact_info", gc_compact_stats, 0);
+ rb_define_singleton_method(rb_mGC, "verify_compaction_references", gc_verify_compaction_references, -1);
+ }
+ else {
+ rb_define_singleton_method(rb_mGC, "compact", rb_f_notimplement, 0);
+ rb_define_singleton_method(rb_mGC, "auto_compact", rb_f_notimplement, 0);
+ rb_define_singleton_method(rb_mGC, "auto_compact=", rb_f_notimplement, 1);
+ rb_define_singleton_method(rb_mGC, "latest_compact_info", rb_f_notimplement, 0);
+ rb_define_singleton_method(rb_mGC, "verify_compaction_references", rb_f_notimplement, -1);
+ }
+
+#if GC_DEBUG_STRESS_TO_CLASS
+ rb_define_singleton_method(rb_mGC, "add_stress_to_class", rb_gcdebug_add_stress_to_class, -1);
+ rb_define_singleton_method(rb_mGC, "remove_stress_to_class", rb_gcdebug_remove_stress_to_class, -1);
+#endif
+
+ /* internal methods */
+ rb_define_singleton_method(rb_mGC, "verify_internal_consistency", gc_verify_internal_consistency_m, 0);
+
+#if MALLOC_ALLOCATED_SIZE
+ rb_define_singleton_method(rb_mGC, "malloc_allocated_size", gc_malloc_allocated_size, 0);
+ rb_define_singleton_method(rb_mGC, "malloc_allocations", gc_malloc_allocations, 0);
+#endif
+
+ VALUE rb_mProfiler = rb_define_module_under(rb_mGC, "Profiler");
+ rb_define_singleton_method(rb_mProfiler, "enabled?", gc_profile_enable_get, 0);
+ rb_define_singleton_method(rb_mProfiler, "enable", gc_profile_enable, 0);
+ rb_define_singleton_method(rb_mProfiler, "raw_data", gc_profile_record_get, 0);
+ rb_define_singleton_method(rb_mProfiler, "disable", gc_profile_disable, 0);
+ rb_define_singleton_method(rb_mProfiler, "clear", gc_profile_clear, 0);
+ rb_define_singleton_method(rb_mProfiler, "result", gc_profile_result, 0);
+ rb_define_singleton_method(rb_mProfiler, "report", gc_profile_report, -1);
+ rb_define_singleton_method(rb_mProfiler, "total_time", gc_profile_total_time, 0);
+
+ {
+ VALUE opts;
+ /* \GC build options */
+ rb_define_const(rb_mGC, "OPTS", opts = rb_ary_new());
+#define OPT(o) if (o) rb_ary_push(opts, rb_interned_str(#o, sizeof(#o) - 1))
+ OPT(GC_DEBUG);
+ OPT(USE_RGENGC);
+ OPT(RGENGC_DEBUG);
+ OPT(RGENGC_CHECK_MODE);
+ OPT(RGENGC_PROFILE);
+ OPT(RGENGC_ESTIMATE_OLDMALLOC);
+ OPT(GC_PROFILE_MORE_DETAIL);
+ OPT(GC_ENABLE_LAZY_SWEEP);
+ OPT(CALC_EXACT_MALLOC_SIZE);
+ OPT(MALLOC_ALLOCATED_SIZE);
+ OPT(MALLOC_ALLOCATED_SIZE_CHECK);
+ OPT(GC_PROFILE_DETAIL_MEMORY);
+ OPT(GC_COMPACTION_SUPPORTED);
+#undef OPT
+ OBJ_FREEZE(opts);
+ }
+}
diff --git a/gc/default/extconf.rb b/gc/default/extconf.rb
new file mode 100644
index 0000000000..2940a4c962
--- /dev/null
+++ b/gc/default/extconf.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+require_relative "../extconf_base"
+
+create_gc_makefile("default")
diff --git a/gc/extconf_base.rb b/gc/extconf_base.rb
new file mode 100644
index 0000000000..2a224b9b0e
--- /dev/null
+++ b/gc/extconf_base.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+require "mkmf"
+
+srcdir = File.join(__dir__, "..")
+$INCFLAGS << " -I#{srcdir}"
+
+$CPPFLAGS << " -DBUILDING_MODULAR_GC"
+
+append_cflags("-fPIC")
+
+def create_gc_makefile(name, &block)
+ create_makefile("librubygc.#{name}", &block)
+end
diff --git a/gc/gc.h b/gc/gc.h
new file mode 100644
index 0000000000..097ddb9394
--- /dev/null
+++ b/gc/gc.h
@@ -0,0 +1,265 @@
+#ifndef GC_GC_H
+#define GC_GC_H
+/**
+ * @author Ruby developers <ruby-core@ruby-lang.org>
+ * @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 Private header for the default GC and other GC implementations
+ * first introduced for [Feature #20470].
+ */
+#include "ruby/ruby.h"
+
+#if USE_MODULAR_GC
+#include "ruby/thread_native.h"
+
+struct rb_gc_vm_context {
+ rb_nativethread_lock_t lock;
+
+ struct rb_execution_context_struct *ec;
+};
+#endif
+
+typedef int (*vm_table_foreach_callback_func)(VALUE value, void *data);
+typedef int (*vm_table_update_callback_func)(VALUE *value, void *data);
+
+enum rb_gc_vm_weak_tables {
+ RB_GC_VM_CI_TABLE,
+ RB_GC_VM_OVERLOADED_CME_TABLE,
+ RB_GC_VM_GLOBAL_SYMBOLS_TABLE,
+ RB_GC_VM_ID2REF_TABLE,
+ RB_GC_VM_GENERIC_FIELDS_TABLE,
+ RB_GC_VM_FROZEN_STRINGS_TABLE,
+ RB_GC_VM_CC_REFINEMENT_TABLE,
+ RB_GC_VM_WEAK_TABLE_COUNT
+};
+
+#define RB_GC_VM_LOCK() rb_gc_vm_lock(__FILE__, __LINE__)
+#define RB_GC_VM_UNLOCK(lev) rb_gc_vm_unlock(lev, __FILE__, __LINE__)
+#define RB_GC_CR_LOCK() rb_gc_cr_lock(__FILE__, __LINE__)
+#define RB_GC_CR_UNLOCK(lev) rb_gc_cr_unlock(lev, __FILE__, __LINE__)
+#define RB_GC_VM_LOCK_NO_BARRIER() rb_gc_vm_lock_no_barrier(__FILE__, __LINE__)
+#define RB_GC_VM_UNLOCK_NO_BARRIER(lev) rb_gc_vm_unlock_no_barrier(lev, __FILE__, __LINE__)
+
+#if USE_MODULAR_GC
+# define MODULAR_GC_FN
+#else
+// This takes advantage of internal linkage winning when appearing first.
+// See C99 6.2.2p4.
+# define MODULAR_GC_FN static
+#endif
+
+#if USE_MODULAR_GC
+RUBY_SYMBOL_EXPORT_BEGIN
+#endif
+
+// These functions cannot be defined as static because they are used by other
+// files in Ruby.
+size_t rb_size_mul_or_raise(size_t x, size_t y, VALUE exc);
+void rb_objspace_reachable_objects_from(VALUE obj, void (func)(VALUE, void *), void *data);
+const char *rb_raw_obj_info(char *const buff, const size_t buff_size, VALUE obj);
+const char *rb_obj_info(VALUE obj);
+size_t rb_obj_memsize_of(VALUE obj);
+bool ruby_free_at_exit_p(void);
+void rb_objspace_reachable_objects_from_root(void (func)(const char *category, VALUE, void *), void *passing_data);
+void rb_gc_verify_shareable(VALUE);
+
+MODULAR_GC_FN unsigned int rb_gc_vm_lock(const char *file, int line);
+MODULAR_GC_FN void rb_gc_vm_unlock(unsigned int lev, const char *file, int line);
+MODULAR_GC_FN unsigned int rb_gc_cr_lock(const char *file, int line);
+MODULAR_GC_FN void rb_gc_cr_unlock(unsigned int lev, const char *file, int line);
+MODULAR_GC_FN unsigned int rb_gc_vm_lock_no_barrier(const char *file, int line);
+MODULAR_GC_FN void rb_gc_vm_unlock_no_barrier(unsigned int lev, const char *file, int line);
+MODULAR_GC_FN void rb_gc_vm_barrier(void);
+MODULAR_GC_FN size_t rb_gc_obj_optimal_size(VALUE obj);
+MODULAR_GC_FN void rb_gc_mark_children(void *objspace, VALUE obj);
+MODULAR_GC_FN void rb_gc_vm_weak_table_foreach(vm_table_foreach_callback_func callback, vm_table_update_callback_func update_callback, void *data, bool weak_only, enum rb_gc_vm_weak_tables table);
+MODULAR_GC_FN void rb_gc_update_object_references(void *objspace, VALUE obj);
+MODULAR_GC_FN void rb_gc_update_vm_references(void *objspace);
+MODULAR_GC_FN void rb_gc_event_hook(VALUE obj, rb_event_flag_t event);
+MODULAR_GC_FN void *rb_gc_get_objspace(void);
+MODULAR_GC_FN void rb_gc_run_obj_finalizer(VALUE objid, long count, VALUE (*callback)(long i, void *data), void *data);
+MODULAR_GC_FN void rb_gc_set_pending_interrupt(void);
+MODULAR_GC_FN void rb_gc_unset_pending_interrupt(void);
+MODULAR_GC_FN void rb_gc_obj_free_vm_weak_references(VALUE obj);
+MODULAR_GC_FN bool rb_gc_obj_free(void *objspace, VALUE obj);
+MODULAR_GC_FN void rb_gc_save_machine_context(void);
+MODULAR_GC_FN void rb_gc_mark_roots(void *objspace, const char **categoryp);
+MODULAR_GC_FN void rb_gc_ractor_newobj_cache_foreach(void (*func)(void *cache, void *data), void *data);
+MODULAR_GC_FN bool rb_gc_multi_ractor_p(void);
+MODULAR_GC_FN bool rb_gc_shutdown_call_finalizer_p(VALUE obj);
+MODULAR_GC_FN uint32_t rb_gc_get_shape(VALUE obj);
+MODULAR_GC_FN void rb_gc_set_shape(VALUE obj, uint32_t shape_id);
+MODULAR_GC_FN uint32_t rb_gc_rebuild_shape(VALUE obj, size_t heap_id);
+MODULAR_GC_FN void rb_gc_prepare_heap_process_object(VALUE obj);
+MODULAR_GC_FN bool rb_memerror_reentered(void);
+MODULAR_GC_FN bool rb_obj_id_p(VALUE);
+MODULAR_GC_FN void rb_gc_before_updating_jit_code(void);
+MODULAR_GC_FN void rb_gc_after_updating_jit_code(void);
+MODULAR_GC_FN bool rb_gc_obj_shareable_p(VALUE);
+MODULAR_GC_FN void rb_gc_rp(VALUE);
+MODULAR_GC_FN void rb_gc_handle_weak_references(VALUE obj);
+
+#if USE_MODULAR_GC
+MODULAR_GC_FN bool rb_gc_event_hook_required_p(rb_event_flag_t event);
+MODULAR_GC_FN void *rb_gc_get_ractor_newobj_cache(void);
+MODULAR_GC_FN void rb_gc_initialize_vm_context(struct rb_gc_vm_context *context);
+MODULAR_GC_FN void rb_gc_worker_thread_set_vm_context(struct rb_gc_vm_context *context);
+MODULAR_GC_FN void rb_gc_worker_thread_unset_vm_context(struct rb_gc_vm_context *context);
+MODULAR_GC_FN void rb_gc_move_obj_during_marking(VALUE from, VALUE to);
+MODULAR_GC_FN void rb_gc_print_backtrace();
+#endif
+
+#if USE_MODULAR_GC
+RUBY_SYMBOL_EXPORT_END
+#endif
+
+void rb_ractor_finish_marking(void);
+
+// -------------------Private section begin------------------------
+// Functions in this section are private to the default GC and gc.c
+
+#ifdef BUILDING_MODULAR_GC
+RBIMPL_WARNING_PUSH()
+RBIMPL_WARNING_IGNORED(-Wunused-function)
+#endif
+
+/* RGENGC_CHECK_MODE
+ * 0: disable all assertions
+ * 1: enable assertions (to debug RGenGC)
+ * 2: enable internal consistency check at each GC (for debugging)
+ * 3: enable internal consistency check at each GC steps (for debugging)
+ * 4: enable liveness check
+ * 5: show all references
+ */
+#ifndef RGENGC_CHECK_MODE
+# define RGENGC_CHECK_MODE 0
+#endif
+
+#ifndef GC_ASSERT
+# define GC_ASSERT(expr, ...) RUBY_ASSERT_MESG_WHEN(RGENGC_CHECK_MODE > 0, expr, #expr RBIMPL_VA_OPT_ARGS(__VA_ARGS__))
+#endif
+
+static int
+hash_foreach_replace_value(st_data_t key, st_data_t value, st_data_t argp, int error)
+{
+ if (rb_gc_location((VALUE)value) != (VALUE)value) {
+ return ST_REPLACE;
+ }
+ return ST_CONTINUE;
+}
+
+static int
+hash_replace_ref_value(st_data_t *key, st_data_t *value, st_data_t argp, int existing)
+{
+ *value = rb_gc_location((VALUE)*value);
+
+ return ST_CONTINUE;
+}
+
+static void
+gc_ref_update_table_values_only(st_table *tbl)
+{
+ if (!tbl || tbl->num_entries == 0) return;
+
+ if (st_foreach_with_replace(tbl, hash_foreach_replace_value, hash_replace_ref_value, 0)) {
+ rb_raise(rb_eRuntimeError, "hash modified during iteration");
+ }
+}
+
+static int
+gc_mark_tbl_no_pin_i(st_data_t key, st_data_t value, st_data_t data)
+{
+ rb_gc_mark_movable((VALUE)value);
+
+ return ST_CONTINUE;
+}
+
+static int
+hash_foreach_replace(st_data_t key, st_data_t value, st_data_t argp, int error)
+{
+ if (rb_gc_location((VALUE)key) != (VALUE)key) {
+ return ST_REPLACE;
+ }
+
+ if (rb_gc_location((VALUE)value) != (VALUE)value) {
+ return ST_REPLACE;
+ }
+
+ return ST_CONTINUE;
+}
+
+static int
+hash_replace_ref(st_data_t *key, st_data_t *value, st_data_t argp, int existing)
+{
+ if (rb_gc_location((VALUE)*key) != (VALUE)*key) {
+ *key = rb_gc_location((VALUE)*key);
+ }
+
+ if (rb_gc_location((VALUE)*value) != (VALUE)*value) {
+ *value = rb_gc_location((VALUE)*value);
+ }
+
+ return ST_CONTINUE;
+}
+
+static void
+gc_update_table_refs(st_table *tbl)
+{
+ if (!tbl || tbl->num_entries == 0) return;
+
+ if (st_foreach_with_replace(tbl, hash_foreach_replace, hash_replace_ref, 0)) {
+ rb_raise(rb_eRuntimeError, "hash modified during iteration");
+ }
+}
+
+static inline size_t
+xmalloc2_size(const size_t count, const size_t elsize)
+{
+ return rb_size_mul_or_raise(count, elsize, rb_eArgError);
+}
+
+static VALUE
+type_sym(size_t type)
+{
+ switch (type) {
+#define COUNT_TYPE(t) case (t): return ID2SYM(rb_intern(#t)); break;
+ COUNT_TYPE(T_NONE);
+ COUNT_TYPE(T_OBJECT);
+ COUNT_TYPE(T_CLASS);
+ COUNT_TYPE(T_MODULE);
+ COUNT_TYPE(T_FLOAT);
+ COUNT_TYPE(T_STRING);
+ COUNT_TYPE(T_REGEXP);
+ COUNT_TYPE(T_ARRAY);
+ COUNT_TYPE(T_HASH);
+ COUNT_TYPE(T_STRUCT);
+ COUNT_TYPE(T_BIGNUM);
+ COUNT_TYPE(T_FILE);
+ COUNT_TYPE(T_DATA);
+ COUNT_TYPE(T_MATCH);
+ COUNT_TYPE(T_COMPLEX);
+ COUNT_TYPE(T_RATIONAL);
+ COUNT_TYPE(T_NIL);
+ COUNT_TYPE(T_TRUE);
+ COUNT_TYPE(T_FALSE);
+ COUNT_TYPE(T_SYMBOL);
+ COUNT_TYPE(T_FIXNUM);
+ COUNT_TYPE(T_IMEMO);
+ COUNT_TYPE(T_UNDEF);
+ COUNT_TYPE(T_NODE);
+ COUNT_TYPE(T_ICLASS);
+ COUNT_TYPE(T_ZOMBIE);
+ COUNT_TYPE(T_MOVED);
+#undef COUNT_TYPE
+ default: return SIZET2NUM(type); break;
+ }
+}
+
+#ifdef BUILDING_MODULAR_GC
+RBIMPL_WARNING_POP()
+#endif
+// -------------------Private section end------------------------
+
+#endif
diff --git a/gc/gc_impl.h b/gc/gc_impl.h
new file mode 100644
index 0000000000..7898316a75
--- /dev/null
+++ b/gc/gc_impl.h
@@ -0,0 +1,126 @@
+#ifndef GC_GC_IMPL_H
+#define GC_GC_IMPL_H
+/**
+ * @author Ruby developers <ruby-core@ruby-lang.org>
+ * @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 Header for GC implementations introduced in [Feature #20470].
+ */
+#include "ruby/ruby.h"
+
+#ifndef RB_GC_OBJECT_METADATA_ENTRY_DEFINED
+# define RB_GC_OBJECT_METADATA_ENTRY_DEFINED
+struct rb_gc_object_metadata_entry {
+ ID name;
+ VALUE val;
+};
+#endif
+
+#ifdef BUILDING_MODULAR_GC
+# define GC_IMPL_FN
+#else
+// `GC_IMPL_FN` is an implementation detail of `!USE_MODULAR_GC` builds
+// to have the default GC in the same translation unit as gc.c for
+// the sake of optimizer visibility. It expands to nothing unless
+// you're the default GC.
+//
+// For the default GC, do not copy-paste this when implementing
+// these functions. This takes advantage of internal linkage winning
+// when appearing first. See C99 6.2.2p4.
+# define GC_IMPL_FN static
+#endif
+
+// Bootup
+GC_IMPL_FN void *rb_gc_impl_objspace_alloc(void);
+GC_IMPL_FN void rb_gc_impl_objspace_init(void *objspace_ptr);
+GC_IMPL_FN void *rb_gc_impl_ractor_cache_alloc(void *objspace_ptr, void *ractor);
+GC_IMPL_FN void rb_gc_impl_set_params(void *objspace_ptr);
+GC_IMPL_FN void rb_gc_impl_init(void);
+GC_IMPL_FN size_t *rb_gc_impl_heap_sizes(void *objspace_ptr);
+// Shutdown
+GC_IMPL_FN void rb_gc_impl_shutdown_free_objects(void *objspace_ptr);
+GC_IMPL_FN void rb_gc_impl_objspace_free(void *objspace_ptr);
+GC_IMPL_FN void rb_gc_impl_ractor_cache_free(void *objspace_ptr, void *cache);
+// GC
+GC_IMPL_FN void rb_gc_impl_start(void *objspace_ptr, bool full_mark, bool immediate_mark, bool immediate_sweep, bool compact);
+GC_IMPL_FN bool rb_gc_impl_during_gc_p(void *objspace_ptr);
+GC_IMPL_FN void rb_gc_impl_prepare_heap(void *objspace_ptr);
+GC_IMPL_FN void rb_gc_impl_gc_enable(void *objspace_ptr);
+GC_IMPL_FN void rb_gc_impl_gc_disable(void *objspace_ptr, bool finish_current_gc);
+GC_IMPL_FN bool rb_gc_impl_gc_enabled_p(void *objspace_ptr);
+GC_IMPL_FN void rb_gc_impl_stress_set(void *objspace_ptr, VALUE flag);
+GC_IMPL_FN VALUE rb_gc_impl_stress_get(void *objspace_ptr);
+GC_IMPL_FN VALUE rb_gc_impl_config_get(void *objspace_ptr);
+GC_IMPL_FN void rb_gc_impl_config_set(void *objspace_ptr, VALUE hash);
+// Object allocation
+GC_IMPL_FN VALUE rb_gc_impl_new_obj(void *objspace_ptr, void *cache_ptr, VALUE klass, VALUE flags, bool wb_protected, size_t alloc_size);
+GC_IMPL_FN size_t rb_gc_impl_obj_slot_size(VALUE obj);
+GC_IMPL_FN size_t rb_gc_impl_heap_id_for_size(void *objspace_ptr, size_t size);
+GC_IMPL_FN bool rb_gc_impl_size_allocatable_p(size_t size);
+// Malloc
+/*
+ * BEWARE: These functions may or may not run under GVL.
+ *
+ * You might want to make them thread-safe.
+ * Garbage collecting inside is possible if and only if you
+ * already have GVL. Also raising exceptions without one is a
+ * total disaster.
+ *
+ * When you absolutely cannot allocate the requested amount of
+ * memory just return NULL (with appropriate errno set).
+ * The caller side takes care of that situation.
+ */
+GC_IMPL_FN void *rb_gc_impl_malloc(void *objspace_ptr, size_t size, bool gc_allowed);
+GC_IMPL_FN void *rb_gc_impl_calloc(void *objspace_ptr, size_t size, bool gc_allowed);
+GC_IMPL_FN void *rb_gc_impl_realloc(void *objspace_ptr, void *ptr, size_t new_size, size_t old_size, bool gc_allowed);
+GC_IMPL_FN void rb_gc_impl_free(void *objspace_ptr, void *ptr, size_t old_size);
+GC_IMPL_FN void rb_gc_impl_adjust_memory_usage(void *objspace_ptr, ssize_t diff);
+// Marking
+GC_IMPL_FN void rb_gc_impl_mark(void *objspace_ptr, VALUE obj);
+GC_IMPL_FN void rb_gc_impl_mark_and_move(void *objspace_ptr, VALUE *ptr);
+GC_IMPL_FN void rb_gc_impl_mark_and_pin(void *objspace_ptr, VALUE obj);
+GC_IMPL_FN void rb_gc_impl_mark_maybe(void *objspace_ptr, VALUE obj);
+// Weak references
+GC_IMPL_FN void rb_gc_impl_declare_weak_references(void *objspace_ptr, VALUE obj);
+GC_IMPL_FN bool rb_gc_impl_handle_weak_references_alive_p(void *objspace_ptr, VALUE obj);
+// Compaction
+GC_IMPL_FN void rb_gc_impl_register_pinning_obj(void *objspace_ptr, VALUE obj);
+GC_IMPL_FN bool rb_gc_impl_object_moved_p(void *objspace_ptr, VALUE obj);
+GC_IMPL_FN VALUE rb_gc_impl_location(void *objspace_ptr, VALUE value);
+// Write barriers
+GC_IMPL_FN void rb_gc_impl_writebarrier(void *objspace_ptr, VALUE a, VALUE b);
+GC_IMPL_FN void rb_gc_impl_writebarrier_unprotect(void *objspace_ptr, VALUE obj);
+GC_IMPL_FN void rb_gc_impl_writebarrier_remember(void *objspace_ptr, VALUE obj);
+// Heap walking
+GC_IMPL_FN void rb_gc_impl_each_objects(void *objspace_ptr, int (*callback)(void *, void *, size_t, void *), void *data);
+GC_IMPL_FN void rb_gc_impl_each_object(void *objspace_ptr, void (*func)(VALUE obj, void *data), void *data);
+// Finalizers
+GC_IMPL_FN void rb_gc_impl_make_zombie(void *objspace_ptr, VALUE obj, void (*dfree)(void *), void *data);
+GC_IMPL_FN VALUE rb_gc_impl_define_finalizer(void *objspace_ptr, VALUE obj, VALUE block);
+GC_IMPL_FN void rb_gc_impl_undefine_finalizer(void *objspace_ptr, VALUE obj);
+GC_IMPL_FN void rb_gc_impl_copy_finalizer(void *objspace_ptr, VALUE dest, VALUE obj);
+GC_IMPL_FN void rb_gc_impl_shutdown_call_finalizer(void *objspace_ptr);
+// Forking
+GC_IMPL_FN void rb_gc_impl_before_fork(void *objspace_ptr);
+GC_IMPL_FN void rb_gc_impl_after_fork(void *objspace_ptr, rb_pid_t pid);
+// Statistics
+GC_IMPL_FN void rb_gc_impl_set_measure_total_time(void *objspace_ptr, VALUE flag);
+GC_IMPL_FN bool rb_gc_impl_get_measure_total_time(void *objspace_ptr);
+GC_IMPL_FN unsigned long long rb_gc_impl_get_total_time(void *objspace_ptr);
+GC_IMPL_FN size_t rb_gc_impl_gc_count(void *objspace_ptr);
+GC_IMPL_FN VALUE rb_gc_impl_latest_gc_info(void *objspace_ptr, VALUE key);
+GC_IMPL_FN VALUE rb_gc_impl_stat(void *objspace_ptr, VALUE hash_or_sym);
+GC_IMPL_FN VALUE rb_gc_impl_stat_heap(void *objspace_ptr, VALUE heap_name, VALUE hash_or_sym);
+GC_IMPL_FN const char *rb_gc_impl_active_gc_name(void);
+// Miscellaneous
+GC_IMPL_FN struct rb_gc_object_metadata_entry *rb_gc_impl_object_metadata(void *objspace_ptr, VALUE obj);
+GC_IMPL_FN bool rb_gc_impl_pointer_to_heap_p(void *objspace_ptr, const void *ptr);
+GC_IMPL_FN bool rb_gc_impl_garbage_object_p(void *objspace_ptr, VALUE obj);
+GC_IMPL_FN void rb_gc_impl_set_event_hook(void *objspace_ptr, const rb_event_flag_t event);
+GC_IMPL_FN void rb_gc_impl_copy_attributes(void *objspace_ptr, VALUE dest, VALUE obj);
+
+#undef GC_IMPL_FN
+
+#endif
diff --git a/gc/mmtk/.gitignore b/gc/mmtk/.gitignore
new file mode 100644
index 0000000000..eb5a316cbd
--- /dev/null
+++ b/gc/mmtk/.gitignore
@@ -0,0 +1 @@
+target
diff --git a/gc/mmtk/Cargo.lock b/gc/mmtk/Cargo.lock
new file mode 100644
index 0000000000..56259d46d6
--- /dev/null
+++ b/gc/mmtk/Cargo.lock
@@ -0,0 +1,1108 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "anstream"
+version = "0.6.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is_terminal_polyfill",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6680de5231bd6ee4c6191b8a1325daa282b415391ec9d3a37bd34f2060dc73fa"
+dependencies = [
+ "anstyle",
+ "once_cell_polyfill",
+ "windows-sys",
+]
+
+[[package]]
+name = "atomic"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d818003e740b63afc82337e3160717f4f63078720a810b7b903e70a5d1d2994"
+dependencies = [
+ "bytemuck",
+]
+
+[[package]]
+name = "atomic-traits"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "707f750b93bd1b739cf9ddf85f8fe7c97a4a62c60ccf8b6f232514bd9103bedc"
+dependencies = [
+ "cfg-if",
+ "rustc_version",
+]
+
+[[package]]
+name = "atomic_refcell"
+version = "0.1.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41e67cd8309bbd06cd603a9e693a784ac2e5d1e955f11286e355089fcab3047c"
+
+[[package]]
+name = "autocfg"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
+
+[[package]]
+name = "bitflags"
+version = "2.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
+
+[[package]]
+name = "built"
+version = "0.7.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56ed6191a7e78c36abdb16ab65341eefd73d64d303fffccdbb00d51e4205967b"
+dependencies = [
+ "git2",
+]
+
+[[package]]
+name = "bytemuck"
+version = "1.23.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9134a6ef01ce4b366b50689c94f82c14bc72bc5d0386829828a2e2752ef7958c"
+dependencies = [
+ "bytemuck_derive",
+]
+
+[[package]]
+name = "bytemuck_derive"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.101",
+]
+
+[[package]]
+name = "cc"
+version = "1.2.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "16595d3be041c03b09d08d0858631facccee9221e579704070e6e9e4915d3bc7"
+dependencies = [
+ "jobserver",
+ "libc",
+ "shlex",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "colorchoice"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
+
+[[package]]
+name = "crossbeam"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-epoch",
+ "crossbeam-queue",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
+dependencies = [
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-queue"
+version = "0.3.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115"
+dependencies = [
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
+
+[[package]]
+name = "delegate"
+version = "0.13.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9b6483c2bbed26f97861cf57651d4f2b731964a28cd2257f934a4b452480d21"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.101",
+]
+
+[[package]]
+name = "downcast-rs"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea8a8b81cacc08888170eef4d13b775126db426d0b348bee9d18c2c1eaf123cf"
+
+[[package]]
+name = "either"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
+
+[[package]]
+name = "enum-map"
+version = "2.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6866f3bfdf8207509a033af1a75a7b08abda06bbaaeae6669323fd5a097df2e9"
+dependencies = [
+ "enum-map-derive",
+]
+
+[[package]]
+name = "enum-map-derive"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.101",
+]
+
+[[package]]
+name = "env_filter"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0"
+dependencies = [
+ "log",
+ "regex",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.11.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "env_filter",
+ "jiff",
+ "log",
+]
+
+[[package]]
+name = "form_urlencoded"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
+dependencies = [
+ "percent-encoding",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "r-efi",
+ "wasi",
+]
+
+[[package]]
+name = "git2"
+version = "0.20.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2deb07a133b1520dc1a5690e9bd08950108873d7ed5de38dcc74d3b5ebffa110"
+dependencies = [
+ "bitflags",
+ "libc",
+ "libgit2-sys",
+ "log",
+ "url",
+]
+
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "hermit-abi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
+
+[[package]]
+name = "hermit-abi"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08"
+
+[[package]]
+name = "idna"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
+dependencies = [
+ "idna_adapter",
+ "smallvec",
+ "utf8_iter",
+]
+
+[[package]]
+name = "idna_adapter"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "279259b0ac81c89d11c290495fdcfa96ea3643b7df311c138b6fe8ca5237f0f8"
+dependencies = [
+ "idna_mapping",
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "idna_mapping"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11c13906586a4b339310541a274dd927aff6fcbb5b8e3af90634c4b31681c792"
+dependencies = [
+ "unicode-joining-type",
+]
+
+[[package]]
+name = "is-terminal"
+version = "0.4.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9"
+dependencies = [
+ "hermit-abi 0.5.1",
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
+
+[[package]]
+name = "itertools"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "jiff"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a194df1107f33c79f4f93d02c80798520551949d59dfad22b6157048a88cca93"
+dependencies = [
+ "jiff-static",
+ "log",
+ "portable-atomic",
+ "portable-atomic-util",
+ "serde",
+]
+
+[[package]]
+name = "jiff-static"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c6e1db7ed32c6c71b759497fae34bf7933636f75a251b9e736555da426f6442"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.101",
+]
+
+[[package]]
+name = "jobserver"
+version = "0.1.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a"
+dependencies = [
+ "getrandom",
+ "libc",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+
+[[package]]
+name = "libc"
+version = "0.2.172"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
+
+[[package]]
+name = "libgit2-sys"
+version = "0.18.1+1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1dcb20f84ffcdd825c7a311ae347cce604a6f084a767dec4a4929829645290e"
+dependencies = [
+ "cc",
+ "libc",
+ "libz-sys",
+ "pkg-config",
+]
+
+[[package]]
+name = "libz-sys"
+version = "1.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+ "vcpkg",
+]
+
+[[package]]
+name = "lock_api"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
+
+[[package]]
+name = "memchr"
+version = "2.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+
+[[package]]
+name = "memoffset"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "mmtk"
+version = "0.31.0"
+source = "git+https://github.com/mmtk/mmtk-core.git?rev=c6317a3f1c262e33fc2e427e4cc999c17bcc4791#c6317a3f1c262e33fc2e427e4cc999c17bcc4791"
+dependencies = [
+ "atomic",
+ "atomic-traits",
+ "atomic_refcell",
+ "built",
+ "bytemuck",
+ "bytemuck_derive",
+ "cfg-if",
+ "crossbeam",
+ "delegate",
+ "downcast-rs",
+ "enum-map",
+ "env_logger",
+ "idna_adapter",
+ "is-terminal",
+ "itertools",
+ "lazy_static",
+ "libc",
+ "log",
+ "memoffset",
+ "mmtk-macros",
+ "num-traits",
+ "num_cpus",
+ "portable-atomic",
+ "probe",
+ "rayon-core",
+ "regex",
+ "rustversion",
+ "spin",
+ "static_assertions",
+ "strum",
+ "strum_macros",
+ "sysinfo 0.33.1",
+]
+
+[[package]]
+name = "mmtk-macros"
+version = "0.31.0"
+source = "git+https://github.com/mmtk/mmtk-core.git?rev=c6317a3f1c262e33fc2e427e4cc999c17bcc4791#c6317a3f1c262e33fc2e427e4cc999c17bcc4791"
+dependencies = [
+ "proc-macro-error",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.101",
+]
+
+[[package]]
+name = "mmtk_ruby"
+version = "0.1.0"
+dependencies = [
+ "atomic_refcell",
+ "env_logger",
+ "libc",
+ "log",
+ "mmtk",
+ "once_cell",
+ "probe",
+ "sysinfo 0.32.1",
+]
+
+[[package]]
+name = "ntapi"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.16.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
+dependencies = [
+ "hermit-abi 0.3.9",
+ "libc",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.21.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
+
+[[package]]
+name = "once_cell_polyfill"
+version = "1.70.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad"
+
+[[package]]
+name = "percent-encoding"
+version = "2.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
+
+[[package]]
+name = "pkg-config"
+version = "0.3.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
+
+[[package]]
+name = "portable-atomic"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e"
+
+[[package]]
+name = "portable-atomic-util"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
+dependencies = [
+ "portable-atomic",
+]
+
+[[package]]
+name = "probe"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8e2d2444b730c8f027344c60f9e1f1554d7a3342df9bdd425142ed119a6e5a3"
+
+[[package]]
+name = "proc-macro-error"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
+dependencies = [
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro-error-attr"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "version_check",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.95"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "r-efi"
+version = "5.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
+
+[[package]]
+name = "rayon"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
+dependencies = [
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
+dependencies = [
+ "crossbeam-deque",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "regex"
+version = "1.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
+
+[[package]]
+name = "rustc_version"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
+dependencies = [
+ "semver",
+]
+
+[[package]]
+name = "rustversion"
+version = "1.0.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
+
+[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
+name = "semver"
+version = "1.0.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
+
+[[package]]
+name = "serde"
+version = "1.0.219"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.219"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.101",
+]
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "smallvec"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9"
+
+[[package]]
+name = "spin"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
+dependencies = [
+ "lock_api",
+]
+
+[[package]]
+name = "static_assertions"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
+
+[[package]]
+name = "strum"
+version = "0.27.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32"
+
+[[package]]
+name = "strum_macros"
+version = "0.27.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "rustversion",
+ "syn 2.0.101",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.109"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+dependencies = [
+ "proc-macro2",
+ "unicode-ident",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.101"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "sysinfo"
+version = "0.32.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c33cd241af0f2e9e3b5c32163b873b29956890b5342e6745b917ce9d490f4af"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+ "memchr",
+ "ntapi",
+ "rayon",
+ "windows",
+]
+
+[[package]]
+name = "sysinfo"
+version = "0.33.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4fc858248ea01b66f19d8e8a6d55f41deaf91e9d495246fd01368d99935c6c01"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+ "memchr",
+ "ntapi",
+ "rayon",
+ "windows",
+]
+
+[[package]]
+name = "tinyvec"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71"
+dependencies = [
+ "tinyvec_macros",
+]
+
+[[package]]
+name = "tinyvec_macros"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+
+[[package]]
+name = "unicode-bidi"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5"
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
+
+[[package]]
+name = "unicode-joining-type"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8d00a78170970967fdb83f9d49b92f959ab2bb829186b113e4f4604ad98e180"
+
+[[package]]
+name = "unicode-normalization"
+version = "0.1.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956"
+dependencies = [
+ "tinyvec",
+]
+
+[[package]]
+name = "url"
+version = "2.5.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "percent-encoding",
+]
+
+[[package]]
+name = "utf8_iter"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
+
+[[package]]
+name = "utf8parse"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
+
+[[package]]
+name = "vcpkg"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+
+[[package]]
+name = "version_check"
+version = "0.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
+
+[[package]]
+name = "wasi"
+version = "0.14.2+wasi-0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
+dependencies = [
+ "wit-bindgen-rt",
+]
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows"
+version = "0.57.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143"
+dependencies = [
+ "windows-core",
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-core"
+version = "0.57.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d"
+dependencies = [
+ "windows-implement",
+ "windows-interface",
+ "windows-result",
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-implement"
+version = "0.57.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.101",
+]
+
+[[package]]
+name = "windows-interface"
+version = "0.57.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.101",
+]
+
+[[package]]
+name = "windows-result"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.59.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+
+[[package]]
+name = "wit-bindgen-rt"
+version = "0.39.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
+dependencies = [
+ "bitflags",
+]
diff --git a/gc/mmtk/Cargo.toml b/gc/mmtk/Cargo.toml
new file mode 100644
index 0000000000..d856122900
--- /dev/null
+++ b/gc/mmtk/Cargo.toml
@@ -0,0 +1,42 @@
+[package]
+name = "mmtk_ruby"
+version = "0.1.0"
+authors = []
+edition = "2021"
+
+[lib]
+name = "mmtk_ruby"
+crate-type = ["cdylib", "staticlib"]
+
+[profile.release]
+lto = true
+
+[dependencies]
+libc = "0.2"
+log = "0.4.14"
+env_logger = "0.11.3"
+once_cell = "1.17.0"
+atomic_refcell = "0.1.9"
+probe = "0.5"
+sysinfo = "0.32.0"
+
+[dependencies.mmtk]
+features = ["is_mmtk_object", "object_pinning", "sticky_immix_non_moving_nursery"]
+
+# Uncomment the following lines to use mmtk-core from the official repository.
+git = "https://github.com/mmtk/mmtk-core.git"
+rev = "c6317a3f1c262e33fc2e427e4cc999c17bcc4791"
+
+# Uncomment the following line to use mmtk-core from a local repository.
+# path = "../../../mmtk-core"
+
+[features]
+default = []
+
+# When moving an object, clear its original copy.
+clear_old_copy = []
+
+# Enable extra assertions in release build. For debugging.
+extra_assert = []
+
+[workspace]
diff --git a/gc/mmtk/cbindgen.toml b/gc/mmtk/cbindgen.toml
new file mode 100644
index 0000000000..b99c30efc8
--- /dev/null
+++ b/gc/mmtk/cbindgen.toml
@@ -0,0 +1,36 @@
+language = "C"
+
+include_guard = "MMTK_H"
+
+autogen_warning = "/* Warning, this file is autogenerated by cbindgen from the mmtk-ruby repository. Don't modify this manually. */"
+
+tab_width = 4
+
+usize_is_size_t = true
+
+after_includes = """
+
+typedef struct MMTk_Builder MMTk_Builder;
+typedef struct MMTk_Mutator MMTk_Mutator;
+
+typedef struct MMTk_ractor_cache *MMTk_VMThread;
+typedef struct MMTk_ractor_cache *MMTk_VMMutatorThread;
+typedef struct MMTk_GCThreadTLS *MMTk_VMWorkerThread;
+typedef void *MMTk_Address;
+typedef void *MMTk_ObjectReference;
+typedef void *MMTk_NullableObjectReference;
+typedef uint32_t MMTk_AllocationSemantics;
+
+typedef struct MMTk_BumpPointer {
+ uintptr_t cursor;
+ uintptr_t limit;
+} MMTk_BumpPointer;
+"""
+
+[export]
+exclude = ["RubyMutator"]
+prefix = "MMTk_"
+
+[export.rename]
+"MMTKBuilder" = "Builder"
+"RubyMutator" = "Mutator"
diff --git a/gc/mmtk/depend b/gc/mmtk/depend
new file mode 100644
index 0000000000..77b229af36
--- /dev/null
+++ b/gc/mmtk/depend
@@ -0,0 +1,18 @@
+$(TARGET_SO): $(MMTK_BUILD)/$(LIBMMTK_RUBY)
+
+# Add the `libmmtk_ruby.a` target to run `cargo build`
+
+release/$(LIBMMTK_RUBY) debug/$(LIBMMTK_RUBY): $(RUSTSRCS) $(srcdir)/Cargo.toml $(srcdir)/Cargo.toml
+
+release/$(LIBMMTK_RUBY):
+ CARGO_TARGET_DIR="." cargo build --manifest-path=$(srcdir)/Cargo.toml --release
+
+debug/$(LIBMMTK_RUBY):
+ CARGO_TARGET_DIR="." cargo build --manifest-path=$(srcdir)/Cargo.toml
+
+clean: clean-mmtk
+
+.PHONY: clean-mmtk
+clean-mmtk:
+ -$(Q)$(RM_RF) debug release
+ -$(Q)$(RM) .rustc_info.json
diff --git a/gc/mmtk/extconf.rb b/gc/mmtk/extconf.rb
new file mode 100644
index 0000000000..c0e788037e
--- /dev/null
+++ b/gc/mmtk/extconf.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require_relative "../extconf_base"
+
+# Statically link `libmmtk_ruby.a`
+$LIBS << " $(MMTK_BUILD)/$(LIBMMTK_RUBY)"
+
+rustsrcs = Dir.glob("src/*.rs", base: __dir__).map {|s| "$(srcdir)/#{s}"}
+
+create_gc_makefile("mmtk") do |makefile|
+ [
+ *makefile,
+
+ <<~MAKEFILE,
+ MMTK_BUILD = debug
+ LIBMMTK_RUBY = libmmtk_ruby.#$LIBEXT
+ RUSTSRCS = #{rustsrcs.join(" \\\n\t ")}
+
+ ifeq ($(MMTK_BUILD), debug)
+ CPPFLAGS += -DMMTK_DEBUG
+ endif
+ MAKEFILE
+ ]
+end
diff --git a/gc/mmtk/mmtk.c b/gc/mmtk/mmtk.c
new file mode 100644
index 0000000000..b1a836a8c5
--- /dev/null
+++ b/gc/mmtk/mmtk.c
@@ -0,0 +1,1554 @@
+#include <pthread.h>
+#include <stdbool.h>
+
+#include "ruby/assert.h"
+#include "ruby/atomic.h"
+#include "ruby/debug.h"
+
+#include "gc/gc.h"
+#include "gc/gc_impl.h"
+#include "gc/mmtk/mmtk.h"
+
+#include "ccan/list/list.h"
+#include "darray.h"
+
+#ifdef __APPLE__
+#include <sys/sysctl.h>
+#endif
+
+struct objspace {
+ bool measure_gc_time;
+ bool gc_stress;
+
+ size_t gc_count;
+ size_t total_gc_time;
+ size_t total_allocated_objects;
+
+ st_table *finalizer_table;
+ struct MMTk_final_job *finalizer_jobs;
+ rb_postponed_job_handle_t finalizer_postponed_job;
+
+ struct ccan_list_head ractor_caches;
+ unsigned long live_ractor_cache_count;
+
+ pthread_mutex_t mutex;
+ rb_atomic_t mutator_blocking_count;
+ bool world_stopped;
+ pthread_cond_t cond_world_stopped;
+ pthread_cond_t cond_world_started;
+ size_t start_the_world_count;
+
+ struct {
+ bool gc_thread_crashed;
+ char crash_msg[256];
+ } crash_context;
+
+ struct rb_gc_vm_context vm_context;
+
+ unsigned int fork_hook_vm_lock_lev;
+};
+
+struct MMTk_ractor_cache {
+ struct ccan_list_node list_node;
+
+ MMTk_Mutator *mutator;
+ bool gc_mutator_p;
+
+ MMTk_BumpPointer *bump_pointer;
+};
+
+struct MMTk_final_job {
+ struct MMTk_final_job *next;
+ enum {
+ MMTK_FINAL_JOB_DFREE,
+ MMTK_FINAL_JOB_FINALIZE,
+ } kind;
+ union {
+ struct {
+ void (*func)(void *);
+ void *data;
+ } dfree;
+ struct {
+ /* HACK: we store the object ID on the 0th element of this array. */
+ VALUE finalizer_array;
+ } finalize;
+ } as;
+};
+
+#ifdef RB_THREAD_LOCAL_SPECIFIER
+RB_THREAD_LOCAL_SPECIFIER struct MMTk_GCThreadTLS *rb_mmtk_gc_thread_tls;
+
+RB_THREAD_LOCAL_SPECIFIER VALUE marking_parent_object;
+#else
+# error We currently need language-supported TLS
+#endif
+
+#ifdef MMTK_DEBUG
+# define MMTK_ASSERT(expr, ...) RUBY_ASSERT_ALWAYS(expr, #expr RBIMPL_VA_OPT_ARGS(__VA_ARGS__))
+#else
+# define MMTK_ASSERT(expr, ...) ((void)0)
+#endif
+
+#include <pthread.h>
+
+static inline VALUE rb_mmtk_call_object_closure(VALUE obj, bool pin);
+
+static void
+rb_mmtk_init_gc_worker_thread(MMTk_VMWorkerThread gc_thread_tls)
+{
+ rb_mmtk_gc_thread_tls = gc_thread_tls;
+}
+
+static bool
+rb_mmtk_is_mutator(void)
+{
+ return ruby_native_thread_p();
+}
+
+static void
+rb_mmtk_stop_the_world(void)
+{
+ struct objspace *objspace = rb_gc_get_objspace();
+
+ int err;
+ if ((err = pthread_mutex_lock(&objspace->mutex)) != 0) {
+ rb_bug("ERROR: cannot lock objspace->mutex: %s", strerror(err));
+ }
+
+ while (!objspace->world_stopped) {
+ pthread_cond_wait(&objspace->cond_world_stopped, &objspace->mutex);
+ }
+
+ if ((err = pthread_mutex_unlock(&objspace->mutex)) != 0) {
+ rb_bug("ERROR: cannot release objspace->mutex: %s", strerror(err));
+ }
+}
+
+static void
+rb_mmtk_resume_mutators(void)
+{
+ struct objspace *objspace = rb_gc_get_objspace();
+
+ int err;
+ if ((err = pthread_mutex_lock(&objspace->mutex)) != 0) {
+ rb_bug("ERROR: cannot lock objspace->mutex: %s", strerror(err));
+ }
+
+ objspace->world_stopped = false;
+ objspace->gc_count++;
+ pthread_cond_broadcast(&objspace->cond_world_started);
+
+ if ((err = pthread_mutex_unlock(&objspace->mutex)) != 0) {
+ rb_bug("ERROR: cannot release objspace->mutex: %s", strerror(err));
+ }
+}
+
+static void
+rb_mmtk_block_for_gc(MMTk_VMMutatorThread mutator)
+{
+ struct objspace *objspace = rb_gc_get_objspace();
+
+ size_t starting_gc_count = objspace->gc_count;
+ RUBY_ATOMIC_INC(objspace->mutator_blocking_count);
+ int lock_lev = RB_GC_VM_LOCK();
+ RUBY_ATOMIC_DEC(objspace->mutator_blocking_count);
+ int err;
+ if ((err = pthread_mutex_lock(&objspace->mutex)) != 0) {
+ rb_bug("ERROR: cannot lock objspace->mutex: %s", strerror(err));
+ }
+
+ if (objspace->gc_count == starting_gc_count) {
+ rb_gc_event_hook(0, RUBY_INTERNAL_EVENT_GC_START);
+
+ rb_gc_initialize_vm_context(&objspace->vm_context);
+
+ mutator->gc_mutator_p = true;
+
+ struct timespec gc_start_time;
+ if (objspace->measure_gc_time) {
+ clock_gettime(CLOCK_MONOTONIC, &gc_start_time);
+ }
+
+ rb_gc_save_machine_context();
+
+ rb_gc_vm_barrier();
+
+ objspace->world_stopped = true;
+
+ pthread_cond_broadcast(&objspace->cond_world_stopped);
+
+ // Wait for GC end
+ while (objspace->world_stopped) {
+ pthread_cond_wait(&objspace->cond_world_started, &objspace->mutex);
+ }
+
+ if (RB_UNLIKELY(objspace->crash_context.gc_thread_crashed)) {
+ rb_bug("%s", objspace->crash_context.crash_msg);
+ }
+
+ if (objspace->measure_gc_time) {
+ struct timespec gc_end_time;
+ clock_gettime(CLOCK_MONOTONIC, &gc_end_time);
+
+ objspace->total_gc_time +=
+ (gc_end_time.tv_sec - gc_start_time.tv_sec) * (1000 * 1000 * 1000) +
+ (gc_end_time.tv_nsec - gc_start_time.tv_nsec);
+ }
+ }
+
+ if ((err = pthread_mutex_unlock(&objspace->mutex)) != 0) {
+ rb_bug("ERROR: cannot release objspace->mutex: %s", strerror(err));
+ }
+ RB_GC_VM_UNLOCK(lock_lev);
+}
+
+static void
+rb_mmtk_before_updating_jit_code(void)
+{
+ rb_gc_before_updating_jit_code();
+}
+
+static void
+rb_mmtk_after_updating_jit_code(void)
+{
+ rb_gc_after_updating_jit_code();
+}
+
+static size_t
+rb_mmtk_number_of_mutators(void)
+{
+ struct objspace *objspace = rb_gc_get_objspace();
+ return objspace->live_ractor_cache_count;
+}
+
+static void
+rb_mmtk_get_mutators(void (*visit_mutator)(MMTk_Mutator *mutator, void *data), void *data)
+{
+ struct objspace *objspace = rb_gc_get_objspace();
+ struct MMTk_ractor_cache *ractor_cache;
+
+ ccan_list_for_each(&objspace->ractor_caches, ractor_cache, list_node) {
+ visit_mutator(ractor_cache->mutator, data);
+ }
+}
+
+static void
+rb_mmtk_scan_gc_roots(void)
+{
+ struct objspace *objspace = rb_gc_get_objspace();
+
+ // FIXME: Make `rb_gc_mark_roots` aware that the current thread may not have EC.
+ // See: https://github.com/ruby/mmtk/issues/22
+ rb_gc_worker_thread_set_vm_context(&objspace->vm_context);
+ rb_gc_mark_roots(objspace, NULL);
+ rb_gc_worker_thread_unset_vm_context(&objspace->vm_context);
+}
+
+static int
+pin_value(st_data_t key, st_data_t value, st_data_t data)
+{
+ rb_gc_impl_mark_and_pin((void *)data, (VALUE)value);
+
+ return ST_CONTINUE;
+}
+
+static void
+rb_mmtk_scan_objspace(void)
+{
+ struct objspace *objspace = rb_gc_get_objspace();
+
+ if (objspace->finalizer_table != NULL) {
+ st_foreach(objspace->finalizer_table, pin_value, (st_data_t)objspace);
+ }
+
+ struct MMTk_final_job *job = objspace->finalizer_jobs;
+ while (job != NULL) {
+ switch (job->kind) {
+ case MMTK_FINAL_JOB_DFREE:
+ break;
+ case MMTK_FINAL_JOB_FINALIZE:
+ rb_gc_impl_mark(objspace, job->as.finalize.finalizer_array);
+ break;
+ default:
+ rb_bug("rb_mmtk_scan_objspace: unknown final job type %d", job->kind);
+ }
+
+ job = job->next;
+ }
+}
+
+static void
+rb_mmtk_move_obj_during_marking(MMTk_ObjectReference from, MMTk_ObjectReference to)
+{
+ rb_gc_move_obj_during_marking((VALUE)from, (VALUE)to);
+}
+
+static void
+rb_mmtk_update_object_references(MMTk_ObjectReference mmtk_object)
+{
+ VALUE object = (VALUE)mmtk_object;
+
+ if (!RB_FL_TEST(object, RUBY_FL_WEAK_REFERENCE)) {
+ marking_parent_object = object;
+ rb_gc_update_object_references(rb_gc_get_objspace(), object);
+ marking_parent_object = 0;
+ }
+}
+
+static void
+rb_mmtk_call_gc_mark_children(MMTk_ObjectReference object)
+{
+ marking_parent_object = (VALUE)object;
+ rb_gc_mark_children(rb_gc_get_objspace(), (VALUE)object);
+ marking_parent_object = 0;
+}
+
+static void
+rb_mmtk_handle_weak_references(MMTk_ObjectReference mmtk_object, bool moving)
+{
+ VALUE object = (VALUE)mmtk_object;
+
+ marking_parent_object = object;
+
+ rb_gc_handle_weak_references(object);
+
+ if (moving) {
+ rb_gc_update_object_references(rb_gc_get_objspace(), object);
+ }
+
+ marking_parent_object = 0;
+}
+
+static void
+rb_mmtk_call_obj_free(MMTk_ObjectReference object)
+{
+ VALUE obj = (VALUE)object;
+ struct objspace *objspace = rb_gc_get_objspace();
+
+ if (RB_UNLIKELY(rb_gc_event_hook_required_p(RUBY_INTERNAL_EVENT_FREEOBJ))) {
+ rb_gc_worker_thread_set_vm_context(&objspace->vm_context);
+ rb_gc_event_hook(obj, RUBY_INTERNAL_EVENT_FREEOBJ);
+ rb_gc_worker_thread_unset_vm_context(&objspace->vm_context);
+ }
+
+ rb_gc_obj_free(objspace, obj);
+
+ // TODO: uncomment this when done debugging
+// #ifdef MMTK_DEBUG
+ memset((void *)obj, 0, rb_gc_impl_obj_slot_size(obj));
+// #endif
+}
+
+static size_t
+rb_mmtk_vm_live_bytes(void)
+{
+ return 0;
+}
+
+static void
+make_final_job(struct objspace *objspace, VALUE obj, VALUE table)
+{
+ MMTK_ASSERT(RB_BUILTIN_TYPE(table) == T_ARRAY);
+
+ struct MMTk_final_job *job = xmalloc(sizeof(struct MMTk_final_job));
+ job->next = objspace->finalizer_jobs;
+ job->kind = MMTK_FINAL_JOB_FINALIZE;
+ job->as.finalize.finalizer_array = table;
+
+ objspace->finalizer_jobs = job;
+}
+
+static int
+rb_mmtk_update_finalizer_table_i(st_data_t key, st_data_t value, st_data_t data, int error)
+{
+ MMTK_ASSERT(mmtk_is_reachable((MMTk_ObjectReference)value));
+ MMTK_ASSERT(RB_BUILTIN_TYPE(value) == T_ARRAY);
+
+ struct objspace *objspace = (struct objspace *)data;
+
+ if (mmtk_is_reachable((MMTk_ObjectReference)key)) {
+ VALUE new_key_location = rb_mmtk_call_object_closure((VALUE)key, false);
+
+ MMTK_ASSERT(RB_FL_TEST(new_key_location, RUBY_FL_FINALIZE));
+
+ if (new_key_location != key) {
+ return ST_REPLACE;
+ }
+ }
+ else {
+ make_final_job(objspace, (VALUE)key, (VALUE)value);
+
+ rb_postponed_job_trigger(objspace->finalizer_postponed_job);
+
+ return ST_DELETE;
+ }
+
+ return ST_CONTINUE;
+}
+
+static int
+rb_mmtk_update_finalizer_table_replace_i(st_data_t *key, st_data_t *value, st_data_t data, int existing)
+{
+ *key = rb_mmtk_call_object_closure((VALUE)*key, false);
+
+ return ST_CONTINUE;
+}
+
+static void
+rb_mmtk_update_finalizer_table(void)
+{
+ struct objspace *objspace = rb_gc_get_objspace();
+
+ st_foreach_with_replace(
+ objspace->finalizer_table,
+ rb_mmtk_update_finalizer_table_i,
+ rb_mmtk_update_finalizer_table_replace_i,
+ (st_data_t)objspace
+ );
+}
+
+static int
+rb_mmtk_global_tables_count(void)
+{
+ return RB_GC_VM_WEAK_TABLE_COUNT;
+}
+
+static inline VALUE rb_mmtk_call_object_closure(VALUE obj, bool pin);
+
+static int
+rb_mmtk_update_global_tables_i(VALUE val, void *data)
+{
+ if (!mmtk_is_reachable((MMTk_ObjectReference)val)) {
+ return ST_DELETE;
+ }
+
+ // TODO: check only if in moving GC
+ if (rb_mmtk_call_object_closure(val, false) != val) {
+ return ST_REPLACE;
+ }
+
+ return ST_CONTINUE;
+}
+
+static int
+rb_mmtk_update_global_tables_replace_i(VALUE *ptr, void *data)
+{
+ // TODO: cache the new location so we don't call rb_mmtk_call_object_closure twice
+ *ptr = rb_mmtk_call_object_closure(*ptr, false);
+
+ return ST_CONTINUE;
+}
+
+static void
+rb_mmtk_update_global_tables(int table)
+{
+ MMTK_ASSERT(table < RB_GC_VM_WEAK_TABLE_COUNT);
+
+ // TODO: set weak_only to true for non-moving GC
+ rb_gc_vm_weak_table_foreach(
+ rb_mmtk_update_global_tables_i,
+ rb_mmtk_update_global_tables_replace_i,
+ NULL,
+ false,
+ (enum rb_gc_vm_weak_tables)table
+ );
+}
+
+static bool
+rb_mmtk_special_const_p(MMTk_ObjectReference object)
+{
+ VALUE obj = (VALUE)object;
+
+ return RB_SPECIAL_CONST_P(obj);
+}
+
+RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2)
+static void
+rb_mmtk_gc_thread_bug(const char *msg, ...)
+{
+ struct objspace *objspace = rb_gc_get_objspace();
+
+ objspace->crash_context.gc_thread_crashed = true;
+
+ va_list args;
+ va_start(args, msg);
+ vsnprintf(objspace->crash_context.crash_msg, sizeof(objspace->crash_context.crash_msg), msg, args);
+ va_end(args);
+
+ fprintf(stderr, "-- GC thread backtrace "
+ "-------------------------------------------\n");
+ rb_gc_print_backtrace();
+ fprintf(stderr, "\n");
+
+ rb_mmtk_resume_mutators();
+
+ sleep(5);
+
+ rb_bug("rb_mmtk_gc_thread_bug");
+}
+
+static void
+rb_mmtk_gc_thread_panic_handler(void)
+{
+ rb_mmtk_gc_thread_bug("MMTk GC thread panicked");
+}
+
+static void
+rb_mmtk_mutator_thread_panic_handler(void)
+{
+ rb_bug("Ruby mutator thread panicked");
+}
+
+// Bootup
+MMTk_RubyUpcalls ruby_upcalls = {
+ rb_mmtk_init_gc_worker_thread,
+ rb_mmtk_is_mutator,
+ rb_mmtk_stop_the_world,
+ rb_mmtk_resume_mutators,
+ rb_mmtk_block_for_gc,
+ rb_mmtk_before_updating_jit_code,
+ rb_mmtk_after_updating_jit_code,
+ rb_mmtk_number_of_mutators,
+ rb_mmtk_get_mutators,
+ rb_mmtk_scan_gc_roots,
+ rb_mmtk_scan_objspace,
+ rb_mmtk_move_obj_during_marking,
+ rb_mmtk_update_object_references,
+ rb_mmtk_call_gc_mark_children,
+ rb_mmtk_handle_weak_references,
+ rb_mmtk_call_obj_free,
+ rb_mmtk_vm_live_bytes,
+ rb_mmtk_update_global_tables,
+ rb_mmtk_global_tables_count,
+ rb_mmtk_update_finalizer_table,
+ rb_mmtk_special_const_p,
+ rb_mmtk_mutator_thread_panic_handler,
+ rb_mmtk_gc_thread_panic_handler,
+};
+
+// Use max 80% of the available memory by default for MMTk
+#define RB_MMTK_HEAP_LIMIT_PERC 80
+#define RB_MMTK_DEFAULT_HEAP_MIN (1024 * 1024)
+#define RB_MMTK_DEFAULT_HEAP_MAX (rb_mmtk_system_physical_memory() / 100 * RB_MMTK_HEAP_LIMIT_PERC)
+
+enum mmtk_heap_mode {
+ RB_MMTK_DYNAMIC_HEAP,
+ RB_MMTK_FIXED_HEAP
+};
+
+MMTk_Builder *
+rb_mmtk_builder_init(void)
+{
+ MMTk_Builder *builder = mmtk_builder_default();
+ return builder;
+}
+
+void *
+rb_gc_impl_objspace_alloc(void)
+{
+ MMTk_Builder *builder = rb_mmtk_builder_init();
+ mmtk_init_binding(builder, NULL, &ruby_upcalls);
+
+ return calloc(1, sizeof(struct objspace));
+}
+
+static void gc_run_finalizers(void *data);
+
+void
+rb_gc_impl_objspace_init(void *objspace_ptr)
+{
+ struct objspace *objspace = objspace_ptr;
+
+ objspace->measure_gc_time = true;
+
+ objspace->finalizer_table = st_init_numtable();
+ objspace->finalizer_postponed_job = rb_postponed_job_preregister(0, gc_run_finalizers, objspace);
+
+ ccan_list_head_init(&objspace->ractor_caches);
+
+ objspace->mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
+ objspace->cond_world_stopped = (pthread_cond_t)PTHREAD_COND_INITIALIZER;
+ objspace->cond_world_started = (pthread_cond_t)PTHREAD_COND_INITIALIZER;
+}
+
+void
+rb_gc_impl_objspace_free(void *objspace_ptr)
+{
+ free(objspace_ptr);
+}
+
+void *
+rb_gc_impl_ractor_cache_alloc(void *objspace_ptr, void *ractor)
+{
+ struct objspace *objspace = objspace_ptr;
+ if (objspace->live_ractor_cache_count == 0) {
+ mmtk_initialize_collection(ractor);
+ }
+ objspace->live_ractor_cache_count++;
+
+ struct MMTk_ractor_cache *cache = malloc(sizeof(struct MMTk_ractor_cache));
+ ccan_list_add(&objspace->ractor_caches, &cache->list_node);
+
+ cache->mutator = mmtk_bind_mutator(cache);
+ cache->bump_pointer = mmtk_get_bump_pointer_allocator(cache->mutator);
+
+ return cache;
+}
+
+void
+rb_gc_impl_ractor_cache_free(void *objspace_ptr, void *cache_ptr)
+{
+ struct objspace *objspace = objspace_ptr;
+ struct MMTk_ractor_cache *cache = cache_ptr;
+
+ ccan_list_del(&cache->list_node);
+
+ if (ruby_free_at_exit_p()) {
+ MMTK_ASSERT(objspace->live_ractor_cache_count > 0);
+ }
+ else {
+ MMTK_ASSERT(objspace->live_ractor_cache_count > 1);
+ }
+
+ objspace->live_ractor_cache_count--;
+
+ mmtk_destroy_mutator(cache->mutator);
+}
+
+void rb_gc_impl_set_params(void *objspace_ptr) { }
+
+static VALUE gc_verify_internal_consistency(VALUE self) { return Qnil; }
+
+#define MMTK_HEAP_COUNT 6
+#define MMTK_MAX_OBJ_SIZE 640
+
+static size_t heap_sizes[MMTK_HEAP_COUNT + 1] = {
+ 32, 40, 80, 160, 320, MMTK_MAX_OBJ_SIZE, 0
+};
+
+void
+rb_gc_impl_init(void)
+{
+ VALUE gc_constants = rb_hash_new();
+ rb_hash_aset(gc_constants, ID2SYM(rb_intern("BASE_SLOT_SIZE")), SIZET2NUM(sizeof(VALUE) * 5));
+ rb_hash_aset(gc_constants, ID2SYM(rb_intern("RBASIC_SIZE")), SIZET2NUM(sizeof(struct RBasic)));
+ rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVALUE_OVERHEAD")), INT2NUM(0));
+ rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVARGC_MAX_ALLOCATE_SIZE")), LONG2FIX(MMTK_MAX_OBJ_SIZE));
+ // Pretend we have 5 size pools
+ rb_hash_aset(gc_constants, ID2SYM(rb_intern("SIZE_POOL_COUNT")), LONG2FIX(MMTK_HEAP_COUNT));
+ // TODO: correctly set RVALUE_OLD_AGE when we have generational GC support
+ rb_hash_aset(gc_constants, ID2SYM(rb_intern("RVALUE_OLD_AGE")), INT2FIX(0));
+ OBJ_FREEZE(gc_constants);
+ rb_define_const(rb_mGC, "INTERNAL_CONSTANTS", gc_constants);
+
+ // no-ops for compatibility
+ rb_define_singleton_method(rb_mGC, "verify_internal_consistency", gc_verify_internal_consistency, 0);
+
+ rb_define_singleton_method(rb_mGC, "compact", rb_f_notimplement, 0);
+ rb_define_singleton_method(rb_mGC, "auto_compact", rb_f_notimplement, 0);
+ rb_define_singleton_method(rb_mGC, "auto_compact=", rb_f_notimplement, 1);
+ rb_define_singleton_method(rb_mGC, "latest_compact_info", rb_f_notimplement, 0);
+ rb_define_singleton_method(rb_mGC, "verify_compaction_references", rb_f_notimplement, -1);
+}
+
+size_t *
+rb_gc_impl_heap_sizes(void *objspace_ptr)
+{
+ return heap_sizes;
+}
+
+int
+rb_mmtk_obj_free_iter_wrapper(VALUE obj, void *data)
+{
+ struct objspace *objspace = data;
+
+ if (!RB_TYPE_P(obj, T_NONE)) {
+ rb_gc_obj_free_vm_weak_references(obj);
+ rb_gc_obj_free(objspace, obj);
+ }
+
+ return 0;
+}
+
+// Shutdown
+static void each_object(struct objspace *objspace, int (*func)(VALUE, void *), void *data);
+
+void
+rb_gc_impl_shutdown_free_objects(void *objspace_ptr)
+{
+ mmtk_set_gc_enabled(false);
+ each_object(objspace_ptr, rb_mmtk_obj_free_iter_wrapper, objspace_ptr);
+ mmtk_set_gc_enabled(true);
+}
+
+// GC
+void
+rb_gc_impl_start(void *objspace_ptr, bool full_mark, bool immediate_mark, bool immediate_sweep, bool compact)
+{
+ mmtk_handle_user_collection_request(rb_gc_get_ractor_newobj_cache(), true, full_mark);
+}
+
+bool
+rb_gc_impl_during_gc_p(void *objspace_ptr)
+{
+ // TODO
+ return false;
+}
+
+static void
+rb_gc_impl_prepare_heap_i(MMTk_ObjectReference obj, void *d)
+{
+ rb_gc_prepare_heap_process_object((VALUE)obj);
+}
+
+void
+rb_gc_impl_prepare_heap(void *objspace_ptr)
+{
+ mmtk_enumerate_objects(rb_gc_impl_prepare_heap_i, NULL);
+}
+
+void
+rb_gc_impl_gc_enable(void *objspace_ptr)
+{
+ mmtk_set_gc_enabled(true);
+}
+
+void
+rb_gc_impl_gc_disable(void *objspace_ptr, bool finish_current_gc)
+{
+ mmtk_set_gc_enabled(false);
+}
+
+bool
+rb_gc_impl_gc_enabled_p(void *objspace_ptr)
+{
+ return mmtk_gc_enabled_p();
+}
+
+void
+rb_gc_impl_stress_set(void *objspace_ptr, VALUE flag)
+{
+ struct objspace *objspace = objspace_ptr;
+
+ objspace->gc_stress = RTEST(flag);
+}
+
+VALUE
+rb_gc_impl_stress_get(void *objspace_ptr)
+{
+ struct objspace *objspace = objspace_ptr;
+
+ return objspace->gc_stress ? Qtrue : Qfalse;
+}
+
+VALUE
+rb_gc_impl_config_get(void *objspace_ptr)
+{
+ VALUE hash = rb_hash_new();
+
+ rb_hash_aset(hash, ID2SYM(rb_intern_const("mmtk_worker_count")), RB_ULONG2NUM(mmtk_worker_count()));
+ rb_hash_aset(hash, ID2SYM(rb_intern_const("mmtk_plan")), rb_str_new_cstr((const char *)mmtk_plan()));
+ rb_hash_aset(hash, ID2SYM(rb_intern_const("mmtk_heap_mode")), rb_str_new_cstr((const char *)mmtk_heap_mode()));
+ size_t heap_min = mmtk_heap_min();
+ if (heap_min > 0) rb_hash_aset(hash, ID2SYM(rb_intern_const("mmtk_heap_min")), RB_ULONG2NUM(heap_min));
+ rb_hash_aset(hash, ID2SYM(rb_intern_const("mmtk_heap_max")), RB_ULONG2NUM(mmtk_heap_max()));
+
+ return hash;
+}
+
+void
+rb_gc_impl_config_set(void *objspace_ptr, VALUE hash)
+{
+ // TODO
+}
+
+// Object allocation
+
+static VALUE
+rb_mmtk_alloc_fast_path(struct objspace *objspace, struct MMTk_ractor_cache *ractor_cache, size_t size)
+{
+ MMTk_BumpPointer *bump_pointer = ractor_cache->bump_pointer;
+ if (bump_pointer == NULL) return 0;
+
+ uintptr_t new_cursor = bump_pointer->cursor + size;
+
+ if (new_cursor > bump_pointer->limit) {
+ return 0;
+ }
+ else {
+ VALUE obj = (VALUE)bump_pointer->cursor;
+ bump_pointer->cursor = new_cursor;
+ return obj;
+ }
+}
+
+static bool
+obj_can_parallel_free_p(VALUE obj)
+{
+ switch (RB_BUILTIN_TYPE(obj)) {
+ case T_ARRAY:
+ case T_BIGNUM:
+ case T_COMPLEX:
+ case T_FLOAT:
+ case T_HASH:
+ case T_OBJECT:
+ case T_RATIONAL:
+ case T_REGEXP:
+ case T_STRING:
+ case T_STRUCT:
+ case T_SYMBOL:
+ return true;
+ default:
+ return false;
+ }
+}
+
+VALUE
+rb_gc_impl_new_obj(void *objspace_ptr, void *cache_ptr, VALUE klass, VALUE flags, bool wb_protected, size_t alloc_size)
+{
+#define MMTK_ALLOCATION_SEMANTICS_DEFAULT 0
+ struct objspace *objspace = objspace_ptr;
+ struct MMTk_ractor_cache *ractor_cache = cache_ptr;
+
+ if (alloc_size > MMTK_MAX_OBJ_SIZE) rb_bug("too big");
+ for (int i = 0; i < MMTK_HEAP_COUNT; i++) {
+ if (alloc_size == heap_sizes[i]) break;
+ if (alloc_size < heap_sizes[i]) {
+ alloc_size = heap_sizes[i];
+ break;
+ }
+ }
+
+ if (objspace->gc_stress) {
+ mmtk_handle_user_collection_request(ractor_cache, false, false);
+ }
+
+ alloc_size += sizeof(VALUE);
+
+ VALUE *alloc_obj = (VALUE *)rb_mmtk_alloc_fast_path(objspace, ractor_cache, alloc_size);
+ if (!alloc_obj) {
+ alloc_obj = mmtk_alloc(ractor_cache->mutator, alloc_size, MMTk_MIN_OBJ_ALIGN, 0, MMTK_ALLOCATION_SEMANTICS_DEFAULT);
+ }
+
+ alloc_obj++;
+ alloc_obj[-1] = alloc_size - sizeof(VALUE);
+ alloc_obj[0] = flags;
+ alloc_obj[1] = klass;
+
+ // TODO: implement fast path for mmtk_post_alloc
+ mmtk_post_alloc(ractor_cache->mutator, (void*)alloc_obj, alloc_size, MMTK_ALLOCATION_SEMANTICS_DEFAULT);
+
+ // TODO: only add when object needs obj_free to be called
+ mmtk_add_obj_free_candidate(alloc_obj, obj_can_parallel_free_p((VALUE)alloc_obj));
+
+ objspace->total_allocated_objects++;
+
+ return (VALUE)alloc_obj;
+}
+
+size_t
+rb_gc_impl_obj_slot_size(VALUE obj)
+{
+ return ((VALUE *)obj)[-1];
+}
+
+size_t
+rb_gc_impl_heap_id_for_size(void *objspace_ptr, size_t size)
+{
+ for (int i = 0; i < MMTK_HEAP_COUNT; i++) {
+ if (size == heap_sizes[i]) return i;
+ if (size < heap_sizes[i]) return i;
+ }
+
+ rb_bug("size too big");
+}
+
+bool
+rb_gc_impl_size_allocatable_p(size_t size)
+{
+ return size <= MMTK_MAX_OBJ_SIZE;
+}
+
+// Malloc
+void *
+rb_gc_impl_malloc(void *objspace_ptr, size_t size, bool gc_allowed)
+{
+ // TODO: don't use system malloc
+ return malloc(size);
+}
+
+void *
+rb_gc_impl_calloc(void *objspace_ptr, size_t size, bool gc_allowed)
+{
+ // TODO: don't use system calloc
+ return calloc(1, size);
+}
+
+void *
+rb_gc_impl_realloc(void *objspace_ptr, void *ptr, size_t new_size, size_t old_size, bool gc_allowed)
+{
+ // TODO: don't use system realloc
+ return realloc(ptr, new_size);
+}
+
+void
+rb_gc_impl_free(void *objspace_ptr, void *ptr, size_t old_size)
+{
+ // TODO: don't use system free
+ free(ptr);
+}
+
+void rb_gc_impl_adjust_memory_usage(void *objspace_ptr, ssize_t diff) { }
+
+// Marking
+static inline VALUE
+rb_mmtk_call_object_closure(VALUE obj, bool pin)
+{
+ if (RB_UNLIKELY(RB_BUILTIN_TYPE(obj) == T_NONE)) {
+ const size_t info_size = 256;
+ char obj_info_buf[info_size];
+ rb_raw_obj_info(obj_info_buf, info_size, obj);
+
+ char parent_obj_info_buf[info_size];
+ rb_raw_obj_info(parent_obj_info_buf, info_size, marking_parent_object);
+
+ rb_mmtk_gc_thread_bug("try to mark T_NONE object (obj: %s, parent: %s)", obj_info_buf, parent_obj_info_buf);
+ }
+
+ return (VALUE)rb_mmtk_gc_thread_tls->object_closure.c_function(
+ rb_mmtk_gc_thread_tls->object_closure.rust_closure,
+ rb_mmtk_gc_thread_tls->gc_context,
+ (MMTk_ObjectReference)obj,
+ pin
+ );
+}
+
+void
+rb_gc_impl_mark(void *objspace_ptr, VALUE obj)
+{
+ if (RB_SPECIAL_CONST_P(obj)) return;
+
+ rb_mmtk_call_object_closure(obj, false);
+}
+
+void
+rb_gc_impl_mark_and_move(void *objspace_ptr, VALUE *ptr)
+{
+ if (RB_SPECIAL_CONST_P(*ptr)) return;
+
+ VALUE new_obj = rb_mmtk_call_object_closure(*ptr, false);
+ if (new_obj != *ptr) {
+ *ptr = new_obj;
+ }
+}
+
+void
+rb_gc_impl_mark_and_pin(void *objspace_ptr, VALUE obj)
+{
+ if (RB_SPECIAL_CONST_P(obj)) return;
+
+ rb_mmtk_call_object_closure(obj, true);
+}
+
+void
+rb_gc_impl_mark_maybe(void *objspace_ptr, VALUE obj)
+{
+ if (rb_gc_impl_pointer_to_heap_p(objspace_ptr, (const void *)obj)) {
+ rb_gc_impl_mark_and_pin(objspace_ptr, obj);
+ }
+}
+
+void
+rb_gc_impl_declare_weak_references(void *objspace_ptr, VALUE obj)
+{
+ RB_FL_SET(obj, RUBY_FL_WEAK_REFERENCE);
+ mmtk_declare_weak_references((MMTk_ObjectReference)obj);
+}
+
+bool
+rb_gc_impl_handle_weak_references_alive_p(void *objspace_ptr, VALUE obj)
+{
+ return mmtk_weak_references_alive_p((MMTk_ObjectReference)obj);
+}
+
+// Compaction
+void
+rb_gc_impl_register_pinning_obj(void *objspace_ptr, VALUE obj)
+{
+ mmtk_register_pinning_obj((MMTk_ObjectReference)obj);
+}
+
+bool
+rb_gc_impl_object_moved_p(void *objspace_ptr, VALUE obj)
+{
+ return rb_mmtk_call_object_closure(obj, false) != obj;
+}
+
+VALUE
+rb_gc_impl_location(void *objspace_ptr, VALUE obj)
+{
+ return rb_mmtk_call_object_closure(obj, false);
+}
+
+// Write barriers
+void
+rb_gc_impl_writebarrier(void *objspace_ptr, VALUE a, VALUE b)
+{
+ struct MMTk_ractor_cache *cache = rb_gc_get_ractor_newobj_cache();
+
+ if (SPECIAL_CONST_P(b)) return;
+
+#ifdef MMTK_DEBUG
+ if (!rb_gc_impl_pointer_to_heap_p(objspace_ptr, (void *)a)) {
+ char buff[256];
+ rb_bug("a: %s is not an object", rb_raw_obj_info(buff, 256, a));
+ }
+
+ if (!rb_gc_impl_pointer_to_heap_p(objspace_ptr, (void *)b)) {
+ char buff[256];
+ rb_bug("b: %s is not an object", rb_raw_obj_info(buff, 256, b));
+ }
+#endif
+
+ MMTK_ASSERT(BUILTIN_TYPE(a) != T_NONE);
+ MMTK_ASSERT(BUILTIN_TYPE(b) != T_NONE);
+
+ mmtk_object_reference_write_post(cache->mutator, (MMTk_ObjectReference)a);
+}
+
+void
+rb_gc_impl_writebarrier_unprotect(void *objspace_ptr, VALUE obj)
+{
+ mmtk_register_wb_unprotected_object((MMTk_ObjectReference)obj);
+}
+
+void
+rb_gc_impl_writebarrier_remember(void *objspace_ptr, VALUE obj)
+{
+ struct MMTk_ractor_cache *cache = rb_gc_get_ractor_newobj_cache();
+
+ mmtk_object_reference_write_post(cache->mutator, (MMTk_ObjectReference)obj);
+}
+
+// Heap walking
+static void
+each_objects_i(MMTk_ObjectReference obj, void *d)
+{
+ rb_darray(VALUE) *objs = d;
+
+ rb_darray_append(objs, (VALUE)obj);
+}
+
+static void
+each_object(struct objspace *objspace, int (*func)(VALUE, void *), void *data)
+{
+ rb_darray(VALUE) objs;
+ rb_darray_make(&objs, 0);
+
+ mmtk_enumerate_objects(each_objects_i, &objs);
+
+ VALUE *obj_ptr;
+ rb_darray_foreach(objs, i, obj_ptr) {
+ if (!mmtk_is_mmtk_object((MMTk_ObjectReference)*obj_ptr)) continue;
+
+ if (func(*obj_ptr, data) != 0) {
+ break;
+ }
+ }
+
+ rb_darray_free(objs);
+}
+
+struct rb_gc_impl_each_objects_data {
+ int (*func)(void *, void *, size_t, void *);
+ void *data;
+};
+
+static int
+rb_gc_impl_each_objects_i(VALUE obj, void *d)
+{
+ struct rb_gc_impl_each_objects_data *data = d;
+
+ size_t slot_size = rb_gc_impl_obj_slot_size(obj);
+
+ return data->func((void *)obj, (void *)(obj + slot_size), slot_size, data->data);
+}
+
+void
+rb_gc_impl_each_objects(void *objspace_ptr, int (*func)(void *, void *, size_t, void *), void *data)
+{
+ struct rb_gc_impl_each_objects_data each_objects_data = {
+ .func = func,
+ .data = data
+ };
+
+ each_object(objspace_ptr, rb_gc_impl_each_objects_i, &each_objects_data);
+}
+
+struct rb_gc_impl_each_object_data {
+ void (*func)(VALUE, void *);
+ void *data;
+};
+
+static int
+rb_gc_impl_each_object_i(VALUE obj, void *d)
+{
+ struct rb_gc_impl_each_object_data *data = d;
+
+ data->func(obj, data->data);
+
+ return 0;
+}
+
+void
+rb_gc_impl_each_object(void *objspace_ptr, void (*func)(VALUE, void *), void *data)
+{
+ struct rb_gc_impl_each_object_data each_object_data = {
+ .func = func,
+ .data = data
+ };
+
+ each_object(objspace_ptr, rb_gc_impl_each_object_i, &each_object_data);
+}
+
+// Finalizers
+static VALUE
+gc_run_finalizers_get_final(long i, void *data)
+{
+ VALUE table = (VALUE)data;
+
+ return RARRAY_AREF(table, i + 1);
+}
+
+static void
+gc_run_finalizers(void *data)
+{
+ struct objspace *objspace = data;
+
+ rb_gc_set_pending_interrupt();
+
+ while (objspace->finalizer_jobs != NULL) {
+ struct MMTk_final_job *job = objspace->finalizer_jobs;
+ objspace->finalizer_jobs = job->next;
+
+ switch (job->kind) {
+ case MMTK_FINAL_JOB_DFREE:
+ job->as.dfree.func(job->as.dfree.data);
+ break;
+ case MMTK_FINAL_JOB_FINALIZE: {
+ VALUE finalizer_array = job->as.finalize.finalizer_array;
+
+ rb_gc_run_obj_finalizer(
+ RARRAY_AREF(finalizer_array, 0),
+ RARRAY_LEN(finalizer_array) - 1,
+ gc_run_finalizers_get_final,
+ (void *)finalizer_array
+ );
+
+ RB_GC_GUARD(finalizer_array);
+ break;
+ }
+ }
+
+ xfree(job);
+ }
+
+ rb_gc_unset_pending_interrupt();
+}
+
+void
+rb_gc_impl_make_zombie(void *objspace_ptr, VALUE obj, void (*dfree)(void *), void *data)
+{
+ if (dfree == NULL) return;
+
+ struct objspace *objspace = objspace_ptr;
+
+ struct MMTk_final_job *job = xmalloc(sizeof(struct MMTk_final_job));
+ job->kind = MMTK_FINAL_JOB_DFREE;
+ job->as.dfree.func = dfree;
+ job->as.dfree.data = data;
+
+ struct MMTk_final_job *prev;
+ do {
+ job->next = objspace->finalizer_jobs;
+ prev = RUBY_ATOMIC_PTR_CAS(objspace->finalizer_jobs, job->next, job);
+ } while (prev != job->next);
+
+ if (!ruby_free_at_exit_p()) {
+ rb_postponed_job_trigger(objspace->finalizer_postponed_job);
+ }
+}
+
+VALUE
+rb_gc_impl_define_finalizer(void *objspace_ptr, VALUE obj, VALUE block)
+{
+ struct objspace *objspace = objspace_ptr;
+ VALUE table;
+ st_data_t data;
+
+ RBASIC(obj)->flags |= FL_FINALIZE;
+
+ int lev = RB_GC_VM_LOCK();
+
+ if (st_lookup(objspace->finalizer_table, obj, &data)) {
+ table = (VALUE)data;
+
+ /* avoid duplicate block, table is usually small */
+ {
+ long len = RARRAY_LEN(table);
+ long i;
+
+ for (i = 0; i < len; i++) {
+ VALUE recv = RARRAY_AREF(table, i);
+ if (rb_equal(recv, block)) {
+ RB_GC_VM_UNLOCK(lev);
+ return recv;
+ }
+ }
+ }
+
+ rb_ary_push(table, block);
+ }
+ else {
+ table = rb_ary_new3(2, rb_obj_id(obj), block);
+ rb_obj_hide(table);
+ st_add_direct(objspace->finalizer_table, obj, table);
+ }
+
+ RB_GC_VM_UNLOCK(lev);
+
+ return block;
+}
+
+void
+rb_gc_impl_undefine_finalizer(void *objspace_ptr, VALUE obj)
+{
+ struct objspace *objspace = objspace_ptr;
+
+ st_data_t data = obj;
+
+ int lev = RB_GC_VM_LOCK();
+ st_delete(objspace->finalizer_table, &data, 0);
+ RB_GC_VM_UNLOCK(lev);
+
+ FL_UNSET(obj, FL_FINALIZE);
+}
+
+void
+rb_gc_impl_copy_finalizer(void *objspace_ptr, VALUE dest, VALUE obj)
+{
+ struct objspace *objspace = objspace_ptr;
+ VALUE table;
+ st_data_t data;
+
+ if (!FL_TEST(obj, FL_FINALIZE)) return;
+
+ int lev = RB_GC_VM_LOCK();
+ if (RB_LIKELY(st_lookup(objspace->finalizer_table, obj, &data))) {
+ table = rb_ary_dup((VALUE)data);
+ RARRAY_ASET(table, 0, rb_obj_id(dest));
+ st_insert(objspace->finalizer_table, dest, table);
+ FL_SET(dest, FL_FINALIZE);
+ }
+ else {
+ rb_bug("rb_gc_copy_finalizer: FL_FINALIZE set but not found in finalizer_table: %s", rb_obj_info(obj));
+ }
+ RB_GC_VM_UNLOCK(lev);
+}
+
+static int
+move_finalizer_from_table_i(st_data_t key, st_data_t val, st_data_t arg)
+{
+ struct objspace *objspace = (struct objspace *)arg;
+
+ make_final_job(objspace, (VALUE)key, (VALUE)val);
+
+ return ST_DELETE;
+}
+
+void
+rb_gc_impl_shutdown_call_finalizer(void *objspace_ptr)
+{
+ struct objspace *objspace = objspace_ptr;
+
+ while (objspace->finalizer_table->num_entries) {
+ st_foreach(objspace->finalizer_table, move_finalizer_from_table_i, (st_data_t)objspace);
+
+ gc_run_finalizers(objspace);
+ }
+
+ unsigned int lev = RB_GC_VM_LOCK();
+ {
+ struct MMTk_RawVecOfObjRef registered_candidates = mmtk_get_all_obj_free_candidates();
+ for (size_t i = 0; i < registered_candidates.len; i++) {
+ VALUE obj = (VALUE)registered_candidates.ptr[i];
+
+ if (rb_gc_shutdown_call_finalizer_p(obj)) {
+ rb_gc_obj_free(objspace_ptr, obj);
+ RBASIC(obj)->flags = 0;
+ }
+ }
+ mmtk_free_raw_vec_of_obj_ref(registered_candidates);
+ }
+ RB_GC_VM_UNLOCK(lev);
+
+ gc_run_finalizers(objspace);
+}
+
+// Forking
+
+void
+rb_gc_impl_before_fork(void *objspace_ptr)
+{
+ struct objspace *objspace = objspace_ptr;
+
+ retry:
+ objspace->fork_hook_vm_lock_lev = RB_GC_VM_LOCK();
+ rb_gc_vm_barrier();
+
+ /* At this point, we know that all the Ractors are paused because of the
+ * rb_gc_vm_barrier above. Since rb_mmtk_block_for_gc is a barrier point,
+ * one or more Ractors could be paused there. However, mmtk_before_fork is
+ * not compatible with that because it assumes that the MMTk workers are idle,
+ * but the workers are not idle because they are busy working on a GC.
+ *
+ * This essentially implements a trylock. It will optimistically lock but will
+ * release the lock if it detects that any other Ractors are waiting in
+ * rb_mmtk_block_for_gc.
+ */
+ rb_atomic_t mutator_blocking_count = RUBY_ATOMIC_LOAD(objspace->mutator_blocking_count);
+ if (mutator_blocking_count != 0) {
+ RB_GC_VM_UNLOCK(objspace->fork_hook_vm_lock_lev);
+ goto retry;
+ }
+
+ mmtk_before_fork();
+}
+
+void
+rb_gc_impl_after_fork(void *objspace_ptr, rb_pid_t pid)
+{
+ struct objspace *objspace = objspace_ptr;
+
+ mmtk_after_fork(rb_gc_get_ractor_newobj_cache());
+
+ RB_GC_VM_UNLOCK(objspace->fork_hook_vm_lock_lev);
+}
+
+// Statistics
+
+void
+rb_gc_impl_set_measure_total_time(void *objspace_ptr, VALUE flag)
+{
+ struct objspace *objspace = objspace_ptr;
+
+ objspace->measure_gc_time = RTEST(flag);
+}
+
+bool
+rb_gc_impl_get_measure_total_time(void *objspace_ptr)
+{
+ struct objspace *objspace = objspace_ptr;
+
+ return objspace->measure_gc_time;
+}
+
+unsigned long long
+rb_gc_impl_get_total_time(void *objspace_ptr)
+{
+ struct objspace *objspace = objspace_ptr;
+
+ return objspace->total_gc_time;
+}
+
+size_t
+rb_gc_impl_gc_count(void *objspace_ptr)
+{
+ struct objspace *objspace = objspace_ptr;
+
+ return objspace->gc_count;
+}
+
+VALUE
+rb_gc_impl_latest_gc_info(void *objspace_ptr, VALUE hash_or_key)
+{
+ VALUE hash = Qnil, key = Qnil;
+
+ if (SYMBOL_P(hash_or_key)) {
+ key = hash_or_key;
+ }
+ else if (RB_TYPE_P(hash_or_key, T_HASH)) {
+ hash = hash_or_key;
+ }
+ else {
+ rb_bug("gc_info_decode: non-hash or symbol given");
+ }
+
+#define SET(name, attr) \
+ if (key == ID2SYM(rb_intern_const(#name))) \
+ return (attr); \
+ else if (hash != Qnil) \
+ rb_hash_aset(hash, ID2SYM(rb_intern_const(#name)), (attr));
+
+ /* Hack to get StackProf working because it calls rb_gc_latest_gc_info with
+ * the :state key and expects a result. This always returns the :none state. */
+ SET(state, ID2SYM(rb_intern_const("none")));
+#undef SET
+
+ if (!NIL_P(key)) {
+ // Matched key should return above
+ return Qundef;
+ }
+
+ return hash;
+}
+
+enum gc_stat_sym {
+ gc_stat_sym_count,
+ gc_stat_sym_time,
+ gc_stat_sym_total_allocated_objects,
+ gc_stat_sym_total_bytes,
+ gc_stat_sym_used_bytes,
+ gc_stat_sym_free_bytes,
+ gc_stat_sym_starting_heap_address,
+ gc_stat_sym_last_heap_address,
+ gc_stat_sym_last
+};
+
+static VALUE gc_stat_symbols[gc_stat_sym_last];
+
+static void
+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(total_allocated_objects);
+ S(total_bytes);
+ S(used_bytes);
+ S(free_bytes);
+ S(starting_heap_address);
+ S(last_heap_address);
+ }
+}
+
+VALUE
+rb_gc_impl_stat(void *objspace_ptr, VALUE hash_or_sym)
+{
+ struct objspace *objspace = objspace_ptr;
+ VALUE hash = Qnil, key = Qnil;
+
+ setup_gc_stat_symbols();
+
+ if (RB_TYPE_P(hash_or_sym, T_HASH)) {
+ hash = hash_or_sym;
+ }
+ else if (SYMBOL_P(hash_or_sym)) {
+ key = hash_or_sym;
+ }
+ else {
+ rb_bug("non-hash or symbol given");
+ }
+
+#define SET(name, attr) \
+ if (key == gc_stat_symbols[gc_stat_sym_##name]) \
+ return SIZET2NUM(attr); \
+ else if (hash != Qnil) \
+ rb_hash_aset(hash, gc_stat_symbols[gc_stat_sym_##name], SIZET2NUM(attr));
+
+ SET(count, objspace->gc_count);
+ SET(time, objspace->total_gc_time / (1000 * 1000));
+ SET(total_allocated_objects, objspace->total_allocated_objects);
+ SET(total_bytes, mmtk_total_bytes());
+ SET(used_bytes, mmtk_used_bytes());
+ SET(free_bytes, mmtk_free_bytes());
+ SET(starting_heap_address, (size_t)mmtk_starting_heap_address());
+ SET(last_heap_address, (size_t)mmtk_last_heap_address());
+#undef SET
+
+ if (!NIL_P(key)) {
+ // Matched key should return above
+ return Qundef;
+ }
+
+ return hash;
+}
+
+VALUE
+rb_gc_impl_stat_heap(void *objspace_ptr, VALUE heap_name, VALUE hash_or_sym)
+{
+ if (RB_TYPE_P(hash_or_sym, T_HASH)) {
+ return hash_or_sym;
+ }
+ else {
+ return Qundef;
+ }
+}
+
+// Miscellaneous
+
+#define RB_GC_OBJECT_METADATA_ENTRY_COUNT 1
+static struct rb_gc_object_metadata_entry object_metadata_entries[RB_GC_OBJECT_METADATA_ENTRY_COUNT + 1];
+
+struct rb_gc_object_metadata_entry *
+rb_gc_impl_object_metadata(void *objspace_ptr, VALUE obj)
+{
+ static ID ID_object_id;
+
+ if (!ID_object_id) {
+#define I(s) ID_##s = rb_intern(#s);
+ I(object_id);
+#undef I
+ }
+
+ size_t n = 0;
+
+#define SET_ENTRY(na, v) do { \
+ MMTK_ASSERT(n <= RB_GC_OBJECT_METADATA_ENTRY_COUNT); \
+ object_metadata_entries[n].name = ID_##na; \
+ object_metadata_entries[n].val = v; \
+ n++; \
+} while (0)
+
+ if (rb_obj_id_p(obj)) SET_ENTRY(object_id, rb_obj_id(obj));
+
+ object_metadata_entries[n].name = 0;
+ object_metadata_entries[n].val = 0;
+
+ return object_metadata_entries;
+}
+
+bool
+rb_gc_impl_pointer_to_heap_p(void *objspace_ptr, const void *ptr)
+{
+ if (ptr == NULL) return false;
+ if ((uintptr_t)ptr % sizeof(void*) != 0) return false;
+ return mmtk_is_mmtk_object((MMTk_Address)ptr);
+}
+
+bool
+rb_gc_impl_garbage_object_p(void *objspace_ptr, VALUE obj)
+{
+ return false;
+}
+
+void rb_gc_impl_set_event_hook(void *objspace_ptr, const rb_event_flag_t event) { }
+
+void
+rb_gc_impl_copy_attributes(void *objspace_ptr, VALUE dest, VALUE obj)
+{
+ if (mmtk_object_wb_unprotected_p((MMTk_ObjectReference)obj)) {
+ rb_gc_impl_writebarrier_unprotect(objspace_ptr, dest);
+ }
+
+ rb_gc_impl_copy_finalizer(objspace_ptr, dest, obj);
+}
+
+// GC Identification
+
+const char *
+rb_gc_impl_active_gc_name(void)
+{
+ return "mmtk";
+}
diff --git a/gc/mmtk/mmtk.h b/gc/mmtk/mmtk.h
new file mode 100644
index 0000000000..21a5bf9415
--- /dev/null
+++ b/gc/mmtk/mmtk.h
@@ -0,0 +1,172 @@
+#ifndef MMTK_H
+#define MMTK_H
+
+/* Warning, this file is autogenerated by cbindgen from the mmtk-ruby repository. Don't modify this manually. */
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+typedef struct MMTk_Builder MMTk_Builder;
+typedef struct MMTk_Mutator MMTk_Mutator;
+
+typedef struct MMTk_ractor_cache *MMTk_VMThread;
+typedef struct MMTk_ractor_cache *MMTk_VMMutatorThread;
+typedef struct MMTk_GCThreadTLS *MMTk_VMWorkerThread;
+typedef void *MMTk_Address;
+typedef void *MMTk_ObjectReference;
+typedef void *MMTk_NullableObjectReference;
+typedef uint32_t MMTk_AllocationSemantics;
+
+typedef struct MMTk_BumpPointer {
+ uintptr_t cursor;
+ uintptr_t limit;
+} MMTk_BumpPointer;
+
+
+#define MMTk_OBJREF_OFFSET 8
+
+#define MMTk_MIN_OBJ_ALIGN 8
+
+#define MMTk_GC_THREAD_KIND_WORKER 1
+
+typedef struct MMTk_RubyBindingOptions {
+ bool ractor_check_mode;
+ size_t suffix_size;
+} MMTk_RubyBindingOptions;
+
+typedef MMTk_ObjectReference (*MMTk_ObjectClosureFunction)(void*, void*, MMTk_ObjectReference, bool);
+
+typedef struct MMTk_ObjectClosure {
+ /**
+ * The function to be called from C.
+ */
+ MMTk_ObjectClosureFunction c_function;
+ /**
+ * The pointer to the Rust-level closure object.
+ */
+ void *rust_closure;
+} MMTk_ObjectClosure;
+
+typedef struct MMTk_GCThreadTLS {
+ int kind;
+ void *gc_context;
+ struct MMTk_ObjectClosure object_closure;
+} MMTk_GCThreadTLS;
+
+typedef struct MMTk_RubyUpcalls {
+ void (*init_gc_worker_thread)(struct MMTk_GCThreadTLS *gc_worker_tls);
+ bool (*is_mutator)(void);
+ void (*stop_the_world)(void);
+ void (*resume_mutators)(void);
+ void (*block_for_gc)(MMTk_VMMutatorThread tls);
+ void (*before_updating_jit_code)(void);
+ void (*after_updating_jit_code)(void);
+ size_t (*number_of_mutators)(void);
+ void (*get_mutators)(void (*visit_mutator)(MMTk_Mutator*, void*), void *data);
+ void (*scan_gc_roots)(void);
+ void (*scan_objspace)(void);
+ void (*move_obj_during_marking)(MMTk_ObjectReference from, MMTk_ObjectReference to);
+ void (*update_object_references)(MMTk_ObjectReference object);
+ void (*call_gc_mark_children)(MMTk_ObjectReference object);
+ void (*handle_weak_references)(MMTk_ObjectReference object, bool moving);
+ void (*call_obj_free)(MMTk_ObjectReference object);
+ size_t (*vm_live_bytes)(void);
+ void (*update_global_tables)(int tbl_idx);
+ int (*global_tables_count)(void);
+ void (*update_finalizer_table)(void);
+ bool (*special_const_p)(MMTk_ObjectReference object);
+ void (*mutator_thread_panic_handler)(void);
+ void (*gc_thread_panic_handler)(void);
+} MMTk_RubyUpcalls;
+
+typedef struct MMTk_RawVecOfObjRef {
+ MMTk_ObjectReference *ptr;
+ size_t len;
+ size_t capa;
+} MMTk_RawVecOfObjRef;
+
+bool mmtk_is_live_object(MMTk_ObjectReference object);
+
+bool mmtk_is_reachable(MMTk_ObjectReference object);
+
+MMTk_Builder *mmtk_builder_default(void);
+
+void mmtk_init_binding(MMTk_Builder *builder,
+ const struct MMTk_RubyBindingOptions *_binding_options,
+ const struct MMTk_RubyUpcalls *upcalls);
+
+void mmtk_initialize_collection(MMTk_VMThread tls);
+
+MMTk_Mutator *mmtk_bind_mutator(MMTk_VMMutatorThread tls);
+
+MMTk_BumpPointer *mmtk_get_bump_pointer_allocator(MMTk_Mutator *m);
+
+void mmtk_destroy_mutator(MMTk_Mutator *mutator);
+
+void mmtk_handle_user_collection_request(MMTk_VMMutatorThread tls, bool force, bool exhaustive);
+
+void mmtk_set_gc_enabled(bool enable);
+
+bool mmtk_gc_enabled_p(void);
+
+MMTk_Address mmtk_alloc(MMTk_Mutator *mutator,
+ size_t size,
+ size_t align,
+ size_t offset,
+ MMTk_AllocationSemantics semantics);
+
+void mmtk_post_alloc(MMTk_Mutator *mutator,
+ MMTk_ObjectReference refer,
+ size_t bytes,
+ MMTk_AllocationSemantics semantics);
+
+void mmtk_add_obj_free_candidate(MMTk_ObjectReference object, bool can_parallel_free);
+
+void mmtk_declare_weak_references(MMTk_ObjectReference object);
+
+bool mmtk_weak_references_alive_p(MMTk_ObjectReference object);
+
+void mmtk_register_pinning_obj(MMTk_ObjectReference obj);
+
+void mmtk_object_reference_write_post(MMTk_Mutator *mutator, MMTk_ObjectReference object);
+
+void mmtk_register_wb_unprotected_object(MMTk_ObjectReference object);
+
+bool mmtk_object_wb_unprotected_p(MMTk_ObjectReference object);
+
+void mmtk_enumerate_objects(void (*callback)(MMTk_ObjectReference, void*), void *data);
+
+struct MMTk_RawVecOfObjRef mmtk_get_all_obj_free_candidates(void);
+
+void mmtk_free_raw_vec_of_obj_ref(struct MMTk_RawVecOfObjRef raw_vec);
+
+void mmtk_before_fork(void);
+
+void mmtk_after_fork(MMTk_VMThread tls);
+
+size_t mmtk_total_bytes(void);
+
+size_t mmtk_used_bytes(void);
+
+size_t mmtk_free_bytes(void);
+
+MMTk_Address mmtk_starting_heap_address(void);
+
+MMTk_Address mmtk_last_heap_address(void);
+
+size_t mmtk_worker_count(void);
+
+const uint8_t *mmtk_plan(void);
+
+const uint8_t *mmtk_heap_mode(void);
+
+size_t mmtk_heap_min(void);
+
+size_t mmtk_heap_max(void);
+
+bool mmtk_is_mmtk_object(MMTk_Address addr);
+
+#endif /* MMTK_H */
diff --git a/gc/mmtk/src/abi.rs b/gc/mmtk/src/abi.rs
new file mode 100644
index 0000000000..255b2b1e56
--- /dev/null
+++ b/gc/mmtk/src/abi.rs
@@ -0,0 +1,336 @@
+use crate::api::RubyMutator;
+use crate::extra_assert;
+use crate::Ruby;
+use libc::c_int;
+use mmtk::scheduler::GCWorker;
+use mmtk::util::Address;
+use mmtk::util::ObjectReference;
+use mmtk::util::VMMutatorThread;
+use mmtk::util::VMWorkerThread;
+
+// For the C binding
+pub const OBJREF_OFFSET: usize = 8;
+pub const MIN_OBJ_ALIGN: usize = 8; // Even on 32-bit machine. A Ruby object is at least 40 bytes large.
+
+pub const GC_THREAD_KIND_WORKER: libc::c_int = 1;
+
+const HIDDEN_SIZE_MASK: usize = 0x0000FFFFFFFFFFFF;
+
+// An opaque type for the C counterpart.
+#[allow(non_camel_case_types)]
+pub struct st_table;
+
+#[repr(C)]
+pub struct HiddenHeader {
+ pub prefix: usize,
+}
+
+impl HiddenHeader {
+ #[inline(always)]
+ pub fn is_sane(&self) -> bool {
+ self.prefix & !HIDDEN_SIZE_MASK == 0
+ }
+
+ #[inline(always)]
+ fn assert_sane(&self) {
+ extra_assert!(
+ self.is_sane(),
+ "Hidden header is corrupted: {:x}",
+ self.prefix
+ );
+ }
+
+ pub fn payload_size(&self) -> usize {
+ self.assert_sane();
+ self.prefix & HIDDEN_SIZE_MASK
+ }
+}
+
+/// Provide convenient methods for accessing Ruby objects.
+/// TODO: Wrap C functions in `RubyUpcalls` as Rust-friendly methods.
+pub struct RubyObjectAccess {
+ objref: ObjectReference,
+}
+
+impl RubyObjectAccess {
+ pub fn from_objref(objref: ObjectReference) -> Self {
+ Self { objref }
+ }
+
+ pub fn obj_start(&self) -> Address {
+ self.objref.to_raw_address().sub(Self::prefix_size())
+ }
+
+ pub fn payload_addr(&self) -> Address {
+ self.objref.to_raw_address()
+ }
+
+ pub fn suffix_addr(&self) -> Address {
+ self.objref.to_raw_address().add(self.payload_size())
+ }
+
+ pub fn obj_end(&self) -> Address {
+ self.suffix_addr() + Self::suffix_size()
+ }
+
+ fn hidden_header(&self) -> &'static HiddenHeader {
+ unsafe { self.obj_start().as_ref() }
+ }
+
+ #[allow(unused)] // Maybe we need to mutate the hidden header in the future.
+ fn hidden_header_mut(&self) -> &'static mut HiddenHeader {
+ unsafe { self.obj_start().as_mut_ref() }
+ }
+
+ pub fn payload_size(&self) -> usize {
+ self.hidden_header().payload_size()
+ }
+
+ fn flags_field(&self) -> Address {
+ self.objref.to_raw_address()
+ }
+
+ pub fn load_flags(&self) -> usize {
+ unsafe { self.flags_field().load::<usize>() }
+ }
+
+ pub fn prefix_size() -> usize {
+ // Currently, a hidden size field of word size is placed before each object.
+ OBJREF_OFFSET
+ }
+
+ pub fn suffix_size() -> usize {
+ // In RACTOR_CHECK_MODE, Ruby hides a field after each object to hold the Ractor ID.
+ unsafe { crate::BINDING_FAST.suffix_size }
+ }
+
+ pub fn object_size(&self) -> usize {
+ Self::prefix_size() + self.payload_size() + Self::suffix_size()
+ }
+}
+
+type ObjectClosureFunction =
+ extern "C" fn(*mut libc::c_void, *mut libc::c_void, ObjectReference, bool) -> ObjectReference;
+
+#[repr(C)]
+pub struct ObjectClosure {
+ /// The function to be called from C.
+ pub c_function: ObjectClosureFunction,
+ /// The pointer to the Rust-level closure object.
+ pub rust_closure: *mut libc::c_void,
+}
+
+impl Default for ObjectClosure {
+ fn default() -> Self {
+ Self {
+ c_function: THE_UNREGISTERED_CLOSURE_FUNC,
+ rust_closure: std::ptr::null_mut(),
+ }
+ }
+}
+
+/// Rust doesn't require function items to have a unique address.
+/// We therefore force using this particular constant.
+///
+/// See: https://rust-lang.github.io/rust-clippy/master/index.html#fn_address_comparisons
+const THE_UNREGISTERED_CLOSURE_FUNC: ObjectClosureFunction = ObjectClosure::c_function_unregistered;
+
+impl ObjectClosure {
+ /// Set this ObjectClosure temporarily to `visit_object`, and execute `f`. During the execution of
+ /// `f`, the Ruby VM may call this ObjectClosure. When the Ruby VM calls this ObjectClosure,
+ /// it effectively calls `visit_object`.
+ ///
+ /// This method is intended to run Ruby VM code in `f` with temporarily modified behavior of
+ /// `rb_gc_mark`, `rb_gc_mark_movable` and `rb_gc_location`
+ ///
+ /// Both `f` and `visit_object` may access and modify local variables in the environment where
+ /// `set_temporarily_and_run_code` called.
+ ///
+ /// Note that this function is not reentrant. Don't call this function in either `callback` or
+ /// `f`.
+ pub fn set_temporarily_and_run_code<'env, T, F1, F2>(
+ &mut self,
+ mut visit_object: F1,
+ f: F2,
+ ) -> T
+ where
+ F1: 'env + FnMut(&'static mut GCWorker<Ruby>, ObjectReference, bool) -> ObjectReference,
+ F2: 'env + FnOnce() -> T,
+ {
+ debug_assert!(
+ std::ptr::fn_addr_eq(self.c_function, THE_UNREGISTERED_CLOSURE_FUNC),
+ "set_temporarily_and_run_code is recursively called."
+ );
+ self.c_function = Self::c_function_registered::<F1>;
+ self.rust_closure = &mut visit_object as *mut F1 as *mut libc::c_void;
+ let result = f();
+ *self = Default::default();
+ result
+ }
+
+ extern "C" fn c_function_registered<F>(
+ rust_closure: *mut libc::c_void,
+ worker: *mut libc::c_void,
+ object: ObjectReference,
+ pin: bool,
+ ) -> ObjectReference
+ where
+ F: FnMut(&'static mut GCWorker<Ruby>, ObjectReference, bool) -> ObjectReference,
+ {
+ let rust_closure = unsafe { &mut *(rust_closure as *mut F) };
+ let worker = unsafe { &mut *(worker as *mut GCWorker<Ruby>) };
+ rust_closure(worker, object, pin)
+ }
+
+ extern "C" fn c_function_unregistered(
+ _rust_closure: *mut libc::c_void,
+ worker: *mut libc::c_void,
+ object: ObjectReference,
+ pin: bool,
+ ) -> ObjectReference {
+ let worker = unsafe { &mut *(worker as *mut GCWorker<Ruby>) };
+ panic!(
+ "object_closure is not set. worker ordinal: {}, object: {}, pin: {}",
+ worker.ordinal, object, pin
+ );
+ }
+}
+
+#[repr(C)]
+pub struct GCThreadTLS {
+ pub kind: libc::c_int,
+ pub gc_context: *mut libc::c_void,
+ pub object_closure: ObjectClosure,
+}
+
+impl GCThreadTLS {
+ fn new(kind: libc::c_int, gc_context: *mut libc::c_void) -> Self {
+ Self {
+ kind,
+ gc_context,
+ object_closure: Default::default(),
+ }
+ }
+
+ pub fn for_worker(gc_context: *mut GCWorker<Ruby>) -> Self {
+ Self::new(GC_THREAD_KIND_WORKER, gc_context as *mut libc::c_void)
+ }
+
+ pub fn from_vwt(vwt: VMWorkerThread) -> *mut GCThreadTLS {
+ unsafe { std::mem::transmute(vwt) }
+ }
+
+ /// Cast a pointer to `GCThreadTLS` to a ref, with assertion for null pointer.
+ ///
+ /// # Safety
+ ///
+ /// Has undefined behavior if `ptr` is invalid.
+ pub unsafe fn check_cast(ptr: *mut GCThreadTLS) -> &'static mut GCThreadTLS {
+ assert!(!ptr.is_null());
+ let result = unsafe { &mut *ptr };
+ debug_assert!({
+ let kind = result.kind;
+ kind == GC_THREAD_KIND_WORKER
+ });
+ result
+ }
+
+ /// Cast a pointer to `VMWorkerThread` to a ref, with assertion for null pointer.
+ ///
+ /// # Safety
+ ///
+ /// Has undefined behavior if `ptr` is invalid.
+ pub unsafe fn from_vwt_check(vwt: VMWorkerThread) -> &'static mut GCThreadTLS {
+ let ptr = Self::from_vwt(vwt);
+ unsafe { Self::check_cast(ptr) }
+ }
+
+ #[allow(clippy::not_unsafe_ptr_arg_deref)] // `transmute` does not dereference pointer
+ pub fn to_vwt(ptr: *mut Self) -> VMWorkerThread {
+ unsafe { std::mem::transmute(ptr) }
+ }
+
+ pub fn worker<'w>(&mut self) -> &'w mut GCWorker<Ruby> {
+ // NOTE: The returned ref points to the worker which does not have the same lifetime as self.
+ assert!(self.kind == GC_THREAD_KIND_WORKER);
+ unsafe { &mut *(self.gc_context as *mut GCWorker<Ruby>) }
+ }
+}
+
+#[repr(C)]
+#[derive(Clone)]
+pub struct RawVecOfObjRef {
+ pub ptr: *mut ObjectReference,
+ pub len: usize,
+ pub capa: usize,
+}
+
+impl RawVecOfObjRef {
+ pub fn from_vec(vec: Vec<ObjectReference>) -> RawVecOfObjRef {
+ // Note: Vec::into_raw_parts is unstable. We implement it manually.
+ let mut vec = std::mem::ManuallyDrop::new(vec);
+ let (ptr, len, capa) = (vec.as_mut_ptr(), vec.len(), vec.capacity());
+
+ RawVecOfObjRef { ptr, len, capa }
+ }
+
+ /// # Safety
+ ///
+ /// This function turns raw pointer into a Vec without check.
+ pub unsafe fn into_vec(self) -> Vec<ObjectReference> {
+ unsafe { Vec::from_raw_parts(self.ptr, self.len, self.capa) }
+ }
+}
+
+impl From<Vec<ObjectReference>> for RawVecOfObjRef {
+ fn from(v: Vec<ObjectReference>) -> Self {
+ Self::from_vec(v)
+ }
+}
+
+#[repr(C)]
+#[derive(Clone)]
+pub struct RubyBindingOptions {
+ pub ractor_check_mode: bool,
+ pub suffix_size: usize,
+}
+
+#[repr(C)]
+#[derive(Clone)]
+pub struct RubyUpcalls {
+ pub init_gc_worker_thread: extern "C" fn(gc_worker_tls: *mut GCThreadTLS),
+ pub is_mutator: extern "C" fn() -> bool,
+ pub stop_the_world: extern "C" fn(),
+ pub resume_mutators: extern "C" fn(),
+ pub block_for_gc: extern "C" fn(tls: VMMutatorThread),
+ pub before_updating_jit_code: extern "C" fn(),
+ pub after_updating_jit_code: extern "C" fn(),
+ pub number_of_mutators: extern "C" fn() -> usize,
+ pub get_mutators: extern "C" fn(
+ visit_mutator: extern "C" fn(*mut RubyMutator, *mut libc::c_void),
+ data: *mut libc::c_void,
+ ),
+ pub scan_gc_roots: extern "C" fn(),
+ pub scan_objspace: extern "C" fn(),
+ pub move_obj_during_marking: extern "C" fn(from: ObjectReference, to: ObjectReference),
+ pub update_object_references: extern "C" fn(object: ObjectReference),
+ pub call_gc_mark_children: extern "C" fn(object: ObjectReference),
+ pub handle_weak_references: extern "C" fn(object: ObjectReference, moving: bool),
+ pub call_obj_free: extern "C" fn(object: ObjectReference),
+ pub vm_live_bytes: extern "C" fn() -> usize,
+ pub update_global_tables: extern "C" fn(tbl_idx: c_int),
+ pub global_tables_count: extern "C" fn() -> c_int,
+ pub update_finalizer_table: extern "C" fn(),
+ pub special_const_p: extern "C" fn(object: ObjectReference) -> bool,
+ pub mutator_thread_panic_handler: extern "C" fn(),
+ pub gc_thread_panic_handler: extern "C" fn(),
+}
+
+unsafe impl Sync for RubyUpcalls {}
+
+#[repr(C)]
+#[derive(Clone)]
+pub struct HeapBounds {
+ pub start: *mut libc::c_void,
+ pub end: *mut libc::c_void,
+}
diff --git a/gc/mmtk/src/active_plan.rs b/gc/mmtk/src/active_plan.rs
new file mode 100644
index 0000000000..80372a7576
--- /dev/null
+++ b/gc/mmtk/src/active_plan.rs
@@ -0,0 +1,56 @@
+use std::collections::VecDeque;
+use std::marker::PhantomData;
+
+use crate::mmtk;
+use crate::upcalls;
+use crate::Ruby;
+use mmtk::util::opaque_pointer::*;
+use mmtk::vm::ActivePlan;
+use mmtk::Mutator;
+
+pub struct VMActivePlan {}
+
+impl ActivePlan<Ruby> for VMActivePlan {
+ fn number_of_mutators() -> usize {
+ (upcalls().number_of_mutators)()
+ }
+
+ fn is_mutator(_tls: VMThread) -> bool {
+ (upcalls().is_mutator)()
+ }
+
+ fn mutator(_tls: VMMutatorThread) -> &'static mut Mutator<Ruby> {
+ unimplemented!()
+ }
+
+ fn mutators<'a>() -> Box<dyn Iterator<Item = &'a mut Mutator<Ruby>> + 'a> {
+ let mut mutators = VecDeque::new();
+ (upcalls().get_mutators)(
+ add_mutator_to_vec,
+ &mut mutators as *mut VecDeque<&mut Mutator<Ruby>> as _,
+ );
+
+ Box::new(RubyMutatorIterator {
+ mutators,
+ phantom_data: PhantomData,
+ })
+ }
+}
+
+extern "C" fn add_mutator_to_vec(mutator: *mut Mutator<Ruby>, mutators: *mut libc::c_void) {
+ let mutators = unsafe { &mut *(mutators as *mut VecDeque<*mut Mutator<Ruby>>) };
+ mutators.push_back(unsafe { &mut *mutator });
+}
+
+struct RubyMutatorIterator<'a> {
+ mutators: VecDeque<&'a mut Mutator<Ruby>>,
+ phantom_data: PhantomData<&'a ()>,
+}
+
+impl<'a> Iterator for RubyMutatorIterator<'a> {
+ type Item = &'a mut Mutator<Ruby>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.mutators.pop_front()
+ }
+}
diff --git a/gc/mmtk/src/api.rs b/gc/mmtk/src/api.rs
new file mode 100644
index 0000000000..3515a2408b
--- /dev/null
+++ b/gc/mmtk/src/api.rs
@@ -0,0 +1,486 @@
+// Functions in this module are unsafe for one reason:
+// They are called by C functions and they need to pass raw pointers to Rust.
+#![allow(clippy::missing_safety_doc)]
+
+use mmtk::util::alloc::BumpPointer;
+use mmtk::util::alloc::ImmixAllocator;
+use mmtk::util::conversions;
+use mmtk::util::options::PlanSelector;
+use std::str::FromStr;
+use std::sync::atomic::Ordering;
+
+use crate::abi::RawVecOfObjRef;
+use crate::abi::RubyBindingOptions;
+use crate::abi::RubyUpcalls;
+use crate::binding;
+use crate::binding::RubyBinding;
+use crate::heap::RubyHeapTriggerConfig;
+use crate::heap::RUBY_HEAP_TRIGGER_CONFIG;
+use crate::mmtk;
+use crate::utils::default_heap_max;
+use crate::utils::parse_capacity;
+use crate::Ruby;
+use crate::RubySlot;
+use mmtk::memory_manager;
+use mmtk::memory_manager::mmtk_init;
+use mmtk::util::constants::MIN_OBJECT_SIZE;
+use mmtk::util::options::GCTriggerSelector;
+use mmtk::util::Address;
+use mmtk::util::ObjectReference;
+use mmtk::util::VMMutatorThread;
+use mmtk::util::VMThread;
+use mmtk::AllocationSemantics;
+use mmtk::MMTKBuilder;
+use mmtk::Mutator;
+
+pub type RubyMutator = Mutator<Ruby>;
+
+#[no_mangle]
+pub extern "C" fn mmtk_is_live_object(object: ObjectReference) -> bool {
+ memory_manager::is_live_object(object)
+}
+
+#[no_mangle]
+pub extern "C" fn mmtk_is_reachable(object: ObjectReference) -> bool {
+ object.is_reachable()
+}
+
+// =============== Bootup ===============
+
+fn parse_env_var_with<T, F: FnOnce(&str) -> Option<T>>(key: &str, parse: F) -> Option<T> {
+ let val = match std::env::var(key) {
+ Ok(val) => val,
+ Err(std::env::VarError::NotPresent) => return None,
+ Err(std::env::VarError::NotUnicode(os_string)) => {
+ eprintln!("[FATAL] Invalid {key} {os_string:?}");
+ std::process::exit(1);
+ }
+ };
+
+ let parsed = parse(&val).unwrap_or_else(|| {
+ eprintln!("[FATAL] Invalid {key} {val}");
+ std::process::exit(1);
+ });
+
+ Some(parsed)
+}
+
+fn parse_env_var<T: FromStr>(key: &str) -> Option<T> {
+ parse_env_var_with(key, |s| s.parse().ok())
+}
+
+fn mmtk_builder_default_parse_threads() -> Option<usize> {
+ parse_env_var("MMTK_THREADS")
+}
+
+fn mmtk_builder_default_parse_heap_min() -> usize {
+ const DEFAULT_HEAP_MIN: usize = 1 << 20;
+ parse_env_var_with("MMTK_HEAP_MIN", parse_capacity).unwrap_or(DEFAULT_HEAP_MIN)
+}
+
+fn mmtk_builder_default_parse_heap_max() -> usize {
+ parse_env_var_with("MMTK_HEAP_MAX", parse_capacity).unwrap_or_else(default_heap_max)
+}
+
+fn parse_float_env_var(key: &str, default: f64, min: f64, max: f64) -> f64 {
+ parse_env_var_with(key, |s| {
+ let mut float = f64::from_str(s).unwrap_or(default);
+
+ if float <= min {
+ eprintln!(
+ "{key} has value {float} which must be greater than {min}, using default instead"
+ );
+ float = default;
+ }
+
+ if float >= max {
+ eprintln!(
+ "{key} has value {float} which must be less than {max}, using default instead"
+ );
+ float = default;
+ }
+
+ Some(float)
+ })
+ .unwrap_or(default)
+}
+
+fn mmtk_builder_default_parse_heap_mode(heap_min: usize, heap_max: usize) -> GCTriggerSelector {
+ let make_fixed = || GCTriggerSelector::FixedHeapSize(heap_max);
+ let make_dynamic = || GCTriggerSelector::DynamicHeapSize(heap_min, heap_max);
+
+ parse_env_var_with("MMTK_HEAP_MODE", |s| match s {
+ "fixed" => Some(make_fixed()),
+ "dynamic" => Some(make_dynamic()),
+ "ruby" => {
+ let min_ratio = parse_float_env_var("RUBY_GC_HEAP_FREE_SLOTS_MIN_RATIO", 0.2, 0.0, 1.0);
+ let goal_ratio =
+ parse_float_env_var("RUBY_GC_HEAP_FREE_SLOTS_GOAL_RATIO", 0.4, min_ratio, 1.0);
+ let max_ratio =
+ parse_float_env_var("RUBY_GC_HEAP_FREE_SLOTS_MAX_RATIO", 0.65, goal_ratio, 1.0);
+
+ crate::heap::RUBY_HEAP_TRIGGER_CONFIG
+ .set(RubyHeapTriggerConfig {
+ min_heap_pages: conversions::bytes_to_pages_up(heap_min),
+ max_heap_pages: conversions::bytes_to_pages_up(heap_max),
+ heap_pages_min_ratio: min_ratio,
+ heap_pages_goal_ratio: goal_ratio,
+ heap_pages_max_ratio: max_ratio,
+ })
+ .unwrap_or_else(|_| panic!("RUBY_HEAP_TRIGGER_CONFIG is already set"));
+
+ Some(GCTriggerSelector::Delegated)
+ }
+ _ => None,
+ })
+ .unwrap_or_else(make_dynamic)
+}
+
+fn mmtk_builder_default_parse_plan() -> PlanSelector {
+ parse_env_var_with("MMTK_PLAN", |s| match s {
+ "NoGC" => Some(PlanSelector::NoGC),
+ "MarkSweep" => Some(PlanSelector::MarkSweep),
+ "Immix" => Some(PlanSelector::Immix),
+ _ => None,
+ })
+ .unwrap_or(PlanSelector::Immix)
+}
+
+#[no_mangle]
+pub extern "C" fn mmtk_builder_default() -> *mut MMTKBuilder {
+ let mut builder = MMTKBuilder::new_no_env_vars();
+ builder.options.no_finalizer.set(true);
+
+ if let Some(threads) = mmtk_builder_default_parse_threads() {
+ if !builder.options.threads.set(threads) {
+ // MMTk will validate it and reject 0.
+ eprintln!("[FATAL] Failed to set the number of MMTk threads to {threads}");
+ std::process::exit(1);
+ }
+ }
+
+ let heap_min = mmtk_builder_default_parse_heap_min();
+
+ let heap_max = mmtk_builder_default_parse_heap_max();
+
+ if heap_min >= heap_max {
+ eprintln!("[FATAL] MMTK_HEAP_MIN({heap_min}) >= MMTK_HEAP_MAX({heap_max})");
+ std::process::exit(1);
+ }
+
+ builder
+ .options
+ .gc_trigger
+ .set(mmtk_builder_default_parse_heap_mode(heap_min, heap_max));
+
+ builder.options.plan.set(mmtk_builder_default_parse_plan());
+
+ Box::into_raw(Box::new(builder))
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn mmtk_init_binding(
+ builder: *mut MMTKBuilder,
+ _binding_options: *const RubyBindingOptions,
+ upcalls: *const RubyUpcalls,
+) {
+ crate::MUTATOR_THREAD_PANIC_HANDLER
+ .set((unsafe { (*upcalls).clone() }).mutator_thread_panic_handler)
+ .unwrap_or_else(|_| panic!("MUTATOR_THREAD_PANIC_HANDLER is already initialized"));
+
+ crate::set_panic_hook();
+
+ let builder: Box<MMTKBuilder> = unsafe { Box::from_raw(builder) };
+ let binding_options = RubyBindingOptions {
+ ractor_check_mode: false,
+ suffix_size: 0,
+ };
+ let mmtk_boxed = mmtk_init(&builder);
+ let mmtk_static = Box::leak(Box::new(mmtk_boxed));
+
+ let mut binding = RubyBinding::new(mmtk_static, &binding_options, upcalls);
+ binding
+ .weak_proc
+ .init_parallel_obj_free_candidates(memory_manager::num_of_workers(binding.mmtk));
+
+ crate::BINDING
+ .set(binding)
+ .unwrap_or_else(|_| panic!("Binding is already initialized"));
+}
+
+#[no_mangle]
+pub extern "C" fn mmtk_initialize_collection(tls: VMThread) {
+ memory_manager::initialize_collection(mmtk(), tls)
+}
+
+#[no_mangle]
+pub extern "C" fn mmtk_bind_mutator(tls: VMMutatorThread) -> *mut RubyMutator {
+ Box::into_raw(memory_manager::bind_mutator(mmtk(), tls))
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn mmtk_get_bump_pointer_allocator(m: *mut RubyMutator) -> *mut BumpPointer {
+ match *crate::BINDING.get().unwrap().mmtk.get_options().plan {
+ PlanSelector::Immix => {
+ let mutator: &mut Mutator<Ruby> = unsafe { &mut *m };
+ let allocator =
+ unsafe { mutator.allocator_mut(mmtk::util::alloc::AllocatorSelector::Immix(0)) };
+
+ if let Some(immix_allocator) = allocator.downcast_mut::<ImmixAllocator<Ruby>>() {
+ &mut immix_allocator.bump_pointer as *mut BumpPointer
+ } else {
+ panic!("Failed to get bump pointer allocator");
+ }
+ }
+ _ => std::ptr::null_mut(),
+ }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn mmtk_destroy_mutator(mutator: *mut RubyMutator) {
+ // notify mmtk-core about destroyed mutator
+ memory_manager::destroy_mutator(unsafe { &mut *mutator });
+ // turn the ptr back to a box, and let Rust properly reclaim it
+ let _ = unsafe { Box::from_raw(mutator) };
+}
+
+// =============== GC ===============
+
+#[no_mangle]
+pub extern "C" fn mmtk_handle_user_collection_request(
+ tls: VMMutatorThread,
+ force: bool,
+ exhaustive: bool,
+) {
+ crate::mmtk().handle_user_collection_request(tls, force, exhaustive);
+}
+
+#[no_mangle]
+pub extern "C" fn mmtk_set_gc_enabled(enable: bool) {
+ crate::CONFIGURATION
+ .gc_enabled
+ .store(enable, Ordering::Relaxed);
+}
+
+#[no_mangle]
+pub extern "C" fn mmtk_gc_enabled_p() -> bool {
+ crate::CONFIGURATION.gc_enabled.load(Ordering::Relaxed)
+}
+
+// =============== Object allocation ===============
+
+#[no_mangle]
+pub unsafe extern "C" fn mmtk_alloc(
+ mutator: *mut RubyMutator,
+ size: usize,
+ align: usize,
+ offset: usize,
+ semantics: AllocationSemantics,
+) -> Address {
+ let clamped_size = size.max(MIN_OBJECT_SIZE);
+ memory_manager::alloc::<Ruby>(
+ unsafe { &mut *mutator },
+ clamped_size,
+ align,
+ offset,
+ semantics,
+ )
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn mmtk_post_alloc(
+ mutator: *mut RubyMutator,
+ refer: ObjectReference,
+ bytes: usize,
+ semantics: AllocationSemantics,
+) {
+ memory_manager::post_alloc::<Ruby>(unsafe { &mut *mutator }, refer, bytes, semantics)
+}
+
+// TODO: Replace with buffered mmtk_add_obj_free_candidates
+#[no_mangle]
+pub extern "C" fn mmtk_add_obj_free_candidate(object: ObjectReference, can_parallel_free: bool) {
+ binding()
+ .weak_proc
+ .add_obj_free_candidate(object, can_parallel_free)
+}
+
+// =============== Weak references ===============
+
+#[no_mangle]
+pub extern "C" fn mmtk_declare_weak_references(object: ObjectReference) {
+ binding().weak_proc.add_weak_reference(object);
+}
+
+#[no_mangle]
+pub extern "C" fn mmtk_weak_references_alive_p(object: ObjectReference) -> bool {
+ object.is_reachable()
+}
+
+// =============== Compaction ===============
+
+#[no_mangle]
+pub extern "C" fn mmtk_register_pinning_obj(obj: ObjectReference) {
+ crate::binding().pinning_registry.register(obj);
+}
+
+// =============== Write barriers ===============
+
+#[no_mangle]
+pub unsafe extern "C" fn mmtk_object_reference_write_post(
+ mutator: *mut RubyMutator,
+ object: ObjectReference,
+) {
+ let ignored_slot = RubySlot::from_address(Address::ZERO);
+ let ignored_target = ObjectReference::from_raw_address(Address::ZERO);
+ mmtk::memory_manager::object_reference_write_post(
+ unsafe { &mut *mutator },
+ object,
+ ignored_slot,
+ ignored_target,
+ )
+}
+
+#[no_mangle]
+pub extern "C" fn mmtk_register_wb_unprotected_object(object: ObjectReference) {
+ crate::binding().register_wb_unprotected_object(object)
+}
+
+#[no_mangle]
+pub extern "C" fn mmtk_object_wb_unprotected_p(object: ObjectReference) -> bool {
+ crate::binding().object_wb_unprotected_p(object)
+}
+
+// =============== Heap walking ===============
+
+#[no_mangle]
+pub extern "C" fn mmtk_enumerate_objects(
+ callback: extern "C" fn(ObjectReference, *mut libc::c_void),
+ data: *mut libc::c_void,
+) {
+ crate::mmtk().enumerate_objects(|object| {
+ callback(object, data);
+ })
+}
+
+// =============== Finalizers ===============
+
+#[no_mangle]
+pub extern "C" fn mmtk_get_all_obj_free_candidates() -> RawVecOfObjRef {
+ let vec = binding().weak_proc.get_all_obj_free_candidates();
+ RawVecOfObjRef::from_vec(vec)
+}
+
+#[no_mangle]
+pub extern "C" fn mmtk_free_raw_vec_of_obj_ref(raw_vec: RawVecOfObjRef) {
+ unsafe { raw_vec.into_vec() };
+}
+
+// =============== Forking ===============
+
+#[no_mangle]
+pub extern "C" fn mmtk_before_fork() {
+ mmtk().prepare_to_fork();
+ binding().join_all_gc_threads();
+}
+
+#[no_mangle]
+pub extern "C" fn mmtk_after_fork(tls: VMThread) {
+ mmtk().after_fork(tls);
+}
+
+// =============== Statistics ===============
+
+#[no_mangle]
+pub extern "C" fn mmtk_total_bytes() -> usize {
+ memory_manager::total_bytes(mmtk())
+}
+
+#[no_mangle]
+pub extern "C" fn mmtk_used_bytes() -> usize {
+ memory_manager::used_bytes(mmtk())
+}
+
+#[no_mangle]
+pub extern "C" fn mmtk_free_bytes() -> usize {
+ memory_manager::free_bytes(mmtk())
+}
+
+#[no_mangle]
+pub extern "C" fn mmtk_starting_heap_address() -> Address {
+ memory_manager::starting_heap_address()
+}
+
+#[no_mangle]
+pub extern "C" fn mmtk_last_heap_address() -> Address {
+ memory_manager::last_heap_address()
+}
+
+#[no_mangle]
+pub extern "C" fn mmtk_worker_count() -> usize {
+ memory_manager::num_of_workers(mmtk())
+}
+
+#[no_mangle]
+pub extern "C" fn mmtk_plan() -> *const u8 {
+ static NO_GC: &[u8] = b"NoGC\0";
+ static MARK_SWEEP: &[u8] = b"MarkSweep\0";
+ static IMMIX: &[u8] = b"Immix\0";
+
+ match *crate::BINDING.get().unwrap().mmtk.get_options().plan {
+ PlanSelector::NoGC => NO_GC.as_ptr(),
+ PlanSelector::MarkSweep => MARK_SWEEP.as_ptr(),
+ PlanSelector::Immix => IMMIX.as_ptr(),
+ _ => panic!("Unknown plan"),
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn mmtk_heap_mode() -> *const u8 {
+ static FIXED_HEAP: &[u8] = b"fixed\0";
+ static DYNAMIC_HEAP: &[u8] = b"dynamic\0";
+ static RUBY_HEAP: &[u8] = b"ruby\0";
+
+ match *crate::BINDING.get().unwrap().mmtk.get_options().gc_trigger {
+ GCTriggerSelector::FixedHeapSize(_) => FIXED_HEAP.as_ptr(),
+ GCTriggerSelector::DynamicHeapSize(_, _) => DYNAMIC_HEAP.as_ptr(),
+ GCTriggerSelector::Delegated => RUBY_HEAP.as_ptr(),
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn mmtk_heap_min() -> usize {
+ match *crate::BINDING.get().unwrap().mmtk.get_options().gc_trigger {
+ GCTriggerSelector::FixedHeapSize(_) => 0,
+ GCTriggerSelector::DynamicHeapSize(min_size, _) => min_size,
+ GCTriggerSelector::Delegated => conversions::pages_to_bytes(
+ RUBY_HEAP_TRIGGER_CONFIG
+ .get()
+ .expect("RUBY_HEAP_TRIGGER_CONFIG not set")
+ .min_heap_pages,
+ ),
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn mmtk_heap_max() -> usize {
+ match *crate::BINDING.get().unwrap().mmtk.get_options().gc_trigger {
+ GCTriggerSelector::FixedHeapSize(max_size) => max_size,
+ GCTriggerSelector::DynamicHeapSize(_, max_size) => max_size,
+ GCTriggerSelector::Delegated => conversions::pages_to_bytes(
+ RUBY_HEAP_TRIGGER_CONFIG
+ .get()
+ .expect("RUBY_HEAP_TRIGGER_CONFIG not set")
+ .max_heap_pages,
+ ),
+ }
+}
+
+// =============== Miscellaneous ===============
+
+#[no_mangle]
+pub extern "C" fn mmtk_is_mmtk_object(addr: Address) -> bool {
+ debug_assert!(!addr.is_zero());
+ debug_assert!(addr.is_aligned_to(mmtk::util::is_mmtk_object::VO_BIT_REGION_SIZE));
+ memory_manager::is_mmtk_object(addr).is_some()
+}
diff --git a/gc/mmtk/src/binding.rs b/gc/mmtk/src/binding.rs
new file mode 100644
index 0000000000..36d4a992fd
--- /dev/null
+++ b/gc/mmtk/src/binding.rs
@@ -0,0 +1,129 @@
+use std::collections::HashSet;
+use std::ffi::CString;
+use std::sync::atomic::AtomicBool;
+use std::sync::Mutex;
+use std::thread::JoinHandle;
+
+use mmtk::util::ObjectReference;
+use mmtk::MMTK;
+
+use crate::abi;
+use crate::abi::RubyBindingOptions;
+use crate::pinning_registry::PinningRegistry;
+use crate::weak_proc::WeakProcessor;
+use crate::Ruby;
+
+pub struct RubyBindingFast {
+ pub suffix_size: usize,
+}
+
+impl Default for RubyBindingFast {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl RubyBindingFast {
+ pub const fn new() -> Self {
+ Self { suffix_size: 0 }
+ }
+}
+
+pub struct RubyConfiguration {
+ pub gc_enabled: AtomicBool,
+}
+
+impl Default for RubyConfiguration {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl RubyConfiguration {
+ pub const fn new() -> Self {
+ Self {
+ // Mimic the old behavior when the gc_enabled flag was in mmtk-core.
+ // We may refactor it so that it is false by default.
+ gc_enabled: AtomicBool::new(true),
+ }
+ }
+}
+
+pub struct RubyBinding {
+ pub mmtk: &'static MMTK<Ruby>,
+ pub options: RubyBindingOptions,
+ pub upcalls: *const abi::RubyUpcalls,
+ pub plan_name: Mutex<Option<CString>>,
+ pub weak_proc: WeakProcessor,
+ pub pinning_registry: PinningRegistry,
+ pub gc_thread_join_handles: Mutex<Vec<JoinHandle<()>>>,
+ pub wb_unprotected_objects: Mutex<HashSet<ObjectReference>>,
+}
+
+unsafe impl Sync for RubyBinding {}
+unsafe impl Send for RubyBinding {}
+
+impl RubyBinding {
+ pub fn new(
+ mmtk: &'static MMTK<Ruby>,
+ binding_options: &RubyBindingOptions,
+ upcalls: *const abi::RubyUpcalls,
+ ) -> Self {
+ unsafe {
+ crate::BINDING_FAST.suffix_size = binding_options.suffix_size;
+ }
+
+ Self {
+ mmtk,
+ options: binding_options.clone(),
+ upcalls,
+ plan_name: Mutex::new(None),
+ weak_proc: WeakProcessor::new(),
+ pinning_registry: PinningRegistry::new(),
+ gc_thread_join_handles: Default::default(),
+ wb_unprotected_objects: Default::default(),
+ }
+ }
+
+ pub fn upcalls(&self) -> &'static abi::RubyUpcalls {
+ unsafe { &*self.upcalls as &'static abi::RubyUpcalls }
+ }
+
+ pub fn get_plan_name_c(&self) -> *const libc::c_char {
+ let mut plan_name = self.plan_name.lock().unwrap();
+ if plan_name.is_none() {
+ let name_string = format!("{:?}", *self.mmtk.get_options().plan);
+ let c_string = CString::new(name_string)
+ .unwrap_or_else(|e| panic!("Failed converting plan name to CString: {e}"));
+ *plan_name = Some(c_string);
+ }
+ plan_name.as_deref().unwrap().as_ptr()
+ }
+
+ pub fn join_all_gc_threads(&self) {
+ let handles = {
+ let mut guard = self.gc_thread_join_handles.lock().unwrap();
+ std::mem::take(&mut *guard)
+ };
+
+ debug!("Joining GC threads...");
+ let total = handles.len();
+ let mut joined = 0;
+ for handle in handles {
+ handle.join().unwrap();
+ joined += 1;
+ debug!("{joined}/{total} GC threads joined.");
+ }
+ }
+
+ pub fn register_wb_unprotected_object(&self, object: ObjectReference) {
+ debug!("Registering WB-unprotected object: {object}");
+ let mut objects = self.wb_unprotected_objects.lock().unwrap();
+ objects.insert(object);
+ }
+
+ pub fn object_wb_unprotected_p(&self, object: ObjectReference) -> bool {
+ let objects = self.wb_unprotected_objects.lock().unwrap();
+ objects.contains(&object)
+ }
+}
diff --git a/gc/mmtk/src/collection.rs b/gc/mmtk/src/collection.rs
new file mode 100644
index 0000000000..83d046aef4
--- /dev/null
+++ b/gc/mmtk/src/collection.rs
@@ -0,0 +1,109 @@
+use crate::abi::GCThreadTLS;
+
+use crate::api::RubyMutator;
+use crate::heap::RubyHeapTrigger;
+use crate::mmtk;
+use crate::upcalls;
+use crate::Ruby;
+use mmtk::memory_manager;
+use mmtk::scheduler::*;
+use mmtk::util::heap::GCTriggerPolicy;
+use mmtk::util::VMMutatorThread;
+use mmtk::util::VMThread;
+use mmtk::util::VMWorkerThread;
+use mmtk::vm::Collection;
+use mmtk::vm::GCThreadContext;
+use std::sync::atomic::AtomicBool;
+use std::sync::atomic::Ordering;
+use std::thread;
+
+static CURRENT_GC_MAY_MOVE: AtomicBool = AtomicBool::new(false);
+
+pub struct VMCollection {}
+
+impl Collection<Ruby> for VMCollection {
+ fn is_collection_enabled() -> bool {
+ crate::CONFIGURATION.gc_enabled.load(Ordering::Relaxed)
+ }
+
+ fn stop_all_mutators<F>(tls: VMWorkerThread, mut mutator_visitor: F)
+ where
+ F: FnMut(&'static mut mmtk::Mutator<Ruby>),
+ {
+ (upcalls().stop_the_world)();
+
+ if crate::mmtk().get_plan().current_gc_may_move_object() {
+ CURRENT_GC_MAY_MOVE.store(true, Ordering::Relaxed);
+ (upcalls().before_updating_jit_code)();
+ } else {
+ CURRENT_GC_MAY_MOVE.store(false, Ordering::Relaxed);
+ }
+
+ crate::binding().pinning_registry.pin_children(tls);
+
+ (upcalls().get_mutators)(
+ Self::notify_mutator_ready::<F>,
+ &mut mutator_visitor as *mut F as *mut _,
+ );
+ }
+
+ fn resume_mutators(_tls: VMWorkerThread) {
+ if CURRENT_GC_MAY_MOVE.load(Ordering::Relaxed) {
+ (upcalls().after_updating_jit_code)();
+ }
+
+ (upcalls().resume_mutators)();
+ }
+
+ fn block_for_gc(tls: VMMutatorThread) {
+ (upcalls().block_for_gc)(tls);
+ }
+
+ fn spawn_gc_thread(_tls: VMThread, ctx: GCThreadContext<Ruby>) {
+ let join_handle = match ctx {
+ GCThreadContext::Worker(mut worker) => thread::Builder::new()
+ .name("MMTk Worker Thread".to_string())
+ .spawn(move || {
+ let ordinal = worker.ordinal;
+ debug!("Hello! This is MMTk Worker Thread running! ordinal: {ordinal}");
+ crate::register_gc_thread(thread::current().id());
+ let ptr_worker = &mut *worker as *mut GCWorker<Ruby>;
+ let gc_thread_tls =
+ Box::into_raw(Box::new(GCThreadTLS::for_worker(ptr_worker)));
+ (upcalls().init_gc_worker_thread)(gc_thread_tls);
+ memory_manager::start_worker(
+ mmtk(),
+ GCThreadTLS::to_vwt(gc_thread_tls),
+ worker,
+ );
+ debug!("An MMTk Worker Thread is quitting. Good bye! ordinal: {ordinal}");
+ crate::unregister_gc_thread(thread::current().id());
+ })
+ .unwrap(),
+ };
+
+ {
+ let mut handles = crate::binding().gc_thread_join_handles.lock().unwrap();
+ handles.push(join_handle);
+ }
+ }
+
+ fn vm_live_bytes() -> usize {
+ (upcalls().vm_live_bytes)()
+ }
+
+ fn create_gc_trigger() -> Box<dyn GCTriggerPolicy<Ruby>> {
+ Box::new(RubyHeapTrigger::default())
+ }
+}
+
+impl VMCollection {
+ extern "C" fn notify_mutator_ready<F>(mutator_ptr: *mut RubyMutator, data: *mut libc::c_void)
+ where
+ F: FnMut(&'static mut mmtk::Mutator<Ruby>),
+ {
+ let mutator = unsafe { &mut *mutator_ptr };
+ let mutator_visitor = unsafe { &mut *(data as *mut F) };
+ mutator_visitor(mutator);
+ }
+}
diff --git a/gc/mmtk/src/heap/mod.rs b/gc/mmtk/src/heap/mod.rs
new file mode 100644
index 0000000000..6af7c1b2e5
--- /dev/null
+++ b/gc/mmtk/src/heap/mod.rs
@@ -0,0 +1,4 @@
+mod ruby_heap_trigger;
+pub use ruby_heap_trigger::RubyHeapTrigger;
+pub use ruby_heap_trigger::RubyHeapTriggerConfig;
+pub use ruby_heap_trigger::RUBY_HEAP_TRIGGER_CONFIG;
diff --git a/gc/mmtk/src/heap/ruby_heap_trigger.rs b/gc/mmtk/src/heap/ruby_heap_trigger.rs
new file mode 100644
index 0000000000..fe1130043d
--- /dev/null
+++ b/gc/mmtk/src/heap/ruby_heap_trigger.rs
@@ -0,0 +1,105 @@
+use std::sync::atomic::AtomicUsize;
+use std::sync::atomic::Ordering;
+
+use mmtk::util::heap::GCTriggerPolicy;
+use mmtk::util::heap::SpaceStats;
+use mmtk::Plan;
+use mmtk::MMTK;
+use once_cell::sync::OnceCell;
+
+use crate::Ruby;
+
+pub static RUBY_HEAP_TRIGGER_CONFIG: OnceCell<RubyHeapTriggerConfig> = OnceCell::new();
+
+pub struct RubyHeapTriggerConfig {
+ /// Min heap size
+ pub min_heap_pages: usize,
+ /// Max heap size
+ pub max_heap_pages: usize,
+ /// Minimum ratio of empty space after a GC before the heap will grow
+ pub heap_pages_min_ratio: f64,
+ /// Ratio the heap will grow by
+ pub heap_pages_goal_ratio: f64,
+ /// Maximum ratio of empty space after a GC before the heap will shrink
+ pub heap_pages_max_ratio: f64,
+}
+
+pub struct RubyHeapTrigger {
+ /// Target number of heap pages
+ target_heap_pages: AtomicUsize,
+}
+
+impl GCTriggerPolicy<Ruby> for RubyHeapTrigger {
+ fn is_gc_required(
+ &self,
+ space_full: bool,
+ space: Option<SpaceStats<Ruby>>,
+ plan: &dyn Plan<VM = Ruby>,
+ ) -> bool {
+ // Let the plan decide
+ plan.collection_required(space_full, space)
+ }
+
+ fn on_gc_end(&self, mmtk: &'static MMTK<Ruby>) {
+ if let Some(plan) = mmtk.get_plan().generational() {
+ if plan.is_current_gc_nursery() {
+ // Nursery GC
+ } else {
+ // Full GC
+ }
+
+ panic!("TODO: support for generational GC not implemented")
+ } else {
+ let used_pages = mmtk.get_plan().get_used_pages();
+
+ let target_min =
+ (used_pages as f64 * (1.0 + Self::get_config().heap_pages_min_ratio)) as usize;
+ let target_max =
+ (used_pages as f64 * (1.0 + Self::get_config().heap_pages_max_ratio)) as usize;
+ let new_target =
+ (((used_pages as f64) * (1.0 + Self::get_config().heap_pages_goal_ratio)) as usize)
+ .clamp(
+ Self::get_config().min_heap_pages,
+ Self::get_config().max_heap_pages,
+ );
+
+ if used_pages < target_min || used_pages > target_max {
+ self.target_heap_pages.store(new_target, Ordering::Relaxed);
+ }
+ }
+ }
+
+ fn is_heap_full(&self, plan: &dyn Plan<VM = Ruby>) -> bool {
+ plan.get_reserved_pages() > self.target_heap_pages.load(Ordering::Relaxed)
+ }
+
+ fn get_current_heap_size_in_pages(&self) -> usize {
+ self.target_heap_pages.load(Ordering::Relaxed)
+ }
+
+ fn get_max_heap_size_in_pages(&self) -> usize {
+ Self::get_config().max_heap_pages
+ }
+
+ fn can_heap_size_grow(&self) -> bool {
+ self.target_heap_pages.load(Ordering::Relaxed) < Self::get_config().max_heap_pages
+ }
+}
+
+impl Default for RubyHeapTrigger {
+ fn default() -> Self {
+ let min_heap_pages = Self::get_config().min_heap_pages;
+
+ Self {
+ target_heap_pages: AtomicUsize::new(min_heap_pages),
+ }
+ }
+}
+
+impl RubyHeapTrigger {
+ fn get_config<'b>() -> &'b RubyHeapTriggerConfig {
+ RUBY_HEAP_TRIGGER_CONFIG
+ .get()
+ .expect("Attempt to use RUBY_HEAP_TRIGGER_CONFIG before it is initialized")
+ }
+}
diff --git a/gc/mmtk/src/lib.rs b/gc/mmtk/src/lib.rs
new file mode 100644
index 0000000000..52dc782051
--- /dev/null
+++ b/gc/mmtk/src/lib.rs
@@ -0,0 +1,161 @@
+// Warn about unsafe operations in functions that are already marked as unsafe.
+// This will become default in Rust 2024 edition.
+#![warn(unsafe_op_in_unsafe_fn)]
+
+extern crate libc;
+extern crate mmtk;
+#[macro_use]
+extern crate log;
+extern crate probe;
+
+use std::collections::HashSet;
+use std::panic::PanicHookInfo;
+use std::sync::Mutex;
+use std::thread::ThreadId;
+
+use abi::RubyUpcalls;
+use binding::RubyBinding;
+use binding::RubyBindingFast;
+use binding::RubyConfiguration;
+use mmtk::vm::slot::SimpleSlot;
+use mmtk::vm::slot::UnimplementedMemorySlice;
+use mmtk::vm::VMBinding;
+use mmtk::MMTK;
+use once_cell::sync::OnceCell;
+
+pub mod abi;
+pub mod active_plan;
+pub mod api;
+pub mod binding;
+pub mod collection;
+pub mod heap;
+pub mod object_model;
+pub mod pinning_registry;
+pub mod reference_glue;
+pub mod scanning;
+pub mod utils;
+pub mod weak_proc;
+
+#[derive(Default)]
+pub struct Ruby;
+
+/// Ruby slot type, i.e. a slot that holds a VALUE.
+/// Currently we use SimpleSlot.
+/// It doesn't matter, becaues we have not started using slot-enqueuing, yet.
+pub type RubySlot = SimpleSlot;
+
+/// Ruby memory slice, i.e. an array of VALUEs.
+/// It is used by array-copy barriers which is supposed to perform bettern than copying array
+/// elements one by one. At this moment, we just leave it unimplemented.
+pub type RubyMemorySlice = UnimplementedMemorySlice<RubySlot>;
+
+impl VMBinding for Ruby {
+ type VMObjectModel = object_model::VMObjectModel;
+ type VMScanning = scanning::VMScanning;
+ type VMCollection = collection::VMCollection;
+ type VMActivePlan = active_plan::VMActivePlan;
+ type VMReferenceGlue = reference_glue::VMReferenceGlue;
+
+ type VMSlot = RubySlot;
+ type VMMemorySlice = RubyMemorySlice;
+}
+
+/// The callback for mutator thread panic handler (which calls rb_bug to output
+/// debugging information such as the Ruby backtrace and memory maps).
+/// This is set before BINDING is set because mmtk_init could panic.
+pub static MUTATOR_THREAD_PANIC_HANDLER: OnceCell<extern "C" fn()> = OnceCell::new();
+
+/// The singleton object for the Ruby binding itself.
+pub static BINDING: OnceCell<RubyBinding> = OnceCell::new();
+
+/// Some data needs to be accessed fast.
+/// We sacrifice safety for speed using unsynchronized global variables.
+pub static mut BINDING_FAST: RubyBindingFast = RubyBindingFast::new();
+
+/// Some data needs to be accessed fast.
+pub static CONFIGURATION: RubyConfiguration = RubyConfiguration::new();
+
+pub fn binding<'b>() -> &'b RubyBinding {
+ BINDING
+ .get()
+ .expect("Attempt to use the binding before it is initialization")
+}
+
+pub fn mmtk() -> &'static MMTK<Ruby> {
+ binding().mmtk
+}
+
+pub fn upcalls() -> &'static RubyUpcalls {
+ binding().upcalls()
+}
+
+pub static GC_THREADS: OnceCell<Mutex<HashSet<ThreadId>>> = OnceCell::new();
+
+pub(crate) fn register_gc_thread(thread_id: ThreadId) {
+ let mut gc_threads = GC_THREADS.get().unwrap().lock().unwrap();
+ gc_threads.insert(thread_id);
+}
+
+pub(crate) fn unregister_gc_thread(thread_id: ThreadId) {
+ let mut gc_threads = GC_THREADS.get().unwrap().lock().unwrap();
+ gc_threads.remove(&thread_id);
+}
+
+pub(crate) fn is_gc_thread(thread_id: ThreadId) -> bool {
+ let gc_threads = GC_THREADS.get().unwrap().lock().unwrap();
+ gc_threads.contains(&thread_id)
+}
+
+fn handle_gc_thread_panic(panic_info: &PanicHookInfo) {
+ eprintln!("ERROR: An MMTk GC thread panicked. This is a bug.");
+ eprintln!("{panic_info}");
+
+ let bt = std::backtrace::Backtrace::capture();
+ match bt.status() {
+ std::backtrace::BacktraceStatus::Unsupported => {
+ eprintln!("Backtrace is unsupported.")
+ }
+ std::backtrace::BacktraceStatus::Disabled => {
+ eprintln!("Backtrace is disabled.");
+ eprintln!("run with `RUST_BACKTRACE=1` environment variable to display a backtrace");
+ }
+ std::backtrace::BacktraceStatus::Captured => {
+ eprintln!("{bt}");
+ }
+ s => {
+ eprintln!("Unknown backtrace status: {s:?}");
+ }
+ }
+}
+
+pub(crate) fn set_panic_hook() {
+ if GC_THREADS.set(Default::default()).is_err() {
+ return;
+ }
+
+ let old_hook = std::panic::take_hook();
+
+ std::panic::set_hook(Box::new(move |panic_info| {
+ if is_gc_thread(std::thread::current().id()) {
+ handle_gc_thread_panic(panic_info);
+
+ (crate::binding().upcalls().gc_thread_panic_handler)();
+ } else {
+ old_hook(panic_info);
+ (crate::MUTATOR_THREAD_PANIC_HANDLER
+ .get()
+ .expect("MUTATOR_THREAD_PANIC_HANDLER is not set"))();
+ }
+ }));
+}
+
+/// This kind of assertion is enabled if either building in debug mode or the
+/// "extra_assert" feature is enabled.
+#[macro_export]
+macro_rules! extra_assert {
+ ($($arg:tt)*) => {
+ if std::cfg!(any(debug_assertions, feature = "extra_assert")) {
+ std::assert!($($arg)*);
+ }
+ };
+}
diff --git a/gc/mmtk/src/object_model.rs b/gc/mmtk/src/object_model.rs
new file mode 100644
index 0000000000..d673ca11a0
--- /dev/null
+++ b/gc/mmtk/src/object_model.rs
@@ -0,0 +1,124 @@
+use std::ptr::copy_nonoverlapping;
+
+use crate::abi;
+use crate::abi::RubyObjectAccess;
+use crate::abi::MIN_OBJ_ALIGN;
+use crate::abi::OBJREF_OFFSET;
+use crate::Ruby;
+use mmtk::util::constants::BITS_IN_BYTE;
+use mmtk::util::copy::CopySemantics;
+use mmtk::util::copy::GCWorkerCopyContext;
+use mmtk::util::Address;
+use mmtk::util::ObjectReference;
+use mmtk::vm::*;
+
+pub struct VMObjectModel {}
+
+impl VMObjectModel {
+ const OBJREF_OFFSET: usize = abi::OBJREF_OFFSET;
+}
+
+impl ObjectModel<Ruby> for VMObjectModel {
+ const GLOBAL_LOG_BIT_SPEC: VMGlobalLogBitSpec = VMGlobalLogBitSpec::side_first();
+
+ // We overwrite the prepended word which were used to hold object sizes.
+ const LOCAL_FORWARDING_POINTER_SPEC: VMLocalForwardingPointerSpec =
+ VMLocalForwardingPointerSpec::in_header(-((OBJREF_OFFSET * BITS_IN_BYTE) as isize));
+
+ const LOCAL_FORWARDING_BITS_SPEC: VMLocalForwardingBitsSpec =
+ VMLocalForwardingBitsSpec::side_first();
+
+ const LOCAL_MARK_BIT_SPEC: VMLocalMarkBitSpec =
+ VMLocalMarkBitSpec::side_after(Self::LOCAL_FORWARDING_BITS_SPEC.as_spec());
+
+ const LOCAL_PINNING_BIT_SPEC: VMLocalPinningBitSpec =
+ VMLocalPinningBitSpec::side_after(Self::LOCAL_MARK_BIT_SPEC.as_spec());
+
+ const LOCAL_LOS_MARK_NURSERY_SPEC: VMLocalLOSMarkNurserySpec =
+ VMLocalLOSMarkNurserySpec::side_after(Self::LOCAL_PINNING_BIT_SPEC.as_spec());
+
+ const UNIFIED_OBJECT_REFERENCE_ADDRESS: bool = false;
+ const OBJECT_REF_OFFSET_LOWER_BOUND: isize = Self::OBJREF_OFFSET as isize;
+
+ const NEED_VO_BITS_DURING_TRACING: bool = true;
+
+ fn copy(
+ from: ObjectReference,
+ semantics: CopySemantics,
+ copy_context: &mut GCWorkerCopyContext<Ruby>,
+ ) -> ObjectReference {
+ let from_acc = RubyObjectAccess::from_objref(from);
+ let from_start = from_acc.obj_start();
+ let object_size = from_acc.object_size();
+ let to_start = copy_context.alloc_copy(from, object_size, MIN_OBJ_ALIGN, 0, semantics);
+ debug_assert!(!to_start.is_zero());
+ let to_payload = to_start.add(OBJREF_OFFSET);
+ unsafe {
+ copy_nonoverlapping::<u8>(from_start.to_ptr(), to_start.to_mut_ptr(), object_size);
+ }
+ let to_obj = unsafe { ObjectReference::from_raw_address_unchecked(to_payload) };
+ copy_context.post_copy(to_obj, object_size, semantics);
+ trace!("Copied object from {} to {}", from, to_obj);
+
+ (crate::binding().upcalls().move_obj_during_marking)(from, to_obj);
+
+ #[cfg(feature = "clear_old_copy")]
+ {
+ trace!(
+ "Clearing old copy {} ({}-{})",
+ from,
+ from_start,
+ from_start + object_size
+ );
+ // For debug purpose, we clear the old copy so that if the Ruby VM reads from the old
+ // copy again, it will likely result in an error.
+ unsafe { std::ptr::write_bytes::<u8>(from_start.to_mut_ptr(), 0, object_size) }
+ }
+
+ to_obj
+ }
+
+ fn copy_to(_from: ObjectReference, _to: ObjectReference, _region: Address) -> Address {
+ unimplemented!(
+ "This function cannot be called because we do not support MarkCompact for Ruby."
+ )
+ }
+
+ fn get_reference_when_copied_to(_from: ObjectReference, _to: Address) -> ObjectReference {
+ unimplemented!(
+ "This function cannot be called because we do not support MarkCompact for Ruby."
+ )
+ }
+
+ fn get_current_size(object: ObjectReference) -> usize {
+ RubyObjectAccess::from_objref(object).object_size()
+ }
+
+ fn get_type_descriptor(_reference: ObjectReference) -> &'static [i8] {
+ todo!()
+ }
+
+ fn ref_to_object_start(object: ObjectReference) -> Address {
+ RubyObjectAccess::from_objref(object).obj_start()
+ }
+
+ fn ref_to_header(object: ObjectReference) -> Address {
+ RubyObjectAccess::from_objref(object).payload_addr()
+ }
+
+ fn get_size_when_copied(object: ObjectReference) -> usize {
+ Self::get_current_size(object)
+ }
+
+ fn get_align_when_copied(_object: ObjectReference) -> usize {
+ todo!()
+ }
+
+ fn get_align_offset_when_copied(_object: ObjectReference) -> usize {
+ todo!()
+ }
+
+ fn dump_object(_object: ObjectReference) {
+ todo!()
+ }
+}
diff --git a/gc/mmtk/src/pinning_registry.rs b/gc/mmtk/src/pinning_registry.rs
new file mode 100644
index 0000000000..b498b508f1
--- /dev/null
+++ b/gc/mmtk/src/pinning_registry.rs
@@ -0,0 +1,187 @@
+use std::sync::Mutex;
+
+use mmtk::memory_manager;
+use mmtk::scheduler::GCWork;
+use mmtk::scheduler::GCWorker;
+use mmtk::scheduler::WorkBucketStage;
+use mmtk::util::ObjectReference;
+use mmtk::util::VMWorkerThread;
+use mmtk::MMTK;
+
+use crate::abi::GCThreadTLS;
+use crate::upcalls;
+use crate::Ruby;
+
+pub struct PinningRegistry {
+ pinning_objs: Mutex<Vec<ObjectReference>>,
+ pinned_objs: Mutex<Vec<ObjectReference>>,
+}
+
+impl PinningRegistry {
+ pub fn new() -> Self {
+ Self {
+ pinning_objs: Default::default(),
+ pinned_objs: Default::default(),
+ }
+ }
+
+ pub fn register(&self, object: ObjectReference) {
+ let mut pinning_objs = self.pinning_objs.lock().unwrap();
+ pinning_objs.push(object);
+ }
+
+ pub fn pin_children(&self, tls: VMWorkerThread) {
+ if !crate::mmtk().get_plan().current_gc_may_move_object() {
+ log::debug!("The current GC is non-moving, skipping pinning children.");
+ return;
+ }
+
+ let gc_tls = unsafe { GCThreadTLS::from_vwt_check(tls) };
+ let worker = gc_tls.worker();
+
+ let pinning_objs = self
+ .pinning_objs
+ .try_lock()
+ .expect("PinningRegistry should not have races during GC.");
+
+ let packet_size = 512;
+ let work_packets = pinning_objs
+ .chunks(packet_size)
+ .map(|chunk| {
+ Box::new(PinPinningChildren {
+ pinning_objs: chunk.to_vec(),
+ }) as _
+ })
+ .collect();
+
+ worker.scheduler().work_buckets[WorkBucketStage::Prepare].bulk_add(work_packets);
+ }
+
+ pub fn cleanup(&self, worker: &mut GCWorker<Ruby>) {
+ worker.scheduler().work_buckets[WorkBucketStage::VMRefClosure].add(RemoveDeadPinnings);
+ if crate::mmtk().get_plan().current_gc_may_move_object() {
+ let packet = {
+ let mut pinned_objs = self
+ .pinned_objs
+ .try_lock()
+ .expect("Unexpected contention on pinned_objs");
+ UnpinPinnedObjects {
+ objs: std::mem::take(&mut pinned_objs),
+ }
+ };
+
+ worker.scheduler().work_buckets[WorkBucketStage::VMRefClosure].add(packet);
+ } else {
+ debug!("The current GC is non-moving, skipping unpinning objects.");
+ debug_assert_eq!(
+ {
+ let pinned_objs = self
+ .pinned_objs
+ .try_lock()
+ .expect("Unexpected contention on pinned_objs");
+ pinned_objs.len()
+ },
+ 0
+ );
+ }
+ }
+}
+
+impl Default for PinningRegistry {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+struct PinPinningChildren {
+ pinning_objs: Vec<ObjectReference>,
+}
+
+impl GCWork<Ruby> for PinPinningChildren {
+ fn do_work(&mut self, worker: &mut GCWorker<Ruby>, _mmtk: &'static MMTK<Ruby>) {
+ let gc_tls = unsafe { GCThreadTLS::from_vwt_check(worker.tls) };
+ let mut pinned_objs = vec![];
+ let mut newly_pinned_objs = vec![];
+
+ let visit_object = |_worker, target_object: ObjectReference, pin| {
+ log::trace!(
+ " -> {} {}",
+ if pin { "(pin)" } else { " " },
+ target_object
+ );
+ if pin {
+ debug_assert!(
+ target_object.get_forwarded_object().is_none(),
+ "Trying to pin {target_object} but has been moved"
+ );
+
+ pinned_objs.push(target_object);
+ }
+ target_object
+ };
+
+ gc_tls
+ .object_closure
+ .set_temporarily_and_run_code(visit_object, || {
+ for obj in self.pinning_objs.iter().cloned() {
+ log::trace!(" Pinning: {}", obj);
+ (upcalls().call_gc_mark_children)(obj);
+ }
+ });
+
+ for target_object in pinned_objs {
+ if memory_manager::pin_object(target_object) {
+ newly_pinned_objs.push(target_object);
+ }
+ }
+
+ let mut pinned_objs = crate::binding()
+ .pinning_registry
+ .pinned_objs
+ .lock()
+ .unwrap();
+ pinned_objs.append(&mut newly_pinned_objs);
+ }
+}
+
+struct RemoveDeadPinnings;
+
+impl GCWork<Ruby> for RemoveDeadPinnings {
+ fn do_work(&mut self, _worker: &mut GCWorker<Ruby>, _mmtk: &'static MMTK<Ruby>) {
+ log::debug!("Removing dead Pinnings...");
+
+ let registry = &crate::binding().pinning_registry;
+ {
+ let mut pinning_objs = registry
+ .pinning_objs
+ .try_lock()
+ .expect("PinningRegistry should not have races during GC.");
+
+ pinning_objs.retain_mut(|obj| {
+ if obj.is_live() {
+ let new_obj = obj.get_forwarded_object().unwrap_or(*obj);
+ *obj = new_obj;
+ true
+ } else {
+ log::trace!(" Dead Pinning removed: {}", *obj);
+ false
+ }
+ });
+ }
+ }
+}
+
+struct UnpinPinnedObjects {
+ objs: Vec<ObjectReference>,
+}
+
+impl GCWork<Ruby> for UnpinPinnedObjects {
+ fn do_work(&mut self, _worker: &mut GCWorker<Ruby>, _mmtk: &'static MMTK<Ruby>) {
+ log::debug!("Unpinning pinned objects...");
+
+ for obj in self.objs.iter() {
+ let unpinned = memory_manager::unpin_object(*obj);
+ debug_assert!(unpinned);
+ }
+ }
+}
diff --git a/gc/mmtk/src/reference_glue.rs b/gc/mmtk/src/reference_glue.rs
new file mode 100644
index 0000000000..1272bd54c1
--- /dev/null
+++ b/gc/mmtk/src/reference_glue.rs
@@ -0,0 +1,26 @@
+use crate::Ruby;
+use mmtk::util::ObjectReference;
+use mmtk::util::VMWorkerThread;
+use mmtk::vm::ReferenceGlue;
+
+pub struct VMReferenceGlue {}
+
+impl ReferenceGlue<Ruby> for VMReferenceGlue {
+ type FinalizableType = ObjectReference;
+
+ fn get_referent(_object: ObjectReference) -> Option<ObjectReference> {
+ unimplemented!()
+ }
+
+ fn set_referent(_reff: ObjectReference, _referent: ObjectReference) {
+ unimplemented!()
+ }
+
+ fn enqueue_references(_references: &[ObjectReference], _tls: VMWorkerThread) {
+ unimplemented!()
+ }
+
+ fn clear_referent(_new_reference: ObjectReference) {
+ unimplemented!()
+ }
+}
diff --git a/gc/mmtk/src/scanning.rs b/gc/mmtk/src/scanning.rs
new file mode 100644
index 0000000000..355a2e7759
--- /dev/null
+++ b/gc/mmtk/src/scanning.rs
@@ -0,0 +1,291 @@
+use crate::abi::GCThreadTLS;
+
+use crate::upcalls;
+use crate::utils::ChunkedVecCollector;
+use crate::Ruby;
+use crate::RubySlot;
+use mmtk::memory_manager;
+use mmtk::scheduler::GCWork;
+use mmtk::scheduler::GCWorker;
+use mmtk::scheduler::WorkBucketStage;
+use mmtk::util::ObjectReference;
+use mmtk::util::VMWorkerThread;
+use mmtk::vm::ObjectTracer;
+use mmtk::vm::RootsWorkFactory;
+use mmtk::vm::Scanning;
+use mmtk::vm::SlotVisitor;
+use mmtk::Mutator;
+
+pub struct VMScanning {}
+
+impl Scanning<Ruby> for VMScanning {
+ const UNIQUE_OBJECT_ENQUEUING: bool = true;
+
+ fn support_slot_enqueuing(_tls: VMWorkerThread, _object: ObjectReference) -> bool {
+ false
+ }
+
+ fn scan_object<EV: SlotVisitor<RubySlot>>(
+ _tls: VMWorkerThread,
+ _object: ObjectReference,
+ _slot_visitor: &mut EV,
+ ) {
+ unreachable!("We have not enabled slot enqueuing for any types, yet.");
+ }
+
+ fn scan_object_and_trace_edges<OT: ObjectTracer>(
+ tls: VMWorkerThread,
+ object: ObjectReference,
+ object_tracer: &mut OT,
+ ) {
+ debug_assert!(
+ mmtk::memory_manager::is_mmtk_object(object.to_raw_address()).is_some(),
+ "Not an MMTk object: {object}",
+ );
+ let gc_tls = unsafe { GCThreadTLS::from_vwt_check(tls) };
+ let visit_object = |_worker, target_object: ObjectReference, pin| {
+ trace!(
+ "Tracing edge: {} -> {}{}",
+ object,
+ target_object,
+ if pin { " pin" } else { "" }
+ );
+ debug_assert!(
+ mmtk::memory_manager::is_mmtk_object(target_object.to_raw_address()).is_some(),
+ "Destination is not an MMTk object. Src: {object} dst: {target_object}"
+ );
+
+ debug_assert!(
+ // If we are in a moving GC, all objects should be pinned by PinningRegistry.
+ // If it is requested that target_object be pinned but it is not pinned, then
+ // it is a bug because it could be moved.
+ if crate::mmtk().get_plan().current_gc_may_move_object() && pin {
+ memory_manager::is_pinned(target_object)
+ } else {
+ true
+ },
+ "Object {object} is trying to pin {target_object}"
+ );
+
+ let forwarded_target = object_tracer.trace_object(target_object);
+ if forwarded_target != target_object {
+ trace!(" Forwarded target {target_object} -> {forwarded_target}");
+ }
+ forwarded_target
+ };
+ gc_tls
+ .object_closure
+ .set_temporarily_and_run_code(visit_object, || {
+ (upcalls().call_gc_mark_children)(object);
+
+ if crate::mmtk().get_plan().current_gc_may_move_object() {
+ (upcalls().update_object_references)(object);
+ }
+ });
+ }
+
+ fn notify_initial_thread_scan_complete(_partial_scan: bool, _tls: VMWorkerThread) {
+ // Do nothing
+ }
+
+ fn scan_roots_in_mutator_thread(
+ _tls: VMWorkerThread,
+ _mutator: &'static mut Mutator<Ruby>,
+ mut _factory: impl RootsWorkFactory<RubySlot>,
+ ) {
+ // Do nothing. All stacks (including Ruby stacks and machine stacks) are reachable from
+ // `rb_vm_t` -> ractor -> thread -> fiber -> stacks. It is part of `ScanGCRoots` which
+ // calls `rb_gc_mark_roots` -> `rb_vm_mark`.
+ }
+
+ fn scan_vm_specific_roots(tls: VMWorkerThread, factory: impl RootsWorkFactory<RubySlot>) {
+ let gc_tls = unsafe { GCThreadTLS::from_vwt_check(tls) };
+ let root_scanning_work_packets: Vec<Box<dyn GCWork<Ruby>>> = vec![
+ Box::new(ScanGCRoots::new(factory.clone())),
+ Box::new(ScanObjspace::new(factory.clone())),
+ ];
+ gc_tls.worker().scheduler().work_buckets[WorkBucketStage::Prepare]
+ .bulk_add(root_scanning_work_packets);
+
+ // Generate WB-unprotected roots scanning work packets
+
+ 'gen_wb_unprotected_work: {
+ let is_nursery_gc = (crate::mmtk().get_plan().generational())
+ .is_some_and(|gen| gen.is_current_gc_nursery());
+ if !is_nursery_gc {
+ break 'gen_wb_unprotected_work;
+ }
+
+ let vecs = {
+ let guard = crate::binding()
+ .wb_unprotected_objects
+ .try_lock()
+ .expect("Someone is holding the lock of wb_unprotected_objects?");
+ if guard.is_empty() {
+ break 'gen_wb_unprotected_work;
+ }
+
+ let mut collector = ChunkedVecCollector::new(128);
+ collector.extend(guard.iter().copied());
+ collector.into_vecs()
+ };
+
+ let packets = vecs
+ .into_iter()
+ .map(|objects| {
+ let factory = factory.clone();
+ Box::new(ScanWbUnprotectedRoots { factory, objects }) as _
+ })
+ .collect::<Vec<_>>();
+
+ gc_tls.worker().scheduler().work_buckets[WorkBucketStage::Prepare].bulk_add(packets);
+ }
+ }
+
+ fn supports_return_barrier() -> bool {
+ false
+ }
+
+ fn prepare_for_roots_re_scanning() {
+ todo!()
+ }
+
+ fn process_weak_refs(
+ worker: &mut GCWorker<Ruby>,
+ tracer_context: impl mmtk::vm::ObjectTracerContext<Ruby>,
+ ) -> bool {
+ crate::binding()
+ .weak_proc
+ .process_weak_stuff(worker, tracer_context);
+ crate::binding().pinning_registry.cleanup(worker);
+ false
+ }
+
+ fn forward_weak_refs(
+ _worker: &mut GCWorker<Ruby>,
+ _tracer_context: impl mmtk::vm::ObjectTracerContext<Ruby>,
+ ) {
+ panic!("We can't use MarkCompact in Ruby.");
+ }
+}
+
+impl VMScanning {
+ const OBJECT_BUFFER_SIZE: usize = 4096;
+
+ fn collect_object_roots_in<F: FnOnce()>(
+ root_scan_kind: &str,
+ gc_tls: &mut GCThreadTLS,
+ factory: &mut impl RootsWorkFactory<RubySlot>,
+ callback: F,
+ ) {
+ let mut buffer: Vec<ObjectReference> = Vec::new();
+ let visit_object = |_, object: ObjectReference, pin| {
+ debug!(
+ "[{}] Visiting object: {}{}",
+ root_scan_kind,
+ object,
+ if pin {
+ "(unmovable root)"
+ } else {
+ "(movable, but we pin it anyway)"
+ }
+ );
+ debug_assert!(
+ mmtk::memory_manager::is_mmtk_object(object.to_raw_address()).is_some(),
+ "Root does not point to MMTk object. object: {object}"
+ );
+ buffer.push(object);
+ if buffer.len() >= Self::OBJECT_BUFFER_SIZE {
+ factory.create_process_pinning_roots_work(std::mem::take(&mut buffer));
+ }
+ object
+ };
+ gc_tls
+ .object_closure
+ .set_temporarily_and_run_code(visit_object, callback);
+
+ if !buffer.is_empty() {
+ factory.create_process_pinning_roots_work(buffer);
+ }
+ }
+}
+
+trait GlobaRootScanningWork {
+ type F: RootsWorkFactory<RubySlot>;
+ const NAME: &'static str;
+
+ fn new(factory: Self::F) -> Self;
+ fn scan_roots();
+ fn roots_work_factory(&mut self) -> &mut Self::F;
+
+ fn do_work(&mut self, worker: &mut GCWorker<Ruby>, _mmtk: &'static mmtk::MMTK<Ruby>) {
+ let gc_tls = unsafe { GCThreadTLS::from_vwt_check(worker.tls) };
+
+ let factory = self.roots_work_factory();
+
+ VMScanning::collect_object_roots_in(Self::NAME, gc_tls, factory, || {
+ Self::scan_roots();
+ });
+ }
+}
+
+macro_rules! define_global_root_scanner {
+ ($name: ident, $code: expr) => {
+ struct $name<F: RootsWorkFactory<RubySlot>> {
+ factory: F,
+ }
+ impl<F: RootsWorkFactory<RubySlot>> GlobaRootScanningWork for $name<F> {
+ type F = F;
+ const NAME: &'static str = stringify!($name);
+ fn new(factory: Self::F) -> Self {
+ Self { factory }
+ }
+ fn scan_roots() {
+ $code
+ }
+ fn roots_work_factory(&mut self) -> &mut Self::F {
+ &mut self.factory
+ }
+ }
+ impl<F: RootsWorkFactory<RubySlot>> GCWork<Ruby> for $name<F> {
+ fn do_work(&mut self, worker: &mut GCWorker<Ruby>, mmtk: &'static mmtk::MMTK<Ruby>) {
+ GlobaRootScanningWork::do_work(self, worker, mmtk);
+ }
+ }
+ };
+}
+
+define_global_root_scanner!(ScanGCRoots, {
+ (crate::upcalls().scan_gc_roots)();
+});
+
+define_global_root_scanner!(ScanObjspace, {
+ (crate::upcalls().scan_objspace)();
+});
+
+struct ScanWbUnprotectedRoots<F: RootsWorkFactory<RubySlot>> {
+ factory: F,
+ objects: Vec<ObjectReference>,
+}
+
+impl<F: RootsWorkFactory<RubySlot>> GCWork<Ruby> for ScanWbUnprotectedRoots<F> {
+ fn do_work(&mut self, worker: &mut GCWorker<Ruby>, _mmtk: &'static mmtk::MMTK<Ruby>) {
+ let gc_tls = unsafe { GCThreadTLS::from_vwt_check(worker.tls) };
+ VMScanning::collect_object_roots_in("wb_unprot_roots", gc_tls, &mut self.factory, || {
+ for object in self.objects.iter().copied() {
+ if object.is_reachable() {
+ debug!("[wb_unprot_roots] Visiting WB-unprotected object (parent): {object}");
+ (upcalls().call_gc_mark_children)(object);
+
+ if crate::mmtk().get_plan().current_gc_may_move_object() {
+ (upcalls().update_object_references)(object);
+ }
+ } else {
+ debug!(
+ "[wb_unprot_roots] Skipping young WB-unprotected object (parent): {object}"
+ );
+ }
+ }
+ });
+ }
+}
diff --git a/gc/mmtk/src/utils.rs b/gc/mmtk/src/utils.rs
new file mode 100644
index 0000000000..d1979eaf58
--- /dev/null
+++ b/gc/mmtk/src/utils.rs
@@ -0,0 +1,161 @@
+use std::sync::atomic::AtomicUsize;
+use std::sync::atomic::Ordering;
+
+use atomic_refcell::AtomicRefCell;
+use mmtk::scheduler::GCWork;
+use mmtk::scheduler::GCWorker;
+use mmtk::scheduler::WorkBucketStage;
+
+use crate::Ruby;
+use sysinfo::System;
+
+pub struct ChunkedVecCollector<T> {
+ vecs: Vec<Vec<T>>,
+ current_vec: Vec<T>,
+ chunk_size: usize,
+}
+
+impl<T> ChunkedVecCollector<T> {
+ pub fn new(chunk_size: usize) -> Self {
+ Self {
+ vecs: vec![],
+ current_vec: Vec::with_capacity(chunk_size),
+ chunk_size,
+ }
+ }
+
+ pub fn add(&mut self, item: T) {
+ self.current_vec.push(item);
+ if self.current_vec.len() == self.chunk_size {
+ self.flush();
+ }
+ }
+
+ fn flush(&mut self) {
+ let new_vec = Vec::with_capacity(self.chunk_size);
+ let old_vec = std::mem::replace(&mut self.current_vec, new_vec);
+ self.vecs.push(old_vec);
+ }
+
+ pub fn into_vecs(mut self) -> Vec<Vec<T>> {
+ if !self.current_vec.is_empty() {
+ self.flush();
+ }
+ self.vecs
+ }
+}
+
+impl<A> Extend<A> for ChunkedVecCollector<A> {
+ fn extend<T: IntoIterator<Item = A>>(&mut self, iter: T) {
+ for item in iter {
+ self.add(item);
+ }
+ }
+}
+
+pub struct AfterAll {
+ counter: AtomicUsize,
+ stage: WorkBucketStage,
+ packets: AtomicRefCell<Vec<Box<dyn GCWork<Ruby>>>>,
+}
+
+unsafe impl Sync for AfterAll {}
+
+impl AfterAll {
+ pub fn new(stage: WorkBucketStage) -> Self {
+ Self {
+ counter: AtomicUsize::new(0),
+ stage,
+ packets: AtomicRefCell::new(vec![]),
+ }
+ }
+
+ pub fn add_packets(&self, mut packets: Vec<Box<dyn GCWork<Ruby>>>) {
+ let mut borrow = self.packets.borrow_mut();
+ borrow.append(&mut packets);
+ }
+
+ pub fn count_up(&self, n: usize) {
+ self.counter.fetch_add(n, Ordering::SeqCst);
+ }
+
+ pub fn count_down(&self, worker: &mut GCWorker<Ruby>) {
+ let old = self.counter.fetch_sub(1, Ordering::SeqCst);
+ if old == 1 {
+ let packets = {
+ let mut borrow = self.packets.borrow_mut();
+ std::mem::take(borrow.as_mut())
+ };
+ worker.scheduler().work_buckets[self.stage].bulk_add(packets);
+ }
+ }
+}
+
+pub fn default_heap_max() -> usize {
+ let mut s = System::new();
+ s.refresh_memory();
+ s.total_memory()
+ .checked_mul(80)
+ .and_then(|v| v.checked_div(100))
+ .expect("Invalid Memory size") as usize
+}
+
+pub fn parse_capacity(input: &str) -> Option<usize> {
+ let trimmed = input.trim();
+
+ const KIBIBYTE: usize = 1024;
+ const MEBIBYTE: usize = 1024 * KIBIBYTE;
+ const GIBIBYTE: usize = 1024 * MEBIBYTE;
+
+ let (number, suffix) = if let Some(pos) = trimmed.find(|c: char| !c.is_numeric()) {
+ trimmed.split_at(pos)
+ } else {
+ (trimmed, "")
+ };
+
+ let Ok(v) = number.parse::<usize>() else {
+ return None;
+ };
+
+ match suffix {
+ "GiB" => Some(v * GIBIBYTE),
+ "MiB" => Some(v * MEBIBYTE),
+ "KiB" => Some(v * KIBIBYTE),
+ "" => Some(v),
+ _ => None,
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_parse_capacity_parses_bare_bytes() {
+ assert_eq!(Some(1234), parse_capacity("1234"));
+ }
+
+ #[test]
+ fn test_parse_capacity_parses_kibibytes() {
+ assert_eq!(Some(10240), parse_capacity("10KiB"));
+ }
+
+ #[test]
+ fn test_parse_capacity_parses_mebibytes() {
+ assert_eq!(Some(10485760), parse_capacity("10MiB"))
+ }
+
+ #[test]
+ fn test_parse_capacity_parses_gibibytes() {
+ assert_eq!(Some(10737418240), parse_capacity("10GiB"))
+ }
+
+ #[test]
+ fn test_parse_capacity_parses_nonsense_values() {
+ assert_eq!(None, parse_capacity("notanumber"));
+ assert_eq!(None, parse_capacity("5tartswithanumber"));
+ assert_eq!(None, parse_capacity("number1nthemiddle"));
+ assert_eq!(None, parse_capacity("numberattheend111"));
+ assert_eq!(None, parse_capacity("mult1pl3numb3r5"));
+ }
+}
diff --git a/gc/mmtk/src/weak_proc.rs b/gc/mmtk/src/weak_proc.rs
new file mode 100644
index 0000000000..19dc6a0ee1
--- /dev/null
+++ b/gc/mmtk/src/weak_proc.rs
@@ -0,0 +1,318 @@
+use std::sync::atomic::AtomicUsize;
+use std::sync::atomic::Ordering;
+use std::sync::Mutex;
+
+use mmtk::scheduler::GCWork;
+use mmtk::scheduler::GCWorker;
+use mmtk::scheduler::WorkBucketStage;
+use mmtk::util::ObjectReference;
+use mmtk::vm::ObjectTracerContext;
+
+use crate::abi::GCThreadTLS;
+use crate::upcalls;
+use crate::Ruby;
+
+pub struct WeakProcessor {
+ non_parallel_obj_free_candidates: Mutex<Vec<ObjectReference>>,
+ parallel_obj_free_candidates: Vec<Mutex<Vec<ObjectReference>>>,
+ parallel_obj_free_candidates_counter: AtomicUsize,
+
+ /// Objects that needs `obj_free` called when dying.
+ /// If it is a bottleneck, replace it with a lock-free data structure,
+ /// or add candidates in batch.
+ weak_references: Mutex<Vec<ObjectReference>>,
+}
+
+impl Default for WeakProcessor {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl WeakProcessor {
+ pub fn new() -> Self {
+ Self {
+ non_parallel_obj_free_candidates: Mutex::new(Vec::new()),
+ parallel_obj_free_candidates: vec![Mutex::new(Vec::new())],
+ parallel_obj_free_candidates_counter: AtomicUsize::new(0),
+ weak_references: Mutex::new(Vec::new()),
+ }
+ }
+
+ pub fn init_parallel_obj_free_candidates(&mut self, num_workers: usize) {
+ debug_assert_eq!(self.parallel_obj_free_candidates.len(), 1);
+
+ for _ in 1..num_workers {
+ self.parallel_obj_free_candidates
+ .push(Mutex::new(Vec::new()));
+ }
+ }
+
+ /// Add an object as a candidate for `obj_free`.
+ ///
+ /// Multiple mutators can call it concurrently, so it has `&self`.
+ pub fn add_obj_free_candidate(&self, object: ObjectReference, can_parallel_free: bool) {
+ if can_parallel_free {
+ // Newly allocated objects are placed in parallel_obj_free_candidates using
+ // round-robin. This may not be ideal for load balancing.
+ let idx = self
+ .parallel_obj_free_candidates_counter
+ .fetch_add(1, Ordering::Relaxed)
+ % self.parallel_obj_free_candidates.len();
+
+ self.parallel_obj_free_candidates[idx]
+ .lock()
+ .unwrap()
+ .push(object);
+ } else {
+ self.non_parallel_obj_free_candidates
+ .lock()
+ .unwrap()
+ .push(object);
+ }
+ }
+
+ pub fn get_all_obj_free_candidates(&self) -> Vec<ObjectReference> {
+ // let mut obj_free_candidates = self.obj_free_candidates.lock().unwrap();
+ let mut all_obj_free_candidates = self
+ .non_parallel_obj_free_candidates
+ .lock()
+ .unwrap()
+ .to_vec();
+
+ for candidates_mutex in &self.parallel_obj_free_candidates {
+ all_obj_free_candidates.extend(candidates_mutex.lock().unwrap().to_vec());
+ }
+
+ std::mem::take(all_obj_free_candidates.as_mut())
+ }
+
+ pub fn add_weak_reference(&self, object: ObjectReference) {
+ let mut weak_references = self.weak_references.lock().unwrap();
+ weak_references.push(object);
+ }
+
+ pub fn process_weak_stuff(
+ &self,
+ worker: &mut GCWorker<Ruby>,
+ _tracer_context: impl ObjectTracerContext<Ruby>,
+ ) {
+ worker.add_work(
+ WorkBucketStage::VMRefClosure,
+ ProcessNonParallelObjFreeCanadidates {},
+ );
+
+ for index in 0..self.parallel_obj_free_candidates.len() {
+ worker.add_work(
+ WorkBucketStage::VMRefClosure,
+ ProcessParallelObjFreeCandidates { index },
+ );
+ }
+
+ worker.add_work(WorkBucketStage::VMRefClosure, ProcessWeakReferences);
+
+ worker.add_work(WorkBucketStage::Prepare, UpdateFinalizerObjIdTables);
+
+ let global_tables_count = (crate::upcalls().global_tables_count)();
+ let work_packets = (0..global_tables_count)
+ .map(|i| Box::new(UpdateGlobalTables { idx: i }) as _)
+ .collect();
+
+ worker.scheduler().work_buckets[WorkBucketStage::VMRefClosure].bulk_add(work_packets);
+
+ worker.scheduler().work_buckets[WorkBucketStage::VMRefClosure]
+ .bulk_add(vec![Box::new(UpdateWbUnprotectedObjectsList) as _]);
+ }
+}
+
+fn process_obj_free_candidates(obj_free_candidates: &mut Vec<ObjectReference>) {
+ // Process obj_free
+ let mut new_candidates = Vec::new();
+
+ for object in obj_free_candidates.iter().copied() {
+ if object.is_reachable() {
+ // Forward and add back to the candidate list.
+ let new_object = object.forward();
+ trace!("Forwarding obj_free candidate: {object} -> {new_object}");
+ new_candidates.push(new_object);
+ } else {
+ (upcalls().call_obj_free)(object);
+ }
+ }
+
+ *obj_free_candidates = new_candidates;
+}
+
+struct ProcessParallelObjFreeCandidates {
+ index: usize,
+}
+
+impl GCWork<Ruby> for ProcessParallelObjFreeCandidates {
+ fn do_work(&mut self, _worker: &mut GCWorker<Ruby>, _mmtk: &'static mmtk::MMTK<Ruby>) {
+ let mut obj_free_candidates = crate::binding().weak_proc.parallel_obj_free_candidates
+ [self.index]
+ .try_lock()
+ .expect("Lock for parallel_obj_free_candidates should not be held");
+
+ process_obj_free_candidates(&mut obj_free_candidates);
+ }
+}
+
+struct ProcessNonParallelObjFreeCanadidates;
+
+impl GCWork<Ruby> for ProcessNonParallelObjFreeCanadidates {
+ fn do_work(&mut self, _worker: &mut GCWorker<Ruby>, _mmtk: &'static mmtk::MMTK<Ruby>) {
+ let mut obj_free_candidates = crate::binding()
+ .weak_proc
+ .non_parallel_obj_free_candidates
+ .try_lock()
+ .expect("Lock for non_parallel_obj_free_candidates should not be held");
+
+ process_obj_free_candidates(&mut obj_free_candidates);
+ }
+}
+
+struct ProcessWeakReferences;
+
+impl GCWork<Ruby> for ProcessWeakReferences {
+ fn do_work(&mut self, worker: &mut GCWorker<Ruby>, _mmtk: &'static mmtk::MMTK<Ruby>) {
+ if crate::mmtk().get_plan().current_gc_may_move_object() {
+ let gc_tls: &mut GCThreadTLS = unsafe { GCThreadTLS::from_vwt_check(worker.tls) };
+
+ let visit_object = |_worker, target_object: ObjectReference, _pin| {
+ debug_assert!(
+ mmtk::memory_manager::is_mmtk_object(target_object.to_raw_address()).is_some(),
+ "Destination is not an MMTk object"
+ );
+
+ target_object
+ .get_forwarded_object()
+ .unwrap_or(target_object)
+ };
+
+ gc_tls
+ .object_closure
+ .set_temporarily_and_run_code(visit_object, || {
+ self.process_weak_references(true);
+ })
+ } else {
+ self.process_weak_references(false);
+ }
+ }
+}
+
+impl ProcessWeakReferences {
+ fn process_weak_references(&mut self, moving_gc: bool) {
+ let mut weak_references = crate::binding()
+ .weak_proc
+ .weak_references
+ .try_lock()
+ .expect("Mutators should not be holding the lock.");
+
+ weak_references.retain_mut(|object_ptr| {
+ let object = object_ptr.get_forwarded_object().unwrap_or(*object_ptr);
+
+ if object != *object_ptr {
+ *object_ptr = object;
+ }
+
+ if object.is_reachable() {
+ (upcalls().handle_weak_references)(object, moving_gc);
+
+ true
+ } else {
+ false
+ }
+ });
+ }
+}
+
+trait GlobalTableProcessingWork {
+ fn process_table(&mut self);
+
+ fn do_work(&mut self, worker: &mut GCWorker<Ruby>, _mmtk: &'static mmtk::MMTK<Ruby>) {
+ let gc_tls = unsafe { GCThreadTLS::from_vwt_check(worker.tls) };
+
+ // `hash_foreach_replace` depends on `gb_object_moved_p` which has to have the semantics
+ // of `trace_object` due to the way it is used in `UPDATE_IF_MOVED`.
+ let forward_object = |_worker, object: ObjectReference, _pin| {
+ debug_assert!(
+ mmtk::memory_manager::is_mmtk_object(object.to_raw_address()).is_some(),
+ "{object} is not an MMTk object"
+ );
+ let result = object.forward();
+ trace!("Forwarding reference: {object} -> {result}");
+ result
+ };
+
+ gc_tls
+ .object_closure
+ .set_temporarily_and_run_code(forward_object, || {
+ self.process_table();
+ });
+ }
+}
+
+struct UpdateFinalizerObjIdTables;
+impl GlobalTableProcessingWork for UpdateFinalizerObjIdTables {
+ fn process_table(&mut self) {
+ (crate::upcalls().update_finalizer_table)();
+ }
+}
+impl GCWork<Ruby> for UpdateFinalizerObjIdTables {
+ fn do_work(&mut self, worker: &mut GCWorker<Ruby>, mmtk: &'static mmtk::MMTK<Ruby>) {
+ GlobalTableProcessingWork::do_work(self, worker, mmtk);
+ }
+}
+
+struct UpdateGlobalTables {
+ idx: i32,
+}
+impl GlobalTableProcessingWork for UpdateGlobalTables {
+ fn process_table(&mut self) {
+ (crate::upcalls().update_global_tables)(self.idx)
+ }
+}
+impl GCWork<Ruby> for UpdateGlobalTables {
+ fn do_work(&mut self, worker: &mut GCWorker<Ruby>, mmtk: &'static mmtk::MMTK<Ruby>) {
+ GlobalTableProcessingWork::do_work(self, worker, mmtk);
+ }
+}
+
+struct UpdateWbUnprotectedObjectsList;
+
+impl GCWork<Ruby> for UpdateWbUnprotectedObjectsList {
+ fn do_work(&mut self, _worker: &mut GCWorker<Ruby>, _mmtk: &'static mmtk::MMTK<Ruby>) {
+ let mut objects = crate::binding().wb_unprotected_objects.try_lock().expect(
+ "Someone is holding the lock of wb_unprotected_objects during weak processing phase?",
+ );
+
+ let old_objects = std::mem::take(&mut *objects);
+
+ debug!("Updating {} WB-unprotected objects", old_objects.len());
+
+ for object in old_objects {
+ if object.is_reachable() {
+ // Forward and add back to the candidate list.
+ let new_object = object.forward();
+ trace!("Forwarding WB-unprotected object: {object} -> {new_object}");
+ objects.insert(new_object);
+ } else {
+ trace!("Removing WB-unprotected object from list: {object}");
+ }
+ }
+
+ debug!("Retained {} live WB-unprotected objects.", objects.len());
+ }
+}
+
+// Provide a shorthand `object.forward()`.
+trait Forwardable {
+ fn forward(&self) -> Self;
+}
+
+impl Forwardable for ObjectReference {
+ fn forward(&self) -> Self {
+ self.get_forwarded_object().unwrap_or(*self)
+ }
+}
diff --git a/gem_prelude.rb b/gem_prelude.rb
index bcd2560fab..1b78d80c72 100644
--- a/gem_prelude.rb
+++ b/gem_prelude.rb
@@ -25,4 +25,3 @@ begin
rescue LoadError
warn "`syntax_suggest' was not loaded."
end if defined?(SyntaxSuggest)
-
diff --git a/gems/bundled_gems b/gems/bundled_gems
index 43a3b72d69..c8414dee75 100644
--- a/gems/bundled_gems
+++ b/gems/bundled_gems
@@ -6,31 +6,43 @@
# - revision: revision in repository-url to test
# if `revision` is not given, "v"+`version` or `version` will be used.
-minitest 5.23.1 https://github.com/minitest/minitest
-power_assert 2.0.3 https://github.com/ruby/power_assert 84e85124c5014a139af39161d484156cfe87a9ed
-rake 13.2.1 https://github.com/ruby/rake
-test-unit 3.6.2 https://github.com/test-unit/test-unit
-rexml 3.2.8 https://github.com/ruby/rexml
-rss 0.3.0 https://github.com/ruby/rss
-net-ftp 0.3.5 https://github.com/ruby/net-ftp
-net-imap 0.4.12 https://github.com/ruby/net-imap
-net-pop 0.1.2 https://github.com/ruby/net-pop
-net-smtp 0.5.0 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 3.4.4 https://github.com/ruby/rbs ba7872795d5de04adb8ff500c0e6afdc81a041dd
-typeprof 0.21.11 https://github.com/ruby/typeprof b19a6416da3a05d57fadd6ffdadb382b6d236ca5
-debug 1.9.2 https://github.com/ruby/debug
-racc 1.8.0 https://github.com/ruby/racc
-mutex_m 0.2.0 https://github.com/ruby/mutex_m
-getoptlong 0.2.1 https://github.com/ruby/getoptlong
-base64 0.2.0 https://github.com/ruby/base64
-bigdecimal 3.1.8 https://github.com/ruby/bigdecimal
-observer 0.1.2 https://github.com/ruby/observer
-abbrev 0.1.2 https://github.com/ruby/abbrev
-resolv-replace 0.1.1 https://github.com/ruby/resolv-replace
-rinda 0.2.0 https://github.com/ruby/rinda
-drb 2.2.1 https://github.com/ruby/drb
-nkf 0.2.0 https://github.com/ruby/nkf
-syslog 0.1.2 https://github.com/ruby/syslog
-csv 3.3.0 https://github.com/ruby/csv
+minitest 6.0.1 https://github.com/minitest/minitest
+power_assert 3.0.1 https://github.com/ruby/power_assert
+rake 13.3.1 https://github.com/ruby/rake
+test-unit 3.7.7 https://github.com/test-unit/test-unit
+rexml 3.4.4 https://github.com/ruby/rexml
+rss 0.3.2 https://github.com/ruby/rss
+net-ftp 0.3.9 https://github.com/ruby/net-ftp
+net-imap 0.6.2 https://github.com/ruby/net-imap d9ae35ef913a45f83387b8444cdce4fb1cbf01af
+net-pop 0.1.2 https://github.com/ruby/net-pop
+net-smtp 0.5.1 https://github.com/ruby/net-smtp
+matrix 0.4.3 https://github.com/ruby/matrix
+prime 0.1.4 https://github.com/ruby/prime
+rbs 3.10.2 https://github.com/ruby/rbs
+typeprof 0.31.1 https://github.com/ruby/typeprof
+debug 1.11.1 https://github.com/ruby/debug
+racc 1.8.1 https://github.com/ruby/racc
+mutex_m 0.3.0 https://github.com/ruby/mutex_m
+getoptlong 0.2.1 https://github.com/ruby/getoptlong
+base64 0.3.0 https://github.com/ruby/base64
+bigdecimal 4.0.1 https://github.com/ruby/bigdecimal
+observer 0.1.2 https://github.com/ruby/observer
+abbrev 0.1.2 https://github.com/ruby/abbrev
+resolv-replace 0.2.0 https://github.com/ruby/resolv-replace
+rinda 0.2.0 https://github.com/ruby/rinda
+drb 2.2.3 https://github.com/ruby/drb
+nkf 0.2.0 https://github.com/ruby/nkf
+syslog 0.3.0 https://github.com/ruby/syslog
+csv 3.3.5 https://github.com/ruby/csv
+repl_type_completor 0.1.12 https://github.com/ruby/repl_type_completor
+ostruct 0.6.3 https://github.com/ruby/ostruct
+pstore 0.2.0 https://github.com/ruby/pstore
+benchmark 0.5.0 https://github.com/ruby/benchmark
+logger 1.7.0 https://github.com/ruby/logger
+rdoc 7.1.0 https://github.com/ruby/rdoc
+win32ole 1.9.2 https://github.com/ruby/win32ole
+irb 1.16.0 https://github.com/ruby/irb
+reline 0.6.3 https://github.com/ruby/reline
+readline 0.0.4 https://github.com/ruby/readline
+fiddle 1.1.8 https://github.com/ruby/fiddle
+tsort 0.2.0 https://github.com/ruby/tsort
diff --git a/gems/lib/rake/extensiontask.rb b/gems/lib/rake/extensiontask.rb
index fdbe8d8874..0ab0cb7b50 100644
--- a/gems/lib/rake/extensiontask.rb
+++ b/gems/lib/rake/extensiontask.rb
@@ -8,5 +8,7 @@ module Rake
puts "#{args.name} => #{args.prereqs.join(' ')}"
end
end
+
+ def lib_dir; end
end
end
diff --git a/goruby.c b/goruby.c
index 5d45277207..3ca96bfda0 100644
--- a/goruby.c
+++ b/goruby.c
@@ -1,4 +1,4 @@
-static void Init_golf(void);
+static void Init_golf_prelude(void);
static void *goruby_options(int argc, char **argv);
static int goruby_run_node(void *arg);
#define ruby_options goruby_options
@@ -17,14 +17,13 @@ static int goruby_run_node(void *arg);
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"
+#include "golf_prelude.rbbin"
static VALUE
init_golf(VALUE arg)
{
- Init_golf();
+ Init_golf_prelude();
rb_provide("golf.so");
return arg;
}
@@ -61,7 +60,8 @@ int
goruby_run_node(void *arg)
{
int state;
- if (NIL_P(rb_protect(init_golf, Qtrue, &state))) {
+ if (ruby_executable_node(arg, NULL) &&
+ NIL_P(rb_protect(init_golf, Qtrue, &state))) {
return state == EXIT_SUCCESS ? EXIT_FAILURE : state;
}
return ruby_run_node(arg);
diff --git a/hash.c b/hash.c
index f34f64065b..c1cc13383b 100644
--- a/hash.c
+++ b/hash.c
@@ -48,6 +48,7 @@
#include "ruby/thread_native.h"
#include "ruby/ractor.h"
#include "vm_sync.h"
+#include "builtin.h"
/* Flags of RHash
*
@@ -63,17 +64,13 @@
* The bounds of the AR table.
* 13-19: RHASH_LEV_MASK
* The iterational level of the hash. Used to prevent modifications
- * to the hash during interation.
+ * to the hash during iteration.
*/
#ifndef HASH_DEBUG
#define HASH_DEBUG 0
#endif
-#if HASH_DEBUG
-#include "internal/gc.h"
-#endif
-
#define SET_DEFAULT(hash, ifnone) ( \
FL_UNSET_RAW(hash, RHASH_PROC_DEFAULT), \
RHASH_SET_IFNONE(hash, ifnone))
@@ -102,6 +99,7 @@ static VALUE rb_hash_s_try_convert(VALUE, VALUE);
* 2. Insert WBs
*/
+/* :nodoc: */
VALUE
rb_hash_freeze(VALUE hash)
{
@@ -109,6 +107,7 @@ rb_hash_freeze(VALUE hash)
}
VALUE rb_cHash;
+VALUE rb_cHash_empty_frozen;
static VALUE envtbl;
static ID id_hash, id_flatten_bang;
@@ -181,7 +180,7 @@ any_hash(VALUE a, st_index_t (*other_func)(VALUE))
hnum = rb_hash_start(hnum);
}
else {
- hnum = RSYMBOL(a)->hashval;
+ hnum = RSHIFT(RSYMBOL(a)->hashval, 1);
}
break;
case T_FIXNUM:
@@ -322,40 +321,35 @@ objid_hash(VALUE obj)
#endif
}
-/**
+/*
* call-seq:
- * obj.hash -> integer
- *
- * Generates an Integer hash value for this object. This function must have the
- * property that <code>a.eql?(b)</code> implies <code>a.hash == b.hash</code>.
+ * hash -> integer
*
- * The hash value is used along with #eql? by the Hash class to determine if
- * two objects reference the same hash key. Any hash value that exceeds the
- * capacity of an Integer will be truncated before being used.
+ * Returns the integer hash value for +self+;
+ * has the property that if <tt>foo.eql?(bar)</tt>
+ * then <tt>foo.hash == bar.hash</tt>.
*
- * The hash value for an object may not be identical across invocations or
- * implementations of Ruby. If you need a stable identifier across Ruby
- * invocations and implementations you will need to generate one with a custom
- * method.
+ * \Class Hash uses both #hash and #eql? to determine whether two objects
+ * used as hash keys are to be treated as the same key.
+ * A hash value that exceeds the capacity of an Integer is truncated before being used.
*
- * Certain core classes such as Integer use built-in hash calculations and
- * do not call the #hash method when used as a hash key.
+ * Many core classes override method Object#hash;
+ * other core classes (e.g., Integer) calculate the hash internally,
+ * and do not call the #hash method when used as a hash key.
*
- * When implementing your own #hash based on multiple values, the best
- * practice is to combine the class and any values using the hash code of an
- * array:
- *
- * For example:
+ * When implementing #hash for a user-defined class,
+ * best practice is to use Array#hash with the class name and the values
+ * that are important in the instance;
+ * this takes advantage of that method's logic for safely and efficiently
+ * generating a hash value:
*
* def hash
* [self.class, a, b, c].hash
* end
*
- * The reason for this is that the Array#hash method already has logic for
- * safely and efficiently combining multiple hash values.
- *--
- * \private
- *++
+ * The hash value may differ among invocations or implementations of Ruby.
+ * If you need stable hash-like identifiers across Ruby invocations and implementations,
+ * use a custom method to generate them.
*/
VALUE
rb_obj_hash(VALUE obj)
@@ -498,37 +492,6 @@ RHASH_AR_TABLE_BOUND(VALUE h)
#if HASH_DEBUG
#define hash_verify(hash) hash_verify_(hash, __FILE__, __LINE__)
-void
-rb_hash_dump(VALUE hash)
-{
- rb_obj_info_dump(hash);
-
- if (RHASH_AR_TABLE_P(hash)) {
- unsigned i, bound = RHASH_AR_TABLE_BOUND(hash);
-
- fprintf(stderr, " size:%u bound:%u\n",
- RHASH_AR_TABLE_SIZE(hash), bound);
-
- for (i=0; i<bound; i++) {
- st_data_t k, v;
-
- if (!ar_cleared_entry(hash, i)) {
- char b1[0x100], b2[0x100];
- ar_table_pair *pair = RHASH_AR_TABLE_REF(hash, i);
- k = pair->key;
- v = pair->val;
- fprintf(stderr, " %d key:%s val:%s hint:%02x\n", i,
- rb_raw_obj_info(b1, 0x100, k),
- rb_raw_obj_info(b2, 0x100, v),
- ar_hint(hash, i));
- }
- else {
- fprintf(stderr, " %d empty\n", i);
- }
- }
- }
-}
-
static VALUE
hash_verify_(VALUE hash, const char *file, int line)
{
@@ -877,10 +840,11 @@ ar_general_foreach(VALUE hash, st_foreach_check_callback_func *func, st_update_c
return 0;
case ST_REPLACE:
if (replace) {
- retval = (*replace)(&key, &val, arg, TRUE);
+ (*replace)(&key, &val, arg, TRUE);
+
+ // Pair should not have moved
+ HASH_ASSERT(pair == RHASH_AR_TABLE_REF(hash, i));
- // TODO: pair should be same as pair before.
- pair = RHASH_AR_TABLE_REF(hash, i);
pair->key = (VALUE)key;
pair->val = (VALUE)val;
}
@@ -948,7 +912,7 @@ ar_foreach_check(VALUE hash, st_foreach_check_callback_func *func, st_data_t arg
if (pair->key == never) break;
ret = ar_find_entry_hint(hash, hint, key);
if (ret == RHASH_AR_TABLE_MAX_BOUND) {
- retval = (*func)(0, 0, arg, 1);
+ (*func)(0, 0, arg, 1);
return 2;
}
}
@@ -1297,7 +1261,6 @@ hash_ar_foreach_iter(st_data_t key, st_data_t value, st_data_t argp, int error)
if (error) return ST_STOP;
int status = (*arg->func)((VALUE)key, (VALUE)value, arg->arg);
- /* TODO: rehash check? rb_raise(rb_eRuntimeError, "rehash occurred during iteration"); */
return hash_iter_status_check(status);
}
@@ -1309,13 +1272,8 @@ hash_foreach_iter(st_data_t key, st_data_t value, st_data_t argp, int error)
if (error) return ST_STOP;
- st_table *tbl = RHASH_ST_TABLE(arg->hash);
int status = (*arg->func)((VALUE)key, (VALUE)value, arg->arg);
- if (RHASH_ST_TABLE(arg->hash) != tbl) {
- rb_raise(rb_eRuntimeError, "rehash occurred during iteration");
- }
-
return hash_iter_status_check(status);
}
@@ -1395,19 +1353,13 @@ hash_iter_lev_dec(VALUE hash)
}
static VALUE
-hash_foreach_ensure_rollback(VALUE hash)
-{
- hash_iter_lev_inc(hash);
- return 0;
-}
-
-static VALUE
hash_foreach_ensure(VALUE hash)
{
hash_iter_lev_dec(hash);
return 0;
}
+/* This does not manage iteration level */
int
rb_hash_stlike_foreach(VALUE hash, st_foreach_callback_func *func, st_data_t arg)
{
@@ -1419,6 +1371,7 @@ rb_hash_stlike_foreach(VALUE hash, st_foreach_callback_func *func, st_data_t arg
}
}
+/* This does not manage iteration level */
int
rb_hash_stlike_foreach_with_replace(VALUE hash, st_foreach_check_callback_func *func, st_update_callback_func *replace, st_data_t arg)
{
@@ -1544,6 +1497,10 @@ rb_hash_new_capa(long capa)
static VALUE
hash_copy(VALUE ret, VALUE hash)
{
+ if (rb_hash_compare_by_id_p(hash)) {
+ rb_gc_register_pinning_obj(ret);
+ }
+
if (RHASH_AR_TABLE_P(hash)) {
if (RHASH_AR_TABLE_P(ret)) {
ar_copy(ret, hash);
@@ -1599,10 +1556,10 @@ VALUE
rb_hash_dup(VALUE hash)
{
const VALUE flags = RBASIC(hash)->flags;
- VALUE ret = hash_dup(hash, rb_obj_class(hash),
- flags & (FL_EXIVAR|RHASH_PROC_DEFAULT));
- if (flags & FL_EXIVAR)
- rb_copy_generic_ivar(ret, hash);
+ VALUE ret = hash_dup(hash, rb_obj_class(hash), flags & RHASH_PROC_DEFAULT);
+
+ rb_copy_generic_ivar(ret, hash);
+
return ret;
}
@@ -1725,14 +1682,14 @@ tbl_update(VALUE hash, VALUE key, tbl_update_func func, st_data_t optional_arg)
.func = func,
.hash = hash,
.key = key,
- .value = (VALUE)optional_arg,
+ .value = 0
};
int ret = rb_hash_stlike_update(hash, key, tbl_update_modify, (st_data_t)&arg);
/* write barrier */
RB_OBJ_WRITTEN(hash, Qundef, arg.key);
- RB_OBJ_WRITTEN(hash, Qundef, arg.value);
+ if (arg.value) RB_OBJ_WRITTEN(hash, Qundef, arg.value);
return ret;
}
@@ -1762,58 +1719,31 @@ set_proc_default(VALUE hash, VALUE proc)
RHASH_SET_IFNONE(hash, proc);
}
-/*
- * call-seq:
- * 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}[rdoc-ref:Hash@Default+Values].
- *
- * If neither an argument nor a block given,
- * initializes both the default value and the default proc to <tt>nil</tt>:
- * h = Hash.new
- * h.default # => nil
- * h.default_proc # => nil
- *
- * If argument <tt>default_value</tt> given but no block given,
- * initializes the default value to the given <tt>default_value</tt>
- * and the default proc to <tt>nil</tt>:
- * 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 <tt>nil</tt>:
- * 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
-rb_hash_initialize(int argc, VALUE *argv, VALUE hash)
+rb_hash_init(rb_execution_context_t *ec, VALUE hash, VALUE capa_value, VALUE ifnone_unset, VALUE ifnone, VALUE block)
{
rb_hash_modify(hash);
- if (rb_block_given_p()) {
- rb_check_arity(argc, 0, 0);
- SET_PROC_DEFAULT(hash, rb_block_proc());
+ if (capa_value != INT2FIX(0)) {
+ long capa = NUM2LONG(capa_value);
+ if (capa > 0 && RHASH_SIZE(hash) == 0 && RHASH_AR_TABLE_P(hash)) {
+ hash_st_table_init(hash, &objhash, capa);
+ }
}
- else {
- rb_check_arity(argc, 0, 1);
- VALUE options, ifnone;
- rb_scan_args(argc, argv, "01:", &ifnone, &options);
- if (NIL_P(ifnone) && !NIL_P(options)) {
- ifnone = options;
- rb_warn_deprecated_to_remove("3.4", "Calling Hash.new with keyword arguments", "Hash.new({ key: value })");
+ if (!NIL_P(block)) {
+ if (ifnone_unset != Qtrue) {
+ rb_check_arity(1, 0, 0);
+ }
+ else {
+ SET_PROC_DEFAULT(hash, block);
}
- RHASH_SET_IFNONE(hash, ifnone);
+ }
+ else {
+ RHASH_SET_IFNONE(hash, ifnone_unset == Qtrue ? Qnil : ifnone);
}
+ hash_verify(hash);
return hash;
}
@@ -1822,36 +1752,38 @@ static VALUE rb_hash_to_a(VALUE hash);
/*
* call-seq:
* Hash[] -> new_empty_hash
- * Hash[hash] -> new_hash
+ * Hash[other_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.
+ * Returns a new \Hash object populated with the given objects, if any.
* See Hash::new.
*
- * With no argument, returns a new empty +Hash+.
+ * With no argument given, returns a new empty hash.
*
- * 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.
+ * With a single argument +other_hash+ given that is a hash,
+ * returns a new hash initialized with the entries from that hash
+ * (but not with its +default+ or +default_proc+):
*
* h = {foo: 0, bar: 1, baz: 2}
- * Hash[h] # => {:foo=>0, :bar=>1, :baz=>2}
+ * Hash[h] # => {foo: 0, bar: 1, baz: 2}
*
- * When the single given argument is an Array of 2-element Arrays,
- * returns a new +Hash+ object wherein each 2-element array forms a
+ * With a single argument +2_element_arrays+ given that is an array of 2-element arrays,
+ * returns a new hash wherein each given 2-element array forms a
* key-value entry:
*
- * Hash[ [ [:foo, 0], [:bar, 1] ] ] # => {:foo=>0, :bar=>1}
+ * 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:
+ * With an even number of arguments +objects+ given,
+ * returns a new hash wherein each successive pair of arguments
+ * is a key-value entry:
*
- * Hash[:foo, 0, :bar, 1] # => {:foo=>0, :bar=>1}
+ * Hash[:foo, 0, :bar, 1] # => {foo: 0, bar: 1}
*
- * Raises an exception if the argument list does not conform to any
+ * Raises ArgumentError if the argument list does not conform to any
* of the above.
+ *
+ * See also {Methods for Creating a Hash}[rdoc-ref:Hash@Methods+for+Creating+a+Hash].
*/
static VALUE
@@ -1931,16 +1863,15 @@ rb_check_hash_type(VALUE hash)
/*
* call-seq:
- * Hash.try_convert(obj) -> obj, new_hash, or nil
- *
- * If +obj+ is a +Hash+ object, returns +obj+.
+ * Hash.try_convert(object) -> object, new_hash, or nil
*
- * Otherwise if +obj+ responds to <tt>:to_hash</tt>,
- * calls <tt>obj.to_hash</tt> and returns the result.
+ * If +object+ is a hash, returns +object+.
*
- * Returns +nil+ if +obj+ does not respond to <tt>:to_hash</tt>
+ * Otherwise if +object+ responds to +:to_hash+,
+ * calls <tt>object.to_hash</tt>;
+ * returns the result if it is a hash, or raises TypeError if not.
*
- * Raises an exception unless <tt>obj.to_hash</tt> returns a +Hash+ object.
+ * Otherwise if +object+ does not respond to +:to_hash+, returns +nil+.
*/
static VALUE
rb_hash_s_try_convert(VALUE dummy, VALUE hash)
@@ -2016,10 +1947,11 @@ rb_hash_rehash_i(VALUE key, VALUE value, VALUE arg)
/*
* call-seq:
- * hash.rehash -> self
+ * rehash -> self
*
- * Rebuilds the hash table by recomputing the hash index for each key;
+ * Rebuilds the hash table for +self+ by recomputing the hash index for each key;
* returns <tt>self</tt>.
+ * Calling this method ensures that the hash table is valid.
*
* The hash table becomes invalid if the hash value of a key
* has changed after the entry was created.
@@ -2067,7 +1999,7 @@ call_default_proc(VALUE proc, VALUE hash, VALUE key)
return rb_proc_call_with_block(proc, 2, args, Qnil);
}
-static bool
+bool
rb_hash_default_unredefined(VALUE hash)
{
VALUE klass = RBASIC_CLASS(hash);
@@ -2120,16 +2052,19 @@ rb_hash_stlike_lookup(VALUE hash, st_data_t key, st_data_t *pval)
/*
* call-seq:
- * hash[key] -> value
+ * self[key] -> object
*
- * Returns the value associated with the given +key+, if found:
- * h = {foo: 0, bar: 1, baz: 2}
- * h[:foo] # => 0
+ * Searches for a hash key equivalent to the given +key+;
+ * see {Hash Key Equivalence}[rdoc-ref:Hash@Hash+Key+Equivalence].
*
- * If +key+ is not found, returns a default value
- * (see {Default Values}[rdoc-ref:Hash@Default+Values]):
- * h = {foo: 0, bar: 1, baz: 2}
- * h[:nosuch] # => nil
+ * If the key is found, returns its value:
+ *
+ * {foo: 0, bar: 1, baz: 2}
+ * h[:bar] # => 1
+ *
+ * Otherwise, returns a default value (see {Hash Default}[rdoc-ref:Hash@Hash+Default]).
+ *
+ * Related: #[]=; see also {Methods for Fetching}[rdoc-ref:Hash@Methods+for+Fetching].
*/
VALUE
@@ -2166,25 +2101,28 @@ rb_hash_lookup(VALUE hash, VALUE key)
/*
* call-seq:
- * hash.fetch(key) -> object
- * hash.fetch(key, default_value) -> object
- * hash.fetch(key) {|key| ... } -> object
+ * fetch(key) -> object
+ * fetch(key, default_value) -> object
+ * fetch(key) {|key| ... } -> object
+ *
+ * With no block given, returns the value for the given +key+, if found;
*
- * Returns the value for the given +key+, if found.
* h = {foo: 0, bar: 1, baz: 2}
- * h.fetch(:bar) # => 1
+ * h.fetch(:bar) # => 1
*
- * If +key+ is not found and no block was given,
- * returns +default_value+:
- * {}.fetch(:nosuch, :default) # => :default
+ * If the key is not found, returns +default_value+, if given,
+ * or raises KeyError otherwise:
*
- * 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"
+ * h.fetch(:nosuch, :default) # => :default
+ * h.fetch(:nosuch) # Raises KeyError.
*
- * Raises KeyError if neither +default_value+ nor a block was given.
+ * With a block given, calls the block with +key+ and returns the block's return value:
+ *
+ * {}.fetch(:nosuch) {|key| "No key #{key}"} # => "No key nosuch"
*
* Note that this method does not use the values of either #default or #default_proc.
+ *
+ * Related: see {Methods for Fetching}[rdoc-ref:Hash@Methods+for+Fetching].
*/
static VALUE
@@ -2231,12 +2169,12 @@ rb_hash_fetch(VALUE hash, VALUE key)
/*
* call-seq:
- * hash.default -> object
- * hash.default(key) -> object
+ * default -> object
+ * 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}[rdoc-ref:Hash@Default+Values].
+ * See {Hash Default}[rdoc-ref:Hash@Hash+Default].
*
* With no argument, returns the current default value:
* h = {}
@@ -2265,7 +2203,7 @@ rb_hash_default(int argc, VALUE *argv, VALUE hash)
/*
* call-seq:
- * hash.default = value -> object
+ * default = value -> object
*
* Sets the default value to +value+; returns +value+:
* h = {}
@@ -2273,10 +2211,10 @@ rb_hash_default(int argc, VALUE *argv, VALUE hash)
* h.default = false # => false
* h.default # => false
*
- * See {Default Values}[rdoc-ref:Hash@Default+Values].
+ * See {Hash Default}[rdoc-ref:Hash@Hash+Default].
*/
-static VALUE
+VALUE
rb_hash_set_default(VALUE hash, VALUE ifnone)
{
rb_hash_modify_check(hash);
@@ -2286,10 +2224,10 @@ rb_hash_set_default(VALUE hash, VALUE ifnone)
/*
* call-seq:
- * hash.default_proc -> proc or nil
+ * default_proc -> proc or nil
*
* Returns the default proc for +self+
- * (see {Default Values}[rdoc-ref:Hash@Default+Values]):
+ * (see {Hash Default}[rdoc-ref:Hash@Hash+Default]):
* h = {}
* h.default_proc # => nil
* h.default_proc = proc {|hash, key| "Default value for #{key}" }
@@ -2307,10 +2245,10 @@ rb_hash_default_proc(VALUE hash)
/*
* call-seq:
- * hash.default_proc = proc -> proc
+ * default_proc = proc -> proc
*
* Sets the default proc for +self+ to +proc+
- * (see {Default Values}[rdoc-ref:Hash@Default+Values]):
+ * (see {Hash Default}[rdoc-ref:Hash@Hash+Default]):
* h = {}
* h.default_proc # => nil
* h.default_proc = proc { |hash, key| "Default value for #{key}" }
@@ -2354,15 +2292,18 @@ key_i(VALUE key, VALUE value, VALUE arg)
/*
* call-seq:
- * hash.key(value) -> key or nil
+ * key(value) -> key or nil
*
* Returns the key for the first-found entry with the given +value+
* (see {Entry Order}[rdoc-ref:Hash@Entry+Order]):
+ *
* h = {foo: 0, bar: 2, baz: 2}
* h.key(0) # => :foo
* h.key(2) # => :bar
*
* Returns +nil+ if no such value is found.
+ *
+ * Related: see {Methods for Fetching}[rdoc-ref:Hash@Methods+for+Fetching].
*/
static VALUE
@@ -2427,29 +2368,36 @@ rb_hash_delete(VALUE hash, VALUE key)
/*
* call-seq:
- * hash.delete(key) -> value or nil
- * hash.delete(key) {|key| ... } -> object
+ * delete(key) -> value or nil
+ * delete(key) {|key| ... } -> object
*
- * Deletes the entry for the given +key+ and returns its associated value.
+ * If an entry for the given +key+ is found,
+ * deletes the entry and returns its associated value;
+ * otherwise returns +nil+ or calls the given block.
+ *
+ * With no block given and +key+ found, deletes the entry and returns its value:
*
- * 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 # => {foo: 0, baz: 2}
+ *
+ * With no block given and +key+ not found, returns +nil+.
*
- * If no block given and +key+ is not found, returns +nil+.
+ * With a block given and +key+ found, ignores the block,
+ * deletes the entry, and returns its value:
*
- * 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}
+ * h # => {foo: 0, bar: 1}
*
- * If a block is given and +key+ is not found,
+ * With a block given and +key+ 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}
+ * h # => {foo: 0, bar: 1, baz: 2}
+ *
+ * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
*/
static VALUE
@@ -2491,16 +2439,18 @@ shift_i_safe(VALUE key, VALUE value, VALUE arg)
/*
* call-seq:
- * hash.shift -> [key, value] or nil
+ * shift -> [key, value] or nil
+ *
+ * Removes and returns the first entry of +self+ as a 2-element array;
+ * see {Entry Order}[rdoc-ref:Hash@Entry+Order]:
*
- * Removes the first hash entry
- * (see {Entry Order}[rdoc-ref:Hash@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 # => {bar: 1, baz: 2}
*
- * Returns nil if the hash is empty.
+ * Returns +nil+ if +self+ is empty.
+ *
+ * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
*/
static VALUE
@@ -2560,19 +2510,19 @@ hash_enum_size(VALUE hash, VALUE args, VALUE eobj)
/*
* call-seq:
- * hash.delete_if {|key, value| ... } -> self
- * hash.delete_if -> new_enumerator
+ * delete_if {|key, value| ... } -> self
+ * 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}
+ * With a block given, calls the block with each key-value pair,
+ * deletes each entry for which the block returns a truthy value,
+ * and returns +self+:
*
- * If no block given, returns a new Enumerator:
* h = {foo: 0, bar: 1, baz: 2}
- * e = h.delete_if # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:delete_if>
- * e.each { |key, value| value > 0 } # => {:foo=>0}
+ * h.delete_if {|key, value| value > 0 } # => {foo: 0}
+ *
+ * With no block given, returns a new Enumerator.
+ *
+ * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
*/
VALUE
@@ -2589,20 +2539,21 @@ rb_hash_delete_if(VALUE hash)
/*
* call-seq:
- * hash.reject! {|key, value| ... } -> self or nil
- * hash.reject! -> new_enumerator
+ * reject! {|key, value| ... } -> self or nil
+ * 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}
+ * With a block given, calls the block with each entry's key and value;
+ * removes the entry from +self+ if the block returns a truthy value.
*
- * Returns +nil+ if no entries are removed.
+ * Return +self+ if any entries were removed, +nil+ otherwise:
*
- * Returns a new Enumerator if no block given:
* h = {foo: 0, bar: 1, baz: 2}
- * e = h.reject! # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:reject!>
- * e.each {|key, value| key.start_with?('b') } # => {:foo=>0}
+ * h.reject! {|key, value| value < 2 } # => {baz: 2}
+ * h.reject! {|key, value| value < 2 } # => nil
+ *
+ * With no block given, returns a new Enumerator.
+ *
+ * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
*/
static VALUE
@@ -2621,20 +2572,21 @@ rb_hash_reject_bang(VALUE hash)
/*
* call-seq:
- * hash.reject {|key, value| ... } -> new_hash
- * hash.reject -> new_enumerator
+ * reject {|key, value| ... } -> new_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}
+ * With a block given, returns a copy of +self+ with zero or more entries removed;
+ * calls the block with each key-value pair;
+ * excludes the entry in the copy if the block returns a truthy value,
+ * includes it otherwise:
*
- * Returns a new Enumerator if no block given:
* h = {foo: 0, bar: 1, baz: 2}
- * e = h.reject # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:reject>
- * h1 = e.each {|key, value| key.start_with?('b') }
- * h1 # => {:foo=>0}
+ * h.reject {|key, value| key.start_with?('b') }
+ * # => {foo: 0}
+ *
+ * With no block given, returns a new Enumerator.
+ *
+ * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
*/
static VALUE
@@ -2653,13 +2605,15 @@ rb_hash_reject(VALUE hash)
/*
* call-seq:
- * hash.slice(*keys) -> new_hash
+ * slice(*keys) -> new_hash
+ *
+ * Returns a new hash containing the entries from +self+ for the given +keys+;
+ * ignores any keys that are not found:
*
- * 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.slice(:baz, :foo, :nosuch) # => {baz: 2, foo: 0}
*
- * Any given +keys+ that are not found are ignored.
+ * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
*/
static VALUE
@@ -2685,13 +2639,16 @@ rb_hash_slice(int argc, VALUE *argv, VALUE hash)
/*
* call-seq:
- * hsh.except(*keys) -> a_hash
+ * except(*keys) -> new_hash
+ *
+ * Returns a copy of +self+ that excludes entries for the given +keys+;
+ * any +keys+ that are not found are ignored:
*
- * 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 = {foo:0, bar: 1, baz: 2} # => {:foo=>0, :bar=>1, :baz=>2}
+ * h.except(:baz, :foo) # => {:bar=>1}
+ * h.except(:bar, :nosuch) # => {:foo=>0, :baz=>2}
*
- * Any given +keys+ that are not found are ignored.
+ * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
*/
static VALUE
@@ -2713,15 +2670,19 @@ rb_hash_except(int argc, VALUE *argv, VALUE hash)
/*
* call-seq:
- * hash.values_at(*keys) -> new_array
+ * values_at(*keys) -> new_array
+ *
+ * Returns a new array containing values for the given +keys+:
*
- * 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}[rdoc-ref:Hash@Default+Values] are returned
- * for any keys that are not found:
+ * The {hash default}[rdoc-ref:Hash@Hash+Default] is returned
+ * for each key that is not found:
+ *
* h.values_at(:hello, :foo) # => [nil, 0]
+ *
+ * Related: see {Methods for Fetching}[rdoc-ref:Hash@Methods+for+Fetching].
*/
static VALUE
@@ -2738,22 +2699,26 @@ rb_hash_values_at(int argc, VALUE *argv, VALUE hash)
/*
* call-seq:
- * hash.fetch_values(*keys) -> new_array
- * hash.fetch_values(*keys) {|key| ... } -> new_array
+ * fetch_values(*keys) -> new_array
+ * fetch_values(*keys) {|key| ... } -> new_array
+ *
+ * When all given +keys+ are found,
+ * returns a new array containing the values associated with the given +keys+:
*
- * 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 a new empty Array if no arguments given.
+ * When any given +keys+ are not found and a block is given,
+ * calls the block with each unfound key and uses the block's return value
+ * as the value for that key:
*
- * 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(:bar, :foo, :bad, :bam) {|key| key.to_s}
+ * # => [1, 0, "bad", "bam"]
*
- * When no block is given, raises an exception if any given key is not found.
+ * When any given +keys+ are not found and no block is given,
+ * raises KeyError.
+ *
+ * Related: see {Methods for Fetching}[rdoc-ref:Hash@Methods+for+Fetching].
*/
static VALUE
@@ -2780,17 +2745,18 @@ keep_if_i(VALUE key, VALUE value, VALUE hash)
/*
* call-seq:
- * hash.select {|key, value| ... } -> new_hash
- * hash.select -> new_enumerator
+ * select {|key, value| ... } -> new_hash
+ * select -> new_enumerator
*
- * 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}
+ * With a block given, calls the block with each entry's key and value;
+ * returns a new hash whose entries are those for which the block returns a truthy value:
*
- * Returns a new Enumerator if no block given:
* h = {foo: 0, bar: 1, baz: 2}
- * e = h.select # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:select>
- * e.each {|key, value| value < 2 } # => {:foo=>0, :bar=>1}
+ * h.select {|key, value| value < 2 } # => {foo: 0, bar: 1}
+ *
+ * With no block given, returns a new Enumerator.
+ *
+ * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
*/
static VALUE
@@ -2809,19 +2775,22 @@ rb_hash_select(VALUE hash)
/*
* call-seq:
- * hash.select! {|key, value| ... } -> self or nil
- * hash.select! -> new_enumerator
+ * select! {|key, value| ... } -> self or nil
+ * select! -> new_enumerator
*
- * 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}
+ * With a block given, calls the block with each entry's key and value;
+ * removes from +self+ each entry for which the block returns +false+ or +nil+.
*
- * Returns +nil+ if no entries were removed.
+ * Returns +self+ if any entries were removed, +nil+ otherwise:
*
- * Returns a new Enumerator if no block given:
* h = {foo: 0, bar: 1, baz: 2}
- * e = h.select! # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:select!>
- * e.each { |key, value| value < 2 } # => {:foo=>0, :bar=>1}
+ * h.select! {|key, value| value < 2 } # => {foo: 0, bar: 1}
+ * h.select! {|key, value| value < 2 } # => nil
+ *
+ *
+ * With no block given, returns a new Enumerator.
+ *
+ * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
*/
static VALUE
@@ -2840,19 +2809,19 @@ rb_hash_select_bang(VALUE hash)
/*
* call-seq:
- * hash.keep_if {|key, value| ... } -> self
- * hash.keep_if -> new_enumerator
+ * keep_if {|key, value| ... } -> self
+ * keep_if -> new_enumerator
*
- * Calls the block for each key-value pair;
+ * With a block given, 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}
+ * otherwise deletes the entry; returns +self+:
*
- * Returns a new Enumerator if no block given:
* h = {foo: 0, bar: 1, baz: 2}
- * e = h.keep_if # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:keep_if>
- * e.each { |key, value| key.start_with?('b') } # => {:bar=>1, :baz=>2}
+ * h.keep_if { |key, value| key.start_with?('b') } # => {bar: 1, baz: 2}
+ *
+ * With no block given, returns a new Enumerator.
+ *
+ * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
*/
static VALUE
@@ -2874,9 +2843,11 @@ clear_i(VALUE key, VALUE value, VALUE dummy)
/*
* call-seq:
- * hash.clear -> self
+ * clear -> self
*
- * Removes all hash entries; returns +self+.
+ * Removes all entries from +self+; returns emptied +self+.
+ *
+ * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
*/
VALUE
@@ -2908,7 +2879,7 @@ hash_aset(st_data_t *key, st_data_t *val, struct update_arg *arg, int existing)
VALUE
rb_hash_key_str(VALUE key)
{
- if (!RB_FL_ANY_RAW(key, FL_EXIVAR) && RBASIC_CLASS(key) == rb_cString) {
+ if (!rb_obj_gen_fields_p(key) && RBASIC_CLASS(key) == rb_cString) {
return rb_fstring(key);
}
else {
@@ -2930,26 +2901,31 @@ NOINSERT_UPDATE_CALLBACK(hash_aset_str)
/*
* call-seq:
- * hash[key] = value -> value
- * hash.store(key, value)
+ * self[key] = object -> object
+ *
+ * Associates the given +object+ with the given +key+; returns +object+.
*
- * Associates the given +value+ with the given +key+; returns +value+.
+ * Searches for a hash key equivalent to the given +key+;
+ * see {Hash Key Equivalence}[rdoc-ref:Hash@Hash+Key+Equivalence].
*
- * If the given +key+ exists, replaces its value with the given +value+;
+ * If the key is found, replaces its value with the given +object+;
* the ordering is not affected
* (see {Entry Order}[rdoc-ref:Hash@Entry+Order]):
+ *
* h = {foo: 0, bar: 1}
* h[:foo] = 2 # => 2
- * h.store(:bar, 3) # => 3
- * h # => {:foo=>2, :bar=>3}
+ * h[:foo] # => 2
*
- * If +key+ does not exist, adds the +key+ and +value+;
+ * If +key+ is not found, creates a new entry for the given +key+ and +object+;
* the new entry is last in the order
* (see {Entry Order}[rdoc-ref:Hash@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}
+ * h[:baz] # => 2
+ * h # => {:foo=>0, :bar=>1, :baz=>2}
+ *
+ * Related: #[]; see also {Methods for Assigning}[rdoc-ref:Hash@Methods+for+Assigning].
*/
VALUE
@@ -2970,12 +2946,23 @@ rb_hash_aset(VALUE hash, VALUE key, VALUE val)
/*
* call-seq:
- * hash.replace(other_hash) -> self
+ * 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}
+ * h.replace({bat: 3, bam: 4}) # => {bat: 3, bam: 4}
+ *
+ * Also replaces the default value or proc of +self+ with the default value
+ * or proc of +other_hash+.
+ *
+ * h = {}
+ * other = Hash.new(:ok)
+ * h.replace(other)
+ * h.default # => :ok
+ *
+ * Related: see {Methods for Assigning}[rdoc-ref:Hash@Methods+for+Assigning].
*/
static VALUE
@@ -3004,13 +2991,13 @@ rb_hash_replace(VALUE hash, VALUE hash2)
/*
* call-seq:
- * hash.length -> integer
- * hash.size -> integer
+ * size -> integer
*
* Returns the count of entries in +self+:
*
- * {foo: 0, bar: 1, baz: 2}.length # => 3
+ * {foo: 0, bar: 1, baz: 2}.size # => 3
*
+ * Related: see {Methods for Querying}[rdoc-ref:Hash@Methods+for+Querying].
*/
VALUE
@@ -3027,11 +3014,14 @@ rb_hash_size_num(VALUE hash)
/*
* call-seq:
- * hash.empty? -> true or false
+ * empty? -> true or false
*
* Returns +true+ if there are no hash entries, +false+ otherwise:
+ *
* {}.empty? # => true
- * {foo: 0, bar: 1, baz: 2}.empty? # => false
+ * {foo: 0}.empty? # => false
+ *
+ * Related: see {Methods for Querying}[rdoc-ref:Hash@Methods+for+Querying].
*/
VALUE
@@ -3049,26 +3039,22 @@ each_value_i(VALUE key, VALUE value, VALUE _)
/*
* call-seq:
- * hash.each_value {|value| ... } -> self
- * hash.each_value -> new_enumerator
+ * each_value {|value| ... } -> self
+ * 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
+ * With a block given, calls the block with each value; returns +self+:
*
- * Returns a new Enumerator if no block given:
* h = {foo: 0, bar: 1, baz: 2}
- * e = h.each_value # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:each_value>
- * h1 = e.each {|value| puts value }
- * h1 # => {:foo=>0, :bar=>1, :baz=>2}
+ * h.each_value {|value| puts value } # => {foo: 0, bar: 1, baz: 2}
+ *
* Output:
* 0
* 1
* 2
+ *
+ * With no block given, returns a new Enumerator.
+ *
+ * Related: see {Methods for Iterating}[rdoc-ref:Hash@Methods+for+Iterating].
*/
static VALUE
@@ -3088,26 +3074,22 @@ each_key_i(VALUE key, VALUE value, VALUE _)
/*
* call-seq:
- * hash.each_key {|key| ... } -> self
- * hash.each_key -> new_enumerator
+ * each_key {|key| ... } -> self
+ * 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
+ * With a block given, calls the block with each key; returns +self+:
*
- * Returns a new Enumerator if no block given:
* h = {foo: 0, bar: 1, baz: 2}
- * e = h.each_key # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:each_key>
- * h1 = e.each {|key| puts key }
- * h1 # => {:foo=>0, :bar=>1, :baz=>2}
+ * h.each_key {|key| puts key } # => {foo: 0, bar: 1, baz: 2}
+ *
* Output:
* foo
* bar
* baz
+ *
+ * With no block given, returns a new Enumerator.
+ *
+ * Related: see {Methods for Iterating}[rdoc-ref:Hash@Methods+for+Iterating].
*/
static VALUE
rb_hash_each_key(VALUE hash)
@@ -3136,28 +3118,23 @@ each_pair_i_fast(VALUE key, VALUE value, VALUE _)
/*
* call-seq:
- * hash.each {|key, value| ... } -> self
- * hash.each_pair {|key, value| ... } -> self
- * hash.each -> new_enumerator
- * hash.each_pair -> new_enumerator
+ * each_pair {|key, value| ... } -> self
+ * each_pair -> new_enumerator
*
- * 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
+ * With a block given, calls the block with each key-value pair; returns +self+:
*
- * Returns a new Enumerator if no block given:
* h = {foo: 0, bar: 1, baz: 2}
- * e = h.each_pair # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:each_pair>
- * h1 = e.each {|key, value| puts "#{key}: #{value}"}
- * h1 # => {: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
+ *
+ * With no block given, returns a new Enumerator.
+ *
+ * Related: see {Methods for Iterating}[rdoc-ref:Hash@Methods+for+Iterating].
*/
static VALUE
@@ -3203,40 +3180,91 @@ transform_keys_i(VALUE key, VALUE value, VALUE result)
/*
* call-seq:
- * 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
+ * transform_keys {|old_key| ... } -> new_hash
+ * transform_keys(other_hash) -> new_hash
+ * transform_keys(other_hash) {|old_key| ...} -> new_hash
+ * transform_keys -> new_enumerator
+ *
+ * With an argument, a block, or both given,
+ * derives a new hash +new_hash+ from +self+, the argument, and/or the block;
+ * all, some, or none of its keys may be different from those in +self+.
*
- * Returns a new +Hash+ object; each entry has:
- * * A key provided by the block.
- * * The value from +self+.
+ * With a block given and no argument,
+ * +new_hash+ has keys determined only by the block.
*
- * 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.
+ * For each key/value pair <tt>old_key/value</tt> in +self+, calls the block with +old_key+;
+ * the block's return value becomes +new_key+;
+ * sets <tt>new_hash[new_key] = value</tt>;
+ * a duplicate key overwrites:
*
- * 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 {|old_key| old_key.to_s }
+ * # => {"foo" => 0, "bar" => 1, "baz" => 2}
+ * h.transform_keys {|old_key| 'xxx' }
+ * # => {"xxx" => 2}
*
- * h.transform_keys(foo: :bar, bar: :foo)
- * #=> {bar: 0, foo: 1, baz: 2}
+ * With argument +other_hash+ given and no block,
+ * +new_hash+ may have new keys provided by +other_hash+
+ * and unchanged keys provided by +self+.
*
- * h.transform_keys(foo: :hello, &:to_s)
- * #=> {:hello=>0, "bar"=>1, "baz"=>2}
+ * For each key/value pair <tt>old_key/old_value</tt> in +self+,
+ * looks for key +old_key+ in +other_hash+:
*
- * Overwrites values for duplicate keys:
- * h = {foo: 0, bar: 1, baz: 2}
- * h1 = h.transform_keys {|key| :bat }
- * h1 # => {:bat=>2}
+ * - If +old_key+ is found, its value <tt>other_hash[old_key]</tt> is taken as +new_key+;
+ * sets <tt>new_hash[new_key] = value</tt>;
+ * a duplicate key overwrites:
+ *
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.transform_keys(baz: :BAZ, bar: :BAR, foo: :FOO)
+ * # => {FOO: 0, BAR: 1, BAZ: 2}
+ * h.transform_keys(baz: :FOO, bar: :FOO, foo: :FOO)
+ * # => {FOO: 2}
+ *
+ * - If +old_key+ is not found,
+ * sets <tt>new_hash[old_key] = value</tt>;
+ * a duplicate key overwrites:
+ *
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.transform_keys({})
+ * # => {foo: 0, bar: 1, baz: 2}
+ * h.transform_keys(baz: :foo)
+ * # => {foo: 2, bar: 1}
+ *
+ * Unused keys in +other_hash+ are ignored:
*
- * Returns a new Enumerator if no block given:
* h = {foo: 0, bar: 1, baz: 2}
- * e = h.transform_keys # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:transform_keys>
- * h1 = e.each { |key| key.to_s }
- * h1 # => {"foo"=>0, "bar"=>1, "baz"=>2}
+ * h.transform_keys(bat: 3)
+ * # => {foo: 0, bar: 1, baz: 2}
+ *
+ * With both argument +other_hash+ and a block given,
+ * +new_hash+ has new keys specified by +other_hash+ or by the block,
+ * and unchanged keys provided by +self+.
+ *
+ * For each pair +old_key+ and +value+ in +self+:
+ *
+ * - If +other_hash+ has key +old_key+ (with value +new_key+),
+ * does not call the block for that key;
+ * sets <tt>new_hash[new_key] = value</tt>;
+ * a duplicate key overwrites:
+ *
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.transform_keys(baz: :BAZ, bar: :BAR, foo: :FOO) {|key| fail 'Not called' }
+ * # => {FOO: 0, BAR: 1, BAZ: 2}
+ *
+ * - If +other_hash+ does not have key +old_key+,
+ * calls the block with +old_key+ and takes its return value as +new_key+;
+ * sets <tt>new_hash[new_key] = value</tt>;
+ * a duplicate key overwrites:
+ *
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.transform_keys(baz: :BAZ) {|key| key.to_s.reverse }
+ * # => {"oof" => 0, "rab" => 1, BAZ: 2}
+ * h.transform_keys(baz: :BAZ) {|key| 'ook' }
+ * # => {"ook" => 1, BAZ: 2}
+ *
+ * With no argument and no block given, returns a new Enumerator.
+ *
+ * Related: see {Methods for Transforming Keys and Values}[rdoc-ref:Hash@Methods+for+Transforming+Keys+and+Values].
*/
static VALUE
rb_hash_transform_keys(int argc, VALUE *argv, VALUE hash)
@@ -3270,13 +3298,97 @@ static int flatten_i(VALUE key, VALUE val, VALUE ary);
/*
* call-seq:
- * hash.transform_keys! {|key| ... } -> self
- * hash.transform_keys!(hash2) -> self
- * hash.transform_keys!(hash2) {|other_key| ...} -> self
- * hash.transform_keys! -> new_enumerator
+ * transform_keys! {|old_key| ... } -> self
+ * transform_keys!(other_hash) -> self
+ * transform_keys!(other_hash) {|old_key| ...} -> self
+ * transform_keys! -> new_enumerator
+ *
+ * With an argument, a block, or both given,
+ * derives keys from the argument, the block, and +self+;
+ * all, some, or none of the keys in +self+ may be changed.
+ *
+ * With a block given and no argument,
+ * derives keys only from the block;
+ * all, some, or none of the keys in +self+ may be changed.
+ *
+ * For each key/value pair <tt>old_key/value</tt> in +self+, calls the block with +old_key+;
+ * the block's return value becomes +new_key+;
+ * removes the entry for +old_key+: <tt>self.delete(old_key)</tt>;
+ * sets <tt>self[new_key] = value</tt>;
+ * a duplicate key overwrites:
+ *
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.transform_keys! {|old_key| old_key.to_s }
+ * # => {"foo" => 0, "bar" => 1, "baz" => 2}
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.transform_keys! {|old_key| 'xxx' }
+ * # => {"xxx" => 2}
+ *
+ * With argument +other_hash+ given and no block,
+ * derives keys for +self+ from +other_hash+ and +self+;
+ * all, some, or none of the keys in +self+ may be changed.
+ *
+ * For each key/value pair <tt>old_key/old_value</tt> in +self+,
+ * looks for key +old_key+ in +other_hash+:
+ *
+ * - If +old_key+ is found, takes value <tt>other_hash[old_key]</tt> as +new_key+;
+ * removes the entry for +old_key+: <tt>self.delete(old_key)</tt>;
+ * sets <tt>self[new_key] = value</tt>;
+ * a duplicate key overwrites:
+ *
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.transform_keys!(baz: :BAZ, bar: :BAR, foo: :FOO)
+ * # => {FOO: 0, BAR: 1, BAZ: 2}
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.transform_keys!(baz: :FOO, bar: :FOO, foo: :FOO)
+ * # => {FOO: 2}
+ *
+ * - If +old_key+ is not found, does nothing:
+ *
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.transform_keys!({})
+ * # => {foo: 0, bar: 1, baz: 2}
+ * h.transform_keys!(baz: :foo)
+ * # => {foo: 2, bar: 1}
+ *
+ * Unused keys in +other_hash+ are ignored:
+ *
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.transform_keys!(bat: 3)
+ * # => {foo: 0, bar: 1, baz: 2}
+ *
+ * With both argument +other_hash+ and a block given,
+ * derives keys from +other_hash+, the block, and +self+;
+ * all, some, or none of the keys in +self+ may be changed.
+ *
+ * For each pair +old_key+ and +value+ in +self+:
+ *
+ * - If +other_hash+ has key +old_key+ (with value +new_key+),
+ * does not call the block for that key;
+ * removes the entry for +old_key+: <tt>self.delete(old_key)</tt>;
+ * sets <tt>self[new_key] = value</tt>;
+ * a duplicate key overwrites:
+ *
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.transform_keys!(baz: :BAZ, bar: :BAR, foo: :FOO) {|key| fail 'Not called' }
+ * # => {FOO: 0, BAR: 1, BAZ: 2}
+ *
+ * - If +other_hash+ does not have key +old_key+,
+ * calls the block with +old_key+ and takes its return value as +new_key+;
+ * removes the entry for +old_key+: <tt>self.delete(old_key)</tt>;
+ * sets <tt>self[new_key] = value</tt>;
+ * a duplicate key overwrites:
+ *
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.transform_keys!(baz: :BAZ) {|key| key.to_s.reverse }
+ * # => {"oof" => 0, "rab" => 1, BAZ: 2}
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.transform_keys!(baz: :BAZ) {|key| 'ook' }
+ * # => {"ook" => 1, BAZ: 2}
+ *
+ * With no argument and no block given, returns a new Enumerator.
*
- * Same as Hash#transform_keys but modifies the receiver in place
- * instead of returning a new hash.
+ * Related: see {Methods for Transforming Keys and Values}[rdoc-ref:Hash@Methods+for+Transforming+Keys+and+Values].
*/
static VALUE
rb_hash_transform_keys_bang(int argc, VALUE *argv, VALUE hash)
@@ -3343,25 +3455,37 @@ transform_values_foreach_replace(st_data_t *key, st_data_t *value, st_data_t arg
return ST_CONTINUE;
}
+static VALUE
+transform_values_call(VALUE hash)
+{
+ rb_hash_stlike_foreach_with_replace(hash, transform_values_foreach_func, transform_values_foreach_replace, hash);
+ return hash;
+}
+
+static void
+transform_values(VALUE hash)
+{
+ hash_iter_lev_inc(hash);
+ rb_ensure(transform_values_call, hash, hash_foreach_ensure, hash);
+}
+
/*
* call-seq:
- * hash.transform_values {|value| ... } -> new_hash
- * hash.transform_values -> new_enumerator
+ * transform_values {|value| ... } -> new_hash
+ * transform_values -> new_enumerator
*
- * Returns a new +Hash+ object; each entry has:
- * * A key from +self+.
- * * A value provided by the block.
+ * With a block given, returns a new hash +new_hash+;
+ * for each pair +key+/+value+ in +self+,
+ * calls the block with +value+ and captures its return as +new_value+;
+ * adds to +new_hash+ the entry +key+/+new_value+:
*
- * Transform values:
* h = {foo: 0, bar: 1, baz: 2}
* h1 = h.transform_values {|value| value * 100}
- * h1 # => {:foo=>0, :bar=>100, :baz=>200}
+ * 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 # => #<Enumerator: {:foo=>0, :bar=>1, :baz=>2}:transform_values>
- * h1 = e.each { |value| value * 100}
- * h1 # => {:foo=>0, :bar=>100, :baz=>200}
+ * With no block given, returns a new Enumerator.
+ *
+ * Related: see {Methods for Transforming Keys and Values}[rdoc-ref:Hash@Methods+for+Transforming+Keys+and+Values].
*/
static VALUE
rb_hash_transform_values(VALUE hash)
@@ -3373,7 +3497,7 @@ rb_hash_transform_values(VALUE 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);
+ transform_values(result);
compact_after_delete(result);
}
@@ -3382,18 +3506,24 @@ rb_hash_transform_values(VALUE hash)
/*
* call-seq:
- * hash.transform_values! {|value| ... } -> self
- * hash.transform_values! -> new_enumerator
+ * transform_values! {|old_value| ... } -> self
+ * 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:
+ * With a block given, changes the values of +self+ as determined by the block;
+ * returns +self+.
+ *
+ * For each entry +key+/+old_value+ in +self+,
+ * calls the block with +old_value+,
+ * captures its return value as +new_value+,
+ * and sets <tt>self[key] = new_value</tt>:
+ *
* h = {foo: 0, bar: 1, baz: 2}
- * e = h.transform_values! # => #<Enumerator: {:foo=>0, :bar=>100, :baz=>200}:transform_values!>
- * h1 = e.each {|value| value * 100}
- * h1 # => {:foo=>0, :bar=>100, :baz=>200}
+ * h.transform_values! {|value| value * 100} # => {foo: 0, bar: 100, baz: 200}
+ *
+ * With no block given, returns a new Enumerator.
+ *
+ * Related: see {Methods for Transforming Keys and Values}[rdoc-ref:Hash@Methods+for+Transforming+Keys+and+Values].
*/
static VALUE
rb_hash_transform_values_bang(VALUE hash)
@@ -3402,7 +3532,7 @@ rb_hash_transform_values_bang(VALUE hash)
rb_hash_modify_check(hash);
if (!RHASH_TABLE_EMPTY_P(hash)) {
- rb_hash_stlike_foreach_with_replace(hash, transform_values_foreach_func, transform_values_foreach_replace, hash);
+ transform_values(hash);
}
return hash;
@@ -3417,12 +3547,15 @@ to_a_i(VALUE key, VALUE value, VALUE ary)
/*
* call-seq:
- * hash.to_a -> new_array
+ * to_a -> new_array
+ *
+ * Returns all elements of +self+ as an array of 2-element arrays;
+ * each nested array contains a key-value pair from +self+:
*
- * 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]]
+ *
+ * Related: see {Methods for Converting}[rdoc-ref:Hash@Methods+for+Converting].
*/
static VALUE
@@ -3436,20 +3569,65 @@ rb_hash_to_a(VALUE hash)
return ary;
}
+static bool
+symbol_key_needs_quote(VALUE str)
+{
+ long len = RSTRING_LEN(str);
+ if (len == 0 || !rb_str_symname_p(str)) return true;
+ const char *s = RSTRING_PTR(str);
+ char first = s[0];
+ if (first == '@' || first == '$' || first == '!') return true;
+ if (!at_char_boundary(s, s + len - 1, RSTRING_END(str), rb_enc_get(str))) return false;
+ switch (s[len - 1]) {
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '`':
+ case '%':
+ case '^':
+ case '&':
+ case '|':
+ case ']':
+ case '<':
+ case '=':
+ case '>':
+ case '~':
+ case '@':
+ return true;
+ default:
+ return false;
+ }
+}
+
static int
inspect_i(VALUE key, VALUE value, VALUE str)
{
VALUE str2;
- str2 = rb_inspect(key);
+ bool is_symbol = SYMBOL_P(key);
+ bool quote = false;
+ if (is_symbol) {
+ str2 = rb_sym2str(key);
+ quote = symbol_key_needs_quote(str2);
+ }
+ else {
+ str2 = rb_inspect(key);
+ }
if (RSTRING_LEN(str) > 1) {
rb_str_buf_cat_ascii(str, ", ");
}
else {
rb_enc_copy(str, str2);
}
- rb_str_buf_append(str, str2);
- rb_str_buf_cat_ascii(str, "=>");
+ if (quote) {
+ rb_str_buf_append(str, rb_str_inspect(str2));
+ }
+ else {
+ rb_str_buf_append(str, str2);
+ }
+
+ rb_str_buf_cat_ascii(str, is_symbol ? ": " : " => ");
str2 = rb_inspect(value);
rb_str_buf_append(str, str2);
@@ -3471,13 +3649,14 @@ inspect_hash(VALUE hash, VALUE dummy, int recur)
/*
* call-seq:
- * hash.inspect -> new_string
+ * inspect -> new_string
+ *
+ * Returns a new string containing the hash entries:
*
- * Returns a new String containing the hash entries:
-
* h = {foo: 0, bar: 1, baz: 2}
- * h.inspect # => "{:foo=>0, :bar=>1, :baz=>2}"
+ * h.inspect # => "{foo: 0, bar: 1, baz: 2}"
*
+ * Related: see {Methods for Converting}[rdoc-ref:Hash@Methods+for+Converting].
*/
static VALUE
@@ -3490,9 +3669,11 @@ rb_hash_inspect(VALUE hash)
/*
* call-seq:
- * hash.to_hash -> self
+ * to_hash -> self
*
* Returns +self+.
+ *
+ * Related: see {Methods for Converting}[rdoc-ref:Hash@Methods+for+Converting].
*/
static VALUE
rb_hash_to_hash(VALUE hash)
@@ -3535,21 +3716,22 @@ rb_hash_to_h_block(VALUE hash)
/*
* call-seq:
- * hash.to_h -> self or new_hash
- * hash.to_h {|key, value| ... } -> new_hash
+ * to_h {|key, value| ... } -> new_hash
+ * to_h -> self or new_hash
*
- * For an instance of +Hash+, returns +self+.
+ * With a block given, returns a new hash whose content is based on the block;
+ * the block is called with each entry's key and value;
+ * the block should return a 2-element array
+ * containing the key and value to be included in the returned array:
*
- * 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}
+ * h.to_h {|key, value| [value, key] }
+ * # => {0 => :foo, 1 => :bar, 2 => :baz}
+ *
+ * With no block given, returns +self+ if +self+ is an instance of +Hash+;
+ * if +self+ is a subclass of +Hash+, returns a new hash containing the content of +self+.
+ *
+ * Related: see {Methods for Converting}[rdoc-ref:Hash@Methods+for+Converting].
*/
static VALUE
@@ -3574,11 +3756,14 @@ keys_i(VALUE key, VALUE value, VALUE ary)
/*
* call-seq:
- * hash.keys -> new_array
+ * keys -> new_array
+ *
+ * Returns a new array containing all keys in +self+:
*
- * Returns a new Array containing all keys in +self+:
* h = {foo: 0, bar: 1, baz: 2}
* h.keys # => [:foo, :bar, :baz]
+ *
+ * Related: see {Methods for Fetching}[rdoc-ref:Hash@Methods+for+Fetching].
*/
VALUE
@@ -3618,11 +3803,14 @@ values_i(VALUE key, VALUE value, VALUE ary)
/*
* call-seq:
- * hash.values -> new_array
+ * values -> new_array
+ *
+ * Returns a new array containing all values in +self+:
*
- * Returns a new Array containing all values in +self+:
* h = {foo: 0, bar: 1, baz: 2}
* h.values # => [0, 1, 2]
+ *
+ * Related: see {Methods for Fetching}[rdoc-ref:Hash@Methods+for+Fetching].
*/
VALUE
@@ -3650,7 +3838,6 @@ rb_hash_values(VALUE hash)
}
rb_ary_set_len(values, size);
}
-
else {
rb_hash_foreach(hash, values_i, values);
}
@@ -3660,12 +3847,15 @@ rb_hash_values(VALUE hash)
/*
* call-seq:
- * 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
+ * include?(key) -> true or false
+ *
+ * Returns whether +key+ is a key in +self+:
+ *
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.include?(:bar) # => true
+ * h.include?(:BAR) # => false
*
- * Returns +true+ if +key+ is a key in +self+, otherwise +false+.
+ * Related: {Methods for Querying}[rdoc-ref:Hash@Methods+for+Querying].
*/
VALUE
@@ -3688,10 +3878,11 @@ rb_hash_search_value(VALUE key, VALUE value, VALUE arg)
/*
* call-seq:
- * hash.has_value?(value) -> true or false
- * hash.value?(value) -> true or false
+ * has_value?(value) -> true or false
*
- * Returns +true+ if +value+ is a value in +self+, otherwise +false+.
+ * Returns whether +value+ is a value in +self+.
+ *
+ * Related: {Methods for Querying}[rdoc-ref:Hash@Methods+for+Querying].
*/
static VALUE
@@ -3788,21 +3979,25 @@ hash_equal(VALUE hash1, VALUE hash2, int eql)
/*
* call-seq:
- * hash == object -> true or false
+ * self == other -> 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+, <tt>hash[key] == object[key]</tt>.
+ * Returns whether all of the following are true:
*
- * Otherwise, returns +false+.
+ * - +other+ is a +Hash+ object (or can be converted to one).
+ * - +self+ and +other+ have the same keys (regardless of order).
+ * - For each key +key+, <tt>self[key] == other[key]</tt>.
*
- * 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
+ * Examples:
+ *
+ * h = {foo: 0, bar: 1}
+ * h == {foo: 0, bar: 1} # => true # Equal entries (same order)
+ * h == {bar: 1, foo: 0} # => true # Equal entries (different order).
+ * h == 1 # => false # Object not a hash.
+ * h == {} # => false # Different number of entries.
+ * h == {foo: 0, bar: 1} # => false # Different key.
+ * h == {foo: 0, bar: 1} # => false # Different value.
+ *
+ * Related: see {Methods for Comparing}[rdoc-ref:Hash@Methods+for+Comparing].
*/
static VALUE
@@ -3813,12 +4008,13 @@ rb_hash_equal(VALUE hash1, VALUE hash2)
/*
* call-seq:
- * hash.eql?(object) -> true or false
+ * 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+, <tt>h[key].eql?(object[key])</tt>.
+ *
+ * - The given +object+ is a +Hash+ object.
+ * - +self+ and +object+ have the same keys (regardless of order).
+ * - For each key +key+, <tt>self[key].eql?(object[key])</tt>.
*
* Otherwise, returns +false+.
*
@@ -3827,6 +4023,8 @@ rb_hash_equal(VALUE hash1, VALUE hash2)
* h1.eql? h2 # => true
* h3 = {baz: 2, bar: 1, foo: 0}
* h1.eql? h3 # => true
+ *
+ * Related: see {Methods for Querying}[rdoc-ref:Hash@Methods+for+Querying].
*/
static VALUE
@@ -3849,16 +4047,19 @@ hash_i(VALUE key, VALUE val, VALUE arg)
/*
* call-seq:
- * hash.hash -> an_integer
+ * hash -> an_integer
*
- * Returns the Integer hash-code for the hash.
+ * Returns the integer hash-code for the hash.
*
- * Two +Hash+ objects have the same hash-code if their content is the same
+ * Two hashes have the same hash-code if their content is the same
* (regardless of order):
+ *
* h1 = {foo: 0, bar: 1, baz: 2}
* h2 = {baz: 2, bar: 1, foo: 0}
* h2.hash == h1.hash # => true
* h2.eql? h1 # => true
+ *
+ * Related: see {Methods for Querying}[rdoc-ref:Hash@Methods+for+Querying].
*/
static VALUE
@@ -3883,17 +4084,21 @@ rb_hash_invert_i(VALUE key, VALUE value, VALUE hash)
/*
* call-seq:
- * hash.invert -> new_hash
+ * invert -> new_hash
+ *
+ * Returns a new hash with each key-value pair inverted:
*
- * 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:
+ * Overwrites any repeated new keys
* (see {Entry Order}[rdoc-ref:Hash@Entry+Order]):
+ *
* h = {foo: 0, bar: 0, baz: 0}
* h.invert # => {0=>:baz}
+ *
+ * Related: see {Methods for Transforming Keys and Values}[rdoc-ref:Hash@Methods+for+Transforming+Keys+and+Values].
*/
static VALUE
@@ -3912,95 +4117,127 @@ rb_hash_update_i(VALUE key, VALUE value, VALUE hash)
return ST_CONTINUE;
}
+struct update_call_args {
+ VALUE hash, newvalue, *argv;
+ int argc;
+ bool block_given;
+ bool iterating;
+};
+
static int
rb_hash_update_block_callback(st_data_t *key, st_data_t *value, struct update_arg *arg, int existing)
{
- st_data_t newvalue = arg->arg;
+ VALUE k = (VALUE)*key, v = (VALUE)*value;
+ struct update_call_args *ua = (void *)arg->arg;
+ VALUE newvalue = ua->newvalue, hash = arg->hash;
if (existing) {
- newvalue = (st_data_t)rb_yield_values(3, (VALUE)*key, (VALUE)*value, (VALUE)newvalue);
+ hash_iter_lev_inc(hash);
+ ua->iterating = true;
+ newvalue = rb_yield_values(3, k, v, newvalue);
+ hash_iter_lev_dec(hash);
+ ua->iterating = false;
}
- else if (RHASH_STRING_KEY_P(arg->hash, *key) && !RB_OBJ_FROZEN(*key)) {
- *key = rb_hash_key_str(*key);
+ else if (RHASH_STRING_KEY_P(hash, k) && !RB_OBJ_FROZEN(k)) {
+ *key = (st_data_t)rb_hash_key_str(k);
}
- *value = newvalue;
+ *value = (st_data_t)newvalue;
return ST_CONTINUE;
}
NOINSERT_UPDATE_CALLBACK(rb_hash_update_block_callback)
static int
-rb_hash_update_block_i(VALUE key, VALUE value, VALUE hash)
+rb_hash_update_block_i(VALUE key, VALUE value, VALUE args)
{
- RHASH_UPDATE(hash, key, rb_hash_update_block_callback, value);
+ struct update_call_args *ua = (void *)args;
+ ua->newvalue = value;
+ RHASH_UPDATE(ua->hash, key, rb_hash_update_block_callback, args);
return ST_CONTINUE;
}
+static VALUE
+rb_hash_update_call(VALUE args)
+{
+ struct update_call_args *arg = (void *)args;
+
+ for (int i = 0; i < arg->argc; i++){
+ VALUE hash = to_hash(arg->argv[i]);
+ if (arg->block_given) {
+ rb_hash_foreach(hash, rb_hash_update_block_i, args);
+ }
+ else {
+ rb_hash_foreach(hash, rb_hash_update_i, arg->hash);
+ }
+ }
+ return arg->hash;
+}
+
+static VALUE
+rb_hash_update_ensure(VALUE args)
+{
+ struct update_call_args *ua = (void *)args;
+ if (ua->iterating) hash_iter_lev_dec(ua->hash);
+ return Qnil;
+}
+
/*
* call-seq:
- * hash.merge! -> self
- * hash.merge!(*other_hashes) -> self
- * hash.merge!(*other_hashes) { |key, old_value, new_value| ... } -> self
+ * update(*other_hashes) -> self
+ * update(*other_hashes) { |key, old_value, new_value| ... } -> self
*
- * Merges each of +other_hashes+ into +self+; returns +self+.
+ * Updates values and/or adds entries to +self+; returns +self+.
*
- * Each argument in +other_hashes+ must be a +Hash+.
+ * Each argument +other_hash+ in +other_hashes+ must be a hash.
*
- * 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.
+ * With no block given, for each successive entry +key+/+new_value+ in each successive +other_hash+:
*
- * 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}
+ * - If +key+ is in +self+, sets <tt>self[key] = new_value</tt>, whose position is unchanged:
*
- * 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.
+ * h0 = {foo: 0, bar: 1, baz: 2}
+ * h1 = {bar: 3, foo: -1}
+ * h0.update(h1) # => {foo: -1, bar: 3, baz: 2}
*
- * 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}
+ * - If +key+ is not in +self+, adds the entry at the end of +self+:
*
- * With no arguments:
- * * Returns +self+, unmodified.
- * * The block, if given, is ignored.
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.update({bam: 3, bah: 4}) # => {foo: 0, bar: 1, baz: 2, bam: 3, bah: 4}
*
- * 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}
+ * With a block given, for each successive entry +key+/+new_value+ in each successive +other_hash+:
+ *
+ * - If +key+ is in +self+, fetches +old_value+ from <tt>self[key]</tt>,
+ * calls the block with +key+, +old_value+, and +new_value+,
+ * and sets <tt>self[key] = new_value</tt>, whose position is unchanged :
+ *
+ * season = {AB: 75, H: 20, HR: 3, SO: 17, W: 11, HBP: 3}
+ * today = {AB: 3, H: 1, W: 1}
+ * yesterday = {AB: 4, H: 2, HR: 1}
+ * season.update(yesterday, today) {|key, old_value, new_value| old_value + new_value }
+ * # => {AB: 82, H: 23, HR: 4, SO: 17, W: 12, HBP: 3}
+ *
+ * - If +key+ is not in +self+, adds the entry at the end of +self+:
+ *
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h.update({bat: 3}) { fail 'Cannot happen' }
+ * # => {foo: 0, bar: 1, baz: 2, bat: 3}
+ *
+ * Related: see {Methods for Assigning}[rdoc-ref:Hash@Methods+for+Assigning].
*/
static VALUE
rb_hash_update(int argc, VALUE *argv, VALUE self)
{
- int i;
- bool block_given = rb_block_given_p();
+ struct update_call_args args = {
+ .hash = self,
+ .argv = argv,
+ .argc = argc,
+ .block_given = rb_block_given_p(),
+ .iterating = false,
+ };
+ VALUE arg = (VALUE)&args;
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);
- }
- }
- return self;
+ return rb_ensure(rb_hash_update_call, arg, rb_hash_update_ensure, arg);
}
struct update_func_arg {
@@ -4054,53 +4291,48 @@ rb_hash_update_by(VALUE hash1, VALUE hash2, rb_hash_update_func *func)
/*
* call-seq:
- * hash.merge -> copy_of_self
- * hash.merge(*other_hashes) -> new_hash
- * hash.merge(*other_hashes) { |key, old_value, new_value| ... } -> new_hash
+ * merge(*other_hashes) -> new_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 +other_hash+ in +other_hashes+ must be a hash.
*
- * Each argument in +other_hashes+ must be a +Hash+.
+ * With arguments +other_hashes+ given and no block,
+ * returns the new hash formed by merging each successive +other_hash+
+ * into a copy of +self+;
+ * returns that copy;
+ * for each successive entry in +other_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.
+ * - For a new key, the entry is added at the end of +self+.
+ * - For duplicate key, the entry overwrites the entry in +self+,
+ * whose position is unchanged.
*
* 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}
+ * 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.
+ * With arguments +other_hashes+ and a block given, behaves as above
+ * except that for a duplicate key
+ * the overwriting entry takes it value not from the entry in +other_hash+,
+ * but instead from the block:
+ *
+ * - The block is called with the duplicate key and the values
+ * from both +self+ and +other_hash+.
+ * - The block's return value becomes the new value for the entry in +self+.
*
* 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}
+ * h.merge(h1, h2) { |key, old_value, new_value| old_value + new_value }
+ * # => {foo: 0, bar: 5, baz: 2, bat: 9, bam: 5}
*
- * With no arguments:
- * * Returns a copy of +self+.
- * * The block, if given, is ignored.
+ * 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}
+ * Related: see {Methods for Assigning}[rdoc-ref:Hash@Methods+for+Assigning].
*/
static VALUE
@@ -4143,13 +4375,17 @@ assoc_i(VALUE key, VALUE val, VALUE arg)
/*
* call-seq:
- * hash.assoc(key) -> new_array or nil
+ * assoc(key) -> entry or nil
+ *
+ * If the given +key+ is found, returns its entry as a 2-element array
+ * containing that key and its value:
*
- * 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]
*
- * Returns +nil+ if key +key+ is not found.
+ * Returns +nil+ if the key is not found.
+ *
+ * Related: see {Methods for Fetching}[rdoc-ref:Hash@Methods+for+Fetching].
*/
static VALUE
@@ -4202,15 +4438,18 @@ rassoc_i(VALUE key, VALUE val, VALUE arg)
/*
* call-seq:
- * hash.rassoc(value) -> new_array or nil
+ * rassoc(value) -> new_array or nil
+ *
+ * Searches +self+ for the first entry whose value is <tt>==</tt> to the given +value+;
+ * see {Entry Order}[rdoc-ref:Hash@Entry+Order].
+ *
+ * If the entry is found, returns its key and value as a 2-element array;
+ * returns +nil+ if not found:
*
- * Returns a new 2-element Array consisting of the key and value
- * of the first-found entry whose value is <tt>==</tt> to value
- * (see {Entry Order}[rdoc-ref:Hash@Entry+Order]):
* h = {foo: 0, bar: 1, baz: 1}
* h.rassoc(1) # => [:bar, 1]
*
- * Returns +nil+ if no such value found.
+ * Related: see {Methods for Fetching}[rdoc-ref:Hash@Methods+for+Fetching].
*/
static VALUE
@@ -4238,33 +4477,38 @@ flatten_i(VALUE key, VALUE val, VALUE ary)
/*
* call-seq:
- * hash.flatten -> new_array
- * hash.flatten(level) -> new_array
+ * flatten(depth = 1) -> new_array
+ *
+ * With positive integer +depth+,
+ * returns a new array that is a recursive flattening of +self+ to the given +depth+.
*
- * Returns a new Array object that is a 1-dimensional flattening of +self+.
+ * At each level of recursion:
*
- * ---
+ * - Each element whose value is an array is "flattened" (that is, replaced by its individual array elements);
+ * see Array#flatten.
+ * - Each element whose value is not an array is unchanged.
+ * even if the value is an object that has instance method flatten (such as a hash).
*
- * By default, nested Arrays are not flattened:
- * h = {foo: 0, bar: [:bat, 3], baz: 2}
- * h.flatten # => [:foo, 0, :bar, [:bat, 3], :baz, 2]
+ * Examples; note that entry <tt>foo: {bar: 1, baz: 2}</tt> is never flattened.
*
- * 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]
+ * h = {foo: {bar: 1, baz: 2}, bat: [:bam, [:bap, [:bah]]]}
+ * h.flatten(1) # => [:foo, {:bar=>1, :baz=>2}, :bat, [:bam, [:bap, [:bah]]]]
+ * h.flatten(2) # => [:foo, {:bar=>1, :baz=>2}, :bat, :bam, [:bap, [:bah]]]
+ * h.flatten(3) # => [:foo, {:bar=>1, :baz=>2}, :bat, :bam, :bap, [:bah]]
+ * h.flatten(4) # => [:foo, {:bar=>1, :baz=>2}, :bat, :bam, :bap, :bah]
+ * h.flatten(5) # => [:foo, {:bar=>1, :baz=>2}, :bat, :bam, :bap, :bah]
*
- * 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]
+ * With negative integer +depth+,
+ * flattens all levels:
*
- * 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
+ * h.flatten(-1) # => [:foo, {:bar=>1, :baz=>2}, :bat, :bam, :bap, :bah]
+ *
+ * With +depth+ zero,
+ * returns the equivalent of #to_a:
+ *
+ * h.flatten(0) # => [[:foo, {:bar=>1, :baz=>2}], [:bat, [:bam, [:bap, [:bah]]]]]
+ *
+ * Related: see {Methods for Converting}[rdoc-ref:Hash@Methods+for+Converting].
*/
static VALUE
@@ -4311,12 +4555,14 @@ delete_if_nil(VALUE key, VALUE value, VALUE hash)
/*
* call-seq:
- * hash.compact -> new_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}
+ * h.compact # => {foo: 0, baz: 2}
+ *
+ * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
*/
static VALUE
@@ -4335,13 +4581,18 @@ rb_hash_compact(VALUE hash)
/*
* call-seq:
- * hash.compact! -> self or nil
+ * compact! -> self or nil
+ *
+ * If +self+ contains any +nil+-valued entries,
+ * returns +self+ with all +nil+-valued entries removed;
+ * returns +nil+ otherwise:
*
- * 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}
+ * h.compact!
+ * h # => {foo: 0, baz: 2}
+ * h.compact! # => nil
*
- * Returns +nil+ if no entries were removed.
+ * Related: see {Methods for Deleting}[rdoc-ref:Hash@Methods+for+Deleting].
*/
static VALUE
@@ -4360,30 +4611,28 @@ rb_hash_compact_bang(VALUE hash)
/*
* call-seq:
- * hash.compare_by_identity -> self
+ * 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+.
+ * Sets +self+ to compare keys using _identity_ (rather than mere _equality_);
+ * returns +self+:
+ *
+ * By default, two keys are considered to be the same key
+ * if and only if they are _equal_ objects (per method #eql?):
*
- * 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'] = 0
+ * h['x'] = 1 # Overwrites.
* 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}
+ * When this method has been called, two keys are considered to be the same key
+ * if and only if they are the _same_ object:
+ *
+ * h.compare_by_identity
+ * h['x'] = 2 # Does not overwrite.
+ * h # => {"x"=>1, "x"=>2}
+ *
+ * Related: #compare_by_identity?;
+ * see also {Methods for Comparing}[rdoc-ref:Hash@Methods+for+Comparing].
*/
VALUE
@@ -4423,14 +4672,24 @@ rb_hash_compare_by_id(VALUE hash)
RHASH_ST_CLEAR(tmp);
}
+ rb_gc_register_pinning_obj(hash);
+
return hash;
}
/*
* call-seq:
- * hash.compare_by_identity? -> true or false
+ * compare_by_identity? -> true or false
+ *
+ * Returns whether #compare_by_identity has been called:
*
- * Returns +true+ if #compare_by_identity has been called, +false+ otherwise.
+ * h = {}
+ * h.compare_by_identity? # => false
+ * h.compare_by_identity
+ * h.compare_by_identity? # => true
+ *
+ * Related: #compare_by_identity;
+ * see also {Methods for Comparing}[rdoc-ref:Hash@Methods+for+Comparing].
*/
VALUE
@@ -4444,6 +4703,7 @@ rb_ident_hash_new(void)
{
VALUE hash = rb_hash_new();
hash_st_table_init(hash, &identhash, 0);
+ rb_gc_register_pinning_obj(hash);
return hash;
}
@@ -4452,6 +4712,7 @@ rb_ident_hash_new_with_size(st_index_t size)
{
VALUE hash = rb_hash_new();
hash_st_table_init(hash, &identhash, size);
+ rb_gc_register_pinning_obj(hash);
return hash;
}
@@ -4496,36 +4757,42 @@ any_p_i_pattern(VALUE key, VALUE value, VALUE arg)
/*
* call-seq:
- * hash.any? -> true or false
- * hash.any?(object) -> true or false
- * hash.any? {|key, value| ... } -> true or false
+ * any? -> true or false
+ * any?(entry) -> true or false
+ * any? {|key, value| ... } -> true or false
*
* Returns +true+ if any element satisfies a given criterion;
* +false+ otherwise.
*
- * If +self+ has no element, returns +false+ and argument or block
- * are not used.
+ * If +self+ has no element, returns +false+ and argument or block are not used;
+ * otherwise behaves as below.
*
* With no argument and no block,
- * returns +true+ if +self+ is non-empty; +false+ if empty.
+ * returns +true+ if +self+ is non-empty, +false+ otherwise.
*
- * With argument +object+ and no block,
+ * With argument +entry+ and no block,
* returns +true+ if for any key +key+
- * <tt>h.assoc(key) == object</tt>:
+ * <tt>self.assoc(key) == entry</tt>, +false+ otherwise:
+ *
* h = {foo: 0, bar: 1, baz: 2}
+ * h.assoc(:bar) # => [:bar, 1]
* h.any?([:bar, 1]) # => true
* h.any?([:bar, 0]) # => false
- * h.any?([:baz, 1]) # => false
*
- * With no argument and a block,
+ * With no argument and a block given,
* calls the block with each key-value pair;
- * returns +true+ if the block returns any truthy value,
+ * returns +true+ if the block returns a 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
*
- * Related: Enumerable#any?
+ * With both argument +entry+ and a block given,
+ * issues a warning and ignores the block.
+ *
+ * Related: Enumerable#any? (which this method overrides);
+ * see also {Methods for Fetching}[rdoc-ref:Hash@Methods+for+Fetching].
*/
static VALUE
@@ -4559,31 +4826,37 @@ rb_hash_any_p(int argc, VALUE *argv, VALUE hash)
/*
* call-seq:
- * hash.dig(key, *identifiers) -> object
+ * dig(key, *identifiers) -> object
+ *
+ * Finds and returns an object found in nested objects,
+ * as specified by +key+ and +identifiers+.
*
- * 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:
+ * 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: 2}
* h.dig(:foo, :bar, :baz) # => 2
* h.dig(:foo, :bar, :BAZ) # => nil
*
- * Nested Hashes and Arrays:
+ * Nested hashes and arrays:
+ *
* h = {foo: {bar: [:a, :b, :c]}}
* h.dig(:foo, :bar, 2) # => :c
*
- * This method will use the {default values}[rdoc-ref:Hash@Default+Values]
- * for keys that are not present:
+ * If no such object is found,
+ * returns the {hash default}[rdoc-ref:Hash@Hash+Default]:
+ *
* 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
+ * h.dig(:hello, :world)
+ * # => {:foo=>{:bar=>[:a, :b, :c]}}
+ *
+ * Related: {Methods for Fetching}[rdoc-ref:Hash@Methods+for+Fetching].
*/
static VALUE
@@ -4618,14 +4891,21 @@ hash_le(VALUE hash1, VALUE hash2)
/*
* call-seq:
- * hash <= other_hash -> true or false
+ * self <= other -> 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
+ * Returns whether the entries of +self+ are a subset of the entries of +other+:
+ *
+ * h0 = {foo: 0, bar: 1}
+ * h1 = {foo: 0, bar: 1, baz: 2}
+ * h0 <= h0 # => true
+ * h0 <= h1 # => true
+ * h1 <= h0 # => false
+ *
+ * See {Hash Inclusion}[rdoc-ref:language/hash_inclusion.rdoc].
+ *
+ * Raises TypeError if +other_hash+ is not a hash and cannot be converted to a hash.
+ *
+ * Related: see {Methods for Comparing}[rdoc-ref:Hash@Methods+for+Comparing].
*/
static VALUE
rb_hash_le(VALUE hash, VALUE other)
@@ -4637,14 +4917,23 @@ rb_hash_le(VALUE hash, VALUE other)
/*
* call-seq:
- * hash < other_hash -> true or false
+ * self < other -> 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
+ * Returns whether the entries of +self+ are a proper subset of the entries of +other+:
+ *
+ * h = {foo: 0, bar: 1}
+ * h < {foo: 0, bar: 1, baz: 2} # => true # Proper subset.
+ * h < {baz: 2, bar: 1, foo: 0} # => true # Order may differ.
+ * h < h # => false # Not a proper subset.
+ * h < {bar: 1, foo: 0} # => false # Not a proper subset.
+ * h < {foo: 0, bar: 1, baz: 2} # => false # Different key.
+ * h < {foo: 0, bar: 1, baz: 2} # => false # Different value.
+ *
+ * See {Hash Inclusion}[rdoc-ref:language/hash_inclusion.rdoc].
+ *
+ * Raises TypeError if +other_hash+ is not a hash and cannot be converted to a hash.
+ *
+ * Related: see {Methods for Comparing}[rdoc-ref:Hash@Methods+for+Comparing].
*/
static VALUE
rb_hash_lt(VALUE hash, VALUE other)
@@ -4656,14 +4945,21 @@ rb_hash_lt(VALUE hash, VALUE other)
/*
* call-seq:
- * hash >= other_hash -> true or false
+ * self >= other -> 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
+ * Returns whether the entries of +self+ are a superset of the entries of +other+:
+ *
+ * h0 = {foo: 0, bar: 1, baz: 2}
+ * h1 = {foo: 0, bar: 1}
+ * h0 >= h1 # => true
+ * h0 >= h0 # => true
+ * h1 >= h0 # => false
+ *
+ * See {Hash Inclusion}[rdoc-ref:language/hash_inclusion.rdoc].
+ *
+ * Raises TypeError if +other_hash+ is not a hash and cannot be converted to a hash.
+ *
+ * Related: see {Methods for Comparing}[rdoc-ref:Hash@Methods+for+Comparing].
*/
static VALUE
rb_hash_ge(VALUE hash, VALUE other)
@@ -4675,14 +4971,23 @@ rb_hash_ge(VALUE hash, VALUE other)
/*
* call-seq:
- * hash > other_hash -> true or false
+ * self > other -> 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
+ * Returns whether the entries of +self+ are a proper superset of the entries of +other+:
+ *
+ * h = {foo: 0, bar: 1, baz: 2}
+ * h > {foo: 0, bar: 1} # => true # Proper superset.
+ * h > {bar: 1, foo: 0} # => true # Order may differ.
+ * h > h # => false # Not a proper superset.
+ * h > {baz: 2, bar: 1, foo: 0} # => false # Not a proper superset.
+ * h > {foo: 0, bar: 1} # => false # Different key.
+ * h > {foo: 0, bar: 1} # => false # Different value.
+ *
+ * See {Hash Inclusion}[rdoc-ref:language/hash_inclusion.rdoc].
+ *
+ * Raises TypeError if +other_hash+ is not a hash and cannot be converted to a hash.
+ *
+ * Related: see {Methods for Comparing}[rdoc-ref:Hash@Methods+for+Comparing].
*/
static VALUE
rb_hash_gt(VALUE hash, VALUE other)
@@ -4701,15 +5006,18 @@ hash_proc_call(RB_BLOCK_CALL_FUNC_ARGLIST(key, hash))
/*
* call-seq:
- * hash.to_proc -> proc
+ * 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
+ *
+ * Related: see {Methods for Converting}[rdoc-ref:Hash@Methods+for+Converting].
*/
static VALUE
rb_hash_to_proc(VALUE hash)
@@ -4727,10 +5035,8 @@ rb_hash_deconstruct_keys(VALUE hash, VALUE keys)
static int
add_new_i(st_data_t *key, st_data_t *val, st_data_t arg, int existing)
{
- VALUE *args = (VALUE *)arg;
if (existing) return ST_STOP;
- RB_OBJ_WRITTEN(args[0], Qundef, (VALUE)*key);
- RB_OBJ_WRITE(args[0], (VALUE *)val, args[1]);
+ *val = arg;
return ST_CONTINUE;
}
@@ -4742,22 +5048,25 @@ int
rb_hash_add_new_element(VALUE hash, VALUE key, VALUE val)
{
st_table *tbl;
- int ret = 0;
- VALUE args[2];
- args[0] = hash;
- args[1] = val;
+ int ret = -1;
if (RHASH_AR_TABLE_P(hash)) {
- ret = ar_update(hash, (st_data_t)key, add_new_i, (st_data_t)args);
- if (ret != -1) {
- return ret;
+ ret = ar_update(hash, (st_data_t)key, add_new_i, (st_data_t)val);
+ if (ret == -1) {
+ ar_force_convert_table(hash, __FILE__, __LINE__);
}
- ar_force_convert_table(hash, __FILE__, __LINE__);
}
- tbl = RHASH_TBL_RAW(hash);
- return st_update(tbl, (st_data_t)key, add_new_i, (st_data_t)args);
-
+ if (ret == -1) {
+ tbl = RHASH_TBL_RAW(hash);
+ ret = st_update(tbl, (st_data_t)key, add_new_i, (st_data_t)val);
+ }
+ if (!ret) {
+ // Newly inserted
+ RB_OBJ_WRITTEN(hash, Qundef, key);
+ RB_OBJ_WRITTEN(hash, Qundef, val);
+ }
+ return ret;
}
static st_data_t
@@ -4824,8 +5133,7 @@ extern char **environ;
#define ENVNMATCH(s1, s2, n) (memcmp((s1), (s2), (n)) == 0)
#endif
-#define ENV_LOCK() RB_VM_LOCK_ENTER()
-#define ENV_UNLOCK() RB_VM_LOCK_LEAVE()
+#define ENV_LOCKING() RB_VM_LOCKING()
static inline rb_encoding *
env_encoding(void)
@@ -4847,28 +5155,27 @@ env_enc_str_new(const char *ptr, long len, rb_encoding *enc)
}
static VALUE
-env_str_new(const char *ptr, long len)
+env_str_new(const char *ptr, long len, rb_encoding *enc)
{
- return env_enc_str_new(ptr, len, env_encoding());
+ return env_enc_str_new(ptr, len, enc);
}
static VALUE
-env_str_new2(const char *ptr)
+env_str_new2(const char *ptr, rb_encoding *enc)
{
if (!ptr) return Qnil;
- return env_str_new(ptr, strlen(ptr));
+ return env_str_new(ptr, strlen(ptr), enc);
}
static VALUE
getenv_with_lock(const char *name)
{
VALUE ret;
- ENV_LOCK();
- {
+ rb_encoding *enc = env_encoding();
+ ENV_LOCKING() {
const char *val = getenv(name);
- ret = env_str_new2(val);
+ ret = env_str_new2(val, enc);
}
- ENV_UNLOCK();
return ret;
}
@@ -4877,11 +5184,9 @@ has_env_with_lock(const char *name)
{
const char *val;
- ENV_LOCK();
- {
+ ENV_LOCKING() {
val = getenv(name);
}
- ENV_UNLOCK();
return val ? true : false;
}
@@ -4921,7 +5226,7 @@ env_name(volatile VALUE *s)
static VALUE env_aset(VALUE nm, VALUE val);
static void
-reset_by_modified_env(const char *nam)
+reset_by_modified_env(const char *nam, const char *val)
{
/*
* ENV['TZ'] = nil has a special meaning.
@@ -4930,7 +5235,7 @@ reset_by_modified_env(const char *nam)
* This hack might works only on Linux glibc.
*/
if (ENVMATCH(nam, TZ_ENV)) {
- ruby_reset_timezone();
+ ruby_reset_timezone(val);
}
}
@@ -4938,7 +5243,7 @@ static VALUE
env_delete(VALUE name)
{
const char *nam = env_name(name);
- reset_by_modified_env(nam);
+ reset_by_modified_env(nam, NULL);
VALUE val = getenv_with_lock(nam);
if (!NIL_P(val)) {
@@ -5084,44 +5389,6 @@ envix(const char *nam)
}
#endif
-#if defined(_WIN32)
-static size_t
-getenvsize(const WCHAR* p)
-{
- const WCHAR* porg = p;
- while (*p++) p += lstrlenW(p) + 1;
- return p - porg + 1;
-}
-
-static size_t
-getenvblocksize(void)
-{
-#ifdef _MAX_ENV
- return _MAX_ENV;
-#else
- return 32767;
-#endif
-}
-
-static int
-check_envsize(size_t n)
-{
- if (_WIN32_WINNT < 0x0600 && rb_w32_osver() < 6) {
- /* https://msdn.microsoft.com/en-us/library/windows/desktop/ms682653(v=vs.85).aspx */
- /* Windows Server 2003 and Windows XP: The maximum size of the
- * environment block for the process is 32,767 characters. */
- WCHAR* p = GetEnvironmentStringsW();
- if (!p) return -1; /* never happen */
- n += getenvsize(p);
- FreeEnvironmentStringsW(p);
- if (n >= getenvblocksize()) {
- return -1;
- }
- }
- return 0;
-}
-#endif
-
#if defined(_WIN32) || \
(defined(__sun) && !(defined(HAVE_SETENV) && defined(HAVE_UNSETENV)))
@@ -5147,9 +5414,6 @@ void
ruby_setenv(const char *name, const char *value)
{
#if defined(_WIN32)
-# if defined(MINGW_HAS_SECURE_API) || RUBY_MSVCRT_VERSION >= 80
-# define HAVE__WPUTENV_S 1
-# endif
VALUE buf;
WCHAR *wname;
WCHAR *wvalue = 0;
@@ -5160,43 +5424,30 @@ ruby_setenv(const char *name, const char *value)
if (value) {
int len2;
len2 = MultiByteToWideChar(CP_UTF8, 0, value, -1, NULL, 0);
- if (check_envsize((size_t)len + len2)) { /* len and len2 include '\0' */
- goto fail; /* 2 for '=' & '\0' */
- }
wname = ALLOCV_N(WCHAR, buf, len + len2);
wvalue = wname + len;
MultiByteToWideChar(CP_UTF8, 0, name, -1, wname, len);
MultiByteToWideChar(CP_UTF8, 0, value, -1, wvalue, len2);
-#ifndef HAVE__WPUTENV_S
- wname[len-1] = L'=';
-#endif
}
else {
wname = ALLOCV_N(WCHAR, buf, len + 1);
MultiByteToWideChar(CP_UTF8, 0, name, -1, wname, len);
wvalue = wname + len;
*wvalue = L'\0';
-#ifndef HAVE__WPUTENV_S
- wname[len-1] = L'=';
-#endif
}
- ENV_LOCK();
- {
-#ifndef HAVE__WPUTENV_S
- failed = _wputenv(wname);
-#else
+ ENV_LOCKING() {
+ /* Use _wputenv_s() instead of SetEnvironmentVariableW() to make sure
+ * special variables like "TZ" are interpret by libc. */
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. */
if (!value || !*value) {
/* putenv() doesn't handle empty value */
- if (!SetEnvironmentVariable(name, value) &&
+ if (!SetEnvironmentVariableW(wname, value ? wvalue : NULL) &&
GetLastError() != ERROR_ENVVAR_NOT_FOUND) goto fail;
}
if (failed) {
@@ -5206,28 +5457,22 @@ ruby_setenv(const char *name, const char *value)
#elif defined(HAVE_SETENV) && defined(HAVE_UNSETENV)
if (value) {
int ret;
- ENV_LOCK();
- {
+ ENV_LOCKING() {
ret = setenv(name, value, 1);
}
- ENV_UNLOCK();
if (ret) rb_sys_fail_sprintf("setenv(%s)", name);
}
else {
#ifdef VOID_UNSETENV
- ENV_LOCK();
- {
+ ENV_LOCKING() {
unsetenv(name);
}
- ENV_UNLOCK();
#else
int ret;
- ENV_LOCK();
- {
+ ENV_LOCKING() {
ret = unsetenv(name);
}
- ENV_UNLOCK();
if (ret) rb_sys_fail_sprintf("unsetenv(%s)", name);
#endif
@@ -5250,8 +5495,7 @@ ruby_setenv(const char *name, const char *value)
snprintf(mem_ptr, mem_size, "%s=%s", name, value);
}
- ENV_LOCK();
- {
+ ENV_LOCKING() {
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);
@@ -5260,15 +5504,12 @@ ruby_setenv(const char *name, const char *value)
}
}
}
- ENV_UNLOCK();
if (value) {
int ret;
- ENV_LOCK();
- {
+ ENV_LOCKING() {
ret = putenv(mem_ptr);
}
- ENV_UNLOCK();
if (ret) {
free(mem_ptr);
@@ -5279,8 +5520,7 @@ ruby_setenv(const char *name, const char *value)
size_t len;
int i;
- ENV_LOCK();
- {
+ ENV_LOCKING() {
i = envix(name); /* where does it go? */
if (environ == origenviron) { /* need we copy environment? */
@@ -5321,7 +5561,6 @@ ruby_setenv(const char *name, const char *value)
finish:;
}
- ENV_UNLOCK();
#endif /* WIN32 */
}
@@ -5396,7 +5635,7 @@ env_aset(VALUE nm, VALUE val)
get_env_ptr(value, val);
ruby_setenv(name, value);
- reset_by_modified_env(name);
+ reset_by_modified_env(name, value);
return val;
}
@@ -5406,8 +5645,7 @@ env_keys(int raw)
rb_encoding *enc = raw ? 0 : rb_locale_encoding();
VALUE ary = rb_ary_new();
- ENV_LOCK();
- {
+ ENV_LOCKING() {
char **env = GET_ENVIRON(environ);
while (*env) {
char *s = strchr(*env, '=');
@@ -5421,7 +5659,6 @@ env_keys(int raw)
}
FREE_ENVIRON(environ);
}
- ENV_UNLOCK();
return ary;
}
@@ -5451,8 +5688,7 @@ rb_env_size(VALUE ehash, VALUE args, VALUE eobj)
char **env;
long cnt = 0;
- ENV_LOCK();
- {
+ ENV_LOCKING() {
env = GET_ENVIRON(environ);
for (; *env ; ++env) {
if (strchr(*env, '=')) {
@@ -5461,7 +5697,6 @@ rb_env_size(VALUE ehash, VALUE args, VALUE eobj)
}
FREE_ENVIRON(environ);
}
- ENV_UNLOCK();
return LONG2FIX(cnt);
}
@@ -5502,20 +5737,19 @@ env_values(void)
{
VALUE ary = rb_ary_new();
- ENV_LOCK();
- {
+ rb_encoding *enc = env_encoding();
+ ENV_LOCKING() {
char **env = GET_ENVIRON(environ);
while (*env) {
char *s = strchr(*env, '=');
if (s) {
- rb_ary_push(ary, env_str_new2(s+1));
+ rb_ary_push(ary, env_str_new2(s+1, enc));
}
env++;
}
FREE_ENVIRON(environ);
}
- ENV_UNLOCK();
return ary;
}
@@ -5596,21 +5830,20 @@ env_each_pair(VALUE ehash)
VALUE ary = rb_ary_new();
- ENV_LOCK();
- {
+ rb_encoding *enc = env_encoding();
+ ENV_LOCKING() {
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));
+ rb_ary_push(ary, env_str_new(*env, s-*env, enc));
+ rb_ary_push(ary, env_str_new2(s+1, enc));
}
env++;
}
FREE_ENVIRON(environ);
}
- ENV_UNLOCK();
if (rb_block_pair_yield_optimizable()) {
for (i=0; i<RARRAY_LEN(ary); i+=2) {
@@ -5947,30 +6180,27 @@ env_to_s(VALUE _)
static VALUE
env_inspect(VALUE _)
{
- VALUE i;
VALUE str = rb_str_buf_new2("{");
+ rb_encoding *enc = env_encoding();
- ENV_LOCK();
- {
+ ENV_LOCKING() {
char **env = GET_ENVIRON(environ);
while (*env) {
- char *s = strchr(*env, '=');
+ const 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);
+ rb_str_buf_append(str, rb_str_inspect(env_enc_str_new(*env, s-*env, enc)));
+ rb_str_buf_cat2(str, " => ");
+ s++;
+ rb_str_buf_append(str, rb_str_inspect(env_enc_str_new(s, strlen(s), enc)));
}
env++;
}
FREE_ENVIRON(environ);
}
- ENV_UNLOCK();
rb_str_buf_cat2(str, "}");
@@ -5991,20 +6221,19 @@ env_to_a(VALUE _)
{
VALUE ary = rb_ary_new();
- ENV_LOCK();
- {
+ rb_encoding *enc = env_encoding();
+ ENV_LOCKING() {
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)));
+ rb_ary_push(ary, rb_assoc_new(env_str_new(*env, s-*env, enc),
+ env_str_new2(s+1, enc)));
}
env++;
}
FREE_ENVIRON(environ);
}
- ENV_UNLOCK();
return ary;
}
@@ -6028,13 +6257,11 @@ env_size_with_lock(void)
{
int i = 0;
- ENV_LOCK();
- {
+ ENV_LOCKING() {
char **env = GET_ENVIRON(environ);
while (env[i]) i++;
FREE_ENVIRON(environ);
}
- ENV_UNLOCK();
return i;
}
@@ -6070,15 +6297,13 @@ env_empty_p(VALUE _)
{
bool empty = true;
- ENV_LOCK();
- {
+ ENV_LOCKING() {
char **env = GET_ENVIRON(environ);
if (env[0] != 0) {
empty = false;
}
FREE_ENVIRON(environ);
}
- ENV_UNLOCK();
return RBOOL(empty);
}
@@ -6167,8 +6392,7 @@ env_has_value(VALUE dmy, VALUE obj)
VALUE ret = Qfalse;
- ENV_LOCK();
- {
+ ENV_LOCKING() {
char **env = GET_ENVIRON(environ);
while (*env) {
char *s = strchr(*env, '=');
@@ -6183,7 +6407,6 @@ env_has_value(VALUE dmy, VALUE obj)
}
FREE_ENVIRON(environ);
}
- ENV_UNLOCK();
return ret;
}
@@ -6210,8 +6433,7 @@ env_rassoc(VALUE dmy, VALUE obj)
VALUE result = Qnil;
- ENV_LOCK();
- {
+ ENV_LOCKING() {
char **env = GET_ENVIRON(environ);
while (*env) {
@@ -6228,7 +6450,6 @@ env_rassoc(VALUE dmy, VALUE obj)
}
FREE_ENVIRON(environ);
}
- ENV_UNLOCK();
return result;
}
@@ -6255,15 +6476,15 @@ env_key(VALUE dmy, VALUE value)
StringValue(value);
VALUE str = Qnil;
- ENV_LOCK();
- {
+ rb_encoding *enc = env_encoding();
+ ENV_LOCKING() {
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);
+ str = env_str_new(*env, s-*env-1, enc);
break;
}
}
@@ -6271,7 +6492,6 @@ env_key(VALUE dmy, VALUE value)
}
FREE_ENVIRON(environ);
}
- ENV_UNLOCK();
return str;
}
@@ -6281,20 +6501,19 @@ env_to_hash(void)
{
VALUE hash = rb_hash_new();
- ENV_LOCK();
- {
+ rb_encoding *enc = env_encoding();
+ ENV_LOCKING() {
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));
+ rb_hash_aset(hash, env_str_new(*env, s-*env, enc),
+ env_str_new2(s+1, enc));
}
env++;
}
FREE_ENVIRON(environ);
}
- ENV_UNLOCK();
return hash;
}
@@ -6338,7 +6557,7 @@ env_f_to_hash(VALUE _)
* 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}
+ * 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:
@@ -6434,21 +6653,20 @@ env_shift(VALUE _)
VALUE result = Qnil;
VALUE key = Qnil;
- ENV_LOCK();
- {
+ rb_encoding *enc = env_encoding();
+ ENV_LOCKING() {
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)));
+ key = env_str_new(p, s-p, enc);
+ VALUE val = env_str_new2(getenv(RSTRING_PTR(key)), enc);
result = rb_assoc_new(key, val);
}
}
FREE_ENVIRON(environ);
}
- ENV_UNLOCK();
if (!NIL_P(key)) {
env_delete(key);
@@ -6659,70 +6877,71 @@ static const rb_data_type_t env_data_type = {
};
/*
- * A +Hash+ maps each of its unique keys to a specific value.
+ * A \Hash object maps each of its unique keys to a specific value.
+ *
+ * A hash has certain similarities to an Array, but:
*
- * A +Hash+ has certain similarities to an Array, but:
- * - An Array index is always an Integer.
- * - A +Hash+ key can be (almost) any object.
+ * - An array index is always an integer.
+ * - A hash key can be (almost) any object.
*
- * === +Hash+ \Data Syntax
+ * === \Hash \Data Syntax
*
- * The older syntax for +Hash+ data uses the "hash rocket," <tt>=></tt>:
+ * The original syntax for a hash entry uses the "hash rocket," <tt>=></tt>:
*
* h = {:foo => 0, :bar => 1, :baz => 2}
- * h # => {:foo=>0, :bar=>1, :baz=>2}
+ * h # => {foo: 0, bar: 1, baz: 2}
*
- * Alternatively, but only for a +Hash+ key that's a Symbol,
+ * Alternatively, but only for a key that's a symbol,
* you can use a newer JSON-style syntax,
- * where each bareword becomes a Symbol:
+ * where each bareword becomes a symbol:
*
* h = {foo: 0, bar: 1, baz: 2}
- * h # => {:foo=>0, :bar=>1, :baz=>2}
+ * h # => {foo: 0, bar: 1, baz: 2}
*
- * You can also use a String in place of a bareword:
+ * You can also use a string in place of a bareword:
*
* h = {'foo': 0, 'bar': 1, 'baz': 2}
- * h # => {:foo=>0, :bar=>1, :baz=>2}
+ * h # => {foo: 0, bar: 1, baz: 2}
*
* And you can mix the styles:
*
* h = {foo: 0, :bar => 1, 'baz': 2}
- * h # => {:foo=>0, :bar=>1, :baz=>2}
+ * h # => {foo: 0, bar: 1, baz: 2}
*
* But it's an error to try the JSON-style syntax
- * for a key that's not a bareword or a String:
+ * for a key that's not a bareword or a string:
*
* # Raises SyntaxError (syntax error, unexpected ':', expecting =>):
* h = {0: 'zero'}
*
- * +Hash+ value can be omitted, meaning that value will be fetched from the context
+ * The value can be omitted, meaning that value will be fetched from the context
* by the name of the key:
*
* x = 0
* y = 100
* h = {x:, y:}
- * h # => {:x=>0, :y=>100}
+ * h # => {x: 0, y: 100}
*
* === Common Uses
*
- * You can use a +Hash+ to give names to objects:
+ * You can use a hash to give names to objects:
*
* person = {name: 'Matz', language: 'Ruby'}
- * person # => {:name=>"Matz", :language=>"Ruby"}
+ * person # => {name: "Matz", language: "Ruby"}
*
- * You can use a +Hash+ to give names to method arguments:
+ * 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}
+ * some_method({foo: 0, bar: 1, baz: 2}) # => {foo: 0, bar: 1, baz: 2}
*
- * Note: when the last argument in a method call is a +Hash+,
+ * Note: when the last argument in a method call is a hash,
* the curly braces may be omitted:
*
- * some_method(foo: 0, bar: 1, baz: 2) # => {:foo=>0, :bar=>1, :baz=>2}
+ * some_method(foo: 0, bar: 1, baz: 2) # => {foo: 0, bar: 1, baz: 2}
*
- * You can use a +Hash+ to initialize an object:
+ * You can use a hash to initialize an object:
*
* class Dev
* attr_accessor :name, :language
@@ -6734,98 +6953,90 @@ static const rb_data_type_t env_data_type = {
* matz = Dev.new(name: 'Matz', language: 'Ruby')
* matz # => #<Dev: @name="Matz", @language="Ruby">
*
- * === Creating a +Hash+
+ * === Creating a \Hash
*
- * You can create a +Hash+ object explicitly with:
+ * You can create a \Hash object explicitly with:
*
* - A {hash literal}[rdoc-ref:syntax/literals.rdoc@Hash+Literals].
*
- * You can convert certain objects to Hashes with:
+ * You can convert certain objects to hashes with:
*
- * - \Method #Hash.
+ * - Method Kernel#Hash.
*
- * You can create a +Hash+ by calling method Hash.new.
- *
- * Create an empty +Hash+:
+ * You can create a hash by calling method Hash.new:
*
+ * # Create an empty hash.
* h = Hash.new
* h # => {}
* h.class # => Hash
*
- * You can create a +Hash+ by calling method Hash.[].
- *
- * Create an empty +Hash+:
+ * You can create a hash by calling method Hash.[]:
*
+ * # Create an empty hash.
* h = Hash[]
* h # => {}
- *
- * Create a +Hash+ with initial entries:
- *
+ * # 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).
+ * h # => {foo: 0, bar: 1, baz: 2}
*
- * Create an empty +Hash+:
+ * You can create a hash by using its literal form (curly braces):
*
+ * # Create an empty hash.
* h = {}
* h # => {}
- *
- * Create a +Hash+ with initial entries:
- *
+ * # Create a +Hash+ with initial entries.
* h = {foo: 0, bar: 1, baz: 2}
- * h # => {:foo=>0, :bar=>1, :baz=>2}
+ * h # => {foo: 0, bar: 1, baz: 2}
*
+ * === \Hash Value Basics
*
- * === +Hash+ Value Basics
- *
- * The simplest way to retrieve a +Hash+ value (instance method #[]):
+ * 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 #[]=):
+ * 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: 0, bar: 1, baz: 2, bat: 3}
* h[:foo] = 4 # => 4
- * h # => {:foo=>4, :bar=>1, :baz=>2, :bat=>3}
+ * h # => {foo: 4, bar: 1, baz: 2, bat: 3}
*
- * The simplest way to delete a +Hash+ entry (instance method #delete):
+ * 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}
+ * h # => {foo: 0, baz: 2}
*
* === Entry Order
*
- * A +Hash+ object presents its entries in the order of their creation. This is seen in:
+ * A \Hash object presents its entries in the order of their creation. This is seen in:
*
* - Iterative methods such as <tt>each</tt>, <tt>each_key</tt>, <tt>each_pair</tt>, <tt>each_value</tt>.
* - Other order-sensitive methods such as <tt>shift</tt>, <tt>keys</tt>, <tt>values</tt>.
- * - The String returned by method <tt>inspect</tt>.
+ * - The string returned by method <tt>inspect</tt>.
*
- * A new +Hash+ has its initial ordering per the given entries:
+ * A new hash has its initial ordering per the given entries:
*
* h = Hash[foo: 0, bar: 1]
- * h # => {: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}
+ * 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}
+ * 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}
+ * h # => {bar: 1, baz: 3, foo: 5}
*
* === +Hash+ Keys
*
@@ -6875,7 +7086,7 @@ static const rb_data_type_t env_data_type = {
*
* ==== User-Defined +Hash+ Keys
*
- * To be useable as a +Hash+ key, objects must implement the methods <code>hash</code> and <code>eql?</code>.
+ * To be usable as a +Hash+ key, objects must implement the methods <code>hash</code> and <code>eql?</code>.
* 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 <code>hash</code> and <code>eql?</code>.
*
@@ -6918,97 +7129,92 @@ static const rb_data_type_t env_data_type = {
*
* reviews.length #=> 1
*
- * === Default Values
+ * === Key Not Found?
*
- * 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`).
+ * When a method tries to retrieve and return the value for a key and that key <i>is found</i>,
+ * the returned value is the value associated with the key.
*
- * You can retrieve the default value with method #default:
+ * But what if the key <i>is not found</i>?
+ * In that case, certain methods will return a default value while other will raise a \KeyError.
*
- * h = Hash.new
- * h.default # => nil
+ * ==== Nil Return Value
*
- * You can set the default value by passing an argument to method Hash.new or
- * with method #default=
+ * If you want +nil+ returned for a not-found key, you can call:
*
- * h = Hash.new(-1)
- * h.default # => -1
- * h.default = 0
- * h.default # => 0
+ * - #[](key) (usually written as <tt>#[key]</tt>.
+ * - #assoc(key).
+ * - #dig(key, *identifiers).
+ * - #values_at(*keys).
*
- * This default value is returned for #[], #values_at and #dig when a key is
- * not found:
+ * You can override these behaviors for #[], #dig, and #values_at (but not #assoc);
+ * see {Hash Default}[rdoc-ref:Hash@Hash+Default].
*
- * 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
+ * ==== \KeyError
*
- * Note that the default value is used without being duplicated. It is not advised to set
- * the default value to a mutable object:
+ * If you want KeyError raised for a not-found key, you can call:
*
- * 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
+ * - #fetch(key).
+ * - #fetch_values(*keys).
*
- * To use a mutable object as default, it is recommended to use a default proc
+ * ==== \Hash Default
*
- * ==== Default Proc
+ * For certain methods (#[], #dig, and #values_at),
+ * the return value for a not-found key is determined by two hash properties:
*
- * 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.
+ * - <i>default value</i>: returned by method #default.
+ * - <i>default proc</i>: returned by method #default_proc.
*
- * You can retrieve the default proc with method #default_proc:
+ * In the simple case, both values are +nil+,
+ * and the methods return +nil+ for a not-found key;
+ * see {Nil Return Value}[rdoc-ref:Hash@Nil+Return+Value] above.
*
- * h = Hash.new
- * h.default_proc # => nil
+ * Note that this entire section ("Hash Default"):
*
- * You can set the default proc by calling Hash.new with a block or
- * calling the method #default_proc=
+ * - Applies _only_ to methods #[], #dig, and #values_at.
+ * - Does _not_ apply to methods #assoc, #fetch, or #fetch_values,
+ * which are not affected by the default value or 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
+ * ===== Any-Key Default
+ *
+ * You can define an any-key default for a hash;
+ * that is, a value that will be returned for _any_ not-found key:
+ *
+ * - The value of #default_proc <i>must be</i> +nil+.
+ * - The value of #default (which may be any object, including +nil+)
+ * will be returned for a not-found key.
*
- * 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:
+ * You can set the default value when the hash is created with Hash.new and option +default_value+,
+ * or later with method #default=.
*
- * h = Hash.new { |hash, key| "Default value for #{key}" }
- * h[:nosuch] # => "Default value for nosuch"
+ * Note: although the value of #default may be any object,
+ * it may not be a good idea to use a mutable object.
*
- * Note that in the example above no entry for key +:nosuch+ is created:
+ * ===== Per-Key Defaults
*
- * h.include?(:nosuch) # => false
+ * You can define a per-key default for a hash;
+ * that is, a Proc that will return a value based on the key itself.
*
- * However, the proc itself can add a new entry:
+ * You can set the default proc when the hash is created with Hash.new and a block,
+ * or later with method #default_proc=.
*
- * 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 the proc can modify +self+,
+ * but modifying +self+ in this way is not thread-safe;
+ * multiple threads can concurrently call into the default proc
+ * for the same key.
*
- * Note that setting the default proc will clear the default value and vice versa.
+ * ==== \Method Default
*
- * Be aware that a default proc that modifies the hash is not thread-safe in the
- * sense that multiple threads can call into the default proc concurrently for the
- * same key.
+ * For two methods, you can specify a default value for a not-found key
+ * that has effect only for a single method call
+ * (and not for any subsequent calls):
+ *
+ * - For method #fetch, you can specify an any-key default:
+ * - For either method #fetch or method #fetch_values,
+ * you can specify a per-key default via a block.
*
* === What's Here
*
- * First, what's elsewhere. \Class +Hash+:
+ * First, what's elsewhere. Class +Hash+:
*
* - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
* - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
@@ -7026,9 +7232,8 @@ static const rb_data_type_t env_data_type = {
* - {Iterating}[rdoc-ref:Hash@Methods+for+Iterating]
* - {Converting}[rdoc-ref:Hash@Methods+for+Converting]
* - {Transforming Keys and Values}[rdoc-ref:Hash@Methods+for+Transforming+Keys+and+Values]
- * - {And more....}[rdoc-ref:Hash@Other+Methods]
*
- * \Class +Hash+ also includes methods from module Enumerable.
+ * Class +Hash+ also includes methods from module Enumerable.
*
* ==== Methods for Creating a +Hash+
*
@@ -7052,10 +7257,9 @@ static const rb_data_type_t env_data_type = {
* - #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+.
+ * - #has_value? (aliased as #value?): Returns whether a given object is a value in +self+.
+ * - #include? (aliased as #has_key?, #member?, #key?): Returns whether a given object is a key in +self+.
+ * - #size (aliased as #length): Returns the count of entries.
*
* ==== Methods for Comparing
*
@@ -7077,15 +7281,15 @@ static const rb_data_type_t env_data_type = {
* - #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: 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.
+ * - #[]= (aliased as #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 given hash.
+ * - #update (aliased as #merge!): Merges each given hash into +self+.
+ * - #replace (aliased as #initialize_copy): Replaces the entire contents of +self+ with the contents of a given hash.
*
* ==== Methods for Deleting
*
@@ -7095,7 +7299,7 @@ static const rb_data_type_t env_data_type = {
* - #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.
+ * - #select! (aliased as #filter!): 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.
@@ -7104,18 +7308,19 @@ static const rb_data_type_t env_data_type = {
*
* - #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.
+ * - #select (aliased as #filter): 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_pair (aliased as #each): 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.
+ * - #flatten: Returns an array that is a 1-dimensional flattening of +self+.
+ * - #inspect (aliased as #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+;
@@ -7125,15 +7330,12 @@ static const rb_data_type_t env_data_type = {
*
* ==== Methods for Transforming Keys and Values
*
+ * - #invert: Returns a hash with the each key-value pair inverted.
* - #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
@@ -7150,9 +7352,9 @@ Init_Hash(void)
rb_define_alloc_func(rb_cHash, empty_hash_alloc);
rb_define_singleton_method(rb_cHash, "[]", rb_hash_s_create, -1);
rb_define_singleton_method(rb_cHash, "try_convert", rb_hash_s_try_convert, 1);
- rb_define_method(rb_cHash, "initialize", rb_hash_initialize, -1);
rb_define_method(rb_cHash, "initialize_copy", rb_hash_replace, 1);
rb_define_method(rb_cHash, "rehash", rb_hash_rehash, 0);
+ rb_define_method(rb_cHash, "freeze", rb_hash_freeze, 0);
rb_define_method(rb_cHash, "to_hash", rb_hash_to_hash, 0);
rb_define_method(rb_cHash, "to_h", rb_hash_to_h, 0);
@@ -7239,6 +7441,10 @@ Init_Hash(void)
rb_define_singleton_method(rb_cHash, "ruby2_keywords_hash?", rb_hash_s_ruby2_keywords_hash_p, 1);
rb_define_singleton_method(rb_cHash, "ruby2_keywords_hash", rb_hash_s_ruby2_keywords_hash, 1);
+ rb_cHash_empty_frozen = rb_hash_freeze(rb_hash_new());
+ RB_OBJ_SET_SHAREABLE(rb_cHash_empty_frozen);
+ rb_vm_register_global_object(rb_cHash_empty_frozen);
+
/* Document-class: ENV
*
* +ENV+ is a hash-like accessor for environment variables.
@@ -7320,7 +7526,7 @@ Init_Hash(void)
*
* === What's Here
*
- * First, what's elsewhere. \Class +ENV+:
+ * First, what's elsewhere. Class +ENV+:
*
* - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
* - Extends {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
@@ -7372,7 +7578,7 @@ Init_Hash(void)
*
* - ::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).
+ * - ::clone: Raises an exception.
* - ::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.
@@ -7406,8 +7612,7 @@ Init_Hash(void)
origenviron = environ;
envtbl = TypedData_Wrap_Struct(rb_cObject, &env_data_type, NULL);
rb_extend_object(envtbl, rb_mEnumerable);
- FL_SET_RAW(envtbl, RUBY_FL_SHAREABLE);
-
+ RB_OBJ_SET_SHAREABLE(envtbl);
rb_define_singleton_method(envtbl, "[]", rb_f_getenv, 1);
rb_define_singleton_method(envtbl, "fetch", env_fetch, -1);
@@ -7472,8 +7677,7 @@ Init_Hash(void)
*/
rb_define_global_const("ENV", envtbl);
- /* for callcc */
- ruby_register_rollback_func_for_ensure(hash_foreach_ensure, hash_foreach_ensure_rollback);
-
HASH_ASSERT(sizeof(ar_hint_t) * RHASH_AR_TABLE_MAX_SIZE == sizeof(VALUE));
}
+
+#include "hash.rbinc"
diff --git a/hash.rb b/hash.rb
new file mode 100644
index 0000000000..99b34a9bda
--- /dev/null
+++ b/hash.rb
@@ -0,0 +1,40 @@
+class Hash
+ # call-seq:
+ # Hash.new(default_value = nil, capacity: 0) -> new_hash
+ # Hash.new(capacity: 0) {|self, key| ... } -> new_hash
+ #
+ # Returns a new empty \Hash object.
+ #
+ # Initializes the values of Hash#default and Hash#default_proc,
+ # which determine the behavior when a given key is not found;
+ # see {Key Not Found?}[rdoc-ref:Hash@Key+Not+Found-3F].
+ #
+ # By default, a hash has +nil+ values for both +default+ and +default_proc+:
+ #
+ # h = Hash.new # => {}
+ # h.default # => nil
+ # h.default_proc # => nil
+ #
+ # With argument +default_value+ given, sets the +default+ value for the hash:
+ #
+ # h = Hash.new(false) # => {}
+ # h.default # => false
+ # h.default_proc # => nil
+ #
+ # With a block given, sets the +default_proc+ value:
+ #
+ # h = Hash.new {|hash, key| "Hash #{hash}: Default value for #{key}" }
+ # h.default # => nil
+ # h.default_proc # => #<Proc:0x00000289b6fa7048 (irb):185>
+ # h[:nosuch] # => "Hash {}: Default value for nosuch"
+ #
+ # Raises ArgumentError if both +default_value+ and a block are given.
+ #
+ # If optional keyword argument +capacity+ is given with a positive integer value +n+,
+ # initializes the hash with enough capacity to accommodate +n+ entries without resizing.
+ #
+ # See also {Methods for Creating a Hash}[rdoc-ref:Hash@Methods+for+Creating+a+Hash].
+ def initialize(ifnone = (ifnone_unset = true), capacity: 0, &block)
+ Primitive.rb_hash_init(capacity, ifnone_unset, ifnone, block)
+ end
+end
diff --git a/id_table.c b/id_table.c
index 6bb067d09a..cece14c389 100644
--- a/id_table.c
+++ b/id_table.c
@@ -47,7 +47,7 @@ struct rb_id_table {
#if SIZEOF_VALUE == 8
#define ITEM_GET_KEY(tbl, i) ((tbl)->items[i].key)
-#define ITEM_KEY_ISSET(tbl, i) ((tbl)->items[i].key)
+#define ITEM_KEY_ISSET(tbl, i) ((tbl)->items && (tbl)->items[i].key)
#define ITEM_COLLIDED(tbl, i) ((tbl)->items[i].collision)
#define ITEM_SET_COLLIDED(tbl, i) ((tbl)->items[i].collision = 1)
static inline void
@@ -80,9 +80,10 @@ round_capa(int capa)
return (capa + 1) << 2;
}
-static struct rb_id_table *
-rb_id_table_init(struct rb_id_table *tbl, int capa)
+struct rb_id_table *
+rb_id_table_init(struct rb_id_table *tbl, size_t s_capa)
{
+ int capa = (int)s_capa;
MEMZERO(tbl, struct rb_id_table, 1);
if (capa > 0) {
capa = round_capa(capa);
@@ -96,7 +97,13 @@ struct rb_id_table *
rb_id_table_create(size_t capa)
{
struct rb_id_table *tbl = ALLOC(struct rb_id_table);
- return rb_id_table_init(tbl, (int)capa);
+ return rb_id_table_init(tbl, capa);
+}
+
+void
+rb_id_table_free_items(struct rb_id_table *tbl)
+{
+ xfree(tbl->items);
}
void
@@ -291,6 +298,10 @@ rb_id_table_foreach_values(struct rb_id_table *tbl, rb_id_table_foreach_values_f
{
int i, capa = tbl->capa;
+ if (!tbl->items) {
+ return;
+ }
+
for (i=0; i<capa; i++) {
if (ITEM_KEY_ISSET(tbl, i)) {
enum rb_id_table_iterator_result ret = (*func)(tbl->items[i].val, data);
@@ -324,3 +335,106 @@ rb_id_table_foreach_values_with_replace(struct rb_id_table *tbl, rb_id_table_for
}
}
+static void
+managed_id_table_free(void *data)
+{
+ struct rb_id_table *tbl = (struct rb_id_table *)data;
+ rb_id_table_free_items(tbl);
+}
+
+static size_t
+managed_id_table_memsize(const void *data)
+{
+ const struct rb_id_table *tbl = (const struct rb_id_table *)data;
+ return rb_id_table_memsize(tbl) - sizeof(struct rb_id_table);
+}
+
+const rb_data_type_t rb_managed_id_table_type = {
+ .wrap_struct_name = "VM/managed_id_table",
+ .function = {
+ .dmark = NULL, // Nothing to mark
+ .dfree = managed_id_table_free,
+ .dsize = managed_id_table_memsize,
+ },
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE,
+};
+
+static inline struct rb_id_table *
+managed_id_table_ptr(VALUE obj)
+{
+ RUBY_ASSERT(RB_TYPE_P(obj, T_DATA));
+ RUBY_ASSERT(rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj), &rb_managed_id_table_type));
+
+ return RTYPEDDATA_GET_DATA(obj);
+}
+
+VALUE
+rb_managed_id_table_create(const rb_data_type_t *type, size_t capa)
+{
+ struct rb_id_table *tbl;
+ VALUE obj = TypedData_Make_Struct(0, struct rb_id_table, type, tbl);
+ RB_OBJ_SET_SHAREABLE(obj);
+ rb_id_table_init(tbl, capa); // NOTE: this can cause GC, so dmark and dsize need to check tbl->items
+ return obj;
+}
+
+VALUE
+rb_managed_id_table_new(size_t capa)
+{
+ return rb_managed_id_table_create(&rb_managed_id_table_type, capa);
+}
+
+static enum rb_id_table_iterator_result
+managed_id_table_dup_i(ID id, VALUE val, void *data)
+{
+ struct rb_id_table *new_tbl = (struct rb_id_table *)data;
+ rb_id_table_insert(new_tbl, id, val);
+ return ID_TABLE_CONTINUE;
+}
+
+VALUE
+rb_managed_id_table_dup(VALUE old_table)
+{
+ struct rb_id_table *new_tbl;
+ VALUE obj = TypedData_Make_Struct(0, struct rb_id_table, RTYPEDDATA_TYPE(old_table), new_tbl);
+ struct rb_id_table *old_tbl = managed_id_table_ptr(old_table);
+ rb_id_table_init(new_tbl, old_tbl->num + 1);
+ rb_id_table_foreach(old_tbl, managed_id_table_dup_i, new_tbl);
+ return obj;
+}
+
+int
+rb_managed_id_table_lookup(VALUE table, ID id, VALUE *valp)
+{
+ return rb_id_table_lookup(managed_id_table_ptr(table), id, valp);
+}
+
+int
+rb_managed_id_table_insert(VALUE table, ID id, VALUE val)
+{
+ return rb_id_table_insert(managed_id_table_ptr(table), id, val);
+}
+
+size_t
+rb_managed_id_table_size(VALUE table)
+{
+ return rb_id_table_size(managed_id_table_ptr(table));
+}
+
+void
+rb_managed_id_table_foreach(VALUE table, rb_id_table_foreach_func_t *func, void *data)
+{
+ rb_id_table_foreach(managed_id_table_ptr(table), func, data);
+}
+
+void
+rb_managed_id_table_foreach_values(VALUE table, rb_id_table_foreach_values_func_t *func, void *data)
+{
+ rb_id_table_foreach_values(managed_id_table_ptr(table), func, data);
+}
+
+int
+rb_managed_id_table_delete(VALUE table, ID id)
+{
+ return rb_id_table_delete(managed_id_table_ptr(table), id);
+}
diff --git a/id_table.h b/id_table.h
index f72e2d1d92..0c8cd343ee 100644
--- a/id_table.h
+++ b/id_table.h
@@ -16,7 +16,10 @@ enum rb_id_table_iterator_result {
};
struct rb_id_table *rb_id_table_create(size_t size);
+struct rb_id_table *rb_id_table_init(struct rb_id_table *tbl, size_t capa);
+
void rb_id_table_free(struct rb_id_table *tbl);
+void rb_id_table_free_items(struct rb_id_table *tbl);
void rb_id_table_clear(struct rb_id_table *tbl);
size_t rb_id_table_memsize(const struct rb_id_table *tbl);
@@ -32,6 +35,18 @@ void rb_id_table_foreach(struct rb_id_table *tbl, rb_id_table_foreach_func_t *fu
void rb_id_table_foreach_values(struct rb_id_table *tbl, rb_id_table_foreach_values_func_t *func, void *data);
void rb_id_table_foreach_values_with_replace(struct rb_id_table *tbl, rb_id_table_foreach_values_func_t *func, rb_id_table_update_value_callback_func_t *replace, void *data);
+VALUE rb_managed_id_table_create(const rb_data_type_t *type, size_t capa);
+VALUE rb_managed_id_table_new(size_t capa);
+VALUE rb_managed_id_table_dup(VALUE table);
+int rb_managed_id_table_insert(VALUE table, ID id, VALUE val);
+int rb_managed_id_table_lookup(VALUE table, ID id, VALUE *valp);
+size_t rb_managed_id_table_size(VALUE table);
+void rb_managed_id_table_foreach(VALUE table, rb_id_table_foreach_func_t *func, void *data);
+void rb_managed_id_table_foreach_values(VALUE table, rb_id_table_foreach_values_func_t *func, void *data);
+int rb_managed_id_table_delete(VALUE table, ID id);
+
+extern const rb_data_type_t rb_managed_id_table_type;
+
RUBY_SYMBOL_EXPORT_BEGIN
size_t rb_id_table_size(const struct rb_id_table *tbl);
RUBY_SYMBOL_EXPORT_END
diff --git a/imemo.c b/imemo.c
index 1face1ce4e..d949466a77 100644
--- a/imemo.c
+++ b/imemo.c
@@ -3,6 +3,8 @@
#include "id_table.h"
#include "internal.h"
#include "internal/imemo.h"
+#include "internal/object.h"
+#include "internal/st.h"
#include "vm_callinfo.h"
size_t rb_iseq_memsize(const rb_iseq_t *iseq);
@@ -15,7 +17,6 @@ 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(ast);
IMEMO_NAME(callcache);
IMEMO_NAME(callinfo);
IMEMO_NAME(constcache);
@@ -25,14 +26,13 @@ rb_imemo_name(enum imemo_type type)
IMEMO_NAME(iseq);
IMEMO_NAME(memo);
IMEMO_NAME(ment);
- IMEMO_NAME(parser_strterm);
IMEMO_NAME(svar);
IMEMO_NAME(throw_data);
IMEMO_NAME(tmpbuf);
+ IMEMO_NAME(fields);
#undef IMEMO_NAME
- default:
- rb_bug("unreachable");
}
+ rb_bug("unreachable");
}
/* =========================================================================
@@ -40,36 +40,36 @@ rb_imemo_name(enum imemo_type type)
* ========================================================================= */
VALUE
-rb_imemo_new(enum imemo_type type, VALUE v0)
+rb_imemo_new(enum imemo_type type, VALUE v0, size_t size, bool is_shareable)
{
- size_t size = RVALUE_SIZE;
- VALUE flags = T_IMEMO | FL_WB_PROTECTED | (type << FL_USHIFT);
+ VALUE flags = T_IMEMO | FL_WB_PROTECTED | (type << FL_USHIFT) | (is_shareable ? FL_SHAREABLE : 0);
NEWOBJ_OF(obj, void, v0, flags, size, 0);
return (VALUE)obj;
}
-static rb_imemo_tmpbuf_t *
+VALUE
rb_imemo_tmpbuf_new(void)
{
- size_t size = sizeof(struct rb_imemo_tmpbuf_struct);
VALUE flags = T_IMEMO | (imemo_tmpbuf << FL_USHIFT);
- NEWOBJ_OF(obj, struct rb_imemo_tmpbuf_struct, 0, flags, size, 0);
+ NEWOBJ_OF(obj, rb_imemo_tmpbuf_t, 0, flags, sizeof(rb_imemo_tmpbuf_t), NULL);
+
+ rb_gc_register_pinning_obj((VALUE)obj);
+
+ obj->ptr = NULL;
+ obj->cnt = 0;
- return obj;
+ return (VALUE)obj;
}
void *
rb_alloc_tmp_buffer_with_count(volatile VALUE *store, size_t size, size_t cnt)
{
- void *ptr;
- rb_imemo_tmpbuf_t *tmpbuf;
-
/* Keep the order; allocate an empty imemo first then xmalloc, to
* get rid of potential memory leak */
- tmpbuf = rb_imemo_tmpbuf_new();
+ rb_imemo_tmpbuf_t *tmpbuf = (rb_imemo_tmpbuf_t *)rb_imemo_tmpbuf_new();
*store = (VALUE)tmpbuf;
- ptr = ruby_xmalloc(size);
+ void *ptr = ruby_xmalloc(size);
tmpbuf->ptr = ptr;
tmpbuf->cnt = cnt;
@@ -94,31 +94,134 @@ rb_free_tmp_buffer(volatile VALUE *store)
rb_imemo_tmpbuf_t *s = (rb_imemo_tmpbuf_t*)ATOMIC_VALUE_EXCHANGE(*store, 0);
if (s) {
void *ptr = ATOMIC_PTR_EXCHANGE(s->ptr, 0);
+ long cnt = s->cnt;
s->cnt = 0;
- ruby_xfree(ptr);
+ ruby_sized_xfree(ptr, sizeof(VALUE) * cnt);
}
}
-rb_imemo_tmpbuf_t *
-rb_imemo_tmpbuf_parser_heap(void *buf, rb_imemo_tmpbuf_t *old_heap, size_t cnt)
+struct MEMO *
+rb_imemo_memo_new(VALUE a, VALUE b, VALUE c)
{
- rb_imemo_tmpbuf_t *tmpbuf = rb_imemo_tmpbuf_new();
- tmpbuf->ptr = buf;
- tmpbuf->next = old_heap;
- tmpbuf->cnt = cnt;
+ struct MEMO *memo = IMEMO_NEW(struct MEMO, imemo_memo, 0);
+
+ rb_gc_register_pinning_obj((VALUE)memo);
- return tmpbuf;
+ *((VALUE *)&memo->v1) = a;
+ *((VALUE *)&memo->v2) = b;
+ *((VALUE *)&memo->u3.value) = c;
+
+ return memo;
+}
+
+static VALUE
+imemo_fields_new(VALUE owner, size_t capa, bool shareable)
+{
+ size_t embedded_size = offsetof(struct rb_fields, as.embed) + capa * sizeof(VALUE);
+ if (rb_gc_size_allocatable_p(embedded_size)) {
+ VALUE fields = rb_imemo_new(imemo_fields, owner, embedded_size, shareable);
+ RUBY_ASSERT(IMEMO_TYPE_P(fields, imemo_fields));
+ return fields;
+ }
+ else {
+ VALUE fields = rb_imemo_new(imemo_fields, owner, sizeof(struct rb_fields), shareable);
+ IMEMO_OBJ_FIELDS(fields)->as.external.ptr = ALLOC_N(VALUE, capa);
+ FL_SET_RAW(fields, OBJ_FIELD_HEAP);
+ return fields;
+ }
}
-#if IMEMO_DEBUG
VALUE
-rb_imemo_new_debug(enum imemo_type type, VALUE v0, const char *file, int line)
+rb_imemo_fields_new(VALUE owner, size_t capa, bool shareable)
{
- VALUE memo = rb_imemo_new(type, v0);
- fprintf(stderr, "memo %p (type: %d) @ %s:%d\n", (void *)memo, imemo_type(memo), file, line);
- return memo;
+ return imemo_fields_new(owner, capa, shareable);
+}
+
+static VALUE
+imemo_fields_new_complex(VALUE owner, size_t capa, bool shareable)
+{
+ VALUE fields = rb_imemo_new(imemo_fields, owner, sizeof(struct rb_fields), shareable);
+ IMEMO_OBJ_FIELDS(fields)->as.complex.table = st_init_numtable_with_size(capa);
+ FL_SET_RAW(fields, OBJ_FIELD_HEAP);
+ return fields;
+}
+
+VALUE
+rb_imemo_fields_new_complex(VALUE owner, size_t capa, bool shareable)
+{
+ return imemo_fields_new_complex(owner, capa, shareable);
+}
+
+static int
+imemo_fields_trigger_wb_i(st_data_t key, st_data_t value, st_data_t arg)
+{
+ VALUE field_obj = (VALUE)arg;
+ RB_OBJ_WRITTEN(field_obj, Qundef, (VALUE)value);
+ return ST_CONTINUE;
+}
+
+static int
+imemo_fields_complex_wb_i(st_data_t key, st_data_t value, st_data_t arg)
+{
+ RB_OBJ_WRITTEN((VALUE)arg, Qundef, (VALUE)value);
+ return ST_CONTINUE;
+}
+
+VALUE
+rb_imemo_fields_new_complex_tbl(VALUE owner, st_table *tbl, bool shareable)
+{
+ VALUE fields = rb_imemo_new(imemo_fields, owner, sizeof(struct rb_fields), shareable);
+ IMEMO_OBJ_FIELDS(fields)->as.complex.table = tbl;
+ FL_SET_RAW(fields, OBJ_FIELD_HEAP);
+ st_foreach(tbl, imemo_fields_trigger_wb_i, (st_data_t)fields);
+ return fields;
+}
+
+VALUE
+rb_imemo_fields_clone(VALUE fields_obj)
+{
+ shape_id_t shape_id = RBASIC_SHAPE_ID(fields_obj);
+ VALUE clone;
+
+ if (rb_shape_too_complex_p(shape_id)) {
+ st_table *src_table = rb_imemo_fields_complex_tbl(fields_obj);
+
+ st_table *dest_table = xcalloc(1, sizeof(st_table));
+ clone = rb_imemo_fields_new_complex_tbl(rb_imemo_fields_owner(fields_obj), dest_table, false /* TODO: check */);
+
+ st_replace(dest_table, src_table);
+ RBASIC_SET_SHAPE_ID(clone, shape_id);
+
+ st_foreach(dest_table, imemo_fields_complex_wb_i, (st_data_t)clone);
+ }
+ else {
+ clone = imemo_fields_new(rb_imemo_fields_owner(fields_obj), RSHAPE_CAPACITY(shape_id), false /* TODO: check */);
+ RBASIC_SET_SHAPE_ID(clone, shape_id);
+ VALUE *fields = rb_imemo_fields_ptr(clone);
+ attr_index_t fields_count = RSHAPE_LEN(shape_id);
+ MEMCPY(fields, rb_imemo_fields_ptr(fields_obj), VALUE, fields_count);
+ for (attr_index_t i = 0; i < fields_count; i++) {
+ RB_OBJ_WRITTEN(clone, Qundef, fields[i]);
+ }
+ }
+
+ return clone;
+}
+
+void
+rb_imemo_fields_clear(VALUE fields_obj)
+{
+ // When replacing an imemo/fields by another one, we must clear
+ // its shape so that gc.c:obj_free_object_id won't be called.
+ if (rb_shape_obj_too_complex_p(fields_obj)) {
+ RBASIC_SET_SHAPE_ID(fields_obj, ROOT_TOO_COMPLEX_SHAPE_ID);
+ }
+ else {
+ RBASIC_SET_SHAPE_ID(fields_obj, ROOT_SHAPE_ID);
+ }
+ // Invalidate the ec->gen_fields_cache.
+ RBASIC_CLEAR_CLASS(fields_obj);
}
-#endif
/* =========================================================================
* memsize
@@ -129,10 +232,6 @@ rb_imemo_memsize(VALUE obj)
{
size_t size = 0;
switch (imemo_type(obj)) {
- case imemo_ast:
- rb_bug("imemo_ast is obsolete");
-
- break;
case imemo_callcache:
break;
case imemo_callinfo:
@@ -157,8 +256,6 @@ rb_imemo_memsize(VALUE obj)
size += sizeof(((rb_method_entry_t *)obj)->def);
break;
- case imemo_parser_strterm:
- break;
case imemo_svar:
break;
case imemo_throw_data:
@@ -167,6 +264,16 @@ rb_imemo_memsize(VALUE obj)
size += ((rb_imemo_tmpbuf_t *)obj)->cnt * sizeof(VALUE);
break;
+ case imemo_fields:
+ if (FL_TEST_RAW(obj, OBJ_FIELD_HEAP)) {
+ if (rb_shape_obj_too_complex_p(obj)) {
+ size += st_memsize(IMEMO_OBJ_FIELDS(obj)->as.complex.table);
+ }
+ else {
+ size += RSHAPE_CAPACITY(RBASIC_SHAPE_ID(obj)) * sizeof(VALUE);
+ }
+ }
+ break;
default:
rb_bug("unreachable");
}
@@ -178,43 +285,10 @@ rb_imemo_memsize(VALUE obj)
* mark
* ========================================================================= */
-static enum rb_id_table_iterator_result
-cc_table_mark_i(ID id, VALUE ccs_ptr, void *data)
-{
- 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 {
- rb_gc_mark_movable((VALUE)ccs->cme);
-
- for (int i=0; i<ccs->len; i++) {
- VM_ASSERT((VALUE)data == ccs->entries[i].cc->klass);
- VM_ASSERT(vm_cc_check_cme(ccs->entries[i].cc, ccs->cme));
-
- rb_gc_mark_movable((VALUE)ccs->entries[i].cc);
- }
- return ID_TABLE_CONTINUE;
- }
-}
-
-void
-rb_cc_table_mark(VALUE klass)
-{
- struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass);
- if (cc_tbl) {
- rb_id_table_foreach(cc_tbl, cc_table_mark_i, (void *)klass);
- }
-}
-
static bool
moved_or_living_object_strictly_p(VALUE obj)
{
- return obj && (rb_objspace_markable_object_p(obj) || BUILTIN_TYPE(obj) == T_MOVED);
+ return !SPECIAL_CONST_P(obj) && (!rb_objspace_garbage_object_p(obj) || BUILTIN_TYPE(obj) == T_MOVED);
}
static void
@@ -246,9 +320,8 @@ mark_and_move_method_entry(rb_method_entry_t *ment, bool reference_updating)
rb_gc_mark_and_move(&def->body.attr.location);
break;
case VM_METHOD_TYPE_BMETHOD:
- rb_gc_mark_and_move(&def->body.bmethod.proc);
- if (!reference_updating) {
- if (def->body.bmethod.hooks) rb_hook_list_mark(def->body.bmethod.hooks);
+ if (!rb_gc_checking_shareable()) {
+ rb_gc_mark_and_move(&def->body.bmethod.proc);
}
break;
case VM_METHOD_TYPE_ALIAS:
@@ -272,49 +345,51 @@ void
rb_imemo_mark_and_move(VALUE obj, bool reference_updating)
{
switch (imemo_type(obj)) {
- case imemo_ast:
- rb_bug("imemo_ast is obsolete");
-
- break;
case imemo_callcache: {
/* cc is callcache.
*
* cc->klass (klass) should not be marked because if the klass is
* free'ed, the cc->klass will be cleared by `vm_cc_invalidate()`.
*
- * cc->cme (cme) should not be marked because if cc is invalidated
- * when cme is free'ed.
+ * For "normal" CCs cc->cme (cme) should not be marked because the cc is
+ * invalidated through the klass when the cme is free'd.
* - klass marks cme if klass uses cme.
- * - caller classe's ccs->cme marks cc->cme.
- * - if cc is invalidated (klass doesn't refer the cc),
- * cc is invalidated by `vm_cc_invalidate()` and cc->cme is
- * not be accessed.
- * - On the multi-Ractors, cme will be collected with global GC
+ * - caller class's ccs->cme marks cc->cme.
+ * - if cc is invalidated (klass doesn't refer the cc), cc is
+ * invalidated by `vm_cc_invalidate()` after which cc->cme must not
+ * be accessed.
+ * - With multi-Ractors, cme will be collected with global GC
* so that it is safe if GC is not interleaving while accessing
* cc and cme.
- * - However, cc_type_super and cc_type_refinement are not chained
- * from ccs so cc->cme should be marked; the cme might be
- * reachable only through cc in these cases.
+ *
+ * However cc_type_super and cc_type_refinement are not chained
+ * from ccs so cc->cme should be marked as long as the cc is valid;
+ * the cme might be reachable only through cc in these cases.
*/
struct rb_callcache *cc = (struct rb_callcache *)obj;
- if (reference_updating) {
- if (!cc->klass) {
- // already invalidated
+ if (UNDEF_P(cc->klass)) {
+ /* If it's invalidated, we must not mark anything.
+ * All fields should are considered invalid
+ */
+ }
+ else if (reference_updating) {
+ if (moved_or_living_object_strictly_p((VALUE)cc->cme_)) {
+ *((VALUE *)&cc->klass) = rb_gc_location(cc->klass);
+ *((struct rb_callable_method_entry_struct **)&cc->cme_) =
+ (struct rb_callable_method_entry_struct *)rb_gc_location((VALUE)cc->cme_);
+
+ RUBY_ASSERT(RB_TYPE_P(cc->klass, T_CLASS) || RB_TYPE_P(cc->klass, T_ICLASS));
+ RUBY_ASSERT(IMEMO_TYPE_P((VALUE)cc->cme_, imemo_ment));
}
else {
- if (moved_or_living_object_strictly_p(cc->klass) &&
- moved_or_living_object_strictly_p((VALUE)cc->cme_)) {
- *((VALUE *)&cc->klass) = rb_gc_location(cc->klass);
- *((struct rb_callable_method_entry_struct **)&cc->cme_) =
- (struct rb_callable_method_entry_struct *)rb_gc_location((VALUE)cc->cme_);
- }
- else {
- vm_cc_invalidate(cc);
- }
+ vm_cc_invalidate(cc);
}
}
else {
- if (vm_cc_super_p(cc) || vm_cc_refinement_p(cc)) {
+ RUBY_ASSERT(RB_TYPE_P(cc->klass, T_CLASS) || RB_TYPE_P(cc->klass, T_ICLASS));
+ RUBY_ASSERT(IMEMO_TYPE_P((VALUE)cc->cme_, imemo_ment));
+
+ if ((vm_cc_super_p(cc) || vm_cc_refinement_p(cc))) {
rb_gc_mark_movable((VALUE)cc->cme_);
}
}
@@ -326,16 +401,27 @@ rb_imemo_mark_and_move(VALUE obj, bool reference_updating)
case imemo_constcache: {
struct iseq_inline_constant_cache_entry *ice = (struct iseq_inline_constant_cache_entry *)obj;
- rb_gc_mark_and_move(&ice->value);
+ if ((ice->flags & IMEMO_CONST_CACHE_SHAREABLE) ||
+ !rb_gc_checking_shareable()) {
+ rb_gc_mark_and_move(&ice->value);
+ }
break;
}
case imemo_cref: {
rb_cref_t *cref = (rb_cref_t *)obj;
- rb_gc_mark_and_move(&cref->klass_or_self);
+ if (!rb_gc_checking_shareable()) {
+ // cref->klass_or_self can be unshareable, but no way to access it from other ractors
+ rb_gc_mark_and_move(&cref->klass_or_self);
+ }
+
rb_gc_mark_and_move_ptr(&cref->next);
- rb_gc_mark_and_move(&cref->refinements);
+
+ // TODO: Ractor and refeinements are not resolved yet
+ if (!rb_gc_checking_shareable()) {
+ rb_gc_mark_and_move(&cref->refinements);
+ }
break;
}
@@ -353,11 +439,20 @@ rb_imemo_mark_and_move(VALUE obj, bool reference_updating)
rb_gc_mark_and_move_ptr(&env->iseq);
+ if (VM_ENV_LOCAL_P(env->ep) && VM_ENV_BOXED_P(env->ep)) {
+ const rb_box_t *box = VM_ENV_BOX(env->ep);
+ if (BOX_USER_P(box)) {
+ rb_gc_mark_and_move((VALUE *)&box->box_object);
+ }
+ }
+
if (reference_updating) {
((VALUE *)env->ep)[VM_ENV_DATA_INDEX_ENV] = rb_gc_location(env->ep[VM_ENV_DATA_INDEX_ENV]);
}
else {
- VM_ENV_FLAGS_SET(env->ep, VM_ENV_FLAG_WB_REQUIRED);
+ if (!VM_ENV_FLAGS(env->ep, VM_ENV_FLAG_WB_REQUIRED)) {
+ VM_ENV_FLAGS_SET(env->ep, VM_ENV_FLAG_WB_REQUIRED);
+ }
rb_gc_mark_movable( (VALUE)rb_vm_env_prev_env(env));
}
}
@@ -390,8 +485,6 @@ rb_imemo_mark_and_move(VALUE obj, bool reference_updating)
case imemo_ment:
mark_and_move_method_entry((rb_method_entry_t *)obj, reference_updating);
break;
- case imemo_parser_strterm:
- break;
case imemo_svar: {
struct vm_svar *svar = (struct vm_svar *)obj;
@@ -413,13 +506,37 @@ rb_imemo_mark_and_move(VALUE obj, bool reference_updating)
const rb_imemo_tmpbuf_t *m = (const rb_imemo_tmpbuf_t *)obj;
if (!reference_updating) {
- do {
- rb_gc_mark_locations(m->ptr, m->ptr + m->cnt);
- } while ((m = m->next) != NULL);
+ rb_gc_mark_locations(m->ptr, m->ptr + m->cnt);
}
break;
}
+ case imemo_fields: {
+ rb_gc_mark_and_move((VALUE *)&RBASIC(obj)->klass);
+
+ if (!rb_gc_checking_shareable()) {
+ // imemo_fields can refer unshareable objects
+ // even if the imemo_fields is shareable.
+
+ if (rb_shape_obj_too_complex_p(obj)) {
+ st_table *tbl = rb_imemo_fields_complex_tbl(obj);
+ if (reference_updating) {
+ rb_gc_ref_update_table_values_only(tbl);
+ }
+ else {
+ rb_mark_tbl_no_pin(tbl);
+ }
+ }
+ else {
+ VALUE *fields = rb_imemo_fields_ptr(obj);
+ attr_index_t len = RSHAPE_LEN(RBASIC_SHAPE_ID(obj));
+ for (attr_index_t i = 0; i < len; i++) {
+ rb_gc_mark_and_move(&fields[i]);
+ }
+ }
+ }
+ break;
+ }
default:
rb_bug("unreachable");
}
@@ -444,67 +561,16 @@ rb_free_const_table(struct rb_id_table *tbl)
rb_id_table_free(tbl);
}
-// alive: if false, target pointers can be freed already.
-static void
-vm_ccs_free(struct rb_class_cc_entries *ccs, int alive, VALUE klass)
+static inline void
+imemo_fields_free(struct rb_fields *fields)
{
- if (ccs->entries) {
- for (int i=0; i<ccs->len; i++) {
- const struct rb_callcache *cc = ccs->entries[i].cc;
- if (!alive) {
- void *ptr = asan_unpoison_object_temporary((VALUE)cc);
- // ccs can be free'ed.
- if (rb_objspace_markable_object_p((VALUE)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_ASSERT(!vm_cc_super_p(cc) && !vm_cc_refinement_p(cc));
- vm_cc_invalidate(cc);
+ if (FL_TEST_RAW((VALUE)fields, OBJ_FIELD_HEAP)) {
+ if (rb_shape_obj_too_complex_p((VALUE)fields)) {
+ st_free_table(fields->as.complex.table);
+ }
+ else {
+ xfree(fields->as.external.ptr);
}
- 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, Qundef);
-}
-
-static enum rb_id_table_iterator_result
-cc_table_free_i(VALUE ccs_ptr, void *data)
-{
- struct rb_class_cc_entries *ccs = (struct rb_class_cc_entries *)ccs_ptr;
- VALUE klass = (VALUE)data;
- VM_ASSERT(vm_ccs_p(ccs));
-
- vm_ccs_free(ccs, false, klass);
-
- return ID_TABLE_CONTINUE;
-}
-
-void
-rb_cc_table_free(VALUE klass)
-{
- struct rb_id_table *cc_tbl = RCLASS_CC_TBL(klass);
-
- if (cc_tbl) {
- rb_id_table_foreach_values(cc_tbl, cc_table_free_i, (void *)klass);
- rb_id_table_free(cc_tbl);
}
}
@@ -512,10 +578,6 @@ void
rb_imemo_free(VALUE obj)
{
switch (imemo_type(obj)) {
- case imemo_ast:
- rb_bug("imemo_ast is obsolete");
-
- break;
case imemo_callcache:
RB_DEBUG_COUNTER_INC(obj_imemo_callcache);
@@ -523,7 +585,6 @@ rb_imemo_free(VALUE obj)
case imemo_callinfo:{
const struct rb_callinfo *ci = ((const struct rb_callinfo *)obj);
- rb_vm_ci_free(ci);
if (ci->kwarg) {
((struct rb_callinfo_kwarg *)ci->kwarg)->references--;
if (ci->kwarg->references == 0) xfree((void *)ci->kwarg);
@@ -566,12 +627,9 @@ rb_imemo_free(VALUE obj)
RB_DEBUG_COUNTER_INC(obj_imemo_ment);
break;
- case imemo_parser_strterm:
- RB_DEBUG_COUNTER_INC(obj_imemo_parser_strterm);
-
- break;
case imemo_svar:
RB_DEBUG_COUNTER_INC(obj_imemo_svar);
+
break;
case imemo_throw_data:
RB_DEBUG_COUNTER_INC(obj_imemo_throw_data);
@@ -582,6 +640,10 @@ rb_imemo_free(VALUE obj)
RB_DEBUG_COUNTER_INC(obj_imemo_tmpbuf);
break;
+ case imemo_fields:
+ imemo_fields_free(IMEMO_OBJ_FIELDS(obj));
+ RB_DEBUG_COUNTER_INC(obj_imemo_fields);
+ break;
default:
rb_bug("unreachable");
}
diff --git a/include/ruby/assert.h b/include/ruby/assert.h
index e9edd9e640..acc5e5bbfc 100644
--- a/include/ruby/assert.h
+++ b/include/ruby/assert.h
@@ -298,17 +298,19 @@ RBIMPL_WARNING_IGNORED(-Wgnu-zero-variadic-macro-arguments)
* @copydetails #RUBY_ASSERT
*/
#if RUBY_DEBUG
-# define RBIMPL_ASSERT_OR_ASSUME(expr) RUBY_ASSERT_ALWAYS(expr)
+# define RBIMPL_ASSERT_OR_ASSUME RUBY_ASSERT_ALWAYS
+#elif ! defined(RBIMPL_VA_OPT_ARGS)
+# define RBIMPL_ASSERT_OR_ASSUME(expr) RBIMPL_ASSUME(expr)
#elif RBIMPL_COMPILER_BEFORE(Clang, 7, 0, 0)
# /* See commit 67d259c5dccd31fe49d417fec169977712ffdf10 */
-# define RBIMPL_ASSERT_OR_ASSUME(expr) RBIMPL_ASSERT_NOTHING
+# define RBIMPL_ASSERT_OR_ASSUME(...) RBIMPL_ASSERT_NOTHING
#elif defined(RUBY_ASSERT_NOASSUME)
# /* See commit d300a734414ef6de7e8eb563b7cc4389c455ed08 */
-# define RBIMPL_ASSERT_OR_ASSUME(expr) RBIMPL_ASSERT_NOTHING
+# define RBIMPL_ASSERT_OR_ASSUME(...) RBIMPL_ASSERT_NOTHING
#elif ! defined(RBIMPL_HAVE___ASSUME)
-# define RBIMPL_ASSERT_OR_ASSUME(expr) RBIMPL_ASSERT_NOTHING
+# define RBIMPL_ASSERT_OR_ASSUME(...) RBIMPL_ASSERT_NOTHING
#else
-# define RBIMPL_ASSERT_OR_ASSUME(expr) RBIMPL_ASSUME(expr)
+# define RBIMPL_ASSERT_OR_ASSUME(expr, ...) RBIMPL_ASSUME(expr)
#endif
#endif /* RUBY_ASSERT_H */
diff --git a/include/ruby/atomic.h b/include/ruby/atomic.h
index 043a6a9945..fcc48f532c 100644
--- a/include/ruby/atomic.h
+++ b/include/ruby/atomic.h
@@ -34,7 +34,7 @@
# include <sys/types.h> /* ssize_t */
#endif
-#if RBIMPL_COMPILER_SINCE(MSVC, 13, 0, 0)
+#if RBIMPL_COMPILER_IS(MSVC)
# pragma intrinsic(_InterlockedOr)
#elif defined(__sun) && defined(HAVE_ATOMIC_H)
# include <atomic.h>
@@ -72,13 +72,40 @@ typedef unsigned int rb_atomic_t;
#elif defined(HAVE_GCC_SYNC_BUILTINS)
typedef unsigned int rb_atomic_t;
#elif defined(_WIN32)
+# include <winsock2.h> // to prevent macro redefinitions
+# include <windows.h> // for `LONG` and `Interlocked` functions
typedef LONG rb_atomic_t;
#elif defined(__sun) && defined(HAVE_ATOMIC_H)
typedef unsigned int rb_atomic_t;
+#elif defined(HAVE_STDATOMIC_H)
+# include <stdatomic.h>
+typedef unsigned int rb_atomic_t;
#else
# error No atomic operation found
#endif
+/* Memory ordering constants */
+#if defined(HAVE_GCC_ATOMIC_BUILTINS)
+# define RBIMPL_ATOMIC_RELAXED __ATOMIC_RELAXED
+# define RBIMPL_ATOMIC_ACQUIRE __ATOMIC_ACQUIRE
+# define RBIMPL_ATOMIC_RELEASE __ATOMIC_RELEASE
+# define RBIMPL_ATOMIC_ACQ_REL __ATOMIC_ACQ_REL
+# define RBIMPL_ATOMIC_SEQ_CST __ATOMIC_SEQ_CST
+#elif defined(HAVE_STDATOMIC_H)
+# define RBIMPL_ATOMIC_RELAXED memory_order_relaxed
+# define RBIMPL_ATOMIC_ACQUIRE memory_order_acquire
+# define RBIMPL_ATOMIC_RELEASE memory_order_release
+# define RBIMPL_ATOMIC_ACQ_REL memory_order_acq_rel
+# define RBIMPL_ATOMIC_SEQ_CST memory_order_seq_cst
+#else
+/* Dummy values for unsupported platforms */
+# define RBIMPL_ATOMIC_RELAXED 0
+# define RBIMPL_ATOMIC_ACQUIRE 1
+# define RBIMPL_ATOMIC_RELEASE 2
+# define RBIMPL_ATOMIC_ACQ_REL 3
+# define RBIMPL_ATOMIC_SEQ_CST 4
+#endif
+
/**
* Atomically replaces the value pointed by `var` with the result of addition
* of `val` to the old value of `var`.
@@ -88,7 +115,7 @@ typedef unsigned int rb_atomic_t;
* @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))
+#define RUBY_ATOMIC_FETCH_ADD(var, val) rbimpl_atomic_fetch_add(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Atomically replaces the value pointed by `var` with the result of
@@ -99,7 +126,7 @@ typedef unsigned int rb_atomic_t;
* @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))
+#define RUBY_ATOMIC_FETCH_SUB(var, val) rbimpl_atomic_fetch_sub(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Atomically replaces the value pointed by `var` with the result of
@@ -111,7 +138,7 @@ typedef unsigned int rb_atomic_t;
* @post `var` holds `var | val`.
* @note For portability, this macro can return void.
*/
-#define RUBY_ATOMIC_OR(var, val) rbimpl_atomic_or(&(var), (val))
+#define RUBY_ATOMIC_OR(var, val) rbimpl_atomic_or(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Atomically replaces the value pointed by `var` with `val`. This is just an
@@ -122,7 +149,7 @@ typedef unsigned int rb_atomic_t;
* @return What was stored in `var` before the assignment.
* @post `var` holds `val`.
*/
-#define RUBY_ATOMIC_EXCHANGE(var, val) rbimpl_atomic_exchange(&(var), (val))
+#define RUBY_ATOMIC_EXCHANGE(var, val) rbimpl_atomic_exchange(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Atomic compare-and-swap. This stores `val` to `var` if and only if the
@@ -136,7 +163,7 @@ typedef unsigned int rb_atomic_t;
* @retval otherwise Something else is at `var`; not updated.
*/
#define RUBY_ATOMIC_CAS(var, oldval, newval) \
- rbimpl_atomic_cas(&(var), (oldval), (newval))
+ rbimpl_atomic_cas(&(var), (oldval), (newval), RBIMPL_ATOMIC_SEQ_CST, RBIMPL_ATOMIC_SEQ_CST)
/**
* Atomic load. This loads `var` with an atomic intrinsic and returns
@@ -145,7 +172,7 @@ typedef unsigned int rb_atomic_t;
* @param var A variable of ::rb_atomic_t
* @return What was stored in `var`j
*/
-#define RUBY_ATOMIC_LOAD(var) rbimpl_atomic_load(&(var))
+#define RUBY_ATOMIC_LOAD(var) rbimpl_atomic_load(&(var), RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_EXCHANGE, except for the return type.
@@ -155,7 +182,7 @@ typedef unsigned int rb_atomic_t;
* @return void
* @post `var` holds `val`.
*/
-#define RUBY_ATOMIC_SET(var, val) rbimpl_atomic_set(&(var), (val))
+#define RUBY_ATOMIC_SET(var, val) rbimpl_atomic_store(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_FETCH_ADD, except for the return type.
@@ -165,7 +192,7 @@ typedef unsigned int rb_atomic_t;
* @return void
* @post `var` holds `var + val`.
*/
-#define RUBY_ATOMIC_ADD(var, val) rbimpl_atomic_add(&(var), (val))
+#define RUBY_ATOMIC_ADD(var, val) rbimpl_atomic_add(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_FETCH_SUB, except for the return type.
@@ -175,7 +202,7 @@ typedef unsigned int rb_atomic_t;
* @return void
* @post `var` holds `var - val`.
*/
-#define RUBY_ATOMIC_SUB(var, val) rbimpl_atomic_sub(&(var), (val))
+#define RUBY_ATOMIC_SUB(var, val) rbimpl_atomic_sub(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Atomically increments the value pointed by `var`.
@@ -184,7 +211,7 @@ typedef unsigned int rb_atomic_t;
* @return void
* @post `var` holds `var + 1`.
*/
-#define RUBY_ATOMIC_INC(var) rbimpl_atomic_inc(&(var))
+#define RUBY_ATOMIC_INC(var) rbimpl_atomic_inc(&(var), RBIMPL_ATOMIC_SEQ_CST)
/**
* Atomically decrements the value pointed by `var`.
@@ -193,7 +220,19 @@ typedef unsigned int rb_atomic_t;
* @return void
* @post `var` holds `var - 1`.
*/
-#define RUBY_ATOMIC_DEC(var) rbimpl_atomic_dec(&(var))
+#define RUBY_ATOMIC_DEC(var) rbimpl_atomic_dec(&(var), RBIMPL_ATOMIC_SEQ_CST)
+
+/**
+ * Identical to #RUBY_ATOMIC_FETCH_ADD, except it expects its arguments to be `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 What was stored in `var` before the addition.
+ * @post `var` holds `var + val`.
+ */
+#define RUBY_ATOMIC_SIZE_FETCH_ADD(var, val) rbimpl_atomic_size_fetch_add(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_INC, except it expects its argument is `size_t`.
@@ -204,7 +243,7 @@ typedef unsigned int rb_atomic_t;
* @return void
* @post `var` holds `var + 1`.
*/
-#define RUBY_ATOMIC_SIZE_INC(var) rbimpl_atomic_size_inc(&(var))
+#define RUBY_ATOMIC_SIZE_INC(var) rbimpl_atomic_size_inc(&(var), RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_DEC, except it expects its argument is `size_t`.
@@ -215,7 +254,7 @@ typedef unsigned int rb_atomic_t;
* @return void
* @post `var` holds `var - 1`.
*/
-#define RUBY_ATOMIC_SIZE_DEC(var) rbimpl_atomic_size_dec(&(var))
+#define RUBY_ATOMIC_SIZE_DEC(var) rbimpl_atomic_size_dec(&(var), RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_EXCHANGE, except it expects its arguments are
@@ -229,7 +268,7 @@ typedef unsigned int rb_atomic_t;
* @post `var` holds `val`.
*/
#define RUBY_ATOMIC_SIZE_EXCHANGE(var, val) \
- rbimpl_atomic_size_exchange(&(var), (val))
+ rbimpl_atomic_size_exchange(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_CAS, except it expects its arguments are `size_t`.
@@ -243,7 +282,7 @@ typedef unsigned int rb_atomic_t;
* @retval otherwise Something else is at `var`; not updated.
*/
#define RUBY_ATOMIC_SIZE_CAS(var, oldval, newval) \
- rbimpl_atomic_size_cas(&(var), (oldval), (newval))
+ rbimpl_atomic_size_cas(&(var), (oldval), (newval), RBIMPL_ATOMIC_SEQ_CST, RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_ADD, except it expects its arguments are `size_t`.
@@ -255,7 +294,7 @@ typedef unsigned int rb_atomic_t;
* @return void
* @post `var` holds `var + val`.
*/
-#define RUBY_ATOMIC_SIZE_ADD(var, val) rbimpl_atomic_size_add(&(var), (val))
+#define RUBY_ATOMIC_SIZE_ADD(var, val) rbimpl_atomic_size_add(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_SUB, except it expects its arguments are `size_t`.
@@ -267,7 +306,7 @@ typedef unsigned int rb_atomic_t;
* @return void
* @post `var` holds `var - val`.
*/
-#define RUBY_ATOMIC_SIZE_SUB(var, val) rbimpl_atomic_size_sub(&(var), (val))
+#define RUBY_ATOMIC_SIZE_SUB(var, val) rbimpl_atomic_size_sub(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_EXCHANGE, except it expects its arguments are
@@ -286,7 +325,7 @@ typedef unsigned int rb_atomic_t;
* some pointers, most notably function pointers.
*/
#define RUBY_ATOMIC_PTR_EXCHANGE(var, val) \
- RBIMPL_CAST(rbimpl_atomic_ptr_exchange((void **)&(var), (void *)val))
+ RBIMPL_CAST(rbimpl_atomic_ptr_exchange((void **)&(var), (void *)val, RBIMPL_ATOMIC_SEQ_CST))
/**
* Identical to #RUBY_ATOMIC_LOAD, except it expects its arguments are `void*`.
@@ -297,7 +336,20 @@ typedef unsigned int rb_atomic_t;
* @return The value of `var` (without tearing)
*/
#define RUBY_ATOMIC_PTR_LOAD(var) \
- RBIMPL_CAST(rbimpl_atomic_ptr_load((void **)&var))
+ RBIMPL_CAST(rbimpl_atomic_ptr_load((void **)&var, RBIMPL_ATOMIC_SEQ_CST))
+
+/**
+* Identical to #RUBY_ATOMIC_SET, except it expects its arguments are
+* `void*`. 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 `void*`.
+* @param val Value to set.
+* @post `var` holds `val`.
+*/
+#define RUBY_ATOMIC_PTR_SET(var, val) \
+ rbimpl_atomic_ptr_store((volatile void **)&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_CAS, except it expects its arguments are `void*`.
@@ -311,7 +363,20 @@ typedef unsigned int rb_atomic_t;
* @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)))
+ RBIMPL_CAST(rbimpl_atomic_ptr_cas((void **)&(var), (void *)(oldval), (void *)(newval), RBIMPL_ATOMIC_SEQ_CST, RBIMPL_ATOMIC_SEQ_CST))
+
+/**
+ * Identical to #RUBY_ATOMIC_SET, 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.
+ * @post `var` holds `val`.
+ */
+#define RUBY_ATOMIC_VALUE_SET(var, val) \
+ rbimpl_atomic_value_store(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_EXCHANGE, except it expects its arguments are
@@ -325,7 +390,7 @@ typedef unsigned int rb_atomic_t;
* @post `var` holds `val`.
*/
#define RUBY_ATOMIC_VALUE_EXCHANGE(var, val) \
- rbimpl_atomic_value_exchange(&(var), (val))
+ rbimpl_atomic_value_exchange(&(var), (val), RBIMPL_ATOMIC_SEQ_CST)
/**
* Identical to #RUBY_ATOMIC_CAS, except it expects its arguments are ::VALUE.
@@ -339,19 +404,20 @@ typedef unsigned int rb_atomic_t;
* @retval otherwise Something else is at `var`; not updated.
*/
#define RUBY_ATOMIC_VALUE_CAS(var, oldval, newval) \
- rbimpl_atomic_value_cas(&(var), (oldval), (newval))
+ rbimpl_atomic_value_cas(&(var), (oldval), (newval), RBIMPL_ATOMIC_SEQ_CST, RBIMPL_ATOMIC_SEQ_CST)
/** @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)
+rbimpl_atomic_fetch_add(volatile rb_atomic_t *ptr, rb_atomic_t val, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
- return __atomic_fetch_add(ptr, val, __ATOMIC_SEQ_CST);
+ return __atomic_fetch_add(ptr, val, memory_order);
#elif defined(HAVE_GCC_SYNC_BUILTINS)
return __sync_fetch_and_add(ptr, val);
@@ -368,6 +434,47 @@ rbimpl_atomic_fetch_add(volatile rb_atomic_t *ptr, rb_atomic_t val)
RBIMPL_ASSERT_OR_ASSUME(val <= INT_MAX);
return atomic_add_int_nv(ptr, val) - val;
+#elif defined(HAVE_STDATOMIC_H)
+ return atomic_fetch_add_explicit((_Atomic volatile rb_atomic_t *)ptr, val, memory_order);
+
+#else
+# error Unsupported platform.
+#endif
+}
+
+/** @cond INTERNAL_MACRO */
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
+static inline size_t
+rbimpl_atomic_size_fetch_add(volatile size_t *ptr, size_t val, int memory_order)
+{
+ (void)memory_order;
+#if 0
+
+#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
+ return __atomic_fetch_add(ptr, val, memory_order);
+
+#elif defined(HAVE_GCC_SYNC_BUILTINS)
+ return __sync_fetch_and_add(ptr, val);
+
+#elif defined(_WIN32)
+ return 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);
+
+#elif defined(__sun) && defined(HAVE_ATOMIC_H)
+ 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_fetch_add(tmp, val, memory_order);
+
+#elif defined(HAVE_STDATOMIC_H)
+ return atomic_fetch_add_explicit((_Atomic volatile size_t *)ptr, val, memory_order);
+
#else
# error Unsupported platform.
#endif
@@ -377,8 +484,9 @@ 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)
+rbimpl_atomic_add(volatile rb_atomic_t *ptr, rb_atomic_t val, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
@@ -387,7 +495,7 @@ rbimpl_atomic_add(volatile rb_atomic_t *ptr, rb_atomic_t val)
* return value is not used, then compiles it into single `LOCK ADD`
* instruction.
*/
- __atomic_add_fetch(ptr, val, __ATOMIC_SEQ_CST);
+ __atomic_add_fetch(ptr, val, memory_order);
#elif defined(HAVE_GCC_SYNC_BUILTINS)
__sync_add_and_fetch(ptr, val);
@@ -405,6 +513,9 @@ rbimpl_atomic_add(volatile rb_atomic_t *ptr, rb_atomic_t val)
RBIMPL_ASSERT_OR_ASSUME(val <= INT_MAX);
atomic_add_int(ptr, val);
+#elif defined(HAVE_STDATOMIC_H)
+ atomic_fetch_add_explicit((_Atomic volatile rb_atomic_t *)ptr, val, memory_order);
+
#else
# error Unsupported platform.
#endif
@@ -414,12 +525,13 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline void
-rbimpl_atomic_size_add(volatile size_t *ptr, size_t val)
+rbimpl_atomic_size_add(volatile size_t *ptr, size_t val, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
- __atomic_add_fetch(ptr, val, __ATOMIC_SEQ_CST);
+ __atomic_add_fetch(ptr, val, memory_order);
#elif defined(HAVE_GCC_SYNC_BUILTINS)
__sync_add_and_fetch(ptr, val);
@@ -433,12 +545,17 @@ rbimpl_atomic_size_add(volatile size_t *ptr, size_t val)
RBIMPL_ASSERT_OR_ASSUME(val <= LONG_MAX);
atomic_add_long(ptr, val);
-#else
+#elif defined(_WIN32) || (defined(__sun) && defined(HAVE_ATOMIC_H))
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);
+ rbimpl_atomic_add(tmp, val, memory_order);
+
+#elif defined(HAVE_STDATOMIC_H)
+ atomic_fetch_add_explicit((_Atomic volatile size_t *)ptr, val, memory_order);
+#else
+# error Unsupported platform.
#endif
}
@@ -446,12 +563,13 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline void
-rbimpl_atomic_inc(volatile rb_atomic_t *ptr)
+rbimpl_atomic_inc(volatile rb_atomic_t *ptr, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS)
- rbimpl_atomic_add(ptr, 1);
+ rbimpl_atomic_add(ptr, 1, memory_order);
#elif defined(_WIN32)
InterlockedIncrement(ptr);
@@ -459,9 +577,11 @@ rbimpl_atomic_inc(volatile rb_atomic_t *ptr)
#elif defined(__sun) && defined(HAVE_ATOMIC_H)
atomic_inc_uint(ptr);
-#else
- rbimpl_atomic_add(ptr, 1);
+#elif defined(HAVE_STDATOMIC_H)
+ rbimpl_atomic_add(ptr, 1, memory_order);
+#else
+# error Unsupported platform.
#endif
}
@@ -469,12 +589,13 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline void
-rbimpl_atomic_size_inc(volatile size_t *ptr)
+rbimpl_atomic_size_inc(volatile size_t *ptr, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS)
- rbimpl_atomic_size_add(ptr, 1);
+ rbimpl_atomic_size_add(ptr, 1, memory_order);
#elif defined(_WIN64)
InterlockedIncrement64(ptr);
@@ -482,11 +603,16 @@ rbimpl_atomic_size_inc(volatile size_t *ptr)
#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx))
atomic_inc_ulong(ptr);
-#else
+#elif defined(_WIN32) || (defined(__sun) && defined(HAVE_ATOMIC_H))
RBIMPL_STATIC_ASSERT(size_of_size_t, sizeof *ptr == sizeof(rb_atomic_t));
- rbimpl_atomic_size_add(ptr, 1);
+ rbimpl_atomic_size_add(ptr, 1, memory_order);
+#elif defined(HAVE_STDATOMIC_H)
+ rbimpl_atomic_size_add(ptr, 1, memory_order);
+
+#else
+# error Unsupported platform.
#endif
}
@@ -494,12 +620,13 @@ 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)
+rbimpl_atomic_fetch_sub(volatile rb_atomic_t *ptr, rb_atomic_t val, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
- return __atomic_fetch_sub(ptr, val, __ATOMIC_SEQ_CST);
+ return __atomic_fetch_sub(ptr, val, memory_order);
#elif defined(HAVE_GCC_SYNC_BUILTINS)
return __sync_fetch_and_sub(ptr, val);
@@ -514,6 +641,9 @@ rbimpl_atomic_fetch_sub(volatile rb_atomic_t *ptr, rb_atomic_t val)
RBIMPL_ASSERT_OR_ASSUME(val <= INT_MAX);
return atomic_add_int_nv(ptr, neg * val) + val;
+#elif defined(HAVE_STDATOMIC_H)
+ return atomic_fetch_sub_explicit((_Atomic volatile rb_atomic_t *)ptr, val, memory_order);
+
#else
# error Unsupported platform.
#endif
@@ -523,12 +653,13 @@ 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)
+rbimpl_atomic_sub(volatile rb_atomic_t *ptr, rb_atomic_t val, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
- __atomic_sub_fetch(ptr, val, __ATOMIC_SEQ_CST);
+ __atomic_sub_fetch(ptr, val, memory_order);
#elif defined(HAVE_GCC_SYNC_BUILTINS)
__sync_sub_and_fetch(ptr, val);
@@ -541,6 +672,9 @@ rbimpl_atomic_sub(volatile rb_atomic_t *ptr, rb_atomic_t val)
RBIMPL_ASSERT_OR_ASSUME(val <= INT_MAX);
atomic_add_int(ptr, neg * val);
+#elif defined(HAVE_STDATOMIC_H)
+ atomic_fetch_sub_explicit((_Atomic volatile rb_atomic_t *)ptr, val, memory_order);
+
#else
# error Unsupported platform.
#endif
@@ -550,12 +684,13 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline void
-rbimpl_atomic_size_sub(volatile size_t *ptr, size_t val)
+rbimpl_atomic_size_sub(volatile size_t *ptr, size_t val, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
- __atomic_sub_fetch(ptr, val, __ATOMIC_SEQ_CST);
+ __atomic_sub_fetch(ptr, val, memory_order);
#elif defined(HAVE_GCC_SYNC_BUILTINS)
__sync_sub_and_fetch(ptr, val);
@@ -569,12 +704,17 @@ rbimpl_atomic_size_sub(volatile size_t *ptr, size_t val)
RBIMPL_ASSERT_OR_ASSUME(val <= LONG_MAX);
atomic_add_long(ptr, neg * val);
-#else
+#elif defined(_WIN32) || (defined(__sun) && defined(HAVE_ATOMIC_H))
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);
+ rbimpl_atomic_sub(tmp, val, memory_order);
+
+#elif defined(HAVE_STDATOMIC_H)
+ atomic_fetch_sub_explicit((_Atomic volatile size_t *)ptr, val, memory_order);
+#else
+# error Unsupported platform.
#endif
}
@@ -582,12 +722,13 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline void
-rbimpl_atomic_dec(volatile rb_atomic_t *ptr)
+rbimpl_atomic_dec(volatile rb_atomic_t *ptr, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS)
- rbimpl_atomic_sub(ptr, 1);
+ rbimpl_atomic_sub(ptr, 1, memory_order);
#elif defined(_WIN32)
InterlockedDecrement(ptr);
@@ -595,9 +736,11 @@ rbimpl_atomic_dec(volatile rb_atomic_t *ptr)
#elif defined(__sun) && defined(HAVE_ATOMIC_H)
atomic_dec_uint(ptr);
-#else
- rbimpl_atomic_sub(ptr, 1);
+#elif defined(HAVE_STDATOMIC_H)
+ rbimpl_atomic_sub(ptr, 1, memory_order);
+#else
+# error Unsupported platform.
#endif
}
@@ -605,12 +748,13 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline void
-rbimpl_atomic_size_dec(volatile size_t *ptr)
+rbimpl_atomic_size_dec(volatile size_t *ptr, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS) || defined(HAVE_GCC_SYNC_BUILTINS)
- rbimpl_atomic_size_sub(ptr, 1);
+ rbimpl_atomic_size_sub(ptr, 1, memory_order);
#elif defined(_WIN64)
InterlockedDecrement64(ptr);
@@ -618,11 +762,16 @@ rbimpl_atomic_size_dec(volatile size_t *ptr)
#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx))
atomic_dec_ulong(ptr);
-#else
+#elif defined(_WIN32) || (defined(__sun) && defined(HAVE_ATOMIC_H))
RBIMPL_STATIC_ASSERT(size_of_size_t, sizeof *ptr == sizeof(rb_atomic_t));
- rbimpl_atomic_size_sub(ptr, 1);
+ rbimpl_atomic_size_sub(ptr, 1, memory_order);
+
+#elif defined(HAVE_STDATOMIC_H)
+ rbimpl_atomic_size_sub(ptr, 1, memory_order);
+#else
+# error Unsupported platform.
#endif
}
@@ -630,59 +779,42 @@ 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)
+rbimpl_atomic_or(volatile rb_atomic_t *ptr, rb_atomic_t val, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
- __atomic_or_fetch(ptr, val, __ATOMIC_SEQ_CST);
+ __atomic_or_fetch(ptr, val, memory_order);
#elif defined(HAVE_GCC_SYNC_BUILTINS)
__sync_or_and_fetch(ptr, val);
-#elif RBIMPL_COMPILER_SINCE(MSVC, 13, 0, 0)
+#elif RBIMPL_COMPILER_IS(MSVC)
_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);
+#elif !defined(_WIN32) && defined(HAVE_STDATOMIC_H)
+ atomic_fetch_or_explicit((_Atomic volatile rb_atomic_t *)ptr, val, memory_order);
+
#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)
+rbimpl_atomic_exchange(volatile rb_atomic_t *ptr, rb_atomic_t val, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
- return __atomic_exchange_n(ptr, val, __ATOMIC_SEQ_CST);
+ return __atomic_exchange_n(ptr, val, memory_order);
#elif defined(HAVE_GCC_SYNC_BUILTINS)
return __sync_lock_test_and_set(ptr, val);
@@ -693,6 +825,9 @@ rbimpl_atomic_exchange(volatile rb_atomic_t *ptr, rb_atomic_t val)
#elif defined(__sun) && defined(HAVE_ATOMIC_H)
return atomic_swap_uint(ptr, val);
+#elif defined(HAVE_STDATOMIC_H)
+ return atomic_exchange_explicit((_Atomic volatile rb_atomic_t *)ptr, val, memory_order);
+
#else
# error Unsupported platform.
#endif
@@ -702,12 +837,13 @@ 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)
+rbimpl_atomic_size_exchange(volatile size_t *ptr, size_t val, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
- return __atomic_exchange_n(ptr, val, __ATOMIC_SEQ_CST);
+ return __atomic_exchange_n(ptr, val, memory_order);
#elif defined(HAVE_GCC_SYNC_BUILTINS)
return __sync_lock_test_and_set(ptr, val);
@@ -718,13 +854,36 @@ rbimpl_atomic_size_exchange(volatile size_t *ptr, size_t val)
#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx))
return atomic_swap_ulong(ptr, val);
-#else
+#elif defined(_WIN32) || (defined(__sun) && defined(HAVE_ATOMIC_H))
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);
+ const rb_atomic_t ret = rbimpl_atomic_exchange(tmp, val, memory_order);
return RBIMPL_CAST((size_t)ret);
+#elif defined(HAVE_STDATOMIC_H)
+ return atomic_exchange_explicit((_Atomic volatile size_t *)ptr, val, memory_order);
+
+#else
+# error Unsupported platform.
+#endif
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
+static inline void
+rbimpl_atomic_size_store(volatile size_t *ptr, size_t val, int memory_order)
+{
+ (void)memory_order;
+#if 0
+
+#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
+ __atomic_store_n(ptr, val, memory_order);
+
+#else
+ rbimpl_atomic_size_exchange(ptr, val, memory_order);
+
#endif
}
@@ -732,8 +891,9 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline void *
-rbimpl_atomic_ptr_exchange(void *volatile *ptr, const void *val)
+rbimpl_atomic_ptr_exchange(void *volatile *ptr, const void *val, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(InterlockedExchangePointer)
@@ -750,7 +910,7 @@ rbimpl_atomic_ptr_exchange(void *volatile *ptr, const void *val)
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);
+ const size_t sret = rbimpl_atomic_size_exchange(sptr, sval, memory_order);
return RBIMPL_CAST((void *)sret);
#endif
@@ -759,29 +919,56 @@ rbimpl_atomic_ptr_exchange(void *volatile *ptr, const void *val)
RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
+static inline void
+rbimpl_atomic_ptr_store(volatile void **ptr, void *val, int memory_order)
+{
+ 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);
+ rbimpl_atomic_size_store(sptr, sval, memory_order);
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
static inline VALUE
-rbimpl_atomic_value_exchange(volatile VALUE *ptr, VALUE val)
+rbimpl_atomic_value_exchange(volatile VALUE *ptr, VALUE val, int memory_order)
{
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);
+ const size_t sret = rbimpl_atomic_size_exchange(sptr, sval, memory_order);
return RBIMPL_CAST((VALUE)sret);
}
RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
+static inline void
+rbimpl_atomic_value_store(volatile VALUE *ptr, VALUE val, int memory_order)
+{
+ 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);
+ rbimpl_atomic_size_store(sptr, sval, memory_order);
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
static inline rb_atomic_t
-rbimpl_atomic_load(volatile rb_atomic_t *ptr)
+rbimpl_atomic_load(volatile rb_atomic_t *ptr, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
- return __atomic_load_n(ptr, __ATOMIC_SEQ_CST);
+ return __atomic_load_n(ptr, memory_order);
#else
- return rbimpl_atomic_fetch_add(ptr, 0);
+ return rbimpl_atomic_fetch_add(ptr, 0, memory_order);
#endif
}
@@ -789,16 +976,17 @@ 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)
+rbimpl_atomic_store(volatile rb_atomic_t *ptr, rb_atomic_t val, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
- __atomic_store_n(ptr, val, __ATOMIC_SEQ_CST);
+ __atomic_store_n(ptr, val, memory_order);
#else
/* Maybe std::atomic<rb_atomic_t>::store can be faster? */
- rbimpl_atomic_exchange(ptr, val);
+ rbimpl_atomic_exchange(ptr, val, memory_order);
#endif
}
@@ -807,56 +995,49 @@ 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)
+rbimpl_atomic_cas(volatile rb_atomic_t *ptr, rb_atomic_t oldval, rb_atomic_t newval, int success_memorder, int failure_memorder)
{
+ (void)success_memorder;
+ (void)failure_memorder;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
__atomic_compare_exchange_n(
- ptr, &oldval, newval, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+ ptr, &oldval, newval, 0, success_memorder, failure_memorder);
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)
+#elif RBIMPL_COMPILER_IS(MSVC)
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);
+#elif defined(HAVE_STDATOMIC_H)
+ atomic_compare_exchange_strong_explicit(
+ (_Atomic volatile rb_atomic_t *)ptr, &oldval, newval, success_memorder, failure_memorder);
+ return oldval;
+
#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)
+rbimpl_atomic_size_cas(volatile size_t *ptr, size_t oldval, size_t newval, int success_memorder, int failure_memorder)
{
+ (void)success_memorder;
+ (void)failure_memorder;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
__atomic_compare_exchange_n(
- ptr, &oldval, newval, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
+ ptr, &oldval, newval, 0, success_memorder, failure_memorder);
return oldval;
#elif defined(HAVE_GCC_SYNC_BUILTINS)
@@ -868,12 +1049,19 @@ rbimpl_atomic_size_cas(volatile size_t *ptr, size_t oldval, size_t newval)
#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx))
return atomic_cas_ulong(ptr, oldval, newval);
-#else
+#elif defined(_WIN32) || (defined(__sun) && defined(HAVE_ATOMIC_H))
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);
+ return rbimpl_atomic_cas(tmp, oldval, newval, success_memorder, failure_memorder);
+
+#elif defined(HAVE_STDATOMIC_H)
+ atomic_compare_exchange_strong_explicit(
+ (_Atomic volatile size_t *)ptr, &oldval, newval, success_memorder, failure_memorder);
+ return oldval;
+#else
+# error Unsupported platform.
#endif
}
@@ -881,8 +1069,10 @@ 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)
+rbimpl_atomic_ptr_cas(void **ptr, const void *oldval, const void *newval, int success_memorder, int failure_memorder)
{
+ (void)success_memorder;
+ (void)failure_memorder;
#if 0
#elif defined(InterlockedExchangePointer)
@@ -905,7 +1095,7 @@ rbimpl_atomic_ptr_cas(void **ptr, const void *oldval, const void *newval)
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);
+ const size_t sret = rbimpl_atomic_size_cas(sptr, sold, snew, success_memorder, failure_memorder);
return RBIMPL_CAST((void *)sret);
#endif
@@ -915,15 +1105,16 @@ RBIMPL_ATTR_ARTIFICIAL()
RBIMPL_ATTR_NOALIAS()
RBIMPL_ATTR_NONNULL((1))
static inline void *
-rbimpl_atomic_ptr_load(void **ptr)
+rbimpl_atomic_ptr_load(void **ptr, int memory_order)
{
+ (void)memory_order;
#if 0
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
- return __atomic_load_n(ptr, __ATOMIC_SEQ_CST);
+ return __atomic_load_n(ptr, memory_order);
#else
void *val = *ptr;
- return rbimpl_atomic_ptr_cas(ptr, val, val);
+ return rbimpl_atomic_ptr_cas(ptr, val, val, memory_order, memory_order);
#endif
}
@@ -931,14 +1122,23 @@ 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_atomic_value_load(volatile VALUE *ptr, int memory_order)
+{
+ return RBIMPL_CAST((VALUE)rbimpl_atomic_ptr_load((void **)ptr, memory_order));
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NOALIAS()
+RBIMPL_ATTR_NONNULL((1))
+static inline VALUE
+rbimpl_atomic_value_cas(volatile VALUE *ptr, VALUE oldval, VALUE newval, int success_memorder, int failure_memorder)
{
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);
+ const size_t sret = rbimpl_atomic_size_cas(sptr, sold, snew, success_memorder, failure_memorder);
return RBIMPL_CAST((VALUE)sret);
}
/** @endcond */
diff --git a/include/ruby/backward.h b/include/ruby/backward.h
index f804c2c36e..6726102158 100644
--- a/include/ruby/backward.h
+++ b/include/ruby/backward.h
@@ -11,12 +11,6 @@
#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"))
-#define RBIMPL_ATTR_DEPRECATED_INTERNAL_ONLY() RBIMPL_ATTR_DEPRECATED(("only for internal use"))
-
-RBIMPL_ATTR_DEPRECATED_INTERNAL_ONLY() void rb_clear_constant_cache(void);
-
/* from version.c */
#if defined(RUBY_SHOW_COPYRIGHT_TO_DIE) && !!(RUBY_SHOW_COPYRIGHT_TO_DIE+0)
# error RUBY_SHOW_COPYRIGHT_TO_DIE is deprecated
diff --git a/include/ruby/backward/2/rmodule.h b/include/ruby/backward/2/rmodule.h
index 53b37831c0..76c0936462 100644
--- a/include/ruby/backward/2/rmodule.h
+++ b/include/ruby/backward/2/rmodule.h
@@ -23,7 +23,7 @@
* 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_IV_TBL(m) RCLASS_FIELDS(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)
diff --git a/include/ruby/backward/cxxanyargs.hpp b/include/ruby/backward/cxxanyargs.hpp
index 2414b7ae6d..0ca2745c20 100644
--- a/include/ruby/backward/cxxanyargs.hpp
+++ b/include/ruby/backward/cxxanyargs.hpp
@@ -190,33 +190,6 @@ rb_define_hooked_variable(const char *q, VALUE *w, std::nullptr_t e, void_type *
/// @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.
-/// @param[in] w Passed to `q`.
-/// @param[in] e What is to be yielded.
-/// @param[in] r Passed to `e`.
-/// @return The return value of `q`.
-/// @note `e` can be nullptr.
-/// @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(onearg_type *q, VALUE w, type *e, VALUE r)
-{
- rb_block_call_func_t t = reinterpret_cast<rb_block_call_func_t>(e);
- 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.
/// @param[in] q The self.
@@ -537,9 +510,7 @@ struct driver {
* 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
diff --git a/include/ruby/debug.h b/include/ruby/debug.h
index f7c8e6ca8d..547d5d94c4 100644
--- a/include/ruby/debug.h
+++ b/include/ruby/debug.h
@@ -297,7 +297,7 @@ VALUE rb_debug_inspector_frame_depth(const rb_debug_inspector_t *dc, long index)
#define RB_DEBUG_INSPECTOR_FRAME_DEPTH(dc, index) rb_debug_inspector_frame_depth(dc, index)
/**
- * Return current frmae depth.
+ * Return current frame depth.
*
* @retval The depth of the current frame in Integer.
*/
@@ -479,7 +479,7 @@ RBIMPL_ATTR_RETURNS_NONNULL()
*/
rb_trace_arg_t *rb_tracearg_from_tracepoint(VALUE tpval);
-RBIMPL_ATTR_NONNULL(())
+RBIMPL_ATTR_NONNULL((1))
/**
* Queries the event of the passed trace.
*
@@ -488,7 +488,7 @@ RBIMPL_ATTR_NONNULL(())
*/
rb_event_flag_t rb_tracearg_event_flag(rb_trace_arg_t *trace_arg);
-RBIMPL_ATTR_NONNULL(())
+RBIMPL_ATTR_NONNULL((1))
/**
* Identical to rb_tracearg_event_flag(), except it returns the name of the
* event in Ruby's symbol.
@@ -498,7 +498,7 @@ RBIMPL_ATTR_NONNULL(())
*/
VALUE rb_tracearg_event(rb_trace_arg_t *trace_arg);
-RBIMPL_ATTR_NONNULL(())
+RBIMPL_ATTR_NONNULL((1))
/**
* Queries the line of the point where the trace is at.
*
@@ -508,7 +508,7 @@ RBIMPL_ATTR_NONNULL(())
*/
VALUE rb_tracearg_lineno(rb_trace_arg_t *trace_arg);
-RBIMPL_ATTR_NONNULL(())
+RBIMPL_ATTR_NONNULL((1))
/**
* Queries the file name of the point where the trace is at.
*
@@ -518,7 +518,19 @@ RBIMPL_ATTR_NONNULL(())
*/
VALUE rb_tracearg_path(rb_trace_arg_t *trace_arg);
-RBIMPL_ATTR_NONNULL(())
+RBIMPL_ATTR_NONNULL((1))
+/**
+ *
+ * Queries the parameters passed on a call or return event.
+ *
+ * @param[in] trace_arg A trace instance
+ * @exception rb_eRuntimeError The tracing event does not support querying parameters.
+ * @return Array of parameters in the format of `Method#parameters`.
+ *
+ */
+VALUE rb_tracearg_parameters(rb_trace_arg_t *trace_arg);
+
+RBIMPL_ATTR_NONNULL((1))
/**
* Queries the method name of the point where the trace is at.
*
@@ -528,7 +540,7 @@ RBIMPL_ATTR_NONNULL(())
*/
VALUE rb_tracearg_method_id(rb_trace_arg_t *trace_arg);
-RBIMPL_ATTR_NONNULL(())
+RBIMPL_ATTR_NONNULL((1))
/**
* Identical to rb_tracearg_method_id(), except it returns callee id like
* rb_frame_callee().
@@ -539,7 +551,7 @@ RBIMPL_ATTR_NONNULL(())
*/
VALUE rb_tracearg_callee_id(rb_trace_arg_t *trace_arg);
-RBIMPL_ATTR_NONNULL(())
+RBIMPL_ATTR_NONNULL((1))
/**
* 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
@@ -551,7 +563,7 @@ RBIMPL_ATTR_NONNULL(())
*/
VALUE rb_tracearg_defined_class(rb_trace_arg_t *trace_arg);
-RBIMPL_ATTR_NONNULL(())
+RBIMPL_ATTR_NONNULL((1))
/**
* Creates a binding object of the point where the trace is at.
*
@@ -566,7 +578,7 @@ RBIMPL_ATTR_NONNULL(())
*/
VALUE rb_tracearg_binding(rb_trace_arg_t *trace_arg);
-RBIMPL_ATTR_NONNULL(())
+RBIMPL_ATTR_NONNULL((1))
/**
* Queries the receiver of the point trace is at.
*
@@ -575,7 +587,7 @@ RBIMPL_ATTR_NONNULL(())
*/
VALUE rb_tracearg_self(rb_trace_arg_t *trace_arg);
-RBIMPL_ATTR_NONNULL(())
+RBIMPL_ATTR_NONNULL((1))
/**
* Queries the return value that the trace represents.
*
@@ -585,7 +597,7 @@ RBIMPL_ATTR_NONNULL(())
*/
VALUE rb_tracearg_return_value(rb_trace_arg_t *trace_arg);
-RBIMPL_ATTR_NONNULL(())
+RBIMPL_ATTR_NONNULL((1))
/**
* Queries the raised exception that the trace represents.
*
@@ -595,7 +607,33 @@ RBIMPL_ATTR_NONNULL(())
*/
VALUE rb_tracearg_raised_exception(rb_trace_arg_t *trace_arg);
-RBIMPL_ATTR_NONNULL(())
+RBIMPL_ATTR_NONNULL((1))
+/**
+ * Queries the compiled source code of the 'script_compiled' event.
+ * If loaded from a file, it will return nil.
+ *
+ * @param[in] trace_arg A trace instance
+ * @exception rb_eRuntimeError The tracing event is not 'script_compiled'.
+ * @retval RUBY_Qnil The script was loaded from a file.
+ * @retval otherwise The compiled source code.
+ *
+ */
+VALUE rb_tracearg_eval_script(rb_trace_arg_t *trace_arg);
+
+RBIMPL_ATTR_NONNULL((1))
+/**
+ *
+ * Queries the compiled instruction sequence on a 'script_compiled' event.
+ * Note that this method is MRI specific.
+ *
+ * @param[in] trace_arg A trace instance
+ * @exception rb_eRuntimeError The tracing event is not 'script_compiled'.
+ * @return The `RubyVM::InstructionSequence` object representing the instruction sequence.
+ *
+ */
+VALUE rb_tracearg_instruction_sequence(rb_trace_arg_t *trace_arg);
+
+RBIMPL_ATTR_NONNULL((1))
/**
* Queries the allocated/deallocated object that the trace represents.
*
diff --git a/include/ruby/fiber/scheduler.h b/include/ruby/fiber/scheduler.h
index 8f3d383330..4d764f68ae 100644
--- a/include/ruby/fiber/scheduler.h
+++ b/include/ruby/fiber/scheduler.h
@@ -23,9 +23,11 @@
RBIMPL_SYMBOL_EXPORT_BEGIN()
-#define RUBY_FIBER_SCHEDULER_VERSION 2
+// Version 3: Adds support for `fiber_interrupt`.
+#define RUBY_FIBER_SCHEDULER_VERSION 3
struct timeval;
+struct rb_thread_struct;
/**
* Wrap a `ssize_t` and `int errno` into a single `VALUE`. This interface should
@@ -117,7 +119,7 @@ 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.
+ * passed thread value instead of the implicit current one.
*
* @param[in] thread Target thread.
* @exception rb_eTypeError `thread` is not a thread.
@@ -127,6 +129,17 @@ VALUE rb_fiber_scheduler_current(void);
VALUE rb_fiber_scheduler_current_for_thread(VALUE thread);
/**
+ * Identical to rb_fiber_scheduler_current_for_thread(), except it expects
+ * a threadptr instead of a thread value.
+ *
+ * @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_threadptr(struct rb_thread_struct *thread);
+
+/**
* Converts the passed timeout to an expression that rb_fiber_scheduler_block()
* etc. expects.
*
@@ -166,6 +179,14 @@ VALUE rb_fiber_scheduler_kernel_sleep(VALUE scheduler, VALUE duration);
*/
VALUE rb_fiber_scheduler_kernel_sleepv(VALUE scheduler, int argc, VALUE * argv);
+/**
+ * Yield to the scheduler, to be resumed on the next scheduling cycle.
+ *
+ * @param[in] scheduler Target scheduler.
+ * @return What `scheduler.yield` returns.
+ */
+VALUE rb_fiber_scheduler_yield(VALUE scheduler);
+
/* Description TBW */
#if 0
VALUE rb_fiber_scheduler_timeout_after(VALUE scheduler, VALUE timeout, VALUE exception, VALUE message);
@@ -199,6 +220,8 @@ VALUE rb_fiber_scheduler_block(VALUE scheduler, VALUE blocker, VALUE timeout);
/**
* Wakes up a fiber previously blocked using rb_fiber_scheduler_block().
*
+ * This function may be called from a different thread.
+ *
* @param[in] scheduler Target scheduler.
* @param[in] blocker What was awaited for.
* @param[in] fiber What to unblock.
@@ -391,9 +414,89 @@ VALUE rb_fiber_scheduler_io_close(VALUE scheduler, VALUE io);
*/
VALUE rb_fiber_scheduler_address_resolve(VALUE scheduler, VALUE hostname);
+// The state of the blocking operation execution.
+struct rb_fiber_scheduler_blocking_operation_state {
+ void *result;
+ int saved_errno;
+};
+
+// The opaque handle for the blocking operation.
+typedef struct rb_fiber_scheduler_blocking_operation rb_fiber_scheduler_blocking_operation_t;
+
+/**
+ * Extract the blocking operation handle from a BlockingOperationRuby object.
+ *
+ * This function safely extracts the opaque handle from a BlockingOperation VALUE
+ * while holding the GVL. The returned pointer can be passed to worker threads
+ * and used with rb_fiber_scheduler_blocking_operation_execute.
+ *
+ * @param[in] self The BlockingOperation VALUE to extract from
+ * @return The opaque struct pointer on success, NULL on error
+ * @note Experimental.
+ */
+rb_fiber_scheduler_blocking_operation_t *rb_fiber_scheduler_blocking_operation_extract(VALUE self);
+
+/**
+ * Execute blocking operation from handle (GVL not required).
+ *
+ * This function executes a blocking operation using the opaque handle
+ * obtained from rb_fiber_scheduler_blocking_operation_extract.
+ * It can be called from native threads without holding the GVL.
+ *
+ * @param[in] blocking_operation The opaque handle.
+ * @return 0 on success, -1 on error.
+ * @note Experimental. Can be called from any thread without holding the GVL
+ */
+int rb_fiber_scheduler_blocking_operation_execute(rb_fiber_scheduler_blocking_operation_t *blocking_operation);
+
+/**
+ * Cancel a blocking operation.
+ *
+ * This function cancels a blocking operation. If the operation is queued,
+ * it just marks it as cancelled. If it's executing, it marks it as cancelled
+ * and calls the unblock function to interrupt the operation.
+ *
+ * @param blocking_operation The opaque struct pointer
+ * @return 1 if unblock function was called, 0 if just marked cancelled, -1 on error
+ * @note Experimental.
+ */
+int rb_fiber_scheduler_blocking_operation_cancel(rb_fiber_scheduler_blocking_operation_t *blocking_operation);
+
+/**
+ * Defer the execution of the passed function to the scheduler.
+ *
+ * @param[in] scheduler Target scheduler.
+ * @param[in] function The function to run.
+ * @param[in] data The data to pass to the function.
+ * @param[in] unblock_function The unblock function to use to interrupt the operation.
+ * @param[in] data2 The data to pass to the unblock function.
+ * @param[in] flags Flags passed to `rb_nogvl`.
+ * @param[out] state The result and errno of the operation.
+ * @retval RUBY_Qundef `scheduler` doesn't have `#blocking_operation_wait`.
+ * @return otherwise What `scheduler.blocking_operation_wait` returns.
+ */
+VALUE rb_fiber_scheduler_blocking_operation_wait(VALUE scheduler, void* (*function)(void *), void *data, rb_unblock_function_t *unblock_function, void *data2, int flags, struct rb_fiber_scheduler_blocking_operation_state *state);
+
+/**
+ * Interrupt a fiber by raising an exception. You can construct an exception using `rb_make_exception`.
+ *
+ * This hook may be invoked by a different thread.
+ *
+ * @param[in] scheduler Target scheduler.
+ * @param[in] fiber The fiber to interrupt.
+ * @param[in] exception The exception to raise in the fiber.
+ * @return What `scheduler.fiber_interrupt` returns.
+ */
+VALUE rb_fiber_scheduler_fiber_interrupt(VALUE scheduler, VALUE fiber, VALUE exception);
+
/**
* Create and schedule a non-blocking fiber.
*
+ * @param[in] scheduler Target scheduler.
+ * @param[in] argc Number of arguments in argv.
+ * @param[in] argv Array of arguments to pass to the fiber.
+ * @param[in] kw_splat Whether to expand last argument as keywords.
+ * @return The created and scheduled fiber.
*/
VALUE rb_fiber_scheduler_fiber(VALUE scheduler, int argc, VALUE *argv, int kw_splat);
diff --git a/include/ruby/intern.h b/include/ruby/intern.h
index 48e4cd546e..8718169ce2 100644
--- a/include/ruby/intern.h
+++ b/include/ruby/intern.h
@@ -51,6 +51,7 @@
#include "ruby/internal/intern/re.h"
#include "ruby/internal/intern/ruby.h"
#include "ruby/internal/intern/select.h"
+#include "ruby/internal/intern/set.h"
#include "ruby/internal/intern/signal.h"
#include "ruby/internal/intern/sprintf.h"
#include "ruby/internal/intern/string.h"
diff --git a/include/ruby/internal/abi.h b/include/ruby/internal/abi.h
index e735a67564..e6d1fa7e8f 100644
--- a/include/ruby/internal/abi.h
+++ b/include/ruby/internal/abi.h
@@ -24,7 +24,7 @@
* In released versions of Ruby, this number is not defined since teeny
* versions of Ruby should guarantee ABI compatibility.
*/
-#define RUBY_ABI_VERSION 0
+#define RUBY_ABI_VERSION 1
/* Windows does not support weak symbols so ruby_abi_version will not exist
* in the shared library. */
diff --git a/include/ruby/internal/anyargs.h b/include/ruby/internal/anyargs.h
index e3e1b6166d..e4c6d155cc 100644
--- a/include/ruby/internal/anyargs.h
+++ b/include/ruby/internal/anyargs.h
@@ -84,12 +84,15 @@
#elif defined(_WIN32) || defined(__CYGWIN__)
# /* Skip due to [Bug #16134] */
+# define RBIMPL_CAST_FN_PTR 1
#elif ! RBIMPL_HAS_ATTRIBUTE(transparent_union)
# /* :TODO: improve here, please find a way to support. */
+# define RBIMPL_CAST_FN_PTR 1
#elif ! defined(HAVE_VA_ARGS_MACRO)
# /* :TODO: improve here, please find a way to support. */
+# define RBIMPL_CAST_FN_PTR 1
#else
# /** @cond INTERNAL_MACRO */
@@ -348,6 +351,25 @@ RBIMPL_ANYARGS_DECL(rb_define_method, VALUE, const char *)
#endif /* __cplusplus */
+#if defined(RBIMPL_CAST_FN_PTR) && !defined(__cplusplus)
+/* In C23, K&R style prototypes are gone and so `void foo(ANYARGS)` became
+ * equivalent to `void foo(void)` unlike in earlier versions. This is a problem
+ * for rb_define_* functions since that makes all valid functions one can pass
+ * trip -Wincompatible-pointer-types, which we treat as errors. This is mostly
+ * not a problem for the __builtin_choose_expr path, but outside of that we
+ * need to add a cast for compatibility.
+ */
+#define rb_define_method(klass, mid, func, arity) rb_define_method((klass), (mid), (VALUE (*)(ANYARGS))(func), (arity))
+#define rb_define_method_id(klass, mid, func, arity) rb_define_method_id((klass), (mid), (VALUE (*)(ANYARGS))(func), (arity))
+#define rb_define_singleton_method(obj, mid, func, arity) rb_define_singleton_method((obj), (mid), (VALUE (*)(ANYARGS))(func), (arity))
+#define rb_define_protected_method(klass, mid, func, arity) rb_define_protected_method((klass), (mid), (VALUE (*)(ANYARGS))(func), (arity))
+#define rb_define_private_method(klass, mid, func, arity) rb_define_private_method((klass), (mid), (VALUE (*)(ANYARGS))(func), (arity))
+#define rb_define_module_function(mod, mid, func, arity) rb_define_module_function((mod), (mid), (VALUE (*)(ANYARGS))(func), (arity))
+#define rb_define_global_function(mid, func, arity) rb_define_global_function((mid), (VALUE (*)(ANYARGS))(func), (arity))
+
+#undef RBIMPL_CAST_FN_PTR
+#endif /* defined(RBIMPL_CAST_FN_PTR) && !defined(__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
diff --git a/include/ruby/internal/arithmetic/int.h b/include/ruby/internal/arithmetic/int.h
index 6bd8ec2184..7b24d16887 100644
--- a/include/ruby/internal/arithmetic/int.h
+++ b/include/ruby/internal/arithmetic/int.h
@@ -254,7 +254,7 @@ static inline VALUE
rb_uint2num_inline(unsigned int v)
{
if (RB_POSFIXABLE(v))
- return RB_LONG2FIX(v);
+ return RB_LONG2FIX(RBIMPL_CAST((long)v));
else
return rb_uint2big(v);
}
diff --git a/include/ruby/internal/arithmetic/intptr_t.h b/include/ruby/internal/arithmetic/intptr_t.h
index a354f4469c..70090f88e6 100644
--- a/include/ruby/internal/arithmetic/intptr_t.h
+++ b/include/ruby/internal/arithmetic/intptr_t.h
@@ -32,6 +32,18 @@
#define rb_int_new rb_int2inum /**< @alias{rb_int2inum} */
#define rb_uint_new rb_uint2inum /**< @alias{rb_uint2inum} */
+// These definitions are same as fiddle/conversions.h
+#if SIZEOF_VOIDP <= SIZEOF_LONG
+# define PTR2NUM(x) (LONG2NUM((long)(x)))
+# define NUM2PTR(x) ((void*)(NUM2ULONG(x)))
+#elif SIZEOF_VOIDP <= SIZEOF_LONG_LONG
+# define PTR2NUM(x) (LL2NUM((LONG_LONG)(x)))
+# define NUM2PTR(x) ((void*)(NUM2ULL(x)))
+#else
+// should have been an error in ruby/internal/value.h
+# error Need integer for VALUE
+#endif
+
RBIMPL_SYMBOL_EXPORT_BEGIN()
/**
diff --git a/include/ruby/internal/attr/deprecated.h b/include/ruby/internal/attr/deprecated.h
index e1bbdbd15a..a374ace868 100644
--- a/include/ruby/internal/attr/deprecated.h
+++ b/include/ruby/internal/attr/deprecated.h
@@ -48,7 +48,7 @@
#elif RBIMPL_HAS_ATTRIBUTE(deprecated) /* but not with message. */
# define RBIMPL_ATTR_DEPRECATED(msg) __attribute__((__deprecated__))
-#elif RBIMPL_COMPILER_SINCE(MSVC, 14, 0, 0)
+#elif RBIMPL_COMPILER_IS(MSVC)
# define RBIMPL_ATTR_DEPRECATED(msg) __declspec(deprecated msg)
#elif RBIMPL_HAS_DECLSPEC_ATTRIBUTE(deprecated)
@@ -72,4 +72,11 @@
# define RBIMPL_ATTR_DEPRECATED_EXT(msg) RBIMPL_ATTR_DEPRECATED(msg)
#endif
+#define RBIMPL_ATTR_DEPRECATED_SINCE(ver) \
+ RBIMPL_ATTR_DEPRECATED(("since " #ver))
+#define RBIMPL_ATTR_DEPRECATED_INTERNAL(ver) \
+ RBIMPL_ATTR_DEPRECATED(("since "#ver", also internal"))
+#define RBIMPL_ATTR_DEPRECATED_INTERNAL_ONLY() \
+ RBIMPL_ATTR_DEPRECATED(("only for internal use"))
+
#endif /* RBIMPL_ATTR_DEPRECATED_H */
diff --git a/include/ruby/internal/attr/forceinline.h b/include/ruby/internal/attr/forceinline.h
index b7daafede7..5b9ae794af 100644
--- a/include/ruby/internal/attr/forceinline.h
+++ b/include/ruby/internal/attr/forceinline.h
@@ -29,7 +29,7 @@
* `__forceinline` are mutually exclusive. We have to mimic that behaviour for
* non-MSVC compilers.
*/
-#if RBIMPL_COMPILER_SINCE(MSVC, 12, 0, 0)
+#if RBIMPL_COMPILER_IS(MSVC)
# define RBIMPL_ATTR_FORCEINLINE() __forceinline
#elif RBIMPL_HAS_ATTRIBUTE(always_inline)
# define RBIMPL_ATTR_FORCEINLINE() __attribute__((__always_inline__)) inline
diff --git a/include/ruby/internal/attr/noexcept.h b/include/ruby/internal/attr/noexcept.h
index 7c3f92f1e7..dd4c667407 100644
--- a/include/ruby/internal/attr/noexcept.h
+++ b/include/ruby/internal/attr/noexcept.h
@@ -78,7 +78,7 @@
#elif defined(__INTEL_CXX11_MODE__)
# define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_))
-#elif RBIMPL_COMPILER_SINCE(MSVC, 19, 0, 0)
+#elif RBIMPL_COMPILER_IS(MSVC)
# define RBIMPL_ATTR_NOEXCEPT(_) noexcept(noexcept(_))
#elif __cplusplus >= 201103L
diff --git a/include/ruby/internal/attr/nonstring.h b/include/ruby/internal/attr/nonstring.h
new file mode 100644
index 0000000000..5ad6ef2a86
--- /dev/null
+++ b/include/ruby/internal/attr/nonstring.h
@@ -0,0 +1,40 @@
+#ifndef RBIMPL_ATTR_NONSTRING_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_ATTR_NONSTRING_H
+/**
+ * @file
+ * @author Ruby developers <ruby-core@ruby-lang.org>
+ * @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_NONSTRING.
+ */
+#include "ruby/internal/has/attribute.h"
+
+/** Wraps (or simulates) `__attribute__((nonstring))` */
+#if RBIMPL_HAS_ATTRIBUTE(nonstring)
+# define RBIMPL_ATTR_NONSTRING() __attribute__((nonstring))
+# if RBIMPL_COMPILER_SINCE(GCC, 15, 0, 0)
+# define RBIMPL_ATTR_NONSTRING_ARRAY() RBIMPL_ATTR_NONSTRING()
+# elif RBIMPL_COMPILER_SINCE(Clang, 21, 0, 0)
+# define RBIMPL_ATTR_NONSTRING_ARRAY() RBIMPL_ATTR_NONSTRING()
+# else
+# define RBIMPL_ATTR_NONSTRING_ARRAY() /* void */
+# endif
+#else
+# define RBIMPL_ATTR_NONSTRING() /* void */
+# define RBIMPL_ATTR_NONSTRING_ARRAY() /* void */
+#endif
+
+#endif /* RBIMPL_ATTR_NONSTRING_H */
diff --git a/include/ruby/internal/attr/restrict.h b/include/ruby/internal/attr/restrict.h
index e39104138c..b12fdc9dbc 100644
--- a/include/ruby/internal/attr/restrict.h
+++ b/include/ruby/internal/attr/restrict.h
@@ -28,7 +28,7 @@
* `__has_declspec_attribute()` which involves macro substitution. */
/** Wraps (or simulates) `__declspec(restrict)` */
-#if RBIMPL_COMPILER_SINCE(MSVC, 14, 0, 0)
+#if RBIMPL_COMPILER_IS(MSVC)
# define RBIMPL_ATTR_RESTRICT() __declspec(re ## strict)
#elif RBIMPL_HAS_ATTRIBUTE(malloc)
diff --git a/include/ruby/internal/compiler_is/msvc.h b/include/ruby/internal/compiler_is/msvc.h
index 8a864ea558..824f0ecc21 100644
--- a/include/ruby/internal/compiler_is/msvc.h
+++ b/include/ruby/internal/compiler_is/msvc.h
@@ -38,19 +38,8 @@
# 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
+# error Unsupported MSVC version
#endif
#endif /* RBIMPL_COMPILER_IS_MSVC_H */
diff --git a/include/ruby/internal/config.h b/include/ruby/internal/config.h
index da070f0979..34862ded6e 100644
--- a/include/ruby/internal/config.h
+++ b/include/ruby/internal/config.h
@@ -50,7 +50,7 @@
# define HAVE_VA_ARGS_MACRO
# elif defined(__INTEL_CXX11_MODE__)
# define HAVE_VA_ARGS_MACRO
-# elif RBIMPL_COMPILER_SINCE(MSVC, 16, 0, 0)
+# elif RBIMPL_COMPILER_IS(MSVC)
# define HAVE_VA_ARGS_MACRO
# else
# /* NG, not known. */
diff --git a/include/ruby/internal/core/rarray.h b/include/ruby/internal/core/rarray.h
index 90690fe794..73cc0f5dd9 100644
--- a/include/ruby/internal/core/rarray.h
+++ b/include/ruby/internal/core/rarray.h
@@ -80,6 +80,8 @@
* here is at least incomplete.
*/
enum ruby_rarray_flags {
+ /* RUBY_FL_USER0 is for ELTS_SHARED */
+
/**
* 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
@@ -99,8 +101,6 @@ enum ruby_rarray_flags {
*/
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
diff --git a/include/ruby/internal/core/rbasic.h b/include/ruby/internal/core/rbasic.h
index a1477e2600..63cdff8e09 100644
--- a/include/ruby/internal/core/rbasic.h
+++ b/include/ruby/internal/core/rbasic.h
@@ -55,6 +55,12 @@ enum ruby_rvalue_flags {
RVALUE_EMBED_LEN_MAX = RBIMPL_RVALUE_EMBED_LEN_MAX
};
+#if (SIZEOF_VALUE < SIZEOF_UINT64_T)
+#define RBASIC_SHAPE_ID_FIELD 1
+#else
+#define RBASIC_SHAPE_ID_FIELD 0
+#endif
+
/**
* Ruby object's base components. All Ruby objects have them in common.
*/
@@ -85,6 +91,10 @@ RBasic {
*/
const VALUE klass;
+#if RBASIC_SHAPE_ID_FIELD
+ VALUE shape_id;
+#endif
+
#ifdef __cplusplus
public:
RBIMPL_ATTR_CONSTEXPR(CXX11)
@@ -100,8 +110,14 @@ RBasic {
RBasic() :
flags(RBIMPL_VALUE_NULL),
klass(RBIMPL_VALUE_NULL)
+#if RBASIC_SHAPE_ID_FIELD
+ , shape_id(RBIMPL_VALUE_NULL)
+#endif
{
}
+# define RBASIC_INIT RBasic()
+#else
+# define RBASIC_INIT {RBIMPL_VALUE_NULL}
#endif
};
diff --git a/include/ruby/internal/core/rclass.h b/include/ruby/internal/core/rclass.h
index b0b6bfc80c..6f78cc569b 100644
--- a/include/ruby/internal/core/rclass.h
+++ b/include/ruby/internal/core/rclass.h
@@ -58,7 +58,7 @@ enum ruby_rmodule_flags {
* 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
+ RMODULE_IS_REFINEMENT = RUBY_FL_USER1
};
struct RClass; /* Opaque, declared here for RCLASS() macro. */
diff --git a/include/ruby/internal/core/rdata.h b/include/ruby/internal/core/rdata.h
index 43ab3c01e7..cee5e7b5ea 100644
--- a/include/ruby/internal/core/rdata.h
+++ b/include/ruby/internal/core/rdata.h
@@ -37,12 +37,8 @@
#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
+#ifndef RUBY_UNTYPED_DATA_WARNING
+#define RUBY_UNTYPED_DATA_WARNING 1
#endif
#define RBIMPL_DATA_FUNC(f) RBIMPL_CAST((void (*)(void *))(f))
@@ -146,7 +142,10 @@ struct RData {
*/
RUBY_DATA_FUNC dfree;
- /** Pointer to the actual C level struct that you want to wrap. */
+ /** Pointer to the actual C level struct that you want to wrap.
+ * This is after dmark and dfree to allow DATA_PTR to continue to work for
+ * both RData and non-embedded RTypedData.
+ */
void *data;
};
@@ -181,11 +180,6 @@ VALUE rb_data_object_wrap(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_D
*/
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()
/**
@@ -331,15 +325,6 @@ 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.
@@ -361,14 +346,6 @@ rb_data_object_make(VALUE klass, RUBY_DATA_FUNC mark_func, RUBY_DATA_FUNC free_f
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);
-}
-
/** @cond INTERNAL_MACRO */
#define rb_data_object_wrap_0 rb_data_object_wrap
#define rb_data_object_wrap_1 rb_data_object_wrap_warning
diff --git a/include/ruby/internal/core/robject.h b/include/ruby/internal/core/robject.h
index c2bcae6306..99f6470ac1 100644
--- a/include/ruby/internal/core/robject.h
+++ b/include/ruby/internal/core/robject.h
@@ -42,10 +42,10 @@
*/
#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_IV_CAPACITY ROBJECT_IV_CAPACITY
-#define ROBJECT_IVPTR ROBJECT_IVPTR
+#define ROBJECT_EMBED_LEN_MAX ROBJECT_EMBED_LEN_MAX
+#define ROBJECT_HEAP ROBJECT_HEAP
+#define ROBJECT_FIELDS_CAPACITY ROBJECT_FIELDS_CAPACITY
+#define ROBJECT_FIELDS ROBJECT_FIELDS
/** @endcond */
/**
@@ -55,10 +55,12 @@
*/
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.
+ * This flag marks that the object's instance variables are stored in an
+ * external heap buffer.
+ * Normally, instance variable references are stored inside the object slot,
+ * but if it overflow, Ruby may have to allocate a separate buffer and spills
+ * the instance variables there.
+ * 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
@@ -71,7 +73,7 @@ enum ruby_robject_flags {
* 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
+ ROBJECT_HEAP = RUBY_FL_USER4
};
struct st_table;
@@ -94,17 +96,7 @@ struct RObject {
*/
struct {
/** 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 rb_id_table *iv_index_tbl;
+ VALUE *fields;
} heap;
/* Embedded instance variables. When an object is small enough, it
@@ -133,17 +125,17 @@ RBIMPL_ATTR_ARTIFICIAL()
* @shyouhei finds no reason for this to be visible from extension libraries.
*/
static inline VALUE *
-ROBJECT_IVPTR(VALUE obj)
+ROBJECT_FIELDS(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;
+ if (RB_UNLIKELY(RB_FL_ANY_RAW(obj, ROBJECT_HEAP))) {
+ return ptr->as.heap.fields;
}
else {
- return ptr->as.heap.ivptr;
+ return ptr->as.ary;
}
}
diff --git a/include/ruby/internal/core/rstring.h b/include/ruby/internal/core/rstring.h
index 0bca74e688..35175ea94a 100644
--- a/include/ruby/internal/core/rstring.h
+++ b/include/ruby/internal/core/rstring.h
@@ -369,41 +369,6 @@ RSTRING_LEN(VALUE str)
return RSTRING(str)->len;
}
-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.len = RSTRING_LEN(str);
- retval.as.heap.ptr = RSTRING(str)->as.embed.ary;
- return retval;
- }
-}
-
-RBIMPL_WARNING_POP()
-
RBIMPL_ATTR_ARTIFICIAL()
/**
* Queries the contents pointer of the string.
@@ -415,7 +380,9 @@ RBIMPL_ATTR_ARTIFICIAL()
static inline char *
RSTRING_PTR(VALUE str)
{
- char *ptr = rbimpl_rstring_getmem(str).as.heap.ptr;
+ char *ptr = RB_FL_TEST_RAW(str, RSTRING_NOEMBED) ?
+ RSTRING(str)->as.heap.ptr :
+ RSTRING(str)->as.embed.ary;
if (RUBY_DEBUG && RB_UNLIKELY(! ptr)) {
/* :BEWARE: @shyouhei thinks that currently, there are rooms for this
@@ -441,14 +408,17 @@ RBIMPL_ATTR_ARTIFICIAL()
static inline char *
RSTRING_END(VALUE str)
{
- struct RString buf = rbimpl_rstring_getmem(str);
+ char *ptr = RB_FL_TEST_RAW(str, RSTRING_NOEMBED) ?
+ RSTRING(str)->as.heap.ptr :
+ RSTRING(str)->as.embed.ary;
+ long len = RSTRING_LEN(str);
- if (RUBY_DEBUG && RB_UNLIKELY(! buf.as.heap.ptr)) {
+ if (RUBY_DEBUG && RB_UNLIKELY(!ptr)) {
/* Ditto. */
rb_debug_rstring_null_ptr("RSTRING_END");
}
- return &buf.as.heap.ptr[buf.len];
+ return &ptr[len];
}
RBIMPL_ATTR_ARTIFICIAL()
@@ -477,16 +447,7 @@ RSTRING_LENINT(VALUE str)
* @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.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/include/ruby/internal/core/rstruct.h b/include/ruby/internal/core/rstruct.h
index 69be487b59..0028a1bdcd 100644
--- a/include/ruby/internal/core/rstruct.h
+++ b/include/ruby/internal/core/rstruct.h
@@ -31,18 +31,6 @@
# 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
diff --git a/include/ruby/internal/core/rtypeddata.h b/include/ruby/internal/core/rtypeddata.h
index 6c19576c20..ec0794e387 100644
--- a/include/ruby/internal/core/rtypeddata.h
+++ b/include/ruby/internal/core/rtypeddata.h
@@ -37,6 +37,7 @@
#include "ruby/internal/dllexport.h"
#include "ruby/internal/error.h"
#include "ruby/internal/fl_type.h"
+#include "ruby/internal/static_assert.h"
#include "ruby/internal/stdbool.h"
#include "ruby/internal/value_type.h"
@@ -108,13 +109,17 @@
/** @cond INTERNAL_MACRO */
#define RTYPEDDATA_P RTYPEDDATA_P
#define RTYPEDDATA_TYPE RTYPEDDATA_TYPE
+#define TYPED_DATA_EMBEDDED ((VALUE)1)
+#define TYPED_DATA_PTR_MASK (~(TYPED_DATA_EMBEDDED))
+/** @endcond */
+
+/**
+ * Macros to see if each corresponding flag is defined.
+ */
#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 */
-
-#define TYPED_DATA_EMBEDDED 2
/**
* @private
@@ -155,6 +160,12 @@ rbimpl_typeddata_flags {
*/
RUBY_TYPED_FROZEN_SHAREABLE = RUBY_FL_SHAREABLE,
+ // experimental flag
+ // Similar to RUBY_TYPED_FROZEN_SHAREABLE, but doesn't make shareable
+ // reachable objects from this T_DATA object on the Ractor.make_shareable.
+ // If it refers to unshareable objects, simply raise an error.
+ // RUBY_TYPED_FROZEN_SHAREABLE_NO_REC = RUBY_FL_FINALIZE,
+
/**
* This flag has something to do with our garbage collector. These days
* ruby objects are "generational". There are those who are young and
@@ -177,9 +188,9 @@ rbimpl_typeddata_flags {
RUBY_TYPED_WB_PROTECTED = RUBY_FL_WB_PROTECTED, /* THIS FLAG DEPENDS ON Ruby version */
/**
- * This flag no longer in use
+ * This flag is used to distinguish RTypedData from deprecated RData objects.
*/
- RUBY_TYPED_UNUSED = RUBY_FL_UNUSED6,
+ RUBY_TYPED_FL_IS_TYPED_DATA = RUBY_FL_USERPRIV0,
/**
* This flag determines whether marking and compaction should be carried out
@@ -251,10 +262,15 @@ struct rb_data_type_struct {
RUBY_DATA_FUNC dcompact;
/**
- * This field is reserved for future extension. For now, it must be
- * filled with zeros.
+ * @internal
*/
- void *reserved[1]; /* For future extension.
+ void (*handle_weak_references)(void *);
+
+ /**
+ * This field is reserved for future extension. For now, it must be
+ * filled with zeros.
+ */
+ void *reserved[7]; /* For future extension.
This array *must* be filled with ZERO. */
} function;
@@ -352,24 +368,28 @@ struct RTypedData {
/** The part that all ruby objects have in common. */
struct RBasic basic;
+ /** Direct reference to the slots that holds instance variables, if any **/
+ VALUE fields_obj;
+
/**
+ * This is a `const rb_data_type_t *const` value, with the low bits set:
+ *
+ * 1: Set if object is embedded.
+ *
* 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 *const type;
-
- /**
- * This has to be always 1.
- *
- * @internal
- */
- const VALUE typed_flag;
+ const VALUE type;
/** Pointer to the actual C level struct that you want to wrap. */
void *data;
};
+#if !defined(__cplusplus) || __cplusplus >= 201103L
+RBIMPL_STATIC_ASSERT(data_in_rtypeddata, offsetof(struct RData, data) == offsetof(struct RTypedData, data));
+#endif
+
RBIMPL_SYMBOL_EXPORT_BEGIN()
RBIMPL_ATTR_NONNULL((3))
/**
@@ -384,6 +404,7 @@ RBIMPL_ATTR_NONNULL((3))
*/
VALUE rb_data_typed_object_wrap(VALUE klass, void *datap, const rb_data_type_t *type);
+RBIMPL_ATTR_NONNULL((3))
/**
* 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
@@ -399,6 +420,7 @@ 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);
+RBIMPL_ATTR_NONNULL(())
/**
* Checks for the domestic relationship between the two.
*
@@ -413,6 +435,7 @@ VALUE rb_data_typed_object_zalloc(VALUE klass, size_t size, const rb_data_type_t
*/
int rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *parent);
+RBIMPL_ATTR_NONNULL((2))
/**
* Checks if the given object is of given kind.
*
@@ -423,6 +446,7 @@ int rb_typeddata_inherited_p(const rb_data_type_t *child, const rb_data_type_t *
*/
int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type);
+RBIMPL_ATTR_NONNULL((2))
/**
* Identical to rb_typeddata_is_kind_of(), except it raises exceptions instead
* of returning false.
@@ -434,8 +458,49 @@ int rb_typeddata_is_kind_of(VALUE obj, const rb_data_type_t *data_type);
* @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_ATTR_NORETURN()
+RBIMPL_ATTR_NONNULL((2))
+/**
+ * @private
+ *
+ * Fails with the given object's type incompatibility to the type.
+ *
+ * This is an implementation detail of Check_Type. People don't use it
+ * directly.
+ *
+ * @param[in] obj The object in question.
+ * @param[in] expected Name of expected data type of `obj`.
+ */
+void rb_unexpected_object_type(VALUE obj, const char *expected);
+
+RBIMPL_ATTR_NORETURN()
+RBIMPL_ATTR_NONNULL(())
+/**
+ * @private
+ *
+ * Fails with the given object's type incompatibility to the type.
+ *
+ * This is an implementation detail of #TypedData_Make_Struct. People don't
+ * use it directly.
+ *
+ * @param[in] actual Actual data type.
+ * @param[in] expected Expected data type.
+ */
+void rb_unexpected_typeddata(const rb_data_type_t *actual, const rb_data_type_t *expected);
RBIMPL_SYMBOL_EXPORT_END()
+#if RUBY_DEBUG
+# define RBIMPL_TYPEDDATA_PRECONDITION(obj, unreachable) \
+ while (RB_UNLIKELY(!RB_TYPE_P(obj, RUBY_T_DATA))) { \
+ rb_unexpected_object_type(obj, "Data"); \
+ unreachable; \
+ }
+#else
+# define RBIMPL_TYPEDDATA_PRECONDITION(obj, unreachable) \
+ RBIMPL_ASSERT_NOTHING
+#endif
+
/**
* Converts sval, a pointer to your struct, into a Ruby object.
*
@@ -464,14 +529,13 @@ RBIMPL_SYMBOL_EXPORT_END()
*/
#define TypedData_Make_Struct0(result, klass, type, size, data_type, sval) \
VALUE result = rb_data_typed_object_zalloc(klass, size, data_type); \
- (sval) = (type *)RTYPEDDATA_GET_DATA(result); \
+ (sval) = RBIMPL_CAST((type *)rbimpl_typeddata_get_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.
+ * ruby_calloc().
*
* @param klass Ruby level class of the object.
* @param type Type name of the C struct.
@@ -502,47 +566,36 @@ RBIMPL_SYMBOL_EXPORT_END()
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))))
+static inline bool
+rbimpl_typeddata_embedded_p(VALUE obj)
+{
+ return (RTYPEDDATA(obj)->type) & TYPED_DATA_EMBEDDED;
+}
+RBIMPL_ATTR_DEPRECATED_INTERNAL_ONLY()
static inline bool
RTYPEDDATA_EMBEDDED_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
+ RBIMPL_TYPEDDATA_PRECONDITION(obj, RBIMPL_UNREACHABLE_RETURN(false));
- return RTYPEDDATA(obj)->typed_flag & TYPED_DATA_EMBEDDED;
+ return rbimpl_typeddata_embedded_p(obj);
}
static inline void *
-RTYPEDDATA_GET_DATA(VALUE obj)
+rbimpl_typeddata_get_data(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
+ /* We reuse the data pointer in embedded TypedData. */
+ return rbimpl_typeddata_embedded_p(obj) ?
+ RBIMPL_CAST((void *)&RTYPEDDATA_DATA(obj)) :
+ RTYPEDDATA_DATA(obj);
+}
- /* We reuse the data pointer in embedded TypedData. We can't use offsetof
- * since RTypedData a non-POD type in C++. */
- const size_t embedded_typed_data_size = sizeof(struct RTypedData) - sizeof(void *);
+static inline void *
+RTYPEDDATA_GET_DATA(VALUE obj)
+{
+ RBIMPL_TYPEDDATA_PRECONDITION(obj, RBIMPL_UNREACHABLE_RETURN(NULL));
- return RTYPEDDATA_EMBEDDED_P(obj) ? (char *)obj + embedded_typed_data_size : RTYPEDDATA(obj)->data;
+ return rbimpl_typeddata_get_data(obj);
}
RBIMPL_ATTR_PURE()
@@ -561,8 +614,28 @@ RBIMPL_ATTR_ARTIFICIAL()
static inline bool
rbimpl_rtypeddata_p(VALUE obj)
{
- VALUE typed_flag = RTYPEDDATA(obj)->typed_flag;
- return typed_flag != 0 && typed_flag <= 3;
+ return FL_TEST_RAW(obj, RUBY_TYPED_FL_IS_TYPED_DATA);
+}
+
+RBIMPL_ATTR_PURE()
+RBIMPL_ATTR_ARTIFICIAL()
+/**
+ * @private
+ *
+ * Identical to rbimpl_rtypeddata_p(), except it is allowed to call on non-data
+ * objects.
+ *
+ * This is an implementation detail of inline functions defined in this file.
+ * People don't use it directly.
+ *
+ * @param[in] obj Object in question
+ * @retval true `obj` is an instance of ::RTypedData.
+ * @retval false `obj` is not an instance of ::RTypedData
+ */
+static inline bool
+rbimpl_obj_typeddata_p(VALUE obj)
+{
+ return RB_TYPE_P(obj, RUBY_T_DATA) && rbimpl_rtypeddata_p(obj);
}
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
@@ -578,19 +651,14 @@ RBIMPL_ATTR_ARTIFICIAL()
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
+ RBIMPL_TYPEDDATA_PRECONDITION(obj, RBIMPL_UNREACHABLE_RETURN(false));
return rbimpl_rtypeddata_p(obj);
}
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
RBIMPL_ATTR_ARTIFICIAL()
-/* :TODO: can this function be __attribute__((returns_nonnull)) or not? */
+RBIMPL_ATTR_RETURNS_NONNULL()
/**
* Queries for the type of given object.
*
@@ -598,19 +666,77 @@ RBIMPL_ATTR_ARTIFICIAL()
* @return Data type struct that corresponds to `obj`.
* @pre `obj` must be an instance of ::RTypedData.
*/
-static inline const struct rb_data_type_struct *
+static inline const rb_data_type_t *
RTYPEDDATA_TYPE(VALUE obj)
{
-#if RUBY_DEBUG
- if (RB_UNLIKELY(! RTYPEDDATA_P(obj))) {
- rb_unexpected_type(obj, RUBY_T_DATA);
- RBIMPL_UNREACHABLE_RETURN(NULL);
+ RBIMPL_TYPEDDATA_PRECONDITION(obj, RBIMPL_UNREACHABLE_RETURN(NULL));
+
+ VALUE type = RTYPEDDATA(obj)->type & TYPED_DATA_PTR_MASK;
+ const rb_data_type_t *ptr = RBIMPL_CAST((const rb_data_type_t *)type);
+ RBIMPL_ASSERT_OR_ASSUME(ptr);
+ return ptr;
+}
+
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NONNULL(())
+static inline bool
+rbimpl_typeddata_inherited_p_inline(const rb_data_type_t *child, const rb_data_type_t *parent)
+{
+ do {
+ if (RB_LIKELY(child == parent)) return true;
+ } while ((child = child->parent) != NULL);
+ return false;
+}
+#define rb_typeddata_inherited_p rbimpl_typeddata_inherited_p_inline
+
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NONNULL((2))
+static inline bool
+rbimpl_typeddata_is_kind_of_inline(VALUE obj, const rb_data_type_t *data_type)
+{
+ if (RB_UNLIKELY(!rbimpl_obj_typeddata_p(obj))) return false;
+ return rb_typeddata_inherited_p(RTYPEDDATA_TYPE(obj), data_type);
+}
+#define rb_typeddata_is_kind_of rbimpl_typeddata_is_kind_of_inline
+
+RBIMPL_ATTR_ARTIFICIAL()
+RBIMPL_ATTR_NONNULL((2))
+/**
+ * @private
+ *
+ * This is an implementation detail of TypedData_Get_Struct(). Don't use it
+ * directly.
+ */
+static inline void *
+rbimpl_check_typeddata(VALUE obj, const rb_data_type_t *expected_type)
+{
+ if (RB_UNLIKELY(!rbimpl_obj_typeddata_p(obj))) {
+ rb_unexpected_object_type(obj, expected_type->wrap_struct_name);
}
-#endif
- return RTYPEDDATA(obj)->type;
+ const rb_data_type_t *actual_type = RTYPEDDATA_TYPE(obj);
+ if (RB_UNLIKELY(!rb_typeddata_inherited_p(actual_type, expected_type))){
+ rb_unexpected_typeddata(actual_type, expected_type);
+ }
+
+ return RTYPEDDATA_GET_DATA(obj);
}
+
+/**
+ * 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 *)rbimpl_check_typeddata((obj), (data_type))))
+
+RBIMPL_ATTR_NONNULL((2))
/**
* 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
@@ -632,12 +758,4 @@ rb_data_typed_object_make(VALUE klass, const rb_data_type_t *type, void **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/include/ruby/internal/ctype.h b/include/ruby/internal/ctype.h
index 0f7ca6c516..8b24026311 100644
--- a/include/ruby/internal/ctype.h
+++ b/include/ruby/internal/ctype.h
@@ -498,8 +498,8 @@ 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 c The byte is not listed 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
diff --git a/include/ruby/internal/encoding/coderange.h b/include/ruby/internal/encoding/coderange.h
index 7a81208c9e..c89f871518 100644
--- a/include/ruby/internal/encoding/coderange.h
+++ b/include/ruby/internal/encoding/coderange.h
@@ -79,7 +79,7 @@ RBIMPL_ATTR_CONST()
static inline bool
RB_ENC_CODERANGE_CLEAN_P(enum ruby_coderange_type cr)
{
- return rb_enc_coderange_clean_p(cr);
+ return rb_enc_coderange_clean_p(RBIMPL_CAST((int)cr));
}
RBIMPL_ATTR_PURE_UNLESS_DEBUG()
diff --git a/include/ruby/internal/encoding/string.h b/include/ruby/internal/encoding/string.h
index 2b9dfe4f31..2cfa91c01e 100644
--- a/include/ruby/internal/encoding/string.h
+++ b/include/ruby/internal/encoding/string.h
@@ -307,13 +307,13 @@ RBIMPL_ATTR_NONNULL(())
/**
* Looks for the passed string in the passed buffer.
*
- * @param[in] x Buffer that potentially includes `y`.
+ * @param[in] x Query string.
* @param[in] m Number of bytes of `x`.
- * @param[in] y Query string.
+ * @param[in] y Buffer that potentially includes `x`.
* @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`.
+ * @retval otherwise Found index in `y`.
* @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);
diff --git a/include/ruby/internal/error.h b/include/ruby/internal/error.h
index cd37f4461a..5bf82bfe7d 100644
--- a/include/ruby/internal/error.h
+++ b/include/ruby/internal/error.h
@@ -53,6 +53,9 @@ typedef enum {
/** Warning is for performance issues (not enabled by -w). */
RB_WARN_CATEGORY_PERFORMANCE,
+ /** Warning is for checking unused block strictly */
+ RB_WARN_CATEGORY_STRICT_UNUSED_BLOCK,
+
RB_WARN_CATEGORY_DEFAULT_BITS = (
(1U << RB_WARN_CATEGORY_DEPRECATED) |
(1U << RB_WARN_CATEGORY_EXPERIMENTAL) |
@@ -62,6 +65,7 @@ typedef enum {
(1U << RB_WARN_CATEGORY_DEPRECATED) |
(1U << RB_WARN_CATEGORY_EXPERIMENTAL) |
(1U << RB_WARN_CATEGORY_PERFORMANCE) |
+ (1U << RB_WARN_CATEGORY_STRICT_UNUSED_BLOCK) |
0)
} rb_warning_category_t;
@@ -417,11 +421,12 @@ void rb_readwrite_syserr_fail(enum rb_io_wait_readwrite waiting, int err, const
RBIMPL_ATTR_COLD()
RBIMPL_ATTR_NORETURN()
/**
+ * @private
+ *
* 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.
+ * This is an implementation detail of Check_Type. People don't use it
+ * directly.
*
* @param[in] self The object in question.
* @param[in] t Expected type of the object.
diff --git a/include/ruby/internal/eval.h b/include/ruby/internal/eval.h
index 5bcbb97746..23aa1d9580 100644
--- a/include/ruby/internal/eval.h
+++ b/include/ruby/internal/eval.h
@@ -155,7 +155,8 @@ VALUE rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv);
* @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.
+ * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method
+ * was called with keyword arguments.
* @exception rb_eNoMethodError No such method.
* @exception rb_eException Any exceptions happen inside.
* @return What the method evaluates to.
@@ -189,7 +190,8 @@ VALUE rb_funcallv_public(VALUE recv, ID mid, int argc, const VALUE *argv);
* @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.
+ * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method
+ * was called with keyword arguments.
* @exception rb_eNoMethodError No such method.
* @exception rb_eNoMethodError The method is private or protected.
* @exception rb_eException Any exceptions happen inside.
@@ -261,7 +263,8 @@ VALUE rb_funcall_passing_block(VALUE recv, ID mid, int argc, const VALUE *argv);
* @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.
+ * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method
+ * was called with keyword arguments.
* @exception rb_eNoMethodError No such method.
* @exception rb_eNoMethodError The method is private or protected.
* @exception rb_eException Any exceptions happen inside.
@@ -307,7 +310,8 @@ VALUE rb_funcall_with_block(VALUE recv, ID mid, int argc, const VALUE *argv, VAL
* @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.
+ * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method
+ * was called with keyword arguments.
* @exception rb_eNoMethodError No such method.
* @exception rb_eNoMethodError The method is private or protected.
* @exception rb_eException Any exceptions happen inside.
@@ -335,7 +339,8 @@ VALUE rb_call_super(int argc, const VALUE *argv);
* @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.
+ * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method
+ * was called with keyword arguments.
* @exception rb_eNoMethodError No super method are there.
* @exception rb_eException Any exceptions happen inside.
* @return What the super method evaluates to.
diff --git a/include/ruby/internal/fl_type.h b/include/ruby/internal/fl_type.h
index 0a05166784..2afb3f1fa3 100644
--- a/include/ruby/internal/fl_type.h
+++ b/include/ruby/internal/fl_type.h
@@ -59,10 +59,8 @@
#define FL_WB_PROTECTED RBIMPL_CAST((VALUE)RUBY_FL_WB_PROTECTED) /**< @old{RUBY_FL_WB_PROTECTED} */
#define FL_PROMOTED RBIMPL_CAST((VALUE)RUBY_FL_PROMOTED) /**< @old{RUBY_FL_PROMOTED} */
#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} */
@@ -218,11 +216,11 @@ ruby_fl_type {
RUBY_FL_PROMOTED = (1<<5),
/**
- * This flag is no longer in use
+ * This flag meaning is type dependent, currently only used by T_DATA.
*
* @internal
*/
- RUBY_FL_UNUSED6 = (1<<6),
+ RUBY_FL_USERPRIV0 = (1<<6),
/**
* This flag has something to do with finalisers. A ruby object can have
@@ -239,16 +237,16 @@ ruby_fl_type {
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
+ * @deprecated This flag was an implementation detail that should never have
+ * no been exposed. Exists here for backwards
* compatibility only. You can safely forget about it.
*/
- RUBY_FL_TAINT
+ RUBY_FL_EXIVAR
#if defined(RBIMPL_HAVE_ENUM_ATTRIBUTE)
- RBIMPL_ATTR_DEPRECATED(("taintedness turned out to be a wrong idea."))
+ RBIMPL_ATTR_DEPRECATED(("FL_EXIVAR is an outdated implementation detail, it should not be used."))
#elif defined(_MSC_VER)
-# pragma deprecated(RUBY_FL_TAINT)
+# pragma deprecated(RUBY_FL_EXIVAR)
#endif
= 0,
@@ -265,52 +263,19 @@ ruby_fl_type {
*/
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
-
- = 0,
-
- /**
- * 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 object weakly refers to other objects.
+ *
+ * @internal
+ */
+ RUBY_FL_WEAK_REFERENCE = (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 is no longer in use
+ *
+ * @internal
+ */
+ RUBY_FL_UNUSED10 = (1<<10),
/**
* This flag has something to do with data immutability. When this flag is
@@ -370,7 +335,7 @@ ruby_fl_type {
* 3rd parties. It must be an implementation detail that they should never
* know. Might better be hidden.
*/
- RUBY_ELTS_SHARED = RUBY_FL_USER2,
+ RUBY_ELTS_SHARED = RUBY_FL_USER0,
/**
* This flag has something to do with an object's class. There are kind of
@@ -398,23 +363,6 @@ ruby_fl_type {
RUBY_FL_SINGLETON = RUBY_FL_USER1,
};
-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()
@@ -446,10 +394,8 @@ 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 {
+ RBIMPL_ASSERT_OR_ASSUME(!RB_TYPE_P(obj, RUBY_T_NODE));
return true;
}
}
@@ -743,128 +689,6 @@ RB_FL_REVERSE(VALUE obj, VALUE 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)
-{
- (void)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)
-{
- (void)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)
-{
- (void)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)
-{
- (void)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)
-{
- (void)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)
-{
- (void)dst;
- (void)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)
-{
- (void)dst;
- (void)src;
- return;
-}
-
-RBIMPL_ATTR_PURE_UNLESS_DEBUG()
-RBIMPL_ATTR_ARTIFICIAL()
/**
* This is an implementation detail of RB_OBJ_FROZEN(). 3rd parties need not
* use this. Just always use RB_OBJ_FROZEN().
@@ -906,6 +730,14 @@ RB_OBJ_FROZEN(VALUE obj)
}
RUBY_SYMBOL_EXPORT_BEGIN
+/**
+ * Prevents further modifications to the given object. ::rb_eFrozenError shall
+ * be raised if modification is attempted.
+ *
+ * @param[out] x Object in question.
+ * @exception rb_eNoMemError Failed to allocate memory for the frozen
+ * representation of the object.
+ */
void rb_obj_freeze_inline(VALUE obj);
RUBY_SYMBOL_EXPORT_END
diff --git a/include/ruby/internal/gc.h b/include/ruby/internal/gc.h
index 462f416af2..21c2b670b3 100644
--- a/include/ruby/internal/gc.h
+++ b/include/ruby/internal/gc.h
@@ -45,7 +45,7 @@
RBIMPL_SYMBOL_EXPORT_BEGIN()
#define RUBY_REF_EDGE(s, p) offsetof(s, p)
-#define RUBY_REFS_LIST_PTR(l) (RUBY_DATA_FUNC)(l)
+#define RUBY_REFS_LIST_PTR(l) (RUBY_DATA_FUNC)(uintptr_t)(l)
#define RUBY_REF_END SIZE_MAX
#define RUBY_REFERENCES(t) static const size_t t[]
#define RUBY_REFERENCES_START(t) RUBY_REFERENCES(t) = {
@@ -823,7 +823,4 @@ rb_obj_write(
return a;
}
-RBIMPL_ATTR_DEPRECATED(("Will be removed soon"))
-static inline void rb_gc_force_recycle(VALUE obj){}
-
#endif /* RBIMPL_GC_H */
diff --git a/include/ruby/internal/globals.h b/include/ruby/internal/globals.h
index 60d8e5309a..9beb215c0c 100644
--- a/include/ruby/internal/globals.h
+++ b/include/ruby/internal/globals.h
@@ -68,6 +68,7 @@ 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_cBox; /**< `Ruby::Box` class. */
RUBY_EXTERN VALUE rb_cClass; /**< `Class` class. */
RUBY_EXTERN VALUE rb_cDir; /**< `Dir` class. */
RUBY_EXTERN VALUE rb_cEncoding; /**< `Encoding` class. */
@@ -91,6 +92,7 @@ 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_cSet; /**< `Set` class. */
RUBY_EXTERN VALUE rb_cStat; /**< `File::Stat` class. */
RUBY_EXTERN VALUE rb_cString; /**< `String` class. */
RUBY_EXTERN VALUE rb_cStruct; /**< `Struct` class. */
diff --git a/include/ruby/internal/has/builtin.h b/include/ruby/internal/has/builtin.h
index 243ba2a34c..8e7fb173d8 100644
--- a/include/ruby/internal/has/builtin.h
+++ b/include/ruby/internal/has/builtin.h
@@ -48,6 +48,7 @@
# /* 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_add_overflow_p RBIMPL_COMPILER_SINCE(GCC, 7, 0, 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
@@ -75,6 +76,7 @@
# 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_sub_overflow_p RBIMPL_COMPILER_SINCE(GCC, 7, 0, 0)
# define RBIMPL_HAS_BUILTIN___builtin_unreachable RBIMPL_COMPILER_SINCE(GCC, 4, 5, 0)
# /* Note that "0, 0, 0" might be inaccurate. */
@@ -82,6 +84,7 @@
# /* 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_add_overflow_p HAVE_BUILTIN___BUILTIN_ADD_OVERFLOW_P
# 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
@@ -107,6 +110,7 @@
# 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
+# define RBIMPL_HAS_BUILTIN___builtin_sub_overflow_p HAVE_BUILTIN___BUILTIN_SUB_OVERFLOW_P
# if defined(HAVE___BUILTIN_UNREACHABLE)
# define RBIMPL_HAS_BUILTIN___builtin_unreachable 1
# else
diff --git a/include/ruby/internal/intern/array.h b/include/ruby/internal/intern/array.h
index 1909fdf17b..b2cc6b132d 100644
--- a/include/ruby/internal/intern/array.h
+++ b/include/ruby/internal/intern/array.h
@@ -144,7 +144,13 @@ void rb_ary_free(VALUE ary);
*/
void rb_ary_modify(VALUE ary);
-/** @alias{rb_obj_freeze} */
+/**
+ * Freeze an array, preventing further modifications. The underlying buffer may
+ * be shrunk before freezing to conserve memory.
+ *
+ * @param[out] obj Object assumed to be an array to freeze.
+ * @see RB_OBJ_FREEZE()
+ */
VALUE rb_ary_freeze(VALUE obj);
RBIMPL_ATTR_PURE()
diff --git a/include/ruby/internal/intern/complex.h b/include/ruby/internal/intern/complex.h
index e111bd8ced..1efc093631 100644
--- a/include/ruby/internal/intern/complex.h
+++ b/include/ruby/internal/intern/complex.h
@@ -87,10 +87,6 @@ VALUE rb_complex_new(VALUE real, VALUE imag);
*/
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.
diff --git a/include/ruby/internal/intern/cont.h b/include/ruby/internal/intern/cont.h
index 32647f48aa..2d813ceb9d 100644
--- a/include/ruby/internal/intern/cont.h
+++ b/include/ruby/internal/intern/cont.h
@@ -148,7 +148,8 @@ VALUE rb_fiber_resume(VALUE fiber, int argc, const VALUE *argv);
* @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.
+ * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method
+ * was called with keyword arguments.
* @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.
@@ -192,7 +193,8 @@ VALUE rb_fiber_yield(int argc, const VALUE *argv);
* @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.
+ * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method
+ * was called with keyword arguments.
* @exception rb_eException What was raised using `Fiber#raise`.
* @return (See rb_fiber_resume() for details)
*/
@@ -247,7 +249,8 @@ VALUE rb_fiber_transfer(VALUE fiber, int argc, const VALUE *argv);
* @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.
+ * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method
+ * was called with keyword arguments.
* @exception rb_eFiberError (See above)
* @exception rb_eException What was raised using `Fiber#raise`.
* @return (See rb_fiber_resume() for details)
@@ -275,7 +278,7 @@ VALUE rb_fiber_transfer_kw(VALUE fiber, int argc, const VALUE *argv, int kw_spla
* @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);
+VALUE rb_fiber_raise(VALUE fiber, int argc, VALUE *argv);
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/internal/intern/enumerator.h b/include/ruby/internal/intern/enumerator.h
index 20e5d7c6fc..00804d786a 100644
--- a/include/ruby/internal/intern/enumerator.h
+++ b/include/ruby/internal/intern/enumerator.h
@@ -100,7 +100,8 @@ VALUE rb_enumeratorize_with_size(VALUE recv, VALUE meth, int argc, const VALUE *
* @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.
+ * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method
+ * was called with keyword arguments.
* @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`.
@@ -186,7 +187,8 @@ RBIMPL_SYMBOL_EXPORT_END()
* @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.
+ * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method
+ * was called with keyword arguments.
* @return A new instance of ::rb_cEnumerator which, when yielded,
* enumerates by calling the current method on `recv` with `argv`.
*/
@@ -220,7 +222,8 @@ RBIMPL_SYMBOL_EXPORT_END()
* @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.
+ * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method
+ * was called with keyword arguments.
* @note This macro may return inside.
*/
#define RETURN_SIZED_ENUMERATOR_KW(obj, argc, argv, size_fn, kw_splat) do { \
@@ -250,7 +253,8 @@ RBIMPL_SYMBOL_EXPORT_END()
* @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.
+ * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method
+ * was called with keyword arguments.
* @note This macro may return inside.
*/
#define RETURN_ENUMERATOR_KW(obj, argc, argv, kw_splat) \
diff --git a/include/ruby/internal/intern/error.h b/include/ruby/internal/intern/error.h
index 2ca51d0111..1fd9ec2f51 100644
--- a/include/ruby/internal/intern/error.h
+++ b/include/ruby/internal/intern/error.h
@@ -237,6 +237,8 @@ RBIMPL_ATTR_NORETURN()
*/
void rb_error_arity(int argc, int min, int max);
+void rb_str_modify(VALUE str);
+
RBIMPL_SYMBOL_EXPORT_END()
/**
@@ -247,7 +249,23 @@ RBIMPL_SYMBOL_EXPORT_END()
#define rb_check_frozen_internal rb_check_frozen
/** @alias{rb_check_frozen} */
-#define rb_check_frozen_inline rb_check_frozen
+static inline void
+rb_check_frozen_inline(VALUE obj)
+{
+ if (RB_UNLIKELY(RB_OBJ_FROZEN(obj))) {
+ rb_error_frozen_object(obj);
+ }
+
+ /* ref: internal CHILLED_STRING_P()
+ This is an implementation detail subject to change. */
+ if (RB_UNLIKELY(RB_TYPE_P(obj, T_STRING) && FL_TEST_RAW(obj, RUBY_FL_USER2 | RUBY_FL_USER3))) { // STR_CHILLED
+ rb_str_modify(obj);
+ }
+}
+
+/* rb_check_frozen() is available as a symbol, but have
+ * the inline version take priority for native consumers. */
+#define rb_check_frozen rb_check_frozen_inline
/**
* Ensures that the passed integer is in the passed range. When you can use
diff --git a/include/ruby/internal/intern/file.h b/include/ruby/internal/intern/file.h
index 79820fdc61..8508b7ab9e 100644
--- a/include/ruby/internal/intern/file.h
+++ b/include/ruby/internal/intern/file.h
@@ -24,6 +24,9 @@
#include "ruby/internal/attr/pure.h"
#include "ruby/internal/dllexport.h"
#include "ruby/internal/value.h"
+#if !defined RUBY_EXPORT && !defined RUBY_NO_OLD_COMPATIBILITY
+# include "ruby/backward.h"
+#endif
RBIMPL_SYMBOL_EXPORT_BEGIN()
diff --git a/include/ruby/internal/intern/hash.h b/include/ruby/internal/intern/hash.h
index af8dfd5d8f..504770fa5f 100644
--- a/include/ruby/internal/intern/hash.h
+++ b/include/ruby/internal/intern/hash.h
@@ -284,20 +284,6 @@ 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);
-/* 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 */
-
/**
* Destructively removes every environment variables of the running process.
*
diff --git a/include/ruby/internal/intern/io.h b/include/ruby/internal/intern/io.h
index 02c249723e..b9eb258cc1 100644
--- a/include/ruby/internal/intern/io.h
+++ b/include/ruby/internal/intern/io.h
@@ -385,7 +385,7 @@ VALUE rb_io_puts(int argc, const VALUE *argv, VALUE io);
* @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.
+ * @return An allocated instance of ::rb_cIO with the autoclose flag set.
* @note Leave `path` NULL if you don't know.
*/
VALUE rb_io_fdopen(int fd, int flags, const char *path);
diff --git a/include/ruby/internal/intern/object.h b/include/ruby/internal/intern/object.h
index 9daad7d046..3897639a0a 100644
--- a/include/ruby/internal/intern/object.h
+++ b/include/ruby/internal/intern/object.h
@@ -80,7 +80,8 @@ VALUE rb_class_new_instance(int argc, const VALUE *argv, VALUE klass);
* @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.
+ * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method
+ * was called with keyword arguments.
* @exception rb_eTypeError `klass`'s allocator is undefined.
* @exception rb_eException Any exceptions can happen inside.
* @return An allocated new instance of `klass`.
diff --git a/include/ruby/internal/intern/proc.h b/include/ruby/internal/intern/proc.h
index b8c3c5e146..2635d672eb 100644
--- a/include/ruby/internal/intern/proc.h
+++ b/include/ruby/internal/intern/proc.h
@@ -101,7 +101,8 @@ VALUE rb_proc_call(VALUE recv, VALUE args);
* @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.
+ * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method
+ * was called with keyword arguments.
* @exception rb_eException Any exceptions happen inside.
* @return What the proc evaluates to.
*/
@@ -141,7 +142,8 @@ VALUE rb_proc_call_with_block(VALUE recv, int argc, const VALUE *argv, VALUE pro
* @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.
+ * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method
+ * was called with keyword arguments.
* @exception rb_eException Any exceptions happen inside.
* @return What the proc evaluates to.
*/
@@ -245,7 +247,8 @@ VALUE rb_method_call(int argc, const VALUE *argv, VALUE recv);
* @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.
+ * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method
+ * was called with keyword arguments.
* @exception rb_eTypeError `recv` is not a method.
* @exception rb_eException Any exceptions happen inside.
* @return What the method returns.
@@ -279,7 +282,8 @@ VALUE rb_method_call_with_block(int argc, const VALUE *argv, VALUE recv, VALUE p
* @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.
+ * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method
+ * was called with keyword arguments.
* @exception rb_eTypeError `recv` is not a method.
* @exception rb_eException Any exceptions happen inside.
* @return What the method returns.
diff --git a/include/ruby/internal/intern/select.h b/include/ruby/internal/intern/select.h
index 6ba84c6e63..ba75213618 100644
--- a/include/ruby/internal/intern/select.h
+++ b/include/ruby/internal/intern/select.h
@@ -72,6 +72,8 @@ struct timeval;
* someone else, vastly varies among operating systems. You would better avoid
* touching an fd from more than one threads.
*
+ * NOTE: this function is used in native extensions, so change its API with care.
+ *
* @internal
*
* Although any file descriptors are possible here, it makes completely no
diff --git a/include/ruby/internal/intern/select/win32.h b/include/ruby/internal/intern/select/win32.h
index edaf7a8523..b7301e63f3 100644
--- a/include/ruby/internal/intern/select/win32.h
+++ b/include/ruby/internal/intern/select/win32.h
@@ -206,7 +206,7 @@ rb_fd_dup(rb_fdset_t *dst, const rb_fdset_t *src)
* 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.
+ * could use `CancelIoEx`. 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)
@@ -253,7 +253,7 @@ rb_fd_max(const rb_fdset_t *f)
const fd_set *p = f->fdset;
RBIMPL_ASSERT_OR_ASSUME(p);
- return p->fd_count;
+ return RBIMPL_CAST((int)p->fd_count);
}
#endif /* RBIMPL_INTERN_SELECT_WIN32_H */
diff --git a/include/ruby/internal/intern/set.h b/include/ruby/internal/intern/set.h
new file mode 100644
index 0000000000..f4ff8665e2
--- /dev/null
+++ b/include/ruby/internal/intern/set.h
@@ -0,0 +1,111 @@
+#ifndef RBIMPL_INTERN_SET_H /*-*-C++-*-vi:se ft=cpp:*/
+#define RBIMPL_INTERN_SET_H
+/**
+ * @file
+ * @author Ruby developers <ruby-core@ruby-lang.org>
+ * @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_cSet.
+ */
+#include "ruby/internal/attr/nonnull.h"
+#include "ruby/internal/dllexport.h"
+#include "ruby/internal/value.h"
+
+RBIMPL_SYMBOL_EXPORT_BEGIN()
+
+/* set.c */
+
+RBIMPL_ATTR_NONNULL(())
+/**
+ * Iterates over a set. Calls func with each element of the set and the
+ * argument given. func should return ST_CONTINUE, ST_STOP, or ST_DELETE.
+ *
+ * @param[in] set An instance of ::rb_cSet to iterate over.
+ * @param[in] func Callback function to yield.
+ * @param[in] arg Passed as-is to `func`.
+ * @exception rb_eRuntimeError `set` was tampered during iterating.
+ */
+void rb_set_foreach(VALUE set, int (*func)(VALUE element, VALUE arg), VALUE arg);
+
+/**
+ * Creates a new, empty set object.
+ *
+ * @return An allocated new instance of ::rb_cSet.
+ */
+VALUE rb_set_new(void);
+
+/**
+ * Identical to rb_set_new(), except it additionally specifies how many elements
+ * it is expected to contain. This way you can create a set that is large enough
+ * for your need. For large sets, it means it won't need to be reallocated
+ * much, improving performance.
+ *
+ * @param[in] capa Designed capacity of the set.
+ * @return An empty Set, whose capacity is `capa`.
+ */
+VALUE rb_set_new_capa(size_t capa);
+
+/**
+ * Whether the set contains the given element.
+ *
+ * @param[in] set Set to look into.
+ * @param[in] element Set element to look for.
+ * @return true if element is in the set, falst otherwise.
+ */
+bool rb_set_lookup(VALUE set, VALUE element);
+
+/**
+ * Adds element to set.
+ *
+ * @param[in] set Target set table to modify.
+ * @param[in] element Arbitrary Ruby object.
+ * @exception rb_eFrozenError `set` is frozen.
+ * @return true if element was not already in set, false otherwise
+ * @post `element` is in `set`.
+ */
+bool rb_set_add(VALUE set, VALUE element);
+
+/**
+ * Removes all entries from set.
+ *
+ * @param[out] set Target to clear.
+ * @exception rb_eFrozenError `set`is frozen.
+ * @return The passed `set`
+ * @post `set` has no elements.
+ */
+VALUE rb_set_clear(VALUE set);
+
+/**
+ * Removes the element from from set.
+ *
+ * @param[in] set Target set to modify.
+ * @param[in] element Key to delete.
+ * @retval true if element was already in set, false otherwise
+ * @post `set` does not have `element` as an element.
+ */
+bool rb_set_delete(VALUE set, VALUE element);
+
+/**
+ * Returns the number of elements in the set.
+ *
+ * @param[in] set A set object.
+ * @return The size of the set.
+ */
+size_t rb_set_size(VALUE set);
+
+RBIMPL_SYMBOL_EXPORT_END()
+
+#endif /* RBIMPL_INTERN_SET_H */
diff --git a/include/ruby/internal/intern/string.h b/include/ruby/internal/intern/string.h
index 37dee45527..8bd1ffcfb4 100644
--- a/include/ruby/internal/intern/string.h
+++ b/include/ruby/internal/intern/string.h
@@ -412,8 +412,8 @@ 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 rb_str_new_shared(),
- * except it returns an infamous "f"string.
+ * C's and preserves its encoding. It can also be seen as a routine identical
+ * 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
@@ -444,8 +444,9 @@ VALUE rb_str_to_interned_str(VALUE str);
* 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`.
+ * length, whose contents are identical to that of `ptr`. Its
+ * encoding will be US-ASCII if all bytes are lower ASCII, BINARY
+ * otherwise.
* @pre At least `len` bytes of continuous memory region shall be
* accessible via `ptr`.
*/
@@ -461,8 +462,9 @@ RBIMPL_ATTR_NONNULL(())
*
* @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`.
+ * @return An instance of ::rb_cString, whose contents are verbatim copy
+ * of `ptr`. Its encoding will be US-ASCII if all bytes are lower
+ * ASCII, BINARY otherwise.
* @pre `ptr` must not be a null pointer.
*/
VALUE rb_interned_str_cstr(const char *ptr);
@@ -591,10 +593,9 @@ void rb_must_asciicompat(VALUE obj);
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().
+ * Like rb_str_dup(), but always create 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.
@@ -970,8 +971,8 @@ st_index_t rb_str_hash(VALUE str);
*
* @param[in] str1 A string.
* @param[in] str2 Another string.
- * @retval 1 They have identical contents, length, and encodings.
- * @retval 0 Otherwise.
+ * @retval 0 They have identical contents, length, and encodings.
+ * @retval 1 Otherwise.
* @pre Both objects must not be any arbitrary objects except
* ::RString.
*
@@ -1686,10 +1687,10 @@ rbimpl_exc_new_cstr(VALUE exc, const char *str)
* 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.
+ * @return An integer constant expression that represents the number of
+ * `str`'s elements, not including the terminating NUL character.
*/
-#define rb_strlen_lit(str) (sizeof(str "") - 1)
+#define rb_strlen_lit(str) ((sizeof(str "") / sizeof(str ""[0])) - 1)
/**
* Identical to rb_str_new_static(), except it cannot take string variables.
diff --git a/include/ruby/internal/intern/thread.h b/include/ruby/internal/intern/thread.h
index 716375acd7..4d87452745 100644
--- a/include/ruby/internal/intern/thread.h
+++ b/include/ruby/internal/intern/thread.h
@@ -61,10 +61,10 @@ int rb_thread_wait_fd(int fd);
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.
+ * This funciton is now a no-op. It was previously used to interrupt threads
+ * that were using the given file descriptor and wait for them to finish.
+ *
+ * @deprecated Use IO with RUBY_IO_MODE_EXTERNAL and `rb_io_close` instead.
*
* @param[in] fd A file descriptor.
* @note This function blocks until all the threads waiting for such fd
diff --git a/include/ruby/internal/intern/vm.h b/include/ruby/internal/intern/vm.h
index 29e0c7f534..f0b54c702c 100644
--- a/include/ruby/internal/intern/vm.h
+++ b/include/ruby/internal/intern/vm.h
@@ -89,7 +89,8 @@ VALUE rb_check_funcall(VALUE recv, ID mid, int argc, const VALUE *argv);
* @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.
+ * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method
+ * was called with keyword arguments.
* @retval RUBY_Qundef `recv` doesn't respond to `mid`.
* @retval otherwise What the method evaluates to.
*/
@@ -106,9 +107,11 @@ VALUE rb_check_funcall_kw(VALUE recv, ID mid, int argc, const VALUE *argv, int k
* @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.
+ * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method
+ * was called with keyword arguments.
* @return What the command evaluates to.
*/
+RBIMPL_ATTR_DEPRECATED_INTERNAL(4.0)
VALUE rb_eval_cmd_kw(VALUE cmd, VALUE arg, int kw_splat);
/**
diff --git a/include/ruby/internal/iterator.h b/include/ruby/internal/iterator.h
index 5f706460f8..891045363e 100644
--- a/include/ruby/internal/iterator.h
+++ b/include/ruby/internal/iterator.h
@@ -265,48 +265,6 @@ int rb_block_given_p(void);
*/
void rb_need_block(void);
-#ifndef __cplusplus
-RBIMPL_ATTR_DEPRECATED(("by: rb_block_call since 1.9"))
-#endif
-/**
- * Old way to iterate a block.
- *
- * @deprecated This is an old API. Use rb_block_call() instead.
- * @warning The passed function must at least once call a ruby method
- * (to handle interrupts etc.)
- * @param[in] func1 A function that could yield a value.
- * @param[in,out] data1 Passed to `func1`
- * @param[in] proc A function acts as a block.
- * @param[in,out] data2 Passed to `proc` as the data2 parameter.
- * @return What `func1` returns.
- */
-VALUE rb_iterate(VALUE (*func1)(VALUE), VALUE data1, rb_block_call_func_t proc, VALUE data2);
-
-#ifdef __cplusplus
-namespace ruby {
-namespace backward {
-/**
- * Old way to iterate a block.
- *
- * @deprecated This is an old API. Use rb_block_call() instead.
- * @warning The passed function must at least once call a ruby method
- * (to handle interrupts etc.)
- * @param[in] iter A function that could yield a value.
- * @param[in,out] data1 Passed to `func1`
- * @param[in] bl A function acts as a block.
- * @param[in,out] data2 Passed to `proc` as the data2 parameter.
- * @return What `func1` returns.
- */
-static inline VALUE
-rb_iterate_deprecated(VALUE (*iter)(VALUE), VALUE data1, rb_block_call_func_t bl, VALUE data2)
-{
- return ::rb_iterate(iter, data1, bl, data2);
-}}}
-
-RBIMPL_ATTR_DEPRECATED(("by: rb_block_call since 1.9"))
-VALUE rb_iterate(VALUE (*func1)(VALUE), VALUE data1, rb_block_call_func_t proc, VALUE data2);
-#endif
-
/**
* Identical to rb_funcallv(), except it additionally passes a function as a
* block. When the method yields, `proc` is called with the yielded value as
@@ -337,7 +295,8 @@ VALUE rb_block_call(VALUE obj, ID mid, int argc, const VALUE *argv, rb_block_cal
* @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.
+ * - RB_PASS_CALLED_KEYWORDS Pass keyword arguments if the current method
+ * was called with keyword arguments.
* @return What `obj.mid` returns.
*/
VALUE rb_block_call_kw(VALUE obj, ID mid, int argc, const VALUE *argv, rb_block_call_func_t proc, VALUE data2, int kw_splat);
diff --git a/include/ruby/internal/memory.h b/include/ruby/internal/memory.h
index 64e850c65e..cd099f85db 100644
--- a/include/ruby/internal/memory.h
+++ b/include/ruby/internal/memory.h
@@ -38,9 +38,14 @@
# include <alloca.h>
#endif
-#if defined(_MSC_VER) && defined(_M_AMD64)
+#if defined(_MSC_VER) && defined(_WIN64)
# include <intrin.h>
+# if defined(_M_AMD64)
# pragma intrinsic(_umul128)
+# endif
+# if defined(_M_ARM64)
+# pragma intrinsic(__umulh)
+# endif
#endif
#include "ruby/internal/attr/alloc_size.h"
@@ -403,7 +408,8 @@ typedef uint128_t DSIZE_T;
/**
* @private
*
- * This is an implementation detail of rbimpl_size_mul_overflow().
+ * This is an implementation detail of rbimpl_size_mul_overflow() and
+ * rbimpl_size_add_overflow().
*
* @internal
*
@@ -411,9 +417,9 @@ typedef uint128_t DSIZE_T;
* nothing more than std::variant<std::size_t> 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. */
+struct rbimpl_size_overflow_tag {
+ bool overflowed; /**< Whether overflow happened or not. */
+ size_t result; /**< Calculation result. */
};
RBIMPL_SYMBOL_EXPORT_BEGIN()
@@ -483,6 +489,18 @@ RBIMPL_ATTR_NORETURN()
*/
void ruby_malloc_size_overflow(size_t x, size_t y);
+RBIMPL_ATTR_NORETURN()
+/**
+ * @private
+ *
+ * This is an implementation detail. 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_add_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
@@ -555,42 +573,46 @@ RBIMPL_ATTR_CONST()
*
* @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`.
+ * @return `{ overflowed, result }`, where `overflowed` is whether there is
+ * an integer overflow or not, and `result` 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
+static inline struct rbimpl_size_overflow_tag
rbimpl_size_mul_overflow(size_t x, size_t y)
{
- struct rbimpl_size_mul_overflow_tag ret = { false, 0, };
+ struct rbimpl_size_overflow_tag ret = { false, 0, };
#if defined(ckd_mul)
- ret.left = ckd_mul(&ret.right, x, y);
+ ret.overflowed = ckd_mul(&ret.result, x, y);
#elif RBIMPL_HAS_BUILTIN(__builtin_mul_overflow)
- ret.left = __builtin_mul_overflow(x, y, &ret.right);
+ ret.overflowed = __builtin_mul_overflow(x, y, &ret.result);
#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);
+ ret.overflowed = dz > SIZE_MAX;
+ ret.result = RBIMPL_CAST((size_t)dz);
-#elif defined(_MSC_VER) && defined(_WIN64)
+#elif defined(_MSC_VER) && defined(_M_AMD64)
unsigned __int64 dp = 0;
unsigned __int64 dz = _umul128(x, y, &dp);
- ret.left = RBIMPL_CAST((bool)dp);
- ret.right = RBIMPL_CAST((size_t)dz);
+ ret.overflowed = RBIMPL_CAST((bool)dp);
+ ret.result = RBIMPL_CAST((size_t)dz);
+
+#elif defined(_MSC_VER) && defined(_M_ARM64)
+ ret.overflowed = __umulh(x, y) != 0;
+ ret.result = x * y;
#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;
+ ret.overflowed = (y != 0) && (x > SIZE_MAX / y);
+ ret.result = x * y;
#endif
return ret;
@@ -614,11 +636,11 @@ rbimpl_size_mul_overflow(size_t x, size_t y)
static inline size_t
rbimpl_size_mul_or_raise(size_t x, size_t y)
{
- struct rbimpl_size_mul_overflow_tag size =
+ struct rbimpl_size_overflow_tag size =
rbimpl_size_mul_overflow(x, y);
- if (RB_LIKELY(! size.left)) {
- return size.right;
+ if (RB_LIKELY(! size.overflowed)) {
+ return size.result;
}
else {
ruby_malloc_size_overflow(x, y);
@@ -626,6 +648,81 @@ rbimpl_size_mul_or_raise(size_t x, size_t y)
}
}
+#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. People don't use this directly.
+ *
+ * @param[in] x Arbitrary value.
+ * @param[in] y Arbitrary value.
+ * @return `{ overflowed, result }`, where `overflowed` is whether there is
+ * an integer overflow or not, and `result` is a (possibly
+ * overflowed) result of `x` + `y`.
+ *
+ * @internal
+ */
+static inline struct rbimpl_size_overflow_tag
+rbimpl_size_add_overflow(size_t x, size_t y)
+{
+ struct rbimpl_size_overflow_tag ret = { false, 0, };
+
+#if defined(ckd_add)
+ ret.overflowed = ckd_add(&ret.result, x, y);
+
+#elif RBIMPL_HAS_BUILTIN(__builtin_add_overflow)
+ ret.overflowed = __builtin_add_overflow(x, y, &ret.result);
+
+#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.overflowed = dz > SIZE_MAX;
+ ret.result = (size_t)dz;
+
+#else
+ ret.result = x + y;
+ ret.overflowed = ret.result < y;
+
+#endif
+
+ return ret;
+}
+
+/**
+ * @private
+ *
+ * This is an implementation detail. 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
+ */
+static inline size_t
+rbimpl_size_add_or_raise(size_t x, size_t y)
+{
+ struct rbimpl_size_overflow_tag size =
+ rbimpl_size_add_overflow(x, y);
+
+ if (RB_LIKELY(!size.overflowed)) {
+ return size.result;
+ }
+ else {
+ ruby_malloc_add_size_overflow(x, y);
+ RBIMPL_UNREACHABLE_RETURN(0);
+ }
+}
+
/**
* This is an implementation detail of #RB_ALLOCV_N(). People don't use this
* directly.
diff --git a/include/ruby/internal/newobj.h b/include/ruby/internal/newobj.h
index 6eee2fa5fa..13030ae279 100644
--- a/include/ruby/internal/newobj.h
+++ b/include/ruby/internal/newobj.h
@@ -109,42 +109,4 @@ void rb_singleton_class_attached(VALUE klass, VALUE obj);
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)
-{
- (void)clone;
- (void)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)
-{
- (void)dup;
- (void)obj;
- return;
-}
-
#endif /* RBIMPL_NEWOBJ_H */
diff --git a/include/ruby/internal/scan_args.h b/include/ruby/internal/scan_args.h
index 1ed2bf6368..2dbc1ee7bc 100644
--- a/include/ruby/internal/scan_args.h
+++ b/include/ruby/internal/scan_args.h
@@ -75,7 +75,7 @@
* Pass keywords if current method is called with keywords, useful for argument
* delegation
*/
-#define RB_PASS_CALLED_KEYWORDS rb_keyword_given_p()
+#define RB_PASS_CALLED_KEYWORDS !!rb_keyword_given_p()
/** @} */
diff --git a/include/ruby/internal/special_consts.h b/include/ruby/internal/special_consts.h
index 85579e33f0..1e2636da48 100644
--- a/include/ruby/internal/special_consts.h
+++ b/include/ruby/internal/special_consts.h
@@ -326,7 +326,7 @@ RBIMPL_ATTR_ARTIFICIAL()
static inline bool
RB_SPECIAL_CONST_P(VALUE obj)
{
- return RB_IMMEDIATE_P(obj) || obj == RUBY_Qfalse;
+ return (obj == RUBY_Qfalse) || RB_IMMEDIATE_P(obj);
}
RBIMPL_ATTR_CONST()
@@ -346,7 +346,7 @@ RBIMPL_ATTR_CONSTEXPR(CXX11)
static inline VALUE
rb_special_const_p(VALUE obj)
{
- return RB_SPECIAL_CONST_P(obj) * RUBY_Qtrue;
+ return (unsigned int)RB_SPECIAL_CONST_P(obj) * RUBY_Qtrue;
}
/**
diff --git a/include/ruby/internal/static_assert.h b/include/ruby/internal/static_assert.h
index b9ff6646e7..30bfd3bb79 100644
--- a/include/ruby/internal/static_assert.h
+++ b/include/ruby/internal/static_assert.h
@@ -23,13 +23,14 @@
#include <assert.h>
#include "ruby/internal/has/extension.h"
#include "ruby/internal/compiler_since.h"
+#include "ruby/internal/attr/maybe_unused.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)
+#elif defined(__cplusplus) && RBIMPL_COMPILER_IS(MSVC)
# define RBIMPL_STATIC_ASSERT0 static_assert
#elif defined(__INTEL_CXX11_MODE__)
@@ -71,7 +72,7 @@
#else
# define RBIMPL_STATIC_ASSERT(name, expr) \
- MAYBE_UNUSED(typedef int static_assert_ ## name ## _check[1 - 2 * !(expr)])
+ RBIMPL_ATTR_MAYBE_UNUSED() typedef int static_assert_ ## name ## _check[1 - 2 * !(expr)]
#endif
#endif /* RBIMPL_STATIC_ASSERT_H */
diff --git a/include/ruby/internal/stdbool.h b/include/ruby/internal/stdbool.h
index 1ca61136ba..5d9026434b 100644
--- a/include/ruby/internal/stdbool.h
+++ b/include/ruby/internal/stdbool.h
@@ -27,25 +27,13 @@
#elif defined(__cplusplus)
# /* bool is a keyword in C++. */
-# if defined(HAVE_STDBOOL_H) && (__cplusplus >= 201103L)
-# include <cstdbool>
-# endif
-#
# ifndef __bool_true_false_are_defined
# define __bool_true_false_are_defined
# endif
-#elif defined(HAVE_STDBOOL_H)
-# /* Take stdbool.h definition. */
+#else
+# /* Take stdbool.h definition. It exists since GCC 3.0 and VS 2015. */
# include <stdbool.h>
-
-#elif !defined(HAVE__BOOL)
-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/include/ruby/internal/symbol.h b/include/ruby/internal/symbol.h
index 869a31115c..8bfd686fbe 100644
--- a/include/ruby/internal/symbol.h
+++ b/include/ruby/internal/symbol.h
@@ -101,12 +101,11 @@ ID rb_intern(const char *name);
ID rb_intern2(const char *name, long len);
/**
- * Identical to rb_intern(), except it takes an instance of ::rb_cString.
+ * Identical to rb_intern(), except it takes a `T_STRING` object.
*
* @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.
+ * @pre `rb_type(str)` must be `T_STRING`.
+ * @exception rb_eEncodingError `str` contains invalid character(s).
* @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
@@ -121,10 +120,17 @@ 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 NULL Unknown id.
* @retval otherwise A name that the id represents.
* @note The return value is managed by the interpreter. Don't pass it
* to free().
+ * @note The underlying name can contain internal NUL bytes, so the return
+ * value might be a truncated representation due to the nature of C
+ * strings.
+ * @note This C string is backed by an underlying Ruby string. The Ruby
+ * string may move during GC compaction which would make this
+ * C string point to invalid memory. Do not use the return value
+ * of this function after a potential GC entry point.
*/
const char *rb_id2name(ID id);
@@ -159,34 +165,40 @@ RBIMPL_ATTR_NONNULL(())
* 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.
+ * @exception rb_eEncodingError Given string contains invalid character(s).
* @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 rb_str_to_str
* @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
+ * Identical to rb_intern_str(), except it tries to convert the parameter object
+ * to an instance of ::rb_cString or its subclasses.
*
- * :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.
+ * @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_eEncodingError Given string contains invalid character(s).
+ * @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.
+ * @see rb_str_to_str
*/
ID rb_to_id(VALUE str);
/**
- * Identical to rb_id2name(), except it returns a Ruby's String instead of C's.
+ * Identical to rb_id2name(), except it returns a frozen Ruby String instead of
+ * a C String.
*
* @param[in] id An id to query.
* @retval RUBY_Qfalse No such id ever existed in the history.
@@ -201,14 +213,14 @@ ID rb_to_id(VALUE str);
VALUE rb_id2str(ID id);
/**
- * Identical to rb_id2str(), except it takes an instance of ::rb_cSymbol rather
- * than an ::ID.
+ * Obtain a frozen string representation of a symbol (not including the leading
+ * colon). Done without any object allocations.
*
- * @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.
+ * @param[in] symbol A ::rb_cSymbol instance to query.
+ * @return A frozen instance of ::rb_cString with the name of `symbol`.
+ * @note This does not create a permanent ::ID using the symbol.
*/
-VALUE rb_sym2str(VALUE id);
+VALUE rb_sym2str(VALUE symbol);
/**
* Identical to rb_intern_str(), except it generates a dynamic symbol if
@@ -237,17 +249,14 @@ RBIMPL_ATTR_NONNULL(())
* 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.
+ * @exception rb_eEncodingError Given string contains invalid character(s).
* @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.
+ * @see rb_str_to_str
*/
VALUE rb_check_symbol(volatile VALUE *namep);
RBIMPL_SYMBOL_EXPORT_END()
@@ -308,8 +317,9 @@ rbimpl_intern_const(ID *ptr, const char *str)
}
/**
- * Old implementation detail of rb_intern().
- * @deprecated Does anyone use it? Preserved for backward compat.
+ * Returns the cached ID for the given str in var, in compiler
+ * independent manner. Use this instead of GCC specific rb_intern()
+ * when you want to cache the ID on all platforms certainly.
*/
#define RUBY_CONST_ID(var, str) \
do { \
@@ -318,7 +328,8 @@ rbimpl_intern_const(ID *ptr, const char *str)
} while (0)
#if defined(HAVE_STMT_AND_DECL_IN_EXPR)
-/* __builtin_constant_p and statement expression is available
+/* GCC specific shorthand for RUBY_CONST_ID().
+ * __builtin_constant_p and statement expression is available
* since gcc-2.7.2.3 at least. */
#define rb_intern(str) \
(RBIMPL_CONSTANT_P(str) ? \
diff --git a/include/ruby/internal/value_type.h b/include/ruby/internal/value_type.h
index 557f18813b..b47d8afb97 100644
--- a/include/ruby/internal/value_type.h
+++ b/include/ruby/internal/value_type.h
@@ -96,10 +96,11 @@
#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)))
+#ifdef RBIMPL_VA_OPT_ARGS
+# define RBIMPL_ASSERT_TYPE(v, t) \
+ RBIMPL_ASSERT_OR_ASSUME(RB_TYPE_P(v, t), "actual type: %d", rb_type(v))
#else
-# define RBIMPL_ASSERT_TYPE Check_Type
+# define RBIMPL_ASSERT_TYPE(v, t) RBIMPL_ASSERT_OR_ASSUME(RB_TYPE_P(v, t))
#endif
/** @endcond */
@@ -129,8 +130,8 @@ ruby_value_type {
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_TRUE = 0x12, /**< @see ::RUBY_Qtrue */
+ RUBY_T_FALSE = 0x13, /**< @see ::RUBY_Qfalse */
RUBY_T_SYMBOL = 0x14, /**< @see struct ::RSymbol */
RUBY_T_FIXNUM = 0x15, /**< Integers formerly known as Fixnums. */
RUBY_T_UNDEF = 0x16, /**< @see ::RUBY_Qundef */
diff --git a/include/ruby/internal/warning_push.h b/include/ruby/internal/warning_push.h
index f5981633f8..91d62cb00d 100644
--- a/include/ruby/internal/warning_push.h
+++ b/include/ruby/internal/warning_push.h
@@ -79,7 +79,7 @@
*/
#define RBIMPL_WARNING_IGNORED(flag) __pragma(warning(disable: flag))
-#elif RBIMPL_COMPILER_SINCE(MSVC, 12, 0, 0)
+#elif RBIMPL_COMPILER_IS(MSVC)
# /* 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))
diff --git a/include/ruby/internal/xmalloc.h b/include/ruby/internal/xmalloc.h
index 57552e4e7d..132bc478ce 100644
--- a/include/ruby/internal/xmalloc.h
+++ b/include/ruby/internal/xmalloc.h
@@ -283,110 +283,6 @@ 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/include/ruby/io.h b/include/ruby/io.h
index e9dfeda5b1..ed0967abad 100644
--- a/include/ruby/io.h
+++ b/include/ruby/io.h
@@ -66,6 +66,21 @@ RBIMPL_SYMBOL_EXPORT_BEGIN()
struct stat;
struct timeval;
+#if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC)
+# define RUBY_USE_STATX 0
+#elif defined(HAVE_STRUCT_STATX_STX_BTIME)
+# define RUBY_USE_STATX 1
+struct statx;
+#else
+# define RUBY_USE_STATX 0
+#endif
+
+#if RUBY_USE_STATX
+typedef struct statx rb_io_stat_data;
+#else
+typedef struct stat rb_io_stat_data;
+#endif
+
/**
* Indicates that a timeout has occurred while performing an IO operation.
*/
@@ -137,6 +152,143 @@ struct rb_io_encoding {
VALUE ecopts;
};
+/**
+ * @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
+/**
+ * This flag means that an IO object is wrapping an "external" file descriptor,
+ * which is owned by something outside the Ruby interpreter (usually a C extension).
+ * Ruby will not close this file when the IO object is garbage collected.
+ * If this flag is set, then IO#autoclose? is false, and vice-versa.
+ *
+ * This flag was previously called FMODE_PREP internally.
+ */
+#define FMODE_EXTERNAL 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 */
+
+/** @} */
+
+enum rb_io_mode {
+ RUBY_IO_MODE_EXTERNAL = FMODE_EXTERNAL,
+
+ RUBY_IO_MODE_READABLE = FMODE_READABLE,
+ RUBY_IO_MODE_WRITABLE = FMODE_WRITABLE,
+ RUBY_IO_MODE_READABLE_WRITABLE = (RUBY_IO_MODE_READABLE|RUBY_IO_MODE_WRITABLE),
+
+ RUBY_IO_MODE_BINARY = FMODE_BINMODE,
+ RUBY_IO_MODE_TEXT = FMODE_TEXTMODE,
+ RUBY_IO_MODE_TEXT_SET_ENCODING_FROM_BOM = FMODE_SETENC_BY_BOM,
+
+ RUBY_IO_MODE_SYNCHRONISED = FMODE_SYNC,
+
+ RUBY_IO_MODE_TTY = FMODE_TTY,
+
+ RUBY_IO_MODE_DUPLEX = FMODE_DUPLEX,
+
+ RUBY_IO_MODE_APPEND = FMODE_APPEND,
+ RUBY_IO_MODE_CREATE = FMODE_CREATE,
+ RUBY_IO_MODE_EXCLUSIVE = FMODE_EXCL,
+ RUBY_IO_MODE_TRUNCATE = FMODE_TRUNC,
+};
+
+typedef enum rb_io_mode rb_io_mode_t;
+
#ifndef HAVE_RB_IO_T
#define HAVE_RB_IO_T 1
/** Ruby's IO, metadata and buffers. */
@@ -155,7 +307,7 @@ struct rb_io {
/** mode flags: FMODE_XXXs */
RBIMPL_ATTR_DEPRECATED(("rb_io_mode"))
- int mode;
+ enum rb_io_mode mode;
/** child's pid (for pipes) */
RBIMPL_ATTR_DEPRECATED(("with no replacement"))
@@ -261,118 +413,6 @@ typedef struct rb_io rb_io_t;
typedef struct rb_io_encoding rb_io_enc_t;
/**
- * @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
-/**
- * This flag means that an IO object is wrapping an "external" file descriptor,
- * which is owned by something outside the Ruby interpreter (usually a C extension).
- * Ruby will not close this file when the IO object is garbage collected.
- * If this flag is set, then IO#autoclose? is false, and vice-versa.
- *
- * This flag was previously called FMODE_PREP internally.
- */
-#define FMODE_EXTERNAL 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 */
-
-/** @} */
-
-/**
* Allocate a new IO object, with the given file descriptor.
*/
VALUE rb_io_open_descriptor(VALUE klass, int descriptor, int mode, VALUE path, VALUE timeout, struct rb_io_encoding *encoding);
@@ -525,7 +565,7 @@ FILE *rb_fdopen(int fd, const char *modestr);
*
* rb_io_modestr_fmode() is not a pure function because it raises.
*/
-int rb_io_modestr_fmode(const char *modestr);
+enum rb_io_mode rb_io_modestr_fmode(const char *modestr);
/**
* Identical to rb_io_modestr_fmode(), except it returns a mixture of `O_`
@@ -780,7 +820,7 @@ int rb_io_mode(VALUE io);
* @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);
+int rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, enum rb_io_mode *fmode_p);
/**
* This function can be seen as an extended version of
@@ -849,7 +889,7 @@ int rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **
* ) -> 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);
+void rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash, int *oflags_p, enum rb_io_mode *fmode_p, rb_io_enc_t *convconfig_p);
/* :TODO: can this function be __attribute__((warn_unused_result)) or not? */
/**
@@ -964,6 +1004,9 @@ VALUE rb_io_wait(VALUE io, VALUE events, VALUE timeout);
* }
* ```
*
+ * On timeout, ::RUBY_Qfalse is returned. Unless you are specifically handling
+ * the timeouts, you should typically raise ::rb_eIOTimeoutError in this case.
+ *
* @param[in] error System errno.
* @param[in] io An IO object to wait.
* @param[in] events An integer set of interests.
@@ -972,19 +1015,19 @@ VALUE rb_io_wait(VALUE io, VALUE events, VALUE timeout);
* @exception rb_eRangeError `timeout` is out of range.
* @exception rb_eSystemCallError `select(2)` failed for some reason.
* @retval RUBY_Qfalse Operation timed out.
+ * @retval RUBY_Qnil Operation failed for some other reason (errno).
* @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.
+ * passed errno. This is a special case of rb_io_maybe_wait() that is
+ * only concerned with reading and handles the timeout.
+ *
+ * If you do not want the default timeout handling, consider using
+ * ::rb_io_maybe_wait directly.
*
* @param[in] error System errno.
* @param[in] io An IO object to wait.
@@ -992,15 +1035,18 @@ VALUE rb_io_maybe_wait(int error, VALUE io, VALUE events, VALUE timeout);
* @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 0 Operation timed out.
+ * @exception rb_eIOTimeoutError The wait operation timed out.
* @retval Otherwise Always returns ::RUBY_IO_READABLE.
*/
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.
+ * passed errno. This is a special case of rb_io_maybe_wait() that is
+ * only concerned with writing, and handles the timeout.
+ *
+ * If you do not want the default timeout handling, consider using
+ * ::rb_io_maybe_wait directly.
*
* @param[in] error System errno.
* @param[in] io An IO object to wait.
@@ -1008,7 +1054,7 @@ int rb_io_maybe_wait_readable(int error, VALUE io, VALUE timeout);
* @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 0 Operation timed out.
+ * @exception rb_eIOTimeoutError The wait operation timed out.
* @retval Otherwise Always returns ::RUBY_IO_WRITABLE.
*/
int rb_io_maybe_wait_writable(int error, VALUE io, VALUE timeout);
@@ -1067,6 +1113,18 @@ int rb_io_read_pending(rb_io_t *fptr);
*/
VALUE rb_stat_new(const struct stat *st);
+#if RUBY_USE_STATX
+/**
+ * Constructs an instance of ::rb_cStat from the passed information.
+ *
+ * @param[in] st A stat.
+ * @return Allocated new instance of ::rb_cStat.
+ */
+VALUE rb_statx_new(const rb_io_stat_data *st);
+#else
+# define rb_statx_new rb_stat_new
+#endif
+
/* gc.c */
RBIMPL_SYMBOL_EXPORT_END()
diff --git a/include/ruby/onigmo.h b/include/ruby/onigmo.h
index d233336316..9dcddee829 100644
--- a/include/ruby/onigmo.h
+++ b/include/ruby/onigmo.h
@@ -4,8 +4,8 @@
onigmo.h - Onigmo (Oniguruma-mod) (regular expression library)
**********************************************************************/
/*-
- * Copyright (c) 2002-2009 K.Kosako <sndgk393 AT ybb DOT ne DOT jp>
- * Copyright (c) 2011-2017 K.Takata <kentkt AT csc DOT jp>
+ * Copyright (c) 2002-2016 K.Kosako <sndgk393 AT ybb DOT ne DOT jp>
+ * Copyright (c) 2011-2019 K.Takata <kentkt AT csc DOT jp>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -38,8 +38,8 @@ extern "C" {
#endif
#define ONIGMO_VERSION_MAJOR 6
-#define ONIGMO_VERSION_MINOR 1
-#define ONIGMO_VERSION_TEENY 3
+#define ONIGMO_VERSION_MINOR 2
+#define ONIGMO_VERSION_TEENY 0
#ifndef ONIG_EXTERN
# ifdef RUBY_EXTERN
@@ -636,6 +636,7 @@ ONIG_EXTERN const OnigSyntaxType* OnigDefaultSyntax;
#define ONIGERR_PARSE_DEPTH_LIMIT_OVER -16
#define ONIGERR_DEFAULT_ENCODING_IS_NOT_SET -21
#define ONIGERR_SPECIFIED_ENCODING_CANT_CONVERT_TO_WIDE_CHAR -22
+#define ONIGERR_TIMEOUT -23
/* general error */
#define ONIGERR_INVALID_ARGUMENT -30
/* syntax error */
@@ -788,8 +789,8 @@ typedef struct re_pattern_buffer {
unsigned char *exact;
unsigned char *exact_end;
unsigned char map[ONIG_CHAR_TABLE_SIZE]; /* used as BM skip or char-map */
- int *int_map; /* BM skip for exact_len > 255 */
- int *int_map_backward; /* BM skip for backward search */
+ int *reserved1;
+ int *reserved2;
OnigDistance dmin; /* min-distance of exact or map */
OnigDistance dmax; /* max-distance of exact or map */
diff --git a/include/ruby/ractor.h b/include/ruby/ractor.h
index 7811616f6d..8cfca21621 100644
--- a/include/ruby/ractor.h
+++ b/include/ruby/ractor.h
@@ -217,7 +217,7 @@ VALUE rb_ractor_make_shareable(VALUE obj);
*
* @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.
+ * @return A deep copy of `obj` which is shareable among Ractors.
*/
VALUE rb_ractor_make_shareable_copy(VALUE obj);
@@ -261,4 +261,18 @@ rb_ractor_shareable_p(VALUE obj)
}
}
+// TODO: optimize on interpreter core
+#ifndef RB_OBJ_SET_SHAREABLE
+VALUE rb_obj_set_shareable(VALUE obj); // ractor.c
+#define RB_OBJ_SET_SHAREABLE(obj) rb_obj_set_shareable(obj)
+#endif
+
+static inline VALUE
+RB_OBJ_SET_FROZEN_SHAREABLE(VALUE obj)
+{
+ RB_OBJ_FREEZE(obj);
+ RB_OBJ_SET_SHAREABLE(obj);
+ return obj;
+}
+
#endif /* RUBY_RACTOR_H */
diff --git a/include/ruby/random.h b/include/ruby/random.h
index f3df0d96fb..740be6bdad 100644
--- a/include/ruby/random.h
+++ b/include/ruby/random.h
@@ -332,7 +332,9 @@ RBIMPL_ATTR_PURE_UNLESS_DEBUG()
static inline const rb_random_interface_t *
rb_rand_if(VALUE obj)
{
+ RBIMPL_ASSERT_OR_ASSUME(RB_TYPE_P(obj, T_DATA));
RBIMPL_ASSERT_OR_ASSUME(RTYPEDDATA_P(obj));
+ RUBY_ASSERT(rb_typeddata_is_kind_of(obj, &rb_random_data_type));
const struct rb_data_type_struct *t = RTYPEDDATA_TYPE(obj);
const void *ret = t->data;
return RBIMPL_CAST((const rb_random_interface_t *)ret);
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index 035f02c70b..ca794bcaeb 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -426,6 +426,21 @@ __extension__({ \
# include "ruby/backward.h"
#endif
+#ifndef RUBY__ASAN_DEFAULT_OPTIONS
+# define RUBY__ASAN_DEFAULT_OPTIONS
+#endif
+
+#define RUBY_GLOBAL_SETUP \
+ RUBY__ASAN_DEFAULT_OPTIONS \
+ /* RUBY_GLOBAL_SETUP end */
+
+#if defined(__wasm__) && !defined(__EMSCRIPTEN__)
+int rb_wasm_rt_start(int (*)(int, char **), int, char **);
+# define ruby_start_main rb_wasm_rt_start
+#else
+# define ruby_start_main(main, argc, argv) main(argc, argv)
+#endif
+
RBIMPL_SYMBOL_EXPORT_END()
#endif /* RUBY_RUBY_H */
diff --git a/include/ruby/thread.h b/include/ruby/thread.h
index 337f477fd0..2fa01229e2 100644
--- a/include/ruby/thread.h
+++ b/include/ruby/thread.h
@@ -59,6 +59,19 @@
*/
#define RB_NOGVL_UBF_ASYNC_SAFE (0x2)
+/**
+ * Passing this flag to rb_nogvl() indicates that the passed function
+ * is safe to offload to a background thread or work pool. In other words, the
+ * function is safe to run using a fiber scheduler's `blocking_operation_wait`.
+ * hook.
+ *
+ * If your function depends on thread-local storage, or thread-specific data
+ * operations/data structures, you should not set this flag, as
+ * these operations may behave differently (or fail) when run in a different
+ * thread/context (e.g. unlocking a mutex).
+ */
+#define RB_NOGVL_OFFLOAD_SAFE (0x4)
+
/** @} */
RBIMPL_SYMBOL_EXPORT_BEGIN()
@@ -320,6 +333,13 @@ void *rb_internal_thread_specific_get(VALUE thread_val, rb_internal_thread_speci
*/
void rb_internal_thread_specific_set(VALUE thread_val, rb_internal_thread_specific_key_t key, void *data);
+/**
+ * Whether the current thread is holding the GVL.
+ *
+ * @return true if the current thread is holding the GVL, false otherwise.
+ */
+int ruby_thread_has_gvl_p(void);
+
RBIMPL_SYMBOL_EXPORT_END()
#endif /* RUBY_THREAD_H */
diff --git a/include/ruby/version.h b/include/ruby/version.h
index e9113177de..5bb381cea2 100644
--- a/include/ruby/version.h
+++ b/include/ruby/version.h
@@ -61,13 +61,13 @@
* 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
+#define RUBY_API_VERSION_MAJOR 4
/**
* 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 4
+#define RUBY_API_VERSION_MINOR 1
/**
* Teeny version. This digit is kind of reserved these days. Kept 0 for the
diff --git a/include/ruby/win32.h b/include/ruby/win32.h
index 27a3467606..ae11a61481 100644
--- a/include/ruby/win32.h
+++ b/include/ruby/win32.h
@@ -30,15 +30,10 @@ extern "C++" { /* template without extern "C++" */
#if !defined(_WIN64) && !defined(WIN32)
#define WIN32
#endif
-#if defined(_MSC_VER) && _MSC_VER <= 1200
-#include <windows.h>
-#endif
#include <winsock2.h>
#include <ws2tcpip.h>
#include <mswsock.h>
-#if !defined(_MSC_VER) || _MSC_VER >= 1400
#include <iphlpapi.h>
-#endif
#if defined(__cplusplus) && defined(_MSC_VER)
}
#endif
@@ -59,13 +54,7 @@ extern "C++" { /* template without extern "C++" */
#include <direct.h>
#include <process.h>
#include <time.h>
-#if defined(__cplusplus) && defined(_MSC_VER) && _MSC_VER == 1200
-extern "C++" { /* template without extern "C++" */
-#endif
#include <math.h>
-#if defined(__cplusplus) && defined(_MSC_VER) && _MSC_VER == 1200
-}
-#endif
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -126,8 +115,30 @@ typedef unsigned int uintptr_t;
#define O_SHARE_DELETE 0x20000000 /* for rb_w32_open(), rb_w32_wopen() */
typedef int clockid_t;
-#define CLOCK_REALTIME 0
-#define CLOCK_MONOTONIC 1
+
+/*
+ * Since we use our versions in win32/win32.c, not to depend on yet
+ * another DLL, prefix our versions not to conflict with inline
+ * versions provided in time.h.
+ */
+#define clock_gettime rb_w32_clock_gettime
+#define clock_getres rb_w32_clock_getres
+
+#ifndef CLOCK_REALTIME
+# define CLOCK_REALTIME 0
+#endif
+#ifndef CLOCK_MONOTONIC
+# define CLOCK_MONOTONIC 1
+#endif
+#ifndef CLOCK_PROCESS_CPUTIME_ID
+# define CLOCK_PROCESS_CPUTIME_ID 2
+#endif
+#ifndef CLOCK_THREAD_CPUTIME_ID
+# define CLOCK_THREAD_CPUTIME_ID 3
+#endif
+#ifndef CLOCK_REALTIME_COARSE
+# define CLOCK_REALTIME_COARSE 4
+#endif
#undef utime
#undef lseek
@@ -251,7 +262,6 @@ struct ifaddrs {
#endif
extern void rb_w32_sysinit(int *, char ***);
-extern DWORD rb_w32_osid(void);
extern int flock(int fd, int oper);
extern int rb_w32_io_cancelable_p(int);
extern int rb_w32_is_socket(int);
@@ -295,7 +305,11 @@ extern void rb_w32_free_environ(char **);
extern int rb_w32_map_errno(DWORD);
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);
+
+RBIMPL_ATTR_DEPRECATED(("as Windows 9x is not supported already"))
+static inline DWORD rb_w32_osid(void) {return VER_PLATFORM_WIN32_NT;}
+RBIMPL_ATTR_DEPRECATED(("by Windows Version Helper APIs"))
+extern DWORD rb_w32_osver(void);
extern int rb_w32_uchown(const char *, int, int);
extern int rb_w32_ulink(const char *, const char *);
@@ -331,7 +345,7 @@ extern int rb_w32_dup2(int, int);
#include <float.h>
-#if defined _MSC_VER && _MSC_VER >= 1800 && defined INFINITY
+#if defined _MSC_VER && defined INFINITY
#pragma warning(push)
#pragma warning(disable:4756)
static inline float
@@ -414,11 +428,6 @@ extern int rb_w32_utruncate(const char *path, rb_off_t length);
#define HAVE_TRUNCATE 1
#define truncate rb_w32_utruncate
-#if defined(_MSC_VER) && _MSC_VER >= 1400 && _MSC_VER < 1800
-#define strtoll _strtoi64
-#define strtoull _strtoui64
-#endif
-
/*
* stubs
*/
diff --git a/inits.c b/inits.c
index 677a384f9a..4988fa09d0 100644
--- a/inits.c
+++ b/inits.c
@@ -52,6 +52,8 @@ rb_call_inits(void)
CALL(Time);
CALL(Random);
CALL(load);
+ CALL(Ruby_module);
+ CALL(Box);
CALL(Proc);
CALL(Binding);
CALL(Math);
@@ -63,18 +65,21 @@ rb_call_inits(void)
CALL(ISeq);
CALL(Thread);
CALL(signal);
+ CALL(Cont);
CALL(Fiber_Scheduler);
CALL(process);
- CALL(Cont);
CALL(Rational);
CALL(Complex);
CALL(MemoryView);
+ CALL(pathname);
CALL(version);
CALL(vm_trace);
CALL(vm_stack_canary);
CALL(ast);
CALL(shape);
CALL(Prism);
+ CALL(unicode_version);
+ CALL(Set);
// enable builtin loading
CALL(builtin);
@@ -84,6 +89,10 @@ void
rb_call_builtin_inits(void)
{
#define BUILTIN(n) CALL(builtin_##n)
+ BUILTIN(jit_hook);
+ BUILTIN(yjit);
+ BUILTIN(zjit);
+ BUILTIN(kernel);
BUILTIN(gc);
BUILTIN(ractor);
BUILTIN(numeric);
@@ -92,19 +101,16 @@ rb_call_builtin_inits(void)
BUILTIN(ast);
BUILTIN(trace_point);
BUILTIN(pack);
+ BUILTIN(pathname_builtin);
BUILTIN(warning);
BUILTIN(array);
- BUILTIN(kernel);
+ BUILTIN(hash);
BUILTIN(symbol);
BUILTIN(timev);
BUILTIN(thread_sync);
- BUILTIN(yjit);
BUILTIN(nilclass);
BUILTIN(marshal);
-#if USE_RJIT
- BUILTIN(rjit_c);
- BUILTIN(rjit);
-#endif
+ BUILTIN(jit_undef);
Init_builtin_prelude();
}
#undef CALL
diff --git a/insns.def b/insns.def
index f7df92cf06..ceeaf4128e 100644
--- a/insns.def
+++ b/insns.def
@@ -212,6 +212,7 @@ getinstancevariable
(VALUE val)
/* Ractor crashes when it accesses class/module-level instances variables. */
// attr bool leaf = false; /* has IVAR_ACCESSOR_SHOULD_BE_MAIN_RACTOR() */
+// attr bool zjit_profile = true;
{
val = vm_getinstancevariable(GET_ISEQ(), GET_SELF(), id, ic);
}
@@ -223,6 +224,7 @@ setinstancevariable
(VALUE val)
()
// attr bool leaf = false; /* has rb_check_frozen() */
+// attr bool zjit_profile = true;
{
vm_setinstancevariable(GET_ISEQ(), GET_SELF(), id, val, ic);
}
@@ -452,26 +454,6 @@ newarray
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
- should be at least one element on the stack, and the top element
- should be a hash. If the top element is empty, it is not
- included in the array.
- */
-DEFINE_INSN
-newarraykwsplat
-(rb_num_t num)
-(...)
-(VALUE val)
-// attr rb_snum_t sp_inc = 1 - (rb_snum_t)num;
-{
- if (RHASH_EMPTY_P(*STACK_ADDR_FROM_TOP(1))) {
- val = rb_ary_new4(num-1, STACK_ADDR_FROM_TOP(num));
- }
- else {
- val = rb_ary_new4(num, STACK_ADDR_FROM_TOP(num));
- }
-}
-
/* push hash onto array unless the hash is empty (as empty keyword
splats should be ignored).
*/
@@ -764,6 +746,7 @@ definedivar
()
(VALUE val)
// attr bool leaf = false;
+// attr bool zjit_profile = true;
{
val = Qnil;
if (!UNDEF_P(vm_getivar(GET_SELF(), id, GET_ISEQ(), ic, NULL, FALSE, Qundef))) {
@@ -822,12 +805,13 @@ defineclass
(VALUE val)
{
VALUE klass = vm_find_or_create_class_by_id(id, flags, cbase, super);
+ const rb_box_t *box = rb_current_box();
rb_iseq_check(class_iseq);
/* enter scope */
vm_push_frame(ec, class_iseq, VM_FRAME_MAGIC_CLASS | VM_ENV_FLAG_LOCAL, klass,
- GET_BLOCK_HANDLER(),
+ GC_GUARDED_PTR(box),
(VALUE)vm_cref_push(ec, klass, NULL, FALSE, FALSE),
ISEQ_BODY(class_iseq)->iseq_encoded, GET_SP(),
ISEQ_BODY(class_iseq)->local_table_size,
@@ -864,6 +848,7 @@ send
(CALL_DATA cd, ISEQ blockiseq)
(...)
(VALUE val)
+// attr bool zjit_profile = true;
// attr rb_snum_t sp_inc = sp_inc_of_sendish(cd->ci);
// attr rb_snum_t comptime_sp_inc = sp_inc_of_sendish(ci);
{
@@ -877,12 +862,40 @@ send
}
}
+/* invoke forward method. */
+DEFINE_INSN
+sendforward
+(CALL_DATA cd, ISEQ blockiseq)
+(...)
+(VALUE val)
+// attr rb_snum_t sp_inc = sp_inc_of_sendish(cd->ci);
+// attr rb_snum_t comptime_sp_inc = sp_inc_of_sendish(ci);
+{
+ struct rb_forwarding_call_data adjusted_cd;
+ struct rb_callinfo adjusted_ci;
+
+ VALUE bh = vm_caller_setup_fwd_args(ec, GET_CFP(), cd, blockiseq, 0, &adjusted_cd, &adjusted_ci);
+
+ val = vm_sendish(ec, GET_CFP(), &adjusted_cd.cd, bh, mexp_search_method);
+ JIT_EXEC(ec, val);
+
+ if (cd->cc != adjusted_cd.cd.cc && vm_cc_markable(adjusted_cd.cd.cc)) {
+ RB_OBJ_WRITE(GET_ISEQ(), &cd->cc, adjusted_cd.cd.cc);
+ }
+
+ if (UNDEF_P(val)) {
+ RESTORE_REGS();
+ NEXT_INSN();
+ }
+}
+
/* Invoke method without block */
DEFINE_INSN
opt_send_without_block
(CALL_DATA cd)
(...)
(VALUE val)
+// attr bool zjit_profile = true;
// attr bool handles_sp = true;
// attr rb_snum_t sp_inc = sp_inc_of_sendish(cd->ci);
// attr rb_snum_t comptime_sp_inc = sp_inc_of_sendish(ci);
@@ -897,6 +910,32 @@ opt_send_without_block
}
}
+/* Jump if "new" method has been defined by user */
+DEFINE_INSN
+opt_new
+(CALL_DATA cd, OFFSET dst)
+()
+()
+// attr bool leaf = false;
+{
+ VALUE argc = vm_ci_argc(cd->ci);
+ VALUE val = TOPN(argc);
+
+ // The bookkeeping slot should be empty.
+ RUBY_ASSERT(TOPN(argc + 1) == Qnil);
+
+ if (vm_method_cfunc_is(GET_ISEQ(), cd, val, rb_class_new_instance_pass_kw)) {
+ RB_DEBUG_COUNTER_INC(opt_new_hit);
+ val = rb_obj_alloc(val);
+ TOPN(argc) = val;
+ TOPN(argc + 1) = val;
+ }
+ else {
+ RB_DEBUG_COUNTER_INC(opt_new_miss);
+ JUMP(dst);
+ }
+}
+
/* Convert object to string using to_s or equivalent. */
DEFINE_INSN
objtostring
@@ -904,6 +943,7 @@ objtostring
(VALUE recv)
(VALUE val)
// attr bool leaf = false;
+// attr bool zjit_profile = true;
{
val = vm_objtostring(GET_ISEQ(), recv, cd);
@@ -913,6 +953,36 @@ objtostring
}
DEFINE_INSN
+opt_ary_freeze
+(VALUE ary, CALL_DATA cd)
+()
+(VALUE val)
+{
+ val = vm_opt_ary_freeze(ary, BOP_FREEZE, idFreeze);
+
+ if (UNDEF_P(val)) {
+ RUBY_DTRACE_CREATE_HOOK(ARRAY, RARRAY_LEN(ary));
+ PUSH(rb_ary_resurrect(ary));
+ CALL_SIMPLE_METHOD();
+ }
+}
+
+DEFINE_INSN
+opt_hash_freeze
+(VALUE hash, CALL_DATA cd)
+()
+(VALUE val)
+{
+ val = vm_opt_hash_freeze(hash, BOP_FREEZE, idFreeze);
+
+ if (UNDEF_P(val)) {
+ RUBY_DTRACE_CREATE_HOOK(HASH, RHASH_SIZE(hash) << 1);
+ PUSH(rb_hash_resurrect(hash));
+ CALL_SIMPLE_METHOD();
+ }
+}
+
+DEFINE_INSN
opt_str_freeze
(VALUE str, CALL_DATA cd)
()
@@ -932,6 +1002,7 @@ opt_nil_p
(CALL_DATA cd)
(VALUE recv)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_nil_p(GET_ISEQ(), cd, recv);
@@ -955,8 +1026,30 @@ opt_str_uminus
}
DEFINE_INSN
+opt_duparray_send
+(VALUE ary, ID method, rb_num_t argc)
+(...)
+(VALUE val)
+/* This instruction typically has no funcalls. But it may compare array
+ * contents to each other which may call methods when necessary.
+ * No way to detect such method calls beforehand.
+ * We must mark it as not leaf. */
+// attr bool leaf = false; /* has rb_funcall() */
+// attr rb_snum_t sp_inc = 1 - (rb_snum_t)argc;
+// attr rb_snum_t comptime_sp_inc = 1 - (rb_snum_t)argc;
+{
+ switch (method) {
+ case idIncludeP:
+ val = vm_opt_duparray_include_p(ec, ary, TOPN(0));
+ break;
+ default:
+ rb_bug("unreachable");
+ }
+}
+
+DEFINE_INSN
opt_newarray_send
-(rb_num_t num, ID method)
+(rb_num_t num, rb_num_t method)
(...)
(VALUE val)
/* This instruction typically has no funcalls. But it compares array
@@ -967,18 +1060,24 @@ opt_newarray_send
// attr rb_snum_t sp_inc = 1 - (rb_snum_t)num;
// attr rb_snum_t comptime_sp_inc = 1 - (rb_snum_t)num;
{
- switch(method) {
- case idHash:
+ switch (method) {
+ case VM_OPT_NEWARRAY_SEND_HASH:
val = vm_opt_newarray_hash(ec, num, STACK_ADDR_FROM_TOP(num));
break;
- case idMin:
+ case VM_OPT_NEWARRAY_SEND_MIN:
val = vm_opt_newarray_min(ec, num, STACK_ADDR_FROM_TOP(num));
break;
- case idMax:
+ case VM_OPT_NEWARRAY_SEND_MAX:
val = vm_opt_newarray_max(ec, num, STACK_ADDR_FROM_TOP(num));
break;
- case idPack:
- val = rb_vm_opt_newarray_pack(ec, (long)num-1, STACK_ADDR_FROM_TOP(num), TOPN(0));
+ case VM_OPT_NEWARRAY_SEND_INCLUDE_P:
+ val = vm_opt_newarray_include_p(ec, (long)num-1, STACK_ADDR_FROM_TOP(num), TOPN(0));
+ break;
+ case VM_OPT_NEWARRAY_SEND_PACK:
+ val = vm_opt_newarray_pack_buffer(ec, (long)num-1, STACK_ADDR_FROM_TOP(num), TOPN(0), Qundef);
+ break;
+ case VM_OPT_NEWARRAY_SEND_PACK_BUFFER:
+ val = vm_opt_newarray_pack_buffer(ec, (long)num-2, STACK_ADDR_FROM_TOP(num), TOPN(1), TOPN(0));
break;
default:
rb_bug("unreachable");
@@ -993,6 +1092,7 @@ invokesuper
(VALUE val)
// attr rb_snum_t sp_inc = sp_inc_of_sendish(cd->ci);
// attr rb_snum_t comptime_sp_inc = sp_inc_of_sendish(ci);
+// attr bool zjit_profile = true;
{
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);
@@ -1004,6 +1104,33 @@ invokesuper
}
}
+/* super(args) # args.size => num */
+DEFINE_INSN
+invokesuperforward
+(CALL_DATA cd, ISEQ blockiseq)
+(...)
+(VALUE val)
+// attr rb_snum_t sp_inc = sp_inc_of_sendish(cd->ci);
+// attr rb_snum_t comptime_sp_inc = sp_inc_of_sendish(ci);
+{
+ struct rb_forwarding_call_data adjusted_cd;
+ struct rb_callinfo adjusted_ci;
+
+ VALUE bh = vm_caller_setup_fwd_args(ec, GET_CFP(), cd, blockiseq, 1, &adjusted_cd, &adjusted_ci);
+
+ val = vm_sendish(ec, GET_CFP(), &adjusted_cd.cd, bh, mexp_search_super);
+ JIT_EXEC(ec, val);
+
+ if (cd->cc != adjusted_cd.cd.cc && vm_cc_markable(adjusted_cd.cd.cc)) {
+ RB_OBJ_WRITE(GET_ISEQ(), &cd->cc, adjusted_cd.cd.cc);
+ }
+
+ if (UNDEF_P(val)) {
+ RESTORE_REGS();
+ NEXT_INSN();
+ }
+}
+
/* yield(args) */
DEFINE_INSN
invokeblock
@@ -1013,6 +1140,7 @@ invokeblock
// attr bool handles_sp = true;
// attr rb_snum_t sp_inc = sp_inc_of_invokeblock(cd->ci);
// attr rb_snum_t comptime_sp_inc = sp_inc_of_invokeblock(ci);
+// attr bool zjit_profile = true;
{
VALUE bh = VM_BLOCK_HANDLER_NONE;
val = vm_sendish(ec, GET_CFP(), cd, bh, mexp_search_invokeblock);
@@ -1085,7 +1213,7 @@ jump
()
()
/* Same discussion as leave. */
-// attr bool leaf = leafness_of_check_ints; /* has rb_threadptr_execute_interrupts() */
+// attr bool leaf = false; /* has rb_threadptr_execute_interrupts() */
{
RUBY_VM_CHECK_INTS(ec);
JUMP(dst);
@@ -1098,7 +1226,7 @@ branchif
(VALUE val)
()
/* Same discussion as jump. */
-// attr bool leaf = leafness_of_check_ints; /* has rb_threadptr_execute_interrupts() */
+// attr bool leaf = false; /* has rb_threadptr_execute_interrupts() */
{
if (RTEST(val)) {
RUBY_VM_CHECK_INTS(ec);
@@ -1113,7 +1241,7 @@ branchunless
(VALUE val)
()
/* Same discussion as jump. */
-// attr bool leaf = leafness_of_check_ints; /* has rb_threadptr_execute_interrupts() */
+// attr bool leaf = false; /* has rb_threadptr_execute_interrupts() */
{
if (!RTEST(val)) {
RUBY_VM_CHECK_INTS(ec);
@@ -1128,7 +1256,7 @@ branchnil
(VALUE val)
()
/* Same discussion as jump. */
-// attr bool leaf = leafness_of_check_ints; /* has rb_threadptr_execute_interrupts() */
+// attr bool leaf = false; /* has rb_threadptr_execute_interrupts() */
{
if (NIL_P(val)) {
RUBY_VM_CHECK_INTS(ec);
@@ -1173,6 +1301,7 @@ opt_plus
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_plus(recv, obj);
@@ -1187,6 +1316,7 @@ opt_minus
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_minus(recv, obj);
@@ -1201,6 +1331,7 @@ opt_mult
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_mult(recv, obj);
@@ -1218,6 +1349,7 @@ opt_div
/* In case of division by zero, it raises. Thus
* ZeroDivisionError#initialize is called. */
// attr bool leaf = false;
+// attr bool zjit_profile = true;
{
val = vm_opt_div(recv, obj);
@@ -1234,6 +1366,7 @@ opt_mod
(VALUE val)
/* Same discussion as opt_div. */
// attr bool leaf = false;
+// attr bool zjit_profile = true;
{
val = vm_opt_mod(recv, obj);
@@ -1248,6 +1381,7 @@ opt_eq
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = opt_equality(GET_ISEQ(), recv, obj, cd);
@@ -1262,6 +1396,7 @@ opt_neq
(CALL_DATA cd_eq, CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_neq(GET_ISEQ(), cd, cd_eq, recv, obj);
@@ -1276,6 +1411,7 @@ opt_lt
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_lt(recv, obj);
@@ -1290,6 +1426,7 @@ opt_le
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_le(recv, obj);
@@ -1304,6 +1441,7 @@ opt_gt
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_gt(recv, obj);
@@ -1318,6 +1456,7 @@ opt_ge
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_ge(recv, obj);
@@ -1336,6 +1475,7 @@ opt_ltlt
* string. Then what happens if that codepoint does not exist in the
* string's encoding? Of course an exception. That's not a leaf. */
// attr bool leaf = false; /* has "invalid codepoint" exception */
+// attr bool zjit_profile = true;
{
val = vm_opt_ltlt(recv, obj);
@@ -1350,6 +1490,7 @@ opt_and
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_and(recv, obj);
@@ -1364,6 +1505,7 @@ opt_or
(CALL_DATA cd)
(VALUE recv, VALUE obj)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_or(recv, obj);
@@ -1383,6 +1525,7 @@ opt_aref
* default_proc. This is a method call. So opt_aref is
* (surprisingly) not leaf. */
// attr bool leaf = false; /* has rb_funcall() */ /* calls #yield */
+// attr bool zjit_profile = true;
{
val = vm_opt_aref(recv, obj);
@@ -1400,6 +1543,7 @@ opt_aset
/* This is another story than opt_aref. When vm_opt_aset() resorts
* to rb_hash_aset(), which should call #hash for `obj`. */
// attr bool leaf = false; /* has rb_funcall() */ /* calls #hash */
+// attr bool zjit_profile = true;
{
val = vm_opt_aset(recv, obj, set);
@@ -1408,50 +1552,13 @@ opt_aset
}
}
-/* recv[str] = set */
-DEFINE_INSN
-opt_aset_with
-(VALUE key, CALL_DATA cd)
-(VALUE recv, VALUE val)
-(VALUE val)
-/* Same discussion as opt_aset. */
-// attr bool leaf = false; /* has rb_funcall() */ /* calls #hash */
-{
- VALUE tmp = vm_opt_aset_with(recv, key, val);
-
- if (!UNDEF_P(tmp)) {
- val = tmp;
- }
- else {
- TOPN(0) = rb_str_resurrect(key);
- PUSH(val);
- CALL_SIMPLE_METHOD();
- }
-}
-
-/* recv[str] */
-DEFINE_INSN
-opt_aref_with
-(VALUE key, CALL_DATA cd)
-(VALUE recv)
-(VALUE val)
-/* Same discussion as opt_aref. */
-// attr bool leaf = false; /* has rb_funcall() */ /* calls #yield */
-{
- val = vm_opt_aref_with(recv, key);
-
- if (UNDEF_P(val)) {
- PUSH(rb_str_resurrect(key));
- CALL_SIMPLE_METHOD();
- }
-}
-
/* optimized length */
DEFINE_INSN
opt_length
(CALL_DATA cd)
(VALUE recv)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_length(recv, BOP_LENGTH);
@@ -1466,6 +1573,7 @@ opt_size
(CALL_DATA cd)
(VALUE recv)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_length(recv, BOP_SIZE);
@@ -1480,6 +1588,7 @@ opt_empty_p
(CALL_DATA cd)
(VALUE recv)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_empty_p(recv);
@@ -1494,6 +1603,7 @@ opt_succ
(CALL_DATA cd)
(VALUE recv)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_succ(recv);
@@ -1508,6 +1618,7 @@ opt_not
(CALL_DATA cd)
(VALUE recv)
(VALUE val)
+// attr bool zjit_profile = true;
{
val = vm_opt_not(GET_ISEQ(), cd, recv);
@@ -1523,6 +1634,7 @@ opt_regexpmatch2
(VALUE obj2, VALUE obj1)
(VALUE val)
// attr bool leaf = false; /* match_at() has rb_thread_check_ints() */
+// attr bool zjit_profile = true;
{
val = vm_opt_regexpmatch2(obj2, obj1);
diff --git a/internal.h b/internal.h
index 4fb99d1c08..002044cfa1 100644
--- a/internal.h
+++ b/internal.h
@@ -58,9 +58,6 @@
/* internal/array.h */
#define rb_ary_new_from_args(...) rb_nonexistent_symbol(__VA_ARGS__)
-/* internal/io.h */
-#define rb_io_fptr_finalize(...) rb_nonexistent_symbol(__VA_ARGS__)
-
/* internal/string.h */
#define rb_fstring_cstr(...) rb_nonexistent_symbol(__VA_ARGS__)
diff --git a/internal/array.h b/internal/array.h
index 39f6fcbea6..3a689646fb 100644
--- a/internal/array.h
+++ b/internal/array.h
@@ -37,6 +37,7 @@ size_t rb_ary_size_as_embedded(VALUE ary);
void rb_ary_make_embedded(VALUE ary);
bool rb_ary_embeddable_p(VALUE ary);
VALUE rb_ary_diff(VALUE ary1, VALUE ary2);
+RUBY_EXTERN VALUE rb_cArray_empty_frozen;
static inline VALUE rb_ary_entry_internal(VALUE ary, long offset);
static inline bool ARY_PTR_USING_P(VALUE ary);
@@ -139,6 +140,8 @@ RARRAY_AREF(VALUE ary, long i)
VALUE val;
RBIMPL_ASSERT_TYPE(ary, RUBY_T_ARRAY);
+ RUBY_ASSERT(i < RARRAY_LEN(ary));
+
RBIMPL_WARNING_PUSH();
#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ == 13
RBIMPL_WARNING_IGNORED(-Warray-bounds);
diff --git a/internal/basic_operators.h b/internal/basic_operators.h
index 4732a65403..493d2fa7f7 100644
--- a/internal/basic_operators.h
+++ b/internal/basic_operators.h
@@ -24,6 +24,7 @@ enum ruby_basic_operators {
BOP_SUCC,
BOP_GT,
BOP_GE,
+ BOP_GTGT,
BOP_NOT,
BOP_NEQ,
BOP_MATCH,
@@ -38,6 +39,7 @@ enum ruby_basic_operators {
BOP_CMP,
BOP_DEFAULT,
BOP_PACK,
+ BOP_INCLUDE_P,
BOP_LAST_
};
diff --git a/internal/bignum.h b/internal/bignum.h
index db8d3aee83..0692bafed3 100644
--- a/internal/bignum.h
+++ b/internal/bignum.h
@@ -9,6 +9,7 @@
* @brief Internal header for Bignums.
*/
#include "ruby/internal/config.h" /* for HAVE_LIBGMP */
+#include "internal/compilers.h" /* for FLEX_ARY_LEN */
#include <stddef.h> /* for size_t */
#ifdef HAVE_SYS_TYPES_H
@@ -76,18 +77,17 @@
#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
+
+/* This is likely more bits than we need today and will also need adjustment if
+ * we change GC slot sizes.
+ */
+#define BIGNUM_EMBED_LEN_NUMBITS 9
#define BIGNUM_EMBED_LEN_MASK \
- (~(~(VALUE)0U << BIGNUM_EMBED_LEN_NUMBITS) << BIGNUM_EMBED_LEN_SHIFT)
+ (RUBY_FL_USER11 | RUBY_FL_USER10 | RUBY_FL_USER9 | RUBY_FL_USER8 | RUBY_FL_USER7 | \
+ RUBY_FL_USER6 | RUBY_FL_USER5 | RUBY_FL_USER4 | RUBY_FL_USER3)
#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
+#define BIGNUM_EMBED_LEN_MAX (BIGNUM_EMBED_LEN_MASK >> BIGNUM_EMBED_LEN_SHIFT)
enum rb_int_parse_flags {
RB_INT_PARSE_SIGN = 0x01,
@@ -104,7 +104,12 @@ struct RBignum {
size_t len;
BDIGIT *digits;
} heap;
- BDIGIT ary[BIGNUM_EMBED_LEN_MAX];
+ /* 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
+ */
+ BDIGIT ary[1];
} as;
};
@@ -121,6 +126,7 @@ 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_aref2(VALUE num, VALUE beg, VALUE len);
VALUE rb_big_abs(VALUE x);
VALUE rb_big_size_m(VALUE big);
VALUE rb_big_bit_length(VALUE big);
@@ -163,7 +169,13 @@ VALUE rb_str2big_gmp(VALUE arg, int base, int badcheck);
VALUE rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits, int base, int flags);
RUBY_SYMBOL_EXPORT_END
+#if HAVE_LONG_LONG
+VALUE rb_ull2big(unsigned LONG_LONG n);
+VALUE rb_ll2big(LONG_LONG n);
+#endif
+
#if defined(HAVE_INT128_T)
+VALUE rb_uint128t2big(uint128_t n);
VALUE rb_int128t2big(int128_t n);
#endif
diff --git a/internal/bits.h b/internal/bits.h
index 1fe98fa430..698ab3e219 100644
--- a/internal/bits.h
+++ b/internal/bits.h
@@ -30,13 +30,13 @@
#include <stdint.h> /* for uintptr_t */
#include "internal/compilers.h" /* for MSC_VERSION_SINCE */
-#if MSC_VERSION_SINCE(1310)
+#ifdef _MSC_VER
# include <stdlib.h> /* for _byteswap_uint64 */
#endif
#if defined(HAVE_X86INTRIN_H)
# include <x86intrin.h> /* for _lzcnt_u64 */
-#elif MSC_VERSION_SINCE(1310)
+#elif defined(_MSC_VER)
# include <intrin.h> /* for the following intrinsics */
#endif
@@ -50,16 +50,13 @@
# pragma intrinsic(__lzcnt64)
#endif
-#if MSC_VERSION_SINCE(1310)
+#if defined(_MSC_VER)
# 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
@@ -90,6 +87,7 @@
#define UNSIGNED_INTEGER_MAX(T) ((T)~(T)0)
+#ifndef MUL_OVERFLOW_SIGNED_INTEGER_P
#if __has_builtin(__builtin_mul_overflow_p)
# define MUL_OVERFLOW_P(a, b) \
__builtin_mul_overflow_p((a), (b), (__typeof__(a * b))0)
@@ -131,6 +129,87 @@
# 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
+#endif
+
+#ifndef ADD_OVERFLOW_SIGNED_INTEGER_P
+#if __has_builtin(__builtin_add_overflow_p)
+# define ADD_OVERFLOW_P(a, b) \
+ __builtin_add_overflow_p((a), (b), (__typeof__(a * b))0)
+#elif __has_builtin(__builtin_add_overflow)
+# define ADD_OVERFLOW_P(a, b) \
+ __extension__ ({ __typeof__(a) c; __builtin_add_overflow((a), (b), &c); })
+#endif
+
+#define ADD_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max) ( \
+ (a) > 0 ? (b) > (max) - (a) : (b) < (min) - (a))
+
+#if __has_builtin(__builtin_add_overflow_p)
+/* __builtin_add_overflow_p can take bitfield */
+/* and GCC permits bitfields for integers other than int */
+# define ADD_OVERFLOW_FIXNUM_P(a, b) \
+ __extension__ ({ \
+ struct { long fixnum : sizeof(long) * CHAR_BIT - 1; } c = { 0 }; \
+ __builtin_add_overflow_p((a), (b), c.fixnum); \
+ })
+#else
+# define ADD_OVERFLOW_FIXNUM_P(a, b) \
+ ADD_OVERFLOW_SIGNED_INTEGER_P(a, b, FIXNUM_MIN, FIXNUM_MAX)
+#endif
+
+#if defined(ADD_OVERFLOW_P) && defined(USE___BUILTIN_ADD_OVERFLOW_LONG_LONG)
+# define ADD_OVERFLOW_LONG_LONG_P(a, b) ADD_OVERFLOW_P(a, b)
+#else
+# define ADD_OVERFLOW_LONG_LONG_P(a, b) ADD_OVERFLOW_SIGNED_INTEGER_P(a, b, LLONG_MIN, LLONG_MAX)
+#endif
+
+#ifdef ADD_OVERFLOW_P
+# define ADD_OVERFLOW_LONG_P(a, b) ADD_OVERFLOW_P(a, b)
+# define ADD_OVERFLOW_INT_P(a, b) ADD_OVERFLOW_P(a, b)
+#else
+# define ADD_OVERFLOW_LONG_P(a, b) ADD_OVERFLOW_SIGNED_INTEGER_P(a, b, LONG_MIN, LONG_MAX)
+# define ADD_OVERFLOW_INT_P(a, b) ADD_OVERFLOW_SIGNED_INTEGER_P(a, b, INT_MIN, INT_MAX)
+#endif
+#endif
+
+#ifndef SUB_OVERFLOW_SIGNED_INTEGER_P
+#if __has_builtin(__builtin_sub_overflow_p)
+# define SUB_OVERFLOW_P(a, b) \
+ __builtin_sub_overflow_p((a), (b), (__typeof__(a * b))0)
+#elif __has_builtin(__builtin_sub_overflow)
+# define SUB_OVERFLOW_P(a, b) \
+ __extension__ ({ __typeof__(a) c; __builtin_sub_overflow((a), (b), &c); })
+#endif
+
+#define SUB_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max) ( \
+ (b) > 0 ? (a) < (min) + (b) : (a) > (max) + (b))
+
+#if __has_builtin(__builtin_sub_overflow_p)
+/* __builtin_sub_overflow_p can take bitfield */
+/* and GCC permits bitfields for integers other than int */
+# define SUB_OVERFLOW_FIXNUM_P(a, b) \
+ __extension__ ({ \
+ struct { long fixnum : sizeof(long) * CHAR_BIT - 1; } c = { 0 }; \
+ __builtin_sub_overflow_p((a), (b), c.fixnum); \
+ })
+#else
+# define SUB_OVERFLOW_FIXNUM_P(a, b) \
+ SUB_OVERFLOW_SIGNED_INTEGER_P(a, b, FIXNUM_MIN, FIXNUM_MAX)
+#endif
+
+#if defined(SUB_OVERFLOW_P) && defined(USE___BUILTIN_SUB_OVERFLOW_LONG_LONG)
+# define SUB_OVERFLOW_LONG_LONG_P(a, b) SUB_OVERFLOW_P(a, b)
+#else
+# define SUB_OVERFLOW_LONG_LONG_P(a, b) SUB_OVERFLOW_SIGNED_INTEGER_P(a, b, LLONG_MIN, LLONG_MAX)
+#endif
+
+#ifdef SUB_OVERFLOW_P
+# define SUB_OVERFLOW_LONG_P(a, b) SUB_OVERFLOW_P(a, b)
+# define SUB_OVERFLOW_INT_P(a, b) SUB_OVERFLOW_P(a, b)
+#else
+# define SUB_OVERFLOW_LONG_P(a, b) SUB_OVERFLOW_SIGNED_INTEGER_P(a, b, LONG_MIN, LONG_MAX)
+# define SUB_OVERFLOW_INT_P(a, b) SUB_OVERFLOW_SIGNED_INTEGER_P(a, b, INT_MIN, INT_MAX)
+#endif
+#endif
#ifdef HAVE_UINT128_T
# define bit_length(x) \
@@ -184,7 +263,7 @@ ruby_swap16(uint16_t x)
#if __has_builtin(__builtin_bswap16)
return __builtin_bswap16(x);
-#elif MSC_VERSION_SINCE(1310)
+#elif defined(_MSC_VER)
return _byteswap_ushort(x);
#else
@@ -199,7 +278,7 @@ ruby_swap32(uint32_t x)
#if __has_builtin(__builtin_bswap32)
return __builtin_bswap32(x);
-#elif MSC_VERSION_SINCE(1310)
+#elif defined(_MSC_VER)
return _byteswap_ulong(x);
#else
@@ -216,7 +295,7 @@ ruby_swap64(uint64_t x)
#if __has_builtin(__builtin_bswap64)
return __builtin_bswap64(x);
-#elif MSC_VERSION_SINCE(1310)
+#elif defined(_MSC_VER)
return _byteswap_uint64(x);
#else
@@ -241,7 +320,7 @@ nlz_int32(uint32_t x)
#elif defined(__x86_64__) && defined(__LZCNT__)
return (unsigned int)_lzcnt_u32(x);
-#elif MSC_VERSION_SINCE(1400) /* &&! defined(__AVX2__) */
+#elif defined(_MSC_VER) /* &&! defined(__AVX2__) */
unsigned long r;
return _BitScanReverse(&r, x) ? (31 - (int)r) : 32;
@@ -270,7 +349,7 @@ nlz_int64(uint64_t x)
#elif defined(__x86_64__) && defined(__LZCNT__)
return (unsigned int)_lzcnt_u64(x);
-#elif defined(_WIN64) && MSC_VERSION_SINCE(1400) /* &&! defined(__AVX2__) */
+#elif defined(_WIN64) && defined(_MSC_VER) /* &&! defined(__AVX2__) */
unsigned long r;
return _BitScanReverse64(&r, x) ? (63u - (unsigned int)r) : 64;
@@ -456,7 +535,7 @@ ntz_int32(uint32_t x)
#if defined(__x86_64__) && defined(__BMI__)
return (unsigned)_tzcnt_u32(x);
-#elif MSC_VERSION_SINCE(1400)
+#elif defined(_MSC_VER)
/* :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;
@@ -478,7 +557,7 @@ ntz_int64(uint64_t x)
#if defined(__x86_64__) && defined(__BMI__)
return (unsigned)_tzcnt_u64(x);
-#elif defined(_WIN64) && MSC_VERSION_SINCE(1400)
+#elif defined(_WIN64) && defined(_MSC_VER)
unsigned long r;
return _BitScanForward64(&r, x) ? (int)r : 64;
@@ -526,10 +605,10 @@ RUBY_BIT_ROTL(VALUE v, int 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)
+#elif defined(_MSC_VER) && (SIZEOF_VALUE * CHAR_BIT == 32)
return _rotl(v, n);
-#elif MSC_VERSION_SINCE(1310) && (SIZEOF_VALUE * CHAR_BIT == 64)
+#elif defined(_MSC_VER) && (SIZEOF_VALUE * CHAR_BIT == 64)
return _rotl64(v, n);
#elif defined(_lrotl) && (SIZEOF_VALUE == SIZEOF_LONG)
@@ -550,10 +629,10 @@ RUBY_BIT_ROTR(VALUE v, int 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)
+#elif defined(_MSC_VER) && (SIZEOF_VALUE * CHAR_BIT == 32)
return _rotr(v, n);
-#elif MSC_VERSION_SINCE(1310) && (SIZEOF_VALUE * CHAR_BIT == 64)
+#elif defined(_MSC_VER) && (SIZEOF_VALUE * CHAR_BIT == 64)
return _rotr64(v, n);
#elif defined(_lrotr) && (SIZEOF_VALUE == SIZEOF_LONG)
diff --git a/internal/box.h b/internal/box.h
new file mode 100644
index 0000000000..b62b6a9bc9
--- /dev/null
+++ b/internal/box.h
@@ -0,0 +1,83 @@
+#ifndef INTERNAL_BOX_H /*-*-C-*-vi:se ft=c:*/
+#define INTERNAL_BOX_H
+
+#include "ruby/ruby.h" /* for VALUE */
+
+/**
+ * @author Ruby developers <ruby-core@ruby-lang.org>
+ * @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 Ruby Box.
+ */
+struct rb_box_struct {
+ /*
+ * To retrieve Ruby::Box object that provides #require and so on.
+ * That is used from load.c, etc., that uses rb_box_t internally.
+ */
+ VALUE box_object;
+ long box_id; // box_id to generate ext filenames
+
+ VALUE top_self;
+
+ VALUE load_path;
+ VALUE load_path_snapshot;
+ VALUE load_path_check_cache;
+ VALUE expanded_load_path;
+ VALUE loaded_features;
+ VALUE loaded_features_snapshot;
+ VALUE loaded_features_realpaths;
+ VALUE loaded_features_realpath_map;
+ struct st_table *loaded_features_index;
+ struct st_table *loading_table;
+ VALUE ruby_dln_libmap;
+
+ VALUE gvar_tbl;
+ struct st_table *classext_cow_classes;
+
+ bool is_user;
+ bool is_optional;
+};
+typedef struct rb_box_struct rb_box_t;
+
+#define BOX_OBJ_P(obj) (rb_obj_class(obj) == rb_cBox)
+
+#define BOX_ROOT_P(box) (box && !box->is_user)
+#define BOX_USER_P(box) (box && box->is_user)
+#define BOX_OPTIONAL_P(box) (box && box->is_optional)
+#define BOX_MAIN_P(box) (box && box->is_user && !box->is_optional)
+
+#define BOX_METHOD_DEFINITION(mdef) (mdef ? mdef->ns : NULL)
+#define BOX_METHOD_ENTRY(me) (me ? BOX_METHOD_DEFINITION(me->def) : NULL)
+#define BOX_CC(cc) (cc ? BOX_METHOD_ENTRY(cc->cme_) : NULL)
+#define BOX_CC_ENTRIES(ccs) (ccs ? BOX_METHOD_ENTRY(ccs->cme) : NULL)
+
+RUBY_EXTERN bool ruby_box_enabled;
+RUBY_EXTERN bool ruby_box_init_done;
+RUBY_EXTERN bool ruby_box_crashed;
+
+static inline bool
+rb_box_available(void)
+{
+ return ruby_box_enabled;
+}
+
+const rb_box_t * rb_root_box(void);
+const rb_box_t * rb_main_box(void);
+const rb_box_t * rb_current_box(void);
+const rb_box_t * rb_loading_box(void);
+const rb_box_t * rb_current_box_in_crash_report(void);
+
+void rb_box_entry_mark(void *);
+void rb_box_gc_update_references(void *ptr);
+
+rb_box_t * rb_get_box_t(VALUE ns);
+VALUE rb_get_box_object(rb_box_t *ns);
+
+VALUE rb_box_local_extension(VALUE box, VALUE fname, VALUE path, VALUE *cleanup);
+void rb_box_cleanup_local_extension(VALUE cleanup);
+
+void rb_initialize_main_box(void);
+void rb_box_init_done(void);
+#endif /* INTERNAL_BOX_H */
diff --git a/internal/class.h b/internal/class.h
index 8a6c956233..ea68b07fc2 100644
--- a/internal/class.h
+++ b/internal/class.h
@@ -10,6 +10,7 @@
*/
#include "id.h"
#include "id_table.h" /* for struct rb_id_table */
+#include "internal/box.h"
#include "internal/serial.h" /* for rb_serial_t */
#include "internal/static_assert.h"
#include "internal/variable.h" /* for rb_class_ivar_set */
@@ -26,6 +27,41 @@
# undef RCLASS_SUPER
#endif
+struct rb_box_subclasses {
+ long refcount;
+ struct st_table *tbl;
+};
+typedef struct rb_box_subclasses rb_box_subclasses_t;
+
+static inline long
+rb_box_subclasses_ref_count(rb_box_subclasses_t *box_sub)
+{
+ return box_sub->refcount;
+}
+
+static inline rb_box_subclasses_t *
+rb_box_subclasses_ref_inc(rb_box_subclasses_t *box_sub)
+{
+ box_sub->refcount++;
+ return box_sub;
+}
+
+static inline void
+rb_box_subclasses_ref_dec(rb_box_subclasses_t *box_sub)
+{
+ box_sub->refcount--;
+ if (box_sub->refcount == 0) {
+ st_free_table(box_sub->tbl);
+ xfree(box_sub);
+ }
+}
+
+struct rb_subclass_anchor {
+ rb_box_subclasses_t *box_subclasses;
+ struct rb_subclass_entry *head;
+};
+typedef struct rb_subclass_anchor rb_subclass_anchor_t;
+
struct rb_subclass_entry {
VALUE klass;
struct rb_subclass_entry *next;
@@ -41,21 +77,35 @@ struct rb_cvar_class_tbl_entry {
};
struct rb_classext_struct {
- VALUE *iv_ptr;
+ const rb_box_t *box;
+ VALUE super;
+ VALUE fields_obj; // Fields are either ivar or other internal properties stored inline
+ struct rb_id_table *m_tbl;
struct rb_id_table *const_tbl;
struct rb_id_table *callable_m_tbl;
- struct rb_id_table *cc_tbl; /* ID -> [[ci1, cc1], [ci2, cc2] ...] */
+ VALUE cc_tbl; /* { ID => { cme, [cc1, cc2, ...] }, ... } */
struct rb_id_table *cvc_tbl;
- size_t superclass_depth;
VALUE *superclasses;
- 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
+ * The head of subclasses is a blank (w/o klass) entry to be referred from anchor (and be never deleted).
+ * (anchor -> head -> 1st-entry)
+ */
+ struct rb_subclass_anchor *subclasses;
+ /**
+ * The `box_super_subclasses` points the `box_subclasses` struct to retreive the subclasses
+ * of the super class in a specific box.
+ * In compaction GCs, collecting a classext should trigger the deletion of a rb_subclass_entry
+ * from the super's subclasses. But it may be prevented by the read barrier.
+ * Fetching the super's subclasses for a ns is to avoid the read barrier in that process.
+ */
+ rb_box_subclasses_t *box_super_subclasses;
+ /**
+ * In the case that this is an `ICLASS`, `box_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;
+ rb_box_subclasses_t *box_module_subclasses;
+
const VALUE origin_;
const VALUE refined_class;
union {
@@ -65,12 +115,19 @@ struct rb_classext_struct {
struct {
VALUE attached_object;
} singleton_class;
+ struct {
+ const VALUE includer;
+ } iclass;
} as;
- const VALUE includer;
attr_index_t max_iv_count;
+ uint16_t superclass_depth;
unsigned char variation_count;
bool permanent_classpath : 1;
bool cloned : 1;
+ bool shared_const_tbl : 1;
+ bool iclass_is_origin : 1;
+ bool iclass_origin_shared_mtbl : 1;
+ bool superclasses_with_self : 1;
VALUE classpath;
};
typedef struct rb_classext_struct rb_classext_t;
@@ -79,103 +136,370 @@ STATIC_ASSERT(shape_max_variations, SHAPE_MAX_VARIATIONS < (1 << (sizeof(((rb_cl
struct RClass {
struct RBasic basic;
- VALUE super;
- struct rb_id_table *m_tbl;
+ VALUE object_id;
+ /*
+ * If box_classext_tbl is NULL, then the prime classext is readable (because no other classext exists).
+ * For the check whether writable or not, check flag RCLASS_PRIME_CLASSEXT_WRITABLE
+ */
};
-// Assert that classes can be embedded in size_pools[2] (which has 160B slot size)
-STATIC_ASSERT(sizeof_rb_classext_t, sizeof(struct RClass) + sizeof(rb_classext_t) <= 4 * RVALUE_SIZE);
-
struct RClass_and_rb_classext_t {
struct RClass rclass;
rb_classext_t classext;
};
-#define RCLASS_EXT(c) (&((struct RClass_and_rb_classext_t*)(c))->classext)
-#define RCLASS_CONST_TBL(c) (RCLASS_EXT(c)->const_tbl)
-#define RCLASS_M_TBL(c) (RCLASS(c)->m_tbl)
-#define RCLASS_IVPTR(c) (RCLASS_EXT(c)->iv_ptr)
-#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_ORIGIN(c) (RCLASS_EXT(c)->origin_)
-#define RCLASS_REFINED_CLASS(c) (RCLASS_EXT(c)->refined_class)
-#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_SUBCLASSES(c) (RCLASS_EXT(c)->subclasses)
-#define RCLASS_SUPERCLASS_DEPTH(c) (RCLASS_EXT(c)->superclass_depth)
-#define RCLASS_SUPERCLASSES(c) (RCLASS_EXT(c)->superclasses)
-#define RCLASS_ATTACHED_OBJECT(c) (RCLASS_EXT(c)->as.singleton_class.attached_object)
+#if SIZEOF_VALUE >= SIZEOF_LONG_LONG
+// Assert that classes can be embedded in heaps[2] (which has 160B slot size)
+// On 32bit platforms there is no variable width allocation so it doesn't matter.
+STATIC_ASSERT(sizeof_rb_classext_t, sizeof(struct RClass_and_rb_classext_t) <= 4 * RVALUE_SIZE);
+#endif
+
+struct RClass_boxable {
+ struct RClass_and_rb_classext_t base;
+ st_table *box_classext_tbl; // box_object -> (rb_classext_t *)
+};
+
+static const uint16_t RCLASS_MAX_SUPERCLASS_DEPTH = ((uint16_t)-1);
+
+static inline bool RCLASS_SINGLETON_P(VALUE klass);
+
+static inline bool RCLASS_PRIME_CLASSEXT_READABLE_P(VALUE obj);
+static inline bool RCLASS_PRIME_CLASSEXT_WRITABLE_P(VALUE obj);
+static inline void RCLASS_SET_PRIME_CLASSEXT_WRITABLE(VALUE obj, bool writable);
+
+#define RCLASS_EXT_PRIME(c) (&((struct RClass_and_rb_classext_t*)(c))->classext)
+#define RCLASS_EXT_PRIME_P(ext, c) (&((struct RClass_and_rb_classext_t*)(c))->classext == ext)
+
+static inline rb_classext_t * RCLASS_EXT_READABLE_IN_BOX(VALUE obj, const rb_box_t *box);
+static inline rb_classext_t * RCLASS_EXT_READABLE(VALUE obj);
+static inline rb_classext_t * RCLASS_EXT_WRITABLE_IN_BOX(VALUE obj, const rb_box_t *box);
+static inline rb_classext_t * RCLASS_EXT_WRITABLE(VALUE obj);
+
+// Raw accessor
+#define RCLASSEXT_BOX(ext) (ext->box)
+#define RCLASSEXT_SUPER(ext) (ext->super)
+#define RCLASSEXT_FIELDS(ext) (ext->fields_obj ? ROBJECT_FIELDS(ext->fields_obj) : NULL)
+#define RCLASSEXT_FIELDS_OBJ(ext) (ext->fields_obj)
+#define RCLASSEXT_M_TBL(ext) (ext->m_tbl)
+#define RCLASSEXT_CONST_TBL(ext) (ext->const_tbl)
+#define RCLASSEXT_CALLABLE_M_TBL(ext) (ext->callable_m_tbl)
+#define RCLASSEXT_CC_TBL(ext) (ext->cc_tbl)
+#define RCLASSEXT_CVC_TBL(ext) (ext->cvc_tbl)
+#define RCLASSEXT_SUPERCLASS_DEPTH(ext) (ext->superclass_depth)
+#define RCLASSEXT_SUPERCLASSES(ext) (ext->superclasses)
+#define RCLASSEXT_SUBCLASSES(ext) (ext->subclasses)
+#define RCLASSEXT_BOX_SUPER_SUBCLASSES(ext) (ext->box_super_subclasses)
+#define RCLASSEXT_BOX_MODULE_SUBCLASSES(ext) (ext->box_module_subclasses)
+#define RCLASSEXT_ORIGIN(ext) (ext->origin_)
+#define RCLASSEXT_REFINED_CLASS(ext) (ext->refined_class)
+// class.allocator/singleton_class.attached_object are not accessed directly via RCLASSEXT_*
+#define RCLASSEXT_INCLUDER(ext) (ext->as.iclass.includer)
+#define RCLASSEXT_PERMANENT_CLASSPATH(ext) (ext->permanent_classpath)
+#define RCLASSEXT_CLONED(ext) (ext->cloned)
+#define RCLASSEXT_SHARED_CONST_TBL(ext) (ext->shared_const_tbl)
+#define RCLASSEXT_ICLASS_IS_ORIGIN(ext) (ext->iclass_is_origin)
+#define RCLASSEXT_ICLASS_ORIGIN_SHARED_MTBL(ext) (ext->iclass_origin_shared_mtbl)
+#define RCLASSEXT_SUPERCLASSES_WITH_SELF(ext) (ext->superclasses_with_self)
+#define RCLASSEXT_CLASSPATH(ext) (ext->classpath)
+
+static inline void RCLASSEXT_SET_ORIGIN(rb_classext_t *ext, VALUE klass, VALUE origin);
+static inline void RCLASSEXT_SET_INCLUDER(rb_classext_t *ext, VALUE klass, VALUE includer);
+
+/* Prime classext entry accessor for very specific reason */
+#define RCLASS_PRIME_BOX(c) (RCLASS_EXT_PRIME(c)->box)
+// To invalidate CC by inserting&invalidating method entry into tables containing the target cme
+// See clear_method_cache_by_id_in_class()
+#define RCLASS_PRIME_FIELDS_OBJ(c) (RCLASS_EXT_PRIME(c)->fields_obj)
+#define RCLASS_PRIME_M_TBL(c) (RCLASS_EXT_PRIME(c)->m_tbl)
+#define RCLASS_PRIME_CONST_TBL(c) (RCLASS_EXT_PRIME(c)->const_tbl)
+#define RCLASS_PRIME_CALLABLE_M_TBL(c) (RCLASS_EXT_PRIME(c)->callable_m_tbl)
+#define RCLASS_PRIME_CC_TBL(c) (RCLASS_EXT_PRIME(c)->cc_tbl)
+#define RCLASS_M_TBL_NOT_PRIME_P(c, tbl) (RCLASS_EXT_PRIME(c)->m_tbl != tbl)
+#define RCLASS_CALLABLE_M_TBL_NOT_PRIME_P(c, tbl) (RCLASS_EXT_PRIME(c)->callable_m_tbl != tbl)
+#define RCLASS_CC_TBL_NOT_PRIME_P(c, tbl) (RCLASS_EXT_PRIME(c)->cc_tbl != tbl)
+
+// Read accessor, regarding box
+#define RCLASS_SUPER(c) (RCLASS_EXT_READABLE(c)->super)
+#define RCLASS_M_TBL(c) (RCLASS_EXT_READABLE(c)->m_tbl)
+#define RCLASS_CONST_TBL(c) (RCLASS_EXT_READABLE(c)->const_tbl)
+/*
+ * Both cc_tbl/callable_m_tbl are cache-like and always be changed when referreed,
+ * so always those should be writable.
+ */
+#define RCLASS_CVC_TBL(c) (RCLASS_EXT_READABLE(c)->cvc_tbl)
+#define RCLASS_SUBCLASSES_X(c) (RCLASS_EXT_READABLE(c)->subclasses)
+#define RCLASS_SUBCLASSES_FIRST(c) (RCLASS_EXT_READABLE(c)->subclasses->head->next)
+#define RCLASS_ORIGIN(c) (RCLASS_EXT_READABLE(c)->origin_)
+#define RICLASS_IS_ORIGIN_P(c) (RCLASS_EXT_READABLE(c)->iclass_is_origin)
+#define RCLASS_PERMANENT_CLASSPATH_P(c) (RCLASS_EXT_READABLE(c)->permanent_classpath)
+#define RCLASS_CLONED_P(c) (RCLASS_EXT_READABLE(c)->cloned)
+#define RCLASS_CLASSPATH(c) (RCLASS_EXT_READABLE(c)->classpath)
+
+// Superclasses can't be changed after initialization
+#define RCLASS_SUPERCLASS_DEPTH(c) (RCLASS_EXT_PRIME(c)->superclass_depth)
+#define RCLASS_SUPERCLASSES(c) (RCLASS_EXT_PRIME(c)->superclasses)
+#define RCLASS_SUPERCLASSES_WITH_SELF_P(c) (RCLASS_EXT_PRIME(c)->superclasses_with_self)
+
+// Ruby Box doesn't make changes on these refined_class/attached_object/includer
+#define RCLASS_REFINED_CLASS(c) (RCLASS_EXT_PRIME(c)->refined_class)
+#define RCLASS_ATTACHED_OBJECT(c) (RCLASS_EXT_PRIME(c)->as.singleton_class.attached_object)
+#define RCLASS_INCLUDER(c) (RCLASS_EXT_PRIME(c)->as.iclass.includer)
+
+// max IV count and variation count are just hints, so they don't need to be per-box
+#define RCLASS_MAX_IV_COUNT(ext) (RCLASS_EXT_PRIME(ext)->max_iv_count)
+#define RCLASS_VARIATION_COUNT(ext) (RCLASS_EXT_PRIME(ext)->variation_count)
+
+// Writable classext entries (instead of RCLASS_SET_*) because member data will be operated directly
+#define RCLASS_WRITABLE_M_TBL(c) (RCLASS_EXT_WRITABLE(c)->m_tbl)
+#define RCLASS_WRITABLE_CONST_TBL(c) (RCLASS_EXT_WRITABLE(c)->const_tbl)
+#define RCLASS_WRITABLE_CALLABLE_M_TBL(c) (RCLASS_EXT_WRITABLE(c)->callable_m_tbl)
+#define RCLASS_WRITABLE_CC_TBL(c) (RCLASS_EXT_WRITABLE(c)->cc_tbl)
+#define RCLASS_WRITABLE_CVC_TBL(c) (RCLASS_EXT_WRITABLE(c)->cvc_tbl)
+#define RCLASS_WRITABLE_SUBCLASSES(c) (RCLASS_EXT_WRITABLE(c)->subclasses)
+
+static inline void RCLASS_SET_SUPER(VALUE klass, VALUE super);
+static inline void RCLASS_WRITE_SUPER(VALUE klass, VALUE super);
+static inline void RCLASS_SET_CONST_TBL(VALUE klass, struct rb_id_table *table, bool shared);
+static inline void RCLASS_WRITE_CONST_TBL(VALUE klass, struct rb_id_table *table, bool shared);
+static inline void RCLASS_WRITE_CALLABLE_M_TBL(VALUE klass, struct rb_id_table *table);
+static inline void RCLASS_WRITE_CC_TBL(VALUE klass, VALUE table);
+static inline void RCLASS_SET_CVC_TBL(VALUE klass, struct rb_id_table *table);
+static inline void RCLASS_WRITE_CVC_TBL(VALUE klass, struct rb_id_table *table);
+
+static inline void RCLASS_WRITE_SUPERCLASSES(VALUE klass, size_t depth, VALUE *superclasses, bool with_self);
+static inline void RCLASS_SET_SUBCLASSES(VALUE klass, rb_subclass_anchor_t *anchor);
+static inline void RCLASS_WRITE_BOX_SUPER_SUBCLASSES(VALUE klass, rb_box_subclasses_t *box_subclasses);
+static inline void RCLASS_WRITE_BOX_MODULE_SUBCLASSES(VALUE klass, rb_box_subclasses_t *box_subclasses);
+
+static inline void RCLASS_SET_ORIGIN(VALUE klass, VALUE origin);
+static inline void RCLASS_WRITE_ORIGIN(VALUE klass, VALUE origin);
+static inline void RICLASS_SET_ORIGIN_SHARED_MTBL(VALUE iclass);
+static inline void RICLASS_WRITE_ORIGIN_SHARED_MTBL(VALUE iclass);
+static inline bool RICLASS_OWNS_M_TBL_P(VALUE iclass);
+
+static inline void RCLASS_SET_REFINED_CLASS(VALUE klass, VALUE refined);
+static inline rb_alloc_func_t RCLASS_ALLOCATOR(VALUE klass);
+static inline void RCLASS_SET_ALLOCATOR(VALUE klass, rb_alloc_func_t allocator);
+static inline VALUE RCLASS_SET_ATTACHED_OBJECT(VALUE klass, VALUE attached_object);
+
+static inline void RCLASS_SET_INCLUDER(VALUE iclass, VALUE klass);
+static inline void RCLASS_SET_MAX_IV_COUNT(VALUE klass, attr_index_t count);
+static inline void RCLASS_SET_CLONED(VALUE klass, bool cloned);
+static inline void RCLASS_SET_CLASSPATH(VALUE klass, VALUE classpath, bool permanent);
+static inline void RCLASS_WRITE_CLASSPATH(VALUE klass, VALUE classpath, bool permanent);
#define RCLASS_IS_ROOT FL_USER0
-#define RICLASS_IS_ORIGIN FL_USER0
-#define RCLASS_SUPERCLASSES_INCLUDE_SELF FL_USER2
-#define RICLASS_ORIGIN_SHARED_MTBL FL_USER3
+// 1 is for RUBY_FL_SINGLETON or RMODULE_IS_REFINEMENT
+#define RCLASS_PRIME_CLASSEXT_WRITABLE FL_USER2
+#define RCLASS_IS_INITIALIZED FL_USER3
+// 3 is RMODULE_IS_REFINEMENT for RMODULE
+#define RCLASS_BOXABLE FL_USER4
static inline st_table *
-RCLASS_IV_HASH(VALUE obj)
+RCLASS_CLASSEXT_TBL(VALUE klass)
{
- RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE));
- RUBY_ASSERT(rb_shape_obj_too_complex(obj));
- return (st_table *)RCLASS_IVPTR(obj);
+ if (FL_TEST_RAW(klass, RCLASS_BOXABLE)) {
+ struct RClass_boxable *box_klass = (struct RClass_boxable *)klass;
+ return box_klass->box_classext_tbl;
+ }
+ return NULL;
}
static inline void
-RCLASS_SET_IV_HASH(VALUE obj, const st_table *tbl)
+RCLASS_SET_CLASSEXT_TBL(VALUE klass, st_table *tbl)
{
- RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE));
- RUBY_ASSERT(rb_shape_obj_too_complex(obj));
- RCLASS_IVPTR(obj) = (VALUE *)tbl;
+ RUBY_ASSERT(FL_TEST_RAW(klass, RCLASS_BOXABLE));
+ struct RClass_boxable *box_klass = (struct RClass_boxable *)klass;
+ box_klass->box_classext_tbl = tbl;
}
-static inline uint32_t
-RCLASS_IV_COUNT(VALUE obj)
+/* class.c */
+rb_classext_t * rb_class_duplicate_classext(rb_classext_t *orig, VALUE obj, const rb_box_t *box);
+void rb_class_ensure_writable(VALUE obj);
+
+void rb_class_set_box_classext(VALUE obj, const rb_box_t *box, rb_classext_t *ext);
+
+static inline int
+RCLASS_SET_BOX_CLASSEXT(VALUE obj, const rb_box_t *box, rb_classext_t *ext)
{
- RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE));
- if (rb_shape_obj_too_complex(obj)) {
- uint32_t count;
-
- // "Too complex" classes could have their IV hash mutated in
- // parallel, so lets lock around getting the hash size.
- RB_VM_LOCK_ENTER();
- {
- count = (uint32_t)rb_st_table_size(RCLASS_IV_HASH(obj));
- }
- RB_VM_LOCK_LEAVE();
+ int first_set = 0;
+ st_table *tbl = RCLASS_CLASSEXT_TBL(obj);
+ VM_ASSERT(BOX_USER_P(box)); // non-prime classext is only for user box, with box_object
+ VM_ASSERT(box->box_object);
+ VM_ASSERT(RCLASSEXT_BOX(ext) == box);
+ if (!tbl) {
+ tbl = st_init_numtable_with_size(1);
+ RCLASS_SET_CLASSEXT_TBL(obj, tbl);
+ }
+ if (rb_st_table_size(tbl) == 0) {
+ first_set = 1;
+ }
+
+ rb_class_set_box_classext(obj, box, ext);
+
+ return first_set;
+}
+
+#define VM_ASSERT_BOXABLE_TYPE(klass) \
+ VM_ASSERT(RB_TYPE_P(klass, T_CLASS) || RB_TYPE_P(klass, T_MODULE) || RB_TYPE_P(klass, T_ICLASS), "%s is not boxable type", rb_type_str(BUILTIN_TYPE(klass)))
- return count;
+static inline bool
+RCLASS_PRIME_CLASSEXT_READABLE_P(VALUE klass)
+{
+ VM_ASSERT(klass != 0, "klass should be a valid object");
+ VM_ASSERT_BOXABLE_TYPE(klass);
+ // if the lookup table exists, then it means the prime classext is NOT directly readable.
+ return !FL_TEST_RAW(klass, RCLASS_BOXABLE) || RCLASS_CLASSEXT_TBL(klass) == NULL;
+}
+
+static inline bool
+RCLASS_PRIME_CLASSEXT_WRITABLE_P(VALUE klass)
+{
+ VM_ASSERT(klass != 0, "klass should be a valid object");
+ VM_ASSERT_BOXABLE_TYPE(klass);
+ return FL_TEST(klass, RCLASS_PRIME_CLASSEXT_WRITABLE);
+}
+
+static inline void
+RCLASS_SET_PRIME_CLASSEXT_WRITABLE(VALUE klass, bool writable)
+{
+ VM_ASSERT(klass != 0, "klass should be a valid object");
+ VM_ASSERT_BOXABLE_TYPE(klass);
+ if (writable) {
+ FL_SET(klass, RCLASS_PRIME_CLASSEXT_WRITABLE);
}
else {
- return rb_shape_get_shape_by_id(RCLASS_SHAPE_ID(obj))->next_iv_index;
+ FL_UNSET(klass, RCLASS_PRIME_CLASSEXT_WRITABLE);
}
}
+static inline rb_classext_t *
+RCLASS_EXT_TABLE_LOOKUP_INTERNAL(VALUE obj, const rb_box_t *box)
+{
+ st_data_t classext_ptr;
+ st_table *classext_tbl = RCLASS_CLASSEXT_TBL(obj);
+ if (classext_tbl) {
+ if (rb_st_lookup(classext_tbl, (st_data_t)box->box_object, &classext_ptr)) {
+ return (rb_classext_t *)classext_ptr;
+ }
+ }
+ return NULL;
+}
+
+static inline rb_classext_t *
+RCLASS_EXT_READABLE_LOOKUP(VALUE obj, const rb_box_t *box)
+{
+ rb_classext_t *ext = RCLASS_EXT_TABLE_LOOKUP_INTERNAL(obj, box);
+ if (ext)
+ return ext;
+ // Classext for the ns not found. Refer the prime one instead.
+ return RCLASS_EXT_PRIME(obj);
+}
+
+static inline rb_classext_t *
+RCLASS_EXT_READABLE_IN_BOX(VALUE obj, const rb_box_t *box)
+{
+ if (BOX_ROOT_P(box)
+ || RCLASS_PRIME_CLASSEXT_READABLE_P(obj)) {
+ return RCLASS_EXT_PRIME(obj);
+ }
+ return RCLASS_EXT_READABLE_LOOKUP(obj, box);
+}
+
+static inline rb_classext_t *
+RCLASS_EXT_READABLE(VALUE obj)
+{
+ const rb_box_t *box;
+ if (RCLASS_PRIME_CLASSEXT_READABLE_P(obj)) {
+ return RCLASS_EXT_PRIME(obj);
+ }
+ // delay determining the current box to optimize for unmodified classes
+ box = rb_current_box();
+ if (BOX_ROOT_P(box)) {
+ return RCLASS_EXT_PRIME(obj);
+ }
+ return RCLASS_EXT_READABLE_LOOKUP(obj, box);
+}
+
+static inline rb_classext_t *
+RCLASS_EXT_WRITABLE_LOOKUP(VALUE obj, const rb_box_t *box)
+{
+ rb_classext_t *ext;
+ int first_set = 0;
+
+ ext = RCLASS_EXT_TABLE_LOOKUP_INTERNAL(obj, box);
+ if (ext)
+ return ext;
+
+ RB_VM_LOCKING() {
+ // re-check the classext is not created to avoid the multi-thread race
+ ext = RCLASS_EXT_TABLE_LOOKUP_INTERNAL(obj, box);
+ if (!ext) {
+ ext = rb_class_duplicate_classext(RCLASS_EXT_PRIME(obj), obj, box);
+ first_set = RCLASS_SET_BOX_CLASSEXT(obj, box, ext);
+ if (first_set) {
+ // TODO: are there any case that a class/module become non-writable after its birthtime?
+ RCLASS_SET_PRIME_CLASSEXT_WRITABLE(obj, false);
+ }
+ }
+ }
+ return ext;
+}
+
+static inline rb_classext_t *
+RCLASS_EXT_WRITABLE_IN_BOX(VALUE obj, const rb_box_t *box)
+{
+ if (BOX_ROOT_P(box)
+ || RCLASS_PRIME_CLASSEXT_WRITABLE_P(obj)) {
+ return RCLASS_EXT_PRIME(obj);
+ }
+ return RCLASS_EXT_WRITABLE_LOOKUP(obj, box);
+}
+
+static inline rb_classext_t *
+RCLASS_EXT_WRITABLE(VALUE obj)
+{
+ const rb_box_t *box;
+ if (LIKELY(RCLASS_PRIME_CLASSEXT_WRITABLE_P(obj))) {
+ return RCLASS_EXT_PRIME(obj);
+ }
+ // delay determining the current box to optimize for unmodified classes
+ box = rb_current_box();
+ if (BOX_ROOT_P(box)) {
+ return RCLASS_EXT_PRIME(obj);
+ }
+ return RCLASS_EXT_WRITABLE_LOOKUP(obj, box);
+}
+
static inline void
-RCLASS_SET_M_TBL(VALUE klass, struct rb_id_table *table)
+RCLASSEXT_SET_ORIGIN(rb_classext_t *ext, VALUE klass, VALUE origin)
{
- RUBY_ASSERT(!RB_OBJ_PROMOTED(klass));
- RCLASS_M_TBL(klass) = table;
+ RB_OBJ_WRITE(klass, &(RCLASSEXT_ORIGIN(ext)), origin);
+}
+
+static inline void
+RCLASSEXT_SET_INCLUDER(rb_classext_t *ext, VALUE klass, VALUE includer)
+{
+ RUBY_ASSERT(RB_TYPE_P(klass, T_ICLASS));
+ RB_OBJ_WRITE(klass, &(RCLASSEXT_INCLUDER(ext)), includer);
}
/* class.c */
+typedef void rb_class_classext_foreach_callback_func(rb_classext_t *classext, bool is_prime, VALUE box_value, void *arg);
+void rb_class_classext_foreach(VALUE klass, rb_class_classext_foreach_callback_func *func, void *arg);
void rb_class_subclass_add(VALUE super, VALUE klass);
-void rb_class_remove_from_super_subclasses(VALUE);
+void rb_class_classext_free_subclasses(rb_classext_t *, VALUE, bool);
+void rb_class_foreach_subclass(VALUE klass, void (*f)(VALUE, VALUE), VALUE);
void rb_class_update_superclasses(VALUE);
-size_t rb_class_superclasses_memsize(VALUE);
-void rb_class_remove_subclass_head(VALUE);
int rb_singleton_class_internal_p(VALUE sklass);
+VALUE rb_class_set_super(VALUE klass, VALUE super);
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_class_set_initialized(VALUE klass);
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_define_class_id_under_no_pin(VALUE outer, ID id, VALUE super);
VALUE rb_obj_methods(int argc, const VALUE *argv, VALUE obj);
VALUE rb_obj_protected_methods(int argc, const VALUE *argv, VALUE obj);
@@ -186,89 +510,269 @@ 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);
-
VALUE rb_class_inherited(VALUE, VALUE);
VALUE rb_keyword_error_new(const char *, VALUE);
+rb_classext_t *rb_class_unlink_classext(VALUE klass, const rb_box_t *box);
+void rb_class_classext_free(VALUE klass, rb_classext_t *ext, bool is_prime);
+void rb_iclass_classext_free(VALUE klass, rb_classext_t *ext, bool is_prime);
+
+RUBY_SYMBOL_EXPORT_BEGIN
+
+/* for objspace */
+VALUE rb_class_super_of(VALUE klass);
+VALUE rb_class_singleton_p(VALUE klass);
+unsigned char rb_class_variation_count(VALUE klass);
+
+RUBY_SYMBOL_EXPORT_END
+
static inline bool
RCLASS_SINGLETON_P(VALUE klass)
{
return RB_TYPE_P(klass, T_CLASS) && FL_TEST_RAW(klass, FL_SINGLETON);
}
+static inline void
+RCLASS_SET_SUPER(VALUE klass, VALUE super)
+{
+ RB_OBJ_WRITE(klass, &RCLASSEXT_SUPER(RCLASS_EXT_PRIME(klass)), super);
+}
+
+static inline void
+RCLASS_WRITE_SUPER(VALUE klass, VALUE super)
+{
+ RB_OBJ_WRITE(klass, &RCLASSEXT_SUPER(RCLASS_EXT_WRITABLE(klass)), super);
+}
+
+static inline VALUE
+RCLASS_WRITABLE_ENSURE_FIELDS_OBJ(VALUE obj)
+{
+ RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE));
+ rb_classext_t *ext = RCLASS_EXT_WRITABLE(obj);
+ if (!ext->fields_obj) {
+ RB_OBJ_WRITE(obj, &ext->fields_obj, rb_imemo_fields_new(obj, 1, true));
+ }
+ return ext->fields_obj;
+}
+
+static inline VALUE
+RCLASS_WRITABLE_FIELDS_OBJ(VALUE obj)
+{
+ RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE));
+ return RCLASSEXT_FIELDS_OBJ(RCLASS_EXT_WRITABLE(obj));
+}
+
+static inline void
+RCLASSEXT_SET_FIELDS_OBJ(VALUE obj, rb_classext_t *ext, VALUE fields_obj)
+{
+ RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE));
+
+ RB_OBJ_ATOMIC_WRITE(obj, &ext->fields_obj, fields_obj);
+}
+
+static inline void
+RCLASS_WRITABLE_SET_FIELDS_OBJ(VALUE obj, VALUE fields_obj)
+{
+ RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE));
+
+ RCLASSEXT_SET_FIELDS_OBJ(obj, RCLASS_EXT_WRITABLE(obj), fields_obj);
+}
+
+static inline uint32_t
+RCLASS_FIELDS_COUNT(VALUE obj)
+{
+ RUBY_ASSERT(RB_TYPE_P(obj, RUBY_T_CLASS) || RB_TYPE_P(obj, RUBY_T_MODULE));
+
+ VALUE fields_obj = RCLASS_WRITABLE_FIELDS_OBJ(obj);
+ if (fields_obj) {
+ if (rb_shape_obj_too_complex_p(fields_obj)) {
+ return (uint32_t)rb_st_table_size(rb_imemo_fields_complex_tbl(fields_obj));
+ }
+ else {
+ return RSHAPE_LEN(RBASIC_SHAPE_ID(fields_obj));
+ }
+ }
+ return 0;
+}
+
+static inline void
+RCLASS_SET_M_TBL(VALUE klass, struct rb_id_table *table)
+{
+ RCLASSEXT_M_TBL(RCLASS_EXT_PRIME(klass)) = table;
+}
+
+static inline void
+RCLASS_WRITE_M_TBL(VALUE klass, struct rb_id_table *table)
+{
+ RCLASSEXT_M_TBL(RCLASS_EXT_WRITABLE(klass)) = table;
+}
+
+static inline void
+RCLASS_SET_CONST_TBL(VALUE klass, struct rb_id_table *table, bool shared)
+{
+ rb_classext_t *ext = RCLASS_EXT_PRIME(klass);
+ RCLASSEXT_CONST_TBL(ext) = table;
+ if (shared)
+ RCLASSEXT_SHARED_CONST_TBL(ext) = true;
+}
+
+static inline void
+RCLASS_WRITE_CONST_TBL(VALUE klass, struct rb_id_table *table, bool shared)
+{
+ rb_classext_t *ext = RCLASS_EXT_WRITABLE(klass);
+ RCLASSEXT_CONST_TBL(ext) = table;
+ if (shared)
+ RCLASSEXT_SHARED_CONST_TBL(ext) = true;
+}
+
+static inline void
+RCLASS_WRITE_CALLABLE_M_TBL(VALUE klass, struct rb_id_table *table)
+{
+ RCLASSEXT_CALLABLE_M_TBL(RCLASS_EXT_WRITABLE(klass)) = table;
+}
+
+static inline void
+RCLASS_WRITE_CC_TBL(VALUE klass, VALUE table)
+{
+ RB_OBJ_ATOMIC_WRITE(klass, &RCLASSEXT_CC_TBL(RCLASS_EXT_WRITABLE(klass)), table);
+}
+
+static inline void
+RCLASS_SET_CVC_TBL(VALUE klass, struct rb_id_table *table)
+{
+ RCLASSEXT_CVC_TBL(RCLASS_EXT_PRIME(klass)) = table;
+}
+
+static inline void
+RCLASS_WRITE_CVC_TBL(VALUE klass, struct rb_id_table *table)
+{
+ RCLASSEXT_CVC_TBL(RCLASS_EXT_WRITABLE(klass)) = table;
+}
+
+static inline void
+RCLASS_SET_REFINED_CLASS(VALUE klass, VALUE refined)
+{
+ RB_OBJ_WRITE(klass, &RCLASSEXT_REFINED_CLASS(RCLASS_EXT_PRIME(klass)), refined);
+}
+
static inline rb_alloc_func_t
RCLASS_ALLOCATOR(VALUE klass)
{
+ RBIMPL_ASSERT_TYPE(klass, T_CLASS);
if (RCLASS_SINGLETON_P(klass)) {
return 0;
}
- return RCLASS_EXT(klass)->as.class.allocator;
+ return RCLASS_EXT_PRIME(klass)->as.class.allocator;
}
static inline void
RCLASS_SET_ALLOCATOR(VALUE klass, rb_alloc_func_t allocator)
{
- assert(!RCLASS_SINGLETON_P(klass));
- RCLASS_EXT(klass)->as.class.allocator = allocator;
+ RUBY_ASSERT(RB_TYPE_P(klass, T_CLASS));
+ RUBY_ASSERT(!RCLASS_SINGLETON_P(klass));
+ RCLASS_EXT_PRIME(klass)->as.class.allocator = allocator; // Allocator is set only on the initial definition
}
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);
+ rb_classext_t *ext = RCLASS_EXT_PRIME(klass);
+ RB_OBJ_WRITE(klass, &RCLASSEXT_ORIGIN(ext), origin);
+ if (klass != origin) RCLASSEXT_ICLASS_IS_ORIGIN(RCLASS_EXT_WRITABLE(origin)) = true;
+}
+
+static inline void
+RCLASS_WRITE_ORIGIN(VALUE klass, VALUE origin)
+{
+ rb_classext_t *ext = RCLASS_EXT_WRITABLE(klass);
+ RB_OBJ_WRITE(klass, &RCLASSEXT_ORIGIN(ext), origin);
+ if (klass != origin) RCLASSEXT_ICLASS_IS_ORIGIN(RCLASS_EXT_WRITABLE(origin)) = true;
}
static inline void
RICLASS_SET_ORIGIN_SHARED_MTBL(VALUE iclass)
{
- FL_SET(iclass, RICLASS_ORIGIN_SHARED_MTBL);
+ RCLASSEXT_ICLASS_ORIGIN_SHARED_MTBL(RCLASS_EXT_PRIME(iclass)) = true;
+}
+
+static inline void
+RICLASS_WRITE_ORIGIN_SHARED_MTBL(VALUE iclass)
+{
+ RCLASSEXT_ICLASS_ORIGIN_SHARED_MTBL(RCLASS_EXT_WRITABLE(iclass)) = true;
}
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;
+ rb_classext_t *ext = RCLASS_EXT_READABLE(iclass);
+ return RCLASSEXT_ICLASS_IS_ORIGIN(ext) && !RCLASSEXT_ICLASS_ORIGIN_SHARED_MTBL(ext);
}
static inline void
RCLASS_SET_INCLUDER(VALUE iclass, VALUE klass)
{
+ RUBY_ASSERT(RB_TYPE_P(iclass, T_ICLASS));
RB_OBJ_WRITE(iclass, &RCLASS_INCLUDER(iclass), klass);
}
-static inline VALUE
-RCLASS_SUPER(VALUE klass)
+static inline void
+RCLASS_WRITE_SUPERCLASSES(VALUE klass, size_t depth, VALUE *superclasses, bool with_self)
{
- return RCLASS(klass)->super;
+ RUBY_ASSERT(depth <= RCLASS_MAX_SUPERCLASS_DEPTH);
+
+ rb_classext_t *ext = RCLASS_EXT_PRIME(klass);
+ RCLASSEXT_SUPERCLASS_DEPTH(ext) = depth;
+ RCLASSEXT_SUPERCLASSES(ext) = superclasses;
+ RCLASSEXT_SUPERCLASSES_WITH_SELF(ext) = with_self;
}
-static inline VALUE
-RCLASS_SET_SUPER(VALUE klass, VALUE super)
+static inline void
+RCLASS_SET_SUBCLASSES(VALUE klass, struct rb_subclass_anchor *anchor)
{
- if (super) {
- rb_class_remove_from_super_subclasses(klass);
- rb_class_subclass_add(super, klass);
- }
- RB_OBJ_WRITE(klass, &RCLASS(klass)->super, super);
- rb_class_update_superclasses(klass);
- return super;
+ rb_classext_t *ext = RCLASS_EXT_PRIME(klass);
+ RCLASSEXT_SUBCLASSES(ext) = anchor;
+}
+
+static inline void
+RCLASS_WRITE_BOX_SUPER_SUBCLASSES(VALUE klass, rb_box_subclasses_t *box_subclasses)
+{
+ rb_classext_t *ext = RCLASS_EXT_WRITABLE(klass);
+ if (RCLASSEXT_BOX_SUPER_SUBCLASSES(ext))
+ rb_box_subclasses_ref_dec(RCLASSEXT_BOX_SUPER_SUBCLASSES(ext));
+ RCLASSEXT_BOX_SUPER_SUBCLASSES(ext) = rb_box_subclasses_ref_inc(box_subclasses);
+}
+
+static inline void
+RCLASS_WRITE_BOX_MODULE_SUBCLASSES(VALUE klass, rb_box_subclasses_t *box_subclasses)
+{
+ rb_classext_t *ext = RCLASS_EXT_WRITABLE(klass);
+ if (RCLASSEXT_BOX_MODULE_SUBCLASSES(ext))
+ rb_box_subclasses_ref_dec(RCLASSEXT_BOX_MODULE_SUBCLASSES(ext));
+ RCLASSEXT_BOX_MODULE_SUBCLASSES(ext) = rb_box_subclasses_ref_inc(box_subclasses);
}
static inline void
RCLASS_SET_CLASSPATH(VALUE klass, VALUE classpath, bool permanent)
{
+ rb_classext_t *ext = RCLASS_EXT_READABLE(klass);
+ assert(BUILTIN_TYPE(klass) == T_CLASS || BUILTIN_TYPE(klass) == T_MODULE);
+ assert(classpath == 0 || BUILTIN_TYPE(classpath) == T_STRING);
+ assert(FL_TEST_RAW(classpath, RUBY_FL_SHAREABLE));
+
+ RB_OBJ_WRITE(klass, &(RCLASSEXT_CLASSPATH(ext)), classpath);
+ RCLASSEXT_PERMANENT_CLASSPATH(ext) = permanent;
+}
+
+static inline void
+RCLASS_WRITE_CLASSPATH(VALUE klass, VALUE classpath, bool permanent)
+{
+ rb_classext_t *ext = RCLASS_EXT_WRITABLE(klass);
assert(BUILTIN_TYPE(klass) == T_CLASS || BUILTIN_TYPE(klass) == T_MODULE);
assert(classpath == 0 || BUILTIN_TYPE(classpath) == T_STRING);
+ assert(!RB_FL_ABLE(classpath) || FL_TEST_RAW(classpath, RUBY_FL_SHAREABLE));
- RB_OBJ_WRITE(klass, &(RCLASS_EXT(klass)->classpath), classpath);
- RCLASS_EXT(klass)->permanent_classpath = permanent;
+ RB_OBJ_WRITE(klass, &(RCLASSEXT_CLASSPATH(ext)), classpath);
+ RCLASSEXT_PERMANENT_CLASSPATH(ext) = permanent;
}
static inline VALUE
@@ -276,8 +780,27 @@ RCLASS_SET_ATTACHED_OBJECT(VALUE klass, VALUE attached_object)
{
assert(RCLASS_SINGLETON_P(klass));
- RB_OBJ_WRITE(klass, &RCLASS_EXT(klass)->as.singleton_class.attached_object, attached_object);
+ RB_OBJ_WRITE(klass, &RCLASS_EXT_PRIME(klass)->as.singleton_class.attached_object, attached_object);
return attached_object;
}
+static inline void
+RCLASS_SET_MAX_IV_COUNT(VALUE klass, attr_index_t count)
+{
+ RCLASS_MAX_IV_COUNT(klass) = count;
+}
+
+static inline void
+RCLASS_SET_CLONED(VALUE klass, bool cloned)
+{
+ RCLASSEXT_CLONED(RCLASS_EXT_PRIME(klass)) = cloned;
+}
+
+static inline bool
+RCLASS_INITIALIZED_P(VALUE klass)
+{
+ VM_ASSERT(RB_TYPE_P(klass, T_CLASS) || RB_TYPE_P(klass, T_MODULE));
+ return FL_TEST_RAW(klass, RCLASS_IS_INITIALIZED);
+}
+
#endif /* INTERNAL_CLASS_H */
diff --git a/internal/cmdlineopt.h b/internal/cmdlineopt.h
index e79b993345..aed209e2a2 100644
--- a/internal/cmdlineopt.h
+++ b/internal/cmdlineopt.h
@@ -1,7 +1,6 @@
#ifndef INTERNAL_CMDLINEOPT_H /*-*-C-*-vi:se ft=c:*/
#define INTERNAL_CMDLINEOPT_H
-#include "rjit.h"
#include "yjit.h"
typedef struct {
@@ -24,9 +23,6 @@ typedef struct ruby_cmdline_options {
ruby_features_t warn;
unsigned int dump;
long backtrace_length_limit;
-#if USE_RJIT
- struct rb_rjit_options rjit;
-#endif
const char *crash_report;
@@ -43,6 +39,9 @@ typedef struct ruby_cmdline_options {
#if USE_YJIT
unsigned int yjit: 1;
#endif
+#if USE_ZJIT
+ unsigned int zjit: 1;
+#endif
} ruby_cmdline_options_t;
struct ruby_opt_message {
diff --git a/internal/concurrent_set.h b/internal/concurrent_set.h
new file mode 100644
index 0000000000..76cbefab04
--- /dev/null
+++ b/internal/concurrent_set.h
@@ -0,0 +1,21 @@
+#ifndef RUBY_RACTOR_SAFE_TABLE_H
+#define RUBY_RACTOR_SAFE_TABLE_H
+
+#include "ruby/atomic.h"
+#include "ruby/ruby.h"
+
+struct rb_concurrent_set_funcs {
+ VALUE (*hash)(VALUE key);
+ bool (*cmp)(VALUE a, VALUE b);
+ VALUE (*create)(VALUE key, void *data);
+ void (*free)(VALUE key);
+};
+
+VALUE rb_concurrent_set_new(const struct rb_concurrent_set_funcs *funcs, int capacity);
+rb_atomic_t rb_concurrent_set_size(VALUE set_obj);
+VALUE rb_concurrent_set_find(VALUE *set_obj_ptr, VALUE key);
+VALUE rb_concurrent_set_find_or_insert(VALUE *set_obj_ptr, VALUE key, void *data);
+VALUE rb_concurrent_set_delete_by_identity(VALUE set_obj, VALUE key);
+void rb_concurrent_set_foreach_with_replace(VALUE set_obj, int (*callback)(VALUE *key, void *data), void *data);
+
+#endif
diff --git a/internal/cont.h b/internal/cont.h
index 3c2528a02a..dcf6f820a3 100644
--- a/internal/cont.h
+++ b/internal/cont.h
@@ -31,5 +31,4 @@ VALUE rb_fiber_inherit_storage(struct rb_execution_context_struct *ec, struct rb
VALUE rb_fiberptr_self(struct rb_fiber_struct *fiber);
unsigned int rb_fiberptr_blocking(struct rb_fiber_struct *fiber);
struct rb_execution_context_struct * rb_fiberptr_get_ec(struct rb_fiber_struct *fiber);
-
#endif /* INTERNAL_CONT_H */
diff --git a/internal/encoding.h b/internal/encoding.h
index fe9ea10ec4..38bf8fc9da 100644
--- a/internal/encoding.h
+++ b/internal/encoding.h
@@ -11,7 +11,6 @@
#include "ruby/ruby.h" /* for ID */
#include "ruby/encoding.h" /* for rb_encoding */
-#define rb_enc_autoload_p(enc) (!rb_enc_mbmaxlen(enc))
#define rb_is_usascii_enc(enc) ((enc) == rb_usascii_encoding())
#define rb_is_ascii8bit_enc(enc) ((enc) == rb_ascii8bit_encoding())
#define rb_is_locale_enc(enc) ((enc) == rb_locale_encoding())
@@ -24,10 +23,14 @@ 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);
+bool rb_enc_autoload_p(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_enc_raw_set(VALUE obj, rb_encoding *enc);
+int rb_enc_registered(const char *name);
+
PUREFUNC(int rb_data_is_encoding(VALUE obj));
/* vm.c */
diff --git a/internal/error.h b/internal/error.h
index 7a4daca6b3..ae9a13fcec 100644
--- a/internal/error.h
+++ b/internal/error.h
@@ -72,13 +72,14 @@ 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);
+PRINTF_ARGS(void rb_warn_reserved_name(const char *removal, const char *fmt, ...), 2, 3);
#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)
+# 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)
+# elif RBIMPL_COMPILER_IS(MSVC)
# define RBIMPL_TODO0(x) __pragma(message(x))
# endif
@@ -110,6 +111,14 @@ rb_deprecated_method_to_be_removed(const char *removal)
RBIMPL_ATTR_DIAGNOSE_IF(RUBY_VERSION_STRING_SINCE(removal), "deprecated method to be removed", "error")
{
}
+
+RBIMPL_ATTR_FORCEINLINE()
+static void
+rb_diagnose_reserved_name_at(const char *coming)
+ RBIMPL_ATTR_DIAGNOSE_IF(!RUBY_VERSION_isdigit(coming[0]), "malformed version number", "error")
+ RBIMPL_ATTR_DIAGNOSE_IF(RUBY_VERSION_STRING_SINCE(coming), "reserved name already in use", "error")
+{
+}
# else
RBIMPL_ATTR_ERROR(("deprecated"))
void rb_deprecated_method_to_be_removed(const char *);
@@ -117,16 +126,32 @@ void rb_deprecated_method_to_be_removed(const char *);
(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)
+
+RBIMPL_ATTR_ERROR(("deprecated"))
+void rb_diagnose_reserved_name_at(const char *);
+# define rb_diagnose_reserved_name_at(coming) \
+ (sizeof(char[1-2*(!RUBY_VERSION_isdigit(coming[0]) || RUBY_VERSION_STRING_SINCE(coming))])!=1 ? \
+ rb_diagnose_reserved_name_at(coming) : \
+ 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__))
+
+# define rb_warn_reserved_name_at(coming, ...) \
+ (rb_diagnose_reserved_name_at(#coming), \
+ rb_warn_reserved_name(#coming, __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 rb_warn_reserved_name_at
+# define rb_warn_reserved_name_at(removal, ...) \
+ rb_warn_reserved_name(#removal, __VA_ARGS__)
+#endif
#ifndef RUBY_VERSION_SINCE
# define RUBY_VERSION_SINCE(major, minor) 0
#endif
@@ -160,6 +185,7 @@ 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
+void rb_bug_without_die(const char *fmt, ...);
RUBY_SYMBOL_EXPORT_BEGIN
/* error.c (export) */
@@ -209,10 +235,18 @@ rb_key_err_raise(VALUE mesg, VALUE recv, VALUE name)
rb_exc_raise(exc);
}
+RBIMPL_ATTR_NONNULL((2))
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);
+ return rbimpl_obj_typeddata_p(obj) && (RTYPEDDATA_TYPE(obj) == data_type);
}
+typedef enum {
+ rb_stack_overflow_prevention = 0, // VM stack overflow or about to machine stack overflow
+ rb_stack_overflow_signal = 1, // machine stack overflow but may be recoverable
+ rb_stack_overflow_fatal = 2, // fatal machine stack overflow
+} ruby_stack_overflow_critical_level;
+NORETURN(void rb_ec_stack_overflow(struct rb_execution_context_struct *ec, ruby_stack_overflow_critical_level crit));
+
#endif /* INTERNAL_ERROR_H */
diff --git a/internal/eval.h b/internal/eval.h
index e594d8516d..17ade0a7f1 100644
--- a/internal/eval.h
+++ b/internal/eval.h
@@ -11,17 +11,27 @@
* header (related to this file, but not the same role).
*/
#include "ruby/ruby.h" /* for ID */
+#include "vm_core.h" /* for ID */
#define id_signo ruby_static_id_signo
#define id_status ruby_static_id_status
/* eval.c */
+struct rb_refinements_data {
+ VALUE refinement;
+ VALUE refinements;
+};
+
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));
+VALUE rb_exception_setup(int argc, VALUE *argv);
+void rb_refinement_setup(struct rb_refinements_data *data, VALUE module, VALUE klass);
+void rb_vm_using_module(VALUE module);
VALUE rb_top_main_class(const char *method);
+VALUE rb_ec_ensure(rb_execution_context_t *ec, VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2);
/* eval_error.c */
VALUE rb_get_backtrace(VALUE info);
diff --git a/internal/fixnum.h b/internal/fixnum.h
index 8c251adef1..b78e31460e 100644
--- a/internal/fixnum.h
+++ b/internal/fixnum.h
@@ -10,6 +10,7 @@
*/
#include "ruby/internal/config.h" /* for HAVE_LONG_LONG */
#include <limits.h> /* for CHAR_BIT */
+#include "internal/bits.h" /* for MUL_OVERFLOW_FIXNUM_P */
#include "internal/compilers.h" /* for __has_builtin */
#include "ruby/internal/stdbool.h" /* for bool */
#include "ruby/intern.h" /* for rb_big_mul */
diff --git a/internal/gc.h b/internal/gc.h
index ecc3f11b2c..ee1f390e10 100644
--- a/internal/gc.h
+++ b/internal/gc.h
@@ -16,8 +16,8 @@
#include "ruby/ruby.h" /* for rb_event_flag_t */
#include "vm_core.h" /* for GET_EC() */
-#ifndef USE_SHARED_GC
-# define USE_SHARED_GC 0
+#ifndef USE_MODULAR_GC
+# define USE_MODULAR_GC 0
#endif
#if defined(__x86_64__) && !defined(_ILP32) && defined(__GNUC__)
@@ -122,12 +122,20 @@ const char *rb_raw_obj_info(char *const buff, const size_t buff_size, VALUE obj)
struct rb_execution_context_struct; /* in vm_core.h */
struct rb_objspace; /* in vm_core.h */
-#define NEWOBJ_OF(var, T, c, f, s, ec) \
+#define NEWOBJ_OF_WITH_SHAPE(var, T, c, f, shape_id, s, ec) \
T *(var) = (T *)(((f) & FL_WB_PROTECTED) ? \
- rb_wb_protected_newobj_of((ec ? ec : GET_EC()), (c), (f) & ~FL_WB_PROTECTED, s) : \
- rb_wb_unprotected_newobj_of((c), (f), s))
+ rb_wb_protected_newobj_of((ec ? ec : GET_EC()), (c), (f) & ~FL_WB_PROTECTED, shape_id, s) : \
+ rb_wb_unprotected_newobj_of((c), (f), shape_id, s))
-#define RB_OBJ_GC_FLAGS_MAX 6 /* used in ext/objspace */
+#define NEWOBJ_OF(var, T, c, f, s, ec) NEWOBJ_OF_WITH_SHAPE(var, T, c, f, 0 /* ROOT_SHAPE_ID */, s, ec)
+
+#ifndef RB_GC_OBJECT_METADATA_ENTRY_DEFINED
+# define RB_GC_OBJECT_METADATA_ENTRY_DEFINED
+struct rb_gc_object_metadata_entry {
+ ID name;
+ VALUE val;
+};
+#endif
#ifndef USE_UNALIGNED_MEMBER_ACCESS
# define UNALIGNED_MEMBER_ACCESS(expr) (expr)
@@ -163,12 +171,6 @@ struct rb_objspace; /* in vm_core.h */
RB_OBJ_WRITE(old, _slot, young); \
} while (0)
-// We use SIZE_POOL_COUNT number of shape IDs for transitions out of different size pools
-// The next available shape ID will be the SPECIAL_CONST_SHAPE_ID
-#ifndef SIZE_POOL_COUNT
-# define SIZE_POOL_COUNT 5
-#endif
-
/* Used in places that could malloc during, which can cause the GC to run. We
* need to temporarily disable the GC to allow the malloc to happen.
* Allocating memory during GC is a bad idea, so use this only when absolutely
@@ -180,25 +182,14 @@ struct rb_objspace; /* in vm_core.h */
#define DURING_GC_COULD_MALLOC_REGION_END() \
if (_already_disabled == Qfalse) rb_gc_enable()
-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 {
- size_t incremental_mark_step_allocated_slots;
- rb_ractor_newobj_size_pool_cache_t size_pool_caches[SIZE_POOL_COUNT];
-} rb_ractor_newobj_cache_t;
-
/* gc.c */
-extern int ruby_disable_gc;
RUBY_ATTR_MALLOC void *ruby_mimmalloc(size_t size);
RUBY_ATTR_MALLOC void *ruby_mimcalloc(size_t num, size_t size);
void ruby_mimfree(void *ptr);
void rb_gc_prepare_heap(void);
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 *);
+VALUE rb_objspace_gc_enable(void *objspace);
+VALUE rb_objspace_gc_disable(void *objspace);
void ruby_gc_set_params(void);
void rb_gc_copy_attributes(VALUE dest, VALUE obj);
size_t rb_size_mul_or_raise(size_t, size_t, VALUE); /* used in compile.c */
@@ -212,22 +203,28 @@ 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);
-void rb_gc_ractor_newobj_cache_clear(rb_ractor_newobj_cache_t *newobj_cache);
+void rb_gc_obj_id_moved(VALUE obj);
+void rb_gc_register_pinning_obj(VALUE obj);
+
+void *rb_gc_ractor_cache_alloc(rb_ractor_t *ractor);
+void rb_gc_ractor_cache_free(void *cache);
+
bool rb_gc_size_allocatable_p(size_t size);
-size_t *rb_gc_size_pool_sizes(void);
-size_t rb_gc_size_pool_id_for_size(size_t size);
-int rb_objspace_garbage_object_p(VALUE obj);
-bool rb_gc_is_ptr_to_obj(const void *ptr);
+size_t *rb_gc_heap_sizes(void);
+size_t rb_gc_heap_id_for_size(size_t size);
void rb_gc_mark_and_move(VALUE *ptr);
-void rb_gc_mark_weak(VALUE *ptr);
-void rb_gc_remove_weak(VALUE parent_obj, VALUE *ptr);
+void rb_gc_declare_weak_references(VALUE obj);
+bool rb_gc_handle_weak_references_alive_p(VALUE obj);
void rb_gc_ref_update_table_values_only(st_table *tbl);
void rb_gc_initial_stress_set(VALUE flag);
+void rb_gc_before_fork(void);
+void rb_gc_after_fork(rb_pid_t pid);
+
#define rb_gc_mark_and_move_ptr(ptr) do { \
VALUE _obj = (VALUE)*(ptr); \
rb_gc_mark_and_move(&_obj); \
@@ -238,8 +235,9 @@ RUBY_SYMBOL_EXPORT_BEGIN
/* exports for objspace module */
void rb_objspace_reachable_objects_from(VALUE obj, void (func)(VALUE, void *), void *data);
void rb_objspace_reachable_objects_from_root(void (func)(const char *category, VALUE, void *), void *data);
-int rb_objspace_markable_object_p(VALUE obj);
int rb_objspace_internal_object_p(VALUE obj);
+int rb_objspace_garbage_object_p(VALUE obj);
+bool rb_gc_pointer_to_heap_p(VALUE obj);
void rb_objspace_each_objects(
int (*callback)(void *start, void *end, size_t stride, void *data),
@@ -249,25 +247,50 @@ size_t rb_gc_obj_slot_size(VALUE obj);
VALUE rb_gc_disable_no_rest(void);
+#define RB_GC_MAX_NAME_LEN 20
/* gc.c (export) */
const char *rb_objspace_data_type_name(VALUE obj);
-VALUE rb_wb_protected_newobj_of(struct rb_execution_context_struct *, VALUE, VALUE, size_t);
-VALUE rb_wb_unprotected_newobj_of(VALUE, VALUE, size_t);
+VALUE rb_wb_protected_newobj_of(struct rb_execution_context_struct *, VALUE, VALUE, uint32_t /* shape_id_t */, size_t);
+VALUE rb_wb_unprotected_newobj_of(VALUE, VALUE, uint32_t /* shape_id_t */, 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);
+struct rb_gc_object_metadata_entry *rb_gc_object_metadata(VALUE obj);
void rb_gc_mark_values(long n, const VALUE *values);
void rb_gc_mark_vm_stack_values(long n, const VALUE *values);
void rb_gc_update_values(long n, 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);
+
+const char *rb_gc_active_gc_name(void);
+int rb_gc_modular_gc_loaded_p(void);
+
RUBY_SYMBOL_EXPORT_END
+static inline VALUE
+rb_obj_atomic_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
+
+ RUBY_ATOMIC_VALUE_SET(*slot, b);
+
+ rb_obj_written(a, RUBY_Qundef /* ignore `oldv' now */, b, filename, line);
+ return a;
+}
+#define RB_OBJ_ATOMIC_WRITE(old, slot, young) \
+ RBIMPL_CAST(rb_obj_atomic_write((VALUE)(old), (VALUE *)(slot), (VALUE)(young), __FILE__, __LINE__))
+
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);
+void ruby_annotate_mmap(const void *addr, unsigned long size, const char *name);
#if defined(HAVE_MALLOC_USABLE_SIZE) || defined(HAVE_MALLOC_SIZE) || defined(_WIN32)
@@ -331,4 +354,8 @@ ruby_sized_realloc_n(void *ptr, size_t new_count, size_t element_size, size_t ol
#define ruby_sized_xrealloc ruby_sized_xrealloc_inlined
#define ruby_sized_xrealloc2 ruby_sized_xrealloc2_inlined
#define ruby_sized_xfree ruby_sized_xfree_inlined
+
+void rb_gc_verify_shareable(VALUE);
+bool rb_gc_checking_shareable(void);
+
#endif /* INTERNAL_GC_H */
diff --git a/internal/hash.h b/internal/hash.h
index fe859cb716..03cd830506 100644
--- a/internal/hash.h
+++ b/internal/hash.h
@@ -72,6 +72,7 @@ struct RHash {
/* 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(VALUE hash, VALUE ifnone);
VALUE rb_hash_set_default_proc(VALUE hash, VALUE proc);
long rb_dbl_long_hash(double d);
st_table *rb_init_identtable(void);
@@ -86,8 +87,10 @@ 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);
+bool rb_hash_default_unredefined(VALUE hash);
VALUE rb_ident_hash_new_with_size(st_index_t size);
void rb_hash_free(VALUE hash);
+RUBY_EXTERN VALUE rb_cHash_empty_frozen;
static inline unsigned RHASH_AR_TABLE_SIZE_RAW(VALUE h);
static inline VALUE RHASH_IFNONE(VALUE h);
diff --git a/internal/imemo.h b/internal/imemo.h
index 36c0776987..31cc0be35a 100644
--- a/internal/imemo.h
+++ b/internal/imemo.h
@@ -10,14 +10,11 @@
*/
#include "ruby/internal/config.h"
#include <stddef.h> /* for size_t */
+#include "id_table.h"
#include "internal/array.h" /* for rb_ary_hidden_new_fill */
#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 */
@@ -28,6 +25,7 @@
#define IMEMO_FL_USER3 FL_USER7
#define IMEMO_FL_USER4 FL_USER8
#define IMEMO_FL_USER5 FL_USER9
+#define IMEMO_FL_USER6 FL_USER10
enum imemo_type {
imemo_env = 0,
@@ -39,11 +37,10 @@ enum imemo_type {
imemo_ment = 6,
imemo_iseq = 7,
imemo_tmpbuf = 8,
- imemo_ast = 9, // Obsolete due to the universal parser
- imemo_parser_strterm = 10,
- imemo_callinfo = 11,
- imemo_callcache = 12,
- imemo_constcache = 13,
+ imemo_callinfo = 10,
+ imemo_callcache = 11,
+ imemo_constcache = 12,
+ imemo_fields = 13,
};
/* CREF (Class REFerence) is defined in method.h */
@@ -79,7 +76,12 @@ struct vm_ifunc_argc {
#endif
};
-/*! IFUNC (Internal FUNCtion) */
+/*! IFUNC (Internal FUNCtion)
+ *
+ * Bookkeeping for converting a C function and some closed-over data into a
+ * block passable to methods. Like Ruby Proc, but not directly accessible at
+ * Ruby level since this is an imemo. See rb_block_call() and friends.
+ */
struct vm_ifunc {
VALUE flags;
VALUE *svar_lep;
@@ -87,12 +89,11 @@ struct vm_ifunc {
const void *data;
struct vm_ifunc_argc argc;
};
+#define IFUNC_YIELD_OPTIMIZABLE IMEMO_FL_USER0
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 */
};
@@ -113,7 +114,8 @@ struct MEMO {
} u3;
};
-#define IMEMO_NEW(T, type, v0) ((T *)rb_imemo_new((type), (v0)))
+#define IMEMO_NEW(T, type, v0) ((T *)rb_imemo_new((type), (v0), sizeof(T), false))
+#define SHAREABLE_IMEMO_NEW(T, type, v0) ((T *)rb_imemo_new((type), (v0), sizeof(T), true))
/* ment is in method.h */
@@ -130,46 +132,27 @@ struct MEMO {
#ifndef RUBY_RUBYPARSER_H
typedef struct rb_imemo_tmpbuf_struct rb_imemo_tmpbuf_t;
#endif
-rb_imemo_tmpbuf_t *rb_imemo_tmpbuf_parser_heap(void *buf, rb_imemo_tmpbuf_t *old_heap, size_t cnt);
+VALUE rb_imemo_new(enum imemo_type type, VALUE v0, size_t size, bool is_shareable);
+VALUE rb_imemo_tmpbuf_new(void);
+struct MEMO *rb_imemo_memo_new(VALUE a, VALUE b, VALUE c);
struct vm_ifunc *rb_vm_ifunc_new(rb_block_call_func_t func, const void *data, int min_argc, int max_argc);
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);
size_t rb_imemo_memsize(VALUE obj);
-void rb_cc_table_mark(VALUE klass);
void rb_imemo_mark_and_move(VALUE obj, bool reference_updating);
-void rb_cc_table_free(VALUE klass);
void rb_imemo_free(VALUE obj);
RUBY_SYMBOL_EXPORT_BEGIN
-#if IMEMO_DEBUG
-VALUE rb_imemo_new_debug(enum imemo_type type, 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 v0);
-#endif
const char *rb_imemo_name(enum imemo_type type);
RUBY_SYMBOL_EXPORT_END
-static inline struct MEMO *
-MEMO_NEW(VALUE a, VALUE b, VALUE c)
-{
- struct MEMO *memo = IMEMO_NEW(struct MEMO, imemo_memo, 0);
- *((VALUE *)&memo->v1) = a;
- *((VALUE *)&memo->v2) = b;
- *((VALUE *)&memo->u3.value) = c;
-
- return memo;
-}
-
static inline enum imemo_type
imemo_type(VALUE imemo)
{
@@ -205,12 +188,6 @@ 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);
-}
-
static inline void *
RB_IMEMO_TMPBUF_PTR(VALUE v)
{
@@ -225,7 +202,7 @@ rb_imemo_tmpbuf_set_ptr(VALUE v, void *ptr)
}
static inline VALUE
-rb_imemo_tmpbuf_auto_free_pointer_new_from_an_RString(VALUE str)
+rb_imemo_tmpbuf_new_from_an_RString(VALUE str)
{
const void *src;
VALUE imemo;
@@ -235,7 +212,7 @@ rb_imemo_tmpbuf_auto_free_pointer_new_from_an_RString(VALUE str)
StringValue(str);
/* create tmpbuf to keep the pointer before xmalloc */
- imemo = rb_imemo_tmpbuf_auto_free_pointer();
+ imemo = rb_imemo_tmpbuf_new();
tmpbuf = (rb_imemo_tmpbuf_t *)imemo;
len = RSTRING_LEN(str);
src = RSTRING_PTR(str);
@@ -257,4 +234,79 @@ MEMO_V2_SET(struct MEMO *m, VALUE v)
RB_OBJ_WRITE(m, &m->v2, v);
}
+struct rb_fields {
+ struct RBasic basic;
+ union {
+ struct {
+ VALUE fields[1];
+ } embed;
+ struct {
+ VALUE *ptr;
+ } external;
+ struct {
+ // Note: the st_table could be embedded, but complex T_CLASS should be rare to
+ // non-existent, so not really worth the trouble.
+ st_table *table;
+ } complex;
+ } as;
+};
+
+// IMEMO/fields and T_OBJECT have exactly the same layout.
+// This is useful for JIT and common codepaths.
+#define OBJ_FIELD_HEAP ROBJECT_HEAP
+STATIC_ASSERT(imemo_fields_flags, OBJ_FIELD_HEAP == IMEMO_FL_USER0);
+STATIC_ASSERT(imemo_fields_embed_offset, offsetof(struct RObject, as.ary) == offsetof(struct rb_fields, as.embed.fields));
+STATIC_ASSERT(imemo_fields_external_offset, offsetof(struct RObject, as.heap.fields) == offsetof(struct rb_fields, as.external.ptr));
+STATIC_ASSERT(imemo_fields_complex_offset, offsetof(struct RObject, as.heap.fields) == offsetof(struct rb_fields, as.complex.table));
+
+#define IMEMO_OBJ_FIELDS(fields) ((struct rb_fields *)fields)
+
+VALUE rb_imemo_fields_new(VALUE owner, size_t capa, bool shareable);
+VALUE rb_imemo_fields_new_complex(VALUE owner, size_t capa, bool shareable);
+VALUE rb_imemo_fields_new_complex_tbl(VALUE owner, st_table *tbl, bool shareable);
+VALUE rb_imemo_fields_clone(VALUE fields_obj);
+void rb_imemo_fields_clear(VALUE fields_obj);
+
+static inline VALUE
+rb_imemo_fields_owner(VALUE fields_obj)
+{
+ RUBY_ASSERT(IMEMO_TYPE_P(fields_obj, imemo_fields));
+
+ return CLASS_OF(fields_obj);
+}
+
+static inline VALUE *
+rb_imemo_fields_ptr(VALUE fields_obj)
+{
+ if (!fields_obj) {
+ return NULL;
+ }
+
+ RUBY_ASSERT(IMEMO_TYPE_P(fields_obj, imemo_fields) || RB_TYPE_P(fields_obj, T_OBJECT));
+
+ if (UNLIKELY(FL_TEST_RAW(fields_obj, OBJ_FIELD_HEAP))) {
+ return IMEMO_OBJ_FIELDS(fields_obj)->as.external.ptr;
+ }
+ else {
+ return IMEMO_OBJ_FIELDS(fields_obj)->as.embed.fields;
+ }
+}
+
+static inline st_table *
+rb_imemo_fields_complex_tbl(VALUE fields_obj)
+{
+ if (!fields_obj) {
+ return NULL;
+ }
+
+ RUBY_ASSERT(IMEMO_TYPE_P(fields_obj, imemo_fields) || RB_TYPE_P(fields_obj, T_OBJECT));
+ RUBY_ASSERT(FL_TEST_RAW(fields_obj, OBJ_FIELD_HEAP));
+
+ // Some codepaths unconditionally access the fields_ptr, and assume it can be used as st_table if the
+ // shape is too_complex.
+ RUBY_ASSERT((st_table *)rb_imemo_fields_ptr(fields_obj) == IMEMO_OBJ_FIELDS(fields_obj)->as.complex.table);
+
+ return IMEMO_OBJ_FIELDS(fields_obj)->as.complex.table;
+}
+
#endif /* INTERNAL_IMEMO_H */
diff --git a/internal/inits.h b/internal/inits.h
index 03de289dd4..dee818285c 100644
--- a/internal/inits.h
+++ b/internal/inits.h
@@ -9,6 +9,10 @@
* @brief Internal header aggregating init functions.
*/
+/* box.c */
+void Init_enable_box(void);
+void Init_root_box(void);
+
/* class.c */
void Init_class_hierarchy(void);
diff --git a/internal/io.h b/internal/io.h
index 1891248a19..b81774e0a7 100644
--- a/internal/io.h
+++ b/internal/io.h
@@ -14,10 +14,21 @@
struct rb_io;
#include "ruby/io.h" /* for rb_io_t */
+#include "ccan/list/list.h"
+#include "serial.h"
-#define IO_WITHOUT_GVL(func, arg) rb_thread_call_without_gvl(func, arg, RUBY_UBF_IO, 0)
+#define IO_WITHOUT_GVL(func, arg) rb_nogvl(func, arg, RUBY_UBF_IO, 0, RB_NOGVL_OFFLOAD_SAFE)
#define IO_WITHOUT_GVL_INT(func, arg) (int)(VALUE)IO_WITHOUT_GVL(func, arg)
+// Represents an in-flight blocking operation:
+struct rb_io_blocking_operation {
+ // The linked list data structure.
+ struct ccan_list_node list;
+
+ // The execution context of the blocking operation.
+ struct rb_execution_context_struct *ec;
+};
+
/** Ruby's IO, metadata and buffers. */
struct rb_io {
@@ -31,7 +42,7 @@ struct rb_io {
int fd;
/** mode flags: FMODE_XXXs */
- int mode;
+ enum rb_io_mode mode;
/** child's pid (for pipes) */
rb_pid_t pid;
@@ -111,6 +122,18 @@ struct rb_io {
* The timeout associated with this IO when performing blocking operations.
*/
VALUE timeout;
+
+ /**
+ * Threads that are performing a blocking operation without the GVL using
+ * this IO. On calling IO#close, these threads will be interrupted so that
+ * the operation can be cancelled.
+ */
+ struct ccan_list_head blocking_operations;
+ struct rb_execution_context_struct *closing_ec;
+ VALUE wakeup_mutex;
+
+ // The fork generation of the blocking operations list.
+ rb_serial_t fork_generation;
};
/* io.c */
@@ -119,22 +142,22 @@ 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);
+int rb_io_notify_close(struct rb_io *fptr);
+
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);
+
+VALUE rb_io_blocking_region_wait(struct rb_io *io, rb_blocking_function_t *function, void *argument, enum rb_io_event events);
+VALUE rb_io_blocking_region(struct rb_io *io, rb_blocking_function_t *function, void *argument);
RUBY_SYMBOL_EXPORT_END
#endif /* INTERNAL_IO_H */
diff --git a/internal/load.h b/internal/load.h
index d4c0bb91ba..fb880a43ba 100644
--- a/internal/load.h
+++ b/internal/load.h
@@ -12,6 +12,8 @@
/* load.c */
VALUE rb_get_expanded_load_path(void);
+VALUE rb_load_entrypoint(VALUE args);
+VALUE rb_require_relative_entrypoint(VALUE fname);
int rb_require_internal(VALUE fname);
NORETURN(void rb_load_fail(VALUE, const char*));
diff --git a/internal/numeric.h b/internal/numeric.h
index 6406cfc2fa..d3905f048c 100644
--- a/internal/numeric.h
+++ b/internal/numeric.h
@@ -85,6 +85,7 @@ 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_xor(VALUE x, VALUE y);
VALUE rb_int_lshift(VALUE x, VALUE y);
VALUE rb_int_rshift(VALUE x, VALUE y);
VALUE rb_int_div(VALUE x, VALUE y);
@@ -126,6 +127,54 @@ VALUE rb_int_bit_length(VALUE num);
VALUE rb_int_uminus(VALUE num);
VALUE rb_int_comp(VALUE num);
+// Unified 128-bit integer structures that work with or without native support:
+union rb_uint128 {
+#ifdef WORDS_BIGENDIAN
+ struct {
+ uint64_t high;
+ uint64_t low;
+ } parts;
+#else
+ struct {
+ uint64_t low;
+ uint64_t high;
+ } parts;
+#endif
+#ifdef HAVE_UINT128_T
+ uint128_t value;
+#endif
+};
+typedef union rb_uint128 rb_uint128_t;
+
+union rb_int128 {
+#ifdef WORDS_BIGENDIAN
+ struct {
+ uint64_t high;
+ uint64_t low;
+ } parts;
+#else
+ struct {
+ uint64_t low;
+ uint64_t high;
+ } parts;
+#endif
+#ifdef HAVE_UINT128_T
+ int128_t value;
+#endif
+};
+typedef union rb_int128 rb_int128_t;
+
+union uint128_int128_conversion {
+ rb_uint128_t uint128;
+ rb_int128_t int128;
+};
+
+// Conversion functions for 128-bit integers:
+rb_uint128_t rb_numeric_to_uint128(VALUE x);
+rb_int128_t rb_numeric_to_int128(VALUE x);
+VALUE rb_uint128_to_numeric(rb_uint128_t n);
+VALUE rb_int128_to_numeric(rb_int128_t n);
+
static inline bool
INT_POSITIVE_P(VALUE num)
{
diff --git a/internal/object.h b/internal/object.h
index 92ad37fdc8..3bde53c31b 100644
--- a/internal/object.h
+++ b/internal/object.h
@@ -11,7 +11,7 @@
#include "ruby/ruby.h" /* for VALUE */
/* object.c */
-size_t rb_obj_embedded_size(uint32_t numiv);
+size_t rb_obj_embedded_size(uint32_t fields_count);
VALUE rb_class_allocate_instance(VALUE klass);
VALUE rb_class_search_ancestor(VALUE klass, VALUE super);
NORETURN(void rb_undefined_alloc(VALUE klass));
diff --git a/internal/parse.h b/internal/parse.h
index 4a9c4acf8a..8e04664ae8 100644
--- a/internal/parse.h
+++ b/internal/parse.h
@@ -12,6 +12,17 @@
#include "rubyparser.h"
#include "internal/static_assert.h"
+// The default parser to use for Ruby code.
+typedef enum {
+ RB_DEFAULT_PARSER_PARSE_Y,
+ RB_DEFAULT_PARSER_PRISM,
+} ruby_default_parser_enum;
+
+ruby_default_parser_enum rb_ruby_default_parser(void);
+void rb_ruby_default_parser_set(ruby_default_parser_enum parser);
+
+#define rb_ruby_prism_p() (rb_ruby_default_parser() == RB_DEFAULT_PARSER_PRISM)
+
#ifdef UNIVERSAL_PARSER
#define rb_encoding const void
#endif
@@ -63,12 +74,15 @@ rb_encoding *rb_ruby_parser_encoding(rb_parser_t *p);
int rb_ruby_parser_end_seen_p(rb_parser_t *p);
int rb_ruby_parser_set_yydebug(rb_parser_t *p, int flag);
rb_parser_string_t *rb_str_to_parser_string(rb_parser_t *p, VALUE str);
+void rb_parser_string_free(rb_parser_t *p, rb_parser_string_t *str);
int rb_parser_dvar_defined_ref(struct parser_params*, ID, ID**);
ID rb_parser_internal_id(struct parser_params*);
-int rb_parser_reg_fragment_check(struct parser_params*, rb_parser_string_t*, int);
-int rb_reg_named_capture_assign_iter_impl(struct parser_params *p, const char *s, long len, rb_encoding *enc, NODE **succ_block, const rb_code_location_t *loc);
+typedef void (*rb_parser_reg_fragment_error_func)(struct parser_params *, VALUE);
+int rb_parser_reg_fragment_check(struct parser_params*, rb_parser_string_t*, int, rb_parser_reg_fragment_error_func);
+int rb_reg_named_capture_assign_iter_impl(struct parser_params *p, const char *s, long len, rb_encoding *enc, NODE **succ_block, const rb_code_location_t *loc, rb_parser_assignable_func assignable);
int rb_parser_local_defined(struct parser_params *p, ID id, const struct rb_iseq_struct *iseq);
+NODE *rb_parser_assignable(struct parser_params *p, ID id, NODE *val, const YYLTYPE *loc);
RUBY_SYMBOL_EXPORT_END
@@ -97,7 +111,7 @@ VALUE rb_ruby_parser_ruby_sourcefile_string(rb_parser_t *p);
int rb_ruby_parser_ruby_sourceline(rb_parser_t *p);
int rb_ruby_parser_lex_state(rb_parser_t *p);
void rb_ruby_ripper_parse0(rb_parser_t *p);
-int rb_ruby_ripper_dedent_string(rb_parser_t *p, VALUE string, int width);
+int rb_ruby_ripper_dedent_string(rb_parser_t *p, rb_parser_string_t *string, int width);
int rb_ruby_ripper_initialized_p(rb_parser_t *p);
void rb_ruby_ripper_parser_initialize(rb_parser_t *p);
long rb_ruby_ripper_column(rb_parser_t *p);
diff --git a/internal/proc.h b/internal/proc.h
index c75f15b283..24a077ca6d 100644
--- a/internal/proc.h
+++ b/internal/proc.h
@@ -22,7 +22,7 @@ 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);
-VALUE rb_func_proc_new(rb_block_call_func_t func, VALUE val);
+VALUE rb_func_proc_dup(VALUE src_obj);
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);
diff --git a/internal/ractor.h b/internal/ractor.h
index eef5ffdb89..a65907a05a 100644
--- a/internal/ractor.h
+++ b/internal/ractor.h
@@ -3,4 +3,8 @@
void rb_ractor_ensure_main_ractor(const char *msg);
+RUBY_SYMBOL_EXPORT_BEGIN
+void rb_ractor_setup_belonging(VALUE obj);
+RUBY_SYMBOL_EXPORT_END
+
#endif /* INTERNAL_RACTOR_H */
diff --git a/internal/range.h b/internal/range.h
index 2394937bf8..80493ce13e 100644
--- a/internal/range.h
+++ b/internal/range.h
@@ -18,19 +18,19 @@ static inline VALUE RANGE_EXCL(VALUE r);
static inline VALUE
RANGE_BEG(VALUE r)
{
- return RSTRUCT(r)->as.ary[0];
+ return RSTRUCT_GET_RAW(r, 0);
}
static inline VALUE
RANGE_END(VALUE r)
{
- return RSTRUCT_GET(r, 1);
+ return RSTRUCT_GET_RAW(r, 1);
}
static inline VALUE
RANGE_EXCL(VALUE r)
{
- return RSTRUCT_GET(r, 2);
+ return RSTRUCT_GET_RAW(r, 2);
}
VALUE
diff --git a/internal/re.h b/internal/re.h
index 3e20114665..593e5c464f 100644
--- a/internal/re.h
+++ b/internal/re.h
@@ -14,15 +14,20 @@
/* 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);
+long rb_reg_search0(VALUE, VALUE, long, int, int, VALUE *);
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);
+VALUE rb_backref_set_string(VALUE string, long pos, long len);
void rb_match_unbusy(VALUE);
int rb_match_count(VALUE match);
VALUE rb_reg_new_ary(VALUE ary, int options);
VALUE rb_reg_last_defined(VALUE match);
+#define ARG_REG_OPTION_MASK \
+ (ONIG_OPTION_IGNORECASE|ONIG_OPTION_MULTILINE|ONIG_OPTION_EXTEND)
+#define ARG_ENCODING_FIXED 16
+#define ARG_ENCODING_NONE 32
+
#endif /* INTERNAL_RE_H */
diff --git a/internal/sanitizers.h b/internal/sanitizers.h
index b0eb1fc851..feafb4e616 100644
--- a/internal/sanitizers.h
+++ b/internal/sanitizers.h
@@ -16,7 +16,7 @@
#endif
#ifdef HAVE_SANITIZER_ASAN_INTERFACE_H
-# if __has_feature(address_sanitizer)
+# if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
# define RUBY_ASAN_ENABLED
# include <sanitizer/asan_interface.h>
# endif
@@ -29,6 +29,13 @@
# endif
#endif
+#ifdef HAVE_SANITIZER_TSAN_INTERFACE_H
+# if __has_feature(thread_sanitizer) || defined(__SANITIZE_THREAD__)
+# define RUBY_TSAN_ENABLED
+# include <sanitizer/tsan_interface.h>
+# endif
+#endif
+
#include "ruby/internal/stdbool.h" /* for bool */
#include "ruby/ruby.h" /* for VALUE */
@@ -39,6 +46,12 @@
#elif defined(RUBY_ASAN_ENABLED)
# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \
__attribute__((__no_sanitize__("address"), __noinline__)) x
+#elif defined(RUBY_MSAN_ENABLED)
+ # define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \
+ __attribute__((__no_sanitize__("memory"), __noinline__)) x
+#elif defined(RUBY_TSAN_ENABLED)
+# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \
+ __attribute__((__no_sanitize__("thread"), __noinline__)) x
#elif defined(NO_SANITIZE_ADDRESS)
# define ATTRIBUTE_NO_ADDRESS_SAFETY_ANALYSIS(x) \
NO_SANITIZE_ADDRESS(NOINLINE(x))
@@ -54,10 +67,11 @@
# include "internal/warnings.h"
# undef NO_SANITIZE
# define NO_SANITIZE(x, y) \
- COMPILER_WARNING_PUSH; \
- COMPILER_WARNING_IGNORED(-Wattributes); \
+ COMPILER_WARNING_PUSH \
+ COMPILER_WARNING_IGNORED(-Wattributes) \
__attribute__((__no_sanitize__(x))) y; \
- COMPILER_WARNING_POP
+ COMPILER_WARNING_POP \
+ y
#endif
#ifndef NO_SANITIZE
@@ -115,26 +129,23 @@ asan_poison_memory_region(const volatile void *ptr, size_t 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);
-}
-
#ifdef RUBY_ASAN_ENABLED
#define asan_poison_object_if(ptr, obj) do { \
- if (ptr) asan_poison_object(obj); \
+ if (ptr) rb_asan_poison_object(obj); \
} while (0)
#else
#define asan_poison_object_if(ptr, obj) ((void)(ptr), (void)(obj))
#endif
+#ifdef RUBY_ASAN_ENABLED
+RUBY_SYMBOL_EXPORT_BEGIN
+/**
+ * This is a variant of asan_poison_memory_region that takes a VALUE.
+ *
+ * @param[in] obj target object.
+ */
+void rb_asan_poison_object(VALUE obj);
+
/**
* This function predicates if the given object is fully addressable or not.
*
@@ -142,12 +153,22 @@ asan_poison_object(VALUE obj)
* @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);
-}
+void *rb_asan_poisoned_object_p(VALUE obj);
+
+/**
+ * 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.
+ */
+void rb_asan_unpoison_object(VALUE obj, bool newobj_p);
+
+RUBY_SYMBOL_EXPORT_END
+#else
+# define rb_asan_poison_object(obj) ((void)obj)
+# define rb_asan_poisoned_object_p(obj) ((void)obj, NULL)
+# define rb_asan_unpoison_object(obj, newobj_p) ((void)obj, (void)newobj_p)
+#endif
/**
* This function asserts that a (formally poisoned) memory region from ptr to
@@ -176,24 +197,11 @@ asan_unpoison_memory_region(const volatile void *ptr, size_t size, bool malloc_p
}
}
-/**
- * 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);
-}
-
static inline void *
asan_unpoison_object_temporary(VALUE obj)
{
- void *ptr = asan_poisoned_object_p(obj);
- asan_unpoison_object(obj, false);
+ void *ptr = rb_asan_poisoned_object_p(obj);
+ rb_asan_unpoison_object(obj, false);
return ptr;
}
@@ -201,11 +209,40 @@ static inline void *
asan_poison_object_restore(VALUE obj, void *ptr)
{
if (ptr) {
- asan_poison_object(obj);
+ rb_asan_poison_object(obj);
}
return NULL;
}
+#define asan_unpoisoning_object(obj) \
+ for (void *poisoned = asan_unpoison_object_temporary(obj), \
+ *unpoisoning = &poisoned; /* flag to loop just once */ \
+ unpoisoning; \
+ unpoisoning = asan_poison_object_restore(obj, poisoned))
+
+
+static inline void *
+asan_unpoison_memory_region_temporary(void *ptr, size_t len)
+{
+ void *poisoned_ptr = __asan_region_is_poisoned(ptr, len);
+ asan_unpoison_memory_region(ptr, len, false);
+ return poisoned_ptr;
+}
+
+static inline void *
+asan_poison_memory_region_restore(void *ptr, size_t len, void *poisoned_ptr)
+{
+ if (poisoned_ptr) {
+ asan_poison_memory_region(ptr, len);
+ }
+ return NULL;
+}
+
+#define asan_unpoisoning_memory_region(ptr, len) \
+ for (void *poisoned = asan_unpoison_memory_region_temporary(ptr, len), \
+ *unpoisoning = &poisoned; /* flag to loop just once */ \
+ unpoisoning; \
+ unpoisoning = asan_poison_memory_region_restore(ptr, len, poisoned))
/**
* Checks if the given pointer is on an ASAN fake stack. If so, it returns the
@@ -293,5 +330,17 @@ asan_get_fake_stack_extents(void *thread_fake_stack_handle, VALUE slot,
return false;
}
+extern const char ruby_asan_default_options[];
+
+#ifdef RUBY_ASAN_ENABLED
+/* Compile in the ASAN options Ruby needs, rather than relying on environment variables, so
+ * that even tests which fork ruby with a clean environment will run ASAN with the right
+ * settings */
+# undef RUBY__ASAN_DEFAULT_OPTIONS
+# define RUBY__ASAN_DEFAULT_OPTIONS \
+ RBIMPL_SYMBOL_EXPORT_BEGIN() \
+ const char * __asan_default_options(void) {return ruby_asan_default_options;} \
+ RBIMPL_SYMBOL_EXPORT_END()
+#endif
#endif /* INTERNAL_SANITIZERS_H */
diff --git a/internal/set_table.h b/internal/set_table.h
new file mode 100644
index 0000000000..3c29abb4f5
--- /dev/null
+++ b/internal/set_table.h
@@ -0,0 +1,70 @@
+#ifndef INTERNAL_SET_TABLE_H
+#define INTERNAL_SET_TABLE_H
+
+#include "ruby/st.h"
+
+struct set_table_entry;
+
+typedef struct set_table_entry set_table_entry;
+
+struct set_table {
+ /* Cached features of the table -- see st.c for more details. */
+ unsigned char entry_power, bin_power, size_ind;
+ /* How many times the table was rebuilt. */
+ unsigned int rebuilds_num;
+ const struct st_hash_type *type;
+ /* Number of entries currently in the table. */
+ st_index_t num_entries;
+
+ /* Start and bound index of entries in array entries.
+ entries_starts and entries_bound are in interval
+ [0,allocated_entries]. */
+ st_index_t entries_start, entries_bound;
+
+ /**
+ * Array of size 2^entry_power.
+ * Followed by st_index_t *bins, Array of bins used for access by keys.
+ */
+ set_table_entry *entries;
+};
+
+typedef struct set_table set_table;
+
+typedef int set_foreach_callback_func(st_data_t, st_data_t);
+typedef int set_foreach_check_callback_func(st_data_t, st_data_t, int);
+typedef int set_update_callback_func(st_data_t *key, st_data_t arg, int existing);
+
+#define set_table_size rb_set_table_size
+size_t rb_set_table_size(const struct set_table *tbl);
+#define set_init_table_with_size rb_set_init_table_with_size
+set_table *rb_set_init_table_with_size(set_table *tab, const struct st_hash_type *, st_index_t);
+#define set_init_numtable rb_set_init_numtable
+set_table *rb_set_init_numtable(void);
+#define set_init_numtable_with_size rb_set_init_numtable_with_size
+set_table *rb_set_init_numtable_with_size(st_index_t size);
+#define set_table_delete rb_set_table_delete
+int rb_set_table_delete(set_table *, st_data_t *); /* returns 0:notfound 1:deleted */
+#define set_insert rb_set_insert
+int rb_set_insert(set_table *, st_data_t);
+#define set_table_lookup rb_set_table_lookup
+int rb_set_table_lookup(set_table *, st_data_t);
+#define set_foreach_with_replace rb_set_foreach_with_replace
+int rb_set_foreach_with_replace(set_table *tab, set_foreach_check_callback_func *func, set_update_callback_func *replace, st_data_t arg);
+#define set_table_foreach rb_set_table_foreach
+int rb_set_table_foreach(set_table *, set_foreach_callback_func *, st_data_t);
+#define set_foreach_check rb_set_foreach_check
+int rb_set_foreach_check(set_table *, set_foreach_check_callback_func *, st_data_t, st_data_t);
+#define set_keys rb_set_keys
+st_index_t rb_set_keys(set_table *table, st_data_t *keys, st_index_t size);
+#define set_free_table rb_set_free_table
+void rb_set_free_table(set_table *);
+#define set_table_clear rb_set_table_clear
+void rb_set_table_clear(set_table *);
+#define set_copy rb_set_copy
+set_table *rb_set_copy(set_table *new_table, set_table *old_table);
+#define set_memsize rb_set_memsize
+PUREFUNC(size_t rb_set_memsize(const set_table *));
+#define set_compact_table rb_set_compact_table
+void set_compact_table(set_table *tab);
+
+#endif
diff --git a/internal/signal.h b/internal/signal.h
index 2363bf412c..904747e226 100644
--- a/internal/signal.h
+++ b/internal/signal.h
@@ -19,6 +19,7 @@ void (*ruby_posix_signal(int, void (*)(int)))(int);
RUBY_SYMBOL_EXPORT_BEGIN
/* signal.c (export) */
+void rb_signal_atfork(void);
RUBY_SYMBOL_EXPORT_END
#endif /* INTERNAL_SIGNAL_H */
diff --git a/internal/st.h b/internal/st.h
index a26b224505..c220edd9f0 100644
--- a/internal/st.h
+++ b/internal/st.h
@@ -1,7 +1,7 @@
#ifndef INTERNAL_ST_H
#define INTERNAL_ST_H
-#include "include/ruby/st.h"
+#include "ruby/st.h"
st_table *rb_st_replace(st_table *new_tab, st_table *old_tab);
#define st_replace rb_st_replace
diff --git a/internal/string.h b/internal/string.h
index 3533766ffb..cd1e8d7929 100644
--- a/internal/string.h
+++ b/internal/string.h
@@ -14,10 +14,13 @@
#include "ruby/internal/stdbool.h" /* for bool */
#include "ruby/encoding.h" /* for rb_encoding */
#include "ruby/ruby.h" /* for VALUE */
+#include "encindex.h"
-#define STR_NOEMBED FL_USER1
-#define STR_SHARED FL_USER2 /* = ELTS_SHARED */
-#define STR_CHILLED FL_USER3
+#define STR_SHARED FL_USER0 /* = ELTS_SHARED */
+#define STR_NOEMBED FL_USER1
+#define STR_CHILLED (FL_USER2 | FL_USER3)
+#define STR_CHILLED_LITERAL FL_USER2
+#define STR_CHILLED_SYMBOL_TO_S FL_USER3
enum ruby_rstring_private_flags {
RSTRING_CHILLED = STR_CHILLED,
@@ -27,7 +30,28 @@ enum ruby_rstring_private_flags {
# undef rb_fstring_cstr
#endif
+static inline bool
+rb_str_encindex_fastpath(int encindex)
+{
+ // The overwhelming majority of strings are in one of these 3 encodings.
+ switch (encindex) {
+ case ENCINDEX_ASCII_8BIT:
+ case ENCINDEX_UTF_8:
+ case ENCINDEX_US_ASCII:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static inline bool
+rb_str_enc_fastpath(VALUE str)
+{
+ return rb_str_encindex_fastpath(ENCODING_GET_INLINED(str));
+}
+
/* string.c */
+VALUE rb_str_dup_m(VALUE str);
VALUE rb_fstring(VALUE);
VALUE rb_fstring_cstr(const char *str);
VALUE rb_fstring_enc_new(const char *ptr, long len, rb_encoding *enc);
@@ -51,6 +75,20 @@ int rb_enc_str_coderange_scan(VALUE str, rb_encoding *enc);
int rb_ascii8bit_appendable_encoding_index(rb_encoding *enc, unsigned int code);
VALUE rb_str_include(VALUE str, VALUE arg);
VALUE rb_str_byte_substr(VALUE str, VALUE beg, VALUE len);
+VALUE rb_str_substr_two_fixnums(VALUE str, VALUE beg, VALUE len, int empty);
+VALUE rb_str_tmp_frozen_no_embed_acquire(VALUE str);
+void rb_str_make_embedded(VALUE);
+VALUE rb_str_upto_each(VALUE, VALUE, int, int (*each)(VALUE, VALUE), VALUE);
+size_t rb_str_size_as_embedded(VALUE);
+bool rb_str_reembeddable_p(VALUE);
+VALUE rb_str_upto_endless_each(VALUE, int (*each)(VALUE, VALUE), VALUE);
+VALUE rb_str_with_debug_created_info(VALUE, VALUE, int);
+VALUE rb_str_frozen_bare_string(VALUE);
+const char *rb_str_null_check(VALUE);
+
+/* error.c */
+void rb_warn_unchilled_literal(VALUE str);
+void rb_warn_unchilled_symbol_to_s(VALUE str);
static inline bool STR_EMBED_P(VALUE str);
static inline bool STR_SHARED_P(VALUE str);
@@ -63,17 +101,14 @@ 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);
-VALUE rb_str_tmp_frozen_no_embed_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);
-void rb_str_make_embedded(VALUE);
-size_t rb_str_size_as_embedded(VALUE);
-bool rb_str_reembeddable_p(VALUE);
RUBY_SYMBOL_EXPORT_END
VALUE rb_fstring_new(const char *ptr, long len);
+void rb_gc_free_fstring(VALUE obj);
+bool rb_obj_is_fstring_table(VALUE obj);
+void Init_fstring_table();
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);
@@ -123,14 +158,18 @@ CHILLED_STRING_P(VALUE obj)
static inline void
CHILLED_STRING_MUTATED(VALUE str)
{
+ VALUE chilled_reason = RB_FL_TEST_RAW(str, STR_CHILLED);
FL_UNSET_RAW(str, STR_CHILLED);
- rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "literal string will be frozen in the future");
-}
-
-static inline void
-STR_CHILL_RAW(VALUE str)
-{
- FL_SET_RAW(str, STR_CHILLED);
+ switch (chilled_reason) {
+ case STR_CHILLED_SYMBOL_TO_S:
+ rb_warn_unchilled_symbol_to_s(str);
+ break;
+ case STR_CHILLED_LITERAL:
+ rb_warn_unchilled_literal(str);
+ break;
+ default:
+ rb_bug("RString was chilled for multiple reasons");
+ }
}
static inline bool
diff --git a/internal/struct.h b/internal/struct.h
index 6da5bad10a..d3c8157393 100644
--- a/internal/struct.h
+++ b/internal/struct.h
@@ -11,10 +11,23 @@
#include "ruby/internal/stdbool.h" /* for bool */
#include "ruby/ruby.h" /* for struct RBasic */
+/* Flags of RStruct
+ *
+ * 1-7: RSTRUCT_EMBED_LEN
+ * If non-zero, the struct is embedded (its contents follow the
+ * header, rather than being on a separately allocated buffer) and
+ * these bits are the length of the Struct.
+ * 8: RSTRUCT_GEN_FIELDS
+ * The struct is embedded and has no space left to store the
+ * IMEMO/fields reference. Any ivar this struct may have will be in
+ * the generic_fields_tbl. This flag doesn't imply the struct has
+ * ivars.
+ */
enum {
RSTRUCT_EMBED_LEN_MASK = RUBY_FL_USER7 | RUBY_FL_USER6 | RUBY_FL_USER5 | RUBY_FL_USER4 |
RUBY_FL_USER3 | RUBY_FL_USER2 | RUBY_FL_USER1,
RSTRUCT_EMBED_LEN_SHIFT = (RUBY_FL_USHIFT+1),
+ RSTRUCT_GEN_FIELDS = RUBY_FL_USER8,
};
struct RStruct {
@@ -23,6 +36,7 @@ struct RStruct {
struct {
long len;
const VALUE *ptr;
+ VALUE fields_obj;
} heap;
/* This is a length 1 array because:
* 1. GCC has a bug that does not optimize C flexible array members
@@ -35,37 +49,16 @@ struct RStruct {
#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 long RSTRUCT_EMBED_LEN(VALUE st);
-static inline long RSTRUCT_LEN(VALUE st);
+static inline long RSTRUCT_LEN_RAW(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 void RSTRUCT_SET_RAW(VALUE st, long k, VALUE v);
+static inline VALUE RSTRUCT_GET_RAW(VALUE st, long k);
static inline long
RSTRUCT_EMBED_LEN(VALUE st)
@@ -76,7 +69,7 @@ RSTRUCT_EMBED_LEN(VALUE st)
}
static inline long
-RSTRUCT_LEN(VALUE st)
+RSTRUCT_LEN_RAW(VALUE st)
{
if (FL_TEST_RAW(st, RSTRUCT_EMBED_LEN_MASK)) {
return RSTRUCT_EMBED_LEN(st);
@@ -89,7 +82,7 @@ RSTRUCT_LEN(VALUE st)
static inline int
RSTRUCT_LENINT(VALUE st)
{
- return rb_long2int(RSTRUCT_LEN(st));
+ return rb_long2int(RSTRUCT_LEN_RAW(st));
}
static inline const VALUE *
@@ -106,22 +99,42 @@ RSTRUCT_CONST_PTR(VALUE st)
}
static inline void
-RSTRUCT_SET(VALUE st, long k, VALUE v)
+RSTRUCT_SET_RAW(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)
+RSTRUCT_GET_RAW(VALUE st, long k)
{
return RSTRUCT_CONST_PTR(st)[k];
}
-static inline const VALUE *
-rb_struct_const_heap_ptr(VALUE st)
+static inline VALUE
+RSTRUCT_FIELDS_OBJ(VALUE st)
{
- assert(!FL_TEST_RAW(st, RSTRUCT_EMBED_LEN_MASK));
- return RSTRUCT(st)->as.heap.ptr;
+ const long embed_len = RSTRUCT_EMBED_LEN(st);
+ VALUE fields_obj;
+ if (embed_len) {
+ RUBY_ASSERT(!FL_TEST_RAW(st, RSTRUCT_GEN_FIELDS));
+ fields_obj = RSTRUCT_GET_RAW(st, embed_len);
+ }
+ else {
+ fields_obj = RSTRUCT(st)->as.heap.fields_obj;
+ }
+ return fields_obj;
}
+static inline void
+RSTRUCT_SET_FIELDS_OBJ(VALUE st, VALUE fields_obj)
+{
+ const long embed_len = RSTRUCT_EMBED_LEN(st);
+ if (embed_len) {
+ RUBY_ASSERT(!FL_TEST_RAW(st, RSTRUCT_GEN_FIELDS));
+ RSTRUCT_SET_RAW(st, embed_len, fields_obj);
+ }
+ else {
+ RB_OBJ_WRITE(st, &RSTRUCT(st)->as.heap.fields_obj, fields_obj);
+ }
+}
#endif /* INTERNAL_STRUCT_H */
diff --git a/internal/symbol.h b/internal/symbol.h
index e7730cb70f..b9109b1347 100644
--- a/internal/symbol.h
+++ b/internal/symbol.h
@@ -17,6 +17,7 @@
#endif
/* symbol.c */
+void rb_sym_global_symbols_mark_and_move(void);
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);
@@ -29,11 +30,11 @@ 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);
+bool rb_obj_is_symbol_table(VALUE obj);
+void rb_sym_global_symbol_table_foreach_weak_reference(int (*callback)(VALUE *key, void *data), void *data);
void rb_gc_free_dsymbol(VALUE);
int rb_static_id_valid_p(ID id);
-
-/* vm.c */
-void rb_free_static_symid_str(void);
+void rb_free_global_symbol_table(void);
#if __has_builtin(__builtin_constant_p)
#define rb_sym_intern_ascii_cstr(ptr) \
diff --git a/internal/thread.h b/internal/thread.h
index 47273436e3..ea891b4372 100644
--- a/internal/thread.h
+++ b/internal/thread.h
@@ -13,6 +13,7 @@
#include "ccan/list/list.h" /* for list in rb_io_close_wait_list */
struct rb_thread_struct; /* in vm_core.h */
+struct rb_io;
#define RB_VM_SAVE_MACHINE_CONTEXT(th) \
do { \
@@ -46,27 +47,35 @@ 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_thread_acquire_fork_lock(void);
+void rb_thread_release_fork_lock(void);
+void rb_thread_reset_fork_lock(void);
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);
VALUE rb_exec_recursive_outer_mid(VALUE (*f)(VALUE g, VALUE h, int r), VALUE g, VALUE h, ID mid);
void ruby_mn_threads_params(void);
-int rb_thread_wait_for_single_fd(int fd, int events, struct timeval * timeout);
+int rb_thread_io_wait(struct rb_thread_struct *th, struct rb_io *io, int events, struct timeval * timeout);
+int rb_thread_wait_for_single_fd(struct rb_thread_struct *th, int fd, int events, struct timeval * timeout);
-struct rb_io_close_wait_list {
- struct ccan_list_head pending_fd_users;
- VALUE closing_thread;
- VALUE wakeup_mutex;
-};
-int rb_notify_fd_close(int fd, struct rb_io_close_wait_list *busy);
-void rb_notify_fd_close_wait(struct rb_io_close_wait_list *busy);
+size_t rb_thread_io_close_interrupt(struct rb_io *);
+void rb_thread_io_close_wait(struct rb_io *);
+
+void rb_ec_check_ints(struct rb_execution_context_struct *ec);
+
+void rb_thread_free_native_thread(void *th_ptr);
RUBY_SYMBOL_EXPORT_BEGIN
+void *rb_thread_prevent_fork(void *(*func)(void *), void *data); /* for ext/socket/raddrinfo.c */
+
/* Temporary. This API will be removed (renamed). */
-VALUE rb_thread_io_blocking_region(rb_blocking_function_t *func, void *data1, int fd);
-VALUE rb_thread_io_blocking_call(rb_blocking_function_t *func, void *data1, int fd, int events);
+VALUE rb_thread_io_blocking_region(struct rb_io *io, rb_blocking_function_t *func, void *data1);
+VALUE rb_thread_io_blocking_call(struct rb_io *io, rb_blocking_function_t *func, void *data1, int events);
+
+// Invoke the given function, with the specified argument, in a way that `IO#close` from another execution context can interrupt it.
+VALUE rb_thread_io_blocking_operation(VALUE self, VALUE(*function)(VALUE), VALUE argument);
/* thread.c (export) */
int ruby_thread_has_gvl_p(void); /* for ext/fiddle/closure.c */
@@ -76,4 +85,28 @@ RUBY_SYMBOL_EXPORT_END
int rb_threadptr_execute_interrupts(struct rb_thread_struct *th, int blocking_timing);
bool rb_thread_mn_schedulable(VALUE thread);
+bool rb_thread_resolve_unblock_function(rb_unblock_function_t **unblock_function, void **data2, struct rb_thread_struct *thread);
+
+// interrupt exec
+
+typedef VALUE (rb_interrupt_exec_func_t)(void *data);
+
+enum rb_interrupt_exec_flag {
+ rb_interrupt_exec_flag_none = 0x00,
+ rb_interrupt_exec_flag_value_data = 0x01,
+ rb_interrupt_exec_flag_new_thread = 0x02,
+};
+
+// interrupt the target_th and run func.
+struct rb_ractor_struct;
+
+void rb_threadptr_interrupt_exec(struct rb_thread_struct *target_th,
+ rb_interrupt_exec_func_t *func, void *data, enum rb_interrupt_exec_flag flags);
+
+// create a thread in the target_r and run func on the created thread.
+void rb_ractor_interrupt_exec(struct rb_ractor_struct *target_r,
+ rb_interrupt_exec_func_t *func, void *data, enum rb_interrupt_exec_flag flags);
+
+void rb_threadptr_interrupt_exec_task_mark(struct rb_thread_struct *th);
+
#endif /* INTERNAL_THREAD_H */
diff --git a/internal/time.h b/internal/time.h
index a3bf0587ec..1f3505f5bc 100644
--- a/internal/time.h
+++ b/internal/time.h
@@ -27,8 +27,8 @@ 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
+void ruby_reset_timezone(const char *);
+
#endif /* INTERNAL_TIME_H */
diff --git a/internal/variable.h b/internal/variable.h
index b2a30c7c58..ca5e189c90 100644
--- a/internal/variable.h
+++ b/internal/variable.h
@@ -13,21 +13,22 @@
#include "constant.h" /* for rb_const_entry_t */
#include "ruby/internal/stdbool.h" /* for bool */
#include "ruby/ruby.h" /* for VALUE */
-#include "shape.h" /* for rb_shape_t */
+#include "shape.h" /* for shape_id_t */
/* 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);
void rb_autoload_str(VALUE mod, ID id, VALUE file);
VALUE rb_autoload_at_p(VALUE, ID, int);
+void rb_autoload_copy_table_for_box(st_table *, const rb_box_t *);
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);
+void rb_gvar_box_ready(const char *name);
/**
* Sets the name of a module.
@@ -45,20 +46,22 @@ void rb_gvar_ractor_local(const char *name);
*/
VALUE rb_mod_set_temporary_name(VALUE, VALUE);
-struct gen_ivtbl;
-int rb_gen_ivtbl_get(VALUE obj, ID id, struct gen_ivtbl **ivtbl);
void rb_obj_copy_ivs_to_hash_table(VALUE obj, st_table *table);
-void rb_obj_convert_to_too_complex(VALUE obj, st_table *table);
+void rb_obj_init_too_complex(VALUE obj, st_table *table);
void rb_evict_ivars_to_hash(VALUE obj);
+VALUE rb_obj_field_get(VALUE obj, shape_id_t target_shape_id);
+void rb_ivar_set_internal(VALUE obj, ID id, VALUE val);
+attr_index_t rb_ivar_set_index(VALUE obj, ID id, VALUE val);
+attr_index_t rb_obj_field_set(VALUE obj, shape_id_t target_shape_id, ID field_name, VALUE val);
+VALUE rb_ivar_get_at(VALUE obj, attr_index_t index, ID id);
+VALUE rb_ivar_get_at_no_ractor_check(VALUE obj, attr_index_t index);
RUBY_SYMBOL_EXPORT_BEGIN
/* variable.c (export) */
void rb_mark_generic_ivar(VALUE obj);
-void rb_ref_update_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);
+bool rb_class_ivar_set(VALUE klass, ID vid, VALUE value);
+void rb_fields_tbl_copy(VALUE dst, VALUE src);
RUBY_SYMBOL_EXPORT_END
VALUE rb_ivar_lookup(VALUE obj, ID id, VALUE undef);
@@ -66,7 +69,6 @@ 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_ensure_iv_list_size(VALUE obj, uint32_t len, uint32_t newsize);
-attr_index_t rb_obj_ivar_set(VALUE obj, ID id, VALUE val);
+void rb_ensure_iv_list_size(VALUE obj, uint32_t current_len, uint32_t newsize);
#endif /* INTERNAL_VARIABLE_H */
diff --git a/internal/vm.h b/internal/vm.h
index 74635e6ad8..029b19d555 100644
--- a/internal/vm.h
+++ b/internal/vm.h
@@ -56,7 +56,6 @@ 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);
VALUE ruby_vm_special_exception_copy(VALUE);
-PUREFUNC(st_table *rb_vm_fstring_table(void));
void rb_lastline_set_up(VALUE val, unsigned int up);
@@ -64,23 +63,27 @@ void rb_lastline_set_up(VALUE val, unsigned int up);
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_ec_yield(struct rb_execution_context_struct *ec, 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);
+#define RB_BLOCK_NO_USE_PACKED_ARGS 2
+VALUE rb_block_call2(VALUE obj, ID mid, int argc, const VALUE *argv, rb_block_call_func_t bl_proc, VALUE data2, long flags);
+struct vm_ifunc *rb_current_ifunc(void);
+VALUE rb_gccct_clear_table(VALUE);
+VALUE rb_eval_cmd_call_kw(VALUE cmd, int argc, const VALUE *argv, int kw_splat);
-#if USE_YJIT
+#if USE_YJIT || USE_ZJIT
/* vm_exec.c */
-extern uint64_t rb_vm_insns_count;
+extern uint64_t rb_vm_insn_count;
#endif
extern bool rb_free_at_exit;
@@ -96,11 +99,8 @@ struct rb_iseq_struct;
const struct rb_callcache *rb_vm_search_method_slowpath(const struct rb_callinfo *ci, VALUE klass);
/* vm_method.c */
-struct rb_execution_context_struct;
int rb_ec_obj_respond_to(struct rb_execution_context_struct *ec, VALUE obj, ID id, int priv);
-void rb_clear_constant_cache(void);
-
/* vm_dump.c */
void rb_print_backtrace(FILE *);
@@ -121,7 +121,6 @@ int rb_get_node_id_from_frame_info(VALUE obj);
const struct rb_iseq_struct *rb_get_iseq_from_frame_info(VALUE obj);
VALUE rb_ec_backtrace_object(const struct rb_execution_context_struct *ec);
-void rb_backtrace_use_iseq_first_lineno_for_last_location(VALUE self);
#define RUBY_DTRACE_CREATE_HOOK(name, arg) \
RUBY_DTRACE_HOOK(name##_CREATE, arg)
diff --git a/io.c b/io.c
index 9ef2892854..25c66550f5 100644
--- a/io.c
+++ b/io.c
@@ -104,6 +104,16 @@
#ifdef HAVE_COPYFILE_H
# include <copyfile.h>
+
+# ifndef COPYFILE_STATE_COPIED
+/*
+ * Some OSes (e.g., OSX < 10.6) implement fcopyfile() but not
+ * COPYFILE_STATE_COPIED. Since the only use of the former here
+ * requires the latter, we disable the former when the latter is undefined.
+ */
+# undef HAVE_FCOPYFILE
+# endif
+
#endif
#include "ruby/internal/stdbool.h"
@@ -210,7 +220,18 @@ static VALUE sym_DATA;
static VALUE sym_HOLE;
#endif
-static VALUE prep_io(int fd, int fmode, VALUE klass, const char *path);
+static VALUE prep_io(int fd, enum rb_io_mode fmode, VALUE klass, const char *path);
+
+VALUE
+rb_io_blocking_region_wait(struct rb_io *io, rb_blocking_function_t *function, void *argument, enum rb_io_event events)
+{
+ return rb_thread_io_blocking_call(io, function, argument, events);
+}
+
+VALUE rb_io_blocking_region(struct rb_io *io, rb_blocking_function_t *function, void *argument)
+{
+ return rb_io_blocking_region_wait(io, function, argument, 0);
+}
struct argf {
VALUE filename, current_file;
@@ -520,7 +541,8 @@ rb_cloexec_fcntl_dupfd(int fd, int minfd)
#endif
static int io_fflush(rb_io_t *);
-static rb_io_t *flush_before_seek(rb_io_t *fptr);
+static rb_io_t *flush_before_seek(rb_io_t *fptr, bool discard_rbuf);
+static void clear_codeconv(rb_io_t *fptr);
#define FMODE_SIGNAL_ON_EPIPE (1<<17)
@@ -605,7 +627,7 @@ rb_sys_fail_on_write(rb_io_t *fptr)
* IO unread with taking care of removed '\r' in text mode.
*/
static void
-io_unread(rb_io_t *fptr)
+io_unread(rb_io_t *fptr, bool discard_rbuf)
{
rb_off_t r, pos;
ssize_t read_size;
@@ -626,19 +648,17 @@ io_unread(rb_io_t *fptr)
if (r < 0 && errno) {
if (errno == ESPIPE)
fptr->mode |= FMODE_DUPLEX;
- return;
+ if (!discard_rbuf) return;
}
- fptr->rbuf.off = 0;
- fptr->rbuf.len = 0;
- return;
+ goto end;
}
pos = lseek(fptr->fd, 0, SEEK_CUR);
if (pos < 0 && errno) {
if (errno == ESPIPE)
fptr->mode |= FMODE_DUPLEX;
- return;
+ if (!discard_rbuf) goto end;
}
/* add extra offset for removed '\r' in rbuf */
@@ -679,8 +699,10 @@ io_unread(rb_io_t *fptr)
}
}
free(buf);
+ end:
fptr->rbuf.off = 0;
fptr->rbuf.len = 0;
+ clear_codeconv(fptr);
return;
}
@@ -699,7 +721,7 @@ set_binary_mode_with_seek_cur(rb_io_t *fptr)
if (fptr->rbuf.len == 0 || fptr->mode & FMODE_DUPLEX) {
return setmode(fptr->fd, O_BINARY);
}
- flush_before_seek(fptr);
+ flush_before_seek(fptr, false);
return setmode(fptr->fd, O_BINARY);
}
#define SET_BINARY_MODE_WITH_SEEK_CUR(fptr) set_binary_mode_with_seek_cur(fptr)
@@ -895,7 +917,7 @@ rb_io_s_try_convert(VALUE dummy, VALUE io)
#if !RUBY_CRLF_ENVIRONMENT
static void
-io_unread(rb_io_t *fptr)
+io_unread(rb_io_t *fptr, bool discard_rbuf)
{
rb_off_t r;
rb_io_check_closed(fptr);
@@ -907,10 +929,11 @@ io_unread(rb_io_t *fptr)
if (r < 0 && errno) {
if (errno == ESPIPE)
fptr->mode |= FMODE_DUPLEX;
- return;
+ if (!discard_rbuf) return;
}
fptr->rbuf.off = 0;
fptr->rbuf.len = 0;
+ clear_codeconv(fptr);
return;
}
#endif
@@ -951,17 +974,17 @@ io_ungetbyte(VALUE str, rb_io_t *fptr)
}
static rb_io_t *
-flush_before_seek(rb_io_t *fptr)
+flush_before_seek(rb_io_t *fptr, bool discard_rbuf)
{
if (io_fflush(fptr) < 0)
rb_sys_fail_on_write(fptr);
- io_unread(fptr);
+ io_unread(fptr, discard_rbuf);
errno = 0;
return fptr;
}
-#define io_seek(fptr, ofs, whence) (errno = 0, lseek(flush_before_seek(fptr)->fd, (ofs), (whence)))
-#define io_tell(fptr) lseek(flush_before_seek(fptr)->fd, 0, SEEK_CUR)
+#define io_seek(fptr, ofs, whence) (errno = 0, lseek(flush_before_seek(fptr, true)->fd, (ofs), (whence)))
+#define io_tell(fptr) lseek(flush_before_seek(fptr, false)->fd, 0, SEEK_CUR)
#ifndef SEEK_CUR
# define SEEK_SET 0
@@ -1029,7 +1052,7 @@ rb_io_check_writable(rb_io_t *fptr)
rb_raise(rb_eIOError, "not opened for writing");
}
if (fptr->rbuf.len) {
- io_unread(fptr);
+ io_unread(fptr, true);
}
}
@@ -1158,8 +1181,15 @@ io_internal_wait(VALUE thread, rb_io_t *fptr, int error, int events, struct time
return -1;
}
- errno = error;
- return -1;
+ // If there was an error BEFORE we started waiting, return it:
+ if (error) {
+ errno = error;
+ return -1;
+ }
+ else {
+ // Otherwise, whatever error was generated by `nogvl_wait_for` is the one we want:
+ return ready;
+ }
}
static VALUE
@@ -1261,7 +1291,8 @@ internal_writev_func(void *ptr)
static ssize_t
rb_io_read_memory(rb_io_t *fptr, void *buf, size_t count)
{
- VALUE scheduler = rb_fiber_scheduler_current();
+ rb_thread_t *th = GET_THREAD();
+ VALUE scheduler = rb_fiber_scheduler_current_for_threadptr(th);
if (scheduler != Qnil) {
VALUE result = rb_fiber_scheduler_io_read_memory(scheduler, fptr->self, buf, count, 0);
@@ -1271,7 +1302,7 @@ rb_io_read_memory(rb_io_t *fptr, void *buf, size_t count)
}
struct io_internal_read_struct iis = {
- .th = rb_thread_current(),
+ .th = th->self,
.fptr = fptr,
.nonblock = 0,
.fd = fptr->fd,
@@ -1288,13 +1319,14 @@ rb_io_read_memory(rb_io_t *fptr, void *buf, size_t count)
iis.timeout = &timeout_storage;
}
- return (ssize_t)rb_thread_io_blocking_call(internal_read_func, &iis, fptr->fd, RB_WAITFD_IN);
+ return (ssize_t)rb_io_blocking_region_wait(fptr, internal_read_func, &iis, RUBY_IO_READABLE);
}
static ssize_t
rb_io_write_memory(rb_io_t *fptr, const void *buf, size_t count)
{
- VALUE scheduler = rb_fiber_scheduler_current();
+ rb_thread_t *th = GET_THREAD();
+ VALUE scheduler = rb_fiber_scheduler_current_for_threadptr(th);
if (scheduler != Qnil) {
VALUE result = rb_fiber_scheduler_io_write_memory(scheduler, fptr->self, buf, count, 0);
@@ -1304,7 +1336,7 @@ rb_io_write_memory(rb_io_t *fptr, const void *buf, size_t count)
}
struct io_internal_write_struct iis = {
- .th = rb_thread_current(),
+ .th = th->self,
.fptr = fptr,
.nonblock = 0,
.fd = fptr->fd,
@@ -1321,7 +1353,7 @@ rb_io_write_memory(rb_io_t *fptr, const void *buf, size_t count)
iis.timeout = &timeout_storage;
}
- return (ssize_t)rb_thread_io_blocking_call(internal_write_func, &iis, fptr->fd, RB_WAITFD_OUT);
+ return (ssize_t)rb_io_blocking_region_wait(fptr, internal_write_func, &iis, RUBY_IO_WRITABLE);
}
#ifdef HAVE_WRITEV
@@ -1330,7 +1362,9 @@ rb_writev_internal(rb_io_t *fptr, const struct iovec *iov, int iovcnt)
{
if (!iovcnt) return 0;
- VALUE scheduler = rb_fiber_scheduler_current();
+ rb_thread_t *th = GET_THREAD();
+
+ VALUE scheduler = rb_fiber_scheduler_current_for_threadptr(th);
if (scheduler != Qnil) {
// This path assumes at least one `iov`:
VALUE result = rb_fiber_scheduler_io_write_memory(scheduler, fptr->self, iov[0].iov_base, iov[0].iov_len, 0);
@@ -1341,7 +1375,7 @@ rb_writev_internal(rb_io_t *fptr, const struct iovec *iov, int iovcnt)
}
struct io_internal_writev_struct iis = {
- .th = rb_thread_current(),
+ .th = th->self,
.fptr = fptr,
.nonblock = 0,
.fd = fptr->fd,
@@ -1358,7 +1392,7 @@ rb_writev_internal(rb_io_t *fptr, const struct iovec *iov, int iovcnt)
iis.timeout = &timeout_storage;
}
- return (ssize_t)rb_thread_io_blocking_call(internal_writev_func, &iis, fptr->fd, RB_WAITFD_OUT);
+ return (ssize_t)rb_io_blocking_region_wait(fptr, internal_writev_func, &iis, RUBY_IO_WRITABLE);
}
#endif
@@ -1384,11 +1418,35 @@ io_flush_buffer_sync(void *arg)
return (VALUE)-1;
}
+static inline VALUE
+io_flush_buffer_fiber_scheduler(VALUE scheduler, rb_io_t *fptr)
+{
+ VALUE ret = rb_fiber_scheduler_io_write_memory(scheduler, fptr->self, fptr->wbuf.ptr+fptr->wbuf.off, fptr->wbuf.len, 0);
+ if (!UNDEF_P(ret)) {
+ ssize_t result = rb_fiber_scheduler_io_result_apply(ret);
+ if (result > 0) {
+ fptr->wbuf.off += result;
+ fptr->wbuf.len -= result;
+ }
+ return result >= 0 ? (VALUE)0 : (VALUE)-1;
+ }
+ return ret;
+}
+
static VALUE
io_flush_buffer_async(VALUE arg)
{
rb_io_t *fptr = (rb_io_t *)arg;
- return rb_thread_io_blocking_call(io_flush_buffer_sync, fptr, fptr->fd, RB_WAITFD_OUT);
+
+ VALUE scheduler = rb_fiber_scheduler_current();
+ if (scheduler != Qnil) {
+ VALUE result = io_flush_buffer_fiber_scheduler(scheduler, fptr);
+ if (!UNDEF_P(result)) {
+ return result;
+ }
+ }
+
+ return rb_io_blocking_region_wait(fptr, io_flush_buffer_sync, fptr, RUBY_IO_WRITABLE);
}
static inline int
@@ -1423,7 +1481,8 @@ io_fflush(rb_io_t *fptr)
VALUE
rb_io_wait(VALUE io, VALUE events, VALUE timeout)
{
- VALUE scheduler = rb_fiber_scheduler_current();
+ rb_thread_t *th = GET_THREAD();
+ VALUE scheduler = rb_fiber_scheduler_current_for_threadptr(th);
if (scheduler != Qnil) {
return rb_fiber_scheduler_io_wait(scheduler, io, events, timeout);
@@ -1444,7 +1503,7 @@ rb_io_wait(VALUE io, VALUE events, VALUE timeout)
tv = &tv_storage;
}
- int ready = rb_thread_wait_for_single_fd(fptr->fd, RB_NUM2INT(events), tv);
+ int ready = rb_thread_io_wait(th, fptr, RB_NUM2INT(events), tv);
if (ready < 0) {
rb_sys_fail(0);
@@ -1468,17 +1527,15 @@ io_from_fd(int fd)
}
static int
-io_wait_for_single_fd(int fd, int events, struct timeval *timeout)
+io_wait_for_single_fd(int fd, int events, struct timeval *timeout, rb_thread_t *th, VALUE scheduler)
{
- 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);
+ return rb_thread_wait_for_single_fd(th, fd, events, timeout);
}
int
@@ -1486,7 +1543,8 @@ rb_io_wait_readable(int f)
{
io_fd_check_closed(f);
- VALUE scheduler = rb_fiber_scheduler_current();
+ rb_thread_t *th = GET_THREAD();
+ VALUE scheduler = rb_fiber_scheduler_current_for_threadptr(th);
switch (errno) {
case EINTR:
@@ -1506,7 +1564,7 @@ rb_io_wait_readable(int f)
);
}
else {
- io_wait_for_single_fd(f, RUBY_IO_READABLE, NULL);
+ io_wait_for_single_fd(f, RUBY_IO_READABLE, NULL, th, scheduler);
}
return TRUE;
@@ -1520,7 +1578,8 @@ rb_io_wait_writable(int f)
{
io_fd_check_closed(f);
- VALUE scheduler = rb_fiber_scheduler_current();
+ rb_thread_t *th = GET_THREAD();
+ VALUE scheduler = rb_fiber_scheduler_current_for_threadptr(th);
switch (errno) {
case EINTR:
@@ -1549,7 +1608,7 @@ rb_io_wait_writable(int f)
);
}
else {
- io_wait_for_single_fd(f, RUBY_IO_WRITABLE, NULL);
+ io_wait_for_single_fd(f, RUBY_IO_WRITABLE, NULL, th, scheduler);
}
return TRUE;
@@ -1561,7 +1620,9 @@ rb_io_wait_writable(int f)
int
rb_wait_for_single_fd(int fd, int events, struct timeval *timeout)
{
- return io_wait_for_single_fd(fd, events, timeout);
+ rb_thread_t *th = GET_THREAD();
+ VALUE scheduler = rb_fiber_scheduler_current_for_threadptr(th);
+ return io_wait_for_single_fd(fd, events, timeout, th, scheduler);
}
int
@@ -1613,7 +1674,7 @@ rb_io_maybe_wait(int error, VALUE io, VALUE events, VALUE timeout)
default:
// Non-specific error, no event is ready:
- return Qfalse;
+ return Qnil;
}
}
@@ -1625,9 +1686,11 @@ rb_io_maybe_wait_readable(int error, VALUE io, VALUE timeout)
if (RTEST(result)) {
return RB_NUM2INT(result);
}
- else {
- return 0;
+ else if (result == RUBY_Qfalse) {
+ rb_raise(rb_eIOTimeoutError, "Timed out waiting for IO to become readable!");
}
+
+ return 0;
}
int
@@ -1638,9 +1701,11 @@ rb_io_maybe_wait_writable(int error, VALUE io, VALUE timeout)
if (RTEST(result)) {
return RB_NUM2INT(result);
}
- else {
- return 0;
+ else if (result == RUBY_Qfalse) {
+ rb_raise(rb_eIOTimeoutError, "Timed out waiting for IO to become writable!");
}
+
+ return 0;
}
static void
@@ -2351,7 +2416,7 @@ rb_io_flush_raw(VALUE io, int sync)
rb_sys_fail_on_write(fptr);
}
if (fptr->mode & FMODE_READABLE) {
- io_unread(fptr);
+ io_unread(fptr, true);
}
return io;
@@ -2594,9 +2659,6 @@ io_fillbuf(rb_io_t *fptr)
fptr->rbuf.len = 0;
fptr->rbuf.capa = IO_RBUF_CAPA_FOR(fptr);
fptr->rbuf.ptr = ALLOC_N(char, fptr->rbuf.capa);
-#ifdef _WIN32
- fptr->rbuf.capa--;
-#endif
}
if (fptr->rbuf.len == 0) {
retry:
@@ -2774,8 +2836,10 @@ rb_io_fsync(VALUE io)
if (io_fflush(fptr) < 0)
rb_sys_fail_on_write(fptr);
- if ((int)rb_thread_io_blocking_region(nogvl_fsync, fptr, fptr->fd) < 0)
+
+ if ((int)rb_io_blocking_region(fptr, nogvl_fsync, fptr))
rb_sys_fail_path(fptr->pathv);
+
return INT2FIX(0);
}
#else
@@ -2824,7 +2888,7 @@ rb_io_fdatasync(VALUE io)
if (io_fflush(fptr) < 0)
rb_sys_fail_on_write(fptr);
- if ((int)rb_thread_io_blocking_region(nogvl_fdatasync, fptr, fptr->fd) == 0)
+ if ((int)rb_io_blocking_region(fptr, nogvl_fdatasync, fptr) == 0)
return INT2FIX(0);
/* fall back */
@@ -3120,8 +3184,6 @@ io_enc_str(VALUE str, rb_io_t *fptr)
return str;
}
-static rb_encoding *io_read_encoding(rb_io_t *fptr);
-
static void
make_readconv(rb_io_t *fptr, int size)
{
@@ -3264,10 +3326,6 @@ io_shift_cbuf(rb_io_t *fptr, int len, VALUE *strp)
static int
io_setstrbuf(VALUE *str, long len)
{
-#ifdef _WIN32
- if (len > 0)
- len = (len + 1) & ~1L; /* round up for wide char */
-#endif
if (NIL_P(*str)) {
*str = rb_str_new(0, len);
return TRUE;
@@ -3409,10 +3467,10 @@ io_read_memory_call(VALUE arg)
}
if (iis->nonblock) {
- return rb_thread_io_blocking_call(internal_read_func, iis, iis->fptr->fd, 0);
+ return rb_io_blocking_region(iis->fptr, internal_read_func, iis);
}
else {
- return rb_thread_io_blocking_call(internal_read_func, iis, iis->fptr->fd, RB_WAITFD_IN);
+ return rb_io_blocking_region_wait(iis->fptr, internal_read_func, iis, RUBY_IO_READABLE);
}
}
@@ -3820,8 +3878,33 @@ rscheck(const char *rsptr, long rslen, VALUE rs)
rb_raise(rb_eRuntimeError, "rs modified");
}
+static const char *
+search_delim(const char *p, long len, int delim, rb_encoding *enc)
+{
+ if (rb_enc_mbminlen(enc) == 1) {
+ p = memchr(p, delim, len);
+ if (p) return p + 1;
+ }
+ else {
+ const char *end = p + len;
+ while (p < end) {
+ int r = rb_enc_precise_mbclen(p, end, enc);
+ if (!MBCLEN_CHARFOUND_P(r)) {
+ p += rb_enc_mbminlen(enc);
+ continue;
+ }
+ int n = MBCLEN_CHARFOUND_LEN(r);
+ if (rb_enc_mbc_to_codepoint(p, end, enc) == (unsigned int)delim) {
+ return p + n;
+ }
+ p += n;
+ }
+ }
+ return NULL;
+}
+
static int
-appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
+appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp, rb_encoding *enc)
{
VALUE str = *strp;
long limit = *lp;
@@ -3836,9 +3919,9 @@ appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
p = READ_CHAR_PENDING_PTR(fptr);
if (0 < limit && limit < searchlen)
searchlen = (int)limit;
- e = memchr(p, delim, searchlen);
+ e = search_delim(p, searchlen, delim, enc);
if (e) {
- int len = (int)(e-p+1);
+ int len = (int)(e-p);
if (NIL_P(str))
*strp = str = rb_str_new(p, len);
else
@@ -3878,8 +3961,8 @@ appendline(rb_io_t *fptr, int delim, VALUE *strp, long *lp)
long last;
if (limit > 0 && pending > limit) pending = limit;
- e = memchr(p, delim, pending);
- if (e) pending = e - p + 1;
+ e = search_delim(p, pending, delim, enc);
+ if (e) pending = e - p;
if (!NIL_P(str)) {
last = RSTRING_LEN(str);
rb_str_resize(str, last + pending);
@@ -4134,21 +4217,31 @@ rb_io_getline_0(VALUE rs, long limit, int chomp, rb_io_t *fptr)
rs = 0;
if (!rb_enc_asciicompat(enc)) {
rs = rb_usascii_str_new(rsptr, rslen);
- rs = rb_str_encode(rs, rb_enc_from_encoding(enc), 0, Qnil);
+ rs = rb_str_conv_enc(rs, 0, enc);
OBJ_FREEZE(rs);
rsptr = RSTRING_PTR(rs);
rslen = RSTRING_LEN(rs);
}
+ newline = '\n';
+ }
+ else if (rb_enc_mbminlen(enc) == 1) {
+ rsptr = RSTRING_PTR(rs);
+ newline = (unsigned char)rsptr[rslen - 1];
}
else {
+ rs = rb_str_conv_enc(rs, 0, enc);
rsptr = RSTRING_PTR(rs);
+ const char *e = rsptr + rslen;
+ const char *last = rb_enc_prev_char(rsptr, e, e, enc);
+ int n;
+ newline = rb_enc_codepoint_len(last, e, &n, enc);
+ if (last + n != e) rb_raise(rb_eArgError, "broken separator");
}
- newline = (unsigned char)rsptr[rslen - 1];
- chomp_cr = chomp && rslen == 1 && newline == '\n';
+ chomp_cr = chomp && newline == '\n' && rslen == rb_enc_mbminlen(enc);
}
/* MS - Optimization */
- while ((c = appendline(fptr, newline, &str, &limit)) != EOF) {
+ while ((c = appendline(fptr, newline, &str, &limit, enc)) != EOF) {
const char *s, *p, *pp, *e;
if (c == newline) {
@@ -4169,8 +4262,8 @@ rb_io_getline_0(VALUE rs, long limit, int chomp, rb_io_t *fptr)
if (limit == 0) {
s = RSTRING_PTR(str);
p = RSTRING_END(str);
- pp = rb_enc_left_char_head(s, p-1, p, enc);
- if (extra_limit &&
+ pp = rb_enc_prev_char(s, p, p, enc);
+ if (extra_limit && pp &&
MBCLEN_NEEDMORE_P(rb_enc_precise_mbclen(pp, p, enc))) {
/* relax the limit while incomplete character.
* extra_limit limits the relax length */
@@ -4236,11 +4329,17 @@ rb_io_gets(VALUE io)
}
VALUE
-rb_io_gets_internal(VALUE io)
+rb_io_gets_limit_internal(VALUE io, long limit)
{
rb_io_t *fptr;
GetOpenFile(io, fptr);
- return rb_io_getline_0(rb_default_rs, -1, FALSE, fptr);
+ return rb_io_getline_0(rb_default_rs, limit, FALSE, fptr);
+}
+
+VALUE
+rb_io_gets_internal(VALUE io)
+{
+ return rb_io_gets_limit_internal(io, -1);
}
/*
@@ -4369,23 +4468,31 @@ rb_io_set_lineno(VALUE io, VALUE lineno)
static VALUE
io_readline(rb_execution_context_t *ec, VALUE io, VALUE sep, VALUE lim, VALUE chomp)
{
+ long limit = -1;
if (NIL_P(lim)) {
+ VALUE tmp = Qnil;
// If sep is specified, but it's not a string and not nil, then assume
// it's the limit (it should be an integer)
- if (!NIL_P(sep) && NIL_P(rb_check_string_type(sep))) {
+ if (!NIL_P(sep) && NIL_P(tmp = rb_check_string_type(sep))) {
// If the user has specified a non-nil / non-string value
// for the separator, we assume it's the limit and set the
// separator to default: rb_rs.
lim = sep;
+ limit = NUM2LONG(lim);
sep = rb_rs;
}
+ else {
+ sep = tmp;
+ }
}
-
- if (!NIL_P(sep)) {
- StringValue(sep);
+ else {
+ if (!NIL_P(sep)) StringValue(sep);
+ limit = NUM2LONG(lim);
}
- VALUE line = rb_io_getline_1(sep, NIL_P(lim) ? -1L : NUM2LONG(lim), RTEST(chomp), io);
+ check_getline_args(&sep, &limit, io);
+
+ VALUE line = rb_io_getline_1(sep, limit, RTEST(chomp), io);
rb_lastline_set_up(line, 1);
if (NIL_P(line)) {
@@ -4613,10 +4720,11 @@ rb_io_each_line(int argc, VALUE *argv, VALUE io)
* Calls the given block with each byte (0..255) in the stream; returns +self+.
* See {Byte IO}[rdoc-ref:IO@Byte+IO].
*
- * f = File.new('t.rus')
+ * File.read('t.ja') # => "こんにちは"
+ * f = File.new('t.ja')
* a = []
* f.each_byte {|b| a << b }
- * a # => [209, 130, 208, 181, 209, 129, 209, 130]
+ * a # => [227, 129, 147, 227, 130, 147, 227, 129, 171, 227, 129, 161, 227, 129, 175]
* f.close
*
* Returns an Enumerator if no block is given.
@@ -4761,10 +4869,11 @@ io_getc(rb_io_t *fptr, rb_encoding *enc)
* Calls the given block with each character in the stream; returns +self+.
* See {Character IO}[rdoc-ref:IO@Character+IO].
*
- * f = File.new('t.rus')
+ * File.read('t.ja') # => "こんにちは"
+ * f = File.new('t.ja')
* a = []
* f.each_char {|c| a << c.ord }
- * a # => [1090, 1077, 1089, 1090]
+ * a # => [12371, 12435, 12395, 12385, 12399]
* f.close
*
* Returns an Enumerator if no block is given.
@@ -4799,10 +4908,11 @@ rb_io_each_char(VALUE io)
*
* Calls the given block with each codepoint in the stream; returns +self+:
*
- * f = File.new('t.rus')
+ * File.read('t.ja') # => "こんにちは"
+ * f = File.new('t.ja')
* a = []
* f.each_codepoint {|c| a << c }
- * a # => [1090, 1077, 1089, 1090]
+ * a # => [12371, 12435, 12395, 12385, 12399]
* f.close
*
* Returns an Enumerator if no block is given.
@@ -4824,6 +4934,7 @@ rb_io_each_codepoint(VALUE io)
rb_io_check_char_readable(fptr);
READ_CHECK(fptr);
+ enc = io_read_encoding(fptr);
if (NEED_READCONV(fptr)) {
SET_BINARY_MODE(fptr);
r = 1; /* no invalid char yet */
@@ -4831,12 +4942,9 @@ rb_io_each_codepoint(VALUE io)
make_readconv(fptr, 0);
for (;;) {
if (fptr->cbuf.len) {
- if (fptr->encs.enc)
- r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
- fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
- fptr->encs.enc);
- else
- r = ONIGENC_CONSTRUCT_MBCLEN_CHARFOUND(1);
+ r = rb_enc_precise_mbclen(fptr->cbuf.ptr+fptr->cbuf.off,
+ fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
+ enc);
if (!MBCLEN_NEEDMORE_P(r))
break;
if (fptr->cbuf.len == fptr->cbuf.capa) {
@@ -4846,33 +4954,25 @@ rb_io_each_codepoint(VALUE io)
if (more_char(fptr) == MORE_CHAR_FINISHED) {
clear_readconv(fptr);
if (!MBCLEN_CHARFOUND_P(r)) {
- enc = fptr->encs.enc;
goto invalid;
}
return io;
}
}
if (MBCLEN_INVALID_P(r)) {
- enc = fptr->encs.enc;
goto invalid;
}
n = MBCLEN_CHARFOUND_LEN(r);
- if (fptr->encs.enc) {
- c = rb_enc_codepoint(fptr->cbuf.ptr+fptr->cbuf.off,
- fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
- fptr->encs.enc);
- }
- else {
- c = (unsigned char)fptr->cbuf.ptr[fptr->cbuf.off];
- }
+ c = rb_enc_codepoint(fptr->cbuf.ptr+fptr->cbuf.off,
+ fptr->cbuf.ptr+fptr->cbuf.off+fptr->cbuf.len,
+ enc);
fptr->cbuf.off += n;
fptr->cbuf.len -= n;
rb_yield(UINT2NUM(c));
- rb_io_check_byte_readable(fptr);
+ rb_io_check_char_readable(fptr);
}
}
NEED_NEWLINE_DECORATOR_ON_READ_CHECK(fptr);
- enc = io_input_encoding(fptr);
while (io_fillbuf(fptr) >= 0) {
r = rb_enc_precise_mbclen(fptr->rbuf.ptr+fptr->rbuf.off,
fptr->rbuf.ptr+fptr->rbuf.off+fptr->rbuf.len, enc);
@@ -4926,8 +5026,9 @@ rb_io_each_codepoint(VALUE io)
* f = File.open('t.txt')
* f.getc # => "F"
* f.close
- * f = File.open('t.rus')
- * f.getc.ord # => 1090
+ * File.read('t.ja') # => "こんにちは"
+ * f = File.open('t.ja')
+ * f.getc.ord # => 12371
* f.close
*
* Related: IO#readchar (may raise EOFError).
@@ -4959,8 +5060,9 @@ rb_io_getc(VALUE io)
* f = File.open('t.txt')
* f.readchar # => "F"
* f.close
- * f = File.open('t.rus')
- * f.readchar.ord # => 1090
+ * File.read('t.ja') # => "こんにちは"
+ * f = File.open('t.ja')
+ * f.readchar.ord # => 12371
* f.close
*
* Related: IO#getc (will not raise EOFError).
@@ -4989,8 +5091,9 @@ rb_io_readchar(VALUE io)
* f = File.open('t.txt')
* f.getbyte # => 70
* f.close
- * f = File.open('t.rus')
- * f.getbyte # => 209
+ * File.read('t.ja') # => "こんにちは"
+ * f = File.open('t.ja')
+ * f.getbyte # => 227
* f.close
*
* Related: IO#readbyte (may raise EOFError).
@@ -5033,8 +5136,9 @@ rb_io_getbyte(VALUE io)
* f = File.open('t.txt')
* f.readbyte # => 70
* f.close
- * f = File.open('t.rus')
- * f.readbyte # => 209
+ * File.read('t.ja') # => "こんにちは"
+ * f = File.open('t.ja')
+ * f.readbyte # => 227
* f.close
*
* Related: IO#getbyte (will not raise EOFError).
@@ -5436,11 +5540,9 @@ maygvl_fclose(FILE *file, int keepgvl)
}
static void free_io_buffer(rb_io_buffer_t *buf);
-static void clear_codeconv(rb_io_t *fptr);
static void
-fptr_finalize_flush(rb_io_t *fptr, int noraise, int keepgvl,
- struct rb_io_close_wait_list *busy)
+fptr_finalize_flush(rb_io_t *fptr, int noraise, int keepgvl)
{
VALUE error = Qnil;
int fd = fptr->fd;
@@ -5480,20 +5582,8 @@ fptr_finalize_flush(rb_io_t *fptr, int noraise, int keepgvl,
fptr->stdio_file = 0;
fptr->mode &= ~(FMODE_READABLE|FMODE_WRITABLE);
- // Ensure waiting_fd users do not hit EBADF.
- if (busy) {
- // Wait for them to exit before we call close().
- rb_notify_fd_close_wait(busy);
- }
-
- // 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 (!UNDEF_P(result)) done = 1;
- // }
- // }
+ // Wait for blocking operations to ensure they do not hit EBADF:
+ rb_thread_io_close_wait(fptr);
if (!done && stdio_file) {
// stdio_file is deallocated anyway even if fclose failed.
@@ -5506,6 +5596,15 @@ fptr_finalize_flush(rb_io_t *fptr, int noraise, int keepgvl,
done = 1;
}
+ VALUE scheduler = rb_fiber_scheduler_current();
+ if (!done && fd >= 0 && scheduler != Qnil) {
+ VALUE result = rb_fiber_scheduler_io_close(scheduler, RB_INT2NUM(fd));
+
+ if (!UNDEF_P(result)) {
+ done = RTEST(result);
+ }
+ }
+
if (!done && fd >= 0) {
// fptr->fd may be closed even if close fails. POSIX doesn't specify it.
// We assumes it is closed.
@@ -5532,7 +5631,7 @@ fptr_finalize_flush(rb_io_t *fptr, int noraise, int keepgvl,
static void
fptr_finalize(rb_io_t *fptr, int noraise)
{
- fptr_finalize_flush(fptr, noraise, FALSE, 0);
+ fptr_finalize_flush(fptr, noraise, FALSE);
free_io_buffer(&fptr->rbuf);
free_io_buffer(&fptr->wbuf);
clear_codeconv(fptr);
@@ -5597,37 +5696,36 @@ rb_io_fptr_cleanup_all(rb_io_t *fptr)
clear_codeconv(fptr);
}
-void
-rb_io_fptr_finalize_internal(void *ptr)
-{
- if (!ptr) return;
- rb_io_fptr_cleanup_all(ptr);
- free(ptr);
-}
-
-#undef rb_io_fptr_finalize
int
-rb_io_fptr_finalize(rb_io_t *fptr)
+rb_io_fptr_finalize(struct rb_io *io)
{
- if (!fptr) {
- return 0;
- }
- else {
- rb_io_fptr_finalize_internal(fptr);
- return 1;
- }
+ if (!io) return 0;
+ rb_io_fptr_cleanup_all(io);
+ free(io);
+
+ return 1;
}
-#define rb_io_fptr_finalize(fptr) rb_io_fptr_finalize_internal(fptr)
size_t
-rb_io_memsize(const rb_io_t *fptr)
+rb_io_memsize(const rb_io_t *io)
{
size_t size = sizeof(rb_io_t);
- size += fptr->rbuf.capa;
- size += fptr->wbuf.capa;
- size += fptr->cbuf.capa;
- if (fptr->readconv) size += rb_econv_memsize(fptr->readconv);
- if (fptr->writeconv) size += rb_econv_memsize(fptr->writeconv);
+ size += io->rbuf.capa;
+ size += io->wbuf.capa;
+ size += io->cbuf.capa;
+ if (io->readconv) size += rb_econv_memsize(io->readconv);
+ if (io->writeconv) size += rb_econv_memsize(io->writeconv);
+
+ struct rb_io_blocking_operation *blocking_operation = 0;
+
+ // Validate the fork generation of the IO object. If the IO object fork generation is different, the list of blocking operations is not valid memory. See `rb_io_blocking_operations` for the exact semantics.
+ rb_serial_t fork_generation = GET_VM()->fork_gen;
+ if (io->fork_generation == fork_generation) {
+ ccan_list_for_each(&io->blocking_operations, blocking_operation, list) {
+ size += sizeof(struct rb_io_blocking_operation);
+ }
+ }
+
return size;
}
@@ -5644,7 +5742,6 @@ io_close_fptr(VALUE io)
rb_io_t *fptr;
VALUE write_io;
rb_io_t *write_fptr;
- struct rb_io_close_wait_list busy;
write_io = GetWriteIO(io);
if (io != write_io) {
@@ -5658,10 +5755,12 @@ io_close_fptr(VALUE io)
if (!fptr) return 0;
if (fptr->fd < 0) return 0;
- if (rb_notify_fd_close(fptr->fd, &busy)) {
+ // This guards against multiple threads closing the same IO object:
+ if (rb_thread_io_close_interrupt(fptr)) {
/* calls close(fptr->fd): */
- fptr_finalize_flush(fptr, FALSE, KEEPGVL, &busy);
+ fptr_finalize_flush(fptr, FALSE, KEEPGVL);
}
+
rb_io_fptr_cleanup(fptr, FALSE);
return fptr;
}
@@ -5699,6 +5798,9 @@ rb_io_close(VALUE io)
* If the stream was opened by IO.popen, sets global variable <tt>$?</tt>
* (child exit status).
*
+ * It is not an error to close an IO object that has already been closed.
+ * It just returns nil.
+ *
* Example:
*
* IO.popen('ruby', 'r+') do |pipe|
@@ -6082,7 +6184,7 @@ rb_io_sysread(int argc, VALUE *argv, VALUE io)
}
struct prdwr_internal_arg {
- VALUE io;
+ struct rb_io *io;
int fd;
void *buf;
size_t count;
@@ -6104,14 +6206,14 @@ pread_internal_call(VALUE _arg)
VALUE scheduler = rb_fiber_scheduler_current();
if (scheduler != Qnil) {
- VALUE result = rb_fiber_scheduler_io_pread_memory(scheduler, arg->io, arg->offset, arg->buf, arg->count, 0);
+ VALUE result = rb_fiber_scheduler_io_pread_memory(scheduler, arg->io->self, arg->offset, arg->buf, arg->count, 0);
if (!UNDEF_P(result)) {
return rb_fiber_scheduler_io_result_apply(result);
}
}
- return rb_thread_io_blocking_call(internal_pread_func, arg, arg->fd, RB_WAITFD_IN);
+ return rb_io_blocking_region_wait(arg->io, internal_pread_func, arg, RUBY_IO_READABLE);
}
/*
@@ -6148,7 +6250,7 @@ rb_io_pread(int argc, VALUE *argv, VALUE io)
VALUE len, offset, str;
rb_io_t *fptr;
ssize_t n;
- struct prdwr_internal_arg arg = {.io = io};
+ struct prdwr_internal_arg arg;
int shrinkable;
rb_scan_args(argc, argv, "21", &len, &offset, &str);
@@ -6162,6 +6264,7 @@ rb_io_pread(int argc, VALUE *argv, VALUE io)
GetOpenFile(io, fptr);
rb_io_check_byte_readable(fptr);
+ arg.io = fptr;
arg.fd = fptr->fd;
rb_io_check_closed(fptr);
@@ -6184,17 +6287,24 @@ internal_pwrite_func(void *_arg)
{
struct prdwr_internal_arg *arg = _arg;
+ return (VALUE)pwrite(arg->fd, arg->buf, arg->count, arg->offset);
+}
+
+static VALUE
+pwrite_internal_call(VALUE _arg)
+{
+ struct prdwr_internal_arg *arg = (struct prdwr_internal_arg *)_arg;
+
VALUE scheduler = rb_fiber_scheduler_current();
if (scheduler != Qnil) {
- VALUE result = rb_fiber_scheduler_io_pwrite_memory(scheduler, arg->io, arg->offset, arg->buf, arg->count, 0);
+ VALUE result = rb_fiber_scheduler_io_pwrite_memory(scheduler, arg->io->self, arg->offset, arg->buf, arg->count, 0);
if (!UNDEF_P(result)) {
return rb_fiber_scheduler_io_result_apply(result);
}
}
-
- return (VALUE)pwrite(arg->fd, arg->buf, arg->count, arg->offset);
+ return rb_io_blocking_region_wait(arg->io, internal_pwrite_func, arg, RUBY_IO_WRITABLE);
}
/*
@@ -6227,7 +6337,7 @@ rb_io_pwrite(VALUE io, VALUE str, VALUE offset)
{
rb_io_t *fptr;
ssize_t n;
- struct prdwr_internal_arg arg = {.io = io};
+ struct prdwr_internal_arg arg;
VALUE tmp;
if (!RB_TYPE_P(str, T_STRING))
@@ -6238,13 +6348,15 @@ rb_io_pwrite(VALUE io, VALUE str, VALUE offset)
io = GetWriteIO(io);
GetOpenFile(io, fptr);
rb_io_check_writable(fptr);
+
+ arg.io = fptr;
arg.fd = fptr->fd;
tmp = rb_str_tmp_frozen_acquire(str);
arg.buf = RSTRING_PTR(tmp);
arg.count = (size_t)RSTRING_LEN(tmp);
- n = (ssize_t)rb_thread_io_blocking_call(internal_pwrite_func, &arg, fptr->fd, RB_WAITFD_OUT);
+ n = (ssize_t)pwrite_internal_call((VALUE)&arg);
if (n < 0) rb_sys_fail_path(fptr->pathv);
rb_str_tmp_frozen_release(str, tmp);
@@ -6349,7 +6461,7 @@ rb_io_binmode_p(VALUE io)
}
static const char*
-rb_io_fmode_modestr(int fmode)
+rb_io_fmode_modestr(enum rb_io_mode fmode)
{
if (fmode & FMODE_APPEND) {
if ((fmode & FMODE_READWRITE) == FMODE_READWRITE) {
@@ -6383,10 +6495,10 @@ io_encname_bom_p(const char *name, long len)
return len > bom_prefix_len && STRNCASECMP(name, bom_prefix, bom_prefix_len) == 0;
}
-int
+enum rb_io_mode
rb_io_modestr_fmode(const char *modestr)
{
- int fmode = 0;
+ enum rb_io_mode fmode = 0;
const char *m = modestr, *p = NULL;
switch (*m++) {
@@ -6443,7 +6555,7 @@ rb_io_modestr_fmode(const char *modestr)
int
rb_io_oflags_fmode(int oflags)
{
- int fmode = 0;
+ enum rb_io_mode fmode = 0;
switch (oflags & O_ACCMODE) {
case O_RDONLY:
@@ -6479,7 +6591,7 @@ rb_io_oflags_fmode(int oflags)
}
static int
-rb_io_fmode_oflags(int fmode)
+rb_io_fmode_oflags(enum rb_io_mode fmode)
{
int oflags = 0;
@@ -6564,7 +6676,7 @@ rb_io_oflags_modestr(int oflags)
* Qnil => no encoding specified (internal only)
*/
static void
-rb_io_ext_int_to_encs(rb_encoding *ext, rb_encoding *intern, rb_encoding **enc, rb_encoding **enc2, int fmode)
+rb_io_ext_int_to_encs(rb_encoding *ext, rb_encoding *intern, rb_encoding **enc, rb_encoding **enc2, enum rb_io_mode fmode)
{
int default_ext = 0;
@@ -6599,12 +6711,12 @@ unsupported_encoding(const char *name, rb_encoding *enc)
static void
parse_mode_enc(const char *estr, rb_encoding *estr_enc,
- rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
+ rb_encoding **enc_p, rb_encoding **enc2_p, enum rb_io_mode *fmode_p)
{
const char *p;
char encname[ENCODING_MAXNAMELEN+1];
int idx, idx2;
- int fmode = fmode_p ? *fmode_p : 0;
+ enum rb_io_mode fmode = fmode_p ? *fmode_p : 0;
rb_encoding *ext_enc, *int_enc;
long len;
@@ -6666,7 +6778,7 @@ parse_mode_enc(const char *estr, rb_encoding *estr_enc,
}
int
-rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, int *fmode_p)
+rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2_p, enum rb_io_mode *fmode_p)
{
VALUE encoding=Qnil, extenc=Qundef, intenc=Qundef, tmp;
int extracted = 0;
@@ -6735,9 +6847,9 @@ rb_io_extract_encoding_option(VALUE opt, rb_encoding **enc_p, rb_encoding **enc2
}
static void
-validate_enc_binmode(int *fmode_p, int ecflags, rb_encoding *enc, rb_encoding *enc2)
+validate_enc_binmode(enum rb_io_mode *fmode_p, int ecflags, rb_encoding *enc, rb_encoding *enc2)
{
- int fmode = *fmode_p;
+ enum rb_io_mode fmode = *fmode_p;
if ((fmode & FMODE_READABLE) &&
!enc2 &&
@@ -6762,7 +6874,7 @@ validate_enc_binmode(int *fmode_p, int ecflags, rb_encoding *enc, rb_encoding *e
}
static void
-extract_binmode(VALUE opthash, int *fmode)
+extract_binmode(VALUE opthash, enum rb_io_mode *fmode)
{
if (!NIL_P(opthash)) {
VALUE v;
@@ -6792,10 +6904,11 @@ extract_binmode(VALUE opthash, int *fmode)
void
rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
- int *oflags_p, int *fmode_p, struct rb_io_encoding *convconfig_p)
+ int *oflags_p, enum rb_io_mode *fmode_p, struct rb_io_encoding *convconfig_p)
{
VALUE vmode;
- int oflags, fmode;
+ int oflags;
+ enum rb_io_mode fmode;
rb_encoding *enc, *enc2;
int ecflags;
VALUE ecopts;
@@ -6953,7 +7066,10 @@ sysopen_func(void *ptr)
static inline int
rb_sysopen_internal(struct sysopen_struct *data)
{
- int fd = IO_WITHOUT_GVL_INT(sysopen_func, data);
+ int fd;
+ do {
+ fd = IO_WITHOUT_GVL_INT(sysopen_func, data);
+ } while (fd < 0 && errno == EINTR);
if (0 <= fd)
rb_update_max_fd(fd);
return fd;
@@ -7107,7 +7223,7 @@ io_set_encoding_by_bom(VALUE io)
}
static VALUE
-rb_file_open_generic(VALUE io, VALUE filename, int oflags, int fmode,
+rb_file_open_generic(VALUE io, VALUE filename, int oflags, enum rb_io_mode fmode,
const struct rb_io_encoding *convconfig, mode_t perm)
{
VALUE pathv;
@@ -7144,7 +7260,7 @@ rb_file_open_generic(VALUE io, VALUE filename, int oflags, int fmode,
static VALUE
rb_file_open_internal(VALUE io, VALUE filename, const char *modestr)
{
- int fmode = rb_io_modestr_fmode(modestr);
+ enum rb_io_mode fmode = rb_io_modestr_fmode(modestr);
const char *p = strchr(modestr, ':');
struct rb_io_encoding convconfig;
@@ -7460,7 +7576,7 @@ char *rb_execarg_commandline(const struct rb_execarg *eargp, VALUE *prog);
#ifndef __EMSCRIPTEN__
static VALUE
-pipe_open(VALUE execarg_obj, const char *modestr, int fmode,
+pipe_open(VALUE execarg_obj, const char *modestr, enum rb_io_mode fmode,
const struct rb_io_encoding *convconfig)
{
struct rb_execarg *eargp = NIL_P(execarg_obj) ? NULL : rb_execarg_get(execarg_obj);
@@ -7689,7 +7805,7 @@ pipe_open(VALUE execarg_obj, const char *modestr, int fmode,
}
#else
static VALUE
-pipe_open(VALUE execarg_obj, const char *modestr, int fmode,
+pipe_open(VALUE execarg_obj, const char *modestr, enum rb_io_mode fmode,
const struct rb_io_encoding *convconfig)
{
rb_raise(rb_eNotImpError, "popen() is not available");
@@ -7711,7 +7827,7 @@ is_popen_fork(VALUE prog)
}
static VALUE
-pipe_open_s(VALUE prog, const char *modestr, int fmode,
+pipe_open_s(VALUE prog, const char *modestr, enum rb_io_mode fmode,
const struct rb_io_encoding *convconfig)
{
int argc = 1;
@@ -7744,7 +7860,7 @@ static VALUE popen_finish(VALUE port, VALUE klass);
* whose $stdin and $stdout are connected to a new stream +io+.
*
* This method has potential security vulnerabilities if called with untrusted input;
- * see {Command Injection}[rdoc-ref:command_injection.rdoc].
+ * see {Command Injection}[rdoc-ref:security/command_injection.rdoc].
*
* If no block is given, returns the new stream,
* which depending on given +mode+ may be open for reading, writing, or both.
@@ -7753,7 +7869,8 @@ static VALUE popen_finish(VALUE port, VALUE klass);
* If a block is given, the stream is passed to the block
* (again, open for reading, writing, or both);
* when the block exits, the stream is closed,
- * and the block's value is assigned to global variable <tt>$?</tt> and returned.
+ * the block's value is returned,
+ * and the global variable <tt>$?</tt> is set to the child's exit status.
*
* Optional argument +mode+ may be any valid \IO mode.
* See {Access Modes}[rdoc-ref:File@Access+Modes].
@@ -7782,7 +7899,7 @@ static VALUE popen_finish(VALUE port, VALUE klass);
* - {Encoding options}[rdoc-ref:encodings.rdoc@Encoding+Options].
* - Options for Kernel#spawn.
*
- * <b>Forked \Process</b>
+ * <b>Forked Process</b>
*
* When argument +cmd+ is the 1-character string <tt>'-'</tt>, causes the process to fork:
* IO.popen('-') do |pipe|
@@ -7920,7 +8037,8 @@ rb_io_popen(VALUE pname, VALUE pmode, VALUE env, VALUE opt)
{
const char *modestr;
VALUE tmp, execarg_obj = Qnil;
- int oflags, fmode;
+ int oflags;
+ enum rb_io_mode fmode;
struct rb_io_encoding convconfig;
tmp = rb_check_array_type(pname);
@@ -7958,7 +8076,7 @@ popen_finish(VALUE port, VALUE klass)
if (NIL_P(port)) {
/* child */
if (rb_block_given_p()) {
- rb_yield(Qnil);
+ rb_protect(rb_yield, Qnil, NULL);
rb_io_flush(rb_ractor_stdout());
rb_io_flush(rb_ractor_stderr());
_exit(0);
@@ -8001,7 +8119,12 @@ ruby_popen_writer(char *const *argv, rb_pid_t *pid)
int write_pair[2];
# endif
- int result = rb_cloexec_pipe(write_pair);
+#ifdef HAVE_PIPE2
+ int result = pipe2(write_pair, O_CLOEXEC);
+#else
+ int result = pipe(write_pair);
+#endif
+
*pid = -1;
if (result == 0) {
# ifdef HAVE_WORKING_FORK
@@ -8029,8 +8152,9 @@ ruby_popen_writer(char *const *argv, rb_pid_t *pid)
static VALUE
rb_open_file(VALUE io, VALUE fname, VALUE vmode, VALUE vperm, VALUE opt)
{
+ int oflags;
+ enum rb_io_mode fmode;
struct rb_io_encoding convconfig;
- int oflags, fmode;
mode_t perm;
FilePathValue(fname);
@@ -8132,21 +8256,6 @@ rb_io_s_sysopen(int argc, VALUE *argv, VALUE _)
return INT2NUM(fd);
}
-static VALUE
-check_pipe_command(VALUE filename_or_command)
-{
- char *s = RSTRING_PTR(filename_or_command);
- long l = RSTRING_LEN(filename_or_command);
- char *e = s + l;
- int chlen;
-
- if (rb_enc_ascget(s, e, &chlen, rb_enc_get(filename_or_command)) == '|') {
- VALUE cmd = rb_str_new(s+chlen, l-chlen);
- return cmd;
- }
- return Qnil;
-}
-
/*
* call-seq:
* open(path, mode = 'r', perm = 0666, **opts) -> io or nil
@@ -8154,9 +8263,6 @@ check_pipe_command(VALUE filename_or_command)
*
* Creates an IO object connected to the given file.
*
- * This method has potential security vulnerabilities if called with untrusted input;
- * see {Command Injection}[rdoc-ref:command_injection.rdoc].
- *
* With no block given, file stream is returned:
*
* open('t.txt') # => #<File:t.txt>
@@ -8192,13 +8298,7 @@ rb_f_open(int argc, VALUE *argv, VALUE _)
redirect = TRUE;
}
else {
- VALUE cmd = check_pipe_command(tmp);
- if (!NIL_P(cmd)) {
- // TODO: when removed in 4.0, update command_injection.rdoc
- rb_warn_deprecated_to_remove_at(4.0, "Calling Kernel#open with a leading '|'", "IO.popen");
- argv[0] = cmd;
- return rb_io_s_popen(argc, argv, rb_cIO);
- }
+ argv[0] = tmp;
}
}
}
@@ -8213,12 +8313,19 @@ rb_f_open(int argc, VALUE *argv, VALUE _)
return rb_io_s_open(argc, argv, rb_cFile);
}
-static VALUE rb_io_open_generic(VALUE, VALUE, int, int, const struct rb_io_encoding *, mode_t);
+static VALUE
+rb_io_open_generic(VALUE klass, VALUE filename, int oflags, enum rb_io_mode fmode,
+ const struct rb_io_encoding *convconfig, mode_t perm)
+{
+ return rb_file_open_generic(io_alloc(klass), filename,
+ oflags, fmode, convconfig, perm);
+}
static VALUE
rb_io_open(VALUE io, VALUE filename, VALUE vmode, VALUE vperm, VALUE opt)
{
- int oflags, fmode;
+ int oflags;
+ enum rb_io_mode fmode;
struct rb_io_encoding convconfig;
mode_t perm;
@@ -8228,22 +8335,6 @@ rb_io_open(VALUE io, VALUE filename, VALUE vmode, VALUE vperm, VALUE opt)
}
static VALUE
-rb_io_open_generic(VALUE klass, VALUE filename, int oflags, int fmode,
- const struct rb_io_encoding *convconfig, mode_t perm)
-{
- VALUE cmd;
- if (klass == rb_cIO && !NIL_P(cmd = check_pipe_command(filename))) {
- // TODO: when removed in 4.0, update command_injection.rdoc
- rb_warn_deprecated_to_remove_at(4.0, "IO process creation with a leading '|'", "IO.popen");
- return pipe_open_s(cmd, rb_io_oflags_modestr(oflags), fmode, convconfig);
- }
- else {
- return rb_file_open_generic(io_alloc(klass), filename,
- oflags, fmode, convconfig, perm);
- }
-}
-
-static VALUE
io_reopen(VALUE io, VALUE nfile)
{
rb_io_t *fptr, *orig;
@@ -8270,7 +8361,7 @@ io_reopen(VALUE io, VALUE nfile)
rb_sys_fail_on_write(fptr);
}
else {
- flush_before_seek(fptr);
+ flush_before_seek(fptr, true);
}
if (orig->mode & FMODE_READABLE) {
pos = io_tell(orig);
@@ -8282,6 +8373,7 @@ io_reopen(VALUE io, VALUE nfile)
/* copy rb_io_t structure */
fptr->mode = orig->mode | (fptr->mode & FMODE_EXTERNAL);
+ fptr->encs = orig->encs;
fptr->pid = orig->pid;
fptr->lineno = orig->lineno;
if (RTEST(orig->pathv)) fptr->pathv = orig->pathv;
@@ -8291,6 +8383,10 @@ io_reopen(VALUE io, VALUE nfile)
fd = fptr->fd;
fd2 = orig->fd;
if (fd != fd2) {
+ // Interrupt all usage of the old file descriptor:
+ rb_thread_io_close_interrupt(fptr);
+ rb_thread_io_close_wait(fptr);
+
if (RUBY_IO_EXTERNAL_P(fptr) || fd <= 2 || !fptr->stdio_file) {
/* need to keep FILE objects of stdin, stdout and stderr */
if (rb_cloexec_dup2(fd2, fd) < 0)
@@ -8306,7 +8402,7 @@ io_reopen(VALUE io, VALUE nfile)
rb_update_max_fd(fd);
fptr->fd = fd;
}
- rb_thread_fd_close(fd);
+
if ((orig->mode & FMODE_READABLE) && pos >= 0) {
if (io_seek(fptr, pos, SEEK_SET) < 0 && errno) {
rb_sys_fail_path(fptr->pathv);
@@ -8395,7 +8491,7 @@ rb_io_reopen(int argc, VALUE *argv, VALUE file)
}
if (!NIL_P(nmode) || !NIL_P(opt)) {
- int fmode;
+ enum rb_io_mode fmode;
struct rb_io_encoding convconfig;
rb_io_extract_modeenc(&nmode, 0, opt, &oflags, &fmode, &convconfig);
@@ -8483,6 +8579,12 @@ rb_io_init_copy(VALUE dest, VALUE io)
fptr->pid = orig->pid;
fptr->lineno = orig->lineno;
fptr->timeout = orig->timeout;
+
+ ccan_list_head_init(&fptr->blocking_operations);
+ fptr->closing_ec = NULL;
+ fptr->wakeup_mutex = Qnil;
+ fptr->fork_generation = GET_VM()->fork_gen;
+
if (!NIL_P(orig->pathv)) fptr->pathv = orig->pathv;
fptr_copy_finalizer(fptr, orig);
@@ -8512,7 +8614,7 @@ rb_io_init_copy(VALUE dest, VALUE io)
* Formats and writes +objects+ to the stream.
*
* For details on +format_string+, see
- * {Format Specifications}[rdoc-ref:format_specifications.rdoc].
+ * {Format Specifications}[rdoc-ref:language/format_specifications.rdoc].
*
*/
@@ -8533,7 +8635,7 @@ rb_io_printf(int argc, const VALUE *argv, VALUE out)
* io.write(sprintf(format_string, *objects))
*
* For details on +format_string+, see
- * {Format Specifications}[rdoc-ref:format_specifications.rdoc].
+ * {Format Specifications}[rdoc-ref:language/format_specifications.rdoc].
*
* With the single argument +format_string+, formats +objects+ into the string,
* then writes the formatted string to $stdout:
@@ -8576,12 +8678,19 @@ rb_f_printf(int argc, VALUE *argv, VALUE _)
return Qnil;
}
+extern void rb_deprecated_str_setter(VALUE val, ID id, VALUE *var);
+
static void
-deprecated_str_setter(VALUE val, ID id, VALUE *var)
+deprecated_rs_setter(VALUE val, ID id, VALUE *var)
{
- rb_str_setter(val, id, &val);
+ rb_deprecated_str_setter(val, id, &val);
if (!NIL_P(val)) {
- rb_warn_deprecated("'%s'", NULL, rb_id2name(id));
+ if (rb_str_equal(val, rb_default_rs)) {
+ val = rb_default_rs;
+ }
+ else {
+ val = rb_str_frozen_bare_string(val);
+ }
}
*var = val;
}
@@ -9201,6 +9310,11 @@ rb_io_open_descriptor(VALUE klass, int descriptor, int mode, VALUE path, VALUE t
io->timeout = timeout;
+ ccan_list_head_init(&io->blocking_operations);
+ io->closing_ec = NULL;
+ io->wakeup_mutex = Qnil;
+ io->fork_generation = GET_VM()->fork_gen;
+
if (encoding) {
io->encs = *encoding;
}
@@ -9211,7 +9325,7 @@ rb_io_open_descriptor(VALUE klass, int descriptor, int mode, VALUE path, VALUE t
}
static VALUE
-prep_io(int fd, int fmode, VALUE klass, const char *path)
+prep_io(int fd, enum rb_io_mode fmode, VALUE klass, const char *path)
{
VALUE path_value = Qnil;
rb_encoding *e;
@@ -9257,7 +9371,7 @@ rb_io_fdopen(int fd, int oflags, const char *path)
}
static VALUE
-prep_stdio(FILE *f, int fmode, VALUE klass, const char *path)
+prep_stdio(FILE *f, enum rb_io_mode fmode, VALUE klass, const char *path)
{
rb_io_t *fptr;
VALUE io = prep_io(fileno(f), fmode|FMODE_EXTERNAL|DEFAULT_TEXTMODE, klass, path);
@@ -9340,6 +9454,10 @@ rb_io_fptr_new(void)
fp->encs.ecopts = Qnil;
fp->write_lock = Qnil;
fp->timeout = Qnil;
+ ccan_list_head_init(&fp->blocking_operations);
+ fp->closing_ec = NULL;
+ fp->wakeup_mutex = Qnil;
+ fp->fork_generation = GET_VM()->fork_gen;
return fp;
}
@@ -9381,7 +9499,8 @@ static VALUE io_initialize(VALUE io, VALUE fnum, VALUE vmode, VALUE opt);
* The new \IO object does not inherit encoding
* (because the integer file descriptor does not have an encoding):
*
- * fd = IO.sysopen('t.rus', 'rb')
+ * File.read('t.ja') # => "こんにちは"
+ * fd = IO.sysopen('t.ja', 'rb')
* io = IO.new(fd)
* io.external_encoding # => #<Encoding:UTF-8> # Not ASCII-8BIT.
*
@@ -9417,7 +9536,8 @@ static VALUE
io_initialize(VALUE io, VALUE fnum, VALUE vmode, VALUE opt)
{
rb_io_t *fp;
- int fd, fmode, oflags = O_RDONLY;
+ int fd, oflags = O_RDONLY;
+ enum rb_io_mode fmode;
struct rb_io_encoding convconfig;
#if defined(HAVE_FCNTL) && defined(F_GETFL)
int ofmode;
@@ -9469,6 +9589,10 @@ io_initialize(VALUE io, VALUE fnum, VALUE vmode, VALUE opt)
fp->encs = convconfig;
fp->pathv = path;
fp->timeout = Qnil;
+ ccan_list_head_init(&fp->blocking_operations);
+ fp->closing_ec = NULL;
+ fp->wakeup_mutex = Qnil;
+ fp->fork_generation = GET_VM()->fork_gen;
clear_codeconv(fp);
io_check_tty(fp);
if (fileno(stdin) == fd)
@@ -9698,7 +9822,7 @@ io_wait_readable(int argc, VALUE *argv, VALUE io)
rb_io_t *fptr;
RB_IO_POINTER(io, fptr);
- rb_io_check_readable(fptr);
+ rb_io_check_char_readable(fptr);
if (rb_io_read_pending(fptr)) return Qtrue;
@@ -9745,7 +9869,7 @@ io_wait_priority(int argc, VALUE *argv, VALUE io)
rb_io_t *fptr = NULL;
RB_IO_POINTER(io, fptr);
- rb_io_check_readable(fptr);
+ rb_io_check_char_readable(fptr);
if (rb_io_read_pending(fptr)) return Qtrue;
@@ -9802,7 +9926,7 @@ io_event_from_value(VALUE value)
/*
* call-seq:
* io.wait(events, timeout) -> event mask, false or nil
- * io.wait(timeout = nil, mode = :read) -> self, true, or false
+ * io.wait(*event_symbols[, timeout]) -> self, true, or false
*
* Waits until the IO becomes ready for the specified events and returns the
* subset of events that become ready, or a falsy value when times out.
@@ -9810,10 +9934,14 @@ io_event_from_value(VALUE value)
* The events can be a bit mask of +IO::READABLE+, +IO::WRITABLE+ or
* +IO::PRIORITY+.
*
- * Returns an event mask (truthy value) immediately when buffered data is available.
+ * Returns an event mask (truthy value) immediately when buffered data is
+ * available.
*
- * Optional parameter +mode+ is one of +:read+, +:write+, or
- * +:read_write+.
+ * The second form: if one or more event symbols (+:read+, +:write+, or
+ * +:read_write+) are passed, the event mask is the bit OR of the bitmask
+ * corresponding to those symbols. In this form, +timeout+ is optional, the
+ * order of the arguments is arbitrary, and returns +io+ if any of the
+ * events is ready.
*/
static VALUE
@@ -9823,10 +9951,6 @@ io_wait(int argc, VALUE *argv, VALUE io)
enum rb_io_event events = 0;
int return_io = 0;
- // The documented signature for this method is actually incorrect.
- // A single timeout is allowed in any position, and multiple symbols can be given.
- // Whether this is intentional or not, I don't know, and as such I consider this to
- // be a legacy/slow path.
if (argc != 2 || (RB_SYMBOL_P(argv[0]) || RB_SYMBOL_P(argv[1]))) {
// We'd prefer to return the actual mask, but this form would return the io itself:
return_io = 1;
@@ -9872,14 +9996,14 @@ io_wait(int argc, VALUE *argv, VALUE io)
}
static void
-argf_mark(void *ptr)
+argf_mark_and_move(void *ptr)
{
struct argf *p = ptr;
- rb_gc_mark(p->filename);
- rb_gc_mark(p->current_file);
- rb_gc_mark(p->argv);
- rb_gc_mark(p->inplace);
- rb_gc_mark(p->encs.ecopts);
+ rb_gc_mark_and_move(&p->filename);
+ rb_gc_mark_and_move(&p->current_file);
+ rb_gc_mark_and_move(&p->argv);
+ rb_gc_mark_and_move(&p->inplace);
+ rb_gc_mark_and_move(&p->encs.ecopts);
}
static size_t
@@ -9892,7 +10016,7 @@ argf_memsize(const void *ptr)
static const rb_data_type_t argf_type = {
"ARGF",
- {argf_mark, RUBY_TYPED_DEFAULT_FREE, argf_memsize},
+ {argf_mark_and_move, RUBY_TYPED_DEFAULT_FREE, argf_memsize, argf_mark_and_move},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
};
@@ -10018,7 +10142,7 @@ argf_next_argv(VALUE argf)
char *fn;
rb_io_t *fptr;
int stdout_binmode = 0;
- int fmode;
+ enum rb_io_mode fmode;
VALUE r_stdout = rb_ractor_stdout();
@@ -10523,14 +10647,14 @@ argf_readlines(int argc, VALUE *argv, VALUE argf)
* sets global variable <tt>$?</tt> to the process status.
*
* This method has potential security vulnerabilities if called with untrusted input;
- * see {Command Injection}[rdoc-ref:command_injection.rdoc].
+ * see {Command Injection}[rdoc-ref:security/command_injection.rdoc].
*
* Examples:
*
* $ `date` # => "Wed Apr 9 08:56:30 CDT 2003\n"
* $ `echo oops && exit 99` # => "oops\n"
* $ $? # => #<Process::Status: pid 17088 exit 99>
- * $ $?.status # => 99>
+ * $ $?.exitstatus # => 99
*
* The built-in syntax <tt>%x{...}</tt> uses this method.
*
@@ -10634,9 +10758,9 @@ select_internal(VALUE read, VALUE write, VALUE except, struct timeval *tp, rb_fd
if (!pending && n == 0) return Qnil; /* returns nil on timeout */
res = rb_ary_new2(3);
- rb_ary_push(res, rp?rb_ary_new():rb_ary_new2(0));
- rb_ary_push(res, wp?rb_ary_new():rb_ary_new2(0));
- rb_ary_push(res, ep?rb_ary_new():rb_ary_new2(0));
+ rb_ary_push(res, rp ? rb_ary_new_capa(RARRAY_LEN(read)) : rb_ary_new());
+ rb_ary_push(res, wp ? rb_ary_new_capa(RARRAY_LEN(write)) : rb_ary_new());
+ rb_ary_push(res, ep ? rb_ary_new_capa(RARRAY_LEN(except)) : rb_ary_new());
if (rp) {
list = RARRAY_AREF(res, 0);
@@ -10786,7 +10910,7 @@ do_io_advise(rb_io_t *fptr, VALUE advice, rb_off_t offset, rb_off_t len)
ias.offset = offset;
ias.len = len;
- rv = (int)rb_thread_io_blocking_region(io_advise_internal, &ias, fptr->fd);
+ rv = (int)rb_io_blocking_region(fptr, io_advise_internal, &ias);
if (rv && rv != ENOSYS) {
/* posix_fadvise(2) doesn't set errno. On success it returns 0; otherwise
it returns the error code. */
@@ -10876,6 +11000,16 @@ rb_io_advise(int argc, VALUE *argv, VALUE io)
#endif
}
+static int
+is_pos_inf(VALUE x)
+{
+ double f;
+ if (!RB_FLOAT_TYPE_P(x))
+ return 0;
+ f = RFLOAT_VALUE(x);
+ return isinf(f) && 0 < f;
+}
+
/*
* call-seq:
* IO.select(read_ios, write_ios = [], error_ios = [], timeout = nil) -> array or nil
@@ -10890,7 +11024,10 @@ rb_io_advise(int argc, VALUE *argv, VALUE io)
* Each of the arguments +read_ios+, +write_ios+, and +error_ios+
* is an array of IO objects.
*
- * Argument +timeout+ is an integer timeout interval in seconds.
+ * Argument +timeout+ is a numeric value (such as integer or float) timeout
+ * interval in seconds.
+ * +timeout+ can also be +nil+ or +Float::INFINITY+.
+ * +nil+ and +Float::INFINITY+ means no timeout.
*
* The method monitors the \IO objects given in all three arrays,
* waiting for some to be ready;
@@ -11041,7 +11178,7 @@ rb_f_select(int argc, VALUE *argv, VALUE obj)
int i;
rb_scan_args(argc, argv, "13", &args.read, &args.write, &args.except, &timeout);
- if (NIL_P(timeout)) {
+ if (NIL_P(timeout) || is_pos_inf(timeout)) {
args.timeout = 0;
}
else {
@@ -11078,16 +11215,16 @@ nogvl_ioctl(void *ptr)
}
static int
-do_ioctl(int fd, ioctl_req_t cmd, long narg)
+do_ioctl(struct rb_io *io, ioctl_req_t cmd, long narg)
{
int retval;
struct ioctl_arg arg;
- arg.fd = fd;
+ arg.fd = io->fd;
arg.cmd = cmd;
arg.narg = narg;
- retval = (int)rb_thread_io_blocking_region(nogvl_ioctl, &arg, fd);
+ retval = (int)rb_io_blocking_region(io, nogvl_ioctl, &arg);
return retval;
}
@@ -11350,7 +11487,7 @@ rb_ioctl(VALUE io, VALUE req, VALUE arg)
narg = setup_narg(cmd, &arg, ioctl_narg_len);
GetOpenFile(io, fptr);
- retval = do_ioctl(fptr->fd, cmd, narg);
+ retval = do_ioctl(fptr, cmd, narg);
return finish_narg(retval, arg, fptr);
}
@@ -11404,16 +11541,16 @@ nogvl_fcntl(void *ptr)
}
static int
-do_fcntl(int fd, int cmd, long narg)
+do_fcntl(struct rb_io *io, int cmd, long narg)
{
int retval;
struct fcntl_arg arg;
- arg.fd = fd;
+ arg.fd = io->fd;
arg.cmd = cmd;
arg.narg = narg;
- retval = (int)rb_thread_io_blocking_region(nogvl_fcntl, &arg, fd);
+ retval = (int)rb_io_blocking_region(io, nogvl_fcntl, &arg);
if (retval != -1) {
switch (cmd) {
#if defined(F_DUPFD)
@@ -11439,7 +11576,7 @@ rb_fcntl(VALUE io, VALUE req, VALUE arg)
narg = setup_narg(cmd, &arg, fcntl_narg_len);
GetOpenFile(io, fptr);
- retval = do_fcntl(fptr->fd, cmd, narg);
+ retval = do_fcntl(fptr, cmd, narg);
return finish_narg(retval, arg, fptr);
}
@@ -11787,7 +11924,7 @@ rb_io_s_pipe(int argc, VALUE *argv, VALUE klass)
VALUE opt;
rb_io_t *fptr, *fptr2;
struct io_encoding_set_args ies_args;
- int fmode = 0;
+ enum rb_io_mode fmode = 0;
VALUE ret;
argc = rb_scan_args(argc, argv, "02:", &v1, &v2, &opt);
@@ -11922,10 +12059,6 @@ io_s_foreach(VALUE v)
*
* Calls the block with each successive line read from the stream.
*
- * When called from class \IO (but not subclasses of \IO),
- * this method has potential security vulnerabilities if called with untrusted input;
- * see {Command Injection}[rdoc-ref:command_injection.rdoc].
- *
* The first argument must be a string that is the path to a file.
*
* With only argument +path+ given, parses lines from the file at the given +path+,
@@ -12025,10 +12158,6 @@ io_s_readlines(VALUE v)
*
* Returns an array of all lines read from the stream.
*
- * When called from class \IO (but not subclasses of \IO),
- * this method has potential security vulnerabilities if called with untrusted input;
- * see {Command Injection}[rdoc-ref:command_injection.rdoc].
- *
* The first argument must be a string that is the path to a file.
*
* With only argument +path+ given, parses lines from the file at the given +path+,
@@ -12114,10 +12243,6 @@ seek_before_access(VALUE argp)
* Opens the stream, reads and returns some or all of its content,
* and closes the stream; returns +nil+ if no bytes were read.
*
- * When called from class \IO (but not subclasses of \IO),
- * this method has potential security vulnerabilities if called with untrusted input;
- * see {Command Injection}[rdoc-ref:command_injection.rdoc].
- *
* The first argument must be a string that is the path to a file.
*
* With only argument +path+ given, reads in text mode and returns the entire content
@@ -12185,10 +12310,6 @@ rb_io_s_read(int argc, VALUE *argv, VALUE io)
* Behaves like IO.read, except that the stream is opened in binary mode
* with ASCII-8BIT encoding.
*
- * When called from class \IO (but not subclasses of \IO),
- * this method has potential security vulnerabilities if called with untrusted input;
- * see {Command Injection}[rdoc-ref:command_injection.rdoc].
- *
*/
static VALUE
@@ -12196,8 +12317,8 @@ rb_io_s_binread(int argc, VALUE *argv, VALUE io)
{
VALUE offset;
struct foreach_arg arg;
+ enum rb_io_mode fmode = FMODE_READABLE|FMODE_BINMODE;
enum {
- fmode = FMODE_READABLE|FMODE_BINMODE,
oflags = O_RDONLY
#ifdef O_BINARY
|O_BINARY
@@ -12289,10 +12410,6 @@ io_s_write(int argc, VALUE *argv, VALUE klass, int binary)
* Opens the stream, writes the given +data+ to it,
* and closes the stream; returns the number of bytes written.
*
- * When called from class \IO (but not subclasses of \IO),
- * this method has potential security vulnerabilities if called with untrusted input;
- * see {Command Injection}[rdoc-ref:command_injection.rdoc].
- *
* The first argument must be a string that is the path to a file.
*
* With only argument +path+ given, writes the given +data+ to the file at that path:
@@ -12339,10 +12456,6 @@ rb_io_s_write(int argc, VALUE *argv, VALUE io)
* Behaves like IO.write, except that the stream is opened in binary mode
* with ASCII-8BIT encoding.
*
- * When called from class \IO (but not subclasses of \IO),
- * this method has potential security vulnerabilities if called with untrusted input;
- * see {Command Injection}[rdoc-ref:command_injection.rdoc].
- *
*/
static VALUE
@@ -13057,6 +13170,7 @@ copy_stream_fallback_body(VALUE arg)
while (1) {
long numwrote;
long l;
+ rb_str_make_independent(buf);
if (stp->copy_length < (rb_off_t)0) {
l = buflen;
}
@@ -14766,7 +14880,7 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
* - \File +t.rb+:
*
* p "ARGV: #{ARGV}"
- * p "Line: #{ARGF.read}" # Read everything from all specified streams.
+ * p "Read: #{ARGF.read}" # Read everything from all specified streams.
*
* - Command and output:
*
@@ -14924,9 +15038,9 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
/*
* An instance of class \IO (commonly called a _stream_)
* represents an input/output stream in the underlying operating system.
- * \Class \IO is the basis for input and output in Ruby.
+ * Class \IO is the basis for input and output in Ruby.
*
- * \Class File is the only class in the Ruby core that is a subclass of \IO.
+ * Class File is the only class in the Ruby core that is a subclass of \IO.
* Some classes in the Ruby standard library are also subclasses of \IO;
* these include TCPSocket and UDPSocket.
*
@@ -14935,7 +15049,7 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
* found in ARGV (or found in STDIN if ARGV is empty).
* ARGF is not itself a subclass of \IO.
*
- * \Class StringIO provides an IO-like stream that handles a String.
+ * Class StringIO provides an IO-like stream that handles a String.
* StringIO is not itself a subclass of \IO.
*
* Important objects based on \IO include:
@@ -15023,6 +15137,9 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
* A new stream has position zero (and line number zero);
* method +rewind+ resets the position (and line number) to zero.
*
+ * These methods discard {buffers}[rdoc-ref:IO@Buffering] and the
+ * Encoding::Converter instances used for that \IO.
+ *
* The relevant methods:
*
* - IO#tell (aliased as +#pos+): Returns the current position (in bytes) in the stream.
@@ -15070,12 +15187,12 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
*
* == Line \IO
*
- * \Class \IO supports line-oriented
+ * Class \IO supports line-oriented
* {input}[rdoc-ref:IO@Line+Input] and {output}[rdoc-ref:IO@Line+Output]
*
* === Line Input
*
- * \Class \IO supports line-oriented input for
+ * Class \IO supports line-oriented input for
* {files}[rdoc-ref:IO@File+Line+Input] and {IO streams}[rdoc-ref:IO@Stream+Line+Input]
*
* ==== \File Line Input
@@ -15195,11 +15312,13 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
* File.open('t.txt') {|f| f.gets(11) } # => "First line\n"
* File.open('t.txt') {|f| f.gets(12) } # => "First line\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
+ * # Text with 3-byte characters, which will not be split.
+ * File.read('t.ja') # => "こんにちは"
+ * File.open('t.ja') {|f| f.gets(1).size } # => 1
+ * File.open('t.ja') {|f| f.gets(2).size } # => 1
+ * File.open('t.ja') {|f| f.gets(3).size } # => 1
+ * File.open('t.ja') {|f| f.gets(4).size } # => 2
+ * File.open('t.ja') {|f| f.gets(5).size } # => 2
*
* ===== Line Separator and Line Limit
*
@@ -15329,6 +15448,7 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
* - IO#putc: Writes a character to the stream.
* - IO#each_char: Reads each remaining character in the stream,
* passing the character to the given block.
+ *
* == Byte \IO
*
* You can process an \IO stream byte-by-byte using these methods:
@@ -15347,7 +15467,7 @@ set_LAST_READ_LINE(VALUE val, ID _x, VALUE *_y)
*
* == What's Here
*
- * First, what's elsewhere. \Class \IO:
+ * First, what's elsewhere. Class \IO:
*
* - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
* - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
@@ -15614,15 +15734,17 @@ 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, deprecated_str_setter);
+ rb_define_hooked_variable("$,", &rb_output_fs, 0, rb_deprecated_str_setter);
rb_default_rs = rb_fstring_lit("\n"); /* avoid modifying RS_default */
rb_vm_register_global_object(rb_default_rs);
rb_rs = rb_default_rs;
rb_output_rs = Qnil;
- 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_hooked_variable("$/", &rb_rs, 0, deprecated_rs_setter);
+ rb_gvar_ractor_local("$/"); // not local but ractor safe
+ rb_define_hooked_variable("$-0", &rb_rs, 0, deprecated_rs_setter);
+ rb_gvar_ractor_local("$-0"); // not local but ractor safe
+ rb_define_hooked_variable("$\\", &rb_output_rs, 0, rb_deprecated_str_setter);
rb_define_virtual_variable("$_", get_LAST_READ_LINE, set_LAST_READ_LINE);
rb_gvar_ractor_local("$_");
diff --git a/io_buffer.c b/io_buffer.c
index e6ca61bdae..f1afc3d3ba 100644
--- a/io_buffer.c
+++ b/io_buffer.c
@@ -6,17 +6,20 @@
**********************************************************************/
-#include "ruby/io.h"
#include "ruby/io/buffer.h"
#include "ruby/fiber/scheduler.h"
+// For `rb_nogvl`.
+#include "ruby/thread.h"
+
#include "internal.h"
#include "internal/array.h"
#include "internal/bits.h"
#include "internal/error.h"
+#include "internal/gc.h"
#include "internal/numeric.h"
#include "internal/string.h"
-#include "internal/thread.h"
+#include "internal/io.h"
VALUE rb_cIOBuffer;
VALUE rb_eIOBufferLockedError;
@@ -81,6 +84,8 @@ io_buffer_map_memory(size_t size, int flags)
if (base == MAP_FAILED) {
rb_sys_fail("io_buffer_map_memory:mmap");
}
+
+ ruby_annotate_mmap(base, size, "Ruby:io_buffer_map_memory");
#endif
return base;
@@ -267,14 +272,36 @@ io_buffer_free(struct rb_io_buffer *buffer)
#endif
}
-void
+static void
rb_io_buffer_type_mark(void *_buffer)
{
struct rb_io_buffer *buffer = _buffer;
- rb_gc_mark(buffer->source);
+ if (buffer->source != Qnil) {
+ if (RB_TYPE_P(buffer->source, T_STRING)) {
+ // The `source` String has to be pinned, because the `base` may point to the embedded String content,
+ // which can be otherwise moved by GC compaction.
+ rb_gc_mark(buffer->source);
+ } else {
+ rb_gc_mark_movable(buffer->source);
+ }
+ }
}
-void
+static void
+rb_io_buffer_type_compact(void *_buffer)
+{
+ struct rb_io_buffer *buffer = _buffer;
+ if (buffer->source != Qnil) {
+ if (RB_TYPE_P(buffer->source, T_STRING)) {
+ // The `source` String has to be pinned, because the `base` may point to the embedded String content,
+ // which can be otherwise moved by GC compaction.
+ } else {
+ buffer->source = rb_gc_location(buffer->source);
+ }
+ }
+}
+
+static void
rb_io_buffer_type_free(void *_buffer)
{
struct rb_io_buffer *buffer = _buffer;
@@ -282,7 +309,7 @@ rb_io_buffer_type_free(void *_buffer)
io_buffer_free(buffer);
}
-size_t
+static size_t
rb_io_buffer_type_size(const void *_buffer)
{
const struct rb_io_buffer *buffer = _buffer;
@@ -301,6 +328,7 @@ static const rb_data_type_t rb_io_buffer_type = {
.dmark = rb_io_buffer_type_mark,
.dfree = rb_io_buffer_type_free,
.dsize = rb_io_buffer_type_size,
+ .dcompact = rb_io_buffer_type_compact,
},
.data = NULL,
.flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE,
@@ -451,6 +479,8 @@ io_buffer_extract_offset_length(VALUE self, int argc, VALUE argv[], size_t *offs
VALUE
rb_io_buffer_type_allocate(VALUE self)
{
+ io_buffer_experimental();
+
struct rb_io_buffer *buffer = NULL;
VALUE instance = TypedData_Make_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);
@@ -493,7 +523,9 @@ io_buffer_for_yield_instance(VALUE _arguments)
arguments->instance = io_buffer_for_make_instance(arguments->klass, arguments->string, arguments->flags);
- rb_str_locktmp(arguments->string);
+ if (!RB_OBJ_FROZEN(arguments->string)) {
+ rb_str_locktmp(arguments->string);
+ }
return rb_yield(arguments->instance);
}
@@ -507,7 +539,9 @@ io_buffer_for_yield_instance_ensure(VALUE _arguments)
rb_io_buffer_free(arguments->instance);
}
- rb_str_unlocktmp(arguments->string);
+ if (!RB_OBJ_FROZEN(arguments->string)) {
+ rb_str_unlocktmp(arguments->string);
+ }
return Qnil;
}
@@ -537,7 +571,7 @@ io_buffer_for_yield_instance_ensure(VALUE _arguments)
* buffer.get_string(0, 1)
* # => "t"
* string
- * # => "best"
+ * # => "test"
*
* buffer.resize(100)
* # in `resize': Cannot resize external buffer! (IO::Buffer::AccessError)
@@ -617,8 +651,6 @@ 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, rb_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 *buffer = NULL;
@@ -635,18 +667,25 @@ rb_io_buffer_map(VALUE io, size_t size, rb_off_t offset, enum rb_io_buffer_flags
* 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.
+ * +file+ should be a +File+ instance, opened for reading or reading and writing.
*
* Optional +size+ and +offset+ of mapping can be specified.
+ * Trying to map an empty file or specify +size+ of 0 will raise an error.
+ * Valid values for +offset+ are system-dependent.
*
- * 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.
+ * By default, the buffer is writable and expects the file to be writable.
+ * It is also shared, so several processes can use the same mapping.
+ *
+ * You can pass IO::Buffer::READONLY in +flags+ argument to make a read-only buffer;
+ * this allows to work with files opened only for reading.
+ * Specifying IO::Buffer::PRIVATE in +flags+ creates a private mapping,
+ * which will not impact other processes or the underlying file.
+ * It also allows updating a buffer created from a read-only file.
*
* File.write('test.txt', 'test')
*
* buffer = IO::Buffer.map(File.open('test.txt'), nil, 0, IO::Buffer::READONLY)
- * # => #<IO::Buffer 0x00000001014a0000+4 MAPPED READONLY>
+ * # => #<IO::Buffer 0x00000001014a0000+4 EXTERNAL MAPPED FILE SHARED READONLY>
*
* buffer.readonly? # => true
*
@@ -654,7 +693,7 @@ rb_io_buffer_map(VALUE io, size_t size, rb_off_t offset, enum rb_io_buffer_flags
* # => "test"
*
* buffer.set_string('b', 0)
- * # `set_string': Buffer is not writable! (IO::Buffer::AccessError)
+ * # 'IO::Buffer#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)
@@ -676,31 +715,48 @@ io_buffer_map(int argc, VALUE *argv, VALUE klass)
// We might like to handle a string path?
VALUE io = argv[0];
+ rb_off_t file_size = rb_file_size(io);
+ // Compiler can confirm that we handled file_size <= 0 case:
+ if (UNLIKELY(file_size <= 0)) {
+ rb_raise(rb_eArgError, "Invalid negative or zero file size!");
+ }
+ // Here, we assume that file_size is positive:
+ else if (UNLIKELY((uintmax_t)file_size > SIZE_MAX)) {
+ rb_raise(rb_eArgError, "File larger than address space!");
+ }
+
size_t size;
if (argc >= 2 && !RB_NIL_P(argv[1])) {
size = io_buffer_extract_size(argv[1]);
- }
- else {
- rb_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!");
+ if (UNLIKELY(size == 0)) {
+ rb_raise(rb_eArgError, "Size can't be zero!");
}
- // 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;
+ if (UNLIKELY(size > (size_t)file_size)) {
+ rb_raise(rb_eArgError, "Size can't be larger than file size!");
}
}
+ else {
+ // This conversion should be safe:
+ size = (size_t)file_size;
+ }
// This is the file offset, not the buffer offset:
rb_off_t offset = 0;
if (argc >= 3) {
offset = NUM2OFFT(argv[2]);
+ if (UNLIKELY(offset < 0)) {
+ rb_raise(rb_eArgError, "Offset can't be negative!");
+ }
+ if (UNLIKELY(offset >= file_size)) {
+ rb_raise(rb_eArgError, "Offset too large!");
+ }
+ if (RB_NIL_P(argv[1])) {
+ // Decrease size if it's set from the actual file size:
+ size = (size_t)(file_size - offset);
+ }
+ else if (UNLIKELY((size_t)(file_size - offset) < size)) {
+ rb_raise(rb_eArgError, "Offset too large!");
+ }
}
enum rb_io_buffer_flags flags = 0;
@@ -749,8 +805,6 @@ io_flags_for_size(size_t size)
VALUE
rb_io_buffer_initialize(int argc, VALUE *argv, VALUE self)
{
- io_buffer_experimental();
-
rb_check_arity(argc, 0, 2);
struct rb_io_buffer *buffer = NULL;
@@ -843,7 +897,8 @@ rb_io_buffer_get_bytes(VALUE self, void **base, size_t *size)
static inline void
io_buffer_get_bytes_for_writing(struct rb_io_buffer *buffer, void **base, size_t *size)
{
- if (buffer->flags & RB_IO_BUFFER_READONLY) {
+ if (buffer->flags & RB_IO_BUFFER_READONLY ||
+ (!NIL_P(buffer->source) && OBJ_FROZEN(buffer->source))) {
rb_raise(rb_eIOBufferAccessError, "Buffer is not writable!");
}
@@ -1469,13 +1524,19 @@ VALUE rb_io_buffer_free_locked(VALUE self)
return self;
}
+static bool
+size_sum_is_bigger_than(size_t a, size_t b, size_t x)
+{
+ struct rbimpl_size_overflow_tag size = rbimpl_size_add_overflow(a, b);
+ return size.overflowed || size.result > x;
+}
+
// Validate that access to the buffer is within bounds, assuming you want to
// access length bytes from the specified offset.
static inline void
io_buffer_validate_range(struct rb_io_buffer *buffer, size_t offset, size_t length)
{
- // We assume here that offset + length won't overflow:
- if (offset + length > buffer->size) {
+ if (size_sum_is_bigger_than(offset, length, buffer->size)) {
rb_raise(rb_eArgError, "Specified offset+length is bigger than the buffer size!");
}
}
@@ -1532,6 +1593,7 @@ rb_io_buffer_slice(struct rb_io_buffer *buffer, VALUE self, size_t offset, size_
struct rb_io_buffer *slice = NULL;
TypedData_Get_Struct(instance, struct rb_io_buffer, &rb_io_buffer_type, slice);
+ slice->flags |= (buffer->flags & RB_IO_BUFFER_READONLY);
slice->base = (char*)buffer->base + offset;
slice->size = length;
@@ -1566,7 +1628,7 @@ rb_io_buffer_slice(struct rb_io_buffer *buffer, VALUE self, size_t offset, size_
* buffer's bounds.
*
* string = 'test'
- * buffer = IO::Buffer.for(string)
+ * buffer = IO::Buffer.for(string).dup
*
* slice = buffer.slice
* # =>
@@ -1593,12 +1655,8 @@ rb_io_buffer_slice(struct rb_io_buffer *buffer, VALUE self, size_t offset, size_
* # it is also visible at position 1 of the original buffer
* buffer
* # =>
- * # #<IO::Buffer 0x00007fc3d31e2d80+4 SLICE>
+ * # #<IO::Buffer 0x00007fc3d31e2d80+4 INTERNAL>
* # 0x00000000 74 6f 73 74 tost
- *
- * # ...and original string
- * string
- * # => tost
*/
static VALUE
io_buffer_slice(int argc, VALUE *argv, VALUE self)
@@ -1788,9 +1846,9 @@ rb_io_buffer_compare(VALUE self, VALUE other)
}
static void
-io_buffer_validate_type(size_t size, size_t offset)
+io_buffer_validate_type(size_t size, size_t offset, size_t extend)
{
- if (offset > size) {
+ if (size_sum_is_bigger_than(offset, extend, size)) {
rb_raise(rb_eArgError, "Type extends beyond end of buffer! (offset=%"PRIdSIZE" > size=%"PRIdSIZE")", offset, size);
}
}
@@ -1810,6 +1868,9 @@ io_buffer_validate_type(size_t size, size_t offset)
// :u64, :U64 | unsigned 64-bit integer.
// :s64, :S64 | signed 64-bit integer.
//
+// :u128, :U128 | unsigned 128-bit integer.
+// :s128, :S128 | signed 128-bit integer.
+//
// :f32, :F32 | 32-bit floating point number.
// :f64, :F64 | 64-bit floating point number.
@@ -1841,13 +1902,53 @@ ruby_swapf64(double value)
return swap.value;
}
+// Structures and conversion functions are now in numeric.h/numeric.c
+// Unified swap function for 128-bit integers (works with both signed and unsigned)
+// Since both rb_uint128_t and rb_int128_t have the same memory layout,
+// we can use a union to make the swap function work with both types
+static inline rb_uint128_t
+ruby_swap128_uint(rb_uint128_t x)
+{
+ rb_uint128_t result;
+#ifdef HAVE_UINT128_T
+#if __has_builtin(__builtin_bswap128)
+ result.value = __builtin_bswap128(x.value);
+#else
+ // Manual byte swap for 128-bit integers
+ uint64_t low = (uint64_t)x.value;
+ uint64_t high = (uint64_t)(x.value >> 64);
+ low = ruby_swap64(low);
+ high = ruby_swap64(high);
+ result.value = ((uint128_t)low << 64) | high;
+#endif
+#else
+ // Fallback swap function using two 64-bit integers
+ // For big-endian data on little-endian host (or vice versa):
+ // 1. Swap bytes within each 64-bit part
+ // 2. Swap the order of the parts (since big-endian stores high first, little-endian stores low first)
+ result.parts.low = ruby_swap64(x.parts.high);
+ result.parts.high = ruby_swap64(x.parts.low);
+#endif
+ return result;
+}
+
+static inline rb_int128_t
+ruby_swap128_int(rb_int128_t x)
+{
+ union uint128_int128_conversion conversion = {
+ .int128 = x
+ };
+ conversion.uint128 = ruby_swap128_uint(conversion.uint128);
+ return conversion.int128;
+}
+
#define IO_BUFFER_DECLARE_TYPE(name, type, endian, wrap, unwrap, swap) \
static ID RB_IO_BUFFER_DATA_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)); \
+ 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); \
@@ -1858,7 +1959,7 @@ io_buffer_read_##name(const void* base, size_t size, size_t *offset) \
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)); \
+ 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)); \
@@ -1887,6 +1988,11 @@ IO_BUFFER_DECLARE_TYPE(U64, uint64_t, RB_IO_BUFFER_BIG_ENDIAN, RB_ULL2NUM, RB_NU
IO_BUFFER_DECLARE_TYPE(s64, int64_t, RB_IO_BUFFER_LITTLE_ENDIAN, RB_LL2NUM, RB_NUM2LL, ruby_swap64)
IO_BUFFER_DECLARE_TYPE(S64, int64_t, RB_IO_BUFFER_BIG_ENDIAN, RB_LL2NUM, RB_NUM2LL, ruby_swap64)
+IO_BUFFER_DECLARE_TYPE(u128, rb_uint128_t, RB_IO_BUFFER_LITTLE_ENDIAN, rb_uint128_to_numeric, rb_numeric_to_uint128, ruby_swap128_uint)
+IO_BUFFER_DECLARE_TYPE(U128, rb_uint128_t, RB_IO_BUFFER_BIG_ENDIAN, rb_uint128_to_numeric, rb_numeric_to_uint128, ruby_swap128_uint)
+IO_BUFFER_DECLARE_TYPE(s128, rb_int128_t, RB_IO_BUFFER_LITTLE_ENDIAN, rb_int128_to_numeric, rb_numeric_to_int128, ruby_swap128_int)
+IO_BUFFER_DECLARE_TYPE(S128, rb_int128_t, RB_IO_BUFFER_BIG_ENDIAN, rb_int128_to_numeric, rb_numeric_to_int128, ruby_swap128_int)
+
IO_BUFFER_DECLARE_TYPE(f32, float, RB_IO_BUFFER_LITTLE_ENDIAN, DBL2NUM, NUM2DBL, ruby_swapf32)
IO_BUFFER_DECLARE_TYPE(F32, float, RB_IO_BUFFER_BIG_ENDIAN, DBL2NUM, NUM2DBL, ruby_swapf32)
IO_BUFFER_DECLARE_TYPE(f64, double, RB_IO_BUFFER_LITTLE_ENDIAN, DBL2NUM, NUM2DBL, ruby_swapf64)
@@ -1911,6 +2017,10 @@ io_buffer_buffer_type_size(ID buffer_type)
IO_BUFFER_DATA_TYPE_SIZE(U64)
IO_BUFFER_DATA_TYPE_SIZE(s64)
IO_BUFFER_DATA_TYPE_SIZE(S64)
+ IO_BUFFER_DATA_TYPE_SIZE(u128)
+ IO_BUFFER_DATA_TYPE_SIZE(U128)
+ IO_BUFFER_DATA_TYPE_SIZE(s128)
+ IO_BUFFER_DATA_TYPE_SIZE(S128)
IO_BUFFER_DATA_TYPE_SIZE(f32)
IO_BUFFER_DATA_TYPE_SIZE(F32)
IO_BUFFER_DATA_TYPE_SIZE(f64)
@@ -1967,6 +2077,11 @@ rb_io_buffer_get_value(const void* base, size_t size, ID buffer_type, size_t *of
IO_BUFFER_GET_VALUE(s64)
IO_BUFFER_GET_VALUE(S64)
+ IO_BUFFER_GET_VALUE(u128)
+ IO_BUFFER_GET_VALUE(U128)
+ IO_BUFFER_GET_VALUE(s128)
+ IO_BUFFER_GET_VALUE(S128)
+
IO_BUFFER_GET_VALUE(f32)
IO_BUFFER_GET_VALUE(F32)
IO_BUFFER_GET_VALUE(f64)
@@ -1996,6 +2111,10 @@ rb_io_buffer_get_value(const void* base, size_t size, ID buffer_type, size_t *of
* * +:U64+: unsigned integer, 8 bytes, big-endian
* * +:s64+: signed integer, 8 bytes, little-endian
* * +:S64+: signed integer, 8 bytes, big-endian
+ * * +:u128+: unsigned integer, 16 bytes, little-endian
+ * * +:U128+: unsigned integer, 16 bytes, big-endian
+ * * +:s128+: signed integer, 16 bytes, little-endian
+ * * +:S128+: signed integer, 16 bytes, big-endian
* * +:f32+: float, 4 bytes, little-endian
* * +:F32+: float, 4 bytes, big-endian
* * +:f64+: double, 8 bytes, little-endian
@@ -2177,7 +2296,7 @@ io_buffer_values(int argc, VALUE *argv, VALUE self)
/*
* call-seq:
- * each_byte([offset, [count]]) {|offset, byte| ...} -> self
+ * each_byte([offset, [count]]) {|byte| ...} -> self
* each_byte([offset, [count]]) -> enumerator
*
* Iterates over the buffer, yielding each byte starting from +offset+.
@@ -2201,7 +2320,7 @@ io_buffer_each_byte(int argc, VALUE *argv, VALUE self)
rb_io_buffer_get_bytes_for_reading(self, &base, &size);
size_t offset, count;
- io_buffer_extract_offset_count(RB_IO_BUFFER_DATA_TYPE_U8, size, argc-1, argv+1, &offset, &count);
+ io_buffer_extract_offset_count(RB_IO_BUFFER_DATA_TYPE_U8, size, argc, argv, &offset, &count);
for (size_t i = 0; i < count; i++) {
unsigned char *value = (unsigned char *)base + i + offset;
@@ -2233,6 +2352,11 @@ rb_io_buffer_set_value(const void* base, size_t size, ID buffer_type, size_t *of
IO_BUFFER_SET_VALUE(s64);
IO_BUFFER_SET_VALUE(S64);
+ IO_BUFFER_SET_VALUE(u128);
+ IO_BUFFER_SET_VALUE(U128);
+ IO_BUFFER_SET_VALUE(s128);
+ IO_BUFFER_SET_VALUE(S128);
+
IO_BUFFER_SET_VALUE(f32);
IO_BUFFER_SET_VALUE(F32);
IO_BUFFER_SET_VALUE(f64);
@@ -2330,8 +2454,32 @@ io_buffer_set_values(VALUE self, VALUE buffer_types, VALUE _offset, VALUE values
return SIZET2NUM(offset);
}
+static size_t IO_BUFFER_BLOCKING_SIZE = 1024*1024;
+
+struct io_buffer_memmove_arguments {
+ unsigned char * destination;
+ const unsigned char * source;
+ size_t length;
+};
+
+static void *
+io_buffer_memmove_blocking(void *data)
+{
+ struct io_buffer_memmove_arguments *arguments = (struct io_buffer_memmove_arguments *)data;
+
+ memmove(arguments->destination, arguments->source, arguments->length);
+
+ return NULL;
+}
+
static void
-io_buffer_memcpy(struct rb_io_buffer *buffer, size_t offset, const void *source_base, size_t source_offset, size_t source_size, size_t length)
+io_buffer_memmove_unblock(void *data)
+{
+ // No safe way to interrupt.
+}
+
+static void
+io_buffer_memmove(struct rb_io_buffer *buffer, size_t offset, const void *source_base, size_t source_offset, size_t source_size, size_t length)
{
void *base;
size_t size;
@@ -2339,11 +2487,21 @@ io_buffer_memcpy(struct rb_io_buffer *buffer, size_t offset, const void *source_
io_buffer_validate_range(buffer, offset, length);
- if (source_offset + length > source_size) {
+ if (size_sum_is_bigger_than(source_offset, length, source_size)) {
rb_raise(rb_eArgError, "The computed source range exceeds the size of the source buffer!");
}
- memcpy((unsigned char*)base+offset, (unsigned char*)source_base+source_offset, length);
+ struct io_buffer_memmove_arguments arguments = {
+ .destination = (unsigned char*)base+offset,
+ .source = (unsigned char*)source_base+source_offset,
+ .length = length
+ };
+
+ if (arguments.length >= IO_BUFFER_BLOCKING_SIZE) {
+ rb_nogvl(io_buffer_memmove_blocking, &arguments, io_buffer_memmove_unblock, &arguments, RB_NOGVL_OFFLOAD_SAFE);
+ } else if (arguments.length != 0) {
+ memmove(arguments.destination, arguments.source, arguments.length);
+ }
}
// (offset, length, source_offset) -> length
@@ -2380,7 +2538,7 @@ io_buffer_copy_from(struct rb_io_buffer *buffer, const void *source_base, size_t
length = source_size - source_offset;
}
- io_buffer_memcpy(buffer, offset, source_base, source_offset, source_size, length);
+ io_buffer_memmove(buffer, offset, source_base, source_offset, source_size, length);
return SIZET2NUM(length);
}
@@ -2415,7 +2573,9 @@ rb_io_buffer_initialize_copy(VALUE self, VALUE source)
io_buffer_initialize(self, buffer, NULL, source_size, io_flags_for_size(source_size), Qnil);
- return io_buffer_copy_from(buffer, source_base, source_size, 0, NULL);
+ VALUE result = io_buffer_copy_from(buffer, source_base, source_size, 0, NULL);
+ RB_GC_GUARD(source);
+ return result;
}
/*
@@ -2423,7 +2583,7 @@ rb_io_buffer_initialize_copy(VALUE self, VALUE source)
* copy(source, [offset, [length, [source_offset]]]) -> size
*
* Efficiently copy from a source IO::Buffer into the buffer, at +offset+
- * using +memcpy+. For copying String instances, see #set_string.
+ * using +memmove+. For copying String instances, see #set_string.
*
* buffer = IO::Buffer.new(32)
* # =>
@@ -2441,10 +2601,11 @@ rb_io_buffer_initialize_copy(VALUE self, VALUE source)
*
* #copy can be used to put buffer into strings associated with buffer:
*
- * string= "data: "
+ * string = "data: "
* # => "data: "
- * buffer = IO::Buffer.for(string)
- * buffer.copy(IO::Buffer.for("test"), 5)
+ * buffer = IO::Buffer.for(string) do |buffer|
+ * buffer.copy(IO::Buffer.for("test"), 5)
+ * end
* # => 4
* string
* # => "data:test"
@@ -2471,6 +2632,19 @@ rb_io_buffer_initialize_copy(VALUE self, VALUE source)
* buffer = IO::Buffer.new(2)
* buffer.copy(IO::Buffer.for('test'), 0)
* # in `copy': Specified offset+length is bigger than the buffer size! (ArgumentError)
+ *
+ * It is safe to copy between memory regions that overlaps each other.
+ * In such case, the data is copied as if the data was first copied from the source buffer to
+ * a temporary buffer, and then copied from the temporary buffer to the destination buffer.
+ *
+ * buffer = IO::Buffer.new(10)
+ * buffer.set_string("0123456789")
+ * buffer.copy(buffer, 3, 7)
+ * # => 7
+ * buffer
+ * # =>
+ * # #<IO::Buffer 0x000056494f8ce440+10 INTERNAL>
+ * # 0x00000000 30 31 32 30 31 32 33 34 35 36 0120123456
*/
static VALUE
io_buffer_copy(int argc, VALUE *argv, VALUE self)
@@ -2486,7 +2660,9 @@ io_buffer_copy(int argc, VALUE *argv, VALUE self)
rb_io_buffer_get_bytes_for_reading(source, &source_base, &source_size);
- return io_buffer_copy_from(buffer, source_base, source_size, argc-1, argv+1);
+ VALUE result = io_buffer_copy_from(buffer, source_base, source_size, argc-1, argv+1);
+ RB_GC_GUARD(source);
+ return result;
}
/*
@@ -2532,7 +2708,7 @@ io_buffer_get_string(int argc, VALUE *argv, VALUE self)
* call-seq: set_string(string, [offset, [length, [source_offset]]]) -> size
*
* Efficiently copy from a source String into the buffer, at +offset+ using
- * +memcpy+.
+ * +memmove+.
*
* buf = IO::Buffer.new(8)
* # =>
@@ -2564,7 +2740,9 @@ io_buffer_set_string(int argc, VALUE *argv, VALUE self)
const void *source_base = RSTRING_PTR(string);
size_t source_size = RSTRING_LEN(string);
- return io_buffer_copy_from(buffer, source_base, source_size, argc-1, argv+1);
+ VALUE result = io_buffer_copy_from(buffer, source_base, source_size, argc-1, argv+1);
+ RB_GC_GUARD(string);
+ return result;
}
void
@@ -2588,29 +2766,29 @@ rb_io_buffer_clear(VALUE self, uint8_t value, size_t offset, size_t length)
* Fill buffer with +value+, starting with +offset+ and going for +length+
* bytes.
*
- * buffer = IO::Buffer.for('test')
+ * buffer = IO::Buffer.for('test').dup
* # =>
- * # <IO::Buffer 0x00007fca40087c38+4 SLICE>
+ * # <IO::Buffer 0x00007fca40087c38+4 INTERNAL>
* # 0x00000000 74 65 73 74 test
*
* buffer.clear
* # =>
- * # <IO::Buffer 0x00007fca40087c38+4 SLICE>
+ * # <IO::Buffer 0x00007fca40087c38+4 INTERNAL>
* # 0x00000000 00 00 00 00 ....
*
* buf.clear(1) # fill with 1
* # =>
- * # <IO::Buffer 0x00007fca40087c38+4 SLICE>
+ * # <IO::Buffer 0x00007fca40087c38+4 INTERNAL>
* # 0x00000000 01 01 01 01 ....
*
* buffer.clear(2, 1, 2) # fill with 2, starting from offset 1, for 2 bytes
* # =>
- * # <IO::Buffer 0x00007fca40087c38+4 SLICE>
+ * # <IO::Buffer 0x00007fca40087c38+4 INTERNAL>
* # 0x00000000 01 02 02 01 ....
*
* buffer.clear(2, 1) # fill with 2, starting from offset 1
* # =>
- * # <IO::Buffer 0x00007fca40087c38+4 SLICE>
+ * # <IO::Buffer 0x00007fca40087c38+4 INTERNAL>
* # 0x00000000 01 02 02 02 ....
*/
static VALUE
@@ -2657,10 +2835,10 @@ io_buffer_default_size(size_t page_size)
}
struct io_buffer_blocking_region_argument {
+ struct rb_io *io;
struct rb_io_buffer *buffer;
rb_blocking_function_t *function;
void *data;
- int descriptor;
};
static VALUE
@@ -2668,7 +2846,7 @@ io_buffer_blocking_region_begin(VALUE _argument)
{
struct io_buffer_blocking_region_argument *argument = (void*)_argument;
- return rb_thread_io_blocking_region(argument->function, argument->data, argument->descriptor);
+ return rb_io_blocking_region(argument->io, argument->function, argument->data);
}
static VALUE
@@ -2682,13 +2860,16 @@ io_buffer_blocking_region_ensure(VALUE _argument)
}
static VALUE
-io_buffer_blocking_region(struct rb_io_buffer *buffer, rb_blocking_function_t *function, void *data, int descriptor)
+io_buffer_blocking_region(VALUE io, struct rb_io_buffer *buffer, rb_blocking_function_t *function, void *data)
{
+ struct rb_io *ioptr;
+ RB_IO_POINTER(io, ioptr);
+
struct io_buffer_blocking_region_argument argument = {
+ .io = ioptr,
.buffer = buffer,
.function = function,
.data = data,
- .descriptor = descriptor,
};
// If the buffer is already locked, we can skip the ensure (unlock):
@@ -2745,6 +2926,8 @@ io_buffer_read_internal(void *_argument)
VALUE
rb_io_buffer_read(VALUE self, VALUE io, size_t length, size_t offset)
{
+ io = rb_io_get_io(io);
+
VALUE scheduler = rb_fiber_scheduler_current();
if (scheduler != Qnil) {
VALUE result = rb_fiber_scheduler_io_read(scheduler, io, self, length, offset);
@@ -2775,7 +2958,7 @@ rb_io_buffer_read(VALUE self, VALUE io, size_t length, size_t offset)
.length = length,
};
- return io_buffer_blocking_region(buffer, io_buffer_read_internal, &argument, descriptor);
+ return io_buffer_blocking_region(io, buffer, io_buffer_read_internal, &argument);
}
/*
@@ -2862,6 +3045,8 @@ io_buffer_pread_internal(void *_argument)
VALUE
rb_io_buffer_pread(VALUE self, VALUE io, rb_off_t from, size_t length, size_t offset)
{
+ io = rb_io_get_io(io);
+
VALUE scheduler = rb_fiber_scheduler_current();
if (scheduler != Qnil) {
VALUE result = rb_fiber_scheduler_io_pread(scheduler, io, from, self, length, offset);
@@ -2893,7 +3078,7 @@ rb_io_buffer_pread(VALUE self, VALUE io, rb_off_t from, size_t length, size_t of
.offset = from,
};
- return io_buffer_blocking_region(buffer, io_buffer_pread_internal, &argument, descriptor);
+ return io_buffer_blocking_region(io, buffer, io_buffer_pread_internal, &argument);
}
/*
@@ -2982,6 +3167,8 @@ io_buffer_write_internal(void *_argument)
VALUE
rb_io_buffer_write(VALUE self, VALUE io, size_t length, size_t offset)
{
+ io = rb_io_get_write_io(rb_io_get_io(io));
+
VALUE scheduler = rb_fiber_scheduler_current();
if (scheduler != Qnil) {
VALUE result = rb_fiber_scheduler_io_write(scheduler, io, self, length, offset);
@@ -3012,7 +3199,7 @@ rb_io_buffer_write(VALUE self, VALUE io, size_t length, size_t offset)
.length = length,
};
- return io_buffer_blocking_region(buffer, io_buffer_write_internal, &argument, descriptor);
+ return io_buffer_blocking_region(io, buffer, io_buffer_write_internal, &argument);
}
/*
@@ -3046,6 +3233,7 @@ io_buffer_write(int argc, VALUE *argv, VALUE self)
return rb_io_buffer_write(self, io, length, offset);
}
+
struct io_buffer_pwrite_internal_argument {
// The file descriptor to write to:
int descriptor;
@@ -3091,6 +3279,8 @@ io_buffer_pwrite_internal(void *_argument)
VALUE
rb_io_buffer_pwrite(VALUE self, VALUE io, rb_off_t from, size_t length, size_t offset)
{
+ io = rb_io_get_write_io(rb_io_get_io(io));
+
VALUE scheduler = rb_fiber_scheduler_current();
if (scheduler != Qnil) {
VALUE result = rb_fiber_scheduler_io_pwrite(scheduler, io, from, self, length, offset);
@@ -3130,7 +3320,7 @@ rb_io_buffer_pwrite(VALUE self, VALUE io, rb_off_t from, size_t length, size_t o
.offset = from,
};
- return io_buffer_blocking_region(buffer, io_buffer_pwrite_internal, &argument, descriptor);
+ return io_buffer_blocking_region(io, buffer, io_buffer_pwrite_internal, &argument);
}
/*
@@ -3340,7 +3530,7 @@ io_buffer_overlaps(const struct rb_io_buffer *a, const struct rb_io_buffer *b)
return io_buffer_overlaps(b, a);
}
- return (b->base >= a->base) && (b->base <= (void*)((unsigned char *)a->base + a->size));
+ return (b->base >= a->base) && (b->base < (void*)((unsigned char *)a->base + a->size));
}
static inline void
@@ -3594,9 +3784,9 @@ io_buffer_not_inplace(VALUE self)
*
* File.write('test.txt', 'test data')
* # => 9
- * buffer = IO::Buffer.map(File.open('test.txt'))
+ * buffer = IO::Buffer.map(File.open('test.txt'), nil, 0, IO::Buffer::READONLY)
* # =>
- * # #<IO::Buffer 0x00007f3f0768c000+9 MAPPED IMMUTABLE>
+ * # #<IO::Buffer 0x00007f3f0768c000+9 EXTERNAL MAPPED FILE SHARED READONLY>
* # ...
* buffer.get_string(5, 2) # read 2 bytes, starting from offset 5
* # => "da"
@@ -3745,6 +3935,11 @@ Init_IO_Buffer(void)
IO_BUFFER_DEFINE_DATA_TYPE(s64);
IO_BUFFER_DEFINE_DATA_TYPE(S64);
+ IO_BUFFER_DEFINE_DATA_TYPE(u128);
+ IO_BUFFER_DEFINE_DATA_TYPE(U128);
+ IO_BUFFER_DEFINE_DATA_TYPE(s128);
+ IO_BUFFER_DEFINE_DATA_TYPE(S128);
+
IO_BUFFER_DEFINE_DATA_TYPE(f32);
IO_BUFFER_DEFINE_DATA_TYPE(F32);
IO_BUFFER_DEFINE_DATA_TYPE(f64);
diff --git a/iseq.c b/iseq.c
index 9631488411..97047794b1 100644
--- a/iseq.c
+++ b/iseq.c
@@ -19,6 +19,7 @@
#endif
#include "eval_intern.h"
+#include "id.h"
#include "id_table.h"
#include "internal.h"
#include "internal/bits.h"
@@ -31,19 +32,21 @@
#include "internal/io.h"
#include "internal/ruby_parser.h"
#include "internal/sanitizers.h"
+#include "internal/set_table.h"
#include "internal/symbol.h"
#include "internal/thread.h"
#include "internal/variable.h"
#include "iseq.h"
-#include "rjit.h"
#include "ruby/util.h"
#include "vm_core.h"
+#include "ractor_core.h"
#include "vm_callinfo.h"
#include "yjit.h"
#include "ruby/ractor.h"
#include "builtin.h"
#include "insns.inc"
#include "insns_info.inc"
+#include "zjit.h"
VALUE rb_cISeq;
static VALUE iseqw_new(const rb_iseq_t *iseq);
@@ -111,12 +114,14 @@ remove_from_constant_cache(ID id, IC ic)
st_data_t ic_data = (st_data_t)ic;
if (rb_id_table_lookup(vm->constant_cache, id, &lookup_result)) {
- st_table *ics = (st_table *)lookup_result;
- st_delete(ics, &ic_data, NULL);
+ set_table *ics = (set_table *)lookup_result;
+ set_table_delete(ics, &ic_data);
- if (ics->num_entries == 0) {
+ if (ics->num_entries == 0 &&
+ // See comment in vm_track_constant_cache on why we need this check
+ id != vm->inserting_constant_cache_id) {
rb_id_table_delete(vm->constant_cache, id);
- st_free_table(ics);
+ set_free_table(ics);
}
}
}
@@ -157,6 +162,24 @@ iseq_clear_ic_references(const rb_iseq_t *iseq)
}
}
+
+rb_hook_list_t *
+rb_iseq_local_hooks(const rb_iseq_t *iseq, rb_ractor_t *r, bool create)
+{
+ rb_hook_list_t *hook_list = NULL;
+ st_data_t val;
+ if (st_lookup(rb_ractor_targeted_hooks(r), (st_data_t)iseq, &val)) {
+ hook_list = (rb_hook_list_t*)val;
+ RUBY_ASSERT(hook_list->type == hook_list_type_targeted_iseq);
+ }
+ else if (create) {
+ hook_list = RB_ZALLOC(rb_hook_list_t);
+ hook_list->type = hook_list_type_targeted_iseq;
+ st_insert(rb_ractor_targeted_hooks(r), (st_data_t)iseq, (st_data_t)hook_list);
+ }
+ return hook_list;
+}
+
void
rb_iseq_free(const rb_iseq_t *iseq)
{
@@ -165,7 +188,6 @@ rb_iseq_free(const rb_iseq_t *iseq)
if (iseq && ISEQ_BODY(iseq)) {
iseq_clear_ic_references(iseq);
struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
- rb_rjit_free_iseq(iseq); /* Notify RJIT */
#if USE_YJIT
rb_yjit_iseq_free(iseq);
if (FL_TEST_RAW((VALUE)iseq, ISEQ_TRANSLATED)) {
@@ -173,14 +195,15 @@ rb_iseq_free(const rb_iseq_t *iseq)
rb_yjit_live_iseq_count--;
}
#endif
+#if USE_ZJIT
+ rb_zjit_iseq_free(iseq);
+#endif
ruby_xfree((void *)body->iseq_encoded);
ruby_xfree((void *)body->insns_info.body);
ruby_xfree((void *)body->insns_info.positions);
#if VM_INSN_INFO_TABLE_IMPL == 2
ruby_xfree(body->insns_info.succ_index_table);
#endif
- if (LIKELY(body->local_table != rb_iseq_shared_exc_local_tbl))
- ruby_xfree((void *)body->local_table);
ruby_xfree((void *)body->is_entries);
ruby_xfree(body->call_data);
ruby_xfree((void *)body->catch_table);
@@ -194,18 +217,21 @@ rb_iseq_free(const rb_iseq_t *iseq)
if (body->param.keyword != NULL) {
if (body->param.keyword->table != &body->local_table[body->param.keyword->bits_start - body->param.keyword->num])
ruby_xfree((void *)body->param.keyword->table);
- ruby_xfree((void *)body->param.keyword->default_values);
+ if (body->param.keyword->default_values) {
+ ruby_xfree((void *)body->param.keyword->default_values);
+ }
ruby_xfree((void *)body->param.keyword);
}
+ if (LIKELY(body->local_table != rb_iseq_shared_exc_local_tbl)) {
+ ruby_xfree((void *)body->local_table);
+ }
+ ruby_xfree((void *)body->lvar_states);
+
compile_data_free(ISEQ_COMPILE_DATA(iseq));
if (body->outer_variables) rb_id_table_free(body->outer_variables);
ruby_xfree(body);
}
- if (iseq && ISEQ_EXECUTABLE_P(iseq) && iseq->aux.exec.local_hooks) {
- rb_hook_list_free(iseq->aux.exec.local_hooks);
- }
-
RUBY_FREE_LEAVE("iseq");
}
@@ -230,7 +256,30 @@ iseq_scan_bits(unsigned int page, iseq_bits_t bits, VALUE *code, VALUE *original
}
static void
-rb_iseq_mark_and_move_each_value(const rb_iseq_t *iseq, VALUE *original_iseq)
+rb_iseq_mark_and_move_each_compile_data_value(const rb_iseq_t *iseq, VALUE *original_iseq)
+{
+ unsigned int size;
+ VALUE *code;
+ const struct iseq_compile_data *const compile_data = ISEQ_COMPILE_DATA(iseq);
+
+ size = compile_data->iseq_size;
+ code = compile_data->iseq_encoded;
+
+ // Embedded VALUEs
+ if (compile_data->mark_bits.list) {
+ if(compile_data->is_single_mark_bit) {
+ iseq_scan_bits(0, compile_data->mark_bits.single, code, original_iseq);
+ }
+ else {
+ for (unsigned int i = 0; i < ISEQ_MBITS_BUFLEN(size); i++) {
+ iseq_bits_t bits = compile_data->mark_bits.list[i];
+ iseq_scan_bits(i, bits, code, original_iseq);
+ }
+ }
+ }
+}
+static void
+rb_iseq_mark_and_move_each_body_value(const rb_iseq_t *iseq, VALUE *original_iseq)
{
unsigned int size;
VALUE *code;
@@ -278,11 +327,9 @@ rb_iseq_mark_and_move_each_value(const rb_iseq_t *iseq, VALUE *original_iseq)
iseq_scan_bits(0, body->mark_bits.single, code, original_iseq);
}
else {
- if (body->mark_bits.list) {
- for (unsigned int i = 0; i < ISEQ_MBITS_BUFLEN(size); i++) {
- iseq_bits_t bits = body->mark_bits.list[i];
- iseq_scan_bits(i, bits, code, original_iseq);
- }
+ for (unsigned int i = 0; i < ISEQ_MBITS_BUFLEN(size); i++) {
+ iseq_bits_t bits = body->mark_bits.list[i];
+ iseq_scan_bits(i, bits, code, original_iseq);
}
}
}
@@ -300,15 +347,13 @@ cc_is_active(const struct rb_callcache *cc, bool reference_updating)
cc = (const struct rb_callcache *)rb_gc_location((VALUE)cc);
}
- if (vm_cc_markable(cc)) {
- if (cc->klass) { // cc is not invalidated
- const struct rb_callable_method_entry_struct *cme = vm_cc_cme(cc);
- if (reference_updating) {
- cme = (const struct rb_callable_method_entry_struct *)rb_gc_location((VALUE)cme);
- }
- if (!METHOD_ENTRY_INVALIDATED(cme)) {
- return true;
- }
+ if (vm_cc_markable(cc) && vm_cc_valid(cc)) {
+ const struct rb_callable_method_entry_struct *cme = vm_cc_cme(cc);
+ if (reference_updating) {
+ cme = (const struct rb_callable_method_entry_struct *)rb_gc_location((VALUE)cme);
+ }
+ if (!METHOD_ENTRY_INVALIDATED(cme)) {
+ return true;
}
}
}
@@ -325,10 +370,8 @@ rb_iseq_mark_and_move(rb_iseq_t *iseq, bool reference_updating)
if (ISEQ_BODY(iseq)) {
struct rb_iseq_constant_body *body = ISEQ_BODY(iseq);
- rb_iseq_mark_and_move_each_value(iseq, reference_updating ? ISEQ_ORIGINAL_ISEQ(iseq) : NULL);
+ rb_iseq_mark_and_move_each_body_value(iseq, reference_updating ? ISEQ_ORIGINAL_ISEQ(iseq) : NULL);
- rb_gc_mark_and_move(&body->variable.coverage);
- rb_gc_mark_and_move(&body->variable.pc2branchindex);
rb_gc_mark_and_move(&body->variable.script_lines);
rb_gc_mark_and_move(&body->location.label);
rb_gc_mark_and_move(&body->location.base_label);
@@ -346,17 +389,19 @@ rb_iseq_mark_and_move(rb_iseq_t *iseq, bool reference_updating)
if (cc_is_active(cds[i].cc, reference_updating)) {
rb_gc_mark_and_move_ptr(&cds[i].cc);
}
- else {
+ else if (cds[i].cc != rb_vm_empty_cc()) {
cds[i].cc = rb_vm_empty_cc();
}
}
}
- if (body->param.flags.has_kw && ISEQ_COMPILE_DATA(iseq) == NULL) {
+ if (body->param.flags.has_kw && body->param.keyword != NULL) {
const struct rb_iseq_param_keyword *const keyword = body->param.keyword;
- for (int j = 0, i = keyword->required_num; i < keyword->num; i++, j++) {
- rb_gc_mark_and_move(&keyword->default_values[j]);
+ if (keyword->default_values != NULL) {
+ for (int j = 0, i = keyword->required_num; i < keyword->num; i++, j++) {
+ rb_gc_mark_and_move(&keyword->default_values[j]);
+ }
}
}
@@ -373,48 +418,51 @@ rb_iseq_mark_and_move(rb_iseq_t *iseq, bool reference_updating)
}
if (reference_updating) {
-#if USE_RJIT
- rb_rjit_iseq_update_references(body);
-#endif
#if USE_YJIT
rb_yjit_iseq_update_references(iseq);
#endif
+#if USE_ZJIT
+ rb_zjit_iseq_update_references(body->zjit_payload);
+#endif
}
else {
-#if USE_RJIT
- rb_rjit_iseq_mark(body->rjit_blocks);
-#endif
+ // TODO: check jit payload
+ if (!rb_gc_checking_shareable()) {
#if USE_YJIT
- rb_yjit_iseq_mark(body->yjit_payload);
+ rb_yjit_iseq_mark(body->yjit_payload);
+#endif
+#if USE_ZJIT
+ rb_zjit_iseq_mark(body->zjit_payload);
#endif
+ }
+ }
+
+ // TODO: ractor aware coverage
+ if (!rb_gc_checking_shareable()) {
+ rb_gc_mark_and_move(&body->variable.coverage);
+ rb_gc_mark_and_move(&body->variable.pc2branchindex);
}
}
if (FL_TEST_RAW((VALUE)iseq, ISEQ_NOT_LOADED_YET)) {
- rb_gc_mark_and_move(&iseq->aux.loader.obj);
+ if (!rb_gc_checking_shareable()) {
+ rb_gc_mark_and_move(&iseq->aux.loader.obj);
+ }
}
else if (FL_TEST_RAW((VALUE)iseq, ISEQ_USE_COMPILE_DATA)) {
- const struct iseq_compile_data *const compile_data = ISEQ_COMPILE_DATA(iseq);
-
- if (!reference_updating) {
- /* The operands in each instruction needs to be pinned because
- * if auto-compaction runs in iseq_set_sequence, then the objects
- * could exist on the generated_iseq buffer, which would not be
- * reference updated which can lead to T_MOVED (and subsequently
- * T_NONE) objects on the iseq. */
- rb_iseq_mark_and_pin_insn_storage(compile_data->insn.storage_head);
- }
+ if (!rb_gc_checking_shareable()) {
+ const struct iseq_compile_data *const compile_data = ISEQ_COMPILE_DATA(iseq);
+
+ rb_iseq_mark_and_move_insn_storage(compile_data->insn.storage_head);
+ rb_iseq_mark_and_move_each_compile_data_value(iseq, reference_updating ? ISEQ_ORIGINAL_ISEQ(iseq) : NULL);
- rb_gc_mark_and_move((VALUE *)&compile_data->err_info);
- rb_gc_mark_and_move((VALUE *)&compile_data->catch_table_ary);
+ rb_gc_mark_and_move((VALUE *)&compile_data->err_info);
+ rb_gc_mark_and_move((VALUE *)&compile_data->catch_table_ary);
+ }
}
else {
/* executable */
VM_ASSERT(ISEQ_EXECUTABLE_P(iseq));
-
- if (iseq->aux.exec.local_hooks) {
- rb_hook_list_mark_and_update(iseq->aux.exec.local_hooks);
- }
}
RUBY_MARK_LEAVE("iseq");
@@ -519,9 +567,14 @@ rb_iseq_pathobj_new(VALUE path, VALUE realpath)
pathobj = rb_fstring(path);
}
else {
- if (!NIL_P(realpath)) realpath = rb_fstring(realpath);
- pathobj = rb_ary_new_from_args(2, rb_fstring(path), realpath);
- rb_obj_freeze(pathobj);
+ if (!NIL_P(realpath)) {
+ realpath = rb_fstring(realpath);
+ }
+ VALUE fpath = rb_fstring(path);
+
+ pathobj = rb_ary_new_from_args(2, fpath, realpath);
+ rb_ary_freeze(pathobj);
+ RB_OBJ_SET_SHAREABLE(pathobj);
}
return pathobj;
}
@@ -533,6 +586,24 @@ rb_iseq_pathobj_set(const rb_iseq_t *iseq, VALUE path, VALUE realpath)
rb_iseq_pathobj_new(path, realpath));
}
+// Make a dummy iseq for a dummy frame that exposes a path for profilers to inspect
+rb_iseq_t *
+rb_iseq_alloc_with_dummy_path(VALUE fname)
+{
+ rb_iseq_t *dummy_iseq = iseq_alloc();
+
+ ISEQ_BODY(dummy_iseq)->type = ISEQ_TYPE_TOP;
+
+ if (!RB_OBJ_SHAREABLE_P(fname)) {
+ RB_OBJ_SET_FROZEN_SHAREABLE(fname);
+ }
+
+ RB_OBJ_WRITE(dummy_iseq, &ISEQ_BODY(dummy_iseq)->location.pathobj, fname);
+ RB_OBJ_WRITE(dummy_iseq, &ISEQ_BODY(dummy_iseq)->location.label, fname);
+
+ return dummy_iseq;
+}
+
static rb_iseq_location_t *
iseq_location_setup(rb_iseq_t *iseq, VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_code_location_t *code_location, const int node_id)
{
@@ -575,11 +646,11 @@ set_relation(rb_iseq_t *iseq, const rb_iseq_t *piseq)
body->local_iseq = iseq;
}
else if (piseq) {
- body->local_iseq = ISEQ_BODY(piseq)->local_iseq;
+ RB_OBJ_WRITE(iseq, &body->local_iseq, ISEQ_BODY(piseq)->local_iseq);
}
if (piseq) {
- body->parent_iseq = piseq;
+ RB_OBJ_WRITE(iseq, &body->parent_iseq, piseq);
}
if (type == ISEQ_TYPE_MAIN) {
@@ -602,6 +673,18 @@ new_arena(void)
return new_arena;
}
+static int
+prepare_node_id(const NODE *node)
+{
+ if (!node) return -1;
+
+ if (nd_type(node) == NODE_SCOPE && RNODE_SCOPE(node)->nd_parent) {
+ return nd_node_id(RNODE_SCOPE(node)->nd_parent);
+ }
+
+ return nd_node_id(node);
+}
+
static VALUE
prepare_iseq_build(rb_iseq_t *iseq,
VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_code_location_t *code_location, const int node_id,
@@ -893,12 +976,12 @@ rb_iseq_new_top(const VALUE ast_value, VALUE name, VALUE path, VALUE realpath, c
* The main entry-point into the prism compiler when a file is required.
*/
rb_iseq_t *
-pm_iseq_new_top(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent)
+pm_iseq_new_top(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent, int *error_state)
{
iseq_new_setup_coverage(path, (int) (node->parser->newline_list.size - 1));
return pm_iseq_new_with_opt(node, name, path, realpath, 0, parent, 0,
- ISEQ_TYPE_TOP, &COMPILE_OPTION_DEFAULT);
+ ISEQ_TYPE_TOP, &COMPILE_OPTION_DEFAULT, error_state);
}
rb_iseq_t *
@@ -917,13 +1000,13 @@ rb_iseq_new_main(const VALUE ast_value, VALUE path, VALUE realpath, const rb_ise
* main file in the program.
*/
rb_iseq_t *
-pm_iseq_new_main(pm_scope_node_t *node, VALUE path, VALUE realpath, const rb_iseq_t *parent, int opt)
+pm_iseq_new_main(pm_scope_node_t *node, VALUE path, VALUE realpath, const rb_iseq_t *parent, int opt, int *error_state)
{
iseq_new_setup_coverage(path, (int) (node->parser->newline_list.size - 1));
return pm_iseq_new_with_opt(node, rb_fstring_lit("<main>"),
path, realpath, 0,
- parent, 0, ISEQ_TYPE_MAIN, opt ? &COMPILE_OPTION_DEFAULT : &COMPILE_OPTION_FALSE);
+ parent, 0, ISEQ_TYPE_MAIN, opt ? &COMPILE_OPTION_DEFAULT : &COMPILE_OPTION_FALSE, error_state);
}
rb_iseq_t *
@@ -943,7 +1026,7 @@ rb_iseq_new_eval(const VALUE ast_value, VALUE name, VALUE path, VALUE realpath,
rb_iseq_t *
pm_iseq_new_eval(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpath,
- int first_lineno, const rb_iseq_t *parent, int isolated_depth)
+ int first_lineno, const rb_iseq_t *parent, int isolated_depth, int *error_state)
{
if (rb_get_coverage_mode() & COVERAGE_TARGET_EVAL) {
VALUE coverages = rb_get_coverages();
@@ -953,7 +1036,7 @@ pm_iseq_new_eval(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpath,
}
return pm_iseq_new_with_opt(node, name, path, realpath, first_lineno,
- parent, isolated_depth, ISEQ_TYPE_EVAL, &COMPILE_OPTION_DEFAULT);
+ parent, isolated_depth, ISEQ_TYPE_EVAL, &COMPILE_OPTION_DEFAULT, error_state);
}
static inline rb_iseq_t *
@@ -971,7 +1054,7 @@ iseq_translate(rb_iseq_t *iseq)
}
rb_iseq_t *
-rb_iseq_new_with_opt(const VALUE ast_value, VALUE name, VALUE path, VALUE realpath,
+rb_iseq_new_with_opt(VALUE ast_value, VALUE name, VALUE path, VALUE realpath,
int first_lineno, const rb_iseq_t *parent, int isolated_depth,
enum rb_iseq_type type, const rb_compile_option_t *option,
VALUE script_lines)
@@ -999,15 +1082,35 @@ rb_iseq_new_with_opt(const VALUE ast_value, VALUE name, VALUE path, VALUE realpa
script_lines = ISEQ_BODY(parent)->variable.script_lines;
}
- prepare_iseq_build(iseq, name, path, realpath, first_lineno, node ? &node->nd_loc : NULL, node ? nd_node_id(node) : -1,
+ prepare_iseq_build(iseq, name, path, realpath, first_lineno, node ? &node->nd_loc : NULL, prepare_node_id(node),
parent, isolated_depth, type, script_lines, option);
rb_iseq_compile_node(iseq, node);
finish_iseq_build(iseq);
+ RB_GC_GUARD(ast_value);
return iseq_translate(iseq);
}
+struct pm_iseq_new_with_opt_data {
+ rb_iseq_t *iseq;
+ pm_scope_node_t *node;
+};
+
+VALUE
+pm_iseq_new_with_opt_try(VALUE d)
+{
+ struct pm_iseq_new_with_opt_data *data = (struct pm_iseq_new_with_opt_data *)d;
+
+ // This can compile child iseqs, which can raise syntax errors
+ pm_iseq_compile_node(data->iseq, data->node);
+
+ // This raises an exception if there is a syntax error
+ finish_iseq_build(data->iseq);
+
+ return Qundef;
+}
+
/**
* This is a step in the prism compiler that is called once all of the various
* options have been established. It is called from one of the pm_iseq_new_*
@@ -1023,11 +1126,10 @@ rb_iseq_new_with_opt(const VALUE ast_value, VALUE name, VALUE path, VALUE realpa
rb_iseq_t *
pm_iseq_new_with_opt(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpath,
int first_lineno, const rb_iseq_t *parent, int isolated_depth,
- enum rb_iseq_type type, const rb_compile_option_t *option)
+ enum rb_iseq_type type, const rb_compile_option_t *option, int *error_state)
{
rb_iseq_t *iseq = iseq_alloc();
ISEQ_BODY(iseq)->prism = true;
- ISEQ_BODY(iseq)->param.flags.use_block = true; // unused block warning is not supported yet
rb_compile_option_t next_option;
if (!option) option = &COMPILE_OPTION_DEFAULT;
@@ -1047,11 +1149,16 @@ pm_iseq_new_with_opt(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpa
.end_pos = { .lineno = (int) end.line, .column = (int) end.column }
};
- prepare_iseq_build(iseq, name, path, realpath, first_lineno, &code_location, -1,
- parent, isolated_depth, type, Qnil, option);
+ prepare_iseq_build(iseq, name, path, realpath, first_lineno, &code_location, node->ast_node->node_id,
+ parent, isolated_depth, type, node->script_lines == NULL ? Qnil : *node->script_lines, option);
- pm_iseq_compile_node(iseq, node);
- finish_iseq_build(iseq);
+ struct pm_iseq_new_with_opt_data data = {
+ .iseq = iseq,
+ .node = node
+ };
+ rb_protect(pm_iseq_new_with_opt_try, (VALUE)&data, error_state);
+
+ if (*error_state) return NULL;
return iseq_translate(iseq);
}
@@ -1087,6 +1194,21 @@ rb_iseq_load_iseq(VALUE fname)
return NULL;
}
+const rb_iseq_t *
+rb_iseq_compile_iseq(VALUE str, VALUE fname)
+{
+ VALUE args[] = {
+ str, fname
+ };
+ VALUE iseqv = rb_check_funcall(rb_cISeq, rb_intern("compile"), 2, args);
+
+ if (!SPECIAL_CONST_P(iseqv) && RBASIC_CLASS(iseqv) == rb_cISeq) {
+ return iseqw_check(iseqv);
+ }
+
+ return NULL;
+}
+
#define CHECK_ARRAY(v) rb_to_array_type(v)
#define CHECK_HASH(v) rb_to_hash_type(v)
#define CHECK_STRING(v) rb_str_to_str(v)
@@ -1276,8 +1398,18 @@ pm_iseq_compile_with_option(VALUE src, VALUE file, VALUE realpath, VALUE line, V
ln = NUM2INT(line);
StringValueCStr(file);
+ bool parse_file = false;
+ if (RB_TYPE_P(src, T_FILE)) {
+ parse_file = true;
+ src = rb_io_path(src);
+ }
+ else {
+ src = StringValue(src);
+ }
+
pm_parse_result_t result = { 0 };
pm_options_line_set(&result.options, NUM2INT(line));
+ pm_options_scopes_init(&result.options, 1);
result.node.coverage_enabled = 1;
switch (option.frozen_string_literal) {
@@ -1294,20 +1426,28 @@ pm_iseq_compile_with_option(VALUE src, VALUE file, VALUE realpath, VALUE line, V
break;
}
+ VALUE script_lines;
VALUE error;
- if (RB_TYPE_P(src, T_FILE)) {
- VALUE filepath = rb_io_path(src);
- error = pm_load_parse_file(&result, filepath);
- RB_GC_GUARD(filepath);
+
+ if (parse_file) {
+ error = pm_load_parse_file(&result, src, ruby_vm_keep_script_lines ? &script_lines : NULL);
}
else {
- src = StringValue(src);
- error = pm_parse_string(&result, src, file);
+ error = pm_parse_string(&result, src, file, ruby_vm_keep_script_lines ? &script_lines : NULL);
}
+ RB_GC_GUARD(src);
+
if (error == Qnil) {
- iseq = pm_iseq_new_with_opt(&result.node, name, file, realpath, ln, NULL, 0, ISEQ_TYPE_TOP, &option);
+ int error_state;
+ iseq = pm_iseq_new_with_opt(&result.node, name, file, realpath, ln, NULL, 0, ISEQ_TYPE_TOP, &option, &error_state);
+
pm_parse_result_free(&result);
+
+ if (error_state) {
+ RUBY_ASSERT(iseq == NULL);
+ rb_jump_tag(error_state);
+ }
}
else {
pm_parse_result_free(&result);
@@ -1401,8 +1541,8 @@ remove_coverage_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);
+ void *ptr = rb_asan_poisoned_object_p(v);
+ rb_asan_unpoison_object(v, false);
if (rb_obj_is_iseq(v)) {
rb_iseq_t *iseq = (rb_iseq_t *)v;
@@ -1423,9 +1563,9 @@ rb_iseq_remove_coverage_all(void)
/* define wrapper class methods (RubyVM::InstructionSequence) */
static void
-iseqw_mark(void *ptr)
+iseqw_mark_and_move(void *ptr)
{
- rb_gc_mark_movable(*(VALUE *)ptr);
+ rb_gc_mark_and_move((VALUE *)ptr);
}
static size_t
@@ -1434,20 +1574,13 @@ iseqw_memsize(const void *ptr)
return rb_iseq_memsize(*(const rb_iseq_t **)ptr);
}
-static void
-iseqw_ref_update(void *ptr)
-{
- VALUE *vptr = ptr;
- *vptr = rb_gc_location(*vptr);
-}
-
static const rb_data_type_t iseqw_data_type = {
"T_IMEMO/iseq",
{
- iseqw_mark,
+ iseqw_mark_and_move,
RUBY_TYPED_DEFAULT_FREE,
iseqw_memsize,
- iseqw_ref_update,
+ iseqw_mark_and_move,
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED
};
@@ -1468,8 +1601,8 @@ iseqw_new(const rb_iseq_t *iseq)
RB_OBJ_WRITE(obj, ptr, iseq);
/* cache a wrapper object */
+ RB_OBJ_SET_FROZEN_SHAREABLE((VALUE)obj);
RB_OBJ_WRITE((VALUE)iseq, &iseq->wrapper, obj);
- RB_OBJ_FREEZE((VALUE)iseq);
return obj;
}
@@ -1531,7 +1664,7 @@ iseqw_s_compile_parser(int argc, VALUE *argv, VALUE self, bool prism)
* real path and first line number of the ruby code in +source+ which are
* metadata attached to the returned +iseq+.
*
- * +file+ is used for `__FILE__` and exception backtrace. +path+ is used for
+ * +file+ is used for +__FILE__+ and exception backtrace. +path+ is used for
* +require_relative+ base. It is recommended these should be the same full
* path.
*
@@ -1559,7 +1692,49 @@ iseqw_s_compile_parser(int argc, VALUE *argv, VALUE self, bool prism)
static VALUE
iseqw_s_compile(int argc, VALUE *argv, VALUE self)
{
- return iseqw_s_compile_parser(argc, argv, self, *rb_ruby_prism_ptr());
+ return iseqw_s_compile_parser(argc, argv, self, rb_ruby_prism_p());
+}
+
+/*
+ * call-seq:
+ * InstructionSequence.compile_parsey(source[, file[, path[, line[, options]]]]) -> iseq
+ *
+ * Takes +source+, which can be a string of Ruby code, or an open +File+ object.
+ * that contains Ruby source code. It parses and compiles using parse.y.
+ *
+ * Optionally takes +file+, +path+, and +line+ which describe the file path,
+ * real path and first line number of the ruby code in +source+ which are
+ * metadata attached to the returned +iseq+.
+ *
+ * +file+ is used for +__FILE__+ and exception backtrace. +path+ is used for
+ * +require_relative+ base. It is recommended these should be the same full
+ * path.
+ *
+ * +options+, which can be +true+, +false+ or a +Hash+, is used to
+ * modify the default behavior of the Ruby iseq compiler.
+ *
+ * For details regarding valid compile options see ::compile_option=.
+ *
+ * RubyVM::InstructionSequence.compile_parsey("a = 1 + 2")
+ * #=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
+ *
+ * path = "test.rb"
+ * RubyVM::InstructionSequence.compile_parsey(File.read(path), path, File.expand_path(path))
+ * #=> <RubyVM::InstructionSequence:<compiled>@test.rb:1>
+ *
+ * file = File.open("test.rb")
+ * RubyVM::InstructionSequence.compile_parsey(file)
+ * #=> <RubyVM::InstructionSequence:<compiled>@<compiled>:1>
+ *
+ * path = File.expand_path("test.rb")
+ * RubyVM::InstructionSequence.compile_parsey(File.read(path), path, path)
+ * #=> <RubyVM::InstructionSequence:<compiled>@/absolute/path/to/test.rb:1>
+ *
+ */
+static VALUE
+iseqw_s_compile_parsey(int argc, VALUE *argv, VALUE self)
+{
+ return iseqw_s_compile_parser(argc, argv, self, false);
}
/*
@@ -1573,7 +1748,7 @@ iseqw_s_compile(int argc, VALUE *argv, VALUE self)
* real path and first line number of the ruby code in +source+ which are
* metadata attached to the returned +iseq+.
*
- * +file+ is used for `__FILE__` and exception backtrace. +path+ is used for
+ * +file+ is used for +__FILE__+ and exception backtrace. +path+ is used for
* +require_relative+ base. It is recommended these should be the same full
* path.
*
@@ -1582,19 +1757,19 @@ iseqw_s_compile(int argc, VALUE *argv, VALUE self)
*
* For details regarding valid compile options see ::compile_option=.
*
- * RubyVM::InstructionSequence.compile("a = 1 + 2")
+ * RubyVM::InstructionSequence.compile_prism("a = 1 + 2")
* #=> <RubyVM::InstructionSequence:<compiled>@<compiled>>
*
* path = "test.rb"
- * RubyVM::InstructionSequence.compile(File.read(path), path, File.expand_path(path))
+ * RubyVM::InstructionSequence.compile_prism(File.read(path), path, File.expand_path(path))
* #=> <RubyVM::InstructionSequence:<compiled>@test.rb:1>
*
* file = File.open("test.rb")
- * RubyVM::InstructionSequence.compile(file)
+ * RubyVM::InstructionSequence.compile_prism(file)
* #=> <RubyVM::InstructionSequence:<compiled>@<compiled>:1>
*
* path = File.expand_path("test.rb")
- * RubyVM::InstructionSequence.compile(File.read(path), path, path)
+ * RubyVM::InstructionSequence.compile_prism(File.read(path), path, path)
* #=> <RubyVM::InstructionSequence:<compiled>@/absolute/path/to/test.rb:1>
*
*/
@@ -1667,6 +1842,7 @@ iseqw_s_compile_file(int argc, VALUE *argv, VALUE self)
1, NULL, 0, ISEQ_TYPE_TOP, &option,
Qnil));
rb_ast_dispose(ast);
+ RB_GC_GUARD(ast_value);
rb_vm_pop_frame(ec);
RB_GC_GUARD(v);
@@ -1716,20 +1892,31 @@ iseqw_s_compile_file_prism(int argc, VALUE *argv, VALUE self)
result.options.line = 1;
result.node.coverage_enabled = 1;
- VALUE error = pm_load_parse_file(&result, file);
+ VALUE script_lines;
+ VALUE error = pm_load_parse_file(&result, file, ruby_vm_keep_script_lines ? &script_lines : NULL);
if (error == Qnil) {
make_compile_option(&option, opt);
- ret = iseqw_new(pm_iseq_new_with_opt(&result.node, rb_fstring_lit("<main>"),
- file,
- rb_realpath_internal(Qnil, file, 1),
- 1, NULL, 0, ISEQ_TYPE_TOP, &option));
+ int error_state;
+ rb_iseq_t *iseq = pm_iseq_new_with_opt(&result.node, rb_fstring_lit("<main>"),
+ file,
+ rb_realpath_internal(Qnil, file, 1),
+ 1, NULL, 0, ISEQ_TYPE_TOP, &option, &error_state);
+
pm_parse_result_free(&result);
+
+ if (error_state) {
+ RUBY_ASSERT(iseq == NULL);
+ rb_jump_tag(error_state);
+ }
+
+ ret = iseqw_new(iseq);
rb_vm_pop_frame(ec);
RB_GC_GUARD(v);
return ret;
- } else {
+ }
+ else {
pm_parse_result_free(&result);
rb_vm_pop_frame(ec);
RB_GC_GUARD(v);
@@ -1824,7 +2011,11 @@ rb_iseqw_to_iseq(VALUE iseqw)
static VALUE
iseqw_eval(VALUE self)
{
- return rb_iseq_eval(iseqw_check(self));
+ const rb_iseq_t *iseq = iseqw_check(self);
+ if (0 == ISEQ_BODY(iseq)->iseq_size) {
+ rb_raise(rb_eTypeError, "attempt to evaluate dummy InstructionSequence");
+ }
+ return rb_iseq_eval(iseq, rb_current_box());
}
/*
@@ -2258,15 +2449,22 @@ rb_iseq_event_flags(const rb_iseq_t *iseq, size_t pos)
}
}
+static void rb_iseq_trace_flag_cleared(const rb_iseq_t *iseq, size_t pos);
+
+// Clear tracing event flags and turn off tracing for a given instruction as needed.
+// This is currently used after updating a one-shot line coverage for the current instruction.
void
rb_iseq_clear_event_flags(const rb_iseq_t *iseq, size_t pos, rb_event_flag_t reset)
{
- struct iseq_insn_info_entry *entry = (struct iseq_insn_info_entry *)get_insn_info(iseq, pos);
- if (entry) {
- entry->events &= ~reset;
- if (!(entry->events & iseq->aux.exec.global_trace_events)) {
- void rb_iseq_trace_flag_cleared(const rb_iseq_t *iseq, size_t pos);
- rb_iseq_trace_flag_cleared(iseq, pos);
+ RB_VM_LOCKING() {
+ rb_vm_barrier();
+
+ struct iseq_insn_info_entry *entry = (struct iseq_insn_info_entry *)get_insn_info(iseq, pos);
+ if (entry) {
+ entry->events &= ~reset;
+ if (!(entry->events & iseq->aux.exec.global_trace_events)) {
+ rb_iseq_trace_flag_cleared(iseq, pos);
+ }
}
}
}
@@ -2449,6 +2647,7 @@ rb_insn_operand_intern(const rb_iseq_t *iseq,
CALL_FLAG(KWARG);
CALL_FLAG(KW_SPLAT);
CALL_FLAG(KW_SPLAT_MUT);
+ CALL_FLAG(FORWARDING);
CALL_FLAG(OPT_SEND); /* maybe not reachable */
rb_ary_push(ary, rb_ary_join(flags, rb_str_new2("|")));
}
@@ -2658,6 +2857,7 @@ rb_iseq_disasm_recursive(const rb_iseq_t *iseq, VALUE indent)
disasm_builtin_attr(str, iseq, LEAF);
disasm_builtin_attr(str, iseq, SINGLE_NOARG_LEAF);
disasm_builtin_attr(str, iseq, INLINE_BLOCK);
+ disasm_builtin_attr(str, iseq, C_TRACE);
}
rb_str_cat2(str, "\n");
@@ -2731,11 +2931,11 @@ rb_iseq_disasm_recursive(const rb_iseq_t *iseq, VALUE indent)
}
snprintf(argi, sizeof(argi), "%s%s%s%s%s%s", /* arg, opts, rest, post, kwrest, block */
- body->param.lead_num > li ? "Arg" : "",
+ (body->param.lead_num > li) ? (body->param.flags.ambiguous_param0 ? "AmbiguousArg" : "Arg") : "",
opti,
- (body->param.flags.has_rest && body->param.rest_start == li) ? "Rest" : "",
+ (body->param.flags.has_rest && body->param.rest_start == li) ? (body->param.flags.anon_rest ? "AnonRest" : "Rest") : "",
(body->param.flags.has_post && body->param.post_start <= li && li < body->param.post_start + body->param.post_num) ? "Post" : "",
- (body->param.flags.has_kwrest && keyword->rest_start == li) ? "Kwrest" : "",
+ (body->param.flags.has_kwrest && keyword->rest_start == li) ? (body->param.flags.anon_kwrest ? "AnonKwrest" : "Kwrest") : "",
(body->param.flags.has_block && body->param.block_start == li) ? "Block" : "");
rb_str_cat(str, indent_str, indent_len);
@@ -2796,7 +2996,7 @@ rb_estimate_iv_count(VALUE klass, const rb_iseq_t * initialize_iseq)
attr_index_t count = (attr_index_t)rb_id_table_size(iv_names);
VALUE superclass = rb_class_superclass(klass);
- count += RCLASS_EXT(superclass)->max_iv_count;
+ count += RCLASS_MAX_IV_COUNT(superclass);
rb_id_table_free(iv_names);
@@ -2978,7 +3178,10 @@ iseqw_s_of(VALUE klass, VALUE body)
{
const rb_iseq_t *iseq = NULL;
- if (rb_obj_is_proc(body)) {
+ if (rb_frame_info_p(body)) {
+ iseq = rb_get_iseq_from_frame_info(body);
+ }
+ else if (rb_obj_is_proc(body)) {
iseq = vm_proc_iseq(body);
if (!rb_obj_is_iseq((VALUE)iseq)) {
@@ -3000,10 +3203,10 @@ iseqw_s_of(VALUE klass, VALUE body)
* InstructionSequence.disasm(body) -> str
* InstructionSequence.disassemble(body) -> str
*
- * Takes +body+, a Method or Proc object, and returns a String with the
- * human readable instructions for +body+.
+ * Takes +body+, a +Method+ or +Proc+ object, and returns a +String+
+ * with the human readable instructions for +body+.
*
- * For a Method object:
+ * For a +Method+ object:
*
* # /tmp/method.rb
* def hello
@@ -3023,7 +3226,7 @@ iseqw_s_of(VALUE klass, VALUE body)
* 0013 trace 16 ( 3)
* 0015 leave ( 2)
*
- * For a Proc:
+ * For a +Proc+ object:
*
* # /tmp/proc.rb
* p = proc { num = 1 + 2 }
@@ -3142,6 +3345,7 @@ iseq_type_id(enum rb_iseq_type type)
static VALUE
iseq_data_to_ary(const rb_iseq_t *iseq)
{
+ VALUE iseq_value = (VALUE)iseq;
unsigned int i;
long l;
const struct rb_iseq_constant_body *const iseq_body = ISEQ_BODY(iseq);
@@ -3159,7 +3363,7 @@ iseq_data_to_ary(const rb_iseq_t *iseq)
VALUE exception = rb_ary_new(); /* [[....]] */
VALUE misc = rb_hash_new();
- static ID insn_syms[VM_INSTRUCTION_SIZE/2]; /* w/o-trace only */
+ static ID insn_syms[VM_BARE_INSTRUCTION_SIZE]; /* w/o-trace only */
struct st_table *labels_table = st_init_numtable();
VALUE labels_wrapper = TypedData_Wrap_Struct(0, &label_wrapper, labels_table);
@@ -3177,7 +3381,7 @@ iseq_data_to_ary(const rb_iseq_t *iseq)
for (i=0; i<iseq_body->local_table_size; i++) {
ID lid = iseq_body->local_table[i];
if (lid) {
- if (rb_id2str(lid)) {
+ if (lid != idItImplicit && rb_id2str(lid)) {
rb_ary_push(locals, ID2SYM(lid));
}
else { /* hidden variable from id_internal() */
@@ -3474,6 +3678,9 @@ iseq_data_to_ary(const rb_iseq_t *iseq)
rb_ary_push(val, params);
rb_ary_push(val, exception);
rb_ary_push(val, body);
+
+ RB_GC_GUARD(iseq_value);
+
return val;
}
@@ -3487,19 +3694,28 @@ rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc)
ID req, opt, rest, block, key, keyrest;
#define PARAM_TYPE(type) rb_ary_push(a = rb_ary_new2(2), ID2SYM(type))
#define PARAM_ID(i) body->local_table[(i)]
-#define PARAM(i, type) ( \
- PARAM_TYPE(type), \
- rb_id2str(PARAM_ID(i)) ? \
- rb_ary_push(a, ID2SYM(PARAM_ID(i))) : \
+#define PARAM(i, type) ( \
+ PARAM_TYPE(type), \
+ PARAM_ID(i) != idItImplicit && rb_id2str(PARAM_ID(i)) ? \
+ rb_ary_push(a, ID2SYM(PARAM_ID(i))) : \
a)
CONST_ID(req, "req");
CONST_ID(opt, "opt");
+
+ if (body->param.flags.forwardable) {
+ // [[:rest, :*], [:keyrest, :**], [:block, :&]]
+ CONST_ID(rest, "rest");
+ CONST_ID(keyrest, "keyrest");
+ CONST_ID(block, "block");
+ rb_ary_push(args, rb_ary_new_from_args(2, ID2SYM(rest), ID2SYM(idMULT)));
+ rb_ary_push(args, rb_ary_new_from_args(2, ID2SYM(keyrest), ID2SYM(idPow)));
+ rb_ary_push(args, rb_ary_new_from_args(2, ID2SYM(block), ID2SYM(idAnd)));
+ }
+
if (is_proc) {
for (i = 0; i < body->param.lead_num; i++) {
- PARAM_TYPE(opt);
- rb_ary_push(a, rb_id2str(PARAM_ID(i)) ? ID2SYM(PARAM_ID(i)) : Qnil);
- rb_ary_push(args, a);
+ rb_ary_push(args, PARAM(i, opt));
}
}
else {
@@ -3509,11 +3725,7 @@ rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc)
}
r = body->param.lead_num + body->param.opt_num;
for (; i < r; i++) {
- PARAM_TYPE(opt);
- if (rb_id2str(PARAM_ID(i))) {
- rb_ary_push(a, ID2SYM(PARAM_ID(i)));
- }
- rb_ary_push(args, a);
+ rb_ary_push(args, PARAM(i, opt));
}
if (body->param.flags.has_rest) {
CONST_ID(rest, "rest");
@@ -3522,9 +3734,7 @@ rb_iseq_parameters(const rb_iseq_t *iseq, int is_proc)
r = body->param.post_start + body->param.post_num;
if (is_proc) {
for (i = body->param.post_start; i < r; i++) {
- PARAM_TYPE(opt);
- rb_ary_push(a, rb_id2str(PARAM_ID(i)) ? ID2SYM(PARAM_ID(i)) : Qnil);
- rb_ary_push(args, a);
+ rb_ary_push(args, PARAM(i, opt));
}
}
else {
@@ -3606,17 +3816,21 @@ rb_iseq_defined_string(enum defined_type type)
return rb_fstring_cstr(estr);
}
-/* A map from encoded_insn to insn_data: decoded insn number, its len,
- * non-trace version of encoded insn, and trace version. */
-
+// A map from encoded_insn to insn_data: decoded insn number, its len,
+// decoded ZJIT insn number, non-trace version of encoded insn,
+// trace version, and zjit version.
static st_table *encoded_insn_data;
typedef struct insn_data_struct {
int insn;
int insn_len;
void *notrace_encoded_insn;
void *trace_encoded_insn;
+#if USE_ZJIT
+ int zjit_insn;
+ void *zjit_encoded_insn;
+#endif
} insn_data_t;
-static insn_data_t insn_data[VM_INSTRUCTION_SIZE/2];
+static insn_data_t insn_data[VM_BARE_INSTRUCTION_SIZE];
void
rb_free_encoded_insn_data(void)
@@ -3624,6 +3838,8 @@ rb_free_encoded_insn_data(void)
st_free_table(encoded_insn_data);
}
+// Initialize a table to decode bare, trace, and zjit instructions.
+// This function also determines which instructions are used when TracePoint is enabled.
void
rb_vm_encoded_insn_data_table_init(void)
{
@@ -3631,32 +3847,42 @@ rb_vm_encoded_insn_data_table_init(void)
const void * const *table = rb_vm_get_insns_address_table();
#define INSN_CODE(insn) ((VALUE)table[insn])
#else
-#define INSN_CODE(insn) (insn)
+#define INSN_CODE(insn) ((VALUE)(insn))
#endif
- st_data_t insn;
- encoded_insn_data = st_init_numtable_with_size(VM_INSTRUCTION_SIZE / 2);
-
- for (insn = 0; insn < VM_INSTRUCTION_SIZE/2; insn++) {
- st_data_t key1 = (st_data_t)INSN_CODE(insn);
- st_data_t key2 = (st_data_t)INSN_CODE(insn + VM_INSTRUCTION_SIZE/2);
+ encoded_insn_data = st_init_numtable_with_size(VM_BARE_INSTRUCTION_SIZE);
- insn_data[insn].insn = (int)insn;
+ for (int insn = 0; insn < VM_BARE_INSTRUCTION_SIZE; insn++) {
+ insn_data[insn].insn = insn;
insn_data[insn].insn_len = insn_len(insn);
- 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);
- }
+ // When tracing :return events, we convert opt_invokebuiltin_delegate_leave + leave into
+ // opt_invokebuiltin_delegate + trace_leave, presumably because we don't want to fire
+ // :return events before invokebuiltin. https://github.com/ruby/ruby/pull/3256
+ int notrace_insn = (insn != BIN(opt_invokebuiltin_delegate_leave)) ? insn : BIN(opt_invokebuiltin_delegate);
+ insn_data[insn].notrace_encoded_insn = (void *)INSN_CODE(notrace_insn);
+ insn_data[insn].trace_encoded_insn = (void *)INSN_CODE(notrace_insn + VM_BARE_INSTRUCTION_SIZE);
+ st_data_t key1 = (st_data_t)INSN_CODE(insn);
+ st_data_t key2 = (st_data_t)INSN_CODE(insn + VM_BARE_INSTRUCTION_SIZE);
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]);
+
+#if USE_ZJIT
+ int zjit_insn = vm_bare_insn_to_zjit_insn(insn);
+ insn_data[insn].zjit_insn = zjit_insn;
+ insn_data[insn].zjit_encoded_insn = (insn != zjit_insn) ? (void *)INSN_CODE(zjit_insn) : 0;
+
+ if (insn != zjit_insn) {
+ st_data_t key3 = (st_data_t)INSN_CODE(zjit_insn);
+ st_add_direct(encoded_insn_data, key3, (st_data_t)&insn_data[insn]);
+ }
+#endif
}
}
+// Decode an insn address to an insn. This returns bare instructions
+// even if they're trace/zjit instructions. Use rb_vm_insn_addr2opcode
+// to decode trace/zjit instructions as is.
int
rb_vm_insn_addr2insn(const void *addr)
{
@@ -3671,7 +3897,8 @@ 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.
+// Decode an insn address to an insn. Unlike rb_vm_insn_addr2insn,
+// this function can return trace/zjit opcode variants.
int
rb_vm_insn_addr2opcode(const void *addr)
{
@@ -3682,15 +3909,22 @@ rb_vm_insn_addr2opcode(const void *addr)
insn_data_t *e = (insn_data_t *)val;
int opcode = e->insn;
if (addr == e->trace_encoded_insn) {
- opcode += VM_INSTRUCTION_SIZE/2;
+ opcode += VM_BARE_INSTRUCTION_SIZE;
+ }
+#if USE_ZJIT
+ else if (addr == e->zjit_encoded_insn) {
+ opcode = e->zjit_insn;
}
+#endif
return opcode;
}
rb_bug("rb_vm_insn_addr2opcode: invalid insn address: %p", addr);
}
-// Decode `ISEQ_BODY(iseq)->iseq_encoded[i]` to an insn.
+// Decode `ISEQ_BODY(iseq)->iseq_encoded[i]` to an insn. This returns
+// bare instructions even if they're trace/zjit instructions. Use
+// rb_vm_insn_addr2opcode to decode trace/zjit instructions as is.
int
rb_vm_insn_decode(const VALUE encoded)
{
@@ -3702,15 +3936,16 @@ rb_vm_insn_decode(const VALUE encoded)
return insn;
}
+// Turn on or off tracing for a given instruction address
static inline int
-encoded_iseq_trace_instrument(VALUE *iseq_encoded_insn, rb_event_flag_t turnon, bool remain_current_trace)
+encoded_iseq_trace_instrument(VALUE *iseq_encoded_insn, rb_event_flag_t turnon, bool remain_traced)
{
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) {
+ if (remain_traced && key == (st_data_t)e->trace_encoded_insn) {
turnon = 1;
}
*iseq_encoded_insn = (VALUE) (turnon ? e->trace_encoded_insn : e->notrace_encoded_insn);
@@ -3720,7 +3955,8 @@ encoded_iseq_trace_instrument(VALUE *iseq_encoded_insn, rb_event_flag_t turnon,
rb_bug("trace_instrument: invalid insn address: %p", (void *)*iseq_encoded_insn);
}
-void
+// Turn off tracing for an instruction at pos after tracing event flags are cleared
+static void
rb_iseq_trace_flag_cleared(const rb_iseq_t *iseq, size_t pos)
{
const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
@@ -3746,14 +3982,16 @@ add_bmethod_events(rb_event_flag_t 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)
+iseq_add_local_tracepoint(const rb_iseq_t *iseq, rb_event_flag_t turnon_events, VALUE tpval, unsigned int target_line, rb_ractor_t *r)
{
unsigned int pc;
int n = 0;
const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
VALUE *iseq_encoded = (VALUE *)body->iseq_encoded;
+ rb_iseq_t *iseq_mut = (rb_iseq_t*)iseq;
VM_ASSERT(ISEQ_EXECUTABLE_P(iseq));
+ ASSERT_vm_locking_with_barrier();
for (pc=0; pc<body->iseq_size;) {
const struct iseq_insn_info_entry *entry = get_insn_info(iseq, pc);
@@ -3775,11 +4013,9 @@ iseq_add_local_tracepoint(const rb_iseq_t *iseq, rb_event_flag_t turnon_events,
}
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);
+ rb_hook_list_t *hook_list = rb_iseq_local_hooks(iseq, r, true);
+ rb_hook_list_connect_local_tracepoint(hook_list, tpval, target_line);
+ iseq_mut->aux.exec.local_hooks_cnt++;
}
return n;
@@ -3790,19 +4026,21 @@ struct trace_set_local_events_struct {
VALUE tpval;
unsigned int target_line;
int n;
+ rb_ractor_t *r;
};
static void
iseq_add_local_tracepoint_i(const rb_iseq_t *iseq, void *p)
{
struct trace_set_local_events_struct *data = (struct trace_set_local_events_struct *)p;
- data->n += iseq_add_local_tracepoint(iseq, data->turnon_events, data->tpval, data->target_line);
+ data->n += iseq_add_local_tracepoint(iseq, data->turnon_events, data->tpval, data->target_line, data->r);
iseq_iterate_children(iseq, iseq_add_local_tracepoint_i, 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, bool target_bmethod)
{
+ ASSERT_vm_locking_with_barrier();
struct trace_set_local_events_struct data;
if (target_bmethod) {
turnon_events = add_bmethod_events(turnon_events);
@@ -3811,35 +4049,52 @@ rb_iseq_add_local_tracepoint_recursively(const rb_iseq_t *iseq, rb_event_flag_t
data.tpval = tpval;
data.target_line = target_line;
data.n = 0;
+ data.r = GET_RACTOR();
iseq_add_local_tracepoint_i(iseq, (void *)&data);
- if (0) rb_funcall(Qnil, rb_intern("puts"), 1, rb_iseq_disasm(iseq)); /* for debug */
+ if (0) fprintf(stderr, "Iseq disasm:\n:%s", RSTRING_PTR(rb_iseq_disasm(iseq))); /* for debug */
return data.n;
}
static int
-iseq_remove_local_tracepoint(const rb_iseq_t *iseq, VALUE tpval)
+iseq_remove_local_tracepoint(const rb_iseq_t *iseq, VALUE tpval, rb_ractor_t *r)
{
int n = 0;
+ unsigned int num_hooks_left;
+ unsigned int pc;
+ const struct rb_iseq_constant_body *body;
+ rb_iseq_t *iseq_mut = (rb_iseq_t*)iseq;
+ rb_hook_list_t *hook_list;
+ VALUE *iseq_encoded;
+ ASSERT_vm_locking_with_barrier();
- if (iseq->aux.exec.local_hooks) {
- unsigned int pc;
- const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
- VALUE *iseq_encoded = (VALUE *)body->iseq_encoded;
+ hook_list = rb_iseq_local_hooks(iseq, r, false);
+
+ if (hook_list) {
rb_event_flag_t local_events = 0;
- rb_hook_list_remove_tracepoint(iseq->aux.exec.local_hooks, tpval);
- local_events = iseq->aux.exec.local_hooks->events;
+ rb_event_flag_t prev_events = hook_list->events;
+ if (rb_hook_list_remove_local_tracepoint(hook_list, tpval)) {
+ RUBY_ASSERT(iseq->aux.exec.local_hooks_cnt > 0);
+ iseq_mut->aux.exec.local_hooks_cnt--;
+ local_events = hook_list->events; // remaining events for this ractor
+ num_hooks_left = rb_hook_list_count(hook_list);
+ if (local_events == 0 && prev_events != 0) {
+ st_delete(rb_ractor_targeted_hooks(r), (st_data_t*)&iseq, NULL);
+ rb_hook_list_free(hook_list);
+ }
- if (local_events == 0) {
- rb_hook_list_free(iseq->aux.exec.local_hooks);
- ((rb_iseq_t *)iseq)->aux.exec.local_hooks = NULL;
- }
+ if (iseq->aux.exec.local_hooks_cnt == num_hooks_left) {
+ body = ISEQ_BODY(iseq);
+ iseq_encoded = (VALUE *)body->iseq_encoded;
+ local_events = add_bmethod_events(local_events);
+ for (pc = 0; pc<body->iseq_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), false);
+ }
+ }
- local_events = add_bmethod_events(local_events);
- for (pc = 0; pc<body->iseq_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), false);
+ n++;
}
}
return n;
@@ -3848,22 +4103,25 @@ iseq_remove_local_tracepoint(const rb_iseq_t *iseq, VALUE tpval)
struct trace_clear_local_events_struct {
VALUE tpval;
int n;
+ rb_ractor_t *r;
};
static void
iseq_remove_local_tracepoint_i(const rb_iseq_t *iseq, void *p)
{
struct trace_clear_local_events_struct *data = (struct trace_clear_local_events_struct *)p;
- data->n += iseq_remove_local_tracepoint(iseq, data->tpval);
+ data->n += iseq_remove_local_tracepoint(iseq, data->tpval, data->r);
iseq_iterate_children(iseq, iseq_remove_local_tracepoint_i, p);
}
int
-rb_iseq_remove_local_tracepoint_recursively(const rb_iseq_t *iseq, VALUE tpval)
+rb_iseq_remove_local_tracepoint_recursively(const rb_iseq_t *iseq, VALUE tpval, rb_ractor_t *r)
{
struct trace_clear_local_events_struct data;
+ ASSERT_vm_locking_with_barrier();
data.tpval = tpval;
data.n = 0;
+ data.r = r;
iseq_remove_local_tracepoint_i(iseq, (void *)&data);
return data.n;
@@ -3881,11 +4139,14 @@ rb_iseq_trace_set(const rb_iseq_t *iseq, rb_event_flag_t turnon_events)
return;
}
else {
+ // NOTE: this does not need VM barrier if it's a new ISEQ
unsigned int pc;
const struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
+
VALUE *iseq_encoded = (VALUE *)body->iseq_encoded;
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_hook_list_t *local_hooks = rb_iseq_local_hooks(iseq, GET_RACTOR(), false);
+ rb_event_flag_t local_events = local_hooks ? local_hooks->events : 0;
((rb_iseq_t *)iseq)->aux.exec.global_trace_events = turnon_events;
enabled_events = add_bmethod_events(turnon_events | local_events);
@@ -3901,6 +4162,7 @@ void rb_vm_cc_general(const struct rb_callcache *cc);
static bool
clear_attr_cc(VALUE v)
{
+ ASSERT_vm_locking_with_barrier();
if (imemo_type_p(v, imemo_callcache) && vm_cc_ivar_p((const struct rb_callcache *)v)) {
rb_vm_cc_general((struct rb_callcache *)v);
return true;
@@ -3913,6 +4175,7 @@ clear_attr_cc(VALUE v)
static bool
clear_bf_cc(VALUE v)
{
+ ASSERT_vm_locking_with_barrier();
if (imemo_type_p(v, imemo_callcache) && vm_cc_bf_p((const struct rb_callcache *)v)) {
rb_vm_cc_general((struct rb_callcache *)v);
return true;
@@ -3927,8 +4190,8 @@ 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);
+ void *ptr = rb_asan_poisoned_object_p(v);
+ rb_asan_unpoison_object(v, false);
clear_attr_cc(v);
asan_poison_object_if(ptr, v);
}
@@ -3938,7 +4201,10 @@ clear_attr_ccs_i(void *vstart, void *vend, size_t stride, void *data)
void
rb_clear_attr_ccs(void)
{
- rb_objspace_each_objects(clear_attr_ccs_i, NULL);
+ RB_VM_LOCKING() {
+ rb_vm_barrier();
+ rb_objspace_each_objects(clear_attr_ccs_i, NULL);
+ }
}
static int
@@ -3946,8 +4212,8 @@ clear_bf_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);
+ void *ptr = rb_asan_poisoned_object_p(v);
+ rb_asan_unpoison_object(v, false);
clear_bf_cc(v);
asan_poison_object_if(ptr, v);
}
@@ -3957,6 +4223,7 @@ clear_bf_ccs_i(void *vstart, void *vend, size_t stride, void *data)
void
rb_clear_bf_ccs(void)
{
+ ASSERT_vm_locking_with_barrier();
rb_objspace_each_objects(clear_bf_ccs_i, NULL);
}
@@ -3967,8 +4234,8 @@ trace_set_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);
+ void *ptr = rb_asan_poisoned_object_p(v);
+ rb_asan_unpoison_object(v, false);
if (rb_obj_is_iseq(v)) {
rb_iseq_trace_set(rb_iseq_check((rb_iseq_t *)v), turnon_events);
@@ -3986,7 +4253,10 @@ trace_set_i(void *vstart, void *vend, size_t stride, void *data)
void
rb_iseq_trace_set_all(rb_event_flag_t turnon_events)
{
- rb_objspace_each_objects(trace_set_i, &turnon_events);
+ RB_VM_LOCKING() {
+ rb_vm_barrier();
+ rb_objspace_each_objects(trace_set_i, &turnon_events);
+ }
}
VALUE
@@ -4263,6 +4533,7 @@ Init_ISeq(void)
(void)iseq_s_load;
rb_define_singleton_method(rb_cISeq, "compile", iseqw_s_compile, -1);
+ rb_define_singleton_method(rb_cISeq, "compile_parsey", iseqw_s_compile_parsey, -1);
rb_define_singleton_method(rb_cISeq, "compile_prism", iseqw_s_compile_prism, -1);
rb_define_singleton_method(rb_cISeq, "compile_file_prism", iseqw_s_compile_file_prism, -1);
rb_define_singleton_method(rb_cISeq, "new", iseqw_s_compile, -1);
diff --git a/iseq.h b/iseq.h
index a0b59c441f..5221c8aeb4 100644
--- a/iseq.h
+++ b/iseq.h
@@ -104,6 +104,16 @@ struct iseq_compile_data {
const VALUE err_info;
const VALUE catch_table_ary; /* Array */
+ /* Mirror fields from ISEQ_BODY so they are accessible during iseq setup */
+ unsigned int iseq_size;
+ VALUE *iseq_encoded; /* half-encoded iseq (insn addr and operands) */
+ bool is_single_mark_bit; /* identifies whether mark bits are single or a list */
+
+ union {
+ iseq_bits_t * list; /* Find references for GC */
+ iseq_bits_t single;
+ } mark_bits;
+
/* GC is not needed */
struct iseq_label_data *start_label;
struct iseq_label_data *end_label;
@@ -164,7 +174,12 @@ ISEQ_COMPILE_DATA_CLEAR(rb_iseq_t *iseq)
static inline rb_iseq_t *
iseq_imemo_alloc(void)
{
- return IMEMO_NEW(rb_iseq_t, imemo_iseq, 0);
+ rb_iseq_t *iseq = SHAREABLE_IMEMO_NEW(rb_iseq_t, imemo_iseq, 0);
+
+ // Clear out the whole iseq except for the flags.
+ memset((char *)iseq + sizeof(VALUE), 0, sizeof(rb_iseq_t) - sizeof(VALUE));
+
+ return iseq;
}
VALUE rb_iseq_ibf_dump(const rb_iseq_t *iseq, VALUE opt);
@@ -174,9 +189,12 @@ 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, bool target_bmethod);
-int rb_iseq_remove_local_tracepoint_recursively(const rb_iseq_t *iseq, VALUE tpval);
+int rb_iseq_remove_local_tracepoint_recursively(const rb_iseq_t *iseq, VALUE tpval, rb_ractor_t *r);
const rb_iseq_t *rb_iseq_load_iseq(VALUE fname);
+const rb_iseq_t *rb_iseq_compile_iseq(VALUE str, VALUE fname);
int rb_iseq_opt_frozen_string_literal(void);
+rb_hook_list_t *rb_iseq_local_hooks(const rb_iseq_t *iseq, rb_ractor_t *r, bool create);
+
#if VM_INSN_INFO_TABLE_IMPL == 2
unsigned int *rb_iseq_insns_info_decode_positions(const struct rb_iseq_constant_body *body);
@@ -193,7 +211,7 @@ VALUE *rb_iseq_original_iseq(const rb_iseq_t *iseq);
void rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc,
VALUE locals, VALUE args,
VALUE exception, VALUE body);
-void rb_iseq_mark_and_pin_insn_storage(struct iseq_compile_data_storage *arena);
+void rb_iseq_mark_and_move_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);
diff --git a/jit.c b/jit.c
new file mode 100644
index 0000000000..9399cb4026
--- /dev/null
+++ b/jit.c
@@ -0,0 +1,799 @@
+// Glue code shared between YJIT and ZJIT for use from Rust.
+// For FFI safety and bindgen compatibility reasons, certain types of C
+// functions require wrapping before they can be called from Rust. Those show
+// up here.
+//
+// Code specific to YJIT and ZJIT should go to yjit.c and zjit.c respectively.
+
+#include "internal.h"
+#include "vm_core.h"
+#include "vm_callinfo.h"
+#include "builtin.h"
+#include "insns.inc"
+#include "insns_info.inc"
+#include "iseq.h"
+#include "internal/gc.h"
+#include "vm_sync.h"
+#include "internal/fixnum.h"
+#include "internal/string.h"
+
+enum jit_bindgen_constants {
+ // Field offsets for the RObject struct
+ ROBJECT_OFFSET_AS_HEAP_FIELDS = offsetof(struct RObject, as.heap.fields),
+ ROBJECT_OFFSET_AS_ARY = offsetof(struct RObject, as.ary),
+
+ // Field offsets for the RString struct
+ RUBY_OFFSET_RSTRING_LEN = offsetof(struct RString, len),
+
+ // Field offsets for rb_execution_context_t
+ RUBY_OFFSET_EC_CFP = offsetof(rb_execution_context_t, cfp),
+ RUBY_OFFSET_EC_INTERRUPT_FLAG = offsetof(rb_execution_context_t, interrupt_flag),
+ RUBY_OFFSET_EC_INTERRUPT_MASK = offsetof(rb_execution_context_t, interrupt_mask),
+ RUBY_OFFSET_EC_THREAD_PTR = offsetof(rb_execution_context_t, thread_ptr),
+ RUBY_OFFSET_EC_RACTOR_ID = offsetof(rb_execution_context_t, ractor_id),
+};
+
+// Manually bound in rust since this is out-of-range of `int`,
+// so this can't be in a `enum`, and we avoid `static const`
+// to avoid allocating storage for the constant.
+const shape_id_t rb_invalid_shape_id = INVALID_SHAPE_ID;
+
+unsigned int
+rb_iseq_encoded_size(const rb_iseq_t *iseq)
+{
+ return iseq->body->iseq_size;
+}
+
+// Get the PC for a given index in an iseq
+VALUE *
+rb_iseq_pc_at_idx(const rb_iseq_t *iseq, uint32_t insn_idx)
+{
+ RUBY_ASSERT_ALWAYS(IMEMO_TYPE_P(iseq, imemo_iseq));
+ RUBY_ASSERT_ALWAYS(insn_idx < iseq->body->iseq_size);
+ VALUE *encoded = iseq->body->iseq_encoded;
+ VALUE *pc = &encoded[insn_idx];
+ return pc;
+}
+
+// Get the opcode given a program counter. Can return trace opcode variants.
+int
+rb_iseq_opcode_at_pc(const rb_iseq_t *iseq, const VALUE *pc)
+{
+ // YJIT should only use iseqs after AST to bytecode compilation.
+ // (Certain non-default interpreter configurations never set ISEQ_TRANSLATED)
+ if (OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE) {
+ RUBY_ASSERT_ALWAYS(FL_TEST_RAW((VALUE)iseq, ISEQ_TRANSLATED));
+ }
+
+ const VALUE at_pc = *pc;
+ return rb_vm_insn_addr2opcode((const void *)at_pc);
+}
+
+unsigned long
+rb_RSTRING_LEN(VALUE str)
+{
+ return RSTRING_LEN(str);
+}
+
+char *
+rb_RSTRING_PTR(VALUE str)
+{
+ return RSTRING_PTR(str);
+}
+
+const char *
+rb_insn_name(VALUE insn)
+{
+ return insn_name(insn);
+}
+
+unsigned int
+rb_vm_ci_argc(const struct rb_callinfo *ci)
+{
+ return vm_ci_argc(ci);
+}
+
+ID
+rb_vm_ci_mid(const struct rb_callinfo *ci)
+{
+ return vm_ci_mid(ci);
+}
+
+unsigned int
+rb_vm_ci_flag(const struct rb_callinfo *ci)
+{
+ return vm_ci_flag(ci);
+}
+
+const struct rb_callinfo_kwarg *
+rb_vm_ci_kwarg(const struct rb_callinfo *ci)
+{
+ return vm_ci_kwarg(ci);
+}
+
+int
+rb_get_cikw_keyword_len(const struct rb_callinfo_kwarg *cikw)
+{
+ return cikw->keyword_len;
+}
+
+VALUE
+rb_get_cikw_keywords_idx(const struct rb_callinfo_kwarg *cikw, int idx)
+{
+ return cikw->keywords[idx];
+}
+
+rb_method_visibility_t
+rb_METHOD_ENTRY_VISI(const rb_callable_method_entry_t *me)
+{
+ return METHOD_ENTRY_VISI(me);
+}
+
+rb_method_type_t
+rb_get_cme_def_type(const rb_callable_method_entry_t *cme)
+{
+ if (UNDEFINED_METHOD_ENTRY_P(cme)) {
+ return VM_METHOD_TYPE_UNDEF;
+ }
+ else {
+ return cme->def->type;
+ }
+}
+
+ID
+rb_get_cme_def_body_attr_id(const rb_callable_method_entry_t *cme)
+{
+ return cme->def->body.attr.id;
+}
+
+enum method_optimized_type
+rb_get_cme_def_body_optimized_type(const rb_callable_method_entry_t *cme)
+{
+ return cme->def->body.optimized.type;
+}
+
+unsigned int
+rb_get_cme_def_body_optimized_index(const rb_callable_method_entry_t *cme)
+{
+ return cme->def->body.optimized.index;
+}
+
+rb_method_cfunc_t *
+rb_get_cme_def_body_cfunc(const rb_callable_method_entry_t *cme)
+{
+ return UNALIGNED_MEMBER_PTR(cme->def, body.cfunc);
+}
+
+uintptr_t
+rb_get_def_method_serial(const rb_method_definition_t *def)
+{
+ return def->method_serial;
+}
+
+ID
+rb_get_def_original_id(const rb_method_definition_t *def)
+{
+ return def->original_id;
+}
+
+VALUE
+rb_get_def_bmethod_proc(rb_method_definition_t *def)
+{
+ RUBY_ASSERT(def->type == VM_METHOD_TYPE_BMETHOD);
+ return def->body.bmethod.proc;
+}
+
+rb_proc_t *
+rb_jit_get_proc_ptr(VALUE procv)
+{
+ rb_proc_t *proc;
+ GetProcPtr(procv, proc);
+ return proc;
+}
+
+VALUE
+rb_optimized_call(VALUE *recv, rb_execution_context_t *ec, int argc, VALUE *argv, int kw_splat, VALUE block_handler)
+{
+ rb_proc_t *proc;
+ GetProcPtr(recv, proc);
+ return rb_vm_invoke_proc(ec, proc, argc, argv, kw_splat, block_handler);
+}
+
+unsigned int
+rb_jit_iseq_builtin_attrs(const rb_iseq_t *iseq)
+{
+ return iseq->body->builtin_attrs;
+}
+
+int
+rb_get_mct_argc(const rb_method_cfunc_t *mct)
+{
+ return mct->argc;
+}
+
+void *
+rb_get_mct_func(const rb_method_cfunc_t *mct)
+{
+ return (void*)(uintptr_t)mct->func; // this field is defined as type VALUE (*func)(ANYARGS)
+}
+
+const rb_iseq_t *
+rb_get_def_iseq_ptr(rb_method_definition_t *def)
+{
+ return def_iseq_ptr(def);
+}
+
+const rb_iseq_t *
+rb_get_iseq_body_local_iseq(const rb_iseq_t *iseq)
+{
+ return iseq->body->local_iseq;
+}
+
+const rb_iseq_t *
+rb_get_iseq_body_parent_iseq(const rb_iseq_t *iseq)
+{
+ return iseq->body->parent_iseq;
+}
+
+unsigned int
+rb_get_iseq_body_local_table_size(const rb_iseq_t *iseq)
+{
+ return iseq->body->local_table_size;
+}
+
+VALUE *
+rb_get_iseq_body_iseq_encoded(const rb_iseq_t *iseq)
+{
+ return iseq->body->iseq_encoded;
+}
+
+unsigned
+rb_get_iseq_body_stack_max(const rb_iseq_t *iseq)
+{
+ return iseq->body->stack_max;
+}
+
+enum rb_iseq_type
+rb_get_iseq_body_type(const rb_iseq_t *iseq)
+{
+ return iseq->body->type;
+}
+
+bool
+rb_get_iseq_flags_has_lead(const rb_iseq_t *iseq)
+{
+ return iseq->body->param.flags.has_lead;
+}
+
+bool
+rb_get_iseq_flags_has_opt(const rb_iseq_t *iseq)
+{
+ return iseq->body->param.flags.has_opt;
+}
+
+bool
+rb_get_iseq_flags_has_kw(const rb_iseq_t *iseq)
+{
+ return iseq->body->param.flags.has_kw;
+}
+
+bool
+rb_get_iseq_flags_has_post(const rb_iseq_t *iseq)
+{
+ return iseq->body->param.flags.has_post;
+}
+
+bool
+rb_get_iseq_flags_has_kwrest(const rb_iseq_t *iseq)
+{
+ return iseq->body->param.flags.has_kwrest;
+}
+
+bool
+rb_get_iseq_flags_anon_kwrest(const rb_iseq_t *iseq)
+{
+ return iseq->body->param.flags.anon_kwrest;
+}
+
+bool
+rb_get_iseq_flags_has_rest(const rb_iseq_t *iseq)
+{
+ return iseq->body->param.flags.has_rest;
+}
+
+bool
+rb_get_iseq_flags_ruby2_keywords(const rb_iseq_t *iseq)
+{
+ return iseq->body->param.flags.ruby2_keywords;
+}
+
+bool
+rb_get_iseq_flags_has_block(const rb_iseq_t *iseq)
+{
+ return iseq->body->param.flags.has_block;
+}
+
+bool
+rb_get_iseq_flags_ambiguous_param0(const rb_iseq_t *iseq)
+{
+ return iseq->body->param.flags.ambiguous_param0;
+}
+
+bool
+rb_get_iseq_flags_accepts_no_kwarg(const rb_iseq_t *iseq)
+{
+ return iseq->body->param.flags.accepts_no_kwarg;
+}
+
+bool
+rb_get_iseq_flags_forwardable(const rb_iseq_t *iseq)
+{
+ return iseq->body->param.flags.forwardable;
+}
+
+// This is defined only as a named struct inside rb_iseq_constant_body.
+// By giving it a separate typedef, we make it nameable by rust-bindgen.
+// Bindgen's temp/anon name isn't guaranteed stable.
+typedef struct rb_iseq_param_keyword rb_iseq_param_keyword_struct;
+
+const rb_iseq_param_keyword_struct *
+rb_get_iseq_body_param_keyword(const rb_iseq_t *iseq)
+{
+ return iseq->body->param.keyword;
+}
+
+unsigned
+rb_get_iseq_body_param_size(const rb_iseq_t *iseq)
+{
+ return iseq->body->param.size;
+}
+
+int
+rb_get_iseq_body_param_lead_num(const rb_iseq_t *iseq)
+{
+ return iseq->body->param.lead_num;
+}
+
+int
+rb_get_iseq_body_param_opt_num(const rb_iseq_t *iseq)
+{
+ return iseq->body->param.opt_num;
+}
+
+const VALUE *
+rb_get_iseq_body_param_opt_table(const rb_iseq_t *iseq)
+{
+ return iseq->body->param.opt_table;
+}
+
+struct rb_control_frame_struct *
+rb_get_ec_cfp(const rb_execution_context_t *ec)
+{
+ return ec->cfp;
+}
+
+const rb_iseq_t *
+rb_get_cfp_iseq(struct rb_control_frame_struct *cfp)
+{
+ return cfp->iseq;
+}
+
+VALUE *
+rb_get_cfp_pc(struct rb_control_frame_struct *cfp)
+{
+ return (VALUE*)cfp->pc;
+}
+
+VALUE *
+rb_get_cfp_sp(struct rb_control_frame_struct *cfp)
+{
+ return cfp->sp;
+}
+
+VALUE
+rb_get_cfp_self(struct rb_control_frame_struct *cfp)
+{
+ return cfp->self;
+}
+
+VALUE *
+rb_get_cfp_ep(struct rb_control_frame_struct *cfp)
+{
+ return (VALUE*)cfp->ep;
+}
+
+const VALUE *
+rb_get_cfp_ep_level(struct rb_control_frame_struct *cfp, uint32_t lv)
+{
+ uint32_t i;
+ const VALUE *ep = (VALUE*)cfp->ep;
+ for (i = 0; i < lv; i++) {
+ ep = VM_ENV_PREV_EP(ep);
+ }
+ return ep;
+}
+
+VALUE
+rb_yarv_class_of(VALUE obj)
+{
+ return rb_class_of(obj);
+}
+
+// The FL_TEST() macro
+VALUE
+rb_FL_TEST(VALUE obj, VALUE flags)
+{
+ return RB_FL_TEST(obj, flags);
+}
+
+// The FL_TEST_RAW() macro, normally an internal implementation detail
+VALUE
+rb_FL_TEST_RAW(VALUE obj, VALUE flags)
+{
+ return FL_TEST_RAW(obj, flags);
+}
+
+// The RB_TYPE_P macro
+bool
+rb_RB_TYPE_P(VALUE obj, enum ruby_value_type t)
+{
+ return RB_TYPE_P(obj, t);
+}
+
+long
+rb_RSTRUCT_LEN(VALUE st)
+{
+ return RSTRUCT_LEN(st);
+}
+
+const struct rb_callinfo *
+rb_get_call_data_ci(const struct rb_call_data *cd)
+{
+ return cd->ci;
+}
+
+bool
+rb_BASIC_OP_UNREDEFINED_P(enum ruby_basic_operators bop, uint32_t klass)
+{
+ return BASIC_OP_UNREDEFINED_P(bop, klass);
+}
+
+VALUE
+rb_RCLASS_ORIGIN(VALUE c)
+{
+ return RCLASS_ORIGIN(c);
+}
+
+// For debug builds
+void
+rb_assert_iseq_handle(VALUE handle)
+{
+ RUBY_ASSERT_ALWAYS(IMEMO_TYPE_P(handle, imemo_iseq));
+}
+
+// Assert that we have the VM lock. Relevant mostly for multi ractor situations.
+// The GC takes the lock before calling us, and this asserts that it indeed happens.
+void
+rb_assert_holding_vm_lock(void)
+{
+ ASSERT_vm_locking();
+}
+
+int
+rb_IMEMO_TYPE_P(VALUE imemo, enum imemo_type imemo_type)
+{
+ return IMEMO_TYPE_P(imemo, imemo_type);
+}
+
+void
+rb_assert_cme_handle(VALUE handle)
+{
+ RUBY_ASSERT_ALWAYS(!rb_objspace_garbage_object_p(handle));
+ RUBY_ASSERT_ALWAYS(IMEMO_TYPE_P(handle, imemo_ment));
+}
+
+// YJIT and ZJIT need this function to never allocate and never raise
+VALUE
+rb_yarv_ary_entry_internal(VALUE ary, long offset)
+{
+ return rb_ary_entry_internal(ary, offset);
+}
+
+long
+rb_jit_array_len(VALUE a)
+{
+ return rb_array_len(a);
+}
+
+void
+rb_set_cfp_pc(struct rb_control_frame_struct *cfp, const VALUE *pc)
+{
+ cfp->pc = pc;
+}
+
+void
+rb_set_cfp_sp(struct rb_control_frame_struct *cfp, VALUE *sp)
+{
+ cfp->sp = sp;
+}
+
+bool
+rb_jit_shape_too_complex_p(shape_id_t shape_id)
+{
+ return rb_shape_too_complex_p(shape_id);
+}
+
+bool
+rb_jit_multi_ractor_p(void)
+{
+ return rb_multi_ractor_p();
+}
+
+// Acquire the VM lock and then signal all other Ruby threads (ractors) to
+// contend for the VM lock, putting them to sleep. ZJIT and YJIT use this to
+// evict threads running inside generated code so among other things, it can
+// safely change memory protection of regions housing generated code.
+void
+rb_jit_vm_lock_then_barrier(unsigned int *recursive_lock_level, const char *file, int line)
+{
+ rb_vm_lock_enter(recursive_lock_level, file, line);
+ rb_vm_barrier();
+}
+
+// Release the VM lock. The lock level must point to the same integer used to
+// acquire the lock.
+void
+rb_jit_vm_unlock(unsigned int *recursive_lock_level, const char *file, int line)
+{
+ rb_vm_lock_leave(recursive_lock_level, file, line);
+}
+
+void
+rb_iseq_reset_jit_func(const rb_iseq_t *iseq)
+{
+ RUBY_ASSERT_ALWAYS(IMEMO_TYPE_P(iseq, imemo_iseq));
+ iseq->body->jit_entry = NULL;
+ iseq->body->jit_exception = NULL;
+ // Enable re-compiling this ISEQ. Event when it's invalidated for TracePoint,
+ // we'd like to re-compile ISEQs that haven't been converted to trace_* insns.
+ iseq->body->jit_entry_calls = 0;
+ iseq->body->jit_exception_calls = 0;
+}
+
+// Callback data for rb_jit_for_each_iseq
+struct iseq_callback_data {
+ rb_iseq_callback callback;
+ void *data;
+};
+
+// Heap-walking callback for rb_jit_for_each_iseq
+static int
+for_each_iseq_i(void *vstart, void *vend, size_t stride, void *data)
+{
+ const struct iseq_callback_data *callback_data = (struct iseq_callback_data *)data;
+ VALUE v = (VALUE)vstart;
+ for (; v != (VALUE)vend; v += stride) {
+ void *ptr = rb_asan_poisoned_object_p(v);
+ rb_asan_unpoison_object(v, false);
+
+ if (rb_obj_is_iseq(v)) {
+ rb_iseq_t *iseq = (rb_iseq_t *)v;
+ callback_data->callback(iseq, callback_data->data);
+ }
+
+ if (ptr) {
+ rb_asan_poison_object(v);
+ }
+ }
+ return 0;
+}
+
+uint32_t
+rb_jit_get_page_size(void)
+{
+#if defined(_SC_PAGESIZE)
+ long page_size = sysconf(_SC_PAGESIZE);
+ if (page_size <= 0) rb_bug("jit: failed to get page size");
+
+ // 1 GiB limit. x86 CPUs with PDPE1GB can do this and anything larger is unexpected.
+ // Though our design sort of assume we have fine grained control over memory protection
+ // which require small page sizes.
+ if (page_size > 0x40000000l) rb_bug("jit page size too large");
+
+ return (uint32_t)page_size;
+#else
+#error "JIT supports POSIX only for now"
+#endif
+}
+
+#if defined(MAP_FIXED_NOREPLACE) && defined(_SC_PAGESIZE)
+// 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;
+}
+#endif
+
+// Address space reservation. Memory pages are mapped on an as needed basis.
+// See the Rust mm module for details.
+uint8_t *
+rb_jit_reserve_addr_space(uint32_t mem_size)
+{
+#ifndef _WIN32
+ uint8_t *mem_block;
+
+ // On Linux
+ #if defined(MAP_FIXED_NOREPLACE) && defined(_SC_PAGESIZE)
+ uint32_t const page_size = (uint32_t)sysconf(_SC_PAGESIZE);
+ uint8_t *const cfunc_sample_addr = (void *)(uintptr_t)&rb_jit_reserve_addr_space;
+ uint8_t *const probe_region_end = cfunc_sample_addr + INT32_MAX;
+ // Align the requested address to page size
+ uint8_t *req_addr = align_ptr(cfunc_sample_addr, page_size);
+
+ // Probe for addresses close to this function using MAP_FIXED_NOREPLACE
+ // to improve odds of being in range for 32-bit relative call instructions.
+ do {
+ mem_block = mmap(
+ req_addr,
+ mem_size,
+ PROT_NONE,
+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED_NOREPLACE,
+ -1,
+ 0
+ );
+
+ // If we succeeded, stop
+ if (mem_block != MAP_FAILED) {
+ ruby_annotate_mmap(mem_block, mem_size, "Ruby:rb_jit_reserve_addr_space");
+ break;
+ }
+
+ // -4MiB. Downwards to probe away from the heap. (On x86/A64 Linux
+ // main_code_addr < heap_addr, and in case we are in a shared
+ // library mapped higher than the heap, downwards is still better
+ // since it's towards the end of the heap rather than the stack.)
+ req_addr -= 4 * 1024 * 1024;
+ } while (req_addr < probe_region_end);
+
+ // On MacOS and other platforms
+ #else
+ // Try to map a chunk of memory as executable
+ mem_block = mmap(
+ (void *)rb_jit_reserve_addr_space,
+ mem_size,
+ PROT_NONE,
+ MAP_PRIVATE | MAP_ANONYMOUS,
+ -1,
+ 0
+ );
+ #endif
+
+ // Fallback
+ if (mem_block == MAP_FAILED) {
+ // Try again without the address hint (e.g., valgrind)
+ mem_block = mmap(
+ NULL,
+ mem_size,
+ PROT_NONE,
+ MAP_PRIVATE | MAP_ANONYMOUS,
+ -1,
+ 0
+ );
+
+ if (mem_block != MAP_FAILED) {
+ ruby_annotate_mmap(mem_block, mem_size, "Ruby:rb_jit_reserve_addr_space:fallback");
+ }
+ }
+
+ // Check that the memory mapping was successful
+ if (mem_block == MAP_FAILED) {
+ perror("ruby: jit: mmap:");
+ if(errno == ENOMEM) {
+ // No crash report if it's only insufficient memory
+ exit(EXIT_FAILURE);
+ }
+ rb_bug("mmap failed");
+ }
+
+ return mem_block;
+#else
+ // Windows not supported for now
+ return NULL;
+#endif
+}
+
+// Walk all ISEQs in the heap and invoke the callback - shared between YJIT and ZJIT
+void
+rb_jit_for_each_iseq(rb_iseq_callback callback, void *data)
+{
+ struct iseq_callback_data callback_data = { .callback = callback, .data = data };
+ rb_objspace_each_objects(for_each_iseq_i, (void *)&callback_data);
+}
+
+bool
+rb_jit_mark_writable(void *mem_block, uint32_t mem_size)
+{
+ return mprotect(mem_block, mem_size, PROT_READ | PROT_WRITE) == 0;
+}
+
+void
+rb_jit_mark_executable(void *mem_block, uint32_t mem_size)
+{
+ // Do not call mprotect when mem_size is zero. Some platforms may return
+ // an error for it. https://github.com/Shopify/ruby/issues/450
+ if (mem_size == 0) {
+ return;
+ }
+ if (mprotect(mem_block, mem_size, PROT_READ | PROT_EXEC)) {
+ rb_bug("Couldn't make JIT page (%p, %lu bytes) executable, errno: %s",
+ mem_block, (unsigned long)mem_size, strerror(errno));
+ }
+}
+
+// Free the specified memory block.
+bool
+rb_jit_mark_unused(void *mem_block, uint32_t mem_size)
+{
+ // On Linux, you need to use madvise MADV_DONTNEED to free memory.
+ // We might not need to call this on macOS, but it's not really documented.
+ // We generally prefer to do the same thing on both to ease testing too.
+ madvise(mem_block, mem_size, MADV_DONTNEED);
+
+ // On macOS, mprotect PROT_NONE seems to reduce RSS.
+ // We also call this on Linux to avoid executing unused pages.
+ return mprotect(mem_block, mem_size, PROT_NONE) == 0;
+}
+
+// Invalidate icache for arm64.
+// `start` is inclusive and `end` is exclusive.
+void
+rb_jit_icache_invalidate(void *start, void *end)
+{
+ // Clear/invalidate the instruction cache. Compiles to nothing on x86_64
+ // but required on ARM before running freshly written code.
+ // On Darwin it's the same as calling sys_icache_invalidate().
+#ifdef __GNUC__
+ __builtin___clear_cache(start, end);
+#elif defined(__aarch64__)
+#error No instruction cache clear available with this compiler on Aarch64!
+#endif
+}
+
+VALUE
+rb_jit_fix_mod_fix(VALUE recv, VALUE obj)
+{
+ return rb_fix_mod_fix(recv, obj);
+}
+
+VALUE
+rb_jit_fix_div_fix(VALUE recv, VALUE obj)
+{
+ return rb_fix_div_fix(recv, obj);
+}
+
+// YJIT/ZJIT need this function to never allocate and never raise
+VALUE
+rb_yarv_str_eql_internal(VALUE str1, VALUE str2)
+{
+ // We wrap this since it's static inline
+ return rb_str_eql_internal(str1, str2);
+}
+
+void rb_jit_str_concat_codepoint(VALUE str, VALUE codepoint);
+
+attr_index_t
+rb_jit_shape_capacity(shape_id_t shape_id)
+{
+ return RSHAPE_CAPACITY(shape_id);
+}
diff --git a/jit/Cargo.toml b/jit/Cargo.toml
new file mode 100644
index 0000000000..530fe3674b
--- /dev/null
+++ b/jit/Cargo.toml
@@ -0,0 +1,6 @@
+[package]
+name = "jit"
+version = "0.1.0"
+edition = "2024"
+
+[dependencies]
diff --git a/jit/src/lib.rs b/jit/src/lib.rs
new file mode 100644
index 0000000000..c0f043131e
--- /dev/null
+++ b/jit/src/lib.rs
@@ -0,0 +1,38 @@
+//! Shared code between YJIT and ZJIT.
+#![warn(unsafe_op_in_unsafe_fn)] // Adopt 2024 edition default when targeting 2021 editions
+
+use std::sync::atomic::{AtomicUsize, Ordering};
+use std::alloc::{GlobalAlloc, Layout, System};
+
+#[global_allocator]
+pub static GLOBAL_ALLOCATOR: StatsAlloc = StatsAlloc { alloc_size: AtomicUsize::new(0) };
+
+pub struct StatsAlloc {
+ pub alloc_size: AtomicUsize,
+}
+
+unsafe impl GlobalAlloc for StatsAlloc {
+ unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
+ self.alloc_size.fetch_add(layout.size(), Ordering::SeqCst);
+ unsafe { System.alloc(layout) }
+ }
+
+ unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
+ self.alloc_size.fetch_sub(layout.size(), Ordering::SeqCst);
+ unsafe { System.dealloc(ptr, layout) }
+ }
+
+ unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
+ self.alloc_size.fetch_add(layout.size(), Ordering::SeqCst);
+ unsafe { System.alloc_zeroed(layout) }
+ }
+
+ unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
+ if new_size > layout.size() {
+ self.alloc_size.fetch_add(new_size - layout.size(), Ordering::SeqCst);
+ } else if new_size < layout.size() {
+ self.alloc_size.fetch_sub(layout.size() - new_size, Ordering::SeqCst);
+ }
+ unsafe { System.realloc(ptr, layout, new_size) }
+ }
+}
diff --git a/jit_hook.rb b/jit_hook.rb
new file mode 100644
index 0000000000..346b716948
--- /dev/null
+++ b/jit_hook.rb
@@ -0,0 +1,12 @@
+class Module
+ # Internal helper for built-in initializations to define methods only when JIT is enabled.
+ # This method is removed in jit_undef.rb.
+ private def with_jit(&block) # :nodoc:
+ # ZJIT currently doesn't compile Array#each properly, so it's disabled for now.
+ if defined?(RubyVM::ZJIT) && false # TODO: remove `&& false` (Shopify/ruby#667)
+ RubyVM::ZJIT.send(:add_jit_hook, block)
+ elsif defined?(RubyVM::YJIT)
+ RubyVM::YJIT.send(:add_jit_hook, block)
+ end
+ end
+end
diff --git a/jit_undef.rb b/jit_undef.rb
new file mode 100644
index 0000000000..0e855fe7a2
--- /dev/null
+++ b/jit_undef.rb
@@ -0,0 +1,4 @@
+# Remove the helper defined in jit_hook.rb
+class Module
+ undef :with_jit
+end
diff --git a/kernel.rb b/kernel.rb
index 541d0cfd9d..dc5cea1515 100644
--- a/kernel.rb
+++ b/kernel.rb
@@ -17,7 +17,7 @@ module Kernel
#
def class
Primitive.attr! :leaf
- Primitive.cexpr! 'rb_obj_class(self)'
+ Primitive.cexpr! 'rb_obj_class_must(self)'
end
#
@@ -40,7 +40,7 @@ module Kernel
# s1.inspect #=> "#<Klass:0x401b3a38 @str=\"Hi\">"
# s2.inspect #=> "#<Klass:0x401b3998 @str=\"Hi\">"
#
- # This method may have class-specific behavior. If so, that
+ # This method may have class-specific behavior. If so, that
# behavior will be documented under the #+initialize_copy+ method of
# the class.
#
@@ -73,7 +73,7 @@ module Kernel
# call-seq:
# obj.tap {|x| block } -> obj
#
- # Yields self to the block, and then returns self.
+ # 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.
#
@@ -100,33 +100,24 @@ module Kernel
#
# 3.next.then {|x| x**x }.to_s #=> "256"
#
- # Good usage for +then+ is value piping in method chains:
+ # A good use of +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) }
+ # construct_url(arguments)
+ # .then {|url| URI(url).read }
+ # .then {|response| JSON.parse(response) }
#
- # When called without block, the method returns +Enumerator+,
+ # When called without a block, the method returns an +Enumerator+,
# which can be used, for example, for conditional
# circuit-breaking:
#
- # # meets condition, no-op
+ # # Meets condition, no-op
# 1.then.detect(&:odd?) # => 1
- # # does not meet condition, drop value
+ # # Does not meet condition, drop value
# 2.then.detect(&:odd?) # => nil
#
- # 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 then
Primitive.attr! :inline_block
unless defined?(yield)
@@ -135,21 +126,7 @@ module Kernel
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"
- #
- def yield_self
- Primitive.attr! :inline_block
- unless defined?(yield)
- return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, rb_obj_size)'
- end
- yield(self)
- end
+ alias yield_self then
module_function
@@ -164,11 +141,12 @@ module Kernel
# loop do
# print "Input: "
# line = gets
+ # # break if q, Q is entered or EOF signal (Ctrl-D on Unix, Ctrl-Z on windows) is sent
# break if !line or line =~ /^q/i
# # ...
# end
#
- # StopIteration raised in the block breaks the loop. In this case,
+ # A StopIteration raised in the block breaks the loop. In this case,
# loop returns the "result" value stored in the exception.
#
# enum = Enumerator.new { |y|
@@ -201,10 +179,10 @@ module Kernel
#
# Returns <i>arg</i> converted to a float. Numeric types are
# converted directly, and with exception to String and
- # <code>nil</code> the rest are converted using
- # <i>arg</i><code>.to_f</code>. Converting a String with invalid
- # characters will result in a ArgumentError. Converting
- # <code>nil</code> generates a TypeError. Exceptions can be
+ # <code>nil</code>, the rest are converted using
+ # <i>arg</i><code>.to_f</code>. Converting a String with invalid
+ # characters will result in an ArgumentError. Converting
+ # <code>nil</code> generates a TypeError. Exceptions can be
# suppressed by passing <code>exception: false</code>.
#
# Float(1) #=> 1.0
@@ -233,22 +211,22 @@ module Kernel
# With a non-zero +base+, +object+ must be a string or convertible
# to a string.
#
- # ==== numeric objects
+ # ==== \Numeric objects
#
- # With integer argument +object+ given, returns +object+:
+ # With an integer argument +object+ given, returns +object+:
#
# Integer(1) # => 1
# Integer(-1) # => -1
#
- # With floating-point argument +object+ given,
+ # With a floating-point argument +object+ given,
# returns +object+ truncated to an integer:
#
# Integer(1.9) # => 1 # Rounds toward zero.
# Integer(-1.9) # => -1 # Rounds toward zero.
#
- # ==== string objects
+ # ==== \String objects
#
- # With string argument +object+ and zero +base+ given,
+ # With a string argument +object+ and zero +base+ given,
# returns +object+ converted to an integer in base 10:
#
# Integer('100') # => 100
@@ -258,7 +236,7 @@ module Kernel
# to specify the actual base (radix indicator):
#
# Integer('0100') # => 64 # Leading '0' specifies base 8.
- # Integer('0b100') # => 4 # Leading '0b', specifies base 2.
+ # Integer('0b100') # => 4 # Leading '0b' specifies base 2.
# Integer('0x100') # => 256 # Leading '0x' specifies base 16.
#
# With a positive +base+ (in range 2..36) given, returns +object+
@@ -269,8 +247,8 @@ module Kernel
# Integer('-100', 16) # => -256
#
# With a negative +base+ (in range -36..-2) given, returns +object+
- # converted to an integer in the radix indicator if exists or
- # +-base+:
+ # converted to the radix indicator if it exists or
+ # +base+:
#
# Integer('0x100', -2) # => 256
# Integer('100', -2) # => 4
@@ -279,7 +257,7 @@ module Kernel
# Integer('0o100', -10) # => 64
# Integer('100', -10) # => 100
#
- # +base+ -1 is equal the -10 case.
+ # +base+ -1 is equivalent to the -10 case.
#
# When converting strings, surrounding whitespace and embedded underscores
# are allowed and ignored:
@@ -287,7 +265,7 @@ module Kernel
# Integer(' 100 ') # => 100
# Integer('-1_0_0', 16) # => -256
#
- # ==== other classes
+ # ==== Other classes
#
# Examples with +object+ of various other classes:
#
@@ -295,22 +273,22 @@ module Kernel
# Integer(Complex(2, 0)) # => 2 # Imaginary part must be zero.
# Integer(Time.now) # => 1650974042
#
- # ==== keywords
+ # ==== Keywords
#
- # With optional keyword argument +exception+ given as +true+ (the default):
+ # With the optional keyword argument +exception+ given as +true+ (the default):
#
# - Raises TypeError if +object+ does not respond to +to_int+ or +to_i+.
# - Raises TypeError if +object+ is +nil+.
- # - Raise ArgumentError if +object+ is an invalid string.
+ # - Raises ArgumentError if +object+ is an invalid string.
#
# With +exception+ given as +false+, an exception of any kind is suppressed
# and +nil+ is returned.
-
+ #
def Integer(arg, base = 0, exception: true)
if Primitive.mandatory_only?
Primitive.rb_f_integer1(arg)
else
- Primitive.rb_f_integer(arg, base, exception);
+ Primitive.rb_f_integer(arg, base, exception)
end
end
end
diff --git a/lex.c.blt b/lex.c.blt
index 85727ed00f..de0719b014 100644
--- a/lex.c.blt
+++ b/lex.c.blt
@@ -1,5 +1,5 @@
/* ANSI-C code produced by gperf version 3.1 */
-/* Command-line: gperf -C -P -p -j1 -i 1 -g -o -t -N rb_reserved_word -k'1,3,$' defs/keywords */
+/* Command-line: gperf -C -L ANSI-C -P -p -j1 -i 1 -g -o -t -N rb_reserved_word -k'1,3,$' defs/keywords */
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
&& ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
@@ -28,7 +28,6 @@
#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gperf@gnu.org>."
#endif
-#define gperf_offsetof(s, n) (short)offsetof(struct s##_t, s##_str##n)
#line 1 "defs/keywords"
struct kwtable {short name, id[2], state;};
@@ -196,88 +195,88 @@ rb_reserved_word (register const char *str, register size_t len)
{
{-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1},
#line 19 "defs/keywords"
- {gperf_offsetof(stringpool, 8), {keyword_break, keyword_break}, EXPR_MID},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str8, {keyword_break, keyword_break}, EXPR_MID},
#line 25 "defs/keywords"
- {gperf_offsetof(stringpool, 9), {keyword_else, keyword_else}, EXPR_BEG},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str9, {keyword_else, keyword_else}, EXPR_BEG},
#line 35 "defs/keywords"
- {gperf_offsetof(stringpool, 10), {keyword_nil, keyword_nil}, EXPR_END},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str10, {keyword_nil, keyword_nil}, EXPR_END},
#line 28 "defs/keywords"
- {gperf_offsetof(stringpool, 11), {keyword_ensure, keyword_ensure}, EXPR_BEG},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str11, {keyword_ensure, keyword_ensure}, EXPR_BEG},
#line 27 "defs/keywords"
- {gperf_offsetof(stringpool, 12), {keyword_end, keyword_end}, EXPR_END},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str12, {keyword_end, keyword_end}, EXPR_END},
#line 44 "defs/keywords"
- {gperf_offsetof(stringpool, 13), {keyword_then, keyword_then}, EXPR_BEG},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str13, {keyword_then, keyword_then}, EXPR_BEG},
#line 36 "defs/keywords"
- {gperf_offsetof(stringpool, 14), {keyword_not, keyword_not}, EXPR_ARG},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str14, {keyword_not, keyword_not}, EXPR_ARG},
#line 29 "defs/keywords"
- {gperf_offsetof(stringpool, 15), {keyword_false, keyword_false}, EXPR_END},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str15, {keyword_false, keyword_false}, EXPR_END},
#line 42 "defs/keywords"
- {gperf_offsetof(stringpool, 16), {keyword_self, keyword_self}, EXPR_END},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str16, {keyword_self, keyword_self}, EXPR_END},
#line 26 "defs/keywords"
- {gperf_offsetof(stringpool, 17), {keyword_elsif, keyword_elsif}, EXPR_VALUE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str17, {keyword_elsif, keyword_elsif}, EXPR_VALUE},
#line 39 "defs/keywords"
- {gperf_offsetof(stringpool, 18), {keyword_rescue, modifier_rescue}, EXPR_MID},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str18, {keyword_rescue, modifier_rescue}, EXPR_MID},
#line 45 "defs/keywords"
- {gperf_offsetof(stringpool, 19), {keyword_true, keyword_true}, EXPR_END},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str19, {keyword_true, keyword_true}, EXPR_END},
#line 48 "defs/keywords"
- {gperf_offsetof(stringpool, 20), {keyword_until, modifier_until}, EXPR_VALUE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str20, {keyword_until, modifier_until}, EXPR_VALUE},
#line 47 "defs/keywords"
- {gperf_offsetof(stringpool, 21), {keyword_unless, modifier_unless}, EXPR_VALUE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str21, {keyword_unless, modifier_unless}, EXPR_VALUE},
#line 41 "defs/keywords"
- {gperf_offsetof(stringpool, 22), {keyword_return, keyword_return}, EXPR_MID},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str22, {keyword_return, keyword_return}, EXPR_MID},
#line 22 "defs/keywords"
- {gperf_offsetof(stringpool, 23), {keyword_def, keyword_def}, EXPR_FNAME},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str23, {keyword_def, keyword_def}, EXPR_FNAME},
#line 17 "defs/keywords"
- {gperf_offsetof(stringpool, 24), {keyword_and, keyword_and}, EXPR_VALUE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str24, {keyword_and, keyword_and}, EXPR_VALUE},
#line 24 "defs/keywords"
- {gperf_offsetof(stringpool, 25), {keyword_do, keyword_do}, EXPR_BEG},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str25, {keyword_do, keyword_do}, EXPR_BEG},
#line 51 "defs/keywords"
- {gperf_offsetof(stringpool, 26), {keyword_yield, keyword_yield}, EXPR_ARG},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str26, {keyword_yield, keyword_yield}, EXPR_ARG},
#line 30 "defs/keywords"
- {gperf_offsetof(stringpool, 27), {keyword_for, keyword_for}, EXPR_VALUE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str27, {keyword_for, keyword_for}, EXPR_VALUE},
#line 46 "defs/keywords"
- {gperf_offsetof(stringpool, 28), {keyword_undef, keyword_undef}, EXPR_FNAME|EXPR_FITEM},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str28, {keyword_undef, keyword_undef}, EXPR_FNAME|EXPR_FITEM},
#line 37 "defs/keywords"
- {gperf_offsetof(stringpool, 29), {keyword_or, keyword_or}, EXPR_VALUE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str29, {keyword_or, keyword_or}, EXPR_VALUE},
#line 32 "defs/keywords"
- {gperf_offsetof(stringpool, 30), {keyword_in, keyword_in}, EXPR_VALUE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str30, {keyword_in, keyword_in}, EXPR_VALUE},
#line 49 "defs/keywords"
- {gperf_offsetof(stringpool, 31), {keyword_when, keyword_when}, EXPR_VALUE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str31, {keyword_when, keyword_when}, EXPR_VALUE},
#line 40 "defs/keywords"
- {gperf_offsetof(stringpool, 32), {keyword_retry, keyword_retry}, EXPR_END},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str32, {keyword_retry, keyword_retry}, EXPR_END},
#line 31 "defs/keywords"
- {gperf_offsetof(stringpool, 33), {keyword_if, modifier_if}, EXPR_VALUE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str33, {keyword_if, modifier_if}, EXPR_VALUE},
#line 20 "defs/keywords"
- {gperf_offsetof(stringpool, 34), {keyword_case, keyword_case}, EXPR_VALUE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str34, {keyword_case, keyword_case}, EXPR_VALUE},
#line 38 "defs/keywords"
- {gperf_offsetof(stringpool, 35), {keyword_redo, keyword_redo}, EXPR_END},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str35, {keyword_redo, keyword_redo}, EXPR_END},
#line 34 "defs/keywords"
- {gperf_offsetof(stringpool, 36), {keyword_next, keyword_next}, EXPR_MID},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str36, {keyword_next, keyword_next}, EXPR_MID},
#line 43 "defs/keywords"
- {gperf_offsetof(stringpool, 37), {keyword_super, keyword_super}, EXPR_ARG},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str37, {keyword_super, keyword_super}, EXPR_ARG},
#line 33 "defs/keywords"
- {gperf_offsetof(stringpool, 38), {keyword_module, keyword_module}, EXPR_VALUE},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str38, {keyword_module, keyword_module}, EXPR_VALUE},
#line 18 "defs/keywords"
- {gperf_offsetof(stringpool, 39), {keyword_begin, keyword_begin}, EXPR_BEG},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str39, {keyword_begin, keyword_begin}, EXPR_BEG},
#line 12 "defs/keywords"
- {gperf_offsetof(stringpool, 40), {keyword__LINE__, keyword__LINE__}, EXPR_END},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str40, {keyword__LINE__, keyword__LINE__}, EXPR_END},
#line 13 "defs/keywords"
- {gperf_offsetof(stringpool, 41), {keyword__FILE__, keyword__FILE__}, EXPR_END},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str41, {keyword__FILE__, keyword__FILE__}, EXPR_END},
#line 11 "defs/keywords"
- {gperf_offsetof(stringpool, 42), {keyword__ENCODING__, keyword__ENCODING__}, EXPR_END},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str42, {keyword__ENCODING__, keyword__ENCODING__}, EXPR_END},
#line 15 "defs/keywords"
- {gperf_offsetof(stringpool, 43), {keyword_END, keyword_END}, EXPR_END},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str43, {keyword_END, keyword_END}, EXPR_END},
#line 16 "defs/keywords"
- {gperf_offsetof(stringpool, 44), {keyword_alias, keyword_alias}, EXPR_FNAME|EXPR_FITEM},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str44, {keyword_alias, keyword_alias}, EXPR_FNAME|EXPR_FITEM},
#line 14 "defs/keywords"
- {gperf_offsetof(stringpool, 45), {keyword_BEGIN, keyword_BEGIN}, EXPR_END},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str45, {keyword_BEGIN, keyword_BEGIN}, EXPR_END},
#line 23 "defs/keywords"
- {gperf_offsetof(stringpool, 46), {keyword_defined, keyword_defined}, EXPR_ARG},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str46, {keyword_defined, keyword_defined}, EXPR_ARG},
#line 21 "defs/keywords"
- {gperf_offsetof(stringpool, 47), {keyword_class, keyword_class}, EXPR_CLASS},
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str47, {keyword_class, keyword_class}, EXPR_CLASS},
{-1}, {-1},
#line 50 "defs/keywords"
- {gperf_offsetof(stringpool, 50), {keyword_while, modifier_while}, EXPR_VALUE}
+ {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str50, {keyword_while, modifier_while}, EXPR_VALUE}
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
diff --git a/lib/English.gemspec b/lib/English.gemspec
index 5f4eb420c2..9c09555ca1 100644
--- a/lib/English.gemspec
+++ b/lib/English.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "english"
- spec.version = "0.8.0"
+ spec.version = "0.8.1"
spec.authors = ["Yukihiro Matsumoto"]
spec.email = ["matz@ruby-lang.org"]
@@ -15,8 +15,13 @@ 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 2>#{IO::NULL}`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ excludes = %W[
+ :^/test :^/spec :^/feature :^/bin
+ :^/Rakefile :^/Gemfile\* :^/.git*
+ :^/#{File.basename(__FILE__)}
+ ]
+ spec.files = IO.popen(%W[git ls-files -z --] + excludes, err: IO::NULL) do |f|
+ f.readlines("\x0", chomp: true)
end
spec.require_paths = ["lib"]
end
diff --git a/lib/English.rb b/lib/English.rb
index 03fe721991..bf7896dcd6 100644
--- a/lib/English.rb
+++ b/lib/English.rb
@@ -9,7 +9,7 @@
# "waterbuffalo" =~ /buff/
# print $', $$, "\n"
#
-# With English:
+# With 'English':
#
# require "English"
#
@@ -20,30 +20,30 @@
# Below is a full list of descriptive aliases and their associated global
# variable:
#
-# $ERROR_INFO:: $!
-# $ERROR_POSITION:: $@
-# $FS:: $;
-# $FIELD_SEPARATOR:: $;
-# $OFS:: $,
-# $OUTPUT_FIELD_SEPARATOR:: $,
-# $RS:: $/
-# $INPUT_RECORD_SEPARATOR:: $/
-# $ORS:: $\
-# $OUTPUT_RECORD_SEPARATOR:: $\
-# $INPUT_LINE_NUMBER:: $.
-# $NR:: $.
-# $LAST_READ_LINE:: $_
-# $DEFAULT_OUTPUT:: $>
-# $DEFAULT_INPUT:: $<
-# $PID:: $$
-# $PROCESS_ID:: $$
-# $CHILD_STATUS:: $?
-# $LAST_MATCH_INFO:: $~
-# $ARGV:: $*
-# $MATCH:: $&
-# $PREMATCH:: $`
-# $POSTMATCH:: $'
-# $LAST_PAREN_MATCH:: $+
+# <tt>$ERROR_INFO</tt>:: <tt>$!</tt>
+# <tt>$ERROR_POSITION</tt>:: <tt>$@</tt>
+# <tt>$FS</tt>:: <tt>$;</tt>
+# <tt>$FIELD_SEPARATOR</tt>:: <tt>$;</tt>
+# <tt>$OFS</tt>:: <tt>$,</tt>
+# <tt>$OUTPUT_FIELD_SEPARATOR</tt>:: <tt>$,</tt>
+# <tt>$RS</tt>:: <tt>$/</tt>
+# <tt>$INPUT_RECORD_SEPARATOR</tt>:: <tt>$/</tt>
+# <tt>$ORS</tt>:: <tt>$\</tt>
+# <tt>$OUTPUT_RECORD_SEPARATOR</tt>:: <tt>$\</tt>
+# <tt>$NR</tt>:: <tt>$.</tt>
+# <tt>$INPUT_LINE_NUMBER</tt>:: <tt>$.</tt>
+# <tt>$LAST_READ_LINE</tt>:: <tt>$_</tt>
+# <tt>$DEFAULT_OUTPUT</tt>:: <tt>$></tt>
+# <tt>$DEFAULT_INPUT</tt>:: <tt>$<</tt>
+# <tt>$PID</tt>:: <tt>$$</tt>
+# <tt>$PROCESS_ID</tt>:: <tt>$$</tt>
+# <tt>$CHILD_STATUS</tt>:: <tt>$?</tt>
+# <tt>$LAST_MATCH_INFO</tt>:: <tt>$~</tt>
+# <tt>$ARGV</tt>:: <tt>$*</tt>
+# <tt>$MATCH</tt>:: <tt>$&</tt>
+# <tt>$PREMATCH</tt>:: <tt>$`</tt>
+# <tt>$POSTMATCH</tt>:: <tt>$'</tt>
+# <tt>$LAST_PAREN_MATCH</tt>:: <tt>$+</tt>
#
module English end if false
diff --git a/lib/benchmark.gemspec b/lib/benchmark.gemspec
deleted file mode 100644
index d6e98db805..0000000000
--- a/lib/benchmark.gemspec
+++ /dev/null
@@ -1,30 +0,0 @@
-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{a performance benchmarking library}
- spec.description = spec.summary
- spec.homepage = "https://github.com/ruby/benchmark"
- spec.licenses = ["Ruby", "BSD-2-Clause"]
-
- spec.metadata["homepage_uri"] = spec.homepage
- spec.metadata["source_code_uri"] = spec.homepage
-
- # Specify which files should be added to the gem when it is released.
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
- `git ls-files -z 2>#{IO::NULL}`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
- end
- spec.bindir = "exe"
- spec.executables = []
- spec.require_paths = ["lib"]
-end
diff --git a/lib/benchmark.rb b/lib/benchmark.rb
deleted file mode 100644
index 9f43255e42..0000000000
--- a/lib/benchmark.rb
+++ /dev/null
@@ -1,584 +0,0 @@
-# frozen_string_literal: true
-#--
-# benchmark.rb - a performance benchmarking library
-#
-# $Id$
-#
-# Created by Gotoken (gotoken@notwork.org).
-#
-# Documentation by Gotoken (original RD), Lyle Johnson (RDoc conversion), and
-# Gavin Sinclair (editing).
-#++
-#
-# == Overview
-#
-# The Benchmark module provides methods for benchmarking Ruby code, giving
-# detailed reports on the time taken for each task.
-#
-
-# The Benchmark module provides methods to measure and report the time
-# used to execute Ruby code.
-#
-# * Measure the time to construct the string given by the expression
-# <code>"a"*1_000_000_000</code>:
-#
-# require 'benchmark'
-#
-# puts Benchmark.measure { "a"*1_000_000_000 }
-#
-# On my machine (OSX 10.8.3 on i5 1.7 GHz) this generates:
-#
-# 0.350000 0.400000 0.750000 ( 0.835234)
-#
-# This report shows the user CPU time, system CPU time, the sum of
-# the user and system CPU times, and the elapsed real time. The unit
-# of time is seconds.
-#
-# * Do some experiments sequentially using the #bm method:
-#
-# require 'benchmark'
-#
-# n = 5000000
-# Benchmark.bm do |x|
-# x.report { for i in 1..n; a = "1"; end }
-# x.report { n.times do ; a = "1"; end }
-# x.report { 1.upto(n) do ; a = "1"; end }
-# end
-#
-# The result:
-#
-# user system total real
-# 1.010000 0.000000 1.010000 ( 1.014479)
-# 1.000000 0.000000 1.000000 ( 0.998261)
-# 0.980000 0.000000 0.980000 ( 0.981335)
-#
-# * Continuing the previous example, put a label in each report:
-#
-# require 'benchmark'
-#
-# n = 5000000
-# Benchmark.bm(7) do |x|
-# x.report("for:") { for i in 1..n; a = "1"; end }
-# x.report("times:") { n.times do ; a = "1"; end }
-# x.report("upto:") { 1.upto(n) do ; a = "1"; end }
-# end
-#
-# The result:
-#
-# user system total real
-# for: 1.010000 0.000000 1.010000 ( 1.015688)
-# times: 1.000000 0.000000 1.000000 ( 1.003611)
-# upto: 1.030000 0.000000 1.030000 ( 1.028098)
-#
-# * The times for some benchmarks depend on the order in which items
-# are run. These differences are due to the cost of memory
-# allocation and garbage collection. To avoid these discrepancies,
-# the #bmbm method is provided. For example, to compare ways to
-# sort an array of floats:
-#
-# require 'benchmark'
-#
-# array = (1..1000000).map { rand }
-#
-# Benchmark.bmbm do |x|
-# x.report("sort!") { array.dup.sort! }
-# x.report("sort") { array.dup.sort }
-# end
-#
-# The result:
-#
-# Rehearsal -----------------------------------------
-# sort! 1.490000 0.010000 1.500000 ( 1.490520)
-# sort 1.460000 0.000000 1.460000 ( 1.463025)
-# -------------------------------- total: 2.960000sec
-#
-# user system total real
-# sort! 1.460000 0.000000 1.460000 ( 1.460465)
-# sort 1.450000 0.010000 1.460000 ( 1.448327)
-#
-# * Report statistics of sequential experiments with unique labels,
-# using the #benchmark method:
-#
-# require 'benchmark'
-# include Benchmark # we need the CAPTION and FORMAT constants
-#
-# n = 5000000
-# Benchmark.benchmark(CAPTION, 7, FORMAT, ">total:", ">avg:") do |x|
-# tf = x.report("for:") { for i in 1..n; a = "1"; end }
-# tt = x.report("times:") { n.times do ; a = "1"; end }
-# tu = x.report("upto:") { 1.upto(n) do ; a = "1"; end }
-# [tf+tt+tu, (tf+tt+tu)/3]
-# end
-#
-# The result:
-#
-# user system total real
-# for: 0.950000 0.000000 0.950000 ( 0.952039)
-# times: 0.980000 0.000000 0.980000 ( 0.984938)
-# upto: 0.950000 0.000000 0.950000 ( 0.946787)
-# >total: 2.880000 0.000000 2.880000 ( 2.883764)
-# >avg: 0.960000 0.000000 0.960000 ( 0.961255)
-
-module Benchmark
-
- VERSION = "0.3.0"
-
- BENCHMARK_VERSION = "2002-04-25" # :nodoc:
-
- # Invokes the block with a Benchmark::Report object, which
- # may be used to collect and report on the results of individual
- # 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
- # Benchmark::Tms objects, these will be used to format
- # additional lines of output. If +labels+ parameter are
- # given, these are used to label these extra lines.
- #
- # _Note_: Other methods provide a simpler interface to this one, and are
- # suitable for nearly all benchmarking requirements. See the examples in
- # Benchmark, and the #bm and #bmbm methods.
- #
- # Example:
- #
- # require 'benchmark'
- # include Benchmark # we need the CAPTION and FORMAT constants
- #
- # n = 5000000
- # Benchmark.benchmark(CAPTION, 7, FORMAT, ">total:", ">avg:") do |x|
- # tf = x.report("for:") { for i in 1..n; a = "1"; end }
- # tt = x.report("times:") { n.times do ; a = "1"; end }
- # tu = x.report("upto:") { 1.upto(n) do ; a = "1"; end }
- # [tf+tt+tu, (tf+tt+tu)/3]
- # end
- #
- # Generates:
- #
- # user system total real
- # for: 0.970000 0.000000 0.970000 ( 0.970493)
- # times: 0.990000 0.000000 0.990000 ( 0.989542)
- # upto: 0.970000 0.000000 0.970000 ( 0.972854)
- # >total: 2.930000 0.000000 2.930000 ( 2.932889)
- # >avg: 0.976667 0.000000 0.976667 ( 0.977630)
- #
-
- def benchmark(caption = "", label_width = nil, format = nil, *labels) # :yield: report
- sync = $stdout.sync
- $stdout.sync = true
- label_width ||= 0
- label_width += 1
- format ||= FORMAT
- print ' '*label_width + caption unless caption.empty?
- report = Report.new(label_width, format)
- results = yield(report)
- Array === results and results.grep(Tms).each {|t|
- print((labels.shift || t.label || "").ljust(label_width), t.format(format))
- }
- report.list
- ensure
- $stdout.sync = sync unless sync.nil?
- end
-
-
- # A simple interface to the #benchmark method, #bm generates sequential
- # reports with labels. +label_width+ and +labels+ parameters have the same
- # meaning as for #benchmark.
- #
- # require 'benchmark'
- #
- # n = 5000000
- # Benchmark.bm(7) do |x|
- # x.report("for:") { for i in 1..n; a = "1"; end }
- # x.report("times:") { n.times do ; a = "1"; end }
- # x.report("upto:") { 1.upto(n) do ; a = "1"; end }
- # end
- #
- # Generates:
- #
- # user system total real
- # for: 0.960000 0.000000 0.960000 ( 0.957966)
- # times: 0.960000 0.000000 0.960000 ( 0.960423)
- # upto: 0.950000 0.000000 0.950000 ( 0.954864)
- #
-
- def bm(label_width = 0, *labels, &blk) # :yield: report
- benchmark(CAPTION, label_width, FORMAT, *labels, &blk)
- end
-
-
- # Sometimes benchmark results are skewed because code executed
- # earlier encounters different garbage collection overheads than
- # that run later. #bmbm attempts to minimize this effect by running
- # the tests twice, the first time as a rehearsal in order to get the
- # runtime environment stable, the second time for
- # real. GC.start is executed before the start of each of
- # the real timings; the cost of this is not included in the
- # timings. In reality, though, there's only so much that #bmbm can
- # do, and the results are not guaranteed to be isolated from garbage
- # collection and other effects.
- #
- # Because #bmbm takes two passes through the tests, it can
- # calculate the required label width.
- #
- # require 'benchmark'
- #
- # array = (1..1000000).map { rand }
- #
- # Benchmark.bmbm do |x|
- # x.report("sort!") { array.dup.sort! }
- # x.report("sort") { array.dup.sort }
- # end
- #
- # Generates:
- #
- # Rehearsal -----------------------------------------
- # sort! 1.440000 0.010000 1.450000 ( 1.446833)
- # sort 1.440000 0.000000 1.440000 ( 1.448257)
- # -------------------------------- total: 2.890000sec
- #
- # user system total real
- # sort! 1.460000 0.000000 1.460000 ( 1.458065)
- # sort 1.450000 0.000000 1.450000 ( 1.455963)
- #
- # #bmbm yields a Benchmark::Job object and returns an array of
- # Benchmark::Tms objects.
- #
- def bmbm(width = 0) # :yield: job
- job = Job.new(width)
- yield(job)
- width = job.width + 1
- sync = $stdout.sync
- $stdout.sync = true
-
- # rehearsal
- puts 'Rehearsal '.ljust(width+CAPTION.length,'-')
- ets = job.list.inject(Tms.new) { |sum,(label,item)|
- print label.ljust(width)
- res = Benchmark.measure(&item)
- print res.format
- sum + res
- }.format("total: %tsec")
- print " #{ets}\n\n".rjust(width+CAPTION.length+2,'-')
-
- # take
- print ' '*width + CAPTION
- job.list.map { |label,item|
- GC.start
- print label.ljust(width)
- Benchmark.measure(label, &item).tap { |res| print res }
- }
- ensure
- $stdout.sync = sync unless sync.nil?
- end
-
- #
- # Returns the time used to execute the given block as a
- # Benchmark::Tms object. Takes +label+ option.
- #
- # require 'benchmark'
- #
- # n = 1000000
- #
- # time = Benchmark.measure do
- # n.times { a = "1" }
- # end
- # puts time
- #
- # Generates:
- #
- # 0.220000 0.000000 0.220000 ( 0.227313)
- #
- def measure(label = "") # :yield:
- t0, r0 = Process.times, Process.clock_gettime(Process::CLOCK_MONOTONIC)
- yield
- t1, r1 = Process.times, Process.clock_gettime(Process::CLOCK_MONOTONIC)
- Benchmark::Tms.new(t1.utime - t0.utime,
- t1.stime - t0.stime,
- t1.cutime - t0.cutime,
- t1.cstime - t0.cstime,
- r1 - r0,
- label)
- end
-
- #
- # Returns the elapsed real time used to execute the given block.
- #
- def realtime # :yield:
- r0 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
- yield
- Process.clock_gettime(Process::CLOCK_MONOTONIC) - r0
- end
-
- module_function :benchmark, :measure, :realtime, :bm, :bmbm
-
- #
- # A Job is a sequence of labelled blocks to be processed by the
- # Benchmark.bmbm method. It is of little direct interest to the user.
- #
- class Job # :nodoc:
- #
- # Returns an initialized Job instance.
- # Usually, one doesn't call this method directly, as new
- # Job objects are created by the #bmbm method.
- # +width+ is a initial value for the label offset used in formatting;
- # the #bmbm method passes its +width+ argument to this constructor.
- #
- def initialize(width)
- @width = width
- @list = []
- end
-
- #
- # Registers the given label and block pair in the job list.
- #
- def item(label = "", &blk) # :yield:
- raise ArgumentError, "no block" unless block_given?
- label = label.to_s
- w = label.length
- @width = w if @width < w
- @list << [label, blk]
- self
- end
-
- alias report item
-
- # An array of 2-element arrays, consisting of label and block pairs.
- attr_reader :list
-
- # Length of the widest label in the #list.
- attr_reader :width
- end
-
- #
- # This class is used by the Benchmark.benchmark and Benchmark.bm methods.
- # It is of little direct interest to the user.
- #
- class Report # :nodoc:
- #
- # Returns an initialized Report instance.
- # Usually, one doesn't call this method directly, as new
- # Report objects are created by the #benchmark and #bm methods.
- # +width+ and +format+ are the label offset and
- # format string used by Tms#format.
- #
- def initialize(width = 0, format = nil)
- @width, @format, @list = width, format, []
- end
-
- #
- # Prints the +label+ and measured time for the block,
- # formatted by +format+. See Tms#format for the
- # formatting rules.
- #
- def item(label = "", *format, &blk) # :yield:
- print label.to_s.ljust(@width)
- @list << res = Benchmark.measure(label, &blk)
- print res.format(@format, *format)
- res
- end
-
- alias report item
-
- # An array of Benchmark::Tms objects representing each item.
- attr_reader :list
- end
-
-
-
- #
- # A data object, representing the times associated with a benchmark
- # measurement.
- #
- class Tms
-
- # Default caption, see also Benchmark::CAPTION
- CAPTION = " user system total real\n"
-
- # Default format string, see also Benchmark::FORMAT
- FORMAT = "%10.6u %10.6y %10.6t %10.6r\n"
-
- # User CPU time
- attr_reader :utime
-
- # System CPU time
- attr_reader :stime
-
- # User CPU time of children
- attr_reader :cutime
-
- # System CPU time of children
- attr_reader :cstime
-
- # Elapsed real time
- attr_reader :real
-
- # Total time, that is +utime+ + +stime+ + +cutime+ + +cstime+
- attr_reader :total
-
- # Label
- attr_reader :label
-
- #
- # Returns an initialized Tms object which has
- # +utime+ as the user CPU time, +stime+ as the system CPU time,
- # +cutime+ as the children's user CPU time, +cstime+ as the children's
- # system CPU time, +real+ as the elapsed real time and +label+ as the label.
- #
- def initialize(utime = 0.0, stime = 0.0, cutime = 0.0, cstime = 0.0, real = 0.0, label = nil)
- @utime, @stime, @cutime, @cstime, @real, @label = utime, stime, cutime, cstime, real, label.to_s
- @total = @utime + @stime + @cutime + @cstime
- end
-
- #
- # Returns a new Tms object whose times are the sum of the times for this
- # Tms object, plus the time required to execute the code block (+blk+).
- #
- def add(&blk) # :yield:
- self + Benchmark.measure(&blk)
- end
-
- #
- # An in-place version of #add.
- # Changes the times of this Tms object by making it the sum of the times
- # for this Tms object, plus the time required to execute
- # the code block (+blk+).
- #
- def add!(&blk)
- t = Benchmark.measure(&blk)
- @utime = utime + t.utime
- @stime = stime + t.stime
- @cutime = cutime + t.cutime
- @cstime = cstime + t.cstime
- @real = real + t.real
- self
- end
-
- #
- # Returns a new Tms object obtained by memberwise summation
- # of the individual times for this Tms object with those of the +other+
- # Tms object.
- # This method and #/() are useful for taking statistics.
- #
- def +(other); memberwise(:+, other) end
-
- #
- # Returns a new Tms object obtained by memberwise subtraction
- # of the individual times for the +other+ Tms object from those of this
- # Tms object.
- #
- def -(other); memberwise(:-, other) end
-
- #
- # Returns a new Tms object obtained by memberwise multiplication
- # of the individual times for this Tms object by +x+.
- #
- def *(x); memberwise(:*, x) end
-
- #
- # Returns a new Tms object obtained by memberwise division
- # of the individual times for this Tms object by +x+.
- # This method and #+() are useful for taking statistics.
- #
- def /(x); memberwise(:/, x) end
-
- #
- # Returns the contents of this Tms object as
- # a formatted string, according to a +format+ string
- # like that passed to Kernel.format. In addition, #format
- # accepts the following extensions:
- #
- # <tt>%u</tt>:: Replaced by the user CPU time, as reported by Tms#utime.
- # <tt>%y</tt>:: Replaced by the system CPU time, as reported by #stime (Mnemonic: y of "s*y*stem")
- # <tt>%U</tt>:: Replaced by the children's user CPU time, as reported by Tms#cutime
- # <tt>%Y</tt>:: Replaced by the children's system CPU time, as reported by Tms#cstime
- # <tt>%t</tt>:: Replaced by the total CPU time, as reported by Tms#total
- # <tt>%r</tt>:: Replaced by the elapsed real time, as reported by Tms#real
- # <tt>%n</tt>:: Replaced by the label string, as reported by Tms#label (Mnemonic: n of "*n*ame")
- #
- # If +format+ is not given, FORMAT is used as default value, detailing the
- # user, system and real elapsed time.
- #
- def format(format = nil, *args)
- str = (format || FORMAT).dup
- str.gsub!(/(%[-+.\d]*)n/) { "#{$1}s" % label }
- str.gsub!(/(%[-+.\d]*)u/) { "#{$1}f" % utime }
- str.gsub!(/(%[-+.\d]*)y/) { "#{$1}f" % stime }
- str.gsub!(/(%[-+.\d]*)U/) { "#{$1}f" % cutime }
- str.gsub!(/(%[-+.\d]*)Y/) { "#{$1}f" % cstime }
- str.gsub!(/(%[-+.\d]*)t/) { "#{$1}f" % total }
- str.gsub!(/(%[-+.\d]*)r/) { "(#{$1}f)" % real }
- format ? str % args : str
- end
-
- #
- # Same as #format.
- #
- def to_s
- format
- end
-
- #
- # Returns a new 6-element array, consisting of the
- # label, user CPU time, system CPU time, children's
- # user CPU time, children's system CPU time and elapsed
- # real time.
- #
- 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
-
- #
- # Returns a new Tms object obtained by memberwise operation +op+
- # of the individual times for this Tms object with those of the other
- # Tms object (+x+).
- #
- # +op+ can be a mathematical operation such as <tt>+</tt>, <tt>-</tt>,
- # <tt>*</tt>, <tt>/</tt>
- #
- def memberwise(op, x)
- case x
- when Benchmark::Tms
- Benchmark::Tms.new(utime.__send__(op, x.utime),
- stime.__send__(op, x.stime),
- cutime.__send__(op, x.cutime),
- cstime.__send__(op, x.cstime),
- real.__send__(op, x.real)
- )
- else
- Benchmark::Tms.new(utime.__send__(op, x),
- stime.__send__(op, x),
- cutime.__send__(op, x),
- cstime.__send__(op, x),
- real.__send__(op, x)
- )
- end
- end
- end
-
- # The default caption string (heading above the output times).
- CAPTION = Benchmark::Tms::CAPTION
-
- # The default format string used to display times. See also Benchmark::Tms#format.
- FORMAT = Benchmark::Tms::FORMAT
-end
diff --git a/lib/bundled_gems.rb b/lib/bundled_gems.rb
index c933ad0471..85f23b2596 100644
--- a/lib/bundled_gems.rb
+++ b/lib/bundled_gems.rb
@@ -1,18 +1,12 @@
# -*- frozen-string-literal: true -*-
# :stopdoc:
+module Gem
+end
+# :startdoc:
-module Gem::BUNDLED_GEMS
+module Gem::BUNDLED_GEMS # :nodoc:
SINCE = {
- "rexml" => "3.0.0",
- "rss" => "3.0.0",
- "webrick" => "3.0.0",
- "matrix" => "3.1.0",
- "net-ftp" => "3.1.0",
- "net-imap" => "3.1.0",
- "net-pop" => "3.1.0",
- "net-smtp" => "3.1.0",
- "prime" => "3.1.0",
"racc" => "3.3.0",
"abbrev" => "3.4.0",
"base64" => "3.4.0",
@@ -26,35 +20,21 @@ module Gem::BUNDLED_GEMS
"resolv-replace" => "3.4.0",
"rinda" => "3.4.0",
"syslog" => "3.4.0",
- "ostruct" => "3.5.0",
- "pstore" => "3.5.0",
- "rdoc" => "3.5.0",
+ "ostruct" => "4.0.0",
+ "pstore" => "4.0.0",
+ "rdoc" => "4.0.0",
+ "win32ole" => "4.0.0",
+ "fiddle" => "4.0.0",
+ "logger" => "4.0.0",
+ "benchmark" => "4.0.0",
+ "irb" => "4.0.0",
+ "reline" => "4.0.0",
+ # "readline" => "4.0.0", # This is wrapper for reline. We don't warn for this.
+ "tsort" => "4.1.0",
}.freeze
EXACT = {
- "abbrev" => true,
- "base64" => true,
- "bigdecimal" => true,
- "csv" => true,
- "drb" => true,
- "getoptlong" => true,
- "mutex_m" => true,
- "nkf" => true, "kconv" => "nkf",
- "observer" => true,
- "resolv-replace" => true,
- "rinda" => true,
- "syslog" => true,
- "ostruct" => true,
- "pstore" => true,
- "rdoc" => true,
- }.freeze
-
- PREFIXED = {
- "bigdecimal" => true,
- "csv" => true,
- "drb" => true,
- "rinda" => true,
- "syslog" => true,
+ "kconv" => "nkf",
}.freeze
WARNED = {} # unfrozen
@@ -74,8 +54,8 @@ module Gem::BUNDLED_GEMS
[::Kernel.singleton_class, ::Kernel].each do |kernel_class|
kernel_class.send(:alias_method, :no_warning_require, :require)
kernel_class.send(:define_method, :require) do |name|
- if message = ::Gem::BUNDLED_GEMS.warning?(name, specs: spec_names) # rubocop:disable Style/HashSyntax
- warn message, :uplevel => 1
+ if message = ::Gem::BUNDLED_GEMS.warning?(name, specs: spec_names)
+ Kernel.warn message, uplevel: ::Gem::BUNDLED_GEMS.uplevel
end
kernel_class.send(:no_warning_require, name)
end
@@ -87,69 +67,125 @@ module Gem::BUNDLED_GEMS
end
end
- def self.find_gem(path)
- if !path
- return
- elsif path.start_with?(ARCHDIR)
- n = path.delete_prefix(ARCHDIR).sub(DLEXT, "")
- elsif path.start_with?(LIBDIR)
- n = path.delete_prefix(LIBDIR).chomp(".rb")
- else
- return
+ def self.uplevel
+ frame_count = 0
+ require_labels = ["replace_require", "require"]
+ uplevel = 0
+ require_found = false
+ Thread.each_caller_location do |cl|
+ frame_count += 1
+
+ if require_found
+ unless require_labels.include?(cl.base_label)
+ return uplevel
+ end
+ else
+ if require_labels.include?(cl.base_label)
+ require_found = true
+ end
+ end
+ uplevel += 1
+ # Don't show script name when bundle exec and call ruby script directly.
+ if cl.path.end_with?("bundle")
+ return
+ end
end
- EXACT[n] or PREFIXED[n = n[%r[\A[^/]+(?=/)]]] && n
+ require_found ? 1 : (frame_count - 1).nonzero?
end
def self.warning?(name, specs: nil)
# name can be a feature name or a file path with String or Pathname
- feature = File.path(name)
- # bootsnap expands `require "csv"` to `require "#{LIBDIR}/csv.rb"`,
- # and `require "syslog"` to `require "#{ARCHDIR}/syslog.so"`.
- name = feature.delete_prefix(ARCHDIR)
- name.delete_prefix!(LIBDIR)
- name.tr!("/", "-")
- name.sub!(LIBEXT, "")
- return if specs.include?(name)
- _t, path = $:.resolve_feature_path(feature)
- if gem = find_gem(path)
- return if specs.include?(gem)
- caller = caller_locations(3, 3)&.find {|c| c&.absolute_path}
- return if find_gem(caller&.absolute_path)
- elsif SINCE[name] && !path
- gem = true
+ feature = File.path(name).sub(LIBEXT, "")
+
+ # The actual checks needed to properly identify the gem being required
+ # are costly (see [Bug #20641]), so we first do a much cheaper check
+ # to exclude the vast majority of candidates.
+ subfeature = if feature.include?("/")
+ # bootsnap expands `require "csv"` to `require "#{LIBDIR}/csv.rb"`,
+ # and `require "syslog"` to `require "#{ARCHDIR}/syslog.so"`.
+ feature.delete_prefix!(ARCHDIR)
+ feature.delete_prefix!(LIBDIR)
+ # 1. A segment for the EXACT mapping and SINCE check
+ # 2. A segment for the SINCE check for dashed names
+ # 3. A segment to check if there's a subfeature
+ segments = feature.split("/", 3)
+ name = segments.shift
+ name = EXACT[name] || name
+ if !SINCE[name]
+ name = "#{name}-#{segments.shift}"
+ return unless SINCE[name]
+ end
+ segments.any?
else
- return
+ name = EXACT[feature] || feature
+ return unless SINCE[name]
+ false
+ end
+
+ if suppress_list = Thread.current[:__bundled_gems_warning_suppression]
+ return if suppress_list.include?(name) || suppress_list.include?(feature)
+ end
+
+ return if specs.include?(name)
+
+ # Don't warn if a hyphenated gem provides this feature
+ # (e.g., benchmark-ips provides benchmark/ips, not the benchmark gem)
+ if subfeature
+ feature_parts = feature.split("/")
+ if feature_parts.size >= 2
+ hyphenated_gem = "#{feature_parts[0]}-#{feature_parts[1]}"
+ return if specs.include?(hyphenated_gem)
+ end
end
return if WARNED[name]
WARNED[name] = true
- if gem == true
- gem = name
- "#{feature} was loaded from the standard library, but"
- elsif gem
- return if WARNED[gem]
- WARNED[gem] = true
- "#{feature} is found in #{gem}, which"
+
+ level = RUBY_VERSION < SINCE[name] ? :warning : :error
+
+ if subfeature
+ "#{feature} is found in #{name}, which"
else
- return
- end + build_message(gem)
+ "#{feature} #{level == :warning ? "was loaded" : "used to be loaded"} from the standard library, but"
+ end + build_message(name, level)
end
- def self.build_message(gem)
- msg = " #{RUBY_VERSION < SINCE[gem] ? "will no longer be" : "is not"} part of the default gems since Ruby #{SINCE[gem]}."
+ def self.build_message(name, level)
+ msg = if level == :warning
+ " will no longer be part of the default gems starting from Ruby #{SINCE[name]}"
+ else
+ " is not part of the default gems since Ruby #{SINCE[name]}."
+ end
if defined?(Bundler)
- msg += " Add #{gem} to your Gemfile or gemspec."
+ motivation = level == :warning ? "silence this warning" : "fix this error"
+ msg += "\nYou can add #{name} to your Gemfile or gemspec to #{motivation}."
- # We detect the gem name from caller_locations. We need to skip 2 frames like:
- # lib/ruby/3.3.0+0/bundled_gems.rb:90:in `warning?'",
- # lib/ruby/3.3.0+0/bundler/rubygems_integration.rb:247:in `block (2 levels) in replace_require'",
+ # We detect the gem name from caller_locations. First we walk until we find `require`
+ # then take the first frame that's not from `require`.
#
# Additionally, we need to skip Bootsnap and Zeitwerk if present, these
# gems decorate Kernel#require, so they are not really the ones issuing
# the require call users should be warned about. Those are upwards.
- location = Thread.each_caller_location(2) do |cl|
- break cl.path unless cl.base_label == "require"
+ frames_to_skip = 3
+ location = nil
+ require_found = false
+ Thread.each_caller_location do |cl|
+ if frames_to_skip >= 1
+ frames_to_skip -= 1
+ next
+ end
+
+ if require_found
+ if cl.base_label != "require"
+ location = cl.path
+ break
+ end
+ else
+ if cl.base_label == "require"
+ require_found = true
+ end
+ end
end
if location && File.file?(location) && !location.start_with?(Gem::BUNDLED_GEMS::LIBDIR)
@@ -161,31 +197,75 @@ module Gem::BUNDLED_GEMS
end
end
if caller_gem
- msg += " Also contact author of #{caller_gem} to add #{gem} into its gemspec."
+ msg += "\nAlso please contact the author of #{caller_gem} to request adding #{name} into its gemspec."
end
end
else
- msg += " Install #{gem} from RubyGems."
+ msg += " Install #{name} from RubyGems."
end
msg
end
- freeze
+ def self.force_activate(gem)
+ require "bundler"
+ Bundler.reset!
+
+ # Build and activate a temporary definition containing the original gems + the requested gem
+ builder = Bundler::Dsl.new
+
+ lockfile = nil
+ if Bundler::SharedHelpers.in_bundle? && Bundler.definition.gemfiles.size > 0
+ Bundler.definition.gemfiles.each {|gemfile| builder.eval_gemfile(gemfile) }
+ lockfile = begin
+ Bundler.default_lockfile
+ rescue Bundler::GemfileNotFound
+ nil
+ end
+ else
+ # Fake BUNDLE_GEMFILE and BUNDLE_LOCKFILE to let checks pass
+ orig_gemfile = ENV["BUNDLE_GEMFILE"]
+ orig_lockfile = ENV["BUNDLE_LOCKFILE"]
+ Bundler::SharedHelpers.set_env "BUNDLE_GEMFILE", "Gemfile"
+ Bundler::SharedHelpers.set_env "BUNDLE_LOCKFILE", "Gemfile.lock"
+ end
+
+ builder.gem gem
+
+ definition = builder.to_definition(lockfile, nil)
+ definition.validate_runtime!
+
+ begin
+ orig_ui = Bundler.ui
+ orig_no_lock = Bundler::Definition.no_lock
+
+ ui = Bundler::UI::Shell.new
+ ui.level = "silent"
+ Bundler.ui = ui
+ Bundler::Definition.no_lock = true
+
+ Bundler::Runtime.new(nil, definition).setup
+ rescue Bundler::GemNotFound
+ warn "Failed to activate #{gem}, please install it with 'gem install #{gem}'"
+ ensure
+ ENV['BUNDLE_GEMFILE'] = orig_gemfile if orig_gemfile
+ ENV['BUNDLE_LOCKFILE'] = orig_lockfile if orig_lockfile
+ Bundler.ui = orig_ui
+ Bundler::Definition.no_lock = orig_no_lock
+ end
+ end
end
# for RubyGems without Bundler environment.
# If loading library is not part of the default gems and the bundled gems, warn it.
class LoadError
- def message
+ def message # :nodoc:
return super unless path
name = path.tr("/", "-")
if !defined?(Bundler) && Gem::BUNDLED_GEMS::SINCE[name] && !Gem::BUNDLED_GEMS::WARNED[name]
- warn name + Gem::BUNDLED_GEMS.build_message(name)
+ warn name + Gem::BUNDLED_GEMS.build_message(name, :error), uplevel: Gem::BUNDLED_GEMS.uplevel
end
super
end
end
-
-# :startdoc:
diff --git a/lib/bundler.rb b/lib/bundler.rb
index 0081b9554f..51ea3beeb0 100644
--- a/lib/bundler.rb
+++ b/lib/bundler.rb
@@ -1,16 +1,15 @@
# frozen_string_literal: true
+require_relative "bundler/rubygems_ext"
require_relative "bundler/vendored_fileutils"
-require "pathname"
+autoload :Pathname, "pathname" unless defined?(Pathname)
require "rbconfig"
require_relative "bundler/errors"
require_relative "bundler/environment_preserver"
require_relative "bundler/plugin"
-require_relative "bundler/rubygems_ext"
require_relative "bundler/rubygems_integration"
require_relative "bundler/version"
-require_relative "bundler/constants"
require_relative "bundler/current_ruby"
require_relative "bundler/build_metadata"
@@ -52,16 +51,17 @@ module Bundler
autoload :Env, File.expand_path("bundler/env", __dir__)
autoload :Fetcher, File.expand_path("bundler/fetcher", __dir__)
autoload :FeatureFlag, File.expand_path("bundler/feature_flag", __dir__)
+ autoload :FREEBSD, File.expand_path("bundler/constants", __dir__)
autoload :GemHelper, File.expand_path("bundler/gem_helper", __dir__)
- autoload :GemHelpers, File.expand_path("bundler/gem_helpers", __dir__)
autoload :GemVersionPromoter, File.expand_path("bundler/gem_version_promoter", __dir__)
- autoload :Graph, File.expand_path("bundler/graph", __dir__)
autoload :Index, File.expand_path("bundler/index", __dir__)
autoload :Injector, File.expand_path("bundler/injector", __dir__)
autoload :Installer, File.expand_path("bundler/installer", __dir__)
autoload :LazySpecification, File.expand_path("bundler/lazy_specification", __dir__)
autoload :LockfileParser, File.expand_path("bundler/lockfile_parser", __dir__)
autoload :MatchRemoteMetadata, File.expand_path("bundler/match_remote_metadata", __dir__)
+ autoload :Materialization, File.expand_path("bundler/materialization", __dir__)
+ autoload :NULL, File.expand_path("bundler/constants", __dir__)
autoload :ProcessLock, File.expand_path("bundler/process_lock", __dir__)
autoload :RemoteSpecification, File.expand_path("bundler/remote_specification", __dir__)
autoload :Resolver, File.expand_path("bundler/resolver", __dir__)
@@ -80,6 +80,7 @@ module Bundler
autoload :UI, File.expand_path("bundler/ui", __dir__)
autoload :URICredentialsFilter, File.expand_path("bundler/uri_credentials_filter", __dir__)
autoload :URINormalizer, File.expand_path("bundler/uri_normalizer", __dir__)
+ autoload :WINDOWS, File.expand_path("bundler/constants", __dir__)
autoload :SafeMarshal, File.expand_path("bundler/safe_marshal", __dir__)
class << self
@@ -111,13 +112,13 @@ module Bundler
end
def configured_bundle_path
- @configured_bundle_path ||= settings.path.tap(&:validate!)
+ @configured_bundle_path ||= Bundler.settings.path.tap(&:validate!)
end
# Returns absolute location of where binstubs are installed to.
def bin_path
@bin_path ||= begin
- path = settings[:bin] || "bin"
+ path = Bundler.settings[:bin] || "bin"
path = Pathname.new(path).expand_path(root).expand_path
mkdir_p(path)
path
@@ -167,14 +168,18 @@ module Bundler
end
end
- # Automatically install dependencies if Bundler.settings[:auto_install] exists.
+ def auto_switch
+ self_manager.restart_with_locked_bundler_if_needed
+ end
+
+ # Automatically install dependencies if settings[:auto_install] exists.
# This is set through config cmd `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
# `Installer` that'll keep a reference to the old one instead.
def auto_install
- return unless settings[:auto_install]
+ return unless Bundler.settings[:auto_install]
begin
definition.specs
@@ -205,7 +210,6 @@ module Bundler
# Bundler.require(:test) # requires second_gem
#
def require(*groups)
- load_plugins
setup(*groups).require(*groups)
end
@@ -214,8 +218,7 @@ module Bundler
end
def environment
- SharedHelpers.major_deprecation 2, "Bundler.environment has been removed in favor of Bundler.load", print_caller_location: true
- load
+ SharedHelpers.feature_removed! "Bundler.environment has been removed in favor of Bundler.load"
end
# Returns an instance of Bundler::Definition for given Gemfile and lockfile
@@ -233,10 +236,10 @@ module Bundler
end
def frozen_bundle?
- frozen = settings[:frozen]
+ frozen = Bundler.settings[:frozen]
return frozen unless frozen.nil?
- settings[:deployment]
+ Bundler.settings[:deployment]
end
def locked_gems
@@ -249,12 +252,6 @@ module Bundler
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
@@ -343,7 +340,7 @@ module Bundler
def app_cache(custom_path = nil)
path = custom_path || root
- Pathname.new(path).join(settings.app_cache_path)
+ Pathname.new(path).join(Bundler.settings.app_cache_path)
end
def tmp(name = Process.pid.to_s)
@@ -366,42 +363,21 @@ module Bundler
ORIGINAL_ENV.clone
end
- # @deprecated Use `unbundled_env` instead
def clean_env
- message =
- "`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`"
removed_message =
"`Bundler.clean_env` has been removed in favor of `Bundler.unbundled_env`. " \
"If you instead want the environment before bundler was originally loaded, use `Bundler.original_env`"
- Bundler::SharedHelpers.major_deprecation(2, message, removed_message: removed_message, print_caller_location: true)
- unbundled_env
+ Bundler::SharedHelpers.feature_removed!(removed_message)
end
# @return [Hash] Environment with all bundler-related variables removed
def unbundled_env
- env = original_env
-
- if env.key?("BUNDLER_ORIG_MANPATH")
- env["MANPATH"] = env["BUNDLER_ORIG_MANPATH"]
- end
-
- env.delete_if {|k, _| k[0, 7] == "BUNDLE_" }
-
- if env.key?("RUBYOPT")
- 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")
- rubylib = env["RUBYLIB"].split(File::PATH_SEPARATOR)
- rubylib.delete(__dir__)
- env["RUBYLIB"] = rubylib.join(File::PATH_SEPARATOR)
- end
+ unbundle_env(original_env)
+ end
- env
+ # Remove all bundler-related variables from ENV
+ def unbundle_env!
+ ENV.replace(unbundle_env(ENV))
end
# Run block with environment present before Bundler was activated
@@ -409,16 +385,11 @@ module Bundler
with_env(original_env) { yield }
end
- # @deprecated Use `with_unbundled_env` instead
def with_clean_env
- message =
- "`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`"
removed_message =
"`Bundler.with_clean_env` has been removed in favor of `Bundler.with_unbundled_env`. " \
"If you instead want the environment before bundler was originally loaded, use `Bundler.with_original_env`"
- Bundler::SharedHelpers.major_deprecation(2, message, removed_message: removed_message, print_caller_location: true)
- with_env(unbundled_env) { yield }
+ Bundler::SharedHelpers.feature_removed!(removed_message)
end
# Run block with all bundler-related variables removed
@@ -431,16 +402,11 @@ module Bundler
with_original_env { Kernel.system(*args) }
end
- # @deprecated Use `unbundled_system` instead
def clean_system(*args)
- message =
- "`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`"
removed_message =
"`Bundler.clean_system` has been removed 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`"
- Bundler::SharedHelpers.major_deprecation(2, message, removed_message: removed_message, print_caller_location: true)
- with_env(unbundled_env) { Kernel.system(*args) }
+ Bundler::SharedHelpers.feature_removed!(removed_message)
end
# Run subcommand in an environment with all bundler related variables removed
@@ -453,16 +419,11 @@ module Bundler
with_original_env { Kernel.exec(*args) }
end
- # @deprecated Use `unbundled_exec` instead
def clean_exec(*args)
- message =
- "`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`"
removed_message =
"`Bundler.clean_exec` has been removed 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`"
- Bundler::SharedHelpers.major_deprecation(2, message, removed_message: removed_message, print_caller_location: true)
- with_env(unbundled_env) { Kernel.exec(*args) }
+ Bundler::SharedHelpers.feature_removed!(removed_message)
end
# Run a `Kernel.exec` to a subcommand in an environment with all bundler related variables removed
@@ -471,10 +432,14 @@ module Bundler
end
def local_platform
- return Gem::Platform::RUBY if settings[:force_ruby_platform]
+ return Gem::Platform::RUBY if Bundler.settings[:force_ruby_platform]
Gem::Platform.local
end
+ def generic_local_platform
+ Gem::Platform.generic(local_platform)
+ end
+
def default_gemfile
SharedHelpers.default_gemfile
end
@@ -505,24 +470,33 @@ module Bundler
end
def mkdir_p(path)
- SharedHelpers.filesystem_access(path, :write) do |p|
+ SharedHelpers.filesystem_access(path, :create) do |p|
FileUtils.mkdir_p(p)
end
end
def which(executable)
- if File.file?(executable) && File.executable?(executable)
- executable
- elsif paths = ENV["PATH"]
+ executable_path = find_executable(executable)
+ return executable_path if executable_path
+
+ if (paths = ENV["PATH"])
quote = '"'
paths.split(File::PATH_SEPARATOR).find do |path|
path = path[1..-2] if path.start_with?(quote) && path.end_with?(quote)
- executable_path = File.expand_path(executable, path)
- return executable_path if File.file?(executable_path) && File.executable?(executable_path)
+ executable_path = find_executable(File.expand_path(executable, path))
+ return executable_path if executable_path
end
end
end
+ def find_executable(path)
+ extensions = RbConfig::CONFIG["EXECUTABLE_EXTS"]&.split
+ extensions = [RbConfig::CONFIG["EXEEXT"]] unless extensions&.any?
+ candidates = extensions.map {|ext| "#{path}#{ext}" }
+
+ candidates.find {|candidate| File.file?(candidate) && File.executable?(candidate) }
+ end
+
def read_file(file)
SharedHelpers.filesystem_access(file, :read) do
File.open(file, "r:UTF-8", &:read)
@@ -554,15 +528,7 @@ module Bundler
def load_gemspec_uncached(file, validate = false)
path = Pathname.new(file)
contents = read_file(file)
- spec = if contents.start_with?("---") # YAML header
- eval_yaml_gemspec(path, contents)
- else
- # Eval the gemspec from its parent directory, because some gemspecs
- # depend on "./" relative paths.
- SharedHelpers.chdir(path.dirname.to_s) do
- eval_gemspec(path, contents)
- end
- end
+ spec = eval_gemspec(path, contents)
return unless spec
spec.loaded_from = path.expand_path.to_s
Bundler.rubygems.validate(spec) if validate
@@ -575,28 +541,11 @@ module Bundler
def git_present?
return @git_present if defined?(@git_present)
- @git_present = Bundler.which("git#{RbConfig::CONFIG["EXEEXT"]}")
+ @git_present = Bundler.which("git")
end
def feature_flag
- @feature_flag ||= FeatureFlag.new(VERSION)
- end
-
- def load_plugins(definition = Bundler.definition)
- return if defined?(@load_plugins_ran)
-
- Bundler.rubygems.load_plugins
-
- requested_path_gems = definition.requested_specs.select {|s| s.source.is_a?(Source::Path) }
- path_plugin_files = requested_path_gems.map do |spec|
- Bundler.rubygems.spec_matches_for_glob(spec, "rubygems_plugin#{Bundler.rubygems.suffix_pattern}")
- rescue TypeError
- error_message = "#{spec.name} #{spec.version} has an invalid gemspec"
- raise Gem::InvalidSpecificationException, error_message
- end.flatten
- Bundler.rubygems.load_plugin_files(path_plugin_files)
- Bundler.rubygems.load_env_plugins
- @load_plugins_ran = true
+ @feature_flag ||= FeatureFlag.new(Bundler.settings[:simulate_version] || VERSION)
end
def reset!
@@ -612,7 +561,6 @@ module Bundler
def reset_paths!
@bin_path = nil
- @bundler_major_version = nil
@bundle_path = nil
@configure = nil
@configured_bundle_path = nil
@@ -647,6 +595,30 @@ module Bundler
private
+ def unbundle_env(env)
+ if env.key?("BUNDLER_ORIG_MANPATH")
+ env["MANPATH"] = env["BUNDLER_ORIG_MANPATH"]
+ end
+
+ env.delete_if {|k, _| k[0, 7] == "BUNDLE_" }
+ env.delete("BUNDLER_SETUP")
+
+ if env.key?("RUBYOPT")
+ 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")
+ rubylib = env["RUBYLIB"].split(File::PATH_SEPARATOR)
+ rubylib.delete(__dir__)
+ env["RUBYLIB"] = rubylib.join(File::PATH_SEPARATOR)
+ end
+
+ env
+ end
+
def load_marshal(data, marshal_proc: nil)
Marshal.load(data, marshal_proc)
rescue TypeError => e
@@ -657,16 +629,22 @@ module Bundler
Kernel.require "psych"
Gem::Specification.from_yaml(contents)
- rescue ::Psych::SyntaxError, ArgumentError, Gem::EndOfYAMLException, Gem::Exception
- eval_gemspec(path, contents)
end
def eval_gemspec(path, contents)
- eval(contents, TOPLEVEL_BINDING.dup, path.expand_path.to_s)
+ if contents.start_with?("---") # YAML header
+ eval_yaml_gemspec(path, contents)
+ else
+ # Eval the gemspec from its parent directory, because some gemspecs
+ # depend on "./" relative paths.
+ SharedHelpers.chdir(path.dirname.to_s) do
+ eval(contents, TOPLEVEL_BINDING.dup, path.expand_path.to_s)
+ end
+ end
rescue ScriptError, StandardError => e
msg = "There was an error while loading `#{path.basename}`: #{e.message}"
- raise GemspecError, Dsl::DSLError.new(msg, path, e.backtrace, contents)
+ raise GemspecError, Dsl::DSLError.new(msg, path.to_s, e.backtrace, contents)
end
def configure_gem_path
diff --git a/lib/bundler/build_metadata.rb b/lib/bundler/build_metadata.rb
index 5d2a8b53bb..49d2518078 100644
--- a/lib/bundler/build_metadata.rb
+++ b/lib/bundler/build_metadata.rb
@@ -4,21 +4,26 @@ module Bundler
# Represents metadata from when the Bundler gem was built.
module BuildMetadata
# begin ivars
- @release = false
+ @built_at = nil
# end ivars
# A hash representation of the build metadata.
def self.to_h
{
- "Built At" => built_at,
+ "Timestamp" => timestamp,
"Git SHA" => git_commit_sha,
- "Released Version" => release?,
}
end
+ # A timestamp representing the date the bundler gem was built, or the
+ # current time if never built
+ def self.timestamp
+ @timestamp ||= @built_at || Time.now.utc.strftime("%Y-%m-%d").freeze
+ end
+
# A string representing the date the bundler gem was built.
def self.built_at
- @built_at ||= Time.now.utc.strftime("%Y-%m-%d").freeze
+ @built_at
end
# The SHA for the git commit the bundler gem was built from.
@@ -34,10 +39,5 @@ module Bundler
@git_commit_sha ||= "unknown"
end
-
- # Whether this is an official release build of Bundler.
- def self.release?
- @release
- end
end
end
diff --git a/lib/bundler/bundler.gemspec b/lib/bundler/bundler.gemspec
index 2d6269fae1..49319e81b4 100644
--- a/lib/bundler/bundler.gemspec
+++ b/lib/bundler/bundler.gemspec
@@ -23,16 +23,16 @@ Gem::Specification.new do |s|
s.description = "Bundler manages an application's dependencies through its entire life, across many machines, systematically and repeatably"
s.metadata = {
- "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",
+ "bug_tracker_uri" => "https://github.com/ruby/rubygems/issues?q=is%3Aopen+is%3Aissue+label%3ABundler",
+ "changelog_uri" => "https://github.com/ruby/rubygems/blob/master/bundler/CHANGELOG.md",
"homepage_uri" => "https://bundler.io/",
- "source_code_uri" => "https://github.com/rubygems/rubygems/tree/master/bundler",
+ "source_code_uri" => "https://github.com/ruby/rubygems/tree/master/bundler",
}
- s.required_ruby_version = ">= 3.0.0"
+ s.required_ruby_version = ">= 3.2.0"
# It should match the RubyGems version shipped with `required_ruby_version` above
- s.required_rubygems_version = ">= 3.2.3"
+ s.required_rubygems_version = ">= 3.4.1"
s.files = Dir.glob("lib/bundler{.rb,/**/*}", File::FNM_DOTMATCH).reject {|f| File.directory?(f) }
diff --git a/lib/bundler/capistrano.rb b/lib/bundler/capistrano.rb
index 705840143f..6d2437d895 100644
--- a/lib/bundler/capistrano.rb
+++ b/lib/bundler/capistrano.rb
@@ -1,22 +1,4 @@
# frozen_string_literal: true
require_relative "shared_helpers"
-Bundler::SharedHelpers.major_deprecation 2,
- "The Bundler task for Capistrano. Please use https://github.com/capistrano/bundler"
-
-# Capistrano task for Bundler.
-#
-# Add "require 'bundler/capistrano'" in your Capistrano deploy.rb, and
-# Bundler will be activated after each new deployment.
-require_relative "deployment"
-require "capistrano/version"
-
-if defined?(Capistrano::Version) && Gem::Version.new(Capistrano::Version).release >= Gem::Version.new("3.0")
- raise "For Capistrano 3.x integration, please use https://github.com/capistrano/bundler"
-end
-
-Capistrano::Configuration.instance(:must_exist).load do
- before "deploy:finalize_update", "bundle:install"
- Bundler::Deployment.define_task(self, :task, except: { no_release: true })
- set :rake, lambda { "#{fetch(:bundle_cmd, "bundle")} exec rake" }
-end
+Bundler::SharedHelpers.feature_removed! "The Bundler task for Capistrano. Please use https://github.com/capistrano/bundler"
diff --git a/lib/bundler/checksum.rb b/lib/bundler/checksum.rb
index 60ba93417c..ce05818bb0 100644
--- a/lib/bundler/checksum.rb
+++ b/lib/bundler/checksum.rb
@@ -126,7 +126,7 @@ module Bundler
end
def removable?
- type == :lock || type == :gem
+ [:lock, :gem].include?(type)
end
def ==(other)
@@ -190,7 +190,7 @@ module Bundler
def replace(spec, checksum)
return unless checksum
- lock_name = spec.name_tuple.lock_name
+ lock_name = spec.lock_name
@store_mutex.synchronize do
existing = fetch_checksum(lock_name, checksum.algo)
if !existing || existing.same_source?(checksum)
@@ -201,10 +201,18 @@ module Bundler
end
end
- def register(spec, checksum)
- return unless checksum
+ def missing?(spec)
+ @store[spec.lock_name].nil?
+ end
+
+ def empty?(spec)
+ return false unless spec.source.is_a?(Bundler::Source::Rubygems)
+
+ @store[spec.lock_name].empty?
+ end
- register_checksum(spec.name_tuple.lock_name, checksum)
+ def register(spec, checksum)
+ register_checksum(spec.lock_name, checksum)
end
def merge!(other)
@@ -216,9 +224,9 @@ module Bundler
end
def to_lock(spec)
- lock_name = spec.name_tuple.lock_name
+ lock_name = spec.lock_name
checksums = @store[lock_name]
- if checksums
+ if checksums&.any?
"#{lock_name} #{checksums.values.map(&:to_lock).sort.join(",")}"
else
lock_name
@@ -229,11 +237,15 @@ module Bundler
def register_checksum(lock_name, checksum)
@store_mutex.synchronize do
- existing = fetch_checksum(lock_name, checksum.algo)
- if existing
- merge_checksum(lock_name, checksum, existing)
+ if checksum
+ existing = fetch_checksum(lock_name, checksum.algo)
+ if existing
+ merge_checksum(lock_name, checksum, existing)
+ else
+ store_checksum(lock_name, checksum)
+ end
else
- store_checksum(lock_name, checksum)
+ init_checksum(lock_name)
end
end
end
@@ -243,7 +255,11 @@ module Bundler
end
def store_checksum(lock_name, checksum)
- (@store[lock_name] ||= {})[checksum.algo] = checksum
+ init_checksum(lock_name)[checksum.algo] = checksum
+ end
+
+ def init_checksum(lock_name)
+ @store[lock_name] ||= {}
end
def fetch_checksum(lock_name, algo)
diff --git a/lib/bundler/cli.rb b/lib/bundler/cli.rb
index eb67668cd2..1f6a65ca57 100644
--- a/lib/bundler/cli.rb
+++ b/lib/bundler/cli.rb
@@ -11,7 +11,7 @@ module Bundler
AUTO_INSTALL_CMDS = %w[show binstubs outdated exec open console licenses clean].freeze
PARSEABLE_COMMANDS = %w[check config help exec platform show version].freeze
- EXTENSIONS = ["c", "rust"].freeze
+ EXTENSIONS = ["c", "rust", "go"].freeze
COMMAND_ALIASES = {
"check" => "c",
@@ -24,7 +24,7 @@ module Bundler
}.freeze
def self.start(*)
- check_deprecated_ext_option(ARGV) if ARGV.include?("--ext")
+ check_invalid_ext_option(ARGV) if ARGV.include?("--ext")
super
ensure
@@ -59,17 +59,29 @@ module Bundler
def initialize(*args)
super
+ current_cmd = args.last[:current_command].name
+
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_settings_and_root!
+ reset_settings = true
+ end
+
+ # lock --lockfile works differently than install --lockfile
+ unless current_cmd == "lock"
+ custom_lockfile = options[:lockfile] || ENV["BUNDLE_LOCKFILE"] || Bundler.settings[:lockfile]
+ if custom_lockfile && !custom_lockfile.empty?
+ Bundler::SharedHelpers.set_env "BUNDLE_LOCKFILE", File.expand_path(custom_lockfile)
+ reset_settings = true
+ end
end
- Bundler.self_manager.restart_with_locked_bundler_if_needed
+ Bundler.reset_settings_and_root! if reset_settings
+
+ Bundler.auto_switch
Bundler.settings.set_command_option_if_given :retry, options[:retry]
- current_cmd = args.last[:current_command].name
Bundler.auto_install if AUTO_INSTALL_CMDS.include?(current_cmd)
rescue UnknownArgumentError => e
raise InvalidOption, e.message
@@ -77,7 +89,7 @@ module Bundler
self.options ||= {}
unprinted_warnings = Bundler.ui.unprinted_warnings
Bundler.ui = UI::Shell.new(options)
- Bundler.ui.level = "debug" if options["verbose"]
+ Bundler.ui.level = "debug" if options[:verbose] || Bundler.settings[:verbose]
unprinted_warnings.each {|w| Bundler.ui.warn(w) }
end
@@ -92,7 +104,7 @@ module Bundler
primary_commands = ["install", "update", "cache", "exec", "config", "help"]
list = self.class.printable_commands(true)
- by_name = list.group_by {|name, _message| name.match(/^bundle (\w+)/)[1] }
+ by_name = list.group_by {|name, _message| name.match(/^bundler? (\w+)/)[1] }
utilities = by_name.keys.sort - primary_commands
primary_commands.map! {|name| (by_name[name] || raise("no primary command #{name}")).first }
utilities.map! {|name| by_name[name].first }
@@ -107,11 +119,37 @@ module Bundler
shell.say
self.class.send(:class_options_help, shell)
end
- default_task(Bundler.feature_flag.default_cli_command)
+
+ desc "install_or_cli_help", "Deprecated alias of install", hide: true
+ def install_or_cli_help
+ Bundler.ui.warn <<~MSG
+ `bundle install_or_cli_help` is a deprecated alias of `bundle install`.
+ It might be called due to the 'default_cli_command' being set to 'install_or_cli_help',
+ if so fix that by running `bundle config set default_cli_command install --global`.
+ MSG
+ invoke_other_command("install")
+ end
+
+ def self.default_command(meth = nil)
+ return super if meth
+
+ unless Bundler.settings[:default_cli_command]
+ Bundler.ui.info <<~MSG
+ In a future version of Bundler, running `bundle` without argument will no longer run `bundle install`.
+ Instead, the `cli_help` command will be displayed. Please use `bundle install` explicitly for scripts like CI/CD.
+ You can use the future behavior now with `bundle config set default_cli_command cli_help --global`,
+ or you can continue to use the current behavior with `bundle config set default_cli_command install --global`.
+ This message will be removed after a default_cli_command value is set.
+
+ MSG
+ end
+
+ Bundler.settings[:default_cli_command] || "install"
+ end
class_option "no-color", type: :boolean, desc: "Disable colorization in output"
- class_option "retry", type: :numeric, aliases: "-r", banner: "NUM",
- desc: "Specify the number of times you wish to attempt network commands"
+ class_option "retry", type: :numeric, aliases: "-r", banner: "NUM",
+ desc: "Specify the number of times you wish to attempt network commands"
class_option "verbose", type: :boolean, desc: "Enable verbose output mode", aliases: "-V"
def help(cli = nil)
@@ -130,7 +168,7 @@ module Bundler
if man_pages.include?(command)
man_page = man_pages[command]
- if Bundler.which("man") && !man_path.match?(%r{^file:/.+!/META-INF/jruby.home/.+})
+ if Bundler.which("man") && !man_path.match?(%r{^(?:file:/.+!|uri:classloader:)/META-INF/jruby.home/.+})
Kernel.exec("man", man_page)
else
puts File.read("#{man_path}/#{File.basename(man_page)}.ronn")
@@ -143,7 +181,7 @@ module Bundler
end
def self.handle_no_command_error(command, has_namespace = $thor_runner)
- if Bundler.feature_flag.plugins? && Bundler::Plugin.command?(command)
+ if Bundler.settings[:plugins] && Bundler::Plugin.command?(command)
return Bundler::Plugin.exec_command(command, ARGV[1..-1])
end
@@ -173,7 +211,7 @@ module Bundler
D
method_option "dry-run", type: :boolean, default: false, banner: "Lock the Gemfile"
method_option "gemfile", type: :string, banner: "Use the specified gemfile instead of Gemfile"
- method_option "path", type: :string, banner: "Specify a different path than the system default ($BUNDLE_PATH or $GEM_HOME).#{" Bundler will remember this value for future installs on this machine" unless Bundler.feature_flag.forget_cli_options?}"
+ method_option "path", type: :string, banner: "Specify a different path than the system default, namely, $BUNDLE_PATH or $GEM_HOME (removed)"
def check
remembered_flag_deprecation("path")
@@ -187,12 +225,11 @@ module Bundler
long_desc <<-D
Removes the given gems from the Gemfile while ensuring that the resulting Gemfile is still valid. If the gem is not found, Bundler prints a error message and if gem could not be removed due to any reason Bundler will display a warning.
D
- method_option "install", type: :boolean, banner: "Runs 'bundle install' after removing the gems from the Gemfile"
+ method_option "install", type: :boolean, banner: "Runs 'bundle install' after removing the gems from the Gemfile (removed)"
def remove(*gems)
if ARGV.include?("--install")
- message = "The `--install` flag has been deprecated. `bundle install` is triggered by default."
removed_message = "The `--install` flag has been removed. `bundle install` is triggered by default."
- SharedHelpers.major_deprecation(2, message, removed_message: removed_message)
+ raise InvalidOption, removed_message
end
require_relative "cli/remove"
@@ -210,42 +247,52 @@ module Bundler
If the bundle has already been installed, bundler will tell you so and then exit.
D
- method_option "binstubs", type: :string, lazy_default: "bin", banner: "Generate bin stubs for bundled gems to ./bin"
- method_option "clean", type: :boolean, banner: "Run bundle clean automatically after install"
- method_option "deployment", type: :boolean, banner: "Install using defaults tuned for deployment environments"
- method_option "frozen", type: :boolean, banner: "Do not allow the Gemfile.lock to be updated after this install"
+ method_option "binstubs", type: :string, lazy_default: "bin", banner: "Generate bin stubs for bundled gems to ./bin (removed)"
+ method_option "clean", type: :boolean, banner: "Run bundle clean automatically after install (removed)"
+ method_option "deployment", type: :boolean, banner: "Install using defaults tuned for deployment environments (removed)"
+ method_option "frozen", type: :boolean, banner: "Do not allow the Gemfile.lock to be updated after this install (removed)"
method_option "full-index", type: :boolean, banner: "Fall back to using the single-file index of all gems"
method_option "gemfile", type: :string, banner: "Use the specified gemfile instead of Gemfile"
method_option "jobs", aliases: "-j", type: :numeric, banner: "Specify the number of jobs to run in parallel"
- method_option "local", type: :boolean, banner: "Do not attempt to fetch gems remotely and use the gem cache instead"
+ method_option "local", type: :boolean, banner: "Do not attempt to fetch gems remotely and use the gem cache instead"
+ method_option "lockfile", type: :string, banner: "Use the specified lockfile instead of the default."
method_option "prefer-local", type: :boolean, banner: "Only attempt to fetch gems remotely if not present locally, even if newer versions are available remotely"
method_option "no-cache", type: :boolean, banner: "Don't update the existing gem cache."
- method_option "redownload", type: :boolean, aliases: "--force", banner: "Force downloading every gem."
- method_option "no-prune", type: :boolean, banner: "Don't remove stale gems from the cache."
- method_option "path", type: :string, banner: "Specify a different path than the system default ($BUNDLE_PATH or $GEM_HOME).#{" Bundler will remember this value for future installs on this machine" unless Bundler.feature_flag.forget_cli_options?}"
+ method_option "no-lock", type: :boolean, banner: "Don't create a lockfile."
+ method_option "force", type: :boolean, aliases: "--redownload", banner: "Force reinstalling every gem, even if already installed"
+ method_option "no-prune", type: :boolean, banner: "Don't remove stale gems from the cache (removed)."
+ method_option "path", type: :string, banner: "Specify a different path than the system default, namely, $BUNDLE_PATH or $GEM_HOME (removed)."
method_option "quiet", type: :boolean, banner: "Only output warnings and errors."
- method_option "shebang", type: :string, banner: "Specify a different shebang executable name than the default (usually 'ruby')"
+ method_option "shebang", type: :string, banner: "Specify a different shebang executable name than the default, usually 'ruby' (removed)"
method_option "standalone", type: :array, lazy_default: [], banner: "Make a bundle that can work without the Bundler runtime"
- method_option "system", type: :boolean, banner: "Install to the system location ($BUNDLE_PATH or $GEM_HOME) even if the bundle was previously installed somewhere else for this application"
- method_option "trust-policy", alias: "P", type: :string, banner: "Gem trust policy (like gem install -P). Must be one of " +
- Bundler.rubygems.security_policy_keys.join("|")
- method_option "without", type: :array, banner: "Exclude gems that are part of the specified named group."
- method_option "with", type: :array, banner: "Include gems that are part of the specified named group."
+ method_option "system", type: :boolean, banner: "Install to the system location ($BUNDLE_PATH or $GEM_HOME) even if the bundle was previously installed somewhere else for this application (removed)"
+ method_option "trust-policy", alias: "P", type: :string, banner: "Gem trust policy (like gem install -P). Must be one of #{Bundler.rubygems.security_policy_keys.join("|")}"
+ method_option "target-rbconfig", type: :string, banner: "Path to rbconfig.rb for the deployment target platform"
+ method_option "without", type: :array, banner: "Exclude gems that are part of the specified named group (removed)."
+ method_option "with", type: :array, banner: "Include gems that are part of the specified named group (removed)."
def install
- SharedHelpers.major_deprecation(2, "The `--force` option has been renamed to `--redownload`") if ARGV.include?("--force")
-
%w[clean deployment frozen no-prune path shebang without with].each do |option|
remembered_flag_deprecation(option)
end
print_remembered_flag_deprecation("--system", "path.system", "true") if ARGV.include?("--system")
- remembered_negative_flag_deprecation("no-deployment")
+ remembered_flag_deprecation("deployment", negative: true)
+
+ if ARGV.include?("--binstubs")
+ removed_message = "The --binstubs option has been removed in favor of `bundle binstubs --all`"
+ raise InvalidOption, removed_message
+ end
require_relative "cli/install"
+ options = self.options.dup
+ options["lockfile"] ||= ENV["BUNDLE_LOCKFILE"]
Bundler.settings.temporary(no_install: false) do
- Install.new(options.dup).run
+ Install.new(options).run
end
+ rescue GemfileNotFound => error
+ invoke_other_command("cli_help")
+ raise error # re-raise to show the error and get a failing exit status
end
map aliases_for("install")
@@ -260,21 +307,20 @@ module Bundler
method_option "gemfile", type: :string, banner: "Use the specified gemfile instead of Gemfile"
method_option "group", aliases: "-g", type: :array, banner: "Update a specific group"
method_option "jobs", aliases: "-j", type: :numeric, banner: "Specify the number of jobs to run in parallel"
- method_option "local", type: :boolean, banner: "Do not attempt to fetch gems remotely and use the gem cache instead"
- method_option "quiet", type: :boolean, banner: "Only output warnings and errors."
+ method_option "local", type: :boolean, banner: "Do not attempt to fetch gems remotely and use the gem cache instead"
+ method_option "quiet", type: :boolean, banner: "Only output warnings and errors."
method_option "source", type: :array, banner: "Update a specific source (and all gems associated with it)"
- method_option "redownload", type: :boolean, aliases: "--force", banner: "Force downloading every gem."
+ method_option "force", type: :boolean, aliases: "--redownload", banner: "Force reinstalling every gem, even if already installed"
method_option "ruby", type: :boolean, banner: "Update ruby specified in Gemfile.lock"
method_option "bundler", type: :string, lazy_default: "> 0.a", banner: "Update the locked version of bundler"
- method_option "patch", type: :boolean, banner: "Prefer updating only to next patch version"
- method_option "minor", type: :boolean, banner: "Prefer updating only to next minor version"
- method_option "major", type: :boolean, banner: "Prefer updating to next major version (default)"
+ method_option "patch", type: :boolean, banner: "Prefer updating only to next patch version"
+ method_option "minor", type: :boolean, banner: "Prefer updating only to next minor version"
+ method_option "major", type: :boolean, banner: "Prefer updating to next major version (default)"
method_option "pre", type: :boolean, banner: "Always choose the highest allowed version when updating gems, regardless of prerelease status"
method_option "strict", type: :boolean, banner: "Do not allow any gem to be updated past latest --patch | --minor | --major"
method_option "conservative", type: :boolean, banner: "Use bundle install conservative update behavior and do not allow shared dependencies to be updated."
method_option "all", type: :boolean, banner: "Update everything."
def update(*gems)
- SharedHelpers.major_deprecation(2, "The `--force` option has been renamed to `--redownload`") if ARGV.include?("--force")
require_relative "cli/update"
Bundler.settings.temporary(no_install: false) do
Update.new(options, gems).run
@@ -286,15 +332,12 @@ module Bundler
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."
+ 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 (removed)."
def show(gem_name = nil)
if ARGV.include?("--outdated")
- message = "the `--outdated` flag to `bundle show` was undocumented and will be removed without replacement"
- removed_message = "the `--outdated` flag to `bundle show` was undocumented and has been removed without replacement"
- SharedHelpers.major_deprecation(2, message, removed_message: removed_message)
+ removed_message = "the `--outdated` flag to `bundle show` has been removed in favor of `bundle show --verbose`"
+ raise InvalidOption, removed_message
end
require_relative "cli/show"
Show.new(options, gem_name).run
@@ -304,6 +347,7 @@ module Bundler
method_option "name-only", type: :boolean, banner: "print only the gem names"
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 "format", type: :string, banner: "format output ('json' is the only supported format)"
method_option "paths", type: :boolean, banner: "print the path to each gem in the bundle"
def list
require_relative "cli/list"
@@ -327,12 +371,14 @@ module Bundler
will create binstubs for all given gems.
D
method_option "force", type: :boolean, default: false, banner: "Overwrite existing binstubs if they exist"
- method_option "path", type: :string, lazy_default: "bin", banner: "Binstub destination directory (default bin)"
+ method_option "path", type: :string, lazy_default: "bin", banner: "Binstub destination directory, `bin` by default (removed)"
method_option "shebang", type: :string, banner: "Specify a different shebang executable name than the default (usually 'ruby')"
method_option "standalone", type: :boolean, banner: "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)
+ remembered_flag_deprecation("path", option_name: "bin")
+
require_relative "cli/binstubs"
Binstubs.new(options, gems).run
end
@@ -351,6 +397,7 @@ module Bundler
method_option "branch", type: :string
method_option "ref", type: :string
method_option "glob", type: :string, banner: "The location of a dependency's .gemspec, expanded within Ruby (single quotes recommended)"
+ method_option "quiet", type: :boolean, banner: "Only output warnings and errors."
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"
method_option "strict", type: :boolean, banner: "Adds strict declaration of version to gem"
@@ -397,17 +444,15 @@ module Bundler
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", type: :boolean, default: Bundler.settings[:cache_all], banner: "Include all sources (including path and git) (removed)."
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)."
+ method_option "cache-path", type: :string, banner: "Specify a different cache path than the default (vendor/cache)."
method_option "gemfile", type: :string, banner: "Use the specified gemfile instead of Gemfile"
method_option "no-install", type: :boolean, banner: "Don't install the gems, only update the cache."
- method_option "no-prune", type: :boolean, banner: "Don't remove stale gems from the cache."
- method_option "path", type: :string, banner: "Specify a different path than the system default ($BUNDLE_PATH or $GEM_HOME).#{" Bundler will remember this value for future installs on this machine" unless Bundler.feature_flag.forget_cli_options?}"
+ method_option "no-prune", type: :boolean, banner: "Don't remove stale gems from the cache (removed)."
+ method_option "path", type: :string, banner: "Specify a different path than the system default, namely, $BUNDLE_PATH or $GEM_HOME (removed)."
method_option "quiet", type: :boolean, banner: "Only output warnings and errors."
- method_option "frozen", type: :boolean, banner: "Do not allow the Gemfile.lock to be updated after this bundle cache operation's install"
+ method_option "frozen", type: :boolean, banner: "Do not allow the Gemfile.lock to be updated after this bundle cache operation's install (removed)"
long_desc <<-D
The cache command will copy the .gem files for every gem in the bundle into the
directory ./vendor/cache. If you then check that directory into your source
@@ -416,18 +461,19 @@ module Bundler
D
def cache
print_remembered_flag_deprecation("--all", "cache_all", "true") if ARGV.include?("--all")
+ print_remembered_flag_deprecation("--no-all", "cache_all", "false") if ARGV.include?("--no-all")
- if ARGV.include?("--path")
- message =
- "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"
+ %w[frozen no-prune].each do |option|
+ remembered_flag_deprecation(option)
+ end
+
+ if flag_passed?("--path")
removed_message =
"The `--path` flag has been removed because its semantics were 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."
- SharedHelpers.major_deprecation 2, message, removed_message: removed_message
+ "and `bundle config path` to configure the path where your gems are installed, " \
+ "and stop using this flag"
+ raise InvalidOption, removed_message
end
require_relative "cli/cache"
@@ -437,8 +483,8 @@ module Bundler
map aliases_for("cache")
desc "exec [OPTIONS]", "Run the command in context of the bundle"
- method_option :keep_file_descriptors, type: :boolean, default: true
- method_option :gemfile, type: :string, required: false
+ method_option :keep_file_descriptors, type: :boolean, default: true, banner: "Passes all file descriptors to the new processes. Default is true, and setting it to false is not permitted (removed)."
+ method_option :gemfile, type: :string, required: false, banner: "Use the specified gemfile instead of Gemfile"
long_desc <<-D
Exec runs a command, providing it access to the gems in the bundle. While using
bundle exec you can require and call the bundled gems as if they were installed
@@ -446,9 +492,8 @@ module Bundler
D
def exec(*args)
if ARGV.include?("--no-keep-file-descriptors")
- message = "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"
removed_message = "The `--no-keep-file-descriptors` has been removed. `bundle exec` no longer mess with your file descriptors. Close them in the exec'd script if you need to"
- SharedHelpers.major_deprecation(2, message, removed_message: removed_message)
+ raise InvalidOption, removed_message
end
require_relative "cli/exec"
@@ -479,25 +524,23 @@ module Bundler
Open.new(options, name).run
end
- unless Bundler.feature_flag.bundler_3_mode?
- desc "console [GROUP]", "Opens an IRB session with the bundle pre-loaded"
- def console(group = nil)
- require_relative "cli/console"
- Console.new(options, group).run
- end
+ desc "console [GROUP]", "Opens an IRB session with the bundle pre-loaded"
+ def console(group = nil)
+ require_relative "cli/console"
+ Console.new(options, group).run
end
desc "version", "Prints Bundler version information"
def version
cli_help = current_command.name == "cli_help"
if cli_help || ARGV.include?("version")
- build_info = " (#{BuildMetadata.built_at} commit #{BuildMetadata.git_commit_sha})"
+ build_info = " (#{BuildMetadata.timestamp} commit #{BuildMetadata.git_commit_sha})"
end
- if !cli_help && Bundler.feature_flag.print_only_version_number?
- Bundler.ui.info "#{Bundler::VERSION}#{build_info}"
+ if !cli_help
+ Bundler.ui.info "#{Bundler.verbose_version}#{build_info}"
else
- Bundler.ui.info "Bundler version #{Bundler::VERSION}#{build_info}"
+ Bundler.ui.info "Bundler version #{Bundler.verbose_version}#{build_info}"
end
end
@@ -517,76 +560,43 @@ module Bundler
end
end
- unless Bundler.feature_flag.bundler_3_mode?
- desc "viz [OPTIONS]", "Generates a visual dependency graph", hide: true
- long_desc <<-D
- Viz generates a PNG file of the current Gemfile as a dependency graph.
- Viz requires the ruby-graphviz gem (and its dependencies).
- The associated gems must also be installed via 'bundle install'.
- D
- method_option :file, type: :string, default: "gem_graph", aliases: "-f", desc: "The name to use for the generated file. see format option"
- method_option :format, type: :string, default: "png", aliases: "-F", desc: "This is output format option. Supported format is png, jpg, svg, dot ..."
- method_option :requirements, type: :boolean, default: false, aliases: "-R", desc: "Set to show the version of each required dependency."
- 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 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
+ desc "viz [OPTIONS]", "Generates a visual dependency graph", hide: true
+ def viz
+ SharedHelpers.feature_removed! "The `viz` command has been renamed to `graph` and moved to a plugin. See https://github.com/rubygems/bundler-graph"
end
- old_gem = instance_method(:gem)
-
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 --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: :string, desc: "Generate the boilerplate for C extension code.", enum: EXTENSIONS
- 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 --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, GitLab CI or CircleCI. Set a default with `bundle config set --global gem.ci (github|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 :exe, type: :boolean, default: false, aliases: ["--bin", "-b"], banner: "Generate a binary executable for your library."
+ method_option :coc, type: :boolean, banner: "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, lazy_default: [ENV["BUNDLER_EDITOR"], ENV["VISUAL"], ENV["EDITOR"]].find {|e| !e.nil? && !e.empty? }, banner: "Open generated gemspec in the specified editor (defaults to $EDITOR or $BUNDLER_EDITOR)"
+ method_option :ext, type: :string, banner: "Generate the boilerplate for C extension code.", enum: EXTENSIONS
+ method_option :git, type: :boolean, default: true, banner: "Initialize a git repo inside your library."
+ method_option :mit, type: :boolean, banner: "Generate an MIT license file. Set a default with `bundle config set --global gem.mit true`."
+ method_option :rubocop, type: :boolean, banner: "Add rubocop to the generated Rakefile and gemspec. Set a default with `bundle config set --global gem.rubocop true` (removed)."
+ method_option :changelog, type: :boolean, banner: "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", enum: %w[rspec minitest test-unit], 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"] || "", enum: %w[github gitlab circle], banner: "Generate CI configuration, either GitHub Actions, GitLab CI or CircleCI. Set a default with `bundle config set --global gem.ci (github|gitlab|circle)`"
+ method_option :linter, type: :string, lazy_default: Bundler.settings["gem.linter"] || "", enum: %w[rubocop standard], banner: "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 <your_username>`."
+ method_option :bundle, type: :boolean, default: Bundler.settings["gem.bundle"], banner: "Automatically run `bundle install` after creation. Set a default with `bundle config set --global gem.bundle true`"
def gem(name)
- end
+ require_relative "cli/gem"
- commands["gem"].tap do |gem_command|
- def gem_command.run(instance, args = [])
- arity = 1 # name
+ raise InvalidOption, "--rubocop has been removed, use --linter=rubocop" if ARGV.include?("--rubocop")
+ raise InvalidOption, "--no-rubocop has been removed, use --no-linter" if ARGV.include?("--no-rubocop")
- require_relative "cli/gem"
- cmd_args = args + [instance]
- cmd_args.unshift(instance.options)
+ cmd_args = args + [self]
+ cmd_args.unshift(options)
- cmd = begin
- Gem.new(*cmd_args)
- rescue ArgumentError => e
- instance.class.handle_argument_error(self, e, args, arity)
- end
-
- cmd.run
- end
+ Gem.new(*cmd_args).run
end
- undef_method(:gem)
- define_method(:gem, old_gem)
- private :gem
-
def self.source_root
File.expand_path("templates", __dir__)
end
- desc "clean [OPTIONS]", "Cleans up unused gems in your bundler directory", hide: true
+ desc "clean [OPTIONS]", "Cleans up unused gems in your bundler directory"
method_option "dry-run", type: :boolean, default: false, banner: "Only print out changes, do not clean gems"
method_option "force", type: :boolean, default: false, banner: "Forces cleaning up unused gems even if Bundler is configured to use globally installed gems. As a consequence, removes all system gems except for the ones in the current application."
def clean
@@ -602,26 +612,24 @@ module Bundler
end
desc "inject GEM VERSION", "Add the named gem, with version requirements, to the resolved Gemfile", hide: true
- method_option "source", type: :string, banner: "Install gem from the given source"
- method_option "group", type: :string, banner: "Install gem into a bundler group"
- def inject(name, version)
- SharedHelpers.major_deprecation 2, "The `inject` command has been replaced by the `add` command"
- require_relative "cli/inject"
- Inject.new(options.dup, name, version).run
+ def inject(*)
+ SharedHelpers.feature_removed! "The `inject` command has been replaced by the `add` command"
end
desc "lock", "Creates a lockfile without installing"
method_option "update", type: :array, lazy_default: true, banner: "ignore the existing lockfile, update all gems by default, or update list of given gems"
- method_option "local", type: :boolean, default: false, banner: "do not attempt to fetch remote gemspecs and use the local gem cache only"
- method_option "print", type: :boolean, default: false, banner: "print the lockfile to STDOUT instead of writing to the file system"
+ method_option "local", type: :boolean, default: false, banner: "do not attempt to fetch remote gemspecs and use the local gem cache only"
+ method_option "print", type: :boolean, default: false, banner: "print the lockfile to STDOUT instead of writing to the file system"
method_option "gemfile", type: :string, banner: "Use the specified gemfile instead of Gemfile"
method_option "lockfile", type: :string, default: nil, banner: "the path the lockfile should be written to"
method_option "full-index", type: :boolean, default: false, banner: "Fall back to using the single-file index of all gems"
+ method_option "add-checksums", type: :boolean, default: false, banner: "Adds checksums to the lockfile"
method_option "add-platform", type: :array, default: [], banner: "Add a new platform to the lockfile"
- method_option "remove-platform", type: :array, default: [], banner: "Remove a platform from the lockfile"
- method_option "patch", type: :boolean, banner: "If updating, prefer updating only to next patch version"
- method_option "minor", type: :boolean, banner: "If updating, prefer updating only to next minor version"
- method_option "major", type: :boolean, banner: "If updating, prefer updating to next major version (default)"
+ method_option "remove-platform", type: :array, default: [], banner: "Remove a platform from the lockfile"
+ method_option "normalize-platforms", type: :boolean, default: false, banner: "Normalize lockfile platforms"
+ method_option "patch", type: :boolean, banner: "If updating, prefer updating only to next patch version"
+ method_option "minor", type: :boolean, banner: "If updating, prefer updating only to next minor version"
+ method_option "major", type: :boolean, banner: "If updating, prefer updating to next major version (default)"
method_option "pre", type: :boolean, banner: "If updating, always choose the highest allowed version, regardless of prerelease status"
method_option "strict", type: :boolean, banner: "If updating, do not allow any gem to be updated past latest --patch | --minor | --major"
method_option "conservative", type: :boolean, banner: "If updating, use bundle install conservative update behavior and do not allow shared dependencies to be updated"
@@ -637,17 +645,8 @@ module Bundler
end
desc "doctor [OPTIONS]", "Checks the bundle for common problems"
- long_desc <<-D
- Doctor scans the OS dependencies of each of the gems requested in the Gemfile. If
- missing dependencies are detected, Bundler prints them and exits status 1.
- Otherwise, Bundler prints a success message and exits with a status of 0.
- D
- method_option "gemfile", type: :string, banner: "Use the specified gemfile instead of Gemfile"
- method_option "quiet", type: :boolean, banner: "Only output warnings and errors."
- def doctor
- require_relative "cli/doctor"
- Doctor.new(options).run
- end
+ require_relative "cli/doctor"
+ subcommand("doctor", Doctor)
desc "issue", "Learn how to report an issue in Bundler"
def issue
@@ -668,7 +667,7 @@ module Bundler
end
end
- if Bundler.feature_flag.plugins?
+ if Bundler.settings[:plugins]
require_relative "cli/plugin"
desc "plugin", "Manage the bundler plugins"
subcommand "plugin", Plugin
@@ -702,18 +701,15 @@ module Bundler
end
end
- def self.check_deprecated_ext_option(arguments)
- # when deprecated version of `--ext` is called
- # print out deprecation warning and pretend `--ext=c` was provided
- if deprecated_ext_value?(arguments)
- message = "Extensions can now be generated using C or Rust, so `--ext` with no arguments has been deprecated. Please select a language, e.g. `--ext=rust` to generate a Rust extension. This gem will now be generated as if `--ext=c` was used."
+ def self.check_invalid_ext_option(arguments)
+ # when invalid version of `--ext` is called
+ if invalid_ext_value?(arguments)
removed_message = "Extensions can now be generated using C or Rust, so `--ext` with no arguments has been removed. Please select a language, e.g. `--ext=rust` to generate a Rust extension."
- SharedHelpers.major_deprecation 2, message, removed_message: removed_message
- arguments[arguments.index("--ext")] = "--ext=c"
+ raise InvalidOption, removed_message
end
end
- def self.deprecated_ext_value?(arguments)
+ def self.invalid_ext_value?(arguments)
index = arguments.index("--ext")
next_argument = arguments[index + 1]
@@ -721,15 +717,15 @@ module Bundler
# for example `bundle gem hello --ext c`
return false if EXTENSIONS.include?(next_argument)
- # deprecated call when --ext is called with no value in last position
+ # invalid call when --ext is called with no value in last position
# for example `bundle gem hello_gem --ext`
return true if next_argument.nil?
- # deprecated call when --ext is followed by other parameter
+ # invalid call when --ext is followed by other parameter
# for example `bundle gem --ext --no-ci hello_gem`
return true if next_argument.start_with?("-")
- # deprecated call when --ext is followed by gem name
+ # invalid call when --ext is followed by gem name
# for example `bundle gem --ext hello_gem`
return true if next_argument
@@ -743,6 +739,19 @@ module Bundler
config[:current_command]
end
+ def invoke_other_command(name)
+ _, _, config = @_initializer
+ original_command = config[:current_command]
+ command = self.class.all_commands[name]
+ config[:current_command] = command
+ send(name)
+ ensure
+ config[:current_command] = original_command
+ end
+
+ def current_command=(command)
+ end
+
def print_command
return unless Bundler.ui.debug?
cmd = current_command
@@ -756,7 +765,7 @@ module Bundler
end
command << Thor::Options.to_switches(options_to_print.sort_by(&:first)).strip
command.reject!(&:empty?)
- Bundler.ui.info "Running `#{command * " "}` with bundler #{Bundler::VERSION}"
+ Bundler.ui.info "Running `#{command * " "}` with bundler #{Bundler.verbose_version}"
end
def warn_on_outdated_bundler
@@ -783,44 +792,30 @@ module Bundler
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)
+ def remembered_flag_deprecation(name, negative: false, option_name: nil)
option = current_command.options[name]
flag_name = option.switch_name
-
- 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
+ flag_name = "--no-" + flag_name.gsub(/\A--/, "") if negative
+ return unless flag_passed?(flag_name)
value = options[name]
value = value.join(" ").to_s if option.type == :array
value = "'#{value}'" unless option.type == :boolean
- print_remembered_flag_deprecation(flag_name, name.tr("-", "_"), value)
+ print_remembered_flag_deprecation(flag_name, option_name || name.tr("-", "_"), value)
end
def print_remembered_flag_deprecation(flag_name, option_name, option_value)
- message =
- "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 #{option_name} " \
- "#{option_value}`, and stop using this flag"
removed_message =
"The `#{flag_name}` flag has been removed because it relied on being " \
- "remembered across bundler invocations, which bundler will no longer " \
- "do. Instead please use `bundle config set #{option_name} " \
- "#{option_value}`, and stop using this flag"
- Bundler::SharedHelpers.major_deprecation 2, message, removed_message: removed_message
+ "remembered across bundler invocations, which bundler no longer does. " \
+ "Instead please use `bundle config set #{option_name} #{option_value}`, " \
+ "and stop using this flag"
+ raise InvalidOption, removed_message
+ end
+
+ def flag_passed?(name)
+ ARGV.any? {|arg| name == arg.split("=")[0] }
end
end
end
diff --git a/lib/bundler/cli/add.rb b/lib/bundler/cli/add.rb
index 002d9e1d33..9f17604096 100644
--- a/lib/bundler/cli/add.rb
+++ b/lib/bundler/cli/add.rb
@@ -12,6 +12,8 @@ module Bundler
end
def run
+ Bundler.ui.level = "warn" if options[:quiet]
+
validate_options!
inject_dependencies
perform_bundle_install unless options["skip-install"]
@@ -34,7 +36,17 @@ module Bundler
end
def validate_options!
- raise InvalidOption, "You can not specify `--strict` and `--optimistic` at the same time." if options[:strict] && options[:optimistic]
+ raise InvalidOption, "You cannot specify `--git` and `--github` at the same time." if options["git"] && options["github"]
+
+ unless options["git"] || options["github"]
+ raise InvalidOption, "You cannot specify `--branch` unless `--git` or `--github` is specified." if options["branch"]
+
+ raise InvalidOption, "You cannot specify `--ref` unless `--git` or `--github` is specified." if options["ref"]
+ end
+
+ raise InvalidOption, "You cannot specify `--branch` and `--ref` at the same time." if options["branch"] && options["ref"]
+
+ raise InvalidOption, "You cannot specify `--strict` and `--optimistic` at the same time." if options[:strict] && options[:optimistic]
# raise error when no gems are specified
raise InvalidOption, "Please specify gems to add." if gems.empty?
diff --git a/lib/bundler/cli/cache.rb b/lib/bundler/cli/cache.rb
index 2e63a16ec3..59605df847 100644
--- a/lib/bundler/cli/cache.rb
+++ b/lib/bundler/cli/cache.rb
@@ -10,17 +10,12 @@ module Bundler
def run
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"]
- 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)
+ Bundler.load.cache
end
end
@@ -33,11 +28,5 @@ module Bundler
options["no-cache"] = true
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
- end
end
end
diff --git a/lib/bundler/cli/check.rb b/lib/bundler/cli/check.rb
index 33d31cdd27..493eb3ec6a 100644
--- a/lib/bundler/cli/check.rb
+++ b/lib/bundler/cli/check.rb
@@ -15,9 +15,9 @@ module Bundler
definition.validate_runtime!
begin
- definition.resolve_only_locally!
+ definition.check!
not_installed = definition.missing_specs
- rescue GemNotFound, SolveFailure
+ rescue GemNotFound, GitError, SolveFailure
Bundler.ui.error "Bundler can't satisfy your Gemfile's dependencies."
Bundler.ui.warn "Install missing gems with `bundle install`."
exit 1
@@ -32,7 +32,7 @@ module Bundler
Bundler.ui.error "This bundle has been frozen, but there is no #{SharedHelpers.relative_lockfile_path} present"
exit 1
else
- Bundler.load.lock(preserve_unknown_sections: true) unless options[:"dry-run"]
+ definition.lock(true) unless options[:"dry-run"]
Bundler.ui.info "The Gemfile's dependencies are satisfied"
end
end
diff --git a/lib/bundler/cli/common.rb b/lib/bundler/cli/common.rb
index 7ef6deb2cf..2f332ff364 100644
--- a/lib/bundler/cli/common.rb
+++ b/lib/bundler/cli/common.rb
@@ -94,11 +94,14 @@ module Bundler
end
def self.gem_not_found_message(missing_gem_name, alternatives)
- require_relative "../similarity_detector"
message = "Could not find gem '#{missing_gem_name}'."
alternate_names = alternatives.map {|a| a.respond_to?(:name) ? a.name : a }
- suggestions = SimilarityDetector.new(alternate_names).similar_word_list(missing_gem_name)
- message += "\nDid you mean #{suggestions}?" if suggestions
+ if alternate_names.include?(missing_gem_name.downcase)
+ message += "\nDid you mean '#{missing_gem_name.downcase}'?"
+ elsif defined?(DidYouMean::SpellChecker)
+ suggestions = DidYouMean::SpellChecker.new(dictionary: alternate_names).correct(missing_gem_name)
+ message += "\nDid you mean #{word_list(suggestions)}?" unless suggestions.empty?
+ end
message
end
@@ -130,9 +133,23 @@ module Bundler
def self.clean_after_install?
clean = Bundler.settings[:clean]
return clean unless clean.nil?
- clean ||= Bundler.feature_flag.auto_clean_without_path? && Bundler.settings[:path].nil?
+ clean ||= Bundler.feature_flag.bundler_5_mode? && Bundler.settings[:path].nil?
clean &&= !Bundler.use_system_gems?
clean
end
+
+ def self.word_list(words)
+ if words.empty?
+ return ""
+ end
+
+ words = words.map {|word| "'#{word}'" }
+
+ if words.length == 1
+ return words[0]
+ end
+
+ [words[0..-2].join(", "), words[-1]].join(" or ")
+ end
end
end
diff --git a/lib/bundler/cli/config.rb b/lib/bundler/cli/config.rb
index 77b502fe60..6a77e4a65e 100644
--- a/lib/bundler/cli/config.rb
+++ b/lib/bundler/cli/config.rb
@@ -26,8 +26,7 @@ module Bundler
end
message = "Using the `config` command without a subcommand [list, get, set, unset] is deprecated and will be removed in the future. Use `bundle #{new_args.join(" ")}` instead."
- removed_message = "Using the `config` command without a subcommand [list, get, set, unset] is has been removed. Use `bundle #{new_args.join(" ")}` instead."
- SharedHelpers.major_deprecation 3, message, removed_message: removed_message
+ SharedHelpers.feature_deprecated! message
Base.new(options, name, value, self).run
end
diff --git a/lib/bundler/cli/console.rb b/lib/bundler/cli/console.rb
index 840cf14fd7..2d1a2ce458 100644
--- a/lib/bundler/cli/console.rb
+++ b/lib/bundler/cli/console.rb
@@ -9,10 +9,6 @@ module Bundler
end
def run
- message = "bundle console will be replaced by `bin/console` generated by `bundle gem <name>`"
- removed_message = "bundle console has been replaced by `bin/console` generated by `bundle gem <name>`"
- Bundler::SharedHelpers.major_deprecation 2, message, removed_message: removed_message
-
group ? Bundler.require(:default, *group.split(" ").map!(&:to_sym)) : Bundler.require
ARGV.clear
@@ -24,9 +20,19 @@ module Bundler
require name
get_constant(name)
rescue LoadError
- Bundler.ui.error "Couldn't load console #{name}, falling back to irb"
- require "irb"
- get_constant("irb")
+ if name == "irb"
+ if defined?(Gem::BUNDLED_GEMS) && Gem::BUNDLED_GEMS.respond_to?(:force_activate)
+ Gem::BUNDLED_GEMS.force_activate "irb"
+ require name
+ return get_constant(name)
+ end
+ Bundler.ui.error "#{name} is not available"
+ exit 1
+ else
+ Bundler.ui.error "Couldn't load console #{name}, falling back to irb"
+ name = "irb"
+ retry
+ end
end
def get_constant(name)
@@ -36,9 +42,6 @@ module Bundler
"irb" => :IRB,
}[name]
Object.const_get(const_name)
- rescue NameError
- Bundler.ui.error "Could not find constant #{const_name}"
- exit 1
end
end
end
diff --git a/lib/bundler/cli/doctor.rb b/lib/bundler/cli/doctor.rb
index 1f6fc93c16..5fd6a73d91 100644
--- a/lib/bundler/cli/doctor.rb
+++ b/lib/bundler/cli/doctor.rb
@@ -1,157 +1,33 @@
# frozen_string_literal: true
-require "rbconfig"
-require "shellwords"
-require "fiddle"
-
module Bundler
- class CLI::Doctor
- DARWIN_REGEX = /\s+(.+) \(compatibility /
- LDD_REGEX = /\t\S+ => (\S+) \(\S+\)/
-
- attr_reader :options
-
- def initialize(options)
- @options = options
- end
-
- def otool_available?
- Bundler.which("otool")
- end
-
- def ldd_available?
- Bundler.which("ldd")
- end
-
- def dylibs_darwin(path)
- 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.shellescape}`.chomp
- output.split("\n").map do |l|
- match = l.match(LDD_REGEX)
- next if match.nil?
- match.captures[0]
- end.compact
- end
-
- def dylibs(path)
- case RbConfig::CONFIG["host_os"]
- when /darwin/
- return [] unless otool_available?
- dylibs_darwin(path)
- when /(linux|solaris|bsd)/
- return [] unless ldd_available?
- dylibs_ldd(path)
- else # Windows, etc.
- Bundler.ui.warn("Dynamic library check not supported on this platform.")
- []
- end
- end
-
- def bundles_for_gem(spec)
- Dir.glob("#{spec.full_gem_path}/**/*.bundle")
- end
-
- def check!
- require_relative "check"
- Bundler::CLI::Check.new({}).run
- end
-
- def run
- Bundler.ui.level = "warn" if options[:quiet]
- Bundler.settings.validate!
- check!
-
- definition = Bundler.definition
- broken_links = {}
-
- definition.specs.each do |spec|
- bundles_for_gem(spec).each do |bundle|
- bad_paths = dylibs(bundle).select do |f|
- Fiddle.dlopen(f)
- false
- rescue Fiddle::DLError
- true
- end
- if bad_paths.any?
- broken_links[spec] ||= []
- broken_links[spec].concat(bad_paths)
- end
- end
- end
-
- permissions_valid = check_home_permissions
-
- if broken_links.any?
- message = "The following gems are missing OS dependencies:"
- broken_links.map do |spec, paths|
- paths.uniq.map do |path|
- "\n * #{spec.name}: #{path}"
- end
- end.flatten.sort.each {|m| message += m }
- raise ProductionError, message
- elsif !permissions_valid
- Bundler.ui.info "No issues found with the installed bundle"
- end
- end
-
- 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.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
- files_not_readable_or_writable << f
- end
- elsif File.stat(f).uid != Process.uid
- files_not_owned_by_current_user_but_still_rw << f
- end
- 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 - ")}"
-
- ok = false
- end
-
- if files_not_rw_and_owned_by_different_user.any?
- Bundler.ui.warn "Files exist in the Bundler home that are owned by another " \
- "user, and are not readable/writable. These files are:\n - #{files_not_rw_and_owned_by_different_user.join("\n - ")}"
-
- ok = false
- end
-
- if files_not_readable_or_writable.any?
- Bundler.ui.warn "Files exist in the Bundler home that are not " \
- "readable/writable by the current user. These files are:\n - #{files_not_readable_or_writable.join("\n - ")}"
-
- ok = false
- end
-
- ok
+ class CLI::Doctor < Thor
+ default_command(:diagnose)
+
+ desc "diagnose [OPTIONS]", "Checks the bundle for common problems"
+ long_desc <<-D
+ Doctor scans the OS dependencies of each of the gems requested in the Gemfile. If
+ missing dependencies are detected, Bundler prints them and exits status 1.
+ Otherwise, Bundler prints a success message and exits with a status of 0.
+ D
+ method_option "gemfile", type: :string, banner: "Use the specified gemfile instead of Gemfile"
+ method_option "quiet", type: :boolean, banner: "Only output warnings and errors."
+ method_option "ssl", type: :boolean, default: false, banner: "Diagnose SSL problems."
+ def diagnose
+ require_relative "doctor/diagnose"
+ Diagnose.new(options).run
+ end
+
+ desc "ssl [OPTIONS]", "Diagnose SSL problems"
+ long_desc <<-D
+ Diagnose SSL problems, especially related to certificates or TLS version while connecting to https://rubygems.org.
+ D
+ method_option "host", type: :string, banner: "The host to diagnose."
+ method_option "tls-version", type: :string, banner: "Specify the SSL/TLS version when running the diagnostic. Accepts either <1.1> or <1.2>"
+ method_option "verify-mode", type: :string, banner: "Specify the mode used for certification verification. Accepts either <peer> or <none>"
+ def ssl
+ require_relative "doctor/ssl"
+ SSL.new(options).run
end
end
end
diff --git a/lib/bundler/cli/doctor/diagnose.rb b/lib/bundler/cli/doctor/diagnose.rb
new file mode 100644
index 0000000000..a878025dda
--- /dev/null
+++ b/lib/bundler/cli/doctor/diagnose.rb
@@ -0,0 +1,167 @@
+# frozen_string_literal: true
+
+require "rbconfig"
+require "shellwords"
+
+module Bundler
+ class CLI::Doctor::Diagnose
+ DARWIN_REGEX = /\s+(.+) \(compatibility /
+ LDD_REGEX = /\t\S+ => (\S+) \(\S+\)/
+
+ attr_reader :options
+
+ def initialize(options)
+ @options = options
+ end
+
+ def otool_available?
+ Bundler.which("otool")
+ end
+
+ def ldd_available?
+ Bundler.which("ldd")
+ end
+
+ def dylibs_darwin(path)
+ output = `/usr/bin/otool -L #{path.shellescape}`.chomp
+ dylibs = output.split("\n")[1..-1].filter_map {|l| l.match(DARWIN_REGEX)&.match(1) }.uniq
+ # ignore @rpath and friends
+ dylibs.reject {|dylib| dylib.start_with? "@" }
+ end
+
+ def dylibs_ldd(path)
+ output = `/usr/bin/ldd #{path.shellescape}`.chomp
+ output.split("\n").filter_map do |l|
+ match = l.match(LDD_REGEX)
+ next if match.nil?
+ match.captures[0]
+ end
+ end
+
+ def dylibs(path)
+ case RbConfig::CONFIG["host_os"]
+ when /darwin/
+ return [] unless otool_available?
+ dylibs_darwin(path)
+ when /(linux|solaris|bsd)/
+ return [] unless ldd_available?
+ dylibs_ldd(path)
+ else # Windows, etc.
+ Bundler.ui.warn("Dynamic library check not supported on this platform.")
+ []
+ end
+ end
+
+ def bundles_for_gem(spec)
+ Dir.glob("#{spec.full_gem_path}/**/*.bundle")
+ end
+
+ def lookup_with_fiddle(path)
+ require "fiddle"
+ Fiddle.dlopen(path)
+ false
+ rescue Fiddle::DLError
+ true
+ end
+
+ def check!
+ require_relative "../check"
+ Bundler::CLI::Check.new({}).run
+ end
+
+ def diagnose_ssl
+ require_relative "ssl"
+ Bundler::CLI::Doctor::SSL.new({}).run
+ end
+
+ def run
+ Bundler.ui.level = "warn" if options[:quiet]
+ Bundler.settings.validate!
+ check!
+ diagnose_ssl if options[:ssl]
+
+ definition = Bundler.definition
+ broken_links = {}
+
+ definition.specs.each do |spec|
+ bundles_for_gem(spec).each do |bundle|
+ bad_paths = dylibs(bundle).select do |f|
+ lookup_with_fiddle(f)
+ end
+ if bad_paths.any?
+ broken_links[spec] ||= []
+ broken_links[spec].concat(bad_paths)
+ end
+ end
+ end
+
+ permissions_valid = check_home_permissions
+
+ if broken_links.any?
+ message = "The following gems are missing OS dependencies:"
+ broken_links.flat_map do |spec, paths|
+ paths.uniq.map do |path|
+ "\n * #{spec.name}: #{path}"
+ end
+ end.sort.each {|m| message += m }
+ raise ProductionError, message
+ elsif permissions_valid
+ Bundler.ui.info "No issues found with the installed bundle"
+ end
+ end
+
+ private
+
+ def check_home_permissions
+ require "find"
+ files_not_readable = []
+ files_not_readable_and_owned_by_different_user = []
+ files_not_owned_by_current_user_but_still_readable = []
+ broken_symlinks = []
+ Find.find(Bundler.bundle_path.to_s).each do |f|
+ if !File.exist?(f)
+ broken_symlinks << f
+ elsif !File.readable?(f)
+ if File.stat(f).uid != Process.uid
+ files_not_readable_and_owned_by_different_user << f
+ else
+ files_not_readable << f
+ end
+ elsif File.stat(f).uid != Process.uid
+ files_not_owned_by_current_user_but_still_readable << f
+ end
+ 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_readable.any?
+ Bundler.ui.warn "Files exist in the Bundler home that are owned by another " \
+ "user, but are still readable. These files are:\n - #{files_not_owned_by_current_user_but_still_readable.join("\n - ")}"
+
+ ok = false
+ end
+
+ if files_not_readable_and_owned_by_different_user.any?
+ Bundler.ui.warn "Files exist in the Bundler home that are owned by another " \
+ "user, and are not readable. These files are:\n - #{files_not_readable_and_owned_by_different_user.join("\n - ")}"
+
+ ok = false
+ end
+
+ if files_not_readable.any?
+ Bundler.ui.warn "Files exist in the Bundler home that are not " \
+ "readable by the current user. These files are:\n - #{files_not_readable.join("\n - ")}"
+
+ ok = false
+ end
+
+ ok
+ end
+ end
+end
diff --git a/lib/bundler/cli/doctor/ssl.rb b/lib/bundler/cli/doctor/ssl.rb
new file mode 100644
index 0000000000..21fc4edf2d
--- /dev/null
+++ b/lib/bundler/cli/doctor/ssl.rb
@@ -0,0 +1,249 @@
+# frozen_string_literal: true
+
+require "rubygems/remote_fetcher"
+require "uri"
+
+module Bundler
+ class CLI::Doctor::SSL
+ attr_reader :options
+
+ def initialize(options)
+ @options = options
+ end
+
+ def run
+ return unless openssl_installed?
+
+ output_ssl_environment
+ bundler_success = bundler_connection_successful?
+ rubygem_success = rubygem_connection_successful?
+
+ return unless net_http_connection_successful?
+
+ Explanation.summarize(bundler_success, rubygem_success, host)
+ end
+
+ private
+
+ def host
+ @options[:host] || "rubygems.org"
+ end
+
+ def tls_version
+ @options[:"tls-version"].then do |version|
+ "TLS#{version.sub(".", "_")}".to_sym if version
+ end
+ end
+
+ def verify_mode
+ mode = @options[:"verify-mode"] || :peer
+
+ @verify_mode ||= mode.then {|mod| OpenSSL::SSL.const_get("verify_#{mod}".upcase) }
+ end
+
+ def uri
+ @uri ||= URI("https://#{host}")
+ end
+
+ def openssl_installed?
+ require "openssl"
+
+ true
+ rescue LoadError
+ Bundler.ui.warn(<<~MSG)
+ Oh no! Your Ruby doesn't have OpenSSL, so it can't connect to #{host}.
+ You'll need to recompile or reinstall Ruby with OpenSSL support and try again.
+ MSG
+
+ false
+ end
+
+ def output_ssl_environment
+ Bundler.ui.info(<<~MESSAGE)
+ Here's your OpenSSL environment:
+
+ OpenSSL: #{OpenSSL::VERSION}
+ Compiled with: #{OpenSSL::OPENSSL_VERSION}
+ Loaded with: #{OpenSSL::OPENSSL_LIBRARY_VERSION}
+ MESSAGE
+ end
+
+ def bundler_connection_successful?
+ Bundler.ui.info("\nTrying connections to #{uri}:\n")
+
+ bundler_uri = Gem::URI(uri.to_s)
+ Bundler::Fetcher.new(
+ Bundler::Source::Rubygems::Remote.new(bundler_uri)
+ ).send(:connection).request(bundler_uri)
+
+ Bundler.ui.info("Bundler: success")
+
+ true
+ rescue StandardError => error
+ Bundler.ui.warn("Bundler: failed (#{Explanation.explain_bundler_or_rubygems_error(error)})")
+
+ false
+ end
+
+ def rubygem_connection_successful?
+ Gem::RemoteFetcher.fetcher.fetch_path(uri)
+ Bundler.ui.info("RubyGems: success")
+
+ true
+ rescue StandardError => error
+ Bundler.ui.warn("RubyGems: failed (#{Explanation.explain_bundler_or_rubygems_error(error)})")
+
+ false
+ end
+
+ def net_http_connection_successful?
+ ::Gem::Net::HTTP.new(uri.host, uri.port).tap do |http|
+ http.use_ssl = true
+ http.min_version = tls_version
+ http.max_version = tls_version
+ http.verify_mode = verify_mode
+ end.start
+
+ Bundler.ui.info("Ruby net/http: success")
+ warn_on_unsupported_tls12
+
+ true
+ rescue StandardError => error
+ Bundler.ui.warn(<<~MSG)
+ Ruby net/http: failed
+
+ Unfortunately, this Ruby can't connect to #{host}.
+
+ #{Explanation.explain_net_http_error(error, host, tls_version)}
+ MSG
+
+ false
+ end
+
+ def warn_on_unsupported_tls12
+ ctx = OpenSSL::SSL::SSLContext.new
+ supported = true
+
+ if ctx.respond_to?(:min_version=)
+ begin
+ ctx.min_version = ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
+ rescue OpenSSL::SSL::SSLError, NameError
+ supported = false
+ end
+ else
+ supported = OpenSSL::SSL::SSLContext::METHODS.include?(:TLSv1_2) # rubocop:disable Naming/VariableNumber
+ end
+
+ Bundler.ui.warn(<<~EOM) unless supported
+
+ WARNING: Although your Ruby can connect to #{host} today, your OpenSSL is very old!
+ WARNING: You will need to upgrade OpenSSL to use #{host}.
+
+ EOM
+ end
+
+ module Explanation
+ extend self
+
+ def explain_bundler_or_rubygems_error(error)
+ case error.message
+ when /certificate verify failed/
+ "certificate verification"
+ when /read server hello A/
+ "SSL/TLS protocol version mismatch"
+ when /tlsv1 alert protocol version/
+ "requested TLS version is too old"
+ else
+ error.message
+ end
+ end
+
+ def explain_net_http_error(error, host, tls_version)
+ case error.message
+ # Check for certificate errors
+ when /certificate verify failed/
+ <<~MSG
+ #{show_ssl_certs}
+ Your Ruby can't connect to #{host} because you are missing the certificate files OpenSSL needs to verify you are connecting to the genuine #{host} servers.
+ MSG
+ # Check for TLS version errors
+ when /read server hello A/, /tlsv1 alert protocol version/
+ if tls_version.to_s == "TLS1_3"
+ "Your Ruby can't connect to #{host} because #{tls_version} isn't supported yet.\n"
+ else
+ <<~MSG
+ Your Ruby can't connect to #{host} because your version of OpenSSL is too old.
+ You'll need to upgrade your OpenSSL install and/or recompile Ruby to use a newer OpenSSL.
+ MSG
+ end
+ # OpenSSL doesn't support TLS version specified by argument
+ when /unknown SSL method/
+ "Your Ruby can't connect because #{tls_version} isn't supported by your version of OpenSSL."
+ else
+ <<~MSG
+ Even worse, we're not sure why.
+
+ Here's the full error information:
+ #{error.class}: #{error.message}
+ #{error.backtrace.join("\n ")}
+
+ You might have more luck using Mislav's SSL doctor.rb script. You can get it here:
+ https://github.com/mislav/ssl-tools/blob/8b3dec4/doctor.rb
+
+ Read more about the script and how to use it in this blog post:
+ https://mislav.net/2013/07/ruby-openssl/
+ MSG
+ end
+ end
+
+ def summarize(bundler_success, rubygems_success, host)
+ guide_url = "http://ruby.to/ssl-check-failed"
+
+ message = if bundler_success && rubygems_success
+ <<~MSG
+ Hooray! This Ruby can connect to #{host}.
+ You are all set to use Bundler and RubyGems.
+
+ MSG
+ elsif !bundler_success && !rubygems_success
+ <<~MSG
+ For some reason, your Ruby installation can connect to #{host}, but neither RubyGems nor Bundler can.
+ The most likely fix is to manually upgrade RubyGems by following the instructions at #{guide_url}.
+ After you've done that, run `gem install bundler` to upgrade Bundler, and then run this script again to make sure everything worked. ❣
+
+ MSG
+ elsif !bundler_success
+ <<~MSG
+ Although your Ruby installation and RubyGems can both connect to #{host}, Bundler is having trouble.
+ The most likely way to fix this is to upgrade Bundler by running `gem install bundler`.
+ Run this script again after doing that to make sure everything is all set.
+ If you're still having trouble, check out the troubleshooting guide at #{guide_url}.
+
+ MSG
+ else
+ <<~MSG
+ It looks like Ruby and Bundler can connect to #{host}, but RubyGems itself cannot.
+ You can likely solve this by manually downloading and installing a RubyGems update.
+ Visit #{guide_url} for instructions on how to manually upgrade RubyGems.
+
+ MSG
+ end
+
+ Bundler.ui.info("\n#{message}")
+ end
+
+ private
+
+ def show_ssl_certs
+ ssl_cert_file = ENV["SSL_CERT_FILE"] || OpenSSL::X509::DEFAULT_CERT_FILE
+ ssl_cert_dir = ENV["SSL_CERT_DIR"] || OpenSSL::X509::DEFAULT_CERT_DIR
+
+ <<~MSG
+ Below affect only Ruby net/http connections:
+ SSL_CERT_FILE: #{File.exist?(ssl_cert_file) ? "exists #{ssl_cert_file}" : "is missing #{ssl_cert_file}"}
+ SSL_CERT_DIR: #{Dir.exist?(ssl_cert_dir) ? "exists #{ssl_cert_dir}" : "is missing #{ssl_cert_dir}"}
+ MSG
+ end
+ end
+ end
+end
diff --git a/lib/bundler/cli/exec.rb b/lib/bundler/cli/exec.rb
index f81cd5d2c4..2fdc416286 100644
--- a/lib/bundler/cli/exec.rb
+++ b/lib/bundler/cli/exec.rb
@@ -19,10 +19,13 @@ module Bundler
validate_cmd!
SharedHelpers.set_bundle_environment
if bin_path = Bundler.which(cmd)
- if !Bundler.settings[:disable_exec_load] && ruby_shebang?(bin_path)
- return kernel_load(bin_path, *args)
+ if !Bundler.settings[:disable_exec_load] && directly_loadable?(bin_path)
+ bin_path.delete_suffix!(".bat") if Gem.win_platform?
+ kernel_load(bin_path, *args)
+ else
+ bin_path = "./" + bin_path unless File.absolute_path?(bin_path)
+ kernel_exec(bin_path, *args)
end
- kernel_exec(bin_path, *args)
else
# exec using the given command
kernel_exec(cmd, *args)
@@ -68,6 +71,29 @@ module Bundler
"#{file} #{args.join(" ")}".strip
end
+ def directly_loadable?(file)
+ if Gem.win_platform?
+ script_wrapper?(file)
+ else
+ ruby_shebang?(file)
+ end
+ end
+
+ def script_wrapper?(file)
+ script_file = file.delete_suffix(".bat")
+ return false unless File.exist?(script_file)
+
+ if File.zero?(script_file)
+ Bundler.ui.warn "#{script_file} is empty"
+ return false
+ end
+
+ header = File.open(file, "r") {|f| f.read(32) }
+ ruby_exe = "#{RbConfig::CONFIG["RUBY_INSTALL_NAME"]}#{RbConfig::CONFIG["EXEEXT"]}"
+ ruby_exe = "ruby.exe" if ruby_exe.empty?
+ header.include?(ruby_exe)
+ end
+
def ruby_shebang?(file)
possibilities = [
"#!/usr/bin/env ruby\n",
diff --git a/lib/bundler/cli/fund.rb b/lib/bundler/cli/fund.rb
index 52db5aef68..ad7f31f3d6 100644
--- a/lib/bundler/cli/fund.rb
+++ b/lib/bundler/cli/fund.rb
@@ -16,7 +16,7 @@ module Bundler
deps = if groups.any?
Bundler.definition.dependencies_for(groups)
else
- Bundler.definition.current_dependencies
+ Bundler.definition.requested_dependencies
end
fund_info = deps.each_with_object([]) do |dep, arr|
diff --git a/lib/bundler/cli/gem.rb b/lib/bundler/cli/gem.rb
index b6571d0e86..236ce530ec 100644
--- a/lib/bundler/cli/gem.rb
+++ b/lib/bundler/cli/gem.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-require "pathname"
-
module Bundler
class CLI
Bundler.require_thor_actions
@@ -15,6 +13,8 @@ module Bundler
"test-unit" => "3.0",
}.freeze
+ DEFAULT_GITHUB_USERNAME = "[USERNAME]"
+
attr_reader :options, :gem_name, :thor, :name, :target, :extension
def initialize(options, gem_name, thor)
@@ -26,12 +26,11 @@ module Bundler
thor.destination_root = nil
@name = @gem_name
- @target = SharedHelpers.pwd.join(gem_name)
+ @target = Pathname.new(SharedHelpers.pwd).join(gem_name)
@extension = options[:ext]
validate_ext_name if @extension
- validate_rust_builder_rubygems_version if @extension == "rust"
end
def run
@@ -48,13 +47,16 @@ module Bundler
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 = github_username(git_username)
- github_username = if options[:github_username].nil?
- git_username
- elsif options[:github_username] == false
- ""
+ if github_username.empty?
+ homepage_uri = "TODO: Put your gem's website or public repo URL here."
+ source_code_uri = "TODO: Put your gem's public repo URL here."
+ changelog_uri = "TODO: Put your gem's CHANGELOG.md URL here."
else
- options[:github_username]
+ homepage_uri = "https://github.com/#{github_username}/#{name}"
+ source_code_uri = "https://github.com/#{github_username}/#{name}"
+ changelog_uri = "https://github.com/#{github_username}/#{name}/blob/main/CHANGELOG.md"
end
config = {
@@ -69,17 +71,22 @@ module Bundler
test: options[:test],
ext: extension,
exe: options[:exe],
+ bundle: options[:bundle],
bundler_version: bundler_dependency_version,
git: use_git,
- github_username: github_username.empty? ? "[USERNAME]" : github_username,
+ github_username: github_username.empty? ? DEFAULT_GITHUB_USERNAME : github_username,
required_ruby_version: required_ruby_version,
rust_builder_required_rubygems_version: rust_builder_required_rubygems_version,
minitest_constant_name: minitest_constant_name,
+ ignore_paths: %w[bin/],
+ homepage_uri: homepage_uri,
+ source_code_uri: source_code_uri,
+ changelog_uri: changelog_uri,
}
ensure_safe_gem_name(name, constant_array)
templates = {
- "#{Bundler.preferred_gemfile_name}.tt" => Bundler.preferred_gemfile_name,
+ "Gemfile.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",
@@ -95,7 +102,18 @@ module Bundler
bin/setup
]
- templates.merge!("gitignore.tt" => ".gitignore") if use_git
+ case Bundler.preferred_gemfile_name
+ when "Gemfile"
+ config[:ignore_paths] << "Gemfile"
+ when "gems.rb"
+ config[:ignore_paths] << "gems.rb"
+ config[:ignore_paths] << "gems.locked"
+ end
+
+ if use_git
+ templates.merge!("gitignore.tt" => ".gitignore")
+ config[:ignore_paths] << ".gitignore"
+ end
if test_framework = ask_and_set_test_framework
config[:test] = test_framework
@@ -109,6 +127,8 @@ module Bundler
"spec/newgem_spec.rb.tt" => "spec/#{namespaced_path}_spec.rb"
)
config[:test_task] = :spec
+ config[:ignore_paths] << ".rspec"
+ config[:ignore_paths] << "spec/"
when "minitest"
# Generate path for minitest target file (FileList["test/**/test_*.rb"])
# foo => test/test_foo.rb
@@ -123,12 +143,14 @@ module Bundler
"test/minitest/test_newgem.rb.tt" => "test/#{minitest_namespaced_path}.rb"
)
config[:test_task] = :test
+ config[:ignore_paths] << "test/"
when "test-unit"
templates.merge!(
"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
+ config[:ignore_paths] << "test/"
end
end
@@ -136,19 +158,19 @@ module Bundler
case config[:ci]
when "github"
templates.merge!("github/workflows/main.yml.tt" => ".github/workflows/main.yml")
- config[:ci_config_path] = ".github "
+ config[:ignore_paths] << ".github/"
when "gitlab"
templates.merge!("gitlab-ci.yml.tt" => ".gitlab-ci.yml")
- config[:ci_config_path] = ".gitlab-ci.yml "
+ config[:ignore_paths] << ".gitlab-ci.yml"
when "circle"
templates.merge!("circleci/config.yml.tt" => ".circleci/config.yml")
- config[:ci_config_path] = ".circleci "
+ config[:ignore_paths] << ".circleci/"
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 " \
- "for free as long as they admit you created it. You can read more about the MIT license " \
- "at https://choosealicense.com/licenses/mit.")
+ "Using a MIT license means that any other developer or company will be legally allowed " \
+ "to use your code for free as long as they admit you created it. You can read more about " \
+ "the MIT license at https://choosealicense.com/licenses/mit.")
config[:mit] = true
Bundler.ui.info "MIT License enabled in config"
templates.merge!("LICENSE.txt.tt" => "LICENSE.txt")
@@ -156,12 +178,8 @@ module Bundler
if ask_and_set(:coc, "Do you want to include a code of conduct in gems you generate?",
"Codes of conduct can increase contributions to your project by contributors who " \
- "prefer collaborative, safe spaces. You can read more about the code of conduct at " \
- "contributor-covenant.org. Having a code of conduct means agreeing to the responsibility " \
- "of enforcing it, so be sure that you are prepared to do that. Be sure that your email " \
- "address is specified as a contact in the generated code of conduct so that people know " \
- "who to contact in case of a violation. For suggestions about " \
- "how to enforce codes of conduct, see https://bit.ly/coc-enforcement.")
+ "prefer safe, respectful, productive, and collaborative spaces. \n" \
+ "See https://github.com/ruby/rubygems/blob/master/CODE_OF_CONDUCT.md")
config[:coc] = true
Bundler.ui.info "Code of conduct enabled in config"
templates.merge!("CODE_OF_CONDUCT.md.tt" => "CODE_OF_CONDUCT.md")
@@ -185,13 +203,18 @@ module Bundler
config[:linter_version] = rubocop_version
Bundler.ui.info "RuboCop enabled in config"
templates.merge!("rubocop.yml.tt" => ".rubocop.yml")
+ config[:ignore_paths] << ".rubocop.yml"
when "standard"
config[:linter_version] = standard_version
Bundler.ui.info "Standard enabled in config"
templates.merge!("standard.yml.tt" => ".standard.yml")
+ config[:ignore_paths] << ".standard.yml"
end
- templates.merge!("exe/newgem.tt" => "exe/#{name}") if config[:exe]
+ if config[:exe]
+ templates.merge!("exe/newgem.tt" => "exe/#{name}")
+ executables.push("exe/#{name}")
+ end
if extension == "c"
templates.merge!(
@@ -210,13 +233,25 @@ module Bundler
)
end
+ if extension == "go"
+ templates.merge!(
+ "ext/newgem/go.mod.tt" => "ext/#{name}/go.mod",
+ "ext/newgem/extconf-go.rb.tt" => "ext/#{name}/extconf.rb",
+ "ext/newgem/newgem.h.tt" => "ext/#{name}/#{underscored_name}.h",
+ "ext/newgem/newgem.go.tt" => "ext/#{name}/#{underscored_name}.go",
+ "ext/newgem/newgem-go.c.tt" => "ext/#{name}/#{underscored_name}.c",
+ )
+
+ config[:go_module_username] = config[:github_username] == DEFAULT_GITHUB_USERNAME ? "username" : config[:github_username]
+ 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}"
+ Bundler.ui.info "\nInitializing git repo in #{target}"
require "shellwords"
`git init #{target.to_s.shellescape}`
@@ -238,26 +273,33 @@ module Bundler
IO.popen(%w[git add .], { chdir: target }, &:read)
end
+ if config[:bundle]
+ Bundler.ui.info "Running bundle install in the new gem directory."
+ Dir.chdir(target) do
+ system("bundle install")
+ end
+ end
+
# Open gemspec in editor
open_editor(options["edit"], target.join("#{name}.gemspec")) if options[:edit]
- Bundler.ui.info "Gem '#{name}' was successfully created. " \
+ Bundler.ui.info "\nGem '#{name}' was successfully created. " \
"For more information on making a RubyGem visit https://bundler.io/guides/creating_gem.html"
end
private
def resolve_name(name)
- SharedHelpers.pwd.join(name).basename.to_s
+ Pathname.new(SharedHelpers.pwd).join(name).basename.to_s
end
- def ask_and_set(key, header, message)
+ def ask_and_set(key, prompt, explanation)
choice = options[key]
choice = Bundler.settings["gem.#{key}"] if choice.nil?
if choice.nil?
- Bundler.ui.confirm header
- choice = Bundler.ui.yes? "#{message} y/(n):"
+ Bundler.ui.info "\n#{explanation}"
+ choice = Bundler.ui.yes? "#{prompt} y/(n):"
Bundler.settings.set_global("gem.#{key}", choice)
end
@@ -275,10 +317,11 @@ module Bundler
end
def ask_and_set_test_framework
+ return if skip?(:test)
test_framework = options[:test] || Bundler.settings["gem.test"]
if test_framework.to_s.empty?
- Bundler.ui.confirm "Do you want to generate tests with your gem?"
+ Bundler.ui.info "\nDo you want to generate tests with your gem?"
Bundler.ui.info hint_text("test")
result = Bundler.ui.ask "Enter a test framework. rspec/minitest/test-unit/(none):"
@@ -300,6 +343,10 @@ module Bundler
test_framework
end
+ def skip?(option)
+ options.key?(option) && options[option].nil?
+ end
+
def hint_text(setting)
if Bundler.settings["gem.#{setting}"] == false
"Your choice will only be applied to this gem."
@@ -310,15 +357,15 @@ module Bundler
end
def ask_and_set_ci
+ return if skip?(: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? " \
+ Bundler.ui.info "\nDo 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" \
- "\n"
+ "* GitLab CI: https://docs.gitlab.com/ee/ci/\n"
Bundler.ui.info hint_text("ci")
result = Bundler.ui.ask "Enter a CI service. github/gitlab/circle/(none):"
@@ -341,15 +388,14 @@ module Bundler
end
def ask_and_set_linter
+ return if skip?(: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? " \
+ Bundler.ui.info "\nDo you want to add a code linter and formatter to your gem? " \
"Supported Linters:\n" \
"* RuboCop: https://rubocop.org\n" \
- "* Standard: https://github.com/standardrb/standard\n" \
- "\n"
+ "* Standard: https://github.com/standardrb/standard\n"
Bundler.ui.info hint_text("linter")
result = Bundler.ui.ask "Enter a linter. rubocop/standard/(none):"
@@ -376,27 +422,6 @@ module Bundler
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",
- removed_message: "--rubocop has been removed, use --linter=rubocop"
- "rubocop"
- else
- Bundler::SharedHelpers.major_deprecation 2,
- "--no-rubocop is deprecated, use --linter",
- removed_message: "--no-rubocop has been removed, 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",
- removed_message: "config gem.rubocop has been removed; 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]
@@ -436,7 +461,7 @@ module Bundler
end
def required_ruby_version
- "3.0.0"
+ "3.2.0"
end
def rubocop_version
@@ -447,10 +472,13 @@ module Bundler
"1.3"
end
- def validate_rust_builder_rubygems_version
- if Gem::Version.new(rust_builder_required_rubygems_version) > Gem.rubygems_version
- Bundler.ui.error "Your RubyGems version (#{Gem.rubygems_version}) is too old to build Rust extension. Please update your RubyGems using `gem update --system` or any other way and try again."
- exit 1
+ def github_username(git_username)
+ if options[:github_username].nil?
+ git_username
+ elsif options[:github_username] == false
+ ""
+ else
+ options[:github_username]
end
end
end
diff --git a/lib/bundler/cli/info.rb b/lib/bundler/cli/info.rb
index 8f34956aca..cd01d4949b 100644
--- a/lib/bundler/cli/info.rb
+++ b/lib/bundler/cli/info.rb
@@ -39,8 +39,8 @@ module Bundler
path = File.expand_path("../../..", __dir__)
else
path = spec.full_gem_path
- if spec.deleted_gem?
- return Bundler.ui.warn "The gem #{name} has been deleted. It was installed at: #{path}"
+ if spec.installation_missing?
+ return Bundler.ui.warn "The gem #{name} is missing. It should be installed at #{path}, but was not found"
end
end
@@ -65,19 +65,19 @@ module Bundler
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}"
+ if name != "bundler" && spec.installation_missing?
+ return Bundler.ui.warn "The gem #{name} is missing. 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|
+ @gem_dependencies ||= Bundler.definition.specs.filter_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.sort
end
end
end
diff --git a/lib/bundler/cli/inject.rb b/lib/bundler/cli/inject.rb
deleted file mode 100644
index 8093a85283..0000000000
--- a/lib/bundler/cli/inject.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# frozen_string_literal: true
-
-module Bundler
- class CLI::Inject
- attr_reader :options, :name, :version, :group, :source, :gems
- def initialize(options, name, version)
- @options = options
- @name = name
- @version = version || last_version_number
- @group = options[:group].split(",") unless options[:group].nil?
- @source = options[:source]
- @gems = []
- end
-
- def run
- # The required arguments allow Thor to give useful feedback when the arguments
- # are incorrect. This adds those first two arguments onto the list as a whole.
- gems.unshift(source).unshift(group).unshift(version).unshift(name)
-
- # Build an array of Dependency objects out of the arguments
- deps = []
- # when `inject` support addition of more than one gem, then this loop will
- # help. Currently this loop is running once.
- gems.each_slice(4) do |gem_name, gem_version, gem_group, gem_source|
- ops = Gem::Requirement::OPS.map {|key, _val| key }
- has_op = ops.any? {|op| gem_version.start_with? op }
- gem_version = "~> #{gem_version}" unless has_op
- deps << Bundler::Dependency.new(gem_name, gem_version, "group" => gem_group, "source" => gem_source)
- end
-
- added = Injector.inject(deps, options)
-
- if added.any?
- Bundler.ui.confirm "Added to Gemfile:"
- Bundler.ui.confirm(added.map do |d|
- name = "'#{d.name}'"
- requirement = ", '#{d.requirement}'"
- group = ", :group => #{d.groups.inspect}" if d.groups != Array(:default)
- source = ", :source => '#{d.source}'" unless d.source.nil?
- %(gem #{name}#{requirement}#{group}#{source})
- end.join("\n"))
- else
- Bundler.ui.confirm "All gems were already present in the Gemfile"
- end
- end
-
- private
-
- def last_version_number
- definition = Bundler.definition(true)
- definition.resolve_remotely!
- specs = definition.index[name].sort_by(&:version)
- unless options[:pre]
- specs.delete_if {|b| b.respond_to?(:version) && b.version.prerelease? }
- end
- spec = specs.last
- spec.version.to_s
- end
- end
-end
diff --git a/lib/bundler/cli/install.rb b/lib/bundler/cli/install.rb
index a233d5d2e5..67feba84bd 100644
--- a/lib/bundler/cli/install.rb
+++ b/lib/bundler/cli/install.rb
@@ -12,53 +12,40 @@ module Bundler
warn_if_root
- Bundler.self_manager.install_locked_bundler_and_restart_with_it_if_needed
+ if options[:local]
+ Bundler.self_manager.restart_with_locked_bundler_if_needed
+ else
+ Bundler.self_manager.install_locked_bundler_and_restart_with_it_if_needed
+ end
Bundler::SharedHelpers.set_env "RB_USER_INSTALL", "1" if Gem.freebsd_platform?
- # Disable color in deployment mode
- Bundler.ui.shell = Thor::Shell::Basic.new if options[:deployment]
-
- check_for_options_conflicts
+ if target_rbconfig_path = options[:"target-rbconfig"]
+ Bundler.rubygems.set_target_rbconfig(target_rbconfig_path)
+ end
check_trust_policy
- if options[:deployment] || options[:frozen] || Bundler.frozen_bundle?
- unless Bundler.default_lockfile.exist?
- flag = "--deployment flag" if options[:deployment]
- flag ||= "--frozen flag" if options[:frozen]
- flag ||= "deployment setting"
- raise ProductionError, "The #{flag} requires a lockfile. Please make " \
- "sure you have checked your #{SharedHelpers.relative_lockfile_path} into version control " \
- "before deploying."
- end
-
- options[:local] = true if Bundler.app_cache.exist?
-
- 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
- if options[:deployment] == false
- Bundler.settings.set_command_option :frozen, nil
- options[:system] = true
+ if Bundler.frozen_bundle? && !Bundler.default_lockfile.exist?
+ flag = "deployment setting" if Bundler.settings[:deployment]
+ flag = "frozen setting" if Bundler.settings[:frozen]
+ raise ProductionError, "The #{flag} requires a lockfile. Please make " \
+ "sure you have checked your #{SharedHelpers.relative_lockfile_path} into version control " \
+ "before deploying."
end
normalize_settings
Bundler::Fetcher.disable_endpoint = options["full-index"]
- if options["binstubs"]
- Bundler::SharedHelpers.major_deprecation 2,
- "The --binstubs option will be removed in favor of `bundle binstubs --all`",
- removed_message: "The --binstubs option have been removed in favor of `bundle binstubs --all`"
- end
-
- Plugin.gemfile_install(Bundler.default_gemfile) if Bundler.feature_flag.plugins?
+ Plugin.gemfile_install(Bundler.default_gemfile) if Bundler.settings[:plugins]
- definition = Bundler.definition
+ # For install we want to enable strict validation
+ # (rather than some optimizations we perform at app runtime).
+ definition = Bundler.definition(strict: true)
definition.validate_runtime!
+ definition.lockfile = options["lockfile"] if options["lockfile"]
+ definition.lockfile = false if options["no-lock"]
installer = Installer.install(Bundler.root, definition, options)
@@ -78,8 +65,6 @@ module Bundler
Bundler::CLI::Common.output_post_install_messages installer.post_install_messages
- warn_ambiguous_gems
-
if CLI::Common.clean_after_install?
require_relative "clean"
Bundler::CLI::Clean.new(options).run
@@ -105,26 +90,10 @@ module Bundler
end
def gems_installed_for(definition)
- count = definition.specs.count
+ count = definition.specs.count {|spec| spec.name != "bundler" }
"#{count} #{count == 1 ? "gem" : "gems"} now installed"
end
- def check_for_group_conflicts_in_cli_options
- conflicting_groups = Array(options[:without]) & Array(options[:with])
- return if conflicting_groups.empty?
- raise InvalidOption, "You can't list a group in both with and without." \
- " The offending groups are: #{conflicting_groups.join(", ")}."
- end
-
- def check_for_options_conflicts
- if (options[:path] || options[:deployment]) && options[:system]
- error_message = String.new
- error_message << "You have specified both --path as well as --system. Please choose only one option.\n" if options[:path]
- error_message << "You have specified both --deployment as well as --system. Please choose only one option.\n" if options[:deployment]
- raise InvalidOption.new(error_message)
- end
- end
-
def check_trust_policy
trust_policy = options["trust-policy"]
unless Bundler.rubygems.security_policies.keys.unshift(nil).include?(trust_policy)
@@ -134,30 +103,11 @@ module Bundler
Bundler.settings.set_command_option_if_given :"trust-policy", trust_policy
end
- def normalize_groups
- check_for_group_conflicts_in_cli_options
-
- # 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.set_command_option_if_given :path, options[:path]
-
if options["standalone"] && Bundler.settings[:path].nil? && !options["local"]
- Bundler.settings.temporary(path_relative_to_cwd: false) do
- Bundler.settings.set_command_option :path, "bundle"
- end
+ Bundler.settings.set_command_option :path, "bundle"
end
- bin_option = options["binstubs"]
- bin_option = nil if bin_option&.empty?
- Bundler.settings.set_command_option :bin, bin_option if options["binstubs"]
-
Bundler.settings.set_command_option_if_given :shebang, options["shebang"]
Bundler.settings.set_command_option_if_given :jobs, options["jobs"]
@@ -168,23 +118,7 @@ module Bundler
Bundler.settings.set_command_option_if_given :clean, options["clean"]
- normalize_groups if options[:without] || options[:with]
-
- options[:force] = options[:redownload]
- end
-
- def warn_ambiguous_gems
- # TODO: remove this when we drop Bundler 1.x support
- Installer.ambiguous_gems.to_a.each do |name, installed_from_uri, *also_found_in_uris|
- Bundler.ui.warn "Warning: the gem '#{name}' was found in multiple sources."
- Bundler.ui.warn "Installed from: #{installed_from_uri}"
- Bundler.ui.warn "Also found in:"
- also_found_in_uris.each {|uri| Bundler.ui.warn " * #{uri}" }
- Bundler.ui.warn "You should add a source requirement to restrict this gem to your preferred source."
- Bundler.ui.warn "For example:"
- Bundler.ui.warn " gem '#{name}', :source => '#{installed_from_uri}'"
- Bundler.ui.warn "Then uninstall the gem '#{name}' (or delete all bundled gems) and then install again."
- end
+ options[:force] = options[:redownload] if options[:redownload]
end
end
end
diff --git a/lib/bundler/cli/issue.rb b/lib/bundler/cli/issue.rb
index 5f2924c4bd..cbfb7da2d8 100644
--- a/lib/bundler/cli/issue.rb
+++ b/lib/bundler/cli/issue.rb
@@ -10,7 +10,7 @@ module Bundler
be sure to check out these resources:
1. Check out our troubleshooting guide for quick fixes to common issues:
- https://github.com/rubygems/rubygems/blob/master/bundler/doc/TROUBLESHOOTING.md
+ https://github.com/ruby/rubygems/blob/master/doc/bundler/TROUBLESHOOTING.md
2. Instructions for common Bundler uses can be found on the documentation
site: https://bundler.io/
@@ -22,7 +22,7 @@ module Bundler
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, by filling
in the new issue form located at
- https://github.com/rubygems/rubygems/issues/new?labels=Bundler&template=bundler-related-issue.md,
+ https://github.com/ruby/rubygems/issues/new?labels=Bundler&template=bundler-related-issue.md,
and copy and pasting the information below.
EOS
@@ -34,8 +34,8 @@ module Bundler
end
def doctor
- require_relative "doctor"
- Bundler::CLI::Doctor.new({}).run
+ require_relative "doctor/diagnose"
+ Bundler::CLI::Doctor::Diagnose.new({}).run
end
end
end
diff --git a/lib/bundler/cli/list.rb b/lib/bundler/cli/list.rb
index f56bf5b86a..6a467f45a9 100644
--- a/lib/bundler/cli/list.rb
+++ b/lib/bundler/cli/list.rb
@@ -1,11 +1,14 @@
# frozen_string_literal: true
+require "json"
+
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)
+ @format = options["format"]
end
def run
@@ -25,6 +28,36 @@ module Bundler
end
end.reject {|s| s.name == "bundler" }.sort_by(&:name)
+ case @format
+ when "json"
+ print_json(specs: specs)
+ when nil
+ print_human(specs: specs)
+ else
+ raise InvalidOption, "Unknown option`--format=#{@format}`. Supported formats: `json`"
+ end
+ end
+
+ private
+
+ def print_json(specs:)
+ gems = if @options["name-only"]
+ specs.map {|s| { name: s.name } }
+ else
+ specs.map do |s|
+ {
+ name: s.name,
+ version: s.version.to_s,
+ git_version: s.git_version&.strip,
+ }.tap do |h|
+ h[:path] = s.full_gem_path if @options["paths"]
+ end
+ end
+ end
+ Bundler.ui.info({ gems: gems }.to_json)
+ end
+
+ def print_human(specs:)
return Bundler.ui.info "No gems in the Gemfile" if specs.empty?
return specs.each {|s| Bundler.ui.info s.name } if @options["name-only"]
@@ -37,8 +70,6 @@ module Bundler
Bundler.ui.info "Use `bundle info` to print more detailed information about a gem"
end
- private
-
def verify_group_exists(groups)
(@without_group + @only_group).each do |group|
raise InvalidOption, "`#{group}` group could not be found." unless groups.include?(group)
diff --git a/lib/bundler/cli/lock.rb b/lib/bundler/cli/lock.rb
index dac3d2a09a..2f78868936 100644
--- a/lib/bundler/cli/lock.rb
+++ b/lib/bundler/cli/lock.rb
@@ -14,9 +14,11 @@ module Bundler
exit 1
end
+ check_for_conflicting_options
+
print = options[:print]
- previous_ui_level = Bundler.ui.level
- Bundler.ui.level = "silent" if print
+ previous_output_stream = Bundler.ui.output_stream
+ Bundler.ui.output_stream = :stderr if print
Bundler::Fetcher.disable_endpoint = options["full-index"]
@@ -33,23 +35,22 @@ module Bundler
update = { bundler: bundler }
end
- file = options[:lockfile]
- file = file ? Pathname.new(file).expand_path : Bundler.default_lockfile
-
Bundler.settings.temporary(frozen: false) do
- definition = Bundler.definition(update, file)
+ definition = Bundler.definition(update, Bundler.default_lockfile)
+ definition.add_checksums if options["add-checksums"]
Bundler::CLI::Common.configure_gem_version_promoter(definition, options) if options[:update]
- options["remove-platform"].each do |platform|
+ options["remove-platform"].each do |platform_string|
+ platform = Gem::Platform.new(platform_string)
definition.remove_platform(platform)
end
options["add-platform"].each do |platform_string|
platform = Gem::Platform.new(platform_string)
if platform.to_s == "unknown"
- Bundler.ui.warn "The platform `#{platform_string}` is unknown to RubyGems " \
- "and adding it will likely lead to resolution errors"
+ Bundler.ui.error "The platform `#{platform_string}` is unknown to RubyGems and can't be added to the lockfile."
+ exit 1
end
definition.add_platform(platform)
end
@@ -58,17 +59,36 @@ module Bundler
raise InvalidOption, "Removing all platforms from the bundle is not allowed"
end
- definition.resolve_remotely! unless options[:local]
+ definition.remotely! unless options[:local]
+
+ if options["normalize-platforms"]
+ definition.normalize_platforms
+ end
if print
puts definition.to_lock
else
+ file = options[:lockfile]
+ file = file ? Pathname.new(file).expand_path : Bundler.default_lockfile
+
puts "Writing lockfile to #{file}"
- definition.lock
+ definition.write_lock(file, false)
end
end
- Bundler.ui.level = previous_ui_level
+ Bundler.ui.output_stream = previous_output_stream
+ end
+
+ private
+
+ def check_for_conflicting_options
+ if options["normalize-platforms"] && options["add-platform"].any?
+ raise InvalidOption, "--normalize-platforms can't be used with --add-platform"
+ end
+
+ if options["normalize-platforms"] && options["remove-platform"].any?
+ raise InvalidOption, "--normalize-platforms can't be used with --remove-platform"
+ end
end
end
end
diff --git a/lib/bundler/cli/outdated.rb b/lib/bundler/cli/outdated.rb
index ec42e631bb..0c8ba3ebf7 100644
--- a/lib/bundler/cli/outdated.rb
+++ b/lib/bundler/cli/outdated.rb
@@ -26,13 +26,15 @@ module Bundler
def run
check_for_deployment_mode!
- gems.each do |gem_name|
- Bundler::CLI::Common.select_spec(gem_name)
- end
-
Bundler.definition.validate_runtime!
current_specs = Bundler.ui.silence { Bundler.definition.resolve }
+ gems.each do |gem_name|
+ if current_specs[gem_name].empty?
+ raise GemNotFound, "Could not find gem '#{gem_name}'."
+ end
+ end
+
current_dependencies = Bundler.ui.silence do
Bundler.load.dependencies.map {|dep| [dep.name, dep] }.to_h
end
@@ -54,7 +56,7 @@ module Bundler
end
if options[:parseable]
- Bundler.ui.silence(&definition_resolution)
+ Bundler.ui.progress(&definition_resolution)
else
definition_resolution.call
end
@@ -97,28 +99,26 @@ module Bundler
}
end
- if outdated_gems.empty?
+ relevant_outdated_gems = if options_include_groups
+ 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
+
+ gems
+ end.compact
+ else
+ outdated_gems
+ end
+
+ if relevant_outdated_gems.empty?
unless options[:parseable]
Bundler.ui.info(nothing_outdated_message)
end
else
- if options_include_groups
- 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
-
- gems
- end.compact
-
- if options[:parseable]
- print_gems(relevant_outdated_gems)
- else
- print_gems_table(relevant_outdated_gems)
- end
- elsif options[:parseable]
- print_gems(outdated_gems)
+ if options[:parseable]
+ print_gems(relevant_outdated_gems)
else
- print_gems_table(outdated_gems)
+ print_gems_table(relevant_outdated_gems)
end
exit 1
@@ -155,7 +155,7 @@ module Bundler
return active_spec if strict
- active_specs = active_spec.source.specs.search(current_spec.name).select {|spec| spec.match_platform(current_spec.platform) }.sort_by(&:version)
+ active_specs = active_spec.source.specs.search(current_spec.name).select {|spec| spec.installable_on_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
diff --git a/lib/bundler/cli/plugin.rb b/lib/bundler/cli/plugin.rb
index fd61ef0d95..32fa660fe0 100644
--- a/lib/bundler/cli/plugin.rb
+++ b/lib/bundler/cli/plugin.rb
@@ -10,11 +10,15 @@ module Bundler
method_option "source", type: :string, default: nil, banner: "URL of the RubyGems source to fetch the plugin from"
method_option "version", type: :string, default: nil, banner: "The version of the plugin to fetch"
method_option "git", type: :string, default: nil, banner: "URL of the git repo to fetch from"
- method_option "local_git", type: :string, default: nil, banner: "Path of the local git repo to fetch from (deprecated)"
+ method_option "local_git", type: :string, default: nil, banner: "Path of the local git repo to fetch from (removed)"
method_option "branch", type: :string, default: nil, banner: "The git branch to checkout"
method_option "ref", type: :string, default: nil, banner: "The git revision to check out"
method_option "path", type: :string, default: nil, banner: "Path of a local gem to directly use"
def install(*plugins)
+ if options.key?(:local_git)
+ raise InvalidOption, "--local_git has been removed, use --git"
+ end
+
Bundler::Plugin.install(plugins, options)
end
diff --git a/lib/bundler/cli/pristine.rb b/lib/bundler/cli/pristine.rb
index e0d7452c44..b8545fe4c9 100644
--- a/lib/bundler/cli/pristine.rb
+++ b/lib/bundler/cli/pristine.rb
@@ -11,6 +11,7 @@ module Bundler
definition = Bundler.definition
definition.validate_runtime!
installer = Bundler::Installer.new(Bundler.root, definition)
+ git_sources = []
ProcessLock.lock do
installed_specs = definition.specs.reject do |spec|
@@ -41,6 +42,9 @@ module Bundler
end
FileUtils.rm_rf spec.extension_dir
FileUtils.rm_rf spec.full_gem_path
+
+ next if git_sources.include?(source)
+ git_sources << source
else
Bundler.ui.warn("Cannot pristine #{gem_name}. Gem is sourced from local path.")
next
@@ -49,7 +53,7 @@ module Bundler
true
end.map(&:name)
- jobs = installer.send(:installation_parallelization, {})
+ jobs = installer.send(:installation_parallelization)
pristine_count = definition.specs.count - installed_specs.count
# allow a pristining a single gem to skip the parallel worker
jobs = [jobs, pristine_count].min
diff --git a/lib/bundler/cli/show.rb b/lib/bundler/cli/show.rb
index 59b0af42e1..67fdcc797e 100644
--- a/lib/bundler/cli/show.rb
+++ b/lib/bundler/cli/show.rb
@@ -6,7 +6,7 @@ module Bundler
def initialize(options, gem_name)
@options = options
@gem_name = gem_name
- @verbose = options[:verbose] || options[:outdated]
+ @verbose = options[:verbose]
@latest_specs = fetch_latest_specs if @verbose
end
@@ -24,7 +24,7 @@ module Bundler
return unless spec
path = spec.full_gem_path
unless File.directory?(path)
- return Bundler.ui.warn "The gem #{gem_name} has been deleted. It was installed at: #{path}"
+ return Bundler.ui.warn "The gem #{gem_name} is missing. It should be installed at #{path}, but was not found"
end
end
return Bundler.ui.info(path)
@@ -57,12 +57,8 @@ module Bundler
def fetch_latest_specs
definition = Bundler.definition(true)
- if options[:outdated]
- Bundler.ui.info "Fetching remote specs for outdated check...\n\n"
- Bundler.ui.silence { definition.resolve_remotely! }
- else
- definition.resolve_with_cache!
- end
+ Bundler.ui.info "Fetching remote specs for outdated check...\n\n"
+ Bundler.ui.silence { definition.remotely! }
Bundler.reset!
definition.specs
end
diff --git a/lib/bundler/cli/update.rb b/lib/bundler/cli/update.rb
index 985e8db051..9cc90acc58 100644
--- a/lib/bundler/cli/update.rb
+++ b/lib/bundler/cli/update.rb
@@ -15,7 +15,7 @@ module 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?
+ Plugin.gemfile_install(Bundler.default_gemfile) if Bundler.settings[:plugins]
sources = Array(options[:source])
groups = Array(options[:group]).map(&:to_sym)
@@ -23,10 +23,10 @@ module 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?
+ if Bundler.settings[:update_requires_all_flag]
raise InvalidOption, "To update everything, pass the `--all` flag."
end
- SharedHelpers.major_deprecation 3, "Pass --all to `bundle update` to update everything"
+ SharedHelpers.feature_deprecated! "Pass --all to `bundle update` to update everything"
elsif !full_update && options[:all]
raise InvalidOption, "Cannot specify --all along with specific options."
end
@@ -63,7 +63,7 @@ module Bundler
opts = options.dup
opts["update"] = true
opts["local"] = options[:local]
- opts["force"] = options[:redownload]
+ opts["force"] = options[:redownload] if options[:redownload]
Bundler.settings.set_command_option_if_given :jobs, opts["jobs"]
@@ -92,7 +92,7 @@ module Bundler
locked_spec = locked_info[:spec]
new_spec = Bundler.definition.specs[name].first
unless new_spec
- unless locked_spec.match_platform(Bundler.local_platform)
+ unless locked_spec.installable_on_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
diff --git a/lib/bundler/cli/viz.rb b/lib/bundler/cli/viz.rb
deleted file mode 100644
index 5c09e00995..0000000000
--- a/lib/bundler/cli/viz.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-module Bundler
- class CLI::Viz
- attr_reader :options, :gem_name
- def initialize(options)
- @options = options
- end
-
- def run
- # make sure we get the right `graphviz`. There is also a `graphviz`
- # gem we're not built to support
- gem "ruby-graphviz"
- require "graphviz"
-
- options[:without] = options[:without].join(":").tr(" ", ":").split(":")
- output_file = File.expand_path(options[:file])
-
- graph = Graph.new(Bundler.load, output_file, options[:version], options[:requirements], options[:format], options[:without])
- graph.viz
- rescue LoadError => e
- Bundler.ui.error e.inspect
- Bundler.ui.warn "Make sure you have the graphviz ruby gem. You can install it with:"
- Bundler.ui.warn "`gem install ruby-graphviz`"
- rescue StandardError => e
- raise unless e.message.to_s.include?("GraphViz not installed or dot not in PATH")
- Bundler.ui.error e.message
- Bundler.ui.warn "Please install GraphViz. On a Mac with Homebrew, you can run `brew install graphviz`."
- end
- end
-end
diff --git a/lib/bundler/compact_index_client.rb b/lib/bundler/compact_index_client.rb
index 692d68e579..6865e30dbc 100644
--- a/lib/bundler/compact_index_client.rb
+++ b/lib/bundler/compact_index_client.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: true
-require "pathname"
require "set"
module Bundler
@@ -28,11 +27,7 @@ module Bundler
# It may be called concurrently without global interpreter lock in some Rubies.
# As a result, some methods may look more complex than necessary to save memory or time.
class CompactIndexClient
- # NOTE: MD5 is here not because we expect a server to respond with it, but
- # because we use it to generate the etag on first request during the upgrade
- # to the compact index client that uses opaque etags saved to files.
- # Remove once 2.5.0 has been out for a while.
- SUPPORTED_DIGESTS = { "sha-256" => :SHA256, "md5" => :MD5 }.freeze
+ SUPPORTED_DIGESTS = { "sha-256" => :SHA256 }.freeze
DEBUG_MUTEX = Thread::Mutex.new
# info returns an Array of INFO Arrays. Each INFO Array has the following indices:
@@ -75,7 +70,7 @@ module Bundler
end
def info(name)
- Bundler::CompactIndexClient.debug { "info(#{names})" }
+ Bundler::CompactIndexClient.debug { "info(#{name})" }
@parser.info(name)
end
diff --git a/lib/bundler/compact_index_client/cache.rb b/lib/bundler/compact_index_client/cache.rb
index bedd7f8028..3bae6c9efd 100644
--- a/lib/bundler/compact_index_client/cache.rb
+++ b/lib/bundler/compact_index_client/cache.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require_relative "gem_parser"
+require "rubygems/resolver/api_set/gem_parser"
module Bundler
class CompactIndexClient
diff --git a/lib/bundler/compact_index_client/gem_parser.rb b/lib/bundler/compact_index_client/gem_parser.rb
deleted file mode 100644
index 60a1817607..0000000000
--- a/lib/bundler/compact_index_client/gem_parser.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-module Bundler
- class CompactIndexClient
- if defined?(Gem::Resolver::APISet::GemParser)
- GemParser = Gem::Resolver::APISet::GemParser
- else
- class GemParser
- EMPTY_ARRAY = [].freeze
- private_constant :EMPTY_ARRAY
-
- 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) } : EMPTY_ARRAY
- requirements = requirements ? requirements.map! {|d| parse_dependency(d) } : EMPTY_ARRAY
- [version, platform, dependencies, requirements]
- end
-
- private
-
- def parse_dependency(string)
- dependency = string.split(":")
- dependency[-1] = dependency[-1].split("&") if dependency.size > 1
- dependency[0] = -dependency[0]
- dependency
- end
- end
- end
- end
-end
diff --git a/lib/bundler/compact_index_client/parser.rb b/lib/bundler/compact_index_client/parser.rb
index 3a0dec4907..43581fd7ef 100644
--- a/lib/bundler/compact_index_client/parser.rb
+++ b/lib/bundler/compact_index_client/parser.rb
@@ -11,7 +11,6 @@ module Bundler
@versions_by_name = nil
@available = nil
@gem_parser = nil
- @versions_data = nil
end
def names
@@ -40,71 +39,45 @@ module Bundler
end
def info(name)
- data = @compact_index.info(name, info_checksum(name))
+ data = @compact_index.info(name, info_checksums[name])
lines(data).map {|line| gem_parser.parse(line).unshift(name) }
end
- # parse the last, most recently updated line of the versions file to determine availability
def available?
return @available unless @available.nil?
- return @available = false unless versions_data&.size&.nonzero?
-
- line_end = versions_data.size - 1
- return @available = false if versions_data[line_end] != "\n"
-
- line_start = versions_data.rindex("\n", line_end - 1)
- line_start ||= -1 # allow a single line versions file
-
- @available = !split_last_word(versions_data, line_start + 1, line_end).nil?
+ @available = !info_checksums.empty?
end
private
- # Search for a line starting with gem name, then return last space-separated word (the checksum)
- def info_checksum(name)
- return unless versions_data
- return unless (line_start = rindex_of_gem(name))
- return unless (line_end = versions_data.index("\n", line_start))
- split_last_word(versions_data, line_start, line_end)
- end
-
- def gem_parser
- @gem_parser ||= GemParser.new
- end
-
- def versions_data
- @versions_data ||= begin
- data = @compact_index.versions
- strip_header!(data) if data
- data.freeze
- end
- end
-
- def rindex_of_gem(name)
- if (pos = versions_data.rindex("\n#{name} "))
- pos + 1
- elsif versions_data.start_with?("#{name} ")
- 0
+ def info_checksums
+ @info_checksums ||= lines(@compact_index.versions).each_with_object({}) do |line, checksums|
+ parse_version_checksum(line, checksums)
end
end
- # This is similar to `string.split(" ").last` but it avoids allocating extra objects.
- def split_last_word(string, line_start, line_end)
- return unless line_start < line_end && line_start >= 0
- word_start = string.rindex(" ", line_end).to_i + 1
- return if word_start < line_start
- string[word_start, line_end - word_start]
+ def lines(data)
+ return [] if data.nil? || data.empty?
+ lines = data.split("\n")
+ header = lines.index("---")
+ header ? lines[header + 1..-1] : lines
end
- def lines(string)
- return [] if string.nil? || string.empty?
- strip_header!(string)
- string.split("\n")
+ def gem_parser
+ @gem_parser ||= Gem::Resolver::APISet::GemParser.new
end
- def strip_header!(string)
- header_end = string.index("---\n")
- string.slice!(0, header_end + 4) if header_end
+ # This is mostly the same as `split(" ", 3)` but it avoids allocating extra objects.
+ # This method gets called at least once for every gem when parsing versions.
+ def parse_version_checksum(line, checksums)
+ return unless (name_end = line.index(" ")) # Artifactory bug causes blank lines in artifactor index files
+ return unless (checksum_start = line.index(" ", name_end + 1) + 1)
+ checksum_end = line.size - checksum_start
+
+ line.freeze # allows slicing into the string to not allocate a copy of the line
+ name = line[0, name_end]
+ checksum = line[checksum_start, checksum_end]
+ checksums[name.freeze] = checksum # freeze name since it is used as a hash key
end
end
end
diff --git a/lib/bundler/compact_index_client/updater.rb b/lib/bundler/compact_index_client/updater.rb
index 88c7146900..6066fdc7c4 100644
--- a/lib/bundler/compact_index_client/updater.rb
+++ b/lib/bundler/compact_index_client/updater.rb
@@ -37,7 +37,8 @@ module Bundler
file.digests = parse_digests(response)
# server may ignore Range and return the full response
if response.is_a?(Gem::Net::HTTPPartialContent)
- break false unless file.append(response.body.byteslice(1..-1))
+ tail = response.body.byteslice(1..-1)
+ break false unless tail && file.append(tail)
else
file.write(response.body)
end
diff --git a/lib/bundler/current_ruby.rb b/lib/bundler/current_ruby.rb
index 93e0c401c0..17c7655adb 100644
--- a/lib/bundler/current_ruby.rb
+++ b/lib/bundler/current_ruby.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require_relative "rubygems_ext"
+
module Bundler
# Returns current version of Ruby
#
@@ -9,41 +11,28 @@ module Bundler
end
class CurrentRuby
- KNOWN_MINOR_VERSIONS = %w[
- 1.8
- 1.9
- 2.0
- 2.1
- 2.2
- 2.3
- 2.4
- 2.5
- 2.6
- 2.7
- 3.0
- 3.1
- 3.2
- 3.3
- ].freeze
-
- KNOWN_MAJOR_VERSIONS = KNOWN_MINOR_VERSIONS.map {|v| v.split(".", 2).first }.uniq.freeze
-
- KNOWN_PLATFORMS = %w[
- jruby
- maglev
- mingw
- mri
- mswin
- mswin64
- rbx
- ruby
- truffleruby
- windows
- x64_mingw
- ].freeze
+ ALL_RUBY_VERSIONS = [*18..27, *30..34, *40..41].freeze
+ KNOWN_MINOR_VERSIONS = ALL_RUBY_VERSIONS.map {|v| v.digits.reverse.join(".") }.freeze
+ KNOWN_MAJOR_VERSIONS = ALL_RUBY_VERSIONS.map {|v| v.digits.last.to_s }.uniq.freeze
+ PLATFORM_MAP = {
+ ruby: [Gem::Platform::RUBY, CurrentRuby::ALL_RUBY_VERSIONS],
+ mri: [Gem::Platform::RUBY, CurrentRuby::ALL_RUBY_VERSIONS],
+ rbx: [Gem::Platform::RUBY],
+ truffleruby: [Gem::Platform::RUBY],
+ jruby: [Gem::Platform::JAVA, [18, 19]],
+ windows: [Gem::Platform::WINDOWS, CurrentRuby::ALL_RUBY_VERSIONS],
+ # deprecated
+ mswin: [Gem::Platform::MSWIN, CurrentRuby::ALL_RUBY_VERSIONS],
+ mswin64: [Gem::Platform::MSWIN64, CurrentRuby::ALL_RUBY_VERSIONS - [18]],
+ mingw: [Gem::Platform::UNIVERSAL_MINGW, CurrentRuby::ALL_RUBY_VERSIONS],
+ x64_mingw: [Gem::Platform::UNIVERSAL_MINGW, CurrentRuby::ALL_RUBY_VERSIONS - [18, 19]],
+ }.each_with_object({}) do |(platform, spec), hash|
+ hash[platform] = spec[0]
+ spec[1]&.each {|version| hash[:"#{platform}_#{version}"] = spec[0] }
+ end.freeze
def ruby?
- return true if Bundler::GemHelpers.generic_local_platform_is_ruby?
+ return true if Bundler::MatchPlatform.generic_local_platform_is_ruby?
!windows? && (RUBY_ENGINE == "ruby" || RUBY_ENGINE == "rbx" || RUBY_ENGINE == "maglev" || RUBY_ENGINE == "truffleruby")
end
@@ -61,7 +50,10 @@ module Bundler
end
def maglev?
- RUBY_ENGINE == "maglev"
+ removed_message =
+ "`CurrentRuby#maglev?` was removed with no replacement. Please use the " \
+ "built-in Ruby `RUBY_ENGINE` constant to check the Ruby implementation you are running on."
+ SharedHelpers.feature_removed!(removed_message)
end
def truffleruby?
@@ -82,11 +74,21 @@ module Bundler
RUBY_VERSION.start_with?("#{version}.")
end
- KNOWN_PLATFORMS.each do |platform|
+ PLATFORM_MAP.keys.each do |platform|
define_method(:"#{platform}_#{trimmed_version}?") do
send(:"#{platform}?") && send(:"on_#{trimmed_version}?")
end
end
+
+ define_method(:"maglev_#{trimmed_version}?") do
+ removed_message =
+ "`CurrentRuby##{__method__}` was removed with no replacement. Please use the " \
+ "built-in Ruby `RUBY_ENGINE` and `RUBY_VERSION` constants to perform a similar check."
+
+ SharedHelpers.feature_removed!(removed_message)
+
+ send(:"maglev?") && send(:"on_#{trimmed_version}?")
+ end
end
end
end
diff --git a/lib/bundler/definition.rb b/lib/bundler/definition.rb
index 6cf1f9a255..5ab577f504 100644
--- a/lib/bundler/definition.rb
+++ b/lib/bundler/definition.rb
@@ -1,25 +1,27 @@
# frozen_string_literal: true
require_relative "lockfile_parser"
+require_relative "worker"
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_writer :lockfile
+
attr_reader(
:dependencies,
+ :locked_checksums,
:locked_deps,
:locked_gems,
:platforms,
:ruby_version,
:lockfile,
:gemfiles,
- :locked_checksums
+ :sources
)
# Given a gemfile and lockfile creates a Bundler definition
@@ -57,17 +59,30 @@ module Bundler
# @param ruby_version [Bundler::RubyVersion, nil] Requested Ruby Version
# @param optional_groups [Array(String)] A list of optional groups
def initialize(lockfile, dependencies, sources, unlock, ruby_version = nil, optional_groups = [], gemfiles = [])
- if [true, false].include?(unlock)
+ unlock ||= {}
+
+ if unlock == true
+ @unlocking_all = true
+ strict = false
@unlocking_bundler = false
@unlocking = unlock
+ @sources_to_unlock = []
+ @unlocking_ruby = false
+ @explicit_unlocks = []
+ conservative = false
else
+ @unlocking_all = false
+ strict = unlock.delete(:strict)
@unlocking_bundler = unlock.delete(:bundler)
@unlocking = unlock.any? {|_k, v| !Array(v).empty? }
+ @sources_to_unlock = unlock.delete(:sources) || []
+ @unlocking_ruby = unlock.delete(:ruby)
+ @explicit_unlocks = unlock.delete(:gems) || []
+ conservative = unlock.delete(:conservative)
end
@dependencies = dependencies
@sources = sources
- @unlock = unlock
@optional_groups = optional_groups
@prefer_local = false
@specs = nil
@@ -81,75 +96,67 @@ module Bundler
@resolved_bundler_version = nil
@locked_ruby_version = nil
- @new_platform = nil
- @removed_platform = nil
+ @new_platforms = []
+ @removed_platforms = []
+ @originally_invalid_platforms = []
if lockfile_exists?
@lockfile_contents = Bundler.read_file(lockfile)
- @locked_gems = LockfileParser.new(@lockfile_contents)
+ @locked_gems = LockfileParser.new(@lockfile_contents, strict: strict)
@locked_platforms = @locked_gems.platforms
+ @most_specific_locked_platform = @locked_gems.most_specific_locked_platform
@platforms = @locked_platforms.dup
@locked_bundler_version = @locked_gems.bundler_version
@locked_ruby_version = @locked_gems.ruby_version
- @originally_locked_deps = @locked_gems.dependencies
+ @locked_deps = @locked_gems.dependencies
@originally_locked_specs = SpecSet.new(@locked_gems.specs)
+ @originally_locked_sources = @locked_gems.sources
@locked_checksums = @locked_gems.checksums
- if unlock != true
- @locked_deps = @originally_locked_deps
- @locked_specs = @originally_locked_specs
- @locked_sources = @locked_gems.sources
- else
- @unlock = {}
- @locked_deps = {}
+ if @unlocking_all
@locked_specs = SpecSet.new([])
@locked_sources = []
+ else
+ @locked_specs = @originally_locked_specs
+ @locked_sources = @originally_locked_sources
end
- else
- @unlock = {}
- @platforms = []
- @locked_gems = nil
- @locked_deps = {}
- @locked_specs = SpecSet.new([])
- @originally_locked_deps = {}
- @originally_locked_specs = @locked_specs
- @locked_sources = []
- @locked_platforms = []
- @locked_checksums = nil
- end
- 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?
+ locked_gem_sources = @originally_locked_sources.select {|s| s.is_a?(Source::Rubygems) }
+ multisource_lockfile = locked_gem_sources.size == 1 && locked_gem_sources.first.multiple_remotes?
- if @multisource_allowed
- unless sources.aggregate_global_source?
+ if multisource_lockfile
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
+ Bundler::SharedHelpers.feature_removed! msg
end
-
- @sources.merged_gem_lockfile_sections!(locked_gem_sources.first)
+ else
+ @locked_gems = nil
+ @locked_platforms = []
+ @most_specific_locked_platform = nil
+ @platforms = []
+ @locked_deps = {}
+ @locked_specs = SpecSet.new([])
+ @locked_sources = []
+ @originally_locked_specs = @locked_specs
+ @originally_locked_sources = @locked_sources
+ @locked_checksums = Bundler.settings[:lockfile_checksums]
end
- @sources_to_unlock = @unlock.delete(:sources) || []
- @unlock[:ruby] ||= if @ruby_version && locked_ruby_version_object
+ @unlocking_ruby ||= if @ruby_version && locked_ruby_version_object
@ruby_version.diff(locked_ruby_version_object)
end
- @unlocking ||= @unlock[:ruby] ||= (!@locked_ruby_version ^ !@ruby_version)
+ @unlocking ||= @unlocking_ruby ||= (!@locked_ruby_version ^ !@ruby_version)
- add_current_platform unless Bundler.frozen_bundle?
+ @current_platform_missing = add_current_platform unless Bundler.frozen_bundle?
- converge_path_sources_to_gemspec_sources
- @path_changes = converge_paths
@source_changes = converge_sources
+ @path_changes = converge_paths
- @explicit_unlocks = @unlock.delete(:gems) || []
-
- if @unlock[:conservative]
+ if conservative
@gems_to_unlock = @explicit_unlocks.any? ? @explicit_unlocks : @dependencies.map(&:name)
else
eager_unlock = @explicit_unlocks.map {|name| Dependency.new(name, ">= 0") }
- @gems_to_unlock = @locked_specs.for(eager_unlock, false, platforms).map(&:name).uniq
+ @gems_to_unlock = @locked_specs.for(eager_unlock, platforms).map(&:name).uniq
end
@dependency_changes = converge_dependencies
@@ -162,25 +169,65 @@ module Bundler
@gem_version_promoter ||= GemVersionPromoter.new
end
- def resolve_only_locally!
+ def check!
+ # If dependencies have changed, we need to resolve remotely. Otherwise,
+ # since we'll be resolving with a single local source, we may end up
+ # locking gems under the wrong source in the lockfile, and missing lockfile
+ # checksums
+ resolve_remotely! if @dependency_changes
+
+ # Now do a local only resolve, to verify if any gems are missing locally
sources.local_only!
resolve
end
+ #
+ # Setup sources according to the given options and the state of the
+ # definition.
+ #
+ # @return [Boolean] Whether fetching remote information will be necessary or not
+ #
+ def setup_domain!(options = {})
+ prefer_local! if options[:"prefer-local"]
+
+ sources.cached!
+
+ if options[:add_checksums] || (!options[:local] && install_needed?)
+ sources.remote!
+ true
+ else
+ Bundler.settings.set_command_option(:jobs, 1) unless install_needed? # to avoid the overhead of Bundler::Worker
+ sources.local!
+ false
+ end
+ end
+
def resolve_with_cache!
+ with_cache!
+
+ resolve
+ end
+
+ def with_cache!
sources.local!
sources.cached!
- resolve
end
def resolve_remotely!
+ remotely!
+
+ resolve
+ end
+
+ def remotely!
sources.cached!
sources.remote!
- resolve
end
def prefer_local!
@prefer_local = true
+
+ sources.prefer_local!
end
# For given dependency list returns a SpecSet with Gemspec of all the required
@@ -202,7 +249,7 @@ module Bundler
end
def missing_specs
- resolve.materialize(requested_dependencies).missing_specs
+ resolve.missing_specs_for(requested_dependencies)
end
def missing_specs?
@@ -213,7 +260,8 @@ module Bundler
rescue BundlerError => e
@resolve = nil
@resolver = nil
- @resolution_packages = nil
+ @resolution_base = nil
+ @source_requirements = nil
@specs = nil
Bundler.ui.debug "The definition is missing dependencies, failed to resolve & materialize locally (#{e})"
@@ -237,12 +285,17 @@ module Bundler
end
def filter_relevant(dependencies)
- platforms_array = [generic_local_platform].freeze
dependencies.select do |d|
- d.should_include? && !d.gem_platforms(platforms_array).empty?
+ relevant_deps?(d)
end
end
+ def relevant_deps?(dep)
+ platforms_array = [Bundler.generic_local_platform].freeze
+
+ dep.should_include? && !dep.gem_platforms(platforms_array).empty?
+ end
+
def locked_dependencies
@locked_deps.values
end
@@ -265,11 +318,7 @@ module Bundler
groups.map!(&:to_sym)
deps = current_dependencies # always returns a new array
deps.select! do |d|
- if RUBY_VERSION >= "3.1"
- d.groups.intersect?(groups)
- else
- !(d.groups & groups).empty?
- end
+ d.groups.intersect?(groups)
end
deps
end
@@ -289,34 +338,30 @@ module Bundler
SpecSet.new(filter_specs(@locked_specs, @dependencies - deleted_deps))
else
Bundler.ui.debug "Found no changes, using resolution from the lockfile"
- if @removed_platform || @locked_gems.may_include_redundant_platform_specific_gems?
+ if @removed_platforms.any? || @locked_gems.may_include_redundant_platform_specific_gems?
SpecSet.new(filter_specs(@locked_specs, @dependencies))
else
@locked_specs
end
end
else
- if lockfile_exists?
- Bundler.ui.debug "Found changes from the lockfile, re-resolving dependencies because #{change_reason}"
- else
- Bundler.ui.debug "Resolving dependencies because there's no lockfile"
- end
+ Bundler.ui.debug resolve_needed_reason
start_resolution
end
end
def spec_git_paths
- sources.git_sources.map {|s| File.realpath(s.path) if File.exist?(s.path) }.compact
+ sources.git_sources.filter_map {|s| File.realpath(s.path) if File.exist?(s.path) }
end
def groups
- dependencies.map(&:groups).flatten.uniq
+ dependencies.flat_map(&:groups).uniq
end
def lock(file_or_preserve_unknown_sections = false, preserve_unknown_sections_or_unused = false)
if [true, false, nil].include?(file_or_preserve_unknown_sections)
- target_lockfile = lockfile || Bundler.default_lockfile
+ target_lockfile = lockfile
preserve_unknown_sections = file_or_preserve_unknown_sections
else
target_lockfile = file_or_preserve_unknown_sections
@@ -330,15 +375,53 @@ module Bundler
msg = "`Definition#lock` was passed a target file argument. #{suggestion}"
- Bundler::SharedHelpers.major_deprecation 2, msg
+ Bundler::SharedHelpers.feature_removed! msg
end
write_lock(target_lockfile, preserve_unknown_sections)
end
+ def write_lock(file, preserve_unknown_sections)
+ return if Definition.no_lock || !lockfile || file.nil?
+
+ contents = to_lock
+
+ # Convert to \r\n if the existing lock has them
+ # i.e., Windows with `git config core.autocrlf=true`
+ contents.gsub!(/\n/, "\r\n") if @lockfile_contents.match?("\r\n")
+
+ if @locked_bundler_version
+ locked_major = @locked_bundler_version.segments.first
+ current_major = bundler_version_to_lock.segments.first
+
+ updating_major = locked_major < current_major
+ end
+
+ preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler))
+
+ if File.exist?(file) && lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections)
+ return if Bundler.frozen_bundle?
+ SharedHelpers.filesystem_access(file) { FileUtils.touch(file) }
+ return
+ end
+
+ if Bundler.frozen_bundle?
+ Bundler.ui.error "Cannot write a changed lockfile while frozen."
+ return
+ end
+
+ begin
+ SharedHelpers.filesystem_access(file) do |p|
+ File.open(p, "wb") {|f| f.puts(contents) }
+ end
+ rescue ReadOnlyFileSystemError
+ raise ProductionError, lockfile_changes_summary("file system is read-only")
+ end
+ end
+
def locked_ruby_version
return unless ruby_version
- if @unlock[:ruby] || !@locked_ruby_version
+ if @unlocking_ruby || !@locked_ruby_version
Bundler::RubyVersion.system
else
@locked_ruby_version
@@ -367,51 +450,22 @@ module Bundler
end
def ensure_equivalent_gemfile_and_lockfile(explicit_flag = false)
- added = []
- deleted = []
- changed = []
+ return unless Bundler.frozen_bundle?
- new_platforms = @platforms - @locked_platforms
- deleted_platforms = @locked_platforms - @platforms
- added.concat new_platforms.map {|p| "* platform: #{p}" }
- deleted.concat deleted_platforms.map {|p| "* platform: #{p}" }
+ raise ProductionError, "Frozen mode is set, but there's no lockfile" unless lockfile_exists?
- 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?
-
- both_sources = Hash.new {|h, k| h[k] = [] }
- current_dependencies.each {|d| both_sources[d.name][0] = d }
- current_locked_dependencies.each {|d| both_sources[d.name][1] = d }
-
- both_sources.each do |name, (dep, lock_dep)|
- next if dep.nil? || lock_dep.nil?
-
- gemfile_source = dep.source || default_source
- lock_source = lock_dep.source || default_source
- next if lock_source.include?(gemfile_source)
-
- gemfile_source_name = dep.source ? gemfile_source.to_gemfile : "no specified source"
- lockfile_source_name = lock_dep.source ? lock_source.to_gemfile : "no specified source"
- changed << "* #{name} from `#{lockfile_source_name}` to `#{gemfile_source_name}`"
- end
-
- reason = change_reason
- msg = String.new
- msg << "#{reason.capitalize.strip}, but the lockfile can't be updated because frozen mode is set"
- msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any?
- msg << "\n\nYou have deleted from the Gemfile:\n" << deleted.join("\n") if deleted.any?
- msg << "\n\nYou have changed in the Gemfile:\n" << changed.join("\n") if changed.any?
- msg << "\n\nRun `bundle install` elsewhere and add the updated #{SharedHelpers.relative_gemfile_path} to version control.\n"
+ msg = lockfile_changes_summary("frozen mode is set")
+ return unless msg
unless explicit_flag
suggested_command = unless Bundler.settings.locations("frozen").keys.include?(:env)
"bundle config set frozen false"
end
- msg << "If this is a development machine, remove the #{SharedHelpers.relative_lockfile_path} " \
+ msg << "\n\nIf this is a development machine, remove the #{SharedHelpers.relative_lockfile_path} " \
"freeze by running `#{suggested_command}`." if suggested_command
end
- raise ProductionError, msg if added.any? || deleted.any? || changed.any? || !nothing_changed?
+ raise ProductionError, msg
end
def validate_runtime!
@@ -445,106 +499,142 @@ module Bundler
end
def validate_platforms!
- return if current_platform_locked?
+ return if current_platform_locked? || @platforms.include?(Gem::Platform::RUBY)
raise ProductionError, "Your bundle only supports platforms #{@platforms.map(&:to_s)} " \
- "but your local platform is #{local_platform}. " \
- "Add the current platform to the lockfile with\n`bundle lock --add-platform #{local_platform}` and try again."
+ "but your local platform is #{Bundler.local_platform}. " \
+ "Add the current platform to the lockfile with\n`bundle lock --add-platform #{Bundler.local_platform}` and try again."
+ end
+
+ def normalize_platforms
+ resolve.normalize_platforms!(current_dependencies, platforms)
+
+ @resolve = SpecSet.new(resolve.for(current_dependencies, @platforms))
end
def add_platform(platform)
- @new_platform ||= !@platforms.include?(platform)
- @platforms |= [platform]
+ return if @platforms.include?(platform)
+
+ @new_platforms << platform
+ @platforms << platform
end
def remove_platform(platform)
- removed_platform = @platforms.delete(Gem::Platform.new(platform))
- @removed_platform ||= removed_platform
- return if removed_platform
- raise InvalidOption, "Unable to remove the platform `#{platform}` since the only platforms are #{@platforms.join ", "}"
- end
+ raise InvalidOption, "Unable to remove the platform `#{platform}` since the only platforms are #{@platforms.join ", "}" unless @platforms.include?(platform)
- def most_specific_locked_platform
- @platforms.min_by do |bundle_platform|
- platform_specificity_match(bundle_platform, local_platform)
- end
+ @removed_platforms << platform
+ @platforms.delete(platform)
end
- attr_reader :sources
- private :sources
-
def nothing_changed?
- return false unless lockfile_exists?
-
- !@source_changes &&
- !@dependency_changes &&
- !@new_platform &&
- !@path_changes &&
- !@local_changes &&
- !@missing_lockfile_dep &&
- !@unlocking_bundler &&
- !@locked_spec_with_missing_deps &&
- !@locked_spec_with_invalid_deps
+ !something_changed?
end
def no_resolve_needed?
- !unlocking? && nothing_changed?
+ !resolve_needed?
end
def unlocking?
@unlocking
end
- private
+ def add_checksums
+ require "rubygems/package"
- def should_add_extra_platforms?
- !lockfile_exists? && generic_local_platform_is_ruby? && !Bundler.settings[:force_ruby_platform]
- end
+ @locked_checksums = true
- def lockfile_exists?
- file_exists?(lockfile)
- end
+ setup_domain!(add_checksums: true)
- def file_exists?(file)
- file && File.exist?(file)
+ # force materialization to real specifications, so that checksums are fetched
+ specs.each do |spec|
+ next unless spec.source.is_a?(Bundler::Source::Rubygems)
+ # Checksum was fetched from the compact index API.
+ next if !spec.source.checksum_store.missing?(spec) && !spec.source.checksum_store.empty?(spec)
+ # The gem isn't installed, can't compute the checksum.
+ next unless spec.loaded_from
+
+ package = Gem::Package.new(spec.source.cached_built_in_gem(spec))
+ checksum = Checksum.from_gem_package(package)
+ spec.source.checksum_store.register(spec, checksum)
+ end
end
- def write_lock(file, preserve_unknown_sections)
- return if Definition.no_lock
+ private
- contents = to_lock
+ def lockfile_changes_summary(update_refused_reason)
+ added = []
+ deleted = []
+ changed = []
- # Convert to \r\n if the existing lock has them
- # i.e., Windows with `git config core.autocrlf=true`
- contents.gsub!(/\n/, "\r\n") if @lockfile_contents.match?("\r\n")
+ added.concat @new_platforms.map {|p| "* platform: #{p}" }
+ deleted.concat @removed_platforms.map {|p| "* platform: #{p}" }
- if @locked_bundler_version
- locked_major = @locked_bundler_version.segments.first
- current_major = bundler_version_to_lock.segments.first
+ 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?
- updating_major = locked_major < current_major
- end
+ both_sources = Hash.new {|h, k| h[k] = [] }
+ current_dependencies.each {|d| both_sources[d.name][0] = d }
+ current_locked_dependencies.each {|d| both_sources[d.name][1] = d }
- preserve_unknown_sections ||= !updating_major && (Bundler.frozen_bundle? || !(unlocking? || @unlocking_bundler))
+ both_sources.each do |name, (dep, lock_dep)|
+ next if dep.nil? || lock_dep.nil?
- if file_exists?(file) && lockfiles_equal?(@lockfile_contents, contents, preserve_unknown_sections)
- return if Bundler.frozen_bundle?
- SharedHelpers.filesystem_access(file) { FileUtils.touch(file) }
- return
- end
+ gemfile_source = dep.source || default_source
+ lock_source = lock_dep.source || default_source
+ next if lock_source.include?(gemfile_source)
- if Bundler.frozen_bundle?
- Bundler.ui.error "Cannot write a changed lockfile while frozen."
- return
+ gemfile_source_name = dep.source ? gemfile_source.to_gemfile : "no specified source"
+ lockfile_source_name = lock_dep.source ? lock_source.to_gemfile : "no specified source"
+ changed << "* #{name} from `#{lockfile_source_name}` to `#{gemfile_source_name}`"
end
- SharedHelpers.filesystem_access(file) do |p|
- File.open(p, "wb") {|f| f.puts(contents) }
- end
+ return unless added.any? || deleted.any? || changed.any? || resolve_needed?
+
+ msg = String.new("#{change_reason[0].upcase}#{change_reason[1..-1].strip}, but ")
+ msg << "the lockfile " unless msg.start_with?("Your lockfile")
+ msg << "can't be updated because #{update_refused_reason}"
+ msg << "\n\nYou have added to the Gemfile:\n" << added.join("\n") if added.any?
+ msg << "\n\nYou have deleted from the Gemfile:\n" << deleted.join("\n") if deleted.any?
+ msg << "\n\nYou have changed in the Gemfile:\n" << changed.join("\n") if changed.any?
+ msg << "\n\nRun `bundle install` elsewhere and add the updated #{SharedHelpers.relative_lockfile_path} to version control.\n" unless unlocking?
+ msg
+ end
+
+ def install_needed?
+ resolve_needed? || missing_specs?
+ end
+
+ def something_changed?
+ return true unless lockfile_exists?
+
+ @source_changes ||
+ @dependency_changes ||
+ @current_platform_missing ||
+ @new_platforms.any? ||
+ @path_changes ||
+ @local_changes ||
+ @missing_lockfile_dep ||
+ @unlocking_bundler ||
+ @locked_spec_with_missing_checksums ||
+ @locked_spec_with_empty_checksums ||
+ @locked_spec_with_missing_deps ||
+ @locked_spec_with_invalid_deps
+ end
+
+ def resolve_needed?
+ unlocking? || something_changed?
+ end
+
+ def should_add_extra_platforms?
+ !lockfile_exists? && Bundler::MatchPlatform.generic_local_platform_is_ruby? && !Bundler.settings[:force_ruby_platform]
+ end
+
+ def lockfile_exists?
+ lockfile && File.exist?(lockfile)
end
def resolver
- @resolver ||= Resolver.new(resolution_packages, gem_version_promoter)
+ @resolver ||= new_resolver(resolution_base)
end
def expanded_dependencies
@@ -553,38 +643,56 @@ module Bundler
def dependencies_with_bundler
return dependencies unless @unlocking_bundler
- return dependencies if dependencies.map(&:name).include?("bundler")
+ return dependencies if dependencies.any? {|d| d.name == "bundler" }
[Dependency.new("bundler", @unlocking_bundler)] + dependencies
end
- def resolution_packages
- @resolution_packages ||= begin
+ def resolution_base
+ @resolution_base ||= begin
last_resolve = converge_locked_specs
- remove_invalid_platforms!(current_dependencies)
- packages = Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: @gems_to_unlock, prerelease: gem_version_promoter.pre?)
- packages = additional_base_requirements_to_prevent_downgrades(packages, last_resolve)
- packages = additional_base_requirements_to_force_updates(packages)
- packages
+ remove_invalid_platforms!
+ base = new_resolution_base(last_resolve: last_resolve, unlock: @unlocking_all || @gems_to_unlock)
+ base = additional_base_requirements_to_prevent_downgrades(base)
+ base = additional_base_requirements_to_force_updates(base)
+ base
end
end
- def filter_specs(specs, deps)
- SpecSet.new(specs).for(deps, false, platforms)
+ def filter_specs(specs, deps, skips: [])
+ SpecSet.new(specs).for(deps, platforms, skips: skips)
end
def materialize(dependencies)
- specs = resolve.materialize(dependencies)
- missing_specs = specs.missing_specs
+ specs = begin
+ resolve.materialize(dependencies)
+ rescue IncorrectLockfileDependencies => e
+ raise if Bundler.frozen_bundle?
+
+ reresolve_without([e.spec])
+ retry
+ end
+
+ missing_specs = resolve.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 || sources.local_mode?
- 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."
+
+ message = if sources.implicit_global_source?
+ "Because your Gemfile specifies no global remote source, your bundle is locked to " \
+ "#{locked_gem} from #{locked_gem.source}. However, #{locked_gem} is not installed. You'll " \
+ "need to either add a global remote source to your Gemfile or make sure #{locked_gem} is " \
+ "available locally before rerunning Bundler."
+ else
+ "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, message
end
missing_specs_list = missing_specs.group_by(&:source).map do |source, missing_specs_for_source|
@@ -594,104 +702,164 @@ module Bundler
raise GemNotFound, "Could not find #{missing_specs_list.join(" nor ")}"
end
- incomplete_specs = specs.incomplete_specs
+ partially_missing_specs = resolve.partially_missing_specs
+
+ if partially_missing_specs.any? && !sources.local_mode?
+ Bundler.ui.warn "Some locked specs have possibly been yanked (#{partially_missing_specs.map(&:full_name).join(", ")}). Ignoring them..."
+
+ resolve.delete(partially_missing_specs)
+ end
+
+ incomplete_specs = resolve.incomplete_specs
loop do
break if incomplete_specs.empty?
Bundler.ui.debug("The lockfile does not have all gems needed for the current platform though, Bundler will still re-resolve dependencies")
sources.remote!
- resolution_packages.delete(incomplete_specs)
- @resolve = start_resolution
+ reresolve_without(incomplete_specs)
specs = resolve.materialize(dependencies)
- still_incomplete_specs = specs.incomplete_specs
+ still_incomplete_specs = resolve.incomplete_specs
if still_incomplete_specs == incomplete_specs
- package = resolution_packages.get_package(incomplete_specs.first.name)
- resolver.raise_not_found! package
+ resolver.raise_incomplete! incomplete_specs
end
incomplete_specs = still_incomplete_specs
end
+ insecurely_materialized_specs = resolve.insecurely_materialized_specs
+
+ if insecurely_materialized_specs.any?
+ Bundler.ui.warn "The following platform specific gems are getting installed, yet the lockfile includes only their generic ruby version:\n" \
+ " * #{insecurely_materialized_specs.map(&:full_name).join("\n * ")}\n" \
+ "Please run `bundle lock --normalize-platforms` and commit the resulting lockfile.\n" \
+ "Alternatively, you may run `bundle lock --add-platform <list-of-platforms-that-you-want-to-support>`"
+ end
+
bundler = sources.metadata_source.specs.search(["bundler", Bundler.gem_version]).last
specs["bundler"] = bundler
specs
end
+ def reresolve_without(incomplete_specs)
+ resolution_base.delete(incomplete_specs)
+ @resolve = start_resolution
+ end
+
def start_resolution
+ local_platform_needed_for_resolvability = @most_specific_non_local_locked_platform && !@platforms.include?(Bundler.local_platform)
+ @platforms << Bundler.local_platform if local_platform_needed_for_resolvability
+
result = SpecSet.new(resolver.start)
@resolved_bundler_version = result.find {|spec| spec.name == "bundler" }&.version
- @platforms = result.add_extra_platforms!(platforms) if should_add_extra_platforms?
- result.complete_platforms!(platforms)
-
- SpecSet.new(result.for(dependencies, false, @platforms))
- end
+ @new_platforms.each do |platform|
+ incomplete_specs = result.incomplete_specs_for_platform(current_dependencies, platform)
- def precompute_source_requirements_for_indirect_dependencies?
- sources.non_global_rubygems_sources.all?(&:dependency_api_available?) && !sources.aggregate_global_source?
- end
-
- def pin_locally_available_names(source_requirements)
- source_requirements.each_with_object({}) do |(name, original_source), new_source_requirements|
- local_source = original_source.dup
- local_source.local_only!
+ if incomplete_specs.any?
+ resolver.raise_incomplete! incomplete_specs
+ end
+ end
- new_source_requirements[name] = if local_source.specs.search(name).any?
- local_source
- else
- original_source
+ if @most_specific_non_local_locked_platform
+ if result.incomplete_for_platform?(current_dependencies, @most_specific_non_local_locked_platform)
+ @platforms.delete(@most_specific_non_local_locked_platform)
+ elsif local_platform_needed_for_resolvability
+ @platforms.delete(Bundler.local_platform)
end
end
- end
- def current_ruby_platform_locked?
- return false unless generic_local_platform_is_ruby?
- return false if Bundler.settings[:force_ruby_platform] && !@platforms.include?(Gem::Platform::RUBY)
+ if should_add_extra_platforms?
+ result.add_extra_platforms!(platforms)
+ elsif @originally_invalid_platforms.any?
+ result.add_originally_invalid_platforms!(platforms, @originally_invalid_platforms)
+ end
- current_platform_locked?
+ SpecSet.new(result.for(dependencies, @platforms | [Gem::Platform::RUBY]))
+ end
+
+ def precompute_source_requirements_for_indirect_dependencies?
+ sources.non_global_rubygems_sources.all?(&:dependency_api_available?)
end
def current_platform_locked?
@platforms.any? do |bundle_platform|
- MatchPlatform.platforms_match?(bundle_platform, local_platform)
+ Bundler.generic_local_platform == bundle_platform || Bundler.local_platform === bundle_platform
end
end
def add_current_platform
- return if current_ruby_platform_locked?
+ return if @platforms.include?(Bundler.local_platform)
+
+ @most_specific_non_local_locked_platform = find_most_specific_locked_platform
+ return if @most_specific_non_local_locked_platform
+
+ @platforms << Bundler.local_platform
+ true
+ end
+
+ def find_most_specific_locked_platform
+ return unless current_platform_locked?
- add_platform(local_platform)
+ @most_specific_locked_platform
end
- def change_reason
- if unlocking?
- unlock_targets = if @gems_to_unlock.any?
- ["gems", @gems_to_unlock]
- elsif @sources_to_unlock.any?
- ["sources", @sources_to_unlock]
+ def resolve_needed_reason
+ if lockfile_exists?
+ if unlocking?
+ "Re-resolving dependencies because #{unlocking_reason}"
+ else
+ "Found changes from the lockfile, re-resolving dependencies because #{lockfile_changed_reason}"
end
+ else
+ "Resolving dependencies because there's no lockfile"
+ end
+ end
- unlock_reason = if unlock_targets
- "#{unlock_targets.first}: (#{unlock_targets.last.join(", ")})"
+ def change_reason
+ if resolve_needed?
+ if unlocking?
+ unlocking_reason
else
- @unlock[:ruby] ? "ruby" : ""
+ lockfile_changed_reason
end
+ else
+ "some dependencies were deleted from your gemfile"
+ end
+ end
+
+ def unlocking_reason
+ unlock_targets = if @gems_to_unlock.any?
+ ["gems", @gems_to_unlock]
+ elsif @sources_to_unlock.any?
+ ["sources", @sources_to_unlock]
+ end
- return "bundler is unlocking #{unlock_reason}"
+ unlock_reason = if unlock_targets
+ "#{unlock_targets.first}: (#{unlock_targets.last.join(", ")})"
+ else
+ @unlocking_ruby ? "ruby" : ""
end
+
+ "bundler is unlocking #{unlock_reason}"
+ end
+
+ def lockfile_changed_reason
[
[@source_changes, "the list of sources changed"],
[@dependency_changes, "the dependencies in your gemfile changed"],
- [@new_platform, "you added a new platform to your gemfile"],
+ [@current_platform_missing, "your lockfile is missing the current platform"],
+ [@new_platforms.any?, "you are adding a new platform to your lockfile"],
[@path_changes, "the gemspecs for path gems changed"],
[@local_changes, "the gemspecs for git local gems changed"],
- [@missing_lockfile_dep, "your lock file is missing \"#{@missing_lockfile_dep}\""],
+ [@missing_lockfile_dep, "your lockfile is missing \"#{@missing_lockfile_dep}\""],
[@unlocking_bundler, "an update to the version of Bundler itself was requested"],
- [@locked_spec_with_missing_deps, "your lock file includes \"#{@locked_spec_with_missing_deps}\" but not some of its dependencies"],
+ [@locked_spec_with_missing_checksums, "your lockfile is missing a CHECKSUMS entry for \"#{@locked_spec_with_missing_checksums}\""],
+ [@locked_spec_with_empty_checksums, "your lockfile has an empty CHECKSUMS entry for \"#{@locked_spec_with_empty_checksums}\""],
+ [@locked_spec_with_missing_deps, "your lockfile includes \"#{@locked_spec_with_missing_deps}\" but not some of its dependencies"],
[@locked_spec_with_invalid_deps, "your lockfile does not satisfy dependencies of \"#{@locked_spec_with_invalid_deps}\""],
].select(&:first).map(&:last).join(", ")
end
@@ -708,8 +876,8 @@ module Bundler
!locked || dependencies_for_source_changed?(source, locked) || specs_for_source_changed?(source)
end
- def dependencies_for_source_changed?(source, locked_source = source)
- deps_for_source = @dependencies.select {|s| s.source == source }
+ def dependencies_for_source_changed?(source, locked_source)
+ deps_for_source = @dependencies.select {|dep| dep.source == source }
locked_deps_for_source = locked_dependencies.select {|dep| dep.source == locked_source }
deps_for_source.uniq.sort != locked_deps_for_source.sort
@@ -717,7 +885,7 @@ module Bundler
def specs_for_source_changed?(source)
locked_index = Index.new
- locked_index.use(@locked_specs.select {|s| source.can_lock?(s) })
+ locked_index.use(@locked_specs.select {|s| s.replace_source_with!(source) })
!locked_index.subset?(source.specs)
rescue PathError, GitError => e
@@ -747,29 +915,40 @@ module Bundler
end
def check_lockfile
- @missing_lockfile_dep = nil
-
@locked_spec_with_invalid_deps = nil
@locked_spec_with_missing_deps = nil
+ @locked_spec_with_missing_checksums = nil
+ @locked_spec_with_empty_checksums = nil
- missing = []
+ missing_deps = []
+ missing_checksums = []
+ empty_checksums = []
invalid = []
@locked_specs.each do |s|
+ if @locked_checksums
+ checksum_store = s.source.checksum_store
+
+ if checksum_store.missing?(s)
+ missing_checksums << s
+ elsif checksum_store.empty?(s)
+ empty_checksums << s
+ end
+ end
+
validation = @locked_specs.validate_deps(s)
- missing << s if validation == :missing
+ missing_deps << s if validation == :missing
invalid << s if validation == :invalid
end
- if missing.any?
- @locked_specs.delete(missing)
+ @locked_spec_with_missing_checksums = missing_checksums.first.name if missing_checksums.any?
+ @locked_spec_with_empty_checksums = empty_checksums.first.name if empty_checksums.any?
+
+ if missing_deps.any?
+ @locked_specs.delete(missing_deps)
- @locked_spec_with_missing_deps = missing.first.name
- elsif !@dependency_changes
- @missing_lockfile_dep = current_dependencies.find do |d|
- @locked_specs[d.name].empty? && d.name != "bundler"
- end&.name
+ @locked_spec_with_missing_deps = missing_deps.first.name
end
if invalid.any?
@@ -785,24 +964,6 @@ module Bundler
end
end
- def converge_path_source_to_gemspec_source(source)
- return source unless source.instance_of?(Source::Path)
- gemspec_source = sources.path_sources.find {|s| s.is_a?(Source::Gemspec) && s.as_path_source == source }
- gemspec_source || source
- end
-
- def converge_path_sources_to_gemspec_sources
- @locked_sources.map! do |source|
- converge_path_source_to_gemspec_source(source)
- end
- @locked_specs.each do |spec|
- spec.source &&= converge_path_source_to_gemspec_source(spec.source)
- end
- @locked_deps.each do |_, dep|
- dep.source &&= converge_path_source_to_gemspec_source(dep.source)
- end
- end
-
def converge_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
@@ -812,7 +973,7 @@ module Bundler
sources.all_sources.each do |source|
# has to be done separately, because we want to keep the locked checksum
# store for a source, even when doing a full update
- if @locked_checksums && @locked_gems && locked_source = @locked_gems.sources.find {|s| s == source && !s.equal?(source) }
+ if @locked_checksums && @locked_gems && locked_source = @originally_locked_sources.find {|s| s == source && !s.equal?(source) }
source.checksum_store.merge!(locked_source.checksum_store)
end
# If the source is unlockable and the current command allows an unlock of
@@ -830,32 +991,40 @@ module Bundler
end
def converge_dependencies
- changes = false
+ @missing_lockfile_dep = nil
+ @changed_dependencies = []
@dependencies.each do |dep|
if dep.source
dep.source = sources.get(dep.source)
end
+ next unless relevant_deps?(dep)
- unless locked_dep = @originally_locked_deps[dep.name]
- changes = true
- next
+ name = dep.name
+
+ dep_changed = @locked_deps[name].nil?
+
+ unless name == "bundler"
+ locked_specs = @originally_locked_specs[name]
+
+ if locked_specs.empty?
+ @missing_lockfile_dep = name if dep_changed == false
+ else
+ if locked_specs.map(&:source).uniq.size > 1
+ @locked_specs.delete(locked_specs.select {|s| s.source != dep.source })
+ end
+
+ unless dep.matches_spec?(locked_specs.first)
+ @gems_to_unlock << name
+ dep_changed = true
+ end
+ end
end
- # Gem::Dependency#== matches Gem::Dependency#type. As the lockfile
- # doesn't carry a notion of the dependency type, if you use
- # add_development_dependency in a gemspec that's loaded with the gemspec
- # 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, dep.type)
-
- # We already know the name matches from the hash lookup
- # so we only need to check the requirement now
- changes ||= dep.requirement != locked_dep.requirement
+ @changed_dependencies << name if dep_changed
end
- changes
+ @changed_dependencies.any?
end
# Remove elements from the locked specs that are expired. This will most
@@ -864,7 +1033,7 @@ module Bundler
def converge_locked_specs
converged = converge_specs(@locked_specs)
- resolve = SpecSet.new(converged.reject {|s| @gems_to_unlock.include?(s.name) })
+ resolve = SpecSet.new(converged)
diff = nil
@@ -885,46 +1054,48 @@ module Bundler
converged = []
deps = []
- @specs_that_changed_sources = []
-
specs.each do |s|
name = s.name
+ next if @gems_to_unlock.include?(name)
+
dep = @dependencies.find {|d| s.satisfies?(d) }
lockfile_source = s.source
if dep
- gemfile_source = dep.source || default_source
-
- @specs_that_changed_sources << s if gemfile_source != lockfile_source
- deps << dep if !dep.source || lockfile_source.include?(dep.source)
- @gems_to_unlock << name if lockfile_source.include?(dep.source) && lockfile_source != gemfile_source
+ replacement_source = dep.source
- # Replace the locked dependency's source with the equivalent source from the Gemfile
- s.source = gemfile_source
+ deps << dep if !replacement_source || lockfile_source.include?(replacement_source) || new_deps.include?(dep)
else
- # Replace the locked dependency's source with the default source, if the locked source is no longer in the Gemfile
- s.source = default_source unless sources.get(lockfile_source)
- end
+ parent_dep = @dependencies.find do |d|
+ next unless d.source && d.source != lockfile_source
+ next if d.source.is_a?(Source::Gemspec)
- next if @sources_to_unlock.include?(s.source.name)
+ parent_locked_specs = @originally_locked_specs[d.name]
- # Path sources have special logic
- if s.source.instance_of?(Source::Path) || s.source.instance_of?(Source::Gemspec)
- new_specs = begin
- s.source.specs
- rescue PathError
- # if we won't need the source (according to the lockfile),
- # don't error if the path source isn't available
- next if specs.
- for(requested_dependencies, false).
- none? {|locked_spec| locked_spec.source == s.source }
-
- raise
+ parent_locked_specs.any? do |parent_spec|
+ parent_spec.runtime_dependencies.any? {|rd| rd.name == s.name }
+ end
end
- new_spec = new_specs[s].first
+ if parent_dep
+ replacement_source = parent_dep.source
+ else
+ replacement_source = sources.get(lockfile_source)
+ end
+ end
+
+ # Replace the locked dependency's source with the equivalent source from the Gemfile
+ s.source = replacement_source || default_source
+ next if s.source_changed?
+
+ source = s.source
+ next if @sources_to_unlock.include?(source.name)
+
+ # Path sources have special logic
+ if source.is_a?(Source::Path)
+ new_spec = source.specs[s].first
if new_spec
- s.dependencies.replace(new_spec.dependencies)
+ s.runtime_dependencies.replace(new_spec.runtime_dependencies)
else
# If the spec is no longer in the path source, unlock it. This
# commonly happens if the version changed in the gemspec
@@ -932,14 +1103,10 @@ module Bundler
end
end
- if dep.nil? && requested_dependencies.find {|d| name == d.name }
- @gems_to_unlock << s.name
- else
- converged << s
- end
+ converged << s
end
- filter_specs(converged, deps)
+ filter_specs(converged, deps, skips: @gems_to_unlock)
end
def metadata_dependencies
@@ -950,12 +1117,31 @@ module Bundler
end
def source_requirements
+ @source_requirements ||= find_source_requirements
+ end
+
+ def preload_git_source_worker
+ @preload_git_source_worker ||= Bundler::Worker.new(5, "Git source preloading", ->(source, _) { source.specs })
+ end
+
+ def preload_git_sources
+ sources.git_sources.each {|source| preload_git_source_worker.enq(source) }
+ ensure
+ preload_git_source_worker.stop
+ end
+
+ def find_source_requirements
+ if Gem.ruby_version >= Gem::Version.new("3.3")
+ # Ruby 3.2 has a bug that incorrectly triggers a circular dependency warning. This version will continue to
+ # fetch git repositories one by one.
+ preload_git_sources
+ end
+
# 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)
source_requirements = if precompute_source_requirements_for_indirect_dependencies?
all_requirements = source_map.all_requirements
- all_requirements = pin_locally_available_names(all_requirements) if @prefer_local
{ default: default_source }.merge(all_requirements)
else
{ default: Source::RubygemsAggregate.new(sources, source_map) }.merge(source_map.direct_requirements)
@@ -974,7 +1160,6 @@ module Bundler
source_requirements["bundler"] = sources.metadata_source # needs to come last to override
end
- verify_changed_sources!
source_requirements
end
@@ -982,14 +1167,6 @@ module Bundler
sources.default_source
end
- def verify_changed_sources!
- @specs_that_changed_sources.each do |s|
- if s.source.specs.search(s.name).empty?
- raise GemNotFound, "Could not find gem '#{s.name}' in #{s.source}"
- end
- end
- end
-
def requested_groups
values = groups - Bundler.settings[:without] - @optional_groups + Bundler.settings[:with]
values &= Bundler.settings[:only] unless Bundler.settings[:only].empty?
@@ -1010,52 +1187,63 @@ module Bundler
current == proposed
end
- def additional_base_requirements_to_prevent_downgrades(resolution_packages, last_resolve)
- return resolution_packages unless @locked_gems && !sources.expired_sources?(@locked_gems.sources)
- converge_specs(@originally_locked_specs - last_resolve).each do |locked_spec|
- next if locked_spec.source.is_a?(Source::Path)
- resolution_packages.base_requirements[locked_spec.name] = Gem::Requirement.new(">= #{locked_spec.version}")
- end
- resolution_packages
- end
+ def additional_base_requirements_to_prevent_downgrades(resolution_base)
+ return resolution_base unless @locked_gems
+ @originally_locked_specs.each do |locked_spec|
+ next if locked_spec.source.is_a?(Source::Path) || locked_spec.source_changed?
- def additional_base_requirements_to_force_updates(resolution_packages)
- return resolution_packages if @explicit_unlocks.empty?
- full_update = dup_for_full_unlock.resolve
- @explicit_unlocks.each do |name|
- version = full_update[name].first&.version
- resolution_packages.base_requirements[name] = Gem::Requirement.new("= #{version}") if version
+ name = locked_spec.name
+ next if @changed_dependencies.include?(name)
+
+ resolution_base.base_requirements[name] = Gem::Requirement.new(">= #{locked_spec.version}")
end
- resolution_packages
+ resolution_base
end
- def dup_for_full_unlock
- unlocked_definition = self.class.new(@lockfile, @dependencies, @sources, true, @ruby_version, @optional_groups, @gemfiles)
- unlocked_definition.gem_version_promoter.tap do |gvp|
- gvp.level = gem_version_promoter.level
- gvp.strict = gem_version_promoter.strict
- gvp.pre = gem_version_promoter.pre
+ def additional_base_requirements_to_force_updates(resolution_base)
+ return resolution_base if @explicit_unlocks.empty?
+ full_update = SpecSet.new(new_resolver_for_full_update.start)
+ @explicit_unlocks.each do |name|
+ version = full_update.version_for(name)
+ resolution_base.base_requirements[name] = Gem::Requirement.new("= #{version}") if version
end
- unlocked_definition
+ resolution_base
end
- def remove_invalid_platforms!(dependencies)
+ def remove_invalid_platforms!
return if Bundler.frozen_bundle?
- platforms.reverse_each do |platform|
- next if local_platform == platform ||
- (@new_platform && platforms.last == platform) ||
- @path_changes ||
- @dependency_changes ||
- !@originally_locked_specs.incomplete_for_platform?(dependencies, platform)
+ skips = (@new_platforms + [Bundler.local_platform]).uniq
- remove_platform(platform)
- add_current_platform if platform == Gem::Platform::RUBY
- end
+ # We should probably avoid removing non-ruby platforms, since that means
+ # lockfile will no longer install on those platforms, so a error to give
+ # heads up to the user may be better. However, we have tests expecting
+ # non ruby platform autoremoval to work, so leaving that in place for
+ # now.
+ skips |= platforms - [Gem::Platform::RUBY] if @dependency_changes
+
+ @originally_invalid_platforms = @originally_locked_specs.remove_invalid_platforms!(current_dependencies, platforms, skips: skips)
end
def source_map
@source_map ||= SourceMap.new(sources, dependencies, @locked_specs)
end
+
+ def new_resolver_for_full_update
+ new_resolver(unlocked_resolution_base)
+ end
+
+ def unlocked_resolution_base
+ new_resolution_base(last_resolve: SpecSet.new([]), unlock: true)
+ end
+
+ def new_resolution_base(last_resolve:, unlock:)
+ new_resolution_platforms = @current_platform_missing ? @new_platforms + [Bundler.local_platform] : @new_platforms
+ Resolver::Base.new(source_requirements, expanded_dependencies, last_resolve, @platforms, locked_specs: @originally_locked_specs, unlock: unlock, prerelease: gem_version_promoter.pre?, prefer_local: @prefer_local, new_platforms: new_resolution_platforms)
+ end
+
+ def new_resolver(base)
+ Resolver.new(base, gem_version_promoter, @most_specific_locked_platform)
+ end
end
end
diff --git a/lib/bundler/dependency.rb b/lib/bundler/dependency.rb
index 2a4f72fe55..cb9c7a76ea 100644
--- a/lib/bundler/dependency.rb
+++ b/lib/bundler/dependency.rb
@@ -2,51 +2,92 @@
require "rubygems/dependency"
require_relative "shared_helpers"
-require_relative "rubygems_ext"
module Bundler
class Dependency < Gem::Dependency
- attr_reader :autorequire
- attr_reader :groups, :platforms, :gemfile, :path, :git, :github, :branch, :ref, :glob
-
- ALL_RUBY_VERSIONS = (18..27).to_a.concat((30..34).to_a).freeze
- PLATFORM_MAP = {
- ruby: [Gem::Platform::RUBY, ALL_RUBY_VERSIONS],
- mri: [Gem::Platform::RUBY, ALL_RUBY_VERSIONS],
- rbx: [Gem::Platform::RUBY],
- truffleruby: [Gem::Platform::RUBY],
- jruby: [Gem::Platform::JAVA, [18, 19]],
- windows: [Gem::Platform::WINDOWS, ALL_RUBY_VERSIONS],
- # deprecated
- mswin: [Gem::Platform::MSWIN, ALL_RUBY_VERSIONS],
- mswin64: [Gem::Platform::MSWIN64, ALL_RUBY_VERSIONS - [18]],
- mingw: [Gem::Platform::MINGW, ALL_RUBY_VERSIONS],
- x64_mingw: [Gem::Platform::X64_MINGW, ALL_RUBY_VERSIONS - [18, 19]],
- }.each_with_object({}) do |(platform, spec), hash|
- hash[platform] = spec[0]
- spec[1]&.each {|version| hash[:"#{platform}_#{version}"] = spec[0] }
- end.freeze
-
def initialize(name, version, options = {}, &blk)
type = options["type"] || :runtime
super(name, version, type)
- @autorequire = nil
- @groups = Array(options["group"] || :default).map(&:to_sym)
- @source = options["source"]
- @path = options["path"]
- @git = options["git"]
- @github = options["github"]
- @branch = options["branch"]
- @ref = options["ref"]
- @glob = options["glob"]
- @platforms = Array(options["platforms"])
- @env = options["env"]
- @should_include = options.fetch("should_include", true)
- @gemfile = options["gemfile"]
- @force_ruby_platform = options["force_ruby_platform"] if options.key?("force_ruby_platform")
+ @options = options
+ end
+
+ def groups
+ @groups ||= Array(@options["group"] || :default).map(&:to_sym)
+ end
+
+ def source
+ return @source if defined?(@source)
+
+ @source = @options["source"]
+ end
+
+ def path
+ return @path if defined?(@path)
+
+ @path = @options["path"]
+ end
+
+ def git
+ return @git if defined?(@git)
- @autorequire = Array(options["require"] || []) if options.key?("require")
+ @git = @options["git"]
+ end
+
+ def github
+ return @github if defined?(@github)
+
+ @github = @options["github"]
+ end
+
+ def branch
+ return @branch if defined?(@branch)
+
+ @branch = @options["branch"]
+ end
+
+ def ref
+ return @ref if defined?(@ref)
+
+ @ref = @options["ref"]
+ end
+
+ def glob
+ return @glob if defined?(@glob)
+
+ @glob = @options["glob"]
+ end
+
+ def platforms
+ @platforms ||= Array(@options["platforms"])
+ end
+
+ def env
+ return @env if defined?(@env)
+
+ @env = @options["env"]
+ end
+
+ def should_include
+ @should_include ||= @options.fetch("should_include", true)
+ end
+
+ def gemfile
+ return @gemfile if defined?(@gemfile)
+
+ @gemfile = @options["gemfile"]
+ end
+
+ def force_ruby_platform
+ return @force_ruby_platform if defined?(@force_ruby_platform)
+
+ @force_ruby_platform = @options["force_ruby_platform"]
+ end
+
+ def autorequire
+ return @autorequire if defined?(@autorequire)
+
+ @autorequire = Array(@options["require"] || []) if @options.key?("require")
end
RUBY_PLATFORM_ARRAY = [Gem::Platform::RUBY].freeze
@@ -56,37 +97,41 @@ module Bundler
# passed in the `valid_platforms` parameter
def gem_platforms(valid_platforms)
return RUBY_PLATFORM_ARRAY if force_ruby_platform
- return valid_platforms if @platforms.empty?
+ return valid_platforms if platforms.empty?
- valid_platforms.select {|p| expanded_platforms.include?(GemHelpers.generic(p)) }
+ valid_platforms.select {|p| expanded_platforms.include?(Gem::Platform.generic(p)) }
end
def expanded_platforms
- @expanded_platforms ||= @platforms.map {|pl| PLATFORM_MAP[pl] }.compact.flatten.uniq
+ @expanded_platforms ||= platforms.filter_map {|pl| CurrentRuby::PLATFORM_MAP[pl] }.flatten.uniq
end
def should_include?
- @should_include && current_env? && current_platform?
+ should_include && current_env? && current_platform?
end
def gemspec_dev_dep?
- type == :development
+ @gemspec_dev_dep ||= @options.fetch("gemspec_dev_dep", false)
+ end
+
+ def gemfile_dep?
+ !gemspec_dev_dep?
end
def current_env?
- return true unless @env
- if @env.is_a?(Hash)
- @env.all? do |key, val|
+ return true unless env
+ if env.is_a?(Hash)
+ env.all? do |key, val|
ENV[key.to_s] && (val.is_a?(String) ? ENV[key.to_s] == val : ENV[key.to_s] =~ val)
end
else
- ENV[@env.to_s]
+ ENV[env.to_s]
end
end
def current_platform?
- return true if @platforms.empty?
- @platforms.any? do |p|
+ return true if platforms.empty?
+ platforms.any? do |p|
Bundler.current_ruby.send("#{p}?")
end
end
diff --git a/lib/bundler/deployment.rb b/lib/bundler/deployment.rb
index b432ae6ae1..3344449e82 100644
--- a/lib/bundler/deployment.rb
+++ b/lib/bundler/deployment.rb
@@ -1,69 +1,6 @@
# frozen_string_literal: true
require_relative "shared_helpers"
-Bundler::SharedHelpers.major_deprecation 2, "Bundler no longer integrates with " \
+Bundler::SharedHelpers.feature_removed! "Bundler no longer integrates with " \
"Capistrano, but Capistrano provides its own integration with " \
"Bundler via the capistrano-bundler gem. Use it instead."
-
-module Bundler
- class Deployment
- def self.define_task(context, task_method = :task, opts = {})
- if defined?(Capistrano) && context.is_a?(Capistrano::Configuration)
- context_name = "capistrano"
- role_default = "{:except => {:no_release => true}}"
- error_type = ::Capistrano::CommandError
- else
- context_name = "vlad"
- role_default = "[:app]"
- error_type = ::Rake::CommandFailedError
- end
-
- roles = context.fetch(:bundle_roles, false)
- opts[:roles] = roles if roles
-
- context.send :namespace, :bundle do
- send :desc, <<-DESC
- Install the current Bundler environment. By default, gems will be \
- installed to the shared/bundle path. Gems in the development and \
- test group will not be installed. The install command is executed \
- with the --deployment and --quiet flags. If the bundle cmd cannot \
- be found then you can override the bundle_cmd variable to specify \
- which one it should use. The base path to the app is fetched from \
- the :latest_release variable. Set it for custom deploy layouts.
-
- You can override any of these defaults by setting the variables shown below.
-
- N.B. bundle_roles must be defined before you require 'bundler/#{context_name}' \
- in your deploy.rb file.
-
- set :bundle_gemfile, "Gemfile"
- set :bundle_dir, File.join(fetch(:shared_path), 'bundle')
- set :bundle_flags, "--deployment --quiet"
- set :bundle_without, [:development, :test]
- set :bundle_with, [:mysql]
- set :bundle_cmd, "bundle" # e.g. "/opt/ruby/bin/bundle"
- set :bundle_roles, #{role_default} # e.g. [:app, :batch]
- DESC
- send task_method, :install, opts do
- bundle_cmd = context.fetch(:bundle_cmd, "bundle")
- bundle_flags = context.fetch(:bundle_flags, "--deployment --quiet")
- bundle_dir = context.fetch(:bundle_dir, File.join(context.fetch(:shared_path), "bundle"))
- bundle_gemfile = context.fetch(:bundle_gemfile, "Gemfile")
- bundle_without = [*context.fetch(:bundle_without, [:development, :test])].compact
- bundle_with = [*context.fetch(:bundle_with, [])].compact
- app_path = context.fetch(:latest_release)
- if app_path.to_s.empty?
- raise error_type.new("Cannot detect current release path - make sure you have deployed at least once.")
- end
- args = ["--gemfile #{File.join(app_path, bundle_gemfile)}"]
- args << "--path #{bundle_dir}" unless bundle_dir.to_s.empty?
- args << bundle_flags.to_s
- args << "--without #{bundle_without.join(" ")}" unless bundle_without.empty?
- args << "--with #{bundle_with.join(" ")}" unless bundle_with.empty?
-
- run "cd #{app_path} && #{bundle_cmd} install #{args.join(" ")}"
- end
- end
- end
- end
-end
diff --git a/lib/bundler/digest.rb b/lib/bundler/digest.rb
index 2c6d971f1b..158803033d 100644
--- a/lib/bundler/digest.rb
+++ b/lib/bundler/digest.rb
@@ -26,7 +26,7 @@ module Bundler
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)
+ 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
diff --git a/lib/bundler/dsl.rb b/lib/bundler/dsl.rb
index 6af80fb31f..6f06c4e918 100644
--- a/lib/bundler/dsl.rb
+++ b/lib/bundler/dsl.rb
@@ -9,14 +9,15 @@ module Bundler
def self.evaluate(gemfile, lockfile, unlock)
builder = new
+ builder.lockfile(lockfile)
builder.eval_gemfile(gemfile)
- builder.to_definition(lockfile, unlock)
+ builder.to_definition(builder.lockfile_path, unlock)
end
- VALID_PLATFORMS = Bundler::Dependency::PLATFORM_MAP.keys.freeze
+ VALID_PLATFORMS = Bundler::CurrentRuby::PLATFORM_MAP.keys.freeze
VALID_KEYS = %w[group groups git path glob name branch ref tag require submodules
- platform platforms type source install_if gemfile force_ruby_platform].freeze
+ platform platforms source install_if force_ruby_platform].freeze
GITHUB_PULL_REQUEST_URL = %r{\Ahttps://github\.com/([A-Za-z0-9_\-\.]+/[A-Za-z0-9_\-\.]+)/pull/(\d+)\z}
GITLAB_MERGE_REQUEST_URL = %r{\Ahttps://gitlab\.com/([A-Za-z0-9_\-\./]+)/-/merge_requests/(\d+)\z}
@@ -38,24 +39,25 @@ module Bundler
@gemspecs = []
@gemfile = nil
@gemfiles = []
+ @lockfile = nil
add_git_sources
end
def eval_gemfile(gemfile, contents = nil)
- expanded_gemfile_path = Pathname.new(gemfile).expand_path(@gemfile&.parent)
- original_gemfile = @gemfile
- @gemfile = expanded_gemfile_path
- @gemfiles << expanded_gemfile_path
- contents ||= Bundler.read_file(@gemfile.to_s)
- instance_eval(contents, @gemfile.to_s, 1)
- rescue Exception => e # rubocop:disable Lint/RescueException
- message = "There was an error " \
- "#{e.is_a?(GemfileEvalError) ? "evaluating" : "parsing"} " \
- "`#{File.basename gemfile.to_s}`: #{e.message}"
-
- raise DSLError.new(message, gemfile, e.backtrace, contents)
- ensure
- @gemfile = original_gemfile
+ with_gemfile(gemfile) do |current_gemfile|
+ contents ||= Bundler.read_file(current_gemfile)
+ instance_eval(contents, current_gemfile, 1)
+ rescue GemfileEvalError => e
+ message = "There was an error evaluating `#{File.basename current_gemfile}`: #{e.message}"
+ raise DSLError.new(message, current_gemfile, e.backtrace, contents)
+ rescue GemfileError, InvalidArgumentError, InvalidOption, DeprecatedError, ScriptError => e
+ message = "There was an error parsing `#{File.basename current_gemfile}`: #{e.message}"
+ raise DSLError.new(message, current_gemfile, e.backtrace, contents)
+ rescue StandardError => e
+ raise unless e.backtrace_locations.first.path == current_gemfile
+ message = "There was an error parsing `#{File.basename current_gemfile}`: #{e.message}"
+ raise DSLError.new(message, current_gemfile, e.backtrace, contents)
+ end
end
def gemspec(opts = nil)
@@ -66,23 +68,23 @@ module Bundler
development_group = opts[:development_group] || :development
expanded_path = gemfile_root.join(path)
- gemspecs = Gem::Util.glob_files_in_dir("{,*}.gemspec", expanded_path).map {|g| Bundler.load_gemspec(g) }.compact
+ gemspecs = Gem::Util.glob_files_in_dir("{,*}.gemspec", expanded_path).filter_map {|g| Bundler.load_gemspec(g) }
gemspecs.reject! {|s| s.name != name } if name
specs_by_name_and_version = gemspecs.group_by {|s| [s.name, s.version] }
case specs_by_name_and_version.size
when 1
specs = specs_by_name_and_version.values.first
- spec = specs.find {|s| s.match_platform(Bundler.local_platform) } || specs.first
+ spec = specs.find {|s| s.installable_on_platform?(Bundler.local_platform) } || specs.first
@gemspecs << spec
- gem spec.name, name: spec.name, path: path, glob: glob
+ path path, "glob" => glob, "name" => spec.name, "gemspec" => spec do
+ add_dependency spec.name
+ end
- group(development_group) do
- spec.development_dependencies.each do |dep|
- gem dep.name, *(dep.requirement.as_list + [type: :development])
- end
+ spec.development_dependencies.each do |dep|
+ add_dependency dep.name, dep.requirement.as_list, "gemspec_dev_dep" => true, "group" => development_group
end
when 0
raise InvalidOption, "There are no gemspecs at #{expanded_path}"
@@ -94,63 +96,20 @@ module Bundler
def gem(name, *args)
options = args.last.is_a?(Hash) ? args.pop.dup : {}
- options["gemfile"] = @gemfile
version = args || [">= 0"]
normalize_options(name, version, options)
- dep = Dependency.new(name, version, options)
-
- # if there's already a dependency with this name we try to prefer one
- if current = @dependencies.find {|d| d.name == dep.name }
- if current.requirement != dep.requirement
- current_requirement_open = current.requirements_list.include?(">= 0")
-
- gemspec_dep = [dep, current].find(&:gemspec_dev_dep?)
- if gemspec_dep
- gemfile_dep = [dep, current].find(&:runtime?)
-
- unless current_requirement_open
- Bundler.ui.warn "A gemspec development dependency (#{gemspec_dep.name}, #{gemspec_dep.requirement}) is being overridden by a Gemfile dependency (#{gemfile_dep.name}, #{gemfile_dep.requirement}).\n" \
- "This behaviour may change in the future. Please remove either of them, or make sure they both have the same requirement\n"
- end
- else
- update_prompt = ""
-
- if File.basename(@gemfile) == Injector::INJECTED_GEMS
- if dep.requirements_list.include?(">= 0") && !current_requirement_open
- update_prompt = ". Gem already added"
- else
- update_prompt = ". If you want to update the gem version, run `bundle update #{current.name}`"
-
- update_prompt += ". You may also need to change the version requirement specified in the Gemfile if it's too restrictive." unless current_requirement_open
- end
- end
-
- 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}"
- end
- end
+ add_dependency(name, version, options)
+ end
- # Always prefer the dependency from the Gemfile
- if current.gemspec_dev_dep?
- @dependencies.delete(current)
- elsif dep.gemspec_dev_dep?
- return
- elsif current.source != dep.source
- raise GemfileError, "You cannot specify the same gem twice coming from different sources.\n" \
- "You specified that #{dep.name} (#{dep.requirement}) should come from " \
- "#{current.source || "an unspecified source"} and #{dep.source}\n"
- 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
- end
+ # For usage in Dsl.evaluate, since lockfile is used as part of the Gemfile.
+ def lockfile_path
+ @lockfile
+ end
- @dependencies << dep
+ def lockfile(file)
+ @lockfile = file
end
def source(source, *args, &blk)
@@ -193,8 +152,7 @@ module Bundler
def path(path, options = {}, &blk)
source_options = normalize_hash(options).merge(
"path" => Pathname.new(path),
- "root_path" => gemfile_root,
- "gemspec" => gemspecs.find {|g| g.name == options["name"] }
+ "root_path" => gemfile_root
)
source_options["global"] = true unless block_given?
@@ -219,7 +177,7 @@ module Bundler
end
def github(repo, options = {})
- raise ArgumentError, "GitHub sources require a block" unless block_given?
+ raise InvalidArgumentError, "GitHub sources require a block" unless block_given?
github_uri = @git_sources["github"].call(repo)
git_options = normalize_hash(options).merge("uri" => github_uri)
git_source = @sources.add_git_source(git_options)
@@ -228,6 +186,7 @@ module Bundler
def to_definition(lockfile, unlock)
check_primary_source_safety
+ lockfile = @lockfile unless @lockfile.nil?
Definition.new(lockfile, @dependencies, @sources, unlock, @ruby_version, @optional_groups, @gemfiles)
end
@@ -285,6 +244,90 @@ module Bundler
private
+ def add_dependency(name, version = nil, options = {})
+ options["gemfile"] = @gemfile
+ options["source"] ||= @source
+ options["env"] ||= @env
+
+ dep = Dependency.new(name, version, options)
+
+ # if there's already a dependency with this name we try to prefer one
+ if current = @dependencies.find {|d| d.name == name }
+ if current.requirement != dep.requirement
+ current_requirement_open = current.requirements_list.include?(">= 0")
+
+ gemspec_dep = [dep, current].find(&:gemspec_dev_dep?)
+ if gemspec_dep
+ require_relative "vendor/pub_grub/lib/pub_grub/version_range"
+ require_relative "vendor/pub_grub/lib/pub_grub/version_constraint"
+ require_relative "vendor/pub_grub/lib/pub_grub/version_union"
+ require_relative "vendor/pub_grub/lib/pub_grub/rubygems"
+
+ current_gemspec_range = PubGrub::RubyGems.requirement_to_range(current.requirement)
+ next_gemspec_range = PubGrub::RubyGems.requirement_to_range(dep.requirement)
+
+ if current_gemspec_range.intersects?(next_gemspec_range)
+ dep = Dependency.new(name, current.requirement.as_list + dep.requirement.as_list, options)
+ else
+ gemfile_dep = [dep, current].find(&:gemfile_dep?)
+
+ if gemfile_dep
+ raise GemfileError, "The #{name} dependency has conflicting requirements in Gemfile (#{gemfile_dep.requirement}) and gemspec (#{gemspec_dep.requirement})"
+ else
+ raise GemfileError, "Two gemspec development dependencies have conflicting requirements on the same gem: #{dep} and #{current}"
+ end
+ end
+ else
+ update_prompt = ""
+
+ if File.basename(@gemfile) == Injector::INJECTED_GEMS
+ if dep.requirements_list.include?(">= 0") && !current_requirement_open
+ update_prompt = ". Gem already added"
+ else
+ update_prompt = ". If you want to update the gem version, run `bundle update #{name}`"
+
+ update_prompt += ". You may also need to change the version requirement specified in the Gemfile if it's too restrictive." unless current_requirement_open
+ end
+ end
+
+ raise GemfileError, "You cannot specify the same gem twice with different version requirements.\n" \
+ "You specified: #{name} (#{current.requirement}) and #{name} (#{dep.requirement})" \
+ "#{update_prompt}"
+ end
+ end
+
+ unless current.gemspec_dev_dep? && dep.gemspec_dev_dep?
+ # Always prefer the dependency from the Gemfile
+ if current.gemspec_dev_dep?
+ @dependencies.delete(current)
+ elsif dep.gemspec_dev_dep?
+ return
+ elsif current.source.to_s != dep.source.to_s
+ raise GemfileError, "You cannot specify the same gem twice coming from different sources.\n" \
+ "You specified that #{name} (#{dep.requirement}) should come from " \
+ "#{current.source || "an unspecified source"} and #{dep.source}\n"
+ else
+ Bundler.ui.warn "Your Gemfile lists the gem #{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
+ end
+ end
+
+ @dependencies << dep
+ end
+
+ def with_gemfile(gemfile)
+ expanded_gemfile_path = Pathname.new(gemfile).expand_path(@gemfile&.parent)
+ original_gemfile = @gemfile
+ @gemfile = expanded_gemfile_path
+ @gemfiles << expanded_gemfile_path
+ yield @gemfile.to_s
+ ensure
+ @gemfile = original_gemfile
+ end
+
def add_git_sources
git_source(:github) do |repo_name|
if repo_name =~ GITHUB_PULL_REQUEST_URL
@@ -381,6 +424,13 @@ module Bundler
raise GemfileError, "`#{p}` is not a valid platform. The available options are: #{VALID_PLATFORMS.inspect}"
end
+ windows_platforms = platforms.select {|pl| pl.to_s.match?(/mingw|mswin/) }
+ if windows_platforms.any?
+ windows_platforms = windows_platforms.map! {|pl| ":#{pl}" }.join(", ")
+ deprecated_message = "Platform #{windows_platforms} will be removed in the future. Please use platform :windows instead."
+ Bundler::SharedHelpers.feature_deprecated! deprecated_message
+ end
+
# Save sources passed in a key
if opts.key?("source")
source = normalize_source(opts["source"])
@@ -407,8 +457,6 @@ module Bundler
opts["source"] = source
end
- opts["source"] ||= @source
- opts["env"] ||= @env
opts["platforms"] = platforms.dup
opts["group"] = groups
opts["should_include"] = install_if
@@ -447,14 +495,10 @@ module Bundler
def normalize_source(source)
case source
when :gemcutter, :rubygems, :rubyforge
- message =
- "The source :#{source} is deprecated because HTTP requests are insecure.\n" \
- "Please change your source to 'https://rubygems.org' if possible, or 'http://rubygems.org' if not."
removed_message =
"The source :#{source} is disallowed because HTTP requests are insecure.\n" \
"Please change your source to 'https://rubygems.org' if possible, or 'http://rubygems.org' if not."
- Bundler::SharedHelpers.major_deprecation 2, message, removed_message: removed_message
- "http://rubygems.org"
+ Bundler::SharedHelpers.feature_removed! removed_message
when String
source
else
@@ -473,43 +517,18 @@ module Bundler
" gem 'rails'\n" \
" end\n\n"
- SharedHelpers.major_deprecation(2, msg.strip)
+ SharedHelpers.feature_removed! 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\"."
+ multiple_global_source_warning if @sources.aggregate_global_source?
end
def multiple_global_source_warning
- if Bundler.feature_flag.bundler_3_mode?
- msg = "This Gemfile contains multiple global sources. " \
- "Each source after the first must include a block to indicate which gems " \
- "should come from that source"
- raise GemfileEvalError, msg
- else
- message =
- "Your Gemfile contains multiple global 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."
- removed_message =
- "Your Gemfile contains multiple global sources. " \
- "Using `source` more than once without a block is a security risk, and " \
- "may result in installing unexpected gems. To resolve this error, use " \
- "a block to indicate which gems should come from the secondary source."
- Bundler::SharedHelpers.major_deprecation 2, message, removed_message: removed_message
- end
+ msg = "This Gemfile contains multiple global sources. " \
+ "Each source after the first must include a block to indicate which gems " \
+ "should come from that source"
+ raise GemfileEvalError, msg
end
class DSLError < GemfileError
@@ -577,23 +596,23 @@ module Bundler
return m unless backtrace && dsl_path && contents
- trace_line = backtrace.find {|l| l.include?(dsl_path.to_s) } || trace_line
+ trace_line = backtrace.find {|l| l.include?(dsl_path) } || trace_line
return m unless trace_line
- line_numer = trace_line.split(":")[1].to_i - 1
- return m unless line_numer
+ line_number = trace_line.split(":")[1].to_i - 1
+ return m unless line_number
lines = contents.lines.to_a
indent = " # "
indicator = indent.tr("#", ">")
- first_line = line_numer.zero?
- last_line = (line_numer == (lines.count - 1))
+ first_line = line_number.zero?
+ last_line = (line_number == (lines.count - 1))
m << "\n"
m << "#{indent}from #{trace_line.gsub(/:in.*$/, "")}\n"
m << "#{indent}-------------------------------------------\n"
- m << "#{indent}#{lines[line_numer - 1]}" unless first_line
- m << "#{indicator}#{lines[line_numer]}"
- m << "#{indent}#{lines[line_numer + 1]}" unless last_line
+ m << "#{indent}#{lines[line_number - 1]}" unless first_line
+ m << "#{indicator}#{lines[line_number]}"
+ m << "#{indent}#{lines[line_number + 1]}" unless last_line
m << "\n" unless m.end_with?("\n")
m << "#{indent}-------------------------------------------\n"
end
@@ -603,7 +622,7 @@ module Bundler
def parse_line_number_from_description
description = self.description
- if dsl_path && description =~ /((#{Regexp.quote File.expand_path(dsl_path)}|#{Regexp.quote dsl_path.to_s}):\d+)/
+ if dsl_path && description =~ /((#{Regexp.quote File.expand_path(dsl_path)}|#{Regexp.quote dsl_path}):\d+)/
trace_line = Regexp.last_match[1]
description = description.sub(/\n.*\n(\.\.\.)? *\^~+$/, "").sub(/#{Regexp.quote trace_line}:\s*/, "").sub("\n", " - ")
end
diff --git a/lib/bundler/endpoint_specification.rb b/lib/bundler/endpoint_specification.rb
index 87cb352efa..c06684657d 100644
--- a/lib/bundler/endpoint_specification.rb
+++ b/lib/bundler/endpoint_specification.rb
@@ -6,7 +6,8 @@ module Bundler
include MatchRemoteMetadata
attr_reader :name, :version, :platform, :checksum
- attr_accessor :source, :remote, :dependencies
+ attr_writer :dependencies
+ attr_accessor :remote, :locked_platform
def initialize(name, version, platform, spec_fetcher, dependencies, metadata = nil)
super()
@@ -14,18 +15,29 @@ module Bundler
@version = Gem::Version.create version
@platform = Gem::Platform.new(platform)
@spec_fetcher = spec_fetcher
- @dependencies = dependencies.map {|dep, reqs| build_dependency(dep, reqs) }
+ @dependencies = nil
+ @unbuilt_dependencies = dependencies
@loaded_from = nil
@remote_specification = nil
+ @locked_platform = nil
parse_metadata(metadata)
end
+ def insecurely_materialized?
+ @locked_platform.to_s != @platform.to_s
+ end
+
def fetch_platform
@platform
end
+ def dependencies
+ @dependencies ||= @unbuilt_dependencies.map! {|dep, reqs| build_dependency(dep, reqs) }
+ end
+ alias_method :runtime_dependencies, :dependencies
+
# needed for standalone, load required_paths from local gemspec
# after the gem is installed
def require_paths
@@ -92,6 +104,17 @@ module Bundler
end
end
+ # needed for `bundle fund`
+ def metadata
+ if @remote_specification
+ @remote_specification.metadata
+ elsif _local_specification
+ _local_specification.metadata
+ else
+ super
+ end
+ end
+
def _local_specification
return unless @loaded_from && File.exist?(local_specification_path)
eval(File.read(local_specification_path), nil, local_specification_path).tap do |spec|
@@ -104,6 +127,10 @@ module Bundler
@remote_specification = spec
end
+ def inspect
+ "#<#{self.class} @name=\"#{name}\" (#{full_name.delete_prefix("#{name}-")})>"
+ end
+
private
def _remote_specification
@@ -141,7 +168,7 @@ module Bundler
end
def build_dependency(name, requirements)
- Gem::Dependency.new(name, requirements)
+ Dependency.new(name, requirements)
end
end
end
diff --git a/lib/bundler/env.rb b/lib/bundler/env.rb
index f6cb198e38..074bef6edc 100644
--- a/lib/bundler/env.rb
+++ b/lib/bundler/env.rb
@@ -120,7 +120,7 @@ module Bundler
specs = Bundler.rubygems.find_name(name)
out << [" #{name}", "(#{specs.map(&:version).join(",")})"] unless specs.empty?
end
- if (exe = caller.last.split(":").first)&.match? %r{(exe|bin)/bundler?\z}
+ if (exe = caller_locations.last.absolute_path)&.match? %r{(exe|bin)/bundler?\z}
shebang = File.read(exe).lines.first
shebang.sub!(/^#!\s*/, "")
unless shebang.start_with?(Gem.ruby, "/usr/bin/env ruby")
diff --git a/lib/bundler/environment_preserver.rb b/lib/bundler/environment_preserver.rb
index 444ab6fd37..bf9478a299 100644
--- a/lib/bundler/environment_preserver.rb
+++ b/lib/bundler/environment_preserver.rb
@@ -6,6 +6,7 @@ module Bundler
BUNDLER_KEYS = %w[
BUNDLE_BIN_PATH
BUNDLE_GEMFILE
+ BUNDLE_LOCKFILE
BUNDLER_VERSION
BUNDLER_SETUP
GEM_HOME
diff --git a/lib/bundler/errors.rb b/lib/bundler/errors.rb
index c29b1bfed8..d8df4d6ec5 100644
--- a/lib/bundler/errors.rb
+++ b/lib/bundler/errors.rb
@@ -25,6 +25,7 @@ module Bundler
class GemNotFound < BundlerError; status_code(7); end
class InstallHookError < BundlerError; status_code(8); end
+ class RemovedError < BundlerError; status_code(9); end
class GemfileNotFound < BundlerError; status_code(10); end
class GitError < BundlerError; status_code(11); end
class DeprecatedError < BundlerError; status_code(12); end
@@ -76,11 +77,6 @@ module Bundler
def mismatch_resolution_instructions
removable, remote = [@existing, @checksum].partition(&:removable?)
case removable.size
- when 0
- msg = +"Mismatched checksums each have an authoritative source:\n"
- msg << " 1. #{@existing.sources.reject(&:removable?).map(&:to_s).join(" and ")}\n"
- msg << " 2. #{@checksum.sources.reject(&:removable?).map(&:to_s).join(" and ")}\n"
- msg << "You may need to alter your Gemfile sources to resolve this issue.\n"
when 1
msg = +"If you trust #{remote.first.sources.first}, to resolve this issue you can:\n"
msg << removable.first.removal_instructions
@@ -135,7 +131,8 @@ module Bundler
attr_reader :orig_exception
def initialize(orig_exception, msg)
- full_message = msg + "\nGem Load Error is: #{orig_exception.message}\n"\
+ full_message = msg + "\nGem Load Error is:
+ #{orig_exception.full_message(highlight: false)}\n"\
"Backtrace for gem load error is:\n"\
"#{orig_exception.backtrace.join("\n")}\n"\
"Bundler Error Backtrace:\n"
@@ -193,6 +190,24 @@ module Bundler
status_code(31)
end
+ class ReadOnlyFileSystemError < PermissionError
+ def message
+ "There was an error while trying to #{action} `#{@path}`. " \
+ "File system is read-only."
+ end
+
+ status_code(42)
+ end
+
+ class OperationNotPermittedError < PermissionError
+ def message
+ "There was an error while trying to #{action} `#{@path}`. " \
+ "Underlying OS system call raised an EPERM error."
+ end
+
+ status_code(43)
+ end
+
class GenericSystemCallError < BundlerError
attr_reader :underlying_error
@@ -207,7 +222,9 @@ module Bundler
class DirectoryRemovalError < BundlerError
def initialize(orig_exception, msg)
full_message = "#{msg}.\n" \
- "The underlying error was #{orig_exception.class}: #{orig_exception.message}, with backtrace:\n" \
+ "The underlying error was #{orig_exception.class}:
+ #{orig_exception.full_message(highlight: false)},
+ with backtrace:\n" \
" #{orig_exception.backtrace.join("\n ")}\n\n" \
"Bundler Error Backtrace:"
super(full_message)
@@ -217,15 +234,15 @@ module Bundler
end
class InsecureInstallPathError < BundlerError
- def initialize(path)
+ def initialize(name, path)
+ @name = name
@path = path
end
def message
- "The installation path is insecure. Bundler cannot continue.\n" \
- "#{@path} is world-writable (without sticky bit).\n" \
- "Bundler cannot safely replace gems in world-writeable directories due to potential vulnerabilities.\n" \
- "Please change the permissions of this directory or choose a different install path."
+ "Bundler cannot reinstall #{@name} because there's a previous installation of it at #{@path} that is unsafe to remove.\n" \
+ "The parent of #{@path} is world-writable and does not have the sticky bit set, making it insecure to remove due to potential vulnerabilities.\n" \
+ "Please change the permissions of #{File.dirname(@path)} or choose a different install path."
end
status_code(38)
@@ -244,4 +261,20 @@ module Bundler
status_code(39)
end
+
+ class InvalidArgumentError < BundlerError; status_code(40); end
+
+ class IncorrectLockfileDependencies < BundlerError
+ attr_reader :spec
+
+ def initialize(spec)
+ @spec = spec
+ end
+
+ def message
+ "Bundler found incorrect dependencies in the lockfile for #{spec.full_name}"
+ end
+
+ status_code(41)
+ end
end
diff --git a/lib/bundler/feature_flag.rb b/lib/bundler/feature_flag.rb
index ab2189f7f0..dea8abedba 100644
--- a/lib/bundler/feature_flag.rb
+++ b/lib/bundler/feature_flag.rb
@@ -2,52 +2,19 @@
module Bundler
class FeatureFlag
- def self.settings_flag(flag, &default)
- unless Bundler::Settings::BOOL_KEYS.include?(flag.to_s)
- raise "Cannot use `#{flag}` as a settings feature flag since it isn't a bool key"
- end
+ (1..10).each {|v| define_method("bundler_#{v}_mode?") { @major_version >= v } }
- settings_method("#{flag}?", flag, &default)
+ def removed_major?(target_major_version)
+ @major_version > target_major_version
end
- private_class_method :settings_flag
- def self.settings_option(key, &default)
- settings_method(key, key, &default)
+ def deprecated_major?(target_major_version)
+ @major_version >= target_major_version
end
- private_class_method :settings_option
-
- def self.settings_method(name, key, &default)
- define_method(name) do
- value = Bundler.settings[key]
- value = instance_eval(&default) if value.nil?
- value
- end
- end
- private_class_method :settings_method
-
- (1..10).each {|v| define_method("bundler_#{v}_mode?") { major_version >= v } }
-
- settings_flag(:allow_offline_install) { bundler_3_mode? }
- settings_flag(:auto_clean_without_path) { bundler_3_mode? }
- settings_flag(:cache_all) { bundler_3_mode? }
- settings_flag(:default_install_uses_path) { bundler_3_mode? }
- settings_flag(:forget_cli_options) { bundler_3_mode? }
- settings_flag(:global_gem_cache) { 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(:update_requires_all_flag) { bundler_4_mode? }
-
- settings_option(:default_cli_command) { bundler_3_mode? ? :cli_help : :install }
def initialize(bundler_version)
@bundler_version = Gem::Version.create(bundler_version)
+ @major_version = @bundler_version.segments.first
end
-
- def major_version
- @bundler_version.segments.first
- end
- private :major_version
end
end
diff --git a/lib/bundler/fetcher.rb b/lib/bundler/fetcher.rb
index 6288b22dcd..0b6ced6f39 100644
--- a/lib/bundler/fetcher.rb
+++ b/lib/bundler/fetcher.rb
@@ -2,8 +2,7 @@
require_relative "vendored_persistent"
require_relative "vendored_timeout"
-require "cgi"
-require "securerandom"
+require_relative "vendored_securerandom"
require "zlib"
module Bundler
@@ -37,8 +36,9 @@ module Bundler
# This is the error raised when a source is HTTPS and OpenSSL didn't load
class SSLError < HTTPError
def initialize(msg = nil)
- super msg || "Could not load OpenSSL.\n" \
- "You must recompile Ruby with OpenSSL support."
+ super "Could not load OpenSSL.\n" \
+ "You must recompile Ruby with OpenSSL support.\n" \
+ "original error: #{msg}\n"
end
end
@@ -72,19 +72,57 @@ module Bundler
end
end
+ HTTP_ERRORS = (Downloader::HTTP_RETRYABLE_ERRORS + Downloader::HTTP_NON_RETRYABLE_ERRORS).freeze
+ deprecate_constant :HTTP_ERRORS
+
+ NET_ERRORS = [
+ :HTTPBadGateway,
+ :HTTPBadRequest,
+ :HTTPFailedDependency,
+ :HTTPForbidden,
+ :HTTPInsufficientStorage,
+ :HTTPMethodNotAllowed,
+ :HTTPMovedPermanently,
+ :HTTPNoContent,
+ :HTTPNotFound,
+ :HTTPNotImplemented,
+ :HTTPPreconditionFailed,
+ :HTTPRequestEntityTooLarge,
+ :HTTPRequestURITooLong,
+ :HTTPUnauthorized,
+ :HTTPUnprocessableEntity,
+ :HTTPUnsupportedMediaType,
+ :HTTPVersionNotSupported,
+ ].freeze
+ deprecate_constant :NET_ERRORS
+
# Exceptions classes that should bypass retry attempts. If your password didn't work the
# first time, it's not going to the third time.
- NET_ERRORS = [:HTTPBadGateway, :HTTPBadRequest, :HTTPFailedDependency,
- :HTTPForbidden, :HTTPInsufficientStorage, :HTTPMethodNotAllowed,
- :HTTPMovedPermanently, :HTTPNoContent, :HTTPNotFound,
- :HTTPNotImplemented, :HTTPPreconditionFailed, :HTTPRequestEntityTooLarge,
- :HTTPRequestURITooLong, :HTTPUnauthorized, :HTTPUnprocessableEntity,
- :HTTPUnsupportedMediaType, :HTTPVersionNotSupported].freeze
- FAIL_ERRORS = begin
- fail_errors = [AuthenticationRequiredError, BadAuthenticationError, AuthenticationForbiddenError, FallbackError, SecurityError]
- fail_errors << Gem::Requirement::BadRequirementError
- fail_errors.concat(NET_ERRORS.map {|e| Gem::Net.const_get(e) })
- end.freeze
+ FAIL_ERRORS = [
+ AuthenticationRequiredError,
+ BadAuthenticationError,
+ AuthenticationForbiddenError,
+ FallbackError,
+ SecurityError,
+ Gem::Requirement::BadRequirementError,
+ Gem::Net::HTTPBadGateway,
+ Gem::Net::HTTPBadRequest,
+ Gem::Net::HTTPFailedDependency,
+ Gem::Net::HTTPForbidden,
+ Gem::Net::HTTPInsufficientStorage,
+ Gem::Net::HTTPMethodNotAllowed,
+ Gem::Net::HTTPMovedPermanently,
+ Gem::Net::HTTPNoContent,
+ Gem::Net::HTTPNotFound,
+ Gem::Net::HTTPNotImplemented,
+ Gem::Net::HTTPPreconditionFailed,
+ Gem::Net::HTTPRequestEntityTooLarge,
+ Gem::Net::HTTPRequestURITooLong,
+ Gem::Net::HTTPUnauthorized,
+ Gem::Net::HTTPUnprocessableEntity,
+ Gem::Net::HTTPUnsupportedMediaType,
+ Gem::Net::HTTPVersionNotSupported,
+ ].freeze
class << self
attr_accessor :disable_endpoint, :api_timeout, :redirect_limit, :max_retries
@@ -182,7 +220,7 @@ module Bundler
agent << " ci/#{cis.join(",")}" if cis.any?
# add a random ID so we can consolidate runs server-side
- agent << " " << SecureRandom.hex(8)
+ agent << " " << Gem::SecureRandom.hex(8)
# add any user agent strings set in the config
extra_ua = Bundler.settings[:user_agent]
@@ -251,7 +289,13 @@ module Bundler
needs_ssl = remote_uri.scheme == "https" ||
Bundler.settings[:ssl_verify_mode] ||
Bundler.settings[:ssl_client_cert]
- raise SSLError if needs_ssl && !defined?(OpenSSL::SSL)
+ if needs_ssl
+ begin
+ require "openssl"
+ rescue StandardError, LoadError => e
+ raise SSLError.new(e.message)
+ end
+ end
con = Gem::Net::HTTP::Persistent.new name: "bundler", proxy: :ENV
if gem_proxy = Gem.configuration[:http_proxy]
@@ -287,13 +331,6 @@ module Bundler
paths.find {|path| File.file? path }
end
- HTTP_ERRORS = [
- Gem::Timeout::Error, EOFError, SocketError, Errno::ENETDOWN, Errno::ENETUNREACH,
- Errno::EINVAL, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EAGAIN,
- Gem::Net::HTTPBadResponse, Gem::Net::HTTPHeaderSyntaxError, Gem::Net::ProtocolError,
- Gem::Net::HTTP::Persistent::Error, Zlib::BufError, Errno::EHOSTUNREACH
- ].freeze
-
def bundler_cert_store
store = OpenSSL::X509::Store.new
ssl_ca_cert = Bundler.settings[:ssl_ca_cert] ||
diff --git a/lib/bundler/fetcher/compact_index.rb b/lib/bundler/fetcher/compact_index.rb
index 6e5656d26a..52168111fe 100644
--- a/lib/bundler/fetcher/compact_index.rb
+++ b/lib/bundler/fetcher/compact_index.rb
@@ -10,7 +10,7 @@ module Bundler
method = instance_method(method_name)
undef_method(method_name)
define_method(method_name) do |*args, &blk|
- method.bind(self).call(*args, &blk)
+ method.bind_call(self, *args, &blk)
rescue NetworkDownError, CompactIndexClient::Updater::MismatchedChecksumError => e
raise HTTPError, e.message
rescue AuthenticationRequiredError, BadAuthenticationError
@@ -110,7 +110,7 @@ module Bundler
def call(path, headers)
fetcher.downloader.fetch(fetcher.fetch_uri + path, headers)
rescue NetworkDownError => e
- raise unless Bundler.feature_flag.allow_offline_install? && headers["If-None-Match"]
+ raise unless headers["If-None-Match"]
ui.warn "Using the cached data for the new index because of a network error: #{e}"
Gem::Net::HTTPNotModified.new(nil, nil, nil)
end
diff --git a/lib/bundler/fetcher/dependency.rb b/lib/bundler/fetcher/dependency.rb
index 0b807c9a4b..994b415e9c 100644
--- a/lib/bundler/fetcher/dependency.rb
+++ b/lib/bundler/fetcher/dependency.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
require_relative "base"
-require "cgi"
+require "cgi/escape"
+require "cgi/util" unless defined?(CGI::EscapeExt)
module Bundler
class Fetcher
diff --git a/lib/bundler/fetcher/downloader.rb b/lib/bundler/fetcher/downloader.rb
index 868b39b959..2eac6e7975 100644
--- a/lib/bundler/fetcher/downloader.rb
+++ b/lib/bundler/fetcher/downloader.rb
@@ -3,6 +3,28 @@
module Bundler
class Fetcher
class Downloader
+ HTTP_NON_RETRYABLE_ERRORS = [
+ SocketError,
+ Errno::EADDRNOTAVAIL,
+ Errno::ENETDOWN,
+ Errno::ENETUNREACH,
+ Gem::Net::HTTP::Persistent::Error,
+ Errno::EHOSTUNREACH,
+ ].freeze
+
+ HTTP_RETRYABLE_ERRORS = [
+ Gem::Timeout::Error,
+ EOFError,
+ Errno::EINVAL,
+ Errno::ECONNRESET,
+ Errno::ETIMEDOUT,
+ Errno::EAGAIN,
+ Gem::Net::HTTPBadResponse,
+ Gem::Net::HTTPHeaderSyntaxError,
+ Gem::Net::ProtocolError,
+ Zlib::BufError,
+ ].freeze
+
attr_reader :connection
attr_reader :redirect_limit
@@ -67,15 +89,19 @@ module Bundler
connection.request(uri, req)
rescue OpenSSL::SSL::SSLError
raise CertificateFailureError.new(uri)
- rescue *HTTP_ERRORS => e
+ rescue *HTTP_NON_RETRYABLE_ERRORS => e
Bundler.ui.trace e
- if e.is_a?(SocketError) || e.message.to_s.include?("host down:")
- raise NetworkDownError, "Could not reach host #{uri.host}. Check your network " \
- "connection and try again."
- else
- raise HTTPError, "Network error while fetching #{filtered_uri}" \
+
+ host = uri.host
+ host_port = "#{host}:#{uri.port}"
+ host = host_port if filtered_uri.to_s.include?(host_port)
+ raise NetworkDownError, "Could not reach host #{host}. Check your network " \
+ "connection and try again."
+ rescue *HTTP_RETRYABLE_ERRORS => e
+ Bundler.ui.trace e
+
+ raise HTTPError, "Network error while fetching #{filtered_uri}" \
" (#{e})"
- end
end
private
diff --git a/lib/bundler/fetcher/gem_remote_fetcher.rb b/lib/bundler/fetcher/gem_remote_fetcher.rb
index 3fc7b68263..3c3c1826a1 100644
--- a/lib/bundler/fetcher/gem_remote_fetcher.rb
+++ b/lib/bundler/fetcher/gem_remote_fetcher.rb
@@ -5,6 +5,12 @@ require "rubygems/remote_fetcher"
module Bundler
class Fetcher
class GemRemoteFetcher < Gem::RemoteFetcher
+ def initialize(*)
+ super
+
+ @pool_size = 5
+ end
+
def request(*args)
super do |req|
req.delete("User-Agent") if headers["User-Agent"]
diff --git a/lib/bundler/force_platform.rb b/lib/bundler/force_platform.rb
index 249a24ecd1..7af33218cb 100644
--- a/lib/bundler/force_platform.rb
+++ b/lib/bundler/force_platform.rb
@@ -2,8 +2,6 @@
module Bundler
module ForcePlatform
- private
-
# The `:force_ruby_platform` value used by dependencies for resolution, and
# by locked specifications for materialization is `false` by default, except
# for TruffleRuby. TruffleRuby generally needs to force the RUBY platform
diff --git a/lib/bundler/friendly_errors.rb b/lib/bundler/friendly_errors.rb
index e61ed64450..5e8eaee6bb 100644
--- a/lib/bundler/friendly_errors.rb
+++ b/lib/bundler/friendly_errors.rb
@@ -80,7 +80,7 @@ module Bundler
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 fill in the new issue form located at #{new_issue_url}, and copy and paste the report template above in there.
+ If there aren't any reports for this error yet, please fill in the new issue form located at #{new_issue_url}. Make sure to copy and paste the full output of this command under the "What happened instead?" section.
EOS
end
@@ -102,13 +102,14 @@ module Bundler
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/rubygems/rubygems/search?q=" \
+ require "cgi/escape"
+ require "cgi/util" unless defined?(CGI::EscapeExt)
+ "https://github.com/ruby/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"
+ "https://github.com/ruby/rubygems/issues/new?labels=Bundler&template=bundler-related-issue.md"
end
end
diff --git a/lib/bundler/gem_helpers.rb b/lib/bundler/gem_helpers.rb
deleted file mode 100644
index de007523ec..0000000000
--- a/lib/bundler/gem_helpers.rb
+++ /dev/null
@@ -1,127 +0,0 @@
-# frozen_string_literal: true
-
-module Bundler
- module GemHelpers
- GENERIC_CACHE = { Gem::Platform::RUBY => Gem::Platform::RUBY } # rubocop:disable Style/MutableConstant
- GENERICS = [
- [Gem::Platform.new("java"), Gem::Platform.new("java")],
- [Gem::Platform.new("mswin32"), Gem::Platform.new("mswin32")],
- [Gem::Platform.new("mswin64"), Gem::Platform.new("mswin64")],
- [Gem::Platform.new("universal-mingw32"), Gem::Platform.new("universal-mingw32")],
- [Gem::Platform.new("x64-mingw32"), Gem::Platform.new("x64-mingw32")],
- [Gem::Platform.new("x86_64-mingw32"), Gem::Platform.new("x64-mingw32")],
- [Gem::Platform.new("x64-mingw-ucrt"), Gem::Platform.new("x64-mingw-ucrt")],
- [Gem::Platform.new("mingw32"), Gem::Platform.new("x86-mingw32")],
- ].freeze
-
- def generic(p)
- GENERIC_CACHE[p] ||= begin
- _, found = GENERICS.find do |match, _generic|
- p.os == match.os && (!match.cpu || p.cpu == match.cpu)
- end
- found || Gem::Platform::RUBY
- end
- end
- module_function :generic
-
- def generic_local_platform
- generic(local_platform)
- end
- module_function :generic_local_platform
-
- def local_platform
- Bundler.local_platform
- end
- module_function :local_platform
-
- def generic_local_platform_is_ruby?
- generic_local_platform == Gem::Platform::RUBY
- end
- module_function :generic_local_platform_is_ruby?
-
- def platform_specificity_match(spec_platform, user_platform)
- spec_platform = Gem::Platform.new(spec_platform)
-
- PlatformMatch.specificity_score(spec_platform, user_platform)
- end
- module_function :platform_specificity_match
-
- def select_best_platform_match(specs, platform)
- matching = specs.select {|spec| spec.match_platform(platform) }
-
- sort_best_platform_match(matching, platform)
- end
- module_function :select_best_platform_match
-
- def force_ruby_platform(specs)
- matching = specs.select {|spec| spec.match_platform(Gem::Platform::RUBY) && spec.force_ruby_platform! }
-
- sort_best_platform_match(matching, Gem::Platform::RUBY)
- end
- module_function :force_ruby_platform
-
- def sort_best_platform_match(matching, 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 :sort_best_platform_match
-
- class PlatformMatch
- 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
-
- os_match(spec_platform, user_platform) +
- cpu_match(spec_platform, user_platform) * 10 +
- platform_version_match(spec_platform, user_platform) * 100
- end
-
- def self.os_match(spec_platform, user_platform)
- if spec_platform.os == user_platform.os
- 0
- else
- 1
- end
- end
-
- def self.cpu_match(spec_platform, user_platform)
- if spec_platform.cpu == user_platform.cpu
- 0
- elsif spec_platform.cpu == "arm" && user_platform.cpu.to_s.start_with?("arm")
- 0
- elsif spec_platform.cpu.nil? || spec_platform.cpu == "universal"
- 1
- else
- 2
- end
- end
-
- def self.platform_version_match(spec_platform, user_platform)
- if spec_platform.version == user_platform.version
- 0
- elsif spec_platform.version.nil?
- 1
- else
- 2
- 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
- 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/lib/bundler/gem_version_promoter.rb b/lib/bundler/gem_version_promoter.rb
index ecc65b4956..d64dbacfdb 100644
--- a/lib/bundler/gem_version_promoter.rb
+++ b/lib/bundler/gem_version_promoter.rb
@@ -132,8 +132,6 @@ module Bundler
# Specific version moves can't always reliably be done during sorting
# as not all elements are compared against each other.
def post_sort(result, unlock, locked_version)
- # default :major behavior in Bundler does not do this
- return result if major?
if unlock || locked_version.nil?
result
else
diff --git a/lib/bundler/graph.rb b/lib/bundler/graph.rb
deleted file mode 100644
index b22b17a453..0000000000
--- a/lib/bundler/graph.rb
+++ /dev/null
@@ -1,152 +0,0 @@
-# frozen_string_literal: true
-
-require "set"
-module Bundler
- class Graph
- GRAPH_NAME = :Gemfile
-
- def initialize(env, output_file, show_version = false, show_requirements = false, output_format = "png", without = [])
- @env = env
- @output_file = output_file
- @show_version = show_version
- @show_requirements = show_requirements
- @output_format = output_format
- @without_groups = without.map(&:to_sym)
-
- @groups = []
- @relations = Hash.new {|h, k| h[k] = Set.new }
- @node_options = {}
- @edge_options = {}
-
- _populate_relations
- end
-
- attr_reader :groups, :relations, :node_options, :edge_options, :output_file, :output_format
-
- def viz
- GraphVizClient.new(self).run
- end
-
- private
-
- def _populate_relations
- parent_dependencies = _groups.values.to_set.flatten
- loop do
- break if parent_dependencies.empty?
-
- tmp = Set.new
- parent_dependencies.each do |dependency|
- child_dependencies = spec_for_dependency(dependency).runtime_dependencies.to_set
- @relations[dependency.name] += child_dependencies.map(&:name).to_set
- tmp += child_dependencies
-
- @node_options[dependency.name] = _make_label(dependency, :node)
- child_dependencies.each do |c_dependency|
- @edge_options["#{dependency.name}_#{c_dependency.name}"] = _make_label(c_dependency, :edge)
- end
- end
- parent_dependencies = tmp
- end
- end
-
- def _groups
- relations = Hash.new {|h, k| h[k] = Set.new }
- @env.current_dependencies.each do |dependency|
- dependency.groups.each do |group|
- next if @without_groups.include?(group)
-
- relations[group.to_s].add(dependency)
- @relations[group.to_s].add(dependency.name)
-
- @node_options[group.to_s] ||= _make_label(group, :node)
- @edge_options["#{group}_#{dependency.name}"] = _make_label(dependency, :edge)
- end
- end
- @groups = relations.keys
- relations
- end
-
- def _make_label(symbol_or_string_or_dependency, element_type)
- case element_type.to_sym
- when :node
- if symbol_or_string_or_dependency.is_a?(Gem::Dependency)
- label = symbol_or_string_or_dependency.name.dup
- label << "\n#{spec_for_dependency(symbol_or_string_or_dependency).version}" if @show_version
- else
- label = symbol_or_string_or_dependency.to_s
- end
- when :edge
- label = nil
- if symbol_or_string_or_dependency.respond_to?(:requirements_list) && @show_requirements
- tmp = symbol_or_string_or_dependency.requirements_list.join(", ")
- label = tmp if tmp != ">= 0"
- end
- else
- raise ArgumentError, "2nd argument is invalid"
- end
- label.nil? ? {} : { label: label }
- end
-
- def spec_for_dependency(dependency)
- @env.requested_specs.find {|s| s.name == dependency.name }
- end
-
- class GraphVizClient
- def initialize(graph_instance)
- @graph_name = graph_instance.class::GRAPH_NAME
- @groups = graph_instance.groups
- @relations = graph_instance.relations
- @node_options = graph_instance.node_options
- @edge_options = graph_instance.edge_options
- @output_file = graph_instance.output_file
- @output_format = graph_instance.output_format
- end
-
- def g
- @g ||= ::GraphViz.digraph(@graph_name, concentrate: true, normalize: true, nodesep: 0.55) do |g|
- g.edge[:weight] = 2
- g.edge[:fontname] = g.node[:fontname] = "Arial, Helvetica, SansSerif"
- g.edge[:fontsize] = 12
- end
- end
-
- def run
- @groups.each do |group|
- g.add_nodes(
- group, {
- style: "filled",
- fillcolor: "#B9B9D5",
- shape: "box3d",
- fontsize: 16,
- }.merge(@node_options[group])
- )
- end
-
- @relations.each do |parent, children|
- children.each do |child|
- if @groups.include?(parent)
- g.add_nodes(child, { style: "filled", fillcolor: "#B9B9D5" }.merge(@node_options[child]))
- g.add_edges(parent, child, { constraint: false }.merge(@edge_options["#{parent}_#{child}"]))
- else
- g.add_nodes(child, @node_options[child])
- g.add_edges(parent, child, @edge_options["#{parent}_#{child}"])
- end
- end
- end
-
- if @output_format.to_s == "debug"
- $stdout.puts g.output none: String
- Bundler.ui.info "debugging bundle viz..."
- else
- begin
- g.output @output_format.to_sym => "#{@output_file}.#{@output_format}"
- Bundler.ui.info "#{@output_file}.#{@output_format}"
- rescue ArgumentError => e
- warn "Unsupported output format. See Ruby-Graphviz/lib/graphviz/constants.rb"
- raise e
- end
- end
- end
- end
- end
-end
diff --git a/lib/bundler/index.rb b/lib/bundler/index.rb
index df46facc88..9aef2dfa12 100644
--- a/lib/bundler/index.rb
+++ b/lib/bundler/index.rb
@@ -46,13 +46,6 @@ module Bundler
true
end
- def search_all(name, &blk)
- return enum_for(:search_all, name) unless blk
- specs_by_name(name).each(&blk)
- @duplicates[name]&.each(&blk)
- @sources.each {|source| source.search_all(name, &blk) }
- end
-
# Search this index's specs, and any source indexes that this index knows
# about, returning all of the results.
def search(query)
@@ -131,6 +124,11 @@ module Bundler
return unless other
other.each do |spec|
if existing = find_by_spec(spec)
+ unless dependencies_eql?(existing, spec)
+ Bundler.ui.warn "Local specification for #{spec.full_name} has different dependencies than the remote gem, ignoring it"
+ next
+ end
+
add_duplicate(existing)
end
add spec
@@ -153,8 +151,8 @@ module Bundler
end
def dependencies_eql?(spec, other_spec)
- deps = spec.dependencies.select {|d| d.type != :development }
- other_deps = other_spec.dependencies.select {|d| d.type != :development }
+ deps = spec.runtime_dependencies
+ other_deps = other_spec.runtime_dependencies
deps.sort == other_deps.sort
end
diff --git a/lib/bundler/injector.rb b/lib/bundler/injector.rb
index 879b481339..21ff90ad13 100644
--- a/lib/bundler/injector.rb
+++ b/lib/bundler/injector.rb
@@ -23,10 +23,7 @@ module Bundler
# @param [Pathname] lockfile_path The lockfile in which to inject the new dependency.
# @return [Array]
def inject(gemfile_path, lockfile_path)
- if Bundler.frozen_bundle?
- # ensure the lock and Gemfile are synced
- Bundler.definition.ensure_equivalent_gemfile_and_lockfile(true)
- end
+ Bundler.definition.ensure_equivalent_gemfile_and_lockfile(true)
# temporarily unfreeze
Bundler.settings.temporary(deployment: false, frozen: false) do
@@ -44,7 +41,7 @@ module Bundler
# resolve to see if the new deps broke anything
@definition = builder.to_definition(lockfile_path, {})
- @definition.resolve_remotely!
+ @definition.remotely!
# since nothing broke, we can add those gems to the gemfile
append_to(gemfile_path, build_gem_lines(@options[:conservative_versioning])) if @deps.any?
@@ -111,17 +108,17 @@ module Bundler
end
if d.groups != Array(:default)
- group = d.groups.size == 1 ? ", :group => #{d.groups.first.inspect}" : ", :groups => #{d.groups.inspect}"
+ group = d.groups.size == 1 ? ", group: #{d.groups.first.inspect}" : ", groups: #{d.groups.inspect}"
end
- source = ", :source => \"#{d.source}\"" unless d.source.nil?
- path = ", :path => \"#{d.path}\"" unless d.path.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?
- glob = ", :glob => \"#{d.glob}\"" unless d.glob.nil?
- require_path = ", :require => #{convert_autorequire(d.autorequire)}" unless d.autorequire.nil?
+ source = ", source: \"#{d.source}\"" unless d.source.nil?
+ path = ", path: \"#{d.path}\"" unless d.path.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?
+ glob = ", glob: \"#{d.glob}\"" unless d.glob.nil?
+ require_path = ", require: #{convert_autorequire(d.autorequire)}" unless d.autorequire.nil?
%(gem #{name}#{requirement}#{group}#{source}#{path}#{git}#{github}#{branch}#{ref}#{glob}#{require_path})
end.join("\n")
@@ -187,7 +184,7 @@ module Bundler
# @param [Array] gems Array of names of gems to be removed.
# @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\)/
+ 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|
diff --git a/lib/bundler/inline.rb b/lib/bundler/inline.rb
index ae4ccf2138..c861bee149 100644
--- a/lib/bundler/inline.rb
+++ b/lib/bundler/inline.rb
@@ -1,16 +1,20 @@
# frozen_string_literal: true
-# Allows for declaring a Gemfile inline in a ruby script, optionally installing
-# any gems that aren't already installed on the user's system.
+# Allows for declaring a Gemfile inline in a ruby script, installing any gems
+# that aren't already installed on the user's system.
#
# @note Every gem that is specified in this 'Gemfile' will be `require`d, as if
# the user had manually called `Bundler.require`. To avoid a requested gem
# being automatically required, add the `:require => false` option to the
# `gem` dependency declaration.
#
-# @param install [Boolean] whether gems that aren't already installed on the
-# user's system should be installed.
-# Defaults to `false`.
+# @param force_latest_compatible [Boolean] Force installing the *latest*
+# compatible versions of the gems,
+# even if compatible versions are
+# already installed locally.
+# This also logs output if the
+# `:quiet` option is not set.
+# Defaults to `false`.
#
# @param gemfile [Proc] a block that is evaluated as a `Gemfile`.
#
@@ -29,31 +33,35 @@
#
# puts Pod::VERSION # => "0.34.4"
#
-def gemfile(install = false, options = {}, &gemfile)
+def gemfile(force_latest_compatible = false, options = {}, &gemfile)
require_relative "../bundler"
Bundler.reset!
opts = options.dup
ui = opts.delete(:ui) { Bundler::UI::Shell.new }
- ui.level = "silent" if opts.delete(:quiet) || !install
+ ui.level = "silent" if opts.delete(:quiet) || !force_latest_compatible
Bundler.ui = ui
raise ArgumentError, "Unknown options: #{opts.keys.join(", ")}" unless opts.empty?
- Bundler.with_unbundled_env do
+ old_gemfile = ENV["BUNDLE_GEMFILE"]
+ old_lockfile = ENV["BUNDLE_LOCKFILE"]
+
+ Bundler.unbundle_env!
+
+ begin
Bundler.instance_variable_set(:@bundle_path, Pathname.new(Gem.dir))
Bundler::SharedHelpers.set_env "BUNDLE_GEMFILE", "Gemfile"
+ Bundler::SharedHelpers.set_env "BUNDLE_LOCKFILE", "Gemfile.lock"
- Bundler::Plugin.gemfile_install(&gemfile) if Bundler.feature_flag.plugins?
+ Bundler::Plugin.gemfile_install(&gemfile) if Bundler.settings[:plugins]
builder = Bundler::Dsl.new
builder.instance_eval(&gemfile)
- builder.check_primary_source_safety
Bundler.settings.temporary(deployment: false, frozen: false) do
definition = builder.to_definition(nil, true)
- def definition.lock(*); end
definition.validate_runtime!
- if install || definition.missing_specs?
+ if force_latest_compatible || definition.missing_specs?
Bundler.settings.temporary(inline: true, no_install: false) do
installer = Bundler::Installer.install(Bundler.root, definition, system: true)
installer.post_install_messages.each do |name, message|
@@ -62,12 +70,37 @@ def gemfile(install = false, options = {}, &gemfile)
end
end
- runtime = Bundler::Runtime.new(nil, definition)
- runtime.setup.require
+ begin
+ runtime = Bundler::Runtime.new(nil, definition).setup
+ rescue Gem::LoadError => e
+ name = e.name
+ version = e.requirement.requirements.first[1]
+ activated_version = Gem.loaded_specs[name].version
+
+ Bundler.ui.info \
+ "The #{name} gem was resolved to #{version}, but #{activated_version} was activated by Bundler while installing it, causing a conflict. " \
+ "Bundler will now retry resolving with #{activated_version} instead."
+
+ builder.dependencies.delete_if {|d| d.name == name }
+ builder.instance_eval { gem name, activated_version }
+ definition = builder.to_definition(nil, true)
+
+ retry
+ end
+
+ runtime.require
+ end
+ ensure
+ if old_gemfile
+ ENV["BUNDLE_GEMFILE"] = old_gemfile
+ else
+ ENV["BUNDLE_GEMFILE"] = ""
end
- end
- if ENV["BUNDLE_GEMFILE"].nil?
- ENV["BUNDLE_GEMFILE"] = ""
+ if old_lockfile
+ ENV["BUNDLE_LOCKFILE"] = old_lockfile
+ else
+ ENV["BUNDLE_LOCKFILE"] = ""
+ end
end
end
diff --git a/lib/bundler/installer.rb b/lib/bundler/installer.rb
index 256f0be348..c5fd75431f 100644
--- a/lib/bundler/installer.rb
+++ b/lib/bundler/installer.rb
@@ -7,12 +7,6 @@ require_relative "installer/gem_installer"
module Bundler
class Installer
- class << self
- attr_accessor :ambiguous_gems
-
- Installer.ambiguous_gems = []
- end
-
attr_reader :post_install_messages, :definition
# Begins the installation process for Bundler.
@@ -69,9 +63,7 @@ module Bundler
Bundler.create_bundle_path
ProcessLock.lock do
- if Bundler.frozen_bundle?
- @definition.ensure_equivalent_gemfile_and_lockfile(options[:deployment])
- end
+ @definition.ensure_equivalent_gemfile_and_lockfile(options[:deployment])
if @definition.dependencies.empty?
Bundler.ui.warn "The Gemfile specifies no dependencies"
@@ -79,12 +71,9 @@ module Bundler
return
end
- if resolve_if_needed(options)
+ if @definition.setup_domain!(options)
ensure_specs_are_compatible!
- Bundler.load_plugins(@definition)
- options.delete(:jobs)
- else
- options[:jobs] = 1 # to avoid the overhead of Bundler::Worker
+ load_plugins
end
install(options)
@@ -96,6 +85,11 @@ module Bundler
end
def generate_bundler_executable_stubs(spec, options = {})
+ if spec.name == "bundler"
+ Bundler.ui.warn "Bundler itself does not use binstubs because its version is selected by RubyGems"
+ return
+ end
+
if options[:binstubs_cmd] && spec.executables.empty?
options = {}
spec.runtime_dependencies.each do |dep|
@@ -120,10 +114,6 @@ module Bundler
ruby_command = Thor::Util.ruby_command
ruby_command = ruby_command
template_path = File.expand_path("templates/Executable", __dir__)
- if spec.name == "bundler"
- template_path += ".bundler"
- spec.executables = %(bundle)
- end
template = File.read(template_path)
exists = []
@@ -196,16 +186,17 @@ module Bundler
# that said, it's a rare situation (other than rake), and parallel
# installation is SO MUCH FASTER. so we let people opt in.
def install(options)
- force = options["force"]
- jobs = installation_parallelization(options)
- install_in_parallel jobs, options[:standalone], force
- end
-
- def installation_parallelization(options)
- if jobs = options.delete(:jobs)
- return jobs
+ standalone = options[:standalone]
+ force = options[:force]
+ local = options[:local] || options[:"prefer-local"]
+ jobs = installation_parallelization
+ spec_installations = ParallelInstaller.call(self, @definition.specs, jobs, standalone, force, local: local)
+ spec_installations.each do |installation|
+ post_install_messages[installation.name] = installation.post_install_message if installation.has_post_install_message?
end
+ end
+ def installation_parallelization
if jobs = Bundler.settings[:jobs]
return jobs
end
@@ -213,6 +204,20 @@ module Bundler
Bundler.settings.processor_count
end
+ def load_plugins
+ Gem.load_plugins
+
+ requested_path_gems = @definition.specs.select {|s| s.source.is_a?(Source::Path) }
+ path_plugin_files = requested_path_gems.flat_map do |spec|
+ spec.matches_for_glob("rubygems_plugin#{Bundler.rubygems.suffix_pattern}")
+ rescue TypeError
+ error_message = "#{spec.name} #{spec.version} has an invalid gemspec"
+ raise Gem::InvalidSpecificationException, error_message
+ end
+ Gem.load_plugin_files(path_plugin_files)
+ Gem.load_env_plugins
+ end
+
def ensure_specs_are_compatible!
@definition.specs.each do |spec|
unless spec.matches_current_ruby?
@@ -226,26 +231,6 @@ module Bundler
end
end
- def install_in_parallel(size, standalone, force = false)
- spec_installations = ParallelInstaller.call(self, @definition.specs, size, standalone, force)
- spec_installations.each do |installation|
- post_install_messages[installation.name] = installation.post_install_message if installation.has_post_install_message?
- end
- end
-
- # returns whether or not a re-resolve was needed
- def resolve_if_needed(options)
- @definition.prefer_local! if options["prefer-local"]
-
- if options["local"] || (@definition.no_resolve_needed? && !@definition.missing_specs?)
- @definition.resolve_with_cache!
- false
- else
- @definition.resolve_remotely!
- true
- end
- end
-
def lock
@definition.lock
end
diff --git a/lib/bundler/installer/gem_installer.rb b/lib/bundler/installer/gem_installer.rb
index a7770eb7e0..5c4fa78253 100644
--- a/lib/bundler/installer/gem_installer.rb
+++ b/lib/bundler/installer/gem_installer.rb
@@ -2,20 +2,20 @@
module Bundler
class GemInstaller
- attr_reader :spec, :standalone, :worker, :force, :installer
+ attr_reader :spec, :standalone, :worker, :force, :local, :installer
- def initialize(spec, installer, standalone = false, worker = 0, force = false)
+ def initialize(spec, installer, standalone = false, worker = 0, force = false, local = false)
@spec = spec
@installer = installer
@standalone = standalone
@worker = worker
@force = force
+ @local = local
end
def install_from_spec
post_install_message = install
Bundler.ui.debug "#{worker}: #{spec.name} (#{spec.version}) from #{spec.loaded_from}"
- generate_executable_stubs
[true, post_install_message]
rescue Bundler::InstallHookError, Bundler::SecurityError, Bundler::APIResponseMismatchError, Bundler::InsecureInstallPathError
raise
@@ -54,6 +54,7 @@ module Bundler
spec.source.install(
spec,
force: force,
+ local: local,
build_args: Array(spec_settings),
previous_spec: previous_spec,
)
@@ -69,15 +70,5 @@ module Bundler
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
-
- def generate_executable_stubs
- return if Bundler.feature_flag.forget_cli_options?
- return if Bundler.settings[:inline]
- if Bundler.settings[:bin] && standalone
- installer.generate_standalone_bundler_executable_stubs(spec)
- elsif Bundler.settings[:bin]
- installer.generate_bundler_executable_stubs(spec, force: true)
- end
- end
end
end
diff --git a/lib/bundler/installer/parallel_installer.rb b/lib/bundler/installer/parallel_installer.rb
index e745088f81..d10e5ec924 100644
--- a/lib/bundler/installer/parallel_installer.rb
+++ b/lib/bundler/installer/parallel_installer.rb
@@ -68,11 +68,12 @@ module Bundler
attr_reader :size
- def initialize(installer, all_specs, size, standalone, force, skip: nil)
+ def initialize(installer, all_specs, size, standalone, force, local: false, skip: nil)
@installer = installer
@size = size
@standalone = standalone
@force = force
+ @local = local
@specs = all_specs.map {|s| SpecInstallation.new(s) }
@specs.each do |spec_install|
spec_install.state = :installed if skip.include?(spec_install.name)
@@ -127,7 +128,7 @@ module Bundler
def do_install(spec_install, worker_num)
Plugin.hook(Plugin::Events::GEM_BEFORE_INSTALL, spec_install)
gem_installer = Bundler::GemInstaller.new(
- spec_install.spec, @installer, @standalone, worker_num, @force
+ spec_install.spec, @installer, @standalone, worker_num, @force, @local
)
success, message = gem_installer.install_from_spec
if success
diff --git a/lib/bundler/installer/standalone.rb b/lib/bundler/installer/standalone.rb
index 5331df2e95..8b4de64df5 100644
--- a/lib/bundler/installer/standalone.rb
+++ b/lib/bundler/installer/standalone.rb
@@ -28,7 +28,7 @@ module Bundler
private
def paths
- @specs.map do |spec|
+ @specs.flat_map do |spec|
next if spec.name == "bundler"
Array(spec.require_paths).map do |path|
gem_path(path, spec).
@@ -36,7 +36,7 @@ module Bundler
sub(extensions_dir, 'extensions/\k<platform>/#{Gem.extension_api_version}')
# This is a static string intentionally. It's interpolated at a later time.
end
- end.flatten.compact
+ end.compact
end
def version_dir
@@ -58,9 +58,6 @@ module Bundler
else
SharedHelpers.relative_path_to(full_path, from: Bundler.root.join(bundler_path))
end
- rescue TypeError
- error_message = "#{spec.name} #{spec.version} has an invalid gemspec"
- raise Gem::InvalidSpecificationException.new(error_message)
end
def prevent_gem_activation
diff --git a/lib/bundler/lazy_specification.rb b/lib/bundler/lazy_specification.rb
index 8669e021c2..786dbcae65 100644
--- a/lib/bundler/lazy_specification.rb
+++ b/lib/bundler/lazy_specification.rb
@@ -8,28 +8,58 @@ module Bundler
include MatchPlatform
include ForcePlatform
- attr_reader :name, :version, :platform
+ attr_reader :name, :version, :platform, :materialization
attr_accessor :source, :remote, :force_ruby_platform, :dependencies, :required_ruby_version, :required_rubygems_version
+ #
+ # For backwards compatibility with existing lockfiles, if the most specific
+ # locked platform is not a specific platform like x86_64-linux or
+ # universal-java-11, then 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.
+ #
+ attr_accessor :most_specific_locked_platform
+
alias_method :runtime_dependencies, :dependencies
def self.from_spec(s)
lazy_spec = new(s.name, s.version, s.platform, s.source)
- lazy_spec.dependencies = s.dependencies
+ lazy_spec.dependencies = s.runtime_dependencies
lazy_spec.required_ruby_version = s.required_ruby_version
lazy_spec.required_rubygems_version = s.required_rubygems_version
lazy_spec
end
- def initialize(name, version, platform, source = nil)
+ def initialize(name, version, platform, source = nil, **materialization_options)
@name = name
@version = version
@dependencies = []
@required_ruby_version = Gem::Requirement.default
@required_rubygems_version = Gem::Requirement.default
- @platform = platform || Gem::Platform::RUBY
- @source = source
+ @platform = platform || Gem::Platform::RUBY
+
+ @original_source = source
+ @source = source
+ @materialization_options = materialization_options
+
@force_ruby_platform = default_force_ruby_platform
+ @most_specific_locked_platform = nil
+ @materialization = nil
+ end
+
+ def missing?
+ @materialization == self
+ end
+
+ def incomplete?
+ @materialization.nil?
+ end
+
+ def source_changed?
+ @original_source != source
end
def full_name
@@ -92,47 +122,37 @@ module Bundler
out
end
- def materialize_for_installation
- source.local!
+ def materialize_for_cache
+ source.remote!
- matching_specs = source.specs.search(use_exact_resolved_specifications? ? self : [name, version])
- return self if matching_specs.empty?
+ materialize(self, &:first)
+ end
- candidates = if use_exact_resolved_specifications?
- matching_specs
- else
- target_platform = ruby_platform_materializes_to_ruby_platform? ? platform : local_platform
+ def materialized_for_installation
+ @materialization = materialize_for_installation
+
+ self unless incomplete?
+ end
- installable_candidates = GemHelpers.select_best_platform_match(matching_specs, target_platform)
+ def materialize_for_installation
+ source.local!
- specification = __materialize__(installable_candidates, fallback_to_non_installable: false)
- return specification unless specification.nil?
+ if use_exact_resolved_specifications?
+ spec = materialize(self) {|specs| choose_compatible(specs, fallback_to_non_installable: false) }
+ return spec if spec
- if target_platform != platform
- installable_candidates = GemHelpers.select_best_platform_match(matching_specs, platform)
+ # Exact spec is incompatible; in frozen mode, try to find a compatible platform variant
+ # In non-frozen mode, return nil to trigger re-resolution and lockfile update
+ if Bundler.frozen_bundle?
+ materialize([name, version]) {|specs| resolve_best_platform(specs) }
end
-
- installable_candidates
+ else
+ materialize([name, version]) {|specs| resolve_best_platform(specs) }
end
-
- __materialize__(candidates)
end
- # If in frozen mode, we fallback to a non-installable candidate because by
- # doing this we avoid re-resolving and potentially end up changing the
- # lock file, which is not allowed. In that case, we will give a proper error
- # about the mismatch higher up the stack, right before trying to install the
- # bad gem.
- def __materialize__(candidates, fallback_to_non_installable: Bundler.frozen_bundle?)
- search = candidates.reverse.find do |spec|
- spec.is_a?(StubSpecification) || spec.matches_current_metadata?
- end
- if search.nil? && fallback_to_non_installable
- search = candidates.last
- else
- search.dependencies = dependencies if search && search.full_name == full_name && (search.is_a?(RemoteSpecification) || search.is_a?(EndpointSpecification))
- end
- search
+ def inspect
+ "#<#{self.class} @name=\"#{name}\" (#{full_name.delete_prefix("#{name}-")})>"
end
def to_s
@@ -148,26 +168,103 @@ module Bundler
@force_ruby_platform = true
end
+ def replace_source_with!(gemfile_source)
+ return unless gemfile_source.can_lock?(self)
+
+ @source = gemfile_source
+
+ true
+ end
+
private
def use_exact_resolved_specifications?
- @use_exact_resolved_specifications ||= !source.is_a?(Source::Path) && ruby_platform_materializes_to_ruby_platform?
+ !source.is_a?(Source::Path) && ruby_platform_materializes_to_ruby_platform?
+ end
+
+ # Try platforms in order of preference until finding a compatible spec.
+ # Used for legacy lockfiles and as a fallback when the exact locked spec
+ # is incompatible. Falls back to frozen bundle behavior if none match.
+ def resolve_best_platform(specs)
+ find_compatible_platform_spec(specs) || frozen_bundle_fallback(specs)
+ end
+
+ def find_compatible_platform_spec(specs)
+ candidate_platforms.each do |plat|
+ candidates = MatchPlatform.select_best_platform_match(specs, plat)
+ spec = choose_compatible(candidates, fallback_to_non_installable: false)
+ return spec if spec
+ end
+ nil
+ end
+
+ # Platforms to try in order of preference. Ruby platform is last since it
+ # requires compilation, but works when precompiled gems are incompatible.
+ def candidate_platforms
+ target = source.is_a?(Source::Path) ? platform : Bundler.local_platform
+ [target, platform, Gem::Platform::RUBY].uniq
+ end
+
+ # In frozen mode, accept any candidate. Will error at install time.
+ # When target differs from locked platform, prefer locked platform's candidates
+ # to preserve lockfile integrity.
+ def frozen_bundle_fallback(specs)
+ target = source.is_a?(Source::Path) ? platform : Bundler.local_platform
+ fallback_platform = target == platform ? target : platform
+ candidates = MatchPlatform.select_best_platform_match(specs, fallback_platform)
+ choose_compatible(candidates)
end
- #
- # For backwards compatibility with existing lockfiles, if the most specific
- # locked platform is not a specific platform like x86_64-linux or
- # universal-java-11, then 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?
- generic_platform = generic_local_platform == Gem::Platform::JAVA ? Gem::Platform::JAVA : Gem::Platform::RUBY
+ generic_platform = Bundler.generic_local_platform == Gem::Platform::JAVA ? Gem::Platform::JAVA : Gem::Platform::RUBY
+
+ (most_specific_locked_platform != generic_platform) || force_ruby_platform || Bundler.settings[:force_ruby_platform]
+ end
+
+ def materialize(query)
+ matching_specs = source.specs.search(query)
+ return self if matching_specs.empty?
+
+ yield matching_specs
+ end
- !Bundler.most_specific_locked_platform?(generic_platform) || force_ruby_platform || Bundler.settings[:force_ruby_platform]
+ # If in frozen mode, we fallback to a non-installable candidate because by
+ # doing this we avoid re-resolving and potentially end up changing the
+ # lockfile, which is not allowed. In that case, we will give a proper error
+ # about the mismatch higher up the stack, right before trying to install the
+ # bad gem.
+ def choose_compatible(candidates, fallback_to_non_installable: Bundler.frozen_bundle?)
+ search = candidates.reverse.find do |spec|
+ spec.is_a?(StubSpecification) || spec.matches_current_metadata?
+ end
+ if search.nil? && fallback_to_non_installable
+ search = candidates.last
+ end
+
+ if search
+ validate_dependencies(search) if search.platform == platform
+
+ search.locked_platform = platform if search.instance_of?(RemoteSpecification) || search.instance_of?(EndpointSpecification)
+ end
+ search
+ end
+
+ # Validate dependencies of this locked spec are consistent with dependencies
+ # of the actual spec that was materialized.
+ #
+ # Note that unless we are in strict mode (which we set during installation)
+ # we don't validate dependencies of locally installed gems but
+ # accept what's in the lockfile instead for performance, since loading
+ # dependencies of locally installed gems would mean evaluating all gemspecs,
+ # which would affect `bundler/setup` performance.
+ def validate_dependencies(spec)
+ if !@materialization_options[:strict] && spec.is_a?(StubSpecification)
+ spec.dependencies = dependencies
+ else
+ if !source.is_a?(Source::Path) && spec.runtime_dependencies.sort != dependencies.sort
+ raise IncorrectLockfileDependencies.new(self)
+ end
+ end
end
end
end
diff --git a/lib/bundler/lockfile_generator.rb b/lib/bundler/lockfile_generator.rb
index a646d00ee1..6b6cf9d9ea 100644
--- a/lib/bundler/lockfile_generator.rb
+++ b/lib/bundler/lockfile_generator.rb
@@ -29,7 +29,7 @@ module Bundler
private
def add_sources
- definition.send(:sources).lock_sources.each_with_index do |source, idx|
+ definition.sources.lock_sources.each_with_index do |source, idx|
out << "\n" unless idx.zero?
# Add the source header
@@ -95,7 +95,7 @@ module Bundler
out << " #{key}: #{val}\n"
end
when String
- out << " #{value}\n"
+ out << " #{value}\n"
else
raise ArgumentError, "#{value.inspect} can't be serialized in a lockfile"
end
diff --git a/lib/bundler/lockfile_parser.rb b/lib/bundler/lockfile_parser.rb
index 1e11621e55..ac0ce1ef3d 100644
--- a/lib/bundler/lockfile_parser.rb
+++ b/lib/bundler/lockfile_parser.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require_relative "shared_helpers"
+
module Bundler
class LockfileParser
class Position
@@ -29,6 +31,7 @@ module Bundler
:dependencies,
:specs,
:platforms,
+ :most_specific_locked_platform,
:bundler_version,
:ruby_version,
:checksums,
@@ -91,7 +94,7 @@ module Bundler
lockfile_contents.split(BUNDLED).last.strip
end
- def initialize(lockfile)
+ def initialize(lockfile, strict: false)
@platforms = []
@sources = []
@dependencies = {}
@@ -103,6 +106,7 @@ module Bundler
"Gemfile.lock"
end
@pos = Position.new(1, 1)
+ @strict = strict
if lockfile.match?(/<<<<<<<|=======|>>>>>>>|\|\|\|\|\|\|\|/)
raise LockfileError, "Your #{@lockfile_path} contains merge conflicts.\n" \
@@ -136,7 +140,17 @@ module Bundler
end
@pos.advance!(line)
end
- @specs = @specs.values.sort_by!(&:full_name)
+
+ if @platforms.include?(Gem::Platform::X64_MINGW_LEGACY)
+ SharedHelpers.feature_deprecated!("Found x64-mingw32 in lockfile, which is deprecated and will be removed in the future.")
+ end
+
+ @most_specific_locked_platform = @platforms.min_by do |bundle_platform|
+ Gem::Platform.platform_specificity_match(bundle_platform, Bundler.local_platform)
+ end
+ @specs = @specs.values.sort_by!(&:full_name).each do |spec|
+ spec.most_specific_locked_platform = @most_specific_locked_platform
+ end
rescue ArgumentError => e
Bundler.ui.debug(e)
raise LockfileError, "Your lockfile is unreadable. Run `rm #{@lockfile_path}` " \
@@ -231,7 +245,6 @@ module Bundler
spaces = $1
return unless spaces.size == 2
checksums = $6
- return unless checksums
name = $2
version = $3
platform = $4
@@ -241,10 +254,14 @@ module Bundler
full_name = Gem::NameTuple.new(name, version, platform).full_name
return unless spec = @specs[full_name]
- checksums.split(",") do |lock_checksum|
- column = line.index(lock_checksum) + 1
- checksum = Checksum.from_lock(lock_checksum, "#{@lockfile_path}:#{@pos.line}:#{column}")
- spec.source.checksum_store.register(spec, checksum)
+ if checksums
+ checksums.split(",") do |lock_checksum|
+ column = line.index(lock_checksum) + 1
+ checksum = Checksum.from_lock(lock_checksum, "#{@lockfile_path}:#{@pos.line}:#{column}")
+ spec.source.checksum_store.register(spec, checksum)
+ end
+ else
+ spec.source.checksum_store.register(spec, nil)
end
end
@@ -260,7 +277,7 @@ module Bundler
version = Gem::Version.new(version)
platform = platform ? Gem::Platform.new(platform) : Gem::Platform::RUBY
- @current_spec = LazySpecification.new(name, version, platform, @current_source)
+ @current_spec = LazySpecification.new(name, version, platform, @current_source, strict: @strict)
@current_source.add_dependency_names(name)
@specs[@current_spec.full_name] = @current_spec
@@ -272,7 +289,7 @@ module Bundler
end
def parse_platform(line)
- @platforms << Gem::Platform.new($1) if line =~ /^ (.*)$/
+ @platforms << Gem::Platform.new($1.strip) if line =~ /^ (.*)$/
end
def parse_bundled_with(line)
diff --git a/lib/bundler/man/bundle-add.1 b/lib/bundler/man/bundle-add.1
index 56a3b6f85c..4474969db6 100644
--- a/lib/bundler/man/bundle-add.1
+++ b/lib/bundler/man/bundle-add.1
@@ -1,53 +1,47 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-ADD" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-ADD" "1" "September 2025" ""
.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] [\-\-path=PATH] [\-\-git=GIT] [\-\-github=GITHUB] [\-\-branch=BRANCH] [\-\-ref=REF] [\-\-skip\-install] [\-\-strict] [\-\-optimistic]
+\fBbundle add\fR \fIGEM_NAME\fR [\-\-group=GROUP] [\-\-version=VERSION] [\-\-source=SOURCE] [\-\-path=PATH] [\-\-git=GIT|\-\-github=GITHUB] [\-\-branch=BRANCH] [\-\-ref=REF] [\-\-quiet] [\-\-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\.
-.P
-Example:
-.P
-bundle add rails
-.P
-bundle add rails \-\-version "< 3\.0, > 1\.1"
-.P
-bundle add rails \-\-version "~> 5\.0\.0" \-\-source "https://gems\.example\.com" \-\-group "development"
-.P
-bundle add rails \-\-skip\-install
-.P
-bundle add rails \-\-group "development, test"
+Adds the named gem to the [\fBGemfile(5)\fR][Gemfile(5)] and run \fBbundle install\fR\. \fBbundle install\fR can be avoided by using the flag \fB\-\-skip\-install\fR\.
.SH "OPTIONS"
.TP
-\fB\-\-version\fR, \fB\-v\fR
+\fB\-\-version=VERSION\fR, \fB\-v=VERSION\fR
Specify version requirements(s) for the added gem\.
.TP
-\fB\-\-group\fR, \fB\-g\fR
+\fB\-\-group=GROUP\fR, \fB\-g=GROUP\fR
Specify the group(s) for the added gem\. Multiple groups should be separated by commas\.
.TP
-\fB\-\-source\fR, \fB\-s\fR
+\fB\-\-source=SOURCE\fR, \fB\-s=SOURCE\fR
Specify the source for the added gem\.
.TP
-\fB\-\-require\fR, \fB\-r\fR
+\fB\-\-require=REQUIRE\fR, \fB\-r=REQUIRE\fR
Adds require path to gem\. Provide false, or a path as a string\.
.TP
-\fB\-\-path\fR
+\fB\-\-path=PATH\fR
Specify the file system path for the added gem\.
.TP
-\fB\-\-git\fR
+\fB\-\-git=GIT\fR
Specify the git source for the added gem\.
.TP
-\fB\-\-github\fR
+\fB\-\-github=GITHUB\fR
Specify the github source for the added gem\.
.TP
-\fB\-\-branch\fR
+\fB\-\-branch=BRANCH\fR
Specify the git branch for the added gem\.
.TP
-\fB\-\-ref\fR
+\fB\-\-ref=REF\fR
Specify the git ref for the added gem\.
.TP
+\fB\-\-glob=GLOB\fR
+Specify the location of a dependency's \.gemspec, expanded within Ruby (single quotes recommended)\.
+.TP
+\fB\-\-quiet\fR
+Do not print progress information to the standard output\.
+.TP
\fB\-\-skip\-install\fR
Adds the gem to the Gemfile but does not install it\.
.TP
@@ -56,4 +50,27 @@ Adds optimistic declaration of version\.
.TP
\fB\-\-strict\fR
Adds strict declaration of version\.
-
+.SH "EXAMPLES"
+.IP "1." 4
+You can add the \fBrails\fR gem to the Gemfile without any version restriction\. The source of the gem will be the global source\.
+.IP
+\fBbundle add rails\fR
+.IP "2." 4
+You can add the \fBrails\fR gem with version greater than 1\.1 (not including 1\.1) and less than 3\.0\.
+.IP
+\fBbundle add rails \-\-version "> 1\.1, < 3\.0"\fR
+.IP "3." 4
+You can use the \fBhttps://gems\.example\.com\fR custom source and assign the gem to a group\.
+.IP
+\fBbundle add rails \-\-version "~> 5\.0\.0" \-\-source "https://gems\.example\.com" \-\-group "development"\fR
+.IP "4." 4
+The following adds the \fBgem\fR entry to the Gemfile without installing the gem\. You can install gems later via \fBbundle install\fR\.
+.IP
+\fBbundle add rails \-\-skip\-install\fR
+.IP "5." 4
+You can assign the gem to more than one group\.
+.IP
+\fBbundle add rails \-\-group "development, test"\fR
+.IP "" 0
+.SH "SEE ALSO"
+Gemfile(5) \fIhttps://bundler\.io/man/gemfile\.5\.html\fR, bundle\-remove(1) \fIbundle\-remove\.1\.html\fR
diff --git a/lib/bundler/man/bundle-add.1.ronn b/lib/bundler/man/bundle-add.1.ronn
index 37c92e5fcd..48c0c66b09 100644
--- a/lib/bundler/man/bundle-add.1.ronn
+++ b/lib/bundler/man/bundle-add.1.ronn
@@ -1,53 +1,52 @@
bundle-add(1) -- Add gem to the Gemfile and run bundle install
-================================================================
+==============================================================
## SYNOPSIS
-`bundle add` <GEM_NAME> [--group=GROUP] [--version=VERSION] [--source=SOURCE] [--path=PATH] [--git=GIT] [--github=GITHUB] [--branch=BRANCH] [--ref=REF] [--skip-install] [--strict] [--optimistic]
+`bundle add` <GEM_NAME> [--group=GROUP] [--version=VERSION] [--source=SOURCE]
+ [--path=PATH] [--git=GIT|--github=GITHUB] [--branch=BRANCH] [--ref=REF]
+ [--quiet] [--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"
+Adds the named gem to the [`Gemfile(5)`][Gemfile(5)] and run `bundle install`.
+`bundle install` can be avoided by using the flag `--skip-install`.
## OPTIONS
-* `--version`, `-v`:
+
+* `--version=VERSION`, `-v=VERSION`:
Specify version requirements(s) for the added gem.
-* `--group`, `-g`:
+* `--group=GROUP`, `-g=GROUP`:
Specify the group(s) for the added gem. Multiple groups should be separated by commas.
-* `--source`, `-s`:
+* `--source=SOURCE`, `-s=SOURCE`:
Specify the source for the added gem.
-* `--require`, `-r`:
+* `--require=REQUIRE`, `-r=REQUIRE`:
Adds require path to gem. Provide false, or a path as a string.
-* `--path`:
+* `--path=PATH`:
Specify the file system path for the added gem.
-* `--git`:
+* `--git=GIT`:
Specify the git source for the added gem.
-* `--github`:
+* `--github=GITHUB`:
Specify the github source for the added gem.
-* `--branch`:
+* `--branch=BRANCH`:
Specify the git branch for the added gem.
-* `--ref`:
+* `--ref=REF`:
Specify the git ref for the added gem.
+* `--glob=GLOB`:
+ Specify the location of a dependency's .gemspec, expanded within Ruby (single quotes recommended).
+
+* `--quiet`:
+ Do not print progress information to the standard output.
+
* `--skip-install`:
Adds the gem to the Gemfile but does not install it.
@@ -56,3 +55,33 @@ bundle add rails --group "development, test"
* `--strict`:
Adds strict declaration of version.
+
+## EXAMPLES
+
+1. You can add the `rails` gem to the Gemfile without any version restriction.
+ The source of the gem will be the global source.
+
+ `bundle add rails`
+
+2. You can add the `rails` gem with version greater than 1.1 (not including 1.1) and less than 3.0.
+
+ `bundle add rails --version "> 1.1, < 3.0"`
+
+3. You can use the `https://gems.example.com` custom source and assign the gem
+ to a group.
+
+ `bundle add rails --version "~> 5.0.0" --source "https://gems.example.com" --group "development"`
+
+4. The following adds the `gem` entry to the Gemfile without installing the
+ gem. You can install gems later via `bundle install`.
+
+ `bundle add rails --skip-install`
+
+5. You can assign the gem to more than one group.
+
+ `bundle add rails --group "development, test"`
+
+## SEE ALSO
+
+[Gemfile(5)](https://bundler.io/man/gemfile.5.html),
+[bundle-remove(1)](bundle-remove.1.html)
diff --git a/lib/bundler/man/bundle-binstubs.1 b/lib/bundler/man/bundle-binstubs.1
index 4ec301951f..b8c153696b 100644
--- a/lib/bundler/man/bundle-binstubs.1
+++ b/lib/bundler/man/bundle-binstubs.1
@@ -1,30 +1,30 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-BINSTUBS" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-BINSTUBS" "1" "September 2025" ""
.SH "NAME"
\fBbundle\-binstubs\fR \- Install the binstubs of the listed gems
.SH "SYNOPSIS"
-\fBbundle binstubs\fR \fIGEM_NAME\fR [\-\-force] [\-\-path PATH] [\-\-standalone]
+\fBbundle binstubs\fR \fIGEM_NAME\fR [\-\-force] [\-\-standalone] [\-\-all\-platforms]
.SH "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 \fBbin/\fR\. Binstubs are a shortcut\-or alternative\- to always using \fBbundle exec\fR\. This gives you a file that can be run directly, and one that will always run the correct gem version used by the application\.
.P
For example, if you run \fBbundle binstubs rspec\-core\fR, Bundler will create the file \fBbin/rspec\fR\. That file will contain enough code to load Bundler, tell it to load the bundled gems, and then run rspec\.
.P
-This command generates binstubs for executables in \fBGEM_NAME\fR\. Binstubs are put into \fBbin\fR, or the \fB\-\-path\fR directory if one has been set\. Calling binstubs with [GEM [GEM]] will create binstubs for all given gems\.
+This command generates binstubs for executables in \fBGEM_NAME\fR\. Binstubs are put into \fBbin\fR, or the directory specified by \fBbin\fR setting if it has been configured\. Calling binstubs with [GEM [GEM]] will create binstubs for all given gems\.
.SH "OPTIONS"
.TP
\fB\-\-force\fR
Overwrite existing binstubs if they exist\.
.TP
-\fB\-\-path\fR
-The location to install the specified binstubs to\. This defaults to \fBbin\fR\.
-.TP
\fB\-\-standalone\fR
Makes binstubs that can work without depending on Rubygems or Bundler at runtime\.
.TP
-\fB\-\-shebang\fR
+\fB\-\-shebang=SHEBANG\fR
Specify a different shebang executable name than the default (default 'ruby')
.TP
\fB\-\-all\fR
Create binstubs for all gems in the bundle\.
+.TP
+\fB\-\-all\-platforms\fR
+Install binstubs for all platforms\.
diff --git a/lib/bundler/man/bundle-binstubs.1.ronn b/lib/bundler/man/bundle-binstubs.1.ronn
index a96186929f..cbe5983f4d 100644
--- a/lib/bundler/man/bundle-binstubs.1.ronn
+++ b/lib/bundler/man/bundle-binstubs.1.ronn
@@ -3,7 +3,7 @@ bundle-binstubs(1) -- Install the binstubs of the listed gems
## SYNOPSIS
-`bundle binstubs` <GEM_NAME> [--force] [--path PATH] [--standalone]
+`bundle binstubs` <GEM_NAME> [--force] [--standalone] [--all-platforms]
## DESCRIPTION
@@ -19,23 +19,24 @@ 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.
+Binstubs are put into `bin`, or the directory specified by `bin` setting if it
+has been configured. 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`:
+* `--shebang=SHEBANG`:
Specify a different shebang executable name than the default (default 'ruby')
* `--all`:
Create binstubs for all gems in the bundle.
+
+* `--all-platforms`:
+ Install binstubs for all platforms.
diff --git a/lib/bundler/man/bundle-cache.1 b/lib/bundler/man/bundle-cache.1
index e2da1269e6..c1dafbf070 100644
--- a/lib/bundler/man/bundle-cache.1
+++ b/lib/bundler/man/bundle-cache.1
@@ -1,16 +1,32 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-CACHE" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-CACHE" "1" "September 2025" ""
.SH "NAME"
\fBbundle\-cache\fR \- Package your needed \fB\.gem\fR files into your application
.SH "SYNOPSIS"
-\fBbundle cache\fR
+\fBbundle cache\fR [\fIOPTIONS\fR]
.P
alias: \fBpackage\fR, \fBpack\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 \fBbundle install(1)\fR \fIbundle\-install\.1\.html\fR, use the gems in the cache in preference to the ones on \fBrubygems\.org\fR\.
+.SH "OPTIONS"
+.TP
+\fB\-\-all\-platforms\fR
+Include gems for all platforms present in the lockfile, not only the current one\.
+.TP
+\fB\-\-cache\-path=CACHE\-PATH\fR
+Specify a different cache path than the default (vendor/cache)\.
+.TP
+\fB\-\-gemfile=GEMFILE\fR
+Use the specified gemfile instead of Gemfile\.
+.TP
+\fB\-\-no\-install\fR
+Don't install the gems, only update the cache\.
+.TP
+\fB\-\-quiet\fR
+Only output warnings and errors\.
.SH "GIT AND PATH GEMS"
-The \fBbundle cache\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\.
+The \fBbundle cache\fR command can also package \fB:git\fR and \fB:path\fR dependencies besides \.gem files\. This can be disabled setting \fBcache_all\fR to false\.
.SH "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 \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"
diff --git a/lib/bundler/man/bundle-cache.1.ronn b/lib/bundler/man/bundle-cache.1.ronn
index 8112c2c551..51846c96b4 100644
--- a/lib/bundler/man/bundle-cache.1.ronn
+++ b/lib/bundler/man/bundle-cache.1.ronn
@@ -1,9 +1,9 @@
bundle-cache(1) -- Package your needed `.gem` files into your application
-===========================================================================
+=========================================================================
## SYNOPSIS
-`bundle cache`
+`bundle cache` [*OPTIONS*]
alias: `package`, `pack`
@@ -13,11 +13,27 @@ 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.1.html),
use the gems in the cache in preference to the ones on `rubygems.org`.
+## OPTIONS
+
+* `--all-platforms`:
+ Include gems for all platforms present in the lockfile, not only the current one.
+
+* `--cache-path=CACHE-PATH`:
+ Specify a different cache path than the default (vendor/cache).
+
+* `--gemfile=GEMFILE`:
+ Use the specified gemfile instead of Gemfile.
+
+* `--no-install`:
+ Don't install the gems, only update the cache.
+
+* `--quiet`:
+ Only output warnings and errors.
+
## 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.
+besides .gem files. This can be disabled setting `cache_all` to false.
## SUPPORT FOR MULTIPLE PLATFORMS
diff --git a/lib/bundler/man/bundle-check.1 b/lib/bundler/man/bundle-check.1
index dee1af1326..f83af1eb55 100644
--- a/lib/bundler/man/bundle-check.1
+++ b/lib/bundler/man/bundle-check.1
@@ -1,10 +1,10 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-CHECK" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-CHECK" "1" "September 2025" ""
.SH "NAME"
\fBbundle\-check\fR \- Verifies if dependencies are satisfied by installed gems
.SH "SYNOPSIS"
-\fBbundle check\fR [\-\-dry\-run] [\-\-gemfile=FILE] [\-\-path=PATH]
+\fBbundle check\fR [\-\-dry\-run] [\-\-gemfile=FILE]
.SH "DESCRIPTION"
\fBcheck\fR 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\.
.P
@@ -16,9 +16,6 @@ If the lockfile needs to be updated then it will be resolved using the gems inst
\fB\-\-dry\-run\fR
Locks the [\fBGemfile(5)\fR][Gemfile(5)] before running the command\.
.TP
-\fB\-\-gemfile\fR
+\fB\-\-gemfile=GEMFILE\fR
Use the specified gemfile instead of the [\fBGemfile(5)\fR][Gemfile(5)]\.
-.TP
-\fB\-\-path\fR
-Specify a different path than the system default (\fB$BUNDLE_PATH\fR or \fB$GEM_HOME\fR)\. Bundler will remember this value for future installs on this machine\.
diff --git a/lib/bundler/man/bundle-check.1.ronn b/lib/bundler/man/bundle-check.1.ronn
index eb3ff1daf9..92589159c9 100644
--- a/lib/bundler/man/bundle-check.1.ronn
+++ b/lib/bundler/man/bundle-check.1.ronn
@@ -5,7 +5,6 @@ bundle-check(1) -- Verifies if dependencies are satisfied by installed gems
`bundle check` [--dry-run]
[--gemfile=FILE]
- [--path=PATH]
## DESCRIPTION
@@ -22,8 +21,6 @@ installed on the local machine, if they satisfy the requirements.
* `--dry-run`:
Locks the [`Gemfile(5)`][Gemfile(5)] before running the command.
-* `--gemfile`:
+
+* `--gemfile=GEMFILE`:
Use the specified gemfile instead of the [`Gemfile(5)`][Gemfile(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.
diff --git a/lib/bundler/man/bundle-clean.1 b/lib/bundler/man/bundle-clean.1
index 7c7f9b5c77..c4d148c5df 100644
--- a/lib/bundler/man/bundle-clean.1
+++ b/lib/bundler/man/bundle-clean.1
@@ -1,6 +1,6 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-CLEAN" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-CLEAN" "1" "September 2025" ""
.SH "NAME"
\fBbundle\-clean\fR \- Cleans up unused gems in your bundler directory
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-config.1 b/lib/bundler/man/bundle-config.1
index 2de52ee375..05c13e2d0f 100644
--- a/lib/bundler/man/bundle-config.1
+++ b/lib/bundler/man/bundle-config.1
@@ -1,16 +1,16 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-CONFIG" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-CONFIG" "1" "September 2025" ""
.SH "NAME"
\fBbundle\-config\fR \- Set bundler configuration options
.SH "SYNOPSIS"
-\fBbundle config\fR list
+\fBbundle config\fR [list]
.br
-\fBbundle config\fR [get] NAME
+\fBbundle config\fR [get [\-\-local|\-\-global]] NAME
.br
-\fBbundle config\fR [set] NAME VALUE
+\fBbundle config\fR [set [\-\-local|\-\-global]] NAME VALUE
.br
-\fBbundle config\fR unset NAME
+\fBbundle config\fR unset [\-\-local|\-\-global] NAME
.SH "DESCRIPTION"
This command allows you to interact with Bundler's configuration system\.
.P
@@ -25,47 +25,203 @@ Global config (\fB~/\.bundle/config\fR)
Bundler default config
.IP "" 0
.P
+Executing \fBbundle\fR with the \fBBUNDLE_IGNORE_CONFIG\fR environment variable set will cause it to ignore all configuration\.
+.SH "SUB\-COMMANDS"
+.SS "list (default command)"
Executing \fBbundle config list\fR will print a list of all bundler configuration for the current bundle, and where that configuration was set\.
+.SS "get"
+Executing \fBbundle config get <name>\fR will print the value of that configuration setting, and all locations where it was set\.
.P
-Executing \fBbundle config get <name>\fR will print the value of that configuration setting, and where it was set\.
-.P
-Executing \fBbundle config set <name> <value>\fR defaults to setting \fBlocal\fR configuration if executing from within a local application, otherwise it will set \fBglobal\fR configuration\. See \fB\-\-local\fR and \fB\-\-global\fR options below\.
+\fBOPTIONS\fR
+.TP
+\fB\-\-local\fR
+Get configuration from configuration file for the local application, namely, \fB<project_root>/\.bundle/config\fR, or \fB$BUNDLE_APP_CONFIG/config\fR if \fBBUNDLE_APP_CONFIG\fR is set\.
+.TP
+\fB\-\-global\fR
+Get configuration from configuration file global to all bundles executed as the current user, namely, from \fB~/\.bundle/config\fR\.
+.SS "set"
+Executing \fBbundle config set <name> <value>\fR defaults to setting \fBlocal\fR configuration if executing from within a local application, otherwise it will set \fBglobal\fR configuration\.
.P
+\fBOPTIONS\fR
+.TP
+\fB\-\-local\fR
Executing \fBbundle config set \-\-local <name> <value>\fR will set that configuration in the directory for the local application\. The configuration will be stored in \fB<project_root>/\.bundle/config\fR\. If \fBBUNDLE_APP_CONFIG\fR is set, the configuration will be stored in \fB$BUNDLE_APP_CONFIG/config\fR\.
-.P
+.TP
+\fB\-\-global\fR
Executing \fBbundle config set \-\-global <name> <value>\fR will set that configuration to the value specified for all bundles executed as the current user\. The configuration will be stored in \fB~/\.bundle/config\fR\. If \fIname\fR already is set, \fIname\fR will be overridden and user will be warned\.
-.P
+.SS "unset"
Executing \fBbundle config unset <name>\fR will delete the configuration in both local and global sources\.
.P
-Executing \fBbundle config unset \-\-global <name>\fR will delete the configuration only from the user configuration\.
-.P
+\fBOPTIONS\fR
+.TP
+\fB\-\-local\fR
Executing \fBbundle config unset \-\-local <name>\fR will delete the configuration only from the local application\.
+.TP
+\fB\-\-global\fR
+Executing \fBbundle config unset \-\-global <name>\fR will delete the configuration only from the user configuration\.
+.SH "CONFIGURATION KEYS"
+Configuration keys in bundler have two forms: the canonical form and the environment variable form\.
.P
-Executing bundle with the \fBBUNDLE_IGNORE_CONFIG\fR environment variable set will cause it to ignore all configuration\.
-.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)\.
+For instance, passing the \fB\-\-without\fR flag to bundle install(1) \fIbundle\-install\.1\.html\fR prevents Bundler from installing certain groups specified in the Gemfile(5)\. Bundler persists this value in \fBapp/\.bundle/config\fR so that calls to \fBBundler\.setup\fR do not try to find gems from the \fBGemfile\fR that you didn't install\. Additionally, subsequent calls to bundle install(1) \fIbundle\-install\.1\.html\fR remember this setting and skip those groups\.
.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 \-\-local path foo\fR)\.
+The canonical form of this configuration is \fB"without"\fR\. To convert the canonical form to the environment variable form, capitalize it, and prepend \fBBUNDLE_\fR\. The environment variable form of \fB"without"\fR is \fBBUNDLE_WITHOUT\fR\.
.P
-The options that can be configured are:
+Any periods in the configuration keys must be replaced with two underscores when setting it via environment variables\. The configuration key \fBlocal\.rack\fR becomes the environment variable \fBBUNDLE_LOCAL__RACK\fR\.
+.SH "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) \fIbundle\-install\.1\.html\fR\.
+.TP
+\fBauto_install\fR (\fBBUNDLE_AUTO_INSTALL\fR)
+Automatically run \fBbundle install\fR when gems are missing\.
+.TP
+\fBbin\fR (\fBBUNDLE_BIN\fR)
+If configured, \fBbundle binstubs\fR will install executables from gems in the bundle to the specified directory\. Otherwise it will create them in a \fBbin\fR directory relative to the Gemfile directory\. These executables run in Bundler's context\. If used, you might add this directory to your environment's \fBPATH\fR variable\. For instance, if the \fBrails\fR gem comes with a \fBrails\fR executable, \fBbundle binstubs\fR will create a \fBbin/rails\fR executable that ensures that all referred dependencies will be resolved using the bundled gems\.
+.TP
+\fBcache_all\fR (\fBBUNDLE_CACHE_ALL\fR)
+Cache all gems, including path and git gems\. This needs to be explicitly before bundler 4, but will be the default on bundler 4\.
+.TP
+\fBcache_all_platforms\fR (\fBBUNDLE_CACHE_ALL_PLATFORMS\fR)
+Cache gems for all platforms\.
+.TP
+\fBcache_path\fR (\fBBUNDLE_CACHE_PATH\fR)
+The directory that bundler will place cached gems in when running \fBbundle package\fR, and that bundler will look in when installing gems\. Defaults to \fBvendor/cache\fR\.
+.TP
+\fBclean\fR (\fBBUNDLE_CLEAN\fR)
+Whether Bundler should run \fBbundle clean\fR automatically after \fBbundle install\fR\. Defaults to \fBtrue\fR in Bundler 4, as long as \fBpath\fR is not explicitly configured\.
+.TP
+\fBconsole\fR (\fBBUNDLE_CONSOLE\fR)
+The console that \fBbundle console\fR starts\. Defaults to \fBirb\fR\.
+.TP
+\fBdefault_cli_command\fR (\fBBUNDLE_DEFAULT_CLI_COMMAND\fR)
+The command that running \fBbundle\fR without arguments should run\. Defaults to \fBcli_help\fR since Bundler 4, but can also be \fBinstall\fR which was the previous default\.
+.TP
+\fBdeployment\fR (\fBBUNDLE_DEPLOYMENT\fR)
+Equivalent to setting \fBfrozen\fR to \fBtrue\fR and \fBpath\fR to \fBvendor/bundle\fR\.
+.TP
+\fBdisable_checksum_validation\fR (\fBBUNDLE_DISABLE_CHECKSUM_VALIDATION\fR)
+Allow installing gems even if they do not match the checksum provided by RubyGems\.
+.TP
+\fBdisable_exec_load\fR (\fBBUNDLE_DISABLE_EXEC_LOAD\fR)
+Stop Bundler from using \fBload\fR to launch an executable in\-process in \fBbundle exec\fR\.
+.TP
+\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\.
+.TP
+\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\.
+.TP
+\fBdisable_shared_gems\fR (\fBBUNDLE_DISABLE_SHARED_GEMS\fR)
+Stop Bundler from accessing gems installed to RubyGems' normal location\.
.TP
-\fBbin\fR
-Creates a directory (defaults to \fB~/bin\fR) 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 \fBPATH\fR variable\. For instance, if the \fBrails\fR gem comes with a \fBrails\fR executable, this flag will create a \fBbin/rails\fR executable that ensures that all referred dependencies will be resolved using the bundled gems\.
+\fBdisable_version_check\fR (\fBBUNDLE_DISABLE_VERSION_CHECK\fR)
+Stop Bundler from checking if a newer Bundler version is available on rubygems\.org\.
.TP
-\fBdeployment\fR
-In deployment mode, Bundler will 'roll\-out' the bundle for \fBproduction\fR use\. Please check carefully if you want to have this option enabled in \fBdevelopment\fR or \fBtest\fR environments\.
+\fBforce_ruby_platform\fR (\fBBUNDLE_FORCE_RUBY_PLATFORM\fR)
+Ignore the current machine's platform and install only \fBruby\fR platform gems\. As a result, gems with native extensions will be compiled from source\.
.TP
-\fBonly\fR
-A space\-separated list of groups to install only gems of the specified groups\.
+\fBfrozen\fR (\fBBUNDLE_FROZEN\fR)
+Disallow any automatic changes to \fBGemfile\.lock\fR\. Bundler commands will be blocked unless the lockfile can be installed exactly as written\. Usually this will happen when changing the \fBGemfile\fR manually and forgetting to update the lockfile through \fBbundle lock\fR or \fBbundle install\fR\.
.TP
-\fBpath\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\.
+\fBgem\.github_username\fR (\fBBUNDLE_GEM__GITHUB_USERNAME\fR)
+Sets a GitHub username or organization to be used in the \fBREADME\fR and \fB\.gemspec\fR files 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\.
.TP
-\fBwithout\fR
-A space\-separated list of groups referencing gems to skip during installation\.
+\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\.
.TP
-\fBwith\fR
-A space\-separated list of \fBoptional\fR groups referencing gems to include during installation\.
+\fBgemfile\fR (\fBBUNDLE_GEMFILE\fR)
+The name of the file that bundler should use as the \fBGemfile\fR\. This location of this file also sets the root of the project, which is used to resolve relative paths in the \fBGemfile\fR, among other things\. By default, bundler will search up from the current working directory until it finds a \fBGemfile\fR\.
+.TP
+\fBglobal_gem_cache\fR (\fBBUNDLE_GLOBAL_GEM_CACHE\fR)
+Whether Bundler should cache all gems and compiled extensions globally, rather than locally to the configured installation path\.
+.TP
+\fBignore_funding_requests\fR (\fBBUNDLE_IGNORE_FUNDING_REQUESTS\fR)
+When set, no funding requests will be printed\.
+.TP
+\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\.
+.TP
+\fBinit_gems_rb\fR (\fBBUNDLE_INIT_GEMS_RB\fR)
+Generate a \fBgems\.rb\fR instead of a \fBGemfile\fR when running \fBbundle init\fR\.
+.TP
+\fBjobs\fR (\fBBUNDLE_JOBS\fR)
+The number of gems Bundler can install in parallel\. Defaults to the number of available processors\.
+.TP
+\fBlockfile\fR (\fBBUNDLE_LOCKFILE\fR)
+The path to the lockfile that bundler should use\. By default, Bundler adds \fB\.lock\fR to the end of the \fBgemfile\fR entry\. Can be set to \fBfalse\fR in the Gemfile to disable lockfile creation entirely (see gemfile(5))\.
+.TP
+\fBlockfile_checksums\fR (\fBBUNDLE_LOCKFILE_CHECKSUMS\fR)
+Whether Bundler should include a checksums section in new lockfiles, to protect from compromised gem sources\. Defaults to true\.
+.TP
+\fBno_install\fR (\fBBUNDLE_NO_INSTALL\fR)
+Whether \fBbundle package\fR should skip installing gems\.
+.TP
+\fBno_prune\fR (\fBBUNDLE_NO_PRUNE\fR)
+Whether Bundler should leave outdated gems unpruned when caching\.
+.TP
+\fBonly\fR (\fBBUNDLE_ONLY\fR)
+A space\-separated list of groups to install only gems of the specified groups\. Please check carefully if you want to install also gems without a group, because they get put inside \fBdefault\fR group\. For example \fBonly test:default\fR will install all gems specified in test group and without one\.
+.TP
+\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\. When not set, Bundler install by default to a \fB\.bundle\fR directory relative to repository root in Bundler 4, and to the default system path (\fBGem\.dir\fR) before Bundler 4\. That means that before Bundler 4, Bundler shares this location with Rubygems, and \fBgem install \|\.\|\.\|\.\fR will have gems installed in the same location and therefore, gems installed without \fBpath\fR set will show up by calling \fBgem list\fR\. This will not be the case in Bundler 4\.
+.TP
+\fBpath\.system\fR (\fBBUNDLE_PATH__SYSTEM\fR)
+Whether Bundler will install gems into the default system path (\fBGem\.dir\fR)\.
+.TP
+\fBplugins\fR (\fBBUNDLE_PLUGINS\fR)
+Enable Bundler's experimental plugin system\.
+.TP
+\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\.
+.TP
+\fBredirect\fR (\fBBUNDLE_REDIRECT\fR)
+The number of redirects allowed for network requests\. Defaults to \fB5\fR\.
+.TP
+\fBretry\fR (\fBBUNDLE_RETRY\fR)
+The number of times to retry failed network requests\. Defaults to \fB3\fR\.
+.TP
+\fBshebang\fR (\fBBUNDLE_SHEBANG\fR)
+The program name that should be invoked for generated binstubs\. Defaults to the ruby install name used to generate the binstub\.
+.TP
+\fBsilence_deprecations\fR (\fBBUNDLE_SILENCE_DEPRECATIONS\fR)
+Whether Bundler should silence deprecation warnings for behavior that will be changed in the next major version\.
+.TP
+\fBsilence_root_warning\fR (\fBBUNDLE_SILENCE_ROOT_WARNING\fR)
+Silence the warning Bundler prints when installing gems as root\.
+.TP
+\fBsimulate_version\fR (\fBBUNDLE_SIMULATE_VERSION\fR)
+The virtual version Bundler should use for activating feature flags\. Can be used to simulate all the new functionality that will be enabled in a future major version\.
+.TP
+\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\.
+.TP
+\fBssl_client_cert\fR (\fBBUNDLE_SSL_CLIENT_CERT\fR)
+Path to a designated file containing a X\.509 client certificate and key in PEM format\.
+.TP
+\fBssl_verify_mode\fR (\fBBUNDLE_SSL_VERIFY_MODE\fR)
+The SSL verification mode Bundler uses when making HTTPS requests\. Defaults to verify peer\.
+.TP
+\fBsystem_bindir\fR (\fBBUNDLE_SYSTEM_BINDIR\fR)
+The location where RubyGems installs binstubs\. Defaults to \fBGem\.bindir\fR\.
+.TP
+\fBtimeout\fR (\fBBUNDLE_TIMEOUT\fR)
+The seconds allowed before timing out for network requests\. Defaults to \fB10\fR\.
+.TP
+\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\.
+.TP
+\fBuser_agent\fR (\fBBUNDLE_USER_AGENT\fR)
+The custom user agent fragment Bundler includes in API requests\.
+.TP
+\fBverbose\fR (\fBBUNDLE_VERBOSE\fR)
+Whether Bundler should print verbose output\. Defaults to \fBfalse\fR, unless the \fB\-\-verbose\fR CLI flag is used\.
+.TP
+\fBversion\fR (\fBBUNDLE_VERSION\fR)
+The version of Bundler to use when running under Bundler environment\. Defaults to \fBlockfile\fR\. You can also specify \fBsystem\fR or \fBx\.y\.z\fR\. \fBlockfile\fR will use the Bundler version specified in the \fBGemfile\.lock\fR, \fBsystem\fR will use the system version of Bundler, and \fBx\.y\.z\fR will use the specified version of Bundler\.
+.TP
+\fBwith\fR (\fBBUNDLE_WITH\fR)
+A space\-separated or \fB:\fR\-separated list of groups whose gems bundler should install\.
+.TP
+\fBwithout\fR (\fBBUNDLE_WITHOUT\fR)
+A space\-separated or \fB:\fR\-separated list of groups whose gems bundler should not install\.
.SH "BUILD OPTIONS"
You can use \fBbundle config\fR to give Bundler the flags to pass to the gem installer every time bundler tries to install a particular gem\.
.P
@@ -84,125 +240,6 @@ bundle config set \-\-global build\.mysql \-\-with\-mysql\-config=/usr/local/mys
.IP "" 0
.P
After running this command, every time bundler needs to install the \fBmysql\fR gem, it will pass along the flags you specified\.
-.SH "CONFIGURATION KEYS"
-Configuration keys in bundler have two forms: the canonical form and the environment variable form\.
-.P
-For instance, passing the \fB\-\-without\fR flag to bundle install(1) \fIbundle\-install\.1\.html\fR prevents Bundler from installing certain groups specified in the Gemfile(5)\. Bundler persists this value in \fBapp/\.bundle/config\fR so that calls to \fBBundler\.setup\fR do not try to find gems from the \fBGemfile\fR that you didn't install\. Additionally, subsequent calls to bundle install(1) \fIbundle\-install\.1\.html\fR remember this setting and skip those groups\.
-.P
-The canonical form of this configuration is \fB"without"\fR\. To convert the canonical form to the environment variable form, capitalize it, and prepend \fBBUNDLE_\fR\. The environment variable form of \fB"without"\fR is \fBBUNDLE_WITHOUT\fR\.
-.P
-Any periods in the configuration keys must be replaced with two underscores when setting it via environment variables\. The configuration key \fBlocal\.rack\fR becomes the environment variable \fBBUNDLE_LOCAL__RACK\fR\.
-.SH "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) \fIbundle\-install\.1\.html\fR\.
-.IP "\(bu" 4
-\fBallow_offline_install\fR (\fBBUNDLE_ALLOW_OFFLINE_INSTALL\fR): Allow Bundler to use cached data when installing without network access\.
-.IP "\(bu" 4
-\fBauto_clean_without_path\fR (\fBBUNDLE_AUTO_CLEAN_WITHOUT_PATH\fR): Automatically run \fBbundle clean\fR after installing when an explicit \fBpath\fR has not been set and Bundler is not installing into the system gems\.
-.IP "\(bu" 4
-\fBauto_install\fR (\fBBUNDLE_AUTO_INSTALL\fR): Automatically run \fBbundle install\fR when gems are missing\.
-.IP "\(bu" 4
-\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\. 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\.
-.IP "\(bu" 4
-\fBcache_path\fR (\fBBUNDLE_CACHE_PATH\fR): The directory that bundler will place cached gems in when running \fBbundle package\fR, and that bundler will look in when installing gems\. Defaults to \fBvendor/cache\fR\.
-.IP "\(bu" 4
-\fBclean\fR (\fBBUNDLE_CLEAN\fR): Whether Bundler should run \fBbundle clean\fR automatically after \fBbundle install\fR\.
-.IP "\(bu" 4
-\fBconsole\fR (\fBBUNDLE_CONSOLE\fR): The console that \fBbundle console\fR starts\. Defaults to \fBirb\fR\.
-.IP "\(bu" 4
-\fBdefault_install_uses_path\fR (\fBBUNDLE_DEFAULT_INSTALL_USES_PATH\fR): Whether a \fBbundle install\fR without an explicit \fB\-\-path\fR argument defaults to installing gems in \fB\.bundle\fR\.
-.IP "\(bu" 4
-\fBdeployment\fR (\fBBUNDLE_DEPLOYMENT\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\.
-.IP "\(bu" 4
-\fBdisable_checksum_validation\fR (\fBBUNDLE_DISABLE_CHECKSUM_VALIDATION\fR): Allow installing gems even if they do not match the checksum provided by RubyGems\.
-.IP "\(bu" 4
-\fBdisable_exec_load\fR (\fBBUNDLE_DISABLE_EXEC_LOAD\fR): Stop Bundler from using \fBload\fR to launch an executable in\-process in \fBbundle exec\fR\.
-.IP "\(bu" 4
-\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_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\.
-.IP "\(bu" 4
-\fBdisable_version_check\fR (\fBBUNDLE_DISABLE_VERSION_CHECK\fR): Stop Bundler from checking if a newer Bundler version is available on rubygems\.org\.
-.IP "\(bu" 4
-\fBforce_ruby_platform\fR (\fBBUNDLE_FORCE_RUBY_PLATFORM\fR): Ignore the current machine's platform and install only \fBruby\fR platform gems\. As a result, gems with native extensions will be compiled from source\.
-.IP "\(bu" 4
-\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
-\fBgemfile\fR (\fBBUNDLE_GEMFILE\fR): The name of the file that bundler should use as the \fBGemfile\fR\. This location of this file also sets the root of the project, which is used to resolve relative paths in the \fBGemfile\fR, among other things\. By default, bundler will search up from the current working directory until it finds a \fBGemfile\fR\.
-.IP "\(bu" 4
-\fBglobal_gem_cache\fR (\fBBUNDLE_GLOBAL_GEM_CACHE\fR): Whether Bundler should cache all gems globally, rather than locally to the installing Ruby installation\.
-.IP "\(bu" 4
-\fBignore_funding_requests\fR (\fBBUNDLE_IGNORE_FUNDING_REQUESTS\fR): When set, no funding requests will be printed\.
-.IP "\(bu" 4
-\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\.
-.IP "\(bu" 4
-\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\.
-.IP "\(bu" 4
-\fBno_prune\fR (\fBBUNDLE_NO_PRUNE\fR): Whether Bundler should leave outdated gems unpruned when caching\.
-.IP "\(bu" 4
-\fBonly\fR (\fBBUNDLE_ONLY\fR): A space\-separated list of groups to install only gems of the specified groups\.
-.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
-\fBpath\.system\fR (\fBBUNDLE_PATH__SYSTEM\fR): Whether Bundler will install gems into the default system path (\fBGem\.dir\fR)\.
-.IP "\(bu" 4
-\fBpath_relative_to_cwd\fR (\fBBUNDLE_PATH_RELATIVE_TO_CWD\fR) Makes \fB\-\-path\fR relative to the CWD instead of the \fBGemfile\fR\.
-.IP "\(bu" 4
-\fBplugins\fR (\fBBUNDLE_PLUGINS\fR): Enable Bundler's experimental plugin system\.
-.IP "\(bu" 4
-\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\.
-.IP "\(bu" 4
-\fBredirect\fR (\fBBUNDLE_REDIRECT\fR): The number of redirects allowed for network requests\. Defaults to \fB5\fR\.
-.IP "\(bu" 4
-\fBretry\fR (\fBBUNDLE_RETRY\fR): The number of times to retry failed network requests\. Defaults to \fB3\fR\.
-.IP "\(bu" 4
-\fBsetup_makes_kernel_gem_public\fR (\fBBUNDLE_SETUP_MAKES_KERNEL_GEM_PUBLIC\fR): Have \fBBundler\.setup\fR make the \fBKernel#gem\fR method public, even though RubyGems declares it as private\.
-.IP "\(bu" 4
-\fBshebang\fR (\fBBUNDLE_SHEBANG\fR): The program name that should be invoked for generated binstubs\. Defaults to the ruby install name used to generate the binstub\.
-.IP "\(bu" 4
-\fBsilence_deprecations\fR (\fBBUNDLE_SILENCE_DEPRECATIONS\fR): Whether Bundler should silence deprecation warnings for behavior that will be changed in the next major version\.
-.IP "\(bu" 4
-\fBsilence_root_warning\fR (\fBBUNDLE_SILENCE_ROOT_WARNING\fR): Silence the warning Bundler prints when installing gems as root\.
-.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
-\fBssl_client_cert\fR (\fBBUNDLE_SSL_CLIENT_CERT\fR): Path to a designated file containing a X\.509 client certificate and key in PEM format\.
-.IP "\(bu" 4
-\fBssl_verify_mode\fR (\fBBUNDLE_SSL_VERIFY_MODE\fR): The SSL verification mode Bundler uses when making HTTPS requests\. Defaults to verify peer\.
-.IP "\(bu" 4
-\fBsystem_bindir\fR (\fBBUNDLE_SYSTEM_BINDIR\fR): The location where RubyGems installs binstubs\. Defaults to \fBGem\.bindir\fR\.
-.IP "\(bu" 4
-\fBtimeout\fR (\fBBUNDLE_TIMEOUT\fR): The seconds allowed before timing out for network requests\. Defaults to \fB10\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\.
-.IP "\(bu" 4
-\fBuser_agent\fR (\fBBUNDLE_USER_AGENT\fR): The custom user agent fragment Bundler includes in API requests\.
-.IP "\(bu" 4
-\fBversion\fR (\fBBUNDLE_VERSION\fR): The version of Bundler to use when running under Bundler environment\. Defaults to \fBlockfile\fR\. You can also specify \fBsystem\fR or \fBx\.y\.z\fR\. \fBlockfile\fR will use the Bundler version specified in the \fBGemfile\.lock\fR, \fBsystem\fR will use the system version of Bundler, and \fBx\.y\.z\fR will use the specified version of Bundler\.
-.IP "\(bu" 4
-\fBwith\fR (\fBBUNDLE_WITH\fR): A \fB:\fR\-separated list of groups whose gems bundler should install\.
-.IP "\(bu" 4
-\fBwithout\fR (\fBBUNDLE_WITHOUT\fR): A \fB:\fR\-separated list of groups whose gems bundler should not install\.
-.IP "" 0
-.P
-In general, you should set these settings per\-application by using the applicable flag to the bundle install(1) \fIbundle\-install\.1\.html\fR or bundle cache(1) \fIbundle\-cache\.1\.html\fR command\.
-.P
-You can set them globally either via environment variables or \fBbundle config\fR, whichever is preferable for your setup\. If you use both, environment variables will take preference over global settings\.
.SH "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:
.IP "" 4
@@ -278,7 +315,7 @@ export BUNDLE_GEMS__LONGEROUS__COM="claudette:s00pers3krit"
For gems with a git source with HTTP(S) URL you can specify credentials like so:
.IP "" 4
.nf
-bundle config set \-\-global https://github\.com/rubygems/rubygems\.git username:password
+bundle config set \-\-global https://github\.com/ruby/rubygems\.git username:password
.fi
.IP "" 0
.P
diff --git a/lib/bundler/man/bundle-config.1.ronn b/lib/bundler/man/bundle-config.1.ronn
index 1a0ec2a5dc..7c34f1d1af 100644
--- a/lib/bundler/man/bundle-config.1.ronn
+++ b/lib/bundler/man/bundle-config.1.ronn
@@ -3,10 +3,10 @@ bundle-config(1) -- Set bundler configuration options
## SYNOPSIS
-`bundle config` list<br>
-`bundle config` [get] NAME<br>
-`bundle config` [set] NAME VALUE<br>
-`bundle config` unset NAME
+`bundle config` [list]<br>
+`bundle config` [get [--local|--global]] NAME<br>
+`bundle config` [set [--local|--global]] NAME VALUE<br>
+`bundle config` unset [--local|--global] NAME
## DESCRIPTION
@@ -19,98 +19,67 @@ Bundler loads configuration settings in this order:
3. Global config (`~/.bundle/config`)
4. Bundler default config
-Executing `bundle config list` will print a list of all bundler
-configuration for the current bundle, and where that configuration
-was set.
-
-Executing `bundle config get <name>` will print the value of that configuration
-setting, and where it was set.
-
-Executing `bundle config set <name> <value>` defaults to setting `local`
-configuration if executing from within a local application, otherwise it will
-set `global` configuration. See `--local` and `--global` options below.
-
-Executing `bundle config set --local <name> <value>` will set that configuration
-in the directory for the local application. The configuration will be stored in
-`<project_root>/.bundle/config`. If `BUNDLE_APP_CONFIG` is set, the configuration
-will be stored in `$BUNDLE_APP_CONFIG/config`.
-
-Executing `bundle config set --global <name> <value>` 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 unset <name>` will delete the configuration in both
-local and global sources.
-
-Executing `bundle config unset --global <name>` will delete the configuration
-only from the user configuration.
-
-Executing `bundle config unset --local <name>` will delete the configuration
-only from the local application.
-
-Executing bundle with the `BUNDLE_IGNORE_CONFIG` environment variable set will
+Executing `bundle` with the `BUNDLE_IGNORE_CONFIG` environment variable set will
cause it to ignore all configuration.
-## REMEMBERING OPTIONS
+## SUB-COMMANDS
-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`).
+### list (default command)
-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`).
+Executing `bundle config list` will print a list of all bundler
+configuration for the current bundle, and where that configuration
+was set.
-The options that can be configured are:
+### get
-* `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.
+Executing `bundle config get <name>` will print the value of that configuration
+setting, and all locations where it was set.
-* `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.
+**OPTIONS**
-* `only`:
- A space-separated list of groups to install only gems of the specified groups.
+* `--local`:
+ Get configuration from configuration file for the local application, namely,
+ `<project_root>/.bundle/config`, or `$BUNDLE_APP_CONFIG/config` if
+ `BUNDLE_APP_CONFIG` is set.
-* `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.
+* `--global`:
+ Get configuration from configuration file global to all bundles executed as
+ the current user, namely, from `~/.bundle/config`.
-* `without`:
- A space-separated list of groups referencing gems to skip during installation.
+### set
-* `with`:
- A space-separated list of **optional** groups referencing gems to include during installation.
+Executing `bundle config set <name> <value>` defaults to setting `local`
+configuration if executing from within a local application, otherwise it will
+set `global` configuration.
-## BUILD OPTIONS
+**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.
+* `--local`:
+ Executing `bundle config set --local <name> <value>` will set that configuration
+ in the directory for the local application. The configuration will be stored in
+ `<project_root>/.bundle/config`. If `BUNDLE_APP_CONFIG` is set, the configuration
+ will be stored in `$BUNDLE_APP_CONFIG/config`.
-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.
+* `--global`:
+ Executing `bundle config set --global <name> <value>` 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.
- gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config
+### unset
-Since the specific location of that executable can change from machine
-to machine, you can specify these flags on a per-machine basis.
+Executing `bundle config unset <name>` will delete the configuration in both
+local and global sources.
- bundle config set --global build.mysql --with-mysql-config=/usr/local/mysql/bin/mysql_config
+**OPTIONS**
-After running this command, every time bundler needs to install the
-`mysql` gem, it will pass along the flags you specified.
+* `--local`:
+ Executing `bundle config unset --local <name>` will delete the configuration
+ only from the local application.
+
+* `--global`:
+ Executing `bundle config unset --global <name>` will delete the configuration
+ only from the user configuration.
## CONFIGURATION KEYS
@@ -137,19 +106,20 @@ the environment variable `BUNDLE_LOCAL__RACK`.
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_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`.
+ If configured, `bundle binstubs` will install executables from gems in the
+ bundle to the specified directory. Otherwise it will create them in a `bin`
+ directory relative to the Gemfile directory. 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, `bundle binstubs` will create a `bin/rails` executable
+ that ensures that all referred dependencies will be resolved using the
+ bundled gems.
* `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.
+ before bundler 4, but will be the default on bundler 4.
* `cache_all_platforms` (`BUNDLE_CACHE_ALL_PLATFORMS`):
Cache gems for all platforms.
* `cache_path` (`BUNDLE_CACHE_PATH`):
@@ -158,15 +128,16 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
Defaults to `vendor/cache`.
* `clean` (`BUNDLE_CLEAN`):
Whether Bundler should run `bundle clean` automatically after
- `bundle install`.
+ `bundle install`. Defaults to `true` in Bundler 4, as long as `path` is not
+ explicitly configured.
* `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`.
+* `default_cli_command` (`BUNDLE_DEFAULT_CLI_COMMAND`):
+ The command that running `bundle` without arguments should run. Defaults to
+ `cli_help` since Bundler 4, but can also be `install` which was the previous
+ default.
* `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.
+ Equivalent to setting `frozen` to `true` and `path` to `vendor/bundle`.
* `disable_checksum_validation` (`BUNDLE_DISABLE_CHECKSUM_VALIDATION`):
Allow installing gems even if they do not match the checksum provided by
RubyGems.
@@ -188,12 +159,13 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
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.
+ Disallow any automatic changes to `Gemfile.lock`. Bundler commands will
+ be blocked unless the lockfile can be installed exactly as written.
+ Usually this will happen when changing the `Gemfile` manually and forgetting
+ to update the lockfile through `bundle lock` or `bundle install`.
* `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
+ Sets a GitHub username or organization to be used in the `README` and `.gemspec` files
+ 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`
@@ -205,8 +177,8 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
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.
+ Whether Bundler should cache all gems and compiled extensions globally,
+ rather than locally to the configured installation path.
* `ignore_funding_requests` (`BUNDLE_IGNORE_FUNDING_REQUESTS`):
When set, no funding requests will be printed.
* `ignore_messages` (`BUNDLE_IGNORE_MESSAGES`):
@@ -217,34 +189,41 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
* `jobs` (`BUNDLE_JOBS`):
The number of gems Bundler can install in parallel. Defaults to the number of
available processors.
+* `lockfile` (`BUNDLE_LOCKFILE`):
+ The path to the lockfile that bundler should use. By default, Bundler adds
+ `.lock` to the end of the `gemfile` entry. Can be set to `false` in the
+ Gemfile to disable lockfile creation entirely (see gemfile(5)).
+* `lockfile_checksums` (`BUNDLE_LOCKFILE_CHECKSUMS`):
+ Whether Bundler should include a checksums section in new lockfiles, to protect from compromised gem sources. Defaults to true.
* `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` (`BUNDLE_ONLY`):
A space-separated list of groups to install only gems of the specified groups.
+ Please check carefully if you want to install also gems without a group, because
+ they get put inside `default` group. For example `only test:default` will install
+ all gems specified in test group and without one.
* `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.
+ will be installed by `bundle install`. When not set, Bundler install by
+ default to a `.bundle` directory relative to repository root in Bundler 4,
+ and to the default system path (`Gem.dir`) before Bundler 4. That means that
+ before Bundler 4, Bundler shares this location with Rubygems, and `gem
+ install ...` will have gems installed in the same location and therefore,
+ gems installed without `path` set will show up by calling `gem list`. This
+ will not be the case in Bundler 4.
* `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.
@@ -253,6 +232,10 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
be changed in the next major version.
* `silence_root_warning` (`BUNDLE_SILENCE_ROOT_WARNING`):
Silence the warning Bundler prints when installing gems as root.
+* `simulate_version` (`BUNDLE_SIMULATE_VERSION`):
+ The virtual version Bundler should use for activating feature flags. Can be
+ used to simulate all the new functionality that will be enabled in a future
+ major version.
* `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.
@@ -271,6 +254,9 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
and disallow passing no options to `bundle update`.
* `user_agent` (`BUNDLE_USER_AGENT`):
The custom user agent fragment Bundler includes in API requests.
+* `verbose` (`BUNDLE_VERBOSE`):
+ Whether Bundler should print verbose output. Defaults to `false`, unless the
+ `--verbose` CLI flag is used.
* `version` (`BUNDLE_VERSION`):
The version of Bundler to use when running under Bundler environment.
Defaults to `lockfile`. You can also specify `system` or `x.y.z`.
@@ -278,16 +264,28 @@ learn more about their operation in [bundle install(1)](bundle-install.1.html).
`system` will use the system version of Bundler, and `x.y.z` will use
the specified version of Bundler.
* `with` (`BUNDLE_WITH`):
- A `:`-separated list of groups whose gems bundler should install.
+ A space-separated or `:`-separated list of groups whose gems bundler should install.
* `without` (`BUNDLE_WITHOUT`):
- A `:`-separated list of groups whose gems bundler should not install.
+ A space-separated or `:`-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 cache(1)](bundle-cache.1.html) command.
+## 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.
-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.
+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.
## LOCAL GIT REPOS
@@ -366,7 +364,7 @@ Or you can set the credentials as an environment variable like this:
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
+ bundle config set --global https://github.com/ruby/rubygems.git username:password
Or you can set the credentials as an environment variable like so:
diff --git a/lib/bundler/man/bundle-console.1 b/lib/bundler/man/bundle-console.1
index dca18ec43d..5ab15668be 100644
--- a/lib/bundler/man/bundle-console.1
+++ b/lib/bundler/man/bundle-console.1
@@ -1,8 +1,8 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-CONSOLE" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-CONSOLE" "1" "September 2025" ""
.SH "NAME"
-\fBbundle\-console\fR \- Deprecated way to open an IRB session with the bundle pre\-loaded
+\fBbundle\-console\fR \- Open an IRB session with the bundle pre\-loaded
.SH "SYNOPSIS"
\fBbundle console\fR [GROUP]
.SH "DESCRIPTION"
@@ -29,7 +29,5 @@ $ bundle console
Resolving dependencies\|\.\|\.\|\.
[1] pry(main)>
.fi
-.SH "NOTES"
-This command was deprecated in Bundler 2\.1 and will be removed in 3\.0\. Use \fBbin/console\fR script, which can be generated by \fBbundle gem <NAME>\fR\.
.SH "SEE ALSO"
Gemfile(5) \fIhttps://bundler\.io/man/gemfile\.5\.html\fR
diff --git a/lib/bundler/man/bundle-console.1.ronn b/lib/bundler/man/bundle-console.1.ronn
index f9096d386a..ed842ae1c3 100644
--- a/lib/bundler/man/bundle-console.1.ronn
+++ b/lib/bundler/man/bundle-console.1.ronn
@@ -1,5 +1,5 @@
-bundle-console(1) -- Deprecated way to open an IRB session with the bundle pre-loaded
-=====================================================================================
+bundle-console(1) -- Open an IRB session with the bundle pre-loaded
+===================================================================
## SYNOPSIS
@@ -34,11 +34,6 @@ the shell from the following:
Resolving dependencies...
[1] pry(main)>
-## NOTES
-
-This command was deprecated in Bundler 2.1 and will be removed in 3.0.
-Use `bin/console` script, which can be generated by `bundle gem <NAME>`.
-
## SEE ALSO
[Gemfile(5)](https://bundler.io/man/gemfile.5.html)
diff --git a/lib/bundler/man/bundle-doctor.1 b/lib/bundler/man/bundle-doctor.1
index 6489cc07f7..a0329dfc48 100644
--- a/lib/bundler/man/bundle-doctor.1
+++ b/lib/bundler/man/bundle-doctor.1
@@ -1,14 +1,21 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-DOCTOR" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-DOCTOR" "1" "September 2025" ""
.SH "NAME"
\fBbundle\-doctor\fR \- Checks the bundle for common problems
.SH "SYNOPSIS"
-\fBbundle doctor\fR [\-\-quiet] [\-\-gemfile=GEMFILE]
+\fBbundle doctor [diagnose]\fR [\-\-quiet] [\-\-gemfile=GEMFILE] [\-\-ssl]
+.br
+\fBbundle doctor ssl\fR [\-\-host=HOST] [\-\-tls\-version=TLS\-VERSION] [\-\-verify\-mode=VERIFY\-MODE]
+.br
+\fBbundle doctor\fR help [COMMAND]
.SH "DESCRIPTION"
+You can diagnose common Bundler problems with this command such as checking gem environment or SSL/TLS issue\.
+.SH "SUB\-COMMANDS"
+.SS "diagnose (default command)"
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\.
.P
-Examples of common problems caught by bundle\-doctor include:
+Examples of common problems caught include:
.IP "\(bu" 4
Invalid Bundler settings
.IP "\(bu" 4
@@ -20,11 +27,43 @@ Uninstalled gems
.IP "\(bu" 4
Missing dependencies
.IP "" 0
-.SH "OPTIONS"
+.P
+\fBOPTIONS\fR
.TP
\fB\-\-quiet\fR
Only output warnings and errors\.
.TP
-\fB\-\-gemfile=<gemfile>\fR
+\fB\-\-gemfile=GEMFILE\fR
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 \fBGemfile\.lock\fR and \fBvendor/cache\fR relative to this location\.
+.TP
+\fB\-\-ssl\fR
+Diagnose common SSL problems when connecting to https://rubygems\.org\.
+.IP
+This flag runs the \fBbundle doctor ssl\fR subcommand with default values underneath\.
+.SS "ssl"
+If you've experienced issues related to SSL certificates and/or TLS versions while connecting to https://rubygems\.org, this command can help troubleshoot common problems\. The diagnostic will perform a few checks such as:
+.IP "\(bu" 4
+Verify the Ruby OpenSSL version installed on your system\.
+.IP "\(bu" 4
+Check the OpenSSL library version used for compilation\.
+.IP "\(bu" 4
+Ensure CA certificates are correctly setup on your machine\.
+.IP "\(bu" 4
+Open a TLS connection and verify the outcome\.
+.IP "" 0
+.P
+\fBOPTIONS\fR
+.TP
+\fB\-\-host=HOST\fR
+Perform the diagnostic on HOST\. Defaults to \fBrubygems\.org\fR\.
+.TP
+\fB\-\-tls\-version=TLS\-VERSION\fR
+Specify the TLS version when opening the connection to HOST\.
+.IP
+Accepted values are: \fB1\.1\fR or \fB1\.2\fR\.
+.TP
+\fB\-\-verify\-mode=VERIFY\-MODE\fR
+Specify the TLS verify mode when opening the connection to HOST\. Defaults to \fBSSL_VERIFY_PEER\fR\.
+.IP
+Accepted values are: \fBCLIENT_ONCE\fR, \fBFAIL_IF_NO_PEER_CERT\fR, \fBNONE\fR, \fBPEER\fR\.
diff --git a/lib/bundler/man/bundle-doctor.1.ronn b/lib/bundler/man/bundle-doctor.1.ronn
index 271ee800ad..7495099ff5 100644
--- a/lib/bundler/man/bundle-doctor.1.ronn
+++ b/lib/bundler/man/bundle-doctor.1.ronn
@@ -3,16 +3,27 @@ bundle-doctor(1) -- Checks the bundle for common problems
## SYNOPSIS
-`bundle doctor` [--quiet]
- [--gemfile=GEMFILE]
+`bundle doctor [diagnose]` [--quiet]
+ [--gemfile=GEMFILE]
+ [--ssl]<br>
+`bundle doctor ssl` [--host=HOST]
+ [--tls-version=TLS-VERSION]
+ [--verify-mode=VERIFY-MODE]<br>
+`bundle doctor` help [COMMAND]
## DESCRIPTION
+You can diagnose common Bundler problems with this command such as checking gem environment or SSL/TLS issue.
+
+## SUB-COMMANDS
+
+### diagnose (default command)
+
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:
+Examples of common problems caught include:
* Invalid Bundler settings
* Mismatched Ruby versions
@@ -20,14 +31,47 @@ Examples of common problems caught by bundle-doctor include:
* Uninstalled gems
* Missing dependencies
-## OPTIONS
+**OPTIONS**
* `--quiet`:
Only output warnings and errors.
-* `--gemfile=<gemfile>`:
+* `--gemfile=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.
+
+* `--ssl`:
+ Diagnose common SSL problems when connecting to https://rubygems.org.
+
+ This flag runs the `bundle doctor ssl` subcommand with default values
+ underneath.
+
+### ssl
+
+If you've experienced issues related to SSL certificates and/or TLS versions while connecting
+to https://rubygems.org, this command can help troubleshoot common problems.
+The diagnostic will perform a few checks such as:
+
+* Verify the Ruby OpenSSL version installed on your system.
+* Check the OpenSSL library version used for compilation.
+* Ensure CA certificates are correctly setup on your machine.
+* Open a TLS connection and verify the outcome.
+
+**OPTIONS**
+
+* `--host=HOST`:
+ Perform the diagnostic on HOST. Defaults to `rubygems.org`.
+
+* `--tls-version=TLS-VERSION`:
+ Specify the TLS version when opening the connection to HOST.
+
+ Accepted values are: `1.1` or `1.2`.
+
+* `--verify-mode=VERIFY-MODE`:
+ Specify the TLS verify mode when opening the connection to HOST.
+ Defaults to `SSL_VERIFY_PEER`.
+
+ Accepted values are: `CLIENT_ONCE`, `FAIL_IF_NO_PEER_CERT`, `NONE`, `PEER`.
diff --git a/lib/bundler/man/bundle-env.1 b/lib/bundler/man/bundle-env.1
new file mode 100644
index 0000000000..eee3ca05d0
--- /dev/null
+++ b/lib/bundler/man/bundle-env.1
@@ -0,0 +1,9 @@
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-ENV" "1" "September 2025" ""
+.SH "NAME"
+\fBbundle\-env\fR \- Print information about the environment Bundler is running under
+.SH "SYNOPSIS"
+\fBbundle env\fR
+.SH "DESCRIPTION"
+Prints information about the environment Bundler is running under\.
diff --git a/lib/bundler/man/bundle-env.1.ronn b/lib/bundler/man/bundle-env.1.ronn
new file mode 100644
index 0000000000..c2df9c29c2
--- /dev/null
+++ b/lib/bundler/man/bundle-env.1.ronn
@@ -0,0 +1,10 @@
+bundle-env(1) -- Print information about the environment Bundler is running under
+=================================================================================
+
+## SYNOPSIS
+
+`bundle env`
+
+## DESCRIPTION
+
+Prints information about the environment Bundler is running under.
diff --git a/lib/bundler/man/bundle-exec.1 b/lib/bundler/man/bundle-exec.1
index 1548d29670..24c84889b5 100644
--- a/lib/bundler/man/bundle-exec.1
+++ b/lib/bundler/man/bundle-exec.1
@@ -1,10 +1,10 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-EXEC" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-EXEC" "1" "September 2025" ""
.SH "NAME"
\fBbundle\-exec\fR \- Execute a command in the context of the bundle
.SH "SYNOPSIS"
-\fBbundle exec\fR [\-\-keep\-file\-descriptors] \fIcommand\fR
+\fBbundle exec\fR [\-\-gemfile=GEMFILE] \fIcommand\fR
.SH "DESCRIPTION"
This command executes the command, making all gems specified in the [\fBGemfile(5)\fR][Gemfile(5)] available to \fBrequire\fR in Ruby programs\.
.P
@@ -13,8 +13,8 @@ Essentially, if you would normally have run something like \fBrspec spec/my_spec
Note that \fBbundle exec\fR does not require that an executable is available on your shell's \fB$PATH\fR\.
.SH "OPTIONS"
.TP
-\fB\-\-keep\-file\-descriptors\fR
-Passes all file descriptors to the new processes\. Default is true from bundler version 2\.2\.26\. Setting it to false is now deprecated\.
+\fB\-\-gemfile=GEMFILE\fR
+Use the specified gemfile instead of [\fBGemfile(5)\fR][Gemfile(5)]\.
.SH "BUNDLE INSTALL \-\-BINSTUBS"
If you use the \fB\-\-binstubs\fR flag in bundle install(1) \fIbundle\-install\.1\.html\fR, Bundler will automatically create a directory (which defaults to \fBapp_root/bin\fR) containing all of the executables available from gems in the bundle\.
.P
@@ -71,8 +71,8 @@ end
Bundler provides convenience helpers that wrap \fBsystem\fR and \fBexec\fR, and they can be used like this:
.IP "" 4
.nf
-Bundler\.clean_system('brew install wget')
-Bundler\.clean_exec('brew install wget')
+Bundler\.unbundled_system('brew install wget')
+Bundler\.unbundled_exec('brew install wget')
.fi
.IP "" 0
.SH "RUBYGEMS PLUGINS"
diff --git a/lib/bundler/man/bundle-exec.1.ronn b/lib/bundler/man/bundle-exec.1.ronn
index 9d5b559f26..e51a66a084 100644
--- a/lib/bundler/man/bundle-exec.1.ronn
+++ b/lib/bundler/man/bundle-exec.1.ronn
@@ -3,7 +3,7 @@ bundle-exec(1) -- Execute a command in the context of the bundle
## SYNOPSIS
-`bundle exec` [--keep-file-descriptors] <command>
+`bundle exec` [--gemfile=GEMFILE] <command>
## DESCRIPTION
@@ -20,9 +20,8 @@ available on your shell's `$PATH`.
## OPTIONS
-* `--keep-file-descriptors`:
- Passes all file descriptors to the new processes. Default is true from
- bundler version 2.2.26. Setting it to false is now deprecated.
+* `--gemfile=GEMFILE`:
+ Use the specified gemfile instead of [`Gemfile(5)`][Gemfile(5)].
## BUNDLE INSTALL --BINSTUBS
@@ -105,8 +104,8 @@ need to use `with_unbundled_env`.
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')
+ Bundler.unbundled_system('brew install wget')
+ Bundler.unbundled_exec('brew install wget')
## RUBYGEMS PLUGINS
diff --git a/lib/bundler/man/bundle-fund.1 b/lib/bundler/man/bundle-fund.1
new file mode 100644
index 0000000000..fe24a25ca1
--- /dev/null
+++ b/lib/bundler/man/bundle-fund.1
@@ -0,0 +1,22 @@
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-FUND" "1" "September 2025" ""
+.SH "NAME"
+\fBbundle\-fund\fR \- Lists information about gems seeking funding assistance
+.SH "SYNOPSIS"
+\fBbundle fund\fR [\fIOPTIONS\fR]
+.SH "DESCRIPTION"
+\fBbundle fund\fR lists information about gems seeking funding assistance\.
+.SH "OPTIONS"
+.TP
+\fB\-\-group=<list>\fR, \fB\-g=<list>\fR
+Fetch funding information for a specific group\.
+.SH "EXAMPLES"
+.nf
+# Lists funding information for all gems
+bundle fund
+
+# Lists funding information for a specific group
+bundle fund \-\-group=security
+.fi
+
diff --git a/lib/bundler/man/bundle-fund.1.ronn b/lib/bundler/man/bundle-fund.1.ronn
new file mode 100644
index 0000000000..faf8b9c4a7
--- /dev/null
+++ b/lib/bundler/man/bundle-fund.1.ronn
@@ -0,0 +1,25 @@
+bundle-fund(1) -- Lists information about gems seeking funding assistance
+=========================================================================
+
+## SYNOPSIS
+
+`bundle fund` [*OPTIONS*]
+
+## DESCRIPTION
+
+**bundle fund** lists information about gems seeking funding assistance.
+
+## OPTIONS
+
+* `--group=<list>`, `-g=<list>`:
+ Fetch funding information for a specific group.
+
+## EXAMPLES
+
+```
+# Lists funding information for all gems
+bundle fund
+
+# Lists funding information for a specific group
+bundle fund --group=security
+```
diff --git a/lib/bundler/man/bundle-gem.1 b/lib/bundler/man/bundle-gem.1
index 5df7b0ef2f..85c0f57674 100644
--- a/lib/bundler/man/bundle-gem.1
+++ b/lib/bundler/man/bundle-gem.1
@@ -1,6 +1,6 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-GEM" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-GEM" "1" "September 2025" ""
.SH "NAME"
\fBbundle\-gem\fR \- Generate a project skeleton for creating a rubygem
.SH "SYNOPSIS"
@@ -19,49 +19,87 @@ The generated project skeleton can be customized with OPTIONS, as explained belo
\fBgem\.test\fR
.IP "" 0
.SH "OPTIONS"
-.IP "\(bu" 4
-\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\.
-.IP "\(bu" 4
-\fB\-\-no\-exe\fR: Do not create a binary (overrides \fB\-\-exe\fR specified in the global config)\.
-.IP "\(bu" 4
-\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\.
-.IP "\(bu" 4
-\fB\-\-no\-coc\fR: Do not create a \fBCODE_OF_CONDUCT\.md\fR (overrides \fB\-\-coc\fR specified in the global config)\.
-.IP "\(bu" 4
-\fB\-\-ext=c\fR, \fB\-\-ext=rust\fR Add boilerplate for C or Rust (currently magnus \fIhttps://docs\.rs/magnus\fR based) extension code to the generated project\. This behavior is disabled by default\.
-.IP "\(bu" 4
-\fB\-\-no\-ext\fR: Do not add extension code (overrides \fB\-\-ext\fR specified in the global config)\.
-.IP "\(bu" 4
-\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\.
-.IP "\(bu" 4
-\fB\-\-no\-mit\fR: Do not create a \fBLICENSE\.txt\fR (overrides \fB\-\-mit\fR specified in the global config)\.
-.IP "\(bu" 4
-\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:
+.TP
+\fB\-\-exe\fR, \fB\-\-bin\fR, \fB\-b\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\-\-changelog\fR
+Add a \fBCHANGELOG\.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\. Update the default with \fBbundle config set \-\-global gem\.changelog <true|false>\fR\.
+.TP
+\fB\-\-no\-changelog\fR
+Do not create a \fBCHANGELOG\.md\fR (overrides \fB\-\-changelog\fR specified in the global config)\.
+.TP
+\fB\-\-ext=c\fR, \fB\-\-ext=go\fR, \fB\-\-ext=rust\fR
+Add boilerplate for C, Go (currently go\-gem\-wrapper \fIhttps://github\.com/ruby\-go\-gem/go\-gem\-wrapper\fR based) or Rust (currently magnus \fIhttps://docs\.rs/magnus\fR based) extension code to the generated project\. This behavior is disabled by default\.
+.TP
+\fB\-\-no\-ext\fR
+Do not add extension code (overrides \fB\-\-ext\fR specified in the global config)\.
+.TP
+\fB\-\-git\fR
+Initialize a git repo inside your library\.
+.TP
+\fB\-\-github\-username=GITHUB_USERNAME\fR
+Fill in GitHub username on README so that you don't have to do it manually\. Set a default with \fBbundle config set \-\-global gem\.github_username <your_username>\fR\.
+.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\.
-.IP "\(bu" 4
-\fB\-\-ci\fR, \fB\-\-ci=github\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, \fBgitlab\fR and \fBcircle\fR\. A configuration file will be generated in the project directory\. Given no option is specified:
+.TP
+\fB\-\-no\-test\fR
+Do not use a test framework (overrides \fB\-\-test\fR specified in the global config)\.
+.TP
+\fB\-\-ci\fR, \fB\-\-ci=circle\fR, \fB\-\-ci=github\fR, \fB\-\-ci=gitlab\fR
+Specify the continuous integration service that Bundler should use when generating the project\. Acceptable values are \fBgithub\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\.
-.IP "\(bu" 4
-\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:
+.TP
+\fB\-\-no\-ci\fR
+Do not use a continuous integration service (overrides \fB\-\-ci\fR specified in the global config)\.
+.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\.
-.IP "\(bu" 4
-\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\.
-.IP "" 0
+.TP
+\fB\-\-no\-linter\fR
+Do not add a linter (overrides \fB\-\-linter\fR specified in the global config)\.
+.TP
+\fB\-\-edit=EDIT\fR, \fB\-e=EDIT\fR
+Open the resulting GEM_NAME\.gemspec in EDIT, or the default editor if not specified\. The default is \fB$BUNDLER_EDITOR\fR, \fB$VISUAL\fR, or \fB$EDITOR\fR\.
+.TP
+\fB\-\-bundle\fR
+Run \fBbundle install\fR after creating the gem\.
+.TP
+\fB\-\-no\-bundle\fR
+Do not run \fBbundle install\fR after creating the gem\.
.SH "SEE ALSO"
.IP "\(bu" 4
bundle config(1) \fIbundle\-config\.1\.html\fR
diff --git a/lib/bundler/man/bundle-gem.1.ronn b/lib/bundler/man/bundle-gem.1.ronn
index 46fa2f179f..488c8113e4 100644
--- a/lib/bundler/man/bundle-gem.1.ronn
+++ b/lib/bundler/man/bundle-gem.1.ronn
@@ -1,5 +1,5 @@
bundle-gem(1) -- Generate a project skeleton for creating a rubygem
-====================================================================
+===================================================================
## SYNOPSIS
@@ -24,7 +24,7 @@ configuration file using the following names:
## OPTIONS
-* `--exe` or `-b` or `--bin`:
+* `--exe`, `--bin`, `-b`:
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.
@@ -41,14 +41,30 @@ configuration file using the following names:
Do not create a `CODE_OF_CONDUCT.md` (overrides `--coc` specified in the
global config).
-* `--ext=c`, `--ext=rust`
- Add boilerplate for C or Rust (currently [magnus](https://docs.rs/magnus) based) extension code to the generated project. This behavior
+* `--changelog`:
+ Add a `CHANGELOG.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.
+ Update the default with `bundle config set --global gem.changelog <true|false>`.
+
+* `--no-changelog`:
+ Do not create a `CHANGELOG.md` (overrides `--changelog` specified in the
+ global config).
+
+* `--ext=c`, `--ext=go`, `--ext=rust`:
+ Add boilerplate for C, Go (currently [go-gem-wrapper](https://github.com/ruby-go-gem/go-gem-wrapper) based) or Rust (currently [magnus](https://docs.rs/magnus) based) extension code to the generated project. This behavior
is disabled by default.
* `--no-ext`:
Do not add extension code (overrides `--ext` specified in the global
config).
+* `--git`:
+ Initialize a git repo inside your library.
+
+* `--github-username=GITHUB_USERNAME`:
+ 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 <your_username>`.
+
* `--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
@@ -76,7 +92,11 @@ configuration file using the following names:
the answer will be saved in Bundler's global config for future `bundle gem`
use.
-* `--ci`, `--ci=github`, `--ci=gitlab`, `--ci=circle`:
+* `--no-test`:
+ Do not use a test framework (overrides `--test` specified in the global
+ config).
+
+* `--ci`, `--ci=circle`, `--ci=github`, `--ci=gitlab`:
Specify the continuous integration service that Bundler should use when
generating the project. Acceptable values are `github`, `gitlab`
and `circle`. A configuration file will be generated in the project directory.
@@ -92,6 +112,10 @@ configuration file using the following names:
the answer will be saved in Bundler's global config for future `bundle gem`
use.
+* `--no-ci`:
+ Do not use a continuous integration service (overrides `--ci` specified in
+ the global config).
+
* `--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
@@ -108,10 +132,19 @@ configuration file using the following names:
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
+* `--no-linter`:
+ Do not add a linter (overrides `--linter` specified in the global config).
+
+* `--edit=EDIT`, `-e=EDIT`:
+ Open the resulting GEM_NAME.gemspec in EDIT, or the default editor if not
specified. The default is `$BUNDLER_EDITOR`, `$VISUAL`, or `$EDITOR`.
+* `--bundle`:
+ Run `bundle install` after creating the gem.
+
+* `--no-bundle`:
+ Do not run `bundle install` after creating the gem.
+
## SEE ALSO
* [bundle config(1)](bundle-config.1.html)
diff --git a/lib/bundler/man/bundle-help.1 b/lib/bundler/man/bundle-help.1
index a3e7c7770d..05fd5a7c48 100644
--- a/lib/bundler/man/bundle-help.1
+++ b/lib/bundler/man/bundle-help.1
@@ -1,6 +1,6 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-HELP" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-HELP" "1" "September 2025" ""
.SH "NAME"
\fBbundle\-help\fR \- Displays detailed help for each subcommand
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-info.1 b/lib/bundler/man/bundle-info.1
index a3d7ff0988..96c7d876f6 100644
--- a/lib/bundler/man/bundle-info.1
+++ b/lib/bundler/man/bundle-info.1
@@ -1,14 +1,17 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-INFO" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-INFO" "1" "September 2025" ""
.SH "NAME"
\fBbundle\-info\fR \- Show information for the given gem in your bundle
.SH "SYNOPSIS"
-\fBbundle info\fR [GEM_NAME] [\-\-path]
+\fBbundle info\fR [GEM_NAME] [\-\-path] [\-\-version]
.SH "DESCRIPTION"
Given a gem name present in your bundle, print the basic information about it such as homepage, version, path and summary\.
.SH "OPTIONS"
.TP
\fB\-\-path\fR
Print the path of the given gem
+.TP
+\fB\-\-version\fR
+Print gem version
diff --git a/lib/bundler/man/bundle-info.1.ronn b/lib/bundler/man/bundle-info.1.ronn
index cecdeb564f..e99db8c614 100644
--- a/lib/bundler/man/bundle-info.1.ronn
+++ b/lib/bundler/man/bundle-info.1.ronn
@@ -1,10 +1,11 @@
bundle-info(1) -- Show information for the given gem in your bundle
-=========================================================================
+===================================================================
## SYNOPSIS
`bundle info` [GEM_NAME]
[--path]
+ [--version]
## DESCRIPTION
@@ -14,4 +15,7 @@ Given a gem name present in your bundle, print the basic information about it
## OPTIONS
* `--path`:
-Print the path of the given gem
+ Print the path of the given gem
+
+* `--version`:
+ Print gem version
diff --git a/lib/bundler/man/bundle-init.1 b/lib/bundler/man/bundle-init.1
index a0edaaa18f..83dad5c050 100644
--- a/lib/bundler/man/bundle-init.1
+++ b/lib/bundler/man/bundle-init.1
@@ -1,6 +1,6 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-INIT" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-INIT" "1" "September 2025" ""
.SH "NAME"
\fBbundle\-init\fR \- Generates a Gemfile into the current working directory
.SH "SYNOPSIS"
@@ -9,10 +9,10 @@
Init generates a default [\fBGemfile(5)\fR][Gemfile(5)] in the current working directory\. When adding a [\fBGemfile(5)\fR][Gemfile(5)] to a gem with a gemspec, the \fB\-\-gemspec\fR option will automatically add each dependency listed in the gemspec file to the newly created [\fBGemfile(5)\fR][Gemfile(5)]\.
.SH "OPTIONS"
.TP
-\fB\-\-gemspec\fR
+\fB\-\-gemspec=GEMSPEC\fR
Use the specified \.gemspec to create the [\fBGemfile(5)\fR][Gemfile(5)]
.TP
-\fB\-\-gemfile\fR
+\fB\-\-gemfile=GEMFILE\fR
Use the specified name for the gemfile instead of \fBGemfile\fR
.SH "FILES"
Included in the default [\fBGemfile(5)\fR][Gemfile(5)] generated is the line \fB# frozen_string_literal: true\fR\. 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\.
diff --git a/lib/bundler/man/bundle-init.1.ronn b/lib/bundler/man/bundle-init.1.ronn
index 7d3cede1f6..ab3c427b52 100644
--- a/lib/bundler/man/bundle-init.1.ronn
+++ b/lib/bundler/man/bundle-init.1.ronn
@@ -14,9 +14,10 @@ created [`Gemfile(5)`][Gemfile(5)].
## OPTIONS
-* `--gemspec`:
+* `--gemspec=GEMSPEC`:
Use the specified .gemspec to create the [`Gemfile(5)`][Gemfile(5)]
-* `--gemfile`:
+
+* `--gemfile=GEMFILE`:
Use the specified name for the gemfile instead of `Gemfile`
## FILES
diff --git a/lib/bundler/man/bundle-inject.1 b/lib/bundler/man/bundle-inject.1
deleted file mode 100644
index 7a1038206e..0000000000
--- a/lib/bundler/man/bundle-inject.1
+++ /dev/null
@@ -1,23 +0,0 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-INJECT" "1" "May 2024" ""
-.SH "NAME"
-\fBbundle\-inject\fR \- Add named gem(s) with version requirements to Gemfile
-.SH "SYNOPSIS"
-\fBbundle inject\fR [GEM] [VERSION]
-.SH "DESCRIPTION"
-Adds the named gem(s) with their version requirements to the resolved [\fBGemfile(5)\fR][Gemfile(5)]\.
-.P
-This command will add the gem to both your [\fBGemfile(5)\fR][Gemfile(5)] and Gemfile\.lock if it isn't listed yet\.
-.P
-Example:
-.IP "" 4
-.nf
-bundle install
-bundle inject 'rack' '> 0'
-.fi
-.IP "" 0
-.P
-This will inject the 'rack' gem with a version greater than 0 in your [\fBGemfile(5)\fR][Gemfile(5)] and Gemfile\.lock\.
-.P
-The \fBbundle inject\fR command was deprecated in Bundler 2\.1 and will be removed in Bundler 3\.0\.
diff --git a/lib/bundler/man/bundle-inject.1.ronn b/lib/bundler/man/bundle-inject.1.ronn
deleted file mode 100644
index 95704eddad..0000000000
--- a/lib/bundler/man/bundle-inject.1.ronn
+++ /dev/null
@@ -1,24 +0,0 @@
-bundle-inject(1) -- 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.
-
-The `bundle inject` command was deprecated in Bundler 2.1 and will be removed in Bundler 3.0.
diff --git a/lib/bundler/man/bundle-install.1 b/lib/bundler/man/bundle-install.1
index cc46a03b7f..68530f3ebb 100644
--- a/lib/bundler/man/bundle-install.1
+++ b/lib/bundler/man/bundle-install.1
@@ -1,10 +1,10 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-INSTALL" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-INSTALL" "1" "September 2025" ""
.SH "NAME"
\fBbundle\-install\fR \- Install the dependencies specified in your Gemfile
.SH "SYNOPSIS"
-\fBbundle install\fR [\-\-binstubs[=DIRECTORY]] [\-\-clean] [\-\-deployment] [\-\-frozen] [\-\-full\-index] [\-\-gemfile=GEMFILE] [\-\-jobs=NUMBER] [\-\-local] [\-\-no\-cache] [\-\-no\-prune] [\-\-path PATH] [\-\-prefer\-local] [\-\-quiet] [\-\-redownload] [\-\-retry=NUMBER] [\-\-shebang] [\-\-standalone[=GROUP[ GROUP\|\.\|\.\|\.]]] [\-\-system] [\-\-trust\-policy=POLICY] [\-\-with=GROUP[ GROUP\|\.\|\.\|\.]] [\-\-without=GROUP[ GROUP\|\.\|\.\|\.]]
+\fBbundle install\fR [\-\-force] [\-\-full\-index] [\-\-gemfile=GEMFILE] [\-\-jobs=NUMBER] [\-\-local] [\-\-lockfile=LOCKFILE] [\-\-no\-cache] [\-\-no\-lock] [\-\-prefer\-local] [\-\-quiet] [\-\-retry=NUMBER] [\-\-standalone[=GROUP[ GROUP\|\.\|\.\|\.]]] [\-\-trust\-policy=TRUST\-POLICY] [\-\-target\-rbconfig=TARGET\-RBCONFIG]
.SH "DESCRIPTION"
Install the gems specified in your Gemfile(5)\. If this is the first time you run bundle install (and a \fBGemfile\.lock\fR does not exist), Bundler will fetch all remote sources, resolve dependencies and install all needed gems\.
.P
@@ -12,92 +12,52 @@ If a \fBGemfile\.lock\fR does exist, and you have not updated your Gemfile(5), B
.P
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"
-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[=<directory>]\fR
-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 \fBbin/\fR\. This lets you link the binstub inside of an application to the exact gem version the application needs\.
-.IP
-Creates a directory (defaults to \fB~/bin\fR) 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 \fBPATH\fR variable\. For instance, if the \fBrails\fR gem comes with a \fBrails\fR executable, this flag will create a \fBbin/rails\fR executable that ensures that all referred dependencies will be resolved using the bundled gems\.
-.TP
-\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\.
-.TP
-\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\.
+\fB\-\-force\fR, \fB\-\-redownload\fR
+Force reinstalling every gem, even if already installed\.
.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\.
.TP
-\fB\-\-gemfile=<gemfile>\fR
+\fB\-\-gemfile=GEMFILE\fR
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 \fBGemfile\.lock\fR and \fBvendor/cache\fR relative to this location\.
.TP
-\fB\-\-jobs=[<number>]\fR, \fB\-j[<number>]\fR
+\fB\-\-jobs=<number>\fR, \fB\-j=<number>\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 an appropriate platform\-specific gem exists on \fBrubygems\.org\fR it will not be found\.
.TP
+\fB\-\-lockfile=LOCKFILE\fR
+The location of the lockfile which Bundler should use\. This defaults to the Gemfile location with \fB\.lock\fR appended\.
+.TP
\fB\-\-prefer\-local\fR
Force using locally installed gems, or gems already present in Rubygems' cache or in \fBvendor/cache\fR, when resolving, even if newer versions are available remotely\. Only attempt to connect to \fBrubygems\.org\fR for gems that are not present locally\.
.TP
\fB\-\-no\-cache\fR
Do not update the cache in \fBvendor/cache\fR 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\.
.TP
-\fB\-\-no\-prune\fR
-Don't remove stale gems from the cache when the installation finishes\.
+\fB\-\-no\-lock\fR
+Do not create a lockfile\. Useful if you want to install dependencies but not lock versions of gems\. Recommended for library development, and other situations where the code is expected to work with a range of dependency versions\.
.IP
-This option is deprecated in favor of the \fBno_prune\fR setting\.
-.TP
-\fB\-\-path=<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\.
+This has the same effect as using \fBlockfile false\fR in the Gemfile\. See gemfile(5) for more information\.
.TP
\fB\-\-quiet\fR
-Do not print progress information to the standard output\. Instead, Bundler will exit using a status code (\fB$?\fR)\.
+Do not print progress information to the standard output\.
.TP
\fB\-\-retry=[<number>]\fR
Retry failed network or git requests for \fInumber\fR times\.
.TP
-\fB\-\-shebang=<ruby\-executable>\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[=<list>]\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]\.
+Makes a bundle that can work without depending on Rubygems or Bundler at runtime\. A space separated list of groups to install can 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\.
.TP
-\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=[<policy>]\fR
+\fB\-\-trust\-policy=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\.
.TP
-\fB\-\-with=<list>\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=<list>\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\.
+\fB\-\-target\-rbconfig=TARGET\-RBCONFIG\fR
+Path to rbconfig\.rb for the deployment target platform\.
.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\.
+Bundler's defaults are optimized for development\. To switch to defaults optimized for deployment and for CI, use the \fBdeployment\fR setting\. Do not activate deployment mode on development machines, as it will cause an error when the Gemfile(5) is modified\.
.IP "1." 4
A \fBGemfile\.lock\fR is required\.
.IP
@@ -117,14 +77,14 @@ In development, it's convenient to share the gems used in your application with
.IP
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\.
.IP
-As a result, \fBbundle install \-\-deployment\fR installs gems to the \fBvendor/bundle\fR directory in the application\. This may be overridden using the \fB\-\-path\fR option\.
+As a result, when \fBdeployment\fR is configured, \fBbundle install\fR installs gems to the \fBvendor/bundle\fR directory in the application\. This may be overridden using the \fBpath\fR setting\.
.IP "" 0
.SH "INSTALLING GROUPS"
By default, \fBbundle install\fR will install all gems in all groups in your Gemfile(5), except those declared for a different platform\.
.P
-However, you can explicitly tell Bundler to skip installing certain groups with the \fB\-\-without\fR option\. This option takes a space\-separated list of groups\.
+However, you can explicitly tell Bundler to skip installing certain groups with the \fBwithout\fR setting\. This setting takes a space\-separated list of groups\.
.P
-While the \fB\-\-without\fR option will skip \fIinstalling\fR the gems in the specified groups, it will still \fIdownload\fR those gems and use them to resolve the dependencies of every gem in your Gemfile(5)\.
+While the \fBwithout\fR setting will skip \fIinstalling\fR the gems in the specified groups, \fBbundle install\fR will still \fIdownload\fR those gems and use them to resolve the dependencies of every gem in your Gemfile(5)\.
.P
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\.
.P
@@ -145,7 +105,7 @@ end
.P
In this case, \fBsinatra\fR depends on any version of Rack (\fB>= 1\.0\fR), while \fBrack\-perftools\-profiler\fR depends on 1\.x (\fB~> 1\.0\fR)\.
.P
-When you run \fBbundle install \-\-without production\fR in development, we look at the dependencies of \fBrack\-perftools\-profiler\fR 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 \fBproduction\fR group \fIis\fR used\.
+When you configure \fBbundle config without production\fR in development, we look at the dependencies of \fBrack\-perftools\-profiler\fR 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 \fBproduction\fR group \fIis\fR used\.
.P
This should not cause any problems in practice, because we do not attempt to \fBinstall\fR the gems in the excluded groups, and only evaluate as part of the dependency resolution process\.
.P
diff --git a/lib/bundler/man/bundle-install.1.ronn b/lib/bundler/man/bundle-install.1.ronn
index ed8169de05..c7d88bfb73 100644
--- a/lib/bundler/man/bundle-install.1.ronn
+++ b/lib/bundler/man/bundle-install.1.ronn
@@ -3,27 +3,20 @@ bundle-install(1) -- Install the dependencies specified in your Gemfile
## SYNOPSIS
-`bundle install` [--binstubs[=DIRECTORY]]
- [--clean]
- [--deployment]
- [--frozen]
+`bundle install` [--force]
[--full-index]
[--gemfile=GEMFILE]
[--jobs=NUMBER]
[--local]
+ [--lockfile=LOCKFILE]
[--no-cache]
- [--no-prune]
- [--path PATH]
+ [--no-lock]
[--prefer-local]
[--quiet]
- [--redownload]
[--retry=NUMBER]
- [--shebang]
[--standalone[=GROUP[ GROUP...]]]
- [--system]
- [--trust-policy=POLICY]
- [--with=GROUP[ GROUP...]]
- [--without=GROUP[ GROUP...]]
+ [--trust-policy=TRUST-POLICY]
+ [--target-rbconfig=TARGET-RBCONFIG]
## DESCRIPTION
@@ -44,63 +37,22 @@ 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[=<directory>]`:
- 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.
+* `--force`, `--redownload`:
+ Force reinstalling every gem, even if already installed.
* `--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=<gemfile>`:
+* `--gemfile=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=[<number>]`, `-j[<number>]`:
+* `--jobs=<number>`, `-j=<number>`:
The maximum number of parallel download and install jobs. The default is the
number of available processors.
@@ -110,6 +62,10 @@ automatically and that requires `bundler` to silently remember them. Since
appropriate platform-specific gem exists on `rubygems.org` it will not be
found.
+* `--lockfile=LOCKFILE`:
+ The location of the lockfile which Bundler should use. This defaults
+ to the Gemfile location with `.lock` appended.
+
* `--prefer-local`:
Force using locally installed gems, or gems already present in Rubygems' cache
or in `vendor/cache`, when resolving, even if newer versions are available
@@ -121,75 +77,42 @@ automatically and that requires `bundler` to silently remember them. Since
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.
+* `--no-lock`:
+ Do not create a lockfile. Useful if you want to install dependencies but not
+ lock versions of gems. Recommended for library development, and other
+ situations where the code is expected to work with a range of dependency
+ versions.
- This option is deprecated in favor of the `no_prune` setting.
-
-* `--path=<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.
+ This has the same effect as using `lockfile false` in the Gemfile.
+ See gemfile(5) for more information.
* `--quiet`:
- Do not print progress information to the standard output. Instead, Bundler
- will exit using a status code (`$?`).
+ Do not print progress information to the standard output.
* `--retry=[<number>]`:
Retry failed network or git requests for <number> times.
-* `--shebang=<ruby-executable>`:
- 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[=<list>]`:
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.
+ runtime. A space separated list of groups to install can 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`.
+ in the manner required.
- This option is deprecated in favor of the `system` setting.
-
-* `--trust-policy=[<policy>]`:
+* `--trust-policy=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=<list>`:
- 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=<list>`:
- 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.
+* `--target-rbconfig=TARGET-RBCONFIG`:
+ Path to rbconfig.rb for the deployment target platform.
## 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
+defaults optimized for deployment and for CI, use the `deployment`
+setting. 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.
@@ -221,9 +144,9 @@ will cause an error when the Gemfile(5) is modified.
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.
+ As a result, when `deployment` is configured, `bundle install` installs gems
+ to the `vendor/bundle` directory in the application. This may be
+ overridden using the `path` setting.
## INSTALLING GROUPS
@@ -231,12 +154,12 @@ 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
+certain groups with the `without` setting. This setting 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).
+While the `without` setting will skip _installing_ the gems in the
+specified groups, `bundle install` 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
@@ -262,7 +185,7 @@ For a simple illustration, consider the following Gemfile(5):
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
+When you configure `bundle config 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
diff --git a/lib/bundler/man/bundle-issue.1 b/lib/bundler/man/bundle-issue.1
new file mode 100644
index 0000000000..394d6c5469
--- /dev/null
+++ b/lib/bundler/man/bundle-issue.1
@@ -0,0 +1,45 @@
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-ISSUE" "1" "September 2025" ""
+.SH "NAME"
+\fBbundle\-issue\fR \- Get help reporting Bundler issues
+.SH "SYNOPSIS"
+\fBbundle issue\fR
+.SH "DESCRIPTION"
+Provides guidance on reporting Bundler issues and outputs detailed system information that should be included when filing a bug report\. This command:
+.IP "1." 4
+Displays links to troubleshooting resources
+.IP "2." 4
+Shows instructions for reporting issues
+.IP "3." 4
+Outputs comprehensive environment information needed for debugging
+.IP "" 0
+.P
+The command helps ensure that bug reports include all necessary system details for effective troubleshooting\.
+.SH "OUTPUT"
+The command outputs several sections:
+.IP "\(bu" 4
+Troubleshooting links and resources
+.IP "\(bu" 4
+Link to the GitHub issue template
+.IP "\(bu" 4
+Environment information including: Bundler version and platforms, Ruby version and configuration, RubyGems version and paths, Development tool versions (Git, RVM, rbenv, chruby)
+.IP "\(bu" 4
+Bundler build metadata
+.IP "\(bu" 4
+Current Bundler settings
+.IP "\(bu" 4
+Bundle Doctor output
+.IP "" 0
+.SH "EXAMPLES"
+Get issue reporting information:
+.IP "" 4
+.nf
+$ bundle issue
+.fi
+.IP "" 0
+.SH "SEE ALSO"
+.IP "\(bu" 4
+bundle\-doctor(1)
+.IP "" 0
+
diff --git a/lib/bundler/man/bundle-issue.1.ronn b/lib/bundler/man/bundle-issue.1.ronn
new file mode 100644
index 0000000000..37f676a354
--- /dev/null
+++ b/lib/bundler/man/bundle-issue.1.ronn
@@ -0,0 +1,37 @@
+bundle-issue(1) -- Get help reporting Bundler issues
+====================================================
+
+## SYNOPSIS
+
+`bundle issue`
+
+## DESCRIPTION
+
+Provides guidance on reporting Bundler issues and outputs detailed system information that should be included when filing a bug report. This command:
+
+1. Displays links to troubleshooting resources
+2. Shows instructions for reporting issues
+3. Outputs comprehensive environment information needed for debugging
+
+The command helps ensure that bug reports include all necessary system details for effective troubleshooting.
+
+## OUTPUT
+
+The command outputs several sections:
+
+* Troubleshooting links and resources
+* Link to the GitHub issue template
+* Environment information including: Bundler version and platforms, Ruby version and configuration, RubyGems version and paths, Development tool versions (Git, RVM, rbenv, chruby)
+* Bundler build metadata
+* Current Bundler settings
+* Bundle Doctor output
+
+## EXAMPLES
+
+Get issue reporting information:
+
+ $ bundle issue
+
+## SEE ALSO
+
+* bundle-doctor(1)
diff --git a/lib/bundler/man/bundle-licenses.1 b/lib/bundler/man/bundle-licenses.1
new file mode 100644
index 0000000000..2931e42dd7
--- /dev/null
+++ b/lib/bundler/man/bundle-licenses.1
@@ -0,0 +1,9 @@
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-LICENSES" "1" "September 2025" ""
+.SH "NAME"
+\fBbundle\-licenses\fR \- Print the license of all gems in the bundle
+.SH "SYNOPSIS"
+\fBbundle licenses\fR
+.SH "DESCRIPTION"
+Prints the license of all gems in the bundle\.
diff --git a/lib/bundler/man/bundle-licenses.1.ronn b/lib/bundler/man/bundle-licenses.1.ronn
new file mode 100644
index 0000000000..91caba6c2a
--- /dev/null
+++ b/lib/bundler/man/bundle-licenses.1.ronn
@@ -0,0 +1,10 @@
+bundle-licenses(1) -- Print the license of all gems in the bundle
+=================================================================
+
+## SYNOPSIS
+
+`bundle licenses`
+
+## DESCRIPTION
+
+Prints the license of all gems in the bundle.
diff --git a/lib/bundler/man/bundle-list.1 b/lib/bundler/man/bundle-list.1
index 21723608cc..d8bcf20585 100644
--- a/lib/bundler/man/bundle-list.1
+++ b/lib/bundler/man/bundle-list.1
@@ -1,6 +1,6 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-LIST" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-LIST" "1" "September 2025" ""
.SH "NAME"
\fBbundle\-list\fR \- List all the gems in the bundle
.SH "SYNOPSIS"
@@ -19,6 +19,8 @@ bundle list \-\-without\-group test
bundle list \-\-only\-group dev
.P
bundle list \-\-only\-group dev test \-\-paths
+.P
+bundle list \-\-format json
.SH "OPTIONS"
.TP
\fB\-\-name\-only\fR
@@ -32,4 +34,7 @@ A space\-separated list of groups of gems to skip during printing\.
.TP
\fB\-\-only\-group=<list>\fR
A space\-separated list of groups of gems to print\.
+.TP
+\fB\-\-format=FORMAT\fR
+Format output ('json' is the only supported format)
diff --git a/lib/bundler/man/bundle-list.1.ronn b/lib/bundler/man/bundle-list.1.ronn
index dc058ecd5f..9ec2b13282 100644
--- a/lib/bundler/man/bundle-list.1.ronn
+++ b/lib/bundler/man/bundle-list.1.ronn
@@ -1,5 +1,5 @@
bundle-list(1) -- List all the gems in the bundle
-=========================================================================
+=================================================
## SYNOPSIS
@@ -21,13 +21,21 @@ bundle list --only-group dev
bundle list --only-group dev test --paths
+bundle list --format json
+
## OPTIONS
* `--name-only`:
Print only the name of each gem.
+
* `--paths`:
Print the path to each gem in the bundle.
+
* `--without-group=<list>`:
A space-separated list of groups of gems to skip during printing.
+
* `--only-group=<list>`:
A space-separated list of groups of gems to print.
+
+* `--format=FORMAT`:
+ Format output ('json' is the only supported format)
diff --git a/lib/bundler/man/bundle-lock.1 b/lib/bundler/man/bundle-lock.1
index 8b81b7732f..478d173535 100644
--- a/lib/bundler/man/bundle-lock.1
+++ b/lib/bundler/man/bundle-lock.1
@@ -1,35 +1,47 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-LOCK" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-LOCK" "1" "September 2025" ""
.SH "NAME"
\fBbundle\-lock\fR \- Creates / Updates a lockfile without installing
.SH "SYNOPSIS"
-\fBbundle lock\fR [\-\-update] [\-\-local] [\-\-print] [\-\-lockfile=PATH] [\-\-full\-index] [\-\-add\-platform] [\-\-remove\-platform] [\-\-patch] [\-\-minor] [\-\-major] [\-\-strict] [\-\-conservative]
+\fBbundle lock\fR [\-\-update] [\-\-bundler[=BUNDLER]] [\-\-local] [\-\-print] [\-\-lockfile=PATH] [\-\-full\-index] [\-\-gemfile=GEMFILE] [\-\-add\-checksums] [\-\-add\-platform] [\-\-remove\-platform] [\-\-normalize\-platforms] [\-\-patch] [\-\-minor] [\-\-major] [\-\-pre] [\-\-strict] [\-\-conservative]
.SH "DESCRIPTION"
Lock the gems specified in Gemfile\.
.SH "OPTIONS"
.TP
-\fB\-\-update=<*gems>\fR
+\fB\-\-update[=<list>]\fR
Ignores the existing lockfile\. Resolve then updates lockfile\. Taking a list of gems or updating all gems if no list is given\.
.TP
+\fB\-\-bundler[=BUNDLER]\fR
+Update the locked version of bundler to the given version or the latest version if no version is given\.
+.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\.
.TP
\fB\-\-print\fR
Prints the lockfile to STDOUT instead of writing to the file system\.
.TP
-\fB\-\-lockfile=<path>\fR
+\fB\-\-lockfile=LOCKFILE\fR
The path where the lockfile should be written to\.
.TP
\fB\-\-full\-index\fR
Fall back to using the single\-file index of all gems\.
.TP
-\fB\-\-add\-platform\fR
+\fB\-\-gemfile=GEMFILE\fR
+Use the specified gemfile instead of [\fBGemfile(5)\fR][Gemfile(5)]\.
+.TP
+\fB\-\-add\-checksums\fR
+Add checksums to the lockfile\.
+.TP
+\fB\-\-add\-platform=<list>\fR
Add a new platform to the lockfile, re\-resolving for the addition of that platform\.
.TP
-\fB\-\-remove\-platform\fR
+\fB\-\-remove\-platform=<list>\fR
Remove a platform from the lockfile\.
.TP
+\fB\-\-normalize\-platforms\fR
+Normalize lockfile platforms\.
+.TP
\fB\-\-patch\fR
If updating, prefer updating only to next patch version\.
.TP
@@ -39,6 +51,9 @@ If updating, prefer updating only to next minor version\.
\fB\-\-major\fR
If updating, prefer updating to next major version (default)\.
.TP
+\fB\-\-pre\fR
+If updating, always choose the highest allowed version, regardless of prerelease status\.
+.TP
\fB\-\-strict\fR
If updating, do not allow any gem to be updated past latest \-\-patch | \-\-minor | \-\-major\.
.TP
diff --git a/lib/bundler/man/bundle-lock.1.ronn b/lib/bundler/man/bundle-lock.1.ronn
index 3aa5920f5a..6d3e63c982 100644
--- a/lib/bundler/man/bundle-lock.1.ronn
+++ b/lib/bundler/man/bundle-lock.1.ronn
@@ -4,15 +4,20 @@ bundle-lock(1) -- Creates / Updates a lockfile without installing
## SYNOPSIS
`bundle lock` [--update]
+ [--bundler[=BUNDLER]]
[--local]
[--print]
[--lockfile=PATH]
[--full-index]
+ [--gemfile=GEMFILE]
+ [--add-checksums]
[--add-platform]
[--remove-platform]
+ [--normalize-platforms]
[--patch]
[--minor]
[--major]
+ [--pre]
[--strict]
[--conservative]
@@ -22,10 +27,14 @@ Lock the gems specified in Gemfile.
## OPTIONS
-* `--update=<*gems>`:
+* `--update[=<list>]`:
Ignores the existing lockfile. Resolve then updates lockfile. Taking a list
of gems or updating all gems if no list is given.
+* `--bundler[=BUNDLER]`:
+ Update the locked version of bundler to the given version or the latest
+ version if no version is given.
+
* `--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
@@ -35,19 +44,28 @@ Lock the gems specified in Gemfile.
* `--print`:
Prints the lockfile to STDOUT instead of writing to the file system.
-* `--lockfile=<path>`:
+* `--lockfile=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`:
+* `--gemfile=GEMFILE`:
+ Use the specified gemfile instead of [`Gemfile(5)`][Gemfile(5)].
+
+* `--add-checksums`:
+ Add checksums to the lockfile.
+
+* `--add-platform=<list>`:
Add a new platform to the lockfile, re-resolving for the addition of that
platform.
-* `--remove-platform`:
+* `--remove-platform=<list>`:
Remove a platform from the lockfile.
+* `--normalize-platforms`:
+ Normalize lockfile platforms.
+
* `--patch`:
If updating, prefer updating only to next patch version.
@@ -57,6 +75,9 @@ Lock the gems specified in Gemfile.
* `--major`:
If updating, prefer updating to next major version (default).
+* `--pre`:
+ If updating, always choose the highest allowed version, regardless of prerelease status.
+
* `--strict`:
If updating, do not allow any gem to be updated past latest --patch | --minor | --major.
diff --git a/lib/bundler/man/bundle-open.1 b/lib/bundler/man/bundle-open.1
index 41a8804a09..2f13b1329f 100644
--- a/lib/bundler/man/bundle-open.1
+++ b/lib/bundler/man/bundle-open.1
@@ -1,6 +1,6 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-OPEN" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-OPEN" "1" "September 2025" ""
.SH "NAME"
\fBbundle\-open\fR \- Opens the source directory for a gem in your bundle
.SH "SYNOPSIS"
@@ -27,6 +27,6 @@ bundle open 'rack' \-\-path 'README\.md'
Will open the README\.md file of the 'rack' gem source in your bundle\.
.SH "OPTIONS"
.TP
-\fB\-\-path\fR
+\fB\-\-path[=PATH]\fR
Specify GEM source relative path to open\.
diff --git a/lib/bundler/man/bundle-open.1.ronn b/lib/bundler/man/bundle-open.1.ronn
index a857f3a965..24dbe97e44 100644
--- a/lib/bundler/man/bundle-open.1.ronn
+++ b/lib/bundler/man/bundle-open.1.ronn
@@ -23,5 +23,6 @@ Will open the source directory for the 'rack' gem in your bundle.
Will open the README.md file of the 'rack' gem source in your bundle.
## OPTIONS
-* `--path`:
+
+* `--path[=PATH]`:
Specify GEM source relative path to open.
diff --git a/lib/bundler/man/bundle-outdated.1 b/lib/bundler/man/bundle-outdated.1
index 838fce45cd..7e10d202be 100644
--- a/lib/bundler/man/bundle-outdated.1
+++ b/lib/bundler/man/bundle-outdated.1
@@ -1,10 +1,10 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-OUTDATED" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-OUTDATED" "1" "September 2025" ""
.SH "NAME"
\fBbundle\-outdated\fR \- List installed gems with newer versions available
.SH "SYNOPSIS"
-\fBbundle outdated\fR [GEM] [\-\-local] [\-\-pre] [\-\-source] [\-\-strict] [\-\-parseable | \-\-porcelain] [\-\-group=GROUP] [\-\-groups] [\-\-patch|\-\-minor|\-\-major] [\-\-filter\-major] [\-\-filter\-minor] [\-\-filter\-patch] [\-\-only\-explicit]
+\fBbundle outdated\fR [GEM] [\-\-local] [\-\-pre] [\-\-source] [\-\-filter\-strict | \-\-strict] [\-\-update\-strict] [\-\-parseable | \-\-porcelain] [\-\-group=GROUP] [\-\-groups] [\-\-patch|\-\-minor|\-\-major] [\-\-filter\-major] [\-\-filter\-minor] [\-\-filter\-patch] [\-\-only\-explicit]
.SH "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\.
.SH "OPTIONS"
@@ -15,16 +15,19 @@ Do not attempt to fetch gems remotely and use the gem cache instead\.
\fB\-\-pre\fR
Check for newer pre\-release gems\.
.TP
-\fB\-\-source\fR
+\fB\-\-source=<list>\fR
Check against a specific source\.
.TP
-\fB\-\-strict\fR
+\fB\-\-filter\-strict\fR, \fB\-\-strict\fR
Only list newer versions allowed by your Gemfile requirements, also respecting conservative update flags (\-\-patch, \-\-minor, \-\-major)\.
.TP
+\fB\-\-update\-strict\fR
+Strict conservative resolution, do not allow any gem to be updated past latest \-\-patch | \-\-minor | \-\-major\.
+.TP
\fB\-\-parseable\fR, \fB\-\-porcelain\fR
Use minimal formatting for more parseable output\.
.TP
-\fB\-\-group\fR
+\fB\-\-group=GROUP\fR
List gems from a specific group\.
.TP
\fB\-\-groups\fR
diff --git a/lib/bundler/man/bundle-outdated.1.ronn b/lib/bundler/man/bundle-outdated.1.ronn
index 4ac65d0532..6f67a31977 100644
--- a/lib/bundler/man/bundle-outdated.1.ronn
+++ b/lib/bundler/man/bundle-outdated.1.ronn
@@ -6,7 +6,8 @@ bundle-outdated(1) -- List installed gems with newer versions available
`bundle outdated` [GEM] [--local]
[--pre]
[--source]
- [--strict]
+ [--filter-strict | --strict]
+ [--update-strict]
[--parseable | --porcelain]
[--group=GROUP]
[--groups]
@@ -31,16 +32,19 @@ are up to date, Bundler will exit with a status of 0. Otherwise, it will exit 1.
* `--pre`:
Check for newer pre-release gems.
-* `--source`:
+* `--source=<list>`:
Check against a specific source.
-* `--strict`:
+* `--filter-strict`, `--strict`:
Only list newer versions allowed by your Gemfile requirements, also respecting conservative update flags (--patch, --minor, --major).
+* `--update-strict`:
+ Strict conservative resolution, do not allow any gem to be updated past latest --patch | --minor | --major.
+
* `--parseable`, `--porcelain`:
Use minimal formatting for more parseable output.
-* `--group`:
+* `--group=GROUP`:
List gems from a specific group.
* `--groups`:
diff --git a/lib/bundler/man/bundle-platform.1 b/lib/bundler/man/bundle-platform.1
index 0dbce7a7a4..6a3a08c3a9 100644
--- a/lib/bundler/man/bundle-platform.1
+++ b/lib/bundler/man/bundle-platform.1
@@ -1,6 +1,6 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-PLATFORM" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-PLATFORM" "1" "September 2025" ""
.SH "NAME"
\fBbundle\-platform\fR \- Displays platform compatibility information
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-plugin.1 b/lib/bundler/man/bundle-plugin.1
index 1290abb3ba..25da562475 100644
--- a/lib/bundler/man/bundle-plugin.1
+++ b/lib/bundler/man/bundle-plugin.1
@@ -1,12 +1,12 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-PLUGIN" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-PLUGIN" "1" "September 2025" ""
.SH "NAME"
\fBbundle\-plugin\fR \- Manage Bundler plugins
.SH "SYNOPSIS"
-\fBbundle plugin\fR install PLUGINS [\-\-source=\fISOURCE\fR] [\-\-version=\fIversion\fR] [\-\-git=\fIgit\-url\fR] [\-\-branch=\fIbranch\fR|\-\-ref=\fIrev\fR] [\-\-path=\fIpath\fR]
+\fBbundle plugin\fR install PLUGINS [\-\-source=SOURCE] [\-\-version=VERSION] [\-\-git=GIT] [\-\-branch=BRANCH|\-\-ref=REF] [\-\-path=PATH]
.br
-\fBbundle plugin\fR uninstall PLUGINS
+\fBbundle plugin\fR uninstall PLUGINS [\-\-all]
.br
\fBbundle plugin\fR list
.br
@@ -16,18 +16,23 @@ You can install, uninstall, and list plugin(s) with this command to extend funct
.SH "SUB\-COMMANDS"
.SS "install"
Install the given plugin(s)\.
+.P
+For example, \fBbundle plugin install bundler\-graph\fR will install bundler\-graph gem from globally configured sources (defaults to RubyGems\.org)\. Note that the global source specified in Gemfile is ignored\.
+.P
+\fBOPTIONS\fR
.TP
-\fBbundle plugin install bundler\-graph\fR
-Install bundler\-graph gem from globally configured sources (defaults to RubyGems\.org)\. The global source, specified in source in Gemfile is ignored\.
-.TP
-\fBbundle plugin install bundler\-graph \-\-source https://example\.com\fR
-Install bundler\-graph gem from example\.com\. The global source, specified in source in Gemfile is not considered\.
+\fB\-\-source=SOURCE\fR
+Install the plugin gem from a specific source, rather than from globally configured sources\.
+.IP
+Example: \fBbundle plugin install bundler\-graph \-\-source https://example\.com\fR
.TP
-\fBbundle plugin install bundler\-graph \-\-version 0\.2\.1\fR
-You can specify the version of the gem via \fB\-\-version\fR\.
+\fB\-\-version=VERSION\fR
+Specify a version of the plugin gem to install via \fB\-\-version\fR\.
+.IP
+Example: \fBbundle plugin install bundler\-graph \-\-version 0\.2\.1\fR
.TP
-\fBbundle plugin install bundler\-graph \-\-git https://github\.com/rubygems/bundler\-graph\fR
-Install bundler\-graph gem from Git repository\. You can use standard Git URLs like:
+\fB\-\-git=GIT\fR
+Install the plugin gem from a Git repository\. You can use standard Git URLs like:
.IP
\fBssh://[user@]host\.xz[:port]/path/to/repo\.git\fR
.br
@@ -37,12 +42,25 @@ Install bundler\-graph gem from Git repository\. You can use standard Git URLs l
.br
\fBfile:///path/to/repo\fR
.IP
-When you specify \fB\-\-git\fR, you can use \fB\-\-branch\fR or \fB\-\-ref\fR to specify any branch, tag, or commit hash (revision) to use\.
+Example: \fBbundle plugin install bundler\-graph \-\-git https://github\.com/rubygems/bundler\-graph\fR
.TP
-\fBbundle plugin install bundler\-graph \-\-path \.\./bundler\-graph\fR
-Install bundler\-graph gem from a local path\.
+\fB\-\-branch=BRANCH\fR
+When you specify \fB\-\-git\fR, you can use \fB\-\-branch\fR to use\.
+.TP
+\fB\-\-ref=REF\fR
+When you specify \fB\-\-git\fR, you can use \fB\-\-ref\fR to specify any tag, or commit hash (revision) to use\.
+.TP
+\fB\-\-path=PATH\fR
+Install the plugin gem from a local path\.
+.IP
+Example: \fBbundle plugin install bundler\-graph \-\-path \.\./bundler\-graph\fR
.SS "uninstall"
Uninstall the plugin(s) specified in PLUGINS\.
+.P
+\fBOPTIONS\fR
+.TP
+\fB\-\-all\fR
+Uninstall all the installed plugins\. If no plugin is installed, then it does nothing\.
.SS "list"
List the installed plugins and available commands\.
.P
diff --git a/lib/bundler/man/bundle-plugin.1.ronn b/lib/bundler/man/bundle-plugin.1.ronn
index b0a34660ea..b54e0c08b4 100644
--- a/lib/bundler/man/bundle-plugin.1.ronn
+++ b/lib/bundler/man/bundle-plugin.1.ronn
@@ -3,10 +3,10 @@ bundle-plugin(1) -- Manage Bundler plugins
## SYNOPSIS
-`bundle plugin` install PLUGINS [--source=<SOURCE>] [--version=<version>]
- [--git=<git-url>] [--branch=<branch>|--ref=<rev>]
- [--path=<path>]<br>
-`bundle plugin` uninstall PLUGINS<br>
+`bundle plugin` install PLUGINS [--source=SOURCE] [--version=VERSION]
+ [--git=GIT] [--branch=BRANCH|--ref=REF]
+ [--path=PATH]<br>
+`bundle plugin` uninstall PLUGINS [--all]<br>
`bundle plugin` list<br>
`bundle plugin` help [COMMAND]
@@ -20,32 +20,53 @@ You can install, uninstall, and list plugin(s) with this command to extend funct
Install the given plugin(s).
-* `bundle plugin install bundler-graph`:
- Install bundler-graph gem from globally configured sources (defaults to RubyGems.org). The global source, specified in source in Gemfile is ignored.
+For example, `bundle plugin install bundler-graph` will install bundler-graph
+gem from globally configured sources (defaults to RubyGems.org). Note that the
+global source specified in Gemfile is ignored.
-* `bundle plugin install bundler-graph --source https://example.com`:
- Install bundler-graph gem from example.com. The global source, specified in source in Gemfile is not considered.
+**OPTIONS**
-* `bundle plugin install bundler-graph --version 0.2.1`:
- You can specify the version of the gem via `--version`.
+* `--source=SOURCE`:
+ Install the plugin gem from a specific source, rather than from globally configured sources.
-* `bundle plugin install bundler-graph --git https://github.com/rubygems/bundler-graph`:
- Install bundler-graph gem from Git repository. You can use standard Git URLs like:
+ Example: `bundle plugin install bundler-graph --source https://example.com`
+
+* `--version=VERSION`:
+ Specify a version of the plugin gem to install via `--version`.
+
+ Example: `bundle plugin install bundler-graph --version 0.2.1`
+
+* `--git=GIT`:
+ Install the plugin gem from a Git repository. You can use standard Git URLs like:
`ssh://[user@]host.xz[:port]/path/to/repo.git`<br>
`http[s]://host.xz[:port]/path/to/repo.git`<br>
`/path/to/repo`<br>
`file:///path/to/repo`
- When you specify `--git`, you can use `--branch` or `--ref` to specify any branch, tag, or commit hash (revision) to use.
+ Example: `bundle plugin install bundler-graph --git https://github.com/rubygems/bundler-graph`
+
+* `--branch=BRANCH`:
+ When you specify `--git`, you can use `--branch` to use.
-* `bundle plugin install bundler-graph --path ../bundler-graph`:
- Install bundler-graph gem from a local path.
+* `--ref=REF`:
+ When you specify `--git`, you can use `--ref` to specify any tag, or commit
+ hash (revision) to use.
+
+* `--path=PATH`:
+ Install the plugin gem from a local path.
+
+ Example: `bundle plugin install bundler-graph --path ../bundler-graph`
### uninstall
Uninstall the plugin(s) specified in PLUGINS.
+**OPTIONS**
+
+* `--all`:
+ Uninstall all the installed plugins. If no plugin is installed, then it does nothing.
+
### list
List the installed plugins and available commands.
diff --git a/lib/bundler/man/bundle-pristine.1 b/lib/bundler/man/bundle-pristine.1
index bf4a7cd323..a8316b5cca 100644
--- a/lib/bundler/man/bundle-pristine.1
+++ b/lib/bundler/man/bundle-pristine.1
@@ -1,6 +1,6 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-PRISTINE" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-PRISTINE" "1" "September 2025" ""
.SH "NAME"
\fBbundle\-pristine\fR \- Restores installed gems to their pristine condition
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-pristine.1.ronn b/lib/bundler/man/bundle-pristine.1.ronn
index e2d6b6a348..984debeb3d 100644
--- a/lib/bundler/man/bundle-pristine.1.ronn
+++ b/lib/bundler/man/bundle-pristine.1.ronn
@@ -1,5 +1,5 @@
bundle-pristine(1) -- Restores installed gems to their pristine condition
-===========================================================================
+=========================================================================
## SYNOPSIS
diff --git a/lib/bundler/man/bundle-remove.1 b/lib/bundler/man/bundle-remove.1
index c3c96b416d..4dc7a03b9f 100644
--- a/lib/bundler/man/bundle-remove.1
+++ b/lib/bundler/man/bundle-remove.1
@@ -1,21 +1,15 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-REMOVE" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-REMOVE" "1" "September 2025" ""
.SH "NAME"
\fBbundle\-remove\fR \- Removes gems from the Gemfile
.SH "SYNOPSIS"
-\fBbundle remove [GEM [GEM \|\.\|\.\|\.]] [\-\-install]\fR
+`bundle remove [GEM [GEM \|\.\|\.\|\.]]
.SH "DESCRIPTION"
Removes the given gems from the Gemfile while ensuring that the resulting 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\.
-.SH "OPTIONS"
-.TP
-\fB\-\-install\fR
-Runs \fBbundle install\fR 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)\.
.P
Example:
.P
bundle remove rails
.P
bundle remove rails rack
-.P
-bundle remove rails rack \-\-install
diff --git a/lib/bundler/man/bundle-remove.1.ronn b/lib/bundler/man/bundle-remove.1.ronn
index 40a239b4a2..49cb4dc1fd 100644
--- a/lib/bundler/man/bundle-remove.1.ronn
+++ b/lib/bundler/man/bundle-remove.1.ronn
@@ -1,23 +1,16 @@
bundle-remove(1) -- Removes gems from the Gemfile
-===========================================================================
+=================================================
## SYNOPSIS
-`bundle remove [GEM [GEM ...]] [--install]`
+`bundle remove [GEM [GEM ...]]
## DESCRIPTION
Removes the given gems from the Gemfile while ensuring that the resulting 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
diff --git a/lib/bundler/man/bundle-show.1 b/lib/bundler/man/bundle-show.1
index c054875efd..901460962c 100644
--- a/lib/bundler/man/bundle-show.1
+++ b/lib/bundler/man/bundle-show.1
@@ -1,6 +1,6 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-SHOW" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-SHOW" "1" "September 2025" ""
.SH "NAME"
\fBbundle\-show\fR \- Shows all the gems in your bundle, or the path to a gem
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-update.1 b/lib/bundler/man/bundle-update.1
index acd80ec75c..2f9932dc1e 100644
--- a/lib/bundler/man/bundle-update.1
+++ b/lib/bundler/man/bundle-update.1
@@ -1,10 +1,10 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-UPDATE" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-UPDATE" "1" "September 2025" ""
.SH "NAME"
\fBbundle\-update\fR \- Update your gems to the latest available versions
.SH "SYNOPSIS"
-\fBbundle update\fR \fI*gems\fR [\-\-all] [\-\-group=NAME] [\-\-source=NAME] [\-\-local] [\-\-ruby] [\-\-bundler[=VERSION]] [\-\-full\-index] [\-\-jobs=JOBS] [\-\-quiet] [\-\-patch|\-\-minor|\-\-major] [\-\-redownload] [\-\-strict] [\-\-conservative]
+\fBbundle update\fR \fI*gems\fR [\-\-all] [\-\-group=NAME] [\-\-source=NAME] [\-\-local] [\-\-ruby] [\-\-bundler[=VERSION]] [\-\-force] [\-\-full\-index] [\-\-gemfile=GEMFILE] [\-\-jobs=NUMBER] [\-\-quiet] [\-\-patch|\-\-minor|\-\-major] [\-\-pre] [\-\-strict] [\-\-conservative]
.SH "DESCRIPTION"
Update the gems specified (all gems, if \fB\-\-all\fR flag is used), ignoring the previously installed gems specified in the \fBGemfile\.lock\fR\. In general, you should use bundle install(1) \fIbundle\-install\.1\.html\fR to install the same exact gems and versions across machines\.
.P
@@ -14,10 +14,10 @@ You would use \fBbundle update\fR to explicitly update the version of a gem\.
\fB\-\-all\fR
Update all gems specified in Gemfile\.
.TP
-\fB\-\-group=<name>\fR, \fB\-g=[<name>]\fR
+\fB\-\-group=<list>\fR, \fB\-g=<list>\fR
Only update the gems in the specified group\. For instance, you can update all gems in the development group with \fBbundle update \-\-group development\fR\. You can also call \fBbundle update rails \-\-group test\fR to update the rails gem and all gems in the test group, for example\.
.TP
-\fB\-\-source=<name>\fR
+\fB\-\-source=<list>\fR
The name of a \fB:git\fR or \fB:path\fR source used in the Gemfile(5)\. For instance, with a \fB:git\fR source of \fBhttp://github\.com/rails/rails\.git\fR, you would call \fBbundle update \-\-source rails\fR
.TP
\fB\-\-local\fR
@@ -26,13 +26,19 @@ Do not attempt to fetch gems remotely and use the gem cache instead\.
\fB\-\-ruby\fR
Update the locked version of Ruby to the current version of Ruby\.
.TP
-\fB\-\-bundler\fR
+\fB\-\-bundler[=BUNDLER]\fR
Update the locked version of bundler to the invoked bundler version\.
.TP
+\fB\-\-force\fR, \fB\-\-redownload\fR
+Force reinstalling every gem, even if already installed\.
+.TP
\fB\-\-full\-index\fR
Fall back to using the single\-file index of all gems\.
.TP
-\fB\-\-jobs=[<number>]\fR, \fB\-j[<number>]\fR
+\fB\-\-gemfile=GEMFILE\fR
+Use the specified gemfile instead of [\fBGemfile(5)\fR][Gemfile(5)]\.
+.TP
+\fB\-\-jobs=<number>\fR, \fB\-j=<number>\fR
Specify the number of jobs to run in parallel\. The default is the number of available processors\.
.TP
\fB\-\-retry=[<number>]\fR
@@ -41,9 +47,6 @@ Retry failed network or git requests for \fInumber\fR times\.
\fB\-\-quiet\fR
Only output warnings and errors\.
.TP
-\fB\-\-redownload\fR
-Force downloading every gem\.
-.TP
\fB\-\-patch\fR
Prefer updating only to next patch version\.
.TP
@@ -53,6 +56,9 @@ Prefer updating only to next minor version\.
\fB\-\-major\fR
Prefer updating to next major version (default)\.
.TP
+\fB\-\-pre\fR
+Always choose the highest allowed version, regardless of prerelease status\.
+.TP
\fB\-\-strict\fR
Do not allow any gem to be updated past latest \fB\-\-patch\fR | \fB\-\-minor\fR | \fB\-\-major\fR\.
.TP
diff --git a/lib/bundler/man/bundle-update.1.ronn b/lib/bundler/man/bundle-update.1.ronn
index fe500cdc96..bfe381677c 100644
--- a/lib/bundler/man/bundle-update.1.ronn
+++ b/lib/bundler/man/bundle-update.1.ronn
@@ -9,11 +9,13 @@ bundle-update(1) -- Update your gems to the latest available versions
[--local]
[--ruby]
[--bundler[=VERSION]]
+ [--force]
[--full-index]
- [--jobs=JOBS]
+ [--gemfile=GEMFILE]
+ [--jobs=NUMBER]
[--quiet]
[--patch|--minor|--major]
- [--redownload]
+ [--pre]
[--strict]
[--conservative]
@@ -32,13 +34,13 @@ gem.
* `--all`:
Update all gems specified in Gemfile.
-* `--group=<name>`, `-g=[<name>]`:
+* `--group=<list>`, `-g=<list>`:
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=<name>`:
+* `--source=<list>`:
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`
@@ -49,13 +51,19 @@ gem.
* `--ruby`:
Update the locked version of Ruby to the current version of Ruby.
-* `--bundler`:
+* `--bundler[=BUNDLER]`:
Update the locked version of bundler to the invoked bundler version.
+* `--force`, `--redownload`:
+ Force reinstalling every gem, even if already installed.
+
* `--full-index`:
Fall back to using the single-file index of all gems.
-* `--jobs=[<number>]`, `-j[<number>]`:
+* `--gemfile=GEMFILE`:
+ Use the specified gemfile instead of [`Gemfile(5)`][Gemfile(5)].
+
+* `--jobs=<number>`, `-j=<number>`:
Specify the number of jobs to run in parallel. The default is the number of
available processors.
@@ -65,9 +73,6 @@ gem.
* `--quiet`:
Only output warnings and errors.
-* `--redownload`:
- Force downloading every gem.
-
* `--patch`:
Prefer updating only to next patch version.
@@ -77,6 +82,9 @@ gem.
* `--major`:
Prefer updating to next major version (default).
+* `--pre`:
+ Always choose the highest allowed version, regardless of prerelease status.
+
* `--strict`:
Do not allow any gem to be updated past latest `--patch` | `--minor` | `--major`.
diff --git a/lib/bundler/man/bundle-version.1 b/lib/bundler/man/bundle-version.1
index 44eaf92224..6462ec7958 100644
--- a/lib/bundler/man/bundle-version.1
+++ b/lib/bundler/man/bundle-version.1
@@ -1,6 +1,6 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-VERSION" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE\-VERSION" "1" "September 2025" ""
.SH "NAME"
\fBbundle\-version\fR \- Prints Bundler version information
.SH "SYNOPSIS"
diff --git a/lib/bundler/man/bundle-viz.1 b/lib/bundler/man/bundle-viz.1
deleted file mode 100644
index 77b902214c..0000000000
--- a/lib/bundler/man/bundle-viz.1
+++ /dev/null
@@ -1,30 +0,0 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE\-VIZ" "1" "May 2024" ""
-.SH "NAME"
-\fBbundle\-viz\fR \- Generates a visual dependency graph for your Gemfile
-.SH "SYNOPSIS"
-\fBbundle viz\fR [\-\-file=FILE] [\-\-format=FORMAT] [\-\-requirements] [\-\-version] [\-\-without=GROUP GROUP]
-.SH "DESCRIPTION"
-\fBviz\fR generates a PNG file of the current \fBGemfile(5)\fR as a dependency graph\. \fBviz\fR requires the ruby\-graphviz gem (and its dependencies)\.
-.P
-The associated gems must also be installed via \fBbundle install(1)\fR \fIbundle\-install\.1\.html\fR\.
-.P
-\fBviz\fR command was deprecated in Bundler 2\.2\. Use bundler\-graph plugin \fIhttps://github\.com/rubygems/bundler\-graph\fR instead\.
-.SH "OPTIONS"
-.TP
-\fB\-\-file\fR, \fB\-f\fR
-The name to use for the generated file\. See \fB\-\-format\fR option
-.TP
-\fB\-\-format\fR, \fB\-F\fR
-This is output format option\. Supported format is png, jpg, svg, dot \|\.\|\.\|\.
-.TP
-\fB\-\-requirements\fR, \fB\-R\fR
-Set to show the version of each required dependency\.
-.TP
-\fB\-\-version\fR, \fB\-v\fR
-Set to show each gem version\.
-.TP
-\fB\-\-without\fR, \fB\-W\fR
-Exclude gems that are part of the specified named group\.
-
diff --git a/lib/bundler/man/bundle-viz.1.ronn b/lib/bundler/man/bundle-viz.1.ronn
deleted file mode 100644
index f220256943..0000000000
--- a/lib/bundler/man/bundle-viz.1.ronn
+++ /dev/null
@@ -1,32 +0,0 @@
-bundle-viz(1) -- 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)`](bundle-install.1.html).
-
-`viz` command was deprecated in Bundler 2.2. Use [bundler-graph plugin](https://github.com/rubygems/bundler-graph) instead.
-
-## 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.
diff --git a/lib/bundler/man/bundle.1 b/lib/bundler/man/bundle.1
index 199d1ce9fd..9f7feb4133 100644
--- a/lib/bundler/man/bundle.1
+++ b/lib/bundler/man/bundle.1
@@ -1,6 +1,6 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "BUNDLE" "1" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "BUNDLE" "1" "September 2025" ""
.SH "NAME"
\fBbundle\fR \- Ruby Dependency Management
.SH "SYNOPSIS"
@@ -66,9 +66,6 @@ Open an installed gem in the editor
\fBbundle lock(1)\fR \fIbundle\-lock\.1\.html\fR
Generate a lockfile for your dependencies
.TP
-\fBbundle viz(1)\fR \fIbundle\-viz\.1\.html\fR (deprecated)
-Generate a visual representation of your dependencies
-.TP
\fBbundle init(1)\fR \fIbundle\-init\.1\.html\fR
Generate a simple \fBGemfile\fR, placed in the current directory
.TP
@@ -94,9 +91,3 @@ Manage Bundler plugins
Prints Bundler version information
.SH "PLUGINS"
When running a command that isn't listed in PRIMARY COMMANDS or UTILITIES, Bundler will try to find an executable on your path named \fBbundler\-<command>\fR and execute it, passing down any extra arguments to it\.
-.SH "OBSOLETE"
-These commands are obsolete and should no longer be used:
-.IP "\(bu" 4
-\fBbundle inject(1)\fR
-.IP "" 0
-
diff --git a/lib/bundler/man/bundle.1.ronn b/lib/bundler/man/bundle.1.ronn
index 8245effabd..1c2b3df7af 100644
--- a/lib/bundler/man/bundle.1.ronn
+++ b/lib/bundler/man/bundle.1.ronn
@@ -76,9 +76,6 @@ We divide `bundle` subcommands into primary commands and utilities:
* [`bundle lock(1)`](bundle-lock.1.html):
Generate a lockfile for your dependencies
-* [`bundle viz(1)`](bundle-viz.1.html) (deprecated):
- Generate a visual representation of your dependencies
-
* [`bundle init(1)`](bundle-init.1.html):
Generate a simple `Gemfile`, placed in the current directory
@@ -108,9 +105,3 @@ We divide `bundle` subcommands into primary commands and utilities:
When running a command that isn't listed in PRIMARY COMMANDS or UTILITIES,
Bundler will try to find an executable on your path named `bundler-<command>`
and execute it, passing down any extra arguments to it.
-
-## OBSOLETE
-
-These commands are obsolete and should no longer be used:
-
-* `bundle inject(1)`
diff --git a/lib/bundler/man/gemfile.5 b/lib/bundler/man/gemfile.5
index fa9e31f615..a8c055a0c1 100644
--- a/lib/bundler/man/gemfile.5
+++ b/lib/bundler/man/gemfile.5
@@ -1,6 +1,6 @@
-.\" generated with nRonn/v0.11.1
-.\" https://github.com/n-ronn/nronn/tree/0.11.1
-.TH "GEMFILE" "5" "May 2024" ""
+.\" generated with Ronn-NG/v0.10.1
+.\" http://github.com/apjanke/ronn-ng/tree/0.10.1
+.TH "GEMFILE" "5" "September 2025" ""
.SH "NAME"
\fBGemfile\fR \- A format for describing gem dependencies for Ruby programs
.SH "SYNOPSIS"
@@ -216,6 +216,8 @@ The following platform values are deprecated and should be replaced with \fBwind
.IP "\(bu" 4
\fBmswin\fR, \fBmswin64\fR, \fBmingw32\fR, \fBx64_mingw\fR
.IP "" 0
+.P
+Note that, while unfortunately using the same terminology, the values of this option are different from the values that \fBbundle lock \-\-add\-platform\fR can take\. The values of this option are more closer to "Ruby Implementation" while the values that \fBbundle lock \-\-add\-platform\fR understands are more related to OS and architecture of the different systems where your lockfile will be used\.
.SS "FORCE_RUBY_PLATFORM"
If you always want the pure ruby variant of a gem to be chosen over platform specific variants, you can use the \fBforce_ruby_platform\fR option:
.IP "" 4
@@ -467,4 +469,35 @@ For implicit gems (dependencies of explicit gems), any source, git, or path repo
.IP "3." 4
If neither of the above conditions are met, the global source will be used\. If multiple global sources are specified, they will be prioritized from last to first, but this is deprecated since Bundler 1\.13, so Bundler prints a warning and will abort with an error in the future\.
.IP "" 0
+.SH "LOCKFILE"
+By default, Bundler will create a lockfile by adding \fB\.lock\fR to the end of the Gemfile name\. To change this, use the \fBlockfile\fR method:
+.IP "" 4
+.nf
+lockfile "/path/to/lockfile\.lock"
+.fi
+.IP "" 0
+.P
+This is useful when you want to use different lockfiles per ruby version or platform\.
+.P
+To avoid writing a lock file, use \fBfalse\fR as the argument:
+.IP "" 4
+.nf
+lockfile false
+.fi
+.IP "" 0
+.P
+This is useful for library development and other situations where the code is expected to work with a range of dependency versions\.
+.SS "LOCKFILE PRECEDENCE"
+When determining path to the lockfile or whether to create a lockfile, the following precedence is used:
+.IP "1." 4
+The \fBbundle install\fR \fB\-\-no\-lock\fR option (which disables lockfile creation)\.
+.IP "2." 4
+The \fBbundle install\fR \fB\-\-lockfile\fR option\.
+.IP "3." 4
+The \fBBUNDLE_LOCKFILE\fR environment variable\.
+.IP "4." 4
+The \fBlockfile\fR method in the Gemfile\.
+.IP "5." 4
+The default behavior of adding \fB\.lock\fR to the end of the Gemfile name\.
+.IP "" 0
diff --git a/lib/bundler/man/gemfile.5.ronn b/lib/bundler/man/gemfile.5.ronn
index 7c1e00d13a..18d7bb826e 100644
--- a/lib/bundler/man/gemfile.5.ronn
+++ b/lib/bundler/man/gemfile.5.ronn
@@ -242,6 +242,12 @@ The following platform values are deprecated and should be replaced with `window
* `mswin`, `mswin64`, `mingw32`, `x64_mingw`
+Note that, while unfortunately using the same terminology, the values of this
+option are different from the values that `bundle lock --add-platform` can take.
+The values of this option are more closer to "Ruby Implementation" while the
+values that `bundle lock --add-platform` understands are more related to OS and
+architecture of the different systems where your lockfile will be used.
+
### FORCE_RUBY_PLATFORM
If you always want the pure ruby variant of a gem to be chosen over platform
@@ -550,3 +556,31 @@ bundler uses the following priority order:
If multiple global sources are specified, they will be prioritized from
last to first, but this is deprecated since Bundler 1.13, so Bundler prints
a warning and will abort with an error in the future.
+
+## LOCKFILE
+
+By default, Bundler will create a lockfile by adding `.lock` to the end of the
+Gemfile name. To change this, use the `lockfile` method:
+
+ lockfile "/path/to/lockfile.lock"
+
+This is useful when you want to use different lockfiles per ruby version or
+platform.
+
+To avoid writing a lock file, use `false` as the argument:
+
+ lockfile false
+
+This is useful for library development and other situations where the code is
+expected to work with a range of dependency versions.
+
+### LOCKFILE PRECEDENCE
+
+When determining path to the lockfile or whether to create a lockfile, the
+following precedence is used:
+
+1. The `bundle install` `--no-lock` option (which disables lockfile creation).
+1. The `bundle install` `--lockfile` option.
+1. The `BUNDLE_LOCKFILE` environment variable.
+1. The `lockfile` method in the Gemfile.
+1. The default behavior of adding `.lock` to the end of the Gemfile name.
diff --git a/lib/bundler/man/index.txt b/lib/bundler/man/index.txt
index 24f7633e66..f610ba852a 100644
--- a/lib/bundler/man/index.txt
+++ b/lib/bundler/man/index.txt
@@ -8,13 +8,16 @@ bundle-clean(1) bundle-clean.1
bundle-config(1) bundle-config.1
bundle-console(1) bundle-console.1
bundle-doctor(1) bundle-doctor.1
+bundle-env(1) bundle-env.1
bundle-exec(1) bundle-exec.1
+bundle-fund(1) bundle-fund.1
bundle-gem(1) bundle-gem.1
bundle-help(1) bundle-help.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-issue(1) bundle-issue.1
+bundle-licenses(1) bundle-licenses.1
bundle-list(1) bundle-list.1
bundle-lock(1) bundle-lock.1
bundle-open(1) bundle-open.1
@@ -26,4 +29,3 @@ bundle-remove(1) bundle-remove.1
bundle-show(1) bundle-show.1
bundle-update(1) bundle-update.1
bundle-version(1) bundle-version.1
-bundle-viz(1) bundle-viz.1
diff --git a/lib/bundler/match_metadata.rb b/lib/bundler/match_metadata.rb
index f6cc27df32..6fd2994a85 100644
--- a/lib/bundler/match_metadata.rb
+++ b/lib/bundler/match_metadata.rb
@@ -13,5 +13,18 @@ module Bundler
def matches_current_rubygems?
@required_rubygems_version.satisfied_by?(Gem.rubygems_version)
end
+
+ def expanded_dependencies
+ runtime_dependencies + [
+ metadata_dependency("Ruby", @required_ruby_version),
+ metadata_dependency("RubyGems", @required_rubygems_version),
+ ].compact
+ end
+
+ def metadata_dependency(name, requirement)
+ return if requirement.nil? || requirement.none?
+
+ Gem::Dependency.new("#{name}\0", requirement)
+ end
end
end
diff --git a/lib/bundler/match_platform.rb b/lib/bundler/match_platform.rb
index ece9fb8679..479818e5ec 100644
--- a/lib/bundler/match_platform.rb
+++ b/lib/bundler/match_platform.rb
@@ -1,23 +1,42 @@
# frozen_string_literal: true
-require_relative "gem_helpers"
-
module Bundler
module MatchPlatform
- include GemHelpers
+ def installable_on_platform?(target_platform) # :nodoc:
+ return true if [Gem::Platform::RUBY, nil, target_platform].include?(platform)
+ return true if Gem::Platform.new(platform) === target_platform
- def match_platform(p)
- MatchPlatform.platforms_match?(platform, p)
+ false
end
- def self.platforms_match?(gemspec_platform, local_platform)
- return true if gemspec_platform.nil?
- return true if gemspec_platform == Gem::Platform::RUBY
- return true if local_platform == gemspec_platform
- gemspec_platform = Gem::Platform.new(gemspec_platform)
- return true if gemspec_platform === local_platform
+ def self.select_best_platform_match(specs, platform, force_ruby: false, prefer_locked: false)
+ matching = select_all_platform_match(specs, platform, force_ruby: force_ruby, prefer_locked: prefer_locked)
- false
+ Gem::Platform.sort_and_filter_best_platform_match(matching, platform)
+ end
+
+ def self.select_best_local_platform_match(specs, force_ruby: false)
+ local = Bundler.local_platform
+ matching = select_all_platform_match(specs, local, force_ruby: force_ruby).filter_map(&:materialized_for_installation)
+
+ Gem::Platform.sort_best_platform_match(matching, local)
+ end
+
+ def self.select_all_platform_match(specs, platform, force_ruby: false, prefer_locked: false)
+ matching = specs.select {|spec| spec.installable_on_platform?(force_ruby ? Gem::Platform::RUBY : platform) }
+
+ specs.each(&:force_ruby_platform!) if force_ruby
+
+ if prefer_locked
+ locked_originally = matching.select {|spec| spec.is_a?(::Bundler::LazySpecification) }
+ return locked_originally if locked_originally.any?
+ end
+
+ matching
+ end
+
+ def self.generic_local_platform_is_ruby?
+ Bundler.generic_local_platform == Gem::Platform::RUBY
end
end
end
diff --git a/lib/bundler/materialization.rb b/lib/bundler/materialization.rb
new file mode 100644
index 0000000000..82e48464a7
--- /dev/null
+++ b/lib/bundler/materialization.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+module Bundler
+ #
+ # This class materializes a set of resolved specifications (`LazySpecification`)
+ # for a given gem into the most appropriate real specifications
+ # (`StubSepecification`, `EndpointSpecification`, etc), given a dependency and a
+ # target platform.
+ #
+ class Materialization
+ def initialize(dep, platform, candidates:)
+ @dep = dep
+ @platform = platform
+ @candidates = candidates
+ end
+
+ def complete?
+ specs.any?
+ end
+
+ def specs
+ @specs ||= if @candidates.nil?
+ []
+ elsif platform
+ MatchPlatform.select_best_platform_match(@candidates, platform, force_ruby: dep.force_ruby_platform)
+ else
+ MatchPlatform.select_best_local_platform_match(@candidates, force_ruby: dep.force_ruby_platform || dep.default_force_ruby_platform)
+ end
+ end
+
+ def dependencies
+ (materialized_spec || specs.first).runtime_dependencies.map {|d| [d, platform] }
+ end
+
+ def materialized_spec
+ specs.reject(&:missing?).first&.materialization
+ end
+
+ def completely_missing_specs
+ return [] unless specs.all?(&:missing?)
+
+ specs
+ end
+
+ def partially_missing_specs
+ specs.select(&:missing?)
+ end
+
+ def incomplete_specs
+ return [] if complete?
+
+ @candidates || LazySpecification.new(dep.name, nil, nil)
+ end
+
+ private
+
+ attr_reader :dep, :platform
+ end
+end
diff --git a/lib/bundler/plugin.rb b/lib/bundler/plugin.rb
index 588fa79be8..fd6da6cf6d 100644
--- a/lib/bundler/plugin.rb
+++ b/lib/bundler/plugin.rb
@@ -195,7 +195,7 @@ module Bundler
@sources[name]
end
- # @param [Hash] The options that are present in the lock file
+ # @param [Hash] The options that are present in the lockfile
# @return [API::Source] the instance of the class that handles the source
# type passed in locked_opts
def from_lock(locked_opts)
@@ -220,7 +220,7 @@ module Bundler
#
# @param [String] event
def hook(event, *args, &arg_blk)
- return unless Bundler.feature_flag.plugins?
+ return unless Bundler.settings[:plugins]
unless Events.defined_event?(event)
raise ArgumentError, "Event '#{event}' not defined in Bundler::Plugin::Events"
end
@@ -342,7 +342,26 @@ module Bundler
# done to avoid conflicts
path = index.plugin_path(name)
- Gem.add_to_load_path(*index.load_paths(name))
+ paths = index.load_paths(name)
+ invalid_paths = paths.reject {|p| File.directory?(p) }
+
+ if invalid_paths.any?
+ Bundler.ui.warn <<~MESSAGE
+ The following plugin paths don't exist: #{invalid_paths.join(", ")}.
+
+ This can happen if the plugin was installed with a different version of Ruby that has since been uninstalled.
+
+ If you would like to reinstall the plugin, run:
+
+ bundler plugin uninstall #{name} && bundler plugin install #{name}
+
+ Continuing without installing plugin #{name}.
+ MESSAGE
+
+ return
+ end
+
+ Gem.add_to_load_path(*paths)
load path.join(PLUGIN_FILE_NAME)
diff --git a/lib/bundler/plugin/api/source.rb b/lib/bundler/plugin/api/source.rb
index 8563ee358a..6c888d0373 100644
--- a/lib/bundler/plugin/api/source.rb
+++ b/lib/bundler/plugin/api/source.rb
@@ -67,7 +67,7 @@ module Bundler
# to check out same version of gem later.
#
# There options are passed when the source plugin is created from the
- # lock file.
+ # lockfile.
#
# @return [Hash]
def options_to_lock
@@ -131,7 +131,7 @@ module Bundler
Bundler::Index.build do |index|
files.each do |file|
next unless spec = Bundler.load_gemspec(file)
- Bundler.rubygems.set_installed_by_version(spec)
+ spec.installed_by_version = Gem::VERSION
spec.source = self
Bundler.rubygems.validate(spec)
@@ -196,6 +196,7 @@ module Bundler
FileUtils.rm_rf(new_cache_path)
FileUtils.cp_r(install_path, new_cache_path)
+ FileUtils.rm_rf(app_cache_path.join(".git"))
FileUtils.touch(app_cache_path.join(".bundlecache"))
end
diff --git a/lib/bundler/plugin/index.rb b/lib/bundler/plugin/index.rb
index c2ab8f90da..0682d37772 100644
--- a/lib/bundler/plugin/index.rb
+++ b/lib/bundler/plugin/index.rb
@@ -31,9 +31,13 @@ module Bundler
begin
load_index(global_index_file, true)
- rescue GenericSystemCallError
+ rescue PermissionError
# no need to fail when on a read-only FS, for example
nil
+ rescue ArgumentError => e
+ # ruby 3.4 checks writability in Dir.tmpdir
+ raise unless e.message&.include?("could not find a temporary directory")
+ nil
end
load_index(local_index_file) if SharedHelpers.in_bundle?
end
diff --git a/lib/bundler/plugin/installer.rb b/lib/bundler/plugin/installer.rb
index 4f60862bb4..853ad9edca 100644
--- a/lib/bundler/plugin/installer.rb
+++ b/lib/bundler/plugin/installer.rb
@@ -34,7 +34,7 @@ module Bundler
# @return [Hash] map of names to their specs they are installed with
def install_definition(definition)
def definition.lock(*); end
- definition.resolve_remotely!
+ definition.remotely!
specs = definition.specs
install_from_specs specs
@@ -43,16 +43,6 @@ module Bundler
private
def check_sources_consistency!(options)
- if options.key?(:git) && options.key?(:local_git)
- raise InvalidOption, "Remote and local plugin git sources can't be both specified"
- end
-
- # back-compat; local_git is an alias for git
- if options.key?(:local_git)
- Bundler::SharedHelpers.major_deprecation(2, "--local_git is deprecated, use --git")
- options[:git] = options.delete(:local_git)
- end
-
if (options.keys & [:source, :git, :path]).length > 1
raise InvalidOption, "Only one of --source, --git, or --path may be specified"
end
diff --git a/lib/bundler/plugin/installer/path.rb b/lib/bundler/plugin/installer/path.rb
index 58a8fa7426..58c4924eb0 100644
--- a/lib/bundler/plugin/installer/path.rb
+++ b/lib/bundler/plugin/installer/path.rb
@@ -8,6 +8,14 @@ module Bundler
SharedHelpers.in_bundle? ? Bundler.root : Plugin.root
end
+ def eql?(other)
+ return unless other.class == self.class
+ expanded_original_path == other.expanded_original_path &&
+ version == other.version
+ end
+
+ alias_method :==, :eql?
+
def generate_bin(spec, disable_extensions = false)
# Need to find a way without code duplication
# For now, we can ignore this
diff --git a/lib/bundler/plugin/source_list.rb b/lib/bundler/plugin/source_list.rb
index 746996de55..d929ade29e 100644
--- a/lib/bundler/plugin/source_list.rb
+++ b/lib/bundler/plugin/source_list.rb
@@ -23,7 +23,7 @@ module Bundler
private
- def rubygems_aggregate_class
+ def source_class
Plugin::Installer::Rubygems
end
end
diff --git a/lib/bundler/process_lock.rb b/lib/bundler/process_lock.rb
index 0297f80e2c..784b17e363 100644
--- a/lib/bundler/process_lock.rb
+++ b/lib/bundler/process_lock.rb
@@ -2,23 +2,19 @@
module Bundler
class ProcessLock
- def self.lock(bundle_path = Bundler.bundle_path)
+ def self.lock(bundle_path = Bundler.bundle_path, &block)
lock_file_path = File.join(bundle_path, "bundler.lock")
- has_lock = false
+ base_lock_file_path = lock_file_path.delete_suffix(".lock")
- File.open(lock_file_path, "w") do |f|
- f.flock(File::LOCK_EX)
- has_lock = true
- yield
- f.flock(File::LOCK_UN)
+ require "fileutils" if Bundler.rubygems.provides?("< 3.6.0")
+
+ begin
+ SharedHelpers.filesystem_access(lock_file_path, :write) do
+ Gem.open_file_with_lock(base_lock_file_path, &block)
+ end
+ rescue PermissionError
+ block.call
end
- rescue Errno::EACCES, Errno::ENOLCK, Errno::ENOTSUP, Errno::EPERM, Errno::EROFS
- # 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.
- yield
- ensure
- FileUtils.rm_f(lock_file_path) if has_lock
end
end
end
diff --git a/lib/bundler/remote_specification.rb b/lib/bundler/remote_specification.rb
index 9d237f3fa0..ab163e2b04 100644
--- a/lib/bundler/remote_specification.rb
+++ b/lib/bundler/remote_specification.rb
@@ -12,7 +12,7 @@ module Bundler
attr_reader :name, :version, :platform
attr_writer :dependencies
- attr_accessor :source, :remote
+ attr_accessor :source, :remote, :locked_platform
def initialize(name, version, platform, spec_fetcher)
@name = name
@@ -21,6 +21,11 @@ module Bundler
@platform = Gem::Platform.new(platform)
@spec_fetcher = spec_fetcher
@dependencies = nil
+ @locked_platform = nil
+ end
+
+ def insecurely_materialized?
+ @locked_platform.to_s != @platform.to_s
end
# Needed before installs, since the arch matters then and quick
diff --git a/lib/bundler/resolver.rb b/lib/bundler/resolver.rb
index 1a6711ea6f..1dbf565d46 100644
--- a/lib/bundler/resolver.rb
+++ b/lib/bundler/resolver.rb
@@ -12,13 +12,13 @@ module Bundler
require_relative "resolver/candidate"
require_relative "resolver/incompatibility"
require_relative "resolver/root"
+ require_relative "resolver/strategy"
- include GemHelpers
-
- def initialize(base, gem_version_promoter)
+ def initialize(base, gem_version_promoter, most_specific_locked_platform = nil)
@source_requirements = base.source_requirements
@base = base
@gem_version_promoter = gem_version_promoter
+ @most_specific_locked_platform = most_specific_locked_platform
end
def start
@@ -77,15 +77,16 @@ module Bundler
end
def solve_versions(root:, logger:)
- solver = PubGrub::VersionSolver.new(source: self, root: root, logger: logger)
+ solver = PubGrub::VersionSolver.new(source: self, root: root, strategy: Strategy.new(self), logger: logger)
result = solver.solve
- result.map {|package, version| version.to_specs(package) }.flatten.uniq
+ resolved_specs = result.flat_map {|package, version| version.to_specs(package, @most_specific_locked_platform) }
+ SpecSet.new(resolved_specs).specs_with_additional_variants_from(@base.locked_specs)
rescue PubGrub::SolveFailure => e
incompatibility = e.incompatibility
- names_to_unlock, names_to_allow_prereleases_for, extended_explanation = find_names_to_relax(incompatibility)
+ names_to_unlock, names_to_allow_prereleases_for, names_to_allow_remote_specs_for, extended_explanation = find_names_to_relax(incompatibility)
- names_to_relax = names_to_unlock + names_to_allow_prereleases_for
+ names_to_relax = names_to_unlock + names_to_allow_prereleases_for + names_to_allow_remote_specs_for
if names_to_relax.any?
if names_to_unlock.any?
@@ -95,11 +96,17 @@ module Bundler
end
if names_to_allow_prereleases_for.any?
- Bundler.ui.debug "Found conflicts with dependencies with prereleases. Will retrying considering prereleases for #{names_to_allow_prereleases_for.join(", ")}...", true
+ Bundler.ui.debug "Found conflicts with dependencies with prereleases. Will retry considering prereleases for #{names_to_allow_prereleases_for.join(", ")}...", true
@base.include_prereleases(names_to_allow_prereleases_for)
end
+ if names_to_allow_remote_specs_for.any?
+ Bundler.ui.debug "Found conflicts with local versions of #{names_to_allow_remote_specs_for.join(", ")}. Will retry considering remote versions...", true
+
+ @base.include_remote_specs(names_to_allow_remote_specs_for)
+ end
+
root, logger = setup_solver
Bundler.ui.debug "Retrying resolution...", true
@@ -119,6 +126,7 @@ module Bundler
def find_names_to_relax(incompatibility)
names_to_unlock = []
names_to_allow_prereleases_for = []
+ names_to_allow_remote_specs_for = []
extended_explanation = nil
while incompatibility.conflict?
@@ -133,6 +141,8 @@ module Bundler
names_to_unlock << name
elsif package.ignores_prereleases? && @all_specs[name].any? {|s| s.version.prerelease? }
names_to_allow_prereleases_for << name
+ elsif package.prefer_local? && @all_specs[name].any? {|s| !s.is_a?(StubSpecification) }
+ names_to_allow_remote_specs_for << name
end
no_versions_incompat = [cause.incompatibility, cause.satisfier].find {|incompat| incompat.cause.is_a?(PubGrub::Incompatibility::NoVersions) }
@@ -142,7 +152,7 @@ module Bundler
end
end
- [names_to_unlock.uniq, names_to_allow_prereleases_for.uniq, extended_explanation]
+ [names_to_unlock.uniq, names_to_allow_prereleases_for.uniq, names_to_allow_remote_specs_for.uniq, extended_explanation]
end
def parse_dependency(package, dependency)
@@ -155,16 +165,8 @@ module Bundler
PubGrub::VersionConstraint.new(package, range: range)
end
- def versions_for(package, range=VersionRange.any)
- versions = select_sorted_versions(package, range)
-
- # Conditional avoids (among other things) calling
- # sort_versions_by_preferred with the root package
- if versions.size > 1
- sort_versions_by_preferred(package, versions)
- else
- versions
- end
+ def versions_for(package, range = VersionRange.any)
+ range.select_versions(@sorted_versions[package])
end
def no_versions_incompatibility_for(package, unsatisfied_term)
@@ -226,7 +228,7 @@ module Bundler
sorted_versions[high]
end
- range = PubGrub::VersionRange.new(min: low, max: high, include_min: true)
+ range = PubGrub::VersionRange.new(min: low, max: high, include_min: !low.nil?)
self_constraint = PubGrub::VersionConstraint.new(package, range: range)
@@ -243,7 +245,7 @@ module Bundler
def all_versions_for(package)
name = package.name
- results = (@base[name] + filter_prereleases(@all_specs[name], package)).uniq {|spec| [spec.version.hash, spec.platform] }
+ results = (@base[name] + filter_specs(@all_specs[name], package)).uniq {|spec| [spec.version.hash, spec.platform] }
if name == "bundler" && !bundler_pinned_to_current_version?
bundler_spec = Gem.loaded_specs["bundler"]
@@ -254,7 +256,7 @@ module Bundler
results = filter_matching_specs(results, locked_requirement) if locked_requirement
results.group_by(&:version).reduce([]) do |groups, (version, specs)|
- platform_specs = package.platforms.map {|platform| select_best_platform_match(specs, platform) }
+ platform_specs = package.platform_specs(specs)
# If package is a top-level dependency,
# candidate is only valid if there are matching versions for all resolution platforms.
@@ -269,14 +271,22 @@ module Bundler
next groups if platform_specs.all?(&:empty?)
end
- platform_specs.flatten!
+ ruby_specs = MatchPlatform.select_best_platform_match(specs, Gem::Platform::RUBY)
+ ruby_group = Resolver::SpecGroup.new(ruby_specs)
- ruby_specs = select_best_platform_match(specs, Gem::Platform::RUBY)
- groups << Resolver::Candidate.new(version, specs: ruby_specs) if ruby_specs.any?
+ unless ruby_group.empty?
+ platform_specs.each do |s|
+ ruby_group.merge(Resolver::SpecGroup.new(s))
+ end
- next groups if platform_specs == ruby_specs || package.force_ruby_platform?
+ groups << Resolver::Candidate.new(version, group: ruby_group, priority: -1)
+ next groups if package.force_ruby_platform?
+ end
- groups << Resolver::Candidate.new(version, specs: platform_specs)
+ platform_group = Resolver::SpecGroup.new(platform_specs.flatten.uniq)
+ next groups if platform_group == ruby_group
+
+ groups << Resolver::Candidate.new(version, group: platform_group, priority: 1)
groups
end
@@ -300,6 +310,16 @@ module Bundler
"Gemfile"
end
+ def raise_incomplete!(incomplete_specs)
+ raise_not_found!(@base.get_package(incomplete_specs.first.name))
+ end
+
+ def sort_versions_by_preferred(package, versions)
+ @gem_version_promoter.sort_versions(package, versions)
+ end
+
+ private
+
def raise_not_found!(package)
name = package.name
source = source_for(name)
@@ -336,8 +356,6 @@ module Bundler
raise GemNotFound, message
end
- private
-
def filtered_versions_for(package)
@gem_version_promoter.filter_versions(package, @all_versions[package])
end
@@ -359,12 +377,31 @@ module Bundler
end
end
+ def filter_specs(specs, package)
+ filter_remote_specs(filter_prereleases(specs, package), package)
+ end
+
def filter_prereleases(specs, package)
return specs unless package.ignores_prereleases? && specs.size > 1
specs.reject {|s| s.version.prerelease? }
end
+ def filter_remote_specs(specs, package)
+ if package.prefer_local?
+ local_specs = specs.select {|s| s.is_a?(StubSpecification) }
+
+ if local_specs.empty?
+ package.consider_remote_versions!
+ specs
+ else
+ local_specs
+ end
+ else
+ specs
+ end
+ end
+
# Ignore versions that depend on themselves incorrectly
def filter_invalid_self_dependencies(specs, name)
specs.reject do |s|
@@ -376,10 +413,6 @@ module Bundler
requirement.satisfied_by?(spec.version) || spec.source.is_a?(Source::Gemspec)
end
- def sort_versions_by_preferred(package, versions)
- @gem_version_promoter.sort_versions(package, versions)
- end
-
def repository_for(package)
source_for(package.name)
end
@@ -389,18 +422,21 @@ module Bundler
end
def prepare_dependencies(requirements, packages)
- to_dependency_hash(requirements, packages).map do |dep_package, dep_constraint|
+ to_dependency_hash(requirements, packages).filter_map do |dep_package, dep_constraint|
name = dep_package.name
next [dep_package, dep_constraint] if name == "bundler"
dep_range = dep_constraint.range
- versions = select_sorted_versions(dep_package, dep_range)
- if versions.empty? && dep_package.ignores_prereleases?
- @all_versions.delete(dep_package)
- @sorted_versions.delete(dep_package)
- dep_package.consider_prereleases!
- versions = select_sorted_versions(dep_package, dep_range)
+ versions = versions_for(dep_package, dep_range)
+ if versions.empty?
+ if dep_package.ignores_prereleases? || dep_package.prefer_local?
+ @all_versions.delete(dep_package)
+ @sorted_versions.delete(dep_package)
+ end
+ dep_package.consider_prereleases! if dep_package.ignores_prereleases?
+ dep_package.consider_remote_versions! if dep_package.prefer_local?
+ versions = versions_for(dep_package, dep_range)
end
if versions.empty? && select_all_versions(dep_package, dep_range).any?
@@ -412,11 +448,7 @@ module Bundler
next unless dep_package.current_platform?
raise_not_found!(dep_package)
- end.compact.to_h
- end
-
- def select_sorted_versions(package, range)
- range.select_versions(@sorted_versions[package])
+ end.to_h
end
def select_all_versions(package, range)
@@ -431,8 +463,8 @@ module Bundler
def requirement_to_range(requirement)
ranges = requirement.requirements.map do |(op, version)|
- ver = Resolver::Candidate.new(version).generic!
- platform_ver = Resolver::Candidate.new(version).platform_specific!
+ ver = Resolver::Candidate.new(version, priority: -1)
+ platform_ver = Resolver::Candidate.new(version, priority: 1)
case op
when "~>"
diff --git a/lib/bundler/resolver/base.rb b/lib/bundler/resolver/base.rb
index ad19eeb3f4..932a92ff41 100644
--- a/lib/bundler/resolver/base.rb
+++ b/lib/bundler/resolver/base.rb
@@ -5,10 +5,11 @@ require_relative "package"
module Bundler
class Resolver
class Base
- attr_reader :packages, :requirements, :source_requirements
+ attr_reader :packages, :requirements, :source_requirements, :locked_specs
def initialize(source_requirements, dependencies, base, platforms, options)
@source_requirements = source_requirements
+ @locked_specs = options[:locked_specs]
@base = base
@@ -16,7 +17,7 @@ module Bundler
hash[name] = Package.new(name, platforms, **options)
end
- @requirements = dependencies.map do |dep|
+ @requirements = dependencies.filter_map do |dep|
dep_platforms = dep.gem_platforms(platforms)
# Dependencies scoped to external platforms are ignored
@@ -27,7 +28,7 @@ module Bundler
@packages[name] = Package.new(name, dep_platforms, **options.merge(dependency: dep))
dep
- end.compact
+ end
end
def [](name)
@@ -68,6 +69,12 @@ module Bundler
end
end
+ def include_remote_specs(names)
+ names.each do |name|
+ get_package(name).consider_remote_versions!
+ end
+ end
+
private
def indirect_pins(names)
@@ -97,6 +104,10 @@ module Bundler
def build_base_requirements
base_requirements = {}
@base.each do |ls|
+ if ls.source_changed? && ls.source.specs.search(ls.name).empty?
+ raise GemNotFound, "Could not find gem '#{ls.name}' in #{ls.source}"
+ end
+
req = Gem::Requirement.new(ls.version)
base_requirements[ls.name] = req
end
diff --git a/lib/bundler/resolver/candidate.rb b/lib/bundler/resolver/candidate.rb
index 9e8b913335..5298b2530f 100644
--- a/lib/bundler/resolver/candidate.rb
+++ b/lib/bundler/resolver/candidate.rb
@@ -17,39 +17,27 @@ module Bundler
# Some candidates may also keep some information explicitly about the
# package they refer to. These candidates are referred to as "canonical" and
# are used when materializing resolution results back into RubyGems
- # specifications that can be installed, written to lock files, and so on.
+ # specifications that can be installed, written to lockfiles, and so on.
#
class Candidate
include Comparable
attr_reader :version
- def initialize(version, specs: [])
- @spec_group = Resolver::SpecGroup.new(specs)
+ def initialize(version, group: nil, priority: -1)
+ @spec_group = group || SpecGroup.new([])
@version = Gem::Version.new(version)
- @ruby_only = specs.map(&:platform).uniq == [Gem::Platform::RUBY]
+ @priority = priority
end
def dependencies
@spec_group.dependencies
end
- def to_specs(package)
+ def to_specs(package, most_specific_locked_platform)
return [] if package.meta?
- @spec_group.to_specs(package.force_ruby_platform?)
- end
-
- def generic!
- @ruby_only = true
-
- self
- end
-
- def platform_specific!
- @ruby_only = false
-
- self
+ @spec_group.to_specs(package.force_ruby_platform?, most_specific_locked_platform)
end
def prerelease?
@@ -60,35 +48,38 @@ module Bundler
@version.segments
end
- def sort_obj
- [@version, @ruby_only ? -1 : 1]
- end
-
def <=>(other)
return unless other.is_a?(self.class)
- sort_obj <=> other.sort_obj
+ version_comparison = version <=> other.version
+ return version_comparison unless version_comparison.zero?
+
+ priority <=> other.priority
end
def ==(other)
return unless other.is_a?(self.class)
- sort_obj == other.sort_obj
+ version == other.version && priority == other.priority
end
def eql?(other)
return unless other.is_a?(self.class)
- sort_obj.eql?(other.sort_obj)
+ version.eql?(other.version) && priority.eql?(other.priority)
end
def hash
- sort_obj.hash
+ [@version, @priority].hash
end
def to_s
@version.to_s
end
+
+ protected
+
+ attr_reader :priority
end
end
end
diff --git a/lib/bundler/resolver/package.rb b/lib/bundler/resolver/package.rb
index 0461328683..3906be3f57 100644
--- a/lib/bundler/resolver/package.rb
+++ b/lib/bundler/resolver/package.rb
@@ -15,14 +15,24 @@ module Bundler
class Package
attr_reader :name, :platforms, :dependency, :locked_version
- def initialize(name, platforms, locked_specs:, unlock:, prerelease: false, dependency: nil)
+ def initialize(name, platforms, locked_specs:, unlock:, prerelease: false, prefer_local: false, dependency: nil, new_platforms: [])
@name = name
@platforms = platforms
- @locked_version = locked_specs[name].first&.version
+ @locked_version = locked_specs.version_for(name)
@unlock = unlock
@dependency = dependency || Dependency.new(name, @locked_version)
+ @platforms |= [Gem::Platform::RUBY] if @dependency.default_force_ruby_platform
@top_level = !dependency.nil?
@prerelease = @dependency.prerelease? || @locked_version&.prerelease? || prerelease ? :consider_first : :ignore
+ @prefer_local = prefer_local
+ @new_platforms = new_platforms
+ end
+
+ def platform_specs(specs)
+ platforms.map do |platform|
+ prefer_locked = @new_platforms.include?(platform) ? false : !unlock?
+ MatchPlatform.select_best_platform_match(specs, platform, prefer_locked: prefer_locked)
+ end
end
def to_s
@@ -50,7 +60,7 @@ module Bundler
end
def unlock?
- @unlock.empty? || @unlock.include?(name)
+ @unlock == true || @unlock.include?(name)
end
def ignores_prereleases?
@@ -65,6 +75,14 @@ module Bundler
@prerelease = :consider_last
end
+ def prefer_local?
+ @prefer_local
+ end
+
+ def consider_remote_versions!
+ @prefer_local = false
+ end
+
def force_ruby_platform?
@dependency.force_ruby_platform
end
diff --git a/lib/bundler/resolver/spec_group.rb b/lib/bundler/resolver/spec_group.rb
index 5cee444e5e..ac6ba86c4c 100644
--- a/lib/bundler/resolver/spec_group.rb
+++ b/lib/bundler/resolver/spec_group.rb
@@ -3,6 +3,8 @@
module Bundler
class Resolver
class SpecGroup
+ attr_reader :specs
+
def initialize(specs)
@specs = specs
end
@@ -23,10 +25,11 @@ module Bundler
@source ||= exemplary_spec.source
end
- def to_specs(force_ruby_platform)
+ def to_specs(force_ruby_platform, most_specific_locked_platform)
@specs.map do |s|
lazy_spec = LazySpecification.from_spec(s)
lazy_spec.force_ruby_platform = force_ruby_platform
+ lazy_spec.most_specific_locked_platform = most_specific_locked_platform
lazy_spec
end
end
@@ -36,43 +39,35 @@ module Bundler
end
def dependencies
- @dependencies ||= @specs.map do |spec|
- __dependencies(spec) + metadata_dependencies(spec)
- end.flatten.uniq
+ @dependencies ||= @specs.flat_map(&:expanded_dependencies).uniq.sort
end
- protected
-
- def sorted_spec_names
- @sorted_spec_names ||= @specs.map(&:full_name).sort
+ def ==(other)
+ sorted_spec_names == other.sorted_spec_names
end
- private
+ def merge(other)
+ return false unless equivalent?(other)
- def exemplary_spec
- @specs.first
- end
+ @specs |= other.specs
- def __dependencies(spec)
- dependencies = []
- spec.dependencies.each do |dep|
- next if dep.type == :development
- dependencies << Dependency.new(dep.name, dep.requirement)
- end
- dependencies
+ true
end
- def metadata_dependencies(spec)
- [
- metadata_dependency("Ruby", spec.required_ruby_version),
- metadata_dependency("RubyGems", spec.required_rubygems_version),
- ].compact
+ protected
+
+ def sorted_spec_names
+ @specs.map(&:full_name).sort
end
- def metadata_dependency(name, requirement)
- return if requirement.nil? || requirement.none?
+ private
+
+ def equivalent?(other)
+ name == other.name && version == other.version && source == other.source && dependencies == other.dependencies
+ end
- Dependency.new("#{name}\0", requirement)
+ def exemplary_spec
+ @specs.first
end
end
end
diff --git a/lib/bundler/resolver/strategy.rb b/lib/bundler/resolver/strategy.rb
new file mode 100644
index 0000000000..4f343bf0ce
--- /dev/null
+++ b/lib/bundler/resolver/strategy.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Bundler
+ class Resolver
+ class Strategy
+ def initialize(source)
+ @source = source
+ end
+
+ def next_package_and_version(unsatisfied)
+ package, range = next_term_to_try_from(unsatisfied)
+
+ [package, most_preferred_version_of(package, range).first]
+ end
+
+ private
+
+ def next_term_to_try_from(unsatisfied)
+ unsatisfied.min_by do |package, range|
+ matching_versions = @source.versions_for(package, range)
+ higher_versions = @source.versions_for(package, range.upper_invert)
+
+ [matching_versions.count <= 1 ? 0 : 1, higher_versions.count]
+ end
+ end
+
+ def most_preferred_version_of(package, range)
+ versions = @source.versions_for(package, range)
+
+ # Conditional avoids (among other things) calling
+ # sort_versions_by_preferred with the root package
+ if versions.size > 1
+ @source.sort_versions_by_preferred(package, versions)
+ else
+ versions
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bundler/retry.rb b/lib/bundler/retry.rb
index b95c42c361..090cb7e2ca 100644
--- a/lib/bundler/retry.rb
+++ b/lib/bundler/retry.rb
@@ -50,7 +50,7 @@ module Bundler
end
return true unless name
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?
+ Bundler.ui.warn "Retrying #{name} due to error (#{current_run.next}/#{total_runs}): #{e.class} #{e.message}", true
end
def keep_trying?
diff --git a/lib/bundler/ruby_dsl.rb b/lib/bundler/ruby_dsl.rb
index fb4b79c4df..5e52f38c8f 100644
--- a/lib/bundler/ruby_dsl.rb
+++ b/lib/bundler/ruby_dsl.rb
@@ -42,12 +42,26 @@ module Bundler
# Loads the file relative to the dirname of the Gemfile itself.
def normalize_ruby_file(filename)
file_content = Bundler.read_file(gemfile.dirname.join(filename))
- # match "ruby-3.2.2" or "ruby 3.2.2" capturing version string up to the first space or comment
- if /^ruby(-|\s+)([^\s#]+)/.match(file_content)
- $2
+ # match "ruby-3.2.2", ruby = "3.2.2", ruby = '3.2.2' or "ruby 3.2.2" capturing version string up to the first space or comment
+ version_match = /^ # Start of line
+ ruby # Literal "ruby"
+ [\s-]* # Optional whitespace or hyphens (for "ruby-3.2.2" format)
+ (?:=\s*)? # Optional equals sign with whitespace (for ruby = "3.2.2" format)
+ (?:
+ "([^"]+)" # Double quoted version
+ |
+ '([^']+)' # Single quoted version
+ |
+ ([^\s#"']+) # Unquoted version
+ )
+ /x.match(file_content)
+ if version_match
+ version_match[1] || version_match[2] || version_match[3]
else
file_content.strip
end
+ rescue Errno::ENOENT
+ raise GemfileError, "Could not find version file #{filename}"
end
end
end
diff --git a/lib/bundler/ruby_version.rb b/lib/bundler/ruby_version.rb
index 7e9e072b83..7f60dde476 100644
--- a/lib/bundler/ruby_version.rb
+++ b/lib/bundler/ruby_version.rb
@@ -23,7 +23,13 @@ module Bundler
# specified must match the version.
@versions = Array(versions).map do |v|
- op, v = Gem::Requirement.parse(normalize_version(v))
+ normalized_v = normalize_version(v)
+
+ unless Gem::Requirement::PATTERN.match?(normalized_v)
+ raise InvalidArgumentError, "#{v} is not a valid requirement on the Ruby version"
+ end
+
+ op, v = Gem::Requirement.parse(normalized_v)
op == "=" ? v.to_s : "#{op} #{v}"
end
@@ -37,7 +43,6 @@ module Bundler
def to_s(versions = self.versions)
output = String.new("ruby #{versions_string(versions)}")
- output << "p#{patchlevel}" if patchlevel && patchlevel != "-1"
output << " (#{engine} #{versions_string(engine_versions)})" unless engine == "ruby"
output
@@ -66,8 +71,7 @@ module Bundler
def ==(other)
versions == other.versions &&
engine == other.engine &&
- engine_versions == other.engine_versions &&
- patchlevel == other.patchlevel
+ engine_versions == other.engine_versions
end
def host
diff --git a/lib/bundler/rubygems_ext.rb b/lib/bundler/rubygems_ext.rb
index 18180a81a1..fedf44b0e6 100644
--- a/lib/bundler/rubygems_ext.rb
+++ b/lib/bundler/rubygems_ext.rb
@@ -13,15 +13,6 @@ require "rubygems" unless defined?(Gem)
# `Gem::Source` from the redefined `Gem::Specification#source`.
require "rubygems/source"
-# Cherry-pick fixes to `Gem.ruby_version` to be useful for modern Bundler
-# versions and ignore patchlevels
-# (https://github.com/rubygems/rubygems/pull/5472,
-# https://github.com/rubygems/rubygems/pull/5486). May be removed once RubyGems
-# 3.3.12 support is dropped.
-unless Gem.ruby_version.to_s == RUBY_VERSION || RUBY_PATCHLEVEL == -1
- Gem.instance_variable_set(:@ruby_version, Gem::Version.new(RUBY_VERSION))
-end
-
module Gem
# Can be removed once RubyGems 3.5.11 support is dropped
unless Gem.respond_to?(:freebsd_platform?)
@@ -30,23 +21,185 @@ module Gem
end
end
+ # Can be removed once RubyGems 3.5.18 support is dropped
+ unless Gem.respond_to?(:open_file_with_lock)
+ class << self
+ remove_method :open_file_with_flock if Gem.respond_to?(:open_file_with_flock)
+
+ def open_file_with_flock(path, &block)
+ # read-write mode is used rather than read-only in order to support NFS
+ mode = IO::RDWR | IO::APPEND | IO::CREAT | IO::BINARY
+ mode |= IO::SHARE_DELETE if IO.const_defined?(:SHARE_DELETE)
+
+ File.open(path, mode) do |io|
+ begin
+ io.flock(File::LOCK_EX)
+ rescue Errno::ENOSYS, Errno::ENOTSUP
+ end
+ yield io
+ end
+ end
+
+ def open_file_with_lock(path, &block)
+ file_lock = "#{path}.lock"
+ open_file_with_flock(file_lock, &block)
+ ensure
+ FileUtils.rm_f file_lock
+ end
+ end
+ end
+
+ require "rubygems/platform"
+
+ class Platform
+ # Can be removed once RubyGems 3.6.9 support is dropped
+ unless respond_to?(:generic)
+ JAVA = Gem::Platform.new("java") # :nodoc:
+ MSWIN = Gem::Platform.new("mswin32") # :nodoc:
+ MSWIN64 = Gem::Platform.new("mswin64") # :nodoc:
+ MINGW = Gem::Platform.new("x86-mingw32") # :nodoc:
+ X64_MINGW_LEGACY = Gem::Platform.new("x64-mingw32") # :nodoc:
+ X64_MINGW = Gem::Platform.new("x64-mingw-ucrt") # :nodoc:
+ UNIVERSAL_MINGW = Gem::Platform.new("universal-mingw") # :nodoc:
+ WINDOWS = [MSWIN, MSWIN64, UNIVERSAL_MINGW].freeze # :nodoc:
+ X64_LINUX = Gem::Platform.new("x86_64-linux") # :nodoc:
+ X64_LINUX_MUSL = Gem::Platform.new("x86_64-linux-musl") # :nodoc:
+
+ GENERICS = [JAVA, *WINDOWS].freeze # :nodoc:
+ private_constant :GENERICS
+
+ GENERIC_CACHE = GENERICS.each_with_object({}) {|g, h| h[g] = g } # :nodoc:
+ private_constant :GENERIC_CACHE
+
+ class << self
+ ##
+ # Returns the generic platform for the given platform.
+
+ def generic(platform)
+ return Gem::Platform::RUBY if platform.nil? || platform == Gem::Platform::RUBY
+
+ GENERIC_CACHE[platform] ||= begin
+ found = GENERICS.find do |match|
+ platform === match
+ end
+ found || Gem::Platform::RUBY
+ end
+ end
+
+ ##
+ # Returns the platform specificity match for the given spec platform and user platform.
+
+ def platform_specificity_match(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
+
+ os_match(spec_platform, user_platform) +
+ cpu_match(spec_platform, user_platform) * 10 +
+ version_match(spec_platform, user_platform) * 100
+ end
+
+ ##
+ # Sorts and filters the best platform match for the given matching specs and platform.
+
+ def sort_and_filter_best_platform_match(matching, platform)
+ return matching if matching.one?
+
+ exact = matching.select {|spec| spec.platform == platform }
+ return exact if exact.any?
+
+ sorted_matching = sort_best_platform_match(matching, platform)
+ exemplary_spec = sorted_matching.first
+
+ sorted_matching.take_while {|spec| same_specificity?(platform, spec, exemplary_spec) && same_deps?(spec, exemplary_spec) }
+ end
+
+ ##
+ # Sorts the best platform match for the given matching specs and platform.
+
+ def sort_best_platform_match(matching, platform)
+ matching.sort_by.with_index do |spec, i|
+ [
+ platform_specificity_match(spec.platform, platform),
+ i, # for stable sort
+ ]
+ end
+ end
+
+ private
+
+ def same_specificity?(platform, spec, exemplary_spec)
+ platform_specificity_match(spec.platform, platform) == platform_specificity_match(exemplary_spec.platform, platform)
+ end
+
+ def same_deps?(spec, exemplary_spec)
+ spec.required_ruby_version == exemplary_spec.required_ruby_version &&
+ spec.required_rubygems_version == exemplary_spec.required_rubygems_version &&
+ spec.dependencies.sort == exemplary_spec.dependencies.sort
+ end
+
+ def os_match(spec_platform, user_platform)
+ if spec_platform.os == user_platform.os
+ 0
+ else
+ 1
+ end
+ end
+
+ def cpu_match(spec_platform, user_platform)
+ if spec_platform.cpu == user_platform.cpu
+ 0
+ elsif spec_platform.cpu == "arm" && user_platform.cpu.to_s.start_with?("arm")
+ 0
+ elsif spec_platform.cpu.nil? || spec_platform.cpu == "universal"
+ 1
+ else
+ 2
+ end
+ end
+
+ def version_match(spec_platform, user_platform)
+ if spec_platform.version == user_platform.version
+ 0
+ elsif spec_platform.version.nil?
+ 1
+ else
+ 2
+ end
+ end
+ end
+
+ end
+ end
+
require "rubygems/specification"
+ # Can be removed once RubyGems 3.5.14 support is dropped
+ VALIDATES_FOR_RESOLUTION = Specification.new.respond_to?(:validate_for_resolution).freeze
+
class Specification
+ # Can be removed once RubyGems 3.5.15 support is dropped
+ correct_array_attributes = @@default_value.select {|_k,v| v.is_a?(Array) }.keys
+ unless @@array_attributes == correct_array_attributes
+ @@array_attributes = correct_array_attributes # rubocop:disable Style/ClassVars
+ end
+
require_relative "match_metadata"
require_relative "match_platform"
include ::Bundler::MatchMetadata
- include ::Bundler::MatchPlatform
- attr_accessor :remote, :location, :relative_loaded_from
+ attr_accessor :remote, :relative_loaded_from
+
+ module AllowSettingSource
+ attr_writer :source
- remove_method :source
- attr_writer :source
- def source
- (defined?(@source) && @source) || Gem::Source::Installed.new
+ def source
+ (defined?(@source) && @source) || super
+ end
end
+ prepend AllowSettingSource
+
alias_method :rg_full_gem_path, :full_gem_path
alias_method :rg_loaded_from, :loaded_from
@@ -82,26 +235,15 @@ module Gem
end
end
- remove_method :gem_dir
+ # Can be removed once RubyGems 3.5.21 support is dropped
+ remove_method :gem_dir if method_defined?(:gem_dir, false)
+
def gem_dir
full_gem_path
end
- unless const_defined?(:LATEST_RUBY_WITHOUT_PATCH_VERSIONS)
- LATEST_RUBY_WITHOUT_PATCH_VERSIONS = Gem::Version.new("2.1")
-
- alias_method :rg_required_ruby_version=, :required_ruby_version=
- def required_ruby_version=(req)
- self.rg_required_ruby_version = req
-
- @required_ruby_version.requirements.map! do |op, v|
- if v >= LATEST_RUBY_WITHOUT_PATCH_VERSIONS && v.release.segments.size == 4
- [op == "~>" ? "=" : op, Gem::Version.new(v.segments.tap {|s| s.delete_at(3) }.join("."))]
- else
- [op, v]
- end
- end
- end
+ def insecurely_materialized?
+ false
end
def groups
@@ -127,10 +269,32 @@ module Gem
dependencies - development_dependencies
end
- def deleted_gem?
+ def installation_missing?
!default_gem? && !File.directory?(full_gem_path)
end
+ def lock_name
+ @lock_name ||= name_tuple.lock_name
+ end
+
+ unless VALIDATES_FOR_RESOLUTION
+ def validate_for_resolution
+ SpecificationPolicy.new(self).validate_for_resolution
+ end
+ end
+
+ if Gem.rubygems_version < Gem::Version.new("3.5.22")
+ module FixPathSourceMissingExtensions
+ def missing_extensions?
+ return false if %w[Bundler::Source::Path Bundler::Source::Gemspec].include?(source.class.name)
+
+ super
+ end
+ end
+
+ prepend FixPathSourceMissingExtensions
+ end
+
private
def dependencies_to_gemfile(dependencies, group = nil)
@@ -150,6 +314,14 @@ module Gem
end
end
+ unless VALIDATES_FOR_RESOLUTION
+ class SpecificationPolicy
+ def validate_for_resolution
+ validate_required!
+ end
+ end
+ end
+
module BetterPermissionError
def data
super
@@ -169,26 +341,20 @@ module Gem
include ::Bundler::ForcePlatform
+ attr_reader :force_ruby_platform
+
attr_accessor :source, :groups
alias_method :eql?, :==
- def force_ruby_platform
- return @force_ruby_platform if defined?(@force_ruby_platform) && !@force_ruby_platform.nil?
-
- @force_ruby_platform = default_force_ruby_platform
- end
-
- def encode_with(coder)
- to_yaml_properties.each do |ivar|
- coder[ivar.to_s.sub(/^@/, "")] = instance_variable_get(ivar)
+ unless method_defined?(:encode_with, false)
+ def encode_with(coder)
+ [:@name, :@requirement, :@type, :@prerelease, :@version_requirements].each do |ivar|
+ coder[ivar.to_s.sub(/^@/, "")] = instance_variable_get(ivar)
+ end
end
end
- def to_yaml_properties
- instance_variables.reject {|p| ["@source", "@groups"].include?(p.to_s) }
- end
-
def to_lock
out = String.new(" #{name}")
unless requirement.none?
@@ -197,106 +363,15 @@ module Gem
end
out
end
- end
- # Requirements using lambda operator differentiate trailing zeros since rubygems 3.2.6
- 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
+ if Gem.rubygems_version < Gem::Version.new("3.5.22")
+ module FilterIgnoredSpecs
+ def matching_specs(platform_only = false)
+ super.reject(&:ignored?)
end
end
- prepend CorrectHashForLambdaOperator
- end
- end
-
- require "rubygems/platform"
-
- class Platform
- JAVA = Gem::Platform.new("java")
- MSWIN = Gem::Platform.new("mswin32")
- MSWIN64 = Gem::Platform.new("mswin64")
- MINGW = Gem::Platform.new("x86-mingw32")
- X64_MINGW = [Gem::Platform.new("x64-mingw32"),
- Gem::Platform.new("x64-mingw-ucrt")].freeze
- WINDOWS = [MSWIN, MSWIN64, MINGW, X64_MINGW].flatten.freeze
- X64_LINUX = Gem::Platform.new("x86_64-linux")
- X64_LINUX_MUSL = Gem::Platform.new("x86_64-linux-musl")
-
- if X64_LINUX === X64_LINUX_MUSL
- remove_method :===
-
- def ===(other)
- return nil unless Gem::Platform === other
-
- # universal-mingw32 matches x64-mingw-ucrt
- return true if (@cpu == "universal" || other.cpu == "universal") &&
- @os.start_with?("mingw") && other.os.start_with?("mingw")
-
- # cpu
- ([nil,"universal"].include?(@cpu) || [nil, "universal"].include?(other.cpu) || @cpu == other.cpu ||
- (@cpu == "arm" && other.cpu.start_with?("arm"))) &&
-
- # os
- @os == other.os &&
-
- # version
- (
- (@os != "linux" && (@version.nil? || other.version.nil?)) ||
- (@os == "linux" && (normalized_linux_version_ext == other.normalized_linux_version_ext || ["musl#{@version}", "musleabi#{@version}", "musleabihf#{@version}"].include?(other.version))) ||
- @version == other.version
- )
- end
-
- # This is a copy of RubyGems 3.3.23 or higher `normalized_linux_method`.
- # Once only 3.3.23 is supported, we can use the method in RubyGems.
- def normalized_linux_version_ext
- return nil unless @version
-
- without_gnu_nor_abi_modifiers = @version.sub(/\Agnu/, "").sub(/eabi(hf)?\Z/, "")
- return nil if without_gnu_nor_abi_modifiers.empty?
-
- without_gnu_nor_abi_modifiers
- end
- end
-
- if RUBY_ENGINE == "truffleruby" && !defined?(REUSE_AS_BINARY_ON_TRUFFLERUBY)
- REUSE_AS_BINARY_ON_TRUFFLERUBY = %w[libv8 libv8-node sorbet-static].freeze
- end
- 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
-
- def match_gem?(platform, gem_name)
- match_platforms?(platform, Gem.platforms)
- end
- end
-
- match_platforms_defined = Gem::Platform.respond_to?(:match_platforms?, true)
-
- if !match_platforms_defined || Gem::Platform.send(:match_platforms?, Gem::Platform::X64_LINUX_MUSL, [Gem::Platform::X64_LINUX])
-
- private
-
- remove_method :match_platforms? if match_platforms_defined
-
- def match_platforms?(platform, platforms)
- platforms.any? do |local_platform|
- platform.nil? ||
- local_platform == platform ||
- (local_platform != Gem::Platform::RUBY && platform =~ local_platform)
- end
- end
+ prepend FilterIgnoredSpecs
end
end
@@ -319,6 +394,20 @@ module Gem
end
end
end
+
+ # Can be removed once RubyGems 3.5.22 support is dropped
+ unless new.respond_to?(:ignored?)
+ def ignored?
+ return @ignored unless @ignored.nil?
+
+ @ignored = missing_extensions?
+ end
+ end
+
+ # Can be removed once RubyGems 3.6.9 support is dropped
+ unless new.respond_to?(:installable_on_platform?)
+ include(::Bundler::MatchPlatform)
+ end
end
require "rubygems/name_tuple"
@@ -328,7 +417,7 @@ module Gem
unless Gem::NameTuple.new("a", Gem::Version.new("1"), Gem::Platform.new("x86_64-linux")).platform.is_a?(String)
alias_method :initialize_with_platform, :initialize
- def initialize(name, version, platform=Gem::Platform::RUBY)
+ def initialize(name, version, platform = Gem::Platform::RUBY)
if Gem::Platform === platform
initialize_with_platform(name, version, platform.to_s)
else
@@ -345,4 +434,48 @@ module Gem
end
end
end
+
+ unless Gem.rubygems_version >= Gem::Version.new("3.5.19")
+ class Resolver::ActivationRequest
+ remove_method :installed?
+
+ def installed?
+ case @spec
+ when Gem::Resolver::VendorSpecification then
+ true
+ else
+ this_spec = full_spec
+
+ Gem::Specification.any? do |s|
+ s == this_spec && s.base_dir == this_spec.base_dir
+ end
+ end
+ end
+ end
+ end
+
+ unless Gem.rubygems_version >= Gem::Version.new("3.6.7")
+ module UnfreezeCompactIndexParsedResponse
+ def parse(line)
+ version, platform, dependencies, requirements = super
+ [version, platform, dependencies.frozen? ? dependencies.dup : dependencies, requirements.frozen? ? requirements.dup : requirements]
+ end
+ end
+
+ Resolver::APISet::GemParser.prepend(UnfreezeCompactIndexParsedResponse)
+ end
+
+ if Gem.rubygems_version < Gem::Version.new("3.6.0")
+ class Package; end
+ require "rubygems/package/tar_reader"
+ require "rubygems/package/tar_reader/entry"
+
+ module FixFullNameEncoding
+ def full_name
+ super.force_encoding(Encoding::UTF_8)
+ end
+ end
+
+ Package::TarReader::Entry.prepend(FixFullNameEncoding)
+ end
end
diff --git a/lib/bundler/rubygems_gem_installer.rb b/lib/bundler/rubygems_gem_installer.rb
index d563868cd2..64ce6193d3 100644
--- a/lib/bundler/rubygems_gem_installer.rb
+++ b/lib/bundler/rubygems_gem_installer.rb
@@ -23,13 +23,18 @@ module Bundler
FileUtils.mkdir_p gem_dir, mode: 0o755
end
- extract_files
+ SharedHelpers.filesystem_access(gem_dir, :write) do
+ extract_files
+ end
build_extensions if spec.extensions.any?
write_build_info_file
run_post_build_hooks
- generate_bin
+ SharedHelpers.filesystem_access(bin_dir, :write) do
+ generate_bin
+ end
+
generate_plugins
write_spec
@@ -45,7 +50,17 @@ module Bundler
spec
end
- def pre_install_checks
+ if Bundler.rubygems.provides?("< 3.5")
+ def pre_install_checks
+ super
+ rescue Gem::FilePermissionError
+ # Ignore permission checks in RubyGems. Instead, go on, and try to write
+ # for real. We properly handle permission errors when they happen.
+ nil
+ end
+ end
+
+ def ensure_writable_dir(dir)
super
rescue Gem::FilePermissionError
# Ignore permission checks in RubyGems. Instead, go on, and try to write
@@ -54,7 +69,7 @@ module Bundler
end
def generate_plugins
- return unless Gem::Installer.instance_methods(false).include?(:generate_plugins)
+ return unless Gem::Installer.method_defined?(:generate_plugins, false)
latest = Gem::Specification.stubs_for(spec.name).first
return if latest && latest.version > spec.version
@@ -68,6 +83,30 @@ module Bundler
end
end
+ if Bundler.rubygems.provides?("< 3.5.19")
+ def generate_bin_script(filename, bindir)
+ bin_script_path = File.join bindir, formatted_program_filename(filename)
+
+ Gem.open_file_with_lock(bin_script_path) do
+ require "fileutils"
+ FileUtils.rm_f bin_script_path # prior install may have been --no-wrappers
+
+ File.open(bin_script_path, "wb", 0o755) do |file|
+ file.write app_script_text(filename)
+ file.chmod(options[:prog_mode] || 0o755)
+ end
+ end
+
+ verbose bin_script_path
+
+ generate_windows_script filename, bindir
+ end
+ end
+
+ def build_jobs
+ Bundler.settings[:jobs] || super
+ end
+
def build_extensions
extension_cache_path = options[:bundler_extension_cache_path]
extension_dir = spec.extension_dir
@@ -112,17 +151,17 @@ module Bundler
SharedHelpers.filesystem_access(extension_dir, :create) do
FileUtils.mkdir_p extension_dir
end
- require "shellwords" unless Bundler.rubygems.provides?(">= 3.2.25")
end
def strict_rm_rf(dir)
return unless File.exist?(dir)
+ return if Dir.empty?(dir)
parent = File.dirname(dir)
parent_st = File.stat(parent)
if parent_st.world_writable? && !parent_st.sticky?
- raise InsecureInstallPathError.new(parent)
+ raise InsecureInstallPathError.new(spec.full_name, dir)
end
begin
diff --git a/lib/bundler/rubygems_integration.rb b/lib/bundler/rubygems_integration.rb
index b841462263..e04ef23259 100644
--- a/lib/bundler/rubygems_integration.rb
+++ b/lib/bundler/rubygems_integration.rb
@@ -20,10 +20,6 @@ module Bundler
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
@@ -34,6 +30,10 @@ module Bundler
Gem::Command.build_args = args
end
+ def set_target_rbconfig(path)
+ Gem.set_target_rbconfig(path)
+ end
+
def loaded_specs(name)
Gem.loaded_specs[name]
end
@@ -48,7 +48,7 @@ module Bundler
end
def validate(spec)
- Bundler.ui.silence { spec.validate(false) }
+ Bundler.ui.silence { spec.validate_for_resolution }
rescue Gem::InvalidSpecificationException => e
error_message = "The gemspec at #{spec.loaded_from} is not valid. Please fix this gemspec.\n" \
"The validation error was '#{e.message}'\n"
@@ -57,28 +57,6 @@ module Bundler
nil
end
- def set_installed_by_version(spec, installed_by_version = Gem::VERSION)
- return unless spec.respond_to?(:installed_by_version=)
- spec.installed_by_version = Gem::Version.create(installed_by_version)
- end
-
- def spec_missing_extensions?(spec, default = true)
- return spec.missing_extensions? if spec.respond_to?(:missing_extensions?)
-
- return false if spec.default_gem?
- return false if spec.extensions.empty?
-
- default
- end
-
- def spec_matches_for_glob(spec, glob)
- return spec.matches_for_glob(glob) if spec.respond_to?(:matches_for_glob)
-
- spec.load_paths.flat_map do |lp|
- Dir["#{lp}/#{glob}#{suffix_pattern}"]
- end
- end
-
def stub_set_spec(stub, spec)
stub.instance_variable_set(:@spec, spec)
end
@@ -156,18 +134,6 @@ module Bundler
loaded_gem_paths.flatten
end
- def load_plugins
- Gem.load_plugins
- end
-
- def load_plugin_files(plugin_files)
- Gem.load_plugin_files(plugin_files)
- end
-
- def load_env_plugins
- Gem.load_env_plugins
- end
-
def ui=(obj)
Gem::DefaultUserInteraction.ui = obj
end
@@ -211,12 +177,12 @@ module Bundler
end
end
- def replace_gem(specs, specs_by_name)
+ def replace_gem(specs_by_name)
executables = nil
[::Kernel.singleton_class, ::Kernel].each do |kernel_class|
redefine_method(kernel_class, :gem) do |dep, *reqs|
- if executables&.include?(File.basename(caller.first.split(":").first))
+ if executables&.include?(File.basename(caller_locations(1, 1).first.path))
break
end
@@ -248,18 +214,11 @@ module Bundler
e.requirement = dep.requirement
raise e
end
-
- # 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
- # Used to make bin stubs that are not created by bundler work
- # under bundler. The new Gem.bin_path only considers gems in
- # +specs+
+ # Used to give better error messages when activating specs outside of the current bundle
def replace_bin_path(specs_by_name)
- gem_class = (class << Gem; self; end)
-
redefine_method(gem_class, :find_spec_for_exe) do |gem_name, *args|
exec_name = args.first
raise ArgumentError, "you must supply exec_name" unless exec_name
@@ -295,31 +254,6 @@ module Bundler
spec
end
-
- redefine_method(gem_class, :activate_bin_path) do |name, *args|
- exec_name = args.first
- return ENV["BUNDLE_BIN_PATH"] if exec_name == "bundle"
-
- # Copy of Rubygems activate_bin_path impl
- requirement = args.last
- spec = find_spec_for_exe name, exec_name, [requirement]
-
- gem_bin = File.join(spec.full_gem_path, spec.bindir, exec_name)
- gem_from_path_bin = File.join(File.dirname(spec.loaded_from), spec.bindir, exec_name)
- File.exist?(gem_bin) ? gem_bin : gem_from_path_bin
- end
-
- redefine_method(gem_class, :bin_path) do |name, *args|
- exec_name = args.first
- return ENV["BUNDLE_BIN_PATH"] if exec_name == "bundle"
-
- spec = find_spec_for_exe(name, *args)
- exec_name ||= spec.default_executable
-
- gem_bin = File.join(spec.full_gem_path, spec.bindir, exec_name)
- gem_from_path_bin = File.join(File.dirname(spec.loaded_from), spec.bindir, exec_name)
- File.exist?(gem_bin) ? gem_bin : gem_from_path_bin
- end
end
# Replace or hook into RubyGems to provide a bundlerized view
@@ -335,8 +269,8 @@ module Bundler
else
Gem::BUNDLED_GEMS.replace_require(specs) if Gem::BUNDLED_GEMS.respond_to?(:replace_require)
end
- replace_gem(specs, specs_by_name)
- stub_rubygems(specs)
+ replace_gem(specs_by_name)
+ stub_rubygems(specs_by_name.values)
replace_bin_path(specs_by_name)
Gem.clear_paths
@@ -354,7 +288,6 @@ module Bundler
default_spec_name = default_spec.name
next if specs_by_name.key?(default_spec_name)
- specs << default_spec
specs_by_name[default_spec_name] = default_spec
end
@@ -365,11 +298,7 @@ module Bundler
@replaced_methods.each do |(sym, klass), method|
redefine_method(klass, sym, method)
end
- if Binding.public_method_defined?(:source_location)
- post_reset_hooks.reject! {|proc| proc.binding.source_location[0] == __FILE__ }
- else
- post_reset_hooks.reject! {|proc| proc.binding.eval("__FILE__") == __FILE__ }
- end
+ post_reset_hooks.reject! {|proc| proc.binding.source_location[0] == __FILE__ }
@replaced_methods.clear
end
@@ -411,9 +340,13 @@ module Bundler
Gem::Specification.all = specs
end
- redefine_method((class << Gem; self; end), :finish_resolve) do |*|
+ redefine_method(gem_class, :finish_resolve) do |*|
[]
end
+
+ redefine_method(gem_class, :load_plugins) do |*|
+ load_plugin_files specs.flat_map(&:plugins)
+ end
end
def plain_specs
@@ -446,7 +379,9 @@ module Bundler
def download_gem(spec, uri, cache_dir, fetcher)
require "rubygems/remote_fetcher"
uri = Bundler.settings.mirror_for(uri)
- Bundler::Retry.new("download gem from #{uri}").attempts do
+ redacted_uri = Gem::Uri.redact(uri)
+
+ Bundler::Retry.new("download gem from #{redacted_uri}").attempts do
gem_file_name = spec.file_name
local_gem_path = File.join cache_dir, gem_file_name
return if File.exist? local_gem_path
@@ -468,7 +403,7 @@ module Bundler
end
end
rescue Gem::RemoteFetcher::FetchError => e
- raise Bundler::HTTPError, "Could not download gem from #{uri} due to underlying error <#{e.message}>"
+ raise Bundler::HTTPError, "Could not download gem from #{redacted_uri} due to underlying error <#{e.message}>"
end
def build(spec, skip_validation = false)
@@ -481,11 +416,7 @@ module Bundler
end
def all_specs
- SharedHelpers.major_deprecation 2, "Bundler.rubygems.all_specs has been removed in favor of Bundler.rubygems.installed_specs"
-
- Gem::Specification.stubs.map do |stub|
- StubSpecification.from_stub(stub)
- end
+ SharedHelpers.feature_removed! "Bundler.rubygems.all_specs has been removed in favor of Bundler.rubygems.installed_specs"
end
def installed_specs
@@ -501,7 +432,7 @@ module Bundler
end
def find_bundler(version)
- find_name("bundler").find {|s| s.version.to_s == version }
+ find_name("bundler").find {|s| s.version.to_s == version.to_s }
end
def find_name(name)
@@ -511,6 +442,12 @@ module Bundler
def default_stubs
Gem::Specification.default_stubs("*.gemspec")
end
+
+ private
+
+ def gem_class
+ class << Gem; self; end
+ end
end
def self.rubygems
diff --git a/lib/bundler/runtime.rb b/lib/bundler/runtime.rb
index 54aa30ce0b..5280e72aa2 100644
--- a/lib/bundler/runtime.rb
+++ b/lib/bundler/runtime.rb
@@ -10,7 +10,7 @@ module Bundler
end
def setup(*groups)
- @definition.ensure_equivalent_gemfile_and_lockfile if Bundler.frozen_bundle?
+ @definition.ensure_equivalent_gemfile_and_lockfile
# Has to happen first
clean_load_path
@@ -50,35 +50,30 @@ module Bundler
Plugin.hook(Plugin::Events::GEM_BEFORE_REQUIRE_ALL, dependencies)
dependencies.each do |dep|
- required_file = nil
Plugin.hook(Plugin::Events::GEM_BEFORE_REQUIRE, dep)
- begin
- # Loop through all the specified autorequires for the
- # dependency. If there are none, use the dependency's name
- # as the autorequire.
- Array(dep.autorequire || dep.name).each do |file|
- # Allow `require: true` as an alias for `require: <name>`
- file = dep.name if file == true
- required_file = file
- begin
- Kernel.require file
- rescue RuntimeError => e
- raise e if e.is_a?(LoadError) # we handle this a little later
+ # Loop through all the specified autorequires for the
+ # dependency. If there are none, use the dependency's name
+ # as the autorequire.
+ Array(dep.autorequire || dep.name).each do |file|
+ # Allow `require: true` as an alias for `require: <name>`
+ file = dep.name if file == true
+ required_file = file
+ begin
+ Kernel.require required_file
+ rescue LoadError => e
+ if dep.autorequire.nil? && e.path == required_file
+ if required_file.include?("-")
+ required_file = required_file.tr("-", "/")
+ retry
+ end
+ else
raise Bundler::GemRequireError.new e,
"There was an error while trying to load the gem '#{file}'."
end
- end
- rescue LoadError => e
- 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
- raise if e.path != namespaced_file
- end
+ rescue StandardError => e
+ raise Bundler::GemRequireError.new e,
+ "There was an error while trying to load the gem '#{file}'."
end
end
@@ -135,8 +130,15 @@ module Bundler
specs_to_cache.each do |spec|
next if spec.name == "bundler"
- next if spec.source.is_a?(Source::Gemspec)
- spec.source.cache(spec, custom_path) if spec.source.respond_to?(:cache)
+
+ source = spec.source
+ next if source.is_a?(Source::Gemspec)
+
+ if source.respond_to?(:migrate_cache)
+ source.migrate_cache(custom_path, local: local)
+ elsif source.respond_to?(:cache)
+ source.cache(spec, custom_path)
+ end
end
Dir[cache_path.join("*/.git")].each do |git_dir|
@@ -172,7 +174,14 @@ module Bundler
spec_cache_paths = []
spec_gemspec_paths = []
spec_extension_paths = []
- Bundler.rubygems.add_default_gems_to(specs).values.each do |spec|
+ specs_to_keep = Bundler.rubygems.add_default_gems_to(specs).values
+
+ current_bundler = Bundler.rubygems.find_bundler(Bundler.gem_version)
+ if current_bundler
+ specs_to_keep << current_bundler
+ end
+
+ specs_to_keep.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)
@@ -238,7 +247,11 @@ module Bundler
cached.each do |path|
Bundler.ui.info " * #{File.basename(path)}"
- File.delete(path)
+
+ begin
+ File.delete(path)
+ rescue Errno::ENOENT
+ end
end
end
end
@@ -268,10 +281,10 @@ module Bundler
def setup_manpath
# Add man/ subdirectories from activated bundles to MANPATH for man(1)
- manuals = $LOAD_PATH.map do |path|
+ manuals = $LOAD_PATH.filter_map do |path|
man_subdir = path.sub(/lib$/, "man")
man_subdir unless Dir[man_subdir + "/man?/"].empty?
- end.compact
+ end
return if manuals.empty?
Bundler::SharedHelpers.set_env "MANPATH", manuals.concat(
diff --git a/lib/bundler/self_manager.rb b/lib/bundler/self_manager.rb
index 5accda4bcb..1db77fd46b 100644
--- a/lib/bundler/self_manager.rb
+++ b/lib/bundler/self_manager.rb
@@ -7,13 +7,15 @@ module Bundler
#
class SelfManager
def restart_with_locked_bundler_if_needed
- return unless needs_switching? && installed?
+ restart_version = find_restart_version
+ return unless restart_version && installed?(restart_version)
restart_with(restart_version)
end
def install_locked_bundler_and_restart_with_it_if_needed
- return unless needs_switching?
+ restart_version = find_restart_version
+ return unless restart_version
if restart_version == lockfile_version
Bundler.ui.info \
@@ -29,8 +31,6 @@ module Bundler
end
def update_bundler_and_restart_with_it_if_needed(target)
- return unless autoswitching_applies?
-
spec = resolve_update_version_from(target)
return unless spec
@@ -38,7 +38,7 @@ module Bundler
Bundler.ui.info "Updating bundler to #{version}."
- install(spec)
+ install(spec) unless installed?(version)
restart_with(version)
end
@@ -68,31 +68,37 @@ module Bundler
def restart_with(version)
configured_gem_home = ENV["GEM_HOME"]
+ configured_orig_gem_home = ENV["BUNDLER_ORIG_GEM_HOME"]
configured_gem_path = ENV["GEM_PATH"]
+ configured_orig_gem_path = ENV["BUNDLER_ORIG_GEM_PATH"]
- cmd = [$PROGRAM_NAME, *ARGV]
- cmd.unshift(Gem.ruby) unless File.executable?($PROGRAM_NAME)
+ argv0 = File.exist?($PROGRAM_NAME) ? $PROGRAM_NAME : Process.argv0
+ cmd = [argv0, *ARGV]
+ cmd.unshift(Gem.ruby) unless File.executable?(argv0)
Bundler.with_original_env do
Kernel.exec(
- { "GEM_HOME" => configured_gem_home, "GEM_PATH" => configured_gem_path, "BUNDLER_VERSION" => version.to_s },
+ {
+ "GEM_HOME" => configured_gem_home,
+ "BUNDLER_ORIG_GEM_HOME" => configured_orig_gem_home,
+ "GEM_PATH" => configured_gem_path,
+ "BUNDLER_ORIG_GEM_PATH" => configured_orig_gem_path,
+ "BUNDLER_VERSION" => version.to_s,
+ },
*cmd
)
end
end
- def needs_switching?
+ def needs_switching?(restart_version)
autoswitching_applies? &&
- released?(lockfile_version) &&
- !running?(lockfile_version) &&
- !updating? &&
- Bundler.settings[:version] != "system"
+ released?(restart_version) &&
+ !running?(restart_version)
end
def autoswitching_applies?
- ENV["BUNDLER_VERSION"].nil? &&
- Bundler.rubygems.supports_bundler_trampolining? &&
- SharedHelpers.in_bundle? &&
+ (ENV["BUNDLER_VERSION"].nil? || ENV["BUNDLER_VERSION"].empty?) &&
+ ruby_can_restart_with_same_arguments? &&
lockfile_version
end
@@ -126,6 +132,7 @@ module Bundler
end
def find_latest_matching_spec(requirement)
+ Bundler.configure
local_result = find_latest_matching_spec_from_collection(local_specs, requirement)
return local_result if local_result && requirement.specific?
@@ -151,18 +158,18 @@ module Bundler
!version.to_s.end_with?(".dev")
end
- def updating?
- "update".start_with?(ARGV.first || " ") && ARGV[1..-1].any? {|a| a.start_with?("--bundler") }
+ def ruby_can_restart_with_same_arguments?
+ $PROGRAM_NAME != "-e"
end
- def installed?
+ def installed?(restart_version)
Bundler.configure
Bundler.rubygems.find_bundler(restart_version.to_s)
end
def current_version
- @current_version ||= Gem::Version.new(Bundler::VERSION)
+ @current_version ||= Bundler.gem_version
end
def lockfile_version
@@ -174,13 +181,16 @@ module Bundler
@lockfile_version = nil
end
- def restart_version
- return @restart_version if defined?(@restart_version)
- # BUNDLE_VERSION=x.y.z
- @restart_version = Gem::Version.new(Bundler.settings[:version])
- rescue ArgumentError
- # BUNDLE_VERSION=lockfile
- @restart_version = lockfile_version
+ def find_restart_version
+ return unless SharedHelpers.in_bundle?
+
+ configured_version = Bundler.settings[:version]
+ return if configured_version == "system"
+
+ restart_version = configured_version == "lockfile" ? lockfile_version : Gem::Version.new(configured_version)
+ return unless needs_switching?(restart_version)
+
+ restart_version
end
end
end
diff --git a/lib/bundler/settings.rb b/lib/bundler/settings.rb
index 4aef0cf1b3..d00a4bb916 100644
--- a/lib/bundler/settings.rb
+++ b/lib/bundler/settings.rb
@@ -7,13 +7,10 @@ module Bundler
autoload :Validator, File.expand_path("settings/validator", __dir__)
BOOL_KEYS = %w[
- allow_offline_install
- auto_clean_without_path
auto_install
cache_all
cache_all_platforms
clean
- default_install_uses_path
deployment
disable_checksum_validation
disable_exec_load
@@ -22,41 +19,26 @@ module Bundler
disable_shared_gems
disable_version_check
force_ruby_platform
- forget_cli_options
frozen
gem.changelog
gem.coc
gem.mit
+ gem.bundle
git.allow_insecure
global_gem_cache
ignore_messages
init_gems_rb
inline
+ lockfile_checksums
no_install
no_prune
- path_relative_to_cwd
path.system
plugins
prefer_patch
- print_only_version_number
- setup_makes_kernel_gem_public
silence_deprecations
silence_root_warning
update_requires_all_flag
- ].freeze
-
- REMEMBERED_KEYS = %w[
- bin
- cache_all
- clean
- deployment
- frozen
- no_prune
- path
- shebang
- path.system
- without
- with
+ verbose
].freeze
NUMBER_KEYS = %w[
@@ -83,8 +65,10 @@ module Bundler
gem.rubocop
gem.test
gemfile
+ lockfile
path
shebang
+ simulate_version
system_bindir
trust-policy
version
@@ -98,6 +82,11 @@ module Bundler
"BUNDLE_RETRY" => 3,
"BUNDLE_TIMEOUT" => 10,
"BUNDLE_VERSION" => "lockfile",
+ "BUNDLE_LOCKFILE_CHECKSUMS" => true,
+ "BUNDLE_CACHE_ALL" => true,
+ "BUNDLE_PLUGINS" => true,
+ "BUNDLE_GLOBAL_GEM_CACHE" => false,
+ "BUNDLE_UPDATE_REQUIRES_ALL_FLAG" => false,
}.freeze
def initialize(root = nil)
@@ -129,12 +118,8 @@ module Bundler
end
def set_command_option(key, value)
- if !is_remembered(key) || Bundler.feature_flag.forget_cli_options?
- temporary(key => value)
- value
- else
- set_local(key, value)
- end
+ temporary(key => value)
+ value
end
def set_command_option_if_given(key, value)
@@ -273,7 +258,7 @@ module Bundler
def use_system_gems?
return true if system_path
return false if explicit_path
- !Bundler.feature_flag.default_install_uses_path?
+ !Bundler.feature_flag.bundler_5_mode?
end
def base_path
@@ -388,10 +373,6 @@ module Bundler
ARRAY_KEYS.include?(self.class.key_to_s(key))
end
- def is_remembered(key)
- REMEMBERED_KEYS.include?(self.class.key_to_s(key))
- end
-
def is_credential(key)
key == "gem.push_key"
end
@@ -425,8 +406,12 @@ module Bundler
Validator.validate!(raw_key, converted_value(value, raw_key), hash)
return unless file
+
+ SharedHelpers.filesystem_access(file.dirname, :create) do |p|
+ FileUtils.mkdir_p(p)
+ end
+
SharedHelpers.filesystem_access(file) do |p|
- FileUtils.mkdir_p(p.dirname)
p.open("w") {|f| f.write(serializer_class.dump(hash)) }
end
end
@@ -492,6 +477,10 @@ module Bundler
valid_file = file.exist? && !file.size.zero?
return {} unless valid_file
serializer_class.load(file.read).inject({}) do |config, (k, v)|
+ k = k.dup
+ k << "/" if /https?:/i.match?(k) && !k.end_with?("/", "__#{FALLBACK_TIMEOUT_URI_OPTION.upcase}")
+ k.gsub!(".", "__")
+
unless k.start_with?("#")
if k.include?("-")
Bundler.ui.warn "Your #{file} config includes `#{k}`, which contains the dash character (`-`).\n" \
@@ -519,26 +508,25 @@ module Bundler
YAMLSerializer
end
- PER_URI_OPTIONS = %w[
- fallback_timeout
- ].freeze
+ FALLBACK_TIMEOUT_URI_OPTION = "fallback_timeout"
NORMALIZE_URI_OPTIONS_PATTERN =
/
\A
(\w+\.)? # optional prefix key
(https?.*?) # URI
- (\.#{Regexp.union(PER_URI_OPTIONS)})? # optional suffix key
+ (\.#{FALLBACK_TIMEOUT_URI_OPTION})? # optional suffix key
\z
/ix
def self.key_for(key)
- key = normalize_uri(key).to_s if key.is_a?(String) && key.start_with?("http", "mirror.http")
- key = key_to_s(key).gsub(".", "__")
+ key = key_to_s(key)
+ key = normalize_uri(key) if key.start_with?("http", "mirror.http")
+ key = key.gsub(".", "__")
key.gsub!("-", "___")
key.upcase!
- key.prepend("BUNDLE_")
+ key.gsub(/\A([ #]*)/, '\1BUNDLE_')
end
# TODO: duplicates Rubygems#normalize_uri
diff --git a/lib/bundler/settings/validator.rb b/lib/bundler/settings/validator.rb
index 0a57ea7f03..9aa1627fb2 100644
--- a/lib/bundler/settings/validator.rb
+++ b/lib/bundler/settings/validator.rb
@@ -74,29 +74,6 @@ module Bundler
fail!(key, value, "`#{other_key}` is current set to #{other_setting.inspect}", "the `#{conflicting.join("`, `")}` groups conflict")
end
end
-
- rule %w[path], "relative paths are expanded relative to the current working directory" do |key, value, settings|
- next if value.nil?
-
- path = Pathname.new(value)
- next if !path.relative? || !Bundler.feature_flag.path_relative_to_cwd?
-
- path = path.expand_path
-
- root = begin
- Bundler.root
- rescue GemfileNotFound
- Pathname.pwd.expand_path
- end
-
- path = begin
- path.relative_path_from(root)
- rescue ArgumentError
- path
- end
-
- set(settings, key, path.to_s)
- end
end
end
end
diff --git a/lib/bundler/setup.rb b/lib/bundler/setup.rb
index 6010d66742..5a0fd8e0e3 100644
--- a/lib/bundler/setup.rb
+++ b/lib/bundler/setup.rb
@@ -5,6 +5,9 @@ require_relative "shared_helpers"
if Bundler::SharedHelpers.in_bundle?
require_relative "../bundler"
+ # autoswitch to locked Bundler version if available
+ Bundler.auto_switch
+
# try to auto_install first before we get to the `Bundler.ui.silence`, so user knows what is happening
Bundler.auto_install
diff --git a/lib/bundler/shared_helpers.rb b/lib/bundler/shared_helpers.rb
index 28f0cdff19..2aa8abe0a0 100644
--- a/lib/bundler/shared_helpers.rb
+++ b/lib/bundler/shared_helpers.rb
@@ -10,8 +10,6 @@ module Bundler
autoload :NULL, File.expand_path("constants", __dir__)
module SharedHelpers
- autoload :Pathname, "pathname"
-
def root
gemfile = find_gemfile
raise GemfileNotFound, "Could not locate Gemfile" unless gemfile
@@ -25,6 +23,9 @@ module Bundler
end
def default_lockfile
+ given = ENV["BUNDLE_LOCKFILE"]
+ return Pathname.new(given) if given && !given.empty?
+
gemfile = default_gemfile
case gemfile.basename.to_s
@@ -57,7 +58,7 @@ module Bundler
def pwd
Bundler.rubygems.ext_lock.synchronize do
- Pathname.pwd
+ Dir.pwd
end
end
@@ -96,14 +97,17 @@ module Bundler
# given block
#
# @example
- # filesystem_access("vendor/cache", :write) do
+ # filesystem_access("vendor/cache", :create) do
# FileUtils.mkdir_p("vendor/cache")
# end
#
# @see {Bundler::PermissionError}
def filesystem_access(path, action = :write, &block)
yield(path.dup)
- rescue Errno::EACCES
+ rescue Errno::EACCES => e
+ path_basename = File.basename(path.to_s)
+ raise unless e.message.include?(path_basename) || action == :create
+
raise PermissionError.new(path, action)
rescue Errno::EAGAIN
raise TemporaryResourceError.new(path, action)
@@ -113,30 +117,27 @@ module Bundler
raise NoSpaceOnDeviceError.new(path, action)
rescue Errno::ENOTSUP
raise OperationNotSupportedError.new(path, action)
+ rescue Errno::EPERM
+ raise OperationNotPermittedError.new(path, action)
+ rescue Errno::EROFS
+ raise ReadOnlyFileSystemError.new(path, action)
rescue Errno::EEXIST, Errno::ENOENT
raise
rescue SystemCallError => e
- raise GenericSystemCallError.new(e, "There was an error accessing `#{path}`.")
+ raise GenericSystemCallError.new(e, "There was an error #{[:create, :write].include?(action) ? "creating" : "accessing"} `#{path}`.")
end
- def major_deprecation(major_version, message, removed_message: nil, print_caller_location: false)
- if print_caller_location
- caller_location = caller_locations(2, 2).first
- suffix = " (called at #{caller_location.path}:#{caller_location.lineno})"
- message += suffix
- removed_message += suffix if removed_message
- end
+ def feature_deprecated!(message)
+ return unless prints_major_deprecations?
- bundler_major_version = Bundler.bundler_major_version
- if bundler_major_version > major_version
- require_relative "errors"
- raise DeprecatedError, "[REMOVED] #{removed_message || message}"
- end
-
- return unless bundler_major_version >= major_version && prints_major_deprecations?
Bundler.ui.warn("[DEPRECATED] #{message}")
end
+ def feature_removed!(message)
+ require_relative "errors"
+ raise RemovedError, "[REMOVED] #{message}"
+ end
+
def print_major_deprecations!
multiple_gemfiles = search_up(".") do |dir|
gemfiles = gemfile_names.select {|gf| File.file? File.expand_path(gf, dir) }
@@ -160,10 +161,10 @@ module Bundler
extra_deps = new_deps - old_deps
return if extra_deps.empty?
- Bundler.ui.debug "#{spec.full_name} from #{spec.remote} has either corrupted API or lockfile dependencies" \
+ Bundler.ui.debug "#{spec.full_name} from #{spec.remote} has corrupted API dependencies" \
" (was expecting #{old_deps.map(&:to_s)}, but the real spec has #{new_deps.map(&:to_s)})"
raise APIResponseMismatchError,
- "Downloading #{spec.full_name} revealed dependencies not in the API or the lockfile (#{extra_deps.join(", ")})." \
+ "Downloading #{spec.full_name} revealed dependencies not in the API (#{extra_deps.join(", ")})." \
"\nRunning `bundle update #{spec.name}` should fix the problem."
end
@@ -274,15 +275,7 @@ module Bundler
until !File.directory?(current) || current == previous
if ENV["BUNDLER_SPEC_RUN"]
# avoid stepping above the tmp directory when testing
- gemspec = if ENV["GEM_COMMAND"]
- # for Ruby Core
- "lib/bundler/bundler.gemspec"
- else
- "bundler.gemspec"
- end
-
- # avoid stepping above the tmp directory when testing
- return nil if File.file?(File.join(current, gemspec))
+ return nil if File.directory?(File.join(current, "tmp"))
end
names.each do |name|
@@ -308,24 +301,43 @@ module Bundler
def set_bundle_variables
Bundler::SharedHelpers.set_env "BUNDLE_BIN_PATH", bundle_bin_path
Bundler::SharedHelpers.set_env "BUNDLE_GEMFILE", find_gemfile.to_s
+ Bundler::SharedHelpers.set_env "BUNDLE_LOCKFILE", default_lockfile.to_s
Bundler::SharedHelpers.set_env "BUNDLER_VERSION", Bundler::VERSION
Bundler::SharedHelpers.set_env "BUNDLER_SETUP", File.expand_path("setup", __dir__)
end
def bundle_bin_path
# bundler exe & lib folders have same root folder, typical gem installation
- exe_file = File.expand_path("../../exe/bundle", __dir__)
+ exe_file = File.join(source_root, "exe/bundle")
# for Ruby core repository testing
- exe_file = File.expand_path("../../libexec/bundle", __dir__) unless File.exist?(exe_file)
+ exe_file = File.join(source_root, "libexec/bundle") unless File.exist?(exe_file)
# bundler is a default gem, exe path is separate
- exe_file = Bundler.rubygems.bin_path("bundler", "bundle", VERSION) unless File.exist?(exe_file)
+ exe_file = Gem.bin_path("bundler", "bundle", VERSION) unless File.exist?(exe_file)
exe_file
end
public :bundle_bin_path
+ def gemspec_path
+ # inside a gem repository, typical gem installation
+ gemspec_file = File.join(source_root, "../../specifications/bundler-#{VERSION}.gemspec")
+
+ # for Ruby core repository testing
+ gemspec_file = File.expand_path("bundler.gemspec", __dir__) unless File.exist?(gemspec_file)
+
+ # bundler is a default gem
+ gemspec_file = File.join(Gem.default_specifications_dir, "bundler-#{VERSION}.gemspec") unless File.exist?(gemspec_file)
+
+ gemspec_file
+ end
+ public :gemspec_path
+
+ def source_root
+ File.expand_path("../..", __dir__)
+ end
+
def set_path
validate_bundle_path
paths = (ENV["PATH"] || "").split(File::PATH_SEPARATOR)
@@ -370,7 +382,6 @@ module Bundler
end
def prints_major_deprecations?
- require_relative "../bundler"
return false if Bundler.settings[:silence_deprecations]
require_relative "deprecate"
return false if Bundler::Deprecate.skip
diff --git a/lib/bundler/similarity_detector.rb b/lib/bundler/similarity_detector.rb
deleted file mode 100644
index 50e66b9cab..0000000000
--- a/lib/bundler/similarity_detector.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-# frozen_string_literal: true
-
-module Bundler
- class SimilarityDetector
- SimilarityScore = Struct.new(:string, :distance)
-
- # initialize with an array of words to be matched against
- def initialize(corpus)
- @corpus = corpus
- end
-
- # return an array of words similar to 'word' from the corpus
- def similar_words(word, limit = 3)
- words_by_similarity = @corpus.map {|w| SimilarityScore.new(w, levenshtein_distance(word, w)) }
- words_by_similarity.select {|s| s.distance <= limit }.sort_by(&:distance).map(&:string)
- end
-
- # return the result of 'similar_words', concatenated into a list
- # (eg "a, b, or c")
- def similar_word_list(word, limit = 3)
- words = similar_words(word, limit)
- if words.length == 1
- words[0]
- elsif words.length > 1
- [words[0..-2].join(", "), words[-1]].join(" or ")
- end
- end
-
- protected
-
- # https://www.informit.com/articles/article.aspx?p=683059&seqNum=36
- def levenshtein_distance(this, that, ins = 2, del = 2, sub = 1)
- # ins, del, sub are weighted costs
- return nil if this.nil?
- return nil if that.nil?
- dm = [] # distance matrix
-
- # Initialize first row values
- dm[0] = (0..this.length).collect {|i| i * ins }
- fill = [0] * (this.length - 1)
-
- # Initialize first column values
- (1..that.length).each do |i|
- dm[i] = [i * del, fill.flatten]
- end
-
- # populate matrix
- (1..that.length).each do |i|
- (1..this.length).each do |j|
- # critical comparison
- dm[i][j] = [
- dm[i - 1][j - 1] + (this[j - 1] == that[i - 1] ? 0 : sub),
- dm[i][j - 1] + ins,
- dm[i - 1][j] + del,
- ].min
- end
- end
-
- # The last value in matrix is the Levenshtein distance between the strings
- dm[that.length][this.length]
- end
- end
-end
diff --git a/lib/bundler/source.rb b/lib/bundler/source.rb
index 115dbd1378..2b90a0eff1 100644
--- a/lib/bundler/source.rb
+++ b/lib/bundler/source.rb
@@ -35,6 +35,8 @@ module Bundler
spec.source == self
end
+ def prefer_local!; end
+
def local!; end
def local_only!; end
@@ -77,7 +79,7 @@ module Bundler
end
def extension_cache_path(spec)
- return unless Bundler.feature_flag.global_gem_cache?
+ return unless Bundler.settings[:global_gem_cache]
return unless source_slug = extension_cache_slug(spec)
Bundler.user_cache.join(
"extensions", Gem::Platform.local.to_s, Bundler.ruby_scope,
diff --git a/lib/bundler/source/gemspec.rb b/lib/bundler/source/gemspec.rb
index 7e3447e776..ed766dbe74 100644
--- a/lib/bundler/source/gemspec.rb
+++ b/lib/bundler/source/gemspec.rb
@@ -4,14 +4,15 @@ module Bundler
class Source
class Gemspec < Path
attr_reader :gemspec
+ attr_writer :checksum_store
def initialize(options)
super
@gemspec = options["gemspec"]
end
- def as_path_source
- Path.new(options)
+ def to_s
+ "gemspec at `#{@path}`"
end
end
end
diff --git a/lib/bundler/source/git.rb b/lib/bundler/source/git.rb
index 198e335bb6..bb669ebba3 100644
--- a/lib/bundler/source/git.rb
+++ b/lib/bundler/source/git.rb
@@ -32,6 +32,20 @@ module Bundler
@local = false
end
+ def remote!
+ return if @allow_remote
+
+ @local_specs = nil
+ @allow_remote = true
+ end
+
+ def cached!
+ return if @allow_cached
+
+ @local_specs = nil
+ @allow_cached = true
+ end
+
def self.from_lock(options)
new(options.merge("uri" => options.delete("remote")))
end
@@ -56,13 +70,13 @@ module Bundler
end
def hash
- [self.class, uri, ref, branch, name, version, glob, submodules].hash
+ [self.class, uri, ref, branch, name, glob, submodules].hash
end
def eql?(other)
other.is_a?(Git) && uri == other.uri && ref == other.ref &&
branch == other.branch && name == other.name &&
- version == other.version && glob == other.glob &&
+ glob == other.glob &&
submodules == other.submodules
end
@@ -88,7 +102,7 @@ module Bundler
end
def identifier
- uri_with_specifiers([humanized_ref, cached_revision, glob_for_display])
+ uri_with_specifiers([humanized_ref, locked_revision, glob_for_display])
end
def uri_with_specifiers(specifiers)
@@ -150,7 +164,8 @@ module Bundler
"does not exist. Run `bundle config unset local.#{override_for(original_path)}` to remove the local override"
end
- set_local!(path)
+ @local = true
+ set_paths!(path)
# Create a new git proxy without the cached revision
# so the Gemfile.lock always picks up the new revision.
@@ -161,10 +176,10 @@ module Bundler
"#{current_branch} but Gemfile specifies #{branch}"
end
- changed = cached_revision && cached_revision != revision
+ changed = locked_revision && locked_revision != 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)} " \
+ if !Bundler.settings[:disable_local_revision_check] && changed && !@unlocked && !git_proxy.contains?(locked_revision)
+ raise GitError, "The Gemfile lock is pointing to revision #{shortref_for_display(locked_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."
end
@@ -173,13 +188,11 @@ module Bundler
end
def specs(*)
- set_local!(app_cache_path) if has_app_cache? && !local?
+ set_cache_path!(app_cache_path) if use_app_cache?
if requires_checkout? && !@copied
- fetch
- git_proxy.copy_to(install_path, submodules)
- serialize_gemspecs_in(install_path)
- @copied = true
+ fetch unless use_app_cache?
+ checkout
end
local_specs
@@ -192,27 +205,25 @@ module Bundler
print_using_message "Using #{version_message(spec, options[:previous_spec])} from #{self}"
if (requires_checkout? && !@copied) || force
- Bundler.ui.debug " * Checking out revision: #{ref}"
- git_proxy.copy_to(install_path, submodules)
- serialize_gemspecs_in(install_path)
- @copied = true
+ checkout
end
- generate_bin_options = { disable_extensions: !Bundler.rubygems.spec_missing_extensions?(spec), build_args: options[:build_args] }
+ generate_bin_options = { disable_extensions: !spec.missing_extensions?, build_args: options[:build_args] }
generate_bin(spec, generate_bin_options)
requires_checkout? ? spec.post_install_message : nil
end
+ def migrate_cache(custom_path = nil, local: false)
+ if local
+ cache_to(custom_path, try_migrate: false)
+ else
+ cache_to(custom_path, try_migrate: true)
+ end
+ end
+
def cache(spec, custom_path = nil)
- app_cache_path = app_cache_path(custom_path)
- return unless Bundler.feature_flag.cache_all?
- return if path == app_cache_path
- cached!
- FileUtils.rm_rf(app_cache_path)
- git_proxy.checkout if requires_checkout?
- git_proxy.copy_to(app_cache_path, @submodules)
- serialize_gemspecs_in(app_cache_path)
+ cache_to(custom_path, try_migrate: false)
end
def load_spec_files
@@ -227,7 +238,7 @@ module Bundler
# across different projects, this cache will be shared.
# When using local git repos, this is set to the local repo.
def cache_path
- @cache_path ||= if Bundler.feature_flag.global_gem_cache?
+ @cache_path ||= if Bundler.settings[:global_gem_cache]
Bundler.user_cache
else
Bundler.bundle_path.join("cache", "bundler")
@@ -235,7 +246,7 @@ module Bundler
end
def app_cache_dirname
- "#{base_name}-#{shortref_for_path(cached_revision || revision)}"
+ "#{base_name}-#{shortref_for_path(locked_revision || revision)}"
end
def revision
@@ -256,6 +267,43 @@ module Bundler
private
+ def cache_to(custom_path, try_migrate: false)
+ return unless Bundler.settings[:cache_all]
+
+ app_cache_path = app_cache_path(custom_path)
+
+ migrate = try_migrate ? bare_repo?(app_cache_path) : false
+
+ set_cache_path!(nil) if migrate
+
+ return if cache_path == app_cache_path
+
+ cached!
+ FileUtils.rm_rf(app_cache_path)
+ git_proxy.checkout if migrate || requires_checkout?
+ git_proxy.copy_to(app_cache_path, @submodules)
+ serialize_gemspecs_in(app_cache_path)
+ end
+
+ def checkout
+ Bundler.ui.debug " * Checking out revision: #{ref}"
+ if use_app_cache? && !bare_repo?(app_cache_path)
+ SharedHelpers.filesystem_access(install_path.dirname) do |p|
+ FileUtils.mkdir_p(p)
+ end
+ FileUtils.cp_r("#{app_cache_path}/.", install_path)
+ else
+ if use_app_cache? && bare_repo?(app_cache_path)
+ Bundler.ui.warn "Installing from cache in old \"bare repository\" format for compatibility. " \
+ "Please run `bundle cache` and commit the updated cache to migrate to the new format and get rid of this warning."
+ end
+
+ git_proxy.copy_to(install_path, submodules)
+ end
+ serialize_gemspecs_in(install_path)
+ @copied = true
+ end
+
def humanized_ref
if local?
path
@@ -278,28 +326,45 @@ module Bundler
# The gemspecs we cache should already be evaluated.
spec = Bundler.load_gemspec(spec_path)
next unless spec
- Bundler.rubygems.set_installed_by_version(spec)
+ spec.installed_by_version = Gem::VERSION
Bundler.rubygems.validate(spec)
File.open(spec_path, "wb") {|file| file.write(spec.to_ruby) }
end
end
- def set_local!(path)
- @local = true
- @local_specs = @git_proxy = nil
- @cache_path = @install_path = path
+ def set_paths!(path)
+ set_cache_path!(path)
+ set_install_path!(path)
+ end
+
+ def set_cache_path!(path)
+ @git_proxy = nil
+ @cache_path = path
+ end
+
+ def set_install_path!(path)
+ @local_specs = nil
+ @install_path = path
end
def has_app_cache?
- cached_revision && super
+ locked_revision && super
+ end
+
+ def use_app_cache?
+ has_app_cache? && !local?
end
def requires_checkout?
- allow_git_ops? && !local? && !cached_revision_checked_out?
+ allow_git_ops? && !local? && !locked_revision_checked_out?
+ end
+
+ def locked_revision_checked_out?
+ locked_revision && locked_revision == revision && installed?
end
- def cached_revision_checked_out?
- cached_revision && cached_revision == revision && install_path.exist?
+ def installed?
+ git_proxy.installed_to?(install_path)
end
def base_name
@@ -336,7 +401,7 @@ module Bundler
Bundler::Digest.sha1(input)
end
- def cached_revision
+ def locked_revision
options["revision"]
end
@@ -345,13 +410,12 @@ module Bundler
end
def git_proxy
- @git_proxy ||= GitProxy.new(cache_path, uri, options, cached_revision, self)
+ @git_proxy ||= GitProxy.new(cache_path, uri, options, locked_revision, self)
end
def fetch
git_proxy.checkout
rescue GitError => e
- raise unless Bundler.feature_flag.allow_offline_install?
Bundler.ui.warn "Using cached git data because of network errors:\n#{e}"
end
@@ -359,9 +423,12 @@ module Bundler
def validate_spec(_spec); end
def load_gemspec(file)
- stub = Gem::StubSpecification.gemspec_stub(file, install_path.parent, install_path.parent)
- stub.full_gem_path = Pathname.new(file).dirname.expand_path(root).to_s
- StubSpecification.from_stub(stub)
+ dirname = Pathname.new(file).dirname
+ SharedHelpers.chdir(dirname.to_s) do
+ stub = Gem::StubSpecification.gemspec_stub(file, install_path.parent, install_path.parent)
+ stub.full_gem_path = dirname.expand_path(root).to_s
+ StubSpecification.from_stub(stub)
+ end
end
def git_scope
@@ -375,6 +442,10 @@ module Bundler
def override_for(path)
Bundler.settings.local_overrides.key(path)
end
+
+ def bare_repo?(path)
+ File.exist?(path.join("objects")) && File.exist?(path.join("HEAD"))
+ end
end
end
end
diff --git a/lib/bundler/source/git/git_proxy.rb b/lib/bundler/source/git/git_proxy.rb
index 2fc9c6535f..cd352c22a7 100644
--- a/lib/bundler/source/git/git_proxy.rb
+++ b/lib/bundler/source/git/git_proxy.rb
@@ -16,7 +16,7 @@ module Bundler
def initialize(command)
msg = String.new
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 << "this error message could probably be more useful. Please submit a ticket at https://github.com/ruby/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
@@ -121,7 +121,7 @@ module Bundler
FileUtils.rm_rf(p)
end
git "clone", "--no-checkout", "--quiet", path.to_s, destination.to_s
- File.chmod(((File.stat(destination).mode | 0o777) & ~File.umask), destination)
+ File.chmod((File.stat(destination).mode | 0o777) & ~File.umask, destination)
rescue Errno::EEXIST => e
file_path = e.message[%r{.*?((?:[a-zA-Z]:)?/.*)}, 1]
raise GitError, "Bundler could not install a gem because it needs to " \
@@ -147,6 +147,12 @@ module Bundler
end
end
+ def installed_to?(destination)
+ # if copy_to is interrupted, it may leave a partially installed directory that
+ # contains .git but no other files -- consider this not to be installed
+ Dir.exist?(destination) && (Dir.children(destination) - [".git"]).any?
+ end
+
private
def git_remote_fetch(args)
@@ -179,7 +185,8 @@ module Bundler
_, err, status = capture(command, nil)
return extra_ref if status.success?
- if err.include?("Could not find remote branch")
+ if err.include?("Could not find remote branch") || # git up to 2.49
+ err.include?("Remote branch #{branch_option} not found") # git 2.49 or higher
raise MissingGitRevisionError.new(command_with_no_credentials, nil, explicit_ref, credential_filtered_uri)
else
idx = command.index("--depth")
@@ -256,7 +263,7 @@ module Bundler
end
def not_pinned?
- branch || tag || ref.nil?
+ branch_option || ref.nil?
end
def pinned_to_full_sha?
@@ -298,8 +305,8 @@ module Bundler
end
def has_revision_cached?
- return unless @revision && path.exist?
- git("cat-file", "-e", @revision, dir: path)
+ return unless commit && path.exist?
+ git("cat-file", "-e", commit, dir: path)
true
rescue GitError
false
@@ -332,8 +339,6 @@ module Bundler
config_auth = Bundler.settings[remote.to_s] || Bundler.settings[remote.host]
remote.userinfo ||= config_auth
remote.to_s
- elsif File.exist?(uri)
- "file://#{uri}"
else
uri.to_s
end
@@ -403,11 +408,7 @@ module Bundler
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
+ ["git", "-C", dir.to_s, *cmd]
end
def extra_clone_args
@@ -422,7 +423,7 @@ module Bundler
# anyways.
return args if @revision
- args += ["--branch", branch || tag] if branch || tag
+ args += ["--branch", branch_option] if branch_option
args
end
@@ -438,12 +439,12 @@ module Bundler
extra_args
end
- def full_clone?
- depth.nil?
+ def branch_option
+ branch || tag
end
- def supports_minus_c?
- @supports_minus_c ||= Gem::Version.new(version) >= Gem::Version.new("1.8.5")
+ def full_clone?
+ depth.nil?
end
def needs_allow_any_sha1_in_want?
diff --git a/lib/bundler/source/metadata.rb b/lib/bundler/source/metadata.rb
index 6b05e17727..fd959cd64e 100644
--- a/lib/bundler/source/metadata.rb
+++ b/lib/bundler/source/metadata.rb
@@ -24,9 +24,8 @@ module Bundler
s.bindir = "exe"
s.homepage = "https://bundler.io"
s.summary = "The best way to manage your application's dependencies"
- s.executables = %w[bundle]
- # can't point to the actual gemspec or else the require paths will be wrong
- s.loaded_from = __dir__
+ s.executables = %w[bundle bundler]
+ s.loaded_from = SharedHelpers.gemspec_path
end
end
diff --git a/lib/bundler/source/path.rb b/lib/bundler/source/path.rb
index 978b0b2c9f..82e782ba25 100644
--- a/lib/bundler/source/path.rb
+++ b/lib/bundler/source/path.rb
@@ -18,16 +18,13 @@ module Bundler
@options = options.dup
@glob = options["glob"] || DEFAULT_GLOB
- @allow_cached = false
- @allow_remote = false
-
@root_path = options["root_path"] || root
if options["path"]
@path = Pathname.new(options["path"])
expanded_path = expand(@path)
@path = if @path.relative?
- expanded_path.relative_path_from(root_path.expand_path)
+ expanded_path.relative_path_from(File.expand_path(root_path))
else
expanded_path
end
@@ -41,16 +38,6 @@ module Bundler
@original_path = @path
end
- def remote!
- @local_specs = nil
- @allow_remote = true
- end
-
- def cached!
- @local_specs = nil
- @allow_cached = true
- end
-
def self.from_lock(options)
new(options.merge("path" => options.delete("remote")))
end
@@ -66,13 +53,17 @@ module Bundler
"source at `#{@path}`"
end
+ alias_method :identifier, :to_s
+
+ alias_method :to_gemfile, :path
+
def hash
[self.class, expanded_path, version].hash
end
def eql?(other)
- return unless other.class == self.class
- expanded_original_path == other.expanded_original_path &&
+ [Gemspec, Path].include?(other.class) &&
+ expanded_original_path == other.expanded_original_path &&
version == other.version
end
@@ -92,7 +83,7 @@ module Bundler
def cache(spec, custom_path = nil)
app_cache_path = app_cache_path(custom_path)
- return unless Bundler.feature_flag.cache_all?
+ return unless Bundler.settings[:cache_all]
return if expand(@original_path).to_s.index(root_path.to_s + "/") == 0
unless @original_path.exist?
@@ -135,11 +126,7 @@ module Bundler
end
def expand(somepath)
- 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
+ somepath.expand_path(root_path)
rescue ArgumentError => e
Bundler.ui.debug(e)
raise PathError, "There was an error while trying to use the path " \
@@ -161,7 +148,7 @@ module Bundler
def load_gemspec(file)
return unless spec = Bundler.load_gemspec(file)
- Bundler.rubygems.set_installed_by_version(spec)
+ spec.installed_by_version = Gem::VERSION
spec
end
@@ -178,6 +165,13 @@ module Bundler
next unless spec = load_gemspec(file)
spec.source = self
+ # The ignore attribute is for ignoring installed gems that don't
+ # have extensions correctly compiled for activation. In the case of
+ # path sources, there's a single version of each gem in the path
+ # source available to Bundler, so we always certainly want to
+ # consider that for activation and never makes sense to ignore it.
+ spec.ignored = false
+
# Validation causes extension_dir to be calculated, which depends
# on #source, so we validate here instead of load_gemspec
validate_spec(spec)
@@ -225,7 +219,7 @@ module Bundler
# Some gem authors put absolute paths in their gemspec
# and we have to save them from themselves
- spec.files = spec.files.map do |path|
+ spec.files = spec.files.filter_map do |path|
next path unless /\A#{Pathname::SEPARATOR_PAT}/o.match?(path)
next if File.directory?(path)
begin
@@ -233,7 +227,7 @@ module Bundler
rescue ArgumentError
path
end
- end.compact
+ end
installer = Path::Installer.new(
spec,
diff --git a/lib/bundler/source/rubygems.rb b/lib/bundler/source/rubygems.rb
index dafc674f9d..e1e030ffc8 100644
--- a/lib/bundler/source/rubygems.rb
+++ b/lib/bundler/source/rubygems.rb
@@ -8,7 +8,7 @@ module Bundler
autoload :Remote, File.expand_path("rubygems/remote", __dir__)
# Ask for X gems per API request
- API_REQUEST_SIZE = 50
+ API_REQUEST_SIZE = 100
attr_accessor :remotes
@@ -19,15 +19,22 @@ module Bundler
@allow_remote = false
@allow_cached = false
@allow_local = options["allow_local"] || false
+ @prefer_local = false
@checksum_store = Checksum::Store.new
Array(options["remotes"]).reverse_each {|r| add_remote(r) }
+
+ @lockfile_remotes = @remotes if options["from_lockfile"]
end
def caches
@caches ||= [cache_path, *Bundler.rubygems.gem_cache]
end
+ def prefer_local!
+ @prefer_local = true
+ end
+
def local_only!
@specs = nil
@allow_local = true
@@ -35,6 +42,10 @@ module Bundler
@allow_remote = false
end
+ def local_only?
+ @allow_local && !@allow_remote
+ end
+
def local!
return if @allow_local
@@ -91,13 +102,13 @@ module Bundler
def self.from_lock(options)
options["remotes"] = Array(options.delete("remote")).reverse
- new(options)
+ new(options.merge("from_lockfile" => true))
end
def to_lock
out = String.new("GEM\n")
- remotes.reverse_each do |remote|
- out << " remote: #{remove_auth remote}\n"
+ lockfile_remotes.reverse_each do |remote|
+ out << " remote: #{remote}\n"
end
out << " specs:\n"
end
@@ -137,26 +148,26 @@ module Bundler
index.merge!(cached_specs) if @allow_cached
index.merge!(installed_specs) if @allow_local
- # complete with default specs, only if not already available in the
- # index through remote, cached, or installed specs
- index.use(default_specs) if @allow_local
+ if @allow_local
+ if @prefer_local
+ index.merge!(default_specs)
+ else
+ # complete with default specs, only if not already available in the
+ # index through remote, cached, or installed specs
+ index.use(default_specs)
+ end
+ end
index
end
end
def install(spec, options = {})
- if (spec.default_gem? && !cached_built_in_gem(spec)) || (installed?(spec) && !options[:force])
+ if (spec.default_gem? && !cached_built_in_gem(spec, local: options[:local])) || (installed?(spec) && !options[:force])
print_using_message "Using #{version_message(spec, options[:previous_spec])}"
return nil # no post-install message
end
- if spec.remote
- # Check for this spec from other sources
- uris = [spec.remote, *remotes_for_spec(spec)].map(&:anonymized_uri).uniq
- Installer.ambiguous_gems << [spec.name, *uris] if uris.length > 1
- end
-
path = fetch_gem_if_possible(spec, options[:previous_spec])
raise GemNotFound, "Could not find #{spec.file_name} for installation" unless path
@@ -200,10 +211,15 @@ module Bundler
message += " with native extensions" if spec.extensions.any?
Bundler.ui.confirm message
- installed_spec = installer.install
+ installed_spec = nil
+
+ Gem.time("Installed #{spec.name} in", 0, true) do
+ installed_spec = installer.install
+ end
spec.full_gem_path = installed_spec.full_gem_path
spec.loaded_from = installed_spec.loaded_from
+ spec.base_dir = installed_spec.base_dir
spec.post_install_message
end
@@ -219,12 +235,13 @@ module Bundler
raise InstallError, e.message
end
- def cached_built_in_gem(spec)
- cached_path = cached_path(spec)
- if cached_path.nil?
+ def cached_built_in_gem(spec, local: false)
+ cached_path = cached_gem(spec)
+ if cached_path.nil? && !local
remote_spec = remote_specs.search(spec).first
if remote_spec
cached_path = fetch_gem(remote_spec)
+ spec.remote = remote_spec.remote
else
Bundler.ui.warn "#{spec.full_name} is built in to Ruby, and can't be cached because your Gemfile doesn't have any sources that contain it."
end
@@ -313,22 +330,7 @@ module Bundler
remotes.map(&method(:remove_auth))
end
- def remotes_for_spec(spec)
- specs.search_all(spec.name).inject([]) do |uris, s|
- uris << s.remote if s.remote
- uris
- end
- end
-
def cached_gem(spec)
- if spec.default_gem?
- cached_built_in_gem(spec)
- else
- cached_path(spec)
- end
- end
-
- def cached_path(spec)
global_cache_path = download_cache_path(spec)
caches << global_cache_path if global_cache_path
@@ -361,10 +363,7 @@ module Bundler
@installed_specs ||= Index.build do |idx|
Bundler.rubygems.installed_specs.reverse_each do |spec|
spec.source = self
- if Bundler.rubygems.spec_missing_extensions?(spec, false)
- Bundler.ui.debug "Source #{self} is ignoring #{spec} because it is missing extensions"
- next
- end
+ next if spec.ignored?
idx << spec
end
end
@@ -446,7 +445,7 @@ module Bundler
end
def installed?(spec)
- installed_specs[spec].any? && !spec.deleted_gem?
+ installed_specs[spec].any? && !spec.installation_missing?
end
def rubygems_dir
@@ -463,6 +462,10 @@ module Bundler
private
+ def lockfile_remotes
+ @lockfile_remotes || credless_remotes
+ end
+
# 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.
#
@@ -479,7 +482,10 @@ module Bundler
uri = spec.remote.uri
Bundler.ui.confirm("Fetching #{version_message(spec, previous_spec)}")
gem_remote_fetcher = remote_fetchers.fetch(spec.remote).gem_remote_fetcher
- Bundler.rubygems.download_gem(spec, uri, download_cache_path, gem_remote_fetcher)
+
+ Gem.time("Downloaded #{spec.name} in", 0, true) do
+ Bundler.rubygems.download_gem(spec, uri, download_cache_path, gem_remote_fetcher)
+ end
end
# Returns the global cache path of the calling Rubygems::Source object.
@@ -494,7 +500,7 @@ module Bundler
# @return [Pathname] The global cache path.
#
def download_cache_path(spec)
- return unless Bundler.feature_flag.global_gem_cache?
+ return unless Bundler.settings[:global_gem_cache]
return unless remote = spec.remote
return unless cache_slug = remote.cache_slug
diff --git a/lib/bundler/source/rubygems/remote.rb b/lib/bundler/source/rubygems/remote.rb
index 9c5c06de24..ed55912a99 100644
--- a/lib/bundler/source/rubygems/remote.rb
+++ b/lib/bundler/source/rubygems/remote.rb
@@ -16,6 +16,9 @@ module Bundler
@anonymized_uri = remove_auth(@uri).freeze
end
+ MAX_CACHE_SLUG_HOST_SIZE = 255 - 1 - 32 # 255 minus dot minus MD5 length
+ private_constant :MAX_CACHE_SLUG_HOST_SIZE
+
# @return [String] A slug suitable for use as a cache key for this
# remote.
#
@@ -28,10 +31,15 @@ module Bundler
host = cache_uri.to_s.start_with?("file://") ? nil : cache_uri.host
uri_parts = [host, cache_uri.user, cache_uri.port, cache_uri.path]
- uri_digest = SharedHelpers.digest(:MD5).hexdigest(uri_parts.compact.join("."))
+ uri_parts.compact!
+ uri_digest = SharedHelpers.digest(:MD5).hexdigest(uri_parts.join("."))
+
+ uri_parts.pop
+ host_parts = uri_parts.join(".")
+ return uri_digest if host_parts.empty?
- uri_parts[-1] = uri_digest
- uri_parts.compact.join(".")
+ shortened_host_parts = host_parts[0...MAX_CACHE_SLUG_HOST_SIZE]
+ [shortened_host_parts, uri_digest].join(".")
end
end
diff --git a/lib/bundler/source_list.rb b/lib/bundler/source_list.rb
index 5f9dd68f17..38fa0972e6 100644
--- a/lib/bundler/source_list.rb
+++ b/lib/bundler/source_list.rb
@@ -9,7 +9,7 @@ module Bundler
:metadata_source
def global_rubygems_source
- @global_rubygems_source ||= rubygems_aggregate_class.new("allow_local" => true)
+ @global_rubygems_source ||= source_class.new("allow_local" => true)
end
def initialize
@@ -21,19 +21,9 @@ module Bundler
@rubygems_sources = []
@metadata_source = Source::Metadata.new
- @merged_gem_lockfile_sections = false
@local_mode = true
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
@@ -90,10 +80,6 @@ module Bundler
@rubygems_sources
end
- def rubygems_remotes
- rubygems_sources.map(&:remotes).flatten.uniq
- end
-
def all_sources
path_sources + git_sources + plugin_sources + rubygems_sources + [metadata_source]
end
@@ -103,7 +89,7 @@ module Bundler
end
def get(source)
- source_list_for(source).find {|s| equivalent_source?(source, s) }
+ source_list_for(source).find {|s| s.include?(source) }
end
def lock_sources
@@ -115,11 +101,7 @@ module Bundler
end
def lock_rubygems_sources
- if merged_gem_lockfile_sections?
- [combine_rubygems_sources]
- else
- rubygems_sources.sort_by(&:identifier)
- end
+ rubygems_sources.sort_by(&:identifier)
end
# Returns true if there are changes
@@ -129,16 +111,11 @@ module Bundler
@rubygems_sources, @path_sources, @git_sources, @plugin_sources = map_sources(replacement_sources)
@global_rubygems_source = global_replacement_source(replacement_sources)
- different_sources?(lock_sources, replacement_sources)
+ !equivalent_sources?(lock_sources, replacement_sources)
end
- # 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)
+ def prefer_local!
+ all_sources.each(&:prefer_local!)
end
def local_only!
@@ -161,52 +138,60 @@ module Bundler
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 = @rubygems_sources.map do |source|
- replace_rubygems_source(replacement_sources, source) || source
+ replace_rubygems_source(replacement_sources, source)
end
git, plugin = [@git_sources, @plugin_sources].map do |sources|
sources.map do |source|
- replacement_sources.find {|s| s == source } || source
+ replace_source(replacement_sources, source)
end
end
path = @path_sources.map do |source|
- replacement_sources.find {|s| s == (source.is_a?(Source::Gemspec) ? source.as_path_source : source) } || source
+ replace_path_source(replacement_sources, source)
end
[rubygems, path, git, plugin]
end
def global_replacement_source(replacement_sources)
- replacement_source = replace_rubygems_source(replacement_sources, global_rubygems_source)
- return global_rubygems_source unless replacement_source
-
- replacement_source.local!
- replacement_source
+ replace_rubygems_source(replacement_sources, global_rubygems_source, &:local!)
end
def replace_rubygems_source(replacement_sources, gemfile_source)
+ replace_source(replacement_sources, gemfile_source) do |replacement_source|
+ # locked sources never include credentials so always prefer remotes from the gemfile
+ replacement_source.remotes = gemfile_source.remotes
+
+ yield replacement_source if block_given?
+
+ replacement_source
+ end
+ end
+
+ def replace_source(replacement_sources, gemfile_source)
replacement_source = replacement_sources.find {|s| s == gemfile_source }
- return unless replacement_source
+ return gemfile_source unless replacement_source
+
+ replacement_source = yield(replacement_source) if block_given?
- # locked sources never include credentials so always prefer remotes from the gemfile
- replacement_source.remotes = gemfile_source.remotes
replacement_source
end
- def different_sources?(lock_sources, replacement_sources)
- !equivalent_sources?(lock_sources, replacement_sources)
+ def replace_path_source(replacement_sources, gemfile_source)
+ replace_source(replacement_sources, gemfile_source) do |replacement_source|
+ if gemfile_source.is_a?(Source::Gemspec)
+ gemfile_source.checksum_store = replacement_source.checksum_store
+ gemfile_source
+ else
+ replacement_source
+ end
+ end
end
- def rubygems_aggregate_class
+ def source_class
Source::Rubygems
end
@@ -225,10 +210,6 @@ module Bundler
end
end
- def combine_rubygems_sources
- Source::Rubygems.new("remotes" => rubygems_remotes)
- end
-
def warn_on_git_protocol(source)
return if Bundler.settings["git.allow_insecure"]
@@ -243,9 +224,5 @@ module Bundler
def equivalent_sources?(lock_sources, replacement_sources)
lock_sources.sort_by(&:identifier) == replacement_sources.sort_by(&:identifier)
end
-
- def equivalent_source?(source, other_source)
- source == other_source
- end
end
end
diff --git a/lib/bundler/source_map.rb b/lib/bundler/source_map.rb
index ca73e01f9d..cb88caf1bd 100644
--- a/lib/bundler/source_map.rb
+++ b/lib/bundler/source_map.rb
@@ -23,15 +23,12 @@ module Bundler
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 << "You must 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}"
+ raise SecurityError, msg
end
end
diff --git a/lib/bundler/spec_set.rb b/lib/bundler/spec_set.rb
index 2933d28450..f9179e7a06 100644
--- a/lib/bundler/spec_set.rb
+++ b/lib/bundler/spec_set.rb
@@ -7,74 +7,81 @@ module Bundler
include Enumerable
include TSort
- attr_reader :incomplete_specs
-
- def initialize(specs, incomplete_specs = [])
+ def initialize(specs)
@specs = specs
- @incomplete_specs = incomplete_specs
end
- def for(dependencies, check = false, platforms = [nil])
- handled = ["bundler"].product(platforms).map {|k| [k, true] }.to_h
- deps = dependencies.product(platforms)
- specs = []
-
- loop do
- break unless dep = deps.shift
+ def for(dependencies, platforms = [nil], legacy_platforms = [nil], skips: [])
+ if [true, false].include?(platforms)
+ Bundler::SharedHelpers.feature_removed! \
+ "SpecSet#for received a `check` parameter, but that's no longer used and deprecated. " \
+ "SpecSet#for always implicitly performs validation. Please remove this parameter"
+ end
- name = dep[0].name
- platform = dep[1]
- incomplete = false
+ materialize_dependencies(dependencies, platforms, skips: skips)
- key = [name, platform]
- next if handled.key?(key)
+ @materializations.flat_map(&:specs).uniq
+ end
- handled[key] = true
+ def normalize_platforms!(deps, platforms)
+ remove_invalid_platforms!(deps, platforms)
+ add_extra_platforms!(platforms)
- specs_for_dep = specs_for_dependency(*dep)
- if specs_for_dep.any?
- specs.concat(specs_for_dep)
+ platforms.map! do |platform|
+ next platform if platform == Gem::Platform::RUBY
- specs_for_dep.first.dependencies.each do |d|
- next if d.type == :development
- incomplete = true if d.name != "bundler" && lookup[d.name].nil?
- deps << [d, dep[1]]
- end
- else
- incomplete = true
+ begin
+ Integer(platform.version)
+ rescue ArgumentError, TypeError
+ next platform
end
- if incomplete && check
- @incomplete_specs += lookup[name] || [LazySpecification.new(name, nil, nil)]
- end
+ less_specific_platform = Gem::Platform.new([platform.cpu, platform.os, nil])
+ next platform if incomplete_for_platform?(deps, less_specific_platform)
+
+ less_specific_platform
+ end.uniq!
+ end
+
+ def add_originally_invalid_platforms!(platforms, originally_invalid_platforms)
+ originally_invalid_platforms.each do |originally_invalid_platform|
+ platforms << originally_invalid_platform if complete_platform(originally_invalid_platform)
+ end
+ end
+
+ def remove_invalid_platforms!(deps, platforms, skips: [])
+ invalid_platforms = []
+
+ platforms.reject! do |platform|
+ next false if skips.include?(platform)
+
+ invalid = incomplete_for_platform?(deps, platform)
+ invalid_platforms << platform if invalid
+ invalid
end
- specs.uniq
+ invalid_platforms
end
def add_extra_platforms!(platforms)
- return platforms.concat([Gem::Platform::RUBY]).uniq if @specs.empty?
+ if @specs.empty?
+ platforms.concat([Gem::Platform::RUBY]).uniq
+ return
+ end
new_platforms = all_platforms.select do |platform|
next if platforms.include?(platform)
- next unless GemHelpers.generic(platform) == Gem::Platform::RUBY
+ next unless Gem::Platform.generic(platform) == Gem::Platform::RUBY
complete_platform(platform)
end
- return platforms if new_platforms.empty?
+ return if new_platforms.empty?
platforms.concat(new_platforms)
+ return if new_platforms.include?(Bundler.local_platform)
less_specific_platform = new_platforms.find {|platform| platform != Gem::Platform::RUBY && Bundler.local_platform === platform && platform === Bundler.local_platform }
platforms.delete(Bundler.local_platform) if less_specific_platform
-
- platforms
- end
-
- def complete_platforms!(platforms)
- platforms.each do |platform|
- complete_platform(platform)
- end
end
def validate_deps(s)
@@ -94,15 +101,13 @@ module Bundler
end
def []=(key, value)
- @specs << value
+ delete_by_name(key)
- reset!
+ add_spec(value)
end
def delete(specs)
- specs.each {|spec| @specs.delete(spec) }
-
- reset!
+ Array(specs).each {|spec| remove_spec(spec) }
end
def sort!
@@ -118,50 +123,78 @@ module Bundler
end
def materialize(deps)
- materialized = self.for(deps, true)
+ materialize_dependencies(deps)
- SpecSet.new(materialized, incomplete_specs)
+ SpecSet.new(materialized_specs)
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<Gem::Specification>]
def materialized_for_all_platforms
@specs.map do |s|
next s unless s.is_a?(LazySpecification)
- s.source.remote!
- spec = s.materialize_for_installation
+ spec = s.materialize_for_cache
raise GemNotFound, "Could not find #{s.full_name} in any of the sources" unless spec
spec
end
end
def incomplete_for_platform?(deps, platform)
- return false if @specs.empty?
+ incomplete_specs_for_platform(deps, platform).any?
+ end
- @incomplete_specs = []
+ def incomplete_specs_for_platform(deps, platform)
+ return [] if @specs.empty?
- self.for(deps, true, [platform])
+ validation_set = self.class.new(@specs)
+ validation_set.for(deps, [platform])
+ validation_set.incomplete_specs
+ end
+
+ def missing_specs_for(deps)
+ materialize_dependencies(deps)
- @incomplete_specs.any?
+ missing_specs
end
def missing_specs
- @specs.select {|s| s.is_a?(LazySpecification) }
+ @materializations.flat_map(&:completely_missing_specs)
+ end
+
+ def partially_missing_specs
+ @materializations.flat_map(&:partially_missing_specs)
+ end
+
+ def incomplete_specs
+ @materializations.flat_map(&:incomplete_specs)
+ end
+
+ def insecurely_materialized_specs
+ materialized_specs.select(&:insecurely_materialized?)
end
def -(other)
- SpecSet.new(to_a - other.to_a)
+ SharedHelpers.feature_removed! "SpecSet#- has been removed with no replacement"
end
def find_by_name_and_platform(name, platform)
- @specs.detect {|spec| spec.name == name && spec.match_platform(platform) }
+ @specs.detect {|spec| spec.name == name && spec.installable_on_platform?(platform) }
+ end
+
+ def specs_with_additional_variants_from(other)
+ sorted | additional_variants_from(other)
end
def delete_by_name(name)
@specs.reject! {|spec| spec.name == name }
+ @sorted&.reject! {|spec| spec.name == name }
+ return if @lookup.nil?
+
+ @lookup[name] = nil
+ end
- reset!
+ def version_for(name)
+ exemplary_spec(name)&.version
end
def what_required(spec)
@@ -172,7 +205,7 @@ module Bundler
end
def <<(spec)
- @specs << spec
+ SharedHelpers.feature_removed! "SpecSet#<< has been removed with no replacement"
end
def length
@@ -195,11 +228,45 @@ module Bundler
lookup.keys
end
+ def valid?(s)
+ s.matches_current_metadata? && valid_dependencies?(s)
+ end
+
+ def to_s
+ map(&:full_name).to_s
+ end
+
private
- def reset!
- @sorted = nil
- @lookup = nil
+ def materialize_dependencies(dependencies, platforms = [nil], skips: [])
+ handled = ["bundler"].product(platforms).map {|k| [k, true] }.to_h
+ deps = dependencies.product(platforms)
+ @materializations = []
+
+ loop do
+ break unless dep = deps.shift
+
+ dependency = dep[0]
+ platform = dep[1]
+ name = dependency.name
+
+ key = [name, platform]
+ next if handled.key?(key)
+
+ handled[key] = true
+
+ materialization = Materialization.new(dependency, platform, candidates: lookup[name])
+
+ deps.concat(materialization.dependencies) if materialization.complete?
+
+ @materializations << materialization unless skips.include?(name)
+ end
+
+ @materializations
+ end
+
+ def materialized_specs
+ @materializations.filter_map(&:materialized_spec)
end
def complete_platform(platform)
@@ -208,8 +275,8 @@ module Bundler
valid_platform = lookup.all? do |_, specs|
spec = specs.first
matching_specs = spec.source.specs.search([spec.name, spec.version])
- platform_spec = GemHelpers.select_best_platform_match(matching_specs, platform).find do |s|
- s.matches_current_metadata? && valid_dependencies?(s)
+ platform_spec = MatchPlatform.select_best_platform_match(matching_specs, platform).find do |s|
+ valid?(s)
end
if platform_spec
@@ -221,9 +288,7 @@ module Bundler
end
if valid_platform && new_specs.any?
- @specs.concat(new_specs)
-
- reset!
+ new_specs.each {|spec| add_spec(spec) }
end
valid_platform
@@ -233,20 +298,28 @@ module Bundler
@specs.flat_map {|spec| spec.source.specs.search([spec.name, spec.version]).map(&:platform) }.uniq
end
+ def additional_variants_from(other)
+ other.select do |other_spec|
+ spec = exemplary_spec(other_spec.name)
+ next unless spec
+
+ selected = spec.version == other_spec.version && valid_dependencies?(other_spec)
+ other_spec.source = spec.source if selected
+ selected
+ end
+ end
+
def valid_dependencies?(s)
validate_deps(s) == :valid
end
def sorted
- rake = @specs.find {|s| s.name == "rake" }
- begin
- @sorted ||= ([rake] + tsort).compact.uniq
- rescue TSort::Cyclic => error
- cgems = extract_circular_gems(error)
- raise CyclicDependencyError, "Your bundle requires gems that depend" \
- " on each other, creating an infinite loop. Please remove either" \
- " gem '#{cgems[0]}' or gem '#{cgems[1]}' and try again."
- end
+ @sorted ||= ([@specs.find {|s| s.name == "rake" }] + tsort).compact.uniq
+ rescue TSort::Cyclic => error
+ cgems = extract_circular_gems(error)
+ raise CyclicDependencyError, "Your bundle requires gems that depend" \
+ " on each other, creating an infinite loop. Please remove either" \
+ " gem '#{cgems[0]}' or gem '#{cgems[1]}' and try again."
end
def extract_circular_gems(error)
@@ -257,8 +330,7 @@ module Bundler
@lookup ||= begin
lookup = {}
@specs.each do |s|
- lookup[s.name] ||= []
- lookup[s.name] << s
+ index_spec(lookup, s.name, s)
end
lookup
end
@@ -269,19 +341,6 @@ module Bundler
@specs.sort_by(&:name).each {|s| yield s }
end
- def specs_for_dependency(dep, platform)
- specs_for_name = lookup[dep.name]
- return [] unless specs_for_name
-
- matching_specs = if dep.force_ruby_platform
- GemHelpers.force_ruby_platform(specs_for_name)
- else
- GemHelpers.select_best_platform_match(specs_for_name, platform || Bundler.local_platform)
- end
- matching_specs.map!(&:materialize_for_installation).compact! if platform.nil?
- matching_specs
- end
-
def tsort_each_child(s)
s.dependencies.sort_by(&:name).each do |d|
next if d.type == :development
@@ -292,5 +351,40 @@ module Bundler
specs_for_name.each {|s2| yield s2 }
end
end
+
+ def add_spec(spec)
+ @specs << spec
+
+ name = spec.name
+
+ @sorted&.insert(@sorted.bsearch_index {|s| s.name >= name } || @sorted.size, spec)
+ return if @lookup.nil?
+
+ index_spec(@lookup, name, spec)
+ end
+
+ def remove_spec(spec)
+ @specs.delete(spec)
+ @sorted&.delete(spec)
+ return if @lookup.nil?
+
+ indexed_specs = @lookup[spec.name]
+ return unless indexed_specs
+
+ if indexed_specs.size > 1
+ @lookup[spec.name].delete(spec)
+ else
+ @lookup[spec.name] = nil
+ end
+ end
+
+ def index_spec(hash, key, value)
+ hash[key] ||= []
+ hash[key] << value
+ end
+
+ def exemplary_spec(name)
+ self[name].first
+ end
end
end
diff --git a/lib/bundler/stub_specification.rb b/lib/bundler/stub_specification.rb
index da830cf8d4..026f753d41 100644
--- a/lib/bundler/stub_specification.rb
+++ b/lib/bundler/stub_specification.rb
@@ -9,6 +9,10 @@ module Bundler
spec
end
+ def insecurely_materialized?
+ false
+ end
+
attr_reader :checksum
attr_accessor :stub, :ignored
@@ -28,6 +32,17 @@ module Bundler
# @!group Stub Delegates
+ def ignored?
+ return @ignored unless @ignored.nil?
+
+ @ignored = missing_extensions?
+ return false unless @ignored
+
+ warn "Source #{source} is ignoring #{self} because it is missing extensions"
+
+ true
+ end
+
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
@@ -45,8 +60,8 @@ module Bundler
true
end
- def activated
- stub.activated
+ def activated?
+ stub.activated?
end
def activated=(activated)
@@ -77,6 +92,14 @@ module Bundler
stub.full_require_paths
end
+ def require_paths
+ stub.require_paths
+ end
+
+ def base_dir=(path)
+ stub.base_dir = path
+ end
+
def load_paths
full_require_paths
end
@@ -93,6 +116,10 @@ module Bundler
stub.raw_require_paths
end
+ def inspect
+ "#<#{self.class} @name=\"#{name}\" (#{full_name.delete_prefix("#{name}-")})>"
+ end
+
private
def _remote_specification
diff --git a/lib/bundler/templates/Executable b/lib/bundler/templates/Executable
index 9ff6f00898..b085c24da6 100644
--- a/lib/bundler/templates/Executable
+++ b/lib/bundler/templates/Executable
@@ -10,17 +10,6 @@
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("<%= relative_gemfile_path %>", __dir__)
-bundle_binstub = File.expand_path("bundle", __dir__)
-
-if File.file?(bundle_binstub)
- if File.read(bundle_binstub, 300).include?("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"
diff --git a/lib/bundler/templates/Executable.bundler b/lib/bundler/templates/Executable.bundler
deleted file mode 100644
index caa2021701..0000000000
--- a/lib/bundler/templates/Executable.bundler
+++ /dev/null
@@ -1,109 +0,0 @@
-#!/usr/bin/env <%= Bundler.settings[:shebang] || RbConfig::CONFIG["ruby_install_name"] %>
-# frozen_string_literal: true
-
-#
-# This file was generated by Bundler.
-#
-# The application '<%= executable %>' 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.match?(Gem::Version::ANCHORED_VERSION_PATTERN)
- bundler_version = a
- end
- next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
- bundler_version = $1
- update_index = i
- end
- bundler_version
- end
-
- def gemfile
- gemfile = ENV["BUNDLE_GEMFILE"]
- return gemfile if gemfile && !gemfile.empty?
-
- File.expand_path("<%= relative_gemfile_path %>", __dir__)
- end
-
- def lockfile
- lockfile =
- case File.basename(gemfile)
- when "gems.rb" then gemfile.sub(/\.rb$/, ".locked")
- 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_requirement
- @bundler_requirement ||=
- env_var_version ||
- cli_arg_version ||
- bundler_requirement_for(lockfile_version)
- end
-
- def bundler_requirement_for(version)
- return "#{Gem::Requirement.default}.a" unless version
-
- bundler_gem_version = Gem::Version.new(version)
-
- bundler_gem_version.approximate_recommendation
- end
-
- def load_bundler!
- ENV["BUNDLE_GEMFILE"] ||= gemfile
-
- activate_bundler
- end
-
- def activate_bundler
- gem_error = activation_error_handling do
- gem "bundler", bundler_requirement
- 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_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION))
- warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`"
- 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("<%= spec.name %>", "<%= executable %>")
-end
diff --git a/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt b/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt
index 67fe8cee79..633baebdd5 100644
--- a/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt
+++ b/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt
@@ -1,132 +1,10 @@
-# Contributor Covenant Code of Conduct
+# Code of Conduct
-## Our Pledge
+<%= config[:name].inspect %> follows [The Ruby Community Conduct Guideline](https://www.ruby-lang.org/en/conduct) in all "collaborative space", which is defined as community communications channels (such as mailing lists, submitted patches, commit comments, etc.):
-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, caste, color, religion, or sexual
-identity and orientation.
+* Participants will be tolerant of opposing views.
+* Participants must ensure that their language and actions are free of personal attacks and disparaging personal remarks.
+* When interpreting the words and actions of others, participants should always assume good intentions.
+* Behaviour which can be reasonably considered harassment will not be tolerated.
-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 a positive environment for our
-community include:
-
-* 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 include:
-
-* 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 email address,
- without their explicit permission
-* Other conduct which could reasonably be considered inappropriate in a
- professional setting
-
-## Enforcement Responsibilities
-
-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.
-
-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 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 email 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 to the community leaders responsible for enforcement at
-[INSERT CONTACT METHOD].
-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.
-
-**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 2.1, available at
-[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
-
-Community Impact Guidelines were inspired by
-[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
-
-For answers to common questions about this code of conduct, see the FAQ at
-[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
-[https://www.contributor-covenant.org/translations][translations].
-
-[homepage]: https://www.contributor-covenant.org
-[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
-[Mozilla CoC]: https://github.com/mozilla/diversity
-[FAQ]: https://www.contributor-covenant.org/faq
-[translations]: https://www.contributor-covenant.org/translations
+If you have any concerns about behaviour within this project, please contact us at [<%= config[:email].inspect %>](mailto:<%= config[:email].inspect %>).
diff --git a/lib/bundler/templates/newgem/Gemfile.tt b/lib/bundler/templates/newgem/Gemfile.tt
index a0d2ac2826..ea7a33ee28 100644
--- a/lib/bundler/templates/newgem/Gemfile.tt
+++ b/lib/bundler/templates/newgem/Gemfile.tt
@@ -5,13 +5,11 @@ source "https://rubygems.org"
# Specify your gem's dependencies in <%= config[:name] %>.gemspec
gemspec
+gem "irb"
gem "rake", "~> 13.0"
<%- if config[:ext] -%>
gem "rake-compiler"
-<%- if config[:ext] == 'rust' -%>
-gem "rb_sys", "~> 0.9.63"
-<%- end -%>
<%- end -%>
<%- if config[:test] -%>
diff --git a/lib/bundler/templates/newgem/README.md.tt b/lib/bundler/templates/newgem/README.md.tt
index 5bf36378e8..0ec6a12fa7 100644
--- a/lib/bundler/templates/newgem/README.md.tt
+++ b/lib/bundler/templates/newgem/README.md.tt
@@ -10,11 +10,15 @@ TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_O
Install the gem and add to the application's Gemfile by executing:
- $ bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
+```bash
+bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
+```
If bundler is not being used to manage dependencies, install the gem by executing:
- $ gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
+```bash
+gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
+```
## Usage
@@ -22,7 +26,7 @@ TODO: Write usage instructions here
## Development
-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 %>
+After checking out the repo, run `bin/setup` to install dependencies.<% if config[:test] %> Then, run `rake <%= config[:test_task] %>` 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 the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
<% if config[:git] -%>
diff --git a/lib/bundler/templates/newgem/Rakefile.tt b/lib/bundler/templates/newgem/Rakefile.tt
index 172183d4b4..83f10009c7 100644
--- a/lib/bundler/templates/newgem/Rakefile.tt
+++ b/lib/bundler/templates/newgem/Rakefile.tt
@@ -59,6 +59,11 @@ Rake::ExtensionTask.new("<%= config[:underscored_name] %>", GEMSPEC) do |ext|
end
<% end -%>
+<% if config[:ext] == "go" -%>
+require "go_gem/rake_task"
+
+GoGem::RakeTask.new("<%= config[:underscored_name] %>")
+<% end -%>
<% end -%>
<% if default_task_names.size == 1 -%>
task default: <%= default_task_names.first.inspect %>
diff --git a/lib/bundler/templates/newgem/circleci/config.yml.tt b/lib/bundler/templates/newgem/circleci/config.yml.tt
index f40f029bf1..c4dd9d0647 100644
--- a/lib/bundler/templates/newgem/circleci/config.yml.tt
+++ b/lib/bundler/templates/newgem/circleci/config.yml.tt
@@ -7,6 +7,10 @@ jobs:
environment:
RB_SYS_FORCE_INSTALL_RUST_TOOLCHAIN: 'true'
<%- end -%>
+<%- if config[:ext] == 'go' -%>
+ environment:
+ GO_VERSION: '1.23.0'
+<%- end -%>
steps:
- checkout
<%- if config[:ext] == 'rust' -%>
@@ -17,6 +21,14 @@ jobs:
name: Install a RubyGems version that can compile rust extensions
command: gem update --system '<%= ::Gem.rubygems_version %>'
<%- end -%>
+<%- if config[:ext] == 'go' -%>
+ - run:
+ name: Install Go
+ command: |
+ wget https://go.dev/dl/go$GO_VERSION.linux-amd64.tar.gz -O /tmp/go.tar.gz
+ tar -C /usr/local -xzf /tmp/go.tar.gz
+ echo 'export PATH=/usr/local/go/bin:"$PATH"' >> "$BASH_ENV"
+<%- end -%>
- run:
name: Run the default task
command: |
diff --git a/lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt b/lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt
index 0ebce0e4a0..c0dc63fbfa 100644
--- a/lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt
+++ b/lib/bundler/templates/newgem/ext/newgem/Cargo.toml.tt
@@ -12,4 +12,4 @@ publish = false
crate-type = ["cdylib"]
[dependencies]
-magnus = { version = "0.6.2" }
+magnus = { version = "0.8.2" }
diff --git a/lib/bundler/templates/newgem/ext/newgem/extconf-go.rb.tt b/lib/bundler/templates/newgem/ext/newgem/extconf-go.rb.tt
new file mode 100644
index 0000000000..a689e21ebe
--- /dev/null
+++ b/lib/bundler/templates/newgem/ext/newgem/extconf-go.rb.tt
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require "mkmf"
+require "go_gem/mkmf"
+
+# Makes all symbols private by default to avoid unintended conflict
+# with other gems. To explicitly export symbols you can use RUBY_FUNC_EXPORTED
+# selectively, or entirely remove this flag.
+append_cflags("-fvisibility=hidden")
+
+create_go_makefile(<%= config[:makefile_path].inspect %>)
diff --git a/lib/bundler/templates/newgem/ext/newgem/go.mod.tt b/lib/bundler/templates/newgem/ext/newgem/go.mod.tt
new file mode 100644
index 0000000000..3f4819d004
--- /dev/null
+++ b/lib/bundler/templates/newgem/ext/newgem/go.mod.tt
@@ -0,0 +1,5 @@
+module github.com/<%= config[:go_module_username] %>/<%= config[:underscored_name] %>
+
+go 1.23
+
+require github.com/ruby-go-gem/go-gem-wrapper latest
diff --git a/lib/bundler/templates/newgem/ext/newgem/newgem-go.c.tt b/lib/bundler/templates/newgem/ext/newgem/newgem-go.c.tt
new file mode 100644
index 0000000000..119c0c96ea
--- /dev/null
+++ b/lib/bundler/templates/newgem/ext/newgem/newgem-go.c.tt
@@ -0,0 +1,2 @@
+#include "<%= config[:underscored_name] %>.h"
+#include "_cgo_export.h"
diff --git a/lib/bundler/templates/newgem/ext/newgem/newgem.go.tt b/lib/bundler/templates/newgem/ext/newgem/newgem.go.tt
new file mode 100644
index 0000000000..f19b750e58
--- /dev/null
+++ b/lib/bundler/templates/newgem/ext/newgem/newgem.go.tt
@@ -0,0 +1,31 @@
+package main
+
+/*
+#include "<%= config[:underscored_name] %>.h"
+
+VALUE rb_<%= config[:underscored_name] %>_sum(VALUE self, VALUE a, VALUE b);
+*/
+import "C"
+
+import (
+ "github.com/ruby-go-gem/go-gem-wrapper/ruby"
+)
+
+//export rb_<%= config[:underscored_name] %>_sum
+func rb_<%= config[:underscored_name] %>_sum(_ C.VALUE, a C.VALUE, b C.VALUE) C.VALUE {
+ longA := ruby.NUM2LONG(ruby.VALUE(a))
+ longB := ruby.NUM2LONG(ruby.VALUE(b))
+
+ sum := longA + longB
+
+ return C.VALUE(ruby.LONG2NUM(sum))
+}
+
+//export Init_<%= config[:underscored_name] %>
+func Init_<%= config[:underscored_name] %>() {
+ rb_m<%= config[:constant_array].join %> := ruby.RbDefineModule(<%= config[:constant_name].inspect %>)
+ ruby.RbDefineSingletonMethod(rb_m<%= config[:constant_array].join %>, "sum", C.rb_<%= config[:underscored_name] %>_sum, 2)
+}
+
+func main() {
+}
diff --git a/lib/bundler/templates/newgem/github/workflows/main.yml.tt b/lib/bundler/templates/newgem/github/workflows/main.yml.tt
index 32b39558d8..7f3e3a5b66 100644
--- a/lib/bundler/templates/newgem/github/workflows/main.yml.tt
+++ b/lib/bundler/templates/newgem/github/workflows/main.yml.tt
@@ -17,21 +17,29 @@ jobs:
- '<%= RUBY_VERSION %>'
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v4
+ with:
+ persist-credentials: false
<%- if config[:ext] == 'rust' -%>
- - name: Set up Ruby & Rust
- uses: oxidize-rb/actions/setup-ruby-and-rust@v1
- with:
- ruby-version: ${{ matrix.ruby }}
- bundler-cache: true
- cargo-cache: true
- rubygems: '<%= ::Gem.rubygems_version %>'
+ - name: Set up Ruby & Rust
+ uses: oxidize-rb/actions/setup-ruby-and-rust@v1
+ with:
+ ruby-version: ${{ matrix.ruby }}
+ bundler-cache: true
+ cargo-cache: true
+ rubygems: '<%= ::Gem.rubygems_version %>'
<%- else -%>
- - name: Set up Ruby
- uses: ruby/setup-ruby@v1
- with:
- ruby-version: ${{ matrix.ruby }}
- bundler-cache: true
+ - name: Set up Ruby
+ uses: ruby/setup-ruby@v1
+ with:
+ ruby-version: ${{ matrix.ruby }}
+ bundler-cache: true
<%- end -%>
- - name: Run the default task
- run: bundle exec rake
+<%- if config[:ext] == 'go' -%>
+ - name: Setup Go
+ uses: actions/setup-go@v5
+ with:
+ go-version-file: ext/<%= config[:underscored_name] %>/go.mod
+<%- end -%>
+ - name: Run the default task
+ run: bundle exec rake
diff --git a/lib/bundler/templates/newgem/gitlab-ci.yml.tt b/lib/bundler/templates/newgem/gitlab-ci.yml.tt
index d2e1f33736..adbd70cbc0 100644
--- a/lib/bundler/templates/newgem/gitlab-ci.yml.tt
+++ b/lib/bundler/templates/newgem/gitlab-ci.yml.tt
@@ -6,6 +6,11 @@ default:
- apt-get update && apt-get install -y clang
- gem update --system '<%= ::Gem.rubygems_version %>'
<%- end -%>
+<%- if config[:ext] == 'go' -%>
+ - wget https://go.dev/dl/go$GO_VERSION.linux-amd64.tar.gz -O /tmp/go.tar.gz
+ - tar -C /usr/local -xzf /tmp/go.tar.gz
+ - export PATH=/usr/local/go/bin:$PATH
+<%- end -%>
- gem install bundler -v <%= Bundler::VERSION %>
- bundle install
@@ -14,5 +19,9 @@ example_job:
variables:
RB_SYS_FORCE_INSTALL_RUST_TOOLCHAIN: 'true'
<%- end -%>
+<%- if config[:ext] == 'go' -%>
+ variables:
+ GO_VERSION: '1.23.0'
+<%- end -%>
script:
- bundle exec rake
diff --git a/lib/bundler/templates/newgem/lib/newgem.rb.tt b/lib/bundler/templates/newgem/lib/newgem.rb.tt
index caf6e32f4a..3aedee0d25 100644
--- a/lib/bundler/templates/newgem/lib/newgem.rb.tt
+++ b/lib/bundler/templates/newgem/lib/newgem.rb.tt
@@ -2,7 +2,7 @@
require_relative "<%= File.basename(config[:namespaced_path]) %>/version"
<%- if config[:ext] -%>
-require_relative "<%= File.basename(config[:namespaced_path]) %>/<%= config[:underscored_name] %>"
+require "<%= File.basename(config[:namespaced_path]) %>/<%= config[:underscored_name] %>"
<%- end -%>
<%- config[:constant_array].each_with_index do |c, i| -%>
diff --git a/lib/bundler/templates/newgem/newgem.gemspec.tt b/lib/bundler/templates/newgem/newgem.gemspec.tt
index 6e88f4dab1..513875fd63 100644
--- a/lib/bundler/templates/newgem/newgem.gemspec.tt
+++ b/lib/bundler/templates/newgem/newgem.gemspec.tt
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
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."
+ spec.homepage = "<%= config[:homepage_uri] %>"
<%- if config[:mit] -%>
spec.license = "MIT"
<%- end -%>
@@ -20,10 +20,11 @@ Gem::Specification.new do |spec|
<%- end -%>
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."
- spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
+ spec.metadata["source_code_uri"] = "<%= config[:source_code_uri] %>"
+<%- if config[:changelog] -%>
+ spec.metadata["changelog_uri"] = "<%= config[:changelog_uri] %>"
+<%- end -%>
# 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.
@@ -31,21 +32,24 @@ Gem::Specification.new do |spec|
spec.files = IO.popen(%w[git ls-files -z], chdir: __dir__, err: IO::NULL) do |ls|
ls.readlines("\x0", chomp: true).reject do |f|
(f == gemspec) ||
- f.start_with?(*%w[bin/ test/ spec/ features/ .git <%= config[:ci_config_path] %>appveyor Gemfile])
+ f.start_with?(*%w[<%= config[:ignore_paths].join(" ") %>])
end
end
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
-<%- if config[:ext] == 'c' -%>
+<%- if %w(c rust go).include?(config[:ext]) -%>
spec.extensions = ["ext/<%= config[:underscored_name] %>/extconf.rb"]
<%- end -%>
-<%- if config[:ext] == 'rust' -%>
- spec.extensions = ["ext/<%= config[:underscored_name] %>/Cargo.toml"]
-<%- end -%>
# Uncomment to register a new dependency of your gem
# spec.add_dependency "example-gem", "~> 1.0"
+<%- if config[:ext] == 'rust' -%>
+ spec.add_dependency "rb_sys", "~> 0.9.91"
+<%- end -%>
+<%- if config[:ext] == 'go' -%>
+ spec.add_dependency "go_gem", "~> 0.2"
+<%- end -%>
# For more information and examples about making a new gem, check out our
# guide at: https://bundler.io/guides/creating_gem.html
diff --git a/lib/bundler/ui/shell.rb b/lib/bundler/ui/shell.rb
index 4555612dbb..b836208da8 100644
--- a/lib/bundler/ui/shell.rb
+++ b/lib/bundler/ui/shell.rb
@@ -6,14 +6,18 @@ module Bundler
module UI
class Shell
LEVELS = %w[silent error warn confirm info debug].freeze
+ OUTPUT_STREAMS = [:stdout, :stderr].freeze
attr_writer :shell
+ attr_reader :output_stream
def initialize(options = {})
Thor::Base.shell = options["no-color"] ? Thor::Shell::Basic : nil
@shell = Thor::Base.shell.new
@level = ENV["DEBUG"] ? "debug" : "info"
@warning_history = []
+ @output_stream = :stdout
+ @thread_safe_logger_key = "logger_level_#{object_id}"
end
def add_color(string, *color)
@@ -77,14 +81,14 @@ module Bundler
end
def ask(msg)
- @shell.ask(msg)
+ @shell.ask(msg, :green)
end
def yes?(msg)
- @shell.yes?(msg)
+ @shell.yes?(msg, :green)
end
- def no?
+ def no?(msg)
@shell.no?(msg)
end
@@ -94,11 +98,18 @@ module Bundler
end
def level(name = nil)
- return @level unless name
+ current_level = Thread.current.thread_variable_get(@thread_safe_logger_key) || @level
+ return current_level unless name
+
unless index = LEVELS.index(name)
raise "#{name.inspect} is not a valid level"
end
- index <= LEVELS.index(@level)
+ index <= LEVELS.index(current_level)
+ end
+
+ def output_stream=(symbol)
+ raise ArgumentError unless OUTPUT_STREAMS.include?(symbol)
+ @output_stream = symbol
end
def trace(e, newline = nil, force = false)
@@ -111,6 +122,10 @@ module Bundler
with_level("silent", &blk)
end
+ def progress(&blk)
+ with_output_stream(:stderr, &blk)
+ end
+
def unprinted_warnings
[]
end
@@ -119,6 +134,8 @@ module Bundler
# valimism
def tell_me(msg, color = nil, newline = nil)
+ return tell_err(msg, color, newline) if output_stream == :stderr
+
msg = word_wrap(msg) if newline.is_a?(Hash) && newline[:wrap]
if newline.nil?
@shell.say(msg, color)
@@ -130,7 +147,7 @@ module Bundler
def tell_err(message, color = nil, newline = nil)
return if @shell.send(:stderr).closed?
- newline ||= !message.to_s.match?(/( |\t)\Z/)
+ newline = !message.to_s.match?(/( |\t)\Z/) if newline.nil?
message = word_wrap(message) if newline.is_a?(Hash) && newline[:wrap]
color = nil if color && !$stderr.tty?
@@ -153,12 +170,21 @@ module Bundler
end * "\n"
end
- def with_level(level)
- original = @level
- @level = level
+ def with_level(desired_level)
+ old_level = level
+ Thread.current.thread_variable_set(@thread_safe_logger_key, desired_level)
+
+ yield
+ ensure
+ Thread.current.thread_variable_set(@thread_safe_logger_key, old_level)
+ end
+
+ def with_output_stream(symbol)
+ original = output_stream
+ self.output_stream = symbol
yield
ensure
- @level = original
+ @output_stream = original
end
end
end
diff --git a/lib/bundler/ui/silent.rb b/lib/bundler/ui/silent.rb
index fa3292bdc9..83d31d4b55 100644
--- a/lib/bundler/ui/silent.rb
+++ b/lib/bundler/ui/silent.rb
@@ -53,6 +53,13 @@ module Bundler
false
end
+ def output_stream=(_symbol)
+ end
+
+ def output_stream
+ nil
+ end
+
def ask(message)
end
@@ -60,7 +67,7 @@ module Bundler
raise "Cannot ask yes? with a silent shell"
end
- def no?
+ def no?(msg)
raise "Cannot ask no? with a silent shell"
end
@@ -77,6 +84,10 @@ module Bundler
yield
end
+ def progress
+ yield
+ end
+
def unprinted_warnings
@warnings
end
diff --git a/lib/bundler/uri_credentials_filter.rb b/lib/bundler/uri_credentials_filter.rb
index a83f5304e2..6804187433 100644
--- a/lib/bundler/uri_credentials_filter.rb
+++ b/lib/bundler/uri_credentials_filter.rb
@@ -16,7 +16,7 @@ module Bundler
if uri.userinfo
# oauth authentication
- if uri.password == "x-oauth-basic" || uri.password == "x"
+ if uri.password == "x-oauth-basic" || uri.password == "x" || uri.password.nil?
# URI as string does not display with password if no user is set
oauth_designation = uri.password
uri.user = oauth_designation
diff --git a/lib/bundler/vendor/connection_pool/lib/connection_pool.rb b/lib/bundler/vendor/connection_pool/lib/connection_pool.rb
index 317088a866..e8aaf70016 100644
--- a/lib/bundler/vendor/connection_pool/lib/connection_pool.rb
+++ b/lib/bundler/vendor/connection_pool/lib/connection_pool.rb
@@ -39,7 +39,7 @@ end
# - :auto_reload_after_fork - automatically drop all connections after fork, defaults to true
#
class Bundler::ConnectionPool
- DEFAULTS = {size: 5, timeout: 5, auto_reload_after_fork: true}
+ DEFAULTS = {size: 5, timeout: 5, auto_reload_after_fork: true}.freeze
def self.wrap(options, &block)
Wrapper.new(options, &block)
@@ -99,10 +99,14 @@ class Bundler::ConnectionPool
@available = TimedStack.new(@size, &block)
@key = :"pool-#{@available.object_id}"
@key_count = :"pool-#{@available.object_id}-count"
- INSTANCES[self] = self if INSTANCES
+ @discard_key = :"pool-#{@available.object_id}-discard"
+ INSTANCES[self] = self if @auto_reload_after_fork && INSTANCES
end
def with(options = {})
+ # We need to manage exception handling manually here in order
+ # to work correctly with `Gem::Timeout.timeout` and `Thread#raise`.
+ # Otherwise an interrupted Thread can leak connections.
Thread.handle_interrupt(Exception => :never) do
conn = checkout(options)
begin
@@ -116,20 +120,65 @@ class Bundler::ConnectionPool
end
alias_method :then, :with
+ ##
+ # Marks the current thread's checked-out connection for discard.
+ #
+ # When a connection is marked for discard, it will not be returned to the pool
+ # when checked in. Instead, the connection will be discarded.
+ # This is useful when a connection has become invalid or corrupted
+ # and should not be reused.
+ #
+ # Takes an optional block that will be called with the connection to be discarded.
+ # The block should perform any necessary clean-up on the connection.
+ #
+ # @yield [conn]
+ # @yieldparam conn [Object] The connection to be discarded.
+ # @yieldreturn [void]
+ #
+ #
+ # Note: This only affects the connection currently checked out by the calling thread.
+ # The connection will be discarded when +checkin+ is called.
+ #
+ # @return [void]
+ #
+ # @example
+ # pool.with do |conn|
+ # begin
+ # conn.execute("SELECT 1")
+ # rescue SomeConnectionError
+ # pool.discard_current_connection # Mark connection as bad
+ # raise
+ # end
+ # end
+ def discard_current_connection(&block)
+ ::Thread.current[@discard_key] = block || proc { |conn| conn }
+ end
+
def checkout(options = {})
if ::Thread.current[@key]
::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] = @available.pop(options[:timeout] || @timeout, options)
end
end
def checkin(force: false)
if ::Thread.current[@key]
if ::Thread.current[@key_count] == 1 || force
- @available.push(::Thread.current[@key])
+ if ::Thread.current[@discard_key]
+ begin
+ @available.decrement_created
+ ::Thread.current[@discard_key].call(::Thread.current[@key])
+ rescue
+ nil
+ ensure
+ ::Thread.current[@discard_key] = nil
+ end
+ else
+ @available.push(::Thread.current[@key])
+ end
::Thread.current[@key] = nil
::Thread.current[@key_count] = nil
else
@@ -146,7 +195,6 @@ class Bundler::ConnectionPool
# 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
@@ -155,11 +203,16 @@ class Bundler::ConnectionPool
# 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
+ ## Reaps idle connections that have been idle for over +idle_seconds+.
+ # +idle_seconds+ defaults to 60.
+ def reap(idle_seconds = 60, &block)
+ @available.reap(idle_seconds, &block)
+ end
+
# Size of this connection pool
attr_reader :size
# Automatically drop all connections after fork
@@ -169,6 +222,11 @@ class Bundler::ConnectionPool
def available
@available.length
end
+
+ # Number of pool entries created and idle in the pool.
+ def idle
+ @available.idle
+ end
end
require_relative "connection_pool/timed_stack"
diff --git a/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb b/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb
index 35d1d7cc35..026d2c5be2 100644
--- a/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb
+++ b/lib/bundler/vendor/connection_pool/lib/connection_pool/timed_stack.rb
@@ -1,8 +1,8 @@
##
# The TimedStack manages a pool of homogeneous connections (or any resource
-# you wish to manage). Connections are created lazily up to a given maximum
+# you wish to manage). Connections are created lazily up to a given maximum
# number.
-
+#
# Examples:
#
# ts = TimedStack.new(1) { MyConnection.new }
@@ -16,14 +16,12 @@
# conn = ts.pop
# ts.pop timeout: 5
# #=> raises Bundler::ConnectionPool::TimeoutError after 5 seconds
-
class Bundler::ConnectionPool::TimedStack
attr_reader :max
##
# Creates a new pool with +size+ connections that are created from the given
# +block+.
-
def initialize(size = 0, &block)
@create_block = block
@created = 0
@@ -35,12 +33,12 @@ class Bundler::ConnectionPool::TimedStack
end
##
- # Returns +obj+ to the stack. +options+ is ignored in TimedStack but may be
+ # Returns +obj+ to the stack. +options+ is ignored in TimedStack but may be
# used by subclasses that extend TimedStack.
-
def push(obj, options = {})
@mutex.synchronize do
if @shutdown_block
+ @created -= 1 unless @created == 0
@shutdown_block.call(obj)
else
store_connection obj, options
@@ -52,14 +50,16 @@ class Bundler::ConnectionPool::TimedStack
alias_method :<<, :push
##
- # Retrieves a connection from the stack. If a connection is available it is
- # immediately returned. If no connection is available within the given
+ # 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 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
- # options may be used by subclasses that extend TimedStack.
-
+ # @option options [Float] :timeout (0.5) Wait this many seconds for an available entry
+ # @option options [Class] :exception (Bundler::ConnectionPool::TimeoutError) Exception class to raise
+ # if an entry was not available within the timeout period. Use `exception: false` to return nil.
+ #
+ # The +timeout+ argument will be removed in 3.0.
+ # Other options may be used by subclasses that extend TimedStack.
def pop(timeout = 0.5, options = {})
options, timeout = timeout, 0.5 if Hash === timeout
timeout = options.fetch :timeout, timeout
@@ -68,13 +68,22 @@ class Bundler::ConnectionPool::TimedStack
@mutex.synchronize do
loop do
raise Bundler::ConnectionPool::PoolShuttingDownError if @shutdown_block
- return fetch_connection(options) if connection_stored?(options)
+ if (conn = try_fetch_connection(options))
+ return conn
+ end
connection = try_create(options)
return connection if connection
to_wait = deadline - current_time
- raise Bundler::ConnectionPool::TimeoutError, "Waited #{timeout} sec, #{length}/#{@max} available" if to_wait <= 0
+ if to_wait <= 0
+ exc = options.fetch(:exception, Bundler::ConnectionPool::TimeoutError)
+ if exc
+ raise Bundler::ConnectionPool::TimeoutError, "Waited #{timeout} sec, #{length}/#{@max} available"
+ else
+ return nil
+ end
+ end
@resource.wait(@mutex, to_wait)
end
end
@@ -85,7 +94,6 @@ class Bundler::ConnectionPool::TimedStack
# removing it from the pool. Attempting to checkout a connection after
# shutdown will raise +Bundler::ConnectionPool::PoolShuttingDownError+ unless
# +:reload+ is +true+.
-
def shutdown(reload: false, &block)
raise ArgumentError, "shutdown must receive a block" unless block
@@ -99,19 +107,49 @@ class Bundler::ConnectionPool::TimedStack
end
##
- # Returns +true+ if there are no available connections.
+ # Reaps connections that were checked in more than +idle_seconds+ ago.
+ def reap(idle_seconds, &block)
+ raise ArgumentError, "reap must receive a block" unless block
+ raise ArgumentError, "idle_seconds must be a number" unless idle_seconds.is_a?(Numeric)
+ raise Bundler::ConnectionPool::PoolShuttingDownError if @shutdown_block
+
+ idle.times do
+ conn =
+ @mutex.synchronize do
+ raise Bundler::ConnectionPool::PoolShuttingDownError if @shutdown_block
+
+ reserve_idle_connection(idle_seconds)
+ end
+ break unless conn
+
+ block.call(conn)
+ end
+ end
+ ##
+ # Returns +true+ if there are no available connections.
def empty?
(@created - @que.length) >= @max
end
##
# The number of connections available on the stack.
-
def length
@max - @created + @que.length
end
+ ##
+ # The number of connections created and available on the stack.
+ def idle
+ @que.length
+ end
+
+ ##
+ # Reduce the created count
+ def decrement_created
+ @created -= 1 unless @created == 0
+ end
+
private
def current_time
@@ -121,8 +159,17 @@ class Bundler::ConnectionPool::TimedStack
##
# This is an extension point for TimedStack and is called with a mutex.
#
- # This method must returns true if a connection is available on the stack.
+ # This method must returns a connection from the stack if one exists. Allows
+ # subclasses with expensive match/search algorithms to avoid double-handling
+ # their stack.
+ def try_fetch_connection(options = nil)
+ connection_stored?(options) && fetch_connection(options)
+ end
+ ##
+ # This is an extension point for TimedStack and is called with a mutex.
+ #
+ # This method must returns true if a connection is available on the stack.
def connection_stored?(options = nil)
!@que.empty?
end
@@ -131,31 +178,48 @@ class Bundler::ConnectionPool::TimedStack
# This is an extension point for TimedStack and is called with a mutex.
#
# This method must return a connection from the stack.
-
def fetch_connection(options = nil)
- @que.pop
+ @que.pop&.first
end
##
# This is an extension point for TimedStack and is called with a mutex.
#
# This method must shut down all connections on the stack.
-
def shutdown_connections(options = nil)
- while connection_stored?(options)
- conn = fetch_connection(options)
+ while (conn = try_fetch_connection(options))
+ @created -= 1 unless @created == 0
@shutdown_block.call(conn)
end
- @created = 0
end
##
# This is an extension point for TimedStack and is called with a mutex.
#
- # This method must return +obj+ to the stack.
+ # This method returns the oldest idle connection if it has been idle for more than idle_seconds.
+ # This requires that the stack is kept in order of checked in time (oldest first).
+ def reserve_idle_connection(idle_seconds)
+ return unless idle_connections?(idle_seconds)
+
+ @created -= 1 unless @created == 0
+
+ @que.shift.first
+ end
+ ##
+ # This is an extension point for TimedStack and is called with a mutex.
+ #
+ # Returns true if the first connection in the stack has been idle for more than idle_seconds
+ def idle_connections?(idle_seconds)
+ connection_stored? && (current_time - @que.first.last > idle_seconds)
+ end
+
+ ##
+ # This is an extension point for TimedStack and is called with a mutex.
+ #
+ # This method must return +obj+ to the stack.
def store_connection(obj, options = nil)
- @que.push obj
+ @que.push [obj, current_time]
end
##
@@ -163,7 +227,6 @@ class Bundler::ConnectionPool::TimedStack
#
# This method must create a connection if and only if the total number of
# connections allowed has not been met.
-
def try_create(options = nil)
unless @created == @max
object = @create_block.call
diff --git a/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb b/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb
index 384d6fc977..2e9eebdbb6 100644
--- a/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb
+++ b/lib/bundler/vendor/connection_pool/lib/connection_pool/version.rb
@@ -1,3 +1,3 @@
class Bundler::ConnectionPool
- VERSION = "2.4.1"
+ VERSION = "2.5.5"
end
diff --git a/lib/bundler/vendor/fileutils/.document b/lib/bundler/vendor/fileutils/.document
deleted file mode 100644
index 0c43bbd6b3..0000000000
--- a/lib/bundler/vendor/fileutils/.document
+++ /dev/null
@@ -1 +0,0 @@
-# Vendored files do not need to be documented
diff --git a/lib/bundler/vendor/fileutils/lib/fileutils.rb b/lib/bundler/vendor/fileutils/lib/fileutils.rb
index 6db19caf6f..a11fdc7176 100644
--- a/lib/bundler/vendor/fileutils/lib/fileutils.rb
+++ b/lib/bundler/vendor/fileutils/lib/fileutils.rb
@@ -180,7 +180,8 @@ end
# - {CVE-2004-0452}[https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0452].
#
module Bundler::FileUtils
- VERSION = "1.7.2"
+ # The version number.
+ VERSION = "1.8.0"
def self.private_module_function(name) #:nodoc:
module_function name
@@ -705,11 +706,12 @@ module Bundler::FileUtils
#
def ln_s(src, dest, force: nil, relative: false, target_directory: true, noop: nil, verbose: nil)
if relative
- return ln_sr(src, dest, force: force, noop: noop, verbose: verbose)
+ return ln_sr(src, dest, force: force, target_directory: target_directory, noop: noop, verbose: verbose)
end
- fu_output_message "ln -s#{force ? 'f' : ''} #{[src,dest].flatten.join ' '}" if verbose
+ fu_output_message "ln -s#{force ? 'f' : ''}#{
+ target_directory ? '' : 'T'} #{[src,dest].flatten.join ' '}" if verbose
return if noop
- fu_each_src_dest0(src, dest) do |s,d|
+ fu_each_src_dest0(src, dest, target_directory) do |s,d|
remove_file d, true if force
File.symlink s, d
end
@@ -729,42 +731,37 @@ module Bundler::FileUtils
# Like Bundler::FileUtils.ln_s, but create links relative to +dest+.
#
def ln_sr(src, dest, target_directory: true, force: nil, noop: nil, verbose: nil)
- options = "#{force ? 'f' : ''}#{target_directory ? '' : 'T'}"
- dest = File.path(dest)
- srcs = Array(src)
- link = proc do |s, target_dir_p = true|
- s = File.path(s)
- if target_dir_p
- d = File.join(destdirs = dest, File.basename(s))
+ cmd = "ln -s#{force ? 'f' : ''}#{target_directory ? '' : 'T'}" if verbose
+ fu_each_src_dest0(src, dest, target_directory) do |s,d|
+ if target_directory
+ parent = File.dirname(d)
+ destdirs = fu_split_path(parent)
+ real_ddirs = fu_split_path(File.realpath(parent))
else
- destdirs = File.dirname(d = dest)
+ destdirs ||= fu_split_path(dest)
+ real_ddirs ||= fu_split_path(File.realdirpath(dest))
end
- destdirs = fu_split_path(File.realpath(destdirs))
- if fu_starting_path?(s)
- srcdirs = fu_split_path((File.realdirpath(s) rescue File.expand_path(s)))
- base = fu_relative_components_from(srcdirs, destdirs)
- s = File.join(*base)
+ srcdirs = fu_split_path(s)
+ i = fu_common_components(srcdirs, destdirs)
+ n = destdirs.size - i
+ n -= 1 unless target_directory
+ link1 = fu_clean_components(*Array.new([n, 0].max, '..'), *srcdirs[i..-1])
+ begin
+ real_sdirs = fu_split_path(File.realdirpath(s)) rescue nil
+ rescue
else
- srcdirs = fu_clean_components(*fu_split_path(s))
- base = fu_relative_components_from(fu_split_path(Dir.pwd), destdirs)
- while srcdirs.first&. == ".." and base.last&.!=("..") and !fu_starting_path?(base.last)
- srcdirs.shift
- base.pop
- end
- s = File.join(*base, *srcdirs)
+ i = fu_common_components(real_sdirs, real_ddirs)
+ n = real_ddirs.size - i
+ n -= 1 unless target_directory
+ link2 = fu_clean_components(*Array.new([n, 0].max, '..'), *real_sdirs[i..-1])
+ link1 = link2 if link1.size > link2.size
end
- fu_output_message "ln -s#{options} #{s} #{d}" if verbose
+ s = File.join(link1)
+ fu_output_message [cmd, s, d].flatten.join(' ') if verbose
next if noop
remove_file d, true if force
File.symlink s, d
end
- case srcs.size
- when 0
- when 1
- link[srcs[0], target_directory && File.directory?(dest)]
- else
- srcs.each(&link)
- end
end
module_function :ln_sr
@@ -799,13 +796,13 @@ module Bundler::FileUtils
# File.file?('dest1/dir1/t2.txt') # => true
# File.file?('dest1/dir1/t3.txt') # => true
#
- # Keyword arguments:
+ # Optional arguments:
#
- # - <tt>dereference_root: true</tt> - dereferences +src+ if it is a symbolic link.
- # - <tt>remove_destination: true</tt> - removes +dest+ before creating links.
+ # - +dereference_root+ - dereferences +src+ if it is a symbolic link (+false+ by default).
+ # - +remove_destination+ - removes +dest+ before creating links (+false+ by default).
#
# Raises an exception if +dest+ is the path to an existing file or directory
- # and keyword argument <tt>remove_destination: true</tt> is not given.
+ # and optional argument +remove_destination+ is not given.
#
# Related: Bundler::FileUtils.ln (has different options).
#
@@ -1028,12 +1025,12 @@ module Bundler::FileUtils
# directories, and symbolic links;
# other file types (FIFO streams, device files, etc.) are not supported.
#
- # Keyword arguments:
+ # Optional arguments:
#
- # - <tt>dereference_root: true</tt> - if +src+ is a symbolic link,
- # follows the link.
- # - <tt>preserve: true</tt> - preserves file times.
- # - <tt>remove_destination: true</tt> - removes +dest+ before copying files.
+ # - +dereference_root+ - if +src+ is a symbolic link,
+ # follows the link (+false+ by default).
+ # - +preserve+ - preserves file times (+false+ by default).
+ # - +remove_destination+ - removes +dest+ before copying files (+false+ by default).
#
# Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
#
@@ -1064,12 +1061,12 @@ module Bundler::FileUtils
# Bundler::FileUtils.copy_file('src0.txt', 'dest0.txt')
# File.file?('dest0.txt') # => true
#
- # Keyword arguments:
+ # Optional arguments:
#
- # - <tt>dereference: false</tt> - if +src+ is a symbolic link,
- # does not follow the link.
- # - <tt>preserve: true</tt> - preserves file times.
- # - <tt>remove_destination: true</tt> - removes +dest+ before copying files.
+ # - +dereference+ - if +src+ is a symbolic link,
+ # follows the link (+true+ by default).
+ # - +preserve+ - preserves file times (+false+ by default).
+ # - +remove_destination+ - removes +dest+ before copying files (+false+ by default).
#
# Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
#
@@ -1490,7 +1487,8 @@ module Bundler::FileUtils
# Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
#
def remove_dir(path, force = false)
- remove_entry path, force # FIXME?? check if it is a directory
+ raise Errno::ENOTDIR, path unless force or File.directory?(path)
+ remove_entry path, force
end
module_function :remove_dir
@@ -1651,7 +1649,7 @@ module Bundler::FileUtils
when "a"
mask | 07777
else
- raise ArgumentError, "invalid `who' symbol in file mode: #{chr}"
+ raise ArgumentError, "invalid 'who' symbol in file mode: #{chr}"
end
end
end
@@ -1705,7 +1703,7 @@ module Bundler::FileUtils
copy_mask = user_mask(chr)
(current_mode & copy_mask) / (copy_mask & 0111) * (user_mask & 0111)
else
- raise ArgumentError, "invalid `perm' symbol in file mode: #{chr}"
+ raise ArgumentError, "invalid 'perm' symbol in file mode: #{chr}"
end
end
@@ -2028,21 +2026,22 @@ module Bundler::FileUtils
private
- module StreamUtils_
+ module StreamUtils_ # :nodoc:
+
private
case (defined?(::RbConfig) ? ::RbConfig::CONFIG['host_os'] : ::RUBY_PLATFORM)
when /mswin|mingw/
- def fu_windows?; true end
+ def fu_windows?; true end #:nodoc:
else
- def fu_windows?; false end
+ def fu_windows?; false end #:nodoc:
end
def fu_copy_stream0(src, dest, blksize = nil) #:nodoc:
IO.copy_stream(src, dest)
end
- def fu_stream_blksize(*streams)
+ def fu_stream_blksize(*streams) #:nodoc:
streams.each do |s|
next unless s.respond_to?(:stat)
size = fu_blksize(s.stat)
@@ -2051,14 +2050,14 @@ module Bundler::FileUtils
fu_default_blksize()
end
- def fu_blksize(st)
+ def fu_blksize(st) #:nodoc:
s = st.blksize
return nil unless s
return nil if s == 0
s
end
- def fu_default_blksize
+ def fu_default_blksize #:nodoc:
1024
end
end
@@ -2473,6 +2472,10 @@ module Bundler::FileUtils
def fu_each_src_dest0(src, dest, target_directory = true) #:nodoc:
if tmp = Array.try_convert(src)
+ unless target_directory or tmp.size <= 1
+ tmp = tmp.map {|f| File.path(f)} # A workaround for RBS
+ raise ArgumentError, "extra target #{tmp}"
+ end
tmp.each do |s|
s = File.path(s)
yield s, (target_directory ? File.join(dest, File.basename(s)) : dest)
@@ -2503,11 +2506,15 @@ module Bundler::FileUtils
end
private_module_function :fu_output_message
- def fu_split_path(path)
+ def fu_split_path(path) #:nodoc:
path = File.path(path)
list = []
until (parent, base = File.split(path); parent == path or parent == ".")
- list << base
+ if base != '..' and list.last == '..' and !(fu_have_symlink? && File.symlink?(path))
+ list.pop
+ else
+ list << base
+ end
path = parent
end
list << path
@@ -2515,16 +2522,16 @@ module Bundler::FileUtils
end
private_module_function :fu_split_path
- def fu_relative_components_from(target, base) #:nodoc:
+ def fu_common_components(target, base) #:nodoc:
i = 0
while target[i]&.== base[i]
i += 1
end
- Array.new(base.size-i, '..').concat(target[i..-1])
+ i
end
- private_module_function :fu_relative_components_from
+ private_module_function :fu_common_components
- def fu_clean_components(*comp)
+ def fu_clean_components(*comp) #:nodoc:
comp.shift while comp.first == "."
return comp if comp.empty?
clean = [comp.shift]
@@ -2532,7 +2539,7 @@ module Bundler::FileUtils
while c = comp.shift
if c == ".." and clean.last != ".." and !(fu_have_symlink? && File.symlink?(path))
clean.pop
- path.chomp!(%r((?<=\A|/)[^/]+/\z), "")
+ path.sub!(%r((?<=\A|/)[^/]+/\z), "")
else
clean << c
path << c << "/"
@@ -2543,11 +2550,11 @@ module Bundler::FileUtils
private_module_function :fu_clean_components
if fu_windows?
- def fu_starting_path?(path)
+ def fu_starting_path?(path) #:nodoc:
path&.start_with?(%r(\w:|/))
end
else
- def fu_starting_path?(path)
+ def fu_starting_path?(path) #:nodoc:
path&.start_with?("/")
end
end
diff --git a/lib/bundler/vendor/net-http-persistent/.document b/lib/bundler/vendor/net-http-persistent/.document
deleted file mode 100644
index 0c43bbd6b3..0000000000
--- a/lib/bundler/vendor/net-http-persistent/.document
+++ /dev/null
@@ -1 +0,0 @@
-# Vendored files do not need to be documented
diff --git a/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb b/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb
index c15b346330..93e403a5bb 100644
--- a/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb
+++ b/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb
@@ -1,6 +1,10 @@
require_relative '../../../../../vendored_net_http'
require_relative '../../../../../vendored_uri'
-require 'cgi' # for escaping
+begin
+ require 'cgi/escape'
+rescue LoadError
+ require 'cgi/util' # for escaping
+end
require_relative '../../../../connection_pool/lib/connection_pool'
autoload :OpenSSL, 'openssl'
@@ -42,9 +46,8 @@ autoload :OpenSSL, 'openssl'
# # perform the POST, the Gem::URI is always required
# response http.request post_uri, post
#
-# Note that for GET, HEAD and other requests that do not have a body you want
-# to use Gem::URI#request_uri not Gem::URI#path. The request_uri contains the query
-# params which are sent in the body for other requests.
+# ⚠ Note that for GET, HEAD and other requests that do not have a body,
+# it uses Gem::URI#request_uri as default to send query params
#
# == TLS/SSL
#
@@ -60,6 +63,7 @@ autoload :OpenSSL, 'openssl'
# #ca_path :: Directory with certificate-authorities
# #cert_store :: An SSL certificate store
# #ciphers :: List of SSl ciphers allowed
+# #extra_chain_cert :: Extra certificates to be added to the certificate chain
# #private_key :: The client's SSL private key
# #reuse_ssl_sessions :: Reuse a previously opened SSL session for a new
# connection
@@ -68,6 +72,8 @@ autoload :OpenSSL, 'openssl'
# #verify_callback :: For server certificate verification
# #verify_depth :: Depth of certificate verification
# #verify_mode :: How connections should be verified
+# #verify_hostname :: Use hostname verification for server certificate
+# during the handshake
#
# == Proxies
#
@@ -174,7 +180,7 @@ class Gem::Net::HTTP::Persistent
##
# The version of Gem::Net::HTTP::Persistent you are using
- VERSION = '4.0.2'
+ VERSION = '4.0.6'
##
# Error class for errors raised by Gem::Net::HTTP::Persistent. Various
@@ -266,6 +272,11 @@ class Gem::Net::HTTP::Persistent
attr_reader :ciphers
##
+ # Extra certificates to be added to the certificate chain
+
+ attr_reader :extra_chain_cert
+
+ ##
# Sends debug_output to this IO via Gem::Net::HTTP#set_debug_output.
#
# Never use this method in production code, it causes a serious security
@@ -450,6 +461,21 @@ class Gem::Net::HTTP::Persistent
attr_reader :verify_mode
##
+ # HTTPS verify_hostname.
+ #
+ # If a client sets this to true and enables SNI with SSLSocket#hostname=,
+ # the hostname verification on the server certificate is performed
+ # automatically during the handshake using
+ # OpenSSL::SSL.verify_certificate_identity().
+ #
+ # You can set +verify_hostname+ as true to use hostname verification
+ # during the handshake.
+ #
+ # NOTE: This works with Ruby > 3.0.
+
+ attr_reader :verify_hostname
+
+ ##
# Creates a new Gem::Net::HTTP::Persistent.
#
# Set a +name+ for fun. Your library name should be good enough, but this
@@ -508,6 +534,7 @@ class Gem::Net::HTTP::Persistent
@verify_callback = nil
@verify_depth = nil
@verify_mode = nil
+ @verify_hostname = nil
@cert_store = nil
@generation = 0 # incremented when proxy Gem::URI changes
@@ -569,6 +596,21 @@ class Gem::Net::HTTP::Persistent
reconnect_ssl
end
+ if Gem::Net::HTTP.method_defined?(:extra_chain_cert=)
+ ##
+ # Extra certificates to be added to the certificate chain.
+ # It is only supported starting from Gem::Net::HTTP version 0.1.1
+ def extra_chain_cert= extra_chain_cert
+ @extra_chain_cert = extra_chain_cert
+
+ reconnect_ssl
+ end
+ else
+ def extra_chain_cert= _extra_chain_cert
+ raise "extra_chain_cert= is not supported by this version of Gem::Net::HTTP"
+ end
+ end
+
##
# Creates a new connection for +uri+
@@ -587,37 +629,49 @@ class Gem::Net::HTTP::Persistent
connection = @pool.checkout net_http_args
- http = connection.http
+ begin
+ http = connection.http
- connection.ressl @ssl_generation if
- connection.ssl_generation != @ssl_generation
+ connection.ressl @ssl_generation if
+ connection.ssl_generation != @ssl_generation
- if not http.started? then
- ssl http if use_ssl
- start http
- elsif expired? connection then
- reset connection
- end
-
- 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=)
+ if not http.started? then
+ ssl http if use_ssl
+ start http
+ elsif expired? connection then
+ reset connection
+ end
- return yield connection
- rescue Errno::ECONNREFUSED
- address = http.proxy_address || http.address
- port = http.proxy_port || http.port
+ 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
+ if http.proxy?
+ address = http.proxy_address
+ port = http.proxy_port
+ else
+ address = http.address
+ port = http.port
+ end
- raise Error, "connection refused: #{address}:#{port}"
- rescue Errno::EHOSTDOWN
- address = http.proxy_address || http.address
- port = http.proxy_port || http.port
+ raise Error, "connection refused: #{address}:#{port}"
+ rescue Errno::EHOSTDOWN
+ if http.proxy?
+ address = http.proxy_address
+ port = http.proxy_port
+ else
+ address = http.address
+ port = http.port
+ end
- raise Error, "host down: #{address}:#{port}"
- ensure
- @pool.checkin net_http_args
+ raise Error, "host down: #{address}:#{port}"
+ ensure
+ @pool.checkin net_http_args
+ end
end
##
@@ -754,7 +808,7 @@ class Gem::Net::HTTP::Persistent
@proxy_connection_id = [nil, *@proxy_args].join ':'
if @proxy_uri.query then
- @no_proxy = CGI.parse(@proxy_uri.query)['no_proxy'].join(',').downcase.split(',').map { |x| x.strip }.reject { |x| x.empty? }
+ @no_proxy = Gem::URI.decode_www_form(@proxy_uri.query).filter_map { |k, v| v if k == 'no_proxy' }.join(',').downcase.split(',').map { |x| x.strip }.reject { |x| x.empty? }
end
end
@@ -925,7 +979,8 @@ class Gem::Net::HTTP::Persistent
end
##
- # Shuts down all connections
+ # Shuts down all connections. Attempting to checkout a connection after
+ # shutdown will raise an error.
#
# *NOTE*: Calling shutdown for can be dangerous!
#
@@ -937,6 +992,17 @@ class Gem::Net::HTTP::Persistent
end
##
+ # Discard all existing connections. Subsequent checkouts will create
+ # new connections as needed.
+ #
+ # If any thread is still using a connection it may cause an error! Call
+ # #reload when you are completely done making requests!
+
+ def reload
+ @pool.reload { |http| http.finish }
+ end
+
+ ##
# Enables SSL on +connection+
def ssl connection
@@ -948,8 +1014,10 @@ class Gem::Net::HTTP::Persistent
connection.min_version = @min_version if @min_version
connection.max_version = @max_version if @max_version
- connection.verify_depth = @verify_depth
- connection.verify_mode = @verify_mode
+ connection.verify_depth = @verify_depth
+ connection.verify_mode = @verify_mode
+ connection.verify_hostname = @verify_hostname if
+ @verify_hostname != nil && connection.respond_to?(:verify_hostname=)
if OpenSSL::SSL::VERIFY_PEER == OpenSSL::SSL::VERIFY_NONE and
not Object.const_defined?(:I_KNOW_THAT_OPENSSL_VERIFY_PEER_EQUALS_VERIFY_NONE_IS_WRONG) then
@@ -991,6 +1059,10 @@ application:
connection.key = @private_key
end
+ if defined?(@extra_chain_cert) and @extra_chain_cert
+ connection.extra_chain_cert = @extra_chain_cert
+ end
+
connection.cert_store = if @cert_store then
@cert_store
else
@@ -1059,6 +1131,15 @@ application:
end
##
+ # Sets the HTTPS verify_hostname.
+
+ def verify_hostname= verify_hostname
+ @verify_hostname = verify_hostname
+
+ reconnect_ssl
+ end
+
+ ##
# SSL verification callback.
def verify_callback= callback
@@ -1070,4 +1151,3 @@ end
require_relative 'persistent/connection'
require_relative 'persistent/pool'
-
diff --git a/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb b/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb
index 214804fcd9..034fbe39b8 100644
--- a/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb
+++ b/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/timed_stack_multi.rb
@@ -63,7 +63,8 @@ class Gem::Net::HTTP::Persistent::TimedStackMulti < Bundler::ConnectionPool::Tim
if @created >= @max && @enqueued >= 1
oldest, = @lru.first
@lru.delete oldest
- @ques[oldest].pop
+ connection = @ques[oldest].pop
+ connection.close if connection.respond_to?(:close)
@created -= 1
end
diff --git a/lib/bundler/vendor/pub_grub/.document b/lib/bundler/vendor/pub_grub/.document
deleted file mode 100644
index 0c43bbd6b3..0000000000
--- a/lib/bundler/vendor/pub_grub/.document
+++ /dev/null
@@ -1 +0,0 @@
-# Vendored files do not need to be documented
diff --git a/lib/bundler/vendor/pub_grub/lib/pub_grub/basic_package_source.rb b/lib/bundler/vendor/pub_grub/lib/pub_grub/basic_package_source.rb
index dce20d37ad..491151ec0b 100644
--- a/lib/bundler/vendor/pub_grub/lib/pub_grub/basic_package_source.rb
+++ b/lib/bundler/vendor/pub_grub/lib/pub_grub/basic_package_source.rb
@@ -79,29 +79,17 @@ module Bundler::PubGrub
dependencies_for(@root_package, @root_version)
end
- # Override me (maybe)
- #
- # If not overridden, the order returned by all_versions_for will be used
- #
- # Returns: Array of versions in preferred order
- def sort_versions_by_preferred(package, sorted_versions)
- indexes = @version_indexes[package]
- sorted_versions.sort_by { |version| indexes[version] }
- end
-
def initialize
@root_package = Package.root
@root_version = Package.root_version
- @cached_versions = Hash.new do |h,k|
+ @sorted_versions = Hash.new do |h,k|
if k == @root_package
h[k] = [@root_version]
else
- h[k] = all_versions_for(k)
+ h[k] = all_versions_for(k).sort
end
end
- @sorted_versions = Hash.new { |h,k| h[k] = @cached_versions[k].sort }
- @version_indexes = Hash.new { |h,k| h[k] = @cached_versions[k].each.with_index.to_h }
@cached_dependencies = Hash.new do |packages, package|
if package == @root_package
@@ -117,15 +105,7 @@ module Bundler::PubGrub
end
def versions_for(package, range=VersionRange.any)
- versions = range.select_versions(@sorted_versions[package])
-
- # Conditional avoids (among other things) calling
- # sort_versions_by_preferred with the root package
- if versions.size > 1
- sort_versions_by_preferred(package, versions)
- else
- versions
- end
+ range.select_versions(@sorted_versions[package])
end
def no_versions_incompatibility_for(_package, unsatisfied_term)
@@ -164,7 +144,7 @@ module Bundler::PubGrub
sorted_versions[high]
end
- range = VersionRange.new(min: low, max: high, include_min: true)
+ range = VersionRange.new(min: low, max: high, include_min: !low.nil?)
self_constraint = VersionConstraint.new(package, range: range)
diff --git a/lib/bundler/vendor/pub_grub/lib/pub_grub/strategy.rb b/lib/bundler/vendor/pub_grub/lib/pub_grub/strategy.rb
new file mode 100644
index 0000000000..6955655ba4
--- /dev/null
+++ b/lib/bundler/vendor/pub_grub/lib/pub_grub/strategy.rb
@@ -0,0 +1,42 @@
+module Bundler::PubGrub
+ class Strategy
+ def initialize(source)
+ @source = source
+
+ @root_package = Package.root
+ @root_version = Package.root_version
+
+ @version_indexes = Hash.new do |h,k|
+ if k == @root_package
+ h[k] = { @root_version => 0 }
+ else
+ h[k] = @source.all_versions_for(k).each.with_index.to_h
+ end
+ end
+ end
+
+ def next_package_and_version(unsatisfied)
+ package, range = next_term_to_try_from(unsatisfied)
+
+ [package, most_preferred_version_of(package, range)]
+ end
+
+ private
+
+ def most_preferred_version_of(package, range)
+ versions = @source.versions_for(package, range)
+
+ indexes = @version_indexes[package]
+ versions.min_by { |version| indexes[version] }
+ end
+
+ def next_term_to_try_from(unsatisfied)
+ unsatisfied.min_by do |package, range|
+ matching_versions = @source.versions_for(package, range)
+ higher_versions = @source.versions_for(package, range.upper_invert)
+
+ [matching_versions.count <= 1 ? 0 : 1, higher_versions.count]
+ end
+ end
+ end
+end
diff --git a/lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb b/lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb
index 8d73c3f7b5..49dcf716a3 100644
--- a/lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb
+++ b/lib/bundler/vendor/pub_grub/lib/pub_grub/version_range.rb
@@ -76,6 +76,9 @@ module Bundler::PubGrub
end
def initialize(min: nil, max: nil, include_min: false, include_max: false, name: nil)
+ raise ArgumentError, "Ranges without a lower bound cannot have include_min == true" if !min && include_min == true
+ raise ArgumentError, "Ranges without an upper bound cannot have include_max == true" if !max && include_max == true
+
@min = min
@max = max
@include_min = include_min
@@ -311,10 +314,19 @@ module Bundler::PubGrub
def contiguous_to?(other)
return false if other.empty?
+ return true if any?
+
+ intersects?(other) || contiguous_below?(other) || contiguous_above?(other)
+ end
+
+ def contiguous_below?(other)
+ return false if !max || !other.min
+
+ max == other.min && (include_max || other.include_min)
+ end
- intersects?(other) ||
- (min == other.max && (include_min || other.include_max)) ||
- (max == other.min && (include_max || other.include_min))
+ def contiguous_above?(other)
+ other.contiguous_below?(self)
end
def allows_all?(other)
@@ -375,15 +387,15 @@ module Bundler::PubGrub
def invert
return self.class.empty if any?
- low = VersionRange.new(max: min, include_max: !include_min)
- high = VersionRange.new(min: max, include_min: !include_max)
+ low = -> { VersionRange.new(max: min, include_max: !include_min) }
+ high = -> { VersionRange.new(min: max, include_min: !include_max) }
if !min
- high
+ high.call
elsif !max
- low
+ low.call
else
- low.union(high)
+ low.call.union(high.call)
end
end
diff --git a/lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb b/lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb
index 4caf6b355b..000923e99a 100644
--- a/lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb
+++ b/lib/bundler/vendor/pub_grub/lib/pub_grub/version_solver.rb
@@ -2,17 +2,20 @@ require_relative 'partial_solution'
require_relative 'term'
require_relative 'incompatibility'
require_relative 'solve_failure'
+require_relative 'strategy'
module Bundler::PubGrub
class VersionSolver
attr_reader :logger
attr_reader :source
attr_reader :solution
+ attr_reader :strategy
- def initialize(source:, root: Package.root, logger: Bundler::PubGrub.logger)
+ def initialize(source:, root: Package.root, strategy: Strategy.new(source), logger: Bundler::PubGrub.logger)
@logger = logger
@source = source
+ @strategy = strategy
# { package => [incompatibility, ...]}
@incompatibilities = Hash.new do |h, k|
@@ -36,26 +39,25 @@ module Bundler::PubGrub
# Returns true if there is more work to be done, false otherwise
def work
- return false if solved?
-
- next_package = choose_package_version
- propagate(next_package)
-
- if solved?
+ unsatisfied_terms = solution.unsatisfied
+ if unsatisfied_terms.empty?
logger.info { "Solution found after #{solution.attempted_solutions} attempts:" }
solution.decisions.each do |package, version|
next if Package.root?(package)
logger.info { "* #{package} #{version}" }
end
- false
- else
- true
+ return false
end
+
+ next_package = choose_package_version_from(unsatisfied_terms)
+ propagate(next_package)
+
+ true
end
def solve
- work until solved?
+ while work; end
solution.decisions
end
@@ -105,29 +107,15 @@ module Bundler::PubGrub
unsatisfied.package
end
- def next_package_to_try
- solution.unsatisfied.min_by do |term|
- package = term.package
- range = term.constraint.range
- matching_versions = source.versions_for(package, range)
- higher_versions = source.versions_for(package, range.upper_invert)
+ def choose_package_version_from(unsatisfied_terms)
+ remaining = unsatisfied_terms.map { |t| [t.package, t.constraint.range] }.to_h
- [matching_versions.count <= 1 ? 0 : 1, higher_versions.count]
- end.package
- end
-
- def choose_package_version
- if solution.unsatisfied.empty?
- logger.info "No packages unsatisfied. Solving complete!"
- return nil
- end
+ package, version = strategy.next_package_and_version(remaining)
- package = next_package_to_try
- unsatisfied_term = solution.unsatisfied.find { |t| t.package == package }
- version = source.versions_for(package, unsatisfied_term.constraint.range).first
logger.debug { "attempting #{package} #{version}" }
if version.nil?
+ unsatisfied_term = unsatisfied_terms.find { |t| t.package == package }
add_incompatibility source.no_versions_incompatibility_for(package, unsatisfied_term)
return package
end
diff --git a/lib/bundler/vendor/securerandom/lib/securerandom.rb b/lib/bundler/vendor/securerandom/lib/securerandom.rb
new file mode 100644
index 0000000000..01b7fa15a6
--- /dev/null
+++ b/lib/bundler/vendor/securerandom/lib/securerandom.rb
@@ -0,0 +1,102 @@
+# -*- 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
+# suitable for generating session keys in HTTP cookies, etc.
+#
+# You can use this library in your application by requiring it:
+#
+# require 'bundler/vendor/securerandom/lib/securerandom'
+#
+# It supports the following secure random number generators:
+#
+# * openssl
+# * /dev/urandom
+# * Win32
+#
+# Bundler::SecureRandom is extended by the Random::Formatter module which
+# defines the following methods:
+#
+# * alphanumeric
+# * base64
+# * choose
+# * gen_random
+# * hex
+# * rand
+# * random_bytes
+# * random_number
+# * urlsafe_base64
+# * uuid
+#
+# These methods are usable as class methods of Bundler::SecureRandom such as
+# +Bundler::SecureRandom.hex+.
+#
+# If a secure random number generator is not available,
+# +NotImplementedError+ is raised.
+
+module Bundler::SecureRandom
+
+ # The version
+ VERSION = "0.4.1"
+
+ class << self
+ # Returns a random binary string containing +size+ bytes.
+ #
+ # See Random.bytes
+ def bytes(n)
+ return gen_random(n)
+ end
+
+ # Compatibility methods for Ruby 3.2, we can remove this after dropping to support Ruby 3.2
+ def alphanumeric(n = nil, chars: ALPHANUMERIC)
+ n = 16 if n.nil?
+ choose(chars, n)
+ end if RUBY_VERSION < '3.3'
+
+ private
+
+ # :stopdoc:
+
+ # Implementation using OpenSSL
+ def gen_random_openssl(n)
+ return OpenSSL::Random.random_bytes(n)
+ end
+
+ # Implementation using system random device
+ def gen_random_urandom(n)
+ ret = Random.urandom(n)
+ unless ret
+ raise NotImplementedError, "No random device"
+ end
+ unless ret.length == n
+ raise NotImplementedError, "Unexpected partial read from random device: only #{ret.length} for #{n} bytes"
+ end
+ ret
+ end
+
+ begin
+ # Check if Random.urandom is available
+ Random.urandom(1)
+ alias gen_random gen_random_urandom
+ rescue RuntimeError
+ begin
+ require 'openssl'
+ rescue NoMethodError
+ raise NotImplementedError, "No random device"
+ else
+ alias gen_random gen_random_openssl
+ end
+ end
+
+ # :startdoc:
+
+ # Generate random data bytes for Random::Formatter
+ public :gen_random
+ end
+end
+
+Bundler::SecureRandom.extend(Random::Formatter)
diff --git a/lib/bundler/vendor/thor/.document b/lib/bundler/vendor/thor/.document
deleted file mode 100644
index 0c43bbd6b3..0000000000
--- a/lib/bundler/vendor/thor/.document
+++ /dev/null
@@ -1 +0,0 @@
-# Vendored files do not need to be documented
diff --git a/lib/bundler/vendor/thor/lib/thor.rb b/lib/bundler/vendor/thor/lib/thor.rb
index 627722164f..945bdbd551 100644
--- a/lib/bundler/vendor/thor/lib/thor.rb
+++ b/lib/bundler/vendor/thor/lib/thor.rb
@@ -439,6 +439,17 @@ class Bundler::Thor
command && disable_required_check.include?(command.name.to_sym)
end
+ # Checks if a specified command exists.
+ #
+ # ==== Parameters
+ # command_name<String>:: The name of the command to check for existence.
+ #
+ # ==== Returns
+ # Boolean:: +true+ if the command exists, +false+ otherwise.
+ def command_exists?(command_name) #:nodoc:
+ commands.keys.include?(normalize_command_name(command_name))
+ end
+
protected
# Returns this class exclusive options array set.
@@ -614,7 +625,7 @@ class Bundler::Thor
# alias name.
def find_command_possibilities(meth)
len = meth.to_s.length
- possibilities = all_commands.merge(map).keys.select { |n| meth == n[0, len] }.sort
+ possibilities = all_commands.reject { |_k, c| c.hidden? }.merge(map).keys.select { |n| meth == n[0, len] }.sort
unique_possibilities = possibilities.map { |k| map[k] || k }.uniq
if possibilities.include?(meth)
diff --git a/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb b/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb
index 80a0255996..d8c9863054 100644
--- a/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb
+++ b/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb
@@ -10,7 +10,6 @@ class Bundler::Thor
# destination<String>:: the relative path to the destination root.
# config<Hash>:: give :verbose => false to not log the status, and
# :mode => :preserve, to preserve the file mode from the source.
-
#
# ==== Examples
#
@@ -243,6 +242,35 @@ class Bundler::Thor
insert_into_file(path, *(args << config), &block)
end
+ # Run a regular expression replacement on a file, raising an error if the
+ # contents of the file are not changed.
+ #
+ # ==== Parameters
+ # path<String>:: path of the file to be changed
+ # flag<Regexp|String>:: the regexp or string to be replaced
+ # replacement<String>:: the replacement, can be also given as a block
+ # config<Hash>:: give :verbose => false to not log the status, and
+ # :force => true, to force the replacement regardless of runner behavior.
+ #
+ # ==== Example
+ #
+ # gsub_file! 'app/controllers/application_controller.rb', /#\s*(filter_parameter_logging :password)/, '\1'
+ #
+ # gsub_file! 'README', /rake/, :green do |match|
+ # match << " no more. Use thor!"
+ # end
+ #
+ def gsub_file!(path, flag, *args, &block)
+ 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)
+
+ actually_gsub_file(path, flag, args, true, &block) unless options[:pretend]
+ end
+
# Run a regular expression replacement on a file.
#
# ==== Parameters
@@ -268,16 +296,11 @@ class Bundler::Thor
path = File.expand_path(path, destination_root)
say_status :gsub, relative_to_original_destination_root(path), config.fetch(:verbose, true)
- unless options[:pretend]
- content = File.binread(path)
- content.gsub!(flag, *args, &block)
- File.open(path, "wb") { |file| file.write(content) }
- end
+ actually_gsub_file(path, flag, args, false, &block) unless options[:pretend]
end
- # Uncomment all lines matching a given regex. It will leave the space
- # which existed before the comment hash in tact but will remove any spacing
- # between the comment hash and the beginning of the line.
+ # Uncomment all lines matching a given regex. Preserves indentation before
+ # the comment hash and removes the hash and any immediate following space.
#
# ==== Parameters
# path<String>:: path of the file to be changed
@@ -291,7 +314,7 @@ class Bundler::Thor
def uncomment_lines(path, flag, *args)
flag = flag.respond_to?(:source) ? flag.source : flag
- gsub_file(path, /^(\s*)#[[:blank:]]*(.*#{flag})/, '\1\2', *args)
+ gsub_file(path, /^(\s*)#[[:blank:]]?(.*#{flag})/, '\1\2', *args)
end
# Comment all lines matching a given regex. It will leave the space
@@ -350,7 +373,7 @@ class Bundler::Thor
end
def with_output_buffer(buf = "".dup) #:nodoc:
- raise ArgumentError, "Buffer can not be a frozen object" if buf.frozen?
+ raise ArgumentError, "Buffer cannot be a frozen object" if buf.frozen?
old_buffer = output_buffer
self.output_buffer = buf
yield
@@ -359,6 +382,17 @@ class Bundler::Thor
self.output_buffer = old_buffer
end
+ def actually_gsub_file(path, flag, args, error_on_no_change, &block)
+ content = File.binread(path)
+ success = content.gsub!(flag, *args, &block)
+
+ if success.nil? && error_on_no_change
+ raise Bundler::Thor::Error, "The content of #{path} did not change"
+ end
+
+ File.open(path, "wb") { |file| file.write(content) }
+ end
+
# Bundler::Thor::Actions#capture depends on what kind of buffer is used in ERB.
# Thus CapturableERB fixes ERB to use String buffer.
class CapturableERB < ERB
diff --git a/lib/bundler/vendor/thor/lib/thor/group.rb b/lib/bundler/vendor/thor/lib/thor/group.rb
index 7ea11e8f93..30bc311294 100644
--- a/lib/bundler/vendor/thor/lib/thor/group.rb
+++ b/lib/bundler/vendor/thor/lib/thor/group.rb
@@ -211,6 +211,17 @@ class Bundler::Thor::Group
raise error, msg
end
+ # Checks if a specified command exists.
+ #
+ # ==== Parameters
+ # command_name<String>:: The name of the command to check for existence.
+ #
+ # ==== Returns
+ # Boolean:: +true+ if the command exists, +false+ otherwise.
+ def command_exists?(command_name) #:nodoc:
+ commands.keys.include?(command_name)
+ end
+
protected
# The method responsible for dispatching given the args.
diff --git a/lib/bundler/vendor/thor/lib/thor/parser/argument.rb b/lib/bundler/vendor/thor/lib/thor/parser/argument.rb
index b9e94e4669..ee9db4ad8a 100644
--- a/lib/bundler/vendor/thor/lib/thor/parser/argument.rb
+++ b/lib/bundler/vendor/thor/lib/thor/parser/argument.rb
@@ -26,10 +26,7 @@ class Bundler::Thor
def print_default
if @type == :array and @default.is_a?(Array)
- @default.map { |x|
- p = x.gsub('"','\\"')
- "\"#{p}\""
- }.join(" ")
+ @default.map(&:dump).join(" ")
else
@default
end
diff --git a/lib/bundler/vendor/thor/lib/thor/parser/option.rb b/lib/bundler/vendor/thor/lib/thor/parser/option.rb
index c6af4e1e87..72617c7e34 100644
--- a/lib/bundler/vendor/thor/lib/thor/parser/option.rb
+++ b/lib/bundler/vendor/thor/lib/thor/parser/option.rb
@@ -89,8 +89,8 @@ class Bundler::Thor
sample = "[#{sample}]".dup unless required?
- if boolean?
- sample << ", [#{dasherize('no-' + human_name)}]" unless (name == "force") || name.match(/\Ano[\-_]/)
+ if boolean? && name != "force" && !name.match(/\A(no|skip)[\-_]/)
+ sample << ", [#{dasherize('no-' + human_name)}], [#{dasherize('skip-' + human_name)}]"
end
aliases_for_usage.ljust(padding) + sample
diff --git a/lib/bundler/vendor/thor/lib/thor/parser/options.rb b/lib/bundler/vendor/thor/lib/thor/parser/options.rb
index 978e76b132..fe22d989e5 100644
--- a/lib/bundler/vendor/thor/lib/thor/parser/options.rb
+++ b/lib/bundler/vendor/thor/lib/thor/parser/options.rb
@@ -144,7 +144,7 @@ class Bundler::Thor
def check_exclusive!
opts = @assigns.keys
# When option A and B are exclusive, if A and B are given at the same time,
- # the diffrence of argument array size will decrease.
+ # the difference of argument array size will decrease.
found = @exclusives.find{ |ex| (ex - opts).size < ex.size - 1 }
if found
names = names_to_switch_names(found & opts).map{|n| "'#{n}'"}
@@ -250,7 +250,8 @@ class Bundler::Thor
@parsing_options
end
- # Parse boolean values which can be given as --foo=true, --foo or --no-foo.
+ # Parse boolean values which can be given as --foo=true or --foo for true values, or
+ # --foo=false, --no-foo or --skip-foo for false values.
#
def parse_boolean(switch)
if current_is_value?
diff --git a/lib/bundler/vendor/thor/lib/thor/runner.rb b/lib/bundler/vendor/thor/lib/thor/runner.rb
index c7cc873131..f0ce6df96c 100644
--- a/lib/bundler/vendor/thor/lib/thor/runner.rb
+++ b/lib/bundler/vendor/thor/lib/thor/runner.rb
@@ -1,9 +1,8 @@
require_relative "../thor"
require_relative "group"
-require "yaml"
require "digest/sha2"
-require "pathname"
+require "pathname" unless defined?(Pathname)
class Bundler::Thor::Runner < Bundler::Thor #:nodoc:
map "-T" => :list, "-i" => :install, "-u" => :update, "-v" => :version
@@ -195,6 +194,7 @@ private
def thor_yaml
@thor_yaml ||= begin
yaml_file = File.join(thor_root, "thor.yml")
+ require "yaml"
yaml = YAML.load_file(yaml_file) if File.exist?(yaml_file)
yaml || {}
end
diff --git a/lib/bundler/vendor/thor/lib/thor/shell/basic.rb b/lib/bundler/vendor/thor/lib/thor/shell/basic.rb
index dc3179e5f3..da02b94227 100644
--- a/lib/bundler/vendor/thor/lib/thor/shell/basic.rb
+++ b/lib/bundler/vendor/thor/lib/thor/shell/basic.rb
@@ -67,15 +67,15 @@ class Bundler::Thor
# Readline.
#
# ==== Example
- # ask("What is your name?")
+ # ask("What is your name?")
#
- # ask("What is the planet furthest from the sun?", :default => "Pluto")
+ # ask("What is the planet furthest from the sun?", :default => "Neptune")
#
- # ask("What is your favorite Neopolitan flavor?", :limited_to => ["strawberry", "chocolate", "vanilla"])
+ # ask("What is your favorite Neopolitan flavor?", :limited_to => ["strawberry", "chocolate", "vanilla"])
#
- # ask("What is your password?", :echo => false)
+ # ask("What is your password?", :echo => false)
#
- # ask("Where should the file be saved?", :path => true)
+ # ask("Where should the file be saved?", :path => true)
#
def ask(statement, *args)
options = args.last.is_a?(Hash) ? args.pop : {}
@@ -93,7 +93,7 @@ class Bundler::Thor
# are passed straight to puts (behavior got from Highline).
#
# ==== Example
- # say("I know you knew that.")
+ # say("I know you knew that.")
#
def say(message = "", color = nil, force_new_line = (message.to_s !~ /( |\t)\Z/))
return if quiet?
@@ -110,7 +110,7 @@ class Bundler::Thor
# are passed straight to puts (behavior got from Highline).
#
# ==== Example
- # say_error("error: something went wrong")
+ # say_error("error: something went wrong")
#
def say_error(message = "", color = nil, force_new_line = (message.to_s !~ /( |\t)\Z/))
return if quiet?
@@ -143,14 +143,14 @@ class Bundler::Thor
stdout.flush
end
- # Make a question the to user and returns true if the user replies "y" or
+ # Asks the user a question and returns true if the user replies "y" or
# "yes".
#
def yes?(statement, color = nil)
!!(ask(statement, color, add_to_history: false) =~ is?(:yes))
end
- # Make a question the to user and returns true if the user replies "n" or
+ # Asks the user a question and returns true if the user replies "n" or
# "no".
#
def no?(statement, color = nil)
@@ -314,7 +314,7 @@ class Bundler::Thor
diff_cmd = ENV["THOR_DIFF"] || ENV["RAILS_DIFF"] || "diff -u"
require "tempfile"
- Tempfile.open(File.basename(destination), File.dirname(destination)) do |temp|
+ Tempfile.open(File.basename(destination), File.dirname(destination), binmode: true) do |temp|
temp.write content
temp.rewind
system %(#{diff_cmd} "#{destination}" "#{temp.path}")
@@ -372,16 +372,12 @@ class Bundler::Thor
Tempfile.open([File.basename(destination), File.extname(destination)], File.dirname(destination)) do |temp|
temp.write content
temp.rewind
- system %(#{merge_tool} "#{temp.path}" "#{destination}")
+ system(merge_tool, temp.path, destination)
end
end
def merge_tool #:nodoc:
- @merge_tool ||= ENV["THOR_MERGE"] || git_merge_tool
- end
-
- def git_merge_tool #:nodoc:
- `git config merge.tool`.rstrip rescue ""
+ @merge_tool ||= ENV["THOR_MERGE"] || "git difftool --no-index"
end
end
end
diff --git a/lib/bundler/vendor/thor/lib/thor/shell/html.rb b/lib/bundler/vendor/thor/lib/thor/shell/html.rb
index 0277b882b7..a0a8520e5c 100644
--- a/lib/bundler/vendor/thor/lib/thor/shell/html.rb
+++ b/lib/bundler/vendor/thor/lib/thor/shell/html.rb
@@ -64,7 +64,7 @@ class Bundler::Thor
# Ask something to the user and receives a response.
#
# ==== Example
- # ask("What is your name?")
+ # ask("What is your name?")
#
# TODO: Implement #ask for Bundler::Thor::Shell::HTML
def ask(statement, color = nil)
diff --git a/lib/bundler/vendor/thor/lib/thor/shell/table_printer.rb b/lib/bundler/vendor/thor/lib/thor/shell/table_printer.rb
index 525f9ce5bb..dee3614753 100644
--- a/lib/bundler/vendor/thor/lib/thor/shell/table_printer.rb
+++ b/lib/bundler/vendor/thor/lib/thor/shell/table_printer.rb
@@ -102,33 +102,17 @@ class Bundler::Thor
def truncate(string)
return string unless @truncate
- as_unicode do
- chars = string.chars.to_a
- if chars.length <= @truncate
- chars.join
- else
- chars[0, @truncate - 3 - @indent].join + "..."
- end
+ chars = string.chars.to_a
+ if chars.length <= @truncate
+ chars.join
+ else
+ chars[0, @truncate - 3 - @indent].join + "..."
end
end
def indentation
" " * @indent
end
-
- if "".respond_to?(:encode)
- def as_unicode
- yield
- end
- else
- def as_unicode
- old = $KCODE # rubocop:disable Style/GlobalVars
- $KCODE = "U" # rubocop:disable Style/GlobalVars
- yield
- ensure
- $KCODE = old # rubocop:disable Style/GlobalVars
- end
- end
end
end
end
diff --git a/lib/bundler/vendor/thor/lib/thor/util.rb b/lib/bundler/vendor/thor/lib/thor/util.rb
index 68916daf2e..cd8f9ece87 100644
--- a/lib/bundler/vendor/thor/lib/thor/util.rb
+++ b/lib/bundler/vendor/thor/lib/thor/util.rb
@@ -133,7 +133,7 @@ class Bundler::Thor
*pieces, command = namespace.split(":")
namespace = pieces.join(":")
namespace = "default" if namespace.empty?
- klass = Bundler::Thor::Base.subclasses.detect { |thor| thor.namespace == namespace && thor.commands.keys.include?(command) }
+ klass = Bundler::Thor::Base.subclasses.detect { |thor| thor.namespace == namespace && thor.command_exists?(command) }
end
unless klass # look for a Bundler::Thor::Group with the right name
klass = Bundler::Thor::Util.find_by_namespace(namespace)
diff --git a/lib/bundler/vendor/thor/lib/thor/version.rb b/lib/bundler/vendor/thor/lib/thor/version.rb
index 1fb00017ed..5474a2f71b 100644
--- a/lib/bundler/vendor/thor/lib/thor/version.rb
+++ b/lib/bundler/vendor/thor/lib/thor/version.rb
@@ -1,3 +1,3 @@
class Bundler::Thor
- VERSION = "1.3.0"
+ VERSION = "1.4.0"
end
diff --git a/lib/bundler/vendor/tsort/.document b/lib/bundler/vendor/tsort/.document
deleted file mode 100644
index 0c43bbd6b3..0000000000
--- a/lib/bundler/vendor/tsort/.document
+++ /dev/null
@@ -1 +0,0 @@
-# Vendored files do not need to be documented
diff --git a/lib/bundler/vendor/uri/.document b/lib/bundler/vendor/uri/.document
deleted file mode 100644
index 0c43bbd6b3..0000000000
--- a/lib/bundler/vendor/uri/.document
+++ /dev/null
@@ -1 +0,0 @@
-# Vendored files do not need to be documented
diff --git a/lib/bundler/vendor/uri/lib/uri.rb b/lib/bundler/vendor/uri/lib/uri.rb
index 976320f6bd..57b380c480 100644
--- a/lib/bundler/vendor/uri/lib/uri.rb
+++ b/lib/bundler/vendor/uri/lib/uri.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: false
# Bundler::URI is a module providing classes to handle Uniform Resource Identifiers
-# (RFC2396[http://tools.ietf.org/html/rfc2396]).
+# (RFC2396[https://www.rfc-editor.org/rfc/rfc2396]).
#
# == Features
#
@@ -47,14 +47,14 @@
# A good place to view an RFC spec is http://www.ietf.org/rfc.html.
#
# Here is a list of all related RFC's:
-# - RFC822[http://tools.ietf.org/html/rfc822]
-# - RFC1738[http://tools.ietf.org/html/rfc1738]
-# - RFC2255[http://tools.ietf.org/html/rfc2255]
-# - RFC2368[http://tools.ietf.org/html/rfc2368]
-# - RFC2373[http://tools.ietf.org/html/rfc2373]
-# - RFC2396[http://tools.ietf.org/html/rfc2396]
-# - RFC2732[http://tools.ietf.org/html/rfc2732]
-# - RFC3986[http://tools.ietf.org/html/rfc3986]
+# - RFC822[https://www.rfc-editor.org/rfc/rfc822]
+# - RFC1738[https://www.rfc-editor.org/rfc/rfc1738]
+# - RFC2255[https://www.rfc-editor.org/rfc/rfc2255]
+# - RFC2368[https://www.rfc-editor.org/rfc/rfc2368]
+# - RFC2373[https://www.rfc-editor.org/rfc/rfc2373]
+# - RFC2396[https://www.rfc-editor.org/rfc/rfc2396]
+# - RFC2732[https://www.rfc-editor.org/rfc/rfc2732]
+# - RFC3986[https://www.rfc-editor.org/rfc/rfc3986]
#
# == Class tree
#
diff --git a/lib/bundler/vendor/uri/lib/uri/common.rb b/lib/bundler/vendor/uri/lib/uri/common.rb
index 93f4f226ad..38339119c5 100644
--- a/lib/bundler/vendor/uri/lib/uri/common.rb
+++ b/lib/bundler/vendor/uri/lib/uri/common.rb
@@ -13,24 +13,54 @@ require_relative "rfc2396_parser"
require_relative "rfc3986_parser"
module Bundler::URI
- include RFC2396_REGEXP
+ # The default parser instance for RFC 2396.
+ RFC2396_PARSER = RFC2396_Parser.new
+ Ractor.make_shareable(RFC2396_PARSER) if defined?(Ractor)
- REGEXP = RFC2396_REGEXP
- Parser = RFC2396_Parser
+ # The default parser instance for RFC 3986.
RFC3986_PARSER = RFC3986_Parser.new
Ractor.make_shareable(RFC3986_PARSER) if defined?(Ractor)
- # Bundler::URI::Parser.new
- DEFAULT_PARSER = Parser.new
- DEFAULT_PARSER.pattern.each_pair do |sym, str|
- unless REGEXP::PATTERN.const_defined?(sym)
- REGEXP::PATTERN.const_set(sym, str)
+ # The default parser instance.
+ DEFAULT_PARSER = RFC3986_PARSER
+ Ractor.make_shareable(DEFAULT_PARSER) if defined?(Ractor)
+
+ # Set the default parser instance.
+ def self.parser=(parser = RFC3986_PARSER)
+ remove_const(:Parser) if defined?(::Bundler::URI::Parser)
+ const_set("Parser", parser.class)
+
+ remove_const(:PARSER) if defined?(::Bundler::URI::PARSER)
+ const_set("PARSER", parser)
+
+ remove_const(:REGEXP) if defined?(::Bundler::URI::REGEXP)
+ remove_const(:PATTERN) if defined?(::Bundler::URI::PATTERN)
+ if Parser == RFC2396_Parser
+ const_set("REGEXP", Bundler::URI::RFC2396_REGEXP)
+ const_set("PATTERN", Bundler::URI::RFC2396_REGEXP::PATTERN)
+ end
+
+ Parser.new.regexp.each_pair do |sym, str|
+ remove_const(sym) if const_defined?(sym, false)
+ const_set(sym, str)
end
end
- DEFAULT_PARSER.regexp.each_pair do |sym, str|
- const_set(sym, str)
+ self.parser = RFC3986_PARSER
+
+ def self.const_missing(const) # :nodoc:
+ if const == :REGEXP
+ warn "Bundler::URI::REGEXP is obsolete. Use Bundler::URI::RFC2396_REGEXP explicitly.", uplevel: 1 if $VERBOSE
+ Bundler::URI::RFC2396_REGEXP
+ elsif value = RFC2396_PARSER.regexp[const]
+ warn "Bundler::URI::#{const} is obsolete. Use Bundler::URI::RFC2396_PARSER.regexp[#{const.inspect}] explicitly.", uplevel: 1 if $VERBOSE
+ value
+ elsif value = RFC2396_Parser.const_get(const)
+ warn "Bundler::URI::#{const} is obsolete. Use Bundler::URI::RFC2396_Parser::#{const} explicitly.", uplevel: 1 if $VERBOSE
+ value
+ else
+ super
+ end
end
- Ractor.make_shareable(DEFAULT_PARSER) if defined?(Ractor)
module Util # :nodoc:
def make_components_hash(klass, array_hash)
@@ -64,7 +94,41 @@ module Bundler::URI
module_function :make_components_hash
end
- module Schemes
+ module Schemes # :nodoc:
+ class << self
+ ReservedChars = ".+-"
+ EscapedChars = "\u01C0\u01C1\u01C2"
+ # Use Lo category chars as escaped chars for TruffleRuby, which
+ # does not allow Symbol categories as identifiers.
+
+ def escape(name)
+ unless name and name.ascii_only?
+ return nil
+ end
+ name.upcase.tr(ReservedChars, EscapedChars)
+ end
+
+ def unescape(name)
+ name.tr(EscapedChars, ReservedChars).encode(Encoding::US_ASCII).upcase
+ end
+
+ def find(name)
+ const_get(name, false) if name and const_defined?(name, false)
+ end
+
+ def register(name, klass)
+ unless scheme = escape(name)
+ raise ArgumentError, "invalid character as scheme - #{name}"
+ end
+ const_set(scheme, klass)
+ end
+
+ def list
+ constants.map { |name|
+ [unescape(name.to_s), const_get(name)]
+ }.to_h
+ end
+ end
end
private_constant :Schemes
@@ -77,7 +141,7 @@ module Bundler::URI
# Note that after calling String#upcase on +scheme+, it must be a valid
# constant name.
def self.register_scheme(scheme, klass)
- Schemes.const_set(scheme.to_s.upcase, klass)
+ Schemes.register(scheme, klass)
end
# Returns a hash of the defined schemes:
@@ -95,14 +159,14 @@ module Bundler::URI
#
# Related: Bundler::URI.register_scheme.
def self.scheme_list
- Schemes.constants.map { |name|
- [name.to_s.upcase, Schemes.const_get(name)]
- }.to_h
+ Schemes.list
end
+ # :stopdoc:
INITIAL_SCHEMES = scheme_list
private_constant :INITIAL_SCHEMES
Ractor.make_shareable(INITIAL_SCHEMES) if defined?(Ractor)
+ # :startdoc:
# Returns a new object constructed from the given +scheme+, +arguments+,
# and +default+:
@@ -121,12 +185,10 @@ module Bundler::URI
# # => #<Bundler::URI::HTTP foo://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
#
def self.for(scheme, *arguments, default: Generic)
- const_name = scheme.to_s.upcase
+ const_name = Schemes.escape(scheme)
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 ||= Schemes.find(const_name)
uri_class ||= default
return uri_class.new(scheme, *arguments)
@@ -168,7 +230,7 @@ module Bundler::URI
# ["fragment", "top"]]
#
def self.split(uri)
- RFC3986_PARSER.split(uri)
+ PARSER.split(uri)
end
# Returns a new \Bundler::URI object constructed from the given string +uri+:
@@ -178,11 +240,11 @@ module Bundler::URI
# Bundler::URI.parse('http://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top')
# # => #<Bundler::URI::HTTP http://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
#
- # It's recommended to first ::escape string +uri+
+ # It's recommended to first Bundler::URI::RFC2396_PARSER.escape string +uri+
# if it may contain invalid Bundler::URI characters.
#
def self.parse(uri)
- RFC3986_PARSER.parse(uri)
+ PARSER.parse(uri)
end
# Merges the given Bundler::URI strings +str+
@@ -209,7 +271,7 @@ module Bundler::URI
# # => #<Bundler::URI::HTTP http://example.com/foo/bar>
#
def self.join(*str)
- RFC3986_PARSER.join(*str)
+ DEFAULT_PARSER.join(*str)
end
#
@@ -238,7 +300,7 @@ module Bundler::URI
#
def self.extract(str, schemes = nil, &block) # :nodoc:
warn "Bundler::URI.extract is obsolete", uplevel: 1 if $VERBOSE
- DEFAULT_PARSER.extract(str, schemes, &block)
+ PARSER.extract(str, schemes, &block)
end
#
@@ -275,14 +337,14 @@ module Bundler::URI
#
def self.regexp(schemes = nil)# :nodoc:
warn "Bundler::URI.regexp is obsolete", uplevel: 1 if $VERBOSE
- DEFAULT_PARSER.make_regexp(schemes)
+ PARSER.make_regexp(schemes)
end
TBLENCWWWCOMP_ = {} # :nodoc:
256.times do |i|
TBLENCWWWCOMP_[-i.chr] = -('%%%02X' % i)
end
- TBLENCURICOMP_ = TBLENCWWWCOMP_.dup.freeze
+ TBLENCURICOMP_ = TBLENCWWWCOMP_.dup.freeze # :nodoc:
TBLENCWWWCOMP_[' '] = '+'
TBLENCWWWCOMP_.freeze
TBLDECWWWCOMP_ = {} # :nodoc:
@@ -380,6 +442,8 @@ module Bundler::URI
_decode_uri_component(/%\h\h/, str, enc)
end
+ # Returns a string derived from the given string +str+ with
+ # Bundler::URI-encoded characters matching +regexp+ according to +table+.
def self._encode_uri_component(regexp, table, str, enc)
str = str.to_s.dup
if str.encoding != Encoding::ASCII_8BIT
@@ -394,6 +458,8 @@ module Bundler::URI
end
private_class_method :_encode_uri_component
+ # Returns a string decoding characters matching +regexp+ from the
+ # given \URL-encoded string +str+.
def self._decode_uri_component(regexp, str, enc)
raise ArgumentError, "invalid %-encoding (#{str})" if /%(?!\h\h)/.match?(str)
str.b.gsub(regexp, TBLDECWWWCOMP_).force_encoding(enc)
@@ -832,6 +898,7 @@ module Bundler
# Returns a \Bundler::URI object derived from the given +uri+,
# which may be a \Bundler::URI string or an existing \Bundler::URI object:
#
+ # require 'bundler/vendor/uri/lib/uri'
# # Returns a new Bundler::URI.
# uri = Bundler::URI('http://github.com/ruby/ruby')
# # => #<Bundler::URI::HTTP http://github.com/ruby/ruby>
@@ -839,6 +906,8 @@ module Bundler
# Bundler::URI(uri)
# # => #<Bundler::URI::HTTP http://github.com/ruby/ruby>
#
+ # You must require 'bundler/vendor/uri/lib/uri' to use this method.
+ #
def URI(uri)
if uri.is_a?(Bundler::URI::Generic)
uri
diff --git a/lib/bundler/vendor/uri/lib/uri/file.rb b/lib/bundler/vendor/uri/lib/uri/file.rb
index 8d75a9de7a..21dd9ee535 100644
--- a/lib/bundler/vendor/uri/lib/uri/file.rb
+++ b/lib/bundler/vendor/uri/lib/uri/file.rb
@@ -47,7 +47,7 @@ module Bundler::URI
# :path => '/ruby/src'})
# uri2.to_s # => "file://host.example.com/ruby/src"
#
- # uri3 = Bundler::URI::File.build({:path => Bundler::URI::escape('/path/my file.txt')})
+ # uri3 = Bundler::URI::File.build({:path => Bundler::URI::RFC2396_PARSER.escape('/path/my file.txt')})
# uri3.to_s # => "file:///path/my%20file.txt"
#
def self.build(args)
@@ -70,17 +70,17 @@ module Bundler::URI
# raise InvalidURIError
def check_userinfo(user)
- raise Bundler::URI::InvalidURIError, "can not set userinfo for file Bundler::URI"
+ raise Bundler::URI::InvalidURIError, "cannot set userinfo for file Bundler::URI"
end
# raise InvalidURIError
def check_user(user)
- raise Bundler::URI::InvalidURIError, "can not set user for file Bundler::URI"
+ raise Bundler::URI::InvalidURIError, "cannot set user for file Bundler::URI"
end
# raise InvalidURIError
def check_password(user)
- raise Bundler::URI::InvalidURIError, "can not set password for file Bundler::URI"
+ raise Bundler::URI::InvalidURIError, "cannot set password for file Bundler::URI"
end
# do nothing
diff --git a/lib/bundler/vendor/uri/lib/uri/ftp.rb b/lib/bundler/vendor/uri/lib/uri/ftp.rb
index 48b4c6718d..f83985fd3d 100644
--- a/lib/bundler/vendor/uri/lib/uri/ftp.rb
+++ b/lib/bundler/vendor/uri/lib/uri/ftp.rb
@@ -17,7 +17,7 @@ module Bundler::URI
# This class will be redesigned because of difference of implementations;
# the structure of its path. draft-hoffman-ftp-uri-04 is a draft but it
# is a good summary about the de facto spec.
- # http://tools.ietf.org/html/draft-hoffman-ftp-uri-04
+ # https://datatracker.ietf.org/doc/html/draft-hoffman-ftp-uri-04
#
class FTP < Generic
# A Default port of 21 for Bundler::URI::FTP.
diff --git a/lib/bundler/vendor/uri/lib/uri/generic.rb b/lib/bundler/vendor/uri/lib/uri/generic.rb
index 762c425ac1..30dab60903 100644
--- a/lib/bundler/vendor/uri/lib/uri/generic.rb
+++ b/lib/bundler/vendor/uri/lib/uri/generic.rb
@@ -73,7 +73,7 @@ module Bundler::URI
#
# At first, tries to create a new Bundler::URI::Generic instance using
# Bundler::URI::Generic::build. But, if exception Bundler::URI::InvalidComponentError is raised,
- # then it does Bundler::URI::Escape.escape all Bundler::URI components and tries again.
+ # then it does Bundler::URI::RFC2396_PARSER.escape all Bundler::URI components and tries again.
#
def self.build2(args)
begin
@@ -82,7 +82,7 @@ module Bundler::URI
if args.kind_of?(Array)
return self.build(args.collect{|x|
if x.is_a?(String)
- DEFAULT_PARSER.escape(x)
+ Bundler::URI::RFC2396_PARSER.escape(x)
else
x
end
@@ -91,7 +91,7 @@ module Bundler::URI
tmp = {}
args.each do |key, value|
tmp[key] = if value
- DEFAULT_PARSER.escape(value)
+ Bundler::URI::RFC2396_PARSER.escape(value)
else
value
end
@@ -126,9 +126,9 @@ module Bundler::URI
end
end
else
- component = self.class.component rescue ::Bundler::URI::Generic::COMPONENT
+ component = self.component rescue ::Bundler::URI::Generic::COMPONENT
raise ArgumentError,
- "expected Array of or Hash of components of #{self.class} (#{component.join(', ')})"
+ "expected Array of or Hash of components of #{self} (#{component.join(', ')})"
end
tmp << nil
@@ -186,18 +186,18 @@ module Bundler::URI
if arg_check
self.scheme = scheme
- self.userinfo = userinfo
self.hostname = host
self.port = port
+ self.userinfo = userinfo
self.path = path
self.query = query
self.opaque = opaque
self.fragment = fragment
else
self.set_scheme(scheme)
- self.set_userinfo(userinfo)
self.set_host(host)
self.set_port(port)
+ self.set_userinfo(userinfo)
self.set_path(path)
self.query = query
self.set_opaque(opaque)
@@ -284,7 +284,7 @@ module Bundler::URI
# Returns the parser to be used.
#
- # Unless a Bundler::URI::Parser is defined, DEFAULT_PARSER is used.
+ # Unless the +parser+ is defined, DEFAULT_PARSER is used.
#
def parser
if !defined?(@parser) || !@parser
@@ -315,7 +315,7 @@ module Bundler::URI
end
#
- # Checks the scheme +v+ component against the Bundler::URI::Parser Regexp for :SCHEME.
+ # Checks the scheme +v+ component against the +parser+ Regexp for :SCHEME.
#
def check_scheme(v)
if v && parser.regexp[:SCHEME] !~ v
@@ -385,7 +385,7 @@ module Bundler::URI
#
# Checks the user +v+ component for RFC2396 compliance
- # and against the Bundler::URI::Parser Regexp for :USERINFO.
+ # and against the +parser+ Regexp for :USERINFO.
#
# Can not have a registry or opaque component defined,
# with a user component defined.
@@ -393,7 +393,7 @@ module Bundler::URI
def check_user(v)
if @opaque
raise InvalidURIError,
- "can not set user with opaque"
+ "cannot set user with opaque"
end
return v unless v
@@ -409,7 +409,7 @@ module Bundler::URI
#
# Checks the password +v+ component for RFC2396 compliance
- # and against the Bundler::URI::Parser Regexp for :USERINFO.
+ # and against the +parser+ Regexp for :USERINFO.
#
# Can not have a registry or opaque component defined,
# with a user component defined.
@@ -417,7 +417,7 @@ module Bundler::URI
def check_password(v, user = @user)
if @opaque
raise InvalidURIError,
- "can not set password with opaque"
+ "cannot set password with opaque"
end
return v unless v
@@ -511,7 +511,7 @@ module Bundler::URI
user, password = split_userinfo(user)
end
@user = user
- @password = password if password
+ @password = password
[@user, @password]
end
@@ -522,7 +522,7 @@ module Bundler::URI
# See also Bundler::URI::Generic.user=.
#
def set_user(v)
- set_userinfo(v, @password)
+ set_userinfo(v, nil)
v
end
protected :set_user
@@ -574,6 +574,12 @@ module Bundler::URI
@password
end
+ # Returns the authority info (array of user, password, host and
+ # port), if any is set. Or returns +nil+.
+ def authority
+ return @user, @password, @host, @port if @user || @password || @host || @port
+ end
+
# Returns the user component after Bundler::URI decoding.
def decoded_user
Bundler::URI.decode_uri_component(@user) if @user
@@ -586,7 +592,7 @@ module Bundler::URI
#
# Checks the host +v+ component for RFC2396 compliance
- # and against the Bundler::URI::Parser Regexp for :HOST.
+ # and against the +parser+ Regexp for :HOST.
#
# Can not have a registry or opaque component defined,
# with a host component defined.
@@ -596,7 +602,7 @@ module Bundler::URI
if @opaque
raise InvalidURIError,
- "can not set host with registry or opaque"
+ "cannot set host with registry or opaque"
elsif parser.regexp[:HOST] !~ v
raise InvalidComponentError,
"bad component(expected host component): #{v}"
@@ -615,6 +621,13 @@ module Bundler::URI
end
protected :set_host
+ # Protected setter for the authority info (+user+, +password+, +host+
+ # and +port+). If +port+ is +nil+, +default_port+ will be set.
+ #
+ protected def set_authority(user, password, host, port = nil)
+ @user, @password, @host, @port = user, password, host, port || self.default_port
+ end
+
#
# == Args
#
@@ -639,6 +652,7 @@ module Bundler::URI
def host=(v)
check_host(v)
set_host(v)
+ set_userinfo(nil)
v
end
@@ -675,7 +689,7 @@ module Bundler::URI
#
# Checks the port +v+ component for RFC2396 compliance
- # and against the Bundler::URI::Parser Regexp for :PORT.
+ # and against the +parser+ Regexp for :PORT.
#
# Can not have a registry or opaque component defined,
# with a port component defined.
@@ -685,7 +699,7 @@ module Bundler::URI
if @opaque
raise InvalidURIError,
- "can not set port with registry or opaque"
+ "cannot set port with registry or opaque"
elsif !v.kind_of?(Integer) && parser.regexp[:PORT] !~ v
raise InvalidComponentError,
"bad component(expected port component): #{v.inspect}"
@@ -729,26 +743,27 @@ module Bundler::URI
def port=(v)
check_port(v)
set_port(v)
+ set_userinfo(nil)
port
end
def check_registry(v) # :nodoc:
- raise InvalidURIError, "can not set registry"
+ raise InvalidURIError, "cannot set registry"
end
private :check_registry
- def set_registry(v) #:nodoc:
- raise InvalidURIError, "can not set registry"
+ def set_registry(v) # :nodoc:
+ raise InvalidURIError, "cannot set registry"
end
protected :set_registry
- def registry=(v)
- raise InvalidURIError, "can not set registry"
+ def registry=(v) # :nodoc:
+ raise InvalidURIError, "cannot set registry"
end
#
# Checks the path +v+ component for RFC2396 compliance
- # and against the Bundler::URI::Parser Regexp
+ # and against the +parser+ Regexp
# for :ABS_PATH and :REL_PATH.
#
# Can not have a opaque component defined,
@@ -853,7 +868,7 @@ module Bundler::URI
#
# Checks the opaque +v+ component for RFC2396 compliance and
- # against the Bundler::URI::Parser Regexp for :OPAQUE.
+ # against the +parser+ Regexp for :OPAQUE.
#
# Can not have a host, port, user, or path component defined,
# with an opaque component defined.
@@ -866,7 +881,7 @@ module Bundler::URI
# hier_part = ( net_path | abs_path ) [ "?" query ]
if @host || @port || @user || @path # userinfo = @user + ':' + @password
raise InvalidURIError,
- "can not set opaque with host, port, userinfo or path"
+ "cannot set opaque with host, port, userinfo or path"
elsif v && parser.regexp[:OPAQUE] !~ v
raise InvalidComponentError,
"bad component(expected opaque component): #{v}"
@@ -905,7 +920,7 @@ module Bundler::URI
end
#
- # Checks the fragment +v+ component against the Bundler::URI::Parser Regexp for :FRAGMENT.
+ # Checks the fragment +v+ component against the +parser+ Regexp for :FRAGMENT.
#
#
# == Args
@@ -945,7 +960,7 @@ module Bundler::URI
# == Description
#
# Bundler::URI has components listed in order of decreasing significance from left to right,
- # see RFC3986 https://tools.ietf.org/html/rfc3986 1.2.3.
+ # see RFC3986 https://www.rfc-editor.org/rfc/rfc3986 1.2.3.
#
# == Usage
#
@@ -1121,7 +1136,7 @@ module Bundler::URI
base = self.dup
- authority = rel.userinfo || rel.host || rel.port
+ authority = rel.authority
# RFC2396, Section 5.2, 2)
if (rel.path.nil? || rel.path.empty?) && !authority && !rel.query
@@ -1133,17 +1148,14 @@ module Bundler::URI
base.fragment=(nil)
# RFC2396, Section 5.2, 4)
- if !authority
- base.set_path(merge_path(base.path, rel.path)) if base.path && rel.path
- else
- # RFC2396, Section 5.2, 4)
- base.set_path(rel.path) if rel.path
+ if authority
+ base.set_authority(*authority)
+ base.set_path(rel.path)
+ elsif base.path && rel.path
+ base.set_path(merge_path(base.path, rel.path))
end
# RFC2396, Section 5.2, 7)
- base.set_userinfo(rel.userinfo) if rel.userinfo
- base.set_host(rel.host) if rel.host
- base.set_port(rel.port) if rel.port
base.query = rel.query if rel.query
base.fragment=(rel.fragment) if rel.fragment
@@ -1235,7 +1247,7 @@ module Bundler::URI
return rel, rel
end
- # you can modify `rel', but can not `oth'.
+ # you can modify `rel', but cannot `oth'.
return oth, rel
end
private :route_from0
@@ -1260,7 +1272,7 @@ module Bundler::URI
# #=> #<Bundler::URI::Generic /main.rbx?page=1>
#
def route_from(oth)
- # you can modify `rel', but can not `oth'.
+ # you can modify `rel', but cannot `oth'.
begin
oth, rel = route_from0(oth)
rescue
@@ -1364,6 +1376,9 @@ module Bundler::URI
str << ':'
str << @port.to_s
end
+ if (@host || @port) && !@path.empty? && !@path.start_with?('/')
+ str << '/'
+ end
str << @path
if @query
str << '?'
@@ -1389,29 +1404,18 @@ module Bundler::URI
end
end
+ # Returns the hash value.
def hash
self.component_ary.hash
end
+ # Compares with _oth_ for Hash.
def eql?(oth)
self.class == oth.class &&
parser == oth.parser &&
self.component_ary.eql?(oth.component_ary)
end
-=begin
-
---- Bundler::URI::Generic#===(oth)
-
-=end
-# def ===(oth)
-# raise NotImplementedError
-# end
-
-=begin
-=end
-
-
# Returns an Array of the components defined from the COMPONENT Array.
def component_ary
component.collect do |x|
@@ -1448,7 +1452,7 @@ module Bundler::URI
end
end
- def inspect
+ def inspect # :nodoc:
"#<#{self.class} #{self}>"
end
@@ -1536,7 +1540,7 @@ module Bundler::URI
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
+ warn 'The environment variable HTTP_PROXY is discouraged. Please use http_proxy instead.', uplevel: 1
end
end
end
diff --git a/lib/bundler/vendor/uri/lib/uri/http.rb b/lib/bundler/vendor/uri/lib/uri/http.rb
index 2c44810644..9b217ee266 100644
--- a/lib/bundler/vendor/uri/lib/uri/http.rb
+++ b/lib/bundler/vendor/uri/lib/uri/http.rb
@@ -61,6 +61,18 @@ module Bundler::URI
super(tmp)
end
+ # Do not allow empty host names, as they are not allowed by RFC 3986.
+ def check_host(v)
+ ret = super
+
+ if ret && v.empty?
+ raise InvalidComponentError,
+ "bad component(expected host component): #{v}"
+ end
+
+ ret
+ end
+
#
# == Description
#
@@ -85,7 +97,7 @@ module Bundler::URI
# == Description
#
# Returns the authority for an HTTP uri, as defined in
- # https://datatracker.ietf.org/doc/html/rfc3986/#section-3.2.
+ # https://www.rfc-editor.org/rfc/rfc3986#section-3.2.
#
#
# Example:
@@ -106,7 +118,7 @@ module Bundler::URI
# == Description
#
# Returns the origin for an HTTP uri, as defined in
- # https://datatracker.ietf.org/doc/html/rfc6454.
+ # https://www.rfc-editor.org/rfc/rfc6454.
#
#
# Example:
diff --git a/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb b/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb
index 09c22c9906..522113fe67 100644
--- a/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb
+++ b/lib/bundler/vendor/uri/lib/uri/rfc2396_parser.rb
@@ -67,7 +67,7 @@ module Bundler::URI
#
# == Synopsis
#
- # Bundler::URI::Parser.new([opts])
+ # Bundler::URI::RFC2396_Parser.new([opts])
#
# == Args
#
@@ -86,7 +86,7 @@ module Bundler::URI
#
# == Examples
#
- # p = Bundler::URI::Parser.new(:ESCAPED => "(?:%[a-fA-F0-9]{2}|%u[a-fA-F0-9]{4})")
+ # p = Bundler::URI::RFC2396_Parser.new(:ESCAPED => "(?:%[a-fA-F0-9]{2}|%u[a-fA-F0-9]{4})")
# u = p.parse("http://example.jp/%uABCD") #=> #<Bundler::URI::HTTP http://example.jp/%uABCD>
# Bundler::URI.parse(u.to_s) #=> raises Bundler::URI::InvalidURIError
#
@@ -108,12 +108,12 @@ module Bundler::URI
# The Hash of patterns.
#
- # See also Bundler::URI::Parser.initialize_pattern.
+ # See also #initialize_pattern.
attr_reader :pattern
# The Hash of Regexp.
#
- # See also Bundler::URI::Parser.initialize_regexp.
+ # See also #initialize_regexp.
attr_reader :regexp
# Returns a split Bundler::URI against +regexp[:ABS_URI]+.
@@ -140,11 +140,11 @@ module Bundler::URI
if !scheme
raise InvalidURIError,
- "bad Bundler::URI(absolute but no scheme): #{uri}"
+ "bad Bundler::URI (absolute but no scheme): #{uri}"
end
if !opaque && (!path && (!host && !registry))
raise InvalidURIError,
- "bad Bundler::URI(absolute but no path): #{uri}"
+ "bad Bundler::URI (absolute but no path): #{uri}"
end
when @regexp[:REL_URI]
@@ -173,7 +173,7 @@ module Bundler::URI
# server = [ [ userinfo "@" ] hostport ]
else
- raise InvalidURIError, "bad Bundler::URI(is not Bundler::URI?): #{uri}"
+ raise InvalidURIError, "bad Bundler::URI (is not Bundler::URI?): #{uri}"
end
path = '' if !path && !opaque # (see RFC2396 Section 5.2)
@@ -202,8 +202,7 @@ module Bundler::URI
#
# == Usage
#
- # p = Bundler::URI::Parser.new
- # p.parse("ldap://ldap.example.com/dc=example?user=john")
+ # Bundler::URI::RFC2396_PARSER.parse("ldap://ldap.example.com/dc=example?user=john")
# #=> #<Bundler::URI::LDAP ldap://ldap.example.com/dc=example?user=john>
#
def parse(uri)
@@ -244,7 +243,7 @@ module Bundler::URI
# If no +block+ given, then returns the result,
# else it calls +block+ for each element in result.
#
- # See also Bundler::URI::Parser.make_regexp.
+ # See also #make_regexp.
#
def extract(str, schemes = nil)
if block_given?
@@ -263,7 +262,7 @@ module Bundler::URI
unless schemes
@regexp[:ABS_URI_REF]
else
- /(?=#{Regexp.union(*schemes)}:)#{@pattern[:X_ABS_URI]}/x
+ /(?=(?i:#{Regexp.union(*schemes).source}):)#{@pattern[:X_ABS_URI]}/x
end
end
@@ -321,14 +320,14 @@ module Bundler::URI
str.gsub(escaped) { [$&[1, 2]].pack('H2').force_encoding(enc) }
end
- @@to_s = Kernel.instance_method(:to_s)
- if @@to_s.respond_to?(:bind_call)
- def inspect
- @@to_s.bind_call(self)
+ TO_S = Kernel.instance_method(:to_s) # :nodoc:
+ if TO_S.respond_to?(:bind_call)
+ def inspect # :nodoc:
+ TO_S.bind_call(self)
end
else
- def inspect
- @@to_s.bind(self).call
+ def inspect # :nodoc:
+ TO_S.bind(self).call
end
end
@@ -524,6 +523,8 @@ module Bundler::URI
ret
end
+ # Returns +uri+ as-is if it is Bundler::URI, or convert it to Bundler::URI if it is
+ # a String.
def convert_to_uri(uri)
if uri.is_a?(Bundler::URI::Generic)
uri
@@ -536,4 +537,11 @@ module Bundler::URI
end
end # class Parser
+
+ # Backward compatibility for Bundler::URI::REGEXP::PATTERN::*
+ RFC2396_Parser.new.pattern.each_pair do |sym, str|
+ unless RFC2396_REGEXP::PATTERN.const_defined?(sym, false)
+ RFC2396_REGEXP::PATTERN.const_set(sym, str)
+ end
+ end
end # module Bundler::URI
diff --git a/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb b/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb
index 4c9882f595..d1ff28df23 100644
--- a/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb
+++ b/lib/bundler/vendor/uri/lib/uri/rfc3986_parser.rb
@@ -78,7 +78,7 @@ module Bundler::URI
begin
uri = uri.to_str
rescue NoMethodError
- raise InvalidURIError, "bad Bundler::URI(is not Bundler::URI?): #{uri.inspect}"
+ raise InvalidURIError, "bad Bundler::URI (is not Bundler::URI?): #{uri.inspect}"
end
uri.ascii_only? or
raise InvalidURIError, "Bundler::URI must be ascii only #{uri.dump}"
@@ -127,7 +127,7 @@ module Bundler::URI
m["fragment"]
]
else
- raise InvalidURIError, "bad Bundler::URI(is not Bundler::URI?): #{uri.inspect}"
+ raise InvalidURIError, "bad Bundler::URI (is not Bundler::URI?): #{uri.inspect}"
end
end
@@ -135,12 +135,35 @@ module Bundler::URI
Bundler::URI.for(*self.split(uri), self)
end
-
def join(*uris) # :nodoc:
uris[0] = convert_to_uri(uris[0])
uris.inject :merge
end
+ # Compatibility for RFC2396 parser
+ def extract(str, schemes = nil, &block) # :nodoc:
+ warn "Bundler::URI::RFC3986_PARSER.extract is obsolete. Use Bundler::URI::RFC2396_PARSER.extract explicitly.", uplevel: 1 if $VERBOSE
+ RFC2396_PARSER.extract(str, schemes, &block)
+ end
+
+ # Compatibility for RFC2396 parser
+ def make_regexp(schemes = nil) # :nodoc:
+ warn "Bundler::URI::RFC3986_PARSER.make_regexp is obsolete. Use Bundler::URI::RFC2396_PARSER.make_regexp explicitly.", uplevel: 1 if $VERBOSE
+ RFC2396_PARSER.make_regexp(schemes)
+ end
+
+ # Compatibility for RFC2396 parser
+ def escape(str, unsafe = nil) # :nodoc:
+ warn "Bundler::URI::RFC3986_PARSER.escape is obsolete. Use Bundler::URI::RFC2396_PARSER.escape explicitly.", uplevel: 1 if $VERBOSE
+ unsafe ? RFC2396_PARSER.escape(str, unsafe) : RFC2396_PARSER.escape(str)
+ end
+
+ # Compatibility for RFC2396 parser
+ def unescape(str, escaped = nil) # :nodoc:
+ warn "Bundler::URI::RFC3986_PARSER.unescape is obsolete. Use Bundler::URI::RFC2396_PARSER.unescape explicitly.", uplevel: 1 if $VERBOSE
+ escaped ? RFC2396_PARSER.unescape(str, escaped) : RFC2396_PARSER.unescape(str)
+ end
+
@@to_s = Kernel.instance_method(:to_s)
if @@to_s.respond_to?(:bind_call)
def inspect
diff --git a/lib/bundler/vendor/uri/lib/uri/version.rb b/lib/bundler/vendor/uri/lib/uri/version.rb
index 1fa1c7c09a..ad76308e81 100644
--- a/lib/bundler/vendor/uri/lib/uri/version.rb
+++ b/lib/bundler/vendor/uri/lib/uri/version.rb
@@ -1,6 +1,6 @@
module Bundler::URI
# :stopdoc:
- VERSION_CODE = '001300'.freeze
- VERSION = VERSION_CODE.scan(/../).collect{|n| n.to_i}.join('.').freeze
+ VERSION = '1.1.1'.freeze
+ VERSION_CODE = VERSION.split('.').map{|s| s.rjust(2, '0')}.join.freeze
# :startdoc:
end
diff --git a/lib/bundler/vendored_net_http.rb b/lib/bundler/vendored_net_http.rb
index 0dcabaa7d7..8ff2ccd1fe 100644
--- a/lib/bundler/vendored_net_http.rb
+++ b/lib/bundler/vendored_net_http.rb
@@ -1,12 +1,23 @@
# frozen_string_literal: true
-begin
- require "rubygems/vendored_net_http"
-rescue LoadError
+# This defined? guard can be removed once RubyGems 3.4 support is dropped.
+#
+# Bundler specs load this code from `spec/support/vendored_net_http.rb` to avoid
+# activating the Bundler gem too early. Without this guard, we get redefinition
+# warnings once Bundler is actually activated and
+# `lib/bundler/vendored_net_http.rb` is required. This is not an issue in
+# RubyGems versions including `rubygems/vendored_net_http` since `require` takes
+# care of avoiding the double load.
+#
+unless defined?(Gem::Net)
begin
- require "rubygems/net/http"
+ require "rubygems/vendored_net_http"
rescue LoadError
- require "net/http"
- Gem::Net = Net
+ begin
+ require "rubygems/net/http"
+ rescue LoadError
+ require "net/http"
+ Gem::Net = Net
+ end
end
end
diff --git a/lib/bundler/vendored_securerandom.rb b/lib/bundler/vendored_securerandom.rb
new file mode 100644
index 0000000000..6a704dbd40
--- /dev/null
+++ b/lib/bundler/vendored_securerandom.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+# Use RubyGems vendored copy when available. Otherwise fallback to Bundler
+# vendored copy. The vendored copy in Bundler can be removed once support for
+# RubyGems 3.5.18 is dropped.
+
+begin
+ require "rubygems/vendored_securerandom"
+rescue LoadError
+ require_relative "vendor/securerandom/lib/securerandom"
+ Gem::SecureRandom = Bundler::SecureRandom
+end
diff --git a/lib/bundler/version.rb b/lib/bundler/version.rb
index f2f6236cda..ca7bb0719a 100644
--- a/lib/bundler/version.rb
+++ b/lib/bundler/version.rb
@@ -1,13 +1,21 @@
# frozen_string_literal: false
module Bundler
- VERSION = "2.6.0.dev".freeze
+ VERSION = "4.1.0.dev".freeze
def self.bundler_major_version
- @bundler_major_version ||= VERSION.split(".").first.to_i
+ @bundler_major_version ||= gem_version.segments.first
end
def self.gem_version
@gem_version ||= Gem::Version.create(VERSION)
end
+
+ def self.verbose_version
+ @verbose_version ||= "#{VERSION}#{simulated_version ? " (simulating Bundler #{simulated_version})" : ""}"
+ end
+
+ def self.simulated_version
+ @simulated_version ||= Bundler.settings[:simulate_version]
+ end
end
diff --git a/lib/bundler/vlad.rb b/lib/bundler/vlad.rb
index 6179d0e4eb..c3a3d949a6 100644
--- a/lib/bundler/vlad.rb
+++ b/lib/bundler/vlad.rb
@@ -1,17 +1,4 @@
# frozen_string_literal: true
require_relative "shared_helpers"
-Bundler::SharedHelpers.major_deprecation 2,
- "The Bundler task for Vlad"
-
-# Vlad task for Bundler.
-#
-# Add "require 'bundler/vlad'" in your Vlad deploy.rb, and
-# include the vlad:bundle:install task in your vlad:deploy task.
-require_relative "deployment"
-
-include Rake::DSL if defined? Rake::DSL
-
-namespace :vlad do
- Bundler::Deployment.define_task(Rake::RemoteTask, :remote_task, roles: :app)
-end
+Bundler::SharedHelpers.feature_removed! "The Bundler task for Vlad"
diff --git a/lib/bundler/worker.rb b/lib/bundler/worker.rb
index 3ebd6f01db..7137484cc6 100644
--- a/lib/bundler/worker.rb
+++ b/lib/bundler/worker.rb
@@ -88,7 +88,7 @@ module Bundler
@threads = Array.new(@size) do |i|
Thread.start { process_queue(i) }.tap do |thread|
- thread.name = "#{name} Worker ##{i}" if thread.respond_to?(:name=)
+ thread.name = "#{name} Worker ##{i}"
end
rescue ThreadError => e
creation_errors << e
diff --git a/lib/bundler/yaml_serializer.rb b/lib/bundler/yaml_serializer.rb
index 42e6aaf89d..ab1eb6dbcf 100644
--- a/lib/bundler/yaml_serializer.rb
+++ b/lib/bundler/yaml_serializer.rb
@@ -41,7 +41,7 @@ module Bundler
HASH_REGEX = /
^
([ ]*) # indentations
- (.+) # key
+ ([^#]+) # key excludes comment char '#'
(?::(?=(?:\s|$))) # : (without the lookahead the #key includes this when : is present in value)
[ ]?
(['"]?) # optional opening quote
@@ -60,7 +60,6 @@ module Bundler
indent, key, quote, val = match.captures
val = strip_comment(val)
- convert_to_backward_compatible_key!(key)
depth = indent.size / 2
if quote.empty? && val.empty?
new_hash = {}
@@ -92,14 +91,8 @@ module Bundler
end
end
- # for settings' keys
- def convert_to_backward_compatible_key!(key)
- key << "/" if /https?:/i.match?(key) && !%r{/\Z}.match?(key)
- key.gsub!(".", "__")
- end
-
class << self
- private :dump_hash, :convert_to_backward_compatible_key!
+ private :dump_hash
end
end
end
diff --git a/lib/cgi.rb b/lib/cgi.rb
index 7af85e7fc8..bb306d2e06 100644
--- a/lib/cgi.rb
+++ b/lib/cgi.rb
@@ -1,297 +1,7 @@
# frozen_string_literal: true
-#
-# cgi.rb - cgi support library
-#
-# Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
-#
-# Copyright (C) 2000 Information-technology Promotion Agency, Japan
-#
-# Author: Wakou Aoyama <wakou@ruby-lang.org>
-#
-# Documentation: Wakou Aoyama (RDoc'd and embellished by William Webber)
-#
-# == Overview
-#
-# The Common Gateway Interface (CGI) is a simple protocol for passing an HTTP
-# request from a web server to a standalone program, and returning the output
-# to the web browser. Basically, a CGI program is called with the parameters
-# of the request passed in either in the environment (GET) or via $stdin
-# (POST), and everything it prints to $stdout is returned to the client.
-#
-# This file holds the CGI class. This class provides functionality for
-# retrieving HTTP request parameters, managing cookies, and generating HTML
-# output.
-#
-# The file CGI::Session provides session management functionality; see that
-# class for more details.
-#
-# See http://www.w3.org/CGI/ for more information on the CGI protocol.
-#
-# == Introduction
-#
-# CGI is a large class, providing several categories of methods, many of which
-# are mixed in from other modules. Some of the documentation is in this class,
-# some in the modules CGI::QueryExtension and CGI::HtmlExtension. See
-# CGI::Cookie for specific information on handling cookies, and cgi/session.rb
-# (CGI::Session) for information on sessions.
-#
-# For queries, CGI provides methods to get at environmental variables,
-# parameters, cookies, and multipart request data. For responses, CGI provides
-# methods for writing output and generating HTML.
-#
-# Read on for more details. Examples are provided at the bottom.
-#
-# == Queries
-#
-# The CGI class dynamically mixes in parameter and cookie-parsing
-# functionality, environmental variable access, and support for
-# parsing multipart requests (including uploaded files) from the
-# CGI::QueryExtension module.
-#
-# === Environmental Variables
-#
-# The standard CGI environmental variables are available as read-only
-# attributes of a CGI object. The following is a list of these variables:
-#
-#
-# AUTH_TYPE HTTP_HOST REMOTE_IDENT
-# CONTENT_LENGTH HTTP_NEGOTIATE REMOTE_USER
-# CONTENT_TYPE HTTP_PRAGMA REQUEST_METHOD
-# GATEWAY_INTERFACE HTTP_REFERER SCRIPT_NAME
-# HTTP_ACCEPT HTTP_USER_AGENT SERVER_NAME
-# HTTP_ACCEPT_CHARSET PATH_INFO SERVER_PORT
-# HTTP_ACCEPT_ENCODING PATH_TRANSLATED SERVER_PROTOCOL
-# HTTP_ACCEPT_LANGUAGE QUERY_STRING SERVER_SOFTWARE
-# HTTP_CACHE_CONTROL REMOTE_ADDR
-# HTTP_FROM REMOTE_HOST
-#
-#
-# For each of these variables, there is a corresponding attribute with the
-# same name, except all lower case and without a preceding HTTP_.
-# +content_length+ and +server_port+ are integers; the rest are strings.
-#
-# === Parameters
-#
-# The method #params() returns a hash of all parameters in the request as
-# name/value-list pairs, where the value-list is an Array of one or more
-# values. The CGI object itself also behaves as a hash of parameter names
-# to values, but only returns a single value (as a String) for each
-# parameter name.
-#
-# For instance, suppose the request contains the parameter
-# "favourite_colours" with the multiple values "blue" and "green". The
-# following behavior would occur:
-#
-# cgi.params["favourite_colours"] # => ["blue", "green"]
-# cgi["favourite_colours"] # => "blue"
-#
-# If a parameter does not exist, the former method will return an empty
-# array, the latter an empty string. The simplest way to test for existence
-# of a parameter is by the #has_key? method.
-#
-# === Cookies
-#
-# HTTP Cookies are automatically parsed from the request. They are available
-# from the #cookies() accessor, which returns a hash from cookie name to
-# CGI::Cookie object.
-#
-# === Multipart requests
-#
-# If a request's method is POST and its content type is multipart/form-data,
-# then it may contain uploaded files. These are stored by the QueryExtension
-# module in the parameters of the request. The parameter name is the name
-# attribute of the file input field, as usual. However, the value is not
-# a string, but an IO object, either an IOString for small files, or a
-# Tempfile for larger ones. This object also has the additional singleton
-# methods:
-#
-# #local_path():: the path of the uploaded file on the local filesystem
-# #original_filename():: the name of the file on the client computer
-# #content_type():: the content type of the file
-#
-# == Responses
-#
-# The CGI class provides methods for sending header and content output to
-# the HTTP client, and mixes in methods for programmatic HTML generation
-# from CGI::HtmlExtension and CGI::TagMaker modules. The precise version of HTML
-# to use for HTML generation is specified at object creation time.
-#
-# === Writing output
-#
-# The simplest way to send output to the HTTP client is using the #out() method.
-# This takes the HTTP headers as a hash parameter, and the body content
-# via a block. The headers can be generated as a string using the #http_header()
-# method. The output stream can be written directly to using the #print()
-# method.
-#
-# === Generating HTML
-#
-# Each HTML element has a corresponding method for generating that
-# element as a String. The name of this method is the same as that
-# of the element, all lowercase. The attributes of the element are
-# passed in as a hash, and the body as a no-argument block that evaluates
-# to a String. The HTML generation module knows which elements are
-# always empty, and silently drops any passed-in body. It also knows
-# which elements require matching closing tags and which don't. However,
-# it does not know what attributes are legal for which elements.
-#
-# There are also some additional HTML generation methods mixed in from
-# the CGI::HtmlExtension module. These include individual methods for the
-# different types of form inputs, and methods for elements that commonly
-# take particular attributes where the attributes can be directly specified
-# as arguments, rather than via a hash.
-#
-# === Utility HTML escape and other methods like a function.
-#
-# There are some utility tool defined in cgi/util.rb .
-# And when include, you can use utility methods like a function.
-#
-# == Examples of use
-#
-# === Get form values
-#
-# require "cgi"
-# cgi = CGI.new
-# value = cgi['field_name'] # <== value string for 'field_name'
-# # if not 'field_name' included, then return "".
-# fields = cgi.keys # <== array of field names
-#
-# # returns true if form has 'field_name'
-# cgi.has_key?('field_name')
-# cgi.has_key?('field_name')
-# cgi.include?('field_name')
-#
-# CAUTION! <code>cgi['field_name']</code> returned an Array with the old
-# cgi.rb(included in Ruby 1.6)
-#
-# === Get form values as hash
-#
-# require "cgi"
-# cgi = CGI.new
-# params = cgi.params
-#
-# cgi.params is a hash.
-#
-# cgi.params['new_field_name'] = ["value"] # add new param
-# cgi.params['field_name'] = ["new_value"] # change value
-# cgi.params.delete('field_name') # delete param
-# cgi.params.clear # delete all params
-#
-#
-# === Save form values to file
-#
-# require "pstore"
-# db = PStore.new("query.db")
-# db.transaction do
-# db["params"] = cgi.params
-# end
-#
-#
-# === Restore form values from file
-#
-# require "pstore"
-# db = PStore.new("query.db")
-# db.transaction do
-# cgi.params = db["params"]
-# end
-#
-#
-# === Get multipart form values
-#
-# require "cgi"
-# cgi = CGI.new
-# value = cgi['field_name'] # <== value string for 'field_name'
-# value.read # <== body of value
-# value.local_path # <== path to local file of value
-# value.original_filename # <== original filename of value
-# value.content_type # <== content_type of value
-#
-# and value has StringIO or Tempfile class methods.
-#
-# === Get cookie values
-#
-# require "cgi"
-# cgi = CGI.new
-# values = cgi.cookies['name'] # <== array of 'name'
-# # if not 'name' included, then return [].
-# names = cgi.cookies.keys # <== array of cookie names
-#
-# and cgi.cookies is a hash.
-#
-# === Get cookie objects
-#
-# require "cgi"
-# cgi = CGI.new
-# for name, cookie in cgi.cookies
-# cookie.expires = Time.now + 30
-# end
-# cgi.out("cookie" => cgi.cookies) {"string"}
-#
-# cgi.cookies # { "name1" => cookie1, "name2" => cookie2, ... }
-#
-# require "cgi"
-# cgi = CGI.new
-# cgi.cookies['name'].expires = Time.now + 30
-# cgi.out("cookie" => cgi.cookies['name']) {"string"}
-#
-# === Print http header and html string to $DEFAULT_OUTPUT ($>)
-#
-# require "cgi"
-# cgi = CGI.new("html4") # add HTML generation methods
-# cgi.out do
-# cgi.html do
-# cgi.head do
-# cgi.title { "TITLE" }
-# end +
-# cgi.body do
-# cgi.form("ACTION" => "uri") do
-# cgi.p do
-# cgi.textarea("get_text") +
-# cgi.br +
-# cgi.submit
-# end
-# end +
-# cgi.pre do
-# CGI.escapeHTML(
-# "params: #{cgi.params.inspect}\n" +
-# "cookies: #{cgi.cookies.inspect}\n" +
-# ENV.collect do |key, value|
-# "#{key} --> #{value}\n"
-# end.join("")
-# )
-# end
-# end
-# end
-# end
-#
-# # add HTML generation methods
-# CGI.new("html3") # html3.2
-# CGI.new("html4") # html4.01 (Strict)
-# CGI.new("html4Tr") # html4.01 Transitional
-# CGI.new("html4Fr") # html4.01 Frameset
-# CGI.new("html5") # html5
-#
-# === Some utility methods
-#
-# require 'cgi/util'
-# CGI.escapeHTML('Usage: foo "bar" <baz>')
-#
-#
-# === Some utility methods like a function
-#
-# require 'cgi/util'
-# include CGI::Util
-# escapeHTML('Usage: foo "bar" <baz>')
-# h('Usage: foo "bar" <baz>') # alias
-#
-#
-
-class CGI
- VERSION = "0.4.1"
-end
-
-require 'cgi/core'
-require 'cgi/cookie'
-require 'cgi/util'
-CGI.autoload(:HtmlExtension, 'cgi/html')
+require "cgi/escape"
+warn <<-WARNING, uplevel: Gem::BUNDLED_GEMS.uplevel if $VERBOSE
+CGI library is removed from Ruby 4.0. Please use cgi/escape instead for CGI.escape and CGI.unescape features.
+If you need to use the full features of CGI library, Please install cgi gem.
+WARNING
diff --git a/lib/cgi/cgi.gemspec b/lib/cgi/cgi.gemspec
deleted file mode 100644
index 381c55a5ca..0000000000
--- a/lib/cgi/cgi.gemspec
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-
-name = File.basename(__FILE__, ".gemspec")
-version = ["lib", Array.new(name.count("-")+1, "..").join("/")].find do |dir|
- break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
- /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
- end rescue nil
-end
-
-Gem::Specification.new do |spec|
- spec.name = name
- spec.version = version
- spec.authors = ["Yukihiro Matsumoto"]
- spec.email = ["matz@ruby-lang.org"]
-
- spec.summary = %q{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.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.executables = []
-
- spec.files = [
- "LICENSE.txt",
- "README.md",
- *Dir["lib{.rb,/**/*.rb}", "bin/*"] ]
-
- spec.require_paths = ["lib"]
-
- if Gem::Platform === spec.platform and spec.platform =~ 'java' or RUBY_ENGINE == 'jruby'
- spec.platform = 'java'
- spec.require_paths << "ext/java/org/jruby/ext/cgi/escape/lib"
- spec.files += Dir["ext/java/**/*.{rb}", "lib/cgi/escape.jar"]
- else
- spec.files += Dir["ext/cgi/**/*.{rb,c,h,sh}", "ext/cgi/escape/depend", "lib/cgi/escape.so"]
- spec.extensions = ["ext/cgi/escape/extconf.rb"]
- end
-end
diff --git a/lib/cgi/cookie.rb b/lib/cgi/cookie.rb
deleted file mode 100644
index 9498e2f9fa..0000000000
--- a/lib/cgi/cookie.rb
+++ /dev/null
@@ -1,209 +0,0 @@
-# frozen_string_literal: true
-require_relative 'util'
-class CGI
- # Class representing an HTTP cookie.
- #
- # In addition to its specific fields and methods, a Cookie instance
- # is a delegator to the array of its values.
- #
- # See RFC 2965.
- #
- # == Examples of use
- # cookie1 = CGI::Cookie.new("name", "value1", "value2", ...)
- # cookie1 = CGI::Cookie.new("name" => "name", "value" => "value")
- # cookie1 = CGI::Cookie.new('name' => 'name',
- # 'value' => ['value1', 'value2', ...],
- # 'path' => 'path', # optional
- # 'domain' => 'domain', # optional
- # 'expires' => Time.now, # optional
- # 'secure' => true, # optional
- # 'httponly' => true # optional
- # )
- #
- # cgi.out("cookie" => [cookie1, cookie2]) { "string" }
- #
- # name = cookie1.name
- # values = cookie1.value
- # path = cookie1.path
- # domain = cookie1.domain
- # expires = cookie1.expires
- # secure = cookie1.secure
- # httponly = cookie1.httponly
- #
- # cookie1.name = 'name'
- # cookie1.value = ['value1', 'value2', ...]
- # cookie1.path = 'path'
- # cookie1.domain = 'domain'
- # cookie1.expires = Time.now + 30
- # cookie1.secure = true
- # cookie1.httponly = true
- class Cookie < Array
- @@accept_charset="UTF-8" unless defined?(@@accept_charset)
-
- TOKEN_RE = %r"\A[[!-~]&&[^()<>@,;:\\\"/?=\[\]{}]]+\z"
- PATH_VALUE_RE = %r"\A[[ -~]&&[^;]]*\z"
- DOMAIN_VALUE_RE = %r"\A\.?(?<label>(?!-)[-A-Za-z0-9]+(?<!-))(?:\.\g<label>)*\z"
-
- # Create a new CGI::Cookie object.
- #
- # :call-seq:
- # Cookie.new(name_string,*value)
- # Cookie.new(options_hash)
- #
- # +name_string+::
- # The name of the cookie; in this form, there is no #domain or
- # #expiration. The #path is gleaned from the +SCRIPT_NAME+ environment
- # variable, and #secure is false.
- # <tt>*value</tt>::
- # value or list of values of the cookie
- # +options_hash+::
- # A Hash of options to initialize this Cookie. Possible options are:
- #
- # name:: the name of the cookie. Required.
- # value:: the cookie's value or list of values.
- # path:: the path for which this cookie applies. Defaults to
- # the value of the +SCRIPT_NAME+ environment variable.
- # domain:: the domain for which this cookie applies.
- # expires:: the time at which this cookie expires, as a +Time+ object.
- # secure:: whether this cookie is a secure cookie or not (default to
- # false). Secure cookies are only transmitted to HTTPS
- # servers.
- # httponly:: whether this cookie is a HttpOnly cookie or not (default to
- # false). HttpOnly cookies are not available to javascript.
- #
- # These keywords correspond to attributes of the cookie object.
- def initialize(name = "", *value)
- @domain = nil
- @expires = nil
- if name.kind_of?(String)
- self.name = name
- self.path = (%r|\A(.*/)| =~ ENV["SCRIPT_NAME"] ? $1 : "")
- @secure = false
- @httponly = false
- return super(value)
- end
-
- options = name
- unless options.has_key?("name")
- raise ArgumentError, "`name' required"
- end
-
- self.name = options["name"]
- value = Array(options["value"])
- # simple support for IE
- self.path = options["path"] || (%r|\A(.*/)| =~ ENV["SCRIPT_NAME"] ? $1 : "")
- self.domain = options["domain"]
- @expires = options["expires"]
- @secure = options["secure"] == true
- @httponly = options["httponly"] == true
-
- super(value)
- end
-
- # Name of this cookie, as a +String+
- attr_reader :name
- # Set name of this cookie
- def name=(str)
- if str and !TOKEN_RE.match?(str)
- raise ArgumentError, "invalid name: #{str.dump}"
- end
- @name = str
- end
-
- # Path for which this cookie applies, as a +String+
- attr_reader :path
- # Set path for which this cookie applies
- def path=(str)
- if str and !PATH_VALUE_RE.match?(str)
- raise ArgumentError, "invalid path: #{str.dump}"
- end
- @path = str
- end
-
- # Domain for which this cookie applies, as a +String+
- attr_reader :domain
- # Set domain for which this cookie applies
- def domain=(str)
- if str and ((str = str.b).bytesize > 255 or !DOMAIN_VALUE_RE.match?(str))
- raise ArgumentError, "invalid domain: #{str.dump}"
- end
- @domain = str
- end
-
- # Time at which this cookie expires, as a +Time+
- attr_accessor :expires
- # True if this cookie is secure; false otherwise
- attr_reader :secure
- # True if this cookie is httponly; false otherwise
- attr_reader :httponly
-
- # Returns the value or list of values for this cookie.
- def value
- self
- end
-
- # Replaces the value of this cookie with a new value or list of values.
- def value=(val)
- replace(Array(val))
- end
-
- # Set whether the Cookie is a secure cookie or not.
- #
- # +val+ must be a boolean.
- def secure=(val)
- @secure = val if val == true or val == false
- @secure
- end
-
- # Set whether the Cookie is a httponly cookie or not.
- #
- # +val+ must be a boolean.
- def httponly=(val)
- @httponly = !!val
- end
-
- # Convert the Cookie to its string representation.
- def to_s
- val = collect{|v| CGI.escape(v) }.join("&")
- buf = "#{@name}=#{val}".dup
- buf << "; domain=#{@domain}" if @domain
- buf << "; path=#{@path}" if @path
- buf << "; expires=#{CGI.rfc1123_date(@expires)}" if @expires
- buf << "; secure" if @secure
- buf << "; HttpOnly" if @httponly
- buf
- end
-
- # Parse a raw cookie string into a hash of cookie-name=>Cookie
- # pairs.
- #
- # cookies = CGI::Cookie.parse("raw_cookie_string")
- # # { "name1" => cookie1, "name2" => cookie2, ... }
- #
- def self.parse(raw_cookie)
- cookies = Hash.new([])
- return cookies unless raw_cookie
-
- raw_cookie.split(/;\s?/).each do |pairs|
- name, values = pairs.split('=',2)
- next unless name and values
- values ||= ""
- values = values.split('&').collect{|v| CGI.unescape(v,@@accept_charset) }
- if cookies.has_key?(name)
- values = cookies[name].value + values
- end
- cookies[name] = Cookie.new(name, *values)
- end
-
- cookies
- end
-
- # A summary of cookie string.
- def inspect
- "#<CGI::Cookie: #{self.to_s.inspect}>"
- end
-
- end # class Cookie
-end
-
-
diff --git a/lib/cgi/core.rb b/lib/cgi/core.rb
deleted file mode 100644
index 62e606837a..0000000000
--- a/lib/cgi/core.rb
+++ /dev/null
@@ -1,900 +0,0 @@
-# frozen_string_literal: true
-#--
-# Methods for generating HTML, parsing CGI-related parameters, and
-# generating HTTP responses.
-#++
-class CGI
- unless const_defined?(:Util)
- module Util
- @@accept_charset = "UTF-8" # :nodoc:
- end
- include Util
- extend Util
- end
-
- $CGI_ENV = ENV # for FCGI support
-
- # String for carriage return
- CR = "\015"
-
- # String for linefeed
- LF = "\012"
-
- # Standard internet newline sequence
- EOL = CR + LF
-
- REVISION = '$Id$' #:nodoc:
-
- # Whether processing will be required in binary vs text
- NEEDS_BINMODE = File::BINARY != 0
-
- # Path separators in different environments.
- PATH_SEPARATOR = {'UNIX'=>'/', 'WINDOWS'=>'\\', 'MACINTOSH'=>':'}
-
- # HTTP status codes.
- HTTP_STATUS = {
- "OK" => "200 OK",
- "PARTIAL_CONTENT" => "206 Partial Content",
- "MULTIPLE_CHOICES" => "300 Multiple Choices",
- "MOVED" => "301 Moved Permanently",
- "REDIRECT" => "302 Found",
- "NOT_MODIFIED" => "304 Not Modified",
- "BAD_REQUEST" => "400 Bad Request",
- "AUTH_REQUIRED" => "401 Authorization Required",
- "FORBIDDEN" => "403 Forbidden",
- "NOT_FOUND" => "404 Not Found",
- "METHOD_NOT_ALLOWED" => "405 Method Not Allowed",
- "NOT_ACCEPTABLE" => "406 Not Acceptable",
- "LENGTH_REQUIRED" => "411 Length Required",
- "PRECONDITION_FAILED" => "412 Precondition Failed",
- "SERVER_ERROR" => "500 Internal Server Error",
- "NOT_IMPLEMENTED" => "501 Method Not Implemented",
- "BAD_GATEWAY" => "502 Bad Gateway",
- "VARIANT_ALSO_VARIES" => "506 Variant Also Negotiates"
- }
-
- # :startdoc:
-
- # Synonym for ENV.
- def env_table
- ENV
- end
-
- # Synonym for $stdin.
- def stdinput
- $stdin
- end
-
- # Synonym for $stdout.
- def stdoutput
- $stdout
- end
-
- private :env_table, :stdinput, :stdoutput
-
- # Create an HTTP header block as a string.
- #
- # :call-seq:
- # http_header(content_type_string="text/html")
- # http_header(headers_hash)
- #
- # Includes the empty line that ends the header block.
- #
- # +content_type_string+::
- # If this form is used, this string is the <tt>Content-Type</tt>
- # +headers_hash+::
- # A Hash of header values. The following header keys are recognized:
- #
- # type:: The Content-Type header. Defaults to "text/html"
- # charset:: The charset of the body, appended to the Content-Type header.
- # nph:: A boolean value. If true, prepend protocol string and status
- # code, and date; and sets default values for "server" and
- # "connection" if not explicitly set.
- # status::
- # The HTTP status code as a String, returned as the Status header. The
- # values are:
- #
- # OK:: 200 OK
- # PARTIAL_CONTENT:: 206 Partial Content
- # MULTIPLE_CHOICES:: 300 Multiple Choices
- # MOVED:: 301 Moved Permanently
- # REDIRECT:: 302 Found
- # NOT_MODIFIED:: 304 Not Modified
- # BAD_REQUEST:: 400 Bad Request
- # AUTH_REQUIRED:: 401 Authorization Required
- # FORBIDDEN:: 403 Forbidden
- # NOT_FOUND:: 404 Not Found
- # METHOD_NOT_ALLOWED:: 405 Method Not Allowed
- # NOT_ACCEPTABLE:: 406 Not Acceptable
- # LENGTH_REQUIRED:: 411 Length Required
- # PRECONDITION_FAILED:: 412 Precondition Failed
- # SERVER_ERROR:: 500 Internal Server Error
- # NOT_IMPLEMENTED:: 501 Method Not Implemented
- # BAD_GATEWAY:: 502 Bad Gateway
- # VARIANT_ALSO_VARIES:: 506 Variant Also Negotiates
- #
- # server:: The server software, returned as the Server header.
- # connection:: The connection type, returned as the Connection header (for
- # instance, "close".
- # length:: The length of the content that will be sent, returned as the
- # Content-Length header.
- # language:: The language of the content, returned as the Content-Language
- # header.
- # expires:: The time on which the current content expires, as a +Time+
- # object, returned as the Expires header.
- # cookie::
- # A cookie or cookies, returned as one or more Set-Cookie headers. The
- # value can be the literal string of the cookie; a CGI::Cookie object;
- # an Array of literal cookie strings or Cookie objects; or a hash all of
- # whose values are literal cookie strings or Cookie objects.
- #
- # These cookies are in addition to the cookies held in the
- # @output_cookies field.
- #
- # Other headers can also be set; they are appended as key: value.
- #
- # Examples:
- #
- # http_header
- # # Content-Type: text/html
- #
- # http_header("text/plain")
- # # Content-Type: text/plain
- #
- # http_header("nph" => true,
- # "status" => "OK", # == "200 OK"
- # # "status" => "200 GOOD",
- # "server" => ENV['SERVER_SOFTWARE'],
- # "connection" => "close",
- # "type" => "text/html",
- # "charset" => "iso-2022-jp",
- # # Content-Type: text/html; charset=iso-2022-jp
- # "length" => 103,
- # "language" => "ja",
- # "expires" => Time.now + 30,
- # "cookie" => [cookie1, cookie2],
- # "my_header1" => "my_value",
- # "my_header2" => "my_value")
- #
- # This method does not perform charset conversion.
- def http_header(options='text/html')
- if options.is_a?(String)
- content_type = options
- buf = _header_for_string(content_type)
- elsif options.is_a?(Hash)
- if options.size == 1 && options.has_key?('type')
- content_type = options['type']
- buf = _header_for_string(content_type)
- else
- buf = _header_for_hash(options.dup)
- end
- else
- raise ArgumentError.new("expected String or Hash but got #{options.class}")
- end
- if defined?(MOD_RUBY)
- _header_for_modruby(buf)
- return ''
- else
- buf << EOL # empty line of separator
- return buf
- end
- end # http_header()
-
- # This method is an alias for #http_header, when HTML5 tag maker is inactive.
- #
- # NOTE: use #http_header to create HTTP header blocks, this alias is only
- # provided for backwards compatibility.
- #
- # Using #header with the HTML5 tag maker will create a <header> element.
- alias :header :http_header
-
- def _no_crlf_check(str)
- if str
- str = str.to_s
- raise "A HTTP status or header field must not include CR and LF" if str =~ /[\r\n]/
- str
- else
- nil
- end
- end
- private :_no_crlf_check
-
- def _header_for_string(content_type) #:nodoc:
- buf = ''.dup
- if nph?()
- buf << "#{_no_crlf_check($CGI_ENV['SERVER_PROTOCOL']) || 'HTTP/1.0'} 200 OK#{EOL}"
- buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}"
- buf << "Server: #{_no_crlf_check($CGI_ENV['SERVER_SOFTWARE'])}#{EOL}"
- buf << "Connection: close#{EOL}"
- end
- buf << "Content-Type: #{_no_crlf_check(content_type)}#{EOL}"
- if @output_cookies
- @output_cookies.each {|cookie| buf << "Set-Cookie: #{_no_crlf_check(cookie)}#{EOL}" }
- end
- return buf
- end # _header_for_string
- private :_header_for_string
-
- def _header_for_hash(options) #:nodoc:
- buf = ''.dup
- ## add charset to option['type']
- options['type'] ||= 'text/html'
- charset = options.delete('charset')
- options['type'] += "; charset=#{charset}" if charset
- ## NPH
- options.delete('nph') if defined?(MOD_RUBY)
- if options.delete('nph') || nph?()
- protocol = _no_crlf_check($CGI_ENV['SERVER_PROTOCOL']) || 'HTTP/1.0'
- status = options.delete('status')
- status = HTTP_STATUS[status] || _no_crlf_check(status) || '200 OK'
- buf << "#{protocol} #{status}#{EOL}"
- buf << "Date: #{CGI.rfc1123_date(Time.now)}#{EOL}"
- options['server'] ||= $CGI_ENV['SERVER_SOFTWARE'] || ''
- options['connection'] ||= 'close'
- end
- ## common headers
- status = options.delete('status')
- buf << "Status: #{HTTP_STATUS[status] || _no_crlf_check(status)}#{EOL}" if status
- server = options.delete('server')
- buf << "Server: #{_no_crlf_check(server)}#{EOL}" if server
- connection = options.delete('connection')
- buf << "Connection: #{_no_crlf_check(connection)}#{EOL}" if connection
- type = options.delete('type')
- buf << "Content-Type: #{_no_crlf_check(type)}#{EOL}" #if type
- length = options.delete('length')
- buf << "Content-Length: #{_no_crlf_check(length)}#{EOL}" if length
- language = options.delete('language')
- buf << "Content-Language: #{_no_crlf_check(language)}#{EOL}" if language
- expires = options.delete('expires')
- buf << "Expires: #{CGI.rfc1123_date(expires)}#{EOL}" if expires
- ## cookie
- if cookie = options.delete('cookie')
- case cookie
- when String, Cookie
- buf << "Set-Cookie: #{_no_crlf_check(cookie)}#{EOL}"
- when Array
- arr = cookie
- arr.each {|c| buf << "Set-Cookie: #{_no_crlf_check(c)}#{EOL}" }
- when Hash
- hash = cookie
- hash.each_value {|c| buf << "Set-Cookie: #{_no_crlf_check(c)}#{EOL}" }
- end
- end
- if @output_cookies
- @output_cookies.each {|c| buf << "Set-Cookie: #{_no_crlf_check(c)}#{EOL}" }
- end
- ## other headers
- options.each do |key, value|
- buf << "#{_no_crlf_check(key)}: #{_no_crlf_check(value)}#{EOL}"
- end
- return buf
- end # _header_for_hash
- private :_header_for_hash
-
- def nph? #:nodoc:
- return /IIS\/(\d+)/ =~ $CGI_ENV['SERVER_SOFTWARE'] && $1.to_i < 5
- end
-
- def _header_for_modruby(buf) #:nodoc:
- request = Apache::request
- buf.scan(/([^:]+): (.+)#{EOL}/o) do |name, value|
- $stderr.printf("name:%s value:%s\n", name, value) if $DEBUG
- case name
- when 'Set-Cookie'
- request.headers_out.add(name, value)
- when /^status$/i
- request.status_line = value
- request.status = value.to_i
- when /^content-type$/i
- request.content_type = value
- when /^content-encoding$/i
- request.content_encoding = value
- when /^location$/i
- request.status = 302 if request.status == 200
- request.headers_out[name] = value
- else
- request.headers_out[name] = value
- end
- end
- request.send_http_header
- return ''
- end
- private :_header_for_modruby
-
- # Print an HTTP header and body to $DEFAULT_OUTPUT ($>)
- #
- # :call-seq:
- # cgi.out(content_type_string='text/html')
- # cgi.out(headers_hash)
- #
- # +content_type_string+::
- # If a string is passed, it is assumed to be the content type.
- # +headers_hash+::
- # This is a Hash of headers, similar to that used by #http_header.
- # +block+::
- # A block is required and should evaluate to the body of the response.
- #
- # <tt>Content-Length</tt> is automatically calculated from the size of
- # the String returned by the content block.
- #
- # If <tt>ENV['REQUEST_METHOD'] == "HEAD"</tt>, then only the header
- # is output (the content block is still required, but it is ignored).
- #
- # If the charset is "iso-2022-jp" or "euc-jp" or "shift_jis" then the
- # content is converted to this charset, and the language is set to "ja".
- #
- # Example:
- #
- # cgi = CGI.new
- # cgi.out{ "string" }
- # # Content-Type: text/html
- # # Content-Length: 6
- # #
- # # string
- #
- # cgi.out("text/plain") { "string" }
- # # Content-Type: text/plain
- # # Content-Length: 6
- # #
- # # string
- #
- # cgi.out("nph" => true,
- # "status" => "OK", # == "200 OK"
- # "server" => ENV['SERVER_SOFTWARE'],
- # "connection" => "close",
- # "type" => "text/html",
- # "charset" => "iso-2022-jp",
- # # Content-Type: text/html; charset=iso-2022-jp
- # "language" => "ja",
- # "expires" => Time.now + (3600 * 24 * 30),
- # "cookie" => [cookie1, cookie2],
- # "my_header1" => "my_value",
- # "my_header2" => "my_value") { "string" }
- # # HTTP/1.1 200 OK
- # # Date: Sun, 15 May 2011 17:35:54 GMT
- # # Server: Apache 2.2.0
- # # Connection: close
- # # Content-Type: text/html; charset=iso-2022-jp
- # # Content-Length: 6
- # # Content-Language: ja
- # # Expires: Tue, 14 Jun 2011 17:35:54 GMT
- # # Set-Cookie: foo
- # # Set-Cookie: bar
- # # my_header1: my_value
- # # my_header2: my_value
- # #
- # # string
- def out(options = "text/html") # :yield:
-
- options = { "type" => options } if options.kind_of?(String)
- content = yield
- options["length"] = content.bytesize.to_s
- output = stdoutput
- output.binmode if defined? output.binmode
- output.print http_header(options)
- output.print content unless "HEAD" == env_table['REQUEST_METHOD']
- end
-
-
- # Print an argument or list of arguments to the default output stream
- #
- # cgi = CGI.new
- # cgi.print # default: cgi.print == $DEFAULT_OUTPUT.print
- def print(*options)
- stdoutput.print(*options)
- end
-
- # Parse an HTTP query string into a hash of key=>value pairs.
- #
- # params = CGI.parse("query_string")
- # # {"name1" => ["value1", "value2", ...],
- # # "name2" => ["value1", "value2", ...], ... }
- #
- def self.parse(query)
- params = {}
- query.split(/[&;]/).each do |pairs|
- key, value = pairs.split('=',2).collect{|v| CGI.unescape(v) }
-
- next unless key
-
- params[key] ||= []
- params[key].push(value) if value
- end
-
- params.default=[].freeze
- params
- end
-
- # Maximum content length of post data
- ##MAX_CONTENT_LENGTH = 2 * 1024 * 1024
-
- # Maximum number of request parameters when multipart
- MAX_MULTIPART_COUNT = 128
-
- # Mixin module that provides the following:
- #
- # 1. Access to the CGI environment variables as methods. See
- # documentation to the CGI class for a list of these variables. The
- # methods are exposed by removing the leading +HTTP_+ (if it exists) and
- # downcasing the name. For example, +auth_type+ will return the
- # environment variable +AUTH_TYPE+, and +accept+ will return the value
- # for +HTTP_ACCEPT+.
- #
- # 2. Access to cookies, including the cookies attribute.
- #
- # 3. Access to parameters, including the params attribute, and overloading
- # #[] to perform parameter value lookup by key.
- #
- # 4. The initialize_query method, for initializing the above
- # mechanisms, handling multipart forms, and allowing the
- # class to be used in "offline" mode.
- #
- module QueryExtension
-
- %w[ CONTENT_LENGTH SERVER_PORT ].each do |env|
- define_method(env.delete_prefix('HTTP_').downcase) do
- (val = env_table[env]) && Integer(val)
- end
- end
-
- %w[ AUTH_TYPE CONTENT_TYPE GATEWAY_INTERFACE PATH_INFO
- PATH_TRANSLATED QUERY_STRING REMOTE_ADDR REMOTE_HOST
- REMOTE_IDENT REMOTE_USER REQUEST_METHOD SCRIPT_NAME
- SERVER_NAME SERVER_PROTOCOL SERVER_SOFTWARE
-
- HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING
- HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_FROM HTTP_HOST
- HTTP_NEGOTIATE HTTP_PRAGMA HTTP_REFERER HTTP_USER_AGENT ].each do |env|
- define_method(env.delete_prefix('HTTP_').downcase) do
- env_table[env]
- end
- end
-
- # Get the raw cookies as a string.
- def raw_cookie
- env_table["HTTP_COOKIE"]
- end
-
- # Get the raw RFC2965 cookies as a string.
- def raw_cookie2
- env_table["HTTP_COOKIE2"]
- end
-
- # Get the cookies as a hash of cookie-name=>Cookie pairs.
- attr_accessor :cookies
-
- # Get the parameters as a hash of name=>values pairs, where
- # values is an Array.
- attr_reader :params
-
- # Get the uploaded files as a hash of name=>values pairs
- attr_reader :files
-
- # Set all the parameters.
- def params=(hash)
- @params.clear
- @params.update(hash)
- end
-
- ##
- # Parses multipart form elements according to
- # http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2
- #
- # Returns a hash of multipart form parameters with bodies of type StringIO or
- # Tempfile depending on whether the multipart form element exceeds 10 KB
- #
- # params[name => body]
- #
- def read_multipart(boundary, content_length)
- ## read first boundary
- stdin = stdinput
- first_line = "--#{boundary}#{EOL}"
- content_length -= first_line.bytesize
- status = stdin.read(first_line.bytesize)
- raise EOFError.new("no content body") unless status
- raise EOFError.new("bad content body") unless first_line == status
- ## parse and set params
- params = {}
- @files = {}
- boundary_rexp = /--#{Regexp.quote(boundary)}(#{EOL}|--)/
- boundary_size = "#{EOL}--#{boundary}#{EOL}".bytesize
- buf = ''.dup
- bufsize = 10 * 1024
- max_count = MAX_MULTIPART_COUNT
- n = 0
- tempfiles = []
- while true
- (n += 1) < max_count or raise StandardError.new("too many parameters.")
- ## create body (StringIO or Tempfile)
- body = create_body(bufsize < content_length)
- tempfiles << body if defined?(Tempfile) && body.kind_of?(Tempfile)
- class << body
- if method_defined?(:path)
- alias local_path path
- else
- def local_path
- nil
- end
- end
- attr_reader :original_filename, :content_type
- end
- ## find head and boundary
- head = nil
- separator = EOL * 2
- until head && matched = boundary_rexp.match(buf)
- if !head && pos = buf.index(separator)
- len = pos + EOL.bytesize
- head = buf[0, len]
- buf = buf[(pos+separator.bytesize)..-1]
- else
- if head && buf.size > boundary_size
- len = buf.size - boundary_size
- body.print(buf[0, len])
- buf[0, len] = ''
- end
- c = stdin.read(bufsize < content_length ? bufsize : content_length)
- raise EOFError.new("bad content body") if c.nil? || c.empty?
- buf << c
- content_length -= c.bytesize
- end
- end
- ## read to end of boundary
- m = matched
- len = m.begin(0)
- s = buf[0, len]
- if s =~ /(\r?\n)\z/
- s = buf[0, len - $1.bytesize]
- end
- body.print(s)
- buf = buf[m.end(0)..-1]
- boundary_end = m[1]
- content_length = -1 if boundary_end == '--'
- ## reset file cursor position
- body.rewind
- ## original filename
- /Content-Disposition:.* filename=(?:"(.*?)"|([^;\r\n]*))/i.match(head)
- filename = $1 || $2 || ''.dup
- filename = CGI.unescape(filename) if unescape_filename?()
- body.instance_variable_set(:@original_filename, filename)
- ## content type
- /Content-Type: (.*)/i.match(head)
- (content_type = $1 || ''.dup).chomp!
- body.instance_variable_set(:@content_type, content_type)
- ## query parameter name
- /Content-Disposition:.* name=(?:"(.*?)"|([^;\r\n]*))/i.match(head)
- name = $1 || $2 || ''
- if body.original_filename.empty?
- value=body.read.dup.force_encoding(@accept_charset)
- body.close! if defined?(Tempfile) && body.kind_of?(Tempfile)
- (params[name] ||= []) << value
- unless value.valid_encoding?
- if @accept_charset_error_block
- @accept_charset_error_block.call(name,value)
- else
- raise InvalidEncoding,"Accept-Charset encoding error"
- end
- end
- class << params[name].last;self;end.class_eval do
- define_method(:read){self}
- define_method(:original_filename){""}
- define_method(:content_type){""}
- end
- else
- (params[name] ||= []) << body
- @files[name]=body
- end
- ## break loop
- break if content_length == -1
- end
- raise EOFError, "bad boundary end of body part" unless boundary_end =~ /--/
- params.default = []
- params
- rescue Exception
- if tempfiles
- tempfiles.each {|t|
- if t.path
- t.close!
- end
- }
- end
- raise
- end # read_multipart
- private :read_multipart
- def create_body(is_large) #:nodoc:
- if is_large
- require 'tempfile'
- body = Tempfile.new('CGI', encoding: Encoding::ASCII_8BIT)
- else
- begin
- require 'stringio'
- body = StringIO.new("".b)
- rescue LoadError
- require 'tempfile'
- body = Tempfile.new('CGI', encoding: Encoding::ASCII_8BIT)
- end
- end
- body.binmode if defined? body.binmode
- return body
- end
- def unescape_filename? #:nodoc:
- user_agent = $CGI_ENV['HTTP_USER_AGENT']
- return false unless user_agent
- return /Mac/i.match(user_agent) && /Mozilla/i.match(user_agent) && !/MSIE/i.match(user_agent)
- end
-
- # offline mode. read name=value pairs on standard input.
- def read_from_cmdline
- require "shellwords"
-
- string = unless ARGV.empty?
- ARGV.join(' ')
- else
- if STDIN.tty?
- STDERR.print(
- %|(offline mode: enter name=value pairs on standard input)\n|
- )
- end
- array = readlines rescue nil
- if not array.nil?
- array.join(' ').gsub(/\n/n, '')
- else
- ""
- end
- end.gsub(/\\=/n, '%3D').gsub(/\\&/n, '%26')
-
- words = Shellwords.shellwords(string)
-
- if words.find{|x| /=/n.match(x) }
- words.join('&')
- else
- words.join('+')
- end
- end
- private :read_from_cmdline
-
- # A wrapper class to use a StringIO object as the body and switch
- # to a TempFile when the passed threshold is passed.
- # Initialize the data from the query.
- #
- # Handles multipart forms (in particular, forms that involve file uploads).
- # Reads query parameters in the @params field, and cookies into @cookies.
- def initialize_query()
- if ("POST" == env_table['REQUEST_METHOD']) and
- %r|\Amultipart/form-data.*boundary=\"?([^\";,]+)\"?| =~ env_table['CONTENT_TYPE']
- current_max_multipart_length = @max_multipart_length.respond_to?(:call) ? @max_multipart_length.call : @max_multipart_length
- raise StandardError.new("too large multipart data.") if env_table['CONTENT_LENGTH'].to_i > current_max_multipart_length
- boundary = $1.dup
- @multipart = true
- @params = read_multipart(boundary, Integer(env_table['CONTENT_LENGTH']))
- else
- @multipart = false
- @params = CGI.parse(
- case env_table['REQUEST_METHOD']
- when "GET", "HEAD"
- if defined?(MOD_RUBY)
- Apache::request.args or ""
- else
- env_table['QUERY_STRING'] or ""
- end
- when "POST"
- stdinput.binmode if defined? stdinput.binmode
- stdinput.read(Integer(env_table['CONTENT_LENGTH'])) or ''
- else
- read_from_cmdline
- end.dup.force_encoding(@accept_charset)
- )
- unless Encoding.find(@accept_charset) == Encoding::ASCII_8BIT
- @params.each do |key,values|
- values.each do |value|
- unless value.valid_encoding?
- if @accept_charset_error_block
- @accept_charset_error_block.call(key,value)
- else
- raise InvalidEncoding,"Accept-Charset encoding error"
- end
- end
- end
- end
- end
- end
-
- @cookies = CGI::Cookie.parse((env_table['HTTP_COOKIE'] or env_table['COOKIE']))
- end
- private :initialize_query
-
- # Returns whether the form contained multipart/form-data
- def multipart?
- @multipart
- end
-
- # Get the value for the parameter with a given key.
- #
- # If the parameter has multiple values, only the first will be
- # retrieved; use #params to get the array of values.
- def [](key)
- params = @params[key]
- return '' unless params
- value = params[0]
- if @multipart
- if value
- return value
- elsif defined? StringIO
- StringIO.new("".b)
- else
- Tempfile.new("CGI",encoding: Encoding::ASCII_8BIT)
- end
- else
- str = if value then value.dup else "" end
- str
- end
- end
-
- # Return all query parameter names as an array of String.
- def keys(*args)
- @params.keys(*args)
- end
-
- # Returns true if a given query string parameter exists.
- def has_key?(*args)
- @params.has_key?(*args)
- end
- alias key? has_key?
- alias include? has_key?
-
- end # QueryExtension
-
- # Exception raised when there is an invalid encoding detected
- class InvalidEncoding < Exception; end
-
- # @@accept_charset is default accept character set.
- # This default value default is "UTF-8"
- # If you want to change the default accept character set
- # when create a new CGI instance, set this:
- #
- # CGI.accept_charset = "EUC-JP"
- #
- @@accept_charset="UTF-8" if false # needed for rdoc?
-
- # Return the accept character set for all new CGI instances.
- def self.accept_charset
- @@accept_charset
- end
-
- # Set the accept character set for all new CGI instances.
- def self.accept_charset=(accept_charset)
- @@accept_charset=accept_charset
- end
-
- # Return the accept character set for this CGI instance.
- attr_reader :accept_charset
-
- # @@max_multipart_length is the maximum length of multipart data.
- # The default value is 128 * 1024 * 1024 bytes
- #
- # The default can be set to something else in the CGI constructor,
- # via the :max_multipart_length key in the option hash.
- #
- # See CGI.new documentation.
- #
- @@max_multipart_length= 128 * 1024 * 1024
-
- # Create a new CGI instance.
- #
- # :call-seq:
- # CGI.new(tag_maker) { block }
- # CGI.new(options_hash = {}) { block }
- #
- #
- # <tt>tag_maker</tt>::
- # This is the same as using the +options_hash+ form with the value <tt>{
- # :tag_maker => tag_maker }</tt> Note that it is recommended to use the
- # +options_hash+ form, since it also allows you specify the charset you
- # will accept.
- # <tt>options_hash</tt>::
- # A Hash that recognizes three options:
- #
- # <tt>:accept_charset</tt>::
- # specifies encoding of received query string. If omitted,
- # <tt>@@accept_charset</tt> is used. If the encoding is not valid, a
- # CGI::InvalidEncoding will be raised.
- #
- # Example. Suppose <tt>@@accept_charset</tt> is "UTF-8"
- #
- # when not specified:
- #
- # cgi=CGI.new # @accept_charset # => "UTF-8"
- #
- # when specified as "EUC-JP":
- #
- # cgi=CGI.new(:accept_charset => "EUC-JP") # => "EUC-JP"
- #
- # <tt>:tag_maker</tt>::
- # String that specifies which version of the HTML generation methods to
- # use. If not specified, no HTML generation methods will be loaded.
- #
- # The following values are supported:
- #
- # "html3":: HTML 3.x
- # "html4":: HTML 4.0
- # "html4Tr":: HTML 4.0 Transitional
- # "html4Fr":: HTML 4.0 with Framesets
- # "html5":: HTML 5
- #
- # <tt>:max_multipart_length</tt>::
- # Specifies maximum length of multipart data. Can be an Integer scalar or
- # a lambda, that will be evaluated when the request is parsed. This
- # allows more complex logic to be set when determining whether to accept
- # multipart data (e.g. consult a registered users upload allowance)
- #
- # Default is 128 * 1024 * 1024 bytes
- #
- # cgi=CGI.new(:max_multipart_length => 268435456) # simple scalar
- #
- # cgi=CGI.new(:max_multipart_length => -> {check_filesystem}) # lambda
- #
- # <tt>block</tt>::
- # If provided, the block is called when an invalid encoding is
- # encountered. For example:
- #
- # encoding_errors={}
- # cgi=CGI.new(:accept_charset=>"EUC-JP") do |name,value|
- # encoding_errors[name] = value
- # end
- #
- # Finally, if the CGI object is not created in a standard CGI call
- # environment (that is, it can't locate REQUEST_METHOD in its environment),
- # then it will run in "offline" mode. In this mode, it reads its parameters
- # from the command line or (failing that) from standard input. Otherwise,
- # cookies and other parameters are parsed automatically from the standard
- # CGI locations, which varies according to the REQUEST_METHOD.
- def initialize(options = {}, &block) # :yields: name, value
- @accept_charset_error_block = block_given? ? block : nil
- @options={
- :accept_charset=>@@accept_charset,
- :max_multipart_length=>@@max_multipart_length
- }
- case options
- when Hash
- @options.merge!(options)
- when String
- @options[:tag_maker]=options
- end
- @accept_charset=@options[:accept_charset]
- @max_multipart_length=@options[:max_multipart_length]
- if defined?(MOD_RUBY) && !ENV.key?("GATEWAY_INTERFACE")
- Apache.request.setup_cgi_env
- end
-
- extend QueryExtension
- @multipart = false
-
- initialize_query() # set @params, @cookies
- @output_cookies = nil
- @output_hidden = nil
-
- case @options[:tag_maker]
- when "html3"
- require_relative 'html'
- extend Html3
- extend HtmlExtension
- when "html4"
- require_relative 'html'
- extend Html4
- extend HtmlExtension
- when "html4Tr"
- require_relative 'html'
- extend Html4Tr
- extend HtmlExtension
- when "html4Fr"
- require_relative 'html'
- extend Html4Tr
- extend Html4Fr
- extend HtmlExtension
- when "html5"
- require_relative 'html'
- extend Html5
- extend HtmlExtension
- end
- end
-
-end # class CGI
diff --git a/lib/cgi/escape.rb b/lib/cgi/escape.rb
new file mode 100644
index 0000000000..555d24a5da
--- /dev/null
+++ b/lib/cgi/escape.rb
@@ -0,0 +1,232 @@
+# frozen_string_literal: true
+
+# Since Ruby 4.0, \CGI is a small holder for various escaping methods, included from CGI::Escape
+#
+# require 'cgi/escape'
+#
+# CGI.escape("Ruby programming language")
+# #=> "Ruby+programming+language"
+# CGI.escapeURIComponent("Ruby programming language")
+# #=> "Ruby%20programming%20language"
+#
+# See CGI::Escape module for methods list and their description.
+class CGI
+ module Escape; end
+ include Escape
+ extend Escape
+ module EscapeExt; end # :nodoc:
+end
+
+# Web-related escape/unescape functionality.
+module CGI::Escape
+ @@accept_charset = Encoding::UTF_8 unless defined?(@@accept_charset)
+
+ # URL-encode a string into application/x-www-form-urlencoded.
+ # Space characters (<tt>" "</tt>) are encoded with plus signs (<tt>"+"</tt>)
+ # url_encoded_string = CGI.escape("'Stop!' said Fred")
+ # # => "%27Stop%21%27+said+Fred"
+ def escape(string)
+ encoding = string.encoding
+ buffer = string.b
+ buffer.gsub!(/([^ a-zA-Z0-9_.\-~]+)/) do |m|
+ '%' + m.unpack('H2' * m.bytesize).join('%').upcase
+ end
+ buffer.tr!(' ', '+')
+ buffer.force_encoding(encoding)
+ end
+
+ # URL-decode an application/x-www-form-urlencoded string with encoding(optional).
+ # string = CGI.unescape("%27Stop%21%27+said+Fred")
+ # # => "'Stop!' said Fred"
+ def unescape(string, encoding = @@accept_charset)
+ str = string.tr('+', ' ')
+ str = str.b
+ str.gsub!(/((?:%[0-9a-fA-F]{2})+)/) do |m|
+ [m.delete('%')].pack('H*')
+ end
+ str.force_encoding(encoding)
+ str.valid_encoding? ? str : str.force_encoding(string.encoding)
+ end
+
+ # URL-encode a string following RFC 3986
+ # Space characters (<tt>" "</tt>) are encoded with (<tt>"%20"</tt>)
+ # url_encoded_string = CGI.escapeURIComponent("'Stop!' said Fred")
+ # # => "%27Stop%21%27%20said%20Fred"
+ def escapeURIComponent(string)
+ encoding = string.encoding
+ buffer = string.b
+ buffer.gsub!(/([^a-zA-Z0-9_.\-~]+)/) do |m|
+ '%' + m.unpack('H2' * m.bytesize).join('%').upcase
+ end
+ buffer.force_encoding(encoding)
+ end
+ alias escape_uri_component escapeURIComponent
+
+ # URL-decode a string following RFC 3986 with encoding(optional).
+ # string = CGI.unescapeURIComponent("%27Stop%21%27+said%20Fred")
+ # # => "'Stop!'+said Fred"
+ def unescapeURIComponent(string, encoding = @@accept_charset)
+ str = string.b
+ str.gsub!(/((?:%[0-9a-fA-F]{2})+)/) do |m|
+ [m.delete('%')].pack('H*')
+ end
+ str.force_encoding(encoding)
+ str.valid_encoding? ? str : str.force_encoding(string.encoding)
+ end
+
+ alias unescape_uri_component unescapeURIComponent
+
+ # The set of special characters and their escaped values
+ TABLE_FOR_ESCAPE_HTML__ = { # :nodoc:
+ "'" => '&#39;',
+ '&' => '&amp;',
+ '"' => '&quot;',
+ '<' => '&lt;',
+ '>' => '&gt;',
+ }
+
+ # \Escape special characters in HTML, namely <tt>'&\"<></tt>
+ # CGI.escapeHTML('Usage: foo "bar" <baz>')
+ # # => "Usage: foo &quot;bar&quot; &lt;baz&gt;"
+ def escapeHTML(string)
+ enc = string.encoding
+ unless enc.ascii_compatible?
+ if enc.dummy?
+ origenc = enc
+ enc = Encoding::Converter.asciicompat_encoding(enc)
+ string = enc ? string.encode(enc) : string.b
+ end
+ table = Hash[TABLE_FOR_ESCAPE_HTML__.map {|pair|pair.map {|s|s.encode(enc)}}]
+ string = string.gsub(/#{"['&\"<>]".encode(enc)}/, table)
+ string.encode!(origenc) if origenc
+ string
+ else
+ string = string.b
+ string.gsub!(/['&\"<>]/, TABLE_FOR_ESCAPE_HTML__)
+ string.force_encoding(enc)
+ end
+ end
+
+ # Unescape a string that has been HTML-escaped
+ # CGI.unescapeHTML("Usage: foo &quot;bar&quot; &lt;baz&gt;")
+ # # => "Usage: foo \"bar\" <baz>"
+ def unescapeHTML(string)
+ enc = string.encoding
+ unless enc.ascii_compatible?
+ if enc.dummy?
+ origenc = enc
+ enc = Encoding::Converter.asciicompat_encoding(enc)
+ string = enc ? string.encode(enc) : string.b
+ end
+ string = string.gsub(Regexp.new('&(apos|amp|quot|gt|lt|#[0-9]+|#x[0-9A-Fa-f]+);'.encode(enc))) do
+ case $1.encode(Encoding::US_ASCII)
+ when 'apos' then "'".encode(enc)
+ when 'amp' then '&'.encode(enc)
+ when 'quot' then '"'.encode(enc)
+ when 'gt' then '>'.encode(enc)
+ when 'lt' then '<'.encode(enc)
+ when /\A#0*(\d+)\z/ then $1.to_i.chr(enc)
+ when /\A#x([0-9a-f]+)\z/i then $1.hex.chr(enc)
+ end
+ end
+ string.encode!(origenc) if origenc
+ return string
+ end
+ return string unless string.include? '&'
+ charlimit = case enc
+ when Encoding::UTF_8; 0x10ffff
+ when Encoding::ISO_8859_1; 256
+ else 128
+ end
+ string = string.b
+ string.gsub!(/&(apos|amp|quot|gt|lt|\#[0-9]+|\#[xX][0-9A-Fa-f]+);/) do
+ match = $1.dup
+ case match
+ when 'apos' then "'"
+ when 'amp' then '&'
+ when 'quot' then '"'
+ when 'gt' then '>'
+ when 'lt' then '<'
+ when /\A#0*(\d+)\z/
+ n = $1.to_i
+ if n < charlimit
+ n.chr(enc)
+ else
+ "&##{$1};"
+ end
+ when /\A#x([0-9a-f]+)\z/i
+ n = $1.hex
+ if n < charlimit
+ n.chr(enc)
+ else
+ "&#x#{$1};"
+ end
+ else
+ "&#{match};"
+ end
+ end
+ string.force_encoding enc
+ end
+
+ alias escape_html escapeHTML
+ alias h escapeHTML
+
+ alias unescape_html unescapeHTML
+
+ # TruffleRuby runs the pure-Ruby variant faster, do not use the C extension there
+ unless RUBY_ENGINE == 'truffleruby'
+ begin
+ require 'cgi/escape.so'
+ rescue LoadError
+ end
+ end
+
+ # \Escape only the tags of certain HTML elements in +string+.
+ #
+ # Takes an element or elements or array of elements. Each element
+ # is specified by the name of the element, without angle brackets.
+ # This matches both the start and the end tag of that element.
+ # The attribute list of the open tag will also be escaped (for
+ # instance, the double-quotes surrounding attribute values).
+ #
+ # print CGI.escapeElement('<BR><A HREF="url"></A>', "A", "IMG")
+ # # "<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt"
+ #
+ # print CGI.escapeElement('<BR><A HREF="url"></A>', ["A", "IMG"])
+ # # "<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt"
+ def escapeElement(string, *elements)
+ elements = elements[0] if elements[0].kind_of?(Array)
+ unless elements.empty?
+ string.gsub(/<\/?(?:#{elements.join("|")})\b[^<>]*+>?/im) do
+ CGI.escapeHTML($&)
+ end
+ else
+ string
+ end
+ end
+
+ # Undo escaping such as that done by CGI.escapeElement
+ #
+ # print CGI.unescapeElement(
+ # CGI.escapeHTML('<BR><A HREF="url"></A>'), "A", "IMG")
+ # # "&lt;BR&gt;<A HREF="url"></A>"
+ #
+ # print CGI.unescapeElement(
+ # CGI.escapeHTML('<BR><A HREF="url"></A>'), ["A", "IMG"])
+ # # "&lt;BR&gt;<A HREF="url"></A>"
+ def unescapeElement(string, *elements)
+ elements = elements[0] if elements[0].kind_of?(Array)
+ unless elements.empty?
+ string.gsub(/&lt;\/?(?:#{elements.join("|")})\b(?>[^&]+|&(?![gl]t;)\w+;)*(?:&gt;)?/im) do
+ unescapeHTML($&)
+ end
+ else
+ string
+ end
+ end
+
+ alias escape_element escapeElement
+
+ alias unescape_element unescapeElement
+
+end
diff --git a/lib/cgi/html.rb b/lib/cgi/html.rb
deleted file mode 100644
index 1543943320..0000000000
--- a/lib/cgi/html.rb
+++ /dev/null
@@ -1,1035 +0,0 @@
-# frozen_string_literal: true
-class CGI
- # Base module for HTML-generation mixins.
- #
- # Provides methods for code generation for tags following
- # the various DTD element types.
- module TagMaker # :nodoc:
-
- # Generate code for an element with required start and end tags.
- #
- # - -
- def nn_element(element, attributes = {})
- s = nOE_element(element, attributes)
- if block_given?
- s << yield.to_s
- end
- s << "</#{element.upcase}>"
- end
-
- def nn_element_def(attributes = {}, &block)
- nn_element(__callee__, attributes, &block)
- end
-
- # Generate code for an empty element.
- #
- # - O EMPTY
- def nOE_element(element, attributes = {})
- attributes={attributes=>nil} if attributes.kind_of?(String)
- s = "<#{element.upcase}".dup
- attributes.each do|name, value|
- next unless value
- s << " "
- s << CGI.escapeHTML(name.to_s)
- if value != true
- s << '="'
- s << CGI.escapeHTML(value.to_s)
- s << '"'
- end
- end
- s << ">"
- end
-
- def nOE_element_def(attributes = {}, &block)
- nOE_element(__callee__, attributes, &block)
- end
-
-
- # Generate code for an element for which the end (and possibly the
- # start) tag is optional.
- #
- # O O or - O
- def nO_element(element, attributes = {})
- s = nOE_element(element, attributes)
- if block_given?
- s << yield.to_s
- s << "</#{element.upcase}>"
- end
- s
- end
-
- def nO_element_def(attributes = {}, &block)
- nO_element(__callee__, attributes, &block)
- end
-
- end # TagMaker
-
-
- # Mixin module providing HTML generation methods.
- #
- # For example,
- # cgi.a("http://www.example.com") { "Example" }
- # # => "<A HREF=\"http://www.example.com\">Example</A>"
- #
- # Modules Html3, Html4, etc., contain more basic HTML-generation methods
- # (+#title+, +#h1+, etc.).
- #
- # See class CGI for a detailed example.
- #
- module HtmlExtension
-
-
- # Generate an Anchor element as a string.
- #
- # +href+ can either be a string, giving the URL
- # for the HREF attribute, or it can be a hash of
- # the element's attributes.
- #
- # The body of the element is the string returned by the no-argument
- # block passed in.
- #
- # a("http://www.example.com") { "Example" }
- # # => "<A HREF=\"http://www.example.com\">Example</A>"
- #
- # a("HREF" => "http://www.example.com", "TARGET" => "_top") { "Example" }
- # # => "<A HREF=\"http://www.example.com\" TARGET=\"_top\">Example</A>"
- #
- def a(href = "") # :yield:
- attributes = if href.kind_of?(String)
- { "HREF" => href }
- else
- href
- end
- super(attributes)
- end
-
- # Generate a Document Base URI element as a String.
- #
- # +href+ can either by a string, giving the base URL for the HREF
- # attribute, or it can be a has of the element's attributes.
- #
- # The passed-in no-argument block is ignored.
- #
- # base("http://www.example.com/cgi")
- # # => "<BASE HREF=\"http://www.example.com/cgi\">"
- def base(href = "") # :yield:
- attributes = if href.kind_of?(String)
- { "HREF" => href }
- else
- href
- end
- super(attributes)
- end
-
- # Generate a BlockQuote element as a string.
- #
- # +cite+ can either be a string, give the URI for the source of
- # the quoted text, or a hash, giving all attributes of the element,
- # or it can be omitted, in which case the element has no attributes.
- #
- # The body is provided by the passed-in no-argument block
- #
- # blockquote("http://www.example.com/quotes/foo.html") { "Foo!" }
- # #=> "<BLOCKQUOTE CITE=\"http://www.example.com/quotes/foo.html\">Foo!</BLOCKQUOTE>
- def blockquote(cite = {}) # :yield:
- attributes = if cite.kind_of?(String)
- { "CITE" => cite }
- else
- cite
- end
- super(attributes)
- end
-
-
- # Generate a Table Caption element as a string.
- #
- # +align+ can be a string, giving the alignment of the caption
- # (one of top, bottom, left, or right). It can be a hash of
- # all the attributes of the element. Or it can be omitted.
- #
- # The body of the element is provided by the passed-in no-argument block.
- #
- # caption("left") { "Capital Cities" }
- # # => <CAPTION ALIGN=\"left\">Capital Cities</CAPTION>
- def caption(align = {}) # :yield:
- attributes = if align.kind_of?(String)
- { "ALIGN" => align }
- else
- align
- end
- super(attributes)
- end
-
-
- # Generate a Checkbox Input element as a string.
- #
- # The attributes of the element can be specified as three arguments,
- # +name+, +value+, and +checked+. +checked+ is a boolean value;
- # if true, the CHECKED attribute will be included in the element.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # checkbox("name")
- # # = checkbox("NAME" => "name")
- #
- # checkbox("name", "value")
- # # = checkbox("NAME" => "name", "VALUE" => "value")
- #
- # checkbox("name", "value", true)
- # # = checkbox("NAME" => "name", "VALUE" => "value", "CHECKED" => true)
- def checkbox(name = "", value = nil, checked = nil)
- attributes = if name.kind_of?(String)
- { "TYPE" => "checkbox", "NAME" => name,
- "VALUE" => value, "CHECKED" => checked }
- else
- name["TYPE"] = "checkbox"
- name
- end
- input(attributes)
- end
-
- # Generate a sequence of checkbox elements, as a String.
- #
- # The checkboxes will all have the same +name+ attribute.
- # Each checkbox is followed by a label.
- # There will be one checkbox for each value. Each value
- # can be specified as a String, which will be used both
- # as the value of the VALUE attribute and as the label
- # for that checkbox. A single-element array has the
- # same effect.
- #
- # Each value can also be specified as a three-element array.
- # The first element is the VALUE attribute; the second is the
- # label; and the third is a boolean specifying whether this
- # checkbox is CHECKED.
- #
- # Each value can also be specified as a two-element
- # array, by omitting either the value element (defaults
- # to the same as the label), or the boolean checked element
- # (defaults to false).
- #
- # checkbox_group("name", "foo", "bar", "baz")
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="foo">foo
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="bar">bar
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="baz">baz
- #
- # checkbox_group("name", ["foo"], ["bar", true], "baz")
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="foo">foo
- # # <INPUT TYPE="checkbox" CHECKED NAME="name" VALUE="bar">bar
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="baz">baz
- #
- # checkbox_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz")
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="1">Foo
- # # <INPUT TYPE="checkbox" CHECKED NAME="name" VALUE="2">Bar
- # # <INPUT TYPE="checkbox" NAME="name" VALUE="Baz">Baz
- #
- # checkbox_group("NAME" => "name",
- # "VALUES" => ["foo", "bar", "baz"])
- #
- # checkbox_group("NAME" => "name",
- # "VALUES" => [["foo"], ["bar", true], "baz"])
- #
- # checkbox_group("NAME" => "name",
- # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"])
- def checkbox_group(name = "", *values)
- if name.kind_of?(Hash)
- values = name["VALUES"]
- name = name["NAME"]
- end
- values.collect{|value|
- if value.kind_of?(String)
- checkbox(name, value) + value
- else
- if value[-1] == true || value[-1] == false
- checkbox(name, value[0], value[-1]) +
- value[-2]
- else
- checkbox(name, value[0]) +
- value[-1]
- end
- end
- }.join
- end
-
-
- # Generate an File Upload Input element as a string.
- #
- # The attributes of the element can be specified as three arguments,
- # +name+, +size+, and +maxlength+. +maxlength+ is the maximum length
- # of the file's _name_, not of the file's _contents_.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # See #multipart_form() for forms that include file uploads.
- #
- # file_field("name")
- # # <INPUT TYPE="file" NAME="name" SIZE="20">
- #
- # file_field("name", 40)
- # # <INPUT TYPE="file" NAME="name" SIZE="40">
- #
- # file_field("name", 40, 100)
- # # <INPUT TYPE="file" NAME="name" SIZE="40" MAXLENGTH="100">
- #
- # file_field("NAME" => "name", "SIZE" => 40)
- # # <INPUT TYPE="file" NAME="name" SIZE="40">
- def file_field(name = "", size = 20, maxlength = nil)
- attributes = if name.kind_of?(String)
- { "TYPE" => "file", "NAME" => name,
- "SIZE" => size.to_s }
- else
- name["TYPE"] = "file"
- name
- end
- attributes["MAXLENGTH"] = maxlength.to_s if maxlength
- input(attributes)
- end
-
-
- # Generate a Form element as a string.
- #
- # +method+ should be either "get" or "post", and defaults to the latter.
- # +action+ defaults to the current CGI script name. +enctype+
- # defaults to "application/x-www-form-urlencoded".
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # See also #multipart_form() for forms that include file uploads.
- #
- # form{ "string" }
- # # <FORM METHOD="post" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
- #
- # form("get") { "string" }
- # # <FORM METHOD="get" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
- #
- # form("get", "url") { "string" }
- # # <FORM METHOD="get" ACTION="url" ENCTYPE="application/x-www-form-urlencoded">string</FORM>
- #
- # form("METHOD" => "post", "ENCTYPE" => "enctype") { "string" }
- # # <FORM METHOD="post" ENCTYPE="enctype">string</FORM>
- def form(method = "post", action = script_name, enctype = "application/x-www-form-urlencoded")
- attributes = if method.kind_of?(String)
- { "METHOD" => method, "ACTION" => action,
- "ENCTYPE" => enctype }
- else
- unless method.has_key?("METHOD")
- method["METHOD"] = "post"
- end
- unless method.has_key?("ENCTYPE")
- method["ENCTYPE"] = enctype
- end
- method
- end
- if block_given?
- body = yield
- else
- body = ""
- end
- if @output_hidden
- body << @output_hidden.collect{|k,v|
- "<INPUT TYPE=\"HIDDEN\" NAME=\"#{k}\" VALUE=\"#{v}\">"
- }.join
- end
- super(attributes){body}
- end
-
- # Generate a Hidden Input element as a string.
- #
- # The attributes of the element can be specified as two arguments,
- # +name+ and +value+.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # hidden("name")
- # # <INPUT TYPE="hidden" NAME="name">
- #
- # hidden("name", "value")
- # # <INPUT TYPE="hidden" NAME="name" VALUE="value">
- #
- # hidden("NAME" => "name", "VALUE" => "reset", "ID" => "foo")
- # # <INPUT TYPE="hidden" NAME="name" VALUE="value" ID="foo">
- def hidden(name = "", value = nil)
- attributes = if name.kind_of?(String)
- { "TYPE" => "hidden", "NAME" => name, "VALUE" => value }
- else
- name["TYPE"] = "hidden"
- name
- end
- input(attributes)
- end
-
- # Generate a top-level HTML element as a string.
- #
- # The attributes of the element are specified as a hash. The
- # pseudo-attribute "PRETTY" can be used to specify that the generated
- # HTML string should be indented. "PRETTY" can also be specified as
- # a string as the sole argument to this method. The pseudo-attribute
- # "DOCTYPE", if given, is used as the leading DOCTYPE SGML tag; it
- # should include the entire text of this tag, including angle brackets.
- #
- # The body of the html element is supplied as a block.
- #
- # html{ "string" }
- # # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><HTML>string</HTML>
- #
- # html("LANG" => "ja") { "string" }
- # # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><HTML LANG="ja">string</HTML>
- #
- # html("DOCTYPE" => false) { "string" }
- # # <HTML>string</HTML>
- #
- # html("DOCTYPE" => '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">') { "string" }
- # # <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"><HTML>string</HTML>
- #
- # html("PRETTY" => " ") { "<BODY></BODY>" }
- # # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
- # # <HTML>
- # # <BODY>
- # # </BODY>
- # # </HTML>
- #
- # html("PRETTY" => "\t") { "<BODY></BODY>" }
- # # <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
- # # <HTML>
- # # <BODY>
- # # </BODY>
- # # </HTML>
- #
- # html("PRETTY") { "<BODY></BODY>" }
- # # = html("PRETTY" => " ") { "<BODY></BODY>" }
- #
- # html(if $VERBOSE then "PRETTY" end) { "HTML string" }
- #
- def html(attributes = {}) # :yield:
- if nil == attributes
- attributes = {}
- elsif "PRETTY" == attributes
- attributes = { "PRETTY" => true }
- end
- pretty = attributes.delete("PRETTY")
- pretty = " " if true == pretty
- buf = "".dup
-
- if attributes.has_key?("DOCTYPE")
- if attributes["DOCTYPE"]
- buf << attributes.delete("DOCTYPE")
- else
- attributes.delete("DOCTYPE")
- end
- else
- buf << doctype
- end
-
- buf << super(attributes)
-
- if pretty
- CGI.pretty(buf, pretty)
- else
- buf
- end
-
- end
-
- # Generate an Image Button Input element as a string.
- #
- # +src+ is the URL of the image to use for the button. +name+
- # is the input name. +alt+ is the alternative text for the image.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # image_button("url")
- # # <INPUT TYPE="image" SRC="url">
- #
- # image_button("url", "name", "string")
- # # <INPUT TYPE="image" SRC="url" NAME="name" ALT="string">
- #
- # image_button("SRC" => "url", "ALT" => "string")
- # # <INPUT TYPE="image" SRC="url" ALT="string">
- def image_button(src = "", name = nil, alt = nil)
- attributes = if src.kind_of?(String)
- { "TYPE" => "image", "SRC" => src, "NAME" => name,
- "ALT" => alt }
- else
- src["TYPE"] = "image"
- src["SRC"] ||= ""
- src
- end
- input(attributes)
- end
-
-
- # Generate an Image element as a string.
- #
- # +src+ is the URL of the image. +alt+ is the alternative text for
- # the image. +width+ is the width of the image, and +height+ is
- # its height.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # img("src", "alt", 100, 50)
- # # <IMG SRC="src" ALT="alt" WIDTH="100" HEIGHT="50">
- #
- # img("SRC" => "src", "ALT" => "alt", "WIDTH" => 100, "HEIGHT" => 50)
- # # <IMG SRC="src" ALT="alt" WIDTH="100" HEIGHT="50">
- def img(src = "", alt = "", width = nil, height = nil)
- attributes = if src.kind_of?(String)
- { "SRC" => src, "ALT" => alt }
- else
- src
- end
- attributes["WIDTH"] = width.to_s if width
- attributes["HEIGHT"] = height.to_s if height
- super(attributes)
- end
-
-
- # Generate a Form element with multipart encoding as a String.
- #
- # Multipart encoding is used for forms that include file uploads.
- #
- # +action+ is the action to perform. +enctype+ is the encoding
- # type, which defaults to "multipart/form-data".
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # multipart_form{ "string" }
- # # <FORM METHOD="post" ENCTYPE="multipart/form-data">string</FORM>
- #
- # multipart_form("url") { "string" }
- # # <FORM METHOD="post" ACTION="url" ENCTYPE="multipart/form-data">string</FORM>
- def multipart_form(action = nil, enctype = "multipart/form-data")
- attributes = if action == nil
- { "METHOD" => "post", "ENCTYPE" => enctype }
- elsif action.kind_of?(String)
- { "METHOD" => "post", "ACTION" => action,
- "ENCTYPE" => enctype }
- else
- unless action.has_key?("METHOD")
- action["METHOD"] = "post"
- end
- unless action.has_key?("ENCTYPE")
- action["ENCTYPE"] = enctype
- end
- action
- end
- if block_given?
- form(attributes){ yield }
- else
- form(attributes)
- end
- end
-
-
- # Generate a Password Input element as a string.
- #
- # +name+ is the name of the input field. +value+ is its default
- # value. +size+ is the size of the input field display. +maxlength+
- # is the maximum length of the inputted password.
- #
- # Alternatively, attributes can be specified as a hash.
- #
- # password_field("name")
- # # <INPUT TYPE="password" NAME="name" SIZE="40">
- #
- # password_field("name", "value")
- # # <INPUT TYPE="password" NAME="name" VALUE="value" SIZE="40">
- #
- # password_field("password", "value", 80, 200)
- # # <INPUT TYPE="password" NAME="name" VALUE="value" SIZE="80" MAXLENGTH="200">
- #
- # password_field("NAME" => "name", "VALUE" => "value")
- # # <INPUT TYPE="password" NAME="name" VALUE="value">
- def password_field(name = "", value = nil, size = 40, maxlength = nil)
- attributes = if name.kind_of?(String)
- { "TYPE" => "password", "NAME" => name,
- "VALUE" => value, "SIZE" => size.to_s }
- else
- name["TYPE"] = "password"
- name
- end
- attributes["MAXLENGTH"] = maxlength.to_s if maxlength
- input(attributes)
- end
-
- # Generate a Select element as a string.
- #
- # +name+ is the name of the element. The +values+ are the options that
- # can be selected from the Select menu. Each value can be a String or
- # a one, two, or three-element Array. If a String or a one-element
- # Array, this is both the value of that option and the text displayed for
- # it. If a three-element Array, the elements are the option value, displayed
- # text, and a boolean value specifying whether this option starts as selected.
- # The two-element version omits either the option value (defaults to the same
- # as the display text) or the boolean selected specifier (defaults to false).
- #
- # The attributes and options can also be specified as a hash. In this
- # case, options are specified as an array of values as described above,
- # with the hash key of "VALUES".
- #
- # popup_menu("name", "foo", "bar", "baz")
- # # <SELECT NAME="name">
- # # <OPTION VALUE="foo">foo</OPTION>
- # # <OPTION VALUE="bar">bar</OPTION>
- # # <OPTION VALUE="baz">baz</OPTION>
- # # </SELECT>
- #
- # popup_menu("name", ["foo"], ["bar", true], "baz")
- # # <SELECT NAME="name">
- # # <OPTION VALUE="foo">foo</OPTION>
- # # <OPTION VALUE="bar" SELECTED>bar</OPTION>
- # # <OPTION VALUE="baz">baz</OPTION>
- # # </SELECT>
- #
- # popup_menu("name", ["1", "Foo"], ["2", "Bar", true], "Baz")
- # # <SELECT NAME="name">
- # # <OPTION VALUE="1">Foo</OPTION>
- # # <OPTION SELECTED VALUE="2">Bar</OPTION>
- # # <OPTION VALUE="Baz">Baz</OPTION>
- # # </SELECT>
- #
- # popup_menu("NAME" => "name", "SIZE" => 2, "MULTIPLE" => true,
- # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"])
- # # <SELECT NAME="name" MULTIPLE SIZE="2">
- # # <OPTION VALUE="1">Foo</OPTION>
- # # <OPTION SELECTED VALUE="2">Bar</OPTION>
- # # <OPTION VALUE="Baz">Baz</OPTION>
- # # </SELECT>
- def popup_menu(name = "", *values)
-
- if name.kind_of?(Hash)
- values = name["VALUES"]
- size = name["SIZE"].to_s if name["SIZE"]
- multiple = name["MULTIPLE"]
- name = name["NAME"]
- else
- size = nil
- multiple = nil
- end
-
- select({ "NAME" => name, "SIZE" => size,
- "MULTIPLE" => multiple }){
- values.collect{|value|
- if value.kind_of?(String)
- option({ "VALUE" => value }){ value }
- else
- if value[value.size - 1] == true
- option({ "VALUE" => value[0], "SELECTED" => true }){
- value[value.size - 2]
- }
- else
- option({ "VALUE" => value[0] }){
- value[value.size - 1]
- }
- end
- end
- }.join
- }
-
- end
-
- # Generates a radio-button Input element.
- #
- # +name+ is the name of the input field. +value+ is the value of
- # the field if checked. +checked+ specifies whether the field
- # starts off checked.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # radio_button("name", "value")
- # # <INPUT TYPE="radio" NAME="name" VALUE="value">
- #
- # radio_button("name", "value", true)
- # # <INPUT TYPE="radio" NAME="name" VALUE="value" CHECKED>
- #
- # radio_button("NAME" => "name", "VALUE" => "value", "ID" => "foo")
- # # <INPUT TYPE="radio" NAME="name" VALUE="value" ID="foo">
- def radio_button(name = "", value = nil, checked = nil)
- attributes = if name.kind_of?(String)
- { "TYPE" => "radio", "NAME" => name,
- "VALUE" => value, "CHECKED" => checked }
- else
- name["TYPE"] = "radio"
- name
- end
- input(attributes)
- end
-
- # Generate a sequence of radio button Input elements, as a String.
- #
- # This works the same as #checkbox_group(). However, it is not valid
- # to have more than one radiobutton in a group checked.
- #
- # radio_group("name", "foo", "bar", "baz")
- # # <INPUT TYPE="radio" NAME="name" VALUE="foo">foo
- # # <INPUT TYPE="radio" NAME="name" VALUE="bar">bar
- # # <INPUT TYPE="radio" NAME="name" VALUE="baz">baz
- #
- # radio_group("name", ["foo"], ["bar", true], "baz")
- # # <INPUT TYPE="radio" NAME="name" VALUE="foo">foo
- # # <INPUT TYPE="radio" CHECKED NAME="name" VALUE="bar">bar
- # # <INPUT TYPE="radio" NAME="name" VALUE="baz">baz
- #
- # radio_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz")
- # # <INPUT TYPE="radio" NAME="name" VALUE="1">Foo
- # # <INPUT TYPE="radio" CHECKED NAME="name" VALUE="2">Bar
- # # <INPUT TYPE="radio" NAME="name" VALUE="Baz">Baz
- #
- # radio_group("NAME" => "name",
- # "VALUES" => ["foo", "bar", "baz"])
- #
- # radio_group("NAME" => "name",
- # "VALUES" => [["foo"], ["bar", true], "baz"])
- #
- # radio_group("NAME" => "name",
- # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"])
- def radio_group(name = "", *values)
- if name.kind_of?(Hash)
- values = name["VALUES"]
- name = name["NAME"]
- end
- values.collect{|value|
- if value.kind_of?(String)
- radio_button(name, value) + value
- else
- if value[-1] == true || value[-1] == false
- radio_button(name, value[0], value[-1]) +
- value[-2]
- else
- radio_button(name, value[0]) +
- value[-1]
- end
- end
- }.join
- end
-
- # Generate a reset button Input element, as a String.
- #
- # This resets the values on a form to their initial values. +value+
- # is the text displayed on the button. +name+ is the name of this button.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # reset
- # # <INPUT TYPE="reset">
- #
- # reset("reset")
- # # <INPUT TYPE="reset" VALUE="reset">
- #
- # reset("VALUE" => "reset", "ID" => "foo")
- # # <INPUT TYPE="reset" VALUE="reset" ID="foo">
- def reset(value = nil, name = nil)
- attributes = if (not value) or value.kind_of?(String)
- { "TYPE" => "reset", "VALUE" => value, "NAME" => name }
- else
- value["TYPE"] = "reset"
- value
- end
- input(attributes)
- end
-
- alias scrolling_list popup_menu
-
- # Generate a submit button Input element, as a String.
- #
- # +value+ is the text to display on the button. +name+ is the name
- # of the input.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # submit
- # # <INPUT TYPE="submit">
- #
- # submit("ok")
- # # <INPUT TYPE="submit" VALUE="ok">
- #
- # submit("ok", "button1")
- # # <INPUT TYPE="submit" VALUE="ok" NAME="button1">
- #
- # submit("VALUE" => "ok", "NAME" => "button1", "ID" => "foo")
- # # <INPUT TYPE="submit" VALUE="ok" NAME="button1" ID="foo">
- def submit(value = nil, name = nil)
- attributes = if (not value) or value.kind_of?(String)
- { "TYPE" => "submit", "VALUE" => value, "NAME" => name }
- else
- value["TYPE"] = "submit"
- value
- end
- input(attributes)
- end
-
- # Generate a text field Input element, as a String.
- #
- # +name+ is the name of the input field. +value+ is its initial
- # value. +size+ is the size of the input area. +maxlength+
- # is the maximum length of input accepted.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # text_field("name")
- # # <INPUT TYPE="text" NAME="name" SIZE="40">
- #
- # text_field("name", "value")
- # # <INPUT TYPE="text" NAME="name" VALUE="value" SIZE="40">
- #
- # text_field("name", "value", 80)
- # # <INPUT TYPE="text" NAME="name" VALUE="value" SIZE="80">
- #
- # text_field("name", "value", 80, 200)
- # # <INPUT TYPE="text" NAME="name" VALUE="value" SIZE="80" MAXLENGTH="200">
- #
- # text_field("NAME" => "name", "VALUE" => "value")
- # # <INPUT TYPE="text" NAME="name" VALUE="value">
- def text_field(name = "", value = nil, size = 40, maxlength = nil)
- attributes = if name.kind_of?(String)
- { "TYPE" => "text", "NAME" => name, "VALUE" => value,
- "SIZE" => size.to_s }
- else
- name["TYPE"] = "text"
- name
- end
- attributes["MAXLENGTH"] = maxlength.to_s if maxlength
- input(attributes)
- end
-
- # Generate a TextArea element, as a String.
- #
- # +name+ is the name of the textarea. +cols+ is the number of
- # columns and +rows+ is the number of rows in the display.
- #
- # Alternatively, the attributes can be specified as a hash.
- #
- # The body is provided by the passed-in no-argument block
- #
- # textarea("name")
- # # = textarea("NAME" => "name", "COLS" => 70, "ROWS" => 10)
- #
- # textarea("name", 40, 5)
- # # = textarea("NAME" => "name", "COLS" => 40, "ROWS" => 5)
- def textarea(name = "", cols = 70, rows = 10) # :yield:
- attributes = if name.kind_of?(String)
- { "NAME" => name, "COLS" => cols.to_s,
- "ROWS" => rows.to_s }
- else
- name
- end
- super(attributes)
- end
-
- end # HtmlExtension
-
-
- # Mixin module for HTML version 3 generation methods.
- module Html3 # :nodoc:
- include TagMaker
-
- # The DOCTYPE declaration for this version of HTML
- def doctype
- %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">|
- end
-
- instance_method(:nn_element_def).tap do |m|
- # - -
- for element in %w[ A TT I B U STRIKE BIG SMALL SUB SUP EM STRONG
- DFN CODE SAMP KBD VAR CITE FONT ADDRESS DIV CENTER MAP
- APPLET PRE XMP LISTING DL OL UL DIR MENU SELECT TABLE TITLE
- STYLE SCRIPT H1 H2 H3 H4 H5 H6 TEXTAREA FORM BLOCKQUOTE
- CAPTION ]
- define_method(element.downcase, m)
- end
- end
-
- instance_method(:nOE_element_def).tap do |m|
- # - O EMPTY
- for element in %w[ IMG BASE BASEFONT BR AREA LINK PARAM HR INPUT
- ISINDEX META ]
- define_method(element.downcase, m)
- end
- end
-
- instance_method(:nO_element_def).tap do |m|
- # O O or - O
- for element in %w[ HTML HEAD BODY P PLAINTEXT DT DD LI OPTION TR
- TH TD ]
- define_method(element.downcase, m)
- end
- end
-
- end # Html3
-
-
- # Mixin module for HTML version 4 generation methods.
- module Html4 # :nodoc:
- include TagMaker
-
- # The DOCTYPE declaration for this version of HTML
- def doctype
- %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">|
- end
-
- # Initialize the HTML generation methods for this version.
- # - -
- instance_method(:nn_element_def).tap do |m|
- for element in %w[ TT I B BIG SMALL EM STRONG DFN CODE SAMP KBD
- VAR CITE ABBR ACRONYM SUB SUP SPAN BDO ADDRESS DIV MAP OBJECT
- H1 H2 H3 H4 H5 H6 PRE Q INS DEL DL OL UL LABEL SELECT OPTGROUP
- FIELDSET LEGEND BUTTON TABLE TITLE STYLE SCRIPT NOSCRIPT
- TEXTAREA FORM A BLOCKQUOTE CAPTION ]
- define_method(element.downcase, m)
- end
- end
-
- # - O EMPTY
- instance_method(:nOE_element_def).tap do |m|
- for element in %w[ IMG BASE BR AREA LINK PARAM HR INPUT COL META ]
- define_method(element.downcase, m)
- end
- end
-
- # O O or - O
- instance_method(:nO_element_def).tap do |m|
- for element in %w[ HTML BODY P DT DD LI OPTION THEAD TFOOT TBODY
- COLGROUP TR TH TD HEAD ]
- define_method(element.downcase, m)
- end
- end
-
- end # Html4
-
-
- # Mixin module for HTML version 4 transitional generation methods.
- module Html4Tr # :nodoc:
- include TagMaker
-
- # The DOCTYPE declaration for this version of HTML
- def doctype
- %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">|
- end
-
- # Initialise the HTML generation methods for this version.
- # - -
- instance_method(:nn_element_def).tap do |m|
- for element in %w[ TT I B U S STRIKE BIG SMALL EM STRONG DFN
- CODE SAMP KBD VAR CITE ABBR ACRONYM FONT SUB SUP SPAN BDO
- ADDRESS DIV CENTER MAP OBJECT APPLET H1 H2 H3 H4 H5 H6 PRE Q
- INS DEL DL OL UL DIR MENU LABEL SELECT OPTGROUP FIELDSET
- LEGEND BUTTON TABLE IFRAME NOFRAMES TITLE STYLE SCRIPT
- NOSCRIPT TEXTAREA FORM A BLOCKQUOTE CAPTION ]
- define_method(element.downcase, m)
- end
- end
-
- # - O EMPTY
- instance_method(:nOE_element_def).tap do |m|
- for element in %w[ IMG BASE BASEFONT BR AREA LINK PARAM HR INPUT
- COL ISINDEX META ]
- define_method(element.downcase, m)
- end
- end
-
- # O O or - O
- instance_method(:nO_element_def).tap do |m|
- for element in %w[ HTML BODY P DT DD LI OPTION THEAD TFOOT TBODY
- COLGROUP TR TH TD HEAD ]
- define_method(element.downcase, m)
- end
- end
-
- end # Html4Tr
-
-
- # Mixin module for generating HTML version 4 with framesets.
- module Html4Fr # :nodoc:
- include TagMaker
-
- # The DOCTYPE declaration for this version of HTML
- def doctype
- %|<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">|
- end
-
- # Initialise the HTML generation methods for this version.
- # - -
- instance_method(:nn_element_def).tap do |m|
- for element in %w[ FRAMESET ]
- define_method(element.downcase, m)
- end
- end
-
- # - O EMPTY
- instance_method(:nOE_element_def).tap do |m|
- for element in %w[ FRAME ]
- define_method(element.downcase, m)
- end
- end
-
- end # Html4Fr
-
-
- # Mixin module for HTML version 5 generation methods.
- module Html5 # :nodoc:
- include TagMaker
-
- # The DOCTYPE declaration for this version of HTML
- def doctype
- %|<!DOCTYPE HTML>|
- end
-
- # Initialise the HTML generation methods for this version.
- # - -
- instance_method(:nn_element_def).tap do |m|
- for element in %w[ SECTION NAV ARTICLE ASIDE HGROUP HEADER
- FOOTER FIGURE FIGCAPTION S TIME U MARK RUBY BDI IFRAME
- VIDEO AUDIO CANVAS DATALIST OUTPUT PROGRESS METER DETAILS
- SUMMARY MENU DIALOG I B SMALL EM STRONG DFN CODE SAMP KBD
- VAR CITE ABBR SUB SUP SPAN BDO ADDRESS DIV MAP OBJECT
- H1 H2 H3 H4 H5 H6 PRE Q INS DEL DL OL UL LABEL SELECT
- FIELDSET LEGEND BUTTON TABLE TITLE STYLE SCRIPT NOSCRIPT
- TEXTAREA FORM A BLOCKQUOTE CAPTION ]
- define_method(element.downcase, m)
- end
- end
-
- # - O EMPTY
- instance_method(:nOE_element_def).tap do |m|
- for element in %w[ IMG BASE BR AREA LINK PARAM HR INPUT COL META
- COMMAND EMBED KEYGEN SOURCE TRACK WBR ]
- define_method(element.downcase, m)
- end
- end
-
- # O O or - O
- instance_method(:nO_element_def).tap do |m|
- for element in %w[ HTML HEAD BODY P DT DD LI OPTION THEAD TFOOT TBODY
- OPTGROUP COLGROUP RT RP TR TH TD ]
- define_method(element.downcase, m)
- end
- end
-
- end # Html5
-
- class HTML3
- include Html3
- include HtmlExtension
- end
-
- class HTML4
- include Html4
- include HtmlExtension
- end
-
- class HTML4Tr
- include Html4Tr
- include HtmlExtension
- end
-
- class HTML4Fr
- include Html4Tr
- include Html4Fr
- include HtmlExtension
- end
-
- class HTML5
- include Html5
- include HtmlExtension
- end
-
-end
diff --git a/lib/cgi/session.rb b/lib/cgi/session.rb
deleted file mode 100644
index aab60869bb..0000000000
--- a/lib/cgi/session.rb
+++ /dev/null
@@ -1,562 +0,0 @@
-# frozen_string_literal: true
-#
-# cgi/session.rb - session support for cgi scripts
-#
-# Copyright (C) 2001 Yukihiro "Matz" Matsumoto
-# Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
-# Copyright (C) 2000 Information-technology Promotion Agency, Japan
-#
-# Author: Yukihiro "Matz" Matsumoto
-#
-# Documentation: William Webber (william@williamwebber.com)
-
-require 'cgi'
-require 'tmpdir'
-
-class CGI
-
- # == Overview
- #
- # This file provides the CGI::Session class, which provides session
- # support for CGI scripts. A session is a sequence of HTTP requests
- # and responses linked together and associated with a single client.
- # Information associated with the session is stored
- # on the server between requests. A session id is passed between client
- # and server with every request and response, transparently
- # to the user. This adds state information to the otherwise stateless
- # HTTP request/response protocol.
- #
- # == Lifecycle
- #
- # A CGI::Session instance is created from a CGI object. By default,
- # this CGI::Session instance will start a new session if none currently
- # exists, or continue the current session for this client if one does
- # exist. The +new_session+ option can be used to either always or
- # never create a new session. See #new() for more details.
- #
- # #delete() deletes a session from session storage. It
- # does not however remove the session id from the client. If the client
- # makes another request with the same id, the effect will be to start
- # a new session with the old session's id.
- #
- # == Setting and retrieving session data.
- #
- # The Session class associates data with a session as key-value pairs.
- # This data can be set and retrieved by indexing the Session instance
- # using '[]', much the same as hashes (although other hash methods
- # are not supported).
- #
- # When session processing has been completed for a request, the
- # session should be closed using the close() method. This will
- # store the session's state to persistent storage. If you want
- # to store the session's state to persistent storage without
- # finishing session processing for this request, call the update()
- # method.
- #
- # == Storing session state
- #
- # The caller can specify what form of storage to use for the session's
- # data with the +database_manager+ option to CGI::Session::new. The
- # following storage classes are provided as part of the standard library:
- #
- # CGI::Session::FileStore:: stores data as plain text in a flat file. Only
- # works with String data. This is the default
- # storage type.
- # CGI::Session::MemoryStore:: stores data in an in-memory hash. The data
- # only persists for as long as the current Ruby
- # interpreter instance does.
- # CGI::Session::PStore:: stores data in Marshalled format. Provided by
- # cgi/session/pstore.rb. Supports data of any type,
- # and provides file-locking and transaction support.
- #
- # Custom storage types can also be created by defining a class with
- # the following methods:
- #
- # new(session, options)
- # restore # returns hash of session data.
- # update
- # close
- # delete
- #
- # Changing storage type mid-session does not work. Note in particular
- # that by default the FileStore and PStore session data files have the
- # same name. If your application switches from one to the other without
- # making sure that filenames will be different
- # and clients still have old sessions lying around in cookies, then
- # things will break nastily!
- #
- # == Maintaining the session id.
- #
- # Most session state is maintained on the server. However, a session
- # id must be passed backwards and forwards between client and server
- # to maintain a reference to this session state.
- #
- # The simplest way to do this is via cookies. The CGI::Session class
- # provides transparent support for session id communication via cookies
- # if the client has cookies enabled.
- #
- # If the client has cookies disabled, the session id must be included
- # as a parameter of all requests sent by the client to the server. The
- # CGI::Session class in conjunction with the CGI class will transparently
- # add the session id as a hidden input field to all forms generated
- # using the CGI#form() HTML generation method. No built-in support is
- # provided for other mechanisms, such as URL re-writing. The caller is
- # responsible for extracting the session id from the session_id
- # attribute and manually encoding it in URLs and adding it as a hidden
- # input to HTML forms created by other mechanisms. Also, session expiry
- # is not automatically handled.
- #
- # == Examples of use
- #
- # === Setting the user's name
- #
- # require 'cgi'
- # require 'cgi/session'
- # require 'cgi/session/pstore' # provides CGI::Session::PStore
- #
- # cgi = CGI.new("html4")
- #
- # session = CGI::Session.new(cgi,
- # 'database_manager' => CGI::Session::PStore, # use PStore
- # 'session_key' => '_rb_sess_id', # custom session key
- # 'session_expires' => Time.now + 30 * 60, # 30 minute timeout
- # 'prefix' => 'pstore_sid_') # PStore option
- # if cgi.has_key?('user_name') and cgi['user_name'] != ''
- # # coerce to String: cgi[] returns the
- # # string-like CGI::QueryExtension::Value
- # session['user_name'] = cgi['user_name'].to_s
- # elsif !session['user_name']
- # session['user_name'] = "guest"
- # end
- # session.close
- #
- # === Creating a new session safely
- #
- # require 'cgi'
- # require 'cgi/session'
- #
- # cgi = CGI.new("html4")
- #
- # # We make sure to delete an old session if one exists,
- # # not just to free resources, but to prevent the session
- # # from being maliciously hijacked later on.
- # begin
- # session = CGI::Session.new(cgi, 'new_session' => false)
- # session.delete
- # rescue ArgumentError # if no old session
- # end
- # session = CGI::Session.new(cgi, 'new_session' => true)
- # session.close
- #
- class Session
-
- class NoSession < RuntimeError #:nodoc:
- end
-
- # The id of this session.
- attr_reader :session_id, :new_session
-
- def Session::callback(dbman) #:nodoc:
- Proc.new{
- dbman[0].close unless dbman.empty?
- }
- end
-
- # Create a new session id.
- #
- # The session id is a secure random number by SecureRandom
- # if possible, otherwise an SHA512 hash based upon the time,
- # a random number, and a constant string. This routine is
- # used internally for automatically generated session ids.
- def create_new_id
- require 'securerandom'
- begin
- # by OpenSSL, or system provided entropy pool
- session_id = SecureRandom.hex(16)
- rescue NotImplementedError
- # never happens on modern systems
- require 'digest'
- d = Digest('SHA512').new
- now = Time::now
- d.update(now.to_s)
- d.update(String(now.usec))
- d.update(String(rand(0)))
- d.update(String($$))
- d.update('foobar')
- session_id = d.hexdigest[0, 32]
- end
- session_id
- end
- private :create_new_id
-
-
- # Create a new file to store the session data.
- #
- # This file will be created if it does not exist, or opened if it
- # does.
- #
- # This path is generated under _tmpdir_ from _prefix_, the
- # digested session id, and _suffix_.
- #
- # +option+ is a hash of options for the initializer. The
- # following options are recognised:
- #
- # tmpdir:: the directory to use for storing the FileStore
- # file. Defaults to Dir::tmpdir (generally "/tmp"
- # on Unix systems).
- # prefix:: the prefix to add to the session id when generating
- # the filename for this session's FileStore file.
- # Defaults to "cgi_sid_".
- # suffix:: the prefix to add to the session id when generating
- # the filename for this session's FileStore file.
- # Defaults to the empty string.
- def new_store_file(option={}) # :nodoc:
- dir = option['tmpdir'] || Dir::tmpdir
- prefix = option['prefix']
- suffix = option['suffix']
- require 'digest/md5'
- md5 = Digest::MD5.hexdigest(session_id)[0,16]
- path = dir+"/"
- path << prefix if prefix
- path << md5
- path << suffix if suffix
- if File::exist? path
- hash = nil
- elsif new_session
- hash = {}
- else
- raise NoSession, "uninitialized session"
- end
- return path, hash
- end
-
- # Create a new CGI::Session object for +request+.
- #
- # +request+ is an instance of the +CGI+ class (see cgi.rb).
- # +option+ is a hash of options for initialising this
- # CGI::Session instance. The following options are
- # recognised:
- #
- # session_key:: the parameter name used for the session id.
- # Defaults to '_session_id'.
- # session_id:: the session id to use. If not provided, then
- # it is retrieved from the +session_key+ parameter
- # of the request, or automatically generated for
- # a new session.
- # new_session:: if true, force creation of a new session. If not set,
- # a new session is only created if none currently
- # exists. If false, a new session is never created,
- # and if none currently exists and the +session_id+
- # option is not set, an ArgumentError is raised.
- # database_manager:: the name of the class providing storage facilities
- # for session state persistence. Built-in support
- # is provided for +FileStore+ (the default),
- # +MemoryStore+, and +PStore+ (from
- # cgi/session/pstore.rb). See the documentation for
- # these classes for more details.
- #
- # The following options are also recognised, but only apply if the
- # session id is stored in a cookie.
- #
- # session_expires:: the time the current session expires, as a
- # +Time+ object. If not set, the session will terminate
- # when the user's browser is closed.
- # session_domain:: the hostname domain for which this session is valid.
- # If not set, defaults to the hostname of the server.
- # session_secure:: if +true+, this session will only work over HTTPS.
- # session_path:: the path for which this session applies. Defaults
- # to the directory of the CGI script.
- #
- # +option+ is also passed on to the session storage class initializer; see
- # the documentation for each session storage class for the options
- # they support.
- #
- # The retrieved or created session is automatically added to +request+
- # as a cookie, and also to its +output_hidden+ table, which is used
- # to add hidden input elements to forms.
- #
- # *WARNING* the +output_hidden+
- # fields are surrounded by a <fieldset> tag in HTML 4 generation, which
- # is _not_ invisible on many browsers; you may wish to disable the
- # use of fieldsets with code similar to the following
- # (see https://blade.ruby-lang.org/ruby-list/37805)
- #
- # cgi = CGI.new("html4")
- # class << cgi
- # undef_method :fieldset
- # end
- #
- def initialize(request, option={})
- @new_session = false
- session_key = option['session_key'] || '_session_id'
- session_id = option['session_id']
- unless session_id
- if option['new_session']
- session_id = create_new_id
- @new_session = true
- end
- end
- unless session_id
- if request.key?(session_key)
- session_id = request[session_key]
- session_id = session_id.read if session_id.respond_to?(:read)
- end
- unless session_id
- session_id, = request.cookies[session_key]
- end
- unless session_id
- unless option.fetch('new_session', true)
- raise ArgumentError, "session_key `%s' should be supplied"%session_key
- end
- session_id = create_new_id
- @new_session = true
- end
- end
- @session_id = session_id
- dbman = option['database_manager'] || FileStore
- begin
- @dbman = dbman::new(self, option)
- rescue NoSession
- unless option.fetch('new_session', true)
- raise ArgumentError, "invalid session_id `%s'"%session_id
- end
- session_id = @session_id = create_new_id unless session_id
- @new_session=true
- retry
- end
- request.instance_eval do
- @output_hidden = {session_key => session_id} unless option['no_hidden']
- @output_cookies = [
- Cookie::new("name" => session_key,
- "value" => session_id,
- "expires" => option['session_expires'],
- "domain" => option['session_domain'],
- "secure" => option['session_secure'],
- "path" =>
- if option['session_path']
- option['session_path']
- elsif ENV["SCRIPT_NAME"]
- File::dirname(ENV["SCRIPT_NAME"])
- else
- ""
- end)
- ] unless option['no_cookies']
- end
- @dbprot = [@dbman]
- ObjectSpace::define_finalizer(self, Session::callback(@dbprot))
- end
-
- # Retrieve the session data for key +key+.
- def [](key)
- @data ||= @dbman.restore
- @data[key]
- end
-
- # Set the session data for key +key+.
- def []=(key, val)
- @write_lock ||= true
- @data ||= @dbman.restore
- @data[key] = val
- end
-
- # Store session data on the server. For some session storage types,
- # this is a no-op.
- def update
- @dbman.update
- end
-
- # Store session data on the server and close the session storage.
- # For some session storage types, this is a no-op.
- def close
- @dbman.close
- @dbprot.clear
- end
-
- # Delete the session from storage. Also closes the storage.
- #
- # Note that the session's data is _not_ automatically deleted
- # upon the session expiring.
- def delete
- @dbman.delete
- @dbprot.clear
- end
-
- # File-based session storage class.
- #
- # Implements session storage as a flat file of 'key=value' values.
- # This storage type only works directly with String values; the
- # user is responsible for converting other types to Strings when
- # storing and from Strings when retrieving.
- class FileStore
- # Create a new FileStore instance.
- #
- # This constructor is used internally by CGI::Session. The
- # user does not generally need to call it directly.
- #
- # +session+ is the session for which this instance is being
- # created. The session id must only contain alphanumeric
- # characters; automatically generated session ids observe
- # this requirement.
- #
- # +option+ is a hash of options for the initializer. The
- # following options are recognised:
- #
- # tmpdir:: the directory to use for storing the FileStore
- # file. Defaults to Dir::tmpdir (generally "/tmp"
- # on Unix systems).
- # prefix:: the prefix to add to the session id when generating
- # the filename for this session's FileStore file.
- # Defaults to "cgi_sid_".
- # suffix:: the prefix to add to the session id when generating
- # the filename for this session's FileStore file.
- # Defaults to the empty string.
- #
- # This session's FileStore file will be created if it does
- # not exist, or opened if it does.
- def initialize(session, option={})
- option = {'prefix' => 'cgi_sid_'}.update(option)
- @path, @hash = session.new_store_file(option)
- end
-
- # Restore session state from the session's FileStore file.
- #
- # Returns the session state as a hash.
- def restore
- unless @hash
- @hash = {}
- begin
- lockf = File.open(@path+".lock", "r")
- lockf.flock File::LOCK_SH
- f = File.open(@path, 'r')
- for line in f
- line.chomp!
- k, v = line.split('=',2)
- @hash[CGI.unescape(k)] = Marshal.restore(CGI.unescape(v))
- end
- ensure
- f&.close
- lockf&.close
- end
- end
- @hash
- end
-
- # Save session state to the session's FileStore file.
- def update
- return unless @hash
- begin
- lockf = File.open(@path+".lock", File::CREAT|File::RDWR, 0600)
- lockf.flock File::LOCK_EX
- f = File.open(@path+".new", File::CREAT|File::TRUNC|File::WRONLY, 0600)
- for k,v in @hash
- f.printf "%s=%s\n", CGI.escape(k), CGI.escape(String(Marshal.dump(v)))
- end
- f.close
- File.rename @path+".new", @path
- ensure
- f&.close
- lockf&.close
- end
- end
-
- # Update and close the session's FileStore file.
- def close
- update
- end
-
- # Close and delete the session's FileStore file.
- def delete
- File::unlink @path+".lock" rescue nil
- File::unlink @path+".new" rescue nil
- File::unlink @path rescue nil
- end
- end
-
- # In-memory session storage class.
- #
- # Implements session storage as a global in-memory hash. Session
- # data will only persist for as long as the Ruby interpreter
- # instance does.
- class MemoryStore
- GLOBAL_HASH_TABLE = {} #:nodoc:
-
- # Create a new MemoryStore instance.
- #
- # +session+ is the session this instance is associated with.
- # +option+ is a list of initialisation options. None are
- # currently recognized.
- def initialize(session, option=nil)
- @session_id = session.session_id
- unless GLOBAL_HASH_TABLE.key?(@session_id)
- unless session.new_session
- raise CGI::Session::NoSession, "uninitialized session"
- end
- GLOBAL_HASH_TABLE[@session_id] = {}
- end
- end
-
- # Restore session state.
- #
- # Returns session data as a hash.
- def restore
- GLOBAL_HASH_TABLE[@session_id]
- end
-
- # Update session state.
- #
- # A no-op.
- def update
- # don't need to update; hash is shared
- end
-
- # Close session storage.
- #
- # A no-op.
- def close
- # don't need to close
- end
-
- # Delete the session state.
- def delete
- GLOBAL_HASH_TABLE.delete(@session_id)
- end
- end
-
- # Dummy session storage class.
- #
- # Implements session storage place holder. No actual storage
- # will be done.
- class NullStore
- # Create a new NullStore instance.
- #
- # +session+ is the session this instance is associated with.
- # +option+ is a list of initialisation options. None are
- # currently recognised.
- def initialize(session, option=nil)
- end
-
- # Restore (empty) session state.
- def restore
- {}
- end
-
- # Update session state.
- #
- # A no-op.
- def update
- end
-
- # Close session storage.
- #
- # A no-op.
- def close
- end
-
- # Delete the session state.
- #
- # A no-op.
- def delete
- end
- end
- end
-end
diff --git a/lib/cgi/session/pstore.rb b/lib/cgi/session/pstore.rb
deleted file mode 100644
index 45d0d8ae2c..0000000000
--- a/lib/cgi/session/pstore.rb
+++ /dev/null
@@ -1,88 +0,0 @@
-# frozen_string_literal: true
-#
-# cgi/session/pstore.rb - persistent storage of marshalled session data
-#
-# Documentation: William Webber (william@williamwebber.com)
-#
-# == Overview
-#
-# This file provides the CGI::Session::PStore class, which builds
-# persistent of session data on top of the pstore library. See
-# cgi/session.rb for more details on session storage managers.
-
-require_relative '../session'
-require 'pstore'
-
-class CGI
- class Session
- # PStore-based session storage class.
- #
- # This builds upon the top-level PStore class provided by the
- # library file pstore.rb. Session data is marshalled and stored
- # in a file. File locking and transaction services are provided.
- class PStore
- # Create a new CGI::Session::PStore instance
- #
- # This constructor is used internally by CGI::Session. The
- # user does not generally need to call it directly.
- #
- # +session+ is the session for which this instance is being
- # created. The session id must only contain alphanumeric
- # characters; automatically generated session ids observe
- # this requirement.
- #
- # +option+ is a hash of options for the initializer. The
- # following options are recognised:
- #
- # tmpdir:: the directory to use for storing the PStore
- # file. Defaults to Dir::tmpdir (generally "/tmp"
- # on Unix systems).
- # prefix:: the prefix to add to the session id when generating
- # the filename for this session's PStore file.
- # Defaults to the empty string.
- #
- # This session's PStore file will be created if it does
- # not exist, or opened if it does.
- def initialize(session, option={})
- option = {'suffix'=>''}.update(option)
- path, @hash = session.new_store_file(option)
- @p = ::PStore.new(path)
- @p.transaction do |p|
- File.chmod(0600, p.path)
- end
- end
-
- # Restore session state from the session's PStore file.
- #
- # Returns the session state as a hash.
- def restore
- unless @hash
- @p.transaction do
- @hash = @p['hash'] || {}
- end
- end
- @hash
- end
-
- # Save session state to the session's PStore file.
- def update
- @p.transaction do
- @p['hash'] = @hash
- end
- end
-
- # Update and close the session's PStore file.
- def close
- update
- end
-
- # Close and delete the session's PStore file.
- def delete
- path = @p.path
- File::unlink path
- end
-
- end
- end
-end
-# :enddoc:
diff --git a/lib/cgi/util.rb b/lib/cgi/util.rb
index 4986e544e0..50a2e91665 100644
--- a/lib/cgi/util.rb
+++ b/lib/cgi/util.rb
@@ -1,258 +1,7 @@
# frozen_string_literal: true
-class CGI
- module Util; end
- include Util
- extend Util
-end
-module CGI::Util
- @@accept_charset = Encoding::UTF_8 unless defined?(@@accept_charset)
- # URL-encode a string into application/x-www-form-urlencoded.
- # Space characters (+" "+) are encoded with plus signs (+"+"+)
- # url_encoded_string = CGI.escape("'Stop!' said Fred")
- # # => "%27Stop%21%27+said+Fred"
- def escape(string)
- encoding = string.encoding
- buffer = string.b
- buffer.gsub!(/([^ a-zA-Z0-9_.\-~]+)/) do |m|
- '%' + m.unpack('H2' * m.bytesize).join('%').upcase
- end
- buffer.tr!(' ', '+')
- buffer.force_encoding(encoding)
- end
-
- # URL-decode an application/x-www-form-urlencoded string with encoding(optional).
- # string = CGI.unescape("%27Stop%21%27+said+Fred")
- # # => "'Stop!' said Fred"
- def unescape(string, encoding = @@accept_charset)
- str = string.tr('+', ' ')
- str = str.b
- str.gsub!(/((?:%[0-9a-fA-F]{2})+)/) do |m|
- [m.delete('%')].pack('H*')
- end
- str.force_encoding(encoding)
- str.valid_encoding? ? str : str.force_encoding(string.encoding)
- end
-
- # URL-encode a string following RFC 3986
- # Space characters (+" "+) are encoded with (+"%20"+)
- # url_encoded_string = CGI.escapeURIComponent("'Stop!' said Fred")
- # # => "%27Stop%21%27%20said%20Fred"
- def escapeURIComponent(string)
- encoding = string.encoding
- buffer = string.b
- buffer.gsub!(/([^a-zA-Z0-9_.\-~]+)/) do |m|
- '%' + m.unpack('H2' * m.bytesize).join('%').upcase
- end
- buffer.force_encoding(encoding)
- end
- alias escape_uri_component escapeURIComponent
-
- # URL-decode a string following RFC 3986 with encoding(optional).
- # string = CGI.unescapeURIComponent("%27Stop%21%27+said%20Fred")
- # # => "'Stop!'+said Fred"
- def unescapeURIComponent(string, encoding = @@accept_charset)
- str = string.b
- str.gsub!(/((?:%[0-9a-fA-F]{2})+)/) do |m|
- [m.delete('%')].pack('H*')
- end
- str.force_encoding(encoding)
- str.valid_encoding? ? str : str.force_encoding(string.encoding)
- end
-
- alias unescape_uri_component unescapeURIComponent
-
- # The set of special characters and their escaped values
- TABLE_FOR_ESCAPE_HTML__ = {
- "'" => '&#39;',
- '&' => '&amp;',
- '"' => '&quot;',
- '<' => '&lt;',
- '>' => '&gt;',
- }
-
- # Escape special characters in HTML, namely '&\"<>
- # CGI.escapeHTML('Usage: foo "bar" <baz>')
- # # => "Usage: foo &quot;bar&quot; &lt;baz&gt;"
- def escapeHTML(string)
- enc = string.encoding
- unless enc.ascii_compatible?
- if enc.dummy?
- origenc = enc
- enc = Encoding::Converter.asciicompat_encoding(enc)
- string = enc ? string.encode(enc) : string.b
- end
- table = Hash[TABLE_FOR_ESCAPE_HTML__.map {|pair|pair.map {|s|s.encode(enc)}}]
- string = string.gsub(/#{"['&\"<>]".encode(enc)}/, table)
- string.encode!(origenc) if origenc
- string
- else
- string = string.b
- string.gsub!(/['&\"<>]/, TABLE_FOR_ESCAPE_HTML__)
- string.force_encoding(enc)
- end
- end
-
- # TruffleRuby runs the pure-Ruby variant faster, do not use the C extension there
- unless RUBY_ENGINE == 'truffleruby'
- begin
- require 'cgi/escape'
- rescue LoadError
- end
- end
-
- # Unescape a string that has been HTML-escaped
- # CGI.unescapeHTML("Usage: foo &quot;bar&quot; &lt;baz&gt;")
- # # => "Usage: foo \"bar\" <baz>"
- def unescapeHTML(string)
- enc = string.encoding
- unless enc.ascii_compatible?
- if enc.dummy?
- origenc = enc
- enc = Encoding::Converter.asciicompat_encoding(enc)
- string = enc ? string.encode(enc) : string.b
- end
- string = string.gsub(Regexp.new('&(apos|amp|quot|gt|lt|#[0-9]+|#x[0-9A-Fa-f]+);'.encode(enc))) do
- case $1.encode(Encoding::US_ASCII)
- when 'apos' then "'".encode(enc)
- when 'amp' then '&'.encode(enc)
- when 'quot' then '"'.encode(enc)
- when 'gt' then '>'.encode(enc)
- when 'lt' then '<'.encode(enc)
- when /\A#0*(\d+)\z/ then $1.to_i.chr(enc)
- when /\A#x([0-9a-f]+)\z/i then $1.hex.chr(enc)
- end
- end
- string.encode!(origenc) if origenc
- return string
- end
- return string unless string.include? '&'
- charlimit = case enc
- when Encoding::UTF_8; 0x10ffff
- when Encoding::ISO_8859_1; 256
- else 128
- end
- string = string.b
- string.gsub!(/&(apos|amp|quot|gt|lt|\#[0-9]+|\#[xX][0-9A-Fa-f]+);/) do
- match = $1.dup
- case match
- when 'apos' then "'"
- when 'amp' then '&'
- when 'quot' then '"'
- when 'gt' then '>'
- when 'lt' then '<'
- when /\A#0*(\d+)\z/
- n = $1.to_i
- if n < charlimit
- n.chr(enc)
- else
- "&##{$1};"
- end
- when /\A#x([0-9a-f]+)\z/i
- n = $1.hex
- if n < charlimit
- n.chr(enc)
- else
- "&#x#{$1};"
- end
- else
- "&#{match};"
- end
- end
- string.force_encoding enc
- end
-
- # Synonym for CGI.escapeHTML(str)
- alias escape_html escapeHTML
-
- # Synonym for CGI.unescapeHTML(str)
- alias unescape_html unescapeHTML
-
- # Escape only the tags of certain HTML elements in +string+.
- #
- # Takes an element or elements or array of elements. Each element
- # is specified by the name of the element, without angle brackets.
- # This matches both the start and the end tag of that element.
- # The attribute list of the open tag will also be escaped (for
- # instance, the double-quotes surrounding attribute values).
- #
- # print CGI.escapeElement('<BR><A HREF="url"></A>', "A", "IMG")
- # # "<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt"
- #
- # print CGI.escapeElement('<BR><A HREF="url"></A>', ["A", "IMG"])
- # # "<BR>&lt;A HREF=&quot;url&quot;&gt;&lt;/A&gt"
- def escapeElement(string, *elements)
- elements = elements[0] if elements[0].kind_of?(Array)
- unless elements.empty?
- string.gsub(/<\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?>/i) do
- CGI.escapeHTML($&)
- end
- else
- string
- end
- end
-
- # Undo escaping such as that done by CGI.escapeElement()
- #
- # print CGI.unescapeElement(
- # CGI.escapeHTML('<BR><A HREF="url"></A>'), "A", "IMG")
- # # "&lt;BR&gt;<A HREF="url"></A>"
- #
- # print CGI.unescapeElement(
- # CGI.escapeHTML('<BR><A HREF="url"></A>'), ["A", "IMG"])
- # # "&lt;BR&gt;<A HREF="url"></A>"
- def unescapeElement(string, *elements)
- elements = elements[0] if elements[0].kind_of?(Array)
- unless elements.empty?
- string.gsub(/&lt;\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?&gt;/i) do
- unescapeHTML($&)
- end
- else
- string
- end
- end
-
- # Synonym for CGI.escapeElement(str)
- alias escape_element escapeElement
-
- # Synonym for CGI.unescapeElement(str)
- alias unescape_element unescapeElement
-
- # Format a +Time+ object as a String using the format specified by RFC 1123.
- #
- # CGI.rfc1123_date(Time.now)
- # # Sat, 01 Jan 2000 00:00:00 GMT
- def rfc1123_date(time)
- time.getgm.strftime("%a, %d %b %Y %T GMT")
- end
-
- # Prettify (indent) an HTML string.
- #
- # +string+ is the HTML string to indent. +shift+ is the indentation
- # unit to use; it defaults to two spaces.
- #
- # print CGI.pretty("<HTML><BODY></BODY></HTML>")
- # # <HTML>
- # # <BODY>
- # # </BODY>
- # # </HTML>
- #
- # print CGI.pretty("<HTML><BODY></BODY></HTML>", "\t")
- # # <HTML>
- # # <BODY>
- # # </BODY>
- # # </HTML>
- #
- def pretty(string, shift = " ")
- lines = string.gsub(/(?!\A)<.*?>/m, "\n\\0").gsub(/<.*?>(?!\n)/m, "\\0\n")
- end_pos = 0
- while end_pos = lines.index(/^<\/(\w+)/, end_pos)
- element = $1.dup
- start_pos = lines.rindex(/^\s*<#{element}/i, end_pos)
- lines[start_pos ... end_pos] = "__" + lines[start_pos ... end_pos].gsub(/\n(?!\z)/, "\n" + shift) + "__"
- end
- lines.gsub(/^((?:#{Regexp::quote(shift)})*)__(?=<\/?\w)/, '\1')
- end
-
- alias h escapeHTML
-end
+require "cgi/escape"
+warn <<-WARNING, uplevel: Gem::BUNDLED_GEMS.uplevel if $VERBOSE
+CGI::Util is removed from Ruby 4.0. Please use cgi/escape instead for CGI.escape and CGI.unescape features.
+If you are using CGI.parse, please install and use the cgi gem instead.
+WARNING
diff --git a/lib/delegate.gemspec b/lib/delegate.gemspec
index 6c3feac74b..f7fcc1ceb9 100644
--- a/lib/delegate.gemspec
+++ b/lib/delegate.gemspec
@@ -25,5 +25,5 @@ Gem::Specification.new do |spec|
`git ls-files -z 2>#{IO::NULL}`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
end
spec.require_paths = ["lib"]
- spec.required_ruby_version = '>= 2.7'
+ spec.required_ruby_version = '>= 3.0'
end
diff --git a/lib/delegate.rb b/lib/delegate.rb
index 1ea4fb985b..0cc3ddb1b0 100644
--- a/lib/delegate.rb
+++ b/lib/delegate.rb
@@ -39,7 +39,8 @@
# Be advised, RDoc will not detect delegated methods.
#
class Delegator < BasicObject
- VERSION = "0.3.1"
+ # The version string
+ VERSION = "0.6.1"
kernel = ::Kernel.dup
kernel.class_eval do
@@ -77,7 +78,7 @@ class Delegator < BasicObject
end
#
- # Handles the magic of delegation through \_\_getobj\_\_.
+ # Handles the magic of delegation through +__getobj__+.
#
ruby2_keywords def method_missing(m, *args, &block)
r = true
@@ -94,7 +95,7 @@ class Delegator < BasicObject
#
# Checks for a method provided by this the delegate object by forwarding the
- # call through \_\_getobj\_\_.
+ # call through +__getobj__+.
#
def respond_to_missing?(m, include_private)
r = true
@@ -107,7 +108,7 @@ class Delegator < BasicObject
r
end
- KERNEL_RESPOND_TO = ::Kernel.instance_method(:respond_to?)
+ KERNEL_RESPOND_TO = ::Kernel.instance_method(:respond_to?) # :nodoc:
private_constant :KERNEL_RESPOND_TO
# Handle BasicObject instances
@@ -126,7 +127,7 @@ class Delegator < BasicObject
#
# Returns the methods available to this delegate object as the union
- # of this object's and \_\_getobj\_\_ methods.
+ # of this object's and +__getobj__+ methods.
#
def methods(all=true)
__getobj__.methods(all) | super
@@ -134,7 +135,7 @@ class Delegator < BasicObject
#
# Returns the methods available to this delegate object as the union
- # of this object's and \_\_getobj\_\_ public methods.
+ # of this object's and +__getobj__+ public methods.
#
def public_methods(all=true)
__getobj__.public_methods(all) | super
@@ -142,7 +143,7 @@ class Delegator < BasicObject
#
# Returns the methods available to this delegate object as the union
- # of this object's and \_\_getobj\_\_ protected methods.
+ # of this object's and +__getobj__+ protected methods.
#
def protected_methods(all=true)
__getobj__.protected_methods(all) | super
@@ -175,7 +176,7 @@ class Delegator < BasicObject
end
#
- # Delegates ! to the \_\_getobj\_\_
+ # Delegates ! to the +__getobj__+
#
def !
!__getobj__
@@ -198,7 +199,7 @@ class Delegator < BasicObject
end
#
- # Serialization support for the object returned by \_\_getobj\_\_.
+ # Serialization support for the object returned by +__getobj__+.
#
def marshal_dump
ivars = instance_variables.reject {|var| /\A@delegate_/ =~ var}
@@ -232,7 +233,7 @@ class Delegator < BasicObject
##
# :method: freeze
- # Freeze both the object returned by \_\_getobj\_\_ and self.
+ # Freeze both the object returned by +__getobj__+ and self.
#
def freeze
__getobj__.freeze
@@ -398,6 +399,17 @@ def DelegateClass(superclass, &block)
protected_instance_methods -= ignores
public_instance_methods = superclass.public_instance_methods
public_instance_methods -= ignores
+
+ normal, special = public_instance_methods.partition { |m| m.match?(/\A[a-zA-Z]\w*[!\?]?\z/) }
+
+ source = normal.map do |method|
+ "def #{method}(...); __getobj__.#{method}(...); end"
+ end
+
+ protected_instance_methods.each do |method|
+ source << "def #{method}(...); __getobj__.__send__(#{method.inspect}, ...); end"
+ end
+
klass.module_eval do
def __getobj__ # :nodoc:
unless defined?(@delegate_dc_obj)
@@ -406,18 +418,21 @@ def DelegateClass(superclass, &block)
end
@delegate_dc_obj
end
+
def __setobj__(obj) # :nodoc:
__raise__ ::ArgumentError, "cannot delegate to self" if self.equal?(obj)
@delegate_dc_obj = obj
end
- protected_instance_methods.each do |method|
- define_method(method, Delegator.delegating_block(method))
- protected method
- end
- public_instance_methods.each do |method|
+
+ class_eval(source.join(";"), __FILE__, __LINE__)
+
+ special.each do |method|
define_method(method, Delegator.delegating_block(method))
end
+
+ protected(*protected_instance_methods)
end
+
klass.define_singleton_method :public_instance_methods do |all=true|
super(all) | superclass.public_instance_methods
end
diff --git a/lib/did_you_mean.rb b/lib/did_you_mean.rb
index e177665099..74cd176042 100644
--- a/lib/did_you_mean.rb
+++ b/lib/did_you_mean.rb
@@ -113,30 +113,6 @@ module DidYouMean
correct_error LoadError, RequirePathChecker if RUBY_VERSION >= '2.8.0'
correct_error NoMatchingPatternKeyError, PatternKeyNameChecker if defined?(::NoMatchingPatternKeyError)
- # TODO: Remove on the 3.4 development start:
- class DeprecatedMapping # :nodoc:
- def []=(key, value)
- warn "Calling `DidYouMean::SPELL_CHECKERS[#{key.to_s}] = #{value.to_s}' has been deprecated. " \
- "Please call `DidYouMean.correct_error(#{key.to_s}, #{value.to_s})' instead."
-
- DidYouMean.correct_error(key, value)
- end
-
- def merge!(hash)
- warn "Calling `DidYouMean::SPELL_CHECKERS.merge!(error_name => spell_checker)' has been deprecated. " \
- "Please call `DidYouMean.correct_error(error_name, spell_checker)' instead."
-
- hash.each do |error_class, spell_checker|
- DidYouMean.correct_error(error_class, spell_checker)
- end
- end
- end
-
- # TODO: Remove on the 3.4 development start:
- SPELL_CHECKERS = DeprecatedMapping.new
- deprecate_constant :SPELL_CHECKERS
- private_constant :DeprecatedMapping
-
# Returns the currently set formatter. By default, it is set to +DidYouMean::Formatter+.
def self.formatter
if defined?(Ractor)
diff --git a/lib/did_you_mean/version.rb b/lib/did_you_mean/version.rb
index 5745ca1efd..85d80e4230 100644
--- a/lib/did_you_mean/version.rb
+++ b/lib/did_you_mean/version.rb
@@ -1,3 +1,3 @@
module DidYouMean
- VERSION = "1.6.3".freeze
+ VERSION = "2.0.0".freeze
end
diff --git a/lib/erb.gemspec b/lib/erb.gemspec
deleted file mode 100644
index 94a8fd5c3e..0000000000
--- a/lib/erb.gemspec
+++ /dev/null
@@ -1,38 +0,0 @@
-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', 'Takashi Kokubun']
- spec.email = ['seki@ruby-lang.org', 'k0kubun@ruby-lang.org']
-
- spec.summary = %q{An easy to use but powerful templating system for Ruby.}
- spec.description = %q{An easy to use but powerful templating system for Ruby.}
- spec.homepage = 'https://github.com/ruby/erb'
- spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0')
- spec.licenses = ['Ruby', 'BSD-2-Clause']
-
- spec.metadata['homepage_uri'] = spec.homepage
- 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']
-
- if RUBY_ENGINE == 'jruby'
- spec.platform = 'java'
- else
- spec.required_ruby_version = '>= 2.7.0'
- spec.extensions = ['ext/erb/escape/extconf.rb']
- end
-
- spec.add_dependency 'cgi', '>= 0.3.3'
-end
diff --git a/lib/erb.rb b/lib/erb.rb
index bc1615d7da..445d4795b0 100644
--- a/lib/erb.rb
+++ b/lib/erb.rb
@@ -12,340 +12,824 @@
#
# You can redistribute it and/or modify it under the same terms as Ruby.
-require 'cgi/util'
+# A NOTE ABOUT TERMS:
+#
+# Formerly: The documentation in this file used the term _template_ to refer to an ERB object.
+#
+# Now: The documentation in this file uses the term _template_
+# to refer to the string input to ERB.new.
+#
+# The reason for the change: When documenting the ERB executable erb,
+# we need a term that refers to its string input;
+# _source_ is not a good idea, because ERB#src means something entirely different;
+# the two different sorts of sources would bring confusion.
+#
+# Therefore we use the term _template_ to refer to:
+#
+# - The string input to ERB.new
+# - The string input to executable erb.
+#
+
require 'erb/version'
require 'erb/compiler'
require 'erb/def_method'
require 'erb/util'
+# :markup: markdown
#
-# = ERB -- Ruby Templating
+# Class **ERB** (the name stands for **Embedded Ruby**)
+# is an easy-to-use, but also very powerful, [template processor][template processor].
#
-# == Introduction
+# ## Usage
#
-# ERB provides an easy to use but powerful templating system for Ruby. Using
-# ERB, actual Ruby code can be added to any plain text document for the
-# purposes of generating document information details and/or flow control.
+# Before you can use \ERB, you must first require it
+# (examples on this page assume that this has been done):
#
-# A very simple example is this:
+# ```
+# require 'erb'
+# ```
#
-# require 'erb'
+# ## In Brief
#
-# x = 42
-# template = ERB.new <<-EOF
-# The value of x is: <%= x %>
-# EOF
-# puts template.result(binding)
+# Here's how \ERB works:
#
-# <em>Prints:</em> The value of x is: 42
+# - You can create a *template*: a plain-text string that includes specially formatted *tags*..
+# - You can create an \ERB object to store the template.
+# - You can call instance method ERB#result to get the *result*.
#
-# More complex examples are given below.
+# \ERB supports tags of three kinds:
#
+# - [Expression tags][expression tags]:
+# each begins with `'<%='`, ends with `'%>'`; contains a Ruby expression;
+# in the result, the value of the expression replaces the entire tag:
#
-# == Recognized Tags
+# template = 'The magic word is <%= magic_word %>.'
+# erb = ERB.new(template)
+# magic_word = 'xyzzy'
+# erb.result(binding) # => "The magic word is xyzzy."
#
-# ERB recognizes certain tags in the provided template and converts them based
-# on the rules below:
+# The above call to #result passes argument `binding`,
+# which contains the binding of variable `magic_word` to its string value `'xyzzy'`.
#
-# <% Ruby code -- inline with output %>
-# <%= Ruby expression -- replace with result %>
-# <%# 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
+# The below call to #result need not pass a binding,
+# because its expression `Date::DAYNAMES` is globally defined.
#
-# All other text is passed through ERB filtering unchanged.
+# ERB.new('Today is <%= Date::DAYNAMES[Date.today.wday] %>.').result # => "Today is Monday."
#
+# - [Execution tags][execution tags]:
+# each begins with `'<%'`, ends with `'%>'`; contains Ruby code to be executed:
#
-# == Options
+# template = '<% File.write("t.txt", "Some stuff.") %>'
+# ERB.new(template).result
+# File.read('t.txt') # => "Some stuff."
#
-# There are several settings you can change when you use ERB:
-# * the nature of the tags that are recognized;
-# * the binding used to resolve local variables in the template.
+# - [Comment tags][comment tags]:
+# each begins with `'<%#'`, ends with `'%>'`; contains comment text;
+# in the result, the entire tag is omitted.
#
-# See the ERB.new and ERB#result methods for more detail.
+# template = 'Some stuff;<%# Note to self: figure out what the stuff is. %> more stuff.'
+# ERB.new(template).result # => "Some stuff; more stuff."
#
-# == Character encodings
+# ## Some Simple Examples
#
-# ERB (or Ruby code generated by ERB) returns a string in the same
-# character encoding as the input string. When the input string has
-# a magic comment, however, it returns a string in the encoding specified
-# by the magic comment.
+# Here's a simple example of \ERB in action:
#
-# # -*- coding: utf-8 -*-
-# require 'erb'
+# ```
+# template = 'The time is <%= Time.now %>.'
+# erb = ERB.new(template)
+# erb.result
+# # => "The time is 2025-09-09 10:49:26 -0500."
+# ```
#
-# template = ERB.new <<EOF
-# <%#-*- coding: Big5 -*-%>
-# \_\_ENCODING\_\_ is <%= \_\_ENCODING\_\_ %>.
-# EOF
-# puts template.result
+# Details:
#
-# <em>Prints:</em> \_\_ENCODING\_\_ is Big5.
+# 1. A plain-text string is assigned to variable `template`.
+# Its embedded [expression tag][expression tags] `'<%= Time.now %>'` includes a Ruby expression, `Time.now`.
+# 2. The string is put into a new \ERB object, and stored in variable `erb`.
+# 4. Method call `erb.result` generates a string that contains the run-time value of `Time.now`,
+# as computed at the time of the call.
#
+# The
+# \ERB object may be re-used:
#
-# == Examples
+# ```
+# erb.result
+# # => "The time is 2025-09-09 10:49:33 -0500."
+# ```
#
-# === Plain Text
+# Another example:
#
-# ERB is useful for any generic templating situation. Note that in this example, we use the
-# convenient "% at start of line" tag, and we quote the template literally with
-# <tt>%q{...}</tt> to avoid trouble with the backslash.
+# ```
+# template = 'The magic word is <%= magic_word %>.'
+# erb = ERB.new(template)
+# magic_word = 'abracadabra'
+# erb.result(binding)
+# # => "The magic word is abracadabra."
+# ```
#
-# require "erb"
+# Details:
#
-# # Create template.
-# template = %q{
-# From: James Edward Gray II <james@grayproductions.net>
-# To: <%= to %>
-# Subject: Addressing Needs
+# 1. As before, a plain-text string is assigned to variable `template`.
+# Its embedded [expression tag][expression tags] `'<%= magic_word %>'` has a variable *name*, `magic_word`.
+# 2. The string is put into a new \ERB object, and stored in variable `erb`;
+# note that `magic_word` need not be defined before the \ERB object is created.
+# 3. `magic_word = 'abracadabra'` assigns a value to variable `magic_word`.
+# 4. Method call `erb.result(binding)` generates a string
+# that contains the *value* of `magic_word`.
#
-# <%= to[/\w+/] %>:
+# As before, the \ERB object may be re-used:
#
-# Just wanted to send a quick note assuring that your needs are being
-# addressed.
+# ```
+# magic_word = 'xyzzy'
+# erb.result(binding)
+# # => "The magic word is xyzzy."
+# ```
#
-# I want you to know that my team will keep working on the issues,
-# especially:
+# ## Bindings
#
-# <%# ignore numerous minor requests -- focus on priorities %>
-# % priorities.each do |priority|
-# * <%= priority %>
-# % end
+# A call to method #result, which produces the formatted result string,
+# requires a [Binding object][binding object] as its argument.
+#
+# The binding object provides the bindings for expressions in [expression tags][expression tags].
+#
+# There are three ways to provide the required binding:
+#
+# - [Default binding][default binding].
+# - [Local binding][local binding].
+# - [Augmented binding][augmented binding]
+#
+# ### Default Binding
+#
+# When you pass no `binding` argument to method #result,
+# the method uses its default binding: the one returned by method #new_toplevel.
+# This binding has the bindings defined by Ruby itself,
+# which are those for Ruby's constants and variables.
+#
+# That binding is sufficient for an expression tag that refers only to Ruby's constants and variables;
+# these expression tags refer only to Ruby's global constant `RUBY_COPYRIGHT` and global variable `$0`:
#
-# Thanks for your patience.
+# ```
+# template = <<TEMPLATE
+# The Ruby copyright is <%= RUBY_COPYRIGHT.inspect %>.
+# The current process is <%= $0 %>.
+# TEMPLATE
+# puts ERB.new(template).result
+# The Ruby copyright is "ruby - Copyright (C) 1993-2025 Yukihiro Matsumoto".
+# The current process is irb.
+# ```
+#
+# (The current process is `irb` because that's where we're doing these examples!)
+#
+# ### Local Binding
+#
+# The default binding is *not* sufficient for an expression
+# that refers to a a constant or variable that is not defined there:
+#
+# ```
+# Foo = 1 # Defines local constant Foo.
+# foo = 2 # Defines local variable foo.
+# template = <<TEMPLATE
+# The current value of constant Foo is <%= Foo %>.
+# The current value of variable foo is <%= foo %>.
+# The Ruby copyright is <%= RUBY_COPYRIGHT.inspect %>.
+# The current process is <%= $0 %>.
+# TEMPLATE
+# erb = ERB.new(template)
+# ```
+#
+# This call below raises `NameError` because although `Foo` and `foo` are defined locally,
+# they are not defined in the default binding:
+#
+# ```
+# erb.result # Raises NameError.
+# ```
+#
+# To make the locally-defined constants and variables available,
+# you can call #result with the local binding:
+#
+# ```
+# puts erb.result(binding)
+# The current value of constant Foo is 1.
+# The current value of variable foo is 2.
+# The Ruby copyright is "ruby - Copyright (C) 1993-2025 Yukihiro Matsumoto".
+# The current process is irb.
+# ```
+#
+# ### Augmented Binding
+#
+# Another way to make variable bindings (but not constant bindings) available
+# is to use method #result_with_hash(hash);
+# the passed hash has name/value pairs that are to be used to define and assign variables
+# in a copy of the default binding:
+#
+# ```
+# template = <<TEMPLATE
+# The current value of variable bar is <%= bar %>.
+# The current value of variable baz is <%= baz %>.
+# The Ruby copyright is <%= RUBY_COPYRIGHT.inspect %>.
+# The current process is <%= $0 %>.
+# TEMPLATE
+# erb = ERB.new(template)
+# ```
+#
+# Both of these calls raise `NameError`, because `bar` and `baz`
+# are not defined in either the default binding or the local binding.
+#
+# ```
+# puts erb.result # Raises NameError.
+# puts erb.result(binding) # Raises NameError.
+# ```
+#
+# This call passes a hash that causes `bar` and `baz` to be defined
+# in a new binding (derived from #new_toplevel):
+#
+# ```
+# hash = {bar: 3, baz: 4}
+# puts erb.result_with_hash(hash)
+# The current value of variable bar is 3.
+# The current value of variable baz is 4.
+# The Ruby copyright is "ruby - Copyright (C) 1993-2025 Yukihiro Matsumoto".
+# The current process is irb.
+# ```
+#
+# ## Tags
+#
+# The examples above use expression tags.
+# These are the tags available in \ERB:
+#
+# - [Expression tag][expression tags]: the tag contains a Ruby expression;
+# in the result, the entire tag is to be replaced with the run-time value of the expression.
+# - [Execution tag][execution tags]: the tag contains Ruby code;
+# in the result, the entire tag is to be replaced with the run-time value of the code.
+# - [Comment tag][comment tags]: the tag contains comment code;
+# in the result, the entire tag is to be omitted.
+#
+# ### Expression Tags
+#
+# You can embed a Ruby expression in a template using an *expression tag*.
+#
+# Its syntax is `<%= _expression_ %>`,
+# where *expression* is any valid Ruby expression.
+#
+# When you call method #result,
+# the method evaluates the expression and replaces the entire expression tag with the expression's value:
+#
+# ```
+# ERB.new('Today is <%= Date::DAYNAMES[Date.today.wday] %>.').result
+# # => "Today is Monday."
+# ERB.new('Tomorrow will be <%= Date::DAYNAMES[Date.today.wday + 1] %>.').result
+# # => "Tomorrow will be Tuesday."
+# ERB.new('Yesterday was <%= Date::DAYNAMES[Date.today.wday - 1] %>.').result
+# # => "Yesterday was Sunday."
+# ```
+#
+# Note that whitespace before and after the expression
+# is allowed but not required,
+# and that such whitespace is stripped from the result.
+#
+# ```
+# ERB.new('My appointment is on <%=Date::DAYNAMES[Date.today.wday + 2]%>.').result
+# # => "My appointment is on Wednesday."
+# ERB.new('My appointment is on <%= Date::DAYNAMES[Date.today.wday + 2] %>.').result
+# # => "My appointment is on Wednesday."
+# ```
+#
+# ### Execution Tags
+#
+# You can embed Ruby executable code in template using an *execution tag*.
+#
+# Its syntax is `<% _code_ %>`,
+# where *code* is any valid Ruby code.
+#
+# When you call method #result,
+# the method executes the code and removes the entire execution tag
+# (generating no text in the result):
+#
+# ```
+# ERB.new('foo <% Dir.chdir("C:/") %> bar').result # => "foo bar"
+# ```
+#
+# Whitespace before and after the embedded code is optional:
+#
+# ```
+# ERB.new('foo <%Dir.chdir("C:/")%> bar').result # => "foo bar"
+# ```
+#
+# You can interleave text with execution tags to form a control structure
+# such as a conditional, a loop, or a `case` statements.
+#
+# Conditional:
+#
+# ```
+# template = <<TEMPLATE
+# <% if verbosity %>
+# An error has occurred.
+# <% else %>
+# Oops!
+# <% end %>
+# TEMPLATE
+# erb = ERB.new(template)
+# verbosity = true
+# erb.result(binding)
+# # => "\nAn error has occurred.\n\n"
+# verbosity = false
+# erb.result(binding)
+# # => "\nOops!\n\n"
+# ```
+#
+# Note that the interleaved text may itself contain expression tags:
+#
+# Loop:
+#
+# ```
+# template = <<TEMPLATE
+# <% Date::ABBR_DAYNAMES.each do |dayname| %>
+# <%= dayname %>
+# <% end %>
+# TEMPLATE
+# ERB.new(template).result
+# # => "\nSun\n\nMon\n\nTue\n\nWed\n\nThu\n\nFri\n\nSat\n\n"
+# ```
+#
+# Other, non-control, lines of Ruby code may be interleaved with the text,
+# and the Ruby code may itself contain regular Ruby comments:
+#
+# ```
+# template = <<TEMPLATE
+# <% 3.times do %>
+# <%= Time.now %>
+# <% sleep(1) # Let's make the times different. %>
+# <% end %>
+# TEMPLATE
+# ERB.new(template).result
+# # => "\n2025-09-09 11:36:02 -0500\n\n\n2025-09-09 11:36:03 -0500\n\n\n2025-09-09 11:36:04 -0500\n\n\n"
+# ```
+#
+# The execution tag may also contain multiple lines of code:
+#
+# ```
+# template = <<TEMPLATE
+# <%
+# (0..2).each do |i|
+# (0..2).each do |j|
+# %>
+# * <%=i%>,<%=j%>
+# <%
+# end
+# end
+# %>
+# TEMPLATE
+# ERB.new(template).result
+# # => "\n* 0,0\n\n* 0,1\n\n* 0,2\n\n* 1,0\n\n* 1,1\n\n* 1,2\n\n* 2,0\n\n* 2,1\n\n* 2,2\n\n"
+# ```
+#
+# #### Shorthand Format for Execution Tags
+#
+# You can use keyword argument `trim_mode: '%'` to enable a shorthand format for execution tags;
+# this example uses the shorthand format `% _code_` instead of `<% _code_ %>`:
+#
+# ```
+# template = <<TEMPLATE
+# % priorities.each do |priority|
+# * <%= priority %>
+# % end
+# TEMPLATE
+# erb = ERB.new(template, trim_mode: '%')
+# priorities = [ 'Run Ruby Quiz',
+# 'Document Modules',
+# 'Answer Questions on Ruby Talk' ]
+# puts erb.result(binding)
+# * Run Ruby Quiz
+# * Document Modules
+# * Answer Questions on Ruby Talk
+# ```
+#
+# Note that in the shorthand format, the character `'%'` must be the first character in the code line
+# (no leading whitespace).
+#
+# #### Suppressing Unwanted Blank Lines
+#
+# With keyword argument `trim_mode` not given,
+# all blank lines go into the result:
+#
+# ```
+# template = <<TEMPLATE
+# <% if true %>
+# <%= RUBY_VERSION %>
+# <% end %>
+# TEMPLATE
+# ERB.new(template).result.lines.each {|line| puts line.inspect }
+# "\n"
+# "3.4.5\n"
+# "\n"
+# ```
+#
+# You can give `trim_mode: '-'`, you can suppress each blank line
+# whose source line ends with `-%>` (instead of `%>`):
+#
+# ```
+# template = <<TEMPLATE
+# <% if true -%>
+# <%= RUBY_VERSION %>
+# <% end -%>
+# TEMPLATE
+# ERB.new(template, trim_mode: '-').result.lines.each {|line| puts line.inspect }
+# "3.4.5\n"
+# ```
+#
+# It is an error to use the trailing `'-%>'` notation without `trim_mode: '-'`:
+#
+# ```
+# ERB.new(template).result.lines.each {|line| puts line.inspect } # Raises SyntaxError.
+# ```
+#
+# #### Suppressing Unwanted Newlines
+#
+# Consider this template:
+#
+# ```
+# template = <<TEMPLATE
+# <% RUBY_VERSION %>
+# <%= RUBY_VERSION %>
+# foo <% RUBY_VERSION %>
+# foo <%= RUBY_VERSION %>
+# TEMPLATE
+# ```
+#
+# With keyword argument `trim_mode` not given, all newlines go into the result:
+#
+# ```
+# ERB.new(template).result.lines.each {|line| puts line.inspect }
+# "\n"
+# "3.4.5\n"
+# "foo \n"
+# "foo 3.4.5\n"
+# ```
+#
+# You can give `trim_mode: '>'` to suppress the trailing newline
+# for each line that ends with `'%>'` (regardless of its beginning):
+#
+# ```
+# ERB.new(template, trim_mode: '>').result.lines.each {|line| puts line.inspect }
+# "3.4.5foo foo 3.4.5"
+# ```
+#
+# You can give `trim_mode: '<>'` to suppress the trailing newline
+# for each line that both begins with `'<%'` and ends with `'%>'`:
+#
+# ```
+# ERB.new(template, trim_mode: '<>').result.lines.each {|line| puts line.inspect }
+# "3.4.5foo \n"
+# "foo 3.4.5\n"
+# ```
+#
+# #### Combining Trim Modes
+#
+# You can combine certain trim modes:
+#
+# - `'%-'`: Enable shorthand and omit each blank line ending with `'-%>'`.
+# - `'%>'`: Enable shorthand and omit newline for each line ending with `'%>'`.
+# - `'%<>'`: Enable shorthand and omit newline for each line starting with `'<%'` and ending with `'%>'`.
+#
+# ### Comment Tags
+#
+# You can embed a comment in a template using a *comment tag*;
+# its syntax is `<%# _text_ %>`,
+# where *text* is the text of the comment.
+#
+# When you call method #result,
+# it removes the entire comment tag
+# (generating no text in the result).
+#
+# Example:
+#
+# ```
+# template = 'Some stuff;<%# Note to self: figure out what the stuff is. %> more stuff.'
+# ERB.new(template).result # => "Some stuff; more stuff."
+# ```
+#
+# A comment tag may appear anywhere in the template.
+#
+# Note that the beginning of the tag must be `'<%#'`, not `'<% #'`.
+#
+# In this example, the tag begins with `'<% #'`, and so is an execution tag, not a comment tag;
+# the cited code consists entirely of a Ruby-style comment (which is of course ignored):
+#
+# ```
+# ERB.new('Some stuff;<% # Note to self: figure out what the stuff is. %> more stuff.').result
+# # => "Some stuff;"
+# ```
+#
+# ## Encodings
+#
+# An \ERB object has an [encoding][encoding],
+# which is by default the encoding of the template string;
+# the result string will also have that encoding.
#
-# James Edward Gray II
-# }.gsub(/^ /, '')
+# ```
+# template = <<TEMPLATE
+# <%# Comment. %>
+# TEMPLATE
+# erb = ERB.new(template)
+# template.encoding # => #<Encoding:UTF-8>
+# erb.encoding # => #<Encoding:UTF-8>
+# erb.result.encoding # => #<Encoding:UTF-8>
+# ```
#
-# message = ERB.new(template, trim_mode: "%<>")
+# You can specify a different encoding by adding a [magic comment][magic comments]
+# at the top of the given template:
#
-# # Set up template data.
-# to = "Community Spokesman <spokesman@ruby_community.org>"
-# priorities = [ "Run Ruby Quiz",
-# "Document Modules",
-# "Answer Questions on Ruby Talk" ]
+# ```
+# template = <<TEMPLATE
+# <%#-*- coding: Big5 -*-%>
+# <%# Comment. %>
+# TEMPLATE
+# erb = ERB.new(template)
+# template.encoding # => #<Encoding:UTF-8>
+# erb.encoding # => #<Encoding:Big5>
+# erb.result.encoding # => #<Encoding:Big5>
+# ```
#
-# # Produce result.
-# email = message.result
-# puts email
+# ## Error Reporting
#
-# <i>Generates:</i>
+# Consider this template (containing an error):
#
-# From: James Edward Gray II <james@grayproductions.net>
-# To: Community Spokesman <spokesman@ruby_community.org>
-# Subject: Addressing Needs
+# ```
+# template = '<%= nosuch %>'
+# erb = ERB.new(template)
+# ```
#
-# Community:
+# When \ERB reports an error,
+# it includes a file name (if available) and a line number;
+# the file name comes from method #filename, the line number from method #lineno.
#
-# Just wanted to send a quick note assuring that your needs are being addressed.
+# Initially, those values are `nil` and `0`, respectively;
+# these initial values are reported as `'(erb)'` and `1`, respectively:
#
-# I want you to know that my team will keep working on the issues, especially:
+# ```
+# erb.filename # => nil
+# erb.lineno # => 0
+# erb.result
+# (erb):1:in '<main>': undefined local variable or method 'nosuch' for main (NameError)
+# ```
#
-# * Run Ruby Quiz
-# * Document Modules
-# * Answer Questions on Ruby Talk
+# You can use methods #filename= and #lineno= to assign values
+# that are more meaningful in your context:
#
-# Thanks for your patience.
+# ```
+# erb.filename = 't.txt'
+# erb.lineno = 555
+# erb.result
+# t.txt:556:in '<main>': undefined local variable or method 'nosuch' for main (NameError)
+# ```
#
-# James Edward Gray II
+# You can use method #location= to set both values:
#
-# === Ruby in HTML
+# ```
+# erb.location = ['u.txt', 999]
+# erb.result
+# u.txt:1000:in '<main>': undefined local variable or method 'nosuch' for main (NameError)
+# ```
#
-# ERB is often used in <tt>.rhtml</tt> files (HTML with embedded Ruby). Notice the need in
-# this example to provide a special binding when the template is run, so that the instance
-# variables in the Product object can be resolved.
+# ## Plain Text with Embedded Ruby
#
-# require "erb"
+# Here's a plain-text template;
+# it uses the literal notation `'%q{ ... }'` to define the template
+# (see [%q literals][%q literals]);
+# this avoids problems with backslashes.
#
-# # Build template data class.
-# class Product
-# def initialize( code, name, desc, cost )
-# @code = code
-# @name = name
-# @desc = desc
-# @cost = cost
+# ```
+# template = %q{
+# From: James Edward Gray II <james@grayproductions.net>
+# To: <%= to %>
+# Subject: Addressing Needs
#
-# @features = [ ]
-# end
+# <%= to[/\w+/] %>:
#
-# def add_feature( feature )
-# @features << feature
-# end
+# Just wanted to send a quick note assuring that your needs are being
+# addressed.
#
-# # Support templating of member data.
-# def get_binding
-# binding
-# end
+# I want you to know that my team will keep working on the issues,
+# especially:
#
-# # ...
-# end
+# <%# ignore numerous minor requests -- focus on priorities %>
+# % priorities.each do |priority|
+# * <%= priority %>
+# % end
#
-# # Create template.
-# template = %{
-# <html>
-# <head><title>Ruby Toys -- <%= @name %></title></head>
-# <body>
+# Thanks for your patience.
#
-# <h1><%= @name %> (<%= @code %>)</h1>
-# <p><%= @desc %></p>
+# James Edward Gray II
+# }
+# ```
#
-# <ul>
-# <% @features.each do |f| %>
-# <li><b><%= f %></b></li>
-# <% end %>
-# </ul>
+# The template will need these:
#
-# <p>
-# <% if @cost < 10 %>
-# <b>Only <%= @cost %>!!!</b>
-# <% else %>
-# Call for a price, today!
-# <% end %>
-# </p>
+# ```
+# to = 'Community Spokesman <spokesman@ruby_community.org>'
+# priorities = [ 'Run Ruby Quiz',
+# 'Document Modules',
+# 'Answer Questions on Ruby Talk' ]
+# ```
#
-# </body>
-# </html>
-# }.gsub(/^ /, '')
+# Finally, create the \ERB object and get the result
#
-# rhtml = ERB.new(template)
+# ```
+# erb = ERB.new(template, trim_mode: '%<>')
+# puts erb.result(binding)
#
-# # Set up template data.
-# toy = Product.new( "TZ-1002",
-# "Rubysapien",
-# "Geek's Best Friend! Responds to Ruby commands...",
-# 999.95 )
-# toy.add_feature("Listens for verbal commands in the Ruby language!")
-# toy.add_feature("Ignores Perl, Java, and all C variants.")
-# toy.add_feature("Karate-Chop Action!!!")
-# toy.add_feature("Matz signature on left leg.")
-# toy.add_feature("Gem studded eyes... Rubies, of course!")
+# From: James Edward Gray II <james@grayproductions.net>
+# To: Community Spokesman <spokesman@ruby_community.org>
+# Subject: Addressing Needs
#
-# # Produce result.
-# rhtml.run(toy.get_binding)
+# Community:
#
-# <i>Generates (some blank lines removed):</i>
+# Just wanted to send a quick note assuring that your needs are being
+# addressed.
#
-# <html>
-# <head><title>Ruby Toys -- Rubysapien</title></head>
-# <body>
+# I want you to know that my team will keep working on the issues,
+# especially:
#
-# <h1>Rubysapien (TZ-1002)</h1>
-# <p>Geek's Best Friend! Responds to Ruby commands...</p>
+# * Run Ruby Quiz
+# * Document Modules
+# * Answer Questions on Ruby Talk
#
-# <ul>
-# <li><b>Listens for verbal commands in the Ruby language!</b></li>
-# <li><b>Ignores Perl, Java, and all C variants.</b></li>
-# <li><b>Karate-Chop Action!!!</b></li>
-# <li><b>Matz signature on left leg.</b></li>
-# <li><b>Gem studded eyes... Rubies, of course!</b></li>
-# </ul>
+# Thanks for your patience.
#
-# <p>
-# Call for a price, today!
-# </p>
+# James Edward Gray II
+# ```
#
-# </body>
-# </html>
+# ## HTML with Embedded Ruby
#
+# This example shows an HTML template.
#
-# == Notes
+# First, here's a custom class, `Product`:
#
-# There are a variety of templating solutions available in various Ruby projects.
-# For example, RDoc, distributed with Ruby, uses its own template engine, which
-# can be reused elsewhere.
+# ```
+# class Product
+# def initialize(code, name, desc, cost)
+# @code = code
+# @name = name
+# @desc = desc
+# @cost = cost
+# @features = []
+# end
#
-# Other popular engines could be found in the corresponding
-# {Category}[https://www.ruby-toolbox.com/categories/template_engines] of
-# The Ruby Toolbox.
+# def add_feature(feature)
+# @features << feature
+# end
+#
+# # Support templating of member data.
+# def get_binding
+# binding
+# end
+#
+# end
+# ```
+#
+# The template below will need these values:
+#
+# ```
+# toy = Product.new('TZ-1002',
+# 'Rubysapien',
+# "Geek's Best Friend! Responds to Ruby commands...",
+# 999.95
+# )
+# toy.add_feature('Listens for verbal commands in the Ruby language!')
+# toy.add_feature('Ignores Perl, Java, and all C variants.')
+# toy.add_feature('Karate-Chop Action!!!')
+# toy.add_feature('Matz signature on left leg.')
+# toy.add_feature('Gem studded eyes... Rubies, of course!')
+# ```
+#
+# Here's the HTML:
+#
+# ```
+# template = <<TEMPLATE
+# <html>
+# <head><title>Ruby Toys -- <%= @name %></title></head>
+# <body>
+# <h1><%= @name %> (<%= @code %>)</h1>
+# <p><%= @desc %></p>
+# <ul>
+# <% @features.each do |f| %>
+# <li><b><%= f %></b></li>
+# <% end %>
+# </ul>
+# <p>
+# <% if @cost < 10 %>
+# <b>Only <%= @cost %>!!!</b>
+# <% else %>
+# Call for a price, today!
+# <% end %>
+# </p>
+# </body>
+# </html>
+# TEMPLATE
+# ```
+#
+# Finally, create the \ERB object and get the result (omitting some blank lines):
+#
+# ```
+# erb = ERB.new(template)
+# puts erb.result(toy.get_binding)
+# <html>
+# <head><title>Ruby Toys -- Rubysapien</title></head>
+# <body>
+# <h1>Rubysapien (TZ-1002)</h1>
+# <p>Geek's Best Friend! Responds to Ruby commands...</p>
+# <ul>
+# <li><b>Listens for verbal commands in the Ruby language!</b></li>
+# <li><b>Ignores Perl, Java, and all C variants.</b></li>
+# <li><b>Karate-Chop Action!!!</b></li>
+# <li><b>Matz signature on left leg.</b></li>
+# <li><b>Gem studded eyes... Rubies, of course!</b></li>
+# </ul>
+# <p>
+# Call for a price, today!
+# </p>
+# </body>
+# </html>
+# ```
+#
+#
+# ## Other Template Processors
+#
+# Various Ruby projects have their own template processors.
+# The Ruby Processing System [RDoc][rdoc], for example, has one that can be used elsewhere.
+#
+# Other popular template processors may found in the [Template Engines][template engines] page
+# of the Ruby Toolbox.
+#
+# [%q literals]: https://docs.ruby-lang.org/en/master/syntax/literals_rdoc.html#label-25q-3A+Non-Interpolable+String+Literals
+# [augmented binding]: rdoc-ref:ERB@Augmented+Binding
+# [binding object]: https://docs.ruby-lang.org/en/master/Binding.html
+# [comment tags]: rdoc-ref:ERB@Comment+Tags
+# [default binding]: rdoc-ref:ERB@Default+Binding
+# [encoding]: https://docs.ruby-lang.org/en/master/Encoding.html
+# [execution tags]: rdoc-ref:ERB@Execution+Tags
+# [expression tags]: rdoc-ref:ERB@Expression+Tags
+# [kernel#binding]: https://docs.ruby-lang.org/en/master/Kernel.html#method-i-binding
+# [local binding]: rdoc-ref:ERB@Local+Binding
+# [magic comments]: https://docs.ruby-lang.org/en/master/syntax/comments_rdoc.html#label-Magic+Comments
+# [rdoc]: https://ruby.github.io/rdoc
+# [sprintf]: https://docs.ruby-lang.org/en/master/Kernel.html#method-i-sprintf
+# [template engines]: https://www.ruby-toolbox.com/categories/template_engines
+# [template processor]: https://en.wikipedia.org/wiki/Template_processor
#
class ERB
- Revision = '$Date:: $' # :nodoc: #'
- deprecate_constant :Revision
-
- # Returns revision information for the erb.rb module.
+ # :markup: markdown
+ #
+ # :call-seq:
+ # self.version -> string
+ #
+ # Returns the string \ERB version.
def self.version
VERSION
end
+ # :markup: markdown
#
- # Constructs a new ERB object with the template specified in _str_.
+ # :call-seq:
+ # ERB.new(template, trim_mode: nil, eoutvar: '_erbout')
#
- # An ERB object works by building a chunk of Ruby code that will output
- # the completed template when run.
+ # Returns a new \ERB object containing the given string +template+.
#
- # If _trim_mode_ is passed a String containing one or more of the following
- # modifiers, ERB will adjust its code generation as listed:
+ # For details about `template`, its embedded tags, and generated results, see ERB.
#
- # % enables Ruby code processing for lines beginning with %
- # <> omit newline for lines starting with <% and ending in %>
- # > omit newline for lines ending in %>
- # - omit blank lines ending in -%>
+ # **Keyword Argument `trim_mode`**
#
- # _eoutvar_ can be used to set the name of the variable ERB will build up
- # its output in. This is useful when you need to run multiple ERB
- # templates through the same binding and/or when you want to control where
- # output ends up. Pass the name of the variable to be used inside a String.
+ # You can use keyword argument `trim_mode: '%'`
+ # to enable the [shorthand format][shorthand format] for execution tags.
#
- # === Example
+ # This value allows [blank line control][blank line control]:
#
- # require "erb"
+ # - `'-'`: Omit each blank line ending with `'%>'`.
#
- # # build data class
- # class Listings
- # PRODUCT = { :name => "Chicken Fried Steak",
- # :desc => "A well messages pattie, breaded and fried.",
- # :cost => 9.95 }
+ # Other values allow [newline control][newline control]:
#
- # attr_reader :product, :price
+ # - `'>'`: Omit newline for each line ending with `'%>'`.
+ # - `'<>'`: Omit newline for each line starting with `'<%'` and ending with `'%>'`.
#
- # def initialize( product = "", price = "" )
- # @product = product
- # @price = price
- # end
+ # You can also [combine trim modes][combine trim modes].
#
- # def build
- # b = binding
- # # create and run templates, filling member data variables
- # ERB.new(<<~'END_PRODUCT', trim_mode: "", eoutvar: "@product").result b
- # <%= PRODUCT[:name] %>
- # <%= PRODUCT[:desc] %>
- # END_PRODUCT
- # ERB.new(<<~'END_PRICE', trim_mode: "", eoutvar: "@price").result b
- # <%= PRODUCT[:name] %> -- <%= PRODUCT[:cost] %>
- # <%= PRODUCT[:desc] %>
- # END_PRICE
- # end
- # end
+ # **Keyword Argument `eoutvar`**
#
- # # setup template data
- # listings = Listings.new
- # listings.build
+ # The string value of keyword argument `eoutvar` specifies the name of the variable
+ # that method #result uses to construct its result string;
+ # see #src.
#
- # puts listings.product + "\n" + listings.price
+ # This is useful when you need to run multiple \ERB templates through the same binding
+ # and/or when you want to control where output ends up.
#
- # _Generates_
+ # It's good practice to choose a variable name that begins with an underscore: `'_'`.
#
- # Chicken Fried Steak
- # A well messages pattie, breaded and fried.
+ # [blank line control]: rdoc-ref:ERB@Suppressing+Unwanted+Blank+Lines
+ # [combine trim modes]: rdoc-ref:ERB@Combining+Trim+Modes
+ # [newline control]: rdoc-ref:ERB@Suppressing+Unwanted+Newlines
+ # [shorthand format]: rdoc-ref:ERB@Shorthand+Format+for+Execution+Tags
#
- # Chicken Fried Steak -- 9.95
- # A well messages pattie, breaded and fried.
- #
- def initialize(str, safe_level=NOT_GIVEN, legacy_trim_mode=NOT_GIVEN, legacy_eoutvar=NOT_GIVEN, trim_mode: nil, eoutvar: '_erbout')
- # Complex initializer for $SAFE deprecation at [Feature #14256]. Use keyword arguments to pass trim_mode or eoutvar.
- 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
- 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
- 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
- eoutvar = legacy_eoutvar
- end
-
+ def initialize(str, trim_mode: nil, eoutvar: '_erbout')
compiler = make_compiler(trim_mode)
set_eoutvar(compiler, eoutvar)
@src, @encoding, @frozen_string = *compiler.compile(str)
@@ -353,54 +837,137 @@ class ERB
@lineno = 0
@_init = self.class.singleton_class
end
- NOT_GIVEN = Object.new
- private_constant :NOT_GIVEN
-
- ##
- # Creates a new compiler for ERB. See ERB::Compiler.new for details
+ # :markup: markdown
+ #
+ # :call-seq:
+ # make_compiler -> erb_compiler
+ #
+ # Returns a new ERB::Compiler with the given `trim_mode`;
+ # for `trim_mode` values, see ERB.new:
+ #
+ # ```
+ # ERB.new('').make_compiler(nil)
+ # # => #<ERB::Compiler:0x000001cff9467678 @insert_cmd="print", @percent=false, @post_cmd=[], @pre_cmd=[], @put_cmd="print", @trim_mode=nil>
+ # ```
+ #
def make_compiler(trim_mode)
ERB::Compiler.new(trim_mode)
end
- # The Ruby code generated by ERB
+ # :markup: markdown
+ #
+ # Returns the Ruby code that, when executed, generates the result;
+ # the code is executed by method #result,
+ # and by its wrapper methods #result_with_hash and #run:
+ #
+ # ```
+ # template = 'The time is <%= Time.now %>.'
+ # erb = ERB.new(template)
+ # erb.src
+ # # => "#coding:UTF-8\n_erbout = +''; _erbout.<< \"The time is \".freeze; _erbout.<<(( Time.now ).to_s); _erbout.<< \".\".freeze; _erbout"
+ # erb.result
+ # # => "The time is 2025-09-18 15:58:08 -0500."
+ # ```
+ #
+ # In a more readable format:
+ #
+ # ```
+ # # puts erb.src.split('; ')
+ # # #coding:UTF-8
+ # # _erbout = +''
+ # # _erbout.<< "The time is ".freeze
+ # # _erbout.<<(( Time.now ).to_s)
+ # # _erbout.<< ".".freeze
+ # # _erbout
+ # ```
+ #
+ # Variable `_erbout` is used to store the intermediate results in the code;
+ # the name `_erbout` is the default in ERB.new,
+ # and can be changed via keyword argument `eoutvar`:
+ #
+ # ```
+ # erb = ERB.new(template, eoutvar: '_foo')
+ # puts template.src.split('; ')
+ # #coding:UTF-8
+ # _foo = +''
+ # _foo.<< "The time is ".freeze
+ # _foo.<<(( Time.now ).to_s)
+ # _foo.<< ".".freeze
+ # _foo
+ # ```
+ #
attr_reader :src
- # The encoding to eval
+ # :markup: markdown
+ #
+ # Returns the encoding of `self`;
+ # see [Encodings][encodings]:
+ #
+ # [encodings]: rdoc-ref:ERB@Encodings
+ #
attr_reader :encoding
- # The optional _filename_ argument passed to Kernel#eval when the ERB code
- # is run
+ # :markup: markdown
+ #
+ # Sets or returns the file name to be used in reporting errors;
+ # see [Error Reporting][error reporting].
+ #
+ # [error reporting]: rdoc-ref:ERB@Error+Reporting
attr_accessor :filename
- # The optional _lineno_ argument passed to Kernel#eval when the ERB code
- # is run
+ # :markup: markdown
+ #
+ # Sets or returns the line number to be used in reporting errors;
+ # see [Error Reporting][error reporting].
+ #
+ # [error reporting]: rdoc-ref:ERB@Error+Reporting
attr_accessor :lineno
+ # :markup: markdown
#
- # Sets optional filename and line number that will be used in ERB code
- # evaluation and error reporting. See also #filename= and #lineno=
- #
- # erb = ERB.new('<%= some_x %>')
- # erb.render
- # # undefined local variable or method `some_x'
- # # from (erb):1
+ # :call-seq:
+ # location = [filename, lineno] => [filename, lineno]
+ # location = filename -> filename
#
- # erb.location = ['file.erb', 3]
- # # All subsequent error reporting would use new location
- # erb.render
- # # undefined local variable or method `some_x'
- # # from file.erb:4
+ # Sets the values of #filename and, if given, #lineno;
+ # see [Error Reporting][error reporting].
#
+ # [error reporting]: rdoc-ref:ERB@Error+Reporting
def location=((filename, lineno))
@filename = filename
@lineno = lineno if lineno
end
+ # :markup: markdown
#
- # Can be used to set _eoutvar_ as described in ERB::new. It's probably
- # easier to just use the constructor though, since calling this method
- # requires the setup of an ERB _compiler_ object.
+ # :call-seq:
+ # set_eoutvar(compiler, eoutvar = '_erbout') -> [eoutvar]
+ #
+ # Sets the `eoutvar` value in the ERB::Compiler object `compiler`;
+ # returns a 1-element array containing the value of `eoutvar`:
+ #
+ # ```
+ # template = ERB.new('')
+ # compiler = template.make_compiler(nil)
+ # pp compiler
+ # #<ERB::Compiler:0x000001cff8a9aa00
+ # @insert_cmd="print",
+ # @percent=false,
+ # @post_cmd=[],
+ # @pre_cmd=[],
+ # @put_cmd="print",
+ # @trim_mode=nil>
+ # template.set_eoutvar(compiler, '_foo') # => ["_foo"]
+ # pp compiler
+ # #<ERB::Compiler:0x000001cff8a9aa00
+ # @insert_cmd="_foo.<<",
+ # @percent=false,
+ # @post_cmd=["_foo"],
+ # @pre_cmd=["_foo = +''"],
+ # @put_cmd="_foo.<<",
+ # @trim_mode=nil>
+ # ```
#
def set_eoutvar(compiler, eoutvar = '_erbout')
compiler.put_cmd = "#{eoutvar}.<<"
@@ -409,18 +976,34 @@ class ERB
compiler.post_cmd = [eoutvar]
end
- # Generate results and print them. (see ERB#result)
+ # :markup: markdown
+ #
+ # :call-seq:
+ # run(binding = new_toplevel) -> nil
+ #
+ # Like #result, but prints the result string (instead of returning it);
+ # returns `nil`.
def run(b=new_toplevel)
print self.result(b)
end
+ # :markup: markdown
+ #
+ # :call-seq:
+ # result(binding = new_toplevel) -> new_string
+ #
+ # Returns the string result formed by processing \ERB tags found in the stored template in `self`.
+ #
+ # With no argument given, uses the default binding;
+ # see [Default Binding][default binding].
+ #
+ # With argument `binding` given, uses the local binding;
+ # see [Local Binding][local binding].
#
- # Executes the generated ERB code to produce a completed template, returning
- # the results of that code. (See ERB::new for details on how this process
- # can be affected by _safe_level_.)
+ # See also #result_with_hash.
#
- # _b_ accepts a Binding object which is used to set the context of
- # code evaluation.
+ # [default binding]: rdoc-ref:ERB@Default+Binding
+ # [local binding]: rdoc-ref:ERB@Local+Binding
#
def result(b=new_toplevel)
unless @_init.equal?(self.class.singleton_class)
@@ -429,8 +1012,18 @@ class ERB
eval(@src, b, (@filename || '(erb)'), @lineno)
end
- # Render a template on a new toplevel binding with local variables specified
- # by a Hash object.
+ # :markup: markdown
+ #
+ # :call-seq:
+ # result_with_hash(hash) -> new_string
+ #
+ # Returns the string result formed by processing \ERB tags found in the stored string in `self`;
+ # see [Augmented Binding][augmented binding].
+ #
+ # See also #result.
+ #
+ # [augmented binding]: rdoc-ref:ERB@Augmented+Binding
+ #
def result_with_hash(hash)
b = new_toplevel(hash.keys)
hash.each_pair do |key, value|
@@ -439,10 +1032,22 @@ class ERB
result(b)
end
- ##
- # Returns a new binding each time *near* TOPLEVEL_BINDING for runs that do
- # not specify a binding.
-
+ # :markup: markdown
+ #
+ # :call-seq:
+ # new_toplevel(symbols) -> new_binding
+ #
+ # Returns a new binding based on `TOPLEVEL_BINDING`;
+ # used to create a default binding for a call to #result.
+ #
+ # See [Default Binding][default binding].
+ #
+ # Argument `symbols` is an array of symbols;
+ # each symbol `symbol` is defined as a new variable to hide and
+ # prevent it from overwriting a variable of the same name already
+ # defined within the binding.
+ #
+ # [default binding]: rdoc-ref:ERB@Default+Binding
def new_toplevel(vars = nil)
b = TOPLEVEL_BINDING
if vars
@@ -455,13 +1060,31 @@ class ERB
end
private :new_toplevel
- # Define _methodname_ as instance method of _mod_ from compiled Ruby source.
+ # :markup: markdown
+ #
+ # :call-seq:
+ # def_method(module, method_signature, filename = '(ERB)') -> method_name
+ #
+ # Creates and returns a new instance method in the given module `module`;
+ # returns the method name as a symbol.
+ #
+ # The method is created from the given `method_signature`,
+ # which consists of the method name and its argument names (if any).
+ #
+ # The `filename` sets the value of #filename;
+ # see [Error Reporting][error reporting].
+ #
+ # [error reporting]: rdoc-ref:ERB@Error+Reporting
+ #
+ # ```
+ # template = '<%= arg1 %> <%= arg2 %>'
+ # erb = ERB.new(template)
+ # MyModule = Module.new
+ # erb.def_method(MyModule, 'render(arg1, arg2)') # => :render
+ # class MyClass; include MyModule; end
+ # MyClass.new.render('foo', 123) # => "foo 123"
+ # ```
#
- # example:
- # filename = 'example.rhtml' # 'arg1' and 'arg2' are used in example.rhtml
- # erb = ERB.new(File.read(filename))
- # erb.def_method(MyClass, 'render(arg1, arg2)', filename)
- # print MyClass.new.render('foo', 123)
def def_method(mod, methodname, fname='(ERB)')
src = self.src.sub(/^(?!#|$)/) {"def #{methodname}\n"} << "\nend\n"
mod.module_eval do
@@ -469,35 +1092,81 @@ class ERB
end
end
- # Create unnamed module, define _methodname_ as instance method of it, and return it.
- #
- # example:
- # filename = 'example.rhtml' # 'arg1' and 'arg2' are used in example.rhtml
- # erb = ERB.new(File.read(filename))
- # erb.filename = filename
- # MyModule = erb.def_module('render(arg1, arg2)')
- # class MyClass
- # include MyModule
- # end
+ # :markup: markdown
+ #
+ # :call-seq:
+ # def_module(method_name = 'erb') -> new_module
+ #
+ # Returns a new nameless module that has instance method `method_name`.
+ #
+ # ```
+ # template = '<%= arg1 %> <%= arg2 %>'
+ # erb = ERB.new(template)
+ # MyModule = template.def_module('render(arg1, arg2)')
+ # class MyClass
+ # include MyModule
+ # end
+ # MyClass.new.render('foo', 123)
+ # # => "foo 123"
+ # ```
+ #
def def_module(methodname='erb')
mod = Module.new
def_method(mod, methodname, @filename || '(ERB)')
mod
end
- # Define unnamed class which has _methodname_ as instance method, and return it.
+ # :markup: markdown
#
- # example:
- # class MyClass_
- # def initialize(arg1, arg2)
- # @arg1 = arg1; @arg2 = arg2
- # end
+ # :call-seq:
+ # def_class(super_class = Object, method_name = 'result') -> new_class
+ #
+ # Returns a new nameless class whose superclass is `super_class`,
+ # and which has instance method `method_name`.
+ #
+ # Create a template from HTML that has embedded expression tags that use `@arg1` and `@arg2`:
+ #
+ # ```
+ # html = <<TEMPLATE
+ # <html>
+ # <body>
+ # <p><%= @arg1 %></p>
+ # <p><%= @arg2 %></p>
+ # </body>
+ # </html>
+ # TEMPLATE
+ # template = ERB.new(html)
+ # ```
+ #
+ # Create a base class that has `@arg1` and `@arg2`:
+ #
+ # ```
+ # class MyBaseClass
+ # def initialize(arg1, arg2)
+ # @arg1 = arg1
+ # @arg2 = arg2
# end
- # filename = 'example.rhtml' # @arg1 and @arg2 are used in example.rhtml
- # erb = ERB.new(File.read(filename))
- # erb.filename = filename
- # MyClass = erb.def_class(MyClass_, 'render()')
- # print MyClass.new('foo', 123).render()
+ # end
+ # ```
+ #
+ # Use method #def_class to create a subclass that has method `:render`:
+ #
+ # ```
+ # MySubClass = template.def_class(MyBaseClass, :render)
+ # ```
+ #
+ # Generate the result:
+ #
+ # ```
+ # puts MySubClass.new('foo', 123).render
+ # <html>
+ # <body>
+ # <p>foo</p>
+ # <p>123</p>
+ # </body>
+ # </html>
+ # ```
+ #
def def_class(superklass=Object, methodname='result')
cls = Class.new(superklass)
def_method(cls, methodname, @filename || '(ERB)')
diff --git a/lib/erb/compiler.rb b/lib/erb/compiler.rb
index 7096c8dcea..6d70288b4f 100644
--- a/lib/erb/compiler.rb
+++ b/lib/erb/compiler.rb
@@ -80,10 +80,16 @@ class ERB::Compiler # :nodoc:
end
class Scanner # :nodoc:
- @scanner_map = {}
+ @scanner_map = defined?(Ractor) ? Ractor.make_shareable({}) : {}
class << self
- def register_scanner(klass, trim_mode, percent)
- @scanner_map[[trim_mode, percent]] = klass
+ if defined?(Ractor)
+ def register_scanner(klass, trim_mode, percent)
+ @scanner_map = Ractor.make_shareable({ **@scanner_map, [trim_mode, percent] => klass })
+ end
+ else
+ def register_scanner(klass, trim_mode, percent)
+ @scanner_map[[trim_mode, percent]] = klass
+ end
end
alias :regist_scanner :register_scanner
end
@@ -219,7 +225,7 @@ class ERB::Compiler # :nodoc:
end
end
- ERB_STAG = %w(<%= <%# <%)
+ ERB_STAG = %w(<%= <%# <%).freeze
def is_erb_stag?(s)
ERB_STAG.member?(s)
end
@@ -466,7 +472,16 @@ class ERB::Compiler # :nodoc:
return enc, frozen
end
+ # :stopdoc:
+ WARNING_UPLEVEL = Class.new {
+ attr_reader :c
+ def initialize from
+ @c = caller.length - from.length
+ end
+ }.new(caller(0)).c
+ private_constant :WARNING_UPLEVEL
+
def warn_invalid_trim_mode(mode, uplevel:)
- warn "Invalid ERB trim mode: #{mode.inspect} (trim_mode: nil, 0, 1, 2, or String composed of '%' and/or '-', '>', '<>')", uplevel: uplevel + 1
+ warn "Invalid ERB trim mode: #{mode.inspect} (trim_mode: nil, 0, 1, 2, or String composed of '%' and/or '-', '>', '<>')", uplevel: uplevel + WARNING_UPLEVEL
end
end
diff --git a/lib/erb/def_method.rb b/lib/erb/def_method.rb
index aee989a926..e503b37140 100644
--- a/lib/erb/def_method.rb
+++ b/lib/erb/def_method.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-#--
+
# ERB::DefMethod
#
# Utility module to define eRuby script as instance method.
diff --git a/lib/erb/erb.gemspec b/lib/erb/erb.gemspec
new file mode 100644
index 0000000000..3793e5d70f
--- /dev/null
+++ b/lib/erb/erb.gemspec
@@ -0,0 +1,37 @@
+begin
+ require_relative 'lib/erb/version'
+rescue LoadError
+ # for Ruby core repository
+ require_relative 'version'
+end
+
+Gem::Specification.new do |spec|
+ spec.name = 'erb'
+ spec.version = ERB::VERSION
+ spec.authors = ['Masatoshi SEKI', 'Takashi Kokubun']
+ spec.email = ['seki@ruby-lang.org', 'k0kubun@ruby-lang.org']
+
+ spec.summary = %q{An easy to use but powerful templating system for Ruby.}
+ spec.description = %q{An easy to use but powerful templating system for Ruby.}
+ spec.homepage = 'https://github.com/ruby/erb'
+ spec.licenses = ['Ruby', 'BSD-2-Clause']
+
+ spec.metadata['homepage_uri'] = spec.homepage
+ spec.metadata['source_code_uri'] = spec.homepage
+ spec.metadata['changelog_uri'] = "https://github.com/ruby/erb/blob/v#{spec.version}/NEWS.md"
+
+ 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.required_ruby_version = '>= 3.2.0'
+
+ if RUBY_ENGINE == 'jruby'
+ spec.platform = 'java'
+ else
+ spec.extensions = ['ext/erb/escape/extconf.rb']
+ end
+end
diff --git a/lib/erb/util.rb b/lib/erb/util.rb
index 1d2a36275d..d7d69eb4f1 100644
--- a/lib/erb/util.rb
+++ b/lib/erb/util.rb
@@ -1,18 +1,25 @@
# frozen_string_literal: true
-#--
-# ERB::Escape
-#
-# A subset of ERB::Util. Unlike ERB::Util#html_escape, we expect/hope
-# Rails will not monkey-patch ERB::Escape#html_escape.
+
+# Load CGI.escapeHTML and CGI.escapeURIComponent.
+# CRuby:
+# cgi.gem v0.1.0+ (Ruby 2.7-3.4) and Ruby 4.0+ stdlib have 'cgi/escape' and CGI.escapeHTML.
+# cgi.gem v0.3.3+ (Ruby 3.2-3.4) and Ruby 4.0+ stdlib have CGI.escapeURIComponent.
+# JRuby: cgi.gem has a Java extension 'cgi/escape'.
+# TruffleRuby: lib/truffle/cgi/escape.rb requires 'cgi/util'.
+require 'cgi/escape'
+
+# Load or define ERB::Escape#html_escape.
+# We don't build the C extension 'cgi/escape' for JRuby, TruffleRuby, and WASM.
+# miniruby (used by CRuby build scripts) also fails to load erb/escape.so.
begin
- # We don't build the C extension for JRuby, TruffleRuby, and WASM
- if $LOAD_PATH.resolve_feature_path('erb/escape')
- require 'erb/escape'
- end
-rescue LoadError # resolve_feature_path raises LoadError on TruffleRuby 22.3.0
-end
-unless defined?(ERB::Escape)
+ require 'erb/escape'
+rescue LoadError
+ # ERB::Escape
+ #
+ # A subset of ERB::Util. Unlike ERB::Util#html_escape, we expect/hope
+ # Rails will not monkey-patch ERB::Escape#html_escape.
module ERB::Escape
+ # :stopdoc:
def html_escape(s)
CGI.escapeHTML(s.to_s)
end
@@ -20,7 +27,6 @@ unless defined?(ERB::Escape)
end
end
-#--
# ERB::Util
#
# A utility module for conversion routines, often handy in HTML generation.
@@ -42,20 +48,28 @@ module ERB::Util
alias h html_escape
module_function :h
- #
- # A utility method for encoding the String _s_ as a URL.
- #
- # require "erb"
- # include ERB::Util
- #
- # puts url_encode("Programming Ruby: The Pragmatic Programmer's Guide")
- #
- # _Generates_
- #
- # Programming%20Ruby%3A%20%20The%20Pragmatic%20Programmer%27s%20Guide
- #
- def url_encode(s)
- CGI.escapeURIComponent(s.to_s)
+ if CGI.respond_to?(:escapeURIComponent)
+ #
+ # A utility method for encoding the String _s_ as a URL.
+ #
+ # require "erb"
+ # include ERB::Util
+ #
+ # puts url_encode("Programming Ruby: The Pragmatic Programmer's Guide")
+ #
+ # _Generates_
+ #
+ # Programming%20Ruby%3A%20%20The%20Pragmatic%20Programmer%27s%20Guide
+ #
+ def url_encode(s)
+ CGI.escapeURIComponent(s.to_s)
+ end
+ else # cgi.gem <= v0.3.2
+ def url_encode(s)
+ s.to_s.b.gsub(/[^a-zA-Z0-9_\-.~]/n) do |m|
+ sprintf("%%%02X", m.unpack1("C"))
+ end
+ end
end
alias u url_encode
module_function :u
diff --git a/lib/erb/version.rb b/lib/erb/version.rb
index b5fe39b330..e367a1b5c7 100644
--- a/lib/erb/version.rb
+++ b/lib/erb/version.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
class ERB
- VERSION = '4.0.4'
- private_constant :VERSION
+ # The string \ERB version.
+ VERSION = '6.0.1'
end
diff --git a/lib/error_highlight/base.rb b/lib/error_highlight/base.rb
index b9c68b8eb8..bc4a62c9d6 100644
--- a/lib/error_highlight/base.rb
+++ b/lib/error_highlight/base.rb
@@ -1,13 +1,13 @@
require_relative "version"
module ErrorHighlight
- # Identify the code fragment at that a given exception occurred.
+ # Identify the code fragment where a given exception occurred.
#
# Options:
#
# point_type: :name | :args
- # :name (default) points the method/variable name that the exception occurred.
- # :args points the arguments of the method call that the exception occurred.
+ # :name (default) points to the method/variable name where the exception occurred.
+ # :args points to the arguments of the method call where the exception occurred.
#
# backtrace_location: Thread::Backtrace::Location
# It locates the code fragment of the given backtrace_location.
@@ -60,14 +60,14 @@ module ErrorHighlight
rescue RuntimeError => error
# RubyVM::AbstractSyntaxTree.of raises an error with a message that
# includes "prism" when the ISEQ was compiled with the prism compiler.
- # In this case, we'll set the node to `nil`. In the future, we will
- # reparse with the prism parser and pass the parsed node to Spotter.
+ # In this case, we'll try to parse again with prism instead.
raise unless error.message.include?("prism")
+ prism_find(loc)
end
Spotter.new(node, **opts).spot
- when RubyVM::AbstractSyntaxTree::Node
+ when RubyVM::AbstractSyntaxTree::Node, Prism::Node
Spotter.new(obj, **opts).spot
else
@@ -81,6 +81,21 @@ module ErrorHighlight
return nil
end
+ # Accepts a Thread::Backtrace::Location object and returns a Prism::Node
+ # corresponding to the backtrace location in the source code.
+ def self.prism_find(location)
+ require "prism"
+ return nil if Prism::VERSION < "1.0.0"
+
+ absolute_path = location.absolute_path
+ return unless absolute_path
+
+ node_id = RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(location)
+ Prism.parse_file(absolute_path).value.breadth_first_search { |node| node.node_id == node_id }
+ end
+
+ private_class_method :prism_find
+
class Spotter
class NonAscii < Exception; end
private_constant :NonAscii
@@ -98,7 +113,7 @@ module ErrorHighlight
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.
+ # It requires 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?
@@ -107,19 +122,17 @@ module ErrorHighlight
end
end
- OPT_GETCONSTANT_PATH = (RUBY_VERSION.split(".").map {|s| s.to_i } <=> [3, 2]) >= 0
- private_constant :OPT_GETCONSTANT_PATH
-
def spot
return nil unless @node
- if OPT_GETCONSTANT_PATH && @node.type == :COLON2
- # In Ruby 3.2 or later, a nested constant access (like `Foo::Bar::Baz`)
- # is compiled to one instruction (opt_getconstant_path).
- # @node points to the node of the whole `Foo::Bar::Baz` even if `Foo`
- # or `Foo::Bar` causes NameError.
- # So we try to spot the sub-node that causes the NameError by using
- # `NameError#name`.
+ # In Ruby 3.2 or later, a nested constant access (like `Foo::Bar::Baz`)
+ # is compiled to one instruction (opt_getconstant_path).
+ # @node points to the node of the whole `Foo::Bar::Baz` even if `Foo`
+ # or `Foo::Bar` causes NameError.
+ # So we try to spot the sub-node that causes the NameError by using
+ # `NameError#name`.
+ case @node.type
+ when :COLON2
subnodes = []
node = @node
while node.type == :COLON2
@@ -139,6 +152,21 @@ module ErrorHighlight
# Do nothing; opt_getconstant_path is used only when the const base is
# NODE_CONST (`Foo`) or NODE_COLON3 (`::Foo`)
end
+ when :constant_path_node
+ subnodes = []
+ node = @node
+
+ begin
+ subnodes << node if node.name == @name
+ end while (node = node.parent).is_a?(Prism::ConstantPathNode)
+
+ if node.is_a?(Prism::ConstantReadNode) && node.name == @name
+ subnodes << node
+ end
+
+ # If we found only one sub-node whose name is equal to @name, use it
+ return nil if subnodes.size != 1
+ @node = subnodes.first
end
case @node.type
@@ -205,6 +233,86 @@ module ErrorHighlight
when :OP_CDECL
spot_op_cdecl
+
+ when :DEFN
+ raise NotImplementedError if @point_type != :name
+ spot_defn
+
+ when :DEFS
+ raise NotImplementedError if @point_type != :name
+ spot_defs
+
+ when :LAMBDA
+ spot_lambda
+
+ when :ITER
+ spot_iter
+
+ when :call_node
+ case @point_type
+ when :name
+ prism_spot_call_for_name
+ when :args
+ prism_spot_call_for_args
+ end
+
+ when :local_variable_operator_write_node
+ case @point_type
+ when :name
+ prism_spot_local_variable_operator_write_for_name
+ when :args
+ prism_spot_local_variable_operator_write_for_args
+ end
+
+ when :call_operator_write_node
+ case @point_type
+ when :name
+ prism_spot_call_operator_write_for_name
+ when :args
+ prism_spot_call_operator_write_for_args
+ end
+
+ when :index_operator_write_node
+ case @point_type
+ when :name
+ prism_spot_index_operator_write_for_name
+ when :args
+ prism_spot_index_operator_write_for_args
+ end
+
+ when :constant_read_node
+ prism_spot_constant_read
+
+ when :constant_path_node
+ prism_spot_constant_path
+
+ when :constant_path_operator_write_node
+ prism_spot_constant_path_operator_write
+
+ when :def_node
+ case @point_type
+ when :name
+ prism_spot_def_for_name
+ when :args
+ raise NotImplementedError
+ end
+
+ when :lambda_node
+ case @point_type
+ when :name
+ prism_spot_lambda_for_name
+ when :args
+ raise NotImplementedError
+ end
+
+ when :block_node
+ case @point_type
+ when :name
+ prism_spot_block_for_name
+ when :args
+ raise NotImplementedError
+ end
+
end
if @snippet && @beg_column && @end_column && @beg_column < @end_column
@@ -269,6 +377,7 @@ module ErrorHighlight
end
elsif mid.to_s =~ /\A\W+\z/ && lines.match(/\G\s*(#{ Regexp.quote(mid) })=.*\n/, nd_recv.last_column)
@snippet = $` + $&
+ @beg_lineno = @end_lineno = lineno
@beg_column = $~.begin(1)
@end_column = $~.end(1)
end
@@ -395,7 +504,6 @@ module ErrorHighlight
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
@@ -507,8 +615,9 @@ module ErrorHighlight
@beg_column = nd_parent.last_column
@end_column = @node.last_column
else
- @snippet = @fetch[@node.last_lineno]
+ fetch_line(@node.last_lineno)
if @snippet[...@node.last_column].match(/#{ Regexp.quote(const) }\z/)
+ @beg_lineno = @end_lineno = @node.last_lineno
@beg_column = $~.begin(0)
@end_column = $~.end(0)
end
@@ -522,7 +631,7 @@ module ErrorHighlight
nd_lhs, op, _nd_rhs = @node.children
*nd_parent_lhs, _const = nd_lhs.children
if @name == op
- @snippet = @fetch[nd_lhs.last_lineno]
+ fetch_line(nd_lhs.last_lineno)
if @snippet.match(/\G\s*(#{ Regexp.quote(op) })=/, nd_lhs.last_column)
@beg_column = $~.begin(1)
@end_column = $~.end(1)
@@ -532,22 +641,297 @@ module ErrorHighlight
@end_column = nd_lhs.last_column
if nd_parent_lhs.empty? # example: ::C += 1
if nd_lhs.first_lineno == nd_lhs.last_lineno
- @snippet = @fetch[nd_lhs.last_lineno]
+ fetch_line(nd_lhs.last_lineno)
@beg_column = nd_lhs.first_column
end
else # example: Foo::Bar::C += 1
if nd_parent_lhs.last.last_lineno == nd_lhs.last_lineno
- @snippet = @fetch[nd_lhs.last_lineno]
+ fetch_line(nd_lhs.last_lineno)
@beg_column = nd_parent_lhs.last.last_column
end
end
end
end
+ # Example:
+ # def bar; end
+ # ^^^
+ def spot_defn
+ mid, = @node.children
+ fetch_line(@node.first_lineno)
+ if @snippet.match(/\Gdef\s+(#{ Regexp.quote(mid) }\b)/, @node.first_column)
+ @beg_column = $~.begin(1)
+ @end_column = $~.end(1)
+ end
+ end
+
+ # Example:
+ # def Foo.bar; end
+ # ^^^^
+ def spot_defs
+ nd_recv, mid, = @node.children
+ fetch_line(nd_recv.last_lineno)
+ if @snippet.match(/\G\s*(\.\s*#{ Regexp.quote(mid) }\b)/, nd_recv.last_column)
+ @beg_column = $~.begin(1)
+ @end_column = $~.end(1)
+ end
+ end
+
+ # Example:
+ # -> { ... }
+ # ^^
+ def spot_lambda
+ fetch_line(@node.first_lineno)
+ if @snippet.match(/\G->/, @node.first_column)
+ @beg_column = $~.begin(0)
+ @end_column = $~.end(0)
+ end
+ end
+
+ # Example:
+ # lambda { ... }
+ # ^
+ # define_method :foo do
+ # ^^
+ def spot_iter
+ _nd_fcall, nd_scope = @node.children
+ fetch_line(nd_scope.first_lineno)
+ if @snippet.match(/\G(?:do\b|\{)/, nd_scope.first_column)
+ @beg_column = $~.begin(0)
+ @end_column = $~.end(0)
+ end
+ end
+
def fetch_line(lineno)
@beg_lineno = @end_lineno = lineno
@snippet = @fetch[lineno]
end
+
+ # Take a location from the prism parser and set the necessary instance
+ # variables.
+ def prism_location(location)
+ @beg_lineno = location.start_line
+ @beg_column = location.start_column
+ @end_lineno = location.end_line
+ @end_column = location.end_column
+ @snippet = @fetch[@beg_lineno, @end_lineno]
+ end
+
+ # Example:
+ # x.foo
+ # ^^^^
+ # x.foo(42)
+ # ^^^^
+ # x&.foo
+ # ^^^^^
+ # x[42]
+ # ^^^^
+ # x.foo = 1
+ # ^^^^^^
+ # x[42] = 1
+ # ^^^^^^
+ # x + 1
+ # ^
+ # +x
+ # ^
+ # foo(42)
+ # ^^^
+ # foo 42
+ # ^^^
+ # foo
+ # ^^^
+ def prism_spot_call_for_name
+ # Explicitly turn off foo.() syntax because error_highlight expects this
+ # to not work.
+ return nil if @node.name == :call && @node.message_loc.nil?
+
+ location = @node.message_loc || @node.call_operator_loc || @node.location
+ location = @node.call_operator_loc.join(location) if @node.call_operator_loc&.start_line == location.start_line
+
+ # If the method name ends with "=" but the message does not, then this is
+ # a method call using the "attribute assignment" syntax
+ # (e.g., foo.bar = 1). In this case we need to go retrieve the = sign and
+ # add it to the location.
+ if (name = @node.name).end_with?("=") && !@node.message.end_with?("=")
+ location = location.adjoin("=")
+ end
+
+ prism_location(location)
+
+ if !name.end_with?("=") && !name.match?(/[[:alpha:]_\[]/)
+ # If the method name is an operator, then error_highlight only
+ # highlights the first line.
+ fetch_line(location.start_line)
+ end
+ end
+
+ # Example:
+ # x.foo(42)
+ # ^^
+ # x[42]
+ # ^^
+ # x.foo = 1
+ # ^
+ # x[42] = 1
+ # ^^^^^^^
+ # x[] = 1
+ # ^^^^^
+ # x + 1
+ # ^
+ # foo(42)
+ # ^^
+ # foo 42
+ # ^^
+ def prism_spot_call_for_args
+ # Disallow highlighting arguments if there are no arguments.
+ return if @node.arguments.nil?
+
+ # Explicitly turn off foo.() syntax because error_highlight expects this
+ # to not work.
+ return nil if @node.name == :call && @node.message_loc.nil?
+
+ if @node.name == :[]= && @node.opening == "[" && (@node.arguments&.arguments || []).length == 1
+ prism_location(@node.opening_loc.copy(start_offset: @node.opening_loc.start_offset + 1).join(@node.arguments.location))
+ else
+ prism_location(@node.arguments.location)
+ end
+ end
+
+ # Example:
+ # x += 1
+ # ^
+ def prism_spot_local_variable_operator_write_for_name
+ prism_location(@node.binary_operator_loc.chop)
+ end
+
+ # Example:
+ # x += 1
+ # ^
+ def prism_spot_local_variable_operator_write_for_args
+ prism_location(@node.value.location)
+ end
+
+ # Example:
+ # x.foo += 42
+ # ^^^ (for foo)
+ # x.foo += 42
+ # ^ (for +)
+ # x.foo += 42
+ # ^^^^^^^ (for foo=)
+ def prism_spot_call_operator_write_for_name
+ if !@name.start_with?(/[[:alpha:]_]/)
+ prism_location(@node.binary_operator_loc.chop)
+ else
+ location = @node.message_loc
+ if @node.call_operator_loc.start_line == location.start_line
+ location = @node.call_operator_loc.join(location)
+ end
+
+ location = location.adjoin("=") if @name.end_with?("=")
+ prism_location(location)
+ end
+ end
+
+ # Example:
+ # x.foo += 42
+ # ^^
+ def prism_spot_call_operator_write_for_args
+ prism_location(@node.value.location)
+ end
+
+ # Example:
+ # x[1] += 42
+ # ^^^ (for [])
+ # x[1] += 42
+ # ^ (for +)
+ # x[1] += 42
+ # ^^^^^^ (for []=)
+ def prism_spot_index_operator_write_for_name
+ case @name
+ when :[]
+ prism_location(@node.opening_loc.join(@node.closing_loc))
+ when :[]=
+ prism_location(@node.opening_loc.join(@node.closing_loc).adjoin("="))
+ else
+ # Explicitly turn off foo[] += 1 syntax when the operator is not on
+ # the same line because error_highlight expects this to not work.
+ return nil if @node.binary_operator_loc.start_line != @node.opening_loc.start_line
+
+ prism_location(@node.binary_operator_loc.chop)
+ end
+ end
+
+ # Example:
+ # x[1] += 42
+ # ^^^^^^^^
+ def prism_spot_index_operator_write_for_args
+ opening_loc =
+ if @node.arguments.nil?
+ @node.opening_loc.copy(start_offset: @node.opening_loc.start_offset + 1)
+ else
+ @node.arguments.location
+ end
+
+ prism_location(opening_loc.join(@node.value.location))
+ end
+
+ # Example:
+ # Foo
+ # ^^^
+ def prism_spot_constant_read
+ prism_location(@node.location)
+ end
+
+ # Example:
+ # Foo::Bar
+ # ^^^^^
+ def prism_spot_constant_path
+ if @node.parent && @node.parent.location.end_line == @node.location.end_line
+ fetch_line(@node.parent.location.end_line)
+ prism_location(@node.delimiter_loc.join(@node.name_loc))
+ else
+ fetch_line(@node.location.end_line)
+ location = @node.name_loc
+ location = @node.delimiter_loc.join(location) if @node.delimiter_loc.end_line == location.start_line
+ prism_location(location)
+ end
+ end
+
+ # Example:
+ # Foo::Bar += 1
+ # ^^^^^^^^
+ def prism_spot_constant_path_operator_write
+ if @name == (target = @node.target).name
+ prism_location(target.delimiter_loc.join(target.name_loc))
+ else
+ prism_location(@node.binary_operator_loc.chop)
+ end
+ end
+
+ # Example:
+ # def foo()
+ # ^^^
+ def prism_spot_def_for_name
+ location = @node.name_loc
+ location = @node.operator_loc.join(location) if @node.operator_loc
+ prism_location(location)
+ end
+
+ # Example:
+ # -> x, y { }
+ # ^^
+ def prism_spot_lambda_for_name
+ prism_location(@node.operator_loc)
+ end
+
+ # Example:
+ # lambda { }
+ # ^
+ # define_method :foo do |x, y|
+ # ^
+ def prism_spot_block_for_name
+ prism_location(@node.opening_loc)
+ end
end
private_constant :Spotter
diff --git a/lib/error_highlight/core_ext.rb b/lib/error_highlight/core_ext.rb
index b69093f74e..c3354f46cd 100644
--- a/lib/error_highlight/core_ext.rb
+++ b/lib/error_highlight/core_ext.rb
@@ -3,9 +3,38 @@ require_relative "formatter"
module ErrorHighlight
module CoreExt
private def generate_snippet
- spot = ErrorHighlight.spot(self)
- return "" unless spot
- return ErrorHighlight.formatter.message_for(spot)
+ if ArgumentError === self && message =~ /\A(?:wrong number of arguments|missing keyword[s]?|unknown keyword[s]?|no keywords accepted)\b/
+ locs = self.backtrace_locations
+ return "" if locs.size < 2
+ callee_loc, caller_loc = locs
+ callee_spot = ErrorHighlight.spot(self, backtrace_location: callee_loc, point_type: :name)
+ caller_spot = ErrorHighlight.spot(self, backtrace_location: caller_loc, point_type: :name)
+ if caller_spot && callee_spot &&
+ caller_loc.path == callee_loc.path &&
+ caller_loc.lineno == callee_loc.lineno &&
+ caller_spot == callee_spot
+ callee_loc = callee_spot = nil
+ end
+ ret = +"\n"
+ [["caller", caller_loc, caller_spot], ["callee", callee_loc, callee_spot]].each do |header, loc, spot|
+ out = nil
+ if loc
+ out = " #{ header }: #{ loc.path }:#{ loc.lineno }"
+ if spot
+ _, _, snippet, highlight = ErrorHighlight.formatter.message_for(spot).lines
+ out += "\n | #{ snippet } #{ highlight }"
+ else
+ # do nothing
+ end
+ end
+ ret << "\n" + out if out
+ end
+ ret
+ else
+ spot = ErrorHighlight.spot(self)
+ return "" unless spot
+ return ErrorHighlight.formatter.message_for(spot)
+ end
end
if Exception.method_defined?(:detailed_message)
diff --git a/lib/error_highlight/error_highlight.gemspec b/lib/error_highlight/error_highlight.gemspec
index b2da18df83..edfc4b776f 100644
--- a/lib/error_highlight/error_highlight.gemspec
+++ b/lib/error_highlight/error_highlight.gemspec
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
spec.homepage = "https://github.com/ruby/error_highlight"
spec.license = "MIT"
- spec.required_ruby_version = Gem::Requirement.new(">= 3.1.0.dev")
+ spec.required_ruby_version = Gem::Requirement.new(">= 3.2.0")
spec.files = Dir.chdir(File.expand_path(__dir__)) do
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
diff --git a/lib/error_highlight/formatter.rb b/lib/error_highlight/formatter.rb
index 20ca78d468..d2fad9e75c 100644
--- a/lib/error_highlight/formatter.rb
+++ b/lib/error_highlight/formatter.rb
@@ -1,15 +1,66 @@
module ErrorHighlight
class DefaultFormatter
+ MIN_SNIPPET_WIDTH = 20
+
def self.message_for(spot)
# currently only a one-line code snippet is supported
- if spot[:first_lineno] == spot[:last_lineno]
- indent = spot[:snippet][0...spot[:first_column]].gsub(/[^\t]/, " ")
- marker = indent + "^" * (spot[:last_column] - spot[:first_column])
+ return "" unless spot[:first_lineno] == spot[:last_lineno]
+
+ snippet = spot[:snippet]
+ first_column = spot[:first_column]
+ last_column = spot[:last_column]
+ ellipsis = "..."
+
+ # truncate snippet to fit in the viewport
+ if max_snippet_width && snippet.size > max_snippet_width
+ available_width = max_snippet_width - ellipsis.size
+ center = first_column - max_snippet_width / 2
+
+ visible_start = last_column < available_width ? 0 : [center, 0].max
+ visible_end = visible_start + max_snippet_width
+ visible_start = snippet.size - max_snippet_width if visible_end > snippet.size
+
+ prefix = visible_start.positive? ? ellipsis : ""
+ suffix = visible_end < snippet.size ? ellipsis : ""
- "\n\n#{ spot[:snippet] }#{ marker }"
- else
- ""
+ snippet = prefix + snippet[(visible_start + prefix.size)...(visible_end - suffix.size)] + suffix
+ snippet << "\n" unless snippet.end_with?("\n")
+
+ first_column -= visible_start
+ last_column = [last_column - visible_start, snippet.size - 1].min
end
+
+ indent = snippet[0...first_column].gsub(/[^\t]/, " ")
+ marker = indent + "^" * (last_column - first_column)
+
+ "\n\n#{ snippet }#{ marker }"
+ end
+
+ def self.max_snippet_width
+ return if Ractor.current[:__error_highlight_max_snippet_width__] == :disabled
+
+ Ractor.current[:__error_highlight_max_snippet_width__] ||= terminal_width
+ end
+
+ def self.max_snippet_width=(width)
+ return Ractor.current[:__error_highlight_max_snippet_width__] = :disabled if width.nil?
+
+ width = width.to_i
+
+ if width < MIN_SNIPPET_WIDTH
+ warn "'max_snippet_width' adjusted to minimum value of #{MIN_SNIPPET_WIDTH}."
+ width = MIN_SNIPPET_WIDTH
+ end
+
+ Ractor.current[:__error_highlight_max_snippet_width__] = width
+ end
+
+ def self.terminal_width
+ # lazy load io/console to avoid loading it when 'max_snippet_width' is manually set
+ require "io/console"
+ $stderr.winsize[1] if $stderr.tty?
+ rescue LoadError, NoMethodError, SystemCallError
+ # skip truncation when terminal window size is unavailable
end
end
diff --git a/lib/error_highlight/version.rb b/lib/error_highlight/version.rb
index 506d37fbc1..f0a5376b14 100644
--- a/lib/error_highlight/version.rb
+++ b/lib/error_highlight/version.rb
@@ -1,3 +1,3 @@
module ErrorHighlight
- VERSION = "0.6.0"
+ VERSION = "0.7.1"
end
diff --git a/lib/fileutils.gemspec b/lib/fileutils.gemspec
index 76baea3039..2603d664da 100644
--- a/lib/fileutils.gemspec
+++ b/lib/fileutils.gemspec
@@ -17,7 +17,7 @@ Gem::Specification.new do |s|
s.description = "Several file utility methods for copying, moving, removing, etc."
s.require_path = %w{lib}
- s.files = ["LICENSE.txt", "README.md", "Rakefile", "fileutils.gemspec", "lib/fileutils.rb"]
+ s.files = ["COPYING", "BSDL", "README.md", "Rakefile", "fileutils.gemspec", "lib/fileutils.rb"]
s.required_ruby_version = ">= 2.5.0"
s.authors = ["Minero Aoki"]
diff --git a/lib/fileutils.rb b/lib/fileutils.rb
index e8cc355760..0706e007ca 100644
--- a/lib/fileutils.rb
+++ b/lib/fileutils.rb
@@ -181,7 +181,7 @@ end
#
module FileUtils
# The version number.
- VERSION = "1.7.2"
+ VERSION = "1.8.0"
def self.private_module_function(name) #:nodoc:
module_function name
@@ -706,11 +706,12 @@ module FileUtils
#
def ln_s(src, dest, force: nil, relative: false, target_directory: true, noop: nil, verbose: nil)
if relative
- return ln_sr(src, dest, force: force, noop: noop, verbose: verbose)
+ return ln_sr(src, dest, force: force, target_directory: target_directory, noop: noop, verbose: verbose)
end
- fu_output_message "ln -s#{force ? 'f' : ''} #{[src,dest].flatten.join ' '}" if verbose
+ fu_output_message "ln -s#{force ? 'f' : ''}#{
+ target_directory ? '' : 'T'} #{[src,dest].flatten.join ' '}" if verbose
return if noop
- fu_each_src_dest0(src, dest) do |s,d|
+ fu_each_src_dest0(src, dest, target_directory) do |s,d|
remove_file d, true if force
File.symlink s, d
end
@@ -730,42 +731,37 @@ module FileUtils
# Like FileUtils.ln_s, but create links relative to +dest+.
#
def ln_sr(src, dest, target_directory: true, force: nil, noop: nil, verbose: nil)
- options = "#{force ? 'f' : ''}#{target_directory ? '' : 'T'}"
- dest = File.path(dest)
- srcs = Array(src)
- link = proc do |s, target_dir_p = true|
- s = File.path(s)
- if target_dir_p
- d = File.join(destdirs = dest, File.basename(s))
+ cmd = "ln -s#{force ? 'f' : ''}#{target_directory ? '' : 'T'}" if verbose
+ fu_each_src_dest0(src, dest, target_directory) do |s,d|
+ if target_directory
+ parent = File.dirname(d)
+ destdirs = fu_split_path(parent)
+ real_ddirs = fu_split_path(File.realpath(parent))
else
- destdirs = File.dirname(d = dest)
+ destdirs ||= fu_split_path(dest)
+ real_ddirs ||= fu_split_path(File.realdirpath(dest))
end
- destdirs = fu_split_path(File.realpath(destdirs))
- if fu_starting_path?(s)
- srcdirs = fu_split_path((File.realdirpath(s) rescue File.expand_path(s)))
- base = fu_relative_components_from(srcdirs, destdirs)
- s = File.join(*base)
+ srcdirs = fu_split_path(s)
+ i = fu_common_components(srcdirs, destdirs)
+ n = destdirs.size - i
+ n -= 1 unless target_directory
+ link1 = fu_clean_components(*Array.new([n, 0].max, '..'), *srcdirs[i..-1])
+ begin
+ real_sdirs = fu_split_path(File.realdirpath(s)) rescue nil
+ rescue
else
- srcdirs = fu_clean_components(*fu_split_path(s))
- base = fu_relative_components_from(fu_split_path(Dir.pwd), destdirs)
- while srcdirs.first&. == ".." and base.last&.!=("..") and !fu_starting_path?(base.last)
- srcdirs.shift
- base.pop
- end
- s = File.join(*base, *srcdirs)
+ i = fu_common_components(real_sdirs, real_ddirs)
+ n = real_ddirs.size - i
+ n -= 1 unless target_directory
+ link2 = fu_clean_components(*Array.new([n, 0].max, '..'), *real_sdirs[i..-1])
+ link1 = link2 if link1.size > link2.size
end
- fu_output_message "ln -s#{options} #{s} #{d}" if verbose
+ s = File.join(link1)
+ fu_output_message [cmd, s, d].flatten.join(' ') if verbose
next if noop
remove_file d, true if force
File.symlink s, d
end
- case srcs.size
- when 0
- when 1
- link[srcs[0], target_directory && File.directory?(dest)]
- else
- srcs.each(&link)
- end
end
module_function :ln_sr
@@ -800,13 +796,13 @@ module FileUtils
# File.file?('dest1/dir1/t2.txt') # => true
# File.file?('dest1/dir1/t3.txt') # => true
#
- # Keyword arguments:
+ # Optional arguments:
#
- # - <tt>dereference_root: true</tt> - dereferences +src+ if it is a symbolic link.
- # - <tt>remove_destination: true</tt> - removes +dest+ before creating links.
+ # - +dereference_root+ - dereferences +src+ if it is a symbolic link (+false+ by default).
+ # - +remove_destination+ - removes +dest+ before creating links (+false+ by default).
#
# Raises an exception if +dest+ is the path to an existing file or directory
- # and keyword argument <tt>remove_destination: true</tt> is not given.
+ # and optional argument +remove_destination+ is not given.
#
# Related: FileUtils.ln (has different options).
#
@@ -1029,12 +1025,12 @@ module FileUtils
# directories, and symbolic links;
# other file types (FIFO streams, device files, etc.) are not supported.
#
- # Keyword arguments:
+ # Optional arguments:
#
- # - <tt>dereference_root: true</tt> - if +src+ is a symbolic link,
- # follows the link.
- # - <tt>preserve: true</tt> - preserves file times.
- # - <tt>remove_destination: true</tt> - removes +dest+ before copying files.
+ # - +dereference_root+ - if +src+ is a symbolic link,
+ # follows the link (+false+ by default).
+ # - +preserve+ - preserves file times (+false+ by default).
+ # - +remove_destination+ - removes +dest+ before copying files (+false+ by default).
#
# Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
#
@@ -1065,12 +1061,12 @@ module FileUtils
# FileUtils.copy_file('src0.txt', 'dest0.txt')
# File.file?('dest0.txt') # => true
#
- # Keyword arguments:
+ # Optional arguments:
#
- # - <tt>dereference: false</tt> - if +src+ is a symbolic link,
- # does not follow the link.
- # - <tt>preserve: true</tt> - preserves file times.
- # - <tt>remove_destination: true</tt> - removes +dest+ before copying files.
+ # - +dereference+ - if +src+ is a symbolic link,
+ # follows the link (+true+ by default).
+ # - +preserve+ - preserves file times (+false+ by default).
+ # - +remove_destination+ - removes +dest+ before copying files (+false+ by default).
#
# Related: {methods for copying}[rdoc-ref:FileUtils@Copying].
#
@@ -1491,7 +1487,8 @@ module FileUtils
# Related: {methods for deleting}[rdoc-ref:FileUtils@Deleting].
#
def remove_dir(path, force = false)
- remove_entry path, force # FIXME?? check if it is a directory
+ raise Errno::ENOTDIR, path unless force or File.directory?(path)
+ remove_entry path, force
end
module_function :remove_dir
@@ -2475,6 +2472,10 @@ module FileUtils
def fu_each_src_dest0(src, dest, target_directory = true) #:nodoc:
if tmp = Array.try_convert(src)
+ unless target_directory or tmp.size <= 1
+ tmp = tmp.map {|f| File.path(f)} # A workaround for RBS
+ raise ArgumentError, "extra target #{tmp}"
+ end
tmp.each do |s|
s = File.path(s)
yield s, (target_directory ? File.join(dest, File.basename(s)) : dest)
@@ -2509,7 +2510,11 @@ module FileUtils
path = File.path(path)
list = []
until (parent, base = File.split(path); parent == path or parent == ".")
- list << base
+ if base != '..' and list.last == '..' and !(fu_have_symlink? && File.symlink?(path))
+ list.pop
+ else
+ list << base
+ end
path = parent
end
list << path
@@ -2517,14 +2522,14 @@ module FileUtils
end
private_module_function :fu_split_path
- def fu_relative_components_from(target, base) #:nodoc:
+ def fu_common_components(target, base) #:nodoc:
i = 0
while target[i]&.== base[i]
i += 1
end
- Array.new(base.size-i, '..').concat(target[i..-1])
+ i
end
- private_module_function :fu_relative_components_from
+ private_module_function :fu_common_components
def fu_clean_components(*comp) #:nodoc:
comp.shift while comp.first == "."
@@ -2534,7 +2539,7 @@ module FileUtils
while c = comp.shift
if c == ".." and clean.last != ".." and !(fu_have_symlink? && File.symlink?(path))
clean.pop
- path.chomp!(%r((?<=\A|/)[^/]+/\z), "")
+ path.sub!(%r((?<=\A|/)[^/]+/\z), "")
else
clean << c
path << c << "/"
diff --git a/lib/find.rb b/lib/find.rb
index 98a79cc76d..8223eea456 100644
--- a/lib/find.rb
+++ b/lib/find.rb
@@ -27,6 +27,7 @@
#
module Find
+ # The version string
VERSION = "0.2.0"
#
diff --git a/lib/forwardable.rb b/lib/forwardable.rb
index 71b4e6adad..175d6d9c6b 100644
--- a/lib/forwardable.rb
+++ b/lib/forwardable.rb
@@ -109,11 +109,11 @@
# +delegate.rb+.
#
module Forwardable
- require 'forwardable/impl'
-
# Version of +forwardable.rb+
- VERSION = "1.3.3"
+ VERSION = "1.4.0"
VERSION.freeze
+
+ # Version for backward compatibility
FORWARDABLE_VERSION = VERSION
FORWARDABLE_VERSION.freeze
@@ -190,9 +190,7 @@ module Forwardable
# 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'
- ret
+ mod.module_eval(&gen)
end
alias delegate instance_delegate
@@ -206,36 +204,33 @@ module Forwardable
if Module === obj ?
obj.method_defined?(accessor) || obj.private_method_defined?(accessor) :
obj.respond_to?(accessor, true)
- accessor = "#{accessor}()"
+ accessor = "(#{accessor}())"
end
- method_call = ".__send__(:#{method}, *args, &block)"
- if _valid_method?(method)
+ args = RUBY_VERSION >= '2.7' ? '...' : '*args, &block'
+ method_call = ".__send__(:#{method}, #{args})"
+ if method.match?(/\A[_a-zA-Z]\w*[?!]?\z/)
loc, = caller_locations(2,1)
pre = "_ ="
mesg = "#{Module === obj ? obj : obj.class}\##{ali} at #{loc.path}:#{loc.lineno} forwarding to private method "
- method_call = "#{<<-"begin;"}\n#{<<-"end;".chomp}"
- begin;
- unless defined? _.#{method}
- ::Kernel.warn #{mesg.dump}"\#{_.class}"'##{method}', uplevel: 1
- _#{method_call}
- else
- _.#{method}(*args, &block)
- end
- end;
+ method_call = <<~RUBY.chomp
+ if defined?(_.#{method})
+ _.#{method}(#{args})
+ else
+ ::Kernel.warn #{mesg.dump}"\#{_.class}"'##{method}', uplevel: 1
+ _#{method_call}
+ end
+ RUBY
end
- _compile_method("#{<<-"begin;"}\n#{<<-"end;"}", __FILE__, __LINE__+1)
- begin;
+ eval(<<~RUBY, nil, __FILE__, __LINE__ + 1)
proc do
- def #{ali}(*args, &block)
- #{pre}
- begin
- #{accessor}
- end#{method_call}
+ def #{ali}(#{args})
+ #{pre}#{accessor}
+ #{method_call}
end
end
- end;
+ RUBY
end
end
@@ -310,9 +305,7 @@ module SingleForwardable
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'
- ret
+ instance_eval(&gen)
end
alias delegate single_delegate
diff --git a/lib/forwardable/forwardable.gemspec b/lib/forwardable/forwardable.gemspec
index 9ad59c5f8a..1b539bcfcb 100644
--- a/lib/forwardable/forwardable.gemspec
+++ b/lib/forwardable/forwardable.gemspec
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
spec.licenses = ["Ruby", "BSD-2-Clause"]
spec.required_ruby_version = '>= 2.4.0'
- spec.files = ["forwardable.gemspec", "lib/forwardable.rb", "lib/forwardable/impl.rb"]
+ spec.files = ["forwardable.gemspec", "lib/forwardable.rb"]
spec.bindir = "exe"
spec.executables = []
spec.require_paths = ["lib"]
diff --git a/lib/forwardable/impl.rb b/lib/forwardable/impl.rb
deleted file mode 100644
index 0322c136db..0000000000
--- a/lib/forwardable/impl.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-module Forwardable
- # :stopdoc:
-
- def self._valid_method?(method)
- catch {|tag|
- eval("BEGIN{throw tag}; ().#{method}", binding, __FILE__, __LINE__)
- }
- rescue SyntaxError
- false
- else
- true
- end
-
- def self._compile_method(src, file, line)
- eval(src, nil, file, line)
- end
-end
diff --git a/lib/ipaddr.gemspec b/lib/ipaddr.gemspec
index 1f4798e43a..cabc9161ba 100644
--- a/lib/ipaddr.gemspec
+++ b/lib/ipaddr.gemspec
@@ -29,8 +29,8 @@ Both IPv4 and IPv6 are supported.
spec.homepage = "https://github.com/ruby/ipaddr"
spec.licenses = ["Ruby", "BSD-2-Clause"]
- spec.files = ["LICENSE.txt", "README.md", "ipaddr.gemspec", "lib/ipaddr.rb"]
+ spec.files = ["LICENSE.txt", "README.md", "lib/ipaddr.rb"]
spec.require_paths = ["lib"]
- spec.required_ruby_version = ">= 2.3"
+ spec.required_ruby_version = ">= 2.4"
end
diff --git a/lib/ipaddr.rb b/lib/ipaddr.rb
index dbb213c90a..6b67d7eec6 100644
--- a/lib/ipaddr.rb
+++ b/lib/ipaddr.rb
@@ -40,7 +40,8 @@ require 'socket'
# p ipaddr3 #=> #<IPAddr: IPv4:192.168.2.0/255.255.255.0>
class IPAddr
- VERSION = "1.2.6"
+ # The version string
+ VERSION = "1.2.8"
# 32 bit mask for IPv4
IN4MASK = 0xffffffff
@@ -151,6 +152,16 @@ class IPAddr
return self.clone.set(addr_mask(~@addr))
end
+ # Returns a new ipaddr greater than the original address by offset
+ def +(offset)
+ self.clone.set(@addr + offset, @family)
+ end
+
+ # Returns a new ipaddr less than the original address by offset
+ def -(offset)
+ self.clone.set(@addr - offset, @family)
+ end
+
# Returns true if two ipaddrs are equal.
def ==(other)
other = coerce_other(other)
@@ -227,10 +238,26 @@ class IPAddr
return str
end
+ # Returns a string containing the IP address representation with prefix.
+ def as_json(*)
+ if ipv4? && prefix == 32
+ to_s
+ elsif ipv6? && prefix == 128
+ to_s
+ else
+ cidr
+ end
+ end
+
+ # Returns a json string containing the IP address representation.
+ def to_json(*a)
+ %Q{"#{as_json(*a)}"}
+ end
+
# Returns a string containing the IP address representation in
# cidr notation
def cidr
- format("%s/%s", to_s, prefix)
+ "#{to_s}/#{prefix}"
end
# Returns a network byte ordered string form of the IP address.
@@ -327,7 +354,7 @@ class IPAddr
_ipv4_compat?
end
- def _ipv4_compat?
+ def _ipv4_compat? # :nodoc:
if !ipv6? || (@addr >> 32) != 0
return false
end
@@ -341,7 +368,7 @@ class IPAddr
# into an IPv4-mapped IPv6 address.
def ipv4_mapped
if !ipv4?
- raise InvalidAddressError, "not an IPv4 address: #{@addr}"
+ raise InvalidAddressError, "not an IPv4 address: #{to_s}"
end
clone = self.clone.set(@addr | 0xffff00000000, Socket::AF_INET6)
clone.instance_variable_set(:@mask_addr, @mask_addr | 0xffffffffffffffffffffffff00000000)
@@ -353,9 +380,11 @@ class IPAddr
def ipv4_compat
warn "IPAddr\##{__callee__} is obsolete", uplevel: 1 if $VERBOSE
if !ipv4?
- raise InvalidAddressError, "not an IPv4 address: #{@addr}"
+ raise InvalidAddressError, "not an IPv4 address: #{to_s}"
end
- return self.clone.set(@addr, Socket::AF_INET6)
+ clone = self.clone.set(@addr, Socket::AF_INET6)
+ clone.instance_variable_set(:@mask_addr, @mask_addr | 0xffffffffffffffffffffffff00000000)
+ clone
end
# Returns a new ipaddr built by converting the IPv6 address into a
@@ -384,7 +413,7 @@ class IPAddr
# Returns a string for DNS reverse lookup compatible with RFC3172.
def ip6_arpa
if !ipv6?
- raise InvalidAddressError, "not an IPv6 address: #{@addr}"
+ raise InvalidAddressError, "not an IPv6 address: #{to_s}"
end
return _reverse + ".ip6.arpa"
end
@@ -392,7 +421,7 @@ class IPAddr
# Returns a string for DNS reverse lookup compatible with RFC1886.
def ip6_int
if !ipv6?
- raise InvalidAddressError, "not an IPv6 address: #{@addr}"
+ raise InvalidAddressError, "not an IPv6 address: #{to_s}"
end
return _reverse + ".ip6.int"
end
@@ -517,6 +546,7 @@ class IPAddr
end
protected
+ # :stopdoc:
def begin_addr
@addr & @mask_addr
@@ -532,6 +562,7 @@ class IPAddr
raise AddressFamilyError, "unsupported address family"
end
end
+ #:startdoc:
# Set +@addr+, the internal stored ip address, to given +addr+. The
# parameter +addr+ is validated using the first +family+ member,
@@ -673,6 +704,7 @@ class IPAddr
end
end
+ # :stopdoc:
def coerce_other(other)
case other
when IPAddr
@@ -693,8 +725,8 @@ class IPAddr
octets = addr.split('.')
end
octets.inject(0) { |i, s|
- (n = s.to_i) < 256 or raise InvalidAddressError, "invalid address: #{@addr}"
- (s != '0') && s.start_with?('0') and raise InvalidAddressError, "zero-filled number in IPv4 address is ambiguous: #{@addr}"
+ (n = s.to_i) < 256 or raise InvalidAddressError, "invalid address: #{addr}"
+ (s != '0') && s.start_with?('0') and raise InvalidAddressError, "zero-filled number in IPv4 address is ambiguous: #{addr}"
i << 8 | n
}
end
@@ -711,19 +743,19 @@ class IPAddr
right = ''
when RE_IPV6ADDRLIKE_COMPRESSED
if $4
- left.count(':') <= 6 or raise InvalidAddressError, "invalid address: #{@addr}"
+ left.count(':') <= 6 or raise InvalidAddressError, "invalid address: #{left}"
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: #{@addr}"
+ raise InvalidAddressError, "invalid address: #{left}"
left = $1
right = $2
addr = 0
end
else
- raise InvalidAddressError, "invalid address: #{@addr}"
+ raise InvalidAddressError, "invalid address: #{left}"
end
l = left.split(':')
r = right.split(':')
@@ -784,7 +816,7 @@ unless Socket.const_defined? :AF_INET6
class << IPSocket
private
- def valid_v6?(addr)
+ def valid_v6?(addr) # :nodoc:
case addr
when IPAddr::RE_IPV6ADDRLIKE_FULL
if $2
diff --git a/lib/irb.rb b/lib/irb.rb
deleted file mode 100644
index b3435c257e..0000000000
--- a/lib/irb.rb
+++ /dev/null
@@ -1,1608 +0,0 @@
-# frozen_string_literal: true
-
-# :markup: markdown
-# irb.rb - irb main module
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-require "ripper"
-require "reline"
-
-require_relative "irb/init"
-require_relative "irb/context"
-require_relative "irb/default_commands"
-
-require_relative "irb/ruby-lex"
-require_relative "irb/statement"
-require_relative "irb/input-method"
-require_relative "irb/locale"
-require_relative "irb/color"
-
-require_relative "irb/version"
-require_relative "irb/easter-egg"
-require_relative "irb/debug"
-require_relative "irb/pager"
-
-# ## IRB
-#
-# Module IRB ("Interactive Ruby") provides a shell-like interface that supports
-# user interaction with the Ruby interpreter.
-#
-# It operates as a *read-eval-print loop*
-# ([REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop))
-# that:
-#
-# * ***Reads*** each character as you type. You can modify the IRB context to
-# change the way input works. See [Input](rdoc-ref:IRB@Input).
-# * ***Evaluates*** the code each time it has read a syntactically complete
-# passage.
-# * ***Prints*** after evaluating. You can modify the IRB context to change
-# the way output works. See [Output](rdoc-ref:IRB@Output).
-#
-#
-# Example:
-#
-# $ irb
-# irb(main):001> File.basename(Dir.pwd)
-# => "irb"
-# irb(main):002> Dir.entries('.').size
-# => 25
-# irb(main):003* Dir.entries('.').select do |entry|
-# irb(main):004* entry.start_with?('R')
-# irb(main):005> end
-# => ["README.md", "Rakefile"]
-#
-# The typed input may also include [\IRB-specific
-# commands](rdoc-ref:IRB@IRB-Specific+Commands).
-#
-# As seen above, you can start IRB by using the shell command `irb`.
-#
-# You can stop an IRB session by typing command `exit`:
-#
-# irb(main):006> exit
-# $
-#
-# At that point, IRB calls any hooks found in array `IRB.conf[:AT_EXIT]`, then
-# exits.
-#
-# ## Startup
-#
-# At startup, IRB:
-#
-# 1. Interprets (as Ruby code) the content of the [configuration
-# file](rdoc-ref:IRB@Configuration+File) (if given).
-# 2. Constructs the initial session context from [hash
-# IRB.conf](rdoc-ref:IRB@Hash+IRB.conf) and from default values; the hash
-# content may have been affected by [command-line
-# options](rdoc-ref:IB@Command-Line+Options), and by direct assignments in
-# the configuration file.
-# 3. Assigns the context to variable `conf`.
-# 4. Assigns command-line arguments to variable `ARGV`.
-# 5. Prints the [prompt](rdoc-ref:IRB@Prompt+and+Return+Formats).
-# 6. Puts the content of the [initialization
-# script](rdoc-ref:IRB@Initialization+Script) onto the IRB shell, just as if
-# it were user-typed commands.
-#
-#
-# ### The Command Line
-#
-# On the command line, all options precede all arguments; the first item that is
-# not recognized as an option is treated as an argument, as are all items that
-# follow.
-#
-# #### Command-Line Options
-#
-# Many command-line options affect entries in hash `IRB.conf`, which in turn
-# affect the initial configuration of the IRB session.
-#
-# Details of the options are described in the relevant subsections below.
-#
-# A cursory list of the IRB command-line options may be seen in the [help
-# message](https://raw.githubusercontent.com/ruby/irb/master/lib/irb/lc/help-message),
-# which is also displayed if you use command-line option `--help`.
-#
-# If you are interested in a specific option, consult the
-# [index](rdoc-ref:doc/irb/indexes.md@Index+of+Command-Line+Options).
-#
-# #### Command-Line Arguments
-#
-# Command-line arguments are passed to IRB in array `ARGV`:
-#
-# $ irb --noscript Foo Bar Baz
-# irb(main):001> ARGV
-# => ["Foo", "Bar", "Baz"]
-# irb(main):002> exit
-# $
-#
-# Command-line option `--` causes everything that follows to be treated as
-# arguments, even those that look like options:
-#
-# $ irb --noscript -- --noscript -- Foo Bar Baz
-# irb(main):001> ARGV
-# => ["--noscript", "--", "Foo", "Bar", "Baz"]
-# irb(main):002> exit
-# $
-#
-# ### Configuration File
-#
-# You can initialize IRB via a *configuration file*.
-#
-# If command-line option `-f` is given, no configuration file is looked for.
-#
-# Otherwise, IRB reads and interprets a configuration file if one is available.
-#
-# The configuration file can contain any Ruby code, and can usefully include
-# user code that:
-#
-# * Can then be debugged in IRB.
-# * Configures IRB itself.
-# * Requires or loads files.
-#
-#
-# The path to the configuration file is the first found among:
-#
-# * The value of variable `$IRBRC`, if defined.
-# * The value of variable `$XDG_CONFIG_HOME/irb/irbrc`, if defined.
-# * File `$HOME/.irbrc`, if it exists.
-# * File `$HOME/.config/irb/irbrc`, if it exists.
-# * File `.irbrc` in the current directory, if it exists.
-# * File `irb.rc` in the current directory, if it exists.
-# * File `_irbrc` in the current directory, if it exists.
-# * File `$irbrc` in the current directory, if it exists.
-#
-#
-# If the search fails, there is no configuration file.
-#
-# If the search succeeds, the configuration file is read as Ruby code, and so
-# can contain any Ruby programming you like.
-#
-# Method `conf.rc?` returns `true` if a configuration file was read, `false`
-# otherwise. Hash entry `IRB.conf[:RC]` also contains that value.
-#
-# ### Hash `IRB.conf`
-#
-# The initial entries in hash `IRB.conf` are determined by:
-#
-# * Default values.
-# * Command-line options, which may override defaults.
-# * Direct assignments in the configuration file.
-#
-#
-# You can see the hash by typing `IRB.conf`.
-#
-# Details of the entries' meanings are described in the relevant subsections
-# below.
-#
-# If you are interested in a specific entry, consult the
-# [index](rdoc-ref:doc/irb/indexes.md@Index+of+IRB.conf+Entries).
-#
-# ### Notes on Initialization Precedence
-#
-# * Any conflict between an entry in hash `IRB.conf` and a command-line option
-# is resolved in favor of the hash entry.
-# * Hash `IRB.conf` affects the context only once, when the configuration file
-# is interpreted; any subsequent changes to it do not affect the context and
-# are therefore essentially meaningless.
-#
-#
-# ### Initialization Script
-#
-# By default, the first command-line argument (after any options) is the path to
-# a Ruby initialization script.
-#
-# IRB reads the initialization script and puts its content onto the IRB shell,
-# just as if it were user-typed commands.
-#
-# Command-line option `--noscript` causes the first command-line argument to be
-# treated as an ordinary argument (instead of an initialization script);
-# `--script` is the default.
-#
-# ## Input
-#
-# This section describes the features that allow you to change the way IRB input
-# works; see also [Input and Output](rdoc-ref:IRB@Input+and+Output).
-#
-# ### Input Command History
-#
-# By default, IRB stores a history of up to 1000 input commands in a file named
-# `.irb_history`. The history file will be in the same directory as the
-# [configuration file](rdoc-ref:IRB@Configuration+File) if one is found, or in
-# `~/` otherwise.
-#
-# A new IRB session creates the history file if it does not exist, and appends
-# to the file if it does exist.
-#
-# You can change the filepath by adding to your configuration file:
-# `IRB.conf[:HISTORY_FILE] = *filepath*`, where *filepath* is a string filepath.
-#
-# During the session, method `conf.history_file` returns the filepath, and
-# method `conf.history_file = *new_filepath*` copies the history to the file at
-# *new_filepath*, which becomes the history file for the session.
-#
-# You can change the number of commands saved by adding to your configuration
-# file: `IRB.conf[:SAVE_HISTORY] = *n*`, wheHISTORY_FILEre *n* is one of:
-#
-# * Positive integer: the number of commands to be saved,
-# * Zero: all commands are to be saved.
-# * `nil`: no commands are to be saved,.
-#
-#
-# During the session, you can use methods `conf.save_history` or
-# `conf.save_history=` to retrieve or change the count.
-#
-# ### Command Aliases
-#
-# By default, IRB defines several command aliases:
-#
-# irb(main):001> conf.command_aliases
-# => {:"$"=>:show_source, :"@"=>:whereami}
-#
-# You can change the initial aliases in the configuration file with:
-#
-# IRB.conf[:COMMAND_ALIASES] = {foo: :show_source, bar: :whereami}
-#
-# You can replace the current aliases at any time with configuration method
-# `conf.command_aliases=`; Because `conf.command_aliases` is a hash, you can
-# modify it.
-#
-# ### End-of-File
-#
-# By default, `IRB.conf[:IGNORE_EOF]` is `false`, which means that typing the
-# end-of-file character `Ctrl-D` causes the session to exit.
-#
-# You can reverse that behavior by adding `IRB.conf[:IGNORE_EOF] = true` to the
-# configuration file.
-#
-# During the session, method `conf.ignore_eof?` returns the setting, and method
-# `conf.ignore_eof = *boolean*` sets it.
-#
-# ### SIGINT
-#
-# By default, `IRB.conf[:IGNORE_SIGINT]` is `true`, which means that typing the
-# interrupt character `Ctrl-C` causes the session to exit.
-#
-# You can reverse that behavior by adding `IRB.conf[:IGNORE_SIGING] = false` to
-# the configuration file.
-#
-# During the session, method `conf.ignore_siging?` returns the setting, and
-# method `conf.ignore_sigint = *boolean*` sets it.
-#
-# ### Automatic Completion
-#
-# By default, IRB enables [automatic
-# completion](https://en.wikipedia.org/wiki/Autocomplete#In_command-line_interpr
-# eters):
-#
-# You can disable it by either of these:
-#
-# * Adding `IRB.conf[:USE_AUTOCOMPLETE] = false` to the configuration file.
-# * Giving command-line option `--noautocomplete` (`--autocomplete` is the
-# default).
-#
-#
-# Method `conf.use_autocomplete?` returns `true` if automatic completion is
-# enabled, `false` otherwise.
-#
-# The setting may not be changed during the session.
-#
-# ### Automatic Indentation
-#
-# By default, IRB automatically indents lines of code to show structure (e.g.,
-# it indent the contents of a block).
-#
-# The current setting is returned by the configuration method
-# `conf.auto_indent_mode`.
-#
-# The default initial setting is `true`:
-#
-# irb(main):001> conf.auto_indent_mode
-# => true
-# irb(main):002* Dir.entries('.').select do |entry|
-# irb(main):003* entry.start_with?('R')
-# irb(main):004> end
-# => ["README.md", "Rakefile"]
-#
-# You can change the initial setting in the configuration file with:
-#
-# IRB.conf[:AUTO_INDENT] = false
-#
-# Note that the *current* setting *may not* be changed in the IRB session.
-#
-# ### Input Method
-#
-# The IRB input method determines how command input is to be read; by default,
-# the input method for a session is IRB::RelineInputMethod. Unless the
-# value of the TERM environment variable is 'dumb', in which case the
-# most simplistic input method is used.
-#
-# You can set the input method by:
-#
-# * Adding to the configuration file:
-#
-# * `IRB.conf[:USE_SINGLELINE] = true` or `IRB.conf[:USE_MULTILINE]=
-# false` sets the input method to IRB::ReadlineInputMethod.
-# * `IRB.conf[:USE_SINGLELINE] = false` or `IRB.conf[:USE_MULTILINE] =
-# true` sets the input method to IRB::RelineInputMethod.
-#
-#
-# * Giving command-line options:
-#
-# * `--singleline` or `--nomultiline` sets the input method to
-# IRB::ReadlineInputMethod.
-# * `--nosingleline` or `--multiline` sets the input method to
-# IRB::RelineInputMethod.
-# * `--nosingleline` together with `--nomultiline` sets the
-# input to IRB::StdioInputMethod.
-#
-#
-# Method `conf.use_multiline?` and its synonym `conf.use_reline` return:
-#
-# * `true` if option `--multiline` was given.
-# * `false` if option `--nomultiline` was given.
-# * `nil` if neither was given.
-#
-#
-# Method `conf.use_singleline?` and its synonym `conf.use_readline` return:
-#
-# * `true` if option `--singleline` was given.
-# * `false` if option `--nosingleline` was given.
-# * `nil` if neither was given.
-#
-#
-# ## Output
-#
-# This section describes the features that allow you to change the way IRB
-# output works; see also [Input and Output](rdoc-ref:IRB@Input+and+Output).
-#
-# ### Return-Value Printing (Echoing)
-#
-# By default, IRB prints (echoes) the values returned by all input commands.
-#
-# You can change the initial behavior and suppress all echoing by:
-#
-# * Adding to the configuration file: `IRB.conf[:ECHO] = false`. (The default
-# value for this entry is `nil`, which means the same as `true`.)
-# * Giving command-line option `--noecho`. (The default is `--echo`.)
-#
-#
-# During the session, you can change the current setting with configuration
-# method `conf.echo=` (set to `true` or `false`).
-#
-# As stated above, by default IRB prints the values returned by all input
-# commands; but IRB offers special treatment for values returned by assignment
-# statements, which may be:
-#
-# * Printed with truncation (to fit on a single line of output), which is the
-# default; an ellipsis (`...` is suffixed, to indicate the truncation):
-#
-# irb(main):001> x = 'abc' * 100
-#
-#
-# > "abcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabcabc...
-#
-# * Printed in full (regardless of the length).
-# * Suppressed (not printed at all)
-#
-#
-# You can change the initial behavior by:
-#
-# * Adding to the configuration file: `IRB.conf[:ECHO_ON_ASSIGNMENT] = false`.
-# (The default value for this entry is `niL`, which means the same as
-# `:truncate`.)
-# * Giving command-line option `--noecho-on-assignment` or
-# `--echo-on-assignment`. (The default is `--truncate-echo-on-assignment`.)
-#
-#
-# During the session, you can change the current setting with configuration
-# method `conf.echo_on_assignment=` (set to `true`, `false`, or `:truncate`).
-#
-# By default, IRB formats returned values by calling method `inspect`.
-#
-# You can change the initial behavior by:
-#
-# * Adding to the configuration file: `IRB.conf[:INSPECT_MODE] = false`. (The
-# default value for this entry is `true`.)
-# * Giving command-line option `--noinspect`. (The default is `--inspect`.)
-#
-#
-# During the session, you can change the setting using method
-# `conf.inspect_mode=`.
-#
-# ### Multiline Output
-#
-# By default, IRB prefixes a newline to a multiline response.
-#
-# You can change the initial default value by adding to the configuration file:
-#
-# IRB.conf[:NEWLINE_BEFORE_MULTILINE_OUTPUT] = false
-#
-# During a session, you can retrieve or set the value using methods
-# `conf.newline_before_multiline_output?` and
-# `conf.newline_before_multiline_output=`.
-#
-# Examples:
-#
-# irb(main):001> conf.inspect_mode = false
-# => false
-# irb(main):002> "foo\nbar"
-# =>
-# foo
-# bar
-# irb(main):003> conf.newline_before_multiline_output = false
-# => false
-# irb(main):004> "foo\nbar"
-# => foo
-# bar
-#
-# ### Evaluation History
-#
-# By default, IRB saves no history of evaluations (returned values), and the
-# related methods `conf.eval_history`, `_`, and `__` are undefined.
-#
-# You can turn on that history, and set the maximum number of evaluations to be
-# stored:
-#
-# * In the configuration file: add `IRB.conf[:EVAL_HISTORY] = *n*`. (Examples
-# below assume that we've added `IRB.conf[:EVAL_HISTORY] = 5`.)
-# * In the session (at any time): `conf.eval_history = *n*`.
-#
-#
-# If `n` is zero, all evaluation history is stored.
-#
-# Doing either of the above:
-#
-# * Sets the maximum size of the evaluation history; defines method
-# `conf.eval_history`, which returns the maximum size `n` of the evaluation
-# history:
-#
-# irb(main):001> conf.eval_history = 5
-# => 5
-# irb(main):002> conf.eval_history
-# => 5
-#
-# * Defines variable `_`, which contains the most recent evaluation, or `nil`
-# if none; same as method `conf.last_value`:
-#
-# irb(main):003> _
-# => 5
-# irb(main):004> :foo
-# => :foo
-# irb(main):005> :bar
-# => :bar
-# irb(main):006> _
-# => :bar
-# irb(main):007> _
-# => :bar
-#
-# * Defines variable `__`:
-#
-# * `__` unadorned: contains all evaluation history:
-#
-# irb(main):008> :foo
-# => :foo
-# irb(main):009> :bar
-# => :bar
-# irb(main):010> :baz
-# => :baz
-# irb(main):011> :bat
-# => :bat
-# irb(main):012> :bam
-# => :bam
-# irb(main):013> __
-# =>
-# 9 :bar
-# 10 :baz
-# 11 :bat
-# 12 :bam
-# irb(main):014> __
-# =>
-# 10 :baz
-# 11 :bat
-# 12 :bam
-# 13 ...self-history...
-#
-# Note that when the evaluation is multiline, it is displayed
-# differently.
-#
-# * `__[`*m*`]`:
-#
-# * Positive *m*: contains the evaluation for the given line number,
-# or `nil` if that line number is not in the evaluation history:
-#
-# irb(main):015> __[12]
-# => :bam
-# irb(main):016> __[1]
-# => nil
-#
-# * Negative *m*: contains the `mth`-from-end evaluation, or `nil` if
-# that evaluation is not in the evaluation history:
-#
-# irb(main):017> __[-3]
-# => :bam
-# irb(main):018> __[-13]
-# => nil
-#
-# * Zero *m*: contains `nil`:
-#
-# irb(main):019> __[0]
-# => nil
-#
-#
-#
-#
-# ### Prompt and Return Formats
-#
-# By default, IRB uses the prompt and return value formats defined in its
-# `:DEFAULT` prompt mode.
-#
-# #### The Default Prompt and Return Format
-#
-# The default prompt and return values look like this:
-#
-# irb(main):001> 1 + 1
-# => 2
-# irb(main):002> 2 + 2
-# => 4
-#
-# The prompt includes:
-#
-# * The name of the running program (`irb`); see [IRB
-# Name](rdoc-ref:IRB@IRB+Name).
-# * The name of the current session (`main`); See [IRB
-# Sessions](rdoc-ref:IRB@IRB+Sessions).
-# * A 3-digit line number (1-based).
-#
-#
-# The default prompt actually defines three formats:
-#
-# * One for most situations (as above):
-#
-# irb(main):003> Dir
-# => Dir
-#
-# * One for when the typed command is a statement continuation (adds trailing
-# asterisk):
-#
-# irb(main):004* Dir.
-#
-# * One for when the typed command is a string continuation (adds trailing
-# single-quote):
-#
-# irb(main):005' Dir.entries('.
-#
-#
-# You can see the prompt change as you type the characters in the following:
-#
-# irb(main):001* Dir.entries('.').select do |entry|
-# irb(main):002* entry.start_with?('R')
-# irb(main):003> end
-# => ["README.md", "Rakefile"]
-#
-# #### Pre-Defined Prompts
-#
-# IRB has several pre-defined prompts, stored in hash `IRB.conf[:PROMPT]`:
-#
-# irb(main):001> IRB.conf[:PROMPT].keys
-# => [:NULL, :DEFAULT, :CLASSIC, :SIMPLE, :INF_RUBY, :XMP]
-#
-# To see the full data for these, type `IRB.conf[:PROMPT]`.
-#
-# Most of these prompt definitions include specifiers that represent values like
-# the IRB name, session name, and line number; see [Prompt
-# Specifiers](rdoc-ref:IRB@Prompt+Specifiers).
-#
-# You can change the initial prompt and return format by:
-#
-# * Adding to the configuration file: `IRB.conf[:PROMPT] = *mode*` where
-# *mode* is the symbol name of a prompt mode.
-# * Giving a command-line option:
-#
-# * `--prompt *mode*`: sets the prompt mode to *mode*. where *mode* is the
-# symbol name of a prompt mode.
-# * `--simple-prompt` or `--sample-book-mode`: sets the prompt mode to
-# `:SIMPLE`.
-# * `--inf-ruby-mode`: sets the prompt mode to `:INF_RUBY` and suppresses
-# both `--multiline` and `--singleline`.
-# * `--noprompt`: suppresses prompting; does not affect echoing.
-#
-#
-#
-# You can retrieve or set the current prompt mode with methods
-#
-# `conf.prompt_mode` and `conf.prompt_mode=`.
-#
-# If you're interested in prompts and return formats other than the defaults,
-# you might experiment by trying some of the others.
-#
-# #### Custom Prompts
-#
-# You can also define custom prompts and return formats, which may be done
-# either in an IRB session or in the configuration file.
-#
-# A prompt in IRB actually defines three prompts, as seen above. For simple
-# custom data, we'll make all three the same:
-#
-# irb(main):001* IRB.conf[:PROMPT][:MY_PROMPT] = {
-# irb(main):002* PROMPT_I: ': ',
-# irb(main):003* PROMPT_C: ': ',
-# irb(main):004* PROMPT_S: ': ',
-# irb(main):005* RETURN: '=> '
-# irb(main):006> }
-# => {:PROMPT_I=>": ", :PROMPT_C=>": ", :PROMPT_S=>": ", :RETURN=>"=> "}
-#
-# If you define the custom prompt in the configuration file, you can also make
-# it the current prompt by adding:
-#
-# IRB.conf[:PROMPT_MODE] = :MY_PROMPT
-#
-# Regardless of where it's defined, you can make it the current prompt in a
-# session:
-#
-# conf.prompt_mode = :MY_PROMPT
-#
-# You can view or modify the current prompt data with various configuration
-# methods:
-#
-# * `conf.prompt_mode`, `conf.prompt_mode=`.
-# * `conf.prompt_c`, `conf.c=`.
-# * `conf.prompt_i`, `conf.i=`.
-# * `conf.prompt_s`, `conf.s=`.
-# * `conf.return_format`, `return_format=`.
-#
-#
-# #### Prompt Specifiers
-#
-# A prompt's definition can include specifiers for which certain values are
-# substituted:
-#
-# * `%N`: the name of the running program.
-# * `%m`: the value of `self.to_s`.
-# * `%M`: the value of `self.inspect`.
-# * `%l`: an indication of the type of string; one of `"`, `'`, `/`, `]`.
-# * `%NNi`: Indentation level. NN is a 2-digit number that specifies the number
-# of digits of the indentation level (03 will result in 001).
-# * `%NNn`: Line number. NN is a 2-digit number that specifies the number
-# of digits of the line number (03 will result in 001).
-# * `%%`: Literal `%`.
-#
-#
-# ### Verbosity
-#
-# By default, IRB verbosity is disabled, which means that output is smaller
-# rather than larger.
-#
-# You can enable verbosity by:
-#
-# * Adding to the configuration file: `IRB.conf[:VERBOSE] = true` (the default
-# is `nil`).
-# * Giving command-line options `--verbose` (the default is `--noverbose`).
-#
-#
-# During a session, you can retrieve or set verbosity with methods
-# `conf.verbose` and `conf.verbose=`.
-#
-# ### Help
-#
-# Command-line option `--version` causes IRB to print its help text and exit.
-#
-# ### Version
-#
-# Command-line option `--version` causes IRB to print its version text and exit.
-#
-# ## Input and Output
-#
-# ### Color Highlighting
-#
-# By default, IRB color highlighting is enabled, and is used for both:
-#
-# * Input: As you type, IRB reads the typed characters and highlights elements
-# that it recognizes; it also highlights errors such as mismatched
-# parentheses.
-# * Output: IRB highlights syntactical elements.
-#
-#
-# You can disable color highlighting by:
-#
-# * Adding to the configuration file: `IRB.conf[:USE_COLORIZE] = false` (the
-# default value is `true`).
-# * Giving command-line option `--nocolorize`
-#
-#
-# ## Debugging
-#
-# Command-line option `-d` sets variables `$VERBOSE` and `$DEBUG` to `true`;
-# these have no effect on IRB output.
-#
-# ### Warnings
-#
-# Command-line option `-w` suppresses warnings.
-#
-# Command-line option `-W[*level*]` sets warning level;
-#
-# * 0=silence
-# * 1=medium
-# * 2=verbose
-#
-# ## Other Features
-#
-# ### Load Modules
-#
-# You can specify the names of modules that are to be required at startup.
-#
-# Array `conf.load_modules` determines the modules (if any) that are to be
-# required during session startup. The array is used only during session
-# startup, so the initial value is the only one that counts.
-#
-# The default initial value is `[]` (load no modules):
-#
-# irb(main):001> conf.load_modules
-# => []
-#
-# You can set the default initial value via:
-#
-# * Command-line option `-r`
-#
-# $ irb -r csv -r json
-# irb(main):001> conf.load_modules
-# => ["csv", "json"]
-#
-# * Hash entry `IRB.conf[:LOAD_MODULES] = *array*`:
-#
-# IRB.conf[:LOAD_MODULES] = %w[csv, json]
-#
-#
-# Note that the configuration file entry overrides the command-line options.
-#
-# ### RI Documentation Directories
-#
-# You can specify the paths to RI documentation directories that are to be
-# loaded (in addition to the default directories) at startup; see details about
-# RI by typing `ri --help`.
-#
-# Array `conf.extra_doc_dirs` determines the directories (if any) that are to be
-# loaded during session startup. The array is used only during session startup,
-# so the initial value is the only one that counts.
-#
-# The default initial value is `[]` (load no extra documentation):
-#
-# irb(main):001> conf.extra_doc_dirs
-# => []
-#
-# You can set the default initial value via:
-#
-# * Command-line option `--extra_doc_dir`
-#
-# $ irb --extra-doc-dir your_doc_dir --extra-doc-dir my_doc_dir
-# irb(main):001> conf.extra_doc_dirs
-# => ["your_doc_dir", "my_doc_dir"]
-#
-# * Hash entry `IRB.conf[:EXTRA_DOC_DIRS] = *array*`:
-#
-# IRB.conf[:EXTRA_DOC_DIRS] = %w[your_doc_dir my_doc_dir]
-#
-#
-# Note that the configuration file entry overrides the command-line options.
-#
-# ### IRB Name
-#
-# You can specify a name for IRB.
-#
-# The default initial value is `'irb'`:
-#
-# irb(main):001> conf.irb_name
-# => "irb"
-#
-# You can set the default initial value via hash entry `IRB.conf[:IRB_NAME] =
-# *string*`:
-#
-# IRB.conf[:IRB_NAME] = 'foo'
-#
-# ### Application Name
-#
-# You can specify an application name for the IRB session.
-#
-# The default initial value is `'irb'`:
-#
-# irb(main):001> conf.ap_name
-# => "irb"
-#
-# You can set the default initial value via hash entry `IRB.conf[:AP_NAME] =
-# *string*`:
-#
-# IRB.conf[:AP_NAME] = 'my_ap_name'
-#
-# ### Configuration Monitor
-#
-# You can monitor changes to the configuration by assigning a proc to
-# `IRB.conf[:IRB_RC]` in the configuration file:
-#
-# IRB.conf[:IRB_RC] = proc {|conf| puts conf.class }
-#
-# Each time the configuration is changed, that proc is called with argument
-# `conf`:
-#
-# ### Encodings
-#
-# Command-line option `-E *ex*[:*in*]` sets initial external (ex) and internal
-# (in) encodings.
-#
-# Command-line option `-U` sets both to UTF-8.
-#
-# ### Commands
-#
-# Please use the `help` command to see the list of available commands.
-#
-# ### IRB Sessions
-#
-# IRB has a special feature, that allows you to manage many sessions at once.
-#
-# You can create new sessions with Irb.irb, and get a list of current sessions
-# with the `jobs` command in the prompt.
-#
-# #### Configuration
-#
-# The command line options, or IRB.conf, specify the default behavior of
-# Irb.irb.
-#
-# On the other hand, each conf in IRB@Command-Line+Options is used to
-# individually configure IRB.irb.
-#
-# If a proc is set for `IRB.conf[:IRB_RC]`, its will be invoked after execution
-# of that proc with the context of the current session as its argument. Each
-# session can be configured using this mechanism.
-#
-# #### Session variables
-#
-# There are a few variables in every Irb session that can come in handy:
-#
-# `_`
-# : The value command executed, as a local variable
-# `__`
-# : The history of evaluated commands. Available only if
-# `IRB.conf[:EVAL_HISTORY]` is not `nil` (which is the default). See also
-# IRB::Context#eval_history= and IRB::History.
-# `__[line_no]`
-# : Returns the evaluation value at the given line number, `line_no`. If
-# `line_no` is a negative, the return value `line_no` many lines before the
-# most recent return value.
-#
-#
-# ## Restrictions
-#
-# Ruby code typed into IRB behaves the same as Ruby code in a file, except that:
-#
-# * Because IRB evaluates input immediately after it is syntactically
-# complete, some results may be slightly different.
-# * Forking may not be well behaved.
-#
-module IRB
-
- # An exception raised by IRB.irb_abort
- class Abort < Exception;end
-
- # The current IRB::Context of the session, see IRB.conf
- #
- # irb
- # irb(main):001:0> IRB.CurrentContext.irb_name = "foo"
- # foo(main):002:0> IRB.conf[:MAIN_CONTEXT].irb_name #=> "foo"
- def IRB.CurrentContext # :nodoc:
- IRB.conf[:MAIN_CONTEXT]
- end
-
- # Initializes IRB and creates a new Irb.irb object at the `TOPLEVEL_BINDING`
- def IRB.start(ap_path = nil)
- STDOUT.sync = true
- $0 = File::basename(ap_path, ".rb") if ap_path
-
- IRB.setup(ap_path)
-
- if @CONF[:SCRIPT]
- irb = Irb.new(nil, @CONF[:SCRIPT])
- else
- irb = Irb.new
- end
- irb.run(@CONF)
- end
-
- # Quits irb
- def IRB.irb_exit(*) # :nodoc:
- throw :IRB_EXIT, false
- end
-
- # Aborts then interrupts irb.
- #
- # Will raise an Abort exception, or the given `exception`.
- def IRB.irb_abort(irb, exception = Abort) # :nodoc:
- irb.context.thread.raise exception, "abort then interrupt!"
- end
-
- class Irb
- # Note: instance and index assignment expressions could also be written like:
- # "foo.bar=(1)" and "foo.[]=(1, bar)", when expressed that way, the former be
- # parsed as :assign and echo will be suppressed, but the latter is parsed as a
- # :method_add_arg and the output won't be suppressed
-
- PROMPT_MAIN_TRUNCATE_LENGTH = 32
- PROMPT_MAIN_TRUNCATE_OMISSION = '...'
- CONTROL_CHARACTERS_PATTERN = "\x00-\x1F"
-
- # Returns the current context of this irb session
- attr_reader :context
- # The lexer used by this irb session
- attr_accessor :scanner
-
- attr_reader :from_binding
-
- # Creates a new irb session
- def initialize(workspace = nil, input_method = nil, from_binding: false)
- @from_binding = from_binding
- @context = Context.new(self, workspace, input_method)
- @context.workspace.load_helper_methods_to_main
- @signal_status = :IN_IRB
- @scanner = RubyLex.new
- @line_no = 1
- end
-
- # A hook point for `debug` command's breakpoint after :IRB_EXIT as well as its
- # clean-up
- def debug_break
- # it means the debug integration has been activated
- if defined?(DEBUGGER__) && DEBUGGER__.respond_to?(:capture_frames_without_irb)
- # after leaving this initial breakpoint, revert the capture_frames patch
- DEBUGGER__.singleton_class.send(:alias_method, :capture_frames, :capture_frames_without_irb)
- # and remove the redundant method
- DEBUGGER__.singleton_class.send(:undef_method, :capture_frames_without_irb)
- end
- end
-
- def debug_readline(binding)
- workspace = IRB::WorkSpace.new(binding)
- context.replace_workspace(workspace)
- context.workspace.load_helper_methods_to_main
- @line_no += 1
-
- # When users run:
- # 1. Debugging commands, like `step 2`
- # 2. Any input that's not irb-command, like `foo = 123`
- #
- #
- # Irb#eval_input will simply return the input, and we need to pass it to the
- # debugger.
- input = nil
- forced_exit = catch(:IRB_EXIT) do
- if IRB.conf[:SAVE_HISTORY] && context.io.support_history_saving?
- # Previous IRB session's history has been saved when `Irb#run` is exited We need
- # to make sure the saved history is not saved again by resetting the counter
- context.io.reset_history_counter
-
- begin
- input = eval_input
- ensure
- context.io.save_history
- end
- else
- input = eval_input
- end
- false
- end
-
- Kernel.exit if forced_exit
-
- if input&.include?("\n")
- @line_no += input.count("\n") - 1
- end
-
- input
- end
-
- def run(conf = IRB.conf)
- in_nested_session = !!conf[:MAIN_CONTEXT]
- conf[:IRB_RC].call(context) if conf[:IRB_RC]
- prev_context = conf[:MAIN_CONTEXT]
- conf[:MAIN_CONTEXT] = context
-
- save_history = !in_nested_session && conf[:SAVE_HISTORY] && context.io.support_history_saving?
-
- if save_history
- context.io.load_history
- end
-
- prev_trap = trap("SIGINT") do
- signal_handle
- end
-
- begin
- if defined?(RubyVM.keep_script_lines)
- keep_script_lines_backup = RubyVM.keep_script_lines
- RubyVM.keep_script_lines = true
- end
-
- forced_exit = catch(:IRB_EXIT) do
- eval_input
- end
- ensure
- # Do not restore to nil. It will cause IRB crash when used with threads.
- IRB.conf[:MAIN_CONTEXT] = prev_context if prev_context
-
- RubyVM.keep_script_lines = keep_script_lines_backup if defined?(RubyVM.keep_script_lines)
- trap("SIGINT", prev_trap)
- conf[:AT_EXIT].each{|hook| hook.call}
-
- context.io.save_history if save_history
- Kernel.exit if forced_exit
- end
- end
-
- # Evaluates input for this session.
- def eval_input
- configure_io
-
- each_top_level_statement do |statement, line_no|
- signal_status(:IN_EVAL) do
- begin
- # If the integration with debugger is activated, we return certain input if it
- # should be dealt with by debugger
- if @context.with_debugger && statement.should_be_handled_by_debugger?
- return statement.code
- end
-
- @context.evaluate(statement, line_no)
-
- if @context.echo? && !statement.suppresses_echo?
- if statement.is_assignment?
- if @context.echo_on_assignment?
- output_value(@context.echo_on_assignment? == :truncate)
- end
- else
- output_value
- end
- end
- rescue SystemExit, SignalException
- raise
- rescue Interrupt, Exception => exc
- handle_exception(exc)
- @context.workspace.local_variable_set(:_, exc)
- end
- end
- end
- end
-
- def read_input(prompt)
- signal_status(:IN_INPUT) do
- @context.io.prompt = prompt
- if l = @context.io.gets
- print l if @context.verbose?
- else
- if @context.ignore_eof? and @context.io.readable_after_eof?
- l = "\n"
- if @context.verbose?
- printf "Use \"exit\" to leave %s\n", @context.ap_name
- end
- else
- print "\n" if @context.prompting?
- end
- end
- l
- end
- end
-
- def readmultiline
- prompt = generate_prompt([], false, 0)
-
- # multiline
- return read_input(prompt) if @context.io.respond_to?(:check_termination)
-
- # nomultiline
- code = +''
- line_offset = 0
- loop do
- line = read_input(prompt)
- unless line
- return code.empty? ? nil : code
- end
-
- code << line
- return code if command?(code)
-
- tokens, opens, terminated = @scanner.check_code_state(code, local_variables: @context.local_variables)
- return code if terminated
-
- line_offset += 1
- continue = @scanner.should_continue?(tokens)
- prompt = generate_prompt(opens, continue, line_offset)
- end
- end
-
- def each_top_level_statement
- loop do
- code = readmultiline
- break unless code
- yield build_statement(code), @line_no
- @line_no += code.count("\n")
- rescue RubyLex::TerminateLineInput
- end
- end
-
- def build_statement(code)
- if code.match?(/\A\n*\z/)
- return Statement::EmptyInput.new
- end
-
- code.force_encoding(@context.io.encoding)
- if (command, arg = parse_command(code))
- command_class = Command.load_command(command)
- Statement::Command.new(code, command_class, arg)
- else
- is_assignment_expression = @scanner.assignment_expression?(code, local_variables: @context.local_variables)
- Statement::Expression.new(code, is_assignment_expression)
- end
- end
-
- def parse_command(code)
- command_name, arg = code.strip.split(/\s+/, 2)
- return unless code.lines.size == 1 && command_name
-
- arg ||= ''
- command = command_name.to_sym
- # Command aliases are always command. example: $, @
- if (alias_name = @context.command_aliases[command])
- return [alias_name, arg]
- end
-
- # Check visibility
- public_method = !!Kernel.instance_method(:public_method).bind_call(@context.main, command) rescue false
- private_method = !public_method && !!Kernel.instance_method(:method).bind_call(@context.main, command) rescue false
- if Command.execute_as_command?(command, public_method: public_method, private_method: private_method)
- [command, arg]
- end
- end
-
- def command?(code)
- !!parse_command(code)
- end
-
- def configure_io
- if @context.io.respond_to?(:check_termination)
- @context.io.check_termination do |code|
- if Reline::IOGate.in_pasting?
- rest = @scanner.check_termination_in_prev_line(code, local_variables: @context.local_variables)
- if rest
- Reline.delete_text
- rest.bytes.reverse_each do |c|
- Reline.ungetc(c)
- end
- true
- else
- false
- end
- else
- next true if command?(code)
-
- _tokens, _opens, terminated = @scanner.check_code_state(code, local_variables: @context.local_variables)
- terminated
- end
- end
- end
- if @context.io.respond_to?(:dynamic_prompt)
- @context.io.dynamic_prompt do |lines|
- tokens = RubyLex.ripper_lex_without_warning(lines.map{ |l| l + "\n" }.join, local_variables: @context.local_variables)
- line_results = IRB::NestingParser.parse_by_line(tokens)
- tokens_until_line = []
- line_results.map.with_index do |(line_tokens, _prev_opens, next_opens, _min_depth), line_num_offset|
- line_tokens.each do |token, _s|
- # Avoid appending duplicated token. Tokens that include "n" like multiline
- # tstring_content can exist in multiple lines.
- tokens_until_line << token if token != tokens_until_line.last
- end
- continue = @scanner.should_continue?(tokens_until_line)
- generate_prompt(next_opens, continue, line_num_offset)
- end
- end
- end
-
- if @context.io.respond_to?(:auto_indent) and @context.auto_indent_mode
- @context.io.auto_indent do |lines, line_index, byte_pointer, is_newline|
- next nil if lines == [nil] # Workaround for exit IRB with CTRL+d
- next nil if !is_newline && lines[line_index]&.byteslice(0, byte_pointer)&.match?(/\A\s*\z/)
-
- code = lines[0..line_index].map { |l| "#{l}\n" }.join
- tokens = RubyLex.ripper_lex_without_warning(code, local_variables: @context.local_variables)
- @scanner.process_indent_level(tokens, lines, line_index, is_newline)
- end
- end
- end
-
- def convert_invalid_byte_sequence(str, enc)
- str.force_encoding(enc)
- str.scrub { |c|
- c.bytes.map{ |b| "\\x#{b.to_s(16).upcase}" }.join
- }
- end
-
- def encode_with_invalid_byte_sequence(str, enc)
- conv = Encoding::Converter.new(str.encoding, enc)
- dst = String.new
- begin
- ret = conv.primitive_convert(str, dst)
- case ret
- when :invalid_byte_sequence
- conv.insert_output(conv.primitive_errinfo[3].dump[1..-2])
- redo
- when :undefined_conversion
- c = conv.primitive_errinfo[3].dup.force_encoding(conv.primitive_errinfo[1])
- conv.insert_output(c.dump[1..-2])
- redo
- when :incomplete_input
- conv.insert_output(conv.primitive_errinfo[3].dump[1..-2])
- when :finished
- end
- break
- end while nil
- dst
- end
-
- def handle_exception(exc)
- if exc.backtrace[0] =~ /\/irb(2)?(\/.*|-.*|\.rb)?:/ && exc.class.to_s !~ /^IRB/ &&
- !(SyntaxError === exc) && !(EncodingError === exc)
- # The backtrace of invalid encoding hash (ex. {"\xAE": 1}) raises EncodingError without lineno.
- irb_bug = true
- else
- irb_bug = false
- # To support backtrace filtering while utilizing Exception#full_message, we need to clone
- # the exception to avoid modifying the original exception's backtrace.
- exc = exc.clone
- filtered_backtrace = exc.backtrace.map { |l| @context.workspace.filter_backtrace(l) }.compact
- backtrace_filter = IRB.conf[:BACKTRACE_FILTER]
-
- if backtrace_filter
- if backtrace_filter.respond_to?(:call)
- filtered_backtrace = backtrace_filter.call(filtered_backtrace)
- else
- warn "IRB.conf[:BACKTRACE_FILTER] #{backtrace_filter} should respond to `call` method"
- end
- end
-
- exc.set_backtrace(filtered_backtrace)
- end
-
- highlight = Color.colorable?
-
- order =
- if RUBY_VERSION < '3.0.0'
- STDOUT.tty? ? :bottom : :top
- else # '3.0.0' <= RUBY_VERSION
- :top
- end
-
- message = exc.full_message(order: order, highlight: highlight)
- 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
- 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 "<top (required)>" in "(irb)" may be the top level of IRB so imitate the main object.
- message = message.gsub(/\(irb\):(?<num>\d+):in (?<open_quote>[`'])<(?<frame>top \(required\))>'/) { "(irb):#{$~[:num]}:in #{$~[:open_quote]}<main>'" }
- puts message
- puts 'Maybe IRB bug!' if irb_bug
- rescue Exception => handler_exc
- begin
- puts exc.inspect
- puts "backtraces are hidden because #{handler_exc} was raised when processing them"
- rescue Exception
- puts 'Uninspectable exception occurred'
- end
- end
-
- # Evaluates the given block using the given `path` as the Context#irb_path and
- # `name` as the Context#irb_name.
- #
- # Used by the irb command `source`, see IRB@IRB+Sessions for more information.
- def suspend_name(path = nil, name = nil)
- @context.irb_path, back_path = path, @context.irb_path if path
- @context.irb_name, back_name = name, @context.irb_name if name
- begin
- yield back_path, back_name
- ensure
- @context.irb_path = back_path if path
- @context.irb_name = back_name if name
- end
- end
-
- # Evaluates the given block using the given `workspace` as the
- # Context#workspace.
- #
- # Used by the irb command `irb_load`, see IRB@IRB+Sessions for more information.
- def suspend_workspace(workspace)
- current_workspace = @context.workspace
- @context.replace_workspace(workspace)
- yield
- ensure
- @context.replace_workspace current_workspace
- end
-
- # Evaluates the given block using the given `input_method` as the Context#io.
- #
- # Used by the irb commands `source` and `irb_load`, see IRB@IRB+Sessions for
- # more information.
- def suspend_input_method(input_method)
- back_io = @context.io
- @context.instance_eval{@io = input_method}
- begin
- yield back_io
- ensure
- @context.instance_eval{@io = back_io}
- end
- end
-
- # Handler for the signal SIGINT, see Kernel#trap for more information.
- def signal_handle
- unless @context.ignore_sigint?
- print "\nabort!\n" if @context.verbose?
- exit
- end
-
- case @signal_status
- when :IN_INPUT
- print "^C\n"
- raise RubyLex::TerminateLineInput
- when :IN_EVAL
- IRB.irb_abort(self)
- when :IN_LOAD
- IRB.irb_abort(self, LoadAbort)
- when :IN_IRB
- # ignore
- else
- # ignore other cases as well
- end
- end
-
- # Evaluates the given block using the given `status`.
- def signal_status(status)
- return yield if @signal_status == :IN_LOAD
-
- signal_status_back = @signal_status
- @signal_status = status
- begin
- yield
- ensure
- @signal_status = signal_status_back
- end
- end
-
- def output_value(omit = false) # :nodoc:
- str = @context.inspect_last_value
- multiline_p = str.include?("\n")
- if omit
- winwidth = @context.io.winsize.last
- if multiline_p
- first_line = str.split("\n").first
- result = @context.newline_before_multiline_output? ? (@context.return_format % first_line) : first_line
- output_width = Reline::Unicode.calculate_width(result, true)
- diff_size = output_width - Reline::Unicode.calculate_width(first_line, true)
- if diff_size.positive? and output_width > winwidth
- lines, _ = Reline::Unicode.split_by_width(first_line, winwidth - diff_size - 3)
- str = "%s..." % lines.first
- str += "\e[0m" if Color.colorable?
- multiline_p = false
- else
- str = str.gsub(/(\A.*?\n).*/m, "\\1...")
- str += "\e[0m" if Color.colorable?
- end
- else
- output_width = Reline::Unicode.calculate_width(@context.return_format % str, true)
- diff_size = output_width - Reline::Unicode.calculate_width(str, true)
- if diff_size.positive? and output_width > winwidth
- lines, _ = Reline::Unicode.split_by_width(str, winwidth - diff_size - 3)
- str = "%s..." % lines.first
- str += "\e[0m" if Color.colorable?
- end
- end
- end
-
- if multiline_p && @context.newline_before_multiline_output?
- str = "\n" + str
- end
-
- Pager.page_content(format(@context.return_format, str), retain_content: true)
- end
-
- # Outputs the local variables to this current session, including #signal_status
- # and #context, using IRB::Locale.
- def inspect
- ary = []
- for iv in instance_variables
- case (iv = iv.to_s)
- when "@signal_status"
- ary.push format("%s=:%s", iv, @signal_status.id2name)
- when "@context"
- ary.push format("%s=%s", iv, eval(iv).__to_s__)
- else
- ary.push format("%s=%s", iv, eval(iv))
- end
- end
- format("#<%s: %s>", self.class, ary.join(", "))
- end
-
- private
-
- def generate_prompt(opens, continue, line_offset)
- ltype = @scanner.ltype_from_open_tokens(opens)
- indent = @scanner.calc_indent_level(opens)
- continue = opens.any? || continue
- line_no = @line_no + line_offset
-
- if ltype
- f = @context.prompt_s
- elsif continue
- f = @context.prompt_c
- else
- f = @context.prompt_i
- end
- f = "" unless f
- if @context.prompting?
- p = format_prompt(f, ltype, indent, line_no)
- else
- p = ""
- end
- if @context.auto_indent_mode and !@context.io.respond_to?(:auto_indent)
- unless ltype
- prompt_i = @context.prompt_i.nil? ? "" : @context.prompt_i
- ind = format_prompt(prompt_i, ltype, indent, line_no)[/.*\z/].size +
- indent * 2 - p.size
- p += " " * ind if ind > 0
- end
- end
- p
- end
-
- def truncate_prompt_main(str) # :nodoc:
- str = str.tr(CONTROL_CHARACTERS_PATTERN, ' ')
- if str.size <= PROMPT_MAIN_TRUNCATE_LENGTH
- str
- else
- str[0, PROMPT_MAIN_TRUNCATE_LENGTH - PROMPT_MAIN_TRUNCATE_OMISSION.size] + PROMPT_MAIN_TRUNCATE_OMISSION
- end
- end
-
- def format_prompt(format, ltype, indent, line_no) # :nodoc:
- format.gsub(/%([0-9]+)?([a-zA-Z%])/) do
- case $2
- when "N"
- @context.irb_name
- when "m"
- main_str = @context.main.to_s rescue "!#{$!.class}"
- truncate_prompt_main(main_str)
- when "M"
- main_str = @context.main.inspect rescue "!#{$!.class}"
- truncate_prompt_main(main_str)
- when "l"
- ltype
- when "i"
- if indent < 0
- if $1
- "-".rjust($1.to_i)
- else
- "-"
- end
- else
- if $1
- format("%" + $1 + "d", indent)
- else
- indent.to_s
- end
- end
- when "n"
- if $1
- format("%" + $1 + "d", line_no)
- else
- line_no.to_s
- end
- when "%"
- "%" unless $1
- end
- end
- end
- end
-end
-
-class Binding
- # Opens an IRB session where `binding.irb` is called which allows for
- # interactive debugging. You can call any methods or variables available in the
- # current scope, and mutate state if you need to.
- #
- # Given a Ruby file called `potato.rb` containing the following code:
- #
- # class Potato
- # def initialize
- # @cooked = false
- # binding.irb
- # puts "Cooked potato: #{@cooked}"
- # end
- # end
- #
- # Potato.new
- #
- # Running `ruby potato.rb` will open an IRB session where `binding.irb` is
- # called, and you will see the following:
- #
- # $ ruby potato.rb
- #
- # From: potato.rb @ line 4 :
- #
- # 1: class Potato
- # 2: def initialize
- # 3: @cooked = false
- # => 4: binding.irb
- # 5: puts "Cooked potato: #{@cooked}"
- # 6: end
- # 7: end
- # 8:
- # 9: Potato.new
- #
- # irb(#<Potato:0x00007feea1916670>):001:0>
- #
- # You can type any valid Ruby code and it will be evaluated in the current
- # context. This allows you to debug without having to run your code repeatedly:
- #
- # irb(#<Potato:0x00007feea1916670>):001:0> @cooked
- # => false
- # irb(#<Potato:0x00007feea1916670>):002:0> self.class
- # => Potato
- # irb(#<Potato:0x00007feea1916670>):003:0> caller.first
- # => ".../2.5.1/lib/ruby/2.5.0/irb/workspace.rb:85:in `eval'"
- # irb(#<Potato:0x00007feea1916670>):004:0> @cooked = true
- # => true
- #
- # You can exit the IRB session with the `exit` command. Note that exiting will
- # resume execution where `binding.irb` had paused it, as you can see from the
- # output printed to standard output in this example:
- #
- # irb(#<Potato:0x00007feea1916670>):005:0> exit
- # Cooked potato: true
- #
- # See IRB for more information.
- def irb(show_code: true)
- # Setup IRB with the current file's path and no command line arguments
- IRB.setup(source_location[0], argv: []) unless IRB.initialized?
- # Create a new workspace using the current binding
- workspace = IRB::WorkSpace.new(self)
- # Print the code around the binding if show_code is true
- STDOUT.print(workspace.code_around_binding) if show_code
- # Get the original IRB instance
- debugger_irb = IRB.instance_variable_get(:@debugger_irb)
-
- irb_path = File.expand_path(source_location[0])
-
- if debugger_irb
- # If we're already in a debugger session, set the workspace and irb_path for the original IRB instance
- debugger_irb.context.replace_workspace(workspace)
- debugger_irb.context.irb_path = irb_path
- # If we've started a debugger session and hit another binding.irb, we don't want
- # to start an IRB session instead, we want to resume the irb:rdbg session.
- IRB::Debug.setup(debugger_irb)
- IRB::Debug.insert_debug_break
- debugger_irb.debug_break
- else
- # If we're not in a debugger session, create a new IRB instance with the current
- # workspace
- binding_irb = IRB::Irb.new(workspace, from_binding: true)
- binding_irb.context.irb_path = irb_path
- binding_irb.run(IRB.conf)
- binding_irb.debug_break
- end
- end
-end
diff --git a/lib/irb/.document b/lib/irb/.document
deleted file mode 100644
index 3b0d6fa4ed..0000000000
--- a/lib/irb/.document
+++ /dev/null
@@ -1 +0,0 @@
-**/*.rb
diff --git a/lib/irb/cmd/nop.rb b/lib/irb/cmd/nop.rb
deleted file mode 100644
index 9d2e3c4d47..0000000000
--- a/lib/irb/cmd/nop.rb
+++ /dev/null
@@ -1,4 +0,0 @@
-# frozen_string_literal: true
-
-# This file is just a placeholder for backward-compatibility.
-# Please require 'irb' and inherit your command from `IRB::Command::Base` instead.
diff --git a/lib/irb/color.rb b/lib/irb/color.rb
deleted file mode 100644
index fca942b28b..0000000000
--- a/lib/irb/color.rb
+++ /dev/null
@@ -1,262 +0,0 @@
-# frozen_string_literal: true
-require 'reline'
-require 'ripper'
-require_relative 'ruby-lex'
-
-module IRB # :nodoc:
- module Color
- CLEAR = 0
- BOLD = 1
- UNDERLINE = 4
- REVERSE = 7
- BLACK = 30
- RED = 31
- GREEN = 32
- YELLOW = 33
- BLUE = 34
- MAGENTA = 35
- CYAN = 36
- WHITE = 37
-
- TOKEN_KEYWORDS = {
- on_kw: ['nil', 'self', 'true', 'false', '__FILE__', '__LINE__', '__ENCODING__'],
- on_const: ['ENV'],
- }
- private_constant :TOKEN_KEYWORDS
-
- # A constant of all-bit 1 to match any Ripper's state in #dispatch_seq
- ALL = -1
- private_constant :ALL
-
- begin
- # Following pry's colors where possible, but sometimes having a compromise like making
- # backtick and regexp as red (string's color, because they're sharing tokens).
- TOKEN_SEQ_EXPRS = {
- on_CHAR: [[BLUE, BOLD], ALL],
- on_backtick: [[RED, BOLD], ALL],
- on_comment: [[BLUE, BOLD], ALL],
- on_const: [[BLUE, BOLD, UNDERLINE], ALL],
- on_embexpr_beg: [[RED], ALL],
- on_embexpr_end: [[RED], ALL],
- on_embvar: [[RED], ALL],
- on_float: [[MAGENTA, BOLD], ALL],
- on_gvar: [[GREEN, BOLD], ALL],
- on_heredoc_beg: [[RED], ALL],
- on_heredoc_end: [[RED], ALL],
- on_ident: [[BLUE, BOLD], Ripper::EXPR_ENDFN],
- on_imaginary: [[BLUE, BOLD], ALL],
- on_int: [[BLUE, BOLD], ALL],
- on_kw: [[GREEN], ALL],
- on_label: [[MAGENTA], ALL],
- on_label_end: [[RED, BOLD], ALL],
- on_qsymbols_beg: [[RED, BOLD], ALL],
- on_qwords_beg: [[RED, BOLD], ALL],
- on_rational: [[BLUE, BOLD], ALL],
- on_regexp_beg: [[RED, BOLD], ALL],
- on_regexp_end: [[RED, BOLD], ALL],
- on_symbeg: [[YELLOW], ALL],
- on_symbols_beg: [[RED, BOLD], ALL],
- on_tstring_beg: [[RED, BOLD], ALL],
- on_tstring_content: [[RED], ALL],
- on_tstring_end: [[RED, BOLD], ALL],
- on_words_beg: [[RED, BOLD], ALL],
- on_parse_error: [[RED, REVERSE], ALL],
- compile_error: [[RED, REVERSE], ALL],
- on_assign_error: [[RED, REVERSE], ALL],
- on_alias_error: [[RED, REVERSE], ALL],
- on_class_name_error:[[RED, REVERSE], ALL],
- on_param_error: [[RED, REVERSE], ALL],
- on___end__: [[GREEN], ALL],
- }
- rescue NameError
- # Give up highlighting Ripper-incompatible older Ruby
- TOKEN_SEQ_EXPRS = {}
- end
- private_constant :TOKEN_SEQ_EXPRS
-
- ERROR_TOKENS = TOKEN_SEQ_EXPRS.keys.select { |k| k.to_s.end_with?('error') }
- private_constant :ERROR_TOKENS
-
- class << self
- def colorable?
- supported = $stdout.tty? && (/mswin|mingw/.match?(RUBY_PLATFORM) || (ENV.key?('TERM') && ENV['TERM'] != 'dumb'))
-
- # because ruby/debug also uses irb's color module selectively,
- # irb won't be activated in that case.
- if IRB.respond_to?(:conf)
- supported && !!IRB.conf.fetch(:USE_COLORIZE, true)
- else
- supported
- end
- end
-
- def inspect_colorable?(obj, seen: {}.compare_by_identity)
- case obj
- when String, Symbol, Regexp, Integer, Float, FalseClass, TrueClass, NilClass
- true
- when Hash
- without_circular_ref(obj, seen: seen) do
- obj.all? { |k, v| inspect_colorable?(k, seen: seen) && inspect_colorable?(v, seen: seen) }
- end
- when Array
- without_circular_ref(obj, seen: seen) do
- obj.all? { |o| inspect_colorable?(o, seen: seen) }
- end
- when Range
- inspect_colorable?(obj.begin, seen: seen) && inspect_colorable?(obj.end, seen: seen)
- when Module
- !obj.name.nil?
- else
- false
- end
- end
-
- def clear(colorable: colorable?)
- return '' unless colorable
- "\e[#{CLEAR}m"
- end
-
- def colorize(text, seq, colorable: colorable?)
- return text unless colorable
- seq = seq.map { |s| "\e[#{const_get(s)}m" }.join('')
- "#{seq}#{text}#{clear(colorable: colorable)}"
- end
-
- # If `complete` is false (code is incomplete), this does not warn compile_error.
- # This option is needed to avoid warning a user when the compile_error is happening
- # because the input is not wrong but just incomplete.
- def colorize_code(code, complete: true, ignore_error: false, colorable: colorable?, local_variables: [])
- return code unless colorable
-
- symbol_state = SymbolState.new
- colored = +''
- lvars_code = RubyLex.generate_local_variables_assign_code(local_variables)
- code_with_lvars = lvars_code ? "#{lvars_code}\n#{code}" : code
-
- scan(code_with_lvars, allow_last_error: !complete) do |token, str, expr|
- # handle uncolorable code
- if token.nil?
- colored << Reline::Unicode.escape_for_print(str)
- next
- end
-
- # IRB::ColorPrinter skips colorizing fragments with any invalid token
- if ignore_error && ERROR_TOKENS.include?(token)
- return Reline::Unicode.escape_for_print(code)
- end
-
- in_symbol = symbol_state.scan_token(token)
- str.each_line do |line|
- line = Reline::Unicode.escape_for_print(line)
- if seq = dispatch_seq(token, expr, line, in_symbol: in_symbol)
- colored << seq.map { |s| "\e[#{s}m" }.join('')
- colored << line.sub(/\Z/, clear(colorable: colorable))
- else
- colored << line
- end
- end
- end
-
- if lvars_code
- raise "#{lvars_code.dump} should have no \\n" if lvars_code.include?("\n")
- colored.sub!(/\A.+\n/, '') # delete_prefix lvars_code with colors
- end
- colored
- end
-
- private
-
- def without_circular_ref(obj, seen:, &block)
- return false if seen.key?(obj)
- seen[obj] = true
- block.call
- ensure
- seen.delete(obj)
- end
-
- def scan(code, allow_last_error:)
- verbose, $VERBOSE = $VERBOSE, nil
- RubyLex.compile_with_errors_suppressed(code) do |inner_code, line_no|
- lexer = Ripper::Lexer.new(inner_code, '(ripper)', line_no)
- byte_pos = 0
- line_positions = [0]
- inner_code.lines.each do |line|
- line_positions << line_positions.last + line.bytesize
- end
-
- on_scan = proc do |elem|
- start_pos = line_positions[elem.pos[0] - 1] + elem.pos[1]
-
- # yield uncolorable code
- if byte_pos < start_pos
- yield(nil, inner_code.byteslice(byte_pos...start_pos), nil)
- end
-
- if byte_pos <= start_pos
- str = elem.tok
- yield(elem.event, str, elem.state)
- byte_pos = start_pos + str.bytesize
- end
- end
-
- lexer.scan.each do |elem|
- next if allow_last_error and /meets end of file|unexpected end-of-input/ =~ elem.message
- on_scan.call(elem)
- end
- # yield uncolorable DATA section
- yield(nil, inner_code.byteslice(byte_pos...inner_code.bytesize), nil) if byte_pos < inner_code.bytesize
- end
- ensure
- $VERBOSE = verbose
- end
-
- def dispatch_seq(token, expr, str, in_symbol:)
- if ERROR_TOKENS.include?(token)
- TOKEN_SEQ_EXPRS[token][0]
- elsif in_symbol
- [YELLOW]
- elsif TOKEN_KEYWORDS.fetch(token, []).include?(str)
- [CYAN, BOLD]
- elsif (seq, exprs = TOKEN_SEQ_EXPRS[token]; (expr & (exprs || 0)) != 0)
- seq
- else
- nil
- end
- end
- end
-
- # A class to manage a state to know whether the current token is for Symbol or not.
- class SymbolState
- def initialize
- # Push `true` to detect Symbol. `false` to increase the nest level for non-Symbol.
- @stack = []
- end
-
- # Return true if the token is a part of Symbol.
- def scan_token(token)
- prev_state = @stack.last
- case token
- when :on_symbeg, :on_symbols_beg, :on_qsymbols_beg
- @stack << true
- when :on_ident, :on_op, :on_const, :on_ivar, :on_cvar, :on_gvar, :on_kw, :on_backtick
- if @stack.last # Pop only when it's Symbol
- @stack.pop
- return prev_state
- end
- when :on_tstring_beg
- @stack << false
- when :on_embexpr_beg
- @stack << false
- return prev_state
- when :on_tstring_end # :on_tstring_end may close Symbol
- @stack.pop
- return prev_state
- when :on_embexpr_end
- @stack.pop
- end
- @stack.last
- end
- end
- private_constant :SymbolState
- end
-end
diff --git a/lib/irb/color_printer.rb b/lib/irb/color_printer.rb
deleted file mode 100644
index 31644aa7f9..0000000000
--- a/lib/irb/color_printer.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-# frozen_string_literal: true
-require 'pp'
-require_relative 'color'
-
-module IRB
- class ColorPrinter < ::PP
- METHOD_RESPOND_TO = Object.instance_method(:respond_to?)
- METHOD_INSPECT = Object.instance_method(:inspect)
-
- class << self
- def pp(obj, out = $>, width = screen_width)
- q = ColorPrinter.new(out, width)
- q.guard_inspect_key {q.pp obj}
- q.flush
- out << "\n"
- end
-
- private
-
- def screen_width
- Reline.get_screen_size.last
- rescue Errno::EINVAL # in `winsize': Invalid argument - <STDIN>
- 79
- end
- end
-
- def pp(obj)
- if String === obj
- # Avoid calling Ruby 2.4+ String#pretty_print that splits a string by "\n"
- text(obj.inspect)
- elsif !METHOD_RESPOND_TO.bind(obj).call(:inspect)
- text(METHOD_INSPECT.bind(obj).call)
- else
- super
- end
- end
-
- def text(str, width = nil)
- unless str.is_a?(String)
- str = str.inspect
- end
- width ||= str.length
-
- case str
- when ''
- when ',', '=>', '[', ']', '{', '}', '..', '...', /\A@\w+\z/
- super(str, width)
- when /\A#</, '=', '>'
- super(Color.colorize(str, [:GREEN]), width)
- else
- super(Color.colorize_code(str, ignore_error: true), width)
- end
- end
- end
-end
diff --git a/lib/irb/command.rb b/lib/irb/command.rb
deleted file mode 100644
index 68a4b52727..0000000000
--- a/lib/irb/command.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-#
-# irb/command.rb - irb command
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-require_relative "command/base"
-
-module IRB # :nodoc:
- module Command
- @commands = {}
-
- class << self
- attr_reader :commands
-
- # Registers a command with the given name.
- # Aliasing is intentionally not supported at the moment.
- def register(name, command_class)
- @commands[name.to_sym] = [command_class, []]
- end
- end
- end
-end
diff --git a/lib/irb/command/backtrace.rb b/lib/irb/command/backtrace.rb
deleted file mode 100644
index 687bb075ac..0000000000
--- a/lib/irb/command/backtrace.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module Command
- class Backtrace < DebugCommand
- def execute(arg)
- execute_debug_command(pre_cmds: "backtrace #{arg}")
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/command/base.rb b/lib/irb/command/base.rb
deleted file mode 100644
index 1d406630a2..0000000000
--- a/lib/irb/command/base.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-# frozen_string_literal: true
-#
-# nop.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB
- # :stopdoc:
-
- module Command
- class CommandArgumentError < StandardError; end
-
- def self.extract_ruby_args(*args, **kwargs)
- throw :EXTRACT_RUBY_ARGS, [args, kwargs]
- end
-
- class Base
- class << self
- def category(category = nil)
- @category = category if category
- @category || "No category"
- end
-
- def description(description = nil)
- @description = description if description
- @description || "No description provided."
- end
-
- def help_message(help_message = nil)
- @help_message = help_message if help_message
- @help_message
- end
-
- private
-
- def highlight(text)
- Color.colorize(text, [:BOLD, :BLUE])
- end
- end
-
- def self.execute(irb_context, arg)
- new(irb_context).execute(arg)
- rescue CommandArgumentError => e
- puts e.message
- end
-
- def initialize(irb_context)
- @irb_context = irb_context
- end
-
- attr_reader :irb_context
-
- def execute(arg)
- #nop
- end
- end
-
- Nop = Base
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/command/break.rb b/lib/irb/command/break.rb
deleted file mode 100644
index a8f81fe665..0000000000
--- a/lib/irb/command/break.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module Command
- class Break < DebugCommand
- def execute(arg)
- execute_debug_command(pre_cmds: "break #{arg}")
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/command/catch.rb b/lib/irb/command/catch.rb
deleted file mode 100644
index 529dcbca5a..0000000000
--- a/lib/irb/command/catch.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module Command
- class Catch < DebugCommand
- def execute(arg)
- execute_debug_command(pre_cmds: "catch #{arg}")
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/command/chws.rb b/lib/irb/command/chws.rb
deleted file mode 100644
index ef456d0961..0000000000
--- a/lib/irb/command/chws.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-#
-# change-ws.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-require_relative "../ext/change-ws"
-
-module IRB
- # :stopdoc:
-
- module Command
-
- class CurrentWorkingWorkspace < Base
- category "Workspace"
- description "Show the current workspace."
-
- def execute(_arg)
- puts "Current workspace: #{irb_context.main}"
- end
- end
-
- class ChangeWorkspace < Base
- category "Workspace"
- description "Change the current workspace to an object."
-
- def execute(arg)
- if arg.empty?
- irb_context.change_workspace
- else
- obj = eval(arg, irb_context.workspace.binding)
- irb_context.change_workspace(obj)
- end
-
- puts "Current workspace: #{irb_context.main}"
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/command/context.rb b/lib/irb/command/context.rb
deleted file mode 100644
index b4fc807343..0000000000
--- a/lib/irb/command/context.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-module IRB
- module Command
- class Context < Base
- category "IRB"
- description "Displays current configuration."
-
- def execute(_arg)
- # This command just displays the configuration.
- # Modifying the configuration is achieved by sending a message to IRB.conf.
- Pager.page_content(IRB.CurrentContext.inspect)
- end
- end
- end
-end
diff --git a/lib/irb/command/continue.rb b/lib/irb/command/continue.rb
deleted file mode 100644
index 0daa029b15..0000000000
--- a/lib/irb/command/continue.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module Command
- class Continue < DebugCommand
- def execute(arg)
- execute_debug_command(do_cmds: "continue #{arg}")
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/command/debug.rb b/lib/irb/command/debug.rb
deleted file mode 100644
index 8a091a49ed..0000000000
--- a/lib/irb/command/debug.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-require_relative "../debug"
-
-module IRB
- # :stopdoc:
-
- module Command
- class Debug < Base
- category "Debugging"
- description "Start the debugger of debug.gem."
-
- def execute(_arg)
- execute_debug_command
- end
-
- def execute_debug_command(pre_cmds: nil, do_cmds: nil)
- pre_cmds = pre_cmds&.rstrip
- do_cmds = do_cmds&.rstrip
-
- if irb_context.with_debugger
- # If IRB is already running with a debug session, throw the command and IRB.debug_readline will pass it to the debugger.
- if cmd = pre_cmds || do_cmds
- throw :IRB_EXIT, cmd
- else
- puts "IRB is already running with a debug session."
- return
- end
- else
- # If IRB is not running with a debug session yet, then:
- # 1. Check if the debugging command is run from a `binding.irb` call.
- # 2. If so, try setting up the debug gem.
- # 3. Insert a debug breakpoint at `Irb#debug_break` with the intended command.
- # 4. Exit the current Irb#run call via `throw :IRB_EXIT`.
- # 5. `Irb#debug_break` will be called and trigger the breakpoint, which will run the intended command.
- unless irb_context.from_binding?
- puts "Debugging commands are only available when IRB is started with binding.irb"
- return
- end
-
- if IRB.respond_to?(:JobManager)
- warn "Can't start the debugger when IRB is running in a multi-IRB session."
- return
- end
-
- unless IRB::Debug.setup(irb_context.irb)
- puts <<~MSG
- You need to install the debug gem before using this command.
- If you use `bundle exec`, please add `gem "debug"` into your Gemfile.
- MSG
- return
- end
-
- IRB::Debug.insert_debug_break(pre_cmds: pre_cmds, do_cmds: do_cmds)
-
- # exit current Irb#run call
- throw :IRB_EXIT
- end
- end
- end
-
- class DebugCommand < Debug
- def self.category
- "Debugging"
- end
-
- def self.description
- command_name = self.name.split("::").last.downcase
- "Start the debugger of debug.gem and run its `#{command_name}` command."
- end
- end
- end
-end
diff --git a/lib/irb/command/delete.rb b/lib/irb/command/delete.rb
deleted file mode 100644
index 2a57a4a3de..0000000000
--- a/lib/irb/command/delete.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module Command
- class Delete < DebugCommand
- def execute(arg)
- execute_debug_command(pre_cmds: "delete #{arg}")
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/command/disable_irb.rb b/lib/irb/command/disable_irb.rb
deleted file mode 100644
index 0b00d0302b..0000000000
--- a/lib/irb/command/disable_irb.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-module IRB
- # :stopdoc:
-
- module Command
- class DisableIrb < Base
- category "IRB"
- description "Disable binding.irb."
-
- def execute(*)
- ::Binding.define_method(:irb) {}
- IRB.irb_exit
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/command/edit.rb b/lib/irb/command/edit.rb
deleted file mode 100644
index cb7e0c4873..0000000000
--- a/lib/irb/command/edit.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-require 'shellwords'
-
-require_relative "../color"
-require_relative "../source_finder"
-
-module IRB
- # :stopdoc:
-
- module Command
- class Edit < Base
- include RubyArgsExtractor
-
- category "Misc"
- description 'Open a file or source location.'
- help_message <<~HELP_MESSAGE
- Usage: edit [FILE or constant or method signature]
-
- Open a file in the editor specified in #{highlight('ENV["VISUAL"]')} or #{highlight('ENV["EDITOR"]')}
-
- - If no arguments are provided, IRB will attempt to open the file the current context was defined in.
- - If FILE is provided, IRB will open the file.
- - If a constant or method signature is provided, IRB will attempt to locate the source file and open it.
-
- Examples:
-
- edit
- edit foo.rb
- edit Foo
- edit Foo#bar
- HELP_MESSAGE
-
- def execute(arg)
- # Accept string literal for backward compatibility
- path = unwrap_string_literal(arg)
-
- if path.nil?
- path = @irb_context.irb_path
- elsif !File.exist?(path)
- source = SourceFinder.new(@irb_context).find_source(path)
-
- if source&.file_exist? && !source.binary_file?
- path = source.file
- end
- end
-
- unless File.exist?(path)
- puts "Can not find file: #{path}"
- return
- end
-
- if editor = (ENV['VISUAL'] || ENV['EDITOR'])
- puts "command: '#{editor}'"
- puts " path: #{path}"
- system(*Shellwords.split(editor), path)
- else
- puts "Can not find editor setting: ENV['VISUAL'] or ENV['EDITOR']"
- end
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/command/exit.rb b/lib/irb/command/exit.rb
deleted file mode 100644
index b4436f0343..0000000000
--- a/lib/irb/command/exit.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-module IRB
- # :stopdoc:
-
- module Command
- class Exit < Base
- category "IRB"
- description "Exit the current irb session."
-
- def execute(_arg)
- IRB.irb_exit
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/command/finish.rb b/lib/irb/command/finish.rb
deleted file mode 100644
index 3311a0e6e9..0000000000
--- a/lib/irb/command/finish.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module Command
- class Finish < DebugCommand
- def execute(arg)
- execute_debug_command(do_cmds: "finish #{arg}")
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/command/force_exit.rb b/lib/irb/command/force_exit.rb
deleted file mode 100644
index 14086aa849..0000000000
--- a/lib/irb/command/force_exit.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-module IRB
- # :stopdoc:
-
- module Command
- class ForceExit < Base
- category "IRB"
- description "Exit the current process."
-
- def execute(_arg)
- throw :IRB_EXIT, true
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/command/help.rb b/lib/irb/command/help.rb
deleted file mode 100644
index c2018f9b30..0000000000
--- a/lib/irb/command/help.rb
+++ /dev/null
@@ -1,83 +0,0 @@
-# frozen_string_literal: true
-
-module IRB
- module Command
- class Help < Base
- category "Help"
- description "List all available commands. Use `help <command>` to get information about a specific command."
-
- def execute(command_name)
- content =
- if command_name.empty?
- help_message
- else
- if command_class = Command.load_command(command_name)
- command_class.help_message || command_class.description
- else
- "Can't find command `#{command_name}`. Please check the command name and try again.\n\n"
- end
- end
- Pager.page_content(content)
- end
-
- private
-
- def help_message
- commands_info = IRB::Command.all_commands_info
- helper_methods_info = IRB::HelperMethod.all_helper_methods_info
- commands_grouped_by_categories = commands_info.group_by { |cmd| cmd[:category] }
- commands_grouped_by_categories["Helper methods"] = helper_methods_info
-
- if irb_context.with_debugger
- # Remove the original "Debugging" category
- commands_grouped_by_categories.delete("Debugging")
- end
-
- longest_cmd_name_length = commands_info.map { |c| c[:display_name].length }.max
-
- output = StringIO.new
-
- help_cmds = commands_grouped_by_categories.delete("Help")
- no_category_cmds = commands_grouped_by_categories.delete("No category")
- aliases = irb_context.instance_variable_get(:@user_aliases).map do |alias_name, target|
- { display_name: alias_name, description: "Alias for `#{target}`" }
- end
-
- # Display help commands first
- add_category_to_output("Help", help_cmds, output, longest_cmd_name_length)
-
- # Display the rest of the commands grouped by categories
- commands_grouped_by_categories.each do |category, cmds|
- add_category_to_output(category, cmds, output, longest_cmd_name_length)
- end
-
- # Display commands without a category
- if no_category_cmds
- add_category_to_output("No category", no_category_cmds, output, longest_cmd_name_length)
- end
-
- # Display aliases
- add_category_to_output("Aliases", aliases, output, longest_cmd_name_length)
-
- # Append the debugger help at the end
- if irb_context.with_debugger
- # Add "Debugging (from debug.gem)" category as title
- add_category_to_output("Debugging (from debug.gem)", [], output, longest_cmd_name_length)
- output.puts DEBUGGER__.help
- end
-
- output.string
- end
-
- def add_category_to_output(category, cmds, output, longest_cmd_name_length)
- output.puts Color.colorize(category, [:BOLD])
-
- cmds.each do |cmd|
- output.puts " #{cmd[:display_name].to_s.ljust(longest_cmd_name_length)} #{cmd[:description]}"
- end
-
- output.puts
- end
- end
- end
-end
diff --git a/lib/irb/command/history.rb b/lib/irb/command/history.rb
deleted file mode 100644
index 90f87f9102..0000000000
--- a/lib/irb/command/history.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-require "stringio"
-
-require_relative "../pager"
-
-module IRB
- # :stopdoc:
-
- module Command
- class History < Base
- category "IRB"
- description "Shows the input history. `-g [query]` or `-G [query]` allows you to filter the output."
-
- def execute(arg)
-
- if (match = arg&.match(/(-g|-G)\s+(?<grep>.+)\s*\n\z/))
- grep = Regexp.new(match[:grep])
- end
-
- formatted_inputs = irb_context.io.class::HISTORY.each_with_index.reverse_each.filter_map do |input, index|
- next if grep && !input.match?(grep)
-
- header = "#{index}: "
-
- first_line, *other_lines = input.split("\n")
- first_line = "#{header}#{first_line}"
-
- truncated_lines = other_lines.slice!(1..) # Show 1 additional line (2 total)
- other_lines << "..." if truncated_lines&.any?
-
- other_lines.map! do |line|
- " " * header.length + line
- end
-
- [first_line, *other_lines].join("\n") + "\n"
- end
-
- Pager.page_content(formatted_inputs.join)
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/command/info.rb b/lib/irb/command/info.rb
deleted file mode 100644
index d08ce00a32..0000000000
--- a/lib/irb/command/info.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module Command
- class Info < DebugCommand
- def execute(arg)
- execute_debug_command(pre_cmds: "info #{arg}")
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/command/internal_helpers.rb b/lib/irb/command/internal_helpers.rb
deleted file mode 100644
index 249b5cdede..0000000000
--- a/lib/irb/command/internal_helpers.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-module IRB
- module Command
- # Internal use only, for default command's backward compatibility.
- module RubyArgsExtractor # :nodoc:
- def unwrap_string_literal(str)
- return if str.empty?
-
- sexp = Ripper.sexp(str)
- if sexp && sexp.size == 2 && sexp.last&.first&.first == :string_literal
- @irb_context.workspace.binding.eval(str).to_s
- else
- str
- end
- end
-
- def ruby_args(arg)
- # Use throw and catch to handle arg that includes `;`
- # For example: "1, kw: (2; 3); 4" will be parsed to [[1], { kw: 3 }]
- catch(:EXTRACT_RUBY_ARGS) do
- @irb_context.workspace.binding.eval "IRB::Command.extract_ruby_args #{arg}"
- end || [[], {}]
- end
- end
- end
-end
diff --git a/lib/irb/command/irb_info.rb b/lib/irb/command/irb_info.rb
deleted file mode 100644
index 6d868de94c..0000000000
--- a/lib/irb/command/irb_info.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-module IRB
- # :stopdoc:
-
- module Command
- class IrbInfo < Base
- category "IRB"
- description "Show information about IRB."
-
- def execute(_arg)
- str = "Ruby version: #{RUBY_VERSION}\n"
- str += "IRB version: #{IRB.version}\n"
- str += "InputMethod: #{IRB.CurrentContext.io.inspect}\n"
- str += "Completion: #{IRB.CurrentContext.io.respond_to?(:completion_info) ? IRB.CurrentContext.io.completion_info : 'off'}\n"
- rc_files = IRB.irbrc_files
- str += ".irbrc paths: #{rc_files.join(", ")}\n" if rc_files.any?
- str += "RUBY_PLATFORM: #{RUBY_PLATFORM}\n"
- str += "LANG env: #{ENV["LANG"]}\n" if ENV["LANG"] && !ENV["LANG"].empty?
- str += "LC_ALL env: #{ENV["LC_ALL"]}\n" if ENV["LC_ALL"] && !ENV["LC_ALL"].empty?
- str += "East Asian Ambiguous Width: #{Reline.ambiguous_width.inspect}\n"
- if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/
- codepage = `chcp`.b.sub(/.*: (\d+)\n/, '\1')
- str += "Code page: #{codepage}\n"
- end
- puts str
- nil
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/command/load.rb b/lib/irb/command/load.rb
deleted file mode 100644
index 1cd3f279d1..0000000000
--- a/lib/irb/command/load.rb
+++ /dev/null
@@ -1,91 +0,0 @@
-# frozen_string_literal: true
-#
-# load.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-require_relative "../ext/loader"
-
-module IRB
- # :stopdoc:
-
- module Command
- class LoaderCommand < Base
- include RubyArgsExtractor
- include IrbLoader
-
- def raise_cmd_argument_error
- raise CommandArgumentError.new("Please specify the file name.")
- end
- end
-
- class Load < LoaderCommand
- category "IRB"
- description "Load a Ruby file."
-
- def execute(arg)
- args, kwargs = ruby_args(arg)
- execute_internal(*args, **kwargs)
- end
-
- def execute_internal(file_name = nil, priv = nil)
- raise_cmd_argument_error unless file_name
- irb_load(file_name, priv)
- end
- end
-
- class Require < LoaderCommand
- category "IRB"
- description "Require a Ruby file."
-
- def execute(arg)
- args, kwargs = ruby_args(arg)
- execute_internal(*args, **kwargs)
- end
-
- def execute_internal(file_name = nil)
- raise_cmd_argument_error unless file_name
-
- rex = Regexp.new("#{Regexp.quote(file_name)}(\.o|\.rb)?")
- return false if $".find{|f| f =~ rex}
-
- case file_name
- when /\.rb$/
- begin
- if irb_load(file_name)
- $".push file_name
- return true
- end
- rescue LoadError
- end
- when /\.(so|o|sl)$/
- return ruby_require(file_name)
- end
-
- begin
- irb_load(f = file_name + ".rb")
- $".push f
- return true
- rescue LoadError
- return ruby_require(file_name)
- end
- end
- end
-
- class Source < LoaderCommand
- category "IRB"
- description "Loads a given file in the current session."
-
- def execute(arg)
- args, kwargs = ruby_args(arg)
- execute_internal(*args, **kwargs)
- end
-
- def execute_internal(file_name = nil)
- raise_cmd_argument_error unless file_name
-
- source_file(file_name)
- end
- end
- end
- # :startdoc:
-end
diff --git a/lib/irb/command/ls.rb b/lib/irb/command/ls.rb
deleted file mode 100644
index cbd9998bc4..0000000000
--- a/lib/irb/command/ls.rb
+++ /dev/null
@@ -1,155 +0,0 @@
-# frozen_string_literal: true
-
-require "reline"
-require "stringio"
-
-require_relative "../pager"
-require_relative "../color"
-
-module IRB
- # :stopdoc:
-
- module Command
- class Ls < Base
- include RubyArgsExtractor
-
- category "Context"
- description "Show methods, constants, and variables."
-
- help_message <<~HELP_MESSAGE
- Usage: ls [obj] [-g [query]]
-
- -g [query] Filter the output with a query.
- HELP_MESSAGE
-
- def execute(arg)
- if match = arg.match(/\A(?<target>.+\s|)(-g|-G)\s+(?<grep>.+)$/)
- if match[:target].empty?
- use_main = true
- else
- obj = @irb_context.workspace.binding.eval(match[:target])
- end
- grep = Regexp.new(match[:grep])
- else
- args, kwargs = ruby_args(arg)
- use_main = args.empty?
- obj = args.first
- grep = kwargs[:grep]
- end
-
- if use_main
- obj = irb_context.workspace.main
- locals = irb_context.workspace.binding.local_variables
- end
-
- o = Output.new(grep: grep)
-
- 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) if locals
- o.print_result
- end
-
- def dump_methods(o, klass, obj)
- singleton_class = begin obj.singleton_class; rescue TypeError; nil end
- dumped_mods = Array.new
- ancestors = klass.ancestors
- ancestors = ancestors.reject { |c| c >= Object } if klass < Object
- singleton_ancestors = (singleton_class&.ancestors || []).reject { |c| c >= Class }
-
- # singleton_class' ancestors should be at the front
- maps = class_method_map(singleton_ancestors, dumped_mods) + class_method_map(ancestors, dumped_mods)
- maps.each do |mod, methods|
- name = mod == singleton_class ? "#{klass}.methods" : "#{mod}#methods"
- o.dump(name, methods)
- end
- end
-
- def class_method_map(classes, dumped_mods)
- dumped_methods = Array.new
- classes.map do |mod|
- next if dumped_mods.include? mod
-
- dumped_mods << mod
-
- methods = mod.public_instance_methods(false).select do |method|
- if dumped_methods.include? method
- false
- else
- dumped_methods << method
- true
- end
- end
-
- [mod, methods]
- end.compact
- end
-
- class Output
- MARGIN = " "
-
- def initialize(grep: nil)
- @grep = grep
- @line_width = screen_width - MARGIN.length # right padding
- @io = StringIO.new
- end
-
- def print_result
- Pager.page_content(@io.string)
- end
-
- def dump(name, strs)
- strs = strs.grep(@grep) if @grep
- strs = strs.sort
- return if strs.empty?
-
- # Attempt a single line
- @io.print "#{Color.colorize(name, [:BOLD, :BLUE])}: "
- if fits_on_line?(strs, cols: strs.size, offset: "#{name}: ".length)
- @io.puts strs.join(MARGIN)
- return
- end
- @io.puts
-
- # Dump with the largest # of columns that fits on a line
- cols = strs.size
- until fits_on_line?(strs, cols: cols, offset: MARGIN.length) || cols == 1
- cols -= 1
- end
- widths = col_widths(strs, cols: cols)
- strs.each_slice(cols) do |ss|
- @io.puts ss.map.with_index { |s, i| "#{MARGIN}%-#{widths[i]}s" % s }.join
- end
- end
-
- private
-
- def fits_on_line?(strs, cols:, offset: 0)
- width = col_widths(strs, cols: cols).sum + MARGIN.length * (cols - 1)
- width <= @line_width - offset
- end
-
- def col_widths(strs, cols:)
- cols.times.map do |col|
- (col...strs.size).step(cols).map do |i|
- strs[i].length
- end.max
- end
- end
-
- def screen_width
- Reline.get_screen_size.last
- rescue Errno::EINVAL # in `winsize': Invalid argument - <STDIN>
- 80
- end
- end
- private_constant :Output
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/command/measure.rb b/lib/irb/command/measure.rb
deleted file mode 100644
index f96be20de8..0000000000
--- a/lib/irb/command/measure.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-module IRB
- # :stopdoc:
-
- module Command
- class Measure < Base
- include RubyArgsExtractor
-
- category "Misc"
- description "`measure` enables the mode to measure processing time. `measure :off` disables it."
-
- def initialize(*args)
- super(*args)
- end
-
- def execute(arg)
- if arg&.match?(/^do$|^do[^\w]|^\{/)
- warn 'Configure IRB.conf[:MEASURE_PROC] to add custom measure methods.'
- return
- end
- args, kwargs = ruby_args(arg)
- execute_internal(*args, **kwargs)
- end
-
- def execute_internal(type = nil, arg = nil)
- # 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.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
- added = IRB.set_measure_callback(arg)
- puts "#{added[0]} is added." if added
- else
- added = IRB.set_measure_callback(type, arg)
- puts "#{added[0]} is added." if added
- end
- nil
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/command/next.rb b/lib/irb/command/next.rb
deleted file mode 100644
index 3fc6b68d21..0000000000
--- a/lib/irb/command/next.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module Command
- class Next < DebugCommand
- def execute(arg)
- execute_debug_command(do_cmds: "next #{arg}")
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/command/pushws.rb b/lib/irb/command/pushws.rb
deleted file mode 100644
index b51928c650..0000000000
--- a/lib/irb/command/pushws.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-# frozen_string_literal: true
-#
-# change-ws.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-require_relative "../ext/workspaces"
-
-module IRB
- # :stopdoc:
-
- module Command
- class Workspaces < Base
- category "Workspace"
- description "Show workspaces."
-
- def execute(_arg)
- inspection_resuls = irb_context.instance_variable_get(:@workspace_stack).map do |ws|
- truncated_inspect(ws.main)
- end
-
- puts "[" + inspection_resuls.join(", ") + "]"
- end
-
- private
-
- def truncated_inspect(obj)
- obj_inspection = obj.inspect
-
- if obj_inspection.size > 20
- obj_inspection = obj_inspection[0, 19] + "...>"
- end
-
- obj_inspection
- end
- end
-
- class PushWorkspace < Workspaces
- category "Workspace"
- description "Push an object to the workspace stack."
-
- def execute(arg)
- if arg.empty?
- irb_context.push_workspace
- else
- obj = eval(arg, irb_context.workspace.binding)
- irb_context.push_workspace(obj)
- end
- super
- end
- end
-
- class PopWorkspace < Workspaces
- category "Workspace"
- description "Pop a workspace from the workspace stack."
-
- def execute(_arg)
- irb_context.pop_workspace
- super
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/command/show_doc.rb b/lib/irb/command/show_doc.rb
deleted file mode 100644
index 8a2188e4eb..0000000000
--- a/lib/irb/command/show_doc.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-# frozen_string_literal: true
-
-module IRB
- module Command
- class ShowDoc < Base
- include RubyArgsExtractor
-
- category "Context"
- description "Look up documentation with RI."
-
- help_message <<~HELP_MESSAGE
- Usage: show_doc [name]
-
- When name is provided, IRB will look up the documentation for the given name.
- When no name is provided, a RI session will be started.
-
- Examples:
-
- show_doc
- show_doc Array
- show_doc Array#each
-
- HELP_MESSAGE
-
- def execute(arg)
- # Accept string literal for backward compatibility
- name = unwrap_string_literal(arg)
- require 'rdoc/ri/driver'
-
- unless ShowDoc.const_defined?(:Ri)
- opts = RDoc::RI::Driver.process_args([])
- ShowDoc.const_set(:Ri, RDoc::RI::Driver.new(opts))
- end
-
- if name.nil?
- Ri.interactive
- else
- begin
- Ri.display_name(name)
- rescue RDoc::RI::Error
- puts $!.message
- end
- end
-
- nil
- rescue LoadError, SystemExit
- warn "Can't display document because `rdoc` is not installed."
- end
- end
- end
-end
diff --git a/lib/irb/command/show_source.rb b/lib/irb/command/show_source.rb
deleted file mode 100644
index f4c6f104a2..0000000000
--- a/lib/irb/command/show_source.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "../source_finder"
-require_relative "../pager"
-require_relative "../color"
-
-module IRB
- module Command
- class ShowSource < Base
- include RubyArgsExtractor
-
- category "Context"
- description "Show the source code of a given method, class/module, or constant."
-
- help_message <<~HELP_MESSAGE
- Usage: show_source [target] [-s]
-
- -s Show the super method. You can stack it like `-ss` to show the super of the super, etc.
-
- Examples:
-
- show_source Foo
- show_source Foo#bar
- show_source Foo#bar -s
- show_source Foo.baz
- show_source Foo::BAR
- HELP_MESSAGE
-
- def execute(arg)
- # Accept string literal for backward compatibility
- str = unwrap_string_literal(arg)
- unless str.is_a?(String)
- puts "Error: Expected a string but got #{str.inspect}"
- return
- end
-
- str, esses = str.split(" -")
- super_level = esses ? esses.count("s") : 0
- source = SourceFinder.new(@irb_context).find_source(str, super_level)
-
- if source
- show_source(source)
- elsif super_level > 0
- puts "Error: Couldn't locate a super definition for #{str}"
- else
- puts "Error: Couldn't locate a definition for #{str}"
- end
- nil
- end
-
- private
-
- def show_source(source)
- if source.binary_file?
- content = "\n#{bold('Defined in binary file')}: #{source.file}\n\n"
- else
- code = source.colorized_content || 'Source not available'
- content = <<~CONTENT
-
- #{bold("From")}: #{source.file}:#{source.line}
-
- #{code.chomp}
-
- CONTENT
- end
- Pager.page_content(content)
- end
-
- def bold(str)
- Color.colorize(str, [:BOLD])
- end
- end
- end
-end
diff --git a/lib/irb/command/step.rb b/lib/irb/command/step.rb
deleted file mode 100644
index 29e5e35ac0..0000000000
--- a/lib/irb/command/step.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "debug"
-
-module IRB
- # :stopdoc:
-
- module Command
- class Step < DebugCommand
- def execute(arg)
- execute_debug_command(do_cmds: "step #{arg}")
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/command/subirb.rb b/lib/irb/command/subirb.rb
deleted file mode 100644
index 85af28c1a5..0000000000
--- a/lib/irb/command/subirb.rb
+++ /dev/null
@@ -1,123 +0,0 @@
-# frozen_string_literal: true
-#
-# multi.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB
- # :stopdoc:
-
- module Command
- class MultiIRBCommand < Base
- include RubyArgsExtractor
-
- private
-
- def print_deprecated_warning
- warn <<~MSG
- Multi-irb commands are deprecated and will be removed in IRB 2.0.0. Please use workspace commands instead.
- If you have any use case for multi-irb, please leave a comment at https://github.com/ruby/irb/issues/653
- MSG
- end
-
- def extend_irb_context
- # this extension patches IRB context like IRB.CurrentContext
- require_relative "../ext/multi-irb"
- end
-
- def print_debugger_warning
- warn "Multi-IRB commands are not available when the debugger is enabled."
- end
- end
-
- class IrbCommand < MultiIRBCommand
- category "Multi-irb (DEPRECATED)"
- description "Start a child IRB."
-
- def execute(arg)
- args, kwargs = ruby_args(arg)
- execute_internal(*args, **kwargs)
- end
-
- def execute_internal(*obj)
- print_deprecated_warning
-
- if irb_context.with_debugger
- print_debugger_warning
- return
- end
-
- extend_irb_context
- IRB.irb(nil, *obj)
- puts IRB.JobManager.inspect
- end
- end
-
- class Jobs < MultiIRBCommand
- category "Multi-irb (DEPRECATED)"
- description "List of current sessions."
-
- def execute(_arg)
- print_deprecated_warning
-
- if irb_context.with_debugger
- print_debugger_warning
- return
- end
-
- extend_irb_context
- puts IRB.JobManager.inspect
- end
- end
-
- class Foreground < MultiIRBCommand
- category "Multi-irb (DEPRECATED)"
- description "Switches to the session of the given number."
-
- def execute(arg)
- args, kwargs = ruby_args(arg)
- execute_internal(*args, **kwargs)
- end
-
- def execute_internal(key = nil)
- print_deprecated_warning
-
- if irb_context.with_debugger
- print_debugger_warning
- return
- end
-
- extend_irb_context
-
- raise CommandArgumentError.new("Please specify the id of target IRB job (listed in the `jobs` command).") unless key
- IRB.JobManager.switch(key)
- puts IRB.JobManager.inspect
- end
- end
-
- class Kill < MultiIRBCommand
- category "Multi-irb (DEPRECATED)"
- description "Kills the session with the given number."
-
- def execute(arg)
- args, kwargs = ruby_args(arg)
- execute_internal(*args, **kwargs)
- end
-
- def execute_internal(*keys)
- print_deprecated_warning
-
- if irb_context.with_debugger
- print_debugger_warning
- return
- end
-
- extend_irb_context
- IRB.JobManager.kill(*keys)
- puts IRB.JobManager.inspect
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/command/whereami.rb b/lib/irb/command/whereami.rb
deleted file mode 100644
index c8439f1212..0000000000
--- a/lib/irb/command/whereami.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-module IRB
- # :stopdoc:
-
- module Command
- class Whereami < Base
- category "Context"
- description "Show the source code around binding.irb again."
-
- def execute(_arg)
- code = irb_context.workspace.code_around_binding
- if code
- puts code
- else
- puts "The current context doesn't have code."
- end
- end
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/completion.rb b/lib/irb/completion.rb
deleted file mode 100644
index a3d89373c3..0000000000
--- a/lib/irb/completion.rb
+++ /dev/null
@@ -1,477 +0,0 @@
-# frozen_string_literal: true
-#
-# irb/completion.rb -
-# by Keiju ISHITSUKA(keiju@ishitsuka.com)
-# From Original Idea of shugo@ruby-lang.org
-#
-
-require_relative 'ruby-lex'
-
-module IRB
- class BaseCompletor # :nodoc:
-
- # Set of reserved words used by Ruby, you should not use these for
- # constants or variables
- ReservedWords = %w[
- __ENCODING__ __LINE__ __FILE__
- BEGIN END
- alias and
- begin break
- case class
- def defined? do
- else elsif end ensure
- false for
- if in
- module
- next nil not
- or
- redo rescue retry return
- self super
- then true
- undef unless until
- when while
- yield
- ]
-
- def completion_candidates(preposing, target, postposing, bind:)
- raise NotImplementedError
- end
-
- def doc_namespace(preposing, matched, postposing, bind:)
- raise NotImplementedError
- end
-
- GEM_PATHS =
- if defined?(Gem::Specification)
- Gem::Specification.latest_specs(true).map { |s|
- s.require_paths.map { |p|
- if File.absolute_path?(p)
- p
- else
- File.join(s.full_gem_path, p)
- end
- }
- }.flatten
- else
- []
- end.freeze
-
- def retrieve_gem_and_system_load_path
- candidates = (GEM_PATHS | $LOAD_PATH)
- candidates.map do |p|
- if p.respond_to?(:to_path)
- p.to_path
- else
- String(p) rescue nil
- end
- end.compact.sort
- end
-
- def 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 command_completions(preposing, target)
- if preposing.empty? && !target.empty?
- IRB::Command.command_names.select { _1.start_with?(target) }
- else
- []
- end
- end
-
- def 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
- end
-
- class TypeCompletor < BaseCompletor # :nodoc:
- def initialize(context)
- @context = context
- end
-
- def inspect
- ReplTypeCompletor.info
- end
-
- def completion_candidates(preposing, target, _postposing, bind:)
- commands = command_completions(preposing, target)
- result = ReplTypeCompletor.analyze(preposing + target, binding: bind, filename: @context.irb_path)
- return commands unless result
-
- commands | result.completion_candidates.map { target + _1 }
- end
-
- def doc_namespace(preposing, matched, _postposing, bind:)
- result = ReplTypeCompletor.analyze(preposing + matched, binding: bind, filename: @context.irb_path)
- result&.doc_namespace('')
- end
- end
-
- class RegexpCompletor < BaseCompletor # :nodoc:
- using Module.new {
- refine ::Binding do
- def eval_methods
- ::Kernel.instance_method(:methods).bind(eval("self")).call
- end
-
- def eval_private_methods
- ::Kernel.instance_method(:private_methods).bind(eval("self")).call
- end
-
- def eval_instance_variables
- ::Kernel.instance_method(:instance_variables).bind(eval("self")).call
- end
-
- def eval_global_variables
- ::Kernel.instance_method(:global_variables).bind(eval("self")).call
- end
-
- def eval_class_constants
- ::Module.instance_method(:constants).bind(eval("self.class")).call
- end
- end
- }
-
- def inspect
- 'RegexpCompletor'
- end
-
- def complete_require_path(target, preposing, postposing)
- 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
- return unless tok&.event == :on_ident && tok.state == Ripper::EXPR_CMDARG
-
- case tok.tok
- when 'require'
- retrieve_files_to_require_from_load_path.select { |path|
- path.start_with?(actual_target)
- }.map { |path|
- quote + path
- }
- when 'require_relative'
- retrieve_files_to_require_relative_from_current_dir.select { |path|
- path.start_with?(actual_target)
- }.map { |path|
- quote + path
- }
- end
- end
-
- def completion_candidates(preposing, target, postposing, bind:)
- if preposing && postposing
- result = complete_require_path(target, preposing, postposing)
- return result if result
- end
- commands = command_completions(preposing || '', target)
- commands | retrieve_completion_data(target, bind: bind, doc_namespace: false).compact.map{ |i| i.encode(Encoding.default_external) }
- end
-
- def doc_namespace(_preposing, matched, _postposing, bind:)
- retrieve_completion_data(matched, bind: bind, doc_namespace: true)
- end
-
- def retrieve_completion_data(input, bind:, doc_namespace:)
- case input
- # this regexp only matches the closing character because of irb's Reline.completer_quote_characters setting
- # details are described in: https://github.com/ruby/irb/pull/523
- when /^(.*["'`])\.([^.]*)$/
- # String
- receiver = $1
- message = $2
-
- if doc_namespace
- "String.#{message}"
- else
- candidates = String.instance_methods.collect{|m| m.to_s}
- select_message(receiver, message, candidates)
- end
-
- # this regexp only matches the closing character because of irb's Reline.completer_quote_characters setting
- # details are described in: https://github.com/ruby/irb/pull/523
- when /^(.*\/)\.([^.]*)$/
- # Regexp
- receiver = $1
- message = $2
-
- if doc_namespace
- "Regexp.#{message}"
- else
- candidates = Regexp.instance_methods.collect{|m| m.to_s}
- select_message(receiver, message, candidates)
- end
-
- when /^([^\]]*\])\.([^.]*)$/
- # Array
- receiver = $1
- message = $2
-
- if doc_namespace
- "Array.#{message}"
- else
- candidates = Array.instance_methods.collect{|m| m.to_s}
- select_message(receiver, message, candidates)
- end
-
- when /^([^\}]*\})\.([^.]*)$/
- # Hash or Proc
- receiver = $1
- message = $2
-
- if doc_namespace
- ["Hash.#{message}", "Proc.#{message}"]
- else
- hash_candidates = Hash.instance_methods.collect{|m| m.to_s}
- proc_candidates = Proc.instance_methods.collect{|m| m.to_s}
- select_message(receiver, message, hash_candidates | proc_candidates)
- end
-
- when /^(:[^:.]+)$/
- # Symbol
- if doc_namespace
- nil
- else
- sym = $1
- candidates = Symbol.all_symbols.collect do |s|
- s.inspect
- rescue EncodingError
- # ignore
- end
- candidates.grep(/^#{Regexp.quote(sym)}/)
- end
- when /^::([A-Z][^:\.\(\)]*)$/
- # Absolute Constant or class methods
- receiver = $1
-
- candidates = Object.constants.collect{|m| m.to_s}
-
- if doc_namespace
- candidates.find { |i| i == receiver }
- else
- candidates.grep(/^#{Regexp.quote(receiver)}/).collect{|e| "::" + e}
- end
-
- when /^([A-Z].*)::([^:.]*)$/
- # Constant or class methods
- receiver = $1
- message = $2
-
- if doc_namespace
- "#{receiver}::#{message}"
- else
- begin
- candidates = eval("#{receiver}.constants.collect{|m| m.to_s}", bind)
- candidates |= eval("#{receiver}.methods.collect{|m| m.to_s}", bind)
- rescue Exception
- candidates = []
- end
-
- select_message(receiver, message, candidates.sort, "::")
- end
-
- when /^(:[^:.]+)(\.|::)([^.]*)$/
- # Symbol
- receiver = $1
- sep = $2
- message = $3
-
- if doc_namespace
- "Symbol.#{message}"
- else
- candidates = Symbol.instance_methods.collect{|m| m.to_s}
- select_message(receiver, message, candidates, sep)
- end
-
- when /^(?<num>-?(?:0[dbo])?[0-9_]+(?:\.[0-9_]+)?(?:(?:[eE][+-]?[0-9]+)?i?|r)?)(?<sep>\.|::)(?<mes>[^.]*)$/
- # Numeric
- receiver = $~[:num]
- sep = $~[:sep]
- message = $~[:mes]
-
- begin
- instance = eval(receiver, bind)
-
- if doc_namespace
- "#{instance.class.name}.#{message}"
- else
- candidates = instance.methods.collect{|m| m.to_s}
- select_message(receiver, message, candidates, sep)
- end
- rescue Exception
- if doc_namespace
- nil
- else
- []
- end
- end
-
- when /^(-?0x[0-9a-fA-F_]+)(\.|::)([^.]*)$/
- # Numeric(0xFFFF)
- receiver = $1
- sep = $2
- message = $3
-
- begin
- instance = eval(receiver, bind)
- if doc_namespace
- "#{instance.class.name}.#{message}"
- else
- candidates = instance.methods.collect{|m| m.to_s}
- select_message(receiver, message, candidates, sep)
- end
- rescue Exception
- if doc_namespace
- nil
- else
- []
- end
- end
-
- when /^(\$[^.]*)$/
- # global var
- gvar = $1
- all_gvars = global_variables.collect{|m| m.to_s}
-
- if doc_namespace
- all_gvars.find{ |i| i == gvar }
- else
- all_gvars.grep(Regexp.new(Regexp.quote(gvar)))
- end
-
- when /^([^.:"].*)(\.|::)([^.]*)$/
- # variable.func or func.func
- receiver = $1
- sep = $2
- message = $3
-
- gv = bind.eval_global_variables.collect{|m| m.to_s}.push("true", "false", "nil")
- lv = bind.local_variables.collect{|m| m.to_s}
- iv = bind.eval_instance_variables.collect{|m| m.to_s}
- cv = bind.eval_class_constants.collect{|m| m.to_s}
-
- if (gv | lv | iv | cv).include?(receiver) or /^[A-Z]/ =~ receiver && /\./ !~ receiver
- # foo.func and foo is var. OR
- # foo::func and foo is var. OR
- # foo::Const and foo is var. OR
- # Foo::Bar.func
- begin
- candidates = []
- rec = eval(receiver, bind)
- if sep == "::" and rec.kind_of?(Module)
- candidates = rec.constants.collect{|m| m.to_s}
- end
- candidates |= rec.methods.collect{|m| m.to_s}
- rescue Exception
- candidates = []
- end
- else
- # func1.func2
- candidates = []
- end
-
- if doc_namespace
- rec_class = rec.is_a?(Module) ? rec : rec.class
- "#{rec_class.name}#{sep}#{candidates.find{ |i| i == message }}" rescue nil
- else
- select_message(receiver, message, candidates, sep)
- end
-
- when /^\.([^.]*)$/
- # unknown(maybe String)
-
- receiver = ""
- message = $1
-
- candidates = String.instance_methods(true).collect{|m| m.to_s}
-
- if doc_namespace
- "String.#{candidates.find{ |i| i == message }}"
- else
- select_message(receiver, message, candidates.sort)
- end
- when /^\s*$/
- # empty input
- if doc_namespace
- nil
- else
- []
- end
- else
- if doc_namespace
- vars = (bind.local_variables | bind.eval_instance_variables).collect{|m| m.to_s}
- perfect_match_var = vars.find{|m| m.to_s == input}
- if perfect_match_var
- eval("#{perfect_match_var}.class.name", bind) rescue nil
- else
- candidates = (bind.eval_methods | bind.eval_private_methods | bind.local_variables | bind.eval_instance_variables | bind.eval_class_constants).collect{|m| m.to_s}
- candidates |= ReservedWords
- candidates.find{ |i| i == input }
- end
- else
- candidates = (bind.eval_methods | bind.eval_private_methods | bind.local_variables | bind.eval_instance_variables | bind.eval_class_constants).collect{|m| m.to_s}
- candidates |= ReservedWords
- candidates.grep(/^#{Regexp.quote(input)}/).sort
- end
- end
- end
-
- # Set of available operators in Ruby
- Operators = %w[% & * ** + - / < << <= <=> == === =~ > >= >> [] []= ^ ! != !~]
-
- def select_message(receiver, message, candidates, sep = ".")
- candidates.grep(/^#{Regexp.quote(message)}/).collect do |e|
- case e
- when /^[a-zA-Z_]/
- receiver + sep + e
- when /^[0-9]/
- when *Operators
- #receiver + " " + e
- end
- end
- end
- end
-
- module InputCompletor
- class << self
- private def regexp_completor
- @regexp_completor ||= RegexpCompletor.new
- end
-
- def retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace.binding, doc_namespace: false)
- regexp_completor.retrieve_completion_data(input, bind: bind, doc_namespace: doc_namespace)
- end
- end
- CompletionProc = ->(target, preposing = nil, postposing = nil) {
- regexp_completor.completion_candidates(preposing, target, postposing, bind: IRB.conf[:MAIN_CONTEXT].workspace.binding)
- }
- end
- deprecate_constant :InputCompletor
-end
diff --git a/lib/irb/context.rb b/lib/irb/context.rb
deleted file mode 100644
index aafce7aade..0000000000
--- a/lib/irb/context.rb
+++ /dev/null
@@ -1,674 +0,0 @@
-# frozen_string_literal: true
-#
-# irb/context.rb - irb context
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-require_relative "workspace"
-require_relative "inspector"
-require_relative "input-method"
-require_relative "output-method"
-
-module IRB
- # A class that wraps the current state of the irb session, including the
- # configuration of IRB.conf.
- class Context
- # Creates a new IRB context.
- #
- # The optional +input_method+ argument:
- #
- # +nil+:: uses stdin or Reline or Readline
- # +String+:: uses a File
- # +other+:: uses this as InputMethod
- def initialize(irb, workspace = nil, input_method = nil)
- @irb = irb
- @workspace_stack = []
- if workspace
- @workspace_stack << workspace
- else
- @workspace_stack << WorkSpace.new
- end
- @thread = Thread.current
-
- # copy of default configuration
- @ap_name = IRB.conf[:AP_NAME]
- @rc = IRB.conf[:RC]
- @load_modules = IRB.conf[:LOAD_MODULES]
-
- if IRB.conf.has_key?(:USE_SINGLELINE)
- @use_singleline = IRB.conf[:USE_SINGLELINE]
- elsif IRB.conf.has_key?(:USE_READLINE) # backward compatibility
- @use_singleline = IRB.conf[:USE_READLINE]
- else
- @use_singleline = nil
- end
- if IRB.conf.has_key?(:USE_MULTILINE)
- @use_multiline = IRB.conf[:USE_MULTILINE]
- elsif IRB.conf.has_key?(:USE_RELINE) # backward compatibility
- warn <<~MSG.strip
- USE_RELINE is deprecated, please use USE_MULTILINE instead.
- MSG
- @use_multiline = IRB.conf[:USE_RELINE]
- elsif IRB.conf.has_key?(:USE_REIDLINE)
- warn <<~MSG.strip
- USE_REIDLINE is deprecated, please use USE_MULTILINE instead.
- MSG
- @use_multiline = IRB.conf[:USE_REIDLINE]
- else
- @use_multiline = nil
- end
- @use_autocomplete = IRB.conf[:USE_AUTOCOMPLETE]
- @verbose = IRB.conf[:VERBOSE]
- @io = nil
-
- self.inspect_mode = IRB.conf[:INSPECT_MODE]
- self.use_tracer = IRB.conf[:USE_TRACER]
- self.use_loader = IRB.conf[:USE_LOADER] if IRB.conf[:USE_LOADER]
- self.eval_history = IRB.conf[:EVAL_HISTORY] if IRB.conf[:EVAL_HISTORY]
-
- @ignore_sigint = IRB.conf[:IGNORE_SIGINT]
- @ignore_eof = IRB.conf[:IGNORE_EOF]
-
- @back_trace_limit = IRB.conf[:BACK_TRACE_LIMIT]
-
- self.prompt_mode = IRB.conf[:PROMPT_MODE]
-
- @irb_name = IRB.conf[:IRB_NAME]
-
- unless IRB.conf[:SINGLE_IRB] or !defined?(IRB::JobManager)
- @irb_name = @irb_name + "#" + IRB.JobManager.n_jobs.to_s
- end
-
- self.irb_path = "(" + @irb_name + ")"
-
- case input_method
- when nil
- @io = nil
- case use_multiline?
- when nil
- if term_interactive? && IRB.conf[:PROMPT_MODE] != :INF_RUBY && !use_singleline?
- # Both of multiline mode and singleline mode aren't specified.
- @io = RelineInputMethod.new(build_completor)
- else
- @io = nil
- end
- when false
- @io = nil
- when true
- @io = RelineInputMethod.new(build_completor)
- end
- unless @io
- case use_singleline?
- when nil
- if (defined?(ReadlineInputMethod) && term_interactive? &&
- IRB.conf[:PROMPT_MODE] != :INF_RUBY)
- @io = ReadlineInputMethod.new
- else
- @io = nil
- end
- when false
- @io = nil
- when true
- if defined?(ReadlineInputMethod)
- @io = ReadlineInputMethod.new
- else
- @io = nil
- end
- else
- @io = nil
- end
- end
- @io = StdioInputMethod.new unless @io
-
- when '-'
- @io = FileInputMethod.new($stdin)
- @irb_name = '-'
- self.irb_path = '-'
- when String
- @io = FileInputMethod.new(input_method)
- @irb_name = File.basename(input_method)
- self.irb_path = input_method
- else
- @io = input_method
- end
- @extra_doc_dirs = IRB.conf[:EXTRA_DOC_DIRS]
-
- @echo = IRB.conf[:ECHO]
- if @echo.nil?
- @echo = true
- end
-
- @echo_on_assignment = IRB.conf[:ECHO_ON_ASSIGNMENT]
- if @echo_on_assignment.nil?
- @echo_on_assignment = :truncate
- end
-
- @newline_before_multiline_output = IRB.conf[:NEWLINE_BEFORE_MULTILINE_OUTPUT]
- if @newline_before_multiline_output.nil?
- @newline_before_multiline_output = true
- end
-
- @user_aliases = IRB.conf[:COMMAND_ALIASES].dup
- @command_aliases = @user_aliases.merge(KEYWORD_ALIASES)
- end
-
- private def term_interactive?
- return true if ENV['TEST_IRB_FORCE_INTERACTIVE']
- STDIN.tty? && ENV['TERM'] != 'dumb'
- end
-
- # because all input will eventually be evaluated as Ruby code,
- # command names that conflict with Ruby keywords need special workaround
- # we can remove them once we implemented a better command system for IRB
- KEYWORD_ALIASES = {
- :break => :irb_break,
- :catch => :irb_catch,
- :next => :irb_next,
- }.freeze
-
- private_constant :KEYWORD_ALIASES
-
- def use_tracer=(val)
- require_relative "ext/tracer" if val
- IRB.conf[:USE_TRACER] = val
- end
-
- def eval_history=(val)
- self.class.remove_method(__method__)
- require_relative "ext/eval_history"
- __send__(__method__, val)
- end
-
- def use_loader=(val)
- self.class.remove_method(__method__)
- require_relative "ext/use-loader"
- __send__(__method__, val)
- end
-
- private def build_completor
- completor_type = IRB.conf[:COMPLETOR]
- case completor_type
- when :regexp
- return RegexpCompletor.new
- when :type
- completor = build_type_completor
- return completor if completor
- else
- warn "Invalid value for IRB.conf[:COMPLETOR]: #{completor_type}"
- end
- # Fallback to RegexpCompletor
- RegexpCompletor.new
- end
-
- private def build_type_completor
- if RUBY_ENGINE == 'truffleruby'
- # Avoid SyntaxError. truffleruby does not support endless method definition yet.
- warn 'TypeCompletor is not supported on TruffleRuby yet'
- return
- end
-
- begin
- require 'repl_type_completor'
- rescue LoadError => e
- warn "TypeCompletor requires `gem repl_type_completor`: #{e.message}"
- return
- end
-
- ReplTypeCompletor.preload_rbs
- TypeCompletor.new(self)
- end
-
- def save_history=(val)
- IRB.conf[:SAVE_HISTORY] = val
- end
-
- def save_history
- IRB.conf[:SAVE_HISTORY]
- end
-
- # A copy of the default <code>IRB.conf[:HISTORY_FILE]</code>
- def history_file
- IRB.conf[:HISTORY_FILE]
- end
-
- # Set <code>IRB.conf[:HISTORY_FILE]</code> to the given +hist+.
- def history_file=(hist)
- IRB.conf[:HISTORY_FILE] = hist
- end
-
- # Workspace in the current context.
- def workspace
- @workspace_stack.last
- end
-
- # Replace the current workspace with the given +workspace+.
- def replace_workspace(workspace)
- @workspace_stack.pop
- @workspace_stack.push(workspace)
- end
-
- # The top-level workspace, see WorkSpace#main
- def main
- workspace.main
- end
-
- # The toplevel workspace, see #home_workspace
- attr_reader :workspace_home
- # The current thread in this context.
- attr_reader :thread
- # The current input method.
- #
- # Can be either StdioInputMethod, ReadlineInputMethod,
- # RelineInputMethod, FileInputMethod or other specified when the
- # context is created. See ::new for more # information on +input_method+.
- attr_accessor :io
-
- # Current irb session.
- attr_accessor :irb
- # A copy of the default <code>IRB.conf[:AP_NAME]</code>
- attr_accessor :ap_name
- # A copy of the default <code>IRB.conf[:RC]</code>
- attr_accessor :rc
- # A copy of the default <code>IRB.conf[:LOAD_MODULES]</code>
- attr_accessor :load_modules
- # Can be either name from <code>IRB.conf[:IRB_NAME]</code>, or the number of
- # the current job set by JobManager, such as <code>irb#2</code>
- attr_accessor :irb_name
-
- # Can be one of the following:
- # - the #irb_name surrounded by parenthesis
- # - the +input_method+ passed to Context.new
- # - the file path of the current IRB context in a binding.irb session
- attr_reader :irb_path
-
- # Sets @irb_path to the given +path+ as well as @eval_path
- # @eval_path is used for evaluating code in the context of IRB session
- # It's the same as irb_path, but with the IRB name postfix
- # This makes sure users can distinguish the methods defined in the IRB session
- # from the methods defined in the current file's context, especially with binding.irb
- def irb_path=(path)
- @irb_path = path
-
- if File.exist?(path)
- @eval_path = "#{path}(#{IRB.conf[:IRB_NAME]})"
- else
- @eval_path = path
- end
- end
-
- # Whether multiline editor mode is enabled or not.
- #
- # A copy of the default <code>IRB.conf[:USE_MULTILINE]</code>
- attr_reader :use_multiline
- # Whether singleline editor mode is enabled or not.
- #
- # A copy of the default <code>IRB.conf[:USE_SINGLELINE]</code>
- attr_reader :use_singleline
- # Whether colorization is enabled or not.
- #
- # A copy of the default <code>IRB.conf[:USE_AUTOCOMPLETE]</code>
- attr_reader :use_autocomplete
- # A copy of the default <code>IRB.conf[:INSPECT_MODE]</code>
- attr_reader :inspect_mode
-
- # A copy of the default <code>IRB.conf[:PROMPT_MODE]</code>
- attr_reader :prompt_mode
- # Standard IRB prompt.
- #
- # See {Custom Prompts}[rdoc-ref:IRB@Custom+Prompts] for more information.
- attr_accessor :prompt_i
- # IRB prompt for continuated strings.
- #
- # See {Custom Prompts}[rdoc-ref:IRB@Custom+Prompts] for more information.
- attr_accessor :prompt_s
- # IRB prompt for continuated statement. (e.g. immediately after an +if+)
- #
- # See {Custom Prompts}[rdoc-ref:IRB@Custom+Prompts] for more information.
- attr_accessor :prompt_c
-
- # TODO: Remove this when developing v2.0
- def prompt_n
- warn "IRB::Context#prompt_n is deprecated and will be removed in the next major release."
- ""
- end
-
- # TODO: Remove this when developing v2.0
- def prompt_n=(_)
- warn "IRB::Context#prompt_n= is deprecated and will be removed in the next major release."
- ""
- end
-
- # Can be either the default <code>IRB.conf[:AUTO_INDENT]</code>, or the
- # mode set by #prompt_mode=
- #
- # To disable auto-indentation in irb:
- #
- # IRB.conf[:AUTO_INDENT] = false
- #
- # or
- #
- # irb_context.auto_indent_mode = false
- #
- # or
- #
- # IRB.CurrentContext.auto_indent_mode = false
- #
- # See IRB@Configuration for more information.
- attr_accessor :auto_indent_mode
- # The format of the return statement, set by #prompt_mode= using the
- # +:RETURN+ of the +mode+ passed to set the current #prompt_mode.
- attr_accessor :return_format
-
- # Whether <code>^C</code> (+control-c+) will be ignored or not.
- #
- # If set to +false+, <code>^C</code> will quit irb.
- #
- # If set to +true+,
- #
- # * during input: cancel input then return to top level.
- # * during execute: abandon current execution.
- attr_accessor :ignore_sigint
- # Whether <code>^D</code> (+control-d+) will be ignored or not.
- #
- # If set to +false+, <code>^D</code> 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 <code>IRB.conf[:ECHO]</code> if available, or defaults to +true+.
- #
- # puts "hello"
- # # hello
- # #=> nil
- # IRB.CurrentContext.echo = false
- # puts "omg"
- # # omg
- attr_accessor :echo
- # Whether to echo for assignment expressions.
- #
- # If set to +false+, the value of assignment will not be shown.
- #
- # If set to +true+, the value of assignment will be shown.
- #
- # If set to +:truncate+, the value of assignment will be shown and truncated.
- #
- # It defaults to +:truncate+.
- #
- # a = "omg"
- # #=> omg
- #
- # a = "omg" * 10
- # #=> omgomgomgomgomgomgomg...
- #
- # IRB.CurrentContext.echo_on_assignment = false
- # a = "omg"
- #
- # IRB.CurrentContext.echo_on_assignment = true
- # a = "omg" * 10
- # #=> omgomgomgomgomgomgomgomgomgomg
- #
- # To set the behaviour of showing on assignment in irb:
- #
- # IRB.conf[:ECHO_ON_ASSIGNMENT] = :truncate or true or false
- #
- # or
- #
- # irb_context.echo_on_assignment = :truncate or true or false
- #
- # or
- #
- # IRB.CurrentContext.echo_on_assignment = :truncate or true or false
- attr_accessor :echo_on_assignment
- # Whether a newline is put before multiline output.
- #
- # Uses <code>IRB.conf[:NEWLINE_BEFORE_MULTILINE_OUTPUT]</code> if available,
- # or defaults to +true+.
- #
- # "abc\ndef"
- # #=>
- # abc
- # def
- # IRB.CurrentContext.newline_before_multiline_output = false
- # "abc\ndef"
- # #=> abc
- # def
- attr_accessor :newline_before_multiline_output
- # Whether verbose messages are displayed or not.
- #
- # A copy of the default <code>IRB.conf[:VERBOSE]</code>
- attr_accessor :verbose
-
- # The limit of backtrace lines displayed as top +n+ and tail +n+.
- #
- # The default value is 16.
- #
- # Can also be set using the +--back-trace-limit+ command line option.
- attr_accessor :back_trace_limit
-
- # User-defined IRB command aliases
- attr_accessor :command_aliases
-
- attr_accessor :with_debugger
-
- # Alias for #use_multiline
- alias use_multiline? use_multiline
- # Alias for #use_singleline
- alias use_singleline? use_singleline
- # backward compatibility
- alias use_reline use_multiline
- # backward compatibility
- alias use_reline? use_multiline
- # backward compatibility
- alias use_readline use_singleline
- # backward compatibility
- alias use_readline? use_singleline
- # Alias for #use_autocomplete
- alias use_autocomplete? use_autocomplete
- # Alias for #rc
- alias rc? rc
- alias ignore_sigint? ignore_sigint
- alias ignore_eof? ignore_eof
- alias echo? echo
- alias echo_on_assignment? echo_on_assignment
- alias newline_before_multiline_output? newline_before_multiline_output
-
- # Returns whether messages are displayed or not.
- def verbose?
- if @verbose.nil?
- if @io.kind_of?(RelineInputMethod)
- false
- elsif defined?(ReadlineInputMethod) && @io.kind_of?(ReadlineInputMethod)
- false
- elsif !STDIN.tty? or @io.kind_of?(FileInputMethod)
- true
- else
- false
- end
- else
- @verbose
- end
- end
-
- # Whether #verbose? is +true+, and +input_method+ is either
- # StdioInputMethod or RelineInputMethod or ReadlineInputMethod, see #io
- # for more information.
- def prompting?
- verbose? || @io.prompting?
- end
-
- # The return value of the last statement evaluated.
- attr_reader :last_value
-
- # Sets the return value from the last statement evaluated in this context
- # to #last_value.
- def set_last_value(value)
- @last_value = value
- workspace.local_variable_set :_, value
- end
-
- # Sets the +mode+ of the prompt in this context.
- #
- # See {Custom Prompts}[rdoc-ref:IRB@Custom+Prompts] for more information.
- def prompt_mode=(mode)
- @prompt_mode = mode
- pconf = IRB.conf[:PROMPT][mode]
- @prompt_i = pconf[:PROMPT_I]
- @prompt_s = pconf[:PROMPT_S]
- @prompt_c = pconf[:PROMPT_C]
- @return_format = pconf[:RETURN]
- @return_format = "%s\n" if @return_format == nil
- if ai = pconf.include?(:AUTO_INDENT)
- @auto_indent_mode = ai
- else
- @auto_indent_mode = IRB.conf[:AUTO_INDENT]
- end
- end
-
- # Whether #inspect_mode is set or not, see #inspect_mode= for more detail.
- def inspect?
- @inspect_mode.nil? or @inspect_mode
- end
-
- # Whether #io uses a File for the +input_method+ passed when creating the
- # current context, see ::new
- def file_input?
- @io.class == FileInputMethod
- end
-
- # Specifies the inspect mode with +opt+:
- #
- # +true+:: display +inspect+
- # +false+:: display +to_s+
- # +nil+:: inspect mode in non-math mode,
- # non-inspect mode in math mode
- #
- # See IRB::Inspector for more information.
- #
- # Can also be set using the +--inspect+ and +--noinspect+ command line
- # options.
- def inspect_mode=(opt)
-
- if i = Inspector::INSPECTORS[opt]
- @inspect_mode = opt
- @inspect_method = i
- i.init
- else
- case opt
- when nil
- if Inspector.keys_with_inspector(Inspector::INSPECTORS[true]).include?(@inspect_mode)
- self.inspect_mode = false
- elsif Inspector.keys_with_inspector(Inspector::INSPECTORS[false]).include?(@inspect_mode)
- self.inspect_mode = true
- else
- puts "Can't switch inspect mode."
- return
- end
- when /^\s*\{.*\}\s*$/
- begin
- inspector = eval "proc#{opt}"
- rescue Exception
- puts "Can't switch inspect mode(#{opt})."
- return
- end
- self.inspect_mode = inspector
- when Proc
- self.inspect_mode = IRB::Inspector(opt)
- when Inspector
- prefix = "usr%d"
- i = 1
- while Inspector::INSPECTORS[format(prefix, i)]; i += 1; end
- @inspect_mode = format(prefix, i)
- @inspect_method = opt
- Inspector.def_inspector(format(prefix, i), @inspect_method)
- else
- puts "Can't switch inspect mode(#{opt})."
- return
- end
- end
- print "Switch to#{unless @inspect_mode; ' non';end} inspect mode.\n" if verbose?
- @inspect_mode
- end
-
- def evaluate(statement, line_no) # :nodoc:
- @line_no = line_no
-
- case statement
- when Statement::EmptyInput
- return
- when Statement::Expression
- result = evaluate_expression(statement.code, line_no)
- set_last_value(result)
- when Statement::Command
- statement.command_class.execute(self, statement.arg)
- set_last_value(nil)
- end
-
- nil
- end
-
- def from_binding?
- @irb.from_binding
- end
-
- def evaluate_expression(code, line_no) # :nodoc:
- result = nil
- if IRB.conf[:MEASURE] && IRB.conf[:MEASURE_CALLBACKS].empty?
- IRB.set_measure_callback
- end
-
- if IRB.conf[:MEASURE] && !IRB.conf[:MEASURE_CALLBACKS].empty?
- last_proc = proc do
- result = workspace.evaluate(code, @eval_path, line_no)
- end
- IRB.conf[:MEASURE_CALLBACKS].inject(last_proc) do |chain, item|
- _name, callback, arg = item
- proc do
- callback.(self, code, line_no, arg) do
- chain.call
- end
- end
- end.call
- else
- result = workspace.evaluate(code, @eval_path, line_no)
- end
- result
- end
-
- def inspect_last_value # :nodoc:
- @inspect_method.inspect_value(@last_value)
- end
-
- NOPRINTING_IVARS = ["@last_value"] # :nodoc:
- NO_INSPECTING_IVARS = ["@irb", "@io"] # :nodoc:
- IDNAME_IVARS = ["@prompt_mode"] # :nodoc:
-
- alias __inspect__ inspect
- def inspect # :nodoc:
- array = []
- for ivar in instance_variables.sort{|e1, e2| e1 <=> e2}
- ivar = ivar.to_s
- name = ivar.sub(/^@(.*)$/, '\1')
- val = instance_eval(ivar)
- case ivar
- when *NOPRINTING_IVARS
- array.push format("conf.%s=%s", name, "...")
- when *NO_INSPECTING_IVARS
- array.push format("conf.%s=%s", name, val.to_s)
- when *IDNAME_IVARS
- array.push format("conf.%s=:%s", name, val.id2name)
- else
- array.push format("conf.%s=%s", name, val.inspect)
- end
- end
- array.join("\n")
- end
- alias __to_s__ to_s
- alias to_s inspect
-
- def local_variables # :nodoc:
- workspace.binding.local_variables
- end
- end
-end
diff --git a/lib/irb/debug.rb b/lib/irb/debug.rb
deleted file mode 100644
index 1ec2335a8e..0000000000
--- a/lib/irb/debug.rb
+++ /dev/null
@@ -1,130 +0,0 @@
-# frozen_string_literal: true
-
-module IRB
- module Debug
- IRB_DIR = File.expand_path('..', __dir__)
-
- class << self
- def insert_debug_break(pre_cmds: nil, do_cmds: nil)
- options = { oneshot: true, hook_call: false }
-
- if pre_cmds || do_cmds
- options[:command] = ['irb', pre_cmds, do_cmds]
- end
- if DEBUGGER__::LineBreakpoint.instance_method(:initialize).parameters.include?([:key, :skip_src])
- options[:skip_src] = true
- end
-
- # To make debugger commands like `next` or `continue` work without asking
- # the user to quit IRB after that, we need to exit IRB first and then hit
- # a TracePoint on #debug_break.
- file, lineno = IRB::Irb.instance_method(:debug_break).source_location
- DEBUGGER__::SESSION.add_line_breakpoint(file, lineno + 1, **options)
- end
-
- def setup(irb)
- # When debug session is not started at all
- unless defined?(DEBUGGER__::SESSION)
- begin
- require "debug/session"
- rescue LoadError # debug.gem is not written in Gemfile
- return false unless load_bundled_debug_gem
- end
- DEBUGGER__::CONFIG.set_config
- configure_irb_for_debugger(irb)
-
- DEBUGGER__.initialize_session{ IRB::Debug::UI.new(irb) }
- end
-
- # When debug session was previously started but not by IRB
- if defined?(DEBUGGER__::SESSION) && !irb.context.with_debugger
- configure_irb_for_debugger(irb)
- DEBUGGER__::SESSION.reset_ui(IRB::Debug::UI.new(irb))
- end
-
- # Apply patches to debug gem so it skips IRB frames
- unless DEBUGGER__.respond_to?(:capture_frames_without_irb)
- DEBUGGER__.singleton_class.send(:alias_method, :capture_frames_without_irb, :capture_frames)
-
- def DEBUGGER__.capture_frames(*args)
- frames = capture_frames_without_irb(*args)
- frames.reject! do |frame|
- frame.realpath&.start_with?(IRB_DIR) || frame.path == "<internal:prelude>"
- end
- frames
- end
-
- DEBUGGER__::ThreadClient.prepend(SkipPathHelperForIRB)
- end
-
- if !@output_modifier_defined && !DEBUGGER__::CONFIG[:no_hint]
- irb_output_modifier_proc = Reline.output_modifier_proc
-
- Reline.output_modifier_proc = proc do |output, complete:|
- unless output.strip.empty?
- cmd = output.split(/\s/, 2).first
-
- if !complete && DEBUGGER__.commands.key?(cmd)
- output = output.sub(/\n$/, " # debug command\n")
- end
- end
-
- irb_output_modifier_proc.call(output, complete: complete)
- end
-
- @output_modifier_defined = true
- end
-
- true
- end
-
- private
-
- def configure_irb_for_debugger(irb)
- require 'irb/debug/ui'
- IRB.instance_variable_set(:@debugger_irb, irb)
- irb.context.with_debugger = true
- irb.context.irb_name += ":rdbg"
- end
-
- module SkipPathHelperForIRB
- def skip_internal_path?(path)
- # The latter can be removed once https://github.com/ruby/debug/issues/866 is resolved
- super || path.match?(IRB_DIR) || path.match?('<internal:prelude>')
- end
- end
-
- # This is used when debug.gem is not written in Gemfile. Even if it's not
- # installed by `bundle install`, debug.gem is installed by default because
- # it's a bundled gem. This method tries to activate and load that.
- def load_bundled_debug_gem
- # Discover latest debug.gem under GEM_PATH
- debug_gem = Gem.paths.path.flat_map { |path| Dir.glob("#{path}/gems/debug-*") }.select do |path|
- File.basename(path).match?(/\Adebug-\d+\.\d+\.\d+(\w+)?\z/)
- end.sort_by do |path|
- Gem::Version.new(File.basename(path).delete_prefix('debug-'))
- end.last
- return false unless debug_gem
-
- # Discover debug/debug.so under extensions for Ruby 3.2+
- ext_name = "/debug/debug.#{RbConfig::CONFIG['DLEXT']}"
- ext_path = Gem.paths.path.flat_map do |path|
- Dir.glob("#{path}/extensions/**/#{File.basename(debug_gem)}#{ext_name}")
- end.first
-
- # Attempt to forcibly load the bundled gem
- if ext_path
- $LOAD_PATH << ext_path.delete_suffix(ext_name)
- end
- $LOAD_PATH << "#{debug_gem}/lib"
- begin
- require "debug/session"
- puts "Loaded #{File.basename(debug_gem)}"
- true
- rescue LoadError
- false
- end
- end
- end
- end
-end
diff --git a/lib/irb/debug/ui.rb b/lib/irb/debug/ui.rb
deleted file mode 100644
index 307097b8c9..0000000000
--- a/lib/irb/debug/ui.rb
+++ /dev/null
@@ -1,103 +0,0 @@
-require 'io/console/size'
-require 'debug/console'
-
-module IRB
- module Debug
- class UI < DEBUGGER__::UI_Base
- def initialize(irb)
- @irb = irb
- end
-
- def remote?
- false
- end
-
- def activate session, on_fork: false
- end
-
- def deactivate
- end
-
- def width
- if (w = IO.console_size[1]) == 0 # for tests PTY
- 80
- else
- w
- end
- end
-
- def quit n
- yield
- exit n
- end
-
- def ask prompt
- setup_interrupt do
- print prompt
- ($stdin.gets || '').strip
- end
- end
-
- def puts str = nil
- case str
- when Array
- str.each{|line|
- $stdout.puts line.chomp
- }
- when String
- str.each_line{|line|
- $stdout.puts line.chomp
- }
- when nil
- $stdout.puts
- end
- end
-
- def readline _
- setup_interrupt do
- tc = DEBUGGER__::SESSION.instance_variable_get(:@tc)
- cmd = @irb.debug_readline(tc.current_frame.binding || TOPLEVEL_BINDING)
-
- case cmd
- when nil # when user types C-d
- "continue"
- else
- cmd
- end
- end
- end
-
- def setup_interrupt
- DEBUGGER__::SESSION.intercept_trap_sigint false do
- current_thread = Thread.current # should be session_server thread
-
- prev_handler = trap(:INT){
- current_thread.raise Interrupt
- }
-
- yield
- ensure
- trap(:INT, prev_handler)
- end
- end
-
- def after_fork_parent
- parent_pid = Process.pid
-
- at_exit{
- DEBUGGER__::SESSION.intercept_trap_sigint_end
- trap(:SIGINT, :IGNORE)
-
- if Process.pid == parent_pid
- # only check child process from its parent
- begin
- # wait for all child processes to keep terminal
- Process.waitpid
- rescue Errno::ESRCH, Errno::ECHILD
- end
- end
- }
- end
- end
- end
-end
diff --git a/lib/irb/default_commands.rb b/lib/irb/default_commands.rb
deleted file mode 100644
index 1bbc68efa7..0000000000
--- a/lib/irb/default_commands.rb
+++ /dev/null
@@ -1,260 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "command"
-require_relative "command/internal_helpers"
-require_relative "command/context"
-require_relative "command/exit"
-require_relative "command/force_exit"
-require_relative "command/chws"
-require_relative "command/pushws"
-require_relative "command/subirb"
-require_relative "command/load"
-require_relative "command/debug"
-require_relative "command/edit"
-require_relative "command/break"
-require_relative "command/catch"
-require_relative "command/next"
-require_relative "command/delete"
-require_relative "command/step"
-require_relative "command/continue"
-require_relative "command/finish"
-require_relative "command/backtrace"
-require_relative "command/info"
-require_relative "command/help"
-require_relative "command/show_doc"
-require_relative "command/irb_info"
-require_relative "command/ls"
-require_relative "command/measure"
-require_relative "command/show_source"
-require_relative "command/whereami"
-require_relative "command/history"
-
-module IRB
- module Command
- NO_OVERRIDE = 0
- OVERRIDE_PRIVATE_ONLY = 0x01
- OVERRIDE_ALL = 0x02
-
- class << self
- # This API is for IRB's internal use only and may change at any time.
- # Please do NOT use it.
- def _register_with_aliases(name, command_class, *aliases)
- @commands[name.to_sym] = [command_class, aliases]
- end
-
- def all_commands_info
- user_aliases = IRB.CurrentContext.command_aliases.each_with_object({}) do |(alias_name, target), result|
- result[target] ||= []
- result[target] << alias_name
- end
-
- commands.map do |command_name, (command_class, aliases)|
- aliases = aliases.map { |a| a.first }
-
- if additional_aliases = user_aliases[command_name]
- aliases += additional_aliases
- end
-
- display_name = aliases.shift || command_name
- {
- display_name: display_name,
- description: command_class.description,
- category: command_class.category
- }
- end
- end
-
- def command_override_policies
- @@command_override_policies ||= commands.flat_map do |cmd_name, (cmd_class, aliases)|
- [[cmd_name, OVERRIDE_ALL]] + aliases
- end.to_h
- end
-
- def execute_as_command?(name, public_method:, private_method:)
- case command_override_policies[name]
- when OVERRIDE_ALL
- true
- when OVERRIDE_PRIVATE_ONLY
- !public_method
- when NO_OVERRIDE
- !public_method && !private_method
- end
- end
-
- def command_names
- command_override_policies.keys.map(&:to_s)
- end
-
- # Convert a command name to its implementation class if such command exists
- def load_command(command)
- command = command.to_sym
- commands.each do |command_name, (command_class, aliases)|
- if command_name == command || aliases.any? { |alias_name, _| alias_name == command }
- return command_class
- end
- end
- nil
- end
- end
-
- _register_with_aliases(:irb_context, Command::Context,
- [:context, NO_OVERRIDE]
- )
-
- _register_with_aliases(:irb_exit, Command::Exit,
- [:exit, OVERRIDE_PRIVATE_ONLY],
- [:quit, OVERRIDE_PRIVATE_ONLY],
- [:irb_quit, OVERRIDE_PRIVATE_ONLY]
- )
-
- _register_with_aliases(:irb_exit!, Command::ForceExit,
- [:exit!, OVERRIDE_PRIVATE_ONLY]
- )
-
- _register_with_aliases(:irb_current_working_workspace, Command::CurrentWorkingWorkspace,
- [:cwws, NO_OVERRIDE],
- [:pwws, NO_OVERRIDE],
- [:irb_print_working_workspace, OVERRIDE_ALL],
- [:irb_cwws, OVERRIDE_ALL],
- [:irb_pwws, OVERRIDE_ALL],
- [:irb_current_working_binding, OVERRIDE_ALL],
- [:irb_print_working_binding, OVERRIDE_ALL],
- [:irb_cwb, OVERRIDE_ALL],
- [:irb_pwb, OVERRIDE_ALL],
- )
-
- _register_with_aliases(:irb_change_workspace, Command::ChangeWorkspace,
- [:chws, NO_OVERRIDE],
- [:cws, NO_OVERRIDE],
- [:irb_chws, OVERRIDE_ALL],
- [:irb_cws, OVERRIDE_ALL],
- [:irb_change_binding, OVERRIDE_ALL],
- [:irb_cb, OVERRIDE_ALL],
- [:cb, NO_OVERRIDE],
- )
-
- _register_with_aliases(:irb_workspaces, Command::Workspaces,
- [:workspaces, NO_OVERRIDE],
- [:irb_bindings, OVERRIDE_ALL],
- [:bindings, NO_OVERRIDE],
- )
-
- _register_with_aliases(:irb_push_workspace, Command::PushWorkspace,
- [:pushws, NO_OVERRIDE],
- [:irb_pushws, OVERRIDE_ALL],
- [:irb_push_binding, OVERRIDE_ALL],
- [:irb_pushb, OVERRIDE_ALL],
- [:pushb, NO_OVERRIDE],
- )
-
- _register_with_aliases(:irb_pop_workspace, Command::PopWorkspace,
- [:popws, NO_OVERRIDE],
- [:irb_popws, OVERRIDE_ALL],
- [:irb_pop_binding, OVERRIDE_ALL],
- [:irb_popb, OVERRIDE_ALL],
- [:popb, NO_OVERRIDE],
- )
-
- _register_with_aliases(:irb_load, Command::Load)
- _register_with_aliases(:irb_require, Command::Require)
- _register_with_aliases(:irb_source, Command::Source,
- [:source, NO_OVERRIDE]
- )
-
- _register_with_aliases(:irb, Command::IrbCommand)
- _register_with_aliases(:irb_jobs, Command::Jobs,
- [:jobs, NO_OVERRIDE]
- )
- _register_with_aliases(:irb_fg, Command::Foreground,
- [:fg, NO_OVERRIDE]
- )
- _register_with_aliases(:irb_kill, Command::Kill,
- [:kill, OVERRIDE_PRIVATE_ONLY]
- )
-
- _register_with_aliases(:irb_debug, Command::Debug,
- [:debug, NO_OVERRIDE]
- )
- _register_with_aliases(:irb_edit, Command::Edit,
- [:edit, NO_OVERRIDE]
- )
-
- _register_with_aliases(:irb_break, Command::Break)
- _register_with_aliases(:irb_catch, Command::Catch)
- _register_with_aliases(:irb_next, Command::Next)
- _register_with_aliases(:irb_delete, Command::Delete,
- [:delete, NO_OVERRIDE]
- )
-
- _register_with_aliases(:irb_step, Command::Step,
- [:step, NO_OVERRIDE]
- )
- _register_with_aliases(:irb_continue, Command::Continue,
- [:continue, NO_OVERRIDE]
- )
- _register_with_aliases(:irb_finish, Command::Finish,
- [:finish, NO_OVERRIDE]
- )
- _register_with_aliases(:irb_backtrace, Command::Backtrace,
- [:backtrace, NO_OVERRIDE],
- [:bt, NO_OVERRIDE]
- )
-
- _register_with_aliases(:irb_debug_info, Command::Info,
- [:info, NO_OVERRIDE]
- )
-
- _register_with_aliases(:irb_help, Command::Help,
- [:help, NO_OVERRIDE],
- [:show_cmds, NO_OVERRIDE]
- )
-
- _register_with_aliases(:irb_show_doc, Command::ShowDoc,
- [:show_doc, NO_OVERRIDE]
- )
-
- _register_with_aliases(:irb_info, Command::IrbInfo)
-
- _register_with_aliases(:irb_ls, Command::Ls,
- [:ls, NO_OVERRIDE]
- )
-
- _register_with_aliases(:irb_measure, Command::Measure,
- [:measure, NO_OVERRIDE]
- )
-
- _register_with_aliases(:irb_show_source, Command::ShowSource,
- [:show_source, NO_OVERRIDE]
- )
-
- _register_with_aliases(:irb_whereami, Command::Whereami,
- [:whereami, NO_OVERRIDE]
- )
-
- _register_with_aliases(:irb_history, Command::History,
- [:history, NO_OVERRIDE],
- [:hist, NO_OVERRIDE]
- )
- end
-
- ExtendCommand = Command
-
- # For backward compatibility, we need to keep this module:
- # - As a container of helper methods
- # - As a place to register commands with the deprecated def_extend_command method
- module ExtendCommandBundle
- # For backward compatibility
- NO_OVERRIDE = Command::NO_OVERRIDE
- OVERRIDE_PRIVATE_ONLY = Command::OVERRIDE_PRIVATE_ONLY
- OVERRIDE_ALL = Command::OVERRIDE_ALL
-
- # Deprecated. Doesn't have any effect.
- @EXTEND_COMMANDS = []
-
- # Drepcated. Use Command.regiser instead.
- def self.def_extend_command(cmd_name, cmd_class, _, *aliases)
- Command._register_with_aliases(cmd_name, cmd_class, *aliases)
- Command.class_variable_set(:@@command_override_policies, nil)
- end
- end
-end
diff --git a/lib/irb/easter-egg.rb b/lib/irb/easter-egg.rb
deleted file mode 100644
index adc0834d55..0000000000
--- a/lib/irb/easter-egg.rb
+++ /dev/null
@@ -1,148 +0,0 @@
-require "reline"
-
-module IRB
- class << self
- class Vec
- def initialize(x, y, z)
- @x, @y, @z = x, y, z
- end
-
- attr_reader :x, :y, :z
-
- def sub(other)
- Vec.new(@x - other.x, @y - other.y, @z - other.z)
- end
-
- def dot(other)
- @x*other.x + @y*other.y + @z*other.z
- end
-
- def cross(other)
- ox, oy, oz = other.x, other.y, other.z
- Vec.new(@y*oz-@z*oy, @z*ox-@x*oz, @x*oy-@y*ox)
- end
-
- def normalize
- r = Math.sqrt(self.dot(self))
- Vec.new(@x / r, @y / r, @z / r)
- end
- end
-
- class Canvas
- def initialize((h, w))
- @data = (0..h-2).map { [0] * w }
- @scale = [w / 2.0, h-2].min
- @center = Complex(w / 2, h-2)
- end
-
- def line((x1, y1), (x2, y2))
- p1 = Complex(x1, y1) / 2 * @scale + @center
- p2 = Complex(x2, y2) / 2 * @scale + @center
- line0(p1, p2)
- end
-
- private def line0(p1, p2)
- mid = (p1 + p2) / 2
- if (p1 - p2).abs < 1
- x, y = mid.rect
- @data[y / 2][x] |= (y % 2 > 1 ? 2 : 1)
- else
- line0(p1, mid)
- line0(p2, mid)
- end
- end
-
- def draw
- @data.each {|row| row.fill(0) }
- yield
- @data.map {|row| row.map {|n| " ',;"[n] }.join }.join("\n")
- end
- end
-
- class RubyModel
- def initialize
- @faces = init_ruby_model
- end
-
- def init_ruby_model
- cap_vertices = (0..5).map {|i| Vec.new(*Complex.polar(1, i * Math::PI / 3).rect, 1) }
- middle_vertices = (0..5).map {|i| Vec.new(*Complex.polar(2, (i + 0.5) * Math::PI / 3).rect, 0) }
- bottom_vertex = Vec.new(0, 0, -2)
-
- faces = [cap_vertices]
- 6.times do |j|
- i = j-1
- faces << [cap_vertices[i], middle_vertices[i], cap_vertices[j]]
- faces << [cap_vertices[j], middle_vertices[i], middle_vertices[j]]
- faces << [middle_vertices[i], bottom_vertex, middle_vertices[j]]
- end
-
- faces
- end
-
- def render_frame(i)
- angle = i / 10.0
- dir = Vec.new(*Complex.polar(1, angle).rect, Math.sin(angle)).normalize
- dir2 = Vec.new(*Complex.polar(1, angle - Math::PI/2).rect, 0)
- up = dir.cross(dir2)
- nm = dir.cross(up)
- @faces.each do |vertices|
- v0, v1, v2, = vertices
- if v1.sub(v0).cross(v2.sub(v0)).dot(dir) > 0
- points = vertices.map {|p| [nm.dot(p), up.dot(p)] }
- (points + [points[0]]).each_cons(2) do |p1, p2|
- yield p1, p2
- end
- end
- end
- end
- end
-
- private def easter_egg_logo(type)
- @easter_egg_logos ||= File.read(File.join(__dir__, 'ruby_logo.aa'), encoding: 'UTF-8:UTF-8')
- .split(/TYPE: ([A-Z]+)\n/)[1..]
- .each_slice(2)
- .to_h
- @easter_egg_logos[type.to_s.upcase]
- end
-
- private def easter_egg(type = nil)
- type ||= [:logo, :dancing].sample
- case type
- when :logo
- require "rdoc"
- RDoc::RI::Driver.new.page do |io|
- io.write easter_egg_logo(:large)
- end
- when :dancing
- STDOUT.cooked do
- interrupted = false
- prev_trap = trap("SIGINT") { interrupted = true }
- canvas = Canvas.new(Reline.get_screen_size)
- Reline::IOGate.set_winch_handler do
- canvas = Canvas.new(Reline.get_screen_size)
- end
- ruby_model = RubyModel.new
- print "\e[?1049h"
- 0.step do |i| # TODO (0..).each needs Ruby 2.6 or later
- buff = canvas.draw do
- ruby_model.render_frame(i) do |p1, p2|
- canvas.line(p1, p2)
- end
- end
- buff[0, 20] = "\e[0mPress Ctrl+C to stop\e[31m\e[1m"
- print "\e[H" + buff
- sleep 0.05
- break if interrupted
- end
- rescue Interrupt
- ensure
- print "\e[0m\e[?1049l"
- trap("SIGINT", prev_trap)
- end
- end
- end
- end
-end
-
-IRB.__send__(:easter_egg, ARGV[0]&.to_sym) if $0 == __FILE__
diff --git a/lib/irb/ext/change-ws.rb b/lib/irb/ext/change-ws.rb
deleted file mode 100644
index 60e8afe31f..0000000000
--- a/lib/irb/ext/change-ws.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-#
-# irb/ext/cb.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB # :nodoc:
- class Context
-
- # Inherited from +TOPLEVEL_BINDING+.
- def home_workspace
- if defined? @home_workspace
- @home_workspace
- else
- @home_workspace = workspace
- end
- end
-
- # Changes the current workspace to given object or binding.
- #
- # If the optional argument is omitted, the workspace will be
- # #home_workspace which is inherited from +TOPLEVEL_BINDING+ or the main
- # object, <code>IRB.conf[:MAIN_CONTEXT]</code> when irb was initialized.
- #
- # See IRB::WorkSpace.new for more information.
- def change_workspace(*_main)
- if _main.empty?
- replace_workspace(home_workspace)
- return main
- end
-
- workspace = WorkSpace.new(_main[0])
- replace_workspace(workspace)
- workspace.load_helper_methods_to_main
- end
- end
-end
diff --git a/lib/irb/ext/eval_history.rb b/lib/irb/ext/eval_history.rb
deleted file mode 100644
index 6c21ff00ee..0000000000
--- a/lib/irb/ext/eval_history.rb
+++ /dev/null
@@ -1,149 +0,0 @@
-# frozen_string_literal: true
-#
-# history.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB # :nodoc:
-
- class Context
-
- NOPRINTING_IVARS.push "@eval_history_values"
-
- # See #set_last_value
- alias _set_last_value set_last_value
-
- def set_last_value(value)
- _set_last_value(value)
-
- if defined?(@eval_history) && @eval_history
- @eval_history_values.push @line_no, @last_value
- workspace.evaluate "__ = IRB.CurrentContext.instance_eval{@eval_history_values}"
- end
-
- @last_value
- end
-
- remove_method :eval_history= if method_defined?(:eval_history=)
- # The command result history limit. This method is not available until
- # #eval_history= was called with non-nil value (directly or via
- # setting <code>IRB.conf[:EVAL_HISTORY]</code> in <code>.irbrc</code>).
- attr_reader :eval_history
- # Sets command result history limit. Default value is set from
- # <code>IRB.conf[:EVAL_HISTORY]</code>.
- #
- # +no+ is an Integer or +nil+.
- #
- # Returns +no+ of history items if greater than 0.
- #
- # If +no+ is 0, the number of history items is unlimited.
- #
- # If +no+ is +nil+, execution result history isn't used (default).
- #
- # EvalHistory values are available via <code>__</code> variable, see
- # IRB::EvalHistory.
- def eval_history=(no)
- if no
- if defined?(@eval_history) && @eval_history
- @eval_history_values.size(no)
- else
- @eval_history_values = EvalHistory.new(no)
- IRB.conf[:__TMP__EHV__] = @eval_history_values
- workspace.evaluate("__ = IRB.conf[:__TMP__EHV__]")
- IRB.conf.delete(:__TMP_EHV__)
- end
- else
- @eval_history_values = nil
- end
- @eval_history = no
- end
- end
-
- # Represents history of results of previously evaluated commands.
- #
- # Available via <code>__</code> variable, only if <code>IRB.conf[:EVAL_HISTORY]</code>
- # or <code>IRB::CurrentContext().eval_history</code> is non-nil integer value
- # (by default it is +nil+).
- #
- # Example (in `irb`):
- #
- # # Initialize history
- # IRB::CurrentContext().eval_history = 10
- # # => 10
- #
- # # Perform some commands...
- # 1 + 2
- # # => 3
- # puts 'x'
- # # x
- # # => nil
- # raise RuntimeError
- # # ...error raised
- #
- # # Inspect history (format is "<item number> <evaluated value>":
- # __
- # # => 1 10
- # # 2 3
- # # 3 nil
- #
- # __[1]
- # # => 10
- #
- class EvalHistory
-
- def initialize(size = 16) # :nodoc:
- @size = size
- @contents = []
- end
-
- def size(size) # :nodoc:
- if size != 0 && size < @size
- @contents = @contents[@size - size .. @size]
- end
- @size = size
- end
-
- # Get one item of the content (both positive and negative indexes work).
- def [](idx)
- begin
- if idx >= 0
- @contents.find{|no, val| no == idx}[1]
- else
- @contents[idx][1]
- end
- rescue NameError
- nil
- end
- end
-
- def push(no, val) # :nodoc:
- @contents.push [no, val]
- @contents.shift if @size != 0 && @contents.size > @size
- end
-
- alias real_inspect inspect
-
- def inspect # :nodoc:
- if @contents.empty?
- return real_inspect
- end
-
- unless (last = @contents.pop)[1].equal?(self)
- @contents.push last
- last = nil
- end
- str = @contents.collect{|no, val|
- if val.equal?(self)
- "#{no} ...self-history..."
- else
- "#{no} #{val.inspect}"
- end
- }.join("\n")
- if str == ""
- str = "Empty."
- end
- @contents.push last if last
- str
- end
- end
-end
diff --git a/lib/irb/ext/loader.rb b/lib/irb/ext/loader.rb
deleted file mode 100644
index df5aaa8e5a..0000000000
--- a/lib/irb/ext/loader.rb
+++ /dev/null
@@ -1,127 +0,0 @@
-# frozen_string_literal: true
-#
-# loader.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB # :nodoc:
- # Raised in the event of an exception in a file loaded from an Irb session
- class LoadAbort < Exception;end
-
- # Provides a few commands for loading files within an irb session.
- #
- # See ExtendCommandBundle for more information.
- module IrbLoader
-
- alias ruby_load load
- alias ruby_require require
-
- # Loads the given file similarly to Kernel#load
- def irb_load(fn, priv = nil)
- path = search_file_from_ruby_path(fn)
- raise LoadError, "No such file to load -- #{fn}" unless path
-
- load_file(path, priv)
- end
-
- def search_file_from_ruby_path(fn) # :nodoc:
- if File.absolute_path?(fn)
- return fn if File.exist?(fn)
- return nil
- end
-
- for path in $:
- if File.exist?(f = File.join(path, fn))
- return f
- end
- end
- return nil
- end
-
- # Loads a given file in the current session and displays the source lines
- #
- # See Irb#suspend_input_method for more information.
- def source_file(path)
- irb = irb_context.irb
- irb.suspend_name(path, File.basename(path)) do
- FileInputMethod.open(path) do |io|
- irb.suspend_input_method(io) do
- |back_io|
- irb.signal_status(:IN_LOAD) do
- if back_io.kind_of?(FileInputMethod)
- irb.eval_input
- else
- begin
- irb.eval_input
- rescue LoadAbort
- print "load abort!!\n"
- end
- end
- end
- end
- end
- end
- end
-
- # Loads the given file in the current session's context and evaluates it.
- #
- # See Irb#suspend_input_method for more information.
- def load_file(path, priv = nil)
- irb = irb_context.irb
- irb.suspend_name(path, File.basename(path)) do
-
- if priv
- ws = WorkSpace.new(Module.new)
- else
- ws = WorkSpace.new
- end
- irb.suspend_workspace(ws) do
- FileInputMethod.open(path) do |io|
- irb.suspend_input_method(io) do
- |back_io|
- irb.signal_status(:IN_LOAD) do
- if back_io.kind_of?(FileInputMethod)
- irb.eval_input
- else
- begin
- irb.eval_input
- rescue LoadAbort
- print "load abort!!\n"
- end
- end
- end
- end
- end
- end
- end
- end
-
- def old # :nodoc:
- back_io = @io
- back_path = irb_path
- back_name = @irb_name
- back_scanner = @irb.scanner
- begin
- @io = FileInputMethod.new(path)
- @irb_name = File.basename(path)
- self.irb_path = path
- @irb.signal_status(:IN_LOAD) do
- if back_io.kind_of?(FileInputMethod)
- @irb.eval_input
- else
- begin
- @irb.eval_input
- rescue LoadAbort
- print "load abort!!\n"
- end
- end
- end
- ensure
- @io = back_io
- @irb_name = back_name
- self.irb_path = back_path
- @irb.scanner = back_scanner
- end
- end
- end
-end
diff --git a/lib/irb/ext/multi-irb.rb b/lib/irb/ext/multi-irb.rb
deleted file mode 100644
index 9f234f0cdc..0000000000
--- a/lib/irb/ext/multi-irb.rb
+++ /dev/null
@@ -1,258 +0,0 @@
-# frozen_string_literal: true
-#
-# irb/multi-irb.rb - multiple irb module
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB
- class JobManager # :nodoc:
-
- # Creates a new JobManager object
- def initialize
- @jobs = []
- @current_job = nil
- end
-
- # The active irb session
- attr_accessor :current_job
-
- # The total number of irb sessions, used to set +irb_name+ of the current
- # Context.
- def n_jobs
- @jobs.size
- end
-
- # Returns the thread for the given +key+ object, see #search for more
- # information.
- def thread(key)
- th, = search(key)
- th
- end
-
- # Returns the irb session for the given +key+ object, see #search for more
- # information.
- def irb(key)
- _, irb = search(key)
- irb
- end
-
- # Returns the top level thread.
- def main_thread
- @jobs[0][0]
- end
-
- # Returns the top level irb session.
- def main_irb
- @jobs[0][1]
- end
-
- # Add the given +irb+ session to the jobs Array.
- def insert(irb)
- @jobs.push [Thread.current, irb]
- end
-
- # Changes the current active irb session to the given +key+ in the jobs
- # Array.
- #
- # Raises an IrbAlreadyDead exception if the given +key+ is no longer alive.
- #
- # If the given irb session is already active, an IrbSwitchedToCurrentThread
- # exception is raised.
- def switch(key)
- th, irb = search(key)
- fail IrbAlreadyDead unless th.alive?
- fail IrbSwitchedToCurrentThread if th == Thread.current
- @current_job = irb
- th.run
- Thread.stop
- @current_job = irb(Thread.current)
- end
-
- # Terminates the irb sessions specified by the given +keys+.
- #
- # Raises an IrbAlreadyDead exception if one of the given +keys+ is already
- # terminated.
- #
- # See Thread#exit for more information.
- def kill(*keys)
- for key in keys
- th, _ = search(key)
- fail IrbAlreadyDead unless th.alive?
- th.exit
- end
- end
-
- # Returns the associated job for the given +key+.
- #
- # If given an Integer, it will return the +key+ index for the jobs Array.
- #
- # When an instance of Irb is given, it will return the irb session
- # associated with +key+.
- #
- # If given an instance of Thread, it will return the associated thread
- # +key+ using Object#=== on the jobs Array.
- #
- # Otherwise returns the irb session with the same top-level binding as the
- # given +key+.
- #
- # Raises a NoSuchJob exception if no job can be found with the given +key+.
- def search(key)
- job = case key
- when Integer
- @jobs[key]
- when Irb
- @jobs.find{|k, v| v.equal?(key)}
- when Thread
- @jobs.assoc(key)
- else
- @jobs.find{|k, v| v.context.main.equal?(key)}
- end
- fail NoSuchJob, key if job.nil?
- job
- end
-
- # Deletes the job at the given +key+.
- def delete(key)
- case key
- when Integer
- fail NoSuchJob, key unless @jobs[key]
- @jobs[key] = nil
- else
- catch(:EXISTS) do
- @jobs.each_index do
- |i|
- if @jobs[i] and (@jobs[i][0] == key ||
- @jobs[i][1] == key ||
- @jobs[i][1].context.main.equal?(key))
- @jobs[i] = nil
- throw :EXISTS
- end
- end
- fail NoSuchJob, key
- end
- end
- until assoc = @jobs.pop; end unless @jobs.empty?
- @jobs.push assoc
- end
-
- # Outputs a list of jobs, see the irb command +irb_jobs+, or +jobs+.
- def inspect
- ary = []
- @jobs.each_index do
- |i|
- th, irb = @jobs[i]
- next if th.nil?
-
- if th.alive?
- if th.stop?
- t_status = "stop"
- else
- t_status = "running"
- end
- else
- t_status = "exited"
- end
- ary.push format("#%d->%s on %s (%s: %s)",
- i,
- irb.context.irb_name,
- irb.context.main,
- th,
- t_status)
- end
- ary.join("\n")
- end
- end
-
- @JobManager = JobManager.new
-
- # The current JobManager in the session
- def IRB.JobManager # :nodoc:
- @JobManager
- end
-
- # The current Context in this session
- def IRB.CurrentContext # :nodoc:
- IRB.JobManager.irb(Thread.current).context
- end
-
- # Creates a new IRB session, see Irb.new.
- #
- # The optional +file+ argument is given to Context.new, along with the
- # workspace created with the remaining arguments, see WorkSpace.new
- def IRB.irb(file = nil, *main) # :nodoc:
- workspace = WorkSpace.new(*main)
- parent_thread = Thread.current
- Thread.start do
- begin
- irb = Irb.new(workspace, file)
- rescue
- print "Subirb can't start with context(self): ", workspace.main.inspect, "\n"
- print "return to main irb\n"
- Thread.pass
- Thread.main.wakeup
- Thread.exit
- end
- @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC]
- @JobManager.insert(irb)
- @JobManager.current_job = irb
- begin
- system_exit = false
- catch(:IRB_EXIT) do
- irb.eval_input
- end
- rescue SystemExit
- system_exit = true
- raise
- #fail
- ensure
- unless system_exit
- @JobManager.delete(irb)
- if @JobManager.current_job == irb
- if parent_thread.alive?
- @JobManager.current_job = @JobManager.irb(parent_thread)
- parent_thread.run
- else
- @JobManager.current_job = @JobManager.main_irb
- @JobManager.main_thread.run
- end
- end
- end
- end
- end
- Thread.stop
- @JobManager.current_job = @JobManager.irb(Thread.current)
- end
-
- @CONF[:SINGLE_IRB_MODE] = false
- @JobManager.insert(@CONF[:MAIN_CONTEXT].irb)
- @JobManager.current_job = @CONF[:MAIN_CONTEXT].irb
-
- class Irb
- def signal_handle
- unless @context.ignore_sigint?
- print "\nabort!!\n" if @context.verbose?
- exit
- end
-
- case @signal_status
- when :IN_INPUT
- print "^C\n"
- IRB.JobManager.thread(self).raise RubyLex::TerminateLineInput
- when :IN_EVAL
- IRB.irb_abort(self)
- when :IN_LOAD
- IRB.irb_abort(self, LoadAbort)
- when :IN_IRB
- # ignore
- else
- # ignore other cases as well
- end
- end
- end
-
- trap("SIGINT") do
- @JobManager.current_job.signal_handle
- Thread.stop
- end
-
-end
diff --git a/lib/irb/ext/tracer.rb b/lib/irb/ext/tracer.rb
deleted file mode 100644
index fd6daa88ae..0000000000
--- a/lib/irb/ext/tracer.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-#
-# irb/lib/tracer.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-# Loading the gem "tracer" will cause it to extend IRB commands with:
-# https://github.com/ruby/tracer/blob/v0.2.2/lib/tracer/irb.rb
-begin
- require "tracer"
-rescue LoadError
- $stderr.puts "Tracer extension of IRB is enabled but tracer gem wasn't found."
- return # This is about to disable loading below
-end
-
-module IRB
- class CallTracer < ::CallTracer
- IRB_DIR = File.expand_path('../..', __dir__)
-
- def skip?(tp)
- super || tp.path.match?(IRB_DIR) || tp.path.match?('<internal:prelude>')
- end
- end
- class WorkSpace
- alias __evaluate__ evaluate
- # Evaluate the context of this workspace and use the Tracer library to
- # output the exact lines of code are being executed in chronological order.
- #
- # See https://github.com/ruby/tracer for more information.
- def evaluate(statements, file = __FILE__, line = __LINE__)
- if IRB.conf[:USE_TRACER] == true
- CallTracer.new(colorize: Color.colorable?).start do
- __evaluate__(statements, file, line)
- end
- else
- __evaluate__(statements, file, line)
- end
- end
- end
-end
diff --git a/lib/irb/ext/use-loader.rb b/lib/irb/ext/use-loader.rb
deleted file mode 100644
index c8a3ea1fe8..0000000000
--- a/lib/irb/ext/use-loader.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-# frozen_string_literal: true
-#
-# use-loader.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-require_relative "../command/load"
-require_relative "loader"
-
-class Object
- alias __original__load__IRB_use_loader__ load
- alias __original__require__IRB_use_loader__ require
-end
-
-module IRB
- module ExtendCommandBundle
- remove_method :irb_load if method_defined?(:irb_load)
- # Loads the given file similarly to Kernel#load, see IrbLoader#irb_load
- def irb_load(*opts, &b)
- Command::Load.execute(irb_context, *opts, &b)
- end
- remove_method :irb_require if method_defined?(:irb_require)
- # Loads the given file similarly to Kernel#require
- def irb_require(*opts, &b)
- Command::Require.execute(irb_context, *opts, &b)
- end
- end
-
- class Context
-
- IRB.conf[:USE_LOADER] = false
-
- # Returns whether +irb+'s own file reader method is used by
- # +load+/+require+ or not.
- #
- # This mode is globally affected (irb-wide).
- def use_loader
- IRB.conf[:USE_LOADER]
- end
-
- alias use_loader? use_loader
-
- remove_method :use_loader= if method_defined?(:use_loader=)
- # Sets <code>IRB.conf[:USE_LOADER]</code>
- #
- # See #use_loader for more information.
- def use_loader=(opt)
-
- if IRB.conf[:USE_LOADER] != opt
- IRB.conf[:USE_LOADER] = opt
- if opt
- (class<<workspace.main;self;end).instance_eval {
- alias_method :load, :irb_load
- alias_method :require, :irb_require
- }
- else
- (class<<workspace.main;self;end).instance_eval {
- alias_method :load, :__original__load__IRB_use_loader__
- alias_method :require, :__original__require__IRB_use_loader__
- }
- end
- end
- print "Switch to load/require#{unless use_loader; ' non';end} trace mode.\n" if verbose?
- opt
- end
- end
-end
diff --git a/lib/irb/ext/workspaces.rb b/lib/irb/ext/workspaces.rb
deleted file mode 100644
index da09faa83e..0000000000
--- a/lib/irb/ext/workspaces.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-#
-# push-ws.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB # :nodoc:
- class Context
- # Creates a new workspace with the given object or binding, and appends it
- # onto the current #workspaces stack.
- #
- # See IRB::Context#change_workspace and IRB::WorkSpace.new for more
- # information.
- def push_workspace(*_main)
- if _main.empty?
- if @workspace_stack.size > 1
- # swap the top two workspaces
- previous_workspace, current_workspace = @workspace_stack.pop(2)
- @workspace_stack.push current_workspace, previous_workspace
- end
- else
- new_workspace = WorkSpace.new(workspace.binding, _main[0])
- @workspace_stack.push new_workspace
- new_workspace.load_helper_methods_to_main
- end
- end
-
- # Removes the last element from the current #workspaces stack and returns
- # it, or +nil+ if the current workspace stack is empty.
- #
- # Also, see #push_workspace.
- def pop_workspace
- @workspace_stack.pop if @workspace_stack.size > 1
- end
- end
-end
diff --git a/lib/irb/frame.rb b/lib/irb/frame.rb
deleted file mode 100644
index 4b697c8719..0000000000
--- a/lib/irb/frame.rb
+++ /dev/null
@@ -1,80 +0,0 @@
-# frozen_string_literal: true
-#
-# frame.rb -
-# by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd)
-#
-
-module IRB
- class Frame
- class FrameOverflow < StandardError
- def initialize
- super("frame overflow")
- end
- end
- class FrameUnderflow < StandardError
- def initialize
- super("frame underflow")
- end
- end
-
- # Default number of stack frames
- INIT_STACK_TIMES = 3
- # Default number of frames offset
- CALL_STACK_OFFSET = 3
-
- # Creates a new stack frame
- def initialize
- @frames = [TOPLEVEL_BINDING] * INIT_STACK_TIMES
- end
-
- # Used by Kernel#set_trace_func to register each event in the call stack
- def trace_func(event, file, line, id, binding)
- case event
- when 'call', 'class'
- @frames.push binding
- when 'return', 'end'
- @frames.pop
- end
- end
-
- # Returns the +n+ number of frames on the call stack from the last frame
- # initialized.
- #
- # Raises FrameUnderflow if there are no frames in the given stack range.
- def top(n = 0)
- bind = @frames[-(n + CALL_STACK_OFFSET)]
- fail FrameUnderflow unless bind
- bind
- end
-
- # Returns the +n+ number of frames on the call stack from the first frame
- # initialized.
- #
- # Raises FrameOverflow if there are no frames in the given stack range.
- def bottom(n = 0)
- bind = @frames[n]
- fail FrameOverflow unless bind
- bind
- end
-
- # Convenience method for Frame#bottom
- def Frame.bottom(n = 0)
- @backtrace.bottom(n)
- end
-
- # Convenience method for Frame#top
- def Frame.top(n = 0)
- @backtrace.top(n)
- end
-
- # Returns the binding context of the caller from the last frame initialized
- def Frame.sender
- eval "self", @backtrace.top
- end
-
- @backtrace = Frame.new
- set_trace_func proc{|event, file, line, id, binding, klass|
- @backtrace.trace_func(event, file, line, id, binding)
- }
- end
-end
diff --git a/lib/irb/help.rb b/lib/irb/help.rb
deleted file mode 100644
index a24bc10a15..0000000000
--- a/lib/irb/help.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-#
-# irb/help.rb - print usage module
-# by Keiju ISHITSUKA(keiju@ishitsuka.com)
-#
-
-module IRB
- # Outputs the irb help message, see IRB@Command-Line+Options.
- def IRB.print_usage # :nodoc:
- lc = IRB.conf[:LC_MESSAGES]
- path = lc.find("irb/help-message")
- space_line = false
- File.open(path){|f|
- f.each_line do |l|
- if /^\s*$/ =~ l
- lc.puts l unless space_line
- space_line = true
- next
- end
- space_line = false
-
- l.sub!(/#.*$/, "")
- next if /^\s*$/ =~ l
- lc.puts l
- end
- }
- end
-end
diff --git a/lib/irb/helper_method.rb b/lib/irb/helper_method.rb
deleted file mode 100644
index f1f6fff915..0000000000
--- a/lib/irb/helper_method.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-require_relative "helper_method/base"
-
-module IRB
- module HelperMethod
- @helper_methods = {}
-
- class << self
- attr_reader :helper_methods
-
- def register(name, helper_class)
- @helper_methods[name] = helper_class
-
- if defined?(HelpersContainer)
- HelpersContainer.install_helper_methods
- end
- end
-
- def all_helper_methods_info
- @helper_methods.map do |name, helper_class|
- { display_name: name, description: helper_class.description }
- end
- end
- end
-
- # Default helper_methods
- require_relative "helper_method/conf"
- register(:conf, HelperMethod::Conf)
- end
-end
diff --git a/lib/irb/helper_method/base.rb b/lib/irb/helper_method/base.rb
deleted file mode 100644
index a68001ed28..0000000000
--- a/lib/irb/helper_method/base.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require "singleton"
-
-module IRB
- module HelperMethod
- class Base
- include Singleton
-
- class << self
- def description(description = nil)
- @description = description if description
- @description
- end
- end
- end
- end
-end
diff --git a/lib/irb/helper_method/conf.rb b/lib/irb/helper_method/conf.rb
deleted file mode 100644
index 718ed279c0..0000000000
--- a/lib/irb/helper_method/conf.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-module IRB
- module HelperMethod
- class Conf < Base
- description "Returns the current IRB context."
-
- def execute
- IRB.CurrentContext
- end
- end
- end
-end
diff --git a/lib/irb/history.rb b/lib/irb/history.rb
deleted file mode 100644
index 685354b2d8..0000000000
--- a/lib/irb/history.rb
+++ /dev/null
@@ -1,87 +0,0 @@
-require "pathname"
-
-module IRB
- module HistorySavingAbility # :nodoc:
- def support_history_saving?
- true
- end
-
- def reset_history_counter
- @loaded_history_lines = self.class::HISTORY.size
- end
-
- def load_history
- history = self.class::HISTORY
-
- if history_file = IRB.conf[:HISTORY_FILE]
- history_file = File.expand_path(history_file)
- end
- history_file = IRB.rc_file("_history") unless history_file
- if history_file && File.exist?(history_file)
- File.open(history_file, "r:#{IRB.conf[:LC_MESSAGES].encoding}") do |f|
- f.each { |l|
- l = l.chomp
- if self.class == RelineInputMethod and history.last&.end_with?("\\")
- history.last.delete_suffix!("\\")
- history.last << "\n" << l
- else
- history << l
- end
- }
- end
- @loaded_history_lines = history.size
- @loaded_history_mtime = File.mtime(history_file)
- end
- end
-
- def save_history
- history = self.class::HISTORY.to_a
-
- if num = IRB.conf[:SAVE_HISTORY] and (num = num.to_i) != 0
- if history_file = IRB.conf[:HISTORY_FILE]
- history_file = File.expand_path(history_file)
- end
- history_file = IRB.rc_file("_history") unless history_file
-
- # When HOME and XDG_CONFIG_HOME are not available, history_file might be nil
- return unless history_file
-
- # Change the permission of a file that already exists[BUG #7694]
- begin
- if File.stat(history_file).mode & 066 != 0
- File.chmod(0600, history_file)
- end
- rescue Errno::ENOENT
- rescue Errno::EPERM
- return
- rescue
- raise
- end
-
- if File.exist?(history_file) &&
- File.mtime(history_file) != @loaded_history_mtime
- history = history[@loaded_history_lines..-1] if @loaded_history_lines
- append_history = true
- end
-
- pathname = Pathname.new(history_file)
- unless Dir.exist?(pathname.dirname)
- warn "Warning: The directory to save IRB's history file does not exist. Please double check `IRB.conf[:HISTORY_FILE]`'s value."
- return
- end
-
- File.open(history_file, (append_history ? 'a' : 'w'), 0o600, encoding: IRB.conf[:LC_MESSAGES]&.encoding) do |f|
- hist = history.map{ |l| l.scrub.split("\n").join("\\\n") }
- unless append_history
- begin
- hist = hist.last(num) if hist.size > num and num > 0
- rescue RangeError # bignum too big to convert into `long'
- # Do nothing because the bignum should be treated as infinity
- end
- end
- f.puts(hist)
- end
- end
- end
- end
-end
diff --git a/lib/irb/init.rb b/lib/irb/init.rb
deleted file mode 100644
index 7dc08912ef..0000000000
--- a/lib/irb/init.rb
+++ /dev/null
@@ -1,538 +0,0 @@
-# frozen_string_literal: true
-#
-# irb/init.rb - irb initialize module
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB # :nodoc:
- @CONF = {}
- @INITIALIZED = false
- # Displays current configuration.
- #
- # Modifying the configuration is achieved by sending a message to IRB.conf.
- #
- # See IRB@Configuration for more information.
- def IRB.conf
- @CONF
- end
-
- def @CONF.inspect
- array = []
- for k, v in sort{|a1, a2| a1[0].id2name <=> a2[0].id2name}
- case k
- when :MAIN_CONTEXT, :__TMP__EHV__
- array.push format("CONF[:%s]=...myself...", k.id2name)
- when :PROMPT
- s = v.collect{
- |kk, vv|
- ss = vv.collect{|kkk, vvv| ":#{kkk.id2name}=>#{vvv.inspect}"}
- format(":%s=>{%s}", kk.id2name, ss.join(", "))
- }
- array.push format("CONF[:%s]={%s}", k.id2name, s.join(", "))
- else
- array.push format("CONF[:%s]=%s", k.id2name, v.inspect)
- end
- end
- array.join("\n")
- end
-
- # Returns the current version of IRB, including release version and last
- # updated date.
- def IRB.version
- format("irb %s (%s)", @RELEASE_VERSION, @LAST_UPDATE_DATE)
- end
-
- def IRB.initialized?
- !!@INITIALIZED
- end
-
- # initialize config
- def IRB.setup(ap_path, argv: ::ARGV)
- IRB.init_config(ap_path)
- IRB.init_error
- IRB.parse_opts(argv: argv)
- IRB.run_config
- IRB.validate_config
- IRB.load_modules
-
- unless @CONF[:PROMPT][@CONF[:PROMPT_MODE]]
- fail UndefinedPromptMode, @CONF[:PROMPT_MODE]
- end
- @INITIALIZED = true
- end
-
- # @CONF default setting
- def IRB.init_config(ap_path)
- # default configurations
- unless ap_path and @CONF[:AP_NAME]
- ap_path = File.join(File.dirname(File.dirname(__FILE__)), "irb.rb")
- end
- @CONF[:VERSION] = version
- @CONF[:AP_NAME] = File::basename(ap_path, ".rb")
-
- @CONF[:IRB_NAME] = "irb"
- @CONF[:IRB_LIB_PATH] = File.dirname(__FILE__)
-
- @CONF[:RC] = true
- @CONF[:LOAD_MODULES] = []
- @CONF[:IRB_RC] = nil
-
- @CONF[:USE_SINGLELINE] = false unless defined?(ReadlineInputMethod)
- @CONF[:USE_COLORIZE] = (nc = ENV['NO_COLOR']).nil? || nc.empty?
- @CONF[:USE_AUTOCOMPLETE] = ENV.fetch("IRB_USE_AUTOCOMPLETE", "true") != "false"
- @CONF[:COMPLETOR] = ENV.fetch("IRB_COMPLETOR", "regexp").to_sym
- @CONF[:INSPECT_MODE] = true
- @CONF[:USE_TRACER] = false
- @CONF[:USE_LOADER] = false
- @CONF[:IGNORE_SIGINT] = true
- @CONF[:IGNORE_EOF] = false
- @CONF[:USE_PAGER] = true
- @CONF[:EXTRA_DOC_DIRS] = []
- @CONF[:ECHO] = nil
- @CONF[:ECHO_ON_ASSIGNMENT] = nil
- @CONF[:VERBOSE] = nil
-
- @CONF[:EVAL_HISTORY] = nil
- @CONF[:SAVE_HISTORY] = 1000
-
- @CONF[:BACK_TRACE_LIMIT] = 16
-
- @CONF[:PROMPT] = {
- :NULL => {
- :PROMPT_I => nil,
- :PROMPT_S => nil,
- :PROMPT_C => nil,
- :RETURN => "%s\n"
- },
- :DEFAULT => {
- :PROMPT_I => "%N(%m):%03n> ",
- :PROMPT_S => "%N(%m):%03n%l ",
- :PROMPT_C => "%N(%m):%03n* ",
- :RETURN => "=> %s\n"
- },
- :CLASSIC => {
- :PROMPT_I => "%N(%m):%03n:%i> ",
- :PROMPT_S => "%N(%m):%03n:%i%l ",
- :PROMPT_C => "%N(%m):%03n:%i* ",
- :RETURN => "%s\n"
- },
- :SIMPLE => {
- :PROMPT_I => ">> ",
- :PROMPT_S => "%l> ",
- :PROMPT_C => "?> ",
- :RETURN => "=> %s\n"
- },
- :INF_RUBY => {
- :PROMPT_I => "%N(%m):%03n> ",
- :PROMPT_S => nil,
- :PROMPT_C => nil,
- :RETURN => "%s\n",
- :AUTO_INDENT => true
- },
- :XMP => {
- :PROMPT_I => nil,
- :PROMPT_S => nil,
- :PROMPT_C => nil,
- :RETURN => " ==>%s\n"
- }
- }
-
- @CONF[:PROMPT_MODE] = (STDIN.tty? ? :DEFAULT : :NULL)
- @CONF[:AUTO_INDENT] = true
-
- @CONF[:CONTEXT_MODE] = 4 # use a copy of TOPLEVEL_BINDING
- @CONF[:SINGLE_IRB] = false
-
- @CONF[:MEASURE] = false
- @CONF[:MEASURE_PROC] = {}
- @CONF[:MEASURE_PROC][:TIME] = proc { |context, code, line_no, &block|
- time = Time.now
- result = block.()
- now = Time.now
- puts 'processing time: %fs' % (now - time) if IRB.conf[:MEASURE]
- result
- }
- # arg can be either a symbol for the mode (:cpu, :wall, ..) or a hash for
- # a more complete configuration.
- # See https://github.com/tmm1/stackprof#all-options.
- @CONF[:MEASURE_PROC][:STACKPROF] = proc { |context, code, line_no, arg, &block|
- return block.() unless IRB.conf[:MEASURE]
- success = false
- begin
- require 'stackprof'
- success = true
- rescue LoadError
- puts 'Please run "gem install stackprof" before measuring by StackProf.'
- end
- if success
- result = nil
- arg = { mode: arg || :cpu } unless arg.is_a?(Hash)
- stackprof_result = StackProf.run(**arg) do
- result = block.()
- end
- case stackprof_result
- when File
- puts "StackProf report saved to #{stackprof_result.path}"
- when Hash
- StackProf::Report.new(stackprof_result).print_text
- else
- puts "Stackprof ran with #{arg.inspect}"
- end
- result
- else
- block.()
- end
- }
- @CONF[:MEASURE_CALLBACKS] = []
-
- @CONF[:LC_MESSAGES] = Locale.new
-
- @CONF[:AT_EXIT] = []
-
- @CONF[:COMMAND_ALIASES] = {
- # Symbol aliases
- :'$' => :show_source,
- :'@' => :whereami,
- }
- 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
- IRB.conf[:MEASURE] = true
- 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
- IRB.conf[:MEASURE] = nil if IRB.conf[:MEASURE_CALLBACKS].empty?
- end
-
- def IRB.init_error
- @CONF[:LC_MESSAGES].load("irb/error.rb")
- end
-
- # option analyzing
- def IRB.parse_opts(argv: ::ARGV)
- load_path = []
- while opt = argv.shift
- case opt
- when "-f"
- @CONF[:RC] = false
- when "-d"
- $DEBUG = true
- $VERBOSE = true
- when "-w"
- Warning[:deprecated] = $VERBOSE = true
- when /^-W(.+)?/
- opt = $1 || argv.shift
- case opt
- when "0"
- $VERBOSE = nil
- when "1"
- $VERBOSE = false
- else
- Warning[:deprecated] = $VERBOSE = true
- end
- when /^-r(.+)?/
- opt = $1 || argv.shift
- @CONF[:LOAD_MODULES].push opt if opt
- when /^-I(.+)?/
- opt = $1 || argv.shift
- load_path.concat(opt.split(File::PATH_SEPARATOR)) if opt
- when '-U'
- set_encoding("UTF-8", "UTF-8")
- when /^-E(.+)?/, /^--encoding(?:=(.+))?/
- opt = $1 || argv.shift
- set_encoding(*opt.split(':', 2))
- when "--inspect"
- if /^-/ !~ argv.first
- @CONF[:INSPECT_MODE] = argv.shift
- else
- @CONF[:INSPECT_MODE] = true
- end
- when "--noinspect"
- @CONF[:INSPECT_MODE] = false
- when "--no-pager"
- @CONF[:USE_PAGER] = false
- when "--singleline", "--readline", "--legacy"
- @CONF[:USE_SINGLELINE] = true
- when "--nosingleline", "--noreadline"
- @CONF[:USE_SINGLELINE] = false
- when "--multiline", "--reidline"
- if opt == "--reidline"
- warn <<~MSG.strip
- --reidline is deprecated, please use --multiline instead.
- MSG
- end
-
- @CONF[:USE_MULTILINE] = true
- when "--nomultiline", "--noreidline"
- if opt == "--noreidline"
- warn <<~MSG.strip
- --noreidline is deprecated, please use --nomultiline instead.
- MSG
- end
-
- @CONF[:USE_MULTILINE] = false
- when /^--extra-doc-dir(?:=(.+))?/
- opt = $1 || argv.shift
- @CONF[:EXTRA_DOC_DIRS] << opt
- when "--echo"
- @CONF[:ECHO] = true
- when "--noecho"
- @CONF[:ECHO] = false
- when "--echo-on-assignment"
- @CONF[:ECHO_ON_ASSIGNMENT] = true
- when "--noecho-on-assignment"
- @CONF[:ECHO_ON_ASSIGNMENT] = false
- when "--truncate-echo-on-assignment"
- @CONF[:ECHO_ON_ASSIGNMENT] = :truncate
- when "--verbose"
- @CONF[:VERBOSE] = true
- when "--noverbose"
- @CONF[:VERBOSE] = false
- when "--colorize"
- @CONF[:USE_COLORIZE] = true
- when "--nocolorize"
- @CONF[:USE_COLORIZE] = false
- when "--autocomplete"
- @CONF[:USE_AUTOCOMPLETE] = true
- when "--noautocomplete"
- @CONF[:USE_AUTOCOMPLETE] = false
- when "--regexp-completor"
- @CONF[:COMPLETOR] = :regexp
- when "--type-completor"
- @CONF[:COMPLETOR] = :type
- when /^--prompt-mode(?:=(.+))?/, /^--prompt(?:=(.+))?/
- opt = $1 || argv.shift
- prompt_mode = opt.upcase.tr("-", "_").intern
- @CONF[:PROMPT_MODE] = prompt_mode
- when "--noprompt"
- @CONF[:PROMPT_MODE] = :NULL
- when "--script"
- noscript = false
- when "--noscript"
- noscript = true
- when "--inf-ruby-mode"
- @CONF[:PROMPT_MODE] = :INF_RUBY
- when "--sample-book-mode", "--simple-prompt"
- @CONF[:PROMPT_MODE] = :SIMPLE
- when "--tracer"
- @CONF[:USE_TRACER] = true
- when /^--back-trace-limit(?:=(.+))?/
- @CONF[:BACK_TRACE_LIMIT] = ($1 || argv.shift).to_i
- when /^--context-mode(?:=(.+))?/
- @CONF[:CONTEXT_MODE] = ($1 || argv.shift).to_i
- when "--single-irb"
- @CONF[:SINGLE_IRB] = true
- when "-v", "--version"
- print IRB.version, "\n"
- exit 0
- when "-h", "--help"
- require_relative "help"
- IRB.print_usage
- exit 0
- when "--"
- if !noscript && (opt = argv.shift)
- @CONF[:SCRIPT] = opt
- $0 = opt
- end
- break
- when /^-./
- fail UnrecognizedSwitch, opt
- else
- if noscript
- argv.unshift(opt)
- else
- @CONF[:SCRIPT] = opt
- $0 = opt
- end
- break
- end
- end
-
- load_path.collect! do |path|
- /\A\.\// =~ path ? path : File.expand_path(path)
- end
- $LOAD_PATH.unshift(*load_path)
- end
-
- # Run the config file
- def IRB.run_config
- if @CONF[:RC]
- irbrc_files.each do |rc|
- load rc
- rescue StandardError, ScriptError => e
- warn "Error loading RC file '#{rc}':\n#{e.full_message(highlight: false)}"
- end
- end
- end
-
- IRBRC_EXT = "rc"
-
- def IRB.rc_file(ext)
- prepare_irbrc_name_generators
-
- # When irbrc exist in default location
- if (rcgen = @existing_rc_name_generators.first)
- return rcgen.call(ext)
- end
-
- # When irbrc does not exist in default location
- rc_file_generators do |rcgen|
- return rcgen.call(ext)
- end
-
- # When HOME and XDG_CONFIG_HOME are not available
- nil
- end
-
- def IRB.irbrc_files
- prepare_irbrc_name_generators
- @irbrc_files
- end
-
- def IRB.validate_config
- conf[:IRB_NAME] = conf[:IRB_NAME].to_s
-
- irb_rc = conf[:IRB_RC]
- unless irb_rc.nil? || irb_rc.respond_to?(:call)
- raise_validation_error "IRB.conf[:IRB_RC] should be a callable object. Got #{irb_rc.inspect}."
- end
-
- back_trace_limit = conf[:BACK_TRACE_LIMIT]
- unless back_trace_limit.is_a?(Integer)
- raise_validation_error "IRB.conf[:BACK_TRACE_LIMIT] should be an integer. Got #{back_trace_limit.inspect}."
- end
-
- prompt = conf[:PROMPT]
- unless prompt.is_a?(Hash)
- msg = "IRB.conf[:PROMPT] should be a Hash. Got #{prompt.inspect}."
-
- if prompt.is_a?(Symbol)
- msg += " Did you mean to set `IRB.conf[:PROMPT_MODE]`?"
- end
-
- raise_validation_error msg
- end
-
- eval_history = conf[:EVAL_HISTORY]
- unless eval_history.nil? || eval_history.is_a?(Integer)
- raise_validation_error "IRB.conf[:EVAL_HISTORY] should be an integer. Got #{eval_history.inspect}."
- end
- end
-
- def IRB.raise_validation_error(msg)
- raise TypeError, msg, @irbrc_files
- end
-
- # loading modules
- def IRB.load_modules
- for m in @CONF[:LOAD_MODULES]
- begin
- require m
- rescue LoadError => err
- warn "#{err.class}: #{err}", uplevel: 0
- end
- end
- end
-
- class << IRB
- private
-
- def prepare_irbrc_name_generators
- return if @existing_rc_name_generators
-
- @existing_rc_name_generators = []
- @irbrc_files = []
- rc_file_generators do |rcgen|
- irbrc = rcgen.call(IRBRC_EXT)
- if File.exist?(irbrc)
- @irbrc_files << irbrc
- @existing_rc_name_generators << rcgen
- end
- end
- generate_current_dir_irbrc_files.each do |irbrc|
- @irbrc_files << irbrc if File.exist?(irbrc)
- end
- @irbrc_files.uniq!
- end
-
- # enumerate possible rc-file base name generators
- def rc_file_generators
- if irbrc = ENV["IRBRC"]
- yield proc{|rc| rc == "rc" ? irbrc : irbrc+rc}
- end
- if xdg_config_home = ENV["XDG_CONFIG_HOME"]
- irb_home = File.join(xdg_config_home, "irb")
- if File.directory?(irb_home)
- yield proc{|rc| irb_home + "/irb#{rc}"}
- end
- end
- if home = ENV["HOME"]
- yield proc{|rc| home+"/.irb#{rc}"}
- if xdg_config_home.nil? || xdg_config_home.empty?
- yield proc{|rc| home+"/.config/irb/irb#{rc}"}
- end
- end
- end
-
- # possible irbrc files in current directory
- def generate_current_dir_irbrc_files
- current_dir = Dir.pwd
- %w[.irbrc irbrc _irbrc $irbrc].map { |file| "#{current_dir}/#{file}" }
- end
-
- def set_encoding(extern, intern = nil, override: true)
- verbose, $VERBOSE = $VERBOSE, nil
- Encoding.default_external = extern unless extern.nil? || extern.empty?
- Encoding.default_internal = intern unless intern.nil? || intern.empty?
- [$stdin, $stdout, $stderr].each do |io|
- io.set_encoding(extern, intern)
- end
- if override
- @CONF[:LC_MESSAGES].instance_variable_set(:@override_encoding, extern)
- else
- @CONF[:LC_MESSAGES].instance_variable_set(:@encoding, extern)
- end
- ensure
- $VERBOSE = verbose
- end
- end
-end
diff --git a/lib/irb/input-method.rb b/lib/irb/input-method.rb
deleted file mode 100644
index 684527edc4..0000000000
--- a/lib/irb/input-method.rb
+++ /dev/null
@@ -1,513 +0,0 @@
-# frozen_string_literal: true
-#
-# irb/input-method.rb - input methods used irb
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-require_relative 'completion'
-require_relative "history"
-require 'io/console'
-require 'reline'
-
-module IRB
- class InputMethod
- BASIC_WORD_BREAK_CHARACTERS = " \t\n`><=;|&{("
-
- # The irb prompt associated with this input method
- attr_accessor :prompt
-
- # Reads the next line from this input method.
- #
- # See IO#gets for more information.
- def gets
- fail NotImplementedError
- end
- public :gets
-
- def winsize
- if instance_variable_defined?(:@stdout) && @stdout.tty?
- @stdout.winsize
- else
- [24, 80]
- end
- end
-
- # Whether this input method is still readable when there is no more data to
- # read.
- #
- # See IO#eof for more information.
- def readable_after_eof?
- false
- end
-
- def support_history_saving?
- false
- end
-
- def prompting?
- false
- end
-
- # For debug message
- def inspect
- 'Abstract InputMethod'
- end
- end
-
- class StdioInputMethod < InputMethod
- # Creates a new input method object
- def initialize
- @line_no = 0
- @line = []
- @stdin = IO.open(STDIN.to_i, :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-")
- @stdout = IO.open(STDOUT.to_i, 'w', :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-")
- end
-
- # Reads the next line from this input method.
- #
- # See IO#gets for more information.
- def gets
- puts if @stdout.tty? # workaround for debug compatibility test
- print @prompt
- line = @stdin.gets
- @line[@line_no += 1] = line
- end
-
- # Whether the end of this input method has been reached, returns +true+ if
- # there is no more data to read.
- #
- # See IO#eof? for more information.
- def eof?
- if @stdin.wait_readable(0.00001)
- c = @stdin.getc
- result = c.nil? ? true : false
- @stdin.ungetc(c) unless c.nil?
- result
- else # buffer is empty
- false
- end
- end
-
- # Whether this input method is still readable when there is no more data to
- # read.
- #
- # See IO#eof for more information.
- def readable_after_eof?
- true
- end
-
- def prompting?
- STDIN.tty?
- end
-
- # Returns the current line number for #io.
- #
- # #line counts the number of times #gets is called.
- #
- # See IO#lineno for more information.
- def line(line_no)
- @line[line_no]
- end
-
- # The external encoding for standard input.
- def encoding
- @stdin.external_encoding
- end
-
- # For debug message
- def inspect
- 'StdioInputMethod'
- end
- end
-
- # Use a File for IO with irb, see InputMethod
- class FileInputMethod < InputMethod
- class << self
- def open(file, &block)
- begin
- io = new(file)
- block.call(io)
- ensure
- io&.close
- end
- end
- end
-
- # Creates a new input method object
- def initialize(file)
- @io = file.is_a?(IO) ? file : File.open(file)
- @external_encoding = @io.external_encoding
- end
-
- # Whether the end of this input method has been reached, returns +true+ if
- # there is no more data to read.
- #
- # See IO#eof? for more information.
- def eof?
- @io.closed? || @io.eof?
- end
-
- # Reads the next line from this input method.
- #
- # See IO#gets for more information.
- def gets
- print @prompt
- @io.gets
- end
-
- # The external encoding for standard input.
- def encoding
- @external_encoding
- end
-
- # For debug message
- def inspect
- 'FileInputMethod'
- end
-
- def close
- @io.close
- end
- end
-
- class ReadlineInputMethod < StdioInputMethod
- def self.initialize_readline
- require "readline"
- rescue LoadError
- else
- include ::Readline
- end
-
- include HistorySavingAbility
-
- # Creates a new input method object using Readline
- def initialize
- self.class.initialize_readline
- if Readline.respond_to?(:encoding_system_needs)
- IRB.__send__(:set_encoding, Readline.encoding_system_needs.name, override: false)
- end
-
- super
-
- @eof = false
- @completor = RegexpCompletor.new
-
- if Readline.respond_to?("basic_word_break_characters=")
- Readline.basic_word_break_characters = BASIC_WORD_BREAK_CHARACTERS
- end
- Readline.completion_append_character = nil
- Readline.completion_proc = ->(target) {
- bind = IRB.conf[:MAIN_CONTEXT].workspace.binding
- @completor.completion_candidates('', target, '', bind: bind)
- }
- end
-
- def completion_info
- 'RegexpCompletor'
- end
-
- # Reads the next line from this input method.
- #
- # See IO#gets for more information.
- def gets
- Readline.input = @stdin
- Readline.output = @stdout
- if l = readline(@prompt, false)
- HISTORY.push(l) if !l.empty?
- @line[@line_no += 1] = l + "\n"
- else
- @eof = true
- l
- end
- end
-
- # Whether the end of this input method has been reached, returns +true+
- # if there is no more data to read.
- #
- # See IO#eof? for more information.
- def eof?
- @eof
- end
-
- def prompting?
- true
- end
-
- # For debug message
- def inspect
- readline_impl = (defined?(Reline) && Readline == Reline) ? 'Reline' : 'ext/readline'
- str = "ReadlineInputMethod with #{readline_impl} #{Readline::VERSION}"
- inputrc_path = File.expand_path(ENV['INPUTRC'] || '~/.inputrc')
- str += " and #{inputrc_path}" if File.exist?(inputrc_path)
- str
- end
- end
-
- class RelineInputMethod < StdioInputMethod
- HISTORY = Reline::HISTORY
- include HistorySavingAbility
- # Creates a new input method object using Reline
- def initialize(completor)
- IRB.__send__(:set_encoding, Reline.encoding_system_needs.name, override: false)
-
- super()
-
- @eof = false
- @completor = completor
-
- Reline.basic_word_break_characters = BASIC_WORD_BREAK_CHARACTERS
- Reline.completion_append_character = nil
- Reline.completer_quote_characters = ''
- Reline.completion_proc = ->(target, preposing, postposing) {
- bind = IRB.conf[:MAIN_CONTEXT].workspace.binding
- @completion_params = [preposing, target, postposing, bind]
- @completor.completion_candidates(preposing, target, postposing, bind: bind)
- }
- Reline.output_modifier_proc =
- if IRB.conf[:USE_COLORIZE]
- proc do |output, complete: |
- next unless IRB::Color.colorable?
- lvars = IRB.CurrentContext&.local_variables || []
- IRB::Color.colorize_code(output, complete: complete, local_variables: lvars)
- end
- else
- proc do |output|
- Reline::Unicode.escape_for_print(output)
- end
- end
- Reline.dig_perfect_match_proc = ->(matched) { display_document(matched) }
- Reline.autocompletion = IRB.conf[:USE_AUTOCOMPLETE]
-
- if IRB.conf[:USE_AUTOCOMPLETE]
- begin
- require 'rdoc'
- Reline.add_dialog_proc(:show_doc, show_doc_dialog_proc, Reline::DEFAULT_DIALOG_CONTEXT)
- rescue LoadError
- end
- end
- end
-
- def completion_info
- autocomplete_message = Reline.autocompletion ? 'Autocomplete' : 'Tab Complete'
- "#{autocomplete_message}, #{@completor.inspect}"
- end
-
- def check_termination(&block)
- @check_termination_proc = block
- end
-
- def dynamic_prompt(&block)
- @prompt_proc = block
- end
-
- def auto_indent(&block)
- @auto_indent_proc = block
- end
-
- def retrieve_doc_namespace(matched)
- preposing, _target, postposing, bind = @completion_params
- @completor.doc_namespace(preposing, matched, postposing, bind: bind)
- end
-
- def rdoc_ri_driver
- return @rdoc_ri_driver if defined?(@rdoc_ri_driver)
-
- begin
- require 'rdoc'
- rescue LoadError
- @rdoc_ri_driver = nil
- else
- options = {}
- options[:extra_doc_dirs] = IRB.conf[:EXTRA_DOC_DIRS] unless IRB.conf[:EXTRA_DOC_DIRS].empty?
- @rdoc_ri_driver = RDoc::RI::Driver.new(options)
- end
- end
-
- def show_doc_dialog_proc
- input_method = self # self is changed in the lambda below.
- ->() {
- 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 = input_method.retrieve_doc_namespace(result[pointer])
- # Use first one because document dialog does not support multiple namespaces.
- name = name.first if name.is_a?(Array)
-
- show_easter_egg = name&.match?(/\ARubyVM/) && !ENV['RUBY_YES_I_AM_NOT_A_NORMAL_USER']
-
- driver = input_method.rdoc_ri_driver
-
- if key.match?(dialog.name)
- if show_easter_egg
- IRB.__send__(:easter_egg)
- else
- begin
- driver.display_names([name])
- rescue RDoc::RI::Driver::NotFoundError
- end
- end
- end
-
- begin
- name = driver.expand_name(name)
- rescue RDoc::RI::Driver::NotFoundError
- return nil
- rescue
- return nil # unknown error
- end
- doc = nil
- used_for_class = false
- if not name =~ /#|\./
- found, klasses, includes, extends = driver.classes_and_includes_and_extends_for(name)
- if not found.empty?
- doc = driver.class_document(name, found, klasses, includes, extends)
- used_for_class = true
- end
- end
- unless used_for_class
- doc = RDoc::Markup::Document.new
- begin
- driver.add_method(doc, name)
- rescue RDoc::RI::Driver::NotFoundError
- doc = nil
- rescue
- return nil # unknown error
- end
- end
- return nil if doc.nil?
- width = 40
-
- right_x = cursor_pos_to_render.x + autocomplete_dialog.width
- if right_x + width > screen_width
- right_width = screen_width - (right_x + 1)
- left_x = autocomplete_dialog.column - width
- left_x = 0 if left_x < 0
- left_width = width > autocomplete_dialog.column ? autocomplete_dialog.column : width
- if right_width.positive? and left_width.positive?
- if right_width >= left_width
- width = right_width
- x = right_x
- else
- width = left_width
- x = left_x
- end
- elsif right_width.positive? and left_width <= 0
- width = right_width
- x = right_x
- elsif right_width <= 0 and left_width.positive?
- width = left_width
- x = left_x
- else # Both are negative width.
- return nil
- end
- else
- x = right_x
- end
- formatter = RDoc::Markup::ToAnsi.new
- formatter.width = width
- dialog.trap_key = alt_d
- mod_key = RUBY_PLATFORM.match?(/darwin/) ? "Option" : "Alt"
- if show_easter_egg
- type = STDOUT.external_encoding == Encoding::UTF_8 ? :unicode : :ascii
- contents = IRB.send(:easter_egg_logo, type).split("\n")
- message = "Press #{mod_key}+d to see more"
- contents[0][0, message.size] = message
- else
- message = "Press #{mod_key}+d to read the full document"
- contents = [message] + doc.accept(formatter).split("\n")
- end
- contents = contents.take(preferred_dialog_height)
-
- y = cursor_pos_to_render.y
- Reline::DialogRenderInfo.new(pos: Reline::CursorPos.new(x, y), contents: contents, width: width, bg_color: '49')
- }
- end
-
- def display_document(matched)
- driver = rdoc_ri_driver
- return unless driver
-
- if matched =~ /\A(?:::)?RubyVM/ and not ENV['RUBY_YES_I_AM_NOT_A_NORMAL_USER']
- IRB.__send__(:easter_egg)
- return
- end
-
- namespace = retrieve_doc_namespace(matched)
- return unless namespace
-
- if namespace.is_a?(Array)
- out = RDoc::Markup::Document.new
- namespace.each do |m|
- begin
- driver.add_method(out, m)
- rescue RDoc::RI::Driver::NotFoundError
- end
- end
- driver.display(out)
- else
- begin
- driver.display_names([namespace])
- rescue RDoc::RI::Driver::NotFoundError
- end
- end
- end
-
- # Reads the next line from this input method.
- #
- # See IO#gets for more information.
- def gets
- Reline.input = @stdin
- Reline.output = @stdout
- Reline.prompt_proc = @prompt_proc
- Reline.auto_indent_proc = @auto_indent_proc if @auto_indent_proc
- if l = Reline.readmultiline(@prompt, false, &@check_termination_proc)
- Reline::HISTORY.push(l) if !l.empty?
- @line[@line_no += 1] = l + "\n"
- else
- @eof = true
- l
- end
- end
-
- # Whether the end of this input method has been reached, returns +true+
- # if there is no more data to read.
- #
- # See IO#eof? for more information.
- def eof?
- @eof
- end
-
- def prompting?
- true
- end
-
- # For debug message
- def inspect
- config = Reline::Config.new
- str = "RelineInputMethod with Reline #{Reline::VERSION}"
- inputrc_path = File.expand_path(config.inputrc_path)
- str += " and #{inputrc_path}" if File.exist?(inputrc_path)
- str
- end
- end
-
- class ReidlineInputMethod < RelineInputMethod
- def initialize
- warn <<~MSG.strip
- IRB::ReidlineInputMethod is deprecated, please use IRB::RelineInputMethod instead.
- MSG
- super
- end
- end
-end
diff --git a/lib/irb/inspector.rb b/lib/irb/inspector.rb
deleted file mode 100644
index 667087ccba..0000000000
--- a/lib/irb/inspector.rb
+++ /dev/null
@@ -1,130 +0,0 @@
-# frozen_string_literal: true
-#
-# irb/inspector.rb - inspect methods
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB # :nodoc:
-
-
- # Convenience method to create a new Inspector, using the given +inspect+
- # proc, and optional +init+ proc and passes them to Inspector.new
- #
- # irb(main):001:0> ins = IRB::Inspector(proc{ |v| "omg! #{v}" })
- # irb(main):001:0> IRB.CurrentContext.inspect_mode = ins # => omg! #<IRB::Inspector:0x007f46f7ba7d28>
- # irb(main):001:0> "what?" #=> omg! what?
- #
- def IRB::Inspector(inspect, init = nil)
- Inspector.new(inspect, init)
- end
-
- # An irb inspector
- #
- # In order to create your own custom inspector there are two things you
- # should be aware of:
- #
- # Inspector uses #inspect_value, or +inspect_proc+, for output of return values.
- #
- # This also allows for an optional #init+, or +init_proc+, which is called
- # when the inspector is activated.
- #
- # Knowing this, you can create a rudimentary inspector as follows:
- #
- # irb(main):001:0> ins = IRB::Inspector.new(proc{ |v| "omg! #{v}" })
- # irb(main):001:0> IRB.CurrentContext.inspect_mode = ins # => omg! #<IRB::Inspector:0x007f46f7ba7d28>
- # irb(main):001:0> "what?" #=> omg! what?
- #
- class Inspector
- KERNEL_INSPECT = Object.instance_method(:inspect)
- # Default inspectors available to irb, this includes:
- #
- # +:pp+:: Using Kernel#pretty_inspect
- # +:yaml+:: Using YAML.dump
- # +:marshal+:: Using Marshal.dump
- INSPECTORS = {}
-
- # Determines the inspector to use where +inspector+ is one of the keys passed
- # during inspector definition.
- def self.keys_with_inspector(inspector)
- INSPECTORS.select{|k, v| v == inspector}.collect{|k, v| k}
- end
-
- # Example
- #
- # Inspector.def_inspector(key, init_p=nil){|v| v.inspect}
- # Inspector.def_inspector([key1,..], init_p=nil){|v| v.inspect}
- # Inspector.def_inspector(key, inspector)
- # Inspector.def_inspector([key1,...], inspector)
- def self.def_inspector(key, arg=nil, &block)
- if block_given?
- inspector = IRB::Inspector(block, arg)
- else
- inspector = arg
- end
-
- case key
- when Array
- for k in key
- def_inspector(k, inspector)
- end
- when Symbol
- INSPECTORS[key] = inspector
- INSPECTORS[key.to_s] = inspector
- when String
- INSPECTORS[key] = inspector
- INSPECTORS[key.intern] = inspector
- else
- INSPECTORS[key] = inspector
- end
- end
-
- # Creates a new inspector object, using the given +inspect_proc+ when
- # output return values in irb.
- def initialize(inspect_proc, init_proc = nil)
- @init = init_proc
- @inspect = inspect_proc
- end
-
- # Proc to call when the inspector is activated, good for requiring
- # dependent libraries.
- def init
- @init.call if @init
- end
-
- # Proc to call when the input is evaluated and output in irb.
- def inspect_value(v)
- @inspect.call(v)
- rescue => e
- puts "An error occurred when inspecting the object: #{e.inspect}"
-
- begin
- puts "Result of Kernel#inspect: #{KERNEL_INSPECT.bind_call(v)}"
- ''
- rescue => e
- puts "An error occurred when running Kernel#inspect: #{e.inspect}"
- puts e.backtrace.join("\n")
- ''
- end
- end
- end
-
- Inspector.def_inspector([false, :to_s, :raw]){|v| v.to_s}
- Inspector.def_inspector([:p, :inspect]){|v|
- Color.colorize_code(v.inspect, colorable: Color.colorable? && Color.inspect_colorable?(v))
- }
- Inspector.def_inspector([true, :pp, :pretty_inspect], proc{require_relative "color_printer"}){|v|
- IRB::ColorPrinter.pp(v, +'').chomp
- }
- Inspector.def_inspector([:yaml, :YAML], proc{require "yaml"}){|v|
- begin
- YAML.dump(v)
- rescue
- puts "(can't dump yaml. use inspect)"
- v.inspect
- end
- }
-
- Inspector.def_inspector([:marshal, :Marshal, :MARSHAL, Marshal]){|v|
- Marshal.dump(v)
- }
-end
diff --git a/lib/irb/irb.gemspec b/lib/irb/irb.gemspec
deleted file mode 100644
index b29002f593..0000000000
--- a/lib/irb/irb.gemspec
+++ /dev/null
@@ -1,46 +0,0 @@
-begin
- require_relative "lib/irb/version"
-rescue LoadError
- # for Ruby core repository
- require_relative "version"
-end
-
-Gem::Specification.new do |spec|
- spec.name = "irb"
- spec.version = IRB::VERSION
- spec.authors = ["aycabta", "Keiju ISHITSUKA"]
- spec.email = ["aycabta@gmail.com", "keiju@ruby-lang.org"]
-
- spec.summary = %q{Interactive Ruby command-line tool for REPL (Read Eval Print Loop).}
- spec.description = %q{Interactive Ruby command-line tool for REPL (Read Eval Print Loop).}
- spec.homepage = "https://github.com/ruby/irb"
- spec.licenses = ["Ruby", "BSD-2-Clause"]
-
- spec.metadata["homepage_uri"] = spec.homepage
- spec.metadata["source_code_uri"] = spec.homepage
- spec.metadata["documentation_uri"] = spec.homepage
- spec.metadata["changelog_uri"] = "#{spec.homepage}/releases"
-
- spec.files = [
- ".document",
- "Gemfile",
- "LICENSE.txt",
- "README.md",
- "Rakefile",
- "bin/console",
- "bin/setup",
- "doc/irb/irb-tools.rd.ja",
- "doc/irb/irb.rd.ja",
- "exe/irb",
- "irb.gemspec",
- "man/irb.1",
- ] + Dir.glob("lib/**/*")
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
- spec.require_paths = ["lib"]
-
- spec.required_ruby_version = Gem::Requirement.new(">= 2.7")
-
- spec.add_dependency "reline", ">= 0.4.2"
- spec.add_dependency "rdoc", ">= 4.0.0"
-end
diff --git a/lib/irb/lc/error.rb b/lib/irb/lc/error.rb
deleted file mode 100644
index ee0f047822..0000000000
--- a/lib/irb/lc/error.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-#
-# irb/lc/error.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB
- # :stopdoc:
-
- class UnrecognizedSwitch < StandardError
- def initialize(val)
- super("Unrecognized switch: #{val}")
- end
- end
- class CantReturnToNormalMode < StandardError
- def initialize
- super("Can't return to normal mode.")
- end
- end
- class IllegalParameter < StandardError
- def initialize(val)
- super("Invalid parameter(#{val}).")
- end
- end
- class IrbAlreadyDead < StandardError
- def initialize
- super("Irb is already dead.")
- end
- end
- class IrbSwitchedToCurrentThread < StandardError
- def initialize
- super("Switched to current thread.")
- end
- end
- class NoSuchJob < StandardError
- def initialize(val)
- super("No such job(#{val}).")
- end
- end
- class CantChangeBinding < StandardError
- def initialize(val)
- super("Can't change binding to (#{val}).")
- end
- end
- class UndefinedPromptMode < StandardError
- def initialize(val)
- super("Undefined prompt mode(#{val}).")
- end
- end
-
- # :startdoc:
-end
diff --git a/lib/irb/lc/help-message b/lib/irb/lc/help-message
deleted file mode 100644
index 37347306e8..0000000000
--- a/lib/irb/lc/help-message
+++ /dev/null
@@ -1,55 +0,0 @@
-Usage: irb.rb [options] [programfile] [arguments]
- -f Don't initialize from configuration file.
- -d Set $DEBUG and $VERBOSE to true (same as 'ruby -d').
- -r load-module Require load-module (same as 'ruby -r').
- -I path Specify $LOAD_PATH directory (same as 'ruby -I').
- -U Set external and internal encodings to UTF-8.
- -E ex[:in] Set default external (ex) and internal (in) encodings
- (same as 'ruby -E').
- -w Suppress warnings (same as 'ruby -w').
- -W[level=2] Set warning level: 0=silence, 1=medium, 2=verbose
- (same as 'ruby -W').
- --context-mode n Set n[0-4] to method to create Binding Object,
- when new workspace was created.
- --extra-doc-dir Add an extra doc dir for the doc dialog.
- --echo Show result (default).
- --noecho Don't show result.
- --echo-on-assignment
- Show result on assignment.
- --noecho-on-assignment
- Don't show result on assignment.
- --truncate-echo-on-assignment
- Show truncated result on assignment (default).
- --inspect Use 'inspect' for output.
- --noinspect Don't use 'inspect' for output.
- --no-pager Don't use pager.
- --multiline Use multiline editor module (default).
- --nomultiline Don't use multiline editor module.
- --singleline Use single line editor module.
- --nosingleline Don't use single line editor module (default).
- --colorize Use color-highlighting (default).
- --nocolorize Don't use color-highlighting.
- --autocomplete Use auto-completion (default).
- --noautocomplete Don't use auto-completion.
- --regexp-completor
- Use regexp based completion (default).
- --type-completor Use type based completion.
- --prompt prompt-mode, --prompt-mode prompt-mode
- Set prompt mode. Pre-defined prompt modes are:
- 'default', 'classic', 'simple', 'inf-ruby', 'xmp', 'null'.
- --inf-ruby-mode Use prompt appropriate for inf-ruby-mode on emacs.
- Suppresses --multiline and --singleline.
- --sample-book-mode, --simple-prompt
- Set prompt mode to 'simple'.
- --noprompt Don't output prompt.
- --script Script mode (default, treat first argument as script)
- --noscript No script mode (leave arguments in argv)
- --single-irb Share self with sub-irb.
- --tracer Show stack trace for each command.
- --back-trace-limit n[=16]
- Display backtrace top n and bottom n.
- --verbose Show details.
- --noverbose Don't show details.
- -v, --version Print the version of irb.
- -h, --help Print help.
- -- Separate options of irb from the list of command-line args.
diff --git a/lib/irb/lc/ja/error.rb b/lib/irb/lc/ja/error.rb
deleted file mode 100644
index 9e2e5b8870..0000000000
--- a/lib/irb/lc/ja/error.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-#
-# irb/lc/ja/error.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB
- # :stopdoc:
-
- class UnrecognizedSwitch < StandardError
- def initialize(val)
- super("スイッチ(#{val})が分りません")
- end
- end
- class CantReturnToNormalMode < StandardError
- def initialize
- super("Normalモードに戻れません.")
- end
- end
- class IllegalParameter < StandardError
- def initialize(val)
- super("パラメータ(#{val})が間違っています.")
- end
- end
- class IrbAlreadyDead < StandardError
- def initialize
- super("Irbは既に死んでいます.")
- end
- end
- class IrbSwitchedToCurrentThread < StandardError
- def initialize
- super("カレントスレッドに切り替わりました.")
- end
- end
- class NoSuchJob < StandardError
- def initialize(val)
- super("そのようなジョブ(#{val})はありません.")
- end
- end
- class CantChangeBinding < StandardError
- def initialize(val)
- super("バインディング(#{val})に変更できません.")
- end
- end
- class UndefinedPromptMode < StandardError
- def initialize(val)
- super("プロンプトモード(#{val})は定義されていません.")
- end
- end
-
- # :startdoc:
-end
-# vim:fileencoding=utf-8
diff --git a/lib/irb/lc/ja/help-message b/lib/irb/lc/ja/help-message
deleted file mode 100644
index 99f4449b3b..0000000000
--- a/lib/irb/lc/ja/help-message
+++ /dev/null
@@ -1,58 +0,0 @@
-Usage: irb.rb [options] [programfile] [arguments]
- -f ~/.irbrc を読み込まない.
- -d $DEBUG をtrueにする(ruby -d と同じ)
- -r load-module ruby -r と同じ.
- -I path $LOAD_PATH に path を追加する.
- -U ruby -U と同じ.
- -E enc ruby -E と同じ.
- -w ruby -w と同じ.
- -W[level=2] ruby -W と同じ.
- --context-mode n 新しいワークスペースを作成した時に関連する Binding
- オブジェクトの作成方法を 0 から 3 のいずれかに設定する.
- --extra-doc-dir 指定したディレクトリのドキュメントを追加で読み込む.
- --echo 実行結果を表示する(デフォルト).
- --noecho 実行結果を表示しない.
- --echo-on-assignment
- 代入結果を表示する.
- --noecho-on-assignment
- 代入結果を表示しない.
- --truncate-echo-on-assignment
- truncateされた代入結果を表示する(デフォルト).
- --inspect 結果出力にinspectを用いる.
- --noinspect 結果出力にinspectを用いない.
- --no-pager ページャを使用しない.
- --multiline マルチラインエディタを利用する.
- --nomultiline マルチラインエディタを利用しない.
- --singleline シングルラインエディタを利用する.
- --nosingleline シングルラインエディタを利用しない.
- --colorize 色付けを利用する.
- --nocolorize 色付けを利用しない.
- --autocomplete オートコンプリートを利用する.
- --noautocomplete オートコンプリートを利用しない.
- --regexp-completor
- 補完に正規表現を利用する.
- --type-completor 補完に型情報を利用する.
- --prompt prompt-mode/--prompt-mode prompt-mode
- プロンプトモードを切替えます. 現在定義されているプ
- ロンプトモードは, default, simple, xmp, inf-rubyが
- 用意されています.
- --inf-ruby-mode emacsのinf-ruby-mode用のプロンプト表示を行なう. 特
- に指定がない限り, シングルラインエディタとマルチラ
- インエディタは使わなくなる.
- --sample-book-mode/--simple-prompt
- 非常にシンプルなプロンプトを用いるモードです.
- --noprompt プロンプト表示を行なわない.
- --script スクリプトモード(最初の引数をスクリプトファイルとして扱う、デフォルト)
- --noscript 引数をargvとして扱う.
- --single-irb irb 中で self を実行して得られるオブジェクトをサ
- ブ irb と共有する.
- --tracer コマンド実行時にトレースを行なう.
- --back-trace-limit n
- バックトレース表示をバックトレースの頭から n, 後ろ
- からnだけ行なう. デフォルトは16
-
- --verbose 詳細なメッセージを出力する.
- --noverbose 詳細なメッセージを出力しない(デフォルト).
- -v, --version irbのバージョンを表示する.
- -h, --help irb のヘルプを表示する.
- -- 以降のコマンドライン引数をオプションとして扱わない.
diff --git a/lib/irb/locale.rb b/lib/irb/locale.rb
deleted file mode 100644
index 2abcc7354b..0000000000
--- a/lib/irb/locale.rb
+++ /dev/null
@@ -1,153 +0,0 @@
-# frozen_string_literal: true
-#
-# irb/locale.rb - internationalization module
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB # :nodoc:
- class Locale
-
- LOCALE_NAME_RE = %r[
- (?<language>[[:alpha:]]{2,3})
- (?:_ (?<territory>[[:alpha:]]{2,3}) )?
- (?:\. (?<codeset>[^@]+) )?
- (?:@ (?<modifier>.*) )?
- ]x
- LOCALE_DIR = "/lc/"
-
- LEGACY_ENCODING_ALIAS_MAP = {
- 'ujis' => Encoding::EUC_JP,
- 'euc' => Encoding::EUC_JP
- }
-
- @@loaded = []
-
- def initialize(locale = nil)
- @override_encoding = nil
- @lang = @territory = @encoding_name = @modifier = nil
- @locale = locale || ENV["IRB_LANG"] || ENV["LC_MESSAGES"] || ENV["LC_ALL"] || ENV["LANG"] || "C"
- if m = LOCALE_NAME_RE.match(@locale)
- @lang, @territory, @encoding_name, @modifier = m[:language], m[:territory], m[:codeset], m[:modifier]
-
- if @encoding_name
- if @encoding = LEGACY_ENCODING_ALIAS_MAP[@encoding_name]
- warn(("%s is obsolete. use %s" % ["#{@lang}_#{@territory}.#{@encoding_name}", "#{@lang}_#{@territory}.#{@encoding.name}"]), uplevel: 1)
- else
- @encoding = Encoding.find(@encoding_name) rescue nil
- end
- end
- end
- @encoding ||= (Encoding.find('locale') rescue Encoding::ASCII_8BIT)
- end
-
- attr_reader :lang, :territory, :modifier
-
- def encoding
- @override_encoding || @encoding
- end
-
- def String(mes)
- mes = super(mes)
- if encoding
- mes.encode(encoding, undef: :replace)
- else
- mes
- end
- end
-
- def format(*opts)
- String(super(*opts))
- end
-
- def gets(*rs)
- String(super(*rs))
- end
-
- def readline(*rs)
- String(super(*rs))
- end
-
- def print(*opts)
- ary = opts.collect{|opt| String(opt)}
- super(*ary)
- end
-
- def printf(*opts)
- s = format(*opts)
- print s
- end
-
- def puts(*opts)
- ary = opts.collect{|opt| String(opt)}
- super(*ary)
- end
-
- def load(file)
- found = find(file)
- if found
- unless @@loaded.include?(found)
- @@loaded << found # cache
- Kernel.load(found)
- end
- else
- raise LoadError, "No such file to load -- #{file}"
- end
- end
-
- def find(file, paths = $:)
- dir = File.dirname(file)
- dir = "" if dir == "."
- base = File.basename(file)
-
- if dir.start_with?('/')
- return each_localized_path(dir, base).find{|full_path| File.readable? full_path}
- else
- return search_file(paths, dir, base)
- end
- end
-
- # @param paths load paths in which IRB find a localized file.
- # @param dir directory
- # @param file basename to be localized
- #
- # typically, for the parameters and a <path> in paths, it searches
- # <path>/<dir>/<locale>/<file>
- def search_file(lib_paths, dir, file)
- each_localized_path(dir, file) do |lc_path|
- lib_paths.each do |libpath|
- full_path = File.join(libpath, lc_path)
- return full_path if File.readable?(full_path)
- end
- redo if defined?(Gem) and Gem.try_activate(lc_path)
- end
- nil
- end
-
- def each_localized_path(dir, file)
- return enum_for(:each_localized_path) unless block_given?
- each_sublocale do |lc|
- yield lc.nil? ? File.join(dir, LOCALE_DIR, file) : File.join(dir, LOCALE_DIR, lc, file)
- end
- end
-
- def each_sublocale
- if @lang
- if @territory
- if @encoding_name
- yield "#{@lang}_#{@territory}.#{@encoding_name}@#{@modifier}" if @modifier
- yield "#{@lang}_#{@territory}.#{@encoding_name}"
- end
- yield "#{@lang}_#{@territory}@#{@modifier}" if @modifier
- yield "#{@lang}_#{@territory}"
- end
- if @encoding_name
- yield "#{@lang}.#{@encoding_name}@#{@modifier}" if @modifier
- yield "#{@lang}.#{@encoding_name}"
- end
- yield "#{@lang}@#{@modifier}" if @modifier
- yield "#{@lang}"
- end
- yield nil
- end
- end
-end
diff --git a/lib/irb/nesting_parser.rb b/lib/irb/nesting_parser.rb
deleted file mode 100644
index 5aa940cc28..0000000000
--- a/lib/irb/nesting_parser.rb
+++ /dev/null
@@ -1,237 +0,0 @@
-# frozen_string_literal: true
-module IRB
- module NestingParser
- IGNORE_TOKENS = %i[on_sp on_ignored_nl on_comment on_embdoc_beg on_embdoc on_embdoc_end]
-
- # Scan each token and call the given block with array of token and other information for parsing
- def self.scan_opens(tokens)
- opens = []
- pending_heredocs = []
- first_token_on_line = true
- tokens.each do |t|
- skip = false
- last_tok, state, args = opens.last
- case state
- when :in_alias_undef
- skip = t.event == :on_kw
- when :in_unquoted_symbol
- unless IGNORE_TOKENS.include?(t.event)
- opens.pop
- skip = true
- end
- when :in_lambda_head
- opens.pop if t.event == :on_tlambeg || (t.event == :on_kw && t.tok == 'do')
- when :in_method_head
- unless IGNORE_TOKENS.include?(t.event)
- next_args = []
- body = nil
- if args.include?(:receiver)
- case t.event
- when :on_lparen, :on_ivar, :on_gvar, :on_cvar
- # def (receiver). | def @ivar. | def $gvar. | def @@cvar.
- next_args << :dot
- when :on_kw
- case t.tok
- when 'self', 'true', 'false', 'nil'
- # def self(arg) | def self.
- next_args.push(:arg, :dot)
- else
- # def if(arg)
- skip = true
- next_args << :arg
- end
- when :on_op, :on_backtick
- # def +(arg)
- skip = true
- next_args << :arg
- when :on_ident, :on_const
- # def a(arg) | def a.
- next_args.push(:arg, :dot)
- end
- end
- if args.include?(:dot)
- # def receiver.name
- next_args << :name if t.event == :on_period || (t.event == :on_op && t.tok == '::')
- end
- if args.include?(:name)
- if %i[on_ident on_const on_op on_kw on_backtick].include?(t.event)
- # def name(arg) | def receiver.name(arg)
- next_args << :arg
- skip = true
- end
- end
- if args.include?(:arg)
- case t.event
- when :on_nl, :on_semicolon
- # def receiver.f;
- body = :normal
- when :on_lparen
- # def receiver.f()
- next_args << :eq
- else
- if t.event == :on_op && t.tok == '='
- # def receiver.f =
- body = :oneliner
- else
- # def receiver.f arg
- next_args << :arg_without_paren
- end
- end
- end
- if args.include?(:eq)
- if t.event == :on_op && t.tok == '='
- body = :oneliner
- else
- body = :normal
- end
- end
- if args.include?(:arg_without_paren)
- if %i[on_semicolon on_nl].include?(t.event)
- # def f a;
- body = :normal
- else
- # def f a, b
- next_args << :arg_without_paren
- end
- end
- if body == :oneliner
- opens.pop
- elsif body
- opens[-1] = [last_tok, nil]
- else
- opens[-1] = [last_tok, :in_method_head, next_args]
- end
- end
- when :in_for_while_until_condition
- if t.event == :on_semicolon || t.event == :on_nl || (t.event == :on_kw && t.tok == 'do')
- skip = true if t.event == :on_kw && t.tok == 'do'
- opens[-1] = [last_tok, nil]
- end
- end
-
- unless skip
- case t.event
- when :on_kw
- case t.tok
- when 'begin', 'class', 'module', 'do', 'case'
- opens << [t, nil]
- when 'end'
- opens.pop
- when 'def'
- opens << [t, :in_method_head, [:receiver, :name]]
- when 'if', 'unless'
- unless t.state.allbits?(Ripper::EXPR_LABEL)
- opens << [t, nil]
- end
- when 'while', 'until'
- unless t.state.allbits?(Ripper::EXPR_LABEL)
- opens << [t, :in_for_while_until_condition]
- end
- when 'ensure', 'rescue'
- unless t.state.allbits?(Ripper::EXPR_LABEL)
- opens.pop
- opens << [t, nil]
- end
- when 'alias'
- opens << [t, :in_alias_undef, 2]
- when 'undef'
- opens << [t, :in_alias_undef, 1]
- when 'elsif', 'else', 'when'
- opens.pop
- opens << [t, nil]
- when 'for'
- opens << [t, :in_for_while_until_condition]
- when 'in'
- if last_tok&.event == :on_kw && %w[case in].include?(last_tok.tok) && first_token_on_line
- opens.pop
- opens << [t, nil]
- end
- end
- when :on_tlambda
- opens << [t, :in_lambda_head]
- when :on_lparen, :on_lbracket, :on_lbrace, :on_tlambeg, :on_embexpr_beg, :on_embdoc_beg
- opens << [t, nil]
- when :on_rparen, :on_rbracket, :on_rbrace, :on_embexpr_end, :on_embdoc_end
- opens.pop
- when :on_heredoc_beg
- pending_heredocs << t
- when :on_heredoc_end
- opens.pop
- when :on_backtick
- opens << [t, nil] if t.state.allbits?(Ripper::EXPR_BEG)
- when :on_tstring_beg, :on_words_beg, :on_qwords_beg, :on_symbols_beg, :on_qsymbols_beg, :on_regexp_beg
- opens << [t, nil]
- when :on_tstring_end, :on_regexp_end, :on_label_end
- opens.pop
- when :on_symbeg
- if t.tok == ':'
- opens << [t, :in_unquoted_symbol]
- else
- opens << [t, nil]
- end
- end
- end
- if t.event == :on_nl || t.event == :on_semicolon
- first_token_on_line = true
- elsif t.event != :on_sp
- first_token_on_line = false
- end
- if pending_heredocs.any? && t.tok.include?("\n")
- pending_heredocs.reverse_each { |t| opens << [t, nil] }
- pending_heredocs = []
- end
- if opens.last && opens.last[1] == :in_alias_undef && !IGNORE_TOKENS.include?(t.event) && t.event != :on_heredoc_end
- tok, state, arg = opens.pop
- opens << [tok, state, arg - 1] if arg >= 1
- end
- yield t, opens if block_given?
- end
- opens.map(&:first) + pending_heredocs.reverse
- end
-
- def self.open_tokens(tokens)
- # scan_opens without block will return a list of open tokens at last token position
- scan_opens(tokens)
- end
-
- # Calculates token information [line_tokens, prev_opens, next_opens, min_depth] for each line.
- # Example code
- # ["hello
- # world"+(
- # First line
- # line_tokens: [[lbracket, '['], [tstring_beg, '"'], [tstring_content("hello\nworld"), "hello\n"]]
- # prev_opens: []
- # next_tokens: [lbracket, tstring_beg]
- # min_depth: 0 (minimum at beginning of line)
- # Second line
- # line_tokens: [[tstring_content("hello\nworld"), "world"], [tstring_end, '"'], [op, '+'], [lparen, '(']]
- # prev_opens: [lbracket, tstring_beg]
- # next_tokens: [lbracket, lparen]
- # min_depth: 1 (minimum just after tstring_end)
- def self.parse_by_line(tokens)
- line_tokens = []
- prev_opens = []
- min_depth = 0
- output = []
- last_opens = scan_opens(tokens) do |t, opens|
- depth = t == opens.last&.first ? opens.size - 1 : opens.size
- min_depth = depth if depth < min_depth
- if t.tok.include?("\n")
- t.tok.each_line do |line|
- line_tokens << [t, line]
- next if line[-1] != "\n"
- next_opens = opens.map(&:first)
- output << [line_tokens, prev_opens, next_opens, min_depth]
- prev_opens = next_opens
- min_depth = prev_opens.size
- line_tokens = []
- end
- else
- line_tokens << [t, t.tok]
- end
- end
- output << [line_tokens, prev_opens, last_opens, min_depth] if line_tokens.any?
- output
- end
- end
-end
diff --git a/lib/irb/notifier.rb b/lib/irb/notifier.rb
deleted file mode 100644
index dc1b9ef14b..0000000000
--- a/lib/irb/notifier.rb
+++ /dev/null
@@ -1,230 +0,0 @@
-# frozen_string_literal: true
-#
-# notifier.rb - output methods used by irb
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-require_relative "output-method"
-
-module IRB
- # An output formatter used internally by the lexer.
- module Notifier
- class ErrUndefinedNotifier < StandardError
- def initialize(val)
- super("undefined notifier level: #{val} is specified")
- end
- end
- class ErrUnrecognizedLevel < StandardError
- def initialize(val)
- super("unrecognized notifier level: #{val} is specified")
- end
- end
-
- # Define a new Notifier output source, returning a new CompositeNotifier
- # with the given +prefix+ and +output_method+.
- #
- # The optional +prefix+ will be appended to all objects being inspected
- # during output, using the given +output_method+ as the output source. If
- # no +output_method+ is given, StdioOutputMethod will be used, and all
- # expressions will be sent directly to STDOUT without any additional
- # formatting.
- def def_notifier(prefix = "", output_method = StdioOutputMethod.new)
- CompositeNotifier.new(prefix, output_method)
- end
- module_function :def_notifier
-
- # An abstract class, or superclass, for CompositeNotifier and
- # LeveledNotifier to inherit. It provides several wrapper methods for the
- # OutputMethod object used by the Notifier.
- class AbstractNotifier
- # Creates a new Notifier object
- def initialize(prefix, base_notifier)
- @prefix = prefix
- @base_notifier = base_notifier
- end
-
- # The +prefix+ for this Notifier, which is appended to all objects being
- # inspected during output.
- attr_reader :prefix
-
- # A wrapper method used to determine whether notifications are enabled.
- #
- # Defaults to +true+.
- def notify?
- true
- end
-
- # See OutputMethod#print for more detail.
- def print(*opts)
- @base_notifier.print prefix, *opts if notify?
- end
-
- # See OutputMethod#printn for more detail.
- def printn(*opts)
- @base_notifier.printn prefix, *opts if notify?
- end
-
- # See OutputMethod#printf for more detail.
- def printf(format, *opts)
- @base_notifier.printf(prefix + format, *opts) if notify?
- end
-
- # See OutputMethod#puts for more detail.
- def puts(*objs)
- if notify?
- @base_notifier.puts(*objs.collect{|obj| prefix + obj.to_s})
- end
- end
-
- # Same as #ppx, except it uses the #prefix given during object
- # initialization.
- # See OutputMethod#ppx for more detail.
- def pp(*objs)
- if notify?
- @base_notifier.ppx @prefix, *objs
- end
- end
-
- # Same as #pp, except it concatenates the given +prefix+ with the #prefix
- # given during object initialization.
- #
- # See OutputMethod#ppx for more detail.
- def ppx(prefix, *objs)
- if notify?
- @base_notifier.ppx @prefix+prefix, *objs
- end
- end
-
- # Execute the given block if notifications are enabled.
- def exec_if
- yield(@base_notifier) if notify?
- end
- end
-
- # A class that can be used to create a group of notifier objects with the
- # intent of representing a leveled notification system for irb.
- #
- # This class will allow you to generate other notifiers, and assign them
- # the appropriate level for output.
- #
- # The Notifier class provides a class-method Notifier.def_notifier to
- # create a new composite notifier. Using the first composite notifier
- # object you create, sibling notifiers can be initialized with
- # #def_notifier.
- class CompositeNotifier < AbstractNotifier
- # Create a new composite notifier object with the given +prefix+, and
- # +base_notifier+ to use for output.
- def initialize(prefix, base_notifier)
- super
-
- @notifiers = [D_NOMSG]
- @level_notifier = D_NOMSG
- end
-
- # List of notifiers in the group
- attr_reader :notifiers
-
- # Creates a new LeveledNotifier in the composite #notifiers group.
- #
- # The given +prefix+ will be assigned to the notifier, and +level+ will
- # be used as the index of the #notifiers Array.
- #
- # This method returns the newly created instance.
- def def_notifier(level, prefix = "")
- notifier = LeveledNotifier.new(self, level, prefix)
- @notifiers[level] = notifier
- notifier
- end
-
- # Returns the leveled notifier for this object
- attr_reader :level_notifier
- alias level level_notifier
-
- # Sets the leveled notifier for this object.
- #
- # When the given +value+ is an instance of AbstractNotifier,
- # #level_notifier is set to the given object.
- #
- # When an Integer is given, #level_notifier is set to the notifier at the
- # index +value+ in the #notifiers Array.
- #
- # If no notifier exists at the index +value+ in the #notifiers Array, an
- # ErrUndefinedNotifier exception is raised.
- #
- # An ErrUnrecognizedLevel exception is raised if the given +value+ is not
- # found in the existing #notifiers Array, or an instance of
- # AbstractNotifier
- def level_notifier=(value)
- case value
- when AbstractNotifier
- @level_notifier = value
- when Integer
- l = @notifiers[value]
- raise ErrUndefinedNotifier, value unless l
- @level_notifier = l
- else
- raise ErrUnrecognizedLevel, value unless l
- end
- end
-
- alias level= level_notifier=
- end
-
- # A leveled notifier is comparable to the composite group from
- # CompositeNotifier#notifiers.
- class LeveledNotifier < AbstractNotifier
- include Comparable
-
- # Create a new leveled notifier with the given +base+, and +prefix+ to
- # send to AbstractNotifier.new
- #
- # The given +level+ is used to compare other leveled notifiers in the
- # CompositeNotifier group to determine whether or not to output
- # notifications.
- def initialize(base, level, prefix)
- super(prefix, base)
-
- @level = level
- end
-
- # The current level of this notifier object
- attr_reader :level
-
- # Compares the level of this notifier object with the given +other+
- # notifier.
- #
- # See the Comparable module for more information.
- def <=>(other)
- @level <=> other.level
- end
-
- # Whether to output messages to the output method, depending on the level
- # of this notifier object.
- def notify?
- @base_notifier.level >= self
- end
- end
-
- # NoMsgNotifier is a LeveledNotifier that's used as the default notifier
- # when creating a new CompositeNotifier.
- #
- # This notifier is used as the +zero+ index, or level +0+, for
- # CompositeNotifier#notifiers, and will not output messages of any sort.
- class NoMsgNotifier < LeveledNotifier
- # Creates a new notifier that should not be used to output messages.
- def initialize
- @base_notifier = nil
- @level = 0
- @prefix = ""
- end
-
- # Ensures notifications are ignored, see AbstractNotifier#notify? for
- # more information.
- def notify?
- false
- end
- end
-
- D_NOMSG = NoMsgNotifier.new # :nodoc:
- end
-end
diff --git a/lib/irb/output-method.rb b/lib/irb/output-method.rb
deleted file mode 100644
index 69942f47a2..0000000000
--- a/lib/irb/output-method.rb
+++ /dev/null
@@ -1,80 +0,0 @@
-# frozen_string_literal: true
-#
-# output-method.rb - output methods used by irb
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-module IRB
- # An abstract output class for IO in irb. This is mainly used internally by
- # IRB::Notifier. You can define your own output method to use with Irb.new,
- # or Context.new
- class OutputMethod
- # Open this method to implement your own output method, raises a
- # NotImplementedError if you don't define #print in your own class.
- def print(*opts)
- raise NotImplementedError
- end
-
- # Prints the given +opts+, with a newline delimiter.
- def printn(*opts)
- print opts.join(" "), "\n"
- end
-
- # Extends IO#printf to format the given +opts+ for Kernel#sprintf using
- # #parse_printf_format
- def printf(format, *opts)
- if /(%*)%I/ =~ format
- format, opts = parse_printf_format(format, opts)
- end
- print sprintf(format, *opts)
- end
-
- # Returns an array of the given +format+ and +opts+ to be used by
- # Kernel#sprintf, if there was a successful Regexp match in the given
- # +format+ from #printf
- #
- # %
- # <flag> [#0- +]
- # <minimum field width> (\*|\*[1-9][0-9]*\$|[1-9][0-9]*)
- # <precision>.(\*|\*[1-9][0-9]*\$|[1-9][0-9]*|)?
- # #<length modifier>(hh|h|l|ll|L|q|j|z|t)
- # <conversion specifier>[diouxXeEfgGcsb%]
- def parse_printf_format(format, opts)
- return format, opts if $1.size % 2 == 1
- end
-
- # Calls #print on each element in the given +objs+, followed by a newline
- # character.
- def puts(*objs)
- for obj in objs
- print(*obj)
- print "\n"
- end
- end
-
- # Prints the given +objs+ calling Object#inspect on each.
- #
- # See #puts for more detail.
- def pp(*objs)
- puts(*objs.collect{|obj| obj.inspect})
- end
-
- # Prints the given +objs+ calling Object#inspect on each and appending the
- # given +prefix+.
- #
- # See #puts for more detail.
- def ppx(prefix, *objs)
- puts(*objs.collect{|obj| prefix+obj.inspect})
- end
-
- end
-
- # A standard output printer
- class StdioOutputMethod < OutputMethod
- # Prints the given +opts+ to standard output, see IO#print for more
- # information.
- def print(*opts)
- STDOUT.print(*opts)
- end
- end
-end
diff --git a/lib/irb/pager.rb b/lib/irb/pager.rb
deleted file mode 100644
index 3391b32c66..0000000000
--- a/lib/irb/pager.rb
+++ /dev/null
@@ -1,91 +0,0 @@
-# frozen_string_literal: true
-
-module IRB
- # The implementation of this class is borrowed from RDoc's lib/rdoc/ri/driver.rb.
- # Please do NOT use this class directly outside of IRB.
- class Pager
- PAGE_COMMANDS = [ENV['RI_PAGER'], ENV['PAGER'], 'less', 'more'].compact.uniq
-
- class << self
- def page_content(content, **options)
- if content_exceeds_screen_height?(content)
- page(**options) do |io|
- io.puts content
- end
- else
- $stdout.puts content
- end
- end
-
- def page(retain_content: false)
- if should_page? && pager = setup_pager(retain_content: retain_content)
- begin
- pid = pager.pid
- yield pager
- ensure
- pager.close
- end
- else
- yield $stdout
- end
- # When user presses Ctrl-C, IRB would raise `IRB::Abort`
- # But since Pager is implemented by running paging commands like `less` in another process with `IO.popen`,
- # the `IRB::Abort` exception only interrupts IRB's execution but doesn't affect the pager
- # So to properly terminate the pager with Ctrl-C, we need to catch `IRB::Abort` and kill the pager process
- rescue IRB::Abort
- Process.kill("TERM", pid) if pid
- nil
- rescue Errno::EPIPE
- end
-
- private
-
- def should_page?
- IRB.conf[:USE_PAGER] && STDIN.tty? && (ENV.key?("TERM") && ENV["TERM"] != "dumb")
- end
-
- def content_exceeds_screen_height?(content)
- screen_height, screen_width = begin
- Reline.get_screen_size
- rescue Errno::EINVAL
- [24, 80]
- end
-
- pageable_height = screen_height - 3 # leave some space for previous and the current prompt
-
- # If the content has more lines than the pageable height
- content.lines.count > pageable_height ||
- # Or if the content is a few long lines
- pageable_height * screen_width < Reline::Unicode.calculate_width(content, true)
- end
-
- def setup_pager(retain_content:)
- require 'shellwords'
-
- PAGE_COMMANDS.each do |pager_cmd|
- cmd = Shellwords.split(pager_cmd)
- next if cmd.empty?
-
- if cmd.first == 'less'
- cmd << '-R' unless cmd.include?('-R')
- cmd << '-X' if retain_content && !cmd.include?('-X')
- end
-
- begin
- io = IO.popen(cmd, 'w')
- rescue
- next
- end
-
- if $? && $?.pid == io.pid && $?.exited? # pager didn't work
- next
- end
-
- return io
- end
-
- nil
- end
- end
- end
-end
diff --git a/lib/irb/ruby-lex.rb b/lib/irb/ruby-lex.rb
deleted file mode 100644
index f6ac7f0f5f..0000000000
--- a/lib/irb/ruby-lex.rb
+++ /dev/null
@@ -1,474 +0,0 @@
-# frozen_string_literal: true
-#
-# irb/ruby-lex.rb - ruby lexcal analyzer
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-require "ripper"
-require "jruby" if RUBY_ENGINE == "jruby"
-require_relative "nesting_parser"
-
-module IRB
- # :stopdoc:
- class RubyLex
- ASSIGNMENT_NODE_TYPES = [
- # Local, instance, global, class, constant, instance, and index assignment:
- # "foo = bar",
- # "@foo = bar",
- # "$foo = bar",
- # "@@foo = bar",
- # "::Foo = bar",
- # "a::Foo = bar",
- # "Foo = bar"
- # "foo.bar = 1"
- # "foo[1] = bar"
- :assign,
-
- # Operation assignment:
- # "foo += bar"
- # "foo -= bar"
- # "foo ||= bar"
- # "foo &&= bar"
- :opassign,
-
- # Multiple assignment:
- # "foo, bar = 1, 2
- :massign,
- ]
-
- class TerminateLineInput < StandardError
- def initialize
- super("Terminate Line Input")
- end
- end
-
- 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
-
- ERROR_TOKENS = [
- :on_parse_error,
- :compile_error,
- :on_assign_error,
- :on_alias_error,
- :on_class_name_error,
- :on_param_error
- ]
-
- def self.generate_local_variables_assign_code(local_variables)
- "#{local_variables.join('=')}=nil;" unless local_variables.empty?
- end
-
- # Some part of the code is not included in Ripper's token.
- # Example: DATA part, token after heredoc_beg when heredoc has unclosed embexpr.
- # With interpolated tokens, tokens.map(&:tok).join will be equal to code.
- def self.interpolate_ripper_ignored_tokens(code, tokens)
- line_positions = [0]
- code.lines.each do |line|
- line_positions << line_positions.last + line.bytesize
- end
- prev_byte_pos = 0
- interpolated = []
- prev_line = 1
- tokens.each do |t|
- line, col = t.pos
- byte_pos = line_positions[line - 1] + col
- if prev_byte_pos < byte_pos
- tok = code.byteslice(prev_byte_pos...byte_pos)
- pos = [prev_line, prev_byte_pos - line_positions[prev_line - 1]]
- interpolated << Ripper::Lexer::Elem.new(pos, :on_ignored_by_ripper, tok, 0)
- prev_line += tok.count("\n")
- end
- interpolated << t
- prev_byte_pos = byte_pos + t.tok.bytesize
- prev_line += t.tok.count("\n")
- end
- if prev_byte_pos < code.bytesize
- tok = code.byteslice(prev_byte_pos..)
- pos = [prev_line, prev_byte_pos - line_positions[prev_line - 1]]
- interpolated << Ripper::Lexer::Elem.new(pos, :on_ignored_by_ripper, tok, 0)
- end
- interpolated
- end
-
- def self.ripper_lex_without_warning(code, local_variables: [])
- verbose, $VERBOSE = $VERBOSE, nil
- lvars_code = generate_local_variables_assign_code(local_variables)
- original_code = code
- if lvars_code
- code = "#{lvars_code}\n#{code}"
- line_no = 0
- else
- line_no = 1
- end
-
- compile_with_errors_suppressed(code, line_no: line_no) do |inner_code, line_no|
- lexer = Ripper::Lexer.new(inner_code, '-', line_no)
- tokens = []
- lexer.scan.each do |t|
- next if t.pos.first == 0
- prev_tk = tokens.last
- position_overlapped = prev_tk && t.pos[0] == prev_tk.pos[0] && t.pos[1] < prev_tk.pos[1] + prev_tk.tok.bytesize
- if position_overlapped
- tokens[-1] = t if ERROR_TOKENS.include?(prev_tk.event) && !ERROR_TOKENS.include?(t.event)
- else
- tokens << t
- end
- end
- interpolate_ripper_ignored_tokens(original_code, tokens)
- end
- ensure
- $VERBOSE = verbose
- end
-
- def check_code_state(code, local_variables:)
- tokens = self.class.ripper_lex_without_warning(code, local_variables: local_variables)
- opens = NestingParser.open_tokens(tokens)
- [tokens, opens, code_terminated?(code, tokens, opens, local_variables: local_variables)]
- end
-
- def code_terminated?(code, tokens, opens, local_variables:)
- case check_code_syntax(code, local_variables: local_variables)
- when :unrecoverable_error
- true
- when :recoverable_error
- false
- when :other_error
- opens.empty? && !should_continue?(tokens)
- when :valid
- !should_continue?(tokens)
- end
- end
-
- def assignment_expression?(code, local_variables:)
- # Try to parse the code and check if the last of possibly multiple
- # expressions is an assignment type.
-
- # If the expression is invalid, Ripper.sexp should return nil which will
- # result in false being returned. Any valid expression should return an
- # s-expression where the second element of the top level array is an
- # array of parsed expressions. The first element of each expression is the
- # expression's type.
- verbose, $VERBOSE = $VERBOSE, nil
- code = "#{RubyLex.generate_local_variables_assign_code(local_variables) || 'nil;'}\n#{code}"
- # Get the last node_type of the line. drop(1) is to ignore the local_variables_assign_code part.
- node_type = Ripper.sexp(code)&.dig(1)&.drop(1)&.dig(-1, 0)
- ASSIGNMENT_NODE_TYPES.include?(node_type)
- ensure
- $VERBOSE = verbose
- end
-
- def should_continue?(tokens)
- # Look at the last token and check if IRB need to continue reading next line.
- # Example code that should continue: `a\` `a +` `a.`
- # Trailing spaces, newline, comments are skipped
- return true if tokens.last&.event == :on_sp && tokens.last.tok == "\\\n"
-
- tokens.reverse_each do |token|
- case token.event
- when :on_sp, :on_nl, :on_ignored_nl, :on_comment, :on_embdoc_beg, :on_embdoc, :on_embdoc_end
- # Skip
- when :on_regexp_end, :on_heredoc_end, :on_semicolon
- # State is EXPR_BEG but should not continue
- return false
- else
- # Endless range should not continue
- return false if token.event == :on_op && token.tok.match?(/\A\.\.\.?\z/)
-
- # EXPR_DOT and most of the EXPR_BEG should continue
- return token.state.anybits?(Ripper::EXPR_BEG | Ripper::EXPR_DOT)
- end
- end
- false
- end
-
- def check_code_syntax(code, local_variables:)
- lvars_code = RubyLex.generate_local_variables_assign_code(local_variables)
- code = "#{lvars_code}\n#{code}"
-
- begin # check if parser error are available
- verbose, $VERBOSE = $VERBOSE, nil
- case RUBY_ENGINE
- when 'ruby'
- self.class.compile_with_errors_suppressed(code) do |inner_code, line_no|
- RubyVM::InstructionSequence.compile(inner_code, nil, nil, line_no)
- end
- when 'jruby'
- JRuby.compile_ir(code)
- else
- catch(:valid) do
- eval("BEGIN { throw :valid, true }\n#{code}")
- false
- end
- end
- rescue EncodingError
- # This is for a hash with invalid encoding symbol, {"\xAE": 1}
- :unrecoverable_error
- rescue SyntaxError => e
- case e.message
- when /unexpected keyword_end/
- # "syntax error, unexpected keyword_end"
- #
- # example:
- # if (
- # end
- #
- # example:
- # end
- return :unrecoverable_error
- when /unexpected '\.'/
- # "syntax error, unexpected '.'"
- #
- # example:
- # .
- return :unrecoverable_error
- when /unexpected tREGEXP_BEG/
- # "syntax error, unexpected tREGEXP_BEG, expecting keyword_do or '{' or '('"
- #
- # example:
- # method / f /
- return :unrecoverable_error
- when /unterminated (?:string|regexp) meets end of file/
- # "unterminated regexp meets end of file"
- #
- # example:
- # /
- #
- # "unterminated string meets end of file"
- #
- # example:
- # '
- return :recoverable_error
- when /unexpected end-of-input/
- # "syntax error, unexpected end-of-input, expecting keyword_end"
- #
- # example:
- # if true
- # hoge
- # if false
- # fuga
- # end
- return :recoverable_error
- else
- return :other_error
- end
- ensure
- $VERBOSE = verbose
- end
- :valid
- end
-
- def calc_indent_level(opens)
- indent_level = 0
- opens.each_with_index do |t, index|
- case t.event
- when :on_heredoc_beg
- if opens[index + 1]&.event != :on_heredoc_beg
- if t.tok.match?(/^<<[~-]/)
- indent_level += 1
- else
- indent_level = 0
- end
- end
- when :on_tstring_beg, :on_regexp_beg, :on_symbeg, :on_backtick
- # No indent: "", //, :"", ``
- # Indent: %(), %r(), %i(), %x()
- indent_level += 1 if t.tok.start_with? '%'
- when :on_embdoc_beg
- indent_level = 0
- else
- indent_level += 1 unless t.tok == 'alias' || t.tok == 'undef'
- end
- end
- indent_level
- end
-
- FREE_INDENT_TOKENS = %i[on_tstring_beg on_backtick on_regexp_beg on_symbeg]
-
- def free_indent_token?(token)
- FREE_INDENT_TOKENS.include?(token&.event)
- end
-
- # Calculates the difference of pasted code's indent and indent calculated from tokens
- def indent_difference(lines, line_results, line_index)
- loop do
- _tokens, prev_opens, _next_opens, min_depth = line_results[line_index]
- open_token = prev_opens.last
- if !open_token || (open_token.event != :on_heredoc_beg && !free_indent_token?(open_token))
- # If the leading whitespace is an indent, return the difference
- indent_level = calc_indent_level(prev_opens.take(min_depth))
- calculated_indent = 2 * indent_level
- actual_indent = lines[line_index][/^ */].size
- return actual_indent - calculated_indent
- elsif open_token.event == :on_heredoc_beg && open_token.tok.match?(/^<<[^-~]/)
- return 0
- end
- # If the leading whitespace is not an indent but part of a multiline token
- # Calculate base_indent of the multiline token's beginning line
- line_index = open_token.pos[0] - 1
- end
- end
-
- def process_indent_level(tokens, lines, line_index, is_newline)
- line_results = NestingParser.parse_by_line(tokens)
- result = line_results[line_index]
- if result
- _tokens, prev_opens, next_opens, min_depth = result
- else
- # When last line is empty
- prev_opens = next_opens = line_results.last[2]
- min_depth = next_opens.size
- end
-
- # To correctly indent line like `end.map do`, we use shortest open tokens on each line for indent calculation.
- # Shortest open tokens can be calculated by `opens.take(min_depth)`
- indent = 2 * calc_indent_level(prev_opens.take(min_depth))
-
- preserve_indent = lines[line_index - (is_newline ? 1 : 0)][/^ */].size
-
- prev_open_token = prev_opens.last
- next_open_token = next_opens.last
-
- # Calculates base indent for pasted code on the line where prev_open_token is located
- # irb(main):001:1* if a # base_indent is 2, indent calculated from tokens is 0
- # irb(main):002:1* if b # base_indent is 6, indent calculated from tokens is 2
- # irb(main):003:0> c # base_indent is 6, indent calculated from tokens is 4
- if prev_open_token
- base_indent = [0, indent_difference(lines, line_results, prev_open_token.pos[0] - 1)].max
- else
- base_indent = 0
- end
-
- if free_indent_token?(prev_open_token)
- if is_newline && prev_open_token.pos[0] == line_index
- # First newline inside free-indent token
- base_indent + indent
- else
- # Accept any number of indent inside free-indent token
- preserve_indent
- end
- elsif prev_open_token&.event == :on_embdoc_beg || next_open_token&.event == :on_embdoc_beg
- if prev_open_token&.event == next_open_token&.event
- # Accept any number of indent inside embdoc content
- preserve_indent
- else
- # =begin or =end
- 0
- end
- elsif prev_open_token&.event == :on_heredoc_beg
- tok = prev_open_token.tok
- if prev_opens.size <= next_opens.size
- if is_newline && lines[line_index].empty? && line_results[line_index - 1][1].last != next_open_token
- # First line in heredoc
- tok.match?(/^<<[-~]/) ? base_indent + indent : indent
- elsif tok.match?(/^<<~/)
- # Accept extra indent spaces inside `<<~` heredoc
- [base_indent + indent, preserve_indent].max
- else
- # Accept any number of indent inside other heredoc
- preserve_indent
- end
- else
- # Heredoc close
- prev_line_indent_level = calc_indent_level(prev_opens)
- tok.match?(/^<<[~-]/) ? base_indent + 2 * (prev_line_indent_level - 1) : 0
- end
- else
- base_indent + indent
- end
- end
-
- LTYPE_TOKENS = %i[
- on_heredoc_beg on_tstring_beg
- on_regexp_beg on_symbeg on_backtick
- on_symbols_beg on_qsymbols_beg
- on_words_beg on_qwords_beg
- ]
-
- def ltype_from_open_tokens(opens)
- start_token = opens.reverse_each.find do |tok|
- LTYPE_TOKENS.include?(tok.event)
- end
- return nil unless start_token
-
- case start_token&.event
- when :on_tstring_beg
- case start_token&.tok
- when ?" then ?"
- when /^%.$/ then ?"
- when /^%Q.$/ then ?"
- when ?' then ?'
- when /^%q.$/ then ?'
- end
- when :on_regexp_beg then ?/
- when :on_symbeg then ?:
- when :on_backtick then ?`
- when :on_qwords_beg then ?]
- when :on_words_beg then ?]
- when :on_qsymbols_beg then ?]
- when :on_symbols_beg then ?]
- when :on_heredoc_beg
- start_token&.tok =~ /<<[-~]?(['"`])\w+\1/
- $1 || ?"
- else
- nil
- end
- end
-
- def check_termination_in_prev_line(code, local_variables:)
- tokens = self.class.ripper_lex_without_warning(code, local_variables: local_variables)
- past_first_newline = false
- index = tokens.rindex do |t|
- # traverse first token before last line
- if past_first_newline
- if t.tok.include?("\n")
- true
- end
- elsif t.tok.include?("\n")
- past_first_newline = true
- false
- else
- false
- end
- end
-
- if index
- first_token = nil
- last_line_tokens = tokens[(index + 1)..(tokens.size - 1)]
- last_line_tokens.each do |t|
- unless [:on_sp, :on_ignored_sp, :on_comment].include?(t.event)
- first_token = t
- break
- end
- end
-
- if first_token && first_token.state != Ripper::EXPR_DOT
- tokens_without_last_line = tokens[0..index]
- code_without_last_line = tokens_without_last_line.map(&:tok).join
- opens_without_last_line = NestingParser.open_tokens(tokens_without_last_line)
- if code_terminated?(code_without_last_line, tokens_without_last_line, opens_without_last_line, local_variables: local_variables)
- return last_line_tokens.map(&:tok).join
- end
- end
- end
- false
- end
- end
- # :startdoc:
-end
-
-RubyLex = IRB::RubyLex
-Object.deprecate_constant(:RubyLex)
diff --git a/lib/irb/ruby_logo.aa b/lib/irb/ruby_logo.aa
deleted file mode 100644
index 61fe22c94a..0000000000
--- a/lib/irb/ruby_logo.aa
+++ /dev/null
@@ -1,80 +0,0 @@
-TYPE: LARGE
-
- -+smJYYN?mm-
- HB"BBYT TQg NggT
- 9Q+g Nm,T 8g NJW
- YS+ N2NJ"Sg N?
- BQg #( gT Nggggk J
- 5j NJ NJ NNge
- #Q #JJ NgT N(
- @j bj mT J
- Bj @/d NJ (
- #q #(( NgT #J
- 5d #(t mT $d
- #q @(@J NJB;
- @( 5d ? HHH H HQmgggggggmN qD
- 5d #uN 2QdH E O
- 5 5JSd Nd NJH @d j
- Fd @J4d s NQH #d (
- #( #o6d Nd NgH #d #d
- 4 B&Od v NgT #d F
- #( 9JGd NH NgUd F
- #d #GJQ d NP $
- #J #U+#Q N Q # j
- j /W BQ+ BQ d NJ NJ
- - NjJH HBIjTQggPJQgW N W k #J
- #J b HYWgggN j s Nag d NN b #d
- #J 5- D s Ngg N d Nd F
- Fd BKH2 #+ s NNgg J Q J ]
- F H @ J N y K(d P I
- F4 E N? #d y #Q NJ E j
- F W Nd q m Bg NxW N(H-
- F d b @ m Hd gW vKJ
- NJ d K d s Bg aT FDd
- b # d N m BQ mV N>
- e5 Nd #d NggggggQWH HHHH NJ -
- m7 NW H N HSVO1z=?11-
- NgTH bB kH WBHWWHBHWmQgg&gggggNNN
- NNggggggNN
-TYPE: ASCII
- ,,,;;;;''''';;;'';,
- ,,;'' ';;,;;; ',
- ,,'' ;;'';'''';;;;;;
- ,;' ;; ',, ;
- ,;' ,;' ';, ;
- ;' ,;; ',,,;
- ,' ,;;,,,,,,,,,,,;;;;
- ;' ;;';;;; ,;;
- ;' ,;' ;; '',, ,;;;
- ;; ,;' ; '';, ,; ;'
-;; ,;;' ;; ;; ;;
-;;, ,,;;' ; ;'; ;;
-;';;,,,,;;;;;;;,,, ;; ,' ; ;;
-; ;;''' ,;'; ''';,,, ; ,;' ;;;;
-;;;;, ; '; ''';;;' ';;;
-;'; ;, ;' '; ,;' ', ;;;
-;;; ; ,; '; ,,' ',, ;;
-;;; '; ;' ';,,'' ';,;;
- '; ';,; ,,;''''''''';;;;;;,,;;;
- ';,,;;,,;;;;;;;;;;''''''''''''''
-TYPE: UNICODE
- ⣀⣤⣴⣾⣿⣿⣿⡛⠛⠛⠛⠛⣻⣿⠿⠛⠛⠶⣤⡀
- ⣀⣴⠾⠛⠉⠁ ⠙⣿⣶⣤⣶⣟⣉ ⠈⠻⣦
- ⣀⣴⠟⠋ ⢸⣿⠟⠻⣯⡙⠛⠛⠛⠶⠶⠶⢶⣽⣇
- ⣠⡾⠋⠁ ⣾⡿ ⠈⠛⢦⣄ ⣿
- ⣠⡾⠋ ⣰⣿⠃ ⠙⠷⣤⡀ ⣿
- ⢀⡾⠋ ⣰⣿⡏ ⠈⠻⣦⣄⢠⣿
- ⣰⠟⠁ ⣴⣿⣿⣁⣀⣠⣤⣤⣤⣤⣤⣤⣤⣴⠶⠿⣿⡏
- ⣼⠏ ⢀⣾⣿⠟⣿⠿⣯⣍⠁ ⣰⣿⡇
- ⢀⣼⠋ ⢀⣴⣿⠟⠁ ⢸⡇ ⠙⠻⢦⣄⡀ ⢠⡿⣿⡇
-⢀⣾⡏ ⢀⣴⣿⠟⠁ ⣿ ⠉⠻⢶⣄⡀⣰⡟ ⣿⠃
-⣾⣿⠁ ⣠⣶⡿⠋⠁ ⢹⡇ ⠈⣿⡏ ⢸⣿
-⣿⣿⡆ ⢀⣠⣴⣿⡿⠋ ⠈⣿ ⢀⡾⠋⣿ ⢸⣿
-⣿⠸⣿⣶⣤⣤⣤⣤⣶⣾⠿⠿⣿⣿⠶⣤⣤⣀⡀ ⢹⡇ ⣴⠟⠁ ⣿⡀⢸⣿
-⣿⢀⣿⣟⠛⠋⠉⠁ ⢰⡟⠹⣧ ⠈⠉⠛⠻⠶⢦⣤⣀⡀ ⠈⣿ ⣠⡾⠃ ⢸⡇⢸⡇
-⣿⣾⣿⢿⡄ ⣿⠁ ⠘⣧ ⠉⠙⠛⠷⣿⣿⡋ ⠸⣇⣸⡇
-⣿⠃⣿⠈⢿⡄ ⣸⠇ ⠘⣧ ⢀⣤⠾⠋⠈⠻⣦⡀ ⣿⣿⡇
-⣿⢸⡏ ⠈⣷⡀ ⢠⡿ ⠘⣧⡀ ⣠⡴⠟⠁ ⠈⠻⣦⣀ ⢿⣿⠁
-⢻⣾⡇ ⠘⣷ ⣼⠃ ⠘⣷⣠⣴⠟⠋ ⠙⢷⣄⢸⣿
- ⠻⣧⡀ ⠘⣧⣰⡏ ⢀⣠⣤⠶⠛⠉⠛⠛⠛⠛⠛⠛⠻⢶⣶⣶⣶⣶⣶⣤⣤⣽⣿⣿
- ⠈⠛⠷⢦⣤⣽⣿⣥⣤⣶⣶⡿⠿⠿⠶⠶⠶⠶⠾⠛⠛⠛⠛⠛⠛⠛⠋⠉⠉⠉⠉⠉⠉⠁
diff --git a/lib/irb/source_finder.rb b/lib/irb/source_finder.rb
deleted file mode 100644
index 5d7d729d19..0000000000
--- a/lib/irb/source_finder.rb
+++ /dev/null
@@ -1,139 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "ruby-lex"
-
-module IRB
- class SourceFinder
- class EvaluationError < StandardError; end
-
- class Source
- attr_reader :file, :line
- def initialize(file, line, ast_source = nil)
- @file = file
- @line = line
- @ast_source = ast_source
- end
-
- def file_exist?
- File.exist?(@file)
- end
-
- def binary_file?
- # If the line is zero, it means that the target's source is probably in a binary file.
- @line.zero?
- end
-
- def file_content
- @file_content ||= File.read(@file)
- end
-
- def colorized_content
- if !binary_file? && file_exist?
- end_line = find_end
- # To correctly colorize, we need to colorize full content and extract the relevant lines.
- colored = IRB::Color.colorize_code(file_content)
- colored.lines[@line - 1...end_line].join
- elsif @ast_source
- IRB::Color.colorize_code(@ast_source)
- end
- end
-
- private
-
- def find_end
- lex = RubyLex.new
- code = file_content
- lines = code.lines[(@line - 1)..-1]
- tokens = RubyLex.ripper_lex_without_warning(lines.join)
- prev_tokens = []
-
- # chunk with line number
- tokens.chunk { |tok| tok.pos[0] }.each do |lnum, chunk|
- code = lines[0..lnum].join
- prev_tokens.concat chunk
- continue = lex.should_continue?(prev_tokens)
- syntax = lex.check_code_syntax(code, local_variables: [])
- if !continue && syntax == :valid
- return @line + lnum
- end
- end
- @line
- end
- end
-
- private_constant :Source
-
- def initialize(irb_context)
- @irb_context = irb_context
- end
-
- def find_source(signature, super_level = 0)
- case signature
- when /\A(::)?[A-Z]\w*(::[A-Z]\w*)*\z/ # ConstName, ::ConstName, ConstPath::ConstName
- eval_receiver_or_owner(signature) # trigger autoload
- *parts, name = signature.split('::', -1)
- base =
- if parts.empty? # ConstName
- find_const_owner(name)
- elsif parts == [''] # ::ConstName
- Object
- else # ConstPath::ConstName
- eval_receiver_or_owner(parts.join('::'))
- end
- file, line = base.const_source_location(name)
- when /\A(?<owner>[A-Z]\w*(::[A-Z]\w*)*)#(?<method>[^ :.]+)\z/ # Class#method
- owner = eval_receiver_or_owner(Regexp.last_match[:owner])
- method = Regexp.last_match[:method]
- return unless owner.respond_to?(:instance_method)
- method = method_target(owner, super_level, method, "owner")
- file, line = method&.source_location
- when /\A((?<receiver>.+)(\.|::))?(?<method>[^ :.]+)\z/ # method, receiver.method, receiver::method
- receiver = eval_receiver_or_owner(Regexp.last_match[:receiver] || 'self')
- method = Regexp.last_match[:method]
- return unless receiver.respond_to?(method, true)
- method = method_target(receiver, super_level, method, "receiver")
- file, line = method&.source_location
- end
- return unless file && line
-
- if File.exist?(file)
- Source.new(file, line)
- elsif method
- # Method defined with eval, probably in IRB session
- source = RubyVM::AbstractSyntaxTree.of(method)&.source rescue nil
- Source.new(file, line, source)
- end
- rescue EvaluationError
- nil
- end
-
- private
-
- def method_target(owner_receiver, super_level, method, type)
- case type
- when "owner"
- target_method = owner_receiver.instance_method(method)
- when "receiver"
- target_method = owner_receiver.method(method)
- end
- super_level.times do |s|
- target_method = target_method.super_method if target_method
- end
- target_method
- rescue NameError
- nil
- end
-
- def eval_receiver_or_owner(code)
- context_binding = @irb_context.workspace.binding
- eval(code, context_binding)
- rescue NameError
- raise EvaluationError
- end
-
- def find_const_owner(name)
- module_nesting = @irb_context.workspace.binding.eval('::Module.nesting')
- module_nesting.find { |mod| mod.const_defined?(name, false) } || module_nesting.find { |mod| mod.const_defined?(name) } || Object
- end
- end
-end
diff --git a/lib/irb/statement.rb b/lib/irb/statement.rb
deleted file mode 100644
index a3391c12a3..0000000000
--- a/lib/irb/statement.rb
+++ /dev/null
@@ -1,80 +0,0 @@
-# frozen_string_literal: true
-
-module IRB
- class Statement
- attr_reader :code
-
- def is_assignment?
- raise NotImplementedError
- end
-
- def suppresses_echo?
- raise NotImplementedError
- end
-
- def should_be_handled_by_debugger?
- raise NotImplementedError
- end
-
- class EmptyInput < Statement
- def is_assignment?
- false
- end
-
- def suppresses_echo?
- true
- end
-
- # Debugger takes empty input to repeat the last command
- def should_be_handled_by_debugger?
- true
- end
-
- def code
- ""
- end
- end
-
- class Expression < Statement
- def initialize(code, is_assignment)
- @code = code
- @is_assignment = is_assignment
- end
-
- def suppresses_echo?
- @code.match?(/;\s*\z/)
- end
-
- def should_be_handled_by_debugger?
- true
- end
-
- def is_assignment?
- @is_assignment
- end
- end
-
- class Command < Statement
- attr_reader :command_class, :arg
-
- def initialize(original_code, command_class, arg)
- @code = original_code
- @command_class = command_class
- @arg = arg
- end
-
- def is_assignment?
- false
- end
-
- def suppresses_echo?
- false
- end
-
- def should_be_handled_by_debugger?
- require_relative 'command/debug'
- IRB::Command::DebugCommand > @command_class
- end
- end
- end
-end
diff --git a/lib/irb/version.rb b/lib/irb/version.rb
deleted file mode 100644
index c41917329c..0000000000
--- a/lib/irb/version.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-#
-# irb/version.rb - irb version definition file
-# by Keiju ISHITSUKA(keiju@ishitsuka.com)
-#
-
-module IRB # :nodoc:
- VERSION = "1.13.1"
- @RELEASE_VERSION = VERSION
- @LAST_UPDATE_DATE = "2024-05-05"
-end
diff --git a/lib/irb/workspace.rb b/lib/irb/workspace.rb
deleted file mode 100644
index d24d1cc38d..0000000000
--- a/lib/irb/workspace.rb
+++ /dev/null
@@ -1,189 +0,0 @@
-# frozen_string_literal: true
-#
-# irb/workspace-binding.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-require "delegate"
-
-require_relative "helper_method"
-
-IRB::TOPLEVEL_BINDING = binding
-module IRB # :nodoc:
- class WorkSpace
- # Creates a new workspace.
- #
- # set self to main if specified, otherwise
- # inherit main from TOPLEVEL_BINDING.
- def initialize(*main)
- if main[0].kind_of?(Binding)
- @binding = main.shift
- elsif IRB.conf[:SINGLE_IRB]
- @binding = TOPLEVEL_BINDING
- else
- case IRB.conf[:CONTEXT_MODE]
- when 0 # binding in proc on TOPLEVEL_BINDING
- @binding = eval("proc{binding}.call",
- TOPLEVEL_BINDING,
- __FILE__,
- __LINE__)
- when 1 # binding in loaded file
- require "tempfile"
- f = Tempfile.open("irb-binding")
- f.print <<EOF
- $binding = binding
-EOF
- f.close
- load f.path
- @binding = $binding
-
- when 2 # binding in loaded file(thread use)
- unless defined? BINDING_QUEUE
- IRB.const_set(:BINDING_QUEUE, Thread::SizedQueue.new(1))
- Thread.abort_on_exception = true
- Thread.start do
- eval "require \"irb/ws-for-case-2\"", TOPLEVEL_BINDING, __FILE__, __LINE__
- end
- Thread.pass
- end
- @binding = BINDING_QUEUE.pop
-
- 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
-
- if main.empty?
- @main = eval("self", @binding)
- else
- @main = main[0]
- end
- IRB.conf[:__MAIN__] = @main
-
- unless main.empty?
- case @main
- when Module
- @binding = eval("IRB.conf[:__MAIN__].module_eval('binding', __FILE__, __LINE__)", @binding, __FILE__, __LINE__)
- else
- begin
- @binding = eval("IRB.conf[:__MAIN__].instance_eval('binding', __FILE__, __LINE__)", @binding, __FILE__, __LINE__)
- rescue TypeError
- fail CantChangeBinding, @main.inspect
- end
- end
- end
-
- case @main
- when Object
- use_delegator = @main.frozen?
- else
- use_delegator = true
- end
-
- if use_delegator
- @main = SimpleDelegator.new(@main)
- IRB.conf[:__MAIN__] = @main
- @main.singleton_class.class_eval do
- private
- define_method(:binding, Kernel.instance_method(:binding))
- define_method(:local_variables, Kernel.instance_method(:local_variables))
- # Define empty method to avoid delegator warning, will be overridden.
- define_method(:exit) {|*a, &b| }
- define_method(:exit!) {|*a, &b| }
- end
- @binding = eval("IRB.conf[:__MAIN__].instance_eval('binding', __FILE__, __LINE__)", @binding, *@binding.source_location)
- end
-
- @binding.local_variable_set(:_, nil)
- end
-
- # The Binding of this workspace
- attr_reader :binding
- # The top-level workspace of this context, also available as
- # <code>IRB.conf[:__MAIN__]</code>
- attr_reader :main
-
- def load_helper_methods_to_main
- ancestors = class<<main;ancestors;end
- main.extend ExtendCommandBundle if !ancestors.include?(ExtendCommandBundle)
- main.extend HelpersContainer if !ancestors.include?(HelpersContainer)
- end
-
- # Evaluate the given +statements+ within the context of this workspace.
- def evaluate(statements, file = __FILE__, line = __LINE__)
- eval(statements, @binding, file, line)
- end
-
- def local_variable_set(name, value)
- @binding.local_variable_set(name, value)
- end
-
- def local_variable_get(name)
- @binding.local_variable_get(name)
- end
-
- # error message manipulator
- # WARN: Rails patches this method to filter its own backtrace. Be cautious when changing it.
- # See: https://github.com/rails/rails/blob/main/railties/lib/rails/commands/console/console_command.rb#L8:~:text=def,filter_backtrace
- def filter_backtrace(bt)
- return nil if bt =~ /\/irb\/.*\.rb/
- return nil if bt =~ /\/irb\.rb/
- return nil if bt =~ /tool\/lib\/.*\.rb|runner\.rb/ # for tests in Ruby repository
- case IRB.conf[:CONTEXT_MODE]
- when 1
- return nil if bt =~ %r!/tmp/irb-binding!
- when 3
- bt = bt.sub(/:\s*in `irb_binding'/, '')
- end
- bt
- end
-
- def code_around_binding
- file, pos = @binding.source_location
-
- if defined?(::SCRIPT_LINES__[file]) && lines = ::SCRIPT_LINES__[file]
- code = ::SCRIPT_LINES__[file].join('')
- else
- begin
- code = File.read(file)
- rescue SystemCallError
- return
- end
- end
-
- lines = Color.colorize_code(code).lines
- pos -= 1
-
- start_pos = [pos - 5, 0].max
- end_pos = [pos + 5, lines.size - 1].min
-
- line_number_fmt = Color.colorize("%#{end_pos.to_s.length}d", [:BLUE, :BOLD])
- fmt = " %2s #{line_number_fmt}: %s"
-
- body = (start_pos..end_pos).map do |current_pos|
- sprintf(fmt, pos == current_pos ? '=>' : '', current_pos + 1, lines[current_pos])
- end.join("")
-
- "\nFrom: #{file} @ line #{pos + 1} :\n\n#{body}#{Color.clear}\n"
- end
- end
-
- module HelpersContainer
- def self.install_helper_methods
- HelperMethod.helper_methods.each do |name, helper_method_class|
- define_method name do |*args, **opts, &block|
- helper_method_class.instance.execute(*args, **opts, &block)
- end unless method_defined?(name)
- end
- end
-
- install_helper_methods
- end
-end
diff --git a/lib/irb/ws-for-case-2.rb b/lib/irb/ws-for-case-2.rb
deleted file mode 100644
index 03f42d73d9..0000000000
--- a/lib/irb/ws-for-case-2.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-#
-# irb/ws-for-case-2.rb -
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-while true
- IRB::BINDING_QUEUE.push _ = binding
-end
diff --git a/lib/irb/xmp.rb b/lib/irb/xmp.rb
deleted file mode 100644
index b1bc53283e..0000000000
--- a/lib/irb/xmp.rb
+++ /dev/null
@@ -1,164 +0,0 @@
-# frozen_string_literal: true
-#
-# xmp.rb - irb version of gotoken xmp
-# by Keiju ISHITSUKA(Nippon Rational Inc.)
-#
-
-require_relative "../irb"
-require_relative "frame"
-
-# An example printer for irb.
-#
-# It's much like the standard library PrettyPrint, that shows the value of each
-# expression as it runs.
-#
-# In order to use this library, you must first require it:
-#
-# require 'irb/xmp'
-#
-# Now, you can take advantage of the Object#xmp convenience method.
-#
-# xmp <<END
-# foo = "bar"
-# baz = 42
-# END
-# #=> foo = "bar"
-# #==>"bar"
-# #=> baz = 42
-# #==>42
-#
-# You can also create an XMP object, with an optional binding to print
-# expressions in the given binding:
-#
-# ctx = binding
-# x = XMP.new ctx
-# x.puts
-# #=> today = "a good day"
-# #==>"a good day"
-# ctx.eval 'today # is what?'
-# #=> "a good day"
-class XMP
-
- # Creates a new XMP object.
- #
- # The top-level binding or, optional +bind+ parameter will be used when
- # creating the workspace. See WorkSpace.new for more information.
- #
- # This uses the +:XMP+ prompt mode.
- # See {Custom Prompts}[rdoc-ref:IRB@Custom+Prompts] for more information.
- def initialize(bind = nil)
- IRB.init_config(nil)
-
- IRB.conf[:PROMPT_MODE] = :XMP
-
- bind = IRB::Frame.top(1) unless bind
- ws = IRB::WorkSpace.new(bind)
- @io = StringInputMethod.new
- @irb = IRB::Irb.new(ws, @io)
- @irb.context.ignore_sigint = false
-
- IRB.conf[:MAIN_CONTEXT] = @irb.context
- end
-
- # Evaluates the given +exps+, for example:
- #
- # require 'irb/xmp'
- # x = XMP.new
- #
- # x.puts '{:a => 1, :b => 2, :c => 3}'
- # #=> {:a => 1, :b => 2, :c => 3}
- # # ==>{:a=>1, :b=>2, :c=>3}
- # x.puts 'foo = "bar"'
- # # => foo = "bar"
- # # ==>"bar"
- def puts(exps)
- @io.puts exps
-
- if @irb.context.ignore_sigint
- begin
- trap_proc_b = trap("SIGINT"){@irb.signal_handle}
- catch(:IRB_EXIT) do
- @irb.eval_input
- end
- ensure
- trap("SIGINT", trap_proc_b)
- end
- else
- catch(:IRB_EXIT) do
- @irb.eval_input
- end
- end
- end
-
- # A custom InputMethod class used by XMP for evaluating string io.
- class StringInputMethod < IRB::InputMethod
- # Creates a new StringInputMethod object
- def initialize
- super
- @exps = []
- end
-
- # Whether there are any expressions left in this printer.
- def eof?
- @exps.empty?
- end
-
- # Reads the next expression from this printer.
- #
- # See IO#gets for more information.
- def gets
- while l = @exps.shift
- next if /^\s+$/ =~ l
- l.concat "\n"
- print @prompt, l
- break
- end
- l
- end
-
- # Concatenates all expressions in this printer, separated by newlines.
- #
- # An Encoding::CompatibilityError is raised of the given +exps+'s encoding
- # doesn't match the previous expression evaluated.
- def puts(exps)
- if @encoding and exps.encoding != @encoding
- enc = Encoding.compatible?(@exps.join("\n"), exps)
- if enc.nil?
- raise Encoding::CompatibilityError, "Encoding in which the passed expression is encoded is not compatible to the preceding's one"
- else
- @encoding = enc
- end
- else
- @encoding = exps.encoding
- end
- @exps.concat exps.split(/\n/)
- end
-
- # Returns the encoding of last expression printed by #puts.
- attr_reader :encoding
- end
-end
-
-# A convenience method that's only available when the you require the IRB::XMP standard library.
-#
-# Creates a new XMP object, using the given expressions as the +exps+
-# parameter, and optional binding as +bind+ or uses the top-level binding. Then
-# evaluates the given expressions using the +:XMP+ prompt mode.
-#
-# For example:
-#
-# require 'irb/xmp'
-# ctx = binding
-# xmp 'foo = "bar"', ctx
-# #=> foo = "bar"
-# #==>"bar"
-# ctx.eval 'foo'
-# #=> "bar"
-#
-# See XMP.new for more information.
-def xmp(exps, bind = nil)
- bind = IRB::Frame.top(1) unless bind
- xmp = XMP.new(bind)
- xmp.puts exps
- xmp
-end
diff --git a/lib/logger.rb b/lib/logger.rb
deleted file mode 100644
index 4099955ef2..0000000000
--- a/lib/logger.rb
+++ /dev/null
@@ -1,747 +0,0 @@
-# frozen_string_literal: true
-# logger.rb - simple logging utility
-# Copyright (C) 2000-2003, 2005, 2008, 2011 NAKAMURA, Hiroshi <nahi@ruby-lang.org>.
-#
-# Documentation:: NAKAMURA, Hiroshi and Gavin Sinclair
-# License::
-# You can redistribute it and/or modify it under the same terms of Ruby's
-# license; either the dual license version in 2003, or any later version.
-# Revision:: $Id$
-#
-# A simple system for logging messages. See Logger for more documentation.
-
-require 'fiber'
-require 'monitor'
-require 'rbconfig'
-
-require_relative 'logger/version'
-require_relative 'logger/formatter'
-require_relative 'logger/log_device'
-require_relative 'logger/severity'
-require_relative 'logger/errors'
-
-# \Class \Logger provides a simple but sophisticated logging utility that
-# you can use to create one or more
-# {event logs}[https://en.wikipedia.org/wiki/Logging_(software)#Event_logs]
-# for your program.
-# Each such log contains a chronological sequence of entries
-# that provides a record of the program's activities.
-#
-# == About the Examples
-#
-# All examples on this page assume that \Logger has been required:
-#
-# require 'logger'
-#
-# == Synopsis
-#
-# Create a log with Logger.new:
-#
-# # Single log file.
-# logger = Logger.new('t.log')
-# # Size-based rotated logging: 3 10-megabyte files.
-# logger = Logger.new('t.log', 3, 10485760)
-# # Period-based rotated logging: daily (also allowed: 'weekly', 'monthly').
-# logger = Logger.new('t.log', 'daily')
-# # Log to an IO stream.
-# logger = Logger.new($stdout)
-#
-# Add entries (level, message) with Logger#add:
-#
-# logger.add(Logger::DEBUG, 'Maximal debugging info')
-# logger.add(Logger::INFO, 'Non-error information')
-# logger.add(Logger::WARN, 'Non-error warning')
-# logger.add(Logger::ERROR, 'Non-fatal error')
-# logger.add(Logger::FATAL, 'Fatal error')
-# logger.add(Logger::UNKNOWN, 'Most severe')
-#
-# Close the log with Logger#close:
-#
-# logger.close
-#
-# == Entries
-#
-# You can add entries with method Logger#add:
-#
-# logger.add(Logger::DEBUG, 'Maximal debugging info')
-# logger.add(Logger::INFO, 'Non-error information')
-# logger.add(Logger::WARN, 'Non-error warning')
-# logger.add(Logger::ERROR, 'Non-fatal error')
-# logger.add(Logger::FATAL, 'Fatal error')
-# logger.add(Logger::UNKNOWN, 'Most severe')
-#
-# These shorthand methods also add entries:
-#
-# logger.debug('Maximal debugging info')
-# logger.info('Non-error information')
-# logger.warn('Non-error warning')
-# logger.error('Non-fatal error')
-# logger.fatal('Fatal error')
-# logger.unknown('Most severe')
-#
-# When you call any of these methods,
-# the entry may or may not be written to the log,
-# depending on the entry's severity and on the log level;
-# see {Log Level}[rdoc-ref:Logger@Log+Level]
-#
-# An entry always has:
-#
-# - A severity (the required argument to #add).
-# - An automatically created timestamp.
-#
-# And may also have:
-#
-# - A message.
-# - A program name.
-#
-# Example:
-#
-# logger = Logger.new($stdout)
-# logger.add(Logger::INFO, 'My message.', 'mung')
-# # => I, [2022-05-07T17:21:46.536234 #20536] INFO -- mung: My message.
-#
-# The default format for an entry is:
-#
-# "%s, [%s #%d] %5s -- %s: %s\n"
-#
-# where the values to be formatted are:
-#
-# - \Severity (one letter).
-# - Timestamp.
-# - Process id.
-# - \Severity (word).
-# - Program name.
-# - Message.
-#
-# You can use a different entry format by:
-#
-# - Setting a custom format proc (affects following entries);
-# see {formatter=}[Logger.html#attribute-i-formatter].
-# - Calling any of the methods above with a block
-# (affects only the one entry).
-# Doing so can have two benefits:
-#
-# - Context: the block can evaluate the entire program context
-# and create a context-dependent message.
-# - Performance: the block is not evaluated unless the log level
-# permits the entry actually to be written:
-#
-# logger.error { my_slow_message_generator }
-#
-# Contrast this with the string form, where the string is
-# always evaluated, regardless of the log level:
-#
-# logger.error("#{my_slow_message_generator}")
-#
-# === \Severity
-#
-# The severity of a log entry has two effects:
-#
-# - Determines whether the entry is selected for inclusion in the log;
-# see {Log Level}[rdoc-ref:Logger@Log+Level].
-# - Indicates to any log reader (whether a person or a program)
-# the relative importance of the entry.
-#
-# === Timestamp
-#
-# The timestamp for a log entry is generated automatically
-# when the entry is created.
-#
-# The logged timestamp is formatted by method
-# {Time#strftime}[rdoc-ref:Time#strftime]
-# using this format string:
-#
-# '%Y-%m-%dT%H:%M:%S.%6N'
-#
-# Example:
-#
-# logger = Logger.new($stdout)
-# logger.add(Logger::INFO)
-# # => I, [2022-05-07T17:04:32.318331 #20536] INFO -- : nil
-#
-# You can set a different format using method #datetime_format=.
-#
-# === Message
-#
-# The message is an optional argument to an entry method:
-#
-# logger = Logger.new($stdout)
-# logger.add(Logger::INFO, 'My message')
-# # => I, [2022-05-07T18:15:37.647581 #20536] INFO -- : My message
-#
-# For the default entry formatter, <tt>Logger::Formatter</tt>,
-# the message object may be:
-#
-# - A string: used as-is.
-# - An Exception: <tt>message.message</tt> is used.
-# - Anything else: <tt>message.inspect</tt> is used.
-#
-# *Note*: Logger::Formatter does not escape or sanitize
-# the message passed to it.
-# Developers should be aware that malicious data (user input)
-# may be in the message, and should explicitly escape untrusted data.
-#
-# You can use a custom formatter to escape message data;
-# see the example at {formatter=}[Logger.html#attribute-i-formatter].
-#
-# === Program Name
-#
-# The program name is an optional argument to an entry method:
-#
-# logger = Logger.new($stdout)
-# logger.add(Logger::INFO, 'My message', 'mung')
-# # => I, [2022-05-07T18:17:38.084716 #20536] INFO -- mung: My message
-#
-# The default program name for a new logger may be set in the call to
-# Logger.new via optional keyword argument +progname+:
-#
-# logger = Logger.new('t.log', progname: 'mung')
-#
-# The default program name for an existing logger may be set
-# by a call to method #progname=:
-#
-# logger.progname = 'mung'
-#
-# The current program name may be retrieved with method
-# {progname}[Logger.html#attribute-i-progname]:
-#
-# logger.progname # => "mung"
-#
-# == Log Level
-#
-# The log level setting determines whether an entry is actually
-# written to the log, based on the entry's severity.
-#
-# These are the defined severities (least severe to most severe):
-#
-# logger = Logger.new($stdout)
-# logger.add(Logger::DEBUG, 'Maximal debugging info')
-# # => D, [2022-05-07T17:57:41.776220 #20536] DEBUG -- : Maximal debugging info
-# logger.add(Logger::INFO, 'Non-error information')
-# # => I, [2022-05-07T17:59:14.349167 #20536] INFO -- : Non-error information
-# logger.add(Logger::WARN, 'Non-error warning')
-# # => W, [2022-05-07T18:00:45.337538 #20536] WARN -- : Non-error warning
-# logger.add(Logger::ERROR, 'Non-fatal error')
-# # => E, [2022-05-07T18:02:41.592912 #20536] ERROR -- : Non-fatal error
-# logger.add(Logger::FATAL, 'Fatal error')
-# # => F, [2022-05-07T18:05:24.703931 #20536] FATAL -- : Fatal error
-# logger.add(Logger::UNKNOWN, 'Most severe')
-# # => A, [2022-05-07T18:07:54.657491 #20536] ANY -- : Most severe
-#
-# The default initial level setting is Logger::DEBUG, the lowest level,
-# which means that all entries are to be written, regardless of severity:
-#
-# logger = Logger.new($stdout)
-# logger.level # => 0
-# logger.add(0, "My message")
-# # => D, [2022-05-11T15:10:59.773668 #20536] DEBUG -- : My message
-#
-# You can specify a different setting in a new logger
-# using keyword argument +level+ with an appropriate value:
-#
-# logger = Logger.new($stdout, level: Logger::ERROR)
-# logger = Logger.new($stdout, level: 'error')
-# logger = Logger.new($stdout, level: :error)
-# logger.level # => 3
-#
-# With this level, entries with severity Logger::ERROR and higher
-# are written, while those with lower severities are not written:
-#
-# logger = Logger.new($stdout, level: Logger::ERROR)
-# logger.add(3)
-# # => E, [2022-05-11T15:17:20.933362 #20536] ERROR -- : nil
-# logger.add(2) # Silent.
-#
-# You can set the log level for an existing logger
-# with method #level=:
-#
-# logger.level = Logger::ERROR
-#
-# These shorthand methods also set the level:
-#
-# logger.debug! # => 0
-# logger.info! # => 1
-# logger.warn! # => 2
-# logger.error! # => 3
-# logger.fatal! # => 4
-#
-# You can retrieve the log level with method #level.
-#
-# logger.level = Logger::ERROR
-# logger.level # => 3
-#
-# These methods return whether a given
-# level is to be written:
-#
-# logger.level = Logger::ERROR
-# logger.debug? # => false
-# logger.info? # => false
-# logger.warn? # => false
-# logger.error? # => true
-# logger.fatal? # => true
-#
-# == Log File Rotation
-#
-# By default, a log file is a single file that grows indefinitely
-# (until explicitly closed); there is no file rotation.
-#
-# To keep log files to a manageable size,
-# you can use _log_ _file_ _rotation_, which uses multiple log files:
-#
-# - Each log file has entries for a non-overlapping
-# time interval.
-# - Only the most recent log file is open and active;
-# the others are closed and inactive.
-#
-# === Size-Based Rotation
-#
-# For size-based log file rotation, call Logger.new with:
-#
-# - Argument +logdev+ as a file path.
-# - Argument +shift_age+ with a positive integer:
-# the number of log files to be in the rotation.
-# - Argument +shift_size+ as a positive integer:
-# the maximum size (in bytes) of each log file;
-# defaults to 1048576 (1 megabyte).
-#
-# Examples:
-#
-# logger = Logger.new('t.log', 3) # Three 1-megabyte files.
-# logger = Logger.new('t.log', 5, 10485760) # Five 10-megabyte files.
-#
-# For these examples, suppose:
-#
-# logger = Logger.new('t.log', 3)
-#
-# Logging begins in the new log file, +t.log+;
-# the log file is "full" and ready for rotation
-# when a new entry would cause its size to exceed +shift_size+.
-#
-# The first time +t.log+ is full:
-#
-# - +t.log+ is closed and renamed to +t.log.0+.
-# - A new file +t.log+ is opened.
-#
-# The second time +t.log+ is full:
-#
-# - +t.log.0 is renamed as +t.log.1+.
-# - +t.log+ is closed and renamed to +t.log.0+.
-# - A new file +t.log+ is opened.
-#
-# Each subsequent time that +t.log+ is full,
-# the log files are rotated:
-#
-# - +t.log.1+ is removed.
-# - +t.log.0 is renamed as +t.log.1+.
-# - +t.log+ is closed and renamed to +t.log.0+.
-# - A new file +t.log+ is opened.
-#
-# === Periodic Rotation
-#
-# For periodic rotation, call Logger.new with:
-#
-# - Argument +logdev+ as a file path.
-# - Argument +shift_age+ as a string period indicator.
-#
-# Examples:
-#
-# logger = Logger.new('t.log', 'daily') # Rotate log files daily.
-# logger = Logger.new('t.log', 'weekly') # Rotate log files weekly.
-# logger = Logger.new('t.log', 'monthly') # Rotate log files monthly.
-#
-# Example:
-#
-# logger = Logger.new('t.log', 'daily')
-#
-# When the given period expires:
-#
-# - The base log file, +t.log+ is closed and renamed
-# with a date-based suffix such as +t.log.20220509+.
-# - A new log file +t.log+ is opened.
-# - Nothing is removed.
-#
-# The default format for the suffix is <tt>'%Y%m%d'</tt>,
-# which produces a suffix similar to the one above.
-# You can set a different format using create-time option
-# +shift_period_suffix+;
-# see details and suggestions at
-# {Time#strftime}[rdoc-ref:Time#strftime].
-#
-class Logger
- _, name, rev = %w$Id$
- if name
- name = name.chomp(",v")
- else
- name = File.basename(__FILE__)
- end
- rev ||= "v#{VERSION}"
- ProgName = "#{name}/#{rev}"
-
- include Severity
-
- # Logging severity threshold (e.g. <tt>Logger::INFO</tt>).
- def level
- @level_override[Fiber.current] || @level
- end
-
- # Sets the log level; returns +severity+.
- # See {Log Level}[rdoc-ref:Logger@Log+Level].
- #
- # Argument +severity+ may be an integer, a string, or a symbol:
- #
- # logger.level = Logger::ERROR # => 3
- # logger.level = 3 # => 3
- # logger.level = 'error' # => "error"
- # logger.level = :error # => :error
- #
- # Logger#sev_threshold= is an alias for Logger#level=.
- #
- def level=(severity)
- @level = Severity.coerce(severity)
- end
-
- # Adjust the log level during the block execution for the current Fiber only
- #
- # logger.with_level(:debug) do
- # logger.debug { "Hello" }
- # end
- def with_level(severity)
- prev, @level_override[Fiber.current] = level, Severity.coerce(severity)
- begin
- yield
- ensure
- if prev
- @level_override[Fiber.current] = prev
- else
- @level_override.delete(Fiber.current)
- end
- end
- end
-
- # Program name to include in log messages.
- attr_accessor :progname
-
- # Sets the date-time format.
- #
- # Argument +datetime_format+ should be either of these:
- #
- # - A string suitable for use as a format for method
- # {Time#strftime}[rdoc-ref:Time#strftime].
- # - +nil+: the logger uses <tt>'%Y-%m-%dT%H:%M:%S.%6N'</tt>.
- #
- def datetime_format=(datetime_format)
- @default_formatter.datetime_format = datetime_format
- end
-
- # Returns the date-time format; see #datetime_format=.
- #
- def datetime_format
- @default_formatter.datetime_format
- end
-
- # Sets or retrieves the logger entry formatter proc.
- #
- # When +formatter+ is +nil+, the logger uses Logger::Formatter.
- #
- # When +formatter+ is a proc, a new entry is formatted by the proc,
- # which is called with four arguments:
- #
- # - +severity+: The severity of the entry.
- # - +time+: A Time object representing the entry's timestamp.
- # - +progname+: The program name for the entry.
- # - +msg+: The message for the entry (string or string-convertible object).
- #
- # The proc should return a string containing the formatted entry.
- #
- # This custom formatter uses
- # {String#dump}[rdoc-ref:String#dump]
- # to escape the message string:
- #
- # logger = Logger.new($stdout, progname: 'mung')
- # original_formatter = logger.formatter || Logger::Formatter.new
- # logger.formatter = proc { |severity, time, progname, msg|
- # original_formatter.call(severity, time, progname, msg.dump)
- # }
- # logger.add(Logger::INFO, "hello \n ''")
- # logger.add(Logger::INFO, "\f\x00\xff\\\"")
- #
- # Output:
- #
- # I, [2022-05-13T13:16:29.637488 #8492] INFO -- mung: "hello \n ''"
- # I, [2022-05-13T13:16:29.637610 #8492] INFO -- mung: "\f\x00\xFF\\\""
- #
- attr_accessor :formatter
-
- alias sev_threshold level
- alias sev_threshold= level=
-
- # Returns +true+ if the log level allows entries with severity
- # Logger::DEBUG to be written, +false+ otherwise.
- # See {Log Level}[rdoc-ref:Logger@Log+Level].
- #
- def debug?; level <= DEBUG; end
-
- # Sets the log level to Logger::DEBUG.
- # See {Log Level}[rdoc-ref:Logger@Log+Level].
- #
- def debug!; self.level = DEBUG; end
-
- # Returns +true+ if the log level allows entries with severity
- # Logger::INFO to be written, +false+ otherwise.
- # See {Log Level}[rdoc-ref:Logger@Log+Level].
- #
- def info?; level <= INFO; end
-
- # Sets the log level to Logger::INFO.
- # See {Log Level}[rdoc-ref:Logger@Log+Level].
- #
- def info!; self.level = INFO; end
-
- # Returns +true+ if the log level allows entries with severity
- # Logger::WARN to be written, +false+ otherwise.
- # See {Log Level}[rdoc-ref:Logger@Log+Level].
- #
- def warn?; level <= WARN; end
-
- # Sets the log level to Logger::WARN.
- # See {Log Level}[rdoc-ref:Logger@Log+Level].
- #
- def warn!; self.level = WARN; end
-
- # Returns +true+ if the log level allows entries with severity
- # Logger::ERROR to be written, +false+ otherwise.
- # See {Log Level}[rdoc-ref:Logger@Log+Level].
- #
- def error?; level <= ERROR; end
-
- # Sets the log level to Logger::ERROR.
- # See {Log Level}[rdoc-ref:Logger@Log+Level].
- #
- def error!; self.level = ERROR; end
-
- # Returns +true+ if the log level allows entries with severity
- # Logger::FATAL to be written, +false+ otherwise.
- # See {Log Level}[rdoc-ref:Logger@Log+Level].
- #
- def fatal?; level <= FATAL; end
-
- # Sets the log level to Logger::FATAL.
- # See {Log Level}[rdoc-ref:Logger@Log+Level].
- #
- def fatal!; self.level = FATAL; end
-
- # :call-seq:
- # Logger.new(logdev, shift_age = 0, shift_size = 1048576, **options)
- #
- # With the single argument +logdev+,
- # returns a new logger with all default options:
- #
- # Logger.new('t.log') # => #<Logger:0x000001e685dc6ac8>
- #
- # Argument +logdev+ must be one of:
- #
- # - A string filepath: entries are to be written
- # to the file at that path; if the file at that path exists,
- # new entries are appended.
- # - An IO stream (typically +$stdout+, +$stderr+. or an open file):
- # entries are to be written to the given stream.
- # - +nil+ or +File::NULL+: no entries are to be written.
- #
- # Examples:
- #
- # Logger.new('t.log')
- # Logger.new($stdout)
- #
- # The keyword options are:
- #
- # - +level+: sets the log level; default value is Logger::DEBUG.
- # See {Log Level}[rdoc-ref:Logger@Log+Level]:
- #
- # Logger.new('t.log', level: Logger::ERROR)
- #
- # - +progname+: sets the default program name; default is +nil+.
- # See {Program Name}[rdoc-ref:Logger@Program+Name]:
- #
- # Logger.new('t.log', progname: 'mung')
- #
- # - +formatter+: sets the entry formatter; default is +nil+.
- # See {formatter=}[Logger.html#attribute-i-formatter].
- # - +datetime_format+: sets the format for entry timestamp;
- # default is +nil+.
- # See #datetime_format=.
- # - +binmode+: sets whether the logger writes in binary mode;
- # default is +false+.
- # - +shift_period_suffix+: sets the format for the filename suffix
- # for periodic log file rotation; default is <tt>'%Y%m%d'</tt>.
- # See {Periodic Rotation}[rdoc-ref:Logger@Periodic+Rotation].
- #
- def initialize(logdev, shift_age = 0, shift_size = 1048576, level: DEBUG,
- progname: nil, formatter: nil, datetime_format: nil,
- binmode: false, shift_period_suffix: '%Y%m%d')
- self.level = level
- self.progname = progname
- @default_formatter = Formatter.new
- self.datetime_format = datetime_format
- self.formatter = formatter
- @logdev = nil
- @level_override = {}
- if logdev && logdev != File::NULL
- @logdev = LogDevice.new(logdev, shift_age: shift_age,
- shift_size: shift_size,
- shift_period_suffix: shift_period_suffix,
- binmode: binmode)
- end
- end
-
- # Sets the logger's output stream:
- #
- # - If +logdev+ is +nil+, reopens the current output stream.
- # - If +logdev+ is a filepath, opens the indicated file for append.
- # - If +logdev+ is an IO stream
- # (usually <tt>$stdout</tt>, <tt>$stderr</tt>, or an open File object),
- # opens the stream for append.
- #
- # Example:
- #
- # logger = Logger.new('t.log')
- # logger.add(Logger::ERROR, 'one')
- # logger.close
- # logger.add(Logger::ERROR, 'two') # Prints 'log writing failed. closed stream'
- # logger.reopen
- # logger.add(Logger::ERROR, 'three')
- # logger.close
- # File.readlines('t.log')
- # # =>
- # # ["# Logfile created on 2022-05-12 14:21:19 -0500 by logger.rb/v1.5.0\n",
- # # "E, [2022-05-12T14:21:27.596726 #22428] ERROR -- : one\n",
- # # "E, [2022-05-12T14:23:05.847241 #22428] ERROR -- : three\n"]
- #
- def reopen(logdev = nil)
- @logdev&.reopen(logdev)
- self
- end
-
- # Creates a log entry, which may or may not be written to the log,
- # depending on the entry's severity and on the log level.
- # See {Log Level}[rdoc-ref:Logger@Log+Level]
- # and {Entries}[rdoc-ref:Logger@Entries] for details.
- #
- # Examples:
- #
- # logger = Logger.new($stdout, progname: 'mung')
- # logger.add(Logger::INFO)
- # logger.add(Logger::ERROR, 'No good')
- # logger.add(Logger::ERROR, 'No good', 'gnum')
- #
- # Output:
- #
- # I, [2022-05-12T16:25:31.469726 #36328] INFO -- mung: mung
- # E, [2022-05-12T16:25:55.349414 #36328] ERROR -- mung: No good
- # E, [2022-05-12T16:26:35.841134 #36328] ERROR -- gnum: No good
- #
- # These convenience methods have implicit severity:
- #
- # - #debug.
- # - #info.
- # - #warn.
- # - #error.
- # - #fatal.
- # - #unknown.
- #
- def add(severity, message = nil, progname = nil)
- severity ||= UNKNOWN
- if @logdev.nil? or severity < level
- return true
- end
- if progname.nil?
- progname = @progname
- end
- if message.nil?
- if block_given?
- message = yield
- else
- message = progname
- progname = @progname
- end
- end
- @logdev.write(
- format_message(format_severity(severity), Time.now, progname, message))
- true
- end
- alias log add
-
- # Writes the given +msg+ to the log with no formatting;
- # returns the number of characters written,
- # or +nil+ if no log device exists:
- #
- # logger = Logger.new($stdout)
- # logger << 'My message.' # => 10
- #
- # Output:
- #
- # My message.
- #
- def <<(msg)
- @logdev&.write(msg)
- end
-
- # Equivalent to calling #add with severity <tt>Logger::DEBUG</tt>.
- #
- def debug(progname = nil, &block)
- add(DEBUG, nil, progname, &block)
- end
-
- # Equivalent to calling #add with severity <tt>Logger::INFO</tt>.
- #
- def info(progname = nil, &block)
- add(INFO, nil, progname, &block)
- end
-
- # Equivalent to calling #add with severity <tt>Logger::WARN</tt>.
- #
- def warn(progname = nil, &block)
- add(WARN, nil, progname, &block)
- end
-
- # Equivalent to calling #add with severity <tt>Logger::ERROR</tt>.
- #
- def error(progname = nil, &block)
- add(ERROR, nil, progname, &block)
- end
-
- # Equivalent to calling #add with severity <tt>Logger::FATAL</tt>.
- #
- def fatal(progname = nil, &block)
- add(FATAL, nil, progname, &block)
- end
-
- # Equivalent to calling #add with severity <tt>Logger::UNKNOWN</tt>.
- #
- def unknown(progname = nil, &block)
- add(UNKNOWN, nil, progname, &block)
- end
-
- # Closes the logger; returns +nil+:
- #
- # logger = Logger.new('t.log')
- # logger.close # => nil
- # logger.info('foo') # Prints "log writing failed. closed stream"
- #
- # Related: Logger#reopen.
- def close
- @logdev&.close
- end
-
-private
-
- # \Severity label for logging (max 5 chars).
- SEV_LABEL = %w(DEBUG INFO WARN ERROR FATAL ANY).freeze
-
- def format_severity(severity)
- SEV_LABEL[severity] || 'ANY'
- end
-
- def format_message(severity, datetime, progname, msg)
- (@formatter || @default_formatter).call(severity, datetime, progname, msg)
- end
-end
diff --git a/lib/logger/errors.rb b/lib/logger/errors.rb
deleted file mode 100644
index 88581793f0..0000000000
--- a/lib/logger/errors.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-class Logger
- # not used after 1.2.7. just for compat.
- class Error < RuntimeError # :nodoc:
- end
- class ShiftingError < Error # :nodoc:
- end
-end
diff --git a/lib/logger/formatter.rb b/lib/logger/formatter.rb
deleted file mode 100644
index c634dbf34d..0000000000
--- a/lib/logger/formatter.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-class Logger
- # Default formatter for log messages.
- class Formatter
- Format = "%.1s, [%s #%d] %5s -- %s: %s\n"
- DatetimeFormat = "%Y-%m-%dT%H:%M:%S.%6N"
-
- attr_accessor :datetime_format
-
- def initialize
- @datetime_format = nil
- end
-
- def call(severity, time, progname, msg)
- sprintf(Format, severity, format_datetime(time), Process.pid, severity, progname, msg2str(msg))
- end
-
- private
-
- def format_datetime(time)
- time.strftime(@datetime_format || DatetimeFormat)
- end
-
- def msg2str(msg)
- case msg
- when ::String
- msg
- when ::Exception
- "#{ msg.message } (#{ msg.class })\n#{ msg.backtrace.join("\n") if msg.backtrace }"
- else
- msg.inspect
- end
- end
- end
-end
diff --git a/lib/logger/log_device.rb b/lib/logger/log_device.rb
deleted file mode 100644
index 84277a2656..0000000000
--- a/lib/logger/log_device.rb
+++ /dev/null
@@ -1,207 +0,0 @@
-# frozen_string_literal: true
-
-require_relative 'period'
-
-class Logger
- # Device used for logging messages.
- class LogDevice
- include Period
-
- attr_reader :dev
- attr_reader :filename
- include MonitorMixin
-
- def initialize(log = nil, shift_age: nil, shift_size: nil, shift_period_suffix: nil, binmode: false)
- @dev = @filename = @shift_age = @shift_size = @shift_period_suffix = nil
- @binmode = binmode
- mon_initialize
- set_dev(log)
- if @filename
- @shift_age = shift_age || 7
- @shift_size = shift_size || 1048576
- @shift_period_suffix = shift_period_suffix || '%Y%m%d'
-
- unless @shift_age.is_a?(Integer)
- base_time = @dev.respond_to?(:stat) ? @dev.stat.mtime : Time.now
- @next_rotate_time = next_rotate_time(base_time, @shift_age)
- end
- end
- end
-
- def write(message)
- begin
- synchronize do
- if @shift_age and @dev.respond_to?(:stat)
- begin
- check_shift_log
- rescue
- warn("log shifting failed. #{$!}")
- end
- end
- begin
- @dev.write(message)
- rescue
- warn("log writing failed. #{$!}")
- end
- end
- rescue Exception => ignored
- warn("log writing failed. #{ignored}")
- end
- end
-
- def close
- begin
- synchronize do
- @dev.close rescue nil
- end
- rescue Exception
- @dev.close rescue nil
- end
- end
-
- def reopen(log = nil)
- # reopen the same filename if no argument, do nothing for IO
- log ||= @filename if @filename
- if log
- synchronize do
- if @filename and @dev
- @dev.close rescue nil # close only file opened by Logger
- @filename = nil
- end
- set_dev(log)
- end
- end
- self
- end
-
- private
-
- def set_dev(log)
- if log.respond_to?(:write) and log.respond_to?(:close)
- @dev = log
- if log.respond_to?(:path) and path = log.path
- if File.exist?(path)
- @filename = path
- end
- end
- else
- @dev = open_logfile(log)
- @dev.sync = true
- @dev.binmode if @binmode
- @filename = log
- end
- end
-
- def open_logfile(filename)
- begin
- File.open(filename, (File::WRONLY | File::APPEND))
- rescue Errno::ENOENT
- create_logfile(filename)
- end
- end
-
- def create_logfile(filename)
- begin
- logdev = File.open(filename, (File::WRONLY | File::APPEND | File::CREAT | File::EXCL))
- logdev.flock(File::LOCK_EX)
- logdev.sync = true
- logdev.binmode if @binmode
- add_log_header(logdev)
- logdev.flock(File::LOCK_UN)
- rescue Errno::EEXIST
- # file is created by another process
- logdev = open_logfile(filename)
- logdev.sync = true
- end
- logdev
- end
-
- def add_log_header(file)
- file.write(
- "# Logfile created on %s by %s\n" % [Time.now.to_s, Logger::ProgName]
- ) if file.size == 0
- end
-
- def check_shift_log
- if @shift_age.is_a?(Integer)
- # Note: always returns false if '0'.
- if @filename && (@shift_age > 0) && (@dev.stat.size > @shift_size)
- lock_shift_log { shift_log_age }
- end
- else
- now = Time.now
- if now >= @next_rotate_time
- @next_rotate_time = next_rotate_time(now, @shift_age)
- lock_shift_log { shift_log_period(previous_period_end(now, @shift_age)) }
- end
- end
- end
-
- if /mswin|mingw|cygwin/ =~ RbConfig::CONFIG['host_os']
- def lock_shift_log
- yield
- end
- else
- def lock_shift_log
- retry_limit = 8
- retry_sleep = 0.1
- begin
- File.open(@filename, File::WRONLY | File::APPEND) do |lock|
- lock.flock(File::LOCK_EX) # inter-process locking. will be unlocked at closing file
- if File.identical?(@filename, lock) and File.identical?(lock, @dev)
- yield # log shifting
- else
- # log shifted by another process (i-node before locking and i-node after locking are different)
- @dev.close rescue nil
- @dev = open_logfile(@filename)
- @dev.sync = true
- end
- end
- rescue Errno::ENOENT
- # @filename file would not exist right after #rename and before #create_logfile
- if retry_limit <= 0
- warn("log rotation inter-process lock failed. #{$!}")
- else
- sleep retry_sleep
- retry_limit -= 1
- retry_sleep *= 2
- retry
- end
- end
- rescue
- warn("log rotation inter-process lock failed. #{$!}")
- end
- end
-
- def shift_log_age
- (@shift_age-3).downto(0) do |i|
- if FileTest.exist?("#{@filename}.#{i}")
- File.rename("#{@filename}.#{i}", "#{@filename}.#{i+1}")
- end
- end
- @dev.close rescue nil
- File.rename("#{@filename}", "#{@filename}.0")
- @dev = create_logfile(@filename)
- return true
- end
-
- def shift_log_period(period_end)
- suffix = period_end.strftime(@shift_period_suffix)
- age_file = "#{@filename}.#{suffix}"
- if FileTest.exist?(age_file)
- # try to avoid filename crash caused by Timestamp change.
- idx = 0
- # .99 can be overridden; avoid too much file search with 'loop do'
- while idx < 100
- idx += 1
- age_file = "#{@filename}.#{suffix}.#{idx}"
- break unless FileTest.exist?(age_file)
- end
- end
- @dev.close rescue nil
- File.rename("#{@filename}", age_file)
- @dev = create_logfile(@filename)
- return true
- end
- end
-end
diff --git a/lib/logger/logger.gemspec b/lib/logger/logger.gemspec
deleted file mode 100644
index 5e8232e4ab..0000000000
--- a/lib/logger/logger.gemspec
+++ /dev/null
@@ -1,22 +0,0 @@
-begin
- require_relative "lib/logger/version"
-rescue LoadError # Fallback to load version file in ruby core repository
- require_relative "version"
-end
-
-Gem::Specification.new do |spec|
- spec.name = "logger"
- spec.version = Logger::VERSION
- spec.authors = ["Naotoshi Seo", "SHIBATA Hiroshi"]
- spec.email = ["sonots@gmail.com", "hsbt@ruby-lang.org"]
-
- spec.summary = %q{Provides a simple logging utility for outputting messages.}
- spec.description = %q{Provides a simple logging utility for outputting messages.}
- spec.homepage = "https://github.com/ruby/logger"
- spec.licenses = ["Ruby", "BSD-2-Clause"]
-
- spec.files = Dir.glob("lib/**/*.rb") + ["logger.gemspec"]
- spec.require_paths = ["lib"]
-
- spec.required_ruby_version = ">= 2.5.0"
-end
diff --git a/lib/logger/period.rb b/lib/logger/period.rb
deleted file mode 100644
index 0a291dbbbe..0000000000
--- a/lib/logger/period.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# frozen_string_literal: true
-
-class Logger
- module Period
- module_function
-
- SiD = 24 * 60 * 60
-
- def next_rotate_time(now, shift_age)
- case shift_age
- when 'daily'
- t = Time.mktime(now.year, now.month, now.mday) + SiD
- when 'weekly'
- t = Time.mktime(now.year, now.month, now.mday) + SiD * (7 - now.wday)
- when 'monthly'
- t = Time.mktime(now.year, now.month, 1) + SiD * 32
- return Time.mktime(t.year, t.month, 1)
- when 'now', 'everytime'
- return now
- else
- raise ArgumentError, "invalid :shift_age #{shift_age.inspect}, should be daily, weekly, monthly, or everytime"
- end
- if t.hour.nonzero? or t.min.nonzero? or t.sec.nonzero?
- hour = t.hour
- t = Time.mktime(t.year, t.month, t.mday)
- t += SiD if hour > 12
- end
- t
- end
-
- def previous_period_end(now, shift_age)
- case shift_age
- when 'daily'
- t = Time.mktime(now.year, now.month, now.mday) - SiD / 2
- when 'weekly'
- t = Time.mktime(now.year, now.month, now.mday) - (SiD * now.wday + SiD / 2)
- when 'monthly'
- t = Time.mktime(now.year, now.month, 1) - SiD / 2
- when 'now', 'everytime'
- return now
- else
- raise ArgumentError, "invalid :shift_age #{shift_age.inspect}, should be daily, weekly, monthly, or everytime"
- end
- Time.mktime(t.year, t.month, t.mday, 23, 59, 59)
- end
- end
-end
diff --git a/lib/logger/severity.rb b/lib/logger/severity.rb
deleted file mode 100644
index e96fb0d320..0000000000
--- a/lib/logger/severity.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-class Logger
- # Logging severity.
- module Severity
- # Low-level information, mostly for developers.
- DEBUG = 0
- # Generic (useful) information about system operation.
- INFO = 1
- # A warning.
- WARN = 2
- # A handleable error condition.
- ERROR = 3
- # An unhandleable error that results in a program crash.
- FATAL = 4
- # An unknown message that should always be logged.
- UNKNOWN = 5
-
- LEVELS = {
- "debug" => DEBUG,
- "info" => INFO,
- "warn" => WARN,
- "error" => ERROR,
- "fatal" => FATAL,
- "unknown" => UNKNOWN,
- }
- private_constant :LEVELS
-
- def self.coerce(severity)
- if severity.is_a?(Integer)
- severity
- else
- key = severity.to_s.downcase
- LEVELS[key] || raise(ArgumentError, "invalid log level: #{severity}")
- end
- end
- end
-end
diff --git a/lib/logger/version.rb b/lib/logger/version.rb
deleted file mode 100644
index 202b6e4fba..0000000000
--- a/lib/logger/version.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-# frozen_string_literal: true
-
-class Logger
- VERSION = "1.6.0"
-end
diff --git a/lib/mkmf.rb b/lib/mkmf.rb
index 73459ffeb9..38a5a15fb5 100644
--- a/lib/mkmf.rb
+++ b/lib/mkmf.rb
@@ -40,7 +40,7 @@ class Array # :nodoc:
end
##
-# mkmf.rb is used by Ruby C extensions to generate a Makefile which will
+# \Module \MakeMakefile is used by Ruby C extensions to generate a Makefile which will
# correctly compile and link the C extension to Ruby and a third-party
# library.
module MakeMakefile
@@ -419,7 +419,7 @@ MESSAGE
# disable ASAN leak reporting - conftest programs almost always don't bother
# to free their memory.
- envs['ASAN_OPTIONS'] = "detect_leaks=0" unless ENV.key?('ASAN_OPTIONS')
+ envs['LSAN_OPTIONS'] = "detect_leaks=0" unless ENV.key?('LSAN_OPTIONS')
return envs, expand[commands]
end
@@ -583,14 +583,15 @@ MSG
end
def libpathflag(libpath=$DEFLIBPATH|$LIBPATH)
+ libpathflags = nil
libpath.map{|x|
case x
when "$(topdir)", /\A\./
LIBPATHFLAG
else
- LIBPATHFLAG+RPATHFLAG
+ libpathflags ||= [LIBPATHFLAG, RPATHFLAG].grep(/\S/).join(" ")
end % x.quote
- }.join
+ }.join(" ")
end
def werror_flag(opt = nil)
@@ -603,9 +604,9 @@ MSG
yield(opt, opts)
end
- def try_link0(src, opt = "", **opts, &b) # :nodoc:
+ def try_link0(src, opt = "", ldflags: "", **opts, &b) # :nodoc:
exe = CONFTEST+$EXEEXT
- cmd = link_command("", opt)
+ cmd = link_command(ldflags, opt)
if $universal
require 'tmpdir'
Dir.mktmpdir("mkmf_", oldtmpdir = ENV["TMPDIR"]) do |tmpdir|
@@ -749,7 +750,7 @@ MSG
# :nodoc:
def try_ldflags(flags, werror: $mswin, **opts)
- try_link(MAIN_DOES_NOTHING, flags, werror: werror, **opts)
+ try_link(MAIN_DOES_NOTHING, "", ldflags: flags, werror: werror, **opts)
end
# :startdoc:
@@ -859,7 +860,7 @@ int main() {printf("%"PRI_CONFTEST_PREFIX"#{neg ? 'd' : 'u'}\\n", conftest_const
v
}
unless strvars.empty?
- prepare << "char " << strvars.map {|v| "#{v}[1024]"}.join(", ") << "; "
+ prepare << "char " << strvars.map {|v| %[#{v}[1024] = ""]}.join(", ") << "; "
end
when nil
call = ""
@@ -1967,7 +1968,7 @@ SRC
if pkgconfig = with_config("#{pkg}-config") and find_executable0(pkgconfig)
# if and only if package specific config command is given
elsif ($PKGCONFIG ||=
- (pkgconfig = with_config("pkg-config") {config_string("PKG_CONFIG") || "pkg-config"}) &&
+ (pkgconfig = with_config("pkg-config") {config_string("PKG_CONFIG") || ENV["PKG_CONFIG"] || "pkg-config"}) &&
find_executable0(pkgconfig) && pkgconfig) and
xsystem([*envs, $PKGCONFIG, "--exists", pkg])
# default to pkg-config command
@@ -1983,7 +1984,20 @@ SRC
opts = Array(opts).map { |o| "--#{o}" }
opts = xpopen([*envs, pkgconfig, *opts, *args], err:[:child, :out], &:read)
Logging.open {puts opts.each_line.map{|s|"=> #{s.inspect}"}}
- opts.strip if $?.success?
+ if $?.success?
+ opts = opts.strip
+ libarg, libpath = LIBARG, LIBPATHFLAG.strip
+ opts = opts.shellsplit.map { |s|
+ if s.start_with?('-l')
+ libarg % s[2..]
+ elsif s.start_with?('-L')
+ libpath % s[2..]
+ else
+ s
+ end
+ }.quote.join(" ")
+ opts
+ end
}
end
orig_ldflags = $LDFLAGS
@@ -2367,6 +2381,19 @@ RULES
# directory, i.e. the current directory. It is included as part of the
# +VPATH+ and added to the list of +INCFLAGS+.
#
+ # Yields the configuration part of the makefile to be generated, as an array
+ # of strings, if the block is given. The returned value will be used the
+ # new configuration part.
+ #
+ # create_makefile('foo') {|conf|
+ # [
+ # *conf,
+ # "MACRO_YOU_NEED = something",
+ # ]
+ # }
+ #
+ # If "depend" file exist in the source directory, that content will be
+ # included in the generated makefile, with formatted by depend_rules method.
def create_makefile(target, srcprefix = nil)
$target = target
libpath = $DEFLIBPATH|$LIBPATH
@@ -2483,16 +2510,19 @@ TIMESTAMP_DIR = #{$extout && $extmk ? '$(extout)/.timestamp' : '.'}
sodir = $extout ? '$(TARGET_SO_DIR)' : '$(RUBYARCHDIR)'
n = '$(TARGET_SO_DIR)$(TARGET)'
cleanobjs = ["$(OBJS)"]
+ cleanlibs = []
if $extmk
%w[bc i s].each {|ex| cleanobjs << "$(OBJS:.#{$OBJEXT}=.#{ex})"}
end
if target
config_string('cleanobjs') {|t| cleanobjs << t.gsub(/\$\*/, "$(TARGET)#{deffile ? '-$(arch)': ''}")}
+ cleanlibs << '$(TARGET_SO)'
end
+ config_string('cleanlibs') {|t| cleanlibs << t.gsub(/\$\*/) {n}}
conf << "\
TARGET_SO_DIR =#{$extout ? " $(RUBYARCHDIR)/" : ''}
TARGET_SO = $(TARGET_SO_DIR)$(DLLIB)
-CLEANLIBS = #{'$(TARGET_SO) ' if target}#{config_string('cleanlibs') {|t| t.gsub(/\$\*/) {n}}}
+CLEANLIBS = #{cleanlibs.join(' ')}
CLEANOBJS = #{cleanobjs.join(' ')} *.bak
TARGET_SO_DIR_TIMESTAMP = #{timestamp_file(sodir, target_prefix)}
" #"
@@ -2564,7 +2594,7 @@ static: #{$extmk && !$static ? "all" : %[$(STATIC_LIB)#{$extout ? " install-rb"
dest = "#{dir}/#{File.basename(f)}"
mfile.print("do-install-rb#{sfx}: #{dest}\n")
mfile.print("#{dest}: #{f} #{timestamp_file(dir, target_prefix)}\n")
- mfile.print("\t$(Q) $(#{$extout ? 'COPY' : 'INSTALL_DATA'}) #{f} $(@D)\n")
+ mfile.print("\t$(Q) $(#{$extout ? 'COPY' : 'INSTALL_DATA'}) #{f} $@\n")
if defined?($installed_list) and !$extout
mfile.print("\t@echo #{dest}>>$(INSTALLED_LIST)\n")
end
@@ -2906,7 +2936,7 @@ MESSAGE
##
# Argument which will add a library path to the linker
- LIBPATHFLAG = config_string('LIBPATHFLAG') || ' -L%s'
+ LIBPATHFLAG = config_string('LIBPATHFLAG') || '-L%s'
##
# Argument which will add a runtime library path to the linker
diff --git a/lib/net/http.rb b/lib/net/http.rb
index 958ff09f0e..98d6793aee 100644
--- a/lib/net/http.rb
+++ b/lib/net/http.rb
@@ -475,8 +475,7 @@ module Net #:nodoc:
#
# - {::start}[rdoc-ref:Net::HTTP.start]:
# Begins a new session in a new \Net::HTTP object.
- # - {#started?}[rdoc-ref:Net::HTTP#started?]
- # (aliased as {#active?}[rdoc-ref:Net::HTTP#active?]):
+ # - {#started?}[rdoc-ref:Net::HTTP#started?]:
# Returns whether in a session.
# - {#finish}[rdoc-ref:Net::HTTP#finish]:
# Ends an active session.
@@ -556,18 +555,15 @@ module Net #:nodoc:
# Sends a PUT request and returns a response object.
# - {#request}[rdoc-ref:Net::HTTP#request]:
# Sends a request and returns a response object.
- # - {#request_get}[rdoc-ref:Net::HTTP#request_get]
- # (aliased as {#get2}[rdoc-ref:Net::HTTP#get2]):
+ # - {#request_get}[rdoc-ref:Net::HTTP#request_get]:
# Sends a GET request and forms a response object;
# if a block given, calls the block with the object,
# otherwise returns the object.
- # - {#request_head}[rdoc-ref:Net::HTTP#request_head]
- # (aliased as {#head2}[rdoc-ref:Net::HTTP#head2]):
+ # - {#request_head}[rdoc-ref:Net::HTTP#request_head]:
# Sends a HEAD request and forms a response object;
# if a block given, calls the block with the object,
# otherwise returns the object.
- # - {#request_post}[rdoc-ref:Net::HTTP#request_post]
- # (aliased as {#post2}[rdoc-ref:Net::HTTP#post2]):
+ # - {#request_post}[rdoc-ref:Net::HTTP#request_post]:
# Sends a POST request and forms a response object;
# if a block given, calls the block with the object,
# otherwise returns the object.
@@ -605,8 +601,7 @@ module Net #:nodoc:
# Returns whether +self+ is a proxy class.
# - {#proxy?}[rdoc-ref:Net::HTTP#proxy?]:
# Returns whether +self+ has a proxy.
- # - {#proxy_address}[rdoc-ref:Net::HTTP#proxy_address]
- # (aliased as {#proxyaddr}[rdoc-ref:Net::HTTP#proxyaddr]):
+ # - {#proxy_address}[rdoc-ref:Net::HTTP#proxy_address]:
# Returns the proxy address.
# - {#proxy_from_env?}[rdoc-ref:Net::HTTP#proxy_from_env?]:
# Returns whether the proxy is taken from an environment variable.
@@ -718,8 +713,7 @@ module Net #:nodoc:
# === \HTTP Version
#
# - {::version_1_2?}[rdoc-ref:Net::HTTP.version_1_2?]
- # (aliased as {::is_version_1_2?}[rdoc-ref:Net::HTTP.is_version_1_2?]
- # and {::version_1_2}[rdoc-ref:Net::HTTP.version_1_2]):
+ # (aliased as {::version_1_2}[rdoc-ref:Net::HTTP.version_1_2]):
# Returns true; retained for compatibility.
#
# === Debugging
@@ -730,7 +724,7 @@ module Net #:nodoc:
class HTTP < Protocol
# :stopdoc:
- VERSION = "0.4.1"
+ VERSION = "0.9.1"
HTTPVersion = '1.1'
begin
require 'zlib'
@@ -1103,7 +1097,7 @@ module Net #:nodoc:
# For proxy-defining arguments +p_addr+ through +p_no_proxy+,
# see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
#
- def HTTP.new(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, p_no_proxy = nil)
+ def HTTP.new(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, p_no_proxy = nil, p_use_ssl = nil)
http = super address, port
if proxy_class? then # from Net::HTTP::Proxy()
@@ -1112,6 +1106,7 @@ module Net #:nodoc:
http.proxy_port = @proxy_port
http.proxy_user = @proxy_user
http.proxy_pass = @proxy_pass
+ http.proxy_use_ssl = @proxy_use_ssl
elsif p_addr == :ENV then
http.proxy_from_env = true
else
@@ -1123,34 +1118,68 @@ module Net #:nodoc:
http.proxy_port = p_port || default_port
http.proxy_user = p_user
http.proxy_pass = p_pass
+ http.proxy_use_ssl = p_use_ssl
end
http
end
+ class << HTTP
+ # Allows to set the default configuration that will be used
+ # when creating a new connection.
+ #
+ # Example:
+ #
+ # Net::HTTP.default_configuration = {
+ # read_timeout: 1,
+ # write_timeout: 1
+ # }
+ # http = Net::HTTP.new(hostname)
+ # http.open_timeout # => 60
+ # http.read_timeout # => 1
+ # http.write_timeout # => 1
+ #
+ attr_accessor :default_configuration
+ end
+
# Creates a new \Net::HTTP object for the specified server address,
# without opening the TCP connection or initializing the \HTTP session.
# The +address+ should be a DNS hostname or IP address.
def initialize(address, port = nil) # :nodoc:
+ defaults = {
+ keep_alive_timeout: 2,
+ close_on_empty_response: false,
+ open_timeout: 60,
+ read_timeout: 60,
+ write_timeout: 60,
+ continue_timeout: nil,
+ max_retries: 1,
+ debug_output: nil,
+ response_body_encoding: false,
+ ignore_eof: true
+ }
+ options = defaults.merge(self.class.default_configuration || {})
+
@address = address
@port = (port || HTTP.default_port)
@ipaddr = nil
@local_host = nil
@local_port = nil
@curr_http_version = HTTPVersion
- @keep_alive_timeout = 2
+ @keep_alive_timeout = options[:keep_alive_timeout]
@last_communicated = nil
- @close_on_empty_response = false
+ @close_on_empty_response = options[:close_on_empty_response]
@socket = nil
@started = false
- @open_timeout = 60
- @read_timeout = 60
- @write_timeout = 60
- @continue_timeout = nil
- @max_retries = 1
- @debug_output = nil
- @response_body_encoding = false
- @ignore_eof = true
+ @open_timeout = options[:open_timeout]
+ @read_timeout = options[:read_timeout]
+ @write_timeout = options[:write_timeout]
+ @continue_timeout = options[:continue_timeout]
+ @max_retries = options[:max_retries]
+ @debug_output = options[:debug_output]
+ @response_body_encoding = options[:response_body_encoding]
+ @ignore_eof = options[:ignore_eof]
+ @tcpsocket_supports_open_timeout = nil
@proxy_from_env = false
@proxy_uri = nil
@@ -1158,6 +1187,7 @@ module Net #:nodoc:
@proxy_port = nil
@proxy_user = nil
@proxy_pass = nil
+ @proxy_use_ssl = nil
@use_ssl = false
@ssl_context = nil
@@ -1293,6 +1323,10 @@ module Net #:nodoc:
# see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
attr_writer :proxy_pass
+ # Sets whether the proxy uses SSL;
+ # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server].
+ attr_writer :proxy_use_ssl
+
# Returns the IP address for the connection.
#
# If the session has not been started,
@@ -1481,23 +1515,6 @@ module Net #:nodoc:
@use_ssl = flag
end
- SSL_IVNAMES = [
- :@ca_file,
- :@ca_path,
- :@cert,
- :@cert_store,
- :@ciphers,
- :@extra_chain_cert,
- :@key,
- :@ssl_timeout,
- :@ssl_version,
- :@min_version,
- :@max_version,
- :@verify_callback,
- :@verify_depth,
- :@verify_mode,
- :@verify_hostname,
- ] # :nodoc:
SSL_ATTRIBUTES = [
:ca_file,
:ca_path,
@@ -1514,7 +1531,9 @@ module Net #:nodoc:
:verify_depth,
:verify_mode,
:verify_hostname,
- ] # :nodoc:
+ ].freeze # :nodoc:
+
+ SSL_IVNAMES = SSL_ATTRIBUTES.map { |a| "@#{a}".to_sym }.freeze # :nodoc:
# Sets or returns the path to a CA certification file in PEM format.
attr_accessor :ca_file
@@ -1531,11 +1550,11 @@ module Net #:nodoc:
attr_accessor :cert_store
# Sets or returns the available SSL ciphers.
- # See {OpenSSL::SSL::SSLContext#ciphers=}[rdoc-ref:OpenSSL::SSL::SSLContext#ciphers-3D].
+ # See {OpenSSL::SSL::SSLContext#ciphers=}[OpenSSL::SSL::SSL::Context#ciphers=].
attr_accessor :ciphers
# Sets or returns the extra X509 certificates to be added to the certificate chain.
- # See {OpenSSL::SSL::SSLContext#add_certificate}[rdoc-ref:OpenSSL::SSL::SSLContext#add_certificate].
+ # See {OpenSSL::SSL::SSLContext#add_certificate}[OpenSSL::SSL::SSL::Context#add_certificate].
attr_accessor :extra_chain_cert
# Sets or returns the OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object.
@@ -1545,15 +1564,15 @@ module Net #:nodoc:
attr_accessor :ssl_timeout
# Sets or returns the SSL version.
- # See {OpenSSL::SSL::SSLContext#ssl_version=}[rdoc-ref:OpenSSL::SSL::SSLContext#ssl_version-3D].
+ # See {OpenSSL::SSL::SSLContext#ssl_version=}[OpenSSL::SSL::SSL::Context#ssl_version=].
attr_accessor :ssl_version
# Sets or returns the minimum SSL version.
- # See {OpenSSL::SSL::SSLContext#min_version=}[rdoc-ref:OpenSSL::SSL::SSLContext#min_version-3D].
+ # See {OpenSSL::SSL::SSLContext#min_version=}[OpenSSL::SSL::SSL::Context#min_version=].
attr_accessor :min_version
# Sets or returns the maximum SSL version.
- # See {OpenSSL::SSL::SSLContext#max_version=}[rdoc-ref:OpenSSL::SSL::SSLContext#max_version-3D].
+ # See {OpenSSL::SSL::SSLContext#max_version=}[OpenSSL::SSL::SSL::Context#max_version=].
attr_accessor :max_version
# Sets or returns the callback for the server certification verification.
@@ -1569,7 +1588,7 @@ module Net #:nodoc:
# Sets or returns whether to verify that the server certificate is valid
# for the hostname.
- # See {OpenSSL::SSL::SSLContext#verify_hostname=}[rdoc-ref:OpenSSL::SSL::SSLContext#attribute-i-verify_mode].
+ # See {OpenSSL::SSL::SSLContext#verify_hostname=}[OpenSSL::SSL::SSL::Context#verify_hostname=].
attr_accessor :verify_hostname
# Returns the X509 certificate chain (an array of strings)
@@ -1617,6 +1636,21 @@ module Net #:nodoc:
self
end
+ # Finishes the \HTTP session:
+ #
+ # http = Net::HTTP.new(hostname)
+ # http.start
+ # http.started? # => true
+ # http.finish # => nil
+ # http.started? # => false
+ #
+ # Raises IOError if not in a session.
+ def finish
+ raise IOError, 'HTTP session not yet started' unless started?
+ do_finish
+ end
+
+ # :stopdoc:
def do_start
connect
@started = true
@@ -1639,19 +1673,26 @@ module Net #:nodoc:
end
debug "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})"
+ begin
+ s = timeouted_connect(conn_addr, conn_port)
+ rescue => e
+ if (defined?(IO::TimeoutError) && e.is_a?(IO::TimeoutError)) || e.is_a?(Errno::ETIMEDOUT) # for compatibility with previous versions
+ e = Net::OpenTimeout.new(e)
end
- }
+ raise e, "Failed to open TCP connection to " +
+ "#{conn_addr}:#{conn_port} (#{e.message})"
+ end
s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
debug "opened"
if use_ssl?
if proxy?
- plain_sock = BufferedIO.new(s, read_timeout: @read_timeout,
+ if @proxy_use_ssl
+ proxy_sock = OpenSSL::SSL::SSLSocket.new(s)
+ ssl_socket_connect(proxy_sock, @open_timeout)
+ else
+ proxy_sock = s
+ end
+ proxy_sock = BufferedIO.new(proxy_sock, read_timeout: @read_timeout,
write_timeout: @write_timeout,
continue_timeout: @continue_timeout,
debug_output: @debug_output)
@@ -1662,8 +1703,8 @@ module Net #:nodoc:
buf << "Proxy-Authorization: Basic #{credential}\r\n"
end
buf << "\r\n"
- plain_sock.write(buf)
- HTTPResponse.read_new(plain_sock).value
+ proxy_sock.write(buf)
+ HTTPResponse.read_new(proxy_sock).value
# assuming nothing left in buffers after successful CONNECT response
end
@@ -1733,23 +1774,30 @@ module Net #:nodoc:
end
private :connect
- def on_connect
+ tcp_socket_parameters = TCPSocket.instance_method(:initialize).parameters
+ TCP_SOCKET_NEW_HAS_OPEN_TIMEOUT = if tcp_socket_parameters != [[:rest]]
+ tcp_socket_parameters.include?([:key, :open_timeout])
+ else
+ # Use Socket.tcp to find out since there is no parameters information for TCPSocket#initialize
+ # See discussion in https://github.com/ruby/net-http/pull/224
+ Socket.method(:tcp).parameters.include?([:key, :open_timeout])
end
- private :on_connect
+ private_constant :TCP_SOCKET_NEW_HAS_OPEN_TIMEOUT
- # Finishes the \HTTP session:
- #
- # http = Net::HTTP.new(hostname)
- # http.start
- # http.started? # => true
- # http.finish # => nil
- # http.started? # => false
- #
- # Raises IOError if not in a session.
- def finish
- raise IOError, 'HTTP session not yet started' unless started?
- do_finish
+ def timeouted_connect(conn_addr, conn_port)
+ if TCP_SOCKET_NEW_HAS_OPEN_TIMEOUT
+ TCPSocket.open(conn_addr, conn_port, @local_host, @local_port, open_timeout: @open_timeout)
+ else
+ Timeout.timeout(@open_timeout, Net::OpenTimeout) {
+ TCPSocket.open(conn_addr, conn_port, @local_host, @local_port)
+ }
+ end
end
+ private :timeouted_connect
+
+ def on_connect
+ end
+ private :on_connect
def do_finish
@started = false
@@ -1771,13 +1819,14 @@ module Net #:nodoc:
@proxy_port = nil
@proxy_user = nil
@proxy_pass = nil
+ @proxy_use_ssl = nil
# Creates an \HTTP proxy class which behaves like \Net::HTTP, but
# performs all access via the specified proxy.
#
# This class is obsolete. You may pass these same parameters directly to
# \Net::HTTP.new. See Net::HTTP.new for details of the arguments.
- def HTTP.Proxy(p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil) #:nodoc:
+ def HTTP.Proxy(p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, p_use_ssl = nil) #:nodoc:
return self unless p_addr
Class.new(self) {
@@ -1795,9 +1844,12 @@ module Net #:nodoc:
@proxy_user = p_user
@proxy_pass = p_pass
+ @proxy_use_ssl = p_use_ssl
}
end
+ # :startdoc:
+
class << HTTP
# Returns true if self is a class which was created by HTTP::Proxy.
def proxy_class?
@@ -1819,6 +1871,9 @@ module Net #:nodoc:
# Returns the password for accessing the proxy, or +nil+ if none;
# see Net::HTTP@Proxy+Server.
attr_reader :proxy_pass
+
+ # Use SSL when talking to the proxy. If Net::HTTP does not use a proxy, nil.
+ attr_reader :proxy_use_ssl
end
# Returns +true+ if a proxy server is defined, +false+ otherwise;
@@ -1889,9 +1944,11 @@ module Net #:nodoc:
alias proxyport proxy_port #:nodoc: obsolete
private
+ # :stopdoc:
def unescape(value)
- require 'cgi/util'
+ require 'cgi/escape'
+ require 'cgi/util' unless defined?(CGI::EscapeExt)
CGI.unescape(value)
end
@@ -1916,6 +1973,7 @@ module Net #:nodoc:
path
end
end
+ # :startdoc:
#
# HTTP operations
@@ -2370,7 +2428,9 @@ module Net #:nodoc:
res
end
- IDEMPOTENT_METHODS_ = %w/GET HEAD PUT DELETE OPTIONS TRACE/ # :nodoc:
+ # :stopdoc:
+
+ IDEMPOTENT_METHODS_ = %w/GET HEAD PUT DELETE OPTIONS TRACE/.freeze # :nodoc:
def transport_request(req)
count = 0
@@ -2527,6 +2587,11 @@ module Net #:nodoc:
alias_method :D, :debug
end
+ # for backward compatibility until Ruby 4.0
+ # https://bugs.ruby-lang.org/issues/20900
+ # https://github.com/bblimke/webmock/pull/1081
+ HTTPSession = HTTP
+ deprecate_constant :HTTPSession
end
require_relative 'http/exceptions'
@@ -2541,5 +2606,3 @@ require_relative 'http/response'
require_relative 'http/responses'
require_relative 'http/proxy_delta'
-
-require_relative 'http/backward'
diff --git a/lib/net/http/backward.rb b/lib/net/http/backward.rb
deleted file mode 100644
index b44577edbd..0000000000
--- a/lib/net/http/backward.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-# for backward compatibility
-
-# :enddoc:
-
-class Net::HTTP
- ProxyMod = ProxyDelta
- deprecate_constant :ProxyMod
-end
-
-module Net::NetPrivate
- HTTPRequest = ::Net::HTTPRequest
- deprecate_constant :HTTPRequest
-end
-
-module Net
- HTTPSession = HTTP
-
- HTTPInformationCode = HTTPInformation
- HTTPSuccessCode = HTTPSuccess
- HTTPRedirectionCode = HTTPRedirection
- HTTPRetriableCode = HTTPRedirection
- HTTPClientErrorCode = HTTPClientError
- HTTPFatalErrorCode = HTTPClientError
- HTTPServerErrorCode = HTTPServerError
- HTTPResponseReceiver = HTTPResponse
-
- HTTPResponceReceiver = HTTPResponse # Typo since 2001
-
- deprecate_constant :HTTPSession,
- :HTTPInformationCode,
- :HTTPSuccessCode,
- :HTTPRedirectionCode,
- :HTTPRetriableCode,
- :HTTPClientErrorCode,
- :HTTPFatalErrorCode,
- :HTTPServerErrorCode,
- :HTTPResponseReceiver,
- :HTTPResponceReceiver
-end
diff --git a/lib/net/http/exceptions.rb b/lib/net/http/exceptions.rb
index ceec8f7b0a..4342cfc0ef 100644
--- a/lib/net/http/exceptions.rb
+++ b/lib/net/http/exceptions.rb
@@ -3,7 +3,7 @@ module Net
# Net::HTTP exception class.
# You cannot use Net::HTTPExceptions directly; instead, you must use
# its subclasses.
- module HTTPExceptions
+ module HTTPExceptions # :nodoc:
def initialize(msg, res) #:nodoc:
super msg
@response = res
@@ -12,6 +12,7 @@ module Net
alias data response #:nodoc: obsolete
end
+ # :stopdoc:
class HTTPError < ProtocolError
include HTTPExceptions
end
diff --git a/lib/net/http/generic_request.rb b/lib/net/http/generic_request.rb
index 44e329a0c8..5b01ea4abd 100644
--- a/lib/net/http/generic_request.rb
+++ b/lib/net/http/generic_request.rb
@@ -19,16 +19,13 @@ class Net::HTTPGenericRequest
if URI === uri_or_path then
raise ArgumentError, "not an HTTP URI" unless URI::HTTP === uri_or_path
- hostname = uri_or_path.hostname
+ hostname = uri_or_path.host
raise ArgumentError, "no host component for URI" unless (hostname && hostname.length > 0)
@uri = uri_or_path.dup
- host = @uri.hostname.dup
- host << ":" << @uri.port.to_s if @uri.port != @uri.default_port
@path = uri_or_path.request_uri
raise ArgumentError, "no HTTP request path given" unless @path
else
@uri = nil
- host = nil
raise ArgumentError, "no HTTP request path given" unless uri_or_path
raise ArgumentError, "HTTP request path is empty" if uri_or_path.empty?
@path = uri_or_path.dup
@@ -51,7 +48,7 @@ class Net::HTTPGenericRequest
initialize_http_header initheader
self['Accept'] ||= '*/*'
self['User-Agent'] ||= 'Ruby'
- self['Host'] ||= host if host
+ self['Host'] ||= @uri.authority if @uri
@body = nil
@body_stream = nil
@body_data = nil
@@ -102,6 +99,31 @@ class Net::HTTPGenericRequest
"\#<#{self.class} #{@method}>"
end
+ # Returns a string representation of the request with the details for pp:
+ #
+ # require 'pp'
+ # post = Net::HTTP::Post.new(uri)
+ # post.inspect # => "#<Net::HTTP::Post POST>"
+ # post.pretty_inspect
+ # # => #<Net::HTTP::Post
+ # POST
+ # path="/"
+ # headers={"accept-encoding" => ["gzip;q=1.0,deflate;q=0.6,identity;q=0.3"],
+ # "accept" => ["*/*"],
+ # "user-agent" => ["Ruby"],
+ # "host" => ["www.ruby-lang.org"]}>
+ #
+ def pretty_print(q)
+ q.object_group(self) {
+ q.breakable
+ q.text @method
+ q.breakable
+ q.text "path="; q.pp @path
+ q.breakable
+ q.text "headers="; q.pp to_hash
+ }
+ end
+
##
# Don't automatically decode response content-encoding if the user indicates
# they want to handle it.
@@ -220,7 +242,7 @@ class Net::HTTPGenericRequest
end
if host = self['host']
- host.sub!(/:.*/m, '')
+ host = URI.parse("//#{host}").host # Remove a port component from the existing Host header
elsif host = @uri.host
else
host = addr
@@ -239,6 +261,8 @@ class Net::HTTPGenericRequest
private
+ # :stopdoc:
+
class Chunker #:nodoc:
def initialize(sock)
@sock = sock
@@ -260,7 +284,6 @@ class Net::HTTPGenericRequest
def send_request_with_body(sock, ver, path, body)
self.content_length = body.bytesize
delete 'Transfer-Encoding'
- supply_default_content_type
write_header sock, ver, path
wait_for_continue sock, ver if sock.continue_timeout
sock.write body
@@ -271,7 +294,6 @@ class Net::HTTPGenericRequest
raise ArgumentError,
"Content-Length not given and Transfer-Encoding is not `chunked'"
end
- supply_default_content_type
write_header sock, ver, path
wait_for_continue sock, ver if sock.continue_timeout
if chunked?
@@ -373,12 +395,6 @@ class Net::HTTPGenericRequest
buf.clear
end
- def supply_default_content_type
- return if content_type()
- warn 'net/http: Content-Type did not set; using application/x-www-form-urlencoded', uplevel: 1 if $VERBOSE
- set_content_type 'application/x-www-form-urlencoded'
- end
-
##
# Waits up to the continue timeout for a response from the server provided
# we're speaking HTTP 1.1 and are expecting a 100-continue response.
@@ -411,4 +427,3 @@ class Net::HTTPGenericRequest
end
end
-
diff --git a/lib/net/http/header.rb b/lib/net/http/header.rb
index f6c36f1b5e..5dcdcc7d74 100644
--- a/lib/net/http/header.rb
+++ b/lib/net/http/header.rb
@@ -179,7 +179,9 @@
# - #each_value: Passes each string field value to the block.
#
module Net::HTTPHeader
+ # The maximum length of HTTP header keys.
MAX_KEY_LENGTH = 1024
+ # The maximum length of HTTP header values.
MAX_FIELD_LENGTH = 65536
def initialize_http_header(initheader) #:nodoc:
@@ -267,6 +269,7 @@ module Net::HTTPHeader
end
end
+ # :stopdoc:
private def set_field(key, val)
case val
when Enumerable
@@ -294,6 +297,7 @@ module Net::HTTPHeader
ary.push val
end
end
+ # :startdoc:
# Returns the array field value for the given +key+,
# or +nil+ if there is no such field;
@@ -490,7 +494,7 @@ module Net::HTTPHeader
alias canonical_each each_capitalized
- def capitalize(name)
+ def capitalize(name) # :nodoc:
name.to_s.split('-'.freeze).map {|s| s.capitalize }.join('-'.freeze)
end
private :capitalize
@@ -957,12 +961,12 @@ module Net::HTTPHeader
@header['proxy-authorization'] = [basic_encode(account, password)]
end
- def basic_encode(account, password)
+ def basic_encode(account, password) # :nodoc:
'Basic ' + ["#{account}:#{password}"].pack('m0')
end
private :basic_encode
-# Returns whether the HTTP session is to be closed.
+ # Returns whether the HTTP session is to be closed.
def connection_close?
token = /(?:\A|,)\s*close\s*(?:\z|,)/i
@header['connection']&.grep(token) {return true}
@@ -970,7 +974,7 @@ module Net::HTTPHeader
false
end
-# Returns whether the HTTP session is to be kept alive.
+ # Returns whether the HTTP session is to be kept alive.
def connection_keep_alive?
token = /(?:\A|,)\s*keep-alive\s*(?:\z|,)/i
@header['connection']&.grep(token) {return true}
diff --git a/lib/net/http/net-http.gemspec b/lib/net/http/net-http.gemspec
index 0021136793..80e94c7bb6 100644
--- a/lib/net/http/net-http.gemspec
+++ b/lib/net/http/net-http.gemspec
@@ -21,19 +21,19 @@ Gem::Specification.new do |spec|
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.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
spec.licenses = ["Ruby", "BSD-2-Clause"]
+ spec.metadata["changelog_uri"] = spec.homepage + "/releases"
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
# Specify which files should be added to the gem when it is released.
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
- `git ls-files -z 2>#{IO::NULL}`.split("\x0").reject { |f| f.match(%r{\A(?:(?:test|spec|features)/|\.git)}) }
- end
+ excludes = %W[/.git* /bin /test /*file /#{File.basename(__FILE__)}]
+ spec.files = IO.popen(%W[git -C #{__dir__} ls-files -z --] + excludes.map {|e| ":^#{e}"}, &:read).split("\x0")
spec.bindir = "exe"
spec.require_paths = ["lib"]
- spec.add_dependency "uri"
+ spec.add_dependency "uri", ">= 0.11.1"
end
diff --git a/lib/net/http/requests.rb b/lib/net/http/requests.rb
index e58057adf1..939d413f91 100644
--- a/lib/net/http/requests.rb
+++ b/lib/net/http/requests.rb
@@ -29,6 +29,7 @@
# - Net::HTTP#get: sends +GET+ request, returns response object.
#
class Net::HTTP::Get < Net::HTTPRequest
+ # :stopdoc:
METHOD = 'GET'
REQUEST_HAS_BODY = false
RESPONSE_HAS_BODY = true
@@ -60,6 +61,7 @@ end
# - Net::HTTP#head: sends +HEAD+ request, returns response object.
#
class Net::HTTP::Head < Net::HTTPRequest
+ # :stopdoc:
METHOD = 'HEAD'
REQUEST_HAS_BODY = false
RESPONSE_HAS_BODY = false
@@ -95,6 +97,7 @@ end
# - Net::HTTP#post: sends +POST+ request, returns response object.
#
class Net::HTTP::Post < Net::HTTPRequest
+ # :stopdoc:
METHOD = 'POST'
REQUEST_HAS_BODY = true
RESPONSE_HAS_BODY = true
@@ -130,6 +133,7 @@ end
# - Net::HTTP#put: sends +PUT+ request, returns response object.
#
class Net::HTTP::Put < Net::HTTPRequest
+ # :stopdoc:
METHOD = 'PUT'
REQUEST_HAS_BODY = true
RESPONSE_HAS_BODY = true
@@ -162,6 +166,7 @@ end
# - Net::HTTP#delete: sends +DELETE+ request, returns response object.
#
class Net::HTTP::Delete < Net::HTTPRequest
+ # :stopdoc:
METHOD = 'DELETE'
REQUEST_HAS_BODY = false
RESPONSE_HAS_BODY = true
@@ -193,6 +198,7 @@ end
# - Net::HTTP#options: sends +OPTIONS+ request, returns response object.
#
class Net::HTTP::Options < Net::HTTPRequest
+ # :stopdoc:
METHOD = 'OPTIONS'
REQUEST_HAS_BODY = false
RESPONSE_HAS_BODY = true
@@ -224,6 +230,7 @@ end
# - Net::HTTP#trace: sends +TRACE+ request, returns response object.
#
class Net::HTTP::Trace < Net::HTTPRequest
+ # :stopdoc:
METHOD = 'TRACE'
REQUEST_HAS_BODY = false
RESPONSE_HAS_BODY = true
@@ -258,6 +265,7 @@ end
# - Net::HTTP#patch: sends +PATCH+ request, returns response object.
#
class Net::HTTP::Patch < Net::HTTPRequest
+ # :stopdoc:
METHOD = 'PATCH'
REQUEST_HAS_BODY = true
RESPONSE_HAS_BODY = true
@@ -285,6 +293,7 @@ end
# - Net::HTTP#propfind: sends +PROPFIND+ request, returns response object.
#
class Net::HTTP::Propfind < Net::HTTPRequest
+ # :stopdoc:
METHOD = 'PROPFIND'
REQUEST_HAS_BODY = true
RESPONSE_HAS_BODY = true
@@ -308,6 +317,7 @@ end
# - Net::HTTP#proppatch: sends +PROPPATCH+ request, returns response object.
#
class Net::HTTP::Proppatch < Net::HTTPRequest
+ # :stopdoc:
METHOD = 'PROPPATCH'
REQUEST_HAS_BODY = true
RESPONSE_HAS_BODY = true
@@ -331,6 +341,7 @@ end
# - Net::HTTP#mkcol: sends +MKCOL+ request, returns response object.
#
class Net::HTTP::Mkcol < Net::HTTPRequest
+ # :stopdoc:
METHOD = 'MKCOL'
REQUEST_HAS_BODY = true
RESPONSE_HAS_BODY = true
@@ -354,6 +365,7 @@ end
# - Net::HTTP#copy: sends +COPY+ request, returns response object.
#
class Net::HTTP::Copy < Net::HTTPRequest
+ # :stopdoc:
METHOD = 'COPY'
REQUEST_HAS_BODY = false
RESPONSE_HAS_BODY = true
@@ -377,6 +389,7 @@ end
# - Net::HTTP#move: sends +MOVE+ request, returns response object.
#
class Net::HTTP::Move < Net::HTTPRequest
+ # :stopdoc:
METHOD = 'MOVE'
REQUEST_HAS_BODY = false
RESPONSE_HAS_BODY = true
@@ -400,6 +413,7 @@ end
# - Net::HTTP#lock: sends +LOCK+ request, returns response object.
#
class Net::HTTP::Lock < Net::HTTPRequest
+ # :stopdoc:
METHOD = 'LOCK'
REQUEST_HAS_BODY = true
RESPONSE_HAS_BODY = true
@@ -423,8 +437,8 @@ end
# - Net::HTTP#unlock: sends +UNLOCK+ request, returns response object.
#
class Net::HTTP::Unlock < Net::HTTPRequest
+ # :stopdoc:
METHOD = 'UNLOCK'
REQUEST_HAS_BODY = true
RESPONSE_HAS_BODY = true
end
-
diff --git a/lib/net/http/response.rb b/lib/net/http/response.rb
index 40de963868..8804a99c9e 100644
--- a/lib/net/http/response.rb
+++ b/lib/net/http/response.rb
@@ -153,6 +153,7 @@ class Net::HTTPResponse
end
private
+ # :stopdoc:
def read_status_line(sock)
str = sock.readline
@@ -259,7 +260,7 @@ class Net::HTTPResponse
# header.
attr_accessor :ignore_eof
- def inspect
+ def inspect # :nodoc:
"#<#{self.class} #{@code} #{@message} readbody=#{@read}>"
end
diff --git a/lib/net/http/responses.rb b/lib/net/http/responses.rb
index 6f6fb8d055..941a6fed80 100644
--- a/lib/net/http/responses.rb
+++ b/lib/net/http/responses.rb
@@ -4,7 +4,9 @@
module Net
+ # Unknown HTTP response
class HTTPUnknownResponse < HTTPResponse
+ # :stopdoc:
HAS_BODY = true
EXCEPTION_TYPE = HTTPError #
end
@@ -19,6 +21,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#1xx_informational_response].
#
class HTTPInformation < HTTPResponse
+ # :stopdoc:
HAS_BODY = false
EXCEPTION_TYPE = HTTPError #
end
@@ -34,6 +37,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#2xx_success].
#
class HTTPSuccess < HTTPResponse
+ # :stopdoc:
HAS_BODY = true
EXCEPTION_TYPE = HTTPError #
end
@@ -49,6 +53,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#3xx_redirection].
#
class HTTPRedirection < HTTPResponse
+ # :stopdoc:
HAS_BODY = true
EXCEPTION_TYPE = HTTPRetriableError #
end
@@ -63,6 +68,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#4xx_client_errors].
#
class HTTPClientError < HTTPResponse
+ # :stopdoc:
HAS_BODY = true
EXCEPTION_TYPE = HTTPClientException #
end
@@ -77,6 +83,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#5xx_server_errors].
#
class HTTPServerError < HTTPResponse
+ # :stopdoc:
HAS_BODY = true
EXCEPTION_TYPE = HTTPFatalError #
end
@@ -94,6 +101,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#100].
#
class HTTPContinue < HTTPInformation
+ # :stopdoc:
HAS_BODY = false
end
@@ -111,6 +119,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#101].
#
class HTTPSwitchProtocol < HTTPInformation
+ # :stopdoc:
HAS_BODY = false
end
@@ -127,6 +136,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#102].
#
class HTTPProcessing < HTTPInformation
+ # :stopdoc:
HAS_BODY = false
end
@@ -145,6 +155,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#103].
#
class HTTPEarlyHints < HTTPInformation
+ # :stopdoc:
HAS_BODY = false
end
@@ -162,6 +173,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#200].
#
class HTTPOK < HTTPSuccess
+ # :stopdoc:
HAS_BODY = true
end
@@ -179,6 +191,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#201].
#
class HTTPCreated < HTTPSuccess
+ # :stopdoc:
HAS_BODY = true
end
@@ -196,6 +209,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#202].
#
class HTTPAccepted < HTTPSuccess
+ # :stopdoc:
HAS_BODY = true
end
@@ -215,6 +229,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#203].
#
class HTTPNonAuthoritativeInformation < HTTPSuccess
+ # :stopdoc:
HAS_BODY = true
end
@@ -232,6 +247,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#204].
#
class HTTPNoContent < HTTPSuccess
+ # :stopdoc:
HAS_BODY = false
end
@@ -250,6 +266,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#205].
#
class HTTPResetContent < HTTPSuccess
+ # :stopdoc:
HAS_BODY = false
end
@@ -268,6 +285,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#206].
#
class HTTPPartialContent < HTTPSuccess
+ # :stopdoc:
HAS_BODY = true
end
@@ -285,6 +303,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#207].
#
class HTTPMultiStatus < HTTPSuccess
+ # :stopdoc:
HAS_BODY = true
end
@@ -304,6 +323,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#208].
#
class HTTPAlreadyReported < HTTPSuccess
+ # :stopdoc:
HAS_BODY = true
end
@@ -321,6 +341,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#226].
#
class HTTPIMUsed < HTTPSuccess
+ # :stopdoc:
HAS_BODY = true
end
@@ -338,6 +359,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#300].
#
class HTTPMultipleChoices < HTTPRedirection
+ # :stopdoc:
HAS_BODY = true
end
HTTPMultipleChoice = HTTPMultipleChoices
@@ -356,6 +378,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#301].
#
class HTTPMovedPermanently < HTTPRedirection
+ # :stopdoc:
HAS_BODY = true
end
@@ -373,6 +396,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#302].
#
class HTTPFound < HTTPRedirection
+ # :stopdoc:
HAS_BODY = true
end
HTTPMovedTemporarily = HTTPFound
@@ -390,6 +414,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#303].
#
class HTTPSeeOther < HTTPRedirection
+ # :stopdoc:
HAS_BODY = true
end
@@ -407,6 +432,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#304].
#
class HTTPNotModified < HTTPRedirection
+ # :stopdoc:
HAS_BODY = false
end
@@ -423,6 +449,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#305].
#
class HTTPUseProxy < HTTPRedirection
+ # :stopdoc:
HAS_BODY = false
end
@@ -440,6 +467,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#307].
#
class HTTPTemporaryRedirect < HTTPRedirection
+ # :stopdoc:
HAS_BODY = true
end
@@ -456,6 +484,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#308].
#
class HTTPPermanentRedirect < HTTPRedirection
+ # :stopdoc:
HAS_BODY = true
end
@@ -472,6 +501,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#400].
#
class HTTPBadRequest < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -488,6 +518,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#401].
#
class HTTPUnauthorized < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -504,6 +535,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#402].
#
class HTTPPaymentRequired < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -521,6 +553,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#403].
#
class HTTPForbidden < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -537,6 +570,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#404].
#
class HTTPNotFound < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -553,6 +587,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#405].
#
class HTTPMethodNotAllowed < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -570,6 +605,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#406].
#
class HTTPNotAcceptable < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -586,6 +622,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#407].
#
class HTTPProxyAuthenticationRequired < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -602,6 +639,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#408].
#
class HTTPRequestTimeout < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
HTTPRequestTimeOut = HTTPRequestTimeout
@@ -619,6 +657,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#409].
#
class HTTPConflict < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -636,6 +675,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#410].
#
class HTTPGone < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -653,6 +693,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#411].
#
class HTTPLengthRequired < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -670,6 +711,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#412].
#
class HTTPPreconditionFailed < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -686,6 +728,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#413].
#
class HTTPPayloadTooLarge < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
HTTPRequestEntityTooLarge = HTTPPayloadTooLarge
@@ -703,6 +746,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#414].
#
class HTTPURITooLong < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
HTTPRequestURITooLong = HTTPURITooLong
@@ -721,6 +765,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#415].
#
class HTTPUnsupportedMediaType < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -737,6 +782,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#416].
#
class HTTPRangeNotSatisfiable < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
HTTPRequestedRangeNotSatisfiable = HTTPRangeNotSatisfiable
@@ -754,6 +800,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#417].
#
class HTTPExpectationFailed < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -774,6 +821,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#421].
#
class HTTPMisdirectedRequest < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -790,6 +838,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#422].
#
class HTTPUnprocessableEntity < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -805,6 +854,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#423].
#
class HTTPLocked < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -821,6 +871,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#424].
#
class HTTPFailedDependency < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -840,6 +891,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#426].
#
class HTTPUpgradeRequired < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -856,6 +908,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#428].
#
class HTTPPreconditionRequired < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -872,6 +925,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#429].
#
class HTTPTooManyRequests < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -889,6 +943,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#431].
#
class HTTPRequestHeaderFieldsTooLarge < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -906,6 +961,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#451].
#
class HTTPUnavailableForLegalReasons < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
# 444 No Response - Nginx
@@ -926,6 +982,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#500].
#
class HTTPInternalServerError < HTTPServerError
+ # :stopdoc:
HAS_BODY = true
end
@@ -943,6 +1000,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#501].
#
class HTTPNotImplemented < HTTPServerError
+ # :stopdoc:
HAS_BODY = true
end
@@ -960,6 +1018,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#502].
#
class HTTPBadGateway < HTTPServerError
+ # :stopdoc:
HAS_BODY = true
end
@@ -977,6 +1036,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#503].
#
class HTTPServiceUnavailable < HTTPServerError
+ # :stopdoc:
HAS_BODY = true
end
@@ -994,6 +1054,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#504].
#
class HTTPGatewayTimeout < HTTPServerError
+ # :stopdoc:
HAS_BODY = true
end
HTTPGatewayTimeOut = HTTPGatewayTimeout
@@ -1011,6 +1072,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#505].
#
class HTTPVersionNotSupported < HTTPServerError
+ # :stopdoc:
HAS_BODY = true
end
@@ -1027,6 +1089,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#506].
#
class HTTPVariantAlsoNegotiates < HTTPServerError
+ # :stopdoc:
HAS_BODY = true
end
@@ -1043,6 +1106,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#507].
#
class HTTPInsufficientStorage < HTTPServerError
+ # :stopdoc:
HAS_BODY = true
end
@@ -1059,6 +1123,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#508].
#
class HTTPLoopDetected < HTTPServerError
+ # :stopdoc:
HAS_BODY = true
end
# 509 Bandwidth Limit Exceeded - Apache bw/limited extension
@@ -1076,6 +1141,7 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#510].
#
class HTTPNotExtended < HTTPServerError
+ # :stopdoc:
HAS_BODY = true
end
@@ -1092,19 +1158,21 @@ module Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#511].
#
class HTTPNetworkAuthenticationRequired < HTTPServerError
+ # :stopdoc:
HAS_BODY = true
end
end
class Net::HTTPResponse
+ # :stopdoc:
CODE_CLASS_TO_OBJ = {
'1' => Net::HTTPInformation,
'2' => Net::HTTPSuccess,
'3' => Net::HTTPRedirection,
'4' => Net::HTTPClientError,
'5' => Net::HTTPServerError
- }
+ }.freeze
CODE_TO_OBJ = {
'100' => Net::HTTPContinue,
'101' => Net::HTTPSwitchProtocol,
@@ -1170,5 +1238,5 @@ class Net::HTTPResponse
'508' => Net::HTTPLoopDetected,
'510' => Net::HTTPNotExtended,
'511' => Net::HTTPNetworkAuthenticationRequired,
- }
+ }.freeze
end
diff --git a/lib/net/net-protocol.gemspec b/lib/net/net-protocol.gemspec
index f9fd83f12b..2d911a966c 100644
--- a/lib/net/net-protocol.gemspec
+++ b/lib/net/net-protocol.gemspec
@@ -25,9 +25,8 @@ 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 2>#{IO::NULL}`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
- end
+ excludes = %W[/.git* /bin /test /*file /#{File.basename(__FILE__)}]
+ spec.files = IO.popen(%W[git -C #{__dir__} ls-files -z --] + excludes.map {|e| ":^#{e}"}, &:read).split("\x0")
spec.require_paths = ["lib"]
spec.add_dependency "timeout"
diff --git a/lib/net/protocol.rb b/lib/net/protocol.rb
index 197ea09089..8c81298c0e 100644
--- a/lib/net/protocol.rb
+++ b/lib/net/protocol.rb
@@ -54,9 +54,20 @@ module Net # :nodoc:
s.connect
end
end
+
+ tcp_socket_parameters = TCPSocket.instance_method(:initialize).parameters
+ TCP_SOCKET_NEW_HAS_OPEN_TIMEOUT = if tcp_socket_parameters != [[:rest]]
+ tcp_socket_parameters.include?([:key, :open_timeout])
+ else
+ # Use Socket.tcp to find out since there is no parameters information for TCPSocket#initialize
+ # See discussion in https://github.com/ruby/net-http/pull/224
+ Socket.method(:tcp).parameters.include?([:key, :open_timeout])
+ end
+ private_constant :TCP_SOCKET_NEW_HAS_OPEN_TIMEOUT
end
+ # :stopdoc:
class ProtocolError < StandardError; end
class ProtoSyntaxError < ProtocolError; end
class ProtoFatalError < ProtocolError; end
@@ -66,6 +77,7 @@ module Net # :nodoc:
class ProtoCommandError < ProtocolError; end
class ProtoRetriableError < ProtocolError; end
ProtocRetryError = ProtoRetriableError
+ # :startdoc:
##
# OpenTimeout, a subclass of Timeout::Error, is raised if a connection cannot
@@ -78,6 +90,7 @@ module Net # :nodoc:
# response cannot be read within the read_timeout.
class ReadTimeout < Timeout::Error
+ # :stopdoc:
def initialize(io = nil)
@io = io
end
@@ -97,6 +110,7 @@ module Net # :nodoc:
# response cannot be written within the write_timeout. Not raised on Windows.
class WriteTimeout < Timeout::Error
+ # :stopdoc:
def initialize(io = nil)
@io = io
end
@@ -484,6 +498,7 @@ module Net # :nodoc:
# The writer adapter class
#
class WriteAdapter
+ # :stopdoc:
def initialize(writer)
@writer = writer
end
diff --git a/lib/open-uri.rb b/lib/open-uri.rb
index ba2379325f..5983c7368b 100644
--- a/lib/open-uri.rb
+++ b/lib/open-uri.rb
@@ -91,8 +91,10 @@ end
module OpenURI
- VERSION = "0.4.1"
+ # The version string
+ VERSION = "0.5.0"
+ # The default options
Options = {
:proxy => true,
:proxy_http_basic_authentication => true,
@@ -109,6 +111,7 @@ module OpenURI
:redirect => true,
:encoding => nil,
:max_redirects => 64,
+ :request_specific_fields => nil,
}
def OpenURI.check_options(options) # :nodoc:
@@ -148,7 +151,11 @@ module OpenURI
end
encoding = Encoding.find(options[:encoding])
end
-
+ if options.has_key? :request_specific_fields
+ if !(options[:request_specific_fields].is_a?(Hash) || options[:request_specific_fields].is_a?(Proc))
+ raise ArgumentError, "Invalid request_specific_fields option: #{options[:request_specific_fields].inspect}"
+ end
+ end
unless mode == nil ||
mode == 'r' || mode == 'rb' ||
mode == File::RDONLY
@@ -212,12 +219,20 @@ module OpenURI
end
uri_set = {}
- max_redirects = options[:max_redirects]
+ max_redirects = options[:max_redirects] || Options.fetch(:max_redirects)
buf = nil
while true
+ request_specific_fields = {}
+ if options.has_key? :request_specific_fields
+ request_specific_fields = if options[:request_specific_fields].is_a?(Hash)
+ options[:request_specific_fields]
+ else options[:request_specific_fields].is_a?(Proc)
+ options[:request_specific_fields].call(uri)
+ end
+ end
redirect = catch(:open_uri_redirect) {
buf = Buffer.new
- uri.buffer_open(buf, find_proxy.call(uri), options)
+ uri.buffer_open(buf, find_proxy.call(uri), options.merge(request_specific_fields))
nil
}
if redirect
@@ -237,6 +252,10 @@ module OpenURI
options = options.dup
options.delete :http_basic_authentication
end
+ if options.include?(:request_specific_fields) && options[:request_specific_fields].is_a?(Hash)
+ # Send request specific headers only for the initial request.
+ options.delete :request_specific_fields
+ end
uri = redirect
raise "HTTP redirection loop: #{uri}" if uri_set.include? uri.to_s
uri_set[uri.to_s] = true
@@ -377,24 +396,28 @@ module OpenURI
end
end
+ # Raised on HTTP session failure
class HTTPError < StandardError
- def initialize(message, io)
+ def initialize(message, io) # :nodoc:
super(message)
@io = io
end
+ # StringIO having the received data
attr_reader :io
end
# Raised on redirection,
# only occurs when +redirect+ option for HTTP is +false+.
class HTTPRedirect < HTTPError
- def initialize(message, io, uri)
+ def initialize(message, io, uri) # :nodoc:
super(message, io)
@uri = uri
end
+ # URI to redirect
attr_reader :uri
end
+ # Raised on too many redirection,
class TooManyRedirects < HTTPError
end
@@ -746,6 +769,44 @@ module OpenURI
# Using +true+ also means that redirections between http and ftp are
# permitted.
#
+ # [:max_redirects]
+ # Synopsis:
+ # :max_redirects=>int
+ #
+ # Number of HTTP redirects allowed before OpenURI::TooManyRedirects is raised.
+ # The default is 64.
+ #
+ # [:request_specific_fields]
+ # Synopsis:
+ # :request_specific_fields => {}
+ # :request_specific_fields => lambda {|url| ...}
+ #
+ # :request_specific_fields option allows specifying custom header fields that
+ # are sent with the HTTP request. It can be passed as a Hash or a Proc that
+ # gets evaluated on each request and returns a Hash of header fields.
+ #
+ # If a Hash is provided, it specifies the headers only for the initial
+ # request and these headers will not be sent on redirects.
+ #
+ # If a Proc is provided, it will be executed for each request including
+ # redirects, allowing dynamic header customization based on the request URL.
+ # It is important that the Proc returns a Hash. And this Hash specifies the
+ # headers to be sent with the request.
+ #
+ # For Example with Hash
+ # URI.open("http://...",
+ # request_specific_fields: {"Authorization" => "token dummy"}) {|f| ... }
+ #
+ # For Example with Proc:
+ # URI.open("http://...",
+ # request_specific_fields: lambda { |uri|
+ # if uri.host == "example.com"
+ # {"Authorization" => "token dummy"}
+ # else
+ # {}
+ # end
+ # }) {|f| ... }
+ #
def open(*rest, &block)
OpenURI.open_uri(self, *rest, &block)
end
diff --git a/lib/open3/version.rb b/lib/open3/version.rb
index bfcec44ccc..322dd71e2a 100644
--- a/lib/open3/version.rb
+++ b/lib/open3/version.rb
@@ -1,3 +1,4 @@
module Open3
+ # The version string
VERSION = "0.2.1"
end
diff --git a/lib/optparse.rb b/lib/optparse.rb
index 069c3e436e..97178e284b 100644
--- a/lib/optparse.rb
+++ b/lib/optparse.rb
@@ -7,6 +7,7 @@
#
# See OptionParser for documentation.
#
+require 'set' unless defined?(Set)
#--
# == Developer Documentation (not for RDoc output)
@@ -142,7 +143,7 @@
# Used:
#
# $ ruby optparse-test.rb -r
-# optparse-test.rb:9:in `<main>': missing argument: -r (OptionParser::MissingArgument)
+# optparse-test.rb:9:in '<main>': missing argument: -r (OptionParser::MissingArgument)
# $ ruby optparse-test.rb -r my-library
# You required my-library!
#
@@ -235,7 +236,7 @@
# $ ruby optparse-test.rb --user 2
# #<struct User id=2, name="Gandalf">
# $ ruby optparse-test.rb --user 3
-# optparse-test.rb:15:in `block in find_user': No User Found for id 3 (RuntimeError)
+# optparse-test.rb:15:in 'block in find_user': No User Found for id 3 (RuntimeError)
#
# === Store options to a Hash
#
@@ -425,7 +426,9 @@
#
class OptionParser
# The version string
- OptionParser::Version = "0.5.0"
+ VERSION = "0.8.1"
+ # An alias for compatibility
+ Version = VERSION
# :stopdoc:
NoArgument = [NO_ARGUMENT = :NONE, nil].freeze
@@ -461,11 +464,14 @@ class OptionParser
candidates
end
+ def self.completable?(key)
+ String.try_convert(key) or defined?(key.id2name)
+ end
+
def candidate(key, icase = false, pat = nil, &_)
Completion.candidate(key, icase, pat, &method(:each))
end
- 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
@@ -496,7 +502,6 @@ class OptionParser
end
end
-
#
# Map from option/keyword string to object with completion.
#
@@ -504,7 +509,6 @@ class OptionParser
include Completion
end
-
#
# Individual switch class. Not important to the user.
#
@@ -546,18 +550,18 @@ class OptionParser
def initialize(pattern = nil, conv = nil,
short = nil, long = nil, arg = nil,
- desc = ([] if short or long), block = nil, &_block)
+ desc = ([] if short or long), block = nil, values = nil, &_block)
raise if Array === pattern
block ||= _block
- @pattern, @conv, @short, @long, @arg, @desc, @block =
- pattern, conv, short, long, arg, desc, block
+ @pattern, @conv, @short, @long, @arg, @desc, @block, @values =
+ pattern, conv, short, long, arg, desc, block, values
end
#
# 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:
+ private def parse_arg(arg) # :nodoc:
pattern or return nil, [arg]
unless m = pattern.match(arg)
yield(InvalidArgument, arg)
@@ -575,22 +579,24 @@ class OptionParser
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:
+ private def conv_arg(arg, val = []) # :nodoc:
+ v, = *val
if conv
val = conv.call(*val)
else
val = proc {|v| v}.call(*val)
end
+ if @values
+ @values.include?(val) or raise InvalidArgument, v
+ end
return arg, block, val
end
- private :conv_arg
#
# Produces the summary text. Each line of the summary is yielded to the
@@ -668,7 +674,7 @@ class OptionParser
(sopts+lopts).each do |opt|
# "(-x -c -r)-l[left justify]"
- if /^--\[no-\](.+)$/ =~ opt
+ if /\A--\[no-\](.+)$/ =~ opt
o = $1
yield("--#{o}", desc.join(""))
yield("--no-#{o}", desc.join(""))
@@ -874,14 +880,13 @@ class OptionParser
# +lopts+:: Long style option list.
# +nlopts+:: Negated long style options list.
#
- def update(sw, sopts, lopts, nsw = nil, nlopts = nil) # :nodoc:
+ private 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
@@ -1032,7 +1037,6 @@ class OptionParser
DefaultList.short['-'] = Switch::NoArgument.new {}
DefaultList.long[''] = Switch::NoArgument.new {throw :terminate}
-
COMPSYS_HEADER = <<'XXX' # :nodoc:
typeset -A opt_args
@@ -1051,16 +1055,16 @@ XXX
end
def help_exit
- if STDOUT.tty? && (pager = ENV.values_at(*%w[RUBY_PAGER PAGER]).find {|e| e && !e.empty?})
+ if $stdout.tty? && (pager = ENV.values_at(*%w[RUBY_PAGER PAGER]).find {|e| e && !e.empty?})
less = ENV["LESS"]
- args = [{"LESS" => "#{!less || less.empty? ? '-' : less}Fe"}, pager, "w"]
+ args = [{"LESS" => "#{less} -Fe"}, pager, "w"]
print = proc do |f|
f.puts help
rescue Errno::EPIPE
# pager terminated
end
if Process.respond_to?(:fork) and false
- IO.popen("-") {|f| f ? Process.exec(*args, in: f) : print.call(STDOUT)}
+ IO.popen("-") {|f| f ? Process.exec(*args, in: f) : print.call($stdout)}
# unreachable
end
IO.popen(*args, &print)
@@ -1102,7 +1106,7 @@ XXX
#
Officious['*-completion-zsh'] = proc do |parser|
Switch::OptionalArgument.new do |arg|
- parser.compsys(STDOUT, arg)
+ parser.compsys($stdout, arg)
exit
end
end
@@ -1115,7 +1119,7 @@ XXX
Switch::OptionalArgument.new do |pkg|
if pkg
begin
- require 'optparse/version'
+ require_relative 'optparse/version'
rescue LoadError
else
show_version(*pkg.split(/,/)) or
@@ -1288,7 +1292,15 @@ XXX
# to $0.
#
def program_name
- @program_name || File.basename($0, '.*')
+ @program_name || strip_ext(File.basename($0))
+ end
+
+ private def strip_ext(name) # :nodoc:
+ exts = /#{
+ require "rbconfig"
+ Regexp.union(*RbConfig::CONFIG["EXECUTABLE_EXTS"]&.split(" "))
+ }\z/o
+ name.sub(exts, "")
end
# for experimental cascading :-)
@@ -1443,14 +1455,13 @@ XXX
# +prv+:: Previously specified argument.
# +msg+:: Exception message.
#
- def notwice(obj, prv, msg) # :nodoc:
+ private 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:
@@ -1467,6 +1478,7 @@ XXX
klass = nil
q, a = nil
has_arg = false
+ values = nil
opts.each do |o|
# argument class
@@ -1480,7 +1492,7 @@ XXX
end
# directly specified pattern(any object possible to match)
- if (!(String === o || Symbol === o)) and o.respond_to?(:match)
+ if !Completion.completable?(o) and o.respond_to?(:match)
pattern = notwice(o, pattern, 'pattern')
if pattern.respond_to?(:convert)
conv = pattern.method(:convert).to_proc
@@ -1494,7 +1506,12 @@ XXX
case o
when Proc, Method
block = notwice(o, block, 'block')
- when Array, Hash
+ when Array, Hash, Set
+ if Array === o
+ o, v = o.partition {|v,| Completion.completable?(v)}
+ values = notwice(v, values, 'values') unless v.empty?
+ next if o.empty?
+ end
case pattern
when CompletingHash
when nil
@@ -1504,11 +1521,13 @@ XXX
raise ArgumentError, "argument pattern given twice"
end
o.each {|pat, *v| pattern[pat] = v.fetch(0) {pat}}
+ when Range
+ values = notwice(o, values, 'values')
when Module
raise ArgumentError, "unsupported argument type: #{o}", ParseError.filter_backtrace(caller(4))
when *ArgumentStyle.keys
style = notwice(ArgumentStyle[o], style, 'style')
- when /^--no-([^\[\]=\s]*)(.+)?/
+ when /\A--no-([^\[\]=\s]*)(.+)?/
q, a = $1, $2
o = notwice(a ? Object : TrueClass, klass, 'type')
not_pattern, not_conv = search(:atype, o) unless not_style
@@ -1519,7 +1538,7 @@ XXX
(q = q.downcase).tr!('_', '-')
long << "no-#{q}"
nolong << q
- when /^--\[no-\]([^\[\]=\s]*)(.+)?/
+ when /\A--\[no-\]([^\[\]=\s]*)(.+)?/
q, a = $1, $2
o = notwice(a ? Object : TrueClass, klass, 'type')
if a
@@ -1532,7 +1551,7 @@ XXX
not_pattern, not_conv = search(:atype, FalseClass) unless not_style
not_style = Switch::NoArgument
nolong << "no-#{o}"
- when /^--([^\[\]=\s]*)(.+)?/
+ when /\A--([^\[\]=\s]*)(.+)?/
q, a = $1, $2
if a
o = notwice(NilClass, klass, 'type')
@@ -1542,7 +1561,7 @@ XXX
ldesc << "--#{q}"
(o = q.downcase).tr!('_', '-')
long << o
- when /^-(\[\^?\]?(?:[^\\\]]|\\.)*\])(.+)?/
+ when /\A-(\[\^?\]?(?:[^\\\]]|\\.)*\])(.+)?/
q, a = $1, $2
o = notwice(Object, klass, 'type')
if a
@@ -1553,7 +1572,7 @@ XXX
end
sdesc << "-#{q}"
short << Regexp.new(q)
- when /^-(.)(.+)?/
+ when /\A-(.)(.+)?/
q, a = $1, $2
if a
o = notwice(NilClass, klass, 'type')
@@ -1562,7 +1581,7 @@ XXX
end
sdesc << "-#{q}"
short << q
- when /^=/
+ when /\A=/
style = notwice(default_style.guess(arg = o), style, 'style')
default_pattern, conv = search(:atype, Object) unless default_pattern
else
@@ -1571,12 +1590,18 @@ XXX
end
default_pattern, conv = search(:atype, default_style.pattern) unless default_pattern
+ if Range === values and klass
+ unless (!values.begin or klass === values.begin) and
+ (!values.end or klass === values.end)
+ raise ArgumentError, "range does not match class"
+ end
+ end
if !(short.empty? and long.empty?)
if has_arg and default_style == Switch::NoArgument
default_style = Switch::RequiredArgument
end
s = (style || default_style).new(pattern || default_pattern,
- conv, sdesc, ldesc, arg, desc, block)
+ conv, sdesc, ldesc, arg, desc, block, values)
elsif !block
if style or pattern
raise ArgumentError, "no switch given", ParseError.filter_backtrace(caller)
@@ -1585,7 +1610,7 @@ XXX
else
short << pattern
s = (style || default_style).new(pattern,
- conv, nil, nil, arg, desc, block)
+ conv, nil, nil, arg, desc, block, values)
end
return s, short, long,
(not_style.new(not_pattern, not_conv, sdesc, ldesc, nil, desc, block) if not_style),
@@ -1703,7 +1728,7 @@ XXX
parse_in_order(argv, setter, **keywords, &nonopt)
end
- def parse_in_order(argv = default_argv, setter = nil, exact: require_exact, **, &nonopt) # :nodoc:
+ private def parse_in_order(argv = default_argv, setter = nil, exact: require_exact, **, &nonopt) # :nodoc:
opt, arg, val, rest = nil
nonopt ||= proc {|a| throw :terminate, a}
argv.unshift(arg) if arg = catch(:terminate) {
@@ -1729,9 +1754,9 @@ XXX
end
end
begin
- opt, cb, *val = sw.parse(rest, argv) {|*exc| raise(*exc)}
- val = callback!(cb, 1, *val) if cb
- callback!(setter, 2, sw.switch_name, *val) if setter
+ opt, cb, val = sw.parse(rest, argv) {|*exc| raise(*exc)}
+ val = callback!(cb, 1, val) if cb
+ callback!(setter, 2, sw.switch_name, val) if setter
rescue ParseError
raise $!.set_option(arg, rest)
end
@@ -1761,7 +1786,7 @@ XXX
raise $!.set_option(arg, true)
end
begin
- opt, cb, *val = sw.parse(val, argv) {|*exc| raise(*exc) if eq}
+ opt, cb, val = sw.parse(val, argv) {|*exc| raise(*exc) if eq}
rescue ParseError
raise $!.set_option(arg, arg.length > 2)
else
@@ -1769,8 +1794,8 @@ XXX
end
begin
argv.unshift(opt) if opt and (!rest or (opt = opt.sub(/\A-*/, '-')) != '-')
- val = callback!(cb, 1, *val) if cb
- callback!(setter, 2, sw.switch_name, *val) if setter
+ val = callback!(cb, 1, val) if cb
+ callback!(setter, 2, sw.switch_name, val) if setter
rescue ParseError
raise $!.set_option(arg, arg.length > 2)
end
@@ -1794,10 +1819,11 @@ XXX
argv
end
- private :parse_in_order
# Calls callback with _val_.
- def callback!(cb, max_arity, *args) # :nodoc:
+ private def callback!(cb, max_arity, *args) # :nodoc:
+ args.compact!
+
if (size = args.size) < max_arity and cb.to_proc.lambda?
(arity = cb.arity) < 0 and arity = (1-arity)
arity = max_arity if arity > max_arity
@@ -1805,7 +1831,6 @@ XXX
end
cb.call(*args)
end
- private :callback!
#
# Parses command line arguments +argv+ in permutation mode and returns
@@ -1825,7 +1850,7 @@ XXX
#
def permute!(argv = default_argv, **keywords)
nonopts = []
- order!(argv, **keywords, &nonopts.method(:<<))
+ order!(argv, **keywords) {|nonopt| nonopts << nonopt}
argv[0, 0] = nonopts
argv
end
@@ -1878,13 +1903,16 @@ XXX
single_options, *long_options = *args
result = {}
+ setter = (symbolize_names ?
+ ->(name, val) {result[name.to_sym] = val}
+ : ->(name, val) {result[name] = val})
single_options.scan(/(.)(:)?/) do |opt, val|
if val
- result[opt] = nil
+ setter[opt, nil]
define("-#{opt} VAL")
else
- result[opt] = false
+ setter[opt, false]
define("-#{opt}")
end
end if single_options
@@ -1893,16 +1921,16 @@ XXX
arg, desc = arg.split(';', 2)
opt, val = arg.split(':', 2)
if val
- result[opt] = val.empty? ? nil : val
+ setter[opt, (val unless val.empty?)]
define("--#{opt}=#{result[opt] || "VAL"}", *[desc].compact)
else
- result[opt] = false
+ setter[opt, false]
define("--#{opt}", *[desc].compact)
end
end
- parse_in_order(argv, result.method(:[]=), **keywords)
- symbolize_names ? result.transform_keys(&:to_sym) : result
+ parse_in_order(argv, setter, **keywords)
+ result
end
#
@@ -1916,24 +1944,22 @@ XXX
# Traverses @stack, sending each element method +id+ with +args+ and
# +block+.
#
- def visit(id, *args, &block) # :nodoc:
+ private 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:
+ private 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
@@ -1944,7 +1970,7 @@ XXX
# +icase+:: Search case insensitive if true.
# +pat+:: Optional pattern for completion.
#
- def complete(typ, opt, icase = false, *pat) # :nodoc:
+ private def complete(typ, opt, icase = false, *pat) # :nodoc:
if pat.empty?
search(typ, opt) {|sw| return [sw, opt]} # exact match or...
end
@@ -1952,9 +1978,8 @@ XXX
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])
+ raise exc.new(opt, additional: proc {|o| additional_message(typ, o)})
end
- private :complete
#
# Returns additional info.
@@ -2017,19 +2042,27 @@ XXX
def load(filename = nil, **keywords)
unless filename
basename = File.basename($0, '.*')
- return true if load(File.expand_path(basename, '~/.options'), **keywords) rescue nil
+ return true if load(File.expand_path("~/.options/#{basename}"), **keywords) rescue nil
basename << ".options"
+ if !(xdg = ENV['XDG_CONFIG_HOME']) or xdg.empty?
+ # https://specifications.freedesktop.org/basedir-spec/latest/#variables
+ #
+ # If $XDG_CONFIG_HOME is either not set or empty, a default
+ # equal to $HOME/.config should be used.
+ xdg = ['~/.config', true]
+ end
return [
- # XDG
- ENV['XDG_CONFIG_HOME'],
- '~/.config',
+ xdg,
+
*ENV['XDG_CONFIG_DIRS']&.split(File::PATH_SEPARATOR),
# Haiku
- '~/config/settings',
- ].any? {|dir|
+ ['~/config/settings', true],
+ ].any? {|dir, expand|
next if !dir or dir.empty?
- load(File.expand_path(basename, dir), **keywords) rescue nil
+ filename = File.join(dir, basename)
+ filename = File.expand_path(filename) if expand
+ load(filename, **keywords) rescue nil
}
end
begin
@@ -2235,9 +2268,10 @@ XXX
argv
end
+ DIR = File.join(__dir__, '')
def self.filter_backtrace(array)
unless $DEBUG
- array.delete_if(&%r"\A#{Regexp.quote(__FILE__)}:"o.method(:=~))
+ array.delete_if {|bt| bt.start_with?(DIR)}
end
array
end
@@ -2280,42 +2314,42 @@ XXX
# Raises when ambiguously completable string is encountered.
#
class AmbiguousOption < ParseError
- const_set(:Reason, 'ambiguous option')
+ Reason = 'ambiguous option' # :nodoc:
end
#
# Raises when there is an argument for a switch which takes no argument.
#
class NeedlessArgument < ParseError
- const_set(:Reason, 'needless argument')
+ Reason = 'needless argument' # :nodoc:
end
#
# Raises when a switch with mandatory argument has no argument.
#
class MissingArgument < ParseError
- const_set(:Reason, 'missing argument')
+ Reason = 'missing argument' # :nodoc:
end
#
# Raises when switch is undefined.
#
class InvalidOption < ParseError
- const_set(:Reason, 'invalid option')
+ Reason = 'invalid option' # :nodoc:
end
#
# Raises when the given argument does not match required format.
#
class InvalidArgument < ParseError
- const_set(:Reason, 'invalid argument')
+ Reason = 'invalid argument' # :nodoc:
end
#
# Raises when the given argument word can't be completed uniquely.
#
class AmbiguousArgument < InvalidArgument
- const_set(:Reason, 'ambiguous argument')
+ Reason = 'ambiguous argument' # :nodoc:
end
#
@@ -2414,9 +2448,11 @@ XXX
# and DecimalNumeric. See Acceptable argument classes (in source code).
#
module Acceptables
- const_set(:DecimalInteger, OptionParser::DecimalInteger)
- const_set(:OctalInteger, OptionParser::OctalInteger)
- const_set(:DecimalNumeric, OptionParser::DecimalNumeric)
+ # :stopdoc:
+ DecimalInteger = OptionParser::DecimalInteger
+ OctalInteger = OptionParser::OctalInteger
+ DecimalNumeric = OptionParser::DecimalNumeric
+ # :startdoc:
end
end
diff --git a/lib/optparse/optparse.gemspec b/lib/optparse/optparse.gemspec
index 1aa54aa781..885b0ec380 100644
--- a/lib/optparse/optparse.gemspec
+++ b/lib/optparse/optparse.gemspec
@@ -3,7 +3,7 @@
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
+ /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
end rescue nil
end
@@ -14,7 +14,10 @@ Gem::Specification.new do |spec|
spec.email = ["nobu@ruby-lang.org"]
spec.summary = %q{OptionParser is a class for command-line option analysis.}
- spec.description = %q{OptionParser is a class for command-line option analysis.}
+ spec.description = File.open(File.join(__dir__, "README.md")) do |readme|
+ readme.gets("") # heading
+ readme.gets("").chomp
+ end rescue spec.summary
spec.homepage = "https://github.com/ruby/optparse"
spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
spec.licenses = ["Ruby", "BSD-2-Clause"]
@@ -22,9 +25,9 @@ Gem::Specification.new do |spec|
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
- spec.files = Dir["{doc,lib,misc}/**/{*,.document}"] +
- %w[README.md ChangeLog COPYING .document .rdoc_options]
- spec.rdoc_options = ["--main=README.md", "--op=rdoc", "--page-dir=doc"]
+ dir, gemspec = File.split(__FILE__)
+ excludes = %W[#{gemspec} rakelib test/ Gemfile Rakefile .git* .editor*].map {|n| ":^"+n}
+ spec.files = IO.popen(%w[git ls-files -z --] + excludes, chdir: dir, &:read).split("\x0")
spec.bindir = "exe"
spec.executables = []
spec.require_paths = ["lib"]
diff --git a/lib/ostruct.gemspec b/lib/ostruct.gemspec
deleted file mode 100644
index 08a7aefb05..0000000000
--- a/lib/ostruct.gemspec
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-name = File.basename(__FILE__, ".gemspec")
-version = ["lib", Array.new(name.count("-")+1, ".").join("/")].find do |dir|
- break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
- /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
- end rescue nil
-end
-
-Gem::Specification.new do |spec|
- spec.name = name
- spec.version = version
- spec.authors = ["Marc-Andre Lafortune"]
- spec.email = ["ruby-core@marc-andre.ca"]
-
- spec.summary = %q{Class to build custom data structures, similar to a Hash.}
- spec.description = %q{Class to build custom data structures, similar to a Hash.}
- spec.homepage = "https://github.com/ruby/ostruct"
- spec.licenses = ["Ruby", "BSD-2-Clause"]
- spec.required_ruby_version = ">= 2.5.0"
-
- spec.files = [".gitignore", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "lib/ostruct.rb", "ostruct.gemspec"]
- spec.require_paths = ["lib"]
-end
diff --git a/lib/ostruct.rb b/lib/ostruct.rb
deleted file mode 100644
index c762baa5a5..0000000000
--- a/lib/ostruct.rb
+++ /dev/null
@@ -1,489 +0,0 @@
-# frozen_string_literal: true
-#
-# = ostruct.rb: OpenStruct implementation
-#
-# Author:: Yukihiro Matsumoto
-# Documentation:: Gavin Sinclair
-#
-# OpenStruct allows the creation of data objects with arbitrary attributes.
-# See OpenStruct for an example.
-#
-
-#
-# An OpenStruct is a data structure, similar to a Hash, that allows the
-# definition of arbitrary attributes with their accompanying values. This is
-# accomplished by using Ruby's metaprogramming to define methods on the class
-# itself.
-#
-# == Examples
-#
-# require "ostruct"
-#
-# person = OpenStruct.new
-# person.name = "John Smith"
-# person.age = 70
-#
-# person.name # => "John Smith"
-# person.age # => 70
-# person.address # => nil
-#
-# An OpenStruct employs a Hash internally to store the attributes and values
-# and can even be initialized with one:
-#
-# australia = OpenStruct.new(:country => "Australia", :capital => "Canberra")
-# # => #<OpenStruct country="Australia", capital="Canberra">
-#
-# Hash keys with spaces or characters that could normally not be used for
-# method calls (e.g. <code>()[]*</code>) will not be immediately available
-# on the OpenStruct object as a method for retrieval or assignment, but can
-# still be reached through the Object#send method or using [].
-#
-# measurements = OpenStruct.new("length (in inches)" => 24)
-# measurements[:"length (in inches)"] # => 24
-# measurements.send("length (in inches)") # => 24
-#
-# message = OpenStruct.new(:queued? => true)
-# message.queued? # => true
-# message.send("queued?=", false)
-# message.queued? # => false
-#
-# Removing the presence of an attribute requires the execution of the
-# delete_field method as setting the property value to +nil+ will not
-# remove the attribute.
-#
-# first_pet = OpenStruct.new(:name => "Rowdy", :owner => "John Smith")
-# second_pet = OpenStruct.new(:name => "Rowdy")
-#
-# first_pet.owner = nil
-# first_pet # => #<OpenStruct name="Rowdy", owner=nil>
-# first_pet == second_pet # => false
-#
-# first_pet.delete_field(:owner)
-# first_pet # => #<OpenStruct name="Rowdy">
-# first_pet == second_pet # => true
-#
-# Ractor compatibility: A frozen OpenStruct with shareable values is itself shareable.
-#
-# == Caveats
-#
-# An OpenStruct utilizes Ruby's method lookup structure to find and define the
-# necessary methods for properties. This is accomplished through the methods
-# method_missing and define_singleton_method.
-#
-# This should be a consideration if there is a concern about the performance of
-# the objects that are created, as there is much more overhead in the setting
-# of these properties compared to using a Hash or a Struct.
-# Creating an open struct from a small Hash and accessing a few of the
-# entries can be 200 times slower than accessing the hash directly.
-#
-# This is a potential security issue; building OpenStruct from untrusted user data
-# (e.g. JSON web request) may be susceptible to a "symbol denial of service" attack
-# since the keys create methods and names of methods are never garbage collected.
-#
-# This may also be the source of incompatibilities between Ruby versions:
-#
-# o = OpenStruct.new
-# o.then # => nil in Ruby < 2.6, enumerator for Ruby >= 2.6
-#
-# Builtin methods may be overwritten this way, which may be a source of bugs
-# or security issues:
-#
-# o = OpenStruct.new
-# o.methods # => [:to_h, :marshal_load, :marshal_dump, :each_pair, ...
-# o.methods = [:foo, :bar]
-# o.methods # => [:foo, :bar]
-#
-# To help remedy clashes, OpenStruct uses only protected/private methods ending with <code>!</code>
-# and defines aliases for builtin public methods by adding a <code>!</code>:
-#
-# 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 <code>!</code>;
-# Note that a subclass' methods may not be overwritten, nor can OpenStruct's own methods
-# ending with <code>!</code>.
-#
-# For all these reasons, consider not using OpenStruct at all.
-#
-class OpenStruct
- VERSION = "0.6.0"
-
- HAS_PERFORMANCE_WARNINGS = begin
- Warning[:performance]
- true
- rescue NoMethodError, ArgumentError
- false
- end
- private_constant :HAS_PERFORMANCE_WARNINGS
-
- #
- # Creates a new OpenStruct object. By default, the resulting OpenStruct
- # object will have no attributes.
- #
- # The optional +hash+, if given, will generate attributes and values
- # (can be a Hash, an OpenStruct or a Struct).
- # For example:
- #
- # require "ostruct"
- # hash = { "country" => "Australia", :capital => "Canberra" }
- # data = OpenStruct.new(hash)
- #
- # data # => #<OpenStruct country="Australia", capital="Canberra">
- #
- def initialize(hash=nil)
- if HAS_PERFORMANCE_WARNINGS && Warning[:performance]
- warn "OpenStruct use is discouraged for performance reasons", uplevel: 1, category: :performance
- end
-
- if hash
- update_to_values!(hash)
- else
- @table = {}
- end
- end
-
- # Duplicates an OpenStruct object's Hash table.
- private def initialize_clone(orig) # :nodoc:
- super # clones the singleton class for us
- @table = @table.dup unless @table.frozen?
- end
-
- private def initialize_dup(orig) # :nodoc:
- super
- update_to_values!(@table)
- end
-
- private def update_to_values!(hash) # :nodoc:
- @table = {}
- hash.each_pair do |k, v|
- set_ostruct_member_value!(k, v)
- end
- end
-
- #
- # call-seq:
- # ostruct.to_h -> hash
- # ostruct.to_h {|name, value| block } -> hash
- #
- # Converts the OpenStruct to a hash with keys representing
- # each attribute (as symbols) and their corresponding values.
- #
- # If a block is given, the results of the block on each pair of
- # the receiver will be used as pairs.
- #
- # require "ostruct"
- # data = OpenStruct.new("country" => "Australia", :capital => "Canberra")
- # data.to_h # => {:country => "Australia", :capital => "Canberra" }
- # data.to_h {|name, value| [name.to_s, value.upcase] }
- # # => {"country" => "AUSTRALIA", "capital" => "CANBERRA" }
- #
- if {test: :to_h}.to_h{ [:works, true] }[:works] # RUBY_VERSION < 2.6 compatibility
- def to_h(&block)
- if block
- @table.to_h(&block)
- else
- @table.dup
- end
- end
- else
- def to_h(&block)
- if block
- @table.map(&block).to_h
- else
- @table.dup
- end
- end
- end
-
- #
- # :call-seq:
- # ostruct.each_pair {|name, value| block } -> ostruct
- # ostruct.each_pair -> Enumerator
- #
- # Yields all attributes (as symbols) along with the corresponding values
- # or returns an enumerator if no block is given.
- #
- # require "ostruct"
- # data = OpenStruct.new("country" => "Australia", :capital => "Canberra")
- # data.each_pair.to_a # => [[:country, "Australia"], [:capital, "Canberra"]]
- #
- def each_pair
- return to_enum(__method__) { @table.size } unless defined?(yield)
- @table.each_pair{|p| yield p}
- self
- end
-
- #
- # Provides marshalling support for use by the Marshal library.
- #
- def marshal_dump # :nodoc:
- @table
- end
-
- #
- # Provides marshalling support for use by the Marshal library.
- #
- alias_method :marshal_load, :update_to_values! # :nodoc:
-
- #
- # Used internally to defined properties on the
- # OpenStruct. It does this by using the metaprogramming function
- # define_singleton_method for both the getter method and the setter method.
- #
- def new_ostruct_member!(name) # :nodoc:
- unless @table.key?(name) || is_method_protected!(name)
- if defined?(::Ractor)
- getter_proc = nil.instance_eval{ Proc.new { @table[name] } }
- setter_proc = nil.instance_eval{ Proc.new {|x| @table[name] = x} }
- ::Ractor.make_shareable(getter_proc)
- ::Ractor.make_shareable(setter_proc)
- else
- getter_proc = Proc.new { @table[name] }
- setter_proc = Proc.new {|x| @table[name] = x}
- end
- define_singleton_method!(name, &getter_proc)
- define_singleton_method!("#{name}=", &setter_proc)
- end
- end
- private :new_ostruct_member!
-
- private def is_method_protected!(name) # :nodoc:
- if !respond_to?(name, true)
- false
- elsif name.match?(/!$/)
- true
- else
- owner = method!(name).owner
- if owner.class == ::Class
- owner < ::OpenStruct
- else
- self.class!.ancestors.any? do |mod|
- return false if mod == ::OpenStruct
- mod == owner
- end
- end
- end
- end
-
- def freeze
- @table.freeze
- super
- end
-
- private def method_missing(mid, *args) # :nodoc:
- len = args.length
- if mname = mid[/.*(?==\z)/m]
- if len != 1
- raise! ArgumentError, "wrong number of arguments (given #{len}, expected 1)", caller(1)
- end
- set_ostruct_member_value!(mname, args[0])
- elsif len == 0
- @table[mid]
- else
- begin
- super
- rescue NoMethodError => err
- err.backtrace.shift
- raise!
- end
- end
- end
-
- #
- # :call-seq:
- # ostruct[name] -> object
- #
- # Returns the value of an attribute, or +nil+ if there is no such attribute.
- #
- # require "ostruct"
- # person = OpenStruct.new("name" => "John Smith", "age" => 70)
- # person[:age] # => 70, same as person.age
- #
- def [](name)
- @table[name.to_sym]
- end
-
- #
- # :call-seq:
- # ostruct[name] = obj -> obj
- #
- # Sets the value of an attribute.
- #
- # require "ostruct"
- # person = OpenStruct.new("name" => "John Smith", "age" => 70)
- # person[:age] = 42 # equivalent to person.age = 42
- # person.age # => 42
- #
- def []=(name, value)
- name = name.to_sym
- new_ostruct_member!(name)
- @table[name] = value
- end
- alias_method :set_ostruct_member_value!, :[]=
- private :set_ostruct_member_value!
-
- # :call-seq:
- # ostruct.dig(name, *identifiers) -> object
- #
- # Finds and returns the object in nested objects
- # that is specified by +name+ and +identifiers+.
- # The nested objects may be instances of various classes.
- # See {Dig Methods}[rdoc-ref:dig_methods.rdoc].
- #
- # Examples:
- # require "ostruct"
- # address = OpenStruct.new("city" => "Anytown NC", "zip" => 12345)
- # person = OpenStruct.new("name" => "John Smith", "address" => address)
- # person.dig(:address, "zip") # => 12345
- # person.dig(:business_address, "zip") # => nil
- def dig(name, *names)
- begin
- name = name.to_sym
- rescue NoMethodError
- raise! TypeError, "#{name} is not a symbol nor a string"
- end
- @table.dig(name, *names)
- end
-
- #
- # Removes the named field from the object and returns the value the field
- # contained if it was defined. You may optionally provide a block.
- # If the field is not defined, the result of the block is returned,
- # or a NameError is raised if no block was given.
- #
- # require "ostruct"
- #
- # person = OpenStruct.new(name: "John", age: 70, pension: 300)
- #
- # person.delete_field!("age") # => 70
- # person # => #<OpenStruct name="John", pension=300>
- #
- # Setting the value to +nil+ will not remove the attribute:
- #
- # person.pension = nil
- # person # => #<OpenStruct name="John", pension=nil>
- #
- # person.delete_field('number') # => NameError
- #
- # person.delete_field('number') { 8675_309 } # => 8675309
- #
- def delete_field(name, &block)
- sym = name.to_sym
- begin
- singleton_class.remove_method(sym, "#{sym}=")
- rescue NameError
- end
- @table.delete(sym) do
- return yield if block
- raise! NameError.new("no field '#{sym}' in #{self}", sym)
- end
- end
-
- InspectKey = :__inspect_key__ # :nodoc:
-
- #
- # Returns a string containing a detailed summary of the keys and values.
- #
- def inspect
- ids = (Thread.current[InspectKey] ||= [])
- if ids.include?(object_id)
- detail = ' ...'
- else
- ids << object_id
- begin
- detail = @table.map do |key, value|
- " #{key}=#{value.inspect}"
- end.join(',')
- ensure
- ids.pop
- end
- end
- ['#<', self.class!, detail, '>'].join
- end
- alias :to_s :inspect
-
- attr_reader :table # :nodoc:
- alias table! table
- protected :table!
-
- #
- # Compares this object and +other+ for equality. An OpenStruct is equal to
- # +other+ when +other+ is an OpenStruct and the two objects' Hash tables are
- # equal.
- #
- # require "ostruct"
- # first_pet = OpenStruct.new("name" => "Rowdy")
- # second_pet = OpenStruct.new(:name => "Rowdy")
- # third_pet = OpenStruct.new("name" => "Rowdy", :age => nil)
- #
- # first_pet == second_pet # => true
- # first_pet == third_pet # => false
- #
- def ==(other)
- return false unless other.kind_of?(OpenStruct)
- @table == other.table!
- end
-
- #
- # Compares this object and +other+ for equality. An OpenStruct is eql? to
- # +other+ when +other+ is an OpenStruct and the two objects' Hash tables are
- # eql?.
- #
- def eql?(other)
- return false unless other.kind_of?(OpenStruct)
- @table.eql?(other.table!)
- end
-
- # Computes a hash code for this OpenStruct.
- def hash # :nodoc:
- @table.hash
- end
-
- #
- # Provides marshalling support for use by the YAML library.
- #
- def encode_with(coder) # :nodoc:
- @table.each_pair do |key, value|
- coder[key.to_s] = value
- end
- if @table.size == 1 && @table.key?(:table) # support for legacy format
- # in the very unlikely case of a single entry called 'table'
- coder['legacy_support!'] = true # add a bogus second entry
- end
- end
-
- #
- # Provides marshalling support for use by the YAML library.
- #
- def init_with(coder) # :nodoc:
- h = coder.map
- if h.size == 1 # support for legacy format
- key, val = h.first
- if key == 'table'
- h = val
- end
- end
- update_to_values!(h)
- end
-
- # Make all public methods (builtin or our own) accessible with <code>!</code>:
- give_access = instance_methods
- # See https://github.com/ruby/ostruct/issues/30
- give_access -= %i[instance_exec instance_eval eval] if RUBY_ENGINE == 'jruby'
- give_access.each do |method|
- next if method.match(/\W$/)
-
- new_name = "#{method}!"
- alias_method new_name, method
- end
- # Other builtin private methods we use:
- alias_method :raise!, :raise
- private :raise!
-
- # See https://github.com/ruby/ostruct/issues/40
- if RUBY_ENGINE != 'jruby'
- alias_method :block_given!, :block_given?
- private :block_given!
- end
-end
diff --git a/lib/pathname.rb b/lib/pathname.rb
new file mode 100644
index 0000000000..b19e379cd4
--- /dev/null
+++ b/lib/pathname.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+#
+# = pathname.rb
+#
+# Object-Oriented Pathname Class
+#
+# Author:: Tanaka Akira <akr@m17n.org>
+# Documentation:: Author and Gavin Sinclair
+#
+# For documentation, see class Pathname.
+#
+
+class Pathname # * Find *
+ #
+ # Iterates over the directory tree in a depth first manner, yielding a
+ # Pathname for each file under "this" directory.
+ #
+ # Note that you need to require 'pathname' to use this method.
+ #
+ # Returns an Enumerator if no block is given.
+ #
+ # Since it is implemented by the standard library module Find, Find.prune can
+ # be used to control the traversal.
+ #
+ # If +self+ is +.+, yielded pathnames begin with a filename in the
+ # current directory, not +./+.
+ #
+ # See Find.find
+ #
+ def find(ignore_error: true) # :yield: pathname
+ return to_enum(__method__, ignore_error: ignore_error) unless block_given?
+ require 'find'
+ if @path == '.'
+ Find.find(@path, ignore_error: ignore_error) {|f| yield self.class.new(f.delete_prefix('./')) }
+ else
+ Find.find(@path, ignore_error: ignore_error) {|f| yield self.class.new(f) }
+ end
+ end
+end
+
+
+class Pathname # * FileUtils *
+ # Recursively deletes a directory, including all directories beneath it.
+ #
+ # Note that you need to require 'pathname' to use this method.
+ #
+ # See FileUtils.rm_rf
+ def rmtree(noop: nil, verbose: nil, secure: nil)
+ # The name "rmtree" is borrowed from File::Path of Perl.
+ # File::Path provides "mkpath" and "rmtree".
+ require 'fileutils'
+ FileUtils.rm_rf(@path, noop: noop, verbose: verbose, secure: secure)
+ self
+ end
+end
+
+class Pathname # * tmpdir *
+ # Creates a tmp directory and wraps the returned path in a Pathname object.
+ #
+ # Note that you need to require 'pathname' to use this method.
+ #
+ # See Dir.mktmpdir
+ def self.mktmpdir
+ require 'tmpdir' unless defined?(Dir.mktmpdir)
+ if block_given?
+ Dir.mktmpdir do |dir|
+ dir = self.new(dir)
+ yield dir
+ end
+ else
+ self.new(Dir.mktmpdir)
+ end
+ end
+end
diff --git a/lib/pp.gemspec b/lib/pp.gemspec
index 27a92a8ce4..15a3b4dc6c 100644
--- a/lib/pp.gemspec
+++ b/lib/pp.gemspec
@@ -22,7 +22,8 @@ Gem::Specification.new do |spec|
spec.metadata["source_code_uri"] = spec.homepage
spec.files = %w[
- LICENSE.txt
+ BSDL
+ COPYING
lib/pp.rb
pp.gemspec
]
diff --git a/lib/pp.rb b/lib/pp.rb
index 1ec5a880eb..5fd29a373a 100644
--- a/lib/pp.rb
+++ b/lib/pp.rb
@@ -63,7 +63,8 @@ require 'prettyprint'
class PP < PrettyPrint
- VERSION = "0.5.0"
+ # The version string
+ VERSION = "0.6.3"
# Returns the usable width for +out+.
# As the width of +out+:
@@ -138,26 +139,19 @@ class PP < PrettyPrint
end
end
+ # Module that defines helper methods for pretty_print.
module PPMethods
# Yields to a block
# and preserves the previous set of objects being printed.
def guard_inspect_key
- if Thread.current[:__recursive_key__] == nil
- Thread.current[:__recursive_key__] = {}.compare_by_identity
- end
-
- if Thread.current[:__recursive_key__][:inspect] == nil
- Thread.current[:__recursive_key__][:inspect] = {}.compare_by_identity
- end
-
- save = Thread.current[:__recursive_key__][:inspect]
-
+ recursive_state = Thread.current[:__recursive_key__] ||= {}.compare_by_identity
+ save = recursive_state[:inspect] ||= {}.compare_by_identity
begin
- Thread.current[:__recursive_key__][:inspect] = {}.compare_by_identity
+ recursive_state[:inspect] = {}.compare_by_identity
yield
ensure
- Thread.current[:__recursive_key__][:inspect] = save
+ recursive_state[:inspect] = save
end
end
@@ -165,9 +159,8 @@ class PP < PrettyPrint
# to be pretty printed. Used to break cycles in chains of objects to be
# pretty printed.
def check_inspect_key(id)
- Thread.current[:__recursive_key__] &&
- Thread.current[:__recursive_key__][:inspect] &&
- Thread.current[:__recursive_key__][:inspect].include?(id)
+ recursive_state = Thread.current[:__recursive_key__] or return false
+ recursive_state[:inspect]&.include?(id)
end
# Adds the object_id +id+ to the set of objects being pretty printed, so
@@ -181,6 +174,24 @@ class PP < PrettyPrint
Thread.current[:__recursive_key__][:inspect].delete id
end
+ private def guard_inspect(object) # :nodoc:
+ recursive_state = Thread.current[:__recursive_key__]
+
+ if recursive_state&.key?(:inspect)
+ begin
+ push_inspect_key(object)
+ yield
+ ensure
+ pop_inspect_key(object) unless PP.sharing_detection
+ end
+ else
+ guard_inspect_key do
+ push_inspect_key(object)
+ yield
+ end
+ end
+ end
+
# Adds +obj+ to the pretty printing buffer
# using Object#pretty_print or Object#pretty_print_cycle.
#
@@ -189,18 +200,19 @@ class PP < PrettyPrint
def pp(obj)
# If obj is a Delegator then use the object being delegated to for cycle
# detection
- obj = obj.__getobj__ if defined?(::Delegator) and obj.is_a?(::Delegator)
+ obj = obj.__getobj__ if defined?(::Delegator) and ::Delegator === obj
if check_inspect_key(obj)
group {obj.pretty_print_cycle self}
return
end
- begin
- push_inspect_key(obj)
- group {obj.pretty_print self}
- ensure
- pop_inspect_key(obj) unless PP.sharing_detection
+ guard_inspect(obj) do
+ group do
+ obj.pretty_print self
+ rescue NoMethodError
+ text Kernel.instance_method(:inspect).bind_call(obj)
+ end
end
end
@@ -255,15 +267,20 @@ class PP < PrettyPrint
def seplist(list, sep=nil, iter_method=:each) # :yield: element
sep ||= lambda { comma_breakable }
first = true
+ kwsplat = EMPTY_KWHASH
list.__send__(iter_method) {|*v|
if first
first = false
else
sep.call
end
- RUBY_VERSION >= "3.0" ? yield(*v, **{}) : yield(*v)
+ kwsplat ? yield(*v, **kwsplat) : yield(*v)
}
end
+ EMPTY_KWHASH = if RUBY_VERSION >= "3.0" # :nodoc:
+ {}.freeze
+ end
+ private_constant :EMPTY_KWHASH
# A present standard failsafe for pretty printing any given Object
def pp_object(obj)
@@ -292,14 +309,33 @@ class PP < PrettyPrint
}
end
- # A pretty print for a pair of Hash
- def pp_hash_pair(k, v)
- pp k
- text '=>'
- group(1) {
- breakable ''
- pp v
- }
+ if RUBY_VERSION >= '3.4.'
+ # A pretty print for a pair of Hash
+ def pp_hash_pair(k, v)
+ if Symbol === k
+ if k.inspect.match?(%r[\A:["$@!]|[%&*+\-\/<=>@\]^`|~]\z])
+ k = k.to_s.inspect
+ end
+ text "#{k}:"
+ else
+ pp k
+ text ' '
+ text '=>'
+ end
+ group(1) {
+ breakable
+ pp v
+ }
+ end
+ else
+ def pp_hash_pair(k, v)
+ pp k
+ text '=>'
+ group(1) {
+ breakable ''
+ pp v
+ }
+ end
end
end
@@ -352,7 +388,8 @@ class PP < PrettyPrint
# This method should return an array of names of instance variables as symbols or strings as:
# +[:@a, :@b]+.
def pretty_print_instance_variables
- instance_variables.sort
+ ivars = respond_to?(:instance_variables_to_inspect, true) ? instance_variables_to_inspect || instance_variables : instance_variables
+ ivars.sort
end
# Is #inspect implementation using #pretty_print.
@@ -395,6 +432,28 @@ class Hash # :nodoc:
end
end
+if defined?(Set)
+ if set_pp = Set.instance_method(:initialize).source_location
+ set_pp = !set_pp.first.end_with?("/set.rb") # not defined in set.rb
+ else
+ set_pp = true # defined in C
+ end
+end
+class Set # :nodoc:
+ def pretty_print(pp) # :nodoc:
+ pp.group(1, "#{self.class.name}[", ']') {
+ pp.seplist(self) { |o|
+ pp.pp o
+ }
+ }
+ end
+
+ def pretty_print_cycle(pp) # :nodoc:
+ name = self.class.name
+ pp.text(empty? ? "#{name}[]" : "#{name}[...]")
+ end
+end if set_pp
+
class << ENV # :nodoc:
def pretty_print(q) # :nodoc:
h = {}
@@ -425,18 +484,37 @@ class Struct # :nodoc:
end
end
+verbose, $VERBOSE = $VERBOSE, nil
+begin
+ has_data_define = defined?(Data.define)
+ensure
+ $VERBOSE = verbose
+end
+
class Data # :nodoc:
def pretty_print(q) # :nodoc:
class_name = PP.mcall(self, Kernel, :class).name
class_name = " #{class_name}" if class_name
q.group(1, "#<data#{class_name}", '>') {
- q.seplist(PP.mcall(self, Kernel, :class).members, lambda { q.text "," }) {|member|
+
+ members = PP.mcall(self, Kernel, :class).members
+ values = []
+ members.select! do |member|
+ begin
+ values << __send__(member)
+ true
+ rescue NoMethodError
+ false
+ end
+ end
+
+ q.seplist(members.zip(values), lambda { q.text "," }) {|(member, value)|
q.breakable
q.text member.to_s
q.text '='
q.group(1) {
q.breakable ''
- q.pp public_send(member)
+ q.pp value
}
}
}
@@ -445,15 +523,17 @@ class Data # :nodoc:
def pretty_print_cycle(q) # :nodoc:
q.text sprintf("#<data %s:...>", PP.mcall(self, Kernel, :class).name)
end
-end if defined?(Data.define)
+end if has_data_define
class Range # :nodoc:
def pretty_print(q) # :nodoc:
- q.pp self.begin if self.begin
+ begin_nil = self.begin == nil
+ end_nil = self.end == nil
+ q.pp self.begin if !begin_nil || end_nil
q.breakable ''
q.text(self.exclude_end? ? '...' : '..')
q.breakable ''
- q.pp self.end if self.end
+ q.pp self.end if !end_nil || begin_nil
end
end
@@ -582,7 +662,7 @@ class MatchData # :nodoc:
end
if defined?(RubyVM::AbstractSyntaxTree)
- class RubyVM::AbstractSyntaxTree::Node
+ class RubyVM::AbstractSyntaxTree::Node # :nodoc:
def pretty_print_children(q, names = [])
children.zip(names) do |c, n|
if n
@@ -647,7 +727,7 @@ module Kernel
# prints arguments in pretty form.
#
- # pp returns argument(s).
+ # +#pp+ returns argument(s).
def pp(*objs)
objs.each {|obj|
PP.pp(obj)
diff --git a/lib/prettyprint.rb b/lib/prettyprint.rb
index 6f50192f5d..a65407c130 100644
--- a/lib/prettyprint.rb
+++ b/lib/prettyprint.rb
@@ -33,6 +33,7 @@
#
class PrettyPrint
+ # The version string
VERSION = "0.2.0"
# This is a convenience method which is same as follows:
diff --git a/lib/prism.rb b/lib/prism.rb
index 66a64e7fd0..d809557fce 100644
--- a/lib/prism.rb
+++ b/lib/prism.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+# :markup: markdown
# The Prism Ruby parser.
#
@@ -19,12 +20,14 @@ module Prism
autoload :DSL, "prism/dsl"
autoload :InspectVisitor, "prism/inspect_visitor"
autoload :LexCompat, "prism/lex_compat"
- autoload :LexRipper, "prism/lex_compat"
+ autoload :LexRipper, "prism/lex_ripper"
autoload :MutationCompiler, "prism/mutation_compiler"
autoload :Pack, "prism/pack"
autoload :Pattern, "prism/pattern"
autoload :Reflection, "prism/reflection"
+ autoload :Relocation, "prism/relocation"
autoload :Serialize, "prism/serialize"
+ autoload :StringQuery, "prism/string_query"
autoload :Translation, "prism/translation"
autoload :Visitor, "prism/visitor"
@@ -34,6 +37,26 @@ module Prism
private_constant :LexCompat
private_constant :LexRipper
+ # Raised when requested to parse as the currently running Ruby version but Prism has no support for it.
+ class CurrentVersionError < ArgumentError
+ # Initialize a new exception for the given ruby version string.
+ def initialize(version)
+ message = +"invalid version: Requested to parse as `version: 'current'`; "
+ segments =
+ if version.match?(/\A\d+\.\d+.\d+\z/)
+ version.split(".").map(&:to_i)
+ end
+
+ if segments && ((segments[0] < 3) || (segments[0] == 3 && segments[1] < 3))
+ message << " #{version} is below the minimum supported syntax."
+ else
+ message << " #{version} is unknown. Please update the `prism` gem."
+ end
+
+ super(message)
+ end
+ end
+
# :call-seq:
# Prism::lex_compat(source, **options) -> LexCompat::Result
#
@@ -57,15 +80,16 @@ module Prism
end
# :call-seq:
- # Prism::load(source, serialized) -> ParseResult
+ # Prism::load(source, serialized, freeze) -> ParseResult
#
# Load the serialized AST using the source as a reference into a tree.
- def self.load(source, serialized)
- Serialize.load(source, serialized)
+ def self.load(source, serialized, freeze = false)
+ Serialize.load_parse(source, serialized, freeze)
end
end
require_relative "prism/polyfill/byteindex"
+require_relative "prism/polyfill/warn"
require_relative "prism/node"
require_relative "prism/node_ext"
require_relative "prism/parse_result"
@@ -75,13 +99,13 @@ require_relative "prism/parse_result"
# it's going to require the built library. Otherwise, it's going to require a
# module that uses FFI to call into the library.
if RUBY_ENGINE == "ruby" and !ENV["PRISM_FFI_BACKEND"]
- require "prism/prism"
-
# The C extension is the default backend on CRuby.
Prism::BACKEND = :CEXT
-else
- require_relative "prism/ffi"
+ require "prism/prism"
+else
# The FFI backend is used on other Ruby implementations.
Prism::BACKEND = :FFI
+
+ require_relative "prism/ffi"
end
diff --git a/lib/prism/desugar_compiler.rb b/lib/prism/desugar_compiler.rb
index de02445149..5d7d38d841 100644
--- a/lib/prism/desugar_compiler.rb
+++ b/lib/prism/desugar_compiler.rb
@@ -1,12 +1,15 @@
# frozen_string_literal: true
+# :markup: markdown
module Prism
class DesugarAndWriteNode # :nodoc:
- attr_reader :node, :source, :read_class, :write_class, :arguments
+ include DSL
- def initialize(node, source, read_class, write_class, *arguments)
+ attr_reader :node, :default_source, :read_class, :write_class, :arguments
+
+ def initialize(node, default_source, read_class, write_class, **arguments)
@node = node
- @source = source
+ @default_source = default_source
@read_class = read_class
@write_class = write_class
@arguments = arguments
@@ -14,22 +17,30 @@ module Prism
# Desugar `x &&= y` to `x && x = y`
def compile
- AndNode.new(
- source,
- read_class.new(source, *arguments, node.name_loc),
- write_class.new(source, *arguments, node.name_loc, node.value, node.operator_loc, node.location),
- node.operator_loc,
- node.location
+ and_node(
+ location: node.location,
+ left: public_send(read_class, location: node.name_loc, **arguments),
+ right: public_send(
+ write_class,
+ location: node.location,
+ **arguments,
+ name_loc: node.name_loc,
+ value: node.value,
+ operator_loc: node.operator_loc
+ ),
+ operator_loc: node.operator_loc
)
end
end
class DesugarOrWriteDefinedNode # :nodoc:
- attr_reader :node, :source, :read_class, :write_class, :arguments
+ include DSL
+
+ attr_reader :node, :default_source, :read_class, :write_class, :arguments
- def initialize(node, source, read_class, write_class, *arguments)
+ def initialize(node, default_source, read_class, write_class, **arguments)
@node = node
- @source = source
+ @default_source = default_source
@read_class = read_class
@write_class = write_class
@arguments = arguments
@@ -37,35 +48,50 @@ module Prism
# Desugar `x ||= y` to `defined?(x) ? x : x = y`
def compile
- IfNode.new(
- source,
- node.operator_loc,
- DefinedNode.new(source, nil, read_class.new(source, *arguments, node.name_loc), nil, node.operator_loc, node.name_loc),
- node.operator_loc,
- StatementsNode.new(source, [read_class.new(source, *arguments, node.name_loc)], node.location),
- ElseNode.new(
- source,
- node.operator_loc,
- StatementsNode.new(
- source,
- [write_class.new(source, *arguments, node.name_loc, node.value, node.operator_loc, node.location)],
- node.location
+ if_node(
+ location: node.location,
+ if_keyword_loc: node.operator_loc,
+ predicate: defined_node(
+ location: node.name_loc,
+ value: public_send(read_class, location: node.name_loc, **arguments),
+ keyword_loc: node.operator_loc
+ ),
+ then_keyword_loc: node.operator_loc,
+ statements: statements_node(
+ location: node.location,
+ body: [public_send(read_class, location: node.name_loc, **arguments)]
+ ),
+ subsequent: else_node(
+ location: node.location,
+ else_keyword_loc: node.operator_loc,
+ statements: statements_node(
+ location: node.location,
+ body: [
+ public_send(
+ write_class,
+ location: node.location,
+ **arguments,
+ name_loc: node.name_loc,
+ value: node.value,
+ operator_loc: node.operator_loc
+ )
+ ]
),
- node.operator_loc,
- node.location
+ end_keyword_loc: node.operator_loc
),
- node.operator_loc,
- node.location
+ end_keyword_loc: node.operator_loc
)
end
end
class DesugarOperatorWriteNode # :nodoc:
- attr_reader :node, :source, :read_class, :write_class, :arguments
+ include DSL
- def initialize(node, source, read_class, write_class, *arguments)
+ attr_reader :node, :default_source, :read_class, :write_class, :arguments
+
+ def initialize(node, default_source, read_class, write_class, **arguments)
@node = node
- @source = source
+ @default_source = default_source
@read_class = read_class
@write_class = write_class
@arguments = arguments
@@ -75,35 +101,41 @@ module Prism
def compile
binary_operator_loc = node.binary_operator_loc.chop
- write_class.new(
- source,
- *arguments,
- node.name_loc,
- CallNode.new(
- source,
- 0,
- read_class.new(source, *arguments, node.name_loc),
- nil,
- binary_operator_loc.slice.to_sym,
- binary_operator_loc,
- nil,
- ArgumentsNode.new(source, 0, [node.value], node.value.location),
- nil,
- nil,
- node.location
+ public_send(
+ write_class,
+ location: node.location,
+ **arguments,
+ name_loc: node.name_loc,
+ value: call_node(
+ location: node.location,
+ receiver: public_send(
+ read_class,
+ location: node.name_loc,
+ **arguments
+ ),
+ name: binary_operator_loc.slice.to_sym,
+ message_loc: binary_operator_loc,
+ arguments: arguments_node(
+ location: node.value.location,
+ arguments: [node.value]
+ )
),
- node.binary_operator_loc.copy(start_offset: node.binary_operator_loc.end_offset - 1, length: 1),
- node.location
+ operator_loc: node.binary_operator_loc.copy(
+ start_offset: node.binary_operator_loc.end_offset - 1,
+ length: 1
+ )
)
end
end
class DesugarOrWriteNode # :nodoc:
- attr_reader :node, :source, :read_class, :write_class, :arguments
+ include DSL
- def initialize(node, source, read_class, write_class, *arguments)
+ attr_reader :node, :default_source, :read_class, :write_class, :arguments
+
+ def initialize(node, default_source, read_class, write_class, **arguments)
@node = node
- @source = source
+ @default_source = default_source
@read_class = read_class
@write_class = write_class
@arguments = arguments
@@ -111,12 +143,18 @@ module Prism
# Desugar `x ||= y` to `x || x = y`
def compile
- OrNode.new(
- source,
- read_class.new(source, *arguments, node.name_loc),
- write_class.new(source, *arguments, node.name_loc, node.value, node.operator_loc, node.location),
- node.operator_loc,
- node.location
+ or_node(
+ location: node.location,
+ left: public_send(read_class, location: node.name_loc, **arguments),
+ right: public_send(
+ write_class,
+ location: node.location,
+ **arguments,
+ name_loc: node.name_loc,
+ value: node.value,
+ operator_loc: node.operator_loc
+ ),
+ operator_loc: node.operator_loc
)
end
end
@@ -125,91 +163,91 @@ module Prism
class ClassVariableAndWriteNode
def desugar # :nodoc:
- DesugarAndWriteNode.new(self, source, ClassVariableReadNode, ClassVariableWriteNode, name).compile
+ DesugarAndWriteNode.new(self, source, :class_variable_read_node, :class_variable_write_node, name: name).compile
end
end
class ClassVariableOrWriteNode
def desugar # :nodoc:
- DesugarOrWriteDefinedNode.new(self, source, ClassVariableReadNode, ClassVariableWriteNode, name).compile
+ DesugarOrWriteDefinedNode.new(self, source, :class_variable_read_node, :class_variable_write_node, name: name).compile
end
end
class ClassVariableOperatorWriteNode
def desugar # :nodoc:
- DesugarOperatorWriteNode.new(self, source, ClassVariableReadNode, ClassVariableWriteNode, name).compile
+ DesugarOperatorWriteNode.new(self, source, :class_variable_read_node, :class_variable_write_node, name: name).compile
end
end
class ConstantAndWriteNode
def desugar # :nodoc:
- DesugarAndWriteNode.new(self, source, ConstantReadNode, ConstantWriteNode, name).compile
+ DesugarAndWriteNode.new(self, source, :constant_read_node, :constant_write_node, name: name).compile
end
end
class ConstantOrWriteNode
def desugar # :nodoc:
- DesugarOrWriteDefinedNode.new(self, source, ConstantReadNode, ConstantWriteNode, name).compile
+ DesugarOrWriteDefinedNode.new(self, source, :constant_read_node, :constant_write_node, name: name).compile
end
end
class ConstantOperatorWriteNode
def desugar # :nodoc:
- DesugarOperatorWriteNode.new(self, source, ConstantReadNode, ConstantWriteNode, name).compile
+ DesugarOperatorWriteNode.new(self, source, :constant_read_node, :constant_write_node, name: name).compile
end
end
class GlobalVariableAndWriteNode
def desugar # :nodoc:
- DesugarAndWriteNode.new(self, source, GlobalVariableReadNode, GlobalVariableWriteNode, name).compile
+ DesugarAndWriteNode.new(self, source, :global_variable_read_node, :global_variable_write_node, name: name).compile
end
end
class GlobalVariableOrWriteNode
def desugar # :nodoc:
- DesugarOrWriteDefinedNode.new(self, source, GlobalVariableReadNode, GlobalVariableWriteNode, name).compile
+ DesugarOrWriteDefinedNode.new(self, source, :global_variable_read_node, :global_variable_write_node, name: name).compile
end
end
class GlobalVariableOperatorWriteNode
def desugar # :nodoc:
- DesugarOperatorWriteNode.new(self, source, GlobalVariableReadNode, GlobalVariableWriteNode, name).compile
+ DesugarOperatorWriteNode.new(self, source, :global_variable_read_node, :global_variable_write_node, name: name).compile
end
end
class InstanceVariableAndWriteNode
def desugar # :nodoc:
- DesugarAndWriteNode.new(self, source, InstanceVariableReadNode, InstanceVariableWriteNode, name).compile
+ DesugarAndWriteNode.new(self, source, :instance_variable_read_node, :instance_variable_write_node, name: name).compile
end
end
class InstanceVariableOrWriteNode
def desugar # :nodoc:
- DesugarOrWriteNode.new(self, source, InstanceVariableReadNode, InstanceVariableWriteNode, name).compile
+ DesugarOrWriteNode.new(self, source, :instance_variable_read_node, :instance_variable_write_node, name: name).compile
end
end
class InstanceVariableOperatorWriteNode
def desugar # :nodoc:
- DesugarOperatorWriteNode.new(self, source, InstanceVariableReadNode, InstanceVariableWriteNode, name).compile
+ DesugarOperatorWriteNode.new(self, source, :instance_variable_read_node, :instance_variable_write_node, name: name).compile
end
end
class LocalVariableAndWriteNode
def desugar # :nodoc:
- DesugarAndWriteNode.new(self, source, LocalVariableReadNode, LocalVariableWriteNode, name, depth).compile
+ DesugarAndWriteNode.new(self, source, :local_variable_read_node, :local_variable_write_node, name: name, depth: depth).compile
end
end
class LocalVariableOrWriteNode
def desugar # :nodoc:
- DesugarOrWriteNode.new(self, source, LocalVariableReadNode, LocalVariableWriteNode, name, depth).compile
+ DesugarOrWriteNode.new(self, source, :local_variable_read_node, :local_variable_write_node, name: name, depth: depth).compile
end
end
class LocalVariableOperatorWriteNode
def desugar # :nodoc:
- DesugarOperatorWriteNode.new(self, source, LocalVariableReadNode, LocalVariableWriteNode, name, depth).compile
+ DesugarOperatorWriteNode.new(self, source, :local_variable_read_node, :local_variable_write_node, name: name, depth: depth).compile
end
end
diff --git a/lib/prism/ffi.rb b/lib/prism/ffi.rb
index 6b48af43cc..d4c9d60c9a 100644
--- a/lib/prism/ffi.rb
+++ b/lib/prism/ffi.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+# :markup: markdown
# typed: ignore
# This file is responsible for mirroring the API provided by the C extension by
@@ -7,13 +8,26 @@
require "rbconfig"
require "ffi"
+# We want to eagerly load this file if there are Ractors so that it does not get
+# autoloaded from within a non-main Ractor.
+require "prism/serialize" if defined?(Ractor)
+
module Prism
module LibRubyParser # :nodoc:
extend FFI::Library
# Define the library that we will be pulling functions from. Note that this
# must align with the build shared library from make/rake.
- ffi_lib File.expand_path("../../build/libprism.#{RbConfig::CONFIG["SOEXT"]}", __dir__)
+ libprism_in_build = File.expand_path("../../build/libprism.#{RbConfig::CONFIG["SOEXT"]}", __dir__)
+ libprism_in_libdir = "#{RbConfig::CONFIG["libdir"]}/prism/libprism.#{RbConfig::CONFIG["SOEXT"]}"
+
+ if File.exist?(libprism_in_build)
+ INCLUDE_DIR = File.expand_path("../../include", __dir__)
+ ffi_lib libprism_in_build
+ else
+ INCLUDE_DIR = "#{RbConfig::CONFIG["libdir"]}/prism/include"
+ ffi_lib libprism_in_libdir
+ end
# Convert a native C type declaration into a symbol that FFI understands.
# For example:
@@ -38,7 +52,7 @@ module Prism
# given functions. For each one, define a function with the same name and
# signature as the C function.
def self.load_exported_functions_from(header, *functions, callbacks)
- File.foreach(File.expand_path("../../include/#{header}", __dir__)) do |line|
+ File.foreach("#{INCLUDE_DIR}/#{header}") do |line|
# We only want to attempt to load exported functions.
next unless line.start_with?("PRISM_EXPORTED_FUNCTION ")
@@ -72,6 +86,9 @@ module Prism
end
callback :pm_parse_stream_fgets_t, [:pointer, :int, :pointer], :pointer
+ callback :pm_parse_stream_feof_t, [:pointer], :int
+ enum :pm_string_init_result_t, %i[PM_STRING_INIT_SUCCESS PM_STRING_INIT_ERROR_GENERIC PM_STRING_INIT_ERROR_DIRECTORY]
+ enum :pm_string_query_t, [:PM_STRING_QUERY_ERROR, -1, :PM_STRING_QUERY_FALSE, :PM_STRING_QUERY_TRUE]
load_exported_functions_from(
"prism.h",
@@ -82,7 +99,10 @@ module Prism
"pm_serialize_lex",
"pm_serialize_parse_lex",
"pm_parse_success_p",
- [:pm_parse_stream_fgets_t]
+ "pm_string_query_local",
+ "pm_string_query_constant",
+ "pm_string_query_method_name",
+ [:pm_parse_stream_fgets_t, :pm_parse_stream_feof_t]
)
load_exported_functions_from(
@@ -145,6 +165,9 @@ module Prism
class PrismString # :nodoc:
SIZEOF = LibRubyParser.pm_string_sizeof
+ PLATFORM_EXPECTS_UTF8 =
+ RbConfig::CONFIG["host_os"].match?(/bccwin|cygwin|djgpp|mingw|mswin|wince|darwin/i)
+
attr_reader :pointer, :length
def initialize(pointer, length, from_string)
@@ -176,13 +199,25 @@ module Prism
def self.with_file(filepath)
raise TypeError unless filepath.is_a?(String)
+ # On Windows and Mac, it's expected that filepaths will be encoded in
+ # UTF-8. If they are not, we need to convert them to UTF-8 before
+ # passing them into pm_string_mapped_init.
+ if PLATFORM_EXPECTS_UTF8 && (encoding = filepath.encoding) != Encoding::ASCII_8BIT && encoding != Encoding::UTF_8
+ filepath = filepath.encode(Encoding::UTF_8)
+ end
+
FFI::MemoryPointer.new(SIZEOF) do |pm_string|
- if LibRubyParser.pm_string_mapped_init(pm_string, filepath)
+ case (result = LibRubyParser.pm_string_mapped_init(pm_string, filepath))
+ when :PM_STRING_INIT_SUCCESS
pointer = LibRubyParser.pm_string_source(pm_string)
length = LibRubyParser.pm_string_length(pm_string)
return yield new(pointer, length, false)
- else
+ when :PM_STRING_INIT_ERROR_GENERIC
raise SystemCallError.new(filepath, FFI.errno)
+ when :PM_STRING_INIT_ERROR_DIRECTORY
+ raise Errno::EISDIR.new(filepath)
+ else
+ raise "Unknown error initializing pm_string_t: #{result.inspect}"
end
ensure
LibRubyParser.pm_string_free(pm_string)
@@ -196,7 +231,7 @@ module Prism
private_constant :LibRubyParser
# The version constant is set by reading the result of calling pm_version.
- VERSION = LibRubyParser.pm_version.read_string
+ VERSION = LibRubyParser.pm_version.read_string.freeze
class << self
# Mirror the Prism.dump API by using the serialization API.
@@ -247,13 +282,15 @@ module Prism
end
}
+ eof_callback = -> (_) { stream.eof? }
+
# In the pm_serialize_parse_stream function it accepts a pointer to the
# IO object as a void* and then passes it through to the callback as the
# third argument, but it never touches it itself. As such, since we have
# access to the IO object already through the closure of the lambda, we
# can pass a null pointer here and not worry.
- LibRubyParser.pm_serialize_parse_stream(buffer.pointer, nil, callback, dump_options(options))
- Prism.load(source, buffer.read)
+ LibRubyParser.pm_serialize_parse_stream(buffer.pointer, nil, callback, eof_callback, dump_options(options))
+ Prism.load(source, buffer.read, options.fetch(:freeze, false))
end
end
@@ -328,50 +365,37 @@ module Prism
def dump_common(string, options) # :nodoc:
LibRubyParser::PrismBuffer.with do |buffer|
LibRubyParser.pm_serialize_parse(buffer.pointer, string.pointer, string.length, dump_options(options))
- buffer.read
+
+ dumped = buffer.read
+ dumped.freeze if options.fetch(:freeze, false)
+
+ dumped
end
end
def lex_common(string, code, options) # :nodoc:
- serialized = LibRubyParser::PrismBuffer.with do |buffer|
+ LibRubyParser::PrismBuffer.with do |buffer|
LibRubyParser.pm_serialize_lex(buffer.pointer, string.pointer, string.length, dump_options(options))
- buffer.read
+ Serialize.load_lex(code, buffer.read, options.fetch(:freeze, false))
end
-
- Serialize.load_tokens(Source.for(code), serialized)
end
def parse_common(string, code, options) # :nodoc:
serialized = dump_common(string, options)
- Prism.load(code, serialized)
+ Serialize.load_parse(code, serialized, options.fetch(:freeze, false))
end
def parse_comments_common(string, code, options) # :nodoc:
LibRubyParser::PrismBuffer.with do |buffer|
LibRubyParser.pm_serialize_parse_comments(buffer.pointer, string.pointer, string.length, dump_options(options))
-
- source = Source.for(code)
- loader = Serialize::Loader.new(source, buffer.read)
-
- loader.load_header
- loader.load_encoding
- loader.load_start_line
- loader.load_comments
+ Serialize.load_parse_comments(code, buffer.read, options.fetch(:freeze, false))
end
end
def parse_lex_common(string, code, options) # :nodoc:
LibRubyParser::PrismBuffer.with do |buffer|
LibRubyParser.pm_serialize_parse_lex(buffer.pointer, string.pointer, string.length, dump_options(options))
-
- source = Source.for(code)
- loader = Serialize::Loader.new(source, buffer.read)
-
- tokens = loader.load_tokens
- node, comments, magic_comments, data_loc, errors, warnings = loader.load_nodes
- tokens.each { |token,| token.value.force_encoding(loader.encoding) }
-
- ParseLexResult.new([node, tokens], comments, magic_comments, data_loc, errors, warnings, source)
+ Serialize.load_parse_lex(code, buffer.read, options.fetch(:freeze, false))
end
end
@@ -397,6 +421,30 @@ module Prism
end
end
+ # Return the value that should be dumped for the version option.
+ def dump_options_version(version)
+ current = version == "current"
+
+ case current ? RUBY_VERSION : version
+ when nil, "latest"
+ 0 # Handled in pm_parser_init
+ when /\A3\.3(\.\d+)?\z/
+ 1
+ when /\A3\.4(\.\d+)?\z/
+ 2
+ when /\A3\.5(\.\d+)?\z/, /\A4\.0(\.\d+)?\z/
+ 3
+ when /\A4\.1(\.\d+)?\z/
+ 4
+ else
+ if current
+ raise CurrentVersionError, RUBY_VERSION
+ else
+ raise ArgumentError, "invalid version: #{version}"
+ end
+ end
+ end
+
# Convert the given options into a serialized options string.
def dump_options(options)
template = +""
@@ -429,17 +477,54 @@ module Prism
values << dump_options_command_line(options)
template << "C"
- values << { nil => 0, "3.3.0" => 1, "3.3.1" => 1, "3.4.0" => 0, "latest" => 0 }.fetch(options[:version])
+ values << dump_options_version(options[:version])
+
+ template << "C"
+ values << (options[:encoding] == false ? 1 : 0)
+
+ template << "C"
+ values << (options.fetch(:main_script, false) ? 1 : 0)
+
+ template << "C"
+ values << (options.fetch(:partial_script, false) ? 1 : 0)
+
+ template << "C"
+ values << (options.fetch(:freeze, false) ? 1 : 0)
template << "L"
if (scopes = options[:scopes])
values << scopes.length
scopes.each do |scope|
+ locals = nil
+ forwarding = 0
+
+ case scope
+ when Array
+ locals = scope
+ when Scope
+ locals = scope.locals
+
+ scope.forwarding.each do |forward|
+ case forward
+ when :* then forwarding |= 0x1
+ when :** then forwarding |= 0x2
+ when :& then forwarding |= 0x4
+ when :"..." then forwarding |= 0x8
+ else raise ArgumentError, "invalid forwarding value: #{forward}"
+ end
+ end
+ else
+ raise TypeError, "wrong argument type #{scope.class.inspect} (expected Array or Prism::Scope)"
+ end
+
template << "L"
- values << scope.length
+ values << locals.length
+
+ template << "C"
+ values << forwarding
- scope.each do |local|
+ locals.each do |local|
name = local.name
template << "L"
values << name.bytesize
@@ -455,4 +540,39 @@ module Prism
values.pack(template)
end
end
+
+ # Here we are going to patch StringQuery to put in the class-level methods so
+ # that it can maintain a consistent interface
+ class StringQuery
+ class << self
+ # Mirrors the C extension's StringQuery::local? method.
+ def local?(string)
+ query(LibRubyParser.pm_string_query_local(string, string.bytesize, string.encoding.name))
+ end
+
+ # Mirrors the C extension's StringQuery::constant? method.
+ def constant?(string)
+ query(LibRubyParser.pm_string_query_constant(string, string.bytesize, string.encoding.name))
+ end
+
+ # Mirrors the C extension's StringQuery::method_name? method.
+ def method_name?(string)
+ query(LibRubyParser.pm_string_query_method_name(string, string.bytesize, string.encoding.name))
+ end
+
+ private
+
+ # Parse the enum result and return an appropriate boolean.
+ def query(result)
+ case result
+ when :PM_STRING_QUERY_ERROR
+ raise ArgumentError, "Invalid or non ascii-compatible encoding"
+ when :PM_STRING_QUERY_FALSE
+ false
+ when :PM_STRING_QUERY_TRUE
+ true
+ end
+ end
+ end
+ end
end
diff --git a/lib/prism/lex_compat.rb b/lib/prism/lex_compat.rb
index 4f8e443a3b..b7c54178ac 100644
--- a/lib/prism/lex_compat.rb
+++ b/lib/prism/lex_compat.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
+# :markup: markdown
require "delegate"
-require "ripper"
module Prism
# This class is responsible for lexing the source using prism and then
@@ -225,14 +225,6 @@ module Prism
end
end
- # Ripper doesn't include the rest of the token in the event, so we need to
- # trim it down to just the content on the first line when comparing.
- class EndContentToken < Token
- def ==(other) # :nodoc:
- [self[0], self[1], self[2][0..self[2].index("\n")], self[3]] == other
- end
- end
-
# Tokens where state should be ignored
# used for :on_comment, :on_heredoc_end, :on_embexpr_end
class IgnoreStateToken < Token
@@ -248,8 +240,8 @@ module Prism
class IdentToken < Token
def ==(other) # :nodoc:
(self[0...-1] == other[0...-1]) && (
- (other[3] == Ripper::EXPR_LABEL | Ripper::EXPR_END) ||
- (other[3] & Ripper::EXPR_ARG_ANY != 0)
+ (other[3] == Translation::Ripper::EXPR_LABEL | Translation::Ripper::EXPR_END) ||
+ (other[3] & (Translation::Ripper::EXPR_ARG | Translation::Ripper::EXPR_CMDARG) != 0)
)
end
end
@@ -260,8 +252,8 @@ module Prism
def ==(other) # :nodoc:
return false unless self[0...-1] == other[0...-1]
- if self[3] == Ripper::EXPR_ARG | Ripper::EXPR_LABELED
- other[3] & Ripper::EXPR_ARG | Ripper::EXPR_LABELED != 0
+ if self[3] == Translation::Ripper::EXPR_ARG | Translation::Ripper::EXPR_LABELED
+ other[3] & Translation::Ripper::EXPR_ARG | Translation::Ripper::EXPR_LABELED != 0
else
self[3] == other[3]
end
@@ -279,8 +271,8 @@ module Prism
class ParamToken < Token
def ==(other) # :nodoc:
(self[0...-1] == other[0...-1]) && (
- (other[3] == Ripper::EXPR_END) ||
- (other[3] == Ripper::EXPR_END | Ripper::EXPR_LABEL)
+ (other[3] == Translation::Ripper::EXPR_END) ||
+ (other[3] == Translation::Ripper::EXPR_END | Translation::Ripper::EXPR_LABEL)
)
end
end
@@ -481,7 +473,7 @@ module Prism
embexpr_balance -= 1
when :on_tstring_content
if embexpr_balance == 0
- while index < max_index && tokens[index].event == :on_tstring_content
+ while index < max_index && tokens[index].event == :on_tstring_content && !token.value.match?(/\\\r?\n\z/)
token.value << tokens[index].value
index += 1
end
@@ -614,6 +606,11 @@ module Prism
private_constant :Heredoc
+ # In previous versions of Ruby, Ripper wouldn't flush the bom before the
+ # first token, so we had to have a hack in place to account for that.
+ BOM_FLUSHED = RUBY_VERSION >= "3.3.0"
+ private_constant :BOM_FLUSHED
+
attr_reader :source, :options
def initialize(source, **options)
@@ -629,13 +626,9 @@ module Prism
result = Prism.lex(source, **options)
result_value = result.value
- previous_state = nil #: Ripper::Lexer::State?
+ previous_state = nil #: State?
last_heredoc_end = nil #: Integer?
- # In previous versions of Ruby, Ripper wouldn't flush the bom before the
- # first token, so we had to have a hack in place to account for that. This
- # checks for that behavior.
- bom_flushed = Ripper.lex("\xEF\xBB\xBF# test")[0][0][1] == 0
bom = source.byteslice(0..2) == "\xEF\xBB\xBF"
result_value.each_with_index do |(token, lex_state), index|
@@ -650,7 +643,7 @@ module Prism
if bom && lineno == 1
column -= 3
- if index == 0 && column == 0 && !bom_flushed
+ if index == 0 && column == 0 && !BOM_FLUSHED
flushed =
case token.type
when :BACK_REFERENCE, :INSTANCE_VARIABLE, :CLASS_VARIABLE,
@@ -674,12 +667,15 @@ module Prism
event = RIPPER.fetch(token.type)
value = token.value
- lex_state = Ripper::Lexer::State.new(lex_state)
+ lex_state = Translation::Ripper::Lexer::State.new(lex_state)
token =
case event
when :on___end__
- EndContentToken.new([[lineno, column], event, value, lex_state])
+ # Ripper doesn't include the rest of the token in the event, so we need to
+ # trim it down to just the content on the first line.
+ value = value[0..value.index("\n")]
+ Token.new([[lineno, column], event, value, lex_state])
when :on_comment
IgnoreStateToken.new([[lineno, column], event, value, lex_state])
when :on_heredoc_end
@@ -688,7 +684,7 @@ module Prism
last_heredoc_end = token.location.end_offset
IgnoreStateToken.new([[lineno, column], event, value, lex_state])
when :on_ident
- if lex_state == Ripper::EXPR_END
+ if lex_state == Translation::Ripper::EXPR_END
# If we have an identifier that follows a method name like:
#
# def foo bar
@@ -698,7 +694,7 @@ module Prism
# yet. We do this more accurately, so we need to allow comparing
# against both END and END|LABEL.
ParamToken.new([[lineno, column], event, value, lex_state])
- elsif lex_state == Ripper::EXPR_END | Ripper::EXPR_LABEL
+ elsif lex_state == Translation::Ripper::EXPR_END | Translation::Ripper::EXPR_LABEL
# In the event that we're comparing identifiers, we're going to
# allow a little divergence. Ripper doesn't account for local
# variables introduced through named captures in regexes, and we
@@ -738,7 +734,7 @@ module Prism
counter += { on_embexpr_beg: -1, on_embexpr_end: 1 }[current_event] || 0
end
- Ripper::Lexer::State.new(result_value[current_index][1])
+ Translation::Ripper::Lexer::State.new(result_value[current_index][1])
else
previous_state
end
@@ -866,62 +862,4 @@ module Prism
end
private_constant :LexCompat
-
- # This is a class that wraps the Ripper lexer to produce almost exactly the
- # same tokens.
- class LexRipper # :nodoc:
- attr_reader :source
-
- def initialize(source)
- @source = source
- end
-
- def result
- previous = [] #: [[Integer, Integer], Symbol, String, untyped] | []
- results = [] #: Array[[[Integer, Integer], Symbol, String, untyped]]
-
- lex(source).each do |token|
- case token[1]
- when :on_sp
- # skip
- when :on_tstring_content
- if previous[1] == :on_tstring_content && (token[2].start_with?("\#$") || token[2].start_with?("\#@"))
- previous[2] << token[2]
- else
- results << token
- previous = token
- end
- when :on_words_sep
- if previous[1] == :on_words_sep
- previous[2] << token[2]
- else
- results << token
- previous = token
- end
- else
- results << token
- previous = token
- end
- end
-
- results
- end
-
- private
-
- if Ripper.method(:lex).parameters.assoc(:keyrest)
- def lex(source)
- Ripper.lex(source, raise_errors: true)
- end
- else
- def lex(source)
- ripper = Ripper::Lexer.new(source)
- ripper.lex.tap do |result|
- raise SyntaxError, ripper.errors.map(&:message).join(' ;') if ripper.errors.any?
- end
- end
- end
- end
-
- private_constant :LexRipper
end
diff --git a/lib/prism/lex_ripper.rb b/lib/prism/lex_ripper.rb
new file mode 100644
index 0000000000..4b5c3b77fd
--- /dev/null
+++ b/lib/prism/lex_ripper.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+# :markup: markdown
+
+require "ripper"
+
+module Prism
+ # This is a class that wraps the Ripper lexer to produce almost exactly the
+ # same tokens.
+ class LexRipper # :nodoc:
+ attr_reader :source
+
+ def initialize(source)
+ @source = source
+ end
+
+ def result
+ previous = [] #: [[Integer, Integer], Symbol, String, untyped] | []
+ results = [] #: Array[[[Integer, Integer], Symbol, String, untyped]]
+
+ lex(source).each do |token|
+ case token[1]
+ when :on_sp
+ # skip
+ when :on_tstring_content
+ if previous[1] == :on_tstring_content && (token[2].start_with?("\#$") || token[2].start_with?("\#@"))
+ previous[2] << token[2]
+ else
+ results << token
+ previous = token
+ end
+ when :on_words_sep
+ if previous[1] == :on_words_sep
+ previous[2] << token[2]
+ else
+ results << token
+ previous = token
+ end
+ else
+ results << token
+ previous = token
+ end
+ end
+
+ results
+ end
+
+ private
+
+ if Ripper.method(:lex).parameters.assoc(:keyrest)
+ def lex(source)
+ Ripper.lex(source, raise_errors: true)
+ end
+ else
+ def lex(source)
+ ripper = Ripper::Lexer.new(source)
+ ripper.lex.tap do |result|
+ raise SyntaxError, ripper.errors.map(&:message).join(' ;') if ripper.errors.any?
+ end
+ end
+ end
+ end
+
+ private_constant :LexRipper
+end
diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb
index cdc4b2bf08..469e54ca0c 100644
--- a/lib/prism/node_ext.rb
+++ b/lib/prism/node_ext.rb
@@ -1,14 +1,20 @@
# frozen_string_literal: true
+# :markup: markdown
+#--
# Here we are reopening the prism module to provide methods on nodes that aren't
# templated and are meant as convenience methods.
+#++
module Prism
class Node
def deprecated(*replacements) # :nodoc:
+ location = caller_locations(1, 1)
+ location = location[0].label if location
suggest = replacements.map { |replacement| "#{self.class}##{replacement}" }
- warn(<<~MSG, category: :deprecated)
- [deprecation]: #{self.class}##{caller_locations(1, 1)[0].label} is deprecated \
- and will be removed in the next major version. Use #{suggest.join("/")} instead.
+
+ warn(<<~MSG, uplevel: 1, category: :deprecated)
+ [deprecation]: #{self.class}##{location} is deprecated and will be \
+ removed in the next major version. Use #{suggest.join("/")} instead.
#{(caller(1, 3) || []).join("\n")}
MSG
end
@@ -18,7 +24,10 @@ module Prism
# Returns a numeric value that represents the flags that were used to create
# the regular expression.
def options
- o = flags & (RegularExpressionFlags::IGNORE_CASE | RegularExpressionFlags::EXTENDED | RegularExpressionFlags::MULTI_LINE)
+ o = 0
+ o |= Regexp::IGNORECASE if flags.anybits?(RegularExpressionFlags::IGNORE_CASE)
+ o |= Regexp::EXTENDED if flags.anybits?(RegularExpressionFlags::EXTENDED)
+ o |= Regexp::MULTILINE if flags.anybits?(RegularExpressionFlags::MULTI_LINE)
o |= Regexp::FIXEDENCODING if flags.anybits?(RegularExpressionFlags::EUC_JP | RegularExpressionFlags::WINDOWS_31J | RegularExpressionFlags::UTF_8)
o |= Regexp::NOENCODING if flags.anybits?(RegularExpressionFlags::ASCII_8BIT)
o
@@ -66,11 +75,12 @@ module Prism
def to_interpolated
InterpolatedStringNode.new(
source,
+ -1,
+ location,
frozen? ? InterpolatedStringNodeFlags::FROZEN : 0,
opening_loc,
- [copy(opening_loc: nil, closing_loc: nil, location: content_loc)],
- closing_loc,
- location
+ [copy(location: content_loc, opening_loc: nil, closing_loc: nil)],
+ closing_loc
)
end
end
@@ -83,10 +93,12 @@ module Prism
def to_interpolated
InterpolatedXStringNode.new(
source,
+ -1,
+ location,
+ flags,
opening_loc,
- [StringNode.new(source, 0, nil, content_loc, nil, unescaped, content_loc)],
- closing_loc,
- location
+ [StringNode.new(source, node_id, content_loc, 0, nil, content_loc, nil, unescaped)],
+ closing_loc
)
end
end
@@ -112,9 +124,9 @@ module Prism
deprecated("value", "numerator", "denominator")
if denominator == 1
- IntegerNode.new(source, flags, numerator, location.chop)
+ IntegerNode.new(source, -1, location.chop, flags, numerator)
else
- FloatNode.new(source, numerator.to_f / denominator, location.chop)
+ FloatNode.new(source, -1, location.chop, 0, numerator.to_f / denominator)
end
end
end
@@ -192,7 +204,12 @@ module Prism
# continue to supply that API.
def child
deprecated("name", "name_loc")
- name ? ConstantReadNode.new(source, name, name_loc) : MissingNode.new(source, location)
+
+ if name
+ ConstantReadNode.new(source, -1, name_loc, 0, name)
+ else
+ MissingNode.new(source, -1, location, 0)
+ end
end
end
@@ -228,7 +245,12 @@ module Prism
# continue to supply that API.
def child
deprecated("name", "name_loc")
- name ? ConstantReadNode.new(source, name, name_loc) : MissingNode.new(source, location)
+
+ if name
+ ConstantReadNode.new(source, -1, name_loc, 0, name)
+ else
+ MissingNode.new(source, -1, location, 0)
+ end
end
end
@@ -261,9 +283,10 @@ module Prism
end
posts.each do |param|
- if param.is_a?(MultiTargetNode)
+ case param
+ when MultiTargetNode
names << [:req]
- elsif param.is_a?(NoKeywordsParameterNode)
+ when NoKeywordsParameterNode, KeywordRestParameterNode, ForwardingParameterNode
# Invalid syntax, e.g. "def f(**nil, ...)" moves the NoKeywordsParameterNode to posts
raise "Invalid syntax"
else
@@ -440,4 +463,49 @@ module Prism
binary_operator_loc
end
end
+
+ class CaseMatchNode < Node
+ # Returns the else clause of the case match node. This method is deprecated
+ # in favor of #else_clause.
+ def consequent
+ deprecated("else_clause")
+ else_clause
+ end
+ end
+
+ class CaseNode < Node
+ # Returns the else clause of the case node. This method is deprecated in
+ # favor of #else_clause.
+ def consequent
+ deprecated("else_clause")
+ else_clause
+ end
+ end
+
+ class IfNode < Node
+ # Returns the subsequent if/elsif/else clause of the if node. This method is
+ # deprecated in favor of #subsequent.
+ def consequent
+ deprecated("subsequent")
+ subsequent
+ end
+ end
+
+ class RescueNode < Node
+ # Returns the subsequent rescue clause of the rescue node. This method is
+ # deprecated in favor of #subsequent.
+ def consequent
+ deprecated("subsequent")
+ subsequent
+ end
+ end
+
+ class UnlessNode < Node
+ # Returns the else clause of the unless node. This method is deprecated in
+ # favor of #else_clause.
+ def consequent
+ deprecated("else_clause")
+ else_clause
+ end
+ end
end
diff --git a/lib/prism/pack.rb b/lib/prism/pack.rb
index c0de8ab8b7..166c04c3c0 100644
--- a/lib/prism/pack.rb
+++ b/lib/prism/pack.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
+# :markup: markdown
# typed: ignore
+#
module Prism
# A parser for the pack template language.
module Pack
diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb
index 798fde09e5..12d19da562 100644
--- a/lib/prism/parse_result.rb
+++ b/lib/prism/parse_result.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+# :markup: markdown
module Prism
# This represents a source of Ruby code that has been parsed. It is used in
@@ -10,7 +11,26 @@ module Prism
# specialized and more performant `ASCIISource` if no multibyte characters
# are present in the source code.
def self.for(source, start_line = 1, offsets = [])
- source.ascii_only? ? ASCIISource.new(source, start_line, offsets): new(source, start_line, offsets)
+ if source.ascii_only?
+ ASCIISource.new(source, start_line, offsets)
+ elsif source.encoding == Encoding::BINARY
+ source.force_encoding(Encoding::UTF_8)
+
+ if source.valid_encoding?
+ new(source, start_line, offsets)
+ else
+ # This is an extremely niche use case where the file is marked as
+ # binary, contains multi-byte characters, and those characters are not
+ # valid UTF-8. In this case we'll mark it as binary and fall back to
+ # treating everything as a single-byte character. This _may_ cause
+ # problems when asking for code units, but it appears to be the
+ # cleanest solution at the moment.
+ source.force_encoding(Encoding::BINARY)
+ ASCIISource.new(source, start_line, offsets)
+ end
+ else
+ new(source, start_line, offsets)
+ end
end
# The source code that this source object represents.
@@ -29,6 +49,16 @@ module Prism
@offsets = offsets # set after parsing is done
end
+ # Replace the value of start_line with the given value.
+ def replace_start_line(start_line)
+ @start_line = start_line
+ end
+
+ # Replace the value of offsets with the given value.
+ def replace_offsets(offsets)
+ @offsets.replace(offsets)
+ end
+
# Returns the encoding of the source code, which is set by parameters to the
# parser or by the encoding magic comment.
def encoding
@@ -46,6 +76,15 @@ module Prism
source.byteslice(byte_offset, length) or raise
end
+ # Converts the line number to a byte offset corresponding to the start of that line
+ def line_to_byte_offset(line)
+ l = line - @start_line
+ if l < 0 || l >= offsets.size
+ raise ArgumentError, "line #{line} is out of range"
+ end
+ offsets[l]
+ end
+
# Binary search through the offsets to find the line number for the given
# byte offset.
def line(byte_offset)
@@ -85,9 +124,26 @@ module Prism
# This method is tested with UTF-8, UTF-16, and UTF-32. If there is the
# concept of code units that differs from the number of characters in other
# encodings, it is not captured here.
+ #
+ # We purposefully replace invalid and undefined characters with replacement
+ # characters in this conversion. This happens for two reasons. First, it's
+ # possible that the given byte offset will not occur on a character
+ # boundary. Second, it's possible that the source code will contain a
+ # character that has no equivalent in the given encoding.
def code_units_offset(byte_offset, encoding)
- byteslice = (source.byteslice(0, byte_offset) or raise).encode(encoding)
- (encoding == Encoding::UTF_16LE || encoding == Encoding::UTF_16BE) ? (byteslice.bytesize / 2) : byteslice.length
+ byteslice = (source.byteslice(0, byte_offset) or raise).encode(encoding, invalid: :replace, undef: :replace)
+
+ if encoding == Encoding::UTF_16LE || encoding == Encoding::UTF_16BE
+ byteslice.bytesize / 2
+ else
+ byteslice.length
+ end
+ end
+
+ # Generate a cache that targets a specific encoding for calculating code
+ # unit offsets.
+ def code_units_cache(encoding)
+ CodeUnitsCache.new(source, encoding)
end
# Returns the column number in code units for the given encoding for the
@@ -96,33 +152,101 @@ module Prism
code_units_offset(byte_offset, encoding) - code_units_offset(line_start(byte_offset), encoding)
end
+ # Freeze this object and the objects it contains.
+ def deep_freeze
+ source.freeze
+ offsets.freeze
+ freeze
+ end
+
private
# Binary search through the offsets to find the line number for the given
# byte offset.
def find_line(byte_offset)
- left = 0
- right = offsets.length - 1
+ index = offsets.bsearch_index { |offset| offset > byte_offset } || offsets.length
+ index - 1
+ end
+ end
+
+ # A cache that can be used to quickly compute code unit offsets from byte
+ # offsets. It purposefully provides only a single #[] method to access the
+ # cache in order to minimize surface area.
+ #
+ # Note that there are some known issues here that may or may not be addressed
+ # in the future:
+ #
+ # * The first is that there are issues when the cache computes values that are
+ # not on character boundaries. This can result in subsequent computations
+ # being off by one or more code units.
+ # * The second is that this cache is currently unbounded. In theory we could
+ # introduce some kind of LRU cache to limit the number of entries, but this
+ # has not yet been implemented.
+ #
+ class CodeUnitsCache
+ class UTF16Counter # :nodoc:
+ def initialize(source, encoding)
+ @source = source
+ @encoding = encoding
+ end
+
+ def count(byte_offset, byte_length)
+ @source.byteslice(byte_offset, byte_length).encode(@encoding, invalid: :replace, undef: :replace).bytesize / 2
+ end
+ end
+
+ class LengthCounter # :nodoc:
+ def initialize(source, encoding)
+ @source = source
+ @encoding = encoding
+ end
+
+ def count(byte_offset, byte_length)
+ @source.byteslice(byte_offset, byte_length).encode(@encoding, invalid: :replace, undef: :replace).length
+ end
+ end
- while left <= right
- mid = left + (right - left) / 2
- return mid if (offset = offsets[mid]) == byte_offset
+ private_constant :UTF16Counter, :LengthCounter
- if offset < byte_offset
- left = mid + 1
+ # Initialize a new cache with the given source and encoding.
+ def initialize(source, encoding)
+ @source = source
+ @counter =
+ if encoding == Encoding::UTF_16LE || encoding == Encoding::UTF_16BE
+ UTF16Counter.new(source, encoding)
else
- right = mid - 1
+ LengthCounter.new(source, encoding)
end
- end
- left - 1
+ @cache = {} #: Hash[Integer, Integer]
+ @offsets = [] #: Array[Integer]
+ end
+
+ # Retrieve the code units offset from the given byte offset.
+ def [](byte_offset)
+ @cache[byte_offset] ||=
+ if (index = @offsets.bsearch_index { |offset| offset > byte_offset }).nil?
+ @offsets << byte_offset
+ @counter.count(0, byte_offset)
+ elsif index == 0
+ @offsets.unshift(byte_offset)
+ @counter.count(0, byte_offset)
+ else
+ @offsets.insert(index, byte_offset)
+ offset = @offsets[index - 1]
+ @cache[offset] + @counter.count(offset, byte_offset - offset)
+ end
end
end
# Specialized version of Prism::Source for source code that includes ASCII
# characters only. This class is used to apply performance optimizations that
- # cannot be applied to sources that include multibyte characters. Sources that
- # include multibyte characters are represented by the Prism::Source class.
+ # cannot be applied to sources that include multibyte characters.
+ #
+ # In the extremely rare case that a source includes multi-byte characters but
+ # is marked as binary because of a magic encoding comment and it cannot be
+ # eagerly converted to UTF-8, this class will be used as well. This is because
+ # at that point we will treat everything as single-byte characters.
class ASCIISource < Source
# Return the character offset for the given byte offset.
def character_offset(byte_offset)
@@ -144,9 +268,16 @@ module Prism
byte_offset
end
+ # Returns a cache that is the identity function in order to maintain the
+ # same interface. We can do this because code units are always equivalent to
+ # byte offsets for ASCII-only sources.
+ def code_units_cache(encoding)
+ ->(byte_offset) { byte_offset }
+ end
+
# Specialized version of `code_units_column` that does not depend on
# `code_units_offset`, which is a more expensive operation. This is
- # essentialy the same as `Prism::Source#column`.
+ # essentially the same as `Prism::Source#column`.
def code_units_column(byte_offset, encoding)
byte_offset - line_start(byte_offset)
end
@@ -253,6 +384,12 @@ module Prism
source.code_units_offset(start_offset, encoding)
end
+ # The start offset from the start of the file in code units using the given
+ # cache to fetch or calculate the value.
+ def cached_start_code_units_offset(cache)
+ cache[start_offset]
+ end
+
# The byte offset from the beginning of the source where this location ends.
def end_offset
start_offset + length
@@ -269,6 +406,12 @@ module Prism
source.code_units_offset(end_offset, encoding)
end
+ # The end offset from the start of the file in code units using the given
+ # cache to fetch or calculate the value.
+ def cached_end_code_units_offset(cache)
+ cache[end_offset]
+ end
+
# The line number where this location starts.
def start_line
source.line(start_offset)
@@ -303,6 +446,12 @@ module Prism
source.code_units_column(start_offset, encoding)
end
+ # The start column in code units using the given cache to fetch or calculate
+ # the value.
+ def cached_start_code_units_column(cache)
+ cache[start_offset] - cache[source.line_start(start_offset)]
+ end
+
# The column number in bytes where this location ends from the start of the
# line.
def end_column
@@ -321,6 +470,12 @@ module Prism
source.code_units_column(end_offset, encoding)
end
+ # The end column in code units using the given cache to fetch or calculate
+ # the value.
+ def cached_end_code_units_column(cache)
+ cache[end_offset] - cache[source.line_start(end_offset)]
+ end
+
# Implement the hash pattern matching interface for Location.
def deconstruct_keys(keys)
{ start_offset: start_offset, end_offset: end_offset }
@@ -570,14 +725,21 @@ module Prism
def failure?
!success?
end
+
+ # Create a code units cache for the given encoding.
+ def code_units_cache(encoding)
+ source.code_units_cache(encoding)
+ end
end
# This is a result specific to the `parse` and `parse_file` methods.
class ParseResult < Result
autoload :Comments, "prism/parse_result/comments"
+ autoload :Errors, "prism/parse_result/errors"
autoload :Newlines, "prism/parse_result/newlines"
private_constant :Comments
+ private_constant :Errors
private_constant :Newlines
# The syntax tree that was parsed from the source code.
@@ -604,6 +766,12 @@ module Prism
def mark_newlines!
value.accept(Newlines.new(source.offsets.size)) # steep:ignore
end
+
+ # Returns a string representation of the syntax tree with the errors
+ # displayed inline.
+ def errors_format
+ Errors.new(self).format
+ end
end
# This is a result specific to the `lex` and `lex_file` methods.
@@ -694,5 +862,46 @@ module Prism
other.type == type &&
other.value == value
end
+
+ # Returns a string representation of this token.
+ def inspect
+ location
+ super
+ end
+
+ # Freeze this object and the objects it contains.
+ def deep_freeze
+ value.freeze
+ location.freeze
+ freeze
+ end
+ end
+
+ # This object is passed to the various Prism.* methods that accept the
+ # `scopes` option as an element of the list. It defines both the local
+ # variables visible at that scope as well as the forwarding parameters
+ # available at that scope.
+ class Scope
+ # The list of local variables that are defined in this scope. This should be
+ # defined as an array of symbols.
+ attr_reader :locals
+
+ # The list of local variables that are forwarded to the next scope. This
+ # should by defined as an array of symbols containing the specific values of
+ # :*, :**, :&, or :"...".
+ attr_reader :forwarding
+
+ # Create a new scope object with the given locals and forwarding.
+ def initialize(locals, forwarding)
+ @locals = locals
+ @forwarding = forwarding
+ end
+ end
+
+ # Create a new scope with the given locals and forwarding options that is
+ # suitable for passing into one of the Prism.* methods that accepts the
+ # `scopes` option.
+ def self.scope(locals: [], forwarding: [])
+ Scope.new(locals, forwarding)
end
end
diff --git a/lib/prism/parse_result/comments.rb b/lib/prism/parse_result/comments.rb
index 22c4148b2c..3e93316aff 100644
--- a/lib/prism/parse_result/comments.rb
+++ b/lib/prism/parse_result/comments.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+# :markup: markdown
module Prism
class ParseResult < Result
diff --git a/lib/prism/parse_result/errors.rb b/lib/prism/parse_result/errors.rb
new file mode 100644
index 0000000000..26c376b3ce
--- /dev/null
+++ b/lib/prism/parse_result/errors.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+# :markup: markdown
+
+require "stringio"
+
+module Prism
+ class ParseResult < Result
+ # An object to represent the set of errors on a parse result. This object
+ # can be used to format the errors in a human-readable way.
+ class Errors
+ # The parse result that contains the errors.
+ attr_reader :parse_result
+
+ # Initialize a new set of errors from the given parse result.
+ def initialize(parse_result)
+ @parse_result = parse_result
+ end
+
+ # Formats the errors in a human-readable way and return them as a string.
+ def format
+ error_lines = {} #: Hash[Integer, Array[ParseError]]
+ parse_result.errors.each do |error|
+ location = error.location
+ (location.start_line..location.end_line).each do |line|
+ error_lines[line] ||= []
+ error_lines[line] << error
+ end
+ end
+
+ source_lines = parse_result.source.source.lines
+ source_lines << "" if error_lines.key?(source_lines.size + 1)
+
+ io = StringIO.new
+ source_lines.each.with_index(1) do |line, line_number|
+ io.puts(line)
+
+ (error_lines.delete(line_number) || []).each do |error|
+ location = error.location
+
+ case line_number
+ when location.start_line
+ io.print(" " * location.start_column + "^")
+
+ if location.start_line == location.end_line
+ if location.start_column != location.end_column
+ io.print("~" * (location.end_column - location.start_column - 1))
+ end
+
+ io.puts(" " + error.message)
+ else
+ io.puts("~" * (line.bytesize - location.start_column))
+ end
+ when location.end_line
+ io.puts("~" * location.end_column + " " + error.message)
+ else
+ io.puts("~" * line.bytesize)
+ end
+ end
+ end
+
+ io.puts
+ io.string
+ end
+ end
+ end
+end
diff --git a/lib/prism/parse_result/newlines.rb b/lib/prism/parse_result/newlines.rb
index cc1343dfda..e7fd62cafe 100644
--- a/lib/prism/parse_result/newlines.rb
+++ b/lib/prism/parse_result/newlines.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+# :markup: markdown
module Prism
class ParseResult < Result
@@ -25,6 +26,7 @@ module Prism
class Newlines < Visitor
# Create a new Newlines visitor with the given newline offsets.
def initialize(lines)
+ # @type var lines: Integer
@lines = Array.new(1 + lines, false)
end
@@ -44,7 +46,7 @@ module Prism
# Mark if/unless nodes as newlines.
def visit_if_node(node)
- node.newline!(@lines)
+ node.newline_flag!(@lines)
super(node)
end
@@ -53,7 +55,7 @@ module Prism
# Permit statements lists to mark newlines within themselves.
def visit_statements_node(node)
node.body.each do |child|
- child.newline!(@lines)
+ child.newline_flag!(@lines)
end
super(node)
end
@@ -61,93 +63,93 @@ module Prism
end
class Node
- def newline? # :nodoc:
- @newline ? true : false
+ def newline_flag? # :nodoc:
+ !!defined?(@newline_flag)
end
- def newline!(lines) # :nodoc:
+ def newline_flag!(lines) # :nodoc:
line = location.start_line
unless lines[line]
lines[line] = true
- @newline = true
+ @newline_flag = true
end
end
end
class BeginNode < Node
- def newline!(lines) # :nodoc:
+ def newline_flag!(lines) # :nodoc:
# Never mark BeginNode with a newline flag, mark children instead.
end
end
class ParenthesesNode < Node
- def newline!(lines) # :nodoc:
+ def newline_flag!(lines) # :nodoc:
# Never mark ParenthesesNode with a newline flag, mark children instead.
end
end
class IfNode < Node
- def newline!(lines) # :nodoc:
- predicate.newline!(lines)
+ def newline_flag!(lines) # :nodoc:
+ predicate.newline_flag!(lines)
end
end
class UnlessNode < Node
- def newline!(lines) # :nodoc:
- predicate.newline!(lines)
+ def newline_flag!(lines) # :nodoc:
+ predicate.newline_flag!(lines)
end
end
class UntilNode < Node
- def newline!(lines) # :nodoc:
- predicate.newline!(lines)
+ def newline_flag!(lines) # :nodoc:
+ predicate.newline_flag!(lines)
end
end
class WhileNode < Node
- def newline!(lines) # :nodoc:
- predicate.newline!(lines)
+ def newline_flag!(lines) # :nodoc:
+ predicate.newline_flag!(lines)
end
end
class RescueModifierNode < Node
- def newline!(lines) # :nodoc:
- expression.newline!(lines)
+ def newline_flag!(lines) # :nodoc:
+ expression.newline_flag!(lines)
end
end
class InterpolatedMatchLastLineNode < Node
- def newline!(lines) # :nodoc:
+ def newline_flag!(lines) # :nodoc:
first = parts.first
- first.newline!(lines) if first
+ first.newline_flag!(lines) if first
end
end
class InterpolatedRegularExpressionNode < Node
- def newline!(lines) # :nodoc:
+ def newline_flag!(lines) # :nodoc:
first = parts.first
- first.newline!(lines) if first
+ first.newline_flag!(lines) if first
end
end
class InterpolatedStringNode < Node
- def newline!(lines) # :nodoc:
+ def newline_flag!(lines) # :nodoc:
first = parts.first
- first.newline!(lines) if first
+ first.newline_flag!(lines) if first
end
end
class InterpolatedSymbolNode < Node
- def newline!(lines) # :nodoc:
+ def newline_flag!(lines) # :nodoc:
first = parts.first
- first.newline!(lines) if first
+ first.newline_flag!(lines) if first
end
end
class InterpolatedXStringNode < Node
- def newline!(lines) # :nodoc:
+ def newline_flag!(lines) # :nodoc:
first = parts.first
- first.newline!(lines) if first
+ first.newline_flag!(lines) if first
end
end
end
diff --git a/lib/prism/pattern.rb b/lib/prism/pattern.rb
index 03fec26789..6ad2d9e5b9 100644
--- a/lib/prism/pattern.rb
+++ b/lib/prism/pattern.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+# :markup: markdown
module Prism
# A pattern is an object that wraps a Ruby pattern matching expression. The
diff --git a/lib/prism/polyfill/append_as_bytes.rb b/lib/prism/polyfill/append_as_bytes.rb
new file mode 100644
index 0000000000..24218bd171
--- /dev/null
+++ b/lib/prism/polyfill/append_as_bytes.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+# Polyfill for String#append_as_bytes, which didn't exist until Ruby 3.4.
+if !("".respond_to?(:append_as_bytes))
+ String.include(
+ Module.new {
+ def append_as_bytes(*args)
+ args.each do |arg|
+ arg = Integer === arg ? [arg].pack("C") : arg.b
+ self.<<(arg) # steep:ignore
+ end
+ end
+ }
+ )
+end
diff --git a/lib/prism/polyfill/scan_byte.rb b/lib/prism/polyfill/scan_byte.rb
new file mode 100644
index 0000000000..9276e509fc
--- /dev/null
+++ b/lib/prism/polyfill/scan_byte.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+require "strscan"
+
+# Polyfill for StringScanner#scan_byte, which didn't exist until Ruby 3.4.
+if !(StringScanner.method_defined?(:scan_byte))
+ StringScanner.include(
+ Module.new {
+ def scan_byte # :nodoc:
+ get_byte&.b&.ord
+ end
+ }
+ )
+end
diff --git a/lib/prism/polyfill/warn.rb b/lib/prism/polyfill/warn.rb
new file mode 100644
index 0000000000..76a4264623
--- /dev/null
+++ b/lib/prism/polyfill/warn.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+# Polyfill for Kernel#warn with the category parameter. Not all Ruby engines
+# have Method#parameters implemented, so we check the arity instead if
+# necessary.
+if (method = Kernel.instance_method(:warn)).respond_to?(:parameters) ? method.parameters.none? { |_, name| name == :category } : (method.arity == -1)
+ Kernel.prepend(
+ Module.new {
+ def warn(*msgs, uplevel: nil, category: nil) # :nodoc:
+ case uplevel
+ when nil
+ super(*msgs)
+ when Integer
+ super(*msgs, uplevel: uplevel + 1)
+ else
+ super(*msgs, uplevel: uplevel.to_int + 1)
+ end
+ end
+ }
+ )
+
+ Object.prepend(
+ Module.new {
+ def warn(*msgs, uplevel: nil, category: nil) # :nodoc:
+ case uplevel
+ when nil
+ super(*msgs)
+ when Integer
+ super(*msgs, uplevel: uplevel + 1)
+ else
+ super(*msgs, uplevel: uplevel.to_int + 1)
+ end
+ end
+ }
+ )
+end
diff --git a/lib/prism/prism.gemspec b/lib/prism/prism.gemspec
index b4504dbf4b..283c7b04aa 100644
--- a/lib/prism/prism.gemspec
+++ b/lib/prism/prism.gemspec
@@ -2,7 +2,7 @@
Gem::Specification.new do |spec|
spec.name = "prism"
- spec.version = "0.29.0"
+ spec.version = "1.8.0"
spec.authors = ["Shopify"]
spec.email = ["ruby@shopify.com"]
@@ -35,6 +35,7 @@ Gem::Specification.new do |spec|
"docs/parser_translation.md",
"docs/parsing_rules.md",
"docs/releasing.md",
+ "docs/relocation.md",
"docs/ripper_translation.md",
"docs/ruby_api.md",
"docs/ruby_parser_translation.md",
@@ -65,7 +66,6 @@ Gem::Specification.new do |spec|
"include/prism/util/pm_newline_list.h",
"include/prism/util/pm_strncasecmp.h",
"include/prism/util/pm_string.h",
- "include/prism/util/pm_string_list.h",
"include/prism/util/pm_strpbrk.h",
"include/prism/version.h",
"lib/prism.rb",
@@ -77,26 +77,35 @@ Gem::Specification.new do |spec|
"lib/prism/ffi.rb",
"lib/prism/inspect_visitor.rb",
"lib/prism/lex_compat.rb",
+ "lib/prism/lex_ripper.rb",
"lib/prism/mutation_compiler.rb",
"lib/prism/node_ext.rb",
"lib/prism/node.rb",
"lib/prism/pack.rb",
"lib/prism/parse_result.rb",
"lib/prism/parse_result/comments.rb",
+ "lib/prism/parse_result/errors.rb",
"lib/prism/parse_result/newlines.rb",
"lib/prism/pattern.rb",
+ "lib/prism/polyfill/append_as_bytes.rb",
"lib/prism/polyfill/byteindex.rb",
+ "lib/prism/polyfill/scan_byte.rb",
"lib/prism/polyfill/unpack1.rb",
+ "lib/prism/polyfill/warn.rb",
"lib/prism/reflection.rb",
+ "lib/prism/relocation.rb",
"lib/prism/serialize.rb",
+ "lib/prism/string_query.rb",
"lib/prism/translation.rb",
"lib/prism/translation/parser.rb",
- "lib/prism/translation/parser33.rb",
- "lib/prism/translation/parser34.rb",
+ "lib/prism/translation/parser_current.rb",
+ "lib/prism/translation/parser_versions.rb",
+ "lib/prism/translation/parser/builder.rb",
"lib/prism/translation/parser/compiler.rb",
"lib/prism/translation/parser/lexer.rb",
- "lib/prism/translation/parser/rubocop.rb",
"lib/prism/translation/ripper.rb",
+ "lib/prism/translation/ripper/filter.rb",
+ "lib/prism/translation/ripper/lexer.rb",
"lib/prism/translation/ripper/sexp.rb",
"lib/prism/translation/ripper/shim.rb",
"lib/prism/translation/ruby_parser.rb",
@@ -104,14 +113,15 @@ Gem::Specification.new do |spec|
"prism.gemspec",
"rbi/prism.rbi",
"rbi/prism/compiler.rbi",
+ "rbi/prism/dsl.rbi",
"rbi/prism/inspect_visitor.rbi",
"rbi/prism/node_ext.rbi",
"rbi/prism/node.rbi",
"rbi/prism/parse_result.rbi",
"rbi/prism/reflection.rbi",
+ "rbi/prism/string_query.rbi",
"rbi/prism/translation/parser.rbi",
- "rbi/prism/translation/parser33.rbi",
- "rbi/prism/translation/parser34.rbi",
+ "rbi/prism/translation/parser_versions.rbi",
"rbi/prism/translation/ripper.rbi",
"rbi/prism/visitor.rbi",
"sig/prism.rbs",
@@ -126,9 +136,12 @@ Gem::Specification.new do |spec|
"sig/prism/node.rbs",
"sig/prism/pack.rbs",
"sig/prism/parse_result.rbs",
+ "sig/prism/parse_result/comments.rbs",
"sig/prism/pattern.rbs",
"sig/prism/reflection.rbs",
+ "sig/prism/relocation.rbs",
"sig/prism/serialize.rbs",
+ "sig/prism/string_query.rbs",
"sig/prism/visitor.rbs",
"src/diagnostic.c",
"src/encoding.c",
@@ -148,7 +161,6 @@ Gem::Specification.new do |spec|
"src/util/pm_list.c",
"src/util/pm_memchr.c",
"src/util/pm_newline_list.c",
- "src/util/pm_string_list.c",
"src/util/pm_string.c",
"src/util/pm_strncasecmp.c",
"src/util/pm_strpbrk.c"
diff --git a/lib/prism/relocation.rb b/lib/prism/relocation.rb
new file mode 100644
index 0000000000..3e9210a785
--- /dev/null
+++ b/lib/prism/relocation.rb
@@ -0,0 +1,505 @@
+# frozen_string_literal: true
+# :markup: markdown
+
+module Prism
+ # Prism parses deterministically for the same input. This provides a nice
+ # property that is exposed through the #node_id API on nodes. Effectively this
+ # means that for the same input, these values will remain consistent every
+ # time the source is parsed. This means we can reparse the source same with a
+ # #node_id value and find the exact same node again.
+ #
+ # The Relocation module provides an API around this property. It allows you to
+ # "save" nodes and locations using a minimal amount of memory (just the
+ # node_id and a field identifier) and then reify them later.
+ module Relocation
+ # An entry in a repository that will lazily reify its values when they are
+ # first accessed.
+ class Entry
+ # Raised if a value that could potentially be on an entry is missing
+ # because it was either not configured on the repository or it has not yet
+ # been fetched.
+ class MissingValueError < StandardError
+ end
+
+ # Initialize a new entry with the given repository.
+ def initialize(repository)
+ @repository = repository
+ @values = nil
+ end
+
+ # Fetch the filepath of the value.
+ def filepath
+ fetch_value(:filepath)
+ end
+
+ # Fetch the start line of the value.
+ def start_line
+ fetch_value(:start_line)
+ end
+
+ # Fetch the end line of the value.
+ def end_line
+ fetch_value(:end_line)
+ end
+
+ # Fetch the start byte offset of the value.
+ def start_offset
+ fetch_value(:start_offset)
+ end
+
+ # Fetch the end byte offset of the value.
+ def end_offset
+ fetch_value(:end_offset)
+ end
+
+ # Fetch the start character offset of the value.
+ def start_character_offset
+ fetch_value(:start_character_offset)
+ end
+
+ # Fetch the end character offset of the value.
+ def end_character_offset
+ fetch_value(:end_character_offset)
+ end
+
+ # Fetch the start code units offset of the value, for the encoding that
+ # was configured on the repository.
+ def start_code_units_offset
+ fetch_value(:start_code_units_offset)
+ end
+
+ # Fetch the end code units offset of the value, for the encoding that was
+ # configured on the repository.
+ def end_code_units_offset
+ fetch_value(:end_code_units_offset)
+ end
+
+ # Fetch the start byte column of the value.
+ def start_column
+ fetch_value(:start_column)
+ end
+
+ # Fetch the end byte column of the value.
+ def end_column
+ fetch_value(:end_column)
+ end
+
+ # Fetch the start character column of the value.
+ def start_character_column
+ fetch_value(:start_character_column)
+ end
+
+ # Fetch the end character column of the value.
+ def end_character_column
+ fetch_value(:end_character_column)
+ end
+
+ # Fetch the start code units column of the value, for the encoding that
+ # was configured on the repository.
+ def start_code_units_column
+ fetch_value(:start_code_units_column)
+ end
+
+ # Fetch the end code units column of the value, for the encoding that was
+ # configured on the repository.
+ def end_code_units_column
+ fetch_value(:end_code_units_column)
+ end
+
+ # Fetch the leading comments of the value.
+ def leading_comments
+ fetch_value(:leading_comments)
+ end
+
+ # Fetch the trailing comments of the value.
+ def trailing_comments
+ fetch_value(:trailing_comments)
+ end
+
+ # Fetch the leading and trailing comments of the value.
+ def comments
+ leading_comments.concat(trailing_comments)
+ end
+
+ # Reify the values on this entry with the given values. This is an
+ # internal-only API that is called from the repository when it is time to
+ # reify the values.
+ def reify!(values) # :nodoc:
+ @repository = nil
+ @values = values
+ end
+
+ private
+
+ # Fetch a value from the entry, raising an error if it is missing.
+ def fetch_value(name)
+ values.fetch(name) do
+ raise MissingValueError, "No value for #{name}, make sure the " \
+ "repository has been properly configured"
+ end
+ end
+
+ # Return the values from the repository, reifying them if necessary.
+ def values
+ @values || (@repository.reify!; @values)
+ end
+ end
+
+ # Represents the source of a repository that will be reparsed.
+ class Source
+ # The value that will need to be reparsed.
+ attr_reader :value
+
+ # Initialize the source with the given value.
+ def initialize(value)
+ @value = value
+ end
+
+ # Reparse the value and return the parse result.
+ def result
+ raise NotImplementedError, "Subclasses must implement #result"
+ end
+
+ # Create a code units cache for the given encoding.
+ def code_units_cache(encoding)
+ result.code_units_cache(encoding)
+ end
+ end
+
+ # A source that is represented by a file path.
+ class SourceFilepath < Source
+ # Reparse the file and return the parse result.
+ def result
+ Prism.parse_file(value)
+ end
+ end
+
+ # A source that is represented by a string.
+ class SourceString < Source
+ # Reparse the string and return the parse result.
+ def result
+ Prism.parse(value)
+ end
+ end
+
+ # A field that represents the file path.
+ class FilepathField
+ # The file path that this field represents.
+ attr_reader :value
+
+ # Initialize a new field with the given file path.
+ def initialize(value)
+ @value = value
+ end
+
+ # Fetch the file path.
+ def fields(_value)
+ { filepath: value }
+ end
+ end
+
+ # A field representing the start and end lines.
+ class LinesField
+ # Fetches the start and end line of a value.
+ def fields(value)
+ { start_line: value.start_line, end_line: value.end_line }
+ end
+ end
+
+ # A field representing the start and end byte offsets.
+ class OffsetsField
+ # Fetches the start and end byte offset of a value.
+ def fields(value)
+ { start_offset: value.start_offset, end_offset: value.end_offset }
+ end
+ end
+
+ # A field representing the start and end character offsets.
+ class CharacterOffsetsField
+ # Fetches the start and end character offset of a value.
+ def fields(value)
+ {
+ start_character_offset: value.start_character_offset,
+ end_character_offset: value.end_character_offset
+ }
+ end
+ end
+
+ # A field representing the start and end code unit offsets.
+ class CodeUnitOffsetsField
+ # A pointer to the repository object that is used for lazily creating a
+ # code units cache.
+ attr_reader :repository
+
+ # The associated encoding for the code units.
+ attr_reader :encoding
+
+ # Initialize a new field with the associated repository and encoding.
+ def initialize(repository, encoding)
+ @repository = repository
+ @encoding = encoding
+ @cache = nil
+ end
+
+ # Fetches the start and end code units offset of a value for a particular
+ # encoding.
+ def fields(value)
+ {
+ start_code_units_offset: value.cached_start_code_units_offset(cache),
+ end_code_units_offset: value.cached_end_code_units_offset(cache)
+ }
+ end
+
+ private
+
+ # Lazily create a code units cache for the associated encoding.
+ def cache
+ @cache ||= repository.code_units_cache(encoding)
+ end
+ end
+
+ # A field representing the start and end byte columns.
+ class ColumnsField
+ # Fetches the start and end byte column of a value.
+ def fields(value)
+ { start_column: value.start_column, end_column: value.end_column }
+ end
+ end
+
+ # A field representing the start and end character columns.
+ class CharacterColumnsField
+ # Fetches the start and end character column of a value.
+ def fields(value)
+ {
+ start_character_column: value.start_character_column,
+ end_character_column: value.end_character_column
+ }
+ end
+ end
+
+ # A field representing the start and end code unit columns for a specific
+ # encoding.
+ class CodeUnitColumnsField
+ # The repository object that is used for lazily creating a code units
+ # cache.
+ attr_reader :repository
+
+ # The associated encoding for the code units.
+ attr_reader :encoding
+
+ # Initialize a new field with the associated repository and encoding.
+ def initialize(repository, encoding)
+ @repository = repository
+ @encoding = encoding
+ @cache = nil
+ end
+
+ # Fetches the start and end code units column of a value for a particular
+ # encoding.
+ def fields(value)
+ {
+ start_code_units_column: value.cached_start_code_units_column(cache),
+ end_code_units_column: value.cached_end_code_units_column(cache)
+ }
+ end
+
+ private
+
+ # Lazily create a code units cache for the associated encoding.
+ def cache
+ @cache ||= repository.code_units_cache(encoding)
+ end
+ end
+
+ # An abstract field used as the parent class of the two comments fields.
+ class CommentsField
+ # An object that represents a slice of a comment.
+ class Comment
+ # The slice of the comment.
+ attr_reader :slice
+
+ # Initialize a new comment with the given slice.
+ def initialize(slice)
+ @slice = slice
+ end
+ end
+
+ private
+
+ # Create comment objects from the given values.
+ def comments(values)
+ values.map { |value| Comment.new(value.slice) }
+ end
+ end
+
+ # A field representing the leading comments.
+ class LeadingCommentsField < CommentsField
+ # Fetches the leading comments of a value.
+ def fields(value)
+ { leading_comments: comments(value.leading_comments) }
+ end
+ end
+
+ # A field representing the trailing comments.
+ class TrailingCommentsField < CommentsField
+ # Fetches the trailing comments of a value.
+ def fields(value)
+ { trailing_comments: comments(value.trailing_comments) }
+ end
+ end
+
+ # A repository is a configured collection of fields and a set of entries
+ # that knows how to reparse a source and reify the values.
+ class Repository
+ # Raised when multiple fields of the same type are configured on the same
+ # repository.
+ class ConfigurationError < StandardError
+ end
+
+ # The source associated with this repository. This will be either a
+ # SourceFilepath (the most common use case) or a SourceString.
+ attr_reader :source
+
+ # The fields that have been configured on this repository.
+ attr_reader :fields
+
+ # The entries that have been saved on this repository.
+ attr_reader :entries
+
+ # Initialize a new repository with the given source.
+ def initialize(source)
+ @source = source
+ @fields = {}
+ @entries = Hash.new { |hash, node_id| hash[node_id] = {} }
+ end
+
+ # Create a code units cache for the given encoding from the source.
+ def code_units_cache(encoding)
+ source.code_units_cache(encoding)
+ end
+
+ # Configure the filepath field for this repository and return self.
+ def filepath
+ raise ConfigurationError, "Can only specify filepath for a filepath source" unless source.is_a?(SourceFilepath)
+ field(:filepath, FilepathField.new(source.value))
+ end
+
+ # Configure the lines field for this repository and return self.
+ def lines
+ field(:lines, LinesField.new)
+ end
+
+ # Configure the offsets field for this repository and return self.
+ def offsets
+ field(:offsets, OffsetsField.new)
+ end
+
+ # Configure the character offsets field for this repository and return
+ # self.
+ def character_offsets
+ field(:character_offsets, CharacterOffsetsField.new)
+ end
+
+ # Configure the code unit offsets field for this repository for a specific
+ # encoding and return self.
+ def code_unit_offsets(encoding)
+ field(:code_unit_offsets, CodeUnitOffsetsField.new(self, encoding))
+ end
+
+ # Configure the columns field for this repository and return self.
+ def columns
+ field(:columns, ColumnsField.new)
+ end
+
+ # Configure the character columns field for this repository and return
+ # self.
+ def character_columns
+ field(:character_columns, CharacterColumnsField.new)
+ end
+
+ # Configure the code unit columns field for this repository for a specific
+ # encoding and return self.
+ def code_unit_columns(encoding)
+ field(:code_unit_columns, CodeUnitColumnsField.new(self, encoding))
+ end
+
+ # Configure the leading comments field for this repository and return
+ # self.
+ def leading_comments
+ field(:leading_comments, LeadingCommentsField.new)
+ end
+
+ # Configure the trailing comments field for this repository and return
+ # self.
+ def trailing_comments
+ field(:trailing_comments, TrailingCommentsField.new)
+ end
+
+ # Configure both the leading and trailing comment fields for this
+ # repository and return self.
+ def comments
+ leading_comments.trailing_comments
+ end
+
+ # This method is called from nodes and locations when they want to enter
+ # themselves into the repository. It it internal-only and meant to be
+ # called from the #save* APIs.
+ def enter(node_id, field_name) # :nodoc:
+ entry = Entry.new(self)
+ @entries[node_id][field_name] = entry
+ entry
+ end
+
+ # This method is called from the entries in the repository when they need
+ # to reify their values. It is internal-only and meant to be called from
+ # the various value APIs.
+ def reify! # :nodoc:
+ result = source.result
+
+ # Attach the comments if they have been requested as part of the
+ # configuration of this repository.
+ if fields.key?(:leading_comments) || fields.key?(:trailing_comments)
+ result.attach_comments!
+ end
+
+ queue = [result.value] #: Array[Prism::node]
+ while (node = queue.shift)
+ @entries[node.node_id].each do |field_name, entry|
+ value = node.public_send(field_name)
+ values = {} #: Hash[Symbol, untyped]
+
+ fields.each_value do |field|
+ values.merge!(field.fields(value))
+ end
+
+ entry.reify!(values)
+ end
+
+ queue.concat(node.compact_child_nodes)
+ end
+
+ @entries.clear
+ end
+
+ private
+
+ # Append the given field to the repository and return the repository so
+ # that these calls can be chained.
+ def field(name, value)
+ raise ConfigurationError, "Cannot specify multiple #{name} fields" if @fields.key?(name)
+ @fields[name] = value
+ self
+ end
+ end
+
+ # Create a new repository for the given filepath.
+ def self.filepath(value)
+ Repository.new(SourceFilepath.new(value))
+ end
+
+ # Create a new repository for the given string.
+ def self.string(value)
+ Repository.new(SourceString.new(value))
+ end
+ end
+end
diff --git a/lib/prism/string_query.rb b/lib/prism/string_query.rb
new file mode 100644
index 0000000000..547f58d2fa
--- /dev/null
+++ b/lib/prism/string_query.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+# :markup: markdown
+
+module Prism
+ # Query methods that allow categorizing strings based on their context for
+ # where they could be valid in a Ruby syntax tree.
+ class StringQuery
+ # The string that this query is wrapping.
+ attr_reader :string
+
+ # Initialize a new query with the given string.
+ def initialize(string)
+ @string = string
+ end
+
+ # Whether or not this string is a valid local variable name.
+ def local?
+ StringQuery.local?(string)
+ end
+
+ # Whether or not this string is a valid constant name.
+ def constant?
+ StringQuery.constant?(string)
+ end
+
+ # Whether or not this string is a valid method name.
+ def method_name?
+ StringQuery.method_name?(string)
+ end
+ end
+end
diff --git a/lib/prism/translation.rb b/lib/prism/translation.rb
index 8b75e8a3ab..57b57135bc 100644
--- a/lib/prism/translation.rb
+++ b/lib/prism/translation.rb
@@ -1,12 +1,17 @@
# frozen_string_literal: true
+# :markup: markdown
module Prism
# This module is responsible for converting the prism syntax tree into other
# syntax trees.
module Translation # steep:ignore
autoload :Parser, "prism/translation/parser"
- autoload :Parser33, "prism/translation/parser33"
- autoload :Parser34, "prism/translation/parser34"
+ autoload :ParserCurrent, "prism/translation/parser_current"
+ autoload :Parser33, "prism/translation/parser_versions"
+ autoload :Parser34, "prism/translation/parser_versions"
+ autoload :Parser35, "prism/translation/parser_versions"
+ autoload :Parser40, "prism/translation/parser_versions"
+ autoload :Parser41, "prism/translation/parser_versions"
autoload :Ripper, "prism/translation/ripper"
autoload :RubyParser, "prism/translation/ruby_parser"
end
diff --git a/lib/prism/translation/parser.rb b/lib/prism/translation/parser.rb
index 3748fc896e..fed4ac4cd1 100644
--- a/lib/prism/translation/parser.rb
+++ b/lib/prism/translation/parser.rb
@@ -1,9 +1,15 @@
# frozen_string_literal: true
+# :markup: markdown
begin
+ required_version = ">= 3.3.7.2"
+ gem "parser", required_version
require "parser"
rescue LoadError
- warn(%q{Error: Unable to load parser. Add `gem "parser"` to your Gemfile.})
+ warn(<<~MSG)
+ Error: Unable to load parser #{required_version}. \
+ Add `gem "parser"` to your Gemfile or run `bundle update parser`.
+ MSG
exit(1)
end
@@ -13,6 +19,13 @@ module Prism
# whitequark/parser gem's syntax tree. It inherits from the base parser for
# the parser gem, and overrides the parse* methods to parse with prism and
# then translate.
+ #
+ # Note that this version of the parser always parses using the latest
+ # version of Ruby syntax supported by Prism. If you want specific version
+ # support, use one of the version-specific subclasses, such as
+ # `Prism::Translation::Parser34`. If you want to parse using the same
+ # version of Ruby syntax as the currently running version of Ruby, use
+ # `Prism::Translation::ParserCurrent`.
class Parser < ::Parser::Base
Diagnostic = ::Parser::Diagnostic # :nodoc:
private_constant :Diagnostic
@@ -33,8 +46,45 @@ module Prism
Racc_debug_parser = false # :nodoc:
+ # The `builder` argument is used to create the parser using our custom builder class by default.
+ #
+ # By using the `:parser` keyword argument, you can translate in a way that is compatible with
+ # the Parser gem using any parser.
+ #
+ # For example, in RuboCop for Ruby LSP, the following approach can be used to improve performance
+ # by reusing a pre-parsed `Prism::ParseLexResult`:
+ #
+ # class PrismPreparsed
+ # def initialize(prism_result)
+ # @prism_result = prism_result
+ # end
+ #
+ # def parse_lex(source, **options)
+ # @prism_result
+ # end
+ # end
+ #
+ # prism_preparsed = PrismPreparsed.new(prism_result)
+ #
+ # Prism::Translation::Ruby34.new(builder, parser: prism_preparsed)
+ #
+ # In an object passed to the `:parser` keyword argument, the `parse` and `parse_lex` methods
+ # should be implemented as needed.
+ #
+ def initialize(builder = Prism::Translation::Parser::Builder.new, parser: Prism)
+ if !builder.is_a?(Prism::Translation::Parser::Builder)
+ warn(<<~MSG, uplevel: 1, category: :deprecated)
+ [deprecation]: The builder passed to `Prism::Translation::Parser.new` is not a \
+ `Prism::Translation::Parser::Builder` subclass. This will raise in the next major version.
+ MSG
+ end
+ @parser = parser
+
+ super(builder)
+ end
+
def version # :nodoc:
- 34
+ 41
end
# The default encoding for Ruby files is UTF-8.
@@ -51,7 +101,7 @@ module Prism
source = source_buffer.source
offset_cache = build_offset_cache(source)
- result = unwrap(Prism.parse(source, filepath: source_buffer.name, version: convert_for_prism(version), scopes: [[]]), offset_cache)
+ result = unwrap(@parser.parse(source, **prism_options), offset_cache)
build_ast(result.value, offset_cache)
ensure
@@ -64,7 +114,7 @@ module Prism
source = source_buffer.source
offset_cache = build_offset_cache(source)
- result = unwrap(Prism.parse(source, filepath: source_buffer.name, version: convert_for_prism(version), scopes: [[]]), offset_cache)
+ result = unwrap(@parser.parse(source, **prism_options), offset_cache)
[
build_ast(result.value, offset_cache),
@@ -83,7 +133,7 @@ module Prism
offset_cache = build_offset_cache(source)
result =
begin
- unwrap(Prism.parse_lex(source, filepath: source_buffer.name, version: convert_for_prism(version), scopes: [[]]), offset_cache)
+ unwrap(@parser.parse_lex(source, **prism_options), offset_cache)
rescue ::Parser::SyntaxError
raise if !recover
end
@@ -285,6 +335,20 @@ module Prism
)
end
+ # Options for how prism should parse/lex the source.
+ def prism_options
+ options = {
+ filepath: @source_buffer.name,
+ version: convert_for_prism(version),
+ partial_script: true,
+ }
+ # The parser gem always encodes to UTF-8, unless it is binary.
+ # https://github.com/whitequark/parser/blob/v3.3.6.0/lib/parser/source/buffer.rb#L80-L107
+ options[:encoding] = false if @source_buffer.source.encoding != Encoding::BINARY
+
+ options
+ end
+
# Converts the version format handled by Parser to the format handled by Prism.
def convert_for_prism(version)
case version
@@ -292,11 +356,16 @@ module Prism
"3.3.1"
when 34
"3.4.0"
+ when 35, 40
+ "4.0.0"
+ when 41
+ "4.1.0"
else
"latest"
end
end
+ require_relative "parser/builder"
require_relative "parser/compiler"
require_relative "parser/lexer"
diff --git a/lib/prism/translation/parser/builder.rb b/lib/prism/translation/parser/builder.rb
new file mode 100644
index 0000000000..6b620c25bc
--- /dev/null
+++ b/lib/prism/translation/parser/builder.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+# :markup: markdown
+
+module Prism
+ module Translation
+ class Parser
+ # A builder that knows how to convert more modern Ruby syntax
+ # into whitequark/parser gem's syntax tree.
+ class Builder < ::Parser::Builders::Default
+ # It represents the `it` block argument, which is not yet implemented in the Parser gem.
+ def itarg
+ n(:itarg, [:it], nil)
+ end
+
+ # The following three lines have been added to support the `it` block parameter syntax in the source code below.
+ #
+ # if args.type == :itarg
+ # block_type = :itblock
+ # args = :it
+ #
+ # https://github.com/whitequark/parser/blob/v3.3.7.1/lib/parser/builders/default.rb#L1122-L1155
+ def block(method_call, begin_t, args, body, end_t)
+ _receiver, _selector, *call_args = *method_call
+
+ if method_call.type == :yield
+ diagnostic :error, :block_given_to_yield, nil, method_call.loc.keyword, [loc(begin_t)]
+ end
+
+ last_arg = call_args.last
+ if last_arg && (last_arg.type == :block_pass || last_arg.type == :forwarded_args)
+ diagnostic :error, :block_and_blockarg, nil, last_arg.loc.expression, [loc(begin_t)]
+ end
+
+ if args.type == :itarg
+ block_type = :itblock
+ args = :it
+ elsif args.type == :numargs
+ block_type = :numblock
+ args = args.children[0]
+ else
+ block_type = :block
+ end
+
+ if [:send, :csend, :index, :super, :zsuper, :lambda].include?(method_call.type)
+ n(block_type, [ method_call, args, body ],
+ block_map(method_call.loc.expression, begin_t, end_t))
+ else
+ # Code like "return foo 1 do end" is reduced in a weird sequence.
+ # Here, method_call is actually (return).
+ actual_send, = *method_call
+ block =
+ n(block_type, [ actual_send, args, body ],
+ block_map(actual_send.loc.expression, begin_t, end_t))
+
+ n(method_call.type, [ block ],
+ method_call.loc.with_expression(join_exprs(method_call, block)))
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/prism/translation/parser/compiler.rb b/lib/prism/translation/parser/compiler.rb
index 816c8841e8..8805614603 100644
--- a/lib/prism/translation/parser/compiler.rb
+++ b/lib/prism/translation/parser/compiler.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+# :markup: markdown
module Prism
module Translation
@@ -74,7 +75,29 @@ module Prism
# []
# ^^
def visit_array_node(node)
- builder.array(token(node.opening_loc), visit_all(node.elements), token(node.closing_loc))
+ if node.opening&.start_with?("%w", "%W", "%i", "%I")
+ elements = node.elements.flat_map do |element|
+ if element.is_a?(StringNode)
+ if element.content.include?("\n")
+ string_nodes_from_line_continuations(element.unescaped, element.content, element.content_loc.start_offset, node.opening)
+ else
+ [builder.string_internal([element.unescaped, srange(element.content_loc)])]
+ end
+ elsif element.is_a?(InterpolatedStringNode)
+ builder.string_compose(
+ token(element.opening_loc),
+ string_nodes_from_interpolation(element, node.opening),
+ token(element.closing_loc)
+ )
+ else
+ [visit(element)]
+ end
+ end
+ else
+ elements = visit_all(node.elements)
+ end
+
+ builder.array(token(node.opening_loc), elements, token(node.closing_loc))
end
# foo => [bar]
@@ -109,10 +132,10 @@ module Prism
# { a: 1 }
# ^^^^
def visit_assoc_node(node)
- if in_pattern
- key = node.key
+ key = node.key
- if node.value.is_a?(ImplicitNode)
+ if node.value.is_a?(ImplicitNode)
+ if in_pattern
if key.is_a?(SymbolNode)
if key.opening.nil?
builder.match_hash_var([key.unescaped, srange(key.location)])
@@ -123,30 +146,31 @@ module Prism
builder.match_hash_var_from_str(token(key.opening_loc), visit_all(key.parts), token(key.closing_loc))
end
else
- builder.pair_keyword([key.unescaped, srange(key.location)], visit(node.value))
- end
- elsif node.value.is_a?(ImplicitNode)
- if (value = node.value.value).is_a?(LocalVariableReadNode)
- builder.pair_keyword(
- [node.key.unescaped, srange(node.key)],
- builder.ident([value.name, srange(node.key.value_loc)]).updated(:lvar)
- )
- else
- builder.pair_label([node.key.unescaped, srange(node.key.location)])
+ value = node.value.value
+
+ implicit_value = if value.is_a?(CallNode)
+ builder.call_method(nil, nil, [value.name, srange(value.message_loc)])
+ elsif value.is_a?(ConstantReadNode)
+ builder.const([value.name, srange(key.value_loc)])
+ else
+ builder.ident([value.name, srange(key.value_loc)]).updated(:lvar)
+ end
+
+ builder.pair_keyword([key.unescaped, srange(key)], implicit_value)
end
elsif node.operator_loc
- builder.pair(visit(node.key), token(node.operator_loc), visit(node.value))
- elsif node.key.is_a?(SymbolNode) && node.key.opening_loc.nil?
- builder.pair_keyword([node.key.unescaped, srange(node.key.location)], visit(node.value))
+ builder.pair(visit(key), token(node.operator_loc), visit(node.value))
+ elsif key.is_a?(SymbolNode) && key.opening_loc.nil?
+ builder.pair_keyword([key.unescaped, srange(key.location)], visit(node.value))
else
parts =
- if node.key.is_a?(SymbolNode)
- [builder.string_internal([node.key.unescaped, srange(node.key.value_loc)])]
+ if key.is_a?(SymbolNode)
+ [builder.string_internal([key.unescaped, srange(key.value_loc)])]
else
- visit_all(node.key.parts)
+ visit_all(key.parts)
end
- builder.pair_quoted(token(node.key.opening_loc), parts, token(node.key.closing_loc), visit(node.value))
+ builder.pair_quoted(token(key.opening_loc), parts, token(key.closing_loc), visit(node.value))
end
end
@@ -179,17 +203,24 @@ module Prism
if (rescue_clause = node.rescue_clause)
begin
find_start_offset = (rescue_clause.reference&.location || rescue_clause.exceptions.last&.location || rescue_clause.keyword_loc).end_offset
- find_end_offset = (rescue_clause.statements&.location&.start_offset || rescue_clause.consequent&.location&.start_offset || (find_start_offset + 1))
+ find_end_offset = (
+ rescue_clause.statements&.location&.start_offset ||
+ rescue_clause.subsequent&.location&.start_offset ||
+ node.else_clause&.location&.start_offset ||
+ node.ensure_clause&.location&.start_offset ||
+ node.end_keyword_loc&.start_offset ||
+ find_start_offset + 1
+ )
rescue_bodies << builder.rescue_body(
token(rescue_clause.keyword_loc),
rescue_clause.exceptions.any? ? builder.array(nil, visit_all(rescue_clause.exceptions), nil) : nil,
token(rescue_clause.operator_loc),
visit(rescue_clause.reference),
- srange_find(find_start_offset, find_end_offset, [";"]),
+ srange_semicolon(find_start_offset, find_end_offset),
visit(rescue_clause.statements)
)
- end until (rescue_clause = rescue_clause.consequent).nil?
+ end until (rescue_clause = rescue_clause.subsequent).nil?
end
begin_body =
@@ -292,7 +323,7 @@ module Prism
visit_all(arguments),
token(node.closing_loc),
),
- srange_find(node.message_loc.end_offset, node.arguments.arguments.last.location.start_offset, ["="]),
+ token(node.equal_loc),
visit(node.arguments.arguments.last)
),
block
@@ -309,7 +340,7 @@ module Prism
if name.end_with?("=") && !message_loc.slice.end_with?("=") && node.arguments && block.nil?
builder.assign(
builder.attr_asgn(visit(node.receiver), call_operator, token(message_loc)),
- srange_find(message_loc.end_offset, node.arguments.location.start_offset, ["="]),
+ token(node.equal_loc),
visit(node.arguments.arguments.last)
)
else
@@ -408,8 +439,8 @@ module Prism
token(node.case_keyword_loc),
visit(node.predicate),
visit_all(node.conditions),
- token(node.consequent&.else_keyword_loc),
- visit(node.consequent),
+ token(node.else_clause&.else_keyword_loc),
+ visit(node.else_clause),
token(node.end_keyword_loc)
)
end
@@ -421,8 +452,8 @@ module Prism
token(node.case_keyword_loc),
visit(node.predicate),
visit_all(node.conditions),
- token(node.consequent&.else_keyword_loc),
- visit(node.consequent),
+ token(node.else_clause&.else_keyword_loc),
+ visit(node.else_clause),
token(node.end_keyword_loc)
)
end
@@ -662,13 +693,37 @@ module Prism
# defined?(a)
# ^^^^^^^^^^^
def visit_defined_node(node)
- builder.keyword_cmd(
- :defined?,
- token(node.keyword_loc),
- token(node.lparen_loc),
- [visit(node.value)],
- token(node.rparen_loc)
- )
+ # Very weird circumstances here where something like:
+ #
+ # defined?
+ # (1)
+ #
+ # gets parsed in Ruby as having only the `1` expression but in parser
+ # it gets parsed as having a begin. In this case we need to synthesize
+ # that begin to match parser's behavior.
+ if node.lparen_loc && node.keyword_loc.join(node.lparen_loc).slice.include?("\n")
+ builder.keyword_cmd(
+ :defined?,
+ token(node.keyword_loc),
+ nil,
+ [
+ builder.begin(
+ token(node.lparen_loc),
+ visit(node.value),
+ token(node.rparen_loc)
+ )
+ ],
+ nil
+ )
+ else
+ builder.keyword_cmd(
+ :defined?,
+ token(node.keyword_loc),
+ token(node.lparen_loc),
+ [visit(node.value)],
+ token(node.rparen_loc)
+ )
+ end
end
# if foo then bar else baz end
@@ -731,10 +786,10 @@ module Prism
visit(node.index),
token(node.in_keyword_loc),
visit(node.collection),
- if node.do_keyword_loc
- token(node.do_keyword_loc)
+ if (do_keyword_loc = node.do_keyword_loc)
+ token(do_keyword_loc)
else
- srange_find(node.collection.location.end_offset, (node.statements&.location || node.end_keyword_loc).start_offset, [";"])
+ srange_semicolon(node.collection.location.end_offset, (node.statements&.location || node.end_keyword_loc).start_offset)
end,
visit(node.statements),
token(node.end_keyword_loc)
@@ -856,26 +911,26 @@ module Prism
visit(node.predicate),
token(node.then_keyword_loc),
visit(node.statements),
- token(node.consequent.else_keyword_loc),
- visit(node.consequent)
+ token(node.subsequent.else_keyword_loc),
+ visit(node.subsequent)
)
elsif node.if_keyword_loc.start_offset == node.location.start_offset
builder.condition(
token(node.if_keyword_loc),
visit(node.predicate),
- if node.then_keyword_loc
- token(node.then_keyword_loc)
+ if (then_keyword_loc = node.then_keyword_loc)
+ token(then_keyword_loc)
else
- srange_find(node.predicate.location.end_offset, (node.statements&.location || node.consequent&.location || node.end_keyword_loc).start_offset, [";"])
+ srange_semicolon(node.predicate.location.end_offset, (node.statements&.location || node.subsequent&.location || node.end_keyword_loc).start_offset)
end,
visit(node.statements),
- case node.consequent
+ case node.subsequent
when IfNode
- token(node.consequent.if_keyword_loc)
+ token(node.subsequent.if_keyword_loc)
when ElseNode
- token(node.consequent.else_keyword_loc)
+ token(node.subsequent.else_keyword_loc)
end,
- visit(node.consequent),
+ visit(node.subsequent),
if node.if_keyword != "elsif"
token(node.end_keyword_loc)
end
@@ -883,7 +938,7 @@ module Prism
else
builder.condition_mod(
visit(node.statements),
- visit(node.consequent),
+ visit(node.subsequent),
token(node.if_keyword_loc),
visit(node.predicate)
)
@@ -929,7 +984,11 @@ module Prism
token(node.in_loc),
pattern,
guard,
- srange_find(node.pattern.location.end_offset, node.statements&.location&.start_offset, [";", "then"]),
+ if (then_loc = node.then_loc)
+ token(then_loc)
+ else
+ srange_semicolon(node.pattern.location.end_offset, node.statements&.location&.start_offset)
+ end,
visit(node.statements)
)
end
@@ -994,7 +1053,7 @@ module Prism
builder.index_asgn(
visit(node.receiver),
token(node.opening_loc),
- visit_all(node.arguments.arguments),
+ visit_all(node.arguments&.arguments || []),
token(node.closing_loc),
)
end
@@ -1062,7 +1121,7 @@ module Prism
def visit_interpolated_regular_expression_node(node)
builder.regexp_compose(
token(node.opening_loc),
- visit_all(node.parts),
+ string_nodes_from_interpolation(node, node.opening),
[node.closing[0], srange_offsets(node.closing_loc.start_offset, node.closing_loc.start_offset + 1)],
builder.regexp_options([node.closing[1..], srange_offsets(node.closing_loc.start_offset + 1, node.closing_loc.end_offset)])
)
@@ -1079,29 +1138,9 @@ module Prism
return visit_heredoc(node) { |children, closing| builder.string_compose(token(node.opening_loc), children, closing) }
end
- parts = if node.parts.one? { |part| part.type == :string_node }
- node.parts.flat_map do |node|
- if node.type == :string_node && node.unescaped.lines.count >= 2
- start_offset = node.content_loc.start_offset
-
- node.unescaped.lines.map do |line|
- end_offset = start_offset + line.length
- offsets = srange_offsets(start_offset, end_offset)
- start_offset = end_offset
-
- builder.string_internal([line, offsets])
- end
- else
- visit(node)
- end
- end
- else
- visit_all(node.parts)
- end
-
builder.string_compose(
token(node.opening_loc),
- parts,
+ string_nodes_from_interpolation(node, node.opening),
token(node.closing_loc)
)
end
@@ -1111,7 +1150,7 @@ module Prism
def visit_interpolated_symbol_node(node)
builder.symbol_compose(
token(node.opening_loc),
- visit_all(node.parts),
+ string_nodes_from_interpolation(node, node.opening),
token(node.closing_loc)
)
end
@@ -1120,14 +1159,14 @@ module Prism
# ^^^^^^^^^^^^
def visit_interpolated_x_string_node(node)
if node.heredoc?
- visit_heredoc(node) { |children, closing| builder.xstring_compose(token(node.opening_loc), children, closing) }
- else
- builder.xstring_compose(
- token(node.opening_loc),
- visit_all(node.parts),
- token(node.closing_loc)
- )
+ return visit_heredoc(node) { |children, closing| builder.xstring_compose(token(node.opening_loc), children, closing) }
end
+
+ builder.xstring_compose(
+ token(node.opening_loc),
+ string_nodes_from_interpolation(node, node.opening),
+ token(node.closing_loc)
+ )
end
# -> { it }
@@ -1139,7 +1178,17 @@ module Prism
# -> { it }
# ^^^^^^^^^
def visit_it_parameters_node(node)
- builder.args(nil, [], nil, false)
+ # FIXME: The builder _should_ always be a subclass of the prism builder.
+ # Currently RuboCop passes in its own builder that always inherits from the
+ # parser builder (which is lacking the `itarg` method). Once rubocop-ast
+ # opts in to use the custom prism builder a warning can be emitted when
+ # it is not the expected class, and eventually raise.
+ # https://github.com/rubocop/rubocop-ast/pull/354
+ if builder.is_a?(Translation::Parser::Builder)
+ builder.itarg
+ else
+ builder.args(nil, [], nil, false)
+ end
end
# foo(bar: baz)
@@ -1181,7 +1230,7 @@ module Prism
false
)
end,
- node.body&.accept(copy_compiler(forwarding: implicit_parameters ? [] : find_forwarding(parameters&.parameters))),
+ visit(node.body),
[node.closing, srange(node.closing_loc)]
)
end
@@ -1293,13 +1342,9 @@ module Prism
# foo, bar = baz
# ^^^^^^^^
def visit_multi_target_node(node)
- elements = [*node.lefts]
- elements << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode)
- elements.concat(node.rights)
-
builder.multi_lhs(
token(node.lparen_loc),
- visit_all(elements),
+ visit_all(multi_target_elements(node)),
token(node.rparen_loc)
)
end
@@ -1307,9 +1352,11 @@ module Prism
# foo, bar = baz
# ^^^^^^^^^^^^^^
def visit_multi_write_node(node)
- elements = [*node.lefts]
- elements << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode)
- elements.concat(node.rights)
+ elements = multi_target_elements(node)
+
+ if elements.length == 1 && elements.first.is_a?(MultiTargetNode) && !node.rest
+ elements = multi_target_elements(elements.first)
+ end
builder.multi_assign(
builder.multi_lhs(
@@ -1390,12 +1437,12 @@ module Prism
if node.requireds.any?
node.requireds.each do |required|
- if required.is_a?(RequiredParameterNode)
- params << visit(required)
- else
- compiler = copy_compiler(in_destructure: true)
- params << required.accept(compiler)
- end
+ params <<
+ if required.is_a?(RequiredParameterNode)
+ visit(required)
+ else
+ required.accept(copy_compiler(in_destructure: true))
+ end
end
end
@@ -1404,12 +1451,12 @@ module Prism
if node.posts.any?
node.posts.each do |post|
- if post.is_a?(RequiredParameterNode)
- params << visit(post)
- else
- compiler = copy_compiler(in_destructure: true)
- params << post.accept(compiler)
- end
+ params <<
+ if post.is_a?(RequiredParameterNode)
+ visit(post)
+ else
+ post.accept(copy_compiler(in_destructure: true))
+ end
end
end
@@ -1435,7 +1482,8 @@ module Prism
# foo => ^(bar)
# ^^^^^^
def visit_pinned_expression_node(node)
- expression = builder.begin(token(node.lparen_loc), visit(node.expression), token(node.rparen_loc))
+ parts = node.expression.accept(copy_compiler(in_pattern: false)) # Don't treat * and similar as match_rest
+ expression = builder.begin(token(node.lparen_loc), parts, token(node.rparen_loc))
builder.pin(token(node.operator_loc), expression)
end
@@ -1507,9 +1555,18 @@ module Prism
# /foo/
# ^^^^^
def visit_regular_expression_node(node)
+ parts =
+ if node.content == ""
+ []
+ elsif node.content.include?("\n")
+ string_nodes_from_line_continuations(node.unescaped, node.content, node.content_loc.start_offset, node.opening)
+ else
+ [builder.string_internal([node.unescaped, srange(node.content_loc)])]
+ end
+
builder.regexp_compose(
token(node.opening_loc),
- [builder.string_internal(token(node.content_loc))],
+ parts,
[node.closing[0], srange_offsets(node.closing_loc.start_offset, node.closing_loc.start_offset + 1)],
builder.regexp_options([node.closing[1..], srange_offsets(node.closing_loc.start_offset + 1, node.closing_loc.end_offset)])
)
@@ -1661,28 +1718,11 @@ module Prism
elsif node.opening&.start_with?("%") && node.unescaped.empty?
builder.string_compose(token(node.opening_loc), [], token(node.closing_loc))
else
- content_lines = node.content.lines
- unescaped_lines = node.unescaped.lines
-
parts =
- if content_lines.length <= 1 || unescaped_lines.length <= 1
- [builder.string_internal([node.unescaped, srange(node.content_loc)])]
- elsif content_lines.length != unescaped_lines.length
- # This occurs when we have line continuations in the string. We
- # need to come back and fix this, but for now this stops the
- # code from breaking when we encounter it because of trying to
- # transpose arrays of different lengths.
- [builder.string_internal([node.unescaped, srange(node.content_loc)])]
+ if node.content.include?("\n")
+ string_nodes_from_line_continuations(node.unescaped, node.content, node.content_loc.start_offset, node.opening)
else
- start_offset = node.content_loc.start_offset
-
- [content_lines, unescaped_lines].transpose.map do |content_line, unescaped_line|
- end_offset = start_offset + content_line.length
- offsets = srange_offsets(start_offset, end_offset)
- start_offset = end_offset
-
- builder.string_internal([unescaped_line, offsets])
- end
+ [builder.string_internal([node.unescaped, srange(node.content_loc)])]
end
builder.string_compose(
@@ -1726,19 +1766,14 @@ module Prism
builder.symbol([node.unescaped, srange(node.location)])
end
else
- parts = if node.value.lines.one?
- [builder.string_internal([node.unescaped, srange(node.value_loc)])]
- else
- start_offset = node.value_loc.start_offset
-
- node.value.lines.map do |line|
- end_offset = start_offset + line.length
- offsets = srange_offsets(start_offset, end_offset)
- start_offset = end_offset
-
- builder.string_internal([line, offsets])
+ parts =
+ if node.value == ""
+ []
+ elsif node.value.include?("\n")
+ string_nodes_from_line_continuations(node.unescaped, node.value, node.value_loc.start_offset, node.opening)
+ else
+ [builder.string_internal([node.unescaped, srange(node.value_loc)])]
end
- end
builder.symbol_compose(
token(node.opening_loc),
@@ -1770,19 +1805,19 @@ module Prism
builder.condition(
token(node.keyword_loc),
visit(node.predicate),
- if node.then_keyword_loc
- token(node.then_keyword_loc)
+ if (then_keyword_loc = node.then_keyword_loc)
+ token(then_keyword_loc)
else
- srange_find(node.predicate.location.end_offset, (node.statements&.location || node.consequent&.location || node.end_keyword_loc).start_offset, [";"])
+ srange_semicolon(node.predicate.location.end_offset, (node.statements&.location || node.else_clause&.location || node.end_keyword_loc).start_offset)
end,
- visit(node.consequent),
- token(node.consequent&.else_keyword_loc),
+ visit(node.else_clause),
+ token(node.else_clause&.else_keyword_loc),
visit(node.statements),
token(node.end_keyword_loc)
)
else
builder.condition_mod(
- visit(node.consequent),
+ visit(node.else_clause),
visit(node.statements),
token(node.keyword_loc),
visit(node.predicate)
@@ -1801,7 +1836,11 @@ module Prism
:until,
token(node.keyword_loc),
visit(node.predicate),
- srange_find(node.predicate.location.end_offset, (node.statements&.location || node.closing_loc).start_offset, [";", "do"]),
+ if (do_keyword_loc = node.do_keyword_loc)
+ token(do_keyword_loc)
+ else
+ srange_semicolon(node.predicate.location.end_offset, (node.statements&.location || node.closing_loc).start_offset)
+ end,
visit(node.statements),
token(node.closing_loc)
)
@@ -1821,10 +1860,10 @@ module Prism
builder.when(
token(node.keyword_loc),
visit_all(node.conditions),
- if node.then_keyword_loc
- token(node.then_keyword_loc)
+ if (then_keyword_loc = node.then_keyword_loc)
+ token(then_keyword_loc)
else
- srange_find(node.conditions.last.location.end_offset, node.statements&.location&.start_offset, [";"])
+ srange_semicolon(node.conditions.last.location.end_offset, node.statements&.location&.start_offset)
end,
visit(node.statements)
)
@@ -1841,7 +1880,11 @@ module Prism
:while,
token(node.keyword_loc),
visit(node.predicate),
- srange_find(node.predicate.location.end_offset, (node.statements&.location || node.closing_loc).start_offset, [";", "do"]),
+ if (do_keyword_loc = node.do_keyword_loc)
+ token(do_keyword_loc)
+ else
+ srange_semicolon(node.predicate.location.end_offset, (node.statements&.location || node.closing_loc).start_offset)
+ end,
visit(node.statements),
token(node.closing_loc)
)
@@ -1859,28 +1902,23 @@ module Prism
# ^^^^^
def visit_x_string_node(node)
if node.heredoc?
- visit_heredoc(node.to_interpolated) { |children, closing| builder.xstring_compose(token(node.opening_loc), children, closing) }
- else
- parts = if node.unescaped.lines.one?
- [builder.string_internal([node.unescaped, srange(node.content_loc)])]
- else
- start_offset = node.content_loc.start_offset
-
- node.unescaped.lines.map do |line|
- end_offset = start_offset + line.length
- offsets = srange_offsets(start_offset, end_offset)
- start_offset = end_offset
+ return visit_heredoc(node.to_interpolated) { |children, closing| builder.xstring_compose(token(node.opening_loc), children, closing) }
+ end
- builder.string_internal([line, offsets])
- end
+ parts =
+ if node.content == ""
+ []
+ elsif node.content.include?("\n")
+ string_nodes_from_line_continuations(node.unescaped, node.content, node.content_loc.start_offset, node.opening)
+ else
+ [builder.string_internal([node.unescaped, srange(node.content_loc)])]
end
- builder.xstring_compose(
- token(node.opening_loc),
- parts,
- token(node.closing_loc)
- )
- end
+ builder.xstring_compose(
+ token(node.opening_loc),
+ parts,
+ token(node.closing_loc)
+ )
end
# yield
@@ -1921,6 +1959,14 @@ module Prism
forwarding
end
+ # Returns the set of targets for a MultiTargetNode or a MultiWriteNode.
+ def multi_target_elements(node)
+ elements = [*node.lefts]
+ elements << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode)
+ elements.concat(node.rights)
+ elements
+ end
+
# Negate the value of a numeric node. This is a special case where you
# have a negative sign on one line and then a number on the next line.
# In normal Ruby, this will always be a method call. The parser gem,
@@ -1966,18 +2012,16 @@ module Prism
Range.new(source_buffer, offset_cache[start_offset], offset_cache[end_offset])
end
- # Constructs a new source range by finding the given tokens between the
- # given start offset and end offset. If the needle is not found, it
- # returns nil. Importantly it does not search past newlines or comments.
+ # Constructs a new source range by finding a semicolon between the given
+ # start offset and end offset. If the semicolon is not found, it returns
+ # nil. Importantly it does not search past newlines or comments.
#
# Note that end_offset is allowed to be nil, in which case this will
# search until the end of the string.
- def srange_find(start_offset, end_offset, tokens)
- if (match = source_buffer.source.byteslice(start_offset...end_offset).match(/(\s*)(#{tokens.join("|")})/))
- _, whitespace, token = *match
- token_offset = start_offset + whitespace.bytesize
-
- [token, Range.new(source_buffer, offset_cache[token_offset], offset_cache[token_offset + token.bytesize])]
+ def srange_semicolon(start_offset, end_offset)
+ if (match = source_buffer.source.byteslice(start_offset...end_offset)[/\A\s*;/])
+ final_offset = start_offset + match.bytesize
+ [";", Range.new(source_buffer, offset_cache[final_offset - 1], offset_cache[final_offset])]
end
end
@@ -2004,7 +2048,8 @@ module Prism
token(parameters.opening_loc),
if procarg0?(parameters.parameters)
parameter = parameters.parameters.requireds.first
- [builder.procarg0(visit(parameter))].concat(visit_all(parameters.locals))
+ visited = parameter.is_a?(RequiredParameterNode) ? visit(parameter) : parameter.accept(copy_compiler(in_destructure: true))
+ [builder.procarg0(visited)].concat(visit_all(parameters.locals))
else
visit(parameters)
end,
@@ -2012,7 +2057,7 @@ module Prism
false
)
end,
- block.body&.accept(copy_compiler(forwarding: implicit_parameters ? [] : find_forwarding(parameters&.parameters))),
+ visit(block.body),
token(block.closing_loc)
)
else
@@ -2036,26 +2081,8 @@ module Prism
node.parts.each do |part|
pushing =
- if part.is_a?(StringNode) && part.unescaped.include?("\n")
- unescaped = part.unescaped.lines(chomp: true)
- escaped = part.content.lines(chomp: true)
-
- escaped_lengths =
- if node.opening.end_with?("'")
- escaped.map { |line| line.bytesize + 1 }
- else
- escaped.chunk_while { |before, after| before.match?(/(?<!\\)\\$/) }.map { |line| line.join.bytesize + line.length }
- end
-
- start_offset = part.location.start_offset
- end_offset = nil
-
- unescaped.zip(escaped_lengths).map do |unescaped_line, escaped_length|
- end_offset = start_offset + (escaped_length || 0)
- inner_part = builder.string_internal(["#{unescaped_line}\n", srange_offsets(start_offset, end_offset)])
- start_offset = end_offset
- inner_part
- end
+ if part.is_a?(StringNode) && part.content.include?("\n")
+ string_nodes_from_line_continuations(part.unescaped, part.content, part.location.start_offset, node.opening)
else
[visit(part)]
end
@@ -2064,7 +2091,12 @@ module Prism
if child.type == :str && child.children.last == ""
# nothing
elsif child.type == :str && children.last && children.last.type == :str && !children.last.children.first.end_with?("\n")
- children.last.children.first << child.children.first
+ appendee = children[-1]
+
+ location = appendee.loc
+ location = location.with_expression(location.expression.join(child.loc.expression))
+
+ children[-1] = appendee.updated(:str, ["#{appendee.children.first}#{child.children.first}"], location: location)
else
children << child
end
@@ -2100,6 +2132,102 @@ module Prism
parser.pattern_variables.pop
end
end
+
+ # When the content of a string node is split across multiple lines, the
+ # parser gem creates individual string nodes for each line the content is part of.
+ def string_nodes_from_interpolation(node, opening)
+ node.parts.flat_map do |part|
+ if part.type == :string_node && part.content.include?("\n") && part.opening_loc.nil?
+ string_nodes_from_line_continuations(part.unescaped, part.content, part.content_loc.start_offset, opening)
+ else
+ visit(part)
+ end
+ end
+ end
+
+ # Create parser string nodes from a single prism node. The parser gem
+ # "glues" strings together when a line continuation is encountered.
+ def string_nodes_from_line_continuations(unescaped, escaped, start_offset, opening)
+ unescaped = unescaped.lines
+ escaped = escaped.lines
+ percent_array = opening&.start_with?("%w", "%W", "%i", "%I")
+ regex = opening == "/" || opening&.start_with?("%r")
+
+ # Non-interpolating strings
+ if opening&.end_with?("'") || opening&.start_with?("%q", "%s", "%w", "%i")
+ current_length = 0
+ current_line = +""
+
+ escaped.filter_map.with_index do |escaped_line, index|
+ unescaped_line = unescaped.fetch(index, "")
+ current_length += escaped_line.bytesize
+ current_line << unescaped_line
+
+ # Glue line continuations together. Only %w and %i arrays can contain these.
+ if percent_array && escaped_line[/(\\)*\n$/, 1]&.length&.odd?
+ next unless index == escaped.count - 1
+ end
+ s = builder.string_internal([current_line, srange_offsets(start_offset, start_offset + current_length)])
+ start_offset += escaped_line.bytesize
+ current_line = +""
+ current_length = 0
+ s
+ end
+ else
+ escaped_lengths = []
+ normalized_lengths = []
+ # Keeps track of where an unescaped line should start a new token. An unescaped
+ # \n would otherwise be indistinguishable from the actual newline at the end of
+ # of the line. The parser gem only emits a new string node at "real" newlines,
+ # line continuations don't start a new node as well.
+ do_next_tokens = []
+
+ escaped
+ .chunk_while { |before, after| before[/(\\*)\r?\n$/, 1]&.length&.odd? || false }
+ .each do |lines|
+ escaped_lengths << lines.sum(&:bytesize)
+
+ unescaped_lines_count =
+ if regex
+ 0 # Will always be preserved as is
+ else
+ lines.sum do |line|
+ count = line.scan(/(\\*)n/).count { |(backslashes)| backslashes&.length&.odd? }
+ count -= 1 if !line.end_with?("\n") && count > 0
+ count
+ end
+ end
+
+ extra = 1
+ extra = lines.count if percent_array # Account for line continuations in percent arrays
+
+ normalized_lengths.concat(Array.new(unescaped_lines_count + extra, 0))
+ normalized_lengths[-1] = lines.sum { |line| line.bytesize }
+ do_next_tokens.concat(Array.new(unescaped_lines_count + extra, false))
+ do_next_tokens[-1] = true
+ end
+
+ current_line = +""
+ current_normalized_length = 0
+
+ emitted_count = 0
+ unescaped.filter_map.with_index do |unescaped_line, index|
+ current_line << unescaped_line
+ current_normalized_length += normalized_lengths.fetch(index, 0)
+
+ if do_next_tokens[index]
+ inner_part = builder.string_internal([current_line, srange_offsets(start_offset, start_offset + current_normalized_length)])
+ start_offset += escaped_lengths.fetch(emitted_count, 0)
+ current_line = +""
+ current_normalized_length = 0
+ emitted_count += 1
+ inner_part
+ else
+ nil
+ end
+ end
+ end
+ end
end
end
end
diff --git a/lib/prism/translation/parser/lexer.rb b/lib/prism/translation/parser/lexer.rb
index 9d7caae0ba..75c48ef667 100644
--- a/lib/prism/translation/parser/lexer.rb
+++ b/lib/prism/translation/parser/lexer.rb
@@ -1,4 +1,9 @@
# frozen_string_literal: true
+# :markup: markdown
+
+require "strscan"
+require_relative "../../polyfill/append_as_bytes"
+require_relative "../../polyfill/scan_byte"
module Prism
module Translation
@@ -6,16 +11,17 @@ module Prism
# Accepts a list of prism tokens and converts them into the expected
# format for the parser gem.
class Lexer
+ # These tokens are always skipped
+ TYPES_ALWAYS_SKIP = Set.new(%i[IGNORED_NEWLINE __END__ EOF])
+ private_constant :TYPES_ALWAYS_SKIP
+
# The direct translating of types between the two lexers.
TYPES = {
# These tokens should never appear in the output of the lexer.
- EOF: nil,
MISSING: nil,
NOT_PROVIDED: nil,
- IGNORED_NEWLINE: nil,
EMBDOC_END: nil,
EMBDOC_LINE: nil,
- __END__: nil,
# These tokens have more or less direct mappings.
AMPERSAND: :tAMPER2,
@@ -134,7 +140,7 @@ module Prism
MINUS_GREATER: :tLAMBDA,
NEWLINE: :tNL,
NUMBERED_REFERENCE: :tNTH_REF,
- PARENTHESIS_LEFT: :tLPAREN,
+ PARENTHESIS_LEFT: :tLPAREN2,
PARENTHESIS_LEFT_PARENTHESES: :tLPAREN_ARG,
PARENTHESIS_RIGHT: :tRPAREN,
PERCENT: :tPERCENT,
@@ -173,7 +179,7 @@ module Prism
UMINUS_NUM: :tUNARY_NUM,
UPLUS: :tUPLUS,
USTAR: :tSTAR,
- USTAR_STAR: :tPOW,
+ USTAR_STAR: :tDSTAR,
WORDS_SEP: :tSPACE
}
@@ -187,7 +193,28 @@ module Prism
EXPR_BEG = 0x1 # :nodoc:
EXPR_LABEL = 0x400 # :nodoc:
- private_constant :TYPES, :EXPR_BEG, :EXPR_LABEL
+ # It is used to determine whether `do` is of the token type `kDO` or `kDO_LAMBDA`.
+ #
+ # NOTE: In edge cases like `-> (foo = -> (bar) {}) do end`, please note that `kDO` is still returned
+ # instead of `kDO_LAMBDA`, which is expected: https://github.com/ruby/prism/pull/3046
+ LAMBDA_TOKEN_TYPES = Set.new([:kDO_LAMBDA, :tLAMBDA, :tLAMBEG])
+
+ # The `PARENTHESIS_LEFT` token in Prism is classified as either `tLPAREN` or `tLPAREN2` in the Parser gem.
+ # The following token types are listed as those classified as `tLPAREN`.
+ LPAREN_CONVERSION_TOKEN_TYPES = Set.new([
+ :kBREAK, :tCARET, :kCASE, :tDIVIDE, :kFOR, :kIF, :kNEXT, :kRETURN, :kUNTIL, :kWHILE, :tAMPER, :tANDOP, :tBANG, :tCOMMA, :tDOT2, :tDOT3,
+ :tEQL, :tLPAREN, :tLPAREN2, :tLPAREN_ARG, :tLSHFT, :tNL, :tOP_ASGN, :tOROP, :tPIPE, :tSEMI, :tSTRING_DBEG, :tUMINUS, :tUPLUS, :tLCURLY
+ ])
+
+ # Types of tokens that are allowed to continue a method call with comments in-between.
+ # For these, the parser gem doesn't emit a newline token after the last comment.
+ COMMENT_CONTINUATION_TYPES = Set.new([:COMMENT, :AMPERSAND_DOT, :DOT])
+ private_constant :COMMENT_CONTINUATION_TYPES
+
+ # Heredocs are complex and require us to keep track of a bit of info to refer to later
+ HeredocData = Struct.new(:identifier, :common_whitespace, keyword_init: true)
+
+ private_constant :TYPES, :EXPR_BEG, :EXPR_LABEL, :LAMBDA_TOKEN_TYPES, :LPAREN_CONVERSION_TOKEN_TYPES, :HeredocData
# The Parser::Source::Buffer that the tokens were lexed from.
attr_reader :source_buffer
@@ -217,39 +244,78 @@ module Prism
index = 0
length = lexed.length
- heredoc_identifier_stack = []
+ heredoc_stack = []
+ quote_stack = []
+
+ # The parser gem emits the newline tokens for comments out of order. This saves
+ # that token location to emit at a later time to properly line everything up.
+ # https://github.com/whitequark/parser/issues/1025
+ comment_newline_location = nil
while index < length
token, state = lexed[index]
index += 1
- next if %i[IGNORED_NEWLINE __END__ EOF].include?(token.type)
+ next if TYPES_ALWAYS_SKIP.include?(token.type)
type = TYPES.fetch(token.type)
value = token.value
- location = Range.new(source_buffer, offset_cache[token.location.start_offset], offset_cache[token.location.end_offset])
+ location = range(token.location.start_offset, token.location.end_offset)
case type
+ when :kDO
+ nearest_lambda_token = tokens.reverse_each.find do |token|
+ LAMBDA_TOKEN_TYPES.include?(token.first)
+ end
+
+ if nearest_lambda_token&.first == :tLAMBDA
+ type = :kDO_LAMBDA
+ end
when :tCHARACTER
value.delete_prefix!("?")
+ # Character literals behave similar to double-quoted strings. We can use the same escaping mechanism.
+ value = unescape_string(value, "?")
when :tCOMMENT
if token.type == :EMBDOC_BEGIN
- start_index = index
- while !((next_token = lexed[index][0]) && next_token.type == :EMBDOC_END) && (index < length - 1)
+ while !((next_token = lexed[index]&.first) && next_token.type == :EMBDOC_END) && (index < length - 1)
value += next_token.value
index += 1
end
- if start_index != index
- value += next_token.value
- location = Range.new(source_buffer, offset_cache[token.location.start_offset], offset_cache[lexed[index][0].location.end_offset])
- index += 1
- end
+ value += next_token.value
+ location = range(token.location.start_offset, next_token.location.end_offset)
+ index += 1
else
- value.chomp!
- location = Range.new(source_buffer, offset_cache[token.location.start_offset], offset_cache[token.location.end_offset - 1])
+ is_at_eol = value.chomp!.nil?
+ location = range(token.location.start_offset, token.location.end_offset + (is_at_eol ? 0 : -1))
+
+ prev_token, _ = lexed[index - 2] if index - 2 >= 0
+ next_token, _ = lexed[index]
+
+ is_inline_comment = prev_token&.location&.start_line == token.location.start_line
+ if is_inline_comment && !is_at_eol && !COMMENT_CONTINUATION_TYPES.include?(next_token&.type)
+ tokens << [:tCOMMENT, [value, location]]
+
+ nl_location = range(token.location.end_offset - 1, token.location.end_offset)
+ tokens << [:tNL, [nil, nl_location]]
+ next
+ elsif is_inline_comment && next_token&.type == :COMMENT
+ comment_newline_location = range(token.location.end_offset - 1, token.location.end_offset)
+ elsif comment_newline_location && !COMMENT_CONTINUATION_TYPES.include?(next_token&.type)
+ tokens << [:tCOMMENT, [value, location]]
+ tokens << [:tNL, [nil, comment_newline_location]]
+ comment_newline_location = nil
+ next
+ end
end
when :tNL
+ next_token, _ = lexed[index]
+ # Newlines after comments are emitted out of order.
+ if next_token&.type == :COMMENT
+ comment_newline_location = location
+ next
+ end
+
value = nil
when :tFLOAT
value = parse_float(value)
@@ -257,8 +323,8 @@ module Prism
value = parse_complex(value)
when :tINTEGER
if value.start_with?("+")
- tokens << [:tUNARY_NUM, ["+", Range.new(source_buffer, offset_cache[token.location.start_offset], offset_cache[token.location.start_offset + 1])]]
- location = Range.new(source_buffer, offset_cache[token.location.start_offset + 1], offset_cache[token.location.end_offset])
+ tokens << [:tUNARY_NUM, ["+", range(token.location.start_offset, token.location.start_offset + 1)]]
+ location = range(token.location.start_offset + 1, token.location.end_offset)
end
value = parse_integer(value)
@@ -268,6 +334,8 @@ module Prism
value.chomp!(":")
when :tLCURLY
type = :tLBRACE if state == EXPR_BEG | EXPR_LABEL
+ when :tLPAREN2
+ type = :tLPAREN if tokens.empty? || LPAREN_CONVERSION_TOKEN_TYPES.include?(tokens.dig(-1, 0))
when :tNTH_REF
value = parse_integer(value.delete_prefix("$"))
when :tOP_ASGN
@@ -275,92 +343,196 @@ module Prism
when :tRATIONAL
value = parse_rational(value)
when :tSPACE
+ location = range(token.location.start_offset, token.location.start_offset + percent_array_leading_whitespace(value))
value = nil
when :tSTRING_BEG
- if token.type == :HEREDOC_START
- heredoc_identifier_stack.push(value.match(/<<[-~]?["'`]?(?<heredoc_identifier>.*?)["'`]?\z/)[:heredoc_identifier])
- end
- if ["\"", "'"].include?(value) && (next_token = lexed[index][0]) && next_token.type == :STRING_END
+ next_token, _ = lexed[index]
+ next_next_token, _ = lexed[index + 1]
+ basic_quotes = value == '"' || value == "'"
+
+ if basic_quotes && next_token&.type == :STRING_END
next_location = token.location.join(next_token.location)
type = :tSTRING
value = ""
- location = Range.new(source_buffer, offset_cache[next_location.start_offset], offset_cache[next_location.end_offset])
+ location = range(next_location.start_offset, next_location.end_offset)
index += 1
- elsif ["\"", "'"].include?(value) && (next_token = lexed[index][0]) && next_token.type == :STRING_CONTENT && next_token.value.lines.count <= 1 && (next_next_token = lexed[index + 1][0]) && next_next_token.type == :STRING_END
- next_location = token.location.join(next_next_token.location)
- type = :tSTRING
- value = next_token.value.gsub("\\\\", "\\")
- location = Range.new(source_buffer, offset_cache[next_location.start_offset], offset_cache[next_location.end_offset])
- index += 2
- elsif value.start_with?("<<")
+ elsif value.start_with?("'", '"', "%")
+ if next_token&.type == :STRING_CONTENT && next_next_token&.type == :STRING_END
+ string_value = next_token.value
+ if simplify_string?(string_value, value)
+ next_location = token.location.join(next_next_token.location)
+ if percent_array?(value)
+ value = percent_array_unescape(string_value)
+ else
+ value = unescape_string(string_value, value)
+ end
+ type = :tSTRING
+ location = range(next_location.start_offset, next_location.end_offset)
+ index += 2
+ tokens << [type, [value, location]]
+
+ next
+ end
+ end
+
+ quote_stack.push(value)
+ elsif token.type == :HEREDOC_START
quote = value[2] == "-" || value[2] == "~" ? value[3] : value[2]
+ heredoc_type = value[2] == "-" || value[2] == "~" ? value[2] : ""
+ heredoc = HeredocData.new(
+ identifier: value.match(/<<[-~]?["'`]?(?<heredoc_identifier>.*?)["'`]?\z/)[:heredoc_identifier],
+ common_whitespace: 0,
+ )
+
if quote == "`"
type = :tXSTRING_BEG
- value = "<<`"
+ end
+
+ # The parser gem trims whitespace from squiggly heredocs. We must record
+ # the most common whitespace to later remove.
+ if heredoc_type == "~" || heredoc_type == "`"
+ heredoc.common_whitespace = calculate_heredoc_whitespace(index)
+ end
+
+ if quote == "'" || quote == '"' || quote == "`"
+ value = "<<#{quote}"
else
- value = "<<#{quote == "'" || quote == "\"" ? quote : "\""}"
+ value = '<<"'
end
+
+ heredoc_stack.push(heredoc)
+ quote_stack.push(value)
end
when :tSTRING_CONTENT
- unless (lines = token.value.lines).one?
- start_offset = offset_cache[token.location.start_offset]
- lines.map do |line|
- newline = line.end_with?("\r\n") ? "\r\n" : "\n"
+ is_percent_array = percent_array?(quote_stack.last)
+
+ if (lines = token.value.lines).one?
+ # Prism usually emits a single token for strings with line continuations.
+ # For squiggly heredocs they are not joined so we do that manually here.
+ current_string = +""
+ current_length = 0
+ start_offset = token.location.start_offset
+ while token.type == :STRING_CONTENT
+ current_length += token.value.bytesize
+ # Heredoc interpolation can have multiple STRING_CONTENT nodes on the same line.
+ prev_token, _ = lexed[index - 2] if index - 2 >= 0
+ is_first_token_on_line = prev_token && token.location.start_line != prev_token.location.start_line
+ # The parser gem only removes indentation when the heredoc is not nested
+ not_nested = heredoc_stack.size == 1
+ if is_percent_array
+ value = percent_array_unescape(token.value)
+ elsif is_first_token_on_line && not_nested && (current_heredoc = heredoc_stack.last).common_whitespace > 0
+ value = trim_heredoc_whitespace(token.value, current_heredoc)
+ end
+
+ current_string << unescape_string(value, quote_stack.last)
+ relevant_backslash_count = if quote_stack.last.start_with?("%W", "%I")
+ 0 # the last backslash escapes the newline
+ else
+ token.value[/(\\{1,})\n/, 1]&.length || 0
+ end
+ if relevant_backslash_count.even? || !interpolation?(quote_stack.last)
+ tokens << [:tSTRING_CONTENT, [current_string, range(start_offset, start_offset + current_length)]]
+ break
+ end
+ token, _ = lexed[index]
+ index += 1
+ end
+ else
+ # When the parser gem encounters a line continuation inside of a multiline string,
+ # it emits a single string node. The backslash (and remaining newline) is removed.
+ current_line = +""
+ adjustment = 0
+ start_offset = token.location.start_offset
+ emit = false
+
+ lines.each.with_index do |line, index|
chomped_line = line.chomp
- if match = chomped_line.match(/(?<backslashes>\\+)\z/)
- adjustment = match[:backslashes].size / 2
- adjusted_line = chomped_line.delete_suffix("\\" * adjustment)
- if match[:backslashes].size.odd?
- adjusted_line.delete_suffix!("\\")
- adjustment += 2
+ backslash_count = chomped_line[/\\{1,}\z/]&.length || 0
+ is_interpolation = interpolation?(quote_stack.last)
+
+ if backslash_count.odd? && (is_interpolation || is_percent_array)
+ if is_percent_array
+ current_line << percent_array_unescape(line)
+ adjustment += 1
else
- adjusted_line << newline
+ chomped_line.delete_suffix!("\\")
+ current_line << chomped_line
+ adjustment += 2
end
+ # If the string ends with a line continuation emit the remainder
+ emit = index == lines.count - 1
else
- adjusted_line = line
- adjustment = 0
+ current_line << line
+ emit = true
end
- end_offset = start_offset + adjusted_line.length + adjustment
- tokens << [:tSTRING_CONTENT, [adjusted_line, Range.new(source_buffer, offset_cache[start_offset], offset_cache[end_offset])]]
- start_offset = end_offset
+ if emit
+ end_offset = start_offset + current_line.bytesize + adjustment
+ tokens << [:tSTRING_CONTENT, [unescape_string(current_line, quote_stack.last), range(start_offset, end_offset)]]
+ start_offset = end_offset
+ current_line = +""
+ adjustment = 0
+ end
end
- next
end
+ next
when :tSTRING_DVAR
value = nil
when :tSTRING_END
if token.type == :HEREDOC_END && value.end_with?("\n")
newline_length = value.end_with?("\r\n") ? 2 : 1
- value = heredoc_identifier_stack.pop
- location = Range.new(source_buffer, offset_cache[token.location.start_offset], offset_cache[token.location.end_offset - newline_length])
+ value = heredoc_stack.pop.identifier
+ location = range(token.location.start_offset, token.location.end_offset - newline_length)
elsif token.type == :REGEXP_END
value = value[0]
- location = Range.new(source_buffer, offset_cache[token.location.start_offset], offset_cache[token.location.start_offset + 1])
+ location = range(token.location.start_offset, token.location.start_offset + 1)
+ end
+
+ if percent_array?(quote_stack.pop)
+ prev_token, _ = lexed[index - 2] if index - 2 >= 0
+ empty = %i[PERCENT_LOWER_I PERCENT_LOWER_W PERCENT_UPPER_I PERCENT_UPPER_W].include?(prev_token&.type)
+ ends_with_whitespace = prev_token&.type == :WORDS_SEP
+ # parser always emits a space token after content in a percent array, even if no actual whitespace is present.
+ if !empty && !ends_with_whitespace
+ tokens << [:tSPACE, [nil, range(token.location.start_offset, token.location.start_offset)]]
+ end
end
when :tSYMBEG
- if (next_token = lexed[index][0]) && next_token.type != :STRING_CONTENT && next_token.type != :EMBEXPR_BEGIN && next_token.type != :EMBVAR
+ if (next_token = lexed[index]&.first) && next_token.type != :STRING_CONTENT && next_token.type != :EMBEXPR_BEGIN && next_token.type != :EMBVAR && next_token.type != :STRING_END
next_location = token.location.join(next_token.location)
type = :tSYMBOL
value = next_token.value
value = { "~@" => "~", "!@" => "!" }.fetch(value, value)
- location = Range.new(source_buffer, offset_cache[next_location.start_offset], offset_cache[next_location.end_offset])
+ location = range(next_location.start_offset, next_location.end_offset)
index += 1
+ else
+ quote_stack.push(value)
end
when :tFID
if !tokens.empty? && tokens.dig(-1, 0) == :kDEF
type = :tIDENTIFIER
end
when :tXSTRING_BEG
- if (next_token = lexed[index][0]) && next_token.type != :STRING_CONTENT && next_token.type != :STRING_END
+ if (next_token = lexed[index]&.first) && !%i[STRING_CONTENT STRING_END EMBEXPR_BEGIN].include?(next_token.type)
+ # self.`()
type = :tBACK_REF2
end
+ quote_stack.push(value)
+ when :tSYMBOLS_BEG, :tQSYMBOLS_BEG, :tWORDS_BEG, :tQWORDS_BEG
+ if (next_token = lexed[index]&.first) && next_token.type == :WORDS_SEP
+ index += 1
+ end
+
+ quote_stack.push(value)
+ when :tREGEXP_BEG
+ quote_stack.push(value)
end
tokens << [type, [value, location]]
if token.type == :REGEXP_END
- tokens << [:tREGEXP_OPT, [token.value[1..], Range.new(source_buffer, offset_cache[token.location.start_offset + 1], offset_cache[token.location.end_offset])]]
+ tokens << [:tREGEXP_OPT, [token.value[1..], range(token.location.start_offset + 1, token.location.end_offset)]]
end
end
@@ -369,6 +541,11 @@ module Prism
private
+ # Creates a new parser range, taking prisms byte offsets into account
+ def range(start_offset, end_offset)
+ Range.new(source_buffer, offset_cache[start_offset], offset_cache[end_offset])
+ end
+
# Parse an integer from the string representation.
def parse_integer(value)
Integer(value)
@@ -410,6 +587,233 @@ module Prism
rescue ArgumentError
0r
end
+
+ # Wonky heredoc tab/spaces rules.
+ # https://github.com/ruby/prism/blob/v1.3.0/src/prism.c#L10548-L10558
+ def calculate_heredoc_whitespace(heredoc_token_index)
+ next_token_index = heredoc_token_index
+ nesting_level = 0
+ previous_line = -1
+ result = Float::MAX
+
+ while (next_token = lexed[next_token_index]&.first)
+ next_token_index += 1
+ next_next_token, _ = lexed[next_token_index]
+ first_token_on_line = next_token.location.start_column == 0
+
+ # String content inside nested heredocs and interpolation is ignored
+ if next_token.type == :HEREDOC_START || next_token.type == :EMBEXPR_BEGIN
+ # When interpolation is the first token of a line there is no string
+ # content to check against. There will be no common whitespace.
+ if nesting_level == 0 && first_token_on_line
+ result = 0
+ end
+ nesting_level += 1
+ elsif next_token.type == :HEREDOC_END || next_token.type == :EMBEXPR_END
+ nesting_level -= 1
+ # When we encountered the matching heredoc end, we can exit
+ break if nesting_level == -1
+ elsif next_token.type == :STRING_CONTENT && nesting_level == 0 && first_token_on_line
+ common_whitespace = 0
+ next_token.value[/^\s*/].each_char do |char|
+ if char == "\t"
+ common_whitespace = (common_whitespace / 8 + 1) * 8;
+ else
+ common_whitespace += 1
+ end
+ end
+
+ is_first_token_on_line = next_token.location.start_line != previous_line
+ # Whitespace is significant if followed by interpolation
+ whitespace_only = common_whitespace == next_token.value.length && next_next_token&.location&.start_line != next_token.location.start_line
+ if is_first_token_on_line && !whitespace_only && common_whitespace < result
+ result = common_whitespace
+ previous_line = next_token.location.start_line
+ end
+ end
+ end
+ result
+ end
+
+ # Wonky heredoc tab/spaces rules.
+ # https://github.com/ruby/prism/blob/v1.3.0/src/prism.c#L16528-L16545
+ def trim_heredoc_whitespace(string, heredoc)
+ trimmed_whitespace = 0
+ trimmed_characters = 0
+ while (string[trimmed_characters] == "\t" || string[trimmed_characters] == " ") && trimmed_whitespace < heredoc.common_whitespace
+ if string[trimmed_characters] == "\t"
+ trimmed_whitespace = (trimmed_whitespace / 8 + 1) * 8;
+ break if trimmed_whitespace > heredoc.common_whitespace
+ else
+ trimmed_whitespace += 1
+ end
+ trimmed_characters += 1
+ end
+
+ string[trimmed_characters..]
+ end
+
+ # Escape sequences that have special and should appear unescaped in the resulting string.
+ ESCAPES = {
+ "a" => "\a", "b" => "\b", "e" => "\e", "f" => "\f",
+ "n" => "\n", "r" => "\r", "s" => "\s", "t" => "\t",
+ "v" => "\v", "\\" => "\\"
+ }.freeze
+ private_constant :ESCAPES
+
+ # When one of these delimiters is encountered, then the other
+ # one is allowed to be escaped as well.
+ DELIMITER_SYMETRY = { "[" => "]", "(" => ")", "{" => "}", "<" => ">" }.freeze
+ private_constant :DELIMITER_SYMETRY
+
+
+ # https://github.com/whitequark/parser/blob/v3.3.6.0/lib/parser/lexer-strings.rl#L14
+ REGEXP_META_CHARACTERS = ["\\", "$", "(", ")", "*", "+", ".", "<", ">", "?", "[", "]", "^", "{", "|", "}"]
+ private_constant :REGEXP_META_CHARACTERS
+
+ # Apply Ruby string escaping rules
+ def unescape_string(string, quote)
+ # In single-quoted heredocs, everything is taken literally.
+ return string if quote == "<<'"
+
+ # OPTIMIZATION: Assume that few strings need escaping to speed up the common case.
+ return string unless string.include?("\\")
+
+ # Enclosing character for the string. `"` for `"foo"`, `{` for `%w{foo}`, etc.
+ delimiter = quote[-1]
+
+ if regexp?(quote)
+ # Should be escaped handled to single-quoted heredocs. The only character that is
+ # allowed to be escaped is the delimiter, except when that also has special meaning
+ # in the regexp. Since all the symetry delimiters have special meaning, they don't need
+ # to be considered separately.
+ if REGEXP_META_CHARACTERS.include?(delimiter)
+ string
+ else
+ # There can never be an even amount of backslashes. It would be a syntax error.
+ string.gsub(/\\(#{Regexp.escape(delimiter)})/, '\1')
+ end
+ elsif interpolation?(quote)
+ # Appending individual escape sequences may force the string out of its intended
+ # encoding. Start out with binary and force it back later.
+ result = "".b
+
+ scanner = StringScanner.new(string)
+ while (skipped = scanner.skip_until(/\\/))
+ # Append what was just skipped over, excluding the found backslash.
+ result.append_as_bytes(string.byteslice(scanner.pos - skipped, skipped - 1))
+ escape_read(result, scanner, false, false)
+ end
+
+ # Add remaining chars
+ result.append_as_bytes(string.byteslice(scanner.pos..))
+ result.force_encoding(source_buffer.source.encoding)
+ else
+ delimiters = Regexp.escape("#{delimiter}#{DELIMITER_SYMETRY[delimiter]}")
+ string.gsub(/\\([\\#{delimiters}])/, '\1')
+ end
+ end
+
+ # Certain strings are merged into a single string token.
+ def simplify_string?(value, quote)
+ case quote
+ when "'"
+ # Only simplify 'foo'
+ !value.include?("\n")
+ when '"'
+ # Simplify when every line ends with a line continuation, or it is the last line
+ value.lines.all? do |line|
+ !line.end_with?("\n") || line[/(\\*)$/, 1]&.length&.odd?
+ end
+ else
+ # %q and similar are never simplified
+ false
+ end
+ end
+
+ # Escape a byte value, given the control and meta flags.
+ def escape_build(value, control, meta)
+ value &= 0x9f if control
+ value |= 0x80 if meta
+ value
+ end
+
+ # Read an escape out of the string scanner, given the control and meta
+ # flags, and push the unescaped value into the result.
+ def escape_read(result, scanner, control, meta)
+ if scanner.skip("\n")
+ # Line continuation
+ elsif (value = ESCAPES[scanner.peek(1)])
+ # Simple single-character escape sequences like \n
+ result.append_as_bytes(value)
+ scanner.pos += 1
+ elsif (value = scanner.scan(/[0-7]{1,3}/))
+ # \nnn
+ result.append_as_bytes(escape_build(value.to_i(8), control, meta))
+ elsif (value = scanner.scan(/x[0-9a-fA-F]{1,2}/))
+ # \xnn
+ result.append_as_bytes(escape_build(value[1..].to_i(16), control, meta))
+ elsif (value = scanner.scan(/u[0-9a-fA-F]{4}/))
+ # \unnnn
+ result.append_as_bytes(value[1..].hex.chr(Encoding::UTF_8))
+ elsif scanner.skip("u{}")
+ # https://github.com/whitequark/parser/issues/856
+ elsif (value = scanner.scan(/u{.*?}/))
+ # \u{nnnn ...}
+ value[2..-2].split.each do |unicode|
+ result.append_as_bytes(unicode.hex.chr(Encoding::UTF_8))
+ end
+ elsif (value = scanner.scan(/c\\?(?=[[:print:]])|C-\\?(?=[[:print:]])/))
+ # \cx or \C-x where x is an ASCII printable character
+ escape_read(result, scanner, true, meta)
+ elsif (value = scanner.scan(/M-\\?(?=[[:print:]])/))
+ # \M-x where x is an ASCII printable character
+ escape_read(result, scanner, control, true)
+ elsif (byte = scanner.scan_byte)
+ # Something else after an escape.
+ if control && byte == 0x3f # ASCII '?'
+ result.append_as_bytes(escape_build(0x7f, false, meta))
+ else
+ result.append_as_bytes(escape_build(byte, control, meta))
+ end
+ end
+ end
+
+ # In a percent array, certain whitespace can be preceeded with a backslash,
+ # causing the following characters to be part of the previous element.
+ def percent_array_unescape(string)
+ string.gsub(/(\\)+[ \f\n\r\t\v]/) do |full_match|
+ full_match.delete_prefix!("\\") if Regexp.last_match[1].length.odd?
+ full_match
+ end
+ end
+
+ # For %-arrays whitespace, the parser gem only considers whitespace before the newline.
+ def percent_array_leading_whitespace(string)
+ return 1 if string.start_with?("\n")
+
+ leading_whitespace = 0
+ string.each_char do |c|
+ break if c == "\n"
+ leading_whitespace += 1
+ end
+ leading_whitespace
+ end
+
+ # Determine if characters preceeded by a backslash should be escaped or not
+ def interpolation?(quote)
+ !quote.end_with?("'") && !quote.start_with?("%q", "%w", "%i", "%s")
+ end
+
+ # Regexp allow interpolation but are handled differently during unescaping
+ def regexp?(quote)
+ quote == "/" || quote.start_with?("%r")
+ end
+
+ # Determine if the string is part of a %-style array.
+ def percent_array?(quote)
+ quote.start_with?("%w", "%W", "%i", "%I")
+ end
end
end
end
diff --git a/lib/prism/translation/parser/rubocop.rb b/lib/prism/translation/parser/rubocop.rb
deleted file mode 100644
index 6c9687a5cc..0000000000
--- a/lib/prism/translation/parser/rubocop.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# frozen_string_literal: true
-# typed: ignore
-
-warn "WARN: Prism is directly supported since RuboCop 1.62. The `prism/translation/parser/rubocop` file is deprecated."
-
-require "parser"
-require "rubocop"
-
-require_relative "../../prism"
-require_relative "../parser"
-
-module Prism
- module Translation
- class Parser
- # This is the special version numbers that should be used in RuboCop
- # configuration files to trigger using prism.
-
- # For Ruby 3.3
- VERSION_3_3 = 80_82_73_83_77.33
-
- # For Ruby 3.4
- VERSION_3_4 = 80_82_73_83_77.34
-
- # This module gets prepended into RuboCop::AST::ProcessedSource.
- module ProcessedSource
- # This condition is compatible with rubocop-ast versions up to 1.30.0.
- if RuboCop::AST::ProcessedSource.instance_method(:parser_class).arity == 1
- # Redefine parser_class so that we can inject the prism parser into the
- # list of known parsers.
- def parser_class(ruby_version)
- if ruby_version == Prism::Translation::Parser::VERSION_3_3
- warn "WARN: Setting `TargetRubyVersion: 80_82_73_83_77.33` is deprecated. " \
- "Set to `ParserEngine: parser_prism` and `TargetRubyVersion: 3.3` instead."
- require_relative "../parser33"
- Prism::Translation::Parser33
- elsif ruby_version == Prism::Translation::Parser::VERSION_3_4
- warn "WARN: Setting `TargetRubyVersion: 80_82_73_83_77.34` is deprecated. " \
- "Set to `ParserEngine: parser_prism` and `TargetRubyVersion: 3.4` instead."
- require_relative "../parser34"
- Prism::Translation::Parser34
- else
- super
- end
- end
- else
- # Redefine parser_class so that we can inject the prism parser into the
- # list of known parsers.
- def parser_class(ruby_version, _parser_engine)
- if ruby_version == Prism::Translation::Parser::VERSION_3_3
- warn "WARN: Setting `TargetRubyVersion: 80_82_73_83_77.33` is deprecated. " \
- "Set to `ParserEngine: parser_prism` and `TargetRubyVersion: 3.3` instead."
- require_relative "../parser33"
- Prism::Translation::Parser33
- elsif ruby_version == Prism::Translation::Parser::VERSION_3_4
- warn "WARN: Setting `TargetRubyVersion: 80_82_73_83_77.34` is deprecated. " \
- "Set to `ParserEngine: parser_prism` and `TargetRubyVersion: 3.4` instead."
- require_relative "../parser34"
- Prism::Translation::Parser34
- else
- super
- end
- end
- end
- end
- end
- end
-end
-
-# :stopdoc:
-RuboCop::AST::ProcessedSource.prepend(Prism::Translation::Parser::ProcessedSource)
-known_rubies = RuboCop::TargetRuby.const_get(:KNOWN_RUBIES)
-RuboCop::TargetRuby.send(:remove_const, :KNOWN_RUBIES)
-RuboCop::TargetRuby::KNOWN_RUBIES = [*known_rubies, Prism::Translation::Parser::VERSION_3_3].freeze
diff --git a/lib/prism/translation/parser33.rb b/lib/prism/translation/parser33.rb
deleted file mode 100644
index b09266e06a..0000000000
--- a/lib/prism/translation/parser33.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-module Prism
- module Translation
- # This class is the entry-point for Ruby 3.3 of `Prism::Translation::Parser`.
- class Parser33 < Parser
- def version # :nodoc:
- 33
- end
- end
- end
-end
diff --git a/lib/prism/translation/parser34.rb b/lib/prism/translation/parser34.rb
deleted file mode 100644
index 0ead70ad3c..0000000000
--- a/lib/prism/translation/parser34.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: true
-
-module Prism
- module Translation
- # This class is the entry-point for Ruby 3.4 of `Prism::Translation::Parser`.
- class Parser34 < Parser
- def version # :nodoc:
- 34
- end
- end
- end
-end
diff --git a/lib/prism/translation/parser_current.rb b/lib/prism/translation/parser_current.rb
new file mode 100644
index 0000000000..f13eff6bbe
--- /dev/null
+++ b/lib/prism/translation/parser_current.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+# :markup: markdown
+# typed: ignore
+
+#
+module Prism
+ module Translation
+ case RUBY_VERSION
+ when /^3\.3\./
+ ParserCurrent = Parser33
+ when /^3\.4\./
+ ParserCurrent = Parser34
+ when /^3\.5\./, /^4\.0\./
+ ParserCurrent = Parser40
+ when /^4\.1\./
+ ParserCurrent = Parser41
+ else
+ # Keep this in sync with released Ruby.
+ parser = Parser40
+ major, minor, _patch = Gem::Version.new(RUBY_VERSION).segments
+ warn "warning: `Prism::Translation::Current` is loading #{parser.name}, " \
+ "but you are running #{major}.#{minor}."
+ ParserCurrent = parser
+ end
+ end
+end
diff --git a/lib/prism/translation/parser_versions.rb b/lib/prism/translation/parser_versions.rb
new file mode 100644
index 0000000000..720c7d548c
--- /dev/null
+++ b/lib/prism/translation/parser_versions.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+# :markup: markdown
+
+module Prism
+ module Translation
+ # This class is the entry-point for Ruby 3.3 of `Prism::Translation::Parser`.
+ class Parser33 < Parser
+ def version # :nodoc:
+ 33
+ end
+ end
+
+ # This class is the entry-point for Ruby 3.4 of `Prism::Translation::Parser`.
+ class Parser34 < Parser
+ def version # :nodoc:
+ 34
+ end
+ end
+
+ # This class is the entry-point for Ruby 4.0 of `Prism::Translation::Parser`.
+ class Parser40 < Parser
+ def version # :nodoc:
+ 40
+ end
+ end
+
+ Parser35 = Parser40 # :nodoc:
+
+ # This class is the entry-point for Ruby 4.1 of `Prism::Translation::Parser`.
+ class Parser41 < Parser
+ def version # :nodoc:
+ 41
+ end
+ end
+ end
+end
diff --git a/lib/prism/translation/ripper.rb b/lib/prism/translation/ripper.rb
index 79ba0e7ab3..c8f9fa7731 100644
--- a/lib/prism/translation/ripper.rb
+++ b/lib/prism/translation/ripper.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: true
-
-require "ripper"
+# :markup: markdown
module Prism
module Translation
@@ -70,7 +69,7 @@ module Prism
# [[1, 13], :on_kw, "end", END ]]
#
def self.lex(src, filename = "-", lineno = 1, raise_errors: false)
- result = Prism.lex_compat(src, filepath: filename, line: lineno)
+ result = Prism.lex_compat(src, filepath: filename, line: lineno, version: "current")
if result.failure? && raise_errors
raise SyntaxError, result.errors.first.message
@@ -79,6 +78,19 @@ module Prism
end
end
+ # 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 self.tokenize(...)
+ lex(...).map(&:value)
+ end
+
# This contains a table of all of the parser events and their
# corresponding arity.
PARSER_EVENT_TABLE = {
@@ -425,9 +437,35 @@ module Prism
end
end
+ autoload :Filter, "prism/translation/ripper/filter"
+ autoload :Lexer, "prism/translation/ripper/lexer"
autoload :SexpBuilder, "prism/translation/ripper/sexp"
autoload :SexpBuilderPP, "prism/translation/ripper/sexp"
+ # :stopdoc:
+ # This is not part of the public API but used by some gems.
+
+ # Ripper-internal bitflags.
+ LEX_STATE_NAMES = %i[
+ BEG END ENDARG ENDFN ARG CMDARG MID FNAME DOT CLASS LABEL LABELED FITEM
+ ].map.with_index.to_h { |name, i| [2 ** i, name] }.freeze
+ private_constant :LEX_STATE_NAMES
+
+ LEX_STATE_NAMES.each do |value, key|
+ const_set("EXPR_#{key}", value)
+ end
+ EXPR_NONE = 0
+ EXPR_VALUE = EXPR_BEG
+ EXPR_BEG_ANY = EXPR_BEG | EXPR_MID | EXPR_CLASS
+ EXPR_ARG_ANY = EXPR_ARG | EXPR_CMDARG
+ EXPR_END_ANY = EXPR_END | EXPR_ENDARG | EXPR_ENDFN
+
+ def self.lex_state_name(state)
+ LEX_STATE_NAMES.filter_map { |flag, name| name if state & flag != 0 }.join("|")
+ end
+
+ # :startdoc:
+
# The source that is being parsed.
attr_reader :source
@@ -1045,10 +1083,20 @@ module Prism
bounds(node.location)
on_unary(node.name, receiver)
when :!
- receiver = visit(node.receiver)
+ if node.message == "not"
+ receiver =
+ if !node.receiver.is_a?(ParenthesesNode) || !node.receiver.body.nil?
+ visit(node.receiver)
+ end
- bounds(node.location)
- on_unary(node.message == "not" ? :not : :!, receiver)
+ bounds(node.location)
+ on_unary(:not, receiver)
+ else
+ receiver = visit(node.receiver)
+
+ bounds(node.location)
+ on_unary(:!, receiver)
+ end
when *BINARY_OPERATORS
receiver = visit(node.receiver)
value = visit(node.arguments.arguments.first)
@@ -1273,8 +1321,8 @@ module Prism
def visit_case_node(node)
predicate = visit(node.predicate)
clauses =
- node.conditions.reverse_each.inject(visit(node.consequent)) do |consequent, condition|
- on_when(*visit(condition), consequent)
+ node.conditions.reverse_each.inject(visit(node.else_clause)) do |current, condition|
+ on_when(*visit(condition), current)
end
bounds(node.location)
@@ -1286,8 +1334,8 @@ module Prism
def visit_case_match_node(node)
predicate = visit(node.predicate)
clauses =
- node.conditions.reverse_each.inject(visit(node.consequent)) do |consequent, condition|
- on_in(*visit(condition), consequent)
+ node.conditions.reverse_each.inject(visit(node.else_clause)) do |current, condition|
+ on_in(*visit(condition), current)
end
bounds(node.location)
@@ -1605,8 +1653,23 @@ module Prism
# defined?(a)
# ^^^^^^^^^^^
def visit_defined_node(node)
+ expression = visit(node.value)
+
+ # Very weird circumstances here where something like:
+ #
+ # defined?
+ # (1)
+ #
+ # gets parsed in Ruby as having only the `1` expression but in Ripper it
+ # gets parsed as having a parentheses node. In this case we need to
+ # synthesize that node to match Ripper's behavior.
+ if node.lparen_loc && node.keyword_loc.join(node.lparen_loc).slice.include?("\n")
+ bounds(node.lparen_loc.join(node.rparen_loc))
+ expression = on_paren(on_stmts_add(on_stmts_new, expression))
+ end
+
bounds(node.location)
- on_defined(visit(node.value))
+ on_defined(expression)
end
# if foo then bar else baz end
@@ -1908,7 +1971,7 @@ module Prism
if node.then_keyword == "?"
predicate = visit(node.predicate)
truthy = visit(node.statements.body.first)
- falsy = visit(node.consequent.statements.body.first)
+ falsy = visit(node.subsequent.statements.body.first)
bounds(node.location)
on_ifop(predicate, truthy, falsy)
@@ -1921,13 +1984,13 @@ module Prism
else
visit(node.statements)
end
- consequent = visit(node.consequent)
+ subsequent = visit(node.subsequent)
bounds(node.location)
if node.if_keyword == "if"
- on_if(predicate, statements, consequent)
+ on_if(predicate, statements, subsequent)
else
- on_elsif(predicate, statements, consequent)
+ on_elsif(predicate, statements, subsequent)
end
else
statements = visit(node.statements.body.first)
@@ -1960,7 +2023,7 @@ module Prism
# ^^^^^^^^^^^^^^^^^^^^^
def visit_in_node(node)
# This is a special case where we're not going to call on_in directly
- # because we don't have access to the consequent. Instead, we'll return
+ # because we don't have access to the subsequent. Instead, we'll return
# the component parts and let the parent node handle it.
pattern = visit_pattern_node(node.pattern)
statements =
@@ -2808,10 +2871,10 @@ module Prism
visit(node.statements)
end
- consequent = visit(node.consequent)
+ subsequent = visit(node.subsequent)
bounds(node.location)
- on_rescue(exceptions, reference, statements, consequent)
+ on_rescue(exceptions, reference, statements, subsequent)
end
# def foo(*bar); end
@@ -3132,10 +3195,10 @@ module Prism
else
visit(node.statements)
end
- consequent = visit(node.consequent)
+ else_clause = visit(node.else_clause)
bounds(node.location)
- on_unless(predicate, statements, consequent)
+ on_unless(predicate, statements, else_clause)
else
statements = visit(node.statements.body.first)
predicate = visit(node.predicate)
@@ -3176,7 +3239,7 @@ module Prism
# ^^^^^^^^^^^^^
def visit_when_node(node)
# This is a special case where we're not going to call on_when directly
- # because we don't have access to the consequent. Instead, we'll return
+ # because we don't have access to the subsequent. Instead, we'll return
# the component parts and let the parent node handle it.
conditions = visit_arguments(node.conditions)
statements =
@@ -3269,11 +3332,7 @@ module Prism
# Lazily initialize the parse result.
def result
- @result ||=
- begin
- scopes = RUBY_VERSION >= "3.3.0" ? [] : [[]]
- Prism.parse(source, scopes: scopes)
- end
+ @result ||= Prism.parse(source, partial_script: true, version: "current")
end
##########################################################################
diff --git a/lib/prism/translation/ripper/filter.rb b/lib/prism/translation/ripper/filter.rb
new file mode 100644
index 0000000000..19deef2d37
--- /dev/null
+++ b/lib/prism/translation/ripper/filter.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+module Prism
+ module Translation
+ class Ripper
+ class Filter # :nodoc:
+ # :stopdoc:
+ def initialize(src, filename = '-', lineno = 1)
+ @__lexer = Lexer.new(src, filename, lineno)
+ @__line = nil
+ @__col = nil
+ @__state = nil
+ end
+
+ def filename
+ @__lexer.filename
+ end
+
+ def lineno
+ @__line
+ end
+
+ def column
+ @__col
+ end
+
+ def state
+ @__state
+ end
+
+ def parse(init = nil)
+ data = init
+ @__lexer.lex.each do |pos, event, tok, state|
+ @__line, @__col = *pos
+ @__state = state
+ data = if respond_to?(event, true)
+ then __send__(event, tok, data)
+ else on_default(event, tok, data)
+ end
+ end
+ data
+ end
+
+ private
+
+ def on_default(event, token, data)
+ data
+ end
+ # :startdoc:
+ end
+ end
+ end
+end
diff --git a/lib/prism/translation/ripper/lexer.rb b/lib/prism/translation/ripper/lexer.rb
new file mode 100644
index 0000000000..bd40fb4c5a
--- /dev/null
+++ b/lib/prism/translation/ripper/lexer.rb
@@ -0,0 +1,128 @@
+# frozen_string_literal: true
+# :markup: markdown
+
+require_relative "../ripper"
+
+module Prism
+ module Translation
+ class Ripper
+ class Lexer < Ripper # :nodoc:
+ # :stopdoc:
+ 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
+ @to_s
+ else
+ nil
+ end
+ end
+
+ alias to_i to_int
+ alias inspect to_s
+ def pretty_print(q) q.text(to_s) end
+ def ==(i) super or to_int == i end
+ def &(i) self.class.new(to_int & i) end
+ def |(i) self.class.new(to_int | i) end
+ def allbits?(i) to_int.allbits?(i) end
+ def anybits?(i) to_int.anybits?(i) end
+ def nobits?(i) to_int.nobits?(i) end
+ end
+
+ class Elem
+ attr_accessor :pos, :event, :tok, :state, :message
+
+ def initialize(pos, event, tok, state, message = nil)
+ @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
+ state.pretty_print(q)
+ q.breakable
+ q.text("token: ")
+ tok.pretty_print(q)
+ if message
+ q.breakable
+ q.text("message: ")
+ q.text(message)
+ end
+ }
+ end
+
+ def to_a
+ if @message
+ [@pos, @event, @tok, @state, @message]
+ else
+ [@pos, @event, @tok, @state]
+ end
+ end
+ end
+
+ # Pretty much just the same as Prism.lex_compat.
+ def lex(raise_errors: false)
+ Ripper.lex(@source, filename, lineno, raise_errors: raise_errors)
+ end
+
+ # Returns the lex_compat result wrapped in `Elem`. Errors are omitted.
+ # Since ripper is a streaming parser, tokens are expected to be emitted in the order
+ # that the parser encounters them. This is not implemented.
+ def parse(...)
+ lex(...).map do |position, event, token, state|
+ Elem.new(position, event, token, state.to_int)
+ end
+ end
+
+ # Similar to parse but ripper sorts the elements by position in the source. Also
+ # includes errors. Since prism does error recovery, in cases of syntax errors
+ # the result may differ greatly compared to ripper.
+ def scan(...)
+ parse(...)
+ end
+
+ # :startdoc:
+ end
+ end
+ end
+end
diff --git a/lib/prism/translation/ripper/sexp.rb b/lib/prism/translation/ripper/sexp.rb
index dc26a639a3..8cfefc8472 100644
--- a/lib/prism/translation/ripper/sexp.rb
+++ b/lib/prism/translation/ripper/sexp.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+# :markup: markdown
require_relative "../ripper"
diff --git a/lib/prism/translation/ruby_parser.rb b/lib/prism/translation/ruby_parser.rb
index 38690c54b3..c026c4ad9c 100644
--- a/lib/prism/translation/ruby_parser.rb
+++ b/lib/prism/translation/ruby_parser.rb
@@ -1,12 +1,18 @@
# frozen_string_literal: true
+# :markup: markdown
begin
- require "ruby_parser"
+ require "sexp"
rescue LoadError
- warn(%q{Error: Unable to load ruby_parser. Add `gem "ruby_parser"` to your Gemfile.})
+ warn(%q{Error: Unable to load sexp. Add `gem "sexp_processor"` to your Gemfile.})
exit(1)
end
+class RubyParser # :nodoc:
+ class SyntaxError < RuntimeError # :nodoc:
+ end
+end
+
module Prism
module Translation
# This module is the entry-point for converting a prism syntax tree into the
@@ -15,7 +21,7 @@ module Prism
# A prism visitor that builds Sexp objects.
class Compiler < ::Prism::Compiler
# This is the name of the file that we are compiling. We set it on every
- # Sexp object that is generated, and also use it to compile __FILE__
+ # Sexp object that is generated, and also use it to compile `__FILE__`
# nodes.
attr_reader :file
@@ -34,32 +40,54 @@ module Prism
@in_pattern = in_pattern
end
+ # ```
# alias foo bar
# ^^^^^^^^^^^^^
+ # ```
def visit_alias_method_node(node)
s(node, :alias, visit(node.new_name), visit(node.old_name))
end
+ # ```
# alias $foo $bar
# ^^^^^^^^^^^^^^^
+ # ```
def visit_alias_global_variable_node(node)
s(node, :valias, node.new_name.name, node.old_name.name)
end
+ # ```
# foo => bar | baz
# ^^^^^^^^^
+ # ```
def visit_alternation_pattern_node(node)
s(node, :or, visit(node.left), visit(node.right))
end
+ # ```
# a and b
# ^^^^^^^
+ # ```
def visit_and_node(node)
- s(node, :and, visit(node.left), visit(node.right))
+ left = visit(node.left)
+
+ if left[0] == :and
+ # ruby_parser has the and keyword as right-associative as opposed to
+ # prism which has it as left-associative. We reverse that
+ # associativity here.
+ nest = left
+ nest = nest[2] while nest[2][0] == :and
+ nest[2] = s(node, :and, nest[2], visit(node.right))
+ left
+ else
+ s(node, :and, left, visit(node.right))
+ end
end
+ # ```
# []
# ^^
+ # ```
def visit_array_node(node)
if in_pattern
s(node, :array_pat, nil).concat(visit_all(node.elements))
@@ -68,8 +96,10 @@ module Prism
end
end
+ # ```
# foo => [bar]
# ^^^^^
+ # ```
def visit_array_pattern_node(node)
if node.constant.nil? && node.requireds.empty? && node.rest.nil? && node.posts.empty?
s(node, :array_pat)
@@ -91,23 +121,29 @@ module Prism
end
end
+ # ```
# foo(bar)
# ^^^
+ # ```
def visit_arguments_node(node)
raise "Cannot visit arguments directly"
end
+ # ```
# { a: 1 }
# ^^^^
+ # ```
def visit_assoc_node(node)
[visit(node.key), visit(node.value)]
end
+ # ```
# def foo(**); bar(**); end
# ^^
#
# { **foo }
# ^^^^^
+ # ```
def visit_assoc_splat_node(node)
if node.value.nil?
[s(node, :kwsplat)]
@@ -116,14 +152,18 @@ module Prism
end
end
+ # ```
# $+
# ^^
+ # ```
def visit_back_reference_read_node(node)
- s(node, :back_ref, node.name.name.delete_prefix("$").to_sym)
+ s(node, :back_ref, node.name.to_s.delete_prefix("$").to_sym)
end
+ # ```
# begin end
# ^^^^^^^^^
+ # ```
def visit_begin_node(node)
result = node.statements.nil? ? s(node, :nil) : visit(node.statements)
@@ -135,7 +175,7 @@ module Prism
end
current = node.rescue_clause
- until (current = current.consequent).nil?
+ until (current = current.subsequent).nil?
result << visit(current)
end
end
@@ -155,16 +195,20 @@ module Prism
result
end
+ # ```
# foo(&bar)
# ^^^^
+ # ```
def visit_block_argument_node(node)
s(node, :block_pass).tap do |result|
result << visit(node.expression) unless node.expression.nil?
end
end
+ # ```
# foo { |; bar| }
# ^^^
+ # ```
def visit_block_local_variable_node(node)
node.name
end
@@ -174,8 +218,10 @@ module Prism
s(node, :block_pass, visit(node.expression))
end
+ # ```
# def foo(&bar); end
# ^^^^
+ # ```
def visit_block_parameter_node(node)
:"&#{node.name}"
end
@@ -216,11 +262,13 @@ module Prism
result
end
+ # ```
# break
# ^^^^^
#
# break foo
# ^^^^^^^^^
+ # ```
def visit_break_node(node)
if node.arguments.nil?
s(node, :break)
@@ -231,6 +279,7 @@ module Prism
end
end
+ # ```
# foo
# ^^^
#
@@ -239,6 +288,7 @@ module Prism
#
# foo.bar() {}
# ^^^^^^^^^^^^
+ # ```
def visit_call_node(node)
case node.name
when :!~
@@ -251,6 +301,11 @@ module Prism
when RegularExpressionNode, InterpolatedRegularExpressionNode
return s(node, :match2, visit(node.receiver), visit(node.arguments.arguments.first))
end
+
+ case node.arguments.arguments.first
+ when RegularExpressionNode, InterpolatedRegularExpressionNode
+ return s(node, :match3, visit(node.arguments.arguments.first), visit(node.receiver))
+ end
end
end
@@ -272,8 +327,10 @@ module Prism
visit_block(node, result, block)
end
+ # ```
# foo.bar += baz
# ^^^^^^^^^^^^^^^
+ # ```
def visit_call_operator_write_node(node)
if op_asgn?(node)
s(node, op_asgn_type(node, :op_asgn), visit(node.receiver), visit_write_value(node.value), node.read_name, node.binary_operator)
@@ -282,8 +339,10 @@ module Prism
end
end
+ # ```
# foo.bar &&= baz
# ^^^^^^^^^^^^^^^
+ # ```
def visit_call_and_write_node(node)
if op_asgn?(node)
s(node, op_asgn_type(node, :op_asgn), visit(node.receiver), visit_write_value(node.value), node.read_name, :"&&")
@@ -292,8 +351,10 @@ module Prism
end
end
+ # ```
# foo.bar ||= baz
# ^^^^^^^^^^^^^^^
+ # ```
def visit_call_or_write_node(node)
if op_asgn?(node)
s(node, op_asgn_type(node, :op_asgn), visit(node.receiver), visit_write_value(node.value), node.read_name, :"||")
@@ -315,32 +376,42 @@ module Prism
node.safe_navigation? ? :"safe_#{type}" : type
end
+ # ```
# foo.bar, = 1
# ^^^^^^^
+ # ```
def visit_call_target_node(node)
s(node, :attrasgn, visit(node.receiver), node.name)
end
+ # ```
# foo => bar => baz
# ^^^^^^^^^^
+ # ```
def visit_capture_pattern_node(node)
visit(node.target) << visit(node.value)
end
+ # ```
# case foo; when bar; end
# ^^^^^^^^^^^^^^^^^^^^^^^
+ # ```
def visit_case_node(node)
- s(node, :case, visit(node.predicate)).concat(visit_all(node.conditions)) << visit(node.consequent)
+ s(node, :case, visit(node.predicate)).concat(visit_all(node.conditions)) << visit(node.else_clause)
end
+ # ```
# case foo; in bar; end
# ^^^^^^^^^^^^^^^^^^^^^
+ # ```
def visit_case_match_node(node)
- s(node, :case, visit(node.predicate)).concat(visit_all(node.conditions)) << visit(node.consequent)
+ s(node, :case, visit(node.predicate)).concat(visit_all(node.conditions)) << visit(node.else_clause)
end
+ # ```
# class Foo; end
# ^^^^^^^^^^^^^^
+ # ```
def visit_class_node(node)
name =
if node.constant_path.is_a?(ConstantReadNode)
@@ -349,51 +420,67 @@ module Prism
visit(node.constant_path)
end
- if node.body.nil?
- s(node, :class, name, visit(node.superclass))
- elsif node.body.is_a?(StatementsNode)
- compiler = copy_compiler(in_def: false)
- s(node, :class, name, visit(node.superclass)).concat(node.body.body.map { |child| child.accept(compiler) })
- else
- s(node, :class, name, visit(node.superclass), node.body.accept(copy_compiler(in_def: false)))
- end
+ result =
+ if node.body.nil?
+ s(node, :class, name, visit(node.superclass))
+ elsif node.body.is_a?(StatementsNode)
+ compiler = copy_compiler(in_def: false)
+ s(node, :class, name, visit(node.superclass)).concat(node.body.body.map { |child| child.accept(compiler) })
+ else
+ s(node, :class, name, visit(node.superclass), node.body.accept(copy_compiler(in_def: false)))
+ end
+
+ attach_comments(result, node)
+ result
end
+ # ```
# @@foo
# ^^^^^
+ # ```
def visit_class_variable_read_node(node)
s(node, :cvar, node.name)
end
+ # ```
# @@foo = 1
# ^^^^^^^^^
#
# @@foo, @@bar = 1
# ^^^^^ ^^^^^
+ # ```
def visit_class_variable_write_node(node)
s(node, class_variable_write_type, node.name, visit_write_value(node.value))
end
+ # ```
# @@foo += bar
# ^^^^^^^^^^^^
+ # ```
def visit_class_variable_operator_write_node(node)
s(node, class_variable_write_type, node.name, s(node, :call, s(node, :cvar, node.name), node.binary_operator, visit_write_value(node.value)))
end
+ # ```
# @@foo &&= bar
# ^^^^^^^^^^^^^
+ # ```
def visit_class_variable_and_write_node(node)
s(node, :op_asgn_and, s(node, :cvar, node.name), s(node, class_variable_write_type, node.name, visit_write_value(node.value)))
end
+ # ```
# @@foo ||= bar
# ^^^^^^^^^^^^^
+ # ```
def visit_class_variable_or_write_node(node)
s(node, :op_asgn_or, s(node, :cvar, node.name), s(node, class_variable_write_type, node.name, visit_write_value(node.value)))
end
+ # ```
# @@foo, = bar
# ^^^^^
+ # ```
def visit_class_variable_target_node(node)
s(node, class_variable_write_type, node.name)
end
@@ -404,47 +491,61 @@ module Prism
in_def ? :cvasgn : :cvdecl
end
+ # ```
# Foo
# ^^^
+ # ```
def visit_constant_read_node(node)
s(node, :const, node.name)
end
+ # ```
# Foo = 1
# ^^^^^^^
#
# Foo, Bar = 1
# ^^^ ^^^
+ # ```
def visit_constant_write_node(node)
s(node, :cdecl, node.name, visit_write_value(node.value))
end
+ # ```
# Foo += bar
# ^^^^^^^^^^^
+ # ```
def visit_constant_operator_write_node(node)
s(node, :cdecl, node.name, s(node, :call, s(node, :const, node.name), node.binary_operator, visit_write_value(node.value)))
end
+ # ```
# Foo &&= bar
# ^^^^^^^^^^^^
+ # ```
def visit_constant_and_write_node(node)
s(node, :op_asgn_and, s(node, :const, node.name), s(node, :cdecl, node.name, visit(node.value)))
end
+ # ```
# Foo ||= bar
# ^^^^^^^^^^^^
+ # ```
def visit_constant_or_write_node(node)
s(node, :op_asgn_or, s(node, :const, node.name), s(node, :cdecl, node.name, visit(node.value)))
end
+ # ```
# Foo, = bar
# ^^^
+ # ```
def visit_constant_target_node(node)
s(node, :cdecl, node.name)
end
+ # ```
# Foo::Bar
# ^^^^^^^^
+ # ```
def visit_constant_path_node(node)
if node.parent.nil?
s(node, :colon3, node.name)
@@ -453,35 +554,45 @@ module Prism
end
end
+ # ```
# Foo::Bar = 1
# ^^^^^^^^^^^^
#
# Foo::Foo, Bar::Bar = 1
# ^^^^^^^^ ^^^^^^^^
+ # ```
def visit_constant_path_write_node(node)
s(node, :cdecl, visit(node.target), visit_write_value(node.value))
end
+ # ```
# Foo::Bar += baz
# ^^^^^^^^^^^^^^^
+ # ```
def visit_constant_path_operator_write_node(node)
s(node, :op_asgn, visit(node.target), node.binary_operator, visit_write_value(node.value))
end
+ # ```
# Foo::Bar &&= baz
# ^^^^^^^^^^^^^^^^
+ # ```
def visit_constant_path_and_write_node(node)
s(node, :op_asgn_and, visit(node.target), visit_write_value(node.value))
end
+ # ```
# Foo::Bar ||= baz
# ^^^^^^^^^^^^^^^^
+ # ```
def visit_constant_path_or_write_node(node)
s(node, :op_asgn_or, visit(node.target), visit_write_value(node.value))
end
+ # ```
# Foo::Bar, = baz
# ^^^^^^^^
+ # ```
def visit_constant_path_target_node(node)
inner =
if node.parent.nil?
@@ -493,11 +604,13 @@ module Prism
s(node, :const, inner)
end
+ # ```
# def foo; end
# ^^^^^^^^^^^^
#
# def self.foo; end
# ^^^^^^^^^^^^^^^^^
+ # ```
def visit_def_node(node)
name = node.name_loc.slice.to_sym
result =
@@ -507,7 +620,9 @@ module Prism
s(node, :defs, visit(node.receiver), name)
end
+ attach_comments(result, node)
result.line(node.name_loc.start_line)
+
if node.parameters.nil?
result << s(node, :args).line(node.name_loc.start_line)
else
@@ -524,55 +639,71 @@ module Prism
end
end
+ # ```
# defined? a
# ^^^^^^^^^^
#
# defined?(a)
# ^^^^^^^^^^^
+ # ```
def visit_defined_node(node)
s(node, :defined, visit(node.value))
end
+ # ```
# if foo then bar else baz end
# ^^^^^^^^^^^^
+ # ```
def visit_else_node(node)
visit(node.statements)
end
+ # ```
# "foo #{bar}"
# ^^^^^^
+ # ```
def visit_embedded_statements_node(node)
result = s(node, :evstr)
result << visit(node.statements) unless node.statements.nil?
result
end
+ # ```
# "foo #@bar"
# ^^^^^
+ # ```
def visit_embedded_variable_node(node)
s(node, :evstr, visit(node.variable))
end
+ # ```
# begin; foo; ensure; bar; end
# ^^^^^^^^^^^^
+ # ```
def visit_ensure_node(node)
node.statements.nil? ? s(node, :nil) : visit(node.statements)
end
+ # ```
# false
# ^^^^^
+ # ```
def visit_false_node(node)
s(node, :false)
end
+ # ```
# foo => [*, bar, *]
# ^^^^^^^^^^^
+ # ```
def visit_find_pattern_node(node)
s(node, :find_pat, visit_pattern_constant(node.constant), :"*#{node.left.expression&.name}", *visit_all(node.requireds), :"*#{node.right.expression&.name}")
end
+ # ```
# if foo .. bar; end
# ^^^^^^^^^^
+ # ```
def visit_flip_flop_node(node)
if node.left.is_a?(IntegerNode) && node.right.is_a?(IntegerNode)
s(node, :lit, Range.new(node.left.value, node.right.value, node.exclude_end?))
@@ -581,86 +712,112 @@ module Prism
end
end
+ # ```
# 1.0
# ^^^
+ # ```
def visit_float_node(node)
s(node, :lit, node.value)
end
+ # ```
# for foo in bar do end
# ^^^^^^^^^^^^^^^^^^^^^
+ # ```
def visit_for_node(node)
s(node, :for, visit(node.collection), visit(node.index), visit(node.statements))
end
+ # ```
# def foo(...); bar(...); end
# ^^^
+ # ```
def visit_forwarding_arguments_node(node)
s(node, :forward_args)
end
+ # ```
# def foo(...); end
# ^^^
+ # ```
def visit_forwarding_parameter_node(node)
s(node, :forward_args)
end
+ # ```
# super
# ^^^^^
#
# super {}
# ^^^^^^^^
+ # ```
def visit_forwarding_super_node(node)
visit_block(node, s(node, :zsuper), node.block)
end
+ # ```
# $foo
# ^^^^
+ # ```
def visit_global_variable_read_node(node)
s(node, :gvar, node.name)
end
+ # ```
# $foo = 1
# ^^^^^^^^
#
# $foo, $bar = 1
# ^^^^ ^^^^
+ # ```
def visit_global_variable_write_node(node)
s(node, :gasgn, node.name, visit_write_value(node.value))
end
+ # ```
# $foo += bar
# ^^^^^^^^^^^
+ # ```
def visit_global_variable_operator_write_node(node)
s(node, :gasgn, node.name, s(node, :call, s(node, :gvar, node.name), node.binary_operator, visit(node.value)))
end
+ # ```
# $foo &&= bar
# ^^^^^^^^^^^^
+ # ```
def visit_global_variable_and_write_node(node)
s(node, :op_asgn_and, s(node, :gvar, node.name), s(node, :gasgn, node.name, visit_write_value(node.value)))
end
+ # ```
# $foo ||= bar
# ^^^^^^^^^^^^
+ # ```
def visit_global_variable_or_write_node(node)
s(node, :op_asgn_or, s(node, :gvar, node.name), s(node, :gasgn, node.name, visit_write_value(node.value)))
end
+ # ```
# $foo, = bar
# ^^^^
+ # ```
def visit_global_variable_target_node(node)
s(node, :gasgn, node.name)
end
+ # ```
# {}
# ^^
+ # ```
def visit_hash_node(node)
s(node, :hash).concat(node.elements.flat_map { |element| visit(element) })
end
+ # ```
# foo => {}
# ^^
+ # ```
def visit_hash_pattern_node(node)
result = s(node, :hash_pat, visit_pattern_constant(node.constant)).concat(node.elements.flat_map { |element| visit(element) })
@@ -674,6 +831,7 @@ module Prism
result
end
+ # ```
# if foo then bar end
# ^^^^^^^^^^^^^^^^^^^
#
@@ -682,8 +840,9 @@ module Prism
#
# foo ? bar : baz
# ^^^^^^^^^^^^^^^
+ # ```
def visit_if_node(node)
- s(node, :if, visit(node.predicate), visit(node.statements), visit(node.consequent))
+ s(node, :if, visit(node.predicate), visit(node.statements), visit(node.subsequent))
end
# 1i
@@ -691,18 +850,24 @@ module Prism
s(node, :lit, node.value)
end
+ # ```
# { foo: }
# ^^^^
+ # ```
def visit_implicit_node(node)
end
+ # ```
# foo { |bar,| }
# ^
+ # ```
def visit_implicit_rest_node(node)
end
+ # ```
# case foo; in bar; end
# ^^^^^^^^^^^^^^^^^^^^^
+ # ```
def visit_in_node(node)
pattern =
if node.pattern.is_a?(ConstantPathNode)
@@ -714,8 +879,10 @@ module Prism
s(node, :in, pattern).concat(node.statements.nil? ? [nil] : visit_all(node.statements.body))
end
+ # ```
# foo[bar] += baz
# ^^^^^^^^^^^^^^^
+ # ```
def visit_index_operator_write_node(node)
arglist = nil
@@ -727,8 +894,10 @@ module Prism
s(node, :op_asgn1, visit(node.receiver), arglist, node.binary_operator, visit_write_value(node.value))
end
+ # ```
# foo[bar] &&= baz
# ^^^^^^^^^^^^^^^^
+ # ```
def visit_index_and_write_node(node)
arglist = nil
@@ -740,8 +909,10 @@ module Prism
s(node, :op_asgn1, visit(node.receiver), arglist, :"&&", visit_write_value(node.value))
end
+ # ```
# foo[bar] ||= baz
# ^^^^^^^^^^^^^^^^
+ # ```
def visit_index_or_write_node(node)
arglist = nil
@@ -753,8 +924,10 @@ module Prism
s(node, :op_asgn1, visit(node.receiver), arglist, :"||", visit_write_value(node.value))
end
+ # ```
# foo[bar], = 1
# ^^^^^^^^
+ # ```
def visit_index_target_node(node)
arguments = visit_all(node.arguments&.arguments || [])
arguments << visit(node.block) unless node.block.nil?
@@ -762,53 +935,69 @@ module Prism
s(node, :attrasgn, visit(node.receiver), :[]=).concat(arguments)
end
+ # ```
# @foo
# ^^^^
+ # ```
def visit_instance_variable_read_node(node)
s(node, :ivar, node.name)
end
+ # ```
# @foo = 1
# ^^^^^^^^
#
# @foo, @bar = 1
# ^^^^ ^^^^
+ # ```
def visit_instance_variable_write_node(node)
s(node, :iasgn, node.name, visit_write_value(node.value))
end
+ # ```
# @foo += bar
# ^^^^^^^^^^^
+ # ```
def visit_instance_variable_operator_write_node(node)
s(node, :iasgn, node.name, s(node, :call, s(node, :ivar, node.name), node.binary_operator, visit_write_value(node.value)))
end
+ # ```
# @foo &&= bar
# ^^^^^^^^^^^^
+ # ```
def visit_instance_variable_and_write_node(node)
s(node, :op_asgn_and, s(node, :ivar, node.name), s(node, :iasgn, node.name, visit(node.value)))
end
+ # ```
# @foo ||= bar
# ^^^^^^^^^^^^
+ # ```
def visit_instance_variable_or_write_node(node)
s(node, :op_asgn_or, s(node, :ivar, node.name), s(node, :iasgn, node.name, visit(node.value)))
end
+ # ```
# @foo, = bar
# ^^^^
+ # ```
def visit_instance_variable_target_node(node)
s(node, :iasgn, node.name)
end
+ # ```
# 1
# ^
+ # ```
def visit_integer_node(node)
s(node, :lit, node.value)
end
+ # ```
# if /foo #{bar}/ then end
# ^^^^^^^^^^^^
+ # ```
def visit_interpolated_match_last_line_node(node)
parts = visit_interpolated_parts(node.parts)
regexp =
@@ -824,8 +1013,10 @@ module Prism
s(node, :match, regexp)
end
+ # ```
# /foo #{bar}/
# ^^^^^^^^^^^^
+ # ```
def visit_interpolated_regular_expression_node(node)
parts = visit_interpolated_parts(node.parts)
@@ -839,22 +1030,28 @@ module Prism
end
end
+ # ```
# "foo #{bar}"
# ^^^^^^^^^^^^
+ # ```
def visit_interpolated_string_node(node)
parts = visit_interpolated_parts(node.parts)
parts.length == 1 ? s(node, :str, parts.first) : s(node, :dstr).concat(parts)
end
+ # ```
# :"foo #{bar}"
# ^^^^^^^^^^^^^
+ # ```
def visit_interpolated_symbol_node(node)
parts = visit_interpolated_parts(node.parts)
parts.length == 1 ? s(node, :lit, parts.first.to_sym) : s(node, :dsym).concat(parts)
end
+ # ```
# `foo #{bar}`
# ^^^^^^^^^^^^
+ # ```
def visit_interpolated_x_string_node(node)
source = node.heredoc? ? node.parts.first : node
parts = visit_interpolated_parts(node.parts)
@@ -864,6 +1061,7 @@ module Prism
# Visit the interpolated content of the string-like node.
private def visit_interpolated_parts(parts)
visited = []
+
parts.each do |part|
result = visit(part)
@@ -875,7 +1073,15 @@ module Prism
else
visited << result
end
+ visited << :space
elsif result[0] == :dstr
+ if !visited.empty? && part.parts[0].is_a?(StringNode)
+ # If we are in the middle of an implicitly concatenated string,
+ # we should not have a bare string as the first part. In this
+ # case we need to visit just that first part and then we can
+ # push the rest of the parts onto the visited array.
+ result[1] = visit(part.parts[0])
+ end
visited.concat(result[1..-1])
else
visited << result
@@ -883,8 +1089,9 @@ module Prism
end
state = :beginning #: :beginning | :string_content | :interpolated_content
+ results = []
- visited.each_with_object([]) do |result, results|
+ visited.each_with_index do |result, index|
case state
when :beginning
if result.is_a?(String)
@@ -899,42 +1106,54 @@ module Prism
state = :interpolated_content
end
when :string_content
- if result.is_a?(String)
- results[0] << result
+ if result == :space
+ # continue
+ elsif result.is_a?(String)
+ results[0] = "#{results[0]}#{result}"
elsif result.is_a?(Array) && result[0] == :str
- results[0] << result[1]
+ results[0] = "#{results[0]}#{result[1]}"
else
results << result
state = :interpolated_content
end
when :interpolated_content
- if result.is_a?(Array) && result[0] == :str && results[-1][0] == :str && (results[-1].line_max == result.line)
- results[-1][1] << result[1]
+ if result == :space
+ # continue
+ elsif visited[index - 1] != :space && result.is_a?(Array) && result[0] == :str && results[-1][0] == :str && (results[-1].line_max == result.line)
+ results[-1][1] = "#{results[-1][1]}#{result[1]}"
results[-1].line_max = result.line_max
else
results << result
end
end
end
+
+ results
end
+ # ```
# -> { it }
# ^^
+ # ```
def visit_it_local_variable_read_node(node)
s(node, :call, nil, :it)
end
+ # ```
# foo(bar: baz)
# ^^^^^^^^
+ # ```
def visit_keyword_hash_node(node)
s(node, :hash).concat(node.elements.flat_map { |element| visit(element) })
end
+ # ```
# def foo(**bar); end
# ^^^^^
#
# def foo(**); end
# ^^
+ # ```
def visit_keyword_rest_parameter_node(node)
:"**#{node.name}"
end
@@ -943,8 +1162,8 @@ module Prism
def visit_lambda_node(node)
parameters =
case node.parameters
- when nil, NumberedParametersNode
- s(node, :args)
+ when nil, ItParametersNode, NumberedParametersNode
+ 0
else
visit(node.parameters)
end
@@ -956,8 +1175,10 @@ module Prism
end
end
+ # ```
# foo
# ^^^
+ # ```
def visit_local_variable_read_node(node)
if node.name.match?(/^_\d$/)
s(node, :call, nil, node.name)
@@ -966,59 +1187,77 @@ module Prism
end
end
+ # ```
# foo = 1
# ^^^^^^^
#
# foo, bar = 1
# ^^^ ^^^
+ # ```
def visit_local_variable_write_node(node)
s(node, :lasgn, node.name, visit_write_value(node.value))
end
+ # ```
# foo += bar
# ^^^^^^^^^^
+ # ```
def visit_local_variable_operator_write_node(node)
s(node, :lasgn, node.name, s(node, :call, s(node, :lvar, node.name), node.binary_operator, visit_write_value(node.value)))
end
+ # ```
# foo &&= bar
# ^^^^^^^^^^^
+ # ```
def visit_local_variable_and_write_node(node)
s(node, :op_asgn_and, s(node, :lvar, node.name), s(node, :lasgn, node.name, visit_write_value(node.value)))
end
+ # ```
# foo ||= bar
# ^^^^^^^^^^^
+ # ```
def visit_local_variable_or_write_node(node)
s(node, :op_asgn_or, s(node, :lvar, node.name), s(node, :lasgn, node.name, visit_write_value(node.value)))
end
+ # ```
# foo, = bar
# ^^^
+ # ```
def visit_local_variable_target_node(node)
s(node, :lasgn, node.name)
end
+ # ```
# if /foo/ then end
# ^^^^^
+ # ```
def visit_match_last_line_node(node)
s(node, :match, s(node, :lit, Regexp.new(node.unescaped, node.options)))
end
+ # ```
# foo in bar
# ^^^^^^^^^^
+ # ```
def visit_match_predicate_node(node)
s(node, :case, visit(node.value), s(node, :in, node.pattern.accept(copy_compiler(in_pattern: true)), nil), nil)
end
+ # ```
# foo => bar
# ^^^^^^^^^^
+ # ```
def visit_match_required_node(node)
s(node, :case, visit(node.value), s(node, :in, node.pattern.accept(copy_compiler(in_pattern: true)), nil), nil)
end
+ # ```
# /(?<foo>foo)/ =~ bar
# ^^^^^^^^^^^^^^^^^^^^
+ # ```
def visit_match_write_node(node)
s(node, :match2, visit(node.call.receiver), visit(node.call.arguments.arguments.first))
end
@@ -1030,8 +1269,10 @@ module Prism
raise "Cannot visit missing node directly"
end
+ # ```
# module Foo; end
# ^^^^^^^^^^^^^^^
+ # ```
def visit_module_node(node)
name =
if node.constant_path.is_a?(ConstantReadNode)
@@ -1040,18 +1281,24 @@ module Prism
visit(node.constant_path)
end
- if node.body.nil?
- s(node, :module, name)
- elsif node.body.is_a?(StatementsNode)
- compiler = copy_compiler(in_def: false)
- s(node, :module, name).concat(node.body.body.map { |child| child.accept(compiler) })
- else
- s(node, :module, name, node.body.accept(copy_compiler(in_def: false)))
- end
+ result =
+ if node.body.nil?
+ s(node, :module, name)
+ elsif node.body.is_a?(StatementsNode)
+ compiler = copy_compiler(in_def: false)
+ s(node, :module, name).concat(node.body.body.map { |child| child.accept(compiler) })
+ else
+ s(node, :module, name, node.body.accept(copy_compiler(in_def: false)))
+ end
+
+ attach_comments(result, node)
+ result
end
+ # ```
# foo, bar = baz
# ^^^^^^^^
+ # ```
def visit_multi_target_node(node)
targets = [*node.lefts]
targets << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode)
@@ -1060,8 +1307,10 @@ module Prism
s(node, :masgn, s(node, :array).concat(visit_all(targets)))
end
+ # ```
# foo, bar = baz
# ^^^^^^^^^^^^^^
+ # ```
def visit_multi_write_node(node)
targets = [*node.lefts]
targets << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode)
@@ -1081,11 +1330,13 @@ module Prism
s(node, :masgn, s(node, :array).concat(visit_all(targets)), value)
end
+ # ```
# next
# ^^^^
#
# next foo
# ^^^^^^^^
+ # ```
def visit_next_node(node)
if node.arguments.nil?
s(node, :next)
@@ -1097,53 +1348,81 @@ module Prism
end
end
+ # ```
# nil
# ^^^
+ # ```
def visit_nil_node(node)
s(node, :nil)
end
+ # ```
# def foo(**nil); end
# ^^^^^
+ # ```
def visit_no_keywords_parameter_node(node)
in_pattern ? s(node, :kwrest, :"**nil") : :"**nil"
end
+ # ```
# -> { _1 + _2 }
# ^^^^^^^^^^^^^^
+ # ```
def visit_numbered_parameters_node(node)
raise "Cannot visit numbered parameters directly"
end
+ # ```
# $1
# ^^
+ # ```
def visit_numbered_reference_read_node(node)
s(node, :nth_ref, node.number)
end
+ # ```
# def foo(bar: baz); end
# ^^^^^^^^
+ # ```
def visit_optional_keyword_parameter_node(node)
s(node, :kwarg, node.name, visit(node.value))
end
+ # ```
# def foo(bar = 1); end
# ^^^^^^^
+ # ```
def visit_optional_parameter_node(node)
s(node, :lasgn, node.name, visit(node.value))
end
+ # ```
# a or b
# ^^^^^^
+ # ```
def visit_or_node(node)
- s(node, :or, visit(node.left), visit(node.right))
+ left = visit(node.left)
+
+ if left[0] == :or
+ # ruby_parser has the or keyword as right-associative as opposed to
+ # prism which has it as left-associative. We reverse that
+ # associativity here.
+ nest = left
+ nest = nest[2] while nest[2][0] == :or
+ nest[2] = s(node, :or, nest[2], visit(node.right))
+ left
+ else
+ s(node, :or, left, visit(node.right))
+ end
end
+ # ```
# def foo(bar, *baz); end
# ^^^^^^^^^
+ # ```
def visit_parameters_node(node)
children =
- node.compact_child_nodes.map do |element|
+ node.each_child_node.map do |element|
if element.is_a?(MultiTargetNode)
visit_destructured_parameter(element)
else
@@ -1154,8 +1433,10 @@ module Prism
s(node, :args).concat(children)
end
+ # ```
# def foo((bar, baz)); end
# ^^^^^^^^^^
+ # ```
private def visit_destructured_parameter(node)
children =
[*node.lefts, *node.rest, *node.rights].map do |child|
@@ -1174,11 +1455,13 @@ module Prism
s(node, :masgn).concat(children)
end
+ # ```
# ()
# ^^
#
# (1)
# ^^^
+ # ```
def visit_parentheses_node(node)
if node.body.nil?
s(node, :nil)
@@ -1187,14 +1470,18 @@ module Prism
end
end
+ # ```
# foo => ^(bar)
# ^^^^^^
+ # ```
def visit_pinned_expression_node(node)
node.expression.accept(copy_compiler(in_pattern: false))
end
+ # ```
# foo = 1 and bar => ^foo
# ^^^^
+ # ```
def visit_pinned_variable_node(node)
if node.variable.is_a?(LocalVariableReadNode) && node.variable.name.match?(/^_\d$/)
s(node, :lvar, node.variable.name)
@@ -1218,8 +1505,10 @@ module Prism
visit(node.statements)
end
+ # ```
# 0..5
# ^^^^
+ # ```
def visit_range_node(node)
if !in_pattern && !node.left.nil? && !node.right.nil? && ([node.left.type, node.right.type] - %i[nil_node integer_node]).empty?
left = node.left.value if node.left.is_a?(IntegerNode)
@@ -1240,44 +1529,58 @@ module Prism
end
end
+ # ```
# 1r
# ^^
+ # ```
def visit_rational_node(node)
s(node, :lit, node.value)
end
+ # ```
# redo
# ^^^^
+ # ```
def visit_redo_node(node)
s(node, :redo)
end
+ # ```
# /foo/
# ^^^^^
+ # ```
def visit_regular_expression_node(node)
s(node, :lit, Regexp.new(node.unescaped, node.options))
end
+ # ```
# def foo(bar:); end
# ^^^^
+ # ```
def visit_required_keyword_parameter_node(node)
s(node, :kwarg, node.name)
end
+ # ```
# def foo(bar); end
# ^^^
+ # ```
def visit_required_parameter_node(node)
node.name
end
+ # ```
# foo rescue bar
# ^^^^^^^^^^^^^^
+ # ```
def visit_rescue_modifier_node(node)
s(node, :rescue, visit(node.expression), s(node.rescue_expression, :resbody, s(node.rescue_expression, :array), visit(node.rescue_expression)))
end
+ # ```
# begin; rescue; end
# ^^^^^^^
+ # ```
def visit_rescue_node(node)
exceptions =
if node.exceptions.length == 1 && node.exceptions.first.is_a?(SplatNode)
@@ -1293,26 +1596,32 @@ module Prism
s(node, :resbody, exceptions).concat(node.statements.nil? ? [nil] : visit_all(node.statements.body))
end
+ # ```
# def foo(*bar); end
# ^^^^
#
# def foo(*); end
# ^
+ # ```
def visit_rest_parameter_node(node)
:"*#{node.name}"
end
+ # ```
# retry
# ^^^^^
+ # ```
def visit_retry_node(node)
s(node, :retry)
end
+ # ```
# return
# ^^^^^^
#
# return 1
# ^^^^^^^^
+ # ```
def visit_return_node(node)
if node.arguments.nil?
s(node, :return)
@@ -1324,8 +1633,10 @@ module Prism
end
end
+ # ```
# self
# ^^^^
+ # ```
def visit_self_node(node)
s(node, :self)
end
@@ -1335,33 +1646,42 @@ module Prism
visit(node.write)
end
+ # ```
# class << self; end
# ^^^^^^^^^^^^^^^^^^
+ # ```
def visit_singleton_class_node(node)
s(node, :sclass, visit(node.expression)).tap do |sexp|
sexp << node.body.accept(copy_compiler(in_def: false)) unless node.body.nil?
end
end
+ # ```
# __ENCODING__
# ^^^^^^^^^^^^
+ # ```
def visit_source_encoding_node(node)
# TODO
s(node, :colon2, s(node, :const, :Encoding), :UTF_8)
end
+ # ```
# __FILE__
# ^^^^^^^^
+ # ```
def visit_source_file_node(node)
s(node, :str, node.filepath)
end
+ # ```
# __LINE__
# ^^^^^^^^
+ # ```
def visit_source_line_node(node)
s(node, :lit, node.location.start_line)
end
+ # ```
# foo(*bar)
# ^^^^
#
@@ -1370,6 +1690,7 @@ module Prism
#
# def foo(*); bar(*); end
# ^
+ # ```
def visit_splat_node(node)
if node.expression.nil?
s(node, :splat)
@@ -1389,14 +1710,25 @@ module Prism
end
end
+ # ```
# "foo"
# ^^^^^
+ # ```
def visit_string_node(node)
- s(node, :str, node.unescaped)
+ unescaped = node.unescaped
+
+ if node.forced_binary_encoding?
+ unescaped = unescaped.dup
+ unescaped.force_encoding(Encoding::BINARY)
+ end
+
+ s(node, :str, unescaped)
end
+ # ```
# super(foo)
# ^^^^^^^^^^
+ # ```
def visit_super_node(node)
arguments = node.arguments&.arguments || []
block = node.block
@@ -1409,60 +1741,76 @@ module Prism
visit_block(node, s(node, :super).concat(visit_all(arguments)), block)
end
+ # ```
# :foo
# ^^^^
+ # ```
def visit_symbol_node(node)
node.value == "!@" ? s(node, :lit, :"!@") : s(node, :lit, node.unescaped.to_sym)
end
+ # ```
# true
# ^^^^
+ # ```
def visit_true_node(node)
s(node, :true)
end
+ # ```
# undef foo
# ^^^^^^^^^
+ # ```
def visit_undef_node(node)
names = node.names.map { |name| s(node, :undef, visit(name)) }
names.length == 1 ? names.first : s(node, :block).concat(names)
end
+ # ```
# unless foo; bar end
# ^^^^^^^^^^^^^^^^^^^
#
# bar unless foo
# ^^^^^^^^^^^^^^
+ # ```
def visit_unless_node(node)
- s(node, :if, visit(node.predicate), visit(node.consequent), visit(node.statements))
+ s(node, :if, visit(node.predicate), visit(node.else_clause), visit(node.statements))
end
+ # ```
# until foo; bar end
# ^^^^^^^^^^^^^^^^^
#
# bar until foo
# ^^^^^^^^^^^^^
+ # ```
def visit_until_node(node)
s(node, :until, visit(node.predicate), visit(node.statements), !node.begin_modifier?)
end
+ # ```
# case foo; when bar; end
# ^^^^^^^^^^^^^
+ # ```
def visit_when_node(node)
s(node, :when, s(node, :array).concat(visit_all(node.conditions))).concat(node.statements.nil? ? [nil] : visit_all(node.statements.body))
end
+ # ```
# while foo; bar end
# ^^^^^^^^^^^^^^^^^^
#
# bar while foo
# ^^^^^^^^^^^^^
+ # ```
def visit_while_node(node)
s(node, :while, visit(node.predicate), visit(node.statements), !node.begin_modifier?)
end
+ # ```
# `foo`
# ^^^^^
+ # ```
def visit_x_string_node(node)
result = s(node, :xstr, node.unescaped)
@@ -1474,17 +1822,30 @@ module Prism
result
end
+ # ```
# yield
# ^^^^^
#
# yield 1
# ^^^^^^^
+ # ```
def visit_yield_node(node)
s(node, :yield).concat(visit_all(node.arguments&.arguments || []))
end
private
+ # Attach prism comments to the given sexp.
+ def attach_comments(sexp, node)
+ return unless node.comments
+ return if node.comments.empty?
+
+ extra = node.location.start_line - node.comments.last.location.start_line
+ comments = node.comments.map(&:slice)
+ comments.concat([nil] * [0, extra].max)
+ sexp.comments = comments.join("\n")
+ end
+
# Create a new compiler with the given options.
def copy_compiler(in_def: self.in_def, in_pattern: self.in_pattern)
Compiler.new(file, in_def: in_def, in_pattern: in_pattern)
@@ -1507,7 +1868,7 @@ module Prism
else
parameters =
case block.parameters
- when nil, NumberedParametersNode
+ when nil, ItParametersNode, NumberedParametersNode
0
else
visit(block.parameters)
@@ -1554,13 +1915,21 @@ module Prism
# Parse the given source and translate it into the seattlerb/ruby_parser
# gem's Sexp format.
def parse(source, filepath = "(string)")
- translate(Prism.parse(source, filepath: filepath, scopes: [[]]), filepath)
+ translate(Prism.parse(source, filepath: filepath, partial_script: true), filepath)
end
# Parse the given file and translate it into the seattlerb/ruby_parser
# gem's Sexp format.
def parse_file(filepath)
- translate(Prism.parse_file(filepath, scopes: [[]]), filepath)
+ translate(Prism.parse_file(filepath, partial_script: true), filepath)
+ end
+
+ # Parse the give file and translate it into the
+ # seattlerb/ruby_parser gem's Sexp format. This method is
+ # provided for API compatibility to RubyParser and takes an
+ # optional +timeout+ argument.
+ def process(ruby, file = "(string)", timeout = nil)
+ Timeout.timeout(timeout) { parse(ruby, file) }
end
class << self
@@ -1587,6 +1956,7 @@ module Prism
raise ::RubyParser::SyntaxError, "#{filepath}:#{error.location.start_line} :: #{error.message}"
end
+ result.attach_comments!
result.value.accept(Compiler.new(filepath))
end
end
diff --git a/lib/pstore.gemspec b/lib/pstore.gemspec
deleted file mode 100644
index 86051d2f43..0000000000
--- a/lib/pstore.gemspec
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-name = File.basename(__FILE__, ".gemspec")
-version = ["lib", Array.new(name.count("-")+1, ".").join("/")].find do |dir|
- break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line|
- /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1
- end rescue nil
-end
-
-Gem::Specification.new do |spec|
- spec.name = name
- spec.version = version
- spec.authors = ["Yukihiro Matsumoto"]
- spec.email = ["matz@ruby-lang.org"]
-
- spec.summary = %q{Transactional File Storage for Ruby Objects}
- spec.description = spec.summary
- spec.homepage = "https://github.com/ruby/pstore"
- spec.licenses = ["Ruby", "BSD-2-Clause"]
-
- spec.metadata["homepage_uri"] = spec.homepage
- spec.metadata["source_code_uri"] = "https://github.com/ruby/pstore"
-
- # Specify which files should be added to the gem when it is released.
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
- `git ls-files -z 2>#{IO::NULL}`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
- end
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
- spec.require_paths = ["lib"]
-end
diff --git a/lib/pstore.rb b/lib/pstore.rb
deleted file mode 100644
index 57ecb0ef5c..0000000000
--- a/lib/pstore.rb
+++ /dev/null
@@ -1,731 +0,0 @@
-# frozen_string_literal: true
-# = PStore -- Transactional File Storage for Ruby Objects
-#
-# pstore.rb -
-# originally by matz
-# documentation by Kev Jackson and James Edward Gray II
-# improved by Hongli Lai
-#
-# See PStore for documentation.
-
-require "digest"
-
-# \PStore implements a file based persistence mechanism based on a Hash.
-# User code can store hierarchies of Ruby objects (values)
-# into the data store by name (keys).
-# An object hierarchy may be just a single object.
-# User code may later read values back from the data store
-# or even update data, as needed.
-#
-# The transactional behavior ensures that any changes succeed or fail together.
-# This can be used to ensure that the data store is not left in a transitory state,
-# where some values were updated but others were not.
-#
-# Behind the scenes, Ruby objects are stored to the data store file with Marshal.
-# That carries the usual limitations. Proc objects cannot be marshalled,
-# for example.
-#
-# There are three important concepts here (details at the links):
-#
-# - {Store}[rdoc-ref:PStore@The+Store]: a store is an instance of \PStore.
-# - {Entries}[rdoc-ref:PStore@Entries]: the store is hash-like;
-# each entry is the key for a stored object.
-# - {Transactions}[rdoc-ref:PStore@Transactions]: each transaction is a collection
-# of prospective changes to the store;
-# a transaction is defined in the block given with a call
-# to PStore#transaction.
-#
-# == About the Examples
-#
-# Examples on this page need a store that has known properties.
-# They can get a new (and populated) store by calling thus:
-#
-# example_store do |store|
-# # Example code using store goes here.
-# end
-#
-# All we really need to know about +example_store+
-# is that it yields a fresh store with a known population of entries;
-# its implementation:
-#
-# require 'pstore'
-# require 'tempfile'
-# # Yield a pristine store for use in examples.
-# def example_store
-# # Create the store in a temporary file.
-# Tempfile.create do |file|
-# store = PStore.new(file)
-# # Populate the store.
-# store.transaction do
-# store[:foo] = 0
-# store[:bar] = 1
-# store[:baz] = 2
-# end
-# yield store
-# end
-# end
-#
-# == The Store
-#
-# The contents of the store are maintained in a file whose path is specified
-# when the store is created (see PStore.new).
-# The objects are stored and retrieved using
-# module Marshal, which means that certain objects cannot be added to the store;
-# see {Marshal::dump}[rdoc-ref:Marshal.dump].
-#
-# == Entries
-#
-# A store may have any number of entries.
-# Each entry has a key and a value, just as in a hash:
-#
-# - Key: as in a hash, the key can be (almost) any object;
-# see {Hash Keys}[rdoc-ref:Hash@Hash+Keys].
-# You may find it convenient to keep it simple by using only
-# symbols or strings as keys.
-# - Value: the value may be any object that can be marshalled by \Marshal
-# (see {Marshal::dump}[rdoc-ref:Marshal.dump])
-# and in fact may be a collection
-# (e.g., an array, a hash, a set, a range, etc).
-# That collection may in turn contain nested objects,
-# including collections, to any depth;
-# those objects must also be \Marshal-able.
-# See {Hierarchical Values}[rdoc-ref:PStore@Hierarchical+Values].
-#
-# == Transactions
-#
-# === The Transaction Block
-#
-# The block given with a call to method #transaction#
-# contains a _transaction_,
-# which consists of calls to \PStore methods that
-# read from or write to the store
-# (that is, all \PStore methods except #transaction itself,
-# #path, and Pstore.new):
-#
-# example_store do |store|
-# store.transaction do
-# store.keys # => [:foo, :bar, :baz]
-# store[:bat] = 3
-# store.keys # => [:foo, :bar, :baz, :bat]
-# end
-# end
-#
-# Execution of the transaction is deferred until the block exits,
-# and is executed _atomically_ (all-or-nothing):
-# either all transaction calls are executed, or none are.
-# This maintains the integrity of the store.
-#
-# Other code in the block (including even calls to #path and PStore.new)
-# is executed immediately, not deferred.
-#
-# The transaction block:
-#
-# - May not contain a nested call to #transaction.
-# - Is the only context where methods that read from or write to
-# the store are allowed.
-#
-# As seen above, changes in a transaction are made automatically
-# when the block exits.
-# The block may be exited early by calling method #commit or #abort.
-#
-# - Method #commit triggers the update to the store and exits the block:
-#
-# example_store do |store|
-# store.transaction do
-# store.keys # => [:foo, :bar, :baz]
-# store[:bat] = 3
-# store.commit
-# fail 'Cannot get here'
-# end
-# store.transaction do
-# # Update was completed.
-# store.keys # => [:foo, :bar, :baz, :bat]
-# end
-# end
-#
-# - Method #abort discards the update to the store and exits the block:
-#
-# example_store do |store|
-# store.transaction do
-# store.keys # => [:foo, :bar, :baz]
-# store[:bat] = 3
-# store.abort
-# fail 'Cannot get here'
-# end
-# store.transaction do
-# # Update was not completed.
-# store.keys # => [:foo, :bar, :baz]
-# end
-# end
-#
-# === Read-Only Transactions
-#
-# By default, a transaction allows both reading from and writing to
-# the store:
-#
-# store.transaction do
-# # Read-write transaction.
-# # Any code except a call to #transaction is allowed here.
-# end
-#
-# If argument +read_only+ is passed as +true+,
-# only reading is allowed:
-#
-# store.transaction(true) do
-# # Read-only transaction:
-# # Calls to #transaction, #[]=, and #delete are not allowed here.
-# end
-#
-# == Hierarchical Values
-#
-# The value for an entry may be a simple object (as seen above).
-# It may also be a hierarchy of objects nested to any depth:
-#
-# deep_store = PStore.new('deep.store')
-# deep_store.transaction do
-# array_of_hashes = [{}, {}, {}]
-# deep_store[:array_of_hashes] = array_of_hashes
-# deep_store[:array_of_hashes] # => [{}, {}, {}]
-# hash_of_arrays = {foo: [], bar: [], baz: []}
-# deep_store[:hash_of_arrays] = hash_of_arrays
-# deep_store[:hash_of_arrays] # => {:foo=>[], :bar=>[], :baz=>[]}
-# deep_store[:hash_of_arrays][:foo].push(:bat)
-# deep_store[:hash_of_arrays] # => {:foo=>[:bat], :bar=>[], :baz=>[]}
-# end
-#
-# And recall that you can use
-# {dig methods}[rdoc-ref:dig_methods.rdoc]
-# in a returned hierarchy of objects.
-#
-# == Working with the Store
-#
-# === Creating a Store
-#
-# Use method PStore.new to create a store.
-# The new store creates or opens its containing file:
-#
-# store = PStore.new('t.store')
-#
-# === Modifying the Store
-#
-# Use method #[]= to update or create an entry:
-#
-# example_store do |store|
-# store.transaction do
-# store[:foo] = 1 # Update.
-# store[:bam] = 1 # Create.
-# end
-# end
-#
-# Use method #delete to remove an entry:
-#
-# example_store do |store|
-# store.transaction do
-# store.delete(:foo)
-# store[:foo] # => nil
-# end
-# end
-#
-# === Retrieving Values
-#
-# Use method #fetch (allows default) or #[] (defaults to +nil+)
-# to retrieve an entry:
-#
-# example_store do |store|
-# store.transaction do
-# store[:foo] # => 0
-# store[:nope] # => nil
-# store.fetch(:baz) # => 2
-# store.fetch(:nope, nil) # => nil
-# store.fetch(:nope) # Raises exception.
-# end
-# end
-#
-# === Querying the Store
-#
-# Use method #key? to determine whether a given key exists:
-#
-# example_store do |store|
-# store.transaction do
-# store.key?(:foo) # => true
-# end
-# end
-#
-# Use method #keys to retrieve keys:
-#
-# example_store do |store|
-# store.transaction do
-# store.keys # => [:foo, :bar, :baz]
-# end
-# end
-#
-# Use method #path to retrieve the path to the store's underlying file;
-# this method may be called from outside a transaction block:
-#
-# store = PStore.new('t.store')
-# store.path # => "t.store"
-#
-# == Transaction Safety
-#
-# For transaction safety, see:
-#
-# - Optional argument +thread_safe+ at method PStore.new.
-# - Attribute #ultra_safe.
-#
-# Needless to say, if you're storing valuable data with \PStore, then you should
-# backup the \PStore file from time to time.
-#
-# == An Example Store
-#
-# require "pstore"
-#
-# # A mock wiki object.
-# class WikiPage
-#
-# attr_reader :page_name
-#
-# def initialize(page_name, author, contents)
-# @page_name = page_name
-# @revisions = Array.new
-# add_revision(author, contents)
-# end
-#
-# def add_revision(author, contents)
-# @revisions << {created: Time.now,
-# author: author,
-# contents: contents}
-# end
-#
-# def wiki_page_references
-# [@page_name] + @revisions.last[:contents].scan(/\b(?:[A-Z]+[a-z]+){2,}/)
-# end
-#
-# end
-#
-# # Create a new wiki page.
-# home_page = WikiPage.new("HomePage", "James Edward Gray II",
-# "A page about the JoysOfDocumentation..." )
-#
-# wiki = PStore.new("wiki_pages.pstore")
-# # Update page data and the index together, or not at all.
-# wiki.transaction do
-# # Store page.
-# wiki[home_page.page_name] = home_page
-# # Create page index.
-# wiki[:wiki_index] ||= Array.new
-# # Update wiki index.
-# wiki[:wiki_index].push(*home_page.wiki_page_references)
-# end
-#
-# # Read wiki data, setting argument read_only to true.
-# wiki.transaction(true) do
-# wiki.keys.each do |key|
-# puts key
-# puts wiki[key]
-# end
-# end
-#
-class PStore
- VERSION = "0.1.3"
-
- RDWR_ACCESS = {mode: IO::RDWR | IO::CREAT | IO::BINARY, encoding: Encoding::ASCII_8BIT}.freeze
- RD_ACCESS = {mode: IO::RDONLY | IO::BINARY, encoding: Encoding::ASCII_8BIT}.freeze
- WR_ACCESS = {mode: IO::WRONLY | IO::CREAT | IO::TRUNC | IO::BINARY, encoding: Encoding::ASCII_8BIT}.freeze
-
- # The error type thrown by all PStore methods.
- class Error < StandardError
- end
-
- # Whether \PStore should do its best to prevent file corruptions,
- # even when an unlikely error (such as memory-error or filesystem error) occurs:
- #
- # - +true+: changes are posted by creating a temporary file,
- # writing the updated data to it, then renaming the file to the given #path.
- # File integrity is maintained.
- # Note: has effect only if the filesystem has atomic file rename
- # (as do POSIX platforms Linux, MacOS, FreeBSD and others).
- #
- # - +false+ (the default): changes are posted by rewinding the open file
- # and writing the updated data.
- # File integrity is maintained if the filesystem raises
- # no unexpected I/O error;
- # if such an error occurs during a write to the store,
- # the file may become corrupted.
- #
- attr_accessor :ultra_safe
-
- # Returns a new \PStore object.
- #
- # Argument +file+ is the path to the file in which objects are to be stored;
- # if the file exists, it should be one that was written by \PStore.
- #
- # path = 't.store'
- # store = PStore.new(path)
- #
- # A \PStore object is
- # {reentrant}[https://en.wikipedia.org/wiki/Reentrancy_(computing)].
- # If argument +thread_safe+ is given as +true+,
- # the object is also thread-safe (at the cost of a small performance penalty):
- #
- # store = PStore.new(path, true)
- #
- def initialize(file, thread_safe = false)
- dir = File::dirname(file)
- unless File::directory? dir
- raise PStore::Error, format("directory %s does not exist", dir)
- end
- if File::exist? file and not File::readable? file
- raise PStore::Error, format("file %s not readable", file)
- end
- @filename = file
- @abort = false
- @ultra_safe = false
- @thread_safe = thread_safe
- @lock = Thread::Mutex.new
- end
-
- # Raises PStore::Error if the calling code is not in a PStore#transaction.
- def in_transaction
- raise PStore::Error, "not in transaction" unless @lock.locked?
- end
- #
- # Raises PStore::Error if the calling code is not in a PStore#transaction or
- # if the code is in a read-only PStore#transaction.
- #
- def in_transaction_wr
- in_transaction
- raise PStore::Error, "in read-only transaction" if @rdonly
- end
- private :in_transaction, :in_transaction_wr
-
- # Returns the value for the given +key+ if the key exists.
- # +nil+ otherwise;
- # if not +nil+, the returned value is an object or a hierarchy of objects:
- #
- # example_store do |store|
- # store.transaction do
- # store[:foo] # => 0
- # store[:nope] # => nil
- # end
- # end
- #
- # Returns +nil+ if there is no such key.
- #
- # See also {Hierarchical Values}[rdoc-ref:PStore@Hierarchical+Values].
- #
- # Raises an exception if called outside a transaction block.
- def [](key)
- in_transaction
- @table[key]
- end
-
- # Like #[], except that it accepts a default value for the store.
- # If the +key+ does not exist:
- #
- # - Raises an exception if +default+ is +PStore::Error+.
- # - Returns the value of +default+ otherwise:
- #
- # example_store do |store|
- # store.transaction do
- # store.fetch(:nope, nil) # => nil
- # store.fetch(:nope) # Raises an exception.
- # end
- # end
- #
- # Raises an exception if called outside a transaction block.
- def fetch(key, default=PStore::Error)
- in_transaction
- unless @table.key? key
- if default == PStore::Error
- raise PStore::Error, format("undefined key '%s'", key)
- else
- return default
- end
- end
- @table[key]
- end
-
- # Creates or replaces the value for the given +key+:
- #
- # example_store do |store|
- # temp.transaction do
- # temp[:bat] = 3
- # end
- # end
- #
- # See also {Hierarchical Values}[rdoc-ref:PStore@Hierarchical+Values].
- #
- # Raises an exception if called outside a transaction block.
- def []=(key, value)
- in_transaction_wr
- @table[key] = value
- end
-
- # Removes and returns the value at +key+ if it exists:
- #
- # example_store do |store|
- # store.transaction do
- # store[:bat] = 3
- # store.delete(:bat)
- # end
- # end
- #
- # Returns +nil+ if there is no such key.
- #
- # Raises an exception if called outside a transaction block.
- def delete(key)
- in_transaction_wr
- @table.delete key
- end
-
- # Returns an array of the existing keys:
- #
- # example_store do |store|
- # store.transaction do
- # store.keys # => [:foo, :bar, :baz]
- # end
- # end
- #
- # Raises an exception if called outside a transaction block.
- def keys
- in_transaction
- @table.keys
- end
- alias roots keys
-
- # Returns +true+ if +key+ exists, +false+ otherwise:
- #
- # example_store do |store|
- # store.transaction do
- # store.key?(:foo) # => true
- # end
- # end
- #
- # Raises an exception if called outside a transaction block.
- def key?(key)
- in_transaction
- @table.key? key
- end
- alias root? key?
-
- # Returns the string file path used to create the store:
- #
- # store.path # => "flat.store"
- #
- def path
- @filename
- end
-
- # Exits the current transaction block, committing any changes
- # specified in the
- # {transaction block}[rdoc-ref:PStore@The+Transaction+Block].
- #
- # Raises an exception if called outside a transaction block.
- def commit
- in_transaction
- @abort = false
- throw :pstore_abort_transaction
- end
-
- # Exits the current transaction block, discarding any changes
- # specified in the
- # {transaction block}[rdoc-ref:PStore@The+Transaction+Block].
- #
- # Raises an exception if called outside a transaction block.
- def abort
- in_transaction
- @abort = true
- throw :pstore_abort_transaction
- end
-
- # Opens a transaction block for the store.
- # See {Transactions}[rdoc-ref:PStore@Transactions].
- #
- # With argument +read_only+ as +false+, the block may both read from
- # and write to the store.
- #
- # With argument +read_only+ as +true+, the block may not include calls
- # to #transaction, #[]=, or #delete.
- #
- # Raises an exception if called within a transaction block.
- def transaction(read_only = false) # :yields: pstore
- value = nil
- if !@thread_safe
- raise PStore::Error, "nested transaction" unless @lock.try_lock
- else
- begin
- @lock.lock
- rescue ThreadError
- raise PStore::Error, "nested transaction"
- end
- end
- begin
- @rdonly = read_only
- @abort = false
- file = open_and_lock_file(@filename, read_only)
- if file
- begin
- @table, checksum, original_data_size = load_data(file, read_only)
-
- catch(:pstore_abort_transaction) do
- value = yield(self)
- end
-
- if !@abort && !read_only
- save_data(checksum, original_data_size, file)
- end
- ensure
- file.close
- end
- else
- # This can only occur if read_only == true.
- @table = {}
- catch(:pstore_abort_transaction) do
- value = yield(self)
- end
- end
- ensure
- @lock.unlock
- end
- value
- end
-
- private
- # Constant for relieving Ruby's garbage collector.
- CHECKSUM_ALGO = %w[SHA512 SHA384 SHA256 SHA1 RMD160 MD5].each do |algo|
- begin
- break Digest(algo)
- rescue LoadError
- end
- end
- EMPTY_STRING = ""
- EMPTY_MARSHAL_DATA = Marshal.dump({})
- EMPTY_MARSHAL_CHECKSUM = CHECKSUM_ALGO.digest(EMPTY_MARSHAL_DATA)
-
- #
- # Open the specified filename (either in read-only mode or in
- # read-write mode) and lock it for reading or writing.
- #
- # The opened File object will be returned. If _read_only_ is true,
- # and the file does not exist, then nil will be returned.
- #
- # All exceptions are propagated.
- #
- def open_and_lock_file(filename, read_only)
- if read_only
- begin
- file = File.new(filename, **RD_ACCESS)
- begin
- file.flock(File::LOCK_SH)
- return file
- rescue
- file.close
- raise
- end
- rescue Errno::ENOENT
- return nil
- end
- else
- file = File.new(filename, **RDWR_ACCESS)
- file.flock(File::LOCK_EX)
- return file
- end
- end
-
- # Load the given PStore file.
- # If +read_only+ is true, the unmarshalled Hash will be returned.
- # If +read_only+ is false, a 3-tuple will be returned: the unmarshalled
- # Hash, a checksum of the data, and the size of the data.
- def load_data(file, read_only)
- if read_only
- begin
- table = load(file)
- raise Error, "PStore file seems to be corrupted." unless table.is_a?(Hash)
- rescue EOFError
- # This seems to be a newly-created file.
- table = {}
- end
- table
- else
- data = file.read
- if data.empty?
- # This seems to be a newly-created file.
- table = {}
- checksum = empty_marshal_checksum
- size = empty_marshal_data.bytesize
- else
- table = load(data)
- checksum = CHECKSUM_ALGO.digest(data)
- size = data.bytesize
- raise Error, "PStore file seems to be corrupted." unless table.is_a?(Hash)
- end
- data.replace(EMPTY_STRING)
- [table, checksum, size]
- end
- end
-
- def on_windows?
- is_windows = RUBY_PLATFORM =~ /mswin|mingw|bccwin|wince/
- self.class.__send__(:define_method, :on_windows?) do
- is_windows
- end
- is_windows
- end
-
- def save_data(original_checksum, original_file_size, file)
- new_data = dump(@table)
-
- if new_data.bytesize != original_file_size || CHECKSUM_ALGO.digest(new_data) != original_checksum
- if @ultra_safe && !on_windows?
- # Windows doesn't support atomic file renames.
- save_data_with_atomic_file_rename_strategy(new_data, file)
- else
- save_data_with_fast_strategy(new_data, file)
- end
- end
-
- new_data.replace(EMPTY_STRING)
- end
-
- def save_data_with_atomic_file_rename_strategy(data, file)
- temp_filename = "#{@filename}.tmp.#{Process.pid}.#{rand 1000000}"
- temp_file = File.new(temp_filename, **WR_ACCESS)
- begin
- temp_file.flock(File::LOCK_EX)
- temp_file.write(data)
- temp_file.flush
- File.rename(temp_filename, @filename)
- rescue
- File.unlink(temp_file) rescue nil
- raise
- ensure
- temp_file.close
- end
- end
-
- def save_data_with_fast_strategy(data, file)
- file.rewind
- file.write(data)
- file.truncate(data.bytesize)
- end
-
-
- # This method is just a wrapped around Marshal.dump
- # to allow subclass overriding used in YAML::Store.
- def dump(table) # :nodoc:
- Marshal::dump(table)
- end
-
- # This method is just a wrapped around Marshal.load.
- # to allow subclass overriding used in YAML::Store.
- def load(content) # :nodoc:
- Marshal::load(content)
- end
-
- def empty_marshal_data
- EMPTY_MARSHAL_DATA
- end
- def empty_marshal_checksum
- EMPTY_MARSHAL_CHECKSUM
- end
-end
diff --git a/lib/random/formatter.rb b/lib/random/formatter.rb
index 037f9d8748..4ecd6ad027 100644
--- a/lib/random/formatter.rb
+++ b/lib/random/formatter.rb
@@ -165,7 +165,7 @@ module Random::Formatter
#
# The result contains 122 random bits (15.25 random bytes).
#
- # See RFC4122[https://www.rfc-editor.org/rfc/rfc4122] for details of UUID.
+ # See RFC9562[https://www.rfc-editor.org/rfc/rfc9562] for details of UUIDv4.
#
def uuid
ary = random_bytes(16)
@@ -204,8 +204,7 @@ module Random::Formatter
# Note that this method cannot be made reproducible because its output
# includes not only random bits but also timestamp.
#
- # See draft-ietf-uuidrev-rfc4122bis[https://datatracker.ietf.org/doc/draft-ietf-uuidrev-rfc4122bis/]
- # for details of UUIDv7.
+ # See RFC9562[https://www.rfc-editor.org/rfc/rfc9562] for details of UUIDv7.
#
# ==== Monotonicity
#
@@ -242,7 +241,7 @@ module Random::Formatter
#
# Counters and other mechanisms for stronger guarantees of monotonicity are
# not implemented. Applications with stricter requirements should follow
- # {Section 6.2}[https://www.ietf.org/archive/id/draft-ietf-uuidrev-rfc4122bis-07.html#monotonicity_counters]
+ # {Section 6.2}[https://www.rfc-editor.org/rfc/rfc9562.html#name-monotonicity-and-counters]
# of the specification.
#
def uuid_v7(extra_timestamp_bits: 0)
@@ -341,7 +340,7 @@ module Random::Formatter
end
# The default character list for #alphanumeric.
- ALPHANUMERIC = [*'A'..'Z', *'a'..'z', *'0'..'9']
+ ALPHANUMERIC = [*'A'..'Z', *'a'..'z', *'0'..'9'].map(&:freeze).freeze
# Generate a random alphanumeric string.
#
diff --git a/lib/rdoc.rb b/lib/rdoc.rb
deleted file mode 100644
index 9dc4595324..0000000000
--- a/lib/rdoc.rb
+++ /dev/null
@@ -1,213 +0,0 @@
-# frozen_string_literal: true
-$DEBUG_RDOC = nil
-
-# :main: README.rdoc
-
-##
-# RDoc produces documentation for Ruby source files by parsing the source and
-# extracting the definition for classes, modules, methods, includes and
-# requires. It associates these with optional documentation contained in an
-# immediately preceding comment block then renders the result using an output
-# formatter.
-#
-# For a simple introduction to writing or generating documentation using RDoc
-# see the README.
-#
-# == Roadmap
-#
-# If you think you found a bug in RDoc see CONTRIBUTING@Bugs
-#
-# If you want to use RDoc to create documentation for your Ruby source files,
-# see RDoc::Markup and refer to <tt>rdoc --help</tt> for command line usage.
-#
-# If you want to set the default markup format see
-# RDoc::Markup@Supported+Formats
-#
-# If you want to store rdoc configuration in your gem (such as the default
-# markup format) see RDoc::Options@Saved+Options
-#
-# If you want to write documentation for Ruby files see RDoc::Parser::Ruby
-#
-# If you want to write documentation for extensions written in C see
-# RDoc::Parser::C
-#
-# If you want to generate documentation using <tt>rake</tt> see RDoc::Task.
-#
-# If you want to drive RDoc programmatically, see RDoc::RDoc.
-#
-# If you want to use the library to format text blocks into HTML or other
-# formats, look at RDoc::Markup.
-#
-# If you want to make an RDoc plugin such as a generator or directive handler
-# see RDoc::RDoc.
-#
-# If you want to write your own output generator see RDoc::Generator.
-#
-# If you want an overview of how RDoc works see CONTRIBUTING
-#
-# == Credits
-#
-# RDoc is currently being maintained by Eric Hodel <drbrain@segment7.net>.
-#
-# Dave Thomas <dave@pragmaticprogrammer.com> is the original author of RDoc.
-#
-# * The Ruby parser in rdoc/parse.rb is based heavily on the outstanding
-# work of Keiju ISHITSUKA of Nippon Rational Inc, who produced the Ruby
-# parser for irb and the rtags package.
-
-module RDoc
-
- ##
- # Exception thrown by any rdoc error.
-
- class Error < RuntimeError; end
-
- require_relative 'rdoc/version'
-
- ##
- # Method visibilities
-
- VISIBILITIES = [:public, :protected, :private]
-
- ##
- # Name of the dotfile that contains the description of files to be processed
- # in the current directory
-
- DOT_DOC_FILENAME = ".document"
-
- ##
- # General RDoc modifiers
-
- GENERAL_MODIFIERS = %w[nodoc].freeze
-
- ##
- # RDoc modifiers for classes
-
- CLASS_MODIFIERS = GENERAL_MODIFIERS
-
- ##
- # RDoc modifiers for attributes
-
- ATTR_MODIFIERS = GENERAL_MODIFIERS
-
- ##
- # RDoc modifiers for constants
-
- CONSTANT_MODIFIERS = GENERAL_MODIFIERS
-
- ##
- # RDoc modifiers for methods
-
- METHOD_MODIFIERS = GENERAL_MODIFIERS +
- %w[arg args yield yields notnew not-new not_new doc]
-
- ##
- # Loads the best available YAML library.
-
- def self.load_yaml
- begin
- gem 'psych'
- rescue NameError => e # --disable-gems
- raise unless e.name == :gem
- rescue Gem::LoadError
- end
-
- begin
- require 'psych'
- rescue ::LoadError
- ensure
- require 'yaml'
- end
- end
-
- ##
- # Searches and returns the directory for settings.
- #
- # 1. <tt>$HOME/.rdoc</tt> directory, if it exists.
- # 2. The +rdoc+ directory under the path specified by the
- # +XDG_DATA_HOME+ environment variable, if it is set.
- # 3. <tt>$HOME/.local/share/rdoc</tt> directory.
- #
- # Other than the home directory, the containing directory will be
- # created automatically.
-
- def self.home
- rdoc_dir = begin
- File.expand_path('~/.rdoc')
- rescue ArgumentError
- end
-
- if File.directory?(rdoc_dir)
- rdoc_dir
- else
- require 'fileutils'
- begin
- # XDG
- xdg_data_home = ENV["XDG_DATA_HOME"] || File.join(File.expand_path("~"), '.local', 'share')
- unless File.exist?(xdg_data_home)
- FileUtils.mkdir_p xdg_data_home
- end
- File.join xdg_data_home, "rdoc"
- rescue Errno::EACCES
- end
- end
- end
-
- autoload :RDoc, "#{__dir__}/rdoc/rdoc"
-
- autoload :CrossReference, "#{__dir__}/rdoc/cross_reference"
- autoload :ERBIO, "#{__dir__}/rdoc/erbio"
- autoload :ERBPartial, "#{__dir__}/rdoc/erb_partial"
- autoload :Encoding, "#{__dir__}/rdoc/encoding"
- autoload :Generator, "#{__dir__}/rdoc/generator"
- autoload :Options, "#{__dir__}/rdoc/options"
- autoload :Parser, "#{__dir__}/rdoc/parser"
- autoload :Servlet, "#{__dir__}/rdoc/servlet"
- autoload :RI, "#{__dir__}/rdoc/ri"
- autoload :Stats, "#{__dir__}/rdoc/stats"
- autoload :Store, "#{__dir__}/rdoc/store"
- autoload :Task, "#{__dir__}/rdoc/task"
- autoload :Text, "#{__dir__}/rdoc/text"
-
- autoload :Markdown, "#{__dir__}/rdoc/markdown"
- autoload :Markup, "#{__dir__}/rdoc/markup"
- autoload :RD, "#{__dir__}/rdoc/rd"
- autoload :TomDoc, "#{__dir__}/rdoc/tom_doc"
-
- autoload :KNOWN_CLASSES, "#{__dir__}/rdoc/known_classes"
-
- autoload :TokenStream, "#{__dir__}/rdoc/token_stream"
-
- autoload :Comment, "#{__dir__}/rdoc/comment"
-
- require_relative 'rdoc/i18n'
-
- # code objects
- #
- # We represent the various high-level code constructs that appear in Ruby
- # programs: classes, modules, methods, and so on.
- autoload :CodeObject, "#{__dir__}/rdoc/code_object"
-
- autoload :Context, "#{__dir__}/rdoc/context"
- autoload :TopLevel, "#{__dir__}/rdoc/top_level"
-
- autoload :AnonClass, "#{__dir__}/rdoc/anon_class"
- autoload :ClassModule, "#{__dir__}/rdoc/class_module"
- autoload :NormalClass, "#{__dir__}/rdoc/normal_class"
- autoload :NormalModule, "#{__dir__}/rdoc/normal_module"
- autoload :SingleClass, "#{__dir__}/rdoc/single_class"
-
- autoload :Alias, "#{__dir__}/rdoc/alias"
- autoload :AnyMethod, "#{__dir__}/rdoc/any_method"
- autoload :MethodAttr, "#{__dir__}/rdoc/method_attr"
- autoload :GhostMethod, "#{__dir__}/rdoc/ghost_method"
- autoload :MetaMethod, "#{__dir__}/rdoc/meta_method"
- autoload :Attr, "#{__dir__}/rdoc/attr"
-
- autoload :Constant, "#{__dir__}/rdoc/constant"
- autoload :Mixin, "#{__dir__}/rdoc/mixin"
- autoload :Include, "#{__dir__}/rdoc/include"
- autoload :Extend, "#{__dir__}/rdoc/extend"
- autoload :Require, "#{__dir__}/rdoc/require"
-
-end
diff --git a/lib/rdoc/.document b/lib/rdoc/.document
deleted file mode 100644
index 6b5e1b21a5..0000000000
--- a/lib/rdoc/.document
+++ /dev/null
@@ -1,2 +0,0 @@
-*.rb
-parser
diff --git a/lib/rdoc/alias.rb b/lib/rdoc/alias.rb
deleted file mode 100644
index 446cf9ccb4..0000000000
--- a/lib/rdoc/alias.rb
+++ /dev/null
@@ -1,111 +0,0 @@
-# frozen_string_literal: true
-##
-# Represent an alias, which is an old_name/new_name pair associated with a
-# particular context
-#--
-# TODO implement Alias as a proxy to a method/attribute, inheriting from
-# MethodAttr
-
-class RDoc::Alias < RDoc::CodeObject
-
- ##
- # Aliased method's name
-
- attr_reader :new_name
-
- alias name new_name
-
- ##
- # Aliasee method's name
-
- attr_reader :old_name
-
- ##
- # Is this an alias declared in a singleton context?
-
- attr_accessor :singleton
-
- ##
- # Source file token stream
-
- attr_reader :text
-
- ##
- # Creates a new Alias with a token stream of +text+ that aliases +old_name+
- # to +new_name+, has +comment+ and is a +singleton+ context.
-
- def initialize(text, old_name, new_name, comment, singleton = false)
- super()
-
- @text = text
- @singleton = singleton
- @old_name = old_name
- @new_name = new_name
- self.comment = comment
- end
-
- ##
- # Order by #singleton then #new_name
-
- def <=>(other)
- [@singleton ? 0 : 1, new_name] <=> [other.singleton ? 0 : 1, other.new_name]
- end
-
- ##
- # HTML fragment reference for this alias
-
- def aref
- type = singleton ? 'c' : 'i'
- "#alias-#{type}-#{html_name}"
- end
-
- ##
- # Full old name including namespace
-
- def full_old_name
- @full_name || "#{parent.name}#{pretty_old_name}"
- end
-
- ##
- # HTML id-friendly version of +#new_name+.
-
- def html_name
- CGI.escape(@new_name.gsub('-', '-2D')).gsub('%','-').sub(/^-/, '')
- end
-
- def inspect # :nodoc:
- parent_name = parent ? parent.name : '(unknown)'
- "#<%s:0x%x %s.alias_method %s, %s>" % [
- self.class, object_id,
- parent_name, @old_name, @new_name,
- ]
- end
-
- ##
- # '::' for the alias of a singleton method/attribute, '#' for instance-level.
-
- def name_prefix
- singleton ? '::' : '#'
- end
-
- ##
- # Old name with prefix '::' or '#'.
-
- def pretty_old_name
- "#{singleton ? '::' : '#'}#{@old_name}"
- end
-
- ##
- # New name with prefix '::' or '#'.
-
- def pretty_new_name
- "#{singleton ? '::' : '#'}#{@new_name}"
- end
-
- alias pretty_name pretty_new_name
-
- def to_s # :nodoc:
- "alias: #{self.new_name} -> #{self.pretty_old_name} in: #{parent}"
- end
-
-end
diff --git a/lib/rdoc/anon_class.rb b/lib/rdoc/anon_class.rb
deleted file mode 100644
index 3c2f0e1877..0000000000
--- a/lib/rdoc/anon_class.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-##
-# An anonymous class like:
-#
-# c = Class.new do end
-#
-# AnonClass is currently not used.
-
-class RDoc::AnonClass < RDoc::ClassModule
-end
diff --git a/lib/rdoc/any_method.rb b/lib/rdoc/any_method.rb
deleted file mode 100644
index 465c4a4fb2..0000000000
--- a/lib/rdoc/any_method.rb
+++ /dev/null
@@ -1,379 +0,0 @@
-# frozen_string_literal: true
-##
-# AnyMethod is the base class for objects representing methods
-
-class RDoc::AnyMethod < RDoc::MethodAttr
-
- ##
- # 2::
- # RDoc 4
- # Added calls_super
- # Added parent name and class
- # Added section title
- # 3::
- # RDoc 4.1
- # Added is_alias_for
-
- MARSHAL_VERSION = 3 # :nodoc:
-
- ##
- # Don't rename \#initialize to \::new
-
- attr_accessor :dont_rename_initialize
-
- ##
- # The C function that implements this method (if it was defined in a C file)
-
- attr_accessor :c_function
-
- # The section title of the method (if defined in a C file via +:category:+)
- attr_accessor :section_title
-
- # Parameters for this method
-
- attr_accessor :params
-
- ##
- # If true this method uses +super+ to call a superclass version
-
- attr_accessor :calls_super
-
- include RDoc::TokenStream
-
- ##
- # Creates a new AnyMethod with a token stream +text+ and +name+
-
- def initialize text, name
- super
-
- @c_function = nil
- @dont_rename_initialize = false
- @token_stream = nil
- @calls_super = false
- @superclass_method = nil
- end
-
- ##
- # Adds +an_alias+ as an alias for this method in +context+.
-
- def add_alias an_alias, context = nil
- method = self.class.new an_alias.text, an_alias.new_name
-
- method.record_location an_alias.file
- method.singleton = self.singleton
- method.params = self.params
- method.visibility = self.visibility
- method.comment = an_alias.comment
- method.is_alias_for = self
- @aliases << method
- context.add_method method if context
- method
- end
-
- ##
- # Prefix for +aref+ is 'method'.
-
- def aref_prefix
- 'method'
- end
-
- ##
- # The call_seq or the param_seq with method name, if there is no call_seq.
- #
- # Use this for displaying a method's argument lists.
-
- def arglists
- if @call_seq then
- @call_seq
- elsif @params then
- "#{name}#{param_seq}"
- end
- end
-
- ##
- # Different ways to call this method
-
- def call_seq
- unless call_seq = _call_seq
- call_seq = is_alias_for._call_seq if is_alias_for
- end
-
- return unless call_seq
-
- deduplicate_call_seq(call_seq)
- end
-
- ##
- # Sets the different ways you can call this method. If an empty +call_seq+
- # is given nil is assumed.
- #
- # See also #param_seq
-
- def call_seq= call_seq
- return if call_seq.empty?
-
- @call_seq = call_seq
- end
-
- ##
- # Whether the method has a call-seq.
-
- def has_call_seq?
- !!(@call_seq || is_alias_for&._call_seq)
- end
-
- ##
- # Loads is_alias_for from the internal name. Returns nil if the alias
- # cannot be found.
-
- def is_alias_for # :nodoc:
- case @is_alias_for
- when RDoc::MethodAttr then
- @is_alias_for
- when Array then
- return nil unless @store
-
- klass_name, singleton, method_name = @is_alias_for
-
- return nil unless klass = @store.find_class_or_module(klass_name)
-
- @is_alias_for = klass.find_method method_name, singleton
- end
- end
-
- ##
- # Dumps this AnyMethod for use by ri. See also #marshal_load
-
- def marshal_dump
- aliases = @aliases.map do |a|
- [a.name, parse(a.comment)]
- end
-
- is_alias_for = [
- @is_alias_for.parent.full_name,
- @is_alias_for.singleton,
- @is_alias_for.name
- ] if @is_alias_for
-
- [ MARSHAL_VERSION,
- @name,
- full_name,
- @singleton,
- @visibility,
- parse(@comment),
- @call_seq,
- @block_params,
- aliases,
- @params,
- @file.relative_name,
- @calls_super,
- @parent.name,
- @parent.class,
- @section.title,
- is_alias_for,
- ]
- end
-
- ##
- # Loads this AnyMethod from +array+. For a loaded AnyMethod the following
- # methods will return cached values:
- #
- # * #full_name
- # * #parent_name
-
- def marshal_load array
- initialize_visibility
-
- @dont_rename_initialize = nil
- @token_stream = nil
- @aliases = []
- @parent = nil
- @parent_name = nil
- @parent_class = nil
- @section = nil
- @file = nil
-
- version = array[0]
- @name = array[1]
- @full_name = array[2]
- @singleton = array[3]
- @visibility = array[4]
- @comment = array[5]
- @call_seq = array[6]
- @block_params = array[7]
- # 8 handled below
- @params = array[9]
- # 10 handled below
- @calls_super = array[11]
- @parent_name = array[12]
- @parent_title = array[13]
- @section_title = array[14]
- @is_alias_for = array[15]
-
- array[8].each do |new_name, comment|
- add_alias RDoc::Alias.new(nil, @name, new_name, comment, @singleton)
- end
-
- @parent_name ||= if @full_name =~ /#/ then
- $`
- else
- name = @full_name.split('::')
- name.pop
- name.join '::'
- end
-
- @file = RDoc::TopLevel.new array[10] if version > 0
- end
-
- ##
- # Method name
- #
- # If the method has no assigned name, it extracts it from #call_seq.
-
- def name
- return @name if @name
-
- @name =
- @call_seq[/^.*?\.(\w+)/, 1] ||
- @call_seq[/^.*?(\w+)/, 1] ||
- @call_seq if @call_seq
- end
-
- ##
- # A list of this method's method and yield parameters. +call-seq+ params
- # are preferred over parsed method and block params.
-
- def param_list
- if @call_seq then
- params = @call_seq.split("\n").last
- params = params.sub(/.*?\((.*)\)/, '\1')
- params = params.sub(/(\{|do)\s*\|([^|]*)\|.*/, ',\2')
- elsif @params then
- params = @params.sub(/\((.*)\)/, '\1')
-
- params << ",#{@block_params}" if @block_params
- elsif @block_params then
- params = @block_params
- else
- return []
- end
-
- if @block_params then
- # If this method has explicit block parameters, remove any explicit
- # &block
- params = params.sub(/,?\s*&\w+/, '')
- else
- params = params.sub(/\&(\w+)/, '\1')
- end
-
- params = params.gsub(/\s+/, '').split(',').reject(&:empty?)
-
- params.map { |param| param.sub(/=.*/, '') }
- end
-
- ##
- # Pretty parameter list for this method. If the method's parameters were
- # given by +call-seq+ it is preferred over the parsed values.
-
- def param_seq
- if @call_seq then
- params = @call_seq.split("\n").last
- params = params.sub(/[^( ]+/, '')
- params = params.sub(/(\|[^|]+\|)\s*\.\.\.\s*(end|\})/, '\1 \2')
- elsif @params then
- params = @params.gsub(/\s*\#.*/, '')
- params = params.tr_s("\n ", " ")
- params = "(#{params})" unless params[0] == ?(
- else
- params = ''
- end
-
- if @block_params then
- # If this method has explicit block parameters, remove any explicit
- # &block
- params = params.sub(/,?\s*&\w+/, '')
-
- block = @block_params.tr_s("\n ", " ")
- if block[0] == ?(
- block = block.sub(/^\(/, '').sub(/\)/, '')
- end
- params << " { |#{block}| ... }"
- end
-
- params
- end
-
- ##
- # Whether to skip the method description, true for methods that have
- # aliases with a call-seq that doesn't include the method name.
-
- def skip_description?
- has_call_seq? && call_seq.nil? && !!(is_alias_for || !aliases.empty?)
- end
-
- ##
- # Sets the store for this method and its referenced code objects.
-
- def store= store
- super
-
- @file = @store.add_file @file.full_name if @file
- end
-
- ##
- # For methods that +super+, find the superclass method that would be called.
-
- def superclass_method
- return unless @calls_super
- return @superclass_method if @superclass_method
-
- parent.each_ancestor do |ancestor|
- if method = ancestor.method_list.find { |m| m.name == @name } then
- @superclass_method = method
- break
- end
- end
-
- @superclass_method
- end
-
- protected
-
- ##
- # call_seq without deduplication and alias lookup.
-
- def _call_seq
- @call_seq if defined?(@call_seq) && @call_seq
- end
-
- private
-
- ##
- # call_seq with alias examples information removed, if this
- # method is an alias method.
-
- def deduplicate_call_seq(call_seq)
- return call_seq unless is_alias_for || !aliases.empty?
-
- method_name = self.name
- method_name = method_name[0, 1] if method_name =~ /\A\[/
-
- entries = call_seq.split "\n"
-
- ignore = aliases.map(&:name)
- if is_alias_for
- ignore << is_alias_for.name
- ignore.concat is_alias_for.aliases.map(&:name)
- end
- ignore.map! { |n| n =~ /\A\[/ ? /\[.*\]/ : n}
- ignore.delete(method_name)
- ignore = Regexp.union(ignore)
-
- matching = entries.reject do |entry|
- entry =~ /^\w*\.?#{ignore}[$\(\s]/ or
- entry =~ /\s#{ignore}\s/
- end
-
- matching.empty? ? nil : matching.join("\n")
- end
-end
diff --git a/lib/rdoc/attr.rb b/lib/rdoc/attr.rb
deleted file mode 100644
index a403235933..0000000000
--- a/lib/rdoc/attr.rb
+++ /dev/null
@@ -1,175 +0,0 @@
-# frozen_string_literal: true
-##
-# An attribute created by \#attr, \#attr_reader, \#attr_writer or
-# \#attr_accessor
-
-class RDoc::Attr < RDoc::MethodAttr
-
- ##
- # 3::
- # RDoc 4
- # Added parent name and class
- # Added section title
-
- MARSHAL_VERSION = 3 # :nodoc:
-
- ##
- # Is the attribute readable ('R'), writable ('W') or both ('RW')?
-
- attr_accessor :rw
-
- ##
- # Creates a new Attr with body +text+, +name+, read/write status +rw+ and
- # +comment+. +singleton+ marks this as a class attribute.
-
- def initialize(text, name, rw, comment, singleton = false)
- super text, name
-
- @rw = rw
- @singleton = singleton
- self.comment = comment
- end
-
- ##
- # Attributes are equal when their names, singleton and rw are identical
-
- def == other
- self.class == other.class and
- self.name == other.name and
- self.rw == other.rw and
- self.singleton == other.singleton
- end
-
- ##
- # Add +an_alias+ as an attribute in +context+.
-
- def add_alias(an_alias, context)
- new_attr = self.class.new(self.text, an_alias.new_name, self.rw,
- self.comment, self.singleton)
-
- new_attr.record_location an_alias.file
- new_attr.visibility = self.visibility
- new_attr.is_alias_for = self
- @aliases << new_attr
- context.add_attribute new_attr
- new_attr
- end
-
- ##
- # The #aref prefix for attributes
-
- def aref_prefix
- 'attribute'
- end
-
- ##
- # Attributes never call super. See RDoc::AnyMethod#calls_super
- #
- # An RDoc::Attr can show up in the method list in some situations (see
- # Gem::ConfigFile)
-
- def calls_super # :nodoc:
- false
- end
-
- ##
- # Returns attr_reader, attr_writer or attr_accessor as appropriate.
-
- def definition
- case @rw
- when 'RW' then 'attr_accessor'
- when 'R' then 'attr_reader'
- when 'W' then 'attr_writer'
- end
- end
-
- def inspect # :nodoc:
- alias_for = @is_alias_for ? " (alias for #{@is_alias_for.name})" : nil
- visibility = self.visibility
- visibility = "forced #{visibility}" if force_documentation
- "#<%s:0x%x %s %s (%s)%s>" % [
- self.class, object_id,
- full_name,
- rw,
- visibility,
- alias_for,
- ]
- end
-
- ##
- # Dumps this Attr for use by ri. See also #marshal_load
-
- def marshal_dump
- [ MARSHAL_VERSION,
- @name,
- full_name,
- @rw,
- @visibility,
- parse(@comment),
- singleton,
- @file.relative_name,
- @parent.full_name,
- @parent.class,
- @section.title
- ]
- end
-
- ##
- # Loads this Attr from +array+. For a loaded Attr the following
- # methods will return cached values:
- #
- # * #full_name
- # * #parent_name
-
- def marshal_load array
- initialize_visibility
-
- @aliases = []
- @parent = nil
- @parent_name = nil
- @parent_class = nil
- @section = nil
- @file = nil
-
- version = array[0]
- @name = array[1]
- @full_name = array[2]
- @rw = array[3]
- @visibility = array[4]
- @comment = array[5]
- @singleton = array[6] || false # MARSHAL_VERSION == 0
- # 7 handled below
- @parent_name = array[8]
- @parent_class = array[9]
- @section_title = array[10]
-
- @file = RDoc::TopLevel.new array[7] if version > 1
-
- @parent_name ||= @full_name.split('#', 2).first
- end
-
- def pretty_print q # :nodoc:
- q.group 2, "[#{self.class.name} #{full_name} #{rw} #{visibility}", "]" do
- unless comment.empty? then
- q.breakable
- q.text "comment:"
- q.breakable
- q.pp @comment
- end
- end
- end
-
- def to_s # :nodoc:
- "#{definition} #{name} in: #{parent}"
- end
-
- ##
- # Attributes do not have token streams.
- #
- # An RDoc::Attr can show up in the method list in some situations (see
- # Gem::ConfigFile)
-
- def token_stream # :nodoc:
- end
-
-end
diff --git a/lib/rdoc/class_module.rb b/lib/rdoc/class_module.rb
deleted file mode 100644
index c69e14b5e4..0000000000
--- a/lib/rdoc/class_module.rb
+++ /dev/null
@@ -1,801 +0,0 @@
-# frozen_string_literal: true
-##
-# ClassModule is the base class for objects representing either a class or a
-# module.
-
-class RDoc::ClassModule < RDoc::Context
-
- ##
- # 1::
- # RDoc 3.7
- # * Added visibility, singleton and file to attributes
- # * Added file to constants
- # * Added file to includes
- # * Added file to methods
- # 2::
- # RDoc 3.13
- # * Added extends
- # 3::
- # RDoc 4.0
- # * Added sections
- # * Added in_files
- # * Added parent name
- # * Complete Constant dump
-
- MARSHAL_VERSION = 3 # :nodoc:
-
- ##
- # Constants that are aliases for this class or module
-
- attr_accessor :constant_aliases
-
- ##
- # Comment and the location it came from. Use #add_comment to add comments
-
- attr_accessor :comment_location
-
- attr_accessor :diagram # :nodoc:
-
- ##
- # Class or module this constant is an alias for
-
- attr_accessor :is_alias_for
-
- ##
- # Return a RDoc::ClassModule of class +class_type+ that is a copy
- # of module +module+. Used to promote modules to classes.
- #--
- # TODO move to RDoc::NormalClass (I think)
-
- def self.from_module class_type, mod
- klass = class_type.new mod.name
-
- mod.comment_location.each do |comment, location|
- klass.add_comment comment, location
- end
-
- klass.parent = mod.parent
- klass.section = mod.section
- klass.viewer = mod.viewer
-
- klass.attributes.concat mod.attributes
- klass.method_list.concat mod.method_list
- klass.aliases.concat mod.aliases
- klass.external_aliases.concat mod.external_aliases
- klass.constants.concat mod.constants
- klass.includes.concat mod.includes
- klass.extends.concat mod.extends
-
- klass.methods_hash.update mod.methods_hash
- klass.constants_hash.update mod.constants_hash
-
- klass.current_section = mod.current_section
- klass.in_files.concat mod.in_files
- klass.sections.concat mod.sections
- klass.unmatched_alias_lists = mod.unmatched_alias_lists
- klass.current_section = mod.current_section
- klass.visibility = mod.visibility
-
- klass.classes_hash.update mod.classes_hash
- klass.modules_hash.update mod.modules_hash
- klass.metadata.update mod.metadata
-
- klass.document_self = mod.received_nodoc ? nil : mod.document_self
- klass.document_children = mod.document_children
- klass.force_documentation = mod.force_documentation
- klass.done_documenting = mod.done_documenting
-
- # update the parent of all children
-
- (klass.attributes +
- klass.method_list +
- klass.aliases +
- klass.external_aliases +
- klass.constants +
- klass.includes +
- klass.extends +
- klass.classes +
- klass.modules).each do |obj|
- obj.parent = klass
- obj.full_name = nil
- end
-
- klass
- end
-
- ##
- # Creates a new ClassModule with +name+ with optional +superclass+
- #
- # This is a constructor for subclasses, and must never be called directly.
-
- def initialize(name, superclass = nil)
- @constant_aliases = []
- @diagram = nil
- @is_alias_for = nil
- @name = name
- @superclass = superclass
- @comment_location = [] # [[comment, location]]
-
- super()
- end
-
- ##
- # Adds +comment+ to this ClassModule's list of comments at +location+. This
- # method is preferred over #comment= since it allows ri data to be updated
- # across multiple runs.
-
- def add_comment comment, location
- return unless document_self
-
- original = comment
-
- comment = case comment
- when RDoc::Comment then
- comment.normalize
- else
- normalize_comment comment
- end
-
- if location.parser == RDoc::Parser::C
- @comment_location.delete_if { |(_, l)| l == location }
- end
-
- @comment_location << [comment, location]
-
- self.comment = original
- end
-
- def add_things my_things, other_things # :nodoc:
- other_things.each do |group, things|
- my_things[group].each { |thing| yield false, thing } if
- my_things.include? group
-
- things.each do |thing|
- yield true, thing
- end
- end
- end
-
- ##
- # Ancestors list for this ClassModule: the list of included modules
- # (classes will add their superclass if any).
- #
- # Returns the included classes or modules, not the includes
- # themselves. The returned values are either String or
- # RDoc::NormalModule instances (see RDoc::Include#module).
- #
- # The values are returned in reverse order of their inclusion,
- # which is the order suitable for searching methods/attributes
- # in the ancestors. The superclass, if any, comes last.
-
- def ancestors
- includes.map { |i| i.module }.reverse
- end
-
- def aref_prefix # :nodoc:
- raise NotImplementedError, "missing aref_prefix for #{self.class}"
- end
-
- ##
- # HTML fragment reference for this module or class. See
- # RDoc::NormalClass#aref and RDoc::NormalModule#aref
-
- def aref
- "#{aref_prefix}-#{full_name}"
- end
-
- ##
- # Ancestors of this class or module only
-
- alias direct_ancestors ancestors
-
- ##
- # Clears the comment. Used by the Ruby parser.
-
- def clear_comment
- @comment = ''
- end
-
- ##
- # This method is deprecated, use #add_comment instead.
- #
- # Appends +comment+ to the current comment, but separated by a rule. Works
- # more like <tt>+=</tt>.
-
- def comment= comment # :nodoc:
- comment = case comment
- when RDoc::Comment then
- comment.normalize
- else
- normalize_comment comment
- end
-
- comment = "#{@comment.to_s}\n---\n#{comment.to_s}" unless @comment.empty?
-
- super comment
- end
-
- ##
- # Prepares this ClassModule for use by a generator.
- #
- # See RDoc::Store#complete
-
- def complete min_visibility
- update_aliases
- remove_nodoc_children
- update_includes
- remove_invisible min_visibility
- end
-
- ##
- # Does this ClassModule or any of its methods have document_self set?
-
- def document_self_or_methods
- document_self || method_list.any?{ |m| m.document_self }
- end
-
- ##
- # Does this class or module have a comment with content or is
- # #received_nodoc true?
-
- def documented?
- return true if @received_nodoc
- return false if @comment_location.empty?
- @comment_location.any? { |comment, _| not comment.empty? }
- end
-
- ##
- # Iterates the ancestors of this class or module for which an
- # RDoc::ClassModule exists.
-
- def each_ancestor # :yields: module
- return enum_for __method__ unless block_given?
-
- ancestors.each do |mod|
- next if String === mod
- next if self == mod
- yield mod
- end
- end
-
- ##
- # Looks for a symbol in the #ancestors. See Context#find_local_symbol.
-
- def find_ancestor_local_symbol symbol
- each_ancestor do |m|
- res = m.find_local_symbol(symbol)
- return res if res
- end
-
- nil
- end
-
- ##
- # Finds a class or module with +name+ in this namespace or its descendants
-
- def find_class_named name
- return self if full_name == name
- return self if @name == name
-
- @classes.values.find do |klass|
- next if klass == self
- klass.find_class_named name
- end
- end
-
- ##
- # Return the fully qualified name of this class or module
-
- def full_name
- @full_name ||= if RDoc::ClassModule === parent then
- "#{parent.full_name}::#{@name}"
- else
- @name
- end
- end
-
- ##
- # TODO: filter included items by #display?
-
- def marshal_dump # :nodoc:
- attrs = attributes.sort.map do |attr|
- next unless attr.display?
- [ attr.name, attr.rw,
- attr.visibility, attr.singleton, attr.file_name,
- ]
- end.compact
-
- method_types = methods_by_type.map do |type, visibilities|
- visibilities = visibilities.map do |visibility, methods|
- method_names = methods.map do |method|
- next unless method.display?
- [method.name, method.file_name]
- end.compact
-
- [visibility, method_names.uniq]
- end
-
- [type, visibilities]
- end
-
- [ MARSHAL_VERSION,
- @name,
- full_name,
- @superclass,
- parse(@comment_location),
- attrs,
- constants.select { |constant| constant.display? },
- includes.map do |incl|
- next unless incl.display?
- [incl.name, parse(incl.comment), incl.file_name]
- end.compact,
- method_types,
- extends.map do |ext|
- next unless ext.display?
- [ext.name, parse(ext.comment), ext.file_name]
- end.compact,
- @sections.values,
- @in_files.map do |tl|
- tl.relative_name
- end,
- parent.full_name,
- parent.class,
- ]
- end
-
- def marshal_load array # :nodoc:
- initialize_visibility
- initialize_methods_etc
- @current_section = nil
- @document_self = true
- @done_documenting = false
- @parent = nil
- @temporary_section = nil
- @visibility = nil
- @classes = {}
- @modules = {}
-
- @name = array[1]
- @full_name = array[2]
- @superclass = array[3]
- @comment = array[4]
-
- @comment_location = if RDoc::Markup::Document === @comment.parts.first then
- @comment
- else
- RDoc::Markup::Document.new @comment
- end
-
- array[5].each do |name, rw, visibility, singleton, file|
- singleton ||= false
- visibility ||= :public
-
- attr = RDoc::Attr.new nil, name, rw, nil, singleton
-
- add_attribute attr
- attr.visibility = visibility
- attr.record_location RDoc::TopLevel.new file
- end
-
- array[6].each do |constant, comment, file|
- case constant
- when RDoc::Constant then
- add_constant constant
- else
- constant = add_constant RDoc::Constant.new(constant, nil, comment)
- constant.record_location RDoc::TopLevel.new file
- end
- end
-
- array[7].each do |name, comment, file|
- incl = add_include RDoc::Include.new(name, comment)
- incl.record_location RDoc::TopLevel.new file
- end
-
- array[8].each do |type, visibilities|
- visibilities.each do |visibility, methods|
- @visibility = visibility
-
- methods.each do |name, file|
- method = RDoc::AnyMethod.new nil, name
- method.singleton = true if type == 'class'
- method.record_location RDoc::TopLevel.new file
- add_method method
- end
- end
- end
-
- array[9].each do |name, comment, file|
- ext = add_extend RDoc::Extend.new(name, comment)
- ext.record_location RDoc::TopLevel.new file
- end if array[9] # Support Marshal version 1
-
- sections = (array[10] || []).map do |section|
- [section.title, section]
- end
-
- @sections = Hash[*sections.flatten]
- @current_section = add_section nil
-
- @in_files = []
-
- (array[11] || []).each do |filename|
- record_location RDoc::TopLevel.new filename
- end
-
- @parent_name = array[12]
- @parent_class = array[13]
- end
-
- ##
- # Merges +class_module+ into this ClassModule.
- #
- # The data in +class_module+ is preferred over the receiver.
-
- def merge class_module
- @parent = class_module.parent
- @parent_name = class_module.parent_name
-
- other_document = parse class_module.comment_location
-
- if other_document then
- document = parse @comment_location
-
- document = document.merge other_document
-
- @comment = @comment_location = document
- end
-
- cm = class_module
- other_files = cm.in_files
-
- merge_collections attributes, cm.attributes, other_files do |add, attr|
- if add then
- add_attribute attr
- else
- @attributes.delete attr
- @methods_hash.delete attr.pretty_name
- end
- end
-
- merge_collections constants, cm.constants, other_files do |add, const|
- if add then
- add_constant const
- else
- @constants.delete const
- @constants_hash.delete const.name
- end
- end
-
- merge_collections includes, cm.includes, other_files do |add, incl|
- if add then
- add_include incl
- else
- @includes.delete incl
- end
- end
-
- @includes.uniq! # clean up
-
- merge_collections extends, cm.extends, other_files do |add, ext|
- if add then
- add_extend ext
- else
- @extends.delete ext
- end
- end
-
- @extends.uniq! # clean up
-
- merge_collections method_list, cm.method_list, other_files do |add, meth|
- if add then
- add_method meth
- else
- @method_list.delete meth
- @methods_hash.delete meth.pretty_name
- end
- end
-
- merge_sections cm
-
- self
- end
-
- ##
- # Merges collection +mine+ with +other+ preferring other. +other_files+ is
- # used to help determine which items should be deleted.
- #
- # Yields whether the item should be added or removed (true or false) and the
- # item to be added or removed.
- #
- # merge_collections things, other.things, other.in_files do |add, thing|
- # if add then
- # # add the thing
- # else
- # # remove the thing
- # end
- # end
-
- def merge_collections mine, other, other_files, &block # :nodoc:
- my_things = mine. group_by { |thing| thing.file }
- other_things = other.group_by { |thing| thing.file }
-
- remove_things my_things, other_files, &block
- add_things my_things, other_things, &block
- end
-
- ##
- # Merges the comments in this ClassModule with the comments in the other
- # ClassModule +cm+.
-
- def merge_sections cm # :nodoc:
- my_sections = sections.group_by { |section| section.title }
- other_sections = cm.sections.group_by { |section| section.title }
-
- other_files = cm.in_files
-
- remove_things my_sections, other_files do |_, section|
- @sections.delete section.title
- end
-
- other_sections.each do |group, sections|
- if my_sections.include? group
- my_sections[group].each do |my_section|
- other_section = cm.sections_hash[group]
-
- my_comments = my_section.comments
- other_comments = other_section.comments
-
- other_files = other_section.in_files
-
- merge_collections my_comments, other_comments, other_files do |add, comment|
- if add then
- my_section.add_comment comment
- else
- my_section.remove_comment comment
- end
- end
- end
- else
- sections.each do |section|
- add_section group, section.comments
- end
- end
- end
- end
-
- ##
- # Does this object represent a module?
-
- def module?
- false
- end
-
- ##
- # Allows overriding the initial name.
- #
- # Used for modules and classes that are constant aliases.
-
- def name= new_name
- @name = new_name
- end
-
- ##
- # Parses +comment_location+ into an RDoc::Markup::Document composed of
- # multiple RDoc::Markup::Documents with their file set.
-
- def parse comment_location
- case comment_location
- when String then
- super
- when Array then
- docs = comment_location.map do |comment, location|
- doc = super comment
- doc.file = location
- doc
- end
-
- RDoc::Markup::Document.new(*docs)
- when RDoc::Comment then
- doc = super comment_location.text, comment_location.format
- doc.file = comment_location.location
- doc
- when RDoc::Markup::Document then
- return comment_location
- else
- raise ArgumentError, "unknown comment class #{comment_location.class}"
- end
- end
-
- ##
- # Path to this class or module for use with HTML generator output.
-
- def path
- http_url @store.rdoc.generator.class_dir
- end
-
- ##
- # Name to use to generate the url:
- # modules and classes that are aliases for another
- # module or class return the name of the latter.
-
- def name_for_path
- is_alias_for ? is_alias_for.full_name : full_name
- end
-
- ##
- # Returns the classes and modules that are not constants
- # aliasing another class or module. For use by formatters
- # only (caches its result).
-
- def non_aliases
- @non_aliases ||= classes_and_modules.reject { |cm| cm.is_alias_for }
- end
-
- ##
- # Updates the child modules or classes of class/module +parent+ by
- # deleting the ones that have been removed from the documentation.
- #
- # +parent_hash+ is either <tt>parent.modules_hash</tt> or
- # <tt>parent.classes_hash</tt> and +all_hash+ is ::all_modules_hash or
- # ::all_classes_hash.
-
- def remove_nodoc_children
- prefix = self.full_name + '::'
-
- modules_hash.each_key do |name|
- full_name = prefix + name
- modules_hash.delete name unless @store.modules_hash[full_name]
- end
-
- classes_hash.each_key do |name|
- full_name = prefix + name
- classes_hash.delete name unless @store.classes_hash[full_name]
- end
- end
-
- def remove_things my_things, other_files # :nodoc:
- my_things.delete_if do |file, things|
- next false unless other_files.include? file
-
- things.each do |thing|
- yield false, thing
- end
-
- true
- end
- end
-
- ##
- # Search record used by RDoc::Generator::JsonIndex
-
- def search_record
- [
- name,
- full_name,
- full_name,
- '',
- path,
- '',
- snippet(@comment_location),
- ]
- end
-
- ##
- # Sets the store for this class or module and its contained code objects.
-
- def store= store
- super
-
- @attributes .each do |attr| attr.store = store end
- @constants .each do |const| const.store = store end
- @includes .each do |incl| incl.store = store end
- @extends .each do |ext| ext.store = store end
- @method_list.each do |meth| meth.store = store end
- end
-
- ##
- # Get the superclass of this class. Attempts to retrieve the superclass
- # object, returns the name if it is not known.
-
- def superclass
- @store.find_class_named(@superclass) || @superclass
- end
-
- ##
- # Set the superclass of this class to +superclass+
-
- def superclass=(superclass)
- raise NoMethodError, "#{full_name} is a module" if module?
- @superclass = superclass
- end
-
- def to_s # :nodoc:
- if is_alias_for then
- "#{self.class.name} #{self.full_name} -> #{is_alias_for}"
- else
- super
- end
- end
-
- ##
- # 'module' or 'class'
-
- def type
- module? ? 'module' : 'class'
- end
-
- ##
- # Updates the child modules & classes by replacing the ones that are
- # aliases through a constant.
- #
- # The aliased module/class is replaced in the children and in
- # RDoc::Store#modules_hash or RDoc::Store#classes_hash
- # by a copy that has <tt>RDoc::ClassModule#is_alias_for</tt> set to
- # the aliased module/class, and this copy is added to <tt>#aliases</tt>
- # of the aliased module/class.
- #
- # Formatters can use the #non_aliases method to retrieve children that
- # are not aliases, for instance to list the namespace content, since
- # the aliased modules are included in the constants of the class/module,
- # that are listed separately.
-
- def update_aliases
- constants.each do |const|
- next unless cm = const.is_alias_for
- cm_alias = cm.dup
- cm_alias.name = const.name
-
- # Don't move top-level aliases under Object, they look ugly there
- unless RDoc::TopLevel === cm_alias.parent then
- cm_alias.parent = self
- cm_alias.full_name = nil # force update for new parent
- end
-
- cm_alias.aliases.clear
- cm_alias.is_alias_for = cm
-
- if cm.module? then
- @store.modules_hash[cm_alias.full_name] = cm_alias
- modules_hash[const.name] = cm_alias
- else
- @store.classes_hash[cm_alias.full_name] = cm_alias
- classes_hash[const.name] = cm_alias
- end
-
- cm.aliases << cm_alias
- end
- end
-
- ##
- # Deletes from #includes those whose module has been removed from the
- # documentation.
- #--
- # FIXME: includes are not reliably removed, see _possible_bug test case
-
- def update_includes
- includes.reject! do |include|
- mod = include.module
- !(String === mod) && @store.modules_hash[mod.full_name].nil?
- end
-
- includes.uniq!
- end
-
- ##
- # Deletes from #extends those whose module has been removed from the
- # documentation.
- #--
- # FIXME: like update_includes, extends are not reliably removed
-
- def update_extends
- extends.reject! do |ext|
- mod = ext.module
-
- !(String === mod) && @store.modules_hash[mod.full_name].nil?
- end
-
- extends.uniq!
- end
-
-end
diff --git a/lib/rdoc/code_object.rb b/lib/rdoc/code_object.rb
deleted file mode 100644
index aeb4b4762e..0000000000
--- a/lib/rdoc/code_object.rb
+++ /dev/null
@@ -1,421 +0,0 @@
-# frozen_string_literal: true
-##
-# Base class for the RDoc code tree.
-#
-# We contain the common stuff for contexts (which are containers) and other
-# elements (methods, attributes and so on)
-#
-# Here's the tree of the CodeObject subclasses:
-#
-# * RDoc::Context
-# * RDoc::TopLevel
-# * RDoc::ClassModule
-# * RDoc::AnonClass (never used so far)
-# * RDoc::NormalClass
-# * RDoc::NormalModule
-# * RDoc::SingleClass
-# * RDoc::MethodAttr
-# * RDoc::Attr
-# * RDoc::AnyMethod
-# * RDoc::GhostMethod
-# * RDoc::MetaMethod
-# * RDoc::Alias
-# * RDoc::Constant
-# * RDoc::Mixin
-# * RDoc::Require
-# * RDoc::Include
-
-class RDoc::CodeObject
-
- include RDoc::Text
-
- ##
- # Our comment
-
- attr_reader :comment
-
- ##
- # Do we document our children?
-
- attr_reader :document_children
-
- ##
- # Do we document ourselves?
-
- attr_reader :document_self
-
- ##
- # Are we done documenting (ie, did we come across a :enddoc:)?
-
- attr_reader :done_documenting
-
- ##
- # Which file this code object was defined in
-
- attr_reader :file
-
- ##
- # Force documentation of this CodeObject
-
- attr_reader :force_documentation
-
- ##
- # Line in #file where this CodeObject was defined
-
- attr_accessor :line
-
- ##
- # Hash of arbitrary metadata for this CodeObject
-
- attr_reader :metadata
-
- ##
- # Sets the parent CodeObject
-
- attr_writer :parent
-
- ##
- # Did we ever receive a +:nodoc:+ directive?
-
- attr_reader :received_nodoc
-
- ##
- # Set the section this CodeObject is in
-
- attr_writer :section
-
- ##
- # The RDoc::Store for this object.
-
- attr_reader :store
-
- ##
- # We are the model of the code, but we know that at some point we will be
- # worked on by viewers. By implementing the Viewable protocol, viewers can
- # associated themselves with these objects.
-
- attr_accessor :viewer
-
- ##
- # Creates a new CodeObject that will document itself and its children
-
- def initialize
- @metadata = {}
- @comment = ''
- @parent = nil
- @parent_name = nil # for loading
- @parent_class = nil # for loading
- @section = nil
- @section_title = nil # for loading
- @file = nil
- @full_name = nil
- @store = nil
- @track_visibility = true
-
- initialize_visibility
- end
-
- ##
- # Initializes state for visibility of this CodeObject and its children.
-
- def initialize_visibility # :nodoc:
- @document_children = true
- @document_self = true
- @done_documenting = false
- @force_documentation = false
- @received_nodoc = false
- @ignored = false
- @suppressed = false
- @track_visibility = true
- end
-
- ##
- # Replaces our comment with +comment+, unless it is empty.
-
- def comment=(comment)
- @comment = case comment
- when NilClass then ''
- when RDoc::Markup::Document then comment
- when RDoc::Comment then comment.normalize
- else
- if comment and not comment.empty? then
- normalize_comment comment
- else
- # HACK correct fix is to have #initialize create @comment
- # with the correct encoding
- if String === @comment and @comment.empty? then
- @comment = RDoc::Encoding.change_encoding @comment, comment.encoding
- end
- @comment
- end
- end
- end
-
- ##
- # Should this CodeObject be displayed in output?
- #
- # A code object should be displayed if:
- #
- # * The item didn't have a nodoc or wasn't in a container that had nodoc
- # * The item wasn't ignored
- # * The item has documentation and was not suppressed
-
- def display?
- @document_self and not @ignored and
- (documented? or not @suppressed)
- end
-
- ##
- # Enables or disables documentation of this CodeObject's children unless it
- # has been turned off by :enddoc:
-
- def document_children=(document_children)
- return unless @track_visibility
-
- @document_children = document_children unless @done_documenting
- end
-
- ##
- # Enables or disables documentation of this CodeObject unless it has been
- # turned off by :enddoc:. If the argument is +nil+ it means the
- # documentation is turned off by +:nodoc:+.
-
- def document_self=(document_self)
- return unless @track_visibility
- return if @done_documenting
-
- @document_self = document_self
- @received_nodoc = true if document_self.nil?
- end
-
- ##
- # Does this object have a comment with content or is #received_nodoc true?
-
- def documented?
- @received_nodoc or !@comment.empty?
- end
-
- ##
- # Turns documentation on/off, and turns on/off #document_self
- # and #document_children.
- #
- # Once documentation has been turned off (by +:enddoc:+),
- # the object will refuse to turn #document_self or
- # #document_children on, so +:doc:+ and +:start_doc:+ directives
- # will have no effect in the current file.
-
- def done_documenting=(value)
- return unless @track_visibility
- @done_documenting = value
- @document_self = !value
- @document_children = @document_self
- end
-
- ##
- # Yields each parent of this CodeObject. See also
- # RDoc::ClassModule#each_ancestor
-
- def each_parent
- code_object = self
-
- while code_object = code_object.parent do
- yield code_object
- end
-
- self
- end
-
- ##
- # File name where this CodeObject was found.
- #
- # See also RDoc::Context#in_files
-
- def file_name
- return unless @file
-
- @file.absolute_name
- end
-
- ##
- # Force the documentation of this object unless documentation
- # has been turned off by :enddoc:
- #--
- # HACK untested, was assigning to an ivar
-
- def force_documentation=(value)
- @force_documentation = value unless @done_documenting
- end
-
- ##
- # Sets the full_name overriding any computed full name.
- #
- # Set to +nil+ to clear RDoc's cached value
-
- def full_name= full_name
- @full_name = full_name
- end
-
- ##
- # Use this to ignore a CodeObject and all its children until found again
- # (#record_location is called). An ignored item will not be displayed in
- # documentation.
- #
- # See github issue #55
- #
- # The ignored status is temporary in order to allow implementation details
- # to be hidden. At the end of processing a file RDoc allows all classes
- # and modules to add new documentation to previously created classes.
- #
- # If a class was ignored (via stopdoc) then reopened later with additional
- # documentation it should be displayed. If a class was ignored and never
- # reopened it should not be displayed. The ignore flag allows this to
- # occur.
-
- def ignore
- return unless @track_visibility
-
- @ignored = true
-
- stop_doc
- end
-
- ##
- # Has this class been ignored?
- #
- # See also #ignore
-
- def ignored?
- @ignored
- end
-
- ##
- # The options instance from the store this CodeObject is attached to, or a
- # default options instance if the CodeObject is not attached.
- #
- # This is used by Text#snippet
-
- def options
- if @store and @store.rdoc then
- @store.rdoc.options
- else
- RDoc::Options.new
- end
- end
-
- ##
- # Our parent CodeObject. The parent may be missing for classes loaded from
- # legacy RI data stores.
-
- def parent
- return @parent if @parent
- return nil unless @parent_name
-
- if @parent_class == RDoc::TopLevel then
- @parent = @store.add_file @parent_name
- else
- @parent = @store.find_class_or_module @parent_name
-
- return @parent if @parent
-
- begin
- @parent = @store.load_class @parent_name
- rescue RDoc::Store::MissingFileError
- nil
- end
- end
- end
-
- ##
- # File name of our parent
-
- def parent_file_name
- @parent ? @parent.base_name : '(unknown)'
- end
-
- ##
- # Name of our parent
-
- def parent_name
- @parent ? @parent.full_name : '(unknown)'
- end
-
- ##
- # Records the RDoc::TopLevel (file) where this code object was defined
-
- def record_location top_level
- @ignored = false
- @suppressed = false
- @file = top_level
- end
-
- ##
- # The section this CodeObject is in. Sections allow grouping of constants,
- # attributes and methods inside a class or module.
-
- def section
- return @section if @section
-
- @section = parent.add_section @section_title if parent
- end
-
- ##
- # Enable capture of documentation unless documentation has been
- # turned off by :enddoc:
-
- def start_doc
- return if @done_documenting
-
- @document_self = true
- @document_children = true
- @ignored = false
- @suppressed = false
- end
-
- ##
- # Disable capture of documentation
-
- def stop_doc
- return unless @track_visibility
-
- @document_self = false
- @document_children = false
- end
-
- ##
- # Sets the +store+ that contains this CodeObject
-
- def store= store
- @store = store
-
- return unless @track_visibility
-
- if :nodoc == options.visibility then
- initialize_visibility
- @track_visibility = false
- end
- end
-
- ##
- # Use this to suppress a CodeObject and all its children until the next file
- # it is seen in or documentation is discovered. A suppressed item with
- # documentation will be displayed while an ignored item with documentation
- # may not be displayed.
-
- def suppress
- return unless @track_visibility
-
- @suppressed = true
-
- stop_doc
- end
-
- ##
- # Has this class been suppressed?
- #
- # See also #suppress
-
- def suppressed?
- @suppressed
- end
-
-end
diff --git a/lib/rdoc/code_objects.rb b/lib/rdoc/code_objects.rb
deleted file mode 100644
index d5f2f920ad..0000000000
--- a/lib/rdoc/code_objects.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-# frozen_string_literal: true
-# This file was used to load all the RDoc::CodeObject subclasses at once. Now
-# autoload handles this.
-
-require_relative '../rdoc'
diff --git a/lib/rdoc/comment.rb b/lib/rdoc/comment.rb
deleted file mode 100644
index 04ec226436..0000000000
--- a/lib/rdoc/comment.rb
+++ /dev/null
@@ -1,229 +0,0 @@
-# frozen_string_literal: true
-##
-# A comment holds the text comment for a RDoc::CodeObject and provides a
-# unified way of cleaning it up and parsing it into an RDoc::Markup::Document.
-#
-# Each comment may have a different markup format set by #format=. By default
-# 'rdoc' is used. The :markup: directive tells RDoc which format to use.
-#
-# See RDoc::MarkupReference@Directive+for+Specifying+RDoc+Source+Format.
-
-
-class RDoc::Comment
-
- include RDoc::Text
-
- ##
- # The format of this comment. Defaults to RDoc::Markup
-
- attr_reader :format
-
- ##
- # The RDoc::TopLevel this comment was found in
-
- attr_accessor :location
-
- ##
- # Line where this Comment was written
-
- attr_accessor :line
-
- ##
- # For duck-typing when merging classes at load time
-
- alias file location # :nodoc:
-
- ##
- # The text for this comment
-
- attr_reader :text
-
- ##
- # Alias for text
-
- alias to_s text
-
- ##
- # Overrides the content returned by #parse. Use when there is no #text
- # source for this comment
-
- attr_writer :document
-
- ##
- # Creates a new comment with +text+ that is found in the RDoc::TopLevel
- # +location+.
-
- def initialize text = nil, location = nil, language = nil
- @location = location
- @text = text.nil? ? nil : text.dup
- @language = language
-
- @document = nil
- @format = 'rdoc'
- @normalized = false
- end
-
- ##
- #--
- # TODO deep copy @document
-
- def initialize_copy copy # :nodoc:
- @text = copy.text.dup
- end
-
- def == other # :nodoc:
- self.class === other and
- other.text == @text and other.location == @location
- end
-
- ##
- # Look for a 'call-seq' in the comment to override the normal parameter
- # handling. The :call-seq: is indented from the baseline. All lines of the
- # same indentation level and prefix are consumed.
- #
- # For example, all of the following will be used as the :call-seq:
- #
- # # :call-seq:
- # # ARGF.readlines(sep=$/) -> array
- # # ARGF.readlines(limit) -> array
- # # ARGF.readlines(sep, limit) -> array
- # #
- # # ARGF.to_a(sep=$/) -> array
- # # ARGF.to_a(limit) -> array
- # # ARGF.to_a(sep, limit) -> array
-
- def extract_call_seq method
- # we must handle situations like the above followed by an unindented first
- # comment. The difficulty is to make sure not to match lines starting
- # with ARGF at the same indent, but that are after the first description
- # paragraph.
- if /^(?<S> ((?!\n)\s)*+ (?# whitespaces except newline))
- :?call-seq:
- (?<B> \g<S>(?<N>\n|\z) (?# trailing spaces))?
- (?<seq>
- (\g<S>(?!\w)\S.*\g<N>)*
- (?>
- (?<H> \g<S>\w+ (?# ' # ARGF' in the example above))
- .*\g<N>)?
- (\g<S>\S.*\g<N> (?# other non-blank line))*+
- (\g<B>+(\k<H>.*\g<N> (?# ARGF.to_a lines))++)*+
- )
- (?m:^\s*$|\z)
- /x =~ @text
- seq = $~[:seq]
-
- all_start, all_stop = $~.offset(0)
- @text.slice! all_start...all_stop
-
- seq.gsub!(/^\s*/, '')
- method.call_seq = seq
- end
-
- method
- end
-
- ##
- # A comment is empty if its text String is empty.
-
- def empty?
- @text.empty?
- end
-
- ##
- # HACK dubious
-
- def encode! encoding
- @text = String.new @text, encoding: encoding
- self
- end
-
- ##
- # Sets the format of this comment and resets any parsed document
-
- def format= format
- @format = format
- @document = nil
- end
-
- def inspect # :nodoc:
- location = @location ? @location.relative_name : '(unknown)'
-
- "#<%s:%x %s %p>" % [self.class, object_id, location, @text]
- end
-
- ##
- # Normalizes the text. See RDoc::Text#normalize_comment for details
-
- def normalize
- return self unless @text
- return self if @normalized # TODO eliminate duplicate normalization
-
- @text = normalize_comment @text
-
- @normalized = true
-
- self
- end
-
- ##
- # Was this text normalized?
-
- def normalized? # :nodoc:
- @normalized
- end
-
- ##
- # Parses the comment into an RDoc::Markup::Document. The parsed document is
- # cached until the text is changed.
-
- def parse
- return @document if @document
-
- @document = super @text, @format
- @document.file = @location
- @document
- end
-
- ##
- # Removes private sections from this comment. Private sections are flush to
- # the comment marker and start with <tt>--</tt> and end with <tt>++</tt>.
- # For C-style comments, a private marker may not start at the opening of the
- # comment.
- #
- # /*
- # *--
- # * private
- # *++
- # * public
- # */
-
- def remove_private
- # Workaround for gsub encoding for Ruby 1.9.2 and earlier
- empty = ''
- empty = RDoc::Encoding.change_encoding empty, @text.encoding
-
- @text = @text.gsub(%r%^\s*([#*]?)--.*?^\s*(\1)\+\+\n?%m, empty)
- @text = @text.sub(%r%^\s*[#*]?--.*%m, '')
- end
-
- ##
- # Replaces this comment's text with +text+ and resets the parsed document.
- #
- # An error is raised if the comment contains a document but no text.
-
- def text= text
- raise RDoc::Error, 'replacing document-only comment is not allowed' if
- @text.nil? and @document
-
- @document = nil
- @text = text.nil? ? nil : text.dup
- end
-
- ##
- # Returns true if this comment is in TomDoc format.
-
- def tomdoc?
- @format == 'tomdoc'
- end
-
-end
diff --git a/lib/rdoc/constant.rb b/lib/rdoc/constant.rb
deleted file mode 100644
index 12b8be775c..0000000000
--- a/lib/rdoc/constant.rb
+++ /dev/null
@@ -1,186 +0,0 @@
-# frozen_string_literal: true
-##
-# A constant
-
-class RDoc::Constant < RDoc::CodeObject
-
- MARSHAL_VERSION = 0 # :nodoc:
-
- ##
- # Sets the module or class this is constant is an alias for.
-
- attr_writer :is_alias_for
-
- ##
- # The constant's name
-
- attr_accessor :name
-
- ##
- # The constant's value
-
- attr_accessor :value
-
- ##
- # The constant's visibility
-
- attr_accessor :visibility
-
- ##
- # Creates a new constant with +name+, +value+ and +comment+
-
- def initialize(name, value, comment)
- super()
-
- @name = name
- @value = value
-
- @is_alias_for = nil
- @visibility = :public
-
- self.comment = comment
- end
-
- ##
- # Constants are ordered by name
-
- def <=> other
- return unless self.class === other
-
- [parent_name, name] <=> [other.parent_name, other.name]
- end
-
- ##
- # Constants are equal when their #parent and #name is the same
-
- def == other
- self.class == other.class and
- @parent == other.parent and
- @name == other.name
- end
-
- ##
- # A constant is documented if it has a comment, or is an alias
- # for a documented class or module.
-
- def documented?
- return true if super
- return false unless @is_alias_for
- case @is_alias_for
- when String then
- found = @store.find_class_or_module @is_alias_for
- return false unless found
- @is_alias_for = found
- end
- @is_alias_for.documented?
- end
-
- ##
- # Full constant name including namespace
-
- def full_name
- @full_name ||= "#{parent_name}::#{@name}"
- end
-
- ##
- # The module or class this constant is an alias for
-
- def is_alias_for
- case @is_alias_for
- when String then
- found = @store.find_class_or_module @is_alias_for
- @is_alias_for = found if found
- @is_alias_for
- else
- @is_alias_for
- end
- end
-
- def inspect # :nodoc:
- "#<%s:0x%x %s::%s>" % [
- self.class, object_id,
- parent_name, @name,
- ]
- end
-
- ##
- # Dumps this Constant for use by ri. See also #marshal_load
-
- def marshal_dump
- alias_name = case found = is_alias_for
- when RDoc::CodeObject then found.full_name
- else found
- end
-
- [ MARSHAL_VERSION,
- @name,
- full_name,
- @visibility,
- alias_name,
- parse(@comment),
- @file.relative_name,
- parent.name,
- parent.class,
- section.title,
- ]
- end
-
- ##
- # Loads this Constant from +array+. For a loaded Constant the following
- # methods will return cached values:
- #
- # * #full_name
- # * #parent_name
-
- def marshal_load array
- initialize array[1], nil, array[5]
-
- @full_name = array[2]
- @visibility = array[3] || :public
- @is_alias_for = array[4]
- # 5 handled above
- # 6 handled below
- @parent_name = array[7]
- @parent_class = array[8]
- @section_title = array[9]
-
- @file = RDoc::TopLevel.new array[6]
- end
-
- ##
- # Path to this constant for use with HTML generator output.
-
- def path
- "#{@parent.path}##{@name}"
- end
-
- def pretty_print q # :nodoc:
- q.group 2, "[#{self.class.name} #{full_name}", "]" do
- unless comment.empty? then
- q.breakable
- q.text "comment:"
- q.breakable
- q.pp @comment
- end
- end
- end
-
- ##
- # Sets the store for this class or module and its contained code objects.
-
- def store= store
- super
-
- @file = @store.add_file @file.full_name if @file
- end
-
- def to_s # :nodoc:
- parent_name = parent ? parent.full_name : '(unknown)'
- if is_alias_for
- "constant #{parent_name}::#@name -> #{is_alias_for}"
- else
- "constant #{parent_name}::#@name"
- end
- end
-
-end
diff --git a/lib/rdoc/context.rb b/lib/rdoc/context.rb
deleted file mode 100644
index c688d562c3..0000000000
--- a/lib/rdoc/context.rb
+++ /dev/null
@@ -1,1264 +0,0 @@
-# frozen_string_literal: true
-##
-# A Context is something that can hold modules, classes, methods, attributes,
-# aliases, requires, and includes. Classes, modules, and files are all
-# Contexts.
-
-class RDoc::Context < RDoc::CodeObject
-
- include Comparable
-
- ##
- # Types of methods
-
- TYPES = %w[class instance]
-
- ##
- # If a context has these titles it will be sorted in this order.
-
- TOMDOC_TITLES = [nil, 'Public', 'Internal', 'Deprecated'] # :nodoc:
- TOMDOC_TITLES_SORT = TOMDOC_TITLES.sort_by { |title| title.to_s } # :nodoc:
-
- ##
- # Class/module aliases
-
- attr_reader :aliases
-
- ##
- # All attr* methods
-
- attr_reader :attributes
-
- ##
- # Block params to be used in the next MethodAttr parsed under this context
-
- attr_accessor :block_params
-
- ##
- # Constants defined
-
- attr_reader :constants
-
- ##
- # Sets the current documentation section of documentation
-
- attr_writer :current_section
-
- ##
- # Files this context is found in
-
- attr_reader :in_files
-
- ##
- # Modules this context includes
-
- attr_reader :includes
-
- ##
- # Modules this context is extended with
-
- attr_reader :extends
-
- ##
- # Methods defined in this context
-
- attr_reader :method_list
-
- ##
- # Name of this class excluding namespace. See also full_name
-
- attr_reader :name
-
- ##
- # Files this context requires
-
- attr_reader :requires
-
- ##
- # Use this section for the next method, attribute or constant added.
-
- attr_accessor :temporary_section
-
- ##
- # Hash <tt>old_name => [aliases]</tt>, for aliases
- # that haven't (yet) been resolved to a method/attribute.
- # (Not to be confused with the aliases of the context.)
-
- attr_accessor :unmatched_alias_lists
-
- ##
- # Aliases that could not be resolved.
-
- attr_reader :external_aliases
-
- ##
- # Current visibility of this context
-
- attr_accessor :visibility
-
- ##
- # Current visibility of this line
-
- attr_writer :current_line_visibility
-
- ##
- # Hash of registered methods. Attributes are also registered here,
- # twice if they are RW.
-
- attr_reader :methods_hash
-
- ##
- # Params to be used in the next MethodAttr parsed under this context
-
- attr_accessor :params
-
- ##
- # Hash of registered constants.
-
- attr_reader :constants_hash
-
- ##
- # Creates an unnamed empty context with public current visibility
-
- def initialize
- super
-
- @in_files = []
-
- @name ||= "unknown"
- @parent = nil
- @visibility = :public
-
- @current_section = Section.new self, nil, nil
- @sections = { nil => @current_section }
- @temporary_section = nil
-
- @classes = {}
- @modules = {}
-
- initialize_methods_etc
- end
-
- ##
- # Sets the defaults for methods and so-forth
-
- def initialize_methods_etc
- @method_list = []
- @attributes = []
- @aliases = []
- @requires = []
- @includes = []
- @extends = []
- @constants = []
- @external_aliases = []
- @current_line_visibility = nil
-
- # This Hash maps a method name to a list of unmatched aliases (aliases of
- # a method not yet encountered).
- @unmatched_alias_lists = {}
-
- @methods_hash = {}
- @constants_hash = {}
-
- @params = nil
-
- @store ||= nil
- end
-
- ##
- # Contexts are sorted by full_name
-
- def <=>(other)
- return nil unless RDoc::CodeObject === other
-
- full_name <=> other.full_name
- end
-
- ##
- # Adds an item of type +klass+ with the given +name+ and +comment+ to the
- # context.
- #
- # Currently only RDoc::Extend and RDoc::Include are supported.
-
- def add klass, name, comment
- if RDoc::Extend == klass then
- ext = RDoc::Extend.new name, comment
- add_extend ext
- elsif RDoc::Include == klass then
- incl = RDoc::Include.new name, comment
- add_include incl
- else
- raise NotImplementedError, "adding a #{klass} is not implemented"
- end
- end
-
- ##
- # Adds +an_alias+ that is automatically resolved
-
- def add_alias an_alias
- return an_alias unless @document_self
-
- method_attr = find_method(an_alias.old_name, an_alias.singleton) ||
- find_attribute(an_alias.old_name, an_alias.singleton)
-
- if method_attr then
- method_attr.add_alias an_alias, self
- else
- add_to @external_aliases, an_alias
- unmatched_alias_list =
- @unmatched_alias_lists[an_alias.pretty_old_name] ||= []
- unmatched_alias_list.push an_alias
- end
-
- an_alias
- end
-
- ##
- # Adds +attribute+ if not already there. If it is (as method(s) or attribute),
- # updates the comment if it was empty.
- #
- # The attribute is registered only if it defines a new method.
- # For instance, <tt>attr_reader :foo</tt> will not be registered
- # if method +foo+ exists, but <tt>attr_accessor :foo</tt> will be registered
- # if method +foo+ exists, but <tt>foo=</tt> does not.
-
- def add_attribute attribute
- return attribute unless @document_self
-
- # mainly to check for redefinition of an attribute as a method
- # TODO find a policy for 'attr_reader :foo' + 'def foo=()'
- register = false
-
- key = nil
-
- if attribute.rw.index 'R' then
- key = attribute.pretty_name
- known = @methods_hash[key]
-
- if known then
- known.comment = attribute.comment if known.comment.empty?
- elsif registered = @methods_hash[attribute.pretty_name + '='] and
- RDoc::Attr === registered then
- registered.rw = 'RW'
- else
- @methods_hash[key] = attribute
- register = true
- end
- end
-
- if attribute.rw.index 'W' then
- key = attribute.pretty_name + '='
- known = @methods_hash[key]
-
- if known then
- known.comment = attribute.comment if known.comment.empty?
- elsif registered = @methods_hash[attribute.pretty_name] and
- RDoc::Attr === registered then
- registered.rw = 'RW'
- else
- @methods_hash[key] = attribute
- register = true
- end
- end
-
- if register then
- attribute.visibility = @visibility
- add_to @attributes, attribute
- resolve_aliases attribute
- end
-
- attribute
- end
-
- ##
- # Adds a class named +given_name+ with +superclass+.
- #
- # Both +given_name+ and +superclass+ may contain '::', and are
- # interpreted relative to the +self+ context. This allows handling correctly
- # examples like these:
- # class RDoc::Gauntlet < Gauntlet
- # module Mod
- # class Object # implies < ::Object
- # class SubObject < Object # this is _not_ ::Object
- #
- # Given <tt>class Container::Item</tt> RDoc assumes +Container+ is a module
- # unless it later sees <tt>class Container</tt>. +add_class+ automatically
- # upgrades +given_name+ to a class in this case.
-
- def add_class class_type, given_name, superclass = '::Object'
- # superclass +nil+ is passed by the C parser in the following cases:
- # - registering Object in 1.8 (correct)
- # - registering BasicObject in 1.9 (correct)
- # - registering RubyVM in 1.9 in iseq.c (incorrect: < Object in vm.c)
- #
- # If we later find a superclass for a registered class with a nil
- # superclass, we must honor it.
-
- # find the name & enclosing context
- if given_name =~ /^:+(\w+)$/ then
- full_name = $1
- enclosing = top_level
- name = full_name.split(/:+/).last
- else
- full_name = child_name given_name
-
- if full_name =~ /^(.+)::(\w+)$/ then
- name = $2
- ename = $1
- enclosing = @store.classes_hash[ename] || @store.modules_hash[ename]
- # HACK: crashes in actionpack/lib/action_view/helpers/form_helper.rb (metaprogramming)
- unless enclosing then
- # try the given name at top level (will work for the above example)
- enclosing = @store.classes_hash[given_name] ||
- @store.modules_hash[given_name]
- return enclosing if enclosing
- # not found: create the parent(s)
- names = ename.split('::')
- enclosing = self
- names.each do |n|
- enclosing = enclosing.classes_hash[n] ||
- enclosing.modules_hash[n] ||
- enclosing.add_module(RDoc::NormalModule, n)
- end
- end
- else
- name = full_name
- enclosing = self
- end
- end
-
- # fix up superclass
- if full_name == 'BasicObject' then
- superclass = nil
- elsif full_name == 'Object' then
- superclass = '::BasicObject'
- end
-
- # find the superclass full name
- if superclass then
- if superclass =~ /^:+/ then
- superclass = $' #'
- else
- if superclass =~ /^(\w+):+(.+)$/ then
- suffix = $2
- mod = find_module_named($1)
- superclass = mod.full_name + '::' + suffix if mod
- else
- mod = find_module_named(superclass)
- superclass = mod.full_name if mod
- end
- end
-
- # did we believe it was a module?
- mod = @store.modules_hash.delete superclass
-
- upgrade_to_class mod, RDoc::NormalClass, mod.parent if mod
-
- # e.g., Object < Object
- superclass = nil if superclass == full_name
- end
-
- klass = @store.classes_hash[full_name]
-
- if klass then
- # if TopLevel, it may not be registered in the classes:
- enclosing.classes_hash[name] = klass
-
- # update the superclass if needed
- if superclass then
- existing = klass.superclass
- existing = existing.full_name unless existing.is_a?(String) if existing
- if existing.nil? ||
- (existing == 'Object' && superclass != 'Object') then
- klass.superclass = superclass
- end
- end
- else
- # this is a new class
- mod = @store.modules_hash.delete full_name
-
- if mod then
- klass = upgrade_to_class mod, RDoc::NormalClass, enclosing
-
- klass.superclass = superclass unless superclass.nil?
- else
- klass = class_type.new name, superclass
-
- enclosing.add_class_or_module(klass, enclosing.classes_hash,
- @store.classes_hash)
- end
- end
-
- klass.parent = self
-
- klass
- end
-
- ##
- # Adds the class or module +mod+ to the modules or
- # classes Hash +self_hash+, and to +all_hash+ (either
- # <tt>TopLevel::modules_hash</tt> or <tt>TopLevel::classes_hash</tt>),
- # unless #done_documenting is +true+. Sets the #parent of +mod+
- # to +self+, and its #section to #current_section. Returns +mod+.
-
- def add_class_or_module mod, self_hash, all_hash
- mod.section = current_section # TODO declaring context? something is
- # wrong here...
- mod.parent = self
- mod.full_name = nil
- mod.store = @store
-
- unless @done_documenting then
- self_hash[mod.name] = mod
- # this must be done AFTER adding mod to its parent, so that the full
- # name is correct:
- all_hash[mod.full_name] = mod
- if @store.unmatched_constant_alias[mod.full_name] then
- to, file = @store.unmatched_constant_alias[mod.full_name]
- add_module_alias mod, mod.name, to, file
- end
- end
-
- mod
- end
-
- ##
- # Adds +constant+ if not already there. If it is, updates the comment,
- # value and/or is_alias_for of the known constant if they were empty/nil.
-
- def add_constant constant
- return constant unless @document_self
-
- # HACK: avoid duplicate 'PI' & 'E' in math.c (1.8.7 source code)
- # (this is a #ifdef: should be handled by the C parser)
- known = @constants_hash[constant.name]
-
- if known then
- known.comment = constant.comment if known.comment.empty?
-
- known.value = constant.value if
- known.value.nil? or known.value.strip.empty?
-
- known.is_alias_for ||= constant.is_alias_for
- else
- @constants_hash[constant.name] = constant
- add_to @constants, constant
- end
-
- constant
- end
-
- ##
- # Adds included module +include+ which should be an RDoc::Include
-
- def add_include include
- add_to @includes, include
-
- include
- end
-
- ##
- # Adds extension module +ext+ which should be an RDoc::Extend
-
- def add_extend ext
- add_to @extends, ext
-
- ext
- end
-
- ##
- # Adds +method+ if not already there. If it is (as method or attribute),
- # updates the comment if it was empty.
-
- def add_method method
- return method unless @document_self
-
- # HACK: avoid duplicate 'new' in io.c & struct.c (1.8.7 source code)
- key = method.pretty_name
- known = @methods_hash[key]
-
- if known then
- if @store then # otherwise we are loading
- known.comment = method.comment if known.comment.empty?
- previously = ", previously in #{known.file}" unless
- method.file == known.file
- @store.rdoc.options.warn \
- "Duplicate method #{known.full_name} in #{method.file}#{previously}"
- end
- else
- @methods_hash[key] = method
- if @current_line_visibility
- method.visibility, @current_line_visibility = @current_line_visibility, nil
- else
- method.visibility = @visibility
- end
- add_to @method_list, method
- resolve_aliases method
- end
-
- method
- end
-
- ##
- # Adds a module named +name+. If RDoc already knows +name+ is a class then
- # that class is returned instead. See also #add_class.
-
- def add_module(class_type, name)
- mod = @classes[name] || @modules[name]
- return mod if mod
-
- full_name = child_name name
- mod = @store.modules_hash[full_name] || class_type.new(name)
-
- add_class_or_module mod, @modules, @store.modules_hash
- end
-
- ##
- # Adds a module by +RDoc::NormalModule+ instance. See also #add_module.
-
- def add_module_by_normal_module(mod)
- add_class_or_module mod, @modules, @store.modules_hash
- end
-
- ##
- # Adds an alias from +from+ (a class or module) to +name+ which was defined
- # in +file+.
-
- def add_module_alias from, from_name, to, file
- return from if @done_documenting
-
- to_full_name = child_name to.name
-
- # if we already know this name, don't register an alias:
- # see the metaprogramming in lib/active_support/basic_object.rb,
- # where we already know BasicObject is a class when we find
- # BasicObject = BlankSlate
- return from if @store.find_class_or_module to_full_name
-
- unless from
- @store.unmatched_constant_alias[child_name(from_name)] = [to, file]
- return to
- end
-
- new_to = from.dup
- new_to.name = to.name
- new_to.full_name = nil
-
- if new_to.module? then
- @store.modules_hash[to_full_name] = new_to
- @modules[to.name] = new_to
- else
- @store.classes_hash[to_full_name] = new_to
- @classes[to.name] = new_to
- end
-
- # Registers a constant for this alias. The constant value and comment
- # will be updated later, when the Ruby parser adds the constant
- const = RDoc::Constant.new to.name, nil, new_to.comment
- const.record_location file
- const.is_alias_for = from
- add_constant const
-
- new_to
- end
-
- ##
- # Adds +require+ to this context's top level
-
- def add_require(require)
- return require unless @document_self
-
- if RDoc::TopLevel === self then
- add_to @requires, require
- else
- parent.add_require require
- end
- end
-
- ##
- # Returns a section with +title+, creating it if it doesn't already exist.
- # +comment+ will be appended to the section's comment.
- #
- # A section with a +title+ of +nil+ will return the default section.
- #
- # See also RDoc::Context::Section
-
- def add_section title, comment = nil
- if section = @sections[title] then
- section.add_comment comment if comment
- else
- section = Section.new self, title, comment
- @sections[title] = section
- end
-
- section
- end
-
- ##
- # Adds +thing+ to the collection +array+
-
- def add_to array, thing
- array << thing if @document_self
-
- thing.parent = self
- thing.store = @store if @store
- thing.section = current_section
- end
-
- ##
- # Is there any content?
- #
- # This means any of: comment, aliases, methods, attributes, external
- # aliases, require, constant.
- #
- # Includes and extends are also checked unless <tt>includes == false</tt>.
-
- def any_content(includes = true)
- @any_content ||= !(
- @comment.empty? &&
- @method_list.empty? &&
- @attributes.empty? &&
- @aliases.empty? &&
- @external_aliases.empty? &&
- @requires.empty? &&
- @constants.empty?
- )
- @any_content || (includes && !(@includes + @extends).empty? )
- end
-
- ##
- # Creates the full name for a child with +name+
-
- def child_name name
- if name =~ /^:+/
- $' #'
- elsif RDoc::TopLevel === self then
- name
- else
- "#{self.full_name}::#{name}"
- end
- end
-
- ##
- # Class attributes
-
- def class_attributes
- @class_attributes ||= attributes.select { |a| a.singleton }
- end
-
- ##
- # Class methods
-
- def class_method_list
- @class_method_list ||= method_list.select { |a| a.singleton }
- end
-
- ##
- # Array of classes in this context
-
- def classes
- @classes.values
- end
-
- ##
- # All classes and modules in this namespace
-
- def classes_and_modules
- classes + modules
- end
-
- ##
- # Hash of classes keyed by class name
-
- def classes_hash
- @classes
- end
-
- ##
- # The current documentation section that new items will be added to. If
- # temporary_section is available it will be used.
-
- def current_section
- if section = @temporary_section then
- @temporary_section = nil
- else
- section = @current_section
- end
-
- section
- end
-
- ##
- # Is part of this thing was defined in +file+?
-
- def defined_in?(file)
- @in_files.include?(file)
- end
-
- def display(method_attr) # :nodoc:
- if method_attr.is_a? RDoc::Attr
- "#{method_attr.definition} #{method_attr.pretty_name}"
- else
- "method #{method_attr.pretty_name}"
- end
- end
-
- ##
- # Iterator for ancestors for duck-typing. Does nothing. See
- # RDoc::ClassModule#each_ancestor.
- #
- # This method exists to make it easy to work with Context subclasses that
- # aren't part of RDoc.
-
- def each_ancestor(&_) # :nodoc:
- end
-
- ##
- # Iterator for attributes
-
- def each_attribute # :yields: attribute
- @attributes.each { |a| yield a }
- end
-
- ##
- # Iterator for classes and modules
-
- def each_classmodule(&block) # :yields: module
- classes_and_modules.sort.each(&block)
- end
-
- ##
- # Iterator for constants
-
- def each_constant # :yields: constant
- @constants.each {|c| yield c}
- end
-
- ##
- # Iterator for included modules
-
- def each_include # :yields: include
- @includes.each do |i| yield i end
- end
-
- ##
- # Iterator for extension modules
-
- def each_extend # :yields: extend
- @extends.each do |e| yield e end
- end
-
- ##
- # Iterator for methods
-
- def each_method # :yields: method
- return enum_for __method__ unless block_given?
-
- @method_list.sort.each { |m| yield m }
- end
-
- ##
- # Iterator for each section's contents sorted by title. The +section+, the
- # section's +constants+ and the sections +attributes+ are yielded. The
- # +constants+ and +attributes+ collections are sorted.
- #
- # To retrieve methods in a section use #methods_by_type with the optional
- # +section+ parameter.
- #
- # NOTE: Do not edit collections yielded by this method
-
- def each_section # :yields: section, constants, attributes
- return enum_for __method__ unless block_given?
-
- constants = @constants.group_by do |constant| constant.section end
- attributes = @attributes.group_by do |attribute| attribute.section end
-
- constants.default = []
- attributes.default = []
-
- sort_sections.each do |section|
- yield section, constants[section].select(&:display?).sort, attributes[section].select(&:display?).sort
- end
- end
-
- ##
- # Finds an attribute +name+ with singleton value +singleton+.
-
- def find_attribute(name, singleton)
- name = $1 if name =~ /^(.*)=$/
- @attributes.find { |a| a.name == name && a.singleton == singleton }
- end
-
- ##
- # Finds an attribute with +name+ in this context
-
- def find_attribute_named(name)
- case name
- when /\A#/ then
- find_attribute name[1..-1], false
- when /\A::/ then
- find_attribute name[2..-1], true
- else
- @attributes.find { |a| a.name == name }
- end
- end
-
- ##
- # Finds a class method with +name+ in this context
-
- def find_class_method_named(name)
- @method_list.find { |meth| meth.singleton && meth.name == name }
- end
-
- ##
- # Finds a constant with +name+ in this context
-
- def find_constant_named(name)
- @constants.find do |m|
- m.name == name || m.full_name == name
- end
- end
-
- ##
- # Find a module at a higher scope
-
- def find_enclosing_module_named(name)
- parent && parent.find_module_named(name)
- end
-
- ##
- # Finds an external alias +name+ with singleton value +singleton+.
-
- def find_external_alias(name, singleton)
- @external_aliases.find { |m| m.name == name && m.singleton == singleton }
- end
-
- ##
- # Finds an external alias with +name+ in this context
-
- def find_external_alias_named(name)
- case name
- when /\A#/ then
- find_external_alias name[1..-1], false
- when /\A::/ then
- find_external_alias name[2..-1], true
- else
- @external_aliases.find { |a| a.name == name }
- end
- end
-
- ##
- # Finds a file with +name+ in this context
-
- def find_file_named name
- @store.find_file_named name
- end
-
- ##
- # Finds an instance method with +name+ in this context
-
- def find_instance_method_named(name)
- @method_list.find { |meth| !meth.singleton && meth.name == name }
- end
-
- ##
- # Finds a method, constant, attribute, external alias, module or file
- # named +symbol+ in this context.
-
- def find_local_symbol(symbol)
- find_method_named(symbol) or
- find_constant_named(symbol) or
- find_attribute_named(symbol) or
- find_external_alias_named(symbol) or
- find_module_named(symbol) or
- find_file_named(symbol)
- end
-
- ##
- # Finds a method named +name+ with singleton value +singleton+.
-
- def find_method(name, singleton)
- @method_list.find { |m|
- if m.singleton
- m.name == name && m.singleton == singleton
- else
- m.name == name && !m.singleton && !singleton
- end
- }
- end
-
- ##
- # Finds a instance or module method with +name+ in this context
-
- def find_method_named(name)
- case name
- when /\A#/ then
- find_method name[1..-1], false
- when /\A::/ then
- find_method name[2..-1], true
- else
- @method_list.find { |meth| meth.name == name }
- end
- end
-
- ##
- # Find a module with +name+ using ruby's scoping rules
-
- def find_module_named(name)
- res = @modules[name] || @classes[name]
- return res if res
- return self if self.name == name
- find_enclosing_module_named name
- end
-
- ##
- # Look up +symbol+, first as a module, then as a local symbol.
-
- def find_symbol(symbol)
- find_symbol_module(symbol) || find_local_symbol(symbol)
- end
-
- ##
- # Look up a module named +symbol+.
-
- def find_symbol_module(symbol)
- result = nil
-
- # look for a class or module 'symbol'
- case symbol
- when /^::/ then
- result = @store.find_class_or_module symbol
- when /^(\w+):+(.+)$/
- suffix = $2
- top = $1
- searched = self
- while searched do
- mod = searched.find_module_named(top)
- break unless mod
- result = @store.find_class_or_module "#{mod.full_name}::#{suffix}"
- break if result || searched.is_a?(RDoc::TopLevel)
- searched = searched.parent
- end
- else
- searched = self
- while searched do
- result = searched.find_module_named(symbol)
- break if result || searched.is_a?(RDoc::TopLevel)
- searched = searched.parent
- end
- end
-
- result
- end
-
- ##
- # The full name for this context. This method is overridden by subclasses.
-
- def full_name
- '(unknown)'
- end
-
- ##
- # Does this context and its methods and constants all have documentation?
- #
- # (Yes, fully documented doesn't mean everything.)
-
- def fully_documented?
- documented? and
- attributes.all? { |a| a.documented? } and
- method_list.all? { |m| m.documented? } and
- constants.all? { |c| c.documented? }
- end
-
- ##
- # URL for this with a +prefix+
-
- def http_url(prefix)
- path = name_for_path
- path = path.gsub(/<<\s*(\w*)/, 'from-\1') if path =~ /<</
- path = [prefix] + path.split('::')
-
- File.join(*path.compact) + '.html'
- end
-
- ##
- # Instance attributes
-
- 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 remove this later
-
- def instance_method_list
- warn '#instance_method_list is obsoleted, please use #instance_methods'
- @instance_methods ||= method_list.reject { |a| a.singleton }
- end
-
- ##
- # Breaks method_list into a nested hash by type (<tt>'class'</tt> or
- # <tt>'instance'</tt>) and visibility (+:public+, +:protected+, +:private+).
- #
- # If +section+ is provided only methods in that RDoc::Context::Section will
- # be returned.
-
- def methods_by_type section = nil
- methods = {}
-
- TYPES.each do |type|
- visibilities = {}
- RDoc::VISIBILITIES.each do |vis|
- visibilities[vis] = []
- end
-
- methods[type] = visibilities
- end
-
- each_method do |method|
- next if section and not method.section == section
- methods[method.type][method.visibility] << method
- end
-
- methods
- end
-
- ##
- # Yields AnyMethod and Attr entries matching the list of names in +methods+.
-
- def methods_matching(methods, singleton = false, &block)
- (@method_list + @attributes).each do |m|
- yield m if methods.include?(m.name) and m.singleton == singleton
- end
-
- each_ancestor do |parent|
- parent.methods_matching(methods, singleton, &block)
- end
- end
-
- ##
- # Array of modules in this context
-
- def modules
- @modules.values
- end
-
- ##
- # Hash of modules keyed by module name
-
- def modules_hash
- @modules
- end
-
- ##
- # Name to use to generate the url.
- # <tt>#full_name</tt> by default.
-
- def name_for_path
- full_name
- end
-
- ##
- # Changes the visibility for new methods to +visibility+
-
- def ongoing_visibility=(visibility)
- @visibility = visibility
- end
-
- ##
- # Record +top_level+ as a file +self+ is in.
-
- def record_location(top_level)
- @in_files << top_level unless @in_files.include?(top_level)
- end
-
- ##
- # Should we remove this context from the documentation?
- #
- # The answer is yes if:
- # * #received_nodoc is +true+
- # * #any_content is +false+ (not counting includes)
- # * All #includes are modules (not a string), and their module has
- # <tt>#remove_from_documentation? == true</tt>
- # * All classes and modules have <tt>#remove_from_documentation? == true</tt>
-
- def remove_from_documentation?
- @remove_from_documentation ||=
- @received_nodoc &&
- !any_content(false) &&
- @includes.all? { |i| !i.module.is_a?(String) && i.module.remove_from_documentation? } &&
- classes_and_modules.all? { |cm| cm.remove_from_documentation? }
- end
-
- ##
- # Removes methods and attributes with a visibility less than +min_visibility+.
- #--
- # TODO mark the visibility of attributes in the template (if not public?)
-
- def remove_invisible min_visibility
- return if [:private, :nodoc].include? min_visibility
- remove_invisible_in @method_list, min_visibility
- remove_invisible_in @attributes, min_visibility
- remove_invisible_in @constants, min_visibility
- end
-
- ##
- # Only called when min_visibility == :public or :private
-
- def remove_invisible_in array, min_visibility # :nodoc:
- if min_visibility == :public then
- array.reject! { |e|
- e.visibility != :public and not e.force_documentation
- }
- else
- array.reject! { |e|
- e.visibility == :private and not e.force_documentation
- }
- end
- end
-
- ##
- # Tries to resolve unmatched aliases when a method or attribute has just
- # been added.
-
- def resolve_aliases added
- # resolve any pending unmatched aliases
- key = added.pretty_name
- unmatched_alias_list = @unmatched_alias_lists[key]
- return unless unmatched_alias_list
- unmatched_alias_list.each do |unmatched_alias|
- added.add_alias unmatched_alias, self
- @external_aliases.delete unmatched_alias
- end
- @unmatched_alias_lists.delete key
- end
-
- ##
- # Returns RDoc::Context::Section objects referenced in this context for use
- # in a table of contents.
-
- def section_contents
- used_sections = {}
-
- each_method do |method|
- next unless method.display?
-
- used_sections[method.section] = true
- end
-
- # order found sections
- sections = sort_sections.select do |section|
- used_sections[section]
- end
-
- # only the default section is used
- return [] if
- sections.length == 1 and not sections.first.title
-
- sections
- end
-
- ##
- # Sections in this context
-
- def sections
- @sections.values
- end
-
- def sections_hash # :nodoc:
- @sections
- end
-
- ##
- # Sets the current section to a section with +title+. See also #add_section
-
- def set_current_section title, comment
- @current_section = add_section title, comment
- end
-
- ##
- # Given an array +methods+ of method names, set the visibility of each to
- # +visibility+
-
- def set_visibility_for(methods, visibility, singleton = false)
- methods_matching methods, singleton do |m|
- m.visibility = visibility
- end
- end
-
- ##
- # Given an array +names+ of constants, set the visibility of each constant to
- # +visibility+
-
- def set_constant_visibility_for(names, visibility)
- names.each do |name|
- constant = @constants_hash[name] or next
- constant.visibility = visibility
- end
- end
-
- ##
- # Sorts sections alphabetically (default) or in TomDoc fashion (none,
- # Public, Internal, Deprecated)
-
- def sort_sections
- titles = @sections.map { |title, _| title }
-
- if titles.length > 1 and
- TOMDOC_TITLES_SORT ==
- (titles | TOMDOC_TITLES).sort_by { |title| title.to_s } then
- @sections.values_at(*TOMDOC_TITLES).compact
- else
- @sections.sort_by { |title, _|
- title.to_s
- }.map { |_, section|
- section
- }
- end
- end
-
- def to_s # :nodoc:
- "#{self.class.name} #{self.full_name}"
- end
-
- ##
- # Return the TopLevel that owns us
- #--
- # FIXME we can be 'owned' by several TopLevel (see #record_location &
- # #in_files)
-
- def top_level
- return @top_level if defined? @top_level
- @top_level = self
- @top_level = @top_level.parent until RDoc::TopLevel === @top_level
- @top_level
- end
-
- ##
- # Upgrades NormalModule +mod+ in +enclosing+ to a +class_type+
-
- def upgrade_to_class mod, class_type, enclosing
- enclosing.modules_hash.delete mod.name
-
- klass = RDoc::ClassModule.from_module class_type, mod
- klass.store = @store
-
- # if it was there, then we keep it even if done_documenting
- @store.classes_hash[mod.full_name] = klass
- enclosing.classes_hash[mod.name] = klass
-
- klass
- end
-
- autoload :Section, "#{__dir__}/context/section"
-
-end
diff --git a/lib/rdoc/context/section.rb b/lib/rdoc/context/section.rb
deleted file mode 100644
index aecd4e0213..0000000000
--- a/lib/rdoc/context/section.rb
+++ /dev/null
@@ -1,233 +0,0 @@
-# frozen_string_literal: true
-require 'cgi/util'
-
-##
-# A section of documentation like:
-#
-# # :section: The title
-# # The body
-#
-# Sections can be referenced multiple times and will be collapsed into a
-# single section.
-
-class RDoc::Context::Section
-
- include RDoc::Text
-
- MARSHAL_VERSION = 0 # :nodoc:
-
- ##
- # Section comment
-
- attr_reader :comment
-
- ##
- # Section comments
-
- attr_reader :comments
-
- ##
- # Context this Section lives in
-
- attr_reader :parent
-
- ##
- # Section title
-
- attr_reader :title
-
- ##
- # Creates a new section with +title+ and +comment+
-
- def initialize parent, title, comment
- @parent = parent
- @title = title ? title.strip : title
-
- @comments = []
-
- add_comment comment
- end
-
- ##
- # Sections are equal when they have the same #title
-
- def == other
- self.class === other and @title == other.title
- end
-
- alias eql? ==
-
- ##
- # Adds +comment+ to this section
-
- def add_comment comment
- comment = extract_comment comment
-
- return if comment.empty?
-
- case comment
- when RDoc::Comment then
- @comments << comment
- when RDoc::Markup::Document then
- @comments.concat comment.parts
- when Array then
- @comments.concat comment
- else
- raise TypeError, "unknown comment type: #{comment.inspect}"
- end
- end
-
- ##
- # Anchor reference for linking to this section
-
- def aref
- title = @title || '[untitled]'
-
- CGI.escape(title).gsub('%', '-').sub(/^-/, '')
- end
-
- ##
- # Extracts the comment for this section from the original comment block.
- # If the first line contains :section:, strip it and use the rest.
- # Otherwise remove lines up to the line containing :section:, and look
- # for those lines again at the end and remove them. This lets us write
- #
- # # :section: The title
- # # The body
-
- def extract_comment comment
- case comment
- when Array then
- comment.map do |c|
- extract_comment c
- end
- when nil
- RDoc::Comment.new ''
- when RDoc::Comment then
- if comment.text =~ /^#[ \t]*:section:.*\n/ then
- start = $`
- rest = $'
-
- comment.text = if start.empty? then
- rest
- else
- rest.sub(/#{start.chomp}\Z/, '')
- end
- end
-
- comment
- when RDoc::Markup::Document then
- comment
- else
- raise TypeError, "unknown comment #{comment.inspect}"
- end
- end
-
- def inspect # :nodoc:
- "#<%s:0x%x %p>" % [self.class, object_id, title]
- end
-
- def hash # :nodoc:
- @title.hash
- end
-
- ##
- # The files comments in this section come from
-
- def in_files
- return [] if @comments.empty?
-
- case @comments
- when Array then
- @comments.map do |comment|
- comment.file
- end
- when RDoc::Markup::Document then
- @comment.parts.map do |document|
- document.file
- end
- else
- raise RDoc::Error, "BUG: unknown comment class #{@comments.class}"
- end
- end
-
- ##
- # Serializes this Section. The title and parsed comment are saved, but not
- # the section parent which must be restored manually.
-
- def marshal_dump
- [
- MARSHAL_VERSION,
- @title,
- parse,
- ]
- end
-
- ##
- # De-serializes this Section. The section parent must be restored manually.
-
- def marshal_load array
- @parent = nil
-
- @title = array[1]
- @comments = array[2]
- end
-
- ##
- # Parses +comment_location+ into an RDoc::Markup::Document composed of
- # multiple RDoc::Markup::Documents with their file set.
-
- def parse
- case @comments
- when String then
- super
- when Array then
- docs = @comments.map do |comment, location|
- doc = super comment
- doc.file = location if location
- doc
- end
-
- RDoc::Markup::Document.new(*docs)
- when RDoc::Comment then
- doc = super @comments.text, comments.format
- doc.file = @comments.location
- doc
- when RDoc::Markup::Document then
- return @comments
- else
- raise ArgumentError, "unknown comment class #{comments.class}"
- end
- end
-
- ##
- # The section's title, or 'Top Section' if the title is nil.
- #
- # This is used by the table of contents template so the name is silly.
-
- def plain_html
- @title || 'Top Section'
- end
-
- ##
- # Removes a comment from this section if it is from the same file as
- # +comment+
-
- def remove_comment comment
- return if @comments.empty?
-
- case @comments
- when Array then
- @comments.delete_if do |my_comment|
- my_comment.file == comment.file
- end
- when RDoc::Markup::Document then
- @comments.parts.delete_if do |document|
- document.file == comment.file.name
- end
- else
- raise RDoc::Error, "BUG: unknown comment class #{@comments.class}"
- end
- end
-
-end
diff --git a/lib/rdoc/cross_reference.rb b/lib/rdoc/cross_reference.rb
deleted file mode 100644
index 4e011219e8..0000000000
--- a/lib/rdoc/cross_reference.rb
+++ /dev/null
@@ -1,228 +0,0 @@
-# frozen_string_literal: true
-
-require_relative 'markup/attribute_manager' # for PROTECT_ATTR
-
-##
-# RDoc::CrossReference is a reusable way to create cross references for names.
-
-class RDoc::CrossReference
-
- ##
- # Regular expression to match class references
- #
- # 1. There can be a '\\' in front of text to suppress the cross-reference
- # 2. There can be a '::' in front of class names to reference from the
- # top-level namespace.
- # 3. The method can be followed by parenthesis (not recommended)
-
- CLASS_REGEXP_STR = '\\\\?((?:\:{2})?[A-Z]\w*(?:\:\:\w+)*)'
-
- ##
- # Regular expression to match a single method argument.
-
- METHOD_ARG_REGEXP_STR = '[\w.+*/=<>-]+'
-
- ##
- # Regular expression to match method arguments.
-
- METHOD_ARGS_REGEXP_STR = /(?:\((?:#{METHOD_ARG_REGEXP_STR}(?:,\s*#{METHOD_ARG_REGEXP_STR})*)?\))?/.source
-
- ##
- # Regular expression to match method references.
- #
- # See CLASS_REGEXP_STR
-
- METHOD_REGEXP_STR = /(
- (?!\d)[\w#{RDoc::Markup::AttributeManager::PROTECT_ATTR}]+[!?=]?|
- %|=(?:==?|~)|![=~]|\[\]=?|<(?:<|=>?)?|>[>=]?|[-+!]@?|\*\*?|[\/%\`|&^~]
- )#{METHOD_ARGS_REGEXP_STR}/.source.delete("\n ").freeze
-
- ##
- # Regular expressions matching text that should potentially have
- # cross-reference links generated are passed to add_regexp_handling. Note
- # that these expressions are meant to pick up text for which cross-references
- # have been suppressed, since the suppression characters are removed by the
- # code that is triggered.
-
- CROSSREF_REGEXP = /(?:^|[\s()])
- (
- (?:
- # A::B::C.meth
- #{CLASS_REGEXP_STR}(?:[.#]|::)#{METHOD_REGEXP_STR}
-
- # A::B::C
- # The stuff after CLASS_REGEXP_STR is a
- # nasty hack. CLASS_REGEXP_STR unfortunately matches
- # words like dog and cat (these are legal "class"
- # names in Fortran 95). When a word is flagged as a
- # potential cross-reference, limitations in the markup
- # engine suppress other processing, such as typesetting.
- # This is particularly noticeable for contractions.
- # In order that words like "can't" not
- # be flagged as potential cross-references, only
- # flag potential class cross-references if the character
- # after the cross-reference is a space, sentence
- # punctuation, tag start character, or attribute
- # marker.
- | #{CLASS_REGEXP_STR}(?=[@\s).?!,;<\000]|\z)
-
- # Stand-alone method (preceded by a #)
- | \\?\##{METHOD_REGEXP_STR}
-
- # Stand-alone method (preceded by ::)
- | ::#{METHOD_REGEXP_STR}
-
- # Things that look like filenames
- # The key thing is that there must be at least
- # one special character (period, slash, or
- # underscore).
- | (?:\.\.\/)*[-\/\w]+[_\/.][-\w\/.]+
-
- # Things that have markup suppressed
- # Don't process things like '\<' in \<tt>, though.
- # TODO: including < is a hack, not very satisfying.
- | \\[^\s<]
- )
-
- # labels for headings
- (?:@[\w+%-]+(?:\.[\w|%-]+)?)?
- )/x
-
- ##
- # Version of CROSSREF_REGEXP used when <tt>--hyperlink-all</tt> is specified.
-
- ALL_CROSSREF_REGEXP = /
- (?:^|[\s()])
- (
- (?:
- # A::B::C.meth
- #{CLASS_REGEXP_STR}(?:[.#]|::)#{METHOD_REGEXP_STR}
-
- # A::B::C
- | #{CLASS_REGEXP_STR}(?=[@\s).?!,;<\000]|\z)
-
- # Stand-alone method
- | \\?#{METHOD_REGEXP_STR}
-
- # Things that look like filenames
- | (?:\.\.\/)*[-\/\w]+[_\/.][-\w\/.]+
-
- # Things that have markup suppressed
- | \\[^\s<]
- )
-
- # labels for headings
- (?:@[\w+%-]+)?
- )/x
-
- ##
- # Hash of references that have been looked-up to their replacements
-
- attr_accessor :seen
-
- ##
- # Allows cross-references to be created based on the given +context+
- # (RDoc::Context).
-
- def initialize context
- @context = context
- @store = context.store
-
- @seen = {}
- end
-
- ##
- # Returns a method reference to +name+.
-
- def resolve_method name
- ref = nil
-
- if /#{CLASS_REGEXP_STR}([.#]|::)#{METHOD_REGEXP_STR}/o =~ name then
- type = $2
- if '.' == type # will find either #method or ::method
- method = $3
- else
- method = "#{type}#{$3}"
- end
- container = @context.find_symbol_module($1)
- elsif /^([.#]|::)#{METHOD_REGEXP_STR}/o =~ name then
- type = $1
- if '.' == type
- method = $2
- else
- method = "#{type}#{$2}"
- end
- container = @context
- else
- type = nil
- container = nil
- end
-
- if container then
- unless RDoc::TopLevel === container then
- if '.' == type then
- if 'new' == method then # AnyClassName.new will be class method
- ref = container.find_local_symbol method
- ref = container.find_ancestor_local_symbol method unless ref
- else
- ref = container.find_local_symbol "::#{method}"
- ref = container.find_ancestor_local_symbol "::#{method}" unless ref
- ref = container.find_local_symbol "##{method}" unless ref
- ref = container.find_ancestor_local_symbol "##{method}" unless ref
- end
- else
- ref = container.find_local_symbol method
- ref = container.find_ancestor_local_symbol method unless ref
- end
- end
- end
-
- ref
- end
-
- ##
- # Returns a reference to +name+.
- #
- # If the reference is found and +name+ is not documented +text+ will be
- # returned. If +name+ is escaped +name+ is returned. If +name+ is not
- # found +text+ is returned.
-
- def resolve name, text
- return @seen[name] if @seen.include? name
-
- ref = case name
- when /^\\(#{CLASS_REGEXP_STR})$/o then
- @context.find_symbol $1
- else
- @context.find_symbol name
- end
-
- ref = resolve_method name unless ref
-
- # Try a page name
- ref = @store.page name if not ref and name =~ /^[\w.]+$/
-
- ref = nil if RDoc::Alias === ref # external alias, can't link to it
-
- out = if name == '\\' then
- name
- elsif name =~ /^\\/ then
- # we remove the \ only in front of what we know:
- # other backslashes are treated later, only outside of <tt>
- ref ? $' : name
- elsif ref then
- if ref.display? then
- ref
- else
- text
- end
- else
- text
- end
-
- @seen[name] = out
-
- out
- end
-
-end
diff --git a/lib/rdoc/encoding.rb b/lib/rdoc/encoding.rb
deleted file mode 100644
index 67e190f782..0000000000
--- a/lib/rdoc/encoding.rb
+++ /dev/null
@@ -1,120 +0,0 @@
-# coding: US-ASCII
-# frozen_string_literal: true
-
-##
-# This class is a wrapper around File IO and Encoding that helps RDoc load
-# files and convert them to the correct encoding.
-
-module RDoc::Encoding
-
- HEADER_REGEXP = /^
- (?:
- \A\#!.*\n
- |
- ^\#\s+frozen[-_]string[-_]literal[=:].+\n
- |
- ^\#[^\n]+\b(?:en)?coding[=:]\s*(?<name>[^\s;]+).*\n
- |
- <\?xml[^?]*encoding=(?<quote>["'])(?<name>.*?)\k<quote>.*\n
- )+
- /xi # :nodoc:
-
- ##
- # Reads the contents of +filename+ and handles any encoding directives in
- # the file.
- #
- # The content will be converted to the +encoding+. If the file cannot be
- # converted a warning will be printed and nil will be returned.
- #
- # If +force_transcode+ is true the document will be transcoded and any
- # unknown character in the target encoding will be replaced with '?'
-
- def self.read_file filename, encoding, force_transcode = false
- content = File.open filename, "rb" do |f| f.read end
- content.gsub!("\r\n", "\n") if RUBY_PLATFORM =~ /mswin|mingw/
-
- utf8 = content.sub!(/\A\xef\xbb\xbf/, '')
-
- enc = RDoc::Encoding.detect_encoding content
- content = RDoc::Encoding.change_encoding content, enc if enc
-
- begin
- encoding ||= Encoding.default_external
- orig_encoding = content.encoding
-
- if not orig_encoding.ascii_compatible? then
- content = content.encode encoding
- elsif utf8 then
- content = RDoc::Encoding.change_encoding content, Encoding::UTF_8
- content = content.encode encoding
- else
- # assume the content is in our output encoding
- content = RDoc::Encoding.change_encoding content, encoding
- end
-
- unless content.valid_encoding? then
- # revert and try to transcode
- content = RDoc::Encoding.change_encoding content, orig_encoding
- content = content.encode encoding
- end
-
- unless content.valid_encoding? then
- warn "unable to convert #{filename} to #{encoding}, skipping"
- content = nil
- end
- rescue Encoding::InvalidByteSequenceError,
- Encoding::UndefinedConversionError => e
- if force_transcode then
- content = RDoc::Encoding.change_encoding content, orig_encoding
- content = content.encode(encoding,
- :invalid => :replace,
- :undef => :replace,
- :replace => '?')
- return content
- else
- warn "unable to convert #{e.message} for #{filename}, skipping"
- return nil
- end
- end
-
- content
- rescue ArgumentError => e
- raise unless e.message =~ /unknown encoding name - (.*)/
- warn "unknown encoding name \"#{$1}\" for #{filename}, skipping"
- nil
- rescue Errno::EISDIR, Errno::ENOENT
- nil
- end
-
- ##
- # Detects the encoding of +string+ based on the magic comment
-
- def self.detect_encoding string
- result = HEADER_REGEXP.match string
- name = result && result[:name]
-
- name ? Encoding.find(name) : nil
- end
-
- ##
- # Removes magic comments and shebang
-
- def self.remove_magic_comment string
- string.sub HEADER_REGEXP do |s|
- s.gsub(/[^\n]/, '')
- end
- end
-
- ##
- # Changes encoding based on +encoding+ without converting and returns new
- # string
-
- def self.change_encoding text, encoding
- if text.kind_of? RDoc::Comment
- text.encode! encoding
- else
- String.new text, encoding: encoding
- end
- end
-
-end
diff --git a/lib/rdoc/erb_partial.rb b/lib/rdoc/erb_partial.rb
deleted file mode 100644
index 043d763db1..0000000000
--- a/lib/rdoc/erb_partial.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-##
-# Allows an ERB template to be rendered in the context (binding) of an
-# existing ERB template evaluation.
-
-class RDoc::ERBPartial < ERB
-
- ##
- # Overrides +compiler+ startup to set the +eoutvar+ to an empty string only
- # if it isn't already set.
-
- def set_eoutvar compiler, eoutvar = '_erbout'
- super
-
- compiler.pre_cmd = ["#{eoutvar} ||= +''"]
- end
-
-end
diff --git a/lib/rdoc/erbio.rb b/lib/rdoc/erbio.rb
deleted file mode 100644
index 0f98eaedee..0000000000
--- a/lib/rdoc/erbio.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-require 'erb'
-
-##
-# A subclass of ERB that writes directly to an IO. Credit to Aaron Patterson
-# and Masatoshi SEKI.
-#
-# To use:
-#
-# erbio = RDoc::ERBIO.new '<%= "hello world" %>', nil, nil
-#
-# File.open 'hello.txt', 'w' do |io|
-# erbio.result binding
-# end
-#
-# Note that binding must enclose the io you wish to output on.
-
-class RDoc::ERBIO < ERB
-
- ##
- # Defaults +eoutvar+ to 'io', otherwise is identical to ERB's initialize
-
- def initialize str, trim_mode: nil, eoutvar: 'io'
- super(str, trim_mode: trim_mode, eoutvar: eoutvar)
- end
-
- ##
- # Instructs +compiler+ how to write to +io_variable+
-
- def set_eoutvar compiler, io_variable
- compiler.put_cmd = "#{io_variable}.write"
- compiler.insert_cmd = "#{io_variable}.write"
- compiler.pre_cmd = []
- compiler.post_cmd = []
- end
-
-end
diff --git a/lib/rdoc/extend.rb b/lib/rdoc/extend.rb
deleted file mode 100644
index 7d57433de6..0000000000
--- a/lib/rdoc/extend.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-##
-# A Module extension to a class with \#extend
-#
-# RDoc::Extend.new 'Enumerable', 'comment ...'
-
-class RDoc::Extend < RDoc::Mixin
-
-end
diff --git a/lib/rdoc/generator.rb b/lib/rdoc/generator.rb
deleted file mode 100644
index a769cf8ac0..0000000000
--- a/lib/rdoc/generator.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-# frozen_string_literal: true
-##
-# RDoc uses generators to turn parsed source code in the form of an
-# RDoc::CodeObject tree into some form of output. RDoc comes with the HTML
-# generator RDoc::Generator::Darkfish and an ri data generator
-# RDoc::Generator::RI.
-#
-# == Registering a Generator
-#
-# Generators are registered by calling RDoc::RDoc.add_generator with the class
-# of the generator:
-#
-# class My::Awesome::Generator
-# RDoc::RDoc.add_generator self
-# end
-#
-# == Adding Options to +rdoc+
-#
-# Before option processing in +rdoc+, RDoc::Options will call ::setup_options
-# on the generator class with an RDoc::Options instance. The generator can
-# use RDoc::Options#option_parser to add command-line options to the +rdoc+
-# tool. See RDoc::Options@Custom+Options for an example and see OptionParser
-# for details on how to add options.
-#
-# You can extend the RDoc::Options instance with additional accessors for your
-# generator.
-#
-# == Generator Instantiation
-#
-# After parsing, RDoc::RDoc will instantiate a generator by calling
-# #initialize with an RDoc::Store instance and an RDoc::Options instance.
-#
-# The RDoc::Store instance holds documentation for parsed source code. In
-# RDoc 3 and earlier the RDoc::TopLevel class held this data. When upgrading
-# a generator from RDoc 3 and earlier you should only need to replace
-# RDoc::TopLevel with the store instance.
-#
-# RDoc will then call #generate on the generator instance. You can use the
-# various methods on RDoc::Store and in the RDoc::CodeObject tree to create
-# your desired output format.
-
-module RDoc::Generator
-
- autoload :Markup, "#{__dir__}/generator/markup"
-
- autoload :Darkfish, "#{__dir__}/generator/darkfish"
- autoload :JsonIndex, "#{__dir__}/generator/json_index"
- autoload :RI, "#{__dir__}/generator/ri"
- autoload :POT, "#{__dir__}/generator/pot"
-
-end
diff --git a/lib/rdoc/generator/darkfish.rb b/lib/rdoc/generator/darkfish.rb
deleted file mode 100644
index 1b408a6f8e..0000000000
--- a/lib/rdoc/generator/darkfish.rb
+++ /dev/null
@@ -1,786 +0,0 @@
-# frozen_string_literal: true
-# -*- mode: ruby; ruby-indent-level: 2; tab-width: 2 -*-
-
-require 'erb'
-require 'fileutils'
-require 'pathname'
-require_relative 'markup'
-
-##
-# Darkfish RDoc HTML Generator
-#
-# $Id: darkfish.rb 52 2009-01-07 02:08:11Z deveiant $
-#
-# == Author/s
-# * Michael Granger (ged@FaerieMUD.org)
-#
-# == Contributors
-# * Mahlon E. Smith (mahlon@martini.nu)
-# * Eric Hodel (drbrain@segment7.net)
-#
-# == License
-#
-# Copyright (c) 2007, 2008, Michael Granger. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright notice,
-# this list of conditions and the following disclaimer.
-#
-# * Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# * Neither the name of the author/s, nor the names of the project's
-# contributors may be used to endorse or promote products derived from this
-# software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# == Attributions
-#
-# Darkfish uses the {Silk Icons}[http://www.famfamfam.com/lab/icons/silk/] set
-# by Mark James.
-
-class RDoc::Generator::Darkfish
-
- RDoc::RDoc.add_generator self
-
- include ERB::Util
-
- ##
- # Stylesheets, fonts, etc. that are included in RDoc.
-
- BUILTIN_STYLE_ITEMS = # :nodoc:
- %w[
- css/fonts.css
- fonts/Lato-Light.ttf
- fonts/Lato-LightItalic.ttf
- fonts/Lato-Regular.ttf
- fonts/Lato-RegularItalic.ttf
- fonts/SourceCodePro-Bold.ttf
- fonts/SourceCodePro-Regular.ttf
- css/rdoc.css
- ]
-
- ##
- # Path to this file's parent directory. Used to find templates and other
- # resources.
-
- GENERATOR_DIR = File.join 'rdoc', 'generator'
-
- ##
- # Release Version
-
- VERSION = '3'
-
- ##
- # Description of this generator
-
- DESCRIPTION = 'HTML generator, written by Michael Granger'
-
- ##
- # The relative path to style sheets and javascript. By default this is set
- # the same as the rel_prefix.
-
- attr_accessor :asset_rel_path
-
- ##
- # The path to generate files into, combined with <tt>--op</tt> from the
- # options for a full path.
-
- attr_reader :base_dir
-
- ##
- # Classes and modules to be used by this generator, not necessarily
- # displayed. See also #modsort
-
- attr_reader :classes
-
- ##
- # No files will be written when dry_run is true.
-
- attr_accessor :dry_run
-
- ##
- # When false the generate methods return a String instead of writing to a
- # file. The default is true.
-
- attr_accessor :file_output
-
- ##
- # Files to be displayed by this generator
-
- attr_reader :files
-
- ##
- # The JSON index generator for this Darkfish generator
-
- attr_reader :json_index
-
- ##
- # Methods to be displayed by this generator
-
- attr_reader :methods
-
- ##
- # Sorted list of classes and modules to be displayed by this generator
-
- attr_reader :modsort
-
- ##
- # The RDoc::Store that is the source of the generated content
-
- attr_reader :store
-
- ##
- # The directory where the template files live
-
- attr_reader :template_dir # :nodoc:
-
- ##
- # The output directory
-
- attr_reader :outputdir
-
- ##
- # Initialize a few instance variables before we start
-
- def initialize store, options
- @store = store
- @options = options
-
- @asset_rel_path = ''
- @base_dir = Pathname.pwd.expand_path
- @dry_run = @options.dry_run
- @file_output = true
- @template_dir = Pathname.new options.template_dir
- @template_cache = {}
-
- @classes = nil
- @context = nil
- @files = nil
- @methods = nil
- @modsort = nil
-
- @json_index = RDoc::Generator::JsonIndex.new self, options
- end
-
- ##
- # Output progress information if debugging is enabled
-
- def debug_msg *msg
- return unless $DEBUG_RDOC
- $stderr.puts(*msg)
- end
-
- ##
- # Directory where generated class HTML files live relative to the output
- # dir.
-
- def class_dir
- nil
- end
-
- ##
- # Directory where generated class HTML files live relative to the output
- # dir.
-
- def file_dir
- nil
- end
-
- ##
- # Create the directories the generated docs will live in if they don't
- # already exist.
-
- def gen_sub_directories
- @outputdir.mkpath
- end
-
- ##
- # Copy over the stylesheet into the appropriate place in the output
- # directory.
-
- def write_style_sheet
- debug_msg "Copying static files"
- options = { :verbose => $DEBUG_RDOC, :noop => @dry_run }
-
- BUILTIN_STYLE_ITEMS.each do |item|
- install_rdoc_static_file @template_dir + item, "./#{item}", options
- end
-
- unless @options.template_stylesheets.empty?
- FileUtils.cp @options.template_stylesheets, '.', **options
- end
-
- Dir[(@template_dir + "{js,images}/**/*").to_s].each do |path|
- next if File.directory? path
- next if File.basename(path) =~ /^\./
-
- dst = Pathname.new(path).relative_path_from @template_dir
-
- install_rdoc_static_file @template_dir + path, dst, options
- end
- end
-
- ##
- # Build the initial indices and output objects based on an array of TopLevel
- # objects containing the extracted information.
-
- def generate
- setup
-
- write_style_sheet
- generate_index
- generate_class_files
- generate_file_files
- generate_table_of_contents
- @json_index.generate
- @json_index.generate_gzipped
-
- copy_static
-
- rescue => e
- debug_msg "%s: %s\n %s" % [
- e.class.name, e.message, e.backtrace.join("\n ")
- ]
-
- raise
- end
-
- ##
- # Copies static files from the static_path into the output directory
-
- def copy_static
- return if @options.static_path.empty?
-
- fu_options = { :verbose => $DEBUG_RDOC, :noop => @dry_run }
-
- @options.static_path.each do |path|
- unless File.directory? path then
- FileUtils.install path, @outputdir, **fu_options.merge(:mode => 0644)
- next
- end
-
- Dir.chdir path do
- Dir[File.join('**', '*')].each do |entry|
- dest_file = @outputdir + entry
-
- if File.directory? entry then
- FileUtils.mkdir_p entry, **fu_options
- else
- FileUtils.install entry, dest_file, **fu_options.merge(:mode => 0644)
- end
- end
- end
- end
- end
-
- ##
- # Return a list of the documented modules sorted by salience first, then
- # by name.
-
- def get_sorted_module_list classes
- classes.select do |klass|
- klass.display?
- end.sort
- end
-
- ##
- # Generate an index page which lists all the classes which are documented.
-
- def generate_index
- setup
-
- template_file = @template_dir + 'index.rhtml'
- return unless template_file.exist?
-
- debug_msg "Rendering the index page..."
-
- out_file = @base_dir + @options.op_dir + 'index.html'
- rel_prefix = @outputdir.relative_path_from out_file.dirname
- search_index_rel_prefix = rel_prefix
- search_index_rel_prefix += @asset_rel_path if @file_output
-
- asset_rel_prefix = rel_prefix + @asset_rel_path
-
- @title = @options.title
-
- render_template template_file, out_file do |io|
- here = binding
- # suppress 1.9.3 warning
- here.local_variable_set(:asset_rel_prefix, asset_rel_prefix)
- here
- end
- rescue => e
- error = RDoc::Error.new \
- "error generating index.html: #{e.message} (#{e.class})"
- error.set_backtrace e.backtrace
-
- raise error
- end
-
- ##
- # Generates a class file for +klass+
-
- def generate_class klass, template_file = nil
- setup
-
- current = klass
-
- template_file ||= @template_dir + 'class.rhtml'
-
- debug_msg " working on %s (%s)" % [klass.full_name, klass.path]
- out_file = @outputdir + klass.path
- rel_prefix = @outputdir.relative_path_from out_file.dirname
- search_index_rel_prefix = rel_prefix
- search_index_rel_prefix += @asset_rel_path if @file_output
-
- asset_rel_prefix = rel_prefix + @asset_rel_path
- svninfo = get_svninfo(current)
-
- @title = "#{klass.type} #{klass.full_name} - #{@options.title}"
-
- debug_msg " rendering #{out_file}"
- render_template template_file, out_file do |io|
- here = binding
- # suppress 1.9.3 warning
- here.local_variable_set(:asset_rel_prefix, asset_rel_prefix)
- here.local_variable_set(:svninfo, svninfo)
- here
- end
- end
-
- ##
- # Generate a documentation file for each class and module
-
- def generate_class_files
- setup
-
- template_file = @template_dir + 'class.rhtml'
- template_file = @template_dir + 'classpage.rhtml' unless
- template_file.exist?
- return unless template_file.exist?
- debug_msg "Generating class documentation in #{@outputdir}"
-
- current = nil
-
- @classes.each do |klass|
- current = klass
-
- generate_class klass, template_file
- end
- rescue => e
- error = RDoc::Error.new \
- "error generating #{current.path}: #{e.message} (#{e.class})"
- error.set_backtrace e.backtrace
-
- raise error
- end
-
- ##
- # Generate a documentation file for each file
-
- def generate_file_files
- setup
-
- page_file = @template_dir + 'page.rhtml'
- fileinfo_file = @template_dir + 'fileinfo.rhtml'
-
- # for legacy templates
- filepage_file = @template_dir + 'filepage.rhtml' unless
- page_file.exist? or fileinfo_file.exist?
-
- return unless
- page_file.exist? or fileinfo_file.exist? or filepage_file.exist?
-
- debug_msg "Generating file documentation in #{@outputdir}"
-
- out_file = nil
- current = nil
-
- @files.each do |file|
- current = file
-
- if file.text? and page_file.exist? then
- generate_page file
- next
- end
-
- template_file = nil
- out_file = @outputdir + file.path
- debug_msg " working on %s (%s)" % [file.full_name, out_file]
- rel_prefix = @outputdir.relative_path_from out_file.dirname
- search_index_rel_prefix = rel_prefix
- search_index_rel_prefix += @asset_rel_path if @file_output
-
- asset_rel_prefix = rel_prefix + @asset_rel_path
-
- unless filepage_file then
- if file.text? then
- next unless page_file.exist?
- template_file = page_file
- @title = file.page_name
- else
- next unless fileinfo_file.exist?
- template_file = fileinfo_file
- @title = "File: #{file.base_name}"
- end
- end
-
- @title += " - #{@options.title}"
- template_file ||= filepage_file
-
- render_template template_file, out_file do |io|
- here = binding
- # suppress 1.9.3 warning
- here.local_variable_set(:asset_rel_prefix, asset_rel_prefix)
- here.local_variable_set(:current, current)
- here
- end
- end
- rescue => e
- error =
- RDoc::Error.new "error generating #{out_file}: #{e.message} (#{e.class})"
- error.set_backtrace e.backtrace
-
- raise error
- end
-
- ##
- # Generate a page file for +file+
-
- def generate_page file
- setup
-
- template_file = @template_dir + 'page.rhtml'
-
- out_file = @outputdir + file.path
- debug_msg " working on %s (%s)" % [file.full_name, out_file]
- rel_prefix = @outputdir.relative_path_from out_file.dirname
- search_index_rel_prefix = rel_prefix
- search_index_rel_prefix += @asset_rel_path if @file_output
-
- current = file
- asset_rel_prefix = rel_prefix + @asset_rel_path
-
- @title = "#{file.page_name} - #{@options.title}"
-
- debug_msg " rendering #{out_file}"
- render_template template_file, out_file do |io|
- here = binding
- # suppress 1.9.3 warning
- here.local_variable_set(:current, current)
- here.local_variable_set(:asset_rel_prefix, asset_rel_prefix)
- here
- end
- end
-
- ##
- # Generates the 404 page for the RDoc servlet
-
- def generate_servlet_not_found message
- setup
-
- template_file = @template_dir + 'servlet_not_found.rhtml'
- return unless template_file.exist?
-
- debug_msg "Rendering the servlet 404 Not Found page..."
-
- rel_prefix = rel_prefix = ''
- search_index_rel_prefix = rel_prefix
- search_index_rel_prefix += @asset_rel_path if @file_output
-
- asset_rel_prefix = ''
-
- @title = 'Not Found'
-
- render_template template_file do |io|
- here = binding
- # suppress 1.9.3 warning
- here.local_variable_set(:asset_rel_prefix, asset_rel_prefix)
- here
- end
- rescue => e
- error = RDoc::Error.new \
- "error generating servlet_not_found: #{e.message} (#{e.class})"
- error.set_backtrace e.backtrace
-
- raise error
- end
-
- ##
- # Generates the servlet root page for the RDoc servlet
-
- def generate_servlet_root installed
- setup
-
- template_file = @template_dir + 'servlet_root.rhtml'
- return unless template_file.exist?
-
- debug_msg 'Rendering the servlet root page...'
-
- rel_prefix = '.'
- asset_rel_prefix = rel_prefix
- search_index_rel_prefix = asset_rel_prefix
- search_index_rel_prefix += @asset_rel_path if @file_output
-
- @title = 'Local RDoc Documentation'
-
- render_template template_file do |io| binding end
- rescue => e
- error = RDoc::Error.new \
- "error generating servlet_root: #{e.message} (#{e.class})"
- error.set_backtrace e.backtrace
-
- raise error
- end
-
- ##
- # Generate an index page which lists all the classes which are documented.
-
- def generate_table_of_contents
- setup
-
- template_file = @template_dir + 'table_of_contents.rhtml'
- return unless template_file.exist?
-
- debug_msg "Rendering the Table of Contents..."
-
- out_file = @outputdir + 'table_of_contents.html'
- rel_prefix = @outputdir.relative_path_from out_file.dirname
- search_index_rel_prefix = rel_prefix
- search_index_rel_prefix += @asset_rel_path if @file_output
-
- asset_rel_prefix = rel_prefix + @asset_rel_path
-
- @title = "Table of Contents - #{@options.title}"
-
- render_template template_file, out_file do |io|
- here = binding
- # suppress 1.9.3 warning
- here.local_variable_set(:asset_rel_prefix, asset_rel_prefix)
- here
- end
- rescue => e
- error = RDoc::Error.new \
- "error generating table_of_contents.html: #{e.message} (#{e.class})"
- error.set_backtrace e.backtrace
-
- raise error
- end
-
- def install_rdoc_static_file source, destination, options # :nodoc:
- return unless source.exist?
-
- begin
- FileUtils.mkdir_p File.dirname(destination), **options
-
- begin
- FileUtils.ln source, destination, **options
- rescue Errno::EEXIST
- FileUtils.rm destination
- retry
- end
- rescue
- FileUtils.cp source, destination, **options
- end
- end
-
- ##
- # Prepares for generation of output from the current directory
-
- def setup
- return if instance_variable_defined? :@outputdir
-
- @outputdir = Pathname.new(@options.op_dir).expand_path @base_dir
-
- return unless @store
-
- @classes = @store.all_classes_and_modules.sort
- @files = @store.all_files.sort
- @methods = @classes.flat_map { |m| m.method_list }.sort
- @modsort = get_sorted_module_list @classes
- end
-
- ##
- # Return a string describing the amount of time in the given number of
- # seconds in terms a human can understand easily.
-
- def time_delta_string seconds
- return 'less than a minute' if seconds < 60
- return "#{seconds / 60} minute#{seconds / 60 == 1 ? '' : 's'}" if
- seconds < 3000 # 50 minutes
- return 'about one hour' if seconds < 5400 # 90 minutes
- return "#{seconds / 3600} hours" if seconds < 64800 # 18 hours
- return 'one day' if seconds < 86400 # 1 day
- return 'about one day' if seconds < 172800 # 2 days
- return "#{seconds / 86400} days" if seconds < 604800 # 1 week
- return 'about one week' if seconds < 1209600 # 2 week
- return "#{seconds / 604800} weeks" if seconds < 7257600 # 3 months
- return "#{seconds / 2419200} months" if seconds < 31536000 # 1 year
- return "#{seconds / 31536000} years"
- end
-
- # %q$Id: darkfish.rb 52 2009-01-07 02:08:11Z deveiant $"
- SVNID_PATTERN = /
- \$Id:\s
- (\S+)\s # filename
- (\d+)\s # rev
- (\d{4}-\d{2}-\d{2})\s # Date (YYYY-MM-DD)
- (\d{2}:\d{2}:\d{2}Z)\s # Time (HH:MM:SSZ)
- (\w+)\s # committer
- \$$
- /x
-
- ##
- # Try to extract Subversion information out of the first constant whose
- # value looks like a subversion Id tag. If no matching constant is found,
- # and empty hash is returned.
-
- def get_svninfo klass
- constants = klass.constants or return {}
-
- constants.find { |c| c.value =~ SVNID_PATTERN } or return {}
-
- filename, rev, date, time, committer = $~.captures
- commitdate = Time.parse "#{date} #{time}"
-
- return {
- :filename => filename,
- :rev => Integer(rev),
- :commitdate => commitdate,
- :commitdelta => time_delta_string(Time.now - commitdate),
- :committer => committer,
- }
- end
-
- ##
- # Creates a template from its components and the +body_file+.
- #
- # For backwards compatibility, if +body_file+ contains "<html" the body is
- # used directly.
-
- def assemble_template body_file
- body = body_file.read
- return body if body =~ /<html/
-
- head_file = @template_dir + '_head.rhtml'
- footer_file = @template_dir + '_footer.rhtml'
-
- <<-TEMPLATE
-<!DOCTYPE html>
-
-<html>
-<head>
-#{head_file.read}
-
-#{body}
-
-#{footer_file.read}
- TEMPLATE
- end
-
- ##
- # Renders the ERb contained in +file_name+ relative to the template
- # directory and returns the result based on the current context.
-
- def render file_name
- template_file = @template_dir + file_name
-
- template = template_for template_file, false, RDoc::ERBPartial
-
- template.filename = template_file.to_s
-
- template.result @context
- end
-
- ##
- # Load and render the erb template in the given +template_file+ and write
- # it out to +out_file+.
- #
- # Both +template_file+ and +out_file+ should be Pathname-like objects.
- #
- # An io will be yielded which must be captured by binding in the caller.
-
- def render_template template_file, out_file = nil # :yield: io
- io_output = out_file && !@dry_run && @file_output
- erb_klass = io_output ? RDoc::ERBIO : ERB
-
- template = template_for template_file, true, erb_klass
-
- if io_output then
- debug_msg "Outputting to %s" % [out_file.expand_path]
-
- out_file.dirname.mkpath
- out_file.open 'w', 0644 do |io|
- io.set_encoding @options.encoding
-
- @context = yield io
-
- template_result template, @context, template_file
- end
- else
- @context = yield nil
-
- output = template_result template, @context, template_file
-
- debug_msg " would have written %d characters to %s" % [
- output.length, out_file.expand_path
- ] if @dry_run
-
- output
- end
- end
-
- ##
- # Creates the result for +template+ with +context+. If an error is raised a
- # Pathname +template_file+ will indicate the file where the error occurred.
-
- def template_result template, context, template_file
- template.filename = template_file.to_s
- template.result context
- rescue NoMethodError => e
- raise RDoc::Error, "Error while evaluating %s: %s" % [
- template_file.expand_path,
- e.message,
- ], e.backtrace
- end
-
- ##
- # Retrieves a cache template for +file+, if present, or fills the cache.
-
- def template_for file, page = true, klass = ERB
- template = @template_cache[file]
-
- return template if template
-
- if page then
- template = assemble_template file
- erbout = 'io'
- else
- template = file.read
- template = template.encode @options.encoding
-
- file_var = File.basename(file).sub(/\..*/, '')
-
- erbout = "_erbout_#{file_var}"
- end
-
- template = klass.new template, trim_mode: '-', eoutvar: erbout
- @template_cache[file] = template
- template
- end
-
-end
diff --git a/lib/rdoc/generator/json_index.rb b/lib/rdoc/generator/json_index.rb
deleted file mode 100644
index c454910d5c..0000000000
--- a/lib/rdoc/generator/json_index.rb
+++ /dev/null
@@ -1,300 +0,0 @@
-# frozen_string_literal: true
-require 'json'
-begin
- require 'zlib'
-rescue LoadError
-end
-
-##
-# The JsonIndex generator is designed to complement an HTML generator and
-# produces a JSON search index. This generator is derived from sdoc by
-# Vladimir Kolesnikov and contains verbatim code written by him.
-#
-# This generator is designed to be used with a regular HTML generator:
-#
-# class RDoc::Generator::Darkfish
-# def initialize options
-# # ...
-# @base_dir = Pathname.pwd.expand_path
-#
-# @json_index = RDoc::Generator::JsonIndex.new self, options
-# end
-#
-# def generate
-# # ...
-# @json_index.generate
-# end
-# end
-#
-# == Index Format
-#
-# The index is output as a JSON file assigned to the global variable
-# +search_data+. The structure is:
-#
-# var search_data = {
-# "index": {
-# "searchIndex":
-# ["a", "b", ...],
-# "longSearchIndex":
-# ["a", "a::b", ...],
-# "info": [
-# ["A", "A", "A.html", "", ""],
-# ["B", "A::B", "A::B.html", "", ""],
-# ...
-# ]
-# }
-# }
-#
-# The same item is described across the +searchIndex+, +longSearchIndex+ and
-# +info+ fields. The +searchIndex+ field contains the item's short name, the
-# +longSearchIndex+ field contains the full_name (when appropriate) and the
-# +info+ field contains the item's name, full_name, path, parameters and a
-# snippet of the item's comment.
-#
-# == LICENSE
-#
-# Copyright (c) 2009 Vladimir Kolesnikov
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-class RDoc::Generator::JsonIndex
-
- include RDoc::Text
-
- ##
- # Where the search index lives in the generated output
-
- SEARCH_INDEX_FILE = File.join 'js', 'search_index.js'
-
- attr_reader :index # :nodoc:
-
- ##
- # Creates a new generator. +parent_generator+ is used to determine the
- # class_dir and file_dir of links in the output index.
- #
- # +options+ are the same options passed to the parent generator.
-
- def initialize parent_generator, options
- @parent_generator = parent_generator
- @store = parent_generator.store
- @options = options
-
- @template_dir = File.expand_path '../template/json_index', __FILE__
- @base_dir = @parent_generator.base_dir
-
- @classes = nil
- @files = nil
- @index = nil
- end
-
- ##
- # Builds the JSON index as a Hash.
-
- def build_index
- reset @store.all_files.sort, @store.all_classes_and_modules.sort
-
- index_classes
- index_methods
- index_pages
-
- { :index => @index }
- end
-
- ##
- # Output progress information if debugging is enabled
-
- def debug_msg *msg
- return unless $DEBUG_RDOC
- $stderr.puts(*msg)
- end
-
- ##
- # Writes the JSON index to disk
-
- def generate
- debug_msg "Generating JSON index"
-
- debug_msg " writing search index to %s" % SEARCH_INDEX_FILE
- data = build_index
-
- return if @options.dry_run
-
- out_dir = @base_dir + @options.op_dir
- index_file = out_dir + SEARCH_INDEX_FILE
-
- FileUtils.mkdir_p index_file.dirname, :verbose => $DEBUG_RDOC
-
- index_file.open 'w', 0644 do |io|
- io.set_encoding Encoding::UTF_8
- io.write 'var search_data = '
-
- JSON.dump data, io, 0
- end
- unless ENV['SOURCE_DATE_EPOCH'].nil?
- index_file.utime index_file.atime, Time.at(ENV['SOURCE_DATE_EPOCH'].to_i).gmtime
- end
-
- Dir.chdir @template_dir do
- Dir['**/*.js'].each do |source|
- dest = File.join out_dir, source
-
- FileUtils.install source, dest, :mode => 0644, :preserve => true, :verbose => $DEBUG_RDOC
- end
- end
- end
-
- ##
- # Compress the search_index.js file using gzip
-
- def generate_gzipped
- return if @options.dry_run or not defined?(Zlib)
-
- debug_msg "Compressing generated JSON index"
- out_dir = @base_dir + @options.op_dir
-
- search_index_file = out_dir + SEARCH_INDEX_FILE
- outfile = out_dir + "#{search_index_file}.gz"
-
- debug_msg "Reading the JSON index file from %s" % search_index_file
- search_index = search_index_file.read(mode: 'r:utf-8')
-
- debug_msg "Writing gzipped search index to %s" % outfile
-
- Zlib::GzipWriter.open(outfile) do |gz|
- gz.mtime = File.mtime(search_index_file)
- gz.orig_name = search_index_file.basename.to_s
- gz.write search_index
- gz.close
- end
-
- # GZip the rest of the js files
- Dir.chdir @template_dir do
- Dir['**/*.js'].each do |source|
- dest = out_dir + source
- outfile = out_dir + "#{dest}.gz"
-
- debug_msg "Reading the original js file from %s" % dest
- data = dest.read
-
- debug_msg "Writing gzipped file to %s" % outfile
-
- Zlib::GzipWriter.open(outfile) do |gz|
- gz.mtime = File.mtime(dest)
- gz.orig_name = dest.basename.to_s
- gz.write data
- gz.close
- end
- end
- end
- end
-
- ##
- # Adds classes and modules to the index
-
- def index_classes
- debug_msg " generating class search index"
-
- documented = @classes.uniq.select do |klass|
- klass.document_self_or_methods
- end
-
- documented.each do |klass|
- debug_msg " #{klass.full_name}"
- record = klass.search_record
- @index[:searchIndex] << search_string(record.shift)
- @index[:longSearchIndex] << search_string(record.shift)
- @index[:info] << record
- end
- end
-
- ##
- # Adds methods to the index
-
- def index_methods
- debug_msg " generating method search index"
-
- list = @classes.uniq.flat_map do |klass|
- klass.method_list
- end.sort_by do |method|
- [method.name, method.parent.full_name]
- end
-
- list.each do |method|
- debug_msg " #{method.full_name}"
- record = method.search_record
- @index[:searchIndex] << "#{search_string record.shift}()"
- @index[:longSearchIndex] << "#{search_string record.shift}()"
- @index[:info] << record
- end
- end
-
- ##
- # Adds pages to the index
-
- def index_pages
- debug_msg " generating pages search index"
-
- pages = @files.select do |file|
- file.text?
- end
-
- pages.each do |page|
- debug_msg " #{page.page_name}"
- record = page.search_record
- @index[:searchIndex] << search_string(record.shift)
- @index[:longSearchIndex] << ''
- record.shift
- @index[:info] << record
- end
- end
-
- ##
- # The directory classes are written to
-
- def class_dir
- @parent_generator.class_dir
- end
-
- ##
- # The directory files are written to
-
- def file_dir
- @parent_generator.file_dir
- end
-
- def reset files, classes # :nodoc:
- @files = files
- @classes = classes
-
- @index = {
- :searchIndex => [],
- :longSearchIndex => [],
- :info => []
- }
- end
-
- ##
- # Removes whitespace and downcases +string+
-
- def search_string string
- string.downcase.gsub(/\s/, '')
- end
-
-end
diff --git a/lib/rdoc/generator/markup.rb b/lib/rdoc/generator/markup.rb
deleted file mode 100644
index 76b7d458aa..0000000000
--- a/lib/rdoc/generator/markup.rb
+++ /dev/null
@@ -1,159 +0,0 @@
-# frozen_string_literal: true
-##
-# Handle common RDoc::Markup tasks for various CodeObjects
-#
-# This module is loaded by generators. It allows RDoc's CodeObject tree to
-# avoid loading generator code to improve startup time for +ri+.
-
-module RDoc::Generator::Markup
-
- ##
- # Generates a relative URL from this object's path to +target_path+
-
- def aref_to(target_path)
- RDoc::Markup::ToHtml.gen_relative_url path, target_path
- end
-
- ##
- # Generates a relative URL from +from_path+ to this object's path
-
- def as_href(from_path)
- RDoc::Markup::ToHtml.gen_relative_url from_path, path
- end
-
- ##
- # Handy wrapper for marking up this object's comment
-
- def description
- markup @comment
- end
-
- ##
- # Creates an RDoc::Markup::ToHtmlCrossref formatter
-
- def formatter
- return @formatter if defined? @formatter
-
- options = @store.rdoc.options
- this = RDoc::Context === self ? self : @parent
-
- @formatter = RDoc::Markup::ToHtmlCrossref.new options, this.path, this
- @formatter.code_object = self
- @formatter
- end
-
- ##
- # Build a webcvs URL starting for the given +url+ with +full_path+ appended
- # as the destination path. If +url+ contains '%s' +full_path+ will be
- # will replace the %s using sprintf on the +url+.
-
- def cvs_url(url, full_path)
- if /%s/ =~ url then
- sprintf url, full_path
- else
- url + full_path
- end
- end
-
-end
-
-class RDoc::CodeObject
-
- include RDoc::Generator::Markup
-
-end
-
-class RDoc::MethodAttr
-
- ##
- # Prepend +src+ with line numbers. Relies on the first line of a source
- # code listing having:
- #
- # # File xxxxx, line dddd
- #
- # If it has this comment then line numbers are added to +src+ and the <tt>,
- # line dddd</tt> portion of the comment is removed.
-
- def add_line_numbers(src)
- return unless src.sub!(/\A(.*)(, line (\d+))/, '\1')
- first = $3.to_i - 1
- last = first + src.count("\n")
- size = last.to_s.length
-
- line = first
- src.gsub!(/^/) do
- res = if line == first then
- " " * (size + 1)
- else
- "<span class=\"line-num\">%2$*1$d</span> " % [size, line]
- end
-
- line += 1
- res
- end
- end
-
- ##
- # Turns the method's token stream into HTML.
- #
- # Prepends line numbers if +options.line_numbers+ is true.
-
- def markup_code
- return '' unless @token_stream
-
- src = RDoc::TokenStream.to_html @token_stream
-
- # dedent the source
- indent = src.length
- lines = src.lines.to_a
- lines.shift if src =~ /\A.*#\ *File/i # remove '# File' comment
- lines.each do |line|
- if line =~ /^ *(?=\S)/
- n = $~.end(0)
- indent = n if n < indent
- break if n == 0
- end
- end
- src.gsub!(/^#{' ' * indent}/, '') if indent > 0
-
- add_line_numbers(src) if options.line_numbers
-
- src
- end
-
-end
-
-class RDoc::ClassModule
-
- ##
- # Handy wrapper for marking up this class or module's comment
-
- def description
- markup @comment_location
- end
-
-end
-
-class RDoc::Context::Section
-
- include RDoc::Generator::Markup
-
-end
-
-class RDoc::TopLevel
-
- ##
- # Returns a URL for this source file on some web repository. Use the -W
- # command line option to set.
-
- def cvs_url
- url = @store.rdoc.options.webcvs
-
- if /%s/ =~ url then
- url % @relative_name
- else
- url + @relative_name
- end
- end
-
-end
diff --git a/lib/rdoc/generator/pot.rb b/lib/rdoc/generator/pot.rb
deleted file mode 100644
index b0b7c07179..0000000000
--- a/lib/rdoc/generator/pot.rb
+++ /dev/null
@@ -1,99 +0,0 @@
-# frozen_string_literal: true
-##
-# Generates a POT file.
-#
-# Here is a translator work flow with the generator.
-#
-# == Create .pot
-#
-# You create .pot file by pot formatter:
-#
-# % rdoc --format pot
-#
-# It generates doc/rdoc.pot.
-#
-# == Create .po
-#
-# You create .po file from doc/rdoc.pot. This operation is needed only
-# the first time. This work flow assumes that you are a translator
-# for Japanese.
-#
-# You create locale/ja/rdoc.po from doc/rdoc.pot. You can use msginit
-# provided by GNU gettext or rmsginit provided by gettext gem. This
-# work flow uses gettext gem because it is more portable than GNU
-# gettext for Rubyists. Gettext gem is implemented by pure Ruby.
-#
-# % gem install gettext
-# % mkdir -p locale/ja
-# % rmsginit --input doc/rdoc.pot --output locale/ja/rdoc.po --locale ja
-#
-# Translate messages in .po
-#
-# You translate messages in .po by a PO file editor. po-mode.el exists
-# for Emacs users. There are some GUI tools such as GTranslator.
-# There are some Web services such as POEditor and Tansifex. You can
-# edit by your favorite text editor because .po is a text file.
-# Generate localized documentation
-#
-# You can generate localized documentation with locale/ja/rdoc.po:
-#
-# % rdoc --locale ja
-#
-# You can find documentation in Japanese in doc/. Yay!
-#
-# == Update translation
-#
-# You need to update translation when your application is added or
-# modified messages.
-#
-# You can update .po by the following command lines:
-#
-# % rdoc --format pot
-# % rmsgmerge --update locale/ja/rdoc.po doc/rdoc.pot
-#
-# You edit locale/ja/rdoc.po to translate new messages.
-
-class RDoc::Generator::POT
-
- RDoc::RDoc.add_generator self
-
- ##
- # Description of this generator
-
- DESCRIPTION = 'creates .pot file'
-
- ##
- # Set up a new .pot generator
-
- def initialize store, options #:not-new:
- @options = options
- @store = store
- end
-
- ##
- # Writes .pot to disk.
-
- def generate
- po = extract_messages
- pot_path = 'rdoc.pot'
- File.open(pot_path, "w") do |pot|
- pot.print(po.to_s)
- end
- end
-
- # :nodoc:
- def class_dir
- nil
- end
-
- private
- def extract_messages
- extractor = MessageExtractor.new(@store)
- extractor.extract
- end
-
- require_relative 'pot/message_extractor'
- require_relative 'pot/po'
- require_relative 'pot/po_entry'
-
-end
diff --git a/lib/rdoc/generator/pot/message_extractor.rb b/lib/rdoc/generator/pot/message_extractor.rb
deleted file mode 100644
index 313dfd2dc7..0000000000
--- a/lib/rdoc/generator/pot/message_extractor.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-# frozen_string_literal: true
-##
-# Extracts message from RDoc::Store
-
-class RDoc::Generator::POT::MessageExtractor
-
- ##
- # Creates a message extractor for +store+.
-
- def initialize store
- @store = store
- @po = RDoc::Generator::POT::PO.new
- end
-
- ##
- # Extracts messages from +store+, stores them into
- # RDoc::Generator::POT::PO and returns it.
-
- def extract
- @store.all_classes_and_modules.each do |klass|
- extract_from_klass(klass)
- end
- @po
- end
-
- private
-
- def extract_from_klass klass
- extract_text(klass.comment_location, klass.full_name)
-
- klass.each_section do |section, constants, attributes|
- extract_text(section.title ,"#{klass.full_name}: section title")
- section.comments.each do |comment|
- extract_text(comment, "#{klass.full_name}: #{section.title}")
- end
- end
-
- klass.each_constant do |constant|
- extract_text(constant.comment, constant.full_name)
- end
-
- klass.each_attribute do |attribute|
- extract_text(attribute.comment, attribute.full_name)
- end
-
- klass.each_method do |method|
- extract_text(method.comment, method.full_name)
- end
- end
-
- def extract_text text, comment, location = nil
- return if text.nil?
-
- options = {
- :extracted_comment => comment,
- :references => [location].compact,
- }
- i18n_text = RDoc::I18n::Text.new(text)
- i18n_text.extract_messages do |part|
- @po.add(entry(part[:paragraph], options))
- end
- end
-
- def entry msgid, options
- RDoc::Generator::POT::POEntry.new(msgid, options)
- end
-
-end
diff --git a/lib/rdoc/generator/pot/po.rb b/lib/rdoc/generator/pot/po.rb
deleted file mode 100644
index 37d45e5258..0000000000
--- a/lib/rdoc/generator/pot/po.rb
+++ /dev/null
@@ -1,84 +0,0 @@
-# frozen_string_literal: true
-##
-# Generates a PO format text
-
-class RDoc::Generator::POT::PO
-
- ##
- # Creates an object that represents PO format.
-
- def initialize
- @entries = {}
- add_header
- end
-
- ##
- # Adds a PO entry to the PO.
-
- def add entry
- existing_entry = @entries[entry.msgid]
- if existing_entry
- entry = existing_entry.merge(entry)
- end
- @entries[entry.msgid] = entry
- end
-
- ##
- # Returns PO format text for the PO.
-
- def to_s
- po = ''
- sort_entries.each do |entry|
- po += "\n" unless po.empty?
- po += entry.to_s
- end
- po
- end
-
- private
-
- def add_header
- add(header_entry)
- end
-
- def header_entry
- comment = <<-COMMENT
-SOME DESCRIPTIVE TITLE.
-Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
-This file is distributed under the same license as the PACKAGE package.
-FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
- COMMENT
-
- content = <<-CONTENT
-Project-Id-Version: PACKAGE VERSEION
-Report-Msgid-Bugs-To:
-PO-Revision-Date: YEAR-MO_DA HO:MI+ZONE
-Last-Translator: FULL NAME <EMAIL@ADDRESS>
-Language-Team: LANGUAGE <LL@li.org>
-Language:
-MIME-Version: 1.0
-Content-Type: text/plain; charset=CHARSET
-Content-Transfer-Encoding: 8bit
-Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;
- CONTENT
-
- options = {
- :msgstr => content,
- :translator_comment => comment,
- :flags => ['fuzzy'],
- }
- RDoc::Generator::POT::POEntry.new('', options)
- end
-
- def sort_entries
- headers, messages = @entries.values.partition do |entry|
- entry.msgid.empty?
- end
- # TODO: sort by location
- sorted_messages = messages.sort_by do |entry|
- entry.msgid
- end
- headers + sorted_messages
- end
-
-end
diff --git a/lib/rdoc/generator/pot/po_entry.rb b/lib/rdoc/generator/pot/po_entry.rb
deleted file mode 100644
index 3c278826f4..0000000000
--- a/lib/rdoc/generator/pot/po_entry.rb
+++ /dev/null
@@ -1,141 +0,0 @@
-# frozen_string_literal: true
-##
-# A PO entry in PO
-
-class RDoc::Generator::POT::POEntry
-
- # The msgid content
- attr_reader :msgid
-
- # The msgstr content
- attr_reader :msgstr
-
- # The comment content created by translator (PO editor)
- attr_reader :translator_comment
-
- # The comment content extracted from source file
- attr_reader :extracted_comment
-
- # The locations where the PO entry is extracted
- attr_reader :references
-
- # The flags of the PO entry
- attr_reader :flags
-
- ##
- # Creates a PO entry for +msgid+. Other valus can be specified by
- # +options+.
-
- def initialize msgid, options = {}
- @msgid = msgid
- @msgstr = options[:msgstr] || ""
- @translator_comment = options[:translator_comment]
- @extracted_comment = options[:extracted_comment]
- @references = options[:references] || []
- @flags = options[:flags] || []
- end
-
- ##
- # Returns the PO entry in PO format.
-
- def to_s
- entry = ''
- entry += format_translator_comment
- entry += format_extracted_comment
- entry += format_references
- entry += format_flags
- entry += <<-ENTRY
-msgid #{format_message(@msgid)}
-msgstr #{format_message(@msgstr)}
- ENTRY
- end
-
- ##
- # Merges the PO entry with +other_entry+.
-
- def merge other_entry
- options = {
- :extracted_comment => merge_string(@extracted_comment,
- other_entry.extracted_comment),
- :translator_comment => merge_string(@translator_comment,
- other_entry.translator_comment),
- :references => merge_array(@references,
- other_entry.references),
- :flags => merge_array(@flags,
- other_entry.flags),
- }
- self.class.new(@msgid, options)
- end
-
- private
-
- def format_comment mark, comment
- return '' unless comment
- return '' if comment.empty?
-
- formatted_comment = ''
- comment.each_line do |line|
- formatted_comment += "#{mark} #{line}"
- end
- formatted_comment += "\n" unless formatted_comment.end_with?("\n")
- formatted_comment
- end
-
- def format_translator_comment
- format_comment('#', @translator_comment)
- end
-
- def format_extracted_comment
- format_comment('#.', @extracted_comment)
- end
-
- def format_references
- return '' if @references.empty?
-
- formatted_references = ''
- @references.sort.each do |file, line|
- formatted_references += "\#: #{file}:#{line}\n"
- end
- formatted_references
- end
-
- def format_flags
- return '' if @flags.empty?
-
- formatted_flags = flags.join(",")
- "\#, #{formatted_flags}\n"
- end
-
- def format_message message
- return "\"#{escape(message)}\"" unless message.include?("\n")
-
- formatted_message = '""'
- message.each_line do |line|
- formatted_message += "\n"
- formatted_message += "\"#{escape(line)}\""
- end
- formatted_message
- end
-
- def escape string
- string.gsub(/["\\\t\n]/) do |special_character|
- case special_character
- when "\t"
- "\\t"
- when "\n"
- "\\n"
- else
- "\\#{special_character}"
- end
- end
- end
-
- def merge_string string1, string2
- [string1, string2].compact.join("\n")
- end
-
- def merge_array array1, array2
- (array1 + array2).uniq
- end
-
-end
diff --git a/lib/rdoc/generator/ri.rb b/lib/rdoc/generator/ri.rb
deleted file mode 100644
index 1c2f018f97..0000000000
--- a/lib/rdoc/generator/ri.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-##
-# Generates ri data files
-
-class RDoc::Generator::RI
-
- RDoc::RDoc.add_generator self
-
- ##
- # Description of this generator
-
- DESCRIPTION = 'creates ri data files'
-
- ##
- # Set up a new ri generator
-
- def initialize store, options #:not-new:
- @options = options
- @store = store
- @store.path = '.'
- end
-
- ##
- # Writes the parsed data store to disk for use by ri.
-
- def generate
- @store.save
- end
-
-end
diff --git a/lib/rdoc/generator/template/darkfish/.document b/lib/rdoc/generator/template/darkfish/.document
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/rdoc/generator/template/darkfish/.document
+++ /dev/null
diff --git a/lib/rdoc/generator/template/darkfish/_footer.rhtml b/lib/rdoc/generator/template/darkfish/_footer.rhtml
deleted file mode 100644
index 9791b42901..0000000000
--- a/lib/rdoc/generator/template/darkfish/_footer.rhtml
+++ /dev/null
@@ -1,5 +0,0 @@
-<footer id="validator-badges" role="contentinfo">
- <p><a href="https://validator.w3.org/check/referer">Validate</a>
- <p>Generated by <a href="https://ruby.github.io/rdoc/">RDoc</a> <%= RDoc::VERSION %>.
- <p>Based on <a href="http://deveiate.org/projects/Darkfish-RDoc/">Darkfish</a> by <a href="http://deveiate.org">Michael Granger</a>.
-</footer>
diff --git a/lib/rdoc/generator/template/darkfish/_head.rhtml b/lib/rdoc/generator/template/darkfish/_head.rhtml
deleted file mode 100644
index d5aed3e9ef..0000000000
--- a/lib/rdoc/generator/template/darkfish/_head.rhtml
+++ /dev/null
@@ -1,20 +0,0 @@
-<meta charset="<%= @options.charset %>">
-
-<title><%= h @title %></title>
-
-<script type="text/javascript">
- var rdoc_rel_prefix = "<%= h asset_rel_prefix %>/";
- var index_rel_prefix = "<%= h rel_prefix %>/";
-</script>
-
-<script src="<%= h asset_rel_prefix %>/js/navigation.js" defer></script>
-<script src="<%= h asset_rel_prefix %>/js/search.js" defer></script>
-<script src="<%= h asset_rel_prefix %>/js/search_index.js" defer></script>
-<script src="<%= h asset_rel_prefix %>/js/searcher.js" defer></script>
-<script src="<%= h asset_rel_prefix %>/js/darkfish.js" defer></script>
-
-<link href="<%= h asset_rel_prefix %>/css/fonts.css" rel="stylesheet">
-<link href="<%= h asset_rel_prefix %>/css/rdoc.css" rel="stylesheet">
-<%- @options.template_stylesheets.each do |stylesheet| -%>
-<link href="<%= h asset_rel_prefix %>/<%= File.basename stylesheet %>" rel="stylesheet">
-<%- end -%>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml
deleted file mode 100644
index 22a12d9e95..0000000000
--- a/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml
+++ /dev/null
@@ -1,19 +0,0 @@
-<%- if !svninfo.empty? then %>
-<div id="file-svninfo-section" class="nav-section">
- <h3>VCS Info</h3>
-
- <div class="section-body">
- <dl class="svninfo">
- <dt>Rev
- <dd><%= svninfo[:rev] %>
-
- <dt>Last Checked In
- <dd><%= svninfo[:commitdate].strftime('%Y-%m-%d %H:%M:%S') %>
- (<%= svninfo[:commitdelta] %> ago)
-
- <dt>Checked in by
- <dd><%= svninfo[:committer] %>
- </dl>
- </div>
-</div>
-<%- end -%>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml
deleted file mode 100644
index d3d8da4017..0000000000
--- a/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml
+++ /dev/null
@@ -1,33 +0,0 @@
-<div id="classindex-section" class="nav-section">
- <h3>Class and Module Index</h3>
-
- <%-
- all_classes = @classes.group_by do |klass|
- klass.full_name[/\A[^:]++(?:::[^:]++(?=::))*+(?=::[^:]*+\z)/]
- end.delete_if do |_, klasses|
- !klasses.any?(&:display?)
- end
- link = proc do |index_klass, display = index_klass.display?|
- if display
- -%><code><a href="<%= rel_prefix %>/<%= index_klass.path %>"><%= index_klass.name %></a></code><%-
- else
- -%><code><%= index_klass.name %></code><%-
- end
- end
- if top = all_classes[nil]
- solo = top.one? {|klass| klass.display?}
- traverse = proc do |klasses| -%>
- <ul class="link-list">
- <%- klasses.each do |index_klass| -%>
- <%- if children = all_classes[index_klass.full_name] -%>
- <li><details<% if solo; solo = false %> open<% end %>><summary><% link.call(index_klass) %></summary>
- <%- traverse.call(children) -%>
- </ul></details>
- <%- elsif index_klass.display? -%>
- <li><% link.call(index_klass, true) %>
- <%- end -%>
- <%- end -%>
- <%- end -%>
- <%- traverse.call(top) -%>
- <%- end -%>
-</div>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml
deleted file mode 100644
index 7602076c96..0000000000
--- a/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml
+++ /dev/null
@@ -1,15 +0,0 @@
-<%- unless klass.extends.empty? then %>
-<div id="extends-section" class="nav-section">
- <h3>Extended With Modules</h3>
-
- <ul class="link-list">
- <%- klass.each_extend do |ext| -%>
- <%- unless String === ext.module then -%>
- <li><a class="extend" href="<%= klass.aref_to ext.module.path %>"><%= ext.module.full_name %></a>
- <%- else -%>
- <li><span class="extend"><%= ext.name %></span>
- <%- end -%>
- <%- end -%>
- </ul>
-</div>
-<%- end -%>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml
deleted file mode 100644
index 74869a4b51..0000000000
--- a/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml
+++ /dev/null
@@ -1,9 +0,0 @@
-<div id="file-list-section" class="nav-section">
- <h3>Defined In</h3>
-
- <ul>
-<%- klass.in_files.each do |tl| -%>
- <li><%= h tl.relative_name %>
-<%- end -%>
- </ul>
-</div>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml
deleted file mode 100644
index 5b600e5975..0000000000
--- a/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml
+++ /dev/null
@@ -1,15 +0,0 @@
-<%- unless klass.includes.empty? then %>
-<div id="includes-section" class="nav-section">
- <h3>Included Modules</h3>
-
- <ul class="link-list">
- <%- klass.each_include do |inc| -%>
- <%- unless String === inc.module then -%>
- <li><a class="include" href="<%= klass.aref_to inc.module.path %>"><%= inc.module.full_name %></a>
- <%- else -%>
- <li><span class="include"><%= inc.name %></span>
- <%- end -%>
- <%- end -%>
- </ul>
-</div>
-<%- end -%>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml
deleted file mode 100644
index faed7e0a94..0000000000
--- a/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml
+++ /dev/null
@@ -1,15 +0,0 @@
-<div id="home-section" class="nav-section">
- <h3>Documentation</h3>
-
- <ul>
- <%- installed.each do |name, href, exists, type, _| -%>
- <%- next if type == :extra -%>
- <li class="folder">
- <%- if exists then -%>
- <a href="<%= href %>"><%= h name %></a>
- <%- else -%>
- <%= h name %>
- <%- end -%>
- <%- end -%>
- </ul>
-</div>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml
deleted file mode 100644
index 5b4c295bed..0000000000
--- a/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml
+++ /dev/null
@@ -1,12 +0,0 @@
-<%- unless klass.method_list.empty? then %>
-<!-- Method Quickref -->
-<div id="method-list-section" class="nav-section">
- <h3>Methods</h3>
-
- <ul class="link-list" role="directory">
- <%- klass.each_method do |meth| -%>
- <li <%- if meth.calls_super %>class="calls-super" <%- end %>><a href="#<%= meth.aref %>"><%= meth.singleton ? '::' : '#' %><%= h meth.name -%></a>
- <%- end -%>
- </ul>
-</div>
-<%- end -%>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_navigation.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_navigation.rhtml
deleted file mode 100644
index d7f330840a..0000000000
--- a/lib/rdoc/generator/template/darkfish/_sidebar_navigation.rhtml
+++ /dev/null
@@ -1,11 +0,0 @@
-<div id="home-section" role="region" title="Quick navigation" class="nav-section">
- <h2>
- <a href="<%= rel_prefix %>/index.html" rel="home">Home</a>
- </h2>
-
- <div id="table-of-contents-navigation">
- <a href="<%= rel_prefix %>/table_of_contents.html#pages">Pages</a>
- <a href="<%= rel_prefix %>/table_of_contents.html#classes">Classes</a>
- <a href="<%= rel_prefix %>/table_of_contents.html#methods">Methods</a>
- </div>
-</div>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml
deleted file mode 100644
index 3f68f0c0dc..0000000000
--- a/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml
+++ /dev/null
@@ -1,32 +0,0 @@
-<%- simple_files = @files.select { |f| f.text? } %>
-<%- if defined?(current) -%>
- <%- dir = current.full_name[%r{\A[^/]+(?=/)}] || current.page_name -%>
-<%- end -%>
-<%- unless simple_files.empty? then -%>
-<div id="fileindex-section" class="nav-section">
- <h3>Pages</h3>
-
- <ul class="link-list">
- <%- simple_files.group_by do |f| -%>
- <%- f.full_name[%r{\A[^/]+(?=/)}] || f.page_name -%>
- <%- end.each do |n, files| -%>
- <%- f = files.shift -%>
- <%- if files.empty? -%>
- <li><a href="<%= rel_prefix %>/<%= h f.path %>"><%= h f.page_name %></a>
- <%- next -%>
- <%- end -%>
- <li><details<% if dir == n %> open<% end %>><summary><%
- if n == f.page_name
- %><a href="<%= rel_prefix %>/<%= h f.path %>"><%= h n %></a><%
- else
- %><%= h n %><% files.unshift(f)
- end %></summary>
- <ul class="link-list">
- <%- files.each do |f| -%>
- <li><a href="<%= rel_prefix %>/<%= h f.path %>"><%= h f.page_name %></a>
- <%- end -%>
- </ul></details>
- <%- end -%>
- </ul>
-</div>
-<%- end -%>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml
deleted file mode 100644
index 1420da3201..0000000000
--- a/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml
+++ /dev/null
@@ -1,11 +0,0 @@
-<%- if klass.type == 'class' then %>
-<div id="parent-class-section" class="nav-section">
- <h3>Parent</h3>
-
- <%- if klass.superclass and not String === klass.superclass then -%>
- <p class="link"><a href="<%= klass.aref_to klass.superclass.path %>"><%= klass.superclass.full_name %></a>
- <%- else -%>
- <p class="link"><%= klass.superclass %>
- <%- end -%>
-</div>
-<%- end -%>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml
deleted file mode 100644
index afc7f7b88d..0000000000
--- a/lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml
+++ /dev/null
@@ -1,14 +0,0 @@
-<div id="search-section" role="search" class="project-section initially-hidden">
- <form action="#" method="get" accept-charset="utf-8">
- <div id="search-field-wrapper">
- <input id="search-field" role="combobox" aria-label="Search"
- aria-autocomplete="list" aria-controls="search-results"
- type="text" name="search" placeholder="Search (/) for a class, method, ..." spellcheck="false"
- title="Type to search, Up and Down to navigate, Enter to load">
- </div>
-
- <ul id="search-results" aria-label="Search Results"
- aria-busy="false" aria-expanded="false"
- aria-atomic="false" class="initially-hidden"></ul>
- </form>
-</div>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml
deleted file mode 100644
index 6dcd2ae81f..0000000000
--- a/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml
+++ /dev/null
@@ -1,11 +0,0 @@
-<%- unless klass.sections.length == 1 then %>
-<div id="sections-section" class="nav-section">
- <h3>Sections</h3>
-
- <ul class="link-list" role="directory">
- <%- klass.sort_sections.each do |section| -%>
- <li><a href="#<%= section.aref %>"><%= h section.title %></a></li>
- <%- end -%>
- </ul>
-</div>
-<%- end -%>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml
deleted file mode 100644
index b1e047b5f7..0000000000
--- a/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml
+++ /dev/null
@@ -1,39 +0,0 @@
-<%- comment = if current.respond_to? :comment_location then
- current.comment_location
- else
- current.comment
- end
- table = current.parse(comment).table_of_contents.dup
-
- if table.length > 1 then %>
-<div class="nav-section">
- <h3>Table of Contents</h3>
-
- <%- display_link = proc do |heading| -%>
- <a href="#<%= heading.label current %>"><%= heading.plain_html %></a>
- <%- end -%>
-
- <%- list_siblings = proc do -%>
- <%- level = table.first&.level -%>
- <%- while table.first && table.first.level >= level -%>
- <%- heading = table.shift -%>
- <%- if table.first.nil? || table.first.level <= heading.level -%>
- <li><% display_link.call heading -%>
- <%- else -%>
- <li>
- <details open>
- <summary><%- display_link.call heading -%></summary>
- <ul class="link-list" role="directory">
- <% list_siblings.call %>
- </ul>
- </details>
- </li>
- <%- end -%>
- <%- end -%>
- <%- end -%>
-
- <ul class="link-list" role="directory">
- <% list_siblings.call %>
- </ul>
-</div>
-<%- end -%>
diff --git a/lib/rdoc/generator/template/darkfish/class.rhtml b/lib/rdoc/generator/template/darkfish/class.rhtml
deleted file mode 100644
index d6510336df..0000000000
--- a/lib/rdoc/generator/template/darkfish/class.rhtml
+++ /dev/null
@@ -1,180 +0,0 @@
-<body id="top" role="document" class="<%= klass.type %>">
-<nav role="navigation">
- <div id="project-navigation">
- <%= render '_sidebar_navigation.rhtml' %>
- <%= render '_sidebar_search.rhtml' %>
- </div>
-
- <%= render '_sidebar_table_of_contents.rhtml' %>
-
- <div id="class-metadata">
- <%= render '_sidebar_sections.rhtml' %>
- <%= render '_sidebar_parent.rhtml' %>
- <%= render '_sidebar_includes.rhtml' %>
- <%= render '_sidebar_extends.rhtml' %>
- <%= render '_sidebar_methods.rhtml' %>
- </div>
-</nav>
-
-<main role="main" aria-labelledby="<%=h klass.aref %>">
- <h1 id="<%=h klass.aref %>" class="<%= klass.type %>">
- <%= klass.type %> <%= klass.full_name %>
- </h1>
-
- <section class="description">
- <%= klass.description %>
- </section>
-
- <%- klass.each_section do |section, constants, attributes| -%>
- <section id="<%= section.aref %>" class="documentation-section">
- <%- if section.title then -%>
- <header class="documentation-section-title">
- <h2>
- <%= section.title %>
- </h2>
- <span class="section-click-top">
- <a href="#top">&uarr; top</a>
- </span>
- </header>
- <%- end -%>
-
- <%- if section.comment then -%>
- <div>
- <%= section.description %>
- </div>
- <%- end -%>
-
- <%- unless constants.empty? then -%>
- <section class="constants-list">
- <header>
- <h3>Constants</h3>
- </header>
- <dl>
- <%- constants.each do |const| -%>
- <dt id="<%= const.name %>"><%= const.name %>
- <%- if const.comment then -%>
- <dd><%= const.description.strip %>
- <%- else -%>
- <dd class="missing-docs">(Not documented)
- <%- end -%>
- <%- end -%>
- </dl>
- </section>
- <%- end -%>
-
- <%- unless attributes.empty? then -%>
- <section class="attribute-method-details" class="method-section">
- <header>
- <h3>Attributes</h3>
- </header>
-
- <%- attributes.each do |attrib| -%>
- <div id="<%= attrib.aref %>" class="method-detail">
- <div class="method-heading attribute-method-heading">
- <span class="method-name"><%= h attrib.name %></span><span
- class="attribute-access-type">[<%= attrib.rw %>]</span>
- </div>
-
- <div class="method-description">
- <%- if attrib.comment then -%>
- <%= attrib.description.strip %>
- <%- else -%>
- <p class="missing-docs">(Not documented)
- <%- end -%>
- </div>
- </div>
- <%- end -%>
- </section>
- <%- end -%>
-
- <%- klass.methods_by_type(section).each do |type, visibilities|
- next if visibilities.empty?
- visibilities.each do |visibility, methods|
- next if methods.empty? %>
- <section id="<%= visibility %>-<%= type %>-<%= section.aref %>-method-details" class="method-section">
- <header>
- <h3><%= visibility.to_s.capitalize %> <%= type.capitalize %> Methods</h3>
- </header>
-
- <%- methods.each do |method| -%>
- <div id="<%= method.aref %>" class="method-detail <%= method.is_alias_for ? "method-alias" : '' %>">
- <div class="method-header">
- <%- if (call_seq = method.call_seq) then -%>
- <%- call_seq.strip.split("\n").each_with_index do |call_seq, i| -%>
- <div class="method-heading">
- <span class="method-callseq">
- <%= h(call_seq.strip.
- gsub( /^\w+\./m, '')).
- gsub(/(.*)[-=]&gt;/, '\1&rarr;') %>
- </span>
- <%- if i == 0 and method.token_stream then -%>
- <span class="method-click-advice">click to toggle source</span>
- <%- end -%>
- </div>
- <%- end -%>
- <%- elsif method.has_call_seq? then -%>
- <div class="method-heading">
- <span class="method-name"><%= h method.name %></span>
- </div>
- <%- else -%>
- <div class="method-heading">
- <span class="method-name"><%= h method.name %></span><span
- class="method-args"><%= h method.param_seq %></span>
- <%- if method.token_stream then -%>
- <span class="method-click-advice">click to toggle source</span>
- <%- end -%>
- </div>
- <%- end -%>
- </div>
-
- <%- unless method.skip_description? then -%>
- <div class="method-description">
- <%- if method.comment then -%>
- <%= method.description.strip %>
- <%- else -%>
- <p class="missing-docs">(Not documented)
- <%- end -%>
- <%- if method.calls_super then -%>
- <div class="method-calls-super">
- Calls superclass method
- <%=
- method.superclass_method ?
- method.formatter.link(method.superclass_method.full_name, method.superclass_method.full_name) : nil
- %>
- </div>
- <%- end -%>
-
- <%- if method.token_stream then -%>
- <div class="method-source-code" id="<%= method.html_name %>-source">
- <pre><%= method.markup_code %></pre>
- </div>
- <%- end -%>
- </div>
- <%- end -%>
-
- <%- unless method.aliases.empty? then -%>
- <div class="aliases">
- Also aliased as: <%= method.aliases.map do |aka|
- if aka.parent then # HACK lib/rexml/encodings
- %{<a href="#{klass.aref_to aka.path}">#{h aka.name}</a>}
- else
- h aka.name
- end
- end.join ", " %>
- </div>
- <%- end -%>
-
- <%- if method.is_alias_for then -%>
- <div class="aliases">
- Alias for: <a href="<%= klass.aref_to method.is_alias_for.path %>"><%= h method.is_alias_for.name %></a>
- </div>
- <%- end -%>
- </div>
-
- <%- end -%>
- </section>
- <%- end
- end %>
- </section>
-<%- end -%>
-</main>
diff --git a/lib/rdoc/generator/template/darkfish/css/fonts.css b/lib/rdoc/generator/template/darkfish/css/fonts.css
deleted file mode 100644
index 57302b5183..0000000000
--- a/lib/rdoc/generator/template/darkfish/css/fonts.css
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/),
- * with Reserved Font Name "Source". All Rights Reserved. Source is a
- * trademark of Adobe Systems Incorporated in the United States and/or other
- * countries.
- *
- * This Font Software is licensed under the SIL Open Font License, Version
- * 1.1.
- *
- * This license is copied below, and is also available with a FAQ at:
- * http://scripts.sil.org/OFL
- */
-
-@font-face {
- font-family: "Source Code Pro";
- font-style: normal;
- font-weight: 400;
- src: local("Source Code Pro"),
- local("SourceCodePro-Regular"),
- url("../fonts/SourceCodePro-Regular.ttf") format("truetype");
-}
-
-@font-face {
- font-family: "Source Code Pro";
- font-style: normal;
- font-weight: 700;
- src: local("Source Code Pro Bold"),
- local("SourceCodePro-Bold"),
- url("../fonts/SourceCodePro-Bold.ttf") format("truetype");
-}
-
-/*
- * Copyright (c) 2010, Łukasz Dziedzic (dziedzic@typoland.com),
- * with Reserved Font Name Lato.
- *
- * This Font Software is licensed under the SIL Open Font License, Version
- * 1.1.
- *
- * This license is copied below, and is also available with a FAQ at:
- * http://scripts.sil.org/OFL
- */
-
-@font-face {
- font-family: "Lato";
- font-style: normal;
- font-weight: 300;
- src: local("Lato Light"),
- local("Lato-Light"),
- url("../fonts/Lato-Light.ttf") format("truetype");
-}
-
-@font-face {
- font-family: "Lato";
- font-style: italic;
- font-weight: 300;
- src: local("Lato Light Italic"),
- local("Lato-LightItalic"),
- url("../fonts/Lato-LightItalic.ttf") format("truetype");
-}
-
-@font-face {
- font-family: "Lato";
- font-style: normal;
- font-weight: 700;
- src: local("Lato Regular"),
- local("Lato-Regular"),
- url("../fonts/Lato-Regular.ttf") format("truetype");
-}
-
-@font-face {
- font-family: "Lato";
- font-style: italic;
- font-weight: 700;
- src: local("Lato Italic"),
- local("Lato-Italic"),
- url("../fonts/Lato-RegularItalic.ttf") format("truetype");
-}
-
-/*
- * -----------------------------------------------------------
- * SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
- * -----------------------------------------------------------
- *
- * PREAMBLE
- * The goals of the Open Font License (OFL) are to stimulate worldwide
- * development of collaborative font projects, to support the font creation
- * efforts of academic and linguistic communities, and to provide a free and
- * open framework in which fonts may be shared and improved in partnership
- * with others.
- *
- * The OFL allows the licensed fonts to be used, studied, modified and
- * redistributed freely as long as they are not sold by themselves. The
- * fonts, including any derivative works, can be bundled, embedded,
- * redistributed and/or sold with any software provided that any reserved
- * names are not used by derivative works. The fonts and derivatives,
- * however, cannot be released under any other type of license. The
- * requirement for fonts to remain under this license does not apply
- * to any document created using the fonts or their derivatives.
- *
- * DEFINITIONS
- * "Font Software" refers to the set of files released by the Copyright
- * Holder(s) under this license and clearly marked as such. This may
- * include source files, build scripts and documentation.
- *
- * "Reserved Font Name" refers to any names specified as such after the
- * copyright statement(s).
- *
- * "Original Version" refers to the collection of Font Software components as
- * distributed by the Copyright Holder(s).
- *
- * "Modified Version" refers to any derivative made by adding to, deleting,
- * or substituting -- in part or in whole -- any of the components of the
- * Original Version, by changing formats or by porting the Font Software to a
- * new environment.
- *
- * "Author" refers to any designer, engineer, programmer, technical
- * writer or other person who contributed to the Font Software.
- *
- * PERMISSION & CONDITIONS
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of the Font Software, to use, study, copy, merge, embed, modify,
- * redistribute, and sell modified and unmodified copies of the Font
- * Software, subject to the following conditions:
- *
- * 1) Neither the Font Software nor any of its individual components,
- * in Original or Modified Versions, may be sold by itself.
- *
- * 2) Original or Modified Versions of the Font Software may be bundled,
- * redistributed and/or sold with any software, provided that each copy
- * contains the above copyright notice and this license. These can be
- * included either as stand-alone text files, human-readable headers or
- * in the appropriate machine-readable metadata fields within text or
- * binary files as long as those fields can be easily viewed by the user.
- *
- * 3) No Modified Version of the Font Software may use the Reserved Font
- * Name(s) unless explicit written permission is granted by the corresponding
- * Copyright Holder. This restriction only applies to the primary font name as
- * presented to the users.
- *
- * 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
- * Software shall not be used to promote, endorse or advertise any
- * Modified Version, except to acknowledge the contribution(s) of the
- * Copyright Holder(s) and the Author(s) or with their explicit written
- * permission.
- *
- * 5) The Font Software, modified or unmodified, in part or in whole,
- * must be distributed entirely under this license, and must not be
- * distributed under any other license. The requirement for fonts to
- * remain under this license does not apply to any document created
- * using the Font Software.
- *
- * TERMINATION
- * This license becomes null and void if any of the above conditions are
- * not met.
- *
- * DISCLAIMER
- * THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
- * OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
- * COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
- * DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
- * OTHER DEALINGS IN THE FONT SOFTWARE.
- */
-
diff --git a/lib/rdoc/generator/template/darkfish/css/rdoc.css b/lib/rdoc/generator/template/darkfish/css/rdoc.css
deleted file mode 100644
index 2cc55e03b1..0000000000
--- a/lib/rdoc/generator/template/darkfish/css/rdoc.css
+++ /dev/null
@@ -1,687 +0,0 @@
-/*
- * "Darkfish" Rdoc CSS
- * $Id: rdoc.css 54 2009-01-27 01:09:48Z deveiant $
- *
- * Author: Michael Granger <ged@FaerieMUD.org>
- *
- */
-
-/* vim: ft=css et sw=2 ts=2 sts=2 */
-/* Base Green is: #6C8C22 */
-
-.hide { display: none !important; }
-
-* { padding: 0; margin: 0; }
-
-body {
- background: #fafafa;
- font-family: Lato, sans-serif;
- font-weight: 300;
-
- /* Layout */
- display: grid;
- grid-template-columns: auto 1fr;
-}
-
-body > :last-child {
- grid-column: 1 / 3;
-}
-
-h1 span,
-h2 span,
-h3 span,
-h4 span,
-h5 span,
-h6 span {
- position: relative;
-
- display: none;
- padding-left: 1em;
- line-height: 0;
- vertical-align: baseline;
- font-size: 10px;
-}
-
-h1 span { top: -1.3em; }
-h2 span { top: -1.2em; }
-h3 span { top: -1.0em; }
-h4 span { top: -0.8em; }
-h5 span { top: -0.5em; }
-h6 span { top: -0.5em; }
-
-h1:hover span,
-h2:hover span,
-h3:hover span,
-h4:hover span,
-h5:hover span,
-h6:hover span {
- display: inline;
-}
-
-h1:target,
-h2:target,
-h3:target,
-h4:target,
-h5:target,
-h6:target {
- margin-left: -10px;
- border-left: 10px solid #f1edba;
-}
-
-:link,
-:visited {
- color: #6C8C22;
- text-decoration: none;
-}
-
-:link:hover,
-:visited:hover {
- border-bottom: 1px dotted #6C8C22;
-}
-
-code,
-pre {
- font-family: "Source Code Pro", Monaco, monospace;
- background-color: rgba(27,31,35,0.05);
- padding: 0em 0.2em;
- border-radius: 0.2em;
-}
-
-em {
- text-decoration-color: rgba(52, 48, 64, 0.25);
- text-decoration-line: underline;
- text-decoration-style: dotted;
-}
-
-strong,
-em {
- background-color: rgba(158, 178, 255, 0.1);
-}
-
-table {
- margin: 0;
- border-spacing: 0;
- border-collapse: collapse;
-}
-
-table tr th, table tr td {
- padding: 0.2em 0.4em;
- border: 1px solid #ccc;
-}
-
-table tr th {
- background-color: #eceaed;
-}
-
-table tr:nth-child(even) td {
- background-color: #f5f4f6;
-}
-
-/* @group Generic Classes */
-
-.initially-hidden {
- display: none;
-}
-
-#search-field {
- width: 98%;
- background: white;
- border: none;
- height: 1.5em;
- -webkit-border-radius: 4px;
- -moz-border-radius: 4px;
- border-radius: 4px;
- text-align: left;
-}
-#search-field:focus {
- background: #f1edba;
-}
-#search-field:-moz-placeholder,
-#search-field::-webkit-input-placeholder {
- font-weight: bold;
- color: #666;
-}
-
-.missing-docs {
- font-size: 120%;
- background: white url(../images/wrench_orange.png) no-repeat 4px center;
- color: #ccc;
- line-height: 2em;
- border: 1px solid #d00;
- opacity: 1;
- padding-left: 20px;
- text-indent: 24px;
- letter-spacing: 3px;
- font-weight: bold;
- -webkit-border-radius: 5px;
- -moz-border-radius: 5px;
-}
-
-.target-section {
- border: 2px solid #dcce90;
- border-left-width: 8px;
- padding: 0 1em;
- background: #fff3c2;
-}
-
-/* @end */
-
-/* @group Index Page, Standalone file pages */
-.table-of-contents ul {
- margin: 1em;
- list-style: none;
-}
-
-.table-of-contents ul ul {
- margin-top: 0.25em;
-}
-
-.table-of-contents ul :link,
-.table-of-contents ul :visited {
- font-size: 16px;
-}
-
-.table-of-contents li {
- margin-bottom: 0.25em;
-}
-
-.table-of-contents li .toc-toggle {
- width: 16px;
- height: 16px;
- background: url(../images/add.png) no-repeat;
-}
-
-.table-of-contents li .toc-toggle.open {
- background: url(../images/delete.png) no-repeat;
-}
-
-/* @end */
-
-/* @group Top-Level Structure */
-
-nav {
- font-family: Helvetica, sans-serif;
- font-size: 14px;
- border-right: 1px solid #ccc;
- position: sticky;
- top: 0;
- overflow: auto;
-
- /* Layout */
- width: 260px; /* fallback */
- width: max(50px, 20vw);
- min-width: 50px;
- max-width: 80vw;
- height: calc(100vh - 100px); /* reduce the footer height */
- resize: horizontal;
-}
-
-main {
- display: block;
- margin: 1em;
- min-width: 340px;
- font-size: 16px;
-}
-
-main h1,
-main h2,
-main h3,
-main h4,
-main h5,
-main h6 {
- font-family: Helvetica, sans-serif;
-}
-
-.table-of-contents main {
- margin-left: 2em;
-}
-
-#validator-badges {
- margin: 1em 1em 2em;
- font-size: smaller;
-}
-
-/* @end */
-
-/* @group navigation */
-nav {
- margin-bottom: 1em;
-}
-
-nav .nav-section {
- margin-top: 2em;
- border-top: 2px solid #aaa;
- font-size: 90%;
- overflow: hidden;
-}
-
-nav h2 {
- margin: 0;
- padding: 2px 8px 2px 8px;
- background-color: #e8e8e8;
- color: #555;
- font-size: 125%;
- text-align: center;
-}
-
-nav h3,
-#table-of-contents-navigation {
- margin: 0;
- padding: 2px 8px 2px 8px;
- text-align: right;
- background-color: #e8e8e8;
- color: #555;
-}
-
-nav ul,
-nav dl,
-nav p {
- padding: 4px 8px 0;
- list-style: none;
-}
-
-#project-navigation .nav-section {
- margin: 0;
- border-top: 0;
-}
-
-#home-section h2 {
- text-align: center;
-}
-
-#table-of-contents-navigation {
- font-size: 1.2em;
- font-weight: bold;
- text-align: center;
-}
-
-#search-section {
- margin-top: 0;
- border-top: 0;
-}
-
-#search-field-wrapper {
- border-top: 1px solid #aaa;
- border-bottom: 1px solid #aaa;
- padding: 3px 8px;
- background-color: #e8e8e8;
- color: #555;
-}
-
-ul.link-list li {
- white-space: nowrap;
- line-height: 1.4em;
-}
-
-ul.link-list .type {
- font-size: 8px;
- text-transform: uppercase;
- color: white;
- background: #969696;
- padding: 2px 4px;
- -webkit-border-radius: 5px;
-}
-
-dl.note-list dt {
- float: left;
- margin-right: 1em;
-}
-
-.calls-super {
- background: url(../images/arrow_up.png) no-repeat right center;
-}
-
-.nav-section details > summary {
- display: block;
-}
-
-.nav-section details > summary::-webkit-details-marker {
- display: none;
-}
-
-.nav-section details > summary::before {
- content: "";
-}
-
-.nav-section details > summary::after {
- content: "\25B6"; /* BLACK RIGHT-POINTING TRIANGLE */
- font-size: 0.8em;
- margin-left: 0.4em;
-}
-
-.nav-section details[open] > summary::after {
- content: "\25BD"; /* WHITE DOWN-POINTING TRIANGLE */
-}
-
-/* @end */
-
-/* @group Documentation Section */
-main {
- color: #333;
-}
-
-main > h1:first-child,
-main > h2:first-child,
-main > h3:first-child,
-main > h4:first-child,
-main > h5:first-child,
-main > h6:first-child {
- margin-top: 0px;
-}
-
-main sup {
- vertical-align: super;
- font-size: 0.8em;
-}
-
-/* The heading with the class name */
-main h1[class] {
- margin-top: 0;
- margin-bottom: 1em;
- font-size: 2em;
- color: #6C8C22;
-}
-
-main h1 {
- margin: 2em 0 0.5em;
- font-size: 1.7em;
-}
-
-main h2 {
- margin: 2em 0 0.5em;
- font-size: 1.5em;
-}
-
-main h3 {
- margin: 2em 0 0.5em;
- font-size: 1.2em;
-}
-
-main h4 {
- margin: 2em 0 0.5em;
- font-size: 1.1em;
-}
-
-main h5 {
- margin: 2em 0 0.5em;
- font-size: 1em;
-}
-
-main h6 {
- margin: 2em 0 0.5em;
- font-size: 1em;
-}
-
-main p {
- margin: 0 0 0.5em;
- line-height: 1.4em;
-}
-
-main pre {
- margin: 1.2em 0.5em;
- padding: 1em;
- font-size: 0.8em;
-}
-
-main hr {
- margin: 1.5em 1em;
- border: 2px solid #ddd;
-}
-
-main blockquote {
- margin: 0 2em 1.2em 1.2em;
- padding-left: 0.5em;
- border-left: 2px solid #ddd;
-}
-
-main ol,
-main ul {
- margin: 1em 2em;
-}
-
-main li > p {
- margin-bottom: 0.5em;
-}
-
-main dl {
- margin: 1em 0.5em;
-}
-
-main dt {
- margin-bottom: 0.5em;
- font-weight: bold;
-}
-
-main dd {
- margin: 0 1em 1em 0.5em;
-}
-
-main header h2 {
- margin-top: 2em;
- border-width: 0;
- border-top: 4px solid #bbb;
- font-size: 130%;
-}
-
-main header h3 {
- margin: 2em 0 1.5em;
- border-width: 0;
- border-top: 3px solid #bbb;
- font-size: 120%;
-}
-
-.documentation-section-title {
- position: relative;
-}
-.documentation-section-title .section-click-top {
- position: absolute;
- top: 6px;
- left: 12px;
- font-size: 10px;
- color: #9b9877;
- visibility: hidden;
- padding-left: 0.5px;
-}
-
-.documentation-section-title:hover .section-click-top {
- visibility: visible;
-}
-
-.constants-list > dl {
- margin: 1em 0 2em;
- border: 0;
-}
-
-.constants-list > dl dt {
- margin-bottom: 0.75em;
- padding-left: 0;
- font-family: "Source Code Pro", Monaco, monospace;
- font-size: 110%;
-}
-
-.constants-list > dl dt a {
- color: inherit;
-}
-
-.constants-list > dl dd {
- margin: 0 0 2em 0;
- padding: 0;
- color: #666;
-}
-
-.documentation-section h2 {
- position: relative;
-}
-
-.documentation-section h2 a {
- position: absolute;
- top: 8px;
- right: 10px;
- font-size: 12px;
- color: #9b9877;
- visibility: hidden;
-}
-
-.documentation-section h2:hover a {
- visibility: visible;
-}
-
-/* @group Method Details */
-
-main .method-source-code {
- max-height: 0;
- overflow: auto;
- transition-duration: 200ms;
- transition-delay: 0ms;
- transition-property: all;
- transition-timing-function: ease-in-out;
-}
-
-main .method-source-code.active-menu {
- max-height: 100vh;
-}
-
-main .method-description .method-calls-super {
- color: #333;
- font-weight: bold;
-}
-
-main .method-detail {
- margin-bottom: 2.5em;
- cursor: pointer;
-}
-
-main .method-detail:target {
- margin-left: -10px;
- border-left: 10px solid #f1edba;
-}
-
-main .method-heading {
- position: relative;
- font-family: "Source Code Pro", Monaco, monospace;
- font-size: 110%;
- font-weight: bold;
- color: #333;
-}
-main .method-heading :link,
-main .method-heading :visited {
- color: inherit;
-}
-main .method-click-advice {
- position: absolute;
- top: 2px;
- right: 5px;
- font-size: 12px;
- color: #9b9877;
- visibility: hidden;
- padding-right: 20px;
- line-height: 20px;
- background: url(../images/zoom.png) no-repeat right top;
-}
-main .method-header:hover .method-click-advice {
- visibility: visible;
-}
-
-main .method-alias .method-heading {
- color: #666;
-}
-
-main .method-description,
-main .aliases {
- margin-top: 0.75em;
- color: #333;
-}
-
-main .aliases {
- padding-top: 4px;
- font-style: italic;
- cursor: default;
-}
-main .method-description ul {
- margin-left: 1.5em;
-}
-
-main #attribute-method-details .method-detail:hover {
- background-color: transparent;
- cursor: default;
-}
-main .attribute-access-type {
- text-transform: uppercase;
- padding: 0 1em;
-}
-/* @end */
-
-/* @end */
-
-/* @group Source Code */
-
-pre {
- margin: 0.5em 0;
- border: 1px dashed #999;
- padding: 0.5em;
- background: #262626;
- color: white;
- overflow: auto;
-}
-
-.ruby-constant { color: #7fffd4; background: transparent; }
-.ruby-keyword { color: #00ffff; background: transparent; }
-.ruby-ivar { color: #eedd82; background: transparent; }
-.ruby-operator { color: #00ffee; background: transparent; }
-.ruby-identifier { color: #ffdead; background: transparent; }
-.ruby-node { color: #ffa07a; background: transparent; }
-.ruby-comment { color: #dc0000; background: transparent; }
-.ruby-regexp { color: #ffa07a; background: transparent; }
-.ruby-value { color: #7fffd4; background: transparent; }
-
-/* @end */
-
-
-/* @group search results */
-#search-results {
- font-family: Lato, sans-serif;
- font-weight: 300;
-}
-
-#search-results .search-match {
- font-family: Helvetica, sans-serif;
- font-weight: normal;
-}
-
-#search-results .search-selected {
- background: #e8e8e8;
- border-bottom: 1px solid transparent;
-}
-
-#search-results li {
- list-style: none;
- border-bottom: 1px solid #aaa;
- margin-bottom: 0.5em;
-}
-
-#search-results li:last-child {
- border-bottom: none;
- margin-bottom: 0;
-}
-
-#search-results li p {
- padding: 0;
- margin: 0.5em;
-}
-
-#search-results .search-namespace {
- font-weight: bold;
-}
-
-#search-results li em {
- background: yellow;
- font-style: normal;
-}
-
-#search-results pre {
- margin: 0.5em;
- font-family: "Source Code Pro", Monaco, monospace;
-}
-
-/* @end */
-
diff --git a/lib/rdoc/generator/template/darkfish/fonts/Lato-Light.ttf b/lib/rdoc/generator/template/darkfish/fonts/Lato-Light.ttf
deleted file mode 100644
index b49dd43729..0000000000
--- a/lib/rdoc/generator/template/darkfish/fonts/Lato-Light.ttf
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/fonts/Lato-LightItalic.ttf b/lib/rdoc/generator/template/darkfish/fonts/Lato-LightItalic.ttf
deleted file mode 100644
index 7959fef075..0000000000
--- a/lib/rdoc/generator/template/darkfish/fonts/Lato-LightItalic.ttf
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/fonts/Lato-Regular.ttf b/lib/rdoc/generator/template/darkfish/fonts/Lato-Regular.ttf
deleted file mode 100644
index 839cd589dc..0000000000
--- a/lib/rdoc/generator/template/darkfish/fonts/Lato-Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/fonts/Lato-RegularItalic.ttf b/lib/rdoc/generator/template/darkfish/fonts/Lato-RegularItalic.ttf
deleted file mode 100644
index bababa09e3..0000000000
--- a/lib/rdoc/generator/template/darkfish/fonts/Lato-RegularItalic.ttf
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf b/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf
deleted file mode 100644
index dd00982d49..0000000000
--- a/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf b/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf
deleted file mode 100644
index 1decfb95af..0000000000
--- a/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/add.png b/lib/rdoc/generator/template/darkfish/images/add.png
deleted file mode 100644
index 6332fefea4..0000000000
--- a/lib/rdoc/generator/template/darkfish/images/add.png
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/arrow_up.png b/lib/rdoc/generator/template/darkfish/images/arrow_up.png
deleted file mode 100644
index 1ebb193243..0000000000
--- a/lib/rdoc/generator/template/darkfish/images/arrow_up.png
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/brick.png b/lib/rdoc/generator/template/darkfish/images/brick.png
deleted file mode 100644
index 7851cf34c9..0000000000
--- a/lib/rdoc/generator/template/darkfish/images/brick.png
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/brick_link.png b/lib/rdoc/generator/template/darkfish/images/brick_link.png
deleted file mode 100644
index 9ebf013a23..0000000000
--- a/lib/rdoc/generator/template/darkfish/images/brick_link.png
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/bug.png b/lib/rdoc/generator/template/darkfish/images/bug.png
deleted file mode 100644
index 2d5fb90ec6..0000000000
--- a/lib/rdoc/generator/template/darkfish/images/bug.png
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/bullet_black.png b/lib/rdoc/generator/template/darkfish/images/bullet_black.png
deleted file mode 100644
index 57619706d1..0000000000
--- a/lib/rdoc/generator/template/darkfish/images/bullet_black.png
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/bullet_toggle_minus.png b/lib/rdoc/generator/template/darkfish/images/bullet_toggle_minus.png
deleted file mode 100644
index b47ce55f68..0000000000
--- a/lib/rdoc/generator/template/darkfish/images/bullet_toggle_minus.png
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/bullet_toggle_plus.png b/lib/rdoc/generator/template/darkfish/images/bullet_toggle_plus.png
deleted file mode 100644
index 9ab4a89664..0000000000
--- a/lib/rdoc/generator/template/darkfish/images/bullet_toggle_plus.png
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/date.png b/lib/rdoc/generator/template/darkfish/images/date.png
deleted file mode 100644
index 783c83357f..0000000000
--- a/lib/rdoc/generator/template/darkfish/images/date.png
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/delete.png b/lib/rdoc/generator/template/darkfish/images/delete.png
deleted file mode 100644
index 08f249365a..0000000000
--- a/lib/rdoc/generator/template/darkfish/images/delete.png
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/find.png b/lib/rdoc/generator/template/darkfish/images/find.png
deleted file mode 100644
index 1547479646..0000000000
--- a/lib/rdoc/generator/template/darkfish/images/find.png
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/loadingAnimation.gif b/lib/rdoc/generator/template/darkfish/images/loadingAnimation.gif
deleted file mode 100644
index 82290f4833..0000000000
--- a/lib/rdoc/generator/template/darkfish/images/loadingAnimation.gif
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/macFFBgHack.png b/lib/rdoc/generator/template/darkfish/images/macFFBgHack.png
deleted file mode 100644
index c6473b324e..0000000000
--- a/lib/rdoc/generator/template/darkfish/images/macFFBgHack.png
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/package.png b/lib/rdoc/generator/template/darkfish/images/package.png
deleted file mode 100644
index da3c2a2d74..0000000000
--- a/lib/rdoc/generator/template/darkfish/images/package.png
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/page_green.png b/lib/rdoc/generator/template/darkfish/images/page_green.png
deleted file mode 100644
index de8e003f9f..0000000000
--- a/lib/rdoc/generator/template/darkfish/images/page_green.png
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/page_white_text.png b/lib/rdoc/generator/template/darkfish/images/page_white_text.png
deleted file mode 100644
index 813f712f72..0000000000
--- a/lib/rdoc/generator/template/darkfish/images/page_white_text.png
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/page_white_width.png b/lib/rdoc/generator/template/darkfish/images/page_white_width.png
deleted file mode 100644
index 1eb880947d..0000000000
--- a/lib/rdoc/generator/template/darkfish/images/page_white_width.png
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/plugin.png b/lib/rdoc/generator/template/darkfish/images/plugin.png
deleted file mode 100644
index 6187b15aec..0000000000
--- a/lib/rdoc/generator/template/darkfish/images/plugin.png
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/ruby.png b/lib/rdoc/generator/template/darkfish/images/ruby.png
deleted file mode 100644
index f763a16880..0000000000
--- a/lib/rdoc/generator/template/darkfish/images/ruby.png
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/tag_blue.png b/lib/rdoc/generator/template/darkfish/images/tag_blue.png
deleted file mode 100644
index 3f02b5f8f8..0000000000
--- a/lib/rdoc/generator/template/darkfish/images/tag_blue.png
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/tag_green.png b/lib/rdoc/generator/template/darkfish/images/tag_green.png
deleted file mode 100644
index 83ec984bd7..0000000000
--- a/lib/rdoc/generator/template/darkfish/images/tag_green.png
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/transparent.png b/lib/rdoc/generator/template/darkfish/images/transparent.png
deleted file mode 100644
index d665e179ef..0000000000
--- a/lib/rdoc/generator/template/darkfish/images/transparent.png
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/wrench.png b/lib/rdoc/generator/template/darkfish/images/wrench.png
deleted file mode 100644
index 5c8213fef5..0000000000
--- a/lib/rdoc/generator/template/darkfish/images/wrench.png
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/wrench_orange.png b/lib/rdoc/generator/template/darkfish/images/wrench_orange.png
deleted file mode 100644
index 565a9330e0..0000000000
--- a/lib/rdoc/generator/template/darkfish/images/wrench_orange.png
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/zoom.png b/lib/rdoc/generator/template/darkfish/images/zoom.png
deleted file mode 100644
index 908612e394..0000000000
--- a/lib/rdoc/generator/template/darkfish/images/zoom.png
+++ /dev/null
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/index.rhtml b/lib/rdoc/generator/template/darkfish/index.rhtml
deleted file mode 100644
index 423e225b68..0000000000
--- a/lib/rdoc/generator/template/darkfish/index.rhtml
+++ /dev/null
@@ -1,22 +0,0 @@
-<body id="top" role="document" class="file">
-<nav role="navigation">
- <div id="project-navigation">
- <%= render '_sidebar_navigation.rhtml' %>
-
- <%= render '_sidebar_search.rhtml' %>
- </div>
-
- <div id="project-metadata">
- <%= render '_sidebar_pages.rhtml' %>
- <%= render '_sidebar_classes.rhtml' %>
- </div>
-</nav>
-
-<main role="main">
-<%- if @options.main_page and
- main_page = @files.find { |f| f.full_name == @options.main_page } then %>
-<%= main_page.description %>
-<%- else -%>
-<p>This is the API documentation for <%= h @title %>.
-<%- end -%>
-</main>
diff --git a/lib/rdoc/generator/template/darkfish/js/darkfish.js b/lib/rdoc/generator/template/darkfish/js/darkfish.js
deleted file mode 100644
index 19a85c54e1..0000000000
--- a/lib/rdoc/generator/template/darkfish/js/darkfish.js
+++ /dev/null
@@ -1,97 +0,0 @@
-/**
- *
- * Darkfish Page Functions
- * $Id: darkfish.js 53 2009-01-07 02:52:03Z deveiant $
- *
- * Author: Michael Granger <mgranger@laika.com>
- *
- */
-
-/* Provide console simulation for firebug-less environments */
-/*
-if (!("console" in window) || !("firebug" in console)) {
- var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
- "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
-
- window.console = {};
- for (var i = 0; i < names.length; ++i)
- window.console[names[i]] = function() {};
-};
-*/
-
-
-function showSource( e ) {
- var target = e.target;
- while (!target.classList.contains('method-detail')) {
- target = target.parentNode;
- }
- if (typeof target !== "undefined" && target !== null) {
- target = target.querySelector('.method-source-code');
- }
- if (typeof target !== "undefined" && target !== null) {
- target.classList.toggle('active-menu')
- }
-};
-
-function hookSourceViews() {
- document.querySelectorAll('.method-heading').forEach(function (codeObject) {
- codeObject.addEventListener('click', showSource);
- });
-};
-
-function hookSearch() {
- var input = document.querySelector('#search-field');
- var result = document.querySelector('#search-results');
- result.classList.remove("initially-hidden");
-
- var search_section = document.querySelector('#search-section');
- search_section.classList.remove("initially-hidden");
-
- var search = new Search(search_data, input, result);
-
- search.renderItem = function(result) {
- var li = document.createElement('li');
- var html = '';
-
- // TODO add relative path to <script> per-page
- html += '<p class="search-match"><a href="' + index_rel_prefix + this.escapeHTML(result.path) + '">' + this.hlt(result.title);
- if (result.params)
- html += '<span class="params">' + result.params + '</span>';
- html += '</a>';
-
-
- if (result.namespace)
- html += '<p class="search-namespace">' + this.hlt(result.namespace);
-
- if (result.snippet)
- html += '<div class="search-snippet">' + result.snippet + '</div>';
-
- li.innerHTML = html;
-
- return li;
- }
-
- search.select = function(result) {
- window.location.href = result.firstChild.firstChild.href;
- }
-
- search.scrollIntoView = search.scrollInWindow;
-};
-
-function hookFocus() {
- document.addEventListener("keydown", (event) => {
- if (document.activeElement.tagName === 'INPUT') {
- return;
- }
- if (event.key === "/") {
- event.preventDefault();
- document.querySelector('#search-field').focus();
- }
- });
-}
-
-document.addEventListener('DOMContentLoaded', function() {
- hookSourceViews();
- hookSearch();
- hookFocus();
-});
diff --git a/lib/rdoc/generator/template/darkfish/js/search.js b/lib/rdoc/generator/template/darkfish/js/search.js
deleted file mode 100644
index d3cded1d57..0000000000
--- a/lib/rdoc/generator/template/darkfish/js/search.js
+++ /dev/null
@@ -1,110 +0,0 @@
-Search = function(data, input, result) {
- this.data = data;
- this.input = input;
- this.result = result;
-
- this.current = null;
- this.view = this.result.parentNode;
- this.searcher = new Searcher(data.index);
- this.init();
-}
-
-Search.prototype = Object.assign({}, Navigation, new function() {
- var suid = 1;
-
- this.init = function() {
- var _this = this;
- var observer = function(e) {
- switch(e.key) {
- case 'ArrowUp':
- case 'ArrowDown':
- return;
- }
- _this.search(_this.input.value);
- };
- this.input.addEventListener('keyup', observer);
- this.input.addEventListener('click', observer); // mac's clear field
-
- this.searcher.ready(function(results, isLast) {
- _this.addResults(results, isLast);
- })
-
- this.initNavigation();
- this.setNavigationActive(false);
- }
-
- this.search = function(value, selectFirstMatch) {
- value = value.trim().toLowerCase();
- if (value) {
- this.setNavigationActive(true);
- } else {
- this.setNavigationActive(false);
- }
-
- if (value == '') {
- this.lastQuery = value;
- this.result.innerHTML = '';
- this.result.setAttribute('aria-expanded', 'false');
- this.setNavigationActive(false);
- } else if (value != this.lastQuery) {
- this.lastQuery = value;
- this.result.setAttribute('aria-busy', 'true');
- this.result.setAttribute('aria-expanded', 'true');
- this.firstRun = true;
- this.searcher.find(value);
- }
- }
-
- this.addResults = function(results, isLast) {
- var target = this.result;
- if (this.firstRun && (results.length > 0 || isLast)) {
- this.current = null;
- this.result.innerHTML = '';
- }
-
- for (var i=0, l = results.length; i < l; i++) {
- var item = this.renderItem.call(this, results[i]);
- item.setAttribute('id', 'search-result-' + target.childElementCount);
- target.appendChild(item);
- };
-
- if (this.firstRun && results.length > 0) {
- this.firstRun = false;
- this.current = target.firstChild;
- this.current.classList.add('search-selected');
- }
- //TODO: ECMAScript
- //if (jQuery.browser.msie) this.$element[0].className += '';
-
- if (isLast) this.result.setAttribute('aria-busy', 'false');
- }
-
- this.move = function(isDown) {
- if (!this.current) return;
- var next = isDown ? this.current.nextElementSibling : this.current.previousElementSibling;
- if (next) {
- this.current.classList.remove('search-selected');
- next.classList.add('search-selected');
- this.input.setAttribute('aria-activedescendant', next.getAttribute('id'));
- this.scrollIntoView(next, this.view);
- this.current = next;
- this.input.value = next.firstChild.firstChild.text;
- this.input.select();
- }
- return true;
- }
-
- this.hlt = function(html) {
- return this.escapeHTML(html).
- replace(/\u0001/g, '<em>').
- replace(/\u0002/g, '</em>');
- }
-
- this.escapeHTML = function(html) {
- return html.replace(/[&<>"`']/g, function(c) {
- return '&#' + c.charCodeAt(0) + ';';
- });
- }
-
-});
-
diff --git a/lib/rdoc/generator/template/darkfish/page.rhtml b/lib/rdoc/generator/template/darkfish/page.rhtml
deleted file mode 100644
index 4a6b006bb3..0000000000
--- a/lib/rdoc/generator/template/darkfish/page.rhtml
+++ /dev/null
@@ -1,18 +0,0 @@
-<body id="top" role="document" class="file">
-<nav role="navigation">
- <div id="project-navigation">
- <%= render '_sidebar_navigation.rhtml' %>
- <%= render '_sidebar_search.rhtml' %>
- </div>
-
- <%= render '_sidebar_table_of_contents.rhtml' %>
-
- <div id="project-metadata">
- <%= render '_sidebar_pages.rhtml' %>
- </div>
-</nav>
-
-<main role="main" aria-label="Page <%=h file.full_name%>">
-<%= file.description %>
-</main>
-
diff --git a/lib/rdoc/generator/template/darkfish/servlet_not_found.rhtml b/lib/rdoc/generator/template/darkfish/servlet_not_found.rhtml
deleted file mode 100644
index f0841572c3..0000000000
--- a/lib/rdoc/generator/template/darkfish/servlet_not_found.rhtml
+++ /dev/null
@@ -1,18 +0,0 @@
-<body role="document">
-<nav role="navigation">
- <%= render '_sidebar_navigation.rhtml' %>
-
- <%= render '_sidebar_search.rhtml' %>
-
- <div id="project-metadata">
- <%= render '_sidebar_pages.rhtml' %>
- <%= render '_sidebar_classes.rhtml' %>
- </div>
-</nav>
-
-<main role="main">
- <h1>Not Found</h1>
-
- <p><%= message %>
-</main>
-
diff --git a/lib/rdoc/generator/template/darkfish/servlet_root.rhtml b/lib/rdoc/generator/template/darkfish/servlet_root.rhtml
deleted file mode 100644
index cab3092b17..0000000000
--- a/lib/rdoc/generator/template/darkfish/servlet_root.rhtml
+++ /dev/null
@@ -1,62 +0,0 @@
-<body role="document">
-<nav role="navigation">
- <div id="project-navigation">
- <div id="home-section" class="nav-section">
- <h2>
- <a href="<%= rel_prefix %>/" rel="home">Home</a>
- </h2>
- </div>
-
- <%= render '_sidebar_search.rhtml' %>
- </div>
-
-<%= render '_sidebar_installed.rhtml' %>
-</nav>
-
-<main role="main">
- <h1>Local RDoc Documentation</h1>
-
- <p>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? -%>
- <h2>Extra Documentation Directories</h2>
-
- <p>The following additional documentation directories are available:</p>
-
- <ol>
- <%- extra_dirs.each do |name, href, exists, _, path| -%>
- <li>
- <%- if exists -%>
- <a href="<%= href %>"><%= h name %></a> (<%= h path %>)
- <%- else -%>
- <%= h name %> (<%= h path %>; <i>not available</i>)
- <%- end -%>
- </li>
- <%- end -%>
- </ol>
-<%- end -%>
-
-<%- gems = installed.select { |_, _, _, type,| type == :gem } -%>
-<%- missing = gems.reject { |_, _, exists,| exists } -%>
-<%- unless missing.empty? then -%>
- <h2>Missing Gem Documentation</h2>
-
- <p>You are missing documentation for some of your installed gems.
- You can install missing documentation for gems by running
- <kbd>gem rdoc --all</kbd>. After installing the missing documentation you
- only need to reload this page. The newly created documentation will
- automatically appear.
-
- <p>You can also install documentation for a specific gem by running one of
- the following commands.
-
- <ul>
- <%- names = missing.map { |name,| name.sub(/-([^-]*)$/, '') }.uniq -%>
- <%- names.each do |name| -%>
- <li><kbd>gem rdoc <%=h name %></kbd>
- <%- end -%>
- </ul>
-<%- end -%>
-</main>
diff --git a/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml b/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml
deleted file mode 100644
index 54a376c9e5..0000000000
--- a/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml
+++ /dev/null
@@ -1,59 +0,0 @@
-<body id="top" class="table-of-contents">
-<main role="main">
-<h1 class="class"><%= h @title %></h1>
-
-<%- simple_files = @files.select { |f| f.text? } -%>
-<%- unless simple_files.empty? then -%>
-<h2 id="pages">Pages</h2>
-<ul>
-<%- simple_files.sort.each do |file| -%>
- <li class="file">
- <a href="<%= h file.path %>"><%= h file.page_name %></a>
-<%
- # HACK table_of_contents should not exist on Document
- table = file.parse(file.comment).table_of_contents
- unless table.empty? then %>
- <ul>
-<%- table.each do |heading| -%>
- <li><a href="<%= h file.path %>#<%= heading.aref %>"><%= heading.plain_html %></a>
-<%- end -%>
- </ul>
-<%- end -%>
- </li>
- <%- end -%>
-</ul>
-<%- end -%>
-
-<h2 id="classes">Classes and Modules</h2>
-<ul>
-<%- @modsort.each do |klass| -%>
- <li class="<%= klass.type %>">
- <a href="<%= klass.path %>"><%= klass.full_name %></a>
-<%- table = []
- table.concat klass.parse(klass.comment_location).table_of_contents
- table.concat klass.section_contents
-
- unless table.empty? then %>
- <ul>
-<%- table.each do |item| -%>
-<%- label = item.respond_to?(:label) ? item.label(klass) : item.aref -%>
- <li><a href="<%= klass.path %>#<%= label %>"><%= item.plain_html %></a>
-<%- end -%>
- </ul>
-<%- end -%>
- </li>
-<%- end -%>
-</ul>
-
-<h2 id="methods">Methods</h2>
-<ul>
-<%- @store.all_classes_and_modules.flat_map do |mod|
- mod.method_list
- end.sort.each do |method| %>
- <li class="method">
- <a href="<%= method.path %>"><%= h method.pretty_name %></a>
- &mdash;
- <span class="container"><%= method.parent.full_name %></span>
-<%- end -%>
-</ul>
-</main>
diff --git a/lib/rdoc/generator/template/json_index/.document b/lib/rdoc/generator/template/json_index/.document
deleted file mode 100644
index 1713b67654..0000000000
--- a/lib/rdoc/generator/template/json_index/.document
+++ /dev/null
@@ -1 +0,0 @@
-# ignore all files in this directory
diff --git a/lib/rdoc/generator/template/json_index/js/navigation.js b/lib/rdoc/generator/template/json_index/js/navigation.js
deleted file mode 100644
index 137e3a0038..0000000000
--- a/lib/rdoc/generator/template/json_index/js/navigation.js
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Navigation allows movement using the arrow keys through the search results.
- *
- * When using this library you will need to set scrollIntoView to the
- * appropriate function for your layout. Use scrollInWindow if the container
- * is not scrollable and scrollInElement if the container is a separate
- * scrolling region.
- */
-Navigation = new function() {
- this.initNavigation = function() {
- var _this = this;
-
- document.addEventListener('keydown', function(e) {
- _this.onkeydown(e);
- });
-
- this.navigationActive = true;
- }
-
- this.setNavigationActive = function(state) {
- this.navigationActive = state;
- }
-
- this.onkeydown = function(e) {
- if (!this.navigationActive) return;
- switch(e.key) {
- case 'ArrowLeft':
- if (this.moveLeft()) e.preventDefault();
- break;
- case 'ArrowUp':
- if (e.key == 'ArrowUp' || e.ctrlKey) {
- if (this.moveUp()) e.preventDefault();
- }
- break;
- case 'ArrowRight':
- if (this.moveRight()) e.preventDefault();
- break;
- case 'ArrowDown':
- if (e.key == 'ArrowDown' || e.ctrlKey) {
- if (this.moveDown()) e.preventDefault();
- }
- break;
- case 'Enter':
- if (this.current) e.preventDefault();
- this.select(this.current);
- break;
- }
- if (e.ctrlKey && e.shiftKey) this.select(this.current);
- }
-
- this.moveRight = function() {
- }
-
- this.moveLeft = function() {
- }
-
- this.move = function(isDown) {
- }
-
- this.moveUp = function() {
- return this.move(false);
- }
-
- this.moveDown = function() {
- return this.move(true);
- }
-
- /*
- * Scrolls to the given element in the scrollable element view.
- */
- this.scrollInElement = function(element, view) {
- var offset, viewHeight, viewScroll, height;
- offset = element.offsetTop;
- height = element.offsetHeight;
- viewHeight = view.offsetHeight;
- viewScroll = view.scrollTop;
-
- if (offset - viewScroll + height > viewHeight) {
- view.scrollTop = offset - viewHeight + height;
- }
- if (offset < viewScroll) {
- view.scrollTop = offset;
- }
- }
-
- /*
- * Scrolls to the given element in the window. The second argument is
- * ignored
- */
- this.scrollInWindow = function(element, ignored) {
- var offset, viewHeight, viewScroll, height;
- offset = element.offsetTop;
- height = element.offsetHeight;
- viewHeight = window.innerHeight;
- viewScroll = window.scrollY;
-
- if (offset - viewScroll + height > viewHeight) {
- window.scrollTo(window.scrollX, offset - viewHeight + height);
- }
- if (offset < viewScroll) {
- window.scrollTo(window.scrollX, offset);
- }
- }
-}
-
diff --git a/lib/rdoc/generator/template/json_index/js/searcher.js b/lib/rdoc/generator/template/json_index/js/searcher.js
deleted file mode 100644
index e200a168b0..0000000000
--- a/lib/rdoc/generator/template/json_index/js/searcher.js
+++ /dev/null
@@ -1,229 +0,0 @@
-Searcher = function(data) {
- this.data = data;
- this.handlers = [];
-}
-
-Searcher.prototype = new function() {
- // search is performed in chunks of 1000 for non-blocking user input
- var CHUNK_SIZE = 1000;
- // do not try to find more than 100 results
- var MAX_RESULTS = 100;
- var huid = 1;
- var suid = 1;
- var runs = 0;
-
- this.find = function(query) {
- var queries = splitQuery(query);
- var regexps = buildRegexps(queries);
- var highlighters = buildHilighters(queries);
- var state = { from: 0, pass: 0, limit: MAX_RESULTS, n: suid++};
- var _this = this;
-
- this.currentSuid = state.n;
-
- if (!query) return;
-
- var run = function() {
- // stop current search thread if new search started
- if (state.n != _this.currentSuid) return;
-
- var results =
- performSearch(_this.data, regexps, queries, highlighters, state);
- var hasMore = (state.limit > 0 && state.pass < 4);
-
- triggerResults.call(_this, results, !hasMore);
- if (hasMore) {
- setTimeout(run, 2);
- }
- runs++;
- };
- runs = 0;
-
- // start search thread
- run();
- }
-
- /* ----- Events ------ */
- this.ready = function(fn) {
- fn.huid = huid;
- this.handlers.push(fn);
- }
-
- /* ----- Utilities ------ */
- function splitQuery(query) {
- return query.split(/(\s+|::?|\(\)?)/).filter(function(string) {
- return string.match(/\S/);
- });
- }
-
- function buildRegexps(queries) {
- return queries.map(function(query) {
- return new RegExp(query.replace(/(.)/g, '([$1])([^$1]*?)'), 'i');
- });
- }
-
- function buildHilighters(queries) {
- return queries.map(function(query) {
- return query.split('').map(function(l, i) {
- return '\u0001$' + (i*2+1) + '\u0002$' + (i*2+2);
- }).join('');
- });
- }
-
- // function longMatchRegexp(index, longIndex, regexps) {
- // for (var i = regexps.length - 1; i >= 0; i--){
- // if (!index.match(regexps[i]) && !longIndex.match(regexps[i])) return false;
- // };
- // return true;
- // }
-
-
- /* ----- Mathchers ------ */
-
- /*
- * This record matches if the index starts with queries[0] and the record
- * matches all of the regexps
- */
- function matchPassBeginning(index, longIndex, queries, regexps) {
- if (index.indexOf(queries[0]) != 0) return false;
- for (var i=1, l = regexps.length; i < l; i++) {
- if (!index.match(regexps[i]) && !longIndex.match(regexps[i]))
- return false;
- };
- return true;
- }
-
- /*
- * This record matches if the longIndex starts with queries[0] and the
- * longIndex matches all of the regexps
- */
- function matchPassLongIndex(index, longIndex, queries, regexps) {
- if (longIndex.indexOf(queries[0]) != 0) return false;
- for (var i=1, l = regexps.length; i < l; i++) {
- if (!longIndex.match(regexps[i]))
- return false;
- };
- return true;
- }
-
- /*
- * This record matches if the index contains queries[0] and the record
- * matches all of the regexps
- */
- function matchPassContains(index, longIndex, queries, regexps) {
- if (index.indexOf(queries[0]) == -1) return false;
- for (var i=1, l = regexps.length; i < l; i++) {
- if (!index.match(regexps[i]) && !longIndex.match(regexps[i]))
- return false;
- };
- return true;
- }
-
- /*
- * This record matches if regexps[0] matches the index and the record
- * matches all of the regexps
- */
- function matchPassRegexp(index, longIndex, queries, regexps) {
- if (!index.match(regexps[0])) return false;
- for (var i=1, l = regexps.length; i < l; i++) {
- if (!index.match(regexps[i]) && !longIndex.match(regexps[i]))
- return false;
- };
- return true;
- }
-
-
- /* ----- Highlighters ------ */
- function highlightRegexp(info, queries, regexps, highlighters) {
- var result = createResult(info);
- for (var i=0, l = regexps.length; i < l; i++) {
- result.title = result.title.replace(regexps[i], highlighters[i]);
- result.namespace = result.namespace.replace(regexps[i], highlighters[i]);
- };
- return result;
- }
-
- function hltSubstring(string, pos, length) {
- return string.substring(0, pos) + '\u0001' + string.substring(pos, pos + length) + '\u0002' + string.substring(pos + length);
- }
-
- function highlightQuery(info, queries, regexps, highlighters) {
- var result = createResult(info);
- var pos = 0;
- var lcTitle = result.title.toLowerCase();
-
- pos = lcTitle.indexOf(queries[0]);
- if (pos != -1) {
- result.title = hltSubstring(result.title, pos, queries[0].length);
- }
-
- result.namespace = result.namespace.replace(regexps[0], highlighters[0]);
- for (var i=1, l = regexps.length; i < l; i++) {
- result.title = result.title.replace(regexps[i], highlighters[i]);
- result.namespace = result.namespace.replace(regexps[i], highlighters[i]);
- };
- return result;
- }
-
- function createResult(info) {
- var result = {};
- result.title = info[0];
- result.namespace = info[1];
- result.path = info[2];
- result.params = info[3];
- result.snippet = info[4];
- result.badge = info[6];
- return result;
- }
-
- /* ----- Searching ------ */
- function performSearch(data, regexps, queries, highlighters, state) {
- var searchIndex = data.searchIndex;
- var longSearchIndex = data.longSearchIndex;
- var info = data.info;
- var result = [];
- var i = state.from;
- var l = searchIndex.length;
- var togo = CHUNK_SIZE;
- var matchFunc, hltFunc;
-
- while (state.pass < 4 && state.limit > 0 && togo > 0) {
- if (state.pass == 0) {
- matchFunc = matchPassBeginning;
- hltFunc = highlightQuery;
- } else if (state.pass == 1) {
- matchFunc = matchPassLongIndex;
- hltFunc = highlightQuery;
- } else if (state.pass == 2) {
- matchFunc = matchPassContains;
- hltFunc = highlightQuery;
- } else if (state.pass == 3) {
- matchFunc = matchPassRegexp;
- hltFunc = highlightRegexp;
- }
-
- for (; togo > 0 && i < l && state.limit > 0; i++, togo--) {
- if (info[i].n == state.n) continue;
- if (matchFunc(searchIndex[i], longSearchIndex[i], queries, regexps)) {
- info[i].n = state.n;
- result.push(hltFunc(info[i], queries, regexps, highlighters));
- state.limit--;
- }
- };
- if (searchIndex.length <= i) {
- state.pass++;
- i = state.from = 0;
- } else {
- state.from = i;
- }
- }
- return result;
- }
-
- function triggerResults(results, isLast) {
- this.handlers.forEach(function(fn) {
- fn.call(this, results, isLast)
- });
- }
-}
-
diff --git a/lib/rdoc/ghost_method.rb b/lib/rdoc/ghost_method.rb
deleted file mode 100644
index 25f951e35e..0000000000
--- a/lib/rdoc/ghost_method.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# frozen_string_literal: true
-##
-# GhostMethod represents a method referenced only by a comment
-
-class RDoc::GhostMethod < RDoc::AnyMethod
-end
diff --git a/lib/rdoc/i18n.rb b/lib/rdoc/i18n.rb
deleted file mode 100644
index f209a9a6f6..0000000000
--- a/lib/rdoc/i18n.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-##
-# This module provides i18n related features.
-
-module RDoc::I18n
-
- autoload :Locale, "#{__dir__}/i18n/locale"
- require_relative 'i18n/text'
-
-end
diff --git a/lib/rdoc/i18n/locale.rb b/lib/rdoc/i18n/locale.rb
deleted file mode 100644
index 6a70d6c986..0000000000
--- a/lib/rdoc/i18n/locale.rb
+++ /dev/null
@@ -1,102 +0,0 @@
-# frozen_string_literal: true
-##
-# A message container for a locale.
-#
-# This object provides the following two features:
-#
-# * Loads translated messages from .po file.
-# * Translates a message into the locale.
-
-class RDoc::I18n::Locale
-
- @@locales = {} # :nodoc:
-
- class << self
-
- ##
- # Returns the locale object for +locale_name+.
-
- def [](locale_name)
- @@locales[locale_name] ||= new(locale_name)
- end
-
- ##
- # Sets the locale object for +locale_name+.
- #
- # Normally, this method is not used. This method is useful for
- # testing.
-
- def []=(locale_name, locale)
- @@locales[locale_name] = locale
- end
-
- end
-
- ##
- # The name of the locale. It uses IETF language tag format
- # +[language[_territory][.codeset][@modifier]]+.
- #
- # See also {BCP 47 - Tags for Identifying
- # Languages}[http://tools.ietf.org/rfc/bcp/bcp47.txt].
-
- attr_reader :name
-
- ##
- # Creates a new locale object for +name+ locale. +name+ must
- # follow IETF language tag format.
-
- def initialize(name)
- @name = name
- @messages = {}
- end
-
- ##
- # Loads translation messages from +locale_directory+/+@name+/rdoc.po
- # or +locale_directory+/+@name+.po. The former has high priority.
- #
- # This method requires gettext gem for parsing .po file. If you
- # don't have gettext gem, this method doesn't load .po file. This
- # method warns and returns +false+.
- #
- # Returns +true+ if succeeded, +false+ otherwise.
-
- def load(locale_directory)
- return false if @name.nil?
-
- po_file_candidates = [
- File.join(locale_directory, @name, 'rdoc.po'),
- File.join(locale_directory, "#{@name}.po"),
- ]
- po_file = po_file_candidates.find do |po_file_candidate|
- File.exist?(po_file_candidate)
- end
- return false unless po_file
-
- begin
- require 'gettext/po_parser'
- require 'gettext/mo'
- rescue LoadError
- warn('Need gettext gem for i18n feature:')
- warn(' gem install gettext')
- return false
- end
-
- po_parser = GetText::POParser.new
- messages = GetText::MO.new
- po_parser.report_warning = false
- po_parser.parse_file(po_file, messages)
-
- @messages.merge!(messages)
-
- true
- end
-
- ##
- # Translates the +message+ into locale. If there is no translation
- # messages for +message+ in locale, +message+ itself is returned.
-
- def translate(message)
- @messages[message] || message
- end
-
-end
diff --git a/lib/rdoc/i18n/text.rb b/lib/rdoc/i18n/text.rb
deleted file mode 100644
index 7ea6664442..0000000000
--- a/lib/rdoc/i18n/text.rb
+++ /dev/null
@@ -1,126 +0,0 @@
-# frozen_string_literal: true
-##
-# An i18n supported text.
-#
-# This object provides the following two features:
-#
-# * Extracts translation messages from wrapped raw text.
-# * Translates wrapped raw text in specified locale.
-#
-# Wrapped raw text is one of String, RDoc::Comment or Array of them.
-
-class RDoc::I18n::Text
-
- ##
- # Creates a new i18n supported text for +raw+ text.
-
- def initialize(raw)
- @raw = raw
- end
-
- ##
- # Extracts translation target messages and yields each message.
- #
- # Each yielded message is a Hash. It consists of the followings:
- #
- # :type :: :paragraph
- # :paragraph :: String (The translation target message itself.)
- # :line_no :: Integer (The line number of the :paragraph is started.)
- #
- # The above content may be added in the future.
-
- def extract_messages
- parse do |part|
- case part[:type]
- when :empty_line
- # ignore
- when :paragraph
- yield(part)
- end
- end
- end
-
- # Translates raw text into +locale+.
- def translate(locale)
- translated_text = ''
- parse do |part|
- case part[:type]
- when :paragraph
- translated_text += locale.translate(part[:paragraph])
- when :empty_line
- translated_text += part[:line]
- else
- raise "should not reach here: unexpected type: #{type}"
- end
- end
- translated_text
- end
-
- private
- def parse(&block)
- paragraph = ''
- paragraph_start_line = 0
- line_no = 0
-
- each_line(@raw) do |line|
- line_no += 1
- case line
- when /\A\s*\z/
- if paragraph.empty?
- emit_empty_line_event(line, line_no, &block)
- else
- paragraph += line
- emit_paragraph_event(paragraph, paragraph_start_line, line_no,
- &block)
- paragraph = ''
- end
- else
- paragraph_start_line = line_no if paragraph.empty?
- paragraph += line
- end
- end
-
- unless paragraph.empty?
- emit_paragraph_event(paragraph, paragraph_start_line, line_no, &block)
- end
- end
-
- def each_line(raw, &block)
- case raw
- when RDoc::Comment
- raw.text.each_line(&block)
- when Array
- raw.each do |comment, location|
- each_line(comment, &block)
- end
- else
- raw.each_line(&block)
- end
- end
-
- def emit_empty_line_event(line, line_no)
- part = {
- :type => :empty_line,
- :line => line,
- :line_no => line_no,
- }
- yield(part)
- end
-
- def emit_paragraph_event(paragraph, paragraph_start_line, line_no, &block)
- paragraph_part = {
- :type => :paragraph,
- :line_no => paragraph_start_line,
- }
- match_data = /(\s*)\z/.match(paragraph)
- if match_data
- paragraph_part[:paragraph] = match_data.pre_match
- yield(paragraph_part)
- emit_empty_line_event(match_data[1], line_no, &block)
- else
- paragraph_part[:paragraph] = paragraph
- yield(paragraph_part)
- end
- end
-
-end
diff --git a/lib/rdoc/include.rb b/lib/rdoc/include.rb
deleted file mode 100644
index c3e0d45e47..0000000000
--- a/lib/rdoc/include.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-##
-# A Module included in a class with \#include
-#
-# RDoc::Include.new 'Enumerable', 'comment ...'
-
-class RDoc::Include < RDoc::Mixin
-
-end
diff --git a/lib/rdoc/known_classes.rb b/lib/rdoc/known_classes.rb
deleted file mode 100644
index 3e8752bbde..0000000000
--- a/lib/rdoc/known_classes.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-# frozen_string_literal: true
-module RDoc
-
- ##
- # Ruby's built-in classes, modules and exceptions
-
- KNOWN_CLASSES = {
- "rb_cArray" => "Array",
- "rb_cBasicObject" => "BasicObject",
- "rb_cBignum" => "Bignum",
- "rb_cClass" => "Class",
- "rb_cData" => "Data",
- "rb_cDir" => "Dir",
- "rb_cEncoding" => "Encoding",
- "rb_cFalseClass" => "FalseClass",
- "rb_cFile" => "File",
- "rb_cFixnum" => "Fixnum",
- "rb_cFloat" => "Float",
- "rb_cHash" => "Hash",
- "rb_cIO" => "IO",
- "rb_cInteger" => "Integer",
- "rb_cModule" => "Module",
- "rb_cNilClass" => "NilClass",
- "rb_cNumeric" => "Numeric",
- "rb_cObject" => "Object",
- "rb_cProc" => "Proc",
- "rb_cRange" => "Range",
- "rb_cRefinement" => "Refinement",
- "rb_cRegexp" => "Regexp",
- "rb_cRubyVM" => "RubyVM",
- "rb_cSocket" => "Socket",
- "rb_cString" => "String",
- "rb_cStruct" => "Struct",
- "rb_cSymbol" => "Symbol",
- "rb_cThread" => "Thread",
- "rb_cTime" => "Time",
- "rb_cTrueClass" => "TrueClass",
-
- "rb_eArgError" => "ArgumentError",
- "rb_eEOFError" => "EOFError",
- "rb_eException" => "Exception",
- "rb_eFatal" => "fatal",
- "rb_eFloatDomainError" => "FloatDomainError",
- "rb_eIOError" => "IOError",
- "rb_eIndexError" => "IndexError",
- "rb_eInterrupt" => "Interrupt",
- "rb_eLoadError" => "LoadError",
- "rb_eNameError" => "NameError",
- "rb_eNoMemError" => "NoMemoryError",
- "rb_eNotImpError" => "NotImplementedError",
- "rb_eRangeError" => "RangeError",
- "rb_eRuntimeError" => "RuntimeError",
- "rb_eScriptError" => "ScriptError",
- "rb_eSecurityError" => "SecurityError",
- "rb_eSignal" => "SignalException",
- "rb_eStandardError" => "StandardError",
- "rb_eSyntaxError" => "SyntaxError",
- "rb_eSystemCallError" => "SystemCallError",
- "rb_eSystemExit" => "SystemExit",
- "rb_eTypeError" => "TypeError",
- "rb_eZeroDivError" => "ZeroDivisionError",
-
- "rb_mComparable" => "Comparable",
- "rb_mEnumerable" => "Enumerable",
- "rb_mErrno" => "Errno",
- "rb_mFConst" => "File::Constants",
- "rb_mFileTest" => "FileTest",
- "rb_mGC" => "GC",
- "rb_mKernel" => "Kernel",
- "rb_mMath" => "Math",
- "rb_mProcess" => "Process"
- }
-
-end
diff --git a/lib/rdoc/markdown.rb b/lib/rdoc/markdown.rb
deleted file mode 100644
index 1416059763..0000000000
--- a/lib/rdoc/markdown.rb
+++ /dev/null
@@ -1,16783 +0,0 @@
-# coding: UTF-8
-# frozen_string_literal: true
-# :markup: markdown
-
-##
-# RDoc::Markdown as described by the [markdown syntax][syntax].
-#
-# To choose Markdown as your only default format see
-# RDoc::Options@Saved+Options for instructions on setting up a `.rdoc_options`
-# file to store your project default.
-#
-# ## Usage
-#
-# Here is a brief example of using this parse to read a markdown file by hand.
-#
-# data = File.read("README.md")
-# formatter = RDoc::Markup::ToHtml.new(RDoc::Options.new, nil)
-# html = RDoc::Markdown.parse(data).accept(formatter)
-#
-# # do something with html
-#
-# ## Extensions
-#
-# The following markdown extensions are supported by the parser, but not all
-# are used in RDoc output by default.
-#
-# ### RDoc
-#
-# The RDoc Markdown parser has the following built-in behaviors that cannot be
-# disabled.
-#
-# Underscores embedded in words are never interpreted as emphasis. (While the
-# [markdown dingus][dingus] emphasizes in-word underscores, neither the
-# Markdown syntax nor MarkdownTest mention this behavior.)
-#
-# For HTML output, RDoc always auto-links bare URLs.
-#
-# ### Break on Newline
-#
-# The break_on_newline extension converts all newlines into hard line breaks
-# as in [Github Flavored Markdown][GFM]. This extension is disabled by
-# default.
-#
-# ### CSS
-#
-# The #css extension enables CSS blocks to be included in the output, but they
-# are not used for any built-in RDoc output format. This extension is disabled
-# by default.
-#
-# Example:
-#
-# <style type="text/css">
-# h1 { font-size: 3em }
-# </style>
-#
-# ### Definition Lists
-#
-# The definition_lists extension allows definition lists using the [PHP
-# Markdown Extra syntax][PHPE], but only one label and definition are supported
-# at this time. This extension is enabled by default.
-#
-# Example:
-#
-# ```
-# cat
-# : A small furry mammal
-# that seems to sleep a lot
-#
-# ant
-# : A little insect that is known
-# to enjoy picnics
-#
-# ```
-#
-# Produces:
-#
-# cat
-# : A small furry mammal
-# that seems to sleep a lot
-#
-# ant
-# : A little insect that is known
-# to enjoy picnics
-#
-# ### Strike
-#
-# Example:
-#
-# ```
-# This is ~~striked~~.
-# ```
-#
-# Produces:
-#
-# This is ~~striked~~.
-#
-# ### Github
-#
-# The #github extension enables a partial set of [Github Flavored Markdown]
-# [GFM]. This extension is enabled by default.
-#
-# Supported github extensions include:
-#
-# #### Fenced code blocks
-#
-# Use ` ``` ` around a block of code instead of indenting it four spaces.
-#
-# #### Syntax highlighting
-#
-# Use ` ``` ruby ` as the start of a code fence to add syntax highlighting.
-# (Currently only `ruby` syntax is supported).
-#
-# ### HTML
-#
-# Enables raw HTML to be included in the output. This extension is enabled by
-# default.
-#
-# Example:
-#
-# <table>
-# ...
-# </table>
-#
-# ### Notes
-#
-# The #notes extension enables footnote support. This extension is enabled by
-# default.
-#
-# Example:
-#
-# Here is some text[^1] including an inline footnote ^[for short footnotes]
-#
-# ...
-#
-# [^1]: With the footnote text down at the bottom
-#
-# Produces:
-#
-# Here is some text[^1] including an inline footnote ^[for short footnotes]
-#
-# [^1]: With the footnote text down at the bottom
-#
-# ## Limitations
-#
-# * Link titles are not used
-# * Footnotes are collapsed into a single paragraph
-#
-# ## Author
-#
-# This markdown parser is a port to kpeg from [peg-markdown][pegmarkdown] by
-# John MacFarlane.
-#
-# It is used under the 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 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 port to kpeg was performed by Eric Hodel and Evan Phoenix
-#
-# [dingus]: http://daringfireball.net/projects/markdown/dingus
-# [GFM]: https://github.github.com/gfm/
-# [pegmarkdown]: https://github.com/jgm/peg-markdown
-# [PHPE]: https://michelf.ca/projects/php-markdown/extra/#def-list
-# [syntax]: http://daringfireball.net/projects/markdown/syntax
-#--
-# Last updated to jgm/peg-markdown commit 8f8fc22ef0
-class RDoc::Markdown
- # :stopdoc:
-
- # This is distinct from setup_parser so that a standalone parser
- # can redefine #initialize and still have access to the proper
- # parser setup code.
- def initialize(str, debug=false)
- setup_parser(str, debug)
- end
-
-
-
- # Prepares for parsing +str+. If you define a custom initialize you must
- # call this method before #parse
- def setup_parser(str, debug=false)
- set_string str, 0
- @memoizations = Hash.new { |h,k| h[k] = {} }
- @result = nil
- @failed_rule = nil
- @failing_rule_offset = -1
- @line_offsets = nil
-
- setup_foreign_grammar
- end
-
- attr_reader :string
- attr_reader :failing_rule_offset
- attr_accessor :result, :pos
-
- def current_column(target=pos)
- if string[target] == "\n" && (c = string.rindex("\n", target-1) || -1)
- return target - c
- elsif c = string.rindex("\n", target)
- return target - c
- end
-
- target + 1
- end
-
- def position_line_offsets
- unless @position_line_offsets
- @position_line_offsets = []
- total = 0
- string.each_line do |line|
- total += line.size
- @position_line_offsets << total
- end
- end
- @position_line_offsets
- end
-
- if [].respond_to? :bsearch_index
- def current_line(target=pos)
- if line = position_line_offsets.bsearch_index {|x| x > target }
- return line + 1
- end
- raise "Target position #{target} is outside of string"
- end
- else
- def current_line(target=pos)
- if line = position_line_offsets.index {|x| x > target }
- return line + 1
- end
-
- raise "Target position #{target} is outside of string"
- end
- end
-
- def current_character(target=pos)
- if target < 0 || target >= string.size
- raise "Target position #{target} is outside of string"
- end
- string[target, 1]
- end
-
- KpegPosInfo = Struct.new(:pos, :lno, :col, :line, :char)
-
- def current_pos_info(target=pos)
- l = current_line target
- c = current_column target
- ln = get_line(l-1)
- chr = string[target,1]
- KpegPosInfo.new(target, l, c, ln, chr)
- end
-
- def lines
- string.lines
- end
-
- def get_line(no)
- loff = position_line_offsets
- if no < 0
- raise "Line No is out of range: #{no} < 0"
- elsif no >= loff.size
- raise "Line No is out of range: #{no} >= #{loff.size}"
- end
- lend = loff[no]-1
- lstart = no > 0 ? loff[no-1] : 0
- string[lstart..lend]
- end
-
-
-
- def get_text(start)
- @string[start..@pos-1]
- end
-
- # Sets the string and current parsing position for the parser.
- def set_string string, pos
- @string = string
- @string_size = string ? string.size : 0
- @pos = pos
- @position_line_offsets = nil
- end
-
- def show_pos
- width = 10
- if @pos < width
- "#{@pos} (\"#{@string[0,@pos]}\" @ \"#{@string[@pos,width]}\")"
- else
- "#{@pos} (\"... #{@string[@pos - width, width]}\" @ \"#{@string[@pos,width]}\")"
- end
- end
-
- def failure_info
- l = current_line @failing_rule_offset
- c = current_column @failing_rule_offset
-
- if @failed_rule.kind_of? Symbol
- info = self.class::Rules[@failed_rule]
- "line #{l}, column #{c}: failed rule '#{info.name}' = '#{info.rendered}'"
- else
- "line #{l}, column #{c}: failed rule '#{@failed_rule}'"
- end
- end
-
- def failure_caret
- p = current_pos_info @failing_rule_offset
- "#{p.line.chomp}\n#{' ' * (p.col - 1)}^"
- end
-
- def failure_character
- current_character @failing_rule_offset
- end
-
- def failure_oneline
- p = current_pos_info @failing_rule_offset
-
- if @failed_rule.kind_of? Symbol
- info = self.class::Rules[@failed_rule]
- "@#{p.lno}:#{p.col} failed rule '#{info.name}', got '#{p.char}'"
- else
- "@#{p.lno}:#{p.col} failed rule '#{@failed_rule}', got '#{p.char}'"
- end
- end
-
- class ParseError < RuntimeError
- end
-
- def raise_error
- raise ParseError, failure_oneline
- end
-
- def show_error(io=STDOUT)
- error_pos = @failing_rule_offset
- p = current_pos_info(error_pos)
-
- io.puts "On line #{p.lno}, column #{p.col}:"
-
- if @failed_rule.kind_of? Symbol
- info = self.class::Rules[@failed_rule]
- io.puts "Failed to match '#{info.rendered}' (rule '#{info.name}')"
- else
- io.puts "Failed to match rule '#{@failed_rule}'"
- end
-
- io.puts "Got: #{p.char.inspect}"
- io.puts "=> #{p.line}"
- io.print(" " * (p.col + 2))
- io.puts "^"
- end
-
- def set_failed_rule(name)
- if @pos > @failing_rule_offset
- @failed_rule = name
- @failing_rule_offset = @pos
- end
- end
-
- attr_reader :failed_rule
-
- def match_string(str)
- len = str.size
- if @string[pos,len] == str
- @pos += len
- return str
- end
-
- return nil
- end
-
- def scan(reg)
- if m = reg.match(@string, @pos)
- @pos = m.end(0)
- return true
- end
-
- return nil
- end
-
- if "".respond_to? :ord
- def get_byte
- if @pos >= @string_size
- return nil
- end
-
- s = @string[@pos].ord
- @pos += 1
- s
- end
- else
- def get_byte
- if @pos >= @string_size
- return nil
- end
-
- s = @string[@pos]
- @pos += 1
- s
- end
- end
-
- def parse(rule=nil)
- # We invoke the rules indirectly via apply
- # instead of by just calling them as methods because
- # if the rules use left recursion, apply needs to
- # manage that.
-
- if !rule
- apply(:_root)
- else
- method = rule.gsub("-","_hyphen_")
- apply :"_#{method}"
- end
- end
-
- class MemoEntry
- def initialize(ans, pos)
- @ans = ans
- @pos = pos
- @result = nil
- @set = false
- @left_rec = false
- end
-
- attr_reader :ans, :pos, :result, :set
- attr_accessor :left_rec
-
- def move!(ans, pos, result)
- @ans = ans
- @pos = pos
- @result = result
- @set = true
- @left_rec = false
- end
- end
-
- def external_invoke(other, rule, *args)
- old_pos = @pos
- old_string = @string
-
- set_string other.string, other.pos
-
- begin
- if val = __send__(rule, *args)
- other.pos = @pos
- other.result = @result
- else
- other.set_failed_rule "#{self.class}##{rule}"
- end
- val
- ensure
- set_string old_string, old_pos
- end
- end
-
- def apply_with_args(rule, *args)
- @result = nil
- memo_key = [rule, args]
- if m = @memoizations[memo_key][@pos]
- @pos = m.pos
- if !m.set
- m.left_rec = true
- return nil
- end
-
- @result = m.result
-
- return m.ans
- else
- m = MemoEntry.new(nil, @pos)
- @memoizations[memo_key][@pos] = m
- start_pos = @pos
-
- ans = __send__ rule, *args
-
- lr = m.left_rec
-
- m.move! ans, @pos, @result
-
- # Don't bother trying to grow the left recursion
- # if it's failing straight away (thus there is no seed)
- if ans and lr
- return grow_lr(rule, args, start_pos, m)
- else
- return ans
- end
- end
- end
-
- def apply(rule)
- @result = nil
- if m = @memoizations[rule][@pos]
- @pos = m.pos
- if !m.set
- m.left_rec = true
- return nil
- end
-
- @result = m.result
-
- return m.ans
- else
- m = MemoEntry.new(nil, @pos)
- @memoizations[rule][@pos] = m
- start_pos = @pos
-
- ans = __send__ rule
-
- lr = m.left_rec
-
- m.move! ans, @pos, @result
-
- # Don't bother trying to grow the left recursion
- # if it's failing straight away (thus there is no seed)
- if ans and lr
- return grow_lr(rule, nil, start_pos, m)
- else
- return ans
- end
- end
- end
-
- def grow_lr(rule, args, start_pos, m)
- while true
- @pos = start_pos
- @result = m.result
-
- if args
- ans = __send__ rule, *args
- else
- ans = __send__ rule
- end
- return nil unless ans
-
- break if @pos <= m.pos
-
- m.move! ans, @pos, @result
- end
-
- @result = m.result
- @pos = m.pos
- return m.ans
- end
-
- class RuleInfo
- def initialize(name, rendered)
- @name = name
- @rendered = rendered
- end
-
- attr_reader :name, :rendered
- end
-
- def self.rule_info(name, rendered)
- RuleInfo.new(name, rendered)
- end
-
-
- # :startdoc:
-
-
-
- require_relative '../rdoc'
- require_relative 'markup/to_joined_paragraph'
- require_relative 'markdown/entities'
-
- require_relative 'markdown/literals'
-
- ##
- # Supported extensions
-
- EXTENSIONS = []
-
- ##
- # Extensions enabled by default
-
- DEFAULT_EXTENSIONS = [
- :definition_lists,
- :github,
- :html,
- :notes,
- :strike,
- ]
-
- # :section: Extensions
-
- ##
- # Creates extension methods for the `name` extension to enable and disable
- # the extension and to query if they are active.
-
- def self.extension name
- EXTENSIONS << name
-
- define_method "#{name}?" do
- extension? name
- end
-
- define_method "#{name}=" do |enable|
- extension name, enable
- end
- end
-
- ##
- # Converts all newlines into hard breaks
-
- extension :break_on_newline
-
- ##
- # Allow style blocks
-
- extension :css
-
- ##
- # Allow PHP Markdown Extras style definition lists
-
- extension :definition_lists
-
- ##
- # Allow Github Flavored Markdown
-
- extension :github
-
- ##
- # Allow HTML
-
- extension :html
-
- ##
- # Enables the notes extension
-
- extension :notes
-
- ##
- # Enables the strike extension
-
- extension :strike
-
- # :section:
-
- ##
- # Parses the `markdown` document into an RDoc::Document using the default
- # extensions.
-
- def self.parse markdown
- parser = new
-
- parser.parse markdown
- end
-
- # TODO remove when kpeg 0.10 is released
- alias orig_initialize initialize # :nodoc:
-
- ##
- # Creates a new markdown parser that enables the given +extensions+.
-
- def initialize extensions = DEFAULT_EXTENSIONS, debug = false
- @debug = debug
- @formatter = RDoc::Markup::ToJoinedParagraph.new
- @extensions = extensions
-
- @references = nil
- @unlinked_references = nil
-
- @footnotes = nil
- @note_order = nil
- end
-
- ##
- # Wraps `text` in emphasis for rdoc inline formatting
-
- def emphasis text
- if text =~ /\A[a-z\d.\/]+\z/i then
- "_#{text}_"
- else
- "<em>#{text}</em>"
- end
- end
-
- ##
- # :category: Extensions
- #
- # Is the extension `name` enabled?
-
- def extension? name
- @extensions.include? name
- end
-
- ##
- # :category: Extensions
- #
- # Enables or disables the extension with `name`
-
- def extension name, enable
- if enable then
- @extensions |= [name]
- else
- @extensions -= [name]
- end
- end
-
- ##
- # Parses `text` in a clone of this parser. This is used for handling nested
- # lists the same way as markdown_parser.
-
- def inner_parse text # :nodoc:
- parser = clone
-
- parser.setup_parser text, @debug
-
- parser.peg_parse
-
- doc = parser.result
-
- doc.accept @formatter
-
- doc.parts
- end
-
- ##
- # Finds a link reference for `label` and creates a new link to it with
- # `content` as the link text. If `label` was not encountered in the
- # reference-gathering parser pass the label and content are reconstructed
- # with the linking `text` (usually whitespace).
-
- def link_to content, label = content, text = nil
- raise ParseError, 'enable notes extension' if
- content.start_with? '^' and label.equal? content
-
- if ref = @references[label] then
- "{#{content}}[#{ref}]"
- elsif label.equal? content then
- "[#{content}]#{text}"
- else
- "[#{content}]#{text}[#{label}]"
- end
- end
-
- ##
- # Creates an RDoc::Markup::ListItem by parsing the `unparsed` content from
- # the first parsing pass.
-
- def list_item_from unparsed
- parsed = inner_parse unparsed.join
- RDoc::Markup::ListItem.new nil, *parsed
- end
-
- ##
- # Stores `label` as a note and fills in previously unknown note references.
-
- def note label
- #foottext = "rdoc-label:foottext-#{label}:footmark-#{label}"
-
- #ref.replace foottext if ref = @unlinked_notes.delete(label)
-
- @notes[label] = foottext
-
- #"{^1}[rdoc-label:footmark-#{label}:foottext-#{label}] "
- end
-
- ##
- # Creates a new link for the footnote `reference` and adds the reference to
- # the note order list for proper display at the end of the document.
-
- def note_for ref
- @note_order << ref
-
- label = @note_order.length
-
- "{*#{label}}[rdoc-label:foottext-#{label}:footmark-#{label}]"
- end
-
- ##
- # The internal kpeg parse method
-
- alias peg_parse parse # :nodoc:
-
- ##
- # Creates an RDoc::Markup::Paragraph from `parts` and including
- # extension-specific behavior
-
- def paragraph parts
- parts = parts.map do |part|
- if "\n" == part then
- RDoc::Markup::HardBreak.new
- else
- part
- end
- end if break_on_newline?
-
- RDoc::Markup::Paragraph.new(*parts)
- end
-
- ##
- # Parses `markdown` into an RDoc::Document
-
- def parse markdown
- @references = {}
- @unlinked_references = {}
-
- markdown += "\n\n"
-
- setup_parser markdown, @debug
- peg_parse 'References'
-
- if notes? then
- @footnotes = {}
-
- setup_parser markdown, @debug
- peg_parse 'Notes'
-
- # using note_order on the first pass would be a bug
- @note_order = []
- end
-
- setup_parser markdown, @debug
- peg_parse
-
- doc = result
-
- if notes? and not @footnotes.empty? then
- doc << RDoc::Markup::Rule.new(1)
-
- @note_order.each_with_index do |ref, index|
- label = index + 1
- note = @footnotes[ref] or raise ParseError, "footnote [^#{ref}] not found"
-
- link = "{^#{label}}[rdoc-label:footmark-#{label}:foottext-#{label}] "
- note.parts.unshift link
-
- doc << note
- end
- end
-
- doc.accept @formatter
-
- doc
- end
-
- ##
- # Stores `label` as a reference to `link` and fills in previously unknown
- # link references.
-
- def reference label, link
- if ref = @unlinked_references.delete(label) then
- ref.replace link
- end
-
- @references[label] = link
- end
-
- ##
- # Wraps `text` in strong markup for rdoc inline formatting
-
- def strong text
- if text =~ /\A[a-z\d.\/-]+\z/i then
- "*#{text}*"
- else
- "<b>#{text}</b>"
- end
- end
-
- ##
- # Wraps `text` in strike markup for rdoc inline formatting
-
- def strike text
- if text =~ /\A[a-z\d.\/-]+\z/i then
- "~#{text}~"
- else
- "<s>#{text}</s>"
- end
- end
-
-
- # :stopdoc:
- def setup_foreign_grammar
- @_grammar_literals = RDoc::Markdown::Literals.new(nil)
- end
-
- # root = Doc
- def _root
- _tmp = apply(:_Doc)
- set_failed_rule :_root unless _tmp
- return _tmp
- end
-
- # Doc = BOM? Block*:a { RDoc::Markup::Document.new(*a.compact) }
- def _Doc
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
- _tmp = apply(:_BOM)
- unless _tmp
- _tmp = true
- self.pos = _save1
- end
- unless _tmp
- self.pos = _save
- break
- end
- _ary = []
- while true
- _tmp = apply(:_Block)
- _ary << @result if _tmp
- break unless _tmp
- end
- _tmp = true
- @result = _ary
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; RDoc::Markup::Document.new(*a.compact) ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Doc unless _tmp
- return _tmp
- end
-
- # Block = @BlankLine* (BlockQuote | Verbatim | CodeFence | Table | Note | Reference | HorizontalRule | Heading | OrderedList | BulletList | DefinitionList | HtmlBlock | StyleBlock | Para | Plain)
- def _Block
-
- _save = self.pos
- while true # sequence
- while true
- _tmp = _BlankLine()
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_BlockQuote)
- break if _tmp
- self.pos = _save2
- _tmp = apply(:_Verbatim)
- break if _tmp
- self.pos = _save2
- _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
- _tmp = apply(:_Reference)
- break if _tmp
- self.pos = _save2
- _tmp = apply(:_HorizontalRule)
- break if _tmp
- self.pos = _save2
- _tmp = apply(:_Heading)
- break if _tmp
- self.pos = _save2
- _tmp = apply(:_OrderedList)
- break if _tmp
- self.pos = _save2
- _tmp = apply(:_BulletList)
- break if _tmp
- self.pos = _save2
- _tmp = apply(:_DefinitionList)
- break if _tmp
- self.pos = _save2
- _tmp = apply(:_HtmlBlock)
- break if _tmp
- self.pos = _save2
- _tmp = apply(:_StyleBlock)
- break if _tmp
- self.pos = _save2
- _tmp = apply(:_Para)
- break if _tmp
- self.pos = _save2
- _tmp = apply(:_Plain)
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Block unless _tmp
- return _tmp
- end
-
- # Para = @NonindentSpace Inlines:a @BlankLine+ { paragraph a }
- def _Para
-
- _save = self.pos
- while true # sequence
- _tmp = _NonindentSpace()
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Inlines)
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- _save1 = self.pos
- _tmp = _BlankLine()
- if _tmp
- while true
- _tmp = _BlankLine()
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save1
- end
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; paragraph a ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Para unless _tmp
- return _tmp
- end
-
- # Plain = Inlines:a { paragraph a }
- def _Plain
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_Inlines)
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; paragraph a ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Plain unless _tmp
- return _tmp
- end
-
- # AtxInline = !@Newline !(@Sp /#*/ @Sp @Newline) Inline
- def _AtxInline
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
- _tmp = _Newline()
- _tmp = _tmp ? nil : true
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- _save2 = self.pos
-
- _save3 = self.pos
- while true # sequence
- _tmp = _Sp()
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = scan(/\G(?-mix:#*)/)
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = _Newline()
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- _tmp = _tmp ? nil : true
- self.pos = _save2
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Inline)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_AtxInline unless _tmp
- return _tmp
- end
-
- # AtxStart = < /\#{1,6}/ > { text.length }
- def _AtxStart
-
- _save = self.pos
- while true # sequence
- _text_start = self.pos
- _tmp = scan(/\G(?-mix:\#{1,6})/)
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; text.length ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_AtxStart unless _tmp
- return _tmp
- end
-
- # AtxHeading = AtxStart:s @Sp AtxInline+:a (@Sp /#*/ @Sp)? @Newline { RDoc::Markup::Heading.new(s, a.join) }
- def _AtxHeading
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_AtxStart)
- s = @result
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save
- break
- end
- _save1 = self.pos
- _ary = []
- _tmp = apply(:_AtxInline)
- if _tmp
- _ary << @result
- while true
- _tmp = apply(:_AtxInline)
- _ary << @result if _tmp
- break unless _tmp
- end
- _tmp = true
- @result = _ary
- else
- self.pos = _save1
- end
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- _save2 = self.pos
-
- _save3 = self.pos
- while true # sequence
- _tmp = _Sp()
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = scan(/\G(?-mix:#*)/)
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- unless _tmp
- _tmp = true
- self.pos = _save2
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _Newline()
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; RDoc::Markup::Heading.new(s, a.join) ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_AtxHeading unless _tmp
- return _tmp
- end
-
- # SetextHeading = (SetextHeading1 | SetextHeading2)
- def _SetextHeading
-
- _save = self.pos
- while true # choice
- _tmp = apply(:_SetextHeading1)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_SetextHeading2)
- break if _tmp
- self.pos = _save
- break
- end # end choice
-
- set_failed_rule :_SetextHeading unless _tmp
- return _tmp
- end
-
- # SetextBottom1 = /={1,}/ @Newline
- def _SetextBottom1
-
- _save = self.pos
- while true # sequence
- _tmp = scan(/\G(?-mix:={1,})/)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _Newline()
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_SetextBottom1 unless _tmp
- return _tmp
- end
-
- # SetextBottom2 = /-{1,}/ @Newline
- def _SetextBottom2
-
- _save = self.pos
- while true # sequence
- _tmp = scan(/\G(?-mix:-{1,})/)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _Newline()
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_SetextBottom2 unless _tmp
- return _tmp
- end
-
- # SetextHeading1 = &(@RawLine SetextBottom1) @StartList:a (!@Endline Inline:b { a << b })+ @Sp @Newline SetextBottom1 { RDoc::Markup::Heading.new(1, a.join) }
- def _SetextHeading1
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
-
- _save2 = self.pos
- while true # sequence
- _tmp = _RawLine()
- unless _tmp
- self.pos = _save2
- break
- end
- _tmp = apply(:_SetextBottom1)
- unless _tmp
- self.pos = _save2
- end
- break
- end # end sequence
-
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _StartList()
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- _save3 = self.pos
-
- _save4 = self.pos
- while true # sequence
- _save5 = self.pos
- _tmp = _Endline()
- _tmp = _tmp ? nil : true
- self.pos = _save5
- unless _tmp
- self.pos = _save4
- break
- end
- _tmp = apply(:_Inline)
- b = @result
- unless _tmp
- self.pos = _save4
- break
- end
- @result = begin; a << b ; end
- _tmp = true
- unless _tmp
- self.pos = _save4
- end
- break
- end # end sequence
-
- if _tmp
- while true
-
- _save6 = self.pos
- while true # sequence
- _save7 = self.pos
- _tmp = _Endline()
- _tmp = _tmp ? nil : true
- self.pos = _save7
- unless _tmp
- self.pos = _save6
- break
- end
- _tmp = apply(:_Inline)
- b = @result
- unless _tmp
- self.pos = _save6
- break
- end
- @result = begin; a << b ; end
- _tmp = true
- unless _tmp
- self.pos = _save6
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save3
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _Newline()
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_SetextBottom1)
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; RDoc::Markup::Heading.new(1, a.join) ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_SetextHeading1 unless _tmp
- return _tmp
- end
-
- # SetextHeading2 = &(@RawLine SetextBottom2) @StartList:a (!@Endline Inline:b { a << b })+ @Sp @Newline SetextBottom2 { RDoc::Markup::Heading.new(2, a.join) }
- def _SetextHeading2
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
-
- _save2 = self.pos
- while true # sequence
- _tmp = _RawLine()
- unless _tmp
- self.pos = _save2
- break
- end
- _tmp = apply(:_SetextBottom2)
- unless _tmp
- self.pos = _save2
- end
- break
- end # end sequence
-
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _StartList()
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- _save3 = self.pos
-
- _save4 = self.pos
- while true # sequence
- _save5 = self.pos
- _tmp = _Endline()
- _tmp = _tmp ? nil : true
- self.pos = _save5
- unless _tmp
- self.pos = _save4
- break
- end
- _tmp = apply(:_Inline)
- b = @result
- unless _tmp
- self.pos = _save4
- break
- end
- @result = begin; a << b ; end
- _tmp = true
- unless _tmp
- self.pos = _save4
- end
- break
- end # end sequence
-
- if _tmp
- while true
-
- _save6 = self.pos
- while true # sequence
- _save7 = self.pos
- _tmp = _Endline()
- _tmp = _tmp ? nil : true
- self.pos = _save7
- unless _tmp
- self.pos = _save6
- break
- end
- _tmp = apply(:_Inline)
- b = @result
- unless _tmp
- self.pos = _save6
- break
- end
- @result = begin; a << b ; end
- _tmp = true
- unless _tmp
- self.pos = _save6
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save3
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _Newline()
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_SetextBottom2)
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; RDoc::Markup::Heading.new(2, a.join) ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_SetextHeading2 unless _tmp
- return _tmp
- end
-
- # Heading = (SetextHeading | AtxHeading)
- def _Heading
-
- _save = self.pos
- while true # choice
- _tmp = apply(:_SetextHeading)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_AtxHeading)
- break if _tmp
- self.pos = _save
- break
- end # end choice
-
- set_failed_rule :_Heading unless _tmp
- return _tmp
- end
-
- # BlockQuote = BlockQuoteRaw:a { RDoc::Markup::BlockQuote.new(*a) }
- def _BlockQuote
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_BlockQuoteRaw)
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; RDoc::Markup::BlockQuote.new(*a) ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_BlockQuote unless _tmp
- return _tmp
- end
-
- # BlockQuoteRaw = @StartList:a (">" " "? Line:l { a << l } (!">" !@BlankLine Line:c { a << c })* (@BlankLine:n { a << n })*)+ { inner_parse a.join }
- def _BlockQuoteRaw
-
- _save = self.pos
- while true # sequence
- _tmp = _StartList()
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- _save1 = self.pos
-
- _save2 = self.pos
- while true # sequence
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save2
- break
- end
- _save3 = self.pos
- _tmp = match_string(" ")
- unless _tmp
- _tmp = true
- self.pos = _save3
- end
- unless _tmp
- self.pos = _save2
- break
- end
- _tmp = apply(:_Line)
- l = @result
- unless _tmp
- self.pos = _save2
- break
- end
- @result = begin; a << l ; end
- _tmp = true
- unless _tmp
- self.pos = _save2
- break
- end
- 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 = _BlankLine()
- _tmp = _tmp ? nil : true
- self.pos = _save7
- unless _tmp
- self.pos = _save5
- break
- end
- _tmp = apply(:_Line)
- c = @result
- unless _tmp
- self.pos = _save5
- break
- end
- @result = begin; a << c ; end
- _tmp = true
- unless _tmp
- self.pos = _save5
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save2
- break
- end
- while true
-
- _save9 = self.pos
- while true # sequence
- _tmp = _BlankLine()
- n = @result
- unless _tmp
- self.pos = _save9
- break
- end
- @result = begin; a << n ; end
- _tmp = true
- unless _tmp
- self.pos = _save9
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save2
- end
- break
- end # end sequence
-
- if _tmp
- while true
-
- _save10 = self.pos
- while true # sequence
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save10
- break
- end
- _save11 = self.pos
- _tmp = match_string(" ")
- unless _tmp
- _tmp = true
- self.pos = _save11
- end
- unless _tmp
- self.pos = _save10
- break
- end
- _tmp = apply(:_Line)
- l = @result
- unless _tmp
- self.pos = _save10
- break
- end
- @result = begin; a << l ; end
- _tmp = true
- unless _tmp
- self.pos = _save10
- break
- end
- while true
-
- _save13 = self.pos
- while true # sequence
- _save14 = self.pos
- _tmp = match_string(">")
- _tmp = _tmp ? nil : true
- self.pos = _save14
- unless _tmp
- self.pos = _save13
- break
- end
- _save15 = self.pos
- _tmp = _BlankLine()
- _tmp = _tmp ? nil : true
- self.pos = _save15
- unless _tmp
- self.pos = _save13
- break
- end
- _tmp = apply(:_Line)
- c = @result
- unless _tmp
- self.pos = _save13
- break
- end
- @result = begin; a << c ; end
- _tmp = true
- unless _tmp
- self.pos = _save13
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save10
- break
- end
- while true
-
- _save17 = self.pos
- while true # sequence
- _tmp = _BlankLine()
- n = @result
- unless _tmp
- self.pos = _save17
- break
- end
- @result = begin; a << n ; end
- _tmp = true
- unless _tmp
- self.pos = _save17
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save10
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save1
- end
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; inner_parse a.join ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_BlockQuoteRaw unless _tmp
- return _tmp
- end
-
- # NonblankIndentedLine = !@BlankLine IndentedLine
- def _NonblankIndentedLine
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
- _tmp = _BlankLine()
- _tmp = _tmp ? nil : true
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_IndentedLine)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_NonblankIndentedLine unless _tmp
- return _tmp
- end
-
- # VerbatimChunk = @BlankLine*:a NonblankIndentedLine+:b { a.concat b }
- def _VerbatimChunk
-
- _save = self.pos
- while true # sequence
- _ary = []
- while true
- _tmp = _BlankLine()
- _ary << @result if _tmp
- break unless _tmp
- end
- _tmp = true
- @result = _ary
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- _save2 = self.pos
- _ary = []
- _tmp = apply(:_NonblankIndentedLine)
- if _tmp
- _ary << @result
- while true
- _tmp = apply(:_NonblankIndentedLine)
- _ary << @result if _tmp
- break unless _tmp
- end
- _tmp = true
- @result = _ary
- else
- self.pos = _save2
- end
- b = @result
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; a.concat b ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_VerbatimChunk unless _tmp
- return _tmp
- end
-
- # Verbatim = VerbatimChunk+:a { RDoc::Markup::Verbatim.new(*a.flatten) }
- def _Verbatim
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
- _ary = []
- _tmp = apply(:_VerbatimChunk)
- if _tmp
- _ary << @result
- while true
- _tmp = apply(:_VerbatimChunk)
- _ary << @result if _tmp
- break unless _tmp
- end
- _tmp = true
- @result = _ary
- else
- self.pos = _save1
- end
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; RDoc::Markup::Verbatim.new(*a.flatten) ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Verbatim unless _tmp
- return _tmp
- end
-
- # HorizontalRule = @NonindentSpace ("*" @Sp "*" @Sp "*" (@Sp "*")* | "-" @Sp "-" @Sp "-" (@Sp "-")* | "_" @Sp "_" @Sp "_" (@Sp "_")*) @Sp @Newline @BlankLine+ { RDoc::Markup::Rule.new 1 }
- def _HorizontalRule
-
- _save = self.pos
- while true # sequence
- _tmp = _NonindentSpace()
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
-
- _save2 = self.pos
- while true # sequence
- _tmp = match_string("*")
- unless _tmp
- self.pos = _save2
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save2
- break
- end
- _tmp = match_string("*")
- unless _tmp
- self.pos = _save2
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save2
- break
- end
- _tmp = match_string("*")
- unless _tmp
- self.pos = _save2
- break
- end
- while true
-
- _save4 = self.pos
- while true # sequence
- _tmp = _Sp()
- unless _tmp
- self.pos = _save4
- break
- end
- _tmp = match_string("*")
- unless _tmp
- self.pos = _save4
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- 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
- _tmp = _Sp()
- unless _tmp
- self.pos = _save5
- break
- end
- _tmp = match_string("-")
- unless _tmp
- self.pos = _save5
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save5
- break
- end
- _tmp = match_string("-")
- unless _tmp
- self.pos = _save5
- break
- end
- while true
-
- _save7 = self.pos
- while true # sequence
- _tmp = _Sp()
- unless _tmp
- self.pos = _save7
- break
- end
- _tmp = match_string("-")
- unless _tmp
- self.pos = _save7
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save5
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save1
-
- _save8 = self.pos
- while true # sequence
- _tmp = match_string("_")
- unless _tmp
- self.pos = _save8
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save8
- break
- end
- _tmp = match_string("_")
- unless _tmp
- self.pos = _save8
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save8
- break
- end
- _tmp = match_string("_")
- unless _tmp
- self.pos = _save8
- break
- end
- while true
-
- _save10 = self.pos
- while true # sequence
- _tmp = _Sp()
- unless _tmp
- self.pos = _save10
- break
- end
- _tmp = match_string("_")
- unless _tmp
- self.pos = _save10
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save8
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _Newline()
- unless _tmp
- self.pos = _save
- break
- end
- _save11 = self.pos
- _tmp = _BlankLine()
- if _tmp
- while true
- _tmp = _BlankLine()
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save11
- end
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; RDoc::Markup::Rule.new 1 ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HorizontalRule unless _tmp
- return _tmp
- end
-
- # Bullet = !HorizontalRule @NonindentSpace /[+*-]/ @Spacechar+
- def _Bullet
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
- _tmp = apply(:_HorizontalRule)
- _tmp = _tmp ? nil : true
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _NonindentSpace()
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = scan(/\G(?-mix:[+*-])/)
- unless _tmp
- self.pos = _save
- break
- end
- _save2 = self.pos
- _tmp = _Spacechar()
- if _tmp
- while true
- _tmp = _Spacechar()
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save2
- end
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Bullet unless _tmp
- return _tmp
- end
-
- # BulletList = &Bullet (ListTight | ListLoose):a { RDoc::Markup::List.new(:BULLET, *a) }
- def _BulletList
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
- _tmp = apply(:_Bullet)
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_ListTight)
- break if _tmp
- self.pos = _save2
- _tmp = apply(:_ListLoose)
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; RDoc::Markup::List.new(:BULLET, *a) ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_BulletList unless _tmp
- return _tmp
- end
-
- # ListTight = ListItemTight+:a @BlankLine* !(Bullet | Enumerator) { a }
- def _ListTight
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
- _ary = []
- _tmp = apply(:_ListItemTight)
- if _tmp
- _ary << @result
- while true
- _tmp = apply(:_ListItemTight)
- _ary << @result if _tmp
- break unless _tmp
- end
- _tmp = true
- @result = _ary
- else
- self.pos = _save1
- end
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = _BlankLine()
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _save3 = self.pos
-
- _save4 = self.pos
- while true # choice
- _tmp = apply(:_Bullet)
- break if _tmp
- self.pos = _save4
- _tmp = apply(:_Enumerator)
- break if _tmp
- self.pos = _save4
- break
- end # end choice
-
- _tmp = _tmp ? nil : true
- self.pos = _save3
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; a ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_ListTight unless _tmp
- return _tmp
- end
-
- # ListLoose = @StartList:a (ListItem:b @BlankLine* { a << b })+ { a }
- def _ListLoose
-
- _save = self.pos
- while true # sequence
- _tmp = _StartList()
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- _save1 = self.pos
-
- _save2 = self.pos
- while true # sequence
- _tmp = apply(:_ListItem)
- b = @result
- unless _tmp
- self.pos = _save2
- break
- end
- while true
- _tmp = _BlankLine()
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save2
- break
- end
- @result = begin; a << b ; end
- _tmp = true
- unless _tmp
- self.pos = _save2
- end
- break
- end # end sequence
-
- if _tmp
- while true
-
- _save4 = self.pos
- while true # sequence
- _tmp = apply(:_ListItem)
- b = @result
- unless _tmp
- self.pos = _save4
- break
- end
- while true
- _tmp = _BlankLine()
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save4
- break
- end
- @result = begin; a << b ; end
- _tmp = true
- unless _tmp
- self.pos = _save4
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save1
- end
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; a ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_ListLoose unless _tmp
- return _tmp
- end
-
- # ListItem = (Bullet | Enumerator) @StartList:a ListBlock:b { a << b } (ListContinuationBlock:c { a.push(*c) })* { list_item_from a }
- def _ListItem
-
- _save = self.pos
- while true # sequence
-
- _save1 = self.pos
- while true # choice
- _tmp = apply(:_Bullet)
- break if _tmp
- self.pos = _save1
- _tmp = apply(:_Enumerator)
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _StartList()
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_ListBlock)
- b = @result
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; a << b ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save3 = self.pos
- while true # sequence
- _tmp = apply(:_ListContinuationBlock)
- c = @result
- unless _tmp
- self.pos = _save3
- break
- end
- @result = begin; a.push(*c) ; end
- _tmp = true
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; list_item_from a ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_ListItem unless _tmp
- return _tmp
- end
-
- # ListItemTight = (Bullet | Enumerator) ListBlock:a (!@BlankLine ListContinuationBlock:b { a.push(*b) })* !ListContinuationBlock { list_item_from a }
- def _ListItemTight
-
- _save = self.pos
- while true # sequence
-
- _save1 = self.pos
- while true # choice
- _tmp = apply(:_Bullet)
- break if _tmp
- self.pos = _save1
- _tmp = apply(:_Enumerator)
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_ListBlock)
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = _BlankLine()
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = apply(:_ListContinuationBlock)
- b = @result
- unless _tmp
- self.pos = _save3
- break
- end
- @result = begin; a.push(*b) ; end
- _tmp = true
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _save5 = self.pos
- _tmp = apply(:_ListContinuationBlock)
- _tmp = _tmp ? nil : true
- self.pos = _save5
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; list_item_from a ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_ListItemTight unless _tmp
- return _tmp
- end
-
- # ListBlock = !@BlankLine Line:a ListBlockLine*:c { [a, *c] }
- def _ListBlock
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
- _tmp = _BlankLine()
- _tmp = _tmp ? nil : true
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Line)
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- _ary = []
- while true
- _tmp = apply(:_ListBlockLine)
- _ary << @result if _tmp
- break unless _tmp
- end
- _tmp = true
- @result = _ary
- c = @result
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; [a, *c] ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_ListBlock unless _tmp
- return _tmp
- end
-
- # ListContinuationBlock = @StartList:a @BlankLine* { a << "\n" } (Indent ListBlock:b { a.concat b })+ { a }
- def _ListContinuationBlock
-
- _save = self.pos
- while true # sequence
- _tmp = _StartList()
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = _BlankLine()
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; a << "\n" ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _save2 = self.pos
-
- _save3 = self.pos
- while true # sequence
- _tmp = apply(:_Indent)
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = apply(:_ListBlock)
- b = @result
- unless _tmp
- self.pos = _save3
- break
- end
- @result = begin; a.concat b ; end
- _tmp = true
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- if _tmp
- while true
-
- _save4 = self.pos
- while true # sequence
- _tmp = apply(:_Indent)
- unless _tmp
- self.pos = _save4
- break
- end
- _tmp = apply(:_ListBlock)
- b = @result
- unless _tmp
- self.pos = _save4
- break
- end
- @result = begin; a.concat b ; end
- _tmp = true
- unless _tmp
- self.pos = _save4
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save2
- end
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; a ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_ListContinuationBlock unless _tmp
- return _tmp
- end
-
- # Enumerator = @NonindentSpace [0-9]+ "." @Spacechar+
- def _Enumerator
-
- _save = self.pos
- while true # sequence
- _tmp = _NonindentSpace()
- unless _tmp
- self.pos = _save
- break
- end
- _save1 = self.pos
- _save2 = self.pos
- _tmp = get_byte
- if _tmp
- unless _tmp >= 48 and _tmp <= 57
- self.pos = _save2
- _tmp = nil
- end
- end
- if _tmp
- while true
- _save3 = self.pos
- _tmp = get_byte
- if _tmp
- unless _tmp >= 48 and _tmp <= 57
- self.pos = _save3
- _tmp = nil
- end
- end
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save1
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(".")
- unless _tmp
- self.pos = _save
- break
- end
- _save4 = self.pos
- _tmp = _Spacechar()
- if _tmp
- while true
- _tmp = _Spacechar()
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save4
- end
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Enumerator unless _tmp
- return _tmp
- end
-
- # OrderedList = &Enumerator (ListTight | ListLoose):a { RDoc::Markup::List.new(:NUMBER, *a) }
- def _OrderedList
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
- _tmp = apply(:_Enumerator)
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_ListTight)
- break if _tmp
- self.pos = _save2
- _tmp = apply(:_ListLoose)
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; RDoc::Markup::List.new(:NUMBER, *a) ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_OrderedList unless _tmp
- return _tmp
- end
-
- # ListBlockLine = !@BlankLine !(Indent? (Bullet | Enumerator)) !HorizontalRule OptionallyIndentedLine
- def _ListBlockLine
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
- _tmp = _BlankLine()
- _tmp = _tmp ? nil : true
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- _save2 = self.pos
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_Indent)
- unless _tmp
- _tmp = true
- self.pos = _save4
- end
- unless _tmp
- self.pos = _save3
- break
- end
-
- _save5 = self.pos
- while true # choice
- _tmp = apply(:_Bullet)
- break if _tmp
- self.pos = _save5
- _tmp = apply(:_Enumerator)
- break if _tmp
- self.pos = _save5
- break
- end # end choice
-
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- _tmp = _tmp ? nil : true
- self.pos = _save2
- unless _tmp
- self.pos = _save
- break
- end
- _save6 = self.pos
- _tmp = apply(:_HorizontalRule)
- _tmp = _tmp ? nil : true
- self.pos = _save6
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_OptionallyIndentedLine)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_ListBlockLine unless _tmp
- return _tmp
- end
-
- # HtmlOpenAnchor = "<" Spnl ("a" | "A") Spnl HtmlAttribute* ">"
- def _HtmlOpenAnchor
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("a")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("A")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlOpenAnchor unless _tmp
- return _tmp
- end
-
- # HtmlCloseAnchor = "<" Spnl "/" ("a" | "A") Spnl ">"
- def _HtmlCloseAnchor
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("a")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("A")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlCloseAnchor unless _tmp
- return _tmp
- end
-
- # HtmlAnchor = HtmlOpenAnchor (HtmlAnchor | !HtmlCloseAnchor .)* HtmlCloseAnchor
- def _HtmlAnchor
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlOpenAnchor)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlAnchor)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlCloseAnchor)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlCloseAnchor)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlAnchor unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenAddress = "<" Spnl ("address" | "ADDRESS") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenAddress
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("address")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("ADDRESS")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenAddress unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseAddress = "<" Spnl "/" ("address" | "ADDRESS") Spnl ">"
- def _HtmlBlockCloseAddress
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("address")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("ADDRESS")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseAddress unless _tmp
- return _tmp
- end
-
- # HtmlBlockAddress = HtmlBlockOpenAddress (HtmlBlockAddress | !HtmlBlockCloseAddress .)* HtmlBlockCloseAddress
- def _HtmlBlockAddress
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenAddress)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockAddress)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseAddress)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseAddress)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockAddress unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenBlockquote = "<" Spnl ("blockquote" | "BLOCKQUOTE") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenBlockquote
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("blockquote")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("BLOCKQUOTE")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenBlockquote unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseBlockquote = "<" Spnl "/" ("blockquote" | "BLOCKQUOTE") Spnl ">"
- def _HtmlBlockCloseBlockquote
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("blockquote")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("BLOCKQUOTE")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseBlockquote unless _tmp
- return _tmp
- end
-
- # HtmlBlockBlockquote = HtmlBlockOpenBlockquote (HtmlBlockBlockquote | !HtmlBlockCloseBlockquote .)* HtmlBlockCloseBlockquote
- def _HtmlBlockBlockquote
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenBlockquote)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockBlockquote)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseBlockquote)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseBlockquote)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockBlockquote unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenCenter = "<" Spnl ("center" | "CENTER") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenCenter
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("center")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("CENTER")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenCenter unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseCenter = "<" Spnl "/" ("center" | "CENTER") Spnl ">"
- def _HtmlBlockCloseCenter
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("center")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("CENTER")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseCenter unless _tmp
- return _tmp
- end
-
- # HtmlBlockCenter = HtmlBlockOpenCenter (HtmlBlockCenter | !HtmlBlockCloseCenter .)* HtmlBlockCloseCenter
- def _HtmlBlockCenter
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenCenter)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockCenter)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseCenter)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseCenter)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCenter unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenDir = "<" Spnl ("dir" | "DIR") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenDir
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("dir")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("DIR")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenDir unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseDir = "<" Spnl "/" ("dir" | "DIR") Spnl ">"
- def _HtmlBlockCloseDir
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("dir")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("DIR")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseDir unless _tmp
- return _tmp
- end
-
- # HtmlBlockDir = HtmlBlockOpenDir (HtmlBlockDir | !HtmlBlockCloseDir .)* HtmlBlockCloseDir
- def _HtmlBlockDir
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenDir)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockDir)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseDir)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseDir)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockDir unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenDiv = "<" Spnl ("div" | "DIV") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenDiv
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("div")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("DIV")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenDiv unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseDiv = "<" Spnl "/" ("div" | "DIV") Spnl ">"
- def _HtmlBlockCloseDiv
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("div")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("DIV")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseDiv unless _tmp
- return _tmp
- end
-
- # HtmlBlockDiv = HtmlBlockOpenDiv (HtmlBlockDiv | !HtmlBlockCloseDiv .)* HtmlBlockCloseDiv
- def _HtmlBlockDiv
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenDiv)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockDiv)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseDiv)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseDiv)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockDiv unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenDl = "<" Spnl ("dl" | "DL") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenDl
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("dl")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("DL")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenDl unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseDl = "<" Spnl "/" ("dl" | "DL") Spnl ">"
- def _HtmlBlockCloseDl
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("dl")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("DL")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseDl unless _tmp
- return _tmp
- end
-
- # HtmlBlockDl = HtmlBlockOpenDl (HtmlBlockDl | !HtmlBlockCloseDl .)* HtmlBlockCloseDl
- def _HtmlBlockDl
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenDl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockDl)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseDl)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseDl)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockDl unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenFieldset = "<" Spnl ("fieldset" | "FIELDSET") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenFieldset
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("fieldset")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("FIELDSET")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenFieldset unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseFieldset = "<" Spnl "/" ("fieldset" | "FIELDSET") Spnl ">"
- def _HtmlBlockCloseFieldset
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("fieldset")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("FIELDSET")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseFieldset unless _tmp
- return _tmp
- end
-
- # HtmlBlockFieldset = HtmlBlockOpenFieldset (HtmlBlockFieldset | !HtmlBlockCloseFieldset .)* HtmlBlockCloseFieldset
- def _HtmlBlockFieldset
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenFieldset)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockFieldset)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseFieldset)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseFieldset)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockFieldset unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenForm = "<" Spnl ("form" | "FORM") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenForm
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("form")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("FORM")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenForm unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseForm = "<" Spnl "/" ("form" | "FORM") Spnl ">"
- def _HtmlBlockCloseForm
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("form")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("FORM")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseForm unless _tmp
- return _tmp
- end
-
- # HtmlBlockForm = HtmlBlockOpenForm (HtmlBlockForm | !HtmlBlockCloseForm .)* HtmlBlockCloseForm
- def _HtmlBlockForm
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenForm)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockForm)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseForm)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseForm)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockForm unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenH1 = "<" Spnl ("h1" | "H1") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenH1
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("h1")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("H1")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenH1 unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseH1 = "<" Spnl "/" ("h1" | "H1") Spnl ">"
- def _HtmlBlockCloseH1
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("h1")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("H1")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseH1 unless _tmp
- return _tmp
- end
-
- # HtmlBlockH1 = HtmlBlockOpenH1 (HtmlBlockH1 | !HtmlBlockCloseH1 .)* HtmlBlockCloseH1
- def _HtmlBlockH1
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenH1)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockH1)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseH1)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseH1)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockH1 unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenH2 = "<" Spnl ("h2" | "H2") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenH2
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("h2")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("H2")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenH2 unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseH2 = "<" Spnl "/" ("h2" | "H2") Spnl ">"
- def _HtmlBlockCloseH2
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("h2")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("H2")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseH2 unless _tmp
- return _tmp
- end
-
- # HtmlBlockH2 = HtmlBlockOpenH2 (HtmlBlockH2 | !HtmlBlockCloseH2 .)* HtmlBlockCloseH2
- def _HtmlBlockH2
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenH2)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockH2)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseH2)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseH2)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockH2 unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenH3 = "<" Spnl ("h3" | "H3") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenH3
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("h3")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("H3")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenH3 unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseH3 = "<" Spnl "/" ("h3" | "H3") Spnl ">"
- def _HtmlBlockCloseH3
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("h3")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("H3")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseH3 unless _tmp
- return _tmp
- end
-
- # HtmlBlockH3 = HtmlBlockOpenH3 (HtmlBlockH3 | !HtmlBlockCloseH3 .)* HtmlBlockCloseH3
- def _HtmlBlockH3
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenH3)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockH3)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseH3)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseH3)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockH3 unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenH4 = "<" Spnl ("h4" | "H4") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenH4
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("h4")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("H4")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenH4 unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseH4 = "<" Spnl "/" ("h4" | "H4") Spnl ">"
- def _HtmlBlockCloseH4
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("h4")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("H4")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseH4 unless _tmp
- return _tmp
- end
-
- # HtmlBlockH4 = HtmlBlockOpenH4 (HtmlBlockH4 | !HtmlBlockCloseH4 .)* HtmlBlockCloseH4
- def _HtmlBlockH4
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenH4)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockH4)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseH4)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseH4)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockH4 unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenH5 = "<" Spnl ("h5" | "H5") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenH5
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("h5")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("H5")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenH5 unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseH5 = "<" Spnl "/" ("h5" | "H5") Spnl ">"
- def _HtmlBlockCloseH5
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("h5")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("H5")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseH5 unless _tmp
- return _tmp
- end
-
- # HtmlBlockH5 = HtmlBlockOpenH5 (HtmlBlockH5 | !HtmlBlockCloseH5 .)* HtmlBlockCloseH5
- def _HtmlBlockH5
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenH5)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockH5)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseH5)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseH5)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockH5 unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenH6 = "<" Spnl ("h6" | "H6") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenH6
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("h6")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("H6")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenH6 unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseH6 = "<" Spnl "/" ("h6" | "H6") Spnl ">"
- def _HtmlBlockCloseH6
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("h6")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("H6")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseH6 unless _tmp
- return _tmp
- end
-
- # HtmlBlockH6 = HtmlBlockOpenH6 (HtmlBlockH6 | !HtmlBlockCloseH6 .)* HtmlBlockCloseH6
- def _HtmlBlockH6
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenH6)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockH6)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseH6)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseH6)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockH6 unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenMenu = "<" Spnl ("menu" | "MENU") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenMenu
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("menu")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("MENU")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenMenu unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseMenu = "<" Spnl "/" ("menu" | "MENU") Spnl ">"
- def _HtmlBlockCloseMenu
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("menu")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("MENU")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseMenu unless _tmp
- return _tmp
- end
-
- # HtmlBlockMenu = HtmlBlockOpenMenu (HtmlBlockMenu | !HtmlBlockCloseMenu .)* HtmlBlockCloseMenu
- def _HtmlBlockMenu
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenMenu)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockMenu)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseMenu)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseMenu)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockMenu unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenNoframes = "<" Spnl ("noframes" | "NOFRAMES") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenNoframes
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("noframes")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("NOFRAMES")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenNoframes unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseNoframes = "<" Spnl "/" ("noframes" | "NOFRAMES") Spnl ">"
- def _HtmlBlockCloseNoframes
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("noframes")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("NOFRAMES")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseNoframes unless _tmp
- return _tmp
- end
-
- # HtmlBlockNoframes = HtmlBlockOpenNoframes (HtmlBlockNoframes | !HtmlBlockCloseNoframes .)* HtmlBlockCloseNoframes
- def _HtmlBlockNoframes
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenNoframes)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockNoframes)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseNoframes)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseNoframes)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockNoframes unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenNoscript = "<" Spnl ("noscript" | "NOSCRIPT") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenNoscript
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("noscript")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("NOSCRIPT")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenNoscript unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseNoscript = "<" Spnl "/" ("noscript" | "NOSCRIPT") Spnl ">"
- def _HtmlBlockCloseNoscript
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("noscript")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("NOSCRIPT")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseNoscript unless _tmp
- return _tmp
- end
-
- # HtmlBlockNoscript = HtmlBlockOpenNoscript (HtmlBlockNoscript | !HtmlBlockCloseNoscript .)* HtmlBlockCloseNoscript
- def _HtmlBlockNoscript
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenNoscript)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockNoscript)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseNoscript)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseNoscript)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockNoscript unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenOl = "<" Spnl ("ol" | "OL") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenOl
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("ol")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("OL")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenOl unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseOl = "<" Spnl "/" ("ol" | "OL") Spnl ">"
- def _HtmlBlockCloseOl
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("ol")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("OL")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseOl unless _tmp
- return _tmp
- end
-
- # HtmlBlockOl = HtmlBlockOpenOl (HtmlBlockOl | !HtmlBlockCloseOl .)* HtmlBlockCloseOl
- def _HtmlBlockOl
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenOl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockOl)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseOl)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseOl)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOl unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenP = "<" Spnl ("p" | "P") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenP
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("p")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("P")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenP unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseP = "<" Spnl "/" ("p" | "P") Spnl ">"
- def _HtmlBlockCloseP
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("p")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("P")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseP unless _tmp
- return _tmp
- end
-
- # HtmlBlockP = HtmlBlockOpenP (HtmlBlockP | !HtmlBlockCloseP .)* HtmlBlockCloseP
- def _HtmlBlockP
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenP)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockP)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseP)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseP)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockP unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenPre = "<" Spnl ("pre" | "PRE") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenPre
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("pre")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("PRE")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenPre unless _tmp
- return _tmp
- end
-
- # HtmlBlockClosePre = "<" Spnl "/" ("pre" | "PRE") Spnl ">"
- def _HtmlBlockClosePre
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("pre")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("PRE")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockClosePre unless _tmp
- return _tmp
- end
-
- # HtmlBlockPre = HtmlBlockOpenPre (HtmlBlockPre | !HtmlBlockClosePre .)* HtmlBlockClosePre
- def _HtmlBlockPre
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenPre)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockPre)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockClosePre)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockClosePre)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockPre unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenTable = "<" Spnl ("table" | "TABLE") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenTable
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("table")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("TABLE")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenTable unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseTable = "<" Spnl "/" ("table" | "TABLE") Spnl ">"
- def _HtmlBlockCloseTable
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("table")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("TABLE")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseTable unless _tmp
- return _tmp
- end
-
- # HtmlBlockTable = HtmlBlockOpenTable (HtmlBlockTable | !HtmlBlockCloseTable .)* HtmlBlockCloseTable
- def _HtmlBlockTable
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenTable)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockTable)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseTable)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseTable)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockTable unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenUl = "<" Spnl ("ul" | "UL") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenUl
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("ul")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("UL")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenUl unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseUl = "<" Spnl "/" ("ul" | "UL") Spnl ">"
- def _HtmlBlockCloseUl
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("ul")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("UL")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseUl unless _tmp
- return _tmp
- end
-
- # HtmlBlockUl = HtmlBlockOpenUl (HtmlBlockUl | !HtmlBlockCloseUl .)* HtmlBlockCloseUl
- def _HtmlBlockUl
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenUl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockUl)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseUl)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseUl)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockUl unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenDd = "<" Spnl ("dd" | "DD") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenDd
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("dd")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("DD")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenDd unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseDd = "<" Spnl "/" ("dd" | "DD") Spnl ">"
- def _HtmlBlockCloseDd
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("dd")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("DD")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseDd unless _tmp
- return _tmp
- end
-
- # HtmlBlockDd = HtmlBlockOpenDd (HtmlBlockDd | !HtmlBlockCloseDd .)* HtmlBlockCloseDd
- def _HtmlBlockDd
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenDd)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockDd)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseDd)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseDd)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockDd unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenDt = "<" Spnl ("dt" | "DT") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenDt
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("dt")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("DT")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenDt unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseDt = "<" Spnl "/" ("dt" | "DT") Spnl ">"
- def _HtmlBlockCloseDt
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("dt")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("DT")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseDt unless _tmp
- return _tmp
- end
-
- # HtmlBlockDt = HtmlBlockOpenDt (HtmlBlockDt | !HtmlBlockCloseDt .)* HtmlBlockCloseDt
- def _HtmlBlockDt
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenDt)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockDt)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseDt)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseDt)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockDt unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenFrameset = "<" Spnl ("frameset" | "FRAMESET") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenFrameset
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("frameset")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("FRAMESET")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenFrameset unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseFrameset = "<" Spnl "/" ("frameset" | "FRAMESET") Spnl ">"
- def _HtmlBlockCloseFrameset
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("frameset")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("FRAMESET")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseFrameset unless _tmp
- return _tmp
- end
-
- # HtmlBlockFrameset = HtmlBlockOpenFrameset (HtmlBlockFrameset | !HtmlBlockCloseFrameset .)* HtmlBlockCloseFrameset
- def _HtmlBlockFrameset
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenFrameset)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockFrameset)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseFrameset)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseFrameset)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockFrameset unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenLi = "<" Spnl ("li" | "LI") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenLi
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("li")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("LI")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenLi unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseLi = "<" Spnl "/" ("li" | "LI") Spnl ">"
- def _HtmlBlockCloseLi
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("li")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("LI")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseLi unless _tmp
- return _tmp
- end
-
- # HtmlBlockLi = HtmlBlockOpenLi (HtmlBlockLi | !HtmlBlockCloseLi .)* HtmlBlockCloseLi
- def _HtmlBlockLi
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenLi)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockLi)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseLi)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseLi)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockLi unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenTbody = "<" Spnl ("tbody" | "TBODY") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenTbody
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("tbody")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("TBODY")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenTbody unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseTbody = "<" Spnl "/" ("tbody" | "TBODY") Spnl ">"
- def _HtmlBlockCloseTbody
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("tbody")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("TBODY")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseTbody unless _tmp
- return _tmp
- end
-
- # HtmlBlockTbody = HtmlBlockOpenTbody (HtmlBlockTbody | !HtmlBlockCloseTbody .)* HtmlBlockCloseTbody
- def _HtmlBlockTbody
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenTbody)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockTbody)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseTbody)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseTbody)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockTbody unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenTd = "<" Spnl ("td" | "TD") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenTd
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("td")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("TD")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenTd unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseTd = "<" Spnl "/" ("td" | "TD") Spnl ">"
- def _HtmlBlockCloseTd
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("td")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("TD")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseTd unless _tmp
- return _tmp
- end
-
- # HtmlBlockTd = HtmlBlockOpenTd (HtmlBlockTd | !HtmlBlockCloseTd .)* HtmlBlockCloseTd
- def _HtmlBlockTd
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenTd)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockTd)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseTd)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseTd)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockTd unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenTfoot = "<" Spnl ("tfoot" | "TFOOT") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenTfoot
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("tfoot")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("TFOOT")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenTfoot unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseTfoot = "<" Spnl "/" ("tfoot" | "TFOOT") Spnl ">"
- def _HtmlBlockCloseTfoot
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("tfoot")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("TFOOT")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseTfoot unless _tmp
- return _tmp
- end
-
- # HtmlBlockTfoot = HtmlBlockOpenTfoot (HtmlBlockTfoot | !HtmlBlockCloseTfoot .)* HtmlBlockCloseTfoot
- def _HtmlBlockTfoot
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenTfoot)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockTfoot)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseTfoot)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseTfoot)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockTfoot unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenTh = "<" Spnl ("th" | "TH") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenTh
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("th")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("TH")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenTh unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseTh = "<" Spnl "/" ("th" | "TH") Spnl ">"
- def _HtmlBlockCloseTh
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("th")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("TH")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseTh unless _tmp
- return _tmp
- end
-
- # HtmlBlockTh = HtmlBlockOpenTh (HtmlBlockTh | !HtmlBlockCloseTh .)* HtmlBlockCloseTh
- def _HtmlBlockTh
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenTh)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockTh)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseTh)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseTh)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockTh unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenThead = "<" Spnl ("thead" | "THEAD") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenThead
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("thead")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("THEAD")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenThead unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseThead = "<" Spnl "/" ("thead" | "THEAD") Spnl ">"
- def _HtmlBlockCloseThead
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("thead")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("THEAD")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseThead unless _tmp
- return _tmp
- end
-
- # HtmlBlockThead = HtmlBlockOpenThead (HtmlBlockThead | !HtmlBlockCloseThead .)* HtmlBlockCloseThead
- def _HtmlBlockThead
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenThead)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockThead)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseThead)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseThead)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockThead unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenTr = "<" Spnl ("tr" | "TR") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenTr
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("tr")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("TR")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenTr unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseTr = "<" Spnl "/" ("tr" | "TR") Spnl ">"
- def _HtmlBlockCloseTr
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("tr")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("TR")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseTr unless _tmp
- return _tmp
- end
-
- # HtmlBlockTr = HtmlBlockOpenTr (HtmlBlockTr | !HtmlBlockCloseTr .)* HtmlBlockCloseTr
- def _HtmlBlockTr
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenTr)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockTr)
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_HtmlBlockCloseTr)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseTr)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockTr unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenScript = "<" Spnl ("script" | "SCRIPT") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenScript
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("script")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("SCRIPT")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenScript unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseScript = "<" Spnl "/" ("script" | "SCRIPT") Spnl ">"
- def _HtmlBlockCloseScript
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("script")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("SCRIPT")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseScript unless _tmp
- return _tmp
- end
-
- # HtmlBlockScript = HtmlBlockOpenScript (!HtmlBlockCloseScript .)* HtmlBlockCloseScript
- def _HtmlBlockScript
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenScript)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # sequence
- _save3 = self.pos
- _tmp = apply(:_HtmlBlockCloseScript)
- _tmp = _tmp ? nil : true
- self.pos = _save3
- unless _tmp
- self.pos = _save2
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save2
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseScript)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockScript unless _tmp
- return _tmp
- end
-
- # HtmlBlockOpenHead = "<" Spnl ("head" | "HEAD") Spnl HtmlAttribute* ">"
- def _HtmlBlockOpenHead
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("head")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("HEAD")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockOpenHead unless _tmp
- return _tmp
- end
-
- # HtmlBlockCloseHead = "<" Spnl "/" ("head" | "HEAD") Spnl ">"
- def _HtmlBlockCloseHead
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("head")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("HEAD")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockCloseHead unless _tmp
- return _tmp
- end
-
- # HtmlBlockHead = HtmlBlockOpenHead (!HtmlBlockCloseHead .)* HtmlBlockCloseHead
- def _HtmlBlockHead
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_HtmlBlockOpenHead)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # sequence
- _save3 = self.pos
- _tmp = apply(:_HtmlBlockCloseHead)
- _tmp = _tmp ? nil : true
- self.pos = _save3
- unless _tmp
- self.pos = _save2
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save2
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockCloseHead)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockHead unless _tmp
- return _tmp
- end
-
- # HtmlBlockInTags = (HtmlAnchor | HtmlBlockAddress | HtmlBlockBlockquote | HtmlBlockCenter | HtmlBlockDir | HtmlBlockDiv | HtmlBlockDl | HtmlBlockFieldset | HtmlBlockForm | HtmlBlockH1 | HtmlBlockH2 | HtmlBlockH3 | HtmlBlockH4 | HtmlBlockH5 | HtmlBlockH6 | HtmlBlockMenu | HtmlBlockNoframes | HtmlBlockNoscript | HtmlBlockOl | HtmlBlockP | HtmlBlockPre | HtmlBlockTable | HtmlBlockUl | HtmlBlockDd | HtmlBlockDt | HtmlBlockFrameset | HtmlBlockLi | HtmlBlockTbody | HtmlBlockTd | HtmlBlockTfoot | HtmlBlockTh | HtmlBlockThead | HtmlBlockTr | HtmlBlockScript | HtmlBlockHead)
- def _HtmlBlockInTags
-
- _save = self.pos
- while true # choice
- _tmp = apply(:_HtmlAnchor)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockAddress)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockBlockquote)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockCenter)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockDir)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockDiv)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockDl)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockFieldset)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockForm)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockH1)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockH2)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockH3)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockH4)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockH5)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockH6)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockMenu)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockNoframes)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockNoscript)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockOl)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockP)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockPre)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockTable)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockUl)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockDd)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockDt)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockFrameset)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockLi)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockTbody)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockTd)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockTfoot)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockTh)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockThead)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockTr)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockScript)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_HtmlBlockHead)
- break if _tmp
- self.pos = _save
- break
- end # end choice
-
- set_failed_rule :_HtmlBlockInTags unless _tmp
- return _tmp
- end
-
- # HtmlBlock = < (HtmlBlockInTags | HtmlComment | HtmlBlockSelfClosing | HtmlUnclosed) > @BlankLine+ { if html? then RDoc::Markup::Raw.new text end }
- def _HtmlBlock
-
- _save = self.pos
- while true # sequence
- _text_start = self.pos
-
- _save1 = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlockInTags)
- break if _tmp
- self.pos = _save1
- _tmp = apply(:_HtmlComment)
- break if _tmp
- self.pos = _save1
- _tmp = apply(:_HtmlBlockSelfClosing)
- break if _tmp
- self.pos = _save1
- _tmp = apply(:_HtmlUnclosed)
- 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
- _save2 = self.pos
- _tmp = _BlankLine()
- if _tmp
- while true
- _tmp = _BlankLine()
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save2
- end
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; if html? then
- RDoc::Markup::Raw.new text
- end ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlock unless _tmp
- return _tmp
- end
-
- # HtmlUnclosed = "<" Spnl HtmlUnclosedType Spnl HtmlAttribute* Spnl ">"
- def _HtmlUnclosed
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlUnclosedType)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlUnclosed unless _tmp
- return _tmp
- end
-
- # HtmlUnclosedType = ("HR" | "hr")
- def _HtmlUnclosedType
-
- _save = self.pos
- while true # choice
- _tmp = match_string("HR")
- break if _tmp
- self.pos = _save
- _tmp = match_string("hr")
- break if _tmp
- self.pos = _save
- break
- end # end choice
-
- set_failed_rule :_HtmlUnclosedType unless _tmp
- return _tmp
- end
-
- # HtmlBlockSelfClosing = "<" Spnl HtmlBlockType Spnl HtmlAttribute* "/" Spnl ">"
- def _HtmlBlockSelfClosing
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_HtmlBlockType)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlBlockSelfClosing unless _tmp
- return _tmp
- end
-
- # HtmlBlockType = ("ADDRESS" | "BLOCKQUOTE" | "CENTER" | "DD" | "DIR" | "DIV" | "DL" | "DT" | "FIELDSET" | "FORM" | "FRAMESET" | "H1" | "H2" | "H3" | "H4" | "H5" | "H6" | "HR" | "ISINDEX" | "LI" | "MENU" | "NOFRAMES" | "NOSCRIPT" | "OL" | "P" | "PRE" | "SCRIPT" | "TABLE" | "TBODY" | "TD" | "TFOOT" | "TH" | "THEAD" | "TR" | "UL" | "address" | "blockquote" | "center" | "dd" | "dir" | "div" | "dl" | "dt" | "fieldset" | "form" | "frameset" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "hr" | "isindex" | "li" | "menu" | "noframes" | "noscript" | "ol" | "p" | "pre" | "script" | "table" | "tbody" | "td" | "tfoot" | "th" | "thead" | "tr" | "ul")
- def _HtmlBlockType
-
- _save = self.pos
- while true # choice
- _tmp = match_string("ADDRESS")
- break if _tmp
- self.pos = _save
- _tmp = match_string("BLOCKQUOTE")
- break if _tmp
- self.pos = _save
- _tmp = match_string("CENTER")
- break if _tmp
- self.pos = _save
- _tmp = match_string("DD")
- break if _tmp
- self.pos = _save
- _tmp = match_string("DIR")
- break if _tmp
- self.pos = _save
- _tmp = match_string("DIV")
- break if _tmp
- self.pos = _save
- _tmp = match_string("DL")
- break if _tmp
- self.pos = _save
- _tmp = match_string("DT")
- break if _tmp
- self.pos = _save
- _tmp = match_string("FIELDSET")
- break if _tmp
- self.pos = _save
- _tmp = match_string("FORM")
- break if _tmp
- self.pos = _save
- _tmp = match_string("FRAMESET")
- break if _tmp
- self.pos = _save
- _tmp = match_string("H1")
- break if _tmp
- self.pos = _save
- _tmp = match_string("H2")
- break if _tmp
- self.pos = _save
- _tmp = match_string("H3")
- break if _tmp
- self.pos = _save
- _tmp = match_string("H4")
- break if _tmp
- self.pos = _save
- _tmp = match_string("H5")
- break if _tmp
- self.pos = _save
- _tmp = match_string("H6")
- break if _tmp
- self.pos = _save
- _tmp = match_string("HR")
- break if _tmp
- self.pos = _save
- _tmp = match_string("ISINDEX")
- break if _tmp
- self.pos = _save
- _tmp = match_string("LI")
- break if _tmp
- self.pos = _save
- _tmp = match_string("MENU")
- break if _tmp
- self.pos = _save
- _tmp = match_string("NOFRAMES")
- break if _tmp
- self.pos = _save
- _tmp = match_string("NOSCRIPT")
- break if _tmp
- self.pos = _save
- _tmp = match_string("OL")
- break if _tmp
- self.pos = _save
- _tmp = match_string("P")
- break if _tmp
- self.pos = _save
- _tmp = match_string("PRE")
- break if _tmp
- self.pos = _save
- _tmp = match_string("SCRIPT")
- break if _tmp
- self.pos = _save
- _tmp = match_string("TABLE")
- break if _tmp
- self.pos = _save
- _tmp = match_string("TBODY")
- break if _tmp
- self.pos = _save
- _tmp = match_string("TD")
- break if _tmp
- self.pos = _save
- _tmp = match_string("TFOOT")
- break if _tmp
- self.pos = _save
- _tmp = match_string("TH")
- break if _tmp
- self.pos = _save
- _tmp = match_string("THEAD")
- break if _tmp
- self.pos = _save
- _tmp = match_string("TR")
- break if _tmp
- self.pos = _save
- _tmp = match_string("UL")
- break if _tmp
- self.pos = _save
- _tmp = match_string("address")
- break if _tmp
- self.pos = _save
- _tmp = match_string("blockquote")
- break if _tmp
- self.pos = _save
- _tmp = match_string("center")
- break if _tmp
- self.pos = _save
- _tmp = match_string("dd")
- break if _tmp
- self.pos = _save
- _tmp = match_string("dir")
- break if _tmp
- self.pos = _save
- _tmp = match_string("div")
- break if _tmp
- self.pos = _save
- _tmp = match_string("dl")
- break if _tmp
- self.pos = _save
- _tmp = match_string("dt")
- break if _tmp
- self.pos = _save
- _tmp = match_string("fieldset")
- break if _tmp
- self.pos = _save
- _tmp = match_string("form")
- break if _tmp
- self.pos = _save
- _tmp = match_string("frameset")
- break if _tmp
- self.pos = _save
- _tmp = match_string("h1")
- break if _tmp
- self.pos = _save
- _tmp = match_string("h2")
- break if _tmp
- self.pos = _save
- _tmp = match_string("h3")
- break if _tmp
- self.pos = _save
- _tmp = match_string("h4")
- break if _tmp
- self.pos = _save
- _tmp = match_string("h5")
- break if _tmp
- self.pos = _save
- _tmp = match_string("h6")
- break if _tmp
- self.pos = _save
- _tmp = match_string("hr")
- break if _tmp
- self.pos = _save
- _tmp = match_string("isindex")
- break if _tmp
- self.pos = _save
- _tmp = match_string("li")
- break if _tmp
- self.pos = _save
- _tmp = match_string("menu")
- break if _tmp
- self.pos = _save
- _tmp = match_string("noframes")
- break if _tmp
- self.pos = _save
- _tmp = match_string("noscript")
- break if _tmp
- self.pos = _save
- _tmp = match_string("ol")
- break if _tmp
- self.pos = _save
- _tmp = match_string("p")
- break if _tmp
- self.pos = _save
- _tmp = match_string("pre")
- break if _tmp
- self.pos = _save
- _tmp = match_string("script")
- break if _tmp
- self.pos = _save
- _tmp = match_string("table")
- break if _tmp
- self.pos = _save
- _tmp = match_string("tbody")
- break if _tmp
- self.pos = _save
- _tmp = match_string("td")
- break if _tmp
- self.pos = _save
- _tmp = match_string("tfoot")
- break if _tmp
- self.pos = _save
- _tmp = match_string("th")
- break if _tmp
- self.pos = _save
- _tmp = match_string("thead")
- break if _tmp
- self.pos = _save
- _tmp = match_string("tr")
- break if _tmp
- self.pos = _save
- _tmp = match_string("ul")
- break if _tmp
- self.pos = _save
- break
- end # end choice
-
- set_failed_rule :_HtmlBlockType unless _tmp
- return _tmp
- end
-
- # StyleOpen = "<" Spnl ("style" | "STYLE") Spnl HtmlAttribute* ">"
- def _StyleOpen
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("style")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("STYLE")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_StyleOpen unless _tmp
- return _tmp
- end
-
- # StyleClose = "<" Spnl "/" ("style" | "STYLE") Spnl ">"
- def _StyleClose
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("/")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = match_string("style")
- break if _tmp
- self.pos = _save1
- _tmp = match_string("STYLE")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_StyleClose unless _tmp
- return _tmp
- end
-
- # InStyleTags = StyleOpen (!StyleClose .)* StyleClose
- def _InStyleTags
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_StyleOpen)
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # sequence
- _save3 = self.pos
- _tmp = apply(:_StyleClose)
- _tmp = _tmp ? nil : true
- self.pos = _save3
- unless _tmp
- self.pos = _save2
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save2
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_StyleClose)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_InStyleTags unless _tmp
- return _tmp
- end
-
- # StyleBlock = < InStyleTags > @BlankLine* { if css? then RDoc::Markup::Raw.new text end }
- def _StyleBlock
-
- _save = self.pos
- while true # sequence
- _text_start = self.pos
- _tmp = apply(:_InStyleTags)
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = _BlankLine()
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; if css? then
- RDoc::Markup::Raw.new text
- end ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_StyleBlock unless _tmp
- return _tmp
- end
-
- # Inlines = (!@Endline Inline:i { i } | @Endline:c !(&{ github? } Ticks3 /[^`\n]*$/) &Inline { c })+:chunks @Endline? { chunks }
- def _Inlines
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
- _ary = []
-
- _save2 = self.pos
- while true # choice
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = _Endline()
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = apply(:_Inline)
- i = @result
- unless _tmp
- self.pos = _save3
- break
- end
- @result = begin; i ; end
- _tmp = true
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
-
- _save5 = self.pos
- while true # sequence
- _tmp = _Endline()
- c = @result
- unless _tmp
- self.pos = _save5
- break
- end
- _save6 = self.pos
-
- _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
- self.pos = _save5
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- if _tmp
- _ary << @result
- while true
-
- _save10 = self.pos
- while true # choice
-
- _save11 = self.pos
- while true # sequence
- _save12 = self.pos
- _tmp = _Endline()
- _tmp = _tmp ? nil : true
- self.pos = _save12
- unless _tmp
- self.pos = _save11
- break
- end
- _tmp = apply(:_Inline)
- i = @result
- unless _tmp
- self.pos = _save11
- break
- end
- @result = begin; i ; end
- _tmp = true
- unless _tmp
- self.pos = _save11
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save10
-
- _save13 = self.pos
- while true # sequence
- _tmp = _Endline()
- c = @result
- unless _tmp
- self.pos = _save13
- break
- end
- _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 = _save17
- unless _tmp
- self.pos = _save13
- break
- end
- @result = begin; c ; end
- _tmp = true
- unless _tmp
- self.pos = _save13
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save10
- break
- end # end choice
-
- _ary << @result if _tmp
- break unless _tmp
- end
- _tmp = true
- @result = _ary
- else
- self.pos = _save1
- end
- chunks = @result
- unless _tmp
- self.pos = _save
- break
- end
- _save18 = self.pos
- _tmp = _Endline()
- unless _tmp
- _tmp = true
- self.pos = _save18
- end
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; chunks ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Inlines unless _tmp
- return _tmp
- end
-
- # Inline = (Str | @Endline | UlOrStarLine | @Space | Strong | Emph | Strike | Image | Link | NoteReference | InlineNote | Code | RawHtml | Entity | EscapedChar | Symbol)
- def _Inline
-
- _save = self.pos
- while true # choice
- _tmp = apply(:_Str)
- break if _tmp
- self.pos = _save
- _tmp = _Endline()
- break if _tmp
- self.pos = _save
- _tmp = apply(:_UlOrStarLine)
- break if _tmp
- self.pos = _save
- _tmp = _Space()
- break if _tmp
- self.pos = _save
- _tmp = apply(:_Strong)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_Emph)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_Strike)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_Image)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_Link)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_NoteReference)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_InlineNote)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_Code)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_RawHtml)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_Entity)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_EscapedChar)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_Symbol)
- break if _tmp
- self.pos = _save
- break
- end # end choice
-
- set_failed_rule :_Inline unless _tmp
- return _tmp
- end
-
- # Space = @Spacechar+ { " " }
- def _Space
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
- _tmp = _Spacechar()
- if _tmp
- while true
- _tmp = _Spacechar()
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save1
- end
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; " " ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Space unless _tmp
- return _tmp
- end
-
- # Str = @StartList:a < @NormalChar+ > { a = text } (StrChunk:c { a << c })* { a }
- def _Str
-
- _save = self.pos
- while true # sequence
- _tmp = _StartList()
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- _text_start = self.pos
- _save1 = self.pos
- _tmp = _NormalChar()
- if _tmp
- while true
- _tmp = _NormalChar()
- 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; a = text ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save3 = self.pos
- while true # sequence
- _tmp = apply(:_StrChunk)
- c = @result
- unless _tmp
- self.pos = _save3
- break
- end
- @result = begin; a << c ; end
- _tmp = true
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; a ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Str unless _tmp
- return _tmp
- end
-
- # StrChunk = < (@NormalChar | /_+/ &Alphanumeric)+ > { text }
- def _StrChunk
-
- _save = self.pos
- while true # sequence
- _text_start = self.pos
- _save1 = self.pos
-
- _save2 = self.pos
- while true # choice
- _tmp = _NormalChar()
- break if _tmp
- self.pos = _save2
-
- _save3 = self.pos
- while true # sequence
- _tmp = scan(/\G(?-mix:_+)/)
- unless _tmp
- self.pos = _save3
- break
- end
- _save4 = self.pos
- _tmp = apply(:_Alphanumeric)
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- if _tmp
- while true
-
- _save5 = self.pos
- while true # choice
- _tmp = _NormalChar()
- break if _tmp
- self.pos = _save5
-
- _save6 = self.pos
- while true # sequence
- _tmp = scan(/\G(?-mix:_+)/)
- unless _tmp
- self.pos = _save6
- break
- end
- _save7 = self.pos
- _tmp = apply(:_Alphanumeric)
- self.pos = _save7
- unless _tmp
- self.pos = _save6
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save5
- break
- end # end choice
-
- 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 ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_StrChunk unless _tmp
- return _tmp
- end
-
- # EscapedChar = "\\" !@Newline < /[:\\`|*_{}\[\]()#+.!><-]/ > { text }
- def _EscapedChar
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("\\")
- unless _tmp
- self.pos = _save
- break
- end
- _save1 = self.pos
- _tmp = _Newline()
- _tmp = _tmp ? nil : true
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- _text_start = self.pos
- _tmp = scan(/\G(?-mix:[:\\`|*_{}\[\]()#+.!><-])/)
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; text ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_EscapedChar unless _tmp
- return _tmp
- end
-
- # Entity = (HexEntity | DecEntity | CharEntity):a { a }
- def _Entity
-
- _save = self.pos
- while true # sequence
-
- _save1 = self.pos
- while true # choice
- _tmp = apply(:_HexEntity)
- break if _tmp
- self.pos = _save1
- _tmp = apply(:_DecEntity)
- break if _tmp
- self.pos = _save1
- _tmp = apply(:_CharEntity)
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; a ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Entity unless _tmp
- return _tmp
- end
-
- # Endline = (@LineBreak | @TerminalEndline | @NormalEndline)
- def _Endline
-
- _save = self.pos
- while true # choice
- _tmp = _LineBreak()
- break if _tmp
- self.pos = _save
- _tmp = _TerminalEndline()
- break if _tmp
- self.pos = _save
- _tmp = _NormalEndline()
- break if _tmp
- self.pos = _save
- break
- end # end choice
-
- set_failed_rule :_Endline unless _tmp
- return _tmp
- end
-
- # NormalEndline = @Sp @Newline !@BlankLine !">" !AtxStart !(Line /={1,}|-{1,}/ @Newline) { "\n" }
- def _NormalEndline
-
- _save = self.pos
- while true # sequence
- _tmp = _Sp()
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _Newline()
- unless _tmp
- self.pos = _save
- break
- end
- _save1 = self.pos
- _tmp = _BlankLine()
- _tmp = _tmp ? nil : true
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- _save2 = self.pos
- _tmp = match_string(">")
- _tmp = _tmp ? nil : true
- self.pos = _save2
- unless _tmp
- self.pos = _save
- break
- end
- _save3 = self.pos
- _tmp = apply(:_AtxStart)
- _tmp = _tmp ? nil : true
- self.pos = _save3
- unless _tmp
- self.pos = _save
- break
- end
- _save4 = self.pos
-
- _save5 = self.pos
- while true # sequence
- _tmp = apply(:_Line)
- unless _tmp
- self.pos = _save5
- break
- end
- _tmp = scan(/\G(?-mix:={1,}|-{1,})/)
- unless _tmp
- self.pos = _save5
- break
- end
- _tmp = _Newline()
- unless _tmp
- self.pos = _save5
- end
- break
- end # end sequence
-
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; "\n" ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_NormalEndline unless _tmp
- return _tmp
- end
-
- # TerminalEndline = @Sp @Newline @Eof
- def _TerminalEndline
-
- _save = self.pos
- while true # sequence
- _tmp = _Sp()
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _Newline()
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _Eof()
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_TerminalEndline unless _tmp
- return _tmp
- end
-
- # LineBreak = " " @NormalEndline { RDoc::Markup::HardBreak.new }
- def _LineBreak
-
- _save = self.pos
- while true # sequence
- _tmp = match_string(" ")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _NormalEndline()
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; RDoc::Markup::HardBreak.new ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_LineBreak unless _tmp
- return _tmp
- end
-
- # Symbol = < @SpecialChar > { text }
- def _Symbol
-
- _save = self.pos
- while true # sequence
- _text_start = self.pos
- _tmp = _SpecialChar()
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; text ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Symbol unless _tmp
- return _tmp
- end
-
- # UlOrStarLine = (UlLine | StarLine):a { a }
- def _UlOrStarLine
-
- _save = self.pos
- while true # sequence
-
- _save1 = self.pos
- while true # choice
- _tmp = apply(:_UlLine)
- break if _tmp
- self.pos = _save1
- _tmp = apply(:_StarLine)
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; a ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_UlOrStarLine unless _tmp
- return _tmp
- end
-
- # StarLine = (< /\*{4,}/ > { text } | < @Spacechar /\*+/ &@Spacechar > { text })
- def _StarLine
-
- _save = self.pos
- while true # choice
-
- _save1 = self.pos
- while true # sequence
- _text_start = self.pos
- _tmp = scan(/\G(?-mix:\*{4,})/)
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save1
- break
- end
- @result = begin; text ; end
- _tmp = true
- unless _tmp
- self.pos = _save1
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save
-
- _save2 = self.pos
- while true # sequence
- _text_start = self.pos
-
- _save3 = self.pos
- while true # sequence
- _tmp = _Spacechar()
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = scan(/\G(?-mix:\*+)/)
- unless _tmp
- self.pos = _save3
- break
- end
- _save4 = self.pos
- _tmp = _Spacechar()
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save2
- break
- end
- @result = begin; text ; end
- _tmp = true
- unless _tmp
- self.pos = _save2
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save
- break
- end # end choice
-
- set_failed_rule :_StarLine unless _tmp
- return _tmp
- end
-
- # UlLine = (< /_{4,}/ > { text } | < @Spacechar /_+/ &@Spacechar > { text })
- def _UlLine
-
- _save = self.pos
- while true # choice
-
- _save1 = self.pos
- while true # sequence
- _text_start = self.pos
- _tmp = scan(/\G(?-mix:_{4,})/)
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save1
- break
- end
- @result = begin; text ; end
- _tmp = true
- unless _tmp
- self.pos = _save1
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save
-
- _save2 = self.pos
- while true # sequence
- _text_start = self.pos
-
- _save3 = self.pos
- while true # sequence
- _tmp = _Spacechar()
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = scan(/\G(?-mix:_+)/)
- unless _tmp
- self.pos = _save3
- break
- end
- _save4 = self.pos
- _tmp = _Spacechar()
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save2
- break
- end
- @result = begin; text ; end
- _tmp = true
- unless _tmp
- self.pos = _save2
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save
- break
- end # end choice
-
- set_failed_rule :_UlLine unless _tmp
- return _tmp
- end
-
- # Emph = (EmphStar | EmphUl)
- def _Emph
-
- _save = self.pos
- while true # choice
- _tmp = apply(:_EmphStar)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_EmphUl)
- break if _tmp
- self.pos = _save
- break
- end # end choice
-
- set_failed_rule :_Emph unless _tmp
- return _tmp
- end
-
- # Whitespace = (@Spacechar | @Newline)
- def _Whitespace
-
- _save = self.pos
- while true # choice
- _tmp = _Spacechar()
- break if _tmp
- self.pos = _save
- _tmp = _Newline()
- break if _tmp
- self.pos = _save
- break
- end # end choice
-
- set_failed_rule :_Whitespace unless _tmp
- return _tmp
- end
-
- # EmphStar = "*" !@Whitespace @StartList:a (!"*" Inline:b { a << b } | StrongStar:b { a << b })+ "*" { emphasis a.join }
- def _EmphStar
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("*")
- unless _tmp
- self.pos = _save
- break
- end
- _save1 = self.pos
- _tmp = _Whitespace()
- _tmp = _tmp ? nil : true
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _StartList()
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- _save2 = self.pos
-
- _save3 = self.pos
- while true # choice
-
- _save4 = self.pos
- while true # sequence
- _save5 = self.pos
- _tmp = match_string("*")
- _tmp = _tmp ? nil : true
- self.pos = _save5
- unless _tmp
- self.pos = _save4
- break
- end
- _tmp = apply(:_Inline)
- b = @result
- unless _tmp
- self.pos = _save4
- break
- end
- @result = begin; a << b ; end
- _tmp = true
- unless _tmp
- self.pos = _save4
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save3
-
- _save6 = self.pos
- while true # sequence
- _tmp = apply(:_StrongStar)
- b = @result
- unless _tmp
- self.pos = _save6
- break
- end
- @result = begin; a << b ; end
- _tmp = true
- unless _tmp
- self.pos = _save6
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save3
- break
- end # end choice
-
- if _tmp
- while true
-
- _save7 = self.pos
- while true # choice
-
- _save8 = self.pos
- while true # sequence
- _save9 = self.pos
- _tmp = match_string("*")
- _tmp = _tmp ? nil : true
- self.pos = _save9
- unless _tmp
- self.pos = _save8
- break
- end
- _tmp = apply(:_Inline)
- b = @result
- unless _tmp
- self.pos = _save8
- break
- end
- @result = begin; a << b ; end
- _tmp = true
- unless _tmp
- self.pos = _save8
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save7
-
- _save10 = self.pos
- while true # sequence
- _tmp = apply(:_StrongStar)
- b = @result
- unless _tmp
- self.pos = _save10
- break
- end
- @result = begin; a << b ; end
- _tmp = true
- unless _tmp
- self.pos = _save10
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save7
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save2
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("*")
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; emphasis a.join ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_EmphStar unless _tmp
- return _tmp
- end
-
- # EmphUl = "_" !@Whitespace @StartList:a (!"_" Inline:b { a << b } | StrongUl:b { a << b })+ "_" { emphasis a.join }
- def _EmphUl
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("_")
- unless _tmp
- self.pos = _save
- break
- end
- _save1 = self.pos
- _tmp = _Whitespace()
- _tmp = _tmp ? nil : true
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _StartList()
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- _save2 = self.pos
-
- _save3 = self.pos
- while true # choice
-
- _save4 = self.pos
- while true # sequence
- _save5 = self.pos
- _tmp = match_string("_")
- _tmp = _tmp ? nil : true
- self.pos = _save5
- unless _tmp
- self.pos = _save4
- break
- end
- _tmp = apply(:_Inline)
- b = @result
- unless _tmp
- self.pos = _save4
- break
- end
- @result = begin; a << b ; end
- _tmp = true
- unless _tmp
- self.pos = _save4
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save3
-
- _save6 = self.pos
- while true # sequence
- _tmp = apply(:_StrongUl)
- b = @result
- unless _tmp
- self.pos = _save6
- break
- end
- @result = begin; a << b ; end
- _tmp = true
- unless _tmp
- self.pos = _save6
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save3
- break
- end # end choice
-
- if _tmp
- while true
-
- _save7 = self.pos
- while true # choice
-
- _save8 = self.pos
- while true # sequence
- _save9 = self.pos
- _tmp = match_string("_")
- _tmp = _tmp ? nil : true
- self.pos = _save9
- unless _tmp
- self.pos = _save8
- break
- end
- _tmp = apply(:_Inline)
- b = @result
- unless _tmp
- self.pos = _save8
- break
- end
- @result = begin; a << b ; end
- _tmp = true
- unless _tmp
- self.pos = _save8
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save7
-
- _save10 = self.pos
- while true # sequence
- _tmp = apply(:_StrongUl)
- b = @result
- unless _tmp
- self.pos = _save10
- break
- end
- @result = begin; a << b ; end
- _tmp = true
- unless _tmp
- self.pos = _save10
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save7
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save2
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("_")
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; emphasis a.join ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_EmphUl unless _tmp
- return _tmp
- end
-
- # Strong = (StrongStar | StrongUl)
- def _Strong
-
- _save = self.pos
- while true # choice
- _tmp = apply(:_StrongStar)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_StrongUl)
- break if _tmp
- self.pos = _save
- break
- end # end choice
-
- set_failed_rule :_Strong unless _tmp
- return _tmp
- end
-
- # StrongStar = "**" !@Whitespace @StartList:a (!"**" Inline:b { a << b })+ "**" { strong a.join }
- def _StrongStar
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("**")
- unless _tmp
- self.pos = _save
- break
- end
- _save1 = self.pos
- _tmp = _Whitespace()
- _tmp = _tmp ? nil : true
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _StartList()
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- _save2 = self.pos
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = match_string("**")
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = apply(:_Inline)
- b = @result
- unless _tmp
- self.pos = _save3
- break
- end
- @result = begin; a << b ; end
- _tmp = true
- unless _tmp
- self.pos = _save3
- 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
- _tmp = apply(:_Inline)
- b = @result
- unless _tmp
- self.pos = _save5
- break
- end
- @result = begin; a << b ; end
- _tmp = true
- unless _tmp
- self.pos = _save5
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save2
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("**")
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; strong a.join ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_StrongStar unless _tmp
- return _tmp
- end
-
- # StrongUl = "__" !@Whitespace @StartList:a (!"__" Inline:b { a << b })+ "__" { strong a.join }
- def _StrongUl
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("__")
- unless _tmp
- self.pos = _save
- break
- end
- _save1 = self.pos
- _tmp = _Whitespace()
- _tmp = _tmp ? nil : true
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _StartList()
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- _save2 = self.pos
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = match_string("__")
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = apply(:_Inline)
- b = @result
- unless _tmp
- self.pos = _save3
- break
- end
- @result = begin; a << b ; end
- _tmp = true
- unless _tmp
- self.pos = _save3
- 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
- _tmp = apply(:_Inline)
- b = @result
- unless _tmp
- self.pos = _save5
- break
- end
- @result = begin; a << b ; end
- _tmp = true
- unless _tmp
- self.pos = _save5
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save2
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("__")
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; strong a.join ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_StrongUl unless _tmp
- return _tmp
- end
-
- # Strike = &{ strike? } "~~" !@Whitespace @StartList:a (!"~~" Inline:b { a << b })+ "~~" { strike a.join }
- def _Strike
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
- _tmp = begin; strike? ; end
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("~~")
- unless _tmp
- self.pos = _save
- break
- end
- _save2 = self.pos
- _tmp = _Whitespace()
- _tmp = _tmp ? nil : true
- self.pos = _save2
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _StartList()
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- _save3 = self.pos
-
- _save4 = self.pos
- while true # sequence
- _save5 = self.pos
- _tmp = match_string("~~")
- _tmp = _tmp ? nil : true
- self.pos = _save5
- unless _tmp
- self.pos = _save4
- break
- end
- _tmp = apply(:_Inline)
- b = @result
- unless _tmp
- self.pos = _save4
- break
- end
- @result = begin; a << b ; end
- _tmp = true
- unless _tmp
- self.pos = _save4
- end
- break
- end # end sequence
-
- if _tmp
- while true
-
- _save6 = self.pos
- while true # sequence
- _save7 = self.pos
- _tmp = match_string("~~")
- _tmp = _tmp ? nil : true
- self.pos = _save7
- unless _tmp
- self.pos = _save6
- break
- end
- _tmp = apply(:_Inline)
- b = @result
- unless _tmp
- self.pos = _save6
- break
- end
- @result = begin; a << b ; end
- _tmp = true
- unless _tmp
- self.pos = _save6
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save3
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("~~")
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; strike a.join ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Strike unless _tmp
- return _tmp
- end
-
- # Image = "!" (ExplicitLink | ReferenceLink):a { "rdoc-image:#{a[/\[(.*)\]/, 1]}" }
- def _Image
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("!")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
- _tmp = apply(:_ExplicitLink)
- break if _tmp
- self.pos = _save1
- _tmp = apply(:_ReferenceLink)
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; "rdoc-image:#{a[/\[(.*)\]/, 1]}" ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Image unless _tmp
- return _tmp
- end
-
- # Link = (ExplicitLink | ReferenceLink | AutoLink)
- def _Link
-
- _save = self.pos
- while true # choice
- _tmp = apply(:_ExplicitLink)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_ReferenceLink)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_AutoLink)
- break if _tmp
- self.pos = _save
- break
- end # end choice
-
- set_failed_rule :_Link unless _tmp
- return _tmp
- end
-
- # ReferenceLink = (ReferenceLinkDouble | ReferenceLinkSingle)
- def _ReferenceLink
-
- _save = self.pos
- while true # choice
- _tmp = apply(:_ReferenceLinkDouble)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_ReferenceLinkSingle)
- break if _tmp
- self.pos = _save
- break
- end # end choice
-
- set_failed_rule :_ReferenceLink unless _tmp
- return _tmp
- end
-
- # ReferenceLinkDouble = Label:content < Spnl > !"[]" Label:label { link_to content, label, text }
- def _ReferenceLinkDouble
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_Label)
- content = @result
- unless _tmp
- self.pos = _save
- break
- end
- _text_start = self.pos
- _tmp = apply(:_Spnl)
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save
- break
- end
- _save1 = self.pos
- _tmp = match_string("[]")
- _tmp = _tmp ? nil : true
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Label)
- label = @result
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; link_to content, label, text ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_ReferenceLinkDouble unless _tmp
- return _tmp
- end
-
- # ReferenceLinkSingle = Label:content < (Spnl "[]")? > { link_to content, content, text }
- def _ReferenceLinkSingle
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_Label)
- content = @result
- unless _tmp
- self.pos = _save
- break
- end
- _text_start = self.pos
- _save1 = self.pos
-
- _save2 = self.pos
- while true # sequence
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save2
- break
- end
- _tmp = match_string("[]")
- unless _tmp
- self.pos = _save2
- end
- break
- end # end sequence
-
- unless _tmp
- _tmp = true
- self.pos = _save1
- end
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; link_to content, content, text ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_ReferenceLinkSingle unless _tmp
- return _tmp
- end
-
- # ExplicitLink = Label:l "(" @Sp Source:s Spnl Title @Sp ")" { "{#{l}}[#{s}]" }
- def _ExplicitLink
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_Label)
- l = @result
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("(")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Source)
- s = @result
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Title)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(")")
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; "{#{l}}[#{s}]" ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_ExplicitLink unless _tmp
- return _tmp
- end
-
- # Source = ("<" < SourceContents > ">" | < SourceContents >) { text }
- def _Source
-
- _save = self.pos
- while true # sequence
-
- _save1 = self.pos
- while true # choice
-
- _save2 = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save2
- break
- end
- _text_start = self.pos
- _tmp = apply(:_SourceContents)
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save2
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save2
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save1
- _text_start = self.pos
- _tmp = apply(:_SourceContents)
- if _tmp
- text = get_text(_text_start)
- end
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; text ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Source unless _tmp
- return _tmp
- end
-
- # SourceContents = ((!"(" !")" !">" Nonspacechar)+ | "(" SourceContents ")")*
- def _SourceContents
- while true
-
- _save1 = self.pos
- while true # choice
- _save2 = self.pos
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = match_string("(")
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _save5 = self.pos
- _tmp = match_string(")")
- _tmp = _tmp ? nil : true
- self.pos = _save5
- unless _tmp
- self.pos = _save3
- break
- end
- _save6 = self.pos
- _tmp = match_string(">")
- _tmp = _tmp ? nil : true
- self.pos = _save6
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- if _tmp
- while true
-
- _save7 = self.pos
- while true # sequence
- _save8 = self.pos
- _tmp = match_string("(")
- _tmp = _tmp ? nil : true
- self.pos = _save8
- unless _tmp
- self.pos = _save7
- break
- end
- _save9 = self.pos
- _tmp = match_string(")")
- _tmp = _tmp ? nil : true
- self.pos = _save9
- unless _tmp
- self.pos = _save7
- break
- end
- _save10 = self.pos
- _tmp = match_string(">")
- _tmp = _tmp ? nil : true
- self.pos = _save10
- unless _tmp
- self.pos = _save7
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save7
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save2
- end
- break if _tmp
- self.pos = _save1
-
- _save11 = self.pos
- while true # sequence
- _tmp = match_string("(")
- unless _tmp
- self.pos = _save11
- break
- end
- _tmp = apply(:_SourceContents)
- unless _tmp
- self.pos = _save11
- break
- end
- _tmp = match_string(")")
- unless _tmp
- self.pos = _save11
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- set_failed_rule :_SourceContents unless _tmp
- return _tmp
- end
-
- # Title = (TitleSingle | TitleDouble | ""):a { a }
- def _Title
-
- _save = self.pos
- while true # sequence
-
- _save1 = self.pos
- while true # choice
- _tmp = apply(:_TitleSingle)
- break if _tmp
- self.pos = _save1
- _tmp = apply(:_TitleDouble)
- break if _tmp
- self.pos = _save1
- _tmp = match_string("")
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; a ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Title unless _tmp
- return _tmp
- end
-
- # TitleSingle = "'" (!("'" @Sp (")" | @Newline)) .)* "'"
- def _TitleSingle
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("'")
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # sequence
- _save3 = self.pos
-
- _save4 = self.pos
- while true # sequence
- _tmp = match_string("'")
- unless _tmp
- self.pos = _save4
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save4
- break
- end
-
- _save5 = self.pos
- while true # choice
- _tmp = match_string(")")
- break if _tmp
- self.pos = _save5
- _tmp = _Newline()
- break if _tmp
- self.pos = _save5
- break
- end # end choice
-
- unless _tmp
- self.pos = _save4
- end
- break
- end # end sequence
-
- _tmp = _tmp ? nil : true
- self.pos = _save3
- unless _tmp
- self.pos = _save2
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save2
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("'")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_TitleSingle unless _tmp
- return _tmp
- end
-
- # TitleDouble = "\"" (!("\"" @Sp (")" | @Newline)) .)* "\""
- def _TitleDouble
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("\"")
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save2 = self.pos
- while true # sequence
- _save3 = self.pos
-
- _save4 = self.pos
- while true # sequence
- _tmp = match_string("\"")
- unless _tmp
- self.pos = _save4
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save4
- break
- end
-
- _save5 = self.pos
- while true # choice
- _tmp = match_string(")")
- break if _tmp
- self.pos = _save5
- _tmp = _Newline()
- break if _tmp
- self.pos = _save5
- break
- end # end choice
-
- unless _tmp
- self.pos = _save4
- end
- break
- end # end sequence
-
- _tmp = _tmp ? nil : true
- self.pos = _save3
- unless _tmp
- self.pos = _save2
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save2
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("\"")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_TitleDouble unless _tmp
- return _tmp
- end
-
- # AutoLink = (AutoLinkUrl | AutoLinkEmail)
- def _AutoLink
-
- _save = self.pos
- while true # choice
- _tmp = apply(:_AutoLinkUrl)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_AutoLinkEmail)
- break if _tmp
- self.pos = _save
- break
- end # end choice
-
- set_failed_rule :_AutoLink unless _tmp
- return _tmp
- end
-
- # AutoLinkUrl = "<" < /[A-Za-z]+/ "://" (!@Newline !">" .)+ > ">" { text }
- def _AutoLinkUrl
-
- _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 # sequence
- _tmp = scan(/\G(?-mix:[A-Za-z]+)/)
- unless _tmp
- self.pos = _save1
- break
- end
- _tmp = match_string("://")
- unless _tmp
- self.pos = _save1
- break
- end
- _save2 = self.pos
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = _Newline()
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _save5 = self.pos
- _tmp = match_string(">")
- _tmp = _tmp ? nil : true
- self.pos = _save5
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- if _tmp
- while true
-
- _save6 = self.pos
- while true # sequence
- _save7 = self.pos
- _tmp = _Newline()
- _tmp = _tmp ? nil : true
- self.pos = _save7
- unless _tmp
- self.pos = _save6
- break
- end
- _save8 = self.pos
- _tmp = match_string(">")
- _tmp = _tmp ? nil : true
- self.pos = _save8
- unless _tmp
- self.pos = _save6
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save6
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save2
- end
- unless _tmp
- self.pos = _save1
- end
- break
- end # end sequence
-
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; text ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_AutoLinkUrl unless _tmp
- return _tmp
- end
-
- # AutoLinkEmail = "<" "mailto:"? < /[\w+.\/!%~$-]+/i "@" (!@Newline !">" .)+ > ">" { "mailto:#{text}" }
- def _AutoLinkEmail
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _save1 = self.pos
- _tmp = match_string("mailto:")
- unless _tmp
- _tmp = true
- self.pos = _save1
- end
- unless _tmp
- self.pos = _save
- break
- end
- _text_start = self.pos
-
- _save2 = self.pos
- while true # sequence
- _tmp = scan(/\G(?i-mx:[\w+.\/!%~$-]+)/)
- unless _tmp
- self.pos = _save2
- break
- end
- _tmp = match_string("@")
- unless _tmp
- self.pos = _save2
- break
- end
- _save3 = self.pos
-
- _save4 = self.pos
- while true # sequence
- _save5 = self.pos
- _tmp = _Newline()
- _tmp = _tmp ? nil : true
- self.pos = _save5
- unless _tmp
- self.pos = _save4
- break
- end
- _save6 = self.pos
- _tmp = match_string(">")
- _tmp = _tmp ? nil : true
- self.pos = _save6
- unless _tmp
- self.pos = _save4
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save4
- end
- break
- end # end sequence
-
- if _tmp
- while true
-
- _save7 = self.pos
- while true # sequence
- _save8 = self.pos
- _tmp = _Newline()
- _tmp = _tmp ? nil : true
- self.pos = _save8
- unless _tmp
- self.pos = _save7
- break
- end
- _save9 = self.pos
- _tmp = match_string(">")
- _tmp = _tmp ? nil : true
- self.pos = _save9
- unless _tmp
- self.pos = _save7
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save7
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save3
- end
- unless _tmp
- self.pos = _save2
- end
- break
- end # end sequence
-
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; "mailto:#{text}" ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_AutoLinkEmail unless _tmp
- return _tmp
- end
-
- # Reference = @NonindentSpace !"[]" Label:label ":" Spnl RefSrc:link RefTitle @BlankLine+ { # TODO use title reference label, link nil }
- def _Reference
-
- _save = self.pos
- while true # sequence
- _tmp = _NonindentSpace()
- unless _tmp
- self.pos = _save
- break
- end
- _save1 = self.pos
- _tmp = match_string("[]")
- _tmp = _tmp ? nil : true
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Label)
- label = @result
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(":")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_RefSrc)
- link = @result
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_RefTitle)
- unless _tmp
- self.pos = _save
- break
- end
- _save2 = self.pos
- _tmp = _BlankLine()
- if _tmp
- while true
- _tmp = _BlankLine()
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save2
- end
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; # TODO use title
- reference label, link
- nil
- ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Reference unless _tmp
- return _tmp
- end
-
- # Label = "[" (!"^" &{ notes? } | &. &{ !notes? }) @StartList:a (!"]" Inline:l { a << l })* "]" { a.join.gsub(/\s+/, ' ') }
- def _Label
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("[")
- unless _tmp
- self.pos = _save
- break
- end
-
- _save1 = self.pos
- while true # choice
-
- _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 = begin; notes? ; end
- self.pos = _save4
- unless _tmp
- self.pos = _save2
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save1
-
- _save5 = self.pos
- while true # sequence
- _save6 = self.pos
- _tmp = get_byte
- self.pos = _save6
- unless _tmp
- self.pos = _save5
- break
- end
- _save7 = self.pos
- _tmp = begin; !notes? ; end
- self.pos = _save7
- unless _tmp
- self.pos = _save5
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _StartList()
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save9 = self.pos
- while true # sequence
- _save10 = self.pos
- _tmp = match_string("]")
- _tmp = _tmp ? nil : true
- self.pos = _save10
- unless _tmp
- self.pos = _save9
- break
- end
- _tmp = apply(:_Inline)
- l = @result
- unless _tmp
- self.pos = _save9
- break
- end
- @result = begin; a << l ; end
- _tmp = true
- unless _tmp
- self.pos = _save9
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("]")
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; a.join.gsub(/\s+/, ' ') ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Label unless _tmp
- return _tmp
- end
-
- # RefSrc = < Nonspacechar+ > { text }
- def _RefSrc
-
- _save = self.pos
- while true # sequence
- _text_start = self.pos
- _save1 = self.pos
- _tmp = apply(:_Nonspacechar)
- if _tmp
- while true
- _tmp = apply(:_Nonspacechar)
- 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 ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_RefSrc unless _tmp
- return _tmp
- end
-
- # RefTitle = (RefTitleSingle | RefTitleDouble | RefTitleParens | EmptyTitle)
- def _RefTitle
-
- _save = self.pos
- while true # choice
- _tmp = apply(:_RefTitleSingle)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_RefTitleDouble)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_RefTitleParens)
- break if _tmp
- self.pos = _save
- _tmp = apply(:_EmptyTitle)
- break if _tmp
- self.pos = _save
- break
- end # end choice
-
- set_failed_rule :_RefTitle unless _tmp
- return _tmp
- end
-
- # EmptyTitle = ""
- def _EmptyTitle
- _tmp = match_string("")
- set_failed_rule :_EmptyTitle unless _tmp
- return _tmp
- end
-
- # RefTitleSingle = Spnl "'" < (!("'" @Sp @Newline | @Newline) .)* > "'" { text }
- def _RefTitleSingle
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("'")
- unless _tmp
- self.pos = _save
- break
- end
- _text_start = self.pos
- while true
-
- _save2 = self.pos
- while true # sequence
- _save3 = self.pos
-
- _save4 = self.pos
- while true # choice
-
- _save5 = self.pos
- while true # sequence
- _tmp = match_string("'")
- unless _tmp
- self.pos = _save5
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save5
- break
- end
- _tmp = _Newline()
- unless _tmp
- self.pos = _save5
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save4
- _tmp = _Newline()
- break if _tmp
- self.pos = _save4
- break
- end # end choice
-
- _tmp = _tmp ? nil : true
- self.pos = _save3
- unless _tmp
- self.pos = _save2
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save2
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("'")
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; text ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_RefTitleSingle unless _tmp
- return _tmp
- end
-
- # RefTitleDouble = Spnl "\"" < (!("\"" @Sp @Newline | @Newline) .)* > "\"" { text }
- def _RefTitleDouble
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("\"")
- unless _tmp
- self.pos = _save
- break
- end
- _text_start = self.pos
- while true
-
- _save2 = self.pos
- while true # sequence
- _save3 = self.pos
-
- _save4 = self.pos
- while true # choice
-
- _save5 = self.pos
- while true # sequence
- _tmp = match_string("\"")
- unless _tmp
- self.pos = _save5
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save5
- break
- end
- _tmp = _Newline()
- unless _tmp
- self.pos = _save5
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save4
- _tmp = _Newline()
- break if _tmp
- self.pos = _save4
- break
- end # end choice
-
- _tmp = _tmp ? nil : true
- self.pos = _save3
- unless _tmp
- self.pos = _save2
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save2
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("\"")
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; text ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_RefTitleDouble unless _tmp
- return _tmp
- end
-
- # RefTitleParens = Spnl "(" < (!(")" @Sp @Newline | @Newline) .)* > ")" { text }
- def _RefTitleParens
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("(")
- unless _tmp
- self.pos = _save
- break
- end
- _text_start = self.pos
- while true
-
- _save2 = self.pos
- while true # sequence
- _save3 = self.pos
-
- _save4 = self.pos
- while true # choice
-
- _save5 = self.pos
- while true # sequence
- _tmp = match_string(")")
- unless _tmp
- self.pos = _save5
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save5
- break
- end
- _tmp = _Newline()
- unless _tmp
- self.pos = _save5
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save4
- _tmp = _Newline()
- break if _tmp
- self.pos = _save4
- break
- end # end choice
-
- _tmp = _tmp ? nil : true
- self.pos = _save3
- unless _tmp
- self.pos = _save2
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save2
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(")")
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; text ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_RefTitleParens unless _tmp
- return _tmp
- end
-
- # References = (Reference | SkipBlock)*
- def _References
- while true
-
- _save1 = self.pos
- while true # choice
- _tmp = apply(:_Reference)
- break if _tmp
- self.pos = _save1
- _tmp = apply(:_SkipBlock)
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- set_failed_rule :_References unless _tmp
- return _tmp
- end
-
- # Ticks1 = "`" !"`"
- def _Ticks1
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("`")
- unless _tmp
- self.pos = _save
- break
- end
- _save1 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save1
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Ticks1 unless _tmp
- return _tmp
- end
-
- # Ticks2 = "``" !"`"
- def _Ticks2
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("``")
- unless _tmp
- self.pos = _save
- break
- end
- _save1 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save1
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Ticks2 unless _tmp
- return _tmp
- end
-
- # Ticks3 = "```" !"`"
- def _Ticks3
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("```")
- unless _tmp
- self.pos = _save
- break
- end
- _save1 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save1
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Ticks3 unless _tmp
- return _tmp
- end
-
- # Ticks4 = "````" !"`"
- def _Ticks4
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("````")
- unless _tmp
- self.pos = _save
- break
- end
- _save1 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save1
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Ticks4 unless _tmp
- return _tmp
- end
-
- # Ticks5 = "`````" !"`"
- def _Ticks5
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("`````")
- unless _tmp
- self.pos = _save
- break
- end
- _save1 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save1
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Ticks5 unless _tmp
- return _tmp
- end
-
- # Code = (Ticks1 @Sp < ((!"`" Nonspacechar)+ | !Ticks1 /`+/ | !(@Sp Ticks1) (@Spacechar | @Newline !@BlankLine))+ > @Sp Ticks1 | Ticks2 @Sp < ((!"`" Nonspacechar)+ | !Ticks2 /`+/ | !(@Sp Ticks2) (@Spacechar | @Newline !@BlankLine))+ > @Sp Ticks2 | Ticks3 @Sp < ((!"`" Nonspacechar)+ | !Ticks3 /`+/ | !(@Sp Ticks3) (@Spacechar | @Newline !@BlankLine))+ > @Sp Ticks3 | Ticks4 @Sp < ((!"`" Nonspacechar)+ | !Ticks4 /`+/ | !(@Sp Ticks4) (@Spacechar | @Newline !@BlankLine))+ > @Sp Ticks4 | Ticks5 @Sp < ((!"`" Nonspacechar)+ | !Ticks5 /`+/ | !(@Sp Ticks5) (@Spacechar | @Newline !@BlankLine))+ > @Sp Ticks5) { "<code>#{text}</code>" }
- def _Code
-
- _save = self.pos
- while true # sequence
-
- _save1 = self.pos
- while true # choice
-
- _save2 = self.pos
- while true # sequence
- _tmp = apply(:_Ticks1)
- unless _tmp
- self.pos = _save2
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save2
- break
- end
- _text_start = self.pos
- _save3 = self.pos
-
- _save4 = self.pos
- while true # choice
- _save5 = self.pos
-
- _save6 = self.pos
- while true # sequence
- _save7 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save7
- unless _tmp
- self.pos = _save6
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save6
- end
- break
- end # end sequence
-
- if _tmp
- while true
-
- _save8 = self.pos
- while true # sequence
- _save9 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save9
- unless _tmp
- self.pos = _save8
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save8
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save5
- end
- break if _tmp
- self.pos = _save4
-
- _save10 = self.pos
- while true # sequence
- _save11 = self.pos
- _tmp = apply(:_Ticks1)
- _tmp = _tmp ? nil : true
- self.pos = _save11
- unless _tmp
- self.pos = _save10
- break
- end
- _tmp = scan(/\G(?-mix:`+)/)
- unless _tmp
- self.pos = _save10
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save4
-
- _save12 = self.pos
- while true # sequence
- _save13 = self.pos
-
- _save14 = self.pos
- while true # sequence
- _tmp = _Sp()
- unless _tmp
- self.pos = _save14
- break
- end
- _tmp = apply(:_Ticks1)
- unless _tmp
- self.pos = _save14
- end
- break
- end # end sequence
-
- _tmp = _tmp ? nil : true
- self.pos = _save13
- unless _tmp
- self.pos = _save12
- break
- end
-
- _save15 = self.pos
- while true # choice
- _tmp = _Spacechar()
- break if _tmp
- self.pos = _save15
-
- _save16 = self.pos
- while true # sequence
- _tmp = _Newline()
- unless _tmp
- self.pos = _save16
- break
- end
- _save17 = self.pos
- _tmp = _BlankLine()
- _tmp = _tmp ? nil : true
- self.pos = _save17
- unless _tmp
- self.pos = _save16
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save15
- break
- end # end choice
-
- unless _tmp
- self.pos = _save12
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save4
- break
- end # end choice
-
- if _tmp
- while true
-
- _save18 = self.pos
- while true # choice
- _save19 = self.pos
-
- _save20 = self.pos
- while true # sequence
- _save21 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save21
- unless _tmp
- self.pos = _save20
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save20
- end
- break
- end # end sequence
-
- if _tmp
- while true
-
- _save22 = self.pos
- while true # sequence
- _save23 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save23
- unless _tmp
- self.pos = _save22
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save22
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save19
- end
- break if _tmp
- self.pos = _save18
-
- _save24 = self.pos
- while true # sequence
- _save25 = self.pos
- _tmp = apply(:_Ticks1)
- _tmp = _tmp ? nil : true
- self.pos = _save25
- unless _tmp
- self.pos = _save24
- break
- end
- _tmp = scan(/\G(?-mix:`+)/)
- unless _tmp
- self.pos = _save24
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save18
-
- _save26 = self.pos
- while true # sequence
- _save27 = self.pos
-
- _save28 = self.pos
- while true # sequence
- _tmp = _Sp()
- unless _tmp
- self.pos = _save28
- break
- end
- _tmp = apply(:_Ticks1)
- unless _tmp
- self.pos = _save28
- end
- break
- end # end sequence
-
- _tmp = _tmp ? nil : true
- self.pos = _save27
- unless _tmp
- self.pos = _save26
- break
- end
-
- _save29 = self.pos
- while true # choice
- _tmp = _Spacechar()
- break if _tmp
- self.pos = _save29
-
- _save30 = self.pos
- while true # sequence
- _tmp = _Newline()
- unless _tmp
- self.pos = _save30
- break
- end
- _save31 = self.pos
- _tmp = _BlankLine()
- _tmp = _tmp ? nil : true
- self.pos = _save31
- unless _tmp
- self.pos = _save30
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save29
- break
- end # end choice
-
- unless _tmp
- self.pos = _save26
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save18
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save3
- end
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save2
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save2
- break
- end
- _tmp = apply(:_Ticks1)
- unless _tmp
- self.pos = _save2
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save1
-
- _save32 = self.pos
- while true # sequence
- _tmp = apply(:_Ticks2)
- unless _tmp
- self.pos = _save32
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save32
- break
- end
- _text_start = self.pos
- _save33 = self.pos
-
- _save34 = self.pos
- while true # choice
- _save35 = self.pos
-
- _save36 = self.pos
- while true # sequence
- _save37 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save37
- unless _tmp
- self.pos = _save36
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save36
- end
- break
- end # end sequence
-
- if _tmp
- while true
-
- _save38 = self.pos
- while true # sequence
- _save39 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save39
- unless _tmp
- self.pos = _save38
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save38
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save35
- end
- break if _tmp
- self.pos = _save34
-
- _save40 = self.pos
- while true # sequence
- _save41 = self.pos
- _tmp = apply(:_Ticks2)
- _tmp = _tmp ? nil : true
- self.pos = _save41
- unless _tmp
- self.pos = _save40
- break
- end
- _tmp = scan(/\G(?-mix:`+)/)
- unless _tmp
- self.pos = _save40
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save34
-
- _save42 = self.pos
- while true # sequence
- _save43 = self.pos
-
- _save44 = self.pos
- while true # sequence
- _tmp = _Sp()
- unless _tmp
- self.pos = _save44
- break
- end
- _tmp = apply(:_Ticks2)
- unless _tmp
- self.pos = _save44
- end
- break
- end # end sequence
-
- _tmp = _tmp ? nil : true
- self.pos = _save43
- unless _tmp
- self.pos = _save42
- break
- end
-
- _save45 = self.pos
- while true # choice
- _tmp = _Spacechar()
- break if _tmp
- self.pos = _save45
-
- _save46 = self.pos
- while true # sequence
- _tmp = _Newline()
- unless _tmp
- self.pos = _save46
- break
- end
- _save47 = self.pos
- _tmp = _BlankLine()
- _tmp = _tmp ? nil : true
- self.pos = _save47
- unless _tmp
- self.pos = _save46
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save45
- break
- end # end choice
-
- unless _tmp
- self.pos = _save42
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save34
- break
- end # end choice
-
- if _tmp
- while true
-
- _save48 = self.pos
- while true # choice
- _save49 = self.pos
-
- _save50 = self.pos
- while true # sequence
- _save51 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save51
- unless _tmp
- self.pos = _save50
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save50
- end
- break
- end # end sequence
-
- if _tmp
- while true
-
- _save52 = self.pos
- while true # sequence
- _save53 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save53
- unless _tmp
- self.pos = _save52
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save52
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save49
- end
- break if _tmp
- self.pos = _save48
-
- _save54 = self.pos
- while true # sequence
- _save55 = self.pos
- _tmp = apply(:_Ticks2)
- _tmp = _tmp ? nil : true
- self.pos = _save55
- unless _tmp
- self.pos = _save54
- break
- end
- _tmp = scan(/\G(?-mix:`+)/)
- unless _tmp
- self.pos = _save54
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save48
-
- _save56 = self.pos
- while true # sequence
- _save57 = self.pos
-
- _save58 = self.pos
- while true # sequence
- _tmp = _Sp()
- unless _tmp
- self.pos = _save58
- break
- end
- _tmp = apply(:_Ticks2)
- unless _tmp
- self.pos = _save58
- end
- break
- end # end sequence
-
- _tmp = _tmp ? nil : true
- self.pos = _save57
- unless _tmp
- self.pos = _save56
- break
- end
-
- _save59 = self.pos
- while true # choice
- _tmp = _Spacechar()
- break if _tmp
- self.pos = _save59
-
- _save60 = self.pos
- while true # sequence
- _tmp = _Newline()
- unless _tmp
- self.pos = _save60
- break
- end
- _save61 = self.pos
- _tmp = _BlankLine()
- _tmp = _tmp ? nil : true
- self.pos = _save61
- unless _tmp
- self.pos = _save60
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save59
- break
- end # end choice
-
- unless _tmp
- self.pos = _save56
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save48
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save33
- end
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save32
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save32
- break
- end
- _tmp = apply(:_Ticks2)
- unless _tmp
- self.pos = _save32
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save1
-
- _save62 = self.pos
- while true # sequence
- _tmp = apply(:_Ticks3)
- unless _tmp
- self.pos = _save62
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save62
- break
- end
- _text_start = self.pos
- _save63 = self.pos
-
- _save64 = self.pos
- while true # choice
- _save65 = self.pos
-
- _save66 = self.pos
- while true # sequence
- _save67 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save67
- unless _tmp
- self.pos = _save66
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save66
- end
- break
- end # end sequence
-
- if _tmp
- while true
-
- _save68 = self.pos
- while true # sequence
- _save69 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save69
- unless _tmp
- self.pos = _save68
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save68
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save65
- end
- break if _tmp
- self.pos = _save64
-
- _save70 = self.pos
- while true # sequence
- _save71 = self.pos
- _tmp = apply(:_Ticks3)
- _tmp = _tmp ? nil : true
- self.pos = _save71
- unless _tmp
- self.pos = _save70
- break
- end
- _tmp = scan(/\G(?-mix:`+)/)
- unless _tmp
- self.pos = _save70
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save64
-
- _save72 = self.pos
- while true # sequence
- _save73 = self.pos
-
- _save74 = self.pos
- while true # sequence
- _tmp = _Sp()
- unless _tmp
- self.pos = _save74
- break
- end
- _tmp = apply(:_Ticks3)
- unless _tmp
- self.pos = _save74
- end
- break
- end # end sequence
-
- _tmp = _tmp ? nil : true
- self.pos = _save73
- unless _tmp
- self.pos = _save72
- break
- end
-
- _save75 = self.pos
- while true # choice
- _tmp = _Spacechar()
- break if _tmp
- self.pos = _save75
-
- _save76 = self.pos
- while true # sequence
- _tmp = _Newline()
- unless _tmp
- self.pos = _save76
- break
- end
- _save77 = self.pos
- _tmp = _BlankLine()
- _tmp = _tmp ? nil : true
- self.pos = _save77
- unless _tmp
- self.pos = _save76
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save75
- break
- end # end choice
-
- unless _tmp
- self.pos = _save72
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save64
- break
- end # end choice
-
- if _tmp
- while true
-
- _save78 = self.pos
- while true # choice
- _save79 = self.pos
-
- _save80 = self.pos
- while true # sequence
- _save81 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save81
- unless _tmp
- self.pos = _save80
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save80
- end
- break
- end # end sequence
-
- if _tmp
- while true
-
- _save82 = self.pos
- while true # sequence
- _save83 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save83
- unless _tmp
- self.pos = _save82
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save82
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save79
- end
- break if _tmp
- self.pos = _save78
-
- _save84 = self.pos
- while true # sequence
- _save85 = self.pos
- _tmp = apply(:_Ticks3)
- _tmp = _tmp ? nil : true
- self.pos = _save85
- unless _tmp
- self.pos = _save84
- break
- end
- _tmp = scan(/\G(?-mix:`+)/)
- unless _tmp
- self.pos = _save84
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save78
-
- _save86 = self.pos
- while true # sequence
- _save87 = self.pos
-
- _save88 = self.pos
- while true # sequence
- _tmp = _Sp()
- unless _tmp
- self.pos = _save88
- break
- end
- _tmp = apply(:_Ticks3)
- unless _tmp
- self.pos = _save88
- end
- break
- end # end sequence
-
- _tmp = _tmp ? nil : true
- self.pos = _save87
- unless _tmp
- self.pos = _save86
- break
- end
-
- _save89 = self.pos
- while true # choice
- _tmp = _Spacechar()
- break if _tmp
- self.pos = _save89
-
- _save90 = self.pos
- while true # sequence
- _tmp = _Newline()
- unless _tmp
- self.pos = _save90
- break
- end
- _save91 = self.pos
- _tmp = _BlankLine()
- _tmp = _tmp ? nil : true
- self.pos = _save91
- unless _tmp
- self.pos = _save90
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save89
- break
- end # end choice
-
- unless _tmp
- self.pos = _save86
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save78
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save63
- end
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save62
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save62
- break
- end
- _tmp = apply(:_Ticks3)
- unless _tmp
- self.pos = _save62
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save1
-
- _save92 = self.pos
- while true # sequence
- _tmp = apply(:_Ticks4)
- unless _tmp
- self.pos = _save92
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save92
- break
- end
- _text_start = self.pos
- _save93 = self.pos
-
- _save94 = self.pos
- while true # choice
- _save95 = self.pos
-
- _save96 = self.pos
- while true # sequence
- _save97 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save97
- unless _tmp
- self.pos = _save96
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save96
- end
- break
- end # end sequence
-
- if _tmp
- while true
-
- _save98 = self.pos
- while true # sequence
- _save99 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save99
- unless _tmp
- self.pos = _save98
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save98
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save95
- end
- break if _tmp
- self.pos = _save94
-
- _save100 = self.pos
- while true # sequence
- _save101 = self.pos
- _tmp = apply(:_Ticks4)
- _tmp = _tmp ? nil : true
- self.pos = _save101
- unless _tmp
- self.pos = _save100
- break
- end
- _tmp = scan(/\G(?-mix:`+)/)
- unless _tmp
- self.pos = _save100
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save94
-
- _save102 = self.pos
- while true # sequence
- _save103 = self.pos
-
- _save104 = self.pos
- while true # sequence
- _tmp = _Sp()
- unless _tmp
- self.pos = _save104
- break
- end
- _tmp = apply(:_Ticks4)
- unless _tmp
- self.pos = _save104
- end
- break
- end # end sequence
-
- _tmp = _tmp ? nil : true
- self.pos = _save103
- unless _tmp
- self.pos = _save102
- break
- end
-
- _save105 = self.pos
- while true # choice
- _tmp = _Spacechar()
- break if _tmp
- self.pos = _save105
-
- _save106 = self.pos
- while true # sequence
- _tmp = _Newline()
- unless _tmp
- self.pos = _save106
- break
- end
- _save107 = self.pos
- _tmp = _BlankLine()
- _tmp = _tmp ? nil : true
- self.pos = _save107
- unless _tmp
- self.pos = _save106
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save105
- break
- end # end choice
-
- unless _tmp
- self.pos = _save102
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save94
- break
- end # end choice
-
- if _tmp
- while true
-
- _save108 = self.pos
- while true # choice
- _save109 = self.pos
-
- _save110 = self.pos
- while true # sequence
- _save111 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save111
- unless _tmp
- self.pos = _save110
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save110
- end
- break
- end # end sequence
-
- if _tmp
- while true
-
- _save112 = self.pos
- while true # sequence
- _save113 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save113
- unless _tmp
- self.pos = _save112
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save112
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save109
- end
- break if _tmp
- self.pos = _save108
-
- _save114 = self.pos
- while true # sequence
- _save115 = self.pos
- _tmp = apply(:_Ticks4)
- _tmp = _tmp ? nil : true
- self.pos = _save115
- unless _tmp
- self.pos = _save114
- break
- end
- _tmp = scan(/\G(?-mix:`+)/)
- unless _tmp
- self.pos = _save114
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save108
-
- _save116 = self.pos
- while true # sequence
- _save117 = self.pos
-
- _save118 = self.pos
- while true # sequence
- _tmp = _Sp()
- unless _tmp
- self.pos = _save118
- break
- end
- _tmp = apply(:_Ticks4)
- unless _tmp
- self.pos = _save118
- end
- break
- end # end sequence
-
- _tmp = _tmp ? nil : true
- self.pos = _save117
- unless _tmp
- self.pos = _save116
- break
- end
-
- _save119 = self.pos
- while true # choice
- _tmp = _Spacechar()
- break if _tmp
- self.pos = _save119
-
- _save120 = self.pos
- while true # sequence
- _tmp = _Newline()
- unless _tmp
- self.pos = _save120
- break
- end
- _save121 = self.pos
- _tmp = _BlankLine()
- _tmp = _tmp ? nil : true
- self.pos = _save121
- unless _tmp
- self.pos = _save120
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save119
- break
- end # end choice
-
- unless _tmp
- self.pos = _save116
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save108
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save93
- end
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save92
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save92
- break
- end
- _tmp = apply(:_Ticks4)
- unless _tmp
- self.pos = _save92
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save1
-
- _save122 = self.pos
- while true # sequence
- _tmp = apply(:_Ticks5)
- unless _tmp
- self.pos = _save122
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save122
- break
- end
- _text_start = self.pos
- _save123 = self.pos
-
- _save124 = self.pos
- while true # choice
- _save125 = self.pos
-
- _save126 = self.pos
- while true # sequence
- _save127 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save127
- unless _tmp
- self.pos = _save126
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save126
- end
- break
- end # end sequence
-
- if _tmp
- while true
-
- _save128 = self.pos
- while true # sequence
- _save129 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save129
- unless _tmp
- self.pos = _save128
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save128
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save125
- end
- break if _tmp
- self.pos = _save124
-
- _save130 = self.pos
- while true # sequence
- _save131 = self.pos
- _tmp = apply(:_Ticks5)
- _tmp = _tmp ? nil : true
- self.pos = _save131
- unless _tmp
- self.pos = _save130
- break
- end
- _tmp = scan(/\G(?-mix:`+)/)
- unless _tmp
- self.pos = _save130
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save124
-
- _save132 = self.pos
- while true # sequence
- _save133 = self.pos
-
- _save134 = self.pos
- while true # sequence
- _tmp = _Sp()
- unless _tmp
- self.pos = _save134
- break
- end
- _tmp = apply(:_Ticks5)
- unless _tmp
- self.pos = _save134
- end
- break
- end # end sequence
-
- _tmp = _tmp ? nil : true
- self.pos = _save133
- unless _tmp
- self.pos = _save132
- break
- end
-
- _save135 = self.pos
- while true # choice
- _tmp = _Spacechar()
- break if _tmp
- self.pos = _save135
-
- _save136 = self.pos
- while true # sequence
- _tmp = _Newline()
- unless _tmp
- self.pos = _save136
- break
- end
- _save137 = self.pos
- _tmp = _BlankLine()
- _tmp = _tmp ? nil : true
- self.pos = _save137
- unless _tmp
- self.pos = _save136
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save135
- break
- end # end choice
-
- unless _tmp
- self.pos = _save132
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save124
- break
- end # end choice
-
- if _tmp
- while true
-
- _save138 = self.pos
- while true # choice
- _save139 = self.pos
-
- _save140 = self.pos
- while true # sequence
- _save141 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save141
- unless _tmp
- self.pos = _save140
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save140
- end
- break
- end # end sequence
-
- if _tmp
- while true
-
- _save142 = self.pos
- while true # sequence
- _save143 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save143
- unless _tmp
- self.pos = _save142
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save142
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save139
- end
- break if _tmp
- self.pos = _save138
-
- _save144 = self.pos
- while true # sequence
- _save145 = self.pos
- _tmp = apply(:_Ticks5)
- _tmp = _tmp ? nil : true
- self.pos = _save145
- unless _tmp
- self.pos = _save144
- break
- end
- _tmp = scan(/\G(?-mix:`+)/)
- unless _tmp
- self.pos = _save144
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save138
-
- _save146 = self.pos
- while true # sequence
- _save147 = self.pos
-
- _save148 = self.pos
- while true # sequence
- _tmp = _Sp()
- unless _tmp
- self.pos = _save148
- break
- end
- _tmp = apply(:_Ticks5)
- unless _tmp
- self.pos = _save148
- end
- break
- end # end sequence
-
- _tmp = _tmp ? nil : true
- self.pos = _save147
- unless _tmp
- self.pos = _save146
- break
- end
-
- _save149 = self.pos
- while true # choice
- _tmp = _Spacechar()
- break if _tmp
- self.pos = _save149
-
- _save150 = self.pos
- while true # sequence
- _tmp = _Newline()
- unless _tmp
- self.pos = _save150
- break
- end
- _save151 = self.pos
- _tmp = _BlankLine()
- _tmp = _tmp ? nil : true
- self.pos = _save151
- unless _tmp
- self.pos = _save150
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save149
- break
- end # end choice
-
- unless _tmp
- self.pos = _save146
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save138
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save123
- end
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save122
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save122
- break
- end
- _tmp = apply(:_Ticks5)
- unless _tmp
- self.pos = _save122
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; "<code>#{text}</code>" ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Code unless _tmp
- return _tmp
- end
-
- # RawHtml = < (HtmlComment | HtmlBlockScript | HtmlTag) > { if html? then text else '' end }
- def _RawHtml
-
- _save = self.pos
- while true # sequence
- _text_start = self.pos
-
- _save1 = self.pos
- while true # choice
- _tmp = apply(:_HtmlComment)
- break if _tmp
- self.pos = _save1
- _tmp = apply(:_HtmlBlockScript)
- break if _tmp
- self.pos = _save1
- _tmp = apply(:_HtmlTag)
- 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; if html? then text else '' end ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_RawHtml unless _tmp
- return _tmp
- end
-
- # BlankLine = @Sp @Newline { "\n" }
- def _BlankLine
-
- _save = self.pos
- while true # sequence
- _tmp = _Sp()
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _Newline()
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; "\n" ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_BlankLine unless _tmp
- return _tmp
- end
-
- # Quoted = ("\"" (!"\"" .)* "\"" | "'" (!"'" .)* "'")
- def _Quoted
-
- _save = self.pos
- while true # choice
-
- _save1 = self.pos
- while true # sequence
- _tmp = match_string("\"")
- unless _tmp
- self.pos = _save1
- break
- end
- while true
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = match_string("\"")
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save1
- break
- end
- _tmp = match_string("\"")
- unless _tmp
- self.pos = _save1
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save
-
- _save5 = self.pos
- while true # sequence
- _tmp = match_string("'")
- unless _tmp
- self.pos = _save5
- break
- end
- while true
-
- _save7 = self.pos
- while true # sequence
- _save8 = self.pos
- _tmp = match_string("'")
- _tmp = _tmp ? nil : true
- self.pos = _save8
- unless _tmp
- self.pos = _save7
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save7
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save5
- break
- end
- _tmp = match_string("'")
- unless _tmp
- self.pos = _save5
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save
- break
- end # end choice
-
- set_failed_rule :_Quoted unless _tmp
- return _tmp
- end
-
- # HtmlAttribute = (AlphanumericAscii | "-")+ Spnl ("=" Spnl (Quoted | (!">" Nonspacechar)+))? Spnl
- def _HtmlAttribute
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
-
- _save2 = self.pos
- while true # choice
- _tmp = apply(:_AlphanumericAscii)
- break if _tmp
- self.pos = _save2
- _tmp = match_string("-")
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- if _tmp
- while true
-
- _save3 = self.pos
- while true # choice
- _tmp = apply(:_AlphanumericAscii)
- break if _tmp
- self.pos = _save3
- _tmp = match_string("-")
- break if _tmp
- self.pos = _save3
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save1
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _save4 = self.pos
-
- _save5 = self.pos
- while true # sequence
- _tmp = match_string("=")
- unless _tmp
- self.pos = _save5
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save5
- break
- end
-
- _save6 = self.pos
- while true # choice
- _tmp = apply(:_Quoted)
- break if _tmp
- self.pos = _save6
- _save7 = self.pos
-
- _save8 = self.pos
- while true # sequence
- _save9 = self.pos
- _tmp = match_string(">")
- _tmp = _tmp ? nil : true
- self.pos = _save9
- unless _tmp
- self.pos = _save8
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save8
- end
- break
- end # end sequence
-
- if _tmp
- while true
-
- _save10 = self.pos
- while true # sequence
- _save11 = self.pos
- _tmp = match_string(">")
- _tmp = _tmp ? nil : true
- self.pos = _save11
- unless _tmp
- self.pos = _save10
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save10
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save7
- end
- break if _tmp
- self.pos = _save6
- break
- end # end choice
-
- unless _tmp
- self.pos = _save5
- end
- break
- end # end sequence
-
- unless _tmp
- _tmp = true
- self.pos = _save4
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlAttribute unless _tmp
- return _tmp
- end
-
- # HtmlComment = "<!--" (!"-->" .)* "-->"
- def _HtmlComment
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<!--")
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _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
- _tmp = get_byte
- unless _tmp
- self.pos = _save2
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("-->")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlComment unless _tmp
- return _tmp
- end
-
- # HtmlTag = "<" Spnl "/"? AlphanumericAscii+ Spnl HtmlAttribute* "/"? Spnl ">"
- def _HtmlTag
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("<")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _save1 = self.pos
- _tmp = match_string("/")
- unless _tmp
- _tmp = true
- self.pos = _save1
- end
- unless _tmp
- self.pos = _save
- break
- end
- _save2 = self.pos
- _tmp = apply(:_AlphanumericAscii)
- if _tmp
- while true
- _tmp = apply(:_AlphanumericAscii)
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save2
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = apply(:_HtmlAttribute)
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- _save4 = self.pos
- _tmp = match_string("/")
- unless _tmp
- _tmp = true
- self.pos = _save4
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(">")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HtmlTag unless _tmp
- return _tmp
- end
-
- # Eof = !.
- def _Eof
- _save = self.pos
- _tmp = get_byte
- _tmp = _tmp ? nil : true
- self.pos = _save
- set_failed_rule :_Eof unless _tmp
- return _tmp
- end
-
- # Nonspacechar = !@Spacechar !@Newline .
- def _Nonspacechar
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
- _tmp = _Spacechar()
- _tmp = _tmp ? nil : true
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- _save2 = self.pos
- _tmp = _Newline()
- _tmp = _tmp ? nil : true
- self.pos = _save2
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Nonspacechar unless _tmp
- return _tmp
- end
-
- # Sp = @Spacechar*
- def _Sp
- while true
- _tmp = _Spacechar()
- break unless _tmp
- end
- _tmp = true
- set_failed_rule :_Sp unless _tmp
- return _tmp
- end
-
- # Spnl = @Sp (@Newline @Sp)?
- def _Spnl
-
- _save = self.pos
- while true # sequence
- _tmp = _Sp()
- unless _tmp
- self.pos = _save
- break
- end
- _save1 = self.pos
-
- _save2 = self.pos
- while true # sequence
- _tmp = _Newline()
- unless _tmp
- self.pos = _save2
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save2
- end
- break
- end # end sequence
-
- unless _tmp
- _tmp = true
- self.pos = _save1
- end
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Spnl unless _tmp
- return _tmp
- end
-
- # SpecialChar = (/[~*_`&\[\]()<!#\\'"]/ | @ExtendedSpecialChar)
- def _SpecialChar
-
- _save = self.pos
- while true # choice
- _tmp = scan(/\G(?-mix:[~*_`&\[\]()<!#\\'"])/)
- break if _tmp
- self.pos = _save
- _tmp = _ExtendedSpecialChar()
- break if _tmp
- self.pos = _save
- break
- end # end choice
-
- set_failed_rule :_SpecialChar unless _tmp
- return _tmp
- end
-
- # NormalChar = !(@SpecialChar | @Spacechar | @Newline) .
- def _NormalChar
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
-
- _save2 = self.pos
- while true # choice
- _tmp = _SpecialChar()
- break if _tmp
- self.pos = _save2
- _tmp = _Spacechar()
- break if _tmp
- self.pos = _save2
- _tmp = _Newline()
- break if _tmp
- self.pos = _save2
- break
- end # end choice
-
- _tmp = _tmp ? nil : true
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = get_byte
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_NormalChar unless _tmp
- return _tmp
- end
-
- # Digit = [0-9]
- def _Digit
- _save = self.pos
- _tmp = get_byte
- if _tmp
- unless _tmp >= 48 and _tmp <= 57
- self.pos = _save
- _tmp = nil
- end
- end
- set_failed_rule :_Digit unless _tmp
- return _tmp
- end
-
- # Alphanumeric = %literals.Alphanumeric
- def _Alphanumeric
- _tmp = @_grammar_literals.external_invoke(self, :_Alphanumeric)
- set_failed_rule :_Alphanumeric unless _tmp
- return _tmp
- end
-
- # AlphanumericAscii = %literals.AlphanumericAscii
- def _AlphanumericAscii
- _tmp = @_grammar_literals.external_invoke(self, :_AlphanumericAscii)
- set_failed_rule :_AlphanumericAscii unless _tmp
- return _tmp
- end
-
- # BOM = %literals.BOM
- def _BOM
- _tmp = @_grammar_literals.external_invoke(self, :_BOM)
- set_failed_rule :_BOM unless _tmp
- return _tmp
- end
-
- # Newline = %literals.Newline
- def _Newline
- _tmp = @_grammar_literals.external_invoke(self, :_Newline)
- set_failed_rule :_Newline unless _tmp
- return _tmp
- end
-
- # Spacechar = %literals.Spacechar
- def _Spacechar
- _tmp = @_grammar_literals.external_invoke(self, :_Spacechar)
- set_failed_rule :_Spacechar unless _tmp
- return _tmp
- end
-
- # HexEntity = /&#x/i < /[0-9a-fA-F]+/ > ";" { [text.to_i(16)].pack 'U' }
- def _HexEntity
-
- _save = self.pos
- while true # sequence
- _tmp = scan(/\G(?i-mx:&#x)/)
- unless _tmp
- self.pos = _save
- break
- end
- _text_start = self.pos
- _tmp = scan(/\G(?-mix:[0-9a-fA-F]+)/)
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(";")
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; [text.to_i(16)].pack 'U' ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_HexEntity unless _tmp
- return _tmp
- end
-
- # DecEntity = "&#" < /[0-9]+/ > ";" { [text.to_i].pack 'U' }
- def _DecEntity
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("&#")
- unless _tmp
- self.pos = _save
- break
- end
- _text_start = self.pos
- _tmp = scan(/\G(?-mix:[0-9]+)/)
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(";")
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; [text.to_i].pack 'U' ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_DecEntity unless _tmp
- return _tmp
- end
-
- # CharEntity = "&" < /[A-Za-z0-9]+/ > ";" { if entity = HTML_ENTITIES[text] then entity.pack 'U*' else "&#{text};" end }
- def _CharEntity
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("&")
- unless _tmp
- self.pos = _save
- break
- end
- _text_start = self.pos
- _tmp = scan(/\G(?-mix:[A-Za-z0-9]+)/)
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(";")
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; if entity = HTML_ENTITIES[text] then
- entity.pack 'U*'
- else
- "&#{text};"
- end
- ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_CharEntity unless _tmp
- return _tmp
- end
-
- # NonindentSpace = / {0,3}/
- def _NonindentSpace
- _tmp = scan(/\G(?-mix: {0,3})/)
- set_failed_rule :_NonindentSpace unless _tmp
- return _tmp
- end
-
- # Indent = /\t| /
- def _Indent
- _tmp = scan(/\G(?-mix:\t| )/)
- set_failed_rule :_Indent unless _tmp
- return _tmp
- end
-
- # IndentedLine = Indent Line
- def _IndentedLine
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_Indent)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Line)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_IndentedLine unless _tmp
- return _tmp
- end
-
- # OptionallyIndentedLine = Indent? Line
- def _OptionallyIndentedLine
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
- _tmp = apply(:_Indent)
- unless _tmp
- _tmp = true
- self.pos = _save1
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Line)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_OptionallyIndentedLine unless _tmp
- return _tmp
- end
-
- # StartList = &. { [] }
- def _StartList
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
- _tmp = get_byte
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; [] ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_StartList unless _tmp
- return _tmp
- end
-
- # Line = @RawLine:a { a }
- def _Line
-
- _save = self.pos
- while true # sequence
- _tmp = _RawLine()
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; a ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Line unless _tmp
- return _tmp
- end
-
- # RawLine = (< /[^\r\n]*/ @Newline > | < .+ > @Eof) { text }
- def _RawLine
-
- _save = self.pos
- while true # sequence
-
- _save1 = self.pos
- while true # choice
- _text_start = self.pos
-
- _save2 = self.pos
- while true # sequence
- _tmp = scan(/\G(?-mix:[^\r\n]*)/)
- unless _tmp
- self.pos = _save2
- break
- end
- _tmp = _Newline()
- unless _tmp
- self.pos = _save2
- end
- break
- end # end sequence
-
- if _tmp
- text = get_text(_text_start)
- end
- break if _tmp
- self.pos = _save1
-
- _save3 = self.pos
- while true # sequence
- _text_start = self.pos
- _save4 = self.pos
- _tmp = get_byte
- if _tmp
- while true
- _tmp = get_byte
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save4
- end
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = _Eof()
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; text ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_RawLine unless _tmp
- return _tmp
- end
-
- # SkipBlock = (HtmlBlock | (!"#" !SetextBottom1 !SetextBottom2 !@BlankLine @RawLine)+ @BlankLine* | @BlankLine+ | @RawLine)
- def _SkipBlock
-
- _save = self.pos
- while true # choice
- _tmp = apply(:_HtmlBlock)
- break if _tmp
- self.pos = _save
-
- _save1 = self.pos
- while true # sequence
- _save2 = self.pos
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = match_string("#")
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _save5 = self.pos
- _tmp = apply(:_SetextBottom1)
- _tmp = _tmp ? nil : true
- self.pos = _save5
- unless _tmp
- self.pos = _save3
- break
- end
- _save6 = self.pos
- _tmp = apply(:_SetextBottom2)
- _tmp = _tmp ? nil : true
- self.pos = _save6
- unless _tmp
- self.pos = _save3
- break
- end
- _save7 = self.pos
- _tmp = _BlankLine()
- _tmp = _tmp ? nil : true
- self.pos = _save7
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = _RawLine()
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- if _tmp
- while true
-
- _save8 = self.pos
- while true # sequence
- _save9 = self.pos
- _tmp = match_string("#")
- _tmp = _tmp ? nil : true
- self.pos = _save9
- unless _tmp
- self.pos = _save8
- break
- end
- _save10 = self.pos
- _tmp = apply(:_SetextBottom1)
- _tmp = _tmp ? nil : true
- self.pos = _save10
- unless _tmp
- self.pos = _save8
- break
- end
- _save11 = self.pos
- _tmp = apply(:_SetextBottom2)
- _tmp = _tmp ? nil : true
- self.pos = _save11
- unless _tmp
- self.pos = _save8
- break
- end
- _save12 = self.pos
- _tmp = _BlankLine()
- _tmp = _tmp ? nil : true
- self.pos = _save12
- unless _tmp
- self.pos = _save8
- break
- end
- _tmp = _RawLine()
- unless _tmp
- self.pos = _save8
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save2
- end
- unless _tmp
- self.pos = _save1
- break
- end
- while true
- _tmp = _BlankLine()
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save1
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save
- _save14 = self.pos
- _tmp = _BlankLine()
- if _tmp
- while true
- _tmp = _BlankLine()
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save14
- end
- break if _tmp
- self.pos = _save
- _tmp = _RawLine()
- break if _tmp
- self.pos = _save
- break
- end # end choice
-
- set_failed_rule :_SkipBlock unless _tmp
- return _tmp
- end
-
- # ExtendedSpecialChar = &{ notes? } "^"
- def _ExtendedSpecialChar
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
- _tmp = begin; notes? ; end
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("^")
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_ExtendedSpecialChar unless _tmp
- return _tmp
- end
-
- # NoteReference = &{ notes? } RawNoteReference:ref { note_for ref }
- def _NoteReference
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
- _tmp = begin; notes? ; end
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_RawNoteReference)
- ref = @result
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; note_for ref ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_NoteReference unless _tmp
- return _tmp
- end
-
- # RawNoteReference = "[^" < (!@Newline !"]" .)+ > "]" { text }
- def _RawNoteReference
-
- _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 = _Newline()
- _tmp = _tmp ? nil : true
- self.pos = _save3
- unless _tmp
- self.pos = _save2
- break
- end
- _save4 = self.pos
- _tmp = match_string("]")
- _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 = _Newline()
- _tmp = _tmp ? nil : true
- self.pos = _save6
- unless _tmp
- self.pos = _save5
- break
- end
- _save7 = self.pos
- _tmp = match_string("]")
- _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
- _tmp = match_string("]")
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; text ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_RawNoteReference unless _tmp
- return _tmp
- end
-
- # Note = &{ notes? } @NonindentSpace RawNoteReference:ref ":" @Sp @StartList:a RawNoteBlock:i { a.concat i } (&Indent RawNoteBlock:i { a.concat i })* { @footnotes[ref] = paragraph a nil }
- def _Note
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
- _tmp = begin; notes? ; end
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _NonindentSpace()
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_RawNoteReference)
- ref = @result
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(":")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _StartList()
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_RawNoteBlock)
- i = @result
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; a.concat i ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- while true
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = apply(:_Indent)
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = apply(:_RawNoteBlock)
- i = @result
- unless _tmp
- self.pos = _save3
- break
- end
- @result = begin; a.concat i ; end
- _tmp = true
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; @footnotes[ref] = paragraph a
-
- nil
- ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Note unless _tmp
- return _tmp
- end
-
- # InlineNote = &{ notes? } "^[" @StartList:a (!"]" Inline:l { a << l })+ "]" { ref = [:inline, @note_order.length] @footnotes[ref] = paragraph a note_for ref }
- def _InlineNote
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
- _tmp = begin; notes? ; end
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("^[")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _StartList()
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- _save2 = self.pos
-
- _save3 = self.pos
- while true # sequence
- _save4 = self.pos
- _tmp = match_string("]")
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = apply(:_Inline)
- l = @result
- unless _tmp
- self.pos = _save3
- break
- end
- @result = begin; a << l ; end
- _tmp = true
- unless _tmp
- self.pos = _save3
- 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
- _tmp = apply(:_Inline)
- l = @result
- unless _tmp
- self.pos = _save5
- break
- end
- @result = begin; a << l ; end
- _tmp = true
- unless _tmp
- self.pos = _save5
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save2
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string("]")
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; ref = [:inline, @note_order.length]
- @footnotes[ref] = paragraph a
-
- note_for ref
- ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_InlineNote unless _tmp
- return _tmp
- end
-
- # Notes = (Note | SkipBlock)*
- def _Notes
- while true
-
- _save1 = self.pos
- while true # choice
- _tmp = apply(:_Note)
- break if _tmp
- self.pos = _save1
- _tmp = apply(:_SkipBlock)
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- set_failed_rule :_Notes unless _tmp
- return _tmp
- end
-
- # RawNoteBlock = @StartList:a (!@BlankLine !RawNoteReference OptionallyIndentedLine:l { a << l })+ < @BlankLine* > { a << text } { a }
- def _RawNoteBlock
-
- _save = self.pos
- while true # sequence
- _tmp = _StartList()
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- _save1 = self.pos
-
- _save2 = self.pos
- while true # sequence
- _save3 = self.pos
- _tmp = _BlankLine()
- _tmp = _tmp ? nil : true
- self.pos = _save3
- unless _tmp
- self.pos = _save2
- break
- end
- _save4 = self.pos
- _tmp = apply(:_RawNoteReference)
- _tmp = _tmp ? nil : true
- self.pos = _save4
- unless _tmp
- self.pos = _save2
- break
- end
- _tmp = apply(:_OptionallyIndentedLine)
- l = @result
- unless _tmp
- self.pos = _save2
- break
- end
- @result = begin; a << l ; end
- _tmp = true
- unless _tmp
- self.pos = _save2
- end
- break
- end # end sequence
-
- if _tmp
- while true
-
- _save5 = self.pos
- while true # sequence
- _save6 = self.pos
- _tmp = _BlankLine()
- _tmp = _tmp ? nil : true
- self.pos = _save6
- unless _tmp
- self.pos = _save5
- break
- end
- _save7 = self.pos
- _tmp = apply(:_RawNoteReference)
- _tmp = _tmp ? nil : true
- self.pos = _save7
- unless _tmp
- self.pos = _save5
- break
- end
- _tmp = apply(:_OptionallyIndentedLine)
- l = @result
- unless _tmp
- self.pos = _save5
- break
- end
- @result = begin; a << l ; end
- _tmp = true
- unless _tmp
- self.pos = _save5
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save1
- end
- unless _tmp
- self.pos = _save
- break
- end
- _text_start = self.pos
- while true
- _tmp = _BlankLine()
- break unless _tmp
- end
- _tmp = true
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; a << text ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; a ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_RawNoteBlock unless _tmp
- return _tmp
- end
-
- # 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 }
- def _CodeFence
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
- _tmp = begin; github? ; end
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Ticks3)
- unless _tmp
- self.pos = _save
- break
- end
- _save2 = self.pos
-
- _save3 = self.pos
- while true # sequence
- _tmp = _Sp()
- unless _tmp
- self.pos = _save3
- break
- end
- _tmp = apply(:_StrChunk)
- format = @result
- unless _tmp
- self.pos = _save3
- end
- break
- end # end sequence
-
- unless _tmp
- _tmp = true
- self.pos = _save2
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Spnl)
- unless _tmp
- self.pos = _save
- break
- end
- _text_start = self.pos
- _save4 = self.pos
-
- _save5 = self.pos
- while true # choice
- _save6 = self.pos
-
- _save7 = self.pos
- while true # sequence
- _save8 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save8
- unless _tmp
- self.pos = _save7
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save7
- end
- break
- end # end sequence
-
- if _tmp
- while true
-
- _save9 = self.pos
- while true # sequence
- _save10 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save10
- unless _tmp
- self.pos = _save9
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save9
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save6
- end
- break if _tmp
- self.pos = _save5
-
- _save11 = self.pos
- while true # sequence
- _save12 = self.pos
- _tmp = apply(:_Ticks3)
- _tmp = _tmp ? nil : true
- self.pos = _save12
- unless _tmp
- self.pos = _save11
- break
- end
- _tmp = scan(/\G(?-mix:`+)/)
- unless _tmp
- self.pos = _save11
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save5
- _tmp = apply(:_Spacechar)
- break if _tmp
- self.pos = _save5
- _tmp = _Newline()
- break if _tmp
- self.pos = _save5
- break
- end # end choice
-
- if _tmp
- while true
-
- _save13 = self.pos
- while true # choice
- _save14 = self.pos
-
- _save15 = self.pos
- while true # sequence
- _save16 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save16
- unless _tmp
- self.pos = _save15
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save15
- end
- break
- end # end sequence
-
- if _tmp
- while true
-
- _save17 = self.pos
- while true # sequence
- _save18 = self.pos
- _tmp = match_string("`")
- _tmp = _tmp ? nil : true
- self.pos = _save18
- unless _tmp
- self.pos = _save17
- break
- end
- _tmp = apply(:_Nonspacechar)
- unless _tmp
- self.pos = _save17
- end
- break
- end # end sequence
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save14
- end
- break if _tmp
- self.pos = _save13
-
- _save19 = self.pos
- while true # sequence
- _save20 = self.pos
- _tmp = apply(:_Ticks3)
- _tmp = _tmp ? nil : true
- self.pos = _save20
- unless _tmp
- self.pos = _save19
- break
- end
- _tmp = scan(/\G(?-mix:`+)/)
- unless _tmp
- self.pos = _save19
- end
- break
- end # end sequence
-
- break if _tmp
- self.pos = _save13
- _tmp = apply(:_Spacechar)
- break if _tmp
- self.pos = _save13
- _tmp = _Newline()
- break if _tmp
- self.pos = _save13
- break
- end # end choice
-
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save4
- end
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Ticks3)
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save
- break
- end
- while true
- _tmp = _Newline()
- break unless _tmp
- end
- _tmp = true
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; verbatim = RDoc::Markup::Verbatim.new text
- verbatim.format = format.intern if format.instance_of?(String)
- verbatim
- ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_CodeFence unless _tmp
- return _tmp
- end
-
- # Table = &{ github? } TableHead:header TableLine:line TableRow+:body { table = RDoc::Markup::Table.new(header, line, body) }
- def _Table
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
- _tmp = begin; github? ; end
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_TableHead)
- header = @result
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_TableLine)
- line = @result
- unless _tmp
- self.pos = _save
- break
- end
- _save2 = self.pos
- _ary = []
- _tmp = apply(:_TableRow)
- if _tmp
- _ary << @result
- while true
- _tmp = apply(:_TableRow)
- _ary << @result if _tmp
- break unless _tmp
- end
- _tmp = true
- @result = _ary
- else
- self.pos = _save2
- end
- body = @result
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; table = RDoc::Markup::Table.new(header, line, body) ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_Table unless _tmp
- return _tmp
- end
-
- # TableHead = TableItem2+:items "|"? @Newline { items }
- def _TableHead
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
- _ary = []
- _tmp = apply(:_TableItem2)
- if _tmp
- _ary << @result
- while true
- _tmp = apply(:_TableItem2)
- _ary << @result if _tmp
- break unless _tmp
- end
- _tmp = true
- @result = _ary
- else
- self.pos = _save1
- end
- items = @result
- unless _tmp
- self.pos = _save
- break
- end
- _save2 = self.pos
- _tmp = match_string("|")
- unless _tmp
- _tmp = true
- self.pos = _save2
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _Newline()
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; items ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_TableHead unless _tmp
- return _tmp
- end
-
- # TableRow = ((TableItem:item1 TableItem2*:items { [item1, *items] }):row | TableItem2+:row) "|"? @Newline { row }
- def _TableRow
-
- _save = self.pos
- while true # sequence
-
- _save1 = self.pos
- while true # choice
-
- _save2 = self.pos
- while true # sequence
- _tmp = apply(:_TableItem)
- item1 = @result
- unless _tmp
- self.pos = _save2
- break
- end
- _ary = []
- while true
- _tmp = apply(:_TableItem2)
- _ary << @result if _tmp
- break unless _tmp
- end
- _tmp = true
- @result = _ary
- items = @result
- unless _tmp
- self.pos = _save2
- break
- end
- @result = begin; [item1, *items] ; end
- _tmp = true
- unless _tmp
- self.pos = _save2
- end
- break
- end # end sequence
-
- row = @result
- break if _tmp
- self.pos = _save1
- _save4 = self.pos
- _ary = []
- _tmp = apply(:_TableItem2)
- if _tmp
- _ary << @result
- while true
- _tmp = apply(:_TableItem2)
- _ary << @result if _tmp
- break unless _tmp
- end
- _tmp = true
- @result = _ary
- else
- self.pos = _save4
- end
- row = @result
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _save5 = self.pos
- _tmp = match_string("|")
- unless _tmp
- _tmp = true
- self.pos = _save5
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _Newline()
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; row ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_TableRow unless _tmp
- return _tmp
- end
-
- # TableItem2 = "|" TableItem
- def _TableItem2
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("|")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_TableItem)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_TableItem2 unless _tmp
- return _tmp
- end
-
- # TableItem = < /(?:\\.|[^|\n])+/ > { text.strip.gsub(/\\(.)/, '\1') }
- def _TableItem
-
- _save = self.pos
- while true # sequence
- _text_start = self.pos
- _tmp = scan(/\G(?-mix:(?:\\.|[^|\n])+)/)
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; text.strip.gsub(/\\(.)/, '\1') ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_TableItem unless _tmp
- return _tmp
- end
-
- # TableLine = ((TableAlign:align1 TableAlign2*:aligns {[align1, *aligns] }):line | TableAlign2+:line) "|"? @Newline { line }
- def _TableLine
-
- _save = self.pos
- while true # sequence
-
- _save1 = self.pos
- while true # choice
-
- _save2 = self.pos
- while true # sequence
- _tmp = apply(:_TableAlign)
- align1 = @result
- unless _tmp
- self.pos = _save2
- break
- end
- _ary = []
- while true
- _tmp = apply(:_TableAlign2)
- _ary << @result if _tmp
- break unless _tmp
- end
- _tmp = true
- @result = _ary
- aligns = @result
- unless _tmp
- self.pos = _save2
- break
- end
- @result = begin; [align1, *aligns] ; end
- _tmp = true
- unless _tmp
- self.pos = _save2
- end
- break
- end # end sequence
-
- line = @result
- break if _tmp
- self.pos = _save1
- _save4 = self.pos
- _ary = []
- _tmp = apply(:_TableAlign2)
- if _tmp
- _ary << @result
- while true
- _tmp = apply(:_TableAlign2)
- _ary << @result if _tmp
- break unless _tmp
- end
- _tmp = true
- @result = _ary
- else
- self.pos = _save4
- end
- line = @result
- break if _tmp
- self.pos = _save1
- break
- end # end choice
-
- unless _tmp
- self.pos = _save
- break
- end
- _save5 = self.pos
- _tmp = match_string("|")
- unless _tmp
- _tmp = true
- self.pos = _save5
- end
- 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
-
- # TableAlign2 = "|" @Sp TableAlign
- def _TableAlign2
-
- _save = self.pos
- while true # sequence
- _tmp = match_string("|")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_TableAlign)
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_TableAlign2 unless _tmp
- return _tmp
- end
-
- # TableAlign = < /:?-+:?/ > @Sp { text.start_with?(":") ? (text.end_with?(":") ? :center : :left) : (text.end_with?(":") ? :right : nil) }
- def _TableAlign
-
- _save = self.pos
- while true # sequence
- _text_start = self.pos
- _tmp = scan(/\G(?-mix::?-+:?)/)
- if _tmp
- text = get_text(_text_start)
- end
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin;
- text.start_with?(":") ?
- (text.end_with?(":") ? :center : :left) :
- (text.end_with?(":") ? :right : nil)
- ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_TableAlign unless _tmp
- return _tmp
- end
-
- # DefinitionList = &{ definition_lists? } DefinitionListItem+:list { RDoc::Markup::List.new :NOTE, *list.flatten }
- def _DefinitionList
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
- _tmp = begin; definition_lists? ; end
- self.pos = _save1
- unless _tmp
- self.pos = _save
- break
- end
- _save2 = self.pos
- _ary = []
- _tmp = apply(:_DefinitionListItem)
- if _tmp
- _ary << @result
- while true
- _tmp = apply(:_DefinitionListItem)
- _ary << @result if _tmp
- break unless _tmp
- end
- _tmp = true
- @result = _ary
- else
- self.pos = _save2
- end
- list = @result
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; RDoc::Markup::List.new :NOTE, *list.flatten ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_DefinitionList unless _tmp
- return _tmp
- end
-
- # 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 }
- def _DefinitionListItem
-
- _save = self.pos
- while true # sequence
- _save1 = self.pos
- _ary = []
- _tmp = apply(:_DefinitionListLabel)
- if _tmp
- _ary << @result
- while true
- _tmp = apply(:_DefinitionListLabel)
- _ary << @result if _tmp
- break unless _tmp
- end
- _tmp = true
- @result = _ary
- else
- self.pos = _save1
- end
- label = @result
- unless _tmp
- self.pos = _save
- break
- end
- _save2 = self.pos
- _ary = []
- _tmp = apply(:_DefinitionListDefinition)
- if _tmp
- _ary << @result
- while true
- _tmp = apply(:_DefinitionListDefinition)
- _ary << @result if _tmp
- break unless _tmp
- end
- _tmp = true
- @result = _ary
- else
- self.pos = _save2
- end
- defns = @result
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; 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
- ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_DefinitionListItem unless _tmp
- return _tmp
- end
-
- # DefinitionListLabel = Inline:label @Sp @Newline { label }
- def _DefinitionListLabel
-
- _save = self.pos
- while true # sequence
- _tmp = apply(:_Inline)
- label = @result
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _Sp()
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _Newline()
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; label ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_DefinitionListLabel unless _tmp
- return _tmp
- end
-
- # DefinitionListDefinition = @NonindentSpace ":" @Space Inlines:a @BlankLine+ { paragraph a }
- def _DefinitionListDefinition
-
- _save = self.pos
- while true # sequence
- _tmp = _NonindentSpace()
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = match_string(":")
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = _Space()
- unless _tmp
- self.pos = _save
- break
- end
- _tmp = apply(:_Inlines)
- a = @result
- unless _tmp
- self.pos = _save
- break
- end
- _save1 = self.pos
- _tmp = _BlankLine()
- if _tmp
- while true
- _tmp = _BlankLine()
- break unless _tmp
- end
- _tmp = true
- else
- self.pos = _save1
- end
- unless _tmp
- self.pos = _save
- break
- end
- @result = begin; paragraph a ; end
- _tmp = true
- unless _tmp
- self.pos = _save
- end
- break
- end # end sequence
-
- set_failed_rule :_DefinitionListDefinition unless _tmp
- return _tmp
- end
-
- 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 | 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")
- Rules[:_AtxStart] = rule_info("AtxStart", "< /\\\#{1,6}/ > { text.length }")
- Rules[:_AtxHeading] = rule_info("AtxHeading", "AtxStart:s @Sp AtxInline+:a (@Sp /\#*/ @Sp)? @Newline { RDoc::Markup::Heading.new(s, a.join) }")
- Rules[:_SetextHeading] = rule_info("SetextHeading", "(SetextHeading1 | SetextHeading2)")
- Rules[:_SetextBottom1] = rule_info("SetextBottom1", "/={1,}/ @Newline")
- Rules[:_SetextBottom2] = rule_info("SetextBottom2", "/-{1,}/ @Newline")
- Rules[:_SetextHeading1] = rule_info("SetextHeading1", "&(@RawLine SetextBottom1) @StartList:a (!@Endline Inline:b { a << b })+ @Sp @Newline SetextBottom1 { RDoc::Markup::Heading.new(1, a.join) }")
- Rules[:_SetextHeading2] = rule_info("SetextHeading2", "&(@RawLine SetextBottom2) @StartList:a (!@Endline Inline:b { a << b })+ @Sp @Newline SetextBottom2 { RDoc::Markup::Heading.new(2, a.join) }")
- Rules[:_Heading] = rule_info("Heading", "(SetextHeading | AtxHeading)")
- Rules[:_BlockQuote] = rule_info("BlockQuote", "BlockQuoteRaw:a { RDoc::Markup::BlockQuote.new(*a) }")
- Rules[:_BlockQuoteRaw] = rule_info("BlockQuoteRaw", "@StartList:a (\">\" \" \"? Line:l { a << l } (!\">\" !@BlankLine Line:c { a << c })* (@BlankLine:n { a << n })*)+ { inner_parse a.join }")
- Rules[:_NonblankIndentedLine] = rule_info("NonblankIndentedLine", "!@BlankLine IndentedLine")
- Rules[:_VerbatimChunk] = rule_info("VerbatimChunk", "@BlankLine*:a NonblankIndentedLine+:b { a.concat b }")
- Rules[:_Verbatim] = rule_info("Verbatim", "VerbatimChunk+:a { RDoc::Markup::Verbatim.new(*a.flatten) }")
- Rules[:_HorizontalRule] = rule_info("HorizontalRule", "@NonindentSpace (\"*\" @Sp \"*\" @Sp \"*\" (@Sp \"*\")* | \"-\" @Sp \"-\" @Sp \"-\" (@Sp \"-\")* | \"_\" @Sp \"_\" @Sp \"_\" (@Sp \"_\")*) @Sp @Newline @BlankLine+ { RDoc::Markup::Rule.new 1 }")
- Rules[:_Bullet] = rule_info("Bullet", "!HorizontalRule @NonindentSpace /[+*-]/ @Spacechar+")
- Rules[:_BulletList] = rule_info("BulletList", "&Bullet (ListTight | ListLoose):a { RDoc::Markup::List.new(:BULLET, *a) }")
- Rules[:_ListTight] = rule_info("ListTight", "ListItemTight+:a @BlankLine* !(Bullet | Enumerator) { a }")
- Rules[:_ListLoose] = rule_info("ListLoose", "@StartList:a (ListItem:b @BlankLine* { a << b })+ { a }")
- Rules[:_ListItem] = rule_info("ListItem", "(Bullet | Enumerator) @StartList:a ListBlock:b { a << b } (ListContinuationBlock:c { a.push(*c) })* { list_item_from a }")
- Rules[:_ListItemTight] = rule_info("ListItemTight", "(Bullet | Enumerator) ListBlock:a (!@BlankLine ListContinuationBlock:b { a.push(*b) })* !ListContinuationBlock { list_item_from a }")
- Rules[:_ListBlock] = rule_info("ListBlock", "!@BlankLine Line:a ListBlockLine*:c { [a, *c] }")
- Rules[:_ListContinuationBlock] = rule_info("ListContinuationBlock", "@StartList:a @BlankLine* { a << \"\\n\" } (Indent ListBlock:b { a.concat b })+ { a }")
- Rules[:_Enumerator] = rule_info("Enumerator", "@NonindentSpace [0-9]+ \".\" @Spacechar+")
- Rules[:_OrderedList] = rule_info("OrderedList", "&Enumerator (ListTight | ListLoose):a { RDoc::Markup::List.new(:NUMBER, *a) }")
- Rules[:_ListBlockLine] = rule_info("ListBlockLine", "!@BlankLine !(Indent? (Bullet | Enumerator)) !HorizontalRule OptionallyIndentedLine")
- Rules[:_HtmlOpenAnchor] = rule_info("HtmlOpenAnchor", "\"<\" Spnl (\"a\" | \"A\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlCloseAnchor] = rule_info("HtmlCloseAnchor", "\"<\" Spnl \"/\" (\"a\" | \"A\") Spnl \">\"")
- Rules[:_HtmlAnchor] = rule_info("HtmlAnchor", "HtmlOpenAnchor (HtmlAnchor | !HtmlCloseAnchor .)* HtmlCloseAnchor")
- Rules[:_HtmlBlockOpenAddress] = rule_info("HtmlBlockOpenAddress", "\"<\" Spnl (\"address\" | \"ADDRESS\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseAddress] = rule_info("HtmlBlockCloseAddress", "\"<\" Spnl \"/\" (\"address\" | \"ADDRESS\") Spnl \">\"")
- Rules[:_HtmlBlockAddress] = rule_info("HtmlBlockAddress", "HtmlBlockOpenAddress (HtmlBlockAddress | !HtmlBlockCloseAddress .)* HtmlBlockCloseAddress")
- Rules[:_HtmlBlockOpenBlockquote] = rule_info("HtmlBlockOpenBlockquote", "\"<\" Spnl (\"blockquote\" | \"BLOCKQUOTE\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseBlockquote] = rule_info("HtmlBlockCloseBlockquote", "\"<\" Spnl \"/\" (\"blockquote\" | \"BLOCKQUOTE\") Spnl \">\"")
- Rules[:_HtmlBlockBlockquote] = rule_info("HtmlBlockBlockquote", "HtmlBlockOpenBlockquote (HtmlBlockBlockquote | !HtmlBlockCloseBlockquote .)* HtmlBlockCloseBlockquote")
- Rules[:_HtmlBlockOpenCenter] = rule_info("HtmlBlockOpenCenter", "\"<\" Spnl (\"center\" | \"CENTER\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseCenter] = rule_info("HtmlBlockCloseCenter", "\"<\" Spnl \"/\" (\"center\" | \"CENTER\") Spnl \">\"")
- Rules[:_HtmlBlockCenter] = rule_info("HtmlBlockCenter", "HtmlBlockOpenCenter (HtmlBlockCenter | !HtmlBlockCloseCenter .)* HtmlBlockCloseCenter")
- Rules[:_HtmlBlockOpenDir] = rule_info("HtmlBlockOpenDir", "\"<\" Spnl (\"dir\" | \"DIR\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseDir] = rule_info("HtmlBlockCloseDir", "\"<\" Spnl \"/\" (\"dir\" | \"DIR\") Spnl \">\"")
- Rules[:_HtmlBlockDir] = rule_info("HtmlBlockDir", "HtmlBlockOpenDir (HtmlBlockDir | !HtmlBlockCloseDir .)* HtmlBlockCloseDir")
- Rules[:_HtmlBlockOpenDiv] = rule_info("HtmlBlockOpenDiv", "\"<\" Spnl (\"div\" | \"DIV\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseDiv] = rule_info("HtmlBlockCloseDiv", "\"<\" Spnl \"/\" (\"div\" | \"DIV\") Spnl \">\"")
- Rules[:_HtmlBlockDiv] = rule_info("HtmlBlockDiv", "HtmlBlockOpenDiv (HtmlBlockDiv | !HtmlBlockCloseDiv .)* HtmlBlockCloseDiv")
- Rules[:_HtmlBlockOpenDl] = rule_info("HtmlBlockOpenDl", "\"<\" Spnl (\"dl\" | \"DL\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseDl] = rule_info("HtmlBlockCloseDl", "\"<\" Spnl \"/\" (\"dl\" | \"DL\") Spnl \">\"")
- Rules[:_HtmlBlockDl] = rule_info("HtmlBlockDl", "HtmlBlockOpenDl (HtmlBlockDl | !HtmlBlockCloseDl .)* HtmlBlockCloseDl")
- Rules[:_HtmlBlockOpenFieldset] = rule_info("HtmlBlockOpenFieldset", "\"<\" Spnl (\"fieldset\" | \"FIELDSET\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseFieldset] = rule_info("HtmlBlockCloseFieldset", "\"<\" Spnl \"/\" (\"fieldset\" | \"FIELDSET\") Spnl \">\"")
- Rules[:_HtmlBlockFieldset] = rule_info("HtmlBlockFieldset", "HtmlBlockOpenFieldset (HtmlBlockFieldset | !HtmlBlockCloseFieldset .)* HtmlBlockCloseFieldset")
- Rules[:_HtmlBlockOpenForm] = rule_info("HtmlBlockOpenForm", "\"<\" Spnl (\"form\" | \"FORM\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseForm] = rule_info("HtmlBlockCloseForm", "\"<\" Spnl \"/\" (\"form\" | \"FORM\") Spnl \">\"")
- Rules[:_HtmlBlockForm] = rule_info("HtmlBlockForm", "HtmlBlockOpenForm (HtmlBlockForm | !HtmlBlockCloseForm .)* HtmlBlockCloseForm")
- Rules[:_HtmlBlockOpenH1] = rule_info("HtmlBlockOpenH1", "\"<\" Spnl (\"h1\" | \"H1\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseH1] = rule_info("HtmlBlockCloseH1", "\"<\" Spnl \"/\" (\"h1\" | \"H1\") Spnl \">\"")
- Rules[:_HtmlBlockH1] = rule_info("HtmlBlockH1", "HtmlBlockOpenH1 (HtmlBlockH1 | !HtmlBlockCloseH1 .)* HtmlBlockCloseH1")
- Rules[:_HtmlBlockOpenH2] = rule_info("HtmlBlockOpenH2", "\"<\" Spnl (\"h2\" | \"H2\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseH2] = rule_info("HtmlBlockCloseH2", "\"<\" Spnl \"/\" (\"h2\" | \"H2\") Spnl \">\"")
- Rules[:_HtmlBlockH2] = rule_info("HtmlBlockH2", "HtmlBlockOpenH2 (HtmlBlockH2 | !HtmlBlockCloseH2 .)* HtmlBlockCloseH2")
- Rules[:_HtmlBlockOpenH3] = rule_info("HtmlBlockOpenH3", "\"<\" Spnl (\"h3\" | \"H3\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseH3] = rule_info("HtmlBlockCloseH3", "\"<\" Spnl \"/\" (\"h3\" | \"H3\") Spnl \">\"")
- Rules[:_HtmlBlockH3] = rule_info("HtmlBlockH3", "HtmlBlockOpenH3 (HtmlBlockH3 | !HtmlBlockCloseH3 .)* HtmlBlockCloseH3")
- Rules[:_HtmlBlockOpenH4] = rule_info("HtmlBlockOpenH4", "\"<\" Spnl (\"h4\" | \"H4\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseH4] = rule_info("HtmlBlockCloseH4", "\"<\" Spnl \"/\" (\"h4\" | \"H4\") Spnl \">\"")
- Rules[:_HtmlBlockH4] = rule_info("HtmlBlockH4", "HtmlBlockOpenH4 (HtmlBlockH4 | !HtmlBlockCloseH4 .)* HtmlBlockCloseH4")
- Rules[:_HtmlBlockOpenH5] = rule_info("HtmlBlockOpenH5", "\"<\" Spnl (\"h5\" | \"H5\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseH5] = rule_info("HtmlBlockCloseH5", "\"<\" Spnl \"/\" (\"h5\" | \"H5\") Spnl \">\"")
- Rules[:_HtmlBlockH5] = rule_info("HtmlBlockH5", "HtmlBlockOpenH5 (HtmlBlockH5 | !HtmlBlockCloseH5 .)* HtmlBlockCloseH5")
- Rules[:_HtmlBlockOpenH6] = rule_info("HtmlBlockOpenH6", "\"<\" Spnl (\"h6\" | \"H6\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseH6] = rule_info("HtmlBlockCloseH6", "\"<\" Spnl \"/\" (\"h6\" | \"H6\") Spnl \">\"")
- Rules[:_HtmlBlockH6] = rule_info("HtmlBlockH6", "HtmlBlockOpenH6 (HtmlBlockH6 | !HtmlBlockCloseH6 .)* HtmlBlockCloseH6")
- Rules[:_HtmlBlockOpenMenu] = rule_info("HtmlBlockOpenMenu", "\"<\" Spnl (\"menu\" | \"MENU\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseMenu] = rule_info("HtmlBlockCloseMenu", "\"<\" Spnl \"/\" (\"menu\" | \"MENU\") Spnl \">\"")
- Rules[:_HtmlBlockMenu] = rule_info("HtmlBlockMenu", "HtmlBlockOpenMenu (HtmlBlockMenu | !HtmlBlockCloseMenu .)* HtmlBlockCloseMenu")
- Rules[:_HtmlBlockOpenNoframes] = rule_info("HtmlBlockOpenNoframes", "\"<\" Spnl (\"noframes\" | \"NOFRAMES\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseNoframes] = rule_info("HtmlBlockCloseNoframes", "\"<\" Spnl \"/\" (\"noframes\" | \"NOFRAMES\") Spnl \">\"")
- Rules[:_HtmlBlockNoframes] = rule_info("HtmlBlockNoframes", "HtmlBlockOpenNoframes (HtmlBlockNoframes | !HtmlBlockCloseNoframes .)* HtmlBlockCloseNoframes")
- Rules[:_HtmlBlockOpenNoscript] = rule_info("HtmlBlockOpenNoscript", "\"<\" Spnl (\"noscript\" | \"NOSCRIPT\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseNoscript] = rule_info("HtmlBlockCloseNoscript", "\"<\" Spnl \"/\" (\"noscript\" | \"NOSCRIPT\") Spnl \">\"")
- Rules[:_HtmlBlockNoscript] = rule_info("HtmlBlockNoscript", "HtmlBlockOpenNoscript (HtmlBlockNoscript | !HtmlBlockCloseNoscript .)* HtmlBlockCloseNoscript")
- Rules[:_HtmlBlockOpenOl] = rule_info("HtmlBlockOpenOl", "\"<\" Spnl (\"ol\" | \"OL\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseOl] = rule_info("HtmlBlockCloseOl", "\"<\" Spnl \"/\" (\"ol\" | \"OL\") Spnl \">\"")
- Rules[:_HtmlBlockOl] = rule_info("HtmlBlockOl", "HtmlBlockOpenOl (HtmlBlockOl | !HtmlBlockCloseOl .)* HtmlBlockCloseOl")
- Rules[:_HtmlBlockOpenP] = rule_info("HtmlBlockOpenP", "\"<\" Spnl (\"p\" | \"P\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseP] = rule_info("HtmlBlockCloseP", "\"<\" Spnl \"/\" (\"p\" | \"P\") Spnl \">\"")
- Rules[:_HtmlBlockP] = rule_info("HtmlBlockP", "HtmlBlockOpenP (HtmlBlockP | !HtmlBlockCloseP .)* HtmlBlockCloseP")
- Rules[:_HtmlBlockOpenPre] = rule_info("HtmlBlockOpenPre", "\"<\" Spnl (\"pre\" | \"PRE\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockClosePre] = rule_info("HtmlBlockClosePre", "\"<\" Spnl \"/\" (\"pre\" | \"PRE\") Spnl \">\"")
- Rules[:_HtmlBlockPre] = rule_info("HtmlBlockPre", "HtmlBlockOpenPre (HtmlBlockPre | !HtmlBlockClosePre .)* HtmlBlockClosePre")
- Rules[:_HtmlBlockOpenTable] = rule_info("HtmlBlockOpenTable", "\"<\" Spnl (\"table\" | \"TABLE\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseTable] = rule_info("HtmlBlockCloseTable", "\"<\" Spnl \"/\" (\"table\" | \"TABLE\") Spnl \">\"")
- Rules[:_HtmlBlockTable] = rule_info("HtmlBlockTable", "HtmlBlockOpenTable (HtmlBlockTable | !HtmlBlockCloseTable .)* HtmlBlockCloseTable")
- Rules[:_HtmlBlockOpenUl] = rule_info("HtmlBlockOpenUl", "\"<\" Spnl (\"ul\" | \"UL\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseUl] = rule_info("HtmlBlockCloseUl", "\"<\" Spnl \"/\" (\"ul\" | \"UL\") Spnl \">\"")
- Rules[:_HtmlBlockUl] = rule_info("HtmlBlockUl", "HtmlBlockOpenUl (HtmlBlockUl | !HtmlBlockCloseUl .)* HtmlBlockCloseUl")
- Rules[:_HtmlBlockOpenDd] = rule_info("HtmlBlockOpenDd", "\"<\" Spnl (\"dd\" | \"DD\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseDd] = rule_info("HtmlBlockCloseDd", "\"<\" Spnl \"/\" (\"dd\" | \"DD\") Spnl \">\"")
- Rules[:_HtmlBlockDd] = rule_info("HtmlBlockDd", "HtmlBlockOpenDd (HtmlBlockDd | !HtmlBlockCloseDd .)* HtmlBlockCloseDd")
- Rules[:_HtmlBlockOpenDt] = rule_info("HtmlBlockOpenDt", "\"<\" Spnl (\"dt\" | \"DT\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseDt] = rule_info("HtmlBlockCloseDt", "\"<\" Spnl \"/\" (\"dt\" | \"DT\") Spnl \">\"")
- Rules[:_HtmlBlockDt] = rule_info("HtmlBlockDt", "HtmlBlockOpenDt (HtmlBlockDt | !HtmlBlockCloseDt .)* HtmlBlockCloseDt")
- Rules[:_HtmlBlockOpenFrameset] = rule_info("HtmlBlockOpenFrameset", "\"<\" Spnl (\"frameset\" | \"FRAMESET\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseFrameset] = rule_info("HtmlBlockCloseFrameset", "\"<\" Spnl \"/\" (\"frameset\" | \"FRAMESET\") Spnl \">\"")
- Rules[:_HtmlBlockFrameset] = rule_info("HtmlBlockFrameset", "HtmlBlockOpenFrameset (HtmlBlockFrameset | !HtmlBlockCloseFrameset .)* HtmlBlockCloseFrameset")
- Rules[:_HtmlBlockOpenLi] = rule_info("HtmlBlockOpenLi", "\"<\" Spnl (\"li\" | \"LI\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseLi] = rule_info("HtmlBlockCloseLi", "\"<\" Spnl \"/\" (\"li\" | \"LI\") Spnl \">\"")
- Rules[:_HtmlBlockLi] = rule_info("HtmlBlockLi", "HtmlBlockOpenLi (HtmlBlockLi | !HtmlBlockCloseLi .)* HtmlBlockCloseLi")
- Rules[:_HtmlBlockOpenTbody] = rule_info("HtmlBlockOpenTbody", "\"<\" Spnl (\"tbody\" | \"TBODY\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseTbody] = rule_info("HtmlBlockCloseTbody", "\"<\" Spnl \"/\" (\"tbody\" | \"TBODY\") Spnl \">\"")
- Rules[:_HtmlBlockTbody] = rule_info("HtmlBlockTbody", "HtmlBlockOpenTbody (HtmlBlockTbody | !HtmlBlockCloseTbody .)* HtmlBlockCloseTbody")
- Rules[:_HtmlBlockOpenTd] = rule_info("HtmlBlockOpenTd", "\"<\" Spnl (\"td\" | \"TD\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseTd] = rule_info("HtmlBlockCloseTd", "\"<\" Spnl \"/\" (\"td\" | \"TD\") Spnl \">\"")
- Rules[:_HtmlBlockTd] = rule_info("HtmlBlockTd", "HtmlBlockOpenTd (HtmlBlockTd | !HtmlBlockCloseTd .)* HtmlBlockCloseTd")
- Rules[:_HtmlBlockOpenTfoot] = rule_info("HtmlBlockOpenTfoot", "\"<\" Spnl (\"tfoot\" | \"TFOOT\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseTfoot] = rule_info("HtmlBlockCloseTfoot", "\"<\" Spnl \"/\" (\"tfoot\" | \"TFOOT\") Spnl \">\"")
- Rules[:_HtmlBlockTfoot] = rule_info("HtmlBlockTfoot", "HtmlBlockOpenTfoot (HtmlBlockTfoot | !HtmlBlockCloseTfoot .)* HtmlBlockCloseTfoot")
- Rules[:_HtmlBlockOpenTh] = rule_info("HtmlBlockOpenTh", "\"<\" Spnl (\"th\" | \"TH\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseTh] = rule_info("HtmlBlockCloseTh", "\"<\" Spnl \"/\" (\"th\" | \"TH\") Spnl \">\"")
- Rules[:_HtmlBlockTh] = rule_info("HtmlBlockTh", "HtmlBlockOpenTh (HtmlBlockTh | !HtmlBlockCloseTh .)* HtmlBlockCloseTh")
- Rules[:_HtmlBlockOpenThead] = rule_info("HtmlBlockOpenThead", "\"<\" Spnl (\"thead\" | \"THEAD\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseThead] = rule_info("HtmlBlockCloseThead", "\"<\" Spnl \"/\" (\"thead\" | \"THEAD\") Spnl \">\"")
- Rules[:_HtmlBlockThead] = rule_info("HtmlBlockThead", "HtmlBlockOpenThead (HtmlBlockThead | !HtmlBlockCloseThead .)* HtmlBlockCloseThead")
- Rules[:_HtmlBlockOpenTr] = rule_info("HtmlBlockOpenTr", "\"<\" Spnl (\"tr\" | \"TR\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseTr] = rule_info("HtmlBlockCloseTr", "\"<\" Spnl \"/\" (\"tr\" | \"TR\") Spnl \">\"")
- Rules[:_HtmlBlockTr] = rule_info("HtmlBlockTr", "HtmlBlockOpenTr (HtmlBlockTr | !HtmlBlockCloseTr .)* HtmlBlockCloseTr")
- Rules[:_HtmlBlockOpenScript] = rule_info("HtmlBlockOpenScript", "\"<\" Spnl (\"script\" | \"SCRIPT\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseScript] = rule_info("HtmlBlockCloseScript", "\"<\" Spnl \"/\" (\"script\" | \"SCRIPT\") Spnl \">\"")
- Rules[:_HtmlBlockScript] = rule_info("HtmlBlockScript", "HtmlBlockOpenScript (!HtmlBlockCloseScript .)* HtmlBlockCloseScript")
- Rules[:_HtmlBlockOpenHead] = rule_info("HtmlBlockOpenHead", "\"<\" Spnl (\"head\" | \"HEAD\") Spnl HtmlAttribute* \">\"")
- Rules[:_HtmlBlockCloseHead] = rule_info("HtmlBlockCloseHead", "\"<\" Spnl \"/\" (\"head\" | \"HEAD\") Spnl \">\"")
- Rules[:_HtmlBlockHead] = rule_info("HtmlBlockHead", "HtmlBlockOpenHead (!HtmlBlockCloseHead .)* HtmlBlockCloseHead")
- Rules[:_HtmlBlockInTags] = rule_info("HtmlBlockInTags", "(HtmlAnchor | HtmlBlockAddress | HtmlBlockBlockquote | HtmlBlockCenter | HtmlBlockDir | HtmlBlockDiv | HtmlBlockDl | HtmlBlockFieldset | HtmlBlockForm | HtmlBlockH1 | HtmlBlockH2 | HtmlBlockH3 | HtmlBlockH4 | HtmlBlockH5 | HtmlBlockH6 | HtmlBlockMenu | HtmlBlockNoframes | HtmlBlockNoscript | HtmlBlockOl | HtmlBlockP | HtmlBlockPre | HtmlBlockTable | HtmlBlockUl | HtmlBlockDd | HtmlBlockDt | HtmlBlockFrameset | HtmlBlockLi | HtmlBlockTbody | HtmlBlockTd | HtmlBlockTfoot | HtmlBlockTh | HtmlBlockThead | HtmlBlockTr | HtmlBlockScript | HtmlBlockHead)")
- Rules[:_HtmlBlock] = rule_info("HtmlBlock", "< (HtmlBlockInTags | HtmlComment | HtmlBlockSelfClosing | HtmlUnclosed) > @BlankLine+ { if html? then RDoc::Markup::Raw.new text end }")
- Rules[:_HtmlUnclosed] = rule_info("HtmlUnclosed", "\"<\" Spnl HtmlUnclosedType Spnl HtmlAttribute* Spnl \">\"")
- Rules[:_HtmlUnclosedType] = rule_info("HtmlUnclosedType", "(\"HR\" | \"hr\")")
- Rules[:_HtmlBlockSelfClosing] = rule_info("HtmlBlockSelfClosing", "\"<\" Spnl HtmlBlockType Spnl HtmlAttribute* \"/\" Spnl \">\"")
- Rules[:_HtmlBlockType] = rule_info("HtmlBlockType", "(\"ADDRESS\" | \"BLOCKQUOTE\" | \"CENTER\" | \"DD\" | \"DIR\" | \"DIV\" | \"DL\" | \"DT\" | \"FIELDSET\" | \"FORM\" | \"FRAMESET\" | \"H1\" | \"H2\" | \"H3\" | \"H4\" | \"H5\" | \"H6\" | \"HR\" | \"ISINDEX\" | \"LI\" | \"MENU\" | \"NOFRAMES\" | \"NOSCRIPT\" | \"OL\" | \"P\" | \"PRE\" | \"SCRIPT\" | \"TABLE\" | \"TBODY\" | \"TD\" | \"TFOOT\" | \"TH\" | \"THEAD\" | \"TR\" | \"UL\" | \"address\" | \"blockquote\" | \"center\" | \"dd\" | \"dir\" | \"div\" | \"dl\" | \"dt\" | \"fieldset\" | \"form\" | \"frameset\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"hr\" | \"isindex\" | \"li\" | \"menu\" | \"noframes\" | \"noscript\" | \"ol\" | \"p\" | \"pre\" | \"script\" | \"table\" | \"tbody\" | \"td\" | \"tfoot\" | \"th\" | \"thead\" | \"tr\" | \"ul\")")
- Rules[:_StyleOpen] = rule_info("StyleOpen", "\"<\" Spnl (\"style\" | \"STYLE\") Spnl HtmlAttribute* \">\"")
- 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 !(&{ 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 }")
- Rules[:_StrChunk] = rule_info("StrChunk", "< (@NormalChar | /_+/ &Alphanumeric)+ > { text }")
- Rules[:_EscapedChar] = rule_info("EscapedChar", "\"\\\\\" !@Newline < /[:\\\\`|*_{}\\[\\]()\#+.!><-]/ > { text }")
- Rules[:_Entity] = rule_info("Entity", "(HexEntity | DecEntity | CharEntity):a { a }")
- Rules[:_Endline] = rule_info("Endline", "(@LineBreak | @TerminalEndline | @NormalEndline)")
- Rules[:_NormalEndline] = rule_info("NormalEndline", "@Sp @Newline !@BlankLine !\">\" !AtxStart !(Line /={1,}|-{1,}/ @Newline) { \"\\n\" }")
- Rules[:_TerminalEndline] = rule_info("TerminalEndline", "@Sp @Newline @Eof")
- Rules[:_LineBreak] = rule_info("LineBreak", "\" \" @NormalEndline { RDoc::Markup::HardBreak.new }")
- Rules[:_Symbol] = rule_info("Symbol", "< @SpecialChar > { text }")
- Rules[:_UlOrStarLine] = rule_info("UlOrStarLine", "(UlLine | StarLine):a { a }")
- Rules[:_StarLine] = rule_info("StarLine", "(< /\\*{4,}/ > { text } | < @Spacechar /\\*+/ &@Spacechar > { text })")
- Rules[:_UlLine] = rule_info("UlLine", "(< /_{4,}/ > { text } | < @Spacechar /_+/ &@Spacechar > { text })")
- Rules[:_Emph] = rule_info("Emph", "(EmphStar | EmphUl)")
- Rules[:_Whitespace] = rule_info("Whitespace", "(@Spacechar | @Newline)")
- Rules[:_EmphStar] = rule_info("EmphStar", "\"*\" !@Whitespace @StartList:a (!\"*\" Inline:b { a << b } | StrongStar:b { a << b })+ \"*\" { emphasis a.join }")
- Rules[:_EmphUl] = rule_info("EmphUl", "\"_\" !@Whitespace @StartList:a (!\"_\" Inline:b { a << b } | StrongUl:b { a << b })+ \"_\" { emphasis a.join }")
- Rules[:_Strong] = rule_info("Strong", "(StrongStar | StrongUl)")
- Rules[:_StrongStar] = rule_info("StrongStar", "\"**\" !@Whitespace @StartList:a (!\"**\" Inline:b { a << b })+ \"**\" { strong a.join }")
- Rules[:_StrongUl] = rule_info("StrongUl", "\"__\" !@Whitespace @StartList:a (!\"__\" Inline:b { a << b })+ \"__\" { strong a.join }")
- Rules[:_Strike] = rule_info("Strike", "&{ strike? } \"~~\" !@Whitespace @StartList:a (!\"~~\" Inline:b { a << b })+ \"~~\" { strike a.join }")
- Rules[:_Image] = rule_info("Image", "\"!\" (ExplicitLink | ReferenceLink):a { \"rdoc-image:\#{a[/\\[(.*)\\]/, 1]}\" }")
- Rules[:_Link] = rule_info("Link", "(ExplicitLink | ReferenceLink | AutoLink)")
- Rules[:_ReferenceLink] = rule_info("ReferenceLink", "(ReferenceLinkDouble | ReferenceLinkSingle)")
- Rules[:_ReferenceLinkDouble] = rule_info("ReferenceLinkDouble", "Label:content < Spnl > !\"[]\" Label:label { link_to content, label, text }")
- Rules[:_ReferenceLinkSingle] = rule_info("ReferenceLinkSingle", "Label:content < (Spnl \"[]\")? > { link_to content, content, text }")
- Rules[:_ExplicitLink] = rule_info("ExplicitLink", "Label:l \"(\" @Sp Source:s Spnl Title @Sp \")\" { \"{\#{l}}[\#{s}]\" }")
- Rules[:_Source] = rule_info("Source", "(\"<\" < SourceContents > \">\" | < SourceContents >) { text }")
- Rules[:_SourceContents] = rule_info("SourceContents", "((!\"(\" !\")\" !\">\" Nonspacechar)+ | \"(\" SourceContents \")\")*")
- Rules[:_Title] = rule_info("Title", "(TitleSingle | TitleDouble | \"\"):a { a }")
- Rules[:_TitleSingle] = rule_info("TitleSingle", "\"'\" (!(\"'\" @Sp (\")\" | @Newline)) .)* \"'\"")
- Rules[:_TitleDouble] = rule_info("TitleDouble", "\"\\\"\" (!(\"\\\"\" @Sp (\")\" | @Newline)) .)* \"\\\"\"")
- Rules[:_AutoLink] = rule_info("AutoLink", "(AutoLinkUrl | AutoLinkEmail)")
- Rules[:_AutoLinkUrl] = rule_info("AutoLinkUrl", "\"<\" < /[A-Za-z]+/ \"://\" (!@Newline !\">\" .)+ > \">\" { text }")
- Rules[:_AutoLinkEmail] = rule_info("AutoLinkEmail", "\"<\" \"mailto:\"? < /[\\w+.\\/!%~$-]+/i \"@\" (!@Newline !\">\" .)+ > \">\" { \"mailto:\#{text}\" }")
- Rules[:_Reference] = rule_info("Reference", "@NonindentSpace !\"[]\" Label:label \":\" Spnl RefSrc:link RefTitle @BlankLine+ { \# TODO use title reference label, link nil }")
- Rules[:_Label] = rule_info("Label", "\"[\" (!\"^\" &{ notes? } | &. &{ !notes? }) @StartList:a (!\"]\" Inline:l { a << l })* \"]\" { a.join.gsub(/\\s+/, ' ') }")
- Rules[:_RefSrc] = rule_info("RefSrc", "< Nonspacechar+ > { text }")
- Rules[:_RefTitle] = rule_info("RefTitle", "(RefTitleSingle | RefTitleDouble | RefTitleParens | EmptyTitle)")
- Rules[:_EmptyTitle] = rule_info("EmptyTitle", "\"\"")
- Rules[:_RefTitleSingle] = rule_info("RefTitleSingle", "Spnl \"'\" < (!(\"'\" @Sp @Newline | @Newline) .)* > \"'\" { text }")
- Rules[:_RefTitleDouble] = rule_info("RefTitleDouble", "Spnl \"\\\"\" < (!(\"\\\"\" @Sp @Newline | @Newline) .)* > \"\\\"\" { text }")
- Rules[:_RefTitleParens] = rule_info("RefTitleParens", "Spnl \"(\" < (!(\")\" @Sp @Newline | @Newline) .)* > \")\" { text }")
- Rules[:_References] = rule_info("References", "(Reference | SkipBlock)*")
- Rules[:_Ticks1] = rule_info("Ticks1", "\"`\" !\"`\"")
- Rules[:_Ticks2] = rule_info("Ticks2", "\"``\" !\"`\"")
- Rules[:_Ticks3] = rule_info("Ticks3", "\"```\" !\"`\"")
- Rules[:_Ticks4] = rule_info("Ticks4", "\"````\" !\"`\"")
- Rules[:_Ticks5] = rule_info("Ticks5", "\"`````\" !\"`\"")
- Rules[:_Code] = rule_info("Code", "(Ticks1 @Sp < ((!\"`\" Nonspacechar)+ | !Ticks1 /`+/ | !(@Sp Ticks1) (@Spacechar | @Newline !@BlankLine))+ > @Sp Ticks1 | Ticks2 @Sp < ((!\"`\" Nonspacechar)+ | !Ticks2 /`+/ | !(@Sp Ticks2) (@Spacechar | @Newline !@BlankLine))+ > @Sp Ticks2 | Ticks3 @Sp < ((!\"`\" Nonspacechar)+ | !Ticks3 /`+/ | !(@Sp Ticks3) (@Spacechar | @Newline !@BlankLine))+ > @Sp Ticks3 | Ticks4 @Sp < ((!\"`\" Nonspacechar)+ | !Ticks4 /`+/ | !(@Sp Ticks4) (@Spacechar | @Newline !@BlankLine))+ > @Sp Ticks4 | Ticks5 @Sp < ((!\"`\" Nonspacechar)+ | !Ticks5 /`+/ | !(@Sp Ticks5) (@Spacechar | @Newline !@BlankLine))+ > @Sp Ticks5) { \"<code>\#{text}</code>\" }")
- Rules[:_RawHtml] = rule_info("RawHtml", "< (HtmlComment | HtmlBlockScript | HtmlTag) > { if html? then text else '' end }")
- Rules[:_BlankLine] = rule_info("BlankLine", "@Sp @Newline { \"\\n\" }")
- Rules[:_Quoted] = rule_info("Quoted", "(\"\\\"\" (!\"\\\"\" .)* \"\\\"\" | \"'\" (!\"'\" .)* \"'\")")
- Rules[:_HtmlAttribute] = rule_info("HtmlAttribute", "(AlphanumericAscii | \"-\")+ Spnl (\"=\" Spnl (Quoted | (!\">\" Nonspacechar)+))? Spnl")
- Rules[:_HtmlComment] = rule_info("HtmlComment", "\"<!--\" (!\"-->\" .)* \"-->\"")
- Rules[:_HtmlTag] = rule_info("HtmlTag", "\"<\" Spnl \"/\"? AlphanumericAscii+ Spnl HtmlAttribute* \"/\"? Spnl \">\"")
- Rules[:_Eof] = rule_info("Eof", "!.")
- Rules[:_Nonspacechar] = rule_info("Nonspacechar", "!@Spacechar !@Newline .")
- Rules[:_Sp] = rule_info("Sp", "@Spacechar*")
- Rules[:_Spnl] = rule_info("Spnl", "@Sp (@Newline @Sp)?")
- Rules[:_SpecialChar] = rule_info("SpecialChar", "(/[~*_`&\\[\\]()<!\#\\\\'\"]/ | @ExtendedSpecialChar)")
- Rules[:_NormalChar] = rule_info("NormalChar", "!(@SpecialChar | @Spacechar | @Newline) .")
- Rules[:_Digit] = rule_info("Digit", "[0-9]")
- Rules[:_Alphanumeric] = rule_info("Alphanumeric", "%literals.Alphanumeric")
- Rules[:_AlphanumericAscii] = rule_info("AlphanumericAscii", "%literals.AlphanumericAscii")
- Rules[:_BOM] = rule_info("BOM", "%literals.BOM")
- Rules[:_Newline] = rule_info("Newline", "%literals.Newline")
- Rules[:_Spacechar] = rule_info("Spacechar", "%literals.Spacechar")
- Rules[:_HexEntity] = rule_info("HexEntity", "/&\#x/i < /[0-9a-fA-F]+/ > \";\" { [text.to_i(16)].pack 'U' }")
- Rules[:_DecEntity] = rule_info("DecEntity", "\"&\#\" < /[0-9]+/ > \";\" { [text.to_i].pack 'U' }")
- Rules[:_CharEntity] = rule_info("CharEntity", "\"&\" < /[A-Za-z0-9]+/ > \";\" { if entity = HTML_ENTITIES[text] then entity.pack 'U*' else \"&\#{text};\" end }")
- Rules[:_NonindentSpace] = rule_info("NonindentSpace", "/ {0,3}/")
- Rules[:_Indent] = rule_info("Indent", "/\\t| /")
- Rules[:_IndentedLine] = rule_info("IndentedLine", "Indent Line")
- Rules[:_OptionallyIndentedLine] = rule_info("OptionallyIndentedLine", "Indent? Line")
- Rules[:_StartList] = rule_info("StartList", "&. { [] }")
- Rules[:_Line] = rule_info("Line", "@RawLine:a { a }")
- Rules[:_RawLine] = rule_info("RawLine", "(< /[^\\r\\n]*/ @Newline > | < .+ > @Eof) { text }")
- Rules[:_SkipBlock] = rule_info("SkipBlock", "(HtmlBlock | (!\"\#\" !SetextBottom1 !SetextBottom2 !@BlankLine @RawLine)+ @BlankLine* | @BlankLine+ | @RawLine)")
- Rules[:_ExtendedSpecialChar] = rule_info("ExtendedSpecialChar", "&{ notes? } \"^\"")
- Rules[:_NoteReference] = rule_info("NoteReference", "&{ notes? } RawNoteReference:ref { note_for ref }")
- Rules[:_RawNoteReference] = rule_info("RawNoteReference", "\"[^\" < (!@Newline !\"]\" .)+ > \"]\" { text }")
- Rules[:_Note] = rule_info("Note", "&{ notes? } @NonindentSpace RawNoteReference:ref \":\" @Sp @StartList:a RawNoteBlock:i { a.concat i } (&Indent RawNoteBlock:i { a.concat i })* { @footnotes[ref] = paragraph a nil }")
- Rules[:_InlineNote] = rule_info("InlineNote", "&{ notes? } \"^[\" @StartList:a (!\"]\" Inline:l { a << l })+ \"]\" { ref = [:inline, @note_order.length] @footnotes[ref] = paragraph a note_for ref }")
- Rules[:_Notes] = rule_info("Notes", "(Note | SkipBlock)*")
- Rules[:_RawNoteBlock] = rule_info("RawNoteBlock", "@StartList:a (!@BlankLine !RawNoteReference 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? } TableHead:header TableLine:line TableRow+:body { table = RDoc::Markup::Table.new(header, line, body) }")
- Rules[:_TableHead] = rule_info("TableHead", "TableItem2+:items \"|\"? @Newline { items }")
- Rules[:_TableRow] = rule_info("TableRow", "((TableItem:item1 TableItem2*:items { [item1, *items] }):row | TableItem2+:row) \"|\"? @Newline { row }")
- Rules[:_TableItem2] = rule_info("TableItem2", "\"|\" TableItem")
- Rules[:_TableItem] = rule_info("TableItem", "< /(?:\\\\.|[^|\\n])+/ > { text.strip.gsub(/\\\\(.)/, '\\1') }")
- Rules[:_TableLine] = rule_info("TableLine", "((TableAlign:align1 TableAlign2*:aligns {[align1, *aligns] }):line | TableAlign2+:line) \"|\"? @Newline { line }")
- Rules[:_TableAlign2] = rule_info("TableAlign2", "\"|\" @Sp TableAlign")
- Rules[:_TableAlign] = rule_info("TableAlign", "< /:?-+:?/ > @Sp { text.start_with?(\":\") ? (text.end_with?(\":\") ? :center : :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", "Inline:label @Sp @Newline { label }")
- Rules[:_DefinitionListDefinition] = rule_info("DefinitionListDefinition", "@NonindentSpace \":\" @Space Inlines:a @BlankLine+ { paragraph a }")
- # :startdoc:
-end
diff --git a/lib/rdoc/markdown/entities.rb b/lib/rdoc/markdown/entities.rb
deleted file mode 100644
index 265c2eb3f3..0000000000
--- a/lib/rdoc/markdown/entities.rb
+++ /dev/null
@@ -1,2131 +0,0 @@
-# frozen_string_literal: true
-##
-# HTML entity name map for RDoc::Markdown
-
-RDoc::Markdown::HTML_ENTITIES = {
- "AElig" => [0x000C6],
- "AMP" => [0x00026],
- "Aacute" => [0x000C1],
- "Abreve" => [0x00102],
- "Acirc" => [0x000C2],
- "Acy" => [0x00410],
- "Afr" => [0x1D504],
- "Agrave" => [0x000C0],
- "Alpha" => [0x00391],
- "Amacr" => [0x00100],
- "And" => [0x02A53],
- "Aogon" => [0x00104],
- "Aopf" => [0x1D538],
- "ApplyFunction" => [0x02061],
- "Aring" => [0x000C5],
- "Ascr" => [0x1D49C],
- "Assign" => [0x02254],
- "Atilde" => [0x000C3],
- "Auml" => [0x000C4],
- "Backslash" => [0x02216],
- "Barv" => [0x02AE7],
- "Barwed" => [0x02306],
- "Bcy" => [0x00411],
- "Because" => [0x02235],
- "Bernoullis" => [0x0212C],
- "Beta" => [0x00392],
- "Bfr" => [0x1D505],
- "Bopf" => [0x1D539],
- "Breve" => [0x002D8],
- "Bscr" => [0x0212C],
- "Bumpeq" => [0x0224E],
- "CHcy" => [0x00427],
- "COPY" => [0x000A9],
- "Cacute" => [0x00106],
- "Cap" => [0x022D2],
- "CapitalDifferentialD" => [0x02145],
- "Cayleys" => [0x0212D],
- "Ccaron" => [0x0010C],
- "Ccedil" => [0x000C7],
- "Ccirc" => [0x00108],
- "Cconint" => [0x02230],
- "Cdot" => [0x0010A],
- "Cedilla" => [0x000B8],
- "CenterDot" => [0x000B7],
- "Cfr" => [0x0212D],
- "Chi" => [0x003A7],
- "CircleDot" => [0x02299],
- "CircleMinus" => [0x02296],
- "CirclePlus" => [0x02295],
- "CircleTimes" => [0x02297],
- "ClockwiseContourIntegral" => [0x02232],
- "CloseCurlyDoubleQuote" => [0x0201D],
- "CloseCurlyQuote" => [0x02019],
- "Colon" => [0x02237],
- "Colone" => [0x02A74],
- "Congruent" => [0x02261],
- "Conint" => [0x0222F],
- "ContourIntegral" => [0x0222E],
- "Copf" => [0x02102],
- "Coproduct" => [0x02210],
- "CounterClockwiseContourIntegral" => [0x02233],
- "Cross" => [0x02A2F],
- "Cscr" => [0x1D49E],
- "Cup" => [0x022D3],
- "CupCap" => [0x0224D],
- "DD" => [0x02145],
- "DDotrahd" => [0x02911],
- "DJcy" => [0x00402],
- "DScy" => [0x00405],
- "DZcy" => [0x0040F],
- "Dagger" => [0x02021],
- "Darr" => [0x021A1],
- "Dashv" => [0x02AE4],
- "Dcaron" => [0x0010E],
- "Dcy" => [0x00414],
- "Del" => [0x02207],
- "Delta" => [0x00394],
- "Dfr" => [0x1D507],
- "DiacriticalAcute" => [0x000B4],
- "DiacriticalDot" => [0x002D9],
- "DiacriticalDoubleAcute" => [0x002DD],
- "DiacriticalGrave" => [0x00060],
- "DiacriticalTilde" => [0x002DC],
- "Diamond" => [0x022C4],
- "DifferentialD" => [0x02146],
- "Dopf" => [0x1D53B],
- "Dot" => [0x000A8],
- "DotDot" => [0x020DC],
- "DotEqual" => [0x02250],
- "DoubleContourIntegral" => [0x0222F],
- "DoubleDot" => [0x000A8],
- "DoubleDownArrow" => [0x021D3],
- "DoubleLeftArrow" => [0x021D0],
- "DoubleLeftRightArrow" => [0x021D4],
- "DoubleLeftTee" => [0x02AE4],
- "DoubleLongLeftArrow" => [0x027F8],
- "DoubleLongLeftRightArrow" => [0x027FA],
- "DoubleLongRightArrow" => [0x027F9],
- "DoubleRightArrow" => [0x021D2],
- "DoubleRightTee" => [0x022A8],
- "DoubleUpArrow" => [0x021D1],
- "DoubleUpDownArrow" => [0x021D5],
- "DoubleVerticalBar" => [0x02225],
- "DownArrow" => [0x02193],
- "DownArrowBar" => [0x02913],
- "DownArrowUpArrow" => [0x021F5],
- "DownBreve" => [0x00311],
- "DownLeftRightVector" => [0x02950],
- "DownLeftTeeVector" => [0x0295E],
- "DownLeftVector" => [0x021BD],
- "DownLeftVectorBar" => [0x02956],
- "DownRightTeeVector" => [0x0295F],
- "DownRightVector" => [0x021C1],
- "DownRightVectorBar" => [0x02957],
- "DownTee" => [0x022A4],
- "DownTeeArrow" => [0x021A7],
- "Downarrow" => [0x021D3],
- "Dscr" => [0x1D49F],
- "Dstrok" => [0x00110],
- "ENG" => [0x0014A],
- "ETH" => [0x000D0],
- "Eacute" => [0x000C9],
- "Ecaron" => [0x0011A],
- "Ecirc" => [0x000CA],
- "Ecy" => [0x0042D],
- "Edot" => [0x00116],
- "Efr" => [0x1D508],
- "Egrave" => [0x000C8],
- "Element" => [0x02208],
- "Emacr" => [0x00112],
- "EmptySmallSquare" => [0x025FB],
- "EmptyVerySmallSquare" => [0x025AB],
- "Eogon" => [0x00118],
- "Eopf" => [0x1D53C],
- "Epsilon" => [0x00395],
- "Equal" => [0x02A75],
- "EqualTilde" => [0x02242],
- "Equilibrium" => [0x021CC],
- "Escr" => [0x02130],
- "Esim" => [0x02A73],
- "Eta" => [0x00397],
- "Euml" => [0x000CB],
- "Exists" => [0x02203],
- "ExponentialE" => [0x02147],
- "Fcy" => [0x00424],
- "Ffr" => [0x1D509],
- "FilledSmallSquare" => [0x025FC],
- "FilledVerySmallSquare" => [0x025AA],
- "Fopf" => [0x1D53D],
- "ForAll" => [0x02200],
- "Fouriertrf" => [0x02131],
- "Fscr" => [0x02131],
- "GJcy" => [0x00403],
- "GT" => [0x0003E],
- "Gamma" => [0x00393],
- "Gammad" => [0x003DC],
- "Gbreve" => [0x0011E],
- "Gcedil" => [0x00122],
- "Gcirc" => [0x0011C],
- "Gcy" => [0x00413],
- "Gdot" => [0x00120],
- "Gfr" => [0x1D50A],
- "Gg" => [0x022D9],
- "Gopf" => [0x1D53E],
- "GreaterEqual" => [0x02265],
- "GreaterEqualLess" => [0x022DB],
- "GreaterFullEqual" => [0x02267],
- "GreaterGreater" => [0x02AA2],
- "GreaterLess" => [0x02277],
- "GreaterSlantEqual" => [0x02A7E],
- "GreaterTilde" => [0x02273],
- "Gscr" => [0x1D4A2],
- "Gt" => [0x0226B],
- "HARDcy" => [0x0042A],
- "Hacek" => [0x002C7],
- "Hat" => [0x0005E],
- "Hcirc" => [0x00124],
- "Hfr" => [0x0210C],
- "HilbertSpace" => [0x0210B],
- "Hopf" => [0x0210D],
- "HorizontalLine" => [0x02500],
- "Hscr" => [0x0210B],
- "Hstrok" => [0x00126],
- "HumpDownHump" => [0x0224E],
- "HumpEqual" => [0x0224F],
- "IEcy" => [0x00415],
- "IJlig" => [0x00132],
- "IOcy" => [0x00401],
- "Iacute" => [0x000CD],
- "Icirc" => [0x000CE],
- "Icy" => [0x00418],
- "Idot" => [0x00130],
- "Ifr" => [0x02111],
- "Igrave" => [0x000CC],
- "Im" => [0x02111],
- "Imacr" => [0x0012A],
- "ImaginaryI" => [0x02148],
- "Implies" => [0x021D2],
- "Int" => [0x0222C],
- "Integral" => [0x0222B],
- "Intersection" => [0x022C2],
- "InvisibleComma" => [0x02063],
- "InvisibleTimes" => [0x02062],
- "Iogon" => [0x0012E],
- "Iopf" => [0x1D540],
- "Iota" => [0x00399],
- "Iscr" => [0x02110],
- "Itilde" => [0x00128],
- "Iukcy" => [0x00406],
- "Iuml" => [0x000CF],
- "Jcirc" => [0x00134],
- "Jcy" => [0x00419],
- "Jfr" => [0x1D50D],
- "Jopf" => [0x1D541],
- "Jscr" => [0x1D4A5],
- "Jsercy" => [0x00408],
- "Jukcy" => [0x00404],
- "KHcy" => [0x00425],
- "KJcy" => [0x0040C],
- "Kappa" => [0x0039A],
- "Kcedil" => [0x00136],
- "Kcy" => [0x0041A],
- "Kfr" => [0x1D50E],
- "Kopf" => [0x1D542],
- "Kscr" => [0x1D4A6],
- "LJcy" => [0x00409],
- "LT" => [0x0003C],
- "Lacute" => [0x00139],
- "Lambda" => [0x0039B],
- "Lang" => [0x027EA],
- "Laplacetrf" => [0x02112],
- "Larr" => [0x0219E],
- "Lcaron" => [0x0013D],
- "Lcedil" => [0x0013B],
- "Lcy" => [0x0041B],
- "LeftAngleBracket" => [0x027E8],
- "LeftArrow" => [0x02190],
- "LeftArrowBar" => [0x021E4],
- "LeftArrowRightArrow" => [0x021C6],
- "LeftCeiling" => [0x02308],
- "LeftDoubleBracket" => [0x027E6],
- "LeftDownTeeVector" => [0x02961],
- "LeftDownVector" => [0x021C3],
- "LeftDownVectorBar" => [0x02959],
- "LeftFloor" => [0x0230A],
- "LeftRightArrow" => [0x02194],
- "LeftRightVector" => [0x0294E],
- "LeftTee" => [0x022A3],
- "LeftTeeArrow" => [0x021A4],
- "LeftTeeVector" => [0x0295A],
- "LeftTriangle" => [0x022B2],
- "LeftTriangleBar" => [0x029CF],
- "LeftTriangleEqual" => [0x022B4],
- "LeftUpDownVector" => [0x02951],
- "LeftUpTeeVector" => [0x02960],
- "LeftUpVector" => [0x021BF],
- "LeftUpVectorBar" => [0x02958],
- "LeftVector" => [0x021BC],
- "LeftVectorBar" => [0x02952],
- "Leftarrow" => [0x021D0],
- "Leftrightarrow" => [0x021D4],
- "LessEqualGreater" => [0x022DA],
- "LessFullEqual" => [0x02266],
- "LessGreater" => [0x02276],
- "LessLess" => [0x02AA1],
- "LessSlantEqual" => [0x02A7D],
- "LessTilde" => [0x02272],
- "Lfr" => [0x1D50F],
- "Ll" => [0x022D8],
- "Lleftarrow" => [0x021DA],
- "Lmidot" => [0x0013F],
- "LongLeftArrow" => [0x027F5],
- "LongLeftRightArrow" => [0x027F7],
- "LongRightArrow" => [0x027F6],
- "Longleftarrow" => [0x027F8],
- "Longleftrightarrow" => [0x027FA],
- "Longrightarrow" => [0x027F9],
- "Lopf" => [0x1D543],
- "LowerLeftArrow" => [0x02199],
- "LowerRightArrow" => [0x02198],
- "Lscr" => [0x02112],
- "Lsh" => [0x021B0],
- "Lstrok" => [0x00141],
- "Lt" => [0x0226A],
- "Map" => [0x02905],
- "Mcy" => [0x0041C],
- "MediumSpace" => [0x0205F],
- "Mellintrf" => [0x02133],
- "Mfr" => [0x1D510],
- "MinusPlus" => [0x02213],
- "Mopf" => [0x1D544],
- "Mscr" => [0x02133],
- "Mu" => [0x0039C],
- "NJcy" => [0x0040A],
- "Nacute" => [0x00143],
- "Ncaron" => [0x00147],
- "Ncedil" => [0x00145],
- "Ncy" => [0x0041D],
- "NegativeMediumSpace" => [0x0200B],
- "NegativeThickSpace" => [0x0200B],
- "NegativeThinSpace" => [0x0200B],
- "NegativeVeryThinSpace" => [0x0200B],
- "NestedGreaterGreater" => [0x0226B],
- "NestedLessLess" => [0x0226A],
- "NewLine" => [0x0000A],
- "Nfr" => [0x1D511],
- "NoBreak" => [0x02060],
- "NonBreakingSpace" => [0x000A0],
- "Nopf" => [0x02115],
- "Not" => [0x02AEC],
- "NotCongruent" => [0x02262],
- "NotCupCap" => [0x0226D],
- "NotDoubleVerticalBar" => [0x02226],
- "NotElement" => [0x02209],
- "NotEqual" => [0x02260],
- "NotEqualTilde" => [0x02242, 0x00338],
- "NotExists" => [0x02204],
- "NotGreater" => [0x0226F],
- "NotGreaterEqual" => [0x02271],
- "NotGreaterFullEqual" => [0x02267, 0x00338],
- "NotGreaterGreater" => [0x0226B, 0x00338],
- "NotGreaterLess" => [0x02279],
- "NotGreaterSlantEqual" => [0x02A7E, 0x00338],
- "NotGreaterTilde" => [0x02275],
- "NotHumpDownHump" => [0x0224E, 0x00338],
- "NotHumpEqual" => [0x0224F, 0x00338],
- "NotLeftTriangle" => [0x022EA],
- "NotLeftTriangleBar" => [0x029CF, 0x00338],
- "NotLeftTriangleEqual" => [0x022EC],
- "NotLess" => [0x0226E],
- "NotLessEqual" => [0x02270],
- "NotLessGreater" => [0x02278],
- "NotLessLess" => [0x0226A, 0x00338],
- "NotLessSlantEqual" => [0x02A7D, 0x00338],
- "NotLessTilde" => [0x02274],
- "NotNestedGreaterGreater" => [0x02AA2, 0x00338],
- "NotNestedLessLess" => [0x02AA1, 0x00338],
- "NotPrecedes" => [0x02280],
- "NotPrecedesEqual" => [0x02AAF, 0x00338],
- "NotPrecedesSlantEqual" => [0x022E0],
- "NotReverseElement" => [0x0220C],
- "NotRightTriangle" => [0x022EB],
- "NotRightTriangleBar" => [0x029D0, 0x00338],
- "NotRightTriangleEqual" => [0x022ED],
- "NotSquareSubset" => [0x0228F, 0x00338],
- "NotSquareSubsetEqual" => [0x022E2],
- "NotSquareSuperset" => [0x02290, 0x00338],
- "NotSquareSupersetEqual" => [0x022E3],
- "NotSubset" => [0x02282, 0x020D2],
- "NotSubsetEqual" => [0x02288],
- "NotSucceeds" => [0x02281],
- "NotSucceedsEqual" => [0x02AB0, 0x00338],
- "NotSucceedsSlantEqual" => [0x022E1],
- "NotSucceedsTilde" => [0x0227F, 0x00338],
- "NotSuperset" => [0x02283, 0x020D2],
- "NotSupersetEqual" => [0x02289],
- "NotTilde" => [0x02241],
- "NotTildeEqual" => [0x02244],
- "NotTildeFullEqual" => [0x02247],
- "NotTildeTilde" => [0x02249],
- "NotVerticalBar" => [0x02224],
- "Nscr" => [0x1D4A9],
- "Ntilde" => [0x000D1],
- "Nu" => [0x0039D],
- "OElig" => [0x00152],
- "Oacute" => [0x000D3],
- "Ocirc" => [0x000D4],
- "Ocy" => [0x0041E],
- "Odblac" => [0x00150],
- "Ofr" => [0x1D512],
- "Ograve" => [0x000D2],
- "Omacr" => [0x0014C],
- "Omega" => [0x003A9],
- "Omicron" => [0x0039F],
- "Oopf" => [0x1D546],
- "OpenCurlyDoubleQuote" => [0x0201C],
- "OpenCurlyQuote" => [0x02018],
- "Or" => [0x02A54],
- "Oscr" => [0x1D4AA],
- "Oslash" => [0x000D8],
- "Otilde" => [0x000D5],
- "Otimes" => [0x02A37],
- "Ouml" => [0x000D6],
- "OverBar" => [0x0203E],
- "OverBrace" => [0x023DE],
- "OverBracket" => [0x023B4],
- "OverParenthesis" => [0x023DC],
- "PartialD" => [0x02202],
- "Pcy" => [0x0041F],
- "Pfr" => [0x1D513],
- "Phi" => [0x003A6],
- "Pi" => [0x003A0],
- "PlusMinus" => [0x000B1],
- "Poincareplane" => [0x0210C],
- "Popf" => [0x02119],
- "Pr" => [0x02ABB],
- "Precedes" => [0x0227A],
- "PrecedesEqual" => [0x02AAF],
- "PrecedesSlantEqual" => [0x0227C],
- "PrecedesTilde" => [0x0227E],
- "Prime" => [0x02033],
- "Product" => [0x0220F],
- "Proportion" => [0x02237],
- "Proportional" => [0x0221D],
- "Pscr" => [0x1D4AB],
- "Psi" => [0x003A8],
- "QUOT" => [0x00022],
- "Qfr" => [0x1D514],
- "Qopf" => [0x0211A],
- "Qscr" => [0x1D4AC],
- "RBarr" => [0x02910],
- "REG" => [0x000AE],
- "Racute" => [0x00154],
- "Rang" => [0x027EB],
- "Rarr" => [0x021A0],
- "Rarrtl" => [0x02916],
- "Rcaron" => [0x00158],
- "Rcedil" => [0x00156],
- "Rcy" => [0x00420],
- "Re" => [0x0211C],
- "ReverseElement" => [0x0220B],
- "ReverseEquilibrium" => [0x021CB],
- "ReverseUpEquilibrium" => [0x0296F],
- "Rfr" => [0x0211C],
- "Rho" => [0x003A1],
- "RightAngleBracket" => [0x027E9],
- "RightArrow" => [0x02192],
- "RightArrowBar" => [0x021E5],
- "RightArrowLeftArrow" => [0x021C4],
- "RightCeiling" => [0x02309],
- "RightDoubleBracket" => [0x027E7],
- "RightDownTeeVector" => [0x0295D],
- "RightDownVector" => [0x021C2],
- "RightDownVectorBar" => [0x02955],
- "RightFloor" => [0x0230B],
- "RightTee" => [0x022A2],
- "RightTeeArrow" => [0x021A6],
- "RightTeeVector" => [0x0295B],
- "RightTriangle" => [0x022B3],
- "RightTriangleBar" => [0x029D0],
- "RightTriangleEqual" => [0x022B5],
- "RightUpDownVector" => [0x0294F],
- "RightUpTeeVector" => [0x0295C],
- "RightUpVector" => [0x021BE],
- "RightUpVectorBar" => [0x02954],
- "RightVector" => [0x021C0],
- "RightVectorBar" => [0x02953],
- "Rightarrow" => [0x021D2],
- "Ropf" => [0x0211D],
- "RoundImplies" => [0x02970],
- "Rrightarrow" => [0x021DB],
- "Rscr" => [0x0211B],
- "Rsh" => [0x021B1],
- "RuleDelayed" => [0x029F4],
- "SHCHcy" => [0x00429],
- "SHcy" => [0x00428],
- "SOFTcy" => [0x0042C],
- "Sacute" => [0x0015A],
- "Sc" => [0x02ABC],
- "Scaron" => [0x00160],
- "Scedil" => [0x0015E],
- "Scirc" => [0x0015C],
- "Scy" => [0x00421],
- "Sfr" => [0x1D516],
- "ShortDownArrow" => [0x02193],
- "ShortLeftArrow" => [0x02190],
- "ShortRightArrow" => [0x02192],
- "ShortUpArrow" => [0x02191],
- "Sigma" => [0x003A3],
- "SmallCircle" => [0x02218],
- "Sopf" => [0x1D54A],
- "Sqrt" => [0x0221A],
- "Square" => [0x025A1],
- "SquareIntersection" => [0x02293],
- "SquareSubset" => [0x0228F],
- "SquareSubsetEqual" => [0x02291],
- "SquareSuperset" => [0x02290],
- "SquareSupersetEqual" => [0x02292],
- "SquareUnion" => [0x02294],
- "Sscr" => [0x1D4AE],
- "Star" => [0x022C6],
- "Sub" => [0x022D0],
- "Subset" => [0x022D0],
- "SubsetEqual" => [0x02286],
- "Succeeds" => [0x0227B],
- "SucceedsEqual" => [0x02AB0],
- "SucceedsSlantEqual" => [0x0227D],
- "SucceedsTilde" => [0x0227F],
- "SuchThat" => [0x0220B],
- "Sum" => [0x02211],
- "Sup" => [0x022D1],
- "Superset" => [0x02283],
- "SupersetEqual" => [0x02287],
- "Supset" => [0x022D1],
- "THORN" => [0x000DE],
- "TRADE" => [0x02122],
- "TSHcy" => [0x0040B],
- "TScy" => [0x00426],
- "Tab" => [0x00009],
- "Tau" => [0x003A4],
- "Tcaron" => [0x00164],
- "Tcedil" => [0x00162],
- "Tcy" => [0x00422],
- "Tfr" => [0x1D517],
- "Therefore" => [0x02234],
- "Theta" => [0x00398],
- "ThickSpace" => [0x0205F, 0x0200A],
- "ThinSpace" => [0x02009],
- "Tilde" => [0x0223C],
- "TildeEqual" => [0x02243],
- "TildeFullEqual" => [0x02245],
- "TildeTilde" => [0x02248],
- "Topf" => [0x1D54B],
- "TripleDot" => [0x020DB],
- "Tscr" => [0x1D4AF],
- "Tstrok" => [0x00166],
- "Uacute" => [0x000DA],
- "Uarr" => [0x0219F],
- "Uarrocir" => [0x02949],
- "Ubrcy" => [0x0040E],
- "Ubreve" => [0x0016C],
- "Ucirc" => [0x000DB],
- "Ucy" => [0x00423],
- "Udblac" => [0x00170],
- "Ufr" => [0x1D518],
- "Ugrave" => [0x000D9],
- "Umacr" => [0x0016A],
- "UnderBar" => [0x0005F],
- "UnderBrace" => [0x023DF],
- "UnderBracket" => [0x023B5],
- "UnderParenthesis" => [0x023DD],
- "Union" => [0x022C3],
- "UnionPlus" => [0x0228E],
- "Uogon" => [0x00172],
- "Uopf" => [0x1D54C],
- "UpArrow" => [0x02191],
- "UpArrowBar" => [0x02912],
- "UpArrowDownArrow" => [0x021C5],
- "UpDownArrow" => [0x02195],
- "UpEquilibrium" => [0x0296E],
- "UpTee" => [0x022A5],
- "UpTeeArrow" => [0x021A5],
- "Uparrow" => [0x021D1],
- "Updownarrow" => [0x021D5],
- "UpperLeftArrow" => [0x02196],
- "UpperRightArrow" => [0x02197],
- "Upsi" => [0x003D2],
- "Upsilon" => [0x003A5],
- "Uring" => [0x0016E],
- "Uscr" => [0x1D4B0],
- "Utilde" => [0x00168],
- "Uuml" => [0x000DC],
- "VDash" => [0x022AB],
- "Vbar" => [0x02AEB],
- "Vcy" => [0x00412],
- "Vdash" => [0x022A9],
- "Vdashl" => [0x02AE6],
- "Vee" => [0x022C1],
- "Verbar" => [0x02016],
- "Vert" => [0x02016],
- "VerticalBar" => [0x02223],
- "VerticalLine" => [0x0007C],
- "VerticalSeparator" => [0x02758],
- "VerticalTilde" => [0x02240],
- "VeryThinSpace" => [0x0200A],
- "Vfr" => [0x1D519],
- "Vopf" => [0x1D54D],
- "Vscr" => [0x1D4B1],
- "Vvdash" => [0x022AA],
- "Wcirc" => [0x00174],
- "Wedge" => [0x022C0],
- "Wfr" => [0x1D51A],
- "Wopf" => [0x1D54E],
- "Wscr" => [0x1D4B2],
- "Xfr" => [0x1D51B],
- "Xi" => [0x0039E],
- "Xopf" => [0x1D54F],
- "Xscr" => [0x1D4B3],
- "YAcy" => [0x0042F],
- "YIcy" => [0x00407],
- "YUcy" => [0x0042E],
- "Yacute" => [0x000DD],
- "Ycirc" => [0x00176],
- "Ycy" => [0x0042B],
- "Yfr" => [0x1D51C],
- "Yopf" => [0x1D550],
- "Yscr" => [0x1D4B4],
- "Yuml" => [0x00178],
- "ZHcy" => [0x00416],
- "Zacute" => [0x00179],
- "Zcaron" => [0x0017D],
- "Zcy" => [0x00417],
- "Zdot" => [0x0017B],
- "ZeroWidthSpace" => [0x0200B],
- "Zeta" => [0x00396],
- "Zfr" => [0x02128],
- "Zopf" => [0x02124],
- "Zscr" => [0x1D4B5],
- "aacute" => [0x000E1],
- "abreve" => [0x00103],
- "ac" => [0x0223E],
- "acE" => [0x0223E, 0x00333],
- "acd" => [0x0223F],
- "acirc" => [0x000E2],
- "acute" => [0x000B4],
- "acy" => [0x00430],
- "aelig" => [0x000E6],
- "af" => [0x02061],
- "afr" => [0x1D51E],
- "agrave" => [0x000E0],
- "alefsym" => [0x02135],
- "aleph" => [0x02135],
- "alpha" => [0x003B1],
- "amacr" => [0x00101],
- "amalg" => [0x02A3F],
- "amp" => [0x00026],
- "and" => [0x02227],
- "andand" => [0x02A55],
- "andd" => [0x02A5C],
- "andslope" => [0x02A58],
- "andv" => [0x02A5A],
- "ang" => [0x02220],
- "ange" => [0x029A4],
- "angle" => [0x02220],
- "angmsd" => [0x02221],
- "angmsdaa" => [0x029A8],
- "angmsdab" => [0x029A9],
- "angmsdac" => [0x029AA],
- "angmsdad" => [0x029AB],
- "angmsdae" => [0x029AC],
- "angmsdaf" => [0x029AD],
- "angmsdag" => [0x029AE],
- "angmsdah" => [0x029AF],
- "angrt" => [0x0221F],
- "angrtvb" => [0x022BE],
- "angrtvbd" => [0x0299D],
- "angsph" => [0x02222],
- "angst" => [0x000C5],
- "angzarr" => [0x0237C],
- "aogon" => [0x00105],
- "aopf" => [0x1D552],
- "ap" => [0x02248],
- "apE" => [0x02A70],
- "apacir" => [0x02A6F],
- "ape" => [0x0224A],
- "apid" => [0x0224B],
- "apos" => [0x00027],
- "approx" => [0x02248],
- "approxeq" => [0x0224A],
- "aring" => [0x000E5],
- "ascr" => [0x1D4B6],
- "ast" => [0x0002A],
- "asymp" => [0x02248],
- "asympeq" => [0x0224D],
- "atilde" => [0x000E3],
- "auml" => [0x000E4],
- "awconint" => [0x02233],
- "awint" => [0x02A11],
- "bNot" => [0x02AED],
- "backcong" => [0x0224C],
- "backepsilon" => [0x003F6],
- "backprime" => [0x02035],
- "backsim" => [0x0223D],
- "backsimeq" => [0x022CD],
- "barvee" => [0x022BD],
- "barwed" => [0x02305],
- "barwedge" => [0x02305],
- "bbrk" => [0x023B5],
- "bbrktbrk" => [0x023B6],
- "bcong" => [0x0224C],
- "bcy" => [0x00431],
- "bdquo" => [0x0201E],
- "becaus" => [0x02235],
- "because" => [0x02235],
- "bemptyv" => [0x029B0],
- "bepsi" => [0x003F6],
- "bernou" => [0x0212C],
- "beta" => [0x003B2],
- "beth" => [0x02136],
- "between" => [0x0226C],
- "bfr" => [0x1D51F],
- "bigcap" => [0x022C2],
- "bigcirc" => [0x025EF],
- "bigcup" => [0x022C3],
- "bigodot" => [0x02A00],
- "bigoplus" => [0x02A01],
- "bigotimes" => [0x02A02],
- "bigsqcup" => [0x02A06],
- "bigstar" => [0x02605],
- "bigtriangledown" => [0x025BD],
- "bigtriangleup" => [0x025B3],
- "biguplus" => [0x02A04],
- "bigvee" => [0x022C1],
- "bigwedge" => [0x022C0],
- "bkarow" => [0x0290D],
- "blacklozenge" => [0x029EB],
- "blacksquare" => [0x025AA],
- "blacktriangle" => [0x025B4],
- "blacktriangledown" => [0x025BE],
- "blacktriangleleft" => [0x025C2],
- "blacktriangleright" => [0x025B8],
- "blank" => [0x02423],
- "blk12" => [0x02592],
- "blk14" => [0x02591],
- "blk34" => [0x02593],
- "block" => [0x02588],
- "bne" => [0x0003D, 0x020E5],
- "bnequiv" => [0x02261, 0x020E5],
- "bnot" => [0x02310],
- "bopf" => [0x1D553],
- "bot" => [0x022A5],
- "bottom" => [0x022A5],
- "bowtie" => [0x022C8],
- "boxDL" => [0x02557],
- "boxDR" => [0x02554],
- "boxDl" => [0x02556],
- "boxDr" => [0x02553],
- "boxH" => [0x02550],
- "boxHD" => [0x02566],
- "boxHU" => [0x02569],
- "boxHd" => [0x02564],
- "boxHu" => [0x02567],
- "boxUL" => [0x0255D],
- "boxUR" => [0x0255A],
- "boxUl" => [0x0255C],
- "boxUr" => [0x02559],
- "boxV" => [0x02551],
- "boxVH" => [0x0256C],
- "boxVL" => [0x02563],
- "boxVR" => [0x02560],
- "boxVh" => [0x0256B],
- "boxVl" => [0x02562],
- "boxVr" => [0x0255F],
- "boxbox" => [0x029C9],
- "boxdL" => [0x02555],
- "boxdR" => [0x02552],
- "boxdl" => [0x02510],
- "boxdr" => [0x0250C],
- "boxh" => [0x02500],
- "boxhD" => [0x02565],
- "boxhU" => [0x02568],
- "boxhd" => [0x0252C],
- "boxhu" => [0x02534],
- "boxminus" => [0x0229F],
- "boxplus" => [0x0229E],
- "boxtimes" => [0x022A0],
- "boxuL" => [0x0255B],
- "boxuR" => [0x02558],
- "boxul" => [0x02518],
- "boxur" => [0x02514],
- "boxv" => [0x02502],
- "boxvH" => [0x0256A],
- "boxvL" => [0x02561],
- "boxvR" => [0x0255E],
- "boxvh" => [0x0253C],
- "boxvl" => [0x02524],
- "boxvr" => [0x0251C],
- "bprime" => [0x02035],
- "breve" => [0x002D8],
- "brvbar" => [0x000A6],
- "bscr" => [0x1D4B7],
- "bsemi" => [0x0204F],
- "bsim" => [0x0223D],
- "bsime" => [0x022CD],
- "bsol" => [0x0005C],
- "bsolb" => [0x029C5],
- "bsolhsub" => [0x027C8],
- "bull" => [0x02022],
- "bullet" => [0x02022],
- "bump" => [0x0224E],
- "bumpE" => [0x02AAE],
- "bumpe" => [0x0224F],
- "bumpeq" => [0x0224F],
- "cacute" => [0x00107],
- "cap" => [0x02229],
- "capand" => [0x02A44],
- "capbrcup" => [0x02A49],
- "capcap" => [0x02A4B],
- "capcup" => [0x02A47],
- "capdot" => [0x02A40],
- "caps" => [0x02229, 0x0FE00],
- "caret" => [0x02041],
- "caron" => [0x002C7],
- "ccaps" => [0x02A4D],
- "ccaron" => [0x0010D],
- "ccedil" => [0x000E7],
- "ccirc" => [0x00109],
- "ccups" => [0x02A4C],
- "ccupssm" => [0x02A50],
- "cdot" => [0x0010B],
- "cedil" => [0x000B8],
- "cemptyv" => [0x029B2],
- "cent" => [0x000A2],
- "centerdot" => [0x000B7],
- "cfr" => [0x1D520],
- "chcy" => [0x00447],
- "check" => [0x02713],
- "checkmark" => [0x02713],
- "chi" => [0x003C7],
- "cir" => [0x025CB],
- "cirE" => [0x029C3],
- "circ" => [0x002C6],
- "circeq" => [0x02257],
- "circlearrowleft" => [0x021BA],
- "circlearrowright" => [0x021BB],
- "circledR" => [0x000AE],
- "circledS" => [0x024C8],
- "circledast" => [0x0229B],
- "circledcirc" => [0x0229A],
- "circleddash" => [0x0229D],
- "cire" => [0x02257],
- "cirfnint" => [0x02A10],
- "cirmid" => [0x02AEF],
- "cirscir" => [0x029C2],
- "clubs" => [0x02663],
- "clubsuit" => [0x02663],
- "colon" => [0x0003A],
- "colone" => [0x02254],
- "coloneq" => [0x02254],
- "comma" => [0x0002C],
- "commat" => [0x00040],
- "comp" => [0x02201],
- "compfn" => [0x02218],
- "complement" => [0x02201],
- "complexes" => [0x02102],
- "cong" => [0x02245],
- "congdot" => [0x02A6D],
- "conint" => [0x0222E],
- "copf" => [0x1D554],
- "coprod" => [0x02210],
- "copy" => [0x000A9],
- "copysr" => [0x02117],
- "crarr" => [0x021B5],
- "cross" => [0x02717],
- "cscr" => [0x1D4B8],
- "csub" => [0x02ACF],
- "csube" => [0x02AD1],
- "csup" => [0x02AD0],
- "csupe" => [0x02AD2],
- "ctdot" => [0x022EF],
- "cudarrl" => [0x02938],
- "cudarrr" => [0x02935],
- "cuepr" => [0x022DE],
- "cuesc" => [0x022DF],
- "cularr" => [0x021B6],
- "cularrp" => [0x0293D],
- "cup" => [0x0222A],
- "cupbrcap" => [0x02A48],
- "cupcap" => [0x02A46],
- "cupcup" => [0x02A4A],
- "cupdot" => [0x0228D],
- "cupor" => [0x02A45],
- "cups" => [0x0222A, 0x0FE00],
- "curarr" => [0x021B7],
- "curarrm" => [0x0293C],
- "curlyeqprec" => [0x022DE],
- "curlyeqsucc" => [0x022DF],
- "curlyvee" => [0x022CE],
- "curlywedge" => [0x022CF],
- "curren" => [0x000A4],
- "curvearrowleft" => [0x021B6],
- "curvearrowright" => [0x021B7],
- "cuvee" => [0x022CE],
- "cuwed" => [0x022CF],
- "cwconint" => [0x02232],
- "cwint" => [0x02231],
- "cylcty" => [0x0232D],
- "dArr" => [0x021D3],
- "dHar" => [0x02965],
- "dagger" => [0x02020],
- "daleth" => [0x02138],
- "darr" => [0x02193],
- "dash" => [0x02010],
- "dashv" => [0x022A3],
- "dbkarow" => [0x0290F],
- "dblac" => [0x002DD],
- "dcaron" => [0x0010F],
- "dcy" => [0x00434],
- "dd" => [0x02146],
- "ddagger" => [0x02021],
- "ddarr" => [0x021CA],
- "ddotseq" => [0x02A77],
- "deg" => [0x000B0],
- "delta" => [0x003B4],
- "demptyv" => [0x029B1],
- "dfisht" => [0x0297F],
- "dfr" => [0x1D521],
- "dharl" => [0x021C3],
- "dharr" => [0x021C2],
- "diam" => [0x022C4],
- "diamond" => [0x022C4],
- "diamondsuit" => [0x02666],
- "diams" => [0x02666],
- "die" => [0x000A8],
- "digamma" => [0x003DD],
- "disin" => [0x022F2],
- "div" => [0x000F7],
- "divide" => [0x000F7],
- "divideontimes" => [0x022C7],
- "divonx" => [0x022C7],
- "djcy" => [0x00452],
- "dlcorn" => [0x0231E],
- "dlcrop" => [0x0230D],
- "dollar" => [0x00024],
- "dopf" => [0x1D555],
- "dot" => [0x002D9],
- "doteq" => [0x02250],
- "doteqdot" => [0x02251],
- "dotminus" => [0x02238],
- "dotplus" => [0x02214],
- "dotsquare" => [0x022A1],
- "doublebarwedge" => [0x02306],
- "downarrow" => [0x02193],
- "downdownarrows" => [0x021CA],
- "downharpoonleft" => [0x021C3],
- "downharpoonright" => [0x021C2],
- "drbkarow" => [0x02910],
- "drcorn" => [0x0231F],
- "drcrop" => [0x0230C],
- "dscr" => [0x1D4B9],
- "dscy" => [0x00455],
- "dsol" => [0x029F6],
- "dstrok" => [0x00111],
- "dtdot" => [0x022F1],
- "dtri" => [0x025BF],
- "dtrif" => [0x025BE],
- "duarr" => [0x021F5],
- "duhar" => [0x0296F],
- "dwangle" => [0x029A6],
- "dzcy" => [0x0045F],
- "dzigrarr" => [0x027FF],
- "eDDot" => [0x02A77],
- "eDot" => [0x02251],
- "eacute" => [0x000E9],
- "easter" => [0x02A6E],
- "ecaron" => [0x0011B],
- "ecir" => [0x02256],
- "ecirc" => [0x000EA],
- "ecolon" => [0x02255],
- "ecy" => [0x0044D],
- "edot" => [0x00117],
- "ee" => [0x02147],
- "efDot" => [0x02252],
- "efr" => [0x1D522],
- "eg" => [0x02A9A],
- "egrave" => [0x000E8],
- "egs" => [0x02A96],
- "egsdot" => [0x02A98],
- "el" => [0x02A99],
- "elinters" => [0x023E7],
- "ell" => [0x02113],
- "els" => [0x02A95],
- "elsdot" => [0x02A97],
- "emacr" => [0x00113],
- "empty" => [0x02205],
- "emptyset" => [0x02205],
- "emptyv" => [0x02205],
- "emsp" => [0x02003],
- "emsp13" => [0x02004],
- "emsp14" => [0x02005],
- "eng" => [0x0014B],
- "ensp" => [0x02002],
- "eogon" => [0x00119],
- "eopf" => [0x1D556],
- "epar" => [0x022D5],
- "eparsl" => [0x029E3],
- "eplus" => [0x02A71],
- "epsi" => [0x003B5],
- "epsilon" => [0x003B5],
- "epsiv" => [0x003F5],
- "eqcirc" => [0x02256],
- "eqcolon" => [0x02255],
- "eqsim" => [0x02242],
- "eqslantgtr" => [0x02A96],
- "eqslantless" => [0x02A95],
- "equals" => [0x0003D],
- "equest" => [0x0225F],
- "equiv" => [0x02261],
- "equivDD" => [0x02A78],
- "eqvparsl" => [0x029E5],
- "erDot" => [0x02253],
- "erarr" => [0x02971],
- "escr" => [0x0212F],
- "esdot" => [0x02250],
- "esim" => [0x02242],
- "eta" => [0x003B7],
- "eth" => [0x000F0],
- "euml" => [0x000EB],
- "euro" => [0x020AC],
- "excl" => [0x00021],
- "exist" => [0x02203],
- "expectation" => [0x02130],
- "exponentiale" => [0x02147],
- "fallingdotseq" => [0x02252],
- "fcy" => [0x00444],
- "female" => [0x02640],
- "ffilig" => [0x0FB03],
- "fflig" => [0x0FB00],
- "ffllig" => [0x0FB04],
- "ffr" => [0x1D523],
- "filig" => [0x0FB01],
- "fjlig" => [0x00066, 0x0006A],
- "flat" => [0x0266D],
- "fllig" => [0x0FB02],
- "fltns" => [0x025B1],
- "fnof" => [0x00192],
- "fopf" => [0x1D557],
- "forall" => [0x02200],
- "fork" => [0x022D4],
- "forkv" => [0x02AD9],
- "fpartint" => [0x02A0D],
- "frac12" => [0x000BD],
- "frac13" => [0x02153],
- "frac14" => [0x000BC],
- "frac15" => [0x02155],
- "frac16" => [0x02159],
- "frac18" => [0x0215B],
- "frac23" => [0x02154],
- "frac25" => [0x02156],
- "frac34" => [0x000BE],
- "frac35" => [0x02157],
- "frac38" => [0x0215C],
- "frac45" => [0x02158],
- "frac56" => [0x0215A],
- "frac58" => [0x0215D],
- "frac78" => [0x0215E],
- "frasl" => [0x02044],
- "frown" => [0x02322],
- "fscr" => [0x1D4BB],
- "gE" => [0x02267],
- "gEl" => [0x02A8C],
- "gacute" => [0x001F5],
- "gamma" => [0x003B3],
- "gammad" => [0x003DD],
- "gap" => [0x02A86],
- "gbreve" => [0x0011F],
- "gcirc" => [0x0011D],
- "gcy" => [0x00433],
- "gdot" => [0x00121],
- "ge" => [0x02265],
- "gel" => [0x022DB],
- "geq" => [0x02265],
- "geqq" => [0x02267],
- "geqslant" => [0x02A7E],
- "ges" => [0x02A7E],
- "gescc" => [0x02AA9],
- "gesdot" => [0x02A80],
- "gesdoto" => [0x02A82],
- "gesdotol" => [0x02A84],
- "gesl" => [0x022DB, 0x0FE00],
- "gesles" => [0x02A94],
- "gfr" => [0x1D524],
- "gg" => [0x0226B],
- "ggg" => [0x022D9],
- "gimel" => [0x02137],
- "gjcy" => [0x00453],
- "gl" => [0x02277],
- "glE" => [0x02A92],
- "gla" => [0x02AA5],
- "glj" => [0x02AA4],
- "gnE" => [0x02269],
- "gnap" => [0x02A8A],
- "gnapprox" => [0x02A8A],
- "gne" => [0x02A88],
- "gneq" => [0x02A88],
- "gneqq" => [0x02269],
- "gnsim" => [0x022E7],
- "gopf" => [0x1D558],
- "grave" => [0x00060],
- "gscr" => [0x0210A],
- "gsim" => [0x02273],
- "gsime" => [0x02A8E],
- "gsiml" => [0x02A90],
- "gt" => [0x0003E],
- "gtcc" => [0x02AA7],
- "gtcir" => [0x02A7A],
- "gtdot" => [0x022D7],
- "gtlPar" => [0x02995],
- "gtquest" => [0x02A7C],
- "gtrapprox" => [0x02A86],
- "gtrarr" => [0x02978],
- "gtrdot" => [0x022D7],
- "gtreqless" => [0x022DB],
- "gtreqqless" => [0x02A8C],
- "gtrless" => [0x02277],
- "gtrsim" => [0x02273],
- "gvertneqq" => [0x02269, 0x0FE00],
- "gvnE" => [0x02269, 0x0FE00],
- "hArr" => [0x021D4],
- "hairsp" => [0x0200A],
- "half" => [0x000BD],
- "hamilt" => [0x0210B],
- "hardcy" => [0x0044A],
- "harr" => [0x02194],
- "harrcir" => [0x02948],
- "harrw" => [0x021AD],
- "hbar" => [0x0210F],
- "hcirc" => [0x00125],
- "hearts" => [0x02665],
- "heartsuit" => [0x02665],
- "hellip" => [0x02026],
- "hercon" => [0x022B9],
- "hfr" => [0x1D525],
- "hksearow" => [0x02925],
- "hkswarow" => [0x02926],
- "hoarr" => [0x021FF],
- "homtht" => [0x0223B],
- "hookleftarrow" => [0x021A9],
- "hookrightarrow" => [0x021AA],
- "hopf" => [0x1D559],
- "horbar" => [0x02015],
- "hscr" => [0x1D4BD],
- "hslash" => [0x0210F],
- "hstrok" => [0x00127],
- "hybull" => [0x02043],
- "hyphen" => [0x02010],
- "iacute" => [0x000ED],
- "ic" => [0x02063],
- "icirc" => [0x000EE],
- "icy" => [0x00438],
- "iecy" => [0x00435],
- "iexcl" => [0x000A1],
- "iff" => [0x021D4],
- "ifr" => [0x1D526],
- "igrave" => [0x000EC],
- "ii" => [0x02148],
- "iiiint" => [0x02A0C],
- "iiint" => [0x0222D],
- "iinfin" => [0x029DC],
- "iiota" => [0x02129],
- "ijlig" => [0x00133],
- "imacr" => [0x0012B],
- "image" => [0x02111],
- "imagline" => [0x02110],
- "imagpart" => [0x02111],
- "imath" => [0x00131],
- "imof" => [0x022B7],
- "imped" => [0x001B5],
- "in" => [0x02208],
- "incare" => [0x02105],
- "infin" => [0x0221E],
- "infintie" => [0x029DD],
- "inodot" => [0x00131],
- "int" => [0x0222B],
- "intcal" => [0x022BA],
- "integers" => [0x02124],
- "intercal" => [0x022BA],
- "intlarhk" => [0x02A17],
- "intprod" => [0x02A3C],
- "iocy" => [0x00451],
- "iogon" => [0x0012F],
- "iopf" => [0x1D55A],
- "iota" => [0x003B9],
- "iprod" => [0x02A3C],
- "iquest" => [0x000BF],
- "iscr" => [0x1D4BE],
- "isin" => [0x02208],
- "isinE" => [0x022F9],
- "isindot" => [0x022F5],
- "isins" => [0x022F4],
- "isinsv" => [0x022F3],
- "isinv" => [0x02208],
- "it" => [0x02062],
- "itilde" => [0x00129],
- "iukcy" => [0x00456],
- "iuml" => [0x000EF],
- "jcirc" => [0x00135],
- "jcy" => [0x00439],
- "jfr" => [0x1D527],
- "jmath" => [0x00237],
- "jopf" => [0x1D55B],
- "jscr" => [0x1D4BF],
- "jsercy" => [0x00458],
- "jukcy" => [0x00454],
- "kappa" => [0x003BA],
- "kappav" => [0x003F0],
- "kcedil" => [0x00137],
- "kcy" => [0x0043A],
- "kfr" => [0x1D528],
- "kgreen" => [0x00138],
- "khcy" => [0x00445],
- "kjcy" => [0x0045C],
- "kopf" => [0x1D55C],
- "kscr" => [0x1D4C0],
- "lAarr" => [0x021DA],
- "lArr" => [0x021D0],
- "lAtail" => [0x0291B],
- "lBarr" => [0x0290E],
- "lE" => [0x02266],
- "lEg" => [0x02A8B],
- "lHar" => [0x02962],
- "lacute" => [0x0013A],
- "laemptyv" => [0x029B4],
- "lagran" => [0x02112],
- "lambda" => [0x003BB],
- "lang" => [0x027E8],
- "langd" => [0x02991],
- "langle" => [0x027E8],
- "lap" => [0x02A85],
- "laquo" => [0x000AB],
- "larr" => [0x02190],
- "larrb" => [0x021E4],
- "larrbfs" => [0x0291F],
- "larrfs" => [0x0291D],
- "larrhk" => [0x021A9],
- "larrlp" => [0x021AB],
- "larrpl" => [0x02939],
- "larrsim" => [0x02973],
- "larrtl" => [0x021A2],
- "lat" => [0x02AAB],
- "latail" => [0x02919],
- "late" => [0x02AAD],
- "lates" => [0x02AAD, 0x0FE00],
- "lbarr" => [0x0290C],
- "lbbrk" => [0x02772],
- "lbrace" => [0x0007B],
- "lbrack" => [0x0005B],
- "lbrke" => [0x0298B],
- "lbrksld" => [0x0298F],
- "lbrkslu" => [0x0298D],
- "lcaron" => [0x0013E],
- "lcedil" => [0x0013C],
- "lceil" => [0x02308],
- "lcub" => [0x0007B],
- "lcy" => [0x0043B],
- "ldca" => [0x02936],
- "ldquo" => [0x0201C],
- "ldquor" => [0x0201E],
- "ldrdhar" => [0x02967],
- "ldrushar" => [0x0294B],
- "ldsh" => [0x021B2],
- "le" => [0x02264],
- "leftarrow" => [0x02190],
- "leftarrowtail" => [0x021A2],
- "leftharpoondown" => [0x021BD],
- "leftharpoonup" => [0x021BC],
- "leftleftarrows" => [0x021C7],
- "leftrightarrow" => [0x02194],
- "leftrightarrows" => [0x021C6],
- "leftrightharpoons" => [0x021CB],
- "leftrightsquigarrow" => [0x021AD],
- "leftthreetimes" => [0x022CB],
- "leg" => [0x022DA],
- "leq" => [0x02264],
- "leqq" => [0x02266],
- "leqslant" => [0x02A7D],
- "les" => [0x02A7D],
- "lescc" => [0x02AA8],
- "lesdot" => [0x02A7F],
- "lesdoto" => [0x02A81],
- "lesdotor" => [0x02A83],
- "lesg" => [0x022DA, 0x0FE00],
- "lesges" => [0x02A93],
- "lessapprox" => [0x02A85],
- "lessdot" => [0x022D6],
- "lesseqgtr" => [0x022DA],
- "lesseqqgtr" => [0x02A8B],
- "lessgtr" => [0x02276],
- "lesssim" => [0x02272],
- "lfisht" => [0x0297C],
- "lfloor" => [0x0230A],
- "lfr" => [0x1D529],
- "lg" => [0x02276],
- "lgE" => [0x02A91],
- "lhard" => [0x021BD],
- "lharu" => [0x021BC],
- "lharul" => [0x0296A],
- "lhblk" => [0x02584],
- "ljcy" => [0x00459],
- "ll" => [0x0226A],
- "llarr" => [0x021C7],
- "llcorner" => [0x0231E],
- "llhard" => [0x0296B],
- "lltri" => [0x025FA],
- "lmidot" => [0x00140],
- "lmoust" => [0x023B0],
- "lmoustache" => [0x023B0],
- "lnE" => [0x02268],
- "lnap" => [0x02A89],
- "lnapprox" => [0x02A89],
- "lne" => [0x02A87],
- "lneq" => [0x02A87],
- "lneqq" => [0x02268],
- "lnsim" => [0x022E6],
- "loang" => [0x027EC],
- "loarr" => [0x021FD],
- "lobrk" => [0x027E6],
- "longleftarrow" => [0x027F5],
- "longleftrightarrow" => [0x027F7],
- "longmapsto" => [0x027FC],
- "longrightarrow" => [0x027F6],
- "looparrowleft" => [0x021AB],
- "looparrowright" => [0x021AC],
- "lopar" => [0x02985],
- "lopf" => [0x1D55D],
- "loplus" => [0x02A2D],
- "lotimes" => [0x02A34],
- "lowast" => [0x02217],
- "lowbar" => [0x0005F],
- "loz" => [0x025CA],
- "lozenge" => [0x025CA],
- "lozf" => [0x029EB],
- "lpar" => [0x00028],
- "lparlt" => [0x02993],
- "lrarr" => [0x021C6],
- "lrcorner" => [0x0231F],
- "lrhar" => [0x021CB],
- "lrhard" => [0x0296D],
- "lrm" => [0x0200E],
- "lrtri" => [0x022BF],
- "lsaquo" => [0x02039],
- "lscr" => [0x1D4C1],
- "lsh" => [0x021B0],
- "lsim" => [0x02272],
- "lsime" => [0x02A8D],
- "lsimg" => [0x02A8F],
- "lsqb" => [0x0005B],
- "lsquo" => [0x02018],
- "lsquor" => [0x0201A],
- "lstrok" => [0x00142],
- "lt" => [0x0003C],
- "ltcc" => [0x02AA6],
- "ltcir" => [0x02A79],
- "ltdot" => [0x022D6],
- "lthree" => [0x022CB],
- "ltimes" => [0x022C9],
- "ltlarr" => [0x02976],
- "ltquest" => [0x02A7B],
- "ltrPar" => [0x02996],
- "ltri" => [0x025C3],
- "ltrie" => [0x022B4],
- "ltrif" => [0x025C2],
- "lurdshar" => [0x0294A],
- "luruhar" => [0x02966],
- "lvertneqq" => [0x02268, 0x0FE00],
- "lvnE" => [0x02268, 0x0FE00],
- "mDDot" => [0x0223A],
- "macr" => [0x000AF],
- "male" => [0x02642],
- "malt" => [0x02720],
- "maltese" => [0x02720],
- "map" => [0x021A6],
- "mapsto" => [0x021A6],
- "mapstodown" => [0x021A7],
- "mapstoleft" => [0x021A4],
- "mapstoup" => [0x021A5],
- "marker" => [0x025AE],
- "mcomma" => [0x02A29],
- "mcy" => [0x0043C],
- "mdash" => [0x02014],
- "measuredangle" => [0x02221],
- "mfr" => [0x1D52A],
- "mho" => [0x02127],
- "micro" => [0x000B5],
- "mid" => [0x02223],
- "midast" => [0x0002A],
- "midcir" => [0x02AF0],
- "middot" => [0x000B7],
- "minus" => [0x02212],
- "minusb" => [0x0229F],
- "minusd" => [0x02238],
- "minusdu" => [0x02A2A],
- "mlcp" => [0x02ADB],
- "mldr" => [0x02026],
- "mnplus" => [0x02213],
- "models" => [0x022A7],
- "mopf" => [0x1D55E],
- "mp" => [0x02213],
- "mscr" => [0x1D4C2],
- "mstpos" => [0x0223E],
- "mu" => [0x003BC],
- "multimap" => [0x022B8],
- "mumap" => [0x022B8],
- "nGg" => [0x022D9, 0x00338],
- "nGt" => [0x0226B, 0x020D2],
- "nGtv" => [0x0226B, 0x00338],
- "nLeftarrow" => [0x021CD],
- "nLeftrightarrow" => [0x021CE],
- "nLl" => [0x022D8, 0x00338],
- "nLt" => [0x0226A, 0x020D2],
- "nLtv" => [0x0226A, 0x00338],
- "nRightarrow" => [0x021CF],
- "nVDash" => [0x022AF],
- "nVdash" => [0x022AE],
- "nabla" => [0x02207],
- "nacute" => [0x00144],
- "nang" => [0x02220, 0x020D2],
- "nap" => [0x02249],
- "napE" => [0x02A70, 0x00338],
- "napid" => [0x0224B, 0x00338],
- "napos" => [0x00149],
- "napprox" => [0x02249],
- "natur" => [0x0266E],
- "natural" => [0x0266E],
- "naturals" => [0x02115],
- "nbsp" => [0x000A0],
- "nbump" => [0x0224E, 0x00338],
- "nbumpe" => [0x0224F, 0x00338],
- "ncap" => [0x02A43],
- "ncaron" => [0x00148],
- "ncedil" => [0x00146],
- "ncong" => [0x02247],
- "ncongdot" => [0x02A6D, 0x00338],
- "ncup" => [0x02A42],
- "ncy" => [0x0043D],
- "ndash" => [0x02013],
- "ne" => [0x02260],
- "neArr" => [0x021D7],
- "nearhk" => [0x02924],
- "nearr" => [0x02197],
- "nearrow" => [0x02197],
- "nedot" => [0x02250, 0x00338],
- "nequiv" => [0x02262],
- "nesear" => [0x02928],
- "nesim" => [0x02242, 0x00338],
- "nexist" => [0x02204],
- "nexists" => [0x02204],
- "nfr" => [0x1D52B],
- "ngE" => [0x02267, 0x00338],
- "nge" => [0x02271],
- "ngeq" => [0x02271],
- "ngeqq" => [0x02267, 0x00338],
- "ngeqslant" => [0x02A7E, 0x00338],
- "nges" => [0x02A7E, 0x00338],
- "ngsim" => [0x02275],
- "ngt" => [0x0226F],
- "ngtr" => [0x0226F],
- "nhArr" => [0x021CE],
- "nharr" => [0x021AE],
- "nhpar" => [0x02AF2],
- "ni" => [0x0220B],
- "nis" => [0x022FC],
- "nisd" => [0x022FA],
- "niv" => [0x0220B],
- "njcy" => [0x0045A],
- "nlArr" => [0x021CD],
- "nlE" => [0x02266, 0x00338],
- "nlarr" => [0x0219A],
- "nldr" => [0x02025],
- "nle" => [0x02270],
- "nleftarrow" => [0x0219A],
- "nleftrightarrow" => [0x021AE],
- "nleq" => [0x02270],
- "nleqq" => [0x02266, 0x00338],
- "nleqslant" => [0x02A7D, 0x00338],
- "nles" => [0x02A7D, 0x00338],
- "nless" => [0x0226E],
- "nlsim" => [0x02274],
- "nlt" => [0x0226E],
- "nltri" => [0x022EA],
- "nltrie" => [0x022EC],
- "nmid" => [0x02224],
- "nopf" => [0x1D55F],
- "not" => [0x000AC],
- "notin" => [0x02209],
- "notinE" => [0x022F9, 0x00338],
- "notindot" => [0x022F5, 0x00338],
- "notinva" => [0x02209],
- "notinvb" => [0x022F7],
- "notinvc" => [0x022F6],
- "notni" => [0x0220C],
- "notniva" => [0x0220C],
- "notnivb" => [0x022FE],
- "notnivc" => [0x022FD],
- "npar" => [0x02226],
- "nparallel" => [0x02226],
- "nparsl" => [0x02AFD, 0x020E5],
- "npart" => [0x02202, 0x00338],
- "npolint" => [0x02A14],
- "npr" => [0x02280],
- "nprcue" => [0x022E0],
- "npre" => [0x02AAF, 0x00338],
- "nprec" => [0x02280],
- "npreceq" => [0x02AAF, 0x00338],
- "nrArr" => [0x021CF],
- "nrarr" => [0x0219B],
- "nrarrc" => [0x02933, 0x00338],
- "nrarrw" => [0x0219D, 0x00338],
- "nrightarrow" => [0x0219B],
- "nrtri" => [0x022EB],
- "nrtrie" => [0x022ED],
- "nsc" => [0x02281],
- "nsccue" => [0x022E1],
- "nsce" => [0x02AB0, 0x00338],
- "nscr" => [0x1D4C3],
- "nshortmid" => [0x02224],
- "nshortparallel" => [0x02226],
- "nsim" => [0x02241],
- "nsime" => [0x02244],
- "nsimeq" => [0x02244],
- "nsmid" => [0x02224],
- "nspar" => [0x02226],
- "nsqsube" => [0x022E2],
- "nsqsupe" => [0x022E3],
- "nsub" => [0x02284],
- "nsubE" => [0x02AC5, 0x00338],
- "nsube" => [0x02288],
- "nsubset" => [0x02282, 0x020D2],
- "nsubseteq" => [0x02288],
- "nsubseteqq" => [0x02AC5, 0x00338],
- "nsucc" => [0x02281],
- "nsucceq" => [0x02AB0, 0x00338],
- "nsup" => [0x02285],
- "nsupE" => [0x02AC6, 0x00338],
- "nsupe" => [0x02289],
- "nsupset" => [0x02283, 0x020D2],
- "nsupseteq" => [0x02289],
- "nsupseteqq" => [0x02AC6, 0x00338],
- "ntgl" => [0x02279],
- "ntilde" => [0x000F1],
- "ntlg" => [0x02278],
- "ntriangleleft" => [0x022EA],
- "ntrianglelefteq" => [0x022EC],
- "ntriangleright" => [0x022EB],
- "ntrianglerighteq" => [0x022ED],
- "nu" => [0x003BD],
- "num" => [0x00023],
- "numero" => [0x02116],
- "numsp" => [0x02007],
- "nvDash" => [0x022AD],
- "nvHarr" => [0x02904],
- "nvap" => [0x0224D, 0x020D2],
- "nvdash" => [0x022AC],
- "nvge" => [0x02265, 0x020D2],
- "nvgt" => [0x0003E, 0x020D2],
- "nvinfin" => [0x029DE],
- "nvlArr" => [0x02902],
- "nvle" => [0x02264, 0x020D2],
- "nvlt" => [0x0003C, 0x020D2],
- "nvltrie" => [0x022B4, 0x020D2],
- "nvrArr" => [0x02903],
- "nvrtrie" => [0x022B5, 0x020D2],
- "nvsim" => [0x0223C, 0x020D2],
- "nwArr" => [0x021D6],
- "nwarhk" => [0x02923],
- "nwarr" => [0x02196],
- "nwarrow" => [0x02196],
- "nwnear" => [0x02927],
- "oS" => [0x024C8],
- "oacute" => [0x000F3],
- "oast" => [0x0229B],
- "ocir" => [0x0229A],
- "ocirc" => [0x000F4],
- "ocy" => [0x0043E],
- "odash" => [0x0229D],
- "odblac" => [0x00151],
- "odiv" => [0x02A38],
- "odot" => [0x02299],
- "odsold" => [0x029BC],
- "oelig" => [0x00153],
- "ofcir" => [0x029BF],
- "ofr" => [0x1D52C],
- "ogon" => [0x002DB],
- "ograve" => [0x000F2],
- "ogt" => [0x029C1],
- "ohbar" => [0x029B5],
- "ohm" => [0x003A9],
- "oint" => [0x0222E],
- "olarr" => [0x021BA],
- "olcir" => [0x029BE],
- "olcross" => [0x029BB],
- "oline" => [0x0203E],
- "olt" => [0x029C0],
- "omacr" => [0x0014D],
- "omega" => [0x003C9],
- "omicron" => [0x003BF],
- "omid" => [0x029B6],
- "ominus" => [0x02296],
- "oopf" => [0x1D560],
- "opar" => [0x029B7],
- "operp" => [0x029B9],
- "oplus" => [0x02295],
- "or" => [0x02228],
- "orarr" => [0x021BB],
- "ord" => [0x02A5D],
- "order" => [0x02134],
- "orderof" => [0x02134],
- "ordf" => [0x000AA],
- "ordm" => [0x000BA],
- "origof" => [0x022B6],
- "oror" => [0x02A56],
- "orslope" => [0x02A57],
- "orv" => [0x02A5B],
- "oscr" => [0x02134],
- "oslash" => [0x000F8],
- "osol" => [0x02298],
- "otilde" => [0x000F5],
- "otimes" => [0x02297],
- "otimesas" => [0x02A36],
- "ouml" => [0x000F6],
- "ovbar" => [0x0233D],
- "par" => [0x02225],
- "para" => [0x000B6],
- "parallel" => [0x02225],
- "parsim" => [0x02AF3],
- "parsl" => [0x02AFD],
- "part" => [0x02202],
- "pcy" => [0x0043F],
- "percnt" => [0x00025],
- "period" => [0x0002E],
- "permil" => [0x02030],
- "perp" => [0x022A5],
- "pertenk" => [0x02031],
- "pfr" => [0x1D52D],
- "phi" => [0x003C6],
- "phiv" => [0x003D5],
- "phmmat" => [0x02133],
- "phone" => [0x0260E],
- "pi" => [0x003C0],
- "pitchfork" => [0x022D4],
- "piv" => [0x003D6],
- "planck" => [0x0210F],
- "planckh" => [0x0210E],
- "plankv" => [0x0210F],
- "plus" => [0x0002B],
- "plusacir" => [0x02A23],
- "plusb" => [0x0229E],
- "pluscir" => [0x02A22],
- "plusdo" => [0x02214],
- "plusdu" => [0x02A25],
- "pluse" => [0x02A72],
- "plusmn" => [0x000B1],
- "plussim" => [0x02A26],
- "plustwo" => [0x02A27],
- "pm" => [0x000B1],
- "pointint" => [0x02A15],
- "popf" => [0x1D561],
- "pound" => [0x000A3],
- "pr" => [0x0227A],
- "prE" => [0x02AB3],
- "prap" => [0x02AB7],
- "prcue" => [0x0227C],
- "pre" => [0x02AAF],
- "prec" => [0x0227A],
- "precapprox" => [0x02AB7],
- "preccurlyeq" => [0x0227C],
- "preceq" => [0x02AAF],
- "precnapprox" => [0x02AB9],
- "precneqq" => [0x02AB5],
- "precnsim" => [0x022E8],
- "precsim" => [0x0227E],
- "prime" => [0x02032],
- "primes" => [0x02119],
- "prnE" => [0x02AB5],
- "prnap" => [0x02AB9],
- "prnsim" => [0x022E8],
- "prod" => [0x0220F],
- "profalar" => [0x0232E],
- "profline" => [0x02312],
- "profsurf" => [0x02313],
- "prop" => [0x0221D],
- "propto" => [0x0221D],
- "prsim" => [0x0227E],
- "prurel" => [0x022B0],
- "pscr" => [0x1D4C5],
- "psi" => [0x003C8],
- "puncsp" => [0x02008],
- "qfr" => [0x1D52E],
- "qint" => [0x02A0C],
- "qopf" => [0x1D562],
- "qprime" => [0x02057],
- "qscr" => [0x1D4C6],
- "quaternions" => [0x0210D],
- "quatint" => [0x02A16],
- "quest" => [0x0003F],
- "questeq" => [0x0225F],
- "quot" => [0x00022],
- "rAarr" => [0x021DB],
- "rArr" => [0x021D2],
- "rAtail" => [0x0291C],
- "rBarr" => [0x0290F],
- "rHar" => [0x02964],
- "race" => [0x0223D, 0x00331],
- "racute" => [0x00155],
- "radic" => [0x0221A],
- "raemptyv" => [0x029B3],
- "rang" => [0x027E9],
- "rangd" => [0x02992],
- "range" => [0x029A5],
- "rangle" => [0x027E9],
- "raquo" => [0x000BB],
- "rarr" => [0x02192],
- "rarrap" => [0x02975],
- "rarrb" => [0x021E5],
- "rarrbfs" => [0x02920],
- "rarrc" => [0x02933],
- "rarrfs" => [0x0291E],
- "rarrhk" => [0x021AA],
- "rarrlp" => [0x021AC],
- "rarrpl" => [0x02945],
- "rarrsim" => [0x02974],
- "rarrtl" => [0x021A3],
- "rarrw" => [0x0219D],
- "ratail" => [0x0291A],
- "ratio" => [0x02236],
- "rationals" => [0x0211A],
- "rbarr" => [0x0290D],
- "rbbrk" => [0x02773],
- "rbrace" => [0x0007D],
- "rbrack" => [0x0005D],
- "rbrke" => [0x0298C],
- "rbrksld" => [0x0298E],
- "rbrkslu" => [0x02990],
- "rcaron" => [0x00159],
- "rcedil" => [0x00157],
- "rceil" => [0x02309],
- "rcub" => [0x0007D],
- "rcy" => [0x00440],
- "rdca" => [0x02937],
- "rdldhar" => [0x02969],
- "rdquo" => [0x0201D],
- "rdquor" => [0x0201D],
- "rdsh" => [0x021B3],
- "real" => [0x0211C],
- "realine" => [0x0211B],
- "realpart" => [0x0211C],
- "reals" => [0x0211D],
- "rect" => [0x025AD],
- "reg" => [0x000AE],
- "rfisht" => [0x0297D],
- "rfloor" => [0x0230B],
- "rfr" => [0x1D52F],
- "rhard" => [0x021C1],
- "rharu" => [0x021C0],
- "rharul" => [0x0296C],
- "rho" => [0x003C1],
- "rhov" => [0x003F1],
- "rightarrow" => [0x02192],
- "rightarrowtail" => [0x021A3],
- "rightharpoondown" => [0x021C1],
- "rightharpoonup" => [0x021C0],
- "rightleftarrows" => [0x021C4],
- "rightleftharpoons" => [0x021CC],
- "rightrightarrows" => [0x021C9],
- "rightsquigarrow" => [0x0219D],
- "rightthreetimes" => [0x022CC],
- "ring" => [0x002DA],
- "risingdotseq" => [0x02253],
- "rlarr" => [0x021C4],
- "rlhar" => [0x021CC],
- "rlm" => [0x0200F],
- "rmoust" => [0x023B1],
- "rmoustache" => [0x023B1],
- "rnmid" => [0x02AEE],
- "roang" => [0x027ED],
- "roarr" => [0x021FE],
- "robrk" => [0x027E7],
- "ropar" => [0x02986],
- "ropf" => [0x1D563],
- "roplus" => [0x02A2E],
- "rotimes" => [0x02A35],
- "rpar" => [0x00029],
- "rpargt" => [0x02994],
- "rppolint" => [0x02A12],
- "rrarr" => [0x021C9],
- "rsaquo" => [0x0203A],
- "rscr" => [0x1D4C7],
- "rsh" => [0x021B1],
- "rsqb" => [0x0005D],
- "rsquo" => [0x02019],
- "rsquor" => [0x02019],
- "rthree" => [0x022CC],
- "rtimes" => [0x022CA],
- "rtri" => [0x025B9],
- "rtrie" => [0x022B5],
- "rtrif" => [0x025B8],
- "rtriltri" => [0x029CE],
- "ruluhar" => [0x02968],
- "rx" => [0x0211E],
- "sacute" => [0x0015B],
- "sbquo" => [0x0201A],
- "sc" => [0x0227B],
- "scE" => [0x02AB4],
- "scap" => [0x02AB8],
- "scaron" => [0x00161],
- "sccue" => [0x0227D],
- "sce" => [0x02AB0],
- "scedil" => [0x0015F],
- "scirc" => [0x0015D],
- "scnE" => [0x02AB6],
- "scnap" => [0x02ABA],
- "scnsim" => [0x022E9],
- "scpolint" => [0x02A13],
- "scsim" => [0x0227F],
- "scy" => [0x00441],
- "sdot" => [0x022C5],
- "sdotb" => [0x022A1],
- "sdote" => [0x02A66],
- "seArr" => [0x021D8],
- "searhk" => [0x02925],
- "searr" => [0x02198],
- "searrow" => [0x02198],
- "sect" => [0x000A7],
- "semi" => [0x0003B],
- "seswar" => [0x02929],
- "setminus" => [0x02216],
- "setmn" => [0x02216],
- "sext" => [0x02736],
- "sfr" => [0x1D530],
- "sfrown" => [0x02322],
- "sharp" => [0x0266F],
- "shchcy" => [0x00449],
- "shcy" => [0x00448],
- "shortmid" => [0x02223],
- "shortparallel" => [0x02225],
- "shy" => [0x000AD],
- "sigma" => [0x003C3],
- "sigmaf" => [0x003C2],
- "sigmav" => [0x003C2],
- "sim" => [0x0223C],
- "simdot" => [0x02A6A],
- "sime" => [0x02243],
- "simeq" => [0x02243],
- "simg" => [0x02A9E],
- "simgE" => [0x02AA0],
- "siml" => [0x02A9D],
- "simlE" => [0x02A9F],
- "simne" => [0x02246],
- "simplus" => [0x02A24],
- "simrarr" => [0x02972],
- "slarr" => [0x02190],
- "smallsetminus" => [0x02216],
- "smashp" => [0x02A33],
- "smeparsl" => [0x029E4],
- "smid" => [0x02223],
- "smile" => [0x02323],
- "smt" => [0x02AAA],
- "smte" => [0x02AAC],
- "smtes" => [0x02AAC, 0x0FE00],
- "softcy" => [0x0044C],
- "sol" => [0x0002F],
- "solb" => [0x029C4],
- "solbar" => [0x0233F],
- "sopf" => [0x1D564],
- "spades" => [0x02660],
- "spadesuit" => [0x02660],
- "spar" => [0x02225],
- "sqcap" => [0x02293],
- "sqcaps" => [0x02293, 0x0FE00],
- "sqcup" => [0x02294],
- "sqcups" => [0x02294, 0x0FE00],
- "sqsub" => [0x0228F],
- "sqsube" => [0x02291],
- "sqsubset" => [0x0228F],
- "sqsubseteq" => [0x02291],
- "sqsup" => [0x02290],
- "sqsupe" => [0x02292],
- "sqsupset" => [0x02290],
- "sqsupseteq" => [0x02292],
- "squ" => [0x025A1],
- "square" => [0x025A1],
- "squarf" => [0x025AA],
- "squf" => [0x025AA],
- "srarr" => [0x02192],
- "sscr" => [0x1D4C8],
- "ssetmn" => [0x02216],
- "ssmile" => [0x02323],
- "sstarf" => [0x022C6],
- "star" => [0x02606],
- "starf" => [0x02605],
- "straightepsilon" => [0x003F5],
- "straightphi" => [0x003D5],
- "strns" => [0x000AF],
- "sub" => [0x02282],
- "subE" => [0x02AC5],
- "subdot" => [0x02ABD],
- "sube" => [0x02286],
- "subedot" => [0x02AC3],
- "submult" => [0x02AC1],
- "subnE" => [0x02ACB],
- "subne" => [0x0228A],
- "subplus" => [0x02ABF],
- "subrarr" => [0x02979],
- "subset" => [0x02282],
- "subseteq" => [0x02286],
- "subseteqq" => [0x02AC5],
- "subsetneq" => [0x0228A],
- "subsetneqq" => [0x02ACB],
- "subsim" => [0x02AC7],
- "subsub" => [0x02AD5],
- "subsup" => [0x02AD3],
- "succ" => [0x0227B],
- "succapprox" => [0x02AB8],
- "succcurlyeq" => [0x0227D],
- "succeq" => [0x02AB0],
- "succnapprox" => [0x02ABA],
- "succneqq" => [0x02AB6],
- "succnsim" => [0x022E9],
- "succsim" => [0x0227F],
- "sum" => [0x02211],
- "sung" => [0x0266A],
- "sup" => [0x02283],
- "sup1" => [0x000B9],
- "sup2" => [0x000B2],
- "sup3" => [0x000B3],
- "supE" => [0x02AC6],
- "supdot" => [0x02ABE],
- "supdsub" => [0x02AD8],
- "supe" => [0x02287],
- "supedot" => [0x02AC4],
- "suphsol" => [0x027C9],
- "suphsub" => [0x02AD7],
- "suplarr" => [0x0297B],
- "supmult" => [0x02AC2],
- "supnE" => [0x02ACC],
- "supne" => [0x0228B],
- "supplus" => [0x02AC0],
- "supset" => [0x02283],
- "supseteq" => [0x02287],
- "supseteqq" => [0x02AC6],
- "supsetneq" => [0x0228B],
- "supsetneqq" => [0x02ACC],
- "supsim" => [0x02AC8],
- "supsub" => [0x02AD4],
- "supsup" => [0x02AD6],
- "swArr" => [0x021D9],
- "swarhk" => [0x02926],
- "swarr" => [0x02199],
- "swarrow" => [0x02199],
- "swnwar" => [0x0292A],
- "szlig" => [0x000DF],
- "target" => [0x02316],
- "tau" => [0x003C4],
- "tbrk" => [0x023B4],
- "tcaron" => [0x00165],
- "tcedil" => [0x00163],
- "tcy" => [0x00442],
- "tdot" => [0x020DB],
- "telrec" => [0x02315],
- "tfr" => [0x1D531],
- "there4" => [0x02234],
- "therefore" => [0x02234],
- "theta" => [0x003B8],
- "thetasym" => [0x003D1],
- "thetav" => [0x003D1],
- "thickapprox" => [0x02248],
- "thicksim" => [0x0223C],
- "thinsp" => [0x02009],
- "thkap" => [0x02248],
- "thksim" => [0x0223C],
- "thorn" => [0x000FE],
- "tilde" => [0x002DC],
- "times" => [0x000D7],
- "timesb" => [0x022A0],
- "timesbar" => [0x02A31],
- "timesd" => [0x02A30],
- "tint" => [0x0222D],
- "toea" => [0x02928],
- "top" => [0x022A4],
- "topbot" => [0x02336],
- "topcir" => [0x02AF1],
- "topf" => [0x1D565],
- "topfork" => [0x02ADA],
- "tosa" => [0x02929],
- "tprime" => [0x02034],
- "trade" => [0x02122],
- "triangle" => [0x025B5],
- "triangledown" => [0x025BF],
- "triangleleft" => [0x025C3],
- "trianglelefteq" => [0x022B4],
- "triangleq" => [0x0225C],
- "triangleright" => [0x025B9],
- "trianglerighteq" => [0x022B5],
- "tridot" => [0x025EC],
- "trie" => [0x0225C],
- "triminus" => [0x02A3A],
- "triplus" => [0x02A39],
- "trisb" => [0x029CD],
- "tritime" => [0x02A3B],
- "trpezium" => [0x023E2],
- "tscr" => [0x1D4C9],
- "tscy" => [0x00446],
- "tshcy" => [0x0045B],
- "tstrok" => [0x00167],
- "twixt" => [0x0226C],
- "twoheadleftarrow" => [0x0219E],
- "twoheadrightarrow" => [0x021A0],
- "uArr" => [0x021D1],
- "uHar" => [0x02963],
- "uacute" => [0x000FA],
- "uarr" => [0x02191],
- "ubrcy" => [0x0045E],
- "ubreve" => [0x0016D],
- "ucirc" => [0x000FB],
- "ucy" => [0x00443],
- "udarr" => [0x021C5],
- "udblac" => [0x00171],
- "udhar" => [0x0296E],
- "ufisht" => [0x0297E],
- "ufr" => [0x1D532],
- "ugrave" => [0x000F9],
- "uharl" => [0x021BF],
- "uharr" => [0x021BE],
- "uhblk" => [0x02580],
- "ulcorn" => [0x0231C],
- "ulcorner" => [0x0231C],
- "ulcrop" => [0x0230F],
- "ultri" => [0x025F8],
- "umacr" => [0x0016B],
- "uml" => [0x000A8],
- "uogon" => [0x00173],
- "uopf" => [0x1D566],
- "uparrow" => [0x02191],
- "updownarrow" => [0x02195],
- "upharpoonleft" => [0x021BF],
- "upharpoonright" => [0x021BE],
- "uplus" => [0x0228E],
- "upsi" => [0x003C5],
- "upsih" => [0x003D2],
- "upsilon" => [0x003C5],
- "upuparrows" => [0x021C8],
- "urcorn" => [0x0231D],
- "urcorner" => [0x0231D],
- "urcrop" => [0x0230E],
- "uring" => [0x0016F],
- "urtri" => [0x025F9],
- "uscr" => [0x1D4CA],
- "utdot" => [0x022F0],
- "utilde" => [0x00169],
- "utri" => [0x025B5],
- "utrif" => [0x025B4],
- "uuarr" => [0x021C8],
- "uuml" => [0x000FC],
- "uwangle" => [0x029A7],
- "vArr" => [0x021D5],
- "vBar" => [0x02AE8],
- "vBarv" => [0x02AE9],
- "vDash" => [0x022A8],
- "vangrt" => [0x0299C],
- "varepsilon" => [0x003F5],
- "varkappa" => [0x003F0],
- "varnothing" => [0x02205],
- "varphi" => [0x003D5],
- "varpi" => [0x003D6],
- "varpropto" => [0x0221D],
- "varr" => [0x02195],
- "varrho" => [0x003F1],
- "varsigma" => [0x003C2],
- "varsubsetneq" => [0x0228A, 0x0FE00],
- "varsubsetneqq" => [0x02ACB, 0x0FE00],
- "varsupsetneq" => [0x0228B, 0x0FE00],
- "varsupsetneqq" => [0x02ACC, 0x0FE00],
- "vartheta" => [0x003D1],
- "vartriangleleft" => [0x022B2],
- "vartriangleright" => [0x022B3],
- "vcy" => [0x00432],
- "vdash" => [0x022A2],
- "vee" => [0x02228],
- "veebar" => [0x022BB],
- "veeeq" => [0x0225A],
- "vellip" => [0x022EE],
- "verbar" => [0x0007C],
- "vert" => [0x0007C],
- "vfr" => [0x1D533],
- "vltri" => [0x022B2],
- "vnsub" => [0x02282, 0x020D2],
- "vnsup" => [0x02283, 0x020D2],
- "vopf" => [0x1D567],
- "vprop" => [0x0221D],
- "vrtri" => [0x022B3],
- "vscr" => [0x1D4CB],
- "vsubnE" => [0x02ACB, 0x0FE00],
- "vsubne" => [0x0228A, 0x0FE00],
- "vsupnE" => [0x02ACC, 0x0FE00],
- "vsupne" => [0x0228B, 0x0FE00],
- "vzigzag" => [0x0299A],
- "wcirc" => [0x00175],
- "wedbar" => [0x02A5F],
- "wedge" => [0x02227],
- "wedgeq" => [0x02259],
- "weierp" => [0x02118],
- "wfr" => [0x1D534],
- "wopf" => [0x1D568],
- "wp" => [0x02118],
- "wr" => [0x02240],
- "wreath" => [0x02240],
- "wscr" => [0x1D4CC],
- "xcap" => [0x022C2],
- "xcirc" => [0x025EF],
- "xcup" => [0x022C3],
- "xdtri" => [0x025BD],
- "xfr" => [0x1D535],
- "xhArr" => [0x027FA],
- "xharr" => [0x027F7],
- "xi" => [0x003BE],
- "xlArr" => [0x027F8],
- "xlarr" => [0x027F5],
- "xmap" => [0x027FC],
- "xnis" => [0x022FB],
- "xodot" => [0x02A00],
- "xopf" => [0x1D569],
- "xoplus" => [0x02A01],
- "xotime" => [0x02A02],
- "xrArr" => [0x027F9],
- "xrarr" => [0x027F6],
- "xscr" => [0x1D4CD],
- "xsqcup" => [0x02A06],
- "xuplus" => [0x02A04],
- "xutri" => [0x025B3],
- "xvee" => [0x022C1],
- "xwedge" => [0x022C0],
- "yacute" => [0x000FD],
- "yacy" => [0x0044F],
- "ycirc" => [0x00177],
- "ycy" => [0x0044B],
- "yen" => [0x000A5],
- "yfr" => [0x1D536],
- "yicy" => [0x00457],
- "yopf" => [0x1D56A],
- "yscr" => [0x1D4CE],
- "yucy" => [0x0044E],
- "yuml" => [0x000FF],
- "zacute" => [0x0017A],
- "zcaron" => [0x0017E],
- "zcy" => [0x00437],
- "zdot" => [0x0017C],
- "zeetrf" => [0x02128],
- "zeta" => [0x003B6],
- "zfr" => [0x1D537],
- "zhcy" => [0x00436],
- "zigrarr" => [0x021DD],
- "zopf" => [0x1D56B],
- "zscr" => [0x1D4CF],
- "zwj" => [0x0200D],
- "zwnj" => [0x0200C],
-}
diff --git a/lib/rdoc/markdown/literals.rb b/lib/rdoc/markdown/literals.rb
deleted file mode 100644
index c5c15d3100..0000000000
--- a/lib/rdoc/markdown/literals.rb
+++ /dev/null
@@ -1,454 +0,0 @@
-# coding: UTF-8
-# frozen_string_literal: true
-# :markup: markdown
-
-##
-# This set of literals is for Ruby 1.9 regular expressions and gives full
-# unicode support.
-#
-# Unlike peg-markdown, this set of literals recognizes Unicode alphanumeric
-# characters, newlines and spaces.
-class RDoc::Markdown::Literals
- # :stopdoc:
-
- # This is distinct from setup_parser so that a standalone parser
- # can redefine #initialize and still have access to the proper
- # parser setup code.
- def initialize(str, debug=false)
- setup_parser(str, debug)
- end
-
-
-
- # Prepares for parsing +str+. If you define a custom initialize you must
- # call this method before #parse
- def setup_parser(str, debug=false)
- set_string str, 0
- @memoizations = Hash.new { |h,k| h[k] = {} }
- @result = nil
- @failed_rule = nil
- @failing_rule_offset = -1
- @line_offsets = nil
-
- setup_foreign_grammar
- end
-
- attr_reader :string
- attr_reader :failing_rule_offset
- attr_accessor :result, :pos
-
- def current_column(target=pos)
- if string[target] == "\n" && (c = string.rindex("\n", target-1) || -1)
- return target - c
- elsif c = string.rindex("\n", target)
- return target - c
- end
-
- target + 1
- end
-
- def position_line_offsets
- unless @position_line_offsets
- @position_line_offsets = []
- total = 0
- string.each_line do |line|
- total += line.size
- @position_line_offsets << total
- end
- end
- @position_line_offsets
- end
-
- if [].respond_to? :bsearch_index
- def current_line(target=pos)
- if line = position_line_offsets.bsearch_index {|x| x > target }
- return line + 1
- end
- raise "Target position #{target} is outside of string"
- end
- else
- def current_line(target=pos)
- if line = position_line_offsets.index {|x| x > target }
- return line + 1
- end
-
- raise "Target position #{target} is outside of string"
- end
- end
-
- def current_character(target=pos)
- if target < 0 || target >= string.size
- raise "Target position #{target} is outside of string"
- end
- string[target, 1]
- end
-
- KpegPosInfo = Struct.new(:pos, :lno, :col, :line, :char)
-
- def current_pos_info(target=pos)
- l = current_line target
- c = current_column target
- ln = get_line(l-1)
- chr = string[target,1]
- KpegPosInfo.new(target, l, c, ln, chr)
- end
-
- def lines
- string.lines
- end
-
- def get_line(no)
- loff = position_line_offsets
- if no < 0
- raise "Line No is out of range: #{no} < 0"
- elsif no >= loff.size
- raise "Line No is out of range: #{no} >= #{loff.size}"
- end
- lend = loff[no]-1
- lstart = no > 0 ? loff[no-1] : 0
- string[lstart..lend]
- end
-
-
-
- def get_text(start)
- @string[start..@pos-1]
- end
-
- # Sets the string and current parsing position for the parser.
- def set_string string, pos
- @string = string
- @string_size = string ? string.size : 0
- @pos = pos
- @position_line_offsets = nil
- end
-
- def show_pos
- width = 10
- if @pos < width
- "#{@pos} (\"#{@string[0,@pos]}\" @ \"#{@string[@pos,width]}\")"
- else
- "#{@pos} (\"... #{@string[@pos - width, width]}\" @ \"#{@string[@pos,width]}\")"
- end
- end
-
- def failure_info
- l = current_line @failing_rule_offset
- c = current_column @failing_rule_offset
-
- if @failed_rule.kind_of? Symbol
- info = self.class::Rules[@failed_rule]
- "line #{l}, column #{c}: failed rule '#{info.name}' = '#{info.rendered}'"
- else
- "line #{l}, column #{c}: failed rule '#{@failed_rule}'"
- end
- end
-
- def failure_caret
- p = current_pos_info @failing_rule_offset
- "#{p.line.chomp}\n#{' ' * (p.col - 1)}^"
- end
-
- def failure_character
- current_character @failing_rule_offset
- end
-
- def failure_oneline
- p = current_pos_info @failing_rule_offset
-
- if @failed_rule.kind_of? Symbol
- info = self.class::Rules[@failed_rule]
- "@#{p.lno}:#{p.col} failed rule '#{info.name}', got '#{p.char}'"
- else
- "@#{p.lno}:#{p.col} failed rule '#{@failed_rule}', got '#{p.char}'"
- end
- end
-
- class ParseError < RuntimeError
- end
-
- def raise_error
- raise ParseError, failure_oneline
- end
-
- def show_error(io=STDOUT)
- error_pos = @failing_rule_offset
- p = current_pos_info(error_pos)
-
- io.puts "On line #{p.lno}, column #{p.col}:"
-
- if @failed_rule.kind_of? Symbol
- info = self.class::Rules[@failed_rule]
- io.puts "Failed to match '#{info.rendered}' (rule '#{info.name}')"
- else
- io.puts "Failed to match rule '#{@failed_rule}'"
- end
-
- io.puts "Got: #{p.char.inspect}"
- io.puts "=> #{p.line}"
- io.print(" " * (p.col + 2))
- io.puts "^"
- end
-
- def set_failed_rule(name)
- if @pos > @failing_rule_offset
- @failed_rule = name
- @failing_rule_offset = @pos
- end
- end
-
- attr_reader :failed_rule
-
- def match_string(str)
- len = str.size
- if @string[pos,len] == str
- @pos += len
- return str
- end
-
- return nil
- end
-
- def scan(reg)
- if m = reg.match(@string, @pos)
- @pos = m.end(0)
- return true
- end
-
- return nil
- end
-
- if "".respond_to? :ord
- def get_byte
- if @pos >= @string_size
- return nil
- end
-
- s = @string[@pos].ord
- @pos += 1
- s
- end
- else
- def get_byte
- if @pos >= @string_size
- return nil
- end
-
- s = @string[@pos]
- @pos += 1
- s
- end
- end
-
- def parse(rule=nil)
- # We invoke the rules indirectly via apply
- # instead of by just calling them as methods because
- # if the rules use left recursion, apply needs to
- # manage that.
-
- if !rule
- apply(:_root)
- else
- method = rule.gsub("-","_hyphen_")
- apply :"_#{method}"
- end
- end
-
- class MemoEntry
- def initialize(ans, pos)
- @ans = ans
- @pos = pos
- @result = nil
- @set = false
- @left_rec = false
- end
-
- attr_reader :ans, :pos, :result, :set
- attr_accessor :left_rec
-
- def move!(ans, pos, result)
- @ans = ans
- @pos = pos
- @result = result
- @set = true
- @left_rec = false
- end
- end
-
- def external_invoke(other, rule, *args)
- old_pos = @pos
- old_string = @string
-
- set_string other.string, other.pos
-
- begin
- if val = __send__(rule, *args)
- other.pos = @pos
- other.result = @result
- else
- other.set_failed_rule "#{self.class}##{rule}"
- end
- val
- ensure
- set_string old_string, old_pos
- end
- end
-
- def apply_with_args(rule, *args)
- @result = nil
- memo_key = [rule, args]
- if m = @memoizations[memo_key][@pos]
- @pos = m.pos
- if !m.set
- m.left_rec = true
- return nil
- end
-
- @result = m.result
-
- return m.ans
- else
- m = MemoEntry.new(nil, @pos)
- @memoizations[memo_key][@pos] = m
- start_pos = @pos
-
- ans = __send__ rule, *args
-
- lr = m.left_rec
-
- m.move! ans, @pos, @result
-
- # Don't bother trying to grow the left recursion
- # if it's failing straight away (thus there is no seed)
- if ans and lr
- return grow_lr(rule, args, start_pos, m)
- else
- return ans
- end
- end
- end
-
- def apply(rule)
- @result = nil
- if m = @memoizations[rule][@pos]
- @pos = m.pos
- if !m.set
- m.left_rec = true
- return nil
- end
-
- @result = m.result
-
- return m.ans
- else
- m = MemoEntry.new(nil, @pos)
- @memoizations[rule][@pos] = m
- start_pos = @pos
-
- ans = __send__ rule
-
- lr = m.left_rec
-
- m.move! ans, @pos, @result
-
- # Don't bother trying to grow the left recursion
- # if it's failing straight away (thus there is no seed)
- if ans and lr
- return grow_lr(rule, nil, start_pos, m)
- else
- return ans
- end
- end
- end
-
- def grow_lr(rule, args, start_pos, m)
- while true
- @pos = start_pos
- @result = m.result
-
- if args
- ans = __send__ rule, *args
- else
- ans = __send__ rule
- end
- return nil unless ans
-
- break if @pos <= m.pos
-
- m.move! ans, @pos, @result
- end
-
- @result = m.result
- @pos = m.pos
- return m.ans
- end
-
- class RuleInfo
- def initialize(name, rendered)
- @name = name
- @rendered = rendered
- end
-
- attr_reader :name, :rendered
- end
-
- def self.rule_info(name, rendered)
- RuleInfo.new(name, rendered)
- end
-
-
- # :startdoc:
- # :stopdoc:
- def setup_foreign_grammar; end
-
- # Alphanumeric = /\p{Word}/
- def _Alphanumeric
- _tmp = scan(/\G(?-mix:\p{Word})/)
- set_failed_rule :_Alphanumeric unless _tmp
- return _tmp
- end
-
- # AlphanumericAscii = /[A-Za-z0-9]/
- def _AlphanumericAscii
- _tmp = scan(/\G(?-mix:[A-Za-z0-9])/)
- set_failed_rule :_AlphanumericAscii unless _tmp
- return _tmp
- end
-
- # BOM = "uFEFF"
- def _BOM
- _tmp = match_string("uFEFF")
- set_failed_rule :_BOM unless _tmp
- return _tmp
- end
-
- # Newline = /\n|\r\n?|\p{Zl}|\p{Zp}/
- def _Newline
- _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(/\G(?-mix:\p{^Word})/)
- set_failed_rule :_NonAlphanumeric unless _tmp
- return _tmp
- end
-
- # Spacechar = /\t|\p{Zs}/
- def _Spacechar
- _tmp = scan(/\G(?-mix:\t|\p{Zs})/)
- set_failed_rule :_Spacechar unless _tmp
- return _tmp
- end
-
- Rules = {}
- Rules[:_Alphanumeric] = rule_info("Alphanumeric", "/\\p{Word}/")
- Rules[:_AlphanumericAscii] = rule_info("AlphanumericAscii", "/[A-Za-z0-9]/")
- Rules[:_BOM] = rule_info("BOM", "\"uFEFF\"")
- Rules[:_Newline] = rule_info("Newline", "/\\n|\\r\\n?|\\p{Zl}|\\p{Zp}/")
- Rules[:_NonAlphanumeric] = rule_info("NonAlphanumeric", "/\\p{^Word}/")
- Rules[:_Spacechar] = rule_info("Spacechar", "/\\t|\\p{Zs}/")
- # :startdoc:
-end
diff --git a/lib/rdoc/markup.rb b/lib/rdoc/markup.rb
deleted file mode 100644
index 6e93030965..0000000000
--- a/lib/rdoc/markup.rb
+++ /dev/null
@@ -1,235 +0,0 @@
-# frozen_string_literal: true
-##
-# RDoc::Markup parses plain text documents and attempts to decompose them into
-# their constituent parts. Some of these parts are high-level: paragraphs,
-# chunks of verbatim text, list entries and the like. Other parts happen at
-# the character level: a piece of bold text, a word in code font. This markup
-# is similar in spirit to that used on WikiWiki webs, where folks create web
-# pages using a simple set of formatting rules.
-#
-# RDoc::Markup and other markup formats do no output formatting, this is
-# handled by the RDoc::Markup::Formatter subclasses.
-#
-# = Supported Formats
-#
-# Besides the RDoc::Markup format, the following formats are built in to RDoc:
-#
-# markdown::
-# The markdown format as described by
-# http://daringfireball.net/projects/markdown/. See RDoc::Markdown for
-# details on the parser and supported extensions.
-# rd::
-# The rdtool format. See RDoc::RD for details on the parser and format.
-# tomdoc::
-# The TomDoc format as described by http://tomdoc.org/. See RDoc::TomDoc
-# for details on the parser and supported extensions.
-#
-# You can choose a markup format using the following methods:
-#
-# per project::
-# If you build your documentation with rake use RDoc::Task#markup.
-#
-# If you build your documentation by hand run:
-#
-# rdoc --markup your_favorite_format --write-options
-#
-# and commit <tt>.rdoc_options</tt> and ship it with your packaged gem.
-# per file::
-# At the top of the file use the <tt>:markup:</tt> directive to set the
-# default format for the rest of the file.
-# per comment::
-# Use the <tt>:markup:</tt> directive at the top of a comment you want
-# to write in a different format.
-#
-# = RDoc::Markup
-#
-# RDoc::Markup is extensible at runtime: you can add \new markup elements to
-# be recognized in the documents that RDoc::Markup parses.
-#
-# RDoc::Markup is intended to be the basis for a family of tools which share
-# the common requirement that simple, plain-text should be rendered in a
-# variety of different output formats and media. It is envisaged that
-# RDoc::Markup could be the basis for formatting RDoc style comment blocks,
-# Wiki entries, and online FAQs.
-#
-# == Synopsis
-#
-# This code converts +input_string+ to HTML. The conversion takes place in
-# the +convert+ method, so you can use the same RDoc::Markup converter to
-# convert multiple input strings.
-#
-# require 'rdoc'
-#
-# h = RDoc::Markup::ToHtml.new(RDoc::Options.new)
-#
-# puts h.convert(input_string)
-#
-# You can extend the RDoc::Markup parser to recognize new markup
-# sequences, and to add regexp handling. Here we make WikiWords significant to
-# the parser, and also make the sequences {word} and \<no>text...</no> signify
-# strike-through text. We then subclass the HTML output class to deal
-# with these:
-#
-# require 'rdoc'
-#
-# class WikiHtml < RDoc::Markup::ToHtml
-# def handle_regexp_WIKIWORD(target)
-# "<font color=red>" + target.text + "</font>"
-# end
-# end
-#
-# markup = RDoc::Markup.new
-# markup.add_word_pair("{", "}", :STRIKE)
-# markup.add_html("no", :STRIKE)
-#
-# markup.add_regexp_handling(/\b([A-Z][a-z]+[A-Z]\w+)/, :WIKIWORD)
-#
-# wh = WikiHtml.new RDoc::Options.new, markup
-# wh.add_tag(:STRIKE, "<strike>", "</strike>")
-#
-# puts "<body>#{wh.convert ARGF.read}</body>"
-#
-# == Encoding
-#
-# Where Encoding support is available, RDoc will automatically convert all
-# documents to the same output encoding. The output encoding can be set via
-# RDoc::Options#encoding and defaults to Encoding.default_external.
-#
-# = \RDoc Markup Reference
-#
-# See RDoc::MarkupReference.
-#
-#--
-# Original Author:: Dave Thomas, dave@pragmaticprogrammer.com
-# License:: Ruby license
-
-class RDoc::Markup
-
- ##
- # An AttributeManager which handles inline markup.
-
- attr_reader :attribute_manager
-
- ##
- # Parses +str+ into an RDoc::Markup::Document.
-
- def self.parse str
- RDoc::Markup::Parser.parse str
- rescue RDoc::Markup::Parser::Error => e
- $stderr.puts <<-EOF
-While parsing markup, RDoc encountered a #{e.class}:
-
-#{e}
-\tfrom #{e.backtrace.join "\n\tfrom "}
-
----8<---
-#{text}
----8<---
-
-RDoc #{RDoc::VERSION}
-
-Ruby #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} #{RUBY_RELEASE_DATE}
-
-Please file a bug report with the above information at:
-
-https://github.com/ruby/rdoc/issues
-
- EOF
- raise
- end
-
- ##
- # Take a block of text and use various heuristics to determine its
- # structure (paragraphs, lists, and so on). Invoke an event handler as we
- # identify significant chunks.
-
- def initialize attribute_manager = nil
- @attribute_manager = attribute_manager || RDoc::Markup::AttributeManager.new
- @output = nil
- end
-
- ##
- # Add to the sequences used to add formatting to an individual word (such
- # as *bold*). Matching entries will generate attributes that the output
- # formatters can recognize by their +name+.
-
- def add_word_pair(start, stop, name)
- @attribute_manager.add_word_pair(start, stop, name)
- end
-
- ##
- # Add to the sequences recognized as general markup.
-
- def add_html(tag, name)
- @attribute_manager.add_html(tag, name)
- end
-
- ##
- # Add to other inline sequences. For example, we could add WikiWords using
- # something like:
- #
- # parser.add_regexp_handling(/\b([A-Z][a-z]+[A-Z]\w+)/, :WIKIWORD)
- #
- # Each wiki word will be presented to the output formatter.
-
- def add_regexp_handling(pattern, name)
- @attribute_manager.add_regexp_handling(pattern, name)
- end
-
- ##
- # We take +input+, parse it if necessary, then invoke the output +formatter+
- # using a Visitor to render the result.
-
- def convert input, formatter
- document = case input
- when RDoc::Markup::Document then
- input
- else
- RDoc::Markup::Parser.parse input
- end
-
- document.accept formatter
- end
-
- autoload :Parser, "#{__dir__}/markup/parser"
- autoload :PreProcess, "#{__dir__}/markup/pre_process"
-
- # Inline markup classes
- autoload :AttrChanger, "#{__dir__}/markup/attr_changer"
- autoload :AttrSpan, "#{__dir__}/markup/attr_span"
- autoload :Attributes, "#{__dir__}/markup/attributes"
- autoload :AttributeManager, "#{__dir__}/markup/attribute_manager"
- autoload :RegexpHandling, "#{__dir__}/markup/regexp_handling"
-
- # RDoc::Markup AST
- autoload :BlankLine, "#{__dir__}/markup/blank_line"
- autoload :BlockQuote, "#{__dir__}/markup/block_quote"
- autoload :Document, "#{__dir__}/markup/document"
- autoload :HardBreak, "#{__dir__}/markup/hard_break"
- autoload :Heading, "#{__dir__}/markup/heading"
- autoload :Include, "#{__dir__}/markup/include"
- autoload :IndentedParagraph, "#{__dir__}/markup/indented_paragraph"
- autoload :List, "#{__dir__}/markup/list"
- autoload :ListItem, "#{__dir__}/markup/list_item"
- autoload :Paragraph, "#{__dir__}/markup/paragraph"
- autoload :Table, "#{__dir__}/markup/table"
- autoload :Raw, "#{__dir__}/markup/raw"
- autoload :Rule, "#{__dir__}/markup/rule"
- autoload :Verbatim, "#{__dir__}/markup/verbatim"
-
- # Formatters
- autoload :Formatter, "#{__dir__}/markup/formatter"
-
- autoload :ToAnsi, "#{__dir__}/markup/to_ansi"
- autoload :ToBs, "#{__dir__}/markup/to_bs"
- autoload :ToHtml, "#{__dir__}/markup/to_html"
- autoload :ToHtmlCrossref, "#{__dir__}/markup/to_html_crossref"
- autoload :ToHtmlSnippet, "#{__dir__}/markup/to_html_snippet"
- autoload :ToLabel, "#{__dir__}/markup/to_label"
- autoload :ToMarkdown, "#{__dir__}/markup/to_markdown"
- autoload :ToRdoc, "#{__dir__}/markup/to_rdoc"
- autoload :ToTableOfContents, "#{__dir__}/markup/to_table_of_contents"
- autoload :ToTest, "#{__dir__}/markup/to_test"
- autoload :ToTtOnly, "#{__dir__}/markup/to_tt_only"
-
-end
diff --git a/lib/rdoc/markup/attr_changer.rb b/lib/rdoc/markup/attr_changer.rb
deleted file mode 100644
index e5ba470bb6..0000000000
--- a/lib/rdoc/markup/attr_changer.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-class RDoc::Markup
-
- AttrChanger = Struct.new :turn_on, :turn_off # :nodoc:
-
-end
-
-##
-# An AttrChanger records a change in attributes. It contains a bitmap of the
-# attributes to turn on, and a bitmap of those to turn off.
-
-class RDoc::Markup::AttrChanger
-
- def to_s # :nodoc:
- "Attr: +#{turn_on}/-#{turn_off}"
- end
-
- def inspect # :nodoc:
- '+%d/-%d' % [turn_on, turn_off]
- end
-
-end
diff --git a/lib/rdoc/markup/attr_span.rb b/lib/rdoc/markup/attr_span.rb
deleted file mode 100644
index f1fabf1c3b..0000000000
--- a/lib/rdoc/markup/attr_span.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-##
-# An array of attributes which parallels the characters in a string.
-
-class RDoc::Markup::AttrSpan
-
- ##
- # Creates a new AttrSpan for +length+ characters
-
- 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)
- if (@exclusive & @attrs[i]) == 0 || (@exclusive & bits) != 0
- @attrs[i] |= bits
- updated = true
- end
- end
- updated
- end
-
- ##
- # Accesses flags for character +n+
-
- def [](n)
- @attrs[n]
- end
-
-end
diff --git a/lib/rdoc/markup/attribute_manager.rb b/lib/rdoc/markup/attribute_manager.rb
deleted file mode 100644
index f6eb06da95..0000000000
--- a/lib/rdoc/markup/attribute_manager.rb
+++ /dev/null
@@ -1,405 +0,0 @@
-# frozen_string_literal: true
-
-##
-# Manages changes of attributes in a block of text
-
-class RDoc::Markup::AttributeManager
- unless ::MatchData.method_defined?(:match_length)
- using ::Module.new {
- refine(::MatchData) {
- def match_length(nth) # :nodoc:
- b, e = offset(nth)
- e - b if b
- end
- }
- }
- end
-
- ##
- # The NUL character
-
- NULL = "\000".freeze
-
- #--
- # We work by substituting non-printing characters in to the text. For now
- # I'm assuming that I can substitute a character in the range 0..8 for a 7
- # bit character without damaging the encoded string, but this might be
- # optimistic
- #++
-
- A_PROTECT = 004 # :nodoc:
-
- ##
- # Special mask character to prevent inline markup handling
-
- PROTECT_ATTR = A_PROTECT.chr # :nodoc:
-
- ##
- # The attributes enabled for this markup object.
-
- attr_reader :attributes
-
- ##
- # This maps delimiters that occur around words (such as *bold* or +tt+)
- # where the start and end delimiters and the same. This lets us optimize
- # the regexp
-
- attr_reader :matching_word_pairs
-
- ##
- # And this is used when the delimiters aren't the same. In this case the
- # hash maps a pattern to the attribute character
-
- attr_reader :word_pair_map
-
- ##
- # This maps HTML tags to the corresponding attribute char
-
- attr_reader :html_tags
-
- ##
- # A \ in front of a character that would normally be processed turns off
- # processing. We do this by turning \< into <#{PROTECT}
-
- attr_reader :protectable
-
- ##
- # And this maps _regexp handling_ sequences to a name. A regexp handling
- # sequence is something like a WikiWord
-
- 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.
-
- def initialize
- @html_tags = {}
- @matching_word_pairs = {}
- @protectable = %w[<]
- @regexp_handlings = []
- @word_pair_map = {}
- @exclusive_bitmap = 0
- @attributes = RDoc::Markup::Attributes.new
-
- add_word_pair "*", "*", :BOLD, true
- add_word_pair "_", "_", :EM, true
- add_word_pair "+", "+", :TT, true
-
- 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
-
- ##
- # Return an attribute object with the given turn_on and turn_off bits set
-
- def attribute(turn_on, turn_off)
- RDoc::Markup::AttrChanger.new turn_on, turn_off
- end
-
- ##
- # Changes the current attribute from +current+ to +new+
-
- def change_attribute current, new
- diff = current ^ new
- attribute(new & diff, current & diff)
- end
-
- ##
- # Used by the tests to change attributes by name from +current_set+ to
- # +new_set+
-
- def changed_attribute_by_name current_set, new_set
- current = new = 0
- current_set.each do |name|
- current |= @attributes.bitmap_for(name)
- end
-
- new_set.each do |name|
- new |= @attributes.bitmap_for(name)
- end
-
- change_attribute(current, new)
- end
-
- ##
- # Copies +start_pos+ to +end_pos+ from the current string
-
- def copy_string(start_pos, end_pos)
- res = @str[start_pos...end_pos]
- res.gsub!(/\000/, '')
- res
- end
-
- # :nodoc:
- def exclusive?(attr)
- (attr & @exclusive_bitmap) != 0
- end
-
- NON_PRINTING_START = "\1" # :nodoc:
- NON_PRINTING_END = "\2" # :nodoc:
-
- ##
- # Map attributes like <b>text</b>to the sequence
- # \001\002<char>\001\003<char>, where <char> is a per-attribute specific
- # character
-
- def convert_attrs(str, attrs, exclusive = false)
- convert_attrs_matching_word_pairs(str, attrs, exclusive)
- convert_attrs_word_pair_map(str, attrs, exclusive)
- end
-
- # :nodoc:
- def convert_attrs_matching_word_pairs(str, attrs, exclusive)
- # first do matching ones
- tags = @matching_word_pairs.select { |start, bitmap|
- exclusive == exclusive?(bitmap)
- }.keys
- return if tags.empty?
- tags = "[#{tags.join("")}](?!#{PROTECT_ATTR})"
- all_tags = "[#{@matching_word_pairs.keys.join("")}](?!#{PROTECT_ATTR})"
-
- re = /(?:^|\W|#{all_tags})\K(#{tags})(\1*[#\\]?[\w:#{PROTECT_ATTR}.\/\[\]-]+?\S?)\1(?!\1)(?=#{all_tags}|\W|$)/
-
- 1 while str.gsub!(re) { |orig|
- a, w = (m = $~).values_at(1, 2)
- attr = @matching_word_pairs[a]
- if attrs.set_attrs(m.begin(2), w.length, attr)
- a = NULL * a.length
- else
- a = NON_PRINTING_START + a + NON_PRINTING_END
- end
- a + w + a
- }
- str.delete!(NON_PRINTING_START + NON_PRINTING_END)
- end
-
- # :nodoc:
- 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|
- next unless exclusive == exclusive?(attr)
- 1 while str.gsub!(regexp) { |orig|
- w = (m = ($~))[2]
- updated = attrs.set_attrs(m.begin(2), w.length, attr)
- if updated
- NULL * m.match_length(1) + w + NULL * m.match_length(3)
- else
- orig
- end
- }
- end
- end
- end
-
- ##
- # Converts HTML tags to RDoc attributes
-
- def convert_html(str, attrs, exclusive = false)
- tags = @html_tags.select { |start, bitmap|
- exclusive == exclusive?(bitmap)
- }.keys.join '|'
-
- 1 while str.gsub!(/<(#{tags})>(.*?)<\/\1>/i) { |orig|
- attr = @html_tags[$1.downcase]
- html_length = $~.match_length(1) + 2 # "<>".length
- seq = NULL * html_length
- attrs.set_attrs($~.begin(2), $~.match_length(2), attr)
- seq + $2 + seq + NULL
- }
- end
-
- ##
- # Converts regexp handling sequences to RDoc attributes
-
- def convert_regexp_handlings str, attrs, exclusive = false
- @regexp_handlings.each do |regexp, attribute|
- next unless exclusive == exclusive?(attribute)
- str.scan(regexp) do
- capture = $~.size == 1 ? 0 : 1
-
- s, e = $~.offset capture
-
- attrs.set_attrs s, e - s, attribute | @attributes.regexp_handling
- end
- end
- end
-
- ##
- # Escapes regexp handling sequences of text to prevent conversion to RDoc
-
- def mask_protected_sequences
- # protect __send__, __FILE__, etc.
- @str.gsub!(/__([a-z]+)__/i,
- "_#{PROTECT_ATTR}_#{PROTECT_ATTR}\\1_#{PROTECT_ATTR}_#{PROTECT_ATTR}")
- @str.gsub!(/(\A|[^\\])\\([#{Regexp.escape @protectable.join}])/m,
- "\\1\\2#{PROTECT_ATTR}")
- @str.gsub!(/\\(\\[#{Regexp.escape @protectable.join}])/m, "\\1")
- end
-
- ##
- # Unescapes regexp handling sequences of text
-
- def unmask_protected_sequences
- @str.gsub!(/(.)#{PROTECT_ATTR}/, "\\1\000")
- end
-
- ##
- # Adds a markup class with +name+ for words wrapped in the +start+ and
- # +stop+ character. To make words wrapped with "*" bold:
- #
- # am.add_word_pair '*', '*', :BOLD
-
- def add_word_pair(start, stop, name, exclusive = false)
- raise ArgumentError, "Word flags may not start with '<'" if
- start[0,1] == '<'
-
- bitmap = @attributes.bitmap_for name
-
- if start == stop then
- @matching_word_pairs[start] = bitmap
- else
- pattern = /(#{Regexp.escape start})(\S+)(#{Regexp.escape stop})/
- @word_pair_map[pattern] = bitmap
- end
-
- @protectable << start[0,1]
- @protectable.uniq!
-
- @exclusive_bitmap |= bitmap if exclusive
- end
-
- ##
- # Adds a markup class with +name+ for words surrounded by HTML tag +tag+.
- # To process emphasis tags:
- #
- # am.add_html 'em', :EM
-
- def add_html(tag, name, exclusive = false)
- bitmap = @attributes.bitmap_for name
- @html_tags[tag.downcase] = bitmap
- @exclusive_bitmap |= bitmap if exclusive
- end
-
- ##
- # Adds a regexp handling for +pattern+ with +name+. A simple URL handler
- # would be:
- #
- # @am.add_regexp_handling(/((https?:)\S+\w)/, :HYPERLINK)
-
- def add_regexp_handling pattern, name, exclusive = false
- bitmap = @attributes.bitmap_for(name)
- @regexp_handlings << [pattern, bitmap]
- @exclusive_bitmap |= bitmap if exclusive
- end
-
- ##
- # Processes +str+ converting attributes, HTML and regexp handlings
-
- def flow str
- @str = str.dup
-
- mask_protected_sequences
-
- @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
-
- unmask_protected_sequences
-
- split_into_flow
- end
-
- ##
- # Debug method that prints a string along with its attributes
-
- def display_attributes
- puts
- puts @str.tr(NULL, "!")
- bit = 1
- 16.times do |bno|
- line = ""
- @str.length.times do |i|
- if (@attrs[i] & bit) == 0
- line << " "
- else
- if bno.zero?
- line << "S"
- else
- line << ("%d" % (bno+1))
- end
- end
- end
- puts(line) unless line =~ /^ *$/
- bit <<= 1
- end
- end
-
- ##
- # Splits the string into chunks by attribute change
-
- def split_into_flow
- res = []
- current_attr = 0
-
- str_len = @str.length
-
- # skip leading invisible text
- i = 0
- i += 1 while i < str_len and @str[i].chr == "\0"
- start_pos = i
-
- # then scan the string, chunking it on attribute changes
- while i < str_len
- new_attr = @attrs[i]
- if new_attr != current_attr
- if i > start_pos
- res << copy_string(start_pos, i)
- start_pos = i
- end
-
- res << change_attribute(current_attr, new_attr)
- current_attr = new_attr
-
- if (current_attr & @attributes.regexp_handling) != 0 then
- i += 1 while
- i < str_len and (@attrs[i] & @attributes.regexp_handling) != 0
-
- res << RDoc::Markup::RegexpHandling.new(current_attr,
- copy_string(start_pos, i))
- start_pos = i
- next
- end
- end
-
- # move on, skipping any invisible characters
- begin
- i += 1
- end while i < str_len and @str[i].chr == "\0"
- end
-
- # tidy up trailing text
- if start_pos < str_len
- res << copy_string(start_pos, str_len)
- end
-
- # and reset to all attributes off
- res << change_attribute(current_attr, 0) if current_attr != 0
-
- res
- end
-
-end
diff --git a/lib/rdoc/markup/attributes.rb b/lib/rdoc/markup/attributes.rb
deleted file mode 100644
index d9d18b3059..0000000000
--- a/lib/rdoc/markup/attributes.rb
+++ /dev/null
@@ -1,70 +0,0 @@
-# frozen_string_literal: true
-##
-# We manage a set of attributes. Each attribute has a symbol name and a bit
-# value.
-
-class RDoc::Markup::Attributes
-
- ##
- # The regexp handling attribute type. See RDoc::Markup#add_regexp_handling
-
- attr_reader :regexp_handling
-
- ##
- # Creates a new attributes set.
-
- def initialize
- @regexp_handling = 1
-
- @name_to_bitmap = [
- [:_REGEXP_HANDLING_, @regexp_handling],
- ]
-
- @next_bitmap = @regexp_handling << 1
- end
-
- ##
- # Returns a unique bit for +name+
-
- def bitmap_for name
- bitmap = @name_to_bitmap.assoc name
-
- unless bitmap then
- bitmap = @next_bitmap
- @next_bitmap <<= 1
- @name_to_bitmap << [name, bitmap]
- else
- bitmap = bitmap.last
- end
-
- bitmap
- end
-
- ##
- # Returns a string representation of +bitmap+
-
- def as_string bitmap
- return 'none' if bitmap.zero?
- res = []
-
- @name_to_bitmap.each do |name, bit|
- res << name if (bitmap & bit) != 0
- end
-
- res.join ','
- end
-
- ##
- # yields each attribute name in +bitmap+
-
- def each_name_of bitmap
- return enum_for __method__, bitmap unless block_given?
-
- @name_to_bitmap.each do |name, bit|
- next if bit == @regexp_handling
-
- yield name.to_s if (bitmap & bit) != 0
- end
- end
-
-end
diff --git a/lib/rdoc/markup/blank_line.rb b/lib/rdoc/markup/blank_line.rb
deleted file mode 100644
index f63ae9479c..0000000000
--- a/lib/rdoc/markup/blank_line.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-##
-# An empty line. This class is a singleton.
-
-class RDoc::Markup::BlankLine
-
- @instance = new
-
- ##
- # RDoc::Markup::BlankLine is a singleton
-
- def self.new
- @instance
- end
-
- ##
- # Calls #accept_blank_line on +visitor+
-
- def accept visitor
- visitor.accept_blank_line self
- end
-
- def pretty_print q # :nodoc:
- q.text 'blankline'
- end
-
-end
diff --git a/lib/rdoc/markup/block_quote.rb b/lib/rdoc/markup/block_quote.rb
deleted file mode 100644
index d9fcbf213c..0000000000
--- a/lib/rdoc/markup/block_quote.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-##
-# A quoted section which contains markup items.
-
-class RDoc::Markup::BlockQuote < RDoc::Markup::Raw
-
- ##
- # Calls #accept_block_quote on +visitor+
-
- def accept visitor
- visitor.accept_block_quote self
- end
-
-end
diff --git a/lib/rdoc/markup/document.rb b/lib/rdoc/markup/document.rb
deleted file mode 100644
index 94cf6a3666..0000000000
--- a/lib/rdoc/markup/document.rb
+++ /dev/null
@@ -1,164 +0,0 @@
-# frozen_string_literal: true
-##
-# A Document containing lists, headings, paragraphs, etc.
-
-class RDoc::Markup::Document
-
- include Enumerable
-
- ##
- # The file this document was created from. See also
- # RDoc::ClassModule#add_comment
-
- attr_reader :file
-
- ##
- # If a heading is below the given level it will be omitted from the
- # table_of_contents
-
- attr_accessor :omit_headings_below
-
- ##
- # The parts of the Document
-
- attr_reader :parts
-
- ##
- # Creates a new Document with +parts+
-
- def initialize *parts
- @parts = []
- @parts.concat parts
-
- @file = nil
- @omit_headings_from_table_of_contents_below = nil
- end
-
- ##
- # Appends +part+ to the document
-
- def << part
- case part
- when RDoc::Markup::Document then
- unless part.empty? then
- parts.concat part.parts
- parts << RDoc::Markup::BlankLine.new
- end
- when String then
- raise ArgumentError,
- "expected RDoc::Markup::Document and friends, got String" unless
- part.empty?
- else
- parts << part
- end
- end
-
- def == other # :nodoc:
- self.class == other.class and
- @file == other.file and
- @parts == other.parts
- end
-
- ##
- # Runs this document and all its #items through +visitor+
-
- def accept visitor
- visitor.start_accepting
-
- visitor.accept_document self
-
- visitor.end_accepting
- end
-
- ##
- # Concatenates the given +parts+ onto the document
-
- def concat parts
- self.parts.concat parts
- end
-
- ##
- # Enumerator for the parts of this document
-
- def each &block
- @parts.each(&block)
- end
-
- ##
- # Does this document have no parts?
-
- def empty?
- @parts.empty? or (@parts.length == 1 and merged? and @parts.first.empty?)
- end
-
- ##
- # The file this Document was created from.
-
- def file= location
- @file = case location
- when RDoc::TopLevel then
- location.relative_name
- else
- location
- end
- end
-
- ##
- # When this is a collection of documents (#file is not set and this document
- # contains only other documents as its direct children) #merge replaces
- # documents in this class with documents from +other+ when the file matches
- # and adds documents from +other+ when the files do not.
- #
- # The information in +other+ is preferred over the receiver
-
- def merge other
- if empty? then
- @parts = other.parts
- return self
- end
-
- other.parts.each do |other_part|
- self.parts.delete_if do |self_part|
- self_part.file and self_part.file == other_part.file
- end
-
- self.parts << other_part
- end
-
- self
- end
-
- ##
- # Does this Document contain other Documents?
-
- def merged?
- RDoc::Markup::Document === @parts.first
- end
-
- def pretty_print q # :nodoc:
- start = @file ? "[doc (#{@file}): " : '[doc: '
-
- q.group 2, start, ']' do
- q.seplist @parts do |part|
- q.pp part
- end
- end
- end
-
- ##
- # Appends +parts+ to the document
-
- def push *parts
- self.parts.concat parts
- end
-
- ##
- # Returns an Array of headings in the document.
- #
- # Require 'rdoc/markup/formatter' before calling this method.
-
- def table_of_contents
- accept RDoc::Markup::ToTableOfContents.to_toc
- end
-
-end
diff --git a/lib/rdoc/markup/formatter.rb b/lib/rdoc/markup/formatter.rb
deleted file mode 100644
index 9daffaabb8..0000000000
--- a/lib/rdoc/markup/formatter.rb
+++ /dev/null
@@ -1,265 +0,0 @@
-# frozen_string_literal: true
-##
-# Base class for RDoc markup formatters
-#
-# Formatters are a visitor that converts an RDoc::Markup tree (from a comment)
-# into some kind of output. RDoc ships with formatters for converting back to
-# rdoc, ANSI text, HTML, a Table of Contents and other formats.
-#
-# If you'd like to write your own Formatter use
-# RDoc::Markup::FormatterTestCase. If you're writing a text-output formatter
-# use RDoc::Markup::TextFormatterTestCase which provides extra test cases.
-
-class RDoc::Markup::Formatter
-
- ##
- # Tag for inline markup containing a +bit+ for the bitmask and the +on+ and
- # +off+ triggers.
-
- InlineTag = Struct.new(:bit, :on, :off)
-
- ##
- # Converts a target url to one that is relative to a given path
-
- def self.gen_relative_url path, target
- from = File.dirname path
- to, to_file = File.split target
-
- from = from.split "/"
- to = to.split "/"
-
- from.delete '.'
- to.delete '.'
-
- while from.size > 0 and to.size > 0 and from[0] == to[0] do
- from.shift
- to.shift
- end
-
- from.fill ".."
- from.concat to
- from << to_file
- File.join(*from)
- end
-
- ##
- # Creates a new Formatter
-
- def initialize options, markup = nil
- @options = options
-
- @markup = markup || RDoc::Markup.new
- @am = @markup.attribute_manager
- @am.add_regexp_handling(/<br>/, :HARD_BREAK)
-
- @attributes = @am.attributes
-
- @attr_tags = []
-
- @in_tt = 0
- @tt_bit = @attributes.bitmap_for :TT
-
- @hard_break = ''
- @from_path = '.'
- end
-
- ##
- # Adds +document+ to the output
-
- def accept_document document
- document.parts.each do |item|
- case item
- when RDoc::Markup::Document then # HACK
- accept_document item
- else
- item.accept self
- end
- end
- end
-
- ##
- # Adds a regexp handling for links of the form rdoc-...:
-
- def add_regexp_handling_RDOCLINK
- @markup.add_regexp_handling(/rdoc-[a-z]+:[^\s\]]+/, :RDOCLINK)
- end
-
- ##
- # Adds a regexp handling for links of the form {<text>}[<url>] and
- # <word>[<url>]
-
- def add_regexp_handling_TIDYLINK
- @markup.add_regexp_handling(/(?:
- \{[^{}]*\} | # multi-word label
- \b[^\s{}]+? # single-word label
- )
-
- \[\S+?\] # link target
- /x, :TIDYLINK)
- end
-
- ##
- # Add a new set of tags for an attribute. We allow separate start and end
- # tags for flexibility
-
- def add_tag(name, start, stop)
- attr = @attributes.bitmap_for name
- @attr_tags << InlineTag.new(attr, start, stop)
- end
-
- ##
- # Allows +tag+ to be decorated with additional information.
-
- def annotate(tag)
- tag
- end
-
- ##
- # Marks up +content+
-
- def convert content
- @markup.convert content, self
- end
-
- ##
- # Converts flow items +flow+
-
- def convert_flow(flow)
- res = []
-
- flow.each do |item|
- case item
- when String then
- res << convert_string(item)
- when RDoc::Markup::AttrChanger then
- off_tags res, item
- on_tags res, item
- when RDoc::Markup::RegexpHandling then
- res << convert_regexp_handling(item)
- else
- raise "Unknown flow element: #{item.inspect}"
- end
- end
-
- res.join
- end
-
- ##
- # Converts added regexp handlings. See RDoc::Markup#add_regexp_handling
-
- def convert_regexp_handling target
- return target.text if in_tt?
-
- handled = false
-
- @attributes.each_name_of target.type do |name|
- method_name = "handle_regexp_#{name}"
-
- if respond_to? method_name then
- target.text = public_send method_name, target
- handled = true
- end
- end
-
- unless handled then
- target_name = @attributes.as_string target.type
-
- raise RDoc::Error, "Unhandled regexp handling #{target_name}: #{target}"
- end
-
- target.text
- end
-
- ##
- # Converts a string to be fancier if desired
-
- def convert_string string
- string
- end
-
- ##
- # Use ignore in your subclass to ignore the content of a node.
- #
- # ##
- # # We don't support raw nodes in ToNoRaw
- #
- # alias accept_raw ignore
-
- def ignore *node
- end
-
- ##
- # Are we currently inside tt tags?
-
- def in_tt?
- @in_tt > 0
- end
-
- ##
- # Turns on tags for +item+ on +res+
-
- def on_tags res, item
- attr_mask = item.turn_on
- return if attr_mask.zero?
-
- @attr_tags.each do |tag|
- if attr_mask & tag.bit != 0 then
- res << annotate(tag.on)
- @in_tt += 1 if tt? tag
- end
- end
- end
-
- ##
- # Turns off tags for +item+ on +res+
-
- def off_tags res, item
- attr_mask = item.turn_off
- return if attr_mask.zero?
-
- @attr_tags.reverse_each do |tag|
- if attr_mask & tag.bit != 0 then
- @in_tt -= 1 if tt? tag
- res << annotate(tag.off)
- end
- end
- end
-
- ##
- # Extracts and a scheme, url and an anchor id from +url+ and returns them.
-
- def parse_url url
- case url
- when /^rdoc-label:([^:]*)(?::(.*))?/ then
- scheme = 'link'
- path = "##{$1}"
- id = " id=\"#{$2}\"" if $2
- when /([A-Za-z]+):(.*)/ then
- scheme = $1.downcase
- path = $2
- when /^#/ then
- else
- scheme = 'http'
- path = url
- url = url
- end
-
- if scheme == 'link' then
- url = if path[0, 1] == '#' then # is this meaningful?
- path
- else
- self.class.gen_relative_url @from_path, path
- end
- end
-
- [scheme, url, id]
- end
-
- ##
- # Is +tag+ a tt tag?
-
- def tt? tag
- tag.bit == @tt_bit
- end
-
-end
diff --git a/lib/rdoc/markup/hard_break.rb b/lib/rdoc/markup/hard_break.rb
deleted file mode 100644
index de1819c903..0000000000
--- a/lib/rdoc/markup/hard_break.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-##
-# A hard-break in the middle of a paragraph.
-
-class RDoc::Markup::HardBreak
-
- @instance = new
-
- ##
- # RDoc::Markup::HardBreak is a singleton
-
- def self.new
- @instance
- end
-
- ##
- # Calls #accept_hard_break on +visitor+
-
- def accept visitor
- visitor.accept_hard_break self
- end
-
- def == other # :nodoc:
- self.class === other
- end
-
- def pretty_print q # :nodoc:
- q.text "[break]"
- end
-
-end
diff --git a/lib/rdoc/markup/heading.rb b/lib/rdoc/markup/heading.rb
deleted file mode 100644
index 02476e5226..0000000000
--- a/lib/rdoc/markup/heading.rb
+++ /dev/null
@@ -1,78 +0,0 @@
-# frozen_string_literal: true
-##
-# A heading with a level (1-6) and text
-
-RDoc::Markup::Heading =
- Struct.new :level, :text do
-
- @to_html = nil
- @to_label = nil
-
- ##
- # A singleton RDoc::Markup::ToLabel formatter for headings.
-
- def self.to_label
- @to_label ||= RDoc::Markup::ToLabel.new
- end
-
- ##
- # A singleton plain HTML formatter for headings. Used for creating labels
- # for the Table of Contents
-
- def self.to_html
- return @to_html if @to_html
-
- markup = RDoc::Markup.new
- markup.add_regexp_handling RDoc::CrossReference::CROSSREF_REGEXP, :CROSSREF
-
- @to_html = RDoc::Markup::ToHtml.new nil
-
- def @to_html.handle_regexp_CROSSREF target
- target.text.sub(/^\\/, '')
- end
-
- @to_html
- end
-
- ##
- # Calls #accept_heading on +visitor+
-
- def accept visitor
- visitor.accept_heading self
- end
-
- ##
- # An HTML-safe anchor reference for this header.
-
- def aref
- "label-#{self.class.to_label.convert text.dup}"
- end
-
- ##
- # Creates a fully-qualified label which will include the label from
- # +context+. This helps keep ids unique in HTML.
-
- def label context = nil
- label = aref
-
- label = [context.aref, label].compact.join '-' if
- context and context.respond_to? :aref
-
- label
- end
-
- ##
- # HTML markup of the text of this label without the surrounding header
- # element.
-
- def plain_html
- self.class.to_html.to_html(text.dup)
- end
-
- def pretty_print q # :nodoc:
- q.group 2, "[head: #{level} ", ']' do
- q.pp text
- end
- end
-
-end
diff --git a/lib/rdoc/markup/include.rb b/lib/rdoc/markup/include.rb
deleted file mode 100644
index 2bf63526b2..0000000000
--- a/lib/rdoc/markup/include.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-##
-# A file included at generation time. Objects of this class are created by
-# RDoc::RD for an extension-less include.
-#
-# This implementation in incomplete.
-
-class RDoc::Markup::Include
-
- ##
- # The filename to be included, without extension
-
- attr_reader :file
-
- ##
- # Directories to search for #file
-
- attr_reader :include_path
-
- ##
- # Creates a new include that will import +file+ from +include_path+
-
- def initialize file, include_path
- @file = file
- @include_path = include_path
- end
-
- def == other # :nodoc:
- self.class === other and
- @file == other.file and @include_path == other.include_path
- end
-
- def pretty_print q # :nodoc:
- q.group 2, '[incl ', ']' do
- q.text file
- q.breakable
- q.text 'from '
- q.pp include_path
- end
- end
-
-end
diff --git a/lib/rdoc/markup/indented_paragraph.rb b/lib/rdoc/markup/indented_paragraph.rb
deleted file mode 100644
index 992cd7cf81..0000000000
--- a/lib/rdoc/markup/indented_paragraph.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# frozen_string_literal: true
-##
-# An Indented Paragraph of text
-
-class RDoc::Markup::IndentedParagraph < RDoc::Markup::Raw
-
- ##
- # The indent in number of spaces
-
- attr_reader :indent
-
- ##
- # Creates a new IndentedParagraph containing +parts+ indented with +indent+
- # spaces
-
- def initialize indent, *parts
- @indent = indent
-
- super(*parts)
- end
-
- def == other # :nodoc:
- super and indent == other.indent
- end
-
- ##
- # Calls #accept_indented_paragraph on +visitor+
-
- def accept visitor
- visitor.accept_indented_paragraph self
- end
-
- ##
- # Joins the raw paragraph text and converts inline HardBreaks to the
- # +hard_break+ text followed by the indent.
-
- def text hard_break = nil
- @parts.map do |part|
- if RDoc::Markup::HardBreak === part then
- '%1$s%3$*2$s' % [hard_break, @indent, ' '] if hard_break
- else
- part
- end
- end.join
- end
-
-end
diff --git a/lib/rdoc/markup/list.rb b/lib/rdoc/markup/list.rb
deleted file mode 100644
index 112b7a1a86..0000000000
--- a/lib/rdoc/markup/list.rb
+++ /dev/null
@@ -1,101 +0,0 @@
-# frozen_string_literal: true
-##
-# A List is a homogeneous set of ListItems.
-#
-# The supported list types include:
-#
-# :BULLET::
-# An unordered list
-# :LABEL::
-# An unordered definition list, but using an alternate RDoc::Markup syntax
-# :LALPHA::
-# An ordered list using increasing lowercase English letters
-# :NOTE::
-# An unordered definition list
-# :NUMBER::
-# An ordered list using increasing Arabic numerals
-# :UALPHA::
-# An ordered list using increasing uppercase English letters
-#
-# Definition lists behave like HTML definition lists. Each list item can
-# describe multiple terms. See RDoc::Markup::ListItem for how labels and
-# definition are stored as list items.
-
-class RDoc::Markup::List
-
- ##
- # The list's type
-
- attr_accessor :type
-
- ##
- # Items in the list
-
- attr_reader :items
-
- ##
- # Creates a new list of +type+ with +items+. Valid list types are:
- # +:BULLET+, +:LABEL+, +:LALPHA+, +:NOTE+, +:NUMBER+, +:UALPHA+
-
- def initialize type = nil, *items
- @type = type
- @items = []
- @items.concat items
- end
-
- ##
- # Appends +item+ to the list
-
- def << item
- @items << item
- end
-
- def == other # :nodoc:
- self.class == other.class and
- @type == other.type and
- @items == other.items
- end
-
- ##
- # Runs this list and all its #items through +visitor+
-
- def accept visitor
- visitor.accept_list_start self
-
- @items.each do |item|
- item.accept visitor
- end
-
- visitor.accept_list_end self
- end
-
- ##
- # Is the list empty?
-
- def empty?
- @items.empty?
- end
-
- ##
- # Returns the last item in the list
-
- def last
- @items.last
- end
-
- def pretty_print q # :nodoc:
- q.group 2, "[list: #{@type} ", ']' do
- q.seplist @items do |item|
- q.pp item
- end
- end
- end
-
- ##
- # Appends +items+ to the list
-
- def push *items
- @items.concat items
- end
-
-end
diff --git a/lib/rdoc/markup/list_item.rb b/lib/rdoc/markup/list_item.rb
deleted file mode 100644
index 0b8326a69f..0000000000
--- a/lib/rdoc/markup/list_item.rb
+++ /dev/null
@@ -1,99 +0,0 @@
-# frozen_string_literal: true
-##
-# An item within a List that contains paragraphs, headings, etc.
-#
-# For BULLET, NUMBER, LALPHA and UALPHA lists, the label will always be nil.
-# For NOTE and LABEL lists, the list label may contain:
-#
-# * a single String for a single label
-# * an Array of Strings for a list item with multiple terms
-# * nil for an extra description attached to a previously labeled list item
-
-class RDoc::Markup::ListItem
-
- ##
- # The label for the ListItem
-
- attr_accessor :label
-
- ##
- # Parts of the ListItem
-
- attr_reader :parts
-
- ##
- # Creates a new ListItem with an optional +label+ containing +parts+
-
- def initialize label = nil, *parts
- @label = label
- @parts = []
- @parts.concat parts
- end
-
- ##
- # Appends +part+ to the ListItem
-
- def << part
- @parts << part
- end
-
- def == other # :nodoc:
- self.class == other.class and
- @label == other.label and
- @parts == other.parts
- end
-
- ##
- # Runs this list item and all its #parts through +visitor+
-
- def accept visitor
- visitor.accept_list_item_start self
-
- @parts.each do |part|
- part.accept visitor
- end
-
- visitor.accept_list_item_end self
- end
-
- ##
- # Is the ListItem empty?
-
- def empty?
- @parts.empty?
- end
-
- ##
- # Length of parts in the ListItem
-
- def length
- @parts.length
- end
-
- def pretty_print q # :nodoc:
- q.group 2, '[item: ', ']' do
- case @label
- when Array then
- q.pp @label
- q.text ';'
- q.breakable
- when String then
- q.pp @label
- q.text ';'
- q.breakable
- end
-
- q.seplist @parts do |part|
- q.pp part
- end
- end
- end
-
- ##
- # Adds +parts+ to the ListItem
-
- def push *parts
- @parts.concat parts
- end
-
-end
diff --git a/lib/rdoc/markup/paragraph.rb b/lib/rdoc/markup/paragraph.rb
deleted file mode 100644
index 21dfda007a..0000000000
--- a/lib/rdoc/markup/paragraph.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-##
-# A Paragraph of text
-
-class RDoc::Markup::Paragraph < RDoc::Markup::Raw
-
- ##
- # Calls #accept_paragraph on +visitor+
-
- def accept visitor
- visitor.accept_paragraph self
- end
-
- ##
- # Joins the raw paragraph text and converts inline HardBreaks to the
- # +hard_break+ text.
-
- def text hard_break = ''
- @parts.map do |part|
- if RDoc::Markup::HardBreak === part then
- hard_break
- else
- part
- end
- end.join
- end
-
-end
diff --git a/lib/rdoc/markup/parser.rb b/lib/rdoc/markup/parser.rb
deleted file mode 100644
index 9c77048591..0000000000
--- a/lib/rdoc/markup/parser.rb
+++ /dev/null
@@ -1,585 +0,0 @@
-# frozen_string_literal: true
-require 'strscan'
-
-##
-# A recursive-descent parser for RDoc markup.
-#
-# The parser tokenizes an input string then parses the tokens into a Document.
-# Documents can be converted into output formats by writing a visitor like
-# RDoc::Markup::ToHTML.
-#
-# The parser only handles the block-level constructs Paragraph, List,
-# ListItem, Heading, Verbatim, BlankLine, Rule and BlockQuote.
-# Inline markup such as <tt>\+blah\+</tt> is handled separately by
-# RDoc::Markup::AttributeManager.
-#
-# To see what markup the Parser implements read RDoc. To see how to use
-# RDoc markup to format text in your program read RDoc::Markup.
-
-class RDoc::Markup::Parser
-
- include RDoc::Text
-
- ##
- # List token types
-
- LIST_TOKENS = [
- :BULLET,
- :LABEL,
- :LALPHA,
- :NOTE,
- :NUMBER,
- :UALPHA,
- ]
-
- ##
- # Parser error subclass
-
- class Error < RuntimeError; end
-
- ##
- # Raised when the parser is unable to handle the given markup
-
- class ParseError < Error; end
-
- ##
- # Enables display of debugging information
-
- attr_accessor :debug
-
- ##
- # Token accessor
-
- attr_reader :tokens
-
- ##
- # Parses +str+ into a Document.
- #
- # Use RDoc::Markup#parse instead of this method.
-
- def self.parse str
- parser = new
- parser.tokenize str
- doc = RDoc::Markup::Document.new
- parser.parse doc
- end
-
- ##
- # Returns a token stream for +str+, for testing
-
- def self.tokenize str
- parser = new
- parser.tokenize str
- parser.tokens
- end
-
- ##
- # Creates a new Parser. See also ::parse
-
- def initialize
- @binary_input = nil
- @current_token = nil
- @debug = false
- @s = nil
- @tokens = []
- end
-
- ##
- # Builds a Heading of +level+
-
- def build_heading level
- type, text, = get
-
- text = case type
- when :TEXT then
- skip :NEWLINE
- text
- else
- unget
- ''
- end
-
- RDoc::Markup::Heading.new level, text
- end
-
- ##
- # Builds a List flush to +margin+
-
- def build_list margin
- p :list_start => margin if @debug
-
- list = RDoc::Markup::List.new
- label = nil
-
- until @tokens.empty? do
- type, data, column, = get
-
- case type
- when *LIST_TOKENS then
- if column < margin || (list.type && list.type != type) then
- unget
- break
- end
-
- list.type = type
- peek_type, _, column, = peek_token
-
- case type
- when :NOTE, :LABEL then
- label = [] unless label
-
- if peek_type == :NEWLINE then
- # description not on the same line as LABEL/NOTE
- # skip the trailing newline & any blank lines below
- while peek_type == :NEWLINE
- get
- peek_type, _, column, = peek_token
- end
-
- # we may be:
- # - at end of stream
- # - at a column < margin:
- # [text]
- # blah blah blah
- # - at the same column, but with a different type of list item
- # [text]
- # * blah blah
- # - at the same column, with the same type of list item
- # [one]
- # [two]
- # In all cases, we have an empty description.
- # In the last case only, we continue.
- if peek_type.nil? || column < margin then
- empty = true
- elsif column == margin then
- case peek_type
- when type
- empty = :continue
- when *LIST_TOKENS
- empty = true
- else
- empty = false
- end
- else
- empty = false
- end
-
- if empty then
- label << data
- next if empty == :continue
- break
- end
- end
- else
- data = nil
- end
-
- if label then
- data = label << data
- label = nil
- end
-
- list_item = RDoc::Markup::ListItem.new data
- parse list_item, column
- list << list_item
-
- else
- unget
- break
- end
- end
-
- p :list_end => margin if @debug
-
- if list.empty? then
- return nil unless label
- return nil unless [:LABEL, :NOTE].include? list.type
-
- list_item = RDoc::Markup::ListItem.new label, RDoc::Markup::BlankLine.new
- list << list_item
- end
-
- list
- end
-
- ##
- # Builds a Paragraph that is flush to +margin+
-
- def build_paragraph margin
- p :paragraph_start => margin if @debug
-
- paragraph = RDoc::Markup::Paragraph.new
-
- until @tokens.empty? do
- type, data, column, = get
-
- if type == :TEXT and column == margin then
- paragraph << data
-
- break if peek_token.first == :BREAK
-
- data << ' ' if skip :NEWLINE and /#{SPACE_SEPARATED_LETTER_CLASS}\z/o.match?(data)
- else
- unget
- break
- end
- end
-
- paragraph.parts.last.sub!(/ \z/, '') # cleanup
-
- p :paragraph_end => margin if @debug
-
- paragraph
- end
-
- ##
- # Builds a Verbatim that is indented from +margin+.
- #
- # The verbatim block is shifted left (the least indented lines start in
- # column 0). Each part of the verbatim is one line of text, always
- # terminated by a newline. Blank lines always consist of a single newline
- # character, and there is never a single newline at the end of the verbatim.
-
- def build_verbatim margin
- p :verbatim_begin => margin if @debug
- verbatim = RDoc::Markup::Verbatim.new
-
- min_indent = nil
- generate_leading_spaces = true
- line = ''.dup
-
- until @tokens.empty? do
- type, data, column, = get
-
- if type == :NEWLINE then
- line << data
- verbatim << line
- line = ''.dup
- generate_leading_spaces = true
- next
- end
-
- if column <= margin
- unget
- break
- end
-
- if generate_leading_spaces then
- indent = column - margin
- line << ' ' * indent
- min_indent = indent if min_indent.nil? || indent < min_indent
- generate_leading_spaces = false
- end
-
- case type
- when :HEADER then
- line << '=' * data
- _, _, peek_column, = peek_token
- peek_column ||= column + data
- indent = peek_column - column - data
- line << ' ' * indent
- when :RULE then
- width = 2 + data
- line << '-' * width
- _, _, peek_column, = peek_token
- peek_column ||= column + width
- indent = peek_column - column - width
- line << ' ' * indent
- when :BREAK, :TEXT then
- line << data
- when :BLOCKQUOTE then
- line << '>>>'
- peek_type, _, peek_column = peek_token
- if peek_type != :NEWLINE and peek_column
- line << ' ' * (peek_column - column - 3)
- end
- else # *LIST_TOKENS
- list_marker = case type
- when :BULLET then data
- when :LABEL then "[#{data}]"
- when :NOTE then "#{data}::"
- else # :LALPHA, :NUMBER, :UALPHA
- "#{data}."
- end
- line << list_marker
- peek_type, _, peek_column = peek_token
- unless peek_type == :NEWLINE then
- peek_column ||= column + list_marker.length
- indent = peek_column - column - list_marker.length
- line << ' ' * indent
- end
- end
-
- end
-
- verbatim << line << "\n" unless line.empty?
- verbatim.parts.each { |p| p.slice!(0, min_indent) unless p == "\n" } if min_indent > 0
- verbatim.normalize
-
- p :verbatim_end => margin if @debug
-
- verbatim
- end
-
- ##
- # Pulls the next token from the stream.
-
- def get
- @current_token = @tokens.shift
- p :get => @current_token if @debug
- @current_token
- end
-
- ##
- # Parses the tokens into an array of RDoc::Markup::XXX objects,
- # and appends them to the passed +parent+ RDoc::Markup::YYY object.
- #
- # Exits at the end of the token stream, or when it encounters a token
- # in a column less than +indent+ (unless it is a NEWLINE).
- #
- # Returns +parent+.
-
- def parse parent, indent = 0
- p :parse_start => indent if @debug
-
- until @tokens.empty? do
- type, data, column, = get
-
- case type
- when :BREAK then
- parent << RDoc::Markup::BlankLine.new
- skip :NEWLINE, false
- next
- when :NEWLINE then
- # trailing newlines are skipped below, so this is a blank line
- parent << RDoc::Markup::BlankLine.new
- skip :NEWLINE, false
- next
- end
-
- # indentation change: break or verbatim
- if column < indent then
- unget
- break
- elsif column > indent then
- unget
- parent << build_verbatim(indent)
- next
- end
-
- # indentation is the same
- case type
- when :HEADER then
- parent << build_heading(data)
- when :RULE then
- parent << RDoc::Markup::Rule.new(data)
- skip :NEWLINE
- when :TEXT then
- unget
- parse_text parent, indent
- when :BLOCKQUOTE then
- nil while (type, = get; type) and type != :NEWLINE
- _, _, column, = peek_token
- bq = RDoc::Markup::BlockQuote.new
- p :blockquote_start => [data, column] if @debug
- parse bq, column
- p :blockquote_end => indent if @debug
- parent << bq
- when *LIST_TOKENS then
- unget
- parent << build_list(indent)
- else
- type, data, column, line = @current_token
- raise ParseError, "Unhandled token #{type} (#{data.inspect}) at #{line}:#{column}"
- end
- end
-
- p :parse_end => indent if @debug
-
- parent
-
- end
-
- ##
- # Small hook that is overridden by RDoc::TomDoc
-
- def parse_text parent, indent # :nodoc:
- parent << build_paragraph(indent)
- end
-
- ##
- # Returns the next token on the stream without modifying the stream
-
- def peek_token
- token = @tokens.first || []
- p :peek => token if @debug
- token
- end
-
- ##
- # A simple wrapper of StringScanner that is aware of the current column and lineno
-
- class MyStringScanner
- # :stopdoc:
-
- def initialize(input)
- @line = @column = 0
- @s = StringScanner.new input
- end
-
- def scan(re)
- ret = @s.scan(re)
- @column += ret.length if ret
- ret
- end
-
- def unscan(s)
- @s.pos -= s.bytesize
- @column -= s.length
- end
-
- def pos
- [@column, @line]
- end
-
- def newline!
- @column = 0
- @line += 1
- end
-
- def eos?
- @s.eos?
- end
-
- def matched
- @s.matched
- end
-
- def [](i)
- @s[i]
- end
-
- #:startdoc:
- end
-
- ##
- # Creates the StringScanner
-
- def setup_scanner input
- @s = MyStringScanner.new input
- end
-
- ##
- # Skips the next token if its type is +token_type+.
- #
- # Optionally raises an error if the next token is not of the expected type.
-
- def skip token_type, error = true
- type, = get
- return unless type # end of stream
- return @current_token if token_type == type
- unget
- raise ParseError, "expected #{token_type} got #{@current_token.inspect}" if error
- end
-
- ##
- # Turns text +input+ into a stream of tokens
-
- def tokenize input
- setup_scanner input
-
- until @s.eos? do
- pos = @s.pos
-
- # leading spaces will be reflected by the column of the next token
- # the only thing we loose are trailing spaces at the end of the file
- next if @s.scan(/ +/)
-
- # note: after BULLET, LABEL, etc.,
- # indent will be the column of the next non-newline token
-
- @tokens << case
- # [CR]LF => :NEWLINE
- when @s.scan(/\r?\n/) then
- token = [:NEWLINE, @s.matched, *pos]
- @s.newline!
- token
- # === text => :HEADER then :TEXT
- when @s.scan(/(=+)(\s*)/) then
- level = @s[1].length
- header = [:HEADER, level, *pos]
-
- if @s[2] =~ /^\r?\n/ then
- @s.unscan(@s[2])
- header
- else
- pos = @s.pos
- @s.scan(/.*/)
- @tokens << header
- [:TEXT, @s.matched.sub(/\r$/, ''), *pos]
- end
- # --- (at least 3) and nothing else on the line => :RULE
- when @s.scan(/(-{3,}) *\r?$/) then
- [:RULE, @s[1].length - 2, *pos]
- # * or - followed by white space and text => :BULLET
- when @s.scan(/([*-]) +(\S)/) then
- @s.unscan(@s[2])
- [:BULLET, @s[1], *pos]
- # A. text, a. text, 12. text => :UALPHA, :LALPHA, :NUMBER
- when @s.scan(/([a-z]|\d+)\. +(\S)/i) then
- # FIXME if tab(s), the column will be wrong
- # either support tabs everywhere by first expanding them to
- # spaces, or assume that they will have been replaced
- # before (and provide a check for that at least in debug
- # mode)
- list_label = @s[1]
- @s.unscan(@s[2])
- list_type =
- case list_label
- when /[a-z]/ then :LALPHA
- when /[A-Z]/ then :UALPHA
- when /\d/ then :NUMBER
- else
- raise ParseError, "BUG token #{list_label}"
- end
- [list_type, list_label, *pos]
- # [text] followed by spaces or end of line => :LABEL
- when @s.scan(/\[(.*?)\]( +|\r?$)/) then
- [:LABEL, @s[1], *pos]
- # text:: followed by spaces or end of line => :NOTE
- when @s.scan(/(.*?)::( +|\r?$)/) then
- [:NOTE, @s[1], *pos]
- # >>> followed by end of line => :BLOCKQUOTE
- when @s.scan(/>>> *(\w+)?$/) then
- if word = @s[1]
- @s.unscan(word)
- end
- [:BLOCKQUOTE, word, *pos]
- # anything else: :TEXT
- else
- @s.scan(/(.*?)( )?\r?$/)
- token = [:TEXT, @s[1], *pos]
-
- if @s[2] then
- @tokens << token
- [:BREAK, @s[2], pos[0] + @s[1].length, pos[1]]
- else
- token
- end
- end
- end
-
- self
- end
-
- ##
- # Returns the current token to the token stream
-
- def unget
- token = @current_token
- p :unget => token if @debug
- raise Error, 'too many #ungets' if token == @tokens.first
- @tokens.unshift token if token
- end
-
-end
diff --git a/lib/rdoc/markup/pre_process.rb b/lib/rdoc/markup/pre_process.rb
deleted file mode 100644
index 88078c9cef..0000000000
--- a/lib/rdoc/markup/pre_process.rb
+++ /dev/null
@@ -1,298 +0,0 @@
-# frozen_string_literal: true
-##
-# Handle common directives that can occur in a block of text:
-#
-# \:include: filename
-#
-# Directives can be escaped by preceding them with a backslash.
-#
-# RDoc plugin authors can register additional directives to be handled by
-# using RDoc::Markup::PreProcess::register.
-#
-# Any directive that is not built-in to RDoc (including those registered via
-# plugins) will be stored in the metadata hash on the CodeObject the comment
-# is attached to. See RDoc::Markup@Directives for the list of built-in
-# directives.
-
-class RDoc::Markup::PreProcess
-
- ##
- # An RDoc::Options instance that will be filled in with overrides from
- # directives
-
- attr_accessor :options
-
- ##
- # Adds a post-process handler for directives. The handler will be called
- # with the result RDoc::Comment (or text String) and the code object for the
- # comment (if any).
-
- def self.post_process &block
- @post_processors << block
- end
-
- ##
- # Registered post-processors
-
- def self.post_processors
- @post_processors
- end
-
- ##
- # Registers +directive+ as one handled by RDoc. If a block is given the
- # directive will be replaced by the result of the block, otherwise the
- # directive will be removed from the processed text.
- #
- # The block will be called with the directive name and the directive
- # parameter:
- #
- # RDoc::Markup::PreProcess.register 'my-directive' do |directive, param|
- # # replace text, etc.
- # end
-
- def self.register directive, &block
- @registered[directive] = block
- end
-
- ##
- # Registered directives
-
- def self.registered
- @registered
- end
-
- ##
- # Clears all registered directives and post-processors
-
- def self.reset
- @post_processors = []
- @registered = {}
- end
-
- reset
-
- ##
- # Creates a new pre-processor for +input_file_name+ that will look for
- # included files in +include_path+
-
- def initialize(input_file_name, include_path)
- @input_file_name = input_file_name
- @include_path = include_path
- @options = nil
- end
-
- ##
- # Look for directives in the given +text+.
- #
- # Options that we don't handle are yielded. If the block returns false the
- # directive is restored to the text. If the block returns nil or no block
- # was given the directive is handled according to the registered directives.
- # If a String was returned the directive is replaced with the string.
- #
- # If no matching directive was registered the directive is restored to the
- # text.
- #
- # If +code_object+ is given and the directive is unknown then the
- # directive's parameter is set as metadata on the +code_object+. See
- # RDoc::CodeObject#metadata for details.
-
- def handle text, code_object = nil, &block
- if RDoc::Comment === text then
- comment = text
- text = text.text
- end
-
- # regexp helper (square brackets for optional)
- # $1 $2 $3 $4 $5
- # [prefix][\]:directive:[spaces][param]newline
- text = text.gsub(/^([ \t]*(?:#|\/?\*)?[ \t]*)(\\?):(\w+):([ \t]*)(.+)?(\r?\n|$)/) do
- # skip something like ':toto::'
- next $& if $4.empty? and $5 and $5[0, 1] == ':'
-
- # skip if escaped
- next "#$1:#$3:#$4#$5\n" unless $2.empty?
-
- # This is not in handle_directive because I didn't want to pass another
- # argument into it
- if comment and $3 == 'markup' then
- next "#{$1.strip}\n" unless $5
- comment.format = $5.downcase
- next "#{$1.strip}\n"
- end
-
- handle_directive $1, $3, $5, code_object, text.encoding, &block
- end
-
- if comment then
- comment.text = text
- else
- comment = text
- end
-
- self.class.post_processors.each do |handler|
- handler.call comment, code_object
- end
-
- text
- end
-
- ##
- # Performs the actions described by +directive+ and its parameter +param+.
- #
- # +code_object+ is used for directives that operate on a class or module.
- # +prefix+ is used to ensure the replacement for handled directives is
- # correct. +encoding+ is used for the <tt>include</tt> directive.
- #
- # For a list of directives in RDoc see RDoc::Markup.
- #--
- # When 1.8.7 support is ditched prefix can be defaulted to ''
-
- def handle_directive prefix, directive, param, code_object = nil,
- encoding = nil
- blankline = "#{prefix.strip}\n"
- directive = directive.downcase
-
- case directive
- when 'arg', 'args' then
- return "#{prefix}:#{directive}: #{param}\n" unless code_object && code_object.kind_of?(RDoc::AnyMethod)
-
- code_object.params = param
-
- blankline
- when 'category' then
- 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
- when 'doc' then
- return blankline unless code_object
- code_object.document_self = true
- code_object.force_documentation = true
-
- blankline
- when 'enddoc' then
- return blankline unless code_object
- code_object.done_documenting = true
-
- blankline
- when 'include' then
- filename = param.split(' ', 2).first
- include_file filename, prefix, encoding
- when 'main' then
- @options.main_page = param if @options.respond_to? :main_page
-
- blankline
- when 'nodoc' then
- return blankline unless code_object
- code_object.document_self = nil # notify nodoc
- code_object.document_children = param !~ /all/i
-
- blankline
- when 'notnew', 'not_new', 'not-new' then
- return blankline unless RDoc::AnyMethod === code_object
-
- code_object.dont_rename_initialize = true
-
- blankline
- when 'startdoc' then
- return blankline unless code_object
-
- code_object.start_doc
- code_object.force_documentation = true
-
- blankline
- when 'stopdoc' then
- return blankline unless code_object
-
- code_object.stop_doc
-
- blankline
- when 'title' then
- @options.default_title = param if @options.respond_to? :default_title=
-
- blankline
- when 'yield', 'yields' then
- return blankline unless code_object
- # remove parameter &block
- code_object.params = code_object.params.sub(/,?\s*&\w+/, '') if code_object.params
-
- code_object.block_params = param
-
- blankline
- else
- result = yield directive, param if block_given?
-
- case result
- when nil then
- code_object.metadata[directive] = param if code_object
-
- if RDoc::Markup::PreProcess.registered.include? directive then
- handler = RDoc::Markup::PreProcess.registered[directive]
- result = handler.call directive, param if handler
- else
- result = "#{prefix}:#{directive}: #{param}\n"
- end
- when false then
- result = "#{prefix}:#{directive}: #{param}\n"
- end
-
- result
- end
- end
-
- ##
- # Handles the <tt>:include: _filename_</tt> directive.
- #
- # If the first line of the included file starts with '#', and contains
- # an encoding information in the form 'coding:' or 'coding=', it is
- # removed.
- #
- # If all lines in the included file start with a '#', this leading '#'
- # is removed before inclusion. The included content is indented like
- # the <tt>:include:</tt> directive.
- #--
- # so all content will be verbatim because of the likely space after '#'?
- # TODO shift left the whole file content in that case
- # TODO comment stop/start #-- and #++ in included file must be processed here
-
- def include_file name, indent, encoding
- full_name = find_include_file name
-
- unless full_name then
- warn "Couldn't find file to include '#{name}' from #{@input_file_name}"
- return ''
- end
-
- content = RDoc::Encoding.read_file full_name, encoding, true
- content = RDoc::Encoding.remove_magic_comment content
-
- # strip magic comment
- content = content.sub(/\A# .*coding[=:].*$/, '').lstrip
-
- # strip leading '#'s, but only if all lines start with them
- if content =~ /^[^#]/ then
- content.gsub(/^/, indent)
- else
- content.gsub(/^#?/, indent)
- end
- end
-
- ##
- # Look for the given file in the directory containing the current file,
- # and then in each of the directories specified in the RDOC_INCLUDE path
-
- def find_include_file(name)
- to_search = [File.dirname(@input_file_name)].concat @include_path
- to_search.each do |dir|
- full_name = File.join(dir, name)
- stat = File.stat(full_name) rescue next
- return full_name if stat.readable?
- end
- nil
- end
-
-end
diff --git a/lib/rdoc/markup/raw.rb b/lib/rdoc/markup/raw.rb
deleted file mode 100644
index a7c1c210a6..0000000000
--- a/lib/rdoc/markup/raw.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-# frozen_string_literal: true
-##
-# A section of text that is added to the output document as-is
-
-class RDoc::Markup::Raw
-
- ##
- # The component parts of the list
-
- attr_reader :parts
-
- ##
- # Creates a new Raw containing +parts+
-
- def initialize *parts
- @parts = []
- @parts.concat parts
- end
-
- ##
- # Appends +text+
-
- def << text
- @parts << text
- end
-
- def == other # :nodoc:
- self.class == other.class and @parts == other.parts
- end
-
- ##
- # Calls #accept_raw+ on +visitor+
-
- def accept visitor
- visitor.accept_raw self
- end
-
- ##
- # Appends +other+'s parts
-
- def merge other
- @parts.concat other.parts
- end
-
- def pretty_print q # :nodoc:
- self.class.name =~ /.*::(\w{1,4})/i
-
- q.group 2, "[#{$1.downcase}: ", ']' do
- q.seplist @parts do |part|
- q.pp part
- end
- end
- end
-
- ##
- # Appends +texts+ onto this Paragraph
-
- def push *texts
- self.parts.concat texts
- end
-
- ##
- # The raw text
-
- def text
- @parts.join ' '
- end
-
-end
diff --git a/lib/rdoc/markup/regexp_handling.rb b/lib/rdoc/markup/regexp_handling.rb
deleted file mode 100644
index c471fe73c7..0000000000
--- a/lib/rdoc/markup/regexp_handling.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-##
-# Hold details of a regexp handling sequence
-
-class RDoc::Markup::RegexpHandling
-
- ##
- # Regexp handling type
-
- attr_reader :type
-
- ##
- # Regexp handling text
-
- attr_accessor :text
-
- ##
- # Creates a new regexp handling sequence of +type+ with +text+
-
- def initialize(type, text)
- @type, @text = type, text
- end
-
- ##
- # Regexp handlings are equal when the have the same text and type
-
- def ==(o)
- self.text == o.text && self.type == o.type
- end
-
- def inspect # :nodoc:
- "#<RDoc::Markup::RegexpHandling:0x%x @type=%p, @text=%p>" % [
- object_id, @type, text.dump]
- end
-
- def to_s # :nodoc:
- "RegexpHandling: type=#{type} text=#{text.dump}"
- end
-
-end
diff --git a/lib/rdoc/markup/rule.rb b/lib/rdoc/markup/rule.rb
deleted file mode 100644
index 448148d6d1..0000000000
--- a/lib/rdoc/markup/rule.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-##
-# A horizontal rule with a weight
-
-class RDoc::Markup::Rule < Struct.new :weight
-
- ##
- # Calls #accept_rule on +visitor+
-
- def accept visitor
- visitor.accept_rule self
- end
-
- def pretty_print q # :nodoc:
- q.group 2, '[rule:', ']' do
- q.pp weight
- end
- end
-
-end
diff --git a/lib/rdoc/markup/table.rb b/lib/rdoc/markup/table.rb
deleted file mode 100644
index 27a20f073a..0000000000
--- a/lib/rdoc/markup/table.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-# frozen_string_literal: true
-##
-# A section of table
-
-class RDoc::Markup::Table
- # headers of each column
- attr_accessor :header
-
- # alignments of each column
- attr_accessor :align
-
- # body texts of each column
- attr_accessor :body
-
- # Creates new instance
- def initialize header, align, body
- @header, @align, @body = header, align, body
- end
-
- # :stopdoc:
- 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
- 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/lib/rdoc/markup/to_ansi.rb b/lib/rdoc/markup/to_ansi.rb
deleted file mode 100644
index c3eacab21a..0000000000
--- a/lib/rdoc/markup/to_ansi.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-# frozen_string_literal: true
-##
-# Outputs RDoc markup with vibrant ANSI color!
-
-class RDoc::Markup::ToAnsi < RDoc::Markup::ToRdoc
-
- ##
- # Creates a new ToAnsi visitor that is ready to output vibrant ANSI color!
-
- def initialize markup = nil
- super
-
- @headings.clear
- @headings[1] = ["\e[1;32m", "\e[m"] # bold
- @headings[2] = ["\e[4;32m", "\e[m"] # underline
- @headings[3] = ["\e[32m", "\e[m"] # just green
- end
-
- ##
- # Maps attributes to ANSI sequences
-
- def init_tags
- add_tag :BOLD, "\e[1m", "\e[m"
- add_tag :TT, "\e[7m", "\e[m"
- add_tag :EM, "\e[4m", "\e[m"
- end
-
- ##
- # Overrides indent width to ensure output lines up correctly.
-
- def accept_list_item_end list_item
- width = case @list_type.last
- when :BULLET then
- 2
- when :NOTE, :LABEL then
- if @prefix then
- @res << @prefix.strip
- @prefix = nil
- end
-
- @res << "\n" unless res.length == 1
- 2
- else
- bullet = @list_index.last.to_s
- @list_index[-1] = @list_index.last.succ
- bullet.length + 2
- end
-
- @indent -= width
- end
-
- ##
- # Adds coloring to note and label list items
-
- def accept_list_item_start list_item
- bullet = case @list_type.last
- when :BULLET then
- '*'
- when :NOTE, :LABEL then
- labels = Array(list_item.label).map do |label|
- attributes(label).strip
- end.join "\n"
-
- labels << ":\n" unless labels.empty?
-
- labels
- else
- @list_index.last.to_s + '.'
- end
-
- case @list_type.last
- when :NOTE, :LABEL then
- @indent += 2
- @prefix = bullet + (' ' * @indent)
- else
- @prefix = (' ' * @indent) + bullet.ljust(bullet.length + 1)
-
- width = bullet.gsub(/\e\[[\d;]*m/, '').length + 1
-
- @indent += width
- end
- end
-
- ##
- # Starts accepting with a reset screen
-
- def start_accepting
- super
-
- @res = ["\e[0m"]
- end
-
-end
diff --git a/lib/rdoc/markup/to_bs.rb b/lib/rdoc/markup/to_bs.rb
deleted file mode 100644
index afd9d6e981..0000000000
--- a/lib/rdoc/markup/to_bs.rb
+++ /dev/null
@@ -1,102 +0,0 @@
-# frozen_string_literal: true
-##
-# Outputs RDoc markup with hot backspace action! You will probably need a
-# pager to use this output format.
-#
-# This formatter won't work on 1.8.6 because it lacks String#chars.
-
-class RDoc::Markup::ToBs < RDoc::Markup::ToRdoc
-
- ##
- # Returns a new ToBs that is ready for hot backspace action!
-
- def initialize markup = nil
- super
-
- @in_b = false
- @in_em = false
- end
-
- ##
- # Sets a flag that is picked up by #annotate to do the right thing in
- # #convert_string
-
- def init_tags
- add_tag :BOLD, '+b', '-b'
- add_tag :EM, '+_', '-_'
- add_tag :TT, '' , '' # we need in_tt information maintained
- end
-
- ##
- # Makes heading text bold.
-
- def accept_heading heading
- use_prefix or @res << ' ' * @indent
- @res << @headings[heading.level][0]
- @in_b = true
- @res << attributes(heading.text)
- @in_b = false
- @res << @headings[heading.level][1]
- @res << "\n"
- end
-
- ##
- # Prepares the visitor for consuming +list_item+
-
- def accept_list_item_start list_item
- type = @list_type.last
-
- case type
- when :NOTE, :LABEL then
- bullets = Array(list_item.label).map do |label|
- attributes(label).strip
- end.join "\n"
-
- bullets << ":\n" unless bullets.empty?
-
- @prefix = ' ' * @indent
- @indent += 2
- @prefix << bullets + (' ' * @indent)
- else
- bullet = type == :BULLET ? '*' : @list_index.last.to_s + '.'
- @prefix = (' ' * @indent) + bullet.ljust(bullet.length + 1)
- width = bullet.length + 1
- @indent += width
- end
- end
-
- ##
- # Turns on or off regexp handling for +convert_string+
-
- def annotate tag
- case tag
- when '+b' then @in_b = true
- when '-b' then @in_b = false
- when '+_' then @in_em = true
- when '-_' then @in_em = false
- end
- ''
- end
-
- ##
- # Calls convert_string on the result of convert_regexp_handling
-
- def convert_regexp_handling target
- convert_string super
- end
-
- ##
- # Adds bold or underline mixed with backspaces
-
- def convert_string string
- return string unless @in_b or @in_em
- chars = if @in_b then
- string.chars.map do |char| "#{char}\b#{char}" end
- elsif @in_em then
- string.chars.map do |char| "_\b#{char}" end
- end
-
- chars.join
- end
-
-end
diff --git a/lib/rdoc/markup/to_html.rb b/lib/rdoc/markup/to_html.rb
deleted file mode 100644
index 91cadf9d16..0000000000
--- a/lib/rdoc/markup/to_html.rb
+++ /dev/null
@@ -1,452 +0,0 @@
-# frozen_string_literal: true
-require 'cgi/util'
-
-##
-# Outputs RDoc markup as HTML.
-
-class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
-
- include RDoc::Text
-
- # :section: Utilities
-
- ##
- # Maps RDoc::Markup::Parser::LIST_TOKENS types to HTML tags
-
- LIST_TYPE_TO_HTML = {
- :BULLET => ['<ul>', '</ul>'],
- :LABEL => ['<dl class="rdoc-list label-list">', '</dl>'],
- :LALPHA => ['<ol style="list-style-type: lower-alpha">', '</ol>'],
- :NOTE => ['<dl class="rdoc-list note-list">', '</dl>'],
- :NUMBER => ['<ol>', '</ol>'],
- :UALPHA => ['<ol style="list-style-type: upper-alpha">', '</ol>'],
- }
-
- attr_reader :res # :nodoc:
- attr_reader :in_list_entry # :nodoc:
- attr_reader :list # :nodoc:
-
- ##
- # The RDoc::CodeObject HTML is being generated for. This is used to
- # generate namespaced URI fragments
-
- attr_accessor :code_object
-
- ##
- # Path to this document for relative links
-
- attr_accessor :from_path
-
- # :section:
-
- ##
- # Creates a new formatter that will output HTML
-
- def initialize options, markup = nil
- super
-
- @code_object = nil
- @from_path = ''
- @in_list_entry = nil
- @list = nil
- @th = nil
- @hard_break = "<br>\n"
-
- init_regexp_handlings
-
- init_tags
- end
-
- # :section: Regexp Handling
- #
- # These methods are used by regexp handling markup added by RDoc::Markup#add_regexp_handling.
-
- # :nodoc:
- URL_CHARACTERS_REGEXP_STR = /[A-Za-z0-9\-._~:\/\?#\[\]@!$&'\(\)*+,;%=]/.source
-
- ##
- # Adds regexp handlings.
-
- def init_regexp_handlings
- # external links
- @markup.add_regexp_handling(/(?:link:|https?:|mailto:|ftp:|irc:|www\.)#{URL_CHARACTERS_REGEXP_STR}+\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:/
- CGI.escapeHTML($')
- when /^rdoc-label:/
- text = $'
-
- text = case text
- when /\Alabel-/ then $'
- when /\Afootmark-/ then $'
- when /\Afoottext-/ then $'
- else text
- end
-
- gen_url CGI.escapeHTML(url), CGI.escapeHTML(text)
- when /^rdoc-image:/
- %[<img src=\"#{CGI.escapeHTML($')}\">]
- when /\Ardoc-[a-z]+:/
- CGI.escapeHTML($')
- end
- end
-
- ##
- # +target+ is a <code><br></code>
-
- def handle_regexp_HARD_BREAK target
- '<br>'
- end
-
- ##
- # +target+ is a potential link. The following schemes are handled:
- #
- # <tt>mailto:</tt>::
- # Inserted as-is.
- # <tt>http:</tt>::
- # Links are checked to see if they reference an image. If so, that image
- # gets inserted using an <tt><img></tt> tag. Otherwise a conventional
- # <tt><a href></tt> is used.
- # <tt>link:</tt>::
- # Reference to a local file relative to the output directory.
-
- def handle_regexp_HYPERLINK(target)
- url = CGI.escapeHTML(target.text)
-
- gen_url url, url
- end
-
- ##
- # +target+ is an rdoc-schemed link that will be converted into a hyperlink.
- #
- # For the +rdoc-ref+ scheme the named reference will be returned without
- # creating a link.
- #
- # For the +rdoc-label+ scheme the footnote and label prefixes are stripped
- # when creating a link. All other contents will be linked verbatim.
-
- def handle_regexp_RDOCLINK target
- handle_RDOCLINK target.text
- end
-
- ##
- # This +target+ is a link where the label is different from the URL
- # <tt>label[url]</tt> or <tt>{long label}[url]</tt>
-
- def handle_regexp_TIDYLINK(target)
- text = target.text
-
- return text unless
- text =~ /^\{(.*)\}\[(.*?)\]$/ or text =~ /^(\S+)\[(.*?)\]$/
-
- label = $1
- url = CGI.escapeHTML($2)
-
- if /^rdoc-image:/ =~ label
- label = handle_RDOCLINK(label)
- else
- label = CGI.escapeHTML(label)
- end
-
- gen_url url, label
- end
-
- # :section: Visitor
- #
- # These methods implement the HTML visitor.
-
- ##
- # Prepares the visitor for HTML generation
-
- def start_accepting
- @res = []
- @in_list_entry = []
- @list = []
- end
-
- ##
- # Returns the generated output
-
- def end_accepting
- @res.join
- end
-
- ##
- # Adds +block_quote+ to the output
-
- def accept_block_quote block_quote
- @res << "\n<blockquote>"
-
- block_quote.parts.each do |part|
- part.accept self
- end
-
- @res << "</blockquote>\n"
- end
-
- ##
- # Adds +paragraph+ to the output
-
- def accept_paragraph paragraph
- @res << "\n<p>"
- text = paragraph.text @hard_break
- text = text.gsub(/(#{SPACE_SEPARATED_LETTER_CLASS})?\K\r?\n(?=(?(1)(#{SPACE_SEPARATED_LETTER_CLASS})?))/o) {
- defined?($2) && ' '
- }
- @res << to_html(text)
- @res << "</p>\n"
- end
-
- ##
- # Adds +verbatim+ to the output
-
- def accept_verbatim verbatim
- text = verbatim.text.rstrip
-
- klass = nil
-
- content = if verbatim.ruby? or parseable? text then
- begin
- tokens = RDoc::Parser::RipperStateLex.parse text
- klass = ' class="ruby"'
-
- result = RDoc::TokenStream.to_html tokens
- result = result + "\n" unless "\n" == result[-1]
- result
- rescue
- CGI.escapeHTML text
- end
- else
- CGI.escapeHTML text
- end
-
- if @options.pipe then
- @res << "\n<pre><code>#{CGI.escapeHTML text}\n</code></pre>\n"
- else
- @res << "\n<pre#{klass}>#{content}</pre>\n"
- end
- end
-
- ##
- # Adds +rule+ to the output
-
- def accept_rule rule
- @res << "<hr>\n"
- end
-
- ##
- # Prepares the visitor for consuming +list+
-
- def accept_list_start(list)
- @list << list.type
- @res << html_list_name(list.type, true)
- @in_list_entry.push false
- end
-
- ##
- # Finishes consumption of +list+
-
- def accept_list_end(list)
- @list.pop
- if tag = @in_list_entry.pop
- @res << tag
- end
- @res << html_list_name(list.type, false) << "\n"
- end
-
- ##
- # Prepares the visitor for consuming +list_item+
-
- def accept_list_item_start(list_item)
- if tag = @in_list_entry.last
- @res << tag
- end
-
- @res << list_item_start(list_item, @list.last)
- end
-
- ##
- # Finishes consumption of +list_item+
-
- def accept_list_item_end(list_item)
- @in_list_entry[-1] = list_end_for(@list.last)
- end
-
- ##
- # Adds +blank_line+ to the output
-
- def accept_blank_line(blank_line)
- # @res << annotate("<p />") << "\n"
- end
-
- ##
- # Adds +heading+ to the output. The headings greater than 6 are trimmed to
- # level 6.
-
- def accept_heading heading
- level = [6, heading.level].min
-
- label = heading.label @code_object
-
- @res << if @options.output_decoration
- "\n<h#{level} id=\"#{label}\">"
- else
- "\n<h#{level}>"
- end
- @res << to_html(heading.text)
- unless @options.pipe then
- @res << "<span><a href=\"##{label}\">&para;</a>"
- @res << " <a href=\"#top\">&uarr;</a></span>"
- end
- @res << "</h#{level}>\n"
- end
-
- ##
- # Adds +raw+ to the output
-
- def accept_raw raw
- @res << raw.parts.join("\n")
- end
-
- ##
- # Adds +table+ to the output
-
- def accept_table header, body, aligns
- @res << "\n<table role=\"table\">\n<thead>\n<tr>\n"
- header.zip(aligns) do |text, align|
- @res << '<th'
- @res << ' align="' << align << '"' if align
- @res << '>' << to_html(text) << "</th>\n"
- end
- @res << "</tr>\n</thead>\n<tbody>\n"
- body.each do |row|
- @res << "<tr>\n"
- row.zip(aligns) do |text, align|
- @res << '<td'
- @res << ' align="' << align << '"' if align
- @res << '>' << to_html(text) << "</td>\n"
- end
- @res << "</tr>\n"
- end
- @res << "</tbody>\n</table>\n"
- end
-
- # :section: Utilities
-
- ##
- # CGI-escapes +text+
-
- def convert_string(text)
- CGI.escapeHTML text
- end
-
- ##
- # Generate a link to +url+ with content +text+. Handles the special cases
- # for img: and link: described under handle_regexp_HYPERLINK
-
- def gen_url url, text
- scheme, url, id = parse_url url
-
- if %w[http https link].include?(scheme) and
- url =~ /\.(gif|png|jpg|jpeg|bmp)$/ then
- "<img src=\"#{url}\" />"
- 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'
-
- link = "<a#{id} href=\"#{url}\">#{text}</a>"
-
- link = "<sup>#{link}</sup>" if /"foot/ =~ id
-
- link
- end
- end
-
- ##
- # Determines the HTML list element for +list_type+ and +open_tag+
-
- def html_list_name(list_type, open_tag)
- tags = LIST_TYPE_TO_HTML[list_type]
- raise RDoc::Error, "Invalid list type: #{list_type.inspect}" unless tags
- tags[open_tag ? 0 : 1]
- end
-
- ##
- # Maps attributes to HTML tags
-
- def init_tags
- add_tag :BOLD, "<strong>", "</strong>"
- add_tag :TT, "<code>", "</code>"
- add_tag :EM, "<em>", "</em>"
- end
-
- ##
- # Returns the HTML tag for +list_type+, possible using a label from
- # +list_item+
-
- def list_item_start(list_item, list_type)
- case list_type
- when :BULLET, :LALPHA, :NUMBER, :UALPHA then
- "<li>"
- when :LABEL, :NOTE then
- Array(list_item.label).map do |label|
- "<dt>#{to_html label}\n"
- end.join << "<dd>"
- else
- raise RDoc::Error, "Invalid list type: #{list_type.inspect}"
- end
- end
-
- ##
- # Returns the HTML end-tag for +list_type+
-
- def list_end_for(list_type)
- case list_type
- when :BULLET, :LALPHA, :NUMBER, :UALPHA then
- "</li>"
- when :LABEL, :NOTE then
- "</dd>"
- else
- raise RDoc::Error, "Invalid list type: #{list_type.inspect}"
- end
- end
-
- ##
- # Returns true if text is valid ruby syntax
-
- def parseable? text
- verbose, $VERBOSE = $VERBOSE, nil
- catch(:valid) do
- eval("BEGIN { throw :valid, true }\n#{text}")
- end
- rescue SyntaxError
- false
- ensure
- $VERBOSE = verbose
- end
-
- ##
- # Converts +item+ to HTML using RDoc::Text#to_html
-
- def to_html item
- super convert_flow @am.flow item
- end
-
-end
diff --git a/lib/rdoc/markup/to_html_crossref.rb b/lib/rdoc/markup/to_html_crossref.rb
deleted file mode 100644
index 9b5de62fd6..0000000000
--- a/lib/rdoc/markup/to_html_crossref.rb
+++ /dev/null
@@ -1,175 +0,0 @@
-# frozen_string_literal: true
-##
-# Subclass of the RDoc::Markup::ToHtml class that supports looking up method
-# names, classes, etc to create links. RDoc::CrossReference is used to
-# generate those links based on the current context.
-
-class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
-
- # :stopdoc:
- ALL_CROSSREF_REGEXP = RDoc::CrossReference::ALL_CROSSREF_REGEXP
- CLASS_REGEXP_STR = RDoc::CrossReference::CLASS_REGEXP_STR
- CROSSREF_REGEXP = RDoc::CrossReference::CROSSREF_REGEXP
- METHOD_REGEXP_STR = RDoc::CrossReference::METHOD_REGEXP_STR
- # :startdoc:
-
- ##
- # RDoc::CodeObject for generating references
-
- attr_accessor :context
-
- ##
- # Should we show '#' characters on method references?
-
- attr_accessor :show_hash
-
- ##
- # Creates a new crossref resolver that generates links relative to +context+
- # which lives at +from_path+ in the generated files. '#' characters on
- # references are removed unless +show_hash+ is true. Only method names
- # preceded by '#' or '::' are linked, unless +hyperlink_all+ is true.
-
- def initialize(options, from_path, context, markup = nil)
- raise ArgumentError, 'from_path cannot be nil' if from_path.nil?
-
- super options, markup
-
- @context = context
- @from_path = from_path
- @hyperlink_all = @options.hyperlink_all
- @show_hash = @options.show_hash
-
- @cross_reference = RDoc::CrossReference.new @context
- end
-
- # :nodoc:
- 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
-
- add_regexp_handling_TIDYLINK
- end
-
- ##
- # Creates a link to the reference +name+ if the name exists. If +text+ is
- # given it is used as the link text, otherwise +name+ is used.
-
- def cross_reference name, text = nil, code = true
- lookup = name
-
- name = name[1..-1] unless @show_hash if name[0, 1] == '#'
-
- if !(name.end_with?('+@', '-@')) and name =~ /(.*[^#:])?@/
- text ||= [CGI.unescape($'), (" at <code>#{$1}</code>" if $~.begin(1))].join("")
- code = false
- else
- text ||= name
- end
-
- link lookup, text, code
- end
-
- ##
- # We're invoked when any text matches the CROSSREF pattern. If we find the
- # corresponding reference, generate a link. If the name we're looking for
- # contains no punctuation, we look for it up the module/class chain. For
- # example, ToHtml is found, even without the <tt>RDoc::Markup::</tt> prefix,
- # because we look for it in module Markup first.
-
- def handle_regexp_CROSSREF(target)
- name = target.text
-
- return name if name =~ /@[\w-]+\.[\w-]/ # labels that look like emails
-
- unless @hyperlink_all then
- # This ensures that words entirely consisting of lowercase letters will
- # not have cross-references generated (to suppress lots of erroneous
- # cross-references to "new" in text, for instance)
- return name if name =~ /\A[a-z]*\z/
- end
-
- cross_reference name
- end
-
- ##
- # Handles <tt>rdoc-ref:</tt> scheme links and allows RDoc::Markup::ToHtml to
- # handle other schemes.
-
- def handle_regexp_HYPERLINK target
- return cross_reference $' if target.text =~ /\Ardoc-ref:/
-
- super
- end
-
- ##
- # +target+ is an rdoc-schemed link that will be converted into a hyperlink.
- # For the rdoc-ref scheme the cross-reference will be looked up and the
- # given name will be used.
- #
- # All other contents are handled by
- # {the superclass}[rdoc-ref:RDoc::Markup::ToHtml#handle_regexp_RDOCLINK]
-
- def handle_regexp_RDOCLINK target
- url = target.text
-
- case url
- when /\Ardoc-ref:/ then
- cross_reference $'
- else
- super
- end
- end
-
- ##
- # Generates links for <tt>rdoc-ref:</tt> scheme URLs and allows
- # RDoc::Markup::ToHtml to handle other schemes.
-
- def gen_url url, text
- return super unless url =~ /\Ardoc-ref:/
-
- name = $'
- cross_reference name, text, name == text
- end
-
- ##
- # Creates an HTML link to +name+ with the given +text+.
-
- def link name, text, code = true
- if !(name.end_with?('+@', '-@')) and name =~ /(.*[^#:])?@/
- name = $1
- label = $'
- end
-
- ref = @cross_reference.resolve name, text if name
-
- case ref
- when String then
- ref
- else
- path = ref ? ref.as_href(@from_path) : +""
-
- if code and RDoc::CodeObject === ref and !(RDoc::TopLevel === ref)
- text = "<code>#{CGI.escapeHTML text}</code>"
- end
-
- if label
- if path =~ /#/
- path << "-label-#{label}"
- elsif ref&.sections&.any? { |section| label == section.title }
- path << "##{label}"
- elsif ref.respond_to?(:aref)
- path << "##{ref.aref}-label-#{label}"
- else
- path << "#label-#{label}"
- end
- end
-
- "<a href=\"#{path}\">#{text}</a>"
- end
- end
-
-end
diff --git a/lib/rdoc/markup/to_html_snippet.rb b/lib/rdoc/markup/to_html_snippet.rb
deleted file mode 100644
index f471395a3a..0000000000
--- a/lib/rdoc/markup/to_html_snippet.rb
+++ /dev/null
@@ -1,287 +0,0 @@
-# frozen_string_literal: true
-##
-# Outputs RDoc markup as paragraphs with inline markup only.
-
-class RDoc::Markup::ToHtmlSnippet < RDoc::Markup::ToHtml
-
- ##
- # After this many characters the input will be cut off.
-
- attr_reader :character_limit
-
- ##
- # The number of characters seen so far.
-
- attr_reader :characters # :nodoc:
-
- ##
- # The attribute bitmask
-
- attr_reader :mask
-
- ##
- # After this many paragraphs the input will be cut off.
-
- attr_reader :paragraph_limit
-
- ##
- # Count of paragraphs found
-
- attr_reader :paragraphs
-
- ##
- # Creates a new ToHtmlSnippet formatter that will cut off the input on the
- # next word boundary after the given number of +characters+ or +paragraphs+
- # of text have been encountered.
-
- def initialize options, characters = 100, paragraphs = 3, markup = nil
- super options, markup
-
- @character_limit = characters
- @paragraph_limit = paragraphs
-
- @characters = 0
- @mask = 0
- @paragraphs = 0
-
- @markup.add_regexp_handling RDoc::CrossReference::CROSSREF_REGEXP, :CROSSREF
- end
-
- ##
- # Adds +heading+ to the output as a paragraph
-
- def accept_heading heading
- @res << "<p>#{to_html heading.text}\n"
-
- add_paragraph
- end
-
- ##
- # Raw sections are untrusted and ignored
-
- alias accept_raw ignore
-
- ##
- # Rules are ignored
-
- alias accept_rule ignore
-
- ##
- # Adds +paragraph+ to the output
-
- def accept_paragraph paragraph
- para = @in_list_entry.last || "<p>"
-
- text = paragraph.text @hard_break
-
- @res << "#{para}#{to_html text}\n"
-
- add_paragraph
- end
-
- ##
- # Finishes consumption of +list_item+
-
- def accept_list_item_end list_item
- end
-
- ##
- # Prepares the visitor for consuming +list_item+
-
- def accept_list_item_start list_item
- @res << list_item_start(list_item, @list.last)
- end
-
- ##
- # Prepares the visitor for consuming +list+
-
- def accept_list_start list
- @list << list.type
- @res << html_list_name(list.type, true)
- @in_list_entry.push ''
- end
-
- ##
- # Adds +verbatim+ to the output
-
- def accept_verbatim verbatim
- throw :done if @characters >= @character_limit
- input = verbatim.text.rstrip
-
- text = truncate input
- text << ' ...' unless text == input
-
- super RDoc::Markup::Verbatim.new text
-
- add_paragraph
- end
-
- ##
- # Prepares the visitor for HTML snippet generation
-
- def start_accepting
- super
-
- @characters = 0
- end
-
- ##
- # Removes escaping from the cross-references in +target+
-
- def handle_regexp_CROSSREF target
- target.text.sub(/\A\\/, '')
- end
-
- ##
- # +target+ is a <code><br></code>
-
- def handle_regexp_HARD_BREAK target
- @characters -= 4
- '<br>'
- end
-
- ##
- # Lists are paragraphs, but notes and labels have a separator
-
- def list_item_start list_item, list_type
- throw :done if @characters >= @character_limit
-
- case list_type
- when :BULLET, :LALPHA, :NUMBER, :UALPHA then
- "<p>"
- when :LABEL, :NOTE then
- labels = Array(list_item.label).map do |label|
- to_html label
- end.join ', '
-
- labels << " &mdash; " unless labels.empty?
-
- start = "<p>#{labels}"
- @characters += 1 # try to include the label
- start
- else
- raise RDoc::Error, "Invalid list type: #{list_type.inspect}"
- end
- end
-
- ##
- # Returns just the text of +link+, +url+ is only used to determine the link
- # type.
-
- def gen_url url, text
- if url =~ /^rdoc-label:([^:]*)(?::(.*))?/ then
- type = "link"
- elsif url =~ /([A-Za-z]+):(.*)/ then
- type = $1
- else
- type = "http"
- end
-
- if (type == "http" or type == "https" or type == "link") and
- url =~ /\.(gif|png|jpg|jpeg|bmp)$/ then
- ''
- else
- text.sub(%r%^#{type}:/*%, '')
- end
- end
-
- ##
- # In snippets, there are no lists
-
- def html_list_name list_type, open_tag
- ''
- end
-
- ##
- # Throws +:done+ when paragraph_limit paragraphs have been encountered
-
- def add_paragraph
- @paragraphs += 1
-
- throw :done if @paragraphs >= @paragraph_limit
- end
-
- ##
- # Marks up +content+
-
- def convert content
- catch :done do
- return super
- end
-
- end_accepting
- end
-
- ##
- # Converts flow items +flow+
-
- def convert_flow flow
- throw :done if @characters >= @character_limit
-
- res = []
- @mask = 0
-
- flow.each do |item|
- case item
- when RDoc::Markup::AttrChanger then
- off_tags res, item
- on_tags res, item
- when String then
- text = convert_string item
- res << truncate(text)
- when RDoc::Markup::RegexpHandling then
- text = convert_regexp_handling item
- res << truncate(text)
- else
- raise "Unknown flow element: #{item.inspect}"
- end
-
- if @characters >= @character_limit then
- off_tags res, RDoc::Markup::AttrChanger.new(0, @mask)
- break
- end
- end
-
- res << ' ...' if @characters >= @character_limit
-
- res.join
- end
-
- ##
- # Maintains a bitmask to allow HTML elements to be closed properly. See
- # RDoc::Markup::Formatter.
-
- def on_tags res, item
- @mask ^= item.turn_on
-
- super
- end
-
- ##
- # Maintains a bitmask to allow HTML elements to be closed properly. See
- # RDoc::Markup::Formatter.
-
- def off_tags res, item
- @mask ^= item.turn_off
-
- super
- end
-
- ##
- # Truncates +text+ at the end of the first word after the character_limit.
-
- def truncate text
- length = text.length
- characters = @characters
- @characters += length
-
- return text if @characters < @character_limit
-
- remaining = @character_limit - characters
-
- text =~ /\A(.{#{remaining},}?)(\s|$)/m # TODO word-break instead of \s?
-
- $1
- end
-
-end
diff --git a/lib/rdoc/markup/to_joined_paragraph.rb b/lib/rdoc/markup/to_joined_paragraph.rb
deleted file mode 100644
index 31cbe0853c..0000000000
--- a/lib/rdoc/markup/to_joined_paragraph.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-##
-# Joins the parts of an RDoc::Markup::Paragraph into a single String.
-#
-# This allows for easier maintenance and testing of Markdown support.
-#
-# This formatter only works on Paragraph instances. Attempting to process
-# other markup syntax items will not work.
-
-class RDoc::Markup::ToJoinedParagraph < RDoc::Markup::Formatter
-
- def initialize # :nodoc:
- super nil
- end
-
- def start_accepting # :nodoc:
- end
-
- def end_accepting # :nodoc:
- end
-
- ##
- # Converts the parts of +paragraph+ to a single entry.
-
- def accept_paragraph paragraph
- parts = paragraph.parts.chunk do |part|
- String === part
- end.flat_map do |string, chunk|
- string ? chunk.join.rstrip : chunk
- end
-
- paragraph.parts.replace parts
- end
-
- alias accept_block_quote ignore
- alias accept_heading ignore
- alias accept_list_end ignore
- alias accept_list_item_end ignore
- alias accept_list_item_start ignore
- alias accept_list_start ignore
- alias accept_raw ignore
- alias accept_rule ignore
- alias accept_verbatim ignore
- alias accept_table ignore
-
-end
diff --git a/lib/rdoc/markup/to_label.rb b/lib/rdoc/markup/to_label.rb
deleted file mode 100644
index cf808364e9..0000000000
--- a/lib/rdoc/markup/to_label.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-# frozen_string_literal: true
-require 'cgi/util'
-
-##
-# Creates HTML-safe labels suitable for use in id attributes. Tidylinks are
-# converted to their link part and cross-reference links have the suppression
-# marks removed (\\SomeClass is converted to SomeClass).
-
-class RDoc::Markup::ToLabel < RDoc::Markup::Formatter
-
- attr_reader :res # :nodoc:
-
- ##
- # Creates a new formatter that will output HTML-safe labels
-
- def initialize markup = nil
- super nil, markup
-
- @markup.add_regexp_handling RDoc::CrossReference::CROSSREF_REGEXP, :CROSSREF
- @markup.add_regexp_handling(/(((\{.*?\})|\b\S+?)\[\S+?\])/, :TIDYLINK)
-
- add_tag :BOLD, '', ''
- add_tag :TT, '', ''
- add_tag :EM, '', ''
-
- @res = []
- end
-
- ##
- # Converts +text+ to an HTML-safe label
-
- def convert text
- label = convert_flow @am.flow text
-
- CGI.escape(label).gsub('%', '-').sub(/^-/, '')
- end
-
- ##
- # Converts the CROSSREF +target+ to plain text, removing the suppression
- # marker, if any
-
- def handle_regexp_CROSSREF target
- text = target.text
-
- text.sub(/^\\/, '')
- end
-
- ##
- # Converts the TIDYLINK +target+ to just the text part
-
- def handle_regexp_TIDYLINK target
- text = target.text
-
- return text unless text =~ /\{(.*?)\}\[(.*?)\]/ or text =~ /(\S+)\[(.*?)\]/
-
- $1
- end
-
- alias accept_blank_line ignore
- alias accept_block_quote ignore
- alias accept_heading ignore
- alias accept_list_end ignore
- alias accept_list_item_end ignore
- alias accept_list_item_start ignore
- alias accept_list_start ignore
- alias accept_paragraph ignore
- alias accept_raw ignore
- alias accept_rule ignore
- alias accept_verbatim ignore
- alias end_accepting ignore
- alias handle_regexp_HARD_BREAK ignore
- alias start_accepting ignore
-
-end
diff --git a/lib/rdoc/markup/to_markdown.rb b/lib/rdoc/markup/to_markdown.rb
deleted file mode 100644
index b915fab60b..0000000000
--- a/lib/rdoc/markup/to_markdown.rb
+++ /dev/null
@@ -1,191 +0,0 @@
-# frozen_string_literal: true
-# :markup: markdown
-
-##
-# Outputs parsed markup as Markdown
-
-class RDoc::Markup::ToMarkdown < RDoc::Markup::ToRdoc
-
- ##
- # Creates a new formatter that will output Markdown format text
-
- def initialize markup = nil
- super
-
- @headings[1] = ['# ', '']
- @headings[2] = ['## ', '']
- @headings[3] = ['### ', '']
- @headings[4] = ['#### ', '']
- @headings[5] = ['##### ', '']
- @headings[6] = ['###### ', '']
-
- add_regexp_handling_RDOCLINK
- add_regexp_handling_TIDYLINK
-
- @hard_break = " \n"
- end
-
- ##
- # Maps attributes to HTML sequences
-
- def init_tags
- add_tag :BOLD, '**', '**'
- add_tag :EM, '*', '*'
- add_tag :TT, '`', '`'
- end
-
- ##
- # Adds a newline to the output
-
- def handle_regexp_HARD_BREAK target
- " \n"
- end
-
- ##
- # Finishes consumption of `list`
-
- def accept_list_end list
- super
- end
-
- ##
- # Finishes consumption of `list_item`
-
- def accept_list_item_end list_item
- width = case @list_type.last
- when :BULLET then
- 4
- when :NOTE, :LABEL then
- use_prefix
-
- @res << "\n"
-
- 4
- else
- @list_index[-1] = @list_index.last.succ
- 4
- end
-
- @indent -= width
- end
-
- ##
- # Prepares the visitor for consuming `list_item`
-
- def accept_list_item_start list_item
- type = @list_type.last
-
- case type
- when :NOTE, :LABEL then
- bullets = Array(list_item.label).map do |label|
- attributes(label).strip
- end.join "\n"
-
- bullets << "\n" unless bullets.empty?
-
- @prefix = ' ' * @indent
- @indent += 4
- @prefix << bullets << ":" << (' ' * (@indent - 1))
- else
- bullet = type == :BULLET ? '*' : @list_index.last.to_s + '.'
- @prefix = (' ' * @indent) + bullet.ljust(4)
-
- @indent += 4
- end
- end
-
- ##
- # Prepares the visitor for consuming `list`
-
- def accept_list_start list
- case list.type
- when :BULLET, :LABEL, :NOTE then
- @list_index << nil
- when :LALPHA, :NUMBER, :UALPHA then
- @list_index << 1
- else
- raise RDoc::Error, "invalid list type #{list.type}"
- end
-
- @list_width << 4
- @list_type << list.type
- end
-
- ##
- # Adds `rule` to the output
-
- def accept_rule rule
- use_prefix or @res << ' ' * @indent
- @res << '-' * 3
- @res << "\n"
- end
-
- ##
- # Outputs `verbatim` indented 4 columns
-
- def accept_verbatim verbatim
- indent = ' ' * (@indent + 4)
-
- verbatim.parts.each do |part|
- @res << indent unless part == "\n"
- @res << part
- end
-
- @res << "\n"
- end
-
- ##
- # Creates a Markdown-style URL from +url+ with +text+.
-
- def gen_url url, text
- scheme, url, = parse_url url
-
- "[#{text.sub(%r{^#{scheme}:/*}i, '')}](#{url})"
- end
-
- ##
- # Handles <tt>rdoc-</tt> type links for footnotes.
-
- def handle_rdoc_link url
- case url
- when /^rdoc-ref:/ then
- $'
- when /^rdoc-label:footmark-(\d+)/ then
- "[^#{$1}]:"
- when /^rdoc-label:foottext-(\d+)/ then
- "[^#{$1}]"
- when /^rdoc-label:label-/ then
- gen_url url, $'
- when /^rdoc-image:/ then
- "![](#{$'})"
- when /^rdoc-[a-z]+:/ then
- $'
- end
- end
-
- ##
- # Converts the RDoc markup tidylink into a Markdown.style link.
-
- def handle_regexp_TIDYLINK target
- text = target.text
-
- return text unless text =~ /\{(.*?)\}\[(.*?)\]/ or text =~ /(\S+)\[(.*?)\]/
-
- label = $1
- url = $2
-
- if url =~ /^rdoc-label:foot/ then
- handle_rdoc_link url
- else
- gen_url url, label
- end
- end
-
- ##
- # Converts the rdoc-...: links into a Markdown.style links.
-
- def handle_regexp_RDOCLINK target
- handle_rdoc_link target.text
- end
-
-end
diff --git a/lib/rdoc/markup/to_rdoc.rb b/lib/rdoc/markup/to_rdoc.rb
deleted file mode 100644
index 88234f5096..0000000000
--- a/lib/rdoc/markup/to_rdoc.rb
+++ /dev/null
@@ -1,352 +0,0 @@
-# frozen_string_literal: true
-##
-# Outputs RDoc markup as RDoc markup! (mostly)
-
-class RDoc::Markup::ToRdoc < RDoc::Markup::Formatter
-
- ##
- # Current indent amount for output in characters
-
- attr_accessor :indent
-
- ##
- # Output width in characters
-
- attr_accessor :width
-
- ##
- # Stack of current list indexes for alphabetic and numeric lists
-
- attr_reader :list_index
-
- ##
- # Stack of list types
-
- attr_reader :list_type
-
- ##
- # Stack of list widths for indentation
-
- attr_reader :list_width
-
- ##
- # Prefix for the next list item. See #use_prefix
-
- attr_reader :prefix
-
- ##
- # Output accumulator
-
- attr_reader :res
-
- ##
- # Creates a new formatter that will output (mostly) \RDoc markup
-
- def initialize markup = nil
- super nil, markup
-
- @markup.add_regexp_handling(/\\\S/, :SUPPRESSED_CROSSREF)
- @width = 78
- init_tags
-
- @headings = {}
- @headings.default = []
-
- @headings[1] = ['= ', '']
- @headings[2] = ['== ', '']
- @headings[3] = ['=== ', '']
- @headings[4] = ['==== ', '']
- @headings[5] = ['===== ', '']
- @headings[6] = ['====== ', '']
-
- @hard_break = "\n"
- end
-
- ##
- # Maps attributes to HTML sequences
-
- def init_tags
- add_tag :BOLD, "<b>", "</b>"
- add_tag :TT, "<tt>", "</tt>"
- add_tag :EM, "<em>", "</em>"
- end
-
- ##
- # Adds +blank_line+ to the output
-
- def accept_blank_line blank_line
- @res << "\n"
- end
-
- ##
- # Adds +paragraph+ to the output
-
- def accept_block_quote block_quote
- @indent += 2
-
- block_quote.parts.each do |part|
- @prefix = '> '
-
- part.accept self
- end
-
- @indent -= 2
- end
-
- ##
- # Adds +heading+ to the output
-
- def accept_heading heading
- use_prefix or @res << ' ' * @indent
- @res << @headings[heading.level][0]
- @res << attributes(heading.text)
- @res << @headings[heading.level][1]
- @res << "\n"
- end
-
- ##
- # Finishes consumption of +list+
-
- def accept_list_end list
- @list_index.pop
- @list_type.pop
- @list_width.pop
- end
-
- ##
- # Finishes consumption of +list_item+
-
- def accept_list_item_end list_item
- width = case @list_type.last
- when :BULLET then
- 2
- when :NOTE, :LABEL then
- if @prefix then
- @res << @prefix.strip
- @prefix = nil
- end
-
- @res << "\n"
- 2
- else
- bullet = @list_index.last.to_s
- @list_index[-1] = @list_index.last.succ
- bullet.length + 2
- end
-
- @indent -= width
- end
-
- ##
- # Prepares the visitor for consuming +list_item+
-
- def accept_list_item_start list_item
- type = @list_type.last
-
- case type
- when :NOTE, :LABEL then
- stripped_labels = Array(list_item.label).map do |label|
- attributes(label).strip
- end
-
- bullets = case type
- when :NOTE
- stripped_labels.map { |b| "#{b}::" }
- when :LABEL
- stripped_labels.map { |b| "[#{b}]" }
- end
-
- bullets = bullets.join("\n")
- bullets << "\n" unless stripped_labels.empty?
-
- @prefix = ' ' * @indent
- @indent += 2
- @prefix << bullets + (' ' * @indent)
- else
- bullet = type == :BULLET ? '*' : @list_index.last.to_s + '.'
- @prefix = (' ' * @indent) + bullet.ljust(bullet.length + 1)
- width = bullet.length + 1
- @indent += width
- end
- end
-
- ##
- # Prepares the visitor for consuming +list+
-
- def accept_list_start list
- case list.type
- when :BULLET then
- @list_index << nil
- @list_width << 1
- when :LABEL, :NOTE then
- @list_index << nil
- @list_width << 2
- when :LALPHA then
- @list_index << 'a'
- @list_width << list.items.length.to_s.length
- when :NUMBER then
- @list_index << 1
- @list_width << list.items.length.to_s.length
- when :UALPHA then
- @list_index << 'A'
- @list_width << list.items.length.to_s.length
- else
- raise RDoc::Error, "invalid list type #{list.type}"
- end
-
- @list_type << list.type
- end
-
- ##
- # Adds +paragraph+ to the output
-
- def accept_paragraph paragraph
- text = paragraph.text @hard_break
- wrap attributes text
- end
-
- ##
- # Adds +paragraph+ to the output
-
- def accept_indented_paragraph paragraph
- @indent += paragraph.indent
- text = paragraph.text @hard_break
- wrap attributes text
- @indent -= paragraph.indent
- end
-
- ##
- # Adds +raw+ to the output
-
- def accept_raw raw
- @res << raw.parts.join("\n")
- end
-
- ##
- # Adds +rule+ to the output
-
- def accept_rule rule
- use_prefix or @res << ' ' * @indent
- @res << '-' * (@width - @indent)
- @res << "\n"
- end
-
- ##
- # Outputs +verbatim+ indented 2 columns
-
- def accept_verbatim verbatim
- indent = ' ' * (@indent + 2)
-
- verbatim.parts.each do |part|
- @res << indent unless part == "\n"
- @res << part
- end
-
- @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
-
- def attributes text
- flow = @am.flow text.dup
- convert_flow flow
- end
-
- ##
- # Returns the generated output
-
- def end_accepting
- @res.join
- end
-
- ##
- # Removes preceding \\ from the suppressed crossref +target+
-
- def handle_regexp_SUPPRESSED_CROSSREF target
- text = target.text
- text = text.sub('\\', '') unless in_tt?
- text
- end
-
- ##
- # Adds a newline to the output
-
- def handle_regexp_HARD_BREAK target
- "\n"
- end
-
- ##
- # Prepares the visitor for text generation
-
- def start_accepting
- @res = [""]
- @indent = 0
- @prefix = nil
-
- @list_index = []
- @list_type = []
- @list_width = []
- end
-
- ##
- # Adds the stored #prefix to the output and clears it. Lists generate a
- # prefix for later consumption.
-
- def use_prefix
- prefix, @prefix = @prefix, nil
- @res << prefix if prefix
-
- prefix
- end
-
- ##
- # Wraps +text+ to #width
-
- def wrap text
- return unless text && !text.empty?
-
- text_len = @width - @indent
-
- text_len = 20 if text_len < 20
-
- next_prefix = ' ' * @indent
-
- prefix = @prefix || next_prefix
- @prefix = nil
-
- text.scan(/\G(?:([^ \n]{#{text_len}})(?=[^ \n])|(.{1,#{text_len}})(?:[ \n]|\z))/) do
- @res << prefix << ($1 || $2) << "\n"
- prefix = next_prefix
- end
- end
-
-end
diff --git a/lib/rdoc/markup/to_table_of_contents.rb b/lib/rdoc/markup/to_table_of_contents.rb
deleted file mode 100644
index e5b8225ba3..0000000000
--- a/lib/rdoc/markup/to_table_of_contents.rb
+++ /dev/null
@@ -1,88 +0,0 @@
-# frozen_string_literal: true
-##
-# Extracts just the RDoc::Markup::Heading elements from a
-# RDoc::Markup::Document to help build a table of contents
-
-class RDoc::Markup::ToTableOfContents < RDoc::Markup::Formatter
-
- @to_toc = nil
-
- ##
- # Singleton for table-of-contents generation
-
- def self.to_toc
- @to_toc ||= new
- end
-
- ##
- # Output accumulator
-
- attr_reader :res
-
- ##
- # Omits headings with a level less than the given level.
-
- attr_accessor :omit_headings_below
-
- def initialize # :nodoc:
- super nil
-
- @omit_headings_below = nil
- end
-
- ##
- # Adds +document+ to the output, using its heading cutoff if present
-
- def accept_document document
- @omit_headings_below = document.omit_headings_below
-
- super
- end
-
- ##
- # Adds +heading+ to the table of contents
-
- def accept_heading heading
- @res << heading unless suppressed? heading
- end
-
- ##
- # Returns the table of contents
-
- def end_accepting
- @res
- end
-
- ##
- # Prepares the visitor for text generation
-
- def start_accepting
- @omit_headings_below = nil
- @res = []
- end
-
- ##
- # Returns true if +heading+ is below the display threshold
-
- def suppressed? heading
- return false unless @omit_headings_below
-
- heading.level > @omit_headings_below
- end
-
- # :stopdoc:
- alias accept_block_quote ignore
- alias accept_raw ignore
- alias accept_rule ignore
- alias accept_blank_line ignore
- alias accept_paragraph ignore
- alias accept_verbatim ignore
- alias accept_list_end ignore
- alias accept_list_item_start ignore
- 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/lib/rdoc/markup/to_test.rb b/lib/rdoc/markup/to_test.rb
deleted file mode 100644
index 30113da561..0000000000
--- a/lib/rdoc/markup/to_test.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-# frozen_string_literal: true
-##
-# This Markup outputter is used for testing purposes.
-
-class RDoc::Markup::ToTest < RDoc::Markup::Formatter
-
- # :stopdoc:
-
- ##
- # :section: Visitor
-
- def start_accepting
- @res = []
- @list = []
- end
-
- def end_accepting
- @res
- end
-
- def accept_paragraph(paragraph)
- @res << convert_flow(@am.flow(paragraph.text))
- end
-
- def accept_raw raw
- @res << raw.parts.join
- end
-
- def accept_verbatim(verbatim)
- @res << verbatim.text.gsub(/^(\S)/, ' \1')
- end
-
- def accept_list_start(list)
- @list << case list.type
- when :BULLET then
- '*'
- when :NUMBER then
- '1'
- else
- list.type
- end
- end
-
- def accept_list_end(list)
- @list.pop
- end
-
- def accept_list_item_start(list_item)
- @res << "#{' ' * (@list.size - 1)}#{@list.last}: "
- end
-
- def accept_list_item_end(list_item)
- end
-
- def accept_blank_line(blank_line)
- @res << "\n"
- end
-
- def accept_heading(heading)
- @res << "#{'=' * heading.level} #{heading.text}"
- end
-
- def accept_rule(rule)
- @res << '-' * rule.weight
- end
-
- # :startdoc:
-
-end
diff --git a/lib/rdoc/markup/to_tt_only.rb b/lib/rdoc/markup/to_tt_only.rb
deleted file mode 100644
index 9ac14ed235..0000000000
--- a/lib/rdoc/markup/to_tt_only.rb
+++ /dev/null
@@ -1,120 +0,0 @@
-# frozen_string_literal: true
-##
-# Extracts sections of text enclosed in plus, tt or code. Used to discover
-# undocumented parameters.
-
-class RDoc::Markup::ToTtOnly < RDoc::Markup::Formatter
-
- ##
- # Stack of list types
-
- attr_reader :list_type
-
- ##
- # Output accumulator
-
- attr_reader :res
-
- ##
- # Creates a new tt-only formatter.
-
- def initialize markup = nil
- super nil, markup
-
- add_tag :TT, nil, nil
- end
-
- ##
- # Adds tts from +block_quote+ to the output
-
- def accept_block_quote block_quote
- tt_sections block_quote.text
- end
-
- ##
- # Pops the list type for +list+ from #list_type
-
- def accept_list_end list
- @list_type.pop
- end
-
- ##
- # Pushes the list type for +list+ onto #list_type
-
- def accept_list_start list
- @list_type << list.type
- end
-
- ##
- # Prepares the visitor for consuming +list_item+
-
- def accept_list_item_start list_item
- case @list_type.last
- when :NOTE, :LABEL then
- Array(list_item.label).map do |label|
- tt_sections label
- end.flatten
- end
- end
-
- ##
- # Adds +paragraph+ to the output
-
- def accept_paragraph paragraph
- tt_sections(paragraph.text)
- end
-
- ##
- # Does nothing to +markup_item+ because it doesn't have any user-built
- # content
-
- def do_nothing markup_item
- end
-
- alias accept_blank_line do_nothing # :nodoc:
- alias accept_heading do_nothing # :nodoc:
- alias accept_list_item_end do_nothing # :nodoc:
- alias accept_raw do_nothing # :nodoc:
- alias accept_rule do_nothing # :nodoc:
- alias accept_verbatim do_nothing # :nodoc:
-
- ##
- # Extracts tt sections from +text+
-
- def tt_sections text
- flow = @am.flow text.dup
-
- flow.each do |item|
- case item
- when String then
- @res << item if in_tt?
- when RDoc::Markup::AttrChanger then
- off_tags res, item
- on_tags res, item
- when RDoc::Markup::RegexpHandling then
- @res << convert_regexp_handling(item) if in_tt? # TODO can this happen?
- else
- raise "Unknown flow element: #{item.inspect}"
- end
- end
-
- res
- end
-
- ##
- # Returns an Array of items that were wrapped in plus, tt or code.
-
- def end_accepting
- @res.compact
- end
-
- ##
- # Prepares the visitor for gathering tt sections
-
- def start_accepting
- @res = []
-
- @list_type = []
- end
-
-end
diff --git a/lib/rdoc/markup/verbatim.rb b/lib/rdoc/markup/verbatim.rb
deleted file mode 100644
index f51c2cfa14..0000000000
--- a/lib/rdoc/markup/verbatim.rb
+++ /dev/null
@@ -1,83 +0,0 @@
-# frozen_string_literal: true
-##
-# A section of verbatim text
-
-class RDoc::Markup::Verbatim < RDoc::Markup::Raw
-
- ##
- # Format of this verbatim section
-
- attr_accessor :format
-
- def initialize *parts # :nodoc:
- super
-
- @format = nil
- end
-
- def == other # :nodoc:
- super and @format == other.format
- end
-
- ##
- # Calls #accept_verbatim on +visitor+
-
- def accept visitor
- visitor.accept_verbatim self
- end
-
- ##
- # Collapses 3+ newlines into two newlines
-
- def normalize
- parts = []
-
- newlines = 0
-
- @parts.each do |part|
- case part
- when /^\s*\n/ then
- newlines += 1
- parts << part if newlines == 1
- else
- newlines = 0
- parts << part
- end
- end
-
- parts.pop if parts.last =~ /\A\r?\n\z/
-
- @parts = parts
- end
-
- def pretty_print q # :nodoc:
- self.class.name =~ /.*::(\w{1,4})/i
-
- q.group 2, "[#{$1.downcase}: ", ']' do
- if @format then
- q.text "format: #{@format}"
- q.breakable
- end
-
- q.seplist @parts do |part|
- q.pp part
- end
- end
- end
-
- ##
- # Is this verbatim section Ruby code?
-
- def ruby?
- @format ||= nil # TODO for older ri data, switch the tree to marshal_dump
- @format == :ruby
- end
-
- ##
- # The text of the section
-
- def text
- @parts.join
- end
-
-end
diff --git a/lib/rdoc/meta_method.rb b/lib/rdoc/meta_method.rb
deleted file mode 100644
index 8c95a0f78c..0000000000
--- a/lib/rdoc/meta_method.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# frozen_string_literal: true
-##
-# MetaMethod represents a meta-programmed method
-
-class RDoc::MetaMethod < RDoc::AnyMethod
-end
diff --git a/lib/rdoc/method_attr.rb b/lib/rdoc/method_attr.rb
deleted file mode 100644
index 61ddb32f46..0000000000
--- a/lib/rdoc/method_attr.rb
+++ /dev/null
@@ -1,418 +0,0 @@
-# frozen_string_literal: true
-##
-# Abstract class representing either a method or an attribute.
-
-class RDoc::MethodAttr < RDoc::CodeObject
-
- include Comparable
-
- ##
- # Name of this method/attribute.
-
- attr_accessor :name
-
- ##
- # public, protected, private
-
- attr_accessor :visibility
-
- ##
- # Is this a singleton method/attribute?
-
- attr_accessor :singleton
-
- ##
- # Source file token stream
-
- attr_reader :text
-
- ##
- # Array of other names for this method/attribute
-
- attr_reader :aliases
-
- ##
- # The method/attribute we're aliasing
-
- attr_accessor :is_alias_for
-
- #--
- # The attributes below are for AnyMethod only.
- # They are left here for the time being to
- # allow ri to operate.
- # TODO modify ri to avoid calling these on attributes.
- #++
-
- ##
- # Parameters yielded by the called block
-
- attr_reader :block_params
-
- ##
- # Parameters for this method
-
- attr_accessor :params
-
- ##
- # Different ways to call this method
-
- attr_accessor :call_seq
-
- ##
- # The call_seq or the param_seq with method name, if there is no call_seq.
-
- attr_reader :arglists
-
- ##
- # Pretty parameter list for this method
-
- attr_reader :param_seq
-
-
- ##
- # Creates a new MethodAttr from token stream +text+ and method or attribute
- # name +name+.
- #
- # Usually this is called by super from a subclass.
-
- def initialize text, name
- super()
-
- @text = text
- @name = name
-
- @aliases = []
- @is_alias_for = nil
- @parent_name = nil
- @singleton = nil
- @visibility = :public
- @see = false
-
- @arglists = nil
- @block_params = nil
- @call_seq = nil
- @param_seq = nil
- @params = nil
- end
-
- ##
- # Resets cached data for the object so it can be rebuilt by accessor methods
-
- def initialize_copy other # :nodoc:
- @full_name = nil
- end
-
- def initialize_visibility # :nodoc:
- super
- @see = nil
- end
-
- ##
- # Order by #singleton then #name
-
- def <=>(other)
- return unless other.respond_to?(:singleton) &&
- other.respond_to?(:name)
-
- [ @singleton ? 0 : 1, name] <=>
- [other.singleton ? 0 : 1, other.name]
- end
-
- def == other # :nodoc:
- equal?(other) or self.class == other.class and full_name == other.full_name
- end
-
- ##
- # A method/attribute is documented if any of the following is true:
- # - it was marked with :nodoc:;
- # - it has a comment;
- # - it is an alias for a documented method;
- # - it has a +#see+ method that is documented.
-
- def documented?
- super or
- (is_alias_for and is_alias_for.documented?) or
- (see and see.documented?)
- end
-
- ##
- # A method/attribute to look at,
- # in particular if this method/attribute has no documentation.
- #
- # It can be a method/attribute of the superclass or of an included module,
- # including the Kernel module, which is always appended to the included
- # modules.
- #
- # Returns +nil+ if there is no such method/attribute.
- # The +#is_alias_for+ method/attribute, if any, is not included.
- #
- # Templates may generate a "see also ..." if this method/attribute
- # has documentation, and "see ..." if it does not.
-
- def see
- @see = find_see if @see == false
- @see
- end
-
- ##
- # Sets the store for this class or module and its contained code objects.
-
- def store= store
- super
-
- @file = @store.add_file @file.full_name if @file
- end
-
- def find_see # :nodoc:
- return nil if singleton || is_alias_for
-
- # look for the method
- other = find_method_or_attribute name
- return other if other
-
- # if it is a setter, look for a getter
- return nil unless name =~ /[a-z_]=$/i # avoid == or ===
- return find_method_or_attribute name[0..-2]
- end
-
- def find_method_or_attribute name # :nodoc:
- return nil unless parent.respond_to? :ancestors
-
- searched = parent.ancestors
- kernel = @store.modules_hash['Kernel']
-
- searched << kernel if kernel &&
- parent != kernel && !searched.include?(kernel)
-
- searched.each do |ancestor|
- next if String === ancestor
- next if parent == ancestor
-
- other = ancestor.find_method_named('#' + name) ||
- ancestor.find_attribute_named(name)
-
- return other if other
- end
-
- nil
- end
-
- ##
- # Abstract method. Contexts in their building phase call this
- # to register a new alias for this known method/attribute.
- #
- # - creates a new AnyMethod/Attribute named <tt>an_alias.new_name</tt>;
- # - adds +self+ as an alias for the new method or attribute
- # - adds the method or attribute to #aliases
- # - adds the method or attribute to +context+.
-
- def add_alias(an_alias, context)
- raise NotImplementedError
- end
-
- ##
- # HTML fragment reference for this method
-
- def aref
- type = singleton ? 'c' : 'i'
- # % characters are not allowed in html names => dash instead
- "#{aref_prefix}-#{type}-#{html_name}"
- end
-
- ##
- # Prefix for +aref+, defined by subclasses.
-
- def aref_prefix
- raise NotImplementedError
- end
-
- ##
- # Attempts to sanitize the content passed by the Ruby parser:
- # remove outer parentheses, etc.
-
- def block_params=(value)
- # 'yield.to_s' or 'assert yield, msg'
- return @block_params = '' if value =~ /^[\.,]/
-
- # remove trailing 'if/unless ...'
- return @block_params = '' if value =~ /^(if|unless)\s/
-
- value = $1.strip if value =~ /^(.+)\s(if|unless)\s/
-
- # outer parentheses
- value = $1 if value =~ /^\s*\((.*)\)\s*$/
- value = value.strip
-
- # proc/lambda
- return @block_params = $1 if value =~ /^(proc|lambda)(\s*\{|\sdo)/
-
- # surrounding +...+ or [...]
- value = $1.strip if value =~ /^\+(.*)\+$/
- value = $1.strip if value =~ /^\[(.*)\]$/
-
- return @block_params = '' if value.empty?
-
- # global variable
- return @block_params = 'str' if value =~ /^\$[&0-9]$/
-
- # wipe out array/hash indices
- value.gsub!(/(\w)\[[^\[]+\]/, '\1')
-
- # remove @ from class/instance variables
- value.gsub!(/@@?([a-z0-9_]+)/, '\1')
-
- # method calls => method name
- value.gsub!(/([A-Z:a-z0-9_]+)\.([a-z0-9_]+)(\s*\(\s*[a-z0-9_.,\s]*\s*\)\s*)?/) do
- case $2
- when 'to_s' then $1
- when 'const_get' then 'const'
- when 'new' then
- $1.split('::').last. # ClassName => class_name
- gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
- gsub(/([a-z\d])([A-Z])/,'\1_\2').
- downcase
- else
- $2
- end
- end
-
- # class prefixes
- value.gsub!(/[A-Za-z0-9_:]+::/, '')
-
- # simple expressions
- value = $1 if value =~ /^([a-z0-9_]+)\s*[-*+\/]/
-
- @block_params = value.strip
- end
-
- ##
- # HTML id-friendly method/attribute name
-
- def html_name
- require 'cgi/util'
-
- CGI.escape(@name.gsub('-', '-2D')).gsub('%','-').sub(/^-/, '')
- end
-
- ##
- # Full method/attribute name including namespace
-
- def full_name
- @full_name ||= "#{parent_name}#{pretty_name}"
- end
-
- def inspect # :nodoc:
- alias_for = @is_alias_for ? " (alias for #{@is_alias_for.name})" : nil
- visibility = self.visibility
- visibility = "forced #{visibility}" if force_documentation
- "#<%s:0x%x %s (%s)%s>" % [
- self.class, object_id,
- full_name,
- visibility,
- alias_for,
- ]
- end
-
- ##
- # '::' for a class method/attribute, '#' for an instance method.
-
- def name_prefix
- @singleton ? '::' : '#'
- end
-
- ##
- # Name for output to HTML. For class methods the full name with a "." is
- # used like +SomeClass.method_name+. For instance methods the class name is
- # used if +context+ does not match the parent.
- #
- # This is to help prevent people from using :: to call class methods.
-
- def output_name context
- return "#{name_prefix}#{@name}" if context == parent
-
- "#{parent_name}#{@singleton ? '.' : '#'}#{@name}"
- end
-
- ##
- # Method/attribute name with class/instance indicator
-
- def pretty_name
- "#{name_prefix}#{@name}"
- end
-
- ##
- # Type of method/attribute (class or instance)
-
- def type
- singleton ? 'class' : 'instance'
- end
-
- ##
- # Path to this method for use with HTML generator output.
-
- def path
- "#{@parent.path}##{aref}"
- end
-
- ##
- # Name of our parent with special handling for un-marshaled methods
-
- def parent_name
- @parent_name || super
- end
-
- def pretty_print q # :nodoc:
- alias_for =
- if @is_alias_for.respond_to? :name then
- "alias for #{@is_alias_for.name}"
- elsif Array === @is_alias_for then
- "alias for #{@is_alias_for.last}"
- end
-
- q.group 2, "[#{self.class.name} #{full_name} #{visibility}", "]" do
- if alias_for then
- q.breakable
- q.text alias_for
- end
-
- if text then
- q.breakable
- q.text "text:"
- q.breakable
- q.pp @text
- end
-
- unless comment.empty? then
- q.breakable
- q.text "comment:"
- q.breakable
- q.pp @comment
- end
- end
- end
-
- ##
- # Used by RDoc::Generator::JsonIndex to create a record for the search
- # engine.
-
- def search_record
- [
- @name,
- full_name,
- @name,
- @parent.full_name,
- path,
- params,
- snippet(@comment),
- ]
- end
-
- def to_s # :nodoc:
- if @is_alias_for
- "#{self.class.name}: #{full_name} -> #{is_alias_for}"
- else
- "#{self.class.name}: #{full_name}"
- end
- end
-
-end
diff --git a/lib/rdoc/mixin.rb b/lib/rdoc/mixin.rb
deleted file mode 100644
index fa8faefc15..0000000000
--- a/lib/rdoc/mixin.rb
+++ /dev/null
@@ -1,120 +0,0 @@
-# frozen_string_literal: true
-##
-# A Mixin adds features from a module into another context. RDoc::Include and
-# RDoc::Extend are both mixins.
-
-class RDoc::Mixin < RDoc::CodeObject
-
- ##
- # Name of included module
-
- attr_accessor :name
-
- ##
- # Creates a new Mixin for +name+ with +comment+
-
- def initialize(name, comment)
- super()
- @name = name
- self.comment = comment
- @module = nil # cache for module if found
- end
-
- ##
- # Mixins are sorted by name
-
- def <=> other
- return unless self.class === other
-
- name <=> other.name
- end
-
- def == other # :nodoc:
- self.class === other and @name == other.name
- end
-
- alias eql? == # :nodoc:
-
- ##
- # Full name based on #module
-
- def full_name
- m = self.module
- RDoc::ClassModule === m ? m.full_name : @name
- end
-
- def hash # :nodoc:
- [@name, self.module].hash
- end
-
- def inspect # :nodoc:
- "#<%s:0x%x %s.%s %s>" % [
- self.class,
- object_id,
- parent_name, self.class.name.downcase, @name,
- ]
- end
-
- ##
- # Attempts to locate the included module object. Returns the name if not
- # known.
- #
- # The scoping rules of Ruby to resolve the name of an included module are:
- # - first look into the children of the current context;
- # - if not found, look into the children of included modules,
- # in reverse inclusion order;
- # - if still not found, go up the hierarchy of names.
- #
- # This method has <code>O(n!)</code> behavior when the module calling
- # include is referencing nonexistent modules. Avoid calling #module until
- # after all the files are parsed. This behavior is due to ruby's constant
- # lookup behavior.
- #
- # As of the beginning of October, 2011, no gem includes nonexistent modules.
-
- def module
- return @module if @module
-
- # search the current context
- return @name unless parent
- full_name = parent.child_name(@name)
- @module = @store.modules_hash[full_name]
- return @module if @module
- return @name if @name =~ /^::/
-
- # search the includes before this one, in reverse order
- searched = parent.includes.take_while { |i| i != self }.reverse
- searched.each do |i|
- inc = i.module
- next if String === inc
- full_name = inc.child_name(@name)
- @module = @store.modules_hash[full_name]
- return @module if @module
- end
-
- # go up the hierarchy of names
- up = parent.parent
- while up
- full_name = up.child_name(@name)
- @module = @store.modules_hash[full_name]
- return @module if @module
- up = up.parent
- end
-
- @name
- end
-
- ##
- # Sets the store for this class or module and its contained code objects.
-
- def store= store
- super
-
- @file = @store.add_file @file.full_name if @file
- end
-
- def to_s # :nodoc:
- "#{self.class.name.downcase} #@name in: #{parent}"
- end
-
-end
diff --git a/lib/rdoc/normal_class.rb b/lib/rdoc/normal_class.rb
deleted file mode 100644
index aa340b5d15..0000000000
--- a/lib/rdoc/normal_class.rb
+++ /dev/null
@@ -1,92 +0,0 @@
-# frozen_string_literal: true
-##
-# A normal class, neither singleton nor anonymous
-
-class RDoc::NormalClass < RDoc::ClassModule
-
- ##
- # The ancestors of this class including modules. Unlike Module#ancestors,
- # this class is not included in the result. The result will contain both
- # RDoc::ClassModules and Strings.
-
- def ancestors
- if String === superclass then
- super << superclass
- elsif superclass then
- ancestors = super
- ancestors << superclass
- ancestors.concat superclass.ancestors
- else
- super
- end
- end
-
- def aref_prefix # :nodoc:
- 'class'
- end
-
- ##
- # The definition of this class, <tt>class MyClassName</tt>
-
- def definition
- "class #{full_name}"
- end
-
- def direct_ancestors
- superclass ? super + [superclass] : super
- end
-
- def inspect # :nodoc:
- superclass = @superclass ? " < #{@superclass}" : nil
- "<%s:0x%x class %s%s includes: %p extends: %p attributes: %p methods: %p aliases: %p>" % [
- self.class, object_id,
- full_name, superclass, @includes, @extends, @attributes, @method_list, @aliases
- ]
- end
-
- def to_s # :nodoc:
- display = "#{self.class.name} #{self.full_name}"
- if superclass
- display += ' < ' + (superclass.is_a?(String) ? superclass : superclass.full_name)
- end
- display += ' -> ' + is_alias_for.to_s if is_alias_for
- display
- end
-
- def pretty_print q # :nodoc:
- superclass = @superclass ? " < #{@superclass}" : nil
-
- q.group 2, "[class #{full_name}#{superclass}", "]" do
- q.breakable
- q.text "includes:"
- q.breakable
- q.seplist @includes do |inc| q.pp inc end
-
- q.breakable
- q.text "constants:"
- q.breakable
- q.seplist @constants do |const| q.pp const end
-
- q.breakable
- q.text "attributes:"
- q.breakable
- q.seplist @attributes do |attr| q.pp attr end
-
- q.breakable
- q.text "methods:"
- q.breakable
- q.seplist @method_list do |meth| q.pp meth end
-
- q.breakable
- q.text "aliases:"
- q.breakable
- q.seplist @aliases do |aliaz| q.pp aliaz end
-
- q.breakable
- q.text "comment:"
- q.breakable
- q.pp comment
- end
- end
-
-end
diff --git a/lib/rdoc/normal_module.rb b/lib/rdoc/normal_module.rb
deleted file mode 100644
index 498ec4dde2..0000000000
--- a/lib/rdoc/normal_module.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# frozen_string_literal: true
-##
-# A normal module, like NormalClass
-
-class RDoc::NormalModule < RDoc::ClassModule
-
- def aref_prefix # :nodoc:
- 'module'
- end
-
- def inspect # :nodoc:
- "#<%s:0x%x module %s includes: %p extends: %p attributes: %p methods: %p aliases: %p>" % [
- self.class, object_id,
- full_name, @includes, @extends, @attributes, @method_list, @aliases
- ]
- end
-
- ##
- # The definition of this module, <tt>module MyModuleName</tt>
-
- def definition
- "module #{full_name}"
- end
-
- ##
- # This is a module, returns true
-
- def module?
- true
- end
-
- def pretty_print q # :nodoc:
- q.group 2, "[module #{full_name}:", "]" do
- q.breakable
- q.text "includes:"
- q.breakable
- q.seplist @includes do |inc| q.pp inc end
- q.breakable
-
- q.breakable
- q.text "constants:"
- q.breakable
- q.seplist @constants do |const| q.pp const end
-
- q.text "attributes:"
- q.breakable
- q.seplist @attributes do |attr| q.pp attr end
- q.breakable
-
- q.text "methods:"
- q.breakable
- q.seplist @method_list do |meth| q.pp meth end
- q.breakable
-
- q.text "aliases:"
- q.breakable
- q.seplist @aliases do |aliaz| q.pp aliaz end
- q.breakable
-
- q.text "comment:"
- q.breakable
- q.pp comment
- end
- end
-
- ##
- # Modules don't have one, raises NoMethodError
-
- def superclass
- raise NoMethodError, "#{full_name} is a module"
- end
-
-end
diff --git a/lib/rdoc/options.rb b/lib/rdoc/options.rb
deleted file mode 100644
index 7518e6cc54..0000000000
--- a/lib/rdoc/options.rb
+++ /dev/null
@@ -1,1331 +0,0 @@
-# frozen_string_literal: true
-require 'optparse'
-require 'pathname'
-
-##
-# RDoc::Options handles the parsing and storage of options
-#
-# == Saved Options
-#
-# You can save some options like the markup format in the
-# <tt>.rdoc_options</tt> file in your gem. The easiest way to do this is:
-#
-# rdoc --markup tomdoc --write-options
-#
-# Which will automatically create the file and fill it with the options you
-# specified.
-#
-# The following options will not be saved since they interfere with the user's
-# preferences or with the normal operation of RDoc:
-#
-# * +--coverage-report+
-# * +--dry-run+
-# * +--encoding+
-# * +--force-update+
-# * +--format+
-# * +--pipe+
-# * +--quiet+
-# * +--template+
-# * +--verbose+
-#
-# == Custom Options
-#
-# Generators can hook into RDoc::Options to add generator-specific command
-# line options.
-#
-# When <tt>--format</tt> is encountered in ARGV, RDoc calls ::setup_options on
-# the generator class to add extra options to the option parser. Options for
-# custom generators must occur after <tt>--format</tt>. <tt>rdoc --help</tt>
-# will list options for all installed generators.
-#
-# Example:
-#
-# class RDoc::Generator::Spellcheck
-# RDoc::RDoc.add_generator self
-#
-# def self.setup_options rdoc_options
-# op = rdoc_options.option_parser
-#
-# op.on('--spell-dictionary DICTIONARY',
-# RDoc::Options::Path) do |dictionary|
-# rdoc_options.spell_dictionary = dictionary
-# end
-# end
-# end
-#
-# Of course, RDoc::Options does not respond to +spell_dictionary+ by default
-# so you will need to add it:
-#
-# class RDoc::Options
-#
-# ##
-# # The spell dictionary used by the spell-checking plugin.
-#
-# attr_accessor :spell_dictionary
-#
-# end
-#
-# == Option Validators
-#
-# OptionParser validators will validate and cast user input values. In
-# addition to the validators that ship with OptionParser (String, Integer,
-# Float, TrueClass, FalseClass, Array, Regexp, Date, Time, URI, etc.),
-# RDoc::Options adds Path, PathArray and Template.
-
-class RDoc::Options
-
- ##
- # The deprecated options.
-
- DEPRECATED = {
- '--accessor' => 'support discontinued',
- '--diagram' => 'support discontinued',
- '--help-output' => 'support discontinued',
- '--image-format' => 'was an option for --diagram',
- '--inline-source' => 'source code is now always inlined',
- '--merge' => 'ri now always merges class information',
- '--one-file' => 'support discontinued',
- '--op-name' => 'support discontinued',
- '--opname' => 'support discontinued',
- '--promiscuous' => 'files always only document their content',
- '--ri-system' => 'Ruby installers use other techniques',
- }
-
- ##
- # RDoc options ignored (or handled specially) by --write-options
-
- SPECIAL = %w[
- coverage_report
- dry_run
- encoding
- files
- force_output
- force_update
- generator
- generator_name
- generator_options
- generators
- locale
- op_dir
- page_dir
- option_parser
- pipe
- rdoc_include
- root
- static_path
- stylesheet_url
- template
- template_dir
- update_output_dir
- verbosity
- write_options
- ]
-
- ##
- # Option validator for OptionParser that matches a directory that exists on
- # the filesystem.
-
- Directory = Object.new
-
- ##
- # Option validator for OptionParser that matches a file or directory that
- # exists on the filesystem.
-
- Path = Object.new
-
- ##
- # Option validator for OptionParser that matches a comma-separated list of
- # files or directories that exist on the filesystem.
-
- PathArray = Object.new
-
- ##
- # Option validator for OptionParser that matches a template directory for an
- # installed generator that lives in
- # <tt>"rdoc/generator/template/#{template_name}"</tt>
-
- Template = Object.new
-
- ##
- # Character-set for HTML output. #encoding is preferred over #charset
-
- attr_accessor :charset
-
- ##
- # If true, RDoc will not write any files.
-
- attr_accessor :dry_run
-
- ##
- # The output encoding. All input files will be transcoded to this encoding.
- #
- # The default encoding is UTF-8. This is set via --encoding.
-
- attr_accessor :encoding
-
- ##
- # Files matching this pattern will be excluded
-
- attr_writer :exclude
-
- ##
- # The list of files to be processed
-
- attr_accessor :files
-
- ##
- # Create the output even if the output directory does not look
- # like an rdoc output directory
-
- attr_accessor :force_output
-
- ##
- # Scan newer sources than the flag file if true.
-
- attr_accessor :force_update
-
- ##
- # Formatter to mark up text with
-
- attr_accessor :formatter
-
- ##
- # Description of the output generator (set with the <tt>--format</tt> option)
-
- attr_accessor :generator
-
- ##
- # For #==
-
- attr_reader :generator_name # :nodoc:
-
- ##
- # Loaded generator options. Used to prevent --help from loading the same
- # options multiple times.
-
- attr_accessor :generator_options
-
- ##
- # Old rdoc behavior: hyperlink all words that match a method name,
- # even if not preceded by '#' or '::'
-
- attr_accessor :hyperlink_all
-
- ##
- # Include line numbers in the source code
-
- attr_accessor :line_numbers
-
- ##
- # The output locale.
-
- attr_accessor :locale
-
- ##
- # The directory where locale data live.
-
- attr_accessor :locale_dir
-
- ##
- # Name of the file, class or module to display in the initial index page (if
- # not specified the first file we encounter is used)
-
- attr_accessor :main_page
-
- ##
- # The default markup format. The default is 'rdoc'. 'markdown', 'tomdoc'
- # and 'rd' are also built-in.
-
- attr_accessor :markup
-
- ##
- # If true, only report on undocumented files
-
- attr_accessor :coverage_report
-
- ##
- # The name of the output directory
-
- attr_accessor :op_dir
-
- ##
- # The OptionParser for this instance
-
- attr_accessor :option_parser
-
- ##
- # Output heading decorations?
- attr_accessor :output_decoration
-
- ##
- # Directory where guides, FAQ, and other pages not associated with a class
- # live. You may leave this unset if these are at the root of your project.
-
- attr_accessor :page_dir
-
- ##
- # Is RDoc in pipe mode?
-
- attr_accessor :pipe
-
- ##
- # Array of directories to search for files to satisfy an :include:
-
- attr_accessor :rdoc_include
-
- ##
- # Root of the source documentation will be generated for. Set this when
- # building documentation outside the source directory. Defaults to the
- # current directory.
-
- attr_accessor :root
-
- ##
- # Include the '#' at the front of hyperlinked instance method names
-
- attr_accessor :show_hash
-
- ##
- # Directory to copy static files from
-
- attr_accessor :static_path
-
- ##
- # The number of columns in a tab
-
- attr_accessor :tab_width
-
- ##
- # Template to be used when generating output
-
- attr_accessor :template
-
- ##
- # Directory the template lives in
-
- attr_accessor :template_dir
-
- ##
- # Additional template stylesheets
-
- attr_accessor :template_stylesheets
-
- ##
- # Documentation title
-
- attr_accessor :title
-
- ##
- # Should RDoc update the timestamps in the output dir?
-
- attr_accessor :update_output_dir
-
- ##
- # Verbosity, zero means quiet
-
- attr_accessor :verbosity
-
- ##
- # URL of web cvs frontend
-
- attr_accessor :webcvs
-
- ##
- # Minimum visibility of a documented method. One of +:public+, +:protected+,
- # +:private+ or +:nodoc+.
- #
- # The +:nodoc+ visibility ignores all directives related to visibility. The
- # other visibilities may be overridden on a per-method basis with the :doc:
- # directive.
-
- attr_reader :visibility
-
- ##
- # Indicates if files of test suites should be skipped
- attr_accessor :skip_tests
-
- def initialize loaded_options = nil # :nodoc:
- init_ivars
- override loaded_options if loaded_options
- end
-
- def init_ivars # :nodoc:
- @dry_run = false
- @exclude = %w[
- ~\z \.orig\z \.rej\z \.bak\z
- \.gemspec\z
- ]
- @files = nil
- @force_output = false
- @force_update = true
- @generator = nil
- @generator_name = nil
- @generator_options = []
- @generators = RDoc::RDoc::GENERATORS
- @hyperlink_all = false
- @line_numbers = false
- @locale = nil
- @locale_name = nil
- @locale_dir = 'locale'
- @main_page = nil
- @markup = 'rdoc'
- @coverage_report = false
- @op_dir = nil
- @page_dir = nil
- @pipe = false
- @output_decoration = true
- @rdoc_include = []
- @root = Pathname(Dir.pwd)
- @show_hash = false
- @static_path = []
- @stylesheet_url = nil # TODO remove in RDoc 4
- @tab_width = 8
- @template = nil
- @template_dir = nil
- @template_stylesheets = []
- @title = nil
- @update_output_dir = true
- @verbosity = 1
- @visibility = :protected
- @webcvs = nil
- @write_options = false
- @encoding = Encoding::UTF_8
- @charset = @encoding.name
- @skip_tests = true
- end
-
- def init_with map # :nodoc:
- init_ivars
-
- encoding = map['encoding']
- @encoding = encoding ? Encoding.find(encoding) : encoding
-
- @charset = map['charset']
- @exclude = map['exclude']
- @generator_name = map['generator_name']
- @hyperlink_all = map['hyperlink_all']
- @line_numbers = map['line_numbers']
- @locale_name = map['locale_name']
- @locale_dir = map['locale_dir']
- @main_page = map['main_page']
- @markup = map['markup']
- @op_dir = map['op_dir']
- @show_hash = map['show_hash']
- @tab_width = map['tab_width']
- @template_dir = map['template_dir']
- @title = map['title']
- @visibility = map['visibility']
- @webcvs = map['webcvs']
-
- @rdoc_include = sanitize_path map['rdoc_include']
- @static_path = sanitize_path map['static_path']
- end
-
- 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')
- @page_dir = map['page_dir'] if map.has_key?('page_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
- @generator_name == other.generator_name and
- @hyperlink_all == other.hyperlink_all and
- @line_numbers == other.line_numbers and
- @locale == other.locale and
- @locale_dir == other.locale_dir and
- @main_page == other.main_page and
- @markup == other.markup and
- @op_dir == other.op_dir and
- @rdoc_include == other.rdoc_include and
- @show_hash == other.show_hash and
- @static_path == other.static_path and
- @tab_width == other.tab_width and
- @template == other.template and
- @title == other.title and
- @visibility == other.visibility and
- @webcvs == other.webcvs
- end
-
- ##
- # Check that the files on the command line exist
-
- def check_files
- @files.delete_if do |file|
- if File.exist? file then
- if File.readable? file then
- false
- else
- warn "file '#{file}' not readable"
-
- true
- end
- else
- warn "file '#{file}' not found"
-
- true
- end
- end
- end
-
- ##
- # Ensure only one generator is loaded
-
- def check_generator
- if @generator then
- raise OptionParser::InvalidOption,
- "generator already set to #{@generator_name}"
- end
- end
-
- ##
- # Set the title, but only if not already set. Used to set the title
- # from a source file, so that a title set from the command line
- # will have the priority.
-
- def default_title=(string)
- @title ||= string
- end
-
- ##
- # For dumping YAML
-
- def to_yaml(*options) # :nodoc:
- encoding = @encoding ? @encoding.name : nil
-
- yaml = {}
- yaml['encoding'] = encoding
- yaml['static_path'] = sanitize_path(@static_path)
- yaml['rdoc_include'] = sanitize_path(@rdoc_include)
- yaml['page_dir'] = (sanitize_path([@page_dir]).first if @page_dir)
-
- ivars = instance_variables.map { |ivar| ivar.to_s[1..-1] }
- ivars -= SPECIAL
-
- ivars.sort.each do |ivar|
- yaml[ivar] = instance_variable_get("@#{ivar}")
- end
- yaml.to_yaml
- end
-
- ##
- # Create a regexp for #exclude
-
- def exclude
- if @exclude.nil? or Regexp === @exclude then
- # done, #finish is being re-run
- @exclude
- elsif @exclude.empty? then
- nil
- else
- Regexp.new(@exclude.join("|"))
- end
- end
-
- ##
- # Completes any unfinished option setup business such as filtering for
- # existent files, creating a regexp for #exclude and setting a default
- # #template.
-
- def finish
- if @write_options then
- write_options
- exit
- end
-
- @op_dir ||= 'doc'
-
- root = @root.to_s
- if @rdoc_include.empty? || !@rdoc_include.include?(root)
- @rdoc_include << root
- end
-
- @exclude = self.exclude
-
- finish_page_dir
-
- check_files
-
- # If no template was specified, use the default template for the output
- # formatter
-
- unless @template then
- @template = @generator_name
- @template_dir = template_dir_for @template
- end
-
- if @locale_name
- @locale = RDoc::I18n::Locale[@locale_name]
- @locale.load(@locale_dir)
- else
- @locale = nil
- end
-
- self
- end
-
- ##
- # Fixes the page_dir to be relative to the root_dir and adds the page_dir to
- # the files list.
-
- def finish_page_dir
- return unless @page_dir
-
- @files << @page_dir
-
- page_dir = Pathname(@page_dir)
- begin
- page_dir = page_dir.expand_path.relative_path_from @root
- rescue ArgumentError
- # On Windows, sometimes crosses different drive letters.
- page_dir = page_dir.expand_path
- end
-
- @page_dir = page_dir
- end
-
- ##
- # Returns a properly-space list of generators and their descriptions.
-
- def generator_descriptions
- lengths = []
-
- generators = RDoc::RDoc::GENERATORS.map do |name, generator|
- lengths << name.length
-
- description = generator::DESCRIPTION if
- generator.const_defined? :DESCRIPTION
-
- [name, description]
- end
-
- longest = lengths.max
-
- generators.sort.map do |name, description|
- if description then
- " %-*s - %s" % [longest, name, description]
- else
- " #{name}"
- end
- end.join "\n"
- end
-
- ##
- # Parses command line options.
-
- def parse argv
- ignore_invalid = true
-
- argv.insert(0, *ENV['RDOCOPT'].split) if ENV['RDOCOPT']
-
- opts = OptionParser.new do |opt|
- @option_parser = opt
- opt.program_name = File.basename $0
- opt.version = RDoc::VERSION
- opt.release = nil
- opt.summary_indent = ' ' * 4
- opt.banner = <<-EOF
-Usage: #{opt.program_name} [options] [names...]
-
- Files are parsed, and the information they contain collected, before any
- output is produced. This allows cross references between all files to be
- resolved. If a name is a directory, it is traversed. If no names are
- specified, all Ruby files in the current directory (and subdirectories) are
- processed.
-
- How RDoc generates output depends on the output formatter being used, and on
- the options you give.
-
- Options can be specified via the RDOCOPT environment variable, which
- functions similar to the RUBYOPT environment variable for ruby.
-
- $ export RDOCOPT="--show-hash"
-
- will make rdoc show hashes in method links by default. Command-line options
- always will override those in RDOCOPT.
-
- Available formatters:
-
-#{generator_descriptions}
-
- RDoc understands the following file formats:
-
- EOF
-
- parsers = Hash.new { |h,parser| h[parser] = [] }
-
- RDoc::Parser.parsers.each do |regexp, parser|
- parsers[parser.name.sub('RDoc::Parser::', '')] << regexp.source
- end
-
- parsers.sort.each do |parser, regexp|
- opt.banner += " - #{parser}: #{regexp.join ', '}\n"
- end
- opt.banner += " - TomDoc: Only in ruby files\n"
-
- opt.banner += "\n The following options are deprecated:\n\n"
-
- name_length = DEPRECATED.keys.sort_by { |k| k.length }.last.length
-
- DEPRECATED.sort_by { |k,| k }.each do |name, reason|
- opt.banner += " %*1$2$s %3$s\n" % [-name_length, name, reason]
- end
-
- opt.accept Template do |template|
- template_dir = template_dir_for template
-
- unless template_dir then
- $stderr.puts "could not find template #{template}"
- nil
- else
- [template, template_dir]
- end
- end
-
- opt.accept Directory do |directory|
- directory = File.expand_path directory
-
- raise OptionParser::InvalidArgument unless File.directory? directory
-
- directory
- end
-
- opt.accept Path do |path|
- path = File.expand_path path
-
- raise OptionParser::InvalidArgument unless File.exist? path
-
- path
- end
-
- opt.accept PathArray do |paths,|
- paths = if paths then
- paths.split(',').map { |d| d unless d.empty? }
- end
-
- paths.map do |path|
- path = File.expand_path path
-
- raise OptionParser::InvalidArgument unless File.exist? path
-
- path
- end
- end
-
- opt.separator nil
- opt.separator "Parsing options:"
- opt.separator nil
-
- opt.on("--encoding=ENCODING", "-e", Encoding.list.map { |e| e.name },
- "Specifies the output encoding. All files",
- "read will be converted to this encoding.",
- "The default encoding is UTF-8.",
- "--encoding is preferred over --charset") do |value|
- @encoding = Encoding.find value
- @charset = @encoding.name # may not be valid value
- end
-
- opt.separator nil
-
- opt.on("--locale=NAME",
- "Specifies the output locale.") do |value|
- @locale_name = value
- end
-
- opt.on("--locale-data-dir=DIR",
- "Specifies the directory where locale data live.") do |value|
- @locale_dir = value
- end
-
- opt.separator nil
-
- opt.on("--all", "-a",
- "Synonym for --visibility=private.") do |value|
- @visibility = :private
- end
-
- opt.separator nil
-
- opt.on("--exclude=PATTERN", "-x", Regexp,
- "Do not process files or directories",
- "matching PATTERN.") do |value|
- @exclude << value
- end
-
- opt.separator nil
-
- opt.on("--no-skipping-tests", nil,
- "Don't skip generating documentation for test and spec files") do |value|
- @skip_tests = false
- end
-
- opt.separator nil
-
- opt.on("--extension=NEW=OLD", "-E",
- "Treat files ending with .new as if they",
- "ended with .old. Using '-E cgi=rb' will",
- "cause xxx.cgi to be parsed as a Ruby file.") do |value|
- new, old = value.split(/=/, 2)
-
- unless new and old then
- raise OptionParser::InvalidArgument, "Invalid parameter to '-E'"
- end
-
- unless RDoc::Parser.alias_extension old, new then
- raise OptionParser::InvalidArgument, "Unknown extension .#{old} to -E"
- end
- end
-
- opt.separator nil
-
- opt.on("--[no-]force-update", "-U",
- "Forces rdoc to scan all sources even if",
- "no files are newer than the flag file.") do |value|
- @force_update = value
- end
-
- opt.separator nil
-
- opt.on("--pipe", "-p",
- "Convert RDoc on stdin to HTML") do
- @pipe = true
- end
-
- opt.separator nil
-
- opt.on("--tab-width=WIDTH", "-w", Integer,
- "Set the width of tab characters.") do |value|
- raise OptionParser::InvalidArgument,
- "#{value} is an invalid tab width" if value <= 0
- @tab_width = value
- end
-
- opt.separator nil
-
- opt.on("--visibility=VISIBILITY", "-V", RDoc::VISIBILITIES + [:nodoc],
- "Minimum visibility to document a method.",
- "One of 'public', 'protected' (the default),",
- "'private' or 'nodoc' (show everything)") do |value|
- @visibility = value
- end
-
- opt.separator nil
-
- markup_formats = RDoc::Text::MARKUP_FORMAT.keys.sort
-
- opt.on("--markup=MARKUP", markup_formats,
- "The markup format for the named files.",
- "The default is rdoc. Valid values are:",
- markup_formats.join(', ')) do |value|
- @markup = value
- end
-
- opt.separator nil
-
- opt.on("--root=ROOT", Directory,
- "Root of the source tree documentation",
- "will be generated for. Set this when",
- "building documentation outside the",
- "source directory. Default is the",
- "current directory.") do |root|
- @root = Pathname(root)
- end
-
- opt.separator nil
-
- opt.on("--page-dir=DIR", Directory,
- "Directory where guides, your FAQ or",
- "other pages not associated with a class",
- "live. Set this when you don't store",
- "such files at your project root.",
- "NOTE: Do not use the same file name in",
- "the page dir and the root of your project") do |page_dir|
- @page_dir = page_dir
- end
-
- opt.separator nil
- opt.separator "Common generator options:"
- opt.separator nil
-
- opt.on("--force-output", "-O",
- "Forces rdoc to write the output files,",
- "even if the output directory exists",
- "and does not seem to have been created",
- "by rdoc.") do |value|
- @force_output = value
- end
-
- opt.separator nil
-
- generator_text = @generators.keys.map { |name| " #{name}" }.sort
-
- opt.on("-f", "--fmt=FORMAT", "--format=FORMAT", @generators.keys,
- "Set the output formatter. One of:", *generator_text) do |value|
- check_generator
-
- @generator_name = value.downcase
- setup_generator
- end
-
- opt.separator nil
-
- opt.on("--include=DIRECTORIES", "-i", PathArray,
- "Set (or add to) the list of directories to",
- "be searched when satisfying :include:",
- "requests. Can be used more than once.") do |value|
- @rdoc_include.concat value.map { |dir| dir.strip }
- end
-
- opt.separator nil
-
- opt.on("--[no-]coverage-report=[LEVEL]", "--[no-]dcov", "-C", Integer,
- "Prints a report on undocumented items.",
- "Does not generate files.") do |value|
- value = 0 if value.nil? # Integer converts -C to nil
-
- @coverage_report = value
- @force_update = true if value
- end
-
- opt.separator nil
-
- opt.on("--output=DIR", "--op", "-o",
- "Set the output directory.") do |value|
- @op_dir = value
- end
-
- opt.separator nil
-
- opt.on("-d",
- "Deprecated --diagram option.",
- "Prevents firing debug mode",
- "with legacy invocation.") do |value|
- end
-
- opt.separator nil
- opt.separator 'HTML generator options:'
- opt.separator nil
-
- opt.on("--charset=CHARSET", "-c",
- "Specifies the output HTML character-set.",
- "Use --encoding instead of --charset if",
- "available.") do |value|
- @charset = value
- end
-
- opt.separator nil
-
- opt.on("--hyperlink-all", "-A",
- "Generate hyperlinks for all words that",
- "correspond to known methods, even if they",
- "do not start with '#' or '::' (legacy",
- "behavior).") do |value|
- @hyperlink_all = value
- end
-
- opt.separator nil
-
- opt.on("--main=NAME", "-m",
- "NAME will be the initial page displayed.") do |value|
- @main_page = value
- end
-
- opt.separator nil
-
- opt.on("--[no-]line-numbers", "-N",
- "Include line numbers in the source code.",
- "By default, only the number of the first",
- "line is displayed, in a leading comment.") do |value|
- @line_numbers = value
- end
-
- opt.separator nil
-
- opt.on("--show-hash", "-H",
- "A name of the form #name in a comment is a",
- "possible hyperlink to an instance method",
- "name. When displayed, the '#' is removed",
- "unless this option is specified.") do |value|
- @show_hash = value
- end
-
- opt.separator nil
-
- opt.on("--template=NAME", "-T", Template,
- "Set the template used when generating",
- "output. The default depends on the",
- "formatter used.") do |(template, template_dir)|
- @template = template
- @template_dir = template_dir
- end
-
- opt.separator nil
-
- opt.on("--template-stylesheets=FILES", PathArray,
- "Set (or add to) the list of files to",
- "include with the html template.") do |value|
- @template_stylesheets.concat value
- end
-
- opt.separator nil
-
- opt.on("--title=TITLE", "-t",
- "Set TITLE as the title for HTML output.") do |value|
- @title = value
- end
-
- opt.separator nil
-
- opt.on("--copy-files=PATH", Path,
- "Specify a file or directory to copy static",
- "files from.",
- "If a file is given it will be copied into",
- "the output dir. If a directory is given the",
- "entire directory will be copied.",
- "You can use this multiple times") do |value|
- @static_path << value
- end
-
- opt.separator nil
-
- opt.on("--webcvs=URL", "-W",
- "Specify a URL for linking to a web frontend",
- "to CVS. If the URL contains a '\%s', the",
- "name of the current file will be",
- "substituted; if the URL doesn't contain a",
- "'\%s', the filename will be appended to it.") do |value|
- @webcvs = value
- end
-
- opt.separator nil
- opt.separator "ri generator options:"
- opt.separator nil
-
- opt.on("--ri", "-r",
- "Generate output for use by `ri`. The files",
- "are stored in the '.rdoc' directory under",
- "your home directory unless overridden by a",
- "subsequent --op parameter, so no special",
- "privileges are needed.") do |value|
- check_generator
-
- @generator_name = "ri"
- @op_dir ||= RDoc::RI::Paths::HOMEDIR
- setup_generator
- end
-
- opt.separator nil
-
- opt.on("--ri-site", "-R",
- "Generate output for use by `ri`. The files",
- "are stored in a site-wide directory,",
- "making them accessible to others, so",
- "special privileges are needed.") do |value|
- check_generator
-
- @generator_name = "ri"
- @op_dir = RDoc::RI::Paths.site_dir
- setup_generator
- end
-
- opt.separator nil
- opt.separator "Generic options:"
- opt.separator nil
-
- opt.on("--write-options",
- "Write .rdoc_options to the current",
- "directory with the given options. Not all",
- "options will be used. See RDoc::Options",
- "for details.") do |value|
- @write_options = true
- end
-
- opt.separator nil
-
- opt.on("--[no-]dry-run",
- "Don't write any files") do |value|
- @dry_run = value
- end
-
- opt.separator nil
-
- opt.on("-D", "--[no-]debug",
- "Displays lots on internal stuff.") do |value|
- $DEBUG_RDOC = value
- end
-
- opt.separator nil
-
- opt.on("--[no-]ignore-invalid",
- "Ignore invalid options and continue",
- "(default true).") do |value|
- ignore_invalid = value
- end
-
- opt.separator nil
-
- opt.on("--quiet", "-q",
- "Don't show progress as we parse.") do |value|
- @verbosity = 0
- end
-
- opt.separator nil
-
- opt.on("--verbose", "-V",
- "Display extra progress as RDoc parses") do |value|
- @verbosity = 2
- end
-
- opt.separator nil
-
- opt.on("--version", "-v", "print the version") do
- puts opt.version
- exit
- end
-
- opt.separator nil
-
- opt.on("--help", "-h", "Display this help") do
- RDoc::RDoc::GENERATORS.each_key do |generator|
- setup_generator generator
- end
-
- puts opt.help
- exit
- end
-
- opt.separator nil
- end
-
- setup_generator 'darkfish' if
- argv.grep(/\A(-f|--fmt|--format|-r|-R|--ri|--ri-site)\b/).empty?
-
- deprecated = []
- invalid = []
-
- begin
- opts.parse! argv
- rescue OptionParser::ParseError => e
- if DEPRECATED[e.args.first] then
- deprecated << e.args.first
- elsif %w[--format --ri -r --ri-site -R].include? e.args.first then
- raise
- else
- invalid << e.args.join(' ')
- end
-
- retry
- end
-
- unless @generator then
- @generator = RDoc::Generator::Darkfish
- @generator_name = 'darkfish'
- end
-
- if @pipe and not argv.empty? then
- @pipe = false
- invalid << '-p (with files)'
- end
-
- unless quiet then
- deprecated.each do |opt|
- $stderr.puts 'option ' + opt + ' is deprecated: ' + DEPRECATED[opt]
- end
- end
-
- unless invalid.empty? then
- invalid = "invalid options: #{invalid.join ', '}"
-
- if ignore_invalid then
- unless quiet then
- $stderr.puts invalid
- $stderr.puts '(invalid options are ignored)'
- end
- else
- unless quiet then
- $stderr.puts opts
- end
- $stderr.puts invalid
- exit 1
- end
- end
-
- @files = argv.dup
-
- self
- end
-
- ##
- # Don't display progress as we process the files
-
- def quiet
- @verbosity.zero?
- end
-
- ##
- # Set quietness to +bool+
-
- def quiet= bool
- @verbosity = bool ? 0 : 1
- end
-
- ##
- # Removes directories from +path+ that are outside the current directory
-
- def sanitize_path path
- require 'pathname'
- dot = Pathname.new('.').expand_path
-
- path.reject do |item|
- path = Pathname.new(item).expand_path
- is_reject = nil
- relative = nil
- begin
- relative = path.relative_path_from(dot).to_s
- rescue ArgumentError
- # On Windows, sometimes crosses different drive letters.
- is_reject = true
- else
- is_reject = relative.start_with? '..'
- end
- is_reject
- end
- end
-
- ##
- # Set up an output generator for the named +generator_name+.
- #
- # If the found generator responds to :setup_options it will be called with
- # the options instance. This allows generators to add custom options or set
- # default options.
-
- def setup_generator generator_name = @generator_name
- @generator = @generators[generator_name]
-
- unless @generator then
- raise OptionParser::InvalidArgument,
- "Invalid output formatter #{generator_name}"
- end
-
- return if @generator_options.include? @generator
-
- @generator_name = generator_name
- @generator_options << @generator
-
- if @generator.respond_to? :setup_options then
- @option_parser ||= OptionParser.new
- @generator.setup_options self
- end
- end
-
- ##
- # Finds the template dir for +template+
-
- def template_dir_for template
- template_path = File.join 'rdoc', 'generator', 'template', template
-
- $LOAD_PATH.map do |path|
- File.join File.expand_path(path), template_path
- end.find do |dir|
- File.directory? dir
- end
- end
-
- # Sets the minimum visibility of a documented method.
- #
- # Accepts +:public+, +:protected+, +:private+, +:nodoc+, or +:all+.
- #
- # When +:all+ is passed, visibility is set to +:private+, similarly to
- # RDOCOPT="--all", see #visibility for more information.
-
- def visibility= visibility
- case visibility
- when :all
- @visibility = :private
- else
- @visibility = visibility
- end
- end
-
- ##
- # Displays a warning using Kernel#warn if we're being verbose
-
- def warn message
- super message if @verbosity > 1
- end
-
- ##
- # Writes the YAML file .rdoc_options to the current directory containing the
- # parsed options.
-
- def write_options
- RDoc.load_yaml
-
- File.open '.rdoc_options', 'w' do |io|
- io.set_encoding Encoding::UTF_8
-
- io.print to_yaml
- 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/lib/rdoc/parser.rb b/lib/rdoc/parser.rb
deleted file mode 100644
index 425105effa..0000000000
--- a/lib/rdoc/parser.rb
+++ /dev/null
@@ -1,296 +0,0 @@
-# -*- coding: us-ascii -*-
-# frozen_string_literal: true
-
-##
-# A parser is simple a class that subclasses RDoc::Parser and implements #scan
-# to fill in an RDoc::TopLevel with parsed data.
-#
-# The initialize method takes an RDoc::TopLevel to fill with parsed content,
-# the name of the file to be parsed, the content of the file, an RDoc::Options
-# object and an RDoc::Stats object to inform the user of parsed items. The
-# scan method is then called to parse the file and must return the
-# RDoc::TopLevel object. By calling super these items will be set for you.
-#
-# In order to be used by RDoc the parser needs to register the file extensions
-# it can parse. Use ::parse_files_matching to register extensions.
-#
-# require 'rdoc'
-#
-# class RDoc::Parser::Xyz < RDoc::Parser
-# parse_files_matching /\.xyz$/
-#
-# def initialize top_level, file_name, content, options, stats
-# super
-#
-# # extra initialization if needed
-# end
-#
-# def scan
-# # parse file and fill in @top_level
-# end
-# end
-
-class RDoc::Parser
-
- @parsers = []
-
- class << self
-
- ##
- # An Array of arrays that maps file extension (or name) regular
- # expressions to parser classes that will parse matching filenames.
- #
- # Use parse_files_matching to register a parser's file extensions.
-
- attr_reader :parsers
-
- end
-
- ##
- # The name of the file being parsed
-
- attr_reader :file_name
-
- ##
- # Alias an extension to another extension. After this call, files ending
- # "new_ext" will be parsed using the same parser as "old_ext"
-
- def self.alias_extension(old_ext, new_ext)
- old_ext = old_ext.sub(/^\.(.*)/, '\1')
- new_ext = new_ext.sub(/^\.(.*)/, '\1')
-
- parser = can_parse_by_name "xxx.#{old_ext}"
- return false unless parser
-
- RDoc::Parser.parsers.unshift [/\.#{new_ext}$/, parser]
-
- true
- end
-
- ##
- # Determines if the file is a "binary" file which basically means it has
- # content that an RDoc parser shouldn't try to consume.
-
- def self.binary?(file)
- return false if file =~ /\.(rdoc|txt)$/
-
- s = File.read(file, 1024) or return false
-
- return true if s[0, 2] == Marshal.dump('')[0, 2] or s.index("\x00")
-
- 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
- s = File.open(file, mode) {|f| f.gets(nil, 1024)}
-
- not s.valid_encoding?
- end
-
- ##
- # Checks if +file+ is a zip file in disguise. Signatures from
- # http://www.garykessler.net/library/file_sigs.html
-
- def self.zip? file
- zip_signature = File.read file, 4
-
- zip_signature == "PK\x03\x04" or
- zip_signature == "PK\x05\x06" or
- zip_signature == "PK\x07\x08"
- rescue
- false
- end
-
- ##
- # Return a parser that can handle a particular extension
-
- def self.can_parse file_name
- parser = can_parse_by_name file_name
-
- # HACK Selenium hides a jar file using a .txt extension
- return if parser == RDoc::Parser::Simple and zip? file_name
-
- parser
- end
-
- ##
- # Returns a parser that can handle the extension for +file_name+. This does
- # not depend upon the file being readable.
-
- def self.can_parse_by_name file_name
- _, parser = RDoc::Parser.parsers.find { |regexp,| regexp =~ file_name }
-
- # The default parser must not parse binary files
- ext_name = File.extname file_name
- return parser if ext_name.empty?
-
- if parser == RDoc::Parser::Simple and ext_name !~ /txt|rdoc/ then
- case mode = check_modeline(file_name)
- when nil, 'rdoc' then # continue
- else
- RDoc::Parser.parsers.find { |_, p| return p if mode.casecmp?(p.name[/\w+\z/]) }
- return nil
- end
- end
-
- parser
- rescue Errno::EACCES
- end
-
- ##
- # Returns the file type from the modeline in +file_name+
-
- def self.check_modeline file_name
- line = File.open file_name do |io|
- io.gets
- end
-
- /-\*-\s*(.*?\S)\s*-\*-/ =~ line
-
- return nil unless type = $1
-
- if /;/ =~ type then
- return nil unless /(?:\s|\A)mode:\s*([^\s;]+)/i =~ type
- type = $1
- end
-
- return nil if /coding:/i =~ type
-
- type.downcase
- rescue ArgumentError
- rescue Encoding::InvalidByteSequenceError # invalid byte sequence
-
- end
-
- ##
- # Finds and instantiates the correct parser for the given +file_name+ and
- # +content+.
-
- def self.for top_level, file_name, content, options, stats
- return if binary? file_name
-
- parser = use_markup content
-
- unless parser then
- parse_name = file_name
-
- # If no extension, look for shebang
- if file_name !~ /\.\w+$/ && content =~ %r{\A#!(.+)} then
- shebang = $1
- case shebang
- when %r{env\s+ruby}, %r{/ruby}
- parse_name = 'dummy.rb'
- end
- end
-
- parser = can_parse parse_name
- end
-
- return unless parser
-
- content = remove_modeline content
-
- parser.new top_level, file_name, content, options, stats
- rescue SystemCallError
- nil
- end
-
- ##
- # Record which file types this parser can understand.
- #
- # It is ok to call this multiple times.
-
- def self.parse_files_matching(regexp)
- RDoc::Parser.parsers.unshift [regexp, self]
- end
-
- ##
- # Removes an emacs-style modeline from the first line of the document
-
- def self.remove_modeline content
- content.sub(/\A.*-\*-\s*(.*?\S)\s*-\*-.*\r?\n/, '')
- end
-
- ##
- # If there is a <tt>markup: parser_name</tt> comment at the front of the
- # file, use it to determine the parser. For example:
- #
- # # markup: rdoc
- # # Class comment can go here
- #
- # class C
- # end
- #
- # The comment should appear as the first line of the +content+.
- #
- # If the content contains a shebang or editor modeline the comment may
- # appear on the second or third line.
- #
- # Any comment style may be used to hide the markup comment.
-
- def self.use_markup content
- markup = content.lines.first(3).grep(/markup:\s+(\w+)/) { $1 }.first
-
- return unless markup
-
- # TODO Ruby should be returned only when the filename is correct
- return RDoc::Parser::Ruby if %w[tomdoc markdown].include? markup
-
- markup = Regexp.escape markup
-
- _, selected = RDoc::Parser.parsers.find do |_, parser|
- /^#{markup}$/i =~ parser.name.sub(/.*:/, '')
- end
-
- selected
- end
-
- ##
- # Creates a new Parser storing +top_level+, +file_name+, +content+,
- # +options+ and +stats+ in instance variables. In +@preprocess+ an
- # RDoc::Markup::PreProcess object is created which allows processing of
- # directives.
-
- def initialize top_level, file_name, content, options, stats
- @top_level = top_level
- @top_level.parser = self.class
- @store = @top_level.store
-
- @file_name = file_name
- @content = content
- @options = options
- @stats = stats
-
- @preprocess = RDoc::Markup::PreProcess.new @file_name, @options.rdoc_include
- @preprocess.options = @options
- end
-
- autoload :RubyTools, "#{__dir__}/parser/ruby_tools"
- autoload :Text, "#{__dir__}/parser/text"
-
- ##
- # Normalizes tabs in +body+
-
- def handle_tab_width(body)
- if /\t/ =~ body
- tab_width = @options.tab_width
- body.split(/\n/).map do |line|
- 1 while line.gsub!(/\t+/) do
- b, e = $~.offset(0)
- ' ' * (tab_width * (e-b) - b % tab_width)
- end
- line
- end.join "\n"
- else
- body
- end
- end
-end
-
-# simple must come first in order to show up last in the parsers list
-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/lib/rdoc/parser/c.rb b/lib/rdoc/parser/c.rb
deleted file mode 100644
index f8f238fd74..0000000000
--- a/lib/rdoc/parser/c.rb
+++ /dev/null
@@ -1,1236 +0,0 @@
-# frozen_string_literal: true
-require 'tsort'
-
-##
-# RDoc::Parser::C attempts to parse C extension files. It looks for
-# the standard patterns that you find in extensions: +rb_define_class+,
-# +rb_define_method+ and so on. It tries to find the corresponding
-# C source for the methods and extract comments, but if we fail
-# we don't worry too much.
-#
-# The comments associated with a Ruby method are extracted from the C
-# comment block associated with the routine that _implements_ that
-# method, that is to say the method whose name is given in the
-# +rb_define_method+ call. For example, you might write:
-#
-# /*
-# * Returns a new array that is a one-dimensional flattening of this
-# * array (recursively). That is, for every element that is an array,
-# * extract its elements into the new array.
-# *
-# * 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]
-# */
-# static VALUE
-# rb_ary_flatten(VALUE ary)
-# {
-# ary = rb_obj_dup(ary);
-# rb_ary_flatten_bang(ary);
-# return ary;
-# }
-#
-# ...
-#
-# void
-# Init_Array(void)
-# {
-# ...
-# rb_define_method(rb_cArray, "flatten", rb_ary_flatten, 0);
-#
-# Here RDoc will determine from the +rb_define_method+ line that there's a
-# method called "flatten" in class Array, and will look for the implementation
-# in the method +rb_ary_flatten+. It will then use the comment from that
-# method in the HTML output. This method must be in the same source file
-# as the +rb_define_method+.
-#
-# The comment blocks may include special directives:
-#
-# [Document-class: +name+]
-# Documentation for the named class.
-#
-# [Document-module: +name+]
-# Documentation for the named module.
-#
-# [Document-const: +name+]
-# Documentation for the named +rb_define_const+.
-#
-# Constant values can be supplied on the first line of the comment like so:
-#
-# /* 300: The highest possible score in bowling */
-# rb_define_const(cFoo, "PERFECT", INT2FIX(300));
-#
-# The value can contain internal colons so long as they are escaped with a \
-#
-# [Document-global: +name+]
-# Documentation for the named +rb_define_global_const+
-#
-# [Document-variable: +name+]
-# Documentation for the named +rb_define_variable+
-#
-# [Document-method\: +method_name+]
-# Documentation for the named method. Use this when the method name is
-# unambiguous.
-#
-# [Document-method\: <tt>ClassName::method_name</tt>]
-# Documentation for a singleton method in the given class. Use this when
-# the method name alone is ambiguous.
-#
-# [Document-method\: <tt>ClassName#method_name</tt>]
-# Documentation for a instance method in the given class. Use this when the
-# method name alone is ambiguous.
-#
-# [Document-attr: +name+]
-# Documentation for the named attribute.
-#
-# [call-seq: <i>text up to an empty line</i>]
-# Because C source doesn't give descriptive names to Ruby-level parameters,
-# you need to document the calling sequence explicitly
-#
-# In addition, RDoc assumes by default that the C method implementing a
-# Ruby function is in the same source file as the rb_define_method call.
-# If this isn't the case, add the comment:
-#
-# rb_define_method(....); // in filename
-#
-# As an example, we might have an extension that defines multiple classes
-# in its Init_xxx method. We could document them using
-#
-# /*
-# * Document-class: MyClass
-# *
-# * Encapsulate the writing and reading of the configuration
-# * file. ...
-# */
-#
-# /*
-# * Document-method: read_value
-# *
-# * call-seq:
-# * cfg.read_value(key) -> value
-# * cfg.read_value(key} { |key| } -> value
-# *
-# * Return the value corresponding to +key+ from the configuration.
-# * In the second form, if the key isn't found, invoke the
-# * block and return its value.
-# */
-
-class RDoc::Parser::C < RDoc::Parser
-
- parse_files_matching(/\.(?:([CcHh])\1?|c([+xp])\2|y)\z/)
-
- include RDoc::Text
-
- # :stopdoc:
- BOOL_ARG_PATTERN = /\s*+\b([01]|Q?(?:true|false)|TRUE|FALSE)\b\s*/
- TRUE_VALUES = ['1', 'TRUE', 'true', 'Qtrue'].freeze
- # :startdoc:
-
- ##
- # Maps C variable names to names of Ruby classes or modules
-
- attr_reader :classes
-
- ##
- # C file the parser is parsing
-
- attr_accessor :content
-
- ##
- # Dependencies from a missing enclosing class to the classes in
- # missing_dependencies that depend upon it.
-
- attr_reader :enclosure_dependencies
-
- ##
- # Maps C variable names to names of Ruby classes (and singleton classes)
-
- attr_reader :known_classes
-
- ##
- # Classes found while parsing the C file that were not yet registered due to
- # a missing enclosing class. These are processed by do_missing
-
- attr_reader :missing_dependencies
-
- ##
- # Maps C variable names to names of Ruby singleton classes
-
- attr_reader :singleton_classes
-
- ##
- # The TopLevel items in the parsed file belong to
-
- attr_reader :top_level
-
- ##
- # Prepares for parsing a C file. See RDoc::Parser#initialize for details on
- # the arguments.
-
- def initialize top_level, file_name, content, options, stats
- super
-
- @known_classes = RDoc::KNOWN_CLASSES.dup
- @content = handle_tab_width handle_ifdefs_in @content
- @file_dir = File.dirname @file_name
-
- @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] = [] } }
-
- # missing variable => [handle_class_module arguments]
- @missing_dependencies = {}
-
- # missing enclosure variable => [dependent handle_class_module arguments]
- @enclosure_dependencies = Hash.new { |h, k| h[k] = [] }
- @enclosure_dependencies.instance_variable_set :@missing_dependencies,
- @missing_dependencies
-
- @enclosure_dependencies.extend TSort
-
- def @enclosure_dependencies.tsort_each_node &block
- each_key(&block)
- rescue TSort::Cyclic => e
- cycle_vars = e.message.scan(/"(.*?)"/).flatten
-
- cycle = cycle_vars.sort.map do |var_name|
- delete var_name
-
- var_name, type, mod_name, = @missing_dependencies[var_name]
-
- "#{type} #{mod_name} (#{var_name})"
- end.join ', '
-
- warn "Unable to create #{cycle} due to a cyclic class or module creation"
-
- retry
- end
-
- def @enclosure_dependencies.tsort_each_child node, &block
- fetch(node, []).each(&block)
- end
- end
-
- ##
- # Scans #content for rb_define_alias
-
- def do_aliases
- @content.scan(/rb_define_alias\s*\(
- \s*(\w+),
- \s*"(.+?)",
- \s*"(.+?)"
- \s*\)/xm) do |var_name, new_name, old_name|
- class_name = @known_classes[var_name]
-
- unless class_name then
- @options.warn "Enclosing class or module %p for alias %s %s is not known" % [
- var_name, new_name, old_name]
- next
- end
-
- class_obj = find_class var_name, class_name
- comment = find_alias_comment var_name, new_name, old_name
- comment.normalize
- 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
-
- def do_attrs
- @content.scan(/rb_attr\s*\(
- \s*(\w+),
- \s*([\w"()]+),
- #{BOOL_ARG_PATTERN},
- #{BOOL_ARG_PATTERN},
- \s*\w+\);/xmo) do |var_name, attr_name, read, write|
- handle_attr var_name, attr_name, read, write
- end
-
- @content.scan(%r%rb_define_attr\(
- \s*([\w\.]+),
- \s*"([^"]+)",
- #{BOOL_ARG_PATTERN},
- #{BOOL_ARG_PATTERN}\);
- %xmo) do |var_name, attr_name, read, write|
- handle_attr var_name, attr_name, read, write
- end
- end
-
- ##
- # Scans #content for boot_defclass
-
- def do_boot_defclass
- @content.scan(/(\w+)\s*=\s*boot_defclass\s*\(\s*"(\w+?)",\s*(\w+?)\s*\)/) do
- |var_name, class_name, parent|
- parent = nil if parent == "0"
- handle_class_module(var_name, :class, class_name, parent, nil)
- end
- end
-
- ##
- # Scans #content for rb_define_class, boot_defclass, rb_define_class_under
- # and rb_singleton_class
-
- def do_classes_and_modules
- do_boot_defclass if @file_name == "class.c"
-
- @content.scan(
- %r(
- (?<open>\s*\(\s*) {0}
- (?<close>\s*\)\s*) {0}
- (?<name>\s*"(?<class_name>\w+)") {0}
- (?<parent>\s*(?:
- (?<parent_name>[\w\*\s\(\)\.\->]+) |
- rb_path2class\s*\(\s*"(?<path>[\w:]+)"\s*\)
- )) {0}
- (?<under>\w+) {0}
-
- (?<var_name>[\w\.]+)\s* =
- \s*rb_(?:
- define_(?:
- class(?: # rb_define_class(name, parent_name)
- \(\s*
- \g<name>,
- \g<parent>
- \s*\)
- |
- _under\g<open> # rb_define_class_under(under, name, parent_name...)
- \g<under>,
- \g<name>,
- \g<parent>
- \g<close>
- )
- |
- (?<module>)
- module(?: # rb_define_module(name)
- \g<open>
- \g<name>
- \g<close>
- |
- _under\g<open> # rb_define_module_under(under, name)
- \g<under>,
- \g<name>
- \g<close>
- )
- )
- |
- (?<attributes>(?:\s*"\w+",)*\s*NULL\s*) {0}
- struct_define(?:
- \g<open> # rb_struct_define(name, ...)
- \g<name>,
- |
- _under\g<open> # rb_struct_define_under(under, name, ...)
- \g<under>,
- \g<name>,
- |
- _without_accessor(?:
- \g<open> # rb_struct_define_without_accessor(name, parent_name, ...)
- |
- _under\g<open> # rb_struct_define_without_accessor_under(under, name, parent_name, ...)
- \g<under>,
- )
- \g<name>,
- \g<parent>,
- \s*\w+, # Allocation function
- )
- \g<attributes>
- \g<close>
- |
- singleton_class\g<open> # rb_singleton_class(target_class_name)
- (?<target_class_name>\w+)
- \g<close>
- )
- )mx
- ) do
- if target_class_name = $~[:target_class_name]
- # rb_singleton_class(target_class_name)
- handle_singleton $~[:var_name], target_class_name
- next
- end
-
- var_name = $~[:var_name]
- type = $~[:module] ? :module : :class
- class_name = $~[:class_name]
- parent_name = $~[:parent_name] || $~[:path]
- under = $~[:under]
- attributes = $~[:attributes]
-
- handle_class_module(var_name, type, class_name, parent_name, under)
- if attributes and !parent_name # rb_struct_define *not* without_accessor
- true_flag = 'Qtrue'
- attributes.scan(/"\K\w+(?=")/) do |attr_name|
- handle_attr var_name, attr_name, true_flag, true_flag
- end
- end
- end
- end
-
- ##
- # Scans #content for rb_define_variable, rb_define_readonly_variable,
- # rb_define_const and rb_define_global_const
-
- def do_constants
- @content.scan(%r%\Wrb_define_
- ( variable |
- readonly_variable |
- const |
- global_const )
- \s*\(
- (?:\s*(\w+),)?
- \s*"(\w+)",
- \s*(.*?)\s*\)\s*;
- %xm) do |type, var_name, const_name, definition|
- var_name = "rb_cObject" if !var_name or var_name == "rb_mKernel"
- handle_constants type, var_name, const_name, definition
- end
-
- @content.scan(%r%
- \Wrb_curses_define_const
- \s*\(
- \s*
- (\w+)
- \s*
- \)
- \s*;%xm) do |consts|
- const = consts.first
-
- handle_constants 'const', 'mCurses', const, "UINT2NUM(#{const})"
- end
-
- @content.scan(%r%
- \Wrb_file_const
- \s*\(
- \s*
- "([^"]+)",
- \s*
- (.*?)
- \s*
- \)
- \s*;%xm) do |name, value|
- handle_constants 'const', 'rb_mFConst', name, value
- end
- end
-
-
- ##
- # Scans #content for rb_include_module
-
- def do_includes
- @content.scan(/rb_include_module\s*\(\s*(\w+?),\s*(\w+?)\s*\)/) do |c,m|
- next unless cls = @classes[c]
- m = @known_classes[m] || m
-
- comment = new_comment '', @top_level, :c
- incl = cls.add_include RDoc::Include.new(m, comment)
- incl.record_location @top_level
- end
- end
-
- ##
- # Scans #content for rb_define_method, rb_define_singleton_method,
- # rb_define_module_function, rb_define_private_method,
- # rb_define_global_function and define_filetest_function
-
- def do_methods
- @content.scan(%r%rb_define_
- (
- singleton_method |
- method |
- module_function |
- private_method
- )
- \s*\(\s*([\w\.]+),
- \s*"([^"]+)",
- \s*(?:RUBY_METHOD_FUNC\(|VALUEFUNC\(|\(METHOD\))?(\w+)\)?,
- \s*(-?\w+)\s*\)
- (?:;\s*/[*/]\s+in\s+(\w+?\.(?:cpp|c|y)))?
- %xm) do |type, var_name, meth_name, function, param_count, source_file|
-
- # Ignore top-object and weird struct.c dynamic stuff
- next if var_name == "ruby_top_self"
- next if var_name == "nstr"
-
- var_name = "rb_cObject" if var_name == "rb_mKernel"
- handle_method(type, var_name, meth_name, function, param_count,
- source_file)
- end
-
- @content.scan(%r%rb_define_global_function\s*\(
- \s*"([^"]+)",
- \s*(?:RUBY_METHOD_FUNC\(|VALUEFUNC\()?(\w+)\)?,
- \s*(-?\w+)\s*\)
- (?:;\s*/[*/]\s+in\s+(\w+?\.[cy]))?
- %xm) do |meth_name, function, param_count, source_file|
- handle_method("method", "rb_mKernel", meth_name, function, param_count,
- source_file)
- end
-
- @content.scan(/define_filetest_function\s*\(
- \s*"([^"]+)",
- \s*(?:RUBY_METHOD_FUNC\(|VALUEFUNC\()?(\w+)\)?,
- \s*(-?\w+)\s*\)/xm) do |meth_name, function, param_count|
-
- handle_method("method", "rb_mFileTest", meth_name, function, param_count)
- handle_method("singleton_method", "rb_cFile", meth_name, function,
- param_count)
- end
- end
-
- ##
- # Creates classes and module that were missing were defined due to the file
- # order being different than the declaration order.
-
- def do_missing
- return if @missing_dependencies.empty?
-
- @enclosure_dependencies.tsort.each do |in_module|
- arguments = @missing_dependencies.delete in_module
-
- next unless arguments # dependency on existing class
-
- handle_class_module(*arguments)
- end
- end
-
- ##
- # Finds the comment for an alias on +class_name+ from +new_name+ to
- # +old_name+
-
- def find_alias_comment class_name, new_name, old_name
- content =~ %r%((?>/\*.*?\*/\s+))
- rb_define_alias\(\s*#{Regexp.escape class_name}\s*,
- \s*"#{Regexp.escape new_name}"\s*,
- \s*"#{Regexp.escape old_name}"\s*\);%xm
-
- new_comment($1 || '', @top_level, :c)
- end
-
- ##
- # Finds a comment for rb_define_attr, rb_attr or Document-attr.
- #
- # +var_name+ is the C class variable the attribute is defined on.
- # +attr_name+ is the attribute's name.
- #
- # +read+ and +write+ are the read/write flags ('1' or '0'). Either both or
- # neither must be provided.
-
- def find_attr_comment var_name, attr_name, read = nil, write = nil
- attr_name = Regexp.escape attr_name
-
- rw = if read and write then
- /\s*#{read}\s*,\s*#{write}\s*/xm
- else
- /.*?/m
- end
-
- comment = if @content =~ %r%((?>/\*.*?\*/\s+))
- rb_define_attr\((?:\s*#{var_name},)?\s*
- "#{attr_name}"\s*,
- #{rw}\)\s*;%xm then
- $1
- elsif @content =~ %r%((?>/\*.*?\*/\s+))
- rb_attr\(\s*#{var_name}\s*,
- \s*#{attr_name}\s*,
- #{rw},.*?\)\s*;%xm then
- $1
- elsif @content =~ %r%(/\*.*?(?:\s*\*\s*)?)
- Document-attr:\s#{attr_name}\s*?\n
- ((?>(.|\n)*?\*/))%x then
- "#{$1}\n#{$2}"
- else
- ''
- end
-
- new_comment comment, @top_level, :c
- end
-
- ##
- # Generate a Ruby-method table
-
- def gen_body_table file_content
- table = {}
- file_content.scan(%r{
- ((?>/\*.*?\*/\s*)?)
- ((?:\w+\s+){0,2} VALUE\s+(\w+)
- \s*(?:\([^\)]*\))(?:[^\);]|$))
- | ((?>/\*.*?\*/\s*))^\s*(\#\s*define\s+(\w+)\s+(\w+))
- | ^\s*\#\s*define\s+(\w+)\s+(\w+)
- }xm) do
- case
- when name = $3
- table[name] = [:func_def, $1, $2, $~.offset(2)] if !(t = table[name]) || t[0] != :func_def
- when name = $6
- table[name] = [:macro_def, $4, $5, $~.offset(5), $7] if !(t = table[name]) || t[0] == :macro_alias
- when name = $8
- table[name] ||= [:macro_alias, $9]
- end
- end
- table
- end
-
- ##
- # Find the C code corresponding to a Ruby method
-
- def find_body class_name, meth_name, meth_obj, file_content, quiet = false
- if file_content
- @body_table ||= {}
- @body_table[file_content] ||= gen_body_table file_content
- type, *args = @body_table[file_content][meth_name]
- end
-
- case type
- when :func_def
- comment = new_comment args[0], @top_level, :c
- body = args[1]
- offset, = args[2]
-
- comment.remove_private if comment
-
- # try to find the whole body
- body = $& if /#{Regexp.escape body}[^(]*?\{.*?^\}/m =~ file_content
-
- # The comment block may have been overridden with a 'Document-method'
- # block. This happens in the interpreter when multiple methods are
- # vectored through to the same C method but those methods are logically
- # distinct (for example Kernel.hash and Kernel.object_id share the same
- # implementation
-
- override_comment = find_override_comment class_name, meth_obj
- comment = override_comment if override_comment
-
- comment.normalize
- find_modifiers comment, meth_obj if comment
-
- #meth_obj.params = params
- meth_obj.start_collecting_tokens
- tk = { :line_no => 1, :char_no => 1, :text => body }
- meth_obj.add_token tk
- meth_obj.comment = comment
- meth_obj.line = file_content[0, offset].count("\n") + 1
-
- body
- when :macro_def
- comment = new_comment args[0], @top_level, :c
- body = args[1]
- offset, = args[2]
-
- find_body class_name, args[3], meth_obj, file_content, true
-
- comment.normalize
- find_modifiers comment, meth_obj
-
- meth_obj.start_collecting_tokens
- tk = { :line_no => 1, :char_no => 1, :text => body }
- meth_obj.add_token tk
- meth_obj.comment = comment
- meth_obj.line = file_content[0, offset].count("\n") + 1
-
- body
- when :macro_alias
- # with no comment we hope the aliased definition has it and use it's
- # definition
-
- body = find_body(class_name, args[0], meth_obj, file_content, true)
-
- return body if body
-
- @options.warn "No definition for #{meth_name}"
- false
- else # No body, but might still have an override comment
- comment = find_override_comment class_name, meth_obj
-
- if comment then
- comment.normalize
- find_modifiers comment, meth_obj
- meth_obj.comment = comment
-
- ''
- else
- @options.warn "No definition for #{meth_name}"
- false
- end
- end
- end
-
- ##
- # Finds a RDoc::NormalClass or RDoc::NormalModule for +raw_name+
-
- def find_class(raw_name, name, base_name = nil)
- unless @classes[raw_name]
- if raw_name =~ /^rb_m/
- container = @top_level.add_module RDoc::NormalModule, name
- else
- container = @top_level.add_class RDoc::NormalClass, name
- end
- container.name = base_name if base_name
-
- container.record_location @top_level
- @classes[raw_name] = container
- end
- @classes[raw_name]
- end
-
- ##
- # Look for class or module documentation above Init_+class_name+(void),
- # in a Document-class +class_name+ (or module) comment or above an
- # rb_define_class (or module). If a comment is supplied above a matching
- # Init_ and a rb_define_class the Init_ comment is used.
- #
- # /*
- # * This is a comment for Foo
- # */
- # Init_Foo(void) {
- # VALUE cFoo = rb_define_class("Foo", rb_cObject);
- # }
- #
- # /*
- # * Document-class: Foo
- # * This is a comment for Foo
- # */
- # Init_foo(void) {
- # VALUE cFoo = rb_define_class("Foo", rb_cObject);
- # }
- #
- # /*
- # * This is a comment for Foo
- # */
- # VALUE cFoo = rb_define_class("Foo", rb_cObject);
-
- def find_class_comment class_name, class_mod
- comment = nil
-
- if @content =~ %r%
- ((?>/\*.*?\*/\s+))
- (static\s+)?
- void\s+
- Init(?:VM)?_(?i:#{class_name})\s*(?:_\(\s*)?\(\s*(?:void\s*)?\)%xm then
- comment = $1.sub(%r%Document-(?:class|module):\s+#{class_name}%, '')
- elsif @content =~ %r%Document-(?:class|module):\s+#{class_name}\s*?
- (?:<\s+[:,\w]+)?\n((?>.*?\*/))%xm then
- comment = "/*\n#{$1}"
- elsif @content =~ %r%((?>/\*.*?\*/\s+))
- ([\w\.\s]+\s* = \s+)?rb_define_(class|module)[\t (]*?"(#{class_name})"%xm then
- comment = $1
- elsif @content =~ %r%((?>/\*.*?\*/\s+))
- ([\w\. \t]+ = \s+)?rb_define_(class|module)_under[\t\w, (]*?"(#{class_name.split('::').last})"%xm then
- comment = $1
- else
- comment = ''
- end
-
- comment = new_comment comment, @top_level, :c
- comment.normalize
-
- look_for_directives_in class_mod, comment
-
- class_mod.add_comment comment, @top_level
- end
-
- ##
- # Generate a const table
-
- def gen_const_table file_content
- table = {}
- @content.scan(%r{
- (?<doc>(?>^\s*/\*.*?\*/\s+))
- rb_define_(?<type>\w+)\(\s*(?:\w+),\s*
- "(?<name>\w+)"\s*,
- .*?\)\s*;
- | (?<doc>(?>^\s*/\*.*?\*/\s+))
- rb_file_(?<type>const)\(\s*
- "(?<name>\w+)"\s*,
- .*?\)\s*;
- | (?<doc>(?>^\s*/\*.*?\*/\s+))
- rb_curses_define_(?<type>const)\(\s*
- (?<name>\w+)
- \s*\)\s*;
- | Document-(?:const|global|variable):\s
- (?<name>(?:\w+::)*\w+)
- \s*?\n(?<doc>(?>.*?\*/))
- }mxi) do
- name, doc, type = $~.values_at(:name, :doc, :type)
- if type
- table[[type, name]] = doc
- else
- table[name] = "/*\n" + doc
- end
- end
- table
- end
-
- ##
- # Finds a comment matching +type+ and +const_name+ either above the
- # comment or in the matching Document- section.
-
- def find_const_comment(type, const_name, class_name = nil)
- @const_table ||= {}
- @const_table[@content] ||= gen_const_table @content
- table = @const_table[@content]
-
- comment =
- table[[type, const_name]] ||
- (class_name && table[class_name + "::" + const_name]) ||
- table[const_name] ||
- ''
-
- new_comment comment, @top_level, :c
- end
-
- ##
- # Handles modifiers in +comment+ and updates +meth_obj+ as appropriate.
-
- def find_modifiers comment, meth_obj
- comment.normalize
- comment.extract_call_seq meth_obj
-
- look_for_directives_in meth_obj, comment
- end
-
- ##
- # Finds a <tt>Document-method</tt> override for +meth_obj+ on +class_name+
-
- def find_override_comment class_name, meth_obj
- name = Regexp.escape meth_obj.name
- prefix = Regexp.escape meth_obj.name_prefix
-
- comment = if @content =~ %r%Document-method:
- \s+#{class_name}#{prefix}#{name}
- \s*?\n((?>.*?\*/))%xm then
- "/*#{$1}"
- elsif @content =~ %r%Document-method:
- \s#{name}\s*?\n((?>.*?\*/))%xm then
- "/*#{$1}"
- end
-
- return unless comment
-
- new_comment comment, @top_level, :c
- end
-
- ##
- # Creates a new RDoc::Attr +attr_name+ on class +var_name+ that is either
- # +read+, +write+ or both
-
- def handle_attr(var_name, attr_name, read, write)
- rw = ''
- rw += 'R' if TRUE_VALUES.include?(read)
- rw += 'W' if TRUE_VALUES.include?(write)
-
- class_name = @known_classes[var_name]
-
- return unless class_name
-
- class_obj = find_class var_name, class_name
-
- return unless class_obj
-
- comment = find_attr_comment var_name, attr_name
- comment.normalize
-
- name = attr_name.gsub(/rb_intern(?:_const)?\("([^"]+)"\)/, '\1')
-
- attr = RDoc::Attr.new '', name, rw, comment
-
- attr.record_location @top_level
- class_obj.add_attribute attr
- @stats.add_attribute attr
- end
-
- ##
- # Creates a new RDoc::NormalClass or RDoc::NormalModule based on +type+
- # named +class_name+ in +parent+ which was assigned to the C +var_name+.
-
- def handle_class_module(var_name, type, class_name, parent, in_module)
- parent_name = @known_classes[parent] || parent
-
- if in_module then
- enclosure = @classes[in_module] || @store.find_c_enclosure(in_module)
-
- if enclosure.nil? and enclosure = @known_classes[in_module] then
- enc_type = /^rb_m/ =~ in_module ? :module : :class
- handle_class_module in_module, enc_type, enclosure, nil, nil
- enclosure = @classes[in_module]
- end
-
- unless enclosure then
- @enclosure_dependencies[in_module] << var_name
- @missing_dependencies[var_name] =
- [var_name, type, class_name, parent, in_module]
-
- return
- end
- else
- enclosure = @top_level
- end
-
- if type == :class then
- full_name = if RDoc::ClassModule === enclosure then
- enclosure.full_name + "::#{class_name}"
- else
- class_name
- end
-
- if @content =~ %r%Document-class:\s+#{full_name}\s*<\s+([:,\w]+)% then
- parent_name = $1
- end
-
- cm = enclosure.add_class RDoc::NormalClass, class_name, parent_name
- else
- cm = enclosure.add_module RDoc::NormalModule, class_name
- end
-
- cm.record_location enclosure.top_level
-
- find_class_comment cm.full_name, cm
-
- case cm
- when RDoc::NormalClass
- @stats.add_class cm
- when RDoc::NormalModule
- @stats.add_module cm
- end
-
- @classes[var_name] = cm
- @known_classes[var_name] = cm.full_name
- @store.add_c_enclosure var_name, cm
- end
-
- ##
- # Adds constants. By providing some_value: at the start of the comment you
- # can override the C value of the comment to give a friendly definition.
- #
- # /* 300: The perfect score in bowling */
- # rb_define_const(cFoo, "PERFECT", INT2FIX(300));
- #
- # Will override <tt>INT2FIX(300)</tt> with the value +300+ in the output
- # RDoc. Values may include quotes and escaped colons (\:).
-
- def handle_constants(type, var_name, const_name, definition)
- class_name = @known_classes[var_name]
-
- return unless class_name
-
- class_obj = find_class var_name, class_name, class_name[/::\K[^:]+\z/]
-
- unless class_obj then
- @options.warn 'Enclosing class or module %p is not known' % [const_name]
- return
- end
-
- comment = find_const_comment type, const_name, class_name
- comment.normalize
-
- # In the case of rb_define_const, the definition and comment are in
- # "/* definition: comment */" form. The literal ':' and '\' characters
- # can be escaped with a backslash.
- if type.downcase == 'const' then
- if /\A(.+?)?:(?!\S)/ =~ comment.text
- new_definition, new_comment = $1, $'
-
- if !new_definition # Default to literal C definition
- new_definition = definition
- else
- new_definition = new_definition.gsub(/\\([\\:])/, '\1')
- end
-
- new_definition.sub!(/\A(\s+)/, '')
-
- new_comment = "#{$1}#{new_comment.lstrip}"
-
- new_comment = self.new_comment(new_comment, @top_level, :c)
-
- con = RDoc::Constant.new const_name, new_definition, new_comment
- else
- con = RDoc::Constant.new const_name, definition, comment
- end
- else
- con = RDoc::Constant.new const_name, definition, comment
- end
-
- con.record_location @top_level
- @stats.add_constant con
- class_obj.add_constant con
- end
-
- ##
- # Removes #ifdefs that would otherwise confuse us
-
- def handle_ifdefs_in(body)
- body.gsub(/^#ifdef HAVE_PROTOTYPES.*?#else.*?\n(.*?)#endif.*?\n/m, '\1')
- end
-
- ##
- # Adds an RDoc::AnyMethod +meth_name+ defined on a class or module assigned
- # to +var_name+. +type+ is the type of method definition function used.
- # +singleton_method+ and +module_function+ create a singleton method.
-
- def handle_method(type, var_name, meth_name, function, param_count,
- source_file = nil)
- class_name = @known_classes[var_name]
- singleton = @singleton_classes.key? var_name
-
- @methods[var_name][function] << meth_name
-
- return unless class_name
-
- 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'
- singleton = true
- type = 'method' # force public
- end
-
- meth_obj = RDoc::AnyMethod.new '', meth_name
- meth_obj.c_function = function
- meth_obj.singleton =
- singleton || %w[singleton_method module_function].include?(type)
-
- p_count = Integer(param_count) rescue -1
-
- if source_file then
- file_name = File.join @file_dir, source_file
-
- if File.exist? file_name then
- file_content = File.read file_name
- else
- @options.warn "unknown source #{source_file} for #{meth_name} in #{@file_name}"
- end
- else
- file_content = @content
- end
-
- body = find_body class_name, function, meth_obj, file_content
-
- if body and meth_obj.document_self then
- meth_obj.params = if p_count < -1 then # -2 is Array
- '(*args)'
- elsif p_count == -1 then # argc, argv
- rb_scan_args body
- else
- args = (1..p_count).map { |i| "p#{i}" }
- "(#{args.join ', '})"
- end
-
-
- 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
- end
- end
-
- ##
- # Registers a singleton class +sclass_var+ as a singleton of +class_var+
-
- def handle_singleton sclass_var, class_var
- class_name = @known_classes[class_var]
-
- @known_classes[sclass_var] = class_name
- @singleton_classes[sclass_var] = class_name
- end
-
- ##
- # Loads the variable map with the given +name+ from the RDoc::Store, if
- # present.
-
- def load_variable_map map_name
- return {} unless files = @store.cache[map_name]
- return {} unless name_map = files[@file_name]
-
- class_map = {}
-
- name_map.each do |variable, name|
- next unless mod = @store.find_class_or_module(name)
-
- class_map[variable] = if map_name == :c_class_variables then
- mod
- else
- name
- end
- @known_classes[variable] = name
- end
-
- class_map
- end
-
- ##
- # Look for directives in a normal comment block:
- #
- # /*
- # * :title: My Awesome Project
- # */
- #
- # This method modifies the +comment+
-
- def look_for_directives_in context, comment
- @preprocess.handle comment, context do |directive, param|
- case directive
- when 'main' then
- @options.main_page = param
- ''
- when 'title' then
- @options.default_title = param if @options.respond_to? :default_title=
- ''
- end
- end
-
- comment
- end
-
- ##
- # Extracts parameters from the +method_body+ and returns a method
- # parameter string. Follows 1.9.3dev's scan-arg-spec, see README.EXT
-
- def rb_scan_args method_body
- method_body =~ /rb_scan_args\((.*?)\)/m
- return '(*args)' unless $1
-
- $1.split(/,/)[2] =~ /"(.*?)"/ # format argument
- format = $1.split(//)
-
- lead = opt = trail = 0
-
- if format.first =~ /\d/ then
- lead = $&.to_i
- format.shift
- if format.first =~ /\d/ then
- opt = $&.to_i
- format.shift
- if format.first =~ /\d/ then
- trail = $&.to_i
- format.shift
- block_arg = true
- end
- end
- end
-
- if format.first == '*' and not block_arg then
- var = true
- format.shift
- if format.first =~ /\d/ then
- trail = $&.to_i
- format.shift
- end
- end
-
- if format.first == ':' then
- hash = true
- format.shift
- end
-
- if format.first == '&' then
- block = true
- format.shift
- end
-
- # if the format string is not empty there's a bug in the C code, ignore it
-
- args = []
- position = 1
-
- (1...(position + lead)).each do |index|
- args << "p#{index}"
- end
-
- position += lead
-
- (position...(position + opt)).each do |index|
- args << "p#{index} = v#{index}"
- end
-
- position += opt
-
- if var then
- args << '*args'
- position += 1
- end
-
- (position...(position + trail)).each do |index|
- args << "p#{index}"
- end
-
- position += trail
-
- if hash then
- args << "p#{position} = {}"
- end
-
- args << '&block' if block
-
- "(#{args.join ', '})"
- end
-
- ##
- # Removes lines that are commented out that might otherwise get picked up
- # when scanning for classes and methods
-
- def remove_commented_out_lines
- @content = @content.gsub(%r%//.*rb_define_%, '//')
- end
-
- ##
- # Extracts the classes, modules, methods, attributes, constants and aliases
- # from a C file and returns an RDoc::TopLevel for this file
-
- def scan
- remove_commented_out_lines
-
- do_classes_and_modules
- do_missing
-
- do_constants
- do_methods
- do_includes
- do_aliases
- do_attrs
-
- @store.add_c_variables self
-
- @top_level
- end
-
- ##
- # Creates a RDoc::Comment instance.
-
- 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/lib/rdoc/parser/changelog.rb b/lib/rdoc/parser/changelog.rb
deleted file mode 100644
index a046241870..0000000000
--- a/lib/rdoc/parser/changelog.rb
+++ /dev/null
@@ -1,349 +0,0 @@
-# frozen_string_literal: true
-
-##
-# A ChangeLog file parser.
-#
-# This parser converts a ChangeLog into an RDoc::Markup::Document. When
-# viewed as HTML a ChangeLog page will have an entry for each day's entries in
-# the sidebar table of contents.
-#
-# This parser is meant to parse the MRI ChangeLog, but can be used to parse any
-# {GNU style Change
-# Log}[http://www.gnu.org/prep/standards/html_node/Style-of-Change-Logs.html].
-
-class RDoc::Parser::ChangeLog < RDoc::Parser
-
- include RDoc::Parser::Text
-
- parse_files_matching(/(\/|\\|\A)ChangeLog[^\/\\]*\z/)
-
- ##
- # Attaches the +continuation+ of the previous line to the +entry_body+.
- #
- # Continued function listings are joined together as a single entry.
- # Continued descriptions are joined to make a single paragraph.
-
- def continue_entry_body entry_body, continuation
- return unless last = entry_body.last
-
- if last =~ /\)\s*\z/ and continuation =~ /\A\(/ then
- last.sub!(/\)\s*\z/, ',')
- continuation = continuation.sub(/\A\(/, '')
- end
-
- if last =~ /\s\z/ then
- last << continuation
- else
- last << ' ' + continuation
- end
- end
-
- ##
- # Creates an RDoc::Markup::Document given the +groups+ of ChangeLog entries.
-
- def create_document groups
- doc = RDoc::Markup::Document.new
- doc.omit_headings_below = 2
- doc.file = @top_level
-
- doc << RDoc::Markup::Heading.new(1, File.basename(@file_name))
- doc << RDoc::Markup::BlankLine.new
-
- groups.sort_by do |day,| day end.reverse_each do |day, entries|
- doc << RDoc::Markup::Heading.new(2, day.dup)
- doc << RDoc::Markup::BlankLine.new
-
- doc.concat create_entries entries
- end
-
- doc
- end
-
- ##
- # Returns a list of ChangeLog entries an RDoc::Markup nodes for the given
- # +entries+.
-
- def create_entries entries
- out = []
-
- entries.each do |entry, items|
- out << RDoc::Markup::Heading.new(3, entry)
- out << RDoc::Markup::BlankLine.new
-
- out << create_items(items)
- end
-
- out
- end
-
- ##
- # Returns an RDoc::Markup::List containing the given +items+ in the
- # ChangeLog
-
- def create_items items
- list = RDoc::Markup::List.new :NOTE
-
- items.each do |item|
- item =~ /\A(.*?(?:\([^)]+\))?):\s*/
-
- title = $1
- body = $'
-
- paragraph = RDoc::Markup::Paragraph.new body
- list_item = RDoc::Markup::ListItem.new title, paragraph
- list << list_item
- end
-
- list
- end
-
- ##
- # Groups +entries+ by date.
-
- def group_entries entries
- @time_cache ||= {}
- entries.group_by do |title, _|
- begin
- time = @time_cache[title]
- (time || parse_date(title)).strftime '%Y-%m-%d'
- rescue NoMethodError, ArgumentError
- time, = title.split ' ', 2
- 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.
- #
- # Returns an Array of each ChangeLog entry in order of parsing.
- #
- # A ChangeLog entry is an Array containing the ChangeLog title (date and
- # committer) and an Array of ChangeLog items (file and function changed with
- # description).
- #
- # An example result would be:
- #
- # [ 'Tue Dec 4 08:33:46 2012 Eric Hodel <drbrain@segment7.net>',
- # [ 'README.EXT: Converted to RDoc format',
- # 'README.EXT.ja: ditto']]
-
- 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 = []
-
- @content.each_line do |line|
- case line
- when /^\s*$/ then
- next
- when /^\w.*/ then
- entries << [entry_name, entry_body] if entry_name
-
- entry_name = $&
-
- begin
- time = parse_date entry_name
- @time_cache[entry_name] = time
- rescue ArgumentError
- entry_name = nil
- end
-
- entry_body = []
- when /^(\t| {8})?\*\s*(.*)/ then # "\t* file.c (func): ..."
- entry_body << $2.dup
- when /^(\t| {8})?\s*(\(.*)/ then # "\t(func): ..."
- entry = $2
-
- if entry_body.last =~ /:/ then
- entry_body << entry.dup
- else
- continue_entry_body entry_body, entry
- end
- when /^(\t| {8})?\s*(.*)/ then
- continue_entry_body entry_body, $2
- end
- end
-
- entries << [entry_name, entry_body] if entry_name
-
- entries.reject! do |(entry,_)|
- entry == nil
- end
-
- entries
- end
-
- ##
- # Converts the ChangeLog into an RDoc::Markup::Document
-
- def scan
- @time_cache = {}
-
- entries = parse_entries
- grouped_entries = group_entries entries
-
- doc = create_document grouped_entries
-
- @top_level.comment = doc
-
- @top_level
- end
-
- ##
- # The extension for Git commit log
-
- module Git
- ##
- # Parses auxiliary info. Currentry `base-url` to expand
- # references is effective.
-
- def parse_info(info)
- /^\s*base-url\s*=\s*(.*\S)/ =~ info
- @base_url = $1
- end
-
- ##
- # Parses the entries in the Git commit logs
-
- 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
-
- ##
- # Returns a list of ChangeLog entries as
- # RDoc::Parser::ChangeLog::Git::LogEntry list for the given
- # +entries+.
-
- 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/lib/rdoc/parser/markdown.rb b/lib/rdoc/parser/markdown.rb
deleted file mode 100644
index 3c316227b9..0000000000
--- a/lib/rdoc/parser/markdown.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-##
-# Parse a Markdown format file. The parsed RDoc::Markup::Document is attached
-# as a file comment.
-
-class RDoc::Parser::Markdown < RDoc::Parser
-
- include RDoc::Parser::Text
-
- parse_files_matching(/\.(md|markdown)(?:\.[^.]+)?$/)
-
- ##
- # Creates an Markdown-format TopLevel for the given file.
-
- def scan
- comment = RDoc::Comment.new @content, @top_level
- comment.format = 'markdown'
-
- @top_level.comment = comment
- end
-
-end
diff --git a/lib/rdoc/parser/rd.rb b/lib/rdoc/parser/rd.rb
deleted file mode 100644
index 19e47e549d..0000000000
--- a/lib/rdoc/parser/rd.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-##
-# Parse a RD format file. The parsed RDoc::Markup::Document is attached as a
-# file comment.
-
-class RDoc::Parser::RD < RDoc::Parser
-
- include RDoc::Parser::Text
-
- parse_files_matching(/\.rd(?:\.[^.]+)?$/)
-
- ##
- # Creates an rd-format TopLevel for the given file.
-
- def scan
- comment = RDoc::Comment.new @content, @top_level
- comment.format = 'rd'
-
- @top_level.comment = comment
- end
-
-end
diff --git a/lib/rdoc/parser/ripper_state_lex.rb b/lib/rdoc/parser/ripper_state_lex.rb
deleted file mode 100644
index f6cefd0305..0000000000
--- a/lib/rdoc/parser/ripper_state_lex.rb
+++ /dev/null
@@ -1,600 +0,0 @@
-# frozen_string_literal: true
-require 'ripper'
-
-##
-# Wrapper for Ripper lex states
-
-class RDoc::Parser::RipperStateLex
- # :stopdoc:
-
- # TODO: Remove this constants after Ruby 2.4 EOL
- RIPPER_HAS_LEX_STATE = Ripper::Filter.method_defined?(:state)
-
- Token = Struct.new(:line_no, :char_no, :kind, :text, :state)
-
- EXPR_NONE = 0
- EXPR_BEG = 1
- EXPR_END = 2
- EXPR_ENDARG = 4
- EXPR_ENDFN = 8
- EXPR_ARG = 16
- EXPR_CMDARG = 32
- EXPR_MID = 64
- EXPR_FNAME = 128
- EXPR_DOT = 256
- EXPR_CLASS = 512
- EXPR_LABEL = 1024
- EXPR_LABELED = 2048
- EXPR_FITEM = 4096
- EXPR_VALUE = EXPR_BEG
- EXPR_BEG_ANY = (EXPR_BEG | EXPR_MID | EXPR_CLASS)
- EXPR_ARG_ANY = (EXPR_ARG | EXPR_CMDARG)
- EXPR_END_ANY = (EXPR_END | EXPR_ENDARG | EXPR_ENDFN)
-
- class InnerStateLex < Ripper::Filter
- attr_accessor :lex_state
-
- def initialize(code)
- @lex_state = EXPR_BEG
- @in_fname = false
- @continue = false
- reset
- super(code)
- end
-
- def reset
- @command_start = false
- @cmd_state = @command_start
- end
-
- def on_nl(tok, data)
- case @lex_state
- when EXPR_FNAME, EXPR_DOT
- @continue = true
- else
- @continue = false
- @lex_state = EXPR_BEG unless (EXPR_LABEL & @lex_state) != 0
- end
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- end
-
- def on_ignored_nl(tok, data)
- case @lex_state
- when EXPR_FNAME, EXPR_DOT
- @continue = true
- else
- @continue = false
- @lex_state = EXPR_BEG unless (EXPR_LABEL & @lex_state) != 0
- end
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- end
-
- def on_op(tok, data)
- case tok
- when '&', '|', '!', '!=', '!~'
- case @lex_state
- when EXPR_FNAME, EXPR_DOT
- @lex_state = EXPR_ARG
- else
- @lex_state = EXPR_BEG
- end
- when '<<'
- # TODO next token?
- case @lex_state
- when EXPR_FNAME, EXPR_DOT
- @lex_state = EXPR_ARG
- else
- @lex_state = EXPR_BEG
- end
- when '?'
- @lex_state = EXPR_BEG
- when '&&', '||', '+=', '-=', '*=', '**=',
- '&=', '|=', '^=', '<<=', '>>=', '||=', '&&='
- @lex_state = EXPR_BEG
- when '::'
- case @lex_state
- when EXPR_ARG, EXPR_CMDARG
- @lex_state = EXPR_DOT
- when EXPR_FNAME, EXPR_DOT
- @lex_state = EXPR_ARG
- else
- @lex_state = EXPR_BEG
- end
- else
- case @lex_state
- when EXPR_FNAME, EXPR_DOT
- @lex_state = EXPR_ARG
- else
- @lex_state = EXPR_BEG
- end
- end
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- end
-
- def on_kw(tok, data)
- case tok
- when 'class'
- @lex_state = EXPR_CLASS
- @in_fname = true
- when 'def'
- @lex_state = EXPR_FNAME
- @continue = true
- @in_fname = true
- when 'if', 'unless', 'while', 'until'
- if ((EXPR_MID | EXPR_END | EXPR_ENDARG | EXPR_ENDFN | EXPR_ARG | EXPR_CMDARG) & @lex_state) != 0 # postfix if
- @lex_state = EXPR_BEG | EXPR_LABEL
- else
- @lex_state = EXPR_BEG
- end
- when 'begin', 'case', 'when'
- @lex_state = EXPR_BEG
- when 'return', 'break'
- @lex_state = EXPR_MID
- else
- if @lex_state == EXPR_FNAME
- @lex_state = EXPR_END
- else
- @lex_state = EXPR_END
- end
- end
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- end
-
- def on_tstring_beg(tok, data)
- @lex_state = EXPR_BEG
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- end
-
- def on_tstring_end(tok, data)
- @lex_state = EXPR_END | EXPR_ENDARG
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- end
-
- def on_CHAR(tok, data)
- @lex_state = EXPR_END
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- end
-
- def on_period(tok, data)
- @lex_state = EXPR_DOT
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- end
-
- def on_int(tok, data)
- @lex_state = EXPR_END | EXPR_ENDARG
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- end
-
- def on_float(tok, data)
- @lex_state = EXPR_END | EXPR_ENDARG
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- end
-
- def on_rational(tok, data)
- @lex_state = EXPR_END | EXPR_ENDARG
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- end
-
- def on_imaginary(tok, data)
- @lex_state = EXPR_END | EXPR_ENDARG
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- end
-
- def on_symbeg(tok, data)
- @lex_state = EXPR_FNAME
- @continue = true
- @in_fname = true
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- end
-
- private def on_variables(event, tok, data)
- if @in_fname
- @lex_state = EXPR_ENDFN
- @in_fname = false
- @continue = false
- elsif @continue
- case @lex_state
- when EXPR_DOT
- @lex_state = EXPR_ARG
- else
- @lex_state = EXPR_ENDFN
- @continue = false
- end
- else
- @lex_state = EXPR_CMDARG
- end
- data << Token.new(lineno, column, event, tok, @lex_state)
- end
-
- def on_ident(tok, data)
- on_variables(__method__, tok, data)
- end
-
- def on_ivar(tok, data)
- @lex_state = EXPR_END
- on_variables(__method__, tok, data)
- end
-
- def on_cvar(tok, data)
- @lex_state = EXPR_END
- on_variables(__method__, tok, data)
- end
-
- def on_gvar(tok, data)
- @lex_state = EXPR_END
- on_variables(__method__, tok, data)
- end
-
- def on_backref(tok, data)
- @lex_state = EXPR_END
- on_variables(__method__, tok, data)
- end
-
- def on_lparen(tok, data)
- @lex_state = EXPR_LABEL | EXPR_BEG
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- end
-
- def on_rparen(tok, data)
- @lex_state = EXPR_ENDFN
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- end
-
- def on_lbrace(tok, data)
- @lex_state = EXPR_LABEL | EXPR_BEG
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- end
-
- def on_rbrace(tok, data)
- @lex_state = EXPR_ENDARG
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- end
-
- def on_lbracket(tok, data)
- @lex_state = EXPR_LABEL | EXPR_BEG
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- end
-
- def on_rbracket(tok, data)
- @lex_state = EXPR_ENDARG
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- end
-
- def on_const(tok, data)
- case @lex_state
- when EXPR_FNAME
- @lex_state = EXPR_ENDFN
- when EXPR_CLASS, EXPR_CMDARG, EXPR_MID
- @lex_state = EXPR_ARG
- else
- @lex_state = EXPR_CMDARG
- end
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- end
-
- def on_sp(tok, data)
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- end
-
- def on_comma(tok, data)
- @lex_state = EXPR_BEG | EXPR_LABEL if (EXPR_ARG_ANY & @lex_state) != 0
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- end
-
- def on_comment(tok, data)
- @lex_state = EXPR_BEG unless (EXPR_LABEL & @lex_state) != 0
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- end
-
- def on_ignored_sp(tok, data)
- @lex_state = EXPR_BEG unless (EXPR_LABEL & @lex_state) != 0
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- end
-
- def on_heredoc_beg(tok, data)
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- @lex_state = EXPR_END
- data
- end
-
- def on_heredoc_end(tok, data)
- data << Token.new(lineno, column, __method__, tok, @lex_state)
- @lex_state = EXPR_BEG
- data
- end
-
- def on_default(event, tok, data)
- reset
- data << Token.new(lineno, column, event, tok, @lex_state)
- end
- end unless RIPPER_HAS_LEX_STATE
-
- class InnerStateLex < Ripper::Filter
- def initialize(code)
- super(code)
- end
-
- def on_default(event, tok, data)
- data << Token.new(lineno, column, event, tok, state)
- end
- end if RIPPER_HAS_LEX_STATE
-
- def get_squashed_tk
- if @buf.empty?
- tk = @tokens.shift
- else
- tk = @buf.shift
- end
- return nil if tk.nil?
- case tk[:kind]
- when :on_symbeg then
- tk = get_symbol_tk(tk)
- when :on_tstring_beg then
- tk = get_string_tk(tk)
- when :on_backtick then
- if (tk[:state] & (EXPR_FNAME | EXPR_ENDFN)) != 0
- @inner_lex.lex_state = EXPR_ARG unless RIPPER_HAS_LEX_STATE
- tk[:kind] = :on_ident
- tk[:state] = Ripper::Lexer.const_defined?(:State) ? Ripper::Lexer::State.new(EXPR_ARG) : EXPR_ARG
- else
- tk = get_string_tk(tk)
- end
- when :on_regexp_beg then
- tk = get_regexp_tk(tk)
- when :on_embdoc_beg then
- tk = get_embdoc_tk(tk)
- when :on_heredoc_beg then
- @heredoc_queue << retrieve_heredoc_info(tk)
- @inner_lex.lex_state = EXPR_END unless RIPPER_HAS_LEX_STATE
- when :on_nl, :on_ignored_nl, :on_comment, :on_heredoc_end then
- if !@heredoc_queue.empty?
- get_heredoc_tk(*@heredoc_queue.shift)
- elsif tk[:text].nil? # :on_ignored_nl sometimes gives nil
- tk[:text] = ''
- end
- when :on_words_beg then
- tk = get_words_tk(tk)
- when :on_qwords_beg then
- tk = get_words_tk(tk)
- when :on_symbols_beg then
- tk = get_words_tk(tk)
- when :on_qsymbols_beg then
- tk = get_words_tk(tk)
- when :on_op then
- if '&.' == tk[:text]
- tk[:kind] = :on_period
- else
- tk = get_op_tk(tk)
- end
- end
- tk
- end
-
- private def get_symbol_tk(tk)
- is_symbol = true
- symbol_tk = Token.new(tk.line_no, tk.char_no, :on_symbol)
- if ":'" == tk[:text] or ':"' == tk[:text] or tk[:text].start_with?('%s')
- tk1 = get_string_tk(tk)
- symbol_tk[:text] = tk1[:text]
- symbol_tk[:state] = tk1[:state]
- else
- case (tk1 = get_squashed_tk)[:kind]
- when :on_ident
- symbol_tk[:text] = ":#{tk1[:text]}"
- symbol_tk[:state] = tk1[:state]
- when :on_tstring_content
- symbol_tk[:text] = ":#{tk1[:text]}"
- symbol_tk[:state] = get_squashed_tk[:state] # skip :on_tstring_end
- when :on_tstring_end
- symbol_tk[:text] = ":#{tk1[:text]}"
- symbol_tk[:state] = tk1[:state]
- when :on_op
- symbol_tk[:text] = ":#{tk1[:text]}"
- symbol_tk[:state] = tk1[:state]
- when :on_ivar
- symbol_tk[:text] = ":#{tk1[:text]}"
- symbol_tk[:state] = tk1[:state]
- when :on_cvar
- symbol_tk[:text] = ":#{tk1[:text]}"
- symbol_tk[:state] = tk1[:state]
- when :on_gvar
- symbol_tk[:text] = ":#{tk1[:text]}"
- symbol_tk[:state] = tk1[:state]
- when :on_const
- symbol_tk[:text] = ":#{tk1[:text]}"
- symbol_tk[:state] = tk1[:state]
- when :on_kw
- symbol_tk[:text] = ":#{tk1[:text]}"
- symbol_tk[:state] = tk1[:state]
- else
- is_symbol = false
- tk = tk1
- end
- end
- if is_symbol
- tk = symbol_tk
- end
- tk
- end
-
- private def get_string_tk(tk)
- string = tk[:text]
- state = nil
- kind = :on_tstring
- loop do
- inner_str_tk = get_squashed_tk
- if inner_str_tk.nil?
- break
- elsif :on_tstring_end == inner_str_tk[:kind]
- string = string + inner_str_tk[:text]
- state = inner_str_tk[:state]
- break
- elsif :on_label_end == inner_str_tk[:kind]
- string = string + inner_str_tk[:text]
- state = inner_str_tk[:state]
- kind = :on_symbol
- break
- else
- string = string + inner_str_tk[:text]
- if :on_embexpr_beg == inner_str_tk[:kind] then
- kind = :on_dstring if :on_tstring == kind
- end
- end
- end
- Token.new(tk.line_no, tk.char_no, kind, string, state)
- end
-
- private def get_regexp_tk(tk)
- string = tk[:text]
- state = nil
- loop do
- inner_str_tk = get_squashed_tk
- if inner_str_tk.nil?
- break
- elsif :on_regexp_end == inner_str_tk[:kind]
- string = string + inner_str_tk[:text]
- state = inner_str_tk[:state]
- break
- else
- string = string + inner_str_tk[:text]
- end
- end
- Token.new(tk.line_no, tk.char_no, :on_regexp, string, state)
- end
-
- private def get_embdoc_tk(tk)
- string = tk[:text]
- until :on_embdoc_end == (embdoc_tk = get_squashed_tk)[:kind] do
- string = string + embdoc_tk[:text]
- end
- string = string + embdoc_tk[:text]
- Token.new(tk.line_no, tk.char_no, :on_embdoc, string, embdoc_tk.state)
- end
-
- private def get_heredoc_tk(heredoc_name, indent)
- string = ''
- start_tk = nil
- prev_tk = nil
- until heredoc_end?(heredoc_name, indent, tk = @tokens.shift) do
- start_tk = tk unless start_tk
- if (prev_tk.nil? or "\n" == prev_tk[:text][-1]) and 0 != tk[:char_no]
- string = string + (' ' * tk[:char_no])
- end
- string = string + tk[:text]
- prev_tk = tk
- end
- start_tk = tk unless start_tk
- prev_tk = tk unless prev_tk
- @buf.unshift tk # closing heredoc
- heredoc_tk = Token.new(start_tk.line_no, start_tk.char_no, :on_heredoc, string, prev_tk.state)
- @buf.unshift heredoc_tk
- end
-
- private def retrieve_heredoc_info(tk)
- name = tk[:text].gsub(/\A<<[-~]?(['"`]?)(.+)\1\z/, '\2')
- indent = tk[:text] =~ /\A<<[-~]/
- [name, indent]
- end
-
- private def heredoc_end?(name, indent, tk)
- result = false
- if :on_heredoc_end == tk[:kind] then
- tk_name = tk[:text].chomp
- tk_name.lstrip! if indent
- if name == tk_name
- result = true
- end
- end
- result
- end
-
- private def get_words_tk(tk)
- string = ''
- start_token = tk[:text]
- start_quote = tk[:text].rstrip[-1]
- line_no = tk[:line_no]
- char_no = tk[:char_no]
- state = tk[:state]
- end_quote =
- case start_quote
- when ?( then ?)
- when ?[ then ?]
- when ?{ then ?}
- when ?< then ?>
- else start_quote
- end
- end_token = nil
- loop do
- tk = get_squashed_tk
- if tk.nil?
- end_token = end_quote
- break
- elsif :on_tstring_content == tk[:kind] then
- string += tk[:text]
- elsif :on_words_sep == tk[:kind] or :on_tstring_end == tk[:kind] then
- if end_quote == tk[:text].strip then
- end_token = tk[:text]
- break
- else
- string += tk[:text]
- end
- else
- string += tk[:text]
- end
- end
- text = "#{start_token}#{string}#{end_token}"
- Token.new(line_no, char_no, :on_dstring, text, state)
- end
-
- private def get_op_tk(tk)
- redefinable_operators = %w[! != !~ % & * ** + +@ - -@ / < << <= <=> == === =~ > >= >> [] []= ^ ` | ~]
- if redefinable_operators.include?(tk[:text]) and tk[:state] == EXPR_ARG then
- @inner_lex.lex_state = EXPR_ARG unless RIPPER_HAS_LEX_STATE
- tk[:state] = Ripper::Lexer.const_defined?(:State) ? Ripper::Lexer::State.new(EXPR_ARG) : EXPR_ARG
- tk[:kind] = :on_ident
- elsif tk[:text] =~ /^[-+]$/ then
- tk_ahead = get_squashed_tk
- case tk_ahead[:kind]
- when :on_int, :on_float, :on_rational, :on_imaginary then
- tk[:text] += tk_ahead[:text]
- tk[:kind] = tk_ahead[:kind]
- tk[:state] = tk_ahead[:state]
- when :on_heredoc_beg, :on_tstring, :on_dstring # frozen/non-frozen string literal
- tk[:text] += tk_ahead[:text]
- tk[:kind] = tk_ahead[:kind]
- tk[:state] = tk_ahead[:state]
- else
- @buf.unshift tk_ahead
- end
- end
- tk
- end
-
- # :startdoc:
-
- # New lexer for +code+.
- def initialize(code)
- @buf = []
- @heredoc_queue = []
- @inner_lex = InnerStateLex.new(code)
- @tokens = @inner_lex.parse([])
- end
-
- # Returns tokens parsed from +code+.
- def self.parse(code)
- lex = self.new(code)
- tokens = []
- begin
- while tk = lex.get_squashed_tk
- tokens.push tk
- end
- rescue StopIteration
- end
- tokens
- end
-
- # Returns +true+ if lex state will be +END+ after +token+.
- def self.end?(token)
- (token[:state] & EXPR_END)
- end
-end
diff --git a/lib/rdoc/parser/ruby.rb b/lib/rdoc/parser/ruby.rb
deleted file mode 100644
index 85f1cd0391..0000000000
--- a/lib/rdoc/parser/ruby.rb
+++ /dev/null
@@ -1,2372 +0,0 @@
-# frozen_string_literal: true
-##
-# This file contains stuff stolen outright from:
-#
-# rtags.rb -
-# ruby-lex.rb - ruby lexcal analyzer
-# ruby-token.rb - ruby tokens
-# by Keiju ISHITSUKA (Nippon Rational Inc.)
-#
-
-require 'ripper'
-require_relative 'ripper_state_lex'
-
-##
-# Extracts code elements from a source file returning a TopLevel object
-# containing the constituent file elements.
-#
-# This file is based on rtags
-#
-# RubyParser understands how to document:
-# * classes
-# * modules
-# * methods
-# * constants
-# * aliases
-# * private, public, protected
-# * private_class_function, public_class_function
-# * private_constant, public_constant
-# * module_function
-# * attr, attr_reader, attr_writer, attr_accessor
-# * extra accessors given on the command line
-# * metaprogrammed methods
-# * require
-# * include
-#
-# == Method Arguments
-#
-#--
-# NOTE: I don't think this works, needs tests, remove the paragraph following
-# this block when known to work
-#
-# The parser extracts the arguments from the method definition. You can
-# override this with a custom argument definition using the :args: directive:
-#
-# ##
-# # This method tries over and over until it is tired
-#
-# def go_go_go(thing_to_try, tries = 10) # :args: thing_to_try
-# puts thing_to_try
-# go_go_go thing_to_try, tries - 1
-# end
-#
-# If you have a more-complex set of overrides you can use the :call-seq:
-# directive:
-#++
-#
-# The parser extracts the arguments from the method definition. You can
-# override this with a custom argument definition using the :call-seq:
-# directive:
-#
-# ##
-# # This method can be called with a range or an offset and length
-# #
-# # :call-seq:
-# # my_method(Range)
-# # my_method(offset, length)
-#
-# def my_method(*args)
-# end
-#
-# The parser extracts +yield+ expressions from method bodies to gather the
-# yielded argument names. If your method manually calls a block instead of
-# yielding or you want to override the discovered argument names use
-# the :yields: directive:
-#
-# ##
-# # My method is awesome
-#
-# def my_method(&block) # :yields: happy, times
-# block.call 1, 2
-# end
-#
-# == Metaprogrammed Methods
-#
-# To pick up a metaprogrammed method, the parser looks for a comment starting
-# with '##' before an identifier:
-#
-# ##
-# # This is a meta-programmed method!
-#
-# add_my_method :meta_method, :arg1, :arg2
-#
-# The parser looks at the token after the identifier to determine the name, in
-# this example, :meta_method. If a name cannot be found, a warning is printed
-# and 'unknown is used.
-#
-# You can force the name of a method using the :method: directive:
-#
-# ##
-# # :method: some_method!
-#
-# By default, meta-methods are instance methods. To indicate that a method is
-# a singleton method instead use the :singleton-method: directive:
-#
-# ##
-# # :singleton-method:
-#
-# You can also use the :singleton-method: directive with a name:
-#
-# ##
-# # :singleton-method: some_method!
-#
-# You can define arguments for metaprogrammed methods via either the
-# :call-seq:, :arg: or :args: directives.
-#
-# Additionally you can mark a method as an attribute by
-# using :attr:, :attr_reader:, :attr_writer: or :attr_accessor:. Just like
-# for :method:, the name is optional.
-#
-# ##
-# # :attr_reader: my_attr_name
-#
-# == Hidden methods and attributes
-#
-# You can provide documentation for methods that don't appear using
-# the :method:, :singleton-method: and :attr: directives:
-#
-# ##
-# # :attr_writer: ghost_writer
-# # There is an attribute here, but you can't see it!
-#
-# ##
-# # :method: ghost_method
-# # There is a method here, but you can't see it!
-#
-# ##
-# # this is a comment for a regular method
-#
-# def regular_method() end
-#
-# Note that by default, the :method: directive will be ignored if there is a
-# standard rdocable item following it.
-
-class RDoc::Parser::Ruby < RDoc::Parser
-
- parse_files_matching(/\.rbw?$/)
-
- include RDoc::TokenStream
- include RDoc::Parser::RubyTools
-
- ##
- # RDoc::NormalClass type
-
- NORMAL = "::"
-
- ##
- # RDoc::SingleClass type
-
- SINGLE = "<<"
-
- ##
- # Creates a new Ruby parser.
-
- def initialize(top_level, file_name, content, options, stats)
- super
-
- content = handle_tab_width(content)
-
- @size = 0
- @token_listeners = nil
- content = RDoc::Encoding.remove_magic_comment content
- @scanner = RDoc::Parser::RipperStateLex.parse(content)
- @content = content
- @scanner_point = 0
- @prev_seek = nil
- @markup = @options.markup
- @track_visibility = :nodoc != @options.visibility
- @encoding = @options.encoding
-
- reset
- end
-
- ##
- # Return +true+ if +tk+ is a newline.
-
- def tk_nl?(tk)
- :on_nl == tk[:kind] or :on_ignored_nl == tk[:kind]
- end
-
- ##
- # Retrieves the read token stream and replaces +pattern+ with +replacement+
- # using gsub. If the result is only a ";" returns an empty string.
-
- def get_tkread_clean pattern, replacement # :nodoc:
- read = get_tkread.gsub(pattern, replacement).strip
- return '' if read == ';'
- read
- end
-
- ##
- # Extracts the visibility information for the visibility token +tk+
- # and +single+ class type identifier.
- #
- # Returns the visibility type (a string), the visibility (a symbol) and
- # +singleton+ if the methods following should be converted to singleton
- # methods.
-
- def get_visibility_information tk, single # :nodoc:
- vis_type = tk[:text]
- singleton = single == SINGLE
-
- vis =
- case vis_type
- when 'private' then :private
- when 'protected' then :protected
- when 'public' then :public
- when 'private_class_method' then
- singleton = true
- :private
- when 'public_class_method' then
- singleton = true
- :public
- when 'module_function' then
- singleton = true
- :public
- else
- raise RDoc::Error, "Invalid visibility: #{tk.name}"
- end
-
- return vis_type, vis, singleton
- end
-
- ##
- # Look for the first comment in a file that isn't a shebang line.
-
- def collect_first_comment
- skip_tkspace
- comment = ''.dup
- comment = RDoc::Encoding.change_encoding comment, @encoding if @encoding
- first_line = true
- first_comment_tk_kind = nil
- line_no = nil
-
- tk = get_tk
-
- while tk && (:on_comment == tk[:kind] or :on_embdoc == tk[:kind])
- comment_body = retrieve_comment_body(tk)
- if first_line and comment_body =~ /\A#!/ then
- skip_tkspace
- tk = get_tk
- elsif first_line and comment_body =~ /\A#\s*-\*-/ then
- first_line = false
- skip_tkspace
- tk = get_tk
- else
- break if first_comment_tk_kind and not first_comment_tk_kind === tk[:kind]
- first_comment_tk_kind = tk[:kind]
-
- line_no = tk[:line_no] if first_line
- first_line = false
- comment << comment_body
- tk = get_tk
-
- if :on_nl === tk then
- skip_tkspace_without_nl
- tk = get_tk
- end
- end
- end
-
- unget_tk tk
-
- new_comment comment, line_no
- end
-
- ##
- # Consumes trailing whitespace from the token stream
-
- def consume_trailing_spaces # :nodoc:
- skip_tkspace_without_nl
- end
-
- ##
- # Creates a new attribute in +container+ with +name+.
-
- def create_attr container, single, name, rw, comment # :nodoc:
- att = RDoc::Attr.new get_tkread, name, rw, comment, single == SINGLE
- record_location att
-
- container.add_attribute att
- @stats.add_attribute att
-
- att
- end
-
- ##
- # Creates a module alias in +container+ at +rhs_name+ (or at the top-level
- # for "::") with the name from +constant+.
-
- def create_module_alias container, constant, rhs_name # :nodoc:
- mod = if rhs_name =~ /^::/ then
- @store.find_class_or_module rhs_name
- else
- container.find_module_named rhs_name
- end
-
- container.add_module_alias mod, rhs_name, constant, @top_level
- end
-
- ##
- # Aborts with +msg+
-
- def error(msg)
- msg = make_message msg
-
- abort msg
- end
-
- ##
- # Looks for a true or false token.
-
- def get_bool
- skip_tkspace
- tk = get_tk
- if :on_kw == tk[:kind] && 'true' == tk[:text]
- true
- elsif :on_kw == tk[:kind] && ('false' == tk[:text] || 'nil' == tk[:text])
- false
- else
- unget_tk tk
- true
- end
- end
-
- ##
- # Look for the name of a class of module (optionally with a leading :: or
- # with :: separated named) and return the ultimate name, the associated
- # container, and the given name (with the ::).
-
- def get_class_or_module container, ignore_constants = false
- skip_tkspace
- name_t = get_tk
- given_name = ''.dup
-
- # class ::A -> A is in the top level
- if :on_op == name_t[:kind] and '::' == name_t[:text] then # bug
- name_t = get_tk
- container = @top_level
- given_name << '::'
- end
-
- skip_tkspace_without_nl
- given_name << name_t[:text]
-
- is_self = name_t[:kind] == :on_op && name_t[:text] == '<<'
- new_modules = []
- while !is_self && (tk = peek_tk) and :on_op == tk[:kind] and '::' == tk[:text] do
- prev_container = container
- container = container.find_module_named name_t[:text]
- container ||=
- if ignore_constants then
- c = RDoc::NormalModule.new name_t[:text]
- c.store = @store
- new_modules << [prev_container, c]
- c
- else
- c = prev_container.add_module RDoc::NormalModule, name_t[:text]
- c.ignore unless prev_container.document_children
- @top_level.add_to_classes_or_modules c
- c
- end
-
- record_location container
-
- get_tk
- skip_tkspace
- if :on_lparen == peek_tk[:kind] # ProcObjectInConstant::()
- parse_method_or_yield_parameters
- break
- end
- name_t = get_tk
- unless :on_const == name_t[:kind] || :on_ident == name_t[:kind]
- raise RDoc::Error, "Invalid class or module definition: #{given_name}"
- end
- if prev_container == container and !ignore_constants
- given_name = name_t[:text]
- else
- given_name << '::' + name_t[:text]
- end
- end
-
- skip_tkspace_without_nl
-
- return [container, name_t, given_name, new_modules]
- end
-
- ##
- # Skip opening parentheses and yield the block.
- # Skip closing parentheses too when exists.
-
- def skip_parentheses(&block)
- left_tk = peek_tk
-
- if :on_lparen == left_tk[:kind]
- get_tk
-
- ret = skip_parentheses(&block)
-
- right_tk = peek_tk
- if :on_rparen == right_tk[:kind]
- get_tk
- end
-
- ret
- else
- yield
- end
- end
-
- ##
- # Return a superclass, which can be either a constant of an expression
-
- def get_class_specification
- tk = peek_tk
- if tk.nil?
- return ''
- elsif :on_kw == tk[:kind] && 'self' == tk[:text]
- return 'self'
- elsif :on_gvar == tk[:kind]
- return ''
- end
-
- res = get_constant
-
- skip_tkspace_without_nl
-
- get_tkread # empty out read buffer
-
- tk = get_tk
- return res unless tk
-
- case tk[:kind]
- when :on_nl, :on_comment, :on_embdoc, :on_semicolon then
- unget_tk(tk)
- return res
- end
-
- res += parse_call_parameters(tk)
- res
- end
-
- ##
- # Parse a constant, which might be qualified by one or more class or module
- # names
-
- def get_constant
- res = ""
- skip_tkspace_without_nl
- tk = get_tk
-
- while tk && ((:on_op == tk[:kind] && '::' == tk[:text]) || :on_const == tk[:kind]) do
- res += tk[:text]
- tk = get_tk
- end
-
- unget_tk(tk)
- res
- end
-
- ##
- # Get an included module that may be surrounded by parens
-
- def get_included_module_with_optional_parens
- skip_tkspace_without_nl
- get_tkread
- tk = get_tk
- end_token = get_end_token tk
- return '' unless end_token
-
- nest = 0
- continue = false
- only_constant = true
-
- while tk != nil do
- is_element_of_constant = false
- case tk[:kind]
- when :on_semicolon then
- break if nest == 0
- when :on_lbracket then
- nest += 1
- when :on_rbracket then
- nest -= 1
- when :on_lbrace then
- nest += 1
- when :on_rbrace then
- nest -= 1
- if nest <= 0
- # we might have a.each { |i| yield i }
- unget_tk(tk) if nest < 0
- break
- end
- when :on_lparen then
- nest += 1
- when end_token[:kind] then
- if end_token[:kind] == :on_rparen
- nest -= 1
- break if nest <= 0
- else
- break if nest <= 0
- end
- when :on_rparen then
- nest -= 1
- when :on_comment, :on_embdoc then
- @read.pop
- if :on_nl == end_token[:kind] and "\n" == tk[:text][-1] and
- (!continue or (tk[:state] & RDoc::Parser::RipperStateLex::EXPR_LABEL) != 0) then
- break if !continue and nest <= 0
- end
- when :on_comma then
- continue = true
- when :on_ident then
- continue = false if continue
- when :on_kw then
- case tk[:text]
- when 'def', 'do', 'case', 'for', 'begin', 'class', 'module'
- nest += 1
- when 'if', 'unless', 'while', 'until', 'rescue'
- # postfix if/unless/while/until/rescue must be EXPR_LABEL
- nest += 1 unless (tk[:state] & RDoc::Parser::RipperStateLex::EXPR_LABEL) != 0
- when 'end'
- nest -= 1
- break if nest == 0
- end
- when :on_const then
- is_element_of_constant = true
- when :on_op then
- is_element_of_constant = true if '::' == tk[:text]
- end
- only_constant = false unless is_element_of_constant
- tk = get_tk
- end
-
- if only_constant
- get_tkread_clean(/\s+/, ' ')
- else
- ''
- end
- end
-
- ##
- # Little hack going on here. In the statement:
- #
- # f = 2*(1+yield)
- #
- # We see the RPAREN as the next token, so we need to exit early. This still
- # won't catch all cases (such as "a = yield + 1"
-
- def get_end_token tk # :nodoc:
- case tk[:kind]
- when :on_lparen
- token = RDoc::Parser::RipperStateLex::Token.new
- token[:kind] = :on_rparen
- token[:text] = ')'
- token
- when :on_rparen
- nil
- else
- token = RDoc::Parser::RipperStateLex::Token.new
- token[:kind] = :on_nl
- token[:text] = "\n"
- token
- end
- end
-
- ##
- # Retrieves the method container for a singleton method.
-
- def get_method_container container, name_t # :nodoc:
- prev_container = container
- container = container.find_module_named(name_t[:text])
-
- unless container then
- constant = prev_container.constants.find do |const|
- const.name == name_t[:text]
- end
-
- if constant then
- parse_method_dummy prev_container
- return
- end
- end
-
- unless container then
- # TODO seems broken, should starting at Object in @store
- obj = name_t[:text].split("::").inject(Object) do |state, item|
- state.const_get(item)
- end rescue nil
-
- type = obj.class == Class ? RDoc::NormalClass : RDoc::NormalModule
-
- unless [Class, Module].include?(obj.class) then
- warn("Couldn't find #{name_t[:text]}. Assuming it's a module")
- end
-
- if type == RDoc::NormalClass then
- sclass = obj.superclass ? obj.superclass.name : nil
- container = prev_container.add_class type, name_t[:text], sclass
- else
- container = prev_container.add_module type, name_t[:text]
- end
-
- record_location container
- end
-
- container
- end
-
- ##
- # Extracts a name or symbol from the token stream.
-
- def get_symbol_or_name
- tk = get_tk
- case tk[:kind]
- when :on_symbol then
- text = tk[:text].sub(/^:/, '')
-
- next_tk = peek_tk
- if next_tk && :on_op == next_tk[:kind] && '=' == next_tk[:text] then
- get_tk
- text << '='
- end
-
- text
- when :on_ident, :on_const, :on_gvar, :on_cvar, :on_ivar, :on_op, :on_kw then
- tk[:text]
- when :on_tstring, :on_dstring then
- tk[:text][1..-2]
- else
- raise RDoc::Error, "Name or symbol expected (got #{tk})"
- end
- end
-
- ##
- # Marks containers between +container+ and +ancestor+ as ignored
-
- def suppress_parents container, ancestor # :nodoc:
- while container and container != ancestor do
- container.suppress unless container.documented?
- container = container.parent
- end
- end
-
- ##
- # Look for directives in a normal comment block:
- #
- # # :stopdoc:
- # # Don't display comment from this point forward
- #
- # This routine modifies its +comment+ parameter.
-
- def look_for_directives_in container, comment
- @preprocess.handle comment, container do |directive, param|
- case directive
- when 'method', 'singleton-method',
- 'attr', 'attr_accessor', 'attr_reader', 'attr_writer' then
- false # handled elsewhere
- when 'section' then
- break unless container.kind_of?(RDoc::Context)
- container.set_current_section param, comment.dup
- comment.text = ''
- break
- end
- end
-
- comment.remove_private
- end
-
- ##
- # Adds useful info about the parser to +message+
-
- def make_message message
- prefix = "#{@file_name}:".dup
-
- tk = peek_tk
- prefix << "#{tk[:line_no]}:#{tk[:char_no]}:" if tk
-
- "#{prefix} #{message}"
- end
-
- ##
- # Creates a comment with the correct format
-
- def new_comment comment, line_no = nil
- c = RDoc::Comment.new comment, @top_level, :ruby
- c.line = line_no
- c.format = @markup
- c
- end
-
- ##
- # Creates an RDoc::Attr for the name following +tk+, setting the comment to
- # +comment+.
-
- def parse_attr(context, single, tk, comment)
- line_no = tk[:line_no]
-
- args = parse_symbol_arg 1
- if args.size > 0 then
- name = args[0]
- rw = "R"
- skip_tkspace_without_nl
- tk = get_tk
-
- if :on_comma == tk[:kind] then
- rw = "RW" if get_bool
- else
- unget_tk tk
- end
-
- att = create_attr context, single, name, rw, comment
- att.line = line_no
-
- read_documentation_modifiers att, RDoc::ATTR_MODIFIERS
- else
- warn "'attr' ignored - looks like a variable"
- end
- end
-
- ##
- # Creates an RDoc::Attr for each attribute listed after +tk+, setting the
- # comment for each to +comment+.
-
- def parse_attr_accessor(context, single, tk, comment)
- line_no = tk[:line_no]
-
- args = parse_symbol_arg
- rw = "?"
-
- tmp = RDoc::CodeObject.new
- read_documentation_modifiers tmp, RDoc::ATTR_MODIFIERS
- # TODO In most other places we let the context keep track of document_self
- # and add found items appropriately but here we do not. I'm not sure why.
- return if @track_visibility and not tmp.document_self
-
- case tk[:text]
- when "attr_reader" then rw = "R"
- when "attr_writer" then rw = "W"
- when "attr_accessor" then rw = "RW"
- else
- rw = '?'
- end
-
- for name in args
- att = create_attr context, single, name, rw, comment
- att.line = line_no
- end
- end
-
- ##
- # Parses an +alias+ in +context+ with +comment+
-
- def parse_alias(context, single, tk, comment)
- line_no = tk[:line_no]
-
- skip_tkspace
-
- if :on_lparen === peek_tk[:kind] then
- get_tk
- skip_tkspace
- end
-
- new_name = get_symbol_or_name
-
- skip_tkspace
- if :on_comma === peek_tk[:kind] then
- get_tk
- skip_tkspace
- end
-
- begin
- old_name = get_symbol_or_name
- rescue RDoc::Error
- return
- end
-
- al = RDoc::Alias.new(get_tkread, old_name, new_name, comment,
- single == SINGLE)
- record_location al
- al.line = line_no
-
- read_documentation_modifiers al, RDoc::ATTR_MODIFIERS
- if al.document_self or not @track_visibility
- context.add_alias al
- @stats.add_alias al
- end
-
- al
- end
-
- ##
- # Extracts call parameters from the token stream.
-
- def parse_call_parameters(tk)
- end_token = case tk[:kind]
- when :on_lparen
- :on_rparen
- when :on_rparen
- return ""
- else
- :on_nl
- end
- nest = 0
-
- loop do
- break if tk.nil?
- case tk[:kind]
- when :on_semicolon
- break
- when :on_lparen
- nest += 1
- when end_token
- if end_token == :on_rparen
- nest -= 1
- break if RDoc::Parser::RipperStateLex.end?(tk) and nest <= 0
- else
- break if RDoc::Parser::RipperStateLex.end?(tk)
- end
- when :on_comment, :on_embdoc
- unget_tk(tk)
- break
- when :on_op
- if tk[:text] =~ /^(.{1,2})?=$/
- unget_tk(tk)
- break
- end
- end
- tk = get_tk
- end
-
- get_tkread_clean "\n", " "
- end
-
- ##
- # Parses a class in +context+ with +comment+
-
- def parse_class container, single, tk, comment
- line_no = tk[:line_no]
-
- declaration_context = container
- container, name_t, given_name, = get_class_or_module container
-
- if name_t[:kind] == :on_const
- cls = parse_class_regular container, declaration_context, single,
- name_t, given_name, comment
- elsif name_t[:kind] == :on_op && name_t[:text] == '<<'
- case name = skip_parentheses { get_class_specification }
- when 'self', container.name
- read_documentation_modifiers cls, RDoc::CLASS_MODIFIERS
- parse_statements container, SINGLE
- return # don't update line
- else
- cls = parse_class_singleton container, name, comment
- end
- else
- warn "Expected class name or '<<'. Got #{name_t[:kind]}: #{name_t[:text].inspect}"
- return
- end
-
- cls.line = line_no
-
- # after end modifiers
- read_documentation_modifiers cls, RDoc::CLASS_MODIFIERS
-
- cls
- end
-
- ##
- # Parses and creates a regular class
-
- def parse_class_regular container, declaration_context, single, # :nodoc:
- name_t, given_name, comment
- superclass = '::Object'
-
- if given_name =~ /^::/ then
- declaration_context = @top_level
- given_name = $'
- end
-
- tk = peek_tk
- if tk[:kind] == :on_op && tk[:text] == '<' then
- get_tk
- skip_tkspace
- superclass = get_class_specification
- superclass = '(unknown)' if superclass.empty?
- end
-
- cls_type = single == SINGLE ? RDoc::SingleClass : RDoc::NormalClass
- cls = declaration_context.add_class cls_type, given_name, superclass
- cls.ignore unless container.document_children
-
- read_documentation_modifiers cls, RDoc::CLASS_MODIFIERS
- record_location cls
-
- cls.add_comment comment, @top_level
-
- @top_level.add_to_classes_or_modules cls
- @stats.add_class cls
-
- suppress_parents container, declaration_context unless cls.document_self
-
- parse_statements cls
-
- cls
- end
-
- ##
- # Parses a singleton class in +container+ with the given +name+ and
- # +comment+.
-
- def parse_class_singleton container, name, comment # :nodoc:
- other = @store.find_class_named name
-
- unless other then
- if name =~ /^::/ then
- name = $'
- container = @top_level
- end
-
- other = container.add_module RDoc::NormalModule, name
- record_location other
-
- # class << $gvar
- other.ignore if name.empty?
-
- other.add_comment comment, @top_level
- end
-
- # notify :nodoc: all if not a constant-named class/module
- # (and remove any comment)
- unless name =~ /\A(::)?[A-Z]/ then
- other.document_self = nil
- other.document_children = false
- other.clear_comment
- end
-
- @top_level.add_to_classes_or_modules other
- @stats.add_class other
-
- read_documentation_modifiers other, RDoc::CLASS_MODIFIERS
- parse_statements(other, SINGLE)
-
- other
- end
-
- ##
- # Parses a constant in +context+ with +comment+. If +ignore_constants+ is
- # true, no found constants will be added to RDoc.
-
- def parse_constant container, tk, comment, ignore_constants = false
- line_no = tk[:line_no]
-
- name = tk[:text]
- skip_tkspace_without_nl
-
- return unless name =~ /^\w+$/
-
- new_modules = []
- if :on_op == peek_tk[:kind] && '::' == peek_tk[:text] then
- unget_tk tk
-
- container, name_t, _, new_modules = get_class_or_module container, true
-
- name = name_t[:text]
- end
-
- is_array_or_hash = false
- if peek_tk && :on_lbracket == peek_tk[:kind]
- get_tk
- nest = 1
- while bracket_tk = get_tk
- case bracket_tk[:kind]
- when :on_lbracket
- nest += 1
- when :on_rbracket
- nest -= 1
- break if nest == 0
- end
- end
- skip_tkspace_without_nl
- is_array_or_hash = true
- end
-
- unless peek_tk && :on_op == peek_tk[:kind] && '=' == peek_tk[:text] then
- return false
- end
- get_tk
-
- unless ignore_constants
- new_modules.each do |prev_c, new_module|
- prev_c.add_module_by_normal_module new_module
- new_module.ignore unless prev_c.document_children
- @top_level.add_to_classes_or_modules new_module
- end
- end
-
- value = ''
- con = RDoc::Constant.new name, value, comment
-
- body = parse_constant_body container, con, is_array_or_hash
-
- return unless body
-
- con.value = body
- record_location con
- con.line = line_no
- read_documentation_modifiers con, RDoc::CONSTANT_MODIFIERS
-
- return if is_array_or_hash
-
- @stats.add_constant con
- container.add_constant con
-
- true
- end
-
- def parse_constant_body container, constant, is_array_or_hash # :nodoc:
- nest = 0
- rhs_name = ''.dup
-
- get_tkread
-
- tk = get_tk
-
- body = nil
- loop do
- break if tk.nil?
- if :on_semicolon == tk[:kind] then
- break if nest <= 0
- elsif [:on_tlambeg, :on_lparen, :on_lbrace, :on_lbracket].include?(tk[:kind]) then
- nest += 1
- elsif (:on_kw == tk[:kind] && 'def' == tk[:text]) then
- nest += 1
- elsif (:on_kw == tk[:kind] && %w{do if unless case begin}.include?(tk[:text])) then
- if (tk[:state] & RDoc::Parser::RipperStateLex::EXPR_LABEL) == 0
- nest += 1
- end
- elsif [:on_rparen, :on_rbrace, :on_rbracket].include?(tk[:kind]) ||
- (:on_kw == tk[:kind] && 'end' == tk[:text]) then
- nest -= 1
- elsif (:on_comment == tk[:kind] or :on_embdoc == tk[:kind]) then
- unget_tk tk
- if nest <= 0 and RDoc::Parser::RipperStateLex.end?(tk) then
- body = get_tkread_clean(/^[ \t]+/, '')
- read_documentation_modifiers constant, RDoc::CONSTANT_MODIFIERS
- break
- else
- read_documentation_modifiers constant, RDoc::CONSTANT_MODIFIERS
- end
- elsif :on_const == tk[:kind] then
- rhs_name << tk[:text]
-
- next_tk = peek_tk
- if nest <= 0 and (next_tk.nil? || :on_nl == next_tk[:kind]) then
- create_module_alias container, constant, rhs_name unless is_array_or_hash
- break
- end
- elsif :on_nl == tk[:kind] then
- if nest <= 0 and RDoc::Parser::RipperStateLex.end?(tk) then
- unget_tk tk
- break
- end
- elsif :on_op == tk[:kind] && '::' == tk[:text]
- rhs_name << '::'
- end
- tk = get_tk
- end
-
- body ? body : get_tkread_clean(/^[ \t]+/, '')
- end
-
- ##
- # Generates an RDoc::Method or RDoc::Attr from +comment+ by looking for
- # :method: or :attr: directives in +comment+.
-
- def parse_comment container, tk, comment
- return parse_comment_tomdoc container, tk, comment if @markup == 'tomdoc'
- column = tk[:char_no]
- line_no = comment.line.nil? ? tk[:line_no] : comment.line
-
- comment.text = comment.text.sub(/(^# +:?)(singleton-)(method:)/, '\1\3')
- singleton = !!$~
-
- co =
- if (comment.text = comment.text.sub(/^# +:?method: *(\S*).*?\n/i, '')) && !!$~ then
- line_no += $`.count("\n")
- parse_comment_ghost container, comment.text, $1, column, line_no, comment
- elsif (comment.text = comment.text.sub(/# +:?(attr(_reader|_writer|_accessor)?): *(\S*).*?\n/i, '')) && !!$~ then
- parse_comment_attr container, $1, $3, comment
- end
-
- if co then
- co.singleton = singleton
- co.line = line_no
- end
-
- true
- end
-
- ##
- # Parse a comment that is describing an attribute in +container+ with the
- # given +name+ and +comment+.
-
- def parse_comment_attr container, type, name, comment # :nodoc:
- return if name.empty?
-
- rw = case type
- when 'attr_reader' then 'R'
- when 'attr_writer' then 'W'
- else 'RW'
- end
-
- create_attr container, NORMAL, name, rw, comment
- end
-
- def parse_comment_ghost container, text, name, column, line_no, # :nodoc:
- comment
- name = nil if name.empty?
-
- meth = RDoc::GhostMethod.new get_tkread, name
- record_location meth
-
- meth.start_collecting_tokens
- indent = RDoc::Parser::RipperStateLex::Token.new(1, 1, :on_sp, ' ' * column)
- position_comment = RDoc::Parser::RipperStateLex::Token.new(line_no, 1, :on_comment)
- position_comment[:text] = "# File #{@top_level.relative_name}, line #{line_no}"
- newline = RDoc::Parser::RipperStateLex::Token.new(0, 0, :on_nl, "\n")
- meth.add_tokens [position_comment, newline, indent]
-
- meth.params =
- if text.sub!(/^#\s+:?args?:\s*(.*?)\s*$/i, '') then
- $1
- else
- ''
- end
-
- comment.normalize
- comment.extract_call_seq meth
-
- return unless meth.name
-
- container.add_method meth
-
- meth.comment = comment
-
- @stats.add_method meth
-
- meth
- end
-
- ##
- # Creates an RDoc::Method on +container+ from +comment+ if there is a
- # Signature section in the comment
-
- def parse_comment_tomdoc container, tk, comment
- return unless signature = RDoc::TomDoc.signature(comment)
- column = tk[:char_no]
- line_no = tk[:line_no]
-
- name, = signature.split %r%[ \(]%, 2
-
- meth = RDoc::GhostMethod.new get_tkread, name
- record_location meth
- meth.line = line_no
-
- meth.start_collecting_tokens
- indent = RDoc::Parser::RipperStateLex::Token.new(1, 1, :on_sp, ' ' * column)
- position_comment = RDoc::Parser::RipperStateLex::Token.new(line_no, 1, :on_comment)
- position_comment[:text] = "# File #{@top_level.relative_name}, line #{line_no}"
- newline = RDoc::Parser::RipperStateLex::Token.new(0, 0, :on_nl, "\n")
- meth.add_tokens [position_comment, newline, indent]
-
- meth.call_seq = signature
-
- comment.normalize
-
- return unless meth.name
-
- container.add_method meth
-
- meth.comment = comment
-
- @stats.add_method meth
- end
-
- ##
- # Parses an +include+ or +extend+, indicated by the +klass+ and adds it to
- # +container+ # with +comment+
-
- def parse_extend_or_include klass, container, comment # :nodoc:
- loop do
- skip_tkspace_comment
-
- name = get_included_module_with_optional_parens
-
- unless name.empty? then
- obj = container.add klass, name, comment
- record_location obj
- end
-
- return if peek_tk.nil? || :on_comma != peek_tk[:kind]
-
- get_tk
- 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.
- #
- # Returns true if the comment was not consumed.
-
- def parse_identifier container, single, tk, comment # :nodoc:
- case tk[:text]
- when 'private', 'protected', 'public', 'private_class_method',
- 'public_class_method', 'module_function' then
- parse_visibility container, single, tk
- return true
- when 'private_constant', 'public_constant'
- parse_constant_visibility container, single, tk
- return true
- when 'attr' then
- parse_attr container, single, tk, comment
- when /^attr_(reader|writer|accessor)$/ then
- parse_attr_accessor container, single, tk, comment
- when 'alias_method' then
- parse_alias container, single, tk, comment
- when 'require', 'include' then
- # ignore
- else
- if comment.text =~ /\A#\#$/ then
- case comment.text
- when /^# +:?attr(_reader|_writer|_accessor)?:/ then
- parse_meta_attr container, single, tk, comment
- else
- method = parse_meta_method container, single, tk, comment
- method.params = container.params if
- container.params
- method.block_params = container.block_params if
- container.block_params
- end
- end
- end
-
- false
- end
-
- ##
- # Parses a meta-programmed attribute and creates an RDoc::Attr.
- #
- # To create foo and bar attributes on class C with comment "My attributes":
- #
- # class C
- #
- # ##
- # # :attr:
- # #
- # # My attributes
- #
- # my_attr :foo, :bar
- #
- # end
- #
- # To create a foo attribute on class C with comment "My attribute":
- #
- # class C
- #
- # ##
- # # :attr: foo
- # #
- # # My attribute
- #
- # my_attr :foo, :bar
- #
- # end
-
- def parse_meta_attr(context, single, tk, comment)
- args = parse_symbol_arg
- rw = "?"
-
- # If nodoc is given, don't document any of them
-
- tmp = RDoc::CodeObject.new
- read_documentation_modifiers tmp, RDoc::ATTR_MODIFIERS
-
- regexp = /^# +:?(attr(_reader|_writer|_accessor)?): *(\S*).*?\n/i
- if regexp =~ comment.text then
- comment.text = comment.text.sub(regexp, '')
- rw = case $1
- when 'attr_reader' then 'R'
- when 'attr_writer' then 'W'
- else 'RW'
- end
- name = $3 unless $3.empty?
- end
-
- if name then
- att = create_attr context, single, name, rw, comment
- else
- args.each do |attr_name|
- att = create_attr context, single, attr_name, rw, comment
- end
- end
-
- att
- end
-
- ##
- # Parses a meta-programmed method
-
- def parse_meta_method(container, single, tk, comment)
- column = tk[:char_no]
- line_no = tk[:line_no]
-
- start_collecting_tokens
- add_token tk
- add_token_listener self
-
- skip_tkspace_without_nl
-
- comment.text = comment.text.sub(/(^# +:?)(singleton-)(method:)/, '\1\3')
- singleton = !!$~
-
- name = parse_meta_method_name comment, tk
-
- return unless name
-
- meth = RDoc::MetaMethod.new get_tkread, name
- record_location meth
- meth.line = line_no
- meth.singleton = singleton
-
- remove_token_listener self
-
- meth.start_collecting_tokens
- indent = RDoc::Parser::RipperStateLex::Token.new(1, 1, :on_sp, ' ' * column)
- position_comment = RDoc::Parser::RipperStateLex::Token.new(line_no, 1, :on_comment)
- position_comment[:text] = "# File #{@top_level.relative_name}, line #{line_no}"
- newline = RDoc::Parser::RipperStateLex::Token.new(0, 0, :on_nl, "\n")
- meth.add_tokens [position_comment, newline, indent]
- meth.add_tokens @token_stream
-
- parse_meta_method_params container, single, meth, tk, comment
-
- meth.comment = comment
-
- @stats.add_method meth
-
- meth
- end
-
- ##
- # Parses the name of a metaprogrammed method. +comment+ is used to
- # determine the name while +tk+ is used in an error message if the name
- # cannot be determined.
-
- def parse_meta_method_name comment, tk # :nodoc:
- if comment.text.sub!(/^# +:?method: *(\S*).*?\n/i, '') then
- return $1 unless $1.empty?
- end
-
- name_t = get_tk
-
- if :on_symbol == name_t[:kind] then
- name_t[:text][1..-1]
- elsif :on_tstring == name_t[:kind] then
- name_t[:text][1..-2]
- elsif :on_op == name_t[:kind] && '=' == name_t[:text] then # ignore
- remove_token_listener self
-
- nil
- else
- warn "unknown name token #{name_t.inspect} for meta-method '#{tk[:text]}'"
- 'unknown'
- end
- end
-
- ##
- # Parses the parameters and block for a meta-programmed method.
-
- def parse_meta_method_params container, single, meth, tk, comment # :nodoc:
- token_listener meth do
- meth.params = ''
-
- look_for_directives_in meth, comment
- comment.normalize
- comment.extract_call_seq meth
-
- container.add_method meth
-
- last_tk = tk
-
- while tk = get_tk do
- if :on_semicolon == tk[:kind] then
- break
- elsif :on_nl == tk[:kind] then
- break unless last_tk and :on_comma == last_tk[:kind]
- elsif :on_sp == tk[:kind] then
- # expression continues
- elsif :on_kw == tk[:kind] && 'do' == tk[:text] then
- parse_statements container, single, meth
- break
- else
- last_tk = tk
- end
- end
- end
- end
-
- ##
- # Parses a normal method defined by +def+
-
- def parse_method(container, single, tk, comment)
- singleton = nil
- added_container = false
- name = nil
- column = tk[:char_no]
- line_no = tk[:line_no]
-
- start_collecting_tokens
- add_token tk
-
- token_listener self do
- prev_container = container
- name, container, singleton = parse_method_name container
- added_container = container != prev_container
- end
-
- return unless name
-
- meth = RDoc::AnyMethod.new get_tkread, name
- look_for_directives_in meth, comment
- meth.singleton = single == SINGLE ? true : singleton
- if singleton
- # `current_line_visibility' is useless because it works against
- # the normal method named as same as the singleton method, after
- # the latter was defined. Of course these are different things.
- container.current_line_visibility = :public
- end
-
- record_location meth
- meth.line = line_no
-
- meth.start_collecting_tokens
- indent = RDoc::Parser::RipperStateLex::Token.new(1, 1, :on_sp, ' ' * column)
- token = RDoc::Parser::RipperStateLex::Token.new(line_no, 1, :on_comment)
- token[:text] = "# File #{@top_level.relative_name}, line #{line_no}"
- newline = RDoc::Parser::RipperStateLex::Token.new(0, 0, :on_nl, "\n")
- meth.add_tokens [token, newline, indent]
- meth.add_tokens @token_stream
-
- parse_method_params_and_body container, single, meth, added_container
-
- comment.normalize
- comment.extract_call_seq meth
-
- meth.comment = comment
-
- # after end modifiers
- read_documentation_modifiers meth, RDoc::METHOD_MODIFIERS
-
- @stats.add_method meth
- end
-
- ##
- # Parses the parameters and body of +meth+
-
- def parse_method_params_and_body container, single, meth, added_container
- token_listener meth do
- parse_method_parameters meth
-
- if meth.document_self or not @track_visibility then
- container.add_method meth
- elsif added_container then
- container.document_self = false
- end
-
- # Having now read the method parameters and documentation modifiers, we
- # now know whether we have to rename #initialize to ::new
-
- if meth.name == "initialize" && !meth.singleton then
- if meth.dont_rename_initialize then
- meth.visibility = :protected
- else
- meth.singleton = true
- meth.name = "new"
- meth.visibility = :public
- end
- end
-
- parse_statements container, single, meth
- end
- end
-
- ##
- # Parses a method that needs to be ignored.
-
- def parse_method_dummy container
- dummy = RDoc::Context.new
- dummy.parent = container
- dummy.store = container.store
- skip_method dummy
- end
-
- ##
- # Parses the name of a method in +container+.
- #
- # Returns the method name, the container it is in (for def Foo.name) and if
- # it is a singleton or regular method.
-
- def parse_method_name container # :nodoc:
- skip_tkspace
- name_t = get_tk
- back_tk = skip_tkspace_without_nl
- singleton = false
-
- dot = get_tk
- if dot[:kind] == :on_period || (dot[:kind] == :on_op && dot[:text] == '::') then
- singleton = true
-
- name, container = parse_method_name_singleton container, name_t
- else
- unget_tk dot
- back_tk.reverse_each do |token|
- unget_tk token
- end
-
- name = parse_method_name_regular container, name_t
- end
-
- return name, container, singleton
- end
-
- ##
- # For the given +container+ and initial name token +name_t+ the method name
- # is parsed from the token stream for a regular method.
-
- def parse_method_name_regular container, name_t # :nodoc:
- if :on_op == name_t[:kind] && (%w{* & [] []= <<}.include?(name_t[:text])) then
- name_t[:text]
- else
- unless [:on_kw, :on_const, :on_ident].include?(name_t[:kind]) then
- warn "expected method name token, . or ::, got #{name_t.inspect}"
- skip_method container
- return
- end
- name_t[:text]
- end
- end
-
- ##
- # For the given +container+ and initial name token +name_t+ the method name
- # and the new +container+ (if necessary) are parsed from the token stream
- # for a singleton method.
-
- def parse_method_name_singleton container, name_t # :nodoc:
- skip_tkspace
- name_t2 = get_tk
-
- if (:on_kw == name_t[:kind] && 'self' == name_t[:text]) || (:on_op == name_t[:kind] && '%' == name_t[:text]) then
- # NOTE: work around '[' being consumed early
- if :on_lbracket == name_t2[:kind]
- get_tk
- name = '[]'
- else
- name = name_t2[:text]
- end
- elsif :on_const == name_t[:kind] then
- name = name_t2[:text]
-
- container = get_method_container container, name_t
-
- return unless container
-
- name
- elsif :on_ident == name_t[:kind] || :on_ivar == name_t[:kind] || :on_gvar == name_t[:kind] then
- parse_method_dummy container
-
- name = nil
- elsif (:on_kw == name_t[:kind]) && ('true' == name_t[:text] || 'false' == name_t[:text] || 'nil' == name_t[:text]) then
- klass_name = "#{name_t[:text].capitalize}Class"
- container = @store.find_class_named klass_name
- container ||= @top_level.add_class RDoc::NormalClass, klass_name
-
- name = name_t2[:text]
- else
- warn "unexpected method name token #{name_t.inspect}"
- # break
- skip_method container
-
- name = nil
- end
-
- return name, container
- end
-
- ##
- # Extracts +yield+ parameters from +method+
-
- def parse_method_or_yield_parameters(method = nil,
- modifiers = RDoc::METHOD_MODIFIERS)
- skip_tkspace_without_nl
- tk = get_tk
- end_token = get_end_token tk
- return '' unless end_token
-
- nest = 0
- continue = false
-
- while tk != nil do
- case tk[:kind]
- when :on_semicolon then
- break if nest == 0
- when :on_lbracket then
- nest += 1
- when :on_rbracket then
- nest -= 1
- when :on_lbrace then
- nest += 1
- when :on_rbrace then
- nest -= 1
- if nest <= 0
- # we might have a.each { |i| yield i }
- unget_tk(tk) if nest < 0
- break
- end
- when :on_lparen then
- nest += 1
- when end_token[:kind] then
- if end_token[:kind] == :on_rparen
- nest -= 1
- break if nest <= 0
- else
- break
- end
- when :on_rparen then
- nest -= 1
- when :on_comment, :on_embdoc then
- @read.pop
- if :on_nl == end_token[:kind] and "\n" == tk[:text][-1] and
- (!continue or (tk[:state] & RDoc::Parser::RipperStateLex::EXPR_LABEL) != 0) then
- if method && method.block_params.nil? then
- unget_tk tk
- read_documentation_modifiers method, modifiers
- end
- break if !continue and nest <= 0
- end
- when :on_comma then
- continue = true
- when :on_ident then
- continue = false if continue
- end
- tk = get_tk
- end
-
- get_tkread_clean(/\s+/, ' ')
- end
-
- ##
- # Capture the method's parameters. Along the way, look for a comment
- # containing:
- #
- # # yields: ....
- #
- # and add this as the block_params for the method
-
- def parse_method_parameters method
- res = parse_method_or_yield_parameters method
-
- res = "(#{res})" unless res =~ /\A\(/
- method.params = res unless method.params
-
- return if method.block_params
-
- skip_tkspace_without_nl
- read_documentation_modifiers method, RDoc::METHOD_MODIFIERS
- end
-
- ##
- # Parses an RDoc::NormalModule in +container+ with +comment+
-
- def parse_module container, single, tk, comment
- container, name_t, = get_class_or_module container
-
- name = name_t[:text]
-
- mod = container.add_module RDoc::NormalModule, name
- mod.ignore unless container.document_children
- record_location mod
-
- read_documentation_modifiers mod, RDoc::CLASS_MODIFIERS
- mod.add_comment comment, @top_level
- parse_statements mod
-
- # after end modifiers
- read_documentation_modifiers mod, RDoc::CLASS_MODIFIERS
-
- @stats.add_module mod
- end
-
- ##
- # Parses an RDoc::Require in +context+ containing +comment+
-
- def parse_require(context, comment)
- skip_tkspace_comment
- tk = get_tk
-
- if :on_lparen == tk[:kind] then
- skip_tkspace_comment
- tk = get_tk
- end
-
- name = tk[:text][1..-2] if :on_tstring == tk[:kind]
-
- if name then
- @top_level.add_require RDoc::Require.new(name, comment)
- else
- unget_tk tk
- end
- end
-
- ##
- # Parses a rescue
-
- def parse_rescue
- skip_tkspace_without_nl
-
- while tk = get_tk
- case tk[:kind]
- when :on_nl, :on_semicolon, :on_comment then
- break
- when :on_comma then
- skip_tkspace_without_nl
-
- get_tk if :on_nl == peek_tk[:kind]
- end
-
- skip_tkspace_without_nl
- end
- end
-
- ##
- # Retrieve comment body without =begin/=end
-
- def retrieve_comment_body(tk)
- if :on_embdoc == tk[:kind]
- tk[:text].gsub(/\A=begin.*\n/, '').gsub(/=end\n?\z/, '')
- else
- tk[:text]
- end
- end
-
- ##
- # The core of the Ruby parser.
-
- def parse_statements(container, single = NORMAL, current_method = nil,
- comment = new_comment(''))
- raise 'no' unless RDoc::Comment === comment
- comment = RDoc::Encoding.change_encoding comment, @encoding if @encoding
-
- nest = 1
- save_visibility = container.visibility
- container.visibility = :public unless current_method
-
- non_comment_seen = true
-
- while tk = get_tk do
- keep_comment = false
- try_parse_comment = false
-
- non_comment_seen = true unless (:on_comment == tk[:kind] or :on_embdoc == tk[:kind])
-
- case tk[:kind]
- when :on_nl, :on_ignored_nl, :on_comment, :on_embdoc then
- if :on_nl == tk[:kind] or :on_ignored_nl == tk[:kind]
- skip_tkspace
- tk = get_tk
- else
- past_tokens = @read.size > 1 ? @read[0..-2] : []
- nl_position = 0
- past_tokens.reverse.each_with_index do |read_tk, i|
- if read_tk =~ /^\n$/ then
- nl_position = (past_tokens.size - 1) - i
- break
- elsif read_tk =~ /^#.*\n$/ then
- nl_position = ((past_tokens.size - 1) - i) + 1
- break
- end
- end
- comment_only_line = past_tokens[nl_position..-1].all?{ |c| c =~ /^\s+$/ }
- unless comment_only_line then
- tk = get_tk
- end
- end
-
- if tk and (:on_comment == tk[:kind] or :on_embdoc == tk[:kind]) then
- if non_comment_seen then
- # Look for RDoc in a comment about to be thrown away
- non_comment_seen = parse_comment container, tk, comment unless
- comment.empty?
-
- comment = ''
- comment = RDoc::Encoding.change_encoding comment, @encoding if @encoding
- end
-
- line_no = nil
- while tk and (:on_comment == tk[:kind] or :on_embdoc == tk[:kind]) do
- comment_body = retrieve_comment_body(tk)
- line_no = tk[:line_no] if comment.empty?
- comment += comment_body
- comment << "\n" unless comment_body =~ /\n\z/
-
- if comment_body.size > 1 && comment_body =~ /\n\z/ then
- skip_tkspace_without_nl # leading spaces
- end
- tk = get_tk
- end
-
- comment = new_comment comment, line_no
-
- unless comment.empty? then
- look_for_directives_in container, comment
-
- if container.done_documenting then
- throw :eof if RDoc::TopLevel === container
- container.ongoing_visibility = save_visibility
- end
- end
-
- keep_comment = true
- else
- non_comment_seen = true
- end
-
- unget_tk tk
- keep_comment = true
- container.current_line_visibility = nil
-
- when :on_kw then
- case tk[:text]
- when 'class' then
- parse_class container, single, tk, comment
-
- when 'module' then
- parse_module container, single, tk, comment
-
- when 'def' then
- parse_method container, single, tk, comment
-
- when 'alias' then
- parse_alias container, single, tk, comment unless current_method
-
- when 'yield' then
- if current_method.nil? then
- warn "Warning: yield outside of method" if container.document_self
- else
- parse_yield container, single, tk, current_method
- end
-
- when 'until', 'while' then
- if (tk[:state] & RDoc::Parser::RipperStateLex::EXPR_LABEL) == 0
- nest += 1
- skip_optional_do_after_expression
- end
-
- # Until and While can have a 'do', which shouldn't increase the nesting.
- # We can't solve the general case, but we can handle most occurrences by
- # ignoring a do at the end of a line.
-
- # 'for' is trickier
- when 'for' then
- nest += 1
- skip_for_variable
- skip_optional_do_after_expression
-
- when 'case', 'do', 'if', 'unless', 'begin' then
- if (tk[:state] & RDoc::Parser::RipperStateLex::EXPR_LABEL) == 0
- nest += 1
- end
-
- when 'super' then
- current_method.calls_super = true if current_method
-
- when 'rescue' then
- parse_rescue
-
- when 'end' then
- nest -= 1
- if nest == 0 then
- container.ongoing_visibility = save_visibility
-
- parse_comment container, tk, comment unless comment.empty?
-
- return
- end
- end
-
- when :on_const then
- unless parse_constant container, tk, comment, current_method then
- try_parse_comment = true
- end
-
- when :on_ident then
- if nest == 1 and current_method.nil? then
- keep_comment = parse_identifier container, single, tk, comment
- end
-
- case tk[:text]
- when "require" then
- parse_require container, comment
- when "include" then
- 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
- try_parse_comment = nest == 1
- end
-
- if try_parse_comment then
- non_comment_seen = parse_comment container, tk, comment unless
- comment.empty?
-
- keep_comment = false
- end
-
- unless keep_comment then
- comment = new_comment ''
- comment = RDoc::Encoding.change_encoding comment, @encoding if @encoding
- container.params = nil
- container.block_params = nil
- end
-
- consume_trailing_spaces
- end
-
- container.params = nil
- container.block_params = nil
- end
-
- ##
- # Parse up to +no+ symbol arguments
-
- def parse_symbol_arg(no = nil)
- skip_tkspace_comment
-
- tk = get_tk
- if tk[:kind] == :on_lparen
- parse_symbol_arg_paren no
- else
- parse_symbol_arg_space no, tk
- end
- end
-
- ##
- # Parses up to +no+ symbol arguments surrounded by () and places them in
- # +args+.
-
- def parse_symbol_arg_paren no # :nodoc:
- args = []
-
- loop do
- skip_tkspace_comment
- if tk1 = parse_symbol_in_arg
- args.push tk1
- break if no and args.size >= no
- end
-
- skip_tkspace_comment
- case (tk2 = get_tk)[:kind]
- when :on_rparen
- break
- when :on_comma
- else
- warn("unexpected token: '#{tk2.inspect}'") if $DEBUG_RDOC
- break
- end
- end
-
- args
- end
-
- ##
- # Parses up to +no+ symbol arguments separated by spaces and places them in
- # +args+.
-
- def parse_symbol_arg_space no, tk # :nodoc:
- args = []
-
- unget_tk tk
- if tk = parse_symbol_in_arg
- args.push tk
- return args if no and args.size >= no
- end
-
- loop do
- skip_tkspace_without_nl
-
- tk1 = get_tk
- if tk1.nil? || :on_comma != tk1[:kind] then
- unget_tk tk1
- break
- end
-
- skip_tkspace_comment
- if tk = parse_symbol_in_arg
- args.push tk
- break if no and args.size >= no
- end
- end
-
- args
- end
-
- ##
- # Returns symbol text from the next token
-
- def parse_symbol_in_arg
- tk = get_tk
- if :on_symbol == tk[:kind] then
- tk[:text].sub(/^:/, '')
- elsif :on_tstring == tk[:kind] then
- tk[:text][1..-2]
- elsif :on_dstring == tk[:kind] or :on_ident == tk[:kind] then
- nil # ignore
- else
- warn("Expected symbol or string, got #{tk.inspect}") if $DEBUG_RDOC
- nil
- end
- end
-
- ##
- # Parses statements in the top-level +container+
-
- def parse_top_level_statements container
- comment = collect_first_comment
-
- look_for_directives_in container, comment
-
- throw :eof if container.done_documenting
-
- @markup = comment.format
-
- # HACK move if to RDoc::Context#comment=
- container.comment = comment if container.document_self unless comment.empty?
-
- parse_statements container, NORMAL, nil, comment
- end
-
- ##
- # Determines the visibility in +container+ from +tk+
-
- def parse_visibility(container, single, tk)
- vis_type, vis, singleton = get_visibility_information tk, single
-
- skip_tkspace_comment false
-
- ptk = peek_tk
- # Ryan Davis suggested the extension to ignore modifiers, because he
- # often writes
- #
- # protected unless $TESTING
- #
- if [:on_nl, :on_semicolon].include?(ptk[:kind]) || (:on_kw == ptk[:kind] && (['if', 'unless'].include?(ptk[:text]))) then
- container.ongoing_visibility = vis
- elsif :on_kw == ptk[:kind] && 'def' == ptk[:text]
- container.current_line_visibility = vis
- else
- update_visibility container, vis_type, vis, singleton
- end
- end
-
- ##
- # Parses a Module#private_constant or Module#public_constant call from +tk+.
-
- def parse_constant_visibility(container, single, tk)
- args = parse_symbol_arg
- case tk[:text]
- when 'private_constant'
- vis = :private
- when 'public_constant'
- vis = :public
- else
- raise RDoc::Error, 'Unreachable'
- end
- container.set_constant_visibility_for args, vis
- end
-
- ##
- # Determines the block parameter for +context+
-
- def parse_yield(context, single, tk, method)
- return if method.block_params
-
- get_tkread
- method.block_params = parse_method_or_yield_parameters
- end
-
- ##
- # Directives are modifier comments that can appear after class, module, or
- # method names. For example:
- #
- # def fred # :yields: a, b
- #
- # or:
- #
- # class MyClass # :nodoc:
- #
- # We return the directive name and any parameters as a two element array if
- # the name is in +allowed+. A directive can be found anywhere up to the end
- # of the current line.
-
- def read_directive allowed
- tokens = []
-
- while tk = get_tk do
- tokens << tk
-
- if :on_nl == tk[:kind] or (:on_kw == tk[:kind] && 'def' == tk[:text]) then
- return
- elsif :on_comment == tk[:kind] or :on_embdoc == tk[:kind] then
- return unless tk[:text] =~ /:?\b([\w-]+):\s*(.*)/
-
- directive = $1.downcase
-
- return [directive, $2] if allowed.include? directive
-
- return
- end
- end
- ensure
- unless tokens.length == 1 and (:on_comment == tokens.first[:kind] or :on_embdoc == tokens.first[:kind]) then
- tokens.reverse_each do |token|
- unget_tk token
- end
- end
- end
-
- ##
- # Handles directives following the definition for +context+ (any
- # RDoc::CodeObject) if the directives are +allowed+ at this point.
- #
- # See also RDoc::Markup::PreProcess#handle_directive
-
- def read_documentation_modifiers context, allowed
- skip_tkspace_without_nl
- directive, value = read_directive allowed
-
- return unless directive
-
- @preprocess.handle_directive '', directive, value, context do |dir, param|
- if %w[notnew not_new not-new].include? dir then
- context.dont_rename_initialize = true
-
- true
- end
- end
- end
-
- ##
- # Records the location of this +container+ in the file for this parser and
- # adds it to the list of classes and modules in the file.
-
- def record_location container # :nodoc:
- case container
- when RDoc::ClassModule then
- @top_level.add_to_classes_or_modules container
- end
-
- container.record_location @top_level
- end
-
- ##
- # Scans this Ruby file for Ruby constructs
-
- def scan
- reset
-
- catch :eof do
- begin
- parse_top_level_statements @top_level
-
- rescue StandardError => e
- if @content.include?('<%') and @content.include?('%>') then
- # Maybe, this is ERB.
- $stderr.puts "\033[2KRDoc detects ERB file. Skips it for compatibility:"
- $stderr.puts @file_name
- return
- end
-
- if @scanner_point >= @scanner.size
- now_line_no = @scanner[@scanner.size - 1][:line_no]
- else
- now_line_no = peek_tk[:line_no]
- end
- first_tk_index = @scanner.find_index { |tk| tk[:line_no] == now_line_no }
- last_tk_index = @scanner.find_index { |tk| tk[:line_no] == now_line_no + 1 }
- last_tk_index = last_tk_index ? last_tk_index - 1 : @scanner.size - 1
- code = @scanner[first_tk_index..last_tk_index].map{ |t| t[:text] }.join
-
- $stderr.puts <<-EOF
-
-#{self.class} failure around line #{now_line_no} of
-#{@file_name}
-
- EOF
-
- unless code.empty? then
- $stderr.puts code
- $stderr.puts
- end
-
- raise e
- end
- end
-
- @top_level
- end
-
- ##
- # while, until, and for have an optional do
-
- def skip_optional_do_after_expression
- skip_tkspace_without_nl
- tk = get_tk
-
- b_nest = 0
- nest = 0
-
- loop do
- break unless tk
- case tk[:kind]
- when :on_semicolon, :on_nl, :on_ignored_nl then
- break if b_nest.zero?
- when :on_lparen then
- nest += 1
- when :on_rparen then
- nest -= 1
- when :on_kw then
- case tk[:text]
- when 'begin'
- b_nest += 1
- when 'end'
- b_nest -= 1
- when 'do'
- break if nest.zero?
- end
- when :on_comment, :on_embdoc then
- if b_nest.zero? and "\n" == tk[:text][-1] then
- break
- end
- end
- tk = get_tk
- end
-
- skip_tkspace_without_nl
-
- get_tk if peek_tk && :on_kw == peek_tk[:kind] && 'do' == peek_tk[:text]
- end
-
- ##
- # skip the var [in] part of a 'for' statement
-
- def skip_for_variable
- skip_tkspace_without_nl
- get_tk
- skip_tkspace_without_nl
- tk = get_tk
- unget_tk(tk) unless :on_kw == tk[:kind] and 'in' == tk[:text]
- end
-
- ##
- # Skips the next method in +container+
-
- def skip_method container
- meth = RDoc::AnyMethod.new "", "anon"
- parse_method_parameters meth
- parse_statements container, false, meth
- end
-
- ##
- # Skip spaces until a comment is found
-
- def skip_tkspace_comment(skip_nl = true)
- loop do
- skip_nl ? skip_tkspace : skip_tkspace_without_nl
- next_tk = peek_tk
- return if next_tk.nil? || (:on_comment != next_tk[:kind] and :on_embdoc != next_tk[:kind])
- get_tk
- end
- end
-
- ##
- # Updates visibility in +container+ from +vis_type+ and +vis+.
-
- def update_visibility container, vis_type, vis, singleton # :nodoc:
- new_methods = []
-
- case vis_type
- when 'module_function' then
- args = parse_symbol_arg
- container.set_visibility_for args, :private, false
-
- container.methods_matching args do |m|
- s_m = m.dup
- record_location s_m
- s_m.singleton = true
- new_methods << s_m
- end
- when 'public_class_method', 'private_class_method' then
- args = parse_symbol_arg
-
- container.methods_matching args, true do |m|
- if m.parent != container then
- m = m.dup
- record_location m
- new_methods << m
- end
-
- m.visibility = vis
- end
- else
- args = parse_symbol_arg
- container.set_visibility_for args, vis, singleton
- end
-
- new_methods.each do |method|
- case method
- when RDoc::AnyMethod then
- container.add_method method
- when RDoc::Attr then
- container.add_attribute method
- end
- method.visibility = vis
- end
- end
-
- ##
- # Prints +message+ to +$stderr+ unless we're being quiet
-
- def warn message
- @options.warn make_message message
- end
-
-end
diff --git a/lib/rdoc/parser/ruby_tools.rb b/lib/rdoc/parser/ruby_tools.rb
deleted file mode 100644
index 40ea517c4d..0000000000
--- a/lib/rdoc/parser/ruby_tools.rb
+++ /dev/null
@@ -1,165 +0,0 @@
-# frozen_string_literal: true
-##
-# Collection of methods for writing parsers
-
-module RDoc::Parser::RubyTools
-
- ##
- # Adds a token listener +obj+, but you should probably use token_listener
-
- def add_token_listener(obj)
- @token_listeners ||= []
- @token_listeners << obj
- end
-
- ##
- # Fetches the next token from the scanner
-
- def get_tk
- tk = nil
-
- if @tokens.empty? then
- if @scanner_point >= @scanner.size
- return nil
- else
- tk = @scanner[@scanner_point]
- @scanner_point += 1
- @read.push tk[:text]
- end
- else
- @read.push @unget_read.shift
- tk = @tokens.shift
- end
-
- if tk == nil || :on___end__ == tk[:kind]
- tk = nil
- end
-
- return nil unless tk
-
- # inform any listeners of our shiny new token
- @token_listeners.each do |obj|
- obj.add_token(tk)
- end if @token_listeners
-
- tk
- end
-
- ##
- # Reads and returns all tokens up to one of +tokens+. Leaves the matched
- # token in the token list.
-
- def get_tk_until(*tokens)
- read = []
-
- loop do
- tk = get_tk
-
- case tk
- when *tokens then
- unget_tk tk
- break
- end
-
- read << tk
- end
-
- read
- end
-
- ##
- # Retrieves a String representation of the read tokens
-
- def get_tkread
- read = @read.join("")
- @read = []
- read
- end
-
- ##
- # Peek equivalent for get_tkread
-
- def peek_read
- @read.join('')
- end
-
- ##
- # Peek at the next token, but don't remove it from the stream
-
- def peek_tk
- unget_tk(tk = get_tk)
- tk
- end
-
- ##
- # Removes the token listener +obj+
-
- def remove_token_listener(obj)
- @token_listeners.delete(obj)
- end
-
- ##
- # Resets the tools
-
- def reset
- @read = []
- @tokens = []
- @unget_read = []
- @nest = 0
- @scanner_point = 0
- end
-
- ##
- # Skips whitespace tokens including newlines
-
- def skip_tkspace
- tokens = []
-
- while (tk = get_tk) and (:on_sp == tk[:kind] or :on_nl == tk[:kind] or :on_ignored_nl == tk[:kind]) do
- tokens.push(tk)
- end
-
- unget_tk(tk)
- tokens
- end
-
- ##
- # Skips whitespace tokens excluding newlines
-
- def skip_tkspace_without_nl
- tokens = []
-
- while (tk = get_tk) and :on_sp == tk[:kind] do
- tokens.push(tk)
- end
-
- unget_tk(tk)
- tokens
- end
-
- ##
- # Has +obj+ listen to tokens
-
- def token_listener(obj)
- add_token_listener obj
- yield
- ensure
- remove_token_listener obj
- end
-
- ##
- # Returns +tk+ to the scanner
-
- def unget_tk(tk)
- @tokens.unshift tk
- @unget_read.unshift @read.pop
-
- # Remove this token from any listeners
- @token_listeners.each do |obj|
- obj.pop_token
- end if @token_listeners
-
- nil
- end
-
-end
diff --git a/lib/rdoc/parser/simple.rb b/lib/rdoc/parser/simple.rb
deleted file mode 100644
index b1dabad0f8..0000000000
--- a/lib/rdoc/parser/simple.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-##
-# Parse a non-source file. We basically take the whole thing as one big
-# comment.
-
-class RDoc::Parser::Simple < RDoc::Parser
-
- include RDoc::Parser::Text
-
- parse_files_matching(//)
-
- attr_reader :content # :nodoc:
-
- ##
- # Prepare to parse a plain file
-
- def initialize(top_level, file_name, content, options, stats)
- super
-
- preprocess = RDoc::Markup::PreProcess.new @file_name, @options.rdoc_include
-
- @content = preprocess.handle @content, @top_level
- end
-
- ##
- # Extract the file contents and attach them to the TopLevel as a comment
-
- def scan
- comment = remove_coding_comment @content
- comment = remove_private_comment comment
-
- comment = RDoc::Comment.new comment, @top_level
-
- @top_level.comment = comment
- @top_level
- end
-
- ##
- # Removes the encoding magic comment from +text+
-
- def remove_coding_comment text
- text.sub(/\A# .*coding[=:].*$/, '')
- end
-
- ##
- # Removes private comments.
- #
- # Unlike RDoc::Comment#remove_private this implementation only looks for two
- # dashes at the beginning of the line. Three or more dashes are considered
- # to be a rule and ignored.
-
- def remove_private_comment comment
- # Workaround for gsub encoding for Ruby 1.9.2 and earlier
- empty = ''
- empty = RDoc::Encoding.change_encoding empty, comment.encoding
-
- comment = comment.gsub(%r%^--\n.*?^\+\+\n?%m, empty)
- comment.sub(%r%^--\n.*%m, empty)
- end
-
-end
diff --git a/lib/rdoc/parser/text.rb b/lib/rdoc/parser/text.rb
deleted file mode 100644
index 5095d8cc64..0000000000
--- a/lib/rdoc/parser/text.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-##
-# Indicates this parser is text and doesn't contain code constructs.
-#
-# Include this module in a RDoc::Parser subclass to make it show up as a file,
-# not as part of a class or module.
-#--
-# This is not named File to avoid overriding ::File
-
-module RDoc::Parser::Text
-end
diff --git a/lib/rdoc/rd.rb b/lib/rdoc/rd.rb
deleted file mode 100644
index 8c2366a3ca..0000000000
--- a/lib/rdoc/rd.rb
+++ /dev/null
@@ -1,99 +0,0 @@
-# frozen_string_literal: true
-##
-# RDoc::RD implements the RD format from the rdtool gem.
-#
-# To choose RD as your only default format see
-# RDoc::Options@Saved+Options for instructions on setting up a
-# <code>.doc_options</code> file to store your project default.
-#
-# == LICENSE
-#
-# The grammar that produces RDoc::RD::BlockParser and RDoc::RD::InlineParser
-# is included in RDoc under the Ruby License.
-#
-# You can find the original source for rdtool at
-# https://github.com/uwabami/rdtool/
-#
-# You can use, re-distribute or change these files under Ruby's License or GPL.
-#
-# 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.
-
-class RDoc::RD
-
- ##
- # Parses +rd+ source and returns an RDoc::Markup::Document. If the
- # <tt>=begin</tt> or <tt>=end</tt> lines are missing they will be added.
-
- def self.parse rd
- rd = rd.lines.to_a
-
- if rd.find { |i| /\S/ === i } and !rd.find{|i| /^=begin\b/ === i } then
- rd.unshift("=begin\n").push("=end\n")
- end
-
- parser = RDoc::RD::BlockParser.new
- document = parser.parse rd
-
- # isn't this always true?
- document.parts.shift if RDoc::Markup::BlankLine === document.parts.first
- document.parts.pop if RDoc::Markup::BlankLine === document.parts.last
-
- document
- end
-
- autoload :BlockParser, "#{__dir__}/rd/block_parser"
- autoload :InlineParser, "#{__dir__}/rd/inline_parser"
- autoload :Inline, "#{__dir__}/rd/inline"
-
-end
diff --git a/lib/rdoc/rd/block_parser.rb b/lib/rdoc/rd/block_parser.rb
deleted file mode 100644
index 527147d91d..0000000000
--- a/lib/rdoc/rd/block_parser.rb
+++ /dev/null
@@ -1,1710 +0,0 @@
-# frozen_string_literal: true
-#
-# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.7.3
-# from Racc grammar file "block_parser.ry".
-#
-
-###### racc/parser.rb begin
-unless $".find {|p| p.end_with?('/racc/parser.rb')}
-$".push "#{__dir__}/racc/parser.rb"
-#--
-# Copyright (c) 1999-2006 Minero Aoki
-#
-# This program is free software.
-# You can distribute/modify this program under the same terms of ruby.
-#
-# As a special exception, when this code is copied by Racc
-# into a Racc output file, you may use that output file
-# without restriction.
-#++
-
-unless $".find {|p| p.end_with?('/racc/info.rb')}
-$".push "#{__dir__}/racc/info.rb"
-
-module Racc
- VERSION = '1.7.3'
- Version = VERSION
- Copyright = 'Copyright (c) 1999-2006 Minero Aoki'
-end
-
-end
-
-
-unless defined?(NotImplementedError)
- NotImplementedError = NotImplementError # :nodoc:
-end
-
-module Racc
- class ParseError < StandardError; end
-end
-unless defined?(::ParseError)
- ParseError = Racc::ParseError # :nodoc:
-end
-
-# Racc is a LALR(1) parser generator.
-# It is written in Ruby itself, and generates Ruby programs.
-#
-# == Command-line Reference
-#
-# racc [-o<var>filename</var>] [--output-file=<var>filename</var>]
-# [-e<var>rubypath</var>] [--executable=<var>rubypath</var>]
-# [-v] [--verbose]
-# [-O<var>filename</var>] [--log-file=<var>filename</var>]
-# [-g] [--debug]
-# [-E] [--embedded]
-# [-l] [--no-line-convert]
-# [-c] [--line-convert-all]
-# [-a] [--no-omit-actions]
-# [-C] [--check-only]
-# [-S] [--output-status]
-# [--version] [--copyright] [--help] <var>grammarfile</var>
-#
-# [+grammarfile+]
-# Racc grammar file. Any extension is permitted.
-# [-o+outfile+, --output-file=+outfile+]
-# A filename for output. default is <+filename+>.tab.rb
-# [-O+filename+, --log-file=+filename+]
-# Place logging output in file +filename+.
-# Default log file name is <+filename+>.output.
-# [-e+rubypath+, --executable=+rubypath+]
-# output executable file(mode 755). where +path+ is the Ruby interpreter.
-# [-v, --verbose]
-# verbose mode. create +filename+.output file, like yacc's y.output file.
-# [-g, --debug]
-# add debug code to parser class. To display debugging information,
-# use this '-g' option and set @yydebug true in parser class.
-# [-E, --embedded]
-# Output parser which doesn't need runtime files (racc/parser.rb).
-# [-F, --frozen]
-# Output parser which declares frozen_string_literals: true
-# [-C, --check-only]
-# Check syntax of racc grammar file and quit.
-# [-S, --output-status]
-# Print messages time to time while compiling.
-# [-l, --no-line-convert]
-# turns off line number converting.
-# [-c, --line-convert-all]
-# Convert line number of actions, inner, header and footer.
-# [-a, --no-omit-actions]
-# Call all actions, even if an action is empty.
-# [--version]
-# print Racc version and quit.
-# [--copyright]
-# Print copyright and quit.
-# [--help]
-# Print usage and quit.
-#
-# == Generating Parser Using Racc
-#
-# To compile Racc grammar file, simply type:
-#
-# $ racc parse.y
-#
-# This creates Ruby script file "parse.tab.y". The -o option can change the output filename.
-#
-# == Writing A Racc Grammar File
-#
-# If you want your own parser, you have to write a grammar file.
-# A grammar file contains the name of your parser class, grammar for the parser,
-# user code, and anything else.
-# When writing a grammar file, yacc's knowledge is helpful.
-# If you have not used yacc before, Racc is not too difficult.
-#
-# Here's an example Racc grammar file.
-#
-# class Calcparser
-# rule
-# target: exp { print val[0] }
-#
-# exp: exp '+' exp
-# | exp '*' exp
-# | '(' exp ')'
-# | NUMBER
-# end
-#
-# Racc grammar files resemble yacc files.
-# But (of course), this is Ruby code.
-# yacc's $$ is the 'result', $0, $1... is
-# an array called 'val', and $-1, $-2... is an array called '_values'.
-#
-# See the {Grammar File Reference}[rdoc-ref:lib/racc/rdoc/grammar.en.rdoc] for
-# more information on grammar files.
-#
-# == Parser
-#
-# Then you must prepare the parse entry method. There are two types of
-# parse methods in Racc, Racc::Parser#do_parse and Racc::Parser#yyparse
-#
-# Racc::Parser#do_parse is simple.
-#
-# It's yyparse() of yacc, and Racc::Parser#next_token is yylex().
-# This method must returns an array like [TOKENSYMBOL, ITS_VALUE].
-# EOF is [false, false].
-# (TOKENSYMBOL is a Ruby symbol (taken from String#intern) by default.
-# If you want to change this, see the grammar reference.
-#
-# Racc::Parser#yyparse is little complicated, but useful.
-# It does not use Racc::Parser#next_token, instead it gets tokens from any iterator.
-#
-# For example, <code>yyparse(obj, :scan)</code> causes
-# calling +obj#scan+, and you can return tokens by yielding them from +obj#scan+.
-#
-# == Debugging
-#
-# When debugging, "-v" or/and the "-g" option is helpful.
-#
-# "-v" creates verbose log file (.output).
-# "-g" creates a "Verbose Parser".
-# Verbose Parser prints the internal status when parsing.
-# But it's _not_ automatic.
-# You must use -g option and set +@yydebug+ to +true+ in order to get output.
-# -g option only creates the verbose parser.
-#
-# === Racc reported syntax error.
-#
-# Isn't there too many "end"?
-# grammar of racc file is changed in v0.10.
-#
-# Racc does not use '%' mark, while yacc uses huge number of '%' marks..
-#
-# === Racc reported "XXXX conflicts".
-#
-# Try "racc -v xxxx.y".
-# It causes producing racc's internal log file, xxxx.output.
-#
-# === Generated parsers does not work correctly
-#
-# Try "racc -g xxxx.y".
-# This command let racc generate "debugging parser".
-# Then set @yydebug=true in your parser.
-# It produces a working log of your parser.
-#
-# == Re-distributing Racc runtime
-#
-# A parser, which is created by Racc, requires the Racc runtime module;
-# racc/parser.rb.
-#
-# Ruby 1.8.x comes with Racc runtime module,
-# you need NOT distribute Racc runtime files.
-#
-# If you want to include the Racc runtime module with your parser.
-# This can be done by using '-E' option:
-#
-# $ racc -E -omyparser.rb myparser.y
-#
-# This command creates myparser.rb which `includes' Racc runtime.
-# Only you must do is to distribute your parser file (myparser.rb).
-#
-# Note: parser.rb is ruby license, but your parser is not.
-# Your own parser is completely yours.
-module Racc
-
- unless defined?(Racc_No_Extensions)
- Racc_No_Extensions = false # :nodoc:
- end
-
- class Parser
-
- Racc_Runtime_Version = ::Racc::VERSION
- Racc_Runtime_Core_Version_R = ::Racc::VERSION
-
- 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
-
- unless new.respond_to?(:_racc_do_parse_c, true)
- raise LoadError, 'old cparse.so'
- end
- 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_Type = 'c' # :nodoc:
- rescue LoadError
- 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_Type = 'ruby'
- end
-
- def Parser.racc_runtime_type # :nodoc:
- Racc_Runtime_Type
- end
-
- def _racc_setup
- @yydebug = false unless self.class::Racc_debug_parser
- @yydebug = false unless defined?(@yydebug)
- if @yydebug
- @racc_debug_out = $stderr unless defined?(@racc_debug_out)
- @racc_debug_out ||= $stderr
- end
- arg = self.class::Racc_arg
- arg[13] = true if arg.size < 14
- arg
- end
-
- def _racc_init_sysvars
- @racc_state = [0]
- @racc_tstack = []
- @racc_vstack = []
-
- @racc_t = nil
- @racc_val = nil
-
- @racc_read_next = true
-
- @racc_user_yyerror = false
- @racc_error_status = 0
- end
-
- # The entry point of the parser. This method is used with #next_token.
- # If Racc wants to get token (and its value), calls next_token.
- #
- # Example:
- # def parse
- # @q = [[1,1],
- # [2,2],
- # [3,3],
- # [false, '$']]
- # do_parse
- # end
- #
- # def next_token
- # @q.shift
- # end
- class_eval <<~RUBY, __FILE__, __LINE__ + 1
- def do_parse
- #{Racc_Main_Parsing_Routine}(_racc_setup(), false)
- end
- RUBY
-
- # The method to fetch next token.
- # If you use #do_parse method, you must implement #next_token.
- #
- # The format of return value is [TOKEN_SYMBOL, VALUE].
- # +token-symbol+ is represented by Ruby's symbol by default, e.g. :IDENT
- # for 'IDENT'. ";" (String) for ';'.
- #
- # The final symbol (End of file) must be false.
- def next_token
- raise NotImplementedError, "#{self.class}\#next_token is not defined"
- end
-
- def _racc_do_parse_rb(arg, in_debug)
- action_table, action_check, action_default, action_pointer,
- _, _, _, _,
- _, _, token_table, * = arg
-
- _racc_init_sysvars
- tok = act = i = nil
-
- catch(:racc_end_parse) {
- while true
- if i = action_pointer[@racc_state[-1]]
- if @racc_read_next
- if @racc_t != 0 # not EOF
- tok, @racc_val = next_token()
- unless tok # EOF
- @racc_t = 0
- else
- @racc_t = (token_table[tok] or 1) # error token
- end
- racc_read_token(@racc_t, tok, @racc_val) if @yydebug
- @racc_read_next = false
- end
- end
- i += @racc_t
- unless i >= 0 and
- act = action_table[i] and
- action_check[i] == @racc_state[-1]
- act = action_default[@racc_state[-1]]
- end
- else
- act = action_default[@racc_state[-1]]
- end
- while act = _racc_evalact(act, arg)
- ;
- end
- end
- }
- end
-
- # Another entry point for the parser.
- # If you use this method, you must implement RECEIVER#METHOD_ID method.
- #
- # RECEIVER#METHOD_ID is a method to get next token.
- # It must 'yield' the token, which format is [TOKEN-SYMBOL, VALUE].
- class_eval <<~RUBY, __FILE__, __LINE__ + 1
- def yyparse(recv, mid)
- #{Racc_YY_Parse_Method}(recv, mid, _racc_setup(), false)
- end
- RUBY
-
- def _racc_yyparse_rb(recv, mid, arg, c_debug)
- action_table, action_check, action_default, action_pointer,
- _, _, _, _,
- _, _, token_table, * = arg
-
- _racc_init_sysvars
-
- catch(:racc_end_parse) {
- until i = action_pointer[@racc_state[-1]]
- while act = _racc_evalact(action_default[@racc_state[-1]], arg)
- ;
- end
- end
- recv.__send__(mid) do |tok, val|
- unless tok
- @racc_t = 0
- else
- @racc_t = (token_table[tok] or 1) # error token
- end
- @racc_val = val
- @racc_read_next = false
-
- i += @racc_t
- unless i >= 0 and
- act = action_table[i] and
- action_check[i] == @racc_state[-1]
- act = action_default[@racc_state[-1]]
- end
- while act = _racc_evalact(act, arg)
- ;
- end
-
- while !(i = action_pointer[@racc_state[-1]]) ||
- ! @racc_read_next ||
- @racc_t == 0 # $
- unless i and i += @racc_t and
- i >= 0 and
- act = action_table[i] and
- action_check[i] == @racc_state[-1]
- act = action_default[@racc_state[-1]]
- end
- while act = _racc_evalact(act, arg)
- ;
- end
- end
- end
- }
- end
-
- ###
- ### common
- ###
-
- def _racc_evalact(act, arg)
- action_table, action_check, _, action_pointer,
- _, _, _, _,
- _, _, _, shift_n,
- reduce_n, * = arg
- nerr = 0 # tmp
-
- if act > 0 and act < shift_n
- #
- # shift
- #
- if @racc_error_status > 0
- @racc_error_status -= 1 unless @racc_t <= 1 # error token or EOF
- end
- @racc_vstack.push @racc_val
- @racc_state.push act
- @racc_read_next = true
- if @yydebug
- @racc_tstack.push @racc_t
- racc_shift @racc_t, @racc_tstack, @racc_vstack
- end
-
- elsif act < 0 and act > -reduce_n
- #
- # reduce
- #
- code = catch(:racc_jump) {
- @racc_state.push _racc_do_reduce(arg, act)
- false
- }
- if code
- case code
- when 1 # yyerror
- @racc_user_yyerror = true # user_yyerror
- return -reduce_n
- when 2 # yyaccept
- return shift_n
- else
- raise '[Racc Bug] unknown jump code'
- end
- end
-
- elsif act == shift_n
- #
- # accept
- #
- racc_accept if @yydebug
- throw :racc_end_parse, @racc_vstack[0]
-
- elsif act == -reduce_n
- #
- # error
- #
- case @racc_error_status
- when 0
- unless arg[21] # user_yyerror
- nerr += 1
- on_error @racc_t, @racc_val, @racc_vstack
- end
- when 3
- if @racc_t == 0 # is $
- # We're at EOF, and another error occurred immediately after
- # attempting auto-recovery
- throw :racc_end_parse, nil
- end
- @racc_read_next = true
- end
- @racc_user_yyerror = false
- @racc_error_status = 3
- while true
- if i = action_pointer[@racc_state[-1]]
- i += 1 # error token
- if i >= 0 and
- (act = action_table[i]) and
- action_check[i] == @racc_state[-1]
- break
- end
- end
- throw :racc_end_parse, nil if @racc_state.size <= 1
- @racc_state.pop
- @racc_vstack.pop
- if @yydebug
- @racc_tstack.pop
- racc_e_pop @racc_state, @racc_tstack, @racc_vstack
- end
- end
- return act
-
- else
- raise "[Racc Bug] unknown action #{act.inspect}"
- end
-
- racc_next_state(@racc_state[-1], @racc_state) if @yydebug
-
- nil
- end
-
- def _racc_do_reduce(arg, act)
- _, _, _, _,
- goto_table, goto_check, goto_default, goto_pointer,
- nt_base, reduce_table, _, _,
- _, use_result, * = arg
-
- state = @racc_state
- vstack = @racc_vstack
- tstack = @racc_tstack
-
- i = act * -3
- len = reduce_table[i]
- reduce_to = reduce_table[i+1]
- method_id = reduce_table[i+2]
- void_array = []
-
- tmp_t = tstack[-len, len] if @yydebug
- tmp_v = vstack[-len, len]
- tstack[-len, len] = void_array if @yydebug
- vstack[-len, len] = void_array
- state[-len, len] = void_array
-
- # tstack must be updated AFTER method call
- if use_result
- vstack.push __send__(method_id, tmp_v, vstack, tmp_v[0])
- else
- vstack.push __send__(method_id, tmp_v, vstack)
- end
- tstack.push reduce_to
-
- racc_reduce(tmp_t, reduce_to, tstack, vstack) if @yydebug
-
- k1 = reduce_to - nt_base
- if i = goto_pointer[k1]
- i += state[-1]
- if i >= 0 and (curstate = goto_table[i]) and goto_check[i] == k1
- return curstate
- end
- end
- goto_default[k1]
- end
-
- # This method is called when a parse error is found.
- #
- # ERROR_TOKEN_ID is an internal ID of token which caused error.
- # You can get string representation of this ID by calling
- # #token_to_str.
- #
- # ERROR_VALUE is a value of error token.
- #
- # value_stack is a stack of symbol values.
- # DO NOT MODIFY this object.
- #
- # This method raises ParseError by default.
- #
- # If this method returns, parsers enter "error recovering mode".
- def on_error(t, val, vstack)
- raise ParseError, sprintf("parse error on value %s (%s)",
- val.inspect, token_to_str(t) || '?')
- end
-
- # Enter error recovering mode.
- # This method does not call #on_error.
- def yyerror
- throw :racc_jump, 1
- end
-
- # Exit parser.
- # Return value is +Symbol_Value_Stack[0]+.
- def yyaccept
- throw :racc_jump, 2
- end
-
- # Leave error recovering mode.
- def yyerrok
- @racc_error_status = 0
- end
-
- # For debugging output
- def racc_read_token(t, tok, val)
- @racc_debug_out.print 'read '
- @racc_debug_out.print tok.inspect, '(', racc_token2str(t), ') '
- @racc_debug_out.puts val.inspect
- @racc_debug_out.puts
- end
-
- def racc_shift(tok, tstack, vstack)
- @racc_debug_out.puts "shift #{racc_token2str tok}"
- racc_print_stacks tstack, vstack
- @racc_debug_out.puts
- end
-
- def racc_reduce(toks, sim, tstack, vstack)
- out = @racc_debug_out
- out.print 'reduce '
- if toks.empty?
- out.print ' <none>'
- else
- toks.each {|t| out.print ' ', racc_token2str(t) }
- end
- out.puts " --> #{racc_token2str(sim)}"
- racc_print_stacks tstack, vstack
- @racc_debug_out.puts
- end
-
- def racc_accept
- @racc_debug_out.puts 'accept'
- @racc_debug_out.puts
- end
-
- def racc_e_pop(state, tstack, vstack)
- @racc_debug_out.puts 'error recovering mode: pop token'
- racc_print_states state
- racc_print_stacks tstack, vstack
- @racc_debug_out.puts
- end
-
- def racc_next_state(curstate, state)
- @racc_debug_out.puts "goto #{curstate}"
- racc_print_states state
- @racc_debug_out.puts
- end
-
- def racc_print_stacks(t, v)
- out = @racc_debug_out
- out.print ' ['
- t.each_index do |i|
- out.print ' (', racc_token2str(t[i]), ' ', v[i].inspect, ')'
- end
- out.puts ' ]'
- end
-
- def racc_print_states(s)
- out = @racc_debug_out
- out.print ' ['
- s.each {|st| out.print ' ', st }
- out.puts ' ]'
- end
-
- def racc_token2str(tok)
- self.class::Racc_token_to_s_table[tok] or
- raise "[Racc Bug] can't convert token #{tok} to string"
- end
-
- # Convert internal ID of token symbol to the string.
- def token_to_str(t)
- self.class::Racc_token_to_s_table[t]
- end
-
- end
-
-end
-
-end
-###### racc/parser.rb end
-
-class RDoc::RD
-
-##
-# RD format parser for headings, paragraphs, lists, verbatim sections that
-# exist as blocks.
-
-class BlockParser < Racc::Parser
-
-
-# :stopdoc:
-
-MARK_TO_LEVEL = {
- '=' => 1,
- '==' => 2,
- '===' => 3,
- '====' => 4,
- '+' => 5,
- '++' => 6,
-}
-
-# :startdoc:
-
-##
-# Footnotes for this document
-
-attr_reader :footnotes
-
-##
-# Labels for items in this document
-
-attr_reader :labels
-
-##
-# Path to find included files in
-
-attr_accessor :include_path
-
-##
-# Creates a new RDoc::RD::BlockParser. Use #parse to parse an rd-format
-# document.
-
-def initialize
- @inline_parser = RDoc::RD::InlineParser.new self
- @include_path = []
-
- # for testing
- @footnotes = []
- @labels = {}
-end
-
-##
-# Parses +src+ and returns an RDoc::Markup::Document.
-
-def parse src
- @src = src
- @src.push false
-
- @footnotes = []
- @labels = {}
-
- # @i: index(line no.) of src
- @i = 0
-
- # stack for current indentation
- @indent_stack = []
-
- # how indented.
- @current_indent = @indent_stack.join("")
-
- # RDoc::RD::BlockParser for tmp src
- @subparser = nil
-
- # which part is in now
- @in_part = nil
- @part_content = []
-
- @in_verbatim = false
-
- @yydebug = true
-
- document = do_parse
-
- unless @footnotes.empty? then
- blankline = document.parts.pop
-
- document.parts << RDoc::Markup::Rule.new(1)
- document.parts.concat @footnotes
-
- document.parts.push blankline
- end
-
- document
-end
-
-##
-# Returns the next token from the document
-
-def next_token # :nodoc:
- # preprocessing
- # if it is not in RD part
- # => method
- while @in_part != "rd"
- line = @src[@i]
- @i += 1 # next line
-
- case line
- # src end
- when false
- return [false, false]
- # RD part begin
- when /^=begin\s*(?:\bRD\b.*)?\s*$/
- if @in_part # if in non-RD part
- @part_content.push(line)
- else
- @in_part = "rd"
- return [:WHITELINE, "=begin\n"] # <= for textblockand
- end
- # non-RD part begin
- when /^=begin\s+(\w+)/
- part = $1
-=begin # not imported to RDoc
- if @in_part # if in non-RD part
- @part_content.push(line)
- else
- @in_part = part if @tree.filter[part] # if filter exists
-# p "BEGIN_PART: #{@in_part}" # DEBUG
- end
-=end
- @in_part = part
- # non-RD part end
- when /^=end(?:$|[\s\0\C-d\C-z])/
- if @in_part # if in non-RD part
-=begin # not imported to RDoc
-# p "END_PART: #{@in_part}" # DEBUG
- # make Part-in object
- part = RDoc::RD::Part.new(@part_content.join(""), @tree, "r")
- @part_content.clear
- # call filter, part_out is output(Part object)
- part_out = @tree.filter[@in_part].call(part)
-
- if @tree.filter[@in_part].mode == :rd # if output is RD formatted
- subtree = parse_subtree(part_out.to_a)
- else # if output is target formatted
- basename = Tempfile.create(["rdtmp", ".#{@in_part}"], @tree.tmp_dir) do |tmpfile|
- tmpfile.print(part_out)
- File.basename(tmpfile.path)
- end
- subtree = parse_subtree(["=begin\n", "<<< #{basename}\n", "=end\n"])
- end
- @in_part = nil
- return [:SUBTREE, subtree]
-=end
- end
- else
-=begin # not imported to RDoc
- if @in_part # if in non-RD part
- @part_content.push(line)
- end
-=end
- end
- end
-
- @current_indent = @indent_stack.join("")
- line = @src[@i]
- case line
- when false
- if_current_indent_equal("") do
- [false, false]
- end
- when /^=end/
- if_current_indent_equal("") do
- @in_part = nil
- [:WHITELINE, "=end"] # MUST CHANGE??
- end
- when /^\s*$/
- @i += 1 # next line
- return [:WHITELINE, ':WHITELINE']
- when /^\#/ # comment line
- @i += 1 # next line
- self.next_token()
- when /^(={1,4})(?!=)\s*(?=\S)/, /^(\+{1,2})(?!\+)\s*(?=\S)/
- rest = $' # '
- rest.strip!
- mark = $1
- if_current_indent_equal("") do
- return [:HEADLINE, [MARK_TO_LEVEL[mark], rest]]
- end
- when /^<<<\s*(\S+)/
- file = $1
- if_current_indent_equal("") do
- suffix = file[-3 .. -1]
- if suffix == ".rd" or suffix == ".rb"
- subtree = parse_subtree(get_included(file))
- [:SUBTREE, subtree]
- else
- [:INCLUDE, file]
- end
- end
- when /^(\s*)\*(\s*)/
- rest = $' # '
- newIndent = $2
- if_current_indent_equal($1) do
- if @in_verbatim
- [:STRINGLINE, line]
- else
- @indent_stack.push("\s" + newIndent)
- [:ITEMLISTLINE, rest]
- end
- end
- when /^(\s*)(\(\d+\))(\s*)/
- rest = $' # '
- mark = $2
- newIndent = $3
- if_current_indent_equal($1) do
- if @in_verbatim
- [:STRINGLINE, line]
- else
- @indent_stack.push("\s" * mark.size + newIndent)
- [:ENUMLISTLINE, rest]
- end
- end
- when /^(\s*):(\s*)/
- rest = $' # '
- newIndent = $2
- if_current_indent_equal($1) do
- if @in_verbatim
- [:STRINGLINE, line]
- else
- @indent_stack.push("\s#{$2}")
- [:DESCLISTLINE, rest]
- end
- end
- when /^(\s*)---(?!-|\s*$)/
- indent = $1
- rest = $'
- /\s*/ === rest
- term = $'
- new_indent = $&
- if_current_indent_equal(indent) do
- if @in_verbatim
- [:STRINGLINE, line]
- else
- @indent_stack.push("\s\s\s" + new_indent)
- [:METHODLISTLINE, term]
- end
- end
- when /^(\s*)/
- if_current_indent_equal($1) do
- [:STRINGLINE, line]
- end
- else
- raise "[BUG] parsing error may occurred."
- end
-end
-
-##
-# Yields to the given block if +indent+ matches the current indent, otherwise
-# an indentation token is processed.
-
-def if_current_indent_equal(indent)
- indent = indent.sub(/\t/, "\s" * 8)
- if @current_indent == indent
- @i += 1 # next line
- yield
- elsif indent.index(@current_indent) == 0
- @indent_stack.push(indent[@current_indent.size .. -1])
- [:INDENT, ":INDENT"]
- else
- @indent_stack.pop
- [:DEDENT, ":DEDENT"]
- end
-end
-private :if_current_indent_equal
-
-##
-# Cuts off excess whitespace in +src+
-
-def cut_off(src)
- ret = []
- whiteline_buf = []
-
- line = src.shift
- /^\s*/ =~ line
-
- indent = Regexp.quote($&)
- ret.push($')
-
- while line = src.shift
- if /^(\s*)$/ =~ line
- whiteline_buf.push(line)
- elsif /^#{indent}/ =~ line
- unless whiteline_buf.empty?
- ret.concat(whiteline_buf)
- whiteline_buf.clear
- end
- ret.push($')
- else
- raise "[BUG]: probably Parser Error while cutting off.\n"
- end
- end
- ret
-end
-private :cut_off
-
-def set_term_to_element(parent, term)
-# parent.set_term_under_document_struct(term, @tree.document_struct)
- parent.set_term_without_document_struct(term)
-end
-private :set_term_to_element
-
-##
-# Raises a ParseError when invalid formatting is found
-
-def on_error(et, ev, _values)
- prv, cur, nxt = format_line_num(@i, @i+1, @i+2)
-
- raise ParseError, <<Msg
-
-RD syntax error: line #{@i+1}:
- #{prv} |#{@src[@i-1].chomp}
- #{cur}=>|#{@src[@i].chomp}
- #{nxt} |#{@src[@i+1].chomp}
-
-Msg
-end
-
-##
-# Current line number
-
-def line_index
- @i
-end
-
-##
-# Parses subtree +src+
-
-def parse_subtree src
- @subparser ||= RDoc::RD::BlockParser.new
-
- @subparser.parse src
-end
-private :parse_subtree
-
-##
-# Retrieves the content for +file+ from the include_path
-
-def get_included(file)
- included = []
-
- @include_path.each do |dir|
- file_name = File.join dir, file
-
- if File.exist? file_name then
- included = File.readlines file_name
- break
- end
- end
-
- included
-end
-private :get_included
-
-##
-# Formats line numbers +line_numbers+ prettily
-
-def format_line_num(*line_numbers)
- width = line_numbers.collect{|i| i.to_s.length }.max
- line_numbers.collect{|i| sprintf("%#{width}d", i) }
-end
-private :format_line_num
-
-##
-# Retrieves the content of +values+ as a single String
-
-def content values
- values.map { |value| value.content }.join
-end
-
-##
-# Creates a paragraph for +value+
-
-def paragraph value
- content = cut_off(value).join(' ').rstrip
- contents = @inline_parser.parse content
-
- RDoc::Markup::Paragraph.new(*contents)
-end
-
-##
-# Adds footnote +content+ to the document
-
-def add_footnote content
- index = @footnotes.length / 2 + 1
-
- footmark_link = "{^#{index}}[rdoc-label:footmark-#{index}:foottext-#{index}]"
-
- @footnotes << RDoc::Markup::Paragraph.new(footmark_link, ' ', *content)
- @footnotes << RDoc::Markup::BlankLine.new
-
- index
-end
-
-##
-# Adds label +label+ to the document
-
-def add_label label
- @labels[label] = true
-
- label
-end
-
-# :stopdoc:
-
-##### State transition tables begin ###
-
-racc_action_table = [
- 34, 35, 30, 33, 40, 34, 35, 30, 33, 40,
- 65, 34, 35, 30, 33, 14, 73, 36, 38, 34,
- 15, 88, 34, 35, 30, 33, 14, 9, 10, 11,
- 12, 15, 34, 35, 30, 33, 14, 9, 10, 11,
- 12, 15, 34, 35, 30, 33, 35, 47, 30, 54,
- 33, 15, 34, 35, 30, 33, 54, 47, 14, 14,
- 59, 15, 34, 35, 30, 33, 14, 73, 67, 76,
- 77, 15, 34, 35, 30, 33, 14, 73, 54, 81,
- 38, 15, 34, 35, 30, 33, 14, 73, 38, 40,
- 83, 15, 34, 35, 30, 33, 14, 73, nil, nil,
- nil, 15, 34, 35, 30, 33, 14, 73, nil, nil,
- nil, 15, 34, 35, 30, 33, 14, 73, nil, nil,
- nil, 15, 34, 35, 30, 33, 14, 73, nil, nil,
- nil, 15, 34, 35, 30, 33, 14, 73, nil, nil,
- nil, 15, 34, 35, 30, 33, 14, 73, 61, 63,
- nil, 15, 14, 62, 60, 61, 63, 79, 61, 63,
- 62, 87, nil, 62, 34, 35, 30, 33 ]
-
-racc_action_check = [
- 41, 41, 41, 41, 41, 15, 15, 15, 15, 15,
- 41, 86, 86, 86, 86, 86, 86, 1, 13, 22,
- 86, 86, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 24, 24, 24, 24, 25, 24, 28, 30,
- 31, 24, 27, 27, 27, 27, 33, 27, 34, 35,
- 36, 27, 45, 45, 45, 45, 45, 45, 44, 49,
- 51, 45, 46, 46, 46, 46, 46, 46, 54, 56,
- 57, 46, 47, 47, 47, 47, 47, 47, 58, 62,
- 66, 47, 68, 68, 68, 68, 68, 68, nil, nil,
- nil, 68, 74, 74, 74, 74, 74, 74, nil, nil,
- nil, 74, 75, 75, 75, 75, 75, 75, nil, nil,
- nil, 75, 78, 78, 78, 78, 78, 78, nil, nil,
- nil, 78, 79, 79, 79, 79, 79, 79, nil, nil,
- nil, 79, 85, 85, 85, 85, 85, 85, 39, 39,
- nil, 85, 52, 39, 39, 82, 82, 52, 64, 64,
- 82, 82, nil, 64, 20, 20, 20, 20 ]
-
-racc_action_pointer = [
- 19, 17, 29, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 11, nil, 2, nil, nil, nil, nil,
- 161, nil, 16, nil, 39, 42, nil, 49, 43, nil,
- 41, 44, nil, 48, 51, 52, 60, nil, nil, 141,
- nil, -3, nil, nil, 55, 59, 69, 79, nil, 56,
- nil, 57, 145, nil, 70, nil, 66, 73, 81, nil,
- nil, nil, 82, nil, 151, nil, 77, nil, 89, nil,
- nil, nil, nil, nil, 99, 109, nil, nil, 119, 129,
- nil, nil, 148, nil, nil, 139, 8, nil, nil ]
-
-racc_action_default = [
- -2, -73, -1, -4, -5, -6, -7, -8, -9, -10,
- -11, -12, -13, -14, -16, -73, -23, -24, -25, -26,
- -27, -31, -32, -34, -72, -36, -38, -72, -40, -42,
- -59, -44, -46, -59, -63, -65, -73, -3, -15, -73,
- -22, -73, -30, -33, -73, -69, -70, -71, -37, -73,
- -41, -73, -51, -58, -61, -45, -73, -62, -64, 89,
- -17, -19, -73, -21, -18, -28, -73, -35, -66, -53,
- -54, -55, -56, -57, -67, -68, -39, -43, -49, -73,
- -60, -47, -73, -29, -52, -48, -73, -20, -50 ]
-
-racc_goto_table = [
- 4, 39, 4, 68, 74, 75, 5, 6, 5, 6,
- 44, 42, 51, 49, 3, 56, 37, 57, 58, 1,
- 2, 66, 84, 41, 43, 48, 50, 64, 84, 84,
- 45, 46, 42, 45, 46, 55, 85, 86, 80, 84,
- 84, nil, nil, nil, nil, nil, nil, nil, 82, nil,
- nil, nil, 78 ]
-
-racc_goto_check = [
- 4, 10, 4, 31, 31, 31, 5, 6, 5, 6,
- 21, 12, 27, 21, 3, 27, 3, 9, 9, 1,
- 2, 11, 32, 17, 19, 23, 26, 10, 32, 32,
- 5, 6, 12, 5, 6, 29, 31, 31, 33, 32,
- 32, nil, nil, nil, nil, nil, nil, nil, 10, nil,
- nil, nil, 4 ]
-
-racc_goto_pointer = [
- nil, 19, 20, 14, 0, 6, 7, nil, nil, -17,
- -14, -20, -9, nil, nil, nil, nil, 8, nil, 2,
- nil, -14, nil, 0, nil, nil, -2, -18, nil, 4,
- nil, -42, -46, -16 ]
-
-racc_goto_default = [
- nil, nil, nil, nil, 70, 71, 72, 7, 8, 13,
- nil, nil, 21, 16, 17, 18, 19, 20, 22, 23,
- 24, nil, 25, 26, 27, 28, 29, nil, 31, 32,
- 52, nil, 69, 53 ]
-
-racc_reduce_table = [
- 0, 0, :racc_error,
- 1, 15, :_reduce_1,
- 0, 15, :_reduce_2,
- 2, 16, :_reduce_3,
- 1, 16, :_reduce_4,
- 1, 17, :_reduce_5,
- 1, 17, :_reduce_6,
- 1, 17, :_reduce_none,
- 1, 17, :_reduce_8,
- 1, 17, :_reduce_9,
- 1, 17, :_reduce_10,
- 1, 17, :_reduce_11,
- 1, 21, :_reduce_12,
- 1, 22, :_reduce_13,
- 1, 18, :_reduce_14,
- 2, 23, :_reduce_15,
- 1, 23, :_reduce_16,
- 3, 19, :_reduce_17,
- 1, 25, :_reduce_18,
- 2, 24, :_reduce_19,
- 4, 24, :_reduce_20,
- 2, 24, :_reduce_21,
- 1, 24, :_reduce_22,
- 1, 26, :_reduce_none,
- 1, 26, :_reduce_none,
- 1, 26, :_reduce_none,
- 1, 26, :_reduce_none,
- 1, 20, :_reduce_27,
- 3, 20, :_reduce_28,
- 4, 20, :_reduce_29,
- 2, 31, :_reduce_30,
- 1, 31, :_reduce_31,
- 1, 27, :_reduce_32,
- 2, 32, :_reduce_33,
- 1, 32, :_reduce_34,
- 3, 33, :_reduce_35,
- 1, 28, :_reduce_36,
- 2, 36, :_reduce_37,
- 1, 36, :_reduce_38,
- 3, 37, :_reduce_39,
- 1, 29, :_reduce_40,
- 2, 39, :_reduce_41,
- 1, 39, :_reduce_42,
- 3, 40, :_reduce_43,
- 1, 30, :_reduce_44,
- 2, 42, :_reduce_45,
- 1, 42, :_reduce_46,
- 3, 43, :_reduce_47,
- 3, 41, :_reduce_48,
- 2, 41, :_reduce_49,
- 4, 41, :_reduce_50,
- 1, 41, :_reduce_51,
- 2, 45, :_reduce_52,
- 1, 45, :_reduce_none,
- 1, 46, :_reduce_54,
- 1, 46, :_reduce_55,
- 1, 46, :_reduce_none,
- 1, 46, :_reduce_57,
- 1, 44, :_reduce_none,
- 0, 44, :_reduce_none,
- 2, 47, :_reduce_none,
- 1, 47, :_reduce_none,
- 2, 34, :_reduce_62,
- 1, 34, :_reduce_63,
- 2, 38, :_reduce_64,
- 1, 38, :_reduce_65,
- 2, 35, :_reduce_66,
- 2, 35, :_reduce_67,
- 2, 35, :_reduce_68,
- 1, 35, :_reduce_69,
- 1, 35, :_reduce_none,
- 1, 35, :_reduce_71,
- 0, 35, :_reduce_72 ]
-
-racc_reduce_n = 73
-
-racc_shift_n = 89
-
-racc_token_table = {
- false => 0,
- :error => 1,
- :DUMMY => 2,
- :ITEMLISTLINE => 3,
- :ENUMLISTLINE => 4,
- :DESCLISTLINE => 5,
- :METHODLISTLINE => 6,
- :STRINGLINE => 7,
- :WHITELINE => 8,
- :SUBTREE => 9,
- :HEADLINE => 10,
- :INCLUDE => 11,
- :INDENT => 12,
- :DEDENT => 13 }
-
-racc_nt_base = 14
-
-racc_use_result_var = true
-
-Racc_arg = [
- racc_action_table,
- racc_action_check,
- racc_action_default,
- racc_action_pointer,
- racc_goto_table,
- racc_goto_check,
- racc_goto_default,
- racc_goto_pointer,
- racc_nt_base,
- racc_reduce_table,
- racc_token_table,
- racc_shift_n,
- racc_reduce_n,
- racc_use_result_var ]
-Ractor.make_shareable(Racc_arg) if defined?(Ractor)
-
-Racc_token_to_s_table = [
- "$end",
- "error",
- "DUMMY",
- "ITEMLISTLINE",
- "ENUMLISTLINE",
- "DESCLISTLINE",
- "METHODLISTLINE",
- "STRINGLINE",
- "WHITELINE",
- "SUBTREE",
- "HEADLINE",
- "INCLUDE",
- "INDENT",
- "DEDENT",
- "$start",
- "document",
- "blocks",
- "block",
- "textblock",
- "verbatim",
- "lists",
- "headline",
- "include",
- "textblockcontent",
- "verbatimcontent",
- "verbatim_after_lists",
- "list",
- "itemlist",
- "enumlist",
- "desclist",
- "methodlist",
- "lists2",
- "itemlistitems",
- "itemlistitem",
- "first_textblock_in_itemlist",
- "other_blocks_in_list",
- "enumlistitems",
- "enumlistitem",
- "first_textblock_in_enumlist",
- "desclistitems",
- "desclistitem",
- "description_part",
- "methodlistitems",
- "methodlistitem",
- "whitelines",
- "blocks_in_list",
- "block_in_list",
- "whitelines2" ]
-Ractor.make_shareable(Racc_token_to_s_table) if defined?(Ractor)
-
-Racc_debug_parser = false
-
-##### State transition tables end #####
-
-# reduce 0 omitted
-
-def _reduce_1(val, _values, result)
- result = RDoc::Markup::Document.new(*val[0])
- result
-end
-
-def _reduce_2(val, _values, result)
- raise ParseError, "file empty"
- result
-end
-
-def _reduce_3(val, _values, result)
- result = val[0].concat val[1]
- result
-end
-
-def _reduce_4(val, _values, result)
- result = val[0]
- result
-end
-
-def _reduce_5(val, _values, result)
- result = val
- result
-end
-
-def _reduce_6(val, _values, result)
- result = val
- result
-end
-
-# reduce 7 omitted
-
-def _reduce_8(val, _values, result)
- result = val
- result
-end
-
-def _reduce_9(val, _values, result)
- result = val
- result
-end
-
-def _reduce_10(val, _values, result)
- result = [RDoc::Markup::BlankLine.new]
- result
-end
-
-def _reduce_11(val, _values, result)
- result = val[0].parts
- result
-end
-
-def _reduce_12(val, _values, result)
- # val[0] is like [level, title]
- title = @inline_parser.parse(val[0][1])
- result = RDoc::Markup::Heading.new(val[0][0], title)
-
- result
-end
-
-def _reduce_13(val, _values, result)
- result = RDoc::Markup::Include.new val[0], @include_path
-
- result
-end
-
-def _reduce_14(val, _values, result)
- # val[0] is Array of String
- result = paragraph val[0]
-
- result
-end
-
-def _reduce_15(val, _values, result)
- result << val[1].rstrip
- result
-end
-
-def _reduce_16(val, _values, result)
- result = [val[0].rstrip]
- result
-end
-
-def _reduce_17(val, _values, result)
- # val[1] is Array of String
- content = cut_off val[1]
- result = RDoc::Markup::Verbatim.new(*content)
-
- # imform to lexer.
- @in_verbatim = false
-
- result
-end
-
-def _reduce_18(val, _values, result)
- # val[0] is Array of String
- content = cut_off val[0]
- result = RDoc::Markup::Verbatim.new(*content)
-
- # imform to lexer.
- @in_verbatim = false
-
- result
-end
-
-def _reduce_19(val, _values, result)
- result << val[1]
-
- result
-end
-
-def _reduce_20(val, _values, result)
- result.concat val[2]
-
- result
-end
-
-def _reduce_21(val, _values, result)
- result << "\n"
-
- result
-end
-
-def _reduce_22(val, _values, result)
- result = val
- # inform to lexer.
- @in_verbatim = true
-
- result
-end
-
-# reduce 23 omitted
-
-# reduce 24 omitted
-
-# reduce 25 omitted
-
-# reduce 26 omitted
-
-def _reduce_27(val, _values, result)
- result = val[0]
-
- result
-end
-
-def _reduce_28(val, _values, result)
- result = val[1]
-
- result
-end
-
-def _reduce_29(val, _values, result)
- result = val[1].push(val[2])
-
- result
-end
-
-def _reduce_30(val, _values, result)
- result = val[0] << val[1]
- result
-end
-
-def _reduce_31(val, _values, result)
- result = [val[0]]
- result
-end
-
-def _reduce_32(val, _values, result)
- result = RDoc::Markup::List.new :BULLET, *val[0]
-
- result
-end
-
-def _reduce_33(val, _values, result)
- result.push(val[1])
- result
-end
-
-def _reduce_34(val, _values, result)
- result = val
- result
-end
-
-def _reduce_35(val, _values, result)
- result = RDoc::Markup::ListItem.new nil, val[0], *val[1]
-
- result
-end
-
-def _reduce_36(val, _values, result)
- result = RDoc::Markup::List.new :NUMBER, *val[0]
-
- result
-end
-
-def _reduce_37(val, _values, result)
- result.push(val[1])
- result
-end
-
-def _reduce_38(val, _values, result)
- result = val
- result
-end
-
-def _reduce_39(val, _values, result)
- result = RDoc::Markup::ListItem.new nil, val[0], *val[1]
-
- result
-end
-
-def _reduce_40(val, _values, result)
- result = RDoc::Markup::List.new :NOTE, *val[0]
-
- result
-end
-
-def _reduce_41(val, _values, result)
- result.push(val[1])
- result
-end
-
-def _reduce_42(val, _values, result)
- result = val
- result
-end
-
-def _reduce_43(val, _values, result)
- term = @inline_parser.parse val[0].strip
-
- result = RDoc::Markup::ListItem.new term, *val[1]
-
- result
-end
-
-def _reduce_44(val, _values, result)
- result = RDoc::Markup::List.new :LABEL, *val[0]
-
- result
-end
-
-def _reduce_45(val, _values, result)
- result.push(val[1])
- result
-end
-
-def _reduce_46(val, _values, result)
- result = val
- result
-end
-
-def _reduce_47(val, _values, result)
- result = RDoc::Markup::ListItem.new "<tt>#{val[0].strip}</tt>", *val[1]
-
- result
-end
-
-def _reduce_48(val, _values, result)
- result = [val[1]].concat(val[2])
-
- result
-end
-
-def _reduce_49(val, _values, result)
- result = [val[1]]
-
- result
-end
-
-def _reduce_50(val, _values, result)
- result = val[2]
-
- result
-end
-
-def _reduce_51(val, _values, result)
- result = []
-
- result
-end
-
-def _reduce_52(val, _values, result)
- result.concat val[1]
- result
-end
-
-# reduce 53 omitted
-
-def _reduce_54(val, _values, result)
- result = val
- result
-end
-
-def _reduce_55(val, _values, result)
- result = val
- result
-end
-
-# reduce 56 omitted
-
-def _reduce_57(val, _values, result)
- result = []
- result
-end
-
-# reduce 58 omitted
-
-# reduce 59 omitted
-
-# reduce 60 omitted
-
-# reduce 61 omitted
-
-def _reduce_62(val, _values, result)
- result = paragraph [val[0]].concat(val[1])
-
- result
-end
-
-def _reduce_63(val, _values, result)
- result = paragraph [val[0]]
-
- result
-end
-
-def _reduce_64(val, _values, result)
- result = paragraph [val[0]].concat(val[1])
-
- result
-end
-
-def _reduce_65(val, _values, result)
- result = paragraph [val[0]]
-
- result
-end
-
-def _reduce_66(val, _values, result)
- result = [val[0]].concat(val[1])
-
- result
-end
-
-def _reduce_67(val, _values, result)
- result.concat val[1]
- result
-end
-
-def _reduce_68(val, _values, result)
- result = val[1]
- result
-end
-
-def _reduce_69(val, _values, result)
- result = val
- result
-end
-
-# reduce 70 omitted
-
-def _reduce_71(val, _values, result)
- result = []
- result
-end
-
-def _reduce_72(val, _values, result)
- result = []
- result
-end
-
-def _reduce_none(val, _values, result)
- val[0]
-end
-
-end # class BlockParser
-
-end
diff --git a/lib/rdoc/rd/inline.rb b/lib/rdoc/rd/inline.rb
deleted file mode 100644
index 77d88b2860..0000000000
--- a/lib/rdoc/rd/inline.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-# frozen_string_literal: true
-##
-# Inline keeps track of markup and labels to create proper links.
-
-class RDoc::RD::Inline
-
- ##
- # The text of the reference
-
- attr_reader :reference
-
- ##
- # The markup of this reference in RDoc format
-
- attr_reader :rdoc
-
- ##
- # Creates a new Inline for +rdoc+ and +reference+.
- #
- # +rdoc+ may be another Inline or a String. If +reference+ is not given it
- # will use the text from +rdoc+.
-
- def self.new rdoc, reference = rdoc
- if self === rdoc and reference.equal? rdoc then
- rdoc
- else
- super
- end
- end
-
- ##
- # Initializes the Inline with +rdoc+ and +inline+
-
- def initialize rdoc, reference # :not-new:
- @reference = reference.equal?(rdoc) ? reference.dup : reference
-
- # unpack
- @reference = @reference.reference if self.class === @reference
- @rdoc = rdoc
- end
-
- def == other # :nodoc:
- self.class === other and
- @reference == other.reference and @rdoc == other.rdoc
- end
-
- ##
- # Appends +more+ to this inline. +more+ may be a String or another Inline.
-
- def append more
- case more
- when String then
- @reference += more
- @rdoc += more
- when RDoc::RD::Inline then
- @reference += more.reference
- @rdoc += more.rdoc
- else
- raise "unknown thingy #{more}"
- end
-
- self
- end
-
- def inspect # :nodoc:
- "(inline: #{self})"
- end
-
- alias to_s rdoc # :nodoc:
-
-end
diff --git a/lib/rdoc/rd/inline_parser.rb b/lib/rdoc/rd/inline_parser.rb
deleted file mode 100644
index adacf64d5b..0000000000
--- a/lib/rdoc/rd/inline_parser.rb
+++ /dev/null
@@ -1,1858 +0,0 @@
-# frozen_string_literal: true
-#
-# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.7.3
-# from Racc grammar file "inline_parser.ry".
-#
-
-###### racc/parser.rb begin
-unless $".find {|p| p.end_with?('/racc/parser.rb')}
-$".push "#{__dir__}/racc/parser.rb"
-#--
-# Copyright (c) 1999-2006 Minero Aoki
-#
-# This program is free software.
-# You can distribute/modify this program under the same terms of ruby.
-#
-# As a special exception, when this code is copied by Racc
-# into a Racc output file, you may use that output file
-# without restriction.
-#++
-
-unless $".find {|p| p.end_with?('/racc/info.rb')}
-$".push "#{__dir__}/racc/info.rb"
-
-module Racc
- VERSION = '1.7.3'
- Version = VERSION
- Copyright = 'Copyright (c) 1999-2006 Minero Aoki'
-end
-
-end
-
-
-unless defined?(NotImplementedError)
- NotImplementedError = NotImplementError # :nodoc:
-end
-
-module Racc
- class ParseError < StandardError; end
-end
-unless defined?(::ParseError)
- ParseError = Racc::ParseError # :nodoc:
-end
-
-# Racc is a LALR(1) parser generator.
-# It is written in Ruby itself, and generates Ruby programs.
-#
-# == Command-line Reference
-#
-# racc [-o<var>filename</var>] [--output-file=<var>filename</var>]
-# [-e<var>rubypath</var>] [--executable=<var>rubypath</var>]
-# [-v] [--verbose]
-# [-O<var>filename</var>] [--log-file=<var>filename</var>]
-# [-g] [--debug]
-# [-E] [--embedded]
-# [-l] [--no-line-convert]
-# [-c] [--line-convert-all]
-# [-a] [--no-omit-actions]
-# [-C] [--check-only]
-# [-S] [--output-status]
-# [--version] [--copyright] [--help] <var>grammarfile</var>
-#
-# [+grammarfile+]
-# Racc grammar file. Any extension is permitted.
-# [-o+outfile+, --output-file=+outfile+]
-# A filename for output. default is <+filename+>.tab.rb
-# [-O+filename+, --log-file=+filename+]
-# Place logging output in file +filename+.
-# Default log file name is <+filename+>.output.
-# [-e+rubypath+, --executable=+rubypath+]
-# output executable file(mode 755). where +path+ is the Ruby interpreter.
-# [-v, --verbose]
-# verbose mode. create +filename+.output file, like yacc's y.output file.
-# [-g, --debug]
-# add debug code to parser class. To display debugging information,
-# use this '-g' option and set @yydebug true in parser class.
-# [-E, --embedded]
-# Output parser which doesn't need runtime files (racc/parser.rb).
-# [-F, --frozen]
-# Output parser which declares frozen_string_literals: true
-# [-C, --check-only]
-# Check syntax of racc grammar file and quit.
-# [-S, --output-status]
-# Print messages time to time while compiling.
-# [-l, --no-line-convert]
-# turns off line number converting.
-# [-c, --line-convert-all]
-# Convert line number of actions, inner, header and footer.
-# [-a, --no-omit-actions]
-# Call all actions, even if an action is empty.
-# [--version]
-# print Racc version and quit.
-# [--copyright]
-# Print copyright and quit.
-# [--help]
-# Print usage and quit.
-#
-# == Generating Parser Using Racc
-#
-# To compile Racc grammar file, simply type:
-#
-# $ racc parse.y
-#
-# This creates Ruby script file "parse.tab.y". The -o option can change the output filename.
-#
-# == Writing A Racc Grammar File
-#
-# If you want your own parser, you have to write a grammar file.
-# A grammar file contains the name of your parser class, grammar for the parser,
-# user code, and anything else.
-# When writing a grammar file, yacc's knowledge is helpful.
-# If you have not used yacc before, Racc is not too difficult.
-#
-# Here's an example Racc grammar file.
-#
-# class Calcparser
-# rule
-# target: exp { print val[0] }
-#
-# exp: exp '+' exp
-# | exp '*' exp
-# | '(' exp ')'
-# | NUMBER
-# end
-#
-# Racc grammar files resemble yacc files.
-# But (of course), this is Ruby code.
-# yacc's $$ is the 'result', $0, $1... is
-# an array called 'val', and $-1, $-2... is an array called '_values'.
-#
-# See the {Grammar File Reference}[rdoc-ref:lib/racc/rdoc/grammar.en.rdoc] for
-# more information on grammar files.
-#
-# == Parser
-#
-# Then you must prepare the parse entry method. There are two types of
-# parse methods in Racc, Racc::Parser#do_parse and Racc::Parser#yyparse
-#
-# Racc::Parser#do_parse is simple.
-#
-# It's yyparse() of yacc, and Racc::Parser#next_token is yylex().
-# This method must returns an array like [TOKENSYMBOL, ITS_VALUE].
-# EOF is [false, false].
-# (TOKENSYMBOL is a Ruby symbol (taken from String#intern) by default.
-# If you want to change this, see the grammar reference.
-#
-# Racc::Parser#yyparse is little complicated, but useful.
-# It does not use Racc::Parser#next_token, instead it gets tokens from any iterator.
-#
-# For example, <code>yyparse(obj, :scan)</code> causes
-# calling +obj#scan+, and you can return tokens by yielding them from +obj#scan+.
-#
-# == Debugging
-#
-# When debugging, "-v" or/and the "-g" option is helpful.
-#
-# "-v" creates verbose log file (.output).
-# "-g" creates a "Verbose Parser".
-# Verbose Parser prints the internal status when parsing.
-# But it's _not_ automatic.
-# You must use -g option and set +@yydebug+ to +true+ in order to get output.
-# -g option only creates the verbose parser.
-#
-# === Racc reported syntax error.
-#
-# Isn't there too many "end"?
-# grammar of racc file is changed in v0.10.
-#
-# Racc does not use '%' mark, while yacc uses huge number of '%' marks..
-#
-# === Racc reported "XXXX conflicts".
-#
-# Try "racc -v xxxx.y".
-# It causes producing racc's internal log file, xxxx.output.
-#
-# === Generated parsers does not work correctly
-#
-# Try "racc -g xxxx.y".
-# This command let racc generate "debugging parser".
-# Then set @yydebug=true in your parser.
-# It produces a working log of your parser.
-#
-# == Re-distributing Racc runtime
-#
-# A parser, which is created by Racc, requires the Racc runtime module;
-# racc/parser.rb.
-#
-# Ruby 1.8.x comes with Racc runtime module,
-# you need NOT distribute Racc runtime files.
-#
-# If you want to include the Racc runtime module with your parser.
-# This can be done by using '-E' option:
-#
-# $ racc -E -omyparser.rb myparser.y
-#
-# This command creates myparser.rb which `includes' Racc runtime.
-# Only you must do is to distribute your parser file (myparser.rb).
-#
-# Note: parser.rb is ruby license, but your parser is not.
-# Your own parser is completely yours.
-module Racc
-
- unless defined?(Racc_No_Extensions)
- Racc_No_Extensions = false # :nodoc:
- end
-
- class Parser
-
- Racc_Runtime_Version = ::Racc::VERSION
- Racc_Runtime_Core_Version_R = ::Racc::VERSION
-
- 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
-
- unless new.respond_to?(:_racc_do_parse_c, true)
- raise LoadError, 'old cparse.so'
- end
- 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_Type = 'c' # :nodoc:
- rescue LoadError
- 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_Type = 'ruby'
- end
-
- def Parser.racc_runtime_type # :nodoc:
- Racc_Runtime_Type
- end
-
- def _racc_setup
- @yydebug = false unless self.class::Racc_debug_parser
- @yydebug = false unless defined?(@yydebug)
- if @yydebug
- @racc_debug_out = $stderr unless defined?(@racc_debug_out)
- @racc_debug_out ||= $stderr
- end
- arg = self.class::Racc_arg
- arg[13] = true if arg.size < 14
- arg
- end
-
- def _racc_init_sysvars
- @racc_state = [0]
- @racc_tstack = []
- @racc_vstack = []
-
- @racc_t = nil
- @racc_val = nil
-
- @racc_read_next = true
-
- @racc_user_yyerror = false
- @racc_error_status = 0
- end
-
- # The entry point of the parser. This method is used with #next_token.
- # If Racc wants to get token (and its value), calls next_token.
- #
- # Example:
- # def parse
- # @q = [[1,1],
- # [2,2],
- # [3,3],
- # [false, '$']]
- # do_parse
- # end
- #
- # def next_token
- # @q.shift
- # end
- class_eval <<~RUBY, __FILE__, __LINE__ + 1
- def do_parse
- #{Racc_Main_Parsing_Routine}(_racc_setup(), false)
- end
- RUBY
-
- # The method to fetch next token.
- # If you use #do_parse method, you must implement #next_token.
- #
- # The format of return value is [TOKEN_SYMBOL, VALUE].
- # +token-symbol+ is represented by Ruby's symbol by default, e.g. :IDENT
- # for 'IDENT'. ";" (String) for ';'.
- #
- # The final symbol (End of file) must be false.
- def next_token
- raise NotImplementedError, "#{self.class}\#next_token is not defined"
- end
-
- def _racc_do_parse_rb(arg, in_debug)
- action_table, action_check, action_default, action_pointer,
- _, _, _, _,
- _, _, token_table, * = arg
-
- _racc_init_sysvars
- tok = act = i = nil
-
- catch(:racc_end_parse) {
- while true
- if i = action_pointer[@racc_state[-1]]
- if @racc_read_next
- if @racc_t != 0 # not EOF
- tok, @racc_val = next_token()
- unless tok # EOF
- @racc_t = 0
- else
- @racc_t = (token_table[tok] or 1) # error token
- end
- racc_read_token(@racc_t, tok, @racc_val) if @yydebug
- @racc_read_next = false
- end
- end
- i += @racc_t
- unless i >= 0 and
- act = action_table[i] and
- action_check[i] == @racc_state[-1]
- act = action_default[@racc_state[-1]]
- end
- else
- act = action_default[@racc_state[-1]]
- end
- while act = _racc_evalact(act, arg)
- ;
- end
- end
- }
- end
-
- # Another entry point for the parser.
- # If you use this method, you must implement RECEIVER#METHOD_ID method.
- #
- # RECEIVER#METHOD_ID is a method to get next token.
- # It must 'yield' the token, which format is [TOKEN-SYMBOL, VALUE].
- class_eval <<~RUBY, __FILE__, __LINE__ + 1
- def yyparse(recv, mid)
- #{Racc_YY_Parse_Method}(recv, mid, _racc_setup(), false)
- end
- RUBY
-
- def _racc_yyparse_rb(recv, mid, arg, c_debug)
- action_table, action_check, action_default, action_pointer,
- _, _, _, _,
- _, _, token_table, * = arg
-
- _racc_init_sysvars
-
- catch(:racc_end_parse) {
- until i = action_pointer[@racc_state[-1]]
- while act = _racc_evalact(action_default[@racc_state[-1]], arg)
- ;
- end
- end
- recv.__send__(mid) do |tok, val|
- unless tok
- @racc_t = 0
- else
- @racc_t = (token_table[tok] or 1) # error token
- end
- @racc_val = val
- @racc_read_next = false
-
- i += @racc_t
- unless i >= 0 and
- act = action_table[i] and
- action_check[i] == @racc_state[-1]
- act = action_default[@racc_state[-1]]
- end
- while act = _racc_evalact(act, arg)
- ;
- end
-
- while !(i = action_pointer[@racc_state[-1]]) ||
- ! @racc_read_next ||
- @racc_t == 0 # $
- unless i and i += @racc_t and
- i >= 0 and
- act = action_table[i] and
- action_check[i] == @racc_state[-1]
- act = action_default[@racc_state[-1]]
- end
- while act = _racc_evalact(act, arg)
- ;
- end
- end
- end
- }
- end
-
- ###
- ### common
- ###
-
- def _racc_evalact(act, arg)
- action_table, action_check, _, action_pointer,
- _, _, _, _,
- _, _, _, shift_n,
- reduce_n, * = arg
- nerr = 0 # tmp
-
- if act > 0 and act < shift_n
- #
- # shift
- #
- if @racc_error_status > 0
- @racc_error_status -= 1 unless @racc_t <= 1 # error token or EOF
- end
- @racc_vstack.push @racc_val
- @racc_state.push act
- @racc_read_next = true
- if @yydebug
- @racc_tstack.push @racc_t
- racc_shift @racc_t, @racc_tstack, @racc_vstack
- end
-
- elsif act < 0 and act > -reduce_n
- #
- # reduce
- #
- code = catch(:racc_jump) {
- @racc_state.push _racc_do_reduce(arg, act)
- false
- }
- if code
- case code
- when 1 # yyerror
- @racc_user_yyerror = true # user_yyerror
- return -reduce_n
- when 2 # yyaccept
- return shift_n
- else
- raise '[Racc Bug] unknown jump code'
- end
- end
-
- elsif act == shift_n
- #
- # accept
- #
- racc_accept if @yydebug
- throw :racc_end_parse, @racc_vstack[0]
-
- elsif act == -reduce_n
- #
- # error
- #
- case @racc_error_status
- when 0
- unless arg[21] # user_yyerror
- nerr += 1
- on_error @racc_t, @racc_val, @racc_vstack
- end
- when 3
- if @racc_t == 0 # is $
- # We're at EOF, and another error occurred immediately after
- # attempting auto-recovery
- throw :racc_end_parse, nil
- end
- @racc_read_next = true
- end
- @racc_user_yyerror = false
- @racc_error_status = 3
- while true
- if i = action_pointer[@racc_state[-1]]
- i += 1 # error token
- if i >= 0 and
- (act = action_table[i]) and
- action_check[i] == @racc_state[-1]
- break
- end
- end
- throw :racc_end_parse, nil if @racc_state.size <= 1
- @racc_state.pop
- @racc_vstack.pop
- if @yydebug
- @racc_tstack.pop
- racc_e_pop @racc_state, @racc_tstack, @racc_vstack
- end
- end
- return act
-
- else
- raise "[Racc Bug] unknown action #{act.inspect}"
- end
-
- racc_next_state(@racc_state[-1], @racc_state) if @yydebug
-
- nil
- end
-
- def _racc_do_reduce(arg, act)
- _, _, _, _,
- goto_table, goto_check, goto_default, goto_pointer,
- nt_base, reduce_table, _, _,
- _, use_result, * = arg
-
- state = @racc_state
- vstack = @racc_vstack
- tstack = @racc_tstack
-
- i = act * -3
- len = reduce_table[i]
- reduce_to = reduce_table[i+1]
- method_id = reduce_table[i+2]
- void_array = []
-
- tmp_t = tstack[-len, len] if @yydebug
- tmp_v = vstack[-len, len]
- tstack[-len, len] = void_array if @yydebug
- vstack[-len, len] = void_array
- state[-len, len] = void_array
-
- # tstack must be updated AFTER method call
- if use_result
- vstack.push __send__(method_id, tmp_v, vstack, tmp_v[0])
- else
- vstack.push __send__(method_id, tmp_v, vstack)
- end
- tstack.push reduce_to
-
- racc_reduce(tmp_t, reduce_to, tstack, vstack) if @yydebug
-
- k1 = reduce_to - nt_base
- if i = goto_pointer[k1]
- i += state[-1]
- if i >= 0 and (curstate = goto_table[i]) and goto_check[i] == k1
- return curstate
- end
- end
- goto_default[k1]
- end
-
- # This method is called when a parse error is found.
- #
- # ERROR_TOKEN_ID is an internal ID of token which caused error.
- # You can get string representation of this ID by calling
- # #token_to_str.
- #
- # ERROR_VALUE is a value of error token.
- #
- # value_stack is a stack of symbol values.
- # DO NOT MODIFY this object.
- #
- # This method raises ParseError by default.
- #
- # If this method returns, parsers enter "error recovering mode".
- def on_error(t, val, vstack)
- raise ParseError, sprintf("parse error on value %s (%s)",
- val.inspect, token_to_str(t) || '?')
- end
-
- # Enter error recovering mode.
- # This method does not call #on_error.
- def yyerror
- throw :racc_jump, 1
- end
-
- # Exit parser.
- # Return value is +Symbol_Value_Stack[0]+.
- def yyaccept
- throw :racc_jump, 2
- end
-
- # Leave error recovering mode.
- def yyerrok
- @racc_error_status = 0
- end
-
- # For debugging output
- def racc_read_token(t, tok, val)
- @racc_debug_out.print 'read '
- @racc_debug_out.print tok.inspect, '(', racc_token2str(t), ') '
- @racc_debug_out.puts val.inspect
- @racc_debug_out.puts
- end
-
- def racc_shift(tok, tstack, vstack)
- @racc_debug_out.puts "shift #{racc_token2str tok}"
- racc_print_stacks tstack, vstack
- @racc_debug_out.puts
- end
-
- def racc_reduce(toks, sim, tstack, vstack)
- out = @racc_debug_out
- out.print 'reduce '
- if toks.empty?
- out.print ' <none>'
- else
- toks.each {|t| out.print ' ', racc_token2str(t) }
- end
- out.puts " --> #{racc_token2str(sim)}"
- racc_print_stacks tstack, vstack
- @racc_debug_out.puts
- end
-
- def racc_accept
- @racc_debug_out.puts 'accept'
- @racc_debug_out.puts
- end
-
- def racc_e_pop(state, tstack, vstack)
- @racc_debug_out.puts 'error recovering mode: pop token'
- racc_print_states state
- racc_print_stacks tstack, vstack
- @racc_debug_out.puts
- end
-
- def racc_next_state(curstate, state)
- @racc_debug_out.puts "goto #{curstate}"
- racc_print_states state
- @racc_debug_out.puts
- end
-
- def racc_print_stacks(t, v)
- out = @racc_debug_out
- out.print ' ['
- t.each_index do |i|
- out.print ' (', racc_token2str(t[i]), ' ', v[i].inspect, ')'
- end
- out.puts ' ]'
- end
-
- def racc_print_states(s)
- out = @racc_debug_out
- out.print ' ['
- s.each {|st| out.print ' ', st }
- out.puts ' ]'
- end
-
- def racc_token2str(tok)
- self.class::Racc_token_to_s_table[tok] or
- raise "[Racc Bug] can't convert token #{tok} to string"
- end
-
- # Convert internal ID of token symbol to the string.
- def token_to_str(t)
- self.class::Racc_token_to_s_table[t]
- end
-
- end
-
-end
-
-end
-###### racc/parser.rb end
-
-require 'strscan'
-
-class RDoc::RD
-
-##
-# RD format parser for inline markup such as emphasis, links, footnotes, etc.
-
-class InlineParser < Racc::Parser
-
-
-# :stopdoc:
-
-EM_OPEN = '((*'
-EM_OPEN_RE = /\A#{Regexp.quote(EM_OPEN)}/
-EM_CLOSE = '*))'
-EM_CLOSE_RE = /\A#{Regexp.quote(EM_CLOSE)}/
-CODE_OPEN = '(({'
-CODE_OPEN_RE = /\A#{Regexp.quote(CODE_OPEN)}/
-CODE_CLOSE = '}))'
-CODE_CLOSE_RE = /\A#{Regexp.quote(CODE_CLOSE)}/
-VAR_OPEN = '((|'
-VAR_OPEN_RE = /\A#{Regexp.quote(VAR_OPEN)}/
-VAR_CLOSE = '|))'
-VAR_CLOSE_RE = /\A#{Regexp.quote(VAR_CLOSE)}/
-KBD_OPEN = '((%'
-KBD_OPEN_RE = /\A#{Regexp.quote(KBD_OPEN)}/
-KBD_CLOSE = '%))'
-KBD_CLOSE_RE = /\A#{Regexp.quote(KBD_CLOSE)}/
-INDEX_OPEN = '((:'
-INDEX_OPEN_RE = /\A#{Regexp.quote(INDEX_OPEN)}/
-INDEX_CLOSE = ':))'
-INDEX_CLOSE_RE = /\A#{Regexp.quote(INDEX_CLOSE)}/
-REF_OPEN = '((<'
-REF_OPEN_RE = /\A#{Regexp.quote(REF_OPEN)}/
-REF_CLOSE = '>))'
-REF_CLOSE_RE = /\A#{Regexp.quote(REF_CLOSE)}/
-FOOTNOTE_OPEN = '((-'
-FOOTNOTE_OPEN_RE = /\A#{Regexp.quote(FOOTNOTE_OPEN)}/
-FOOTNOTE_CLOSE = '-))'
-FOOTNOTE_CLOSE_RE = /\A#{Regexp.quote(FOOTNOTE_CLOSE)}/
-VERB_OPEN = "(('"
-VERB_OPEN_RE = /\A#{Regexp.quote(VERB_OPEN)}/
-VERB_CLOSE = "'))"
-VERB_CLOSE_RE = /\A#{Regexp.quote(VERB_CLOSE)}/
-
-BAR = "|"
-BAR_RE = /\A#{Regexp.quote(BAR)}/
-QUOTE = '"'
-QUOTE_RE = /\A#{Regexp.quote(QUOTE)}/
-SLASH = "/"
-SLASH_RE = /\A#{Regexp.quote(SLASH)}/
-BACK_SLASH = "\\"
-BACK_SLASH_RE = /\A#{Regexp.quote(BACK_SLASH)}/
-URL = "URL:"
-URL_RE = /\A#{Regexp.quote(URL)}/
-
-other_re_mode = Regexp::EXTENDED
-other_re_mode |= Regexp::MULTILINE
-
-OTHER_RE = Regexp.new(
- "\\A.+?(?=#{Regexp.quote(EM_OPEN)}|#{Regexp.quote(EM_CLOSE)}|
- #{Regexp.quote(CODE_OPEN)}|#{Regexp.quote(CODE_CLOSE)}|
- #{Regexp.quote(VAR_OPEN)}|#{Regexp.quote(VAR_CLOSE)}|
- #{Regexp.quote(KBD_OPEN)}|#{Regexp.quote(KBD_CLOSE)}|
- #{Regexp.quote(INDEX_OPEN)}|#{Regexp.quote(INDEX_CLOSE)}|
- #{Regexp.quote(REF_OPEN)}|#{Regexp.quote(REF_CLOSE)}|
- #{Regexp.quote(FOOTNOTE_OPEN)}|#{Regexp.quote(FOOTNOTE_CLOSE)}|
- #{Regexp.quote(VERB_OPEN)}|#{Regexp.quote(VERB_CLOSE)}|
- #{Regexp.quote(BAR)}|
- #{Regexp.quote(QUOTE)}|
- #{Regexp.quote(SLASH)}|
- #{Regexp.quote(BACK_SLASH)}|
- #{Regexp.quote(URL)})", other_re_mode)
-
-# :startdoc:
-
-##
-# Creates a new parser for inline markup in the rd format. The +block_parser+
-# is used to for footnotes and labels in the inline text.
-
-def initialize block_parser
- @block_parser = block_parser
-end
-
-##
-# Parses the +inline+ text from RD format into RDoc format.
-
-def parse inline
- @inline = inline
- @src = StringScanner.new inline
- @pre = "".dup
- @yydebug = true
- do_parse.to_s
-end
-
-##
-# Returns the next token from the inline text
-
-def next_token
- return [false, false] if @src.eos?
-# p @src.rest if @yydebug
- if ret = @src.scan(EM_OPEN_RE)
- @pre << ret
- [:EM_OPEN, ret]
- elsif ret = @src.scan(EM_CLOSE_RE)
- @pre << ret
- [:EM_CLOSE, ret]
- elsif ret = @src.scan(CODE_OPEN_RE)
- @pre << ret
- [:CODE_OPEN, ret]
- elsif ret = @src.scan(CODE_CLOSE_RE)
- @pre << ret
- [:CODE_CLOSE, ret]
- elsif ret = @src.scan(VAR_OPEN_RE)
- @pre << ret
- [:VAR_OPEN, ret]
- elsif ret = @src.scan(VAR_CLOSE_RE)
- @pre << ret
- [:VAR_CLOSE, ret]
- elsif ret = @src.scan(KBD_OPEN_RE)
- @pre << ret
- [:KBD_OPEN, ret]
- elsif ret = @src.scan(KBD_CLOSE_RE)
- @pre << ret
- [:KBD_CLOSE, ret]
- elsif ret = @src.scan(INDEX_OPEN_RE)
- @pre << ret
- [:INDEX_OPEN, ret]
- elsif ret = @src.scan(INDEX_CLOSE_RE)
- @pre << ret
- [:INDEX_CLOSE, ret]
- elsif ret = @src.scan(REF_OPEN_RE)
- @pre << ret
- [:REF_OPEN, ret]
- elsif ret = @src.scan(REF_CLOSE_RE)
- @pre << ret
- [:REF_CLOSE, ret]
- elsif ret = @src.scan(FOOTNOTE_OPEN_RE)
- @pre << ret
- [:FOOTNOTE_OPEN, ret]
- elsif ret = @src.scan(FOOTNOTE_CLOSE_RE)
- @pre << ret
- [:FOOTNOTE_CLOSE, ret]
- elsif ret = @src.scan(VERB_OPEN_RE)
- @pre << ret
- [:VERB_OPEN, ret]
- elsif ret = @src.scan(VERB_CLOSE_RE)
- @pre << ret
- [:VERB_CLOSE, ret]
- elsif ret = @src.scan(BAR_RE)
- @pre << ret
- [:BAR, ret]
- elsif ret = @src.scan(QUOTE_RE)
- @pre << ret
- [:QUOTE, ret]
- elsif ret = @src.scan(SLASH_RE)
- @pre << ret
- [:SLASH, ret]
- elsif ret = @src.scan(BACK_SLASH_RE)
- @pre << ret
- [:BACK_SLASH, ret]
- elsif ret = @src.scan(URL_RE)
- @pre << ret
- [:URL, ret]
- elsif ret = @src.scan(OTHER_RE)
- @pre << ret
- [:OTHER, ret]
- else
- ret = @src.rest
- @pre << ret
- @src.terminate
- [:OTHER, ret]
- end
-end
-
-##
-# Raises a ParseError when invalid formatting is found
-
-def on_error(et, ev, values)
- lines_of_rest = @src.rest.lines.to_a.length
- prev_words = prev_words_on_error(ev)
- at = 4 + prev_words.length
-
- message = <<-MSG
-RD syntax error: line #{@block_parser.line_index - lines_of_rest}:
-...#{prev_words} #{(ev||'')} #{next_words_on_error()} ...
- MSG
-
- message << " " * at + "^" * (ev ? ev.length : 0) + "\n"
- raise ParseError, message
-end
-
-##
-# Returns words before the error
-
-def prev_words_on_error(ev)
- pre = @pre
- if ev and /#{Regexp.quote(ev)}$/ =~ pre
- pre = $`
- end
- last_line(pre)
-end
-
-##
-# Returns the last line of +src+
-
-def last_line(src)
- if n = src.rindex("\n")
- src[(n+1) .. -1]
- else
- src
- end
-end
-private :last_line
-
-##
-# Returns words following an error
-
-def next_words_on_error
- if n = @src.rest.index("\n")
- @src.rest[0 .. (n-1)]
- else
- @src.rest
- end
-end
-
-##
-# Creates a new RDoc::RD::Inline for the +rdoc+ markup and the raw +reference+
-
-def inline rdoc, reference = rdoc
- RDoc::RD::Inline.new rdoc, reference
-end
-
-# :stopdoc:
-##### State transition tables begin ###
-
-racc_action_table = [
- 104, 103, 102, 100, 101, 99, 115, 116, 117, 29,
- 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
- 84, 118, 119, 63, 64, 65, 61, 81, 62, 76,
- 78, 79, 85, 66, 67, 68, 69, 70, 71, 72,
- 73, 74, 75, 77, 80, 149, 63, 64, 65, 153,
- 81, 62, 76, 78, 79, 86, 66, 67, 68, 69,
- 70, 71, 72, 73, 74, 75, 77, 80, 152, 104,
- 103, 102, 100, 101, 99, 115, 116, 117, 87, 105,
- 106, 107, 108, 109, 110, 111, 112, 113, 114, 88,
- 118, 119, 104, 103, 102, 100, 101, 99, 115, 116,
- 117, 89, 105, 106, 107, 108, 109, 110, 111, 112,
- 113, 114, 96, 118, 119, 104, 103, 102, 100, 101,
- 99, 115, 116, 117, 124, 105, 106, 107, 108, 109,
- 110, 111, 112, 113, 114, 137, 118, 119, 22, 23,
- 24, 25, 26, 21, 18, 19, 176, 177, 13, 148,
- 14, 154, 15, 137, 16, 161, 17, 164, 173, 20,
- 22, 23, 24, 25, 26, 21, 18, 19, 175, 177,
- 13, nil, 14, nil, 15, nil, 16, nil, 17, nil,
- nil, 20, 22, 23, 24, 25, 26, 21, 18, 19,
- nil, nil, 13, nil, 14, nil, 15, nil, 16, nil,
- 17, nil, nil, 20, 22, 23, 24, 25, 26, 21,
- 18, 19, nil, nil, 13, nil, 14, nil, 15, nil,
- 16, nil, 17, nil, nil, 20, 22, 23, 24, 25,
- 26, 21, 18, 19, nil, nil, 13, nil, 14, nil,
- 15, nil, 16, nil, 17, nil, nil, 20, 22, 23,
- 24, 25, 26, 21, 18, 19, nil, nil, 13, nil,
- 14, nil, 15, nil, 16, nil, 17, nil, nil, 20,
- 22, 23, 24, 25, 26, 21, 18, 19, nil, nil,
- 13, nil, 14, nil, 15, nil, 16, nil, 17, 42,
- nil, 20, 54, 38, 53, 55, 56, 57, nil, 13,
- nil, 14, nil, 15, nil, 16, nil, 17, nil, nil,
- 20, 22, 23, 24, 25, 26, 21, 18, 19, nil,
- nil, 13, nil, 14, nil, 15, nil, 16, nil, 17,
- nil, nil, 20, 63, 64, 65, 61, 81, 62, 76,
- 78, 79, nil, 66, 67, 68, 69, 70, 71, 72,
- 73, 74, 75, 77, 80, 122, nil, nil, 54, nil,
- 53, 55, 56, 57, nil, 13, nil, 14, nil, 15,
- nil, 16, nil, 17, 145, nil, 20, 54, 133, 53,
- 55, 56, 57, nil, 13, nil, 14, nil, 15, nil,
- 16, nil, 17, 145, nil, 20, 54, 133, 53, 55,
- 56, 57, nil, 13, nil, 14, nil, 15, nil, 16,
- nil, 17, 145, nil, 20, 54, 133, 53, 55, 56,
- 57, nil, 13, nil, 14, nil, 15, nil, 16, nil,
- 17, 145, nil, 20, 54, 133, 53, 55, 56, 57,
- nil, 13, nil, 14, nil, 15, nil, 16, nil, 17,
- nil, nil, 20, 135, 136, 54, 133, 53, 55, 56,
- 57, nil, 13, nil, 14, nil, 15, nil, 16, nil,
- 17, nil, nil, 20, 135, 136, 54, 133, 53, 55,
- 56, 57, nil, 13, nil, 14, nil, 15, nil, 16,
- nil, 17, nil, nil, 20, 135, 136, 54, 133, 53,
- 55, 56, 57, nil, 13, nil, 14, nil, 15, nil,
- 16, nil, 17, 95, nil, 20, 54, 91, 53, 55,
- 56, 57, 145, nil, nil, 54, 133, 53, 55, 56,
- 57, 158, nil, nil, 54, nil, 53, 55, 56, 57,
- 165, 135, 136, 54, 133, 53, 55, 56, 57, 145,
- nil, nil, 54, 133, 53, 55, 56, 57, 172, 135,
- 136, 54, 133, 53, 55, 56, 57, 174, 135, 136,
- 54, 133, 53, 55, 56, 57, 178, 135, 136, 54,
- 133, 53, 55, 56, 57, 135, 136, 54, 133, 53,
- 55, 56, 57, 135, 136, 54, 133, 53, 55, 56,
- 57, 135, 136, 54, 133, 53, 55, 56, 57, 22,
- 23, 24, 25, 26, 21 ]
-
-racc_action_check = [
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 1,
- 38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 29, 38, 38, 59, 59, 59, 59, 59, 59, 59,
- 59, 59, 31, 59, 59, 59, 59, 59, 59, 59,
- 59, 59, 59, 59, 59, 59, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 32, 61, 61, 61, 61,
- 61, 61, 61, 61, 61, 61, 61, 61, 61, 91,
- 91, 91, 91, 91, 91, 91, 91, 91, 33, 91,
- 91, 91, 91, 91, 91, 91, 91, 91, 91, 34,
- 91, 91, 97, 97, 97, 97, 97, 97, 97, 97,
- 97, 35, 97, 97, 97, 97, 97, 97, 97, 97,
- 97, 97, 37, 97, 97, 155, 155, 155, 155, 155,
- 155, 155, 155, 155, 41, 155, 155, 155, 155, 155,
- 155, 155, 155, 155, 155, 43, 155, 155, 0, 0,
- 0, 0, 0, 0, 0, 0, 165, 165, 0, 58,
- 0, 90, 0, 94, 0, 100, 0, 125, 162, 0,
- 2, 2, 2, 2, 2, 2, 2, 2, 164, 172,
- 2, nil, 2, nil, 2, nil, 2, nil, 2, nil,
- nil, 2, 13, 13, 13, 13, 13, 13, 13, 13,
- nil, nil, 13, nil, 13, nil, 13, nil, 13, nil,
- 13, nil, nil, 13, 14, 14, 14, 14, 14, 14,
- 14, 14, nil, nil, 14, nil, 14, nil, 14, nil,
- 14, nil, 14, nil, nil, 14, 15, 15, 15, 15,
- 15, 15, 15, 15, nil, nil, 15, nil, 15, nil,
- 15, nil, 15, nil, 15, nil, nil, 15, 16, 16,
- 16, 16, 16, 16, 16, 16, nil, nil, 16, nil,
- 16, nil, 16, nil, 16, nil, 16, nil, nil, 16,
- 17, 17, 17, 17, 17, 17, 17, 17, nil, nil,
- 17, nil, 17, nil, 17, nil, 17, nil, 17, 18,
- nil, 17, 18, 18, 18, 18, 18, 18, nil, 18,
- nil, 18, nil, 18, nil, 18, nil, 18, nil, nil,
- 18, 19, 19, 19, 19, 19, 19, 19, 19, nil,
- nil, 19, nil, 19, nil, 19, nil, 19, nil, 19,
- nil, nil, 19, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, nil, 20, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 20, 20, 39, nil, nil, 39, nil,
- 39, 39, 39, 39, nil, 39, nil, 39, nil, 39,
- nil, 39, nil, 39, 44, nil, 39, 44, 44, 44,
- 44, 44, 44, nil, 44, nil, 44, nil, 44, nil,
- 44, nil, 44, 45, nil, 44, 45, 45, 45, 45,
- 45, 45, nil, 45, nil, 45, nil, 45, nil, 45,
- nil, 45, 138, nil, 45, 138, 138, 138, 138, 138,
- 138, nil, 138, nil, 138, nil, 138, nil, 138, nil,
- 138, 146, nil, 138, 146, 146, 146, 146, 146, 146,
- nil, 146, nil, 146, nil, 146, nil, 146, nil, 146,
- nil, nil, 146, 42, 42, 42, 42, 42, 42, 42,
- 42, nil, 42, nil, 42, nil, 42, nil, 42, nil,
- 42, nil, nil, 42, 122, 122, 122, 122, 122, 122,
- 122, 122, nil, 122, nil, 122, nil, 122, nil, 122,
- nil, 122, nil, nil, 122, 127, 127, 127, 127, 127,
- 127, 127, 127, nil, 127, nil, 127, nil, 127, nil,
- 127, nil, 127, 36, nil, 127, 36, 36, 36, 36,
- 36, 36, 52, nil, nil, 52, 52, 52, 52, 52,
- 52, 92, nil, nil, 92, nil, 92, 92, 92, 92,
- 126, 126, 126, 126, 126, 126, 126, 126, 126, 142,
- nil, nil, 142, 142, 142, 142, 142, 142, 159, 159,
- 159, 159, 159, 159, 159, 159, 159, 163, 163, 163,
- 163, 163, 163, 163, 163, 163, 171, 171, 171, 171,
- 171, 171, 171, 171, 171, 95, 95, 95, 95, 95,
- 95, 95, 95, 158, 158, 158, 158, 158, 158, 158,
- 158, 168, 168, 168, 168, 168, 168, 168, 168, 27,
- 27, 27, 27, 27, 27 ]
-
-racc_action_pointer = [
- 135, 9, 157, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 179, 201, 223, 245, 267, 286, 308,
- 330, nil, nil, nil, nil, nil, nil, 606, nil, 20,
- nil, 18, 39, 60, 69, 79, 510, 89, -3, 352,
- nil, 120, 449, 130, 371, 390, nil, nil, nil, nil,
- nil, nil, 519, nil, nil, nil, nil, nil, 138, 20,
- nil, 43, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 128, 66, 528, nil, 148, 581, nil, 89, nil, nil,
- 149, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 470, nil, nil, 154, 537, 491, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 409, nil,
- nil, nil, 546, nil, nil, nil, 428, nil, nil, nil,
- nil, nil, nil, nil, nil, 112, nil, nil, 589, 555,
- nil, nil, 155, 564, 164, 142, nil, nil, 597, nil,
- nil, 573, 164, nil, nil, nil, nil, nil, nil ]
-
-racc_action_default = [
- -138, -138, -1, -3, -4, -5, -6, -7, -8, -9,
- -10, -11, -12, -138, -138, -138, -138, -138, -138, -138,
- -138, -103, -104, -105, -106, -107, -108, -111, -110, -138,
- -2, -138, -138, -138, -138, -138, -138, -138, -138, -27,
- -26, -35, -138, -58, -41, -40, -47, -48, -49, -50,
- -51, -52, -63, -66, -67, -68, -69, -70, -138, -138,
- -112, -138, -116, -117, -118, -119, -120, -121, -122, -123,
- -124, -125, -126, -127, -128, -129, -130, -131, -132, -133,
- -134, -135, -137, -109, 179, -13, -14, -15, -16, -17,
- -138, -138, -23, -22, -33, -138, -19, -24, -79, -80,
- -138, -82, -83, -84, -85, -86, -87, -88, -89, -90,
- -91, -92, -93, -94, -95, -96, -97, -98, -99, -100,
- -25, -35, -138, -58, -28, -138, -59, -42, -46, -55,
- -56, -65, -71, -72, -75, -76, -77, -31, -38, -44,
- -53, -54, -57, -61, -73, -74, -39, -62, -101, -102,
- -136, -113, -114, -115, -18, -20, -21, -33, -138, -138,
- -78, -81, -138, -59, -36, -37, -64, -45, -59, -43,
- -60, -138, -34, -36, -37, -29, -30, -32, -34 ]
-
-racc_goto_table = [
- 126, 44, 125, 43, 144, 144, 160, 93, 97, 52,
- 166, 82, 144, 40, 41, 39, 138, 146, 169, 30,
- 36, 94, 44, 1, 123, 129, 169, 52, 90, 37,
- 52, 167, 147, 92, 120, 121, 31, 32, 33, 34,
- 35, 170, 58, 166, 59, 83, 170, 166, 151, nil,
- 150, nil, 166, 159, 4, 166, 4, nil, nil, nil,
- nil, 155, nil, 156, 160, nil, nil, 4, 4, 4,
- 4, 4, nil, 4, 5, nil, 5, 157, nil, nil,
- 163, nil, 162, 52, nil, 168, nil, 5, 5, 5,
- 5, 5, nil, 5, nil, nil, nil, nil, 144, nil,
- nil, nil, 144, nil, nil, 129, 144, 144, nil, 6,
- 129, 6, nil, nil, nil, nil, 171, 7, nil, 7,
- nil, nil, 6, 6, 6, 6, 6, 8, 6, 8,
- 7, 7, 7, 7, 7, 11, 7, 11, nil, nil,
- 8, 8, 8, 8, 8, nil, 8, nil, 11, 11,
- 11, 11, 11, nil, 11 ]
-
-racc_goto_check = [
- 22, 24, 21, 23, 36, 36, 37, 18, 16, 34,
- 35, 41, 36, 19, 20, 17, 25, 25, 28, 3,
- 13, 23, 24, 1, 23, 24, 28, 34, 14, 15,
- 34, 29, 32, 17, 19, 20, 1, 1, 1, 1,
- 1, 33, 1, 35, 38, 39, 33, 35, 42, nil,
- 41, nil, 35, 22, 4, 35, 4, nil, nil, nil,
- nil, 16, nil, 18, 37, nil, nil, 4, 4, 4,
- 4, 4, nil, 4, 5, nil, 5, 23, nil, nil,
- 22, nil, 21, 34, nil, 22, nil, 5, 5, 5,
- 5, 5, nil, 5, nil, nil, nil, nil, 36, nil,
- nil, nil, 36, nil, nil, 24, 36, 36, nil, 6,
- 24, 6, nil, nil, nil, nil, 22, 7, nil, 7,
- nil, nil, 6, 6, 6, 6, 6, 8, 6, 8,
- 7, 7, 7, 7, 7, 11, 7, 11, nil, nil,
- 8, 8, 8, 8, 8, nil, 8, nil, 11, 11,
- 11, 11, 11, nil, 11 ]
-
-racc_goto_pointer = [
- nil, 23, nil, 17, 54, 74, 109, 117, 127, nil,
- nil, 135, nil, 2, -8, 11, -30, -3, -29, -5,
- -4, -40, -42, -15, -17, -28, nil, nil, -120, -96,
- nil, nil, -20, -101, -9, -116, -40, -91, 24, 18,
- nil, -9, -13 ]
-
-racc_goto_default = [
- nil, nil, 2, 3, 46, 47, 48, 49, 50, 9,
- 10, 51, 12, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 140, nil, 45, 127, 139, 128,
- 141, 130, 142, 143, 132, 131, 134, 98, nil, 28,
- 27, nil, 60 ]
-
-racc_reduce_table = [
- 0, 0, :racc_error,
- 1, 27, :_reduce_none,
- 2, 28, :_reduce_2,
- 1, 28, :_reduce_3,
- 1, 29, :_reduce_none,
- 1, 29, :_reduce_none,
- 1, 29, :_reduce_none,
- 1, 29, :_reduce_none,
- 1, 29, :_reduce_none,
- 1, 29, :_reduce_none,
- 1, 29, :_reduce_none,
- 1, 29, :_reduce_none,
- 1, 29, :_reduce_none,
- 3, 30, :_reduce_13,
- 3, 31, :_reduce_14,
- 3, 32, :_reduce_15,
- 3, 33, :_reduce_16,
- 3, 34, :_reduce_17,
- 4, 35, :_reduce_18,
- 3, 35, :_reduce_19,
- 2, 40, :_reduce_20,
- 2, 40, :_reduce_21,
- 1, 40, :_reduce_22,
- 1, 40, :_reduce_23,
- 2, 41, :_reduce_24,
- 2, 41, :_reduce_25,
- 1, 41, :_reduce_26,
- 1, 41, :_reduce_27,
- 2, 39, :_reduce_none,
- 4, 39, :_reduce_29,
- 4, 39, :_reduce_30,
- 2, 43, :_reduce_31,
- 4, 43, :_reduce_32,
- 1, 44, :_reduce_33,
- 3, 44, :_reduce_34,
- 1, 45, :_reduce_none,
- 3, 45, :_reduce_36,
- 3, 45, :_reduce_37,
- 2, 46, :_reduce_38,
- 2, 46, :_reduce_39,
- 1, 46, :_reduce_40,
- 1, 46, :_reduce_41,
- 1, 47, :_reduce_none,
- 2, 51, :_reduce_43,
- 1, 51, :_reduce_44,
- 2, 53, :_reduce_45,
- 1, 53, :_reduce_46,
- 1, 50, :_reduce_none,
- 1, 50, :_reduce_none,
- 1, 50, :_reduce_none,
- 1, 50, :_reduce_none,
- 1, 50, :_reduce_none,
- 1, 50, :_reduce_none,
- 1, 54, :_reduce_none,
- 1, 54, :_reduce_none,
- 1, 55, :_reduce_none,
- 1, 55, :_reduce_none,
- 1, 56, :_reduce_57,
- 1, 52, :_reduce_58,
- 1, 57, :_reduce_59,
- 2, 58, :_reduce_60,
- 1, 58, :_reduce_none,
- 2, 49, :_reduce_62,
- 1, 49, :_reduce_none,
- 2, 48, :_reduce_64,
- 1, 48, :_reduce_none,
- 1, 60, :_reduce_none,
- 1, 60, :_reduce_none,
- 1, 60, :_reduce_none,
- 1, 60, :_reduce_none,
- 1, 60, :_reduce_none,
- 1, 62, :_reduce_none,
- 1, 62, :_reduce_none,
- 1, 59, :_reduce_none,
- 1, 59, :_reduce_none,
- 1, 61, :_reduce_none,
- 1, 61, :_reduce_none,
- 1, 61, :_reduce_none,
- 2, 42, :_reduce_78,
- 1, 42, :_reduce_none,
- 1, 63, :_reduce_none,
- 2, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 3, 36, :_reduce_101,
- 3, 37, :_reduce_102,
- 1, 65, :_reduce_none,
- 1, 65, :_reduce_none,
- 1, 65, :_reduce_none,
- 1, 65, :_reduce_none,
- 1, 65, :_reduce_none,
- 1, 65, :_reduce_none,
- 2, 66, :_reduce_109,
- 1, 66, :_reduce_none,
- 1, 38, :_reduce_111,
- 1, 67, :_reduce_none,
- 2, 67, :_reduce_113,
- 2, 67, :_reduce_114,
- 2, 67, :_reduce_115,
- 1, 68, :_reduce_none,
- 1, 68, :_reduce_none,
- 1, 68, :_reduce_none,
- 1, 68, :_reduce_none,
- 1, 68, :_reduce_none,
- 1, 68, :_reduce_none,
- 1, 68, :_reduce_none,
- 1, 68, :_reduce_none,
- 1, 68, :_reduce_none,
- 1, 68, :_reduce_none,
- 1, 68, :_reduce_none,
- 1, 68, :_reduce_none,
- 1, 68, :_reduce_none,
- 1, 68, :_reduce_none,
- 1, 68, :_reduce_none,
- 1, 68, :_reduce_none,
- 1, 68, :_reduce_none,
- 1, 68, :_reduce_none,
- 1, 68, :_reduce_none,
- 1, 68, :_reduce_none,
- 2, 64, :_reduce_136,
- 1, 64, :_reduce_none ]
-
-racc_reduce_n = 138
-
-racc_shift_n = 179
-
-racc_token_table = {
- false => 0,
- :error => 1,
- :EX_LOW => 2,
- :QUOTE => 3,
- :BAR => 4,
- :SLASH => 5,
- :BACK_SLASH => 6,
- :URL => 7,
- :OTHER => 8,
- :REF_OPEN => 9,
- :FOOTNOTE_OPEN => 10,
- :FOOTNOTE_CLOSE => 11,
- :EX_HIGH => 12,
- :EM_OPEN => 13,
- :EM_CLOSE => 14,
- :CODE_OPEN => 15,
- :CODE_CLOSE => 16,
- :VAR_OPEN => 17,
- :VAR_CLOSE => 18,
- :KBD_OPEN => 19,
- :KBD_CLOSE => 20,
- :INDEX_OPEN => 21,
- :INDEX_CLOSE => 22,
- :REF_CLOSE => 23,
- :VERB_OPEN => 24,
- :VERB_CLOSE => 25 }
-
-racc_nt_base = 26
-
-racc_use_result_var = true
-
-Racc_arg = [
- racc_action_table,
- racc_action_check,
- racc_action_default,
- racc_action_pointer,
- racc_goto_table,
- racc_goto_check,
- racc_goto_default,
- racc_goto_pointer,
- racc_nt_base,
- racc_reduce_table,
- racc_token_table,
- racc_shift_n,
- racc_reduce_n,
- racc_use_result_var ]
-Ractor.make_shareable(Racc_arg) if defined?(Ractor)
-
-Racc_token_to_s_table = [
- "$end",
- "error",
- "EX_LOW",
- "QUOTE",
- "BAR",
- "SLASH",
- "BACK_SLASH",
- "URL",
- "OTHER",
- "REF_OPEN",
- "FOOTNOTE_OPEN",
- "FOOTNOTE_CLOSE",
- "EX_HIGH",
- "EM_OPEN",
- "EM_CLOSE",
- "CODE_OPEN",
- "CODE_CLOSE",
- "VAR_OPEN",
- "VAR_CLOSE",
- "KBD_OPEN",
- "KBD_CLOSE",
- "INDEX_OPEN",
- "INDEX_CLOSE",
- "REF_CLOSE",
- "VERB_OPEN",
- "VERB_CLOSE",
- "$start",
- "content",
- "elements",
- "element",
- "emphasis",
- "code",
- "var",
- "keyboard",
- "index",
- "reference",
- "footnote",
- "verb",
- "normal_str_ele",
- "substitute",
- "ref_label",
- "ref_label2",
- "ref_url_strings",
- "filename",
- "element_label",
- "element_label2",
- "ref_subst_content",
- "ref_subst_content_q",
- "ref_subst_strings_q",
- "ref_subst_strings_first",
- "ref_subst_ele2",
- "ref_subst_eles",
- "ref_subst_str_ele_first",
- "ref_subst_eles_q",
- "ref_subst_ele",
- "ref_subst_ele_q",
- "ref_subst_str_ele",
- "ref_subst_str_ele_q",
- "ref_subst_strings",
- "ref_subst_string3",
- "ref_subst_string",
- "ref_subst_string_q",
- "ref_subst_string2",
- "ref_url_string",
- "verb_strings",
- "normal_string",
- "normal_strings",
- "verb_string",
- "verb_normal_string" ]
-Ractor.make_shareable(Racc_token_to_s_table) if defined?(Ractor)
-
-Racc_debug_parser = false
-
-##### State transition tables end #####
-
-# reduce 0 omitted
-
-# reduce 1 omitted
-
-def _reduce_2(val, _values, result)
- result.append val[1]
- result
-end
-
-def _reduce_3(val, _values, result)
- result = val[0]
- result
-end
-
-# reduce 4 omitted
-
-# reduce 5 omitted
-
-# reduce 6 omitted
-
-# reduce 7 omitted
-
-# reduce 8 omitted
-
-# reduce 9 omitted
-
-# reduce 10 omitted
-
-# reduce 11 omitted
-
-# reduce 12 omitted
-
-def _reduce_13(val, _values, result)
- content = val[1]
- result = inline "<em>#{content}</em>", content
-
- result
-end
-
-def _reduce_14(val, _values, result)
- content = val[1]
- result = inline "<code>#{content}</code>", content
-
- result
-end
-
-def _reduce_15(val, _values, result)
- content = val[1]
- result = inline "+#{content}+", content
-
- result
-end
-
-def _reduce_16(val, _values, result)
- content = val[1]
- result = inline "<tt>#{content}</tt>", content
-
- result
-end
-
-def _reduce_17(val, _values, result)
- label = val[1]
- @block_parser.add_label label.reference
- result = "<span id=\"label-#{label}\">#{label}</span>"
-
- result
-end
-
-def _reduce_18(val, _values, result)
- result = "{#{val[1]}}[#{val[2].join}]"
-
- result
-end
-
-def _reduce_19(val, _values, result)
- scheme, inline = val[1]
-
- result = "{#{inline}}[#{scheme}#{inline.reference}]"
-
- result
-end
-
-def _reduce_20(val, _values, result)
- result = [nil, inline(val[1])]
-
- result
-end
-
-def _reduce_21(val, _values, result)
- result = [
- 'rdoc-label:',
- inline("#{val[0].reference}/#{val[1].reference}")
- ]
-
- result
-end
-
-def _reduce_22(val, _values, result)
- result = ['rdoc-label:', val[0].reference]
-
- result
-end
-
-def _reduce_23(val, _values, result)
- result = ['rdoc-label:', "#{val[0].reference}/"]
-
- result
-end
-
-def _reduce_24(val, _values, result)
- result = [nil, inline(val[1])]
-
- result
-end
-
-def _reduce_25(val, _values, result)
- result = [
- 'rdoc-label:',
- inline("#{val[0].reference}/#{val[1].reference}")
- ]
-
- result
-end
-
-def _reduce_26(val, _values, result)
- result = ['rdoc-label:', val[0]]
-
- result
-end
-
-def _reduce_27(val, _values, result)
- ref = val[0].reference
- result = ['rdoc-label:', inline(ref, "#{ref}/")]
-
- result
-end
-
-# reduce 28 omitted
-
-def _reduce_29(val, _values, result)
- result = val[1]
- result
-end
-
-def _reduce_30(val, _values, result)
- result = val[1]
- result
-end
-
-def _reduce_31(val, _values, result)
- result = inline val[0]
-
- result
-end
-
-def _reduce_32(val, _values, result)
- result = inline "\"#{val[1]}\""
-
- result
-end
-
-def _reduce_33(val, _values, result)
- result = inline val[0]
-
- result
-end
-
-def _reduce_34(val, _values, result)
- result = inline "\"#{val[1]}\""
-
- result
-end
-
-# reduce 35 omitted
-
-def _reduce_36(val, _values, result)
- result = val[1]
- result
-end
-
-def _reduce_37(val, _values, result)
- result = inline val[1]
- result
-end
-
-def _reduce_38(val, _values, result)
- result = val[0].append val[1]
-
- result
-end
-
-def _reduce_39(val, _values, result)
- result = val[0].append val[1]
-
- result
-end
-
-def _reduce_40(val, _values, result)
- result = val[0]
-
- result
-end
-
-def _reduce_41(val, _values, result)
- result = inline val[0]
-
- result
-end
-
-# reduce 42 omitted
-
-def _reduce_43(val, _values, result)
- result = val[0].append val[1]
-
- result
-end
-
-def _reduce_44(val, _values, result)
- result = inline val[0]
-
- result
-end
-
-def _reduce_45(val, _values, result)
- result = val[0].append val[1]
-
- result
-end
-
-def _reduce_46(val, _values, result)
- result = val[0]
-
- result
-end
-
-# reduce 47 omitted
-
-# reduce 48 omitted
-
-# reduce 49 omitted
-
-# reduce 50 omitted
-
-# reduce 51 omitted
-
-# reduce 52 omitted
-
-# reduce 53 omitted
-
-# reduce 54 omitted
-
-# reduce 55 omitted
-
-# reduce 56 omitted
-
-def _reduce_57(val, _values, result)
- result = val[0]
-
- result
-end
-
-def _reduce_58(val, _values, result)
- result = inline val[0]
-
- result
-end
-
-def _reduce_59(val, _values, result)
- result = inline val[0]
-
- result
-end
-
-def _reduce_60(val, _values, result)
- result << val[1]
- result
-end
-
-# reduce 61 omitted
-
-def _reduce_62(val, _values, result)
- result << val[1]
-
- result
-end
-
-# reduce 63 omitted
-
-def _reduce_64(val, _values, result)
- result << val[1]
-
- result
-end
-
-# reduce 65 omitted
-
-# reduce 66 omitted
-
-# reduce 67 omitted
-
-# reduce 68 omitted
-
-# reduce 69 omitted
-
-# reduce 70 omitted
-
-# reduce 71 omitted
-
-# reduce 72 omitted
-
-# reduce 73 omitted
-
-# reduce 74 omitted
-
-# reduce 75 omitted
-
-# reduce 76 omitted
-
-# reduce 77 omitted
-
-def _reduce_78(val, _values, result)
- result << val[1]
- result
-end
-
-# reduce 79 omitted
-
-# reduce 80 omitted
-
-# reduce 81 omitted
-
-# reduce 82 omitted
-
-# reduce 83 omitted
-
-# reduce 84 omitted
-
-# reduce 85 omitted
-
-# reduce 86 omitted
-
-# reduce 87 omitted
-
-# reduce 88 omitted
-
-# reduce 89 omitted
-
-# reduce 90 omitted
-
-# reduce 91 omitted
-
-# reduce 92 omitted
-
-# reduce 93 omitted
-
-# reduce 94 omitted
-
-# reduce 95 omitted
-
-# reduce 96 omitted
-
-# reduce 97 omitted
-
-# reduce 98 omitted
-
-# reduce 99 omitted
-
-# reduce 100 omitted
-
-def _reduce_101(val, _values, result)
- index = @block_parser.add_footnote val[1].rdoc
- result = "{*#{index}}[rdoc-label:foottext-#{index}:footmark-#{index}]"
-
- result
-end
-
-def _reduce_102(val, _values, result)
- result = inline "<tt>#{val[1]}</tt>", val[1]
-
- result
-end
-
-# reduce 103 omitted
-
-# reduce 104 omitted
-
-# reduce 105 omitted
-
-# reduce 106 omitted
-
-# reduce 107 omitted
-
-# reduce 108 omitted
-
-def _reduce_109(val, _values, result)
- result << val[1]
- result
-end
-
-# reduce 110 omitted
-
-def _reduce_111(val, _values, result)
- result = inline val[0]
-
- result
-end
-
-# reduce 112 omitted
-
-def _reduce_113(val, _values, result)
- result = val[1]
- result
-end
-
-def _reduce_114(val, _values, result)
- result = val[1]
- result
-end
-
-def _reduce_115(val, _values, result)
- result = val[1]
- result
-end
-
-# reduce 116 omitted
-
-# reduce 117 omitted
-
-# reduce 118 omitted
-
-# reduce 119 omitted
-
-# reduce 120 omitted
-
-# reduce 121 omitted
-
-# reduce 122 omitted
-
-# reduce 123 omitted
-
-# reduce 124 omitted
-
-# reduce 125 omitted
-
-# reduce 126 omitted
-
-# reduce 127 omitted
-
-# reduce 128 omitted
-
-# reduce 129 omitted
-
-# reduce 130 omitted
-
-# reduce 131 omitted
-
-# reduce 132 omitted
-
-# reduce 133 omitted
-
-# reduce 134 omitted
-
-# reduce 135 omitted
-
-def _reduce_136(val, _values, result)
- result << val[1]
- result
-end
-
-# reduce 137 omitted
-
-def _reduce_none(val, _values, result)
- val[0]
-end
-
-end # class InlineParser
-
-end
diff --git a/lib/rdoc/rdoc.gemspec b/lib/rdoc/rdoc.gemspec
deleted file mode 100644
index 93a281c8ae..0000000000
--- a/lib/rdoc/rdoc.gemspec
+++ /dev/null
@@ -1,237 +0,0 @@
-begin
- require_relative "lib/rdoc/version"
-rescue LoadError
- # for Ruby repository
- require_relative "version"
-end
-
-Gem::Specification.new do |s|
- s.name = "rdoc"
- s.version = RDoc::VERSION
-
- s.authors = [
- "Eric Hodel",
- "Dave Thomas",
- "Phil Hagelberg",
- "Tony Strauss",
- "Zachary Scott",
- "Hiroshi SHIBATA",
- "ITOYANAGI Sakura"
- ]
- s.email = ["drbrain@segment7.net", "", "", "", "mail@zzak.io", "hsbt@ruby-lang.org", "aycabta@gmail.com"]
-
- s.summary = "RDoc produces HTML and command-line documentation for Ruby projects"
- s.description = <<-DESCRIPTION
-RDoc produces HTML and command-line documentation for Ruby projects.
-RDoc includes the +rdoc+ and +ri+ tools for generating and displaying documentation from the command-line.
- DESCRIPTION
- s.homepage = "https://ruby.github.io/rdoc"
- s.licenses = ["Ruby"]
-
- s.metadata["homepage_uri"] = s.homepage
- s.metadata["source_code_uri"] = "https://github.com/ruby/rdoc"
- s.metadata["changelog_uri"] = "#{s.metadata["source_code_uri"]}/releases"
-
- s.bindir = "exe"
- s.executables = ["rdoc", "ri"]
- s.require_paths = ["lib"]
- # for ruby core repository. It was generated by
- # `git ls-files -z`.split("\x0").each {|f| puts " #{f.dump}," unless f.start_with?(*%W[test/ spec/ features/ .]) }
- s.files = [
- "CONTRIBUTING.rdoc",
- "CVE-2013-0256.rdoc",
- "ExampleMarkdown.md",
- "ExampleRDoc.rdoc",
- "History.rdoc",
- "LEGAL.rdoc",
- "LICENSE.rdoc",
- "README.rdoc",
- "RI.rdoc",
- "TODO.rdoc",
- "exe/rdoc",
- "exe/ri",
- "lib/rdoc.rb",
- "lib/rdoc/alias.rb",
- "lib/rdoc/anon_class.rb",
- "lib/rdoc/any_method.rb",
- "lib/rdoc/attr.rb",
- "lib/rdoc/class_module.rb",
- "lib/rdoc/code_object.rb",
- "lib/rdoc/code_objects.rb",
- "lib/rdoc/comment.rb",
- "lib/rdoc/constant.rb",
- "lib/rdoc/context.rb",
- "lib/rdoc/context/section.rb",
- "lib/rdoc/cross_reference.rb",
- "lib/rdoc/encoding.rb",
- "lib/rdoc/erb_partial.rb",
- "lib/rdoc/erbio.rb",
- "lib/rdoc/extend.rb",
- "lib/rdoc/generator.rb",
- "lib/rdoc/generator/darkfish.rb",
- "lib/rdoc/generator/json_index.rb",
- "lib/rdoc/generator/markup.rb",
- "lib/rdoc/generator/pot.rb",
- "lib/rdoc/generator/pot/message_extractor.rb",
- "lib/rdoc/generator/pot/po.rb",
- "lib/rdoc/generator/pot/po_entry.rb",
- "lib/rdoc/generator/ri.rb",
- "lib/rdoc/generator/template/darkfish/.document",
- "lib/rdoc/generator/template/darkfish/_footer.rhtml",
- "lib/rdoc/generator/template/darkfish/_head.rhtml",
- "lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml",
- "lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml",
- "lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml",
- "lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml",
- "lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml",
- "lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml",
- "lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml",
- "lib/rdoc/generator/template/darkfish/_sidebar_navigation.rhtml",
- "lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml",
- "lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml",
- "lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml",
- "lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml",
- "lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml",
- "lib/rdoc/generator/template/darkfish/class.rhtml",
- "lib/rdoc/generator/template/darkfish/css/fonts.css",
- "lib/rdoc/generator/template/darkfish/css/rdoc.css",
- "lib/rdoc/generator/template/darkfish/fonts/Lato-Light.ttf",
- "lib/rdoc/generator/template/darkfish/fonts/Lato-LightItalic.ttf",
- "lib/rdoc/generator/template/darkfish/fonts/Lato-Regular.ttf",
- "lib/rdoc/generator/template/darkfish/fonts/Lato-RegularItalic.ttf",
- "lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf",
- "lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf",
- "lib/rdoc/generator/template/darkfish/images/add.png",
- "lib/rdoc/generator/template/darkfish/images/arrow_up.png",
- "lib/rdoc/generator/template/darkfish/images/brick.png",
- "lib/rdoc/generator/template/darkfish/images/brick_link.png",
- "lib/rdoc/generator/template/darkfish/images/bug.png",
- "lib/rdoc/generator/template/darkfish/images/bullet_black.png",
- "lib/rdoc/generator/template/darkfish/images/bullet_toggle_minus.png",
- "lib/rdoc/generator/template/darkfish/images/bullet_toggle_plus.png",
- "lib/rdoc/generator/template/darkfish/images/date.png",
- "lib/rdoc/generator/template/darkfish/images/delete.png",
- "lib/rdoc/generator/template/darkfish/images/find.png",
- "lib/rdoc/generator/template/darkfish/images/loadingAnimation.gif",
- "lib/rdoc/generator/template/darkfish/images/macFFBgHack.png",
- "lib/rdoc/generator/template/darkfish/images/package.png",
- "lib/rdoc/generator/template/darkfish/images/page_green.png",
- "lib/rdoc/generator/template/darkfish/images/page_white_text.png",
- "lib/rdoc/generator/template/darkfish/images/page_white_width.png",
- "lib/rdoc/generator/template/darkfish/images/plugin.png",
- "lib/rdoc/generator/template/darkfish/images/ruby.png",
- "lib/rdoc/generator/template/darkfish/images/tag_blue.png",
- "lib/rdoc/generator/template/darkfish/images/tag_green.png",
- "lib/rdoc/generator/template/darkfish/images/transparent.png",
- "lib/rdoc/generator/template/darkfish/images/wrench.png",
- "lib/rdoc/generator/template/darkfish/images/wrench_orange.png",
- "lib/rdoc/generator/template/darkfish/images/zoom.png",
- "lib/rdoc/generator/template/darkfish/index.rhtml",
- "lib/rdoc/generator/template/darkfish/js/darkfish.js",
- "lib/rdoc/generator/template/darkfish/js/search.js",
- "lib/rdoc/generator/template/darkfish/page.rhtml",
- "lib/rdoc/generator/template/darkfish/servlet_not_found.rhtml",
- "lib/rdoc/generator/template/darkfish/servlet_root.rhtml",
- "lib/rdoc/generator/template/darkfish/table_of_contents.rhtml",
- "lib/rdoc/generator/template/json_index/.document",
- "lib/rdoc/generator/template/json_index/js/navigation.js",
- "lib/rdoc/generator/template/json_index/js/searcher.js",
- "lib/rdoc/ghost_method.rb",
- "lib/rdoc/i18n.rb",
- "lib/rdoc/i18n/locale.rb",
- "lib/rdoc/i18n/text.rb",
- "lib/rdoc/include.rb",
- "lib/rdoc/known_classes.rb",
- "lib/rdoc/markdown.kpeg",
- "lib/rdoc/markdown/entities.rb",
- "lib/rdoc/markdown/literals.kpeg",
- "lib/rdoc/markup.rb",
- "lib/rdoc/markup/attr_changer.rb",
- "lib/rdoc/markup/attr_span.rb",
- "lib/rdoc/markup/attribute_manager.rb",
- "lib/rdoc/markup/attributes.rb",
- "lib/rdoc/markup/blank_line.rb",
- "lib/rdoc/markup/block_quote.rb",
- "lib/rdoc/markup/document.rb",
- "lib/rdoc/markup/formatter.rb",
- "lib/rdoc/markup/hard_break.rb",
- "lib/rdoc/markup/heading.rb",
- "lib/rdoc/markup/include.rb",
- "lib/rdoc/markup/indented_paragraph.rb",
- "lib/rdoc/markup/list.rb",
- "lib/rdoc/markup/list_item.rb",
- "lib/rdoc/markup/paragraph.rb",
- "lib/rdoc/markup/parser.rb",
- "lib/rdoc/markup/pre_process.rb",
- "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",
- "lib/rdoc/markup/to_html_crossref.rb",
- "lib/rdoc/markup/to_html_snippet.rb",
- "lib/rdoc/markup/to_joined_paragraph.rb",
- "lib/rdoc/markup/to_label.rb",
- "lib/rdoc/markup/to_markdown.rb",
- "lib/rdoc/markup/to_rdoc.rb",
- "lib/rdoc/markup/to_table_of_contents.rb",
- "lib/rdoc/markup/to_test.rb",
- "lib/rdoc/markup/to_tt_only.rb",
- "lib/rdoc/markup/verbatim.rb",
- "lib/rdoc/meta_method.rb",
- "lib/rdoc/method_attr.rb",
- "lib/rdoc/mixin.rb",
- "lib/rdoc/normal_class.rb",
- "lib/rdoc/normal_module.rb",
- "lib/rdoc/options.rb",
- "lib/rdoc/parser.rb",
- "lib/rdoc/parser/c.rb",
- "lib/rdoc/parser/changelog.rb",
- "lib/rdoc/parser/markdown.rb",
- "lib/rdoc/parser/rd.rb",
- "lib/rdoc/parser/ripper_state_lex.rb",
- "lib/rdoc/parser/ruby.rb",
- "lib/rdoc/parser/ruby_tools.rb",
- "lib/rdoc/parser/simple.rb",
- "lib/rdoc/parser/text.rb",
- "lib/rdoc/rd.rb",
- "lib/rdoc/rd/block_parser.ry",
- "lib/rdoc/rd/inline.rb",
- "lib/rdoc/rd/inline_parser.ry",
- "lib/rdoc/rdoc.rb",
- "lib/rdoc/require.rb",
- "lib/rdoc/ri.rb",
- "lib/rdoc/ri/driver.rb",
- "lib/rdoc/ri/formatter.rb",
- "lib/rdoc/ri/paths.rb",
- "lib/rdoc/ri/store.rb",
- "lib/rdoc/ri/task.rb",
- "lib/rdoc/rubygems_hook.rb",
- "lib/rdoc/servlet.rb",
- "lib/rdoc/single_class.rb",
- "lib/rdoc/stats.rb",
- "lib/rdoc/stats/normal.rb",
- "lib/rdoc/stats/quiet.rb",
- "lib/rdoc/stats/verbose.rb",
- "lib/rdoc/store.rb",
- "lib/rdoc/task.rb",
- "lib/rdoc/text.rb",
- "lib/rdoc/token_stream.rb",
- "lib/rdoc/tom_doc.rb",
- "lib/rdoc/top_level.rb",
- "lib/rdoc/version.rb",
- "man/ri.1",
- ]
- # files from .gitignore
- s.files << "lib/rdoc/rd/block_parser.rb" << "lib/rdoc/rd/inline_parser.rb" << "lib/rdoc/markdown.rb" << "lib/rdoc/markdown/literals.rb"
-
- s.rdoc_options = ["--main", "README.rdoc"]
- s.extra_rdoc_files += s.files.grep(%r[\A[^\/]+\.(?:rdoc|md)\z])
-
- s.required_ruby_version = Gem::Requirement.new(">= 2.6.0")
- s.required_rubygems_version = Gem::Requirement.new(">= 2.2")
-
- s.add_dependency 'psych', '>= 4.0.0'
-end
diff --git a/lib/rdoc/rdoc.rb b/lib/rdoc/rdoc.rb
deleted file mode 100644
index 2da6d9b575..0000000000
--- a/lib/rdoc/rdoc.rb
+++ /dev/null
@@ -1,563 +0,0 @@
-# frozen_string_literal: true
-require_relative '../rdoc'
-
-require 'find'
-require 'fileutils'
-require 'pathname'
-require 'time'
-
-##
-# This is the driver for generating RDoc output. It handles file parsing and
-# generation of output.
-#
-# To use this class to generate RDoc output via the API, the recommended way
-# is:
-#
-# rdoc = RDoc::RDoc.new
-# options = RDoc::Options.load_options # returns an RDoc::Options instance
-# # set extra options
-# rdoc.document options
-#
-# You can also generate output like the +rdoc+ executable:
-#
-# rdoc = RDoc::RDoc.new
-# rdoc.document argv
-#
-# Where +argv+ is an array of strings, each corresponding to an argument you'd
-# give rdoc on the command line. See <tt>rdoc --help</tt> for details.
-
-class RDoc::RDoc
-
- @current = nil
-
- ##
- # This is the list of supported output generators
-
- GENERATORS = {}
-
- ##
- # List of directory names always skipped
-
- UNCONDITIONALLY_SKIPPED_DIRECTORIES = %w[CVS .svn .git].freeze
-
- ##
- # List of directory names skipped if test suites should be skipped
-
- TEST_SUITE_DIRECTORY_NAMES = %w[spec test].freeze
-
-
- ##
- # Generator instance used for creating output
-
- attr_accessor :generator
-
- ##
- # Hash of files and their last modified times.
-
- attr_reader :last_modified
-
- ##
- # RDoc options
-
- attr_accessor :options
-
- ##
- # Accessor for statistics. Available after each call to parse_files
-
- attr_reader :stats
-
- ##
- # The current documentation store
-
- attr_reader :store
-
- ##
- # Add +klass+ that can generate output after parsing
-
- def self.add_generator(klass)
- name = klass.name.sub(/^RDoc::Generator::/, '').downcase
- GENERATORS[name] = klass
- end
-
- ##
- # Active RDoc::RDoc instance
-
- def self.current
- @current
- end
-
- ##
- # Sets the active RDoc::RDoc instance
-
- def self.current= rdoc
- @current = rdoc
- end
-
- ##
- # Creates a new RDoc::RDoc instance. Call #document to parse files and
- # generate documentation.
-
- def initialize
- @current = nil
- @generator = nil
- @last_modified = {}
- @old_siginfo = nil
- @options = nil
- @stats = nil
- @store = nil
- end
-
- ##
- # Report an error message and exit
-
- def error(msg)
- raise RDoc::Error, msg
- end
-
- ##
- # Gathers a set of parseable files from the files and directories listed in
- # +files+.
-
- def gather_files files
- files = [@options.root.to_s] if files.empty?
-
- file_list = normalized_file_list files, true, @options.exclude
-
- file_list = remove_unparseable(file_list)
-
- 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
-
- ##
- # Turns RDoc from stdin into HTML
-
- def handle_pipe
- @html = RDoc::Markup::ToHtml.new @options
-
- parser = RDoc::Text::MARKUP_FORMAT[@options.markup]
-
- document = parser.parse $stdin.read
-
- out = @html.convert document
-
- $stdout.write out
- end
-
- ##
- # Installs a siginfo handler that prints the current filename.
-
- def install_siginfo_handler
- return unless Signal.list.include? 'INFO'
-
- @old_siginfo = trap 'INFO' do
- puts @current if @current
- end
- end
-
- ##
- # Create an output dir if it doesn't exist. If it does exist, but doesn't
- # contain the flag file <tt>created.rid</tt> then we refuse to use it, as
- # we may clobber some manually generated documentation
-
- def setup_output_dir(dir, force)
- flag_file = output_flag_file dir
-
- last = {}
-
- if @options.dry_run then
- # do nothing
- elsif File.exist? dir then
- error "#{dir} exists and is not a directory" unless File.directory? dir
-
- begin
- File.open flag_file do |io|
- unless force then
- Time.parse io.gets
-
- io.each do |line|
- file, time = line.split "\t", 2
- time = Time.parse(time) rescue next
- last[file] = time
- end
- end
- end
- rescue SystemCallError, TypeError
- error <<-ERROR
-
-Directory #{dir} already exists, but it looks like it isn't an RDoc directory.
-
-Because RDoc doesn't want to risk destroying any of your existing files,
-you'll need to specify a different output directory name (using the --op <dir>
-option)
-
- ERROR
- end unless @options.force_output
- else
- FileUtils.mkdir_p dir
- FileUtils.touch flag_file
- end
-
- last
- end
-
- ##
- # Sets the current documentation tree to +store+ and sets the store's rdoc
- # driver to this instance.
-
- def store= store
- @store = store
- @store.rdoc = self
- end
-
- ##
- # Update the flag file in an output directory.
-
- def update_output_dir(op_dir, time, last = {})
- return if @options.dry_run or not @options.update_output_dir
- unless ENV['SOURCE_DATE_EPOCH'].nil?
- time = Time.at(ENV['SOURCE_DATE_EPOCH'].to_i).gmtime
- end
-
- File.open output_flag_file(op_dir), "w" do |f|
- f.puts time.rfc2822
- last.each do |n, t|
- f.puts "#{n}\t#{t.rfc2822}"
- end
- end
- end
-
- ##
- # Return the path name of the flag file in an output directory.
-
- def output_flag_file(op_dir)
- File.join op_dir, "created.rid"
- end
-
- ##
- # The .document file contains a list of file and directory name patterns,
- # representing candidates for documentation. It may also contain comments
- # (starting with '#')
-
- def parse_dot_doc_file in_dir, filename
- # read and strip comments
- patterns = File.read(filename).gsub(/#.*/, '')
-
- result = {}
-
- patterns.split(' ').each do |patt|
- candidates = Dir.glob(File.join(in_dir, patt))
- result.update normalized_file_list(candidates, false, @options.exclude)
- end
-
- result
- end
-
- ##
- # Given a list of files and directories, create a list of all the Ruby
- # files they contain.
- #
- # If +force_doc+ is true we always add the given files, if false, only
- # add files that we guarantee we can parse. It is true when looking at
- # files given on the command line, false when recursing through
- # subdirectories.
- #
- # The effect of this is that if you want a file with a non-standard
- # extension parsed, you must name it explicitly.
-
- def normalized_file_list(relative_files, force_doc = false,
- exclude_pattern = nil)
- 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
- 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] = mtime
- end
- when "directory" then
- next if UNCONDITIONALLY_SKIPPED_DIRECTORIES.include?(rel_file_name)
-
- basename = File.basename(rel_file_name)
- next if options.skip_tests && TEST_SUITE_DIRECTORY_NAMES.include?(basename)
-
- created_rid = File.join rel_file_name, "created.rid"
- next if File.file? created_rid
-
- dot_doc = File.join rel_file_name, RDoc::DOT_DOC_FILENAME
-
- if File.file? dot_doc then
- file_list.update(parse_dot_doc_file(rel_file_name, dot_doc))
- else
- 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
- end
-
- ##
- # Return a list of the files to be processed in a directory. We know that
- # this directory doesn't have a .document file, so we're looking for real
- # files. However we may well contain subdirectories which must be tested
- # for .document files.
-
- def list_files_in_directory dir
- files = Dir.glob File.join(dir, "*")
-
- normalized_file_list files, false, @options.exclude
- end
-
- ##
- # Parses +filename+ and returns an RDoc::TopLevel
-
- def parse_file filename
- encoding = @options.encoding
- filename = filename.encode encoding
-
- @stats.add_file filename
-
- return if RDoc::Parser.binary? filename
-
- content = RDoc::Encoding.read_file filename, encoding
-
- return unless content
-
- filename_path = Pathname(filename).expand_path
- begin
- relative_path = filename_path.relative_path_from @options.root
- rescue ArgumentError
- relative_path = filename_path
- end
-
- if @options.page_dir and
- relative_path.to_s.start_with? @options.page_dir.to_s then
- relative_path =
- relative_path.relative_path_from @options.page_dir
- end
-
- top_level = @store.add_file filename, relative_name: relative_path.to_s
-
- parser = RDoc::Parser.for top_level, filename, content, @options, @stats
-
- return unless parser
-
- parser.scan
-
- # restart documentation for the classes & modules found
- top_level.classes_or_modules.each do |cm|
- cm.done_documenting = false
- end
-
- top_level
-
- rescue Errno::EACCES => e
- $stderr.puts <<-EOF
-Unable to read #{filename}, #{e.message}
-
-Please check the permissions for this file. Perhaps you do not have access to
-it or perhaps the original author's permissions are to restrictive. If the
-this is not your library please report a bug to the author.
- EOF
- rescue => e
- $stderr.puts <<-EOF
-Before reporting this, could you check that the file you're documenting
-has proper syntax:
-
- #{Gem.ruby} -c #{filename}
-
-RDoc is not a full Ruby parser and will fail when fed invalid ruby programs.
-
-The internal error was:
-
-\t(#{e.class}) #{e.message}
-
- EOF
-
- $stderr.puts e.backtrace.join("\n\t") if $DEBUG_RDOC
-
- raise e
- nil
- end
-
- ##
- # Parse each file on the command line, recursively entering directories.
-
- def parse_files files
- file_list = gather_files files
- @stats = RDoc::Stats.new @store, file_list.length, @options.verbosity
-
- return [] if file_list.empty?
-
- original_options = @options.dup
- @stats.begin_adding
-
- file_info = file_list.map do |filename|
- @current = filename
- parse_file filename
- end.compact
-
- @stats.done_adding
- @options = original_options
-
- file_info
- end
-
- ##
- # Removes file extensions known to be unparseable from +files+ and TAGS
- # files for emacs and vim.
-
- def remove_unparseable files
- files.reject do |file, *|
- file =~ /\.(?:class|eps|erb|scpt\.txt|svg|ttf|yml)$/i or
- (file =~ /tags$/i and
- /\A(\f\n[^,]+,\d+$|!_TAG_)/.match?(File.binread(file, 100)))
- end
- end
-
- ##
- # Generates documentation or a coverage report depending upon the settings
- # in +options+.
- #
- # +options+ can be either an RDoc::Options instance or an array of strings
- # equivalent to the strings that would be passed on the command line like
- # <tt>%w[-q -o doc -t My\ Doc\ Title]</tt>. #document will automatically
- # call RDoc::Options#finish if an options instance was given.
- #
- # For a list of options, see either RDoc::Options or <tt>rdoc --help</tt>.
- #
- # By default, output will be stored in a directory called "doc" below the
- # current directory, so make sure you're somewhere writable before invoking.
-
- def document options
- self.store = RDoc::Store.new
-
- if RDoc::Options === options then
- @options = options
- else
- @options = RDoc::Options.load_options
- @options.parse options
- end
- @options.finish
-
- if @options.pipe then
- handle_pipe
- exit
- end
-
- unless @options.coverage_report then
- @last_modified = setup_output_dir @options.op_dir, @options.force_update
- end
-
- @store.encoding = @options.encoding
- @store.dry_run = @options.dry_run
- @store.main = @options.main_page
- @store.title = @options.title
- @store.path = @options.op_dir
-
- @start_time = Time.now
-
- @store.load_cache
-
- file_info = parse_files @options.files
-
- @options.default_title = "RDoc Documentation"
-
- @store.complete @options.visibility
-
- @stats.coverage_level = @options.coverage_report
-
- if @options.coverage_report then
- puts
-
- puts @stats.report.accept RDoc::Markup::ToRdoc.new
- elsif file_info.empty? then
- $stderr.puts "\nNo newer files." unless @options.quiet
- else
- gen_klass = @options.generator
-
- @generator = gen_klass.new @store, @options
-
- generate
- end
-
- if @stats and (@options.coverage_report or not @options.quiet) then
- puts
- puts @stats.summary.accept RDoc::Markup::ToRdoc.new
- end
-
- exit @stats.fully_documented? if @options.coverage_report
- end
-
- ##
- # Generates documentation for +file_info+ (from #parse_files) into the
- # output dir using the generator selected
- # by the RDoc options
-
- def generate
- if @options.dry_run then
- # do nothing
- @generator.generate
- else
- Dir.chdir @options.op_dir do
- unless @options.quiet then
- $stderr.puts "\nGenerating #{@generator.class.name.sub(/^.*::/, '')} format into #{Dir.pwd}..."
- end
-
- @generator.generate
- update_output_dir '.', @start_time, @last_modified
- end
- end
- end
-
- ##
- # Removes a siginfo handler and replaces the previous
-
- def remove_siginfo_handler
- return unless Signal.list.key? 'INFO'
-
- handler = @old_siginfo || 'DEFAULT'
-
- trap 'INFO', handler
- end
-
-end
-
-begin
- require 'rubygems'
-
- rdoc_extensions = Gem.find_files 'rdoc/discover'
-
- rdoc_extensions.each do |extension|
- begin
- load extension
- rescue => e
- warn "error loading #{extension.inspect}: #{e.message} (#{e.class})"
- warn "\t#{e.backtrace.join "\n\t"}" if $DEBUG
- end
- end
-rescue LoadError
-end
-
-# require built-in generators after discovery in case they've been replaced
-require_relative 'generator/darkfish'
-require_relative 'generator/ri'
-require_relative 'generator/pot'
diff --git a/lib/rdoc/require.rb b/lib/rdoc/require.rb
deleted file mode 100644
index 05e26b84b0..0000000000
--- a/lib/rdoc/require.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-# frozen_string_literal: true
-##
-# A file loaded by \#require
-
-class RDoc::Require < RDoc::CodeObject
-
- ##
- # Name of the required file
-
- attr_accessor :name
-
- ##
- # Creates a new Require that loads +name+ with +comment+
-
- def initialize(name, comment)
- super()
- @name = name.gsub(/'|"/, "") #'
- @top_level = nil
- self.comment = comment
- end
-
- def inspect # :nodoc:
- "#<%s:0x%x require '%s' in %s>" % [
- self.class,
- object_id,
- @name,
- parent_file_name,
- ]
- end
-
- def to_s # :nodoc:
- "require #{name} in: #{parent}"
- end
-
- ##
- # The RDoc::TopLevel corresponding to this require, or +nil+ if not found.
-
- def top_level
- @top_level ||= begin
- tl = RDoc::TopLevel.all_files_hash[name + '.rb']
-
- if tl.nil? and RDoc::TopLevel.all_files.first.full_name =~ %r(^lib/) then
- # second chance
- tl = RDoc::TopLevel.all_files_hash['lib/' + name + '.rb']
- end
-
- tl
- end
- end
-
-end
diff --git a/lib/rdoc/ri.rb b/lib/rdoc/ri.rb
deleted file mode 100644
index 0af05f729f..0000000000
--- a/lib/rdoc/ri.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-require_relative '../rdoc'
-
-##
-# Namespace for the ri command line tool's implementation.
-#
-# See <tt>ri --help</tt> for details.
-
-module RDoc::RI
-
- ##
- # Base RI error class
-
- class Error < RDoc::Error; end
-
- autoload :Driver, "#{__dir__}/ri/driver"
- autoload :Paths, "#{__dir__}/ri/paths"
- autoload :Store, "#{__dir__}/ri/store"
-
-end
diff --git a/lib/rdoc/ri/driver.rb b/lib/rdoc/ri/driver.rb
deleted file mode 100644
index c6fddbac67..0000000000
--- a/lib/rdoc/ri/driver.rb
+++ /dev/null
@@ -1,1517 +0,0 @@
-# frozen_string_literal: true
-require 'optparse'
-
-require_relative '../../rdoc'
-
-require_relative 'formatter' # For RubyGems backwards compatibility
-# TODO: Fix weird documentation with `require_relative`
-
-##
-# The RI driver implements the command-line ri tool.
-#
-# The driver supports:
-# * loading RI data from:
-# * Ruby's standard library
-# * RubyGems
-# * ~/.rdoc
-# * A user-supplied directory
-# * Paging output (uses RI_PAGER environment variable, PAGER environment
-# variable or the less, more and pager programs)
-# * Interactive mode with tab-completion
-# * Abbreviated names (ri Zl shows Zlib documentation)
-# * Colorized output
-# * Merging output from multiple RI data sources
-
-class RDoc::RI::Driver
-
- ##
- # Base Driver error class
-
- class Error < RDoc::RI::Error; end
-
- ##
- # Raised when a name isn't found in the ri data stores
-
- class NotFoundError < Error
-
- def initialize(klass, suggestion_proc = nil) # :nodoc:
- @klass = klass
- @suggestion_proc = suggestion_proc
- end
-
- ##
- # Name that wasn't found
-
- def name
- @klass
- end
-
- def message # :nodoc:
- str = "Nothing known about #{@klass}"
- suggestions = @suggestion_proc&.call
- if suggestions and !suggestions.empty?
- str += "\nDid you mean? #{suggestions.join("\n ")}"
- end
- str
- end
- end
-
- ##
- # Show all method documentation following a class or module
-
- attr_accessor :show_all
-
- ##
- # An RDoc::RI::Store for each entry in the RI path
-
- attr_accessor :stores
-
- ##
- # Controls the user of the pager vs $stdout
-
- attr_accessor :use_stdout
-
- ##
- # Default options for ri
-
- def self.default_options
- options = {}
- options[:interactive] = false
- options[:profile] = false
- options[:show_all] = false
- options[:use_stdout] = !$stdout.tty?
- options[:width] = 72
-
- # By default all standard paths are used.
- options[:use_system] = true
- options[:use_site] = true
- options[:use_home] = true
- options[:use_gems] = true
- options[:extra_doc_dirs] = []
-
- return options
- end
-
- ##
- # Dump +data_path+ using pp
-
- def self.dump data_path
- require 'pp'
-
- File.open data_path, 'rb' do |io|
- pp Marshal.load(io.read)
- end
- end
-
- ##
- # Parses +argv+ and returns a Hash of options
-
- def self.process_args argv
- options = default_options
-
- opts = OptionParser.new do |opt|
- opt.program_name = File.basename $0
- opt.version = RDoc::VERSION
- opt.release = nil
- opt.summary_indent = ' ' * 4
-
- opt.banner = <<-EOT
-Usage: #{opt.program_name} [options] [name ...]
-
-Where name can be:
-
- Class | Module | Module::Class
-
- Class::method | Class#method | Class.method | method
-
- 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.
-
-A '.' matches either class or instance methods, while #method
-matches only instance and ::method matches only class methods.
-
-README and other files may be displayed by prefixing them with the gem name
-they're contained in. If the gem name is followed by a ':' all files in the
-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
- #{opt.program_name} File
- #{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:
-
- #{opt.program_name} 'Array.[]'
- #{opt.program_name} compact\\!
-
-To see the default directories #{opt.program_name} will search, run:
-
- #{opt.program_name} --list-doc-dirs
-
-Specifying the --system, --site, --home, --gems, or --doc-dir options
-will limit ri to searching only the specified directories.
-
-ri options may be set in the RI environment variable.
-
-The ri pager can be set with the RI_PAGER environment variable
-or the PAGER environment variable.
- EOT
-
- opt.separator nil
- opt.separator "Options:"
-
- opt.separator nil
-
- opt.on("--[no-]interactive", "-i",
- "In interactive mode you can repeatedly",
- "look up methods with autocomplete.") do |interactive|
- options[:interactive] = interactive
- end
-
- opt.separator nil
-
- opt.on("--[no-]all", "-a",
- "Show all documentation for a class or",
- "module.") do |show_all|
- options[:show_all] = show_all
- end
-
- opt.separator nil
-
- opt.on("--[no-]list", "-l",
- "List classes ri knows about.") do |list|
- options[:list] = list
- end
-
- opt.separator nil
-
- opt.on("--[no-]pager",
- "Send output to a pager,",
- "rather than directly to stdout.") do |use_pager|
- options[:use_stdout] = !use_pager
- end
-
- opt.separator nil
-
- opt.on("-T",
- "Synonym for --no-pager.") do
- options[:use_stdout] = true
- end
-
- opt.separator nil
-
- opt.on("--width=WIDTH", "-w", OptionParser::DecimalInteger,
- "Set the width of the output.") do |width|
- options[:width] = width
- end
-
- opt.separator nil
-
- opt.on("--server[=PORT]", Integer,
- "Run RDoc server on the given port.",
- "The default port is 8214.") do |port|
- options[:server] = port || 8214
- end
-
- opt.separator nil
-
- formatters = RDoc::Markup.constants.grep(/^To[A-Z][a-z]+$/).sort
- formatters = formatters.sort.map do |formatter|
- formatter.to_s.sub('To', '').downcase
- end
- formatters -= %w[html label test] # remove useless output formats
-
- opt.on("--format=NAME", "-f",
- "Use the selected formatter. The default",
- "formatter is bs for paged output and ansi",
- "otherwise. Valid formatters are:",
- "#{formatters.join(', ')}.", formatters) do |value|
- options[:formatter] = RDoc::Markup.const_get "To#{value.capitalize}"
- end
-
- opt.separator nil
-
- opt.on("--help", "-h",
- "Show help and exit.") do
- puts opts
- exit
- end
-
- opt.separator nil
-
- opt.on("--version", "-v",
- "Output version information and exit.") do
- puts "#{opts.program_name} #{opts.version}"
- exit
- end
-
- opt.separator nil
- opt.separator "Data source options:"
- opt.separator nil
-
- opt.on("--[no-]list-doc-dirs",
- "List the directories from which ri will",
- "source documentation on stdout and exit.") do |list_doc_dirs|
- options[:list_doc_dirs] = list_doc_dirs
- end
-
- opt.separator nil
-
- opt.on("--doc-dir=DIRNAME", "-d", Array,
- "List of directories from which to source",
- "documentation in addition to the standard",
- "directories. May be repeated.") do |value|
- value.each do |dir|
- unless File.directory? dir then
- raise OptionParser::InvalidArgument, "#{dir} is not a directory"
- end
-
- options[:extra_doc_dirs] << File.expand_path(dir)
- end
- end
-
- opt.separator nil
-
- opt.on("--no-standard-docs",
- "Do not include documentation from",
- "the Ruby standard library, site_lib,",
- "installed gems, or ~/.rdoc.",
- "Use with --doc-dir.") do
- options[:use_system] = false
- options[:use_site] = false
- options[:use_gems] = false
- options[:use_home] = false
- end
-
- opt.separator nil
-
- opt.on("--[no-]system",
- "Include documentation from Ruby's",
- "standard library. Defaults to true.") do |value|
- options[:use_system] = value
- end
-
- opt.separator nil
-
- opt.on("--[no-]site",
- "Include documentation from libraries",
- "installed in site_lib.",
- "Defaults to true.") do |value|
- options[:use_site] = value
- end
-
- opt.separator nil
-
- opt.on("--[no-]gems",
- "Include documentation from RubyGems.",
- "Defaults to true.") do |value|
- options[:use_gems] = value
- end
-
- opt.separator nil
-
- opt.on("--[no-]home",
- "Include documentation stored in ~/.rdoc.",
- "Defaults to true.") do |value|
- options[:use_home] = value
- end
-
- opt.separator nil
- opt.separator "Debug options:"
- opt.separator nil
-
- opt.on("--[no-]profile",
- "Run with the ruby profiler.") do |value|
- options[:profile] = value
- end
-
- opt.separator nil
-
- opt.on("--dump=CACHE",
- "Dump data from an ri cache or data file.") do |value|
- unless File.readable?(value)
- abort "#{value.inspect} is not readable"
- end
-
- if File.directory?(value)
- abort "#{value.inspect} is a directory"
- end
-
- options[:dump_path] = File.new(value)
- end
- end
-
- argv = ENV['RI'].to_s.split(' ').concat argv
-
- opts.parse! argv
-
- options[:names] = argv
-
- options[:use_stdout] ||= !$stdout.tty?
- options[:use_stdout] ||= options[:interactive]
- options[:width] ||= 72
-
- options
-
- rescue OptionParser::InvalidArgument, OptionParser::InvalidOption => e
- puts opts
- puts
- puts e
- exit 1
- end
-
- ##
- # Runs the ri command line executable using +argv+
-
- def self.run argv = ARGV
- options = process_args argv
-
- if options[:dump_path] then
- dump options[:dump_path]
- return
- end
-
- ri = new options
- ri.run
- end
-
- ##
- # Creates a new driver using +initial_options+ from ::process_args
-
- def initialize initial_options = {}
- @paging = false
- @classes = nil
-
- options = self.class.default_options.update(initial_options)
-
- @formatter_klass = options[:formatter]
-
- require 'profile' if options[:profile]
-
- @names = options[:names]
- @list = options[:list]
-
- @doc_dirs = []
- @stores = []
-
- RDoc::RI::Paths.each(options[:use_system], options[:use_site],
- options[:use_home], options[:use_gems],
- *options[:extra_doc_dirs]) do |path, type|
- @doc_dirs << path
-
- store = RDoc::RI::Store.new path, type
- store.load_cache
- @stores << store
- end
-
- @list_doc_dirs = options[:list_doc_dirs]
-
- @interactive = options[:interactive]
- @server = options[:server]
- @use_stdout = options[:use_stdout]
- @show_all = options[:show_all]
- @width = options[:width]
- end
-
- ##
- # Adds paths for undocumented classes +also_in+ to +out+
-
- def add_also_in out, also_in
- return if also_in.empty?
-
- out << RDoc::Markup::Rule.new(1)
- out << RDoc::Markup::Paragraph.new("Also found in:")
-
- paths = RDoc::Markup::Verbatim.new
- also_in.each do |store|
- paths.parts.push store.friendly_path, "\n"
- end
- out << paths
- end
-
- ##
- # Adds a class header to +out+ for class +name+ which is described in
- # +classes+.
-
- def add_class out, name, classes
- heading = if classes.all? { |klass| klass.module? } then
- name
- else
- superclass = classes.map do |klass|
- klass.superclass unless klass.module?
- end.compact.shift || 'Object'
-
- superclass = superclass.full_name unless String === superclass
-
- "#{name} < #{superclass}"
- end
-
- out << RDoc::Markup::Heading.new(1, heading)
- out << RDoc::Markup::BlankLine.new
- end
-
- ##
- # Adds "(from ...)" to +out+ for +store+
-
- def add_from out, store
- out << RDoc::Markup::Paragraph.new("(from #{store.friendly_path})")
- end
-
- ##
- # Adds +extends+ to +out+
-
- def add_extends out, extends
- add_extension_modules out, 'Extended by', extends
- end
-
- ##
- # Adds a list of +extensions+ to this module of the given +type+ to +out+.
- # add_includes and add_extends call this, so you should use those directly.
-
- def add_extension_modules out, type, extensions
- return if extensions.empty?
-
- out << RDoc::Markup::Rule.new(1)
- out << RDoc::Markup::Heading.new(1, "#{type}:")
-
- extensions.each do |modules, store|
- if modules.length == 1 then
- add_extension_modules_single out, store, modules.first
- else
- add_extension_modules_multiple out, store, modules
- end
- end
- end
-
- ##
- # Renders multiple included +modules+ from +store+ to +out+.
-
- def add_extension_modules_multiple out, store, modules # :nodoc:
- out << RDoc::Markup::Paragraph.new("(from #{store.friendly_path})")
-
- wout, with = modules.partition { |incl| incl.comment.empty? }
-
- out << RDoc::Markup::BlankLine.new unless with.empty?
-
- with.each do |incl|
- out << RDoc::Markup::Paragraph.new(incl.name)
- out << RDoc::Markup::BlankLine.new
- out << incl.comment
- end
-
- unless wout.empty? then
- verb = RDoc::Markup::Verbatim.new
-
- wout.each do |incl|
- verb.push incl.name, "\n"
- end
-
- out << verb
- end
- end
-
- ##
- # Adds a single extension module +include+ from +store+ to +out+
-
- def add_extension_modules_single out, store, include # :nodoc:
- name = include.name
- path = store.friendly_path
- out << RDoc::Markup::Paragraph.new("#{name} (from #{path})")
-
- if include.comment then
- out << RDoc::Markup::BlankLine.new
- out << include.comment
- end
- end
-
- ##
- # Adds +includes+ to +out+
-
- def add_includes out, includes
- add_extension_modules out, 'Includes', includes
- end
-
- ##
- # Looks up the method +name+ and adds it to +out+
-
- def add_method out, name
- filtered = lookup_method name
-
- method_out = method_document name, filtered
-
- out.concat method_out.parts
- end
-
- ##
- # Adds documentation for all methods in +klass+ to +out+
-
- def add_method_documentation out, klass
- klass.method_list.each do |method|
- begin
- add_method out, method.full_name
- rescue NotFoundError
- next
- end
- end
- end
-
- ##
- # Adds a list of +methods+ to +out+ with a heading of +name+
-
- def add_method_list out, methods, name
- return if methods.empty?
-
- out << RDoc::Markup::Heading.new(1, "#{name}:")
- out << RDoc::Markup::BlankLine.new
-
- if @use_stdout and !@interactive then
- out.concat methods.map { |method|
- RDoc::Markup::Verbatim.new method
- }
- else
- out << RDoc::Markup::IndentedParagraph.new(2, methods.join(', '))
- end
-
- out << RDoc::Markup::BlankLine.new
- end
-
- ##
- # Returns ancestor classes of +klass+
-
- def ancestors_of klass
- ancestors = []
-
- unexamined = [klass]
- seen = []
-
- loop do
- break if unexamined.empty?
- current = unexamined.shift
- seen << current
-
- stores = classes[current]
-
- next unless stores and not stores.empty?
-
- klasses = stores.flat_map do |store|
- store.ancestors[current] || []
- end.uniq
-
- klasses = klasses - seen
-
- ancestors.concat klasses
- unexamined.concat klasses
- end
-
- ancestors.reverse
- end
-
- ##
- # For RubyGems backwards compatibility
-
- def class_cache # :nodoc:
- end
-
- ##
- # Builds a RDoc::Markup::Document from +found+, +klasess+ and +includes+
-
- def class_document name, found, klasses, includes, extends
- also_in = []
-
- out = RDoc::Markup::Document.new
-
- add_class out, name, klasses
-
- add_includes out, includes
- add_extends out, extends
-
- found.each do |store, klass|
- render_class out, store, klass, also_in
- end
-
- add_also_in out, also_in
-
- out
- end
-
- ##
- # Adds the class +comment+ to +out+.
-
- def class_document_comment out, comment # :nodoc:
- unless comment.empty? then
- out << RDoc::Markup::Rule.new(1)
-
- if comment.merged? then
- parts = comment.parts
- parts = parts.zip [RDoc::Markup::BlankLine.new] * parts.length
- parts.flatten!
- parts.pop
-
- out.concat parts
- else
- out << comment
- end
- end
- end
-
- ##
- # Adds the constants from +klass+ to the Document +out+.
-
- def class_document_constants out, klass # :nodoc:
- return if klass.constants.empty?
-
- out << RDoc::Markup::Heading.new(1, "Constants:")
- out << RDoc::Markup::BlankLine.new
- list = RDoc::Markup::List.new :NOTE
-
- constants = klass.constants.sort_by { |constant| constant.name }
-
- list.items.concat constants.map { |constant|
- parts = constant.comment.parts if constant.comment
- parts << RDoc::Markup::Paragraph.new('[not documented]') if
- parts.empty?
-
- RDoc::Markup::ListItem.new(constant.name, *parts)
- }
-
- out << list
- out << RDoc::Markup::BlankLine.new
- end
-
- ##
- # Hash mapping a known class or module to the stores it can be loaded from
-
- def classes
- return @classes if @classes
-
- @classes = {}
-
- @stores.each do |store|
- store.cache[:modules].each do |mod|
- # using default block causes searched-for modules to be added
- @classes[mod] ||= []
- @classes[mod] << store
- end
- end
-
- @classes
- end
-
- ##
- # Returns the stores wherein +name+ is found along with the classes,
- # extends and includes that match it
-
- def classes_and_includes_and_extends_for name
- klasses = []
- extends = []
- includes = []
-
- found = @stores.map do |store|
- begin
- klass = store.load_class name
- klasses << klass
- extends << [klass.extends, store] if klass.extends
- includes << [klass.includes, store] if klass.includes
- [store, klass]
- rescue RDoc::Store::MissingFileError
- end
- end.compact
-
- extends.reject! do |modules,| modules.empty? end
- includes.reject! do |modules,| modules.empty? end
-
- [found, klasses, includes, extends]
- end
-
- ##
- # Completes +name+ based on the caches. For Readline
-
- def complete name
- completions = []
-
- klass, selector, method = parse_name name
-
- complete_klass name, klass, selector, method, completions
- complete_method name, klass, selector, completions
-
- completions.sort.uniq
- end
-
- def complete_klass name, klass, selector, method, completions # :nodoc:
- klasses = classes.keys
-
- # may need to include Foo when given Foo::
- klass_name = method ? name : klass
-
- if name !~ /#|\./ then
- completions.replace klasses.grep(/^#{Regexp.escape klass_name}[^:]*$/)
- completions.concat klasses.grep(/^#{Regexp.escape name}[^:]*$/) if
- name =~ /::$/
-
- completions << klass if classes.key? klass # to complete a method name
- elsif selector then
- completions << klass if classes.key? klass
- elsif classes.key? klass_name then
- completions << klass_name
- end
- end
-
- def complete_method name, klass, selector, completions # :nodoc:
- if completions.include? klass and name =~ /#|\.|::/ then
- methods = list_methods_matching name
-
- if not methods.empty? then
- # remove Foo if given Foo:: and a method was found
- completions.delete klass
- elsif selector then
- # replace Foo with Foo:: as given
- completions.delete klass
- completions << "#{klass}#{selector}"
- end
-
- completions.concat methods
- end
- end
-
- ##
- # Converts +document+ to text and writes it to the pager
-
- def display document
- page do |io|
- f = formatter(io)
- f.width = @width if @width and f.respond_to?(:width)
- text = document.accept f
-
- io.write text
- end
- end
-
- ##
- # Outputs formatted RI data for class +name+. Groups undocumented classes
-
- def display_class name
- return if name =~ /#|\./
-
- found, klasses, includes, extends =
- classes_and_includes_and_extends_for name
-
- return if found.empty?
-
- out = class_document name, found, klasses, includes, extends
-
- display out
- end
-
- ##
- # Outputs formatted RI data for method +name+
-
- def display_method name
- out = RDoc::Markup::Document.new
-
- add_method out, name
-
- display out
- end
-
- ##
- # Outputs formatted RI data for the class or method +name+.
- #
- # Returns true if +name+ was found, false if it was not an alternative could
- # be guessed, raises an error if +name+ couldn't be guessed.
-
- def display_name name
- if name =~ /\w:(\w|$)/ then
- display_page name
- return true
- end
-
- return true if display_class name
-
- display_method name if name =~ /::|#|\./
-
- true
- rescue NotFoundError
- matches = list_methods_matching name if name =~ /::|#|\./
- matches = classes.keys.grep(/^#{Regexp.escape name}/) if matches.empty?
-
- raise if matches.empty?
-
- page do |io|
- io.puts "#{name} not found, maybe you meant:"
- io.puts
- io.puts matches.sort.join("\n")
- end
-
- false
- end
-
- ##
- # Displays each name in +name+
-
- def display_names names
- names.each do |name|
- name = expand_name name
-
- display_name name
- end
- end
-
- ##
- # Outputs formatted RI data for page +name+.
-
- def display_page name
- store_name, page_name = name.split ':', 2
-
- store = @stores.find { |s| s.source == store_name }
-
- return display_page_list store if page_name.empty?
-
- pages = store.cache[:pages]
-
- unless pages.include? page_name then
- found_names = pages.select do |n|
- n =~ /#{Regexp.escape page_name}\.[^.]+$/
- end
-
- if found_names.length.zero? then
- return display_page_list store, pages
- elsif found_names.length > 1 then
- return display_page_list store, found_names, page_name
- end
-
- page_name = found_names.first
- end
-
- page = store.load_page page_name
-
- display page.comment
- end
-
- ##
- # Outputs a formatted RI page list for the pages in +store+.
-
- def display_page_list store, pages = store.cache[:pages], search = nil
- out = RDoc::Markup::Document.new
-
- title = if search then
- "#{search} pages"
- else
- 'Pages'
- end
-
- out << RDoc::Markup::Heading.new(1, "#{title} in #{store.friendly_path}")
- out << RDoc::Markup::BlankLine.new
-
- list = RDoc::Markup::List.new(:BULLET)
-
- pages.each do |page|
- list << RDoc::Markup::Paragraph.new(page)
- end
-
- out << list
-
- display out
- end
-
- def check_did_you_mean # :nodoc:
- if defined? DidYouMean::SpellChecker
- true
- else
- begin
- require 'did_you_mean'
- if defined? DidYouMean::SpellChecker
- true
- else
- false
- end
- rescue LoadError
- false
- end
- end
- end
-
- ##
- # Expands abbreviated klass +klass+ into a fully-qualified class. "Zl::Da"
- # will be expanded to Zlib::DataError.
-
- def expand_class klass
- class_names = classes.keys
- ary = class_names.grep(Regexp.new("\\A#{klass.gsub(/(?=::|\z)/, '[^:]*')}\\z"))
- if ary.length != 1 && ary.first != klass
- if check_did_you_mean
- suggestion_proc = -> { DidYouMean::SpellChecker.new(dictionary: class_names).correct(klass) }
- raise NotFoundError.new(klass, suggestion_proc)
- else
- raise NotFoundError, klass
- end
- end
- ary.first
- end
-
- ##
- # Expands the class portion of +name+ into a fully-qualified class. See
- # #expand_class.
-
- def expand_name name
- klass, selector, method = parse_name name
-
- return [selector, method].join if klass.empty?
-
- case selector
- when ':' then
- [find_store(klass), selector, method]
- else
- [expand_class(klass), selector, method]
- end.join
- end
-
- ##
- # Filters the methods in +found+ trying to find a match for +name+.
-
- def filter_methods found, name
- regexp = name_regexp name
-
- filtered = found.find_all do |store, methods|
- methods.any? { |method| method.full_name =~ regexp }
- end
-
- return filtered unless filtered.empty?
-
- found
- end
-
- ##
- # Yields items matching +name+ including the store they were found in, the
- # class being searched for, the class they were found in (an ancestor) the
- # types of methods to look up (from #method_type), and the method name being
- # searched for
-
- def find_methods name
- klass, selector, method = parse_name name
-
- types = method_type selector
-
- klasses = nil
- ambiguous = klass.empty?
-
- if ambiguous then
- klasses = classes.keys
- else
- klasses = ancestors_of klass
- klasses.unshift klass
- end
-
- methods = []
-
- klasses.each do |ancestor|
- ancestors = classes[ancestor]
-
- next unless ancestors
-
- klass = ancestor if ambiguous
-
- ancestors.each do |store|
- methods << [store, klass, ancestor, types, method]
- end
- end
-
- methods = methods.sort_by do |_, k, a, _, m|
- [k, a, m].compact
- end
-
- methods.each do |item|
- yield(*item) # :yields: store, klass, ancestor, types, method
- end
-
- self
- end
-
- ##
- # Finds a store that matches +name+ which can be the name of a gem, "ruby",
- # "home" or "site".
- #
- # See also RDoc::Store#source
-
- def find_store name
- @stores.each do |store|
- source = store.source
-
- return source if source == name
-
- return source if
- store.type == :gem and source =~ /^#{Regexp.escape name}-\d/
- end
-
- raise RDoc::RI::Driver::NotFoundError, name
- end
-
- ##
- # Creates a new RDoc::Markup::Formatter. If a formatter is given with -f,
- # use it. If we're outputting to a pager, use bs, otherwise ansi.
-
- def formatter(io)
- if @formatter_klass then
- @formatter_klass.new
- elsif paging? or !io.tty? then
- RDoc::Markup::ToBs.new
- else
- RDoc::Markup::ToAnsi.new
- end
- end
-
- ##
- # Runs ri interactively using Readline if it is available.
-
- def interactive
- puts "\nEnter the method name you want to look up."
-
- begin
- require 'readline'
- rescue LoadError
- end
- if defined? Readline then
- Readline.completion_proc = method :complete
- puts "You can use tab to autocomplete."
- end
-
- puts "Enter a blank line to exit.\n\n"
-
- loop do
- name = if defined? Readline then
- Readline.readline ">> ", true
- else
- print ">> "
- $stdin.gets
- end
-
- return if name.nil? or name.empty?
-
- begin
- display_name expand_name(name.strip)
- rescue NotFoundError => e
- puts e.message
- end
- end
-
- rescue Interrupt
- exit
- end
-
- ##
- # Lists classes known to ri starting with +names+. If +names+ is empty all
- # known classes are shown.
-
- def list_known_classes names = []
- classes = []
-
- stores.each do |store|
- classes << store.module_names
- end
-
- classes = classes.flatten.uniq.sort
-
- unless names.empty? then
- filter = Regexp.union names.map { |name| /^#{name}/ }
-
- classes = classes.grep filter
- end
-
- page do |io|
- if paging? or io.tty? then
- if names.empty? then
- io.puts "Classes and Modules known to ri:"
- else
- io.puts "Classes and Modules starting with #{names.join ', '}:"
- end
- io.puts
- end
-
- io.puts classes.join("\n")
- end
- end
-
- ##
- # Returns an Array of methods matching +name+
-
- def list_methods_matching name
- found = []
-
- find_methods name do |store, klass, ancestor, types, method|
- if types == :instance or types == :both then
- methods = store.instance_methods[ancestor]
-
- if methods then
- matches = methods.grep(/^#{Regexp.escape method.to_s}/)
-
- matches = matches.map do |match|
- "#{klass}##{match}"
- end
-
- found.concat matches
- end
- end
-
- if types == :class or types == :both then
- methods = store.class_methods[ancestor]
-
- next unless methods
- matches = methods.grep(/^#{Regexp.escape method.to_s}/)
-
- matches = matches.map do |match|
- "#{klass}::#{match}"
- end
-
- found.concat matches
- end
- end
-
- found.uniq
- end
-
- ##
- # Loads RI data for method +name+ on +klass+ from +store+. +type+ and
- # +cache+ indicate if it is a class or instance method.
-
- def load_method store, cache, klass, type, name
- methods = store.public_send(cache)[klass]
-
- return unless methods
-
- method = methods.find do |method_name|
- method_name == name
- end
-
- return unless method
-
- store.load_method klass, "#{type}#{method}"
- rescue RDoc::Store::MissingFileError => e
- comment = RDoc::Comment.new("missing documentation at #{e.file}").parse
-
- method = RDoc::AnyMethod.new nil, name
- method.comment = comment
- method
- end
-
- ##
- # Returns an Array of RI data for methods matching +name+
-
- def load_methods_matching name
- found = []
-
- find_methods name do |store, klass, ancestor, types, method|
- methods = []
-
- methods << load_method(store, :class_methods, ancestor, '::', method) if
- [:class, :both].include? types
-
- methods << load_method(store, :instance_methods, ancestor, '#', method) if
- [:instance, :both].include? types
-
- found << [store, methods.compact]
- end
-
- found.reject do |path, methods| methods.empty? end
- end
-
- ##
- # Returns a filtered list of methods matching +name+
-
- def lookup_method name
- found = load_methods_matching name
-
- if found.empty?
- if check_did_you_mean
- methods = []
- _, _, method_name = parse_name name
- find_methods name do |store, klass, ancestor, types, method|
- methods.push(*store.class_methods[klass]) if [:class, :both].include? types
- methods.push(*store.instance_methods[klass]) if [:instance, :both].include? types
- end
- methods = methods.uniq
- suggestion_proc = -> { DidYouMean::SpellChecker.new(dictionary: methods).correct(method_name) }
- raise NotFoundError.new(name, suggestion_proc)
- else
- raise NotFoundError, name
- end
- end
-
- filter_methods found, name
- end
-
- ##
- # Builds a RDoc::Markup::Document from +found+, +klasses+ and +includes+
-
- def method_document name, filtered
- out = RDoc::Markup::Document.new
-
- out << RDoc::Markup::Heading.new(1, name)
- out << RDoc::Markup::BlankLine.new
-
- filtered.each do |store, methods|
- methods.each do |method|
- render_method out, store, method, name
- end
- end
-
- out
- end
-
- ##
- # Returns the type of method (:both, :instance, :class) for +selector+
-
- def method_type selector
- case selector
- when '.', nil then :both
- when '#' then :instance
- else :class
- end
- end
-
- ##
- # Returns a regular expression for +name+ that will match an
- # RDoc::AnyMethod's name.
-
- def name_regexp name
- klass, type, name = parse_name name
-
- case type
- when '#', '::' then
- /^#{klass}#{type}#{Regexp.escape name}$/
- else
- /^#{klass}(#|::)#{Regexp.escape name}$/
- end
- end
-
- ##
- # Paginates output through a pager program.
-
- def page
- if pager = setup_pager then
- begin
- yield pager
- ensure
- pager.close
- end
- else
- yield $stdout
- end
- rescue Errno::EPIPE
- ensure
- @paging = false
- end
-
- ##
- # Are we using a pager?
-
- def paging?
- @paging
- end
-
- ##
- # Extracts the class, selector and method name parts from +name+ like
- # Foo::Bar#baz.
- #
- # NOTE: Given Foo::Bar, Bar is considered a class even though it may be a
- # method
-
- def parse_name name
- parts = name.split(/(::?|#|\.)/)
-
- if parts.length == 1 then
- if parts.first =~ /^[a-z]|^([%&*+\/<>^`|~-]|\+@|-@|<<|<=>?|===?|=>|=~|>>|\[\]=?|~@)$/ then
- type = '.'
- meth = parts.pop
- else
- type = nil
- meth = nil
- end
- elsif parts.length == 2 or parts.last =~ /::|#|\./ then
- type = parts.pop
- meth = nil
- elsif parts[1] == ':' then
- klass = parts.shift
- type = parts.shift
- meth = parts.join
- elsif parts[-2] != '::' or parts.last !~ /^[A-Z]/ then
- meth = parts.pop
- type = parts.pop
- end
-
- klass ||= parts.join
-
- [klass, type, meth]
- end
-
- ##
- # Renders the +klass+ from +store+ to +out+. If the klass has no
- # documentable items the class is added to +also_in+ instead.
-
- def render_class out, store, klass, also_in # :nodoc:
- comment = klass.comment
- # TODO the store's cache should always return an empty Array
- class_methods = store.class_methods[klass.full_name] || []
- instance_methods = store.instance_methods[klass.full_name] || []
- attributes = store.attributes[klass.full_name] || []
-
- if comment.empty? and
- instance_methods.empty? and class_methods.empty? then
- also_in << store
- return
- end
-
- add_from out, store
-
- class_document_comment out, comment
-
- if class_methods or instance_methods or not klass.constants.empty? then
- out << RDoc::Markup::Rule.new(1)
- end
-
- class_document_constants out, klass
-
- add_method_list out, class_methods, 'Class methods'
- add_method_list out, instance_methods, 'Instance methods'
- add_method_list out, attributes, 'Attributes'
-
- add_method_documentation out, klass if @show_all
- end
-
- def render_method out, store, method, name # :nodoc:
- out << RDoc::Markup::Paragraph.new("(from #{store.friendly_path})")
-
- unless name =~ /^#{Regexp.escape method.parent_name}/ then
- out << RDoc::Markup::Heading.new(3, "Implementation from #{method.parent_name}")
- end
-
- out << RDoc::Markup::Rule.new(1)
-
- render_method_arguments out, method.arglists
- render_method_superclass out, method
- if method.is_alias_for
- al = method.is_alias_for
- alias_for = store.load_method al.parent_name, "#{al.name_prefix}#{al.name}"
- render_method_comment out, method, alias_for
- else
- render_method_comment out, method
- end
- end
-
- def render_method_arguments out, arglists # :nodoc:
- return unless arglists
-
- arglists = arglists.chomp.split "\n"
- arglists = arglists.map { |line| line + "\n" }
- out << RDoc::Markup::Verbatim.new(*arglists)
- out << RDoc::Markup::Rule.new(1)
- end
-
- def render_method_comment out, method, alias_for = nil# :nodoc:
- if alias_for
- unless method.comment.nil? or method.comment.empty?
- out << RDoc::Markup::BlankLine.new
- out << method.comment
- end
- out << RDoc::Markup::BlankLine.new
- out << RDoc::Markup::Paragraph.new("(This method is an alias for #{alias_for.full_name}.)")
- out << RDoc::Markup::BlankLine.new
- out << alias_for.comment
- out << RDoc::Markup::BlankLine.new
- else
- out << RDoc::Markup::BlankLine.new
- out << method.comment
- out << RDoc::Markup::BlankLine.new
- end
- end
-
- def render_method_superclass out, method # :nodoc:
- return unless
- method.respond_to?(:superclass_method) and method.superclass_method
-
- out << RDoc::Markup::BlankLine.new
- out << RDoc::Markup::Heading.new(4, "(Uses superclass method #{method.superclass_method})")
- out << RDoc::Markup::Rule.new(1)
- end
-
- ##
- # Looks up and displays ri data according to the options given.
-
- def run
- if @list_doc_dirs then
- puts @doc_dirs
- elsif @list then
- list_known_classes @names
- elsif @server then
- start_server
- elsif @interactive or @names.empty? then
- interactive
- else
- display_names @names
- end
- rescue NotFoundError => e
- abort e.message
- end
-
- ##
- # Sets up a pager program to pass output through. Tries the RI_PAGER and
- # PAGER environment variables followed by pager, less then more.
-
- def setup_pager
- return if @use_stdout
-
- pagers = [ENV['RI_PAGER'], ENV['PAGER'], 'pager', 'less', 'more']
-
- require 'shellwords'
- pagers.compact.uniq.each do |pager|
- pager = Shellwords.split(pager)
- next if pager.empty?
-
- io = IO.popen(pager, 'w') rescue next
- next if $? and $?.pid == io.pid and $?.exited? # pager didn't work
-
- @paging = true
-
- return io
- end
-
- @use_stdout = true
-
- nil
- end
-
- ##
- # Starts a WEBrick server for ri.
-
- def start_server
- 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
-
- extra_doc_dirs = @stores.map {|s| s.type == :extra ? s.path : nil}.compact
-
- server.mount '/', RDoc::Servlet, nil, extra_doc_dirs
-
- trap 'INT' do server.shutdown end
- trap 'TERM' do server.shutdown end
-
- server.start
- end
-
-end
diff --git a/lib/rdoc/ri/formatter.rb b/lib/rdoc/ri/formatter.rb
deleted file mode 100644
index 832a101e6c..0000000000
--- a/lib/rdoc/ri/formatter.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# frozen_string_literal: true
-##
-# For RubyGems backwards compatibility
-
-module RDoc::RI::Formatter # :nodoc:
-end
diff --git a/lib/rdoc/ri/paths.rb b/lib/rdoc/ri/paths.rb
deleted file mode 100644
index 8e89b04e54..0000000000
--- a/lib/rdoc/ri/paths.rb
+++ /dev/null
@@ -1,171 +0,0 @@
-# frozen_string_literal: true
-require_relative '../rdoc'
-
-##
-# The directories where ri data lives. Paths can be enumerated via ::each, or
-# queried individually via ::system_dir, ::site_dir, ::home_dir and ::gem_dir.
-
-module RDoc::RI::Paths
-
- #:stopdoc:
- require 'rbconfig'
-
- version = RbConfig::CONFIG['ruby_version']
-
- BASE = File.join RbConfig::CONFIG['ridir'], version
-
- HOMEDIR = RDoc.home
- #:startdoc:
-
- ##
- # Iterates over each selected path yielding the directory and type.
- #
- # Yielded types:
- # :system:: Where Ruby's ri data is stored. Yielded when +system+ is
- # true
- # :site:: Where ri for installed libraries are stored. Yielded when
- # +site+ is true. Normally no ri data is stored here.
- # :home:: ~/.rdoc. Yielded when +home+ is true.
- # :gem:: ri data for an installed gem. Yielded when +gems+ is true.
- # :extra:: ri data directory from the command line. Yielded for each
- # entry in +extra_dirs+
-
- def self.each system = true, site = true, home = true, gems = :latest, *extra_dirs # :yields: directory, type
- return enum_for __method__, system, site, home, gems, *extra_dirs unless
- block_given?
-
- extra_dirs.each do |dir|
- yield dir, :extra
- end
-
- yield system_dir, :system if system
- yield site_dir, :site if site
- yield home_dir, :home if home and HOMEDIR
-
- gemdirs(gems).each do |dir|
- yield dir, :gem
- end if gems
-
- nil
- end
-
- ##
- # The ri directory for the gem with +gem_name+.
-
- def self.gem_dir name, version
- req = Gem::Requirement.new "= #{version}"
-
- spec = Gem::Specification.find_by_name name, req
-
- File.join spec.doc_dir, 'ri'
- end
-
- ##
- # The latest installed gems' ri directories. +filter+ can be :all or
- # :latest.
- #
- # A +filter+ :all includes all versions of gems and includes gems without
- # ri documentation.
-
- def self.gemdirs filter = :latest
- ri_paths = {}
-
- all = Gem::Specification.map do |spec|
- [File.join(spec.doc_dir, 'ri'), spec.name, spec.version]
- end
-
- if filter == :all then
- gemdirs = []
-
- all.group_by do |_, name, _|
- name
- end.sort_by do |group, _|
- group
- end.map do |group, items|
- items.sort_by do |_, _, version|
- version
- end.reverse_each do |dir,|
- gemdirs << dir
- end
- end
-
- return gemdirs
- end
-
- all.each do |dir, name, ver|
- next unless File.exist? dir
-
- if ri_paths[name].nil? or ver > ri_paths[name].first then
- ri_paths[name] = [ver, name, dir]
- end
- end
-
- ri_paths.sort_by { |_, (_, name, _)| name }.map { |k, v| v.last }
- rescue LoadError
- []
- end
-
- ##
- # The location of the rdoc data in the user's home directory.
- #
- # Like ::system, ri data in the user's home directory is rare and predates
- # libraries distributed via RubyGems. ri data is rarely generated into this
- # directory.
-
- def self.home_dir
- HOMEDIR
- end
-
- ##
- # Returns existing directories from the selected documentation directories
- # as an Array.
- #
- # See also ::each
-
- def self.path(system = true, site = true, home = true, gems = :latest, *extra_dirs)
- path = raw_path system, site, home, gems, *extra_dirs
-
- path.select { |directory| File.directory? directory }
- end
-
- ##
- # Returns selected documentation directories including nonexistent
- # directories.
- #
- # See also ::each
-
- def self.raw_path(system, site, home, gems, *extra_dirs)
- path = []
-
- each(system, site, home, gems, *extra_dirs) do |dir, type|
- path << dir
- end
-
- path.compact
- end
-
- ##
- # The location of ri data installed into the site dir.
- #
- # Historically this was available for documentation installed by Ruby
- # libraries predating RubyGems. It is unlikely to contain any content for
- # modern Ruby installations.
-
- def self.site_dir
- File.join BASE, 'site'
- end
-
- ##
- # The location of the built-in ri data.
- #
- # This data is built automatically when `make` is run when Ruby is
- # installed. If you did not install Ruby by hand you may need to install
- # the documentation yourself. Please consult the documentation for your
- # package manager or Ruby installer for details. You can also use the
- # rdoc-data gem to install system ri data for common versions of Ruby.
-
- def self.system_dir
- File.join BASE, 'system'
- end
-
-end
diff --git a/lib/rdoc/ri/store.rb b/lib/rdoc/ri/store.rb
deleted file mode 100644
index 96742e7ae3..0000000000
--- a/lib/rdoc/ri/store.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# frozen_string_literal: true
-module RDoc::RI
-
- Store = RDoc::Store # :nodoc:
-
-end
diff --git a/lib/rdoc/ri/task.rb b/lib/rdoc/ri/task.rb
deleted file mode 100644
index 1122ea3775..0000000000
--- a/lib/rdoc/ri/task.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-# frozen_string_literal: true
-begin
- gem 'rdoc'
-rescue Gem::LoadError
-end unless defined?(RDoc)
-
-require_relative '../task'
-
-##
-# RDoc::RI::Task creates ri data in <code>./.rdoc</code> for your project.
-#
-# It contains the following tasks:
-#
-# [ri]
-# Build ri data
-#
-# [clobber_ri]
-# Delete ri data files. This target is automatically added to the main
-# clobber target.
-#
-# [reri]
-# Rebuild the ri data from scratch even if they are not out of date.
-#
-# Simple example:
-#
-# require 'rdoc/ri/task'
-#
-# RDoc::RI::Task.new do |ri|
-# ri.main = 'README.rdoc'
-# ri.rdoc_files.include 'README.rdoc', 'lib/**/*.rb'
-# end
-#
-# For further configuration details see RDoc::Task.
-
-class RDoc::RI::Task < RDoc::Task
-
- DEFAULT_NAMES = { # :nodoc:
- :clobber_rdoc => :clobber_ri,
- :rdoc => :ri,
- :rerdoc => :reri,
- }
-
- ##
- # Create an ri task with the given name. See RDoc::Task for documentation on
- # setting names.
-
- def initialize name = DEFAULT_NAMES # :yield: self
- super
- end
-
- def clobber_task_description # :nodoc:
- "Remove RI data files"
- end
-
- ##
- # Sets default task values
-
- def defaults
- super
-
- @rdoc_dir = '.rdoc'
- end
-
- def rdoc_task_description # :nodoc:
- 'Build RI data files'
- end
-
- def rerdoc_task_description # :nodoc:
- 'Rebuild RI data files'
- end
-end
diff --git a/lib/rdoc/rubygems_hook.rb b/lib/rdoc/rubygems_hook.rb
deleted file mode 100644
index 3160072e53..0000000000
--- a/lib/rdoc/rubygems_hook.rb
+++ /dev/null
@@ -1,248 +0,0 @@
-# frozen_string_literal: true
-require 'rubygems/user_interaction'
-require 'fileutils'
-require_relative '../rdoc'
-
-##
-# Gem::RDoc provides methods to generate RDoc and ri data for installed gems
-# upon gem installation.
-#
-# This file is automatically required by RubyGems 1.9 and newer.
-
-class RDoc::RubygemsHook
-
- include Gem::UserInteraction
- extend Gem::UserInteraction
-
- @rdoc_version = nil
- @specs = []
-
- ##
- # Force installation of documentation?
-
- attr_accessor :force
-
- ##
- # Generate rdoc?
-
- attr_accessor :generate_rdoc
-
- ##
- # Generate ri data?
-
- attr_accessor :generate_ri
-
- class << self
-
- ##
- # Loaded version of RDoc. Set by ::load_rdoc
-
- attr_reader :rdoc_version
-
- end
-
- ##
- # Post installs hook that generates documentation for each specification in
- # +specs+
-
- def self.generation_hook installer, specs
- start = Time.now
- types = installer.document
-
- generate_rdoc = types.include? 'rdoc'
- generate_ri = types.include? 'ri'
-
- specs.each do |spec|
- new(spec, generate_rdoc, generate_ri).generate
- end
-
- return unless generate_rdoc or generate_ri
-
- duration = (Time.now - start).to_i
- names = specs.map(&:name).join ', '
-
- say "Done installing documentation for #{names} after #{duration} seconds"
- end
-
- ##
- # Loads the RDoc generator
-
- def self.load_rdoc
- return if @rdoc_version
-
- require_relative 'rdoc'
-
- @rdoc_version = Gem::Version.new ::RDoc::VERSION
- end
-
- ##
- # Creates a new documentation generator for +spec+. RDoc and ri data
- # generation can be enabled or disabled through +generate_rdoc+ and
- # +generate_ri+ respectively.
- #
- # Only +generate_ri+ is enabled by default.
-
- def initialize spec, generate_rdoc = false, generate_ri = true
- @doc_dir = spec.doc_dir
- @force = false
- @rdoc = nil
- @spec = spec
-
- @generate_rdoc = generate_rdoc
- @generate_ri = generate_ri
-
- @rdoc_dir = spec.doc_dir 'rdoc'
- @ri_dir = spec.doc_dir 'ri'
- end
-
- ##
- # Removes legacy rdoc arguments from +args+
- #--
- # TODO move to RDoc::Options
-
- def delete_legacy_args args
- args.delete '--inline-source'
- args.delete '--promiscuous'
- args.delete '-p'
- args.delete '--one-file'
- end
-
- ##
- # Generates documentation using the named +generator+ ("darkfish" or "ri")
- # and following the given +options+.
- #
- # Documentation will be generated into +destination+
-
- def document generator, options, destination
- generator_name = generator
-
- options = options.dup
- options.exclude ||= [] # TODO maybe move to RDoc::Options#finish
- options.setup_generator generator
- options.op_dir = destination
- Dir.chdir @spec.full_gem_path do
- options.finish
- end
-
- generator = options.generator.new @rdoc.store, options
-
- @rdoc.options = options
- @rdoc.generator = generator
-
- say "Installing #{generator_name} documentation for #{@spec.full_name}"
-
- FileUtils.mkdir_p options.op_dir
-
- Dir.chdir options.op_dir do
- begin
- @rdoc.class.current = @rdoc
- @rdoc.generator.generate
- ensure
- @rdoc.class.current = nil
- end
- end
- end
-
- ##
- # Generates RDoc and ri data
-
- def generate
- return if @spec.default_gem?
- return unless @generate_ri or @generate_rdoc
-
- setup
-
- options = nil
-
- args = @spec.rdoc_options
- args.concat @spec.source_paths
- args.concat @spec.extra_rdoc_files
-
- case config_args = Gem.configuration[:rdoc]
- when String then
- args = args.concat config_args.split(' ')
- when Array then
- args = args.concat config_args
- end
-
- delete_legacy_args args
-
- Dir.chdir @spec.full_gem_path do
- options = ::RDoc::Options.new
- options.default_title = "#{@spec.full_name} Documentation"
- options.parse args
- end
-
- options.quiet = !Gem.configuration.really_verbose
-
- @rdoc = new_rdoc
- @rdoc.options = options
-
- store = RDoc::Store.new
- store.encoding = options.encoding
- store.dry_run = options.dry_run
- store.main = options.main_page
- store.title = options.title
-
- @rdoc.store = store
-
- say "Parsing documentation for #{@spec.full_name}"
-
- Dir.chdir @spec.full_gem_path do
- @rdoc.parse_files options.files
- end
-
- document 'ri', options, @ri_dir if
- @generate_ri and (@force or not File.exist? @ri_dir)
-
- document 'darkfish', options, @rdoc_dir if
- @generate_rdoc and (@force or not File.exist? @rdoc_dir)
- end
-
- ##
- # #new_rdoc creates a new RDoc instance. This method is provided only to
- # make testing easier.
-
- def new_rdoc # :nodoc:
- ::RDoc::RDoc.new
- end
-
- ##
- # Is rdoc documentation installed?
-
- def rdoc_installed?
- File.exist? @rdoc_dir
- end
-
- ##
- # Removes generated RDoc and ri data
-
- def remove
- base_dir = @spec.base_dir
-
- raise Gem::FilePermissionError, base_dir unless File.writable? base_dir
-
- FileUtils.rm_rf @rdoc_dir
- FileUtils.rm_rf @ri_dir
- end
-
- ##
- # Is ri data installed?
-
- def ri_installed?
- File.exist? @ri_dir
- end
-
- ##
- # Prepares the spec for documentation generation
-
- def setup
- self.class.load_rdoc
-
- raise Gem::FilePermissionError, @doc_dir if
- File.exist?(@doc_dir) and not File.writable?(@doc_dir)
-
- FileUtils.mkdir_p @doc_dir unless File.exist? @doc_dir
- end
-
-end
diff --git a/lib/rdoc/servlet.rb b/lib/rdoc/servlet.rb
deleted file mode 100644
index d05368766a..0000000000
--- a/lib/rdoc/servlet.rb
+++ /dev/null
@@ -1,451 +0,0 @@
-# frozen_string_literal: true
-require_relative '../rdoc'
-require 'erb'
-require 'time'
-require 'json'
-
-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.
-#
-# You can show documentation through either `ri --server` or, with RubyGems
-# 2.0 or newer, `gem server`. For ri, the server runs on port 8214 by
-# default. For RubyGems the server runs on port 8808 by default.
-#
-# You can use this servlet in your own project by mounting it on a WEBrick
-# server:
-#
-# require 'webrick'
-#
-# server = WEBrick::HTTPServer.new Port: 8000
-#
-# server.mount '/', RDoc::Servlet
-#
-# If you want to mount the servlet some other place than the root, provide the
-# base path when mounting:
-#
-# server.mount '/rdoc', RDoc::Servlet, '/rdoc'
-
-class RDoc::Servlet < WEBrick::HTTPServlet::AbstractServlet
-
- @server_stores = Hash.new { |hash, server| hash[server] = {} }
- @cache = Hash.new { |hash, store| hash[store] = {} }
-
- ##
- # Maps an asset type to its path on the filesystem
-
- attr_reader :asset_dirs
-
- ##
- # An RDoc::Options instance used for rendering options
-
- attr_reader :options
-
- ##
- # Creates an instance of this servlet that shares cached data between
- # requests.
-
- def self.get_instance server, *options # :nodoc:
- stores = @server_stores[server]
-
- new server, stores, @cache, *options
- end
-
- ##
- # Creates a new WEBrick servlet.
- #
- # Use +mount_path+ when mounting the servlet somewhere other than /.
- #
- # Use +extra_doc_dirs+ for additional documentation directories.
- #
- # +server+ is provided automatically by WEBrick when mounting. +stores+ and
- # +cache+ are provided automatically by the servlet.
-
- def initialize server, stores, cache, mount_path = nil, extra_doc_dirs = []
- super server
-
- @cache = cache
- @mount_path = mount_path
- @extra_doc_dirs = extra_doc_dirs
- @stores = stores
-
- @options = RDoc::Options.new
- @options.op_dir = '.'
-
- darkfish_dir = nil
-
- # HACK dup
- $LOAD_PATH.each do |path|
- darkfish_dir = File.join path, 'rdoc/generator/template/darkfish/'
- next unless File.directory? darkfish_dir
- @options.template_dir = darkfish_dir
- break
- end
-
- @asset_dirs = {
- :darkfish => darkfish_dir,
- :json_index =>
- File.expand_path('../generator/template/json_index/', __FILE__),
- }
- end
-
- ##
- # Serves the asset at the path in +req+ for +generator_name+ via +res+.
-
- def asset generator_name, req, res
- asset_dir = @asset_dirs[generator_name]
-
- asset_path = File.join asset_dir, req.path
-
- if_modified_since req, res, asset_path
-
- res.body = File.read asset_path
-
- res.content_type = case req.path
- when /\.css\z/ then 'text/css'
- when /\.js\z/ then 'application/javascript'
- else 'application/octet-stream'
- end
- end
-
- ##
- # GET request entry point. Fills in +res+ for the path, etc. in +req+.
-
- def do_GET req, res
- req.path.sub!(/\A#{Regexp.escape @mount_path}/, '') if @mount_path
-
- case req.path
- when '/' then
- root req, res
- when '/js/darkfish.js', '/js/jquery.js', '/js/search.js',
- %r%^/css/%, %r%^/images/%, %r%^/fonts/% then
- asset :darkfish, req, res
- when '/js/navigation.js', '/js/searcher.js' then
- asset :json_index, req, res
- when '/js/search_index.js' then
- root_search req, res
- else
- show_documentation req, res
- end
- rescue WEBrick::HTTPStatus::NotFound => e
- generator = generator_for RDoc::Store.new
-
- not_found generator, req, res, e.message
- rescue WEBrick::HTTPStatus::Status
- raise
- rescue => e
- error e, req, res
- end
-
- ##
- # Fills in +res+ with the class, module or page for +req+ from +store+.
- #
- # +path+ is relative to the mount_path and is used to determine the class,
- # module or page name (/RDoc/Servlet.html becomes RDoc::Servlet).
- # +generator+ is used to create the page.
-
- def documentation_page store, generator, path, req, res
- text_name = path.chomp '.html'
- name = text_name.gsub '/', '::'
-
- if klass = store.find_class_or_module(name) then
- res.body = generator.generate_class klass
- elsif page = store.find_text_page(name.sub(/_([^_]*)\z/, '.\1')) then
- res.body = generator.generate_page page
- elsif page = store.find_text_page(text_name.sub(/_([^_]*)\z/, '.\1')) then
- res.body = generator.generate_page page
- else
- not_found generator, req, res
- end
- end
-
- ##
- # Creates the JSON search index on +res+ for the given +store+. +generator+
- # must respond to \#json_index to build. +req+ is ignored.
-
- def documentation_search store, generator, req, res
- json_index = @cache[store].fetch :json_index do
- @cache[store][:json_index] =
- JSON.dump generator.json_index.build_index
- end
-
- res.content_type = 'application/javascript'
- res.body = "var search_data = #{json_index}"
- end
-
- ##
- # Returns the RDoc::Store and path relative to +mount_path+ for
- # documentation at +path+.
-
- def documentation_source path
- _, source_name, path = path.split '/', 3
-
- store = @stores[source_name]
- return store, path if store
-
- store = store_for source_name
-
- store.load_all
-
- @stores[source_name] = store
-
- return store, path
- end
-
- ##
- # Generates an error page for the +exception+ while handling +req+ on +res+.
-
- def error exception, req, res
- backtrace = exception.backtrace.join "\n"
-
- res.content_type = 'text/html'
- res.status = 500
- res.body = <<-BODY
-<!DOCTYPE html>
-<html>
-<head>
-<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
-
-<title>Error - #{ERB::Util.html_escape exception.class}</title>
-
-<link type="text/css" media="screen" href="#{@mount_path}/css/rdoc.css" rel="stylesheet">
-</head>
-<body>
-<h1>Error</h1>
-
-<p>While processing <code>#{ERB::Util.html_escape req.request_uri}</code> the
-RDoc (#{ERB::Util.html_escape RDoc::VERSION}) server has encountered a
-<code>#{ERB::Util.html_escape exception.class}</code>
-exception:
-
-<pre>#{ERB::Util.html_escape exception.message}</pre>
-
-<p>Please report this to the
-<a href="https://github.com/ruby/rdoc/issues">RDoc issues tracker</a>. Please
-include the RDoc version, the URI above and exception class, message and
-backtrace. If you're viewing a gem's documentation, include the gem name and
-version. If you're viewing Ruby's documentation, include the version of ruby.
-
-<p>Backtrace:
-
-<pre>#{ERB::Util.html_escape backtrace}</pre>
-
-</body>
-</html>
- BODY
- end
-
- ##
- # Instantiates a Darkfish generator for +store+
-
- def generator_for store
- generator = RDoc::Generator::Darkfish.new store, @options
- generator.file_output = false
- generator.asset_rel_path = '..'
-
- rdoc = RDoc::RDoc.new
- rdoc.store = store
- rdoc.generator = generator
- rdoc.options = @options
-
- @options.main_page = store.main
- @options.title = store.title
-
- generator
- end
-
- ##
- # Handles the If-Modified-Since HTTP header on +req+ for +path+. If the
- # file has not been modified a Not Modified response is returned. If the
- # file has been modified a Last-Modified header is added to +res+.
-
- def if_modified_since req, res, path = nil
- last_modified = File.stat(path).mtime if path
-
- res['last-modified'] = last_modified.httpdate
-
- return unless ims = req['if-modified-since']
-
- ims = Time.parse ims
-
- unless ims < last_modified then
- res.body = ''
- raise WEBrick::HTTPStatus::NotModified
- end
- end
-
- ##
- # Returns an Array of installed documentation.
- #
- # Each entry contains the documentation name (gem name, 'Ruby
- # Documentation', etc.), the path relative to the mount point, whether the
- # documentation exists, the type of documentation (See RDoc::RI::Paths#each)
- # and the filesystem to the RDoc::Store for the documentation.
-
- def installed_docs
- extra_counter = 0
- ri_paths.map do |path, type|
- store = RDoc::Store.new path, type
- exists = File.exist? store.cache_path
-
- case type
- when :gem then
- gem_path = path[%r%/([^/]*)/ri$%, 1]
- [gem_path, "#{gem_path}/", exists, type, path]
- when :system then
- ['Ruby Documentation', 'ruby/', exists, type, path]
- when :site then
- ['Site Documentation', 'site/', exists, type, path]
- when :home then
- ['Home Documentation', 'home/', exists, type, path]
- when :extra then
- extra_counter += 1
- store.load_cache if exists
- title = store.title || "Extra Documentation"
- [title, "extra-#{extra_counter}/", exists, type, path]
- end
- end
- end
-
- ##
- # Returns a 404 page built by +generator+ for +req+ on +res+.
-
- def not_found generator, req, res, message = nil
- message ||= "The page <kbd>#{ERB::Util.h req.path}</kbd> was not found"
- res.body = generator.generate_servlet_not_found message
- res.status = 404
- end
-
- ##
- # Enumerates the ri paths. See RDoc::RI::Paths#each
-
- def ri_paths &block
- RDoc::RI::Paths.each true, true, true, :all, *@extra_doc_dirs, &block #TODO: pass extra_dirs
- end
-
- ##
- # Generates the root page on +res+. +req+ is ignored.
-
- def root req, res
- generator = RDoc::Generator::Darkfish.new nil, @options
-
- res.body = generator.generate_servlet_root installed_docs
-
- res.content_type = 'text/html'
- end
-
- ##
- # Generates a search index for the root page on +res+. +req+ is ignored.
-
- def root_search req, res
- search_index = []
- info = []
-
- installed_docs.map do |name, href, exists, type, path|
- next unless exists
-
- search_index << name
-
- case type
- when :gem
- gemspec = path.gsub(%r%/doc/([^/]*?)/ri$%,
- '/specifications/\1.gemspec')
-
- spec = Gem::Specification.load gemspec
-
- path = spec.full_name
- comment = spec.summary
- when :system then
- path = 'ruby'
- comment = 'Documentation for the Ruby standard library'
- when :site then
- path = 'site'
- comment = 'Documentation for non-gem libraries'
- when :home then
- path = 'home'
- comment = 'Documentation from your home directory'
- when :extra
- comment = name
- end
-
- info << [name, '', path, '', comment]
- end
-
- index = {
- :index => {
- :searchIndex => search_index,
- :longSearchIndex => search_index,
- :info => info,
- }
- }
-
- res.body = "var search_data = #{JSON.dump index};"
- res.content_type = 'application/javascript'
- end
-
- ##
- # Displays documentation for +req+ on +res+, whether that be HTML or some
- # asset.
-
- def show_documentation req, res
- store, path = documentation_source req.path
-
- if_modified_since req, res, store.cache_path
-
- generator = generator_for store
-
- case path
- when nil, '', 'index.html' then
- res.body = generator.generate_index
- when 'table_of_contents.html' then
- res.body = generator.generate_table_of_contents
- when 'js/search_index.js' then
- documentation_search store, generator, req, res
- else
- documentation_page store, generator, path, req, res
- end
- ensure
- res.content_type ||= 'text/html'
- end
-
- ##
- # Returns an RDoc::Store for the given +source_name+ ('ruby' or a gem name).
-
- def store_for source_name
- case source_name
- when 'home' then
- RDoc::Store.new RDoc::RI::Paths.home_dir, :home
- when 'ruby' then
- RDoc::Store.new RDoc::RI::Paths.system_dir, :system
- when 'site' then
- RDoc::Store.new RDoc::RI::Paths.site_dir, :site
- when /\Aextra-(\d+)\z/ then
- index = $1.to_i - 1
- ri_dir = installed_docs[index][4]
- RDoc::Store.new ri_dir, :extra
- else
- ri_dir, type = ri_paths.find do |dir, dir_type|
- next unless dir_type == :gem
-
- source_name == dir[%r%/([^/]*)/ri$%, 1]
- end
-
- raise WEBrick::HTTPStatus::NotFound,
- "Could not find gem \"#{ERB::Util.html_escape(source_name)}\". Are you sure you installed it?" unless ri_dir
-
- store = RDoc::Store.new ri_dir, type
-
- return store if File.exist? store.cache_path
-
- raise WEBrick::HTTPStatus::NotFound,
- "Could not find documentation for \"#{ERB::Util.html_escape(source_name)}\". Please run `gem rdoc --ri gem_name`"
-
- end
- end
-
-end
diff --git a/lib/rdoc/single_class.rb b/lib/rdoc/single_class.rb
deleted file mode 100644
index dd16529648..0000000000
--- a/lib/rdoc/single_class.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-##
-# A singleton class
-
-class RDoc::SingleClass < RDoc::ClassModule
-
- ##
- # Adds the superclass to the included modules.
-
- def ancestors
- superclass ? super + [superclass] : super
- end
-
- def aref_prefix # :nodoc:
- 'sclass'
- end
-
- ##
- # The definition of this singleton class, <tt>class << MyClassName</tt>
-
- def definition
- "class << #{full_name}"
- end
-
- def pretty_print q # :nodoc:
- q.group 2, "[class << #{full_name}", "]" do
- next
- end
- end
-end
diff --git a/lib/rdoc/stats.rb b/lib/rdoc/stats.rb
deleted file mode 100644
index 4817c9c729..0000000000
--- a/lib/rdoc/stats.rb
+++ /dev/null
@@ -1,461 +0,0 @@
-# frozen_string_literal: true
-##
-# RDoc statistics collector which prints a summary and report of a project's
-# documentation totals.
-
-class RDoc::Stats
-
- include RDoc::Text
-
- ##
- # Output level for the coverage report
-
- attr_reader :coverage_level
-
- ##
- # Count of files parsed during parsing
-
- attr_reader :files_so_far
-
- ##
- # Total number of files found
-
- attr_reader :num_files
-
- ##
- # Creates a new Stats that will have +num_files+. +verbosity+ defaults to 1
- # which will create an RDoc::Stats::Normal outputter.
-
- def initialize store, num_files, verbosity = 1
- @num_files = num_files
- @store = store
-
- @coverage_level = 0
- @doc_items = nil
- @files_so_far = 0
- @fully_documented = false
- @num_params = 0
- @percent_doc = nil
- @start = Time.now
- @undoc_params = 0
-
- @display = case verbosity
- when 0 then Quiet.new num_files
- when 1 then Normal.new num_files
- else Verbose.new num_files
- end
- end
-
- ##
- # Records the parsing of an alias +as+.
-
- def add_alias as
- @display.print_alias as
- end
-
- ##
- # Records the parsing of an attribute +attribute+
-
- def add_attribute attribute
- @display.print_attribute attribute
- end
-
- ##
- # Records the parsing of a class +klass+
-
- def add_class klass
- @display.print_class klass
- end
-
- ##
- # Records the parsing of +constant+
-
- def add_constant constant
- @display.print_constant constant
- end
-
- ##
- # Records the parsing of +file+
-
- def add_file(file)
- @files_so_far += 1
- @display.print_file @files_so_far, file
- end
-
- ##
- # Records the parsing of +method+
-
- def add_method(method)
- @display.print_method method
- end
-
- ##
- # Records the parsing of a module +mod+
-
- def add_module(mod)
- @display.print_module mod
- end
-
- ##
- # Call this to mark the beginning of parsing for display purposes
-
- def begin_adding
- @display.begin_adding
- end
-
- ##
- # Calculates documentation totals and percentages for classes, modules,
- # constants, attributes and methods.
-
- def calculate
- return if @doc_items
-
- ucm = @store.unique_classes_and_modules
-
- classes = @store.unique_classes.reject { |cm| cm.full_name == 'Object' }
-
- constants = []
- ucm.each { |cm| constants.concat cm.constants }
-
- methods = []
- ucm.each { |cm| methods.concat cm.method_list }
-
- attributes = []
- ucm.each { |cm| attributes.concat cm.attributes }
-
- @num_attributes, @undoc_attributes = doc_stats attributes
- @num_classes, @undoc_classes = doc_stats classes
- @num_constants, @undoc_constants = doc_stats constants
- @num_methods, @undoc_methods = doc_stats methods
- @num_modules, @undoc_modules = doc_stats @store.unique_modules
-
- @num_items =
- @num_attributes +
- @num_classes +
- @num_constants +
- @num_methods +
- @num_modules +
- @num_params
-
- @undoc_items =
- @undoc_attributes +
- @undoc_classes +
- @undoc_constants +
- @undoc_methods +
- @undoc_modules +
- @undoc_params
-
- @doc_items = @num_items - @undoc_items
- end
-
- ##
- # Sets coverage report level. Accepted values are:
- #
- # false or nil:: No report
- # 0:: Classes, modules, constants, attributes, methods
- # 1:: Level 0 + method parameters
-
- def coverage_level= level
- level = -1 unless level
-
- @coverage_level = level
- end
-
- ##
- # Returns the length and number of undocumented items in +collection+.
-
- def doc_stats collection
- visible = collection.select { |item| item.display? }
- [visible.length, visible.count { |item| not item.documented? }]
- end
-
- ##
- # Call this to mark the end of parsing for display purposes
-
- def done_adding
- @display.done_adding
- end
-
- ##
- # The documentation status of this project. +true+ when 100%, +false+ when
- # less than 100% and +nil+ when unknown.
- #
- # Set by calling #calculate
-
- def fully_documented?
- @fully_documented
- end
-
- ##
- # A report that says you did a great job!
-
- def great_job
- report = RDoc::Markup::Document.new
-
- report << RDoc::Markup::Paragraph.new('100% documentation!')
- report << RDoc::Markup::Paragraph.new('Great Job!')
-
- report
- end
-
- ##
- # Calculates the percentage of items documented.
-
- def percent_doc
- return @percent_doc if @percent_doc
-
- @fully_documented = (@num_items - @doc_items) == 0
-
- @percent_doc = @doc_items.to_f / @num_items * 100 if @num_items.nonzero?
- @percent_doc ||= 0
-
- @percent_doc
- end
-
- ##
- # Returns a report on which items are not documented
-
- def report
- if @coverage_level > 0 then
- extend RDoc::Text
- end
-
- if @coverage_level.zero? then
- calculate
-
- return great_job if @num_items == @doc_items
- end
-
- ucm = @store.unique_classes_and_modules
-
- report = RDoc::Markup::Document.new
- report << RDoc::Markup::Paragraph.new('The following items are not documented:')
- report << RDoc::Markup::BlankLine.new
-
- ucm.sort.each do |cm|
- body = report_class_module(cm) {
- [
- report_constants(cm),
- report_attributes(cm),
- report_methods(cm),
- ].compact
- }
-
- report << body if body
- end
-
- if @coverage_level > 0 then
- calculate
-
- return great_job if @num_items == @doc_items
- end
-
- report
- end
-
- ##
- # Returns a report on undocumented attributes in ClassModule +cm+
-
- def report_attributes cm
- return if cm.attributes.empty?
-
- report = []
-
- cm.each_attribute do |attr|
- next if attr.documented?
- line = attr.line ? ":#{attr.line}" : nil
- report << " #{attr.definition} :#{attr.name} # in file #{attr.file.full_name}#{line}\n"
- report << "\n"
- end
-
- report
- end
-
- ##
- # Returns a report on undocumented items in ClassModule +cm+
-
- def report_class_module cm
- return if cm.fully_documented? and @coverage_level.zero?
- return unless cm.display?
-
- report = RDoc::Markup::Document.new
-
- if cm.in_files.empty? then
- report << RDoc::Markup::Paragraph.new("#{cm.definition} is referenced but empty.")
- report << RDoc::Markup::Paragraph.new("It probably came from another project. I'm sorry I'm holding it against you.")
-
- return report
- elsif cm.documented? then
- documented = true
- klass = RDoc::Markup::Verbatim.new("#{cm.definition} # is documented\n")
- else
- report << RDoc::Markup::Paragraph.new('In files:')
-
- list = RDoc::Markup::List.new :BULLET
-
- cm.in_files.each do |file|
- para = RDoc::Markup::Paragraph.new file.full_name
- list << RDoc::Markup::ListItem.new(nil, para)
- end
-
- report << list
- report << RDoc::Markup::BlankLine.new
-
- klass = RDoc::Markup::Verbatim.new("#{cm.definition}\n")
- end
-
- klass << "\n"
-
- body = yield.flatten # HACK remove #flatten
-
- if body.empty? then
- return if documented
-
- klass.parts.pop
- else
- klass.parts.concat body
- end
-
- klass << "end\n"
-
- report << klass
-
- report
- end
-
- ##
- # Returns a report on undocumented constants in ClassModule +cm+
-
- def report_constants cm
- return if cm.constants.empty?
-
- report = []
-
- cm.each_constant do |constant|
- # TODO constant aliases are listed in the summary but not reported
- # figure out what to do here
- next if constant.documented? || constant.is_alias_for
-
- line = constant.line ? ":#{constant.line}" : line
- report << " # in file #{constant.file.full_name}#{line}\n"
- report << " #{constant.name} = nil\n"
- report << "\n"
- end
-
- report
- end
-
- ##
- # Returns a report on undocumented methods in ClassModule +cm+
-
- def report_methods cm
- return if cm.method_list.empty?
-
- report = []
-
- cm.each_method do |method|
- next if method.documented? and @coverage_level.zero?
-
- if @coverage_level > 0 then
- params, undoc = undoc_params method
-
- @num_params += params
-
- unless undoc.empty? then
- @undoc_params += undoc.length
-
- undoc = undoc.map do |param| "+#{param}+" end
- param_report = " # #{undoc.join ', '} is not documented\n"
- end
- end
-
- next if method.documented? and not param_report
-
- line = method.line ? ":#{method.line}" : nil
- scope = method.singleton ? 'self.' : nil
-
- report << " # in file #{method.file.full_name}#{line}\n"
- report << param_report if param_report
- report << " def #{scope}#{method.name}#{method.params}; end\n"
- report << "\n"
- end
-
- report
- end
-
- ##
- # Returns a summary of the collected statistics.
-
- def summary
- calculate
-
- num_width = [@num_files, @num_items].max.to_s.length
- undoc_width = [
- @undoc_attributes,
- @undoc_classes,
- @undoc_constants,
- @undoc_items,
- @undoc_methods,
- @undoc_modules,
- @undoc_params,
- ].max.to_s.length
-
- report = RDoc::Markup::Verbatim.new
-
- report << "Files: %*d\n" % [num_width, @num_files]
-
- report << "\n"
-
- report << "Classes: %*d (%*d undocumented)\n" % [
- num_width, @num_classes, undoc_width, @undoc_classes]
- report << "Modules: %*d (%*d undocumented)\n" % [
- num_width, @num_modules, undoc_width, @undoc_modules]
- report << "Constants: %*d (%*d undocumented)\n" % [
- num_width, @num_constants, undoc_width, @undoc_constants]
- report << "Attributes: %*d (%*d undocumented)\n" % [
- num_width, @num_attributes, undoc_width, @undoc_attributes]
- report << "Methods: %*d (%*d undocumented)\n" % [
- num_width, @num_methods, undoc_width, @undoc_methods]
- report << "Parameters: %*d (%*d undocumented)\n" % [
- num_width, @num_params, undoc_width, @undoc_params] if
- @coverage_level > 0
-
- report << "\n"
-
- report << "Total: %*d (%*d undocumented)\n" % [
- num_width, @num_items, undoc_width, @undoc_items]
-
- report << "%6.2f%% documented\n" % percent_doc
- report << "\n"
- report << "Elapsed: %0.1fs\n" % (Time.now - @start)
-
- RDoc::Markup::Document.new report
- end
-
- ##
- # Determines which parameters in +method+ were not documented. Returns a
- # total parameter count and an Array of undocumented methods.
-
- def undoc_params method
- @formatter ||= RDoc::Markup::ToTtOnly.new
-
- params = method.param_list
-
- params = params.map { |param| param.gsub(/^\*\*?/, '') }
-
- return 0, [] if params.empty?
-
- document = parse method.comment
-
- tts = document.accept @formatter
-
- undoc = params - tts
-
- [params.length, undoc]
- end
-
- autoload :Quiet, "#{__dir__}/stats/quiet"
- autoload :Normal, "#{__dir__}/stats/normal"
- autoload :Verbose, "#{__dir__}/stats/verbose"
-
-end
diff --git a/lib/rdoc/stats/normal.rb b/lib/rdoc/stats/normal.rb
deleted file mode 100644
index 0a22f0582b..0000000000
--- a/lib/rdoc/stats/normal.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# frozen_string_literal: true
-begin
- require 'io/console/size'
-rescue LoadError
- # for JRuby
- require 'io/console'
-end
-
-##
-# Stats printer that prints just the files being documented with a progress
-# bar
-
-class RDoc::Stats::Normal < RDoc::Stats::Quiet
-
- def begin_adding # :nodoc:
- puts "Parsing sources..."
- @last_width = 0
- end
-
- ##
- # Prints a file with a progress bar
-
- def print_file files_so_far, filename
- progress_bar = sprintf("%3d%% [%2d/%2d] ",
- 100 * files_so_far / @num_files,
- files_so_far,
- @num_files)
-
- if $stdout.tty?
- # Print a progress bar, but make sure it fits on a single line. Filename
- # will be truncated if necessary.
- size = IO.respond_to?(:console_size) ? IO.console_size : IO.console.winsize
- terminal_width = size[1].to_i.nonzero? || 80
- max_filename_size = (terminal_width - progress_bar.size) - 1
-
- if filename.size > max_filename_size then
- # Turn "some_long_filename.rb" to "...ong_filename.rb"
- filename = filename[(filename.size - max_filename_size) .. -1]
- filename[0..2] = "..."
- end
-
- # Clean the line with whitespaces so that leftover output from the
- # previous line doesn't show up.
- $stdout.print("\r\e[K") if @last_width && @last_width > 0
- @last_width = progress_bar.size + filename.size
- term = "\r"
- else
- term = "\n"
- end
- $stdout.print(progress_bar, filename, term)
- $stdout.flush
- end
-
- def done_adding # :nodoc:
- puts
- end
-
-end
diff --git a/lib/rdoc/stats/quiet.rb b/lib/rdoc/stats/quiet.rb
deleted file mode 100644
index 9c98ea5f86..0000000000
--- a/lib/rdoc/stats/quiet.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-# frozen_string_literal: true
-##
-# Stats printer that prints nothing
-
-class RDoc::Stats::Quiet
-
- ##
- # Creates a new Quiet that will print nothing
-
- def initialize num_files
- @num_files = num_files
- end
-
- ##
- # Prints a message at the beginning of parsing
-
- def begin_adding(*) end
-
- ##
- # Prints when an alias is added
-
- def print_alias(*) end
-
- ##
- # Prints when an attribute is added
-
- def print_attribute(*) end
-
- ##
- # Prints when a class is added
-
- def print_class(*) end
-
- ##
- # Prints when a constant is added
-
- def print_constant(*) end
-
- ##
- # Prints when a file is added
-
- def print_file(*) end
-
- ##
- # Prints when a method is added
-
- def print_method(*) end
-
- ##
- # Prints when a module is added
-
- def print_module(*) end
-
- ##
- # Prints when RDoc is done
-
- def done_adding(*) end
-
-end
diff --git a/lib/rdoc/stats/verbose.rb b/lib/rdoc/stats/verbose.rb
deleted file mode 100644
index 7090d561f8..0000000000
--- a/lib/rdoc/stats/verbose.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-##
-# Stats printer that prints everything documented, including the documented
-# status
-
-class RDoc::Stats::Verbose < RDoc::Stats::Normal
-
- ##
- # Returns a marker for RDoc::CodeObject +co+ being undocumented
-
- def nodoc co
- " (undocumented)" unless co.documented?
- end
-
- def print_alias as # :nodoc:
- puts " alias #{as.new_name} #{as.old_name}#{nodoc as}"
- end
-
- def print_attribute attribute # :nodoc:
- puts " #{attribute.definition} #{attribute.name}#{nodoc attribute}"
- end
-
- def print_class(klass) # :nodoc:
- puts " class #{klass.full_name}#{nodoc klass}"
- end
-
- def print_constant(constant) # :nodoc:
- puts " #{constant.name}#{nodoc constant}"
- end
-
- def print_file(files_so_far, file) # :nodoc:
- super
- puts
- end
-
- def print_method(method) # :nodoc:
- puts " #{method.singleton ? '::' : '#'}#{method.name}#{nodoc method}"
- end
-
- def print_module(mod) # :nodoc:
- puts " module #{mod.full_name}#{nodoc mod}"
- end
-
-end
diff --git a/lib/rdoc/store.rb b/lib/rdoc/store.rb
deleted file mode 100644
index cd27d47dd1..0000000000
--- a/lib/rdoc/store.rb
+++ /dev/null
@@ -1,989 +0,0 @@
-# frozen_string_literal: true
-require 'fileutils'
-
-##
-# A set of rdoc data for a single project (gem, path, etc.).
-#
-# The store manages reading and writing ri data for a project and maintains a
-# cache of methods, classes and ancestors in the store.
-#
-# The store maintains a #cache of its contents for faster lookup. After
-# adding items to the store it must be flushed using #save_cache. The cache
-# contains the following structures:
-#
-# @cache = {
-# :ancestors => {}, # class name => ancestor names
-# :attributes => {}, # class name => attributes
-# :class_methods => {}, # class name => class methods
-# :instance_methods => {}, # class name => instance methods
-# :modules => [], # classes and modules in this store
-# :pages => [], # page names
-# }
-#--
-# TODO need to prune classes
-
-class RDoc::Store
-
- ##
- # Errors raised from loading or saving the store
-
- class Error < RDoc::Error
- end
-
- ##
- # Raised when a stored file for a class, module, page or method is missing.
-
- class MissingFileError < Error
-
- ##
- # The store the file should exist in
-
- attr_reader :store
-
- ##
- # The file the #name should be saved as
-
- attr_reader :file
-
- ##
- # The name of the object the #file would be loaded from
-
- attr_reader :name
-
- ##
- # Creates a new MissingFileError for the missing +file+ for the given
- # +name+ that should have been in the +store+.
-
- def initialize store, file, name
- @store = store
- @file = file
- @name = name
- end
-
- def message # :nodoc:
- "store at #{@store.path} missing file #{@file} for #{@name}"
- end
-
- end
-
- ##
- # Stores the name of the C variable a class belongs to. This helps wire up
- # classes defined from C across files.
-
- attr_reader :c_enclosure_classes # :nodoc:
-
- attr_reader :c_enclosure_names # :nodoc:
-
- ##
- # Maps C variables to class or module names for each parsed C file.
-
- attr_reader :c_class_variables
-
- ##
- # Maps C variables to singleton class names for each parsed C file.
-
- attr_reader :c_singleton_class_variables
-
- ##
- # If true this Store will not write any files
-
- attr_accessor :dry_run
-
- ##
- # Path this store reads or writes
-
- attr_accessor :path
-
- ##
- # The RDoc::RDoc driver for this parse tree. This allows classes consulting
- # the documentation tree to access user-set options, for example.
-
- attr_accessor :rdoc
-
- ##
- # Type of ri datastore this was loaded from. See RDoc::RI::Driver,
- # RDoc::RI::Paths.
-
- attr_accessor :type
-
- ##
- # The contents of the Store
-
- attr_reader :cache
-
- ##
- # The encoding of the contents in the Store
-
- attr_accessor :encoding
-
- ##
- # The lazy constants alias will be discovered in passing
-
- attr_reader :unmatched_constant_alias
-
- ##
- # Creates a new Store of +type+ that will load or save to +path+
-
- def initialize path = nil, type = nil
- @dry_run = false
- @encoding = nil
- @path = path
- @rdoc = nil
- @type = type
-
- @cache = {
- :ancestors => {},
- :attributes => {},
- :class_methods => {},
- :c_class_variables => {},
- :c_singleton_class_variables => {},
- :encoding => @encoding,
- :instance_methods => {},
- :main => nil,
- :modules => [],
- :pages => [],
- :title => nil,
- }
-
- @classes_hash = {}
- @modules_hash = {}
- @files_hash = {}
- @text_files_hash = {}
-
- @c_enclosure_classes = {}
- @c_enclosure_names = {}
-
- @c_class_variables = {}
- @c_singleton_class_variables = {}
-
- @unique_classes = nil
- @unique_modules = nil
-
- @unmatched_constant_alias = {}
- end
-
- ##
- # Adds +module+ as an enclosure (namespace) for the given +variable+ for C
- # files.
-
- def add_c_enclosure variable, namespace
- @c_enclosure_classes[variable] = namespace
- end
-
- ##
- # Adds C variables from an RDoc::Parser::C
-
- def add_c_variables c_parser
- filename = c_parser.top_level.relative_name
-
- @c_class_variables[filename] = make_variable_map c_parser.classes
-
- @c_singleton_class_variables[filename] = c_parser.singleton_classes
- end
-
- ##
- # Adds the file with +name+ as an RDoc::TopLevel to the store. Returns the
- # created RDoc::TopLevel.
-
- def add_file absolute_name, relative_name: absolute_name, parser: nil
- unless top_level = @files_hash[relative_name] then
- top_level = RDoc::TopLevel.new absolute_name, relative_name
- top_level.parser = parser if parser
- top_level.store = self
- @files_hash[relative_name] = top_level
- @text_files_hash[relative_name] = top_level if top_level.text?
- end
-
- top_level
- end
-
- ##
- # Sets the parser of +absolute_name+, unless it from a source code file.
-
- def update_parser_of_file(absolute_name, parser)
- if top_level = @files_hash[absolute_name] then
- @text_files_hash[absolute_name] = top_level if top_level.text?
- end
- end
-
- ##
- # Returns all classes discovered by RDoc
-
- def all_classes
- @classes_hash.values
- end
-
- ##
- # Returns all classes and modules discovered by RDoc
-
- def all_classes_and_modules
- @classes_hash.values + @modules_hash.values
- end
-
- ##
- # All TopLevels known to RDoc
-
- def all_files
- @files_hash.values
- end
-
- ##
- # Returns all modules discovered by RDoc
-
- def all_modules
- modules_hash.values
- end
-
- ##
- # Ancestors cache accessor. Maps a klass name to an Array of its ancestors
- # in this store. If Foo in this store inherits from Object, Kernel won't be
- # listed (it will be included from ruby's ri store).
-
- def ancestors
- @cache[:ancestors]
- end
-
- ##
- # Attributes cache accessor. Maps a class to an Array of its attributes.
-
- def attributes
- @cache[:attributes]
- end
-
- ##
- # Path to the cache file
-
- def cache_path
- File.join @path, 'cache.ri'
- end
-
- ##
- # Path to the ri data for +klass_name+
-
- def class_file klass_name
- name = klass_name.split('::').last
- File.join class_path(klass_name), "cdesc-#{name}.ri"
- end
-
- ##
- # Class methods cache accessor. Maps a class to an Array of its class
- # methods (not full name).
-
- def class_methods
- @cache[:class_methods]
- end
-
- ##
- # Path where data for +klass_name+ will be stored (methods or class data)
-
- def class_path klass_name
- File.join @path, *klass_name.split('::')
- end
-
- ##
- # Hash of all classes known to RDoc
-
- def classes_hash
- @classes_hash
- end
-
- ##
- # Removes empty items and ensures item in each collection are unique and
- # sorted
-
- def clean_cache_collection collection # :nodoc:
- collection.each do |name, item|
- if item.empty? then
- collection.delete name
- else
- # HACK mongrel-1.1.5 documents its files twice
- item.uniq!
- item.sort!
- end
- end
- end
-
- ##
- # Prepares the RDoc code object tree for use by a generator.
- #
- # It finds unique classes/modules defined, and replaces classes/modules that
- # are aliases for another one by a copy with RDoc::ClassModule#is_alias_for
- # set.
- #
- # It updates the RDoc::ClassModule#constant_aliases attribute of "real"
- # classes or modules.
- #
- # It also completely removes the classes and modules that should be removed
- # from the documentation and the methods that have a visibility below
- # +min_visibility+, which is the <tt>--visibility</tt> option.
- #
- # See also RDoc::Context#remove_from_documentation?
-
- def complete min_visibility
- fix_basic_object_inheritance
-
- # cache included modules before they are removed from the documentation
- all_classes_and_modules.each { |cm| cm.ancestors }
-
- unless min_visibility == :nodoc then
- remove_nodoc @classes_hash
- remove_nodoc @modules_hash
- end
-
- @unique_classes = find_unique @classes_hash
- @unique_modules = find_unique @modules_hash
-
- unique_classes_and_modules.each do |cm|
- cm.complete min_visibility
- end
-
- @files_hash.each_key do |file_name|
- tl = @files_hash[file_name]
-
- unless tl.text? then
- tl.modules_hash.clear
- tl.classes_hash.clear
-
- tl.classes_or_modules.each do |cm|
- name = cm.full_name
- if cm.type == 'class' then
- tl.classes_hash[name] = cm if @classes_hash[name]
- else
- tl.modules_hash[name] = cm if @modules_hash[name]
- end
- end
- end
- end
- end
-
- ##
- # Hash of all files known to RDoc
-
- def files_hash
- @files_hash
- end
-
- ##
- # Finds the enclosure (namespace) for the given C +variable+.
-
- def find_c_enclosure variable
- @c_enclosure_classes.fetch variable do
- break unless name = @c_enclosure_names[variable]
-
- mod = find_class_or_module name
-
- unless mod then
- loaded_mod = load_class_data name
-
- file = loaded_mod.in_files.first
-
- return unless file # legacy data source
-
- file.store = self
-
- mod = file.add_module RDoc::NormalModule, name
- end
-
- @c_enclosure_classes[variable] = mod
- end
- end
-
- ##
- # Finds the class with +name+ in all discovered classes
-
- def find_class_named name
- @classes_hash[name]
- end
-
- ##
- # Finds the class with +name+ starting in namespace +from+
-
- def find_class_named_from name, from
- from = find_class_named from unless RDoc::Context === from
-
- until RDoc::TopLevel === from do
- return nil unless from
-
- klass = from.find_class_named name
- return klass if klass
-
- from = from.parent
- end
-
- find_class_named name
- end
-
- ##
- # Finds the class or module with +name+
-
- def find_class_or_module name
- name = $' if name =~ /^::/
- @classes_hash[name] || @modules_hash[name]
- end
-
- ##
- # Finds the file with +name+ in all discovered files
-
- def find_file_named name
- @files_hash[name]
- end
-
- ##
- # Finds the module with +name+ in all discovered modules
-
- def find_module_named name
- @modules_hash[name]
- end
-
- ##
- # Returns the RDoc::TopLevel that is a text file and has the given
- # +file_name+
-
- def find_text_page file_name
- @text_files_hash.each_value.find do |file|
- file.full_name == file_name
- end
- end
-
- ##
- # Finds unique classes/modules defined in +all_hash+,
- # and returns them as an array. Performs the alias
- # updates in +all_hash+: see ::complete.
- #--
- # TODO aliases should be registered by Context#add_module_alias
-
- def find_unique all_hash
- unique = []
-
- all_hash.each_pair do |full_name, cm|
- unique << cm if full_name == cm.full_name
- end
-
- unique
- end
-
- ##
- # Fixes the erroneous <tt>BasicObject < Object</tt> in 1.9.
- #
- # Because we assumed all classes without a stated superclass
- # inherit from Object, we have the above wrong inheritance.
- #
- # We fix BasicObject right away if we are running in a Ruby
- # version >= 1.9.
-
- def fix_basic_object_inheritance
- basic = classes_hash['BasicObject']
- return unless basic
- basic.superclass = nil
- end
-
- ##
- # Friendly rendition of #path
-
- def friendly_path
- case type
- when :gem then
- parent = File.expand_path '..', @path
- "gem #{File.basename parent}"
- when :home then RDoc.home
- when :site then 'ruby site'
- when :system then 'ruby core'
- else @path
- end
- end
-
- def inspect # :nodoc:
- "#<%s:0x%x %s %p>" % [self.class, object_id, @path, module_names.sort]
- end
-
- ##
- # Instance methods cache accessor. Maps a class to an Array of its
- # instance methods (not full name).
-
- def instance_methods
- @cache[:instance_methods]
- end
-
- ##
- # Loads all items from this store into memory. This recreates a
- # documentation tree for use by a generator
-
- def load_all
- load_cache
-
- module_names.each do |module_name|
- mod = find_class_or_module(module_name) || load_class(module_name)
-
- # load method documentation since the loaded class/module does not have
- # it
- loaded_methods = mod.method_list.map do |method|
- load_method module_name, method.full_name
- end
-
- mod.method_list.replace loaded_methods
-
- loaded_attributes = mod.attributes.map do |attribute|
- load_method module_name, attribute.full_name
- end
-
- mod.attributes.replace loaded_attributes
- end
-
- all_classes_and_modules.each do |mod|
- descendent_re = /^#{mod.full_name}::[^:]+$/
-
- module_names.each do |name|
- next unless name =~ descendent_re
-
- descendent = find_class_or_module name
-
- case descendent
- when RDoc::NormalClass then
- mod.classes_hash[name] = descendent
- when RDoc::NormalModule then
- mod.modules_hash[name] = descendent
- end
- end
- end
-
- @cache[:pages].each do |page_name|
- page = load_page page_name
- @files_hash[page_name] = page
- @text_files_hash[page_name] = page if page.text?
- end
- end
-
- ##
- # Loads cache file for this store
-
- def load_cache
- #orig_enc = @encoding
-
- @cache = marshal_load(cache_path)
-
- load_enc = @cache[:encoding]
-
- # TODO this feature will be time-consuming to add:
- # a) Encodings may be incompatible but transcodeable
- # b) Need to warn in the appropriate spots, wherever they may be
- # c) Need to handle cross-cache differences in encodings
- # d) Need to warn when generating into a cache with different encodings
- #
- #if orig_enc and load_enc != orig_enc then
- # warn "Cached encoding #{load_enc} is incompatible with #{orig_enc}\n" \
- # "from #{path}/cache.ri" unless
- # Encoding.compatible? orig_enc, load_enc
- #end
-
- @encoding = load_enc unless @encoding
-
- @cache[:pages] ||= []
- @cache[:main] ||= nil
- @cache[:c_class_variables] ||= {}
- @cache[:c_singleton_class_variables] ||= {}
-
- @cache[:c_class_variables].each do |_, map|
- map.each do |variable, name|
- @c_enclosure_names[variable] = name
- end
- end
-
- @cache
- rescue Errno::ENOENT
- end
-
- ##
- # Loads ri data for +klass_name+ and hooks it up to this store.
-
- def load_class klass_name
- obj = load_class_data klass_name
-
- obj.store = self
-
- case obj
- when RDoc::NormalClass then
- @classes_hash[klass_name] = obj
- when RDoc::SingleClass then
- @classes_hash[klass_name] = obj
- when RDoc::NormalModule then
- @modules_hash[klass_name] = obj
- end
- end
-
- ##
- # Loads ri data for +klass_name+
-
- def load_class_data klass_name
- file = class_file klass_name
-
- marshal_load(file)
- rescue Errno::ENOENT => e
- error = MissingFileError.new(self, file, klass_name)
- error.set_backtrace e.backtrace
- raise error
- end
-
- ##
- # Loads ri data for +method_name+ in +klass_name+
-
- def load_method klass_name, method_name
- file = method_file klass_name, method_name
-
- obj = marshal_load(file)
- obj.store = self
- obj.parent ||= find_class_or_module(klass_name) || load_class(klass_name)
- obj
- rescue Errno::ENOENT => e
- error = MissingFileError.new(self, file, klass_name + method_name)
- error.set_backtrace e.backtrace
- raise error
- end
-
- ##
- # Loads ri data for +page_name+
-
- def load_page page_name
- file = page_file page_name
-
- obj = marshal_load(file)
- obj.store = self
- obj
- rescue Errno::ENOENT => e
- error = MissingFileError.new(self, file, page_name)
- error.set_backtrace e.backtrace
- raise error
- end
-
- ##
- # Gets the main page for this RDoc store. This page is used as the root of
- # the RDoc server.
-
- def main
- @cache[:main]
- end
-
- ##
- # Sets the main page for this RDoc store.
-
- def main= page
- @cache[:main] = page
- end
-
- ##
- # Converts the variable => ClassModule map +variables+ from a C parser into
- # a variable => class name map.
-
- def make_variable_map variables
- map = {}
-
- variables.each { |variable, class_module|
- map[variable] = class_module.full_name
- }
-
- map
- end
-
- ##
- # Path to the ri data for +method_name+ in +klass_name+
-
- def method_file klass_name, method_name
- method_name = method_name.split('::').last
- method_name =~ /#(.*)/
- method_type = $1 ? 'i' : 'c'
- method_name = $1 if $1
- method_name = method_name.gsub(/\W/) { "%%%02x" % $&[0].ord }
-
- File.join class_path(klass_name), "#{method_name}-#{method_type}.ri"
- end
-
- ##
- # Modules cache accessor. An Array of all the module (and class) names in
- # the store.
-
- def module_names
- @cache[:modules]
- end
-
- ##
- # Hash of all modules known to RDoc
-
- def modules_hash
- @modules_hash
- end
-
- ##
- # Returns the RDoc::TopLevel that is a text file and has the given +name+
-
- def page name
- @text_files_hash.each_value.find do |file|
- file.page_name == name or file.base_name == name
- end
- end
-
- ##
- # Path to the ri data for +page_name+
-
- def page_file page_name
- file_name = File.basename(page_name).gsub('.', '_')
-
- File.join @path, File.dirname(page_name), "page-#{file_name}.ri"
- end
-
- ##
- # Removes from +all_hash+ the contexts that are nodoc or have no content.
- #
- # See RDoc::Context#remove_from_documentation?
-
- def remove_nodoc all_hash
- all_hash.keys.each do |name|
- context = all_hash[name]
- all_hash.delete(name) if context.remove_from_documentation?
- end
- end
-
- ##
- # Saves all entries in the store
-
- def save
- load_cache
-
- all_classes_and_modules.each do |klass|
- save_class klass
-
- klass.each_method do |method|
- save_method klass, method
- end
-
- klass.each_attribute do |attribute|
- save_method klass, attribute
- end
- end
-
- all_files.each do |file|
- save_page file
- end
-
- save_cache
- end
-
- ##
- # Writes the cache file for this store
-
- def save_cache
- clean_cache_collection @cache[:ancestors]
- clean_cache_collection @cache[:attributes]
- clean_cache_collection @cache[:class_methods]
- clean_cache_collection @cache[:instance_methods]
-
- @cache[:modules].uniq!
- @cache[:modules].sort!
-
- @cache[:pages].uniq!
- @cache[:pages].sort!
-
- @cache[:encoding] = @encoding # this gets set twice due to assert_cache
-
- @cache[:c_class_variables].merge! @c_class_variables
- @cache[:c_singleton_class_variables].merge! @c_singleton_class_variables
-
- return if @dry_run
-
- File.open cache_path, 'wb' do |io|
- Marshal.dump @cache, io
- end
- end
-
- ##
- # Writes the ri data for +klass+ (or module)
-
- def save_class klass
- full_name = klass.full_name
-
- FileUtils.mkdir_p class_path(full_name) unless @dry_run
-
- @cache[:modules] << full_name
-
- path = class_file full_name
-
- begin
- disk_klass = load_class full_name
-
- klass = disk_klass.merge klass
- rescue MissingFileError
- end
-
- # BasicObject has no ancestors
- ancestors = klass.direct_ancestors.compact.map do |ancestor|
- # HACK for classes we don't know about (class X < RuntimeError)
- String === ancestor ? ancestor : ancestor.full_name
- end
-
- @cache[:ancestors][full_name] ||= []
- @cache[:ancestors][full_name].concat ancestors
-
- attribute_definitions = klass.attributes.map do |attribute|
- "#{attribute.definition} #{attribute.name}"
- end
-
- unless attribute_definitions.empty? then
- @cache[:attributes][full_name] ||= []
- @cache[:attributes][full_name].concat attribute_definitions
- end
-
- to_delete = []
-
- unless klass.method_list.empty? then
- @cache[:class_methods][full_name] ||= []
- @cache[:instance_methods][full_name] ||= []
-
- class_methods, instance_methods =
- klass.method_list.partition { |meth| meth.singleton }
-
- class_methods = class_methods. map { |method| method.name }
- instance_methods = instance_methods.map { |method| method.name }
- attribute_names = klass.attributes.map { |attr| attr.name }
-
- old = @cache[:class_methods][full_name] - class_methods
- to_delete.concat old.map { |method|
- method_file full_name, "#{full_name}::#{method}"
- }
-
- old = @cache[:instance_methods][full_name] -
- instance_methods - attribute_names
- to_delete.concat old.map { |method|
- method_file full_name, "#{full_name}##{method}"
- }
-
- @cache[:class_methods][full_name] = class_methods
- @cache[:instance_methods][full_name] = instance_methods
- end
-
- return if @dry_run
-
- FileUtils.rm_f to_delete
-
- File.open path, 'wb' do |io|
- Marshal.dump klass, io
- end
- end
-
- ##
- # Writes the ri data for +method+ on +klass+
-
- def save_method klass, method
- full_name = klass.full_name
-
- FileUtils.mkdir_p class_path(full_name) unless @dry_run
-
- cache = if method.singleton then
- @cache[:class_methods]
- else
- @cache[:instance_methods]
- end
- cache[full_name] ||= []
- cache[full_name] << method.name
-
- return if @dry_run
-
- File.open method_file(full_name, method.full_name), 'wb' do |io|
- Marshal.dump method, io
- end
- end
-
- ##
- # Writes the ri data for +page+
-
- def save_page page
- return unless page.text?
-
- path = page_file page.full_name
-
- FileUtils.mkdir_p File.dirname(path) unless @dry_run
-
- cache[:pages] ||= []
- cache[:pages] << page.full_name
-
- return if @dry_run
-
- File.open path, 'wb' do |io|
- Marshal.dump page, io
- end
- end
-
- ##
- # Source of the contents of this store.
- #
- # For a store from a gem the source is the gem name. For a store from the
- # home directory the source is "home". For system ri store (the standard
- # library documentation) the source is"ruby". For a store from the site
- # ri directory the store is "site". For other stores the source is the
- # #path.
-
- def source
- case type
- when :gem then File.basename File.expand_path '..', @path
- when :home then 'home'
- when :site then 'site'
- when :system then 'ruby'
- else @path
- end
- end
-
- ##
- # Gets the title for this RDoc store. This is used as the title in each
- # page on the RDoc server
-
- def title
- @cache[:title]
- end
-
- ##
- # Sets the title page for this RDoc store.
-
- def title= title
- @cache[:title] = title
- end
-
- ##
- # Returns the unique classes discovered by RDoc.
- #
- # ::complete must have been called prior to using this method.
-
- def unique_classes
- @unique_classes
- end
-
- ##
- # Returns the unique classes and modules discovered by RDoc.
- # ::complete must have been called prior to using this method.
-
- def unique_classes_and_modules
- @unique_classes + @unique_modules
- end
-
- ##
- # Returns the unique modules discovered by RDoc.
- # ::complete must have been called prior to using this method.
-
- def unique_modules
- @unique_modules
- end
-
- private
- def marshal_load(file)
- File.open(file, 'rb') {|io| Marshal.load(io, MarshalFilter)}
- end
-
- MarshalFilter = proc do |obj|
- case obj
- when true, false, nil, Array, Class, Encoding, Hash, Integer, String, Symbol, RDoc::Text
- else
- unless obj.class.name.start_with?("RDoc::")
- raise TypeError, "not permitted class: #{obj.class.name}"
- end
- end
- obj
- end
- private_constant :MarshalFilter
-
-end
diff --git a/lib/rdoc/task.rb b/lib/rdoc/task.rb
deleted file mode 100644
index eb584c9d2a..0000000000
--- a/lib/rdoc/task.rb
+++ /dev/null
@@ -1,355 +0,0 @@
-# frozen_string_literal: true
-#--
-# Copyright (c) 2003, 2004 Jim Weirich, 2009 Eric Hodel
-#
-# 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.
-#++
-
-begin
- gem 'rdoc'
-rescue Gem::LoadError
-end unless defined?(RDoc)
-
-begin
- gem 'rake'
-rescue Gem::LoadError
-end unless defined?(Rake)
-
-require_relative '../rdoc'
-require 'rake'
-require 'rake/tasklib'
-
-##
-# RDoc::Task creates the following rake tasks to generate and clean up RDoc
-# output:
-#
-# [rdoc]
-# Main task for this RDoc task.
-#
-# [clobber_rdoc]
-# Delete all the rdoc files. This target is automatically added to the main
-# clobber target.
-#
-# [rerdoc]
-# Rebuild the rdoc files from scratch, even if they are not out of date.
-#
-# [rdoc:coverage]
-# Print RDoc coverage report for all rdoc files.
-#
-# Simple Example:
-#
-# require 'rdoc/task'
-#
-# RDoc::Task.new do |rdoc|
-# rdoc.main = "README.rdoc"
-# rdoc.rdoc_files.include("README.rdoc", "lib/**/*.rb")
-# end
-#
-# The +rdoc+ object passed to the block is an RDoc::Task object. See the
-# attributes list for the RDoc::Task class for available customization options.
-#
-# == Specifying different task names
-#
-# You may wish to give the task a different name, such as if you are
-# generating two sets of documentation. For instance, if you want to have a
-# development set of documentation including private methods:
-#
-# require 'rdoc/task'
-#
-# RDoc::Task.new :rdoc_dev do |rdoc|
-# rdoc.main = "README.rdoc"
-# rdoc.rdoc_files.include("README.rdoc", "lib/**/*.rb")
-# rdoc.options << "--all"
-# end
-#
-# The tasks would then be named :<em>rdoc_dev</em>,
-# :clobber_<em>rdoc_dev</em>, and :re<em>rdoc_dev</em>.
-#
-# If you wish to have completely different task names, then pass a Hash as
-# first argument. With the <tt>:rdoc</tt>, <tt>:clobber_rdoc</tt> and
-# <tt>:rerdoc</tt> options, you can customize the task names to your liking.
-#
-# For example:
-#
-# require 'rdoc/task'
-#
-# RDoc::Task.new(:rdoc => "rdoc", :clobber_rdoc => "rdoc:clean",
-# :rerdoc => "rdoc:force")
-#
-# This will create the tasks <tt>:rdoc</tt>, <tt>:rdoc:clean</tt>,
-# <tt>:rdoc:force</tt>, and <tt>:rdoc:coverage</tt>.
-
-class RDoc::Task < Rake::TaskLib
-
- ##
- # Name of the main, top level task. (default is :rdoc)
-
- attr_accessor :name
-
- ##
- # Comment markup format. rdoc, rd and tomdoc are supported. (default is
- # 'rdoc')
-
- attr_accessor :markup
-
- ##
- # Name of directory to receive the html output files. (default is "html")
-
- attr_accessor :rdoc_dir
-
- ##
- # Title of RDoc documentation. (defaults to rdoc's default)
-
- attr_accessor :title
-
- ##
- # Name of file to be used as the main, top level file of the RDoc. (default
- # is none)
-
- attr_accessor :main
-
- ##
- # Name of template to be used by rdoc. (defaults to rdoc's default)
-
- attr_accessor :template
-
- ##
- # Name of format generator (<tt>--format</tt>) used by rdoc. (defaults to
- # rdoc's default)
-
- attr_accessor :generator
-
- ##
- # List of files to be included in the rdoc generation. (default is [])
-
- attr_accessor :rdoc_files
-
- ##
- # Additional list of options to be passed rdoc. (default is [])
-
- attr_accessor :options
-
- ##
- # Whether to run the rdoc process as an external shell (default is false)
-
- attr_accessor :external
-
- ##
- # Create an RDoc task with the given name. See the RDoc::Task class overview
- # for documentation.
-
- def initialize name = :rdoc # :yield: self
- defaults
-
- check_names name
-
- @name = name
-
- yield self if block_given?
-
- define
- end
-
- ##
- # Ensures that +names+ only includes names for the :rdoc, :clobber_rdoc and
- # :rerdoc. If other names are given an ArgumentError is raised.
-
- def check_names names
- return unless Hash === names
-
- invalid_options =
- names.keys.map { |k| k.to_sym } - [:rdoc, :clobber_rdoc, :rerdoc]
-
- unless invalid_options.empty? then
- raise ArgumentError, "invalid options: #{invalid_options.join ', '}"
- end
- end
-
- ##
- # Task description for the clobber rdoc task or its renamed equivalent
-
- def clobber_task_description
- "Remove RDoc HTML files"
- end
-
- ##
- # Sets default task values
-
- def defaults
- @name = :rdoc
- @rdoc_files = Rake::FileList.new
- @rdoc_dir = 'html'
- @main = nil
- @title = nil
- @template = nil
- @generator = nil
- @options = []
- end
-
- ##
- # All source is inline now. This method is deprecated
-
- def inline_source # :nodoc:
- warn "RDoc::Task#inline_source is deprecated"
- true
- end
-
- ##
- # All source is inline now. This method is deprecated
-
- def inline_source=(value) # :nodoc:
- warn "RDoc::Task#inline_source is deprecated"
- end
-
- ##
- # Create the tasks defined by this task lib.
-
- def define
- desc rdoc_task_description
- task rdoc_task_name
-
- desc rerdoc_task_description
- task rerdoc_task_name => [clobber_task_name, rdoc_task_name]
-
- desc clobber_task_description
- task clobber_task_name do
- rm_r @rdoc_dir rescue nil
- end
-
- task :clobber => [clobber_task_name]
-
- directory @rdoc_dir
-
- rdoc_target_deps = [
- @rdoc_files,
- Rake.application.rakefile
- ].flatten.compact
-
- task rdoc_task_name => [rdoc_target]
- file rdoc_target => rdoc_target_deps do
- @before_running_rdoc.call if @before_running_rdoc
- args = option_list + @rdoc_files
-
- $stderr.puts "rdoc #{args.join ' '}" if Rake.application.options.trace
- RDoc::RDoc.new.document args
- end
-
- namespace rdoc_task_name do
- desc coverage_task_description
- task coverage_task_name do
- @before_running_rdoc.call if @before_running_rdoc
- opts = option_list << "-C"
- args = opts + @rdoc_files
-
- $stderr.puts "rdoc #{args.join ' '}" if Rake.application.options.trace
- RDoc::RDoc.new.document args
- end
- end
-
- self
- end
-
- ##
- # List of options that will be supplied to RDoc
-
- def option_list
- result = @options.dup
- result << "-o" << @rdoc_dir
- result << "--main" << main if main
- result << "--markup" << markup if markup
- result << "--title" << title if title
- result << "-T" << template if template
- result << '-f' << generator if generator
- result
- end
-
- ##
- # The block passed to this method will be called just before running the
- # RDoc generator. It is allowed to modify RDoc::Task attributes inside the
- # block.
-
- def before_running_rdoc(&block)
- @before_running_rdoc = block
- end
-
- ##
- # Task description for the rdoc task or its renamed equivalent
-
- def rdoc_task_description
- 'Build RDoc HTML files'
- end
-
- ##
- # Task description for the rerdoc task or its renamed description
-
- def rerdoc_task_description
- "Rebuild RDoc HTML files"
- end
-
- ##
- # Task description for the coverage task or its renamed description
-
- def coverage_task_description
- "Print RDoc coverage report"
- end
-
- private
-
- def rdoc_target
- "#{rdoc_dir}/created.rid"
- end
-
- def rdoc_task_name
- case name
- when Hash then (name[:rdoc] || "rdoc").to_s
- else name.to_s
- end
- end
-
- def clobber_task_name
- case name
- when Hash then (name[:clobber_rdoc] || "clobber_rdoc").to_s
- else "clobber_#{name}"
- end
- end
-
- def rerdoc_task_name
- case name
- when Hash then (name[:rerdoc] || "rerdoc").to_s
- else "re#{name}"
- end
- end
-
- def coverage_task_name
- "coverage"
- end
-
-end
-
-# :stopdoc:
-module Rake
-
- ##
- # For backwards compatibility
-
- RDocTask = RDoc::Task # :nodoc:
-
-end
-# :startdoc:
diff --git a/lib/rdoc/text.rb b/lib/rdoc/text.rb
deleted file mode 100644
index 9804f81abe..0000000000
--- a/lib/rdoc/text.rb
+++ /dev/null
@@ -1,322 +0,0 @@
-# frozen_string_literal: true
-
-##
-# For RDoc::Text#to_html
-
-require 'strscan'
-
-##
-# Methods for manipulating comment text
-
-module RDoc::Text
-
- ##
- # The language for this text. This affects stripping comments
- # markers.
-
- attr_accessor :language
-
- ##
- # Maps markup formats to classes that can parse them. If the format is
- # unknown, "rdoc" format is used.
-
- MARKUP_FORMAT = {
- 'markdown' => RDoc::Markdown,
- 'rdoc' => RDoc::Markup,
- 'rd' => RDoc::RD,
- 'tomdoc' => RDoc::TomDoc,
- }
-
- MARKUP_FORMAT.default = RDoc::Markup
-
- ##
- # Maps an encoding to a Hash of characters properly transcoded for that
- # encoding.
- #
- # See also encode_fallback.
-
- TO_HTML_CHARACTERS = Hash.new do |h, encoding|
- h[encoding] = {
- :close_dquote => encode_fallback('”', encoding, '"'),
- :close_squote => encode_fallback('’', encoding, '\''),
- :copyright => encode_fallback('©', encoding, '(c)'),
- :ellipsis => encode_fallback('…', encoding, '...'),
- :em_dash => encode_fallback('—', encoding, '---'),
- :en_dash => encode_fallback('–', encoding, '--'),
- :open_dquote => encode_fallback('“', encoding, '"'),
- :open_squote => encode_fallback('‘', encoding, '\''),
- :trademark => encode_fallback('®', encoding, '(r)'),
- }
- end
-
- ##
- # Transcodes +character+ to +encoding+ with a +fallback+ character.
-
- def self.encode_fallback character, encoding, fallback
- character.encode(encoding, :fallback => { character => fallback },
- :undef => :replace, :replace => fallback)
- end
-
- ##
- # Expands tab characters in +text+ to eight spaces
-
- def expand_tabs text
- expanded = []
-
- text.each_line do |line|
- nil while line.gsub!(/(?:\G|\r)((?:.{8})*?)([^\t\r\n]{0,7})\t/) do
- r = "#{$1}#{$2}#{' ' * (8 - $2.size)}"
- r = RDoc::Encoding.change_encoding r, text.encoding
- r
- end
-
- expanded << line
- end
-
- expanded.join
- end
-
- ##
- # Flush +text+ left based on the shortest line
-
- def flush_left text
- indent = 9999
-
- text.each_line do |line|
- line_indent = line =~ /\S/ || 9999
- indent = line_indent if indent > line_indent
- end
-
- empty = ''
- empty = RDoc::Encoding.change_encoding empty, text.encoding
-
- text.gsub(/^ {0,#{indent}}/, empty)
- end
-
- ##
- # Convert a string in markup format into HTML.
- #
- # Requires the including class to implement #formatter
-
- def markup text
- if @store.rdoc.options
- locale = @store.rdoc.options.locale
- else
- locale = nil
- end
- if locale
- i18n_text = RDoc::I18n::Text.new(text)
- text = i18n_text.translate(locale)
- end
- parse(text).accept formatter
- end
-
- ##
- # Strips hashes, expands tabs then flushes +text+ to the left
-
- def normalize_comment text
- return text if text.empty?
-
- case language
- when :ruby
- text = strip_hashes text
- when :c
- text = strip_stars text
- end
- text = expand_tabs text
- text = flush_left text
- text = strip_newlines text
- text
- end
-
- ##
- # Normalizes +text+ then builds a RDoc::Markup::Document from it
-
- def parse text, format = 'rdoc'
- return text if RDoc::Markup::Document === text
- return text.parse if RDoc::Comment === text
-
- text = normalize_comment text # TODO remove, should not be necessary
-
- return RDoc::Markup::Document.new if text =~ /\A\n*\z/
-
- MARKUP_FORMAT[format].parse text
- end
-
- ##
- # The first +limit+ characters of +text+ as HTML
-
- def snippet text, limit = 100
- document = parse text
-
- RDoc::Markup::ToHtmlSnippet.new(options, limit).convert document
- end
-
- ##
- # Strips leading # characters from +text+
-
- def strip_hashes text
- return text if text =~ /^(?>\s*)[^\#]/
-
- empty = ''
- empty = RDoc::Encoding.change_encoding empty, text.encoding
-
- text.gsub(/^\s*(#+)/) { $1.tr '#', ' ' }.gsub(/^\s+$/, empty)
- end
-
- ##
- # Strips leading and trailing \n characters from +text+
-
- def strip_newlines text
- text.gsub(/\A\n*(.*?)\n*\z/m) do $1 end # block preserves String encoding
- end
-
- ##
- # Strips /* */ style comments
-
- def strip_stars text
- return text unless text =~ %r%/\*.*\*/%m
-
- encoding = text.encoding
-
- text = text.gsub %r%Document-method:\s+[\w:.#=!?|^&<>~+\-/*\%@`\[\]]+%, ''
-
- space = ' '
- space = RDoc::Encoding.change_encoding space, encoding if encoding
-
- text.sub! %r%/\*+% do space * $&.length end
- text.sub! %r%\*+/% do space * $&.length end
- text.gsub! %r%^[ \t]*\*%m do space * $&.length end
-
- empty = ''
- empty = RDoc::Encoding.change_encoding empty, encoding if encoding
- text.gsub(/^\s+$/, empty)
- end
-
- ##
- # Converts ampersand, dashes, ellipsis, quotes, copyright and registered
- # trademark symbols in +text+ to properly encoded characters.
-
- def to_html text
- html = (''.encode text.encoding).dup
-
- encoded = RDoc::Text::TO_HTML_CHARACTERS[text.encoding]
-
- s = StringScanner.new text
- insquotes = false
- indquotes = false
- after_word = nil
-
- until s.eos? do
- case
- when s.scan(/<(tt|code)>.*?<\/\1>/) then # skip contents of tt
- html << s.matched.gsub('\\\\', '\\')
- when s.scan(/<(tt|code)>.*?/) then
- warn "mismatched <#{s[1]}> tag" # TODO signal file/line
- html << s.matched
- when s.scan(/<[^>]+\/?s*>/) then # skip HTML tags
- html << s.matched
- when s.scan(/\\(\S)/) then # unhandled suppressed crossref
- html << s[1]
- after_word = nil
- when s.scan(/\.\.\.(\.?)/) then
- html << s[1] << encoded[:ellipsis]
- after_word = nil
- when s.scan(/\(c\)/i) then
- html << encoded[:copyright]
- after_word = nil
- when s.scan(/\(r\)/i) then
- html << encoded[:trademark]
- after_word = nil
- when s.scan(/---/) then
- html << encoded[:em_dash]
- after_word = nil
- when s.scan(/--/) then
- html << encoded[:en_dash]
- after_word = nil
- when s.scan(/&quot;|"/) then
- html << encoded[indquotes ? :close_dquote : :open_dquote]
- indquotes = !indquotes
- after_word = nil
- when s.scan(/``/) then # backtick double quote
- html << encoded[:open_dquote]
- after_word = nil
- when s.scan(/(?:&#39;|'){2}/) then # tick double quote
- html << encoded[:close_dquote]
- after_word = nil
- 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(/&#39;|'/) then # single quote
- if insquotes
- html << encoded[:close_squote]
- insquotes = false
- elsif after_word
- # Mary's dog, my parents' house: do not start paired quotes
- html << encoded[:close_squote]
- else
- html << encoded[:open_squote]
- insquotes = true
- end
-
- after_word = nil
- else # advance to the next potentially significant character
- match = s.scan(/.+?(?=[<\\.("'`&-])/) #"
-
- if match then
- html << match
- after_word = match =~ /\w$/
- else
- html << s.rest
- break
- end
- end
- end
-
- html
- end
-
- ##
- # Wraps +txt+ to +line_len+
-
- def wrap(txt, line_len = 76)
- res = []
- sp = 0
- ep = txt.length
-
- while sp < ep
- # scan back for a space
- p = sp + line_len - 1
- if p >= ep
- p = ep
- else
- while p > sp and txt[p] != ?\s
- p -= 1
- end
- if p <= sp
- p = sp + line_len
- while p < ep and txt[p] != ?\s
- p += 1
- end
- end
- end
- res << txt[sp...p] << "\n"
- sp = p
- sp += 1 while sp < ep and txt[sp] == ?\s
- end
-
- res.join.strip
- end
-
- ##
- # Character class to be separated by a space when concatenating
- # lines.
-
- SPACE_SEPARATED_LETTER_CLASS = /[\p{Nd}\p{Lc}\p{Pc}]|[!-~&&\W]/
-
-end
diff --git a/lib/rdoc/token_stream.rb b/lib/rdoc/token_stream.rb
deleted file mode 100644
index 19ca7ed248..0000000000
--- a/lib/rdoc/token_stream.rb
+++ /dev/null
@@ -1,118 +0,0 @@
-# frozen_string_literal: true
-##
-# A TokenStream is a list of tokens, gathered during the parse of some entity
-# (say a method). Entities populate these streams by being registered with the
-# lexer. Any class can collect tokens by including TokenStream. From the
-# outside, you use such an object by calling the start_collecting_tokens
-# method, followed by calls to add_token and pop_token.
-
-module RDoc::TokenStream
-
- ##
- # Converts +token_stream+ to HTML wrapping various tokens with
- # <tt><span></tt> elements. Some tokens types are wrapped in spans
- # with the given class names. Other token types are not wrapped in spans.
-
- def self.to_html token_stream
- starting_title = false
-
- token_stream.map do |t|
- next unless t
-
- style = case t[:kind]
- when :on_const then 'ruby-constant'
- when :on_kw then 'ruby-keyword'
- when :on_ivar then 'ruby-ivar'
- when :on_cvar then 'ruby-identifier'
- when :on_gvar then 'ruby-identifier'
- when '=' != t[:text] && :on_op
- then 'ruby-operator'
- when :on_tlambda then 'ruby-operator'
- when :on_ident then 'ruby-identifier'
- when :on_label then 'ruby-value'
- when :on_backref, :on_dstring
- then 'ruby-node'
- when :on_comment then 'ruby-comment'
- when :on_embdoc then 'ruby-comment'
- when :on_regexp then 'ruby-regexp'
- when :on_tstring then 'ruby-string'
- when :on_int, :on_float,
- :on_rational, :on_imaginary,
- :on_heredoc,
- :on_symbol, :on_CHAR then 'ruby-value'
- when :on_heredoc_beg, :on_heredoc_end
- then 'ruby-identifier'
- end
-
- comment_with_nl = false
- if :on_comment == t[:kind] or :on_embdoc == t[:kind] or :on_heredoc_end == t[:kind]
- comment_with_nl = true if "\n" == t[:text][-1]
- text = t[:text].rstrip
- else
- text = t[:text]
- end
-
- if :on_ident == t[:kind] && starting_title
- starting_title = false
- style = 'ruby-identifier ruby-title'
- end
-
- if :on_kw == t[:kind] and 'def' == t[:text]
- starting_title = true
- end
-
- text = CGI.escapeHTML text
-
- if style then
- "<span class=\"#{style}\">#{text}</span>#{"\n" if comment_with_nl}"
- else
- text
- end
- end.join
- end
-
- ##
- # Adds +tokens+ to the collected tokens
-
- def add_tokens(tokens)
- @token_stream.concat(tokens)
- end
-
- ##
- # Adds one +token+ to the collected tokens
-
- def add_token(token)
- @token_stream.push(token)
- end
-
- ##
- # Starts collecting tokens
-
- def collect_tokens
- @token_stream = []
- end
-
- alias start_collecting_tokens collect_tokens
-
- ##
- # Remove the last token from the collected tokens
-
- def pop_token
- @token_stream.pop
- end
-
- ##
- # Current token stream
-
- def token_stream
- @token_stream
- end
-
- ##
- # Returns a string representation of the token stream
-
- def tokens_to_s
- (token_stream or return '').compact.map { |token| token[:text] }.join ''
- end
-
-end
diff --git a/lib/rdoc/tom_doc.rb b/lib/rdoc/tom_doc.rb
deleted file mode 100644
index e161fcf42f..0000000000
--- a/lib/rdoc/tom_doc.rb
+++ /dev/null
@@ -1,263 +0,0 @@
-# frozen_string_literal: true
-# :markup: tomdoc
-
-# A parser for TomDoc based on TomDoc 1.0.0-rc1 (02adef9b5a)
-#
-# The TomDoc specification can be found at:
-#
-# http://tomdoc.org
-#
-# The latest version of the TomDoc specification can be found at:
-#
-# https://github.com/mojombo/tomdoc/blob/master/tomdoc.md
-#
-# To choose TomDoc as your only default format see RDoc::Options@Saved+Options
-# for instructions on setting up a <code>.rdoc_options</code> file to store
-# your project default.
-#
-# There are a few differences between this parser and the specification. A
-# best-effort was made to follow the specification as closely as possible but
-# some choices to deviate were made.
-#
-# A future version of RDoc will warn when a MUST or MUST NOT is violated and
-# may warn when a SHOULD or SHOULD NOT is violated. RDoc will always try
-# to emit documentation even if given invalid TomDoc.
-#
-# Here are some implementation choices this parser currently makes:
-#
-# This parser allows rdoc-style inline markup but you should not depended on
-# it.
-#
-# This parser allows a space between the comment and the method body.
-#
-# This parser does not require the default value to be described for an
-# optional argument.
-#
-# This parser does not examine the order of sections. An Examples section may
-# precede the Arguments section.
-#
-# This class is documented in TomDoc format. Since this is a subclass of the
-# RDoc markup parser there isn't much to see here, unfortunately.
-
-class RDoc::TomDoc < RDoc::Markup::Parser
-
- # Internal: Token accessor
-
- attr_reader :tokens
-
- # Internal: Adds a post-processor which sets the RDoc section based on the
- # comment's status.
- #
- # Returns nothing.
-
- def self.add_post_processor # :nodoc:
- RDoc::Markup::PreProcess.post_process do |comment, code_object|
- next unless code_object and
- RDoc::Comment === comment and comment.format == 'tomdoc'
-
- comment.text.gsub!(/(\A\s*# )(Public|Internal|Deprecated):\s+/) do
- section = code_object.add_section $2
- code_object.temporary_section = section
-
- $1
- end
- end
- end
-
- add_post_processor
-
- # Public: Parses TomDoc from text
- #
- # text - A String containing TomDoc-format text.
- #
- # Examples
- #
- # RDoc::TomDoc.parse <<-TOMDOC
- # This method does some things
- #
- # Returns nothing.
- # TOMDOC
- # # => #<RDoc::Markup::Document:0xXXX @parts=[...], @file=nil>
- #
- # Returns an RDoc::Markup::Document representing the TomDoc format.
-
- def self.parse text
- parser = new
-
- parser.tokenize text
- doc = RDoc::Markup::Document.new
- parser.parse doc
- doc
- end
-
- # Internal: Extracts the Signature section's method signature
- #
- # comment - An RDoc::Comment that will be parsed and have the signature
- # extracted
- #
- # Returns a String containing the signature and nil if not
-
- def self.signature comment
- return unless comment.tomdoc?
-
- document = comment.parse
-
- signature = nil
- found_heading = false
- found_signature = false
-
- document.parts.delete_if do |part|
- next false if found_signature
-
- found_heading ||=
- RDoc::Markup::Heading === part && part.text == 'Signature'
-
- next false unless found_heading
-
- next true if RDoc::Markup::BlankLine === part
-
- if RDoc::Markup::Verbatim === part then
- signature = part
- found_signature = true
- end
- end
-
- signature and signature.text
- end
-
- # Public: Creates a new TomDoc parser. See also RDoc::Markup::parse
-
- def initialize
- super
-
- @section = nil
- @seen_returns = false
- end
-
- # Internal: Builds a heading from the token stream
- #
- # level - The level of heading to create
- #
- # Returns an RDoc::Markup::Heading
-
- def build_heading level
- heading = super
-
- @section = heading.text
-
- heading
- end
-
- # Internal: Builds a verbatim from the token stream. A verbatim in the
- # Examples section will be marked as in Ruby format.
- #
- # margin - The indentation from the margin for lines that belong to this
- # verbatim section.
- #
- # Returns an RDoc::Markup::Verbatim
-
- def build_verbatim margin
- verbatim = super
-
- verbatim.format = :ruby if @section == 'Examples'
-
- verbatim
- end
-
- # Internal: Builds a paragraph from the token stream
- #
- # margin - Unused
- #
- # Returns an RDoc::Markup::Paragraph.
-
- def build_paragraph margin
- p :paragraph_start => margin if @debug
-
- paragraph = RDoc::Markup::Paragraph.new
-
- until @tokens.empty? do
- type, data, = get
-
- case type
- when :TEXT then
- @section = 'Returns' if data =~ /\A(Returns|Raises)/
-
- paragraph << data
- when :NEWLINE then
- if :TEXT == peek_token[0] then
- # Lines beginning with 'Raises' in the Returns section should not be
- # treated as multiline text
- if 'Returns' == @section and
- peek_token[1].start_with?('Raises') then
- break
- else
- paragraph << ' '
- end
- else
- break
- end
- else
- unget
- break
- end
- end
-
- p :paragraph_end => margin if @debug
-
- paragraph
- end
-
- ##
- # Detects a section change to "Returns" and adds a heading
-
- def parse_text parent, indent # :nodoc:
- paragraph = build_paragraph indent
-
- if false == @seen_returns and 'Returns' == @section then
- @seen_returns = true
- parent << RDoc::Markup::Heading.new(3, 'Returns')
- parent << RDoc::Markup::BlankLine.new
- end
-
- parent << paragraph
- end
-
- # Internal: Turns text into an Array of tokens
- #
- # text - A String containing TomDoc-format text.
- #
- # Returns self.
-
- def tokenize text
- text = text.sub(/\A(Public|Internal|Deprecated):\s+/, '')
-
- setup_scanner text
-
- until @s.eos? do
- pos = @s.pos
-
- # leading spaces will be reflected by the column of the next token
- # the only thing we loose are trailing spaces at the end of the file
- next if @s.scan(/ +/)
-
- @tokens << case
- when @s.scan(/\r?\n/) then
- token = [:NEWLINE, @s.matched, *pos]
- @s.newline!
- token
- when @s.scan(/(Examples|Signature)$/) then
- @tokens << [:HEADER, 3, *pos]
-
- [:TEXT, @s[1], *pos]
- when @s.scan(/([:\w][\w\[\]]*)[ ]+- /) then
- [:NOTE, @s[1], *pos]
- else
- @s.scan(/.*/)
- [:TEXT, @s.matched.sub(/\r$/, ''), *pos]
- end
- end
-
- self
- end
-
-end
diff --git a/lib/rdoc/top_level.rb b/lib/rdoc/top_level.rb
deleted file mode 100644
index 3864f66431..0000000000
--- a/lib/rdoc/top_level.rb
+++ /dev/null
@@ -1,291 +0,0 @@
-# frozen_string_literal: true
-##
-# A TopLevel context is a representation of the contents of a single file
-
-class RDoc::TopLevel < RDoc::Context
-
- MARSHAL_VERSION = 0 # :nodoc:
-
- ##
- # This TopLevel's File::Stat struct
-
- attr_accessor :file_stat
-
- ##
- # Relative name of this file
-
- attr_accessor :relative_name
-
- ##
- # Absolute name of this file
-
- attr_accessor :absolute_name
-
- ##
- # All the classes or modules that were declared in
- # this file. These are assigned to either +#classes_hash+
- # or +#modules_hash+ once we know what they really are.
-
- attr_reader :classes_or_modules
-
- attr_accessor :diagram # :nodoc:
-
- ##
- # The parser class that processed this file
-
- attr_reader :parser
-
- ##
- # Creates a new TopLevel for the file at +absolute_name+. If documentation
- # is being generated outside the source dir +relative_name+ is relative to
- # the source directory.
-
- def initialize absolute_name, relative_name = absolute_name
- super()
- @name = nil
- @absolute_name = absolute_name
- @relative_name = relative_name
- @file_stat = File.stat(absolute_name) rescue nil # HACK for testing
- @diagram = nil
- @parser = nil
-
- @classes_or_modules = []
- end
-
- ##
- # Sets the parser for this toplevel context, also the store.
-
- def parser=(val)
- @parser = val
- @store.update_parser_of_file(absolute_name, val) if @store
- @parser
- end
-
- ##
- # An RDoc::TopLevel is equal to another with the same relative_name
-
- def == other
- self.class === other and @relative_name == other.relative_name
- end
-
- alias eql? ==
-
- ##
- # Adds +an_alias+ to +Object+ instead of +self+.
-
- def add_alias(an_alias)
- object_class.record_location self
- return an_alias unless @document_self
- object_class.add_alias an_alias
- end
-
- ##
- # Adds +constant+ to +Object+ instead of +self+.
-
- def add_constant constant
- object_class.record_location self
- return constant unless @document_self
- object_class.add_constant constant
- end
-
- ##
- # Adds +include+ to +Object+ instead of +self+.
-
- def add_include(include)
- object_class.record_location self
- return include unless @document_self
- object_class.add_include include
- end
-
- ##
- # Adds +method+ to +Object+ instead of +self+.
-
- def add_method(method)
- object_class.record_location self
- return method unless @document_self
- object_class.add_method method
- end
-
- ##
- # Adds class or module +mod+. Used in the building phase
- # by the Ruby parser.
-
- def add_to_classes_or_modules mod
- @classes_or_modules << mod
- end
-
- ##
- # Base name of this file
-
- def base_name
- File.basename @relative_name
- end
-
- alias name base_name
-
- ##
- # Only a TopLevel that contains text file) will be displayed. See also
- # RDoc::CodeObject#display?
-
- def display?
- text? and super
- end
-
- ##
- # See RDoc::TopLevel::find_class_or_module
- #--
- # TODO Why do we search through all classes/modules found, not just the
- # ones of this instance?
-
- def find_class_or_module name
- @store.find_class_or_module name
- end
-
- ##
- # Finds a class or module named +symbol+
-
- def find_local_symbol(symbol)
- find_class_or_module(symbol) || super
- end
-
- ##
- # Finds a module or class with +name+
-
- def find_module_named(name)
- find_class_or_module(name)
- end
-
- ##
- # Returns the relative name of this file
-
- def full_name
- @relative_name
- end
-
- ##
- # An RDoc::TopLevel has the same hash as another with the same
- # relative_name
-
- def hash
- @relative_name.hash
- end
-
- ##
- # URL for this with a +prefix+
-
- def http_url(prefix)
- path = [prefix, @relative_name.tr('.', '_')]
-
- File.join(*path.compact) + '.html'
- end
-
- def inspect # :nodoc:
- "#<%s:0x%x %p modules: %p classes: %p>" % [
- self.class, object_id,
- base_name,
- @modules.map { |n,m| m },
- @classes.map { |n,c| c }
- ]
- end
-
- ##
- # Time this file was last modified, if known
-
- def last_modified
- @file_stat ? file_stat.mtime : nil
- end
-
- ##
- # Dumps this TopLevel for use by ri. See also #marshal_load
-
- def marshal_dump
- [
- MARSHAL_VERSION,
- @relative_name,
- @parser,
- parse(@comment),
- ]
- end
-
- ##
- # Loads this TopLevel from +array+.
-
- def marshal_load array # :nodoc:
- initialize array[1]
-
- @parser = array[2]
- @comment = array[3]
-
- @file_stat = nil
- end
-
- ##
- # Returns the NormalClass "Object", creating it if not found.
- #
- # Records +self+ as a location in "Object".
-
- def object_class
- @object_class ||= begin
- oc = @store.find_class_named('Object') || add_class(RDoc::NormalClass, 'Object')
- oc.record_location self
- oc
- end
- end
-
- ##
- # Base name of this file without the extension
-
- def page_name
- basename = File.basename @relative_name
- basename =~ /\.(rb|rdoc|txt|md)$/i
-
- $` || basename
- end
-
- ##
- # Path to this file for use with HTML generator output.
-
- def path
- http_url @store.rdoc.generator.file_dir
- end
-
- def pretty_print q # :nodoc:
- q.group 2, "[#{self.class}: ", "]" do
- q.text "base name: #{base_name.inspect}"
- q.breakable
-
- items = @modules.map { |n,m| m }
- items.concat @modules.map { |n,c| c }
- q.seplist items do |mod| q.pp mod end
- end
- end
-
- ##
- # Search record used by RDoc::Generator::JsonIndex
-
- def search_record
- return unless @parser < RDoc::Parser::Text
-
- [
- page_name,
- '',
- page_name,
- '',
- path,
- '',
- snippet(@comment),
- ]
- end
-
- ##
- # Is this TopLevel from a text file instead of a source code file?
-
- def text?
- @parser and @parser.include? RDoc::Parser::Text
- end
-
- def to_s # :nodoc:
- "file #{full_name}"
- end
-
-end
diff --git a/lib/rdoc/version.rb b/lib/rdoc/version.rb
deleted file mode 100644
index 427d4ae232..0000000000
--- a/lib/rdoc/version.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-module RDoc
-
- ##
- # RDoc version you are using
-
- VERSION = '6.7.0'
-
-end
diff --git a/lib/readline.gemspec b/lib/readline.gemspec
deleted file mode 100644
index 9221c29263..0000000000
--- a/lib/readline.gemspec
+++ /dev/null
@@ -1,33 +0,0 @@
-Gem::Specification.new do |spec|
- spec.name = 'readline'
- spec.version = '0.0.4'
- spec.authors = ['aycabta']
- spec.email = ['aycabta@gmail.com']
-
- spec.summary = %q{Loader for "readline".}
- spec.description = <<~EOD
- 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'
-
- 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 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 |
- | the "readline-ext" gem. |
- +---------------------------------------------------------------------------+
- EOM
-
- spec.add_runtime_dependency 'reline'
-end
diff --git a/lib/readline.rb b/lib/readline.rb
deleted file mode 100644
index d1c9d3a955..0000000000
--- a/lib/readline.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-begin
- require "readline.#{RbConfig::CONFIG["DLEXT"]}"
-rescue LoadError
- require 'reline' unless defined? Reline
- Object.send(:remove_const, :Readline) if Object.const_defined?(:Readline)
- Readline = Reline
-end
diff --git a/lib/reline.rb b/lib/reline.rb
deleted file mode 100644
index 796e637e85..0000000000
--- a/lib/reline.rb
+++ /dev/null
@@ -1,593 +0,0 @@
-require 'io/console'
-require 'forwardable'
-require 'reline/version'
-require 'reline/config'
-require 'reline/key_actor'
-require 'reline/key_stroke'
-require 'reline/line_editor'
-require 'reline/history'
-require 'reline/terminfo'
-require 'reline/io'
-require 'reline/face'
-require 'rbconfig'
-
-module Reline
- # NOTE: For making compatible with the rb-readline gem
- FILENAME_COMPLETION_PROC = nil
- USERNAME_COMPLETION_PROC = nil
-
- class ConfigEncodingConversionError < StandardError; end
-
- Key = Struct.new(: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,
- :face,
- :bg_color, # For the time being, this line should stay here for the compatibility with IRB.
- :width,
- :height,
- :scrollbar,
- keyword_init: true
- )
-
- class Core
- ATTR_READER_NAMES = %i(
- completion_append_character
- basic_word_break_characters
- completer_word_break_characters
- basic_quote_characters
- completer_quote_characters
- filename_quote_characters
- special_prefixes
- completion_proc
- output_modifier_proc
- prompt_proc
- auto_indent_proc
- pre_input_hook
- dig_perfect_match_proc
- ).each(&method(:attr_reader))
-
- attr_accessor :config
- attr_accessor :key_stroke
- attr_accessor :line_editor
- attr_accessor :last_incremental_search
- attr_reader :output
-
- extend Forwardable
- def_delegators :config,
- :autocompletion,
- :autocompletion=
-
- def initialize
- self.output = STDOUT
- @mutex = Mutex.new
- @dialog_proc_list = {}
- yield self
- @completion_quote_character = nil
- end
-
- def io_gate
- Reline::IOGate
- end
-
- def encoding
- io_gate.encoding
- end
-
- def completion_append_character=(val)
- if val.nil?
- @completion_append_character = nil
- elsif val.size == 1
- @completion_append_character = val.encode(encoding)
- elsif val.size > 1
- @completion_append_character = val[0].encode(encoding)
- else
- @completion_append_character = nil
- end
- end
-
- def basic_word_break_characters=(v)
- @basic_word_break_characters = v.encode(encoding)
- end
-
- def completer_word_break_characters=(v)
- @completer_word_break_characters = v.encode(encoding)
- end
-
- def basic_quote_characters=(v)
- @basic_quote_characters = v.encode(encoding)
- end
-
- def completer_quote_characters=(v)
- @completer_quote_characters = v.encode(encoding)
- end
-
- def filename_quote_characters=(v)
- @filename_quote_characters = v.encode(encoding)
- end
-
- def special_prefixes=(v)
- @special_prefixes = v.encode(encoding)
- end
-
- def completion_case_fold=(v)
- @config.completion_ignore_case = v
- end
-
- def completion_case_fold
- @config.completion_ignore_case
- end
-
- def completion_quote_character
- @completion_quote_character
- end
-
- def completion_proc=(p)
- raise ArgumentError unless p.respond_to?(:call) or p.nil?
- @completion_proc = p
- end
-
- def output_modifier_proc=(p)
- 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) or p.nil?
- @prompt_proc = p
- end
-
- def auto_indent_proc=(p)
- raise ArgumentError unless p.respond_to?(:call) or p.nil?
- @auto_indent_proc = p
- end
-
- def pre_input_hook=(p)
- @pre_input_hook = p
- end
-
- def dig_perfect_match_proc=(p)
- 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 name_sym.instance_of?(Symbol)
- if p.nil?
- @dialog_proc_list.delete(name_sym)
- else
- raise ArgumentError unless p.respond_to?(:call)
- @dialog_proc_list[name_sym] = DialogProc.new(p, context)
- end
- 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) && io_gate.respond_to?(:input=)
- io_gate.input = val
- end
- end
-
- def output=(val)
- raise TypeError unless val.respond_to?(:write) or val.nil?
- @output = val
- if io_gate.respond_to?(:output=)
- io_gate.output = val
- end
- end
-
- def vi_editing_mode
- config.editing_mode = :vi_insert
- nil
- end
-
- def emacs_editing_mode
- config.editing_mode = :emacs
- nil
- end
-
- def vi_editing_mode?
- config.editing_mode_is?(:vi_insert, :vi_command)
- end
-
- def emacs_editing_mode?
- config.editing_mode_is?(:emacs)
- end
-
- def get_screen_size
- io_gate.get_screen_size
- end
-
- Reline::DEFAULT_DIALOG_PROC_AUTOCOMPLETE = ->() {
- # autocomplete
- return unless config.autocompletion
-
- journey_data = completion_journey_data
- return unless journey_data
-
- target = journey_data.list.first
- completed = journey_data.list[journey_data.pointer]
- result = journey_data.list.drop(1)
- pointer = journey_data.pointer - 1
- return if completed.empty? || (result == [completed] && pointer < 0)
-
- target_width = Reline::Unicode.calculate_width(target)
- completed_width = Reline::Unicode.calculate_width(completed)
- if cursor_pos.x <= completed_width - target_width
- # When target is rendered on the line above cursor position
- x = screen_width - completed_width
- y = -1
- else
- x = [cursor_pos.x - completed_width, 0].max
- 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, preferred_dialog_height].min,
- face: :completion_dialog
- )
- }
- Reline::DEFAULT_DIALOG_CONTEXT = Array.new
-
- def readmultiline(prompt = '', add_hist = false, &confirm_multiline_termination)
- @mutex.synchronize do
- unless confirm_multiline_termination
- raise ArgumentError.new('#readmultiline needs block to confirm multiline termination')
- end
-
- Reline.update_iogate
- io_gate.with_raw_input do
- inner_readline(prompt, add_hist, true, &confirm_multiline_termination)
- end
-
- whole_buffer = line_editor.whole_buffer.dup
- whole_buffer.taint if RUBY_VERSION < '2.7'
- if add_hist and whole_buffer and whole_buffer.chomp("\n").size > 0
- Reline::HISTORY << whole_buffer
- end
-
- if line_editor.eof?
- line_editor.reset_line
- # Return nil if the input is aborted by C-d.
- nil
- else
- whole_buffer
- end
- end
- end
-
- def readline(prompt = '', add_hist = false)
- @mutex.synchronize do
- Reline.update_iogate
- io_gate.with_raw_input do
- inner_readline(prompt, add_hist, false)
- end
-
- line = line_editor.line.dup
- line.taint if RUBY_VERSION < '2.7'
- if add_hist and line and line.chomp("\n").size > 0
- Reline::HISTORY << line.chomp("\n")
- end
-
- line_editor.reset_line if line_editor.line.nil?
- line
- end
- end
-
- private def inner_readline(prompt, add_hist, multiline, &confirm_multiline_termination)
- if ENV['RELINE_STDERR_TTY']
- if io_gate.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
- unless config.test_mode or config.loaded?
- config.read
- io_gate.set_default_key_bindings(config)
- end
- otio = io_gate.prep
-
- may_req_ambiguous_char_width
- line_editor.reset(prompt, encoding: encoding)
- if multiline
- line_editor.multiline_on
- if block_given?
- line_editor.confirm_multiline_termination_proc = confirm_multiline_termination
- end
- else
- line_editor.multiline_off
- end
- line_editor.output = output
- line_editor.completion_proc = completion_proc
- line_editor.completion_append_character = completion_append_character
- line_editor.output_modifier_proc = output_modifier_proc
- line_editor.prompt_proc = prompt_proc
- line_editor.auto_indent_proc = auto_indent_proc
- line_editor.dig_perfect_match_proc = dig_perfect_match_proc
- pre_input_hook&.call
- unless Reline::IOGate.dumb?
- @dialog_proc_list.each_pair do |name_sym, d|
- line_editor.add_dialog_proc(name_sym, d.dialog_proc, d.context)
- end
- end
-
- line_editor.print_nomultiline_prompt(prompt)
- line_editor.update_dialogs
- line_editor.rerender
-
- begin
- line_editor.set_signal_handlers
- loop do
- read_io(config.keyseq_timeout) { |inputs|
- line_editor.set_pasting_state(io_gate.in_pasting?)
- inputs.each do |key|
- if key.char == :bracketed_paste_start
- text = io_gate.read_bracketed_paste
- line_editor.insert_pasted_text(text)
- line_editor.scroll_into_view
- else
- line_editor.update(key)
- end
- end
- }
- if line_editor.finished?
- line_editor.render_finished
- break
- else
- line_editor.set_pasting_state(io_gate.in_pasting?)
- line_editor.rerender
- end
- end
- io_gate.move_cursor_column(0)
- rescue Errno::EIO
- # Maybe the I/O has been closed.
- ensure
- line_editor.finalize
- io_gate.deprep(otio)
- end
- end
-
- # 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.
- private def read_io(keyseq_timeout, &block)
- buffer = []
- loop do
- c = io_gate.getc(Float::INFINITY)
- if c == -1
- result = :unmatched
- else
- buffer << c
- result = key_stroke.match_status(buffer)
- end
- case result
- when :matched
- expanded = key_stroke.expand(buffer).map{ |expanded_c|
- Reline::Key.new(expanded_c, expanded_c, false)
- }
- block.(expanded)
- break
- when :matching
- if buffer.size == 1
- case read_2nd_character_of_key_sequence(keyseq_timeout, buffer, c, block)
- when :break then break
- when :next then next
- end
- end
- when :unmatched
- if buffer.size == 1 and c == "\e".ord
- read_escaped_key(keyseq_timeout, c, block)
- else
- expanded = buffer.map{ |expanded_c|
- Reline::Key.new(expanded_c, expanded_c, false)
- }
- block.(expanded)
- end
- break
- end
- end
- end
-
- private def read_2nd_character_of_key_sequence(keyseq_timeout, buffer, c, block)
- succ_c = io_gate.getc(keyseq_timeout.fdiv(1000))
- if succ_c
- 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
- io_gate.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
- else
- block.([Reline::Key.new(c, c, false)])
- return :break
- end
- end
-
- private def read_escaped_key(keyseq_timeout, c, block)
- escaped_c = io_gate.getc(keyseq_timeout.fdiv(1000))
-
- if escaped_c.nil?
- block.([Reline::Key.new(c, c, false)])
- elsif escaped_c >= 128 # maybe, first byte of multi byte
- block.([Reline::Key.new(c, c, false), Reline::Key.new(escaped_c, escaped_c, false)])
- elsif escaped_c == "\e".ord # escape twice
- block.([Reline::Key.new(c, c, false), Reline::Key.new(c, c, false)])
- else
- block.([Reline::Key.new(escaped_c, escaped_c | 0b10000000, true)])
- 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 io_gate.dumb? or !STDOUT.tty?
- return if defined? @ambiguous_width
- io_gate.move_cursor_column(0)
- begin
- output.write "\u{25bd}"
- rescue Encoding::UndefinedConversionError
- # LANG=C
- @ambiguous_width = 1
- else
- @ambiguous_width = io_gate.cursor_pos.x
- end
- io_gate.move_cursor_column(0)
- io_gate.erase_after_cursor
- end
- end
-
- extend Forwardable
- extend SingleForwardable
-
- #--------------------------------------------------------
- # Documented API
- #--------------------------------------------------------
-
- (Core::ATTR_READER_NAMES).each { |name|
- def_single_delegators :core, :"#{name}", :"#{name}="
- }
- def_single_delegators :core, :input=, :output=
- def_single_delegators :core, :vi_editing_mode, :emacs_editing_mode
- def_single_delegators :core, :readline
- def_single_delegators :core, :completion_case_fold, :completion_case_fold=
- def_single_delegators :core, :completion_quote_character
- def_instance_delegators self, :readline
- private :readline
-
-
- #--------------------------------------------------------
- # Undocumented API
- #--------------------------------------------------------
-
- # Testable in original
- def_single_delegators :core, :get_screen_size
- def_single_delegators :line_editor, :eof?
- def_instance_delegators self, :eof?
- def_single_delegators :line_editor, :delete_text
- def_single_delegator :line_editor, :line, :line_buffer
- def_single_delegator :line_editor, :byte_pointer, :point
- def_single_delegator :line_editor, :byte_pointer=, :point=
-
- def self.insert_text(*args, &block)
- line_editor.insert_text(*args, &block)
- self
- end
-
- # Untestable in original
- def_single_delegator :line_editor, :rerender, :redisplay
- def_single_delegators :core, :vi_editing_mode?, :emacs_editing_mode?
- 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
- private :readmultiline
-
- def self.encoding_system_needs
- self.core.encoding
- end
-
- def self.core
- @core ||= Core.new { |core|
- core.config = Reline::Config.new
- core.key_stroke = Reline::KeyStroke.new(core.config)
- core.line_editor = Reline::LineEditor.new(core.config, core.encoding)
-
- core.basic_word_break_characters = " \t\n`><=;|&{("
- core.completer_word_break_characters = " \t\n`><=;|&{("
- core.basic_quote_characters = '"\''
- 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)
- core.io_gate.ungetc(c)
- end
-
- def self.line_editor
- core.line_editor
- end
-
- def self.update_iogate
- return if core.config.test_mode
-
- # Need to change IOGate when `$stdout.tty?` change from false to true by `$stdout.reopen`
- # Example: rails/spring boot the application in non-tty, then run console in tty.
- if ENV['TERM'] != 'dumb' && core.io_gate.dumb? && $stdout.tty?
- require 'reline/io/ansi'
- remove_const(:IOGate)
- const_set(:IOGate, Reline::ANSI.new)
- end
- end
-end
-
-
-Reline::IOGate = Reline::IO.decide_io_gate
-
-# Deprecated
-Reline::GeneralIO = Reline::Dumb.new
-
-Reline::Face.load_initial_configs
-
-Reline::HISTORY = Reline::History.new(Reline.core.config)
diff --git a/lib/reline/config.rb b/lib/reline/config.rb
deleted file mode 100644
index 62c6d105b3..0000000000
--- a/lib/reline/config.rb
+++ /dev/null
@@ -1,380 +0,0 @@
-class Reline::Config
- attr_reader :test_mode
-
- 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
- attr_accessor :file, :lineno
- end
-
- VARIABLE_NAMES = %w{
- completion-ignore-case
- convert-meta
- disable-completion
- history-size
- keyseq-timeout
- show-all-if-ambiguous
- 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|
- attr_accessor v
- end
-
- attr_accessor :autocompletion
-
- def initialize
- @additional_key_bindings = {} # from inputrc
- @additional_key_bindings[:emacs] = {}
- @additional_key_bindings[:vi_insert] = {}
- @additional_key_bindings[:vi_command] = {}
- @oneshot_key_bindings = {}
- @editing_mode_label = :emacs
- @keymap_label = :emacs
- @keymap_prefix = []
- @key_actors = {}
- @key_actors[:emacs] = Reline::KeyActor::Emacs.new
- @key_actors[:vi_insert] = Reline::KeyActor::ViInsert.new
- @key_actors[:vi_command] = Reline::KeyActor::ViCommand.new
- @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)
- @loaded = false
- @enable_bracketed_paste = true
- end
-
- def reset
- if editing_mode_is?(:vi_command)
- @editing_mode_label = :vi_insert
- end
- @oneshot_key_bindings.clear
- end
-
- def editing_mode
- @key_actors[@editing_mode_label]
- end
-
- def editing_mode=(val)
- @editing_mode_label = val
- end
-
- def editing_mode_is?(*val)
- val.any?(@editing_mode_label)
- end
-
- def keymap
- @key_actors[@keymap_label]
- end
-
- def loaded?
- @loaded
- end
-
- def inputrc_path
- case ENV['INPUTRC']
- when nil, ''
- else
- 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)
- @loaded = true
- file ||= default_inputrc_path
- begin
- if file.respond_to?(:readlines)
- lines = file.readlines
- else
- lines = File.readlines(file)
- end
- rescue Errno::ENOENT
- return nil
- end
-
- read_lines(lines, file)
- self
- rescue InvalidInputrc => e
- warn e.message
- nil
- end
-
- def 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)
- @key_actors[@keymap_label].default_key_bindings[keystroke] = target
- 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
- if_stack = []
-
- lines.each_with_index do |line, no|
- next if line.match(/\A\s*#/)
-
- no += 1
-
- line = line.chomp.lstrip
- if line.start_with?('$')
- handle_directive(line[1..-1], file, no, if_stack)
- next
- end
-
- next if if_stack.any? { |_no, skip| skip }
-
- case line
- when /^set +([^ ]+) +(.+)/i
- # value ignores everything after a space, raw_value does not.
- var, value, raw_value = $1.downcase, $2.partition(' ').first, $2
- bind_variable(var, value, raw_value)
- next
- when /\s*("#{KEYSEQ_PATTERN}+")\s*:\s*(.*)\s*$/o
- key, func_name = $1, $2
- func_name = func_name.split.first
- keystroke, func = bind_key(key, func_name)
- next unless keystroke
- @additional_key_bindings[@keymap_label][@keymap_prefix + keystroke] = func
- end
- end
- unless if_stack.empty?
- raise InvalidInputrc, "#{file}:#{if_stack.last[0]}: unclosed if"
- end
- end
-
- def handle_directive(directive, file, no, if_stack)
- directive, args = directive.split(' ')
- case directive
- when 'if'
- condition = false
- case args
- when /^mode=(vi|emacs)$/i
- mode = $1.downcase
- # NOTE: mode=vi means vi-insert mode
- mode = 'vi_insert' if mode == 'vi'
- if @editing_mode_label == mode.to_sym
- condition = true
- end
- when 'term'
- when 'version'
- else # application name
- condition = true if args == 'Ruby'
- condition = true if args == 'Reline'
- end
- if_stack << [no, !condition]
- when 'else'
- if if_stack.empty?
- raise InvalidInputrc, "#{file}:#{no}: unmatched else"
- end
- if_stack.last[1] = !if_stack.last[1]
- when 'endif'
- if if_stack.empty?
- raise InvalidInputrc, "#{file}:#{no}: unmatched endif"
- end
- if_stack.pop
- when 'include'
- read(File.expand_path(args))
- end
- end
-
- def bind_variable(name, value, raw_value)
- case name
- when 'history-size'
- begin
- @history_size = Integer(value)
- rescue ArgumentError
- @history_size = 500
- end
- when 'bell-style'
- @bell_style =
- case value
- when 'none', 'off'
- :none
- when 'audible', 'on'
- :audible
- when 'visible'
- :visible
- else
- :audible
- end
- when 'comment-begin'
- @comment_begin = value.dup
- when 'completion-query-items'
- @completion_query_items = value.to_i
- when 'isearch-terminators'
- @isearch_terminators = retrieve_string(raw_value)
- when 'editing-mode'
- case value
- when 'emacs'
- @editing_mode_label = :emacs
- @keymap_label = :emacs
- @keymap_prefix = []
- when 'vi'
- @editing_mode_label = :vi_insert
- @keymap_label = :vi_insert
- @keymap_prefix = []
- end
- when 'keymap'
- case value
- when 'emacs', 'emacs-standard'
- @keymap_label = :emacs
- @keymap_prefix = []
- when 'emacs-ctlx'
- @keymap_label = :emacs
- @keymap_prefix = [?\C-x.ord]
- when 'emacs-meta'
- @keymap_label = :emacs
- @keymap_prefix = [?\e.ord]
- when 'vi', 'vi-move', 'vi-command'
- @keymap_label = :vi_command
- @keymap_prefix = []
- when 'vi-insert'
- @keymap_label = :vi_insert
- @keymap_prefix = []
- 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(raw_value)
- when 'vi-ins-mode-string'
- @vi_ins_mode_string = retrieve_string(raw_value)
- when 'emacs-mode-string'
- @emacs_mode_string = retrieve_string(raw_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)
- else
- keyseq = nil
- end
- if func_name =~ /"(.*)"/
- func = parse_keyseq($1)
- else
- func = func_name.tr(?-, ?_).to_sym # It must be macro.
- end
- [keyseq, func]
- end
-
- def key_notation_to_code(notation)
- case notation
- when /\\(?:C|Control)-([A-Za-z_])/
- (1 + $1.downcase.ord - ?a.ord)
- when /\\(?:M|Meta)-([0-9A-Za-z_])/
- modified_key = $1
- case $1
- when /[0-9]/
- ?\M-0.bytes.first + (modified_key.ord - ?0.ord)
- when /[A-Z]/
- ?\M-A.bytes.first + (modified_key.ord - ?A.ord)
- when /[a-z]/
- ?\M-a.bytes.first + (modified_key.ord - ?a.ord)
- end
- when /\\(?:C|Control)-(?:M|Meta)-[A-Za-z_]/, /\\(?:M|Meta)-(?:C|Control)-[A-Za-z_]/
- # 129 M-^A
- when /\\(\d{1,3})/ then $1.to_i(8) # octal
- when /\\x(\h{1,2})/ then $1.to_i(16) # hexadecimal
- when "\\e" then ?\e.ord
- when "\\\\" then ?\\.ord
- when "\\\"" then ?".ord
- when "\\'" then ?'.ord
- when "\\a" then ?\a.ord
- when "\\b" then ?\b.ord
- when "\\d" then ?\d.ord
- when "\\f" then ?\f.ord
- when "\\n" then ?\n.ord
- when "\\r" then ?\r.ord
- when "\\t" then ?\t.ord
- when "\\v" then ?\v.ord
- else notation.ord
- end
- end
-
- def parse_keyseq(str)
- ret = []
- str.scan(KEYSEQ_PATTERN) do
- ret << key_notation_to_code($&)
- end
- ret
- end
-
- private def seven_bit_encoding?(encoding)
- encoding == Encoding::US_ASCII
- end
-end
diff --git a/lib/reline/face.rb b/lib/reline/face.rb
deleted file mode 100644
index d07196e2e7..0000000000
--- a/lib/reline/face.rb
+++ /dev/null
@@ -1,199 +0,0 @@
-# frozen_string_literal: true
-
-class Reline::Face
- SGR_PARAMETERS = {
- foreground: {
- black: 30,
- red: 31,
- green: 32,
- yellow: 33,
- blue: 34,
- magenta: 35,
- cyan: 36,
- white: 37,
- bright_black: 90,
- gray: 90,
- bright_red: 91,
- bright_green: 92,
- bright_yellow: 93,
- bright_blue: 94,
- bright_magenta: 95,
- bright_cyan: 96,
- bright_white: 97
- },
- background: {
- black: 40,
- red: 41,
- green: 42,
- yellow: 43,
- blue: 44,
- magenta: 45,
- cyan: 46,
- white: 47,
- bright_black: 100,
- gray: 100,
- bright_red: 101,
- bright_green: 102,
- bright_yellow: 103,
- bright_blue: 104,
- bright_magenta: 105,
- bright_cyan: 106,
- bright_white: 107,
- },
- style: {
- reset: 0,
- bold: 1,
- faint: 2,
- italicized: 3,
- underlined: 4,
- slowly_blinking: 5,
- blinking: 5,
- rapidly_blinking: 6,
- negative: 7,
- concealed: 8,
- crossed_out: 9
- }
- }.freeze
-
- class Config
- ESSENTIAL_DEFINE_NAMES = %i(default enhanced scrollbar).freeze
- RESET_SGR = "\e[0m".freeze
-
- def initialize(name, &block)
- @definition = {}
- block.call(self)
- ESSENTIAL_DEFINE_NAMES.each do |name|
- @definition[name] ||= { style: :reset, escape_sequence: RESET_SGR }
- end
- end
-
- attr_reader :definition
-
- def define(name, **values)
- values[:escape_sequence] = format_to_sgr(values.to_a).freeze
- @definition[name] = values
- end
-
- def reconfigure
- @definition.each_value do |values|
- values.delete(:escape_sequence)
- values[:escape_sequence] = format_to_sgr(values.to_a).freeze
- end
- end
-
- def [](name)
- @definition.dig(name, :escape_sequence) or raise ArgumentError, "unknown face: #{name}"
- end
-
- private
-
- def sgr_rgb(key, value)
- return nil unless rgb_expression?(value)
- if Reline::Face.truecolor?
- sgr_rgb_truecolor(key, value)
- else
- sgr_rgb_256color(key, value)
- end
- end
-
- def sgr_rgb_truecolor(key, value)
- case key
- when :foreground
- "38;2;"
- when :background
- "48;2;"
- end + value[1, 6].scan(/../).map(&:hex).join(";")
- end
-
- def sgr_rgb_256color(key, value)
- # 256 colors are
- # 0..15: standard colors, hight intensity colors
- # 16..232: 216 colors (R, G, B each 6 steps)
- # 233..255: grayscale colors (24 steps)
- # This methods converts rgb_expression to 216 colors
- rgb = value[1, 6].scan(/../).map(&:hex)
- # Color steps are [0, 95, 135, 175, 215, 255]
- r, g, b = rgb.map { |v| v <= 95 ? v / 48 : (v - 35) / 40 }
- color = (16 + 36 * r + 6 * g + b)
- case key
- when :foreground
- "38;5;#{color}"
- when :background
- "48;5;#{color}"
- end
- end
-
- def format_to_sgr(ordered_values)
- sgr = "\e[" + ordered_values.map do |key_value|
- key, value = key_value
- case key
- when :foreground, :background
- case value
- when Symbol
- SGR_PARAMETERS[key][value]
- when String
- sgr_rgb(key, value)
- end
- when :style
- [ value ].flatten.map do |style_name|
- SGR_PARAMETERS[:style][style_name]
- end.then do |sgr_parameters|
- sgr_parameters.include?(nil) ? nil : sgr_parameters
- end
- end.then do |rendition_expression|
- unless rendition_expression
- raise ArgumentError, "invalid SGR parameter: #{value.inspect}"
- end
- rendition_expression
- end
- end.join(';') + "m"
- sgr == RESET_SGR ? RESET_SGR : RESET_SGR + sgr
- end
-
- def rgb_expression?(color)
- color.respond_to?(:match?) and color.match?(/\A#[0-9a-fA-F]{6}\z/)
- end
- end
-
- private_constant :SGR_PARAMETERS, :Config
-
- def self.truecolor?
- @force_truecolor || %w[truecolor 24bit].include?(ENV['COLORTERM'])
- end
-
- def self.force_truecolor
- @force_truecolor = true
- @configs&.each_value(&:reconfigure)
- end
-
- def self.[](name)
- @configs[name]
- end
-
- def self.config(name, &block)
- @configs ||= {}
- @configs[name] = Config.new(name, &block)
- end
-
- def self.configs
- @configs.transform_values(&:definition)
- end
-
- def self.load_initial_configs
- config(:default) do |conf|
- conf.define :default, style: :reset
- conf.define :enhanced, style: :reset
- conf.define :scrollbar, style: :reset
- end
- config(:completion_dialog) do |conf|
- conf.define :default, foreground: :bright_white, background: :gray
- conf.define :enhanced, foreground: :black, background: :white
- conf.define :scrollbar, foreground: :white, background: :gray
- end
- end
-
- def self.reset_to_initial_configs
- @configs = {}
- load_initial_configs
- end
-end
diff --git a/lib/reline/history.rb b/lib/reline/history.rb
deleted file mode 100644
index 3f3b65fea6..0000000000
--- a/lib/reline/history.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-class Reline::History < Array
- def initialize(config)
- @config = config
- end
-
- def to_s
- 'HISTORY'
- end
-
- def delete_at(index)
- index = check_index(index)
- super(index)
- end
-
- def [](index)
- index = check_index(index) unless index.is_a?(Range)
- super(index)
- end
-
- def []=(index, val)
- index = check_index(index)
- super(index, String.new(val, encoding: Reline.encoding_system_needs))
- end
-
- def concat(*val)
- val.each do |v|
- push(*v)
- end
- end
-
- def push(*val)
- # 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)
- }))
- end
-
- def <<(val)
- # 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
- 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
-end
diff --git a/lib/reline/io.rb b/lib/reline/io.rb
deleted file mode 100644
index 7fca0c338a..0000000000
--- a/lib/reline/io.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-
-module Reline
- class IO
- RESET_COLOR = "\e[0m"
-
- def self.decide_io_gate
- if ENV['TERM'] == 'dumb'
- Reline::Dumb.new
- else
- require 'reline/io/ansi'
-
- case RbConfig::CONFIG['host_os']
- when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
- require 'reline/io/windows'
- io = Reline::Windows.new
- if io.msys_tty?
- Reline::ANSI.new
- else
- io
- end
- else
- if $stdout.tty?
- Reline::ANSI.new
- else
- Reline::Dumb.new
- end
- end
- end
- end
-
- def dumb?
- false
- end
-
- def win?
- false
- end
-
- def reset_color_sequence
- self.class::RESET_COLOR
- end
- end
-end
-
-require 'reline/io/dumb'
diff --git a/lib/reline/io/ansi.rb b/lib/reline/io/ansi.rb
deleted file mode 100644
index cf3c9965dd..0000000000
--- a/lib/reline/io/ansi.rb
+++ /dev/null
@@ -1,358 +0,0 @@
-require 'io/console'
-require 'io/wait'
-
-class Reline::ANSI < Reline::IO
- CAPNAME_KEY_BINDINGS = {
- 'khome' => :ed_move_to_beg,
- 'kend' => :ed_move_to_end,
- 'kdch1' => :key_delete,
- 'kpp' => :ed_search_prev_history,
- 'knp' => :ed_search_next_history,
- 'kcuu1' => :ed_prev_history,
- 'kcud1' => :ed_next_history,
- 'kcuf1' => :ed_next_char,
- 'kcub1' => :ed_prev_char,
- }
-
- ANSI_CURSOR_KEY_BINDINGS = {
- # Up
- 'A' => [:ed_prev_history, {}],
- # Down
- 'B' => [:ed_next_history, {}],
- # Right
- 'C' => [:ed_next_char, { ctrl: :em_next_word, meta: :em_next_word }],
- # Left
- 'D' => [:ed_prev_char, { ctrl: :ed_prev_word, meta: :ed_prev_word }],
- # End
- 'F' => [:ed_move_to_end, {}],
- # Home
- 'H' => [:ed_move_to_beg, {}],
- }
-
- if Reline::Terminfo.enabled?
- Reline::Terminfo.setupterm(0, 2)
- end
-
- def initialize
- @input = STDIN
- @output = STDOUT
- @buf = []
- @old_winch_handler = nil
- end
-
- def encoding
- Encoding.default_external
- end
-
- def set_default_key_bindings(config, allow_terminfo: true)
- set_bracketed_paste_key_bindings(config)
- set_default_key_bindings_ansi_cursor(config)
- if allow_terminfo && Reline::Terminfo.enabled?
- set_default_key_bindings_terminfo(config)
- else
- set_default_key_bindings_comprehensive_list(config)
- 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-<space>
- [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 set_bracketed_paste_key_bindings(config)
- [:emacs, :vi_insert, :vi_command].each do |keymap|
- config.add_default_key_binding_by_keymap(keymap, START_BRACKETED_PASTE.bytes, :bracketed_paste_start)
- end
- end
-
- def set_default_key_bindings_ansi_cursor(config)
- ANSI_CURSOR_KEY_BINDINGS.each do |char, (default_func, modifiers)|
- bindings = [["\e[#{char}", default_func]] # CSI + char
- if modifiers[:ctrl]
- # CSI + ctrl_key_modifier + char
- bindings << ["\e[1;5#{char}", modifiers[:ctrl]]
- end
- if modifiers[:meta]
- # CSI + meta_key_modifier + char
- bindings << ["\e[1;3#{char}", modifiers[:meta]]
- # Meta(ESC) + CSI + char
- bindings << ["\e\e[#{char}", modifiers[:meta]]
- end
- bindings.each do |sequence, func|
- key = sequence.bytes
- 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
- end
-
- def set_default_key_bindings_terminfo(config)
- key_bindings = CAPNAME_KEY_BINDINGS.map do |capname, key_binding|
- begin
- key_code = Reline::Terminfo.tigetstr(capname)
- [ key_code.bytes, key_binding ]
- 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 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
-
- # KDE
- # 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
-
- [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
-
- def input=(val)
- @input = val
- end
-
- def output=(val)
- @output = val
- end
-
- def with_raw_input
- if @input.tty?
- @input.raw(intr: true) { yield }
- else
- yield
- end
- end
-
- def inner_getc(timeout_second)
- unless @buf.empty?
- return @buf.shift
- end
- until @input.wait_readable(0.01)
- timeout_second -= 0.01
- return nil if timeout_second <= 0
-
- Reline.core.line_editor.handle_signal
- end
- c = @input.getbyte
- (c == 0x16 && @input.raw(min: 0, time: 0, &:getbyte)) || c
- rescue Errno::EIO
- # Maybe the I/O has been closed.
- nil
- rescue Errno::ENOTTY
- nil
- end
-
- START_BRACKETED_PASTE = String.new("\e[200~", encoding: Encoding::ASCII_8BIT)
- END_BRACKETED_PASTE = String.new("\e[201~", encoding: Encoding::ASCII_8BIT)
- def read_bracketed_paste
- buffer = String.new(encoding: Encoding::ASCII_8BIT)
- until buffer.end_with?(END_BRACKETED_PASTE)
- c = inner_getc(Float::INFINITY)
- break unless c
- buffer << c
- end
- string = buffer.delete_suffix(END_BRACKETED_PASTE).force_encoding(encoding)
- string.valid_encoding? ? string : ''
- end
-
- # if the usage expects to wait indefinitely, use Float::INFINITY for timeout_second
- def getc(timeout_second)
- inner_getc(timeout_second)
- end
-
- def in_pasting?
- not empty_buffer?
- end
-
- def empty_buffer?
- unless @buf.empty?
- return false
- end
- !@input.wait_readable(0)
- end
-
- def ungetc(c)
- @buf.unshift(c)
- end
-
- def retrieve_keybuffer
- begin
- return unless @input.wait_readable(0.001)
- str = @input.read_nonblock(1024)
- str.bytes.each do |c|
- @buf.push(c)
- end
- rescue EOFError
- end
- end
-
- def get_screen_size
- s = @input.winsize
- return s if s[0] > 0 && s[1] > 0
- s = [ENV["LINES"].to_i, ENV["COLUMNS"].to_i]
- return s if s[0] > 0 && s[1] > 0
- [24, 80]
- rescue Errno::ENOTTY, Errno::ENODEV
- [24, 80]
- end
-
- def set_screen_size(rows, columns)
- @input.winsize = [rows, columns]
- self
- rescue Errno::ENOTTY
- self
- end
-
- def cursor_pos
- begin
- res = +''
- m = nil
- @input.raw do |stdin|
- @output << "\e[6n"
- @output.flush
- loop do
- c = stdin.getc
- next if c.nil?
- res << c
- m = res.match(/\e\[(?<row>\d+);(?<column>\d+)R/)
- break if m
- end
- (m.pre_match + m.post_match).chars.reverse_each do |ch|
- stdin.ungetc ch
- end
- end
- column = m[:column].to_i - 1
- row = m[:row].to_i - 1
- rescue Errno::ENOTTY
- 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, IOError
- # 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
-
- def move_cursor_column(x)
- @output.write "\e[#{x + 1}G"
- end
-
- def move_cursor_up(x)
- if x > 0
- @output.write "\e[#{x}A"
- elsif x < 0
- move_cursor_down(-x)
- end
- end
-
- def move_cursor_down(x)
- if x > 0
- @output.write "\e[#{x}B"
- elsif x < 0
- move_cursor_up(-x)
- end
- end
-
- def hide_cursor
- if Reline::Terminfo.enabled? && Reline::Terminfo.term_supported?
- begin
- @output.write Reline::Terminfo.tigetstr('civis')
- rescue Reline::Terminfo::TerminfoError
- # civis is undefined
- end
- else
- # ignored
- end
- end
-
- def show_cursor
- if Reline::Terminfo.enabled? && Reline::Terminfo.term_supported?
- begin
- @output.write Reline::Terminfo.tigetstr('cnorm')
- rescue Reline::Terminfo::TerminfoError
- # cnorm is undefined
- end
- else
- # ignored
- end
- end
-
- def erase_after_cursor
- @output.write "\e[K"
- end
-
- # This only works when the cursor is at the bottom of the scroll range
- # For more details, see https://github.com/ruby/reline/pull/577#issuecomment-1646679623
- def scroll_down(x)
- return if x.zero?
- # We use `\n` instead of CSI + S because CSI + S would cause https://github.com/ruby/reline/issues/576
- @output.write "\n" * x
- end
-
- def clear_screen
- @output.write "\e[2J"
- @output.write "\e[1;1H"
- end
-
- def set_winch_handler(&handler)
- @old_winch_handler = Signal.trap('WINCH', &handler)
- end
-
- def prep
- # Enable bracketed paste
- @output.write "\e[?2004h" if Reline.core.config.enable_bracketed_paste
- retrieve_keybuffer
- nil
- end
-
- def deprep(otio)
- # Disable bracketed paste
- @output.write "\e[?2004l" if Reline.core.config.enable_bracketed_paste
- Signal.trap('WINCH', @old_winch_handler) if @old_winch_handler
- end
-end
diff --git a/lib/reline/io/dumb.rb b/lib/reline/io/dumb.rb
deleted file mode 100644
index 6ed69ffdfa..0000000000
--- a/lib/reline/io/dumb.rb
+++ /dev/null
@@ -1,106 +0,0 @@
-require 'io/wait'
-
-class Reline::Dumb < Reline::IO
- RESET_COLOR = '' # Do not send color reset sequence
-
- def initialize(encoding: nil)
- @input = STDIN
- @buf = []
- @pasting = false
- @encoding = encoding
- @screen_size = [24, 80]
- end
-
- def dumb?
- true
- end
-
- def encoding
- if @encoding
- @encoding
- elsif RUBY_PLATFORM =~ /mswin|mingw/
- Encoding::UTF_8
- else
- Encoding::default_external
- end
- end
-
- def set_default_key_bindings(_)
- end
-
- def input=(val)
- @input = val
- end
-
- def with_raw_input
- yield
- end
-
- def getc(_timeout_second)
- unless @buf.empty?
- return @buf.shift
- end
- c = nil
- loop do
- Reline.core.line_editor.handle_signal
- result = @input.wait_readable(0.1)
- next if result.nil?
- c = @input.read(1)
- break
- end
- c&.ord
- end
-
- def ungetc(c)
- @buf.unshift(c)
- end
-
- def get_screen_size
- @screen_size
- end
-
- def cursor_pos
- Reline::CursorPos.new(1, 1)
- end
-
- def hide_cursor
- end
-
- def show_cursor
- end
-
- def move_cursor_column(val)
- end
-
- def move_cursor_up(val)
- end
-
- def move_cursor_down(val)
- end
-
- def erase_after_cursor
- end
-
- def scroll_down(val)
- end
-
- def clear_screen
- end
-
- def set_screen_size(rows, columns)
- @screen_size = [rows, columns]
- end
-
- def set_winch_handler(&handler)
- end
-
- def in_pasting?
- @pasting
- end
-
- def prep
- end
-
- def deprep(otio)
- end
-end
diff --git a/lib/reline/io/windows.rb b/lib/reline/io/windows.rb
deleted file mode 100644
index 6ba4b830d6..0000000000
--- a/lib/reline/io/windows.rb
+++ /dev/null
@@ -1,503 +0,0 @@
-require 'fiddle/import'
-
-class Reline::Windows < Reline::IO
- def initialize
- @input_buf = []
- @output_buf = []
-
- @output = STDOUT
- @hsg = nil
- @getwch = Win32API.new('msvcrt', '_getwch', [], 'I')
- @kbhit = Win32API.new('msvcrt', '_kbhit', [], 'I')
- @GetKeyState = Win32API.new('user32', 'GetKeyState', ['L'], 'L')
- @GetConsoleScreenBufferInfo = Win32API.new('kernel32', 'GetConsoleScreenBufferInfo', ['L', 'P'], 'L')
- @SetConsoleCursorPosition = Win32API.new('kernel32', 'SetConsoleCursorPosition', ['L', 'L'], 'L')
- @GetStdHandle = Win32API.new('kernel32', 'GetStdHandle', ['L'], 'L')
- @FillConsoleOutputCharacter = Win32API.new('kernel32', 'FillConsoleOutputCharacter', ['L', 'L', 'L', 'L', 'P'], 'L')
- @ScrollConsoleScreenBuffer = Win32API.new('kernel32', 'ScrollConsoleScreenBuffer', ['L', 'P', 'P', 'L', 'P'], 'L')
- @hConsoleHandle = @GetStdHandle.call(STD_OUTPUT_HANDLE)
- @hConsoleInputHandle = @GetStdHandle.call(STD_INPUT_HANDLE)
- @GetNumberOfConsoleInputEvents = Win32API.new('kernel32', 'GetNumberOfConsoleInputEvents', ['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')
-
- @legacy_console = getconsolemode & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0
- end
-
- def encoding
- Encoding::UTF_8
- end
-
- def win?
- true
- end
-
- def win_legacy_console?
- @legacy_console
- end
-
- def 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-<space>
- [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'
- else
- 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
- end
- end
-
- VK_RETURN = 0x0D
- VK_MENU = 0x12 # ALT key
- 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
- FILE_TYPE_PIPE = 0x0003
- FILE_NAME_INFO = 2
- ENABLE_VIRTUAL_TERMINAL_PROCESSING = 4
-
- private def getconsolemode
- mode = "\000\000\000\000"
- @GetConsoleMode.call(@hConsoleHandle, mode)
- mode.unpack1('L')
- end
-
- private def setconsolemode(mode)
- @SetConsoleMode.call(@hConsoleHandle, mode)
- end
-
- #if @legacy_console
- # setconsolemode(getconsolemode() | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
- # @legacy_console = (getconsolemode() & ENABLE_VIRTUAL_TERMINAL_PROCESSING == 0)
- #end
-
- def msys_tty?(io = @hConsoleInputHandle)
- # check if fd is a pipe
- if @GetFileType.call(io) != FILE_TYPE_PIPE
- return false
- end
-
- bufsize = 1024
- p_buffer = "\0" * bufsize
- res = @GetFileInformationByHandleEx.call(io, FILE_NAME_INFO, p_buffer, bufsize - 2)
- return false if res == 0
-
- # get pipe name: p_buffer layout is:
- # struct _FILE_NAME_INFO {
- # DWORD FileNameLength;
- # WCHAR FileName[1];
- # } FILE_NAME_INFO
- 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')
- # or a cygwin pty pipe ('\cygwin-XXXX-ptyN-XX')
- name =~ /(msys-|cygwin-).*-pty/ ? true : false
- end
-
- 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] ],
- ]
-
- def 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
- # 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
-
- 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) and !key.control_keys.include?(:CTRL)
-
- @output_buf.concat(key.char.bytes)
- end
-
- def check_input_event
- num_of_events = 0.chr * 8
- while @output_buf.empty?
- Reline.core.line_editor.handle_signal
- 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 @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
- end
-
- def with_raw_input
- yield
- end
-
- def getc(_timeout_second)
- check_input_event
- @output_buf.shift
- end
-
- def ungetc(c)
- @output_buf.unshift(c)
- end
-
- def in_pasting?
- not empty_buffer?
- end
-
- def empty_buffer?
- if not @output_buf.empty?
- false
- elsif @kbhit.call == 0
- true
- else
- false
- end
- end
-
- def 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
- return if @GetConsoleScreenBufferInfo.call(@hConsoleHandle, csbi) == 0
- csbi
- end
-
- def get_screen_size
- unless csbi = get_console_screen_buffer_info
- return [1, 1]
- end
- csbi[0, 4].unpack('SS').reverse
- end
-
- def cursor_pos
- 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
-
- def move_cursor_column(val)
- @SetConsoleCursorPosition.call(@hConsoleHandle, cursor_pos.y * 65536 + val)
- end
-
- def move_cursor_up(val)
- if val > 0
- 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
- end
-
- def 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)
- end
- end
-
- def erase_after_cursor
- 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 scroll_down(val)
- return if val < 0
- return unless csbi = get_console_screen_buffer_info
- buffer_width, buffer_lines, x, y, 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 clear_screen
- 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 set_screen_size(rows, columns)
- raise NotImplementedError
- end
-
- def hide_cursor
- size = 100
- visible = 0 # 0 means false
- cursor_info = [size, visible].pack('Li')
- @SetConsoleCursorInfo.call(@hConsoleHandle, cursor_info)
- end
-
- def show_cursor
- size = 100
- visible = 1 # 1 means true
- cursor_info = [size, visible].pack('Li')
- @SetConsoleCursorInfo.call(@hConsoleHandle, cursor_info)
- end
-
- def set_winch_handler(&handler)
- @winch_handler = handler
- end
-
- def prep
- # do nothing
- nil
- end
-
- def 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/lib/reline/key_actor.rb b/lib/reline/key_actor.rb
deleted file mode 100644
index ebe09d2009..0000000000
--- a/lib/reline/key_actor.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-module Reline::KeyActor
-end
-
-require 'reline/key_actor/base'
-require 'reline/key_actor/emacs'
-require 'reline/key_actor/vi_command'
-require 'reline/key_actor/vi_insert'
diff --git a/lib/reline/key_actor/base.rb b/lib/reline/key_actor/base.rb
deleted file mode 100644
index 194e98938c..0000000000
--- a/lib/reline/key_actor/base.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-class Reline::KeyActor::Base
- MAPPING = Array.new(256)
-
- def get_method(key)
- self.class::MAPPING[key]
- end
-
- def initialize
- @default_key_bindings = {}
- end
-
- def default_key_bindings
- @default_key_bindings
- end
-end
diff --git a/lib/reline/key_actor/emacs.rb b/lib/reline/key_actor/emacs.rb
deleted file mode 100644
index d7354520b0..0000000000
--- a/lib/reline/key_actor/emacs.rb
+++ /dev/null
@@ -1,517 +0,0 @@
-class Reline::KeyActor::Emacs < Reline::KeyActor::Base
- MAPPING = [
- # 0 ^@
- :em_set_mark,
- # 1 ^A
- :ed_move_to_beg,
- # 2 ^B
- :ed_prev_char,
- # 3 ^C
- :ed_ignore,
- # 4 ^D
- :em_delete,
- # 5 ^E
- :ed_move_to_end,
- # 6 ^F
- :ed_next_char,
- # 7 ^G
- :ed_unassigned,
- # 8 ^H
- :em_delete_prev_char,
- # 9 ^I
- :complete,
- # 10 ^J
- :ed_newline,
- # 11 ^K
- :ed_kill_line,
- # 12 ^L
- :ed_clear_screen,
- # 13 ^M
- :ed_newline,
- # 14 ^N
- :ed_next_history,
- # 15 ^O
- :ed_ignore,
- # 16 ^P
- :ed_prev_history,
- # 17 ^Q
- :ed_quoted_insert,
- # 18 ^R
- :vi_search_prev,
- # 19 ^S
- :vi_search_next,
- # 20 ^T
- :ed_transpose_chars,
- # 21 ^U
- :unix_line_discard,
- # 22 ^V
- :ed_quoted_insert,
- # 23 ^W
- :em_kill_region,
- # 24 ^X
- :ed_unassigned,
- # 25 ^Y
- :em_yank,
- # 26 ^Z
- :ed_ignore,
- # 27 ^[
- :ed_unassigned,
- # 28 ^\
- :ed_ignore,
- # 29 ^]
- :ed_ignore,
- # 30 ^^
- :ed_unassigned,
- # 31 ^_
- :undo,
- # 32 SPACE
- :ed_insert,
- # 33 !
- :ed_insert,
- # 34 "
- :ed_insert,
- # 35 #
- :ed_insert,
- # 36 $
- :ed_insert,
- # 37 %
- :ed_insert,
- # 38 &
- :ed_insert,
- # 39 '
- :ed_insert,
- # 40 (
- :ed_insert,
- # 41 )
- :ed_insert,
- # 42 *
- :ed_insert,
- # 43 +
- :ed_insert,
- # 44 ,
- :ed_insert,
- # 45 -
- :ed_insert,
- # 46 .
- :ed_insert,
- # 47 /
- :ed_insert,
- # 48 0
- :ed_digit,
- # 49 1
- :ed_digit,
- # 50 2
- :ed_digit,
- # 51 3
- :ed_digit,
- # 52 4
- :ed_digit,
- # 53 5
- :ed_digit,
- # 54 6
- :ed_digit,
- # 55 7
- :ed_digit,
- # 56 8
- :ed_digit,
- # 57 9
- :ed_digit,
- # 58 :
- :ed_insert,
- # 59 ;
- :ed_insert,
- # 60 <
- :ed_insert,
- # 61 =
- :ed_insert,
- # 62 >
- :ed_insert,
- # 63 ?
- :ed_insert,
- # 64 @
- :ed_insert,
- # 65 A
- :ed_insert,
- # 66 B
- :ed_insert,
- # 67 C
- :ed_insert,
- # 68 D
- :ed_insert,
- # 69 E
- :ed_insert,
- # 70 F
- :ed_insert,
- # 71 G
- :ed_insert,
- # 72 H
- :ed_insert,
- # 73 I
- :ed_insert,
- # 74 J
- :ed_insert,
- # 75 K
- :ed_insert,
- # 76 L
- :ed_insert,
- # 77 M
- :ed_insert,
- # 78 N
- :ed_insert,
- # 79 O
- :ed_insert,
- # 80 P
- :ed_insert,
- # 81 Q
- :ed_insert,
- # 82 R
- :ed_insert,
- # 83 S
- :ed_insert,
- # 84 T
- :ed_insert,
- # 85 U
- :ed_insert,
- # 86 V
- :ed_insert,
- # 87 W
- :ed_insert,
- # 88 X
- :ed_insert,
- # 89 Y
- :ed_insert,
- # 90 Z
- :ed_insert,
- # 91 [
- :ed_insert,
- # 92 \
- :ed_insert,
- # 93 ]
- :ed_insert,
- # 94 ^
- :ed_insert,
- # 95 _
- :ed_insert,
- # 96 `
- :ed_insert,
- # 97 a
- :ed_insert,
- # 98 b
- :ed_insert,
- # 99 c
- :ed_insert,
- # 100 d
- :ed_insert,
- # 101 e
- :ed_insert,
- # 102 f
- :ed_insert,
- # 103 g
- :ed_insert,
- # 104 h
- :ed_insert,
- # 105 i
- :ed_insert,
- # 106 j
- :ed_insert,
- # 107 k
- :ed_insert,
- # 108 l
- :ed_insert,
- # 109 m
- :ed_insert,
- # 110 n
- :ed_insert,
- # 111 o
- :ed_insert,
- # 112 p
- :ed_insert,
- # 113 q
- :ed_insert,
- # 114 r
- :ed_insert,
- # 115 s
- :ed_insert,
- # 116 t
- :ed_insert,
- # 117 u
- :ed_insert,
- # 118 v
- :ed_insert,
- # 119 w
- :ed_insert,
- # 120 x
- :ed_insert,
- # 121 y
- :ed_insert,
- # 122 z
- :ed_insert,
- # 123 {
- :ed_insert,
- # 124 |
- :ed_insert,
- # 125 }
- :ed_insert,
- # 126 ~
- :ed_insert,
- # 127 ^?
- :em_delete_prev_char,
- # 128 M-^@
- :ed_unassigned,
- # 129 M-^A
- :ed_unassigned,
- # 130 M-^B
- :ed_unassigned,
- # 131 M-^C
- :ed_unassigned,
- # 132 M-^D
- :ed_unassigned,
- # 133 M-^E
- :ed_unassigned,
- # 134 M-^F
- :ed_unassigned,
- # 135 M-^G
- :ed_unassigned,
- # 136 M-^H
- :ed_delete_prev_word,
- # 137 M-^I
- :ed_unassigned,
- # 138 M-^J
- :key_newline,
- # 139 M-^K
- :ed_unassigned,
- # 140 M-^L
- :ed_clear_screen,
- # 141 M-^M
- :key_newline,
- # 142 M-^N
- :ed_unassigned,
- # 143 M-^O
- :ed_unassigned,
- # 144 M-^P
- :ed_unassigned,
- # 145 M-^Q
- :ed_unassigned,
- # 146 M-^R
- :ed_unassigned,
- # 147 M-^S
- :ed_unassigned,
- # 148 M-^T
- :ed_unassigned,
- # 149 M-^U
- :ed_unassigned,
- # 150 M-^V
- :ed_unassigned,
- # 151 M-^W
- :ed_unassigned,
- # 152 M-^X
- :ed_unassigned,
- # 153 M-^Y
- :em_yank_pop,
- # 154 M-^Z
- :ed_unassigned,
- # 155 M-^[
- :ed_unassigned,
- # 156 M-^\
- :ed_unassigned,
- # 157 M-^]
- :ed_unassigned,
- # 158 M-^^
- :ed_unassigned,
- # 159 M-^_
- :redo,
- # 160 M-SPACE
- :em_set_mark,
- # 161 M-!
- :ed_unassigned,
- # 162 M-"
- :ed_unassigned,
- # 163 M-#
- :ed_unassigned,
- # 164 M-$
- :ed_unassigned,
- # 165 M-%
- :ed_unassigned,
- # 166 M-&
- :ed_unassigned,
- # 167 M-'
- :ed_unassigned,
- # 168 M-(
- :ed_unassigned,
- # 169 M-)
- :ed_unassigned,
- # 170 M-*
- :ed_unassigned,
- # 171 M-+
- :ed_unassigned,
- # 172 M-,
- :ed_unassigned,
- # 173 M--
- :ed_unassigned,
- # 174 M-.
- :ed_unassigned,
- # 175 M-/
- :ed_unassigned,
- # 176 M-0
- :ed_argument_digit,
- # 177 M-1
- :ed_argument_digit,
- # 178 M-2
- :ed_argument_digit,
- # 179 M-3
- :ed_argument_digit,
- # 180 M-4
- :ed_argument_digit,
- # 181 M-5
- :ed_argument_digit,
- # 182 M-6
- :ed_argument_digit,
- # 183 M-7
- :ed_argument_digit,
- # 184 M-8
- :ed_argument_digit,
- # 185 M-9
- :ed_argument_digit,
- # 186 M-:
- :ed_unassigned,
- # 187 M-;
- :ed_unassigned,
- # 188 M-<
- :ed_unassigned,
- # 189 M-=
- :ed_unassigned,
- # 190 M->
- :ed_unassigned,
- # 191 M-?
- :ed_unassigned,
- # 192 M-@
- :ed_unassigned,
- # 193 M-A
- :ed_unassigned,
- # 194 M-B
- :ed_prev_word,
- # 195 M-C
- :em_capitol_case,
- # 196 M-D
- :em_delete_next_word,
- # 197 M-E
- :ed_unassigned,
- # 198 M-F
- :em_next_word,
- # 199 M-G
- :ed_unassigned,
- # 200 M-H
- :ed_unassigned,
- # 201 M-I
- :ed_unassigned,
- # 202 M-J
- :ed_unassigned,
- # 203 M-K
- :ed_unassigned,
- # 204 M-L
- :em_lower_case,
- # 205 M-M
- :ed_unassigned,
- # 206 M-N
- :vi_search_next,
- # 207 M-O
- :ed_unassigned,
- # 208 M-P
- :vi_search_prev,
- # 209 M-Q
- :ed_unassigned,
- # 210 M-R
- :ed_unassigned,
- # 211 M-S
- :ed_unassigned,
- # 212 M-T
- :ed_unassigned,
- # 213 M-U
- :em_upper_case,
- # 214 M-V
- :ed_unassigned,
- # 215 M-W
- :ed_unassigned,
- # 216 M-X
- :ed_unassigned,
- # 217 M-Y
- :em_yank_pop,
- # 218 M-Z
- :ed_unassigned,
- # 219 M-[
- :ed_unassigned,
- # 220 M-\
- :ed_unassigned,
- # 221 M-]
- :ed_unassigned,
- # 222 M-^
- :ed_unassigned,
- # 223 M-_
- :ed_unassigned,
- # 224 M-`
- :ed_unassigned,
- # 225 M-a
- :ed_unassigned,
- # 226 M-b
- :ed_prev_word,
- # 227 M-c
- :em_capitol_case,
- # 228 M-d
- :em_delete_next_word,
- # 229 M-e
- :ed_unassigned,
- # 230 M-f
- :em_next_word,
- # 231 M-g
- :ed_unassigned,
- # 232 M-h
- :ed_unassigned,
- # 233 M-i
- :ed_unassigned,
- # 234 M-j
- :ed_unassigned,
- # 235 M-k
- :ed_unassigned,
- # 236 M-l
- :em_lower_case,
- # 237 M-m
- :ed_unassigned,
- # 238 M-n
- :vi_search_next,
- # 239 M-o
- :ed_unassigned,
- # 240 M-p
- :vi_search_prev,
- # 241 M-q
- :ed_unassigned,
- # 242 M-r
- :ed_unassigned,
- # 243 M-s
- :ed_unassigned,
- # 244 M-t
- :ed_transpose_words,
- # 245 M-u
- :em_upper_case,
- # 246 M-v
- :ed_unassigned,
- # 247 M-w
- :ed_unassigned,
- # 248 M-x
- :ed_unassigned,
- # 249 M-y
- :ed_unassigned,
- # 250 M-z
- :ed_unassigned,
- # 251 M-{
- :ed_unassigned,
- # 252 M-|
- :ed_unassigned,
- # 253 M-}
- :ed_unassigned,
- # 254 M-~
- :ed_unassigned,
- # 255 M-^?
- :ed_delete_prev_word
- # EOF
- ]
-end
diff --git a/lib/reline/key_actor/vi_command.rb b/lib/reline/key_actor/vi_command.rb
deleted file mode 100644
index 06bb0ba8e4..0000000000
--- a/lib/reline/key_actor/vi_command.rb
+++ /dev/null
@@ -1,518 +0,0 @@
-class Reline::KeyActor::ViCommand < Reline::KeyActor::Base
- MAPPING = [
- # 0 ^@
- :ed_unassigned,
- # 1 ^A
- :ed_move_to_beg,
- # 2 ^B
- :ed_unassigned,
- # 3 ^C
- :ed_ignore,
- # 4 ^D
- :vi_end_of_transmission,
- # 5 ^E
- :ed_move_to_end,
- # 6 ^F
- :ed_unassigned,
- # 7 ^G
- :ed_unassigned,
- # 8 ^H
- :ed_prev_char,
- # 9 ^I
- :ed_unassigned,
- # 10 ^J
- :ed_newline,
- # 11 ^K
- :ed_kill_line,
- # 12 ^L
- :ed_clear_screen,
- # 13 ^M
- :ed_newline,
- # 14 ^N
- :ed_next_history,
- # 15 ^O
- :ed_ignore,
- # 16 ^P
- :ed_prev_history,
- # 17 ^Q
- :ed_ignore,
- # 18 ^R
- :vi_search_prev,
- # 19 ^S
- :ed_ignore,
- # 20 ^T
- :ed_transpose_chars,
- # 21 ^U
- :vi_kill_line_prev,
- # 22 ^V
- :ed_quoted_insert,
- # 23 ^W
- :ed_delete_prev_word,
- # 24 ^X
- :ed_unassigned,
- # 25 ^Y
- :em_yank,
- # 26 ^Z
- :ed_unassigned,
- # 27 ^[
- :ed_unassigned,
- # 28 ^\
- :ed_ignore,
- # 29 ^]
- :ed_unassigned,
- # 30 ^^
- :ed_unassigned,
- # 31 ^_
- :ed_unassigned,
- # 32 SPACE
- :ed_next_char,
- # 33 !
- :ed_unassigned,
- # 34 "
- :ed_unassigned,
- # 35 #
- :vi_comment_out,
- # 36 $
- :ed_move_to_end,
- # 37 %
- :ed_unassigned,
- # 38 &
- :ed_unassigned,
- # 39 '
- :ed_unassigned,
- # 40 (
- :ed_unassigned,
- # 41 )
- :ed_unassigned,
- # 42 *
- :ed_unassigned,
- # 43 +
- :ed_next_history,
- # 44 ,
- :ed_unassigned,
- # 45 -
- :ed_prev_history,
- # 46 .
- :ed_unassigned,
- # 47 /
- :vi_search_prev,
- # 48 0
- :vi_zero,
- # 49 1
- :ed_argument_digit,
- # 50 2
- :ed_argument_digit,
- # 51 3
- :ed_argument_digit,
- # 52 4
- :ed_argument_digit,
- # 53 5
- :ed_argument_digit,
- # 54 6
- :ed_argument_digit,
- # 55 7
- :ed_argument_digit,
- # 56 8
- :ed_argument_digit,
- # 57 9
- :ed_argument_digit,
- # 58 :
- :ed_unassigned,
- # 59 ;
- :ed_unassigned,
- # 60 <
- :ed_unassigned,
- # 61 =
- :ed_unassigned,
- # 62 >
- :ed_unassigned,
- # 63 ?
- :vi_search_next,
- # 64 @
- :vi_alias,
- # 65 A
- :vi_add_at_eol,
- # 66 B
- :vi_prev_big_word,
- # 67 C
- :vi_change_to_eol,
- # 68 D
- :ed_kill_line,
- # 69 E
- :vi_end_big_word,
- # 70 F
- :vi_prev_char,
- # 71 G
- :vi_to_history_line,
- # 72 H
- :ed_unassigned,
- # 73 I
- :vi_insert_at_bol,
- # 74 J
- :vi_join_lines,
- # 75 K
- :vi_search_prev,
- # 76 L
- :ed_unassigned,
- # 77 M
- :ed_unassigned,
- # 78 N
- :ed_unassigned,
- # 79 O
- :ed_unassigned,
- # 80 P
- :vi_paste_prev,
- # 81 Q
- :ed_unassigned,
- # 82 R
- :ed_unassigned,
- # 83 S
- :ed_unassigned,
- # 84 T
- :vi_to_prev_char,
- # 85 U
- :ed_unassigned,
- # 86 V
- :ed_unassigned,
- # 87 W
- :vi_next_big_word,
- # 88 X
- :ed_delete_prev_char,
- # 89 Y
- :ed_unassigned,
- # 90 Z
- :ed_unassigned,
- # 91 [
- :ed_unassigned,
- # 92 \
- :ed_unassigned,
- # 93 ]
- :ed_unassigned,
- # 94 ^
- :vi_first_print,
- # 95 _
- :ed_unassigned,
- # 96 `
- :ed_unassigned,
- # 97 a
- :vi_add,
- # 98 b
- :vi_prev_word,
- # 99 c
- :vi_change_meta,
- # 100 d
- :vi_delete_meta,
- # 101 e
- :vi_end_word,
- # 102 f
- :vi_next_char,
- # 103 g
- :ed_unassigned,
- # 104 h
- :ed_prev_char,
- # 105 i
- :vi_insert,
- # 106 j
- :ed_next_history,
- # 107 k
- :ed_prev_history,
- # 108 l
- :ed_next_char,
- # 109 m
- :ed_unassigned,
- # 110 n
- :ed_unassigned,
- # 111 o
- :ed_unassigned,
- # 112 p
- :vi_paste_next,
- # 113 q
- :ed_unassigned,
- # 114 r
- :vi_replace_char,
- # 115 s
- :ed_unassigned,
- # 116 t
- :vi_to_next_char,
- # 117 u
- :ed_unassigned,
- # 118 v
- :vi_histedit,
- # 119 w
- :vi_next_word,
- # 120 x
- :ed_delete_next_char,
- # 121 y
- :vi_yank,
- # 122 z
- :ed_unassigned,
- # 123 {
- :ed_unassigned,
- # 124 |
- :vi_to_column,
- # 125 }
- :ed_unassigned,
- # 126 ~
- :ed_unassigned,
- # 127 ^?
- :em_delete_prev_char,
- # 128 M-^@
- :ed_unassigned,
- # 129 M-^A
- :ed_unassigned,
- # 130 M-^B
- :ed_unassigned,
- # 131 M-^C
- :ed_unassigned,
- # 132 M-^D
- :ed_unassigned,
- # 133 M-^E
- :ed_unassigned,
- # 134 M-^F
- :ed_unassigned,
- # 135 M-^G
- :ed_unassigned,
- # 136 M-^H
- :ed_unassigned,
- # 137 M-^I
- :ed_unassigned,
- # 138 M-^J
- :ed_unassigned,
- # 139 M-^K
- :ed_unassigned,
- # 140 M-^L
- :ed_unassigned,
- # 141 M-^M
- :ed_unassigned,
- # 142 M-^N
- :ed_unassigned,
- # 143 M-^O
- :ed_unassigned,
- # 144 M-^P
- :ed_unassigned,
- # 145 M-^Q
- :ed_unassigned,
- # 146 M-^R
- :ed_unassigned,
- # 147 M-^S
- :ed_unassigned,
- # 148 M-^T
- :ed_unassigned,
- # 149 M-^U
- :ed_unassigned,
- # 150 M-^V
- :ed_unassigned,
- # 151 M-^W
- :ed_unassigned,
- # 152 M-^X
- :ed_unassigned,
- # 153 M-^Y
- :ed_unassigned,
- # 154 M-^Z
- :ed_unassigned,
- # 155 M-^[
- :ed_unassigned,
- # 156 M-^\
- :ed_unassigned,
- # 157 M-^]
- :ed_unassigned,
- # 158 M-^^
- :ed_unassigned,
- # 159 M-^_
- :ed_unassigned,
- # 160 M-SPACE
- :ed_unassigned,
- # 161 M-!
- :ed_unassigned,
- # 162 M-"
- :ed_unassigned,
- # 163 M-#
- :ed_unassigned,
- # 164 M-$
- :ed_unassigned,
- # 165 M-%
- :ed_unassigned,
- # 166 M-&
- :ed_unassigned,
- # 167 M-'
- :ed_unassigned,
- # 168 M-(
- :ed_unassigned,
- # 169 M-)
- :ed_unassigned,
- # 170 M-*
- :ed_unassigned,
- # 171 M-+
- :ed_unassigned,
- # 172 M-,
- :ed_unassigned,
- # 173 M--
- :ed_unassigned,
- # 174 M-.
- :ed_unassigned,
- # 175 M-/
- :ed_unassigned,
- # 176 M-0
- :ed_unassigned,
- # 177 M-1
- :ed_unassigned,
- # 178 M-2
- :ed_unassigned,
- # 179 M-3
- :ed_unassigned,
- # 180 M-4
- :ed_unassigned,
- # 181 M-5
- :ed_unassigned,
- # 182 M-6
- :ed_unassigned,
- # 183 M-7
- :ed_unassigned,
- # 184 M-8
- :ed_unassigned,
- # 185 M-9
- :ed_unassigned,
- # 186 M-:
- :ed_unassigned,
- # 187 M-;
- :ed_unassigned,
- # 188 M-<
- :ed_unassigned,
- # 189 M-=
- :ed_unassigned,
- # 190 M->
- :ed_unassigned,
- # 191 M-?
- :ed_unassigned,
- # 192 M-@
- :ed_unassigned,
- # 193 M-A
- :ed_unassigned,
- # 194 M-B
- :ed_unassigned,
- # 195 M-C
- :ed_unassigned,
- # 196 M-D
- :ed_unassigned,
- # 197 M-E
- :ed_unassigned,
- # 198 M-F
- :ed_unassigned,
- # 199 M-G
- :ed_unassigned,
- # 200 M-H
- :ed_unassigned,
- # 201 M-I
- :ed_unassigned,
- # 202 M-J
- :ed_unassigned,
- # 203 M-K
- :ed_unassigned,
- # 204 M-L
- :ed_unassigned,
- # 205 M-M
- :ed_unassigned,
- # 206 M-N
- :ed_unassigned,
- # 207 M-O
- :ed_unassigned,
- # 208 M-P
- :ed_unassigned,
- # 209 M-Q
- :ed_unassigned,
- # 210 M-R
- :ed_unassigned,
- # 211 M-S
- :ed_unassigned,
- # 212 M-T
- :ed_unassigned,
- # 213 M-U
- :ed_unassigned,
- # 214 M-V
- :ed_unassigned,
- # 215 M-W
- :ed_unassigned,
- # 216 M-X
- :ed_unassigned,
- # 217 M-Y
- :ed_unassigned,
- # 218 M-Z
- :ed_unassigned,
- # 219 M-[
- :ed_unassigned,
- # 220 M-\
- :ed_unassigned,
- # 221 M-]
- :ed_unassigned,
- # 222 M-^
- :ed_unassigned,
- # 223 M-_
- :ed_unassigned,
- # 224 M-`
- :ed_unassigned,
- # 225 M-a
- :ed_unassigned,
- # 226 M-b
- :ed_unassigned,
- # 227 M-c
- :ed_unassigned,
- # 228 M-d
- :ed_unassigned,
- # 229 M-e
- :ed_unassigned,
- # 230 M-f
- :ed_unassigned,
- # 231 M-g
- :ed_unassigned,
- # 232 M-h
- :ed_unassigned,
- # 233 M-i
- :ed_unassigned,
- # 234 M-j
- :ed_unassigned,
- # 235 M-k
- :ed_unassigned,
- # 236 M-l
- :ed_unassigned,
- # 237 M-m
- :ed_unassigned,
- # 238 M-n
- :ed_unassigned,
- # 239 M-o
- :ed_unassigned,
- # 240 M-p
- :ed_unassigned,
- # 241 M-q
- :ed_unassigned,
- # 242 M-r
- :ed_unassigned,
- # 243 M-s
- :ed_unassigned,
- # 244 M-t
- :ed_unassigned,
- # 245 M-u
- :ed_unassigned,
- # 246 M-v
- :ed_unassigned,
- # 247 M-w
- :ed_unassigned,
- # 248 M-x
- :ed_unassigned,
- # 249 M-y
- :ed_unassigned,
- # 250 M-z
- :ed_unassigned,
- # 251 M-{
- :ed_unassigned,
- # 252 M-|
- :ed_unassigned,
- # 253 M-}
- :ed_unassigned,
- # 254 M-~
- :ed_unassigned,
- # 255 M-^?
- :ed_unassigned
- # EOF
- ]
-end
-
diff --git a/lib/reline/key_actor/vi_insert.rb b/lib/reline/key_actor/vi_insert.rb
deleted file mode 100644
index f8ccf468c6..0000000000
--- a/lib/reline/key_actor/vi_insert.rb
+++ /dev/null
@@ -1,517 +0,0 @@
-class Reline::KeyActor::ViInsert < Reline::KeyActor::Base
- MAPPING = [
- # 0 ^@
- :ed_unassigned,
- # 1 ^A
- :ed_insert,
- # 2 ^B
- :ed_insert,
- # 3 ^C
- :ed_insert,
- # 4 ^D
- :vi_list_or_eof,
- # 5 ^E
- :ed_insert,
- # 6 ^F
- :ed_insert,
- # 7 ^G
- :ed_insert,
- # 8 ^H
- :vi_delete_prev_char,
- # 9 ^I
- :complete,
- # 10 ^J
- :ed_newline,
- # 11 ^K
- :ed_insert,
- # 12 ^L
- :ed_insert,
- # 13 ^M
- :ed_newline,
- # 14 ^N
- :menu_complete,
- # 15 ^O
- :ed_insert,
- # 16 ^P
- :menu_complete_backward,
- # 17 ^Q
- :ed_ignore,
- # 18 ^R
- :vi_search_prev,
- # 19 ^S
- :vi_search_next,
- # 20 ^T
- :ed_transpose_chars,
- # 21 ^U
- :vi_kill_line_prev,
- # 22 ^V
- :ed_quoted_insert,
- # 23 ^W
- :ed_delete_prev_word,
- # 24 ^X
- :ed_insert,
- # 25 ^Y
- :em_yank,
- # 26 ^Z
- :ed_insert,
- # 27 ^[
- :vi_command_mode,
- # 28 ^\
- :ed_ignore,
- # 29 ^]
- :ed_insert,
- # 30 ^^
- :ed_insert,
- # 31 ^_
- :ed_insert,
- # 32 SPACE
- :ed_insert,
- # 33 !
- :ed_insert,
- # 34 "
- :ed_insert,
- # 35 #
- :ed_insert,
- # 36 $
- :ed_insert,
- # 37 %
- :ed_insert,
- # 38 &
- :ed_insert,
- # 39 '
- :ed_insert,
- # 40 (
- :ed_insert,
- # 41 )
- :ed_insert,
- # 42 *
- :ed_insert,
- # 43 +
- :ed_insert,
- # 44 ,
- :ed_insert,
- # 45 -
- :ed_insert,
- # 46 .
- :ed_insert,
- # 47 /
- :ed_insert,
- # 48 0
- :ed_insert,
- # 49 1
- :ed_insert,
- # 50 2
- :ed_insert,
- # 51 3
- :ed_insert,
- # 52 4
- :ed_insert,
- # 53 5
- :ed_insert,
- # 54 6
- :ed_insert,
- # 55 7
- :ed_insert,
- # 56 8
- :ed_insert,
- # 57 9
- :ed_insert,
- # 58 :
- :ed_insert,
- # 59 ;
- :ed_insert,
- # 60 <
- :ed_insert,
- # 61 =
- :ed_insert,
- # 62 >
- :ed_insert,
- # 63 ?
- :ed_insert,
- # 64 @
- :ed_insert,
- # 65 A
- :ed_insert,
- # 66 B
- :ed_insert,
- # 67 C
- :ed_insert,
- # 68 D
- :ed_insert,
- # 69 E
- :ed_insert,
- # 70 F
- :ed_insert,
- # 71 G
- :ed_insert,
- # 72 H
- :ed_insert,
- # 73 I
- :ed_insert,
- # 74 J
- :ed_insert,
- # 75 K
- :ed_insert,
- # 76 L
- :ed_insert,
- # 77 M
- :ed_insert,
- # 78 N
- :ed_insert,
- # 79 O
- :ed_insert,
- # 80 P
- :ed_insert,
- # 81 Q
- :ed_insert,
- # 82 R
- :ed_insert,
- # 83 S
- :ed_insert,
- # 84 T
- :ed_insert,
- # 85 U
- :ed_insert,
- # 86 V
- :ed_insert,
- # 87 W
- :ed_insert,
- # 88 X
- :ed_insert,
- # 89 Y
- :ed_insert,
- # 90 Z
- :ed_insert,
- # 91 [
- :ed_insert,
- # 92 \
- :ed_insert,
- # 93 ]
- :ed_insert,
- # 94 ^
- :ed_insert,
- # 95 _
- :ed_insert,
- # 96 `
- :ed_insert,
- # 97 a
- :ed_insert,
- # 98 b
- :ed_insert,
- # 99 c
- :ed_insert,
- # 100 d
- :ed_insert,
- # 101 e
- :ed_insert,
- # 102 f
- :ed_insert,
- # 103 g
- :ed_insert,
- # 104 h
- :ed_insert,
- # 105 i
- :ed_insert,
- # 106 j
- :ed_insert,
- # 107 k
- :ed_insert,
- # 108 l
- :ed_insert,
- # 109 m
- :ed_insert,
- # 110 n
- :ed_insert,
- # 111 o
- :ed_insert,
- # 112 p
- :ed_insert,
- # 113 q
- :ed_insert,
- # 114 r
- :ed_insert,
- # 115 s
- :ed_insert,
- # 116 t
- :ed_insert,
- # 117 u
- :ed_insert,
- # 118 v
- :ed_insert,
- # 119 w
- :ed_insert,
- # 120 x
- :ed_insert,
- # 121 y
- :ed_insert,
- # 122 z
- :ed_insert,
- # 123 {
- :ed_insert,
- # 124 |
- :ed_insert,
- # 125 }
- :ed_insert,
- # 126 ~
- :ed_insert,
- # 127 ^?
- :vi_delete_prev_char,
- # 128 M-^@
- :ed_unassigned,
- # 129 M-^A
- :ed_unassigned,
- # 130 M-^B
- :ed_unassigned,
- # 131 M-^C
- :ed_unassigned,
- # 132 M-^D
- :ed_unassigned,
- # 133 M-^E
- :ed_unassigned,
- # 134 M-^F
- :ed_unassigned,
- # 135 M-^G
- :ed_unassigned,
- # 136 M-^H
- :ed_unassigned,
- # 137 M-^I
- :ed_unassigned,
- # 138 M-^J
- :key_newline,
- # 139 M-^K
- :ed_unassigned,
- # 140 M-^L
- :ed_unassigned,
- # 141 M-^M
- :key_newline,
- # 142 M-^N
- :ed_unassigned,
- # 143 M-^O
- :ed_unassigned,
- # 144 M-^P
- :ed_unassigned,
- # 145 M-^Q
- :ed_unassigned,
- # 146 M-^R
- :ed_unassigned,
- # 147 M-^S
- :ed_unassigned,
- # 148 M-^T
- :ed_unassigned,
- # 149 M-^U
- :ed_unassigned,
- # 150 M-^V
- :ed_unassigned,
- # 151 M-^W
- :ed_unassigned,
- # 152 M-^X
- :ed_unassigned,
- # 153 M-^Y
- :ed_unassigned,
- # 154 M-^Z
- :ed_unassigned,
- # 155 M-^[
- :ed_unassigned,
- # 156 M-^\
- :ed_unassigned,
- # 157 M-^]
- :ed_unassigned,
- # 158 M-^^
- :ed_unassigned,
- # 159 M-^_
- :ed_unassigned,
- # 160 M-SPACE
- :ed_unassigned,
- # 161 M-!
- :ed_unassigned,
- # 162 M-"
- :ed_unassigned,
- # 163 M-#
- :ed_unassigned,
- # 164 M-$
- :ed_unassigned,
- # 165 M-%
- :ed_unassigned,
- # 166 M-&
- :ed_unassigned,
- # 167 M-'
- :ed_unassigned,
- # 168 M-(
- :ed_unassigned,
- # 169 M-)
- :ed_unassigned,
- # 170 M-*
- :ed_unassigned,
- # 171 M-+
- :ed_unassigned,
- # 172 M-,
- :ed_unassigned,
- # 173 M--
- :ed_unassigned,
- # 174 M-.
- :ed_unassigned,
- # 175 M-/
- :ed_unassigned,
- # 176 M-0
- :ed_unassigned,
- # 177 M-1
- :ed_unassigned,
- # 178 M-2
- :ed_unassigned,
- # 179 M-3
- :ed_unassigned,
- # 180 M-4
- :ed_unassigned,
- # 181 M-5
- :ed_unassigned,
- # 182 M-6
- :ed_unassigned,
- # 183 M-7
- :ed_unassigned,
- # 184 M-8
- :ed_unassigned,
- # 185 M-9
- :ed_unassigned,
- # 186 M-:
- :ed_unassigned,
- # 187 M-;
- :ed_unassigned,
- # 188 M-<
- :ed_unassigned,
- # 189 M-=
- :ed_unassigned,
- # 190 M->
- :ed_unassigned,
- # 191 M-?
- :ed_unassigned,
- # 192 M-@
- :ed_unassigned,
- # 193 M-A
- :ed_unassigned,
- # 194 M-B
- :ed_unassigned,
- # 195 M-C
- :ed_unassigned,
- # 196 M-D
- :ed_unassigned,
- # 197 M-E
- :ed_unassigned,
- # 198 M-F
- :ed_unassigned,
- # 199 M-G
- :ed_unassigned,
- # 200 M-H
- :ed_unassigned,
- # 201 M-I
- :ed_unassigned,
- # 202 M-J
- :ed_unassigned,
- # 203 M-K
- :ed_unassigned,
- # 204 M-L
- :ed_unassigned,
- # 205 M-M
- :ed_unassigned,
- # 206 M-N
- :ed_unassigned,
- # 207 M-O
- :ed_unassigned,
- # 208 M-P
- :ed_unassigned,
- # 209 M-Q
- :ed_unassigned,
- # 210 M-R
- :ed_unassigned,
- # 211 M-S
- :ed_unassigned,
- # 212 M-T
- :ed_unassigned,
- # 213 M-U
- :ed_unassigned,
- # 214 M-V
- :ed_unassigned,
- # 215 M-W
- :ed_unassigned,
- # 216 M-X
- :ed_unassigned,
- # 217 M-Y
- :ed_unassigned,
- # 218 M-Z
- :ed_unassigned,
- # 219 M-[
- :ed_unassigned,
- # 220 M-\
- :ed_unassigned,
- # 221 M-]
- :ed_unassigned,
- # 222 M-^
- :ed_unassigned,
- # 223 M-_
- :ed_unassigned,
- # 224 M-`
- :ed_unassigned,
- # 225 M-a
- :ed_unassigned,
- # 226 M-b
- :ed_unassigned,
- # 227 M-c
- :ed_unassigned,
- # 228 M-d
- :ed_unassigned,
- # 229 M-e
- :ed_unassigned,
- # 230 M-f
- :ed_unassigned,
- # 231 M-g
- :ed_unassigned,
- # 232 M-h
- :ed_unassigned,
- # 233 M-i
- :ed_unassigned,
- # 234 M-j
- :ed_unassigned,
- # 235 M-k
- :ed_unassigned,
- # 236 M-l
- :ed_unassigned,
- # 237 M-m
- :ed_unassigned,
- # 238 M-n
- :ed_unassigned,
- # 239 M-o
- :ed_unassigned,
- # 240 M-p
- :ed_unassigned,
- # 241 M-q
- :ed_unassigned,
- # 242 M-r
- :ed_unassigned,
- # 243 M-s
- :ed_unassigned,
- # 244 M-t
- :ed_unassigned,
- # 245 M-u
- :ed_unassigned,
- # 246 M-v
- :ed_unassigned,
- # 247 M-w
- :ed_unassigned,
- # 248 M-x
- :ed_unassigned,
- # 249 M-y
- :ed_unassigned,
- # 250 M-z
- :ed_unassigned,
- # 251 M-{
- :ed_unassigned,
- # 252 M-|
- :ed_unassigned,
- # 253 M-}
- :ed_unassigned,
- # 254 M-~
- :ed_unassigned,
- # 255 M-^?
- :ed_unassigned
- # EOF
- ]
-end
diff --git a/lib/reline/key_stroke.rb b/lib/reline/key_stroke.rb
deleted file mode 100644
index bceffbb53f..0000000000
--- a/lib/reline/key_stroke.rb
+++ /dev/null
@@ -1,148 +0,0 @@
-class Reline::KeyStroke
- ESC_BYTE = 27
- CSI_PARAMETER_BYTES_RANGE = 0x30..0x3f
- CSI_INTERMEDIATE_BYTES_RANGE = (0x20..0x2f)
-
- 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 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 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|
- start_with?(lhs, input)
- }.tap { |it|
- 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
- }
- if key_mapping.keys.any? { |lhs| start_with?(input, lhs) }
- :matched
- else
- match_unknown_escape_sequence(input).first
- end
- end
-
- def expand(input)
- lhs = key_mapping.keys.select { |item| start_with?(input, item) }.sort_by(&:size).last
- unless lhs
- status, size = match_unknown_escape_sequence(input)
- case status
- when :matched
- return [:ed_unassigned] + expand(input.drop(size))
- when :matching
- return [:ed_unassigned]
- else
- return input
- end
- end
- rhs = key_mapping[lhs]
-
- case rhs
- when String
- rhs_bytes = rhs.bytes
- expand(expand(rhs_bytes) + expand(input.drop(lhs.size)))
- when Symbol
- [rhs] + expand(input.drop(lhs.size))
- when Array
- rhs
- end
- end
-
- private
-
- # returns match status of CSI/SS3 sequence and matched length
- def match_unknown_escape_sequence(input)
- idx = 0
- return [:unmatched, nil] unless input[idx] == ESC_BYTE
- idx += 1
- idx += 1 if input[idx] == ESC_BYTE
-
- case input[idx]
- when nil
- return [:matching, nil]
- when 91 # == '['.ord
- # CSI sequence
- idx += 1
- idx += 1 while idx < input.size && CSI_PARAMETER_BYTES_RANGE.cover?(input[idx])
- idx += 1 while idx < input.size && CSI_INTERMEDIATE_BYTES_RANGE.cover?(input[idx])
- input[idx] ? [:matched, idx + 1] : [:matching, nil]
- when 79 # == 'O'.ord
- # SS3 sequence
- input[idx + 1] ? [:matched, idx + 2] : [:matching, nil]
- else
- if idx == 1
- # `ESC char`, make it :unmatched so that it will be handled correctly in `read_2nd_character_of_key_sequence`
- [:unmatched, nil]
- else
- # `ESC ESC char`
- [:matched, idx + 1]
- end
- end
- end
-
- def key_mapping
- @config.key_bindings
- end
-end
diff --git a/lib/reline/kill_ring.rb b/lib/reline/kill_ring.rb
deleted file mode 100644
index 201f6f3ca0..0000000000
--- a/lib/reline/kill_ring.rb
+++ /dev/null
@@ -1,125 +0,0 @@
-class Reline::KillRing
- include Enumerable
-
- module State
- FRESH = :fresh
- CONTINUED = :continued
- PROCESSED = :processed
- YANK = :yank
- end
-
- RingPoint = Struct.new(:backward, :forward, :str) do
- def initialize(str)
- super(nil, nil, str)
- end
-
- def ==(other)
- equal?(other)
- end
- end
-
- class RingBuffer
- attr_reader :size
- attr_reader :head
-
- def initialize(max = 1024)
- @max = max
- @size = 0
- @head = nil # reading head of ring-shaped tape
- end
-
- def <<(point)
- if @size.zero?
- @head = point
- @head.backward = @head
- @head.forward = @head
- @size = 1
- elsif @size >= @max
- tail = @head.forward
- new_tail = tail.forward
- @head.forward = point
- point.backward = @head
- new_tail.backward = point
- point.forward = new_tail
- @head = point
- else
- tail = @head.forward
- @head.forward = point
- point.backward = @head
- tail.backward = point
- point.forward = tail
- @head = point
- @size += 1
- end
- end
-
- def empty?
- @size.zero?
- end
- end
-
- def initialize(max = 1024)
- @ring = RingBuffer.new(max)
- @ring_pointer = nil
- @buffer = nil
- @state = State::FRESH
- end
-
- def append(string, before_p = false)
- case @state
- when State::FRESH, State::YANK
- @ring << RingPoint.new(+string)
- @state = State::CONTINUED
- when State::CONTINUED, State::PROCESSED
- if before_p
- @ring.head.str.prepend(string)
- else
- @ring.head.str.concat(string)
- end
- @state = State::CONTINUED
- end
- end
-
- def process
- case @state
- when State::FRESH
- # nothing to do
- when State::CONTINUED
- @state = State::PROCESSED
- when State::PROCESSED
- @state = State::FRESH
- when State::YANK
- # nothing to do
- end
- end
-
- def yank
- unless @ring.empty?
- @state = State::YANK
- @ring_pointer = @ring.head
- @ring_pointer.str
- else
- nil
- end
- end
-
- def yank_pop
- if @state == State::YANK
- prev_yank = @ring_pointer.str
- @ring_pointer = @ring_pointer.backward
- [@ring_pointer.str, prev_yank]
- else
- 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/lib/reline/line_editor.rb b/lib/reline/line_editor.rb
deleted file mode 100644
index c2f5f0622e..0000000000
--- a/lib/reline/line_editor.rb
+++ /dev/null
@@ -1,2554 +0,0 @@
-require 'reline/kill_ring'
-require 'reline/unicode'
-
-require 'tempfile'
-
-class Reline::LineEditor
- # TODO: Use "private alias_method" idiom after drop Ruby 2.5.
- attr_reader :byte_pointer
- attr_accessor :confirm_multiline_termination_proc
- attr_accessor :completion_proc
- attr_accessor :completion_append_character
- attr_accessor :output_modifier_proc
- attr_accessor :prompt_proc
- attr_accessor :auto_indent_proc
- attr_accessor :dig_perfect_match_proc
- attr_writer :output
-
- VI_MOTIONS = %i{
- ed_prev_char
- ed_next_char
- vi_zero
- ed_move_to_beg
- ed_move_to_end
- vi_to_column
- vi_next_char
- vi_prev_char
- vi_next_word
- vi_prev_word
- vi_to_next_char
- vi_to_prev_char
- vi_end_word
- vi_next_big_word
- vi_prev_big_word
- vi_end_big_word
- }
-
- module CompletionState
- NORMAL = :normal
- COMPLETION = :completion
- MENU = :menu
- MENU_WITH_PERFECT_MATCH = :menu_with_perfect_match
- PERFECT_MATCH = :perfect_match
- end
-
- RenderedScreen = Struct.new(:base_y, :lines, :cursor_y, keyword_init: true)
-
- CompletionJourneyState = Struct.new(:line_index, :pre, :target, :post, :list, :pointer)
-
- class MenuInfo
- attr_reader :list
-
- def initialize(list)
- @list = list
- end
-
- def lines(screen_width)
- return [] if @list.empty?
-
- list = @list.sort
- sizes = list.map { |item| Reline::Unicode.calculate_width(item) }
- item_width = sizes.max + 2
- num_cols = [screen_width / item_width, 1].max
- num_rows = list.size.fdiv(num_cols).ceil
- list_with_padding = list.zip(sizes).map { |item, size| item + ' ' * (item_width - size) }
- aligned = (list_with_padding + [nil] * (num_rows * num_cols - list_with_padding.size)).each_slice(num_rows).to_a.transpose
- aligned.map do |row|
- row.join.rstrip
- end
- end
- end
-
- MINIMUM_SCROLLBAR_HEIGHT = 1
-
- def initialize(config, encoding)
- @config = config
- @completion_append_character = ''
- @screen_size = [0, 0] # Should be initialized with actual winsize in LineEditor#reset
- reset_variables(encoding: encoding)
- end
-
- def io_gate
- Reline::IOGate
- end
-
- def set_pasting_state(in_pasting)
- # While pasting, text to be inserted is stored to @continuous_insertion_buffer.
- # After pasting, this buffer should be force inserted.
- process_insert(force: true) if @in_pasting && !in_pasting
- @in_pasting = in_pasting
- end
-
- private def check_mode_string
- if @config.show_mode_in_prompt
- if @config.editing_mode_is?(:vi_command)
- @config.vi_cmd_mode_string
- elsif @config.editing_mode_is?(:vi_insert)
- @config.vi_ins_mode_string
- elsif @config.editing_mode_is?(:emacs)
- @config.emacs_mode_string
- else
- '?'
- end
- end
- end
-
- private def check_multiline_prompt(buffer, mode_string)
- if @vi_arg
- prompt = "(arg: #{@vi_arg}) "
- elsif @searching_prompt
- prompt = @searching_prompt
- else
- prompt = @prompt
- end
- if !@is_multiline
- mode_string = check_mode_string
- prompt = mode_string + prompt if mode_string
- [prompt] + [''] * (buffer.size - 1)
- elsif @prompt_proc
- prompt_list = @prompt_proc.(buffer).map { |pr| pr.gsub("\n", "\\n") }
- prompt_list.map!{ prompt } if @vi_arg or @searching_prompt
- prompt_list = [prompt] if prompt_list.empty?
- 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_list
- else
- prompt = mode_string + prompt if mode_string
- [prompt] * buffer.size
- end
- end
-
- def reset(prompt = '', encoding:)
- @screen_size = Reline::IOGate.get_screen_size
- reset_variables(prompt, encoding: encoding)
- @rendered_screen.base_y = Reline::IOGate.cursor_pos.y
- 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 handle_signal
- handle_interrupted
- handle_resized
- end
-
- private def handle_resized
- return unless @resized
-
- @screen_size = Reline::IOGate.get_screen_size
- @resized = false
- scroll_into_view
- Reline::IOGate.move_cursor_up @rendered_screen.cursor_y
- @rendered_screen.base_y = Reline::IOGate.cursor_pos.y
- @rendered_screen.lines = []
- @rendered_screen.cursor_y = 0
- render_differential
- end
-
- private def handle_interrupted
- return unless @interrupted
-
- @interrupted = false
- clear_dialogs
- scrolldown = render_differential
- Reline::IOGate.scroll_down scrolldown
- Reline::IOGate.move_cursor_column 0
- @rendered_screen.lines = []
- @rendered_screen.cursor_y = 0
- 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
- end
-
- def set_signal_handlers
- Reline::IOGate.set_winch_handler do
- @resized = true
- end
- @old_trap = Signal.trap('INT') do
- @interrupted = true
- end
- end
-
- def finalize
- Signal.trap('INT', @old_trap)
- end
-
- def eof?
- @eof
- end
-
- def reset_variables(prompt = '', encoding:)
- @prompt = prompt.gsub("\n", "\\n")
- @mark_pointer = nil
- @encoding = encoding
- @is_multiline = false
- @finished = false
- @history_pointer = nil
- @kill_ring ||= Reline::KillRing.new
- @vi_clipboard = ''
- @vi_arg = nil
- @waiting_proc = nil
- @vi_waiting_operator = nil
- @vi_waiting_operator_arg = nil
- @completion_journey_state = nil
- @completion_state = CompletionState::NORMAL
- @perfect_matched = nil
- @menu_info = nil
- @searching_prompt = nil
- @first_char = true
- @just_cursor_moving = false
- @eof = false
- @continuous_insertion_buffer = String.new(encoding: @encoding)
- @scroll_partial_screen = 0
- @drop_terminate_spaces = false
- @in_pasting = false
- @auto_indent_proc = nil
- @dialogs = []
- @interrupted = false
- @resized = false
- @cache = {}
- @rendered_screen = RenderedScreen.new(base_y: 0, lines: [], cursor_y: 0)
- @input_lines = [[[""], 0, 0]]
- @input_lines_position = 0
- @undoing = false
- reset_line
- end
-
- def reset_line
- @byte_pointer = 0
- @buffer_of_lines = [String.new(encoding: @encoding)]
- @line_index = 0
- @cache.clear
- @line_backup_in_history = nil
- @multibyte_buffer = String.new(encoding: 'ASCII-8BIT')
- end
-
- def multiline_on
- @is_multiline = true
- end
-
- def multiline_off
- @is_multiline = false
- end
-
- private def insert_new_line(cursor_line, next_line)
- @buffer_of_lines.insert(@line_index + 1, String.new(next_line, encoding: @encoding))
- @buffer_of_lines[@line_index] = cursor_line
- @line_index += 1
- @byte_pointer = 0
- if @auto_indent_proc && !@in_pasting
- if next_line.empty?
- (
- # For compatibility, use this calculation instead of just `process_auto_indent @line_index - 1, cursor_dependent: false`
- indent1 = @auto_indent_proc.(@buffer_of_lines.take(@line_index - 1).push(''), @line_index - 1, 0, true)
- indent2 = @auto_indent_proc.(@buffer_of_lines.take(@line_index), @line_index - 1, @buffer_of_lines[@line_index - 1].bytesize, false)
- indent = indent2 || indent1
- @buffer_of_lines[@line_index - 1] = ' ' * indent + @buffer_of_lines[@line_index - 1].gsub(/\A\s*/, '')
- )
- process_auto_indent @line_index, add_newline: true
- else
- process_auto_indent @line_index - 1, cursor_dependent: false
- process_auto_indent @line_index, add_newline: true # Need for compatibility
- process_auto_indent @line_index, cursor_dependent: false
- end
- end
- end
-
- private def split_by_width(str, max_width, offset: 0)
- Reline::Unicode.split_by_width(str, max_width, @encoding, offset: offset)
- end
-
- def current_byte_pointer_cursor
- calculate_width(current_line.byteslice(0, @byte_pointer))
- end
-
- private def calculate_nearest_cursor(cursor)
- line_to_calc = current_line
- new_cursor_max = calculate_width(line_to_calc)
- new_cursor = 0
- new_byte_pointer = 0
- height = 1
- max_width = screen_width
- if @config.editing_mode_is?(:vi_command)
- last_byte_size = Reline::Unicode.get_prev_mbchar_size(line_to_calc, line_to_calc.bytesize)
- if last_byte_size > 0
- 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)
- end_of_line_cursor = new_cursor_max - last_width
- else
- end_of_line_cursor = new_cursor_max
- end
- else
- end_of_line_cursor = new_cursor_max
- end
- 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 > end_of_line_cursor or now > cursor
- break
- end
- new_cursor += mbchar_width
- if new_cursor > max_width * height
- height += 1
- end
- new_byte_pointer += gc.bytesize
- end
- @byte_pointer = new_byte_pointer
- end
-
- def with_cache(key, *deps)
- cached_deps, value = @cache[key]
- if cached_deps != deps
- @cache[key] = [deps, value = yield(*deps, cached_deps, value)]
- end
- value
- end
-
- def modified_lines
- with_cache(__method__, whole_lines, finished?) do |whole, complete|
- modify_lines(whole, complete)
- end
- end
-
- def prompt_list
- with_cache(__method__, whole_lines, check_mode_string, @vi_arg, @searching_prompt) do |lines, mode_string|
- check_multiline_prompt(lines, mode_string)
- end
- end
-
- def screen_height
- @screen_size.first
- end
-
- def screen_width
- @screen_size.last
- end
-
- def screen_scroll_top
- @scroll_partial_screen
- end
-
- def wrapped_prompt_and_input_lines
- with_cache(__method__, @buffer_of_lines.size, modified_lines, prompt_list, screen_width) do |n, lines, prompts, width, prev_cache_key, cached_value|
- prev_n, prev_lines, prev_prompts, prev_width = prev_cache_key
- cached_wraps = {}
- if prev_width == width
- prev_n.times do |i|
- cached_wraps[[prev_prompts[i], prev_lines[i]]] = cached_value[i]
- end
- end
-
- n.times.map do |i|
- prompt = prompts[i] || ''
- line = lines[i] || ''
- if (cached = cached_wraps[[prompt, line]])
- next cached
- end
- *wrapped_prompts, code_line_prompt = split_by_width(prompt, width).first.compact
- wrapped_lines = split_by_width(line, width, offset: calculate_width(code_line_prompt, true)).first.compact
- wrapped_prompts.map { |p| [p, ''] } + [[code_line_prompt, wrapped_lines.first]] + wrapped_lines.drop(1).map { |c| ['', c] }
- end
- end
- end
-
- def calculate_overlay_levels(overlay_levels)
- levels = []
- overlay_levels.each do |x, w, l|
- levels.fill(l, x, w)
- end
- levels
- end
-
- def render_line_differential(old_items, new_items)
- old_levels = calculate_overlay_levels(old_items.zip(new_items).each_with_index.map {|((x, w, c), (nx, _nw, nc)), i| [x, w, c == nc && x == nx ? i : -1] if x }.compact)
- new_levels = calculate_overlay_levels(new_items.each_with_index.map { |(x, w), i| [x, w, i] if x }.compact).take(screen_width)
- base_x = 0
- new_levels.zip(old_levels).chunk { |n, o| n == o ? :skip : n || :blank }.each do |level, chunk|
- width = chunk.size
- if level == :skip
- # do nothing
- elsif level == :blank
- Reline::IOGate.move_cursor_column base_x
- @output.write "#{Reline::IOGate.reset_color_sequence}#{' ' * width}"
- else
- x, w, content = new_items[level]
- cover_begin = base_x != 0 && new_levels[base_x - 1] == level
- cover_end = new_levels[base_x + width] == level
- pos = 0
- unless x == base_x && w == width
- content, pos = Reline::Unicode.take_mbchar_range(content, base_x - x, width, cover_begin: cover_begin, cover_end: cover_end, padding: true)
- end
- Reline::IOGate.move_cursor_column x + pos
- @output.write "#{Reline::IOGate.reset_color_sequence}#{content}#{Reline::IOGate.reset_color_sequence}"
- end
- base_x += width
- end
- if old_levels.size > new_levels.size
- Reline::IOGate.move_cursor_column new_levels.size
- Reline::IOGate.erase_after_cursor
- end
- end
-
- # Calculate cursor position in word wrapped content.
- def wrapped_cursor_position
- prompt_width = calculate_width(prompt_list[@line_index], true)
- line_before_cursor = whole_lines[@line_index].byteslice(0, @byte_pointer)
- wrapped_line_before_cursor = split_by_width(' ' * prompt_width + line_before_cursor, screen_width).first.compact
- wrapped_cursor_y = wrapped_prompt_and_input_lines[0...@line_index].sum(&:size) + wrapped_line_before_cursor.size - 1
- wrapped_cursor_x = calculate_width(wrapped_line_before_cursor.last)
- [wrapped_cursor_x, wrapped_cursor_y]
- end
-
- def clear_dialogs
- @dialogs.each do |dialog|
- dialog.contents = nil
- dialog.trap_key = nil
- end
- end
-
- def update_dialogs(key = nil)
- wrapped_cursor_x, wrapped_cursor_y = wrapped_cursor_position
- @dialogs.each do |dialog|
- dialog.trap_key = nil
- update_each_dialog(dialog, wrapped_cursor_x, wrapped_cursor_y - screen_scroll_top, key)
- end
- end
-
- def render_finished
- clear_rendered_lines
- render_full_content
- end
-
- def clear_rendered_lines
- Reline::IOGate.move_cursor_up @rendered_screen.cursor_y
- Reline::IOGate.move_cursor_column 0
-
- num_lines = @rendered_screen.lines.size
- return unless num_lines && num_lines >= 1
-
- Reline::IOGate.move_cursor_down num_lines - 1
- (num_lines - 1).times do
- Reline::IOGate.erase_after_cursor
- Reline::IOGate.move_cursor_up 1
- end
- Reline::IOGate.erase_after_cursor
- @rendered_screen.lines = []
- @rendered_screen.cursor_y = 0
- end
-
- def render_full_content
- lines = @buffer_of_lines.size.times.map do |i|
- line = prompt_list[i] + modified_lines[i]
- wrapped_lines, = split_by_width(line, screen_width)
- wrapped_lines.last.empty? ? "#{line} " : line
- end
- @output.puts lines.map { |l| "#{l}\r\n" }.join
- end
-
- def print_nomultiline_prompt(prompt)
- return unless prompt && !@is_multiline
-
- # Readline's test `TestRelineAsReadline#test_readline` requires first output to be prompt, not cursor reset escape sequence.
- @rendered_screen.lines = [[[0, Reline::Unicode.calculate_width(prompt, true), prompt]]]
- @rendered_screen.cursor_y = 0
- @output.write prompt
- end
-
- def render_differential
- wrapped_cursor_x, wrapped_cursor_y = wrapped_cursor_position
-
- rendered_lines = @rendered_screen.lines
- new_lines = wrapped_prompt_and_input_lines.flatten(1)[screen_scroll_top, screen_height].map do |prompt, line|
- prompt_width = Reline::Unicode.calculate_width(prompt, true)
- [[0, prompt_width, prompt], [prompt_width, Reline::Unicode.calculate_width(line, true), line]]
- end
- if @menu_info
- @menu_info.lines(screen_width).each do |item|
- new_lines << [[0, Reline::Unicode.calculate_width(item), item]]
- end
- @menu_info = nil # TODO: do not change state here
- end
-
- @dialogs.each_with_index do |dialog, index|
- next unless dialog.contents
-
- x_range, y_range = dialog_range dialog, wrapped_cursor_y - screen_scroll_top
- y_range.each do |row|
- next if row < 0 || row >= screen_height
- dialog_rows = new_lines[row] ||= []
- # index 0 is for prompt, index 1 is for line, index 2.. is for dialog
- dialog_rows[index + 2] = [x_range.begin, dialog.width, dialog.contents[row - y_range.begin]]
- end
- end
-
- cursor_y = @rendered_screen.cursor_y
- if new_lines != rendered_lines
- # Hide cursor while rendering to avoid cursor flickering.
- Reline::IOGate.hide_cursor
- num_lines = [[new_lines.size, rendered_lines.size].max, screen_height].min
- if @rendered_screen.base_y + num_lines > screen_height
- Reline::IOGate.scroll_down(num_lines - cursor_y - 1)
- @rendered_screen.base_y = screen_height - num_lines
- cursor_y = num_lines - 1
- end
- num_lines.times do |i|
- rendered_line = rendered_lines[i] || []
- line_to_render = new_lines[i] || []
- next if rendered_line == line_to_render
-
- Reline::IOGate.move_cursor_down i - cursor_y
- cursor_y = i
- unless rendered_lines[i]
- Reline::IOGate.move_cursor_column 0
- Reline::IOGate.erase_after_cursor
- end
- render_line_differential(rendered_line, line_to_render)
- end
- @rendered_screen.lines = new_lines
- Reline::IOGate.show_cursor
- end
- y = wrapped_cursor_y - screen_scroll_top
- Reline::IOGate.move_cursor_column wrapped_cursor_x
- Reline::IOGate.move_cursor_down y - cursor_y
- @rendered_screen.cursor_y = y
- new_lines.size - y
- end
-
- def upper_space_height(wrapped_cursor_y)
- wrapped_cursor_y - screen_scroll_top
- end
-
- def rest_height(wrapped_cursor_y)
- screen_height - wrapped_cursor_y + screen_scroll_top - @rendered_screen.base_y - 1
- end
-
- def rerender
- render_differential unless @in_pasting
- end
-
- class DialogProcScope
- CompletionJourneyData = Struct.new(:preposing, :postposing, :list, :pointer)
-
- 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.screen_width
- end
-
- def screen_height
- @line_editor.screen_height
- end
-
- def preferred_dialog_height
- _wrapped_cursor_x, wrapped_cursor_y = @line_editor.wrapped_cursor_position
- [@line_editor.upper_space_height(wrapped_cursor_y), @line_editor.rest_height(wrapped_cursor_y), (screen_height + 6) / 5].max
- end
-
- def completion_journey_data
- @line_editor.dialog_proc_scope_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, :pointer, :column, :vertical_offset, :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
- 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 dialog_range(dialog, dialog_y)
- x_range = dialog.column...dialog.column + dialog.width
- y_range = dialog_y + dialog.vertical_offset...dialog_y + dialog.vertical_offset + dialog.contents.size
- [x_range, y_range]
- end
-
- private def update_each_dialog(dialog, cursor_column, cursor_row, key = nil)
- dialog.set_cursor_pos(cursor_column, cursor_row)
- dialog_render_info = dialog.call(key)
- if dialog_render_info.nil? or dialog_render_info.contents.nil? or dialog_render_info.contents.empty?
- dialog.contents = nil
- dialog.trap_key = nil
- return
- end
- contents = dialog_render_info.contents
- pointer = dialog.pointer
- if dialog_render_info.width
- dialog.width = dialog_render_info.width
- else
- dialog.width = contents.map { |l| calculate_width(l, true) }.max
- end
- height = dialog_render_info.height || DIALOG_DEFAULT_HEIGHT
- height = contents.size if contents.size < height
- if 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
- else
- dialog.scroll_top = 0
- end
- contents = contents[dialog.scroll_top, 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 * ((contents.size * 2).to_f / (dialog_render_info.contents.size * 2))).floor.to_i
- bar_height = MINIMUM_SCROLLBAR_HEIGHT if bar_height < MINIMUM_SCROLLBAR_HEIGHT
- scrollbar_pos = ((bar_max_height - bar_height) * position_ratio).floor.to_i
- else
- scrollbar_pos = nil
- end
- dialog.column = dialog_render_info.pos.x
- dialog.width += @block_elem_width if scrollbar_pos
- diff = (dialog.column + dialog.width) - screen_width
- if diff > 0
- dialog.column -= diff
- end
- if rest_height(screen_scroll_top + cursor_row) - dialog_render_info.pos.y >= height
- dialog.vertical_offset = dialog_render_info.pos.y + 1
- elsif cursor_row >= height
- dialog.vertical_offset = dialog_render_info.pos.y - height
- else
- dialog.vertical_offset = dialog_render_info.pos.y + 1
- end
- if dialog.column < 0
- dialog.column = 0
- dialog.width = screen_width
- end
- face = Reline::Face[dialog_render_info.face || :default]
- scrollbar_sgr = face[:scrollbar]
- default_sgr = face[:default]
- enhanced_sgr = face[:enhanced]
- dialog.contents = contents.map.with_index do |item, i|
- line_sgr = i == pointer ? enhanced_sgr : default_sgr
- str_width = dialog.width - (scrollbar_pos.nil? ? 0 : @block_elem_width)
- str, = Reline::Unicode.take_mbchar_range(item, 0, str_width, padding: true)
- colored_content = "#{line_sgr}#{str}"
- if scrollbar_pos
- if scrollbar_pos <= (i * 2) and (i * 2 + 1) < (scrollbar_pos + bar_height)
- colored_content + scrollbar_sgr + @full_block
- elsif scrollbar_pos <= (i * 2) and (i * 2) < (scrollbar_pos + bar_height)
- colored_content + scrollbar_sgr + @upper_half_block
- elsif scrollbar_pos <= (i * 2 + 1) and (i * 2) < (scrollbar_pos + bar_height)
- colored_content + scrollbar_sgr + @lower_half_block
- else
- colored_content + scrollbar_sgr + ' ' * @block_elem_width
- end
- else
- colored_content
- end
- end
- end
-
- private def modify_lines(before, complete)
- if after = @output_modifier_proc&.call("#{before.join("\n")}\n", complete: complete)
- after.lines("\n").map { |l| l.chomp('') }
- else
- before.map { |l| Reline::Unicode.escape_for_print(l) }
- end
- end
-
- def editing_mode
- @config.editing_mode
- end
-
- private def menu(_target, list)
- @menu_info = MenuInfo.new(list)
- end
-
- private def complete_internal_proc(list, is_menu)
- preposing, target, postposing = retrieve_completion_block
- list = list.select { |i|
- if i and not Encoding.compatible?(target.encoding, i.encoding)
- raise Encoding::CompatibilityError, "#{target.encoding.name} is not compatible with #{i.encoding.name}"
- end
- if @config.completion_ignore_case
- i&.downcase&.start_with?(target.downcase)
- else
- i&.start_with?(target)
- end
- }.uniq
- if is_menu
- menu(target, list)
- return nil
- end
- completed = list.inject { |memo, item|
- begin
- memo_mbchars = memo.unicode_normalize.grapheme_clusters
- item_mbchars = item.unicode_normalize.grapheme_clusters
- rescue Encoding::CompatibilityError
- memo_mbchars = memo.grapheme_clusters
- item_mbchars = item.grapheme_clusters
- end
- size = [memo_mbchars.size, item_mbchars.size].min
- result = +''
- size.times do |i|
- if @config.completion_ignore_case
- if memo_mbchars[i].casecmp?(item_mbchars[i])
- result << memo_mbchars[i]
- else
- break
- end
- else
- if memo_mbchars[i] == item_mbchars[i]
- result << memo_mbchars[i]
- else
- break
- end
- end
- end
- result
- }
- [target, preposing, completed, postposing]
- end
-
- private def perform_completion(list, just_show_list)
- case @completion_state
- when CompletionState::NORMAL
- @completion_state = CompletionState::COMPLETION
- when CompletionState::PERFECT_MATCH
- @dig_perfect_match_proc&.(@perfect_matched)
- end
- if just_show_list
- is_menu = true
- elsif @completion_state == CompletionState::MENU
- is_menu = true
- elsif @completion_state == CompletionState::MENU_WITH_PERFECT_MATCH
- is_menu = true
- else
- is_menu = false
- end
- result = complete_internal_proc(list, is_menu)
- if @completion_state == CompletionState::MENU_WITH_PERFECT_MATCH
- @completion_state = CompletionState::PERFECT_MATCH
- end
- return if result.nil?
- target, preposing, completed, postposing = result
- return if completed.nil?
- if target <= completed and (@completion_state == CompletionState::COMPLETION)
- if list.include?(completed)
- if list.one?
- @completion_state = CompletionState::PERFECT_MATCH
- else
- @completion_state = CompletionState::MENU_WITH_PERFECT_MATCH
- perform_completion(list, true) if @config.show_all_if_ambiguous
- end
- @perfect_matched = completed
- else
- @completion_state = CompletionState::MENU
- perform_completion(list, true) if @config.show_all_if_ambiguous
- end
- if not just_show_list and target < completed
- @buffer_of_lines[@line_index] = (preposing + completed + completion_append_character.to_s + postposing).split("\n")[@line_index] || String.new(encoding: @encoding)
- line_to_pointer = (preposing + completed + completion_append_character.to_s).split("\n")[@line_index] || String.new(encoding: @encoding)
- @byte_pointer = line_to_pointer.bytesize
- end
- end
- end
-
- def dialog_proc_scope_completion_journey_data
- return nil unless @completion_journey_state
- line_index = @completion_journey_state.line_index
- pre_lines = @buffer_of_lines[0...line_index].map { |line| line + "\n" }
- post_lines = @buffer_of_lines[(line_index + 1)..-1].map { |line| line + "\n" }
- DialogProcScope::CompletionJourneyData.new(
- pre_lines.join + @completion_journey_state.pre,
- @completion_journey_state.post + post_lines.join,
- @completion_journey_state.list,
- @completion_journey_state.pointer
- )
- end
-
- private def move_completed_list(direction)
- @completion_journey_state ||= retrieve_completion_journey_state
- return false unless @completion_journey_state
-
- if (delta = { up: -1, down: +1 }[direction])
- @completion_journey_state.pointer = (@completion_journey_state.pointer + delta) % @completion_journey_state.list.size
- end
- completed = @completion_journey_state.list[@completion_journey_state.pointer]
- set_current_line(@completion_journey_state.pre + completed + @completion_journey_state.post, @completion_journey_state.pre.bytesize + completed.bytesize)
- true
- end
-
- private def retrieve_completion_journey_state
- preposing, target, postposing = retrieve_completion_block
- list = call_completion_proc
- return unless list.is_a?(Array)
-
- candidates = list.select{ |item| item.start_with?(target) }
- return if candidates.empty?
-
- pre = preposing.split("\n", -1).last || ''
- post = postposing.split("\n", -1).first || ''
- CompletionJourneyState.new(
- @line_index, pre, target, post, [target] + candidates, 0
- )
- end
-
- private def run_for_operators(key, method_symbol, &block)
- if @vi_waiting_operator
- if VI_MOTIONS.include?(method_symbol)
- old_byte_pointer = @byte_pointer
- @vi_arg = (@vi_arg || 1) * @vi_waiting_operator_arg
- block.(true)
- unless @waiting_proc
- byte_pointer_diff = @byte_pointer - old_byte_pointer
- @byte_pointer = old_byte_pointer
- method_obj = method(@vi_waiting_operator)
- wrap_method_call(@vi_waiting_operator, method_obj, byte_pointer_diff)
- cleanup_waiting
- end
- else
- # Ignores operator when not motion is given.
- block.(false)
- cleanup_waiting
- end
- @vi_arg = nil
- else
- block.(false)
- end
- end
-
- private def argumentable?(method_obj)
- 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 @vi_waiting_operator.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 cleanup_waiting
- @waiting_proc = nil
- @vi_waiting_operator = nil
- @vi_waiting_operator_arg = nil
- @searching_prompt = nil
- @drop_terminate_spaces = false
- end
-
- private def process_key(key, method_symbol)
- if key.is_a?(Symbol)
- cleanup_waiting
- elsif @waiting_proc
- old_byte_pointer = @byte_pointer
- @waiting_proc.call(key)
- if @vi_waiting_operator
- byte_pointer_diff = @byte_pointer - old_byte_pointer
- @byte_pointer = old_byte_pointer
- method_obj = method(@vi_waiting_operator)
- wrap_method_call(@vi_waiting_operator, method_obj, byte_pointer_diff)
- cleanup_waiting
- end
- @kill_ring.process
- return
- end
-
- if method_symbol and respond_to?(method_symbol, true)
- method_obj = method(method_symbol)
- end
- if method_symbol and key.is_a?(Symbol)
- if @vi_arg and argumentable?(method_obj)
- run_for_operators(key, method_symbol) do |with_operator|
- wrap_method_call(method_symbol, method_obj, key, with_operator)
- end
- else
- wrap_method_call(method_symbol, method_obj, key) if method_obj
- end
- @kill_ring.process
- if @vi_arg
- @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 |with_operator|
- wrap_method_call(method_symbol, method_obj, key, with_operator)
- end
- elsif method_obj
- wrap_method_call(method_symbol, method_obj, key)
- else
- ed_insert(key) unless @config.editing_mode_is?(:vi_command)
- end
- @kill_ring.process
- if @vi_arg
- @vi_arg = nil
- end
- end
- elsif method_obj
- if method_symbol == :ed_argument_digit
- wrap_method_call(method_symbol, method_obj, key)
- else
- 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) unless @config.editing_mode_is?(:vi_command)
- end
- end
-
- private def normal_char(key)
- @multibyte_buffer << key.combined_char
- if @multibyte_buffer.size > 1
- if @multibyte_buffer.dup.force_encoding(@encoding).valid_encoding?
- process_key(@multibyte_buffer.dup.force_encoding(@encoding), nil)
- @multibyte_buffer.clear
- else
- # invalid
- return
- end
- else # single byte
- return if key.char >= 128 # maybe, first byte of multi byte
- method_symbol = @config.editing_mode.get_method(key.combined_char)
- if key.with_meta and method_symbol == :ed_unassigned
- if @config.editing_mode_is?(:vi_command, :vi_insert)
- # split ESC + key in vi mode
- method_symbol = @config.editing_mode.get_method("\e".ord)
- process_key("\e".ord, method_symbol)
- method_symbol = @config.editing_mode.get_method(key.char)
- process_key(key.char, method_symbol)
- end
- else
- process_key(key.combined_char, method_symbol)
- end
- @multibyte_buffer.clear
- end
- if @config.editing_mode_is?(:vi_command) and @byte_pointer > 0 and @byte_pointer == current_line.bytesize
- byte_size = Reline::Unicode.get_prev_mbchar_size(@buffer_of_lines[@line_index], @byte_pointer)
- @byte_pointer -= byte_size
- end
- end
-
- def update(key)
- modified = input_key(key)
- unless @in_pasting
- scroll_into_view
- @just_cursor_moving = !modified
- update_dialogs(key)
- @just_cursor_moving = false
- end
- end
-
- def input_key(key)
- save_old_buffer
- @config.reset_oneshot_key_bindings
- @dialogs.each do |dialog|
- if key.char.instance_of?(Symbol) and key.char == dialog.name
- return
- end
- end
- if key.char.nil?
- process_insert(force: true)
- if @first_char
- @eof = true
- end
- finish
- return
- end
- @first_char = false
- @completion_occurs = false
-
- if key.char.is_a?(Symbol)
- process_key(key.char, key.char)
- else
- normal_char(key)
- end
- unless @completion_occurs
- @completion_state = CompletionState::NORMAL
- @completion_journey_state = nil
- end
-
- push_input_lines unless @undoing
- @undoing = false
-
- if @in_pasting
- clear_dialogs
- return
- end
-
- modified = @old_buffer_of_lines != @buffer_of_lines
- if !@completion_occurs && modified && !@config.disable_completion && @config.autocompletion
- # Auto complete starts only when edited
- process_insert(force: true)
- @completion_journey_state = retrieve_completion_journey_state
- end
- modified
- end
-
- def save_old_buffer
- @old_buffer_of_lines = @buffer_of_lines.dup
- end
-
- def push_input_lines
- if @old_buffer_of_lines == @buffer_of_lines
- @input_lines[@input_lines_position] = [@buffer_of_lines.dup, @byte_pointer, @line_index]
- else
- @input_lines = @input_lines[0..@input_lines_position]
- @input_lines_position += 1
- @input_lines.push([@buffer_of_lines.dup, @byte_pointer, @line_index])
- end
- trim_input_lines
- end
-
- MAX_INPUT_LINES = 100
- def trim_input_lines
- if @input_lines.size > MAX_INPUT_LINES
- @input_lines.shift
- @input_lines_position -= 1
- end
- end
-
- def scroll_into_view
- _wrapped_cursor_x, wrapped_cursor_y = wrapped_cursor_position
- if wrapped_cursor_y < screen_scroll_top
- @scroll_partial_screen = wrapped_cursor_y
- end
- if wrapped_cursor_y >= screen_scroll_top + screen_height
- @scroll_partial_screen = wrapped_cursor_y - screen_height + 1
- end
- end
-
- def call_completion_proc
- result = retrieve_completion_block(true)
- 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(line_index = @line_index, cursor_dependent: true, add_newline: false)
- return if @in_pasting
- return unless @auto_indent_proc
-
- line = @buffer_of_lines[line_index]
- byte_pointer = cursor_dependent && @line_index == line_index ? @byte_pointer : line.bytesize
- new_indent = @auto_indent_proc.(@buffer_of_lines.take(line_index + 1).push(''), line_index, byte_pointer, add_newline)
- return unless new_indent
-
- new_line = ' ' * new_indent + line.lstrip
- @buffer_of_lines[line_index] = new_line
- if @line_index == line_index
- indent_diff = new_line.bytesize - line.bytesize
- @byte_pointer = [@byte_pointer + indent_diff, 0].max
- end
- end
-
- def line()
- @buffer_of_lines.join("\n") unless eof?
- end
-
- def current_line
- @buffer_of_lines[@line_index]
- end
-
- def set_current_line(line, byte_pointer = nil)
- cursor = current_byte_pointer_cursor
- @buffer_of_lines[@line_index] = line
- if byte_pointer
- @byte_pointer = byte_pointer
- else
- calculate_nearest_cursor(cursor)
- end
- process_auto_indent
- end
-
- def set_current_lines(lines, byte_pointer = nil, line_index = 0)
- cursor = current_byte_pointer_cursor
- @buffer_of_lines = lines
- @line_index = line_index
- if byte_pointer
- @byte_pointer = byte_pointer
- else
- calculate_nearest_cursor(cursor)
- end
- process_auto_indent
- end
-
- def retrieve_completion_block(set_completion_quote_character = false)
- 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 = current_line.byteslice(0, @byte_pointer)
- rest = nil
- break_pointer = nil
- quote = nil
- closing_quote = nil
- escaped_quote = nil
- i = 0
- while i < @byte_pointer do
- slice = current_line.byteslice(i, @byte_pointer - i)
- unless slice.valid_encoding?
- i += 1
- next
- end
- if quote and slice.start_with?(closing_quote)
- quote = nil
- i += 1
- rest = nil
- elsif quote and slice.start_with?(escaped_quote)
- # skip
- i += 2
- 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 word_break_regexp and not quote and slice =~ word_break_regexp
- rest = $'
- i += 1
- before = current_line.byteslice(i, @byte_pointer - i)
- break_pointer = i
- else
- i += 1
- end
- end
- postposing = current_line.byteslice(@byte_pointer, current_line.bytesize - @byte_pointer)
- if rest
- preposing = current_line.byteslice(0, break_pointer)
- target = rest
- if set_completion_quote_character and quote
- Reline.core.instance_variable_set(:@completion_quote_character, quote)
- if postposing !~ /(?!\\)#{Regexp.escape(quote)}/ # closing quote
- insert_text(quote)
- end
- end
- else
- preposing = ''
- if break_pointer
- preposing = current_line.byteslice(0, break_pointer)
- else
- preposing = ''
- end
- target = before
- end
- lines = whole_lines
- 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
- [preposing.encode(@encoding), target.encode(@encoding), postposing.encode(@encoding)]
- end
-
- def confirm_multiline_termination
- temp_buffer = @buffer_of_lines.dup
- @confirm_multiline_termination_proc.(temp_buffer.join("\n") + "\n")
- end
-
- def insert_pasted_text(text)
- save_old_buffer
- pre = @buffer_of_lines[@line_index].byteslice(0, @byte_pointer)
- post = @buffer_of_lines[@line_index].byteslice(@byte_pointer..)
- lines = (pre + text.gsub(/\r\n?/, "\n") + post).split("\n", -1)
- lines << '' if lines.empty?
- @buffer_of_lines[@line_index, 1] = lines
- @line_index += lines.size - 1
- @byte_pointer = @buffer_of_lines[@line_index].bytesize - post.bytesize
- push_input_lines
- end
-
- def insert_text(text)
- if @buffer_of_lines[@line_index].bytesize == @byte_pointer
- @buffer_of_lines[@line_index] += text
- else
- @buffer_of_lines[@line_index] = byteinsert(@buffer_of_lines[@line_index], @byte_pointer, text)
- end
- @byte_pointer += text.bytesize
- process_auto_indent
- end
-
- def delete_text(start = nil, length = nil)
- if start.nil? and length.nil?
- if @buffer_of_lines.size == 1
- @buffer_of_lines[@line_index] = ''
- @byte_pointer = 0
- elsif @line_index == (@buffer_of_lines.size - 1) and @line_index > 0
- @buffer_of_lines.pop
- @line_index -= 1
- @byte_pointer = 0
- elsif @line_index < (@buffer_of_lines.size - 1)
- @buffer_of_lines.delete_at(@line_index)
- @byte_pointer = 0
- end
- elsif not start.nil? and not length.nil?
- if current_line
- before = current_line.byteslice(0, start)
- after = current_line.byteslice(start + length, current_line.bytesize)
- set_current_line(before + after)
- end
- elsif start.is_a?(Range)
- range = start
- first = range.first
- last = range.last
- last = current_line.bytesize - 1 if last > current_line.bytesize
- last += current_line.bytesize if last < 0
- first += current_line.bytesize if first < 0
- range = range.exclude_end? ? first...last : first..last
- line = current_line.bytes.reject.with_index{ |c, i| range.include?(i) }.map{ |c| c.chr(Encoding::ASCII_8BIT) }.join.force_encoding(@encoding)
- set_current_line(line)
- else
- set_current_line(current_line.byteslice(0, start))
- end
- end
-
- def byte_pointer=(val)
- @byte_pointer = val
- end
-
- def whole_lines
- @buffer_of_lines.dup
- end
-
- def whole_buffer
- whole_lines.join("\n")
- end
-
- def finished?
- @finished
- end
-
- def finish
- @finished = true
- @config.reset
- end
-
- private def byteslice!(str, byte_pointer, size)
- new_str = str.byteslice(0, byte_pointer)
- new_str << str.byteslice(byte_pointer + size, str.bytesize)
- [new_str, str.byteslice(byte_pointer, size)]
- end
-
- private def byteinsert(str, byte_pointer, other)
- new_str = str.byteslice(0, byte_pointer)
- new_str << other
- new_str << str.byteslice(byte_pointer, str.bytesize)
- new_str
- end
-
- private def calculate_width(str, allow_escape_code = false)
- Reline::Unicode.calculate_width(str, allow_escape_code)
- end
-
- private def key_delete(key)
- if @config.editing_mode_is?(:vi_insert)
- ed_delete_next_char(key)
- elsif @config.editing_mode_is?(:emacs)
- em_delete(key)
- end
- end
-
- private def key_newline(key)
- if @is_multiline
- next_line = current_line.byteslice(@byte_pointer, current_line.bytesize - @byte_pointer)
- cursor_line = current_line.byteslice(0, @byte_pointer)
- insert_new_line(cursor_line, next_line)
- end
- end
-
- private def complete(_key)
- return if @config.disable_completion
-
- process_insert(force: true)
- if @config.autocompletion
- @completion_state = CompletionState::NORMAL
- @completion_occurs = move_completed_list(:down)
- else
- @completion_journey_state = nil
- result = call_completion_proc
- if result.is_a?(Array)
- @completion_occurs = true
- perform_completion(result, false)
- end
- end
- end
-
- private def completion_journey_move(direction)
- return if @config.disable_completion
-
- process_insert(force: true)
- @completion_state = CompletionState::NORMAL
- @completion_occurs = move_completed_list(direction)
- end
-
- private def menu_complete(_key)
- completion_journey_move(:down)
- end
-
- private def menu_complete_backward(_key)
- completion_journey_move(:up)
- end
-
- private def completion_journey_up(_key)
- completion_journey_move(:up) if @config.autocompletion
- 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)
- insert_text(@continuous_insertion_buffer)
- @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)
- if key.instance_of?(String)
- begin
- key.encode(Encoding::UTF_8)
- rescue Encoding::UndefinedConversionError
- return
- end
- str = key
- else
- begin
- key.chr.encode(Encoding::UTF_8)
- rescue Encoding::UndefinedConversionError
- return
- end
- str = key.chr
- end
- if @in_pasting
- @continuous_insertion_buffer << str
- return
- elsif not @continuous_insertion_buffer.empty?
- process_insert
- end
-
- insert_text(str)
- end
- alias_method :ed_digit, :ed_insert
- alias_method :self_insert, :ed_insert
-
- private def ed_quoted_insert(str, arg: 1)
- @waiting_proc = proc { |key|
- 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
- end
- @waiting_proc = nil
- }
- end
- alias_method :quoted_insert, :ed_quoted_insert
-
- private def ed_next_char(key, arg: 1)
- byte_size = Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer)
- if (@byte_pointer < current_line.bytesize)
- @byte_pointer += byte_size
- elsif @config.editing_mode_is?(:emacs) and @byte_pointer == current_line.bytesize and @line_index < @buffer_of_lines.size - 1
- @byte_pointer = 0
- @line_index += 1
- end
- arg -= 1
- ed_next_char(key, arg: arg) if arg > 0
- end
- alias_method :forward_char, :ed_next_char
-
- private def ed_prev_char(key, arg: 1)
- if @byte_pointer > 0
- byte_size = Reline::Unicode.get_prev_mbchar_size(current_line, @byte_pointer)
- @byte_pointer -= byte_size
- elsif @config.editing_mode_is?(:emacs) and @byte_pointer == 0 and @line_index > 0
- @line_index -= 1
- @byte_pointer = current_line.bytesize
- end
- 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, = Reline::Unicode.vi_first_print(current_line)
- end
-
- private def ed_move_to_beg(key)
- @byte_pointer = 0
- end
- alias_method :beginning_of_line, :ed_move_to_beg
- alias_method :vi_zero, :ed_move_to_beg
-
- private def ed_move_to_end(key)
- @byte_pointer = current_line.bytesize
- end
- alias_method :end_of_line, :ed_move_to_end
-
- private def generate_searcher(search_key)
- search_word = String.new(encoding: @encoding)
- multibyte_buf = String.new(encoding: 'ASCII-8BIT')
- hit_pointer = nil
- lambda do |key|
- search_again = false
- case key
- when "\C-h".ord, "\C-?".ord
- grapheme_clusters = search_word.grapheme_clusters
- if grapheme_clusters.size > 0
- grapheme_clusters.pop
- search_word = grapheme_clusters.join
- end
- when "\C-r".ord, "\C-s".ord
- search_again = true if search_key == key
- search_key = key
- else
- multibyte_buf << key
- if multibyte_buf.dup.force_encoding(@encoding).valid_encoding?
- search_word << multibyte_buf.dup.force_encoding(@encoding)
- multibyte_buf.clear
- end
- end
- hit = nil
- if not search_word.empty? and @line_backup_in_history&.include?(search_word)
- hit_pointer = Reline::HISTORY.size
- hit = @line_backup_in_history
- else
- if search_again
- if search_word.empty? and Reline.last_incremental_search
- search_word = Reline.last_incremental_search
- end
- if @history_pointer
- case search_key
- when "\C-r".ord
- history_pointer_base = 0
- history = Reline::HISTORY[0..(@history_pointer - 1)]
- when "\C-s".ord
- history_pointer_base = @history_pointer + 1
- history = Reline::HISTORY[(@history_pointer + 1)..-1]
- end
- else
- history_pointer_base = 0
- history = Reline::HISTORY
- end
- elsif @history_pointer
- case search_key
- when "\C-r".ord
- history_pointer_base = 0
- history = Reline::HISTORY[0..@history_pointer]
- when "\C-s".ord
- history_pointer_base = @history_pointer
- history = Reline::HISTORY[@history_pointer..-1]
- end
- else
- history_pointer_base = 0
- history = Reline::HISTORY
- end
- case search_key
- when "\C-r".ord
- hit_index = history.rindex { |item|
- item.include?(search_word)
- }
- when "\C-s".ord
- hit_index = history.index { |item|
- item.include?(search_word)
- }
- end
- if hit_index
- hit_pointer = history_pointer_base + hit_index
- hit = Reline::HISTORY[hit_pointer]
- end
- end
- case search_key
- when "\C-r".ord
- prompt_name = 'reverse-i-search'
- when "\C-s".ord
- prompt_name = 'i-search'
- end
- prompt_name = "failed #{prompt_name}" unless hit
- [search_word, prompt_name, hit_pointer]
- end
- end
-
- private def incremental_search_history(key)
- unless @history_pointer
- @line_backup_in_history = whole_buffer
- end
- searcher = generate_searcher(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 *termination_keys
- if @history_pointer
- buffer = Reline::HISTORY[@history_pointer]
- else
- buffer = @line_backup_in_history
- end
- @buffer_of_lines = buffer.split("\n")
- @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
- @line_index = @buffer_of_lines.size - 1
- @searching_prompt = nil
- @waiting_proc = nil
- @byte_pointer = 0
- when "\C-g".ord
- @buffer_of_lines = @line_backup_in_history.split("\n")
- @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
- @line_index = @buffer_of_lines.size - 1
- move_history(nil, line: :end, cursor: :end, save_buffer: false)
- @searching_prompt = nil
- @waiting_proc = nil
- @byte_pointer = 0
- else
- chr = k.is_a?(String) ? k : k.chr(Encoding::ASCII_8BIT)
- if chr.match?(/[[:print:]]/) or k == "\C-h".ord or k == "\C-?".ord or k == "\C-r".ord or k == "\C-s".ord
- search_word, prompt_name, hit_pointer = searcher.call(k)
- Reline.last_incremental_search = search_word
- @searching_prompt = "(%s)`%s'" % [prompt_name, search_word]
- @searching_prompt += ': ' unless @is_multiline
- move_history(hit_pointer, line: :end, cursor: :end, save_buffer: false) if hit_pointer
- else
- if @history_pointer
- line = Reline::HISTORY[@history_pointer]
- else
- line = @line_backup_in_history
- end
- @line_backup_in_history = whole_buffer
- @buffer_of_lines = line.split("\n")
- @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
- @line_index = @buffer_of_lines.size - 1
- @searching_prompt = nil
- @waiting_proc = nil
- @byte_pointer = 0
- end
- end
- }
- end
-
- 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 :forward_search_history, :vi_search_next
-
- private def search_history(prefix, pointer_range)
- pointer_range.each do |pointer|
- lines = Reline::HISTORY[pointer].split("\n")
- lines.each_with_index do |line, index|
- return [pointer, index] if line.start_with?(prefix)
- end
- end
- nil
- end
-
- private def ed_search_prev_history(key, arg: 1)
- substr = current_line.byteslice(0, @byte_pointer)
- return if @history_pointer == 0
- return if @history_pointer.nil? && substr.empty? && !current_line.empty?
-
- history_range = 0...(@history_pointer || Reline::HISTORY.size)
- h_pointer, line_index = search_history(substr, history_range.reverse_each)
- return unless h_pointer
- move_history(h_pointer, line: line_index || :start, cursor: @byte_pointer)
- 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 = current_line.byteslice(0, @byte_pointer)
- return if @history_pointer.nil?
-
- history_range = @history_pointer + 1...Reline::HISTORY.size
- h_pointer, line_index = search_history(substr, history_range)
- return if h_pointer.nil? and not substr.empty?
-
- move_history(h_pointer, line: line_index || :start, cursor: @byte_pointer)
- arg -= 1
- ed_search_next_history(key, arg: arg) if arg > 0
- end
- alias_method :history_search_forward, :ed_search_next_history
-
- private def move_history(history_pointer, line:, cursor:, save_buffer: true)
- history_pointer ||= Reline::HISTORY.size
- return if history_pointer < 0 || history_pointer > Reline::HISTORY.size
- old_history_pointer = @history_pointer || Reline::HISTORY.size
- if old_history_pointer == Reline::HISTORY.size
- @line_backup_in_history = save_buffer ? whole_buffer : ''
- else
- Reline::HISTORY[old_history_pointer] = whole_buffer if save_buffer
- end
- if history_pointer == Reline::HISTORY.size
- buf = @line_backup_in_history
- @history_pointer = @line_backup_in_history = nil
- else
- buf = Reline::HISTORY[history_pointer]
- @history_pointer = history_pointer
- end
- @buffer_of_lines = buf.split("\n")
- @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
- @line_index = line == :start ? 0 : line == :end ? @buffer_of_lines.size - 1 : line
- @byte_pointer = cursor == :start ? 0 : cursor == :end ? current_line.bytesize : cursor
- end
-
- private def ed_prev_history(key, arg: 1)
- if @line_index > 0
- cursor = current_byte_pointer_cursor
- @line_index -= 1
- calculate_nearest_cursor(cursor)
- return
- end
- move_history(
- (@history_pointer || Reline::HISTORY.size) - 1,
- line: :end,
- cursor: @config.editing_mode_is?(:vi_command) ? :start : :end,
- )
- 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 @line_index < (@buffer_of_lines.size - 1)
- cursor = current_byte_pointer_cursor
- @line_index += 1
- calculate_nearest_cursor(cursor)
- return
- end
- move_history(
- (@history_pointer || Reline::HISTORY.size) + 1,
- line: :start,
- cursor: @config.editing_mode_is?(:vi_command) ? :start : :end,
- )
- 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)
- ed_next_history(key) # means cursor down
- else
- # should check confirm_multiline_termination to finish?
- finish
- end
- else
- if @line_index == (@buffer_of_lines.size - 1)
- if confirm_multiline_termination
- finish
- else
- key_newline(key)
- end
- else
- # should check confirm_multiline_termination to finish?
- @line_index = @buffer_of_lines.size - 1
- @byte_pointer = current_line.bytesize
- finish
- end
- end
- else
- finish
- end
- end
-
- private def em_delete_prev_char(key, arg: 1)
- arg.times do
- if @byte_pointer == 0 and @line_index > 0
- @byte_pointer = @buffer_of_lines[@line_index - 1].bytesize
- @buffer_of_lines[@line_index - 1] += @buffer_of_lines.delete_at(@line_index)
- @line_index -= 1
- elsif @byte_pointer > 0
- byte_size = Reline::Unicode.get_prev_mbchar_size(current_line, @byte_pointer)
- line, = byteslice!(current_line, @byte_pointer - byte_size, byte_size)
- set_current_line(line, @byte_pointer - byte_size)
- end
- end
- process_auto_indent
- 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 current_line.bytesize > @byte_pointer
- line, deleted = byteslice!(current_line, @byte_pointer, current_line.bytesize - @byte_pointer)
- set_current_line(line, line.bytesize)
- @kill_ring.append(deleted)
- elsif @byte_pointer == current_line.bytesize and @buffer_of_lines.size > @line_index + 1
- set_current_line(current_line + @buffer_of_lines.delete_at(@line_index + 1), current_line.bytesize)
- end
- end
- alias_method :kill_line, :ed_kill_line
-
- # Editline:: +vi_change_to_eol+ (vi command: +C+) + Kill and change from the cursor to the end of the line.
- private def vi_change_to_eol(key)
- ed_kill_line(key)
-
- @config.editing_mode = :vi_insert
- end
-
- # 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!(current_line, 0, @byte_pointer)
- set_current_line(line, 0)
- @kill_ring.append(deleted, true)
- 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 current_line.size > 0
- @kill_ring.append(current_line.dup, true)
- set_current_line('', 0)
- end
- end
- alias_method :kill_whole_line, :em_kill_line
-
- private def em_delete(key)
- if current_line.empty? and @buffer_of_lines.size == 1 and key == "\C-d".ord
- @eof = true
- finish
- elsif @byte_pointer < current_line.bytesize
- splitted_last = current_line.byteslice(@byte_pointer, current_line.bytesize)
- mbchar = splitted_last.grapheme_clusters.first
- line, = byteslice!(current_line, @byte_pointer, mbchar.bytesize)
- set_current_line(line)
- elsif @byte_pointer == current_line.bytesize and @buffer_of_lines.size > @line_index + 1
- set_current_line(current_line + @buffer_of_lines.delete_at(@line_index + 1), current_line.bytesize)
- end
- end
- alias_method :delete_char, :em_delete
-
- private def em_delete_or_list(key)
- if current_line.empty? or @byte_pointer < current_line.bytesize
- em_delete(key)
- elsif !@config.autocompletion # show completed list
- result = call_completion_proc
- if result.is_a?(Array)
- perform_completion(result, true)
- end
- end
- end
- alias_method :delete_char_or_list, :em_delete_or_list
-
- private def em_yank(key)
- yanked = @kill_ring.yank
- insert_text(yanked) if yanked
- end
- alias_method :yank, :em_yank
-
- private def em_yank_pop(key)
- yanked, prev_yank = @kill_ring.yank_pop
- if yanked
- line, = byteslice!(current_line, @byte_pointer - prev_yank.bytesize, prev_yank.bytesize)
- set_current_line(line, @byte_pointer - prev_yank.bytesize)
- insert_text(yanked)
- end
- end
- alias_method :yank_pop, :em_yank_pop
-
- private def ed_clear_screen(key)
- Reline::IOGate.clear_screen
- @screen_size = Reline::IOGate.get_screen_size
- @rendered_screen.lines = []
- @rendered_screen.base_y = 0
- @rendered_screen.cursor_y = 0
- end
- alias_method :clear_screen, :ed_clear_screen
-
- private def em_next_word(key)
- if current_line.bytesize > @byte_pointer
- byte_size, _ = Reline::Unicode.em_forward_word(current_line, @byte_pointer)
- @byte_pointer += byte_size
- end
- end
- alias_method :forward_word, :em_next_word
-
- private def ed_prev_word(key)
- if @byte_pointer > 0
- byte_size, _ = Reline::Unicode.em_backward_word(current_line, @byte_pointer)
- @byte_pointer -= byte_size
- end
- end
- alias_method :backward_word, :ed_prev_word
-
- private def em_delete_next_word(key)
- if current_line.bytesize > @byte_pointer
- byte_size, _ = Reline::Unicode.em_forward_word(current_line, @byte_pointer)
- line, word = byteslice!(current_line, @byte_pointer, byte_size)
- set_current_line(line)
- @kill_ring.append(word)
- end
- end
- alias_method :kill_word, :em_delete_next_word
-
- private def ed_delete_prev_word(key)
- if @byte_pointer > 0
- byte_size, _ = Reline::Unicode.em_backward_word(current_line, @byte_pointer)
- line, word = byteslice!(current_line, @byte_pointer - byte_size, byte_size)
- set_current_line(line, @byte_pointer - byte_size)
- @kill_ring.append(word, true)
- end
- end
- alias_method :backward_kill_word, :ed_delete_prev_word
-
- private def ed_transpose_chars(key)
- if @byte_pointer > 0
- if @byte_pointer < current_line.bytesize
- byte_size = Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer)
- @byte_pointer += byte_size
- end
- back1_byte_size = Reline::Unicode.get_prev_mbchar_size(current_line, @byte_pointer)
- if (@byte_pointer - back1_byte_size) > 0
- back2_byte_size = Reline::Unicode.get_prev_mbchar_size(current_line, @byte_pointer - back1_byte_size)
- back2_pointer = @byte_pointer - back1_byte_size - back2_byte_size
- line, back2_mbchar = byteslice!(current_line, back2_pointer, back2_byte_size)
- set_current_line(byteinsert(line, @byte_pointer - back2_byte_size, back2_mbchar))
- end
- end
- end
- alias_method :transpose_chars, :ed_transpose_chars
-
- private def ed_transpose_words(key)
- left_word_start, middle_start, right_word_start, after_start = Reline::Unicode.ed_transpose_words(current_line, @byte_pointer)
- before = current_line.byteslice(0, left_word_start)
- left_word = current_line.byteslice(left_word_start, middle_start - left_word_start)
- middle = current_line.byteslice(middle_start, right_word_start - middle_start)
- right_word = current_line.byteslice(right_word_start, after_start - right_word_start)
- after = current_line.byteslice(after_start, current_line.bytesize - after_start)
- return if left_word.empty? or right_word.empty?
- from_head_to_left_word = before + right_word + middle + left_word
- set_current_line(from_head_to_left_word + after, from_head_to_left_word.bytesize)
- end
- alias_method :transpose_words, :ed_transpose_words
-
- private def em_capitol_case(key)
- if current_line.bytesize > @byte_pointer
- byte_size, _, new_str = Reline::Unicode.em_forward_word_with_capitalization(current_line, @byte_pointer)
- before = current_line.byteslice(0, @byte_pointer)
- after = current_line.byteslice((@byte_pointer + byte_size)..-1)
- set_current_line(before + new_str + after, @byte_pointer + new_str.bytesize)
- end
- end
- alias_method :capitalize_word, :em_capitol_case
-
- private def em_lower_case(key)
- if current_line.bytesize > @byte_pointer
- byte_size, = Reline::Unicode.em_forward_word(current_line, @byte_pointer)
- part = current_line.byteslice(@byte_pointer, byte_size).grapheme_clusters.map { |mbchar|
- mbchar =~ /[A-Z]/ ? mbchar.downcase : mbchar
- }.join
- rest = current_line.byteslice((@byte_pointer + byte_size)..-1)
- line = current_line.byteslice(0, @byte_pointer) + part
- set_current_line(line + rest, line.bytesize)
- end
- end
- alias_method :downcase_word, :em_lower_case
-
- private def em_upper_case(key)
- if current_line.bytesize > @byte_pointer
- byte_size, = Reline::Unicode.em_forward_word(current_line, @byte_pointer)
- part = current_line.byteslice(@byte_pointer, byte_size).grapheme_clusters.map { |mbchar|
- mbchar =~ /[a-z]/ ? mbchar.upcase : mbchar
- }.join
- rest = current_line.byteslice((@byte_pointer + byte_size)..-1)
- line = current_line.byteslice(0, @byte_pointer) + part
- set_current_line(line + rest, line.bytesize)
- end
- end
- alias_method :upcase_word, :em_upper_case
-
- private def em_kill_region(key)
- if @byte_pointer > 0
- byte_size, _ = Reline::Unicode.em_big_backward_word(current_line, @byte_pointer)
- line, deleted = byteslice!(current_line, @byte_pointer - byte_size, byte_size)
- set_current_line(line, @byte_pointer - byte_size)
- @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)
- @vi_clipboard = text
- end
- end
-
- private def vi_insert(key)
- @config.editing_mode = :vi_insert
- end
-
- private def vi_add(key)
- @config.editing_mode = :vi_insert
- ed_next_char(key)
- end
-
- private def vi_command_mode(key)
- ed_prev_char(key)
- @config.editing_mode = :vi_command
- end
- alias_method :vi_movement_mode, :vi_command_mode
-
- private def vi_next_word(key, arg: 1)
- if current_line.bytesize > @byte_pointer
- byte_size, _ = Reline::Unicode.vi_forward_word(current_line, @byte_pointer, @drop_terminate_spaces)
- @byte_pointer += byte_size
- end
- arg -= 1
- vi_next_word(key, arg: arg) if arg > 0
- end
-
- private def vi_prev_word(key, arg: 1)
- if @byte_pointer > 0
- byte_size, _ = Reline::Unicode.vi_backward_word(current_line, @byte_pointer)
- @byte_pointer -= byte_size
- end
- arg -= 1
- vi_prev_word(key, arg: arg) if arg > 0
- end
-
- private def vi_end_word(key, arg: 1, inclusive: false)
- if current_line.bytesize > @byte_pointer
- byte_size, _ = Reline::Unicode.vi_forward_end_word(current_line, @byte_pointer)
- @byte_pointer += byte_size
- end
- arg -= 1
- if inclusive and arg.zero?
- byte_size = Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer)
- if byte_size > 0
- @byte_pointer += byte_size
- end
- end
- vi_end_word(key, arg: arg) if arg > 0
- end
-
- private def vi_next_big_word(key, arg: 1)
- if current_line.bytesize > @byte_pointer
- byte_size, _ = Reline::Unicode.vi_big_forward_word(current_line, @byte_pointer)
- @byte_pointer += byte_size
- end
- arg -= 1
- vi_next_big_word(key, arg: arg) if arg > 0
- end
-
- private def vi_prev_big_word(key, arg: 1)
- if @byte_pointer > 0
- byte_size, _ = Reline::Unicode.vi_big_backward_word(current_line, @byte_pointer)
- @byte_pointer -= byte_size
- end
- arg -= 1
- vi_prev_big_word(key, arg: arg) if arg > 0
- end
-
- private def vi_end_big_word(key, arg: 1, inclusive: false)
- if current_line.bytesize > @byte_pointer
- byte_size, _ = Reline::Unicode.vi_big_forward_end_word(current_line, @byte_pointer)
- @byte_pointer += byte_size
- end
- arg -= 1
- if inclusive and arg.zero?
- byte_size = Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer)
- if byte_size > 0
- @byte_pointer += byte_size
- end
- end
- vi_end_big_word(key, arg: arg) if arg > 0
- end
-
- private def vi_delete_prev_char(key)
- if @byte_pointer == 0 and @line_index > 0
- @byte_pointer = @buffer_of_lines[@line_index - 1].bytesize
- @buffer_of_lines[@line_index - 1] += @buffer_of_lines.delete_at(@line_index)
- @line_index -= 1
- process_auto_indent cursor_dependent: false
- elsif @byte_pointer > 0
- byte_size = Reline::Unicode.get_prev_mbchar_size(current_line, @byte_pointer)
- @byte_pointer -= byte_size
- line, _ = byteslice!(current_line, @byte_pointer, byte_size)
- set_current_line(line)
- end
- end
-
- private def vi_insert_at_bol(key)
- ed_move_to_beg(key)
- @config.editing_mode = :vi_insert
- end
-
- private def vi_add_at_eol(key)
- ed_move_to_end(key)
- @config.editing_mode = :vi_insert
- end
-
- private def ed_delete_prev_char(key, arg: 1)
- deleted = +''
- arg.times do
- if @byte_pointer > 0
- byte_size = Reline::Unicode.get_prev_mbchar_size(current_line, @byte_pointer)
- @byte_pointer -= byte_size
- line, mbchar = byteslice!(current_line, @byte_pointer, byte_size)
- set_current_line(line)
- deleted.prepend(mbchar)
- end
- end
- copy_for_vi(deleted)
- end
-
- private def vi_change_meta(key, arg: nil)
- if @vi_waiting_operator
- set_current_line('', 0) if @vi_waiting_operator == :vi_change_meta_confirm && arg.nil?
- @vi_waiting_operator = nil
- @vi_waiting_operator_arg = nil
- else
- @drop_terminate_spaces = true
- @vi_waiting_operator = :vi_change_meta_confirm
- @vi_waiting_operator_arg = arg || 1
- end
- end
-
- private def vi_change_meta_confirm(byte_pointer_diff)
- vi_delete_meta_confirm(byte_pointer_diff)
- @config.editing_mode = :vi_insert
- @drop_terminate_spaces = false
- end
-
- private def vi_delete_meta(key, arg: nil)
- if @vi_waiting_operator
- set_current_line('', 0) if @vi_waiting_operator == :vi_delete_meta_confirm && arg.nil?
- @vi_waiting_operator = nil
- @vi_waiting_operator_arg = nil
- else
- @vi_waiting_operator = :vi_delete_meta_confirm
- @vi_waiting_operator_arg = arg || 1
- end
- end
-
- private def vi_delete_meta_confirm(byte_pointer_diff)
- if byte_pointer_diff > 0
- line, cut = byteslice!(current_line, @byte_pointer, byte_pointer_diff)
- elsif byte_pointer_diff < 0
- line, cut = byteslice!(current_line, @byte_pointer + byte_pointer_diff, -byte_pointer_diff)
- end
- copy_for_vi(cut)
- set_current_line(line || '', @byte_pointer + (byte_pointer_diff < 0 ? byte_pointer_diff : 0))
- end
-
- private def vi_yank(key, arg: nil)
- if @vi_waiting_operator
- copy_for_vi(current_line) if @vi_waiting_operator == :vi_yank_confirm && arg.nil?
- @vi_waiting_operator = nil
- @vi_waiting_operator_arg = nil
- else
- @vi_waiting_operator = :vi_yank_confirm
- @vi_waiting_operator_arg = arg || 1
- end
- end
-
- private def vi_yank_confirm(byte_pointer_diff)
- if byte_pointer_diff > 0
- cut = current_line.byteslice(@byte_pointer, byte_pointer_diff)
- elsif byte_pointer_diff < 0
- cut = current_line.byteslice(@byte_pointer + byte_pointer_diff, -byte_pointer_diff)
- end
- copy_for_vi(cut)
- end
-
- private def vi_list_or_eof(key)
- if current_line.empty? and @buffer_of_lines.size == 1
- set_current_line('', 0)
- @eof = true
- finish
- else
- ed_newline(key)
- end
- end
- alias_method :vi_end_of_transmission, :vi_list_or_eof
- alias_method :vi_eof_maybe, :vi_list_or_eof
-
- private def ed_delete_next_char(key, arg: 1)
- byte_size = Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer)
- unless current_line.empty? || byte_size == 0
- line, mbchar = byteslice!(current_line, @byte_pointer, byte_size)
- copy_for_vi(mbchar)
- if @byte_pointer > 0 && current_line.bytesize == @byte_pointer + byte_size
- byte_size = Reline::Unicode.get_prev_mbchar_size(line, @byte_pointer)
- set_current_line(line, @byte_pointer - byte_size)
- else
- set_current_line(line, @byte_pointer)
- end
- end
- arg -= 1
- ed_delete_next_char(key, arg: arg) if arg > 0
- end
-
- private def vi_to_history_line(key)
- if Reline::HISTORY.empty?
- return
- end
- move_history(0, line: :start, cursor: :start)
- end
-
- private def vi_histedit(key)
- path = Tempfile.open { |fp|
- fp.write whole_lines.join("\n")
- fp.path
- }
- system("#{ENV['EDITOR']} #{path}")
- @buffer_of_lines = File.read(path).split("\n")
- @buffer_of_lines = [String.new(encoding: @encoding)] if @buffer_of_lines.empty?
- @line_index = 0
- finish
- end
-
- private def vi_paste_prev(key, arg: 1)
- if @vi_clipboard.size > 0
- cursor_point = @vi_clipboard.grapheme_clusters[0..-2].join
- set_current_line(byteinsert(current_line, @byte_pointer, @vi_clipboard), @byte_pointer + cursor_point.bytesize)
- end
- arg -= 1
- vi_paste_prev(key, arg: arg) if arg > 0
- end
-
- private def vi_paste_next(key, arg: 1)
- if @vi_clipboard.size > 0
- byte_size = Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer)
- line = byteinsert(current_line, @byte_pointer + byte_size, @vi_clipboard)
- set_current_line(line, @byte_pointer + @vi_clipboard.bytesize)
- end
- arg -= 1
- vi_paste_next(key, arg: arg) if arg > 0
- end
-
- private def ed_argument_digit(key)
- if @vi_arg.nil?
- 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
- @vi_arg = @vi_arg * 10 + key.chr.to_i
- end
- end
-
- private def vi_to_column(key, arg: 0)
- # Implementing behavior of vi, not Readline's vi-mode.
- @byte_pointer, = current_line.grapheme_clusters.inject([0, 0]) { |(total_byte_size, total_width), gc|
- mbchar_width = Reline::Unicode.get_mbchar_width(gc)
- break [total_byte_size, total_width] if (total_width + mbchar_width) >= arg
- [total_byte_size + gc.bytesize, total_width + mbchar_width]
- }
- end
-
- private def vi_replace_char(key, arg: 1)
- @waiting_proc = ->(k) {
- if arg == 1
- byte_size = Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer)
- before = current_line.byteslice(0, @byte_pointer)
- remaining_point = @byte_pointer + byte_size
- after = current_line.byteslice(remaining_point, current_line.bytesize - remaining_point)
- set_current_line(before + k.chr + after)
- @waiting_proc = nil
- elsif arg > 1
- byte_size = 0
- arg.times do
- byte_size += Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer + byte_size)
- end
- before = current_line.byteslice(0, @byte_pointer)
- remaining_point = @byte_pointer + byte_size
- after = current_line.byteslice(remaining_point, current_line.bytesize - remaining_point)
- replaced = k.chr * arg
- set_current_line(before + replaced + after, @byte_pointer + replaced.bytesize)
- @waiting_proc = nil
- end
- }
- end
-
- 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, 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, inclusive: false)
- if key.instance_of?(String)
- inputed_char = key
- else
- inputed_char = key.chr
- end
- prev_total = nil
- total = nil
- found = false
- current_line.byteslice(@byte_pointer..-1).grapheme_clusters.each do |mbchar|
- # total has [byte_size, cursor]
- unless total
- # skip cursor point
- width = Reline::Unicode.get_mbchar_width(mbchar)
- total = [mbchar.bytesize, width]
- else
- if inputed_char == mbchar
- arg -= 1
- if arg.zero?
- found = true
- break
- end
- end
- width = Reline::Unicode.get_mbchar_width(mbchar)
- prev_total = total
- total = [total.first + mbchar.bytesize, total.last + width]
- end
- end
- if not need_prev_char and found and total
- byte_size, _ = total
- @byte_pointer += byte_size
- elsif need_prev_char and found and prev_total
- byte_size, _ = prev_total
- @byte_pointer += byte_size
- end
- if inclusive
- byte_size = Reline::Unicode.get_next_mbchar_size(current_line, @byte_pointer)
- if byte_size > 0
- @byte_pointer += byte_size
- end
- end
- @waiting_proc = nil
- end
-
- private def vi_prev_char(key, arg: 1)
- @waiting_proc = ->(key_for_proc) { search_prev_char(key_for_proc, arg) }
- end
-
- private def vi_to_prev_char(key, arg: 1)
- @waiting_proc = ->(key_for_proc) { search_prev_char(key_for_proc, arg, true) }
- end
-
- private def search_prev_char(key, arg, need_next_char = false)
- if key.instance_of?(String)
- inputed_char = key
- else
- inputed_char = key.chr
- end
- prev_total = nil
- total = nil
- found = false
- current_line.byteslice(0..@byte_pointer).grapheme_clusters.reverse_each do |mbchar|
- # total has [byte_size, cursor]
- unless total
- # skip cursor point
- width = Reline::Unicode.get_mbchar_width(mbchar)
- total = [mbchar.bytesize, width]
- else
- if inputed_char == mbchar
- arg -= 1
- if arg.zero?
- found = true
- break
- end
- end
- width = Reline::Unicode.get_mbchar_width(mbchar)
- prev_total = total
- total = [total.first + mbchar.bytesize, total.last + width]
- end
- end
- if not need_next_char and found and total
- byte_size, _ = total
- @byte_pointer -= byte_size
- elsif need_next_char and found and prev_total
- byte_size, _ = prev_total
- @byte_pointer -= byte_size
- end
- @waiting_proc = nil
- end
-
- private def vi_join_lines(key, arg: 1)
- if @buffer_of_lines.size > @line_index + 1
- next_line = @buffer_of_lines.delete_at(@line_index + 1).lstrip
- set_current_line(current_line + ' ' + next_line, current_line.bytesize)
- end
- arg -= 1
- vi_join_lines(key, arg: arg) if arg > 0
- end
-
- private def em_set_mark(key)
- @mark_pointer = [@byte_pointer, @line_index]
- end
- alias_method :set_mark, :em_set_mark
-
- private def em_exchange_mark(key)
- return unless @mark_pointer
- new_pointer = [@byte_pointer, @line_index]
- @byte_pointer, @line_index = @mark_pointer
- @mark_pointer = new_pointer
- end
- alias_method :exchange_point_and_mark, :em_exchange_mark
-
- private def emacs_editing_mode(key)
- @config.editing_mode = :emacs
- end
-
- private def vi_editing_mode(key)
- @config.editing_mode = :vi_insert
- end
-
- private def undo(_key)
- @undoing = true
-
- return if @input_lines_position <= 0
-
- @input_lines_position -= 1
- target_lines, target_cursor_x, target_cursor_y = @input_lines[@input_lines_position]
- set_current_lines(target_lines.dup, target_cursor_x, target_cursor_y)
- end
-
- private def redo(_key)
- @undoing = true
-
- return if @input_lines_position >= @input_lines.size - 1
-
- @input_lines_position += 1
- target_lines, target_cursor_x, target_cursor_y = @input_lines[@input_lines_position]
- set_current_lines(target_lines.dup, target_cursor_x, target_cursor_y)
- end
-end
diff --git a/lib/reline/reline.gemspec b/lib/reline/reline.gemspec
deleted file mode 100644
index dfaf966728..0000000000
--- a/lib/reline/reline.gemspec
+++ /dev/null
@@ -1,30 +0,0 @@
-
-begin
- require_relative 'lib/reline/version'
-rescue LoadError
- require_relative 'version'
-end
-
-Gem::Specification.new do |spec|
- spec.name = 'reline'
- spec.version = Reline::VERSION
- spec.authors = ['aycabta']
- spec.email = ['aycabta@gmail.com']
-
- 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'
-
- spec.files = Dir['BSDL', 'COPYING', 'README.md', 'license_of_rb-readline', 'lib/**/*']
- spec.require_paths = ['lib']
- spec.metadata = {
- "bug_tracker_uri" => "https://github.com/ruby/reline/issues",
- "changelog_uri" => "https://github.com/ruby/reline/releases",
- "source_code_uri" => "https://github.com/ruby/reline"
- }
-
- spec.required_ruby_version = Gem::Requirement.new('>= 2.6')
-
- spec.add_dependency 'io-console', '~> 0.5'
-end
diff --git a/lib/reline/terminfo.rb b/lib/reline/terminfo.rb
deleted file mode 100644
index 6885a0c6be..0000000000
--- a/lib/reline/terminfo.rb
+++ /dev/null
@@ -1,153 +0,0 @@
-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 Fiddle.const_defined?(:TYPE_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
- begin
- #extern 'int tigetflag(char *str)'
- @tigetflag = Fiddle::Function.new(curses_dl['tigetflag'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
- rescue Fiddle::DLError
- # OpenBSD lacks tigetflag
- #extern 'int tgetflag(char *str)'
- @tigetflag = Fiddle::Function.new(curses_dl['tgetflag'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
- end
- begin
- #extern 'int tigetnum(char *str)'
- @tigetnum = Fiddle::Function.new(curses_dl['tigetnum'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
- rescue Fiddle::DLError
- # OpenBSD lacks tigetnum
- #extern 'int tgetnum(char *str)'
- @tigetnum = Fiddle::Function.new(curses_dl['tgetnum'], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT)
- end
-
- def self.setupterm(term, fildes)
- errret_int = Fiddle::Pointer.malloc(Fiddle::SIZEOF_INT)
- ret = @setupterm.(term, fildes, errret_int)
- case ret
- when 0 # OK
- @term_supported = true
- when -1 # ERR
- @term_supported = false
- end
- end
-
- class StringWithTiparm < String
- def tiparm(*args) # for method chain
- Reline::Terminfo.tiparm(self, *args)
- end
- end
-
- def self.tigetstr(capname)
- raise TerminfoError, "capname is not String: #{capname.inspect}" unless capname.is_a?(String)
- 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.tigetflag(capname)
- raise TerminfoError, "capname is not String: #{capname.inspect}" unless capname.is_a?(String)
- flag = @tigetflag.(capname).to_i
- case flag
- when -1
- raise TerminfoError, "not boolean capability: #{capname}"
- when 0
- raise TerminfoError, "can't find capability: #{capname}"
- end
- flag
- end
-
- def self.tigetnum(capname)
- raise TerminfoError, "capname is not String: #{capname.inspect}" unless capname.is_a?(String)
- num = @tigetnum.(capname).to_i
- case num
- when -2
- raise TerminfoError, "not numeric capability: #{capname}"
- when -1
- raise TerminfoError, "can't find capability: #{capname}"
- end
- num
- end
-
- # NOTE: This means Fiddle and curses are enabled.
- def self.enabled?
- true
- end
-
- def self.term_supported?
- @term_supported
- end
-end if Reline::Terminfo.curses_dl
-
-module Reline::Terminfo
- def self.enabled?
- false
- end
-end unless Reline::Terminfo.curses_dl
diff --git a/lib/reline/unicode.rb b/lib/reline/unicode.rb
deleted file mode 100644
index d7460d6d4a..0000000000
--- a/lib/reline/unicode.rb
+++ /dev/null
@@ -1,696 +0,0 @@
-class Reline::Unicode
- EscapedPairs = {
- 0x00 => '^@',
- 0x01 => '^A', # C-a
- 0x02 => '^B',
- 0x03 => '^C',
- 0x04 => '^D',
- 0x05 => '^E',
- 0x06 => '^F',
- 0x07 => '^G',
- 0x08 => '^H', # Backspace
- 0x09 => '^I',
- 0x0A => '^J',
- 0x0B => '^K',
- 0x0C => '^L',
- 0x0D => '^M', # Enter
- 0x0E => '^N',
- 0x0F => '^O',
- 0x10 => '^P',
- 0x11 => '^Q',
- 0x12 => '^R',
- 0x13 => '^S',
- 0x14 => '^T',
- 0x15 => '^U',
- 0x16 => '^V',
- 0x17 => '^W',
- 0x18 => '^X',
- 0x19 => '^Y',
- 0x1A => '^Z', # C-z
- 0x1B => '^[', # C-[ C-3
- 0x1D => '^]', # C-]
- 0x1E => '^^', # C-~ C-6
- 0x1F => '^_', # C-_ C-7
- 0x7F => '^?', # C-? C-8
- }
- EscapedChars = EscapedPairs.keys.map(&:chr)
-
- NON_PRINTING_START = "\1"
- NON_PRINTING_END = "\2"
- CSI_REGEXP = /\e\[[\d;]*[ABCDEFGHJKSTfminsuhl]/
- OSC_REGEXP = /\e\]\d+(?:;[^;\a\e]+)*(?:\a|\e\\)/
- WIDTH_SCANNER = /\G(?:(#{NON_PRINTING_START})|(#{NON_PRINTING_END})|(#{CSI_REGEXP})|(#{OSC_REGEXP})|(\X))/o
-
- def self.escape_for_print(str)
- str.chars.map! { |gr|
- case gr
- when -"\n"
- gr
- when -"\t"
- -' '
- else
- EscapedPairs[gr.ord] || gr
- end
- }.join
- end
-
- require 'reline/unicode/east_asian_width'
-
- HalfwidthDakutenHandakuten = /[\u{FF9E}\u{FF9F}]/
-
- MBCharWidthRE = /
- (?<width_2_1>
- [#{ EscapedChars.map {|c| "\\x%02x" % c.ord }.join }] (?# ^ + char, such as ^M, ^H, ^[, ...)
- )
- | (?<width_3>^\u{2E3B}) (?# THREE-EM DASH)
- | (?<width_0>^\p{M})
- | (?<width_2_2>
- #{ EastAsianWidth::TYPE_F }
- | #{ EastAsianWidth::TYPE_W }
- )
- | (?<width_1>
- #{ EastAsianWidth::TYPE_H }
- | #{ EastAsianWidth::TYPE_NA }
- | #{ EastAsianWidth::TYPE_N }
- )(?!#{ HalfwidthDakutenHandakuten })
- | (?<width_2_3>
- (?: #{ EastAsianWidth::TYPE_H }
- | #{ EastAsianWidth::TYPE_NA }
- | #{ EastAsianWidth::TYPE_N })
- #{ HalfwidthDakutenHandakuten }
- )
- | (?<ambiguous_width>
- #{EastAsianWidth::TYPE_A}
- )
- /x
-
- def self.get_mbchar_width(mbchar)
- 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 |non_printing_start, non_printing_end, csi, osc, gc|
- case
- when non_printing_start
- in_zero_width = true
- when non_printing_end
- in_zero_width = false
- when csi, osc
- when gc
- 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, offset: 0)
- lines = [String.new(encoding: encoding)]
- height = 1
- width = offset
- rest = str.encode(Encoding::UTF_8)
- in_zero_width = false
- seq = String.new(encoding: encoding)
- rest.scan(WIDTH_SCANNER) do |non_printing_start, non_printing_end, csi, osc, gc|
- case
- when non_printing_start
- in_zero_width = true
- lines.last << NON_PRINTING_START
- when non_printing_end
- in_zero_width = false
- lines.last << NON_PRINTING_END
- when csi
- lines.last << csi
- unless in_zero_width
- if csi == -"\e[m" || csi == -"\e[0m"
- seq.clear
- else
- seq << csi
- end
- end
- when osc
- lines.last << osc
- seq << osc
- when gc
- unless in_zero_width
- mbchar_width = get_mbchar_width(gc)
- if (width += mbchar_width) > max_width
- width = mbchar_width
- lines << nil
- lines << seq.dup
- 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)
- take_mbchar_range(str, start_col, max_width).first
- end
-
- def self.take_mbchar_range(str, start_col, width, cover_begin: false, cover_end: false, padding: false)
- chunk = String.new(encoding: str.encoding)
-
- end_col = start_col + width
- total_width = 0
- rest = str.encode(Encoding::UTF_8)
- in_zero_width = false
- chunk_start_col = nil
- chunk_end_col = nil
- has_csi = false
- rest.scan(WIDTH_SCANNER) do |non_printing_start, non_printing_end, csi, osc, gc|
- case
- when non_printing_start
- in_zero_width = true
- chunk << NON_PRINTING_START
- when non_printing_end
- in_zero_width = false
- chunk << NON_PRINTING_END
- when csi
- has_csi = true
- chunk << csi
- when osc
- chunk << osc
- when gc
- if in_zero_width
- chunk << gc
- next
- end
-
- mbchar_width = get_mbchar_width(gc)
- prev_width = total_width
- total_width += mbchar_width
-
- if (cover_begin || padding ? total_width <= start_col : prev_width < start_col)
- # Current character haven't reached start_col yet
- next
- elsif padding && !cover_begin && prev_width < start_col && start_col < total_width
- # Add preceding padding. This padding might have background color.
- chunk << ' '
- chunk_start_col ||= start_col
- chunk_end_col = total_width
- next
- elsif (cover_end ? prev_width < end_col : total_width <= end_col)
- # Current character is in the range
- chunk << gc
- chunk_start_col ||= prev_width
- chunk_end_col = total_width
- break if total_width >= end_col
- else
- # Current character exceeds end_col
- if padding && end_col < total_width
- # Add succeeding padding. This padding might have background color.
- chunk << ' '
- chunk_start_col ||= prev_width
- chunk_end_col = end_col
- end
- break
- end
- end
- end
- chunk_start_col ||= start_col
- chunk_end_col ||= start_col
- if padding && chunk_end_col < end_col
- # Append padding. This padding should not include background color.
- chunk << "\e[0m" if has_csi
- chunk << ' ' * (end_col - chunk_end_col)
- chunk_end_col = end_col
- end
- [chunk, chunk_start_col, chunk_end_col - chunk_start_col]
- end
-
- def self.get_next_mbchar_size(line, byte_pointer)
- grapheme = line.byteslice(byte_pointer..-1).grapheme_clusters.first
- grapheme ? grapheme.bytesize : 0
- end
-
- def self.get_prev_mbchar_size(line, byte_pointer)
- if byte_pointer.zero?
- 0
- else
- grapheme = line.byteslice(0..(byte_pointer - 1)).grapheme_clusters.last
- grapheme ? grapheme.bytesize : 0
- end
- end
-
- def self.em_forward_word(line, byte_pointer)
- width = 0
- byte_size = 0
- 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.encode(Encoding::UTF_8) =~ /\p{Word}/
- width += get_mbchar_width(mbchar)
- byte_size += size
- end
- 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.encode(Encoding::UTF_8) =~ /\P{Word}/
- width += get_mbchar_width(mbchar)
- byte_size += size
- end
- [byte_size, width]
- end
-
- def self.em_forward_word_with_capitalization(line, byte_pointer)
- width = 0
- byte_size = 0
- new_str = String.new
- 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.encode(Encoding::UTF_8) =~ /\p{Word}/
- new_str += mbchar
- width += get_mbchar_width(mbchar)
- byte_size += size
- end
- first = true
- 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.encode(Encoding::UTF_8) =~ /\P{Word}/
- if first
- new_str += mbchar.upcase
- first = false
- else
- new_str += mbchar.downcase
- end
- width += get_mbchar_width(mbchar)
- byte_size += size
- end
- [byte_size, width, new_str]
- end
-
- def self.em_backward_word(line, byte_pointer)
- width = 0
- byte_size = 0
- while 0 < (byte_pointer - byte_size)
- size = get_prev_mbchar_size(line, byte_pointer - byte_size)
- mbchar = line.byteslice(byte_pointer - byte_size - size, size)
- break if mbchar.encode(Encoding::UTF_8) =~ /\p{Word}/
- width += get_mbchar_width(mbchar)
- byte_size += size
- end
- while 0 < (byte_pointer - byte_size)
- size = get_prev_mbchar_size(line, byte_pointer - byte_size)
- mbchar = line.byteslice(byte_pointer - byte_size - size, size)
- break if mbchar.encode(Encoding::UTF_8) =~ /\P{Word}/
- width += get_mbchar_width(mbchar)
- byte_size += size
- end
- [byte_size, width]
- end
-
- def self.em_big_backward_word(line, byte_pointer)
- width = 0
- byte_size = 0
- while 0 < (byte_pointer - byte_size)
- size = get_prev_mbchar_size(line, byte_pointer - byte_size)
- mbchar = line.byteslice(byte_pointer - byte_size - size, size)
- break if mbchar =~ /\S/
- width += get_mbchar_width(mbchar)
- byte_size += size
- end
- while 0 < (byte_pointer - byte_size)
- size = get_prev_mbchar_size(line, byte_pointer - byte_size)
- mbchar = line.byteslice(byte_pointer - byte_size - size, size)
- break if mbchar =~ /\s/
- width += get_mbchar_width(mbchar)
- byte_size += size
- end
- [byte_size, width]
- end
-
- def self.ed_transpose_words(line, byte_pointer)
- right_word_start = nil
- size = get_next_mbchar_size(line, byte_pointer)
- mbchar = line.byteslice(byte_pointer, size)
- if size.zero?
- # ' aaa bbb [cursor]'
- byte_size = 0
- while 0 < (byte_pointer + byte_size)
- size = get_prev_mbchar_size(line, byte_pointer + byte_size)
- mbchar = line.byteslice(byte_pointer + byte_size - size, size)
- break if mbchar.encode(Encoding::UTF_8) =~ /\p{Word}/
- byte_size -= size
- end
- while 0 < (byte_pointer + byte_size)
- size = get_prev_mbchar_size(line, byte_pointer + byte_size)
- mbchar = line.byteslice(byte_pointer + byte_size - size, size)
- break if mbchar.encode(Encoding::UTF_8) =~ /\P{Word}/
- byte_size -= size
- end
- right_word_start = byte_pointer + byte_size
- byte_size = 0
- 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.encode(Encoding::UTF_8) =~ /\P{Word}/
- byte_size += size
- end
- after_start = byte_pointer + byte_size
- elsif mbchar.encode(Encoding::UTF_8) =~ /\p{Word}/
- # ' aaa bb[cursor]b'
- byte_size = 0
- while 0 < (byte_pointer + byte_size)
- size = get_prev_mbchar_size(line, byte_pointer + byte_size)
- mbchar = line.byteslice(byte_pointer + byte_size - size, size)
- break if mbchar.encode(Encoding::UTF_8) =~ /\P{Word}/
- byte_size -= size
- end
- right_word_start = byte_pointer + byte_size
- byte_size = 0
- 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.encode(Encoding::UTF_8) =~ /\P{Word}/
- byte_size += size
- end
- after_start = byte_pointer + byte_size
- else
- byte_size = 0
- while (line.bytesize - 1) > (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.encode(Encoding::UTF_8) =~ /\p{Word}/
- byte_size += size
- end
- if (byte_pointer + byte_size) == (line.bytesize - 1)
- # ' aaa bbb [cursor] '
- after_start = line.bytesize
- while 0 < (byte_pointer + byte_size)
- size = get_prev_mbchar_size(line, byte_pointer + byte_size)
- mbchar = line.byteslice(byte_pointer + byte_size - size, size)
- break if mbchar.encode(Encoding::UTF_8) =~ /\p{Word}/
- byte_size -= size
- end
- while 0 < (byte_pointer + byte_size)
- size = get_prev_mbchar_size(line, byte_pointer + byte_size)
- mbchar = line.byteslice(byte_pointer + byte_size - size, size)
- break if mbchar.encode(Encoding::UTF_8) =~ /\P{Word}/
- byte_size -= size
- end
- right_word_start = byte_pointer + byte_size
- else
- # ' aaa [cursor] bbb '
- right_word_start = 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)
- break if mbchar.encode(Encoding::UTF_8) =~ /\P{Word}/
- byte_size += size
- end
- after_start = byte_pointer + byte_size
- end
- end
- byte_size = right_word_start - byte_pointer
- while 0 < (byte_pointer + byte_size)
- size = get_prev_mbchar_size(line, byte_pointer + byte_size)
- mbchar = line.byteslice(byte_pointer + byte_size - size, size)
- break if mbchar.encode(Encoding::UTF_8) =~ /\p{Word}/
- byte_size -= size
- end
- middle_start = byte_pointer + byte_size
- byte_size = middle_start - byte_pointer
- while 0 < (byte_pointer + byte_size)
- size = get_prev_mbchar_size(line, byte_pointer + byte_size)
- mbchar = line.byteslice(byte_pointer + byte_size - size, size)
- break if mbchar.encode(Encoding::UTF_8) =~ /\P{Word}/
- byte_size -= size
- end
- left_word_start = byte_pointer + byte_size
- [left_word_start, middle_start, right_word_start, after_start]
- end
-
- def self.vi_big_forward_word(line, byte_pointer)
- width = 0
- byte_size = 0
- while (line.bytesize - 1) > (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/
- width += get_mbchar_width(mbchar)
- byte_size += size
- end
- while (line.bytesize - 1) > (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/
- width += get_mbchar_width(mbchar)
- byte_size += size
- end
- [byte_size, width]
- end
-
- def self.vi_big_forward_end_word(line, byte_pointer)
- if (line.bytesize - 1) > byte_pointer
- size = get_next_mbchar_size(line, byte_pointer)
- mbchar = line.byteslice(byte_pointer, size)
- width = get_mbchar_width(mbchar)
- byte_size = size
- else
- return [0, 0]
- end
- while (line.bytesize - 1) > (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/
- width += get_mbchar_width(mbchar)
- byte_size += size
- end
- prev_width = width
- prev_byte_size = 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)
- break if mbchar =~ /\s/
- prev_width = width
- prev_byte_size = byte_size
- width += get_mbchar_width(mbchar)
- byte_size += size
- end
- [prev_byte_size, prev_width]
- end
-
- def self.vi_big_backward_word(line, byte_pointer)
- width = 0
- byte_size = 0
- while 0 < (byte_pointer - byte_size)
- size = get_prev_mbchar_size(line, byte_pointer - byte_size)
- mbchar = line.byteslice(byte_pointer - byte_size - size, size)
- break if mbchar =~ /\S/
- width += get_mbchar_width(mbchar)
- byte_size += size
- end
- while 0 < (byte_pointer - byte_size)
- size = get_prev_mbchar_size(line, byte_pointer - byte_size)
- mbchar = line.byteslice(byte_pointer - byte_size - size, size)
- break if mbchar =~ /\s/
- width += get_mbchar_width(mbchar)
- byte_size += size
- end
- [byte_size, width]
- end
-
- 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/
- started_by = :word
- elsif mbchar =~ /\s/
- started_by = :space
- else
- started_by = :non_word_printable
- end
- width = get_mbchar_width(mbchar)
- byte_size = size
- else
- return [0, 0]
- end
- 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
- when :word
- break if mbchar =~ /\W/
- when :space
- break if mbchar =~ /\S/
- when :non_word_printable
- break if mbchar =~ /\w|\s/
- end
- width += get_mbchar_width(mbchar)
- byte_size += size
- end
- 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/
- width += get_mbchar_width(mbchar)
- byte_size += size
- end
- [byte_size, width]
- end
-
- def self.vi_forward_end_word(line, byte_pointer)
- if (line.bytesize - 1) > byte_pointer
- size = get_next_mbchar_size(line, byte_pointer)
- mbchar = line.byteslice(byte_pointer, size)
- if mbchar =~ /\w/
- started_by = :word
- elsif mbchar =~ /\s/
- started_by = :space
- else
- started_by = :non_word_printable
- end
- width = get_mbchar_width(mbchar)
- byte_size = size
- else
- return [0, 0]
- end
- if (line.bytesize - 1) > (byte_pointer + byte_size)
- size = get_next_mbchar_size(line, byte_pointer + byte_size)
- mbchar = line.byteslice(byte_pointer + byte_size, size)
- if mbchar =~ /\w/
- second = :word
- elsif mbchar =~ /\s/
- second = :space
- else
- second = :non_word_printable
- end
- second_width = get_mbchar_width(mbchar)
- second_byte_size = size
- else
- return [byte_size, width]
- end
- if second == :space
- width += second_width
- byte_size += second_byte_size
- while (line.bytesize - 1) > (byte_pointer + byte_size)
- size = get_next_mbchar_size(line, byte_pointer + byte_size)
- mbchar = line.byteslice(byte_pointer + byte_size, size)
- if mbchar =~ /\S/
- if mbchar =~ /\w/
- started_by = :word
- else
- started_by = :non_word_printable
- end
- break
- end
- width += get_mbchar_width(mbchar)
- byte_size += size
- end
- else
- case [started_by, second]
- when [:word, :non_word_printable], [:non_word_printable, :word]
- started_by = second
- else
- width += second_width
- byte_size += second_byte_size
- started_by = second
- end
- end
- prev_width = width
- prev_byte_size = 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
- when :word
- break if mbchar =~ /\W/
- when :non_word_printable
- break if mbchar =~ /[\w\s]/
- end
- prev_width = width
- prev_byte_size = byte_size
- width += get_mbchar_width(mbchar)
- byte_size += size
- end
- [prev_byte_size, prev_width]
- end
-
- def self.vi_backward_word(line, byte_pointer)
- width = 0
- byte_size = 0
- while 0 < (byte_pointer - byte_size)
- size = get_prev_mbchar_size(line, byte_pointer - byte_size)
- mbchar = line.byteslice(byte_pointer - byte_size - size, size)
- if mbchar =~ /\S/
- if mbchar =~ /\w/
- started_by = :word
- else
- started_by = :non_word_printable
- end
- break
- end
- width += get_mbchar_width(mbchar)
- byte_size += size
- end
- while 0 < (byte_pointer - byte_size)
- size = get_prev_mbchar_size(line, byte_pointer - byte_size)
- mbchar = line.byteslice(byte_pointer - byte_size - size, size)
- case started_by
- when :word
- break if mbchar =~ /\W/
- when :non_word_printable
- break if mbchar =~ /[\w\s]/
- end
- width += get_mbchar_width(mbchar)
- byte_size += size
- end
- [byte_size, width]
- end
-
- def self.vi_first_print(line)
- width = 0
- byte_size = 0
- while (line.bytesize - 1) > byte_size
- size = get_next_mbchar_size(line, byte_size)
- mbchar = line.byteslice(byte_size, size)
- if mbchar =~ /\S/
- break
- end
- width += get_mbchar_width(mbchar)
- byte_size += size
- end
- [byte_size, width]
- end
-end
diff --git a/lib/reline/unicode/east_asian_width.rb b/lib/reline/unicode/east_asian_width.rb
deleted file mode 100644
index fa16a1bb56..0000000000
--- a/lib/reline/unicode/east_asian_width.rb
+++ /dev/null
@@ -1,1196 +0,0 @@
-class Reline::Unicode::EastAsianWidth
- # This is based on EastAsianWidth.txt
- # UNICODE_VERSION = '15.1.0'
-
- # Fullwidth
- TYPE_F = /^[#{ %W(
- \u{3000}
- \u{FF01}-\u{FF60}
- \u{FFE0}-\u{FFE6}
- ).join }]/
-
- # Halfwidth
- 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 = /^[#{ %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{2FFF}
- \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{31EF}-\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{1AFF0}-\u{1AFF3}
- \u{1AFF5}-\u{1AFFB}
- \u{1AFFD}-\u{1AFFE}
- \u{1B000}-\u{1B122}
- \u{1B132}
- \u{1B150}-\u{1B152}
- \u{1B155}
- \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{1F6DC}-\u{1F6DF}
- \u{1F6EB}-\u{1F6EC}
- \u{1F6F4}-\u{1F6FC}
- \u{1F7E0}-\u{1F7EB}
- \u{1F7F0}
- \u{1F90C}-\u{1F93A}
- \u{1F93C}-\u{1F945}
- \u{1F947}-\u{1F9FF}
- \u{1FA70}-\u{1FA7C}
- \u{1FA80}-\u{1FA88}
- \u{1FA90}-\u{1FABD}
- \u{1FABF}-\u{1FAC5}
- \u{1FACE}-\u{1FADB}
- \u{1FAE0}-\u{1FAE8}
- \u{1FAF0}-\u{1FAF8}
- \u{20000}-\u{2FFFD}
- \u{30000}-\u{3FFFD}
- ).join }]/
-
- # Narrow
- 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 = /^[#{ %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 = /^[#{ %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{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{0870}-\u{088E}
- \u{0890}-\u{0891}
- \u{0898}-\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{0C3C}-\u{0C44}
- \u{0C46}-\u{0C48}
- \u{0C4A}-\u{0C4D}
- \u{0C55}-\u{0C56}
- \u{0C58}-\u{0C5A}
- \u{0C5D}
- \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{0CDD}-\u{0CDE}
- \u{0CE0}-\u{0CE3}
- \u{0CE6}-\u{0CEF}
- \u{0CF1}-\u{0CF3}
- \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{0ECE}
- \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{1715}
- \u{171F}-\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{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{1ACE}
- \u{1B00}-\u{1B4C}
- \u{1B50}-\u{1B7E}
- \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{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{20C0}
- \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{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{2E5D}
- \u{303F}
- \u{4DC0}-\u{4DFF}
- \u{A4D0}-\u{A62B}
- \u{A640}-\u{A6F7}
- \u{A700}-\u{A7CA}
- \u{A7D0}-\u{A7D1}
- \u{A7D3}
- \u{A7D5}-\u{A7D9}
- \u{A7F2}-\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{FBC2}
- \u{FBD3}-\u{FD8F}
- \u{FD92}-\u{FDC7}
- \u{FDCF}
- \u{FDF0}-\u{FDFF}
- \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{1057A}
- \u{1057C}-\u{1058A}
- \u{1058C}-\u{10592}
- \u{10594}-\u{10595}
- \u{10597}-\u{105A1}
- \u{105A3}-\u{105B1}
- \u{105B3}-\u{105B9}
- \u{105BB}-\u{105BC}
- \u{10600}-\u{10736}
- \u{10740}-\u{10755}
- \u{10760}-\u{10767}
- \u{10780}-\u{10785}
- \u{10787}-\u{107B0}
- \u{107B2}-\u{107BA}
- \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{10EFD}-\u{10F27}
- \u{10F30}-\u{10F59}
- \u{10F70}-\u{10F89}
- \u{10FB0}-\u{10FCB}
- \u{10FE0}-\u{10FF6}
- \u{11000}-\u{1104D}
- \u{11052}-\u{11075}
- \u{1107F}-\u{110C2}
- \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{11241}
- \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{116B9}
- \u{116C0}-\u{116C9}
- \u{11700}-\u{1171A}
- \u{1171D}-\u{1172B}
- \u{11730}-\u{11746}
- \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{11AB0}-\u{11AF8}
- \u{11B00}-\u{11B09}
- \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{11F00}-\u{11F10}
- \u{11F12}-\u{11F3A}
- \u{11F3E}-\u{11F59}
- \u{11FB0}
- \u{11FC0}-\u{11FF1}
- \u{11FFF}-\u{12399}
- \u{12400}-\u{1246E}
- \u{12470}-\u{12474}
- \u{12480}-\u{12543}
- \u{12F90}-\u{12FF2}
- \u{13000}-\u{13455}
- \u{14400}-\u{14646}
- \u{16800}-\u{16A38}
- \u{16A40}-\u{16A5E}
- \u{16A60}-\u{16A69}
- \u{16A6E}-\u{16ABE}
- \u{16AC0}-\u{16AC9}
- \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{1CF00}-\u{1CF2D}
- \u{1CF30}-\u{1CF46}
- \u{1CF50}-\u{1CFC3}
- \u{1D000}-\u{1D0F5}
- \u{1D100}-\u{1D126}
- \u{1D129}-\u{1D1EA}
- \u{1D200}-\u{1D245}
- \u{1D2C0}-\u{1D2D3}
- \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{1DF00}-\u{1DF1E}
- \u{1DF25}-\u{1DF2A}
- \u{1E000}-\u{1E006}
- \u{1E008}-\u{1E018}
- \u{1E01B}-\u{1E021}
- \u{1E023}-\u{1E024}
- \u{1E026}-\u{1E02A}
- \u{1E030}-\u{1E06D}
- \u{1E08F}
- \u{1E100}-\u{1E12C}
- \u{1E130}-\u{1E13D}
- \u{1E140}-\u{1E149}
- \u{1E14E}-\u{1E14F}
- \u{1E290}-\u{1E2AE}
- \u{1E2C0}-\u{1E2F9}
- \u{1E2FF}
- \u{1E4D0}-\u{1E4F9}
- \u{1E7E0}-\u{1E7E6}
- \u{1E7E8}-\u{1E7EB}
- \u{1E7ED}-\u{1E7EE}
- \u{1E7F0}-\u{1E7FE}
- \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{1F776}
- \u{1F77B}-\u{1F7D9}
- \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/lib/reline/version.rb b/lib/reline/version.rb
deleted file mode 100644
index 680e5a9cca..0000000000
--- a/lib/reline/version.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-module Reline
- VERSION = '0.5.8'
-end
diff --git a/lib/resolv.gemspec b/lib/resolv.gemspec
index 6b83e303d7..66aed34e01 100644
--- a/lib/resolv.gemspec
+++ b/lib/resolv.gemspec
@@ -16,13 +16,13 @@ Gem::Specification.new do |spec|
spec.homepage = "https://github.com/ruby/resolv"
spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
spec.licenses = ["Ruby", "BSD-2-Clause"]
+ spec.extensions << "ext/win32/resolv/extconf.rb"
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
+ excludes = %W[/.git* /bin /test /*file /#{File.basename(__FILE__)}]
+ spec.files = IO.popen(%W[git -C #{__dir__} ls-files -z --] + excludes.map {|e| ":^#{e}"}, &:read).split("\x0")
spec.bindir = "exe"
spec.executables = []
spec.require_paths = ["lib"]
diff --git a/lib/resolv.rb b/lib/resolv.rb
index e36dbce259..fa7d4e2e47 100644
--- a/lib/resolv.rb
+++ b/lib/resolv.rb
@@ -3,11 +3,8 @@
require 'socket'
require 'timeout'
require 'io/wait'
-
-begin
- require 'securerandom'
-rescue LoadError
-end
+require 'securerandom'
+require 'rbconfig'
# Resolv is a thread-aware DNS resolver library written in Ruby. Resolv can
# handle multiple DNS requests concurrently without blocking the entire Ruby
@@ -37,7 +34,8 @@ end
class Resolv
- VERSION = "0.4.0"
+ # The version string
+ VERSION = "0.7.0"
##
# Looks up the first IP address for +name+.
@@ -83,9 +81,22 @@ class Resolv
##
# Creates a new Resolv using +resolvers+.
+ #
+ # If +resolvers+ is not given, a hash, or +nil+, uses a Hosts resolver and
+ # and a DNS resolver. If +resolvers+ is a hash, uses the hash as
+ # configuration for the DNS resolver.
- def initialize(resolvers=nil, use_ipv6: nil)
- @resolvers = resolvers || [Hosts.new, DNS.new(DNS::Config.default_config_hash.merge(use_ipv6: use_ipv6))]
+ def initialize(resolvers=(arg_not_set = true; nil), use_ipv6: (keyword_not_set = true; nil))
+ if !keyword_not_set && !arg_not_set
+ warn "Support for separate use_ipv6 keyword is deprecated, as it is ignored if an argument is provided. Do not provide a positional argument if using the use_ipv6 keyword argument.", uplevel: 1
+ end
+
+ @resolvers = case resolvers
+ when Hash, nil
+ [Hosts.new, DNS.new(DNS::Config.default_config_hash.merge(resolvers || {}))]
+ else
+ resolvers
+ end
end
##
@@ -168,14 +179,15 @@ class Resolv
# Resolv::Hosts is a hostname resolver that uses the system hosts file.
class Hosts
- if /mswin|mingw|cygwin/ =~ RUBY_PLATFORM and
+ if /mswin|cygwin|mingw|bccwin/ =~ RUBY_PLATFORM || ::RbConfig::CONFIG['host_os'] =~ /mswin/
begin
- require 'win32/resolv'
- DefaultFileName = Win32::Resolv.get_hosts_path || IO::NULL
+ require 'win32/resolv' unless defined?(Win32::Resolv)
+ hosts = Win32::Resolv.get_hosts_path || IO::NULL
rescue LoadError
end
end
- DefaultFileName ||= '/etc/hosts'
+ # The default file name for host names
+ DefaultFileName = hosts || '/etc/hosts'
##
# Creates a new Resolv::Hosts, using +filename+ for its data source.
@@ -396,13 +408,15 @@ class Resolv
# be a Resolv::IPv4 or Resolv::IPv6
def each_address(name)
- each_resource(name, Resource::IN::A) {|resource| yield resource.address}
if use_ipv6?
each_resource(name, Resource::IN::AAAA) {|resource| yield resource.address}
end
+ each_resource(name, Resource::IN::A) {|resource| yield resource.address}
end
def use_ipv6? # :nodoc:
+ @config.lazy_initialize unless @config.instance_variable_get(:@initialized)
+
use_ipv6 = @config.use_ipv6?
unless use_ipv6.nil?
return use_ipv6
@@ -511,37 +525,44 @@ class Resolv
}
end
+ # :stopdoc:
+
def fetch_resource(name, typeclass)
lazy_initialize
- begin
- requester = make_udp_requester
+ truncated = {}
+ requesters = {}
+ udp_requester = begin
+ make_udp_requester
rescue Errno::EACCES
# fall back to TCP
end
senders = {}
+
begin
- @config.resolv(name) {|candidate, tout, nameserver, port|
- requester ||= make_tcp_requester(nameserver, port)
+ @config.resolv(name) do |candidate, tout, nameserver, port|
msg = Message.new
msg.rd = 1
msg.add_question(candidate, typeclass)
- unless sender = senders[[candidate, nameserver, port]]
+
+ requester = requesters.fetch([nameserver, port]) do
+ if !truncated[candidate] && udp_requester
+ udp_requester
+ else
+ requesters[[nameserver, port]] = make_tcp_requester(nameserver, port)
+ end
+ end
+
+ unless sender = senders[[candidate, requester, nameserver, port]]
sender = requester.sender(msg, candidate, nameserver, port)
next if !sender
- senders[[candidate, nameserver, port]] = sender
+ senders[[candidate, requester, nameserver, port]] = sender
end
reply, reply_name = requester.request(sender, tout)
case reply.rcode
when RCode::NoError
if reply.tc == 1 and not Requester::TCP === requester
- requester.close
# Retry via TCP:
- requester = make_tcp_requester(nameserver, port)
- senders = {}
- # This will use TCP for all remaining candidates (assuming the
- # current candidate does not already respond successfully via
- # TCP). This makes sense because we already know the full
- # response will not fit in an untruncated UDP packet.
+ truncated[candidate] = true
redo
else
yield(reply, reply_name)
@@ -552,9 +573,10 @@ class Resolv
else
raise Config::OtherResolvError.new(reply_name.to_s)
end
- }
+ end
ensure
- requester&.close
+ udp_requester&.close
+ requesters.each_value { |requester| requester&.close }
end
end
@@ -569,6 +591,11 @@ class Resolv
def make_tcp_requester(host, port) # :nodoc:
return Requester::TCP.new(host, port)
+ rescue Errno::ECONNREFUSED
+ # Treat a refused TCP connection attempt to a nameserver like a timeout,
+ # as Resolv::DNS::Config#resolv considers ResolvTimeout exceptions as a
+ # hint to try the next nameserver:
+ raise ResolvTimeout
end
def extract_resources(msg, name, typeclass) # :nodoc:
@@ -602,16 +629,10 @@ class Resolv
}
end
- if defined? SecureRandom
- def self.random(arg) # :nodoc:
- begin
- SecureRandom.random_number(arg)
- rescue NotImplementedError
- rand(arg)
- end
- end
- else
- def self.random(arg) # :nodoc:
+ def self.random(arg) # :nodoc:
+ begin
+ SecureRandom.random_number(arg)
+ rescue NotImplementedError
rand(arg)
end
end
@@ -643,8 +664,20 @@ class Resolv
}
end
- def self.bind_random_port(udpsock, bind_host="0.0.0.0") # :nodoc:
- begin
+ case RUBY_PLATFORM
+ when *[
+ # https://www.rfc-editor.org/rfc/rfc6056.txt
+ # Appendix A. Survey of the Algorithms in Use by Some Popular Implementations
+ /freebsd/, /linux/, /netbsd/, /openbsd/, /solaris/,
+ /darwin/, # the same as FreeBSD
+ ] then
+ def self.bind_random_port(udpsock, bind_host="0.0.0.0") # :nodoc:
+ udpsock.bind(bind_host, 0)
+ end
+ else
+ # Sequential port assignment
+ def self.bind_random_port(udpsock, bind_host="0.0.0.0") # :nodoc:
+ # Ephemeral port number range recommended by RFC 6056
port = random(1024..65535)
udpsock.bind(bind_host, port)
rescue Errno::EADDRINUSE, # POSIX
@@ -688,7 +721,8 @@ class Resolv
begin
reply, from = recv_reply(select_result[0])
rescue Errno::ECONNREFUSED, # GNU/Linux, FreeBSD
- Errno::ECONNRESET # Windows
+ Errno::ECONNRESET, # Windows
+ EOFError
# No name server running on the server?
# Don't wait anymore.
raise ResolvTimeout
@@ -897,8 +931,11 @@ class Resolv
end
def recv_reply(readable_socks)
- len = readable_socks[0].read(2).unpack('n')[0]
+ len_data = readable_socks[0].read(2)
+ raise EOFError if len_data.nil? || len_data.bytesize != 2
+ len = len_data.unpack('n')[0]
reply = @socks[0].read(len)
+ raise EOFError if reply.nil? || reply.bytesize != len
return reply, nil
end
@@ -967,13 +1004,13 @@ class Resolv
next unless keyword
case keyword
when 'nameserver'
- nameserver.concat(args)
+ nameserver.concat(args.each(&:freeze))
when 'domain'
next if args.empty?
- search = [args[0]]
+ search = [args[0].freeze]
when 'search'
next if args.empty?
- search = args
+ search = args.each(&:freeze)
when 'options'
args.each {|arg|
case arg
@@ -984,22 +1021,21 @@ class Resolv
end
}
}
- return { :nameserver => nameserver, :search => search, :ndots => ndots }
+ return { :nameserver => nameserver.freeze, :search => search.freeze, :ndots => ndots.freeze }.freeze
end
def Config.default_config_hash(filename="/etc/resolv.conf")
if File.exist? filename
- config_hash = Config.parse_resolv_conf(filename)
+ Config.parse_resolv_conf(filename)
+ elsif defined?(Win32::Resolv)
+ search, nameserver = Win32::Resolv.get_resolv_info
+ config_hash = {}
+ config_hash[:nameserver] = nameserver if nameserver
+ config_hash[:search] = [search].flatten if search
+ config_hash
else
- if /mswin|cygwin|mingw|bccwin/ =~ RUBY_PLATFORM
- require 'win32/resolv'
- search, nameserver = Win32::Resolv.get_resolv_info
- config_hash = {}
- config_hash[:nameserver] = nameserver if nameserver
- config_hash[:search] = [search].flatten if search
- end
+ {}
end
- config_hash || {}
end
def lazy_initialize
@@ -1648,6 +1684,7 @@ class Resolv
prev_index = @index
save_index = nil
d = []
+ size = -1
while true
raise DecodeError.new("limit exceeded") if @limit <= @index
case @data.getbyte(@index)
@@ -1668,7 +1705,10 @@ class Resolv
end
@index = idx
else
- d << self.get_label
+ l = self.get_label
+ d << l
+ size += 1 + l.string.bytesize
+ raise DecodeError.new("name label data exceed 255 octets") if size > 255
end
end
end
@@ -1800,7 +1840,6 @@ class Resolv
end
end
-
##
# Base class for SvcParam. [RFC9460]
@@ -2095,7 +2134,14 @@ class Resolv
attr_reader :ttl
- ClassHash = {} # :nodoc:
+ ClassHash = Module.new do
+ module_function
+
+ def []=(type_class_value, klass)
+ type_value, class_value = type_class_value
+ Resource.const_set(:"Type#{type_value}_Class#{class_value}", klass)
+ end
+ end
def encode_rdata(msg) # :nodoc:
raise NotImplementedError.new
@@ -2133,7 +2179,9 @@ class Resolv
end
def self.get_class(type_value, class_value) # :nodoc:
- return ClassHash[[type_value, class_value]] ||
+ cache = :"Type#{type_value}_Class#{class_value}"
+
+ return (const_defined?(cache) && const_get(cache)) ||
Generic.create(type_value, class_value)
end
@@ -2499,7 +2547,6 @@ class Resolv
attr_reader :altitude
-
def encode_rdata(msg) # :nodoc:
msg.put_bytes(@version)
msg.put_bytes(@ssize.scalar)
@@ -2563,7 +2610,7 @@ class Resolv
end
##
- # Flags for this proprty:
+ # Flags for this property:
# - Bit 0 : 0 = not critical, 1 = critical
attr_reader :flags
@@ -2884,15 +2931,21 @@ class Resolv
class IPv4
- ##
- # Regular expression IPv4 addresses must match.
-
Regex256 = /0
|1(?:[0-9][0-9]?)?
|2(?:[0-4][0-9]?|5[0-5]?|[6-9])?
- |[3-9][0-9]?/x
+ |[3-9][0-9]?/x # :nodoc:
+
+ ##
+ # Regular expression IPv4 addresses must match.
Regex = /\A(#{Regex256})\.(#{Regex256})\.(#{Regex256})\.(#{Regex256})\z/
+ ##
+ # Creates a new IPv4 address from +arg+ which may be:
+ #
+ # IPv4:: returns +arg+.
+ # String:: +arg+ must match the IPv4::Regex constant
+
def self.create(arg)
case arg
when IPv4
@@ -3201,13 +3254,15 @@ class Resolv
end
- module LOC
+ module LOC # :nodoc:
##
# A Resolv::LOC::Size
class Size
+ # Regular expression LOC size must match.
+
Regex = /^(\d+\.*\d*)[m]$/
##
@@ -3233,6 +3288,7 @@ class Resolv
end
end
+ # Internal use; use self.create.
def initialize(scalar)
@scalar = scalar
end
@@ -3270,6 +3326,8 @@ class Resolv
class Coord
+ # Regular expression LOC Coord must match.
+
Regex = /^(\d+)\s(\d+)\s(\d+\.\d+)\s([NESW])$/
##
@@ -3299,6 +3357,7 @@ class Resolv
end
end
+ # Internal use; use self.create.
def initialize(coordinates,orientation)
unless coordinates.kind_of?(String)
raise ArgumentError.new("Coord must be a 32bit unsigned integer in hex format: #{coordinates.inspect}")
@@ -3361,6 +3420,8 @@ class Resolv
class Alt
+ # Regular expression LOC Alt must match.
+
Regex = /^([+-]*\d+\.*\d*)[m]$/
##
@@ -3386,6 +3447,7 @@ class Resolv
end
end
+ # Internal use; use self.create.
def initialize(altitude)
@altitude = altitude
end
@@ -3439,4 +3501,3 @@ class Resolv
AddressRegex = /(?:#{IPv4::Regex})|(?:#{IPv6::Regex})/
end
-
diff --git a/lib/ruby_vm/rjit/.document b/lib/ruby_vm/rjit/.document
deleted file mode 100644
index 0a603afe3d..0000000000
--- a/lib/ruby_vm/rjit/.document
+++ /dev/null
@@ -1 +0,0 @@
-stats.rb
diff --git a/lib/ruby_vm/rjit/assembler.rb b/lib/ruby_vm/rjit/assembler.rb
deleted file mode 100644
index 645072d11b..0000000000
--- a/lib/ruby_vm/rjit/assembler.rb
+++ /dev/null
@@ -1,1140 +0,0 @@
-# frozen_string_literal: true
-module RubyVM::RJIT
- # 8-bit memory access
- class BytePtr < Data.define(:reg, :disp); end
-
- # 32-bit memory access
- class DwordPtr < Data.define(:reg, :disp); end
-
- # 64-bit memory access
- QwordPtr = Array
-
- # SystemV x64 calling convention
- C_ARGS = [:rdi, :rsi, :rdx, :rcx, :r8, :r9]
- C_RET = :rax
-
- # https://cdrdv2.intel.com/v1/dl/getContent/671110
- # Mostly an x86_64 assembler, but this also has some stuff that is useful for any architecture.
- class Assembler
- # rel8 jumps are made with labels
- class Label < Data.define(:id, :name); end
-
- # rel32 is inserted as [Rel32, Rel32Pad..] and converted on #resolve_rel32
- class Rel32 < Data.define(:addr); end
- Rel32Pad = Object.new
-
- # A set of ModR/M values encoded on #insn
- class ModRM < Data.define(:mod, :reg, :rm); end
- Mod00 = 0b00 # Mod 00: [reg]
- Mod01 = 0b01 # Mod 01: [reg]+disp8
- Mod10 = 0b10 # Mod 10: [reg]+disp32
- Mod11 = 0b11 # Mod 11: reg
-
- # REX = 0100WR0B
- REX_B = 0b01000001
- REX_R = 0b01000100
- REX_W = 0b01001000
-
- # Operand matchers
- R32 = -> (op) { op.is_a?(Symbol) && r32?(op) }
- R64 = -> (op) { op.is_a?(Symbol) && r64?(op) }
- IMM8 = -> (op) { op.is_a?(Integer) && imm8?(op) }
- IMM32 = -> (op) { op.is_a?(Integer) && imm32?(op) }
- IMM64 = -> (op) { op.is_a?(Integer) && imm64?(op) }
-
- def initialize
- @bytes = []
- @labels = {}
- @label_id = 0
- @comments = Hash.new { |h, k| h[k] = [] }
- @blocks = Hash.new { |h, k| h[k] = [] }
- @stub_starts = Hash.new { |h, k| h[k] = [] }
- @stub_ends = Hash.new { |h, k| h[k] = [] }
- @pos_markers = Hash.new { |h, k| h[k] = [] }
- end
-
- def assemble(addr)
- set_code_addrs(addr)
- resolve_rel32(addr)
- resolve_labels
-
- write_bytes(addr)
-
- @pos_markers.each do |write_pos, markers|
- markers.each { |marker| marker.call(addr + write_pos) }
- end
- @bytes.size
- ensure
- @bytes.clear
- end
-
- def size
- @bytes.size
- end
-
- #
- # Instructions
- #
-
- def add(dst, src)
- case [dst, src]
- # ADD r/m64, imm8 (Mod 00: [reg])
- in [QwordPtr[R64 => dst_reg], IMM8 => src_imm]
- # REX.W + 83 /0 ib
- # MI: Operand 1: ModRM:r/m (r, w), Operand 2: imm8/16/32
- insn(
- prefix: REX_W,
- opcode: 0x83,
- mod_rm: ModRM[mod: Mod00, reg: 0, rm: dst_reg],
- imm: imm8(src_imm),
- )
- # ADD r/m64, imm8 (Mod 11: reg)
- in [R64 => dst_reg, IMM8 => src_imm]
- # REX.W + 83 /0 ib
- # MI: Operand 1: ModRM:r/m (r, w), Operand 2: imm8/16/32
- insn(
- prefix: REX_W,
- opcode: 0x83,
- mod_rm: ModRM[mod: Mod11, reg: 0, rm: dst_reg],
- imm: imm8(src_imm),
- )
- # ADD r/m64 imm32 (Mod 11: reg)
- in [R64 => dst_reg, IMM32 => src_imm]
- # REX.W + 81 /0 id
- # MI: Operand 1: ModRM:r/m (r, w), Operand 2: imm8/16/32
- insn(
- prefix: REX_W,
- opcode: 0x81,
- mod_rm: ModRM[mod: Mod11, reg: 0, rm: dst_reg],
- imm: imm32(src_imm),
- )
- # ADD r/m64, r64 (Mod 11: reg)
- in [R64 => dst_reg, R64 => src_reg]
- # REX.W + 01 /r
- # MR: Operand 1: ModRM:r/m (r, w), Operand 2: ModRM:reg (r)
- insn(
- prefix: REX_W,
- opcode: 0x01,
- mod_rm: ModRM[mod: Mod11, reg: src_reg, rm: dst_reg],
- )
- end
- end
-
- def and(dst, src)
- case [dst, src]
- # AND r/m64, imm8 (Mod 11: reg)
- in [R64 => dst_reg, IMM8 => src_imm]
- # REX.W + 83 /4 ib
- # MI: Operand 1: ModRM:r/m (r, w), Operand 2: imm8/16/32
- insn(
- prefix: REX_W,
- opcode: 0x83,
- mod_rm: ModRM[mod: Mod11, reg: 4, rm: dst_reg],
- imm: imm8(src_imm),
- )
- # AND r/m64, imm32 (Mod 11: reg)
- in [R64 => dst_reg, IMM32 => src_imm]
- # REX.W + 81 /4 id
- # MI: Operand 1: ModRM:r/m (r, w), Operand 2: imm8/16/32
- insn(
- prefix: REX_W,
- opcode: 0x81,
- mod_rm: ModRM[mod: Mod11, reg: 4, rm: dst_reg],
- imm: imm32(src_imm),
- )
- # AND r64, r/m64 (Mod 01: [reg]+disp8)
- in [R64 => dst_reg, QwordPtr[R64 => src_reg, IMM8 => src_disp]]
- # REX.W + 23 /r
- # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r)
- insn(
- prefix: REX_W,
- opcode: 0x23,
- mod_rm: ModRM[mod: Mod01, reg: dst_reg, rm: src_reg],
- disp: imm8(src_disp),
- )
- end
- end
-
- def call(dst)
- case dst
- # CALL rel32
- in Integer => dst_addr
- # E8 cd
- # D: Operand 1: Offset
- insn(opcode: 0xe8, imm: rel32(dst_addr))
- # CALL r/m64 (Mod 11: reg)
- in R64 => dst_reg
- # FF /2
- # M: Operand 1: ModRM:r/m (r)
- insn(
- opcode: 0xff,
- mod_rm: ModRM[mod: Mod11, reg: 2, rm: dst_reg],
- )
- end
- end
-
- def cmove(dst, src)
- case [dst, src]
- # CMOVE r64, r/m64 (Mod 11: reg)
- in [R64 => dst_reg, R64 => src_reg]
- # REX.W + 0F 44 /r
- # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r)
- insn(
- prefix: REX_W,
- opcode: [0x0f, 0x44],
- mod_rm: ModRM[mod: Mod11, reg: dst_reg, rm: src_reg],
- )
- end
- end
-
- def cmovg(dst, src)
- case [dst, src]
- # CMOVG r64, r/m64 (Mod 11: reg)
- in [R64 => dst_reg, R64 => src_reg]
- # REX.W + 0F 4F /r
- # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r)
- insn(
- prefix: REX_W,
- opcode: [0x0f, 0x4f],
- mod_rm: ModRM[mod: Mod11, reg: dst_reg, rm: src_reg],
- )
- end
- end
-
- def cmovge(dst, src)
- case [dst, src]
- # CMOVGE r64, r/m64 (Mod 11: reg)
- in [R64 => dst_reg, R64 => src_reg]
- # REX.W + 0F 4D /r
- # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r)
- insn(
- prefix: REX_W,
- opcode: [0x0f, 0x4d],
- mod_rm: ModRM[mod: Mod11, reg: dst_reg, rm: src_reg],
- )
- end
- end
-
- def cmovl(dst, src)
- case [dst, src]
- # CMOVL r64, r/m64 (Mod 11: reg)
- in [R64 => dst_reg, R64 => src_reg]
- # REX.W + 0F 4C /r
- # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r)
- insn(
- prefix: REX_W,
- opcode: [0x0f, 0x4c],
- mod_rm: ModRM[mod: Mod11, reg: dst_reg, rm: src_reg],
- )
- end
- end
-
- def cmovle(dst, src)
- case [dst, src]
- # CMOVLE r64, r/m64 (Mod 11: reg)
- in [R64 => dst_reg, R64 => src_reg]
- # REX.W + 0F 4E /r
- # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r)
- insn(
- prefix: REX_W,
- opcode: [0x0f, 0x4e],
- mod_rm: ModRM[mod: Mod11, reg: dst_reg, rm: src_reg],
- )
- end
- end
-
- def cmovne(dst, src)
- case [dst, src]
- # CMOVNE r64, r/m64 (Mod 11: reg)
- in [R64 => dst_reg, R64 => src_reg]
- # REX.W + 0F 45 /r
- # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r)
- insn(
- prefix: REX_W,
- opcode: [0x0f, 0x45],
- mod_rm: ModRM[mod: Mod11, reg: dst_reg, rm: src_reg],
- )
- end
- end
-
- def cmovnz(dst, src)
- case [dst, src]
- # CMOVNZ r64, r/m64 (Mod 11: reg)
- in [R64 => dst_reg, R64 => src_reg]
- # REX.W + 0F 45 /r
- # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r)
- insn(
- prefix: REX_W,
- opcode: [0x0f, 0x45],
- mod_rm: ModRM[mod: Mod11, reg: dst_reg, rm: src_reg],
- )
- end
- end
-
- def cmovz(dst, src)
- case [dst, src]
- # CMOVZ r64, r/m64 (Mod 11: reg)
- in [R64 => dst_reg, R64 => src_reg]
- # REX.W + 0F 44 /r
- # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r)
- insn(
- prefix: REX_W,
- opcode: [0x0f, 0x44],
- mod_rm: ModRM[mod: Mod11, reg: dst_reg, rm: src_reg],
- )
- # CMOVZ r64, r/m64 (Mod 01: [reg]+disp8)
- in [R64 => dst_reg, QwordPtr[R64 => src_reg, IMM8 => src_disp]]
- # REX.W + 0F 44 /r
- # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r)
- insn(
- prefix: REX_W,
- opcode: [0x0f, 0x44],
- mod_rm: ModRM[mod: Mod01, reg: dst_reg, rm: src_reg],
- disp: imm8(src_disp),
- )
- end
- end
-
- def cmp(left, right)
- case [left, right]
- # CMP r/m8, imm8 (Mod 01: [reg]+disp8)
- in [BytePtr[R64 => left_reg, IMM8 => left_disp], IMM8 => right_imm]
- # 80 /7 ib
- # MI: Operand 1: ModRM:r/m (r), Operand 2: imm8/16/32
- insn(
- opcode: 0x80,
- mod_rm: ModRM[mod: Mod01, reg: 7, rm: left_reg],
- disp: left_disp,
- imm: imm8(right_imm),
- )
- # CMP r/m32, imm32 (Mod 01: [reg]+disp8)
- in [DwordPtr[R64 => left_reg, IMM8 => left_disp], IMM32 => right_imm]
- # 81 /7 id
- # MI: Operand 1: ModRM:r/m (r), Operand 2: imm8/16/32
- insn(
- opcode: 0x81,
- mod_rm: ModRM[mod: Mod01, reg: 7, rm: left_reg],
- disp: left_disp,
- imm: imm32(right_imm),
- )
- # CMP r/m64, imm8 (Mod 01: [reg]+disp8)
- in [QwordPtr[R64 => left_reg, IMM8 => left_disp], IMM8 => right_imm]
- # REX.W + 83 /7 ib
- # MI: Operand 1: ModRM:r/m (r), Operand 2: imm8/16/32
- insn(
- prefix: REX_W,
- opcode: 0x83,
- mod_rm: ModRM[mod: Mod01, reg: 7, rm: left_reg],
- disp: left_disp,
- imm: imm8(right_imm),
- )
- # CMP r/m64, imm32 (Mod 01: [reg]+disp8)
- in [QwordPtr[R64 => left_reg, IMM8 => left_disp], IMM32 => right_imm]
- # REX.W + 81 /7 id
- # MI: Operand 1: ModRM:r/m (r), Operand 2: imm8/16/32
- insn(
- prefix: REX_W,
- opcode: 0x81,
- mod_rm: ModRM[mod: Mod01, reg: 7, rm: left_reg],
- disp: left_disp,
- imm: imm32(right_imm),
- )
- # CMP r/m64, imm8 (Mod 10: [reg]+disp32)
- in [QwordPtr[R64 => left_reg, IMM32 => left_disp], IMM8 => right_imm]
- # REX.W + 83 /7 ib
- # MI: Operand 1: ModRM:r/m (r), Operand 2: imm8/16/32
- insn(
- prefix: REX_W,
- opcode: 0x83,
- mod_rm: ModRM[mod: Mod10, reg: 7, rm: left_reg],
- disp: imm32(left_disp),
- imm: imm8(right_imm),
- )
- # CMP r/m64, imm8 (Mod 11: reg)
- in [R64 => left_reg, IMM8 => right_imm]
- # REX.W + 83 /7 ib
- # MI: Operand 1: ModRM:r/m (r), Operand 2: imm8/16/32
- insn(
- prefix: REX_W,
- opcode: 0x83,
- mod_rm: ModRM[mod: Mod11, reg: 7, rm: left_reg],
- imm: imm8(right_imm),
- )
- # CMP r/m64, imm32 (Mod 11: reg)
- in [R64 => left_reg, IMM32 => right_imm]
- # REX.W + 81 /7 id
- # MI: Operand 1: ModRM:r/m (r), Operand 2: imm8/16/32
- insn(
- prefix: REX_W,
- opcode: 0x81,
- mod_rm: ModRM[mod: Mod11, reg: 7, rm: left_reg],
- imm: imm32(right_imm),
- )
- # CMP r/m64, r64 (Mod 01: [reg]+disp8)
- in [QwordPtr[R64 => left_reg, IMM8 => left_disp], R64 => right_reg]
- # REX.W + 39 /r
- # MR: Operand 1: ModRM:r/m (r), Operand 2: ModRM:reg (r)
- insn(
- prefix: REX_W,
- opcode: 0x39,
- mod_rm: ModRM[mod: Mod01, reg: right_reg, rm: left_reg],
- disp: left_disp,
- )
- # CMP r/m64, r64 (Mod 10: [reg]+disp32)
- in [QwordPtr[R64 => left_reg, IMM32 => left_disp], R64 => right_reg]
- # REX.W + 39 /r
- # MR: Operand 1: ModRM:r/m (r), Operand 2: ModRM:reg (r)
- insn(
- prefix: REX_W,
- opcode: 0x39,
- mod_rm: ModRM[mod: Mod10, reg: right_reg, rm: left_reg],
- disp: imm32(left_disp),
- )
- # CMP r/m64, r64 (Mod 11: reg)
- in [R64 => left_reg, R64 => right_reg]
- # REX.W + 39 /r
- # MR: Operand 1: ModRM:r/m (r), Operand 2: ModRM:reg (r)
- insn(
- prefix: REX_W,
- opcode: 0x39,
- mod_rm: ModRM[mod: Mod11, reg: right_reg, rm: left_reg],
- )
- end
- end
-
- def jbe(dst)
- case dst
- # JBE rel8
- in Label => dst_label
- # 76 cb
- insn(opcode: 0x76, imm: dst_label)
- # JBE rel32
- in Integer => dst_addr
- # 0F 86 cd
- insn(opcode: [0x0f, 0x86], imm: rel32(dst_addr))
- end
- end
-
- def je(dst)
- case dst
- # JE rel8
- in Label => dst_label
- # 74 cb
- insn(opcode: 0x74, imm: dst_label)
- # JE rel32
- in Integer => dst_addr
- # 0F 84 cd
- insn(opcode: [0x0f, 0x84], imm: rel32(dst_addr))
- end
- end
-
- def jl(dst)
- case dst
- # JL rel32
- in Integer => dst_addr
- # 0F 8C cd
- insn(opcode: [0x0f, 0x8c], imm: rel32(dst_addr))
- end
- end
-
- def jmp(dst)
- case dst
- # JZ rel8
- in Label => dst_label
- # EB cb
- insn(opcode: 0xeb, imm: dst_label)
- # JMP rel32
- in Integer => dst_addr
- # E9 cd
- insn(opcode: 0xe9, imm: rel32(dst_addr))
- # JMP r/m64 (Mod 01: [reg]+disp8)
- in QwordPtr[R64 => dst_reg, IMM8 => dst_disp]
- # FF /4
- insn(opcode: 0xff, mod_rm: ModRM[mod: Mod01, reg: 4, rm: dst_reg], disp: dst_disp)
- # JMP r/m64 (Mod 11: reg)
- in R64 => dst_reg
- # FF /4
- insn(opcode: 0xff, mod_rm: ModRM[mod: Mod11, reg: 4, rm: dst_reg])
- end
- end
-
- def jne(dst)
- case dst
- # JNE rel8
- in Label => dst_label
- # 75 cb
- insn(opcode: 0x75, imm: dst_label)
- # JNE rel32
- in Integer => dst_addr
- # 0F 85 cd
- insn(opcode: [0x0f, 0x85], imm: rel32(dst_addr))
- end
- end
-
- def jnz(dst)
- case dst
- # JE rel8
- in Label => dst_label
- # 75 cb
- insn(opcode: 0x75, imm: dst_label)
- # JNZ rel32
- in Integer => dst_addr
- # 0F 85 cd
- insn(opcode: [0x0f, 0x85], imm: rel32(dst_addr))
- end
- end
-
- def jo(dst)
- case dst
- # JO rel32
- in Integer => dst_addr
- # 0F 80 cd
- insn(opcode: [0x0f, 0x80], imm: rel32(dst_addr))
- end
- end
-
- def jz(dst)
- case dst
- # JZ rel8
- in Label => dst_label
- # 74 cb
- insn(opcode: 0x74, imm: dst_label)
- # JZ rel32
- in Integer => dst_addr
- # 0F 84 cd
- insn(opcode: [0x0f, 0x84], imm: rel32(dst_addr))
- end
- end
-
- def lea(dst, src)
- case [dst, src]
- # LEA r64,m (Mod 01: [reg]+disp8)
- in [R64 => dst_reg, QwordPtr[R64 => src_reg, IMM8 => src_disp]]
- # REX.W + 8D /r
- # RM: Operand 1: ModRM:reg (w), Operand 2: ModRM:r/m (r)
- insn(
- prefix: REX_W,
- opcode: 0x8d,
- mod_rm: ModRM[mod: Mod01, reg: dst_reg, rm: src_reg],
- disp: imm8(src_disp),
- )
- # LEA r64,m (Mod 10: [reg]+disp32)
- in [R64 => dst_reg, QwordPtr[R64 => src_reg, IMM32 => src_disp]]
- # REX.W + 8D /r
- # RM: Operand 1: ModRM:reg (w), Operand 2: ModRM:r/m (r)
- insn(
- prefix: REX_W,
- opcode: 0x8d,
- mod_rm: ModRM[mod: Mod10, reg: dst_reg, rm: src_reg],
- disp: imm32(src_disp),
- )
- end
- end
-
- def mov(dst, src)
- case dst
- in R32 => dst_reg
- case src
- # MOV r32 r/m32 (Mod 01: [reg]+disp8)
- in DwordPtr[R64 => src_reg, IMM8 => src_disp]
- # 8B /r
- # RM: Operand 1: ModRM:reg (w), Operand 2: ModRM:r/m (r)
- insn(
- opcode: 0x8b,
- mod_rm: ModRM[mod: Mod01, reg: dst_reg, rm: src_reg],
- disp: src_disp,
- )
- # MOV r32, imm32 (Mod 11: reg)
- in IMM32 => src_imm
- # B8+ rd id
- # OI: Operand 1: opcode + rd (w), Operand 2: imm8/16/32/64
- insn(
- opcode: 0xb8,
- rd: dst_reg,
- imm: imm32(src_imm),
- )
- end
- in R64 => dst_reg
- case src
- # MOV r64, r/m64 (Mod 00: [reg])
- in QwordPtr[R64 => src_reg]
- # REX.W + 8B /r
- # RM: Operand 1: ModRM:reg (w), Operand 2: ModRM:r/m (r)
- insn(
- prefix: REX_W,
- opcode: 0x8b,
- mod_rm: ModRM[mod: Mod00, reg: dst_reg, rm: src_reg],
- )
- # MOV r64, r/m64 (Mod 01: [reg]+disp8)
- in QwordPtr[R64 => src_reg, IMM8 => src_disp]
- # REX.W + 8B /r
- # RM: Operand 1: ModRM:reg (w), Operand 2: ModRM:r/m (r)
- insn(
- prefix: REX_W,
- opcode: 0x8b,
- mod_rm: ModRM[mod: Mod01, reg: dst_reg, rm: src_reg],
- disp: src_disp,
- )
- # MOV r64, r/m64 (Mod 10: [reg]+disp32)
- in QwordPtr[R64 => src_reg, IMM32 => src_disp]
- # REX.W + 8B /r
- # RM: Operand 1: ModRM:reg (w), Operand 2: ModRM:r/m (r)
- insn(
- prefix: REX_W,
- opcode: 0x8b,
- mod_rm: ModRM[mod: Mod10, reg: dst_reg, rm: src_reg],
- disp: imm32(src_disp),
- )
- # MOV r64, r/m64 (Mod 11: reg)
- in R64 => src_reg
- # REX.W + 8B /r
- # RM: Operand 1: ModRM:reg (w), Operand 2: ModRM:r/m (r)
- insn(
- prefix: REX_W,
- opcode: 0x8b,
- mod_rm: ModRM[mod: Mod11, reg: dst_reg, rm: src_reg],
- )
- # MOV r/m64, imm32 (Mod 11: reg)
- in IMM32 => src_imm
- # REX.W + C7 /0 id
- # MI: Operand 1: ModRM:r/m (w), Operand 2: imm8/16/32/64
- insn(
- prefix: REX_W,
- opcode: 0xc7,
- mod_rm: ModRM[mod: Mod11, reg: 0, rm: dst_reg],
- imm: imm32(src_imm),
- )
- # MOV r64, imm64
- in IMM64 => src_imm
- # REX.W + B8+ rd io
- # OI: Operand 1: opcode + rd (w), Operand 2: imm8/16/32/64
- insn(
- prefix: REX_W,
- opcode: 0xb8,
- rd: dst_reg,
- imm: imm64(src_imm),
- )
- end
- in DwordPtr[R64 => dst_reg, IMM8 => dst_disp]
- case src
- # MOV r/m32, imm32 (Mod 01: [reg]+disp8)
- in IMM32 => src_imm
- # C7 /0 id
- # MI: Operand 1: ModRM:r/m (w), Operand 2: imm8/16/32/64
- insn(
- opcode: 0xc7,
- mod_rm: ModRM[mod: Mod01, reg: 0, rm: dst_reg],
- disp: dst_disp,
- imm: imm32(src_imm),
- )
- end
- in QwordPtr[R64 => dst_reg]
- case src
- # MOV r/m64, imm32 (Mod 00: [reg])
- in IMM32 => src_imm
- # REX.W + C7 /0 id
- # MI: Operand 1: ModRM:r/m (w), Operand 2: imm8/16/32/64
- insn(
- prefix: REX_W,
- opcode: 0xc7,
- mod_rm: ModRM[mod: Mod00, reg: 0, rm: dst_reg],
- imm: imm32(src_imm),
- )
- # MOV r/m64, r64 (Mod 00: [reg])
- in R64 => src_reg
- # REX.W + 89 /r
- # MR: Operand 1: ModRM:r/m (w), Operand 2: ModRM:reg (r)
- insn(
- prefix: REX_W,
- opcode: 0x89,
- mod_rm: ModRM[mod: Mod00, reg: src_reg, rm: dst_reg],
- )
- end
- in QwordPtr[R64 => dst_reg, IMM8 => dst_disp]
- # Optimize encoding when disp is 0
- return mov([dst_reg], src) if dst_disp == 0
-
- case src
- # MOV r/m64, imm32 (Mod 01: [reg]+disp8)
- in IMM32 => src_imm
- # REX.W + C7 /0 id
- # MI: Operand 1: ModRM:r/m (w), Operand 2: imm8/16/32/64
- insn(
- prefix: REX_W,
- opcode: 0xc7,
- mod_rm: ModRM[mod: Mod01, reg: 0, rm: dst_reg],
- disp: dst_disp,
- imm: imm32(src_imm),
- )
- # MOV r/m64, r64 (Mod 01: [reg]+disp8)
- in R64 => src_reg
- # REX.W + 89 /r
- # MR: Operand 1: ModRM:r/m (w), Operand 2: ModRM:reg (r)
- insn(
- prefix: REX_W,
- opcode: 0x89,
- mod_rm: ModRM[mod: Mod01, reg: src_reg, rm: dst_reg],
- disp: dst_disp,
- )
- end
- in QwordPtr[R64 => dst_reg, IMM32 => dst_disp]
- case src
- # MOV r/m64, imm32 (Mod 10: [reg]+disp32)
- in IMM32 => src_imm
- # REX.W + C7 /0 id
- # MI: Operand 1: ModRM:r/m (w), Operand 2: imm8/16/32/64
- insn(
- prefix: REX_W,
- opcode: 0xc7,
- mod_rm: ModRM[mod: Mod10, reg: 0, rm: dst_reg],
- disp: imm32(dst_disp),
- imm: imm32(src_imm),
- )
- # MOV r/m64, r64 (Mod 10: [reg]+disp32)
- in R64 => src_reg
- # REX.W + 89 /r
- # MR: Operand 1: ModRM:r/m (w), Operand 2: ModRM:reg (r)
- insn(
- prefix: REX_W,
- opcode: 0x89,
- mod_rm: ModRM[mod: Mod10, reg: src_reg, rm: dst_reg],
- disp: imm32(dst_disp),
- )
- end
- end
- end
-
- def or(dst, src)
- case [dst, src]
- # OR r/m64, imm8 (Mod 11: reg)
- in [R64 => dst_reg, IMM8 => src_imm]
- # REX.W + 83 /1 ib
- # MI: Operand 1: ModRM:r/m (r, w), Operand 2: imm8/16/32
- insn(
- prefix: REX_W,
- opcode: 0x83,
- mod_rm: ModRM[mod: Mod11, reg: 1, rm: dst_reg],
- imm: imm8(src_imm),
- )
- # OR r/m64, imm32 (Mod 11: reg)
- in [R64 => dst_reg, IMM32 => src_imm]
- # REX.W + 81 /1 id
- # MI: Operand 1: ModRM:r/m (r, w), Operand 2: imm8/16/32
- insn(
- prefix: REX_W,
- opcode: 0x81,
- mod_rm: ModRM[mod: Mod11, reg: 1, rm: dst_reg],
- imm: imm32(src_imm),
- )
- # OR r64, r/m64 (Mod 01: [reg]+disp8)
- in [R64 => dst_reg, QwordPtr[R64 => src_reg, IMM8 => src_disp]]
- # REX.W + 0B /r
- # RM: Operand 1: ModRM:reg (r, w), Operand 2: ModRM:r/m (r)
- insn(
- prefix: REX_W,
- opcode: 0x0b,
- mod_rm: ModRM[mod: Mod01, reg: dst_reg, rm: src_reg],
- disp: imm8(src_disp),
- )
- end
- end
-
- def push(src)
- case src
- # PUSH r64
- in R64 => src_reg
- # 50+rd
- # O: Operand 1: opcode + rd (r)
- insn(opcode: 0x50, rd: src_reg)
- end
- end
-
- def pop(dst)
- case dst
- # POP r64
- in R64 => dst_reg
- # 58+ rd
- # O: Operand 1: opcode + rd (r)
- insn(opcode: 0x58, rd: dst_reg)
- end
- end
-
- def ret
- # RET
- # Near return: A return to a procedure within the current code segment
- insn(opcode: 0xc3)
- end
-
- def sar(dst, src)
- case [dst, src]
- in [R64 => dst_reg, IMM8 => src_imm]
- # REX.W + C1 /7 ib
- # MI: Operand 1: ModRM:r/m (r, w), Operand 2: imm8
- insn(
- prefix: REX_W,
- opcode: 0xc1,
- mod_rm: ModRM[mod: Mod11, reg: 7, rm: dst_reg],
- imm: imm8(src_imm),
- )
- end
- end
-
- def sub(dst, src)
- case [dst, src]
- # SUB r/m64, imm8 (Mod 11: reg)
- in [R64 => dst_reg, IMM8 => src_imm]
- # REX.W + 83 /5 ib
- # MI: Operand 1: ModRM:r/m (r, w), Operand 2: imm8/16/32
- insn(
- prefix: REX_W,
- opcode: 0x83,
- mod_rm: ModRM[mod: Mod11, reg: 5, rm: dst_reg],
- imm: imm8(src_imm),
- )
- # SUB r/m64, r64 (Mod 11: reg)
- in [R64 => dst_reg, R64 => src_reg]
- # REX.W + 29 /r
- # MR: Operand 1: ModRM:r/m (r, w), Operand 2: ModRM:reg (r)
- insn(
- prefix: REX_W,
- opcode: 0x29,
- mod_rm: ModRM[mod: Mod11, reg: src_reg, rm: dst_reg],
- )
- end
- end
-
- def test(left, right)
- case [left, right]
- # TEST r/m8*, imm8 (Mod 01: [reg]+disp8)
- in [BytePtr[R64 => left_reg, IMM8 => left_disp], IMM8 => right_imm]
- # REX + F6 /0 ib
- # MI: Operand 1: ModRM:r/m (r), Operand 2: imm8/16/32
- insn(
- opcode: 0xf6,
- mod_rm: ModRM[mod: Mod01, reg: 0, rm: left_reg],
- disp: left_disp,
- imm: imm8(right_imm),
- )
- # TEST r/m64, imm32 (Mod 01: [reg]+disp8)
- in [QwordPtr[R64 => left_reg, IMM8 => left_disp], IMM32 => right_imm]
- # REX.W + F7 /0 id
- # MI: Operand 1: ModRM:r/m (r), Operand 2: imm8/16/32
- insn(
- prefix: REX_W,
- opcode: 0xf7,
- mod_rm: ModRM[mod: Mod01, reg: 0, rm: left_reg],
- disp: left_disp,
- imm: imm32(right_imm),
- )
- # TEST r/m64, imm32 (Mod 10: [reg]+disp32)
- in [QwordPtr[R64 => left_reg, IMM32 => left_disp], IMM32 => right_imm]
- # REX.W + F7 /0 id
- # MI: Operand 1: ModRM:r/m (r), Operand 2: imm8/16/32
- insn(
- prefix: REX_W,
- opcode: 0xf7,
- mod_rm: ModRM[mod: Mod10, reg: 0, rm: left_reg],
- disp: imm32(left_disp),
- imm: imm32(right_imm),
- )
- # TEST r/m64, imm32 (Mod 11: reg)
- in [R64 => left_reg, IMM32 => right_imm]
- # REX.W + F7 /0 id
- # MI: Operand 1: ModRM:r/m (r), Operand 2: imm8/16/32
- insn(
- prefix: REX_W,
- opcode: 0xf7,
- mod_rm: ModRM[mod: Mod11, reg: 0, rm: left_reg],
- imm: imm32(right_imm),
- )
- # TEST r/m32, r32 (Mod 11: reg)
- in [R32 => left_reg, R32 => right_reg]
- # 85 /r
- # MR: Operand 1: ModRM:r/m (r), Operand 2: ModRM:reg (r)
- insn(
- opcode: 0x85,
- mod_rm: ModRM[mod: Mod11, reg: right_reg, rm: left_reg],
- )
- # TEST r/m64, r64 (Mod 11: reg)
- in [R64 => left_reg, R64 => right_reg]
- # REX.W + 85 /r
- # MR: Operand 1: ModRM:r/m (r), Operand 2: ModRM:reg (r)
- insn(
- prefix: REX_W,
- opcode: 0x85,
- mod_rm: ModRM[mod: Mod11, reg: right_reg, rm: left_reg],
- )
- end
- end
-
- def xor(dst, src)
- case [dst, src]
- # XOR r/m64, r64 (Mod 11: reg)
- in [R64 => dst_reg, R64 => src_reg]
- # REX.W + 31 /r
- # MR: Operand 1: ModRM:r/m (r, w), Operand 2: ModRM:reg (r)
- insn(
- prefix: REX_W,
- opcode: 0x31,
- mod_rm: ModRM[mod: Mod11, reg: src_reg, rm: dst_reg],
- )
- end
- end
-
- #
- # Utilities
- #
-
- attr_reader :comments
-
- def comment(message)
- @comments[@bytes.size] << message
- end
-
- # Mark the starting address of a block
- def block(block)
- @blocks[@bytes.size] << block
- end
-
- # Mark the starting/ending addresses of a stub
- def stub(stub)
- @stub_starts[@bytes.size] << stub
- yield
- ensure
- @stub_ends[@bytes.size] << stub
- end
-
- def pos_marker(&block)
- @pos_markers[@bytes.size] << block
- end
-
- def new_label(name)
- Label.new(id: @label_id += 1, name:)
- end
-
- # @param [RubyVM::RJIT::Assembler::Label] label
- def write_label(label)
- @labels[label] = @bytes.size
- end
-
- def incr_counter(name)
- if C.rjit_opts.stats
- comment("increment counter #{name}")
- mov(:rax, C.rb_rjit_counters[name].to_i)
- add([:rax], 1) # TODO: lock
- end
- end
-
- private
-
- def insn(prefix: 0, opcode:, rd: nil, mod_rm: nil, disp: nil, imm: nil)
- # Determine prefix
- if rd
- prefix |= REX_B if extended_reg?(rd)
- opcode += reg_code(rd)
- end
- if mod_rm
- prefix |= REX_R if mod_rm.reg.is_a?(Symbol) && extended_reg?(mod_rm.reg)
- prefix |= REX_B if mod_rm.rm.is_a?(Symbol) && extended_reg?(mod_rm.rm)
- end
-
- # Encode insn
- if prefix > 0
- @bytes.push(prefix)
- end
- @bytes.push(*Array(opcode))
- if mod_rm
- mod_rm_byte = encode_mod_rm(
- mod: mod_rm.mod,
- reg: mod_rm.reg.is_a?(Symbol) ? reg_code(mod_rm.reg) : mod_rm.reg,
- rm: mod_rm.rm.is_a?(Symbol) ? reg_code(mod_rm.rm) : mod_rm.rm,
- )
- @bytes.push(mod_rm_byte)
- end
- if disp
- @bytes.push(*Array(disp))
- end
- if imm
- @bytes.push(*imm)
- end
- end
-
- def reg_code(reg)
- reg_code_extended(reg).first
- end
-
- # Table 2-2. 32-Bit Addressing Forms with the ModR/M Byte
- #
- # 7 6 5 4 3 2 1 0
- # +--+--+--+--+--+--+--+--+
- # | Mod | Reg/ | R/M |
- # | | Opcode | |
- # +--+--+--+--+--+--+--+--+
- #
- # The r/m field can specify a register as an operand or it can be combined
- # with the mod field to encode an addressing mode.
- #
- # /0: R/M is 0 (not used)
- # /r: R/M is a register
- def encode_mod_rm(mod:, reg: 0, rm: 0)
- if mod > 0b11
- raise ArgumentError, "too large Mod: #{mod}"
- end
- if reg > 0b111
- raise ArgumentError, "too large Reg/Opcode: #{reg}"
- end
- if rm > 0b111
- raise ArgumentError, "too large R/M: #{rm}"
- end
- (mod << 6) + (reg << 3) + rm
- end
-
- # ib: 1 byte
- def imm8(imm)
- unless imm8?(imm)
- raise ArgumentError, "unexpected imm8: #{imm}"
- end
- [imm].pack('c').unpack('c*') # TODO: consider uimm
- end
-
- # id: 4 bytes
- def imm32(imm)
- unless imm32?(imm)
- raise ArgumentError, "unexpected imm32: #{imm}"
- end
- [imm].pack('l').unpack('c*') # TODO: consider uimm
- end
-
- # io: 8 bytes
- def imm64(imm)
- unless imm64?(imm)
- raise ArgumentError, "unexpected imm64: #{imm}"
- end
- imm_bytes(imm, 8)
- end
-
- def imm_bytes(imm, num_bytes)
- bytes = []
- bits = imm
- num_bytes.times do
- bytes << (bits & 0xff)
- bits >>= 8
- end
- if bits != 0
- raise ArgumentError, "unexpected imm with #{num_bytes} bytes: #{imm}"
- end
- bytes
- end
-
- def rel32(addr)
- [Rel32.new(addr), Rel32Pad, Rel32Pad, Rel32Pad]
- end
-
- def set_code_addrs(write_addr)
- (@bytes.size + 1).times do |index|
- @blocks.fetch(index, []).each do |block|
- block.start_addr = write_addr + index
- end
- @stub_starts.fetch(index, []).each do |stub|
- stub.start_addr = write_addr + index
- end
- @stub_ends.fetch(index, []).each do |stub|
- stub.end_addr = write_addr + index
- end
- end
- end
-
- def resolve_rel32(write_addr)
- @bytes.each_with_index do |byte, index|
- if byte.is_a?(Rel32)
- src_addr = write_addr + index + 4 # offset 4 bytes for rel32 itself
- dst_addr = byte.addr
- rel32 = dst_addr - src_addr
- raise "unexpected offset: #{rel32}" unless imm32?(rel32)
- imm32(rel32).each_with_index do |rel_byte, rel_index|
- @bytes[index + rel_index] = rel_byte
- end
- end
- end
- end
-
- def resolve_labels
- @bytes.each_with_index do |byte, index|
- if byte.is_a?(Label)
- src_index = index + 1 # offset 1 byte for rel8 itself
- dst_index = @labels.fetch(byte)
- rel8 = dst_index - src_index
- raise "unexpected offset: #{rel8}" unless imm8?(rel8)
- @bytes[index] = rel8
- end
- end
- end
-
- def write_bytes(addr)
- Fiddle::Pointer.new(addr)[0, @bytes.size] = @bytes.pack('c*')
- end
- end
-
- module OperandMatcher
- def imm8?(imm)
- (-0x80..0x7f).include?(imm)
- end
-
- def imm32?(imm)
- (-0x8000_0000..0x7fff_ffff).include?(imm) # TODO: consider uimm
- end
-
- def imm64?(imm)
- (-0x8000_0000_0000_0000..0xffff_ffff_ffff_ffff).include?(imm)
- end
-
- def r32?(reg)
- if extended_reg?(reg)
- reg.end_with?('d')
- else
- reg.start_with?('e')
- end
- end
-
- def r64?(reg)
- if extended_reg?(reg)
- reg.match?(/\Ar\d+\z/)
- else
- reg.start_with?('r')
- end
- end
-
- def extended_reg?(reg)
- reg_code_extended(reg).last
- end
-
- def reg_code_extended(reg)
- case reg
- # Not extended
- when :al, :ax, :eax, :rax then [0, false]
- when :cl, :cx, :ecx, :rcx then [1, false]
- when :dl, :dx, :edx, :rdx then [2, false]
- when :bl, :bx, :ebx, :rbx then [3, false]
- when :ah, :sp, :esp, :rsp then [4, false]
- when :ch, :bp, :ebp, :rbp then [5, false]
- when :dh, :si, :esi, :rsi then [6, false]
- when :bh, :di, :edi, :rdi then [7, false]
- # Extended
- when :r8b, :r8w, :r8d, :r8 then [0, true]
- when :r9b, :r9w, :r9d, :r9 then [1, true]
- when :r10b, :r10w, :r10d, :r10 then [2, true]
- when :r11b, :r11w, :r11d, :r11 then [3, true]
- when :r12b, :r12w, :r12d, :r12 then [4, true]
- when :r13b, :r13w, :r13d, :r13 then [5, true]
- when :r14b, :r14w, :r14d, :r14 then [6, true]
- when :r15b, :r15w, :r15d, :r15 then [7, true]
- else raise ArgumentError, "unexpected reg: #{reg.inspect}"
- end
- end
- end
-
- class Assembler
- include OperandMatcher
- extend OperandMatcher
- end
-end
diff --git a/lib/ruby_vm/rjit/block.rb b/lib/ruby_vm/rjit/block.rb
deleted file mode 100644
index cfdaade8b1..0000000000
--- a/lib/ruby_vm/rjit/block.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-class RubyVM::RJIT::Block < Struct.new(
- :iseq, # @param ``
- :pc, # @param [Integer] Starting PC
- :ctx, # @param [RubyVM::RJIT::Context] **Starting** Context (TODO: freeze?)
- :start_addr, # @param [Integer] Starting address of this block's JIT code
- :entry_exit, # @param [Integer] Address of entry exit (optional)
- :incoming, # @param [Array<RubyVM::RJIT::BranchStub>] Incoming branches
- :invalidated, # @param [TrueClass,FalseClass] true if already invalidated
-)
- def initialize(incoming: [], invalidated: false, **) = super
-end
diff --git a/lib/ruby_vm/rjit/branch_stub.rb b/lib/ruby_vm/rjit/branch_stub.rb
deleted file mode 100644
index b9fe78b744..0000000000
--- a/lib/ruby_vm/rjit/branch_stub.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-module RubyVM::RJIT
- # Branch shapes
- Next0 = :Next0 # target0 is a fallthrough
- Next1 = :Next1 # target1 is a fallthrough
- Default = :Default # neither targets is a fallthrough
-
- class BranchStub < Struct.new(
- :iseq, # @param [RubyVM::RJIT::CPointer::Struct_rb_iseq_struct] Branch target ISEQ
- :shape, # @param [Symbol] Next0, Next1, or Default
- :target0, # @param [RubyVM::RJIT::BranchTarget] First branch target
- :target1, # @param [RubyVM::RJIT::BranchTarget,NilClass] Second branch target (optional)
- :compile, # @param [Proc] A callback to (re-)generate this branch stub
- :start_addr, # @param [Integer] Stub source start address to be re-generated
- :end_addr, # @param [Integer] Stub source end address to be re-generated
- )
- end
-
- class BranchTarget < Struct.new(
- :pc,
- :ctx,
- :address,
- )
- end
-end
diff --git a/lib/ruby_vm/rjit/c_pointer.rb b/lib/ruby_vm/rjit/c_pointer.rb
deleted file mode 100644
index db00c4cd11..0000000000
--- a/lib/ruby_vm/rjit/c_pointer.rb
+++ /dev/null
@@ -1,394 +0,0 @@
-module RubyVM::RJIT
- # Every class under this namespace is a pointer. Even if the type is
- # immediate, it shouldn't be dereferenced until `*` is called.
- module CPointer
- # Note: We'd like to avoid alphabetic method names to avoid a conflict
- # with member methods. to_i and to_s are considered an exception.
- class Struct
- # @param name [String]
- # @param sizeof [Integer]
- # @param members [Hash{ Symbol => [RubyVM::RJIT::CType::*, Integer, TrueClass] }]
- def initialize(addr, sizeof, members)
- @addr = addr
- @sizeof = sizeof
- @members = members
- end
-
- # Get a raw address
- def to_i
- @addr
- end
-
- # Serialized address for generated code
- def to_s
- "0x#{@addr.to_s(16)}"
- end
-
- # Pointer diff
- def -(struct)
- raise ArgumentError if self.class != struct.class
- (@addr - struct.to_i) / @sizeof
- end
-
- # Primitive API that does no automatic dereference
- # TODO: remove this?
- # @param member [Symbol]
- def [](member)
- type, offset = @members.fetch(member)
- type.new(@addr + offset / 8)
- end
-
- private
-
- # @param member [Symbol]
- # @param value [Object]
- def []=(member, value)
- type, offset = @members.fetch(member)
- type[@addr + offset / 8] = value
- end
-
- # @param size [Integer]
- # @param members [Hash{ Symbol => [Integer, RubyVM::RJIT::CType::*] }]
- def self.define(size, members)
- Class.new(self) do
- # Return the size of this type
- define_singleton_method(:size) { size }
-
- # Return the offset to a field
- define_singleton_method(:offsetof) do |field, *fields|
- member, offset = members.fetch(field)
- offset /= 8
- unless fields.empty?
- offset += member.offsetof(*fields)
- end
- offset
- end
-
- # Return member names
- define_singleton_method(:members) { members.keys }
-
- define_method(:initialize) do |addr = nil|
- if addr.nil? # TODO: get rid of this feature later
- addr = Fiddle.malloc(size)
- end
- super(addr, size, members)
- end
-
- members.each do |member, (type, offset, to_ruby)|
- # Intelligent API that does automatic dereference
- define_method(member) do
- value = self[member]
- if value.respond_to?(:*)
- value = value.*
- end
- if to_ruby
- value = C.to_ruby(value)
- end
- value
- end
-
- define_method("#{member}=") do |value|
- if to_ruby
- value = C.to_value(value)
- end
- self[member] = value
- end
- end
- end
- end
- end
-
- # Note: We'd like to avoid alphabetic method names to avoid a conflict
- # with member methods. to_i is considered an exception.
- class Union
- # @param _name [String] To be used when it starts defining a union pointer class
- # @param sizeof [Integer]
- # @param members [Hash{ Symbol => RubyVM::RJIT::CType::* }]
- def initialize(addr, sizeof, members)
- @addr = addr
- @sizeof = sizeof
- @members = members
- end
-
- # Get a raw address
- def to_i
- @addr
- end
-
- # Move addr to access this pointer like an array
- def +(index)
- raise ArgumentError unless index.is_a?(Integer)
- self.class.new(@addr + index * @sizeof)
- end
-
- # Pointer diff
- def -(union)
- raise ArgumentError if self.class != union.class
- (@addr - union.instance_variable_get(:@addr)) / @sizeof
- end
-
- # @param sizeof [Integer]
- # @param members [Hash{ Symbol => RubyVM::RJIT::CType::* }]
- def self.define(sizeof, members)
- Class.new(self) do
- # Return the size of this type
- define_singleton_method(:sizeof) { sizeof }
-
- # Part of Struct's offsetof implementation
- define_singleton_method(:offsetof) do |field, *fields|
- member = members.fetch(field)
- offset = 0
- unless fields.empty?
- offset += member.offsetof(*fields)
- end
- offset
- end
-
- define_method(:initialize) do |addr|
- super(addr, sizeof, members)
- end
-
- members.each do |member, type|
- # Intelligent API that does automatic dereference
- define_method(member) do
- value = type.new(@addr)
- if value.respond_to?(:*)
- value = value.*
- end
- value
- end
- end
- end
- end
- end
-
- class Immediate
- # @param addr [Integer]
- # @param size [Integer]
- # @param pack [String]
- def initialize(addr, size, pack)
- @addr = addr
- @size = size
- @pack = pack
- end
-
- # Get a raw address
- def to_i
- @addr
- end
-
- # Move addr to addess this pointer like an array
- def +(index)
- Immediate.new(@addr + index * @size, @size, @pack)
- end
-
- # Dereference
- def *
- self[0]
- end
-
- # Array access
- def [](index)
- return nil if @addr == 0
- Fiddle::Pointer.new(@addr + index * @size)[0, @size].unpack1(@pack)
- end
-
- # Array set
- def []=(index, value)
- Fiddle::Pointer.new(@addr + index * @size)[0, @size] = [value].pack(@pack)
- end
-
- # Serialized address for generated code. Used for embedding things like body->iseq_encoded.
- def to_s
- "0x#{Integer(@addr).to_s(16)}"
- end
-
- # @param fiddle_type [Integer] Fiddle::TYPE_*
- def self.define(fiddle_type)
- size = Fiddle::PackInfo::SIZE_MAP.fetch(fiddle_type)
- pack = Fiddle::PackInfo::PACK_MAP.fetch(fiddle_type)
-
- Class.new(self) do
- define_method(:initialize) do |addr|
- super(addr, size, pack)
- end
-
- define_singleton_method(:size) do
- size
- end
-
- # Type-level []=: Used by struct fields
- define_singleton_method(:[]=) do |addr, value|
- Fiddle::Pointer.new(addr)[0, size] = [value].pack(pack)
- end
- end
- end
- end
-
- # -Fiddle::TYPE_CHAR Immediate with special handling of true/false
- class Bool < Immediate.define(-Fiddle::TYPE_CHAR)
- # Dereference
- def *
- return nil if @addr == 0
- super != 0
- end
-
- def self.[]=(addr, value)
- super(addr, value ? 1 : 0)
- end
- end
-
- # Basically Immediate but without #* to skip auto-dereference of structs.
- class Array
- attr_reader :type
-
- # @param addr [Integer]
- # @param type [Class] RubyVM::RJIT::CType::*
- def initialize(addr, type)
- @addr = addr
- @type = type
- end
-
- # Array access
- def [](index)
- @type.new(@addr)[index]
- end
-
- # Array set
- # @param index [Integer]
- # @param value [Integer, RubyVM::RJIT::CPointer::Struct] an address itself or an object that return an address with to_i
- def []=(index, value)
- @type.new(@addr)[index] = value
- end
-
- private
-
- def self.define(block)
- Class.new(self) do
- define_method(:initialize) do |addr|
- super(addr, block.call)
- end
- end
- end
- end
-
- class Pointer
- attr_reader :type
-
- # @param addr [Integer]
- # @param type [Class] RubyVM::RJIT::CType::*
- def initialize(addr, type)
- @addr = addr
- @type = type
- end
-
- # Move addr to addess this pointer like an array
- def +(index)
- raise ArgumentError unless index.is_a?(Integer)
- Pointer.new(@addr + index * Fiddle::SIZEOF_VOIDP, @type)
- end
-
- # Dereference
- def *
- return nil if dest_addr == 0
- @type.new(dest_addr)
- end
-
- # Array access
- def [](index)
- (self + index).*
- end
-
- # Array set
- # @param index [Integer]
- # @param value [Integer, RubyVM::RJIT::CPointer::Struct] an address itself or an object that return an address with to_i
- def []=(index, value)
- Fiddle::Pointer.new(@addr + index * Fiddle::SIZEOF_VOIDP)[0, Fiddle::SIZEOF_VOIDP] =
- [value.to_i].pack(Fiddle::PackInfo::PACK_MAP[Fiddle::TYPE_VOIDP])
- end
-
- # Get a raw address
- def to_i
- @addr
- end
-
- private
-
- def dest_addr
- Fiddle::Pointer.new(@addr)[0, Fiddle::SIZEOF_VOIDP].unpack1(Fiddle::PackInfo::PACK_MAP[Fiddle::TYPE_VOIDP])
- end
-
- def self.define(block)
- Class.new(self) do
- define_method(:initialize) do |addr|
- super(addr, block.call)
- end
-
- # Type-level []=: Used by struct fields
- # @param addr [Integer]
- # @param value [Integer, RubyVM::RJIT::CPointer::Struct] an address itself, or an object that return an address with to_i
- define_singleton_method(:[]=) do |addr, value|
- value = value.to_i
- Fiddle::Pointer.new(addr)[0, Fiddle::SIZEOF_VOIDP] = [value].pack(Fiddle::PackInfo::PACK_MAP[Fiddle::TYPE_VOIDP])
- end
- end
- end
- end
-
- class BitField
- # @param addr [Integer]
- # @param width [Integer]
- # @param offset [Integer]
- def initialize(addr, width, offset)
- @addr = addr
- @width = width
- @offset = offset
- end
-
- # Dereference
- def *
- byte = Fiddle::Pointer.new(@addr)[0, Fiddle::SIZEOF_CHAR].unpack('c').first
- if @width == 1
- bit = (1 & (byte >> @offset))
- bit == 1
- elsif @width <= 8 && @offset == 0
- bitmask = @width.times.map { |i| 1 << i }.sum
- byte & bitmask
- else
- raise NotImplementedError.new("not-implemented bit field access: width=#{@width} offset=#{@offset}")
- end
- end
-
- # @param width [Integer]
- # @param offset [Integer]
- def self.define(width, offset)
- Class.new(self) do
- define_method(:initialize) do |addr|
- super(addr, width, offset)
- end
- end
- end
- end
-
- # Give a name to a dynamic CPointer class to see it on inspect
- def self.with_class_name(prefix, name, cache: false, &block)
- return block.call if !name.nil? && name.empty?
-
- # Use a cached result only if cache: true
- class_name = "#{prefix}_#{name}"
- klass =
- if cache && self.const_defined?(class_name)
- self.const_get(class_name)
- else
- block.call
- end
-
- # Give it a name unless it's already defined
- unless self.const_defined?(class_name)
- self.const_set(class_name, klass)
- end
-
- klass
- end
- end
-end
diff --git a/lib/ruby_vm/rjit/c_type.rb b/lib/ruby_vm/rjit/c_type.rb
deleted file mode 100644
index 3b313a658b..0000000000
--- a/lib/ruby_vm/rjit/c_type.rb
+++ /dev/null
@@ -1,99 +0,0 @@
-require 'fiddle'
-require 'fiddle/pack'
-require_relative 'c_pointer'
-
-module RubyVM::RJIT
- module CType
- module Struct
- # @param name [String]
- # @param members [Hash{ Symbol => [Integer, RubyVM::RJIT::CType::*] }]
- def self.new(name, sizeof, **members)
- name = members.keys.join('_') if name.empty?
- CPointer.with_class_name('Struct', name) do
- CPointer::Struct.define(sizeof, members)
- end
- end
- end
-
- module Union
- # @param name [String]
- # @param members [Hash{ Symbol => RubyVM::RJIT::CType::* }]
- def self.new(name, sizeof, **members)
- name = members.keys.join('_') if name.empty?
- CPointer.with_class_name('Union', name) do
- CPointer::Union.define(sizeof, members)
- end
- end
- end
-
- module Immediate
- # @param fiddle_type [Integer]
- def self.new(fiddle_type)
- name = Fiddle.constants.find do |const|
- const.start_with?('TYPE_') && Fiddle.const_get(const) == fiddle_type.abs
- end&.to_s
- name.delete_prefix!('TYPE_')
- if fiddle_type.negative?
- name.prepend('U')
- end
- CPointer.with_class_name('Immediate', name, cache: true) do
- CPointer::Immediate.define(fiddle_type)
- end
- end
-
- # @param type [String]
- def self.parse(ctype)
- new(Fiddle::Importer.parse_ctype(ctype))
- end
-
- def self.find(size, signed)
- fiddle_type = TYPE_MAP.fetch(size)
- fiddle_type = -fiddle_type unless signed
- new(fiddle_type)
- end
-
- TYPE_MAP = Fiddle::PackInfo::SIZE_MAP.map { |type, size| [size, type.abs] }.to_h
- private_constant :TYPE_MAP
- end
-
- module Bool
- def self.new
- CPointer::Bool
- end
- end
-
- class Array
- def self.new(&block)
- CPointer.with_class_name('Array', block.object_id.to_s) do
- CPointer::Array.define(block)
- end
- end
- end
-
- class Pointer
- # This takes a block to avoid "stack level too deep" on a cyclic reference
- # @param block [Proc]
- def self.new(&block)
- CPointer.with_class_name('Pointer', block.object_id.to_s) do
- CPointer::Pointer.define(block)
- end
- end
- end
-
- module BitField
- # @param width [Integer]
- # @param offset [Integer]
- def self.new(width, offset)
- CPointer.with_class_name('BitField', "#{offset}_#{width}") do
- CPointer::BitField.define(width, offset)
- end
- end
- end
-
- # Types that are referenced but not part of code generation targets
- Stub = ::Struct.new(:name)
-
- # Types that it failed to figure out from the header
- Unknown = Module.new
- end
-end
diff --git a/lib/ruby_vm/rjit/code_block.rb b/lib/ruby_vm/rjit/code_block.rb
deleted file mode 100644
index 260bd98671..0000000000
--- a/lib/ruby_vm/rjit/code_block.rb
+++ /dev/null
@@ -1,91 +0,0 @@
-module RubyVM::RJIT
- class CodeBlock
- # @param mem_block [Integer] JIT buffer address
- # @param mem_size [Integer] JIT buffer size
- # @param outliend [TrueClass,FalseClass] true for outlined CodeBlock
- def initialize(mem_block:, mem_size:, outlined: false)
- @comments = Hash.new { |h, k| h[k] = [] } if dump_disasm?
- @mem_block = mem_block
- @mem_size = mem_size
- @write_pos = 0
- @outlined = outlined
- end
-
- # @param asm [RubyVM::RJIT::Assembler]
- def write(asm)
- return 0 if @write_pos + asm.size >= @mem_size
-
- start_addr = write_addr
-
- # Write machine code
- C.mprotect_write(@mem_block, @mem_size)
- @write_pos += asm.assemble(start_addr)
- C.mprotect_exec(@mem_block, @mem_size)
-
- end_addr = write_addr
-
- # Convert comment indexes to addresses
- asm.comments.each do |index, comments|
- @comments[start_addr + index] += comments if dump_disasm?
- end
- asm.comments.clear
-
- # Dump disasm if --rjit-dump-disasm
- if C.rjit_opts.dump_disasm && start_addr < end_addr
- dump_disasm(start_addr, end_addr)
- end
- start_addr
- end
-
- def set_write_addr(addr)
- @write_pos = addr - @mem_block
- @comments.delete(addr) if dump_disasm?
- end
-
- def with_write_addr(addr)
- old_write_pos = @write_pos
- set_write_addr(addr)
- yield
- ensure
- @write_pos = old_write_pos
- end
-
- def write_addr
- @mem_block + @write_pos
- end
-
- def include?(addr)
- (@mem_block...(@mem_block + @mem_size)).include?(addr)
- end
-
- def dump_disasm(from, to, io: STDOUT, color: true, test: false)
- C.dump_disasm(from, to, test:).each do |address, mnemonic, op_str|
- @comments.fetch(address, []).each do |comment|
- io.puts colorize(" # #{comment}", bold: true, color:)
- end
- io.puts colorize(" 0x#{format("%x", address)}: #{mnemonic} #{op_str}", color:)
- end
- io.puts
- end
-
- private
-
- def colorize(text, bold: false, color:)
- return text unless color
- buf = +''
- buf << "\e[1m" if bold
- buf << "\e[34m" if @outlined
- buf << text
- buf << "\e[0m"
- buf
- end
-
- def bold(text)
- "\e[1m#{text}\e[0m"
- end
-
- def dump_disasm?
- C.rjit_opts.dump_disasm
- end
- end
-end
diff --git a/lib/ruby_vm/rjit/compiler.rb b/lib/ruby_vm/rjit/compiler.rb
deleted file mode 100644
index e5c3adf0ec..0000000000
--- a/lib/ruby_vm/rjit/compiler.rb
+++ /dev/null
@@ -1,518 +0,0 @@
-require 'ruby_vm/rjit/assembler'
-require 'ruby_vm/rjit/block'
-require 'ruby_vm/rjit/branch_stub'
-require 'ruby_vm/rjit/code_block'
-require 'ruby_vm/rjit/context'
-require 'ruby_vm/rjit/entry_stub'
-require 'ruby_vm/rjit/exit_compiler'
-require 'ruby_vm/rjit/insn_compiler'
-require 'ruby_vm/rjit/instruction'
-require 'ruby_vm/rjit/invariants'
-require 'ruby_vm/rjit/jit_state'
-require 'ruby_vm/rjit/type'
-
-module RubyVM::RJIT
- # Compilation status
- KeepCompiling = :KeepCompiling
- CantCompile = :CantCompile
- EndBlock = :EndBlock
-
- # Ruby constants
- Qtrue = Fiddle::Qtrue
- Qfalse = Fiddle::Qfalse
- Qnil = Fiddle::Qnil
- Qundef = Fiddle::Qundef
-
- # Callee-saved registers
- # TODO: support using r12/r13 here
- EC = :r14
- CFP = :r15
- SP = :rbx
-
- # Scratch registers: rax, rcx, rdx
-
- # Mark objects in this Array during GC
- GC_REFS = []
-
- # Maximum number of versions per block
- # 1 means always create generic versions
- MAX_VERSIONS = 4
-
- class Compiler
- attr_accessor :write_pos
-
- def self.decode_insn(encoded)
- INSNS.fetch(C.rb_vm_insn_decode(encoded))
- end
-
- def initialize
- mem_size = C.rjit_opts.exec_mem_size * 1024 * 1024
- mem_block = C.mmap(mem_size)
- @cb = CodeBlock.new(mem_block: mem_block, mem_size: mem_size / 2)
- @ocb = CodeBlock.new(mem_block: mem_block + mem_size / 2, mem_size: mem_size / 2, outlined: true)
- @exit_compiler = ExitCompiler.new
- @insn_compiler = InsnCompiler.new(@cb, @ocb, @exit_compiler)
- Invariants.initialize(@cb, @ocb, self, @exit_compiler)
- end
-
- # Compile an ISEQ from its entry point.
- # @param iseq `RubyVM::RJIT::CPointer::Struct_rb_iseq_t`
- # @param cfp `RubyVM::RJIT::CPointer::Struct_rb_control_frame_t`
- def compile(iseq, cfp)
- return unless supported_platform?
- pc = cfp.pc.to_i
- jit = JITState.new(iseq:, cfp:)
- asm = Assembler.new
- compile_prologue(asm, iseq, pc)
- compile_block(asm, jit:, pc:)
- iseq.body.jit_entry = @cb.write(asm)
- rescue Exception => e
- STDERR.puts "#{e.class}: #{e.message}"
- STDERR.puts e.backtrace
- exit 1
- end
-
- # Compile an entry.
- # @param entry [RubyVM::RJIT::EntryStub]
- def entry_stub_hit(entry_stub, cfp)
- # Compile a new entry guard as a next entry
- pc = cfp.pc.to_i
- next_entry = Assembler.new.then do |asm|
- compile_entry_chain_guard(asm, cfp.iseq, pc)
- @cb.write(asm)
- end
-
- # Try to find an existing compiled version of this block
- ctx = Context.new
- block = find_block(cfp.iseq, pc, ctx)
- if block
- # If an existing block is found, generate a jump to the block.
- asm = Assembler.new
- asm.jmp(block.start_addr)
- @cb.write(asm)
- else
- # If this block hasn't yet been compiled, generate blocks after the entry guard.
- asm = Assembler.new
- jit = JITState.new(iseq: cfp.iseq, cfp:)
- compile_block(asm, jit:, pc:, ctx:)
- @cb.write(asm)
-
- block = jit.block
- end
-
- # Regenerate the previous entry
- @cb.with_write_addr(entry_stub.start_addr) do
- # The last instruction of compile_entry_chain_guard is jne
- asm = Assembler.new
- asm.jne(next_entry)
- @cb.write(asm)
- end
-
- return block.start_addr
- rescue Exception => e
- STDERR.puts e.full_message
- exit 1
- end
-
- # Compile a branch stub.
- # @param branch_stub [RubyVM::RJIT::BranchStub]
- # @param cfp `RubyVM::RJIT::CPointer::Struct_rb_control_frame_t`
- # @param target0_p [TrueClass,FalseClass]
- # @return [Integer] The starting address of the compiled branch stub
- def branch_stub_hit(branch_stub, cfp, target0_p)
- # Update cfp->pc for `jit.at_current_insn?`
- target = target0_p ? branch_stub.target0 : branch_stub.target1
- cfp.pc = target.pc
-
- # Reuse an existing block if it already exists
- block = find_block(branch_stub.iseq, target.pc, target.ctx)
-
- # If the branch stub's jump is the last code, allow overwriting part of
- # the old branch code with the new block code.
- fallthrough = block.nil? && @cb.write_addr == branch_stub.end_addr
- if fallthrough
- # If the branch stub's jump is the last code, allow overwriting part of
- # the old branch code with the new block code.
- @cb.set_write_addr(branch_stub.start_addr)
- branch_stub.shape = target0_p ? Next0 : Next1
- Assembler.new.tap do |branch_asm|
- branch_stub.compile.call(branch_asm)
- @cb.write(branch_asm)
- end
- end
-
- # Reuse or generate a block
- if block
- target.address = block.start_addr
- else
- jit = JITState.new(iseq: branch_stub.iseq, cfp:)
- target.address = Assembler.new.then do |asm|
- compile_block(asm, jit:, pc: target.pc, ctx: target.ctx.dup)
- @cb.write(asm)
- end
- block = jit.block
- end
- block.incoming << branch_stub # prepare for invalidate_block
-
- # Re-generate the branch code for non-fallthrough cases
- unless fallthrough
- @cb.with_write_addr(branch_stub.start_addr) do
- branch_asm = Assembler.new
- branch_stub.compile.call(branch_asm)
- @cb.write(branch_asm)
- end
- end
-
- return target.address
- rescue Exception => e
- STDERR.puts e.full_message
- exit 1
- end
-
- # @param iseq `RubyVM::RJIT::CPointer::Struct_rb_iseq_t`
- # @param pc [Integer]
- def invalidate_blocks(iseq, pc)
- list_blocks(iseq, pc).each do |block|
- invalidate_block(block)
- end
-
- # If they were the ISEQ's first blocks, re-compile RJIT entry as well
- if iseq.body.iseq_encoded.to_i == pc
- iseq.body.jit_entry = 0
- iseq.body.jit_entry_calls = 0
- end
- end
-
- def invalidate_block(block)
- iseq = block.iseq
- # Avoid touching GCed ISEQs. We assume it won't be re-entered.
- return unless C.imemo_type_p(iseq, C.imemo_iseq)
-
- # Remove this block from the version array
- remove_block(iseq, block)
-
- # Invalidate the block with entry exit
- unless block.invalidated
- @cb.with_write_addr(block.start_addr) do
- asm = Assembler.new
- asm.comment('invalidate_block')
- asm.jmp(block.entry_exit)
- @cb.write(asm)
- end
- block.invalidated = true
- end
-
- # Re-stub incoming branches
- block.incoming.each do |branch_stub|
- target = [branch_stub.target0, branch_stub.target1].compact.find do |target|
- target.pc == block.pc && target.ctx == block.ctx
- end
- next if target.nil?
- # TODO: Could target.address be a stub address? Is invalidation not needed in that case?
-
- # If the target being re-generated is currently a fallthrough block,
- # the fallthrough code must be rewritten with a jump to the stub.
- if target.address == branch_stub.end_addr
- branch_stub.shape = Default
- end
-
- target.address = Assembler.new.then do |ocb_asm|
- @exit_compiler.compile_branch_stub(block.ctx, ocb_asm, branch_stub, target == branch_stub.target0)
- @ocb.write(ocb_asm)
- end
- @cb.with_write_addr(branch_stub.start_addr) do
- branch_asm = Assembler.new
- branch_stub.compile.call(branch_asm)
- @cb.write(branch_asm)
- end
- end
- end
-
- private
-
- # Callee-saved: rbx, rsp, rbp, r12, r13, r14, r15
- # Caller-saved: rax, rdi, rsi, rdx, rcx, r8, r9, r10, r11
- #
- # @param asm [RubyVM::RJIT::Assembler]
- def compile_prologue(asm, iseq, pc)
- asm.comment('RJIT entry point')
-
- # Save callee-saved registers used by JITed code
- asm.push(CFP)
- asm.push(EC)
- asm.push(SP)
-
- # Move arguments EC and CFP to dedicated registers
- asm.mov(EC, :rdi)
- asm.mov(CFP, :rsi)
-
- # Load sp to a dedicated register
- asm.mov(SP, [CFP, C.rb_control_frame_t.offsetof(:sp)]) # rbx = cfp->sp
-
- # Setup cfp->jit_return
- asm.mov(:rax, leave_exit)
- asm.mov([CFP, C.rb_control_frame_t.offsetof(:jit_return)], :rax)
-
- # 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
- compile_entry_chain_guard(asm, iseq, pc)
- end
- end
-
- def compile_entry_chain_guard(asm, iseq, pc)
- entry_stub = EntryStub.new
- stub_addr = Assembler.new.then do |ocb_asm|
- @exit_compiler.compile_entry_stub(ocb_asm, entry_stub)
- @ocb.write(ocb_asm)
- end
-
- asm.comment('guard expected PC')
- asm.mov(:rax, pc)
- asm.cmp([CFP, C.rb_control_frame_t.offsetof(:pc)], :rax)
-
- asm.stub(entry_stub) do
- asm.jne(stub_addr)
- end
- end
-
- # @param asm [RubyVM::RJIT::Assembler]
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- def compile_block(asm, jit:, pc:, ctx: Context.new)
- # Mark the block start address and prepare an exit code storage
- ctx = limit_block_versions(jit.iseq, pc, ctx)
- block = Block.new(iseq: jit.iseq, pc:, ctx: ctx.dup)
- jit.block = block
- asm.block(block)
-
- iseq = jit.iseq
- asm.comment("Block: #{iseq.body.location.label}@#{C.rb_iseq_path(iseq)}:#{iseq_lineno(iseq, pc)}")
-
- # Compile each insn
- index = (pc - iseq.body.iseq_encoded.to_i) / C.VALUE.size
- while index < iseq.body.iseq_size
- # Set the current instruction
- insn = self.class.decode_insn(iseq.body.iseq_encoded[index])
- jit.pc = (iseq.body.iseq_encoded + index).to_i
- jit.stack_size_for_pc = ctx.stack_size
- jit.side_exit_for_pc.clear
-
- # If previous instruction requested to record the boundary
- if jit.record_boundary_patch_point
- # Generate an exit to this instruction and record it
- exit_pos = Assembler.new.then do |ocb_asm|
- @exit_compiler.compile_side_exit(jit.pc, ctx, ocb_asm)
- @ocb.write(ocb_asm)
- end
- Invariants.record_global_inval_patch(asm, exit_pos)
- jit.record_boundary_patch_point = false
- end
-
- # In debug mode, verify our existing assumption
- if C.rjit_opts.verify_ctx && jit.at_current_insn?
- verify_ctx(jit, ctx)
- end
-
- case status = @insn_compiler.compile(jit, ctx, asm, insn)
- when KeepCompiling
- # 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
-
- index += insn.len
- when EndBlock
- # TODO: pad nops if entry exit exists (not needed for x86_64?)
- break
- when CantCompile
- # Rewind stack_size using ctx.with_stack_size to allow stack_size changes
- # before you return CantCompile.
- @exit_compiler.compile_side_exit(jit.pc, ctx.with_stack_size(jit.stack_size_for_pc), asm)
-
- # If this is the first instruction, this block never needs to be invalidated.
- if block.pc == iseq.body.iseq_encoded.to_i + index * C.VALUE.size
- block.invalidated = true
- end
-
- break
- else
- raise "compiling #{insn.name} returned unexpected status: #{status.inspect}"
- end
- end
-
- incr_counter(:compiled_block_count)
- add_block(iseq, block)
- end
-
- def leave_exit
- @leave_exit ||= Assembler.new.then do |asm|
- @exit_compiler.compile_leave_exit(asm)
- @ocb.write(asm)
- end
- end
-
- def incr_counter(name)
- if C.rjit_opts.stats
- C.rb_rjit_counters[name][0] += 1
- end
- end
-
- # Produce a generic context when the block version limit is hit for the block
- def limit_block_versions(iseq, pc, ctx)
- # Guard chains implement limits separately, do nothing
- if ctx.chain_depth > 0
- return ctx.dup
- end
-
- # If this block version we're about to add will hit the version limit
- if list_blocks(iseq, pc).size + 1 >= 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.
- generic_ctx = Context.new
- generic_ctx.stack_size = ctx.stack_size
- generic_ctx.sp_offset = ctx.sp_offset
-
- if ctx.diff(generic_ctx) == TypeDiff::Incompatible
- raise 'should substitute a compatible context'
- end
-
- return generic_ctx
- end
-
- return ctx.dup
- end
-
- def list_blocks(iseq, pc)
- rjit_blocks(iseq)[pc]
- end
-
- # @param [Integer] pc
- # @param [RubyVM::RJIT::Context] ctx
- # @return [RubyVM::RJIT::Block,NilClass]
- def find_block(iseq, pc, ctx)
- versions = rjit_blocks(iseq)[pc]
-
- best_version = nil
- best_diff = Float::INFINITY
-
- versions.each do |block|
- # Note that we always prefer the first matching
- # version found because of inline-cache chains
- case ctx.diff(block.ctx)
- in TypeDiff::Compatible[diff] if diff < best_diff
- best_version = block
- best_diff = diff
- else
- end
- end
-
- return best_version
- end
-
- # @param [RubyVM::RJIT::Block] block
- def add_block(iseq, block)
- rjit_blocks(iseq)[block.pc] << block
- end
-
- # @param [RubyVM::RJIT::Block] block
- def remove_block(iseq, block)
- rjit_blocks(iseq)[block.pc].delete(block)
- end
-
- def rjit_blocks(iseq)
- # Guard against ISEQ GC at random moments
-
- unless C.imemo_type_p(iseq, C.imemo_iseq)
- return Hash.new { |h, k| h[k] = [] }
- end
-
- unless iseq.body.rjit_blocks
- iseq.body.rjit_blocks = Hash.new { |blocks, pc| blocks[pc] = [] }
- # For some reason, rb_rjit_iseq_mark didn't protect this Hash
- # from being freed. So we rely on GC_REFS to keep the Hash.
- GC_REFS << iseq.body.rjit_blocks
- end
- iseq.body.rjit_blocks
- end
-
- def iseq_lineno(iseq, pc)
- C.rb_iseq_line_no(iseq, (pc - iseq.body.iseq_encoded.to_i) / C.VALUE.size)
- rescue RangeError # bignum too big to convert into `unsigned long long' (RangeError)
- -1
- end
-
- # Verify the ctx's types and mappings against the compile-time stack, self, and locals.
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- def verify_ctx(jit, ctx)
- # Only able to check types when at current insn
- assert(jit.at_current_insn?)
-
- self_val = jit.peek_at_self
- self_val_type = Type.from(self_val)
-
- # Verify self operand type
- assert_compatible(self_val_type, ctx.get_opnd_type(SelfOpnd))
-
- # Verify stack operand types
- [ctx.stack_size, MAX_TEMP_TYPES].min.times do |i|
- learned_mapping, learned_type = ctx.get_opnd_mapping(StackOpnd[i])
- stack_val = jit.peek_at_stack(i)
- val_type = Type.from(stack_val)
-
- case learned_mapping
- in MapToSelf
- if C.to_value(self_val) != C.to_value(stack_val)
- raise "verify_ctx: stack value was mapped to self, but values did not match:\n"\
- "stack: #{stack_val.inspect}, self: #{self_val.inspect}"
- end
- in MapToLocal[local_idx]
- local_val = jit.peek_at_local(local_idx)
- if C.to_value(local_val) != C.to_value(stack_val)
- raise "verify_ctx: stack value was mapped to local, but values did not match:\n"\
- "stack: #{stack_val.inspect}, local: #{local_val.inspect}"
- end
- in MapToStack
- # noop
- end
-
- # If the actual type differs from the learned type
- assert_compatible(val_type, learned_type)
- end
-
- # Verify local variable types
- local_table_size = jit.iseq.body.local_table_size
- [local_table_size, MAX_TEMP_TYPES].min.times do |i|
- learned_type = ctx.get_local_type(i)
- local_val = jit.peek_at_local(i)
- local_type = Type.from(local_val)
-
- assert_compatible(local_type, learned_type)
- end
- end
-
- def assert_compatible(actual_type, ctx_type)
- if actual_type.diff(ctx_type) == TypeDiff::Incompatible
- raise "verify_ctx: ctx type (#{ctx_type.type.inspect}) is incompatible with actual type (#{actual_type.type.inspect})"
- end
- end
-
- def assert(cond)
- unless cond
- raise "'#{cond.inspect}' was not true"
- end
- end
-
- def supported_platform?
- return @supported_platform if defined?(@supported_platform)
- @supported_platform = RUBY_PLATFORM.match?(/x86_64/).tap do |supported|
- warn "warning: RJIT does not support #{RUBY_PLATFORM} yet" unless supported
- end
- end
- end
-end
diff --git a/lib/ruby_vm/rjit/context.rb b/lib/ruby_vm/rjit/context.rb
deleted file mode 100644
index a2a7ecc6dc..0000000000
--- a/lib/ruby_vm/rjit/context.rb
+++ /dev/null
@@ -1,377 +0,0 @@
-module RubyVM::RJIT
- # Maximum number of temp value types we keep track of
- MAX_TEMP_TYPES = 8
- # Maximum number of local variable types we keep track of
- MAX_LOCAL_TYPES = 8
-
- # Operand to a YARV bytecode instruction
- SelfOpnd = :SelfOpnd # The value is self
- StackOpnd = Data.define(:index) # Temporary stack operand with stack index
-
- # Potential mapping of a value on the temporary stack to self,
- # a local variable, or constant so that we can track its type
- MapToStack = :MapToStack # Normal stack value
- MapToSelf = :MapToSelf # Temp maps to the self operand
- MapToLocal = Data.define(:local_index) # Temp maps to a local variable with index
-
- class Context < Struct.new(
- :stack_size, # @param [Integer] The number of values on the stack
- :sp_offset, # @param [Integer] JIT sp offset relative to the interpreter's sp
- :chain_depth, # @param [Integer] jit_chain_guard depth
- :local_types, # @param [Array<RubyVM::RJIT::Type>] Local variable types we keep track of
- :temp_types, # @param [Array<RubyVM::RJIT::Type>] Temporary variable types we keep track of
- :self_type, # @param [RubyVM::RJIT::Type] Type we track for self
- :temp_mapping, # @param [Array<Symbol>] Mapping of temp stack entries to types we track
- )
- def initialize(
- stack_size: 0,
- sp_offset: 0,
- chain_depth: 0,
- local_types: [Type::Unknown] * MAX_LOCAL_TYPES,
- temp_types: [Type::Unknown] * MAX_TEMP_TYPES,
- self_type: Type::Unknown,
- temp_mapping: [MapToStack] * MAX_TEMP_TYPES
- ) = super
-
- # Deep dup by default for safety
- def dup
- ctx = super
- ctx.local_types = ctx.local_types.dup
- ctx.temp_types = ctx.temp_types.dup
- ctx.temp_mapping = ctx.temp_mapping.dup
- ctx
- end
-
- # Create a new Context instance with a given stack_size and sp_offset adjusted
- # accordingly. This is useful when you want to virtually rewind a stack_size for
- # generating a side exit while considering past sp_offset changes on gen_save_sp.
- def with_stack_size(stack_size)
- ctx = self.dup
- ctx.sp_offset -= ctx.stack_size - stack_size
- ctx.stack_size = stack_size
- ctx
- end
-
- def stack_opnd(depth_from_top)
- [SP, C.VALUE.size * (self.sp_offset - 1 - depth_from_top)]
- end
-
- def sp_opnd(offset_bytes = 0)
- [SP, (C.VALUE.size * self.sp_offset) + offset_bytes]
- end
-
- # Push one new value on the temp stack with an explicit mapping
- # Return a pointer to the new stack top
- def stack_push_mapping(mapping_temp_type)
- stack_size = self.stack_size
-
- # Keep track of the type and mapping of the value
- if stack_size < MAX_TEMP_TYPES
- mapping, temp_type = mapping_temp_type
- self.temp_mapping[stack_size] = mapping
- self.temp_types[stack_size] = temp_type
-
- case mapping
- in MapToLocal[idx]
- assert(idx < MAX_LOCAL_TYPES)
- else
- end
- end
-
- self.stack_size += 1
- self.sp_offset += 1
-
- return self.stack_opnd(0)
- end
-
- # Push one new value on the temp stack
- # Return a pointer to the new stack top
- def stack_push(val_type)
- return self.stack_push_mapping([MapToStack, val_type])
- end
-
- # Push the self value on the stack
- def stack_push_self
- return self.stack_push_mapping([MapToStack, Type::Unknown])
- end
-
- # Push a local variable on the stack
- def stack_push_local(local_idx)
- if local_idx >= MAX_LOCAL_TYPES
- return self.stack_push(Type::Unknown)
- end
-
- return self.stack_push_mapping([MapToLocal[local_idx], Type::Unknown])
- end
-
- # Pop N values off the stack
- # Return a pointer to the stack top before the pop operation
- def stack_pop(n = 1)
- assert(n <= self.stack_size)
-
- top = self.stack_opnd(0)
-
- # Clear the types of the popped values
- n.times do |i|
- idx = self.stack_size - i - 1
-
- if idx < MAX_TEMP_TYPES
- self.temp_types[idx] = Type::Unknown
- self.temp_mapping[idx] = MapToStack
- end
- end
-
- self.stack_size -= n
- self.sp_offset -= n
-
- return top
- end
-
- def shift_stack(argc)
- assert(argc < self.stack_size)
-
- method_name_index = self.stack_size - argc - 1
-
- (method_name_index...(self.stack_size - 1)).each do |i|
- if i + 1 < MAX_TEMP_TYPES
- self.temp_types[i] = self.temp_types[i + 1]
- self.temp_mapping[i] = self.temp_mapping[i + 1]
- end
- end
- self.stack_pop(1)
- end
-
- # Get the type of an instruction operand
- def get_opnd_type(opnd)
- case opnd
- in SelfOpnd
- self.self_type
- in StackOpnd[idx]
- assert(idx < self.stack_size)
- stack_idx = self.stack_size - 1 - idx
-
- # If outside of tracked range, do nothing
- if stack_idx >= MAX_TEMP_TYPES
- return Type::Unknown
- end
-
- mapping = self.temp_mapping[stack_idx]
-
- case mapping
- in MapToSelf
- self.self_type
- in MapToStack
- self.temp_types[self.stack_size - 1 - idx]
- in MapToLocal[idx]
- assert(idx < MAX_LOCAL_TYPES)
- self.local_types[idx]
- end
- end
- end
-
- # Get the currently tracked type for a local variable
- def get_local_type(idx)
- self.local_types[idx] || Type::Unknown
- end
-
- # 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.
- def upgrade_opnd_type(opnd, opnd_type)
- case opnd
- in SelfOpnd
- self.self_type = self.self_type.upgrade(opnd_type)
- in StackOpnd[idx]
- assert(idx < self.stack_size)
- stack_idx = self.stack_size - 1 - idx
-
- # If outside of tracked range, do nothing
- if stack_idx >= MAX_TEMP_TYPES
- return
- end
-
- mapping = self.temp_mapping[stack_idx]
-
- case mapping
- in MapToSelf
- self.self_type = self.self_type.upgrade(opnd_type)
- in MapToStack
- self.temp_types[stack_idx] = self.temp_types[stack_idx].upgrade(opnd_type)
- in MapToLocal[idx]
- assert(idx < MAX_LOCAL_TYPES)
- self.local_types[idx] = self.local_types[idx].upgrade(opnd_type)
- end
- end
- end
-
- # Get both the type and mapping (where the value originates) of an operand.
- # This is can be used with stack_push_mapping or set_opnd_mapping to copy
- # a stack value's type while maintaining the mapping.
- def get_opnd_mapping(opnd)
- opnd_type = self.get_opnd_type(opnd)
-
- case opnd
- in SelfOpnd
- return [MapToSelf, opnd_type]
- in StackOpnd[idx]
- assert(idx < self.stack_size)
- stack_idx = self.stack_size - 1 - idx
-
- if stack_idx < MAX_TEMP_TYPES
- return [self.temp_mapping[stack_idx], opnd_type]
- else
- # We can't know the source of this stack operand, so we assume it is
- # a stack-only temporary. type will be UNKNOWN
- assert(opnd_type == Type::Unknown)
- return [MapToStack, opnd_type]
- end
- end
- end
-
- # Overwrite both the type and mapping of a stack operand.
- def set_opnd_mapping(opnd, mapping_opnd_type)
- case opnd
- in SelfOpnd
- raise 'self always maps to self'
- in StackOpnd[idx]
- assert(idx < self.stack_size)
- stack_idx = self.stack_size - 1 - idx
-
- # If outside of tracked range, do nothing
- if stack_idx >= MAX_TEMP_TYPES
- return
- end
-
- mapping, opnd_type = mapping_opnd_type
- self.temp_mapping[stack_idx] = mapping
-
- # Only used when mapping == MAP_STACK
- self.temp_types[stack_idx] = opnd_type
- end
- end
-
- # Set the type of a local variable
- def set_local_type(local_idx, local_type)
- if local_idx >= MAX_LOCAL_TYPES
- return
- end
-
- # If any values on the stack map to this local we must detach them
- MAX_TEMP_TYPES.times do |stack_idx|
- case self.temp_mapping[stack_idx]
- in MapToStack
- # noop
- in MapToSelf
- # noop
- in MapToLocal[idx]
- if idx == local_idx
- self.temp_types[stack_idx] = self.local_types[idx]
- self.temp_mapping[stack_idx] = MapToStack
- else
- # noop
- end
- end
- end
-
- self.local_types[local_idx] = local_type
- end
-
- # Erase local variable type information
- # eg: because of a call we can't track
- def clear_local_types
- # When clearing local types we must detach any stack mappings to those
- # locals. Even if local values may have changed, stack values will not.
- MAX_TEMP_TYPES.times do |stack_idx|
- case self.temp_mapping[stack_idx]
- in MapToStack
- # noop
- in MapToSelf
- # noop
- in MapToLocal[local_idx]
- self.temp_types[stack_idx] = self.local_types[local_idx]
- self.temp_mapping[stack_idx] = MapToStack
- end
- end
-
- # Clear the local types
- self.local_types = [Type::Unknown] * MAX_LOCAL_TYPES
- end
-
- # Compute a difference score for two context objects
- def diff(dst)
- # Self is the source context (at the end of the predecessor)
- src = self
-
- # Can only lookup the first version in the chain
- if dst.chain_depth != 0
- return TypeDiff::Incompatible
- end
-
- # Blocks with depth > 0 always produce new versions
- # Sidechains cannot overlap
- if src.chain_depth != 0
- return TypeDiff::Incompatible
- end
-
- if dst.stack_size != src.stack_size
- return TypeDiff::Incompatible
- end
-
- if dst.sp_offset != src.sp_offset
- return TypeDiff::Incompatible
- end
-
- # Difference sum
- diff = 0
-
- # Check the type of self
- diff += case src.self_type.diff(dst.self_type)
- in TypeDiff::Compatible[diff] then diff
- in TypeDiff::Incompatible then return TypeDiff::Incompatible
- end
-
- # For each local type we track
- src.local_types.size.times do |i|
- t_src = src.local_types[i]
- t_dst = dst.local_types[i]
- diff += case t_src.diff(t_dst)
- in TypeDiff::Compatible[diff] then diff
- in TypeDiff::Incompatible then return TypeDiff::Incompatible
- end
- end
-
- # For each value on the temp stack
- src.stack_size.times do |i|
- src_mapping, src_type = src.get_opnd_mapping(StackOpnd[i])
- dst_mapping, dst_type = dst.get_opnd_mapping(StackOpnd[i])
-
- # If the two mappings aren't the same
- if src_mapping != dst_mapping
- if dst_mapping == MapToStack
- # We can safely drop information about the source of the temp
- # stack operand.
- diff += 1
- else
- return TypeDiff::Incompatible
- end
- end
-
- diff += case src_type.diff(dst_type)
- in TypeDiff::Compatible[diff] then diff
- in TypeDiff::Incompatible then return TypeDiff::Incompatible
- end
- end
-
- return TypeDiff::Compatible[diff]
- end
-
- private
-
- def assert(cond)
- unless cond
- raise "'#{cond.inspect}' was not true"
- end
- end
- end
-end
diff --git a/lib/ruby_vm/rjit/entry_stub.rb b/lib/ruby_vm/rjit/entry_stub.rb
deleted file mode 100644
index 9bcef14053..0000000000
--- a/lib/ruby_vm/rjit/entry_stub.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-module RubyVM::RJIT
- class EntryStub < Struct.new(
- :start_addr, # @param [Integer] Stub source start address to be re-generated
- :end_addr, # @param [Integer] Stub source end address to be re-generated
- )
- end
-end
diff --git a/lib/ruby_vm/rjit/exit_compiler.rb b/lib/ruby_vm/rjit/exit_compiler.rb
deleted file mode 100644
index 1ced2141a4..0000000000
--- a/lib/ruby_vm/rjit/exit_compiler.rb
+++ /dev/null
@@ -1,164 +0,0 @@
-module RubyVM::RJIT
- class ExitCompiler
- def initialize = freeze
-
- # Used for invalidating a block on entry.
- # @param pc [Integer]
- # @param asm [RubyVM::RJIT::Assembler]
- def compile_entry_exit(pc, ctx, asm, cause:)
- # Fix pc/sp offsets for the interpreter
- save_pc_and_sp(pc, ctx, asm, reset_sp_offset: false)
-
- # Increment per-insn exit counter
- count_insn_exit(pc, asm)
-
- # Restore callee-saved registers
- asm.comment("#{cause}: entry exit")
- asm.pop(SP)
- asm.pop(EC)
- asm.pop(CFP)
-
- asm.mov(C_RET, Qundef)
- asm.ret
- end
-
- # Set to cfp->jit_return by default for leave insn
- # @param asm [RubyVM::RJIT::Assembler]
- def compile_leave_exit(asm)
- asm.comment('default cfp->jit_return')
-
- # Restore callee-saved registers
- asm.pop(SP)
- asm.pop(EC)
- asm.pop(CFP)
-
- # :rax is written by #leave
- asm.ret
- end
-
- # Fire cfunc events on invalidation by TracePoint
- # @param asm [RubyVM::RJIT::Assembler]
- def compile_full_cfunc_return(asm)
- # This chunk of code expects REG_EC to be filled properly and
- # RAX to contain the return value of the C method.
-
- asm.comment('full cfunc return')
- asm.mov(C_ARGS[0], EC)
- asm.mov(C_ARGS[1], :rax)
- asm.call(C.rjit_full_cfunc_return)
-
- # TODO: count the exit
-
- # Restore callee-saved registers
- asm.pop(SP)
- asm.pop(EC)
- asm.pop(CFP)
-
- asm.mov(C_RET, Qundef)
- asm.ret
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def compile_side_exit(pc, ctx, asm)
- # Fix pc/sp offsets for the interpreter
- save_pc_and_sp(pc, ctx.dup, asm) # dup to avoid sp_offset update
-
- # Increment per-insn exit counter
- count_insn_exit(pc, asm)
-
- # Restore callee-saved registers
- asm.comment("exit to interpreter on #{pc_to_insn(pc).name}")
- asm.pop(SP)
- asm.pop(EC)
- asm.pop(CFP)
-
- asm.mov(C_RET, Qundef)
- asm.ret
- end
-
- # @param asm [RubyVM::RJIT::Assembler]
- # @param entry_stub [RubyVM::RJIT::EntryStub]
- def compile_entry_stub(asm, entry_stub)
- # Call rb_rjit_entry_stub_hit
- asm.comment('entry stub hit')
- asm.mov(C_ARGS[0], to_value(entry_stub))
- asm.call(C.rb_rjit_entry_stub_hit)
-
- # Jump to the address returned by rb_rjit_entry_stub_hit
- asm.jmp(:rax)
- end
-
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- # @param branch_stub [RubyVM::RJIT::BranchStub]
- # @param target0_p [TrueClass,FalseClass]
- def compile_branch_stub(ctx, asm, branch_stub, target0_p)
- # Call rb_rjit_branch_stub_hit
- iseq = branch_stub.iseq
- if C.rjit_opts.dump_disasm && C.imemo_type_p(iseq, C.imemo_iseq) # Guard against ISEQ GC at random moments
- asm.comment("branch stub hit: #{iseq.body.location.label}@#{C.rb_iseq_path(iseq)}:#{iseq_lineno(iseq, target0_p ? branch_stub.target0.pc : branch_stub.target1.pc)}")
- end
- asm.mov(:rdi, to_value(branch_stub))
- asm.mov(:esi, ctx.sp_offset)
- asm.mov(:edx, target0_p ? 1 : 0)
- asm.call(C.rb_rjit_branch_stub_hit)
-
- # Jump to the address returned by rb_rjit_branch_stub_hit
- asm.jmp(:rax)
- end
-
- private
-
- def pc_to_insn(pc)
- Compiler.decode_insn(C.VALUE.new(pc).*)
- end
-
- # @param pc [Integer]
- # @param asm [RubyVM::RJIT::Assembler]
- def count_insn_exit(pc, asm)
- if C.rjit_opts.stats
- insn = Compiler.decode_insn(C.VALUE.new(pc).*)
- asm.comment("increment insn exit: #{insn.name}")
- asm.mov(:rax, (C.rjit_insn_exits + insn.bin).to_i)
- asm.add([:rax], 1) # TODO: lock
- end
- if C.rjit_opts.trace_exits
- asm.comment('rjit_record_exit_stack')
- asm.mov(C_ARGS[0], pc)
- asm.call(C.rjit_record_exit_stack)
- end
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def save_pc_and_sp(pc, ctx, asm, reset_sp_offset: true)
- # Update pc (TODO: manage PC offset?)
- asm.comment("save PC#{' and SP' if ctx.sp_offset != 0} to CFP")
- asm.mov(:rax, pc) # rax = jit.pc
- asm.mov([CFP, C.rb_control_frame_t.offsetof(:pc)], :rax) # cfp->pc = rax
-
- # Update sp
- if ctx.sp_offset != 0
- asm.add(SP, C.VALUE.size * ctx.sp_offset) # sp += stack_size
- asm.mov([CFP, C.rb_control_frame_t.offsetof(:sp)], SP) # cfp->sp = sp
- if reset_sp_offset
- ctx.sp_offset = 0
- end
- end
- end
-
- def to_value(obj)
- GC_REFS << obj
- C.to_value(obj)
- end
-
- def iseq_lineno(iseq, pc)
- C.rb_iseq_line_no(iseq, (pc - iseq.body.iseq_encoded.to_i) / C.VALUE.size)
- rescue RangeError # bignum too big to convert into `unsigned long long' (RangeError)
- -1
- end
- end
-end
diff --git a/lib/ruby_vm/rjit/hooks.rb b/lib/ruby_vm/rjit/hooks.rb
deleted file mode 100644
index ea9d7bf5a8..0000000000
--- a/lib/ruby_vm/rjit/hooks.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-module RubyVM::RJIT
- module Hooks # :nodoc: all
- def self.on_bop_redefined(_redefined_flag, _bop)
- # C.rjit_cancel_all("BOP is redefined")
- end
-
- def self.on_cme_invalidate(cme)
- cme = C.rb_callable_method_entry_struct.new(cme)
- Invariants.on_cme_invalidate(cme)
- end
-
- def self.on_ractor_spawn
- # C.rjit_cancel_all("Ractor is spawned")
- end
-
- # Global constant changes like const_set
- def self.on_constant_state_changed(id)
- Invariants.on_constant_state_changed(id)
- end
-
- # ISEQ-specific constant invalidation
- def self.on_constant_ic_update(iseq, ic, insn_idx)
- iseq = C.rb_iseq_t.new(iseq)
- ic = C.IC.new(ic)
- Invariants.on_constant_ic_update(iseq, ic, insn_idx)
- end
-
- def self.on_tracing_invalidate_all(_new_iseq_events)
- Invariants.on_tracing_invalidate_all
- end
-
- def self.on_update_references
- Invariants.on_update_references
- end
- end
-end
diff --git a/lib/ruby_vm/rjit/insn_compiler.rb b/lib/ruby_vm/rjit/insn_compiler.rb
deleted file mode 100644
index f9450241c9..0000000000
--- a/lib/ruby_vm/rjit/insn_compiler.rb
+++ /dev/null
@@ -1,6002 +0,0 @@
-# frozen_string_literal: true
-module RubyVM::RJIT
- class InsnCompiler
- # struct rb_calling_info. Storing flags instead of ci.
- CallingInfo = Struct.new(:argc, :flags, :kwarg, :ci_addr, :send_shift, :block_handler) do
- def kw_splat = flags & C::VM_CALL_KW_SPLAT != 0
- end
-
- # @param ocb [CodeBlock]
- # @param exit_compiler [RubyVM::RJIT::ExitCompiler]
- def initialize(cb, ocb, exit_compiler)
- @ocb = ocb
- @exit_compiler = exit_compiler
-
- @cfunc_codegen_table = {}
- register_cfunc_codegen_funcs
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- # @param insn `RubyVM::RJIT::Instruction`
- def compile(jit, ctx, asm, insn)
- asm.incr_counter(:rjit_insns_count)
-
- stack = ctx.stack_size.times.map do |stack_idx|
- ctx.get_opnd_type(StackOpnd[ctx.stack_size - stack_idx - 1]).type
- end
- locals = jit.iseq.body.local_table_size.times.map do |local_idx|
- (ctx.local_types[local_idx] || Type::Unknown).type
- end
-
- insn_idx = format('%04d', (jit.pc.to_i - jit.iseq.body.iseq_encoded.to_i) / C.VALUE.size)
- asm.comment("Insn: #{insn_idx} #{insn.name} (stack: [#{stack.join(', ')}], locals: [#{locals.join(', ')}])")
-
- # 83/102
- case insn.name
- when :nop then nop(jit, ctx, asm)
- when :getlocal then getlocal(jit, ctx, asm)
- when :setlocal then setlocal(jit, ctx, asm)
- when :getblockparam then getblockparam(jit, ctx, asm)
- # setblockparam
- when :getblockparamproxy then getblockparamproxy(jit, ctx, asm)
- when :getspecial then getspecial(jit, ctx, asm)
- # setspecial
- when :getinstancevariable then getinstancevariable(jit, ctx, asm)
- when :setinstancevariable then setinstancevariable(jit, ctx, asm)
- when :getclassvariable then getclassvariable(jit, ctx, asm)
- when :setclassvariable then setclassvariable(jit, ctx, asm)
- when :opt_getconstant_path then opt_getconstant_path(jit, ctx, asm)
- when :getconstant then getconstant(jit, ctx, asm)
- # setconstant
- when :getglobal then getglobal(jit, ctx, asm)
- # setglobal
- when :putnil then putnil(jit, ctx, asm)
- when :putself then putself(jit, ctx, asm)
- when :putobject then putobject(jit, ctx, asm)
- when :putspecialobject then putspecialobject(jit, ctx, asm)
- when :putstring then putstring(jit, ctx, asm)
- when :putchilledstring then putchilledstring(jit, ctx, asm)
- when :concatstrings then concatstrings(jit, ctx, asm)
- when :anytostring then anytostring(jit, ctx, asm)
- when :toregexp then toregexp(jit, ctx, asm)
- when :intern then intern(jit, ctx, asm)
- when :newarray then newarray(jit, ctx, asm)
- # newarraykwsplat
- when :duparray then duparray(jit, ctx, asm)
- # duphash
- when :expandarray then expandarray(jit, ctx, asm)
- when :concatarray then concatarray(jit, ctx, asm)
- when :splatarray then splatarray(jit, ctx, asm)
- when :newhash then newhash(jit, ctx, asm)
- when :newrange then newrange(jit, ctx, asm)
- when :pop then pop(jit, ctx, asm)
- when :dup then dup(jit, ctx, asm)
- when :dupn then dupn(jit, ctx, asm)
- when :swap then swap(jit, ctx, asm)
- # opt_reverse
- when :topn then topn(jit, ctx, asm)
- when :setn then setn(jit, ctx, asm)
- when :adjuststack then adjuststack(jit, ctx, asm)
- when :defined then defined(jit, ctx, asm)
- when :definedivar then definedivar(jit, ctx, asm)
- # checkmatch
- when :checkkeyword then checkkeyword(jit, ctx, asm)
- # checktype
- # defineclass
- # definemethod
- # definesmethod
- when :send then send(jit, ctx, asm)
- when :opt_send_without_block then opt_send_without_block(jit, ctx, asm)
- when :objtostring then objtostring(jit, ctx, asm)
- when :opt_str_freeze then opt_str_freeze(jit, ctx, asm)
- when :opt_nil_p then opt_nil_p(jit, ctx, asm)
- # opt_str_uminus
- when :opt_newarray_send then opt_newarray_send(jit, ctx, asm)
- when :invokesuper then invokesuper(jit, ctx, asm)
- when :invokeblock then invokeblock(jit, ctx, asm)
- when :leave then leave(jit, ctx, asm)
- when :throw then throw(jit, ctx, asm)
- when :jump then jump(jit, ctx, asm)
- when :branchif then branchif(jit, ctx, asm)
- when :branchunless then branchunless(jit, ctx, asm)
- when :branchnil then branchnil(jit, ctx, asm)
- # once
- when :opt_case_dispatch then opt_case_dispatch(jit, ctx, asm)
- when :opt_plus then opt_plus(jit, ctx, asm)
- when :opt_minus then opt_minus(jit, ctx, asm)
- when :opt_mult then opt_mult(jit, ctx, asm)
- when :opt_div then opt_div(jit, ctx, asm)
- when :opt_mod then opt_mod(jit, ctx, asm)
- when :opt_eq then opt_eq(jit, ctx, asm)
- when :opt_neq then opt_neq(jit, ctx, asm)
- when :opt_lt then opt_lt(jit, ctx, asm)
- when :opt_le then opt_le(jit, ctx, asm)
- when :opt_gt then opt_gt(jit, ctx, asm)
- when :opt_ge then opt_ge(jit, ctx, asm)
- when :opt_ltlt then opt_ltlt(jit, ctx, asm)
- when :opt_and then opt_and(jit, ctx, asm)
- when :opt_or then opt_or(jit, ctx, asm)
- when :opt_aref then opt_aref(jit, ctx, asm)
- when :opt_aset then opt_aset(jit, ctx, asm)
- # opt_aset_with
- # opt_aref_with
- when :opt_length then opt_length(jit, ctx, asm)
- when :opt_size then opt_size(jit, ctx, asm)
- when :opt_empty_p then opt_empty_p(jit, ctx, asm)
- when :opt_succ then opt_succ(jit, ctx, asm)
- when :opt_not then opt_not(jit, ctx, asm)
- when :opt_regexpmatch2 then opt_regexpmatch2(jit, ctx, asm)
- # invokebuiltin
- when :opt_invokebuiltin_delegate then opt_invokebuiltin_delegate(jit, ctx, asm)
- when :opt_invokebuiltin_delegate_leave then opt_invokebuiltin_delegate_leave(jit, ctx, asm)
- when :getlocal_WC_0 then getlocal_WC_0(jit, ctx, asm)
- when :getlocal_WC_1 then getlocal_WC_1(jit, ctx, asm)
- when :setlocal_WC_0 then setlocal_WC_0(jit, ctx, asm)
- when :setlocal_WC_1 then setlocal_WC_1(jit, ctx, asm)
- when :putobject_INT2FIX_0_ then putobject_INT2FIX_0_(jit, ctx, asm)
- when :putobject_INT2FIX_1_ then putobject_INT2FIX_1_(jit, ctx, asm)
- else CantCompile
- end
- end
-
- private
-
- #
- # Insns
- #
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def nop(jit, ctx, asm)
- # Do nothing
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def getlocal(jit, ctx, asm)
- idx = jit.operand(0)
- level = jit.operand(1)
- jit_getlocal_generic(jit, ctx, asm, idx:, level:)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def getlocal_WC_0(jit, ctx, asm)
- idx = jit.operand(0)
- jit_getlocal_generic(jit, ctx, asm, idx:, level: 0)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def getlocal_WC_1(jit, ctx, asm)
- idx = jit.operand(0)
- jit_getlocal_generic(jit, ctx, asm, idx:, level: 1)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def setlocal(jit, ctx, asm)
- idx = jit.operand(0)
- level = jit.operand(1)
- jit_setlocal_generic(jit, ctx, asm, idx:, level:)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def setlocal_WC_0(jit, ctx, asm)
- idx = jit.operand(0)
- jit_setlocal_generic(jit, ctx, asm, idx:, level: 0)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def setlocal_WC_1(jit, ctx, asm)
- idx = jit.operand(0)
- jit_setlocal_generic(jit, ctx, asm, idx:, level: 1)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def getblockparam(jit, ctx, asm)
- # EP level
- level = jit.operand(1)
-
- # Save the PC and SP because we might allocate
- jit_prepare_routine_call(jit, ctx, asm)
-
- # A mirror of the interpreter code. Checking for the case
- # where it's pushing rb_block_param_proxy.
- side_exit = side_exit(jit, ctx)
-
- # Load environment pointer EP from CFP
- ep_reg = :rax
- jit_get_ep(asm, level, reg: ep_reg)
-
- # Bail when VM_ENV_FLAGS(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM) is non zero
- # FIXME: This is testing bits in the same place that the WB check is testing.
- # We should combine these at some point
- asm.test([ep_reg, C.VALUE.size * C::VM_ENV_DATA_INDEX_FLAGS], C::VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM)
-
- # If the frame flag has been modified, then the actual proc value is
- # already in the EP and we should just use the value.
- frame_flag_modified = asm.new_label('frame_flag_modified')
- asm.jnz(frame_flag_modified)
-
- # This instruction writes the block handler to the EP. If we need to
- # fire a write barrier for the write, then exit (we'll let the
- # interpreter handle it so it can fire the write barrier).
- # flags & VM_ENV_FLAG_WB_REQUIRED
- asm.test([ep_reg, C.VALUE.size * C::VM_ENV_DATA_INDEX_FLAGS], C::VM_ENV_FLAG_WB_REQUIRED)
-
- # if (flags & VM_ENV_FLAG_WB_REQUIRED) != 0
- asm.jnz(side_exit)
-
- # Convert the block handler in to a proc
- # call rb_vm_bh_to_procval(const rb_execution_context_t *ec, VALUE block_handler)
- asm.mov(C_ARGS[0], EC)
- # The block handler for the current frame
- # note, VM_ASSERT(VM_ENV_LOCAL_P(ep))
- asm.mov(C_ARGS[1], [ep_reg, C.VALUE.size * C::VM_ENV_DATA_INDEX_SPECVAL])
- asm.call(C.rb_vm_bh_to_procval)
-
- # Load environment pointer EP from CFP (again)
- ep_reg = :rcx
- jit_get_ep(asm, level, reg: ep_reg)
-
- # Write the value at the environment pointer
- idx = jit.operand(0)
- offs = -(C.VALUE.size * idx)
- asm.mov([ep_reg, offs], C_RET);
-
- # Set the frame modified flag
- asm.mov(:rax, [ep_reg, C.VALUE.size * C::VM_ENV_DATA_INDEX_FLAGS]) # flag_check
- asm.or(:rax, C::VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM) # modified_flag
- asm.mov([ep_reg, C.VALUE.size * C::VM_ENV_DATA_INDEX_FLAGS], :rax)
-
- asm.write_label(frame_flag_modified)
-
- # Push the proc on the stack
- stack_ret = ctx.stack_push(Type::Unknown)
- ep_reg = :rax
- jit_get_ep(asm, level, reg: ep_reg)
- asm.mov(:rax, [ep_reg, offs])
- asm.mov(stack_ret, :rax)
-
- KeepCompiling
- end
-
- # setblockparam
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def getblockparamproxy(jit, ctx, asm)
- # To get block_handler
- unless jit.at_current_insn?
- defer_compilation(jit, ctx, asm)
- return EndBlock
- end
-
- starting_context = ctx.dup # make a copy for use with jit_chain_guard
-
- # A mirror of the interpreter code. Checking for the case
- # where it's pushing rb_block_param_proxy.
- side_exit = side_exit(jit, ctx)
-
- # EP level
- level = jit.operand(1)
-
- # Peek at the block handler so we can check whether it's nil
- comptime_handler = jit.peek_at_block_handler(level)
-
- # When a block handler is present, it should always be a GC-guarded
- # pointer (VM_BH_ISEQ_BLOCK_P)
- if comptime_handler != 0 && comptime_handler & 0x3 != 0x1
- asm.incr_counter(:getblockpp_not_gc_guarded)
- return CantCompile
- end
-
- # Load environment pointer EP from CFP
- ep_reg = :rax
- jit_get_ep(asm, level, reg: ep_reg)
-
- # Bail when VM_ENV_FLAGS(ep, VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM) is non zero
- asm.test([ep_reg, C.VALUE.size * C::VM_ENV_DATA_INDEX_FLAGS], C::VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM)
- asm.jnz(counted_exit(side_exit, :getblockpp_block_param_modified))
-
- # Load the block handler for the current frame
- # note, VM_ASSERT(VM_ENV_LOCAL_P(ep))
- block_handler = :rax
- asm.mov(block_handler, [ep_reg, C.VALUE.size * C::VM_ENV_DATA_INDEX_SPECVAL])
-
- # Specialize compilation for the case where no block handler is present
- if comptime_handler == 0
- # Bail if there is a block handler
- asm.cmp(block_handler, 0)
-
- jit_chain_guard(:jnz, jit, starting_context, asm, counted_exit(side_exit, :getblockpp_block_handler_none))
-
- putobject(jit, ctx, asm, val: Qnil)
- else
- # Block handler is a tagged pointer. Look at the tag. 0x03 is from VM_BH_ISEQ_BLOCK_P().
- asm.and(block_handler, 0x3)
-
- # Bail unless VM_BH_ISEQ_BLOCK_P(bh). This also checks for null.
- asm.cmp(block_handler, 0x1)
-
- jit_chain_guard(:jnz, jit, starting_context, asm, counted_exit(side_exit, :getblockpp_not_iseq_block))
-
- # Push rb_block_param_proxy. It's a root, so no need to use jit_mov_gc_ptr.
- top = ctx.stack_push(Type::BlockParamProxy)
- asm.mov(:rax, C.rb_block_param_proxy)
- asm.mov(top, :rax)
- end
-
- jump_to_next_insn(jit, ctx, asm)
-
- EndBlock
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def getspecial(jit, ctx, asm)
- # 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.jit_get_arg(0);
- rtype = jit.operand(1)
-
- if rtype == 0
- # not yet implemented
- return CantCompile;
- elsif rtype & 0x01 != 0
- # Fetch a "special" backref based on a char encoded by shifting by 1
-
- # Can raise if matchdata uninitialized
- jit_prepare_routine_call(jit, ctx, asm)
-
- # call rb_backref_get()
- asm.comment('rb_backref_get')
- asm.call(C.rb_backref_get)
-
- asm.mov(C_ARGS[0], C_RET) # backref
- case [rtype >> 1].pack('c')
- in ?&
- asm.comment("rb_reg_last_match")
- asm.call(C.rb_reg_last_match)
- in ?`
- asm.comment("rb_reg_match_pre")
- asm.call(C.rb_reg_match_pre)
- in ?'
- asm.comment("rb_reg_match_post")
- asm.call(C.rb_reg_match_post)
- in ?+
- asm.comment("rb_reg_match_last")
- asm.call(C.rb_reg_match_last)
- end
-
- stack_ret = ctx.stack_push(Type::Unknown)
- asm.mov(stack_ret, C_RET)
-
- KeepCompiling
- 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, asm)
-
- # call rb_backref_get()
- asm.comment('rb_backref_get')
- asm.call(C.rb_backref_get)
-
- # rb_reg_nth_match((int)(type >> 1), backref);
- asm.comment('rb_reg_nth_match')
- asm.mov(C_ARGS[0], rtype >> 1)
- asm.mov(C_ARGS[1], C_RET) # backref
- asm.call(C.rb_reg_nth_match)
-
- stack_ret = ctx.stack_push(Type::Unknown)
- asm.mov(stack_ret, C_RET)
-
- KeepCompiling
- end
- end
-
- # setspecial
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def getinstancevariable(jit, ctx, asm)
- # Specialize on a compile-time receiver, and split a block for chain guards
- unless jit.at_current_insn?
- defer_compilation(jit, ctx, asm)
- return EndBlock
- end
-
- id = jit.operand(0)
- comptime_obj = jit.peek_at_self
-
- jit_getivar(jit, ctx, asm, comptime_obj, id, nil, SelfOpnd)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def setinstancevariable(jit, ctx, asm)
- starting_context = ctx.dup # make a copy for use with jit_chain_guard
-
- # Defer compilation so we can specialize on a runtime `self`
- unless jit.at_current_insn?
- defer_compilation(jit, ctx, asm)
- return EndBlock
- end
-
- ivar_name = jit.operand(0)
- comptime_receiver = jit.peek_at_self
-
- # If the comptime receiver is frozen, writing an IV will raise an exception
- # and we don't want to JIT code to deal with that situation.
- if C.rb_obj_frozen_p(comptime_receiver)
- asm.incr_counter(:setivar_frozen)
- return CantCompile
- end
-
- # Check if the comptime receiver is a T_OBJECT
- receiver_t_object = C::BUILTIN_TYPE(comptime_receiver) == C::T_OBJECT
-
- # If the receiver isn't a T_OBJECT, or uses a custom allocator,
- # then just write out the IV write as a function call.
- # too-complex shapes can't use index access, so we use rb_ivar_get for them too.
- if !receiver_t_object || shape_too_complex?(comptime_receiver) || ctx.chain_depth >= 10
- asm.comment('call rb_vm_setinstancevariable')
-
- ic = jit.operand(1)
-
- # The function could raise exceptions.
- # Note that this modifies REG_SP, which is why we do it first
- jit_prepare_routine_call(jit, ctx, asm)
-
- # Get the operands from the stack
- val_opnd = ctx.stack_pop(1)
-
- # Call rb_vm_setinstancevariable(iseq, obj, id, val, ic);
- asm.mov(:rdi, jit.iseq.to_i)
- asm.mov(:rsi, [CFP, C.rb_control_frame_t.offsetof(:self)])
- asm.mov(:rdx, ivar_name)
- asm.mov(:rcx, val_opnd)
- asm.mov(:r8, ic)
- asm.call(C.rb_vm_setinstancevariable)
- else
- # Get the iv index
- shape_id = C.rb_shape_get_shape_id(comptime_receiver)
- ivar_index = C.rb_shape_get_iv_index(shape_id, ivar_name)
-
- # Get the receiver
- asm.mov(:rax, [CFP, C.rb_control_frame_t.offsetof(:self)])
-
- # Generate a side exit
- side_exit = side_exit(jit, ctx)
-
- # Upgrade type
- guard_object_is_heap(jit, ctx, asm, :rax, SelfOpnd, :setivar_not_heap)
-
- asm.comment('guard shape')
- asm.cmp(DwordPtr[:rax, C.rb_shape_id_offset], shape_id)
- megamorphic_side_exit = counted_exit(side_exit, :setivar_megamorphic)
- jit_chain_guard(:jne, jit, starting_context, asm, megamorphic_side_exit)
-
- # If we don't have an instance variable index, then we need to
- # transition out of the current shape.
- if ivar_index.nil?
- shape = C.rb_shape_get_shape_by_id(shape_id)
-
- current_capacity = shape.capacity
- dest_shape = C.rb_shape_get_next(shape, comptime_receiver, ivar_name)
- new_shape_id = C.rb_shape_id(dest_shape)
-
- if new_shape_id == C::OBJ_TOO_COMPLEX_SHAPE_ID
- asm.incr_counter(:setivar_too_complex)
- return CantCompile
- end
-
- ivar_index = shape.next_iv_index
-
- # If the new shape has a different capacity, we need to
- # reallocate the object.
- needs_extension = dest_shape.capacity != shape.capacity
-
- if needs_extension
- # Generate the C call so that runtime code will increase
- # the capacity and set the buffer.
- asm.mov(C_ARGS[0], :rax)
- asm.mov(C_ARGS[1], current_capacity)
- asm.mov(C_ARGS[2], dest_shape.capacity)
- asm.call(C.rb_ensure_iv_list_size)
-
- # Load the receiver again after the function call
- asm.mov(:rax, [CFP, C.rb_control_frame_t.offsetof(:self)])
- end
-
- write_val = ctx.stack_pop(1)
- jit_write_iv(asm, comptime_receiver, :rax, :rcx, ivar_index, write_val, needs_extension)
-
- # Store the new shape
- asm.comment('write shape')
- asm.mov(:rax, [CFP, C.rb_control_frame_t.offsetof(:self)]) # reload after jit_write_iv
- asm.mov(DwordPtr[:rax, C.rb_shape_id_offset], new_shape_id)
- else
- # If the iv index already exists, then we don't need to
- # transition to a new shape. The reason is because we find
- # the iv index by searching up the shape tree. If we've
- # made the transition already, then there's no reason to
- # update the shape on the object. Just set the IV.
- write_val = ctx.stack_pop(1)
- jit_write_iv(asm, comptime_receiver, :rax, :rcx, ivar_index, write_val, false)
- end
-
- skip_wb = asm.new_label('skip_wb')
- # If the value we're writing is an immediate, we don't need to WB
- asm.test(write_val, C::RUBY_IMMEDIATE_MASK)
- asm.jnz(skip_wb)
-
- # If the value we're writing is nil or false, we don't need to WB
- asm.cmp(write_val, Qnil)
- asm.jbe(skip_wb)
-
- asm.comment('write barrier')
- asm.mov(C_ARGS[0], [CFP, C.rb_control_frame_t.offsetof(:self)]) # reload after jit_write_iv
- asm.mov(C_ARGS[1], write_val)
- asm.call(C.rb_gc_writebarrier)
-
- asm.write_label(skip_wb)
- end
-
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def getclassvariable(jit, ctx, asm)
- # rb_vm_getclassvariable can raise exceptions.
- jit_prepare_routine_call(jit, ctx, asm)
-
- asm.mov(C_ARGS[0], [CFP, C.rb_control_frame_t.offsetof(:iseq)])
- asm.mov(C_ARGS[1], CFP)
- asm.mov(C_ARGS[2], jit.operand(0))
- asm.mov(C_ARGS[3], jit.operand(1))
- asm.call(C.rb_vm_getclassvariable)
-
- top = ctx.stack_push(Type::Unknown)
- asm.mov(top, C_RET)
-
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def setclassvariable(jit, ctx, asm)
- # rb_vm_setclassvariable can raise exceptions.
- jit_prepare_routine_call(jit, ctx, asm)
-
- asm.mov(C_ARGS[0], [CFP, C.rb_control_frame_t.offsetof(:iseq)])
- asm.mov(C_ARGS[1], CFP)
- asm.mov(C_ARGS[2], jit.operand(0))
- asm.mov(C_ARGS[3], ctx.stack_pop(1))
- asm.mov(C_ARGS[4], jit.operand(1))
- asm.call(C.rb_vm_setclassvariable)
-
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_getconstant_path(jit, ctx, asm)
- # Cut the block for invalidation
- unless jit.at_current_insn?
- defer_compilation(jit, ctx, asm)
- return EndBlock
- end
-
- ic = C.iseq_inline_constant_cache.new(jit.operand(0))
- idlist = ic.segments
-
- # Make sure there is an exit for this block as the interpreter might want
- # to invalidate this block from rb_rjit_constant_ic_update().
- # For now, we always take an entry exit even if it was a side exit.
- Invariants.ensure_block_entry_exit(jit, cause: 'opt_getconstant_path')
-
- # See vm_ic_hit_p(). The same conditions are checked in yjit_constant_ic_update().
- ice = ic.entry
- if ice.nil?
- # In this case, leave a block that unconditionally side exits
- # for the interpreter to invalidate.
- asm.incr_counter(:optgetconst_not_cached)
- return CantCompile
- end
-
- if ice.ic_cref # with cref
- # Cache is keyed on a certain lexical scope. Use the interpreter's cache.
- side_exit = side_exit(jit, ctx)
-
- # Call function to verify the cache. It doesn't allocate or call methods.
- asm.mov(C_ARGS[0], ic.to_i)
- asm.mov(C_ARGS[1], [CFP, C.rb_control_frame_t.offsetof(:ep)])
- asm.call(C.rb_vm_ic_hit_p)
-
- # Check the result. SysV only specifies one byte for _Bool return values,
- # so it's important we only check one bit to ignore the higher bits in the register.
- asm.test(C_RET, 1)
- asm.jz(counted_exit(side_exit, :optgetconst_cache_miss))
-
- asm.mov(:rax, ic.to_i) # inline_cache
- asm.mov(:rax, [:rax, C.iseq_inline_constant_cache.offsetof(:entry)]) # ic_entry
- asm.mov(:rax, [:rax, C.iseq_inline_constant_cache_entry.offsetof(:value)]) # ic_entry_val
-
- # Push ic->entry->value
- stack_top = ctx.stack_push(Type::Unknown)
- asm.mov(stack_top, :rax)
- else # without cref
- # TODO: implement this
- # Optimize for single ractor mode.
- # if !assume_single_ractor_mode(jit, ocb)
- # return CantCompile
- # end
-
- # Invalidate output code on any constant writes associated with
- # constants referenced within the current block.
- Invariants.assume_stable_constant_names(jit, idlist)
-
- putobject(jit, ctx, asm, val: ice.value)
- end
-
- jump_to_next_insn(jit, ctx, asm)
- EndBlock
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def getconstant(jit, ctx, asm)
- id = jit.operand(0)
-
- # vm_get_ev_const can raise exceptions.
- jit_prepare_routine_call(jit, ctx, asm)
-
- allow_nil_opnd = ctx.stack_pop(1)
- klass_opnd = ctx.stack_pop(1)
-
- asm.mov(C_ARGS[0], EC)
- asm.mov(C_ARGS[1], klass_opnd)
- asm.mov(C_ARGS[2], id)
- asm.mov(C_ARGS[3], allow_nil_opnd)
- asm.call(C.rb_vm_get_ev_const)
-
- top = ctx.stack_push(Type::Unknown)
- asm.mov(top, C_RET)
-
- KeepCompiling
- end
-
- # setconstant
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def getglobal(jit, ctx, asm)
- gid = jit.operand(0)
-
- # Save the PC and SP because we might make a Ruby call for warning
- jit_prepare_routine_call(jit, ctx, asm)
-
- asm.mov(C_ARGS[0], gid)
- asm.call(C.rb_gvar_get)
-
- top = ctx.stack_push(Type::Unknown)
- asm.mov(top, C_RET)
-
- KeepCompiling
- end
-
- # setglobal
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def putnil(jit, ctx, asm)
- putobject(jit, ctx, asm, val: Qnil)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def putself(jit, ctx, asm)
- stack_top = ctx.stack_push_self
- asm.mov(:rax, [CFP, C.rb_control_frame_t.offsetof(:self)])
- asm.mov(stack_top, :rax)
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def putobject(jit, ctx, asm, val: jit.operand(0))
- # Push it to the stack
- val_type = Type.from(C.to_ruby(val))
- stack_top = ctx.stack_push(val_type)
- if asm.imm32?(val)
- asm.mov(stack_top, val)
- else # 64-bit immediates can't be directly written to memory
- asm.mov(:rax, val)
- asm.mov(stack_top, :rax)
- end
-
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def putspecialobject(jit, ctx, asm)
- object_type = jit.operand(0)
- if object_type == C::VM_SPECIAL_OBJECT_VMCORE
- stack_top = ctx.stack_push(Type::UnknownHeap)
- asm.mov(:rax, C.rb_mRubyVMFrozenCore)
- asm.mov(stack_top, :rax)
- KeepCompiling
- else
- # TODO: implement for VM_SPECIAL_OBJECT_CBASE and
- # VM_SPECIAL_OBJECT_CONST_BASE
- CantCompile
- end
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def putstring(jit, ctx, asm)
- put_val = jit.operand(0, ruby: true)
-
- # Save the PC and SP because the callee will allocate
- jit_prepare_routine_call(jit, ctx, asm)
-
- asm.mov(C_ARGS[0], EC)
- asm.mov(C_ARGS[1], to_value(put_val))
- asm.mov(C_ARGS[2], 0)
- asm.call(C.rb_ec_str_resurrect)
-
- stack_top = ctx.stack_push(Type::TString)
- asm.mov(stack_top, C_RET)
-
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def putchilledstring(jit, ctx, asm)
- put_val = jit.operand(0, ruby: true)
-
- # Save the PC and SP because the callee will allocate
- jit_prepare_routine_call(jit, ctx, asm)
-
- asm.mov(C_ARGS[0], EC)
- asm.mov(C_ARGS[1], to_value(put_val))
- asm.mov(C_ARGS[2], 1)
- asm.call(C.rb_ec_str_resurrect)
-
- stack_top = ctx.stack_push(Type::TString)
- asm.mov(stack_top, C_RET)
-
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def concatstrings(jit, ctx, asm)
- n = jit.operand(0)
-
- # Save the PC and SP because we are allocating
- jit_prepare_routine_call(jit, ctx, asm)
-
- asm.lea(:rax, ctx.sp_opnd(-C.VALUE.size * n))
-
- # call rb_str_concat_literals(size_t n, const VALUE *strings);
- asm.mov(C_ARGS[0], n)
- asm.mov(C_ARGS[1], :rax)
- asm.call(C.rb_str_concat_literals)
-
- ctx.stack_pop(n)
- stack_ret = ctx.stack_push(Type::TString)
- asm.mov(stack_ret, C_RET)
-
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def anytostring(jit, ctx, asm)
- # Save the PC and SP since we might call #to_s
- jit_prepare_routine_call(jit, ctx, asm)
-
- str = ctx.stack_pop(1)
- val = ctx.stack_pop(1)
-
- asm.mov(C_ARGS[0], str)
- asm.mov(C_ARGS[1], val)
- asm.call(C.rb_obj_as_string_result)
-
- # Push the return value
- stack_ret = ctx.stack_push(Type::TString)
- asm.mov(stack_ret, C_RET)
-
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def toregexp(jit, ctx, asm)
- opt = jit.operand(0, signed: true)
- cnt = jit.operand(1)
-
- # Save the PC and SP because this allocates an object and could
- # raise an exception.
- jit_prepare_routine_call(jit, ctx, asm)
-
- asm.lea(:rax, ctx.sp_opnd(-C.VALUE.size * cnt)) # values_ptr
- ctx.stack_pop(cnt)
-
- asm.mov(C_ARGS[0], 0)
- asm.mov(C_ARGS[1], cnt)
- asm.mov(C_ARGS[2], :rax) # values_ptr
- asm.call(C.rb_ary_tmp_new_from_values)
-
- # Save the array so we can clear it later
- asm.push(C_RET)
- asm.push(C_RET) # Alignment
-
- asm.mov(C_ARGS[0], C_RET)
- asm.mov(C_ARGS[1], opt)
- asm.call(C.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
- asm.pop(:rcx) # Alignment
- asm.pop(:rcx) # ary
-
- # The value we want to push on the stack is in RAX right now
- stack_ret = ctx.stack_push(Type::UnknownHeap)
- asm.mov(stack_ret, C_RET)
-
- # Clear the temp array.
- asm.mov(C_ARGS[0], :rcx) # ary
- asm.call(C.rb_ary_clear)
-
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def intern(jit, ctx, asm)
- # Save the PC and SP because we might allocate
- jit_prepare_routine_call(jit, ctx, asm);
-
- str = ctx.stack_pop(1)
- asm.mov(C_ARGS[0], str)
- asm.call(C.rb_str_intern)
-
- # Push the return value
- stack_ret = ctx.stack_push(Type::Unknown)
- asm.mov(stack_ret, C_RET)
-
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def newarray(jit, ctx, asm)
- n = jit.operand(0)
-
- # Save the PC and SP because we are allocating
- jit_prepare_routine_call(jit, ctx, asm)
-
- # If n is 0, then elts is never going to be read, so we can just pass null
- if n == 0
- values_ptr = 0
- else
- asm.comment('load pointer to array elts')
- offset_magnitude = C.VALUE.size * n
- values_opnd = ctx.sp_opnd(-(offset_magnitude))
- asm.lea(:rax, values_opnd)
- values_ptr = :rax
- end
-
- # call rb_ec_ary_new_from_values(struct rb_execution_context_struct *ec, long n, const VALUE *elts);
- asm.mov(C_ARGS[0], EC)
- asm.mov(C_ARGS[1], n)
- asm.mov(C_ARGS[2], values_ptr)
- asm.call(C.rb_ec_ary_new_from_values)
-
- ctx.stack_pop(n)
- stack_ret = ctx.stack_push(Type::TArray)
- asm.mov(stack_ret, C_RET)
-
- KeepCompiling
- end
-
- # newarraykwsplat
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def duparray(jit, ctx, asm)
- ary = jit.operand(0)
-
- # Save the PC and SP because we are allocating
- jit_prepare_routine_call(jit, ctx, asm)
-
- # call rb_ary_resurrect(VALUE ary);
- asm.comment('call rb_ary_resurrect')
- asm.mov(C_ARGS[0], ary)
- asm.call(C.rb_ary_resurrect)
-
- stack_ret = ctx.stack_push(Type::TArray)
- asm.mov(stack_ret, C_RET)
-
- KeepCompiling
- end
-
- # duphash
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def expandarray(jit, ctx, asm)
- # Both arguments are rb_num_t which is unsigned
- num = jit.operand(0)
- flag = jit.operand(1)
-
- # If this instruction has the splat flag, then bail out.
- if flag & 0x01 != 0
- asm.incr_counter(:expandarray_splat)
- return CantCompile
- end
-
- # If this instruction has the postarg flag, then bail out.
- if flag & 0x02 != 0
- asm.incr_counter(:expandarray_postarg)
- return CantCompile
- end
-
- side_exit = side_exit(jit, ctx)
-
- array_opnd = ctx.stack_opnd(0)
- array_stack_opnd = StackOpnd[0]
-
- # num is the number of requested values. If there aren't enough in the
- # array then we're going to push on nils.
- if ctx.get_opnd_type(array_stack_opnd) == Type::Nil
- ctx.stack_pop(1) # pop after using the type info
- # special case for a, b = nil pattern
- # push N nils onto the stack
- num.times do
- push_opnd = ctx.stack_push(Type::Nil)
- asm.mov(push_opnd, Qnil)
- end
- return KeepCompiling
- end
-
- # Move the array from the stack and check that it's an array.
- asm.mov(:rax, array_opnd)
- guard_object_is_array(jit, ctx, asm, :rax, :rcx, array_stack_opnd, :expandarray_not_array)
- ctx.stack_pop(1) # pop after using the type info
-
- # If we don't actually want any values, then just return.
- if num == 0
- return KeepCompiling
- end
-
- jit_array_len(asm, :rax, :rcx)
-
- # Only handle the case where the number of values in the array is greater
- # than or equal to the number of values requested.
- asm.cmp(:rcx, num)
- asm.jl(counted_exit(side_exit, :expandarray_rhs_too_small))
-
- # Conditionally load the address of the heap array into REG1.
- # (struct RArray *)(obj)->as.heap.ptr
- #asm.mov(:rax, array_opnd)
- asm.mov(:rcx, [:rax, C.RBasic.offsetof(:flags)])
- asm.test(:rcx, C::RARRAY_EMBED_FLAG);
- asm.mov(:rcx, [:rax, C.RArray.offsetof(:as, :heap, :ptr)])
-
- # Load the address of the embedded array into REG1.
- # (struct RArray *)(obj)->as.ary
- asm.lea(:rax, [:rax, C.RArray.offsetof(:as, :ary)])
-
- asm.cmovnz(:rcx, :rax)
-
- # Loop backward through the array and push each element onto the stack.
- (num - 1).downto(0).each do |i|
- top = ctx.stack_push(Type::Unknown)
- asm.mov(:rax, [:rcx, i * C.VALUE.size])
- asm.mov(top, :rax)
- end
-
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def concatarray(jit, ctx, asm)
- # 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, asm)
-
- # Get the operands from the stack
- ary2st_opnd = ctx.stack_pop(1)
- ary1_opnd = ctx.stack_pop(1)
-
- # Call rb_vm_concat_array(ary1, ary2st)
- asm.mov(C_ARGS[0], ary1_opnd)
- asm.mov(C_ARGS[1], ary2st_opnd)
- asm.call(C.rb_vm_concat_array)
-
- stack_ret = ctx.stack_push(Type::TArray)
- asm.mov(stack_ret, C_RET)
-
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def splatarray(jit, ctx, asm)
- flag = jit.operand(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, asm)
-
- # Get the operands from the stack
- ary_opnd = ctx.stack_pop(1)
-
- # Call rb_vm_splat_array(flag, ary)
- asm.mov(C_ARGS[0], flag)
- asm.mov(C_ARGS[1], ary_opnd)
- asm.call(C.rb_vm_splat_array)
-
- stack_ret = ctx.stack_push(Type::TArray)
- asm.mov(stack_ret, C_RET)
-
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def newhash(jit, ctx, asm)
- num = jit.operand(0)
-
- # Save the PC and SP because we are allocating
- jit_prepare_routine_call(jit, ctx, asm)
-
- if num != 0
- # val = rb_hash_new_with_size(num / 2);
- asm.mov(C_ARGS[0], num / 2)
- asm.call(C.rb_hash_new_with_size)
-
- # Save the allocated hash as we want to push it after insertion
- asm.push(C_RET)
- asm.push(C_RET) # x86 alignment
-
- # Get a pointer to the values to insert into the hash
- asm.lea(:rcx, ctx.stack_opnd(num - 1))
-
- # rb_hash_bulk_insert(num, STACK_ADDR_FROM_TOP(num), val);
- asm.mov(C_ARGS[0], num)
- asm.mov(C_ARGS[1], :rcx)
- asm.mov(C_ARGS[2], C_RET)
- asm.call(C.rb_hash_bulk_insert)
-
- asm.pop(:rax)
- asm.pop(:rax)
-
- ctx.stack_pop(num)
- stack_ret = ctx.stack_push(Type::Hash)
- asm.mov(stack_ret, :rax)
- else
- # val = rb_hash_new();
- asm.call(C.rb_hash_new)
- stack_ret = ctx.stack_push(Type::Hash)
- asm.mov(stack_ret, C_RET)
- end
-
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def newrange(jit, ctx, asm)
- flag = jit.operand(0)
-
- # rb_range_new() allocates and can raise
- jit_prepare_routine_call(jit, ctx, asm)
-
- # val = rb_range_new(low, high, (int)flag);
- asm.mov(C_ARGS[0], ctx.stack_opnd(1))
- asm.mov(C_ARGS[1], ctx.stack_opnd(0))
- asm.mov(C_ARGS[2], flag)
- asm.call(C.rb_range_new)
-
- ctx.stack_pop(2)
- stack_ret = ctx.stack_push(Type::UnknownHeap)
- asm.mov(stack_ret, C_RET)
-
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def pop(jit, ctx, asm)
- ctx.stack_pop
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def dup(jit, ctx, asm)
- dup_val = ctx.stack_opnd(0)
- mapping, tmp_type = ctx.get_opnd_mapping(StackOpnd[0])
-
- loc0 = ctx.stack_push_mapping([mapping, tmp_type])
- asm.mov(:rax, dup_val)
- asm.mov(loc0, :rax)
-
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def dupn(jit, ctx, asm)
- n = jit.operand(0)
-
- # In practice, seems to be only used for n==2
- if n != 2
- return CantCompile
- end
-
- opnd1 = ctx.stack_opnd(1)
- opnd0 = ctx.stack_opnd(0)
-
- mapping1 = ctx.get_opnd_mapping(StackOpnd[1])
- mapping0 = ctx.get_opnd_mapping(StackOpnd[0])
-
- dst1 = ctx.stack_push_mapping(mapping1)
- asm.mov(:rax, opnd1)
- asm.mov(dst1, :rax)
-
- dst0 = ctx.stack_push_mapping(mapping0)
- asm.mov(:rax, opnd0)
- asm.mov(dst0, :rax)
-
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def swap(jit, ctx, asm)
- stack_swap(jit, ctx, asm, 0, 1)
- KeepCompiling
- end
-
- # opt_reverse
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def topn(jit, ctx, asm)
- n = jit.operand(0)
-
- top_n_val = ctx.stack_opnd(n)
- mapping = ctx.get_opnd_mapping(StackOpnd[n])
- loc0 = ctx.stack_push_mapping(mapping)
- asm.mov(:rax, top_n_val)
- asm.mov(loc0, :rax)
-
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def setn(jit, ctx, asm)
- n = jit.operand(0)
-
- top_val = ctx.stack_pop(0)
- dst_opnd = ctx.stack_opnd(n)
- asm.mov(:rax, top_val)
- asm.mov(dst_opnd, :rax)
-
- mapping = ctx.get_opnd_mapping(StackOpnd[0])
- ctx.set_opnd_mapping(StackOpnd[n], mapping)
-
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def adjuststack(jit, ctx, asm)
- n = jit.operand(0)
- ctx.stack_pop(n)
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def defined(jit, ctx, asm)
- op_type = jit.operand(0)
- obj = jit.operand(1, ruby: true)
- pushval = jit.operand(2, ruby: true)
-
- # 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, asm)
-
- # Get the operands from the stack
- v_opnd = ctx.stack_pop(1)
-
- # Call vm_defined(ec, reg_cfp, op_type, obj, v)
- asm.mov(C_ARGS[0], EC)
- asm.mov(C_ARGS[1], CFP)
- asm.mov(C_ARGS[2], op_type)
- asm.mov(C_ARGS[3], to_value(obj))
- asm.mov(C_ARGS[4], v_opnd)
- asm.call(C.rb_vm_defined)
-
- asm.test(C_RET, 255)
- asm.mov(:rax, Qnil)
- asm.mov(:rcx, to_value(pushval))
- asm.cmovnz(:rax, :rcx)
-
- # Push the return value onto the stack
- out_type = if C::SPECIAL_CONST_P(pushval)
- Type::UnknownImm
- else
- Type::Unknown
- end
- stack_ret = ctx.stack_push(out_type)
- asm.mov(stack_ret, :rax)
-
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def definedivar(jit, ctx, asm)
- # Defer compilation so we can specialize base on a runtime receiver
- unless jit.at_current_insn?
- defer_compilation(jit, ctx, asm)
- return EndBlock
- end
-
- ivar_name = jit.operand(0)
- # Value that will be pushed on the stack if the ivar is defined. In practice this is always the
- # string "instance-variable". If the ivar is not defined, nil will be pushed instead.
- pushval = jit.operand(2, ruby: true)
-
- # Get the receiver
- recv = :rcx
- asm.mov(recv, [CFP, C.rb_control_frame_t.offsetof(:self)])
-
- # Specialize base on compile time values
- comptime_receiver = jit.peek_at_self
-
- if shape_too_complex?(comptime_receiver)
- # Fall back to calling rb_ivar_defined
-
- # 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, asm) # clobbers :rax
-
- # Call rb_ivar_defined(recv, ivar_name)
- asm.mov(C_ARGS[0], recv)
- asm.mov(C_ARGS[1], ivar_name)
- asm.call(C.rb_ivar_defined)
-
- # if (rb_ivar_defined(recv, ivar_name)) {
- # val = pushval;
- # }
- asm.test(C_RET, 255)
- asm.mov(:rax, Qnil)
- asm.mov(:rcx, to_value(pushval))
- asm.cmovnz(:rax, :rcx)
-
- # Push the return value onto the stack
- out_type = C::SPECIAL_CONST_P(pushval) ? Type::UnknownImm : Type::Unknown
- stack_ret = ctx.stack_push(out_type)
- asm.mov(stack_ret, :rax)
-
- return KeepCompiling
- end
-
- shape_id = C.rb_shape_get_shape_id(comptime_receiver)
- ivar_exists = C.rb_shape_get_iv_index(shape_id, ivar_name)
-
- side_exit = side_exit(jit, ctx)
-
- # Guard heap object (recv_opnd must be used before stack_pop)
- guard_object_is_heap(jit, ctx, asm, recv, SelfOpnd)
-
- shape_opnd = DwordPtr[recv, C.rb_shape_id_offset]
-
- asm.comment('guard shape')
- asm.cmp(shape_opnd, shape_id)
- jit_chain_guard(:jne, jit, ctx, asm, side_exit)
-
- result = ivar_exists ? C.to_value(pushval) : Qnil
- putobject(jit, ctx, asm, val: result)
-
- # Jump to next instruction. This allows guard chains to share the same successor.
- jump_to_next_insn(jit, ctx, asm)
-
- return EndBlock
- end
-
- # checkmatch
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def checkkeyword(jit, ctx, asm)
- # 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 CantCompile
- end
-
- # The EP offset to the undefined bits local
- bits_offset = jit.operand(0)
-
- # The index of the keyword we want to check
- index = jit.operand(1, signed: true)
-
- # Load environment pointer EP
- ep_reg = :rax
- jit_get_ep(asm, 0, reg: ep_reg)
-
- # VALUE kw_bits = *(ep - bits)
- bits_opnd = [ep_reg, C.VALUE.size * -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
- bit_test = 0x01 << (index + 1)
- asm.test(bits_opnd, bit_test)
- asm.mov(:rax, Qfalse)
- asm.mov(:rcx, Qtrue)
- asm.cmovz(:rax, :rcx)
-
- stack_ret = ctx.stack_push(Type::UnknownImm)
- asm.mov(stack_ret, :rax)
-
- KeepCompiling
- end
-
- # checktype
- # defineclass
- # definemethod
- # definesmethod
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def send(jit, ctx, asm)
- # Specialize on a compile-time receiver, and split a block for chain guards
- unless jit.at_current_insn?
- defer_compilation(jit, ctx, asm)
- return EndBlock
- end
-
- cd = C.rb_call_data.new(jit.operand(0))
- blockiseq = jit.operand(1)
-
- # calling->ci
- mid = C.vm_ci_mid(cd.ci)
- calling = build_calling(ci: cd.ci, block_handler: blockiseq)
-
- # vm_sendish
- cme, comptime_recv_klass = jit_search_method(jit, ctx, asm, mid, calling)
- if cme == CantCompile
- return CantCompile
- end
- jit_call_general(jit, ctx, asm, mid, calling, cme, comptime_recv_klass)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_send_without_block(jit, ctx, asm, cd: C.rb_call_data.new(jit.operand(0)))
- # Specialize on a compile-time receiver, and split a block for chain guards
- unless jit.at_current_insn?
- defer_compilation(jit, ctx, asm)
- return EndBlock
- end
-
- # calling->ci
- mid = C.vm_ci_mid(cd.ci)
- calling = build_calling(ci: cd.ci, block_handler: C::VM_BLOCK_HANDLER_NONE)
-
- # vm_sendish
- cme, comptime_recv_klass = jit_search_method(jit, ctx, asm, mid, calling)
- if cme == CantCompile
- return CantCompile
- end
- jit_call_general(jit, ctx, asm, mid, calling, cme, comptime_recv_klass)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def objtostring(jit, ctx, asm)
- unless jit.at_current_insn?
- defer_compilation(jit, ctx, asm)
- return EndBlock
- end
-
- recv = ctx.stack_opnd(0)
- comptime_recv = jit.peek_at_stack(0)
-
- if C.RB_TYPE_P(comptime_recv, C::RUBY_T_STRING)
- side_exit = side_exit(jit, ctx)
-
- jit_guard_known_klass(jit, ctx, asm, C.rb_class_of(comptime_recv), recv, StackOpnd[0], comptime_recv, side_exit)
- # No work needed. The string value is already on the top of the stack.
- KeepCompiling
- else
- cd = C.rb_call_data.new(jit.operand(0))
- opt_send_without_block(jit, ctx, asm, cd:)
- end
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_str_freeze(jit, ctx, asm)
- unless Invariants.assume_bop_not_redefined(jit, C::STRING_REDEFINED_OP_FLAG, C::BOP_FREEZE)
- return CantCompile;
- end
-
- str = jit.operand(0, ruby: true)
-
- # Push the return value onto the stack
- stack_ret = ctx.stack_push(Type::CString)
- asm.mov(:rax, to_value(str))
- asm.mov(stack_ret, :rax)
-
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_nil_p(jit, ctx, asm)
- opt_send_without_block(jit, ctx, asm)
- end
-
- # opt_str_uminus
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_newarray_send(jit, ctx, asm)
- type = C.ID2SYM jit.operand(1)
-
- case type
- when :min then opt_newarray_min(jit, ctx, asm)
- when :max then opt_newarray_max(jit, ctx, asm)
- when :hash then opt_newarray_hash(jit, ctx, asm)
- else
- return CantCompile
- end
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_newarray_min(jit, ctx, asm)
- num = jit.operand(0)
-
- # Save the PC and SP because we may allocate
- jit_prepare_routine_call(jit, ctx, asm)
-
- offset_magnitude = C.VALUE.size * num
- values_opnd = ctx.sp_opnd(-offset_magnitude)
- asm.lea(:rax, values_opnd)
-
- asm.mov(C_ARGS[0], EC)
- asm.mov(C_ARGS[1], num)
- asm.mov(C_ARGS[2], :rax)
- asm.call(C.rb_vm_opt_newarray_min)
-
- ctx.stack_pop(num)
- stack_ret = ctx.stack_push(Type::Unknown)
- asm.mov(stack_ret, C_RET)
-
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_newarray_max(jit, ctx, asm)
- num = jit.operand(0)
-
- # Save the PC and SP because we may allocate
- jit_prepare_routine_call(jit, ctx, asm)
-
- offset_magnitude = C.VALUE.size * num
- values_opnd = ctx.sp_opnd(-offset_magnitude)
- asm.lea(:rax, values_opnd)
-
- asm.mov(C_ARGS[0], EC)
- asm.mov(C_ARGS[1], num)
- asm.mov(C_ARGS[2], :rax)
- asm.call(C.rb_vm_opt_newarray_max)
-
- ctx.stack_pop(num)
- stack_ret = ctx.stack_push(Type::Unknown)
- asm.mov(stack_ret, C_RET)
-
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_newarray_hash(jit, ctx, asm)
- num = jit.operand(0)
-
- # Save the PC and SP because we may allocate
- jit_prepare_routine_call(jit, ctx, asm)
-
- offset_magnitude = C.VALUE.size * num
- values_opnd = ctx.sp_opnd(-offset_magnitude)
- asm.lea(:rax, values_opnd)
-
- asm.mov(C_ARGS[0], EC)
- asm.mov(C_ARGS[1], num)
- asm.mov(C_ARGS[2], :rax)
- asm.call(C.rb_vm_opt_newarray_hash)
-
- ctx.stack_pop(num)
- stack_ret = ctx.stack_push(Type::Unknown)
- asm.mov(stack_ret, C_RET)
-
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def invokesuper(jit, ctx, asm)
- cd = C.rb_call_data.new(jit.operand(0))
- block = jit.operand(1)
-
- # Defer compilation so we can specialize on class of receiver
- unless jit.at_current_insn?
- defer_compilation(jit, ctx, asm)
- return EndBlock
- end
-
- me = C.rb_vm_frame_method_entry(jit.cfp)
- if me.nil?
- return CantCompile
- end
-
- # FIXME: We should track and invalidate this block when this cme is invalidated
- current_defined_class = me.defined_class
- mid = me.def.original_id
-
- if me.to_i != C.rb_callable_method_entry(current_defined_class, me.called_id).to_i
- # 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 CantCompile
- end
-
- # vm_search_normal_superclass
- rbasic_klass = C.to_ruby(C.RBasic.new(C.to_value(current_defined_class)).klass)
- if C::BUILTIN_TYPE(current_defined_class) == C::RUBY_T_ICLASS && C::BUILTIN_TYPE(rbasic_klass) == C::RUBY_T_MODULE && \
- C::FL_TEST_RAW(rbasic_klass, C::RMODULE_IS_REFINEMENT)
- return CantCompile
- end
- comptime_superclass = C.rb_class_get_superclass(C.RCLASS_ORIGIN(current_defined_class))
-
- ci = cd.ci
- argc = C.vm_ci_argc(ci)
-
- ci_flags = C.vm_ci_flag(ci)
-
- # Don't JIT calls that aren't simple
- # Note, not using VM_CALL_ARGS_SIMPLE because sometimes we pass a block.
-
- if ci_flags & C::VM_CALL_KWARG != 0
- asm.incr_counter(:send_keywords)
- return CantCompile
- end
- if ci_flags & C::VM_CALL_KW_SPLAT != 0
- asm.incr_counter(:send_kw_splat)
- return CantCompile
- end
- if ci_flags & C::VM_CALL_ARGS_BLOCKARG != 0
- asm.incr_counter(:send_block_arg)
- return CantCompile
- end
-
- # 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.
- comptime_recv = jit.peek_at_stack(argc)
- unless C.obj_is_kind_of(comptime_recv, current_defined_class)
- return CantCompile
- end
-
- # Do method lookup
- cme = C.rb_callable_method_entry(comptime_superclass, mid)
-
- if cme.nil?
- return CantCompile
- end
-
- # Check that we'll be able to write this method dispatch before generating checks
- cme_def_type = cme.def.type
- if cme_def_type != C::VM_METHOD_TYPE_ISEQ && cme_def_type != C::VM_METHOD_TYPE_CFUNC
- # others unimplemented
- return CantCompile
- end
-
- asm.comment('guard known me')
- lep_opnd = :rax
- jit_get_lep(jit, asm, reg: lep_opnd)
- ep_me_opnd = [lep_opnd, C.VALUE.size * C::VM_ENV_DATA_INDEX_ME_CREF]
-
- asm.mov(:rcx, me.to_i)
- asm.cmp(ep_me_opnd, :rcx)
- asm.jne(counted_exit(side_exit(jit, ctx), :invokesuper_me_changed))
-
- if block == C::VM_BLOCK_HANDLER_NONE
- # 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_*
- asm.comment('guard no block given')
- ep_specval_opnd = [lep_opnd, C.VALUE.size * C::VM_ENV_DATA_INDEX_SPECVAL]
- asm.cmp(ep_specval_opnd, C::VM_BLOCK_HANDLER_NONE)
- asm.jne(counted_exit(side_exit(jit, ctx), :invokesuper_block))
- end
-
- # We need to assume that both our current method entry and the super
- # method entry we invoke remain stable
- Invariants.assume_method_lookup_stable(jit, me)
- Invariants.assume_method_lookup_stable(jit, cme)
-
- # Method calls may corrupt types
- ctx.clear_local_types
-
- calling = build_calling(ci:, block_handler: block)
- case cme_def_type
- in C::VM_METHOD_TYPE_ISEQ
- iseq = def_iseq_ptr(cme.def)
- frame_type = C::VM_FRAME_MAGIC_METHOD | C::VM_ENV_FLAG_LOCAL
- jit_call_iseq(jit, ctx, asm, cme, calling, iseq, frame_type:)
- in C::VM_METHOD_TYPE_CFUNC
- jit_call_cfunc(jit, ctx, asm, cme, calling)
- end
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def invokeblock(jit, ctx, asm)
- unless jit.at_current_insn?
- defer_compilation(jit, ctx, asm)
- return EndBlock
- end
-
- # Get call info
- cd = C.rb_call_data.new(jit.operand(0))
- calling = build_calling(ci: cd.ci, block_handler: :captured)
-
- # Get block_handler
- cfp = jit.cfp
- lep = C.rb_vm_ep_local_ep(cfp.ep)
- comptime_handler = lep[C::VM_ENV_DATA_INDEX_SPECVAL]
-
- # Handle each block_handler type
- if comptime_handler == C::VM_BLOCK_HANDLER_NONE # no block given
- asm.incr_counter(:invokeblock_none)
- CantCompile
- elsif comptime_handler & 0x3 == 0x1 # VM_BH_ISEQ_BLOCK_P
- asm.comment('get local EP')
- ep_reg = :rax
- jit_get_lep(jit, asm, reg: ep_reg)
- asm.mov(:rax, [ep_reg, C.VALUE.size * C::VM_ENV_DATA_INDEX_SPECVAL]) # block_handler_opnd
-
- asm.comment('guard block_handler type')
- side_exit = side_exit(jit, ctx)
- asm.mov(:rcx, :rax)
- asm.and(:rcx, 0x3) # block_handler is a tagged pointer
- asm.cmp(:rcx, 0x1) # VM_BH_ISEQ_BLOCK_P
- tag_changed_exit = counted_exit(side_exit, :invokeblock_tag_changed)
- jit_chain_guard(:jne, jit, ctx, asm, tag_changed_exit)
-
- comptime_captured = C.rb_captured_block.new(comptime_handler & ~0x3)
- comptime_iseq = comptime_captured.code.iseq
-
- asm.comment('guard known ISEQ')
- asm.and(:rax, ~0x3) # captured
- asm.mov(:rax, [:rax, C.VALUE.size * 2]) # captured->iseq
- asm.mov(:rcx, comptime_iseq.to_i)
- asm.cmp(:rax, :rcx)
- block_changed_exit = counted_exit(side_exit, :invokeblock_iseq_block_changed)
- jit_chain_guard(:jne, jit, ctx, asm, block_changed_exit)
-
- jit_call_iseq(jit, ctx, asm, nil, calling, comptime_iseq, frame_type: C::VM_FRAME_MAGIC_BLOCK)
- elsif comptime_handler & 0x3 == 0x3 # VM_BH_IFUNC_P
- # We aren't handling CALLER_SETUP_ARG and CALLER_REMOVE_EMPTY_KW_SPLAT yet.
- if calling.flags & C::VM_CALL_ARGS_SPLAT != 0
- asm.incr_counter(:invokeblock_ifunc_args_splat)
- return CantCompile
- end
- if calling.flags & C::VM_CALL_KW_SPLAT != 0
- asm.incr_counter(:invokeblock_ifunc_kw_splat)
- return CantCompile
- end
-
- asm.comment('get local EP')
- jit_get_lep(jit, asm, reg: :rax)
- asm.mov(:rcx, [:rax, C.VALUE.size * C::VM_ENV_DATA_INDEX_SPECVAL]) # block_handler_opnd
-
- asm.comment('guard block_handler type');
- side_exit = side_exit(jit, ctx)
- asm.mov(:rax, :rcx) # block_handler_opnd
- asm.and(:rax, 0x3) # tag_opnd: block_handler is a tagged pointer
- asm.cmp(:rax, 0x3) # VM_BH_IFUNC_P
- tag_changed_exit = counted_exit(side_exit, :invokeblock_tag_changed)
- jit_chain_guard(:jne, jit, ctx, asm, tag_changed_exit)
-
- # The cfunc may not be leaf
- jit_prepare_routine_call(jit, ctx, asm) # clobbers :rax
-
- asm.comment('call ifunc')
- asm.and(:rcx, ~0x3) # captured_opnd
- asm.lea(:rax, ctx.sp_opnd(-calling.argc * C.VALUE.size)) # argv
- asm.mov(C_ARGS[0], EC)
- asm.mov(C_ARGS[1], :rcx) # captured_opnd
- asm.mov(C_ARGS[2], calling.argc)
- asm.mov(C_ARGS[3], :rax) # argv
- asm.call(C.rb_vm_yield_with_cfunc)
-
- ctx.stack_pop(calling.argc)
- stack_ret = ctx.stack_push(Type::Unknown)
- asm.mov(stack_ret, C_RET)
-
- # cfunc calls may corrupt types
- ctx.clear_local_types
-
- # Share the successor with other chains
- jump_to_next_insn(jit, ctx, asm)
- EndBlock
- elsif symbol?(comptime_handler)
- asm.incr_counter(:invokeblock_symbol)
- CantCompile
- else # Proc
- asm.incr_counter(:invokeblock_proc)
- CantCompile
- end
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def leave(jit, ctx, asm)
- assert_equal(ctx.stack_size, 1)
-
- jit_check_ints(jit, ctx, asm)
-
- asm.comment('pop stack frame')
- asm.lea(:rax, [CFP, C.rb_control_frame_t.size])
- asm.mov(CFP, :rax)
- asm.mov([EC, C.rb_execution_context_t.offsetof(:cfp)], :rax)
-
- # Return a value (for compile_leave_exit)
- ret_opnd = ctx.stack_pop
- asm.mov(:rax, ret_opnd)
-
- # Set caller's SP and push a value to its stack (for JIT)
- asm.mov(SP, [CFP, C.rb_control_frame_t.offsetof(:sp)]) # Note: SP is in the position after popping a receiver and arguments
- asm.mov([SP], :rax)
-
- # Jump to cfp->jit_return
- asm.jmp([CFP, -C.rb_control_frame_t.size + C.rb_control_frame_t.offsetof(:jit_return)])
-
- EndBlock
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def throw(jit, ctx, asm)
- throw_state = jit.operand(0)
- asm.mov(:rcx, ctx.stack_pop(1)) # throwobj
-
- # THROW_DATA_NEW allocates. Save SP for GC and PC for allocation tracing as
- # well as handling the catch table. However, not using jit_prepare_routine_call
- # since we don't need a patch point for this implementation.
- jit_save_pc(jit, asm) # clobbers rax
- jit_save_sp(ctx, asm)
-
- # rb_vm_throw verifies it's a valid throw, sets ec->tag->state, and returns throw
- # data, which is throwobj or a vm_throw_data wrapping it. When ec->tag->state is
- # set, JIT code callers will handle the throw with vm_exec_handle_exception.
- asm.mov(C_ARGS[0], EC)
- asm.mov(C_ARGS[1], CFP)
- asm.mov(C_ARGS[2], throw_state)
- # asm.mov(C_ARGS[3], :rcx) # same reg
- asm.call(C.rb_vm_throw)
-
- asm.comment('exit from throw')
- asm.pop(SP)
- asm.pop(EC)
- asm.pop(CFP)
-
- # return C_RET as C_RET
- asm.ret
- EndBlock
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jump(jit, ctx, asm)
- # Check for interrupts, but only on backward branches that may create loops
- jump_offset = jit.operand(0, signed: true)
- if jump_offset < 0
- jit_check_ints(jit, ctx, asm)
- end
-
- pc = jit.pc + C.VALUE.size * (jit.insn.len + jump_offset)
- jit_direct_jump(jit.iseq, pc, ctx, asm)
- EndBlock
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def branchif(jit, ctx, asm)
- # Check for interrupts, but only on backward branches that may create loops
- jump_offset = jit.operand(0, signed: true)
- if jump_offset < 0
- jit_check_ints(jit, ctx, asm)
- end
-
- # Get the branch target instruction offsets
- next_pc = jit.pc + C.VALUE.size * jit.insn.len
- jump_pc = jit.pc + C.VALUE.size * (jit.insn.len + jump_offset)
-
- val_type = ctx.get_opnd_type(StackOpnd[0])
- val_opnd = ctx.stack_pop(1)
-
- if (result = val_type.known_truthy) != nil
- target_pc = result ? jump_pc : next_pc
- jit_direct_jump(jit.iseq, target_pc, ctx, asm)
- else
- # This `test` sets ZF only for Qnil and Qfalse, which let jz jump.
- asm.test(val_opnd, ~Qnil)
-
- # Set stubs
- branch_stub = BranchStub.new(
- iseq: jit.iseq,
- shape: Default,
- target0: BranchTarget.new(ctx:, pc: jump_pc), # branch target
- target1: BranchTarget.new(ctx:, pc: next_pc), # fallthrough
- )
- branch_stub.target0.address = Assembler.new.then do |ocb_asm|
- @exit_compiler.compile_branch_stub(ctx, ocb_asm, branch_stub, true)
- @ocb.write(ocb_asm)
- end
- branch_stub.target1.address = Assembler.new.then do |ocb_asm|
- @exit_compiler.compile_branch_stub(ctx, ocb_asm, branch_stub, false)
- @ocb.write(ocb_asm)
- end
-
- # Jump to target0 on jnz
- branch_stub.compile = compile_branchif(branch_stub)
- branch_stub.compile.call(asm)
- end
-
- EndBlock
- end
-
- def compile_branchif(branch_stub) # Proc escapes arguments in memory
- proc do |branch_asm|
- branch_asm.comment("branchif #{branch_stub.shape}")
- branch_asm.stub(branch_stub) do
- case branch_stub.shape
- in Default
- branch_asm.jnz(branch_stub.target0.address)
- branch_asm.jmp(branch_stub.target1.address)
- in Next0
- branch_asm.jz(branch_stub.target1.address)
- in Next1
- branch_asm.jnz(branch_stub.target0.address)
- end
- end
- end
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def branchunless(jit, ctx, asm)
- # Check for interrupts, but only on backward branches that may create loops
- jump_offset = jit.operand(0, signed: true)
- if jump_offset < 0
- jit_check_ints(jit, ctx, asm)
- end
-
- # Get the branch target instruction offsets
- next_pc = jit.pc + C.VALUE.size * jit.insn.len
- jump_pc = jit.pc + C.VALUE.size * (jit.insn.len + jump_offset)
-
- val_type = ctx.get_opnd_type(StackOpnd[0])
- val_opnd = ctx.stack_pop(1)
-
- if (result = val_type.known_truthy) != nil
- target_pc = result ? next_pc : jump_pc
- jit_direct_jump(jit.iseq, target_pc, ctx, asm)
- else
- # This `test` sets ZF only for Qnil and Qfalse, which let jz jump.
- asm.test(val_opnd, ~Qnil)
-
- # Set stubs
- branch_stub = BranchStub.new(
- iseq: jit.iseq,
- shape: Default,
- target0: BranchTarget.new(ctx:, pc: jump_pc), # branch target
- target1: BranchTarget.new(ctx:, pc: next_pc), # fallthrough
- )
- branch_stub.target0.address = Assembler.new.then do |ocb_asm|
- @exit_compiler.compile_branch_stub(ctx, ocb_asm, branch_stub, true)
- @ocb.write(ocb_asm)
- end
- branch_stub.target1.address = Assembler.new.then do |ocb_asm|
- @exit_compiler.compile_branch_stub(ctx, ocb_asm, branch_stub, false)
- @ocb.write(ocb_asm)
- end
-
- # Jump to target0 on jz
- branch_stub.compile = compile_branchunless(branch_stub)
- branch_stub.compile.call(asm)
- end
-
- EndBlock
- end
-
- def compile_branchunless(branch_stub) # Proc escapes arguments in memory
- proc do |branch_asm|
- branch_asm.comment("branchunless #{branch_stub.shape}")
- branch_asm.stub(branch_stub) do
- case branch_stub.shape
- in Default
- branch_asm.jz(branch_stub.target0.address)
- branch_asm.jmp(branch_stub.target1.address)
- in Next0
- branch_asm.jnz(branch_stub.target1.address)
- in Next1
- branch_asm.jz(branch_stub.target0.address)
- end
- end
- end
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def branchnil(jit, ctx, asm)
- # Check for interrupts, but only on backward branches that may create loops
- jump_offset = jit.operand(0, signed: true)
- if jump_offset < 0
- jit_check_ints(jit, ctx, asm)
- end
-
- # Get the branch target instruction offsets
- next_pc = jit.pc + C.VALUE.size * jit.insn.len
- jump_pc = jit.pc + C.VALUE.size * (jit.insn.len + jump_offset)
-
- val_type = ctx.get_opnd_type(StackOpnd[0])
- val_opnd = ctx.stack_pop(1)
-
- if (result = val_type.known_nil) != nil
- target_pc = result ? jump_pc : next_pc
- jit_direct_jump(jit.iseq, target_pc, ctx, asm)
- else
- asm.cmp(val_opnd, Qnil)
-
- # Set stubs
- branch_stub = BranchStub.new(
- iseq: jit.iseq,
- shape: Default,
- target0: BranchTarget.new(ctx:, pc: jump_pc), # branch target
- target1: BranchTarget.new(ctx:, pc: next_pc), # fallthrough
- )
- branch_stub.target0.address = Assembler.new.then do |ocb_asm|
- @exit_compiler.compile_branch_stub(ctx, ocb_asm, branch_stub, true)
- @ocb.write(ocb_asm)
- end
- branch_stub.target1.address = Assembler.new.then do |ocb_asm|
- @exit_compiler.compile_branch_stub(ctx, ocb_asm, branch_stub, false)
- @ocb.write(ocb_asm)
- end
-
- # Jump to target0 on je
- branch_stub.compile = compile_branchnil(branch_stub)
- branch_stub.compile.call(asm)
- end
-
- EndBlock
- end
-
- def compile_branchnil(branch_stub) # Proc escapes arguments in memory
- proc do |branch_asm|
- branch_asm.comment("branchnil #{branch_stub.shape}")
- branch_asm.stub(branch_stub) do
- case branch_stub.shape
- in Default
- branch_asm.je(branch_stub.target0.address)
- branch_asm.jmp(branch_stub.target1.address)
- in Next0
- branch_asm.jne(branch_stub.target1.address)
- in Next1
- branch_asm.je(branch_stub.target0.address)
- end
- end
- end
- end
-
- # once
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_case_dispatch(jit, ctx, asm)
- # 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.
- unless jit.at_current_insn?
- defer_compilation(jit, ctx, asm)
- return EndBlock
- end
- starting_context = ctx.dup
-
- case_hash = jit.operand(0, ruby: true)
- else_offset = jit.operand(1)
-
- # Try to reorder case/else branches so that ones that are actually used come first.
- # Supporting only Fixnum for now so that the implementation can be an equality check.
- key_opnd = ctx.stack_pop(1)
- comptime_key = jit.peek_at_stack(0)
-
- # Check that all cases are fixnums to avoid having to register BOP assumptions on
- # all the types that case hashes support. This spends compile time to save memory.
- if fixnum?(comptime_key) && comptime_key <= 2**32 && C.rb_hash_keys(case_hash).all? { |key| fixnum?(key) }
- unless Invariants.assume_bop_not_redefined(jit, C::INTEGER_REDEFINED_OP_FLAG, C::BOP_EQQ)
- return CantCompile
- end
-
- # Check if the key is the same value
- asm.cmp(key_opnd, to_value(comptime_key))
- side_exit = side_exit(jit, starting_context)
- jit_chain_guard(:jne, jit, starting_context, asm, side_exit)
-
- # Get the offset for the compile-time key
- offset = C.rb_hash_stlike_lookup(case_hash, comptime_key)
- # NOTE: If we hit the else branch with various values, it could negatively impact the performance.
- jump_offset = offset || else_offset
-
- # Jump to the offset of case or else
- target_pc = jit.pc + (jit.insn.len + jump_offset) * C.VALUE.size
- jit_direct_jump(jit.iseq, target_pc, ctx, asm)
- EndBlock
- else
- KeepCompiling # continue with === branches
- end
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_plus(jit, ctx, asm)
- unless jit.at_current_insn?
- defer_compilation(jit, ctx, asm)
- return EndBlock
- end
-
- comptime_recv = jit.peek_at_stack(1)
- comptime_obj = jit.peek_at_stack(0)
-
- if fixnum?(comptime_recv) && fixnum?(comptime_obj)
- unless Invariants.assume_bop_not_redefined(jit, C::INTEGER_REDEFINED_OP_FLAG, C::BOP_PLUS)
- return CantCompile
- end
-
- # Check that both operands are fixnums
- guard_two_fixnums(jit, ctx, asm)
-
- obj_opnd = ctx.stack_pop
- recv_opnd = ctx.stack_pop
-
- asm.mov(:rax, recv_opnd)
- asm.sub(:rax, 1) # untag
- asm.mov(:rcx, obj_opnd)
- asm.add(:rax, :rcx)
- asm.jo(side_exit(jit, ctx))
-
- dst_opnd = ctx.stack_push(Type::Fixnum)
- asm.mov(dst_opnd, :rax)
-
- KeepCompiling
- else
- opt_send_without_block(jit, ctx, asm)
- end
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_minus(jit, ctx, asm)
- unless jit.at_current_insn?
- defer_compilation(jit, ctx, asm)
- return EndBlock
- end
-
- comptime_recv = jit.peek_at_stack(1)
- comptime_obj = jit.peek_at_stack(0)
-
- if fixnum?(comptime_recv) && fixnum?(comptime_obj)
- unless Invariants.assume_bop_not_redefined(jit, C::INTEGER_REDEFINED_OP_FLAG, C::BOP_MINUS)
- return CantCompile
- end
-
- # Check that both operands are fixnums
- guard_two_fixnums(jit, ctx, asm)
-
- obj_opnd = ctx.stack_pop
- recv_opnd = ctx.stack_pop
-
- asm.mov(:rax, recv_opnd)
- asm.mov(:rcx, obj_opnd)
- asm.sub(:rax, :rcx)
- asm.jo(side_exit(jit, ctx))
- asm.add(:rax, 1) # re-tag
-
- dst_opnd = ctx.stack_push(Type::Fixnum)
- asm.mov(dst_opnd, :rax)
-
- KeepCompiling
- else
- opt_send_without_block(jit, ctx, asm)
- end
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_mult(jit, ctx, asm)
- opt_send_without_block(jit, ctx, asm)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_div(jit, ctx, asm)
- opt_send_without_block(jit, ctx, asm)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_mod(jit, ctx, asm)
- unless jit.at_current_insn?
- defer_compilation(jit, ctx, asm)
- return EndBlock
- end
-
- if two_fixnums_on_stack?(jit)
- unless Invariants.assume_bop_not_redefined(jit, C::INTEGER_REDEFINED_OP_FLAG, C::BOP_MOD)
- return CantCompile
- end
-
- # Check that both operands are fixnums
- guard_two_fixnums(jit, ctx, asm)
-
- # Get the operands and destination from the stack
- arg1 = ctx.stack_pop(1)
- arg0 = ctx.stack_pop(1)
-
- # Check for arg0 % 0
- asm.cmp(arg1, 0)
- asm.je(side_exit(jit, ctx))
-
- # Call rb_fix_mod_fix(VALUE recv, VALUE obj)
- asm.mov(C_ARGS[0], arg0)
- asm.mov(C_ARGS[1], arg1)
- asm.call(C.rb_fix_mod_fix)
-
- # Push the return value onto the stack
- stack_ret = ctx.stack_push(Type::Fixnum)
- asm.mov(stack_ret, C_RET)
-
- KeepCompiling
- else
- opt_send_without_block(jit, ctx, asm)
- end
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_eq(jit, ctx, asm)
- unless jit.at_current_insn?
- defer_compilation(jit, ctx, asm)
- return EndBlock
- end
-
- if jit_equality_specialized(jit, ctx, asm, true)
- jump_to_next_insn(jit, ctx, asm)
- EndBlock
- else
- opt_send_without_block(jit, ctx, asm)
- end
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_neq(jit, ctx, asm)
- # opt_neq is passed two rb_call_data as arguments:
- # first for ==, second for !=
- neq_cd = C.rb_call_data.new(jit.operand(1))
- opt_send_without_block(jit, ctx, asm, cd: neq_cd)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_lt(jit, ctx, asm)
- jit_fixnum_cmp(jit, ctx, asm, opcode: :cmovl, bop: C::BOP_LT)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_le(jit, ctx, asm)
- jit_fixnum_cmp(jit, ctx, asm, opcode: :cmovle, bop: C::BOP_LE)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_gt(jit, ctx, asm)
- jit_fixnum_cmp(jit, ctx, asm, opcode: :cmovg, bop: C::BOP_GT)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_ge(jit, ctx, asm)
- jit_fixnum_cmp(jit, ctx, asm, opcode: :cmovge, bop: C::BOP_GE)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_ltlt(jit, ctx, asm)
- opt_send_without_block(jit, ctx, asm)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_and(jit, ctx, asm)
- unless jit.at_current_insn?
- defer_compilation(jit, ctx, asm)
- return EndBlock
- end
-
- if two_fixnums_on_stack?(jit)
- unless Invariants.assume_bop_not_redefined(jit, C::INTEGER_REDEFINED_OP_FLAG, C::BOP_AND)
- return CantCompile
- end
-
- # Check that both operands are fixnums
- guard_two_fixnums(jit, ctx, asm)
-
- # Get the operands and destination from the stack
- arg1 = ctx.stack_pop(1)
- arg0 = ctx.stack_pop(1)
-
- asm.comment('bitwise and')
- asm.mov(:rax, arg0)
- asm.and(:rax, arg1)
-
- # Push the return value onto the stack
- dst = ctx.stack_push(Type::Fixnum)
- asm.mov(dst, :rax)
-
- KeepCompiling
- else
- opt_send_without_block(jit, ctx, asm)
- end
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_or(jit, ctx, asm)
- unless jit.at_current_insn?
- defer_compilation(jit, ctx, asm)
- return EndBlock
- end
-
- if two_fixnums_on_stack?(jit)
- unless Invariants.assume_bop_not_redefined(jit, C::INTEGER_REDEFINED_OP_FLAG, C::BOP_OR)
- return CantCompile
- end
-
- # Check that both operands are fixnums
- guard_two_fixnums(jit, ctx, asm)
-
- # Get the operands and destination from the stack
- asm.comment('bitwise or')
- arg1 = ctx.stack_pop(1)
- arg0 = ctx.stack_pop(1)
-
- # Do the bitwise or arg0 | arg1
- asm.mov(:rax, arg0)
- asm.or(:rax, arg1)
-
- # Push the return value onto the stack
- dst = ctx.stack_push(Type::Fixnum)
- asm.mov(dst, :rax)
-
- KeepCompiling
- else
- opt_send_without_block(jit, ctx, asm)
- end
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_aref(jit, ctx, asm)
- cd = C.rb_call_data.new(jit.operand(0))
- argc = C.vm_ci_argc(cd.ci)
-
- if argc != 1
- asm.incr_counter(:optaref_argc_not_one)
- return CantCompile
- end
-
- unless jit.at_current_insn?
- defer_compilation(jit, ctx, asm)
- return EndBlock
- end
-
- comptime_recv = jit.peek_at_stack(1)
- comptime_obj = jit.peek_at_stack(0)
-
- side_exit = side_exit(jit, ctx)
-
- if C.rb_class_of(comptime_recv) == Array && fixnum?(comptime_obj)
- unless Invariants.assume_bop_not_redefined(jit, C::ARRAY_REDEFINED_OP_FLAG, C::BOP_AREF)
- return CantCompile
- end
-
- idx_opnd = ctx.stack_opnd(0)
- recv_opnd = ctx.stack_opnd(1)
-
- not_array_exit = counted_exit(side_exit, :optaref_recv_not_array)
- jit_guard_known_klass(jit, ctx, asm, C.rb_class_of(comptime_recv), recv_opnd, StackOpnd[1], comptime_recv, not_array_exit)
-
- # Bail if idx is not a FIXNUM
- asm.mov(:rax, idx_opnd)
- asm.test(:rax, C::RUBY_FIXNUM_FLAG)
- asm.jz(counted_exit(side_exit, :optaref_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.
- asm.sar(:rax, 1) # Convert fixnum to int
- asm.mov(C_ARGS[0], recv_opnd)
- asm.mov(C_ARGS[1], :rax)
- asm.call(C.rb_ary_entry_internal)
-
- # Pop the argument and the receiver
- ctx.stack_pop(2)
-
- # Push the return value onto the stack
- stack_ret = ctx.stack_push(Type::Unknown)
- asm.mov(stack_ret, C_RET)
-
- # Let guard chains share the same successor
- jump_to_next_insn(jit, ctx, asm)
- EndBlock
- elsif C.rb_class_of(comptime_recv) == Hash
- unless Invariants.assume_bop_not_redefined(jit, C::HASH_REDEFINED_OP_FLAG, C::BOP_AREF)
- return CantCompile
- end
-
- recv_opnd = ctx.stack_opnd(1)
-
- # Guard that the receiver is a Hash
- not_hash_exit = counted_exit(side_exit, :optaref_recv_not_hash)
- jit_guard_known_klass(jit, ctx, asm, C.rb_class_of(comptime_recv), recv_opnd, StackOpnd[1], comptime_recv, not_hash_exit)
-
- # Prepare to call rb_hash_aref(). It might call #hash on the key.
- jit_prepare_routine_call(jit, ctx, asm)
-
- asm.comment('call rb_hash_aref')
- key_opnd = ctx.stack_opnd(0)
- recv_opnd = ctx.stack_opnd(1)
- asm.mov(:rdi, recv_opnd)
- asm.mov(:rsi, key_opnd)
- asm.call(C.rb_hash_aref)
-
- # Pop the key and the receiver
- ctx.stack_pop(2)
-
- stack_ret = ctx.stack_push(Type::Unknown)
- asm.mov(stack_ret, C_RET)
-
- # Let guard chains share the same successor
- jump_to_next_insn(jit, ctx, asm)
- EndBlock
- else
- opt_send_without_block(jit, ctx, asm)
- end
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_aset(jit, ctx, asm)
- # Defer compilation so we can specialize on a runtime `self`
- unless jit.at_current_insn?
- defer_compilation(jit, ctx, asm)
- return EndBlock
- end
-
- comptime_recv = jit.peek_at_stack(2)
- comptime_key = jit.peek_at_stack(1)
-
- # Get the operands from the stack
- recv = ctx.stack_opnd(2)
- key = ctx.stack_opnd(1)
- _val = ctx.stack_opnd(0)
-
- if C.rb_class_of(comptime_recv) == Array && fixnum?(comptime_key)
- side_exit = side_exit(jit, ctx)
-
- # Guard receiver is an Array
- jit_guard_known_klass(jit, ctx, asm, C.rb_class_of(comptime_recv), recv, StackOpnd[2], comptime_recv, side_exit)
-
- # Guard key is a fixnum
- jit_guard_known_klass(jit, ctx, asm, C.rb_class_of(comptime_key), key, StackOpnd[1], comptime_key, side_exit)
-
- # We might allocate or raise
- jit_prepare_routine_call(jit, ctx, asm)
-
- asm.comment('call rb_ary_store')
- recv = ctx.stack_opnd(2)
- key = ctx.stack_opnd(1)
- val = ctx.stack_opnd(0)
- asm.mov(:rax, key)
- asm.sar(:rax, 1) # FIX2LONG(key)
- asm.mov(C_ARGS[0], recv)
- asm.mov(C_ARGS[1], :rax)
- asm.mov(C_ARGS[2], val)
- asm.call(C.rb_ary_store)
-
- # rb_ary_store returns void
- # stored value should still be on stack
- val = ctx.stack_opnd(0)
-
- # Push the return value onto the stack
- ctx.stack_pop(3)
- stack_ret = ctx.stack_push(Type::Unknown)
- asm.mov(:rax, val)
- asm.mov(stack_ret, :rax)
-
- jump_to_next_insn(jit, ctx, asm)
- EndBlock
- elsif C.rb_class_of(comptime_recv) == Hash
- side_exit = side_exit(jit, ctx)
-
- # Guard receiver is a Hash
- jit_guard_known_klass(jit, ctx, asm, C.rb_class_of(comptime_recv), recv, StackOpnd[2], comptime_recv, side_exit)
-
- # We might allocate or raise
- jit_prepare_routine_call(jit, ctx, asm)
-
- # Call rb_hash_aset
- recv = ctx.stack_opnd(2)
- key = ctx.stack_opnd(1)
- val = ctx.stack_opnd(0)
- asm.mov(C_ARGS[0], recv)
- asm.mov(C_ARGS[1], key)
- asm.mov(C_ARGS[2], val)
- asm.call(C.rb_hash_aset)
-
- # Push the return value onto the stack
- ctx.stack_pop(3)
- stack_ret = ctx.stack_push(Type::Unknown)
- asm.mov(stack_ret, C_RET)
-
- jump_to_next_insn(jit, ctx, asm)
- EndBlock
- else
- opt_send_without_block(jit, ctx, asm)
- end
- end
-
- # opt_aset_with
- # opt_aref_with
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_length(jit, ctx, asm)
- opt_send_without_block(jit, ctx, asm)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_size(jit, ctx, asm)
- opt_send_without_block(jit, ctx, asm)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_empty_p(jit, ctx, asm)
- opt_send_without_block(jit, ctx, asm)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_succ(jit, ctx, asm)
- opt_send_without_block(jit, ctx, asm)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_not(jit, ctx, asm)
- opt_send_without_block(jit, ctx, asm)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_regexpmatch2(jit, ctx, asm)
- opt_send_without_block(jit, ctx, asm)
- end
-
- # invokebuiltin
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_invokebuiltin_delegate(jit, ctx, asm)
- bf = C.rb_builtin_function.new(jit.operand(0))
- bf_argc = bf.argc
- start_index = jit.operand(1)
-
- # ec, self, and arguments
- if bf_argc + 2 > C_ARGS.size
- return CantCompile
- end
-
- # If the calls don't allocate, do they need up to date PC, SP?
- jit_prepare_routine_call(jit, ctx, asm)
-
- # Call the builtin func (ec, recv, arg1, arg2, ...)
- asm.comment('call builtin func')
- asm.mov(C_ARGS[0], EC)
- asm.mov(C_ARGS[1], [CFP, C.rb_control_frame_t.offsetof(:self)])
-
- # Copy arguments from locals
- if bf_argc > 0
- # Load environment pointer EP from CFP
- asm.mov(:rax, [CFP, C.rb_control_frame_t.offsetof(:ep)])
-
- bf_argc.times do |i|
- table_size = jit.iseq.body.local_table_size
- offs = -table_size - C::VM_ENV_DATA_SIZE + 1 + start_index + i
- asm.mov(C_ARGS[2 + i], [:rax, offs * C.VALUE.size])
- end
- end
- asm.call(bf.func_ptr)
-
- # Push the return value
- stack_ret = ctx.stack_push(Type::Unknown)
- asm.mov(stack_ret, C_RET)
-
- KeepCompiling
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def opt_invokebuiltin_delegate_leave(jit, ctx, asm)
- opt_invokebuiltin_delegate(jit, ctx, asm)
- # opt_invokebuiltin_delegate is always followed by leave insn
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def putobject_INT2FIX_0_(jit, ctx, asm)
- putobject(jit, ctx, asm, val: C.to_value(0))
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def putobject_INT2FIX_1_(jit, ctx, asm)
- putobject(jit, ctx, asm, val: C.to_value(1))
- end
-
- #
- # C func
- #
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_rb_true(jit, ctx, asm, argc, _known_recv_class)
- return false if argc != 0
- asm.comment('nil? == true')
- ctx.stack_pop(1)
- stack_ret = ctx.stack_push(Type::True)
- asm.mov(stack_ret, Qtrue)
- true
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_rb_false(jit, ctx, asm, argc, _known_recv_class)
- return false if argc != 0
- asm.comment('nil? == false')
- ctx.stack_pop(1)
- stack_ret = ctx.stack_push(Type::False)
- asm.mov(stack_ret, Qfalse)
- true
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_rb_kernel_is_a(jit, ctx, asm, argc, known_recv_class)
- if argc != 1
- return false
- end
-
- # If this is a super call we might not know the class
- if known_recv_class.nil?
- return false
- end
-
- # Important note: The output code will simply `return true/false`.
- # Correctness follows from:
- # - `known_recv_class` implies there is a guard scheduled before here
- # for a particular `CLASS_OF(lhs)`.
- # - We guard that rhs is identical to the compile-time sample
- # - In general, for any two Class instances A, B, `A < B` does not change at runtime.
- # Class#superclass is stable.
-
- sample_rhs = jit.peek_at_stack(0)
- sample_lhs = jit.peek_at_stack(1)
-
- # We are not allowing module here because the module hierarchy can change at runtime.
- if C.RB_TYPE_P(sample_rhs, C::RUBY_T_CLASS)
- return false
- end
- sample_is_a = C.obj_is_kind_of(sample_lhs, sample_rhs)
-
- side_exit = side_exit(jit, ctx)
- asm.comment('Kernel#is_a?')
- asm.mov(:rax, to_value(sample_rhs))
- asm.cmp(ctx.stack_opnd(0), :rax)
- asm.jne(counted_exit(side_exit, :send_is_a_class_mismatch))
-
- ctx.stack_pop(2)
-
- if sample_is_a
- stack_ret = ctx.stack_push(Type::True)
- asm.mov(stack_ret, Qtrue)
- else
- stack_ret = ctx.stack_push(Type::False)
- asm.mov(stack_ret, Qfalse)
- end
- return true
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_rb_kernel_instance_of(jit, ctx, asm, argc, known_recv_class)
- if argc != 1
- return false
- end
-
- # If this is a super call we might not know the class
- if known_recv_class.nil?
- return false
- end
-
- # Important note: The output code will simply `return true/false`.
- # Correctness follows from:
- # - `known_recv_class` implies there is a guard scheduled before here
- # for a particular `CLASS_OF(lhs)`.
- # - We guard that rhs is identical to the compile-time sample
- # - For a particular `CLASS_OF(lhs)`, `rb_obj_class(lhs)` does not change.
- # (because for any singleton class `s`, `s.superclass.equal?(s.attached_object.class)`)
-
- sample_rhs = jit.peek_at_stack(0)
- sample_lhs = jit.peek_at_stack(1)
-
- # Filters out cases where the C implementation raises
- unless C.RB_TYPE_P(sample_rhs, C::RUBY_T_CLASS) || C.RB_TYPE_P(sample_rhs, C::RUBY_T_MODULE)
- return false
- end
-
- # We need to grab the class here to deal with singleton classes.
- # Instance of grabs the "real class" of the object rather than the
- # singleton class.
- sample_lhs_real_class = C.rb_obj_class(sample_lhs)
-
- sample_instance_of = (sample_lhs_real_class == sample_rhs)
-
- side_exit = side_exit(jit, ctx)
- asm.comment('Kernel#instance_of?')
- asm.mov(:rax, to_value(sample_rhs))
- asm.cmp(ctx.stack_opnd(0), :rax)
- asm.jne(counted_exit(side_exit, :send_instance_of_class_mismatch))
-
- ctx.stack_pop(2)
-
- if sample_instance_of
- stack_ret = ctx.stack_push(Type::True)
- asm.mov(stack_ret, Qtrue)
- else
- stack_ret = ctx.stack_push(Type::False)
- asm.mov(stack_ret, Qfalse)
- end
- return true;
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_rb_obj_not(jit, ctx, asm, argc, _known_recv_class)
- return false if argc != 0
- recv_type = ctx.get_opnd_type(StackOpnd[0])
-
- case recv_type.known_truthy
- in false
- asm.comment('rb_obj_not(nil_or_false)')
- ctx.stack_pop(1)
- out_opnd = ctx.stack_push(Type::True)
- asm.mov(out_opnd, Qtrue)
- in true
- # Note: recv_type != Type::Nil && recv_type != Type::False.
- asm.comment('rb_obj_not(truthy)')
- ctx.stack_pop(1)
- out_opnd = ctx.stack_push(Type::False)
- asm.mov(out_opnd, Qfalse)
- in nil
- asm.comment('rb_obj_not')
-
- recv = ctx.stack_pop
- # This `test` sets ZF only for Qnil and Qfalse, which let cmovz set.
- asm.test(recv, ~Qnil)
- asm.mov(:rax, Qfalse)
- asm.mov(:rcx, Qtrue)
- asm.cmovz(:rax, :rcx)
-
- stack_ret = ctx.stack_push(Type::UnknownImm)
- asm.mov(stack_ret, :rax)
- end
- true
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_rb_obj_equal(jit, ctx, asm, argc, _known_recv_class)
- return false if argc != 1
- asm.comment('equal?')
- obj1 = ctx.stack_pop(1)
- obj2 = ctx.stack_pop(1)
-
- asm.mov(:rax, obj1)
- asm.mov(:rcx, obj2)
- asm.cmp(:rax, :rcx)
- asm.mov(:rax, Qfalse)
- asm.mov(:rcx, Qtrue)
- asm.cmove(:rax, :rcx)
-
- stack_ret = ctx.stack_push(Type::UnknownImm)
- asm.mov(stack_ret, :rax)
- true
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_rb_obj_not_equal(jit, ctx, asm, argc, _known_recv_class)
- return false if argc != 1
- jit_equality_specialized(jit, ctx, asm, false)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_rb_mod_eqq(jit, ctx, asm, argc, _known_recv_class)
- return false if argc != 1
-
- asm.comment('Module#===')
- # By being here, we know that the receiver is a T_MODULE or a T_CLASS, because Module#=== can
- # only live on these objects. With that, we can call rb_obj_is_kind_of() without
- # jit_prepare_routine_call() or a control frame push because it can't raise, allocate, or call
- # Ruby methods with these inputs.
- # Note the difference in approach from Kernel#is_a? because we don't get a free guard for the
- # right hand side.
- lhs = ctx.stack_opnd(1) # the module
- rhs = ctx.stack_opnd(0)
- asm.mov(C_ARGS[0], rhs);
- asm.mov(C_ARGS[1], lhs);
- asm.call(C.rb_obj_is_kind_of)
-
- # Return the result
- ctx.stack_pop(2)
- stack_ret = ctx.stack_push(Type::UnknownImm)
- asm.mov(stack_ret, C_RET)
-
- return true
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_rb_int_equal(jit, ctx, asm, argc, _known_recv_class)
- return false if argc != 1
- return false unless two_fixnums_on_stack?(jit)
-
- guard_two_fixnums(jit, ctx, asm)
-
- # Compare the arguments
- asm.comment('rb_int_equal')
- arg1 = ctx.stack_pop(1)
- arg0 = ctx.stack_pop(1)
- asm.mov(:rax, arg1)
- asm.cmp(arg0, :rax)
- asm.mov(:rax, Qfalse)
- asm.mov(:rcx, Qtrue)
- asm.cmove(:rax, :rcx)
-
- stack_ret = ctx.stack_push(Type::UnknownImm)
- asm.mov(stack_ret, :rax)
- true
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_rb_int_mul(jit, ctx, asm, argc, _known_recv_class)
- return false if argc != 1
- return false unless two_fixnums_on_stack?(jit)
-
- guard_two_fixnums(jit, ctx, asm)
-
- asm.comment('rb_int_mul')
- y_opnd = ctx.stack_pop
- x_opnd = ctx.stack_pop
- asm.mov(C_ARGS[0], x_opnd)
- asm.mov(C_ARGS[1], y_opnd)
- asm.call(C.rb_fix_mul_fix)
-
- ret_opnd = ctx.stack_push(Type::Unknown)
- asm.mov(ret_opnd, C_RET)
- true
- end
-
- def jit_rb_int_div(jit, ctx, asm, argc, _known_recv_class)
- return false if argc != 1
- return false unless two_fixnums_on_stack?(jit)
-
- guard_two_fixnums(jit, ctx, asm)
-
- asm.comment('rb_int_div')
- y_opnd = ctx.stack_pop
- x_opnd = ctx.stack_pop
- asm.mov(:rax, y_opnd)
- asm.cmp(:rax, C.to_value(0))
- asm.je(side_exit(jit, ctx))
-
- asm.mov(C_ARGS[0], x_opnd)
- asm.mov(C_ARGS[1], :rax)
- asm.call(C.rb_fix_div_fix)
-
- ret_opnd = ctx.stack_push(Type::Unknown)
- asm.mov(ret_opnd, C_RET)
- true
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_rb_int_aref(jit, ctx, asm, argc, _known_recv_class)
- return false if argc != 1
- return false unless two_fixnums_on_stack?(jit)
-
- guard_two_fixnums(jit, ctx, asm)
-
- asm.comment('rb_int_aref')
- y_opnd = ctx.stack_pop
- x_opnd = ctx.stack_pop
-
- asm.mov(C_ARGS[0], x_opnd)
- asm.mov(C_ARGS[1], y_opnd)
- asm.call(C.rb_fix_aref)
-
- ret_opnd = ctx.stack_push(Type::UnknownImm)
- asm.mov(ret_opnd, C_RET)
- true
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_rb_str_empty_p(jit, ctx, asm, argc, known_recv_class)
- recv_opnd = ctx.stack_pop(1)
- out_opnd = ctx.stack_push(Type::UnknownImm)
-
- asm.comment('get string length')
- asm.mov(:rax, recv_opnd)
- str_len_opnd = [:rax, C.RString.offsetof(:len)]
-
- asm.cmp(str_len_opnd, 0)
- asm.mov(:rax, Qfalse)
- asm.mov(:rcx, Qtrue)
- asm.cmove(:rax, :rcx)
- asm.mov(out_opnd, :rax)
-
- return true
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_rb_str_to_s(jit, ctx, asm, argc, known_recv_class)
- return false if argc != 0
- if known_recv_class == String
- asm.comment('to_s on plain string')
- # The method returns the receiver, which is already on the stack.
- # No stack movement.
- return true
- end
- false
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_rb_str_bytesize(jit, ctx, asm, argc, known_recv_class)
- asm.comment('String#bytesize')
-
- recv = ctx.stack_pop(1)
- asm.mov(C_ARGS[0], recv)
- asm.call(C.rb_str_bytesize)
-
- out_opnd = ctx.stack_push(Type::Fixnum)
- asm.mov(out_opnd, C_RET)
-
- true
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_rb_str_concat(jit, ctx, asm, argc, known_recv_class)
- # The << operator can accept integer codepoints for characters
- # as the argument. We only specially optimise string arguments.
- # If the peeked-at compile time argument is something other than
- # a string, assume it won't be a string later either.
- comptime_arg = jit.peek_at_stack(0)
- unless C.RB_TYPE_P(comptime_arg, C::RUBY_T_STRING)
- return false
- end
-
- # Guard that the concat argument is a string
- asm.mov(:rax, ctx.stack_opnd(0))
- guard_object_is_string(jit, ctx, asm, :rax, :rcx, StackOpnd[0])
-
- # Guard buffers from GC since rb_str_buf_append may allocate. During the VM lock on GC,
- # other Ractors may trigger global invalidation, so we need ctx.clear_local_types.
- # PC is used on errors like Encoding::CompatibilityError raised by rb_str_buf_append.
- jit_prepare_routine_call(jit, ctx, asm)
-
- concat_arg = ctx.stack_pop(1)
- recv = ctx.stack_pop(1)
-
- # Test if string encodings differ. If different, use rb_str_append. If the same,
- # use rb_yjit_str_simple_append, which calls rb_str_cat.
- asm.comment('<< on strings')
-
- # Take receiver's object flags XOR arg's flags. If any
- # string-encoding flags are different between the two,
- # the encodings don't match.
- recv_reg = :rax
- asm.mov(recv_reg, recv)
- concat_arg_reg = :rcx
- asm.mov(concat_arg_reg, concat_arg)
- asm.mov(recv_reg, [recv_reg, C.RBasic.offsetof(:flags)])
- asm.mov(concat_arg_reg, [concat_arg_reg, C.RBasic.offsetof(:flags)])
- asm.xor(recv_reg, concat_arg_reg)
- asm.test(recv_reg, C::RUBY_ENCODING_MASK)
-
- # Push once, use the resulting operand in both branches below.
- stack_ret = ctx.stack_push(Type::TString)
-
- enc_mismatch = asm.new_label('enc_mismatch')
- asm.jnz(enc_mismatch)
-
- # If encodings match, call the simple append function and jump to return
- asm.mov(C_ARGS[0], recv)
- asm.mov(C_ARGS[1], concat_arg)
- asm.call(C.rjit_str_simple_append)
- ret_label = asm.new_label('func_return')
- asm.mov(stack_ret, C_RET)
- asm.jmp(ret_label)
-
- # If encodings are different, use a slower encoding-aware concatenate
- asm.write_label(enc_mismatch)
- asm.mov(C_ARGS[0], recv)
- asm.mov(C_ARGS[1], concat_arg)
- asm.call(C.rb_str_buf_append)
- asm.mov(stack_ret, C_RET)
- # Drop through to return
-
- asm.write_label(ret_label)
-
- true
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_rb_str_uplus(jit, ctx, asm, argc, _known_recv_class)
- if argc != 0
- return false
- end
-
- # We allocate when we dup the string
- jit_prepare_routine_call(jit, ctx, asm)
-
- asm.comment('Unary plus on string')
- asm.mov(:rax, ctx.stack_pop(1)) # recv_opnd
- asm.mov(:rcx, [:rax, C.RBasic.offsetof(:flags)]) # flags_opnd
- asm.test(:rcx, C::RUBY_FL_FREEZE)
-
- ret_label = asm.new_label('stack_ret')
-
- # String#+@ can only exist on T_STRING
- stack_ret = ctx.stack_push(Type::TString)
-
- # If the string isn't frozen, we just return it.
- asm.mov(stack_ret, :rax) # recv_opnd
- asm.jz(ret_label)
-
- # Str is frozen - duplicate it
- asm.mov(C_ARGS[0], :rax) # recv_opnd
- asm.call(C.rb_str_dup)
- asm.mov(stack_ret, C_RET)
-
- asm.write_label(ret_label)
-
- true
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_rb_str_getbyte(jit, ctx, asm, argc, _known_recv_class)
- return false if argc != 1
- asm.comment('rb_str_getbyte')
-
- index_opnd = ctx.stack_pop
- str_opnd = ctx.stack_pop
- asm.mov(C_ARGS[0], str_opnd)
- asm.mov(C_ARGS[1], index_opnd)
- asm.call(C.rb_str_getbyte)
-
- ret_opnd = ctx.stack_push(Type::Fixnum)
- asm.mov(ret_opnd, C_RET)
- true
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_rb_ary_empty_p(jit, ctx, asm, argc, _known_recv_class)
- array_reg = :rax
- asm.mov(array_reg, ctx.stack_pop(1))
- jit_array_len(asm, array_reg, :rcx)
-
- asm.test(:rcx, :rcx)
- asm.mov(:rax, Qfalse)
- asm.mov(:rcx, Qtrue)
- asm.cmovz(:rax, :rcx)
-
- out_opnd = ctx.stack_push(Type::UnknownImm)
- asm.mov(out_opnd, :rax)
-
- return true
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_rb_ary_push(jit, ctx, asm, argc, _known_recv_class)
- return false if argc != 1
- asm.comment('rb_ary_push')
-
- jit_prepare_routine_call(jit, ctx, asm)
-
- item_opnd = ctx.stack_pop
- ary_opnd = ctx.stack_pop
- asm.mov(C_ARGS[0], ary_opnd)
- asm.mov(C_ARGS[1], item_opnd)
- asm.call(C.rb_ary_push)
-
- ret_opnd = ctx.stack_push(Type::TArray)
- asm.mov(ret_opnd, C_RET)
- true
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_obj_respond_to(jit, ctx, asm, argc, known_recv_class)
- # respond_to(:sym) or respond_to(:sym, true)
- if argc != 1 && argc != 2
- return false
- end
-
- if known_recv_class.nil?
- return false
- end
-
- recv_class = known_recv_class
-
- # Get the method_id from compile time. We will later add a guard against it.
- mid_sym = jit.peek_at_stack(argc - 1)
- unless static_symbol?(mid_sym)
- return false
- end
- mid = C.rb_sym2id(mid_sym)
-
- # This represents the value of the "include_all" argument and whether it's known
- allow_priv = if argc == 1
- # Default is false
- false
- else
- # Get value from type information (may or may not be known)
- ctx.get_opnd_type(StackOpnd[0]).known_truthy
- end
-
- target_cme = C.rb_callable_method_entry_or_negative(recv_class, mid)
-
- # Should never be null, as in that case we will be returned a "negative CME"
- assert_equal(false, target_cme.nil?)
-
- cme_def_type = C.UNDEFINED_METHOD_ENTRY_P(target_cme) ? C::VM_METHOD_TYPE_UNDEF : target_cme.def.type
-
- if cme_def_type == C::VM_METHOD_TYPE_REFINED
- return false
- end
-
- visibility = if cme_def_type == C::VM_METHOD_TYPE_UNDEF
- C::METHOD_VISI_UNDEF
- else
- C.METHOD_ENTRY_VISI(target_cme)
- end
-
- result =
- case [visibility, allow_priv]
- in C::METHOD_VISI_UNDEF, _ then Qfalse # No method => false
- in C::METHOD_VISI_PUBLIC, _ then Qtrue # Public method => true regardless of include_all
- in _, true then Qtrue # include_all => always true
- else return false # not public and include_all not known, can't compile
- end
-
- if result != Qtrue
- # Only if respond_to_missing? hasn't been overridden
- # In the future, we might want to jit the call to respond_to_missing?
- unless Invariants.assume_method_basic_definition(jit, recv_class, C.idRespond_to_missing)
- return false
- end
- end
-
- # Invalidate this block if method lookup changes for the method being queried. This works
- # both for the case where a method does or does not exist, as for the latter we asked for a
- # "negative CME" earlier.
- Invariants.assume_method_lookup_stable(jit, target_cme)
-
- # Generate a side exit
- side_exit = side_exit(jit, ctx)
-
- if argc == 2
- # pop include_all argument (we only use its type info)
- ctx.stack_pop(1)
- end
-
- sym_opnd = ctx.stack_pop(1)
- _recv_opnd = ctx.stack_pop(1)
-
- # This is necessary because we have no guarantee that sym_opnd is a constant
- asm.comment('guard known mid')
- asm.mov(:rax, to_value(mid_sym))
- asm.cmp(sym_opnd, :rax)
- asm.jne(side_exit)
-
- putobject(jit, ctx, asm, val: result)
-
- true
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_rb_f_block_given_p(jit, ctx, asm, argc, _known_recv_class)
- asm.comment('block_given?')
-
- # Same as rb_vm_frame_block_handler
- jit_get_lep(jit, asm, reg: :rax)
- asm.mov(:rax, [:rax, C.VALUE.size * C::VM_ENV_DATA_INDEX_SPECVAL]) # block_handler
-
- ctx.stack_pop(1)
- out_opnd = ctx.stack_push(Type::UnknownImm)
-
- # Return `block_handler != VM_BLOCK_HANDLER_NONE`
- asm.cmp(:rax, C::VM_BLOCK_HANDLER_NONE)
- asm.mov(:rax, Qfalse)
- asm.mov(:rcx, Qtrue)
- asm.cmovne(:rax, :rcx) # block_given
- asm.mov(out_opnd, :rax)
-
- true
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_thread_s_current(jit, ctx, asm, argc, _known_recv_class)
- return false if argc != 0
- asm.comment('Thread.current')
- ctx.stack_pop(1)
-
- # ec->thread_ptr
- asm.mov(:rax, [EC, C.rb_execution_context_t.offsetof(:thread_ptr)])
-
- # thread->self
- asm.mov(:rax, [:rax, C.rb_thread_struct.offsetof(:self)])
-
- stack_ret = ctx.stack_push(Type::UnknownHeap)
- asm.mov(stack_ret, :rax)
- true
- end
-
- #
- # Helpers
- #
-
- def register_cfunc_codegen_funcs
- # Specialization for C methods. See register_cfunc_method for details.
- register_cfunc_method(BasicObject, :!, :jit_rb_obj_not)
-
- register_cfunc_method(NilClass, :nil?, :jit_rb_true)
- register_cfunc_method(Kernel, :nil?, :jit_rb_false)
- register_cfunc_method(Kernel, :is_a?, :jit_rb_kernel_is_a)
- register_cfunc_method(Kernel, :kind_of?, :jit_rb_kernel_is_a)
- register_cfunc_method(Kernel, :instance_of?, :jit_rb_kernel_instance_of)
-
- register_cfunc_method(BasicObject, :==, :jit_rb_obj_equal)
- register_cfunc_method(BasicObject, :equal?, :jit_rb_obj_equal)
- register_cfunc_method(BasicObject, :!=, :jit_rb_obj_not_equal)
- register_cfunc_method(Kernel, :eql?, :jit_rb_obj_equal)
- register_cfunc_method(Module, :==, :jit_rb_obj_equal)
- register_cfunc_method(Module, :===, :jit_rb_mod_eqq)
- register_cfunc_method(Symbol, :==, :jit_rb_obj_equal)
- register_cfunc_method(Symbol, :===, :jit_rb_obj_equal)
- register_cfunc_method(Integer, :==, :jit_rb_int_equal)
- register_cfunc_method(Integer, :===, :jit_rb_int_equal)
-
- # rb_str_to_s() methods in string.c
- register_cfunc_method(String, :empty?, :jit_rb_str_empty_p)
- register_cfunc_method(String, :to_s, :jit_rb_str_to_s)
- register_cfunc_method(String, :to_str, :jit_rb_str_to_s)
- register_cfunc_method(String, :bytesize, :jit_rb_str_bytesize)
- register_cfunc_method(String, :<<, :jit_rb_str_concat)
- register_cfunc_method(String, :+@, :jit_rb_str_uplus)
-
- # rb_ary_empty_p() method in array.c
- register_cfunc_method(Array, :empty?, :jit_rb_ary_empty_p)
-
- register_cfunc_method(Kernel, :respond_to?, :jit_obj_respond_to)
- register_cfunc_method(Kernel, :block_given?, :jit_rb_f_block_given_p)
-
- # Thread.current
- register_cfunc_method(C.rb_singleton_class(Thread), :current, :jit_thread_s_current)
-
- #---
- register_cfunc_method(Array, :<<, :jit_rb_ary_push)
- register_cfunc_method(Integer, :*, :jit_rb_int_mul)
- register_cfunc_method(Integer, :/, :jit_rb_int_div)
- register_cfunc_method(Integer, :[], :jit_rb_int_aref)
- register_cfunc_method(String, :getbyte, :jit_rb_str_getbyte)
- end
-
- def register_cfunc_method(klass, mid_sym, func)
- mid = C.rb_intern(mid_sym.to_s)
- me = C.rb_method_entry_at(klass, mid)
-
- assert_equal(false, me.nil?)
-
- # Only cfuncs are supported
- method_serial = me.def.method_serial
-
- @cfunc_codegen_table[method_serial] = method(func)
- end
-
- def lookup_cfunc_codegen(cme_def)
- @cfunc_codegen_table[cme_def.method_serial]
- end
-
- def stack_swap(_jit, ctx, asm, offset0, offset1)
- stack0_mem = ctx.stack_opnd(offset0)
- stack1_mem = ctx.stack_opnd(offset1)
-
- mapping0 = ctx.get_opnd_mapping(StackOpnd[offset0])
- mapping1 = ctx.get_opnd_mapping(StackOpnd[offset1])
-
- asm.mov(:rax, stack0_mem)
- asm.mov(:rcx, stack1_mem)
- asm.mov(stack0_mem, :rcx)
- asm.mov(stack1_mem, :rax)
-
- ctx.set_opnd_mapping(StackOpnd[offset0], mapping1)
- ctx.set_opnd_mapping(StackOpnd[offset1], mapping0)
- end
-
- def jit_getlocal_generic(jit, ctx, asm, idx:, level:)
- # Load environment pointer EP (level 0) from CFP
- ep_reg = :rax
- jit_get_ep(asm, level, reg: ep_reg)
-
- # Load the local from the block
- # val = *(vm_get_ep(GET_EP(), level) - idx);
- asm.mov(:rax, [ep_reg, -idx * C.VALUE.size])
-
- # Write the local at SP
- stack_top = if level == 0
- local_idx = ep_offset_to_local_idx(jit.iseq, idx)
- ctx.stack_push_local(local_idx)
- else
- ctx.stack_push(Type::Unknown)
- end
-
- asm.mov(stack_top, :rax)
- KeepCompiling
- end
-
- def jit_setlocal_generic(jit, ctx, asm, idx:, level:)
- value_type = ctx.get_opnd_type(StackOpnd[0])
-
- # Load environment pointer EP at level
- ep_reg = :rax
- jit_get_ep(asm, level, reg: ep_reg)
-
- # Write barriers may be required when VM_ENV_FLAG_WB_REQUIRED is set, however write barriers
- # only affect heap objects being written. If we know an immediate value is being written we
- # can skip this check.
- unless value_type.imm?
- # flags & VM_ENV_FLAG_WB_REQUIRED
- flags_opnd = [ep_reg, C.VALUE.size * C::VM_ENV_DATA_INDEX_FLAGS]
- asm.test(flags_opnd, C::VM_ENV_FLAG_WB_REQUIRED)
-
- # if (flags & VM_ENV_FLAG_WB_REQUIRED) != 0
- asm.jnz(side_exit(jit, ctx))
- end
-
- if level == 0
- local_idx = ep_offset_to_local_idx(jit.iseq, idx)
- ctx.set_local_type(local_idx, value_type)
- end
-
- # Pop the value to write from the stack
- stack_top = ctx.stack_pop(1)
-
- # Write the value at the environment pointer
- asm.mov(:rcx, stack_top)
- asm.mov([ep_reg, -(C.VALUE.size * idx)], :rcx)
-
- KeepCompiling
- end
-
- # Compute the index of a local variable from its slot index
- def ep_offset_to_local_idx(iseq, ep_offset)
- # Layout illustration
- # This is an array of VALUE
- # | VM_ENV_DATA_SIZE |
- # v v
- # low addr <+-------+-------+-------+-------+------------------+
- # |local 0|local 1| ... |local n| .... |
- # +-------+-------+-------+-------+------------------+
- # ^ ^ ^ ^
- # +-------+---local_table_size----+ cfp->ep--+
- # | |
- # +------------------ep_offset---------------+
- #
- # See usages of local_var_name() from iseq.c for similar calculation.
-
- # Equivalent of iseq->body->local_table_size
- local_table_size = iseq.body.local_table_size
- op = ep_offset - C::VM_ENV_DATA_SIZE
- local_idx = local_table_size - op - 1
- assert_equal(true, local_idx >= 0 && local_idx < local_table_size)
- local_idx
- end
-
- # Compute the index of a local variable from its slot index
- def slot_to_local_idx(iseq, slot_idx)
- # Layout illustration
- # This is an array of VALUE
- # | VM_ENV_DATA_SIZE |
- # v v
- # low addr <+-------+-------+-------+-------+------------------+
- # |local 0|local 1| ... |local n| .... |
- # +-------+-------+-------+-------+------------------+
- # ^ ^ ^ ^
- # +-------+---local_table_size----+ cfp->ep--+
- # | |
- # +------------------slot_idx----------------+
- #
- # See usages of local_var_name() from iseq.c for similar calculation.
-
- local_table_size = iseq.body.local_table_size
- op = slot_idx - C::VM_ENV_DATA_SIZE
- local_table_size - op - 1
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def guard_object_is_heap(jit, ctx, asm, object, object_opnd, counter = nil)
- object_type = ctx.get_opnd_type(object_opnd)
- if object_type.heap?
- return
- end
-
- side_exit = side_exit(jit, ctx)
- side_exit = counted_exit(side_exit, counter) if counter
-
- asm.comment('guard object is heap')
- # Test that the object is not an immediate
- asm.test(object, C::RUBY_IMMEDIATE_MASK)
- asm.jnz(side_exit)
-
- # Test that the object is not false
- asm.cmp(object, Qfalse)
- asm.je(side_exit)
-
- if object_type.diff(Type::UnknownHeap) != TypeDiff::Incompatible
- ctx.upgrade_opnd_type(object_opnd, Type::UnknownHeap)
- end
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def guard_object_is_array(jit, ctx, asm, object_reg, flags_reg, object_opnd, counter = nil)
- object_type = ctx.get_opnd_type(object_opnd)
- if object_type.array?
- return
- end
-
- guard_object_is_heap(jit, ctx, asm, object_reg, object_opnd, counter)
-
- side_exit = side_exit(jit, ctx)
- side_exit = counted_exit(side_exit, counter) if counter
-
- asm.comment('guard object is array')
- # Pull out the type mask
- asm.mov(flags_reg, [object_reg, C.RBasic.offsetof(:flags)])
- asm.and(flags_reg, C::RUBY_T_MASK)
-
- # Compare the result with T_ARRAY
- asm.cmp(flags_reg, C::RUBY_T_ARRAY)
- asm.jne(side_exit)
-
- if object_type.diff(Type::TArray) != TypeDiff::Incompatible
- ctx.upgrade_opnd_type(object_opnd, Type::TArray)
- end
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def guard_object_is_string(jit, ctx, asm, object_reg, flags_reg, object_opnd, counter = nil)
- object_type = ctx.get_opnd_type(object_opnd)
- if object_type.string?
- return
- end
-
- guard_object_is_heap(jit, ctx, asm, object_reg, object_opnd, counter)
-
- side_exit = side_exit(jit, ctx)
- side_exit = counted_exit(side_exit, counter) if counter
-
- asm.comment('guard object is string')
- # Pull out the type mask
- asm.mov(flags_reg, [object_reg, C.RBasic.offsetof(:flags)])
- asm.and(flags_reg, C::RUBY_T_MASK)
-
- # Compare the result with T_STRING
- asm.cmp(flags_reg, C::RUBY_T_STRING)
- asm.jne(side_exit)
-
- if object_type.diff(Type::TString) != TypeDiff::Incompatible
- ctx.upgrade_opnd_type(object_opnd, Type::TString)
- end
- end
-
- # clobbers object_reg
- def guard_object_is_not_ruby2_keyword_hash(asm, object_reg, flags_reg, side_exit)
- asm.comment('guard object is not ruby2 keyword hash')
-
- not_ruby2_keyword = asm.new_label('not_ruby2_keyword')
- asm.test(object_reg, C::RUBY_IMMEDIATE_MASK)
- asm.jnz(not_ruby2_keyword)
-
- asm.cmp(object_reg, Qfalse)
- asm.je(not_ruby2_keyword)
-
- asm.mov(flags_reg, [object_reg, C.RBasic.offsetof(:flags)])
- type_reg = object_reg
- asm.mov(type_reg, flags_reg)
- asm.and(type_reg, C::RUBY_T_MASK)
-
- asm.cmp(type_reg, C::RUBY_T_HASH)
- asm.jne(not_ruby2_keyword)
-
- asm.test(flags_reg, C::RHASH_PASS_AS_KEYWORDS)
- asm.jnz(side_exit)
-
- asm.write_label(not_ruby2_keyword)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_chain_guard(opcode, jit, ctx, asm, side_exit, limit: 20)
- opcode => :je | :jne | :jnz | :jz
-
- if ctx.chain_depth < limit
- deeper = ctx.dup
- deeper.chain_depth += 1
-
- branch_stub = BranchStub.new(
- iseq: jit.iseq,
- shape: Default,
- target0: BranchTarget.new(ctx: deeper, pc: jit.pc),
- )
- branch_stub.target0.address = Assembler.new.then do |ocb_asm|
- @exit_compiler.compile_branch_stub(deeper, ocb_asm, branch_stub, true)
- @ocb.write(ocb_asm)
- end
- branch_stub.compile = compile_jit_chain_guard(branch_stub, opcode:)
- branch_stub.compile.call(asm)
- else
- asm.public_send(opcode, side_exit)
- end
- end
-
- def compile_jit_chain_guard(branch_stub, opcode:) # Proc escapes arguments in memory
- proc do |branch_asm|
- # Not using `asm.comment` here since it's usually put before cmp/test before this.
- branch_asm.stub(branch_stub) do
- case branch_stub.shape
- in Default
- branch_asm.public_send(opcode, branch_stub.target0.address)
- end
- end
- end
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_guard_known_klass(jit, ctx, asm, known_klass, obj_opnd, insn_opnd, comptime_obj, side_exit, limit: 10)
- # Only memory operand is supported for now
- assert_equal(true, obj_opnd.is_a?(Array))
-
- known_klass = C.to_value(known_klass)
- val_type = ctx.get_opnd_type(insn_opnd)
- if val_type.known_class == known_klass
- # We already know from type information that this is a match
- return
- end
-
- # Touching this as Ruby could crash for FrozenCore
- if known_klass == C.rb_cNilClass
- assert(!val_type.heap?)
- assert(val_type.unknown?)
-
- asm.comment('guard object is nil')
- asm.cmp(obj_opnd, Qnil)
- jit_chain_guard(:jne, jit, ctx, asm, side_exit, limit:)
-
- ctx.upgrade_opnd_type(insn_opnd, Type::Nil)
- elsif known_klass == C.rb_cTrueClass
- assert(!val_type.heap?)
- assert(val_type.unknown?)
-
- asm.comment('guard object is true')
- asm.cmp(obj_opnd, Qtrue)
- jit_chain_guard(:jne, jit, ctx, asm, side_exit, limit:)
-
- ctx.upgrade_opnd_type(insn_opnd, Type::True)
- elsif known_klass == C.rb_cFalseClass
- assert(!val_type.heap?)
- assert(val_type.unknown?)
-
- asm.comment('guard object is false')
- asm.cmp(obj_opnd, Qfalse)
- jit_chain_guard(:jne, jit, ctx, asm, side_exit, limit:)
-
- ctx.upgrade_opnd_type(insn_opnd, Type::False)
- elsif known_klass == C.rb_cInteger && fixnum?(comptime_obj)
- # We will guard fixnum and bignum as though they were separate classes
- # BIGNUM can be handled by the general else case below
- assert(val_type.unknown?)
-
- asm.comment('guard object is fixnum')
- asm.test(obj_opnd, C::RUBY_FIXNUM_FLAG)
- jit_chain_guard(:jz, jit, ctx, asm, side_exit, limit:)
-
- ctx.upgrade_opnd_type(insn_opnd, Type::Fixnum)
- elsif known_klass == C.rb_cSymbol && static_symbol?(comptime_obj)
- assert(!val_type.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::ImmSymbol || !val_type.imm?
- assert(val_type.unknown?)
-
- asm.comment('guard object is static symbol')
- assert_equal(8, C::RUBY_SPECIAL_SHIFT)
- asm.cmp(BytePtr[*obj_opnd], C::RUBY_SYMBOL_FLAG)
- jit_chain_guard(:jne, jit, ctx, asm, side_exit, limit:)
-
- ctx.upgrade_opnd_type(insn_opnd, Type::ImmSymbol)
- end
- elsif known_klass == C.rb_cFloat && flonum?(comptime_obj)
- assert(!val_type.heap?)
- if val_type != Type::Flonum || !val_type.imm?
- assert(val_type.unknown?)
-
- # We will guard flonum vs heap float as though they were separate classes
- asm.comment('guard object is flonum')
- asm.mov(:rax, obj_opnd)
- asm.and(:rax, C::RUBY_FLONUM_MASK)
- asm.cmp(:rax, C::RUBY_FLONUM_FLAG)
- jit_chain_guard(:jne, jit, ctx, asm, side_exit, limit:)
-
- ctx.upgrade_opnd_type(insn_opnd, Type::Flonum)
- end
- elsif C.RCLASS_SINGLETON_P(known_klass) && comptime_obj == C.rb_class_attached_object(known_klass)
- # 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.
- asm.comment('guard known object with singleton class')
- asm.mov(:rax, to_value(comptime_obj))
- asm.cmp(obj_opnd, :rax)
- jit_chain_guard(:jne, jit, ctx, asm, side_exit, limit:)
- elsif val_type == Type::CString && known_klass == C.rb_cString
- # guard elided because the context says we've already checked
- assert_equal(C.to_value(C.rb_class_of(comptime_obj)), C.rb_cString)
- else
- assert(!val_type.imm?)
-
- # Load memory to a register
- asm.mov(:rax, obj_opnd)
- obj_opnd = :rax
-
- # Check that the receiver is a heap object
- # Note: if we get here, the class doesn't have immediate instances.
- unless val_type.heap?
- asm.comment('guard not immediate')
- asm.test(obj_opnd, C::RUBY_IMMEDIATE_MASK)
- jit_chain_guard(:jnz, jit, ctx, asm, side_exit, limit:)
- asm.cmp(obj_opnd, Qfalse)
- jit_chain_guard(:je, jit, ctx, asm, side_exit, limit:)
- end
-
- # Bail if receiver class is different from known_klass
- klass_opnd = [obj_opnd, C.RBasic.offsetof(:klass)]
- asm.comment("guard known class #{known_klass}")
- asm.mov(:rcx, known_klass)
- asm.cmp(klass_opnd, :rcx)
- jit_chain_guard(:jne, jit, ctx, asm, side_exit, limit:)
-
- if known_klass == C.rb_cString
- # Upgrading to Type::CString here is incorrect.
- # The guard we put only checks RBASIC_CLASS(obj),
- # which adding a singleton class can change. We
- # additionally need to know the string is frozen
- # to claim Type::CString.
- ctx.upgrade_opnd_type(insn_opnd, Type::TString)
- elsif known_klass == C.rb_cArray
- ctx.upgrade_opnd_type(insn_opnd, Type::TArray)
- end
- end
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- def two_fixnums_on_stack?(jit)
- comptime_recv = jit.peek_at_stack(1)
- comptime_arg = jit.peek_at_stack(0)
- return fixnum?(comptime_recv) && fixnum?(comptime_arg)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def guard_two_fixnums(jit, ctx, asm)
- # Get stack operands without popping them
- arg1 = ctx.stack_opnd(0)
- arg0 = ctx.stack_opnd(1)
-
- # Get the stack operand types
- arg1_type = ctx.get_opnd_type(StackOpnd[0])
- arg0_type = ctx.get_opnd_type(StackOpnd[1])
-
- if arg0_type.heap? || arg1_type.heap?
- asm.comment('arg is heap object')
- asm.jmp(side_exit(jit, ctx))
- return
- end
-
- if arg0_type != Type::Fixnum && arg0_type.specific?
- asm.comment('arg0 not fixnum')
- asm.jmp(side_exit(jit, ctx))
- return
- end
-
- if arg1_type != Type::Fixnum && arg1_type.specific?
- asm.comment('arg1 not fixnum')
- asm.jmp(side_exit(jit, ctx))
- return
- end
-
- assert(!arg0_type.heap?)
- assert(!arg1_type.heap?)
- assert(arg0_type == Type::Fixnum || arg0_type.unknown?)
- assert(arg1_type == Type::Fixnum || arg1_type.unknown?)
-
- # If not fixnums at run-time, fall back
- if arg0_type != Type::Fixnum
- asm.comment('guard arg0 fixnum')
- asm.test(arg0, C::RUBY_FIXNUM_FLAG)
- jit_chain_guard(:jz, jit, ctx, asm, side_exit(jit, ctx))
- end
- if arg1_type != Type::Fixnum
- asm.comment('guard arg1 fixnum')
- asm.test(arg1, C::RUBY_FIXNUM_FLAG)
- jit_chain_guard(:jz, jit, ctx, asm, side_exit(jit, ctx))
- end
-
- # Set stack types in context
- ctx.upgrade_opnd_type(StackOpnd[0], Type::Fixnum)
- ctx.upgrade_opnd_type(StackOpnd[1], Type::Fixnum)
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_fixnum_cmp(jit, ctx, asm, opcode:, bop:)
- opcode => :cmovl | :cmovle | :cmovg | :cmovge
-
- unless jit.at_current_insn?
- defer_compilation(jit, ctx, asm)
- return EndBlock
- end
-
- comptime_recv = jit.peek_at_stack(1)
- comptime_obj = jit.peek_at_stack(0)
-
- if fixnum?(comptime_recv) && fixnum?(comptime_obj)
- unless Invariants.assume_bop_not_redefined(jit, C::INTEGER_REDEFINED_OP_FLAG, bop)
- return CantCompile
- end
-
- # Check that both operands are fixnums
- guard_two_fixnums(jit, ctx, asm)
-
- obj_opnd = ctx.stack_pop
- recv_opnd = ctx.stack_pop
-
- asm.mov(:rax, obj_opnd)
- asm.cmp(recv_opnd, :rax)
- asm.mov(:rax, Qfalse)
- asm.mov(:rcx, Qtrue)
- asm.public_send(opcode, :rax, :rcx)
-
- dst_opnd = ctx.stack_push(Type::UnknownImm)
- asm.mov(dst_opnd, :rax)
-
- KeepCompiling
- else
- opt_send_without_block(jit, ctx, asm)
- end
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_equality_specialized(jit, ctx, asm, gen_eq)
- # Create a side-exit to fall back to the interpreter
- side_exit = side_exit(jit, ctx)
-
- a_opnd = ctx.stack_opnd(1)
- b_opnd = ctx.stack_opnd(0)
-
- comptime_a = jit.peek_at_stack(1)
- comptime_b = jit.peek_at_stack(0)
-
- if two_fixnums_on_stack?(jit)
- unless Invariants.assume_bop_not_redefined(jit, C::INTEGER_REDEFINED_OP_FLAG, C::BOP_EQ)
- return false
- end
-
- guard_two_fixnums(jit, ctx, asm)
-
- asm.comment('check fixnum equality')
- asm.mov(:rax, a_opnd)
- asm.mov(:rcx, b_opnd)
- asm.cmp(:rax, :rcx)
- asm.mov(:rax, gen_eq ? Qfalse : Qtrue)
- asm.mov(:rcx, gen_eq ? Qtrue : Qfalse)
- asm.cmove(:rax, :rcx)
-
- # Push the output on the stack
- ctx.stack_pop(2)
- dst = ctx.stack_push(Type::UnknownImm)
- asm.mov(dst, :rax)
-
- true
- elsif C.rb_class_of(comptime_a) == String && C.rb_class_of(comptime_b) == String
- unless Invariants.assume_bop_not_redefined(jit, C::STRING_REDEFINED_OP_FLAG, C::BOP_EQ)
- # if overridden, emit the generic version
- return false
- end
-
- # Guard that a is a String
- jit_guard_known_klass(jit, ctx, asm, C.rb_class_of(comptime_a), a_opnd, StackOpnd[1], comptime_a, side_exit)
-
- equal_label = asm.new_label(:equal)
- ret_label = asm.new_label(:ret)
-
- # If they are equal by identity, return true
- asm.mov(:rax, a_opnd)
- asm.mov(:rcx, b_opnd)
- asm.cmp(:rax, :rcx)
- asm.je(equal_label)
-
- # Otherwise guard that b is a T_STRING (from type info) or String (from runtime guard)
- btype = ctx.get_opnd_type(StackOpnd[0])
- unless btype.string?
- # Note: any T_STRING is valid here, but we check for a ::String for simplicity
- # To pass a mutable static variable (rb_cString) requires an unsafe block
- jit_guard_known_klass(jit, ctx, asm, C.rb_class_of(comptime_b), b_opnd, StackOpnd[0], comptime_b, side_exit)
- end
-
- asm.comment('call rb_str_eql_internal')
- asm.mov(C_ARGS[0], a_opnd)
- asm.mov(C_ARGS[1], b_opnd)
- asm.call(gen_eq ? C.rb_str_eql_internal : C.rjit_str_neq_internal)
-
- # Push the output on the stack
- ctx.stack_pop(2)
- dst = ctx.stack_push(Type::UnknownImm)
- asm.mov(dst, C_RET)
- asm.jmp(ret_label)
-
- asm.write_label(equal_label)
- asm.mov(dst, gen_eq ? Qtrue : Qfalse)
-
- asm.write_label(ret_label)
-
- true
- else
- false
- end
- end
-
- # NOTE: This clobbers :rax
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_prepare_routine_call(jit, ctx, asm)
- jit.record_boundary_patch_point = true
- jit_save_pc(jit, asm)
- jit_save_sp(ctx, asm)
-
- # In case the routine calls Ruby methods, it can set local variables
- # through Kernel#binding and other means.
- ctx.clear_local_types
- end
-
- # NOTE: This clobbers :rax
- # @param jit [RubyVM::RJIT::JITState]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_save_pc(jit, asm, comment: 'save PC to CFP')
- next_pc = jit.pc + jit.insn.len * C.VALUE.size # Use the next one for backtrace and side exits
- asm.comment(comment)
- asm.mov(:rax, next_pc)
- asm.mov([CFP, C.rb_control_frame_t.offsetof(:pc)], :rax)
- end
-
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_save_sp(ctx, asm)
- if ctx.sp_offset != 0
- asm.comment('save SP to CFP')
- asm.lea(SP, ctx.sp_opnd)
- asm.mov([CFP, C.rb_control_frame_t.offsetof(:sp)], SP)
- ctx.sp_offset = 0
- end
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jump_to_next_insn(jit, ctx, asm)
- reset_depth = ctx.dup
- reset_depth.chain_depth = 0
-
- next_pc = jit.pc + jit.insn.len * C.VALUE.size
-
- # We are at the end of the current instruction. Record the boundary.
- if jit.record_boundary_patch_point
- exit_pos = Assembler.new.then do |ocb_asm|
- @exit_compiler.compile_side_exit(next_pc, ctx, ocb_asm)
- @ocb.write(ocb_asm)
- end
- Invariants.record_global_inval_patch(asm, exit_pos)
- jit.record_boundary_patch_point = false
- end
-
- jit_direct_jump(jit.iseq, next_pc, reset_depth, asm, comment: 'jump_to_next_insn')
- end
-
- # rb_vm_check_ints
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_check_ints(jit, ctx, asm)
- asm.comment('RUBY_VM_CHECK_INTS(ec)')
- asm.mov(:eax, DwordPtr[EC, C.rb_execution_context_t.offsetof(:interrupt_flag)])
- asm.test(:eax, :eax)
- asm.jnz(side_exit(jit, ctx))
- end
-
- # See get_lvar_level in compile.c
- def get_lvar_level(iseq)
- level = 0
- while iseq.to_i != iseq.body.local_iseq.to_i
- level += 1
- iseq = iseq.body.parent_iseq
- end
- return level
- end
-
- # GET_LEP
- # @param jit [RubyVM::RJIT::JITState]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_get_lep(jit, asm, reg:)
- level = get_lvar_level(jit.iseq)
- jit_get_ep(asm, level, reg:)
- end
-
- # vm_get_ep
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_get_ep(asm, level, reg:)
- asm.mov(reg, [CFP, C.rb_control_frame_t.offsetof(:ep)])
- level.times do
- # GET_PREV_EP: ep[VM_ENV_DATA_INDEX_SPECVAL] & ~0x03
- asm.mov(reg, [reg, C.VALUE.size * C::VM_ENV_DATA_INDEX_SPECVAL])
- asm.and(reg, ~0x03)
- end
- end
-
- # vm_getivar
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_getivar(jit, ctx, asm, comptime_obj, ivar_id, obj_opnd, obj_yarv_opnd)
- side_exit = side_exit(jit, ctx)
- starting_ctx = ctx.dup # copy for jit_chain_guard
-
- # Guard not special const
- if C::SPECIAL_CONST_P(comptime_obj)
- asm.incr_counter(:getivar_special_const)
- return CantCompile
- end
-
- case C::BUILTIN_TYPE(comptime_obj)
- when C::T_OBJECT
- # This is the only supported case for now (ROBJECT_IVPTR)
- else
- # General case. Call rb_ivar_get().
- # VALUE rb_ivar_get(VALUE obj, ID id)
- asm.comment('call rb_ivar_get()')
- asm.mov(C_ARGS[0], obj_opnd ? obj_opnd : [CFP, C.rb_control_frame_t.offsetof(:self)])
- asm.mov(C_ARGS[1], ivar_id)
-
- # The function could raise exceptions.
- jit_prepare_routine_call(jit, ctx, asm) # clobbers obj_opnd and :rax
-
- asm.call(C.rb_ivar_get)
-
- if obj_opnd # attr_reader
- ctx.stack_pop
- end
-
- # Push the ivar on the stack
- out_opnd = ctx.stack_push(Type::Unknown)
- asm.mov(out_opnd, C_RET)
-
- # Jump to next instruction. This allows guard chains to share the same successor.
- jump_to_next_insn(jit, ctx, asm)
- return EndBlock
- end
-
- asm.mov(:rax, obj_opnd ? obj_opnd : [CFP, C.rb_control_frame_t.offsetof(:self)])
- guard_object_is_heap(jit, ctx, asm, :rax, obj_yarv_opnd, :getivar_not_heap)
-
- shape_id = C.rb_shape_get_shape_id(comptime_obj)
- if shape_id == C::OBJ_TOO_COMPLEX_SHAPE_ID
- asm.incr_counter(:getivar_too_complex)
- return CantCompile
- end
-
- asm.comment('guard shape')
- asm.cmp(DwordPtr[:rax, C.rb_shape_id_offset], shape_id)
- jit_chain_guard(:jne, jit, starting_ctx, asm, counted_exit(side_exit, :getivar_megamorphic))
-
- if obj_opnd
- ctx.stack_pop # pop receiver for attr_reader
- end
-
- index = C.rb_shape_get_iv_index(shape_id, ivar_id)
- # If there is no IVAR index, then the ivar was undefined
- # when we entered the compiler. That means we can just return
- # nil for this shape + iv name
- if index.nil?
- stack_opnd = ctx.stack_push(Type::Nil)
- val_opnd = Qnil
- else
- asm.comment('ROBJECT_IVPTR')
- if C::FL_TEST_RAW(comptime_obj, C::ROBJECT_EMBED)
- # Access embedded array
- asm.mov(:rax, [:rax, C.RObject.offsetof(:as, :ary) + (index * C.VALUE.size)])
- else
- # Pull out an ivar table on heap
- asm.mov(:rax, [:rax, C.RObject.offsetof(:as, :heap, :ivptr)])
- # Read the table
- asm.mov(:rax, [:rax, index * C.VALUE.size])
- end
- stack_opnd = ctx.stack_push(Type::Unknown)
- val_opnd = :rax
- end
- asm.mov(stack_opnd, val_opnd)
-
- # Let guard chains share the same successor
- jump_to_next_insn(jit, ctx, asm)
- EndBlock
- end
-
- def jit_write_iv(asm, comptime_receiver, recv_reg, temp_reg, ivar_index, set_value, needs_extension)
- # Compile time self is embedded and the ivar index lands within the object
- embed_test_result = C::FL_TEST_RAW(comptime_receiver, C::ROBJECT_EMBED) && !needs_extension
-
- if embed_test_result
- # Find the IV offset
- offs = C.RObject.offsetof(:as, :ary) + ivar_index * C.VALUE.size
-
- # Write the IV
- asm.comment('write IV')
- asm.mov(temp_reg, set_value)
- asm.mov([recv_reg, offs], temp_reg)
- else
- # Compile time value is *not* embedded.
-
- # Get a pointer to the extended table
- asm.mov(recv_reg, [recv_reg, C.RObject.offsetof(:as, :heap, :ivptr)])
-
- # Write the ivar in to the extended table
- asm.comment("write IV");
- asm.mov(temp_reg, set_value)
- asm.mov([recv_reg, C.VALUE.size * ivar_index], temp_reg)
- end
- end
-
- # vm_caller_setup_arg_block: Handle VM_CALL_ARGS_BLOCKARG cases.
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def guard_block_arg(jit, ctx, asm, calling)
- if calling.flags & C::VM_CALL_ARGS_BLOCKARG != 0
- block_arg_type = ctx.get_opnd_type(StackOpnd[0])
- case block_arg_type
- in Type::Nil
- calling.block_handler = C::VM_BLOCK_HANDLER_NONE
- in Type::BlockParamProxy
- calling.block_handler = C.rb_block_param_proxy
- else
- asm.incr_counter(:send_block_arg)
- return CantCompile
- end
- end
- end
-
- # vm_search_method
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_search_method(jit, ctx, asm, mid, calling)
- assert_equal(true, jit.at_current_insn?)
-
- # Generate a side exit
- side_exit = side_exit(jit, ctx)
-
- # kw_splat is not supported yet
- if calling.flags & C::VM_CALL_KW_SPLAT != 0
- asm.incr_counter(:send_kw_splat)
- return CantCompile
- end
-
- # Get a compile-time receiver and its class
- recv_idx = calling.argc + (calling.flags & C::VM_CALL_ARGS_BLOCKARG != 0 ? 1 : 0) # blockarg is not popped yet
- recv_idx += calling.send_shift
- comptime_recv = jit.peek_at_stack(recv_idx)
- comptime_recv_klass = C.rb_class_of(comptime_recv)
-
- # Guard the receiver class (part of vm_search_method_fastpath)
- recv_opnd = ctx.stack_opnd(recv_idx)
- megamorphic_exit = counted_exit(side_exit, :send_klass_megamorphic)
- jit_guard_known_klass(jit, ctx, asm, comptime_recv_klass, recv_opnd, StackOpnd[recv_idx], comptime_recv, megamorphic_exit)
-
- # Do method lookup (vm_cc_cme(cc) != NULL)
- cme = C.rb_callable_method_entry(comptime_recv_klass, mid)
- if cme.nil?
- asm.incr_counter(:send_missing_cme)
- return CantCompile # We don't support vm_call_method_name
- end
-
- # Invalidate on redefinition (part of vm_search_method_fastpath)
- Invariants.assume_method_lookup_stable(jit, cme)
-
- return cme, comptime_recv_klass
- end
-
- # vm_call_general
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_call_general(jit, ctx, asm, mid, calling, cme, known_recv_class)
- jit_call_method(jit, ctx, asm, mid, calling, cme, known_recv_class)
- end
-
- # vm_call_method
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- # @param send_shift [Integer] The number of shifts needed for VM_CALL_OPT_SEND
- def jit_call_method(jit, ctx, asm, mid, calling, cme, known_recv_class)
- # The main check of vm_call_method before vm_call_method_each_type
- case C::METHOD_ENTRY_VISI(cme)
- in C::METHOD_VISI_PUBLIC
- # You can always call public methods
- in C::METHOD_VISI_PRIVATE
- # Allow only callsites without a receiver
- if calling.flags & C::VM_CALL_FCALL == 0
- asm.incr_counter(:send_private)
- return CantCompile
- end
- in C::METHOD_VISI_PROTECTED
- # If the method call is an FCALL, it is always valid
- if calling.flags & C::VM_CALL_FCALL == 0
- # otherwise we need an ancestry check to ensure the receiver is valid to be called as protected
- jit_protected_callee_ancestry_guard(asm, cme, side_exit(jit, ctx))
- end
- end
-
- # Get a compile-time receiver
- recv_idx = calling.argc + (calling.flags & C::VM_CALL_ARGS_BLOCKARG != 0 ? 1 : 0) # blockarg is not popped yet
- recv_idx += calling.send_shift
- comptime_recv = jit.peek_at_stack(recv_idx)
- recv_opnd = ctx.stack_opnd(recv_idx)
-
- jit_call_method_each_type(jit, ctx, asm, calling, cme, comptime_recv, recv_opnd, known_recv_class)
- end
-
- # Generate ancestry guard for protected callee.
- # Calls to protected callees only go through when self.is_a?(klass_that_defines_the_callee).
- def jit_protected_callee_ancestry_guard(asm, cme, side_exit)
- # See vm_call_method().
- def_class = 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);
-
- asm.mov(C_ARGS[0], [CFP, C.rb_control_frame_t.offsetof(:self)])
- asm.mov(C_ARGS[1], to_value(def_class))
- asm.call(C.rb_obj_is_kind_of)
- asm.test(C_RET, C_RET)
- asm.jz(counted_exit(side_exit, :send_protected_check_failed))
- end
-
- # vm_call_method_each_type
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_call_method_each_type(jit, ctx, asm, calling, cme, comptime_recv, recv_opnd, known_recv_class)
- case cme.def.type
- in C::VM_METHOD_TYPE_ISEQ
- iseq = def_iseq_ptr(cme.def)
- jit_call_iseq(jit, ctx, asm, cme, calling, iseq)
- in C::VM_METHOD_TYPE_NOTIMPLEMENTED
- asm.incr_counter(:send_notimplemented)
- return CantCompile
- in C::VM_METHOD_TYPE_CFUNC
- jit_call_cfunc(jit, ctx, asm, cme, calling, known_recv_class:)
- in C::VM_METHOD_TYPE_ATTRSET
- jit_call_attrset(jit, ctx, asm, cme, calling, comptime_recv, recv_opnd)
- in C::VM_METHOD_TYPE_IVAR
- jit_call_ivar(jit, ctx, asm, cme, calling, comptime_recv, recv_opnd)
- in C::VM_METHOD_TYPE_MISSING
- asm.incr_counter(:send_missing)
- return CantCompile
- in C::VM_METHOD_TYPE_BMETHOD
- jit_call_bmethod(jit, ctx, asm, calling, cme, comptime_recv, recv_opnd, known_recv_class)
- in C::VM_METHOD_TYPE_ALIAS
- jit_call_alias(jit, ctx, asm, calling, cme, comptime_recv, recv_opnd, known_recv_class)
- in C::VM_METHOD_TYPE_OPTIMIZED
- jit_call_optimized(jit, ctx, asm, cme, calling, known_recv_class)
- in C::VM_METHOD_TYPE_UNDEF
- asm.incr_counter(:send_undef)
- return CantCompile
- in C::VM_METHOD_TYPE_ZSUPER
- asm.incr_counter(:send_zsuper)
- return CantCompile
- in C::VM_METHOD_TYPE_REFINED
- asm.incr_counter(:send_refined)
- return CantCompile
- end
- end
-
- # vm_call_iseq_setup
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_call_iseq(jit, ctx, asm, cme, calling, iseq, frame_type: nil, prev_ep: nil)
- argc = calling.argc
- flags = calling.flags
- send_shift = calling.send_shift
-
- # 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.
- doing_kw_call = iseq.body.param.flags.has_kw
- supplying_kws = flags & C::VM_CALL_KWARG != 0
-
- if flags & C::VM_CALL_TAILCALL != 0
- # We can't handle tailcalls
- asm.incr_counter(:send_tailcall)
- return CantCompile
- end
-
- # No support for callees with these parameters yet as they require allocation
- # or complex handling.
- if iseq.body.param.flags.has_post
- asm.incr_counter(:send_iseq_has_opt)
- return CantCompile
- end
- if iseq.body.param.flags.has_kwrest
- asm.incr_counter(:send_iseq_has_kwrest)
- return CantCompile
- end
-
- # In order to handle backwards compatibility between ruby 3 and 2
- # ruby2_keywords was introduced. It is called only on methods
- # with splat and changes they way they handle them.
- # We are just going to not compile these.
- # https://www.rubydoc.info/stdlib/core/Proc:ruby2_keywords
- if iseq.body.param.flags.ruby2_keywords && flags & C::VM_CALL_ARGS_SPLAT != 0
- asm.incr_counter(:send_iseq_ruby2_keywords)
- return CantCompile
- end
-
- iseq_has_rest = iseq.body.param.flags.has_rest
- if iseq_has_rest && calling.block_handler == :captured
- asm.incr_counter(:send_iseq_has_rest_and_captured)
- return CantCompile
- end
-
- if iseq_has_rest && iseq.body.param.flags.has_kw && supplying_kws
- asm.incr_counter(:send_iseq_has_rest_and_kw_supplied)
- return CantCompile
- end
-
- # 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
- asm.incr_counter(:send_iseq_has_no_kw)
- return CantCompile
- end
-
- # 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
- asm.incr_counter(:send_iseq_accepts_no_kwarg)
- return CantCompile
- end
-
- # For computing number of locals to set up for the callee
- 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.to_i == iseq.to_i
- num_params -= 1
- 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.
- asm.incr_counter(:send_iseq_materialized_block)
- return CantCompile
- end
- end
-
- if flags & C::VM_CALL_ARGS_SPLAT != 0 && flags & C::VM_CALL_ZSUPER != 0
- # zsuper methods are super calls without any arguments.
- # They are also marked as splat, but don't actually have an array
- # they pull arguments from, instead we need to change to call
- # a different method with the current stack.
- asm.incr_counter(:send_iseq_zsuper)
- return CantCompile
- end
-
- start_pc_offset = 0
- required_num = iseq.body.param.lead_num
-
- # This struct represents the metadata about the caller-specified
- # keyword arguments.
- kw_arg = calling.kwarg
- kw_arg_num = if kw_arg.nil?
- 0
- else
- kw_arg.keyword_len
- end
-
- # Arity handling and optional parameter setup
- opts_filled = argc - required_num - kw_arg_num
- opt_num = iseq.body.param.opt_num
- opts_missing = opt_num - opts_filled
-
- if doing_kw_call && flags & C::VM_CALL_ARGS_SPLAT != 0
- asm.incr_counter(:send_iseq_splat_with_kw)
- return CantCompile
- end
-
- if flags & C::VM_CALL_KW_SPLAT != 0
- asm.incr_counter(:send_iseq_kw_splat)
- return CantCompile
- end
-
- if iseq_has_rest && opt_num != 0
- asm.incr_counter(:send_iseq_has_rest_and_optional)
- return CantCompile
- end
-
- if opts_filled < 0 && flags & C::VM_CALL_ARGS_SPLAT == 0
- # Too few arguments and no splat to make up for it
- asm.incr_counter(:send_iseq_arity_error)
- return CantCompile
- end
-
- if opts_filled > opt_num && !iseq_has_rest
- # Too many arguments and no place to put them (i.e. rest arg)
- asm.incr_counter(:send_iseq_arity_error)
- return CantCompile
- end
-
- block_arg = flags & C::VM_CALL_ARGS_BLOCKARG != 0
-
- # Guard block_arg_type
- if guard_block_arg(jit, ctx, asm, calling) == CantCompile
- return CantCompile
- end
-
- # If we have unfilled optional arguments and keyword arguments then we
- # would need to adjust the arguments location to account for that.
- # For now we aren't handling this case.
- if doing_kw_call && opts_missing > 0
- asm.incr_counter(:send_iseq_missing_optional_kw)
- return CantCompile
- end
-
- # We will handle splat case later
- if opt_num > 0 && flags & C::VM_CALL_ARGS_SPLAT == 0
- num_params -= opts_missing
- start_pc_offset = iseq.body.param.opt_table[opts_filled]
- end
-
- 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.
- keyword = iseq.body.param.keyword
- keyword_num = keyword.num
- keyword_required_num = keyword.required_num
-
- 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.
- asm.incr_counter(:send_iseq_too_many_kwargs)
- return CantCompile
- end
-
- # 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.
- # SAFETY: see compile.c for sizing of this slice.
- callee_kwargs = keyword_num.times.map { |i| keyword.table[i] }
-
- # 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.
- caller_kwargs = []
- kw_arg.keyword_len.times do |kwarg_idx|
- sym = C.to_ruby(kw_arg[:keywords][kwarg_idx])
- caller_kwargs << C.rb_sym2id(sym)
- end
-
- # 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.
- caller_kwargs.each do |caller_kwarg|
- search_result = callee_kwargs.map.with_index.find { |kwarg, _| kwarg == caller_kwarg }
-
- case search_result
- in nil
- # 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.
- asm.incr_counter(:send_iseq_kwargs_mismatch)
- return CantCompile
- in _, callee_idx if callee_idx < keyword_required_num
- # Keep a count to ensure all required kwargs are specified
- required_kwargs_filled += 1
- else
- end
- end
- end
- assert_equal(true, required_kwargs_filled <= keyword_required_num)
- if required_kwargs_filled != keyword_required_num
- asm.incr_counter(:send_iseq_kwargs_mismatch)
- return CantCompile
- end
- end
-
- # Check if we need the arg0 splat handling of vm_callee_setup_block_arg
- arg_setup_block = (calling.block_handler == :captured) # arg_setup_type: arg_setup_block (invokeblock)
- block_arg0_splat = arg_setup_block && argc == 1 &&
- (iseq.body.param.flags.has_lead || opt_num > 1) &&
- !iseq.body.param.flags.ambiguous_param0
- if block_arg0_splat
- # If block_arg0_splat, we still need side exits after splat, but
- # doing push_splat_args here disallows it. So bail out.
- if flags & C::VM_CALL_ARGS_SPLAT != 0 && !iseq_has_rest
- asm.incr_counter(:invokeblock_iseq_arg0_args_splat)
- return CantCompile
- end
- # The block_arg0_splat implementation is for the rb_simple_iseq_p case,
- # but doing_kw_call means it's not a simple ISEQ.
- if doing_kw_call
- asm.incr_counter(:invokeblock_iseq_arg0_has_kw)
- return CantCompile
- end
- # The block_arg0_splat implementation cannot deal with optional parameters.
- # This is a setup_parameters_complex() situation and interacts with the
- # starting position of the callee.
- if opt_num > 1
- asm.incr_counter(:invokeblock_iseq_arg0_optional)
- return CantCompile
- end
- end
- if flags & C::VM_CALL_ARGS_SPLAT != 0 && !iseq_has_rest
- array = jit.peek_at_stack(block_arg ? 1 : 0)
- splat_array_length = if array.nil?
- 0
- else
- array.length
- end
-
- if opt_num == 0 && required_num != splat_array_length + argc - 1
- asm.incr_counter(:send_iseq_splat_arity_error)
- return CantCompile
- end
- end
-
- # We will not have CantCompile from here.
-
- if block_arg
- ctx.stack_pop(1)
- end
-
- if calling.block_handler == C::VM_BLOCK_HANDLER_NONE && iseq.body.builtin_attrs & C::BUILTIN_ATTR_LEAF != 0
- if jit_leaf_builtin_func(jit, ctx, asm, flags, iseq)
- return KeepCompiling
- end
- end
-
- # Number of locals that are not parameters
- num_locals = iseq.body.local_table_size - num_params
-
- # 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)
- asm.comment('stack overflow check')
- locals_offs = C.VALUE.size * (num_locals + iseq.body.stack_max) + 2 * C.rb_control_frame_t.size
- asm.lea(:rax, ctx.sp_opnd(locals_offs))
- asm.cmp(CFP, :rax)
- asm.jbe(counted_exit(side_exit(jit, ctx), :send_stackoverflow))
-
- # push_splat_args does stack manipulation so we can no longer side exit
- if splat_array_length
- remaining_opt = (opt_num + required_num) - (splat_array_length + (argc - 1))
-
- if opt_num > 0
- # We are going to jump to the correct offset based on how many optional
- # params are remaining.
- offset = opt_num - remaining_opt
- start_pc_offset = iseq.body.param.opt_table[offset]
- end
- # We are going to assume that the splat fills
- # all the remaining arguments. In the generated code
- # we test if this is true and if not side exit.
- argc = argc - 1 + splat_array_length + remaining_opt
- push_splat_args(splat_array_length, jit, ctx, asm)
-
- remaining_opt.times do
- # We need to push nil for the optional arguments
- stack_ret = ctx.stack_push(Type::Unknown)
- asm.mov(stack_ret, Qnil)
- end
- end
-
- # This is a .send call and we need to adjust the stack
- if flags & C::VM_CALL_OPT_SEND != 0
- handle_opt_send_shift_stack(asm, argc, ctx, send_shift:)
- end
-
- if iseq_has_rest
- # We are going to allocate so setting pc and sp.
- jit_save_pc(jit, asm) # clobbers rax
- jit_save_sp(ctx, asm)
-
- if flags & C::VM_CALL_ARGS_SPLAT != 0
- non_rest_arg_count = argc - 1
- # We start by dupping the array because someone else might have
- # a reference to it.
- array = ctx.stack_pop(1)
- asm.mov(C_ARGS[0], array)
- asm.call(C.rb_ary_dup)
- array = C_RET
- if non_rest_arg_count > required_num
- # If we have more arguments than required, we need to prepend
- # the items from the stack onto the array.
- diff = (non_rest_arg_count - required_num)
-
- # diff is >0 so no need to worry about null pointer
- asm.comment('load pointer to array elements')
- offset_magnitude = C.VALUE.size * diff
- values_opnd = ctx.sp_opnd(-offset_magnitude)
- values_ptr = :rcx
- asm.lea(values_ptr, values_opnd)
-
- asm.comment('prepend stack values to rest array')
- asm.mov(C_ARGS[0], diff)
- asm.mov(C_ARGS[1], values_ptr)
- asm.mov(C_ARGS[2], array)
- asm.call(C.rb_ary_unshift_m)
- ctx.stack_pop(diff)
-
- stack_ret = ctx.stack_push(Type::TArray)
- asm.mov(stack_ret, C_RET)
- # We now should have the required arguments
- # and an array of all the rest arguments
- argc = required_num + 1
- elsif non_rest_arg_count < required_num
- # If we have fewer arguments than required, we need to take some
- # from the array and move them to the stack.
- diff = (required_num - non_rest_arg_count)
- # This moves the arguments onto the stack. But it doesn't modify the array.
- move_rest_args_to_stack(array, diff, jit, ctx, asm)
-
- # We will now slice the array to give us a new array of the correct size
- asm.mov(C_ARGS[0], array)
- asm.mov(C_ARGS[1], diff)
- asm.call(C.rjit_rb_ary_subseq_length)
- stack_ret = ctx.stack_push(Type::TArray)
- asm.mov(stack_ret, C_RET)
-
- # We now should have the required arguments
- # and an array of all the rest arguments
- argc = required_num + 1
- else
- # The arguments are equal so we can just push to the stack
- assert_equal(non_rest_arg_count, required_num)
- stack_ret = ctx.stack_push(Type::TArray)
- asm.mov(stack_ret, array)
- end
- else
- assert_equal(true, argc >= required_num)
- n = (argc - required_num)
- argc = required_num + 1
- # If n is 0, then elts is never going to be read, so we can just pass null
- if n == 0
- values_ptr = 0
- else
- asm.comment('load pointer to array elements')
- offset_magnitude = C.VALUE.size * n
- values_opnd = ctx.sp_opnd(-offset_magnitude)
- values_ptr = :rcx
- asm.lea(values_ptr, values_opnd)
- end
-
- asm.mov(C_ARGS[0], EC)
- asm.mov(C_ARGS[1], n)
- asm.mov(C_ARGS[2], values_ptr)
- asm.call(C.rb_ec_ary_new_from_values)
-
- ctx.stack_pop(n)
- stack_ret = ctx.stack_push(Type::TArray)
- asm.mov(stack_ret, C_RET)
- end
- end
-
- 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
- args_before_kw = required_num + opt_num
-
- # This struct represents the metadata about the caller-specified
- # keyword arguments.
- ci_kwarg = calling.kwarg
- caller_keyword_len = if ci_kwarg.nil?
- 0
- else
- ci_kwarg.keyword_len
- end
-
- # This struct represents the metadata about the callee-specified
- # keyword parameters.
- keyword = iseq.body.param.keyword
-
- asm.comment('keyword args')
-
- # This is the list of keyword arguments that the callee specified
- # in its initial declaration.
- callee_kwargs = keyword.table
- 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.
- caller_kwargs = []
-
- caller_keyword_len.times do |kwarg_idx|
- sym = C.to_ruby(ci_kwarg[:keywords][kwarg_idx])
- caller_kwargs << C.rb_sym2id(sym)
- end
- kwarg_idx = caller_keyword_len
-
- unspecified_bits = 0
-
- keyword_required_num = keyword.required_num
- (keyword_required_num...total_kwargs).each do |callee_idx|
- already_passed = false
- callee_kwarg = callee_kwargs[callee_idx]
-
- caller_keyword_len.times do |caller_idx|
- if caller_kwargs[caller_idx] == callee_kwarg
- already_passed = true
- break
- end
- end
-
- unless 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 += 1
- default_arg = ctx.stack_push(Type::Unknown)
-
- # callee_idx - keyword->required_num is used in a couple of places below.
- req_num = keyword.required_num
- extra_args = callee_idx - req_num
-
- # VALUE default_value = keyword->default_values[callee_idx - keyword->required_num];
- default_value = keyword.default_values[extra_args]
-
- 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 << extra_args
- default_value = Qnil
- end
-
- asm.mov(:rax, default_value)
- asm.mov(default_arg, :rax)
-
- caller_kwargs[kwarg_idx] = callee_kwarg
- kwarg_idx += 1
- end
- end
-
- assert_equal(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.
- total_kwargs.times do |kwarg_idx|
- 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]
- next
- end
-
- # 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.
- ((kwarg_idx + 1)...total_kwargs).each do |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.
- offset0 = argc - 1 - swap_idx - args_before_kw
- offset1 = argc - 1 - kwarg_idx - args_before_kw
- stack_swap(jit, ctx, asm, offset0, offset1)
-
- # Next we're going to do some bookkeeping on our end so
- # that we know the order that the arguments are
- # actually in now.
- caller_kwargs[kwarg_idx], caller_kwargs[swap_idx] =
- caller_kwargs[swap_idx], caller_kwargs[kwarg_idx]
-
- break
- end
- end
- end
-
- # 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.
- asm.mov(ctx.stack_opnd(-1), C.to_value(unspecified_bits))
- end
-
- # Same as vm_callee_setup_block_arg_arg0_check and vm_callee_setup_block_arg_arg0_splat
- # on vm_callee_setup_block_arg for arg_setup_block. This is done after CALLER_SETUP_ARG
- # and CALLER_REMOVE_EMPTY_KW_SPLAT, so this implementation is put here. This may need
- # side exits, so you still need to allow side exits here if block_arg0_splat is true.
- # Note that you can't have side exits after this arg0 splat.
- if block_arg0_splat
- asm.incr_counter(:send_iseq_block_arg0_splat)
- return CantCompile
- end
-
- # Create a context for the callee
- callee_ctx = Context.new
-
- # Set the argument types in the callee's context
- argc.times do |arg_idx|
- stack_offs = argc - arg_idx - 1
- arg_type = ctx.get_opnd_type(StackOpnd[stack_offs])
- callee_ctx.set_local_type(arg_idx, arg_type)
- end
-
- recv_type = if calling.block_handler == :captured
- Type::Unknown # we don't track the type information of captured->self for now
- else
- ctx.get_opnd_type(StackOpnd[argc])
- end
- callee_ctx.upgrade_opnd_type(SelfOpnd, recv_type)
-
- # Setup the new frame
- frame_type ||= C::VM_FRAME_MAGIC_METHOD | C::VM_ENV_FLAG_LOCAL
- jit_push_frame(
- jit, ctx, asm, cme, flags, argc, frame_type, calling.block_handler,
- iseq: iseq,
- local_size: num_locals,
- stack_max: iseq.body.stack_max,
- prev_ep:,
- doing_kw_call:,
- )
-
- # Directly jump to the entry point of the callee
- pc = (iseq.body.iseq_encoded + start_pc_offset).to_i
- jit_direct_jump(iseq, pc, callee_ctx, asm)
-
- EndBlock
- end
-
- def jit_leaf_builtin_func(jit, ctx, asm, flags, iseq)
- builtin_func = builtin_function(iseq)
- if builtin_func.nil?
- return false
- end
-
- # this is a .send call not currently supported for builtins
- if flags & C::VM_CALL_OPT_SEND != 0
- return false
- end
-
- builtin_argc = builtin_func.argc
- if builtin_argc + 1 >= C_ARGS.size
- return false
- end
-
- asm.comment('inlined leaf builtin')
-
- # The callee may allocate, e.g. Integer#abs on a Bignum.
- # Save SP for GC, save PC for allocation tracing, and prepare
- # for global invalidation after GC's VM lock contention.
- jit_prepare_routine_call(jit, ctx, asm)
-
- # Call the builtin func (ec, recv, arg1, arg2, ...)
- asm.mov(C_ARGS[0], EC)
-
- # Copy self and arguments
- (0..builtin_argc).each do |i|
- stack_opnd = ctx.stack_opnd(builtin_argc - i)
- asm.mov(C_ARGS[i + 1], stack_opnd)
- end
- ctx.stack_pop(builtin_argc + 1)
- asm.call(builtin_func.func_ptr)
-
- # Push the return value
- stack_ret = ctx.stack_push(Type::Unknown)
- asm.mov(stack_ret, C_RET)
- return true
- end
-
- # vm_call_cfunc
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_call_cfunc(jit, ctx, asm, cme, calling, known_recv_class: nil)
- argc = calling.argc
- flags = calling.flags
-
- cfunc = cme.def.body.cfunc
- cfunc_argc = cfunc.argc
-
- # If the function expects a Ruby array of arguments
- if cfunc_argc < 0 && cfunc_argc != -1
- asm.incr_counter(:send_cfunc_ruby_array_varg)
- return CantCompile
- end
-
- # We aren't handling a vararg cfuncs with splat currently.
- if flags & C::VM_CALL_ARGS_SPLAT != 0 && cfunc_argc == -1
- asm.incr_counter(:send_args_splat_cfunc_var_args)
- return CantCompile
- end
-
- if flags & C::VM_CALL_ARGS_SPLAT != 0 && flags & C::VM_CALL_ZSUPER != 0
- # zsuper methods are super calls without any arguments.
- # They are also marked as splat, but don't actually have an array
- # they pull arguments from, instead we need to change to call
- # a different method with the current stack.
- asm.incr_counter(:send_args_splat_cfunc_zuper)
- return CantCompile;
- end
-
- # In order to handle backwards compatibility between ruby 3 and 2
- # ruby2_keywords was introduced. It is called only on methods
- # with splat and changes they way they handle them.
- # We are just going to not compile these.
- # https://docs.ruby-lang.org/en/3.2/Module.html#method-i-ruby2_keywords
- if jit.iseq.body.param.flags.ruby2_keywords && flags & C::VM_CALL_ARGS_SPLAT != 0
- asm.incr_counter(:send_args_splat_cfunc_ruby2_keywords)
- return CantCompile;
- end
-
- kw_arg = calling.kwarg
- kw_arg_num = if kw_arg.nil?
- 0
- else
- kw_arg.keyword_len
- end
-
- if kw_arg_num != 0 && flags & C::VM_CALL_ARGS_SPLAT != 0
- asm.incr_counter(:send_cfunc_splat_with_kw)
- return CantCompile
- end
-
- if c_method_tracing_currently_enabled?
- # Don't JIT if tracing c_call or c_return
- asm.incr_counter(:send_cfunc_tracing)
- return CantCompile
- end
-
- # Delegate to codegen for C methods if we have it.
- if kw_arg.nil? && flags & C::VM_CALL_OPT_SEND == 0 && flags & C::VM_CALL_ARGS_SPLAT == 0 && (cfunc_argc == -1 || argc == cfunc_argc)
- known_cfunc_codegen = lookup_cfunc_codegen(cme.def)
- if known_cfunc_codegen&.call(jit, ctx, asm, argc, known_recv_class)
- # cfunc codegen generated code. Terminate the block so
- # there isn't multiple calls in the same block.
- jump_to_next_insn(jit, ctx, asm)
- return EndBlock
- end
- end
-
- # Check for interrupts
- jit_check_ints(jit, ctx, asm)
-
- # Stack overflow check
- # #define CHECK_VM_STACK_OVERFLOW0(cfp, sp, margin)
- # REG_CFP <= REG_SP + 4 * SIZEOF_VALUE + sizeof(rb_control_frame_t)
- asm.comment('stack overflow check')
- asm.lea(:rax, ctx.sp_opnd(C.VALUE.size * 4 + 2 * C.rb_control_frame_t.size))
- asm.cmp(CFP, :rax)
- asm.jbe(counted_exit(side_exit(jit, ctx), :send_stackoverflow))
-
- # Number of args which will be passed through to the callee
- # This is adjusted by the kwargs being combined into a hash.
- passed_argc = if kw_arg.nil?
- argc
- else
- argc - kw_arg_num + 1
- end
-
- # If the argument count doesn't match
- if cfunc_argc >= 0 && cfunc_argc != passed_argc && flags & C::VM_CALL_ARGS_SPLAT == 0
- asm.incr_counter(:send_cfunc_argc_mismatch)
- return CantCompile
- end
-
- # Don't JIT functions that need C stack arguments for now
- if cfunc_argc >= 0 && passed_argc + 1 > C_ARGS.size
- asm.incr_counter(:send_cfunc_toomany_args)
- return CantCompile
- end
-
- block_arg = flags & C::VM_CALL_ARGS_BLOCKARG != 0
-
- # Guard block_arg_type
- if guard_block_arg(jit, ctx, asm, calling) == CantCompile
- return CantCompile
- end
-
- if block_arg
- ctx.stack_pop(1)
- end
-
- # push_splat_args does stack manipulation so we can no longer side exit
- if flags & C::VM_CALL_ARGS_SPLAT != 0
- assert_equal(true, cfunc_argc >= 0)
- required_args = cfunc_argc - (argc - 1)
- # + 1 because we pass self
- if required_args + 1 >= C_ARGS.size
- asm.incr_counter(:send_cfunc_toomany_args)
- return CantCompile
- end
-
- # We are going to assume that the splat fills
- # all the remaining arguments. So the number of args
- # should just equal the number of args the cfunc takes.
- # In the generated code we test if this is true
- # and if not side exit.
- argc = cfunc_argc
- passed_argc = argc
- push_splat_args(required_args, jit, ctx, asm)
- end
-
- # This is a .send call and we need to adjust the stack
- if flags & C::VM_CALL_OPT_SEND != 0
- handle_opt_send_shift_stack(asm, argc, ctx, send_shift: calling.send_shift)
- end
-
- # Points to the receiver operand on the stack
-
- # Store incremented PC into current control frame in case callee raises.
- jit_save_pc(jit, asm)
-
- # Increment the stack pointer by 3 (in the callee)
- # sp += 3
-
- frame_type = C::VM_FRAME_MAGIC_CFUNC | C::VM_FRAME_FLAG_CFRAME | C::VM_ENV_FLAG_LOCAL
- if kw_arg
- frame_type |= C::VM_FRAME_FLAG_CFRAME_KW
- end
-
- jit_push_frame(jit, ctx, asm, cme, flags, argc, frame_type, calling.block_handler)
-
- if kw_arg
- # Build a hash from all kwargs passed
- asm.comment('build_kwhash')
- imemo_ci = calling.ci_addr
- # we assume all callinfos with kwargs are on the GC heap
- assert_equal(true, C.imemo_type_p(imemo_ci, C.imemo_callinfo))
- asm.mov(C_ARGS[0], imemo_ci)
- asm.lea(C_ARGS[1], ctx.sp_opnd(0))
- asm.call(C.rjit_build_kwhash)
-
- # Replace the stack location at the start of kwargs with the new hash
- stack_opnd = ctx.stack_opnd(argc - passed_argc)
- asm.mov(stack_opnd, C_RET)
- end
-
- # Copy SP because REG_SP will get overwritten
- sp = :rax
- asm.lea(sp, ctx.sp_opnd(0))
-
- # Pop the C function arguments from the stack (in the caller)
- ctx.stack_pop(argc + 1)
-
- # Write interpreter SP into CFP.
- # Needed in case the callee yields to the block.
- jit_save_sp(ctx, asm)
-
- # Non-variadic method
- case cfunc_argc
- in (0..) # Non-variadic method
- # 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
- (0..passed_argc).each do |i|
- asm.mov(C_ARGS[i], [sp, -(argc + 1 - i) * C.VALUE.size])
- end
- in -1 # Variadic method: rb_f_puts(int argc, VALUE *argv, VALUE recv)
- # The method gets a pointer to the first argument
- # rb_f_puts(int argc, VALUE *argv, VALUE recv)
- asm.mov(C_ARGS[0], passed_argc)
- asm.lea(C_ARGS[1], [sp, -argc * C.VALUE.size]) # argv
- asm.mov(C_ARGS[2], [sp, -(argc + 1) * C.VALUE.size]) # recv
- end
-
- # 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 yjit_method_lookup_change()
- asm.comment('call C function')
- asm.mov(:rax, cfunc.func)
- asm.call(:rax) # TODO: use rel32 if close enough
-
- # Record code position for TracePoint patching. See full_cfunc_return().
- Invariants.record_global_inval_patch(asm, full_cfunc_return)
-
- # Push the return value on the Ruby stack
- stack_ret = ctx.stack_push(Type::Unknown)
- asm.mov(stack_ret, C_RET)
-
- # Pop the stack frame (ec->cfp++)
- # Instead of recalculating, we can reuse the previous CFP, which is stored in a callee-saved
- # register
- asm.mov([EC, C.rb_execution_context_t.offsetof(:cfp)], CFP)
-
- # cfunc calls may corrupt types
- ctx.clear_local_types
-
- # Note: the return block of jit_call_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
- assert_equal(1, ctx.sp_offset)
- jump_to_next_insn(jit, ctx, asm)
- EndBlock
- end
-
- # vm_call_attrset
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_call_attrset(jit, ctx, asm, cme, calling, comptime_recv, recv_opnd)
- argc = calling.argc
- flags = calling.flags
- send_shift = calling.send_shift
-
- if flags & C::VM_CALL_ARGS_SPLAT != 0
- asm.incr_counter(:send_attrset_splat)
- return CantCompile
- end
- if flags & C::VM_CALL_KWARG != 0
- asm.incr_counter(:send_attrset_kwarg)
- return CantCompile
- elsif argc != 1 || !C.RB_TYPE_P(comptime_recv, C::RUBY_T_OBJECT)
- asm.incr_counter(:send_attrset_method)
- return CantCompile
- elsif c_method_tracing_currently_enabled?
- # Can't generate code for firing c_call and c_return events
- # See :attr-tracing:
- asm.incr_counter(:send_c_tracingg)
- return CantCompile
- elsif flags & C::VM_CALL_ARGS_BLOCKARG != 0
- asm.incr_counter(:send_block_arg)
- return CantCompile
- end
-
- ivar_name = cme.def.body.attr.id
-
- # This is a .send call and we need to adjust the stack
- if flags & C::VM_CALL_OPT_SEND != 0
- handle_opt_send_shift_stack(asm, argc, ctx, send_shift:)
- end
-
- # 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, asm)
-
- # Get the operands from the stack
- val_opnd = ctx.stack_pop(1)
- recv_opnd = ctx.stack_pop(1)
-
- # Call rb_vm_set_ivar_id with the receiver, the ivar name, and the value
- asm.mov(C_ARGS[0], recv_opnd)
- asm.mov(C_ARGS[1], ivar_name)
- asm.mov(C_ARGS[2], val_opnd)
- asm.call(C.rb_vm_set_ivar_id)
-
- out_opnd = ctx.stack_push(Type::Unknown)
- asm.mov(out_opnd, C_RET)
-
- KeepCompiling
- end
-
- # vm_call_ivar (+ part of vm_call_method_each_type)
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_call_ivar(jit, ctx, asm, cme, calling, comptime_recv, recv_opnd)
- argc = calling.argc
- flags = calling.flags
-
- if flags & C::VM_CALL_ARGS_SPLAT != 0
- asm.incr_counter(:send_ivar_splat)
- return CantCompile
- end
-
- if argc != 0
- asm.incr_counter(:send_arity)
- return CantCompile
- end
-
- # We don't support handle_opt_send_shift_stack for this yet.
- if flags & C::VM_CALL_OPT_SEND != 0
- asm.incr_counter(:send_ivar_opt_send)
- return CantCompile
- end
-
- ivar_id = cme.def.body.attr.id
-
- # Not handling block_handler
- if flags & C::VM_CALL_ARGS_BLOCKARG != 0
- asm.incr_counter(:send_block_arg)
- return CantCompile
- end
-
- jit_getivar(jit, ctx, asm, comptime_recv, ivar_id, recv_opnd, StackOpnd[0])
- end
-
- # vm_call_bmethod
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_call_bmethod(jit, ctx, asm, calling, cme, comptime_recv, recv_opnd, known_recv_class)
- proc_addr = cme.def.body.bmethod.proc
-
- proc_t = C.rb_yjit_get_proc_ptr(proc_addr)
- proc_block = proc_t.block
-
- if proc_block.type != C.block_type_iseq
- asm.incr_counter(:send_bmethod_not_iseq)
- return CantCompile
- end
-
- capture = proc_block.as.captured
- iseq = capture.code.iseq
-
- # TODO: implement this
- # Optimize for single ractor mode and avoid runtime check for
- # "defined with an un-shareable Proc in a different Ractor"
- # if !assume_single_ractor_mode(jit, ocb)
- # return CantCompile;
- # end
-
- # Passing a block to a block needs logic different from passing
- # a block to a method and sometimes requires allocation. Bail for now.
- if calling.block_handler != C::VM_BLOCK_HANDLER_NONE
- asm.incr_counter(:send_bmethod_blockarg)
- return CantCompile
- end
-
- jit_call_iseq(
- jit, ctx, asm, cme, calling, iseq,
- frame_type: C::VM_FRAME_MAGIC_BLOCK | C::VM_FRAME_FLAG_BMETHOD | C::VM_FRAME_FLAG_LAMBDA,
- prev_ep: capture.ep,
- )
- end
-
- # vm_call_alias
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_call_alias(jit, ctx, asm, calling, cme, comptime_recv, recv_opnd, known_recv_class)
- cme = C.rb_aliased_callable_method_entry(cme)
- jit_call_method_each_type(jit, ctx, asm, calling, cme, comptime_recv, recv_opnd, known_recv_class)
- end
-
- # vm_call_optimized
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_call_optimized(jit, ctx, asm, cme, calling, known_recv_class)
- if calling.flags & C::VM_CALL_ARGS_BLOCKARG != 0
- # Not working yet
- asm.incr_counter(:send_block_arg)
- return CantCompile
- end
-
- case cme.def.body.optimized.type
- in C::OPTIMIZED_METHOD_TYPE_SEND
- jit_call_opt_send(jit, ctx, asm, cme, calling, known_recv_class)
- in C::OPTIMIZED_METHOD_TYPE_CALL
- jit_call_opt_call(jit, ctx, asm, cme, calling.flags, calling.argc, calling.block_handler, known_recv_class, send_shift: calling.send_shift)
- in C::OPTIMIZED_METHOD_TYPE_BLOCK_CALL
- asm.incr_counter(:send_optimized_block_call)
- return CantCompile
- in C::OPTIMIZED_METHOD_TYPE_STRUCT_AREF
- jit_call_opt_struct_aref(jit, ctx, asm, cme, calling.flags, calling.argc, calling.block_handler, known_recv_class, send_shift: calling.send_shift)
- in C::OPTIMIZED_METHOD_TYPE_STRUCT_ASET
- asm.incr_counter(:send_optimized_struct_aset)
- return CantCompile
- end
- end
-
- # vm_call_opt_send
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_call_opt_send(jit, ctx, asm, cme, calling, known_recv_class)
- if jit_caller_setup_arg(jit, ctx, asm, calling.flags) == CantCompile
- return CantCompile
- end
-
- if calling.argc == 0
- asm.incr_counter(:send_optimized_send_no_args)
- return CantCompile
- end
-
- calling.argc -= 1
- # We aren't handling `send(:send, ...)` yet. This might work, but not tested yet.
- if calling.send_shift > 0
- asm.incr_counter(:send_optimized_send_send)
- return CantCompile
- end
- # Lazily handle stack shift in handle_opt_send_shift_stack
- calling.send_shift += 1
-
- jit_call_symbol(jit, ctx, asm, cme, calling, known_recv_class, C::VM_CALL_FCALL)
- end
-
- # vm_call_opt_call
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_call_opt_call(jit, ctx, asm, cme, flags, argc, block_handler, known_recv_class, send_shift:)
- if block_handler != C::VM_BLOCK_HANDLER_NONE
- asm.incr_counter(:send_optimized_call_block)
- return CantCompile
- end
-
- if flags & C::VM_CALL_KWARG != 0
- asm.incr_counter(:send_optimized_call_kwarg)
- return CantCompile
- end
-
- if flags & C::VM_CALL_ARGS_SPLAT != 0
- asm.incr_counter(:send_optimized_call_splat)
- return CantCompile
- end
-
- # TODO: implement this
- # Optimize for single ractor mode and avoid runtime check for
- # "defined with an un-shareable Proc in a different Ractor"
- # if !assume_single_ractor_mode(jit, ocb)
- # return CantCompile
- # end
-
- # If this is a .send call we need to adjust the stack
- if flags & C::VM_CALL_OPT_SEND != 0
- handle_opt_send_shift_stack(asm, argc, ctx, send_shift:)
- end
-
- # About to reset the SP, need to load this here
- recv_idx = argc # blockarg is not supported. send_shift is already handled.
- asm.mov(:rcx, ctx.stack_opnd(recv_idx)) # recv
-
- # Save the PC and SP because the callee can make Ruby calls
- jit_prepare_routine_call(jit, ctx, asm) # NOTE: clobbers rax
-
- asm.lea(:rax, ctx.sp_opnd(0)) # sp
-
- kw_splat = flags & C::VM_CALL_KW_SPLAT
-
- asm.mov(C_ARGS[0], :rcx)
- asm.mov(C_ARGS[1], EC)
- asm.mov(C_ARGS[2], argc)
- asm.lea(C_ARGS[3], [:rax, -argc * C.VALUE.size]) # stack_argument_pointer. NOTE: C_ARGS[3] is rcx
- asm.mov(C_ARGS[4], kw_splat)
- asm.mov(C_ARGS[5], C::VM_BLOCK_HANDLER_NONE)
- asm.call(C.rjit_optimized_call)
-
- ctx.stack_pop(argc + 1)
-
- stack_ret = ctx.stack_push(Type::Unknown)
- asm.mov(stack_ret, C_RET)
- return KeepCompiling
- end
-
- # vm_call_opt_struct_aref
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_call_opt_struct_aref(jit, ctx, asm, cme, flags, argc, block_handler, known_recv_class, send_shift:)
- if argc != 0
- asm.incr_counter(:send_optimized_struct_aref_error)
- return CantCompile
- end
-
- if c_method_tracing_currently_enabled?
- # Don't JIT if tracing c_call or c_return
- asm.incr_counter(:send_cfunc_tracing)
- return CantCompile
- end
-
- off = cme.def.body.optimized.index
-
- recv_idx = argc # blockarg is not supported
- recv_idx += send_shift
- comptime_recv = jit.peek_at_stack(recv_idx)
-
- # This is a .send call and we need to adjust the stack
- if flags & C::VM_CALL_OPT_SEND != 0
- handle_opt_send_shift_stack(asm, argc, ctx, send_shift:)
- end
-
- # 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.
- embedded = C::FL_TEST_RAW(comptime_recv, C::RSTRUCT_EMBED_LEN_MASK)
-
- asm.comment('struct aref')
- asm.mov(:rax, ctx.stack_pop(1)) # recv
-
- if embedded
- asm.mov(:rax, [:rax, C.RStruct.offsetof(:as, :ary) + (C.VALUE.size * off)])
- else
- asm.mov(:rax, [:rax, C.RStruct.offsetof(:as, :heap, :ptr)])
- asm.mov(:rax, [:rax, C.VALUE.size * off])
- end
-
- ret = ctx.stack_push(Type::Unknown)
- asm.mov(ret, :rax)
-
- jump_to_next_insn(jit, ctx, asm)
- EndBlock
- end
-
- # vm_call_opt_send (lazy part)
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def handle_opt_send_shift_stack(asm, argc, ctx, send_shift:)
- # We don't support `send(:send, ...)` for now.
- assert_equal(1, send_shift)
-
- asm.comment('shift stack')
- (0...argc).reverse_each do |i|
- opnd = ctx.stack_opnd(i)
- opnd2 = ctx.stack_opnd(i + 1)
- asm.mov(:rax, opnd)
- asm.mov(opnd2, :rax)
- end
-
- ctx.shift_stack(argc)
- end
-
- # vm_call_symbol
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_call_symbol(jit, ctx, asm, cme, calling, known_recv_class, flags)
- flags |= C::VM_CALL_OPT_SEND | (calling.kw_splat ? C::VM_CALL_KW_SPLAT : 0)
-
- comptime_symbol = jit.peek_at_stack(calling.argc)
- if comptime_symbol.class != String && !static_symbol?(comptime_symbol)
- asm.incr_counter(:send_optimized_send_not_sym_or_str)
- return CantCompile
- end
-
- mid = C.get_symbol_id(comptime_symbol)
- if mid == 0
- asm.incr_counter(:send_optimized_send_null_mid)
- return CantCompile
- end
-
- asm.comment("Guard #{comptime_symbol.inspect} is on stack")
- class_changed_exit = counted_exit(side_exit(jit, ctx), :send_optimized_send_mid_class_changed)
- jit_guard_known_klass(
- jit, ctx, asm, C.rb_class_of(comptime_symbol), ctx.stack_opnd(calling.argc),
- StackOpnd[calling.argc], comptime_symbol, class_changed_exit,
- )
- asm.mov(C_ARGS[0], ctx.stack_opnd(calling.argc))
- asm.call(C.rb_get_symbol_id)
- asm.cmp(C_RET, mid)
- id_changed_exit = counted_exit(side_exit(jit, ctx), :send_optimized_send_mid_id_changed)
- jit_chain_guard(:jne, jit, ctx, asm, id_changed_exit)
-
- # rb_callable_method_entry_with_refinements
- calling.flags = flags
- cme, _ = jit_search_method(jit, ctx, asm, mid, calling)
- if cme == CantCompile
- return CantCompile
- end
-
- if flags & C::VM_CALL_FCALL != 0
- return jit_call_method(jit, ctx, asm, mid, calling, cme, known_recv_class)
- end
-
- raise NotImplementedError # unreachable for now
- end
-
- # vm_push_frame
- #
- # Frame structure:
- # | args | locals | cme/cref | block_handler/prev EP | frame type (EP here) | stack bottom (SP here)
- #
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_push_frame(jit, ctx, asm, cme, flags, argc, frame_type, block_handler, iseq: nil, local_size: 0, stack_max: 0, prev_ep: nil, doing_kw_call: nil)
- # Save caller SP and PC before pushing a callee frame for backtrace and side exits
- asm.comment('save SP to caller CFP')
- recv_idx = argc # blockarg is already popped
- recv_idx += (block_handler == :captured) ? 0 : 1 # receiver is not on stack when captured->self is used
- if iseq
- # Skip setting this to SP register. This cfp->sp will be copied to SP on leave insn.
- asm.lea(:rax, ctx.sp_opnd(C.VALUE.size * -recv_idx)) # Pop receiver and arguments to prepare for side exits
- asm.mov([CFP, C.rb_control_frame_t.offsetof(:sp)], :rax)
- else
- asm.lea(SP, ctx.sp_opnd(C.VALUE.size * -recv_idx))
- asm.mov([CFP, C.rb_control_frame_t.offsetof(:sp)], SP)
- ctx.sp_offset = recv_idx
- end
- jit_save_pc(jit, asm, comment: 'save PC to caller CFP')
-
- sp_offset = ctx.sp_offset + 3 + local_size + (doing_kw_call ? 1 : 0) # callee_sp
- local_size.times do |i|
- asm.comment('set local variables') if i == 0
- local_index = sp_offset + i - local_size - 3
- asm.mov([SP, C.VALUE.size * local_index], Qnil)
- end
-
- asm.comment('set up EP with managing data')
- ep_offset = sp_offset - 1
- # ep[-2]: cref_or_me
- asm.mov(:rax, cme.to_i)
- asm.mov([SP, C.VALUE.size * (ep_offset - 2)], :rax)
- # ep[-1]: block handler or prev env ptr (specval)
- if prev_ep
- asm.mov(:rax, prev_ep.to_i | 1) # tagged prev ep
- asm.mov([SP, C.VALUE.size * (ep_offset - 1)], :rax)
- elsif block_handler == :captured
- # Set captured->ep, saving captured in :rcx for captured->self
- ep_reg = :rcx
- jit_get_lep(jit, asm, reg: ep_reg)
- asm.mov(:rcx, [ep_reg, C.VALUE.size * C::VM_ENV_DATA_INDEX_SPECVAL]) # block_handler
- asm.and(:rcx, ~0x3) # captured
- asm.mov(:rax, [:rcx, C.VALUE.size]) # captured->ep
- asm.or(:rax, 0x1) # GC_GUARDED_PTR
- asm.mov([SP, C.VALUE.size * (ep_offset - 1)], :rax)
- elsif block_handler == C::VM_BLOCK_HANDLER_NONE
- asm.mov([SP, C.VALUE.size * (ep_offset - 1)], C::VM_BLOCK_HANDLER_NONE)
- elsif block_handler == C.rb_block_param_proxy
- # vm_caller_setup_arg_block: block_code == rb_block_param_proxy
- jit_get_lep(jit, asm, reg: :rax) # VM_CF_BLOCK_HANDLER: VM_CF_LEP
- asm.mov(:rax, [:rax, C.VALUE.size * C::VM_ENV_DATA_INDEX_SPECVAL]) # VM_CF_BLOCK_HANDLER: VM_ENV_BLOCK_HANDLER
- asm.mov([CFP, C.rb_control_frame_t.offsetof(:block_code)], :rax) # reg_cfp->block_code = handler
- asm.mov([SP, C.VALUE.size * (ep_offset - 1)], :rax) # return handler;
- else # assume blockiseq
- asm.mov(:rax, block_handler)
- asm.mov([CFP, C.rb_control_frame_t.offsetof(:block_code)], :rax)
- asm.lea(:rax, [CFP, C.rb_control_frame_t.offsetof(:self)]) # VM_CFP_TO_CAPTURED_BLOCK
- asm.or(:rax, 1) # VM_BH_FROM_ISEQ_BLOCK
- asm.mov([SP, C.VALUE.size * (ep_offset - 1)], :rax)
- end
- # ep[-0]: ENV_FLAGS
- asm.mov([SP, C.VALUE.size * (ep_offset - 0)], frame_type)
-
- asm.comment('set up new frame')
- cfp_offset = -C.rb_control_frame_t.size # callee CFP
- # For ISEQ, JIT code will set it as needed. However, C func needs 0 there for svar frame detection.
- if iseq.nil?
- asm.mov([CFP, cfp_offset + C.rb_control_frame_t.offsetof(:pc)], 0)
- end
- asm.mov(:rax, iseq.to_i)
- asm.mov([CFP, cfp_offset + C.rb_control_frame_t.offsetof(:iseq)], :rax)
- if block_handler == :captured
- asm.mov(:rax, [:rcx]) # captured->self
- else
- self_index = ctx.sp_offset - (1 + argc) # blockarg has been popped
- asm.mov(:rax, [SP, C.VALUE.size * self_index])
- end
- asm.mov([CFP, cfp_offset + C.rb_control_frame_t.offsetof(:self)], :rax)
- asm.lea(:rax, [SP, C.VALUE.size * ep_offset])
- asm.mov([CFP, cfp_offset + C.rb_control_frame_t.offsetof(:ep)], :rax)
- asm.mov([CFP, cfp_offset + C.rb_control_frame_t.offsetof(:block_code)], 0)
- # Update SP register only for ISEQ calls. SP-relative operations should be done above this.
- sp_reg = iseq ? SP : :rax
- asm.lea(sp_reg, [SP, C.VALUE.size * sp_offset])
- asm.mov([CFP, cfp_offset + C.rb_control_frame_t.offsetof(:sp)], sp_reg)
-
- # cfp->jit_return is used only for ISEQs
- if iseq
- # The callee might change locals through Kernel#binding and other means.
- ctx.clear_local_types
-
- # Stub cfp->jit_return
- return_ctx = ctx.dup
- return_ctx.stack_pop(argc + ((block_handler == :captured) ? 0 : 1)) # Pop args and receiver. blockarg has been popped
- return_ctx.stack_push(Type::Unknown) # push callee's return value
- return_ctx.sp_offset = 1 # SP is in the position after popping a receiver and arguments
- return_ctx.chain_depth = 0
- branch_stub = BranchStub.new(
- iseq: jit.iseq,
- shape: Default,
- target0: BranchTarget.new(ctx: return_ctx, pc: jit.pc + jit.insn.len * C.VALUE.size),
- )
- branch_stub.target0.address = Assembler.new.then do |ocb_asm|
- @exit_compiler.compile_branch_stub(return_ctx, ocb_asm, branch_stub, true)
- @ocb.write(ocb_asm)
- end
- branch_stub.compile = compile_jit_return(branch_stub, cfp_offset:)
- branch_stub.compile.call(asm)
- end
-
- asm.comment('switch to callee CFP')
- # Update CFP register only for ISEQ calls
- cfp_reg = iseq ? CFP : :rax
- asm.lea(cfp_reg, [CFP, cfp_offset])
- asm.mov([EC, C.rb_execution_context_t.offsetof(:cfp)], cfp_reg)
- end
-
- def compile_jit_return(branch_stub, cfp_offset:) # Proc escapes arguments in memory
- proc do |branch_asm|
- branch_asm.comment('set jit_return to callee CFP')
- branch_asm.stub(branch_stub) do
- case branch_stub.shape
- in Default
- branch_asm.mov(:rax, branch_stub.target0.address)
- branch_asm.mov([CFP, cfp_offset + C.rb_control_frame_t.offsetof(:jit_return)], :rax)
- end
- end
- end
- end
-
- # CALLER_SETUP_ARG: Return CantCompile if not supported
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def jit_caller_setup_arg(jit, ctx, asm, flags)
- if flags & C::VM_CALL_ARGS_SPLAT != 0 && flags & C::VM_CALL_KW_SPLAT != 0
- asm.incr_counter(:send_args_splat_kw_splat)
- return CantCompile
- elsif flags & C::VM_CALL_ARGS_SPLAT != 0
- # splat is not supported in this path
- asm.incr_counter(:send_args_splat)
- return CantCompile
- elsif flags & C::VM_CALL_KW_SPLAT != 0
- asm.incr_counter(:send_args_kw_splat)
- return CantCompile
- elsif flags & C::VM_CALL_KWARG != 0
- asm.incr_counter(:send_kwarg)
- return CantCompile
- end
- end
-
- # Pushes arguments from an array to the stack. Differs from push splat because
- # the array can have items left over.
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def move_rest_args_to_stack(array, num_args, jit, ctx, asm)
- side_exit = side_exit(jit, ctx)
-
- asm.comment('move_rest_args_to_stack')
-
- # array is :rax
- array_len_opnd = :rcx
- jit_array_len(asm, array, array_len_opnd)
-
- asm.comment('Side exit if length is less than required')
- asm.cmp(array_len_opnd, num_args)
- asm.jl(counted_exit(side_exit, :send_iseq_has_rest_and_splat_not_equal))
-
- asm.comment('Push arguments from array')
-
- # Load the address of the embedded array
- # (struct RArray *)(obj)->as.ary
- array_reg = array
-
- # Conditionally load the address of the heap array
- # (struct RArray *)(obj)->as.heap.ptr
- flags_opnd = [array_reg, C.RBasic.offsetof(:flags)]
- asm.test(flags_opnd, C::RARRAY_EMBED_FLAG)
- heap_ptr_opnd = [array_reg, C.RArray.offsetof(:as, :heap, :ptr)]
- # Load the address of the embedded array
- # (struct RArray *)(obj)->as.ary
- ary_opnd = :rdx # NOTE: array :rax is used after move_rest_args_to_stack too
- asm.lea(:rcx, [array_reg, C.RArray.offsetof(:as, :ary)])
- asm.mov(ary_opnd, heap_ptr_opnd)
- asm.cmovnz(ary_opnd, :rcx)
-
- num_args.times do |i|
- top = ctx.stack_push(Type::Unknown)
- asm.mov(:rcx, [ary_opnd, i * C.VALUE.size])
- asm.mov(top, :rcx)
- end
- end
-
- # vm_caller_setup_arg_splat (+ CALLER_SETUP_ARG):
- # Pushes arguments from an array to the stack that are passed with a splat (i.e. *args).
- # It optimistically compiles to a static size that is the exact number of arguments needed for the function.
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def push_splat_args(required_args, jit, ctx, asm)
- side_exit = side_exit(jit, ctx)
-
- asm.comment('push_splat_args')
-
- array_opnd = ctx.stack_opnd(0)
- array_stack_opnd = StackOpnd[0]
- array_reg = :rax
- asm.mov(array_reg, array_opnd)
-
- guard_object_is_array(jit, ctx, asm, array_reg, :rcx, array_stack_opnd, :send_args_splat_not_array)
-
- array_len_opnd = :rcx
- jit_array_len(asm, array_reg, array_len_opnd)
-
- asm.comment('Side exit if length is not equal to remaining args')
- asm.cmp(array_len_opnd, required_args)
- asm.jne(counted_exit(side_exit, :send_args_splat_length_not_equal))
-
- asm.comment('Check last argument is not ruby2keyword hash')
-
- ary_opnd = :rcx
- jit_array_ptr(asm, array_reg, ary_opnd) # clobbers array_reg
-
- last_array_value = :rax
- asm.mov(last_array_value, [ary_opnd, (required_args - 1) * C.VALUE.size])
-
- ruby2_exit = counted_exit(side_exit, :send_args_splat_ruby2_hash);
- guard_object_is_not_ruby2_keyword_hash(asm, last_array_value, :rcx, ruby2_exit) # clobbers :rax
-
- asm.comment('Push arguments from array')
- array_opnd = ctx.stack_pop(1)
-
- if required_args > 0
- # Load the address of the embedded array
- # (struct RArray *)(obj)->as.ary
- array_reg = :rax
- asm.mov(array_reg, array_opnd)
-
- # Conditionally load the address of the heap array
- # (struct RArray *)(obj)->as.heap.ptr
- flags_opnd = [array_reg, C.RBasic.offsetof(:flags)]
- asm.test(flags_opnd, C::RARRAY_EMBED_FLAG)
- heap_ptr_opnd = [array_reg, C.RArray.offsetof(:as, :heap, :ptr)]
- # Load the address of the embedded array
- # (struct RArray *)(obj)->as.ary
- asm.lea(:rcx, [array_reg, C.RArray.offsetof(:as, :ary)])
- asm.mov(:rax, heap_ptr_opnd)
- asm.cmovnz(:rax, :rcx)
- ary_opnd = :rax
-
- (0...required_args).each do |i|
- top = ctx.stack_push(Type::Unknown)
- asm.mov(:rcx, [ary_opnd, i * C.VALUE.size])
- asm.mov(top, :rcx)
- end
-
- asm.comment('end push_each')
- end
- end
-
- # Generate RARRAY_LEN. For array_opnd, use Opnd::Reg to reduce memory access,
- # and use Opnd::Mem to save registers.
- def jit_array_len(asm, array_reg, len_reg)
- asm.comment('get array length for embedded or heap')
-
- # Pull out the embed flag to check if it's an embedded array.
- asm.mov(len_reg, [array_reg, C.RBasic.offsetof(:flags)])
-
- # Get the length of the array
- asm.and(len_reg, C::RARRAY_EMBED_LEN_MASK)
- asm.sar(len_reg, C::RARRAY_EMBED_LEN_SHIFT)
-
- # Conditionally move the length of the heap array
- asm.test([array_reg, C.RBasic.offsetof(:flags)], C::RARRAY_EMBED_FLAG)
-
- # Select the array length value
- asm.cmovz(len_reg, [array_reg, C.RArray.offsetof(:as, :heap, :len)])
- end
-
- # Generate RARRAY_CONST_PTR (part of RARRAY_AREF)
- def jit_array_ptr(asm, array_reg, ary_opnd) # clobbers array_reg
- asm.comment('get array pointer for embedded or heap')
-
- flags_opnd = [array_reg, C.RBasic.offsetof(:flags)]
- asm.test(flags_opnd, C::RARRAY_EMBED_FLAG)
- # Load the address of the embedded array
- # (struct RArray *)(obj)->as.ary
- asm.mov(ary_opnd, [array_reg, C.RArray.offsetof(:as, :heap, :ptr)])
- asm.lea(array_reg, [array_reg, C.RArray.offsetof(:as, :ary)]) # clobbers array_reg
- asm.cmovnz(ary_opnd, array_reg)
- end
-
- def assert(cond)
- assert_equal(cond, true)
- end
-
- def assert_equal(left, right)
- if left != right
- raise "'#{left.inspect}' was not '#{right.inspect}'"
- end
- end
-
- def fixnum?(obj)
- (C.to_value(obj) & C::RUBY_FIXNUM_FLAG) == C::RUBY_FIXNUM_FLAG
- end
-
- def flonum?(obj)
- (C.to_value(obj) & C::RUBY_FLONUM_MASK) == C::RUBY_FLONUM_FLAG
- end
-
- def symbol?(obj)
- static_symbol?(obj) || dynamic_symbol?(obj)
- end
-
- def static_symbol?(obj)
- (C.to_value(obj) & 0xff) == C::RUBY_SYMBOL_FLAG
- end
-
- def dynamic_symbol?(obj)
- return false if C::SPECIAL_CONST_P(obj)
- C.RB_TYPE_P(obj, C::RUBY_T_SYMBOL)
- end
-
- def shape_too_complex?(obj)
- C.rb_shape_get_shape_id(obj) == C::OBJ_TOO_COMPLEX_SHAPE_ID
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- # @param asm [RubyVM::RJIT::Assembler]
- def defer_compilation(jit, ctx, asm)
- # Make a stub to compile the current insn
- if ctx.chain_depth != 0
- raise "double defer!"
- end
- ctx.chain_depth += 1
- jit_direct_jump(jit.iseq, jit.pc, ctx, asm, comment: 'defer_compilation')
- end
-
- def jit_direct_jump(iseq, pc, ctx, asm, comment: 'jit_direct_jump')
- branch_stub = BranchStub.new(
- iseq:,
- shape: Default,
- target0: BranchTarget.new(ctx:, pc:),
- )
- branch_stub.target0.address = Assembler.new.then do |ocb_asm|
- @exit_compiler.compile_branch_stub(ctx, ocb_asm, branch_stub, true)
- @ocb.write(ocb_asm)
- end
- branch_stub.compile = compile_jit_direct_jump(branch_stub, comment:)
- branch_stub.compile.call(asm)
- end
-
- def compile_jit_direct_jump(branch_stub, comment:) # Proc escapes arguments in memory
- proc do |branch_asm|
- branch_asm.comment(comment)
- branch_asm.stub(branch_stub) do
- case branch_stub.shape
- in Default
- branch_asm.jmp(branch_stub.target0.address)
- in Next0
- # Just write the block without a jump
- end
- end
- end
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param ctx [RubyVM::RJIT::Context]
- def side_exit(jit, ctx)
- # We use the latest ctx.sp_offset to generate a side exit to tolerate sp_offset changes by jit_save_sp.
- # However, we want to simulate an old stack_size when we take a side exit. We do that by adjusting the
- # sp_offset because gen_outlined_exit uses ctx.sp_offset to move SP.
- ctx = ctx.with_stack_size(jit.stack_size_for_pc)
-
- jit.side_exit_for_pc[ctx.sp_offset] ||= Assembler.new.then do |asm|
- @exit_compiler.compile_side_exit(jit.pc, ctx, asm)
- @ocb.write(asm)
- end
- end
-
- def counted_exit(side_exit, name)
- asm = Assembler.new
- asm.incr_counter(name)
- asm.jmp(side_exit)
- @ocb.write(asm)
- end
-
- def def_iseq_ptr(cme_def)
- C.rb_iseq_check(cme_def.body.iseq.iseqptr)
- end
-
- def to_value(obj)
- GC_REFS << obj
- C.to_value(obj)
- end
-
- def full_cfunc_return
- @full_cfunc_return ||= Assembler.new.then do |asm|
- @exit_compiler.compile_full_cfunc_return(asm)
- @ocb.write(asm)
- end
- end
-
- def c_method_tracing_currently_enabled?
- C.rb_rjit_global_events & (C::RUBY_EVENT_C_CALL | C::RUBY_EVENT_C_RETURN) != 0
- end
-
- # Return a builtin function if a given iseq consists of only that builtin function
- def builtin_function(iseq)
- opt_invokebuiltin_delegate_leave = INSNS.values.find { |i| i.name == :opt_invokebuiltin_delegate_leave }
- leave = INSNS.values.find { |i| i.name == :leave }
- if iseq.body.iseq_size == opt_invokebuiltin_delegate_leave.len + leave.len &&
- C.rb_vm_insn_decode(iseq.body.iseq_encoded[0]) == opt_invokebuiltin_delegate_leave.bin &&
- C.rb_vm_insn_decode(iseq.body.iseq_encoded[opt_invokebuiltin_delegate_leave.len]) == leave.bin
- C.rb_builtin_function.new(iseq.body.iseq_encoded[1])
- end
- end
-
- def build_calling(ci:, block_handler:)
- CallingInfo.new(
- argc: C.vm_ci_argc(ci),
- flags: C.vm_ci_flag(ci),
- kwarg: C.vm_ci_kwarg(ci),
- ci_addr: ci.to_i,
- send_shift: 0,
- block_handler:,
- )
- end
- end
-end
diff --git a/lib/ruby_vm/rjit/invariants.rb b/lib/ruby_vm/rjit/invariants.rb
deleted file mode 100644
index 5b061d1994..0000000000
--- a/lib/ruby_vm/rjit/invariants.rb
+++ /dev/null
@@ -1,155 +0,0 @@
-require 'set'
-
-module RubyVM::RJIT
- class Invariants
- class << self
- # Called by RubyVM::RJIT::Compiler to lazily initialize this
- # @param cb [CodeBlock]
- # @param ocb [CodeBlock]
- # @param compiler [RubyVM::RJIT::Compiler]
- # @param exit_compiler [RubyVM::RJIT::ExitCompiler]
- def initialize(cb, ocb, compiler, exit_compiler)
- @cb = cb
- @ocb = ocb
- @compiler = compiler
- @exit_compiler = exit_compiler
- @bop_blocks = Set.new # TODO: actually invalidate this
- @cme_blocks = Hash.new { |h, k| h[k] = Set.new }
- @const_blocks = Hash.new { |h, k| h[k] = Set.new }
- @patches = {}
-
- # freeze # workaround a binding.irb issue. TODO: resurrect this
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param klass [Integer]
- # @param op [Integer]
- def assume_bop_not_redefined(jit, klass, op)
- return false unless C.BASIC_OP_UNREDEFINED_P(klass, op)
-
- ensure_block_entry_exit(jit, cause: 'assume_bop_not_redefined')
- @bop_blocks << jit.block
- true
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- def assume_method_lookup_stable(jit, cme)
- ensure_block_entry_exit(jit, cause: 'assume_method_lookup_stable')
- @cme_blocks[cme.to_i] << jit.block
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- def assume_method_basic_definition(jit, klass, mid)
- if C.rb_method_basic_definition_p(klass, mid)
- cme = C.rb_callable_method_entry(klass, mid)
- assume_method_lookup_stable(jit, cme)
- true
- else
- false
- end
- end
-
- def assume_stable_constant_names(jit, idlist)
- (0..).each do |i|
- break if (id = idlist[i]) == 0
- @const_blocks[id] << jit.block
- end
- end
-
- # @param asm [RubyVM::RJIT::Assembler]
- def record_global_inval_patch(asm, target)
- asm.pos_marker do |address|
- if @patches.key?(address)
- raise 'multiple patches in the same address'
- end
- @patches[address] = target
- end
- end
-
- def on_cme_invalidate(cme)
- @cme_blocks.fetch(cme.to_i, []).each do |block|
- @cb.with_write_addr(block.start_addr) do
- asm = Assembler.new
- asm.comment('on_cme_invalidate')
- asm.jmp(block.entry_exit)
- @cb.write(asm)
- end
- # TODO: re-generate branches that refer to this block
- end
- @cme_blocks.delete(cme.to_i)
- end
-
- def on_constant_ic_update(iseq, ic, insn_idx)
- # TODO: check multi ractor as well
- if ic.entry.ic_cref
- # No need to recompile the slowpath
- return
- end
-
- pc = iseq.body.iseq_encoded + insn_idx
- insn_name = Compiler.decode_insn(pc.*).name
- if insn_name != :opt_getconstant_path && insn_name != :trace_opt_getconstant_path
- raise 'insn_idx was not at opt_getconstant_path'
- end
- if ic.to_i != pc[1]
- raise 'insn_idx + 1 was not at the updated IC'
- end
- @compiler.invalidate_blocks(iseq, pc.to_i)
- end
-
- def on_constant_state_changed(id)
- @const_blocks.fetch(id, []).each do |block|
- @compiler.invalidate_block(block)
- end
- end
-
- def on_tracing_invalidate_all
- invalidate_all
- end
-
- def on_update_references
- # Give up. In order to support GC.compact, you'd have to update ISEQ
- # addresses in BranchStub, etc. Ideally, we'd need to update moved
- # pointers in JITed code here, but we just invalidate all for now.
- invalidate_all
- end
-
- # @param jit [RubyVM::RJIT::JITState]
- # @param block [RubyVM::RJIT::Block]
- def ensure_block_entry_exit(jit, cause:)
- block = jit.block
- if block.entry_exit.nil?
- block.entry_exit = Assembler.new.then do |asm|
- @exit_compiler.compile_entry_exit(block.pc, block.ctx, asm, cause:)
- @ocb.write(asm)
- end
- end
- end
-
- private
-
- def invalidate_all
- # On-Stack Replacement
- @patches.each do |address, target|
- # TODO: assert patches don't overlap each other
- @cb.with_write_addr(address) do
- asm = Assembler.new
- asm.comment('on_tracing_invalidate_all')
- asm.jmp(target)
- @cb.write(asm)
- end
- end
- @patches.clear
-
- C.rjit_for_each_iseq do |iseq|
- # Avoid entering past code
- iseq.body.jit_entry = 0
- # Avoid reusing past code
- iseq.body.rjit_blocks.clear if iseq.body.rjit_blocks
- # Compile this again if not converted to trace_* insns
- iseq.body.jit_entry_calls = 0
- end
- end
- end
- end
-end
diff --git a/lib/ruby_vm/rjit/jit_state.rb b/lib/ruby_vm/rjit/jit_state.rb
deleted file mode 100644
index 02a713474e..0000000000
--- a/lib/ruby_vm/rjit/jit_state.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-module RubyVM::RJIT
- class JITState < Struct.new(
- :iseq, # @param `RubyVM::RJIT::CPointer::Struct_rb_iseq_t`
- :pc, # @param [Integer] The JIT target PC
- :cfp, # @param `RubyVM::RJIT::CPointer::Struct_rb_control_frame_t` The JIT source CFP (before RJIT is called)
- :block, # @param [RubyVM::RJIT::Block]
- :stack_size_for_pc, # @param [Integer]
- :side_exit_for_pc, # @param [Hash{ Integer => Integer }] { sp_offset => address }
- :record_boundary_patch_point, # @param [TrueClass,FalseClass]
- )
- def initialize(side_exit_for_pc: {}, record_boundary_patch_point: false, **) = super
-
- def insn
- Compiler.decode_insn(C.VALUE.new(pc).*)
- end
-
- def operand(index, signed: false, ruby: false)
- addr = pc + (index + 1) * Fiddle::SIZEOF_VOIDP
- value = Fiddle::Pointer.new(addr)[0, Fiddle::SIZEOF_VOIDP].unpack(signed ? 'q' : 'Q')[0]
- if ruby
- value = C.to_ruby(value)
- end
- value
- end
-
- def at_current_insn?
- pc == cfp.pc.to_i
- end
-
- def peek_at_local(n)
- local_table_size = iseq.body.local_table_size
- offset = -C::VM_ENV_DATA_SIZE - local_table_size + n + 1
- value = (cfp.ep + offset).*
- C.to_ruby(value)
- end
-
- def peek_at_stack(depth_from_top)
- raise 'not at current insn' unless at_current_insn?
- offset = -(1 + depth_from_top)
- # rb_rjit_branch_stub_hit updates SP, so you don't need to worry about sp_offset
- value = (cfp.sp + offset).*
- C.to_ruby(value)
- end
-
- def peek_at_self
- C.to_ruby(cfp.self)
- end
-
- def peek_at_block_handler(level)
- ep = ep_at_level(cfp, level:)
- ep[C::VM_ENV_DATA_INDEX_SPECVAL]
- end
-
- private
-
- def ep_at_level(cfp, level:)
- ep = cfp.ep
- level.times do
- # VM_ENV_PREV_EP
- ep = C.VALUE.new(ep[C::VM_ENV_DATA_INDEX_SPECVAL] & ~0x03)
- end
- ep
- end
- end
-end
diff --git a/lib/ruby_vm/rjit/stats.rb b/lib/ruby_vm/rjit/stats.rb
deleted file mode 100644
index 7e353c698e..0000000000
--- a/lib/ruby_vm/rjit/stats.rb
+++ /dev/null
@@ -1,191 +0,0 @@
-# frozen_string_literal: true
-module RubyVM::RJIT
- # Return a Hash for \RJIT statistics. \--rjit-stats makes more information available.
- def self.runtime_stats
- stats = {}
-
- # Insn exits
- INSNS.each_value do |insn|
- exits = C.rjit_insn_exits[insn.bin]
- if exits > 0
- stats[:"exit_#{insn.name}"] = exits
- end
- end
-
- # Runtime stats
- C.rb_rjit_runtime_counters.members.each do |member|
- stats[member] = C.rb_rjit_counters.public_send(member)
- end
- stats[:vm_insns_count] = C.rb_vm_insns_count
-
- # Other stats are calculated here
- stats[:side_exit_count] = stats.select { |name, _count| name.start_with?('exit_') }.sum(&:last)
- if stats[:vm_insns_count] > 0
- retired_in_rjit = stats[:rjit_insns_count] - stats[:side_exit_count]
- stats[:total_insns_count] = retired_in_rjit + stats[:vm_insns_count]
- stats[:ratio_in_rjit] = 100.0 * retired_in_rjit / stats[:total_insns_count]
- else
- stats.delete(:vm_insns_count)
- end
-
- stats
- end
-
- # :nodoc: all
- class << self
- private
-
- # --yjit-stats at_exit
- def print_stats
- stats = runtime_stats
- $stderr.puts("***RJIT: Printing RJIT statistics on exit***")
-
- print_counters(stats, prefix: 'send_', prompt: 'method call exit reasons')
- print_counters(stats, prefix: 'invokeblock_', prompt: 'invokeblock exit reasons')
- print_counters(stats, prefix: 'invokesuper_', prompt: 'invokesuper exit reasons')
- print_counters(stats, prefix: 'getblockpp_', 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: 'optaref_', prompt: 'opt_aref exit reasons')
- print_counters(stats, prefix: 'optgetconst_', prompt: 'opt_getconstant_path exit reasons')
- print_counters(stats, prefix: 'expandarray_', prompt: 'expandarray exit reasons')
-
- $stderr.puts "compiled_block_count: #{format_number(13, stats[:compiled_block_count])}"
- $stderr.puts "side_exit_count: #{format_number(13, stats[:side_exit_count])}"
- $stderr.puts "total_insns_count: #{format_number(13, stats[:total_insns_count])}" if stats.key?(:total_insns_count)
- $stderr.puts "vm_insns_count: #{format_number(13, stats[:vm_insns_count])}" if stats.key?(:vm_insns_count)
- $stderr.puts "rjit_insns_count: #{format_number(13, stats[:rjit_insns_count])}"
- $stderr.puts "ratio_in_rjit: #{format('%12.1f', stats[:ratio_in_rjit])}%" if stats.key?(:ratio_in_rjit)
-
- print_exit_counts(stats)
- end
-
- def print_counters(stats, prefix:, prompt:)
- $stderr.puts("#{prompt}: ")
- counters = stats.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 %s (%4.1f%%)\n", longest_name_length, name, format_number(10, value), percentage)
- end
- end
-
- def print_exit_counts(stats, how_many: 20, padding: 2)
- exits = stats.filter_map { |name, count| [name.to_s.delete_prefix('exit_'), count] if name.start_with?('exit_') }.to_h
- return if exits.empty?
-
- top_exits = exits.sort_by { |_name, count| -count }.first(how_many).to_h
- total_exits = exits.values.sum
- $stderr.puts "Top-#{top_exits.size} most frequent exit ops (#{format("%.1f", 100.0 * top_exits.values.sum / total_exits)}% of exits):"
-
- name_width = top_exits.map { |name, _count| name.length }.max + padding
- count_width = top_exits.map { |_name, count| format_number(10, count).length }.max + padding
- top_exits.each do |name, count|
- ratio = 100.0 * count / total_exits
- $stderr.puts "#{format("%#{name_width}s", name)}: #{format_number(count_width, count)} (#{format('%4.1f', ratio)}%)"
- end
- end
-
- # Format large numbers with comma separators for readability
- def format_number(pad, number)
- integer, decimal = number.to_s.split('.')
- d_groups = integer.chars.reverse.each_slice(3)
- with_commas = d_groups.map(&:join).join(',').reverse
- [with_commas, decimal].compact.join('.').rjust(pad, ' ')
- end
-
- # --yjit-trace-exits at_exit
- def dump_trace_exits
- filename = "#{Dir.pwd}/rjit_exit_locations.dump"
- File.binwrite(filename, Marshal.dump(exit_traces))
- $stderr.puts("RJIT exit locations dumped to:\n#{filename}")
- end
-
- # Convert rb_rjit_raw_samples and rb_rjit_line_samples into a StackProf format.
- def exit_traces
- results = C.rjit_exit_traces
- raw_samples = results[:raw].dup
- line_samples = results[:lines].dup
- frames = results[:frames].dup
- samples_count = 0
-
- # Loop through the instructions and set the frame hash with the data.
- # We use nonexistent.def for the file name, otherwise insns.def will be displayed
- # and that information isn't useful in this context.
- RubyVM::INSTRUCTION_NAMES.each_with_index do |name, frame_id|
- frame_hash = { samples: 0, total_samples: 0, edges: {}, name: name, file: "nonexistent.def", line: nil, lines: {} }
- results[:frames][frame_id] = frame_hash
- frames[frame_id] = frame_hash
- end
-
- # Loop through the raw_samples and build the hashes for StackProf.
- # The loop is based off an example in the StackProf documentation and therefore
- # this functionality can only work with that library.
- #
- # Raw Samples:
- # [ length, frame1, frame2, frameN, ..., instruction, count
- #
- # Line Samples
- # [ length, line_1, line_2, line_n, ..., dummy value, count
- i = 0
- while i < raw_samples.length
- stack_length = raw_samples[i] + 1
- i += 1 # consume the stack length
-
- prev_frame_id = nil
- stack_length.times do |idx|
- idx += i
- frame_id = raw_samples[idx]
-
- if prev_frame_id
- prev_frame = frames[prev_frame_id]
- prev_frame[:edges][frame_id] ||= 0
- prev_frame[:edges][frame_id] += 1
- end
-
- frame_info = frames[frame_id]
- frame_info[:total_samples] += 1
-
- frame_info[:lines][line_samples[idx]] ||= [0, 0]
- frame_info[:lines][line_samples[idx]][0] += 1
-
- prev_frame_id = frame_id
- end
-
- i += stack_length # consume the stack
-
- top_frame_id = prev_frame_id
- top_frame_line = 1
-
- sample_count = raw_samples[i]
-
- frames[top_frame_id][:samples] += sample_count
- frames[top_frame_id][:lines] ||= {}
- frames[top_frame_id][:lines][top_frame_line] ||= [0, 0]
- frames[top_frame_id][:lines][top_frame_line][1] += sample_count
-
- samples_count += sample_count
- i += 1
- end
-
- results[:samples] = samples_count
- # Set missed_samples and gc_samples to 0 as their values
- # don't matter to us in this context.
- results[:missed_samples] = 0
- results[:gc_samples] = 0
- results
- end
- end
-end
diff --git a/lib/ruby_vm/rjit/type.rb b/lib/ruby_vm/rjit/type.rb
deleted file mode 100644
index 119692014b..0000000000
--- a/lib/ruby_vm/rjit/type.rb
+++ /dev/null
@@ -1,221 +0,0 @@
-module RubyVM::RJIT
- # Represent the type of a value (local/stack/self) in RJIT
- Type = Data.define(:type) do
- # Check if the type is an immediate
- def imm?
- case self
- in Type::UnknownImm then true
- in Type::Nil then true
- in Type::True then true
- in Type::False then true
- in Type::Fixnum then true
- in Type::Flonum then true
- in Type::ImmSymbol then true
- else false
- end
- end
-
- # Returns true when the type is not specific.
- def unknown?
- case self
- in Type::Unknown | Type::UnknownImm | Type::UnknownHeap then true
- else false
- end
- end
-
- # Returns true when we know the VALUE is a specific handle type,
- # such as a static symbol ([Type::ImmSymbol], i.e. true from RB_STATIC_SYM_P()).
- # Opposite of [Self::is_unknown].
- def specific?
- !self.unknown?
- end
-
- # Check if the type is a heap object
- def heap?
- case self
- in Type::UnknownHeap then true
- in Type::TArray then true
- in Type::Hash then true
- in Type::HeapSymbol then true
- in Type::TString then true
- in Type::CString then true
- in Type::BlockParamProxy then true
- else false
- end
- end
-
- # Check if it's a T_ARRAY object
- def array?
- case self
- in Type::TArray then true
- else false
- end
- end
-
- # Check if it's a T_STRING object (both TString and CString are T_STRING)
- def string?
- case self
- in Type::TString then true
- in Type::CString then true
- else false
- end
- end
-
- # Returns the class if it is known, otherwise nil
- def known_class
- case self
- in Type::Nil then C.rb_cNilClass
- in Type::True then C.rb_cTrueClass
- in Type::False then C.rb_cFalseClass
- in Type::Fixnum then C.rb_cInteger
- in Type::Flonum then C.rb_cFloat
- in Type::ImmSymbol | Type::HeapSymbol then C.rb_cSymbol
- in Type::CString then C.rb_cString
- else nil
- end
- end
-
- # Returns a boolean representing whether the value is truthy if known, otherwise nil
- def known_truthy
- case self
- in Type::Nil then false
- in Type::False then false
- in Type::UnknownHeap then false
- in Type::Unknown | Type::UnknownImm then nil
- else true
- end
- end
-
- # Returns a boolean representing whether the value is equal to nil if known, otherwise nil
- def known_nil
- case [self, self.known_truthy]
- in Type::Nil, _ then true
- in Type::False, _ then false # Qfalse is not nil
- in _, true then false # if truthy, can't be nil
- in _, _ then nil # otherwise unknown
- end
- end
-
- def diff(dst)
- # Perfect match, difference is zero
- if self == dst
- return TypeDiff::Compatible[0]
- end
-
- # Any type can flow into an unknown type
- if dst == Type::Unknown
- return TypeDiff::Compatible[1]
- end
-
- # A CString is also a TString.
- if self == Type::CString && dst == Type::TString
- return TypeDiff::Compatible[1]
- end
-
- # Specific heap type into unknown heap type is imperfect but valid
- if self.heap? && dst == Type::UnknownHeap
- return TypeDiff::Compatible[1]
- end
-
- # Specific immediate type into unknown immediate type is imperfect but valid
- if self.imm? && dst == Type::UnknownImm
- return TypeDiff::Compatible[1]
- end
-
- # Incompatible types
- return TypeDiff::Incompatible
- end
-
- def upgrade(new_type)
- assert(new_type.diff(self) != TypeDiff::Incompatible)
- new_type
- end
-
- private
-
- def assert(cond)
- unless cond
- raise "'#{cond.inspect}' was not true"
- end
- end
- end
-
- # This returns an appropriate Type based on a known value
- class << Type
- def from(val)
- if C::SPECIAL_CONST_P(val)
- if fixnum?(val)
- Type::Fixnum
- elsif val.nil?
- Type::Nil
- elsif val == true
- Type::True
- elsif val == false
- Type::False
- elsif static_symbol?(val)
- Type::ImmSymbol
- elsif flonum?(val)
- Type::Flonum
- else
- raise "Illegal value: #{val.inspect}"
- end
- else
- val_class = C.to_value(C.rb_class_of(val))
- if val_class == C.rb_cString && C.rb_obj_frozen_p(val)
- return Type::CString
- end
- if C.to_value(val) == C.rb_block_param_proxy
- return Type::BlockParamProxy
- end
- case C::BUILTIN_TYPE(val)
- in C::RUBY_T_ARRAY
- Type::TArray
- in C::RUBY_T_HASH
- Type::Hash
- in C::RUBY_T_STRING
- Type::TString
- else
- Type::UnknownHeap
- end
- end
- end
-
- private
-
- def fixnum?(obj)
- (C.to_value(obj) & C::RUBY_FIXNUM_FLAG) == C::RUBY_FIXNUM_FLAG
- end
-
- def flonum?(obj)
- (C.to_value(obj) & C::RUBY_FLONUM_MASK) == C::RUBY_FLONUM_FLAG
- end
-
- def static_symbol?(obj)
- (C.to_value(obj) & 0xff) == C::RUBY_SYMBOL_FLAG
- end
- end
-
- # List of types
- Type::Unknown = Type[:Unknown]
- Type::UnknownImm = Type[:UnknownImm]
- Type::UnknownHeap = Type[:UnknownHeap]
- Type::Nil = Type[:Nil]
- Type::True = Type[:True]
- Type::False = Type[:False]
- Type::Fixnum = Type[:Fixnum]
- Type::Flonum = Type[:Flonum]
- Type::Hash = Type[:Hash]
- Type::ImmSymbol = Type[:ImmSymbol]
- Type::HeapSymbol = Type[:HeapSymbol]
-
- Type::TString = Type[:TString] # An object with the T_STRING flag set, possibly an rb_cString
- Type::CString = Type[:CString] # An un-subclassed string of type rb_cString (can have instance vars in some cases)
- Type::TArray = Type[:TArray] # An object with the T_ARRAY flag set, possibly an rb_cArray
-
- Type::BlockParamProxy = Type[:BlockParamProxy] # A special sentinel value indicating the block parameter should be read from
-
- module TypeDiff
- Compatible = Data.define(:diversion) # The smaller, the more compatible.
- Incompatible = :Incompatible
- end
-end
diff --git a/lib/rubygems.rb b/lib/rubygems.rb
index ac225ca70a..b52dd1b9d3 100644
--- a/lib/rubygems.rb
+++ b/lib/rubygems.rb
@@ -9,15 +9,15 @@
require "rbconfig"
module Gem
- VERSION = "3.6.0.dev"
+ VERSION = "4.1.0.dev"
end
-# Must be first since it unloads the prelude from 1.9.2
-require_relative "rubygems/compatibility"
-
require_relative "rubygems/defaults"
require_relative "rubygems/deprecate"
require_relative "rubygems/errors"
+require_relative "rubygems/target_rbconfig"
+require_relative "rubygems/win_platform"
+require_relative "rubygems/util/atomic_file_writer"
##
# RubyGems is the Ruby standard for publishing and managing third party
@@ -38,7 +38,7 @@ require_relative "rubygems/errors"
# Further RubyGems documentation can be found at:
#
# * {RubyGems Guides}[https://guides.rubygems.org]
-# * {RubyGems API}[https://www.rubydoc.info/github/rubygems/rubygems] (also available from
+# * {RubyGems API}[https://www.rubydoc.info/github/ruby/rubygems] (also available from
# <tt>gem server</tt>)
#
# == RubyGems Plugins
@@ -70,7 +70,7 @@ require_relative "rubygems/errors"
# == Bugs
#
# You can submit bugs to the
-# {RubyGems bug tracker}[https://github.com/rubygems/rubygems/issues]
+# {RubyGems bug tracker}[https://github.com/ruby/rubygems/issues]
# on GitHub
#
# == Credits
@@ -106,7 +106,7 @@ require_relative "rubygems/errors"
#
# == License
#
-# See {LICENSE.txt}[rdoc-ref:lib/rubygems/LICENSE.txt] for permissions.
+# See {LICENSE.txt}[https://github.com/ruby/rubygems/blob/master/LICENSE.txt] for permissions.
#
# Thanks!
#
@@ -115,18 +115,6 @@ require_relative "rubygems/errors"
module Gem
RUBYGEMS_DIR = __dir__
- ##
- # An Array of Regexps that match windows Ruby platforms.
-
- WIN_PATTERNS = [
- /bccwin/i,
- /cygwin/i,
- /djgpp/i,
- /mingw/i,
- /mswin/i,
- /wince/i,
- ].freeze
-
GEM_DEP_FILES = %w[
gem.deps.rb
gems.rb
@@ -155,7 +143,12 @@ module Gem
specifications/default
].freeze
- @@win_platform = nil
+ ##
+ # The default value for SOURCE_DATE_EPOCH if not specified.
+ # We want a date after 1980-01-01, to prevent issues with Zip files.
+ # This particular timestamp is for 1980-01-02 00:00:00 GMT.
+
+ DEFAULT_SOURCE_DATE_EPOCH = 315_619_200
@configuration = nil
@gemdeps = nil
@@ -179,6 +172,8 @@ module Gem
@discover_gems_on_require = true
+ @target_rbconfig = nil
+
##
# Try to activate a gem containing +path+. Returns true if
# activation succeeded or wasn't needed because it was already
@@ -217,7 +212,7 @@ module Gem
finish_resolve rs
end
- def self.finish_resolve(request_set=Gem::RequestSet.new)
+ def self.finish_resolve(request_set = Gem::RequestSet.new)
request_set.import Gem::Specification.unresolved_deps.values
request_set.import Gem.loaded_specs.values.map {|s| Gem::Dependency.new(s.name, s.version) }
@@ -239,6 +234,16 @@ module Gem
find_spec_for_exe(name, exec_name, requirements).bin_file exec_name
end
+ def self.find_and_activate_spec_for_exe(name, exec_name, requirements)
+ spec = find_spec_for_exe name, exec_name, requirements
+ Gem::LOADED_SPECS_MUTEX.synchronize do
+ spec.activate
+ finish_resolve
+ end
+ spec
+ end
+ private_class_method :find_and_activate_spec_for_exe
+
def self.find_spec_for_exe(name, exec_name, requirements)
raise ArgumentError, "you must supply exec_name" unless exec_name
@@ -264,6 +269,42 @@ module Gem
private_class_method :find_spec_for_exe
##
+ # Find and load the full path to the executable for gem +name+. If the
+ # +exec_name+ is not given, an exception will be raised, otherwise the
+ # specified executable's path is returned. +requirements+ allows
+ # you to specify specific gem versions.
+ #
+ # A side effect of this method is that it will activate the gem that
+ # contains the executable.
+ #
+ # This method should *only* be used in bin stub files.
+
+ def self.activate_and_load_bin_path(name, exec_name = nil, *requirements)
+ spec = find_and_activate_spec_for_exe name, exec_name, requirements
+
+ if spec.name == "bundler"
+ # Old versions of Bundler need a workaround to support nested `bundle
+ # exec` invocations by overriding `Gem.activate_bin_path`. However,
+ # RubyGems now uses this new `Gem.activate_and_load_bin_path` helper in
+ # binstubs, which is of course not overridden in Bundler since it didn't
+ # exist at the time. So, include the override here to workaround that.
+ load ENV["BUNDLE_BIN_PATH"] if ENV["BUNDLE_BIN_PATH"] && spec.version <= Gem::Version.create("2.5.22")
+
+ # Make sure there's no version of Bundler in `$LOAD_PATH` that's different
+ # from the version we just activated. If that was the case (it happens
+ # when testing Bundler from ruby/ruby), we would load Bundler extensions
+ # to RubyGems from the copy in `$LOAD_PATH` but then load the binstub from
+ # an installed copy, causing those copies to be mixed and yet more
+ # redefinition warnings.
+ #
+ require_path = $LOAD_PATH.resolve_feature_path("bundler").last.delete_suffix("/bundler.rb")
+ Gem.load_bundler_extensions(spec.version) if spec.full_require_paths.include?(require_path)
+ end
+
+ load spec.bin_file(exec_name)
+ end
+
+ ##
# Find the full path to the executable for gem +name+. If the +exec_name+
# is not given, an exception will be raised, otherwise the
# specified executable's path is returned. +requirements+ allows
@@ -275,12 +316,7 @@ module Gem
# This method should *only* be used in bin stub files.
def self.activate_bin_path(name, exec_name = nil, *requirements) # :nodoc:
- spec = find_spec_for_exe name, exec_name, requirements
- Gem::LOADED_SPECS_MUTEX.synchronize do
- spec.activate
- finish_resolve
- end
- spec.bin_file exec_name
+ find_and_activate_spec_for_exe(name, exec_name, requirements).bin_file exec_name
end
##
@@ -293,7 +329,7 @@ module Gem
##
# The path where gem executables are to be installed.
- def self.bindir(install_dir=Gem.dir)
+ def self.bindir(install_dir = Gem.dir)
return File.join install_dir, "bin" unless
install_dir.to_s == Gem.default_dir.to_s
Gem.default_bindir
@@ -302,7 +338,7 @@ module Gem
##
# The path were rubygems plugins are to be installed.
- def self.plugindir(install_dir=Gem.dir)
+ def self.plugindir(install_dir = Gem.dir)
File.join install_dir, "plugins"
end
@@ -397,6 +433,23 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
end
##
+ # The RbConfig object for the deployment target platform.
+ #
+ # This is usually the same as the running platform, but may be
+ # different if you are cross-compiling.
+
+ def self.target_rbconfig
+ @target_rbconfig || Gem::TargetRbConfig.for_running_ruby
+ end
+
+ def self.set_target_rbconfig(rbconfig_path)
+ @target_rbconfig = Gem::TargetRbConfig.from_path(rbconfig_path)
+ Gem::Platform.local(refresh: true)
+ Gem.platforms << Gem::Platform.local unless Gem.platforms.include? Gem::Platform.local
+ @target_rbconfig
+ end
+
+ ##
# Quietly ensure the Gem directory +dir+ contains all the proper
# subdirectories. If we can't create a directory due to a permission
# problem, then we will silently continue.
@@ -450,7 +503,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# distinction as extensions cannot be shared between the two.
def self.extension_api_version # :nodoc:
- if RbConfig::CONFIG["ENABLE_SHARED"] == "no"
+ if target_rbconfig["ENABLE_SHARED"] == "no"
"#{ruby_api_version}-static"
else
ruby_api_version
@@ -469,16 +522,16 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# Note that find_files will return all files even if they are from different
# versions of the same gem. See also find_latest_files
- def self.find_files(glob, check_load_path=true)
+ def self.find_files(glob, check_load_path = true)
files = []
files = find_files_from_load_path glob if check_load_path
gem_specifications = @gemdeps ? Gem.loaded_specs.values : Gem::Specification.stubs
- files.concat gem_specifications.map {|spec|
+ files.concat gem_specifications.flat_map {|spec|
spec.matches_for_glob("#{glob}#{Gem.suffix_pattern}")
- }.flatten
+ }
# $LOAD_PATH might contain duplicate entries or reference
# the spec dirs directly, so we prune.
@@ -489,9 +542,9 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
def self.find_files_from_load_path(glob) # :nodoc:
glob_with_suffixes = "#{glob}#{Gem.suffix_pattern}"
- $LOAD_PATH.map do |load_path|
+ $LOAD_PATH.flat_map do |load_path|
Gem::Util.glob_files_in_dir(glob_with_suffixes, load_path)
- end.flatten.select {|file| File.file? file }
+ end.select {|file| File.file? file }
end
##
@@ -506,14 +559,14 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# Unlike find_files, find_latest_files will return only files from the
# latest version of a gem.
- def self.find_latest_files(glob, check_load_path=true)
+ def self.find_latest_files(glob, check_load_path = true)
files = []
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).flat_map {|spec|
spec.matches_for_glob("#{glob}#{Gem.suffix_pattern}")
- }.flatten
+ }
# $LOAD_PATH might contain duplicate entries or reference
# the spec dirs directly, so we prune.
@@ -610,6 +663,30 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
end
##
+ # Load Bundler extensions to RubyGems, making sure to avoid redefinition
+ # warnings in platform constants
+
+ def self.load_bundler_extensions(version)
+ return unless version <= Gem::Version.create("2.6.9")
+
+ previous_platforms = {}
+
+ platform_const_list = ["JAVA", "MSWIN", "MSWIN64", "MINGW", "X64_MINGW_LEGACY", "X64_MINGW", "UNIVERSAL_MINGW", "WINDOWS", "X64_LINUX", "X64_LINUX_MUSL"]
+
+ platform_const_list.each do |platform|
+ previous_platforms[platform] = Gem::Platform.const_get(platform)
+ Gem::Platform.send(:remove_const, platform)
+ end
+
+ require "bundler/rubygems_ext"
+
+ platform_const_list.each do |platform|
+ Gem::Platform.send(:remove_const, platform) if Gem::Platform.const_defined?(platform)
+ Gem::Platform.const_set(platform, previous_platforms[platform])
+ end
+ end
+
+ ##
# The file name and line number of the caller of the caller of this method.
#
# +depth+ is how many layers up the call stack it should go.
@@ -753,44 +830,58 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# Safely read a file in binary mode on all platforms.
def self.read_binary(path)
- open_file(path, "rb+", &:read)
- rescue Errno::EACCES, Errno::EROFS
- open_file(path, "rb", &:read)
+ File.binread(path)
end
##
- # Safely write a file in binary mode on all platforms.
+ # Atomically write a file in binary mode on all platforms.
+
def self.write_binary(path, data)
- open_file(path, "wb") do |io|
- io.write data
+ Gem::AtomicFileWriter.open(path) do |file|
+ file.write(data)
end
- rescue Errno::ENOSPC
- # If we ran out of space but the file exists, it's *guaranteed* to be corrupted.
- File.delete(path) if File.exist?(path)
- raise
end
##
- # Open a file with given flags, and on Windows protect access with flock
+ # Open a file with given flags
def self.open_file(path, flags, &block)
- File.open(path, flags) do |io|
- if !java_platform? && win_platform?
- begin
+ File.open(path, flags, &block)
+ end
+
+ ##
+ # Open a file with given flags, and protect access with a file lock
+
+ def self.open_file_with_lock(path, &block)
+ file_lock = "#{path}.lock"
+ open_file_with_flock(file_lock, &block)
+ ensure
+ require "fileutils"
+ FileUtils.rm_f file_lock
+ end
+
+ ##
+ # Open a file with given flags, and protect access with flock
+
+ def self.open_file_with_flock(path, &block)
+ # read-write mode is used rather than read-only in order to support NFS
+ mode = IO::RDWR | IO::APPEND | IO::CREAT | IO::BINARY
+ mode |= IO::SHARE_DELETE if IO.const_defined?(:SHARE_DELETE)
+
+ File.open(path, mode) do |io|
+ begin
+ # Try to get a lock without blocking.
+ # If we do, the file is locked.
+ # Otherwise, explain why we're waiting and get a lock, but block this time.
+ if io.flock(File::LOCK_EX | File::LOCK_NB) != 0
+ warn "Waiting for another process to let go of lock: #{path}"
io.flock(File::LOCK_EX)
- rescue Errno::ENOSYS, Errno::ENOTSUP
end
+ io.puts(Process.pid)
+ rescue Errno::ENOSYS, Errno::ENOTSUP
end
yield io
end
- rescue Errno::ENOLCK # NFS
- if Thread.main != Thread.current
- raise
- else
- File.open(path, flags) do |io|
- yield io
- end
- end
end
##
@@ -810,7 +901,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# Returns a String containing the API compatibility version of Ruby
def self.ruby_api_version
- @ruby_api_version ||= RbConfig::CONFIG["ruby_version"].dup
+ @ruby_api_version ||= target_rbconfig["ruby_version"].dup
end
def self.env_requirement(gem_name)
@@ -987,18 +1078,6 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
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 }.nil?
- end
-
- @@win_platform
- end
-
- ##
# Is this a java platform?
def self.java_platform?
@@ -1119,8 +1198,7 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
##
# 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.
+ # Otherwise, returns DEFAULT_SOURCE_DATE_EPOCH as a string.
#
# NOTE(@duckinator): The implementation is a tad weird because we want to:
# 1. Make builds reproducible by default, by having this function always
@@ -1135,15 +1213,12 @@ An Array (#{env.inspect}) was passed in from #{caller[3]}
# https://reproducible-builds.org/specs/source-date-epoch/
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
-
specified_epoch = ENV["SOURCE_DATE_EPOCH"]
# 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 = specified_epoch || DEFAULT_SOURCE_DATE_EPOCH.to_s
epoch.strip
end
@@ -1358,17 +1433,6 @@ begin
rescue LoadError
end
-# TruffleRuby >= 24 defines REUSE_AS_BINARY_ON_TRUFFLERUBY in defaults/truffleruby.
-# However, TruffleRuby < 24 defines REUSE_AS_BINARY_ON_TRUFFLERUBY directly in its copy
-# of lib/rubygems/platform.rb, so it is not defined if RubyGems is updated (gem update --system).
-# Instead, we define it here in that case, similar to bundler/lib/bundler/rubygems_ext.rb.
-# We must define it here and not in platform.rb because platform.rb is loaded before defaults/truffleruby.
-class Gem::Platform
- if RUBY_ENGINE == "truffleruby" && !defined?(REUSE_AS_BINARY_ON_TRUFFLERUBY)
- REUSE_AS_BINARY_ON_TRUFFLERUBY = %w[libv8 libv8-node sorbet-static].freeze
- end
-end
-
##
# Loads the default specs.
Gem::Specification.load_defaults
diff --git a/lib/rubygems/basic_specification.rb b/lib/rubygems/basic_specification.rb
index f25756f92c..0ed7fc60bb 100644
--- a/lib/rubygems/basic_specification.rb
+++ b/lib/rubygems/basic_specification.rb
@@ -34,15 +34,6 @@ class Gem::BasicSpecification
internal_init
end
- def self.default_specifications_dir
- Gem.default_specifications_dir
- end
-
- class << self
- extend Gem::Deprecate
- rubygems_deprecate :default_specifications_dir, "Gem.default_specifications_dir"
- end
-
##
# The path to the gem.build_complete file within the extension install
# directory.
@@ -71,11 +62,7 @@ class Gem::BasicSpecification
# Return true if this spec can require +file+.
def contains_requirable_file?(file)
- if @ignored
- return false
- elsif missing_extensions?
- @ignored = true
-
+ if ignored?
if platform == Gem::Platform::RUBY || Gem::Platform.local === platform
warn "Ignoring #{full_name} because its extensions are not built. " \
"Try: gem pristine #{name} --version #{version}"
@@ -93,12 +80,35 @@ class Gem::BasicSpecification
end
end
+ ##
+ # Return true if this spec should be ignored because it's missing extensions.
+
+ def ignored?
+ return @ignored unless @ignored.nil?
+
+ @ignored = missing_extensions?
+ end
+
def default_gem?
- loaded_from &&
+ !loaded_from.nil? &&
File.dirname(loaded_from) == Gem.default_specifications_dir
end
##
+ # Regular gems take precedence over default gems
+
+ def default_gem_priority
+ default_gem? ? 1 : -1
+ end
+
+ ##
+ # Gems higher up in +gem_path+ take precedence
+
+ def base_dir_priority(gem_path)
+ gem_path.index(base_dir) || gem_path.size
+ end
+
+ ##
# Returns full path to the directory where gem's extensions are installed.
def extension_dir
@@ -115,7 +125,6 @@ class Gem::BasicSpecification
end
def find_full_gem_path # :nodoc:
- # TODO: also, shouldn't it default to full_name if it hasn't been written?
File.expand_path File.join(gems_dir, full_name)
end
@@ -123,10 +132,10 @@ class Gem::BasicSpecification
##
# The full path to the gem (install path + full name).
+ #
+ # TODO: This is duplicated with #gem_dir. Eventually either of them should be deprecated.
def full_gem_path
- # TODO: This is a heavily used method by gems, so we'll need
- # to aleast just alias it to #gem_dir rather than remove it.
@full_gem_path ||= find_full_gem_path
end
@@ -181,6 +190,9 @@ class Gem::BasicSpecification
File.expand_path(File.join(gems_dir, full_name, "data", name))
end
+ extend Gem::Deprecate
+ rubygems_deprecate :datadir, :none, "4.1"
+
##
# Full path of the target library file.
# If the file is not in this gem, return nil.
@@ -202,9 +214,11 @@ class Gem::BasicSpecification
##
# Returns the full path to this spec's gem directory.
# eg: /usr/local/lib/ruby/1.8/gems/mygem-1.0
+ #
+ # TODO: This is duplicated with #full_gem_path. Eventually either of them should be deprecated.
def gem_dir
- @gem_dir ||= File.expand_path File.join(gems_dir, full_name)
+ @gem_dir ||= find_full_gem_path
end
##
@@ -236,6 +250,13 @@ class Gem::BasicSpecification
raise NotImplementedError
end
+ def installable_on_platform?(target_platform) # :nodoc:
+ return true if [Gem::Platform::RUBY, nil, target_platform].include?(platform)
+ return true if Gem::Platform.new(platform) === target_platform
+
+ false
+ end
+
def raw_require_paths # :nodoc:
raise NotImplementedError
end
diff --git a/lib/rubygems/bundler_version_finder.rb b/lib/rubygems/bundler_version_finder.rb
index dd2fd77418..c930c2e19c 100644
--- a/lib/rubygems/bundler_version_finder.rb
+++ b/lib/rubygems/bundler_version_finder.rb
@@ -2,7 +2,10 @@
module Gem::BundlerVersionFinder
def self.bundler_version
+ return if bundle_config_version == "system"
+
v = ENV["BUNDLER_VERSION"]
+ v = nil if v&.empty?
v ||= bundle_update_bundler_version
return if v == true
@@ -21,7 +24,7 @@ module Gem::BundlerVersionFinder
end
def self.bundle_update_bundler_version
- return unless File.basename($0) == "bundle"
+ return unless ["bundle", "bundler"].include? File.basename($0)
return unless "update".start_with?(ARGV.first || " ")
bundler_version = nil
update_index = nil
@@ -64,9 +67,12 @@ module Gem::BundlerVersionFinder
return unless gemfile
- lockfile = case gemfile
- when "gems.rb" then "gems.locked"
- else "#{gemfile}.lock"
+ lockfile = ENV["BUNDLE_LOCKFILE"]
+ lockfile = nil if lockfile&.empty?
+
+ lockfile ||= case gemfile
+ when "gems.rb" then "gems.locked"
+ else "#{gemfile}.lock"
end
return unless File.file?(lockfile)
@@ -74,4 +80,33 @@ module Gem::BundlerVersionFinder
File.read(lockfile)
end
private_class_method :lockfile_contents
+
+ def self.bundle_config_version
+ config_file = bundler_config_file
+ return unless config_file && File.file?(config_file)
+
+ contents = File.read(config_file)
+ contents =~ /^BUNDLE_VERSION:\s*["']?([^"'\s]+)["']?\s*$/
+
+ $1
+ end
+ private_class_method :bundle_config_version
+
+ def self.bundler_config_file
+ # see Bundler::Settings#global_config_file and local_config_file
+ # global
+ if ENV["BUNDLE_CONFIG"] && !ENV["BUNDLE_CONFIG"].empty?
+ ENV["BUNDLE_CONFIG"]
+ elsif ENV["BUNDLE_USER_CONFIG"] && !ENV["BUNDLE_USER_CONFIG"].empty?
+ ENV["BUNDLE_USER_CONFIG"]
+ elsif ENV["BUNDLE_USER_HOME"] && !ENV["BUNDLE_USER_HOME"].empty?
+ ENV["BUNDLE_USER_HOME"] + "config"
+ elsif Gem.user_home && !Gem.user_home.empty?
+ Gem.user_home + ".bundle/config"
+ else
+ # local
+ "config"
+ end
+ end
+ private_class_method :bundler_config_file
end
diff --git a/lib/rubygems/command.rb b/lib/rubygems/command.rb
index ec498a8b94..d38363f293 100644
--- a/lib/rubygems/command.rb
+++ b/lib/rubygems/command.rb
@@ -117,7 +117,7 @@ class Gem::Command
# Unhandled arguments (gem names, files, etc.) are left in
# <tt>options[:args]</tt>.
- def initialize(command, summary=nil, defaults={})
+ def initialize(command, summary = nil, defaults = {})
@command = command
@summary = summary
@program_name = "gem #{command}"
@@ -650,9 +650,6 @@ RubyGems is a package manager for Ruby.
gem help platforms gem platforms guide
gem help <COMMAND> show help on COMMAND
(e.g. 'gem help install')
- gem server present a web page at
- http://localhost:8808/
- with info about installed gems
Further information:
https://guides.rubygems.org
HELP
diff --git a/lib/rubygems/command_manager.rb b/lib/rubygems/command_manager.rb
index 8e578dc196..76b2fba835 100644
--- a/lib/rubygems/command_manager.rb
+++ b/lib/rubygems/command_manager.rb
@@ -58,7 +58,6 @@ class Gem::CommandManager
:owner,
:pristine,
:push,
- :query,
:rdoc,
:rebuild,
:search,
@@ -118,7 +117,7 @@ class Gem::CommandManager
##
# Register the Symbol +command+ as a gem command.
- def register_command(command, obj=false)
+ def register_command(command, obj = false)
@commands[command] = obj
end
@@ -148,7 +147,7 @@ class Gem::CommandManager
##
# Run the command specified by +args+.
- def run(args, build_args=nil)
+ def run(args, build_args = nil)
process_args(args, build_args)
rescue StandardError, Gem::Timeout::Error => ex
if ex.respond_to?(:detailed_message)
@@ -165,7 +164,7 @@ class Gem::CommandManager
terminate_interaction(1)
end
- def process_args(args, build_args=nil)
+ def process_args(args, build_args = nil)
if args.empty?
say Gem::Command::HELP
terminate_interaction 1
@@ -230,18 +229,16 @@ class Gem::CommandManager
def load_and_instantiate(command_name)
command_name = command_name.to_s
const_name = command_name.capitalize.gsub(/_(.)/) { $1.upcase } << "Command"
- load_error = nil
begin
begin
require "rubygems/commands/#{command_name}_command"
- rescue LoadError => e
- load_error = e
+ rescue LoadError
+ # it may have been defined from a rubygems_plugin.rb file
end
+
Gem::Commands.const_get(const_name).new
rescue StandardError => e
- e = load_error if load_error
-
alert_error clean_text("Loading command: #{command_name} (#{e.class})\n\t#{e}")
ui.backtrace e
end
diff --git a/lib/rubygems/commands/build_command.rb b/lib/rubygems/commands/build_command.rb
index 2ec8324141..cfe1f8ec3c 100644
--- a/lib/rubygems/commands/build_command.rb
+++ b/lib/rubygems/commands/build_command.rb
@@ -25,13 +25,6 @@ class Gem::Commands::BuildCommand < Gem::Command
add_option "-o", "--output FILE", "output gem with the given filename" do |value, options|
options[:output] = value
end
-
- add_option "-C PATH", "Run as if gem build was started in <PATH> instead of the current working directory." do |value, options|
- options[:build_path] = value
- end
- deprecate_option "-C",
- version: "4.0",
- extra_msg: "-C is a global flag now. Use `gem -C PATH build GEMSPEC_FILE [options]` instead"
end
def arguments # :nodoc:
diff --git a/lib/rubygems/commands/cert_command.rb b/lib/rubygems/commands/cert_command.rb
index 72dcf1dd17..fe03841ddb 100644
--- a/lib/rubygems/commands/cert_command.rb
+++ b/lib/rubygems/commands/cert_command.rb
@@ -158,7 +158,7 @@ class Gem::Commands::CertCommand < Gem::Command
cert = Gem::Security.create_cert_email(
email,
key,
- (Gem::Security::ONE_DAY * expiration_length_days)
+ Gem::Security::ONE_DAY * expiration_length_days
)
Gem::Security.write cert, "gem-public_cert.pem"
diff --git a/lib/rubygems/commands/cleanup_command.rb b/lib/rubygems/commands/cleanup_command.rb
index 08fb598cea..c89a24eee9 100644
--- a/lib/rubygems/commands/cleanup_command.rb
+++ b/lib/rubygems/commands/cleanup_command.rb
@@ -38,8 +38,6 @@ class Gem::Commands::CleanupCommand < Gem::Command
@default_gems = []
@full = nil
@gems_to_cleanup = nil
- @original_home = nil
- @original_path = nil
@primary_gems = nil
end
@@ -95,9 +93,6 @@ If no gems are named all gems in GEM_HOME are cleaned.
end
def clean_gems
- @original_home = Gem.dir
- @original_path = Gem.path
-
get_primary_gems
get_candidate_gems
get_gems_to_cleanup
@@ -112,17 +107,15 @@ If no gems are named all gems in GEM_HOME are cleaned.
deps.reverse_each do |spec|
uninstall_dep spec
end
-
- Gem::Specification.reset
end
def get_candidate_gems
@candidate_gems = if options[:args].empty?
Gem::Specification.to_a
else
- options[:args].map do |gem_name|
+ options[:args].flat_map do |gem_name|
Gem::Specification.find_all_by_name gem_name
- end.flatten
+ end
end
end
@@ -133,7 +126,7 @@ If no gems are named all gems in GEM_HOME are cleaned.
default_gems, gems_to_cleanup = gems_to_cleanup.partition(&:default_gem?)
- uninstall_from = options[:user_install] ? Gem.user_dir : @original_home
+ uninstall_from = options[:user_install] ? Gem.user_dir : Gem.dir
gems_to_cleanup = gems_to_cleanup.select do |spec|
spec.base_dir == uninstall_from
@@ -181,8 +174,5 @@ If no gems are named all gems in GEM_HOME are cleaned.
say "Unable to uninstall #{spec.full_name}:"
say "\t#{e.class}: #{e.message}"
end
- ensure
- # Restore path Gem::Uninstaller may have changed
- Gem.use_paths @original_home, *@original_path
end
end
diff --git a/lib/rubygems/commands/contents_command.rb b/lib/rubygems/commands/contents_command.rb
index 807158d9c9..d4f9871868 100644
--- a/lib/rubygems/commands/contents_command.rb
+++ b/lib/rubygems/commands/contents_command.rb
@@ -102,15 +102,22 @@ prefix or only the files that are requireable.
end
def files_in_default_gem(spec)
- spec.files.map do |file|
- case file
- when %r{\A#{spec.bindir}/}
- # $' is POSTMATCH
- [RbConfig::CONFIG["bindir"], $']
- when /\.so\z/
- [RbConfig::CONFIG["archdir"], file]
+ spec.files.filter_map do |file|
+ if file.start_with?("#{spec.bindir}/")
+ [RbConfig::CONFIG["bindir"], file.delete_prefix("#{spec.bindir}/")]
else
- [RbConfig::CONFIG["rubylibdir"], file]
+ gem spec.name, spec.version
+
+ require_path = spec.require_paths.find do |path|
+ file.start_with?("#{path}/")
+ end
+
+ requirable_part = file.delete_prefix("#{require_path}/")
+
+ resolve = $LOAD_PATH.resolve_feature_path(requirable_part)&.last
+ next unless resolve
+
+ [resolve.delete_suffix(requirable_part), requirable_part]
end
end
end
@@ -182,8 +189,8 @@ prefix or only the files that are requireable.
end
def specification_directories # :nodoc:
- options[:specdirs].map do |i|
+ options[:specdirs].flat_map do |i|
[i, File.join(i, "specifications")]
- end.flatten
+ end
end
end
diff --git a/lib/rubygems/commands/environment_command.rb b/lib/rubygems/commands/environment_command.rb
index 8ed0996069..aea8c0d7de 100644
--- a/lib/rubygems/commands/environment_command.rb
+++ b/lib/rubygems/commands/environment_command.rb
@@ -15,6 +15,7 @@ class Gem::Commands::EnvironmentCommand < Gem::Command
version display the gem format version
remotesources display the remote gem servers
platform display the supported gem platforms
+ credentials display the path where credentials are stored
<omitted> display everything
EOF
args.gsub(/^\s+/, "")
@@ -88,6 +89,8 @@ lib/rubygems/defaults/operating_system.rb
Gem.sources.to_a.join("\n")
when /^platform/ then
Gem.platforms.join(File::PATH_SEPARATOR)
+ when /^credentials/, /^creds/ then
+ Gem.configuration.credentials_path
when nil then
show_environment
else
@@ -114,6 +117,8 @@ lib/rubygems/defaults/operating_system.rb
out << " - USER INSTALLATION DIRECTORY: #{Gem.user_dir}\n"
+ out << " - CREDENTIALS FILE: #{Gem.configuration.credentials_path}\n"
+
out << " - RUBYGEMS PREFIX: #{Gem.prefix}\n" unless Gem.prefix.nil?
out << " - RUBY EXECUTABLE: #{Gem.ruby}\n"
diff --git a/lib/rubygems/commands/exec_command.rb b/lib/rubygems/commands/exec_command.rb
index d588804290..c24ebbf711 100644
--- a/lib/rubygems/commands/exec_command.rb
+++ b/lib/rubygems/commands/exec_command.rb
@@ -57,8 +57,6 @@ to the same gem path as user-installed gems.
end
def execute
- gem_paths = { "GEM_HOME" => Gem.paths.home, "GEM_PATH" => Gem.paths.path.join(File::PATH_SEPARATOR), "GEM_SPEC_CACHE" => Gem.paths.spec_cache_dir }.compact
-
check_executable
print_command
@@ -74,9 +72,6 @@ to the same gem path as user-installed gems.
end
load!
- ensure
- ENV.update(gem_paths) if gem_paths
- Gem.clear_paths
end
private
@@ -143,7 +138,7 @@ to the same gem path as user-installed gems.
end
def set_gem_exec_install_paths
- home = File.join(Gem.dir, "gem_exec")
+ home = Gem.dir
ENV["GEM_PATH"] = ([home] + Gem.path).join(File::PATH_SEPARATOR)
ENV["GEM_HOME"] = home
@@ -200,7 +195,7 @@ to the same gem path as user-installed gems.
argv = ARGV.clone
ARGV.replace options[:args]
- exe = executable = options[:executable]
+ executable = options[:executable]
contains_executable = Gem.loaded_specs.values.select do |spec|
spec.executables.include?(executable)
@@ -211,13 +206,22 @@ to the same gem path as user-installed gems.
end
if contains_executable.empty?
- if (spec = Gem.loaded_specs[executable]) && (exe = spec.executable)
- contains_executable << spec
- else
+ spec = Gem.loaded_specs[executable]
+
+ if spec.nil? || spec.executables.empty?
alert_error "Failed to load executable `#{executable}`," \
" are you sure the gem `#{options[:gem_name]}` contains it?"
terminate_interaction 1
end
+
+ if spec.executables.size > 1
+ alert_error "Ambiguous which executable from gem `#{executable}` should be run: " \
+ "the options are #{spec.executables.sort}, specify one via COMMAND, and use `-g` and `-v` to specify gem and version"
+ terminate_interaction 1
+ end
+
+ contains_executable << spec
+ executable = spec.executable
end
if contains_executable.size > 1
@@ -227,8 +231,11 @@ to the same gem path as user-installed gems.
terminate_interaction 1
end
- load Gem.activate_bin_path(contains_executable.first.name, exe, ">= 0.a")
+ old_exe = $0
+ $0 = executable
+ load Gem.activate_bin_path(contains_executable.first.name, executable, ">= 0.a")
ensure
+ $0 = old_exe if old_exe
ARGV.replace argv
end
diff --git a/lib/rubygems/commands/fetch_command.rb b/lib/rubygems/commands/fetch_command.rb
index f7f5b62306..c524cf7922 100644
--- a/lib/rubygems/commands/fetch_command.rb
+++ b/lib/rubygems/commands/fetch_command.rb
@@ -63,6 +63,17 @@ then repackaging it.
def execute
check_version
+
+ exit_code = fetch_gems
+
+ terminate_interaction exit_code
+ end
+
+ private
+
+ def fetch_gems
+ exit_code = 0
+
version = options[:version]
platform = Gem.platforms.last
@@ -86,10 +97,13 @@ then repackaging it.
if spec.nil?
show_lookup_failure gem_name, gem_version, errors, suppress_suggestions, options[:domain]
+ exit_code |= 2
next
end
source.download spec
say "Downloaded #{spec.full_name}"
end
+
+ exit_code
end
end
diff --git a/lib/rubygems/commands/install_command.rb b/lib/rubygems/commands/install_command.rb
index 2091634a29..70d32013ba 100644
--- a/lib/rubygems/commands/install_command.rb
+++ b/lib/rubygems/commands/install_command.rb
@@ -224,10 +224,6 @@ You can use `i` command instead of `install`.
rescue Gem::InstallError => e
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, suppress_suggestions
-
- exit_code |= 2
rescue Gem::UnsatisfiableDependencyError => e
show_lookup_failure e.name, e.version, e.errors, suppress_suggestions,
"'#{gem_name}' (#{gem_version})"
@@ -243,11 +239,7 @@ You can use `i` command instead of `install`.
# Loads post-install hooks
def load_hooks # :nodoc:
- if options[:install_as_default]
- require_relative "../install_default_message"
- else
- require_relative "../install_message"
- end
+ require_relative "../install_message"
require_relative "../rdoc"
end
diff --git a/lib/rubygems/commands/pristine_command.rb b/lib/rubygems/commands/pristine_command.rb
index 999c9fef0f..942b75fba1 100644
--- a/lib/rubygems/commands/pristine_command.rb
+++ b/lib/rubygems/commands/pristine_command.rb
@@ -88,6 +88,10 @@ If you have made modifications to an installed gem, the pristine command
will revert them. All extensions are rebuilt and all bin stubs for the gem
are regenerated after checking for modifications.
+Rebuilding extensions also refreshes C-extension gems against updated system
+libraries (for example after OS or package upgrades) to avoid mismatches like
+outdated library version warnings.
+
If the cached gem cannot be found it will be downloaded.
If --no-extensions is provided pristine will not attempt to restore a gem
@@ -120,9 +124,9 @@ extensions will be restored.
elsif options[:only_missing_extensions]
specification_record.select(&:missing_extensions?)
else
- get_all_gem_names.sort.map do |gem_name|
+ get_all_gem_names.sort.flat_map do |gem_name|
specification_record.find_all_by_name(gem_name, options[:version]).reverse
- end.flatten
+ end
end
specs = specs.select {|spec| spec.platform == RUBY_ENGINE || Gem::Platform.local === spec.platform || spec.platform == Gem::Platform::RUBY }
@@ -134,10 +138,17 @@ extensions will be restored.
say "Restoring gems to pristine condition..."
- specs.each do |spec|
- if spec.default_gem?
- say "Skipped #{spec.full_name}, it is a default gem"
- next
+ specs.group_by(&:full_name_with_location).values.each do |grouped_specs|
+ spec = grouped_specs.find {|s| !s.default_gem? } || grouped_specs.first
+
+ only_executables = options[:only_executables]
+ only_plugins = options[:only_plugins]
+
+ unless only_executables || only_plugins
+ # Default gemspecs include changes provided by ruby-core installer that
+ # can't currently be pristined (inclusion of compiled extension targets in
+ # the file list). So stick to resetting executables if it's a default gem.
+ only_executables = true if spec.default_gem?
end
if options.key? :skip
@@ -147,14 +158,14 @@ extensions will be restored.
end
end
- unless spec.extensions.empty? || options[:extensions] || options[:only_executables] || options[:only_plugins]
+ unless spec.extensions.empty? || options[:extensions] || only_executables || only_plugins
say "Skipped #{spec.full_name_with_location}, it needs to compile an extension"
next
end
gem = spec.cache_file
- unless File.exist?(gem) || options[:only_executables] || options[:only_plugins]
+ unless File.exist?(gem) || only_executables || only_plugins
require_relative "../remote_fetcher"
say "Cached gem for #{spec.full_name_with_location} not found, attempting to fetch..."
@@ -190,10 +201,10 @@ extensions will be restored.
bin_dir: bin_dir,
}
- if options[:only_executables]
+ if only_executables
installer = Gem::Installer.for_spec(spec, installer_options)
installer.generate_bin
- elsif options[:only_plugins]
+ elsif only_plugins
installer = Gem::Installer.for_spec(spec, installer_options)
installer.generate_plugins
else
diff --git a/lib/rubygems/commands/push_command.rb b/lib/rubygems/commands/push_command.rb
index 591ddc3a80..d2ce86703b 100644
--- a/lib/rubygems/commands/push_command.rb
+++ b/lib/rubygems/commands/push_command.rb
@@ -30,7 +30,7 @@ The push command will use ~/.gem/credentials to authenticate to a server, but yo
end
def initialize
- super "push", "Push a gem up to the gem server", host: host
+ super "push", "Push a gem up to the gem server", host: host, attestations: []
@user_defined_host = false
@@ -45,6 +45,11 @@ The push command will use ~/.gem/credentials to authenticate to a server, but yo
@user_defined_host = true
end
+ add_option("--attestation FILE",
+ "Push with sigstore attestations") do |value, options|
+ options[:attestations] << value
+ end
+
@host = nil
end
@@ -87,11 +92,20 @@ The push command will use ~/.gem/credentials to authenticate to a server, but yo
private
def send_push_request(name, args)
- 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
+ scope = get_push_scope
+ rubygems_api_request(*args, scope: scope) do |request|
+ body = Gem.read_binary name
+ if options[:attestations].any?
+ request.set_form([
+ ["gem", body, { filename: name, content_type: "application/octet-stream" }],
+ get_attestations_part,
+ ], "multipart/form-data")
+ else
+ request.body = body
+ request.add_field "Content-Type", "application/octet-stream"
+ request.add_field "Content-Length", request.body.size
+ end
+ request.add_field "Authorization", api_key
end
end
@@ -107,4 +121,15 @@ The push command will use ~/.gem/credentials to authenticate to a server, but yo
def get_push_scope
:push_rubygem
end
+
+ def get_attestations_part
+ bundles = "[" + options[:attestations].map do |attestation|
+ Gem.read_binary(attestation)
+ end.join(",") + "]"
+ [
+ "attestations",
+ bundles,
+ { content_type: "application/json" },
+ ]
+ end
end
diff --git a/lib/rubygems/commands/query_command.rb b/lib/rubygems/commands/query_command.rb
deleted file mode 100644
index 3b527974a3..0000000000
--- a/lib/rubygems/commands/query_command.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "../command"
-require_relative "../query_utils"
-require_relative "../deprecate"
-
-class Gem::Commands::QueryCommand < Gem::Command
- extend Gem::Deprecate
- rubygems_deprecate_command
-
- include Gem::QueryUtils
-
- alias_method :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,
- domain: :local, details: false, versions: true,
- installed: nil, version: Gem::Requirement.default
-
- 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_query_options
- end
-
- def description # :nodoc:
- <<-EOF
-The query command is the basis for the list and search commands.
-
-You should really use the list and search commands instead. This command
-is too hard to use.
- EOF
- end
-end
diff --git a/lib/rubygems/commands/rdoc_command.rb b/lib/rubygems/commands/rdoc_command.rb
index 977c90b8c4..62c4bf8ce9 100644
--- a/lib/rubygems/commands/rdoc_command.rb
+++ b/lib/rubygems/commands/rdoc_command.rb
@@ -64,9 +64,9 @@ Use --overwrite to force rebuilding of documentation.
specs = if options[:all]
Gem::Specification.to_a
else
- get_all_gem_names.map do |name|
+ get_all_gem_names.flat_map do |name|
Gem::Specification.find_by_name name, options[:version]
- end.flatten.uniq
+ end.uniq
end
if specs.empty?
diff --git a/lib/rubygems/commands/rebuild_command.rb b/lib/rubygems/commands/rebuild_command.rb
index 77a474ef1d..23b9d7b3ba 100644
--- a/lib/rubygems/commands/rebuild_command.rb
+++ b/lib/rubygems/commands/rebuild_command.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: true
-require "date"
require "digest"
require "fileutils"
require "tmpdir"
diff --git a/lib/rubygems/commands/setup_command.rb b/lib/rubygems/commands/setup_command.rb
index 9c633d6ef7..175599967c 100644
--- a/lib/rubygems/commands/setup_command.rb
+++ b/lib/rubygems/commands/setup_command.rb
@@ -7,8 +7,8 @@ require_relative "../command"
# RubyGems checkout or tarball.
class Gem::Commands::SetupCommand < Gem::Command
- HISTORY_HEADER = %r{^#\s*[\d.a-zA-Z]+\s*/\s*\d{4}-\d{2}-\d{2}\s*$}
- VERSION_MATCHER = %r{^#\s*([\d.a-zA-Z]+)\s*/\s*\d{4}-\d{2}-\d{2}\s*$}
+ HISTORY_HEADER = %r{^##\s*[\d.a-zA-Z]+\s*/\s*\d{4}-\d{2}-\d{2}\s*$}
+ VERSION_MATCHER = %r{^##\s*([\d.a-zA-Z]+)\s*/\s*\d{4}-\d{2}-\d{2}\s*$}
ENV_PATHS = %w[/usr/bin/env /bin/env].freeze
@@ -107,15 +107,6 @@ class Gem::Commands::SetupCommand < Gem::Command
@verbose = nil
end
- def check_ruby_version
- required_version = Gem::Requirement.new ">= 2.6.0"
-
- unless required_version.satisfied_by? Gem.ruby_version
- alert_error "Expected Ruby version #{required_version}, is #{Gem.ruby_version}"
- terminate_interaction 1
- end
- end
-
def defaults_str # :nodoc:
"--format-executable --document ri --regenerate-binstubs"
end
@@ -148,8 +139,6 @@ By default, this RubyGems will install gem as:
def execute
@verbose = Gem.configuration.really_verbose
- check_ruby_version
-
require "fileutils"
if Gem.configuration.really_verbose
extend FileUtils::Verbose
@@ -279,11 +268,7 @@ By default, this RubyGems will install gem as:
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
- GOTO :EOF
- :WinNT
- @"#{File.basename(Gem.ruby).chomp('"')}" "%~dpn0" %*
+ @"%~dp0#{File.basename(Gem.ruby).chomp('"')}" "%~dpn0" %*
TEXT
end
@@ -340,6 +325,8 @@ By default, this RubyGems will install gem as:
require_relative "../rdoc"
+ return false unless defined?(Gem::RDoc)
+
fake_spec = Gem::Specification.new "rubygems", Gem::VERSION
def fake_spec.full_gem_path
File.expand_path "../../..", __dir__
@@ -363,9 +350,15 @@ By default, this RubyGems will install gem as:
def install_default_bundler_gem(bin_dir)
current_default_spec = Gem::Specification.default_stubs.find {|s| s.name == "bundler" }
specs_dir = if current_default_spec && default_dir == Gem.default_dir
+ all_specs_current_version = Gem::Specification.stubs.select {|s| s.full_name == current_default_spec.full_name }
+
Gem::Specification.remove_spec current_default_spec
loaded_from = current_default_spec.loaded_from
File.delete(loaded_from)
+
+ # Remove previous default gem executables if they were not shadowed by a regular gem
+ FileUtils.rm_rf current_default_spec.full_gem_path if all_specs_current_version.size == 1
+
File.dirname(loaded_from)
else
target_specs_dir = File.join(default_dir, "specifications", "default")
@@ -400,16 +393,20 @@ By default, this RubyGems will install gem as:
Dir.chdir("bundler") do
built_gem = Gem::Package.build(new_bundler_spec)
begin
- Gem::Installer.at(
+ 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,
install_dir: default_dir,
wrappers: true
- ).install
+ )
+ # We need to install only executable and default spec files.
+ # lib/bundler.rb and lib/bundler/* are available under the site_ruby directory.
+ installer.extract_bin
+ installer.generate_bin
+ installer.write_default_spec
ensure
FileUtils.rm_f built_gem
end
diff --git a/lib/rubygems/commands/sources_command.rb b/lib/rubygems/commands/sources_command.rb
index 976f4a4ea2..7e5c2a2465 100644
--- a/lib/rubygems/commands/sources_command.rb
+++ b/lib/rubygems/commands/sources_command.rb
@@ -18,6 +18,14 @@ class Gem::Commands::SourcesCommand < Gem::Command
options[:add] = value
end
+ add_option "--append SOURCE_URI", "Append source (can be used multiple times)" do |value, options|
+ options[:append] = value
+ end
+
+ add_option "-p", "--prepend SOURCE_URI", "Prepend source (can be used multiple times)" do |value, options|
+ options[:prepend] = value
+ end
+
add_option "-l", "--list", "List sources" do |value, options|
options[:list] = value
end
@@ -26,8 +34,7 @@ class Gem::Commands::SourcesCommand < Gem::Command
options[:remove] = value
end
- add_option "-c", "--clear-all",
- "Remove all sources (clear the cache)" do |value, options|
+ add_option "-c", "--clear-all", "Remove all sources (clear the cache)" do |value, options|
options[:clear_all] = value
end
@@ -68,6 +75,60 @@ class Gem::Commands::SourcesCommand < Gem::Command
end
end
+ def append_source(source_uri) # :nodoc:
+ check_rubygems_https source_uri
+
+ source = Gem::Source.new source_uri
+
+ check_typo_squatting(source)
+
+ begin
+ source.load_specs :released
+ was_present = Gem.sources.include?(source)
+ Gem.sources.append source
+ Gem.configuration.write
+
+ if was_present
+ say "#{source_uri} moved to end of sources"
+ else
+ say "#{source_uri} added to sources"
+ end
+ rescue Gem::URI::Error, ArgumentError
+ say "#{source_uri} is not a URI"
+ terminate_interaction 1
+ rescue Gem::RemoteFetcher::FetchError => e
+ say "Error fetching #{Gem::Uri.redact(source.uri)}:\n\t#{e.message}"
+ terminate_interaction 1
+ end
+ end
+
+ def prepend_source(source_uri) # :nodoc:
+ check_rubygems_https source_uri
+
+ source = Gem::Source.new source_uri
+
+ check_typo_squatting(source)
+
+ begin
+ source.load_specs :released
+ was_present = Gem.sources.include?(source)
+ Gem.sources.prepend source
+ Gem.configuration.write
+
+ if was_present
+ say "#{source_uri} moved to top of sources"
+ else
+ say "#{source_uri} added to sources"
+ end
+ rescue Gem::URI::Error, ArgumentError
+ say "#{source_uri} is not a URI"
+ terminate_interaction 1
+ rescue Gem::RemoteFetcher::FetchError => e
+ say "Error fetching #{Gem::Uri.redact(source.uri)}:\n\t#{e.message}"
+ terminate_interaction 1
+ end
+ end
+
def check_typo_squatting(source)
if source.typo_squatting?("rubygems.org")
question = <<-QUESTION.chomp
@@ -128,7 +189,7 @@ yourself to use your own gem server.
Without any arguments the sources lists your currently configured sources:
$ gem sources
- *** CURRENT SOURCES ***
+ *** NO CONFIGURED SOURCES, DEFAULT SOURCES LISTED BELOW ***
https://rubygems.org
@@ -147,33 +208,49 @@ Since all of these sources point to the same set of gems you only need one
of them in your list. https://rubygems.org is recommended as it brings the
protections of an SSL connection to gem downloads.
-To add a source use the --add argument:
+To add a private gem source use the --prepend argument to insert it before
+the default source. This is usually the best place for private gem sources:
- $ gem sources --add https://rubygems.org
- https://rubygems.org added to sources
+ $ gem sources --prepend https://my.private.source
+ https://my.private.source added to sources
RubyGems will check to see if gems can be installed from the source given
before it is added.
+To add or move a source after all other sources, use --append:
+
+ $ gem sources --append https://rubygems.org
+ https://rubygems.org moved to end of sources
+
To remove a source use the --remove argument:
- $ gem sources --remove https://rubygems.org/
- https://rubygems.org/ removed from sources
+ $ gem sources --remove https://my.private.source/
+ https://my.private.source/ removed from sources
EOF
end
def list # :nodoc:
- say "*** CURRENT SOURCES ***"
+ if configured_sources
+ header = "*** CURRENT SOURCES ***"
+ list = configured_sources
+ else
+ header = "*** NO CONFIGURED SOURCES, DEFAULT SOURCES LISTED BELOW ***"
+ list = Gem.sources
+ end
+
+ say header
say
- Gem.sources.each do |src|
+ list.each do |src|
say src
end
end
def list? # :nodoc:
!(options[:add] ||
+ options[:prepend] ||
+ options[:append] ||
options[:clear_all] ||
options[:remove] ||
options[:update])
@@ -182,11 +259,13 @@ To remove a source use the --remove argument:
def execute
clear_all if options[:clear_all]
- source_uri = options[:add]
- add_source source_uri if source_uri
+ add_source options[:add] if options[:add]
+
+ prepend_source options[:prepend] if options[:prepend]
+
+ append_source options[:append] if options[:append]
- source_uri = options[:remove]
- remove_source source_uri if source_uri
+ remove_source options[:remove] if options[:remove]
update if options[:update]
@@ -194,13 +273,21 @@ To remove a source use the --remove argument:
end
def remove_source(source_uri) # :nodoc:
- if Gem.sources.include? source_uri
- Gem.sources.delete source_uri
+ source = Gem::Source.new source_uri
+
+ if configured_sources&.include? source
+ Gem.sources.delete source
Gem.configuration.write
- say "#{source_uri} removed from sources"
+ if default_sources.include?(source) && configured_sources.one?
+ alert_warning "Removing a default source when it is the only source has no effect. Add a different source to #{config_file_name} if you want to stop using it as a source."
+ else
+ say "#{source_uri} removed from sources"
+ end
+ elsif configured_sources
+ say "source #{source_uri} cannot be removed because it's not present in #{config_file_name}"
else
- say "source #{source_uri} not present in cache"
+ say "source #{source_uri} cannot be removed because there are no configured sources in #{config_file_name}"
end
end
@@ -224,4 +311,21 @@ To remove a source use the --remove argument:
say "*** Unable to remove #{desc} source cache ***"
end
end
+
+ private
+
+ def default_sources
+ Gem::SourceList.from(Gem.default_sources)
+ end
+
+ def configured_sources
+ return @configured_sources if defined?(@configured_sources)
+
+ configuration_sources = Gem.configuration.sources
+ @configured_sources = Gem::SourceList.from(configuration_sources) if configuration_sources
+ end
+
+ def config_file_name
+ Gem.configuration.config_file_name
+ end
end
diff --git a/lib/rubygems/commands/uninstall_command.rb b/lib/rubygems/commands/uninstall_command.rb
index 283bc96ce3..3d6e41e49e 100644
--- a/lib/rubygems/commands/uninstall_command.rb
+++ b/lib/rubygems/commands/uninstall_command.rb
@@ -157,9 +157,14 @@ that is a dependency of an existing gem. You can use the
gem_specs = Gem::Specification.find_all_by_name(name, original_gem_version[name])
- say("Gem '#{name}' is not installed") if gem_specs.empty?
- gem_specs.each do |spec|
- deplist.add spec
+ if gem_specs.empty?
+ say("Gem '#{name}' is not installed")
+ else
+ gem_specs.reject!(&:default_gem?) if gem_specs.size > 1
+
+ gem_specs.each do |spec|
+ deplist.add spec
+ end
end
end
diff --git a/lib/rubygems/commands/update_command.rb b/lib/rubygems/commands/update_command.rb
index 8e80d46856..d9740d814a 100644
--- a/lib/rubygems/commands/update_command.rb
+++ b/lib/rubygems/commands/update_command.rb
@@ -317,16 +317,10 @@ command to remove old versions.
#
# 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
+ # originally ships with the oldest supported patch version of ruby.
#
def oldest_supported_version
@oldest_supported_version ||=
- if Gem.ruby_version > Gem::Version.new("3.1.a")
- Gem::Version.new("3.3.3")
- else
- Gem::Version.new("3.2.3")
- end
+ Gem::Version.new("3.3.3")
end
end
diff --git a/lib/rubygems/compatibility.rb b/lib/rubygems/compatibility.rb
deleted file mode 100644
index 0d9df56f8a..0000000000
--- a/lib/rubygems/compatibility.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-#--
-# This file contains all sorts of little compatibility hacks that we've
-# had to introduce over the years. Quarantining them into one file helps
-# us know when we can get rid of them.
-#
-# Ruby 1.9.x has introduced some things that are awkward, and we need to
-# support them, so we define some constants to use later.
-#
-# TODO remove at RubyGems 4
-#++
-
-module Gem
- # :stopdoc:
-
- RubyGemsVersion = VERSION
- deprecate_constant(:RubyGemsVersion)
-
- RbConfigPriorities = %w[
- MAJOR
- MINOR
- TEENY
- EXEEXT RUBY_SO_NAME arch bindir datadir libdir ruby_install_name
- ruby_version rubylibprefix sitedir sitelibdir vendordir vendorlibdir
- rubylibdir
- ].freeze
-
- if defined?(ConfigMap)
- RbConfigPriorities.each do |key|
- ConfigMap[key.to_sym] = RbConfig::CONFIG[key]
- end
- else
- ##
- # Configuration settings from ::RbConfig
- ConfigMap = Hash.new do |cm, key|
- cm[key] = RbConfig::CONFIG[key.to_s]
- end
- deprecate_constant(:ConfigMap)
- end
-end
diff --git a/lib/rubygems/config_file.rb b/lib/rubygems/config_file.rb
index 7874ad0dc9..e58a83f6b7 100644
--- a/lib/rubygems/config_file.rb
+++ b/lib/rubygems/config_file.rb
@@ -345,7 +345,7 @@ if you believe they were disclosed to a third party.
require "fileutils"
FileUtils.mkdir_p(dirname)
- permissions = 0o600 & (~File.umask)
+ permissions = 0o600 & ~File.umask
File.open(credentials_path, "w", permissions) do |f|
f.write self.class.dump_with_rubygems_yaml(config)
end
@@ -522,12 +522,12 @@ if you believe they were disclosed to a third party.
# Return the configuration information for +key+.
def [](key)
- @hash[key.to_s]
+ @hash[key] || @hash[key.to_s]
end
# Set configuration option +key+ to +value+.
def []=(key, value)
- @hash[key.to_s] = value
+ @hash[key] = value
end
def ==(other) # :nodoc:
@@ -555,8 +555,13 @@ if you believe they were disclosed to a third party.
require_relative "yaml_serializer"
content = Gem::YAMLSerializer.load(yaml)
+ deep_transform_config_keys!(content)
+ end
- content.transform_keys! do |k|
+ private
+
+ def self.deep_transform_config_keys!(config)
+ config.transform_keys! do |k|
if k.match?(/\A:(.*)\Z/)
k[1..-1].to_sym
elsif k.include?("__") || k.match?(%r{/\Z})
@@ -570,7 +575,7 @@ if you believe they were disclosed to a third party.
end
end
- content.transform_values! do |v|
+ config.transform_values! do |v|
if v.is_a?(String)
if v.match?(/\A:(.*)\Z/)
v[1..-1].to_sym
@@ -583,18 +588,18 @@ if you believe they were disclosed to a third party.
else
v
end
- elsif v.is_a?(Hash) && v.empty?
+ elsif v.empty?
nil
+ elsif v.is_a?(Hash)
+ deep_transform_config_keys!(v)
else
v
end
end
- content
+ config
end
- private
-
def set_config_file_name(args)
@config_file_name = ENV["GEMRC"]
need_config_file_name = false
diff --git a/lib/rubygems/core_ext/kernel_require.rb b/lib/rubygems/core_ext/kernel_require.rb
index 073966b696..3a9bdbdc9d 100644
--- a/lib/rubygems/core_ext/kernel_require.rb
+++ b/lib/rubygems/core_ext/kernel_require.rb
@@ -64,8 +64,11 @@ module Kernel
rp
end
- Kernel.send(:gem, name, Gem::Requirement.default_prerelease) unless
- resolved_path
+ next if resolved_path
+
+ Kernel.send(:gem, name, Gem::Requirement.default_prerelease)
+
+ Gem.load_bundler_extensions(Gem.loaded_specs[name].version) if name == "bundler"
next
end
diff --git a/lib/rubygems/core_ext/kernel_warn.rb b/lib/rubygems/core_ext/kernel_warn.rb
index 9dc9f2218c..f806b77fab 100644
--- a/lib/rubygems/core_ext/kernel_warn.rb
+++ b/lib/rubygems/core_ext/kernel_warn.rb
@@ -13,11 +13,7 @@ module Kernel
module_function define_method(:warn) {|*messages, **kw|
unless uplevel = kw[:uplevel]
- if Gem.java_platform? && RUBY_VERSION < "3.1"
- return original_warn.bind(self).call(*messages)
- else
- return original_warn.bind(self).call(*messages, **kw)
- end
+ return original_warn.bind_call(self, *messages, **kw)
end
# Ensure `uplevel` fits a `long`
@@ -44,6 +40,6 @@ module Kernel
kw[:uplevel] = start
end
- original_warn.bind(self).call(*messages, **kw)
+ original_warn.bind_call(self, *messages, **kw)
}
end
diff --git a/lib/rubygems/defaults.rb b/lib/rubygems/defaults.rb
index 1bd208feb9..90f09fc191 100644
--- a/lib/rubygems/defaults.rb
+++ b/lib/rubygems/defaults.rb
@@ -13,7 +13,7 @@ module Gem
# An Array of the default sources that come with RubyGems
def self.default_sources
- %w[https://rubygems.org/]
+ @default_sources ||= %w[https://rubygems.org/]
end
##
@@ -239,7 +239,7 @@ module Gem
# Enables automatic installation into user directory
def self.default_user_install # :nodoc:
- if !ENV.key?("GEM_HOME") && (File.exist?(Gem.dir) && !File.writable?(Gem.dir))
+ if !ENV.key?("GEM_HOME") && File.exist?(Gem.dir) && !File.writable?(Gem.dir)
Gem.ui.say "Defaulting to user installation because default installation directory (#{Gem.dir}) is not writable."
return true
end
diff --git a/lib/rubygems/dependency.rb b/lib/rubygems/dependency.rb
index 5ce9c5e840..1e91f493a6 100644
--- a/lib/rubygems/dependency.rb
+++ b/lib/rubygems/dependency.rb
@@ -217,7 +217,7 @@ class Gem::Dependency
# NOTE: Unlike #matches_spec? this method does not return true when the
# version is a prerelease version unless this is a prerelease dependency.
- def match?(obj, version=nil, allow_prerelease=false)
+ def match?(obj, version = nil, allow_prerelease = false)
if !version
name = obj.name
version = obj.version
@@ -279,7 +279,7 @@ class Gem::Dependency
end
end
- matches
+ matches.reject(&:ignored?)
end
##
@@ -337,4 +337,12 @@ class Gem::Dependency
:released
end
end
+
+ def encode_with(coder) # :nodoc:
+ coder.add "name", @name
+ coder.add "requirement", @requirement
+ coder.add "type", @type
+ coder.add "prerelease", @prerelease
+ coder.add "version_requirements", @version_requirements
+ end
end
diff --git a/lib/rubygems/dependency_installer.rb b/lib/rubygems/dependency_installer.rb
index b119dca1cf..6a6dfa5c20 100644
--- a/lib/rubygems/dependency_installer.rb
+++ b/lib/rubygems/dependency_installer.rb
@@ -7,14 +7,12 @@ 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
DEFAULT_OPTIONS = { # :nodoc:
env_shebang: false,
@@ -28,7 +26,6 @@ class Gem::DependencyInstaller
wrappers: true,
build_args: nil,
build_docs_in_background: false,
- install_as_default: false,
}.freeze
##
@@ -86,8 +83,8 @@ class Gem::DependencyInstaller
@user_install = options[:user_install]
@wrappers = options[:wrappers]
@build_args = options[:build_args]
+ @build_jobs = options[:build_jobs]
@build_docs_in_background = options[:build_docs_in_background]
- @install_as_default = options[:install_as_default]
@dir_mode = options[:dir_mode]
@data_mode = options[:data_mode]
@prog_mode = options[:prog_mode]
@@ -121,78 +118,6 @@ class Gem::DependencyInstaller
@domain == :both || @domain == :remote
end
- ##
- # Returns a list of pairs of gemspecs and source_uris that match
- # Gem::Dependency +dep+ from both local (Dir.pwd) and remote (Gem.sources)
- # sources. Gems are sorted with newer gems preferred over older gems, and
- # local gems preferred over remote gems.
-
- def find_gems_with_sources(dep, best_only=false) # :nodoc:
- set = Gem::AvailableSet.new
-
- if consider_local?
- sl = Gem::Source::Local.new
-
- if spec = sl.find_gem(dep.name)
- if dep.matches_spec? spec
- set.add spec, sl
- end
- end
- end
-
- if consider_remote?
- begin
- # This is pulled from #spec_for_dependency to allow
- # us to filter tuples before fetching specs.
- tuples, errors = Gem::SpecFetcher.fetcher.search_for_dependency dep
-
- if best_only && !tuples.empty?
- tuples.sort! do |a,b|
- if b[0].version == a[0].version
- if b[0].platform != Gem::Platform::RUBY
- 1
- else
- -1
- end
- else
- b[0].version <=> a[0].version
- end
- end
- tuples = [tuples.first]
- end
-
- specs = []
- tuples.each do |tup, source|
- spec = source.fetch_spec(tup)
- rescue Gem::RemoteFetcher::FetchError => e
- errors << Gem::SourceFetchProblem.new(source, e)
- else
- specs << [spec, source]
- end
-
- if @errors
- @errors += errors
- else
- @errors = errors
- end
-
- set << specs
- rescue Gem::RemoteFetcher::FetchError => e
- # FIX if there is a problem talking to the network, we either need to always tell
- # the user (no really_verbose) or fail hard, not silently tell them that we just
- # couldn't find their requested gem.
- verbose do
- "Error fetching remote data:\t\t#{e.message}\n" \
- "Falling back to local-only install"
- end
- @domain = :local
- end
- end
-
- set
- end
- rubygems_deprecate :find_gems_with_sources
-
def in_background(what) # :nodoc:
fork_happened = false
if @build_docs_in_background && Process.respond_to?(:fork)
@@ -230,6 +155,7 @@ class Gem::DependencyInstaller
options = {
bin_dir: @bin_dir,
build_args: @build_args,
+ build_jobs: @build_jobs,
document: @document,
env_shebang: @env_shebang,
force: @force,
@@ -240,7 +166,6 @@ class Gem::DependencyInstaller
user_install: @user_install,
wrappers: @wrappers,
build_root: @build_root,
- install_as_default: @install_as_default,
dir_mode: @dir_mode,
data_mode: @data_mode,
prog_mode: @prog_mode,
diff --git a/lib/rubygems/dependency_list.rb b/lib/rubygems/dependency_list.rb
index ad5e59e8c1..d50cfe2d54 100644
--- a/lib/rubygems/dependency_list.rb
+++ b/lib/rubygems/dependency_list.rb
@@ -7,7 +7,6 @@
#++
require_relative "vendored_tsort"
-require_relative "deprecate"
##
# Gem::DependencyList is used for installing and uninstalling gems in the
@@ -140,7 +139,7 @@ class Gem::DependencyList
# If removing the gemspec creates breaks a currently ok dependency, then it
# is NOT ok to remove the gemspec.
- def ok_to_remove?(full_name, check_dev=true)
+ def ok_to_remove?(full_name, check_dev = true)
gem_to_remove = find_name full_name
# If the state is inconsistent, at least don't crash
diff --git a/lib/rubygems/deprecate.rb b/lib/rubygems/deprecate.rb
index 7d24f9cbfc..eb503bb269 100644
--- a/lib/rubygems/deprecate.rb
+++ b/lib/rubygems/deprecate.rb
@@ -1,75 +1,75 @@
# frozen_string_literal: true
-##
-# 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.some_class_method
-# # ...
-# end
-#
-# def some_instance_method
-# # ...
-# end
-#
-# def some_old_method
-# # ...
-# end
-#
-# extend Gem::Deprecate
-# deprecate :some_instance_method, "X.z", 2011, 4
-# rubygems_deprecate :some_old_method, "Modern#some_new_method"
-#
-# class << self
-# extend Gem::Deprecate
-# 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
-
module Gem
+ ##
+ # Provides 3 methods for declaring when something is going away.
+ #
+ # <tt>deprecate(name, repl, year, month)</tt>:
+ # Indicate something may be removed on/after a certain date.
+ #
+ # <tt>rubygems_deprecate(name, replacement=:none)</tt>:
+ # 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.some_class_method
+ # # ...
+ # end
+ #
+ # def some_instance_method
+ # # ...
+ # end
+ #
+ # def some_old_method
+ # # ...
+ # end
+ #
+ # extend Gem::Deprecate
+ # deprecate :some_instance_method, "X.z", 2011, 4
+ # rubygems_deprecate :some_old_method, "Modern#some_new_method"
+ #
+ # class << self
+ # extend Gem::Deprecate
+ # 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
+
module Deprecate
def self.skip # :nodoc:
@skip ||= false
@@ -126,17 +126,18 @@ module Gem
# 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)
+ def rubygems_deprecate(name, replacement = :none, version = nil)
class_eval do
old = "_deprecated_#{name}"
alias_method old, name
define_method name do |*args, &block|
klass = is_a? Module
target = klass ? "#{self}." : "#{self.class}#"
+ version ||= Gem::Deprecate.next_rubygems_major_version
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}",
+ ". It will be removed in Rubygems #{version}",
"\n#{target}#{name} called from #{Gem.location_of_caller.join(":")}",
]
warn "#{msg.join}." unless Gem::Deprecate.skip
@@ -147,13 +148,14 @@ module Gem
end
# Deprecation method to deprecate Rubygems commands
- def rubygems_deprecate_command(version = Gem::Deprecate.next_rubygems_major_version)
+ def rubygems_deprecate_command(version = nil)
class_eval do
define_method "deprecated?" do
true
end
define_method "deprecation_warning" do
+ version ||= Gem::Deprecate.next_rubygems_major_version
msg = [
"#{command} command is deprecated",
". It will be removed in Rubygems #{version}.\n",
diff --git a/lib/rubygems/doctor.rb b/lib/rubygems/doctor.rb
index 56b7c081eb..4f26260d83 100644
--- a/lib/rubygems/doctor.rb
+++ b/lib/rubygems/doctor.rb
@@ -113,7 +113,7 @@ class Gem::Doctor
next if installed_specs.include? basename
next if /^rubygems-\d/.match?(basename)
next if sub_directory == "specifications" && basename == "default"
- next if sub_directory == "plugins" && Gem.plugin_suffix_regexp =~ (basename)
+ next if sub_directory == "plugins" && Gem.plugin_suffix_regexp =~ basename
type = File.directory?(child) ? "directory" : "file"
diff --git a/lib/rubygems/errors.rb b/lib/rubygems/errors.rb
index be6c34dc85..4bbc5217e0 100644
--- a/lib/rubygems/errors.rb
+++ b/lib/rubygems/errors.rb
@@ -26,10 +26,11 @@ module Gem
# 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, extra_message=nil)
+ def initialize(name, requirement, extra_message = nil)
@name = name
@requirement = requirement
@extra_message = extra_message
+ super(message)
end
def message # :nodoc:
@@ -53,8 +54,8 @@ module Gem
attr_reader :specs
def initialize(name, requirement, specs)
- super(name, requirement)
@specs = specs
+ super(name, requirement)
end
private
diff --git a/lib/rubygems/exceptions.rb b/lib/rubygems/exceptions.rb
index 0308b4687f..40485bbadf 100644
--- a/lib/rubygems/exceptions.rb
+++ b/lib/rubygems/exceptions.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: true
-require_relative "deprecate"
require_relative "unknown_command_spell_checker"
##
@@ -21,20 +20,11 @@ class Gem::UnknownCommandError < Gem::Exception
end
def self.attach_correctable
- return if defined?(@attached)
+ return if method_defined?(:corrections)
- 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
+ if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
+ DidYouMean.correct_error(Gem::UnknownCommandError, Gem::UnknownCommandSpellChecker)
end
-
- @attached = true
end
end
@@ -104,16 +94,13 @@ end
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
# are also stored.
- def initialize(name, version, errors=nil)
+ def initialize(name, version, errors = nil)
super "Could not find a valid gem '#{name}' (#{version}) locally or in a repository"
@name = name
@@ -137,6 +124,8 @@ class Gem::SpecificGemNotFoundException < Gem::GemNotFoundException
attr_reader :errors
end
+Gem.deprecate_constant :SpecificGemNotFoundException
+
##
# Raised by Gem::Resolver when dependencies conflict and create the
# inability to find a valid possible spec for a request.
@@ -262,7 +251,7 @@ class Gem::UnsatisfiableDependencyError < Gem::DependencyError
# Creates a new UnsatisfiableDependencyError for the unsatisfiable
# Gem::Resolver::DependencyRequest +dep+
- def initialize(dep, platform_mismatch=nil)
+ def initialize(dep, platform_mismatch = nil)
if platform_mismatch && !platform_mismatch.empty?
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(", ")}"
diff --git a/lib/rubygems/ext/builder.rb b/lib/rubygems/ext/builder.rb
index be1ba3031c..350daf1e16 100644
--- a/lib/rubygems/ext/builder.rb
+++ b/lib/rubygems/ext/builder.rb
@@ -7,11 +7,13 @@
#++
require_relative "../user_interaction"
-require_relative "../shellwords"
class Gem::Ext::Builder
include Gem::UserInteraction
+ class NoMakefileError < Gem::InstallError
+ end
+
attr_accessor :build_args # :nodoc:
def self.class_name
@@ -19,19 +21,31 @@ class Gem::Ext::Builder
$1.downcase
end
- def self.make(dest_path, results, make_dir = Dir.pwd, sitedir = nil, targets = ["clean", "", "install"])
+ def self.make(dest_path, results, make_dir = Dir.pwd, sitedir = nil, targets = ["clean", "", "install"],
+ target_rbconfig: Gem.target_rbconfig, n_jobs: nil)
unless File.exist? File.join(make_dir, "Makefile")
- raise Gem::InstallError, "Makefile not found"
+ # No makefile exists, nothing to do.
+ raise NoMakefileError, "No Makefile found in #{make_dir}"
end
# try to find make program from Ruby configure arguments first
- RbConfig::CONFIG["configure_args"] =~ /with-make-prog\=(\w+)/
+ target_rbconfig["configure_args"] =~ /with-make-prog\=(\w+)/
make_program_name = ENV["MAKE"] || ENV["make"] || $1
make_program_name ||= RUBY_PLATFORM.include?("mswin") ? "nmake" : "make"
- make_program = Shellwords.split(make_program_name)
+ make_program = shellsplit(make_program_name)
+ is_nmake = /\bnmake/i.match?(make_program_name)
# 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"] != "" ? format("DESTDIR=%s", ENV["DESTDIR"]) : ""
+ destdir = !is_nmake || ENV["DESTDIR"] && ENV["DESTDIR"] != "" ? format("DESTDIR=%s", ENV["DESTDIR"]) : ""
+
+ # nmake doesn't support parallel build
+ unless is_nmake
+ have_make_arguments = make_program.size > 1
+
+ if !have_make_arguments && !ENV["MAKEFLAGS"] && n_jobs
+ make_program << "-j#{n_jobs}"
+ end
+ end
env = [destdir]
@@ -57,7 +71,7 @@ class Gem::Ext::Builder
def self.ruby
# Gem.ruby is quoted if it contains whitespace
- cmd = Shellwords.split(Gem.ruby)
+ cmd = shellsplit(Gem.ruby)
# This load_path is only needed when running rubygems test without a proper installation.
# Prepending it in a normal installation will cause problem with order of $LOAD_PATH.
@@ -82,7 +96,7 @@ class Gem::Ext::Builder
p(command)
end
results << "current directory: #{dir}"
- results << Shellwords.join(command)
+ results << shelljoin(command)
require "open3"
# Set $SOURCE_DATE_EPOCH for the subprocess.
@@ -126,15 +140,29 @@ class Gem::Ext::Builder
end
end
+ def self.shellsplit(command)
+ require "shellwords"
+
+ Shellwords.split(command)
+ end
+
+ def self.shelljoin(command)
+ require "shellwords"
+
+ Shellwords.join(command)
+ end
+
##
# Creates a new extension builder for +spec+. If the +spec+ does not yet
# have build arguments, saved, set +build_args+ which is an ARGV-style
# array.
- def initialize(spec, build_args = spec.build_args)
+ def initialize(spec, build_args = spec.build_args, target_rbconfig = Gem.target_rbconfig, build_jobs = nil)
@spec = spec
@build_args = build_args
@gem_dir = spec.full_gem_path
+ @target_rbconfig = target_rbconfig
+ @build_jobs = build_jobs
@ran_rake = false
end
@@ -152,7 +180,7 @@ class Gem::Ext::Builder
@ran_rake = true
Gem::Ext::RakeBuilder
when /CMakeLists.txt/ then
- Gem::Ext::CmakeBuilder
+ Gem::Ext::CmakeBuilder.new
when /Cargo.toml/ then
Gem::Ext::CargoBuilder.new
else
@@ -191,7 +219,7 @@ EOF
FileUtils.mkdir_p dest_path
results = builder.build(extension, dest_path,
- results, @build_args, lib_dir, extension_dir)
+ results, @build_args, lib_dir, extension_dir, @target_rbconfig, n_jobs: @build_jobs)
verbose { results.join("\n") }
diff --git a/lib/rubygems/ext/cargo_builder.rb b/lib/rubygems/ext/cargo_builder.rb
index 09ad1407c2..42dca3b102 100644
--- a/lib/rubygems/ext/cargo_builder.rb
+++ b/lib/rubygems/ext/cargo_builder.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-require_relative "../shellwords"
-
# This class is used by rubygems to build Rust extensions. It is a thin-wrapper
# over the `cargo rustc` command which takes care of building Rust code in a way
# that Ruby can use.
@@ -16,10 +14,15 @@ class Gem::Ext::CargoBuilder < Gem::Ext::Builder
@profile = :release
end
- def build(extension, dest_path, results, args = [], lib_dir = nil, cargo_dir = Dir.pwd)
+ def build(extension, dest_path, results, args = [], lib_dir = nil, cargo_dir = Dir.pwd,
+ target_rbconfig = Gem.target_rbconfig, n_jobs: nil)
require "tempfile"
require "fileutils"
+ if target_rbconfig.path
+ warn "--target-rbconfig is not yet supported for Rust extensions. Ignoring"
+ end
+
# Where's the Cargo.toml of the crate we're building
cargo_toml = File.join(cargo_dir, "Cargo.toml")
# What's the crate's name
@@ -154,7 +157,11 @@ class Gem::Ext::CargoBuilder < Gem::Ext::Builder
# We want to use the same linker that Ruby uses, so that the linker flags from
# mkmf work properly.
def linker_args
- cc_flag = Shellwords.split(makefile_config("CC"))
+ cc_flag = self.class.shellsplit(makefile_config("CC"))
+ # Avoid to ccache like tool from Rust build
+ # see https://github.com/ruby/rubygems/pull/8521#issuecomment-2689854359
+ # ex. CC="ccache gcc" or CC="sccache clang --any --args"
+ cc_flag.shift if cc_flag.size >= 2 && !cc_flag[1].start_with?("-")
linker = cc_flag.shift
link_args = cc_flag.flat_map {|a| ["-C", "link-arg=#{a}"] }
@@ -173,7 +180,7 @@ class Gem::Ext::CargoBuilder < Gem::Ext::Builder
def libruby_args(dest_dir)
libs = makefile_config(ruby_static? ? "LIBRUBYARG_STATIC" : "LIBRUBYARG_SHARED")
- raw_libs = Shellwords.split(libs)
+ raw_libs = self.class.shellsplit(libs)
raw_libs.flat_map {|l| ldflag_to_link_modifier(l) }
end
@@ -247,8 +254,7 @@ EOF
def rustc_dynamic_linker_flags(dest_dir, crate_name)
split_flags("DLDFLAGS").
- map {|arg| maybe_resolve_ldflag_variable(arg, dest_dir, crate_name) }.
- compact.
+ filter_map {|arg| maybe_resolve_ldflag_variable(arg, dest_dir, crate_name) }.
flat_map {|arg| ldflag_to_link_modifier(arg) }
end
@@ -257,7 +263,7 @@ EOF
end
def split_flags(var)
- Shellwords.split(RbConfig::CONFIG.fetch(var, ""))
+ self.class.shellsplit(RbConfig::CONFIG.fetch(var, ""))
end
def ldflag_to_link_modifier(arg)
diff --git a/lib/rubygems/ext/cmake_builder.rb b/lib/rubygems/ext/cmake_builder.rb
index b162664784..e660ed558b 100644
--- a/lib/rubygems/ext/cmake_builder.rb
+++ b/lib/rubygems/ext/cmake_builder.rb
@@ -1,16 +1,110 @@
# frozen_string_literal: true
+# This builder creates extensions defined using CMake. Its is invoked if a Gem's spec file
+# sets the `extension` property to a string that contains `CMakeLists.txt`.
+#
+# In general, CMake projects are built in two steps:
+#
+# * configure
+# * build
+#
+# The builder follow this convention. First it runs a configuration step and then it runs a build step.
+#
+# CMake projects can be quite configurable - it is likely you will want to specify options when
+# installing a gem. To pass options to CMake specify them after `--` in the gem install command. For example:
+#
+# gem install <gem_name> -- --preset <preset_name>
+#
+# Note that options are ONLY sent to the configure step - it is not currently possible to specify
+# options for the build step. If this becomes and issue then the CMake builder can be updated to
+# support build options.
+#
+# Useful options to know are:
+#
+# -G to specify a generator (-G Ninja is recommended)
+# -D<CMAKE_VARIABLE> to set a CMake variable (for example -DCMAKE_BUILD_TYPE=Release)
+# --preset <preset_name> to use a preset
+#
+# If the Gem author provides presets, via CMakePresets.json file, you will likely want to use one of them.
+# If not, you may wish to specify a generator. Ninja is recommended because it can build projects in parallel
+# and thus much faster than building them serially like Make does.
+
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]
+ attr_accessor :runner, :profile
+ def initialize
+ @runner = self.class.method(:run)
+ @profile = :release
+ end
- run cmd, results, class_name, cmake_dir
+ def build(extension, dest_path, results, args = [], lib_dir = nil, cmake_dir = Dir.pwd,
+ target_rbconfig = Gem.target_rbconfig, n_jobs: nil)
+ if target_rbconfig.path
+ warn "--target-rbconfig is not yet supported for CMake extensions. Ignoring"
end
- make dest_path, results, cmake_dir
+ # Figure the build dir
+ build_dir = File.join(cmake_dir, "build")
+
+ # Check if the gem defined presets
+ check_presets(cmake_dir, args, results)
+
+ # Configure
+ configure(cmake_dir, build_dir, dest_path, args, results)
+
+ # Compile
+ compile(cmake_dir, build_dir, args, results)
results
end
+
+ def configure(cmake_dir, build_dir, install_dir, args, results)
+ cmd = ["cmake",
+ cmake_dir,
+ "-B",
+ build_dir,
+ "-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=#{install_dir}", # Windows
+ "-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=#{install_dir}", # Not Windows
+ *Gem::Command.build_args,
+ *args]
+
+ runner.call(cmd, results, "cmake_configure", cmake_dir)
+ end
+
+ def compile(cmake_dir, build_dir, args, results)
+ cmd = ["cmake",
+ "--build",
+ build_dir.to_s,
+ "--config",
+ @profile.to_s]
+
+ runner.call(cmd, results, "cmake_compile", cmake_dir)
+ end
+
+ private
+
+ def check_presets(cmake_dir, args, results)
+ # Return if the user specified a preset
+ return unless args.grep(/--preset/i).empty?
+
+ cmd = ["cmake",
+ "--list-presets"]
+
+ presets = Array.new
+ begin
+ runner.call(cmd, presets, "cmake_presets", cmake_dir)
+
+ # Remove the first two lines of the array which is the current_directory and the command
+ # that was run
+ presets = presets[2..].join
+ results << <<~EOS
+ The gem author provided a list of presets that can be used to build the gem. To use a preset specify it on the command line:
+
+ gem install <gem_name> -- --preset <preset_name>
+
+ #{presets}
+ EOS
+ rescue Gem::InstallError
+ # Do nothing, CMakePresets.json was not included in the Gem
+ end
+ end
end
diff --git a/lib/rubygems/ext/configure_builder.rb b/lib/rubygems/ext/configure_builder.rb
index 6b8590ba2e..230b214b3c 100644
--- a/lib/rubygems/ext/configure_builder.rb
+++ b/lib/rubygems/ext/configure_builder.rb
@@ -7,14 +7,19 @@
#++
class Gem::Ext::ConfigureBuilder < Gem::Ext::Builder
- def self.build(extension, dest_path, results, args=[], lib_dir=nil, configure_dir=Dir.pwd)
+ def self.build(extension, dest_path, results, args = [], lib_dir = nil, configure_dir = Dir.pwd,
+ target_rbconfig = Gem.target_rbconfig, n_jobs: nil)
+ if target_rbconfig.path
+ warn "--target-rbconfig is not yet supported for configure-based extensions. Ignoring"
+ end
+
unless File.exist?(File.join(configure_dir, "Makefile"))
cmd = ["sh", "./configure", "--prefix=#{dest_path}", *args]
run cmd, results, class_name, configure_dir
end
- make dest_path, results, configure_dir
+ make dest_path, results, configure_dir, target_rbconfig: target_rbconfig, n_jobs: n_jobs
results
end
diff --git a/lib/rubygems/ext/ext_conf_builder.rb b/lib/rubygems/ext/ext_conf_builder.rb
index fb68a7a8cc..822454355d 100644
--- a/lib/rubygems/ext/ext_conf_builder.rb
+++ b/lib/rubygems/ext/ext_conf_builder.rb
@@ -7,7 +7,8 @@
#++
class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder
- def self.build(extension, dest_path, results, args=[], lib_dir=nil, extension_dir=Dir.pwd)
+ def self.build(extension, dest_path, results, args = [], lib_dir = nil, extension_dir = Dir.pwd,
+ target_rbconfig = Gem.target_rbconfig, n_jobs: nil)
require "fileutils"
require "tempfile"
@@ -23,6 +24,7 @@ class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder
begin
cmd = ruby << File.basename(extension)
+ cmd << "--target-rbconfig=#{target_rbconfig.path}" if target_rbconfig.path
cmd.push(*args)
run(cmd, results, class_name, extension_dir) do |s, r|
@@ -39,11 +41,14 @@ class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder
ENV["DESTDIR"] = nil
- make dest_path, results, extension_dir, tmp_dest_relative
+ make dest_path, results, extension_dir, tmp_dest_relative, target_rbconfig: target_rbconfig, n_jobs: n_jobs
full_tmp_dest = File.join(extension_dir, tmp_dest_relative)
- if Gem.install_extension_in_lib && lib_dir
+ is_cross_compiling = target_rbconfig["platform"] != RbConfig::CONFIG["platform"]
+ # Do not copy extension libraries by default when cross-compiling
+ # not to conflict with the one already built for the host platform.
+ if Gem.install_extension_in_lib && lib_dir && !is_cross_compiling
FileUtils.mkdir_p lib_dir
entries = Dir.entries(full_tmp_dest) - %w[. ..]
entries = entries.map {|entry| File.join full_tmp_dest, entry }
@@ -55,12 +60,16 @@ class Gem::Ext::ExtConfBuilder < Gem::Ext::Builder
destent.exist? || FileUtils.mv(ent.path, destent.path)
end
- make dest_path, results, extension_dir, tmp_dest_relative, ["clean"]
+ make dest_path, results, extension_dir, tmp_dest_relative, ["clean"], target_rbconfig: target_rbconfig
ensure
ENV["DESTDIR"] = destdir
end
results
+ rescue Gem::Ext::Builder::NoMakefileError => error
+ results << error.message
+ results << "Skipping make for #{extension} as no Makefile was found."
+ # We are good, do not re-raise the error.
ensure
FileUtils.rm_rf tmp_dest if tmp_dest
end
diff --git a/lib/rubygems/ext/rake_builder.rb b/lib/rubygems/ext/rake_builder.rb
index 0171807b39..d702d7f339 100644
--- a/lib/rubygems/ext/rake_builder.rb
+++ b/lib/rubygems/ext/rake_builder.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-require_relative "../shellwords"
-
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
@@ -9,7 +7,12 @@ require_relative "../shellwords"
#++
class Gem::Ext::RakeBuilder < Gem::Ext::Builder
- def self.build(extension, dest_path, results, args=[], lib_dir=nil, extension_dir=Dir.pwd)
+ def self.build(extension, dest_path, results, args = [], lib_dir = nil, extension_dir = Dir.pwd,
+ target_rbconfig = Gem.target_rbconfig, n_jobs: nil)
+ if target_rbconfig.path
+ warn "--target-rbconfig is not yet supported for Rake extensions. Ignoring"
+ end
+
if /mkrf_conf/i.match?(File.basename(extension))
run([Gem.ruby, File.basename(extension), *args], results, class_name, extension_dir)
end
@@ -17,7 +20,7 @@ class Gem::Ext::RakeBuilder < Gem::Ext::Builder
rake = ENV["rake"]
if rake
- rake = Shellwords.split(rake)
+ rake = shellsplit(rake)
else
begin
rake = ruby << "-rrubygems" << Gem.bin_path("rake", "rake")
diff --git a/lib/rubygems/gem_runner.rb b/lib/rubygems/gem_runner.rb
index 8335a0ad03..e60cebd0cb 100644
--- a/lib/rubygems/gem_runner.rb
+++ b/lib/rubygems/gem_runner.rb
@@ -8,7 +8,6 @@
require_relative "../rubygems"
require_relative "command_manager"
-require_relative "deprecate"
##
# Run an instance of the gem program.
@@ -29,6 +28,7 @@ class Gem::GemRunner
# Run the gem command with the following arguments.
def run(args)
+ validate_encoding args
build_args = extract_build_args args
do_configuration args
@@ -72,6 +72,14 @@ class Gem::GemRunner
private
+ def validate_encoding(args)
+ invalid_arg = args.find {|arg| !arg.valid_encoding? }
+
+ if invalid_arg
+ raise Gem::OptionParser::InvalidArgument.new("'#{invalid_arg.scrub}' has invalid encoding")
+ end
+ end
+
def do_configuration(args)
Gem.configuration = @config_file_class.new(args)
Gem.use_paths Gem.configuration[:gemhome], Gem.configuration[:gempath]
diff --git a/lib/rubygems/gemcutter_utilities.rb b/lib/rubygems/gemcutter_utilities.rb
index a8361b7ff1..afe7957f43 100644
--- a/lib/rubygems/gemcutter_utilities.rb
+++ b/lib/rubygems/gemcutter_utilities.rb
@@ -62,6 +62,10 @@ module Gem::GemcutterUtilities
options[:otp] || ENV["GEM_HOST_OTP_CODE"]
end
+ def webauthn_enabled?
+ options[:webauthn]
+ end
+
##
# The host to connect to either from the RUBYGEMS_HOST environment variable
# or from the user's configuration
@@ -136,7 +140,6 @@ module Gem::GemcutterUtilities
response = rubygems_api_request(:put, "api/v1/api_key",
sign_in_host, scope: scope) do |request|
request.basic_auth identifier, password
- request["OTP"] = otp if otp
request.body = Gem::URI.encode_www_form({ api_key: api_key }.merge(update_scope_params))
end
@@ -176,7 +179,6 @@ module Gem::GemcutterUtilities
response = rubygems_api_request(:post, "api/v1/api_key",
sign_in_host, credentials: credentials, scope: scope) do |request|
request.basic_auth identifier, password
- request["OTP"] = otp if otp
request.body = Gem::URI.encode_www_form({ name: key_name }.merge(all_params))
end
@@ -251,6 +253,8 @@ module Gem::GemcutterUtilities
req["OTP"] = otp if otp
block.call(req)
end
+ ensure
+ options[:otp] = nil if webauthn_enabled?
end
def fetch_otp(credentials)
@@ -259,7 +263,10 @@ module Gem::GemcutterUtilities
port = server.addr[1].to_s
url_with_port = "#{webauthn_url}?port=#{port}"
- say "You have enabled multi-factor authentication. Please visit #{url_with_port} to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, you can re-run the gem signin command with the `--otp [your_code]` option."
+ say "You have enabled multi-factor authentication. Please visit the following URL to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, you can re-run the gem signin command with the `--otp [your_code]` option."
+ say ""
+ say url_with_port
+ say ""
threads = [WebauthnListener.listener_thread(host, server), WebauthnPoller.poll_thread(options, host, webauthn_url, credentials)]
otp_thread = wait_for_otp_thread(*threads)
@@ -271,6 +278,8 @@ module Gem::GemcutterUtilities
terminate_interaction(1)
end
+ options[:webauthn] = true
+
say "You are verified with a security device. You may close the browser window."
otp_thread[:otp]
else
@@ -310,7 +319,7 @@ module Gem::GemcutterUtilities
end
def get_scope_params(scope)
- scope_params = { index_rubygems: true }
+ scope_params = { index_rubygems: true, push_rubygem: true }
if scope
scope_params = { scope => true }
diff --git a/lib/rubygems/gemcutter_utilities/webauthn_listener.rb b/lib/rubygems/gemcutter_utilities/webauthn_listener.rb
index abf65efe37..3f56a077c9 100644
--- a/lib/rubygems/gemcutter_utilities/webauthn_listener.rb
+++ b/lib/rubygems/gemcutter_utilities/webauthn_listener.rb
@@ -85,10 +85,17 @@ module Gem::GemcutterUtilities
end
def parse_otp_from_uri(uri)
- require "cgi"
+ query = uri.query
+ return unless query && !query.empty?
- return if uri.query.nil?
- CGI.parse(uri.query).dig("code", 0)
+ query.split("&") do |param|
+ key, value = param.split("=", 2)
+ if value && Gem::URI.decode_www_form_component(key) == "code"
+ return Gem::URI.decode_www_form_component(value)
+ end
+ end
+
+ nil
end
class SocketResponder
diff --git a/lib/rubygems/install_default_message.rb b/lib/rubygems/install_default_message.rb
deleted file mode 100644
index 0640eaaf08..0000000000
--- a/lib/rubygems/install_default_message.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "../rubygems"
-require_relative "user_interaction"
-
-##
-# A post-install hook that displays "Successfully installed
-# some_gem-1.0 as a default gem"
-
-Gem.post_install do |installer|
- ui = Gem::DefaultUserInteraction.ui
- ui.say "Successfully installed #{installer.spec.full_name} as a default gem"
-end
diff --git a/lib/rubygems/install_update_options.rb b/lib/rubygems/install_update_options.rb
index aad207a718..66cb5c049b 100644
--- a/lib/rubygems/install_update_options.rb
+++ b/lib/rubygems/install_update_options.rb
@@ -31,6 +31,15 @@ module Gem::InstallUpdateOptions
options[:bin_dir] = File.expand_path(value)
end
+ add_option(:"Install/Update", "-j", "--build-jobs VALUE", Integer,
+ "Specify the number of jobs to pass to `make` when installing",
+ "gems with native extensions.",
+ "Defaults to the number of processors.",
+ "This option is ignored on the mswin platform or",
+ "if the MAKEFLAGS environment variable is set.") do |value, options|
+ options[:build_jobs] = value
+ end
+
add_option(:"Install/Update", "--document [TYPES]", Array,
"Generate documentation for installed gems",
"List the documentation types you wish to",
@@ -158,10 +167,9 @@ module Gem::InstallUpdateOptions
options[:without_groups].concat v.map(&:intern)
end
- add_option(:"Install/Update", "--default",
+ add_option(:Deprecated, "--default",
"Add the gem's full specification to",
"specifications/default and extract only its bin") do |v,_o|
- options[:install_as_default] = v
end
add_option(:"Install/Update", "--explain",
@@ -179,6 +187,11 @@ module Gem::InstallUpdateOptions
"Suggest alternates when gems are not found") do |v,_o|
options[:suggest_alternate] = v
end
+
+ add_option(:"Install/Update", "--target-rbconfig [FILE]",
+ "rbconfig.rb for the deployment target platform") do |v, _o|
+ Gem.set_target_rbconfig(v)
+ end
end
##
diff --git a/lib/rubygems/installer.rb b/lib/rubygems/installer.rb
index 844f292ba2..914e413677 100644
--- a/lib/rubygems/installer.rb
+++ b/lib/rubygems/installer.rb
@@ -8,7 +8,6 @@
require_relative "installer_uninstaller_utils"
require_relative "exceptions"
-require_relative "deprecate"
require_relative "package"
require_relative "ext"
require_relative "user_interaction"
@@ -27,8 +26,6 @@ require_relative "user_interaction"
# file. See Gem.pre_install and Gem.post_install for details.
class Gem::Installer
- extend Gem::Deprecate
-
##
# Paths where env(1) might live. Some systems are broken and have it in
# /bin
@@ -66,31 +63,7 @@ class Gem::Installer
attr_reader :package
- @path_warning = false
-
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.
-
- def inherited(klass)
- if klass.name == "Bundler::RubyGemsGemInstaller"
- require "rubygems/command"
- end
-
- super(klass)
- end
-
- ##
- # True if we've warned about PATH not including Gem.bindir
-
- attr_accessor :path_warning
-
##
# Overrides the executable format.
#
@@ -177,7 +150,7 @@ class Gem::Installer
# process. If not set, then Gem::Command.build_args is used
# :post_install_message:: Print gem post install message if true
- def initialize(package, options={})
+ def initialize(package, options = {})
require "fileutils"
@options = options
@@ -188,15 +161,6 @@ class Gem::Installer
@package.dir_mode = options[:dir_mode]
@package.prog_mode = options[:prog_mode]
@package.data_mode = options[:data_mode]
-
- if @gem_home == Gem.user_dir
- # If we get here, then one of the following likely happened:
- # - `--user-install` was specified
- # - `Gem::PathSupport#home` fell back to `Gem.user_dir`
- # - GEM_HOME was manually set to `Gem.user_dir`
-
- check_that_user_bin_dir_is_in_path
- end
end
##
@@ -244,8 +208,7 @@ class Gem::Installer
ruby_executable = true
existing = io.read.slice(/
^\s*(
- gem \s |
- load \s Gem\.bin_path\( |
+ Gem\.activate_and_load_bin_path\( |
load \s Gem\.activate_bin_path\(
)
(['"])(.*?)(\2),
@@ -308,11 +271,7 @@ class Gem::Installer
run_pre_install_hooks
# Set loaded_from to ensure extension_dir is correct
- if @options[:install_as_default]
- spec.loaded_from = default_spec_file
- else
- spec.loaded_from = spec_file
- end
+ spec.loaded_from = spec_file
# Completely remove any previous gem files
FileUtils.rm_rf gem_dir
@@ -321,24 +280,17 @@ class Gem::Installer
dir_mode = options[:dir_mode]
FileUtils.mkdir_p gem_dir, mode: dir_mode && 0o755
- if @options[:install_as_default]
- extract_bin
- write_default_spec
- else
- extract_files
+ extract_files
- build_extensions
- write_build_info_file
- run_post_build_hooks
- end
+ build_extensions
+ write_build_info_file
+ run_post_build_hooks
generate_bin
generate_plugins
- unless @options[:install_as_default]
- write_spec
- write_cache_file
- end
+ write_spec
+ write_cache_file
File.chmod(dir_mode, gem_dir) if dir_mode
@@ -427,15 +379,6 @@ class Gem::Installer
end
##
- # Unpacks the gem into the given directory.
-
- def unpack(directory)
- @gem_dir = directory
- extract_files
- end
- rubygems_deprecate :unpack
-
- ##
# The location of the spec file that is installed.
#
@@ -443,12 +386,18 @@ class Gem::Installer
File.join gem_home, "specifications", "#{spec.full_name}.gemspec"
end
+ def default_spec_dir
+ dir = File.join(gem_home, "specifications", "default")
+ FileUtils.mkdir_p dir
+ dir
+ end
+
##
# The location of the default spec file for default gems.
#
def default_spec_file
- File.join gem_home, "specifications", "default", "#{spec.full_name}.gemspec"
+ File.join default_spec_dir, "#{spec.full_name}.gemspec"
end
##
@@ -488,11 +437,21 @@ class Gem::Installer
end
def generate_bin # :nodoc:
- return if spec.executables.nil? || spec.executables.empty?
+ executables = spec.executables
+ return if executables.nil? || executables.empty?
+
+ if @gem_home == Gem.user_dir
+ # If we get here, then one of the following likely happened:
+ # - `--user-install` was specified
+ # - `Gem::PathSupport#home` fell back to `Gem.user_dir`
+ # - GEM_HOME was manually set to `Gem.user_dir`
+
+ check_that_user_bin_dir_is_in_path(executables)
+ end
ensure_writable_dir @bin_dir
- spec.executables.each do |filename|
+ executables.each do |filename|
bin_path = File.join gem_dir, spec.bindir, filename
next unless File.exist? bin_path
@@ -500,8 +459,7 @@ class Gem::Installer
dir_mode = options[:prog_mode] || (mode | 0o111)
unless dir_mode == mode
- require "fileutils"
- FileUtils.chmod dir_mode, bin_path
+ File.chmod dir_mode, bin_path
end
check_executable_overwrite filename
@@ -539,12 +497,14 @@ class Gem::Installer
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
+ Gem.open_file_with_lock(bin_script_path) do
+ require "fileutils"
+ FileUtils.rm_f bin_script_path # prior install may have been --no-wrappers
- File.open bin_script_path, "wb", 0o755 do |file|
- file.print app_script_text(filename)
- file.chmod(options[:prog_mode] || 0o755)
+ File.open(bin_script_path, "wb", 0o755) do |file|
+ file.write app_script_text(filename)
+ file.chmod(options[:prog_mode] || 0o755)
+ end
end
verbose bin_script_path
@@ -675,6 +635,7 @@ class Gem::Installer
@build_root = options[:build_root]
@build_args = options[:build_args]
+ @build_jobs = options[:build_jobs]
@gem_home = @install_dir || user_install_dir || Gem.dir
@@ -693,9 +654,7 @@ class Gem::Installer
end
end
- def check_that_user_bin_dir_is_in_path # :nodoc:
- return if self.class.path_warning
-
+ def check_that_user_bin_dir_is_in_path(executables) # :nodoc:
user_bin_dir = @bin_dir || Gem.bindir(gem_home)
user_bin_dir = user_bin_dir.tr(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
@@ -711,8 +670,7 @@ class Gem::Installer
unless path.include? user_bin_dir
unless !Gem.win_platform? && (path.include? user_bin_dir.sub(ENV["HOME"], "~"))
- alert_warning "You don't have #{user_bin_dir} in your PATH,\n\t gem executables will not run."
- self.class.path_warning = true
+ alert_warning "You don't have #{user_bin_dir} in your PATH,\n\t gem executables (#{executables.join(", ")}) will not run."
end
end
end
@@ -757,54 +715,53 @@ class Gem::Installer
def app_script_text(bin_file_name)
# NOTE: that the `load` lines cannot be indented, as old RG versions match
# against the beginning of the line
- <<-TEXT
-#{shebang bin_file_name}
-#
-# This file was generated by RubyGems.
-#
-# The application '#{spec.name}' is installed as part of a gem, and
-# this file is here to facilitate running it.
-#
-
-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)
- #{explicit_version_requirement(spec.name)}
- ARGV.shift
- end
-end
+ <<~TEXT
+ #{shebang bin_file_name}
+ #
+ # This file was generated by RubyGems.
+ #
+ # The application '#{spec.name}' is installed as part of a gem, and
+ # this file is here to facilitate running it.
+ #
+
+ 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)
+ #{explicit_version_requirement(spec.name)}
+ ARGV.shift
+ end
+ end
-if Gem.respond_to?(:activate_bin_path)
-load Gem.activate_bin_path('#{spec.name}', '#{bin_file_name}', version)
-else
-gem #{spec.name.dump}, version
-load Gem.bin_path(#{spec.name.dump}, #{bin_file_name.dump}, version)
-end
-TEXT
+ if Gem.respond_to?(:activate_and_load_bin_path)
+ Gem.activate_and_load_bin_path('#{spec.name}', '#{bin_file_name}', version)
+ else
+ load Gem.activate_bin_path('#{spec.name}', '#{bin_file_name}', version)
+ end
+ TEXT
end
def gemdeps_load(name)
return "" if name == "bundler"
- <<-TEXT
+ <<~TEXT
-Gem.use_gemdeps
-TEXT
+ Gem.use_gemdeps
+ TEXT
end
def explicit_version_requirement(name)
code = "version = str"
return code unless name == "bundler"
- code += <<-TEXT
+ code += <<~TEXT
- ENV['BUNDLER_VERSION'] = str
-TEXT
+ ENV['BUNDLER_VERSION'] = str
+ TEXT
end
##
@@ -819,9 +776,9 @@ TEXT
if File.exist?(File.join(bindir, ruby_exe))
# stub & ruby.exe within same folder. Portable
- <<-TEXT
-@ECHO OFF
-@"%~dp0#{ruby_exe}" "%~dpn0" %*
+ <<~TEXT
+ @ECHO OFF
+ @"%~dp0#{ruby_exe}" "%~dpn0" %*
TEXT
elsif bindir.downcase.start_with? rb_topdir.downcase
# stub within ruby folder, but not standard bin. Portable
@@ -829,16 +786,16 @@ TEXT
from = Pathname.new bindir
to = Pathname.new "#{rb_topdir}/bin"
rel = to.relative_path_from from
- <<-TEXT
-@ECHO OFF
-@"%~dp0#{rel}/#{ruby_exe}" "%~dpn0" %*
+ <<~TEXT
+ @ECHO OFF
+ @"%~dp0#{rel}/#{ruby_exe}" "%~dpn0" %*
TEXT
else
# outside ruby folder, maybe -user-install or bundler. Portable, but ruby
# is dependent on PATH
- <<-TEXT
-@ECHO OFF
-@#{ruby_exe} "%~dpn0" %*
+ <<~TEXT
+ @ECHO OFF
+ @#{ruby_exe} "%~dpn0" %*
TEXT
end
end
@@ -847,7 +804,7 @@ TEXT
# 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, Gem.target_rbconfig, build_jobs
builder.build_extensions
end
@@ -916,11 +873,7 @@ TEXT
ensure_loadable_spec
- if options[:install_as_default]
- Gem.ensure_default_gem_subdirectories gem_home
- else
- Gem.ensure_gem_subdirectories gem_home
- end
+ Gem.ensure_gem_subdirectories gem_home
return true if @force
@@ -961,11 +914,8 @@ TEXT
end
def ensure_writable_dir(dir) # :nodoc:
- begin
- Dir.mkdir dir, *[options[:dir_mode] && 0o755].compact
- rescue SystemCallError
- raise unless File.directory? dir
- end
+ require "fileutils"
+ FileUtils.mkdir_p dir, mode: options[:dir_mode] && 0o755
raise Gem::FilePermissionError.new(dir) unless File.writable? dir
end
@@ -992,8 +942,17 @@ TEXT
end
end
+ def build_jobs
+ @build_jobs ||= begin
+ require "etc"
+ Etc.nprocessors + 1
+ rescue LoadError
+ 1
+ end
+ end
+
def rb_config
- RbConfig::CONFIG
+ Gem.target_rbconfig
end
def ruby_install_name
@@ -1006,18 +965,17 @@ TEXT
def bash_prolog_script
if load_relative_enabled?
- script = +<<~EOS
- bindir="${0%/*}"
- EOS
-
- script << %(exec "$bindir/#{ruby_install_name}" "-x" "$0" "$@"\n)
-
<<~EOS
#!/bin/sh
# -*- ruby -*-
_=_\\
=begin
- #{script.chomp}
+ bindir="${0%/*}"
+ ruby="$bindir/#{ruby_install_name}"
+ if [ ! -f "$ruby" ]; then
+ ruby="#{ruby_install_name}"
+ fi
+ exec "$ruby" "-x" "$0" "$@"
=end
EOS
else
diff --git a/lib/rubygems/local_remote_options.rb b/lib/rubygems/local_remote_options.rb
index 51a61213a5..3b88c43149 100644
--- a/lib/rubygems/local_remote_options.rb
+++ b/lib/rubygems/local_remote_options.rb
@@ -134,13 +134,13 @@ module Gem::LocalRemoteOptions
# Is local fetching enabled?
def local?
- options[:domain] == :local || options[:domain] == :both
+ [:local, :both].include?(options[:domain])
end
##
# Is remote fetching enabled?
def remote?
- options[:domain] == :remote || options[:domain] == :both
+ [:remote, :both].include?(options[:domain])
end
end
diff --git a/lib/rubygems/name_tuple.rb b/lib/rubygems/name_tuple.rb
index 3f4a6fcf3d..cbdf4d7ac5 100644
--- a/lib/rubygems/name_tuple.rb
+++ b/lib/rubygems/name_tuple.rb
@@ -6,7 +6,7 @@
# wrap the data returned from the indexes.
class Gem::NameTuple
- def initialize(name, version, platform=Gem::Platform::RUBY)
+ def initialize(name, version, platform = Gem::Platform::RUBY)
@name = name
@version = version
@@ -81,6 +81,12 @@ class Gem::NameTuple
[@name, @version, @platform]
end
+ alias_method :deconstruct, :to_a
+
+ def deconstruct_keys(keys)
+ { name: @name, version: @version, platform: @platform }
+ end
+
def inspect # :nodoc:
"#<Gem::NameTuple #{@name}, #{@version}, #{@platform}>"
end
diff --git a/lib/rubygems/package.rb b/lib/rubygems/package.rb
index c855423ed7..6b21ff1b95 100644
--- a/lib/rubygems/package.rb
+++ b/lib/rubygems/package.rb
@@ -7,6 +7,7 @@
# rubocop:enable Style/AsciiComments
+require_relative "win_platform"
require_relative "security"
require_relative "user_interaction"
@@ -267,7 +268,7 @@ class Gem::Package
tar.add_file_simple file, stat.mode, stat.size do |dst_io|
File.open file, "rb" do |src_io|
- copy_stream(src_io, dst_io)
+ copy_stream(src_io, dst_io, stat.size)
end
end
end
@@ -436,8 +437,6 @@ EOM
symlinks << [full_name, link_target, destination, real_destination]
end
- FileUtils.rm_rf destination
-
mkdir =
if entry.directory?
destination
@@ -451,8 +450,14 @@ EOM
end
if entry.file?
- File.open(destination, "wb") {|out| copy_stream(entry, out) }
- FileUtils.chmod file_mode(entry.header.mode) & ~File.umask, destination
+ File.open(destination, "wb") do |out|
+ copy_stream(tar.io, out, entry.size)
+ # Flush needs to happen before chmod because there could be data
+ # in the IO buffer that needs to be written, and that could be
+ # written after the chmod (on close) which would mess up the perms
+ out.flush
+ out.chmod file_mode(entry.header.mode) & ~File.umask
+ end
end
verbose destination
@@ -514,10 +519,12 @@ EOM
destination
end
- def normalize_path(pathname)
- if Gem.win_platform?
+ if Gem.win_platform?
+ def normalize_path(pathname) # :nodoc:
pathname.downcase
- else
+ end
+ else
+ def normalize_path(pathname) # :nodoc:
pathname
end
end
@@ -635,6 +642,8 @@ EOM
raise Gem::Package::FormatError.new e.message, @gem
end
+ private
+
##
# Verifies the +checksums+ against the +digests+. This check is not
# cryptographically secure. Missing checksums are ignored.
@@ -715,12 +724,12 @@ EOM
end
if RUBY_ENGINE == "truffleruby"
- def copy_stream(src, dst) # :nodoc:
- dst.write src.read
+ def copy_stream(src, dst, size) # :nodoc:
+ dst.write src.read(size)
end
else
- def copy_stream(src, dst) # :nodoc:
- IO.copy_stream(src, dst)
+ def copy_stream(src, dst, size) # :nodoc:
+ IO.copy_stream(src, dst, size)
end
end
diff --git a/lib/rubygems/package/tar_header.rb b/lib/rubygems/package/tar_header.rb
index dd5e835a1e..dd20d65080 100644
--- a/lib/rubygems/package/tar_header.rb
+++ b/lib/rubygems/package/tar_header.rb
@@ -56,7 +56,7 @@ class Gem::Package::TarHeader
##
# Pack format for a tar header
- PACK_FORMAT = "a100" + # name
+ PACK_FORMAT = ("a100" + # name
"a8" + # mode
"a8" + # uid
"a8" + # gid
@@ -71,12 +71,12 @@ class Gem::Package::TarHeader
"a32" + # gname
"a8" + # devmajor
"a8" + # devminor
- "a155" # prefix
+ "a155").freeze # prefix
##
# Unpack format for a tar header
- UNPACK_FORMAT = "A100" + # name
+ UNPACK_FORMAT = ("A100" + # name
"A8" + # mode
"A8" + # uid
"A8" + # gid
@@ -91,7 +91,7 @@ class Gem::Package::TarHeader
"A32" + # gname
"A8" + # devmajor
"A8" + # devminor
- "A155" # prefix
+ "A155").freeze # prefix
attr_reader(*FIELDS)
@@ -228,6 +228,17 @@ class Gem::Package::TarHeader
@checksum = oct calculate_checksum(header), 6
end
+ ##
+ # Header's full name, including prefix
+
+ def full_name
+ if prefix != ""
+ File.join prefix, name
+ else
+ name
+ end
+ end
+
private
def calculate_checksum(header)
diff --git a/lib/rubygems/package/tar_reader.rb b/lib/rubygems/package/tar_reader.rb
index 25f9b2f945..b66a8a62bc 100644
--- a/lib/rubygems/package/tar_reader.rb
+++ b/lib/rubygems/package/tar_reader.rb
@@ -30,6 +30,8 @@ class Gem::Package::TarReader
nil
end
+ attr_reader :io # :nodoc:
+
##
# Creates a new tar file reader on +io+ which needs to respond to #pos,
# #eof?, #read, #getc and #pos=
diff --git a/lib/rubygems/package/tar_reader/entry.rb b/lib/rubygems/package/tar_reader/entry.rb
index 5e9d9af5c6..f837e86fd6 100644
--- a/lib/rubygems/package/tar_reader/entry.rb
+++ b/lib/rubygems/package/tar_reader/entry.rb
@@ -87,11 +87,7 @@ class Gem::Package::TarReader::Entry
# Full name of the tar entry
def full_name
- if @header.prefix != ""
- File.join @header.prefix, @header.name
- else
- @header.name
- end
+ @header.full_name.force_encoding(Encoding::UTF_8)
rescue ArgumentError => e
raise unless e.message == "string contains null byte"
raise Gem::Package::TarInvalidError,
diff --git a/lib/rubygems/package/tar_writer.rb b/lib/rubygems/package/tar_writer.rb
index b24bdb63e7..39fed9e2af 100644
--- a/lib/rubygems/package/tar_writer.rb
+++ b/lib/rubygems/package/tar_writer.rb
@@ -95,10 +95,11 @@ class Gem::Package::TarWriter
end
##
- # Adds file +name+ with permissions +mode+, and yields an IO for writing the
- # file to
+ # Adds file +name+ with permissions +mode+ and mtime +mtime+ (sets
+ # Gem.source_date_epoch if not specified), and yields an IO for
+ # writing the file to
- def add_file(name, mode) # :yields: io
+ def add_file(name, mode, mtime = nil) # :yields: io
check_closed
name, prefix = split_name name
@@ -118,7 +119,7 @@ class Gem::Package::TarWriter
header = Gem::Package::TarHeader.new name: name, mode: mode,
size: size, prefix: prefix,
- mtime: Gem.source_date_epoch
+ mtime: mtime || Gem.source_date_epoch
@io.write header
@io.pos = final_pos
diff --git a/lib/rubygems/platform.rb b/lib/rubygems/platform.rb
index d54ad12880..367b00e7e1 100644
--- a/lib/rubygems/platform.rb
+++ b/lib/rubygems/platform.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-require_relative "deprecate"
-
##
# Available list of platforms for targeting Gem installations.
#
@@ -12,23 +10,15 @@ class Gem::Platform
attr_accessor :cpu, :os, :version
- def self.local
- @local ||= begin
- arch = RbConfig::CONFIG["arch"]
+ def self.local(refresh: false)
+ return @local if @local && !refresh
+ @local = begin
+ arch = Gem.target_rbconfig["arch"]
arch = "#{arch}_60" if /mswin(?:32|64)$/.match?(arch)
new(arch)
end
end
- def self.match(platform)
- match_platforms?(platform, Gem.platforms)
- end
-
- class << self
- extend Gem::Deprecate
- rubygems_deprecate :match, "Gem::Platform.match_spec? or match_gem?"
- end
-
def self.match_platforms?(platform, platforms)
platform = Gem::Platform.new(platform) unless platform.is_a?(Gem::Platform)
platforms.any? do |local_platform|
@@ -87,56 +77,45 @@ class Gem::Platform
when Array then
@cpu, @os, @version = arch
when String then
- arch = arch.split "-"
-
- if arch.length > 2 && !arch.last.match?(/\d+(\.\d+)?$/) # reassemble x86-linux-{libc}
- extra = arch.pop
- arch.last << "-#{extra}"
- end
+ cpu, os = arch.sub(/-+$/, "").split("-", 2)
- cpu = arch.shift
-
- @cpu = case cpu
- when /i\d86/ then "x86"
- else cpu
- end
-
- if arch.length == 2 && arch.last.match?(/^\d+(\.\d+)?$/) # for command-line
- @os, @version = arch
- return
+ @cpu = if cpu&.match?(/i\d86/)
+ "x86"
+ else
+ cpu
end
- os, = arch
if os.nil?
@cpu = nil
os = cpu
end # 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 /^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-?(\w+)?/ then ["linux", $1]
- when /mingw32/ then ["mingw32", nil]
- when /mingw-?(\w+)?/ then ["mingw", $1]
- when /(mswin\d+)(\_(\d+))?/ then
+ when /aix-?(\d+)?/ then ["aix", $1]
+ when /cygwin/ then ["cygwin", nil]
+ when /darwin-?(\d+)?/ then ["darwin", $1]
+ when "macruby" then ["macruby", nil]
+ when /^macruby-?(\d+(?:\.\d+)*)?/ then ["macruby", $1]
+ when /freebsd-?(\d+)?/ then ["freebsd", $1]
+ when "java", "jruby" then ["java", nil]
+ when /^java-?(\d+(?:\.\d+)*)?/ then ["java", $1]
+ when /^dalvik-?(\d+)?$/ then ["dalvik", $1]
+ when /^dotnet$/ then ["dotnet", nil]
+ when /^dotnet-?(\d+(?:\.\d+)*)?/ then ["dotnet", $1]
+ when /linux-?(\w+)?/ then ["linux", $1]
+ when /mingw32/ then ["mingw32", nil]
+ when /mingw-?(\w+)?/ then ["mingw", $1]
+ when /(mswin\d+)(?:[_-](\d+))?/ then
os = $1
- version = $3
- @cpu = "x86" if @cpu.nil? && os =~ /32$/
+ version = $2
+ @cpu = "x86" if @cpu.nil? && os.end_with?("32")
[os, version]
- when /netbsdelf/ then ["netbsdelf", nil]
- when /openbsd(\d+\.\d+)?/ then ["openbsd", $1]
- when /solaris(\d+\.\d+)?/ then ["solaris", $1]
- when /wasi/ then ["wasi", nil]
+ when /netbsdelf/ then ["netbsdelf", nil]
+ when /openbsd-?(\d+\.\d+)?/ then ["openbsd", $1]
+ when /solaris-?(\d+\.\d+)?/ then ["solaris", $1]
+ when /wasi/ then ["wasi", nil]
# test
- when /^(\w+_platform)(\d+)?/ then [$1, $2]
+ when /^(\w+_platform)-?(\d+)?/ then [$1, $2]
else ["unknown", nil]
end
when Gem::Platform then
@@ -153,7 +132,38 @@ class Gem::Platform
end
def to_s
- to_a.compact.join "-"
+ to_a.compact.join(@cpu.nil? ? "" : "-")
+ end
+
+ ##
+ # Deconstructs the platform into an array for pattern matching.
+ # Returns [cpu, os, version].
+ #
+ # Gem::Platform.new("x86_64-linux").deconstruct #=> ["x86_64", "linux", nil]
+ #
+ # This enables array pattern matching:
+ #
+ # case Gem::Platform.new("arm64-darwin-21")
+ # in ["arm64", "darwin", version]
+ # # version => "21"
+ # end
+ alias_method :deconstruct, :to_a
+
+ ##
+ # Deconstructs the platform into a hash for pattern matching.
+ # Returns a hash with keys +:cpu+, +:os+, and +:version+.
+ #
+ # Gem::Platform.new("x86_64-darwin-20").deconstruct_keys(nil)
+ # #=> { cpu: "x86_64", os: "darwin", version: "20" }
+ #
+ # This enables hash pattern matching:
+ #
+ # case Gem::Platform.new("x86_64-linux")
+ # in cpu: "x86_64", os: "linux"
+ # # Matches Linux on x86_64
+ # end
+ def deconstruct_keys(keys)
+ { cpu: @cpu, os: @os, version: @version }
end
##
@@ -176,7 +186,7 @@ class Gem::Platform
# they have the same version, or either one has no version
#
# Additionally, the platform will match if the local CPU is 'arm' and the
- # other CPU starts with "arm" (for generic ARM family support).
+ # other CPU starts with "armv" (for generic 32-bit ARM family support).
#
# Of note, this method is not commutative. Indeed the OS 'linux' has a
# special case: the version is the libc name, yet while "no version" stands
@@ -197,7 +207,7 @@ class Gem::Platform
# cpu
([nil,"universal"].include?(@cpu) || [nil, "universal"].include?(other.cpu) || @cpu == other.cpu ||
- (@cpu == "arm" && other.cpu.start_with?("arm"))) &&
+ (@cpu == "arm" && other.cpu.start_with?("armv"))) &&
# os
@os == other.os &&
@@ -265,4 +275,118 @@ class Gem::Platform
# This will be replaced with Gem::Platform::local.
CURRENT = "current"
+
+ JAVA = Gem::Platform.new("java") # :nodoc:
+ MSWIN = Gem::Platform.new("mswin32") # :nodoc:
+ MSWIN64 = Gem::Platform.new("mswin64") # :nodoc:
+ MINGW = Gem::Platform.new("x86-mingw32") # :nodoc:
+ X64_MINGW_LEGACY = Gem::Platform.new("x64-mingw32") # :nodoc:
+ X64_MINGW = Gem::Platform.new("x64-mingw-ucrt") # :nodoc:
+ UNIVERSAL_MINGW = Gem::Platform.new("universal-mingw") # :nodoc:
+ WINDOWS = [MSWIN, MSWIN64, UNIVERSAL_MINGW].freeze # :nodoc:
+ X64_LINUX = Gem::Platform.new("x86_64-linux") # :nodoc:
+ X64_LINUX_MUSL = Gem::Platform.new("x86_64-linux-musl") # :nodoc:
+
+ GENERICS = [JAVA, *WINDOWS].freeze # :nodoc:
+ private_constant :GENERICS
+
+ GENERIC_CACHE = GENERICS.each_with_object({}) {|g, h| h[g] = g } # :nodoc:
+ private_constant :GENERIC_CACHE
+
+ class << self
+ ##
+ # Returns the generic platform for the given platform.
+
+ def generic(platform)
+ return Gem::Platform::RUBY if platform.nil? || platform == Gem::Platform::RUBY
+
+ GENERIC_CACHE[platform] ||= begin
+ found = GENERICS.find do |match|
+ platform === match
+ end
+ found || Gem::Platform::RUBY
+ end
+ end
+
+ ##
+ # Returns the platform specificity match for the given spec platform and user platform.
+
+ def platform_specificity_match(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
+
+ os_match(spec_platform, user_platform) +
+ cpu_match(spec_platform, user_platform) * 10 +
+ version_match(spec_platform, user_platform) * 100
+ end
+
+ ##
+ # Sorts and filters the best platform match for the given matching specs and platform.
+
+ def sort_and_filter_best_platform_match(matching, platform)
+ return matching if matching.one?
+
+ exact = matching.select {|spec| spec.platform == platform }
+ return exact if exact.any?
+
+ sorted_matching = sort_best_platform_match(matching, platform)
+ exemplary_spec = sorted_matching.first
+
+ sorted_matching.take_while {|spec| same_specificity?(platform, spec, exemplary_spec) && same_deps?(spec, exemplary_spec) }
+ end
+
+ ##
+ # Sorts the best platform match for the given matching specs and platform.
+
+ def sort_best_platform_match(matching, platform)
+ matching.sort_by.with_index do |spec, i|
+ [
+ platform_specificity_match(spec.platform, platform),
+ i, # for stable sort
+ ]
+ end
+ end
+
+ private
+
+ def same_specificity?(platform, spec, exemplary_spec)
+ platform_specificity_match(spec.platform, platform) == platform_specificity_match(exemplary_spec.platform, platform)
+ end
+
+ def same_deps?(spec, exemplary_spec)
+ spec.required_ruby_version == exemplary_spec.required_ruby_version &&
+ spec.required_rubygems_version == exemplary_spec.required_rubygems_version &&
+ spec.dependencies.sort == exemplary_spec.dependencies.sort
+ end
+
+ def os_match(spec_platform, user_platform)
+ if spec_platform.os == user_platform.os
+ 0
+ else
+ 1
+ end
+ end
+
+ def cpu_match(spec_platform, user_platform)
+ if spec_platform.cpu == user_platform.cpu
+ 0
+ elsif spec_platform.cpu == "arm" && user_platform.cpu.to_s.start_with?("arm")
+ 0
+ elsif spec_platform.cpu.nil? || spec_platform.cpu == "universal"
+ 1
+ else
+ 2
+ end
+ end
+
+ def version_match(spec_platform, user_platform)
+ if spec_platform.version == user_platform.version
+ 0
+ elsif spec_platform.version.nil?
+ 1
+ else
+ 2
+ end
+ end
+ end
end
diff --git a/lib/rubygems/psych_tree.rb b/lib/rubygems/psych_tree.rb
index 24857adb9d..8b4c425a33 100644
--- a/lib/rubygems/psych_tree.rb
+++ b/lib/rubygems/psych_tree.rb
@@ -22,7 +22,7 @@ module Gem
def register(target, obj)
end
- # This is ported over from the yaml_tree in 1.9.3
+ # This is ported over from the YAMLTree implementation in Ruby 1.9.3
def format_time(time)
if time.utc?
time.strftime("%Y-%m-%d %H:%M:%S.%9N Z")
diff --git a/lib/rubygems/query_utils.rb b/lib/rubygems/query_utils.rb
index a95a759401..9849370b1a 100644
--- a/lib/rubygems/query_utils.rb
+++ b/lib/rubygems/query_utils.rb
@@ -132,7 +132,7 @@ module Gem::QueryUtils
version_matches = show_prereleases? || !s.version.prerelease?
name_matches && version_matches
- end
+ end.uniq(&:full_name)
spec_tuples = specs.map do |spec|
[spec.name_tuple, spec]
@@ -311,7 +311,7 @@ module Gem::QueryUtils
label = "Installed at"
specs.each do |s|
version = s.version.to_s
- default = ", default" if s.default_gem?
+ default = s.default_gem? ? ", default" : ""
entry << "\n" << " #{label} (#{version}#{default}): #{s.base_dir}"
label = " " * label.length
end
diff --git a/lib/rubygems/rdoc.rb b/lib/rubygems/rdoc.rb
index 907dcd9431..3524b161b2 100644
--- a/lib/rubygems/rdoc.rb
+++ b/lib/rubygems/rdoc.rb
@@ -5,9 +5,22 @@ require_relative "../rubygems"
begin
require "rdoc/rubygems_hook"
module Gem
- RDoc = ::RDoc::RubygemsHook
- end
+ ##
+ # Returns whether RDoc defines its own install hooks through a RubyGems
+ # plugin. This and whatever is guarded by it can be removed once no
+ # supported Ruby ships with RDoc older than 6.9.0.
+
+ def self.rdoc_hooks_defined_via_plugin?
+ Gem::Version.new(::RDoc::VERSION) >= Gem::Version.new("6.9.0")
+ end
- Gem.done_installing(&Gem::RDoc.method(:generation_hook))
+ if rdoc_hooks_defined_via_plugin?
+ RDoc = ::RDoc::RubyGemsHook
+ else
+ RDoc = ::RDoc::RubygemsHook
+
+ Gem.done_installing(&Gem::RDoc.method(:generation_hook))
+ end
+ end
rescue LoadError
end
diff --git a/lib/rubygems/remote_fetcher.rb b/lib/rubygems/remote_fetcher.rb
index c3a41592f6..805f7aaf82 100644
--- a/lib/rubygems/remote_fetcher.rb
+++ b/lib/rubygems/remote_fetcher.rb
@@ -72,10 +72,9 @@ class Gem::RemoteFetcher
# +headers+: A set of additional HTTP headers to be sent to the server when
# fetching the gem.
- def initialize(proxy=nil, dns=nil, headers={})
+ def initialize(proxy = nil, dns = nil, headers = {})
require_relative "core_ext/tcpsocket_init" if Gem.configuration.ipv4_fallback_enabled
require_relative "vendored_net_http"
- require "stringio"
require_relative "vendor/uri/lib/uri"
Socket.do_not_reverse_lookup = true
@@ -83,6 +82,7 @@ class Gem::RemoteFetcher
@proxy = proxy
@pools = {}
@pool_lock = Thread::Mutex.new
+ @pool_size = 1
@cert_files = Gem::Request.get_cert_files
@headers = headers
@@ -246,11 +246,14 @@ class Gem::RemoteFetcher
def fetch_path(uri, mtime = nil, head = false)
uri = Gem::Uri.new uri
- unless uri.scheme
- raise ArgumentError, "uri scheme is invalid: #{uri.scheme.inspect}"
- end
+ method = {
+ "http" => "fetch_http",
+ "https" => "fetch_http",
+ "s3" => "fetch_s3",
+ "file" => "fetch_file",
+ }.fetch(uri.scheme) { raise ArgumentError, "uri scheme is invalid: #{uri.scheme.inspect}" }
- data = send "fetch_#{uri.scheme}", uri, mtime, head
+ data = send method, uri, mtime, head
if data && !head && uri.to_s.end_with?(".gz")
begin
@@ -268,7 +271,7 @@ class Gem::RemoteFetcher
def fetch_s3(uri, mtime = nil, head = false)
begin
- public_uri = s3_uri_signer(uri).sign
+ public_uri = s3_uri_signer(uri, head ? "HEAD" : "GET").sign
rescue Gem::S3URISigner::ConfigurationError, Gem::S3URISigner::InstanceProfileError => e
raise FetchError.new(e.message, "s3://#{uri.host}")
end
@@ -276,8 +279,8 @@ class Gem::RemoteFetcher
end
# we have our own signing code here to avoid a dependency on the aws-sdk gem
- def s3_uri_signer(uri)
- Gem::S3URISigner.new(uri)
+ def s3_uri_signer(uri, method)
+ Gem::S3URISigner.new(uri, method)
end
##
@@ -336,7 +339,7 @@ class Gem::RemoteFetcher
def pools_for(proxy)
@pool_lock.synchronize do
- @pools[proxy] ||= Gem::Request::ConnectionPools.new proxy, @cert_files
+ @pools[proxy] ||= Gem::Request::ConnectionPools.new proxy, @cert_files, @pool_size
end
end
end
diff --git a/lib/rubygems/request/connection_pools.rb b/lib/rubygems/request/connection_pools.rb
index 6c1b04ab65..01e7e0629a 100644
--- a/lib/rubygems/request/connection_pools.rb
+++ b/lib/rubygems/request/connection_pools.rb
@@ -7,11 +7,12 @@ class Gem::Request::ConnectionPools # :nodoc:
attr_accessor :client
end
- def initialize(proxy_uri, cert_files)
+ def initialize(proxy_uri, cert_files, pool_size = 1)
@proxy_uri = proxy_uri
@cert_files = cert_files
@pools = {}
@pool_mutex = Thread::Mutex.new
+ @pool_size = pool_size
end
def pool_for(uri)
@@ -20,9 +21,9 @@ class Gem::Request::ConnectionPools # :nodoc:
@pool_mutex.synchronize do
@pools[key] ||=
if https? uri
- Gem::Request::HTTPSPool.new(http_args, @cert_files, @proxy_uri)
+ Gem::Request::HTTPSPool.new(http_args, @cert_files, @proxy_uri, @pool_size)
else
- Gem::Request::HTTPPool.new(http_args, @cert_files, @proxy_uri)
+ Gem::Request::HTTPPool.new(http_args, @cert_files, @proxy_uri, @pool_size)
end
end
end
diff --git a/lib/rubygems/request/http_pool.rb b/lib/rubygems/request/http_pool.rb
index 52543de41f..468502ca6b 100644
--- a/lib/rubygems/request/http_pool.rb
+++ b/lib/rubygems/request/http_pool.rb
@@ -9,12 +9,14 @@
class Gem::Request::HTTPPool # :nodoc:
attr_reader :cert_files, :proxy_uri
- def initialize(http_args, cert_files, proxy_uri)
+ def initialize(http_args, cert_files, proxy_uri, pool_size)
@http_args = http_args
@cert_files = cert_files
@proxy_uri = proxy_uri
- @queue = Thread::SizedQueue.new 1
- @queue << nil
+ @pool_size = pool_size
+
+ @queue = Thread::SizedQueue.new @pool_size
+ setup_queue
end
def checkout
@@ -31,7 +33,8 @@ class Gem::Request::HTTPPool # :nodoc:
connection.finish
end
end
- @queue.push(nil)
+
+ setup_queue
end
private
@@ -44,4 +47,8 @@ class Gem::Request::HTTPPool # :nodoc:
connection.start
connection
end
+
+ def setup_queue
+ @pool_size.times { @queue.push(nil) }
+ end
end
diff --git a/lib/rubygems/request_set.rb b/lib/rubygems/request_set.rb
index 875df7e019..5a855fdb10 100644
--- a/lib/rubygems/request_set.rb
+++ b/lib/rubygems/request_set.rb
@@ -181,13 +181,10 @@ class Gem::RequestSet
# Install requested gems after they have been downloaded
sorted_requests.each do |req|
- if req.installed?
+ if req.installed? && @always_install.none? {|spec| spec == req.spec.spec }
req.spec.spec.build_extensions
-
- if @always_install.none? {|spec| spec == req.spec.spec }
- yield req, nil if block_given?
- next
- end
+ yield req, nil if block_given?
+ next
end
spec =
diff --git a/lib/rubygems/request_set/gem_dependency_api.rb b/lib/rubygems/request_set/gem_dependency_api.rb
index 4347d22ccb..99d96f928b 100644
--- a/lib/rubygems/request_set/gem_dependency_api.rb
+++ b/lib/rubygems/request_set/gem_dependency_api.rb
@@ -330,7 +330,7 @@ class Gem::RequestSet::GemDependencyAPI
# git: ::
# Install this dependency from a git repository:
#
- # gem 'private_gem', git: git@my.company.example:private_gem.git'
+ # gem 'private_gem', git: 'git@my.company.example:private_gem.git'
#
# gist: ::
# Install this dependency from the gist ID:
diff --git a/lib/rubygems/request_set/lockfile.rb b/lib/rubygems/request_set/lockfile.rb
index c446b3ae51..da6dd329bc 100644
--- a/lib/rubygems/request_set/lockfile.rb
+++ b/lib/rubygems/request_set/lockfile.rb
@@ -38,7 +38,7 @@ class Gem::RequestSet::Lockfile
end
##
- # Creates a new Lockfile for the given +request_set+ and +gem_deps_file+
+ # Creates a new Lockfile for the given Gem::RequestSet and +gem_deps_file+
# location.
def self.build(request_set, gem_deps_file, dependencies = nil)
diff --git a/lib/rubygems/requirement.rb b/lib/rubygems/requirement.rb
index 02543cb14a..0d3f98eb0f 100644
--- a/lib/rubygems/requirement.rb
+++ b/lib/rubygems/requirement.rb
@@ -13,8 +13,8 @@ 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 },
"<=" => lambda {|v, r| v <= r },
"~>" => lambda {|v, r| v >= r && v.release < r.bump },
@@ -22,7 +22,7 @@ class Gem::Requirement
SOURCE_SET_REQUIREMENT = Struct.new(:for_lockfile).new "!" # :nodoc:
- quoted = OPS.keys.map {|k| Regexp.quote k }.join "|"
+ quoted = Regexp.union(OPS.keys)
PATTERN_RAW = "\\s*(#{quoted})?\\s*(#{Gem::Version::VERSION_PATTERN})\\s*".freeze # :nodoc:
##
@@ -106,13 +106,15 @@ class Gem::Requirement
unless PATTERN =~ obj.to_s
raise BadRequirementError, "Illformed requirement [#{obj.inspect}]"
end
+ op = -($1 || "=")
+ version = -$2
- if $1 == ">=" && $2 == "0"
+ if op == ">=" && version == "0"
DefaultRequirement
- elsif $1 == ">=" && $2 == "0.a"
+ elsif op == ">=" && version == "0.a"
DefaultPrereleaseRequirement
else
- [-($1 || "="), Gem::Version.new($2)]
+ [op, Gem::Version.new(version)]
end
end
@@ -201,7 +203,8 @@ class Gem::Requirement
def marshal_load(array) # :nodoc:
@requirements = array[0]
- raise TypeError, "wrong @requirements" unless Array === @requirements
+ raise TypeError, "wrong @requirements" unless Array === @requirements &&
+ @requirements.all? {|r| r.size == 2 && (r.first.is_a?(String) || r[0] = "=") && r.last.is_a?(Gem::Version) }
end
def yaml_initialize(tag, vals) # :nodoc:
@@ -214,10 +217,6 @@ class Gem::Requirement
yaml_initialize coder.tag, coder.map
end
- def to_yaml_properties # :nodoc:
- ["@requirements"]
- end
-
def encode_with(coder) # :nodoc:
coder.add "requirements", @requirements
end
@@ -242,7 +241,7 @@ class Gem::Requirement
def satisfied_by?(version)
raise ArgumentError, "Need a Gem::Version: #{version.inspect}" unless
Gem::Version === version
- requirements.all? {|op, rv| OPS[op].call version, rv }
+ requirements.all? {|op, rv| OPS.fetch(op).call version, rv }
end
alias_method :===, :satisfied_by?
diff --git a/lib/rubygems/resolver.rb b/lib/rubygems/resolver.rb
index 115c716b6b..bc4fef893e 100644
--- a/lib/rubygems/resolver.rb
+++ b/lib/rubygems/resolver.rb
@@ -2,7 +2,6 @@
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
@@ -59,7 +58,7 @@ class Gem::Resolver
def self.compose_sets(*sets)
sets.compact!
- sets = sets.map do |set|
+ sets = sets.flat_map do |set|
case set
when Gem::Resolver::BestSet then
set
@@ -68,7 +67,7 @@ class Gem::Resolver
else
set
end
- end.flatten
+ end
case sets.length
when 0 then
@@ -144,7 +143,7 @@ class Gem::Resolver
[spec, activation_request]
end
- def requests(s, act, reqs=[]) # :nodoc:
+ def requests(s, act, reqs = []) # :nodoc:
return reqs if @ignore_dependencies
s.fetch_development_dependencies if @development
@@ -183,7 +182,7 @@ class Gem::Resolver
# Proceed with resolution! Returns an array of ActivationRequest objects.
def resolve
- Gem::Molinillo::Resolver.new(self, self).resolve(@needed.map {|d| DependencyRequest.new d, nil }).tsort.map(&:payload).compact
+ Gem::Molinillo::Resolver.new(self, self).resolve(@needed.map {|d| DependencyRequest.new d, nil }).tsort.filter_map(&:payload)
rescue Gem::Molinillo::VersionConflict => e
conflict = e.conflicts.values.first
raise Gem::DependencyResolutionError, Conflict.new(conflict.requirement_trees.first.first, conflict.existing, conflict.requirement)
@@ -241,7 +240,7 @@ class Gem::Resolver
sources.each do |source|
groups[source].
- sort_by {|spec| [spec.version, spec.platform =~ Gem::Platform.local ? 1 : 0] }. # rubocop:disable Performance/RegexpMatch
+ sort_by {|spec| [spec.version, -Gem::Platform.platform_specificity_match(spec.platform, Gem::Platform.local)] }.
map {|spec| ActivationRequest.new spec, dependency }.
each {|activation_request| activation_requests << activation_request }
end
diff --git a/lib/rubygems/resolver/activation_request.rb b/lib/rubygems/resolver/activation_request.rb
index fc9ff58f57..5c722001b1 100644
--- a/lib/rubygems/resolver/activation_request.rb
+++ b/lib/rubygems/resolver/activation_request.rb
@@ -106,7 +106,7 @@ class Gem::Resolver::ActivationRequest
this_spec = full_spec
Gem::Specification.any? do |s|
- s == this_spec
+ s == this_spec && s.base_dir == this_spec.base_dir
end
end
end
diff --git a/lib/rubygems/resolver/api_set.rb b/lib/rubygems/resolver/api_set.rb
index 3e4dadc40f..9f6695a6a9 100644
--- a/lib/rubygems/resolver/api_set.rb
+++ b/lib/rubygems/resolver/api_set.rb
@@ -104,16 +104,21 @@ class Gem::Resolver::APISet < Gem::Resolver::Set
end
uri = @dep_uri + name
- str = Gem::RemoteFetcher.fetcher.fetch_path uri
- lines(str).each do |ver|
- number, platform, dependencies, requirements = parse_gem(ver)
+ begin
+ str = Gem::RemoteFetcher.fetcher.fetch_path uri
+ rescue Gem::RemoteFetcher::FetchError
+ @data[name] = []
+ else
+ 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
+ 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 }
+ @data[name] << { name: name, number: number, platform: platform, dependencies: dependencies, requirements: requirements }
+ end
end
@data[name]
diff --git a/lib/rubygems/resolver/api_set/gem_parser.rb b/lib/rubygems/resolver/api_set/gem_parser.rb
index 643b857107..7dd9a89ebc 100644
--- a/lib/rubygems/resolver/api_set/gem_parser.rb
+++ b/lib/rubygems/resolver/api_set/gem_parser.rb
@@ -1,15 +1,12 @@
# frozen_string_literal: true
class Gem::Resolver::APISet::GemParser
- EMPTY_ARRAY = [].freeze
- private_constant :EMPTY_ARRAY
-
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) } : EMPTY_ARRAY
- requirements = requirements ? requirements.map! {|d| parse_dependency(d) } : EMPTY_ARRAY
+ dependencies = dependencies ? dependencies.map! {|d| parse_dependency(d) } : []
+ requirements = requirements ? requirements.map! {|d| parse_dependency(d) } : []
[version, platform, dependencies, requirements]
end
diff --git a/lib/rubygems/resolver/best_set.rb b/lib/rubygems/resolver/best_set.rb
index a983f8c6b6..e647a2c11b 100644
--- a/lib/rubygems/resolver/best_set.rb
+++ b/lib/rubygems/resolver/best_set.rb
@@ -21,7 +21,7 @@ class Gem::Resolver::BestSet < Gem::Resolver::ComposedSet
def pick_sets # :nodoc:
@sources.each_source do |source|
- @sets << source.dependency_resolver_set
+ @sets << source.dependency_resolver_set(@prerelease)
end
end
@@ -29,10 +29,6 @@ class Gem::Resolver::BestSet < Gem::Resolver::ComposedSet
pick_sets if @remote && @sets.empty?
super
- rescue Gem::RemoteFetcher::FetchError => e
- replace_failed_api_set e
-
- retry
end
def prefetch(reqs) # :nodoc:
@@ -50,28 +46,4 @@ class Gem::Resolver::BestSet < Gem::Resolver::ComposedSet
q.pp @sets
end
end
-
- ##
- # Replaces a failed APISet for the URI in +error+ with an IndexSet.
- #
- # If no matching APISet can be found the original +error+ is raised.
- #
- # The calling method must retry the exception to repeat the lookup.
-
- def replace_failed_api_set(error) # :nodoc:
- uri = error.original_uri
- uri = Gem::URI uri unless Gem::URI === uri
- uri += "."
-
- raise error unless api_set = @sets.find do |set|
- Gem::Resolver::APISet === set && set.dep_uri == uri
- end
-
- index_set = Gem::Resolver::IndexSet.new api_set.source
-
- @sets.map! do |set|
- next set unless set == api_set
- index_set
- end
- end
end
diff --git a/lib/rubygems/resolver/composed_set.rb b/lib/rubygems/resolver/composed_set.rb
index 8a714ad447..e67dd41754 100644
--- a/lib/rubygems/resolver/composed_set.rb
+++ b/lib/rubygems/resolver/composed_set.rb
@@ -44,16 +44,16 @@ class Gem::Resolver::ComposedSet < Gem::Resolver::Set
end
def errors
- @errors + @sets.map(&:errors).flatten
+ @errors + @sets.flat_map(&:errors)
end
##
# Finds all specs matching +req+ in all sets.
def find_all(req)
- @sets.map do |s|
+ @sets.flat_map do |s|
s.find_all req
- end.flatten
+ end
end
##
diff --git a/lib/rubygems/resolver/conflict.rb b/lib/rubygems/resolver/conflict.rb
index 367a36b43d..77c3add4b3 100644
--- a/lib/rubygems/resolver/conflict.rb
+++ b/lib/rubygems/resolver/conflict.rb
@@ -21,7 +21,7 @@ class Gem::Resolver::Conflict
# Creates a new resolver conflict when +dependency+ is in conflict with an
# already +activated+ specification.
- def initialize(dependency, activated, failed_dep=dependency)
+ def initialize(dependency, activated, failed_dep = dependency)
@dependency = dependency
@activated = activated
@failed_dep = failed_dep
diff --git a/lib/rubygems/resolver/git_set.rb b/lib/rubygems/resolver/git_set.rb
index 89342ff80d..2912378fe7 100644
--- a/lib/rubygems/resolver/git_set.rb
+++ b/lib/rubygems/resolver/git_set.rb
@@ -36,7 +36,6 @@ class Gem::Resolver::GitSet < Gem::Resolver::Set
def initialize # :nodoc:
super()
- @git = ENV["git"] || "git"
@need_submodules = {}
@repositories = {}
@root_dir = Gem.dir
diff --git a/lib/rubygems/resolver/index_set.rb b/lib/rubygems/resolver/index_set.rb
index 0b4f376452..cddaf8773f 100644
--- a/lib/rubygems/resolver/index_set.rb
+++ b/lib/rubygems/resolver/index_set.rb
@@ -65,11 +65,11 @@ class Gem::Resolver::IndexSet < Gem::Resolver::Set
q.breakable
- names = @all.values.map do |tuples|
+ names = @all.values.flat_map do |tuples|
tuples.map do |_, tuple|
tuple.full_name
end
- end.flatten
+ end
q.seplist names do |name|
q.text name
diff --git a/lib/rubygems/resolver/source_set.rb b/lib/rubygems/resolver/source_set.rb
index 296cf41078..074b473edc 100644
--- a/lib/rubygems/resolver/source_set.rb
+++ b/lib/rubygems/resolver/source_set.rb
@@ -42,6 +42,6 @@ class Gem::Resolver::SourceSet < Gem::Resolver::Set
def get_set(name)
link = @links[name]
- @sets[link] ||= Gem::Source.new(link).dependency_resolver_set if link
+ @sets[link] ||= Gem::Source.new(link).dependency_resolver_set(@prerelease) if link
end
end
diff --git a/lib/rubygems/s3_uri_signer.rb b/lib/rubygems/s3_uri_signer.rb
index 7c95a9d4f5..148cba38c4 100644
--- a/lib/rubygems/s3_uri_signer.rb
+++ b/lib/rubygems/s3_uri_signer.rb
@@ -1,11 +1,14 @@
# frozen_string_literal: true
require_relative "openssl"
+require_relative "user_interaction"
##
# 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
+ include Gem::UserInteraction
+
class ConfigurationError < Gem::Exception
def initialize(message)
super message
@@ -27,9 +30,11 @@ class Gem::S3URISigner
end
attr_accessor :uri
+ attr_accessor :method
- def initialize(uri)
+ def initialize(uri, method)
@uri = uri
+ @method = method
end
##
@@ -38,7 +43,7 @@ class Gem::S3URISigner
s3_config = fetch_s3_config
current_time = Time.now.utc
- date_time = current_time.strftime("%Y%m%dT%H%m%SZ")
+ date_time = current_time.strftime("%Y%m%dT%H%M%SZ")
date = date_time[0,8]
credential_info = "#{date}/#{s3_config.region}/s3/aws4_request"
@@ -73,7 +78,7 @@ class Gem::S3URISigner
def generate_canonical_request(canonical_host, query_params)
[
- "GET",
+ method.upcase,
uri.path,
query_params,
"host:#{canonical_host}",
@@ -145,17 +150,40 @@ class Gem::S3URISigner
require_relative "request/connection_pools"
require "json"
- iam_info = ec2_metadata_request(EC2_IAM_INFO)
+ # First try V2 fallback to V1
+ res = nil
+ begin
+ res = ec2_metadata_credentials_imds_v2
+ rescue InstanceProfileError
+ alert_warning "Unable to access ec2 credentials via IMDSv2, falling back to IMDSv1"
+ res = ec2_metadata_credentials_imds_v1
+ end
+ res
+ end
+
+ def ec2_metadata_credentials_imds_v2
+ token = ec2_metadata_token
+ iam_info = ec2_metadata_request(EC2_IAM_INFO, token:)
# Expected format: arn:aws:iam::<id>:instance-profile/<role_name>
role_name = iam_info["InstanceProfileArn"].split("/").last
- ec2_metadata_request(EC2_IAM_SECURITY_CREDENTIALS + role_name)
+ ec2_metadata_request(EC2_IAM_SECURITY_CREDENTIALS + role_name, token:)
end
- def ec2_metadata_request(url)
- uri = Gem::URI(url)
- @request_pool ||= create_request_pool(uri)
- request = Gem::Request.new(uri, Gem::Net::HTTP::Get, nil, @request_pool)
- response = request.fetch
+ def ec2_metadata_credentials_imds_v1
+ iam_info = ec2_metadata_request(EC2_IAM_INFO, token: nil)
+ # Expected format: arn:aws:iam::<id>:instance-profile/<role_name>
+ role_name = iam_info["InstanceProfileArn"].split("/").last
+ ec2_metadata_request(EC2_IAM_SECURITY_CREDENTIALS + role_name, token: nil)
+ end
+
+ def ec2_metadata_request(url, token:)
+ request = ec2_iam_request(Gem::URI(url), Gem::Net::HTTP::Get)
+
+ response = request.fetch do |req|
+ if token
+ req.add_field "X-aws-ec2-metadata-token", token
+ end
+ end
case response
when Gem::Net::HTTPOK then
@@ -165,6 +193,26 @@ class Gem::S3URISigner
end
end
+ def ec2_metadata_token
+ request = ec2_iam_request(Gem::URI(EC2_IAM_TOKEN), Gem::Net::HTTP::Put)
+
+ response = request.fetch do |req|
+ req.add_field "X-aws-ec2-metadata-token-ttl-seconds", 60
+ end
+
+ case response
+ when Gem::Net::HTTPOK then
+ response.body
+ else
+ raise InstanceProfileError.new("Unable to fetch AWS metadata from #{uri}: #{response.message} #{response.code}")
+ end
+ end
+
+ def ec2_iam_request(uri, verb)
+ @request_pool ||= create_request_pool(uri)
+ Gem::Request.new(uri, verb, nil, @request_pool)
+ end
+
def create_request_pool(uri)
proxy_uri = Gem::Request.proxy_uri(Gem::Request.get_proxy_from_env(uri.scheme))
certs = Gem::Request.get_cert_files
@@ -172,6 +220,7 @@ class Gem::S3URISigner
end
BASE64_URI_TRANSLATE = { "+" => "%2B", "/" => "%2F", "=" => "%3D", "\n" => "" }.freeze
+ EC2_IAM_TOKEN = "http://169.254.169.254/latest/api/token"
EC2_IAM_INFO = "http://169.254.169.254/latest/meta-data/iam/info"
EC2_IAM_SECURITY_CREDENTIALS = "http://169.254.169.254/latest/meta-data/iam/security-credentials/"
end
diff --git a/lib/rubygems/safe_marshal/reader.rb b/lib/rubygems/safe_marshal/reader.rb
index 740be113e5..4362d65fd6 100644
--- a/lib/rubygems/safe_marshal/reader.rb
+++ b/lib/rubygems/safe_marshal/reader.rb
@@ -20,6 +20,12 @@ module Gem
class EOFError < Error
end
+ class DataTooShortError < Error
+ end
+
+ class NegativeLengthError < Error
+ end
+
def initialize(io)
@io = io
end
@@ -27,7 +33,7 @@ module Gem
def read!
read_header
root = read_element
- raise UnconsumedBytesError unless @io.eof?
+ raise UnconsumedBytesError, "expected EOF, got #{@io.read(10).inspect}... after top-level element #{root.class}" unless @io.eof?
root
end
@@ -41,8 +47,16 @@ module Gem
raise UnsupportedVersionError, "Unsupported marshal version #{v.bytes.map(&:ord).join(".")}, expected #{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}" unless v == MARSHAL_VERSION
end
+ def read_bytes(n)
+ raise NegativeLengthError if n < 0
+ str = @io.read(n)
+ raise EOFError, "expected #{n} bytes, got EOF" if str.nil?
+ raise DataTooShortError, "expected #{n} bytes, got #{str.inspect}" unless str.bytesize == n
+ str
+ end
+
def read_byte
- @io.getbyte
+ @io.getbyte || raise(EOFError, "Unexpected EOF")
end
def read_integer
@@ -67,8 +81,6 @@ module Gem
read_byte | (read_byte << 8) | -0x10000
when 0xFF
read_byte | -0x100
- when nil
- raise EOFError, "Unexpected EOF"
else
signed = (b ^ 128) - 128
if b >= 128
@@ -107,8 +119,6 @@ module Gem
when 47 then read_regexp # ?/
when 83 then read_struct # ?S
when 67 then read_user_class # ?C
- when nil
- raise EOFError, "Unexpected EOF"
else
raise Error, "Unknown marshal type discriminator #{type.chr.inspect} (#{type})"
end
@@ -127,7 +137,7 @@ module Gem
Elements::Symbol.new(byte.chr)
end
else
- name = -@io.read(len)
+ name = read_bytes(len)
Elements::Symbol.new(name)
end
end
@@ -138,7 +148,7 @@ module Gem
def read_string
length = read_integer
return EMPTY_STRING if length == 0
- str = @io.read(length)
+ str = read_bytes(length)
Elements::String.new(str)
end
@@ -152,7 +162,7 @@ module Gem
def read_user_defined
name = read_element
- binary_string = @io.read(read_integer)
+ binary_string = read_bytes(read_integer)
Elements::UserDefined.new(name, binary_string)
end
@@ -162,6 +172,7 @@ module Gem
def read_array
length = read_integer
return EMPTY_ARRAY if length == 0
+ raise NegativeLengthError if length < 0
elements = Array.new(length) do
read_element
end
@@ -170,7 +181,9 @@ module Gem
def read_object_with_ivars
object = read_element
- ivars = Array.new(read_integer) do
+ length = read_integer
+ raise NegativeLengthError if length < 0
+ ivars = Array.new(length) do
[read_element, read_element]
end
Elements::WithIvars.new(object, ivars)
@@ -239,7 +252,9 @@ module Gem
end
def read_hash_with_default_value
- pairs = Array.new(read_integer) do
+ length = read_integer
+ raise NegativeLengthError if length < 0
+ pairs = Array.new(length) do
[read_element, read_element]
end
default = read_element
@@ -249,7 +264,9 @@ module Gem
def read_object
name = read_element
object = Elements::Object.new(name)
- ivars = Array.new(read_integer) do
+ length = read_integer
+ raise NegativeLengthError if length < 0
+ ivars = Array.new(length) do
[read_element, read_element]
end
Elements::WithIvars.new(object, ivars)
@@ -260,13 +277,13 @@ module Gem
end
def read_float
- string = @io.read(read_integer)
+ string = read_bytes(read_integer)
Elements::Float.new(string)
end
def read_bignum
sign = read_byte
- data = @io.read(read_integer * 2)
+ data = read_bytes(read_integer * 2)
Elements::Bignum.new(sign, data)
end
diff --git a/lib/rubygems/safe_marshal/visitors/to_ruby.rb b/lib/rubygems/safe_marshal/visitors/to_ruby.rb
index a9f1d048d4..a1f9481776 100644
--- a/lib/rubygems/safe_marshal/visitors/to_ruby.rb
+++ b/lib/rubygems/safe_marshal/visitors/to_ruby.rb
@@ -45,7 +45,7 @@ module Gem::SafeMarshal
idx = 0
# not idiomatic, but there's a huge number of IMEMOs allocated here, so we avoid the block
# because this is such a hot path when doing a bundle install with the full index
- until idx == size
+ while idx < size
push_stack idx
array << visit(elements[idx])
idx += 1
@@ -98,16 +98,21 @@ module Gem::SafeMarshal
end
s = e.object.binary_string
+ # 122 is the largest integer that can be represented in marshal in a single byte
+ raise TimeTooLargeError.new("binary string too large", stack: formatted_stack) if s.bytesize > 122
marshal_string = "\x04\bIu:\tTime".b
- marshal_string.concat(s.size + 5)
+ marshal_string.concat(s.bytesize + 5)
marshal_string << s
+ # internal is limited to 5, so no overflow is possible
marshal_string.concat(internal.size + 5)
internal.each do |k, v|
+ k = k.name
+ # ivar name can't be too large because only known ivars are in the internal ivars list
marshal_string.concat(":")
- marshal_string.concat(k.size + 5)
- marshal_string.concat(k.to_s)
+ marshal_string.concat(k.bytesize + 5)
+ marshal_string.concat(k)
dumped = Marshal.dump(v)
dumped[0, 2] = ""
marshal_string.concat(dumped)
@@ -171,11 +176,11 @@ module Gem::SafeMarshal
end
def visit_Gem_SafeMarshal_Elements_ObjectLink(o)
- @objects[o.offset]
+ @objects.fetch(o.offset)
end
def visit_Gem_SafeMarshal_Elements_SymbolLink(o)
- @symbols[o.offset]
+ @symbols.fetch(o.offset)
end
def visit_Gem_SafeMarshal_Elements_UserDefined(o)
@@ -219,16 +224,18 @@ module Gem::SafeMarshal
end
def visit_Gem_SafeMarshal_Elements_Float(f)
- case f.string
- when "inf"
- ::Float::INFINITY
- when "-inf"
- -::Float::INFINITY
- when "nan"
- ::Float::NAN
- else
- f.string.to_f
- end
+ register_object(
+ case f.string
+ when "inf"
+ ::Float::INFINITY
+ when "-inf"
+ -::Float::INFINITY
+ when "nan"
+ ::Float::NAN
+ else
+ f.string.to_f
+ end
+ )
end
def visit_Gem_SafeMarshal_Elements_Bignum(b)
@@ -374,6 +381,12 @@ module Gem::SafeMarshal
class Error < StandardError
end
+ class TimeTooLargeError < Error
+ def initialize(message, stack:)
+ super "#{message} @ #{stack.join "."}"
+ end
+ end
+
class UnpermittedSymbolError < Error
def initialize(symbol:, stack:)
@symbol = symbol
diff --git a/lib/rubygems/security/policy.rb b/lib/rubygems/security/policy.rb
index 7b86ac5763..128958ab80 100644
--- a/lib/rubygems/security/policy.rb
+++ b/lib/rubygems/security/policy.rb
@@ -143,7 +143,7 @@ class Gem::Security::Policy
end
##
- # Ensures the root of +chain+ has a trusted certificate in +trust_dir+ and
+ # Ensures the root of +chain+ has a trusted certificate in Gem::Security.trust_dir and
# the digests of the two certificates match according to +digester+
def check_trust(chain, digester, trust_dir)
diff --git a/lib/rubygems/security/signer.rb b/lib/rubygems/security/signer.rb
index 5732fb57fd..eeeeb52906 100644
--- a/lib/rubygems/security/signer.rb
+++ b/lib/rubygems/security/signer.rb
@@ -52,7 +52,7 @@ class Gem::Security::Signer
re_signed_cert = Gem::Security.re_sign(
expired_cert,
private_key,
- (Gem::Security::ONE_DAY * Gem.configuration.cert_expiration_length_days)
+ Gem::Security::ONE_DAY * Gem.configuration.cert_expiration_length_days
)
Gem::Security.write(re_signed_cert, expired_cert_path)
diff --git a/lib/rubygems/shellwords.rb b/lib/rubygems/shellwords.rb
deleted file mode 100644
index 741dccb363..0000000000
--- a/lib/rubygems/shellwords.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-# frozen_string_literal: true
-
-autoload :Shellwords, "shellwords"
diff --git a/lib/rubygems/source.rb b/lib/rubygems/source.rb
index d90e311b65..f203b7312b 100644
--- a/lib/rubygems/source.rb
+++ b/lib/rubygems/source.rb
@@ -67,28 +67,11 @@ class Gem::Source
##
# Returns a Set that can fetch specifications from this source.
-
- def dependency_resolver_set # :nodoc:
- return Gem::Resolver::IndexSet.new self if uri.scheme == "file"
-
- 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
- response = fetcher.fetch_path bundler_api_uri, nil, true
- rescue Gem::RemoteFetcher::FetchError
- Gem::Resolver::IndexSet.new self
- else
- Gem::Resolver::APISet.new response.uri + "./info/"
- end
+ #
+ # The set will optionally fetch prereleases if requested.
+ #
+ def dependency_resolver_set(prerelease = false)
+ new_dependency_resolver_set.tap {|set| set.prerelease = prerelease }
end
def hash # :nodoc:
@@ -119,7 +102,7 @@ class Gem::Source
end
##
- # Fetches a specification for the given +name_tuple+.
+ # Fetches a specification for the given Gem::NameTuple.
def fetch_spec(name_tuple)
fetcher = Gem::RemoteFetcher.fetcher
@@ -207,31 +190,56 @@ class Gem::Source
# Downloads +spec+ and writes it to +dir+. See also
# Gem::RemoteFetcher#download.
- def download(spec, dir=Dir.pwd)
+ def download(spec, dir = Dir.pwd)
fetcher = Gem::RemoteFetcher.fetcher
fetcher.download spec, uri.to_s, dir
end
def pretty_print(q) # :nodoc:
- q.group 2, "[Remote:", "]" do
- q.breakable
- q.text @uri.to_s
-
- if api = uri
+ q.object_group(self) do
+ q.group 2, "[Remote:", "]" do
q.breakable
- q.text "API URI: "
- q.text api.to_s
+ q.text @uri.to_s
+
+ if api = uri
+ q.breakable
+ q.text "API URI: "
+ q.text api.to_s
+ end
end
end
end
- def typo_squatting?(host, distance_threshold=4)
+ def typo_squatting?(host, distance_threshold = 4)
return if @uri.host.nil?
levenshtein_distance(@uri.host, host).between? 1, distance_threshold
end
private
+ def new_dependency_resolver_set
+ return Gem::Resolver::IndexSet.new self if uri.scheme == "file"
+
+ 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) + "versions"
+
+ begin
+ fetcher = Gem::RemoteFetcher.fetcher
+ response = fetcher.fetch_path bundler_api_uri, nil, true
+ rescue Gem::RemoteFetcher::FetchError
+ Gem::Resolver::IndexSet.new self
+ else
+ Gem::Resolver::APISet.new response.uri + "./info/"
+ end
+ end
+
def enforce_trailing_slash(uri)
uri.merge(uri.path.gsub(%r{/+$}, "") + "/")
end
diff --git a/lib/rubygems/source/git.rb b/lib/rubygems/source/git.rb
index bda63c6844..baf2f9dd4c 100644
--- a/lib/rubygems/source/git.rb
+++ b/lib/rubygems/source/git.rb
@@ -58,7 +58,6 @@ class Gem::Source::Git < Gem::Source
@remote = true
@root_dir = Gem.dir
- @git = ENV["git"] || "git"
end
def <=>(other)
@@ -81,6 +80,10 @@ class Gem::Source::Git < Gem::Source
@need_submodules == other.need_submodules
end
+ def git_command
+ ENV.fetch("git", "git")
+ end
+
##
# Checks out the files for the repository into the install_dir.
@@ -90,18 +93,18 @@ class Gem::Source::Git < Gem::Source
return false unless File.exist? repo_cache_dir
unless File.exist? install_dir
- system @git, "clone", "--quiet", "--no-checkout",
+ system git_command, "clone", "--quiet", "--no-checkout",
repo_cache_dir, install_dir
end
Dir.chdir install_dir do
- system @git, "fetch", "--quiet", "--force", "--tags", install_dir
+ system git_command, "fetch", "--quiet", "--force", "--tags", install_dir
- success = system @git, "reset", "--quiet", "--hard", rev_parse
+ success = system git_command, "reset", "--quiet", "--hard", rev_parse
if @need_submodules
require "open3"
- _, status = Open3.capture2e(@git, "submodule", "update", "--quiet", "--init", "--recursive")
+ _, status = Open3.capture2e(git_command, "submodule", "update", "--quiet", "--init", "--recursive")
success &&= status.success?
end
@@ -118,11 +121,11 @@ class Gem::Source::Git < Gem::Source
if File.exist? repo_cache_dir
Dir.chdir repo_cache_dir do
- system @git, "fetch", "--quiet", "--force", "--tags",
+ system git_command, "fetch", "--quiet", "--force", "--tags",
@repository, "refs/heads/*:refs/heads/*"
end
else
- system @git, "clone", "--quiet", "--bare", "--no-hardlinks",
+ system git_command, "clone", "--quiet", "--bare", "--no-hardlinks",
@repository, repo_cache_dir
end
end
@@ -157,12 +160,14 @@ class Gem::Source::Git < Gem::Source
end
def pretty_print(q) # :nodoc:
- q.group 2, "[Git: ", "]" do
- q.breakable
- q.text @repository
+ q.object_group(self) do
+ q.group 2, "[Git: ", "]" do
+ q.breakable
+ q.text @repository
- q.breakable
- q.text @reference
+ q.breakable
+ q.text @reference
+ end
end
end
@@ -180,7 +185,7 @@ class Gem::Source::Git < Gem::Source
hash = nil
Dir.chdir repo_cache_dir do
- hash = Gem::Util.popen(@git, "rev-parse", @reference).strip
+ hash = Gem::Util.popen(git_command, "rev-parse", @reference).strip
end
raise Gem::Exception,
@@ -199,7 +204,7 @@ class Gem::Source::Git < Gem::Source
return [] unless install_dir
Dir.chdir install_dir do
- Dir["{,*,*/*}.gemspec"].map do |spec_file|
+ Dir["{,*,*/*}.gemspec"].filter_map do |spec_file|
directory = File.dirname spec_file
file = File.basename spec_file
@@ -216,7 +221,7 @@ class Gem::Source::Git < Gem::Source
end
spec
end
- end.compact
+ end
end
end
diff --git a/lib/rubygems/source/installed.rb b/lib/rubygems/source/installed.rb
index cbe12a0516..f5c96fee51 100644
--- a/lib/rubygems/source/installed.rb
+++ b/lib/rubygems/source/installed.rb
@@ -32,6 +32,8 @@ class Gem::Source::Installed < Gem::Source
end
def pretty_print(q) # :nodoc:
- q.text "[Installed]"
+ q.object_group(self) do
+ q.text "[Installed]"
+ end
end
end
diff --git a/lib/rubygems/source/local.rb b/lib/rubygems/source/local.rb
index d81d8343a8..ba6eea1f9a 100644
--- a/lib/rubygems/source/local.rb
+++ b/lib/rubygems/source/local.rb
@@ -117,10 +117,14 @@ class Gem::Source::Local < Gem::Source
end
def pretty_print(q) # :nodoc:
- q.group 2, "[Local gems:", "]" do
- q.breakable
- q.seplist @specs.keys do |v|
- q.text v.full_name
+ q.object_group(self) do
+ q.group 2, "[Local gems:", "]" do
+ q.breakable
+ if @specs
+ q.seplist @specs.keys do |v|
+ q.text v.full_name
+ end
+ end
end
end
end
diff --git a/lib/rubygems/source/specific_file.rb b/lib/rubygems/source/specific_file.rb
index e9b2753646..dde1d48a21 100644
--- a/lib/rubygems/source/specific_file.rb
+++ b/lib/rubygems/source/specific_file.rb
@@ -42,9 +42,11 @@ class Gem::Source::SpecificFile < Gem::Source
end
def pretty_print(q) # :nodoc:
- q.group 2, "[SpecificFile:", "]" do
- q.breakable
- q.text @path
+ q.object_group(self) do
+ q.group 2, "[SpecificFile:", "]" do
+ q.breakable
+ q.text @path
+ end
end
end
diff --git a/lib/rubygems/source_list.rb b/lib/rubygems/source_list.rb
index 33db64fbc1..19bf4595c4 100644
--- a/lib/rubygems/source_list.rb
+++ b/lib/rubygems/source_list.rb
@@ -60,6 +60,42 @@ class Gem::SourceList
end
##
+ # Prepends +obj+ to the beginning of the source list which may be a Gem::Source, Gem::URI or URI
+ # Moves +obj+ to the beginning of the list if already present.
+ # String.
+
+ def prepend(obj)
+ src = case obj
+ when Gem::Source
+ obj
+ else
+ Gem::Source.new(obj)
+ end
+
+ @sources.delete(src) if @sources.include?(src)
+ @sources.unshift(src)
+ src
+ end
+
+ ##
+ # Appends +obj+ to the end of the source list, moving it if already present.
+ # +obj+ may be a Gem::Source, Gem::URI or URI String.
+ # Moves +obj+ to the end of the list if already present.
+
+ def append(obj)
+ src = case obj
+ when Gem::Source
+ obj
+ else
+ Gem::Source.new(obj)
+ end
+
+ @sources.delete(src) if @sources.include?(src)
+ @sources << src
+ src
+ end
+
+ ##
# Replaces this SourceList with the sources in +other+ See #<< for
# acceptable items in +other+.
diff --git a/lib/rubygems/spec_fetcher.rb b/lib/rubygems/spec_fetcher.rb
index 610edf25c9..835dedf948 100644
--- a/lib/rubygems/spec_fetcher.rb
+++ b/lib/rubygems/spec_fetcher.rb
@@ -83,7 +83,7 @@ class Gem::SpecFetcher
#
# If +matching_platform+ is false, gems for all platforms are returned.
- def search_for_dependency(dependency, matching_platform=true)
+ def search_for_dependency(dependency, matching_platform = true)
found = {}
rejected_specs = {}
@@ -130,7 +130,7 @@ class Gem::SpecFetcher
##
# Return all gem name tuples who's names match +obj+
- def detect(type=:complete)
+ def detect(type = :complete)
tuples = []
list, _ = available_specs(type)
@@ -150,7 +150,7 @@ class Gem::SpecFetcher
#
# If +matching_platform+ is false, gems for all platforms are returned.
- def spec_for_dependency(dependency, matching_platform=true)
+ def spec_for_dependency(dependency, matching_platform = true)
tuples, errors = search_for_dependency(dependency, matching_platform)
specs = []
@@ -170,23 +170,55 @@ class Gem::SpecFetcher
# alternative gem names.
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)
+ gem_name = gem_name.downcase.tr("_-", "")
- matches = names.map do |n|
+ # All results for 3-character-or-shorter (minus hyphens/underscores) gem
+ # names get rejected, so we just return an empty array immediately instead.
+ return [] if gem_name.length <= 3
+
+ max = gem_name.size / 2
+ names = available_specs(type).first.values.flatten(1)
+
+ min_length = gem_name.length - max
+ max_length = gem_name.length + max
+
+ gem_name_with_postfix = "#{gem_name}ruby"
+ gem_name_with_prefix = "ruby#{gem_name}"
+
+ matches = names.filter_map do |n|
+ len = n.name.length
+ # If the gem doesn't support the current platform, bail early.
next unless n.match_platform?
- [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
+
+ # If the length is min_length or shorter, we've done `max` deletions.
+ # This would be rejected later, so we skip it for performance.
+ next if len <= min_length
+
+ # The candidate name, normalized the same as gem_name.
+ normalized_name = n.name.downcase
+ normalized_name.tr!("_-", "")
+
+ # If the gem is "{NAME}-ruby" and "ruby-{NAME}", we want to return it.
+ # But we already removed hyphens, so we check "{NAME}ruby" and "ruby{NAME}".
+ next [n.name, 0] if normalized_name == gem_name_with_postfix
+ next [n.name, 0] if normalized_name == gem_name_with_prefix
+
+ # If the length is max_length or longer, we've done `max` insertions.
+ # This would be rejected later, so we skip it for performance.
+ next if len >= max_length
+
+ # If we found an exact match (after stripping underscores and hyphens),
+ # that's our most likely candidate.
+ # Return it immediately, and skip the rest of the loop.
+ return [n.name] if normalized_name == gem_name
+
+ distance = levenshtein_distance gem_name, normalized_name
+
+ # Skip current candidate, if the edit distance is greater than allowed.
+ next if distance >= max
+
+ # If all else fails, return the name and the calculated distance.
+ [n.name, distance]
end
matches = if matches.empty? && type != :prerelease
@@ -248,7 +280,7 @@ class Gem::SpecFetcher
# Retrieves NameTuples from +source+ of the given +type+ (:prerelease,
# etc.). If +gracefully_ignore+ is true, errors are ignored.
- def tuples_for(source, type, gracefully_ignore=false) # :nodoc:
+ def tuples_for(source, type, gracefully_ignore = false) # :nodoc:
@caches[type][source.uri] ||=
source.load_specs(type).sort_by(&:name)
rescue Gem::RemoteFetcher::FetchError
diff --git a/lib/rubygems/specification.rb b/lib/rubygems/specification.rb
index da55a2e6d3..3d1f2dad91 100644
--- a/lib/rubygems/specification.rb
+++ b/lib/rubygems/specification.rb
@@ -7,12 +7,10 @@
# See LICENSE.txt for permissions.
#++
-require_relative "deprecate"
require_relative "basic_specification"
require_relative "stub_specification"
require_relative "platform"
require_relative "specification_record"
-require_relative "util/list"
require "rbconfig"
@@ -38,8 +36,6 @@ require "rbconfig"
# 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
# module. There's enough special stuff around it that it may justify
# a separate class.
@@ -175,7 +171,7 @@ class Gem::Specification < Gem::BasicSpecification
end
@@attributes = @@default_value.keys.sort_by(&:to_s)
- @@array_attributes = @@default_value.reject {|_k,v| v != [] }.keys
+ @@array_attributes = @@default_value.select {|_k,v| v.is_a?(Array) }.keys
@@nil_attributes, @@non_nil_attributes = @@default_value.keys.partition do |k|
@@default_value[k].nil?
end
@@ -391,7 +387,7 @@ class Gem::Specification < Gem::BasicSpecification
# "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"
+ # "wiki_uri" => "https://example.com/user/bestgemever/wiki",
# "funding_uri" => "https://example.com/donate"
# }
#
@@ -464,10 +460,7 @@ class Gem::Specification < Gem::BasicSpecification
# spec.platform = Gem::Platform.local
def platform=(platform)
- if @original_platform.nil? ||
- @original_platform == Gem::Platform::RUBY
- @original_platform = platform
- end
+ @original_platform = platform
case platform
when Gem::Platform::CURRENT then
@@ -491,8 +484,6 @@ class Gem::Specification < Gem::BasicSpecification
end
@platform = @new_platform.to_s
-
- invalidate_memoized_attributes
end
##
@@ -546,9 +537,9 @@ class Gem::Specification < Gem::BasicSpecification
#
# Usage:
#
- # spec.add_runtime_dependency 'example', '~> 1.1', '>= 1.1.4'
+ # spec.add_dependency 'example', '~> 1.1', '>= 1.1.4'
- def add_runtime_dependency(gem, *requirements)
+ def add_dependency(gem, *requirements)
if requirements.uniq.size != requirements.size
warn "WARNING: duplicated #{gem} dependency #{requirements}"
end
@@ -741,14 +732,6 @@ class Gem::Specification < Gem::BasicSpecification
attr_accessor :autorequire # :nodoc:
##
- # Sets the default executable for this gem.
- #
- # Deprecated: You must now specify the executable name to Gem.bin_path.
-
- attr_writer :default_executable
- rubygems_deprecate :default_executable=
-
- ##
# Allows deinstallation of gems with legacy platforms.
attr_writer :original_platform # :nodoc:
@@ -771,6 +754,11 @@ class Gem::Specification < Gem::BasicSpecification
end
private_class_method :clear_load_cache
+ def self.gem_path # :nodoc:
+ Gem.path
+ end
+ private_class_method :gem_path
+
def self.each_gemspec(dirs) # :nodoc:
dirs.each do |dir|
Gem::Util.glob_files_in_dir("*.gemspec", dir).each do |path|
@@ -832,7 +820,9 @@ class Gem::Specification < Gem::BasicSpecification
next versions if versions.nonzero?
platforms = Gem::Platform.sort_priority(b.platform) <=> Gem::Platform.sort_priority(a.platform)
next platforms if platforms.nonzero?
- b.base_dir == Gem.path.first ? 1 : -1
+ default_gem = a.default_gem_priority <=> b.default_gem_priority
+ next default_gem if default_gem.nonzero?
+ a.base_dir_priority(gem_path) <=> b.base_dir_priority(gem_path)
end
end
@@ -867,7 +857,7 @@ class Gem::Specification < Gem::BasicSpecification
# You probably want to use one of the Enumerable methods instead.
def self.all
- warn "NOTE: Specification.all called from #{caller.first}" unless
+ warn "NOTE: Specification.all called from #{caller(1, 1).first}" unless
Gem::Deprecate.skip
_all
end
@@ -908,7 +898,7 @@ class Gem::Specification < Gem::BasicSpecification
# Return the directories that Specification uses to find specs.
def self.dirs
- @@dirs ||= Gem::SpecificationRecord.dirs_from(Gem.path)
+ @@dirs ||= Gem::SpecificationRecord.dirs_from(gem_path)
end
##
@@ -998,7 +988,7 @@ class Gem::Specification < Gem::BasicSpecification
def self.find_in_unresolved_tree(path)
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)
+ if to_spec.has_conflicts? || to_spec.conflicts_when_loaded_with?(trail)
:next
else
return trail.reverse if to_spec.contains_requirable_file? path
@@ -1010,7 +1000,7 @@ class Gem::Specification < Gem::BasicSpecification
end
def self.unresolved_specs
- unresolved_deps.values.map(&:to_specs).flatten
+ unresolved_deps.values.flat_map(&:to_specs)
end
private_class_method :unresolved_specs
@@ -1069,7 +1059,7 @@ class Gem::Specification < Gem::BasicSpecification
result[spec.name] = spec
end
- result.map(&:last).flatten.sort_by(&:name)
+ result.flat_map(&:last).sort_by(&:name)
end
##
@@ -1195,21 +1185,30 @@ class Gem::Specification < Gem::BasicSpecification
Gem.pre_reset_hooks.each(&:call)
@specification_record = nil
clear_load_cache
- unresolved = unresolved_deps
- unless unresolved.empty?
- warn "WARN: Unresolved or ambiguous specs during Gem::Specification.reset:"
- unresolved.values.each do |dep|
- warn " #{dep}"
-
- versions = find_all_by_name(dep.name)
- unless versions.empty?
- warn " Available/installed versions of this gem:"
- versions.each {|s| warn " - #{s.version}" }
+
+ unless unresolved_deps.empty?
+ unresolved = unresolved_deps.filter_map do |name, dep|
+ matching_versions = find_all_by_name(name)
+ next if dep.latest_version? && matching_versions.any?(&:default_gem?)
+
+ [dep, matching_versions.uniq(&:full_name)]
+ end.to_h
+
+ unless unresolved.empty?
+ warn "WARN: Unresolved or ambiguous specs during Gem::Specification.reset:"
+ unresolved.each do |dep, versions|
+ warn " #{dep}"
+
+ unless versions.empty?
+ warn " Available/installed versions of this gem:"
+ versions.each {|s| warn " - #{s.version}" }
+ end
end
+ warn "WARN: Clearing out unresolved specs. Try 'gem cleanup <gem>'"
+ warn "Please report a bug if this causes problems."
end
- warn "WARN: Clearing out unresolved specs. Try 'gem cleanup <gem>'"
- warn "Please report a bug if this causes problems."
- unresolved.clear
+
+ unresolved_deps.clear
end
Gem.post_reset_hooks.each(&:call)
end
@@ -1301,17 +1300,15 @@ class Gem::Specification < Gem::BasicSpecification
spec.instance_variable_set :@summary, array[5]
spec.instance_variable_set :@required_ruby_version, array[6]
spec.instance_variable_set :@required_rubygems_version, array[7]
- spec.instance_variable_set :@original_platform, array[8]
+ spec.platform = array[8]
spec.instance_variable_set :@dependencies, array[9]
# offset due to rubyforge_project removal
spec.instance_variable_set :@email, array[11]
spec.instance_variable_set :@authors, array[12]
spec.instance_variable_set :@description, array[13]
spec.instance_variable_set :@homepage, array[14]
- spec.instance_variable_set :@has_rdoc, array[15]
- spec.instance_variable_set :@new_platform, array[16]
- spec.instance_variable_set :@platform, array[16].to_s
- spec.instance_variable_set :@license, array[17]
+ # offset due to has_rdoc removal
+ spec.instance_variable_set :@licenses, array[17]
spec.instance_variable_set :@metadata, array[18]
spec.instance_variable_set :@loaded, false
spec.instance_variable_set :@activated, false
@@ -1404,13 +1401,11 @@ class Gem::Specification < Gem::BasicSpecification
raise e
end
- begin
- specs = spec_dep.to_specs
- rescue Gem::MissingSpecError => e
- raise Gem::MissingSpecError.new(e.name, e.requirement, "at: #{spec_file}")
- end
+ specs = spec_dep.matching_specs(true).uniq(&:full_name)
- if specs.size == 1
+ if specs.size == 0
+ raise Gem::MissingSpecError.new(spec_dep.name, spec_dep.requirement, "at: #{spec_file}")
+ elsif specs.size == 1
specs.first.activate
else
name = spec_dep.name
@@ -1497,7 +1492,7 @@ class Gem::Specification < Gem::BasicSpecification
private :add_dependency_with_type
- alias_method :add_dependency, :add_runtime_dependency
+ alias_method :add_runtime_dependency, :add_dependency
##
# Adds this spec's require paths to LOAD_PATH, in the proper location.
@@ -1611,14 +1606,14 @@ class Gem::Specification < Gem::BasicSpecification
# spec's cached gem.
def cache_dir
- @cache_dir ||= File.join base_dir, "cache"
+ File.join base_dir, "cache"
end
##
# Returns the full path to the cached gem for this spec.
def cache_file
- @cache_file ||= File.join cache_dir, "#{full_name}.gem"
+ File.join cache_dir, "#{full_name}.gem"
end
##
@@ -1640,7 +1635,7 @@ class Gem::Specification < Gem::BasicSpecification
##
# return true if there will be conflict when spec if loaded together with the list of specs.
- def conficts_when_loaded_with?(list_of_specs) # :nodoc:
+ def conflicts_when_loaded_with?(list_of_specs) # :nodoc:
result = list_of_specs.any? do |spec|
spec.runtime_dependencies.any? {|dep| (dep.name == name) && !satisfies_requirement?(dep) }
end
@@ -1708,24 +1703,6 @@ class Gem::Specification < Gem::BasicSpecification
end
##
- # The default executable for this gem.
- #
- # Deprecated: The name of the gem is assumed to be the name of the
- # executable now. See Gem.bin_path.
-
- def default_executable # :nodoc:
- if defined?(@default_executable) && @default_executable
- result = @default_executable
- elsif @executables && @executables.size == 1
- result = Array(@executables).first
- else
- result = nil
- end
- result
- end
- rubygems_deprecate :default_executable
-
- ##
# The default value for specification attribute +name+
def default_value(name)
@@ -1748,7 +1725,7 @@ class Gem::Specification < Gem::BasicSpecification
#
# [depending_gem, dependency, [list_of_gems_that_satisfy_dependency]]
- def dependent_gems(check_dev=true)
+ def dependent_gems(check_dev = true)
out = []
Gem::Specification.each do |spec|
deps = check_dev ? spec.dependencies : spec.runtime_dependencies
@@ -1768,7 +1745,7 @@ class Gem::Specification < Gem::BasicSpecification
# Returns all specs that matches this spec's runtime dependencies.
def dependent_specs
- runtime_dependencies.map(&:to_specs).flatten
+ runtime_dependencies.flat_map(&:to_specs)
end
##
@@ -1806,15 +1783,8 @@ class Gem::Specification < Gem::BasicSpecification
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
- coder.add "platform", platform
+ coder.add "platform", platform.to_s
+ coder.add "original_platform", original_platform.to_s if platform.to_s != original_platform.to_s
attributes = @@attributes.map(&:to_s) - %w[name version platform]
attributes.each do |name|
@@ -1901,12 +1871,9 @@ class Gem::Specification < Gem::BasicSpecification
spec
end
- def full_name
- @full_name ||= super
- end
-
##
- # Work around bundler removing my methods
+ # Work around old bundler versions removing my methods
+ # Can be removed once RubyGems can no longer install Bundler 2.5
def gem_dir # :nodoc:
super
@@ -1917,29 +1884,6 @@ class Gem::Specification < Gem::BasicSpecification
end
##
- # Deprecated and ignored, defaults to true.
- #
- # Formerly used to indicate this gem was RDoc-capable.
-
- def has_rdoc # :nodoc:
- true
- end
- rubygems_deprecate :has_rdoc
-
- ##
- # Deprecated and ignored.
- #
- # Formerly used to indicate this gem was RDoc-capable.
-
- def has_rdoc=(ignored) # :nodoc:
- @has_rdoc = true
- end
- rubygems_deprecate :has_rdoc=
-
- alias_method :has_rdoc?, :has_rdoc # :nodoc:
- rubygems_deprecate :has_rdoc?
-
- ##
# True if this gem has files in test_files
def has_unit_tests? # :nodoc:
@@ -2041,17 +1985,6 @@ class Gem::Specification < Gem::BasicSpecification
end
end
- ##
- # Expire memoized instance variables that can incorrectly generate, replace
- # or miss files due changes in certain attributes used to compute them.
-
- def invalidate_memoized_attributes
- @full_name = nil
- @cache_file = nil
- end
-
- private :invalidate_memoized_attributes
-
def inspect # :nodoc:
if $DEBUG
super
@@ -2090,8 +2023,6 @@ class Gem::Specification < Gem::BasicSpecification
def internal_init # :nodoc:
super
@bin_dir = nil
- @cache_dir = nil
- @cache_file = nil
@doc_dir = nil
@ri_dir = nil
@spec_dir = nil
@@ -2141,11 +2072,11 @@ class Gem::Specification < Gem::BasicSpecification
@files.concat(@extra_rdoc_files)
end
- @files = @files.uniq if @files
- @extensions = @extensions.uniq if @extensions
- @test_files = @test_files.uniq if @test_files
- @executables = @executables.uniq if @executables
- @extra_rdoc_files = @extra_rdoc_files.uniq if @extra_rdoc_files
+ @files = @files.uniq.sort if @files
+ @extensions = @extensions.uniq.sort if @extensions
+ @test_files = @test_files.uniq.sort if @test_files
+ @executables = @executables.uniq.sort if @executables
+ @extra_rdoc_files = @extra_rdoc_files.uniq.sort if @extra_rdoc_files
end
##
@@ -2444,8 +2375,6 @@ class Gem::Specification < Gem::BasicSpecification
:required_rubygems_version,
:specification_version,
:version,
- :has_rdoc,
- :default_executable,
:metadata,
:signing_key,
]
@@ -2464,7 +2393,7 @@ class Gem::Specification < Gem::BasicSpecification
if @installed_by_version
result << nil
- result << " s.installed_by_version = #{ruby_code Gem::VERSION} if s.respond_to? :installed_by_version"
+ result << " s.installed_by_version = #{ruby_code Gem::VERSION}"
end
unless dependencies.empty?
@@ -2579,29 +2508,15 @@ class Gem::Specification < Gem::BasicSpecification
@test_files.delete_if {|x| File.directory?(x) && !File.symlink?(x) }
end
- def validate_metadata
- Gem::SpecificationPolicy.new(self).validate_metadata
+ def validate_for_resolution
+ Gem::SpecificationPolicy.new(self).validate_for_resolution
end
- rubygems_deprecate :validate_metadata
-
- def validate_dependencies
- Gem::SpecificationPolicy.new(self).validate_dependencies
- end
- rubygems_deprecate :validate_dependencies
-
- def validate_permissions
- Gem::SpecificationPolicy.new(self).validate_permissions
- end
- rubygems_deprecate :validate_permissions
##
# Set the version to +version+.
def version=(version)
- @version = Gem::Version.create(version)
- return if @version.nil?
-
- invalidate_memoized_attributes
+ @version = version.nil? ? version : Gem::Version.create(version)
end
def stubbed?
@@ -2614,13 +2529,12 @@ class Gem::Specification < Gem::BasicSpecification
when "date"
# Force Date to go through the extra coerce logic in date=
self.date = val
+ when "platform"
+ self.platform = val
else
instance_variable_set "@#{ivar}", val
end
end
-
- @original_platform = @platform # for backwards compatibility
- self.platform = Gem::Platform.new @platform
end
##
diff --git a/lib/rubygems/specification_policy.rb b/lib/rubygems/specification_policy.rb
index 812b0f889e..e5008a24db 100644
--- a/lib/rubygems/specification_policy.rb
+++ b/lib/rubygems/specification_policy.rb
@@ -45,6 +45,7 @@ class Gem::SpecificationPolicy
def validate(strict = false)
validate_required!
+ validate_required_metadata!
validate_optional(strict) if packaging || strict
@@ -85,15 +86,17 @@ class Gem::SpecificationPolicy
validate_authors_field
- validate_metadata
-
validate_licenses_length
- validate_lazy_metadata
-
validate_duplicate_dependencies
end
+ def validate_required_metadata!
+ validate_metadata
+
+ validate_lazy_metadata
+ end
+
def validate_optional(strict)
validate_licenses
@@ -121,6 +124,13 @@ class Gem::SpecificationPolicy
end
##
+ # Implementation for Specification#validate_for_resolution
+
+ def validate_for_resolution
+ validate_required!
+ end
+
+ ##
# Implementation for Specification#validate_metadata
def validate_metadata
@@ -180,9 +190,6 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
##
# Checks that the gem does not depend on itself.
- # 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 = []
@@ -190,39 +197,6 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
if dep.name == @specification.name # warn on self reference
warning_messages << "Self referencing dependency is unnecessary and strongly discouraged."
end
-
- prerelease_dep = dep.requirements_list.any? do |req|
- Gem::Requirement.new(req).prerelease?
- end
-
- warning_messages << "prerelease dependency on #{dep} is not recommended" if
- prerelease_dep && !@specification.version.prerelease?
-
- open_ended = dep.requirement.requirements.all? do |op, version|
- !version.prerelease? && [">", ">="].include?(op)
- end
-
- next unless open_ended
- op, dep_version = dep.requirement.requirements.first
-
- segments = dep_version.segments
-
- base = segments.first 2
-
- recommendation = if [">", ">="].include?(op) && segments == [0]
- " use a bounded requirement, such as \"~> x.y\""
- else
- bugfix = if op == ">"
- ", \"> #{dep_version}\""
- elsif op == ">=" && 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
if warning_messages.any?
warning_messages.each {|warning_message| warning warning_message }
@@ -297,7 +271,7 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
elsif !VALID_NAME_PATTERN.match?(name)
error "invalid value for attribute name: #{name.dump} can only include letters, numbers, dashes, and underscores"
elsif SPECIAL_CHARACTERS.match?(name)
- error "invalid value for attribute name: #{name.dump} can not begin with a period, dash, or underscore"
+ error "invalid value for attribute name: #{name.dump} cannot begin with a period, dash, or underscore"
end
end
diff --git a/lib/rubygems/specification_record.rb b/lib/rubygems/specification_record.rb
index 664d506265..d08410096f 100644
--- a/lib/rubygems/specification_record.rb
+++ b/lib/rubygems/specification_record.rb
@@ -30,7 +30,7 @@ module Gem
# Returns the list of all specifications in the record
def all
- @all ||= Gem.loaded_specs.values | stubs.map(&:to_spec)
+ @all ||= stubs.map(&:to_spec)
end
##
@@ -73,7 +73,7 @@ module Gem
end
##
- # Adds +spec+ to the the record, keeping the collection properly sorted.
+ # Adds +spec+ to the record, keeping the collection properly sorted.
def add_spec(spec)
return if all.include? spec
diff --git a/lib/rubygems/ssl_certs/rubygems.org/GlobalSignRootCA_R3.pem b/lib/rubygems/ssl_certs/rubygems.org/GlobalSign.pem
index 8afb219058..8afb219058 100644
--- a/lib/rubygems/ssl_certs/rubygems.org/GlobalSignRootCA_R3.pem
+++ b/lib/rubygems/ssl_certs/rubygems.org/GlobalSign.pem
diff --git a/lib/rubygems/ssl_certs/rubygems.org/GlobalSignRootCA.pem b/lib/rubygems/ssl_certs/rubygems.org/GlobalSignRootCA.pem
deleted file mode 100644
index f4ce4ca43d..0000000000
--- a/lib/rubygems/ssl_certs/rubygems.org/GlobalSignRootCA.pem
+++ /dev/null
@@ -1,21 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
-A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
-b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
-MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
-YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
-aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
-jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
-xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
-1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
-snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
-U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
-9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
-BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
-AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
-yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
-38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
-AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
-DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
-HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
------END CERTIFICATE-----
diff --git a/lib/rubygems/stub_specification.rb b/lib/rubygems/stub_specification.rb
index ea66fbc3f6..4f6a70ba4b 100644
--- a/lib/rubygems/stub_specification.rb
+++ b/lib/rubygems/stub_specification.rb
@@ -83,11 +83,7 @@ class Gem::StubSpecification < Gem::BasicSpecification
# True when this gem has been activated
def activated?
- @activated ||=
- begin
- loaded = Gem.loaded_specs[name]
- loaded && loaded.version == version
- end
+ @activated ||= !loaded_spec.nil?
end
def default_gem?
@@ -187,11 +183,7 @@ class Gem::StubSpecification < Gem::BasicSpecification
# The full Gem::Specification for this gem, loaded from evalling its gemspec
def spec
- @spec ||= if @data
- loaded = Gem.loaded_specs[name]
- loaded if loaded && loaded.version == version
- end
-
+ @spec ||= loaded_spec if @data
@spec ||= Gem::Specification.load(loaded_from)
end
alias_method :to_spec, :spec
@@ -231,4 +223,13 @@ class Gem::StubSpecification < Gem::BasicSpecification
def sort_obj # :nodoc:
[name, version, Gem::Platform.sort_priority(platform)]
end
+
+ private
+
+ def loaded_spec
+ spec = Gem.loaded_specs[name]
+ return unless spec && spec.version == version && spec.default_gem? == default_gem?
+
+ spec
+ end
end
diff --git a/lib/rubygems/target_rbconfig.rb b/lib/rubygems/target_rbconfig.rb
new file mode 100644
index 0000000000..21d90ee9db
--- /dev/null
+++ b/lib/rubygems/target_rbconfig.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require "rbconfig"
+
+##
+# A TargetConfig is a wrapper around an RbConfig object that provides a
+# consistent interface for querying configuration for *deployment target
+# platform*, where the gem being installed is intended to run on.
+#
+# The TargetConfig is typically created from the RbConfig of the running Ruby
+# process, but can also be created from an RbConfig file on disk for cross-
+# compiling gems.
+
+class Gem::TargetRbConfig
+ attr_reader :path
+
+ def initialize(rbconfig, path)
+ @rbconfig = rbconfig
+ @path = path
+ end
+
+ ##
+ # Creates a TargetRbConfig for the platform that RubyGems is running on.
+
+ def self.for_running_ruby
+ new(::RbConfig, nil)
+ end
+
+ ##
+ # Creates a TargetRbConfig from the RbConfig file at the given path.
+ # Typically used for cross-compiling gems.
+
+ def self.from_path(rbconfig_path)
+ namespace = Module.new do |m|
+ # Load the rbconfig.rb file within a new anonymous module to avoid
+ # conflicts with the rbconfig for the running platform.
+ Kernel.load rbconfig_path, m
+ end
+ rbconfig = namespace.const_get(:RbConfig)
+
+ new(rbconfig, rbconfig_path)
+ end
+
+ ##
+ # Queries the configuration for the given key.
+
+ def [](key)
+ @rbconfig::CONFIG[key]
+ end
+end
diff --git a/lib/rubygems/text.rb b/lib/rubygems/text.rb
index da0795b771..88d4ce59b4 100644
--- a/lib/rubygems/text.rb
+++ b/lib/rubygems/text.rb
@@ -21,7 +21,7 @@ module Gem::Text
# Wraps +text+ to +wrap+ characters and optionally indents by +indent+
# characters
- def format_text(text, wrap, indent=0)
+ def format_text(text, wrap, indent = 0)
result = []
work = clean_text(text)
diff --git a/lib/rubygems/uninstaller.rb b/lib/rubygems/uninstaller.rb
index 23791313c8..fe4c3a80cf 100644
--- a/lib/rubygems/uninstaller.rb
+++ b/lib/rubygems/uninstaller.rb
@@ -10,7 +10,6 @@ require "fileutils"
require_relative "../rubygems"
require_relative "installer_uninstaller_utils"
require_relative "dependency_list"
-require_relative "rdoc"
require_relative "user_interaction"
##
@@ -43,10 +42,25 @@ class Gem::Uninstaller
attr_reader :spec
##
- # Constructs an uninstaller that will uninstall +gem+
+ # Constructs an uninstaller that will uninstall gem named +gem+.
+ # +options+ is a Hash with the following keys:
+ #
+ # :version:: Version requirement for the gem to uninstall. If not specified,
+ # uses Gem::Requirement.default.
+ # :install_dir:: The directory where the gem is installed. If not specified,
+ # uses Gem.dir.
+ # :executables:: Whether executables should be removed without confirmation or not. If nil, asks the user explicitly.
+ # :all:: If more than one version matches the requirement, whether to forcefully remove all matching versions or ask the user to select specific matching versions that should be removed.
+ # :ignore:: Ignore broken dependency checks when uninstalling.
+ # :bin_dir:: Directory containing executables to remove. If not specified,
+ # uses Gem.bindir.
+ # :format_executable:: In order to find executables to be removed, format executable names using Gem::Installer.exec_format.
+ # :abort_on_dependent:: Directly abort uninstallation if dependencies would be broken, rather than asking the user for confirmation.
+ # :check_dev:: When checking if uninstalling gem would leave broken dependencies around, also consider development dependencies.
+ # :force:: Set both :all and :ignore to true for forced uninstallation.
+ # :user_install:: Uninstall from user gem directory instead of system directory.
def initialize(gem, options = {})
- # TODO: document the valid options
@gem = gem
@version = options[:version] || Gem::Requirement.default
@install_dir = options[:install_dir]
@@ -58,10 +72,6 @@ class Gem::Uninstaller
@bin_dir = options[:bin_dir]
@format_executable = options[:format_executable]
@abort_on_dependent = options[:abort_on_dependent]
-
- # Indicate if development dependencies should be checked when
- # uninstalling. (default: false)
- #
@check_dev = options[:check_dev]
if options[:force]
@@ -178,7 +188,7 @@ class Gem::Uninstaller
# Removes installed executables and batch files (windows only) for +spec+.
def remove_executables(spec)
- return if spec.executables.empty?
+ return if spec.executables.empty? || default_spec_matches?(spec)
executables = spec.executables.clone
@@ -251,7 +261,15 @@ class Gem::Uninstaller
raise Gem::FilePermissionError, spec.base_dir unless
File.writable?(spec.base_dir)
- safe_delete { FileUtils.rm_r spec.full_gem_path }
+ full_gem_path = spec.full_gem_path
+ exclusions = []
+
+ if default_spec_matches?(spec) && spec.executables.any?
+ exclusions = spec.executables.map {|exe| File.join(spec.bin_dir, exe) }
+ exclusions << File.dirname(exclusions.last) until exclusions.last == full_gem_path
+ end
+
+ safe_delete { rm_r full_gem_path, exclusions: exclusions }
safe_delete { FileUtils.rm_r spec.extension_dir }
old_platform_name = spec.original_name
@@ -378,6 +396,12 @@ class Gem::Uninstaller
private
+ def rm_r(path, exclusions:)
+ FileUtils::Entry_.new(path).postorder_traverse do |ent|
+ ent.remove unless exclusions.include?(ent.path)
+ end
+ end
+
def specification_record
@specification_record ||= @install_dir ? Gem::SpecificationRecord.from_path(@install_dir) : Gem::Specification.specification_record
end
diff --git a/lib/rubygems/uri.rb b/lib/rubygems/uri.rb
index a44aaceba5..d729c67d26 100644
--- a/lib/rubygems/uri.rb
+++ b/lib/rubygems/uri.rb
@@ -30,7 +30,7 @@ class Gem::Uri
begin
Gem::URI.parse(uri)
rescue Gem::URI::InvalidURIError
- Gem::URI.parse(Gem::URI::DEFAULT_PARSER.escape(uri))
+ Gem::URI.parse(Gem::URI::RFC2396_PARSER.escape(uri))
end
end
diff --git a/lib/rubygems/uri_formatter.rb b/lib/rubygems/uri_formatter.rb
index 517ce33637..8856fdadd2 100644
--- a/lib/rubygems/uri_formatter.rb
+++ b/lib/rubygems/uri_formatter.rb
@@ -17,7 +17,8 @@ class Gem::UriFormatter
# Creates a new URI formatter for +uri+.
def initialize(uri)
- require "cgi"
+ require "cgi/escape"
+ require "cgi/util" unless defined?(CGI::EscapeExt)
@uri = uri
end
diff --git a/lib/rubygems/user_interaction.rb b/lib/rubygems/user_interaction.rb
index 0172c4ee89..9fe3e755c4 100644
--- a/lib/rubygems/user_interaction.rb
+++ b/lib/rubygems/user_interaction.rb
@@ -6,7 +6,6 @@
# See LICENSE.txt for permissions.
#++
-require_relative "deprecate"
require_relative "text"
##
@@ -170,8 +169,6 @@ end
# Gem::StreamUI implements a simple stream based user interface.
class Gem::StreamUI
- extend Gem::Deprecate
-
##
# The input stream
@@ -193,7 +190,7 @@ class Gem::StreamUI
# then special operations (like asking for passwords) will use the TTY
# commands to disable character echo.
- def initialize(in_stream, out_stream, err_stream=$stderr, usetty=true)
+ def initialize(in_stream, out_stream, err_stream = $stderr, usetty = true)
@ins = in_stream
@outs = out_stream
@errs = err_stream
@@ -246,7 +243,7 @@ class Gem::StreamUI
# to a tty, raises an exception if default is nil, otherwise returns
# default.
- def ask_yes_no(question, default=nil)
+ def ask_yes_no(question, default = nil)
unless tty?
if default.nil?
raise Gem::OperationNotSupportedError,
@@ -325,14 +322,14 @@ class Gem::StreamUI
##
# Display a statement.
- def say(statement="")
+ def say(statement = "")
@outs.puts statement
end
##
# Display an informational alert. Will ask +question+ if it is not nil.
- def alert(statement, question=nil)
+ def alert(statement, question = nil)
@outs.puts "INFO: #{statement}"
ask(question) if question
end
@@ -340,7 +337,7 @@ class Gem::StreamUI
##
# Display a warning on stderr. Will ask +question+ if it is not nil.
- def alert_warning(statement, question=nil)
+ def alert_warning(statement, question = nil)
@errs.puts "WARNING: #{statement}"
ask(question) if question
end
@@ -349,7 +346,7 @@ class Gem::StreamUI
# Display an error message in a location expected to get error messages.
# Will ask +question+ if it is not nil.
- def alert_error(statement, question=nil)
+ def alert_error(statement, question = nil)
@errs.puts "ERROR: #{statement}"
ask(question) if question
end
diff --git a/lib/rubygems/util.rb b/lib/rubygems/util.rb
index 51f9c2029f..ee4106c6ce 100644
--- a/lib/rubygems/util.rb
+++ b/lib/rubygems/util.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-require_relative "deprecate"
-
##
# This module contains various utility methods as module methods.
@@ -57,26 +55,6 @@ module Gem::Util
end
##
- # Invokes system, but silences all output.
-
- def self.silent_system(*command)
- opt = { out: IO::NULL, err: [:child, :out] }
- if Hash === command.last
- opt.update(command.last)
- cmds = command[0...-1]
- else
- cmds = command.dup
- end
- system(*(cmds << opt))
- end
-
- class << self
- extend Gem::Deprecate
-
- rubygems_deprecate :silent_system
- end
-
- ##
# Enumerates the parents of +directory+.
def self.traverse_parents(directory, &block)
diff --git a/lib/rubygems/util/atomic_file_writer.rb b/lib/rubygems/util/atomic_file_writer.rb
new file mode 100644
index 0000000000..32767c6a79
--- /dev/null
+++ b/lib/rubygems/util/atomic_file_writer.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+# Based on ActiveSupport's AtomicFile implementation
+# Copyright (c) David Heinemeier Hansson
+# https://github.com/rails/rails/blob/main/activesupport/lib/active_support/core_ext/file/atomic.rb
+# Licensed under the MIT License
+
+module Gem
+ class AtomicFileWriter
+ ##
+ # Write to a file atomically. Useful for situations where you don't
+ # want other processes or threads to see half-written files.
+
+ def self.open(file_name)
+ require "securerandom" unless defined?(SecureRandom)
+
+ old_stat = begin
+ File.stat(file_name)
+ rescue SystemCallError
+ nil
+ end
+
+ # Names can't be longer than 255B
+ tmp_suffix = ".tmp.#{SecureRandom.hex}"
+ dirname = File.dirname(file_name)
+ basename = File.basename(file_name)
+ tmp_path = File.join(dirname, ".#{basename.byteslice(0, 254 - tmp_suffix.bytesize)}#{tmp_suffix}")
+
+ flags = File::RDWR | File::CREAT | File::EXCL | File::BINARY
+ flags |= File::SHARE_DELETE if defined?(File::SHARE_DELETE)
+
+ File.open(tmp_path, flags) do |temp_file|
+ temp_file.binmode
+ if old_stat
+ # Set correct permissions on new file
+ begin
+ File.chown(old_stat.uid, old_stat.gid, temp_file.path)
+ # This operation will affect filesystem ACL's
+ File.chmod(old_stat.mode, temp_file.path)
+ rescue Errno::EPERM, Errno::EACCES
+ # Changing file ownership failed, moving on.
+ end
+ end
+
+ return_val = yield temp_file
+ rescue StandardError => error
+ begin
+ temp_file.close
+ rescue StandardError
+ nil
+ end
+
+ begin
+ File.unlink(temp_file.path)
+ rescue StandardError
+ nil
+ end
+
+ raise error
+ else
+ begin
+ File.rename(temp_file.path, file_name)
+ rescue StandardError
+ begin
+ File.unlink(temp_file.path)
+ rescue StandardError
+ end
+
+ raise
+ end
+
+ return_val
+ end
+ end
+ end
+end
diff --git a/lib/rubygems/util/licenses.rb b/lib/rubygems/util/licenses.rb
index 192ae30b9b..fbb7b55075 100644
--- a/lib/rubygems/util/licenses.rb
+++ b/lib/rubygems/util/licenses.rb
@@ -59,12 +59,15 @@ class Gem::Licenses
Artistic-1.0-Perl
Artistic-1.0-cl8
Artistic-2.0
+ Artistic-dist
+ Aspell-RU
BSD-1-Clause
BSD-2-Clause
BSD-2-Clause-Darwin
BSD-2-Clause-Patent
BSD-2-Clause-Views
BSD-2-Clause-first-lines
+ BSD-2-Clause-pkgconf-disclaimer
BSD-3-Clause
BSD-3-Clause-Attribution
BSD-3-Clause-Clear
@@ -104,6 +107,7 @@ class Gem::Licenses
Bitstream-Vera
BlueOak-1.0.0
Boehm-GC
+ Boehm-GC-without-fee
Borceux
Brian-Gladman-2-Clause
Brian-Gladman-3-Clause
@@ -163,6 +167,8 @@ class Gem::Licenses
CC-BY-SA-3.0-IGO
CC-BY-SA-4.0
CC-PDDC
+ CC-PDM-1.0
+ CC-SA-1.0
CC0-1.0
CDDL-1.0
CDDL-1.1
@@ -202,6 +208,7 @@ class Gem::Licenses
Cornell-Lossless-JPEG
Cronyx
Crossword
+ CryptoSwift
CrystalStacker
Cube
D-FSL-1.0
@@ -212,6 +219,10 @@ class Gem::Licenses
DRL-1.0
DRL-1.1
DSDP
+ DocBook-DTD
+ DocBook-Schema
+ DocBook-Stylesheet
+ DocBook-XML
Dotseqn
ECL-1.0
ECL-2.0
@@ -234,7 +245,10 @@ class Gem::Licenses
FSFAP-no-warranty-disclaimer
FSFUL
FSFULLR
+ FSFULLRSD
FSFULLRWD
+ FSL-1.1-ALv2
+ FSL-1.1-MIT
FTL
Fair
Ferguson-Twofish
@@ -270,11 +284,14 @@ class Gem::Licenses
GPL-2.0-or-later
GPL-3.0-only
GPL-3.0-or-later
+ Game-Programming-Gems
Giftware
Glide
Glulxe
Graphics-Gems
Gutmann
+ HDF5
+ HIDAPI
HP-1986
HP-1989
HPND
@@ -285,6 +302,7 @@ class Gem::Licenses
HPND-Kevlin-Henney
HPND-MIT-disclaimer
HPND-Markus-Kuhn
+ HPND-Netrek
HPND-Pbmplus
HPND-UC
HPND-UC-export-US
@@ -316,6 +334,7 @@ class Gem::Licenses
Imlib2
Info-ZIP
Inner-Net-2.0
+ InnoSetup
Intel
Intel-ACPI
Interbase-1.0
@@ -360,9 +379,11 @@ class Gem::Licenses
Linux-man-pages-copyleft-2-para
Linux-man-pages-copyleft-var
Lucida-Bitmap-Fonts
+ MIPS
MIT
MIT-0
MIT-CMU
+ MIT-Click
MIT-Festival
MIT-Khronos-old
MIT-Modern-Variant
@@ -415,10 +436,10 @@ class Gem::Licenses
NPL-1.1
NPOSL-3.0
NRL
+ NTIA-PD
NTP
NTP-0
Naumen
- Net-SNMP
NetCDF
Newsletr
Nokia
@@ -500,6 +521,7 @@ class Gem::Licenses
RSCPL
Rdisc
Ruby
+ Ruby-pty
SAX-PD
SAX-PD-2.0
SCEA
@@ -513,19 +535,23 @@ class Gem::Licenses
SISSL
SISSL-1.2
SL
+ SMAIL-GPL
SMLNJ
SMPPL
SNIA
+ SOFA
SPL-1.0
SSH-OpenSSH
SSH-short
SSLeay-standalone
SSPL-1.0
+ SUL-1.0
SWL
Saxpath
SchemeReport
Sendmail
Sendmail-8.23
+ Sendmail-Open-Source-1.1
SimPL-2.0
Sleepycat
Soundex
@@ -551,17 +577,22 @@ class Gem::Licenses
TU-Berlin-1.0
TU-Berlin-2.0
TermReadKey
+ ThirdEye
+ TrustedQSL
UCAR
UCL-1.0
UMich-Merit
UPL-1.0
URT-RLE
+ Ubuntu-font-1.0
Unicode-3.0
Unicode-DFS-2015
Unicode-DFS-2016
Unicode-TOU
UnixCrypt
Unlicense
+ Unlicense-libtelnet
+ Unlicense-libwhirlpool
VOSTROM
VSL-1.0
Vim
@@ -574,6 +605,7 @@ class Gem::Licenses
Wsuipa
X11
X11-distribute-modifications-variant
+ X11-swapped
XFree86-1.1
XSkat
Xdebug-1.03
@@ -592,6 +624,7 @@ class Gem::Licenses
Zimbra-1.4
Zlib
any-OSI
+ any-OSI-perl-modules
bcrypt-Solar-Designer
blessing
bzip2-1.0.6
@@ -608,10 +641,13 @@ class Gem::Licenses
etalab-2.0
fwlw
gSOAP-1.3b
+ generic-xts
gnuplot
gtkbook
hdparm
iMatix
+ jove
+ libpng-1.6.35
libpng-2.0
libselinux-1.0
libtiff
@@ -619,10 +655,12 @@ class Gem::Licenses
lsof
magaz
mailprio
+ man2html
metamail
mpi-permissive
mpich2
mplus
+ ngrep
pkgconf
pnmstitch
psfrag
@@ -636,6 +674,7 @@ class Gem::Licenses
threeparttable
ulem
w3m
+ wwl
xinetd
xkeyboard-config-Zinoviev
xlock
@@ -671,6 +710,7 @@ class Gem::Licenses
LGPL-2.1+
LGPL-3.0
LGPL-3.0+
+ Net-SNMP
Nunit
StandardML-NJ
bzip2-1.0.5
@@ -691,9 +731,11 @@ class Gem::Licenses
Bison-exception-1.24
Bison-exception-2.2
Bootloader-exception
+ CGAL-linking-exception
CLISP-exception-2.0
Classpath-exception-2.0
DigiRule-FOSS-exception
+ Digia-Qt-LGPL-exception-1.1
FLTK-exception
Fawkes-Runtime-exception
Font-exception-2.0
@@ -703,6 +745,7 @@ class Gem::Licenses
GNAT-exception
GNOME-examples-exception
GNU-compiler-exception
+ GPL-3.0-389-ds-base-exception
GPL-3.0-interface-exception
GPL-3.0-linking-exception
GPL-3.0-linking-source-exception
@@ -710,6 +753,7 @@ class Gem::Licenses
GStreamer-exception-2005
GStreamer-exception-2008
Gmsh-exception
+ Independent-modules-exception
KiCad-libraries-exception
LGPL-3.0-linking-exception
LLGPL
@@ -738,13 +782,18 @@ class Gem::Licenses
WxWindows-exception-3.1
cryptsetup-OpenSSL-exception
eCos-exception-2.0
+ erlang-otp-linking-exception
fmt-exception
freertos-exception-2.0
gnu-javamail-exception
+ harbour-exception
i2p-gpl-java-exception
libpri-OpenH323-exception
mif-exception
+ mxml-exception
openvpn-openssl-exception
+ polyparse-exception
+ romic-exception
stunnel-exception
u-boot-exception-2.0
vsftpd-openssl-exception
diff --git a/lib/rubygems/util/list.rb b/lib/rubygems/util/list.rb
deleted file mode 100644
index 2899e8a2b9..0000000000
--- a/lib/rubygems/util/list.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-module Gem
- # The Gem::List class is currently unused and will be removed in the next major rubygems version
- class List # :nodoc:
- include Enumerable
- attr_accessor :value, :tail
-
- def initialize(value = nil, tail = nil)
- @value = value
- @tail = tail
- end
-
- def each
- n = self
- while n
- yield n.value
- n = n.tail
- end
- end
-
- def to_a
- super.reverse
- end
-
- def prepend(value)
- List.new value, self
- end
-
- def pretty_print(q) # :nodoc:
- q.pp to_a
- end
-
- def self.prepend(list, value)
- return List.new(value) unless list
- List.new value, list
- end
- end
- deprecate_constant :List
-end
diff --git a/lib/rubygems/validator.rb b/lib/rubygems/validator.rb
index 57e0747eb4..eb5b513570 100644
--- a/lib/rubygems/validator.rb
+++ b/lib/rubygems/validator.rb
@@ -59,7 +59,7 @@ class Gem::Validator
#--
# TODO needs further cleanup
- def alien(gems=[])
+ def alien(gems = [])
errors = Hash.new {|h,k| h[k] = {} }
Gem::Specification.each do |spec|
diff --git a/lib/bundler/vendor/connection_pool/.document b/lib/rubygems/vendor/.document
index 0c43bbd6b3..0c43bbd6b3 100644
--- a/lib/bundler/vendor/connection_pool/.document
+++ b/lib/rubygems/vendor/.document
diff --git a/lib/rubygems/vendor/molinillo/.document b/lib/rubygems/vendor/molinillo/.document
deleted file mode 100644
index 0c43bbd6b3..0000000000
--- a/lib/rubygems/vendor/molinillo/.document
+++ /dev/null
@@ -1 +0,0 @@
-# Vendored files do not need to be documented
diff --git a/lib/rubygems/vendor/net-http/.document b/lib/rubygems/vendor/net-http/.document
deleted file mode 100644
index 0c43bbd6b3..0000000000
--- a/lib/rubygems/vendor/net-http/.document
+++ /dev/null
@@ -1 +0,0 @@
-# Vendored files do not need to be documented
diff --git a/lib/rubygems/vendor/net-http/lib/net/http.rb b/lib/rubygems/vendor/net-http/lib/net/http.rb
index 7b15c3cf54..4800cd25f1 100644
--- a/lib/rubygems/vendor/net-http/lib/net/http.rb
+++ b/lib/rubygems/vendor/net-http/lib/net/http.rb
@@ -46,7 +46,7 @@ module Gem::Net #:nodoc:
# == Strategies
#
# - If you will make only a few GET requests,
- # consider using {OpenURI}[rdoc-ref:OpenURI].
+ # consider using {OpenURI}[https://docs.ruby-lang.org/en/master/OpenURI.html].
# - If you will make only a few requests of all kinds,
# consider using the various singleton convenience methods in this class.
# Each of the following methods automatically starts and finishes
@@ -67,6 +67,8 @@ module Gem::Net #:nodoc:
# Gem::Net::HTTP.post(uri, data)
# params = {title: 'foo', body: 'bar', userId: 1}
# Gem::Net::HTTP.post_form(uri, params)
+ # data = '{"title": "foo", "body": "bar", "userId": 1}'
+ # Gem::Net::HTTP.put(uri, data)
#
# - If performance is important, consider using sessions, which lower request overhead.
# This {session}[rdoc-ref:Gem::Net::HTTP@Sessions] has multiple requests for
@@ -100,14 +102,14 @@ module Gem::Net #:nodoc:
#
# == URIs
#
- # On the internet, a URI
+ # On the internet, a Gem::URI
# ({Universal Resource Identifier}[https://en.wikipedia.org/wiki/Uniform_Resource_Identifier])
# is a string that identifies a particular resource.
# It consists of some or all of: scheme, hostname, path, query, and fragment;
- # see {URI syntax}[https://en.wikipedia.org/wiki/Uniform_Resource_Identifier#Syntax].
+ # see {Gem::URI syntax}[https://en.wikipedia.org/wiki/Uniform_Resource_Identifier#Syntax].
#
- # A Ruby {Gem::URI::Generic}[rdoc-ref:Gem::URI::Generic] object
- # represents an internet URI.
+ # A Ruby {Gem::URI::Generic}[https://docs.ruby-lang.org/en/master/Gem::URI/Generic.html] object
+ # represents an internet Gem::URI.
# It provides, among others, methods
# +scheme+, +hostname+, +path+, +query+, and +fragment+.
#
@@ -142,7 +144,7 @@ module Gem::Net #:nodoc:
#
# === Queries
#
- # A host-specific query adds name/value pairs to the URI:
+ # A host-specific query adds name/value pairs to the Gem::URI:
#
# _uri = uri.dup
# params = {userId: 1, completed: false}
@@ -152,7 +154,7 @@ module Gem::Net #:nodoc:
#
# === Fragments
#
- # A {URI fragment}[https://en.wikipedia.org/wiki/URI_fragment] has no effect
+ # A {Gem::URI fragment}[https://en.wikipedia.org/wiki/URI_fragment] has no effect
# in \Gem::Net::HTTP;
# the same data is returned, regardless of whether a fragment is included.
#
@@ -325,9 +327,9 @@ module Gem::Net #:nodoc:
# res = http.request(req)
# end
#
- # Or if you simply want to make a GET request, you may pass in a URI
+ # Or if you simply want to make a GET request, you may pass in a Gem::URI
# object that has an \HTTPS URL. \Gem::Net::HTTP automatically turns on TLS
- # verification if the URI object has a 'https' :URI scheme:
+ # verification if the Gem::URI object has a 'https' Gem::URI scheme:
#
# uri # => #<Gem::URI::HTTPS https://jsonplaceholder.typicode.com/>
# Gem::Net::HTTP.get(uri)
@@ -372,7 +374,7 @@ module Gem::Net #:nodoc:
#
# When environment variable <tt>'http_proxy'</tt>
# is set to a \Gem::URI string,
- # the returned +http+ will have the server at that URI as its proxy;
+ # the returned +http+ will have the server at that Gem::URI as its proxy;
# note that the \Gem::URI string must have a protocol
# such as <tt>'http'</tt> or <tt>'https'</tt>:
#
@@ -456,6 +458,10 @@ module Gem::Net #:nodoc:
#
# == What's Here
#
+ # First, what's elsewhere. Class Gem::Net::HTTP:
+ #
+ # - Inherits from {class Object}[https://docs.ruby-lang.org/en/master/Object.html#class-Object-label-What-27s+Here].
+ #
# This is a categorized summary of methods and attributes.
#
# === \Gem::Net::HTTP Objects
@@ -469,8 +475,7 @@ module Gem::Net #:nodoc:
#
# - {::start}[rdoc-ref:Gem::Net::HTTP.start]:
# Begins a new session in a new \Gem::Net::HTTP object.
- # - {#started?}[rdoc-ref:Gem::Net::HTTP#started?]
- # (aliased as {#active?}[rdoc-ref:Gem::Net::HTTP#active?]):
+ # - {#started?}[rdoc-ref:Gem::Net::HTTP#started?]:
# Returns whether in a session.
# - {#finish}[rdoc-ref:Gem::Net::HTTP#finish]:
# Ends an active session.
@@ -520,6 +525,8 @@ module Gem::Net #:nodoc:
# Sends a POST request with form data and returns a response object.
# - {::post}[rdoc-ref:Gem::Net::HTTP.post]:
# Sends a POST request with data and returns a response object.
+ # - {::put}[rdoc-ref:Gem::Net::HTTP.put]:
+ # Sends a PUT request with data and returns a response object.
# - {#copy}[rdoc-ref:Gem::Net::HTTP#copy]:
# Sends a COPY request and returns a response object.
# - {#delete}[rdoc-ref:Gem::Net::HTTP#delete]:
@@ -548,18 +555,15 @@ module Gem::Net #:nodoc:
# Sends a PUT request and returns a response object.
# - {#request}[rdoc-ref:Gem::Net::HTTP#request]:
# Sends a request and returns a response object.
- # - {#request_get}[rdoc-ref:Gem::Net::HTTP#request_get]
- # (aliased as {#get2}[rdoc-ref:Gem::Net::HTTP#get2]):
+ # - {#request_get}[rdoc-ref:Gem::Net::HTTP#request_get]:
# Sends a GET request and forms a response object;
# if a block given, calls the block with the object,
# otherwise returns the object.
- # - {#request_head}[rdoc-ref:Gem::Net::HTTP#request_head]
- # (aliased as {#head2}[rdoc-ref:Gem::Net::HTTP#head2]):
+ # - {#request_head}[rdoc-ref:Gem::Net::HTTP#request_head]:
# Sends a HEAD request and forms a response object;
# if a block given, calls the block with the object,
# otherwise returns the object.
- # - {#request_post}[rdoc-ref:Gem::Net::HTTP#request_post]
- # (aliased as {#post2}[rdoc-ref:Gem::Net::HTTP#post2]):
+ # - {#request_post}[rdoc-ref:Gem::Net::HTTP#request_post]:
# Sends a POST request and forms a response object;
# if a block given, calls the block with the object,
# otherwise returns the object.
@@ -597,8 +601,7 @@ module Gem::Net #:nodoc:
# Returns whether +self+ is a proxy class.
# - {#proxy?}[rdoc-ref:Gem::Net::HTTP#proxy?]:
# Returns whether +self+ has a proxy.
- # - {#proxy_address}[rdoc-ref:Gem::Net::HTTP#proxy_address]
- # (aliased as {#proxyaddr}[rdoc-ref:Gem::Net::HTTP#proxyaddr]):
+ # - {#proxy_address}[rdoc-ref:Gem::Net::HTTP#proxy_address]:
# Returns the proxy address.
# - {#proxy_from_env?}[rdoc-ref:Gem::Net::HTTP#proxy_from_env?]:
# Returns whether the proxy is taken from an environment variable.
@@ -710,8 +713,7 @@ module Gem::Net #:nodoc:
# === \HTTP Version
#
# - {::version_1_2?}[rdoc-ref:Gem::Net::HTTP.version_1_2?]
- # (aliased as {::is_version_1_2?}[rdoc-ref:Gem::Net::HTTP.is_version_1_2?]
- # and {::version_1_2}[rdoc-ref:Gem::Net::HTTP.version_1_2]):
+ # (aliased as {::version_1_2}[rdoc-ref:Gem::Net::HTTP.version_1_2]):
# Returns true; retained for compatibility.
#
# === Debugging
@@ -722,7 +724,7 @@ module Gem::Net #:nodoc:
class HTTP < Protocol
# :stopdoc:
- VERSION = "0.4.0"
+ VERSION = "0.9.1"
HTTPVersion = '1.1'
begin
require 'zlib'
@@ -788,7 +790,7 @@ module Gem::Net #:nodoc:
# "completed": false
# }
#
- # With URI object +uri+ and optional hash argument +headers+:
+ # With Gem::URI object +uri+ and optional hash argument +headers+:
#
# uri = Gem::URI('https://jsonplaceholder.typicode.com/todos/1')
# headers = {'Content-type' => 'application/json; charset=UTF-8'}
@@ -861,7 +863,7 @@ module Gem::Net #:nodoc:
# Posts data to a host; returns a Gem::Net::HTTPResponse object.
#
- # Argument +url+ must be a URI;
+ # Argument +url+ must be a Gem::URI;
# argument +data+ must be a hash:
#
# _uri = uri.dup
@@ -889,6 +891,39 @@ module Gem::Net #:nodoc:
}
end
+ # Sends a PUT request to the server; returns a Gem::Net::HTTPResponse object.
+ #
+ # Argument +url+ must be a URL;
+ # argument +data+ must be a string:
+ #
+ # _uri = uri.dup
+ # _uri.path = '/posts'
+ # data = '{"title": "foo", "body": "bar", "userId": 1}'
+ # headers = {'content-type': 'application/json'}
+ # res = Gem::Net::HTTP.put(_uri, data, headers) # => #<Gem::Net::HTTPCreated 201 Created readbody=true>
+ # puts res.body
+ #
+ # Output:
+ #
+ # {
+ # "title": "foo",
+ # "body": "bar",
+ # "userId": 1,
+ # "id": 101
+ # }
+ #
+ # Related:
+ #
+ # - Gem::Net::HTTP::Put: request class for \HTTP method +PUT+.
+ # - Gem::Net::HTTP#put: convenience method for \HTTP method +PUT+.
+ #
+ def HTTP.put(url, data, header = nil)
+ start(url.hostname, url.port,
+ :use_ssl => url.scheme == 'https' ) {|http|
+ http.put(url, data, header)
+ }
+ end
+
#
# \HTTP session management
#
@@ -1062,7 +1097,7 @@ module Gem::Net #:nodoc:
# For proxy-defining arguments +p_addr+ through +p_no_proxy+,
# see {Proxy Server}[rdoc-ref:Gem::Net::HTTP@Proxy+Server].
#
- def HTTP.new(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, p_no_proxy = nil)
+ def HTTP.new(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, p_no_proxy = nil, p_use_ssl = nil)
http = super address, port
if proxy_class? then # from Gem::Net::HTTP::Proxy()
@@ -1071,6 +1106,7 @@ module Gem::Net #:nodoc:
http.proxy_port = @proxy_port
http.proxy_user = @proxy_user
http.proxy_pass = @proxy_pass
+ http.proxy_use_ssl = @proxy_use_ssl
elsif p_addr == :ENV then
http.proxy_from_env = true
else
@@ -1082,34 +1118,68 @@ module Gem::Net #:nodoc:
http.proxy_port = p_port || default_port
http.proxy_user = p_user
http.proxy_pass = p_pass
+ http.proxy_use_ssl = p_use_ssl
end
http
end
+ class << HTTP
+ # Allows to set the default configuration that will be used
+ # when creating a new connection.
+ #
+ # Example:
+ #
+ # Gem::Net::HTTP.default_configuration = {
+ # read_timeout: 1,
+ # write_timeout: 1
+ # }
+ # http = Gem::Net::HTTP.new(hostname)
+ # http.open_timeout # => 60
+ # http.read_timeout # => 1
+ # http.write_timeout # => 1
+ #
+ attr_accessor :default_configuration
+ end
+
# Creates a new \Gem::Net::HTTP object for the specified server address,
# without opening the TCP connection or initializing the \HTTP session.
# The +address+ should be a DNS hostname or IP address.
def initialize(address, port = nil) # :nodoc:
+ defaults = {
+ keep_alive_timeout: 2,
+ close_on_empty_response: false,
+ open_timeout: 60,
+ read_timeout: 60,
+ write_timeout: 60,
+ continue_timeout: nil,
+ max_retries: 1,
+ debug_output: nil,
+ response_body_encoding: false,
+ ignore_eof: true
+ }
+ options = defaults.merge(self.class.default_configuration || {})
+
@address = address
@port = (port || HTTP.default_port)
@ipaddr = nil
@local_host = nil
@local_port = nil
@curr_http_version = HTTPVersion
- @keep_alive_timeout = 2
+ @keep_alive_timeout = options[:keep_alive_timeout]
@last_communicated = nil
- @close_on_empty_response = false
+ @close_on_empty_response = options[:close_on_empty_response]
@socket = nil
@started = false
- @open_timeout = 60
- @read_timeout = 60
- @write_timeout = 60
- @continue_timeout = nil
- @max_retries = 1
- @debug_output = nil
- @response_body_encoding = false
- @ignore_eof = true
+ @open_timeout = options[:open_timeout]
+ @read_timeout = options[:read_timeout]
+ @write_timeout = options[:write_timeout]
+ @continue_timeout = options[:continue_timeout]
+ @max_retries = options[:max_retries]
+ @debug_output = options[:debug_output]
+ @response_body_encoding = options[:response_body_encoding]
+ @ignore_eof = options[:ignore_eof]
+ @tcpsocket_supports_open_timeout = nil
@proxy_from_env = false
@proxy_uri = nil
@@ -1117,6 +1187,7 @@ module Gem::Net #:nodoc:
@proxy_port = nil
@proxy_user = nil
@proxy_pass = nil
+ @proxy_use_ssl = nil
@use_ssl = false
@ssl_context = nil
@@ -1217,7 +1288,7 @@ module Gem::Net #:nodoc:
# - The name of an encoding.
# - An alias for an encoding name.
#
- # See {Encoding}[rdoc-ref:Encoding].
+ # See {Encoding}[https://docs.ruby-lang.org/en/master/Encoding.html].
#
# Examples:
#
@@ -1252,6 +1323,10 @@ module Gem::Net #:nodoc:
# see {Proxy Server}[rdoc-ref:Gem::Net::HTTP@Proxy+Server].
attr_writer :proxy_pass
+ # Sets whether the proxy uses SSL;
+ # see {Proxy Server}[rdoc-ref:Gem::Net::HTTP@Proxy+Server].
+ attr_writer :proxy_use_ssl
+
# Returns the IP address for the connection.
#
# If the session has not been started,
@@ -1440,23 +1515,6 @@ module Gem::Net #:nodoc:
@use_ssl = flag
end
- SSL_IVNAMES = [
- :@ca_file,
- :@ca_path,
- :@cert,
- :@cert_store,
- :@ciphers,
- :@extra_chain_cert,
- :@key,
- :@ssl_timeout,
- :@ssl_version,
- :@min_version,
- :@max_version,
- :@verify_callback,
- :@verify_depth,
- :@verify_mode,
- :@verify_hostname,
- ] # :nodoc:
SSL_ATTRIBUTES = [
:ca_file,
:ca_path,
@@ -1473,7 +1531,9 @@ module Gem::Net #:nodoc:
:verify_depth,
:verify_mode,
:verify_hostname,
- ] # :nodoc:
+ ].freeze # :nodoc:
+
+ SSL_IVNAMES = SSL_ATTRIBUTES.map { |a| "@#{a}".to_sym }.freeze # :nodoc:
# Sets or returns the path to a CA certification file in PEM format.
attr_accessor :ca_file
@@ -1490,11 +1550,11 @@ module Gem::Net #:nodoc:
attr_accessor :cert_store
# Sets or returns the available SSL ciphers.
- # See {OpenSSL::SSL::SSLContext#ciphers=}[rdoc-ref:OpenSSL::SSL::SSLContext#ciphers-3D].
+ # See {OpenSSL::SSL::SSLContext#ciphers=}[OpenSSL::SSL::SSL::Context#ciphers=].
attr_accessor :ciphers
# Sets or returns the extra X509 certificates to be added to the certificate chain.
- # See {OpenSSL::SSL::SSLContext#add_certificate}[rdoc-ref:OpenSSL::SSL::SSLContext#add_certificate].
+ # See {OpenSSL::SSL::SSLContext#add_certificate}[OpenSSL::SSL::SSL::Context#add_certificate].
attr_accessor :extra_chain_cert
# Sets or returns the OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object.
@@ -1504,15 +1564,15 @@ module Gem::Net #:nodoc:
attr_accessor :ssl_timeout
# Sets or returns the SSL version.
- # See {OpenSSL::SSL::SSLContext#ssl_version=}[rdoc-ref:OpenSSL::SSL::SSLContext#ssl_version-3D].
+ # See {OpenSSL::SSL::SSLContext#ssl_version=}[OpenSSL::SSL::SSL::Context#ssl_version=].
attr_accessor :ssl_version
# Sets or returns the minimum SSL version.
- # See {OpenSSL::SSL::SSLContext#min_version=}[rdoc-ref:OpenSSL::SSL::SSLContext#min_version-3D].
+ # See {OpenSSL::SSL::SSLContext#min_version=}[OpenSSL::SSL::SSL::Context#min_version=].
attr_accessor :min_version
# Sets or returns the maximum SSL version.
- # See {OpenSSL::SSL::SSLContext#max_version=}[rdoc-ref:OpenSSL::SSL::SSLContext#max_version-3D].
+ # See {OpenSSL::SSL::SSLContext#max_version=}[OpenSSL::SSL::SSL::Context#max_version=].
attr_accessor :max_version
# Sets or returns the callback for the server certification verification.
@@ -1528,7 +1588,7 @@ module Gem::Net #:nodoc:
# Sets or returns whether to verify that the server certificate is valid
# for the hostname.
- # See {OpenSSL::SSL::SSLContext#verify_hostname=}[rdoc-ref:OpenSSL::SSL::SSLContext#attribute-i-verify_mode].
+ # See {OpenSSL::SSL::SSLContext#verify_hostname=}[OpenSSL::SSL::SSL::Context#verify_hostname=].
attr_accessor :verify_hostname
# Returns the X509 certificate chain (an array of strings)
@@ -1576,6 +1636,21 @@ module Gem::Net #:nodoc:
self
end
+ # Finishes the \HTTP session:
+ #
+ # http = Gem::Net::HTTP.new(hostname)
+ # http.start
+ # http.started? # => true
+ # http.finish # => nil
+ # http.started? # => false
+ #
+ # Raises IOError if not in a session.
+ def finish
+ raise IOError, 'HTTP session not yet started' unless started?
+ do_finish
+ end
+
+ # :stopdoc:
def do_start
connect
@started = true
@@ -1598,19 +1673,26 @@ module Gem::Net #:nodoc:
end
debug "opening connection to #{conn_addr}:#{conn_port}..."
- s = Gem::Timeout.timeout(@open_timeout, Gem::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})"
+ begin
+ s = timeouted_connect(conn_addr, conn_port)
+ rescue => e
+ if (defined?(IO::TimeoutError) && e.is_a?(IO::TimeoutError)) || e.is_a?(Errno::ETIMEDOUT) # for compatibility with previous versions
+ e = Gem::Net::OpenTimeout.new(e)
end
- }
+ raise e, "Failed to open TCP connection to " +
+ "#{conn_addr}:#{conn_port} (#{e.message})"
+ end
s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
debug "opened"
if use_ssl?
if proxy?
- plain_sock = BufferedIO.new(s, read_timeout: @read_timeout,
+ if @proxy_use_ssl
+ proxy_sock = OpenSSL::SSL::SSLSocket.new(s)
+ ssl_socket_connect(proxy_sock, @open_timeout)
+ else
+ proxy_sock = s
+ end
+ proxy_sock = BufferedIO.new(proxy_sock, read_timeout: @read_timeout,
write_timeout: @write_timeout,
continue_timeout: @continue_timeout,
debug_output: @debug_output)
@@ -1621,8 +1703,8 @@ module Gem::Net #:nodoc:
buf << "Proxy-Authorization: Basic #{credential}\r\n"
end
buf << "\r\n"
- plain_sock.write(buf)
- HTTPResponse.read_new(plain_sock).value
+ proxy_sock.write(buf)
+ HTTPResponse.read_new(proxy_sock).value
# assuming nothing left in buffers after successful CONNECT response
end
@@ -1692,23 +1774,30 @@ module Gem::Net #:nodoc:
end
private :connect
- def on_connect
+ tcp_socket_parameters = TCPSocket.instance_method(:initialize).parameters
+ TCP_SOCKET_NEW_HAS_OPEN_TIMEOUT = if tcp_socket_parameters != [[:rest]]
+ tcp_socket_parameters.include?([:key, :open_timeout])
+ else
+ # Use Socket.tcp to find out since there is no parameters information for TCPSocket#initialize
+ # See discussion in https://github.com/ruby/net-http/pull/224
+ Socket.method(:tcp).parameters.include?([:key, :open_timeout])
end
- private :on_connect
+ private_constant :TCP_SOCKET_NEW_HAS_OPEN_TIMEOUT
- # Finishes the \HTTP session:
- #
- # http = Gem::Net::HTTP.new(hostname)
- # http.start
- # http.started? # => true
- # http.finish # => nil
- # http.started? # => false
- #
- # Raises IOError if not in a session.
- def finish
- raise IOError, 'HTTP session not yet started' unless started?
- do_finish
+ def timeouted_connect(conn_addr, conn_port)
+ if TCP_SOCKET_NEW_HAS_OPEN_TIMEOUT
+ TCPSocket.open(conn_addr, conn_port, @local_host, @local_port, open_timeout: @open_timeout)
+ else
+ Gem::Timeout.timeout(@open_timeout, Gem::Net::OpenTimeout) {
+ TCPSocket.open(conn_addr, conn_port, @local_host, @local_port)
+ }
+ end
+ end
+ private :timeouted_connect
+
+ def on_connect
end
+ private :on_connect
def do_finish
@started = false
@@ -1730,13 +1819,14 @@ module Gem::Net #:nodoc:
@proxy_port = nil
@proxy_user = nil
@proxy_pass = nil
+ @proxy_use_ssl = nil
# Creates an \HTTP proxy class which behaves like \Gem::Net::HTTP, but
# performs all access via the specified proxy.
#
# This class is obsolete. You may pass these same parameters directly to
# \Gem::Net::HTTP.new. See Gem::Net::HTTP.new for details of the arguments.
- def HTTP.Proxy(p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil) #:nodoc:
+ def HTTP.Proxy(p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, p_use_ssl = nil) #:nodoc:
return self unless p_addr
Class.new(self) {
@@ -1754,9 +1844,12 @@ module Gem::Net #:nodoc:
@proxy_user = p_user
@proxy_pass = p_pass
+ @proxy_use_ssl = p_use_ssl
}
end
+ # :startdoc:
+
class << HTTP
# Returns true if self is a class which was created by HTTP::Proxy.
def proxy_class?
@@ -1778,6 +1871,9 @@ module Gem::Net #:nodoc:
# Returns the password for accessing the proxy, or +nil+ if none;
# see Gem::Net::HTTP@Proxy+Server.
attr_reader :proxy_pass
+
+ # Use SSL when talking to the proxy. If Gem::Net::HTTP does not use a proxy, nil.
+ attr_reader :proxy_use_ssl
end
# Returns +true+ if a proxy server is defined, +false+ otherwise;
@@ -1793,7 +1889,7 @@ module Gem::Net #:nodoc:
@proxy_from_env
end
- # The proxy URI determined from the environment for this connection.
+ # The proxy Gem::URI determined from the environment for this connection.
def proxy_uri # :nodoc:
return if @proxy_uri == false
@proxy_uri ||= Gem::URI::HTTP.new(
@@ -1848,9 +1944,11 @@ module Gem::Net #:nodoc:
alias proxyport proxy_port #:nodoc: obsolete
private
+ # :stopdoc:
def unescape(value)
- require 'cgi/util'
+ require 'cgi/escape'
+ require 'cgi/util' unless defined?(CGI::EscapeExt)
CGI.unescape(value)
end
@@ -1875,6 +1973,7 @@ module Gem::Net #:nodoc:
path
end
end
+ # :startdoc:
#
# HTTP operations
@@ -2012,6 +2111,11 @@ module Gem::Net #:nodoc:
# http = Gem::Net::HTTP.new(hostname)
# http.put('/todos/1', data) # => #<Gem::Net::HTTPOK 200 OK readbody=true>
#
+ # Related:
+ #
+ # - Gem::Net::HTTP::Put: request class for \HTTP method PUT.
+ # - Gem::Net::HTTP.put: sends PUT request, returns response body.
+ #
def put(path, data, initheader = nil)
request(Put.new(path, initheader), data)
end
@@ -2324,7 +2428,9 @@ module Gem::Net #:nodoc:
res
end
- IDEMPOTENT_METHODS_ = %w/GET HEAD PUT DELETE OPTIONS TRACE/ # :nodoc:
+ # :stopdoc:
+
+ IDEMPOTENT_METHODS_ = %w/GET HEAD PUT DELETE OPTIONS TRACE/.freeze # :nodoc:
def transport_request(req)
count = 0
@@ -2350,7 +2456,10 @@ module Gem::Net #:nodoc:
res
}
res.reading_body(@socket, req.response_body_permitted?) {
- yield res if block_given?
+ if block_given?
+ count = max_retries # Don't restart in the middle of a download
+ yield res
+ end
}
rescue Gem::Net::OpenTimeout
raise
@@ -2478,6 +2587,11 @@ module Gem::Net #:nodoc:
alias_method :D, :debug
end
+ # for backward compatibility until Ruby 4.0
+ # https://bugs.ruby-lang.org/issues/20900
+ # https://github.com/bblimke/webmock/pull/1081
+ HTTPSession = HTTP
+ deprecate_constant :HTTPSession
end
require_relative 'http/exceptions'
@@ -2492,5 +2606,3 @@ require_relative 'http/response'
require_relative 'http/responses'
require_relative 'http/proxy_delta'
-
-require_relative 'http/backward'
diff --git a/lib/rubygems/vendor/net-http/lib/net/http/backward.rb b/lib/rubygems/vendor/net-http/lib/net/http/backward.rb
deleted file mode 100644
index 10dbc16224..0000000000
--- a/lib/rubygems/vendor/net-http/lib/net/http/backward.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-# for backward compatibility
-
-# :enddoc:
-
-class Gem::Net::HTTP
- ProxyMod = ProxyDelta
- deprecate_constant :ProxyMod
-end
-
-module Gem::Net::NetPrivate
- HTTPRequest = ::Gem::Net::HTTPRequest
- deprecate_constant :HTTPRequest
-end
-
-module Gem::Net
- HTTPSession = HTTP
-
- HTTPInformationCode = HTTPInformation
- HTTPSuccessCode = HTTPSuccess
- HTTPRedirectionCode = HTTPRedirection
- HTTPRetriableCode = HTTPRedirection
- HTTPClientErrorCode = HTTPClientError
- HTTPFatalErrorCode = HTTPClientError
- HTTPServerErrorCode = HTTPServerError
- HTTPResponseReceiver = HTTPResponse
-
- HTTPResponceReceiver = HTTPResponse # Typo since 2001
-
- deprecate_constant :HTTPSession,
- :HTTPInformationCode,
- :HTTPSuccessCode,
- :HTTPRedirectionCode,
- :HTTPRetriableCode,
- :HTTPClientErrorCode,
- :HTTPFatalErrorCode,
- :HTTPServerErrorCode,
- :HTTPResponseReceiver,
- :HTTPResponceReceiver
-end
diff --git a/lib/rubygems/vendor/net-http/lib/net/http/exceptions.rb b/lib/rubygems/vendor/net-http/lib/net/http/exceptions.rb
index c629c0113b..218df9a8bd 100644
--- a/lib/rubygems/vendor/net-http/lib/net/http/exceptions.rb
+++ b/lib/rubygems/vendor/net-http/lib/net/http/exceptions.rb
@@ -3,7 +3,7 @@ module Gem::Net
# Gem::Net::HTTP exception class.
# You cannot use Gem::Net::HTTPExceptions directly; instead, you must use
# its subclasses.
- module HTTPExceptions
+ module HTTPExceptions # :nodoc:
def initialize(msg, res) #:nodoc:
super msg
@response = res
@@ -12,6 +12,7 @@ module Gem::Net
alias data response #:nodoc: obsolete
end
+ # :stopdoc:
class HTTPError < ProtocolError
include HTTPExceptions
end
diff --git a/lib/rubygems/vendor/net-http/lib/net/http/generic_request.rb b/lib/rubygems/vendor/net-http/lib/net/http/generic_request.rb
index 5cfe75a7cd..d6496d4ac1 100644
--- a/lib/rubygems/vendor/net-http/lib/net/http/generic_request.rb
+++ b/lib/rubygems/vendor/net-http/lib/net/http/generic_request.rb
@@ -19,16 +19,13 @@ class Gem::Net::HTTPGenericRequest
if Gem::URI === uri_or_path then
raise ArgumentError, "not an HTTP Gem::URI" unless Gem::URI::HTTP === uri_or_path
- hostname = uri_or_path.hostname
+ hostname = uri_or_path.host
raise ArgumentError, "no host component for Gem::URI" unless (hostname && hostname.length > 0)
@uri = uri_or_path.dup
- host = @uri.hostname.dup
- host << ":" << @uri.port.to_s if @uri.port != @uri.default_port
@path = uri_or_path.request_uri
raise ArgumentError, "no HTTP request path given" unless @path
else
@uri = nil
- host = nil
raise ArgumentError, "no HTTP request path given" unless uri_or_path
raise ArgumentError, "HTTP request path is empty" if uri_or_path.empty?
@path = uri_or_path.dup
@@ -51,7 +48,7 @@ class Gem::Net::HTTPGenericRequest
initialize_http_header initheader
self['Accept'] ||= '*/*'
self['User-Agent'] ||= 'Ruby'
- self['Host'] ||= host if host
+ self['Host'] ||= @uri.authority if @uri
@body = nil
@body_stream = nil
@body_data = nil
@@ -102,6 +99,31 @@ class Gem::Net::HTTPGenericRequest
"\#<#{self.class} #{@method}>"
end
+ # Returns a string representation of the request with the details for pp:
+ #
+ # require 'pp'
+ # post = Gem::Net::HTTP::Post.new(uri)
+ # post.inspect # => "#<Gem::Net::HTTP::Post POST>"
+ # post.pretty_inspect
+ # # => #<Gem::Net::HTTP::Post
+ # POST
+ # path="/"
+ # headers={"accept-encoding" => ["gzip;q=1.0,deflate;q=0.6,identity;q=0.3"],
+ # "accept" => ["*/*"],
+ # "user-agent" => ["Ruby"],
+ # "host" => ["www.ruby-lang.org"]}>
+ #
+ def pretty_print(q)
+ q.object_group(self) {
+ q.breakable
+ q.text @method
+ q.breakable
+ q.text "path="; q.pp @path
+ q.breakable
+ q.text "headers="; q.pp to_hash
+ }
+ end
+
##
# Don't automatically decode response content-encoding if the user indicates
# they want to handle it.
@@ -220,7 +242,7 @@ class Gem::Net::HTTPGenericRequest
end
if host = self['host']
- host.sub!(/:.*/m, '')
+ host = Gem::URI.parse("//#{host}").host # Remove a port component from the existing Host header
elsif host = @uri.host
else
host = addr
@@ -239,6 +261,8 @@ class Gem::Net::HTTPGenericRequest
private
+ # :stopdoc:
+
class Chunker #:nodoc:
def initialize(sock)
@sock = sock
@@ -260,7 +284,6 @@ class Gem::Net::HTTPGenericRequest
def send_request_with_body(sock, ver, path, body)
self.content_length = body.bytesize
delete 'Transfer-Encoding'
- supply_default_content_type
write_header sock, ver, path
wait_for_continue sock, ver if sock.continue_timeout
sock.write body
@@ -271,7 +294,6 @@ class Gem::Net::HTTPGenericRequest
raise ArgumentError,
"Content-Length not given and Transfer-Encoding is not `chunked'"
end
- supply_default_content_type
write_header sock, ver, path
wait_for_continue sock, ver if sock.continue_timeout
if chunked?
@@ -373,12 +395,6 @@ class Gem::Net::HTTPGenericRequest
buf.clear
end
- def supply_default_content_type
- return if content_type()
- warn 'net/http: Content-Type did not set; using application/x-www-form-urlencoded', uplevel: 1 if $VERBOSE
- set_content_type 'application/x-www-form-urlencoded'
- end
-
##
# Waits up to the continue timeout for a response from the server provided
# we're speaking HTTP 1.1 and are expecting a 100-continue response.
@@ -411,4 +427,3 @@ class Gem::Net::HTTPGenericRequest
end
end
-
diff --git a/lib/rubygems/vendor/net-http/lib/net/http/header.rb b/lib/rubygems/vendor/net-http/lib/net/http/header.rb
index 1488e60068..bc68cd2eef 100644
--- a/lib/rubygems/vendor/net-http/lib/net/http/header.rb
+++ b/lib/rubygems/vendor/net-http/lib/net/http/header.rb
@@ -179,7 +179,9 @@
# - #each_value: Passes each string field value to the block.
#
module Gem::Net::HTTPHeader
+ # The maximum length of HTTP header keys.
MAX_KEY_LENGTH = 1024
+ # The maximum length of HTTP header values.
MAX_FIELD_LENGTH = 65536
def initialize_http_header(initheader) #:nodoc:
@@ -267,6 +269,7 @@ module Gem::Net::HTTPHeader
end
end
+ # :stopdoc:
private def set_field(key, val)
case val
when Enumerable
@@ -294,6 +297,7 @@ module Gem::Net::HTTPHeader
ary.push val
end
end
+ # :startdoc:
# Returns the array field value for the given +key+,
# or +nil+ if there is no such field;
@@ -490,8 +494,8 @@ module Gem::Net::HTTPHeader
alias canonical_each each_capitalized
- def capitalize(name)
- name.to_s.split(/-/).map {|s| s.capitalize }.join('-')
+ def capitalize(name) # :nodoc:
+ name.to_s.split('-'.freeze).map {|s| s.capitalize }.join('-'.freeze)
end
private :capitalize
@@ -957,12 +961,12 @@ module Gem::Net::HTTPHeader
@header['proxy-authorization'] = [basic_encode(account, password)]
end
- def basic_encode(account, password)
+ def basic_encode(account, password) # :nodoc:
'Basic ' + ["#{account}:#{password}"].pack('m0')
end
private :basic_encode
-# Returns whether the HTTP session is to be closed.
+ # Returns whether the HTTP session is to be closed.
def connection_close?
token = /(?:\A|,)\s*close\s*(?:\z|,)/i
@header['connection']&.grep(token) {return true}
@@ -970,7 +974,7 @@ module Gem::Net::HTTPHeader
false
end
-# Returns whether the HTTP session is to be kept alive.
+ # Returns whether the HTTP session is to be kept alive.
def connection_keep_alive?
token = /(?:\A|,)\s*keep-alive\s*(?:\z|,)/i
@header['connection']&.grep(token) {return true}
diff --git a/lib/rubygems/vendor/net-http/lib/net/http/requests.rb b/lib/rubygems/vendor/net-http/lib/net/http/requests.rb
index 1a57ddc7c2..f990761042 100644
--- a/lib/rubygems/vendor/net-http/lib/net/http/requests.rb
+++ b/lib/rubygems/vendor/net-http/lib/net/http/requests.rb
@@ -29,6 +29,7 @@
# - Gem::Net::HTTP#get: sends +GET+ request, returns response object.
#
class Gem::Net::HTTP::Get < Gem::Net::HTTPRequest
+ # :stopdoc:
METHOD = 'GET'
REQUEST_HAS_BODY = false
RESPONSE_HAS_BODY = true
@@ -60,6 +61,7 @@ end
# - Gem::Net::HTTP#head: sends +HEAD+ request, returns response object.
#
class Gem::Net::HTTP::Head < Gem::Net::HTTPRequest
+ # :stopdoc:
METHOD = 'HEAD'
REQUEST_HAS_BODY = false
RESPONSE_HAS_BODY = false
@@ -95,6 +97,7 @@ end
# - Gem::Net::HTTP#post: sends +POST+ request, returns response object.
#
class Gem::Net::HTTP::Post < Gem::Net::HTTPRequest
+ # :stopdoc:
METHOD = 'POST'
REQUEST_HAS_BODY = true
RESPONSE_HAS_BODY = true
@@ -124,7 +127,13 @@ end
# - {Idempotent}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Idempotent_methods]: yes.
# - {Cacheable}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Cacheable_methods]: no.
#
+# Related:
+#
+# - Gem::Net::HTTP.put: sends +PUT+ request, returns response object.
+# - Gem::Net::HTTP#put: sends +PUT+ request, returns response object.
+#
class Gem::Net::HTTP::Put < Gem::Net::HTTPRequest
+ # :stopdoc:
METHOD = 'PUT'
REQUEST_HAS_BODY = true
RESPONSE_HAS_BODY = true
@@ -157,6 +166,7 @@ end
# - Gem::Net::HTTP#delete: sends +DELETE+ request, returns response object.
#
class Gem::Net::HTTP::Delete < Gem::Net::HTTPRequest
+ # :stopdoc:
METHOD = 'DELETE'
REQUEST_HAS_BODY = false
RESPONSE_HAS_BODY = true
@@ -188,6 +198,7 @@ end
# - Gem::Net::HTTP#options: sends +OPTIONS+ request, returns response object.
#
class Gem::Net::HTTP::Options < Gem::Net::HTTPRequest
+ # :stopdoc:
METHOD = 'OPTIONS'
REQUEST_HAS_BODY = false
RESPONSE_HAS_BODY = true
@@ -219,6 +230,7 @@ end
# - Gem::Net::HTTP#trace: sends +TRACE+ request, returns response object.
#
class Gem::Net::HTTP::Trace < Gem::Net::HTTPRequest
+ # :stopdoc:
METHOD = 'TRACE'
REQUEST_HAS_BODY = false
RESPONSE_HAS_BODY = true
@@ -253,6 +265,7 @@ end
# - Gem::Net::HTTP#patch: sends +PATCH+ request, returns response object.
#
class Gem::Net::HTTP::Patch < Gem::Net::HTTPRequest
+ # :stopdoc:
METHOD = 'PATCH'
REQUEST_HAS_BODY = true
RESPONSE_HAS_BODY = true
@@ -280,6 +293,7 @@ end
# - Gem::Net::HTTP#propfind: sends +PROPFIND+ request, returns response object.
#
class Gem::Net::HTTP::Propfind < Gem::Net::HTTPRequest
+ # :stopdoc:
METHOD = 'PROPFIND'
REQUEST_HAS_BODY = true
RESPONSE_HAS_BODY = true
@@ -303,6 +317,7 @@ end
# - Gem::Net::HTTP#proppatch: sends +PROPPATCH+ request, returns response object.
#
class Gem::Net::HTTP::Proppatch < Gem::Net::HTTPRequest
+ # :stopdoc:
METHOD = 'PROPPATCH'
REQUEST_HAS_BODY = true
RESPONSE_HAS_BODY = true
@@ -326,6 +341,7 @@ end
# - Gem::Net::HTTP#mkcol: sends +MKCOL+ request, returns response object.
#
class Gem::Net::HTTP::Mkcol < Gem::Net::HTTPRequest
+ # :stopdoc:
METHOD = 'MKCOL'
REQUEST_HAS_BODY = true
RESPONSE_HAS_BODY = true
@@ -349,6 +365,7 @@ end
# - Gem::Net::HTTP#copy: sends +COPY+ request, returns response object.
#
class Gem::Net::HTTP::Copy < Gem::Net::HTTPRequest
+ # :stopdoc:
METHOD = 'COPY'
REQUEST_HAS_BODY = false
RESPONSE_HAS_BODY = true
@@ -372,6 +389,7 @@ end
# - Gem::Net::HTTP#move: sends +MOVE+ request, returns response object.
#
class Gem::Net::HTTP::Move < Gem::Net::HTTPRequest
+ # :stopdoc:
METHOD = 'MOVE'
REQUEST_HAS_BODY = false
RESPONSE_HAS_BODY = true
@@ -395,6 +413,7 @@ end
# - Gem::Net::HTTP#lock: sends +LOCK+ request, returns response object.
#
class Gem::Net::HTTP::Lock < Gem::Net::HTTPRequest
+ # :stopdoc:
METHOD = 'LOCK'
REQUEST_HAS_BODY = true
RESPONSE_HAS_BODY = true
@@ -418,8 +437,8 @@ end
# - Gem::Net::HTTP#unlock: sends +UNLOCK+ request, returns response object.
#
class Gem::Net::HTTP::Unlock < Gem::Net::HTTPRequest
+ # :stopdoc:
METHOD = 'UNLOCK'
REQUEST_HAS_BODY = true
RESPONSE_HAS_BODY = true
end
-
diff --git a/lib/rubygems/vendor/net-http/lib/net/http/response.rb b/lib/rubygems/vendor/net-http/lib/net/http/response.rb
index cbbd191d87..dc164f1504 100644
--- a/lib/rubygems/vendor/net-http/lib/net/http/response.rb
+++ b/lib/rubygems/vendor/net-http/lib/net/http/response.rb
@@ -153,6 +153,7 @@ class Gem::Net::HTTPResponse
end
private
+ # :stopdoc:
def read_status_line(sock)
str = sock.readline
@@ -259,7 +260,7 @@ class Gem::Net::HTTPResponse
# header.
attr_accessor :ignore_eof
- def inspect
+ def inspect # :nodoc:
"#<#{self.class} #{@code} #{@message} readbody=#{@read}>"
end
diff --git a/lib/rubygems/vendor/net-http/lib/net/http/responses.rb b/lib/rubygems/vendor/net-http/lib/net/http/responses.rb
index 0f26ae6c26..62ce1cba1b 100644
--- a/lib/rubygems/vendor/net-http/lib/net/http/responses.rb
+++ b/lib/rubygems/vendor/net-http/lib/net/http/responses.rb
@@ -4,7 +4,9 @@
module Gem::Net
+ # Unknown HTTP response
class HTTPUnknownResponse < HTTPResponse
+ # :stopdoc:
HAS_BODY = true
EXCEPTION_TYPE = HTTPError #
end
@@ -19,6 +21,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#1xx_informational_response].
#
class HTTPInformation < HTTPResponse
+ # :stopdoc:
HAS_BODY = false
EXCEPTION_TYPE = HTTPError #
end
@@ -34,6 +37,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#2xx_success].
#
class HTTPSuccess < HTTPResponse
+ # :stopdoc:
HAS_BODY = true
EXCEPTION_TYPE = HTTPError #
end
@@ -49,6 +53,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#3xx_redirection].
#
class HTTPRedirection < HTTPResponse
+ # :stopdoc:
HAS_BODY = true
EXCEPTION_TYPE = HTTPRetriableError #
end
@@ -63,6 +68,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#4xx_client_errors].
#
class HTTPClientError < HTTPResponse
+ # :stopdoc:
HAS_BODY = true
EXCEPTION_TYPE = HTTPClientException #
end
@@ -77,6 +83,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#5xx_server_errors].
#
class HTTPServerError < HTTPResponse
+ # :stopdoc:
HAS_BODY = true
EXCEPTION_TYPE = HTTPFatalError #
end
@@ -94,6 +101,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#100].
#
class HTTPContinue < HTTPInformation
+ # :stopdoc:
HAS_BODY = false
end
@@ -111,6 +119,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#101].
#
class HTTPSwitchProtocol < HTTPInformation
+ # :stopdoc:
HAS_BODY = false
end
@@ -127,6 +136,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#102].
#
class HTTPProcessing < HTTPInformation
+ # :stopdoc:
HAS_BODY = false
end
@@ -145,6 +155,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#103].
#
class HTTPEarlyHints < HTTPInformation
+ # :stopdoc:
HAS_BODY = false
end
@@ -162,6 +173,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#200].
#
class HTTPOK < HTTPSuccess
+ # :stopdoc:
HAS_BODY = true
end
@@ -179,6 +191,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#201].
#
class HTTPCreated < HTTPSuccess
+ # :stopdoc:
HAS_BODY = true
end
@@ -196,6 +209,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#202].
#
class HTTPAccepted < HTTPSuccess
+ # :stopdoc:
HAS_BODY = true
end
@@ -215,6 +229,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#203].
#
class HTTPNonAuthoritativeInformation < HTTPSuccess
+ # :stopdoc:
HAS_BODY = true
end
@@ -232,6 +247,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#204].
#
class HTTPNoContent < HTTPSuccess
+ # :stopdoc:
HAS_BODY = false
end
@@ -250,6 +266,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#205].
#
class HTTPResetContent < HTTPSuccess
+ # :stopdoc:
HAS_BODY = false
end
@@ -268,6 +285,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#206].
#
class HTTPPartialContent < HTTPSuccess
+ # :stopdoc:
HAS_BODY = true
end
@@ -285,6 +303,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#207].
#
class HTTPMultiStatus < HTTPSuccess
+ # :stopdoc:
HAS_BODY = true
end
@@ -304,6 +323,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#208].
#
class HTTPAlreadyReported < HTTPSuccess
+ # :stopdoc:
HAS_BODY = true
end
@@ -321,6 +341,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#226].
#
class HTTPIMUsed < HTTPSuccess
+ # :stopdoc:
HAS_BODY = true
end
@@ -338,6 +359,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#300].
#
class HTTPMultipleChoices < HTTPRedirection
+ # :stopdoc:
HAS_BODY = true
end
HTTPMultipleChoice = HTTPMultipleChoices
@@ -356,6 +378,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#301].
#
class HTTPMovedPermanently < HTTPRedirection
+ # :stopdoc:
HAS_BODY = true
end
@@ -373,6 +396,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#302].
#
class HTTPFound < HTTPRedirection
+ # :stopdoc:
HAS_BODY = true
end
HTTPMovedTemporarily = HTTPFound
@@ -390,6 +414,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#303].
#
class HTTPSeeOther < HTTPRedirection
+ # :stopdoc:
HAS_BODY = true
end
@@ -407,6 +432,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#304].
#
class HTTPNotModified < HTTPRedirection
+ # :stopdoc:
HAS_BODY = false
end
@@ -423,6 +449,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#305].
#
class HTTPUseProxy < HTTPRedirection
+ # :stopdoc:
HAS_BODY = false
end
@@ -440,6 +467,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#307].
#
class HTTPTemporaryRedirect < HTTPRedirection
+ # :stopdoc:
HAS_BODY = true
end
@@ -456,6 +484,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#308].
#
class HTTPPermanentRedirect < HTTPRedirection
+ # :stopdoc:
HAS_BODY = true
end
@@ -472,6 +501,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#400].
#
class HTTPBadRequest < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -488,6 +518,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#401].
#
class HTTPUnauthorized < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -504,6 +535,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#402].
#
class HTTPPaymentRequired < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -521,6 +553,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#403].
#
class HTTPForbidden < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -537,6 +570,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#404].
#
class HTTPNotFound < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -553,6 +587,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#405].
#
class HTTPMethodNotAllowed < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -570,6 +605,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#406].
#
class HTTPNotAcceptable < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -586,6 +622,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#407].
#
class HTTPProxyAuthenticationRequired < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -602,6 +639,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#408].
#
class HTTPRequestTimeout < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
HTTPRequestTimeOut = HTTPRequestTimeout
@@ -619,6 +657,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#409].
#
class HTTPConflict < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -636,6 +675,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#410].
#
class HTTPGone < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -653,6 +693,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#411].
#
class HTTPLengthRequired < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -670,6 +711,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#412].
#
class HTTPPreconditionFailed < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -686,6 +728,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#413].
#
class HTTPPayloadTooLarge < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
HTTPRequestEntityTooLarge = HTTPPayloadTooLarge
@@ -703,6 +746,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#414].
#
class HTTPURITooLong < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
HTTPRequestURITooLong = HTTPURITooLong
@@ -721,6 +765,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#415].
#
class HTTPUnsupportedMediaType < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -737,6 +782,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#416].
#
class HTTPRangeNotSatisfiable < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
HTTPRequestedRangeNotSatisfiable = HTTPRangeNotSatisfiable
@@ -754,6 +800,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#417].
#
class HTTPExpectationFailed < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -774,6 +821,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#421].
#
class HTTPMisdirectedRequest < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -790,6 +838,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#422].
#
class HTTPUnprocessableEntity < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -805,6 +854,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#423].
#
class HTTPLocked < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -821,6 +871,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#424].
#
class HTTPFailedDependency < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -840,6 +891,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#426].
#
class HTTPUpgradeRequired < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -856,6 +908,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#428].
#
class HTTPPreconditionRequired < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -872,6 +925,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#429].
#
class HTTPTooManyRequests < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -889,6 +943,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#431].
#
class HTTPRequestHeaderFieldsTooLarge < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
@@ -906,6 +961,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#451].
#
class HTTPUnavailableForLegalReasons < HTTPClientError
+ # :stopdoc:
HAS_BODY = true
end
# 444 No Response - Nginx
@@ -926,6 +982,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#500].
#
class HTTPInternalServerError < HTTPServerError
+ # :stopdoc:
HAS_BODY = true
end
@@ -943,6 +1000,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#501].
#
class HTTPNotImplemented < HTTPServerError
+ # :stopdoc:
HAS_BODY = true
end
@@ -960,6 +1018,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#502].
#
class HTTPBadGateway < HTTPServerError
+ # :stopdoc:
HAS_BODY = true
end
@@ -977,6 +1036,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#503].
#
class HTTPServiceUnavailable < HTTPServerError
+ # :stopdoc:
HAS_BODY = true
end
@@ -994,6 +1054,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#504].
#
class HTTPGatewayTimeout < HTTPServerError
+ # :stopdoc:
HAS_BODY = true
end
HTTPGatewayTimeOut = HTTPGatewayTimeout
@@ -1011,6 +1072,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#505].
#
class HTTPVersionNotSupported < HTTPServerError
+ # :stopdoc:
HAS_BODY = true
end
@@ -1027,6 +1089,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#506].
#
class HTTPVariantAlsoNegotiates < HTTPServerError
+ # :stopdoc:
HAS_BODY = true
end
@@ -1043,6 +1106,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#507].
#
class HTTPInsufficientStorage < HTTPServerError
+ # :stopdoc:
HAS_BODY = true
end
@@ -1059,6 +1123,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#508].
#
class HTTPLoopDetected < HTTPServerError
+ # :stopdoc:
HAS_BODY = true
end
# 509 Bandwidth Limit Exceeded - Apache bw/limited extension
@@ -1076,6 +1141,7 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#510].
#
class HTTPNotExtended < HTTPServerError
+ # :stopdoc:
HAS_BODY = true
end
@@ -1092,19 +1158,21 @@ module Gem::Net
# - {Wikipedia}[https://en.wikipedia.org/wiki/List_of_HTTP_status_codes#511].
#
class HTTPNetworkAuthenticationRequired < HTTPServerError
+ # :stopdoc:
HAS_BODY = true
end
end
class Gem::Net::HTTPResponse
+ # :stopdoc:
CODE_CLASS_TO_OBJ = {
'1' => Gem::Net::HTTPInformation,
'2' => Gem::Net::HTTPSuccess,
'3' => Gem::Net::HTTPRedirection,
'4' => Gem::Net::HTTPClientError,
'5' => Gem::Net::HTTPServerError
- }
+ }.freeze
CODE_TO_OBJ = {
'100' => Gem::Net::HTTPContinue,
'101' => Gem::Net::HTTPSwitchProtocol,
@@ -1170,5 +1238,5 @@ class Gem::Net::HTTPResponse
'508' => Gem::Net::HTTPLoopDetected,
'510' => Gem::Net::HTTPNotExtended,
'511' => Gem::Net::HTTPNetworkAuthenticationRequired,
- }
+ }.freeze
end
diff --git a/lib/rubygems/vendor/net-http/lib/net/https.rb b/lib/rubygems/vendor/net-http/lib/net/https.rb
index d2784f0be0..f104c85c81 100644
--- a/lib/rubygems/vendor/net-http/lib/net/https.rb
+++ b/lib/rubygems/vendor/net-http/lib/net/https.rb
@@ -4,7 +4,7 @@
= net/https -- SSL/TLS enhancement for Gem::Net::HTTP.
This file has been merged with net/http. There is no longer any need to
- require 'rubygems/vendor/net-http/lib/net/https' to use HTTPS.
+ require_relative 'https' to use HTTPS.
See Gem::Net::HTTP for details on how to make HTTPS connections.
diff --git a/lib/rubygems/vendor/net-protocol/.document b/lib/rubygems/vendor/net-protocol/.document
deleted file mode 100644
index 0c43bbd6b3..0000000000
--- a/lib/rubygems/vendor/net-protocol/.document
+++ /dev/null
@@ -1 +0,0 @@
-# Vendored files do not need to be documented
diff --git a/lib/rubygems/vendor/optparse/.document b/lib/rubygems/vendor/optparse/.document
deleted file mode 100644
index 0c43bbd6b3..0000000000
--- a/lib/rubygems/vendor/optparse/.document
+++ /dev/null
@@ -1 +0,0 @@
-# Vendored files do not need to be documented
diff --git a/lib/rubygems/vendor/optparse/lib/optparse.rb b/lib/rubygems/vendor/optparse/lib/optparse.rb
index 5937431720..d39d9dd4e0 100644
--- a/lib/rubygems/vendor/optparse/lib/optparse.rb
+++ b/lib/rubygems/vendor/optparse/lib/optparse.rb
@@ -7,7 +7,7 @@
#
# See Gem::OptionParser for documentation.
#
-
+require 'set' unless defined?(Set)
#--
# == Developer Documentation (not for RDoc output)
@@ -143,7 +143,7 @@
# Used:
#
# $ ruby optparse-test.rb -r
-# optparse-test.rb:9:in `<main>': missing argument: -r (Gem::OptionParser::MissingArgument)
+# optparse-test.rb:9:in '<main>': missing argument: -r (Gem::OptionParser::MissingArgument)
# $ ruby optparse-test.rb -r my-library
# You required my-library!
#
@@ -236,7 +236,7 @@
# $ ruby optparse-test.rb --user 2
# #<struct User id=2, name="Gandalf">
# $ ruby optparse-test.rb --user 3
-# optparse-test.rb:15:in `block in find_user': No User Found for id 3 (RuntimeError)
+# optparse-test.rb:15:in 'block in find_user': No User Found for id 3 (RuntimeError)
#
# === Store options to a Hash
#
@@ -425,7 +425,9 @@
# If you have any questions, file a ticket at http://bugs.ruby-lang.org.
#
class Gem::OptionParser
- Gem::OptionParser::Version = "0.4.0"
+ # The version string
+ VERSION = "0.8.0"
+ Version = VERSION # for compatibility
# :stopdoc:
NoArgument = [NO_ARGUMENT = :NONE, nil].freeze
@@ -438,6 +440,8 @@ class Gem::OptionParser
# and resolved against a list of acceptable values.
#
module Completion
+ # :nodoc:
+
def self.regexp(key, icase)
Regexp.new('\A' + Regexp.quote(key).gsub(/\w+\b/, '\&\w*'), icase)
end
@@ -459,7 +463,11 @@ class Gem::OptionParser
candidates
end
- def candidate(key, icase = false, pat = nil)
+ def self.completable?(key)
+ String.try_convert(key) or defined?(key.id2name)
+ end
+
+ def candidate(key, icase = false, pat = nil, &_)
Completion.candidate(key, icase, pat, &method(:each))
end
@@ -494,7 +502,6 @@ class Gem::OptionParser
end
end
-
#
# Map from option/keyword string to object with completion.
#
@@ -502,7 +509,6 @@ class Gem::OptionParser
include Completion
end
-
#
# Individual switch class. Not important to the user.
#
@@ -510,6 +516,8 @@ class Gem::OptionParser
# RequiredArgument, etc.
#
class Switch
+ # :nodoc:
+
attr_reader :pattern, :conv, :short, :long, :arg, :desc, :block
#
@@ -542,11 +550,11 @@ class Gem::OptionParser
def initialize(pattern = nil, conv = nil,
short = nil, long = nil, arg = nil,
- desc = ([] if short or long), block = nil, &_block)
+ desc = ([] if short or long), block = nil, values = nil, &_block)
raise if Array === pattern
block ||= _block
- @pattern, @conv, @short, @long, @arg, @desc, @block =
- pattern, conv, short, long, arg, desc, block
+ @pattern, @conv, @short, @long, @arg, @desc, @block, @values =
+ pattern, conv, short, long, arg, desc, block, values
end
#
@@ -579,11 +587,15 @@ class Gem::OptionParser
# exception.
#
def conv_arg(arg, val = []) # :nodoc:
+ v, = *val
if conv
val = conv.call(*val)
else
val = proc {|v| v}.call(*val)
end
+ if @values
+ @values.include?(val) or raise InvalidArgument, v
+ end
return arg, block, val
end
private :conv_arg
@@ -664,7 +676,7 @@ class Gem::OptionParser
(sopts+lopts).each do |opt|
# "(-x -c -r)-l[left justify]"
- if /^--\[no-\](.+)$/ =~ opt
+ if /\A--\[no-\](.+)$/ =~ opt
o = $1
yield("--#{o}", desc.join(""))
yield("--no-#{o}", desc.join(""))
@@ -697,6 +709,11 @@ class Gem::OptionParser
q.object_group(self) {pretty_print_contents(q)}
end
+ def omitted_argument(val) # :nodoc:
+ val.pop if val.size == 3 and val.last.nil?
+ val
+ end
+
#
# Switch that takes no arguments.
#
@@ -710,10 +727,10 @@ class Gem::OptionParser
conv_arg(arg)
end
- def self.incompatible_argument_styles(*)
+ def self.incompatible_argument_styles(*) # :nodoc:
end
- def self.pattern
+ def self.pattern # :nodoc:
Object
end
@@ -730,7 +747,7 @@ class Gem::OptionParser
#
# Raises an exception if argument is not present.
#
- def parse(arg, argv)
+ def parse(arg, argv, &_)
unless arg
raise MissingArgument if argv.empty?
arg = argv.shift
@@ -755,7 +772,7 @@ class Gem::OptionParser
if arg
conv_arg(*parse_arg(arg, &error))
else
- conv_arg(arg)
+ omitted_argument conv_arg(arg)
end
end
@@ -774,13 +791,14 @@ class Gem::OptionParser
#
def parse(arg, argv, &error)
if !(val = arg) and (argv.empty? or /\A-./ =~ (val = argv[0]))
- return nil, block, nil
+ return nil, block
end
opt = (val = parse_arg(val, &error))[1]
val = conv_arg(*val)
if opt and !arg
argv.shift
else
+ omitted_argument val
val[0] = nil
end
val
@@ -798,6 +816,8 @@ class Gem::OptionParser
# matching pattern and converter pair. Also provides summary feature.
#
class List
+ # :nodoc:
+
# Map from acceptable argument types to pattern and converter pairs.
attr_reader :atype
@@ -837,7 +857,7 @@ class Gem::OptionParser
def accept(t, pat = /.*/m, &block)
if pat
pat.respond_to?(:match) or
- raise TypeError, "has no `match'", ParseError.filter_backtrace(caller(2))
+ raise TypeError, "has no 'match'", ParseError.filter_backtrace(caller(2))
else
pat = t if t.respond_to?(:match)
end
@@ -1020,7 +1040,6 @@ class Gem::OptionParser
DefaultList.short['-'] = Switch::NoArgument.new {}
DefaultList.long[''] = Switch::NoArgument.new {throw :terminate}
-
COMPSYS_HEADER = <<'XXX' # :nodoc:
typeset -A opt_args
@@ -1033,11 +1052,31 @@ XXX
to << "#compdef #{name}\n"
to << COMPSYS_HEADER
visit(:compsys, {}, {}) {|o, d|
- to << %Q[ "#{o}[#{d.gsub(/[\"\[\]]/, '\\\\\&')}]" \\\n]
+ to << %Q[ "#{o}[#{d.gsub(/[\\\"\[\]]/, '\\\\\&')}]" \\\n]
}
to << " '*:file:_files' && return 0\n"
end
+ def help_exit
+ if $stdout.tty? && (pager = ENV.values_at(*%w[RUBY_PAGER PAGER]).find {|e| e && !e.empty?})
+ less = ENV["LESS"]
+ args = [{"LESS" => "#{less} -Fe"}, pager, "w"]
+ print = proc do |f|
+ f.puts help
+ rescue Errno::EPIPE
+ # pager terminated
+ end
+ if Process.respond_to?(:fork) and false
+ IO.popen("-") {|f| f ? Process.exec(*args, in: f) : print.call($stdout)}
+ # unreachable
+ end
+ IO.popen(*args, &print)
+ else
+ puts help
+ end
+ exit
+ end
+
#
# Default options for ARGV, which never appear in option summary.
#
@@ -1049,8 +1088,7 @@ XXX
#
Officious['help'] = proc do |parser|
Switch::NoArgument.new do |arg|
- puts parser.help
- exit
+ parser.help_exit
end
end
@@ -1071,7 +1109,7 @@ XXX
#
Officious['*-completion-zsh'] = proc do |parser|
Switch::OptionalArgument.new do |arg|
- parser.compsys(STDOUT, arg)
+ parser.compsys($stdout, arg)
exit
end
end
@@ -1084,7 +1122,7 @@ XXX
Switch::OptionalArgument.new do |pkg|
if pkg
begin
- require 'rubygems/vendor/optparse/lib/optparse/version'
+ require_relative 'optparse/version'
rescue LoadError
else
show_version(*pkg.split(/,/)) or
@@ -1129,6 +1167,10 @@ XXX
default.to_i + 1
end
end
+
+ #
+ # See self.inc
+ #
def inc(*args)
self.class.inc(*args)
end
@@ -1167,11 +1209,19 @@ XXX
def terminate(arg = nil)
self.class.terminate(arg)
end
+ #
+ # See #terminate.
+ #
def self.terminate(arg = nil)
throw :terminate, arg
end
@stack = [DefaultList]
+ #
+ # Returns the global top option list.
+ #
+ # Do not use directly.
+ #
def self.top() DefaultList end
#
@@ -1192,9 +1242,9 @@ XXX
#
# Directs to reject specified class argument.
#
- # +t+:: Argument class specifier, any object including Class.
+ # +type+:: Argument class specifier, any object including Class.
#
- # reject(t)
+ # reject(type)
#
def reject(*args, &blk) top.reject(*args, &blk) end
#
@@ -1245,7 +1295,15 @@ XXX
# to $0.
#
def program_name
- @program_name || File.basename($0, '.*')
+ @program_name || strip_ext(File.basename($0))
+ end
+
+ private def strip_ext(name) # :nodoc:
+ exts = /#{
+ require "rbconfig"
+ Regexp.union(*RbConfig::CONFIG["EXECUTABLE_EXTS"]&.split(" "))
+ }\z/o
+ name.sub(exts, "")
end
# for experimental cascading :-)
@@ -1284,10 +1342,24 @@ XXX
end
end
+ #
+ # Shows warning message with the program name
+ #
+ # +mesg+:: Message, defaulted to +$!+.
+ #
+ # See Kernel#warn.
+ #
def warn(mesg = $!)
super("#{program_name}: #{mesg}")
end
+ #
+ # Shows message with the program name then aborts.
+ #
+ # +mesg+:: Message, defaulted to +$!+.
+ #
+ # See Kernel#abort.
+ #
def abort(mesg = $!)
super("#{program_name}: #{mesg}")
end
@@ -1309,6 +1381,9 @@ XXX
#
# Pushes a new List.
#
+ # If a block is given, yields +self+ and returns the result of the
+ # block, otherwise returns +self+.
+ #
def new
@stack.push(List.new)
if block_given?
@@ -1407,6 +1482,7 @@ XXX
klass = nil
q, a = nil
has_arg = false
+ values = nil
opts.each do |o|
# argument class
@@ -1420,7 +1496,7 @@ XXX
end
# directly specified pattern(any object possible to match)
- if (!(String === o || Symbol === o)) and o.respond_to?(:match)
+ if !Completion.completable?(o) and o.respond_to?(:match)
pattern = notwice(o, pattern, 'pattern')
if pattern.respond_to?(:convert)
conv = pattern.method(:convert).to_proc
@@ -1434,7 +1510,12 @@ XXX
case o
when Proc, Method
block = notwice(o, block, 'block')
- when Array, Hash
+ when Array, Hash, Set
+ if Array === o
+ o, v = o.partition {|v,| Completion.completable?(v)}
+ values = notwice(v, values, 'values') unless v.empty?
+ next if o.empty?
+ end
case pattern
when CompletingHash
when nil
@@ -1444,11 +1525,13 @@ XXX
raise ArgumentError, "argument pattern given twice"
end
o.each {|pat, *v| pattern[pat] = v.fetch(0) {pat}}
+ when Range
+ values = notwice(o, values, 'values')
when Module
raise ArgumentError, "unsupported argument type: #{o}", ParseError.filter_backtrace(caller(4))
when *ArgumentStyle.keys
style = notwice(ArgumentStyle[o], style, 'style')
- when /^--no-([^\[\]=\s]*)(.+)?/
+ when /\A--no-([^\[\]=\s]*)(.+)?/
q, a = $1, $2
o = notwice(a ? Object : TrueClass, klass, 'type')
not_pattern, not_conv = search(:atype, o) unless not_style
@@ -1459,7 +1542,7 @@ XXX
(q = q.downcase).tr!('_', '-')
long << "no-#{q}"
nolong << q
- when /^--\[no-\]([^\[\]=\s]*)(.+)?/
+ when /\A--\[no-\]([^\[\]=\s]*)(.+)?/
q, a = $1, $2
o = notwice(a ? Object : TrueClass, klass, 'type')
if a
@@ -1472,7 +1555,7 @@ XXX
not_pattern, not_conv = search(:atype, FalseClass) unless not_style
not_style = Switch::NoArgument
nolong << "no-#{o}"
- when /^--([^\[\]=\s]*)(.+)?/
+ when /\A--([^\[\]=\s]*)(.+)?/
q, a = $1, $2
if a
o = notwice(NilClass, klass, 'type')
@@ -1482,7 +1565,7 @@ XXX
ldesc << "--#{q}"
(o = q.downcase).tr!('_', '-')
long << o
- when /^-(\[\^?\]?(?:[^\\\]]|\\.)*\])(.+)?/
+ when /\A-(\[\^?\]?(?:[^\\\]]|\\.)*\])(.+)?/
q, a = $1, $2
o = notwice(Object, klass, 'type')
if a
@@ -1493,7 +1576,7 @@ XXX
end
sdesc << "-#{q}"
short << Regexp.new(q)
- when /^-(.)(.+)?/
+ when /\A-(.)(.+)?/
q, a = $1, $2
if a
o = notwice(NilClass, klass, 'type')
@@ -1502,7 +1585,7 @@ XXX
end
sdesc << "-#{q}"
short << q
- when /^=/
+ when /\A=/
style = notwice(default_style.guess(arg = o), style, 'style')
default_pattern, conv = search(:atype, Object) unless default_pattern
else
@@ -1511,12 +1594,18 @@ XXX
end
default_pattern, conv = search(:atype, default_style.pattern) unless default_pattern
+ if Range === values and klass
+ unless (!values.begin or klass === values.begin) and
+ (!values.end or klass === values.end)
+ raise ArgumentError, "range does not match class"
+ end
+ end
if !(short.empty? and long.empty?)
if has_arg and default_style == Switch::NoArgument
default_style = Switch::RequiredArgument
end
s = (style || default_style).new(pattern || default_pattern,
- conv, sdesc, ldesc, arg, desc, block)
+ conv, sdesc, ldesc, arg, desc, block, values)
elsif !block
if style or pattern
raise ArgumentError, "no switch given", ParseError.filter_backtrace(caller)
@@ -1525,13 +1614,19 @@ XXX
else
short << pattern
s = (style || default_style).new(pattern,
- conv, nil, nil, arg, desc, block)
+ conv, nil, nil, arg, desc, block, values)
end
return s, short, long,
(not_style.new(not_pattern, not_conv, sdesc, ldesc, nil, desc, block) if not_style),
nolong
end
+ # ----
+ # Option definition phase methods
+ #
+ # These methods are used to define options, or to construct an
+ # Gem::OptionParser instance in other words.
+
# :call-seq:
# define(*params, &block)
#
@@ -1607,6 +1702,13 @@ XXX
top.append(string, nil, nil)
end
+ # ----
+ # Arguments parse phase methods
+ #
+ # These methods parse +argv+, convert, and store the results by
+ # calling handlers. As these methods do not modify +self+, +self+
+ # can be frozen.
+
#
# Parses command line arguments +argv+ in order. When a block is given,
# each non-option argument is yielded. When optional +into+ keyword
@@ -1616,21 +1718,21 @@ XXX
#
# Returns the rest of +argv+ left unparsed.
#
- def order(*argv, into: nil, &nonopt)
+ def order(*argv, **keywords, &nonopt)
argv = argv[0].dup if argv.size == 1 and Array === argv[0]
- order!(argv, into: into, &nonopt)
+ order!(argv, **keywords, &nonopt)
end
#
# Same as #order, but removes switches destructively.
# Non-option arguments remain in +argv+.
#
- def order!(argv = default_argv, into: nil, &nonopt)
+ def order!(argv = default_argv, into: nil, **keywords, &nonopt)
setter = ->(name, val) {into[name.to_sym] = val} if into
- parse_in_order(argv, setter, &nonopt)
+ parse_in_order(argv, setter, **keywords, &nonopt)
end
- def parse_in_order(argv = default_argv, setter = nil, &nonopt) # :nodoc:
+ def parse_in_order(argv = default_argv, setter = nil, exact: require_exact, **, &nonopt) # :nodoc:
opt, arg, val, rest = nil
nonopt ||= proc {|a| throw :terminate, a}
argv.unshift(arg) if arg = catch(:terminate) {
@@ -1641,19 +1743,24 @@ XXX
opt, rest = $1, $2
opt.tr!('_', '-')
begin
- sw, = complete(:long, opt, true)
- if require_exact && !sw.long.include?(arg)
- throw :terminate, arg unless raise_unknown
- raise InvalidOption, arg
+ if exact
+ sw, = search(:long, opt)
+ else
+ sw, = complete(:long, opt, true)
end
rescue ParseError
throw :terminate, arg unless raise_unknown
raise $!.set_option(arg, true)
+ else
+ unless sw
+ throw :terminate, arg unless raise_unknown
+ raise InvalidOption, arg
+ end
end
begin
opt, cb, val = sw.parse(rest, argv) {|*exc| raise(*exc)}
- val = cb.call(val) if cb
- setter.call(sw.switch_name, val) if setter
+ val = callback!(cb, 1, val) if cb
+ callback!(setter, 2, sw.switch_name, val) if setter
rescue ParseError
raise $!.set_option(arg, rest)
end
@@ -1671,7 +1778,7 @@ XXX
val = arg.delete_prefix('-')
has_arg = true
rescue InvalidOption
- raise if require_exact
+ raise if exact
# if no short options match, try completion with long
# options.
sw, = complete(:long, opt)
@@ -1691,8 +1798,8 @@ XXX
end
begin
argv.unshift(opt) if opt and (!rest or (opt = opt.sub(/\A-*/, '-')) != '-')
- val = cb.call(val) if cb
- setter.call(sw.switch_name, val) if setter
+ val = callback!(cb, 1, val) if cb
+ callback!(setter, 2, sw.switch_name, val) if setter
rescue ParseError
raise $!.set_option(arg, arg.length > 2)
end
@@ -1718,6 +1825,19 @@ XXX
end
private :parse_in_order
+ # Calls callback with _val_.
+ def callback!(cb, max_arity, *args) # :nodoc:
+ args.compact!
+
+ if (size = args.size) < max_arity and cb.to_proc.lambda?
+ (arity = cb.arity) < 0 and arity = (1-arity)
+ arity = max_arity if arity > max_arity
+ args[arity - 1] = nil if arity > size
+ end
+ cb.call(*args)
+ end
+ private :callback!
+
#
# Parses command line arguments +argv+ in permutation mode and returns
# list of non-option arguments. When optional +into+ keyword
@@ -1725,18 +1845,18 @@ XXX
# <code>[]=</code> method (so it can be Hash, or OpenStruct, or other
# similar object).
#
- def permute(*argv, into: nil)
+ def permute(*argv, **keywords)
argv = argv[0].dup if argv.size == 1 and Array === argv[0]
- permute!(argv, into: into)
+ permute!(argv, **keywords)
end
#
# Same as #permute, but removes switches destructively.
# Non-option arguments remain in +argv+.
#
- def permute!(argv = default_argv, into: nil)
+ def permute!(argv = default_argv, **keywords)
nonopts = []
- order!(argv, into: into, &nonopts.method(:<<))
+ order!(argv, **keywords) {|nonopt| nonopts << nonopt}
argv[0, 0] = nonopts
argv
end
@@ -1748,20 +1868,20 @@ XXX
# values are stored there via <code>[]=</code> method (so it can be Hash,
# or OpenStruct, or other similar object).
#
- def parse(*argv, into: nil)
+ def parse(*argv, **keywords)
argv = argv[0].dup if argv.size == 1 and Array === argv[0]
- parse!(argv, into: into)
+ parse!(argv, **keywords)
end
#
# Same as #parse, but removes switches destructively.
# Non-option arguments remain in +argv+.
#
- def parse!(argv = default_argv, into: nil)
+ def parse!(argv = default_argv, **keywords)
if ENV.include?('POSIXLY_CORRECT')
- order!(argv, into: into)
+ order!(argv, **keywords)
else
- permute!(argv, into: into)
+ permute!(argv, **keywords)
end
end
@@ -1784,18 +1904,21 @@ XXX
# # params[:bar] = "x" # --bar x
# # params[:zot] = "z" # --zot Z
#
- def getopts(*args, symbolize_names: false)
+ def getopts(*args, symbolize_names: false, **keywords)
argv = Array === args.first ? args.shift : default_argv
single_options, *long_options = *args
result = {}
+ setter = (symbolize_names ?
+ ->(name, val) {result[name.to_sym] = val}
+ : ->(name, val) {result[name] = val})
single_options.scan(/(.)(:)?/) do |opt, val|
if val
- result[opt] = nil
+ setter[opt, nil]
define("-#{opt} VAL")
else
- result[opt] = false
+ setter[opt, false]
define("-#{opt}")
end
end if single_options
@@ -1804,16 +1927,16 @@ XXX
arg, desc = arg.split(';', 2)
opt, val = arg.split(':', 2)
if val
- result[opt] = val.empty? ? nil : val
+ setter[opt, (val unless val.empty?)]
define("--#{opt}=#{result[opt] || "VAL"}", *[desc].compact)
else
- result[opt] = false
+ setter[opt, false]
define("--#{opt}", *[desc].compact)
end
end
- parse_in_order(argv, result.method(:[]=))
- symbolize_names ? result.transform_keys(&:to_sym) : result
+ parse_in_order(argv, setter, **keywords)
+ result
end
#
@@ -1863,7 +1986,7 @@ XXX
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])
+ raise exc.new(opt, additional: proc {|o| additional_message(typ, o)})
end
private :complete
@@ -1881,6 +2004,9 @@ XXX
DidYouMean.formatter.message_for(all_candidates & checker.correct(opt))
end
+ #
+ # Return candidates for +word+.
+ #
def candidate(word)
list = []
case word
@@ -1922,26 +2048,34 @@ XXX
# The optional +into+ keyword argument works exactly like that accepted in
# method #parse.
#
- def load(filename = nil, into: nil)
+ def load(filename = nil, **keywords)
unless filename
basename = File.basename($0, '.*')
- return true if load(File.expand_path(basename, '~/.options'), into: into) rescue nil
+ return true if load(File.expand_path("~/.options/#{basename}"), **keywords) rescue nil
basename << ".options"
+ if !(xdg = ENV['XDG_CONFIG_HOME']) or xdg.empty?
+ # https://specifications.freedesktop.org/basedir-spec/latest/#variables
+ #
+ # If $XDG_CONFIG_HOME is either not set or empty, a default
+ # equal to $HOME/.config should be used.
+ xdg = ['~/.config', true]
+ end
return [
- # XDG
- ENV['XDG_CONFIG_HOME'],
- '~/.config',
+ xdg,
+
*ENV['XDG_CONFIG_DIRS']&.split(File::PATH_SEPARATOR),
# Haiku
- '~/config/settings',
- ].any? {|dir|
+ ['~/config/settings', true],
+ ].any? {|dir, expand|
next if !dir or dir.empty?
- load(File.expand_path(basename, dir), into: into) rescue nil
+ filename = File.join(dir, basename)
+ filename = File.expand_path(filename) if expand
+ load(filename, **keywords) rescue nil
}
end
begin
- parse(*File.readlines(filename, chomp: true), into: into)
+ parse(*File.readlines(filename, chomp: true), **keywords)
true
rescue Errno::ENOENT, Errno::ENOTDIR
false
@@ -1954,10 +2088,10 @@ XXX
#
# +env+ defaults to the basename of the program.
#
- def environment(env = File.basename($0, '.*'))
+ def environment(env = File.basename($0, '.*'), **keywords)
env = ENV[env] || ENV[env.upcase] or return
require 'shellwords'
- parse(*Shellwords.shellwords(env))
+ parse(*Shellwords.shellwords(env), **keywords)
end
#
@@ -2123,6 +2257,7 @@ XXX
# Reason which caused the error.
Reason = 'parse error'
+ # :nodoc:
def initialize(*args, additional: nil)
@additional = additional
@arg0, = args
@@ -2142,9 +2277,10 @@ XXX
argv
end
+ DIR = File.join(__dir__, '')
def self.filter_backtrace(array)
unless $DEBUG
- array.delete_if(&%r"\A#{Regexp.quote(__FILE__)}:"o.method(:=~))
+ array.delete_if {|bt| bt.start_with?(DIR)}
end
array
end
@@ -2273,19 +2409,19 @@ XXX
# Parses +self+ destructively in order and returns +self+ containing the
# rest arguments left unparsed.
#
- def order!(&blk) options.order!(self, &blk) end
+ def order!(**keywords, &blk) options.order!(self, **keywords, &blk) end
#
# Parses +self+ destructively in permutation mode and returns +self+
# containing the rest arguments left unparsed.
#
- def permute!() options.permute!(self) end
+ def permute!(**keywords) options.permute!(self, **keywords) end
#
# Parses +self+ destructively and returns +self+ containing the
# rest arguments left unparsed.
#
- def parse!() options.parse!(self) end
+ def parse!(**keywords) options.parse!(self, **keywords) end
#
# Substitution of getopts is possible as follows. Also see
@@ -2298,8 +2434,8 @@ XXX
# rescue Gem::OptionParser::ParseError
# end
#
- def getopts(*args, symbolize_names: false)
- options.getopts(self, *args, symbolize_names: symbolize_names)
+ def getopts(*args, symbolize_names: false, **keywords)
+ options.getopts(self, *args, symbolize_names: symbolize_names, **keywords)
end
#
@@ -2309,7 +2445,8 @@ XXX
super
obj.instance_eval {@optparse = nil}
end
- def initialize(*args)
+
+ def initialize(*args) # :nodoc:
super
@optparse = nil
end
diff --git a/lib/rubygems/vendor/optparse/lib/optparse/ac.rb b/lib/rubygems/vendor/optparse/lib/optparse/ac.rb
index e84d01bf91..28a5b1b33e 100644
--- a/lib/rubygems/vendor/optparse/lib/optparse/ac.rb
+++ b/lib/rubygems/vendor/optparse/lib/optparse/ac.rb
@@ -1,7 +1,11 @@
# frozen_string_literal: false
require_relative '../optparse'
+#
+# autoconf-like options.
+#
class Gem::OptionParser::AC < Gem::OptionParser
+ # :stopdoc:
private
def _check_ac_args(name, block)
@@ -14,6 +18,7 @@ class Gem::OptionParser::AC < Gem::OptionParser
end
ARG_CONV = proc {|val| val.nil? ? true : val}
+ private_constant :ARG_CONV
def _ac_arg_enable(prefix, name, help_string, block)
_check_ac_args(name, block)
@@ -29,16 +34,27 @@ class Gem::OptionParser::AC < Gem::OptionParser
enable
end
+ # :startdoc:
+
public
+ # Define <tt>--enable</tt> / <tt>--disable</tt> style option
+ #
+ # Appears as <tt>--enable-<i>name</i></tt> in help message.
def ac_arg_enable(name, help_string, &block)
_ac_arg_enable("enable", name, help_string, block)
end
+ # Define <tt>--enable</tt> / <tt>--disable</tt> style option
+ #
+ # Appears as <tt>--disable-<i>name</i></tt> in help message.
def ac_arg_disable(name, help_string, &block)
_ac_arg_enable("disable", name, help_string, block)
end
+ # Define <tt>--with</tt> / <tt>--without</tt> style option
+ #
+ # Appears as <tt>--with-<i>name</i></tt> in help message.
def ac_arg_with(name, help_string, &block)
_check_ac_args(name, block)
diff --git a/lib/rubygems/vendor/optparse/lib/optparse/kwargs.rb b/lib/rubygems/vendor/optparse/lib/optparse/kwargs.rb
index 6987a5ed62..70762f033b 100644
--- a/lib/rubygems/vendor/optparse/lib/optparse/kwargs.rb
+++ b/lib/rubygems/vendor/optparse/lib/optparse/kwargs.rb
@@ -7,12 +7,17 @@ class Gem::OptionParser
#
# :include: ../../doc/optparse/creates_option.rdoc
#
- def define_by_keywords(options, meth, **opts)
- meth.parameters.each do |type, name|
+ # Defines options which set in to _options_ for keyword parameters
+ # of _method_.
+ #
+ # Parameters for each keywords are given as elements of _params_.
+ #
+ def define_by_keywords(options, method, **params)
+ method.parameters.each do |type, name|
case type
when :key, :keyreq
op, cl = *(type == :key ? %w"[ ]" : ["", ""])
- define("--#{name}=#{op}#{name.upcase}#{cl}", *opts[name]) do |o|
+ define("--#{name}=#{op}#{name.upcase}#{cl}", *params[name]) do |o|
options[name] = o
end
end
diff --git a/lib/rubygems/vendor/optparse/lib/optparse/version.rb b/lib/rubygems/vendor/optparse/lib/optparse/version.rb
index 5d79e9db44..e39889ae87 100644
--- a/lib/rubygems/vendor/optparse/lib/optparse/version.rb
+++ b/lib/rubygems/vendor/optparse/lib/optparse/version.rb
@@ -2,6 +2,11 @@
# Gem::OptionParser internal utility
class << Gem::OptionParser
+ #
+ # Shows version string in packages if Version is defined.
+ #
+ # +pkgs+:: package list
+ #
def show_version(*pkgs)
progname = ARGV.options.program_name
result = false
@@ -47,6 +52,8 @@ class << Gem::OptionParser
result
end
+ # :stopdoc:
+
def each_const(path, base = ::Object)
path.split(/::|\//).inject(base) do |klass, name|
raise NameError, path unless Module === klass
@@ -68,4 +75,6 @@ class << Gem::OptionParser
end
end
end
+
+ # :startdoc:
end
diff --git a/lib/rubygems/vendor/resolv/.document b/lib/rubygems/vendor/resolv/.document
deleted file mode 100644
index 0c43bbd6b3..0000000000
--- a/lib/rubygems/vendor/resolv/.document
+++ /dev/null
@@ -1 +0,0 @@
-# Vendored files do not need to be documented
diff --git a/lib/rubygems/vendor/resolv/lib/resolv.rb b/lib/rubygems/vendor/resolv/lib/resolv.rb
index ac0ba0b313..168df21f3e 100644
--- a/lib/rubygems/vendor/resolv/lib/resolv.rb
+++ b/lib/rubygems/vendor/resolv/lib/resolv.rb
@@ -1,13 +1,9 @@
# frozen_string_literal: true
require 'socket'
-require_relative '../../timeout/lib/timeout'
+require_relative '../../../vendored_timeout'
require 'io/wait'
-
-begin
- require 'securerandom'
-rescue LoadError
-end
+require_relative '../../../vendored_securerandom'
# Gem::Resolv is a thread-aware DNS resolver library written in Ruby. Gem::Resolv can
# handle multiple DNS requests concurrently without blocking the entire Ruby
@@ -37,7 +33,7 @@ end
class Gem::Resolv
- VERSION = "0.4.0"
+ VERSION = "0.6.2"
##
# Looks up the first IP address for +name+.
@@ -83,9 +79,22 @@ class Gem::Resolv
##
# Creates a new Gem::Resolv using +resolvers+.
+ #
+ # If +resolvers+ is not given, a hash, or +nil+, uses a Hosts resolver and
+ # and a DNS resolver. If +resolvers+ is a hash, uses the hash as
+ # configuration for the DNS resolver.
+
+ def initialize(resolvers=(arg_not_set = true; nil), use_ipv6: (keyword_not_set = true; nil))
+ if !keyword_not_set && !arg_not_set
+ warn "Support for separate use_ipv6 keyword is deprecated, as it is ignored if an argument is provided. Do not provide a positional argument if using the use_ipv6 keyword argument.", uplevel: 1
+ end
- def initialize(resolvers=nil, use_ipv6: nil)
- @resolvers = resolvers || [Hosts.new, DNS.new(DNS::Config.default_config_hash.merge(use_ipv6: use_ipv6))]
+ @resolvers = case resolvers
+ when Hash, nil
+ [Hosts.new, DNS.new(DNS::Config.default_config_hash.merge(resolvers || {}))]
+ else
+ resolvers
+ end
end
##
@@ -164,13 +173,16 @@ class Gem::Resolv
class ResolvTimeout < Gem::Timeout::Error; end
+ WINDOWS = /mswin|cygwin|mingw|bccwin/ =~ RUBY_PLATFORM || ::RbConfig::CONFIG['host_os'] =~ /mswin/
+ private_constant :WINDOWS
+
##
# Gem::Resolv::Hosts is a hostname resolver that uses the system hosts file.
class Hosts
- if /mswin|mingw|cygwin/ =~ RUBY_PLATFORM and
+ if WINDOWS
begin
- require 'win32/resolv'
+ require 'win32/resolv' unless defined?(Win32::Resolv)
DefaultFileName = Win32::Resolv.get_hosts_path || IO::NULL
rescue LoadError
end
@@ -396,13 +408,15 @@ class Gem::Resolv
# be a Gem::Resolv::IPv4 or Gem::Resolv::IPv6
def each_address(name)
- each_resource(name, Resource::IN::A) {|resource| yield resource.address}
if use_ipv6?
each_resource(name, Resource::IN::AAAA) {|resource| yield resource.address}
end
+ each_resource(name, Resource::IN::A) {|resource| yield resource.address}
end
def use_ipv6? # :nodoc:
+ @config.lazy_initialize unless @config.instance_variable_get(:@initialized)
+
use_ipv6 = @config.use_ipv6?
unless use_ipv6.nil?
return use_ipv6
@@ -513,35 +527,40 @@ class Gem::Resolv
def fetch_resource(name, typeclass)
lazy_initialize
- begin
- requester = make_udp_requester
+ truncated = {}
+ requesters = {}
+ udp_requester = begin
+ make_udp_requester
rescue Errno::EACCES
# fall back to TCP
end
senders = {}
+
begin
- @config.resolv(name) {|candidate, tout, nameserver, port|
- requester ||= make_tcp_requester(nameserver, port)
+ @config.resolv(name) do |candidate, tout, nameserver, port|
msg = Message.new
msg.rd = 1
msg.add_question(candidate, typeclass)
- unless sender = senders[[candidate, nameserver, port]]
+
+ requester = requesters.fetch([nameserver, port]) do
+ if !truncated[candidate] && udp_requester
+ udp_requester
+ else
+ requesters[[nameserver, port]] = make_tcp_requester(nameserver, port)
+ end
+ end
+
+ unless sender = senders[[candidate, requester, nameserver, port]]
sender = requester.sender(msg, candidate, nameserver, port)
next if !sender
- senders[[candidate, nameserver, port]] = sender
+ senders[[candidate, requester, nameserver, port]] = sender
end
reply, reply_name = requester.request(sender, tout)
case reply.rcode
when RCode::NoError
if reply.tc == 1 and not Requester::TCP === requester
- requester.close
# Retry via TCP:
- requester = make_tcp_requester(nameserver, port)
- senders = {}
- # This will use TCP for all remaining candidates (assuming the
- # current candidate does not already respond successfully via
- # TCP). This makes sense because we already know the full
- # response will not fit in an untruncated UDP packet.
+ truncated[candidate] = true
redo
else
yield(reply, reply_name)
@@ -552,9 +571,10 @@ class Gem::Resolv
else
raise Config::OtherResolvError.new(reply_name.to_s)
end
- }
+ end
ensure
- requester&.close
+ udp_requester&.close
+ requesters.each_value { |requester| requester&.close }
end
end
@@ -569,6 +589,11 @@ class Gem::Resolv
def make_tcp_requester(host, port) # :nodoc:
return Requester::TCP.new(host, port)
+ rescue Errno::ECONNREFUSED
+ # Treat a refused TCP connection attempt to a nameserver like a timeout,
+ # as Gem::Resolv::DNS::Config#resolv considers ResolvTimeout exceptions as a
+ # hint to try the next nameserver:
+ raise ResolvTimeout
end
def extract_resources(msg, name, typeclass) # :nodoc:
@@ -602,16 +627,10 @@ class Gem::Resolv
}
end
- if defined? SecureRandom
- def self.random(arg) # :nodoc:
- begin
- SecureRandom.random_number(arg)
- rescue NotImplementedError
- rand(arg)
- end
- end
- else
- def self.random(arg) # :nodoc:
+ def self.random(arg) # :nodoc:
+ begin
+ Gem::SecureRandom.random_number(arg)
+ rescue NotImplementedError
rand(arg)
end
end
@@ -643,8 +662,20 @@ class Gem::Resolv
}
end
- def self.bind_random_port(udpsock, bind_host="0.0.0.0") # :nodoc:
- begin
+ case RUBY_PLATFORM
+ when *[
+ # https://www.rfc-editor.org/rfc/rfc6056.txt
+ # Appendix A. Survey of the Algorithms in Use by Some Popular Implementations
+ /freebsd/, /linux/, /netbsd/, /openbsd/, /solaris/,
+ /darwin/, # the same as FreeBSD
+ ] then
+ def self.bind_random_port(udpsock, bind_host="0.0.0.0") # :nodoc:
+ udpsock.bind(bind_host, 0)
+ end
+ else
+ # Sequential port assignment
+ def self.bind_random_port(udpsock, bind_host="0.0.0.0") # :nodoc:
+ # Ephemeral port number range recommended by RFC 6056
port = random(1024..65535)
udpsock.bind(bind_host, port)
rescue Errno::EADDRINUSE, # POSIX
@@ -967,13 +998,13 @@ class Gem::Resolv
next unless keyword
case keyword
when 'nameserver'
- nameserver.concat(args)
+ nameserver.concat(args.each(&:freeze))
when 'domain'
next if args.empty?
- search = [args[0]]
+ search = [args[0].freeze]
when 'search'
next if args.empty?
- search = args
+ search = args.each(&:freeze)
when 'options'
args.each {|arg|
case arg
@@ -984,22 +1015,22 @@ class Gem::Resolv
end
}
}
- return { :nameserver => nameserver, :search => search, :ndots => ndots }
+ return { :nameserver => nameserver.freeze, :search => search.freeze, :ndots => ndots.freeze }.freeze
end
def Config.default_config_hash(filename="/etc/resolv.conf")
if File.exist? filename
- config_hash = Config.parse_resolv_conf(filename)
+ Config.parse_resolv_conf(filename)
+ elsif WINDOWS
+ require 'win32/resolv' unless defined?(Win32::Resolv)
+ search, nameserver = Win32::Resolv.get_resolv_info
+ config_hash = {}
+ config_hash[:nameserver] = nameserver if nameserver
+ config_hash[:search] = [search].flatten if search
+ config_hash
else
- if /mswin|cygwin|mingw|bccwin/ =~ RUBY_PLATFORM
- require 'win32/resolv'
- search, nameserver = Win32::Resolv.get_resolv_info
- config_hash = {}
- config_hash[:nameserver] = nameserver if nameserver
- config_hash[:search] = [search].flatten if search
- end
+ {}
end
- config_hash || {}
end
def lazy_initialize
@@ -1648,6 +1679,7 @@ class Gem::Resolv
prev_index = @index
save_index = nil
d = []
+ size = -1
while true
raise DecodeError.new("limit exceeded") if @limit <= @index
case @data.getbyte(@index)
@@ -1668,7 +1700,10 @@ class Gem::Resolv
end
@index = idx
else
- d << self.get_label
+ l = self.get_label
+ d << l
+ size += 1 + l.string.bytesize
+ raise DecodeError.new("name label data exceed 255 octets") if size > 255
end
end
end
@@ -1800,7 +1835,6 @@ class Gem::Resolv
end
end
-
##
# Base class for SvcParam. [RFC9460]
@@ -2095,7 +2129,14 @@ class Gem::Resolv
attr_reader :ttl
- ClassHash = {} # :nodoc:
+ ClassHash = Module.new do
+ module_function
+
+ def []=(type_class_value, klass)
+ type_value, class_value = type_class_value
+ Resource.const_set(:"Type#{type_value}_Class#{class_value}", klass)
+ end
+ end
def encode_rdata(msg) # :nodoc:
raise NotImplementedError.new
@@ -2133,7 +2174,9 @@ class Gem::Resolv
end
def self.get_class(type_value, class_value) # :nodoc:
- return ClassHash[[type_value, class_value]] ||
+ cache = :"Type#{type_value}_Class#{class_value}"
+
+ return (const_defined?(cache) && const_get(cache)) ||
Generic.create(type_value, class_value)
end
@@ -2499,7 +2542,6 @@ class Gem::Resolv
attr_reader :altitude
-
def encode_rdata(msg) # :nodoc:
msg.put_bytes(@version)
msg.put_bytes(@ssize.scalar)
@@ -2563,7 +2605,7 @@ class Gem::Resolv
end
##
- # Flags for this proprty:
+ # Flags for this property:
# - Bit 0 : 0 = not critical, 1 = critical
attr_reader :flags
@@ -3439,4 +3481,3 @@ class Gem::Resolv
AddressRegex = /(?:#{IPv4::Regex})|(?:#{IPv6::Regex})/
end
-
diff --git a/lib/rubygems/vendor/securerandom/lib/securerandom.rb b/lib/rubygems/vendor/securerandom/lib/securerandom.rb
new file mode 100644
index 0000000000..b6f1d71ad3
--- /dev/null
+++ b/lib/rubygems/vendor/securerandom/lib/securerandom.rb
@@ -0,0 +1,102 @@
+# -*- 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
+# suitable for generating session keys in HTTP cookies, etc.
+#
+# You can use this library in your application by requiring it:
+#
+# require 'rubygems/vendor/securerandom/lib/securerandom'
+#
+# It supports the following secure random number generators:
+#
+# * openssl
+# * /dev/urandom
+# * Win32
+#
+# Gem::SecureRandom is extended by the Random::Formatter module which
+# defines the following methods:
+#
+# * alphanumeric
+# * base64
+# * choose
+# * gen_random
+# * hex
+# * rand
+# * random_bytes
+# * random_number
+# * urlsafe_base64
+# * uuid
+#
+# These methods are usable as class methods of Gem::SecureRandom such as
+# +Gem::SecureRandom.hex+.
+#
+# If a secure random number generator is not available,
+# +NotImplementedError+ is raised.
+
+module Gem::SecureRandom
+
+ # The version
+ VERSION = "0.4.1"
+
+ class << self
+ # Returns a random binary string containing +size+ bytes.
+ #
+ # See Random.bytes
+ def bytes(n)
+ return gen_random(n)
+ end
+
+ # Compatibility methods for Ruby 3.2, we can remove this after dropping to support Ruby 3.2
+ def alphanumeric(n = nil, chars: ALPHANUMERIC)
+ n = 16 if n.nil?
+ choose(chars, n)
+ end if RUBY_VERSION < '3.3'
+
+ private
+
+ # :stopdoc:
+
+ # Implementation using OpenSSL
+ def gen_random_openssl(n)
+ return OpenSSL::Random.random_bytes(n)
+ end
+
+ # Implementation using system random device
+ def gen_random_urandom(n)
+ ret = Random.urandom(n)
+ unless ret
+ raise NotImplementedError, "No random device"
+ end
+ unless ret.length == n
+ raise NotImplementedError, "Unexpected partial read from random device: only #{ret.length} for #{n} bytes"
+ end
+ ret
+ end
+
+ begin
+ # Check if Random.urandom is available
+ Random.urandom(1)
+ alias gen_random gen_random_urandom
+ rescue RuntimeError
+ begin
+ require 'openssl'
+ rescue NoMethodError
+ raise NotImplementedError, "No random device"
+ else
+ alias gen_random gen_random_openssl
+ end
+ end
+
+ # :startdoc:
+
+ # Generate random data bytes for Random::Formatter
+ public :gen_random
+ end
+end
+
+Gem::SecureRandom.extend(Random::Formatter)
diff --git a/lib/rubygems/vendor/timeout/.document b/lib/rubygems/vendor/timeout/.document
deleted file mode 100644
index 0c43bbd6b3..0000000000
--- a/lib/rubygems/vendor/timeout/.document
+++ /dev/null
@@ -1 +0,0 @@
-# Vendored files do not need to be documented
diff --git a/lib/rubygems/vendor/timeout/lib/timeout.rb b/lib/rubygems/vendor/timeout/lib/timeout.rb
index df97d64ca0..376b8c0e2b 100644
--- a/lib/rubygems/vendor/timeout/lib/timeout.rb
+++ b/lib/rubygems/vendor/timeout/lib/timeout.rb
@@ -4,7 +4,7 @@
# == Synopsis
#
# require 'rubygems/vendor/timeout/lib/timeout'
-# status = Gem::Timeout::timeout(5) {
+# status = Gem::Timeout.timeout(5) {
# # Something that should be interrupted if it takes more than 5 seconds...
# }
#
@@ -13,28 +13,25 @@
# Gem::Timeout provides a way to auto-terminate a potentially long-running
# operation if it hasn't finished in a fixed amount of time.
#
-# Previous versions didn't use a module for namespacing, however
-# #timeout is provided for backwards compatibility. You
-# should prefer Gem::Timeout.timeout instead.
-#
# == Copyright
#
# Copyright:: (C) 2000 Network Applied Communication Laboratory, Inc.
# Copyright:: (C) 2000 Information-technology Promotion Agency, Japan
module Gem::Timeout
- VERSION = "0.4.1"
+ # The version
+ VERSION = "0.4.4"
# Internal error raised to when a timeout is triggered.
class ExitException < Exception
- def exception(*)
+ def exception(*) # :nodoc:
self
end
end
# Raised by Gem::Timeout.timeout when the block times out.
class Error < RuntimeError
- def self.handle_timeout(message)
+ def self.handle_timeout(message) # :nodoc:
exc = ExitException.new(message)
begin
@@ -126,6 +123,9 @@ module Gem::Timeout
def self.ensure_timeout_thread_created
unless @timeout_thread and @timeout_thread.alive?
+ # If the Mutex is already owned we are in a signal handler.
+ # In that case, just return and let the main thread create the @timeout_thread.
+ return if TIMEOUT_THREAD_MUTEX.owned?
TIMEOUT_THREAD_MUTEX.synchronize do
unless @timeout_thread and @timeout_thread.alive?
@timeout_thread = create_timeout_thread
@@ -144,9 +144,10 @@ module Gem::Timeout
# Perform an operation in a block, raising an error if it takes longer than
# +sec+ seconds to complete.
#
- # +sec+:: Number of seconds to wait for the block to terminate. Any number
- # may be used, including Floats to specify fractional seconds. A
+ # +sec+:: Number of seconds to wait for the block to terminate. Any non-negative number
+ # or nil may be used, including Floats to specify fractional seconds. A
# value of 0 or +nil+ will execute the block without any timeout.
+ # Any negative number will raise an ArgumentError.
# +klass+:: Exception Class to raise if the block fails to terminate
# in +sec+ seconds. Omitting will use the default, Gem::Timeout::Error
# +message+:: Error message to raise with Exception Class.
@@ -168,6 +169,7 @@ module Gem::Timeout
# a module method, so you can call it directly as Gem::Timeout.timeout().
def timeout(sec, klass = nil, message = nil, &block) #:yield: +sec+
return yield(sec) if sec == nil or sec.zero?
+ raise ArgumentError, "Timeout sec must be a non-negative number" if 0 > sec
message ||= "execution expired"
diff --git a/lib/rubygems/vendor/tsort/.document b/lib/rubygems/vendor/tsort/.document
deleted file mode 100644
index 0c43bbd6b3..0000000000
--- a/lib/rubygems/vendor/tsort/.document
+++ /dev/null
@@ -1 +0,0 @@
-# Vendored files do not need to be documented
diff --git a/lib/rubygems/vendor/uri/.document b/lib/rubygems/vendor/uri/.document
deleted file mode 100644
index 0c43bbd6b3..0000000000
--- a/lib/rubygems/vendor/uri/.document
+++ /dev/null
@@ -1 +0,0 @@
-# Vendored files do not need to be documented
diff --git a/lib/rubygems/vendor/uri/lib/uri.rb b/lib/rubygems/vendor/uri/lib/uri.rb
index f1ccc167cc..4691b122b2 100644
--- a/lib/rubygems/vendor/uri/lib/uri.rb
+++ b/lib/rubygems/vendor/uri/lib/uri.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: false
# Gem::URI is a module providing classes to handle Uniform Resource Identifiers
-# (RFC2396[http://tools.ietf.org/html/rfc2396]).
+# (RFC2396[https://www.rfc-editor.org/rfc/rfc2396]).
#
# == Features
#
@@ -47,14 +47,14 @@
# A good place to view an RFC spec is http://www.ietf.org/rfc.html.
#
# Here is a list of all related RFC's:
-# - RFC822[http://tools.ietf.org/html/rfc822]
-# - RFC1738[http://tools.ietf.org/html/rfc1738]
-# - RFC2255[http://tools.ietf.org/html/rfc2255]
-# - RFC2368[http://tools.ietf.org/html/rfc2368]
-# - RFC2373[http://tools.ietf.org/html/rfc2373]
-# - RFC2396[http://tools.ietf.org/html/rfc2396]
-# - RFC2732[http://tools.ietf.org/html/rfc2732]
-# - RFC3986[http://tools.ietf.org/html/rfc3986]
+# - RFC822[https://www.rfc-editor.org/rfc/rfc822]
+# - RFC1738[https://www.rfc-editor.org/rfc/rfc1738]
+# - RFC2255[https://www.rfc-editor.org/rfc/rfc2255]
+# - RFC2368[https://www.rfc-editor.org/rfc/rfc2368]
+# - RFC2373[https://www.rfc-editor.org/rfc/rfc2373]
+# - RFC2396[https://www.rfc-editor.org/rfc/rfc2396]
+# - RFC2732[https://www.rfc-editor.org/rfc/rfc2732]
+# - RFC3986[https://www.rfc-editor.org/rfc/rfc3986]
#
# == Class tree
#
diff --git a/lib/rubygems/vendor/uri/lib/uri/common.rb b/lib/rubygems/vendor/uri/lib/uri/common.rb
index 921fb9dd28..e9bdfa6a07 100644
--- a/lib/rubygems/vendor/uri/lib/uri/common.rb
+++ b/lib/rubygems/vendor/uri/lib/uri/common.rb
@@ -13,24 +13,54 @@ require_relative "rfc2396_parser"
require_relative "rfc3986_parser"
module Gem::URI
- include RFC2396_REGEXP
+ # The default parser instance for RFC 2396.
+ RFC2396_PARSER = RFC2396_Parser.new
+ Ractor.make_shareable(RFC2396_PARSER) if defined?(Ractor)
- REGEXP = RFC2396_REGEXP
- Parser = RFC2396_Parser
+ # The default parser instance for RFC 3986.
RFC3986_PARSER = RFC3986_Parser.new
Ractor.make_shareable(RFC3986_PARSER) if defined?(Ractor)
- # Gem::URI::Parser.new
- DEFAULT_PARSER = Parser.new
- DEFAULT_PARSER.pattern.each_pair do |sym, str|
- unless REGEXP::PATTERN.const_defined?(sym)
- REGEXP::PATTERN.const_set(sym, str)
+ # The default parser instance.
+ DEFAULT_PARSER = RFC3986_PARSER
+ Ractor.make_shareable(DEFAULT_PARSER) if defined?(Ractor)
+
+ # Set the default parser instance.
+ def self.parser=(parser = RFC3986_PARSER)
+ remove_const(:Parser) if defined?(::Gem::URI::Parser)
+ const_set("Parser", parser.class)
+
+ remove_const(:PARSER) if defined?(::Gem::URI::PARSER)
+ const_set("PARSER", parser)
+
+ remove_const(:REGEXP) if defined?(::Gem::URI::REGEXP)
+ remove_const(:PATTERN) if defined?(::Gem::URI::PATTERN)
+ if Parser == RFC2396_Parser
+ const_set("REGEXP", Gem::URI::RFC2396_REGEXP)
+ const_set("PATTERN", Gem::URI::RFC2396_REGEXP::PATTERN)
+ end
+
+ Parser.new.regexp.each_pair do |sym, str|
+ remove_const(sym) if const_defined?(sym, false)
+ const_set(sym, str)
end
end
- DEFAULT_PARSER.regexp.each_pair do |sym, str|
- const_set(sym, str)
+ self.parser = RFC3986_PARSER
+
+ def self.const_missing(const) # :nodoc:
+ if const == :REGEXP
+ warn "Gem::URI::REGEXP is obsolete. Use Gem::URI::RFC2396_REGEXP explicitly.", uplevel: 1 if $VERBOSE
+ Gem::URI::RFC2396_REGEXP
+ elsif value = RFC2396_PARSER.regexp[const]
+ warn "Gem::URI::#{const} is obsolete. Use Gem::URI::RFC2396_PARSER.regexp[#{const.inspect}] explicitly.", uplevel: 1 if $VERBOSE
+ value
+ elsif value = RFC2396_Parser.const_get(const)
+ warn "Gem::URI::#{const} is obsolete. Use Gem::URI::RFC2396_Parser::#{const} explicitly.", uplevel: 1 if $VERBOSE
+ value
+ else
+ super
+ end
end
- Ractor.make_shareable(DEFAULT_PARSER) if defined?(Ractor)
module Util # :nodoc:
def make_components_hash(klass, array_hash)
@@ -64,7 +94,41 @@ module Gem::URI
module_function :make_components_hash
end
- module Schemes
+ module Schemes # :nodoc:
+ class << self
+ ReservedChars = ".+-"
+ EscapedChars = "\u01C0\u01C1\u01C2"
+ # Use Lo category chars as escaped chars for TruffleRuby, which
+ # does not allow Symbol categories as identifiers.
+
+ def escape(name)
+ unless name and name.ascii_only?
+ return nil
+ end
+ name.upcase.tr(ReservedChars, EscapedChars)
+ end
+
+ def unescape(name)
+ name.tr(EscapedChars, ReservedChars).encode(Encoding::US_ASCII).upcase
+ end
+
+ def find(name)
+ const_get(name, false) if name and const_defined?(name, false)
+ end
+
+ def register(name, klass)
+ unless scheme = escape(name)
+ raise ArgumentError, "invalid character as scheme - #{name}"
+ end
+ const_set(scheme, klass)
+ end
+
+ def list
+ constants.map { |name|
+ [unescape(name.to_s), const_get(name)]
+ }.to_h
+ end
+ end
end
private_constant :Schemes
@@ -77,7 +141,7 @@ module Gem::URI
# Note that after calling String#upcase on +scheme+, it must be a valid
# constant name.
def self.register_scheme(scheme, klass)
- Schemes.const_set(scheme.to_s.upcase, klass)
+ Schemes.register(scheme, klass)
end
# Returns a hash of the defined schemes:
@@ -95,14 +159,14 @@ module Gem::URI
#
# Related: Gem::URI.register_scheme.
def self.scheme_list
- Schemes.constants.map { |name|
- [name.to_s.upcase, Schemes.const_get(name)]
- }.to_h
+ Schemes.list
end
+ # :stopdoc:
INITIAL_SCHEMES = scheme_list
private_constant :INITIAL_SCHEMES
Ractor.make_shareable(INITIAL_SCHEMES) if defined?(Ractor)
+ # :startdoc:
# Returns a new object constructed from the given +scheme+, +arguments+,
# and +default+:
@@ -121,12 +185,10 @@ module Gem::URI
# # => #<Gem::URI::HTTP foo://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
#
def self.for(scheme, *arguments, default: Generic)
- const_name = scheme.to_s.upcase
+ const_name = Schemes.escape(scheme)
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 ||= Schemes.find(const_name)
uri_class ||= default
return uri_class.new(scheme, *arguments)
@@ -168,7 +230,7 @@ module Gem::URI
# ["fragment", "top"]]
#
def self.split(uri)
- RFC3986_PARSER.split(uri)
+ PARSER.split(uri)
end
# Returns a new \Gem::URI object constructed from the given string +uri+:
@@ -178,11 +240,11 @@ module Gem::URI
# Gem::URI.parse('http://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top')
# # => #<Gem::URI::HTTP http://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
#
- # It's recommended to first ::escape string +uri+
+ # It's recommended to first Gem::URI::RFC2396_PARSER.escape string +uri+
# if it may contain invalid Gem::URI characters.
#
def self.parse(uri)
- RFC3986_PARSER.parse(uri)
+ PARSER.parse(uri)
end
# Merges the given Gem::URI strings +str+
@@ -209,7 +271,7 @@ module Gem::URI
# # => #<Gem::URI::HTTP http://example.com/foo/bar>
#
def self.join(*str)
- RFC3986_PARSER.join(*str)
+ DEFAULT_PARSER.join(*str)
end
#
@@ -238,7 +300,7 @@ module Gem::URI
#
def self.extract(str, schemes = nil, &block) # :nodoc:
warn "Gem::URI.extract is obsolete", uplevel: 1 if $VERBOSE
- DEFAULT_PARSER.extract(str, schemes, &block)
+ PARSER.extract(str, schemes, &block)
end
#
@@ -275,14 +337,14 @@ module Gem::URI
#
def self.regexp(schemes = nil)# :nodoc:
warn "Gem::URI.regexp is obsolete", uplevel: 1 if $VERBOSE
- DEFAULT_PARSER.make_regexp(schemes)
+ PARSER.make_regexp(schemes)
end
TBLENCWWWCOMP_ = {} # :nodoc:
256.times do |i|
TBLENCWWWCOMP_[-i.chr] = -('%%%02X' % i)
end
- TBLENCURICOMP_ = TBLENCWWWCOMP_.dup.freeze
+ TBLENCURICOMP_ = TBLENCWWWCOMP_.dup.freeze # :nodoc:
TBLENCWWWCOMP_[' '] = '+'
TBLENCWWWCOMP_.freeze
TBLDECWWWCOMP_ = {} # :nodoc:
@@ -380,6 +442,8 @@ module Gem::URI
_decode_uri_component(/%\h\h/, str, enc)
end
+ # Returns a string derived from the given string +str+ with
+ # Gem::URI-encoded characters matching +regexp+ according to +table+.
def self._encode_uri_component(regexp, table, str, enc)
str = str.to_s.dup
if str.encoding != Encoding::ASCII_8BIT
@@ -394,6 +458,8 @@ module Gem::URI
end
private_class_method :_encode_uri_component
+ # Returns a string decoding characters matching +regexp+ from the
+ # given \URL-encoded string +str+.
def self._decode_uri_component(regexp, str, enc)
raise ArgumentError, "invalid %-encoding (#{str})" if /%(?!\h\h)/.match?(str)
str.b.gsub(regexp, TBLDECWWWCOMP_).force_encoding(enc)
@@ -401,7 +467,7 @@ module Gem::URI
private_class_method :_decode_uri_component
# Returns a URL-encoded string derived from the given
- # {Enumerable}[https://docs.ruby-lang.org/en/master/Enumerable.html#module-Enumerable-label-Enumerable+in+Ruby+Classes]
+ # {Enumerable}[rdoc-ref:Enumerable@Enumerable+in+Ruby+Classes]
# +enum+.
#
# The result is suitable for use as form data
@@ -470,7 +536,7 @@ module Gem::URI
# each +key+/+value+ pair is converted to one or more fields:
#
# - If +value+ is
- # {Array-convertible}[https://docs.ruby-lang.org/en/master/implicit_conversion_rdoc.html#label-Array-Convertible+Objects],
+ # {Array-convertible}[rdoc-ref:implicit_conversion.rdoc@Array-Convertible+Objects],
# each element +ele+ in +value+ is paired with +key+ to form a field:
#
# name = Gem::URI.encode_www_form_component(key, enc)
@@ -528,7 +594,7 @@ module Gem::URI
# each subarray is a name/value pair (both are strings).
# Each returned string has encoding +enc+,
# and has had invalid characters removed via
- # {String#scrub}[https://docs.ruby-lang.org/en/master/String.html#method-i-scrub].
+ # {String#scrub}[rdoc-ref:String#scrub].
#
# A simple example:
#
@@ -832,6 +898,7 @@ module Gem
# Returns a \Gem::URI object derived from the given +uri+,
# which may be a \Gem::URI string or an existing \Gem::URI object:
#
+ # require 'rubygems/vendor/uri/lib/uri'
# # Returns a new Gem::URI.
# uri = Gem::URI('http://github.com/ruby/ruby')
# # => #<Gem::URI::HTTP http://github.com/ruby/ruby>
@@ -839,6 +906,8 @@ module Gem
# Gem::URI(uri)
# # => #<Gem::URI::HTTP http://github.com/ruby/ruby>
#
+ # You must require 'rubygems/vendor/uri/lib/uri' to use this method.
+ #
def URI(uri)
if uri.is_a?(Gem::URI::Generic)
uri
diff --git a/lib/rubygems/vendor/uri/lib/uri/file.rb b/lib/rubygems/vendor/uri/lib/uri/file.rb
index d419b26055..391c499716 100644
--- a/lib/rubygems/vendor/uri/lib/uri/file.rb
+++ b/lib/rubygems/vendor/uri/lib/uri/file.rb
@@ -47,7 +47,7 @@ module Gem::URI
# :path => '/ruby/src'})
# uri2.to_s # => "file://host.example.com/ruby/src"
#
- # uri3 = Gem::URI::File.build({:path => Gem::URI::escape('/path/my file.txt')})
+ # uri3 = Gem::URI::File.build({:path => Gem::URI::RFC2396_PARSER.escape('/path/my file.txt')})
# uri3.to_s # => "file:///path/my%20file.txt"
#
def self.build(args)
@@ -70,17 +70,17 @@ module Gem::URI
# raise InvalidURIError
def check_userinfo(user)
- raise Gem::URI::InvalidURIError, "can not set userinfo for file Gem::URI"
+ raise Gem::URI::InvalidURIError, "cannot set userinfo for file Gem::URI"
end
# raise InvalidURIError
def check_user(user)
- raise Gem::URI::InvalidURIError, "can not set user for file Gem::URI"
+ raise Gem::URI::InvalidURIError, "cannot set user for file Gem::URI"
end
# raise InvalidURIError
def check_password(user)
- raise Gem::URI::InvalidURIError, "can not set password for file Gem::URI"
+ raise Gem::URI::InvalidURIError, "cannot set password for file Gem::URI"
end
# do nothing
diff --git a/lib/rubygems/vendor/uri/lib/uri/ftp.rb b/lib/rubygems/vendor/uri/lib/uri/ftp.rb
index 100498ffb2..7517813029 100644
--- a/lib/rubygems/vendor/uri/lib/uri/ftp.rb
+++ b/lib/rubygems/vendor/uri/lib/uri/ftp.rb
@@ -17,7 +17,7 @@ module Gem::URI
# This class will be redesigned because of difference of implementations;
# the structure of its path. draft-hoffman-ftp-uri-04 is a draft but it
# is a good summary about the de facto spec.
- # http://tools.ietf.org/html/draft-hoffman-ftp-uri-04
+ # https://datatracker.ietf.org/doc/html/draft-hoffman-ftp-uri-04
#
class FTP < Generic
# A Default port of 21 for Gem::URI::FTP.
diff --git a/lib/rubygems/vendor/uri/lib/uri/generic.rb b/lib/rubygems/vendor/uri/lib/uri/generic.rb
index 72c52aa8ee..d0bc77dfda 100644
--- a/lib/rubygems/vendor/uri/lib/uri/generic.rb
+++ b/lib/rubygems/vendor/uri/lib/uri/generic.rb
@@ -73,7 +73,7 @@ module Gem::URI
#
# At first, tries to create a new Gem::URI::Generic instance using
# Gem::URI::Generic::build. But, if exception Gem::URI::InvalidComponentError is raised,
- # then it does Gem::URI::Escape.escape all Gem::URI components and tries again.
+ # then it does Gem::URI::RFC2396_PARSER.escape all Gem::URI components and tries again.
#
def self.build2(args)
begin
@@ -82,7 +82,7 @@ module Gem::URI
if args.kind_of?(Array)
return self.build(args.collect{|x|
if x.is_a?(String)
- DEFAULT_PARSER.escape(x)
+ Gem::URI::RFC2396_PARSER.escape(x)
else
x
end
@@ -91,7 +91,7 @@ module Gem::URI
tmp = {}
args.each do |key, value|
tmp[key] = if value
- DEFAULT_PARSER.escape(value)
+ Gem::URI::RFC2396_PARSER.escape(value)
else
value
end
@@ -126,9 +126,9 @@ module Gem::URI
end
end
else
- component = self.class.component rescue ::Gem::URI::Generic::COMPONENT
+ component = self.component rescue ::Gem::URI::Generic::COMPONENT
raise ArgumentError,
- "expected Array of or Hash of components of #{self.class} (#{component.join(', ')})"
+ "expected Array of or Hash of components of #{self} (#{component.join(', ')})"
end
tmp << nil
@@ -186,18 +186,18 @@ module Gem::URI
if arg_check
self.scheme = scheme
- self.userinfo = userinfo
self.hostname = host
self.port = port
+ self.userinfo = userinfo
self.path = path
self.query = query
self.opaque = opaque
self.fragment = fragment
else
self.set_scheme(scheme)
- self.set_userinfo(userinfo)
self.set_host(host)
self.set_port(port)
+ self.set_userinfo(userinfo)
self.set_path(path)
self.query = query
self.set_opaque(opaque)
@@ -284,7 +284,7 @@ module Gem::URI
# Returns the parser to be used.
#
- # Unless a Gem::URI::Parser is defined, DEFAULT_PARSER is used.
+ # Unless the +parser+ is defined, DEFAULT_PARSER is used.
#
def parser
if !defined?(@parser) || !@parser
@@ -315,7 +315,7 @@ module Gem::URI
end
#
- # Checks the scheme +v+ component against the Gem::URI::Parser Regexp for :SCHEME.
+ # Checks the scheme +v+ component against the +parser+ Regexp for :SCHEME.
#
def check_scheme(v)
if v && parser.regexp[:SCHEME] !~ v
@@ -385,7 +385,7 @@ module Gem::URI
#
# Checks the user +v+ component for RFC2396 compliance
- # and against the Gem::URI::Parser Regexp for :USERINFO.
+ # and against the +parser+ Regexp for :USERINFO.
#
# Can not have a registry or opaque component defined,
# with a user component defined.
@@ -393,7 +393,7 @@ module Gem::URI
def check_user(v)
if @opaque
raise InvalidURIError,
- "can not set user with opaque"
+ "cannot set user with opaque"
end
return v unless v
@@ -409,7 +409,7 @@ module Gem::URI
#
# Checks the password +v+ component for RFC2396 compliance
- # and against the Gem::URI::Parser Regexp for :USERINFO.
+ # and against the +parser+ Regexp for :USERINFO.
#
# Can not have a registry or opaque component defined,
# with a user component defined.
@@ -417,7 +417,7 @@ module Gem::URI
def check_password(v, user = @user)
if @opaque
raise InvalidURIError,
- "can not set password with opaque"
+ "cannot set password with opaque"
end
return v unless v
@@ -511,7 +511,7 @@ module Gem::URI
user, password = split_userinfo(user)
end
@user = user
- @password = password if password
+ @password = password
[@user, @password]
end
@@ -522,7 +522,7 @@ module Gem::URI
# See also Gem::URI::Generic.user=.
#
def set_user(v)
- set_userinfo(v, @password)
+ set_userinfo(v, nil)
v
end
protected :set_user
@@ -574,6 +574,12 @@ module Gem::URI
@password
end
+ # Returns the authority info (array of user, password, host and
+ # port), if any is set. Or returns +nil+.
+ def authority
+ return @user, @password, @host, @port if @user || @password || @host || @port
+ end
+
# Returns the user component after Gem::URI decoding.
def decoded_user
Gem::URI.decode_uri_component(@user) if @user
@@ -586,7 +592,7 @@ module Gem::URI
#
# Checks the host +v+ component for RFC2396 compliance
- # and against the Gem::URI::Parser Regexp for :HOST.
+ # and against the +parser+ Regexp for :HOST.
#
# Can not have a registry or opaque component defined,
# with a host component defined.
@@ -596,7 +602,7 @@ module Gem::URI
if @opaque
raise InvalidURIError,
- "can not set host with registry or opaque"
+ "cannot set host with registry or opaque"
elsif parser.regexp[:HOST] !~ v
raise InvalidComponentError,
"bad component(expected host component): #{v}"
@@ -615,6 +621,13 @@ module Gem::URI
end
protected :set_host
+ # Protected setter for the authority info (+user+, +password+, +host+
+ # and +port+). If +port+ is +nil+, +default_port+ will be set.
+ #
+ protected def set_authority(user, password, host, port = nil)
+ @user, @password, @host, @port = user, password, host, port || self.default_port
+ end
+
#
# == Args
#
@@ -639,6 +652,7 @@ module Gem::URI
def host=(v)
check_host(v)
set_host(v)
+ set_userinfo(nil)
v
end
@@ -675,7 +689,7 @@ module Gem::URI
#
# Checks the port +v+ component for RFC2396 compliance
- # and against the Gem::URI::Parser Regexp for :PORT.
+ # and against the +parser+ Regexp for :PORT.
#
# Can not have a registry or opaque component defined,
# with a port component defined.
@@ -685,7 +699,7 @@ module Gem::URI
if @opaque
raise InvalidURIError,
- "can not set port with registry or opaque"
+ "cannot set port with registry or opaque"
elsif !v.kind_of?(Integer) && parser.regexp[:PORT] !~ v
raise InvalidComponentError,
"bad component(expected port component): #{v.inspect}"
@@ -729,26 +743,27 @@ module Gem::URI
def port=(v)
check_port(v)
set_port(v)
+ set_userinfo(nil)
port
end
def check_registry(v) # :nodoc:
- raise InvalidURIError, "can not set registry"
+ raise InvalidURIError, "cannot set registry"
end
private :check_registry
- def set_registry(v) #:nodoc:
- raise InvalidURIError, "can not set registry"
+ def set_registry(v) # :nodoc:
+ raise InvalidURIError, "cannot set registry"
end
protected :set_registry
- def registry=(v)
- raise InvalidURIError, "can not set registry"
+ def registry=(v) # :nodoc:
+ raise InvalidURIError, "cannot set registry"
end
#
# Checks the path +v+ component for RFC2396 compliance
- # and against the Gem::URI::Parser Regexp
+ # and against the +parser+ Regexp
# for :ABS_PATH and :REL_PATH.
#
# Can not have a opaque component defined,
@@ -853,7 +868,7 @@ module Gem::URI
#
# Checks the opaque +v+ component for RFC2396 compliance and
- # against the Gem::URI::Parser Regexp for :OPAQUE.
+ # against the +parser+ Regexp for :OPAQUE.
#
# Can not have a host, port, user, or path component defined,
# with an opaque component defined.
@@ -866,7 +881,7 @@ module Gem::URI
# hier_part = ( net_path | abs_path ) [ "?" query ]
if @host || @port || @user || @path # userinfo = @user + ':' + @password
raise InvalidURIError,
- "can not set opaque with host, port, userinfo or path"
+ "cannot set opaque with host, port, userinfo or path"
elsif v && parser.regexp[:OPAQUE] !~ v
raise InvalidComponentError,
"bad component(expected opaque component): #{v}"
@@ -905,7 +920,7 @@ module Gem::URI
end
#
- # Checks the fragment +v+ component against the Gem::URI::Parser Regexp for :FRAGMENT.
+ # Checks the fragment +v+ component against the +parser+ Regexp for :FRAGMENT.
#
#
# == Args
@@ -945,7 +960,7 @@ module Gem::URI
# == Description
#
# Gem::URI has components listed in order of decreasing significance from left to right,
- # see RFC3986 https://tools.ietf.org/html/rfc3986 1.2.3.
+ # see RFC3986 https://www.rfc-editor.org/rfc/rfc3986 1.2.3.
#
# == Usage
#
@@ -1121,7 +1136,7 @@ module Gem::URI
base = self.dup
- authority = rel.userinfo || rel.host || rel.port
+ authority = rel.authority
# RFC2396, Section 5.2, 2)
if (rel.path.nil? || rel.path.empty?) && !authority && !rel.query
@@ -1133,17 +1148,14 @@ module Gem::URI
base.fragment=(nil)
# RFC2396, Section 5.2, 4)
- if !authority
- base.set_path(merge_path(base.path, rel.path)) if base.path && rel.path
- else
- # RFC2396, Section 5.2, 4)
- base.set_path(rel.path) if rel.path
+ if authority
+ base.set_authority(*authority)
+ base.set_path(rel.path)
+ elsif base.path && rel.path
+ base.set_path(merge_path(base.path, rel.path))
end
# RFC2396, Section 5.2, 7)
- base.set_userinfo(rel.userinfo) if rel.userinfo
- base.set_host(rel.host) if rel.host
- base.set_port(rel.port) if rel.port
base.query = rel.query if rel.query
base.fragment=(rel.fragment) if rel.fragment
@@ -1235,7 +1247,7 @@ module Gem::URI
return rel, rel
end
- # you can modify `rel', but can not `oth'.
+ # you can modify `rel', but cannot `oth'.
return oth, rel
end
private :route_from0
@@ -1260,7 +1272,7 @@ module Gem::URI
# #=> #<Gem::URI::Generic /main.rbx?page=1>
#
def route_from(oth)
- # you can modify `rel', but can not `oth'.
+ # you can modify `rel', but cannot `oth'.
begin
oth, rel = route_from0(oth)
rescue
@@ -1364,6 +1376,9 @@ module Gem::URI
str << ':'
str << @port.to_s
end
+ if (@host || @port) && !@path.empty? && !@path.start_with?('/')
+ str << '/'
+ end
str << @path
if @query
str << '?'
@@ -1389,29 +1404,18 @@ module Gem::URI
end
end
+ # Returns the hash value.
def hash
self.component_ary.hash
end
+ # Compares with _oth_ for Hash.
def eql?(oth)
self.class == oth.class &&
parser == oth.parser &&
self.component_ary.eql?(oth.component_ary)
end
-=begin
-
---- Gem::URI::Generic#===(oth)
-
-=end
-# def ===(oth)
-# raise NotImplementedError
-# end
-
-=begin
-=end
-
-
# Returns an Array of the components defined from the COMPONENT Array.
def component_ary
component.collect do |x|
@@ -1448,7 +1452,7 @@ module Gem::URI
end
end
- def inspect
+ def inspect # :nodoc:
"#<#{self.class} #{self}>"
end
@@ -1536,7 +1540,7 @@ module Gem::URI
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
+ warn 'The environment variable HTTP_PROXY is discouraged. Please use http_proxy instead.', uplevel: 1
end
end
end
diff --git a/lib/rubygems/vendor/uri/lib/uri/http.rb b/lib/rubygems/vendor/uri/lib/uri/http.rb
index bef43490a3..99c78358ac 100644
--- a/lib/rubygems/vendor/uri/lib/uri/http.rb
+++ b/lib/rubygems/vendor/uri/lib/uri/http.rb
@@ -61,6 +61,18 @@ module Gem::URI
super(tmp)
end
+ # Do not allow empty host names, as they are not allowed by RFC 3986.
+ def check_host(v)
+ ret = super
+
+ if ret && v.empty?
+ raise InvalidComponentError,
+ "bad component(expected host component): #{v}"
+ end
+
+ ret
+ end
+
#
# == Description
#
@@ -85,7 +97,7 @@ module Gem::URI
# == Description
#
# Returns the authority for an HTTP uri, as defined in
- # https://datatracker.ietf.org/doc/html/rfc3986/#section-3.2.
+ # https://www.rfc-editor.org/rfc/rfc3986#section-3.2.
#
#
# Example:
@@ -106,7 +118,7 @@ module Gem::URI
# == Description
#
# Returns the origin for an HTTP uri, as defined in
- # https://datatracker.ietf.org/doc/html/rfc6454.
+ # https://www.rfc-editor.org/rfc/rfc6454.
#
#
# Example:
diff --git a/lib/rubygems/vendor/uri/lib/uri/rfc2396_parser.rb b/lib/rubygems/vendor/uri/lib/uri/rfc2396_parser.rb
index 735a269f2c..2bb4181649 100644
--- a/lib/rubygems/vendor/uri/lib/uri/rfc2396_parser.rb
+++ b/lib/rubygems/vendor/uri/lib/uri/rfc2396_parser.rb
@@ -67,7 +67,7 @@ module Gem::URI
#
# == Synopsis
#
- # Gem::URI::Parser.new([opts])
+ # Gem::URI::RFC2396_Parser.new([opts])
#
# == Args
#
@@ -86,7 +86,7 @@ module Gem::URI
#
# == Examples
#
- # p = Gem::URI::Parser.new(:ESCAPED => "(?:%[a-fA-F0-9]{2}|%u[a-fA-F0-9]{4})")
+ # p = Gem::URI::RFC2396_Parser.new(:ESCAPED => "(?:%[a-fA-F0-9]{2}|%u[a-fA-F0-9]{4})")
# u = p.parse("http://example.jp/%uABCD") #=> #<Gem::URI::HTTP http://example.jp/%uABCD>
# Gem::URI.parse(u.to_s) #=> raises Gem::URI::InvalidURIError
#
@@ -108,12 +108,12 @@ module Gem::URI
# The Hash of patterns.
#
- # See also Gem::URI::Parser.initialize_pattern.
+ # See also #initialize_pattern.
attr_reader :pattern
# The Hash of Regexp.
#
- # See also Gem::URI::Parser.initialize_regexp.
+ # See also #initialize_regexp.
attr_reader :regexp
# Returns a split Gem::URI against +regexp[:ABS_URI]+.
@@ -140,11 +140,11 @@ module Gem::URI
if !scheme
raise InvalidURIError,
- "bad Gem::URI(absolute but no scheme): #{uri}"
+ "bad Gem::URI (absolute but no scheme): #{uri}"
end
if !opaque && (!path && (!host && !registry))
raise InvalidURIError,
- "bad Gem::URI(absolute but no path): #{uri}"
+ "bad Gem::URI (absolute but no path): #{uri}"
end
when @regexp[:REL_URI]
@@ -173,7 +173,7 @@ module Gem::URI
# server = [ [ userinfo "@" ] hostport ]
else
- raise InvalidURIError, "bad Gem::URI(is not Gem::URI?): #{uri}"
+ raise InvalidURIError, "bad Gem::URI (is not Gem::URI?): #{uri}"
end
path = '' if !path && !opaque # (see RFC2396 Section 5.2)
@@ -202,8 +202,7 @@ module Gem::URI
#
# == Usage
#
- # p = Gem::URI::Parser.new
- # p.parse("ldap://ldap.example.com/dc=example?user=john")
+ # Gem::URI::RFC2396_PARSER.parse("ldap://ldap.example.com/dc=example?user=john")
# #=> #<Gem::URI::LDAP ldap://ldap.example.com/dc=example?user=john>
#
def parse(uri)
@@ -244,7 +243,7 @@ module Gem::URI
# If no +block+ given, then returns the result,
# else it calls +block+ for each element in result.
#
- # See also Gem::URI::Parser.make_regexp.
+ # See also #make_regexp.
#
def extract(str, schemes = nil)
if block_given?
@@ -263,7 +262,7 @@ module Gem::URI
unless schemes
@regexp[:ABS_URI_REF]
else
- /(?=#{Regexp.union(*schemes)}:)#{@pattern[:X_ABS_URI]}/x
+ /(?=(?i:#{Regexp.union(*schemes).source}):)#{@pattern[:X_ABS_URI]}/x
end
end
@@ -321,14 +320,14 @@ module Gem::URI
str.gsub(escaped) { [$&[1, 2]].pack('H2').force_encoding(enc) }
end
- @@to_s = Kernel.instance_method(:to_s)
- if @@to_s.respond_to?(:bind_call)
- def inspect
- @@to_s.bind_call(self)
+ TO_S = Kernel.instance_method(:to_s) # :nodoc:
+ if TO_S.respond_to?(:bind_call)
+ def inspect # :nodoc:
+ TO_S.bind_call(self)
end
else
- def inspect
- @@to_s.bind(self).call
+ def inspect # :nodoc:
+ TO_S.bind(self).call
end
end
@@ -524,6 +523,8 @@ module Gem::URI
ret
end
+ # Returns +uri+ as-is if it is Gem::URI, or convert it to Gem::URI if it is
+ # a String.
def convert_to_uri(uri)
if uri.is_a?(Gem::URI::Generic)
uri
@@ -536,4 +537,11 @@ module Gem::URI
end
end # class Parser
+
+ # Backward compatibility for Gem::URI::REGEXP::PATTERN::*
+ RFC2396_Parser.new.pattern.each_pair do |sym, str|
+ unless RFC2396_REGEXP::PATTERN.const_defined?(sym, false)
+ RFC2396_REGEXP::PATTERN.const_set(sym, str)
+ end
+ end
end # module Gem::URI
diff --git a/lib/rubygems/vendor/uri/lib/uri/rfc3986_parser.rb b/lib/rubygems/vendor/uri/lib/uri/rfc3986_parser.rb
index 728bb55674..3b6961abf6 100644
--- a/lib/rubygems/vendor/uri/lib/uri/rfc3986_parser.rb
+++ b/lib/rubygems/vendor/uri/lib/uri/rfc3986_parser.rb
@@ -78,7 +78,7 @@ module Gem::URI
begin
uri = uri.to_str
rescue NoMethodError
- raise InvalidURIError, "bad Gem::URI(is not Gem::URI?): #{uri.inspect}"
+ raise InvalidURIError, "bad Gem::URI (is not Gem::URI?): #{uri.inspect}"
end
uri.ascii_only? or
raise InvalidURIError, "Gem::URI must be ascii only #{uri.dump}"
@@ -127,7 +127,7 @@ module Gem::URI
m["fragment"]
]
else
- raise InvalidURIError, "bad Gem::URI(is not Gem::URI?): #{uri.inspect}"
+ raise InvalidURIError, "bad Gem::URI (is not Gem::URI?): #{uri.inspect}"
end
end
@@ -135,12 +135,35 @@ module Gem::URI
Gem::URI.for(*self.split(uri), self)
end
-
def join(*uris) # :nodoc:
uris[0] = convert_to_uri(uris[0])
uris.inject :merge
end
+ # Compatibility for RFC2396 parser
+ def extract(str, schemes = nil, &block) # :nodoc:
+ warn "Gem::URI::RFC3986_PARSER.extract is obsolete. Use Gem::URI::RFC2396_PARSER.extract explicitly.", uplevel: 1 if $VERBOSE
+ RFC2396_PARSER.extract(str, schemes, &block)
+ end
+
+ # Compatibility for RFC2396 parser
+ def make_regexp(schemes = nil) # :nodoc:
+ warn "Gem::URI::RFC3986_PARSER.make_regexp is obsolete. Use Gem::URI::RFC2396_PARSER.make_regexp explicitly.", uplevel: 1 if $VERBOSE
+ RFC2396_PARSER.make_regexp(schemes)
+ end
+
+ # Compatibility for RFC2396 parser
+ def escape(str, unsafe = nil) # :nodoc:
+ warn "Gem::URI::RFC3986_PARSER.escape is obsolete. Use Gem::URI::RFC2396_PARSER.escape explicitly.", uplevel: 1 if $VERBOSE
+ unsafe ? RFC2396_PARSER.escape(str, unsafe) : RFC2396_PARSER.escape(str)
+ end
+
+ # Compatibility for RFC2396 parser
+ def unescape(str, escaped = nil) # :nodoc:
+ warn "Gem::URI::RFC3986_PARSER.unescape is obsolete. Use Gem::URI::RFC2396_PARSER.unescape explicitly.", uplevel: 1 if $VERBOSE
+ escaped ? RFC2396_PARSER.unescape(str, escaped) : RFC2396_PARSER.unescape(str)
+ end
+
@@to_s = Kernel.instance_method(:to_s)
if @@to_s.respond_to?(:bind_call)
def inspect
diff --git a/lib/rubygems/vendor/uri/lib/uri/version.rb b/lib/rubygems/vendor/uri/lib/uri/version.rb
index 3c80c334d4..7ee577887b 100644
--- a/lib/rubygems/vendor/uri/lib/uri/version.rb
+++ b/lib/rubygems/vendor/uri/lib/uri/version.rb
@@ -1,6 +1,6 @@
module Gem::URI
# :stopdoc:
- VERSION_CODE = '001300'.freeze
- VERSION = VERSION_CODE.scan(/../).collect{|n| n.to_i}.join('.').freeze
+ VERSION = '1.1.1'.freeze
+ VERSION_CODE = VERSION.split('.').map{|s| s.rjust(2, '0')}.join.freeze
# :startdoc:
end
diff --git a/lib/rubygems/vendored_securerandom.rb b/lib/rubygems/vendored_securerandom.rb
new file mode 100644
index 0000000000..859b6d7d7a
--- /dev/null
+++ b/lib/rubygems/vendored_securerandom.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+require_relative "vendor/securerandom/lib/securerandom"
diff --git a/lib/rubygems/version.rb b/lib/rubygems/version.rb
index e174d8ad95..90fe1b3c24 100644
--- a/lib/rubygems/version.rb
+++ b/lib/rubygems/version.rb
@@ -171,9 +171,7 @@ class Gem::Version
# True if the +version+ string matches RubyGems' requirements.
def self.correct?(version)
- nil_versions_are_discouraged! if version.nil?
-
- ANCHORED_VERSION_PATTERN.match?(version.to_s)
+ version.nil? || ANCHORED_VERSION_PATTERN.match?(version.to_s)
end
##
@@ -182,15 +180,10 @@ class Gem::Version
#
# ver1 = Version.create('1.3.17') # -> (Version object)
# ver2 = Version.create(ver1) # -> (ver1)
- # ver3 = Version.create(nil) # -> nil
def self.create(input)
if self === input # check yourself before you wreck yourself
input
- elsif input.nil?
- nil_versions_are_discouraged!
-
- nil
else
new input
end
@@ -206,14 +199,6 @@ class Gem::Version
@@all[version] ||= super
end
- def self.nil_versions_are_discouraged!
- unless Gem::Deprecate.skip
- warn "nil versions are discouraged and will be deprecated in Rubygems 4"
- end
- end
-
- private_class_method :nil_versions_are_discouraged!
-
##
# Constructs a Version from the +version+ string. A version string is a
# series of digits or ASCII letters separated by dots.
@@ -224,7 +209,7 @@ class Gem::Version
end
# If version is an empty string convert it to 0
- version = 0 if version.is_a?(String) && /\A\s*\Z/.match?(version)
+ version = 0 if version.nil? || (version.is_a?(String) && /\A\s*\Z/.match?(version))
@version = version.to_s
@@ -288,7 +273,10 @@ class Gem::Version
# 1.3.5 and earlier) compatibility.
def marshal_load(array)
- initialize array[0]
+ string = array[0]
+ raise TypeError, "wrong version string" unless string.is_a?(String)
+
+ initialize string
end
def yaml_initialize(tag, map) # :nodoc:
@@ -297,10 +285,6 @@ class Gem::Version
@hash = nil
end
- def to_yaml_properties # :nodoc:
- ["@version"]
- end
-
def encode_with(coder) # :nodoc:
coder.add "version", @version
end
@@ -355,11 +339,14 @@ class Gem::Version
##
# 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
- # <tt>Gem::Version</tt> or a valid version String return +nil+.
+ # one. +other+ must be an instance of Gem::Version, comparing with
+ # other types may raise an exception.
def <=>(other)
- return self <=> self.class.new(other) if (String === other) && self.class.correct?(other)
+ if String === other
+ return unless self.class.correct?(other)
+ return self <=> self.class.new(other)
+ end
return unless Gem::Version === other
return 0 if @version == other.version || canonical_segments == other.canonical_segments
@@ -369,13 +356,13 @@ class Gem::Version
lhsize = lhsegments.size
rhsize = rhsegments.size
- limit = (lhsize > rhsize ? lhsize : rhsize) - 1
+ limit = (lhsize > rhsize ? rhsize : lhsize)
i = 0
- while i <= limit
- lhs = lhsegments[i] || 0
- rhs = rhsegments[i] || 0
+ while i < limit
+ lhs = lhsegments[i]
+ rhs = rhsegments[i]
i += 1
next if lhs == rhs
@@ -385,6 +372,24 @@ class Gem::Version
return lhs <=> rhs
end
+ lhs = lhsegments[i]
+
+ if lhs.nil?
+ rhs = rhsegments[i]
+
+ while i < rhsize
+ return 1 if String === rhs
+ return -1 unless rhs.zero?
+ rhs = rhsegments[i += 1]
+ end
+ else
+ while i < lhsize
+ return -1 if String === lhs
+ return 1 unless lhs.zero?
+ lhs = lhsegments[i += 1]
+ end
+ end
+
0
end
diff --git a/lib/rubygems/win_platform.rb b/lib/rubygems/win_platform.rb
new file mode 100644
index 0000000000..78e968fe49
--- /dev/null
+++ b/lib/rubygems/win_platform.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require "rbconfig"
+
+module Gem
+ ##
+ # An Array of Regexps that match windows Ruby platforms.
+
+ WIN_PATTERNS = [
+ /bccwin/i,
+ /cygwin/i,
+ /djgpp/i,
+ /mingw/i,
+ /mswin/i,
+ /wince/i,
+ ].freeze
+
+ @@win_platform = nil
+
+ ##
+ # 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 }.nil?
+ end
+
+ @@win_platform
+ end
+end
diff --git a/lib/rubygems/yaml_serializer.rb b/lib/rubygems/yaml_serializer.rb
index 128becc1ce..f89004f32a 100644
--- a/lib/rubygems/yaml_serializer.rb
+++ b/lib/rubygems/yaml_serializer.rb
@@ -41,7 +41,7 @@ module Gem
HASH_REGEX = /
^
([ ]*) # indentations
- (.+) # key
+ ([^#]+) # key excludes comment char '#'
(?::(?=(?:\s|$))) # : (without the lookahead the #key includes this when : is present in value)
[ ]?
(['"]?) # optional opening quote
@@ -60,7 +60,6 @@ module Gem
indent, key, quote, val = match.captures
val = strip_comment(val)
- convert_to_backward_compatible_key!(key)
depth = indent.size / 2
if quote.empty? && val.empty?
new_hash = {}
@@ -92,14 +91,8 @@ module Gem
end
end
- # for settings' keys
- def convert_to_backward_compatible_key!(key)
- key << "/" if /https?:/i.match?(key) && !%r{/\Z}.match?(key)
- key.gsub!(".", "__")
- end
-
class << self
- private :dump_hash, :convert_to_backward_compatible_key!
+ private :dump_hash
end
end
end
diff --git a/lib/securerandom.gemspec b/lib/securerandom.gemspec
index 0b023486a6..fe46c11013 100644
--- a/lib/securerandom.gemspec
+++ b/lib/securerandom.gemspec
@@ -14,9 +14,10 @@ Gem::Specification.new do |spec|
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.required_ruby_version = Gem::Requirement.new(">= 3.1.0")
spec.licenses = ["Ruby", "BSD-2-Clause"]
+ spec.metadata["changelog_uri"] = spec.homepage + "/releases"
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
diff --git a/lib/securerandom.rb b/lib/securerandom.rb
index 81757f3100..6079fdb5c4 100644
--- a/lib/securerandom.rb
+++ b/lib/securerandom.rb
@@ -41,7 +41,7 @@ require 'random/formatter'
module SecureRandom
# The version
- VERSION = "0.3.1"
+ VERSION = "0.4.1"
class << self
# Returns a random binary string containing +size+ bytes.
@@ -51,6 +51,12 @@ module SecureRandom
return gen_random(n)
end
+ # Compatibility methods for Ruby 3.2, we can remove this after dropping to support Ruby 3.2
+ def alphanumeric(n = nil, chars: ALPHANUMERIC)
+ n = 16 if n.nil?
+ choose(chars, n)
+ end if RUBY_VERSION < '3.3'
+
private
# :stopdoc:
diff --git a/lib/set.rb b/lib/set.rb
deleted file mode 100644
index a0954a31d1..0000000000
--- a/lib/set.rb
+++ /dev/null
@@ -1,852 +0,0 @@
-# frozen_string_literal: true
-# :markup: markdown
-#
-# set.rb - defines the Set class
-#
-# Copyright (c) 2002-2023 Akinori MUSHA <knu@iDaemons.org>
-#
-# Documentation by Akinori MUSHA and Gavin Sinclair.
-#
-# All rights reserved. You can redistribute and/or modify it under the same
-# terms as Ruby.
-
-
-##
-# This library provides the Set class, which implements a collection
-# of unordered values with no duplicates. It is a hybrid of Array's
-# intuitive inter-operation facilities and Hash's fast lookup.
-#
-# The method `to_set` is added to Enumerable for convenience.
-#
-# 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.
-#
-# Set uses Hash as storage, so you must note the following points:
-#
-# * Equality of elements is determined according to Object#eql? and
-# Object#hash. Use Set#compare_by_identity to make a set compare
-# its elements by their identity.
-# * Set assumes that the identity of each element does not change
-# while it is stored. Modifying an element of a set will render the
-# set to an unreliable state.
-# * 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. 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] #=> #<Set: {1, 2}>
-# s2 = [1, 2].to_set #=> #<Set: {1, 2}>
-# s1 == s2 #=> true
-# s1.add("foo") #=> #<Set: {1, 2, "foo"}>
-# s1.merge([2, 6]) #=> #<Set: {1, 2, "foo", 6}>
-# s1.subset?(s2) #=> false
-# s2.subset?(s1) #=> true
-# ```
-#
-# ## Contact
-#
-# - Akinori MUSHA <<knu@iDaemons.org>> (current maintainer)
-#
-# ## What's Here
-#
-# First, what's elsewhere. \Class \Set:
-#
-# - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
-# - Includes {module Enumerable}[rdoc-ref:Enumerable@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:
-# Merges the elements of each given enumerable 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
- VERSION = "1.1.0"
-
- include Enumerable
-
- # Creates a new set containing the given objects.
- #
- # Set[1, 2] # => #<Set: {1, 2}>
- # Set[1, 2, 1] # => #<Set: {1, 2}>
- # Set[1, 'c', :s] # => #<Set: {1, "c", :s}>
- def self.[](*ary)
- new(ary)
- end
-
- # Creates a new set containing the elements of the given enumerable
- # object.
- #
- # If a block is given, the elements of enum are preprocessed by the
- # given block.
- #
- # Set.new([1, 2]) #=> #<Set: {1, 2}>
- # Set.new([1, 2, 1]) #=> #<Set: {1, 2}>
- # Set.new([1, 'c', :s]) #=> #<Set: {1, "c", :s}>
- # Set.new(1..5) #=> #<Set: {1, 2, 3, 4, 5}>
- # Set.new([1, 2, 3]) { |x| x * x } #=> #<Set: {1, 4, 9}>
- def initialize(enum = nil, &block) # :yields: o
- @hash ||= Hash.new(false)
-
- enum.nil? and return
-
- if block
- do_with_enum(enum) { |o| add(block[o]) }
- else
- merge(enum)
- end
- end
-
- # Makes the set compare its elements by their identity and returns
- # self. This method may not be supported by all subclasses of Set.
- def compare_by_identity
- if @hash.respond_to?(:compare_by_identity)
- @hash.compare_by_identity
- self
- else
- raise NotImplementedError, "#{self.class.name}\##{__method__} is not implemented"
- end
- end
-
- # Returns true if the set will compare its elements by their
- # identity. Also see Set#compare_by_identity.
- def compare_by_identity?
- @hash.respond_to?(:compare_by_identity?) && @hash.compare_by_identity?
- end
-
- def do_with_enum(enum, &block) # :nodoc:
- if enum.respond_to?(:each_entry)
- enum.each_entry(&block) if block
- elsif enum.respond_to?(:each)
- enum.each(&block) if block
- else
- raise ArgumentError, "value must be enumerable"
- end
- end
- private :do_with_enum
-
- # Dup internal hash.
- def initialize_dup(orig)
- super
- @hash = orig.instance_variable_get(:@hash).dup
- end
-
- # Clone internal hash.
- def initialize_clone(orig, **options)
- super
- @hash = orig.instance_variable_get(:@hash).clone(**options)
- end
-
- def freeze # :nodoc:
- @hash.freeze
- super
- end
-
- # Returns the number of elements.
- def size
- @hash.size
- end
- alias length size
-
- # Returns true if the set contains no elements.
- def empty?
- @hash.empty?
- end
-
- # Removes all elements and returns self.
- #
- # set = Set[1, 'c', :s] #=> #<Set: {1, "c", :s}>
- # set.clear #=> #<Set: {}>
- # set #=> #<Set: {}>
- def clear
- @hash.clear
- self
- end
-
- # Replaces the contents of the set with the contents of the given
- # enumerable object and returns self.
- #
- # set = Set[1, 'c', :s] #=> #<Set: {1, "c", :s}>
- # set.replace([1, 2]) #=> #<Set: {1, 2}>
- # set #=> #<Set: {1, 2}>
- def replace(enum)
- if enum.instance_of?(self.class)
- @hash.replace(enum.instance_variable_get(:@hash))
- self
- else
- do_with_enum(enum) # make sure enum is enumerable before calling clear
- clear
- merge(enum)
- end
- end
-
- # Converts the set to an array. The order of elements is uncertain.
- #
- # Set[1, 2].to_a #=> [1, 2]
- # Set[1, 'c', :s].to_a #=> [1, "c", :s]
- def to_a
- @hash.keys
- end
-
- # Returns self if no arguments are given. Otherwise, converts the
- # set to another with `klass.new(self, *args, &block)`.
- #
- # 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?
- klass.new(self, *args, &block)
- end
-
- def flatten_merge(set, seen = Set.new) # :nodoc:
- set.each { |e|
- if e.is_a?(Set)
- if seen.include?(e_id = e.object_id)
- raise ArgumentError, "tried to flatten recursive Set"
- end
-
- seen.add(e_id)
- flatten_merge(e, seen)
- seen.delete(e_id)
- else
- add(e)
- end
- }
-
- self
- end
- protected :flatten_merge
-
- # Returns a new set that is a copy of the set, flattening each
- # containing set recursively.
- def flatten
- self.class.new.flatten_merge(self)
- end
-
- # Equivalent to Set#flatten, but replaces the receiver with the
- # result in place. Returns nil if no modifications were made.
- def flatten!
- replace(flatten()) if any?(Set)
- end
-
- # Returns true if the set contains the given object.
- #
- # Note that <code>include?</code> and <code>member?</code> do not test member
- # equality using <code>==</code> as do other Enumerables.
- #
- # See also Enumerable#include?
- def include?(o)
- @hash[o]
- end
- alias member? include?
-
- # Returns true if the set is a superset of the given set.
- def superset?(set)
- case
- when set.instance_of?(self.class) && @hash.respond_to?(:>=)
- @hash >= set.instance_variable_get(:@hash)
- when set.is_a?(Set)
- size >= set.size && set.all?(self)
- else
- raise ArgumentError, "value must be a set"
- end
- end
- alias >= superset?
-
- # Returns true if the set is a proper superset of the given set.
- def proper_superset?(set)
- case
- when set.instance_of?(self.class) && @hash.respond_to?(:>)
- @hash > set.instance_variable_get(:@hash)
- when set.is_a?(Set)
- size > set.size && set.all?(self)
- else
- raise ArgumentError, "value must be a set"
- end
- end
- alias > proper_superset?
-
- # Returns true if the set is a subset of the given set.
- def subset?(set)
- case
- when set.instance_of?(self.class) && @hash.respond_to?(:<=)
- @hash <= set.instance_variable_get(:@hash)
- when set.is_a?(Set)
- size <= set.size && all?(set)
- else
- raise ArgumentError, "value must be a set"
- end
- end
- alias <= subset?
-
- # Returns true if the set is a proper subset of the given set.
- def proper_subset?(set)
- case
- when set.instance_of?(self.class) && @hash.respond_to?(:<)
- @hash < set.instance_variable_get(:@hash)
- when set.is_a?(Set)
- size < set.size && all?(set)
- else
- raise ArgumentError, "value must be a set"
- end
- end
- alias < proper_subset?
-
- # 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? 4..5 #=> false
- # Set[1, 2, 3].intersect? [3, 4] #=> true
- def intersect?(set)
- case set
- when Set
- if size < set.size
- any?(set)
- else
- set.any?(self)
- end
- when Enumerable
- set.any?(self)
- else
- raise ArgumentError, "value must be enumerable"
- end
- end
-
- # 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? [3, 4] #=> false
- # Set[1, 2, 3].disjoint? 4..5 #=> true
- def disjoint?(set)
- !intersect?(set)
- end
-
- # Calls the given block once for each element in the set, passing
- # the element as parameter. Returns an enumerator if no block is
- # given.
- def each(&block)
- block_given? or return enum_for(__method__) { size }
- @hash.each_key(&block)
- self
- end
-
- # Adds the given object to the set and returns self. Use `merge` to
- # add many elements at once.
- #
- # Set[1, 2].add(3) #=> #<Set: {1, 2, 3}>
- # Set[1, 2].add([3, 4]) #=> #<Set: {1, 2, [3, 4]}>
- # Set[1, 2].add(2) #=> #<Set: {1, 2}>
- def add(o)
- @hash[o] = true
- self
- end
- alias << add
-
- # Adds the given object to the set and returns self. If the
- # object is already in the set, returns nil.
- #
- # Set[1, 2].add?(3) #=> #<Set: {1, 2, 3}>
- # Set[1, 2].add?([3, 4]) #=> #<Set: {1, 2, [3, 4]}>
- # Set[1, 2].add?(2) #=> nil
- 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.
- def delete(o)
- @hash.delete(o)
- self
- end
-
- # Deletes the given object from the set and returns self. If the
- # object is not in the set, returns nil.
- def delete?(o)
- delete(o) if include?(o)
- end
-
- # Deletes every element of the set for which block evaluates to
- # true, and returns self. Returns an enumerator if no block is
- # given.
- def delete_if
- block_given? or return enum_for(__method__) { size }
- # @hash.delete_if should be faster, but using it breaks the order
- # of enumeration in subclasses.
- select { |o| yield o }.each { |o| @hash.delete(o) }
- self
- end
-
- # Deletes every element of the set for which block evaluates to
- # false, and returns self. Returns an enumerator if no block is
- # given.
- def keep_if
- block_given? or return enum_for(__method__) { size }
- # @hash.keep_if should be faster, but using it breaks the order of
- # enumeration in subclasses.
- reject { |o| yield o }.each { |o| @hash.delete(o) }
- self
- end
-
- # 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 }
- set = self.class.new
- each { |o| set << yield(o) }
- replace(set)
- end
- alias map! collect!
-
- # Equivalent to Set#delete_if, but returns nil if no changes were
- # made. Returns an enumerator if no block is given.
- def reject!(&block)
- block_given? or return enum_for(__method__) { size }
- n = size
- delete_if(&block)
- self if size != n
- end
-
- # Equivalent to Set#keep_if, but returns nil if no changes were
- # made. Returns an enumerator if no block is given.
- def select!(&block)
- block_given? or return enum_for(__method__) { size }
- n = size
- keep_if(&block)
- self if size != n
- end
-
- # Equivalent to Set#select!
- alias filter! select!
-
- # Merges the elements of the given enumerable objects to the set and
- # returns self.
- def merge(*enums, **nil)
- enums.each do |enum|
- if enum.instance_of?(self.class)
- @hash.update(enum.instance_variable_get(:@hash))
- else
- do_with_enum(enum) { |o| add(o) }
- end
- end
-
- self
- end
-
- # Deletes every element that appears in the given enumerable object
- # and returns self.
- def subtract(enum)
- do_with_enum(enum) { |o| delete(o) }
- self
- end
-
- # Returns a new set built by merging the set and the elements of the
- # given enumerable object.
- #
- # Set[1, 2, 3] | Set[2, 4, 5] #=> #<Set: {1, 2, 3, 4, 5}>
- # Set[1, 5, 'z'] | (1..6) #=> #<Set: {1, 5, "z", 2, 3, 4, 6}>
- def |(enum)
- dup.merge(enum)
- end
- alias + |
- alias union |
-
- # Returns a new set built by duplicating the set, removing every
- # element that appears in the given enumerable object.
- #
- # Set[1, 3, 5] - Set[1, 5] #=> #<Set: {3}>
- # Set['a', 'b', 'z'] - ['a', 'c'] #=> #<Set: {"b", "z"}>
- def -(enum)
- dup.subtract(enum)
- end
- alias difference -
-
- # Returns a new set containing elements common to the set and the
- # given enumerable object.
- #
- # Set[1, 3, 5] & Set[3, 2, 1] #=> #<Set: {3, 1}>
- # Set['a', 'b', 'z'] & ['a', 'b', 'c'] #=> #<Set: {"a", "b"}>
- def &(enum)
- n = self.class.new
- 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))`.
- #
- # Set[1, 2] ^ Set[2, 3] #=> #<Set: {3, 1}>
- # Set[1, 'b', 'c'] ^ ['b', 'd'] #=> #<Set: {"d", 1, "c"}>
- def ^(enum)
- n = Set.new(enum)
- each { |o| n.add(o) unless n.delete?(o) }
- n
- end
-
- # Returns true if two sets are equal. The equality of each couple
- # of elements is defined according to Object#eql?.
- #
- # Set[1, 2] == Set[2, 1] #=> true
- # Set[1, 3, 5] == Set[1, 5] #=> false
- # Set['a', 'b', 'c'] == Set['a', 'c', 'b'] #=> true
- # Set['a', 'b', 'c'] == ['a', 'c', 'b'] #=> false
- def ==(other)
- if self.equal?(other)
- true
- elsif other.instance_of?(self.class)
- @hash == other.instance_variable_get(:@hash)
- elsif other.is_a?(Set) && self.size == other.size
- other.all? { |o| @hash.include?(o) }
- else
- false
- end
- end
-
- def hash # :nodoc:
- @hash.hash
- end
-
- def eql?(o) # :nodoc:
- return false unless o.is_a?(Set)
- @hash.eql?(o.instance_variable_get(:@hash))
- end
-
- # Resets the internal state after modification to existing elements
- # and returns self.
- #
- # Elements will be reindexed and deduplicated.
- def reset
- if @hash.respond_to?(:rehash)
- @hash.rehash # This should perform frozenness check.
- else
- raise FrozenError, "can't modify frozen #{self.class.name}" if frozen?
- end
- self
- end
-
- # Returns true if the given object is a member of the set,
- # and false otherwise.
- #
- # Used in case statements:
- #
- # require 'set'
- #
- # 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
- #
- alias === include?
-
- # Classifies the set by the return value of the given block and
- # returns a hash of {value => set of elements} pairs. The block is
- # 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=>#<Set: {"a.rb", "b.rb"}>,
- # # 2001=>#<Set: {"c.rb", "d.rb", "e.rb"}>,
- # # 2002=>#<Set: {"f.rb"}>}
- #
- # Returns an enumerator if no block is given.
- def classify # :yields: o
- block_given? or return enum_for(__method__) { size }
-
- h = {}
-
- each { |i|
- (h[yield(i)] ||= self.class.new).add(i)
- }
-
- h
- end
-
- # Divides the set into a set of subsets according to the commonality
- # defined by the given block.
- #
- # If the arity of the block is 2, elements o1 and o2 are in common
- # 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 #=> #<Set: {#<Set: {1}>,
- # # #<Set: {11, 9, 10}>,
- # # #<Set: {3, 4}>,
- # # #<Set: {6}>}>
- #
- # Returns an enumerator if no block is given.
- def divide(&func)
- func or return enum_for(__method__) { size }
-
- if func.arity == 2
- require 'tsort'
-
- class << dig = {} # :nodoc:
- include TSort
-
- alias tsort_each_node each_key
- def tsort_each_child(node, &block)
- fetch(node).each(&block)
- end
- end
-
- each { |u|
- dig[u] = a = []
- each{ |v| func.call(u, v) and a << v }
- }
-
- set = Set.new()
- dig.each_strongly_connected_component { |css|
- set.add(self.class.new(css))
- }
- set
- else
- Set.new(classify(&func).values)
- 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
- # set ("#<Set: {element1, element2, ...}>").
- def inspect
- ids = (Thread.current[InspectKey] ||= [])
-
- if ids.include?(object_id)
- return sprintf('#<%s: {...}>', self.class.name)
- end
-
- ids << object_id
- begin
- return sprintf('#<%s: {%s}>', self.class, to_a.inspect[1..-2])
- ensure
- ids.pop
- end
- end
-
- alias to_s inspect
-
- def pretty_print(pp) # :nodoc:
- pp.group(1, sprintf('#<%s:', self.class.name), '>') {
- pp.breakable
- pp.group(1, '{', '}') {
- pp.seplist(self) { |o|
- pp.pp o
- }
- }
- }
- end
-
- def pretty_print_cycle(pp) # :nodoc:
- pp.text sprintf('#<%s: {%s}>', self.class.name, empty? ? '' : '...')
- end
-end
-
-module Enumerable
- # Makes a set from the enumerable object with given arguments.
- # Needs to `require "set"` to use this method.
- def to_set(klass = Set, *args, &block)
- klass.new(self, *args, &block)
- end unless method_defined?(:to_set)
-end
-
-autoload :SortedSet, "#{__dir__}/set/sorted_set"
diff --git a/lib/set/set.gemspec b/lib/set/set.gemspec
deleted file mode 100644
index 2ebef6985d..0000000000
--- a/lib/set/set.gemspec
+++ /dev/null
@@ -1,30 +0,0 @@
-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 = ["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(">= 3.0.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/lib/set/sorted_set.rb b/lib/set/sorted_set.rb
deleted file mode 100644
index bc07bc1fb0..0000000000
--- a/lib/set/sorted_set.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-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/lib/set/subclass_compatible.rb b/lib/set/subclass_compatible.rb
new file mode 100644
index 0000000000..f43c34f6a2
--- /dev/null
+++ b/lib/set/subclass_compatible.rb
@@ -0,0 +1,347 @@
+# frozen_string_literal: true
+
+# :markup: markdown
+#
+# set/subclass_compatible.rb - Provides compatibility for set subclasses
+#
+# Copyright (c) 2002-2024 Akinori MUSHA <knu@iDaemons.org>
+#
+# Documentation by Akinori MUSHA and Gavin Sinclair.
+#
+# All rights reserved. You can redistribute and/or modify it under the same
+# terms as Ruby.
+
+
+class Set
+ # This module is automatically included in subclasses of Set, to
+ # make them backwards compatible with the pure-Ruby set implementation
+ # used before Ruby 4. Users who want to use Set subclasses without
+ # this compatibility layer should subclass from Set::CoreSet.
+ #
+ # Note that Set subclasses that access `@hash` are not compatible even
+ # with this support. Such subclasses must be updated to support Ruby 4.
+ module SubclassCompatible
+ module ClassMethods
+ def [](*ary)
+ new(ary)
+ end
+ end
+
+ # Creates a new set containing the elements of the given enumerable
+ # object.
+ #
+ # If a block is given, the elements of enum are preprocessed by the
+ # given block.
+ #
+ # Set.new([1, 2]) #=> #<Set: {1, 2}>
+ # Set.new([1, 2, 1]) #=> #<Set: {1, 2}>
+ # Set.new([1, 'c', :s]) #=> #<Set: {1, "c", :s}>
+ # Set.new(1..5) #=> #<Set: {1, 2, 3, 4, 5}>
+ # Set.new([1, 2, 3]) { |x| x * x } #=> #<Set: {1, 4, 9}>
+ def initialize(enum = nil, &block) # :yields: o
+ enum.nil? and return
+
+ if block
+ do_with_enum(enum) { |o| add(block[o]) }
+ else
+ merge(enum)
+ end
+ end
+
+ def do_with_enum(enum, &block) # :nodoc:
+ if enum.respond_to?(:each_entry)
+ enum.each_entry(&block) if block
+ elsif enum.respond_to?(:each)
+ enum.each(&block) if block
+ else
+ raise ArgumentError, "value must be enumerable"
+ end
+ end
+ private :do_with_enum
+
+ def replace(enum)
+ if enum.instance_of?(self.class)
+ super
+ else
+ do_with_enum(enum) # make sure enum is enumerable before calling clear
+ clear
+ merge(enum)
+ end
+ end
+
+ def to_set(&block)
+ return self if instance_of?(Set) && block.nil?
+ Set.new(self, &block)
+ end
+
+ def flatten_merge(set, seen = {}) # :nodoc:
+ set.each { |e|
+ if e.is_a?(Set)
+ case seen[e_id = e.object_id]
+ when true
+ raise ArgumentError, "tried to flatten recursive Set"
+ when false
+ next
+ end
+
+ seen[e_id] = true
+ flatten_merge(e, seen)
+ seen[e_id] = false
+ else
+ add(e)
+ end
+ }
+
+ self
+ end
+ protected :flatten_merge
+
+ def flatten
+ self.class.new.flatten_merge(self)
+ end
+
+ def flatten!
+ replace(flatten()) if any?(Set)
+ end
+
+ def superset?(set)
+ case
+ when set.instance_of?(self.class)
+ super
+ when set.is_a?(Set)
+ size >= set.size && set.all?(self)
+ else
+ raise ArgumentError, "value must be a set"
+ end
+ end
+ alias >= superset?
+
+ def proper_superset?(set)
+ case
+ when set.instance_of?(self.class)
+ super
+ when set.is_a?(Set)
+ size > set.size && set.all?(self)
+ else
+ raise ArgumentError, "value must be a set"
+ end
+ end
+ alias > proper_superset?
+
+ def subset?(set)
+ case
+ when set.instance_of?(self.class)
+ super
+ when set.is_a?(Set)
+ size <= set.size && all?(set)
+ else
+ raise ArgumentError, "value must be a set"
+ end
+ end
+ alias <= subset?
+
+ def proper_subset?(set)
+ case
+ when set.instance_of?(self.class)
+ super
+ when set.is_a?(Set)
+ size < set.size && all?(set)
+ else
+ raise ArgumentError, "value must be a set"
+ end
+ end
+ alias < proper_subset?
+
+ 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
+
+ def intersect?(set)
+ case set
+ when Set
+ if size < set.size
+ any?(set)
+ else
+ set.any?(self)
+ end
+ when Enumerable
+ set.any?(self)
+ else
+ raise ArgumentError, "value must be enumerable"
+ end
+ end
+
+ def disjoint?(set)
+ !intersect?(set)
+ end
+
+ def add?(o)
+ add(o) unless include?(o)
+ end
+
+ def delete?(o)
+ delete(o) if include?(o)
+ end
+
+ def delete_if(&block)
+ block_given? or return enum_for(__method__) { size }
+ select(&block).each { |o| delete(o) }
+ self
+ end
+
+ def keep_if(&block)
+ block_given? or return enum_for(__method__) { size }
+ reject(&block).each { |o| delete(o) }
+ self
+ end
+
+ def collect!
+ block_given? or return enum_for(__method__) { size }
+ set = self.class.new
+ each { |o| set << yield(o) }
+ replace(set)
+ end
+ alias map! collect!
+
+ def reject!(&block)
+ block_given? or return enum_for(__method__) { size }
+ n = size
+ delete_if(&block)
+ self if size != n
+ end
+
+ def select!(&block)
+ block_given? or return enum_for(__method__) { size }
+ n = size
+ keep_if(&block)
+ self if size != n
+ end
+
+ alias filter! select!
+
+ def merge(*enums, **nil)
+ enums.each do |enum|
+ if enum.instance_of?(self.class)
+ super(enum)
+ else
+ do_with_enum(enum) { |o| add(o) }
+ end
+ end
+
+ self
+ end
+
+ def subtract(enum)
+ do_with_enum(enum) { |o| delete(o) }
+ self
+ end
+
+ def |(enum)
+ dup.merge(enum)
+ end
+ alias + |
+ alias union |
+
+ def -(enum)
+ dup.subtract(enum)
+ end
+ alias difference -
+
+ def &(enum)
+ n = self.class.new
+ 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 &
+
+ def ^(enum)
+ n = self.class.new(enum)
+ each { |o| n.add(o) unless n.delete?(o) }
+ n
+ end
+
+ def ==(other)
+ if self.equal?(other)
+ true
+ elsif other.instance_of?(self.class)
+ super
+ elsif other.is_a?(Set) && self.size == other.size
+ other.all? { |o| include?(o) }
+ else
+ false
+ end
+ end
+
+ def eql?(o) # :nodoc:
+ return false unless o.is_a?(Set)
+ super
+ end
+
+ def classify
+ block_given? or return enum_for(__method__) { size }
+
+ h = {}
+
+ each { |i|
+ (h[yield(i)] ||= self.class.new).add(i)
+ }
+
+ h
+ end
+
+ def join(separator=nil)
+ to_a.join(separator)
+ end
+
+ InspectKey = :__inspect_key__ # :nodoc:
+
+ # Returns a string containing a human-readable representation of the
+ # set ("#<Set: {element1, element2, ...}>").
+ def inspect
+ ids = (Thread.current[InspectKey] ||= [])
+
+ if ids.include?(object_id)
+ return sprintf('#<%s: {...}>', self.class.name)
+ end
+
+ ids << object_id
+ begin
+ return sprintf('#<%s: {%s}>', self.class, to_a.inspect[1..-2])
+ ensure
+ ids.pop
+ end
+ end
+
+ alias to_s inspect
+
+ def pretty_print(pp) # :nodoc:
+ pp.group(1, sprintf('#<%s:', self.class.name), '>') {
+ pp.breakable
+ pp.group(1, '{', '}') {
+ pp.seplist(self) { |o|
+ pp.pp o
+ }
+ }
+ }
+ end
+
+ def pretty_print_cycle(pp) # :nodoc:
+ pp.text sprintf('#<%s: {%s}>', self.class.name, empty? ? '' : '...')
+ end
+ end
+ private_constant :SubclassCompatible
+end
diff --git a/lib/shellwords.gemspec b/lib/shellwords.gemspec
index d60ab5f650..b601508f94 100644
--- a/lib/shellwords.gemspec
+++ b/lib/shellwords.gemspec
@@ -21,10 +21,9 @@ Gem::Specification.new do |spec|
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)/}) }
+ srcdir, gemspec_file = File.split(__FILE__)
+ spec.files = Dir.chdir(srcdir) do
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:(?:test|spec|features)/|\.git|Rake)}) || f == gemspec_file}
end
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
end
diff --git a/lib/shellwords.rb b/lib/shellwords.rb
index 067432e374..20a85ed9d2 100644
--- a/lib/shellwords.rb
+++ b/lib/shellwords.rb
@@ -5,9 +5,9 @@
# This module manipulates strings according to the word parsing rules
# of the UNIX Bourne shell.
#
-# The shellwords() function was originally a port of shellwords.pl,
-# but modified to conform to the Shell & Utilities volume of the IEEE
-# Std 1003.1-2008, 2016 Edition [1].
+# The <tt>shellwords()</tt> function was originally a port of shellwords.pl, but
+# modified to conform to {the Shell & Utilities volume of the IEEE Std 1003.1-2008, 2016
+# Edition}[http://pubs.opengroup.org/onlinepubs/9699919799/utilities/contents.html]
#
# === Usage
#
@@ -62,13 +62,10 @@
#
# === Contact
# * Akinori MUSHA <knu@iDaemons.org> (current maintainer)
-#
-# === Resources
-#
-# 1: {IEEE Std 1003.1-2008, 2016 Edition, the Shell & Utilities volume}[http://pubs.opengroup.org/onlinepubs/9699919799/utilities/contents.html]
module Shellwords
- VERSION = "0.2.0"
+ # The version number string.
+ VERSION = "0.2.2"
# Splits a string into an array of tokens in the same way the UNIX
# Bourne shell does.
@@ -76,6 +73,9 @@ module Shellwords
# argv = Shellwords.split('here are "two words"')
# argv #=> ["here", "are", "two words"]
#
+ # +line+ must not contain NUL characters because of nature of
+ # +exec+ system call.
+ #
# Note, however, that this is not a command line parser. Shell
# metacharacters except for the single and double quotes and
# backslash are not treated as such.
@@ -90,9 +90,14 @@ module Shellwords
def shellsplit(line)
words = []
field = String.new
- line.scan(/\G\s*(?>([^\s\\\'\"]+)|'([^\']*)'|"((?:[^\"\\]|\\.)*)"|(\\.?)|(\S))(\s|\z)?/m) do
+ line.scan(/\G\s*(?>([^\0\s\\\'\"]+)|'([^\0\']*)'|"((?:[^\0\"\\]|\\[^\0])*)"|(\\[^\0]?)|(\S))(\s|\z)?/m) do
|word, sq, dq, esc, garbage, sep|
- raise ArgumentError, "Unmatched quote: #{line.inspect}" if garbage
+ if garbage
+ b = $~.begin(0)
+ line = $~[0]
+ line = "..." + line if b > 0
+ raise ArgumentError, "#{garbage == "\0" ? 'Nul character' : 'Unmatched quote'} at #{b}: #{line}"
+ end
# 2.2.3 Double-Quotes:
#
# The <backslash> shall retain its special meaning as an
@@ -121,6 +126,9 @@ module Shellwords
# command line. +str+ can be a non-string object that responds to
# +to_s+.
#
+ # +str+ must not contain NUL characters because of nature of +exec+
+ # system call.
+ #
# Note that a resulted string should be used unquoted and is not
# intended for use in double quotes nor in single quotes.
#
@@ -153,6 +161,9 @@ module Shellwords
# An empty argument will be skipped, so return empty quotes.
return "''".dup if str.empty?
+ # Shellwords cannot contain NUL characters.
+ raise ArgumentError, "NUL character" if str.index("\0")
+
str = str.dup
# Treat multibyte characters as is. It is the caller's responsibility
@@ -178,6 +189,7 @@ module Shellwords
# All elements are joined into a single string with fields separated by a
# space, where each element is escaped for the Bourne shell and stringified
# using +to_s+.
+ # See also Shellwords.shellescape.
#
# ary = ["There's", "a", "time", "and", "place", "for", "everything"]
# argv = Shellwords.join(ary)
diff --git a/lib/singleton.rb b/lib/singleton.rb
index 6da939124e..74aec8903c 100644
--- a/lib/singleton.rb
+++ b/lib/singleton.rb
@@ -1,4 +1,4 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
# The Singleton module implements the Singleton pattern.
#
@@ -92,22 +92,26 @@
# p a.strip # => nil
#
module Singleton
- VERSION = "0.2.0"
+ # The version string
+ VERSION = "0.3.0"
- # Raises a TypeError to prevent cloning.
- def clone
- raise TypeError, "can't clone instance of singleton #{self.class}"
- end
+ module SingletonInstanceMethods # :nodoc:
+ # Raises a TypeError to prevent cloning.
+ def clone
+ raise TypeError, "can't clone instance of singleton #{self.class}"
+ end
- # Raises a TypeError to prevent duping.
- def dup
- raise TypeError, "can't dup instance of singleton #{self.class}"
- end
+ # Raises a TypeError to prevent duping.
+ def dup
+ raise TypeError, "can't dup instance of singleton #{self.class}"
+ end
- # By default, do not retain any state when marshalling.
- def _dump(depth = -1)
- ''
+ # By default, do not retain any state when marshalling.
+ def _dump(depth = -1)
+ ''
+ end
end
+ include SingletonInstanceMethods
module SingletonClassMethods # :nodoc:
@@ -130,22 +134,42 @@ module Singleton
super
Singleton.__init__(sub_klass)
end
+
+ def set_instance(val)
+ @singleton__instance__ = val
+ end
+
+ def set_mutex(val)
+ @singleton__mutex__ = val
+ end
end
- class << Singleton # :nodoc:
+ def self.module_with_class_methods # :nodoc:
+ SingletonClassMethods
+ end
+
+ module SingletonClassProperties # :nodoc:
+
+ def self.included(c)
+ # extending an object with Singleton is a bad idea
+ c.undef_method :extend_object
+ end
+
+ def self.extended(c)
+ # extending an object with Singleton is a bad idea
+ c.singleton_class.send(:undef_method, :extend_object)
+ end
+
def __init__(klass) # :nodoc:
klass.instance_eval {
- @singleton__instance__ = nil
- @singleton__mutex__ = Thread::Mutex.new
+ set_instance(nil)
+ set_mutex(Thread::Mutex.new)
}
klass
end
private
- # extending an object with Singleton is a bad idea
- undef_method :extend_object
-
def append_features(mod)
# help out people counting on transitive mixins
unless mod.instance_of?(Class)
@@ -157,10 +181,11 @@ module Singleton
def included(klass)
super
klass.private_class_method :new, :allocate
- klass.extend SingletonClassMethods
+ klass.extend module_with_class_methods
Singleton.__init__(klass)
end
end
+ extend SingletonClassProperties
##
# :singleton-method: _load
@@ -170,3 +195,46 @@ module Singleton
# :singleton-method: instance
# Returns the singleton instance.
end
+
+if defined?(Ractor)
+ module RactorLocalSingleton # :nodoc:
+ include Singleton::SingletonInstanceMethods
+
+ module RactorLocalSingletonClassMethods # :nodoc:
+ include Singleton::SingletonClassMethods
+ def instance
+ set_mutex(Thread::Mutex.new) if Ractor.current[mutex_key].nil?
+ return Ractor.current[instance_key] if Ractor.current[instance_key]
+ Ractor.current[mutex_key].synchronize {
+ return Ractor.current[instance_key] if Ractor.current[instance_key]
+ set_instance(new())
+ }
+ Ractor.current[instance_key]
+ end
+
+ private
+
+ def instance_key
+ :"__RactorLocalSingleton_instance_with_class_id_#{object_id}__"
+ end
+
+ def mutex_key
+ :"__RactorLocalSingleton_mutex_with_class_id_#{object_id}__"
+ end
+
+ def set_instance(val)
+ Ractor.current[instance_key] = val
+ end
+
+ def set_mutex(val)
+ Ractor.current[mutex_key] = val
+ end
+ end
+
+ def self.module_with_class_methods
+ RactorLocalSingletonClassMethods
+ end
+
+ extend Singleton::SingletonClassProperties
+ end
+end
diff --git a/lib/syntax_suggest/api.rb b/lib/syntax_suggest/api.rb
index 65660ec5e5..0f82d8362a 100644
--- a/lib/syntax_suggest/api.rb
+++ b/lib/syntax_suggest/api.rb
@@ -146,11 +146,7 @@ module SyntaxSuggest
def self.valid_without?(without_lines:, code_lines:)
lines = code_lines - Array(without_lines).flatten
- if lines.empty?
- true
- else
- valid?(lines)
- end
+ lines.empty? || valid?(lines)
end
# SyntaxSuggest.invalid? [Private]
@@ -227,6 +223,7 @@ require_relative "lex_all"
require_relative "code_line"
require_relative "code_block"
require_relative "block_expand"
+require_relative "mini_stringio"
require_relative "priority_queue"
require_relative "unvisited_lines"
require_relative "around_block_scan"
diff --git a/lib/syntax_suggest/capture_code_context.rb b/lib/syntax_suggest/capture_code_context.rb
index 1f232cfae3..5de9ec09cc 100644
--- a/lib/syntax_suggest/capture_code_context.rb
+++ b/lib/syntax_suggest/capture_code_context.rb
@@ -15,7 +15,7 @@ module SyntaxSuggest
#
# 1. Sanitize/format input source
# 2. Search for invalid blocks
- # 3. Format invalid blocks into something meaninful
+ # 3. Format invalid blocks into something meaningful
#
# This class handles the third part.
#
diff --git a/lib/syntax_suggest/clean_document.rb b/lib/syntax_suggest/clean_document.rb
index 2790ccae86..ba307af46e 100644
--- a/lib/syntax_suggest/clean_document.rb
+++ b/lib/syntax_suggest/clean_document.rb
@@ -10,7 +10,7 @@ module SyntaxSuggest
#
# 1. Sanitize/format input source
# 2. Search for invalid blocks
- # 3. Format invalid blocks into something meaninful
+ # 3. Format invalid blocks into something meaningful
#
# This class handles the first part.
#
diff --git a/lib/syntax_suggest/code_frontier.rb b/lib/syntax_suggest/code_frontier.rb
index 0f870d0df0..38d5375ef4 100644
--- a/lib/syntax_suggest/code_frontier.rb
+++ b/lib/syntax_suggest/code_frontier.rb
@@ -8,7 +8,7 @@ module SyntaxSuggest
#
# 1. Sanitize/format input source
# 2. Search for invalid blocks
- # 3. Format invalid blocks into something meaninful
+ # 3. Format invalid blocks into something meaningful
#
# The Code frontier is a critical part of the second step
#
diff --git a/lib/syntax_suggest/core_ext.rb b/lib/syntax_suggest/core_ext.rb
index c299627bb7..94f57ba605 100644
--- a/lib/syntax_suggest/core_ext.rb
+++ b/lib/syntax_suggest/core_ext.rb
@@ -3,24 +3,6 @@
# Ruby 3.2+ has a cleaner way to hook into Ruby that doesn't use `require`
if SyntaxError.method_defined?(:detailed_message)
module SyntaxSuggest
- # Mini String IO [Private]
- #
- # Acts like a StringIO with reduced API, but without having to require that
- # class.
- class MiniStringIO
- def initialize(isatty: $stderr.isatty)
- @string = +""
- @isatty = isatty
- end
-
- attr_reader :isatty
- def puts(value = $/, **)
- @string << value
- end
-
- attr_reader :string
- end
-
# SyntaxSuggest.module_for_detailed_message [Private]
#
# Used to monkeypatch SyntaxError via Module.prepend
diff --git a/lib/syntax_suggest/lex_value.rb b/lib/syntax_suggest/lex_value.rb
index 008cc105b5..b46a332772 100644
--- a/lib/syntax_suggest/lex_value.rb
+++ b/lib/syntax_suggest/lex_value.rb
@@ -28,7 +28,7 @@ module SyntaxSuggest
@is_end = false
@is_kw = false
return if type != :on_kw
- #
+
return if last_lex && last_lex.fname? # https://github.com/ruby/ruby/commit/776759e300e4659bb7468e2b97c8c2d4359a2953
case token
diff --git a/lib/syntax_suggest/mini_stringio.rb b/lib/syntax_suggest/mini_stringio.rb
new file mode 100644
index 0000000000..1a82572eeb
--- /dev/null
+++ b/lib/syntax_suggest/mini_stringio.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module SyntaxSuggest
+ # Mini String IO [Private]
+ #
+ # Acts like a StringIO with reduced API, but without having to require that
+ # class.
+ #
+ # The original codebase emitted directly to $stderr, but now SyntaxError#detailed_message
+ # needs a string output. To accomplish that we kept the original print infrastructure in place and
+ # added this class to accumulate the print output into a string.
+ class MiniStringIO
+ EMPTY_ARG = Object.new
+
+ def initialize(isatty: $stderr.isatty)
+ @string = +""
+ @isatty = isatty
+ end
+
+ attr_reader :isatty
+ def puts(value = EMPTY_ARG, **)
+ if !value.equal?(EMPTY_ARG)
+ @string << value
+ end
+ @string << $/
+ end
+
+ attr_reader :string
+ end
+end
diff --git a/lib/syntax_suggest/version.rb b/lib/syntax_suggest/version.rb
index 4320adb218..1aa908f4e5 100644
--- a/lib/syntax_suggest/version.rb
+++ b/lib/syntax_suggest/version.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
module SyntaxSuggest
- VERSION = "2.0.0"
+ VERSION = "2.0.2"
end
diff --git a/lib/tempfile.rb b/lib/tempfile.rb
index bddef3bf22..cd512bb1c5 100644
--- a/lib/tempfile.rb
+++ b/lib/tempfile.rb
@@ -29,7 +29,7 @@ require 'tmpdir'
# require 'tempfile'
#
# # Tempfile.create with a block
-# # The filename are choosen automatically.
+# # The filename are chosen automatically.
# # (You can specify the prefix and suffix of the filename by an optional argument.)
# Tempfile.create {|f|
# f.puts "foo"
@@ -157,7 +157,7 @@ require 'tmpdir'
class Tempfile < DelegateClass(File)
# The version
- VERSION = "0.2.1"
+ VERSION = "0.3.1"
# Creates a file in the underlying file system;
# returns a new \Tempfile object based on that file.
@@ -221,45 +221,47 @@ class Tempfile < DelegateClass(File)
@unlinked = false
@mode = mode|File::RDWR|File::CREAT|File::EXCL
- @finalizer_obj = Object.new
tmpfile = nil
::Dir::Tmpname.create(basename, tmpdir, **options) do |tmpname, n, opts|
opts[:perm] = 0600
tmpfile = File.open(tmpname, @mode, **opts)
@opts = opts.freeze
end
- ObjectSpace.define_finalizer(@finalizer_obj, Remover.new(tmpfile.path))
- ObjectSpace.define_finalizer(self, Closer.new(tmpfile))
super(tmpfile)
+
+ @finalizer_manager = FinalizerManager.new(__getobj__.path)
+ @finalizer_manager.register(self, __getobj__)
end
def initialize_dup(other) # :nodoc:
initialize_copy_iv(other)
super(other)
- ObjectSpace.define_finalizer(self, Closer.new(__getobj__))
+ @finalizer_manager.register(self, __getobj__)
end
def initialize_clone(other) # :nodoc:
initialize_copy_iv(other)
super(other)
- ObjectSpace.define_finalizer(self, Closer.new(__getobj__))
+ @finalizer_manager.register(self, __getobj__)
end
private def initialize_copy_iv(other) # :nodoc:
@unlinked = other.unlinked
@mode = other.mode
@opts = other.opts
- @finalizer_obj = other.finalizer_obj
+ @finalizer_manager = other.finalizer_manager
end
# Opens or reopens the file with mode "r+".
def open
_close
- ObjectSpace.undefine_finalizer(self)
+
mode = @mode & ~(File::CREAT|File::EXCL)
__setobj__(File.open(__getobj__.path, mode, **@opts))
- ObjectSpace.define_finalizer(self, Closer.new(__getobj__))
+
+ @finalizer_manager.register(self, __getobj__)
+
__getobj__
end
@@ -327,7 +329,9 @@ class Tempfile < DelegateClass(File)
# may not be able to unlink on Windows; just ignore
return
end
- ObjectSpace.undefine_finalizer(@finalizer_obj)
+
+ @finalizer_manager.unlinked = true
+
@unlinked = true
end
alias delete unlink
@@ -361,35 +365,35 @@ class Tempfile < DelegateClass(File)
protected
- attr_reader :unlinked, :mode, :opts, :finalizer_obj
+ attr_reader :unlinked, :mode, :opts, :finalizer_manager
- class Closer # :nodoc:
- def initialize(tmpfile)
- @tmpfile = tmpfile
- end
-
- def call(*args)
- @tmpfile.close
- end
- end
+ class FinalizerManager # :nodoc:
+ attr_accessor :unlinked
- class Remover # :nodoc:
def initialize(path)
- @pid = Process.pid
+ @open_files = {}
@path = path
+ @pid = Process.pid
+ @unlinked = false
end
- def call(*args)
- return if @pid != Process.pid
+ def register(obj, file)
+ ObjectSpace.undefine_finalizer(obj)
+ ObjectSpace.define_finalizer(obj, self)
+ @open_files[obj.object_id] = file
+ end
- $stderr.puts "removing #{@path}..." if $DEBUG
+ def call(object_id)
+ @open_files.delete(object_id).close
- begin
- File.unlink(@path)
- rescue Errno::ENOENT
+ if @open_files.empty? && !@unlinked && Process.pid == @pid
+ $stderr.puts "removing #{@path}..." if $DEBUG
+ begin
+ File.unlink(@path)
+ rescue Errno::ENOENT
+ end
+ $stderr.puts "done" if $DEBUG
end
-
- $stderr.puts "done" if $DEBUG
end
end
@@ -524,18 +528,18 @@ end
#
# The keyword argument +anonymous+ specifies when the file is removed.
#
-# - +anonymous=false+ (default) without a block: the file is not removed.
-# - +anonymous=false+ (default) with a block: the file is removed after the block exits.
-# - +anonymous=true+ without a block: the file is removed before returning.
-# - +anonymous=true+ with a block: the file is removed before the block is called.
+# - <tt>anonymous=false</tt> (default) without a block: the file is not removed.
+# - <tt>anonymous=false</tt> (default) with a block: the file is removed after the block exits.
+# - <tt>anonymous=true</tt> without a block: the file is removed before returning.
+# - <tt>anonymous=true</tt> with a block: the file is removed before the block is called.
#
-# In the first case (+anonymous=false+ without a block),
+# In the first case (<tt>anonymous=false</tt> without a block),
# the file is not removed automatically.
# It should be explicitly closed.
# It can be used to rename to the desired filename.
# If the file is not needed, it should be explicitly removed.
#
-# The +File#path+ method of the created file object returns the temporary directory with a trailing slash
+# The File#path method of the created file object returns the temporary directory with a trailing slash
# when +anonymous+ is true.
#
# When a block is given, it creates the file as described above, passes it to the block,
@@ -546,8 +550,8 @@ end
#
# Implementation note:
#
-# The keyword argument +anonymous=true+ is implemented using FILE_SHARE_DELETE on Windows.
-# O_TMPFILE is used on Linux.
+# The keyword argument <tt>anonymous=true</tt> is implemented using +FILE_SHARE_DELETE+ on Windows.
+# +O_TMPFILE+ is used on Linux.
#
# Related: Tempfile.new.
#
@@ -560,6 +564,8 @@ def Tempfile.create(basename="", tmpdir=nil, mode: 0, anonymous: false, **option
end
class << Tempfile
+# :stopdoc:
+
private def create_with_filename(basename="", tmpdir=nil, mode: 0, **options)
tmpfile = nil
Dir::Tmpname.create(basename, tmpdir, **options) do |tmpname, n, opts|
@@ -589,6 +595,16 @@ private def create_with_filename(basename="", tmpdir=nil, mode: 0, **options)
end
end
+if RUBY_VERSION < "3.2"
+ module PathAttr # :nodoc:
+ attr_reader :path
+
+ def self.set_path(file, path)
+ file.extend(self).instance_variable_set(:@path, path)
+ end
+ end
+end
+
private def create_anonymous(basename="", tmpdir=nil, mode: 0, **options, &block)
tmpfile = nil
tmpdir = Dir.tmpdir() if tmpdir.nil?
@@ -604,12 +620,14 @@ private def create_anonymous(basename="", tmpdir=nil, mode: 0, **options, &block
mode |= File::SHARE_DELETE | File::BINARY # Windows needs them to unlink the opened file.
tmpfile = create_with_filename(basename, tmpdir, mode: mode, **options)
File.unlink(tmpfile.path)
+ tmppath = tmpfile.path
end
path = File.join(tmpdir, '')
- if tmpfile.path != path
+ unless tmppath == path
# clear path.
tmpfile.autoclose = false
tmpfile = File.new(tmpfile.fileno, mode: File::RDWR, path: path)
+ PathAttr.set_path(tmpfile, path) if defined?(PathAttr)
end
if block
begin
diff --git a/lib/time.gemspec b/lib/time.gemspec
index 4b9f9e1218..73650ab12e 100644
--- a/lib/time.gemspec
+++ b/lib/time.gemspec
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = spec.homepage
+ spec.metadata["changelog_uri"] = "https://github.com/ruby/time/releases"
srcdir, gemspec = File.split(__FILE__)
spec.files = Dir.chdir(srcdir) do
diff --git a/lib/time.rb b/lib/time.rb
index b565130b50..e6aab3fa5d 100644
--- a/lib/time.rb
+++ b/lib/time.rb
@@ -24,9 +24,10 @@ require 'date'
# :startdoc:
+# #
class Time
- VERSION = "0.3.0"
+ VERSION = "0.4.2" # :nodoc:
class << Time
@@ -79,7 +80,7 @@ class Time
#
# You must require 'time' to use this method.
#
- def zone_offset(zone, year=self.now.year)
+ def zone_offset(zone, year=nil)
off = nil
zone = zone.upcase
if /\A([+-])(\d\d)(:?)(\d\d)(?:\3(\d\d))?\z/ =~ zone
@@ -88,10 +89,13 @@ class Time
off = zone.to_i * 3600
elsif ZoneOffset.include?(zone)
off = ZoneOffset[zone] * 3600
- elsif ((t = self.local(year, 1, 1)).zone.upcase == zone rescue false)
- off = t.utc_offset
- elsif ((t = self.local(year, 7, 1)).zone.upcase == zone rescue false)
- off = t.utc_offset
+ else
+ year ||= self.now.year
+ if ((t = self.local(year, 1, 1)).zone.upcase == zone rescue false)
+ off = t.utc_offset
+ elsif ((t = self.local(year, 7, 1)).zone.upcase == zone rescue false)
+ off = t.utc_offset
+ end
end
off
end
@@ -280,7 +284,7 @@ class Time
#
# 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
+ # cryptic result. Should consider to use Time.strptime instead
# of this method as possible.
#
# require 'time'
@@ -391,7 +395,7 @@ class Time
# heuristic to detect the format of the input string, you provide
# a second argument that describes the format of the string.
#
- # Raises `ArgumentError` if the date or format is invalid.
+ # Raises ArgumentError if the date or format is invalid.
#
# If a block is given, the year described in +date+ is converted by the
# block. For example:
@@ -407,7 +411,7 @@ class Time
# %c :: The preferred local date and time representation
# %C :: Century (20 in 2009)
# %d :: Day of the month (01..31)
- # %D :: Date (%m/%d/%y)
+ # %D :: \Date (%m/%d/%y)
# %e :: Day of the month, blank-padded ( 1..31)
# %F :: Equivalent to %Y-%m-%d (the ISO 8601 date format)
# %g :: The last two digits of the commercial year
@@ -444,8 +448,8 @@ class Time
# %X :: Preferred representation for the time alone, no date
# %y :: Year without a century (00..99)
# %Y :: Year which may include century, if provided
- # %z :: Time zone as hour offset from UTC (e.g. +0900)
- # %Z :: Time zone name
+ # %z :: \Time zone as hour offset from UTC (e.g. +0900)
+ # %Z :: \Time zone name
# %% :: Literal "%" character
# %+ :: date(1) (%a %b %e %H:%M:%S %Z %Y)
#
@@ -695,35 +699,36 @@ class Time
getutc.strftime('%a, %d %b %Y %T GMT')
end
- #
- # Returns a string which represents the time as a dateTime defined by XML
- # Schema:
- #
- # CCYY-MM-DDThh:mm:ssTZD
- # CCYY-MM-DDThh:mm:ss.sssTZD
- #
- # where TZD is Z or [+-]hh:mm.
- #
- # If self is a UTC time, Z is used as TZD. [+-]hh:mm is used otherwise.
- #
- # +fraction_digits+ specifies a number of digits to use for fractional
- # seconds. Its default value is 0.
- #
- # require 'time'
- #
- # t = Time.now
- # t.iso8601 # => "2011-10-05T22:26:12-04:00"
- #
- # You must require 'time' to use this method.
- #
- def xmlschema(fraction_digits=0)
- fraction_digits = fraction_digits.to_i
- s = strftime("%FT%T")
- if fraction_digits > 0
- s << strftime(".%#{fraction_digits}N")
+ unless method_defined?(:xmlschema)
+ #
+ # Returns a string which represents the time as a dateTime defined by XML
+ # Schema:
+ #
+ # CCYY-MM-DDThh:mm:ssTZD
+ # CCYY-MM-DDThh:mm:ss.sssTZD
+ #
+ # where TZD is Z or [+-]hh:mm.
+ #
+ # If self is a UTC time, Z is used as TZD. [+-]hh:mm is used otherwise.
+ #
+ # +fraction_digits+ specifies a number of digits to use for fractional
+ # seconds. Its default value is 0.
+ #
+ # require 'time'
+ #
+ # t = Time.now
+ # t.iso8601 # => "2011-10-05T22:26:12-04:00"
+ #
+ # You must require 'time' to use this method.
+ #
+ def xmlschema(fraction_digits=0)
+ fraction_digits = fraction_digits.to_i
+ s = strftime("%FT%T")
+ if fraction_digits > 0
+ s << strftime(".%#{fraction_digits}N")
+ end
+ s << (utc? ? 'Z' : strftime("%:z"))
end
- s << (utc? ? 'Z' : strftime("%:z"))
end
- alias iso8601 xmlschema
+ alias iso8601 xmlschema unless method_defined?(:iso8601)
end
-
diff --git a/lib/timeout.rb b/lib/timeout.rb
index c67a748856..e293e3be7c 100644
--- a/lib/timeout.rb
+++ b/lib/timeout.rb
@@ -4,7 +4,7 @@
# == Synopsis
#
# require 'timeout'
-# status = Timeout::timeout(5) {
+# status = Timeout.timeout(5) {
# # Something that should be interrupted if it takes more than 5 seconds...
# }
#
@@ -13,10 +13,6 @@
# Timeout provides a way to auto-terminate a potentially long-running
# operation if it hasn't finished in a fixed amount of time.
#
-# Previous versions didn't use a module for namespacing, however
-# #timeout is provided for backwards compatibility. You
-# should prefer Timeout.timeout instead.
-#
# == Copyright
#
# Copyright:: (C) 2000 Network Applied Communication Laboratory, Inc.
@@ -24,9 +20,9 @@
module Timeout
# The version
- VERSION = "0.4.1"
+ VERSION = "0.6.0"
- # Internal error raised to when a timeout is triggered.
+ # Internal exception raised to when a timeout is triggered.
class ExitException < Exception
def exception(*) # :nodoc:
self
@@ -48,12 +44,101 @@ module Timeout
end
# :stopdoc:
- CONDVAR = ConditionVariable.new
- QUEUE = Queue.new
- QUEUE_MUTEX = Mutex.new
- TIMEOUT_THREAD_MUTEX = Mutex.new
- @timeout_thread = nil
- private_constant :CONDVAR, :QUEUE, :QUEUE_MUTEX, :TIMEOUT_THREAD_MUTEX
+
+ # We keep a private reference so that time mocking libraries won't break Timeout.
+ GET_TIME = Process.method(:clock_gettime)
+ if defined?(Ractor.make_shareable)
+ # Ractor.make_shareable(Method) only works on Ruby 4+
+ Ractor.make_shareable(GET_TIME) rescue nil
+ end
+ private_constant :GET_TIME
+
+ class State
+ def initialize
+ @condvar = ConditionVariable.new
+ @queue = Queue.new
+ @queue_mutex = Mutex.new
+
+ @timeout_thread = nil
+ @timeout_thread_mutex = Mutex.new
+ end
+
+ if defined?(Ractor.store_if_absent) && defined?(Ractor.shareable?) && Ractor.shareable?(GET_TIME)
+ # Ractor support if
+ # 1. Ractor.store_if_absent is available
+ # 2. Method object can be shareable (4.0~)
+ def self.instance
+ Ractor.store_if_absent :timeout_gem_state do
+ State.new
+ end
+ end
+ else
+ GLOBAL_STATE = State.new
+
+ def self.instance
+ GLOBAL_STATE
+ end
+ end
+
+ def create_timeout_thread
+ # Threads unexpectedly inherit the interrupt mask: https://github.com/ruby/timeout/issues/41
+ # So reset the interrupt mask to the default one for the timeout thread
+ Thread.handle_interrupt(Object => :immediate) do
+ watcher = Thread.new do
+ requests = []
+ while true
+ until @queue.empty? and !requests.empty? # wait to have at least one request
+ req = @queue.pop
+ requests << req unless req.done?
+ end
+ closest_deadline = requests.min_by(&:deadline).deadline
+
+ now = 0.0
+ @queue_mutex.synchronize do
+ while (now = GET_TIME.call(Process::CLOCK_MONOTONIC)) < closest_deadline and @queue.empty?
+ @condvar.wait(@queue_mutex, closest_deadline - now)
+ end
+ end
+
+ requests.each do |req|
+ req.interrupt if req.expired?(now)
+ end
+ requests.reject!(&:done?)
+ end
+ end
+
+ if !watcher.group.enclosed? && (!defined?(Ractor.main?) || Ractor.main?)
+ ThreadGroup::Default.add(watcher)
+ end
+
+ watcher.name = "Timeout stdlib thread"
+ watcher.thread_variable_set(:"\0__detached_thread__", true)
+ watcher
+ end
+ end
+
+ def ensure_timeout_thread_created
+ unless @timeout_thread&.alive?
+ # If the Mutex is already owned we are in a signal handler.
+ # In that case, just return and let the main thread create the Timeout thread.
+ return if @timeout_thread_mutex.owned?
+
+ Sync.synchronize @timeout_thread_mutex do
+ unless @timeout_thread&.alive?
+ @timeout_thread = create_timeout_thread
+ end
+ end
+ end
+ end
+
+ def add_request(request)
+ Sync.synchronize @queue_mutex do
+ @queue << request
+ @condvar.signal
+ end
+ end
+ end
+ private_constant :State
class Request
attr_reader :deadline
@@ -68,6 +153,7 @@ module Timeout
@done = false # protected by @mutex
end
+ # Only called by the timeout thread, so does not need Sync.synchronize
def done?
@mutex.synchronize do
@done
@@ -78,6 +164,7 @@ module Timeout
now >= @deadline
end
+ # Only called by the timeout thread, so does not need Sync.synchronize
def interrupt
@mutex.synchronize do
unless @done
@@ -88,87 +175,109 @@ module Timeout
end
def finished
- @mutex.synchronize do
+ Sync.synchronize @mutex do
@done = true
end
end
end
private_constant :Request
- def self.create_timeout_thread
- watcher = Thread.new do
- requests = []
- while true
- until QUEUE.empty? and !requests.empty? # wait to have at least one request
- req = QUEUE.pop
- requests << req unless req.done?
- end
- closest_deadline = requests.min_by(&:deadline).deadline
-
- now = 0.0
- QUEUE_MUTEX.synchronize do
- while (now = GET_TIME.call(Process::CLOCK_MONOTONIC)) < closest_deadline and QUEUE.empty?
- CONDVAR.wait(QUEUE_MUTEX, closest_deadline - now)
- end
- end
-
- requests.each do |req|
- req.interrupt if req.expired?(now)
- end
- requests.reject!(&:done?)
- end
- end
- ThreadGroup::Default.add(watcher) unless watcher.group.enclosed?
- watcher.name = "Timeout stdlib thread"
- watcher.thread_variable_set(:"\0__detached_thread__", true)
- watcher
- end
- private_class_method :create_timeout_thread
-
- def self.ensure_timeout_thread_created
- unless @timeout_thread and @timeout_thread.alive?
- TIMEOUT_THREAD_MUTEX.synchronize do
- unless @timeout_thread and @timeout_thread.alive?
- @timeout_thread = create_timeout_thread
- end
+ module Sync
+ # Calls mutex.synchronize(&block) but if that fails on CRuby due to being in a trap handler,
+ # run mutex.synchronize(&block) in a separate Thread instead.
+ def self.synchronize(mutex, &block)
+ begin
+ mutex.synchronize(&block)
+ rescue ThreadError => e
+ raise e unless e.message == "can't be called from trap context"
+ # Workaround CRuby issue https://bugs.ruby-lang.org/issues/19473
+ # which raises on Mutex#synchronize in trap handler.
+ # It's expensive to create a Thread just for this,
+ # but better than failing.
+ Thread.new {
+ mutex.synchronize(&block)
+ }.join
end
end
end
-
- # We keep a private reference so that time mocking libraries won't break
- # Timeout.
- GET_TIME = Process.method(:clock_gettime)
- private_constant :GET_TIME
+ private_constant :Sync
# :startdoc:
- # Perform an operation in a block, raising an error if it takes longer than
+ # Perform an operation in a block, raising an exception if it takes longer than
# +sec+ seconds to complete.
#
- # +sec+:: Number of seconds to wait for the block to terminate. Any number
- # may be used, including Floats to specify fractional seconds. A
+ # +sec+:: Number of seconds to wait for the block to terminate. Any non-negative number
+ # or nil may be used, including Floats to specify fractional seconds. A
# value of 0 or +nil+ will execute the block without any timeout.
+ # Any negative number will raise an ArgumentError.
# +klass+:: Exception Class to raise if the block fails to terminate
- # in +sec+ seconds. Omitting will use the default, Timeout::Error
+ # in +sec+ seconds. Omitting will use the default, Timeout::Error.
# +message+:: Error message to raise with Exception Class.
- # Omitting will use the default, "execution expired"
+ # Omitting will use the default, <tt>"execution expired"</tt>.
#
# Returns the result of the block *if* the block completed before
- # +sec+ seconds, otherwise throws an exception, based on the value of +klass+.
+ # +sec+ seconds, otherwise raises an exception, based on the value of +klass+.
+ #
+ # The exception raised to terminate the given block is the given +klass+, or
+ # Timeout::ExitException if +klass+ is not given. The reason for that behavior
+ # is that Timeout::Error inherits from RuntimeError and might be caught unexpectedly by +rescue+.
+ # Timeout::ExitException inherits from Exception so it will only be rescued by <tt>rescue Exception</tt>.
+ # Note that the Timeout::ExitException is translated to a Timeout::Error once it reaches the Timeout.timeout call,
+ # so outside that call it will be a Timeout::Error.
#
- # The exception thrown to terminate the given block cannot be rescued inside
- # the block unless +klass+ is given explicitly. However, the block can use
- # ensure to prevent the handling of the exception. For that reason, this
- # method cannot be relied on to enforce timeouts for untrusted blocks.
+ # In general, be aware that the code block may rescue the exception, and in such a case not respect the timeout.
+ # Also, the block can use +ensure+ to prevent the handling of the exception.
+ # For those reasons, 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.
+ # Fiber::Scheduler#timeout_after.
#
# Note that this is both a method of module Timeout, so you can <tt>include
# Timeout</tt> 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, &block) #:yield: +sec+
+ #
+ # ==== Ensuring the exception does not fire inside ensure blocks
+ #
+ # When using Timeout.timeout, it can be desirable to ensure the timeout exception does not fire inside an +ensure+ block.
+ # The simplest and best way to do so is to put the Timeout.timeout call inside the body of the +begin+/+ensure+/+end+:
+ #
+ # begin
+ # Timeout.timeout(sec) { some_long_operation }
+ # ensure
+ # cleanup # safe, cannot be interrupted by timeout
+ # end
+ #
+ # If that is not feasible, e.g. if there are +ensure+ blocks inside +some_long_operation+,
+ # they need to not be interrupted by timeout, and it's not possible to move these ensure blocks outside,
+ # one can use Thread.handle_interrupt to delay the timeout exception like so:
+ #
+ # Thread.handle_interrupt(Timeout::Error => :never) {
+ # Timeout.timeout(sec, Timeout::Error) do
+ # setup # timeout cannot happen here, no matter how long it takes
+ # Thread.handle_interrupt(Timeout::Error => :immediate) {
+ # some_long_operation # timeout can happen here
+ # }
+ # ensure
+ # cleanup # timeout cannot happen here, no matter how long it takes
+ # end
+ # }
+ #
+ # An important thing to note is the need to pass an exception +klass+ to Timeout.timeout,
+ # otherwise it does not work. Specifically, using <tt>Thread.handle_interrupt(Timeout::ExitException => ...)</tt>
+ # is unsupported and causes subtle errors like raising the wrong exception outside the block, do not use that.
+ #
+ # Note that Thread.handle_interrupt is somewhat dangerous because if setup or cleanup hangs
+ # then the current thread will hang too and the timeout will never fire.
+ # Also note the block might run for longer than +sec+ seconds:
+ # e.g. +some_long_operation+ executes for +sec+ seconds + whatever time cleanup takes.
+ #
+ # If you want the timeout to only happen on blocking operations, one can use +:on_blocking+
+ # instead of +:immediate+. However, that means if the block uses no blocking operations after +sec+ seconds,
+ # the block will not be interrupted.
+ def self.timeout(sec, klass = nil, message = nil, &block) #:yield: +sec+
return yield(sec) if sec == nil or sec.zero?
+ raise ArgumentError, "Timeout sec must be a non-negative number" if 0 > sec
message ||= "execution expired"
@@ -176,13 +285,12 @@ module Timeout
return scheduler.timeout_after(sec, klass || Error, message, &block)
end
- Timeout.ensure_timeout_thread_created
+ state = State.instance
+ state.ensure_timeout_thread_created
+
perform = Proc.new do |exc|
request = Request.new(Thread.current, sec, exc, message)
- QUEUE_MUTEX.synchronize do
- QUEUE << request
- CONDVAR.signal
- end
+ state.add_request(request)
begin
return yield(sec)
ensure
@@ -196,5 +304,8 @@ module Timeout
Error.handle_timeout(message, &perform)
end
end
- module_function :timeout
+
+ private def timeout(*args, &block)
+ Timeout.timeout(*args, &block)
+ end
end
diff --git a/lib/tmpdir.gemspec b/lib/tmpdir.gemspec
index 4c96e5984b..4935d1cb3c 100644
--- a/lib/tmpdir.gemspec
+++ b/lib/tmpdir.gemspec
@@ -1,6 +1,6 @@
Gem::Specification.new do |spec|
spec.name = "tmpdir"
- spec.version = "0.2.0"
+ spec.version = "0.3.1"
spec.authors = ["Yukihiro Matsumoto"]
spec.email = ["matz@ruby-lang.org"]
diff --git a/lib/tmpdir.rb b/lib/tmpdir.rb
index fe3e0e19d1..f78fd721b7 100644
--- a/lib/tmpdir.rb
+++ b/lib/tmpdir.rb
@@ -16,10 +16,6 @@ class Dir
# Class variables are inaccessible from non-main Ractor.
# And instance variables too, in Ruby 3.0.
- # System-wide temporary directory path
- SYSTMPDIR = (defined?(Etc.systmpdir) ? Etc.systmpdir.freeze : '/tmp')
- private_constant :SYSTMPDIR
-
##
# Returns the operating system's temporary file path.
#
@@ -27,7 +23,7 @@ class Dir
# Dir.tmpdir # => "/tmp"
def self.tmpdir
- ['TMPDIR', 'TMP', 'TEMP', ['system temporary path', SYSTMPDIR], ['/tmp']*2, ['.']*2].find do |name, dir|
+ Tmpname::TMPDIR_CANDIDATES.find do |name, dir|
unless dir
next if !(dir = ENV[name] rescue next) or dir.empty?
end
@@ -36,7 +32,9 @@ class Dir
case
when !stat.directory?
warn "#{name} is not a directory: #{dir}"
- when !stat.writable?
+ when !File.writable?(dir)
+ # We call File.writable?, not stat.writable?, because you can't tell if a dir is actually
+ # writable just from stat; OS mechanisms other than user/group/world bits can affect this.
warn "#{name} is not writable: #{dir}"
when stat.world_writable? && !stat.sticky?
warn "#{name} is world-writable: #{dir}"
@@ -96,13 +94,13 @@ class Dir
# FileUtils.remove_entry dir
# end
#
- def self.mktmpdir(prefix_suffix=nil, *rest, **options)
+ def self.mktmpdir(prefix_suffix=nil, *rest, **options, &block)
base = nil
path = Tmpname.create(prefix_suffix || "d", *rest, **options) {|path, _, _, d|
base = d
mkdir(path, 0700)
}
- if block_given?
+ if block
begin
yield path.dup
ensure
@@ -124,6 +122,18 @@ class Dir
module Tmpname # :nodoc:
module_function
+ # System-wide temporary directory path
+ systmpdir = (defined?(Etc.systmpdir) ? Etc.systmpdir.freeze : '/tmp')
+
+ # Temporary directory candidates consisting of environment variable
+ # names or description and path pairs.
+ TMPDIR_CANDIDATES = [
+ 'TMPDIR', 'TMP', 'TEMP',
+ ['system temporary path', systmpdir],
+ %w[/tmp /tmp],
+ %w[. .],
+ ].each(&:freeze).freeze
+
def tmpdir
Dir.tmpdir
end
@@ -147,8 +157,12 @@ class Dir
# Generates and yields random names to create a temporary name
def create(basename, tmpdir=nil, max_try: nil, **opts)
- origdir = tmpdir
- tmpdir ||= tmpdir()
+ if tmpdir
+ origdir = tmpdir = File.path(tmpdir)
+ raise ArgumentError, "empty parent path" if tmpdir.empty?
+ else
+ tmpdir = tmpdir()
+ end
n = nil
prefix, suffix = basename
prefix = (String.try_convert(prefix) or
diff --git a/lib/tsort.gemspec b/lib/tsort.gemspec
deleted file mode 100644
index 0e2f110a53..0000000000
--- a/lib/tsort.gemspec
+++ /dev/null
@@ -1,29 +0,0 @@
-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 = ["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/lib/tsort.rb b/lib/tsort.rb
deleted file mode 100644
index dbaed45415..0000000000
--- a/lib/tsort.rb
+++ /dev/null
@@ -1,455 +0,0 @@
-# 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",
-# <em>SIAM Journal on Computing</em>, Vol. 1, No. 2, pp. 146-160, June 1972.
-#
-
-module TSort
-
- VERSION = "0.2.0"
-
- 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 self.tsort(each_node, each_child)
- tsort_each(each_node, each_child).to_a
- end
-
- # The iterator version of the #tsort method.
- # <tt><em>obj</em>.tsort_each</tt> is similar to <tt><em>obj</em>.tsort.each</tt>, 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 self.tsort_each(each_node, each_child) # :yields: node
- return to_enum(__method__, each_node, each_child) unless block_given?
-
- 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 self.strongly_connected_components(each_node, each_child)
- each_strongly_connected_component(each_node, each_child).to_a
- end
-
- # The iterator version of the #strongly_connected_components method.
- # <tt><em>obj</em>.each_strongly_connected_component</tt> is similar to
- # <tt><em>obj</em>.strongly_connected_components.each</tt>, 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 self.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
- 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 self.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 =
- 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
diff --git a/lib/unicode_normalize/normalize.rb b/lib/unicode_normalize/normalize.rb
index 1caf2cc8c8..0447df8de7 100644
--- a/lib/unicode_normalize/normalize.rb
+++ b/lib/unicode_normalize/normalize.rb
@@ -82,16 +82,22 @@ module UnicodeNormalize # :nodoc:
## Canonical Ordering
def self.canonical_ordering_one(string)
- sorting = string.each_char.collect { |c| [c, CLASS_TABLE[c]] }
- (sorting.length-2).downto(0) do |i| # almost, but not exactly bubble sort
- (0..i).each do |j|
- later_class = sorting[j+1].last
- if 0<later_class and later_class<sorting[j].last
- sorting[j], sorting[j+1] = sorting[j+1], sorting[j]
- end
+ result = ''
+ unordered = []
+ chars = string.chars
+ n = chars.size
+ chars.each_with_index do |char, i|
+ ccc = CLASS_TABLE[char]
+ if ccc == 0
+ unordered.sort!.each { result << chars[it % n] }
+ unordered.clear
+ result << char
+ else
+ unordered << ccc * n + i
end
end
- return sorting.collect(&:first).join('')
+ unordered.sort!.each { result << chars[it % n] }
+ result
end
## Normalization Forms for Patterns (not whole Strings)
@@ -105,16 +111,22 @@ module UnicodeNormalize # :nodoc:
start = nfd_string[0]
last_class = CLASS_TABLE[start]-1
accents = ''
+ result = ''
nfd_string[1..-1].each_char do |accent|
accent_class = CLASS_TABLE[accent]
if last_class<accent_class and composite = COMPOSITION_TABLE[start+accent]
start = composite
+ elsif accent_class == 0
+ result << start << accents
+ start = accent
+ accents = ''
+ last_class = -1
else
accents << accent
last_class = accent_class
end
end
- hangul_comp_one(start+accents)
+ hangul_comp_one(result+start+accents)
end
def self.normalize(string, form = :nfc)
diff --git a/lib/unicode_normalize/tables.rb b/lib/unicode_normalize/tables.rb
index 7448fad13f..dd5d3499b8 100644
--- a/lib/unicode_normalize/tables.rb
+++ b/lib/unicode_normalize/tables.rb
@@ -1,6 +1,9 @@
# coding: us-ascii
# frozen_string_literal: true
+Encoding::UNICODE_VERSION == "17.0.0" or
+ raise "Unicode version mismatch: 17.0.0 expected but #{Encoding::UNICODE_VERSION}"
+
# automatically generated by template/unicode_norm_gen.tmpl
module UnicodeNormalize # :nodoc:
@@ -29,7 +32,7 @@ module UnicodeNormalize # :nodoc:
"\u0825-\u0827" \
"\u0829-\u082D" \
"\u0859-\u085B" \
- "\u0898-\u089F" \
+ "\u0897-\u089F" \
"\u08CA-\u08E1" \
"\u08E3-\u08FF" \
"\u093C" \
@@ -96,7 +99,8 @@ module UnicodeNormalize # :nodoc:
"\u1A75-\u1A7C" \
"\u1A7F" \
"\u1AB0-\u1ABD" \
- "\u1ABF-\u1ACE" \
+ "\u1ABF-\u1ADD" \
+ "\u1AE0-\u1AEB" \
"\u1B34\u1B35" \
"\u1B44" \
"\u1B6B-\u1B73" \
@@ -149,7 +153,9 @@ module UnicodeNormalize # :nodoc:
"\u{10A3F}" \
"\u{10AE5}\u{10AE6}" \
"\u{10D24}-\u{10D27}" \
+ "\u{10D69}-\u{10D6D}" \
"\u{10EAB}\u{10EAC}" \
+ "\u{10EFA}\u{10EFB}" \
"\u{10EFD}-\u{10EFF}" \
"\u{10F46}-\u{10F50}" \
"\u{10F82}-\u{10F85}" \
@@ -171,6 +177,12 @@ module UnicodeNormalize # :nodoc:
"\u{11357}" \
"\u{11366}-\u{1136C}" \
"\u{11370}-\u{11374}" \
+ "\u{113B8}" \
+ "\u{113BB}" \
+ "\u{113C2}" \
+ "\u{113C5}" \
+ "\u{113C7}-\u{113C9}" \
+ "\u{113CE}-\u{113D0}" \
"\u{11442}" \
"\u{11446}" \
"\u{1145E}" \
@@ -196,8 +208,11 @@ module UnicodeNormalize # :nodoc:
"\u{11D44}\u{11D45}" \
"\u{11D97}" \
"\u{11F41}\u{11F42}" \
+ "\u{1611E}-\u{16129}" \
+ "\u{1612F}" \
"\u{16AF0}-\u{16AF4}" \
"\u{16B30}-\u{16B36}" \
+ "\u{16D67}\u{16D68}" \
"\u{16FF0}\u{16FF1}" \
"\u{1BC9E}" \
"\u{1D165}-\u{1D169}" \
@@ -216,6 +231,11 @@ module UnicodeNormalize # :nodoc:
"\u{1E2AE}" \
"\u{1E2EC}-\u{1E2EF}" \
"\u{1E4EC}-\u{1E4EF}" \
+ "\u{1E5EE}\u{1E5EF}" \
+ "\u{1E6E3}" \
+ "\u{1E6E6}" \
+ "\u{1E6EE}\u{1E6EF}" \
+ "\u{1E6F5}" \
"\u{1E8D0}-\u{1E8D6}" \
"\u{1E944}-\u{1E94A}" \
"]"
@@ -441,15 +461,25 @@ module UnicodeNormalize # :nodoc:
"\uFB40\uFB41" \
"\uFB43\uFB44" \
"\uFB46-\uFB4E" \
+ "\u{105C9}" \
+ "\u{105E4}" \
"\u{1109A}" \
"\u{1109C}" \
"\u{110AB}" \
"\u{1112E}\u{1112F}" \
"\u{1134B}\u{1134C}" \
+ "\u{11383}" \
+ "\u{11385}" \
+ "\u{1138E}" \
+ "\u{11391}" \
+ "\u{113C5}" \
+ "\u{113C7}\u{113C8}" \
"\u{114BB}\u{114BC}" \
"\u{114BE}" \
"\u{115BA}\u{115BB}" \
"\u{11938}" \
+ "\u{16121}-\u{16128}" \
+ "\u{16D68}-\u{16D6A}" \
"\u{1D15E}-\u{1D164}" \
"\u{1D1BB}-\u{1D1C0}" \
"\u{2F800}-\u{2FA1D}" \
@@ -613,14 +643,25 @@ module UnicodeNormalize # :nodoc:
"\u30DB" \
"\u30EF-\u30F2" \
"\u30FD" \
+ "\u{105D2}" \
+ "\u{105DA}" \
"\u{11099}" \
"\u{1109B}" \
"\u{110A5}" \
"\u{11131}\u{11132}" \
"\u{11347}" \
+ "\u{11382}" \
+ "\u{11384}" \
+ "\u{1138B}" \
+ "\u{11390}" \
+ "\u{113C2}" \
"\u{114B9}" \
"\u{115B8}\u{115B9}" \
"\u{11935}" \
+ "\u{1611E}" \
+ "\u{16129}" \
+ "\u{16D63}" \
+ "\u{16D67}" \
"]?#{accents}+" \
"|#{'' # precomposed Hangul syllables
}" \
@@ -891,6 +932,10 @@ module UnicodeNormalize # :nodoc:
"\u30F4" \
"\u30F7-\u30FA" \
"\u30FD\u30FE" \
+ "\u{105C9}" \
+ "\u{105D2}" \
+ "\u{105DA}" \
+ "\u{105E4}" \
"\u{11099}-\u{1109C}" \
"\u{110A5}" \
"\u{110AB}" \
@@ -898,12 +943,23 @@ module UnicodeNormalize # :nodoc:
"\u{11131}\u{11132}" \
"\u{11347}" \
"\u{1134B}\u{1134C}" \
+ "\u{11382}-\u{11385}" \
+ "\u{1138B}" \
+ "\u{1138E}" \
+ "\u{11390}\u{11391}" \
+ "\u{113C2}" \
+ "\u{113C5}" \
+ "\u{113C7}\u{113C8}" \
"\u{114B9}" \
"\u{114BB}\u{114BC}" \
"\u{114BE}" \
"\u{115B8}-\u{115BB}" \
"\u{11935}" \
"\u{11938}" \
+ "\u{1611E}" \
+ "\u{16121}-\u{16129}" \
+ "\u{16D63}" \
+ "\u{16D67}-\u{16D6A}" \
"]?#{accents}+" \
"|#{'' # Hangul syllables with separate trailer
}" \
@@ -1410,7 +1466,7 @@ module UnicodeNormalize # :nodoc:
"\u3280-\u33FF" \
"\uA69C\uA69D" \
"\uA770" \
- "\uA7F2-\uA7F4" \
+ "\uA7F1-\uA7F4" \
"\uA7F8\uA7F9" \
"\uAB5C-\uAB5F" \
"\uAB69" \
@@ -1440,6 +1496,7 @@ module UnicodeNormalize # :nodoc:
"\u{10781}-\u{10785}" \
"\u{10787}-\u{107B0}" \
"\u{107B2}-\u{107BA}" \
+ "\u{1CCD6}-\u{1CCF9}" \
"\u{1D400}-\u{1D454}" \
"\u{1D456}-\u{1D49C}" \
"\u{1D49E}\u{1D49F}" \
@@ -1789,6 +1846,7 @@ module UnicodeNormalize # :nodoc:
"\u0859"=>220,
"\u085A"=>220,
"\u085B"=>220,
+ "\u0897"=>230,
"\u0898"=>230,
"\u0899"=>220,
"\u089A"=>220,
@@ -1967,6 +2025,33 @@ module UnicodeNormalize # :nodoc:
"\u1ACC"=>230,
"\u1ACD"=>230,
"\u1ACE"=>230,
+ "\u1ACF"=>230,
+ "\u1AD0"=>230,
+ "\u1AD1"=>230,
+ "\u1AD2"=>230,
+ "\u1AD3"=>230,
+ "\u1AD4"=>230,
+ "\u1AD5"=>230,
+ "\u1AD6"=>230,
+ "\u1AD7"=>230,
+ "\u1AD8"=>230,
+ "\u1AD9"=>230,
+ "\u1ADA"=>230,
+ "\u1ADB"=>230,
+ "\u1ADC"=>230,
+ "\u1ADD"=>220,
+ "\u1AE0"=>230,
+ "\u1AE1"=>230,
+ "\u1AE2"=>230,
+ "\u1AE3"=>230,
+ "\u1AE4"=>230,
+ "\u1AE5"=>230,
+ "\u1AE6"=>220,
+ "\u1AE7"=>230,
+ "\u1AE8"=>230,
+ "\u1AE9"=>230,
+ "\u1AEA"=>230,
+ "\u1AEB"=>234,
"\u1B34"=>7,
"\u1B44"=>9,
"\u1B6B"=>230,
@@ -2234,8 +2319,15 @@ module UnicodeNormalize # :nodoc:
"\u{10D25}"=>230,
"\u{10D26}"=>230,
"\u{10D27}"=>230,
+ "\u{10D69}"=>230,
+ "\u{10D6A}"=>230,
+ "\u{10D6B}"=>230,
+ "\u{10D6C}"=>230,
+ "\u{10D6D}"=>230,
"\u{10EAB}"=>230,
"\u{10EAC}"=>230,
+ "\u{10EFA}"=>220,
+ "\u{10EFB}"=>220,
"\u{10EFD}"=>220,
"\u{10EFE}"=>220,
"\u{10EFF}"=>220,
@@ -2286,6 +2378,9 @@ module UnicodeNormalize # :nodoc:
"\u{11372}"=>230,
"\u{11373}"=>230,
"\u{11374}"=>230,
+ "\u{113CE}"=>9,
+ "\u{113CF}"=>9,
+ "\u{113D0}"=>9,
"\u{11442}"=>9,
"\u{11446}"=>7,
"\u{1145E}"=>230,
@@ -2313,6 +2408,7 @@ module UnicodeNormalize # :nodoc:
"\u{11D97}"=>9,
"\u{11F41}"=>9,
"\u{11F42}"=>9,
+ "\u{1612F}"=>9,
"\u{16AF0}"=>1,
"\u{16AF1}"=>1,
"\u{16AF2}"=>1,
@@ -2416,6 +2512,13 @@ module UnicodeNormalize # :nodoc:
"\u{1E4ED}"=>232,
"\u{1E4EE}"=>220,
"\u{1E4EF}"=>230,
+ "\u{1E5EE}"=>230,
+ "\u{1E5EF}"=>220,
+ "\u{1E6E3}"=>230,
+ "\u{1E6E6}"=>230,
+ "\u{1E6EE}"=>230,
+ "\u{1E6EF}"=>230,
+ "\u{1E6F5}"=>230,
"\u{1E8D0}"=>220,
"\u{1E8D1}"=>220,
"\u{1E8D2}"=>220,
@@ -3928,6 +4031,8 @@ module UnicodeNormalize # :nodoc:
"\uFB4C"=>"\u05D1\u05BF",
"\uFB4D"=>"\u05DB\u05BF",
"\uFB4E"=>"\u05E4\u05BF",
+ "\u{105C9}"=>"\u{105D2}\u0307",
+ "\u{105E4}"=>"\u{105DA}\u0307",
"\u{1109A}"=>"\u{11099}\u{110BA}",
"\u{1109C}"=>"\u{1109B}\u{110BA}",
"\u{110AB}"=>"\u{110A5}\u{110BA}",
@@ -3935,12 +4040,30 @@ module UnicodeNormalize # :nodoc:
"\u{1112F}"=>"\u{11132}\u{11127}",
"\u{1134B}"=>"\u{11347}\u{1133E}",
"\u{1134C}"=>"\u{11347}\u{11357}",
+ "\u{11383}"=>"\u{11382}\u{113C9}",
+ "\u{11385}"=>"\u{11384}\u{113BB}",
+ "\u{1138E}"=>"\u{1138B}\u{113C2}",
+ "\u{11391}"=>"\u{11390}\u{113C9}",
+ "\u{113C5}"=>"\u{113C2}\u{113C2}",
+ "\u{113C7}"=>"\u{113C2}\u{113B8}",
+ "\u{113C8}"=>"\u{113C2}\u{113C9}",
"\u{114BB}"=>"\u{114B9}\u{114BA}",
"\u{114BC}"=>"\u{114B9}\u{114B0}",
"\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{16121}"=>"\u{1611E}\u{1611E}",
+ "\u{16122}"=>"\u{1611E}\u{16129}",
+ "\u{16123}"=>"\u{1611E}\u{1611F}",
+ "\u{16124}"=>"\u{16129}\u{1611F}",
+ "\u{16125}"=>"\u{1611E}\u{16120}",
+ "\u{16126}"=>"\u{1611E}\u{1611E}\u{1611F}",
+ "\u{16127}"=>"\u{1611E}\u{16129}\u{1611F}",
+ "\u{16128}"=>"\u{1611E}\u{1611E}\u{16120}",
+ "\u{16D68}"=>"\u{16D67}\u{16D67}",
+ "\u{16D69}"=>"\u{16D63}\u{16D67}",
+ "\u{16D6A}"=>"\u{16D63}\u{16D67}\u{16D67}",
"\u{1D15E}"=>"\u{1D157}\u{1D165}",
"\u{1D15F}"=>"\u{1D158}\u{1D165}",
"\u{1D160}"=>"\u{1D158}\u{1D165}\u{1D16E}",
@@ -5839,6 +5962,7 @@ module UnicodeNormalize # :nodoc:
"\uA69C"=>"\u044A",
"\uA69D"=>"\u044C",
"\uA770"=>"\uA76F",
+ "\uA7F1"=>"S",
"\uA7F2"=>"C",
"\uA7F3"=>"F",
"\uA7F4"=>"Q",
@@ -6950,6 +7074,42 @@ module UnicodeNormalize # :nodoc:
"\u{107B8}"=>"\u01C2",
"\u{107B9}"=>"\u{1DF0A}",
"\u{107BA}"=>"\u{1DF1E}",
+ "\u{1CCD6}"=>"A",
+ "\u{1CCD7}"=>"B",
+ "\u{1CCD8}"=>"C",
+ "\u{1CCD9}"=>"D",
+ "\u{1CCDA}"=>"E",
+ "\u{1CCDB}"=>"F",
+ "\u{1CCDC}"=>"G",
+ "\u{1CCDD}"=>"H",
+ "\u{1CCDE}"=>"I",
+ "\u{1CCDF}"=>"J",
+ "\u{1CCE0}"=>"K",
+ "\u{1CCE1}"=>"L",
+ "\u{1CCE2}"=>"M",
+ "\u{1CCE3}"=>"N",
+ "\u{1CCE4}"=>"O",
+ "\u{1CCE5}"=>"P",
+ "\u{1CCE6}"=>"Q",
+ "\u{1CCE7}"=>"R",
+ "\u{1CCE8}"=>"S",
+ "\u{1CCE9}"=>"T",
+ "\u{1CCEA}"=>"U",
+ "\u{1CCEB}"=>"V",
+ "\u{1CCEC}"=>"W",
+ "\u{1CCED}"=>"X",
+ "\u{1CCEE}"=>"Y",
+ "\u{1CCEF}"=>"Z",
+ "\u{1CCF0}"=>"0",
+ "\u{1CCF1}"=>"1",
+ "\u{1CCF2}"=>"2",
+ "\u{1CCF3}"=>"3",
+ "\u{1CCF4}"=>"4",
+ "\u{1CCF5}"=>"5",
+ "\u{1CCF6}"=>"6",
+ "\u{1CCF7}"=>"7",
+ "\u{1CCF8}"=>"8",
+ "\u{1CCF9}"=>"9",
"\u{1D400}"=>"A",
"\u{1D401}"=>"B",
"\u{1D402}"=>"C",
@@ -9242,6 +9402,8 @@ module UnicodeNormalize # :nodoc:
"\u30F1\u3099"=>"\u30F9",
"\u30F2\u3099"=>"\u30FA",
"\u30FD\u3099"=>"\u30FE",
+ "\u{105D2}\u0307"=>"\u{105C9}",
+ "\u{105DA}\u0307"=>"\u{105E4}",
"\u{11099}\u{110BA}"=>"\u{1109A}",
"\u{1109B}\u{110BA}"=>"\u{1109C}",
"\u{110A5}\u{110BA}"=>"\u{110AB}",
@@ -9249,11 +9411,29 @@ module UnicodeNormalize # :nodoc:
"\u{11132}\u{11127}"=>"\u{1112F}",
"\u{11347}\u{1133E}"=>"\u{1134B}",
"\u{11347}\u{11357}"=>"\u{1134C}",
+ "\u{11382}\u{113C9}"=>"\u{11383}",
+ "\u{11384}\u{113BB}"=>"\u{11385}",
+ "\u{1138B}\u{113C2}"=>"\u{1138E}",
+ "\u{11390}\u{113C9}"=>"\u{11391}",
+ "\u{113C2}\u{113C2}"=>"\u{113C5}",
+ "\u{113C2}\u{113B8}"=>"\u{113C7}",
+ "\u{113C2}\u{113C9}"=>"\u{113C8}",
"\u{114B9}\u{114BA}"=>"\u{114BB}",
"\u{114B9}\u{114B0}"=>"\u{114BC}",
"\u{114B9}\u{114BD}"=>"\u{114BE}",
"\u{115B8}\u{115AF}"=>"\u{115BA}",
"\u{115B9}\u{115AF}"=>"\u{115BB}",
"\u{11935}\u{11930}"=>"\u{11938}",
+ "\u{1611E}\u{1611E}"=>"\u{16121}",
+ "\u{1611E}\u{16129}"=>"\u{16122}",
+ "\u{1611E}\u{1611F}"=>"\u{16123}",
+ "\u{16129}\u{1611F}"=>"\u{16124}",
+ "\u{1611E}\u{16120}"=>"\u{16125}",
+ "\u{16121}\u{1611F}"=>"\u{16126}",
+ "\u{16122}\u{1611F}"=>"\u{16127}",
+ "\u{16121}\u{16120}"=>"\u{16128}",
+ "\u{16D67}\u{16D67}"=>"\u{16D68}",
+ "\u{16D63}\u{16D67}"=>"\u{16D69}",
+ "\u{16D69}\u{16D67}"=>"\u{16D6A}",
}.freeze
end
diff --git a/lib/uri/common.rb b/lib/uri/common.rb
index dce09fbc1e..0b3bb4f099 100644
--- a/lib/uri/common.rb
+++ b/lib/uri/common.rb
@@ -13,24 +13,54 @@ require_relative "rfc2396_parser"
require_relative "rfc3986_parser"
module URI
- include RFC2396_REGEXP
+ # The default parser instance for RFC 2396.
+ RFC2396_PARSER = RFC2396_Parser.new
+ Ractor.make_shareable(RFC2396_PARSER) if defined?(Ractor)
- REGEXP = RFC2396_REGEXP
- Parser = RFC2396_Parser
+ # The default parser instance for RFC 3986.
RFC3986_PARSER = RFC3986_Parser.new
Ractor.make_shareable(RFC3986_PARSER) if defined?(Ractor)
- # URI::Parser.new
- DEFAULT_PARSER = Parser.new
- DEFAULT_PARSER.pattern.each_pair do |sym, str|
- unless REGEXP::PATTERN.const_defined?(sym)
- REGEXP::PATTERN.const_set(sym, str)
+ # The default parser instance.
+ DEFAULT_PARSER = RFC3986_PARSER
+ Ractor.make_shareable(DEFAULT_PARSER) if defined?(Ractor)
+
+ # Set the default parser instance.
+ def self.parser=(parser = RFC3986_PARSER)
+ remove_const(:Parser) if defined?(::URI::Parser)
+ const_set("Parser", parser.class)
+
+ remove_const(:PARSER) if defined?(::URI::PARSER)
+ const_set("PARSER", parser)
+
+ remove_const(:REGEXP) if defined?(::URI::REGEXP)
+ remove_const(:PATTERN) if defined?(::URI::PATTERN)
+ if Parser == RFC2396_Parser
+ const_set("REGEXP", URI::RFC2396_REGEXP)
+ const_set("PATTERN", URI::RFC2396_REGEXP::PATTERN)
+ end
+
+ Parser.new.regexp.each_pair do |sym, str|
+ remove_const(sym) if const_defined?(sym, false)
+ const_set(sym, str)
end
end
- DEFAULT_PARSER.regexp.each_pair do |sym, str|
- const_set(sym, str)
+ self.parser = RFC3986_PARSER
+
+ def self.const_missing(const) # :nodoc:
+ if const == :REGEXP
+ warn "URI::REGEXP is obsolete. Use URI::RFC2396_REGEXP explicitly.", uplevel: 1 if $VERBOSE
+ URI::RFC2396_REGEXP
+ elsif value = RFC2396_PARSER.regexp[const]
+ warn "URI::#{const} is obsolete. Use URI::RFC2396_PARSER.regexp[#{const.inspect}] explicitly.", uplevel: 1 if $VERBOSE
+ value
+ elsif value = RFC2396_Parser.const_get(const)
+ warn "URI::#{const} is obsolete. Use URI::RFC2396_Parser::#{const} explicitly.", uplevel: 1 if $VERBOSE
+ value
+ else
+ super
+ end
end
- Ractor.make_shareable(DEFAULT_PARSER) if defined?(Ractor)
module Util # :nodoc:
def make_components_hash(klass, array_hash)
@@ -64,7 +94,41 @@ module URI
module_function :make_components_hash
end
- module Schemes
+ module Schemes # :nodoc:
+ class << self
+ ReservedChars = ".+-"
+ EscapedChars = "\u01C0\u01C1\u01C2"
+ # Use Lo category chars as escaped chars for TruffleRuby, which
+ # does not allow Symbol categories as identifiers.
+
+ def escape(name)
+ unless name and name.ascii_only?
+ return nil
+ end
+ name.upcase.tr(ReservedChars, EscapedChars)
+ end
+
+ def unescape(name)
+ name.tr(EscapedChars, ReservedChars).encode(Encoding::US_ASCII).upcase
+ end
+
+ def find(name)
+ const_get(name, false) if name and const_defined?(name, false)
+ end
+
+ def register(name, klass)
+ unless scheme = escape(name)
+ raise ArgumentError, "invalid character as scheme - #{name}"
+ end
+ const_set(scheme, klass)
+ end
+
+ def list
+ constants.map { |name|
+ [unescape(name.to_s), const_get(name)]
+ }.to_h
+ end
+ end
end
private_constant :Schemes
@@ -77,7 +141,7 @@ module URI
# Note that after calling String#upcase on +scheme+, it must be a valid
# constant name.
def self.register_scheme(scheme, klass)
- Schemes.const_set(scheme.to_s.upcase, klass)
+ Schemes.register(scheme, klass)
end
# Returns a hash of the defined schemes:
@@ -95,14 +159,14 @@ module URI
#
# Related: URI.register_scheme.
def self.scheme_list
- Schemes.constants.map { |name|
- [name.to_s.upcase, Schemes.const_get(name)]
- }.to_h
+ Schemes.list
end
+ # :stopdoc:
INITIAL_SCHEMES = scheme_list
private_constant :INITIAL_SCHEMES
Ractor.make_shareable(INITIAL_SCHEMES) if defined?(Ractor)
+ # :startdoc:
# Returns a new object constructed from the given +scheme+, +arguments+,
# and +default+:
@@ -121,12 +185,10 @@ module URI
# # => #<URI::HTTP foo://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
#
def self.for(scheme, *arguments, default: Generic)
- const_name = scheme.to_s.upcase
+ const_name = Schemes.escape(scheme)
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 ||= Schemes.find(const_name)
uri_class ||= default
return uri_class.new(scheme, *arguments)
@@ -168,7 +230,7 @@ module URI
# ["fragment", "top"]]
#
def self.split(uri)
- RFC3986_PARSER.split(uri)
+ PARSER.split(uri)
end
# Returns a new \URI object constructed from the given string +uri+:
@@ -178,11 +240,11 @@ module URI
# URI.parse('http://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top')
# # => #<URI::HTTP http://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
#
- # It's recommended to first ::escape string +uri+
+ # It's recommended to first URI::RFC2396_PARSER.escape string +uri+
# if it may contain invalid URI characters.
#
def self.parse(uri)
- RFC3986_PARSER.parse(uri)
+ PARSER.parse(uri)
end
# Merges the given URI strings +str+
@@ -209,7 +271,7 @@ module URI
# # => #<URI::HTTP http://example.com/foo/bar>
#
def self.join(*str)
- RFC3986_PARSER.join(*str)
+ DEFAULT_PARSER.join(*str)
end
#
@@ -238,7 +300,7 @@ module URI
#
def self.extract(str, schemes = nil, &block) # :nodoc:
warn "URI.extract is obsolete", uplevel: 1 if $VERBOSE
- DEFAULT_PARSER.extract(str, schemes, &block)
+ PARSER.extract(str, schemes, &block)
end
#
@@ -275,14 +337,14 @@ module URI
#
def self.regexp(schemes = nil)# :nodoc:
warn "URI.regexp is obsolete", uplevel: 1 if $VERBOSE
- DEFAULT_PARSER.make_regexp(schemes)
+ PARSER.make_regexp(schemes)
end
TBLENCWWWCOMP_ = {} # :nodoc:
256.times do |i|
TBLENCWWWCOMP_[-i.chr] = -('%%%02X' % i)
end
- TBLENCURICOMP_ = TBLENCWWWCOMP_.dup.freeze
+ TBLENCURICOMP_ = TBLENCWWWCOMP_.dup.freeze # :nodoc:
TBLENCWWWCOMP_[' '] = '+'
TBLENCWWWCOMP_.freeze
TBLDECWWWCOMP_ = {} # :nodoc:
@@ -380,6 +442,8 @@ module URI
_decode_uri_component(/%\h\h/, str, enc)
end
+ # Returns a string derived from the given string +str+ with
+ # URI-encoded characters matching +regexp+ according to +table+.
def self._encode_uri_component(regexp, table, str, enc)
str = str.to_s.dup
if str.encoding != Encoding::ASCII_8BIT
@@ -394,6 +458,8 @@ module URI
end
private_class_method :_encode_uri_component
+ # Returns a string decoding characters matching +regexp+ from the
+ # given \URL-encoded string +str+.
def self._decode_uri_component(regexp, str, enc)
raise ArgumentError, "invalid %-encoding (#{str})" if /%(?!\h\h)/.match?(str)
str.b.gsub(regexp, TBLDECWWWCOMP_).force_encoding(enc)
@@ -832,6 +898,7 @@ module Kernel
# Returns a \URI object derived from the given +uri+,
# which may be a \URI string or an existing \URI object:
#
+ # require 'uri'
# # Returns a new URI.
# uri = URI('http://github.com/ruby/ruby')
# # => #<URI::HTTP http://github.com/ruby/ruby>
@@ -839,6 +906,8 @@ module Kernel
# URI(uri)
# # => #<URI::HTTP http://github.com/ruby/ruby>
#
+ # You must require 'uri' to use this method.
+ #
def URI(uri)
if uri.is_a?(URI::Generic)
uri
diff --git a/lib/uri/file.rb b/lib/uri/file.rb
index 4ff0bc097e..47b5aef067 100644
--- a/lib/uri/file.rb
+++ b/lib/uri/file.rb
@@ -47,7 +47,7 @@ module URI
# :path => '/ruby/src'})
# uri2.to_s # => "file://host.example.com/ruby/src"
#
- # uri3 = URI::File.build({:path => URI::escape('/path/my file.txt')})
+ # uri3 = URI::File.build({:path => URI::RFC2396_PARSER.escape('/path/my file.txt')})
# uri3.to_s # => "file:///path/my%20file.txt"
#
def self.build(args)
@@ -70,17 +70,17 @@ module URI
# raise InvalidURIError
def check_userinfo(user)
- raise URI::InvalidURIError, "can not set userinfo for file URI"
+ raise URI::InvalidURIError, "cannot set userinfo for file URI"
end
# raise InvalidURIError
def check_user(user)
- raise URI::InvalidURIError, "can not set user for file URI"
+ raise URI::InvalidURIError, "cannot set user for file URI"
end
# raise InvalidURIError
def check_password(user)
- raise URI::InvalidURIError, "can not set password for file URI"
+ raise URI::InvalidURIError, "cannot set password for file URI"
end
# do nothing
diff --git a/lib/uri/generic.rb b/lib/uri/generic.rb
index bdd366661e..6a0f638d76 100644
--- a/lib/uri/generic.rb
+++ b/lib/uri/generic.rb
@@ -73,7 +73,7 @@ module URI
#
# At first, tries to create a new URI::Generic instance using
# URI::Generic::build. But, if exception URI::InvalidComponentError is raised,
- # then it does URI::Escape.escape all URI components and tries again.
+ # then it does URI::RFC2396_PARSER.escape all URI components and tries again.
#
def self.build2(args)
begin
@@ -82,7 +82,7 @@ module URI
if args.kind_of?(Array)
return self.build(args.collect{|x|
if x.is_a?(String)
- DEFAULT_PARSER.escape(x)
+ URI::RFC2396_PARSER.escape(x)
else
x
end
@@ -91,7 +91,7 @@ module URI
tmp = {}
args.each do |key, value|
tmp[key] = if value
- DEFAULT_PARSER.escape(value)
+ URI::RFC2396_PARSER.escape(value)
else
value
end
@@ -126,9 +126,9 @@ module URI
end
end
else
- component = self.class.component rescue ::URI::Generic::COMPONENT
+ component = self.component rescue ::URI::Generic::COMPONENT
raise ArgumentError,
- "expected Array of or Hash of components of #{self.class} (#{component.join(', ')})"
+ "expected Array of or Hash of components of #{self} (#{component.join(', ')})"
end
tmp << nil
@@ -186,18 +186,18 @@ module URI
if arg_check
self.scheme = scheme
- self.userinfo = userinfo
self.hostname = host
self.port = port
+ self.userinfo = userinfo
self.path = path
self.query = query
self.opaque = opaque
self.fragment = fragment
else
self.set_scheme(scheme)
- self.set_userinfo(userinfo)
self.set_host(host)
self.set_port(port)
+ self.set_userinfo(userinfo)
self.set_path(path)
self.query = query
self.set_opaque(opaque)
@@ -284,7 +284,7 @@ module URI
# Returns the parser to be used.
#
- # Unless a URI::Parser is defined, DEFAULT_PARSER is used.
+ # Unless the +parser+ is defined, DEFAULT_PARSER is used.
#
def parser
if !defined?(@parser) || !@parser
@@ -315,7 +315,7 @@ module URI
end
#
- # Checks the scheme +v+ component against the URI::Parser Regexp for :SCHEME.
+ # Checks the scheme +v+ component against the +parser+ Regexp for :SCHEME.
#
def check_scheme(v)
if v && parser.regexp[:SCHEME] !~ v
@@ -385,7 +385,7 @@ module URI
#
# Checks the user +v+ component for RFC2396 compliance
- # and against the URI::Parser Regexp for :USERINFO.
+ # and against the +parser+ Regexp for :USERINFO.
#
# Can not have a registry or opaque component defined,
# with a user component defined.
@@ -393,7 +393,7 @@ module URI
def check_user(v)
if @opaque
raise InvalidURIError,
- "can not set user with opaque"
+ "cannot set user with opaque"
end
return v unless v
@@ -409,7 +409,7 @@ module URI
#
# Checks the password +v+ component for RFC2396 compliance
- # and against the URI::Parser Regexp for :USERINFO.
+ # and against the +parser+ Regexp for :USERINFO.
#
# Can not have a registry or opaque component defined,
# with a user component defined.
@@ -417,7 +417,7 @@ module URI
def check_password(v, user = @user)
if @opaque
raise InvalidURIError,
- "can not set password with opaque"
+ "cannot set password with opaque"
end
return v unless v
@@ -466,7 +466,7 @@ module URI
#
# uri = URI.parse("http://john:S3nsit1ve@my.example.com")
# uri.user = "sam"
- # uri.to_s #=> "http://sam:V3ry_S3nsit1ve@my.example.com"
+ # uri.to_s #=> "http://sam@my.example.com"
#
def user=(user)
check_user(user)
@@ -511,7 +511,7 @@ module URI
user, password = split_userinfo(user)
end
@user = user
- @password = password if password
+ @password = password
[@user, @password]
end
@@ -522,7 +522,7 @@ module URI
# See also URI::Generic.user=.
#
def set_user(v)
- set_userinfo(v, @password)
+ set_userinfo(v, nil)
v
end
protected :set_user
@@ -574,6 +574,12 @@ module URI
@password
end
+ # Returns the authority info (array of user, password, host and
+ # port), if any is set. Or returns +nil+.
+ def authority
+ return @user, @password, @host, @port if @user || @password || @host || @port
+ end
+
# Returns the user component after URI decoding.
def decoded_user
URI.decode_uri_component(@user) if @user
@@ -586,7 +592,7 @@ module URI
#
# Checks the host +v+ component for RFC2396 compliance
- # and against the URI::Parser Regexp for :HOST.
+ # and against the +parser+ Regexp for :HOST.
#
# Can not have a registry or opaque component defined,
# with a host component defined.
@@ -596,7 +602,7 @@ module URI
if @opaque
raise InvalidURIError,
- "can not set host with registry or opaque"
+ "cannot set host with registry or opaque"
elsif parser.regexp[:HOST] !~ v
raise InvalidComponentError,
"bad component(expected host component): #{v}"
@@ -615,6 +621,13 @@ module URI
end
protected :set_host
+ # Protected setter for the authority info (+user+, +password+, +host+
+ # and +port+). If +port+ is +nil+, +default_port+ will be set.
+ #
+ protected def set_authority(user, password, host, port = nil)
+ @user, @password, @host, @port = user, password, host, port || self.default_port
+ end
+
#
# == Args
#
@@ -639,6 +652,7 @@ module URI
def host=(v)
check_host(v)
set_host(v)
+ set_userinfo(nil)
v
end
@@ -675,7 +689,7 @@ module URI
#
# Checks the port +v+ component for RFC2396 compliance
- # and against the URI::Parser Regexp for :PORT.
+ # and against the +parser+ Regexp for :PORT.
#
# Can not have a registry or opaque component defined,
# with a port component defined.
@@ -685,7 +699,7 @@ module URI
if @opaque
raise InvalidURIError,
- "can not set port with registry or opaque"
+ "cannot set port with registry or opaque"
elsif !v.kind_of?(Integer) && parser.regexp[:PORT] !~ v
raise InvalidComponentError,
"bad component(expected port component): #{v.inspect}"
@@ -729,26 +743,27 @@ module URI
def port=(v)
check_port(v)
set_port(v)
+ set_userinfo(nil)
port
end
def check_registry(v) # :nodoc:
- raise InvalidURIError, "can not set registry"
+ raise InvalidURIError, "cannot set registry"
end
private :check_registry
- def set_registry(v) #:nodoc:
- raise InvalidURIError, "can not set registry"
+ def set_registry(v) # :nodoc:
+ raise InvalidURIError, "cannot set registry"
end
protected :set_registry
- def registry=(v)
- raise InvalidURIError, "can not set registry"
+ def registry=(v) # :nodoc:
+ raise InvalidURIError, "cannot set registry"
end
#
# Checks the path +v+ component for RFC2396 compliance
- # and against the URI::Parser Regexp
+ # and against the +parser+ Regexp
# for :ABS_PATH and :REL_PATH.
#
# Can not have a opaque component defined,
@@ -853,7 +868,7 @@ module URI
#
# Checks the opaque +v+ component for RFC2396 compliance and
- # against the URI::Parser Regexp for :OPAQUE.
+ # against the +parser+ Regexp for :OPAQUE.
#
# Can not have a host, port, user, or path component defined,
# with an opaque component defined.
@@ -866,7 +881,7 @@ module URI
# hier_part = ( net_path | abs_path ) [ "?" query ]
if @host || @port || @user || @path # userinfo = @user + ':' + @password
raise InvalidURIError,
- "can not set opaque with host, port, userinfo or path"
+ "cannot set opaque with host, port, userinfo or path"
elsif v && parser.regexp[:OPAQUE] !~ v
raise InvalidComponentError,
"bad component(expected opaque component): #{v}"
@@ -905,7 +920,7 @@ module URI
end
#
- # Checks the fragment +v+ component against the URI::Parser Regexp for :FRAGMENT.
+ # Checks the fragment +v+ component against the +parser+ Regexp for :FRAGMENT.
#
#
# == Args
@@ -1121,7 +1136,7 @@ module URI
base = self.dup
- authority = rel.userinfo || rel.host || rel.port
+ authority = rel.authority
# RFC2396, Section 5.2, 2)
if (rel.path.nil? || rel.path.empty?) && !authority && !rel.query
@@ -1133,17 +1148,14 @@ module URI
base.fragment=(nil)
# RFC2396, Section 5.2, 4)
- if !authority
- base.set_path(merge_path(base.path, rel.path)) if base.path && rel.path
- else
- # RFC2396, Section 5.2, 4)
- base.set_path(rel.path) if rel.path
+ if authority
+ base.set_authority(*authority)
+ base.set_path(rel.path)
+ elsif base.path && rel.path
+ base.set_path(merge_path(base.path, rel.path))
end
# RFC2396, Section 5.2, 7)
- base.set_userinfo(rel.userinfo) if rel.userinfo
- base.set_host(rel.host) if rel.host
- base.set_port(rel.port) if rel.port
base.query = rel.query if rel.query
base.fragment=(rel.fragment) if rel.fragment
@@ -1235,7 +1247,7 @@ module URI
return rel, rel
end
- # you can modify `rel', but can not `oth'.
+ # you can modify `rel', but cannot `oth'.
return oth, rel
end
private :route_from0
@@ -1260,7 +1272,7 @@ module URI
# #=> #<URI::Generic /main.rbx?page=1>
#
def route_from(oth)
- # you can modify `rel', but can not `oth'.
+ # you can modify `rel', but cannot `oth'.
begin
oth, rel = route_from0(oth)
rescue
@@ -1392,10 +1404,12 @@ module URI
end
end
+ # Returns the hash value.
def hash
self.component_ary.hash
end
+ # Compares with _oth_ for Hash.
def eql?(oth)
self.class == oth.class &&
parser == oth.parser &&
@@ -1438,7 +1452,7 @@ module URI
end
end
- def inspect
+ def inspect # :nodoc:
"#<#{self.class} #{self}>"
end
@@ -1526,7 +1540,7 @@ module URI
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
+ warn 'The environment variable HTTP_PROXY is discouraged. Please use http_proxy instead.', uplevel: 1
end
end
end
diff --git a/lib/uri/http.rb b/lib/uri/http.rb
index 900b132c8c..3c41cd4e93 100644
--- a/lib/uri/http.rb
+++ b/lib/uri/http.rb
@@ -61,6 +61,18 @@ module URI
super(tmp)
end
+ # Do not allow empty host names, as they are not allowed by RFC 3986.
+ def check_host(v)
+ ret = super
+
+ if ret && v.empty?
+ raise InvalidComponentError,
+ "bad component(expected host component): #{v}"
+ end
+
+ ret
+ end
+
#
# == Description
#
diff --git a/lib/uri/rfc2396_parser.rb b/lib/uri/rfc2396_parser.rb
index 00c66cf042..cefd126cc6 100644
--- a/lib/uri/rfc2396_parser.rb
+++ b/lib/uri/rfc2396_parser.rb
@@ -67,7 +67,7 @@ module URI
#
# == Synopsis
#
- # URI::Parser.new([opts])
+ # URI::RFC2396_Parser.new([opts])
#
# == Args
#
@@ -86,7 +86,7 @@ module URI
#
# == Examples
#
- # p = URI::Parser.new(:ESCAPED => "(?:%[a-fA-F0-9]{2}|%u[a-fA-F0-9]{4})")
+ # p = URI::RFC2396_Parser.new(:ESCAPED => "(?:%[a-fA-F0-9]{2}|%u[a-fA-F0-9]{4})")
# u = p.parse("http://example.jp/%uABCD") #=> #<URI::HTTP http://example.jp/%uABCD>
# URI.parse(u.to_s) #=> raises URI::InvalidURIError
#
@@ -108,12 +108,12 @@ module URI
# The Hash of patterns.
#
- # See also URI::Parser.initialize_pattern.
+ # See also #initialize_pattern.
attr_reader :pattern
# The Hash of Regexp.
#
- # See also URI::Parser.initialize_regexp.
+ # See also #initialize_regexp.
attr_reader :regexp
# Returns a split URI against +regexp[:ABS_URI]+.
@@ -140,11 +140,11 @@ module URI
if !scheme
raise InvalidURIError,
- "bad URI(absolute but no scheme): #{uri}"
+ "bad URI (absolute but no scheme): #{uri}"
end
if !opaque && (!path && (!host && !registry))
raise InvalidURIError,
- "bad URI(absolute but no path): #{uri}"
+ "bad URI (absolute but no path): #{uri}"
end
when @regexp[:REL_URI]
@@ -173,7 +173,7 @@ module URI
# server = [ [ userinfo "@" ] hostport ]
else
- raise InvalidURIError, "bad URI(is not URI?): #{uri}"
+ raise InvalidURIError, "bad URI (is not URI?): #{uri}"
end
path = '' if !path && !opaque # (see RFC2396 Section 5.2)
@@ -202,8 +202,7 @@ module URI
#
# == Usage
#
- # p = URI::Parser.new
- # p.parse("ldap://ldap.example.com/dc=example?user=john")
+ # URI::RFC2396_PARSER.parse("ldap://ldap.example.com/dc=example?user=john")
# #=> #<URI::LDAP ldap://ldap.example.com/dc=example?user=john>
#
def parse(uri)
@@ -244,7 +243,7 @@ module URI
# If no +block+ given, then returns the result,
# else it calls +block+ for each element in result.
#
- # See also URI::Parser.make_regexp.
+ # See also #make_regexp.
#
def extract(str, schemes = nil)
if block_given?
@@ -263,7 +262,7 @@ module URI
unless schemes
@regexp[:ABS_URI_REF]
else
- /(?=#{Regexp.union(*schemes)}:)#{@pattern[:X_ABS_URI]}/x
+ /(?=(?i:#{Regexp.union(*schemes).source}):)#{@pattern[:X_ABS_URI]}/x
end
end
@@ -321,14 +320,14 @@ module URI
str.gsub(escaped) { [$&[1, 2]].pack('H2').force_encoding(enc) }
end
- @@to_s = Kernel.instance_method(:to_s)
- if @@to_s.respond_to?(:bind_call)
- def inspect
- @@to_s.bind_call(self)
+ TO_S = Kernel.instance_method(:to_s) # :nodoc:
+ if TO_S.respond_to?(:bind_call)
+ def inspect # :nodoc:
+ TO_S.bind_call(self)
end
else
- def inspect
- @@to_s.bind(self).call
+ def inspect # :nodoc:
+ TO_S.bind(self).call
end
end
@@ -524,6 +523,8 @@ module URI
ret
end
+ # Returns +uri+ as-is if it is URI, or convert it to URI if it is
+ # a String.
def convert_to_uri(uri)
if uri.is_a?(URI::Generic)
uri
@@ -536,4 +537,11 @@ module URI
end
end # class Parser
+
+ # Backward compatibility for URI::REGEXP::PATTERN::*
+ RFC2396_Parser.new.pattern.each_pair do |sym, str|
+ unless RFC2396_REGEXP::PATTERN.const_defined?(sym, false)
+ RFC2396_REGEXP::PATTERN.const_set(sym, str)
+ end
+ end
end # module URI
diff --git a/lib/uri/rfc3986_parser.rb b/lib/uri/rfc3986_parser.rb
index 092a1ac89d..0b5f0c4488 100644
--- a/lib/uri/rfc3986_parser.rb
+++ b/lib/uri/rfc3986_parser.rb
@@ -78,7 +78,7 @@ module URI
begin
uri = uri.to_str
rescue NoMethodError
- raise InvalidURIError, "bad URI(is not URI?): #{uri.inspect}"
+ raise InvalidURIError, "bad URI (is not URI?): #{uri.inspect}"
end
uri.ascii_only? or
raise InvalidURIError, "URI must be ascii only #{uri.dump}"
@@ -127,7 +127,7 @@ module URI
m["fragment"]
]
else
- raise InvalidURIError, "bad URI(is not URI?): #{uri.inspect}"
+ raise InvalidURIError, "bad URI (is not URI?): #{uri.inspect}"
end
end
@@ -135,12 +135,35 @@ module URI
URI.for(*self.split(uri), self)
end
-
def join(*uris) # :nodoc:
uris[0] = convert_to_uri(uris[0])
uris.inject :merge
end
+ # Compatibility for RFC2396 parser
+ def extract(str, schemes = nil, &block) # :nodoc:
+ warn "URI::RFC3986_PARSER.extract is obsolete. Use URI::RFC2396_PARSER.extract explicitly.", uplevel: 1 if $VERBOSE
+ RFC2396_PARSER.extract(str, schemes, &block)
+ end
+
+ # Compatibility for RFC2396 parser
+ def make_regexp(schemes = nil) # :nodoc:
+ warn "URI::RFC3986_PARSER.make_regexp is obsolete. Use URI::RFC2396_PARSER.make_regexp explicitly.", uplevel: 1 if $VERBOSE
+ RFC2396_PARSER.make_regexp(schemes)
+ end
+
+ # Compatibility for RFC2396 parser
+ def escape(str, unsafe = nil) # :nodoc:
+ warn "URI::RFC3986_PARSER.escape is obsolete. Use URI::RFC2396_PARSER.escape explicitly.", uplevel: 1 if $VERBOSE
+ unsafe ? RFC2396_PARSER.escape(str, unsafe) : RFC2396_PARSER.escape(str)
+ end
+
+ # Compatibility for RFC2396 parser
+ def unescape(str, escaped = nil) # :nodoc:
+ warn "URI::RFC3986_PARSER.unescape is obsolete. Use URI::RFC2396_PARSER.unescape explicitly.", uplevel: 1 if $VERBOSE
+ escaped ? RFC2396_PARSER.unescape(str, escaped) : RFC2396_PARSER.unescape(str)
+ end
+
@@to_s = Kernel.instance_method(:to_s)
if @@to_s.respond_to?(:bind_call)
def inspect
diff --git a/lib/uri/uri.gemspec b/lib/uri/uri.gemspec
index 9cf0a71196..0d0f897cba 100644
--- a/lib/uri/uri.gemspec
+++ b/lib/uri/uri.gemspec
@@ -30,8 +30,11 @@ 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.
+ gemspec = File.basename(__FILE__)
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
- `git ls-files -z 2>#{IO::NULL}`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ `git ls-files -z 2>#{IO::NULL}`.split("\x0").reject do |file|
+ (file == gemspec) || file.start_with?(*%w[bin/ test/ rakelib/ .github/ .gitignore Gemfile Rakefile])
+ end
end
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
diff --git a/lib/uri/version.rb b/lib/uri/version.rb
index 2dafa57d59..1f810602eb 100644
--- a/lib/uri/version.rb
+++ b/lib/uri/version.rb
@@ -1,6 +1,6 @@
module URI
# :stopdoc:
- VERSION_CODE = '001300'.freeze
- VERSION = VERSION_CODE.scan(/../).collect{|n| n.to_i}.join('.').freeze
+ VERSION = '1.1.1'.freeze
+ VERSION_CODE = VERSION.split('.').map{|s| s.rjust(2, '0')}.join.freeze
# :startdoc:
end
diff --git a/lib/weakref.gemspec b/lib/weakref.gemspec
index 03893f77e6..9d5c79851e 100644
--- a/lib/weakref.gemspec
+++ b/lib/weakref.gemspec
@@ -26,8 +26,6 @@ Gem::Specification.new do |spec|
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
`git ls-files -z 2>#{IO::NULL}`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
end
- spec.bindir = "exe"
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.add_dependency "delegate"
diff --git a/lib/weakref.rb b/lib/weakref.rb
index a8da39a26a..c7274f9664 100644
--- a/lib/weakref.rb
+++ b/lib/weakref.rb
@@ -17,7 +17,8 @@ require "delegate"
#
class WeakRef < Delegator
- VERSION = "0.1.3"
+ # The version string
+ VERSION = "0.1.4"
##
# RefError is raised when a referenced object has been recycled by the
@@ -41,7 +42,7 @@ class WeakRef < Delegator
super
end
- def __getobj__ # :nodoc:
+ def __getobj__(&_block) # :nodoc:
@@__map[self] or defined?(@delegate_sd_obj) ? @delegate_sd_obj :
Kernel::raise(RefError, "Invalid Reference - probably recycled", Kernel::caller(2))
end
diff --git a/lib/yaml.rb b/lib/yaml.rb
index b2669899dd..c6f0f89fd2 100644
--- a/lib/yaml.rb
+++ b/lib/yaml.rb
@@ -66,5 +66,6 @@ YAML = Psych # :nodoc:
#
# Syck can also be found on github: https://github.com/ruby/syck
module YAML
- LOADER_VERSION = "0.3.0"
+ # The version of YAML wrapper
+ LOADER_VERSION = "0.4.0"
end
diff --git a/lib/yaml/dbm.rb b/lib/yaml/dbm.rb
index e2508cd74b..a3cbaeccf6 100644
--- a/lib/yaml/dbm.rb
+++ b/lib/yaml/dbm.rb
@@ -1,6 +1,10 @@
# frozen_string_literal: false
require 'yaml'
-require 'dbm'
+
+begin
+ require 'dbm'
+rescue LoadError
+end
module YAML
@@ -16,7 +20,6 @@ module YAML
#
# See the documentation for ::DBM and ::YAML for more information.
class DBM < ::DBM
- VERSION = "0.1" # :nodoc:
# :call-seq:
# ydbm[key] -> value
@@ -56,7 +59,13 @@ class DBM < ::DBM
def fetch( keystr, ifnone = nil )
begin
val = super( keystr )
- return YAML.load( val ) if String === val
+ if String === val
+ if YAML.respond_to?(:safe_load)
+ return YAML.safe_load( val )
+ else
+ return YAML.load( val )
+ end
+ end
rescue IndexError
end
if block_given?
@@ -102,7 +111,11 @@ class DBM < ::DBM
def delete( key )
v = super( key )
if String === v
- v = YAML.load( v )
+ if YAML.respond_to?(:safe_load)
+ v = YAML.safe_load( v )
+ else
+ v = YAML.load( v )
+ end
end
v
end
@@ -149,7 +162,7 @@ class DBM < ::DBM
#
# Returns +self+.
def each_value # :yields: value
- super { |v| yield YAML.load( v ) }
+ super { |v| yield YAML.respond_to?(:safe_load) ? YAML.safe_load( v ) : YAML.load( v ) }
self
end
@@ -158,7 +171,7 @@ class DBM < ::DBM
#
# Returns an array of values from the database.
def values
- super.collect { |v| YAML.load( v ) }
+ super.collect { |v| YAML.respond_to?(:safe_load) ? YAML.safe_load( v ) : YAML.load( v ) }
end
# :call-seq:
@@ -204,7 +217,9 @@ class DBM < ::DBM
# The order in which values are removed/returned is not guaranteed.
def shift
a = super
- a[1] = YAML.load( a[1] ) if a
+ if a
+ a[1] = YAML.respond_to?(:safe_load) ? YAML.safe_load( a[1] ) : YAML.load( a[1] )
+ end
a
end
@@ -277,4 +292,4 @@ class DBM < ::DBM
alias :each :each_pair
end
-end
+end if defined?(DBM)
diff --git a/lib/yaml/store.rb b/lib/yaml/store.rb
index f24e4ad332..27c823b9f9 100644
--- a/lib/yaml/store.rb
+++ b/lib/yaml/store.rb
@@ -69,8 +69,16 @@ class YAML::Store < PStore
end
def load(content)
- table = YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(content) : YAML.load(content)
- if table == false
+ table = if YAML.respond_to?(:safe_load)
+ if Psych::VERSION >= "3.1"
+ YAML.safe_load(content, permitted_classes: [Symbol])
+ else
+ YAML.safe_load(content, [Symbol])
+ end
+ else
+ YAML.load(content)
+ end
+ if table == false || table == nil
{}
else
table
diff --git a/libexec/erb b/libexec/erb
index 4381671f25..de7d5888c3 100755
--- a/libexec/erb
+++ b/libexec/erb
@@ -90,29 +90,49 @@ class ERB
when '-P'
disable_percent = true
when '--help'
- raise "print this help"
+ raise ''
when /\A-/
- raise "unknown switch #{switch.dump}"
+ raise "Unknown switch: #{switch.dump}"
else
var, val = *switch.split('=', 2)
(variables ||= {})[var] = val
end
end
rescue # usage
- STDERR.puts $!.to_s
- STDERR.puts File.basename($0) +
- " [switches] [var=value...] [inputfile]"
+ message = $!.to_s
+ STDERR.puts message unless message.empty?
+ STDERR.puts 'Usage:'
+ STDERR.puts " #{File.basename($0)} [options] [filepaths]"
STDERR.puts <<EOU
- -x print ruby script
- -n print ruby script with line number
- -v enable verbose mode
- -d set $DEBUG to true
- -r library load a library
- -E ex[:in] set default external/internal encodings
- -U set default encoding to UTF-8
- -T trim_mode specify trim_mode (0..2, -)
- -P disable ruby code evaluation for lines beginning with %
- var=value set variable
+
+Options:
+ -d --debug Set $DEBUG to enable debugging.
+ -E ex[:in] --encoding ex[:in]
+ Set default external and internal encodings.
+ -h --help Print this text and exit.
+ -n Print generated Ruby source code with line numbers;
+ ignored if given without option -x.
+ -P Disable execution tag shorthand (for lines beginning with '%').
+ -r library Load the named library.
+ -T trim_mode Specify trim_mode:
+ '0' means '%'; '1' means '%>'; '2' means '<>'; '-' means '%-'.
+ -U Set default encoding to UTF-8.
+ -v Set $VERBOSE to enable debugging,
+ --version Print ERB version string and exit.
+ -x Print generated Ruby source code.
+ -- Treat all following words as filepaths (not options).
+ name=value Set the variable named name to the given string value.
+
+Filepaths:
+ The erb program reads the text from all files at the filepaths as a single ERB template:
+ plain text, possibly with embedded ERB tags;
+ filepaths may be repeated.
+
+ The pseudo-filepath '-' (hyphen character) specifies the standard input.
+
+ If no filepaths are given, the sole input is the standard input.
+
+See details and examples at https://docs.ruby-lang.org/en/master/erb_executable_md.html
EOU
exit 1
end
diff --git a/libexec/irb b/libexec/irb
deleted file mode 100755
index 12f41e4f0a..0000000000
--- a/libexec/irb
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/bin/env ruby
-#
-# irb.rb - interactive ruby
-# by Keiju ISHITSUKA(keiju@ruby-lang.org)
-#
-
-require "irb"
-
-IRB.start(__FILE__)
diff --git a/libexec/rdoc b/libexec/rdoc
deleted file mode 100755
index 95b6eea277..0000000000
--- a/libexec/rdoc
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env ruby
-#
-# RDoc: Documentation tool for source code
-# (see lib/rdoc/rdoc.rb for more information)
-#
-# Copyright (c) 2003 Dave Thomas
-# Released under the same terms as Ruby
-
-begin
- gem 'rdoc'
-rescue NameError => e # --disable-gems
- raise unless e.name == :gem
-rescue Gem::LoadError
-end
-
-require 'rdoc/rdoc'
-
-begin
- r = RDoc::RDoc.new
- r.document ARGV
-rescue Errno::ENOSPC
- $stderr.puts 'Ran out of space creating documentation'
- $stderr.puts
- $stderr.puts 'Please free up some space and try again'
-rescue SystemExit
- raise
-rescue Exception => e
- if $DEBUG_RDOC then
- $stderr.puts e.message
- $stderr.puts "#{e.backtrace.join "\n\t"}"
- $stderr.puts
- elsif Interrupt === e then
- $stderr.puts
- $stderr.puts 'Interrupted'
- else
- $stderr.puts "uh-oh! RDoc had a problem:"
- $stderr.puts e.message
- $stderr.puts
- $stderr.puts "run with --debug for full backtrace"
- end
-
- exit 1
-end
diff --git a/libexec/ri b/libexec/ri
deleted file mode 100755
index 7fbed0c099..0000000000
--- a/libexec/ri
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/usr/bin/env ruby
-
-begin
- gem 'rdoc'
-rescue NameError => e # --disable-gems
- raise unless e.name == :gem
-rescue Gem::LoadError
-end
-
-require 'rdoc/ri/driver'
-
-RDoc::RI::Driver.run ARGV
diff --git a/libexec/syntax_suggest b/libexec/syntax_suggest
index e4a0b0b658..3dc8eb94d1 100755
--- a/libexec/syntax_suggest
+++ b/libexec/syntax_suggest
@@ -1,6 +1,6 @@
#!/usr/bin/env ruby
-require_relative "../lib/syntax_suggest/api"
+require "syntax_suggest/api"
SyntaxSuggest::Cli.new(
argv: ARGV
diff --git a/load.c b/load.c
index 89e9ea8f99..144f095b04 100644
--- a/load.c
+++ b/load.c
@@ -5,8 +5,10 @@
#include "dln.h"
#include "eval_intern.h"
#include "internal.h"
+#include "internal/box.h"
#include "internal/dir.h"
#include "internal/error.h"
+#include "internal/eval.h"
#include "internal/file.h"
#include "internal/hash.h"
#include "internal/load.h"
@@ -18,23 +20,13 @@
#include "darray.h"
#include "ruby/encoding.h"
#include "ruby/util.h"
-
-static VALUE ruby_dln_libmap;
+#include "ractor_core.h"
+#include "vm_core.h"
#define IS_RBEXT(e) (strcmp((e), ".rb") == 0)
#define IS_SOEXT(e) (strcmp((e), ".so") == 0 || strcmp((e), ".o") == 0)
#define IS_DLEXT(e) (strcmp((e), DLEXT) == 0)
-#if SIZEOF_VALUE <= SIZEOF_LONG
-# define SVALUE2NUM(x) LONG2NUM((long)(x))
-# define NUM2SVALUE(x) (SIGNED_VALUE)NUM2LONG(x)
-#elif SIZEOF_VALUE <= SIZEOF_LONG_LONG
-# define SVALUE2NUM(x) LL2NUM((LONG_LONG)(x))
-# define NUM2SVALUE(x) (SIGNED_VALUE)NUM2LL(x)
-#else
-# error Need integer for VALUE
-#endif
-
enum {
loadable_ext_rb = (0+ /* .rb extension is the first in both tables */
1) /* offset by rb_find_file_ext() */
@@ -63,10 +55,11 @@ enum expand_type {
string objects in $LOAD_PATH are frozen.
*/
static void
-rb_construct_expanded_load_path(rb_vm_t *vm, enum expand_type type, int *has_relative, int *has_non_cache)
+rb_construct_expanded_load_path(rb_box_t *box, enum expand_type type, int *has_relative, int *has_non_cache)
{
- VALUE load_path = vm->load_path;
- VALUE expanded_load_path = vm->expanded_load_path;
+ VALUE load_path = box->load_path;
+ VALUE expanded_load_path = box->expanded_load_path;
+ VALUE snapshot;
VALUE ary;
long i;
@@ -104,109 +97,91 @@ rb_construct_expanded_load_path(rb_vm_t *vm, enum expand_type type, int *has_rel
if (NIL_P(expanded_path)) expanded_path = as_str;
rb_ary_push(ary, rb_fstring(expanded_path));
}
- rb_obj_freeze(ary);
- vm->expanded_load_path = ary;
- rb_ary_replace(vm->load_path_snapshot, vm->load_path);
+ rb_ary_freeze(ary);
+ box->expanded_load_path = ary;
+ snapshot = box->load_path_snapshot;
+ load_path = box->load_path;
+ rb_ary_replace(snapshot, load_path);
}
static VALUE
-get_expanded_load_path(rb_vm_t *vm)
+get_expanded_load_path(rb_box_t *box)
{
+ VALUE check_cache;
const VALUE non_cache = Qtrue;
+ const VALUE load_path_snapshot = box->load_path_snapshot;
+ const VALUE load_path = box->load_path;
- if (!rb_ary_shared_with_p(vm->load_path_snapshot, vm->load_path)) {
+ if (!rb_ary_shared_with_p(load_path_snapshot, 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(vm, EXPAND_ALL, &has_relative, &has_non_cache);
+ rb_construct_expanded_load_path(box, EXPAND_ALL, &has_relative, &has_non_cache);
if (has_relative) {
- vm->load_path_check_cache = rb_dir_getwd_ospath();
+ box->load_path_check_cache = rb_dir_getwd_ospath();
}
else if (has_non_cache) {
/* Non string object. */
- vm->load_path_check_cache = non_cache;
+ box->load_path_check_cache = non_cache;
}
else {
- vm->load_path_check_cache = 0;
+ box->load_path_check_cache = 0;
}
}
- else if (vm->load_path_check_cache == non_cache) {
+ else if ((check_cache = box->load_path_check_cache) == non_cache) {
int has_relative = 1, has_non_cache = 1;
/* Expand only non-cacheable objects. */
- rb_construct_expanded_load_path(vm, EXPAND_NON_CACHE,
+ rb_construct_expanded_load_path(box, EXPAND_NON_CACHE,
&has_relative, &has_non_cache);
}
- else if (vm->load_path_check_cache) {
+ else if (check_cache) {
int has_relative = 1, has_non_cache = 1;
VALUE cwd = rb_dir_getwd_ospath();
- if (!rb_str_equal(vm->load_path_check_cache, cwd)) {
+ if (!rb_str_equal(check_cache, cwd)) {
/* 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(vm, EXPAND_RELATIVE,
+ box->load_path_check_cache = cwd;
+ rb_construct_expanded_load_path(box, EXPAND_RELATIVE,
&has_relative, &has_non_cache);
}
else {
/* Expand only tilde (User HOME) and non-cacheable objects. */
- rb_construct_expanded_load_path(vm, EXPAND_HOME,
+ rb_construct_expanded_load_path(box, EXPAND_HOME,
&has_relative, &has_non_cache);
}
}
- return vm->expanded_load_path;
+ return box->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)
-{
- rb_vm_t *vm = (void *)p;
- return vm->load_path;
-}
-
-static VALUE
-get_loaded_features(rb_vm_t *vm)
-{
- return vm->loaded_features;
-}
-
-static VALUE
-get_loaded_features_realpaths(rb_vm_t *vm)
-{
- return vm->loaded_features_realpaths;
+ return get_expanded_load_path((rb_box_t *)rb_loading_box());
}
static VALUE
-get_loaded_features_realpath_map(rb_vm_t *vm)
+load_path_getter(ID _x, VALUE * _y)
{
- return vm->loaded_features_realpath_map;
+ return rb_loading_box()->load_path;
}
static VALUE
get_LOADED_FEATURES(ID _x, VALUE *_y)
{
- return get_loaded_features(GET_VM());
+ return rb_loading_box()->loaded_features;
}
static void
-reset_loaded_features_snapshot(rb_vm_t *vm)
+reset_loaded_features_snapshot(const rb_box_t *box)
{
- rb_ary_replace(vm->loaded_features_snapshot, vm->loaded_features);
+ VALUE snapshot = box->loaded_features_snapshot;
+ VALUE loaded_features = box->loaded_features;
+ rb_ary_replace(snapshot, loaded_features);
}
static struct st_table *
-get_loaded_features_index_raw(rb_vm_t *vm)
+get_loaded_features_index_raw(const rb_box_t *box)
{
- return vm->loaded_features_index;
-}
-
-static st_table *
-get_loading_table(rb_vm_t *vm)
-{
- return vm->loading_table;
+ return box->loaded_features_index;
}
static st_data_t
@@ -227,7 +202,7 @@ is_rbext_path(VALUE feature_path)
typedef rb_darray(long) feature_indexes_t;
struct features_index_add_single_args {
- rb_vm_t *vm;
+ const rb_box_t *box;
VALUE offset;
bool rb;
};
@@ -236,7 +211,7 @@ static int
features_index_add_single_callback(st_data_t *key, st_data_t *value, st_data_t raw_args, int existing)
{
struct features_index_add_single_args *args = (struct features_index_add_single_args *)raw_args;
- rb_vm_t *vm = args->vm;
+ const rb_box_t *box = args->box;
VALUE offset = args->offset;
bool rb = args->rb;
@@ -244,7 +219,7 @@ features_index_add_single_callback(st_data_t *key, st_data_t *value, st_data_t r
VALUE this_feature_index = *value;
if (FIXNUM_P(this_feature_index)) {
- VALUE loaded_features = get_loaded_features(vm);
+ VALUE loaded_features = box->loaded_features;
VALUE this_feature_path = RARRAY_AREF(loaded_features, FIX2LONG(this_feature_index));
feature_indexes_t feature_indexes;
@@ -264,7 +239,7 @@ features_index_add_single_callback(st_data_t *key, st_data_t *value, st_data_t r
long pos = -1;
if (rb) {
- VALUE loaded_features = get_loaded_features(vm);
+ VALUE loaded_features = box->loaded_features;
for (size_t i = 0; i < rb_darray_size(feature_indexes); ++i) {
long idx = rb_darray_get(feature_indexes, i);
VALUE this_feature_path = RARRAY_AREF(loaded_features, idx);
@@ -283,7 +258,7 @@ features_index_add_single_callback(st_data_t *key, st_data_t *value, st_data_t r
if (pos >= 0) {
long *ptr = rb_darray_data_ptr(feature_indexes);
long len = rb_darray_size(feature_indexes);
- MEMMOVE(ptr + pos, ptr + pos + 1, long, len - pos - 1);
+ MEMMOVE(ptr + pos + 1, ptr + pos, long, len - pos - 1);
ptr[pos] = FIX2LONG(offset);
}
}
@@ -296,7 +271,7 @@ features_index_add_single_callback(st_data_t *key, st_data_t *value, st_data_t r
}
static void
-features_index_add_single(rb_vm_t *vm, const char* str, size_t len, VALUE offset, bool rb)
+features_index_add_single(const rb_box_t *box, const char* str, size_t len, VALUE offset, bool rb)
{
struct st_table *features_index;
st_data_t short_feature_key;
@@ -304,10 +279,10 @@ features_index_add_single(rb_vm_t *vm, const char* str, size_t len, VALUE offset
Check_Type(offset, T_FIXNUM);
short_feature_key = feature_key(str, len);
- features_index = get_loaded_features_index_raw(vm);
+ features_index = get_loaded_features_index_raw(box);
struct features_index_add_single_args args = {
- .vm = vm,
+ .box = box,
.offset = offset,
.rb = rb,
};
@@ -324,8 +299,10 @@ features_index_add_single(rb_vm_t *vm, const char* str, size_t len, VALUE offset
relies on for its fast lookup.
*/
static void
-features_index_add(rb_vm_t *vm, VALUE feature, VALUE offset)
+features_index_add(const rb_box_t *box, VALUE feature, VALUE offset)
{
+ RUBY_ASSERT(rb_ractor_main_p());
+
const char *feature_str, *feature_end, *ext, *p;
bool rb = false;
@@ -350,14 +327,14 @@ features_index_add(rb_vm_t *vm, VALUE feature, VALUE offset)
if (p < feature_str)
break;
/* Now *p == '/'. We reach this point for every '/' in `feature`. */
- features_index_add_single(vm, p + 1, feature_end - p - 1, offset, false);
+ features_index_add_single(box, p + 1, feature_end - p - 1, offset, false);
if (ext) {
- features_index_add_single(vm, p + 1, ext - p - 1, offset, rb);
+ features_index_add_single(box, p + 1, ext - p - 1, offset, rb);
}
}
- features_index_add_single(vm, feature_str, feature_end - feature_str, offset, false);
+ features_index_add_single(box, feature_str, feature_end - feature_str, offset, false);
if (ext) {
- features_index_add_single(vm, feature_str, ext - feature_str, offset, rb);
+ features_index_add_single(box, feature_str, ext - feature_str, offset, rb);
}
}
@@ -371,30 +348,28 @@ loaded_features_index_clear_i(st_data_t key, st_data_t val, st_data_t arg)
return ST_DELETE;
}
-void
-rb_free_loaded_features_index(rb_vm_t *vm)
-{
- st_foreach(vm->loaded_features_index, loaded_features_index_clear_i, 0);
- st_free_table(vm->loaded_features_index);
-}
-
static st_table *
-get_loaded_features_index(rb_vm_t *vm)
+get_loaded_features_index(const rb_box_t *box)
{
- VALUE features;
int i;
+ VALUE features = box->loaded_features;
+ const VALUE snapshot = box->loaded_features_snapshot;
- if (!rb_ary_shared_with_p(vm->loaded_features_snapshot, vm->loaded_features)) {
+ if (!rb_ary_shared_with_p(snapshot, 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);
+ st_foreach(box->loaded_features_index, loaded_features_index_clear_i, 0);
- VALUE realpaths = vm->loaded_features_realpaths;
- VALUE realpath_map = vm->loaded_features_realpath_map;
+ VALUE realpaths = box->loaded_features_realpaths;
+ VALUE realpath_map = box->loaded_features_realpath_map;
VALUE previous_realpath_map = rb_hash_dup(realpath_map);
rb_hash_clear(realpaths);
rb_hash_clear(realpath_map);
- features = vm->loaded_features;
+
+ /* We have to make a copy of features here because the StringValue call
+ * below could call a Ruby method, which could modify $LOADED_FEATURES
+ * and cause it to be corrupt. */
+ features = rb_ary_resurrect(features);
for (i = 0; i < RARRAY_LEN(features); i++) {
VALUE entry, as_str;
as_str = entry = rb_ary_entry(features, i);
@@ -402,11 +377,15 @@ get_loaded_features_index(rb_vm_t *vm)
as_str = rb_fstring(as_str);
if (as_str != entry)
rb_ary_store(features, i, as_str);
- features_index_add(vm, as_str, INT2FIX(i));
+ features_index_add(box, as_str, INT2FIX(i));
}
- reset_loaded_features_snapshot(vm);
+ /* The user modified $LOADED_FEATURES, so we should restore the changes. */
+ if (!rb_ary_shared_with_p(features, box->loaded_features)) {
+ rb_ary_replace(box->loaded_features, features);
+ }
+ reset_loaded_features_snapshot(box);
- features = rb_ary_dup(vm->loaded_features_snapshot);
+ features = box->loaded_features_snapshot;
long j = RARRAY_LEN(features);
for (i = 0; i < j; i++) {
VALUE as_str = rb_ary_entry(features, i);
@@ -420,7 +399,7 @@ get_loaded_features_index(rb_vm_t *vm)
rb_hash_aset(realpath_map, as_str, realpath);
}
}
- return vm->loaded_features_index;
+ return box->loaded_features_index;
}
/* This searches `load_path` for a value such that
@@ -505,7 +484,7 @@ loaded_feature_path_i(st_data_t v, st_data_t b, st_data_t f)
* 'u': unsuffixed
*/
static int
-rb_feature_p(rb_vm_t *vm, const char *feature, const char *ext, int rb, int expanded, const char **fn)
+rb_feature_p(const rb_box_t *box, 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;
@@ -526,8 +505,8 @@ rb_feature_p(rb_vm_t *vm, const char *feature, const char *ext, int rb, int expa
elen = 0;
type = 0;
}
- features = get_loaded_features(vm);
- features_index = get_loaded_features_index(vm);
+ features = box->loaded_features;
+ features_index = get_loaded_features_index(box);
key = feature_key(feature, strlen(feature));
/* We search `features` for an entry such that either
@@ -569,12 +548,13 @@ rb_feature_p(rb_vm_t *vm, const char *feature, const char *ext, int rb, int expa
index = rb_darray_get(feature_indexes, i);
}
+ if (index >= RARRAY_LEN(features)) continue;
v = RARRAY_AREF(features, index);
f = StringValuePtr(v);
if ((n = RSTRING_LEN(v)) < len) continue;
if (strncmp(f, feature, len) != 0) {
if (expanded) continue;
- if (!load_path) load_path = get_expanded_load_path(vm);
+ if (!load_path) load_path = get_expanded_load_path((rb_box_t *)box);
if (!(p = loaded_feature_path(f, n, feature, len, type, load_path)))
continue;
expanded = 1;
@@ -594,14 +574,14 @@ rb_feature_p(rb_vm_t *vm, const char *feature, const char *ext, int rb, int expa
}
}
- loading_tbl = get_loading_table(vm);
+ loading_tbl = box->loading_table;
f = 0;
- if (!expanded) {
+ if (!expanded && !rb_is_absolute_path(feature)) {
struct loaded_feature_searching fs;
fs.name = feature;
fs.len = len;
fs.type = type;
- fs.load_path = load_path ? load_path : get_expanded_load_path(vm);
+ fs.load_path = load_path ? load_path : get_expanded_load_path((rb_box_t *)box);
fs.result = 0;
st_foreach(loading_tbl, loaded_feature_path_i, (st_data_t)&fs);
if ((f = fs.result) != 0) {
@@ -656,7 +636,7 @@ rb_provided(const char *feature)
}
static int
-feature_provided(rb_vm_t *vm, const char *feature, const char **loading)
+feature_provided(rb_box_t *box, const char *feature, const char **loading)
{
const char *ext = strrchr(feature, '.');
VALUE fullpath = 0;
@@ -668,15 +648,15 @@ feature_provided(rb_vm_t *vm, const char *feature, const char **loading)
}
if (ext && !strchr(ext, '/')) {
if (IS_RBEXT(ext)) {
- if (rb_feature_p(vm, feature, ext, TRUE, FALSE, loading)) return TRUE;
+ if (rb_feature_p(box, feature, ext, TRUE, FALSE, loading)) return TRUE;
return FALSE;
}
else if (IS_SOEXT(ext) || IS_DLEXT(ext)) {
- if (rb_feature_p(vm, feature, ext, FALSE, FALSE, loading)) return TRUE;
+ if (rb_feature_p(box, feature, ext, FALSE, FALSE, loading)) return TRUE;
return FALSE;
}
}
- if (rb_feature_p(vm, feature, 0, TRUE, FALSE, loading))
+ if (rb_feature_p(box, feature, 0, TRUE, FALSE, loading))
return TRUE;
RB_GC_GUARD(fullpath);
return FALSE;
@@ -685,35 +665,40 @@ feature_provided(rb_vm_t *vm, const char *feature, const char **loading)
int
rb_feature_provided(const char *feature, const char **loading)
{
- return feature_provided(GET_VM(), feature, loading);
+ rb_box_t *box = (rb_box_t *)rb_current_box();
+ return feature_provided(box, feature, loading);
}
static void
-rb_provide_feature(rb_vm_t *vm, VALUE feature)
+rb_provide_feature(const rb_box_t *box, VALUE feature)
{
VALUE features;
- features = get_loaded_features(vm);
+ features = box->loaded_features;
if (OBJ_FROZEN(features)) {
rb_raise(rb_eRuntimeError,
"$LOADED_FEATURES is frozen; cannot append feature");
}
feature = rb_fstring(feature);
- get_loaded_features_index(vm);
+ get_loaded_features_index(box);
// If loaded_features and loaded_features_snapshot share the same backing
// array, pushing into it would cause the whole array to be copied.
// To avoid this we first clear loaded_features_snapshot.
- rb_ary_clear(vm->loaded_features_snapshot);
+ rb_ary_clear(box->loaded_features_snapshot);
rb_ary_push(features, feature);
- features_index_add(vm, feature, INT2FIX(RARRAY_LEN(features)-1));
- reset_loaded_features_snapshot(vm);
+ features_index_add(box, feature, INT2FIX(RARRAY_LEN(features)-1));
+ reset_loaded_features_snapshot(box);
}
void
rb_provide(const char *feature)
{
- rb_provide_feature(GET_VM(), rb_fstring_cstr(feature));
+ /*
+ * rb_provide() must use rb_current_box to store provided features
+ * in the current box's loaded_features, etc.
+ */
+ rb_provide_feature(rb_current_box(), rb_fstring_cstr(feature));
}
NORETURN(static void load_failed(VALUE));
@@ -734,25 +719,32 @@ realpath_internal_cached(VALUE hash, VALUE path)
static inline void
load_iseq_eval(rb_execution_context_t *ec, VALUE fname)
{
+ const rb_box_t *box = rb_loading_box();
const rb_iseq_t *iseq = rb_iseq_load_iseq(fname);
if (!iseq) {
rb_execution_context_t *ec = GET_EC();
VALUE v = rb_vm_push_frame_fname(ec, fname);
- rb_thread_t *th = rb_ec_thread_ptr(ec);
- VALUE realpath_map = get_loaded_features_realpath_map(th->vm);
+ VALUE realpath_map = box->loaded_features_realpath_map;
- if (*rb_ruby_prism_ptr()) {
+ if (rb_ruby_prism_p()) {
pm_parse_result_t result = { 0 };
result.options.line = 1;
result.node.coverage_enabled = 1;
- VALUE error = pm_load_parse_file(&result, fname);
+ VALUE error = pm_load_parse_file(&result, fname, NULL);
if (error == Qnil) {
- iseq = pm_iseq_new_top(&result.node, rb_fstring_lit("<top (required)>"), fname, realpath_internal_cached(realpath_map, fname), NULL);
+ int error_state;
+ iseq = pm_iseq_new_top(&result.node, rb_fstring_lit("<top (required)>"), fname, realpath_internal_cached(realpath_map, fname), NULL, &error_state);
+
pm_parse_result_free(&result);
+
+ if (error_state) {
+ RUBY_ASSERT(iseq == NULL);
+ rb_jump_tag(error_state);
+ }
}
else {
rb_vm_pop_frame(ec);
@@ -778,13 +770,15 @@ load_iseq_eval(rb_execution_context_t *ec, VALUE fname)
RB_GC_GUARD(v);
}
rb_exec_event_hook_script_compiled(ec, iseq, Qnil);
- rb_iseq_eval(iseq);
+
+ rb_iseq_eval(iseq, box);
}
static inline enum ruby_tag_type
load_wrapping(rb_execution_context_t *ec, VALUE fname, VALUE load_wrapper)
{
enum ruby_tag_type state;
+ rb_box_t *box;
rb_thread_t *th = rb_ec_thread_ptr(ec);
volatile VALUE wrapper = th->top_wrapper;
volatile VALUE self = th->top_self;
@@ -795,7 +789,16 @@ load_wrapping(rb_execution_context_t *ec, VALUE fname, VALUE load_wrapper)
ec->errinfo = Qnil; /* ensure */
/* load in module as toplevel */
- th->top_self = rb_obj_clone(rb_vm_top_self());
+ if (BOX_OBJ_P(load_wrapper)) {
+ box = rb_get_box_t(load_wrapper);
+ if (!box->top_self) {
+ box->top_self = rb_obj_clone(rb_vm_top_self());
+ }
+ th->top_self = box->top_self;
+ }
+ else {
+ th->top_self = rb_obj_clone(rb_vm_top_self());
+ }
th->top_wrapper = load_wrapper;
rb_extend_object(th->top_self, th->top_wrapper);
@@ -830,7 +833,9 @@ raise_load_if_failed(rb_execution_context_t *ec, enum ruby_tag_type state)
static void
rb_load_internal(VALUE fname, VALUE wrap)
{
+ VALUE box_value;
rb_execution_context_t *ec = GET_EC();
+ const rb_box_t *box = rb_loading_box();
enum ruby_tag_type state = TAG_NONE;
if (RTEST(wrap)) {
if (!RB_TYPE_P(wrap, T_MODULE)) {
@@ -838,6 +843,10 @@ rb_load_internal(VALUE fname, VALUE wrap)
}
state = load_wrapping(ec, fname, wrap);
}
+ else if (BOX_OPTIONAL_P(box)) {
+ box_value = box->box_object;
+ state = load_wrapping(ec, fname, box_value);
+ }
else {
load_iseq_eval(ec, fname);
}
@@ -866,6 +875,40 @@ rb_load_protect(VALUE fname, int wrap, int *pstate)
if (state != TAG_NONE) *pstate = state;
}
+static VALUE
+load_entrypoint_internal(VALUE fname, VALUE wrap)
+{
+ VALUE path, orig_fname;
+
+ orig_fname = rb_get_path_check_to_string(fname);
+ fname = rb_str_encode_ospath(orig_fname);
+ RUBY_DTRACE_HOOK(LOAD_ENTRY, RSTRING_PTR(orig_fname));
+
+ path = rb_find_file(fname);
+ if (!path) {
+ if (!rb_file_load_ok(RSTRING_PTR(fname)))
+ load_failed(orig_fname);
+ path = fname;
+ }
+ rb_load_internal(path, wrap);
+
+ RUBY_DTRACE_HOOK(LOAD_RETURN, RSTRING_PTR(orig_fname));
+
+ return Qtrue;
+}
+
+VALUE
+rb_load_entrypoint(VALUE args)
+{
+ VALUE fname, wrap;
+ if (RARRAY_LEN(args) != 2) {
+ rb_bug("invalid arguments: %ld", RARRAY_LEN(args));
+ }
+ fname = rb_ary_entry(args, 0);
+ wrap = rb_ary_entry(args, 1);
+ return load_entrypoint_internal(fname, wrap);
+}
+
/*
* call-seq:
* load(filename, wrap=false) -> true
@@ -899,32 +942,16 @@ rb_load_protect(VALUE fname, int wrap, int *pstate)
static VALUE
rb_f_load(int argc, VALUE *argv, VALUE _)
{
- VALUE fname, wrap, path, orig_fname;
-
+ VALUE fname, wrap;
rb_scan_args(argc, argv, "11", &fname, &wrap);
-
- orig_fname = rb_get_path_check_to_string(fname);
- fname = rb_str_encode_ospath(orig_fname);
- RUBY_DTRACE_HOOK(LOAD_ENTRY, RSTRING_PTR(orig_fname));
-
- path = rb_find_file(fname);
- if (!path) {
- if (!rb_file_load_ok(RSTRING_PTR(fname)))
- load_failed(orig_fname);
- path = fname;
- }
- rb_load_internal(path, wrap);
-
- RUBY_DTRACE_HOOK(LOAD_RETURN, RSTRING_PTR(orig_fname));
-
- return Qtrue;
+ return load_entrypoint_internal(fname, wrap);
}
static char *
-load_lock(rb_vm_t *vm, const char *ftptr, bool warn)
+load_lock(const rb_box_t *box, const char *ftptr, bool warn)
{
st_data_t data;
- st_table *loading_tbl = get_loading_table(vm);
+ st_table *loading_tbl = box->loading_table;
if (!st_lookup(loading_tbl, (st_data_t)ftptr, &data)) {
/* partial state */
@@ -966,11 +993,11 @@ release_thread_shield(st_data_t *key, st_data_t *value, st_data_t done, int exis
}
static void
-load_unlock(rb_vm_t *vm, const char *ftptr, int done)
+load_unlock(const rb_box_t *box, const char *ftptr, int done)
{
if (ftptr) {
st_data_t key = (st_data_t)ftptr;
- st_table *loading_tbl = get_loading_table(vm);
+ st_table *loading_tbl = box->loading_table;
st_update(loading_tbl, key, release_thread_shield, done);
}
@@ -1021,6 +1048,17 @@ rb_f_require(VALUE obj, VALUE fname)
return rb_require_string(fname);
}
+VALUE
+rb_require_relative_entrypoint(VALUE fname)
+{
+ VALUE base = rb_current_realfilepath();
+ if (NIL_P(base)) {
+ rb_loaderror("cannot infer basepath");
+ }
+ base = rb_file_dirname(base);
+ return rb_require_string_internal(rb_file_absolute_path(fname, base), false);
+}
+
/*
* call-seq:
* require_relative(string) -> true or false
@@ -1033,18 +1071,13 @@ rb_f_require(VALUE obj, VALUE fname)
VALUE
rb_f_require_relative(VALUE obj, VALUE fname)
{
- VALUE base = rb_current_realfilepath();
- if (NIL_P(base)) {
- rb_loaderror("cannot infer basepath");
- }
- base = rb_file_dirname(base);
- return rb_require_string_internal(rb_file_absolute_path(fname, base), false);
+ return rb_require_relative_entrypoint(fname);
}
-typedef int (*feature_func)(rb_vm_t *vm, const char *feature, const char *ext, int rb, int expanded, const char **fn);
+typedef int (*feature_func)(const rb_box_t *box, const char *feature, const char *ext, int rb, int expanded, const char **fn);
static int
-search_required(rb_vm_t *vm, VALUE fname, volatile VALUE *path, feature_func rb_feature_p)
+search_required(const rb_box_t *box, VALUE fname, volatile VALUE *path, feature_func rb_feature_p)
{
VALUE tmp;
char *ext, *ftptr;
@@ -1055,20 +1088,20 @@ search_required(rb_vm_t *vm, VALUE fname, volatile VALUE *path, feature_func rb_
ext = strrchr(ftptr = RSTRING_PTR(fname), '.');
if (ext && !strchr(ext, '/')) {
if (IS_RBEXT(ext)) {
- if (rb_feature_p(vm, ftptr, ext, TRUE, FALSE, &loading)) {
+ if (rb_feature_p(box, 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(vm, ftptr, ext, TRUE, TRUE, &loading) || loading)
+ if (!rb_feature_p(box, ftptr, ext, TRUE, TRUE, &loading) || loading)
*path = tmp;
return 'r';
}
return 0;
}
else if (IS_SOEXT(ext)) {
- if (rb_feature_p(vm, ftptr, ext, FALSE, FALSE, &loading)) {
+ if (rb_feature_p(box, ftptr, ext, FALSE, FALSE, &loading)) {
if (loading) *path = rb_filesystem_str_new_cstr(loading);
return 's';
}
@@ -1077,25 +1110,25 @@ search_required(rb_vm_t *vm, VALUE fname, volatile VALUE *path, feature_func rb_
OBJ_FREEZE(tmp);
if ((tmp = rb_find_file(tmp)) != 0) {
ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
- if (!rb_feature_p(vm, ftptr, ext, FALSE, TRUE, &loading) || loading)
+ if (!rb_feature_p(box, ftptr, ext, FALSE, TRUE, &loading) || loading)
*path = tmp;
return 's';
}
}
else if (IS_DLEXT(ext)) {
- if (rb_feature_p(vm, ftptr, ext, FALSE, FALSE, &loading)) {
+ if (rb_feature_p(box, 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(vm, ftptr, ext, FALSE, TRUE, &loading) || loading)
+ if (!rb_feature_p(box, ftptr, ext, FALSE, TRUE, &loading) || loading)
*path = tmp;
return 's';
}
}
}
- else if ((ft = rb_feature_p(vm, ftptr, 0, FALSE, FALSE, &loading)) == 'r') {
+ else if ((ft = rb_feature_p(box, ftptr, 0, FALSE, FALSE, &loading)) == 'r') {
if (loading) *path = rb_filesystem_str_new_cstr(loading);
return 'r';
}
@@ -1104,19 +1137,23 @@ search_required(rb_vm_t *vm, VALUE fname, volatile VALUE *path, feature_func rb_
// Check if it's a statically linked extension when
// not already a feature and not found as a dynamic library.
- if (!ft && type != loadable_ext_rb && vm->static_ext_inits) {
- VALUE lookup_name = tmp;
- // Append ".so" if not already present so for example "etc" can find "etc.so".
- // We always register statically linked extensions with a ".so" extension.
- // See encinit.c and extinit.c (generated at build-time).
- if (!ext) {
- lookup_name = rb_str_dup(lookup_name);
- rb_str_cat_cstr(lookup_name, ".so");
- }
- ftptr = RSTRING_PTR(lookup_name);
- if (st_lookup(vm->static_ext_inits, (st_data_t)ftptr, NULL)) {
- *path = rb_filesystem_str_new_cstr(ftptr);
- return 's';
+ if (!ft && type != loadable_ext_rb) {
+ rb_vm_t *vm = GET_VM();
+ if (vm->static_ext_inits) {
+ VALUE lookup_name = tmp;
+ // Append ".so" if not already present so for example "etc" can find "etc.so".
+ // We always register statically linked extensions with a ".so" extension.
+ // See encinit.c and extinit.c (generated at build-time).
+ if (!ext) {
+ lookup_name = rb_str_dup(lookup_name);
+ rb_str_cat_cstr(lookup_name, ".so");
+ }
+ ftptr = RSTRING_PTR(lookup_name);
+ if (st_lookup(vm->static_ext_inits, (st_data_t)ftptr, NULL)) {
+ *path = rb_filesystem_str_new_cstr(ftptr);
+ RB_GC_GUARD(lookup_name);
+ return 's';
+ }
}
}
@@ -1125,7 +1162,7 @@ search_required(rb_vm_t *vm, VALUE fname, volatile VALUE *path, feature_func rb_
if (ft)
goto feature_present;
ftptr = RSTRING_PTR(tmp);
- return rb_feature_p(vm, ftptr, 0, FALSE, TRUE, 0);
+ return rb_feature_p(box, ftptr, 0, FALSE, TRUE, 0);
default:
if (ft) {
@@ -1134,7 +1171,7 @@ search_required(rb_vm_t *vm, VALUE fname, volatile VALUE *path, feature_func rb_
/* fall through */
case loadable_ext_rb:
ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
- if (rb_feature_p(vm, ftptr, ext, type == loadable_ext_rb, TRUE, &loading) && !loading)
+ if (rb_feature_p(box, ftptr, ext, type == loadable_ext_rb, TRUE, &loading) && !loading)
break;
*path = tmp;
}
@@ -1152,42 +1189,57 @@ load_failed(VALUE fname)
}
static VALUE
-load_ext(VALUE path)
+load_ext(VALUE path, VALUE fname)
{
+ VALUE loaded = path;
+ const rb_box_t *box = rb_loading_box();
+ VALUE cleanup = 0;
+ if (BOX_USER_P(box)) {
+ loaded = rb_box_local_extension(box->box_object, fname, path, &cleanup);
+ }
rb_scope_visibility_set(METHOD_VISI_PUBLIC);
- return (VALUE)dln_load(RSTRING_PTR(path));
+ void *handle = dln_load_feature(RSTRING_PTR(loaded), RSTRING_PTR(fname));
+ if (cleanup) {
+ rb_box_cleanup_local_extension(cleanup);
+ }
+ RB_GC_GUARD(loaded);
+ RB_GC_GUARD(fname);
+ return (VALUE)handle;
}
-static bool
-run_static_ext_init(rb_vm_t *vm, const char *feature)
+static VALUE
+run_static_ext_init(VALUE vm_ptr, VALUE feature_value)
{
+ rb_vm_t *vm = (rb_vm_t *)vm_ptr;
+ const char *feature = RSTRING_PTR(feature_value);
st_data_t key = (st_data_t)feature;
st_data_t init_func;
if (vm->static_ext_inits && st_delete(vm->static_ext_inits, &key, &init_func)) {
((void (*)(void))init_func)();
- return true;
+ return Qtrue;
}
- return false;
+ return Qfalse;
}
static int
-no_feature_p(rb_vm_t *vm, const char *feature, const char *ext, int rb, int expanded, const char **fn)
+no_feature_p(const rb_box_t *box, const char *feature, const char *ext, int rb, int expanded, const char **fn)
{
return 0;
}
-// Documented in doc/globals.rdoc
+// Documented in doc/language/globals.md
VALUE
rb_resolve_feature_path(VALUE klass, VALUE fname)
{
VALUE path;
int found;
VALUE sym;
+ const rb_box_t *box = rb_loading_box();
fname = rb_get_path(fname);
path = rb_str_encode_ospath(fname);
- found = search_required(GET_VM(), path, &path, no_feature_p);
+ found = search_required(box, path, &path, no_feature_p);
switch (found) {
case 'r':
@@ -1204,14 +1256,14 @@ rb_resolve_feature_path(VALUE klass, VALUE fname)
}
static void
-ext_config_push(rb_thread_t *th, struct rb_ext_config *prev)
+ext_config_push(rb_thread_t *th, volatile 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)
+ext_config_pop(rb_thread_t *th, volatile struct rb_ext_config *prev)
{
th->ext_config = *prev;
}
@@ -1234,22 +1286,24 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception, bool wa
{
volatile int result = -1;
rb_thread_t *th = rb_ec_thread_ptr(ec);
+ const rb_box_t *box = rb_loading_box();
volatile const struct {
VALUE wrapper, self, errinfo;
rb_execution_context_t *ec;
+ const rb_box_t *box;
} saved = {
th->top_wrapper, th->top_self, ec->errinfo,
- ec,
+ ec, box,
};
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);
- VALUE realpath_map = get_loaded_features_realpath_map(th->vm);
+ VALUE realpaths = box->loaded_features_realpaths;
+ VALUE realpath_map = box->loaded_features_realpath_map;
volatile bool reset_ext_config = false;
- struct rb_ext_config prev_ext_config;
+ volatile struct rb_ext_config prev_ext_config;
path = rb_str_encode_ospath(fname);
RUBY_DTRACE_HOOK(REQUIRE_ENTRY, RSTRING_PTR(fname));
@@ -1263,18 +1317,18 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception, bool wa
int found;
RUBY_DTRACE_HOOK(FIND_REQUIRE_ENTRY, RSTRING_PTR(fname));
- found = search_required(th->vm, path, &saved_path, rb_feature_p);
+ found = search_required(box, 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(th->vm, RSTRING_PTR(path), warn))) {
+ if (!path || !(ftptr = load_lock(box, RSTRING_PTR(path), warn))) {
result = 0;
}
else if (!*ftptr) {
result = TAG_RETURN;
}
- else if (found == 's' && run_static_ext_init(th->vm, RSTRING_PTR(path))) {
+ else if (found == 's' && RTEST(rb_vm_call_cfunc_in_box(Qnil, run_static_ext_init, (VALUE)th->vm, path, path, box))) {
result = TAG_RETURN;
}
else if (RTEST(rb_hash_aref(realpaths,
@@ -1290,9 +1344,8 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception, bool wa
case 's':
reset_ext_config = true;
ext_config_push(th, &prev_ext_config);
- handle = rb_vm_call_cfunc(rb_vm_top_self(), load_ext,
- path, VM_BLOCK_HANDLER_NONE, path);
- rb_hash_aset(ruby_dln_libmap, path, SVALUE2NUM((SIGNED_VALUE)handle));
+ handle = rb_vm_call_cfunc_in_box(box->top_self, load_ext, path, fname, path, box);
+ rb_hash_aset(box->ruby_dln_libmap, path, PTR2NUM(handle));
break;
}
result = TAG_RETURN;
@@ -1302,13 +1355,14 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception, bool wa
EC_POP_TAG();
ec = saved.ec;
+ box = saved.box;
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 (ftptr) load_unlock(box, RSTRING_PTR(path), !state);
if (state) {
if (state == TAG_FATAL || state == TAG_THROW) {
@@ -1334,7 +1388,7 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception, bool wa
}
if (result == TAG_RETURN) {
- rb_provide_feature(th2->vm, path);
+ rb_provide_feature(box, path);
VALUE real = realpath;
if (real) {
real = rb_fstring(real);
@@ -1351,6 +1405,10 @@ require_internal(rb_execution_context_t *ec, VALUE fname, int exception, bool wa
int
rb_require_internal_silent(VALUE fname)
{
+ if (!rb_ractor_main_p()) {
+ return NUM2INT(rb_ractor_require(fname, true));
+ }
+
rb_execution_context_t *ec = GET_EC();
return require_internal(ec, fname, 1, false);
}
@@ -1365,7 +1423,7 @@ rb_require_internal(VALUE fname)
int
ruby_require_internal(const char *fname, unsigned int len)
{
- struct RString fake;
+ struct RString fake = {RBASIC_INIT};
VALUE str = rb_setup_fake_str(&fake, fname, len, 0);
rb_execution_context_t *ec = GET_EC();
int result = require_internal(ec, str, 0, RTEST(ruby_verbose));
@@ -1383,23 +1441,31 @@ static VALUE
rb_require_string_internal(VALUE fname, bool resurrect)
{
rb_execution_context_t *ec = GET_EC();
- int result = require_internal(ec, fname, 1, RTEST(ruby_verbose));
- if (result > TAG_RETURN) {
- EC_JUMP_TAG(ec, result);
- }
- if (result < 0) {
+ // main ractor check
+ if (!rb_ractor_main_p()) {
if (resurrect) fname = rb_str_resurrect(fname);
- load_failed(fname);
+ return rb_ractor_require(fname, false);
}
+ else {
+ int result = require_internal(ec, fname, 1, RTEST(ruby_verbose));
+
+ if (result > TAG_RETURN) {
+ EC_JUMP_TAG(ec, result);
+ }
+ if (result < 0) {
+ if (resurrect) fname = rb_str_resurrect(fname);
+ load_failed(fname);
+ }
- return RBOOL(result);
+ return RBOOL(result);
+ }
}
VALUE
rb_require(const char *fname)
{
- struct RString fake;
+ struct RString fake = {RBASIC_INIT};
VALUE str = rb_setup_fake_str(&fake, fname, strlen(fname), 0);
return rb_require_string_internal(str, true);
}
@@ -1426,8 +1492,9 @@ ruby_init_ext(const char *name, void (*init)(void))
{
st_table *inits_table;
rb_vm_t *vm = GET_VM();
+ const rb_box_t *box = rb_loading_box();
- if (feature_provided(vm, name, 0))
+ if (feature_provided((rb_box_t *)box, name, 0))
return;
inits_table = vm->static_ext_inits;
@@ -1451,9 +1518,12 @@ ruby_init_ext(const char *name, void (*init)(void))
* A.autoload(:B, "b")
* A::B.doit # autoloads "b"
*
- * If _const_ in _mod_ is defined as autoload, the file name to be
- * loaded is replaced with _filename_. If _const_ is defined but not
- * as autoload, does nothing.
+ * If _const_ in _mod_ is defined as autoload, the file name to be
+ * loaded is replaced with _filename_. If _const_ is defined but not
+ * as autoload, does nothing.
+ *
+ * Files that are currently being loaded must not be registered for
+ * autoload.
*/
static VALUE
@@ -1515,9 +1585,12 @@ rb_mod_autoload_p(int argc, VALUE *argv, VALUE mod)
*
* autoload(:MyModule, "/usr/local/lib/modules/my_module.rb")
*
- * If _const_ is defined as autoload, the file name to be loaded is
- * replaced with _filename_. If _const_ is defined but not as
- * autoload, does nothing.
+ * If _const_ is defined as autoload, the file name to be loaded is
+ * replaced with _filename_. If _const_ is defined but not as
+ * autoload, does nothing.
+ *
+ * Files that are currently being loaded must not be registered for
+ * autoload.
*/
static VALUE
@@ -1572,6 +1645,7 @@ rb_ext_resolve_symbol(const char* fname, const char* symbol)
VALUE path;
char *ext;
VALUE fname_str = rb_str_new_cstr(fname);
+ const rb_box_t *box = rb_loading_box();
resolved = rb_resolve_feature_path((VALUE)NULL, fname_str);
if (NIL_P(resolved)) {
@@ -1579,7 +1653,7 @@ rb_ext_resolve_symbol(const char* fname, const char* symbol)
if (!ext || !IS_SOEXT(ext)) {
rb_str_cat_cstr(fname_str, ".so");
}
- if (rb_feature_p(GET_VM(), fname, 0, FALSE, FALSE, 0)) {
+ if (rb_feature_p(box, fname, 0, FALSE, FALSE, 0)) {
return dln_symbol(NULL, symbol);
}
return NULL;
@@ -1588,38 +1662,28 @@ rb_ext_resolve_symbol(const char* fname, const char* symbol)
return NULL;
}
path = rb_ary_entry(resolved, 1);
- handle = rb_hash_lookup(ruby_dln_libmap, path);
+ handle = rb_hash_lookup(box->ruby_dln_libmap, path);
if (NIL_P(handle)) {
return NULL;
}
- return dln_symbol((void *)NUM2SVALUE(handle), symbol);
+ return dln_symbol(NUM2PTR(handle), symbol);
}
void
Init_load(void)
{
- 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_define_hooked_variable(var_load_path, 0, load_path_getter, rb_gvar_readonly_setter);
+ rb_gvar_box_ready(var_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_hidden_new(0);
- vm->load_path_snapshot = rb_ary_hidden_new(0);
- vm->load_path_check_cache = 0;
- rb_define_singleton_method(vm->load_path, "resolve_feature_path", rb_resolve_feature_path, 1);
rb_define_virtual_variable("$\"", get_LOADED_FEATURES, 0);
- rb_define_virtual_variable("$LOADED_FEATURES", get_LOADED_FEATURES, 0);
- vm->loaded_features = rb_ary_new();
- vm->loaded_features_snapshot = rb_ary_hidden_new(0);
- vm->loaded_features_index = st_init_numtable();
- vm->loaded_features_realpaths = rb_hash_new();
- rb_obj_hide(vm->loaded_features_realpaths);
- vm->loaded_features_realpath_map = rb_hash_new();
- rb_obj_hide(vm->loaded_features_realpath_map);
+ rb_gvar_box_ready("$\"");
+ rb_define_virtual_variable("$LOADED_FEATURES", get_LOADED_FEATURES, 0); // TODO: rb_alias_variable ?
+ rb_gvar_box_ready("$LOADED_FEATURES");
rb_define_global_function("load", rb_f_load, -1);
rb_define_global_function("require", rb_f_require, 1);
@@ -1628,7 +1692,4 @@ Init_load(void)
rb_define_method(rb_cModule, "autoload?", rb_mod_autoload_p, -1);
rb_define_global_function("autoload", rb_f_autoload, 2);
rb_define_global_function("autoload?", rb_f_autoload_p, -1);
-
- ruby_dln_libmap = rb_hash_new_with_size(0);
- rb_vm_register_global_object(ruby_dln_libmap);
}
diff --git a/main.c b/main.c
index cbb294ba72..525189db85 100644
--- a/main.c
+++ b/main.c
@@ -32,6 +32,8 @@
# undef RUBY_DEBUG_ENV
#endif
+RUBY_GLOBAL_SETUP
+
static int
rb_main(int argc, char **argv)
{
@@ -40,9 +42,10 @@ rb_main(int argc, char **argv)
return ruby_run_node(ruby_options(argc, argv));
}
-#if defined(__wasm__) && !defined(__EMSCRIPTEN__)
-int rb_wasm_rt_start(int (main)(int argc, char **argv), int argc, char **argv);
-#define rb_main(argc, argv) rb_wasm_rt_start(rb_main, argc, argv)
+#ifdef _WIN32
+#define main(argc, argv) w32_main(argc, argv)
+static int main(int argc, char **argv);
+int wmain(void) {return main(0, NULL);}
#endif
int
@@ -56,16 +59,5 @@ main(int argc, char **argv)
#endif
ruby_sysinit(&argc, &argv);
- return rb_main(argc, argv);
+ return ruby_start_main(rb_main, argc, argv);
}
-
-#ifdef RUBY_ASAN_ENABLED
-/* Compile in the ASAN options Ruby needs, rather than relying on environment variables, so
- * that even tests which fork ruby with a clean environment will run ASAN with the right
- * settings */
-const char *
-__asan_default_options(void)
-{
- return "use_sigaltstack=0:detect_leaks=0";
-}
-#endif
diff --git a/man/index.txt b/man/index.txt
deleted file mode 100644
index 400eb02267..0000000000
--- a/man/index.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-Gemfile(5) gemfile.5
-bundle(1) bundle.1
-bundle-add(1) bundle-add.1
-bundle-binstubs(1) bundle-binstubs.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-package(1) bundle-package.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/man/irb.1 b/man/irb.1
deleted file mode 100644
index 93ef9b8f66..0000000000
--- a/man/irb.1
+++ /dev/null
@@ -1,257 +0,0 @@
-.\"Ruby is copyrighted by Yukihiro Matsumoto <matz@netlab.jp>.
-.Dd August 11, 2019
-.Dt IRB \&1 "Ruby Programmer's Reference Guide"
-.Os UNIX
-.Sh NAME
-.Nm irb
-.Nd Interactive Ruby Shell
-.Sh SYNOPSIS
-.Nm
-.Op Fl -version
-.Op Fl dfUw
-.Op Fl I Ar directory
-.Op Fl r Ar library
-.Op Fl E Ar external Ns Op : Ns Ar internal
-.Op Fl W Ns Op Ar level
-.Op Fl - Ns Oo no Oc Ns inspect
-.Op Fl - Ns Oo no Oc Ns multiline
-.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
-.Op Fl -inf-ruby-mode
-.Op Fl -simple-prompt
-.Op Fl -noprompt
-.Op Fl -tracer
-.Op Fl -back-trace-limit Ar n
-.Op Fl -
-.Op program_file
-.Op argument ...
-.Pp
-.Sh DESCRIPTION
-.Nm
-is the REPL(read-eval-print loop) environment for Ruby programs.
-.Pp
-.Sh OPTIONS
-.Bl -tag -width "1234567890123" -compact
-.Pp
-.It Fl -version
-Prints the version of
-.Nm .
-.Pp
-.It Fl E Ar external Ns Op : Ns Ar internal
-.It Fl -encoding Ar external Ns Op : Ns Ar internal
-Same as `ruby -E' .
-Specifies the default value(s) for external encodings and internal encoding. Values should be separated with colon (:).
-.Pp
-You can omit the one for internal encodings, then the value
-.Pf ( Li "Encoding.default_internal" ) will be nil.
-.Pp
-.It Fl I Ar path
-Same as `ruby -I' .
-Specifies
-.Li $LOAD_PATH
-directory
-.Pp
-.It Fl U
-Same as `ruby -U' .
-Sets the default value for internal encodings
-.Pf ( Li "Encoding.default_internal" ) to UTF-8.
-.Pp
-.It Fl d
-Same as `ruby -d' .
-Sets
-.Li $DEBUG
-to true.
-.Pp
-.It Fl f
-Suppresses read of
-.Pa ~/.irbrc .
-.Pp
-.It Fl w
-Same as `ruby -w' .
-.Pp
-.Pp
-.It Fl W
-Same as `ruby -W' .
-.Pp
-.It Fl h
-.It Fl -help
-Prints a summary of the options.
-.Pp
-.It Fl r Ar library
-Same as `ruby -r'.
-Causes irb to load the library using require.
-.Pp
-.It Fl -inspect
-Uses `inspect' for output (default except for bc mode)
-.Pp
-.It Fl -noinspect
-Doesn't use inspect for output
-.Pp
-.It Fl -multiline
-Uses multiline editor module.
-.Pp
-.It Fl -nomultiline
-Doesn't use multiline editor module.
-.Pp
-.It Fl -singleline
-Uses singleline editor module.
-.Pp
-.It Fl -nosingleline
-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).
-.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
-.It Fl -nocolorize
-Don't use colorization.
-.Pp
-.Pp
-.It Fl -autocomplete
-Use autocompletion.
-.Pp
-.It Fl -noautocomplete
-Don't use autocompletion.
-.Pp
-.Pp
-.It Fl -regexp-completor
-Use regexp based completion.
-.Pp
-.It Fl -type-completor
-Use type based completion.
-.Pp
-.Pp
-.It Fl -verbose
-Show details.
-.Pp
-.It Fl -noverbose
-Don't show details.
-.Pp
-.It Fl -prompt Ar mode
-.It Fl -prompt-mode Ar mode
-Switch prompt mode. Pre-defined prompt modes are
-`default', `simple', `xmp' and `inf-ruby'.
-.Pp
-.It Fl -inf-ruby-mode
-Uses prompt appropriate for inf-ruby-mode on emacs.
-Suppresses --multiline and --singleline.
-.Pp
-.It Fl -simple-prompt
-Makes prompts simple.
-.Pp
-.It Fl -noprompt
-No prompt mode.
-.Pp
-.It Fl -tracer
-Displays trace for each execution of commands.
-.Pp
-.It Fl -back-trace-limit Ar n
-Displays backtrace top
-.Ar n
-and tail
-.Ar n Ns .
-The default value is 16.
-.El
-.Pp
-.Sh ENVIRONMENT
-.Bl -tag -compact -width "XDG_CONFIG_HOME"
-.It Ev IRB_LANG
-The locale used for
-.Nm .
-.Pp
-.It Ev IRBRC
-The path to the personal initialization file.
-.Pp
-.It Ev XDG_CONFIG_HOME
-.Nm
-respects XDG_CONFIG_HOME. If this is set, load
-.Pa $XDG_CONFIG_HOME/irb/irbrc
-as a personal initialization file.
-.Pp
-.El
-.Pp
-Also
-.Nm
-depends on same variables as
-.Xr ruby 1 .
-.Pp
-.Sh FILES
-.Bl -tag -compact
-.It Pa ~/.irbrc
-Personal irb initialization. If
-.Ev IRBRC
-is set, read
-.Pa $IRBRC
-instead. If
-.Ev IRBRC
-is not set and
-.Ev XDG_CONFIG_HOME
-is set,
-.Pa $XDG_CONFIG_HOME/irb/irbrc
-is loaded.
-.Pp
-.El
-.Pp
-.Sh EXAMPLES
-.Dl % irb
-.Dl irb(main):001:0> Ic 1 + 1
-.Dl 2
-.Dl irb(main):002:0> Ic def t(x)
-.Dl irb(main):003:1> Ic x + 1
-.Dl irb(main):004:1> Ic end
-.Dl => :t
-.Dl irb(main):005:0> Ic t(3)
-.Dl => 4
-.Dl irb(main):006:0> Ic if t(3) == 4
-.Dl irb(main):007:1> Ic p :ok
-.Dl irb(main):008:1> Ic end
-.Dl :ok
-.Dl => :ok
-.Dl irb(main):009:0> Ic quit
-.Dl %
-.Pp
-.Sh SEE ALSO
-.Xr ruby 1 .
-.Pp
-.Sh REPORTING BUGS
-.Bl -bullet
-.It
-Security vulnerabilities should be reported via an email to
-.Mt security@ruby-lang.org .
-Reported problems will be published after being fixed.
-.Pp
-.It
-Other bugs and feature requests can be reported via the
-Ruby Issue Tracking System
-.Pq Lk https://bugs.ruby-lang.org/ .
-Do not report security vulnerabilities
-via this system because it publishes the vulnerabilities immediately.
-.El
-.Sh AUTHORS
-Written by Keiju ISHITSUKA.
diff --git a/man/ri.1 b/man/ri.1
deleted file mode 100644
index 85a6dfcd53..0000000000
--- a/man/ri.1
+++ /dev/null
@@ -1,247 +0,0 @@
-.\"Ruby is copyrighted by Yukihiro Matsumoto <matz@netlab.jp>.
-.Dd April 20, 2017
-.Dt RI \&1 "Ruby Programmer's Reference Guide"
-.Os UNIX
-.Sh NAME
-.Nm ri
-.Nd Ruby API reference front end
-.Sh SYNOPSIS
-.Nm
-.Op Fl ahilTv
-.Op Fl d Ar DIRNAME
-.Op Fl f Ar FORMAT
-.Op Fl w Ar WIDTH
-.Op Fl - Ns Oo Cm no- Oc Ns Cm pager
-.Op Fl -server Ns Oo = Ns Ar PORT Oc
-.Op Fl - Ns Oo Cm no- Oc Ns Cm list-doc-dirs
-.Op Fl -no-standard-docs
-.Op Fl - Ns Oo Cm no- Oc Ns Bro Cm system Ns | Ns Cm site Ns | Ns Cm gems Ns | Ns Cm home Brc
-.Op Fl - Ns Oo Cm no- Oc Ns Cm profile
-.Op Fl -dump Ns = Ns Ar CACHE
-.Op Ar name ...
-.Sh DESCRIPTION
-.Nm
-is a command-line front end for the Ruby API reference.
-You can search and read the API reference for classes and methods with
-.Nm .
-.Pp
-.Nm
-is a part of Ruby.
-.Pp
-.Ar name
-can be:
-.Bl -diag -offset indent
-.It Class | Module | Module::Class
-.Pp
-.It Class::method | Class#method | Class.method | method
-.Pp
-.It gem_name: | gem_name:README | gem_name:History
-.El
-.Pp
-All class names may be abbreviated to their minimum unambiguous form.
-If a name is ambiguous, all valid options will be listed.
-.Pp
-A
-.Ql \&.
-matches either class or instance methods, while #method
-matches only instance and ::method matches only class methods.
-.Pp
-README and other files may be displayed by prefixing them with the gem name
-they're contained in. If the gem name is followed by a
-.Ql \&:
-all files in the gem will be shown.
-The file name extension may be omitted where it is unambiguous.
-.Pp
-For example:
-.Bd -literal -offset indent
-ri Fil
-ri File
-ri File.new
-ri zip
-ri rdoc:README
-.Ed
-.Pp
-Note that shell quoting or escaping may be required for method names
-containing punctuation:
-.Bd -literal -offset indent
-ri 'Array.[]'
-ri compact\e!
-.Ed
-.Pp
-To see the default directories
-.Nm
-will search, run:
-.Bd -literal -offset indent
-ri --list-doc-dirs
-.Ed
-.Pp
-Specifying the
-.Fl -system , Fl -site , Fl -home , Fl -gems ,
-or
-.Fl -doc-dir
-options will limit
-.Nm
-to searching only the specified directories.
-.Pp
-.Nm
-options may be set in the
-.Ev RI
-environment variable.
-.Pp
-The
-.Nm
-pager can be set with the
-.Ev RI_PAGER
-environment variable or the
-.Ev PAGER
-environment variable.
-.Pp
-.Sh OPTIONS
-.Bl -tag -width "1234567890123" -compact
-.Pp
-.It Fl i
-.It Fl - Ns Oo Cm no- Oc Ns Cm interactive
-In interactive mode you can repeatedly
-look up methods with autocomplete.
-.Pp
-.It Fl a
-.It Fl - Ns Oo Cm no- Oc Ns Cm all
-Show all documentation for a class or module.
-.Pp
-.It Fl l
-.It Fl - Ns Oo Cm no- Oc Ns Cm list
-List classes
-.Nm
-knows about.
-.Pp
-.It Fl - Ns Oo Cm no- Oc Ns Cm pager
-Send output to a pager,
-rather than directly to stdout.
-.Pp
-.It Fl T
-Synonym for
-.Fl -no-pager .
-.Pp
-.It Fl w Ar WIDTH
-.It Fl -width Ns = Ns Ar WIDTH
-Set the width of the output.
-.Pp
-.It Fl -server Ns Oo = Ns Ar PORT Oc
-Run RDoc server on the given port.
-The default port is\~8214.
-.Pp
-.It Fl f Ar FORMAT
-.It Fl -format Ns = Ns Ar FORMAT
-Use the selected formatter.
-The default formatter is
-.Li bs
-for paged output and
-.Li ansi
-otherwise.
-Valid formatters are:
-.Li ansi , Li bs , Li markdown , Li rdoc .
-.Pp
-.It Fl h
-.It Fl -help
-Show help and exit.
-.Pp
-.It Fl v
-.It Fl -version
-Output version information and exit.
-.El
-.Pp
-Data source options:
-.Bl -tag -width "1234567890123" -compact
-.Pp
-.It Fl - Ns Oo Cm no- Oc Ns Cm list-doc-dirs
-List the directories from which
-.Nm
-will source documentation on stdout and exit.
-.Pp
-.It Fl d Ar DIRNAME
-.It Fl -doc-dir Ns = Ns Ar DIRNAME
-List of directories from which to source
-documentation in addition to the standard
-directories. May be repeated.
-.Pp
-.It Fl -no-standard-docs
-Do not include documentation from the Ruby standard library,
-.Pa site_lib ,
-installed gems, or
-.Pa ~/.rdoc .
-Use with
-.Fl -doc-dir .
-.Pp
-.It Fl - Ns Oo Cm no- Oc Ns Cm system
-Include documentation from Ruby's standard library. Defaults to true.
-.Pp
-.It Fl - Ns Oo Cm no- Oc Ns Cm site
-Include documentation from libraries installed in
-.Pa site_lib .
-Defaults to true.
-.Pp
-.It Fl - Ns Oo Cm no- Oc Ns Cm gems
-Include documentation from RubyGems. Defaults to true.
-.Pp
-.It Fl - Ns Oo Cm no- Oc Ns Cm home
-Include documentation stored in
-.Pa ~/.rdoc .
-Defaults to true.
-.El
-.Pp
-Debug options:
-.Bl -tag -width "1234567890123" -compact
-.Pp
-.It Fl - Ns Oo Cm no- Oc Ns Cm profile
-Run with the Ruby profiler.
-.Pp
-.It Fl -dump Ns = Ns Ar CACHE
-Dump data from an ri cache or data file.
-.El
-.Pp
-.Sh ENVIRONMENT
-.Bl -tag -width "USERPROFILE" -compact
-.Pp
-.It Ev RI
-Options to prepend to those specified on the command-line.
-.Pp
-.It Ev RI_PAGER
-.It Ev PAGER
-Pager program to use for displaying.
-.Pp
-.It Ev HOME
-.It Ev USERPROFILE
-.It Ev HOMEPATH
-Path to the user's home directory.
-.El
-.Pp
-.Sh FILES
-.Bl -tag -width "USERPROFILE" -compact
-.Pp
-.It Pa ~/.rdoc
-Path for ri data in the user's home directory.
-.Pp
-.El
-.Pp
-.Sh SEE ALSO
-.Xr ruby 1 ,
-.Xr rdoc 1 ,
-.Xr gem 1
-.Pp
-.Sh REPORTING BUGS
-.Bl -bullet
-.It
-Security vulnerabilities should be reported via an email to
-.Mt security@ruby-lang.org .
-Reported problems will be published after being fixed.
-.Pp
-.It
-Other bugs and feature requests can be reported via the
-Ruby Issue Tracking System
-.Pq Lk https://bugs.ruby-lang.org/ .
-Do not report security vulnerabilities
-via this system because it publishes the vulnerabilities immediately.
-.El
-.Sh AUTHORS
-Written by
-.An Dave Thomas Aq dave@pragmaticprogrammer.com .
diff --git a/man/ruby.1 b/man/ruby.1
index bbad8ae203..8141a6d7ef 100644
--- a/man/ruby.1
+++ b/man/ruby.1
@@ -287,6 +287,8 @@ to the standard output.
.It Fl -debug
Turns on debug mode.
.Li "$DEBUG"
+and
+.Li "$VERBOSE"
will be set to true.
.Pp
.It Fl e Ar command
@@ -430,7 +432,7 @@ Dump some information.
Prints the specified target.
.Ar target
can be one of:
-.Bl -hang -offset indent
+.Bl -hang -offset indent -width "version"
.It Sy version
Print version description (same as
.Fl -version).
@@ -448,7 +450,7 @@ Check syntax (same as
.El
.Pp
Or one of the following, which are intended for debugging the interpreter:
-.Bl -hang -offset indent -tag -width "+error-tolerant"
+.Bl -hang -offset indent -width "parsetree"
.It Sy yydebug
Enable compiler debug mode (same as
.Fl -yydebug).
@@ -517,6 +519,43 @@ enabled for only mswin32, mingw32, and OS/2 platforms. If this
variable is not defined, Ruby refers to
.Ev COMSPEC .
.Pp
+.It Ev RUBY_FREE_AT_EXIT
+If set, Ruby tries to free all dynamically allocated memories.
+Introduced in Ruby 3.3, default: unset.
+.Pp
+.It Ev RUBY_BOX
+If set to
+.Li 1 ,
+Ruby Box is enabled and users will be able to execute
+.Li Ruby::Box.new .
+Ruby Box is an experimental feature introduced in Ruby 4.0.
+.Pp
+.It Ev RUBY_IO_BUFFER_DEFAULT_SIZE
+The custom default buffer size of
+.Li IO::Buffer .
+.Pp
+.It Ev RUBY_MAX_CPU
+The maximum number of native threads used by M:N Threads scheduler
+Introduced in Ruby 3.3, default: 8.
+.Pp
+.It Ev RUBY_MN_THREADS
+If set to
+.Li 1 ,
+M:N Thread scheduler is enabled on the main Ractor.
+Introduced in Ruby 3.3, default: unset.
+.Pp
+.It Ev RUBY_PAGER
+The pager command that will be used for
+.Fl -help
+option.
+Introduced in Ruby 3.0, default:
+.Ev PAGER
+environment variable.
+.Pp
+.It Ev RUBY_THREAD_TIMESLICE
+Sets the default thread time slice (thread quantum) in milliseconds.
+Introduced in Ruby 3.4, default: 100ms.
+.Pp
.It Ev PATH
Ruby refers to the
.Ev PATH
@@ -561,14 +600,15 @@ Reaching the old malloc limit.
.El
.Pp
There are currently 4 possible areas where the GC may be tuned by
-the following 11 environment variables:
-.Bl -hang -compact -width "RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR"
-.It Ev RUBY_GC_HEAP_INIT_SLOTS
-Initial allocation slots. Applies to all slot sizes. Introduced in Ruby 2.1, default: 10000.
+the following environment variables:
+.Bl -hang -compact -width "RUBY_GC_HEAP_n_INIT_SLOTS"
.Pp
-.It Ev RUBY_GC_HEAP_%d_INIT_SLOTS
+.It Ev RUBY_GC_HEAP_ Ns Ar n Ns Ev _INIT_SLOTS
Initial allocation of slots in a specific heap.
-The available heaps can be found in the keys of `GC.stat_heap`.
+The available heaps can be found in the keys of
+.Li GC.stat_heap .
+.Ar n
+is a decimal number between 0 and 4.
Introduced in Ruby 3.3.
.Pp
.It Ev RUBY_GC_HEAP_FREE_SLOTS
@@ -591,6 +631,12 @@ where R is this factor and N is the number of old objects after the
last full GC.
Introduced in Ruby 2.1.1, default: 2.0
.Pp
+.It Ev RUBY_GC_HEAP_REMEMBERED_WB_UNPROTECTED_OBJECTS_LIMIT_RATIO
+Used to calculate the
+.Li remembered_wb_unprotected_objects_limit
+using a ratio of
+.Li old_objects .
+Introduced in Ruby 3.3, default: 0.1, minimum: 0.0
.It Ev RUBY_GC_MALLOC_LIMIT
The initial limit of young generation allocation from the malloc-family.
GC will start when this limit is reached.
@@ -607,6 +653,31 @@ GC frequency but increasing malloc growth until RUBY_GC_MALLOC_LIMIT_MAX
is reached.
Introduced in Ruby 2.1, default: 1.4, minimum: 1.0 (no growth)
.Pp
+.It Ev RUBY_GC_HEAP_FREE_SLOTS_MIN_RATIO
+Allocate additional pages when the number of free slots is
+lower than the value
+.Li (total_slots * (this ratio)) .
+Introduced in Ruby 2.4, default: 0.2, minimum: 0.0, maximum: 1.0
+.Pp
+.It Ev RUBY_GC_HEAP_FREE_SLOTS_MAX_RATIO
+Allow to free pages when the number of free slots is greater than the value
+.Li (total_slots * (this ratio)) .
+Introduced in Ruby 2.4, default: 0.4, minimum:
+.Li RUBY_GC_HEAP_FREE_SLOTS_MIN_RATIO,
+maximum: 1.0
+.Pp
+.It Ev RUBY_GC_HEAP_FREE_SLOTS_GOAL_RATIO
+Allocate slots to satisfy this formula:
+.Li free_slots = total_slots * goal_ratio
+In other words, prepare
+.Li (total_slots * goal_ratio)
+free slots.
+if this value is 0.0, then use RUBY_GC_HEAP_GROWTH_FACTOR directly.
+Introduced in Ruby 2.4, default: 0.65, minimum:
+.Li RUBY_GC_HEAP_FREE_SLOTS_MIN_RATIO,
+maximum:
+.Li RUBY_GC_HEAP_FREE_SLOTS_MAX_RATIO
+.Pp
.It Ev RUBY_GC_OLDMALLOC_LIMIT
The initial limit of old generation allocation from malloc,
a full GC will start when this limit is reached.
@@ -624,6 +695,11 @@ GC frequency but increasing malloc growth until RUBY_GC_OLDMALLOC_LIMIT_MAX
is reached.
Introduced in Ruby 2.1, default: 1.2, minimum: 1.0 (no growth)
.Pp
+.It Ev RUBY_SHARED_FIBER_POOL_FREE_STACKS
+Frees stacks of pooled fibers, if set to 1.
+Do not free the stacks if set to 0.
+Introduced in Ruby 2.7, default: 1 (no growth)
+.Pp
.El
.Sh STACK SIZE ENVIRONMENT
Stack size environment variables are implementation-dependent and
@@ -639,11 +715,11 @@ 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: 524288 (32-bit CPU) or 1048575 (64-bit)
+default: 524288 (32-bit CPU) or 1048576 (64-bit)
.Pp
.It Ev RUBY_THREAD_MACHINE_STACK_SIZE
Machine stack size used at thread creation.
-default: 524288 or 1048575
+default: 524288 or 1048576
.Pp
.It Ev RUBY_FIBER_VM_STACK_SIZE
VM stack size used at fiber creation.
@@ -709,6 +785,17 @@ a program (or script) that is to be executed.
.Pp
The pipe template is split on spaces into an argument list before the
template parameters are expanded.
+.Sh MISC ENVIRONMENT
+.Pp
+.Bl -hang -compact -width "RUBY_TCP_NO_FAST_FALLBACK"
+.It Ev RUBY_TCP_NO_FAST_FALLBACK
+If set to
+.Li 1 ,
+disables the fast fallback feature by default in TCPSocket.new and Socket.tcp.
+When set to
+.Li 0
+or left unset, the fast fallback feature is enabled.
+Introduced in Ruby 3.4, default: unset.
.Sh SEE ALSO
.Bl -hang -compact -width "https://www.ruby-toolbox.com/"
.It Lk https://www.ruby-lang.org/
diff --git a/marshal.c b/marshal.c
index c0bc2dd6da..9d9a83097c 100644
--- a/marshal.c
+++ b/marshal.c
@@ -40,6 +40,7 @@
#include "ruby/util.h"
#include "builtin.h"
#include "shape.h"
+#include "ruby/internal/attr/nonstring.h"
#define BITSPERSHORT (2*CHAR_BIT)
#define SHORTMASK ((1<<BITSPERSHORT)-1)
@@ -100,6 +101,7 @@ static ID s_dump, s_load, s_mdump, s_mload;
static ID s_dump_data, s_load_data, s_alloc, s_call;
static ID s_getbyte, s_read, s_write, s_binmode;
static ID s_encoding_short, s_ruby2_keywords_flag;
+#define s_encoding_long rb_id_encoding()
#define name_s_dump "_dump"
#define name_s_load "_load"
@@ -114,6 +116,7 @@ static ID s_encoding_short, s_ruby2_keywords_flag;
#define name_s_write "write"
#define name_s_binmode "binmode"
#define name_s_encoding_short "E"
+#define name_s_encoding_long "encoding"
#define name_s_ruby2_keywords_flag "K"
typedef struct {
@@ -142,12 +145,14 @@ rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE (*dumper)(VALUE),
compat_allocator_table();
compat = ALLOC(marshal_compat_t);
- RB_OBJ_WRITE(compat_allocator_tbl_wrapper, &compat->newclass, newclass);
- RB_OBJ_WRITE(compat_allocator_tbl_wrapper, &compat->oldclass, oldclass);
+ compat->newclass = newclass;
+ compat->oldclass = oldclass;
compat->dumper = dumper;
compat->loader = loader;
st_insert(compat_allocator_table(), (st_data_t)allocator, (st_data_t)compat);
+ RB_OBJ_WRITTEN(compat_allocator_tbl_wrapper, Qundef, newclass);
+ RB_OBJ_WRITTEN(compat_allocator_tbl_wrapper, Qundef, oldclass);
}
struct dump_arg {
@@ -156,6 +161,7 @@ struct dump_arg {
st_table *data;
st_table *compat_tbl;
st_table *encodings;
+ st_table *userdefs;
st_index_t num_entries;
};
@@ -204,6 +210,7 @@ mark_dump_arg(void *ptr)
rb_mark_set(p->symbols);
rb_mark_set(p->data);
rb_mark_hash(p->compat_tbl);
+ rb_mark_set(p->userdefs);
rb_gc_mark(p->str);
}
@@ -221,6 +228,7 @@ memsize_dump_arg(const void *ptr)
if (p->symbols) memsize += rb_st_memsize(p->symbols);
if (p->data) memsize += rb_st_memsize(p->data);
if (p->compat_tbl) memsize += rb_st_memsize(p->compat_tbl);
+ if (p->userdefs) memsize += rb_st_memsize(p->userdefs);
if (p->encodings) memsize += rb_st_memsize(p->encodings);
return memsize;
}
@@ -454,6 +462,31 @@ w_float(double d, struct dump_arg *arg)
}
}
+
+static VALUE
+w_encivar(VALUE str, struct dump_arg *arg)
+{
+ VALUE encname = encoding_name(str, arg);
+ if (NIL_P(encname) ||
+ is_ascii_string(str)) {
+ return Qnil;
+ }
+ w_byte(TYPE_IVAR, arg);
+ return encname;
+}
+
+static void
+w_encname(VALUE encname, struct dump_arg *arg)
+{
+ if (!NIL_P(encname)) {
+ struct dump_call_arg c_arg;
+ c_arg.limit = 1;
+ c_arg.arg = arg;
+ w_long(1L, arg);
+ w_encoding(encname, &c_arg);
+ }
+}
+
static void
w_symbol(VALUE sym, struct dump_arg *arg)
{
@@ -470,24 +503,11 @@ w_symbol(VALUE sym, struct dump_arg *arg)
if (!sym) {
rb_raise(rb_eTypeError, "can't dump anonymous ID %"PRIdVALUE, sym);
}
- encname = encoding_name(sym, arg);
- if (NIL_P(encname) ||
- is_ascii_string(sym)) {
- encname = Qnil;
- }
- else {
- w_byte(TYPE_IVAR, arg);
- }
+ encname = w_encivar(sym, arg);
w_byte(TYPE_SYMBOL, arg);
w_bytes(RSTRING_PTR(sym), RSTRING_LEN(sym), arg);
st_add_direct(arg->symbols, orig_sym, arg->symbols->num_entries);
- if (!NIL_P(encname)) {
- struct dump_call_arg c_arg;
- c_arg.limit = 1;
- c_arg.arg = arg;
- w_long(1L, arg);
- w_encoding(encname, &c_arg);
- }
+ w_encname(encname, arg);
}
}
@@ -525,7 +545,7 @@ w_extended(VALUE klass, struct dump_arg *arg, int check)
klass = RCLASS_SUPER(klass);
}
while (BUILTIN_TYPE(klass) == T_ICLASS) {
- if (!FL_TEST(klass, RICLASS_IS_ORIGIN) ||
+ if (!RICLASS_IS_ORIGIN_P(klass) ||
BUILTIN_TYPE(RBASIC(klass)->klass) != T_MODULE) {
VALUE path = rb_class_name(RBASIC(klass)->klass);
w_byte(TYPE_EXTENDED, arg);
@@ -578,13 +598,21 @@ 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 instance variable name `id` is a special name to be skipped,
+ * returns the name of it. otherwise it cannot be dumped (unnamed),
+ * returns `name` as-is. returns NULL for ID that can be dumped.
+ */
+static inline const char *
+skipping_ivar_name(const ID id, const char *name)
{
- 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);
+#define IS_SKIPPED_IVAR(idname) \
+ ((id == idname) && (name = name_##idname, true))
+ if (IS_SKIPPED_IVAR(s_encoding_short)) return name;
+ if (IS_SKIPPED_IVAR(s_ruby2_keywords_flag)) return name;
+ if (IS_SKIPPED_IVAR(s_encoding_long)) return name;
+ if (!rb_id2str(id)) return name;
+ return NULL;
}
struct w_ivar_arg {
@@ -597,15 +625,12 @@ w_obj_each(ID id, VALUE value, st_data_t a)
{
struct w_ivar_arg *ivarg = (struct w_ivar_arg *)a;
struct dump_call_arg *arg = ivarg->dump;
+ const char unnamed[] = "", *ivname = skipping_ivar_name(id, unnamed);
- if (to_be_skipped_id(id)) {
- if (id == s_encoding_short) {
- 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));
+ if (ivname) {
+ if (ivname != unnamed) {
+ rb_warn("instance variable '%s' on class %"PRIsVALUE" is not dumped",
+ ivname, CLASS_OF(arg->obj));
}
return ST_CONTINUE;
}
@@ -618,7 +643,7 @@ w_obj_each(ID id, VALUE value, st_data_t a)
static int
obj_count_ivars(ID id, VALUE val, st_data_t a)
{
- if (!to_be_skipped_id(id) && UNLIKELY(!++*(st_index_t *)a)) {
+ if (!skipping_ivar_name(id, "") && UNLIKELY(!++*(st_index_t *)a)) {
rb_raise(rb_eRuntimeError, "too many instance variables");
}
return ST_CONTINUE;
@@ -702,20 +727,18 @@ has_ivars(VALUE obj, VALUE encname, VALUE *ivobj)
static void
w_ivar_each(VALUE obj, st_index_t num, struct dump_call_arg *arg)
{
- shape_id_t shape_id = rb_shape_get_shape_id(arg->obj);
+ shape_id_t shape_id = rb_obj_shape_id(arg->obj);
struct w_ivar_arg ivarg = {arg, num};
if (!num) return;
rb_ivar_foreach(obj, w_obj_each, (st_data_t)&ivarg);
- if (shape_id != rb_shape_get_shape_id(arg->obj)) {
- rb_shape_t * expected_shape = rb_shape_get_shape_by_id(shape_id);
- rb_shape_t * actual_shape = rb_shape_get_shape(arg->obj);
-
+ shape_id_t actual_shape_id = rb_obj_shape_id(arg->obj);
+ if (shape_id != actual_shape_id) {
// If the shape tree got _shorter_ then we probably removed an IV
// If the shape tree got longer, then we probably added an IV.
// The exception message might not be accurate when someone adds and
// removes the same number of IVs, but they will still get an exception
- if (rb_shape_depth(expected_shape) > rb_shape_depth(actual_shape)) {
+ if (rb_shape_depth(shape_id) > rb_shape_depth(rb_obj_shape_id(arg->obj))) {
rb_raise(rb_eRuntimeError, "instance variable removed from %"PRIsVALUE" instance",
CLASS_OF(arg->obj));
}
@@ -887,6 +910,9 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
st_index_t hasiv2;
VALUE encname2;
+ if (arg->userdefs && st_is_member(arg->userdefs, (st_data_t)obj)) {
+ rb_raise(rb_eRuntimeError, "can't dump recursive object using _dump()");
+ }
v = INT2NUM(limit);
v = dump_funcall(arg, obj, s_dump, 1, &v);
if (!RB_TYPE_P(v, T_STRING)) {
@@ -903,7 +929,13 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
w_class(TYPE_USERDEF, obj, arg, FALSE);
w_bytes(RSTRING_PTR(v), RSTRING_LEN(v), arg);
if (hasiv) {
+ st_data_t userdefs = (st_data_t)obj;
+ if (!arg->userdefs) {
+ arg->userdefs = rb_init_identtable();
+ }
+ st_add_direct(arg->userdefs, userdefs, 0);
w_ivar(hasiv, ivobj, encname, &c_arg);
+ st_delete(arg->userdefs, &userdefs, NULL);
}
w_remember(obj, arg);
return;
@@ -935,19 +967,23 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
if (FL_TEST(obj, FL_SINGLETON)) {
rb_raise(rb_eTypeError, "singleton class can't be dumped");
}
- w_byte(TYPE_CLASS, arg);
{
VALUE path = class2path(obj);
+ VALUE encname = w_encivar(path, arg);
+ w_byte(TYPE_CLASS, arg);
w_bytes(RSTRING_PTR(path), RSTRING_LEN(path), arg);
+ w_encname(encname, arg);
RB_GC_GUARD(path);
}
break;
case T_MODULE:
- w_byte(TYPE_MODULE, arg);
{
VALUE path = class2path(obj);
+ VALUE encname = w_encivar(path, arg);
+ w_byte(TYPE_MODULE, arg);
w_bytes(RSTRING_PTR(path), RSTRING_LEN(path), arg);
+ w_encname(encname, arg);
RB_GC_GUARD(path);
}
break;
@@ -1048,7 +1084,7 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
case T_STRUCT:
w_class(TYPE_STRUCT, obj, arg, TRUE);
{
- long len = RSTRUCT_LEN(obj);
+ long len = RSTRUCT_LEN_RAW(obj);
VALUE mem;
long i;
@@ -1056,7 +1092,7 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
mem = rb_struct_members(obj);
for (i=0; i<len; i++) {
w_symbol(RARRAY_AREF(mem, i), arg);
- w_object(RSTRUCT_GET(obj, i), arg, limit);
+ w_object(RSTRUCT_GET_RAW(obj, i), arg, limit);
}
}
break;
@@ -1110,6 +1146,10 @@ clear_dump_arg(struct dump_arg *arg)
st_free_table(arg->encodings);
arg->encodings = 0;
}
+ if (arg->userdefs) {
+ st_free_table(arg->userdefs);
+ arg->userdefs = 0;
+ }
}
NORETURN(static inline void io_needed(void));
@@ -1149,7 +1189,7 @@ io_needed(void)
* * anonymous Class/Module.
* * objects which are related to system (ex: Dir, File::Stat, IO, File, Socket
* and so on)
- * * an instance of MatchData, Data, Method, UnboundMethod, Proc, Thread,
+ * * an instance of MatchData, Method, UnboundMethod, Proc, Thread,
* ThreadGroup, Continuation
* * objects which define singleton methods
*/
@@ -1187,6 +1227,7 @@ rb_marshal_dump_limited(VALUE obj, VALUE port, int limit)
arg->num_entries = 0;
arg->compat_tbl = 0;
arg->encodings = 0;
+ arg->userdefs = 0;
arg->str = rb_str_buf_new(0);
if (!NIL_P(port)) {
if (!rb_respond_to(port, s_write)) {
@@ -1387,7 +1428,7 @@ long
ruby_marshal_read_long(const char **buf, long len)
{
long x;
- struct RString src;
+ struct RString src = {RBASIC_INIT};
struct load_arg arg;
memset(&arg, 0, sizeof(arg));
arg.src = rb_setup_fake_str(&src, *buf, len, 0);
@@ -1491,7 +1532,7 @@ name_equal(const char *name, size_t nlen, const char *p, long l)
static int
sym2encidx(VALUE sym, VALUE val)
{
- static const char name_encoding[8] = "encoding";
+ RBIMPL_ATTR_NONSTRING() static const char name_encoding[8] = "encoding";
const char *p;
long l;
if (rb_enc_get_index(sym) != ENCINDEX_US_ASCII) return -1;
@@ -1684,6 +1725,34 @@ r_copy_ivar(VALUE v, VALUE data)
"can't override instance variable of "type" '%"PRIsVALUE"'", \
(str))
+static int
+r_ivar_encoding(VALUE obj, struct load_arg *arg, VALUE sym, VALUE val)
+{
+ int idx = sym2encidx(sym, val);
+ if (idx >= 0) {
+ if (rb_enc_capable(obj)) {
+ rb_enc_associate_index(obj, idx);
+ }
+ else {
+ rb_raise(rb_eArgError, "%"PRIsVALUE" is not enc_capable", obj);
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static long
+r_encname(VALUE obj, struct load_arg *arg)
+{
+ long len = r_long(arg);
+ if (len > 0) {
+ VALUE sym = r_symbol(arg);
+ VALUE val = r_object(arg);
+ len -= r_ivar_encoding(obj, arg, sym, val);
+ }
+ return len;
+}
+
static void
r_ivar(VALUE obj, int *has_encoding, struct load_arg *arg)
{
@@ -1700,14 +1769,7 @@ r_ivar(VALUE obj, int *has_encoding, struct load_arg *arg)
do {
VALUE sym = r_symbol(arg);
VALUE val = r_object(arg);
- int idx = sym2encidx(sym, val);
- if (idx >= 0) {
- if (rb_enc_capable(obj)) {
- rb_enc_associate_index(obj, idx);
- }
- else {
- rb_raise(rb_eArgError, "%"PRIsVALUE" is not enc_capable", obj);
- }
+ if (r_ivar_encoding(obj, arg, sym, val)) {
if (has_encoding) *has_encoding = TRUE;
}
else if (symname_equal_lit(sym, name_s_ruby2_keywords_flag)) {
@@ -2231,6 +2293,7 @@ r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE extmod, int typ
{
VALUE str = r_bytes(arg);
+ if (ivp && *ivp > 0) *ivp = r_encname(str, arg) > 0;
v = path2class(str);
prohibit_ivar("class", str);
v = r_entry(v, arg);
@@ -2242,6 +2305,7 @@ r_object_for(struct load_arg *arg, bool partial, int *ivp, VALUE extmod, int typ
{
VALUE str = r_bytes(arg);
+ if (ivp && *ivp > 0) *ivp = r_encname(str, arg) > 0;
v = path2module(str);
prohibit_ivar("module", str);
v = r_entry(v, arg);
@@ -2508,19 +2572,19 @@ Init_marshal(void)
}
static int
-marshal_compat_table_mark_i(st_data_t key, st_data_t value, st_data_t _)
+marshal_compat_table_mark_and_move_i(st_data_t key, st_data_t value, st_data_t _)
{
marshal_compat_t *p = (marshal_compat_t *)value;
- rb_gc_mark_movable(p->newclass);
- rb_gc_mark_movable(p->oldclass);
+ rb_gc_mark_and_move(&p->newclass);
+ rb_gc_mark_and_move(&p->oldclass);
return ST_CONTINUE;
}
static void
-marshal_compat_table_mark(void *tbl)
+marshal_compat_table_mark_and_move(void *tbl)
{
if (!tbl) return;
- st_foreach(tbl, marshal_compat_table_mark_i, 0);
+ st_foreach(tbl, marshal_compat_table_mark_and_move_i, 0);
}
static int
@@ -2543,29 +2607,13 @@ marshal_compat_table_memsize(const void *data)
return st_memsize(data) + sizeof(marshal_compat_t) * st_table_size(data);
}
-static int
-marshal_compat_table_compact_i(st_data_t key, st_data_t value, st_data_t _)
-{
- marshal_compat_t *p = (marshal_compat_t *)value;
- p->newclass = rb_gc_location(p->newclass);
- p->oldclass = rb_gc_location(p->oldclass);
- return ST_CONTINUE;
-}
-
-static void
-marshal_compat_table_compact(void *tbl)
-{
- if (!tbl) return;
- st_foreach(tbl, marshal_compat_table_compact_i, 0);
-}
-
static const rb_data_type_t marshal_compat_type = {
.wrap_struct_name = "marshal_compat_table",
.function = {
- .dmark = marshal_compat_table_mark,
+ .dmark = marshal_compat_table_mark_and_move,
.dfree = marshal_compat_table_free,
.dsize = marshal_compat_table_memsize,
- .dcompact = marshal_compat_table_compact,
+ .dcompact = marshal_compat_table_mark_and_move,
},
.flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY,
};
diff --git a/math.c b/math.c
index 2394fe9f58..852620da20 100644
--- a/math.c
+++ b/math.c
@@ -15,7 +15,6 @@
# define _USE_MATH_DEFINES 1
#endif
-#include <errno.h>
#include <float.h>
#include <math.h>
@@ -458,6 +457,34 @@ math_exp(VALUE unused_obj, VALUE x)
return DBL2NUM(exp(Get_Double(x)));
}
+/*
+ * call-seq:
+ * Math.expm1(x) -> float
+ *
+ * Returns "exp(x) - 1", +e+ raised to the +x+ power, minus 1.
+ *
+ *
+ * - Domain: <tt>[-INFINITY, INFINITY]</tt>.
+ * - Range: <tt>[-1.0, INFINITY]</tt>.
+ *
+ * Examples:
+ *
+ * expm1(-INFINITY) # => 0.0
+ * expm1(-1.0) # => -0.6321205588285577 # 1.0/E - 1
+ * expm1(0.0) # => 0.0
+ * expm1(0.5) # => 0.6487212707001282 # sqrt(E) - 1
+ * expm1(1.0) # => 1.718281828459045 # E - 1
+ * expm1(2.0) # => 6.38905609893065 # E**2 - 1
+ * expm1(INFINITY) # => Infinity
+ *
+ */
+
+static VALUE
+math_expm1(VALUE unused_obj, VALUE x)
+{
+ return DBL2NUM(expm1(Get_Double(x)));
+}
+
#if defined __CYGWIN__
# include <cygwin/version.h>
# if CYGWIN_VERSION_DLL_MAJOR < 1005
@@ -647,6 +674,47 @@ math_log10(VALUE unused_obj, VALUE x)
return DBL2NUM(log10(d) + numbits * log10(2)); /* log10(d * 2 ** numbits) */
}
+/*
+ * call-seq:
+ * Math.log1p(x) -> float
+ *
+ * Returns "log(x + 1)", the base E {logarithm}[https://en.wikipedia.org/wiki/Logarithm] of (+x+ + 1).
+ *
+ * - Domain: <tt>[-1, INFINITY]</tt>.
+ * - Range: <tt>[-INFINITY, INFINITY]</tt>.
+ *
+ * Examples:
+ *
+ * log1p(-1.0) # => -Infinity
+ * log1p(0.0) # => 0.0
+ * log1p(E - 1) # => 1.0
+ * log1p(INFINITY) # => Infinity
+ *
+ */
+
+static VALUE
+math_log1p(VALUE unused_obj, VALUE x)
+{
+ size_t numbits;
+ double d = get_double_rshift(x, &numbits);
+
+ if (numbits != 0) {
+ x = rb_big_plus(x, INT2FIX(1));
+ d = math_log_split(x, &numbits);
+ /* check for pole error */
+ if (d == 0.0) return DBL2NUM(-HUGE_VAL);
+ d = log(d);
+ d += numbits * M_LN2;
+ return DBL2NUM(d);
+ }
+
+ domain_check_min(d, -1.0, "log1p");
+ /* check for pole error */
+ if (d == -1.0) return DBL2NUM(-HUGE_VAL);
+
+ return DBL2NUM(log1p(d)); /* log10(d * 2 ** numbits) */
+}
+
static VALUE rb_math_sqrt(VALUE x);
/*
@@ -986,7 +1054,7 @@ math_gamma(VALUE unused_obj, VALUE x)
*
* [Math.log(Math.gamma(x).abs), Math.gamma(x) < 0 ? -1 : 1]
*
- * See {logarithmic gamma function}[https://en.wikipedia.org/wiki/Gamma_function#The_log-gamma_function].
+ * See {log gamma function}[https://en.wikipedia.org/wiki/Gamma_function#Log-gamma_function].
*
* - Domain: <tt>(-INFINITY, INFINITY]</tt>.
* - Range of first element: <tt>(-INFINITY, INFINITY]</tt>.
@@ -1121,9 +1189,11 @@ InitVM_Math(void)
rb_define_module_function(rb_mMath, "atanh", math_atanh, 1);
rb_define_module_function(rb_mMath, "exp", math_exp, 1);
+ rb_define_module_function(rb_mMath, "expm1", math_expm1, 1);
rb_define_module_function(rb_mMath, "log", math_log, -1);
rb_define_module_function(rb_mMath, "log2", math_log2, 1);
rb_define_module_function(rb_mMath, "log10", math_log10, 1);
+ rb_define_module_function(rb_mMath, "log1p", math_log1p, 1);
rb_define_module_function(rb_mMath, "sqrt", math_sqrt, 1);
rb_define_module_function(rb_mMath, "cbrt", math_cbrt, 1);
diff --git a/memory_view.c b/memory_view.c
index 519aad2ca1..7bcb39972f 100644
--- a/memory_view.c
+++ b/memory_view.c
@@ -51,11 +51,11 @@ exported_object_registry_mark(void *ptr)
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();
+ RB_VM_LOCKING() {
+ st_clear(exported_object_table);
+ st_free_table(exported_object_table);
+ exported_object_table = NULL;
+ }
}
const rb_data_type_t rb_memory_view_exported_object_registry_data_type = {
@@ -99,18 +99,18 @@ exported_object_dec_ref(st_data_t *key, st_data_t *val, st_data_t arg, int exist
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();
+ RB_VM_LOCKING() {
+ st_update(exported_object_table, (st_data_t)obj, exported_object_add_ref, 0);
+ }
}
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();
+ RB_VM_LOCKING() {
+ if (exported_object_table)
+ st_update(exported_object_table, (st_data_t)obj, exported_object_dec_ref, 0);
+ }
}
// MemoryView
diff --git a/method.h b/method.h
index fdc7c263d1..260344d53b 100644
--- a/method.h
+++ b/method.h
@@ -15,6 +15,7 @@
#include "internal/imemo.h"
#include "internal/compilers.h"
#include "internal/static_assert.h"
+#include "ruby/atomic.h"
#ifndef END_OF_ENUMERATION
# if defined(__GNUC__) &&! defined(__STRICT_ANSI__)
@@ -72,11 +73,18 @@ typedef struct rb_callable_method_entry_struct { /* same fields with rb_method_e
#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)
static inline void
+METHOD_ENTRY_CACHED_SET(rb_callable_method_entry_t *me)
+{
+ if (!METHOD_ENTRY_CACHED(me)) {
+ me->flags |= IMEMO_FL_USER4;
+ }
+}
+
+static inline void
METHOD_ENTRY_VISI_SET(rb_method_entry_t *me, rb_method_visibility_t visi)
{
VM_ASSERT((int)visi >= 0 && visi <= 3);
@@ -158,8 +166,8 @@ 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_serial_t defined_ractor_id;
+ unsigned int local_hooks_cnt;
} rb_method_bmethod_t;
enum method_optimized_type {
@@ -181,7 +189,8 @@ struct rb_method_definition_struct {
unsigned int iseq_overload: 1;
unsigned int no_redef_warning: 1;
unsigned int aliased : 1;
- int reference_count : 28;
+
+ rb_atomic_t reference_count;
union {
rb_method_iseq_t iseq;
@@ -195,9 +204,12 @@ struct rb_method_definition_struct {
ID original_id;
uintptr_t method_serial;
+ const rb_box_t *box;
};
struct rb_id_table;
+struct rb_ractor_struct;
+struct rb_hook_list_struct;
typedef struct rb_method_definition_struct rb_method_definition_t;
STATIC_ASSERT(sizeof_method_def, offsetof(rb_method_definition_t, body) <= 8);
@@ -237,6 +249,7 @@ st_index_t rb_hash_method_entry(st_index_t hash, const rb_method_entry_t *me);
VALUE rb_method_entry_location(const rb_method_entry_t *me);
+void rb_free_method_entry_vm_weak_references(const rb_method_entry_t *me);
void rb_free_method_entry(const rb_method_entry_t *me);
const rb_method_entry_t *rb_method_entry_clone(const rb_method_entry_t *me);
@@ -244,12 +257,20 @@ const rb_callable_method_entry_t *rb_method_entry_complement_defined_class(const
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_method_table_insert0(VALUE klass, struct rb_id_table *table, ID method_id, const rb_method_entry_t *me, bool iclass_shared_mtbl);
void rb_scope_visibility_set(rb_method_visibility_t);
VALUE rb_unnamed_parameters(int arity);
+void rb_vm_insert_cc_refinement(const struct rb_callcache *cc);
+void rb_vm_delete_cc_refinement(const struct rb_callcache *cc);
+
void rb_clear_method_cache(VALUE klass_or_module, ID mid);
void rb_clear_all_refinement_method_cache(void);
+void rb_invalidate_method_caches(struct rb_id_table *cm_tbl, VALUE cc_tbl);
+struct rb_hook_list_struct *rb_method_def_local_hooks(rb_method_definition_t *def, struct rb_ractor_struct *cr, bool create);
+void rb_method_definition_addref(rb_method_definition_t *def);
+void rb_method_definition_release(rb_method_definition_t *def);
#endif /* RUBY_METHOD_H */
diff --git a/mini_builtin.c b/mini_builtin.c
index 2024d5d4a6..48f401e78a 100644
--- a/mini_builtin.c
+++ b/mini_builtin.c
@@ -1,25 +1,49 @@
#include "internal.h"
#include "internal/array.h"
+#include "internal/eval.h"
#include "iseq.h"
#include "vm_core.h"
#include "builtin.h"
#include "miniprelude.c"
-// included from miniinit.c
+static VALUE
+prelude_ast_value(VALUE name, VALUE code, int line)
+{
+ rb_ast_t *ast;
+ VALUE ast_value = rb_parser_compile_string_path(rb_parser_new(), name, code, line);
+ ast = rb_ruby_ast_data_get(ast_value);
+ if (!ast || !ast->body.root) {
+ if (ast) rb_ast_dispose(ast);
+ rb_exc_raise(rb_errinfo());
+ }
+ return ast_value;
+}
-#ifndef INCLUDED_BY_BUILTIN_C
-static struct st_table *loaded_builtin_table;
-#endif
+static void
+pm_prelude_load(pm_parse_result_t *result, VALUE name, VALUE code, int line)
+{
+ pm_options_line_set(&result->options, line);
+ VALUE error = pm_parse_string(result, code, name, NULL);
-bool pm_builtin_ast_value(pm_parse_result_t *result, const char *feature_name, VALUE *name_str);
-VALUE rb_builtin_ast_value(const char *feature_name, VALUE *name_str);
+ if (!NIL_P(error)) {
+ pm_parse_result_free(result);
+ rb_exc_raise(error);
+ }
+}
static const rb_iseq_t *
builtin_iseq_load(const char *feature_name, const struct rb_builtin_function *table)
{
VALUE name_str = 0;
+ int start_line;
const rb_iseq_t *iseq;
+ VALUE code = rb_builtin_find(feature_name, &name_str, &start_line);
+ if (NIL_P(code)) {
+ rb_fatal("builtin_iseq_load: can not find %s; "
+ "probably miniprelude.c is out of date",
+ feature_name);
+ }
rb_vm_t *vm = GET_VM();
static const rb_compile_option_t optimization = {
@@ -35,35 +59,30 @@ builtin_iseq_load(const char *feature_name, const struct rb_builtin_function *ta
.debug_level = 0,
};
- if (*rb_ruby_prism_ptr()) {
+ if (rb_ruby_prism_p()) {
pm_parse_result_t result = { 0 };
- if (!pm_builtin_ast_value(&result, feature_name, &name_str)) {
- rb_fatal("builtin_iseq_load: can not find %s; "
- "probably miniprelude.c is out of date",
- feature_name);
- }
+ pm_prelude_load(&result, name_str, code, start_line);
vm->builtin_function_table = table;
- iseq = pm_iseq_new_with_opt(&result.node, name_str, name_str, Qnil, 0, NULL, 0, ISEQ_TYPE_TOP, &optimization);
+ int error_state;
+ iseq = pm_iseq_new_with_opt(&result.node, name_str, name_str, Qnil, 0, NULL, 0, ISEQ_TYPE_TOP, &optimization, &error_state);
- GET_VM()->builtin_function_table = NULL;
+ vm->builtin_function_table = NULL;
pm_parse_result_free(&result);
- }
- else {
- VALUE ast_value = rb_builtin_ast_value(feature_name, &name_str);
- if (NIL_P(ast_value)) {
- rb_fatal("builtin_iseq_load: can not find %s; "
- "probably miniprelude.c is out of date",
- feature_name);
+ if (error_state) {
+ RUBY_ASSERT(iseq == NULL);
+ rb_jump_tag(error_state);
}
-
+ }
+ else {
+ VALUE ast_value = prelude_ast_value(name_str, code, start_line);
rb_ast_t *ast = rb_ruby_ast_data_get(ast_value);
vm->builtin_function_table = table;
iseq = rb_iseq_new_with_opt(ast_value, name_str, name_str, Qnil, 0, NULL, 0, ISEQ_TYPE_TOP, &optimization, Qnil);
- GET_VM()->builtin_function_table = NULL;
+ vm->builtin_function_table = NULL;
rb_ast_dispose(ast);
}
@@ -72,10 +91,7 @@ builtin_iseq_load(const char *feature_name, const struct rb_builtin_function *ta
rb_io_write(rb_stdout, rb_iseq_disasm((const rb_iseq_t *)iseq));
}
-#ifndef INCLUDED_BY_BUILTIN_C
- st_insert(loaded_builtin_table, (st_data_t)feature_name, (st_data_t)iseq);
- rb_vm_register_global_object((VALUE)iseq);
-#endif
+ BUILTIN_LOADED(feature_name, iseq);
return iseq;
}
@@ -84,41 +100,5 @@ void
rb_load_with_builtin_functions(const char *feature_name, const struct rb_builtin_function *table)
{
const rb_iseq_t *iseq = builtin_iseq_load(feature_name, table);
- rb_iseq_eval(iseq);
-}
-
-#ifndef INCLUDED_BY_BUILTIN_C
-
-static int
-each_builtin_i(st_data_t key, st_data_t val, st_data_t dmy)
-{
- const char *feature = (const char *)key;
- const rb_iseq_t *iseq = (const rb_iseq_t *)val;
-
- rb_yield_values(2, rb_str_new2(feature), rb_iseqw_new(iseq));
-
- return ST_CONTINUE;
-}
-
-/* :nodoc: */
-static VALUE
-each_builtin(VALUE self)
-{
- st_foreach(loaded_builtin_table, each_builtin_i, 0);
- return Qnil;
-}
-
-void
-Init_builtin(void)
-{
- rb_define_singleton_method(rb_cRubyVM, "each_builtin", each_builtin, 0);
- loaded_builtin_table = st_init_strtable();
-}
-
-void
-Init_builtin_features(void)
-{
- // register for ruby
- builtin_iseq_load("gem_prelude", NULL);
+ rb_iseq_eval(iseq, rb_root_box());
}
-#endif
diff --git a/miniinit.c b/miniinit.c
index 09608c1113..b0adf9da2a 100644
--- a/miniinit.c
+++ b/miniinit.c
@@ -54,8 +54,53 @@ Init_ext(void)
{
}
+static void builtin_loaded(const char *feature_name, VALUE iseq);
+#define BUILTIN_LOADED(feature_name, iseq) builtin_loaded(feature_name, (VALUE)(iseq))
+
#include "mini_builtin.c"
+static struct st_table *loaded_builtin_table;
+
+static void
+builtin_loaded(const char *feature_name, VALUE iseq)
+{
+ st_insert(loaded_builtin_table, (st_data_t)feature_name, (st_data_t)iseq);
+ rb_vm_register_global_object(iseq);
+}
+
+static int
+each_builtin_i(st_data_t key, st_data_t val, st_data_t dmy)
+{
+ const char *feature = (const char *)key;
+ const rb_iseq_t *iseq = (const rb_iseq_t *)val;
+
+ rb_yield_values(2, rb_str_new2(feature), rb_iseqw_new(iseq));
+
+ return ST_CONTINUE;
+}
+
+/* :nodoc: */
+static VALUE
+each_builtin(VALUE self)
+{
+ st_foreach(loaded_builtin_table, each_builtin_i, 0);
+ return Qnil;
+}
+
+void
+Init_builtin(void)
+{
+ rb_define_singleton_method(rb_cRubyVM, "each_builtin", each_builtin, 0);
+ loaded_builtin_table = st_init_strtable();
+}
+
+void
+Init_builtin_features(void)
+{
+ // register for ruby
+ builtin_iseq_load("gem_prelude", NULL);
+}
+
void
rb_free_loaded_builtin_table(void)
{
diff --git a/misc/.vscode/settings.json b/misc/.vscode/settings.json
index 7b1a38c536..a2e4e1ec69 100644
--- a/misc/.vscode/settings.json
+++ b/misc/.vscode/settings.json
@@ -2,7 +2,9 @@
"rust-analyzer.cargo.features": [
"disasm",
],
- "rust-analyzer.cargo.unsetTest": [
- "yjit",
- ],
+ "rust-analyzer.cfg.setTest": false,
+ // rust-analyzer bundled in the VSCode extension may only support Rust newer than 1.85.0.
+ // To avoid warnings, install rust-analyzer with `rustup component add rust-analyzer` and
+ // use `~/.cargo/bin/rust-analyzer` with the following config.
+ "rust-analyzer.server.path": "rust-analyzer",
}
diff --git a/misc/expand_tabs.rb b/misc/expand_tabs.rb
index a94eea5046..d26568eefc 100755
--- a/misc/expand_tabs.rb
+++ b/misc/expand_tabs.rb
@@ -59,53 +59,31 @@ class Git
end
DEFAULT_GEM_LIBS = %w[
- abbrev
- base64
- benchmark
bundler
- cmath
- csv
- debug
delegate
did_you_mean
- drb
english
erb
+ error_highlight
fileutils
find
forwardable
- getoptlong
ipaddr
- irb
- logger
- mutex_m
net-http
net-protocol
- observer
open3
open-uri
optparse
ostruct
pp
prettyprint
- prime
- pstore
- rdoc
- readline
- reline
+ prism
resolv
- resolv-replace
- rexml
- rinda
- rss
rubygems
- scanf
securerandom
- set
shellwords
singleton
tempfile
- thwait
time
timeout
tmpdir
@@ -117,27 +95,19 @@ DEFAULT_GEM_LIBS = %w[
]
DEFAULT_GEM_EXTS = %w[
- bigdecimal
- cgi
date
digest
etc
fcntl
- fiddle
io-console
io-nonblock
io-wait
json
- nkf
openssl
pathname
psych
- racc
- readline-ext
stringio
strscan
- syslog
- win32ole
zlib
]
diff --git a/misc/lldb_cruby.py b/misc/lldb_cruby.py
index 400ccb45b9..b3d4fb509a 100755..100644
--- a/misc/lldb_cruby.py
+++ b/misc/lldb_cruby.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env python
#coding: utf-8
#
# Usage: run `command script import -r misc/lldb_cruby.py` on LLDB
@@ -14,6 +13,7 @@ import sys
import shlex
import platform
import glob
+import math
from lldb_rb.constants import *
@@ -67,7 +67,7 @@ class BackTrace:
return self.VM_FRAME_MAGIC_NAME.get(frame_type, "(none)")
def rb_iseq_path_str(self, iseq):
- tRBasic = self.target.FindFirstType("struct RBasic").GetPointerType()
+ tRBasic = self.target.FindFirstType("::RBasic").GetPointerType()
pathobj = iseq.GetValueForExpressionPath("->body->location.pathobj")
pathobj = pathobj.Cast(tRBasic)
@@ -269,8 +269,7 @@ def lldb_inspect(debugger, target, result, val):
elif num & RUBY_IMMEDIATE_MASK:
print('immediate(%x)' % num, file=result)
else:
- tRBasic = target.FindFirstType("struct RBasic").GetPointerType()
- tRValue = target.FindFirstType("struct RVALUE")
+ tRBasic = target.FindFirstType("::RBasic").GetPointerType()
val = val.Cast(tRBasic)
flags = val.GetValueForExpressionPath("->flags").GetValueAsUnsigned()
@@ -524,10 +523,11 @@ def rb_backtrace(debugger, command, result, internal_dict):
bt.print_bt(val)
def dump_bits(target, result, page, object_address, end = "\n"):
- tRValue = target.FindFirstType("struct RVALUE")
+ slot_size = page.GetChildMemberWithName("heap").GetChildMemberWithName("slot_size").unsigned
+ byte_size = 40 ** math.floor(math.log(slot_size, 40))
tUintPtr = target.FindFirstType("uintptr_t") # bits_t
- num_in_page = (object_address & HEAP_PAGE_ALIGN_MASK) // tRValue.GetByteSize();
+ num_in_page = (object_address & HEAP_PAGE_ALIGN_MASK) // byte_size;
bits_bitlength = tUintPtr.GetByteSize() * 8
bitmap_index = num_in_page // bits_bitlength
bitmap_offset = num_in_page & (bits_bitlength - 1)
@@ -547,10 +547,9 @@ class HeapPageIter:
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.slot_size = page.GetChildMemberWithName('heap').GetChildMemberWithName('slot_size').unsigned
self.counter = 0
- self.tRBasic = target.FindFirstType("struct RBasic")
- self.tRValue = target.FindFirstType("struct RVALUE")
+ self.tRBasic = target.FindFirstType("::RBasic")
def is_valid(self):
heap_page_header_size = self.target.FindFirstType("struct heap_page_header").GetByteSize()
@@ -582,14 +581,13 @@ def dump_page_internal(page, target, process, thread, frame, result, debugger, h
freelist = []
fl_start = page.GetChildMemberWithName('freelist').GetValueAsUnsigned()
- tRVALUE = target.FindFirstType("struct RVALUE")
+ free_slot = target.FindFirstType("struct free_slot")
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()
-
+ obj = target.CreateValueFromAddress("object", obj_addr, free_slot)
+ fl_start = obj.GetChildMemberWithName("next").GetValueAsUnsigned()
page_iter = HeapPageIter(page, target)
if page_iter.is_valid():
diff --git a/misc/lldb_rb/commands/heap_page_command.py b/misc/lldb_rb/commands/heap_page_command.py
index b56a3eae4e..2eed3c3bee 100644
--- a/misc/lldb_rb/commands/heap_page_command.py
+++ b/misc/lldb_rb/commands/heap_page_command.py
@@ -8,14 +8,15 @@ class HeapPageCommand(RbBaseCommand):
help_string = "prints out 'struct heap_page' for a VALUE pointer in the page"
def call(self, debugger, command, exe_ctx, result):
+ self.result = result
self.t_heap_page_body = self.target.FindFirstType("struct heap_page_body")
self.t_heap_page_ptr = self.target.FindFirstType("struct heap_page").GetPointerType()
page = self._get_page(self.frame.EvaluateExpression(command))
page.Cast(self.t_heap_page_ptr)
- self._append_expression(debugger, "(struct heap_page *) %0#x" % page.GetValueAsUnsigned(), result)
- self._append_expression(debugger, "*(struct heap_page *) %0#x" % page.GetValueAsUnsigned(), result)
+ self._append_expression("(struct heap_page *) %0#x" % page.GetValueAsUnsigned())
+ self._append_expression("*(struct heap_page *) %0#x" % page.GetValueAsUnsigned())
def _get_page(self, val):
addr = val.GetValueAsUnsigned()
diff --git a/misc/lldb_rb/commands/print_flags_command.py b/misc/lldb_rb/commands/print_flags_command.py
index 00da4834bf..bc494ae01a 100644
--- a/misc/lldb_rb/commands/print_flags_command.py
+++ b/misc/lldb_rb/commands/print_flags_command.py
@@ -11,13 +11,13 @@ class PrintFlagsCommand(RbBaseCommand):
# call is where our command logic will be implemented
def call(self, debugger, command, exe_ctx, result):
- rclass_t = self.target.FindFirstType("struct RBasic")
+ rclass_t = self.target.FindFirstType("::RBasic")
rcass_ptr = self.target.EvaluateExpression(command).Cast(rclass_t.GetPointerType())
obj_flags = rcass_ptr.GetValueForExpressionPath("->flags").GetValueAsUnsigned()
flags = [
- "RUBY_FL_WB_PROTECTED", "RUBY_FL_PROMOTED0", "RUBY_FL_PROMOTED1", "RUBY_FL_FINALIZE",
- "RUBY_FL_SHAREABLE", "RUBY_FL_EXIVAR", "RUBY_FL_FREEZE",
+ "RUBY_FL_WB_PROTECTED", "RUBY_FL_PROMOTED", "RUBY_FL_FINALIZE",
+ "RUBY_FL_SHAREABLE", "RUBY_FL_FREEZE",
"RUBY_FL_USER0", "RUBY_FL_USER1", "RUBY_FL_USER2", "RUBY_FL_USER3", "RUBY_FL_USER4",
"RUBY_FL_USER5", "RUBY_FL_USER6", "RUBY_FL_USER7", "RUBY_FL_USER8", "RUBY_FL_USER9",
"RUBY_FL_USER10", "RUBY_FL_USER11", "RUBY_FL_USER12", "RUBY_FL_USER13", "RUBY_FL_USER14",
diff --git a/misc/lldb_rb/lldb_interface.py b/misc/lldb_rb/lldb_interface.py
index 785a54b3e3..25930b2e16 100644
--- a/misc/lldb_rb/lldb_interface.py
+++ b/misc/lldb_rb/lldb_interface.py
@@ -5,3 +5,14 @@ class LLDBInterface:
self.process = self.target.GetProcess()
self.thread = self.process.GetSelectedThread()
self.frame = self.thread.GetSelectedFrame()
+
+ def _append_command_output(self, command):
+ output1 = self.result.GetOutput()
+ self.debugger.GetCommandInterpreter().HandleCommand(command, self.result)
+ output2 = self.result.GetOutput()
+ self.result.Clear()
+ self.result.write(output1)
+ self.result.write(output2)
+
+ def _append_expression(self, expression):
+ self._append_command_output("expression " + expression)
diff --git a/misc/lldb_rb/rb_heap_structs.py b/misc/lldb_rb/rb_heap_structs.py
index 86b38dbbbd..798b838080 100644
--- a/misc/lldb_rb/rb_heap_structs.py
+++ b/misc/lldb_rb/rb_heap_structs.py
@@ -1,4 +1,5 @@
import lldb
+import math
from lldb_rb.lldb_interface import LLDBInterface
from lldb_rb.constants import *
@@ -50,8 +51,7 @@ class RbObject(LLDBInterface):
self.flUser9 = self.ruby_globals["RUBY_FL_USER9"]
self.flUshift = self.ruby_globals["RUBY_FL_USHIFT"]
- self.tRBasic = self.target.FindFirstType("struct RBasic").GetPointerType()
- self.tRValue = self.target.FindFirstType("struct RVALUE")
+ self.tRBasic = self.target.FindFirstType("::RBasic").GetPointerType()
self.val = ptr.Cast(self.tRBasic)
self.page = HeapPage(self.debugger, self.val)
@@ -70,10 +70,12 @@ class RbObject(LLDBInterface):
return ' '
def dump_bits(self, result, end = "\n"):
- tRValue = self.target.FindFirstType("struct RVALUE")
tUintPtr = self.target.FindFirstType("uintptr_t") # bits_t
- num_in_page = (self.val.GetValueAsUnsigned() & HEAP_PAGE_ALIGN_MASK) // tRValue.GetByteSize();
+ slot_size = self.page.to_heap_page_struct().GetChildMemberWithName("heap").GetChildMemberWithName("slot_size").unsigned
+ byte_size = 40 ** math.floor(math.log(slot_size, 40))
+
+ num_in_page = (self.val.GetValueAsUnsigned() & HEAP_PAGE_ALIGN_MASK) // byte_size;
bits_bitlength = tUintPtr.GetByteSize() * 8
bitmap_index = num_in_page // bits_bitlength
bitmap_offset = num_in_page & (bits_bitlength - 1)
@@ -109,7 +111,14 @@ class RbObject(LLDBInterface):
return False
def as_type(self, type_name):
- return self.val.Cast(self.tRValue.GetPointerType()).GetValueForExpressionPath("->as."+type_name)
+ if type_name == "array":
+ tRarray = self.target.FindFirstType("struct RArray")
+ return self.val.Cast(tRarray.GetPointerType())
+ elif type_name == "bignum":
+ tRbignum = self.target.FindFirstType("struct RBignum")
+ return self.val.Cast(tRbignum.GetPointerType())
+ else:
+ print("as_type is not implemented for:", type_name)
def ary_ptr(self):
rval = self.as_type("array")
diff --git a/misc/lldb_rb/utils.py b/misc/lldb_rb/utils.py
index a6bbd385cd..1415dd3f33 100644
--- a/misc/lldb_rb/utils.py
+++ b/misc/lldb_rb/utils.py
@@ -8,17 +8,6 @@ class RbInspector(LLDBInterface):
self.result = result
self.ruby_globals = ruby_globals
- def _append_command_output(self, command):
- output1 = self.result.GetOutput()
- self.debugger.GetCommandInterpreter().HandleCommand(command, self.result)
- output2 = self.result.GetOutput()
- self.result.Clear()
- self.result.write(output1)
- self.result.write(output2)
-
- def _append_expression(self, expression):
- self._append_command_output("expression " + expression)
-
def string2cstr(self, rstring):
"""Returns the pointer to the C-string in the given String object"""
if rstring.TypeIsPointerType():
@@ -247,13 +236,26 @@ class RbInspector(LLDBInterface):
elif rval.is_type("RUBY_T_DATA"):
tRTypedData = self.target.FindFirstType("struct RTypedData").GetPointerType()
val = val.Cast(tRTypedData)
- flag = val.GetValueForExpressionPath("->typed_flag")
-
- if flag.GetValueAsUnsigned() == 1:
- print("T_DATA: %s" %
- val.GetValueForExpressionPath("->type->wrap_struct_name"),
+ is_typed_data = self.ruby_globals.get("RUBY_TYPED_FL_IS_TYPED_DATA", None)
+ if is_typed_data:
+ typed = rval.flags & is_typed_data
+ else:
+ typed = val.GetValueForExpressionPath("->typed_flag").GetValueAsUnsigned() == 1
+
+ if typed:
+ type = val.GetValueForExpressionPath("->type").GetValueAsUnsigned()
+ embed = (type & 1)
+ if embed:
+ flaginfo += "[EMBED] "
+ type = self.frame.EvaluateExpression("(rb_data_type_t *)%0#x" % (type & ~1))
+ print("T_DATA: %s%s" %
+ (flaginfo, type.GetValueForExpressionPath("->wrap_struct_name")),
file=self.result)
- self._append_expression("*(struct RTypedData *) %0#x" % val.GetValueAsUnsigned())
+ print("%s", type.Dereference(), file=self.result)
+ ptr = val.GetValueForExpressionPath("->data")
+ if embed:
+ ptr = ptr.AddressOf()
+ self._append_expression("(void *)%0#x" % ptr.GetValueAsUnsigned())
else:
print("T_DATA:", file=self.result)
self._append_expression("*(struct RData *) %0#x" % val.GetValueAsUnsigned())
diff --git a/misc/ruby-style.el b/misc/ruby-style.el
index 13aad77b3d..03d0830d3a 100644
--- a/misc/ruby-style.el
+++ b/misc/ruby-style.el
@@ -56,7 +56,9 @@
(c-basic-offset . 4)
(tab-width . 8)
(indent-tabs-mode . nil)
- (setq show-trailing-whitespace t)
+ (show-trailing-whitespace . t)
+ (c-backslash-column . 1)
+ (c-backslash-max-column . 1)
(c-offsets-alist
(case-label . *)
(label . (ruby-style-label-indent *))
@@ -66,6 +68,17 @@
(access-label /)
)))
+(c-add-style
+ "prism"
+ '("bsd"
+ (c-basic-offset . 4)
+ (tab-width . 8)
+ (indent-tabs-mode . nil)
+ (show-trailing-whitespace . t)
+ (c-offsets-alist
+ (case-label . +)
+ )))
+
;;;###autoload
(defun ruby-style-c-mode ()
(interactive)
diff --git a/misc/tsan_suppressions.txt b/misc/tsan_suppressions.txt
new file mode 100644
index 0000000000..5492500e7f
--- /dev/null
+++ b/misc/tsan_suppressions.txt
@@ -0,0 +1,109 @@
+# TSan: ThreadSanitizer
+# https://github.com/google/sanitizers/wiki/threadsanitizersuppressions
+#
+# This file describes a number of places where TSAN detects problems in CRuby.
+# Many of these indicate bugs. Others are benign (ex. data races that can be
+# replaced with relaxed atomic loads)
+#
+# Usage:
+# Configure with:
+# ./configure cflags='-fsanitize=thread' CC=clang
+# Build and run with:
+# TSAN_OPTIONS="suppressions=$(pwd)/misc/tsan_suppressions.txt:die_after_fork=0"
+#
+# Other useful TSAN_OPTIONS:
+# * halt_on_error=1
+# * strip_path_prefix=$(pwd)/
+
+# Namespaces
+race_top:push_subclass_entry_to_list
+
+# sub_nounderflow includes non-atomic read, possibly other issue
+race:objspace_malloc_increase_body
+
+# Signals and ubf
+race:unregister_ubf_list
+
+# It's already crashing. We're doing our best
+signal:rb_vm_bugreport
+race:check_reserved_signal_
+
+race_top:rb_check_deadlock
+
+# vm->ractor.sched.grq_cnt++
+race_top:ractor_sched_enq
+race_top:ractor_sched_deq
+
+# Race between vm_remove_ractor writing ractor count and
+# native_thread_check_and_create_shared reading it during thread creation.
+# The write happens when a ractor thread exits, the read happens when
+# checking if new shared threads need to be created.
+race:vm_remove_ractor
+
+# th->sched.finished at end of co_start
+race_top:rb_thread_sched_mark_zombies
+
+# Races against timer thread setting th->sched.waiting_reason.flags
+race_top:thread_sched_wait_events
+
+# At thread start
+race_top:rb_ractor_set_current_ec_
+
+# TSan reports a lock-order-inversion between thread_sched_lock_ and this lock.
+# It's unclear if that can cause a deadlock since the lock is on self
+deadlock:ractor_lock_self
+
+# TSan reports a deadlock when reacquiring the this lock after a barrier, but
+# we know the other threads have been stopped
+deadlock:rb_ractor_sched_barrier_start
+
+# RVALUE_AGE_SET manipulates flag bits on objects which may be accessed in Ractors
+race_top:RVALUE_AGE_SET
+
+# Inline caches and call cache updates
+# Multiple threads can race when updating shared call caches during method lookups
+# and argument forwarding. These races involve reading/writing cd->cc fields.
+race_top:vm_cc_call_set
+race_top:vm_cc_class_check
+race_top:vm_search_cc
+race_top:vm_search_method_slowpath0
+race_top:rb_vm_opt_getconstant_path
+race_top:vm_ic_attr_index_set
+race:vm_ic_update
+race:vm_caller_setup_fwd_args
+
+# Race in shape_get_next where multiple threads simultaneously access and modify
+# RCLASS_MAX_IV_COUNT and RCLASS_VARIATION_COUNT fields in class objects.
+# One thread reads the field while another thread calls RCLASS_SET_MAX_IV_COUNT.
+# This happens during instance variable shape transitions in multi-threaded code.
+race:shape_get_next
+
+# Non-atomic reads/writes
+race:gccct_method_search
+
+# Ignore exit for now
+race:rb_ec_finalize
+race:rb_ec_cleanup
+
+# TSan doesn't work well post-fork, this raises errors when creating the new
+# timer thread
+race:after_fork_ruby
+
+# Sets objspace->flags.dont_incremental while writebarrier may be running
+race_top:objspace_each_exec
+race_top:objspace_each_objects_ensure
+
+# Non-atomic lazy initialized static variable
+race_top:rbimpl_intern_const
+
+# Setting def->aliased bitfield non-atomically
+race_top:method_definition_addref
+
+# Switching to setting up tracing. Likely other ractors should be stopped for this.
+race_top:encoded_iseq_trace_instrument
+race:rb_iseq_trace_set_all
+race:rb_tracepoint_enable
+
+# GC enable/disable flag modifications race with object allocation flag reads
+race_top:rb_gc_impl_gc_disable
+race_top:rb_gc_impl_gc_enable
diff --git a/missing/dtoa.c b/missing/dtoa.c
index bce2cb22a1..ba8cd46ebd 100644
--- a/missing/dtoa.c
+++ b/missing/dtoa.c
@@ -98,17 +98,6 @@
* 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
@@ -221,6 +210,29 @@
#include <locale.h>
#endif
+#if defined(HAVE_STDCKDINT_H) || !defined(__has_include)
+#elif __has_include(<stdckdint.h>)
+# define HAVE_STDCKDINT_H 1
+#endif
+#ifdef HAVE_STDCKDINT_H
+# include <stdckdint.h>
+#endif
+
+#if !defined(ckd_add)
+static inline int /* bool */
+ckd_add(int *result, int x, int y)
+{
+ if (x < 0) {
+ if (y < INT_MIN - x) return 1;
+ }
+ else if (x > 0) {
+ if (y > INT_MAX - x) return 1;
+ }
+ *result = x + y;
+ return 0;
+}
+#endif
+
#ifdef MALLOC
extern void *MALLOC(size_t);
#else
@@ -235,14 +247,6 @@ extern void FREE(void*);
#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
@@ -527,83 +531,29 @@ struct Bigint {
typedef struct Bigint Bigint;
-static Bigint *freelist[Kmax+1];
-
-#define BLOCKING_BIGINT ((Bigint *)(-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, 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;
- }
- }
- }
- 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);
+
+ x = 1 << k;
+ rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong));
+ if (!rv) return NULL;
+ rv->k = k;
+ rv->maxwds = x;
rv->sign = rv->wds = 0;
return rv;
}
static void
-Bfree(Bigint *v)
+Bclear(Bigint **vp)
{
- Bigint *vn;
- if (v) {
- if (v->k > Kmax) {
- FREE(v);
- return;
- }
- ACQUIRE_DTOA_LOCK(0);
- 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);
- }
+ Bigint *v = *vp;
+ *vp = NULL;
+ if (v) FREE(v);
}
+#define Bfree(v) Bclear(&(v))
#define Bcopy(x,y) memcpy((char *)&(x)->sign, (char *)&(y)->sign, \
(y)->wds*sizeof(Long) + 2*sizeof(int))
@@ -649,6 +599,10 @@ multadd(Bigint *b, int m, int a) /* multiply by m and add a */
if (carry) {
if (wds >= b->maxwds) {
b1 = Balloc(b->k+1);
+ if (!b1) {
+ Bfree(b);
+ return NULL;
+ }
Bcopy(b1, b);
Bfree(b);
b = b1;
@@ -670,10 +624,12 @@ s2b(const char *s, int nd0, int nd, ULong y9)
for (k = 0, y = 1; x > y; y <<= 1, k++) ;
#ifdef Pack_32
b = Balloc(k);
+ if (!b) return NULL;
b->x[0] = y9;
b->wds = 1;
#else
b = Balloc(k+1);
+ if (!b) return NULL;
b->x[0] = y9 & 0xffff;
b->wds = (b->x[1] = y9 >> 16) ? 2 : 1;
#endif
@@ -683,13 +639,16 @@ s2b(const char *s, int nd0, int nd, ULong y9)
s += 9;
do {
b = multadd(b, 10, *s++ - '0');
+ if (!b) return NULL;
} while (++i < nd0);
s++;
}
else
s += 10;
- for (; i < nd; i++)
+ for (; i < nd; i++) {
b = multadd(b, 10, *s++ - '0');
+ if (!b) return NULL;
+ }
return b;
}
@@ -771,11 +730,14 @@ i2b(int i)
Bigint *b;
b = Balloc(1);
+ if (!b) return NULL;
b->x[0] = i;
b->wds = 1;
return b;
}
+#define Bzero_p(b) (!(b)->x[0] && (b)->wds <= 1)
+
static Bigint *
mult(Bigint *a, Bigint *b)
{
@@ -792,6 +754,14 @@ mult(Bigint *a, Bigint *b)
#endif
#endif
+ if (Bzero_p(a) || Bzero_p(b)) {
+ c = Balloc(0);
+ if (!c) return NULL;
+ c->wds = 1;
+ c->x[0] = 0;
+ return c;
+ }
+
if (a->wds < b->wds) {
c = a;
a = b;
@@ -804,6 +774,7 @@ mult(Bigint *a, Bigint *b)
if (wc > a->maxwds)
k++;
c = Balloc(k);
+ if (!c) return NULL;
for (x = c->x, xa = x + wc; x < xa; x++)
*x = 0;
xa = a->x;
@@ -883,50 +854,47 @@ 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)
+ if ((i = k & 3) != 0) {
b = multadd(b, p05[i-1], 0);
+ if (!b) return NULL;
+ }
+
+#define b_cache(var, addr, new_expr) \
+ if ((var = addr) != 0) {} else { \
+ Bigint *tmp = 0; \
+ ACQUIRE_DTOA_LOCK(1); \
+ if (!(var = addr) && (var = (new_expr)) != 0) { \
+ var->next = 0; \
+ tmp = ATOMIC_PTR_CAS(addr, NULL, var); \
+ } \
+ FREE_DTOA_LOCK(1); \
+ if (UNLIKELY(tmp)) { \
+ Bfree(var); \
+ var = tmp; \
+ } \
+ else if (!var) { \
+ Bfree(b); \
+ return NULL; \
+ } \
+ }
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);
- }
+ /* first time */
+ b_cache(p5, p5s, i2b(625));
for (;;) {
if (k & 1) {
b1 = mult(b, p5);
Bfree(b);
b = b1;
+ if (!b) return NULL;
}
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);
- }
+ b_cache(p51, p5->next, mult(p5, p5));
p5 = p51;
}
return b;
@@ -939,6 +907,8 @@ lshift(Bigint *b, int k)
Bigint *b1;
ULong *x, *x1, *xe, z;
+ if (!k || Bzero_p(b)) return b;
+
#ifdef Pack_32
n = k >> 5;
#else
@@ -949,6 +919,10 @@ lshift(Bigint *b, int k)
for (i = b->maxwds; n1 > i; i <<= 1)
k1++;
b1 = Balloc(k1);
+ if (!b1) {
+ Bfree(b);
+ return NULL;
+ }
x1 = b1->x;
for (i = 0; i < n; i++)
*x1++ = 0;
@@ -1034,6 +1008,7 @@ diff(Bigint *a, Bigint *b)
i = cmp(a,b);
if (!i) {
c = Balloc(0);
+ if (!c) return NULL;
c->wds = 1;
c->x[0] = 0;
return c;
@@ -1047,6 +1022,7 @@ diff(Bigint *a, Bigint *b)
else
i = 0;
c = Balloc(a->k);
+ if (!c) return NULL;
c->sign = i;
wa = a->wds;
xa = a->x;
@@ -1232,6 +1208,7 @@ d2b(double d_, int *e, int *bits)
#else
b = Balloc(2);
#endif
+ if (!b) return NULL;
x = b->x;
z = d0 & Frac_mask;
@@ -1552,7 +1529,7 @@ break2:
aadj = 1.0;
nd0 = -4;
- if (!*++s || !(s1 = strchr(hexdigit, *s))) goto ret0;
+ if (!*++s || (!(s1 = strchr(hexdigit, *s)) && *s != '.')) goto ret0;
if (*s == '0') {
while (*++s == '0');
if (!*s) goto ret;
@@ -1566,9 +1543,7 @@ break2:
} while (*++s && (s1 = strchr(hexdigit, *s)));
}
- if (*s == '.') {
- dsign = 1;
- if (!*++s || !(s1 = strchr(hexdigit, *s))) goto ret0;
+ if ((*s == '.') && *++s && (s1 = strchr(hexdigit, *s))) {
if (nd0 < 0) {
while (*s == '0') {
s++;
@@ -1583,9 +1558,6 @@ break2:
}
}
}
- else {
- dsign = 0;
- }
if (*s == 'P' || *s == 'p') {
dsign = 0x2C - *++s; /* +: 2B, -: 2D */
@@ -1608,9 +1580,6 @@ break2:
} while ('0' <= c && c <= '9');
nd0 += nd * dsign;
}
- else {
- if (dsign) goto ret0;
- }
dval(rv) = ldexp(adj, nd0);
goto ret;
}
@@ -1647,9 +1616,9 @@ break2:
}
#endif
if (c == '.') {
- if (!ISDIGIT(s[1]))
- goto dig_done;
c = *++s;
+ if (!ISDIGIT(c))
+ goto dig_done;
if (!nd) {
for (; c == '0'; c = *++s)
nz++;
@@ -1990,12 +1959,16 @@ undfl:
/* Put digits into bd: true value = bd * 10^e */
bd0 = s2b(s0, nd0, nd, y);
+ if (!bd0) goto ret;
for (;;) {
bd = Balloc(bd0->k);
+ if (!bd) goto retfree;
Bcopy(bd, bd0);
bb = d2b(dval(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
+ if (!bb) goto retfree;
bs = i2b(1);
+ if (!bs) goto retfree;
if (e >= 0) {
bb2 = bb5 = 0;
@@ -2052,19 +2025,30 @@ undfl:
}
if (bb5 > 0) {
bs = pow5mult(bs, bb5);
+ if (!bs) goto retfree;
bb1 = mult(bs, bb);
Bfree(bb);
bb = bb1;
+ if (!bb) goto retfree;
}
- if (bb2 > 0)
+ if (bb2 > 0) {
bb = lshift(bb, bb2);
- if (bd5 > 0)
+ if (!bb) goto retfree;
+ }
+ if (bd5 > 0) {
bd = pow5mult(bd, bd5);
- if (bd2 > 0)
+ if (!bd) goto retfree;
+ }
+ if (bd2 > 0) {
bd = lshift(bd, bd2);
- if (bs2 > 0)
+ if (!bd) goto retfree;
+ }
+ if (bs2 > 0) {
bs = lshift(bs, bs2);
+ if (!bs) goto retfree;
+ }
delta = diff(bb, bd);
+ if (!delta) goto retfree;
dsign = delta->sign;
delta->sign = 0;
i = cmp(delta, bs);
@@ -2097,6 +2081,7 @@ undfl:
#endif
{
delta = lshift(delta,Log2P);
+ if (!delta) goto nomem;
if (cmp(delta, bs) <= 0)
adj = -0.5;
}
@@ -2186,6 +2171,7 @@ apply_adj:
break;
}
delta = lshift(delta,Log2P);
+ if (!delta) goto retfree;
if (cmp(delta, bs) > 0)
goto drop_down;
break;
@@ -2588,6 +2574,7 @@ nrv_alloc(const char *s, char **rve, size_t n)
char *rv, *t;
t = rv = rv_alloc(n);
+ if (!rv) return NULL;
while ((*t = *s++) != 0) t++;
if (rve)
*rve = t;
@@ -2760,6 +2747,7 @@ dtoa(double d_, int mode, int ndigits, int *decpt, int *sign, char **rve)
#endif
b = d2b(dval(d), &be, &bbits);
+ if (!b) return NULL;
#ifdef Sudden_Underflow
i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
#else
@@ -2879,13 +2867,20 @@ dtoa(double d_, int mode, int ndigits, int *decpt, int *sign, char **rve)
leftright = 0;
/* no break */
case 5:
- i = ndigits + k + 1;
+ if (ckd_add(&i, ndigits, k + 1)) { /* k + 1 should be safe */
+ Bfree(b);
+ return NULL;
+ }
ilim = i;
ilim1 = i - 1;
if (i <= 0)
i = 1;
}
s = s0 = rv_alloc(i+1);
+ if (!s) {
+ Bfree(b);
+ return NULL;
+ }
#ifdef Honor_FLT_ROUNDS
if (mode > 1 && rounding != 1)
@@ -3066,6 +3061,7 @@ bump_up:
b2 += i;
s2 += i;
mhi = i2b(1);
+ if (!mhi) goto nomem;
}
if (m2 > 0 && s2 > 0) {
i = m2 < s2 ? m2 : s2;
@@ -3077,19 +3073,28 @@ bump_up:
if (leftright) {
if (m5 > 0) {
mhi = pow5mult(mhi, m5);
+ if (!mhi) goto nomem;
b1 = mult(mhi, b);
Bfree(b);
b = b1;
+ if (!b) goto nomem;
}
- if ((j = b5 - m5) != 0)
+ if ((j = b5 - m5) != 0) {
b = pow5mult(b, j);
+ if (!b) goto nomem;
+ }
}
- else
+ else {
b = pow5mult(b, b5);
+ if (!b) goto nomem;
+ }
}
S = i2b(1);
- if (s5 > 0)
+ if (!S) goto nomem;
+ if (s5 > 0) {
S = pow5mult(S, s5);
+ if (!S) goto nomem;
+ }
/* Check for special case that d is a normalized power of 2. */
@@ -3137,16 +3142,23 @@ bump_up:
m2 += i;
s2 += i;
}
- if (b2 > 0)
+ if (b2 > 0) {
b = lshift(b, b2);
- if (s2 > 0)
+ if (!b) goto nomem;
+ }
+ if (s2 > 0) {
S = lshift(S, s2);
+ if (!S) goto nomem;
+ }
if (k_check) {
if (cmp(b,S) < 0) {
k--;
b = multadd(b, 10, 0); /* we botched the k estimate */
- if (leftright)
+ if (!b) goto nomem;
+ if (leftright) {
mhi = multadd(mhi, 10, 0);
+ if (!mhi) goto nomem;
+ }
ilim = ilim1;
}
}
@@ -3163,8 +3175,10 @@ one_digit:
goto ret;
}
if (leftright) {
- if (m2 > 0)
+ if (m2 > 0) {
mhi = lshift(mhi, m2);
+ if (!mhi) goto nomem;
+ }
/* Compute mlo -- check for special case
* that d is a normalized power of 2.
@@ -3173,8 +3187,10 @@ one_digit:
mlo = mhi;
if (spec_case) {
mhi = Balloc(mhi->k);
+ if (!mhi) goto nomem;
Bcopy(mhi, mlo);
mhi = lshift(mhi, Log2P);
+ if (!mhi) goto nomem;
}
for (i = 1;;i++) {
@@ -3184,6 +3200,7 @@ one_digit:
*/
j = cmp(b, mlo);
delta = diff(S, mhi);
+ if (!delta) goto nomem;
j1 = delta->sign ? 1 : cmp(b, delta);
Bfree(delta);
#ifndef ROUND_BIASED
@@ -3224,6 +3241,7 @@ one_digit:
#endif /*Honor_FLT_ROUNDS*/
if (j1 > 0) {
b = lshift(b, 1);
+ if (!b) goto nomem;
j1 = cmp(b, S);
if ((j1 > 0 || (j1 == 0 && (dig & 1))) && dig++ == '9')
goto round_9_up;
@@ -3252,11 +3270,16 @@ keep_dig:
if (i == ilim)
break;
b = multadd(b, 10, 0);
- if (mlo == mhi)
+ if (!b) goto nomem;
+ if (mlo == mhi) {
mlo = mhi = multadd(mhi, 10, 0);
+ if (!mlo) goto nomem;
+ }
else {
mlo = multadd(mlo, 10, 0);
+ if (!mlo) goto nomem;
mhi = multadd(mhi, 10, 0);
+ if (!mhi) goto nomem;
}
}
}
@@ -3272,6 +3295,7 @@ keep_dig:
if (i >= ilim)
break;
b = multadd(b, 10, 0);
+ if (!b) goto nomem;
}
/* Round off last digit */
@@ -3283,6 +3307,7 @@ keep_dig:
}
#endif
b = lshift(b, 1);
+ if (!b) goto nomem;
j = cmp(b, S);
if (j > 0 || (j == 0 && (dig & 1))) {
roundoff:
@@ -3324,6 +3349,16 @@ ret1:
if (rve)
*rve = s;
return s0;
+ nomem:
+ if (S) Bfree(S);
+ if (mhi) {
+ if (mlo && mlo != mhi)
+ Bfree(mlo);
+ Bfree(mhi);
+ }
+ if (b) Bfree(b);
+ FREE(s0);
+ return NULL;
}
/*-
@@ -3432,6 +3467,7 @@ hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign, char **rv
*/
bufsize = (ndigits > 0) ? ndigits : SIGFIGS;
s0 = rv_alloc(bufsize+1);
+ if (!s0) return NULL;
/* Round to the desired number of digits. */
if (SIGFIGS > ndigits && ndigits > 0) {
diff --git a/nilclass.rb b/nilclass.rb
index 5a2e19680d..acd5666c71 100644
--- a/nilclass.rb
+++ b/nilclass.rb
@@ -1,6 +1,32 @@
class NilClass
#
# call-seq:
+ # rationalize(eps = nil) -> (0/1)
+ #
+ # Returns zero as a Rational:
+ #
+ # nil.rationalize # => (0/1)
+ #
+ # Argument +eps+ is ignored.
+ #
+ def rationalize(eps = nil)
+ 0r
+ end
+
+ #
+ # call-seq:
+ # to_c -> (0+0i)
+ #
+ # Returns zero as a Complex:
+ #
+ # nil.to_c # => (0+0i)
+ #
+ def to_c
+ 0i
+ end
+
+ #
+ # call-seq:
# nil.to_i -> 0
#
# Always returns zero.
@@ -22,4 +48,16 @@ class NilClass
def to_f
return 0.0
end
+
+ #
+ # call-seq:
+ # to_r -> (0/1)
+ #
+ # Returns zero as a Rational:
+ #
+ # nil.to_r # => (0/1)
+ #
+ def to_r
+ 0r
+ end
end
diff --git a/node.c b/node.c
index 2efcd6eba8..5d00823eb6 100644
--- a/node.c
+++ b/node.c
@@ -163,6 +163,14 @@ parser_tokens_free(rb_ast_t *ast, rb_parser_ary_t *tokens)
}
static void
+parser_nodes_free(rb_ast_t *ast, rb_parser_ary_t *nodes)
+{
+ /* Do nothing for nodes because nodes are freed when rb_ast_t is freed */
+ xfree(nodes->data);
+ xfree(nodes);
+}
+
+static void
free_ast_value(rb_ast_t *ast, void *ctx, NODE *node)
{
switch (nd_type(node)) {
@@ -206,6 +214,9 @@ free_ast_value(rb_ast_t *ast, void *ctx, NODE *node)
case NODE_IMAGINARY:
xfree(RNODE_IMAGINARY(node)->val);
break;
+ case NODE_UNDEF:
+ parser_nodes_free(ast, RNODE_UNDEF(node)->nd_undefs);
+ break;
default:
break;
}
@@ -214,7 +225,7 @@ free_ast_value(rb_ast_t *ast, void *ctx, NODE *node)
static void
rb_node_buffer_free(rb_ast_t *ast, node_buffer_t *nb)
{
- if (nb && nb->tokens) {
+ if (nb->tokens) {
parser_tokens_free(ast, nb->tokens);
}
iterate_node_values(ast, &nb->buffer_list, free_ast_value, NULL);
@@ -427,3 +438,9 @@ rb_node_set_type(NODE *n, enum node_type t)
{
return nd_init_type(n, t);
}
+
+enum node_type
+rb_node_get_type(const NODE *n)
+{
+ return (enum node_type)nd_type(n);
+}
diff --git a/node.h b/node.h
index 1e411f211b..d8ee7dbb64 100644
--- a/node.h
+++ b/node.h
@@ -67,16 +67,27 @@ const struct kwtable *rb_reserved_word(const char *, unsigned int);
struct parser_params;
PRINTF_ARGS(void rb_parser_printf(struct parser_params *parser, const char *fmt, ...), 2, 3);
VALUE rb_node_set_type(NODE *n, enum node_type t);
+enum node_type rb_node_get_type(const NODE *n);
RUBY_SYMBOL_EXPORT_END
#define NODE_LSHIFT (NODE_TYPESHIFT+7)
#define NODE_LMASK (((SIGNED_VALUE)1<<(sizeof(VALUE)*CHAR_BIT-NODE_LSHIFT))-1)
-#define nd_line(n) (int)(((SIGNED_VALUE)(n)->flags)>>NODE_LSHIFT)
-#define nd_set_line(n,l) \
- (n)->flags=(((n)->flags&~((VALUE)(-1)<<NODE_LSHIFT))|((VALUE)((l)&NODE_LMASK)<<NODE_LSHIFT))
+static inline int
+nd_line(const NODE *n)
+{
+ if (!n) return -1;
+ SIGNED_VALUE flags = (SIGNED_VALUE)n->flags;
+ return (int)(flags >> NODE_LSHIFT);
+}
+static inline void
+nd_set_line(NODE *n, SIGNED_VALUE l)
+{
+ n->flags &= ~(~(VALUE)0 << NODE_LSHIFT);
+ n->flags |= ((VALUE)(l & NODE_LMASK) << NODE_LSHIFT);
+}
#define NODE_SPECIAL_REQUIRED_KEYWORD ((NODE *)-1)
#define NODE_REQUIRED_KEYWORD_P(node) ((node) == NODE_SPECIAL_REQUIRED_KEYWORD)
diff --git a/node_dump.c b/node_dump.c
index 37abea8441..82a7d78c28 100644
--- a/node_dump.c
+++ b/node_dump.c
@@ -27,6 +27,10 @@
#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_dump_literal(lit))
+#define A_LOC(loc) \
+ rb_str_catf(buf, "(%d,%d)-(%d,%d)", \
+ loc.beg_pos.lineno, loc.beg_pos.column, \
+ loc.end_pos.lineno, loc.end_pos.column)
#define A_NODE_HEADER(node, term) \
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), \
@@ -84,6 +88,7 @@
#define F_LIT(name, type, ann) SIMPLE_FIELD1(#name, ann) A_LIT(type(node)->name)
#define F_VALUE(name, val, ann) SIMPLE_FIELD1(#name, ann) A_LIT(val)
#define F_MSG(name, ann, desc) SIMPLE_FIELD1(#name, ann) A(desc)
+#define F_LOC(name, type) SIMPLE_FIELD1(#name, "") A_LOC(type(node)->name)
#define F_SHAREABILITY(name, type, ann) SIMPLE_FIELD1(#name, ann) A_SHAREABILITY(type(node)->name)
#define F_NODE(name, type, ann) \
@@ -92,6 +97,9 @@
#define F_NODE2(name, n, ann) \
COMPOUND_FIELD1(#name, ann) {dump_node(buf, indent, comment, n);}
+#define F_ARRAY(name, type, ann) \
+ COMPOUND_FIELD1(#name, ann) {dump_parser_array(buf, indent, comment, type(node)->name);}
+
#define ANN(ann) \
if (comment) { \
A_INDENT; A("| # " ann "\n"); \
@@ -165,6 +173,28 @@ dump_array(VALUE buf, VALUE indent, int comment, const NODE *node)
}
static void
+dump_parser_array(VALUE buf, VALUE indent, int comment, const rb_parser_ary_t *ary)
+{
+ int field_flag;
+ const char *next_indent = default_indent;
+
+ if (ary->data_type != PARSER_ARY_DATA_NODE) {
+ rb_bug("unexpected rb_parser_ary_data_type: %d", ary->data_type);
+ }
+
+ F_CUSTOM1(length, "length") { A_LONG(ary->len); }
+ for (long i = 0; i < ary->len; i++) {
+ if (i == ary->len - 1) LAST_NODE;
+ A_INDENT;
+ rb_str_catf(buf, "+- element (%s%ld):\n",
+ comment ? "statement #" : "", i);
+ D_INDENT;
+ dump_node(buf, indent, comment, ary->data[i]);
+ D_DEDENT;
+ }
+}
+
+static void
dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
{
int field_flag;
@@ -209,8 +239,11 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("example: if x == 1 then foo else bar end");
F_NODE(nd_cond, RNODE_IF, "condition expr");
F_NODE(nd_body, RNODE_IF, "then clause");
- LAST_NODE;
F_NODE(nd_else, RNODE_IF, "else clause");
+ F_LOC(if_keyword_loc, RNODE_IF);
+ F_LOC(then_keyword_loc, RNODE_IF);
+ LAST_NODE;
+ F_LOC(end_keyword_loc, RNODE_IF);
return;
case NODE_UNLESS:
@@ -219,8 +252,11 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("example: unless x == 1 then foo else bar end");
F_NODE(nd_cond, RNODE_UNLESS, "condition expr");
F_NODE(nd_body, RNODE_UNLESS, "then clause");
- LAST_NODE;
F_NODE(nd_else, RNODE_UNLESS, "else clause");
+ F_LOC(keyword_loc, RNODE_UNLESS);
+ F_LOC(then_keyword_loc, RNODE_UNLESS);
+ LAST_NODE;
+ F_LOC(end_keyword_loc, RNODE_UNLESS);
return;
case NODE_CASE:
@@ -228,24 +264,30 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("format: case [nd_head]; [nd_body]; end");
ANN("example: case x; when 1; foo; when 2; bar; else baz; end");
F_NODE(nd_head, RNODE_CASE, "case expr");
- LAST_NODE;
F_NODE(nd_body, RNODE_CASE, "when clauses");
+ F_LOC(case_keyword_loc, RNODE_CASE);
+ LAST_NODE;
+ F_LOC(end_keyword_loc, RNODE_CASE);
return;
case NODE_CASE2:
ANN("case statement with no head");
ANN("format: case; [nd_body]; end");
ANN("example: case; when 1; foo; when 2; bar; else baz; end");
F_NODE(nd_head, RNODE_CASE2, "case expr");
- LAST_NODE;
F_NODE(nd_body, RNODE_CASE2, "when clauses");
+ F_LOC(case_keyword_loc, RNODE_CASE2);
+ LAST_NODE;
+ F_LOC(end_keyword_loc, RNODE_CASE2);
return;
case NODE_CASE3:
ANN("case statement (pattern matching)");
ANN("format: case [nd_head]; [nd_body]; end");
ANN("example: case x; in 1; foo; in 2; bar; else baz; end");
F_NODE(nd_head, RNODE_CASE3, "case expr");
- LAST_NODE;
F_NODE(nd_body, RNODE_CASE3, "in clauses");
+ F_LOC(case_keyword_loc, RNODE_CASE3);
+ LAST_NODE;
+ F_LOC(end_keyword_loc, RNODE_CASE3);
return;
case NODE_WHEN:
@@ -256,6 +298,9 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
F_NODE(nd_body, RNODE_WHEN, "when body");
LAST_NODE;
F_NODE(nd_next, RNODE_WHEN, "next when clause");
+ F_LOC(keyword_loc, RNODE_WHEN);
+ LAST_NODE;
+ F_LOC(then_keyword_loc, RNODE_WHEN);
return;
case NODE_IN:
@@ -264,8 +309,11 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("example: case x; in 1; foo; in 2; bar; else baz; end");
F_NODE(nd_head, RNODE_IN, "in pattern");
F_NODE(nd_body, RNODE_IN, "in body");
- LAST_NODE;
F_NODE(nd_next, RNODE_IN, "next in clause");
+ F_LOC(in_keyword_loc, RNODE_IN);
+ F_LOC(then_keyword_loc, RNODE_IN);
+ LAST_NODE;
+ F_LOC(operator_loc, RNODE_IN);
return;
case NODE_WHILE:
@@ -283,23 +331,32 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
A((RNODE_WHILE(node)->nd_state == 1) ? " (while-end)" : " (begin-end-while)");
}
F_NODE(nd_cond, RNODE_WHILE, "condition");
- LAST_NODE;
F_NODE(nd_body, RNODE_WHILE, "body");
+ F_LOC(keyword_loc, RNODE_WHILE);
+ LAST_NODE;
+ F_LOC(closing_loc, RNODE_WHILE);
return;
case NODE_ITER:
ANN("method call with block");
ANN("format: [nd_iter] { [nd_body] }");
ANN("example: 3.times { foo }");
- goto iter;
+ F_NODE(nd_iter, RNODE_ITER, "iteration receiver");
+ LAST_NODE;
+ F_NODE(nd_body, RNODE_ITER, "body");
+ return;
+
case NODE_FOR:
ANN("for statement");
ANN("format: for * in [nd_iter] do [nd_body] end");
ANN("example: for i in 1..3 do foo end");
- iter:
- F_NODE(nd_iter, RNODE_ITER, "iteration receiver");
+ F_NODE(nd_iter, RNODE_FOR, "iteration receiver");
+ F_NODE(nd_body, RNODE_FOR, "body");
+ F_LOC(for_keyword_loc, RNODE_FOR);
+ F_LOC(in_keyword_loc, RNODE_FOR);
+ F_LOC(do_keyword_loc, RNODE_FOR);
LAST_NODE;
- F_NODE(nd_body, RNODE_ITER, "body");
+ F_LOC(end_keyword_loc, RNODE_FOR);
return;
case NODE_FOR_MASGN:
@@ -314,28 +371,32 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("break statement");
ANN("format: break [nd_stts]");
ANN("example: break 1");
- LAST_NODE;
F_NODE(nd_stts, RNODE_BREAK, "value");
+ LAST_NODE;
+ F_LOC(keyword_loc, RNODE_BREAK);
return;
case NODE_NEXT:
ANN("next statement");
ANN("format: next [nd_stts]");
ANN("example: next 1");
- LAST_NODE;
F_NODE(nd_stts, RNODE_NEXT, "value");
+ LAST_NODE;
+ F_LOC(keyword_loc, RNODE_NEXT);
return;
case NODE_RETURN:
ANN("return statement");
ANN("format: return [nd_stts]");
ANN("example: return 1");
- LAST_NODE;
F_NODE(nd_stts, RNODE_RETURN, "value");
+ LAST_NODE;
+ F_LOC(keyword_loc, RNODE_RETURN);
return;
case NODE_REDO:
ANN("redo statement");
ANN("format: redo");
ANN("example: redo");
+ F_LOC(keyword_loc, RNODE_REDO);
return;
case NODE_RETRY:
@@ -364,9 +425,10 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
case NODE_RESBODY:
ANN("rescue clause (cont'd)");
- ANN("format: rescue [nd_args]; [nd_body]; (rescue) [nd_head]");
+ ANN("format: rescue [nd_args] (=> [nd_exc_var]); [nd_body]; (rescue) [nd_next]");
ANN("example: begin; foo; rescue; bar; else; baz; end");
F_NODE(nd_args, RNODE_RESBODY, "rescue exceptions");
+ F_NODE(nd_exc_var, RNODE_RESBODY, "exception variable");
F_NODE(nd_body, RNODE_RESBODY, "rescue clause");
LAST_NODE;
F_NODE(nd_next, RNODE_RESBODY, "next rescue clause");
@@ -397,8 +459,9 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
break;
node = RNODE_AND(node)->nd_2nd;
}
- LAST_NODE;
F_NODE(nd_2nd, RNODE_AND, "right expr");
+ LAST_NODE;
+ F_LOC(operator_loc, RNODE_AND);
return;
case NODE_MASGN:
@@ -492,8 +555,12 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
F_NODE(nd_recv, RNODE_OP_ASGN1, "receiver");
F_ID(nd_mid, RNODE_OP_ASGN1, "operator");
F_NODE(nd_index, RNODE_OP_ASGN1, "index");
- LAST_NODE;
F_NODE(nd_rvalue, RNODE_OP_ASGN1, "rvalue");
+ F_LOC(call_operator_loc, RNODE_OP_ASGN1);
+ F_LOC(opening_loc, RNODE_OP_ASGN1);
+ F_LOC(closing_loc, RNODE_OP_ASGN1);
+ LAST_NODE;
+ F_LOC(binary_operator_loc, RNODE_OP_ASGN1);
return;
case NODE_OP_ASGN2:
@@ -506,8 +573,11 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
A_ID(RNODE_OP_ASGN2(node)->nd_vid);
}
F_ID(nd_mid, RNODE_OP_ASGN2, "operator");
- LAST_NODE;
F_NODE(nd_value, RNODE_OP_ASGN2, "rvalue");
+ F_LOC(call_operator_loc, RNODE_OP_ASGN2);
+ F_LOC(message_loc, RNODE_OP_ASGN2);
+ LAST_NODE;
+ F_LOC(binary_operator_loc, RNODE_OP_ASGN2);
return;
case NODE_OP_ASGN_AND:
@@ -586,8 +656,11 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("super invocation");
ANN("format: super [nd_args]");
ANN("example: super 1");
- LAST_NODE;
F_NODE(nd_args, RNODE_SUPER, "arguments");
+ F_LOC(keyword_loc, RNODE_SUPER);
+ F_LOC(lparen_loc, RNODE_SUPER);
+ LAST_NODE;
+ F_LOC(rparen_loc, RNODE_SUPER);
return;
case NODE_ZSUPER:
@@ -634,8 +707,11 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("yield invocation");
ANN("format: yield [nd_head]");
ANN("example: yield 1");
- LAST_NODE;
F_NODE(nd_head, RNODE_YIELD, "arguments");
+ F_LOC(keyword_loc, RNODE_YIELD);
+ F_LOC(lparen_loc, RNODE_YIELD);
+ LAST_NODE;
+ F_LOC(rparen_loc, RNODE_YIELD);
return;
case NODE_LVAR:
@@ -769,8 +845,11 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("regexp literal");
ANN("format: [string]");
ANN("example: /foo/");
- LAST_NODE;
F_VALUE(string, rb_node_regx_string_val(node), "string");
+ F_LOC(opening_loc, RNODE_REGX);
+ F_LOC(content_loc, RNODE_REGX);
+ LAST_NODE;
+ F_LOC(closing_loc, RNODE_REGX);
return;
case NODE_ONCE:
@@ -819,8 +898,10 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("interpolation expression");
ANN("format: \"..#{ [nd_body] }..\"");
ANN("example: \"foo#{ bar }baz\"");
- LAST_NODE;
F_NODE(nd_body, RNODE_EVSTR, "body");
+ F_LOC(opening_loc, RNODE_EVSTR);
+ LAST_NODE;
+ F_LOC(closing_loc, RNODE_EVSTR);
return;
case NODE_ARGSCAT:
@@ -845,17 +926,25 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("splat argument");
ANN("format: *[nd_head]");
ANN("example: foo(*ary)");
- LAST_NODE;
F_NODE(nd_head, RNODE_SPLAT, "splat'ed array");
+ LAST_NODE;
+ F_LOC(operator_loc, RNODE_SPLAT);
return;
case NODE_BLOCK_PASS:
ANN("arguments with block argument");
ANN("format: ..([nd_head], &[nd_body])");
ANN("example: foo(x, &blk)");
+ F_CUSTOM1(forwarding, "arguments forwarding or not") {
+ switch (RNODE_BLOCK_PASS(node)->forwarding) {
+ case 0: A("0 (no forwarding)"); break;
+ case 1: A("1 (forwarding)"); break;
+ }
+ }
F_NODE(nd_head, RNODE_BLOCK_PASS, "other arguments");
- LAST_NODE;
F_NODE(nd_body, RNODE_BLOCK_PASS, "block argument");
+ LAST_NODE;
+ F_LOC(operator_loc, RNODE_BLOCK_PASS);
return;
case NODE_DEFN:
@@ -882,8 +971,9 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("format: alias [nd_1st] [nd_2nd]");
ANN("example: alias bar foo");
F_NODE(nd_1st, RNODE_ALIAS, "new name");
- LAST_NODE;
F_NODE(nd_2nd, RNODE_ALIAS, "old name");
+ LAST_NODE;
+ F_LOC(keyword_loc, RNODE_ALIAS);
return;
case NODE_VALIAS:
@@ -892,14 +982,16 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("example: alias $y $x");
F_ID(nd_alias, RNODE_VALIAS, "new name");
F_ID(nd_orig, RNODE_VALIAS, "old name");
+ F_LOC(keyword_loc, RNODE_VALIAS);
return;
case NODE_UNDEF:
ANN("method undef statement");
- ANN("format: undef [nd_undef]");
+ ANN("format: undef [nd_undefs]");
ANN("example: undef foo");
LAST_NODE;
- F_NODE(nd_undef, RNODE_UNDEF, "old name");
+ F_ARRAY(nd_undefs, RNODE_UNDEF, "nd_undefs");
+ F_LOC(keyword_loc, RNODE_UNDEF);
return;
case NODE_CLASS:
@@ -908,8 +1000,11 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("example: class C2 < C; ..; end");
F_NODE(nd_cpath, RNODE_CLASS, "class path");
F_NODE(nd_super, RNODE_CLASS, "superclass");
- LAST_NODE;
F_NODE(nd_body, RNODE_CLASS, "class definition");
+ F_LOC(class_keyword_loc, RNODE_CLASS);
+ F_LOC(inheritance_operator_loc, RNODE_CLASS);
+ LAST_NODE;
+ F_LOC(end_keyword_loc, RNODE_CLASS);
return;
case NODE_MODULE:
@@ -917,8 +1012,10 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("format: module [nd_cpath]; [nd_body]; end");
ANN("example: module M; ..; end");
F_NODE(nd_cpath, RNODE_MODULE, "module path");
- LAST_NODE;
F_NODE(nd_body, RNODE_MODULE, "module definition");
+ F_LOC(module_keyword_loc, RNODE_MODULE);
+ LAST_NODE;
+ F_LOC(end_keyword_loc, RNODE_MODULE);
return;
case NODE_SCLASS:
@@ -926,8 +1023,11 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("format: class << [nd_recv]; [nd_body]; end");
ANN("example: class << obj; ..; end");
F_NODE(nd_recv, RNODE_SCLASS, "receiver");
- LAST_NODE;
F_NODE(nd_body, RNODE_SCLASS, "singleton class definition");
+ F_LOC(class_keyword_loc, RNODE_SCLASS);
+ F_LOC(operator_loc, RNODE_SCLASS);
+ LAST_NODE;
+ F_LOC(end_keyword_loc, RNODE_SCLASS);
return;
case NODE_COLON2:
@@ -935,8 +1035,10 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("format: [nd_head]::[nd_mid]");
ANN("example: M::C");
F_ID(nd_mid, RNODE_COLON2, "constant name");
- LAST_NODE;
F_NODE(nd_head, RNODE_COLON2, "receiver");
+ F_LOC(delimiter_loc, RNODE_COLON2);
+ LAST_NODE;
+ F_LOC(name_loc, RNODE_COLON2);
return;
case NODE_COLON3:
@@ -944,6 +1046,8 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("format: ::[nd_mid]");
ANN("example: ::Object");
F_ID(nd_mid, RNODE_COLON3, "constant name");
+ F_LOC(delimiter_loc, RNODE_COLON3);
+ F_LOC(name_loc, RNODE_COLON3);
return;
case NODE_DOT2:
@@ -967,8 +1071,9 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("example: if (x==1)...(x==5); foo; end");
dot:
F_NODE(nd_beg, RNODE_DOT2, "begin");
- LAST_NODE;
F_NODE(nd_end, RNODE_DOT2, "end");
+ LAST_NODE;
+ F_LOC(operator_loc, RNODE_DOT2);
return;
case NODE_SELF:
@@ -1009,14 +1114,19 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("format: defined?([nd_head])");
ANN("example: defined?(foo)");
F_NODE(nd_head, RNODE_DEFINED, "expr");
+ LAST_NODE;
+ F_LOC(keyword_loc, RNODE_DEFINED);
return;
case NODE_POSTEXE:
ANN("post-execution");
ANN("format: END { [nd_body] }");
ANN("example: END { foo }");
- LAST_NODE;
F_NODE(nd_body, RNODE_POSTEXE, "END clause");
+ F_LOC(keyword_loc, RNODE_POSTEXE);
+ F_LOC(opening_loc, RNODE_POSTEXE);
+ LAST_NODE;
+ F_LOC(closing_loc, RNODE_POSTEXE);
return;
case NODE_ATTRASGN:
@@ -1033,8 +1143,11 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("lambda expression");
ANN("format: -> [nd_body]");
ANN("example: -> { foo }");
- LAST_NODE;
F_NODE(nd_body, RNODE_LAMBDA, "lambda clause");
+ F_LOC(operator_loc, RNODE_LAMBDA);
+ F_LOC(opening_loc, RNODE_LAMBDA);
+ LAST_NODE;
+ F_LOC(closing_loc, RNODE_LAMBDA);
return;
case NODE_OPT_ARG:
@@ -1073,6 +1186,12 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("method parameters");
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_CUSTOM1(nd_ainfo.forwarding, "arguments forwarding or not") {
+ switch (RNODE_ARGS(node)->nd_ainfo.forwarding) {
+ case 0: A("0 (no forwarding)"); break;
+ case 1: A("1 (forwarding)"); break;
+ }
+ }
F_INT(nd_ainfo.pre_args_num, RNODE_ARGS, "count of mandatory (pre-)arguments");
F_NODE(nd_ainfo.pre_init, RNODE_ARGS, "initialization of (pre-)arguments");
F_INT(nd_ainfo.post_args_num, RNODE_ARGS, "count of mandatory post-arguments");
diff --git a/numeric.c b/numeric.c
index 4db0834ae3..e8df2a6aa0 100644
--- a/numeric.c
+++ b/numeric.c
@@ -552,39 +552,6 @@ num_clone(int argc, VALUE *argv, VALUE x)
# define num_clone rb_immutable_obj_clone
#endif
-#if 0
-/*
- * call-seq:
- * dup -> self
- *
- * Returns +self+.
- *
- * Related: Numeric#clone.
- *
- */
-static VALUE
-num_dup(VALUE x)
-{
- return x;
-}
-#else
-# define num_dup num_uplus
-#endif
-
-/*
- * call-seq:
- * +self -> self
- *
- * Returns +self+.
- *
- */
-
-static VALUE
-num_uplus(VALUE num)
-{
- return num;
-}
-
/*
* call-seq:
* i -> complex
@@ -609,7 +576,7 @@ num_imaginary(VALUE num)
* call-seq:
* -self -> numeric
*
- * Unary Minus---Returns the receiver, negated.
+ * Returns +self+, negated.
*/
static VALUE
@@ -628,8 +595,8 @@ num_uminus(VALUE num)
* fdiv(other) -> float
*
* Returns the quotient <tt>self/other</tt> as a float,
- * using method +/+ in the derived class of +self+.
- * (\Numeric itself does not define method +/+.)
+ * using method +/+ as defined in the subclass of \Numeric.
+ * (\Numeric itself does not define +/+.)
*
* Of the Core and Standard Library classes,
* only BigDecimal uses this implementation.
@@ -647,8 +614,8 @@ num_fdiv(VALUE x, VALUE y)
* div(other) -> integer
*
* Returns the quotient <tt>self/other</tt> as an integer (via +floor+),
- * using method +/+ in the derived class of +self+.
- * (\Numeric itself does not define method +/+.)
+ * using method +/+ as defined in the subclass of \Numeric.
+ * (\Numeric itself does not define +/+.)
*
* Of the Core and Standard Library classes,
* Only Float and Rational use this implementation.
@@ -666,7 +633,7 @@ num_div(VALUE x, VALUE y)
* call-seq:
* self % other -> real_numeric
*
- * Returns +self+ modulo +other+ as a real number.
+ * Returns +self+ modulo +other+ as a real numeric (\Integer, \Float, or \Rational).
*
* Of the Core and Standard Library classes,
* only Rational uses this implementation.
@@ -862,7 +829,7 @@ rb_int_zero_p(VALUE num)
* Of the Core and Standard Library classes,
* Integer, Float, Rational, and Complex use this implementation.
*
- * Related: #zero?
+ * Related: #zero?
*
*/
@@ -880,7 +847,8 @@ num_nonzero_p(VALUE num)
* to_int -> integer
*
* Returns +self+ as an integer;
- * converts using method +to_i+ in the derived class.
+ * converts using method +to_i+ in the subclass of \Numeric.
+ * (\Numeric itself does not define +to_i+.)
*
* Of the Core and Standard Library classes,
* only Rational and Complex use this implementation.
@@ -890,7 +858,7 @@ num_nonzero_p(VALUE num)
* 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)
+ * Complex(2, 1).to_int # Raises RangeError (non-zero imaginary part)
*
*/
@@ -938,88 +906,6 @@ num_negative_p(VALUE num)
return RBOOL(rb_num_negative_int_p(num));
}
-
-/********************************************************************
- *
- * Document-class: Float
- *
- * 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:
- *
- * - https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
- * - https://github.com/rdp/ruby_tutorials_core/wiki/Ruby-Talk-FAQ#-why-are-rubys-floats-imprecise
- * - https://en.wikipedia.org/wiki/Floating_point#Accuracy_problems
- *
- * You can create a \Float object explicitly with:
- *
- * - A {floating-point literal}[rdoc-ref:syntax/literals.rdoc@Float+Literals].
- *
- * You can convert certain objects to Floats with:
- *
- * - \Method #Float.
- *
- * == What's Here
- *
- * First, what's elsewhere. \Class \Float:
- *
- * - Inherits from
- * {class Numeric}[rdoc-ref:Numeric@What-27s+Here]
- * and {class Object}[rdoc-ref:Object@What-27s+Here].
- * - Includes {module Comparable}[rdoc-ref:Comparable@What-27s+Here].
- *
- * Here, class \Float provides methods for:
- *
- * - {Querying}[rdoc-ref:Float@Querying]
- * - {Comparing}[rdoc-ref:Float@Comparing]
- * - {Converting}[rdoc-ref:Float@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
- *
- * - #<: Returns whether +self+ is less than the given value.
- * - #<=: Returns whether +self+ is less than or equal to the given value.
- * - #<=>: Returns a number indicating whether +self+ is less than, equal
- * to, or greater than the given value.
- * - #== (aliased as #=== and #eql?): Returns whether +self+ is equal to
- * the given value.
- * - #>: Returns whether +self+ is greater than the given value.
- * - #>=: 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.
- * - #**: 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.
- * - #/: 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
rb_float_new_in_heap(double d)
{
@@ -1047,16 +933,15 @@ rb_float_new_in_heap(double d)
* may contain:
*
* - A fixed-point number.
+ * 3.14.to_s # => "3.14"
* - A number in "scientific notation" (containing an exponent).
+ * (10.1**50).to_s # => "1.644631821843879e+50"
* - 'Infinity'.
+ * (10.1**500).to_s # => "Infinity"
* - '-Infinity'.
+ * (-10.1**500).to_s # => "-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"
+ * (0.0/0.0).to_s # => "NaN"
*
*/
@@ -1165,15 +1050,21 @@ rb_float_uminus(VALUE flt)
/*
* call-seq:
- * self + other -> numeric
+ * self + other -> float or complex
*
- * Returns a new \Float which is the sum of +self+ and +other+:
+ * Returns the sum of +self+ and +other+;
+ * the result may be inexact (see Float):
*
- * 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)
+ * 3.14 + 0 # => 3.14
+ * 3.14 + 1 # => 4.140000000000001
+ * -3.14 + 0 # => -3.14
+ * -3.14 + 1 # => -2.14
+
+ * 3.14 + -3.14 # => 0.0
+ * -3.14 + -3.14 # => -6.28
+ *
+ * 3.14 + Complex(1, 0) # => (4.140000000000001+0i)
+ * 3.14 + Rational(1, 1) # => 4.140000000000001
*
*/
@@ -1198,7 +1089,7 @@ rb_float_plus(VALUE x, VALUE y)
* call-seq:
* self - other -> numeric
*
- * Returns a new \Float which is the difference of +self+ and +other+:
+ * Returns the difference of +self+ and +other+:
*
* f = 3.14
* f - 1 # => 2.14
@@ -1229,13 +1120,14 @@ rb_float_minus(VALUE x, VALUE y)
* call-seq:
* self * other -> numeric
*
- * Returns a new \Float which is the product of +self+ and +other+:
+ * Returns the numeric 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
@@ -1283,7 +1175,7 @@ rb_flo_div_flo(VALUE x, VALUE y)
* call-seq:
* self / other -> numeric
*
- * Returns a new \Float which is the result of dividing +self+ by +other+:
+ * Returns the quotient of +self+ and +other+:
*
* f = 3.14
* f / 2 # => 1.57
@@ -1392,7 +1284,7 @@ ruby_float_mod(double x, double y)
* call-seq:
* self % other -> float
*
- * Returns +self+ modulo +other+ as a float.
+ * Returns +self+ modulo +other+ as a \Float.
*
* For float +f+ and real number +r+, these expressions are equivalent:
*
@@ -1498,9 +1390,9 @@ flo_divmod(VALUE x, VALUE y)
/*
* call-seq:
- * self ** other -> numeric
+ * self ** exponent -> numeric
*
- * Raises +self+ to the power of +other+:
+ * Returns +self+ raised to the power +exponent+:
*
* f = 3.14
* f ** 2 # => 9.8596
@@ -1555,7 +1447,7 @@ rb_float_pow(VALUE x, VALUE y)
* 1.eql?(Rational(1, 1)) # => false
* 1.eql?(Complex(1, 0)) # => false
*
- * \Method +eql?+ is different from <tt>==</tt> in that +eql?+ requires matching types,
+ * Method +eql?+ is different from <tt>==</tt> in that +eql?+ requires matching types,
* while <tt>==</tt> does not.
*
*/
@@ -1576,10 +1468,17 @@ num_eql(VALUE x, VALUE y)
* call-seq:
* self <=> other -> zero or nil
*
- * Returns zero if +self+ is the same as +other+, +nil+ otherwise.
+ * Compares +self+ and +other+.
*
- * No subclass in the Ruby Core or Standard Library uses this implementation.
+ * Returns:
*
+ * - Zero, if +self+ is the same as +other+.
+ * - +nil+, otherwise.
+ *
+ * \Class \Numeric includes module Comparable,
+ * each of whose methods uses Numeric#<=> for comparison.
+ *
+ * No subclass in the Ruby Core or Standard Library uses this implementation.
*/
static VALUE
@@ -1602,7 +1501,7 @@ num_equal(VALUE x, VALUE y)
* call-seq:
* self == other -> true or false
*
- * Returns +true+ if +other+ has the same value as +self+, +false+ otherwise:
+ * Returns whether +other+ is numerically equal to +self+:
*
* 2.0 == 2 # => true
* 2.0 == 2.0 # => true
@@ -1625,17 +1524,11 @@ rb_float_equal(VALUE x, VALUE y)
}
else if (RB_FLOAT_TYPE_P(y)) {
b = RFLOAT_VALUE(y);
-#if MSC_VERSION_BEFORE(1300)
- if (isnan(b)) return Qfalse;
-#endif
}
else {
return num_equal(x, y);
}
a = RFLOAT_VALUE(x);
-#if MSC_VERSION_BEFORE(1300)
- if (isnan(a)) return Qfalse;
-#endif
return RBOOL(a == b);
}
@@ -1675,30 +1568,32 @@ rb_dbl_cmp(double a, double b)
/*
* call-seq:
- * self <=> other -> -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+:
+ * Compares +self+ and +other+.
+ *
+ * Returns:
*
- * - -1, if +self+ is less than +other+.
- * - 0, if +self+ is equal to +other+.
- * - 1, if +self+ is greater than +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.1 # => -1
* 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
*
- * This is the basis for the tests in the Comparable module.
- *
* <tt>Float::NAN <=> Float::NAN</tt> returns an implementation-dependent value.
*
+ * \Class \Float includes module Comparable,
+ * each of whose methods uses Float#<=> for comparison.
+ *
*/
static VALUE
@@ -1743,7 +1638,8 @@ rb_float_cmp(VALUE x, VALUE y)
* call-seq:
* self > other -> true or false
*
- * Returns +true+ if +self+ is numerically greater than +other+:
+ * Returns whether the value of +self+ is greater than the value of +other+;
+ * +other+ must be numeric, but may not be Complex:
*
* 2.0 > 1 # => true
* 2.0 > 1.0 # => true
@@ -1768,16 +1664,10 @@ rb_float_gt(VALUE x, VALUE y)
}
else if (RB_FLOAT_TYPE_P(y)) {
b = RFLOAT_VALUE(y);
-#if MSC_VERSION_BEFORE(1300)
- if (isnan(b)) return Qfalse;
-#endif
}
else {
return rb_num_coerce_relop(x, y, '>');
}
-#if MSC_VERSION_BEFORE(1300)
- if (isnan(a)) return Qfalse;
-#endif
return RBOOL(a > b);
}
@@ -1785,7 +1675,8 @@ rb_float_gt(VALUE x, VALUE y)
* call-seq:
* self >= other -> true or false
*
- * Returns +true+ if +self+ is numerically greater than or equal to +other+:
+ * Returns whether the value of +self+ is greater than or equal to the value of +other+;
+ * +other+ must be numeric, but may not be Complex:
*
* 2.0 >= 1 # => true
* 2.0 >= 1.0 # => true
@@ -1811,16 +1702,10 @@ flo_ge(VALUE x, VALUE y)
}
else if (RB_FLOAT_TYPE_P(y)) {
b = RFLOAT_VALUE(y);
-#if MSC_VERSION_BEFORE(1300)
- if (isnan(b)) return Qfalse;
-#endif
}
else {
return rb_num_coerce_relop(x, y, idGE);
}
-#if MSC_VERSION_BEFORE(1300)
- if (isnan(a)) return Qfalse;
-#endif
return RBOOL(a >= b);
}
@@ -1828,7 +1713,8 @@ flo_ge(VALUE x, VALUE y)
* call-seq:
* self < other -> true or false
*
- * Returns +true+ if +self+ is numerically less than +other+:
+ * Returns whether the value of +self+ is less than the value of +other+;
+ * +other+ must be numeric, but may not be Complex:
*
* 2.0 < 3 # => true
* 2.0 < 3.0 # => true
@@ -1836,7 +1722,6 @@ flo_ge(VALUE x, VALUE y)
* 2.0 < 2.0 # => false
*
* <tt>Float::NAN < Float::NAN</tt> returns an implementation-dependent value.
- *
*/
static VALUE
@@ -1853,16 +1738,10 @@ flo_lt(VALUE x, VALUE y)
}
else if (RB_FLOAT_TYPE_P(y)) {
b = RFLOAT_VALUE(y);
-#if MSC_VERSION_BEFORE(1300)
- if (isnan(b)) return Qfalse;
-#endif
}
else {
return rb_num_coerce_relop(x, y, '<');
}
-#if MSC_VERSION_BEFORE(1300)
- if (isnan(a)) return Qfalse;
-#endif
return RBOOL(a < b);
}
@@ -1870,7 +1749,8 @@ flo_lt(VALUE x, VALUE y)
* call-seq:
* self <= other -> true or false
*
- * Returns +true+ if +self+ is numerically less than or equal to +other+:
+ * Returns whether the value of +self+ is less than or equal to the value of +other+;
+ * +other+ must be numeric, but may not be Complex:
*
* 2.0 <= 3 # => true
* 2.0 <= 3.0 # => true
@@ -1896,16 +1776,10 @@ flo_le(VALUE x, VALUE y)
}
else if (RB_FLOAT_TYPE_P(y)) {
b = RFLOAT_VALUE(y);
-#if MSC_VERSION_BEFORE(1300)
- if (isnan(b)) return Qfalse;
-#endif
}
else {
return rb_num_coerce_relop(x, y, idLE);
}
-#if MSC_VERSION_BEFORE(1300)
- if (isnan(a)) return Qfalse;
-#endif
return RBOOL(a <= b);
}
@@ -1933,10 +1807,7 @@ rb_float_eql(VALUE x, VALUE y)
if (RB_FLOAT_TYPE_P(y)) {
double a = RFLOAT_VALUE(x);
double b = RFLOAT_VALUE(y);
-#if MSC_VERSION_BEFORE(1300)
- if (isnan(a) || isnan(b)) return Qfalse;
-#endif
- return RBOOL(a == b);
+ return RBOOL(a == b);
}
return Qfalse;
}
@@ -2170,36 +2041,78 @@ flo_ndigits(int argc, VALUE *argv)
}
/*
+ * :markup: markdown
+ *
* call-seq:
* floor(ndigits = 0) -> float or integer
*
- * Returns the largest number less than or equal to +self+ with
- * a precision of +ndigits+ decimal digits.
+ * Returns a float or integer that is a "floor" value for `self`,
+ * as specified by `ndigits`,
+ * which must be an
+ * [integer-convertible object](rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects).
*
- * When +ndigits+ is positive, returns a float with +ndigits+
- * digits after the decimal point (as available):
+ * When `self` is zero,
+ * returns a zero value:
+ * a float if `ndigits` is positive,
+ * an integer otherwise:
*
- * 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
+ * ```
+ * f = 0.0 # => 0.0
+ * f.floor(20) # => 0.0
+ * f.floor(0) # => 0
+ * f.floor(-20) # => 0
+ * ```
*
- * When +ndigits+ is non-positive, returns an integer with at least
- * <code>ndigits.abs</code> trailing zeros:
+ * When `self` is non-zero and `ndigits` is positive, returns a float with `ndigits`
+ * digits after the decimal point (as available):
*
- * f = 12345.6789
- * f.floor(0) # => 12345
- * f.floor(-3) # => 12000
- * f = -12345.6789
- * f.floor(0) # => -12346
- * f.floor(-3) # => -13000
+ * ```
+ * f = 12345.6789
+ * f.floor(1) # => 12345.6
+ * f.floor(3) # => 12345.678
+ * f.floor(30) # => 12345.6789
+ * f = -12345.6789
+ * f.floor(1) # => -12345.7
+ * f.floor(3) # => -12345.679
+ * f.floor(30) # => -12345.6789
+ * ```
+ *
+ * When `self` is non-zero and `ndigits` is non-positive,
+ * returns an integer value based on a computed granularity:
+ *
+ * - The granularity is `10 ** ndigits.abs`.
+ * - The returned value is the largest multiple of the granularity
+ * that is less than or equal to `self`.
+ *
+ * Examples with positive `self`:
+ *
+ * | ndigits | Granularity | 12345.6789.floor(ndigits) |
+ * |--------:|------------:|--------------------------:|
+ * | 0 | 1 | 12345 |
+ * | -1 | 10 | 12340 |
+ * | -2 | 100 | 12300 |
+ * | -3 | 1000 | 12000 |
+ * | -4 | 10000 | 10000 |
+ * | -5 | 100000 | 0 |
+ *
+ * Examples with negative `self`:
+ *
+ * | ndigits | Granularity | -12345.6789.floor(ndigits) |
+ * |--------:|------------:|---------------------------:|
+ * | 0 | 1 | -12346 |
+ * | -1 | 10 | -12350 |
+ * | -2 | 100 | -12400 |
+ * | -3 | 1000 | -13000 |
+ * | -4 | 10000 | -20000 |
+ * | -5 | 100000 | -100000 |
+ * | -6 | 1000000 | -1000000 |
*
* Note that the limited precision of floating-point arithmetic
* may lead to surprising results:
*
- * (0.3 / 0.1).floor #=> 2 (!)
+ * ```
+ * (0.3 / 0.1).floor # => 2 # Not 3, (because (0.3 / 0.1) # => 2.9999999999999996, not 3.0)
+ * ```
*
* Related: Float#ceil.
*
@@ -2213,36 +2126,78 @@ flo_floor(int argc, VALUE *argv, VALUE num)
}
/*
+ * :markup: markdown
+ *
* 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
- * <code>ndigits.abs</code> trailing zeros:
- *
- * f = 12345.6789
- * f.ceil(0) # => 12346
- * f.ceil(-3) # => 13000
- * f = -12345.6789
- * f.ceil(0) # => -12345
- * f.ceil(-3) # => -12000
+ * Returns a numeric that is a "ceiling" value for `self`,
+ * as specified by the given `ndigits`,
+ * which must be an
+ * [integer-convertible object](rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects).
+ *
+ * When `ndigits` is positive, returns a Float with `ndigits`
+ * decimal digits after the decimal point
+ * (as available, but no fewer than 1):
+ *
+ * ```
+ * f = 12345.6789
+ * f.ceil(1) # => 12345.7
+ * f.ceil(3) # => 12345.679
+ * f.ceil(30) # => 12345.6789
+ * f = -12345.6789
+ * f.ceil(1) # => -12345.6
+ * f.ceil(3) # => -12345.678
+ * f.ceil(30) # => -12345.6789
+ * f = 0.0
+ * f.ceil(1) # => 0.0
+ * f.ceil(100) # => 0.0
+ * ```
+ *
+ * When `ndigits` is non-positive,
+ * returns an Integer based on a computed granularity:
+ *
+ * - The granularity is `10 ** ndigits.abs`.
+ * - The returned value is the largest multiple of the granularity
+ * that is less than or equal to `self`.
+ *
+ * Examples with positive `self`:
+ *
+ * | ndigits | Granularity | 12345.6789.ceil(ndigits) |
+ * |--------:|------------:|-------------------------:|
+ * | 0 | 1 | 12346 |
+ * | -1 | 10 | 12350 |
+ * | -2 | 100 | 12400 |
+ * | -3 | 1000 | 13000 |
+ * | -4 | 10000 | 20000 |
+ * | -5 | 100000 | 100000 |
+ *
+ * Examples with negative `self`:
+ *
+ * | ndigits | Granularity | -12345.6789.ceil(ndigits) |
+ * |--------:|------------:|--------------------------:|
+ * | 0 | 1 | -12345 |
+ * | -1 | 10 | -12340 |
+ * | -2 | 100 | -12300 |
+ * | -3 | 1000 | -12000 |
+ * | -4 | 10000 | -10000 |
+ * | -5 | 100000 | 0 |
+ *
+ * When `self` is zero and `ndigits` is non-positive,
+ * returns Integer zero:
+ *
+ * ```
+ * 0.0.ceil(0) # => 0
+ * 0.0.ceil(-1) # => 0
+ * 0.0.ceil(-2) # => 0
+ * ```
*
* Note that the limited precision of floating-point arithmetic
* may lead to surprising results:
*
- * (2.1 / 0.7).ceil #=> 4 (!)
+ * ```
+ * (2.1 / 0.7).ceil #=> 4 # Not 3 (because 2.1 / 0.7 # => 3.0000000000000004, not 3.0)
+ * ```
*
* Related: Float#floor.
*
@@ -2378,11 +2333,7 @@ rb_int_round(VALUE num, int ndigits, enum ruby_num_rounding_mode mode)
static VALUE
rb_int_floor(VALUE num, int ndigits)
{
- VALUE f;
-
- if (int_round_zero_p(num, ndigits))
- return INT2FIX(0);
- f = int_pow(10, -ndigits);
+ VALUE f = int_pow(10, -ndigits);
if (FIXNUM_P(num) && FIXNUM_P(f)) {
SIGNED_VALUE x = FIX2LONG(num), y = FIX2LONG(f);
int neg = x < 0;
@@ -2391,21 +2342,19 @@ rb_int_floor(VALUE num, int ndigits)
if (neg) x = -x;
return LONG2NUM(x);
}
- if (RB_FLOAT_TYPE_P(f)) {
- /* then int_pow overflow */
- return INT2FIX(0);
+ else {
+ bool neg = int_neg_p(num);
+ if (neg) num = rb_int_minus(rb_int_plus(rb_int_uminus(num), f), INT2FIX(1));
+ num = rb_int_mul(rb_int_div(num, f), f);
+ if (neg) num = rb_int_uminus(num);
+ return num;
}
- return rb_int_minus(num, rb_int_modulo(num, f));
}
static VALUE
rb_int_ceil(VALUE num, int ndigits)
{
- VALUE f;
-
- if (int_round_zero_p(num, ndigits))
- return INT2FIX(0);
- f = int_pow(10, -ndigits);
+ VALUE f = int_pow(10, -ndigits);
if (FIXNUM_P(num) && FIXNUM_P(f)) {
SIGNED_VALUE x = FIX2LONG(num), y = FIX2LONG(f);
int neg = x < 0;
@@ -2415,11 +2364,16 @@ rb_int_ceil(VALUE num, int ndigits)
if (neg) x = -x;
return LONG2NUM(x);
}
- if (RB_FLOAT_TYPE_P(f)) {
- /* then int_pow overflow */
- return INT2FIX(0);
+ else {
+ bool neg = int_neg_p(num);
+ if (neg)
+ num = rb_int_uminus(num);
+ else
+ num = rb_int_plus(num, rb_int_minus(f, INT2FIX(1)));
+ num = rb_int_mul(rb_int_div(num, f), f);
+ if (neg) num = rb_int_uminus(num);
+ return num;
}
- return rb_int_plus(num, rb_int_minus(f, rb_int_modulo(num, f)));
}
VALUE
@@ -2656,13 +2610,16 @@ flo_truncate(int argc, VALUE *argv, VALUE num)
/*
* call-seq:
- * floor(digits = 0) -> integer or float
+ * floor(ndigits = 0) -> float or integer
*
- * Returns the largest number that is less than or equal to +self+ with
- * a precision of +digits+ decimal digits.
+ * Returns the largest float or integer that is less than or equal to +self+,
+ * as specified by the given +ndigits+,
+ * which must be an
+ * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
*
- * \Numeric implements this by converting +self+ to a Float and
- * invoking Float#floor.
+ * Equivalent to <tt>self.to_f.floor(ndigits)</tt>.
+ *
+ * Related: #ceil, Float#floor.
*/
static VALUE
@@ -2673,13 +2630,16 @@ num_floor(int argc, VALUE *argv, VALUE num)
/*
* call-seq:
- * ceil(digits = 0) -> integer or float
+ * ceil(ndigits = 0) -> float or integer
*
- * Returns the smallest number that is greater than or equal to +self+ with
- * a precision of +digits+ decimal digits.
+ * Returns the smallest float or integer that is greater than or equal to +self+,
+ * as specified by the given +ndigits+,
+ * which must be an
+ * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects].
*
- * \Numeric implements this by converting +self+ to a Float and
- * invoking Float#ceil.
+ * Equivalent to <tt>self.to_f.ceil(ndigits)</tt>.
+ *
+ * Related: #floor, Float#ceil.
*/
static VALUE
@@ -3472,6 +3432,232 @@ rb_num2ull(VALUE val)
#endif /* HAVE_LONG_LONG */
+// Conversion functions for unified 128-bit integer structures,
+// These work with or without native 128-bit integer support.
+
+#ifndef HAVE_UINT128_T
+// Helper function to build 128-bit value from bignum digits (fallback path).
+static inline void
+rb_uint128_from_bignum_digits_fallback(rb_uint128_t *result, BDIGIT *digits, size_t length)
+{
+ // Build the 128-bit value from bignum digits:
+ for (long i = length - 1; i >= 0; i--) {
+ // Shift both low and high parts:
+ uint64_t carry = result->parts.low >> (64 - (SIZEOF_BDIGIT * CHAR_BIT));
+ result->parts.low = (result->parts.low << (SIZEOF_BDIGIT * CHAR_BIT)) | digits[i];
+ result->parts.high = (result->parts.high << (SIZEOF_BDIGIT * CHAR_BIT)) | carry;
+ }
+}
+
+// Helper function to convert absolute value of negative bignum to two's complement.
+// Ruby stores negative bignums as absolute values, so we need to convert to two's complement.
+static inline void
+rb_uint128_twos_complement_negate(rb_uint128_t *value)
+{
+ if (value->parts.low == 0) {
+ value->parts.high = ~value->parts.high + 1;
+ }
+ else {
+ value->parts.low = ~value->parts.low + 1;
+ value->parts.high = ~value->parts.high + (value->parts.low == 0 ? 1 : 0);
+ }
+}
+#endif
+
+rb_uint128_t
+rb_numeric_to_uint128(VALUE x)
+{
+ rb_uint128_t result = {0};
+ if (RB_FIXNUM_P(x)) {
+ long value = RB_FIX2LONG(x);
+ if (value < 0) {
+ rb_raise(rb_eRangeError, "negative integer cannot be converted to unsigned 128-bit integer");
+ }
+#ifdef HAVE_UINT128_T
+ result.value = (uint128_t)value;
+#else
+ result.parts.low = (uint64_t)value;
+ result.parts.high = 0;
+#endif
+ return result;
+ }
+ else if (RB_BIGNUM_TYPE_P(x)) {
+ if (BIGNUM_NEGATIVE_P(x)) {
+ rb_raise(rb_eRangeError, "negative integer cannot be converted to unsigned 128-bit integer");
+ }
+ size_t length = BIGNUM_LEN(x);
+#ifdef HAVE_UINT128_T
+ if (length > roomof(SIZEOF_INT128_T, SIZEOF_BDIGIT)) {
+ rb_raise(rb_eRangeError, "bignum too big to convert into 'unsigned 128-bit integer'");
+ }
+ BDIGIT *digits = BIGNUM_DIGITS(x);
+ result.value = 0;
+ for (long i = length - 1; i >= 0; i--) {
+ result.value = (result.value << (SIZEOF_BDIGIT * CHAR_BIT)) | digits[i];
+ }
+#else
+ // Check if bignum fits in 128 bits (16 bytes)
+ if (length > roomof(16, SIZEOF_BDIGIT)) {
+ rb_raise(rb_eRangeError, "bignum too big to convert into 'unsigned 128-bit integer'");
+ }
+ BDIGIT *digits = BIGNUM_DIGITS(x);
+ rb_uint128_from_bignum_digits_fallback(&result, digits, length);
+#endif
+ return result;
+ }
+ else {
+ rb_raise(rb_eTypeError, "not an integer");
+ }
+}
+
+rb_int128_t
+rb_numeric_to_int128(VALUE x)
+{
+ rb_int128_t result = {0};
+ if (RB_FIXNUM_P(x)) {
+ long value = RB_FIX2LONG(x);
+#ifdef HAVE_UINT128_T
+ result.value = (int128_t)value;
+#else
+ if (value < 0) {
+ // Two's complement representation: for negative values, sign extend
+ // Convert to unsigned: for -1, we want all bits set
+ result.parts.low = (uint64_t)value; // This will be the two's complement representation
+ result.parts.high = UINT64_MAX; // Sign extend: all bits set for negative
+ }
+ else {
+ result.parts.low = (uint64_t)value;
+ result.parts.high = 0;
+ }
+#endif
+ return result;
+ }
+ else if (RB_BIGNUM_TYPE_P(x)) {
+ size_t length = BIGNUM_LEN(x);
+#ifdef HAVE_UINT128_T
+ if (length > roomof(SIZEOF_INT128_T, SIZEOF_BDIGIT)) {
+ rb_raise(rb_eRangeError, "bignum too big to convert into 'signed 128-bit integer'");
+ }
+ BDIGIT *digits = BIGNUM_DIGITS(x);
+ uint128_t unsigned_result = 0;
+ for (long i = length - 1; i >= 0; i--) {
+ unsigned_result = (unsigned_result << (SIZEOF_BDIGIT * CHAR_BIT)) | digits[i];
+ }
+ if (BIGNUM_NEGATIVE_P(x)) {
+ // Convert from two's complement
+ // Maximum negative value is 2^127
+ if (unsigned_result > ((uint128_t)1 << 127)) {
+ rb_raise(rb_eRangeError, "bignum too big to convert into 'signed 128-bit integer'");
+ }
+ result.value = -(int128_t)(unsigned_result - 1) - 1;
+ }
+ else {
+ // Maximum positive value is 2^127 - 1
+ if (unsigned_result > (((uint128_t)1 << 127) - 1)) {
+ rb_raise(rb_eRangeError, "bignum too big to convert into 'signed 128-bit integer'");
+ }
+ result.value = (int128_t)unsigned_result;
+ }
+#else
+ if (length > roomof(16, SIZEOF_BDIGIT)) {
+ rb_raise(rb_eRangeError, "bignum too big to convert into 'signed 128-bit integer'");
+ }
+ BDIGIT *digits = BIGNUM_DIGITS(x);
+ rb_uint128_t unsigned_result = {0};
+ rb_uint128_from_bignum_digits_fallback(&unsigned_result, digits, length);
+ if (BIGNUM_NEGATIVE_P(x)) {
+ // Check if value fits in signed 128-bit (max negative is 2^127)
+ uint64_t max_neg_high = (uint64_t)1 << 63;
+ if (unsigned_result.parts.high > max_neg_high || (unsigned_result.parts.high == max_neg_high && unsigned_result.parts.low > 0)) {
+ rb_raise(rb_eRangeError, "bignum too big to convert into 'signed 128-bit integer'");
+ }
+ // Convert from absolute value to two's complement (Ruby stores negative as absolute value)
+ rb_uint128_twos_complement_negate(&unsigned_result);
+ result.parts.low = unsigned_result.parts.low;
+ result.parts.high = (int64_t)unsigned_result.parts.high; // Sign extend
+ }
+ else {
+ // Check if value fits in signed 128-bit (max positive is 2^127 - 1)
+ // Max positive: high = 0x7FFFFFFFFFFFFFFF, low = 0xFFFFFFFFFFFFFFFF
+ uint64_t max_pos_high = ((uint64_t)1 << 63) - 1;
+ if (unsigned_result.parts.high > max_pos_high) {
+ rb_raise(rb_eRangeError, "bignum too big to convert into 'signed 128-bit integer'");
+ }
+ result.parts.low = unsigned_result.parts.low;
+ result.parts.high = unsigned_result.parts.high;
+ }
+#endif
+ return result;
+ }
+ else {
+ rb_raise(rb_eTypeError, "not an integer");
+ }
+}
+
+VALUE
+rb_uint128_to_numeric(rb_uint128_t n)
+{
+#ifdef HAVE_UINT128_T
+ if (n.value <= (uint128_t)RUBY_FIXNUM_MAX) {
+ return LONG2FIX((long)n.value);
+ }
+ return rb_uint128t2big(n.value);
+#else
+ // If high part is zero and low part fits in fixnum
+ if (n.parts.high == 0 && n.parts.low <= (uint64_t)RUBY_FIXNUM_MAX) {
+ return LONG2FIX((long)n.parts.low);
+ }
+ // Convert to bignum by building it from the two 64-bit parts
+ VALUE bignum = rb_ull2big(n.parts.low);
+ if (n.parts.high > 0) {
+ VALUE high_bignum = rb_ull2big(n.parts.high);
+ // Multiply high part by 2^64 and add to low part
+ VALUE shifted_value = rb_int_lshift(high_bignum, INT2FIX(64));
+ bignum = rb_int_plus(bignum, shifted_value);
+ }
+ return bignum;
+#endif
+}
+
+VALUE
+rb_int128_to_numeric(rb_int128_t n)
+{
+#ifdef HAVE_UINT128_T
+ if (FIXABLE(n.value)) {
+ return LONG2FIX((long)n.value);
+ }
+ return rb_int128t2big(n.value);
+#else
+ int64_t high = (int64_t)n.parts.high;
+ // If it's a small positive value that fits in fixnum
+ if (high == 0 && n.parts.low <= (uint64_t)RUBY_FIXNUM_MAX) {
+ return LONG2FIX((long)n.parts.low);
+ }
+ // Check if it's negative (high bit of high part is set)
+ if (high < 0) {
+ // Negative value - convert from two's complement to absolute value
+ rb_uint128_t unsigned_value = {0};
+ if (n.parts.low == 0) {
+ unsigned_value.parts.low = 0;
+ unsigned_value.parts.high = ~n.parts.high + 1;
+ }
+ else {
+ unsigned_value.parts.low = ~n.parts.low + 1;
+ unsigned_value.parts.high = ~n.parts.high + (unsigned_value.parts.low == 0 ? 1 : 0);
+ }
+ VALUE bignum = rb_uint128_to_numeric(unsigned_value);
+ return rb_int_uminus(bignum);
+ }
+ else {
+ // Positive value
+ union uint128_int128_conversion conversion = {
+ .int128 = n
+ };
+ return rb_uint128_to_numeric(conversion.uint128);
+ }
+#endif
+}
+
/********************************************************************
*
* Document-class: Integer
@@ -3484,14 +3670,14 @@ rb_num2ull(VALUE val)
*
* You can convert certain objects to Integers with:
*
- * - \Method #Integer.
+ * - Method #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:
+ * First, what's elsewhere. Class \Integer:
*
* - Inherits from
* {class Numeric}[rdoc-ref:Numeric@What-27s+Here]
@@ -3537,6 +3723,7 @@ rb_num2ull(VALUE val)
* - #>>: Returns the value of +self+ after a rightward bit-shift.
* - #[]: Returns a slice of bits from +self+.
* - #^: Returns the bitwise EXCLUSIVE OR of +self+ and the given value.
+ * - #|: Returns the bitwise 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+.
@@ -3556,7 +3743,6 @@ rb_num2ull(VALUE val)
* - #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.
- * - #|: Returns the bitwise OR of +self+ and the given value.
*
* === Other
*
@@ -3975,17 +4161,20 @@ rb_fix_plus(VALUE x, VALUE y)
/*
* call-seq:
- * self + numeric -> numeric_result
+ * self + other -> numeric
+ *
+ * Returns the sum of +self+ and +other+:
*
- * Performs addition:
+ * 1 + 1 # => 2
+ * 1 + -1 # => 0
+ * 1 + 0 # => 1
+ * 1 + -2 # => -1
+ * 1 + Complex(1, 0) # => (2+0i)
+ * 1 + Rational(1, 1) # => (2/1)
*
- * 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)
+ * For a computation involving Floats, the result may be inexact (see Float#+):
*
+ * 1 + 3.14 # => 4.140000000000001
*/
VALUE
@@ -4020,9 +4209,9 @@ fix_minus(VALUE x, VALUE y)
/*
* call-seq:
- * self - numeric -> numeric_result
+ * self - other -> numeric
*
- * Performs subtraction:
+ * Returns the difference of +self+ and +other+:
*
* 4 - 2 # => 2
* -4 - 2 # => -6
@@ -4076,16 +4265,17 @@ fix_mul(VALUE x, VALUE y)
/*
* call-seq:
- * self * numeric -> numeric_result
+ * self * other -> numeric
*
- * Performs multiplication:
+ * Returns the numeric product of +self+ and +other+:
*
* 4 * 2 # => 8
- * 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
@@ -4208,16 +4398,18 @@ fix_div(VALUE x, VALUE y)
/*
* call-seq:
- * self / numeric -> numeric_result
+ * self / other -> numeric
+ *
+ * Returns the quotient of +self+ and +other+.
*
- * Performs division; for integer +numeric+, truncates the result to an integer:
+ * For integer +other+, 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:
+ * For non-integer +other+, returns a non-integer result:
*
* 4 / 3.0 # => 1.3333333333333333
* 4 / Rational(3, 1) # => (4/3)
@@ -4294,9 +4486,9 @@ fix_mod(VALUE x, VALUE y)
/*
* call-seq:
- * self % other -> real_number
+ * self % other -> real_numeric
*
- * Returns +self+ modulo +other+ as a real number.
+ * Returns +self+ modulo +other+ as a real numeric (\Integer, \Float, or \Rational).
*
* For integer +n+ and real number +r+, these expressions are equivalent:
*
@@ -4445,9 +4637,9 @@ rb_int_divmod(VALUE x, VALUE y)
/*
* call-seq:
- * self ** numeric -> numeric_result
+ * self ** exponent -> numeric
*
- * Raises +self+ to the power of +numeric+:
+ * Returns +self+ raised to the power +exponent+:
*
* 2 ** 3 # => 8
* 2 ** -3 # => (1/8)
@@ -4568,17 +4760,47 @@ fix_pow(VALUE x, VALUE y)
/*
* 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)
+ * self ** exponent -> numeric
+ *
+ * Returns +self+ raised to the power +exponent+:
+ *
+ * # Result for non-negative Integer exponent is Integer.
+ * 2 ** 0 # => 1
+ * 2 ** 1 # => 2
+ * 2 ** 2 # => 4
+ * 2 ** 3 # => 8
+ * -2 ** 3 # => -8
+ * # Result for negative Integer exponent is Rational, not Float.
+ * 2 ** -3 # => (1/8)
+ * -2 ** -3 # => (-1/8)
+ *
+ * # Result for Float exponent is Float.
+ * 2 ** 0.0 # => 1.0
+ * 2 ** 1.0 # => 2.0
+ * 2 ** 2.0 # => 4.0
+ * 2 ** 3.0 # => 8.0
+ * -2 ** 3.0 # => -8.0
+ * 2 ** -3.0 # => 0.125
+ * -2 ** -3.0 # => -0.125
+ *
+ * # Result for non-negative Complex exponent is Complex with Integer parts.
+ * 2 ** Complex(0, 0) # => (1+0i)
+ * 2 ** Complex(1, 0) # => (2+0i)
+ * 2 ** Complex(2, 0) # => (4+0i)
+ * 2 ** Complex(3, 0) # => (8+0i)
+ * -2 ** Complex(3, 0) # => (-8+0i)
+ * # Result for negative Complex exponent is Complex with Rational parts.
+ * 2 ** Complex(-3, 0) # => ((1/8)+(0/1)*i)
+ * -2 ** Complex(-3, 0) # => ((-1/8)+(0/1)*i)
+ *
+ * # Result for Rational exponent is Rational.
+ * 2 ** Rational(0, 1) # => (1/1)
+ * 2 ** Rational(1, 1) # => (2/1)
+ * 2 ** Rational(2, 1) # => (4/1)
+ * 2 ** Rational(3, 1) # => (8/1)
+ * -2 ** Rational(3, 1) # => (-8/1)
+ * 2 ** Rational(-3, 1) # => (1/8)
+ * -2 ** Rational(-3, 1) # => (-1/8)
*
*/
VALUE
@@ -4631,7 +4853,7 @@ fix_equal(VALUE x, VALUE y)
* call-seq:
* self == other -> true or false
*
- * Returns +true+ if +self+ is numerically equal to +other+; +false+ otherwise.
+ * Returns whether +self+ is numerically equal to +other+:
*
* 1 == 2 #=> false
* 1 == 1.0 #=> true
@@ -4677,28 +4899,29 @@ fix_cmp(VALUE x, VALUE y)
/*
* call-seq:
- * self <=> other -> -1, 0, +1, or nil
+ * self <=> other -> -1, 0, 1, or nil
+ *
+ * Compares +self+ and +other+.
*
* Returns:
*
- * - -1, if +self+ is less than +other+.
- * - 0, if +self+ is equal to +other+.
- * - 1, if +self+ is greater then +other+.
+ * - +-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
+ * 1 <=> 0 # => 1
+ * 1 <=> 'foo' # => nil
*
- * This method is the basis for comparisons in module Comparable.
- *
+ * \Class \Integer includes module Comparable,
+ * each of whose methods uses Integer#<=> for comparison.
*/
VALUE
@@ -4736,7 +4959,8 @@ fix_gt(VALUE x, VALUE y)
* call-seq:
* self > other -> true or false
*
- * Returns +true+ if the value of +self+ is greater than that of +other+:
+ * Returns whether the value of +self+ is greater than the value of +other+;
+ * +other+ must be numeric, but may not be Complex:
*
* 1 > 0 # => true
* 1 > 1 # => false
@@ -4780,10 +5004,10 @@ fix_ge(VALUE x, VALUE y)
/*
* call-seq:
- * self >= real -> true or false
+ * self >= other -> true or false
*
- * Returns +true+ if the value of +self+ is greater than or equal to
- * that of +other+:
+ * Returns whether the value of +self+ is greater than or equal to the value of +other+;
+ * +other+ must be numeric, but may not be Complex:
*
* 1 >= 0 # => true
* 1 >= 1 # => true
@@ -4828,7 +5052,8 @@ fix_lt(VALUE x, VALUE y)
* call-seq:
* self < other -> true or false
*
- * Returns +true+ if the value of +self+ is less than that of +other+:
+ * Returns whether the value of +self+ is less than the value of +other+;
+ * +other+ must be numeric, but may not be Complex:
*
* 1 < 0 # => false
* 1 < 1 # => false
@@ -4836,8 +5061,6 @@ fix_lt(VALUE x, VALUE y)
* 1 < 0.5 # => false
* 1 < Rational(1, 2) # => false
*
- * Raises an exception if the comparison cannot be made.
- *
*/
static VALUE
@@ -4872,10 +5095,10 @@ fix_le(VALUE x, VALUE y)
/*
* call-seq:
- * self <= real -> true or false
+ * self <= other -> true or false
*
- * Returns +true+ if the value of +self+ is less than or equal to
- * that of +other+:
+ * Returns whether the value of +self+ is less than or equal to the value of +other+;
+ * +other+ must be numeric, but may not be Complex:
*
* 1 <= 0 # => false
* 1 <= 1 # => true
@@ -5060,8 +5283,8 @@ fix_xor(VALUE x, VALUE y)
*
*/
-static VALUE
-int_xor(VALUE x, VALUE y)
+VALUE
+rb_int_xor(VALUE x, VALUE y)
{
if (FIXNUM_P(x)) {
return fix_xor(x, y);
@@ -5234,9 +5457,22 @@ generate_mask(VALUE len)
}
static VALUE
+int_aref2(VALUE num, VALUE beg, VALUE len)
+{
+ if (RB_TYPE_P(num, T_BIGNUM)) {
+ return rb_big_aref2(num, beg, len);
+ }
+ else {
+ num = rb_int_rshift(num, beg);
+ VALUE mask = generate_mask(len);
+ return rb_int_and(num, mask);
+ }
+}
+
+static VALUE
int_aref1(VALUE num, VALUE arg)
{
- VALUE orig_num = num, beg, end;
+ VALUE beg, end;
int excl;
if (rb_range_values(arg, &beg, &end, &excl)) {
@@ -5256,22 +5492,19 @@ int_aref1(VALUE num, VALUE arg)
return INT2FIX(0);
}
}
- num = rb_int_rshift(num, beg);
int cmp = compare_indexes(beg, end);
if (!NIL_P(end) && cmp < 0) {
VALUE len = rb_int_minus(end, beg);
if (!excl) len = rb_int_plus(len, INT2FIX(1));
- VALUE mask = generate_mask(len);
- num = rb_int_and(num, mask);
+ return int_aref2(num, beg, len);
}
else if (cmp == 0) {
if (excl) return INT2FIX(0);
- num = orig_num;
arg = beg;
goto one_bit;
}
- return num;
+ return rb_int_rshift(num, beg);
}
one_bit:
@@ -5284,15 +5517,6 @@ one_bit:
return Qnil;
}
-static VALUE
-int_aref2(VALUE num, VALUE beg, VALUE len)
-{
- num = rb_int_rshift(num, beg);
- VALUE mask = generate_mask(len);
- num = rb_int_and(num, mask);
- return num;
-}
-
/*
* call-seq:
* self[offset] -> 0 or 1
@@ -5497,7 +5721,7 @@ rb_int_digits_bigbase(VALUE num, VALUE base)
}
bases = rb_ary_new();
- for (VALUE b = base; int_lt(b, num) == Qtrue; b = rb_int_mul(b, b)) {
+ for (VALUE b = base; int_le(b, num) == Qtrue; b = rb_int_mul(b, b)) {
rb_ary_push(bases, b);
}
digits = rb_ary_new_from_args(1, num);
@@ -5739,24 +5963,56 @@ int_round(int argc, VALUE* argv, VALUE num)
}
/*
+ * :markup: markdown
+ *
* call-seq:
* floor(ndigits = 0) -> integer
*
- * Returns the largest number less than or equal to +self+ with
- * a precision of +ndigits+ decimal digits.
+ * Returns an integer that is a "floor" value for `self`,
+ * as specified by the given `ndigits`,
+ * which must be an
+ * [integer-convertible object](rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects).
*
- * When +ndigits+ is negative, the returned value
- * has at least <tt>ndigits.abs</tt> trailing zeros:
+ * - When `self` is zero, returns zero (regardless of the value of `ndigits`):
*
- * 555.floor(-1) # => 550
- * 555.floor(-2) # => 500
- * -555.floor(-2) # => -600
- * 555.floor(-3) # => 0
+ * ```
+ * 0.floor(2) # => 0
+ * 0.floor(-2) # => 0
+ * ```
*
- * Returns +self+ when +ndigits+ is zero or positive.
+ * - When `self` is non-zero and `ndigits` is non-negative, returns `self`:
+ *
+ * ```
+ * 555.floor # => 555
+ * 555.floor(50) # => 555
+ * ```
+ *
+ * - When `self` is non-zero and `ndigits` is negative,
+ * returns a value based on a computed granularity:
+ *
+ * - The granularity is `10 ** ndigits.abs`.
+ * - The returned value is the largest multiple of the granularity
+ * that is less than or equal to `self`.
+ *
+ * Examples with positive `self`:
*
- * 555.floor # => 555
- * 555.floor(50) # => 555
+ * | ndigits | Granularity | 1234.floor(ndigits) |
+ * |--------:|------------:|--------------------:|
+ * | -1 | 10 | 1230 |
+ * | -2 | 100 | 1200 |
+ * | -3 | 1000 | 1000 |
+ * | -4 | 10000 | 0 |
+ * | -5 | 100000 | 0 |
+ *
+ * Examples with negative `self`:
+ *
+ * | ndigits | Granularity | -1234.floor(ndigits) |
+ * |--------:|------------:|---------------------:|
+ * | -1 | 10 | -1240 |
+ * | -2 | 100 | -1300 |
+ * | -3 | 1000 | -2000 |
+ * | -4 | 10000 | -10000 |
+ * | -5 | 100000 | -100000 |
*
* Related: Integer#ceil.
*
@@ -5776,27 +6032,58 @@ int_floor(int argc, VALUE* argv, VALUE num)
}
/*
+ * :markup: markdown
+ *
* call-seq:
* ceil(ndigits = 0) -> integer
*
- * Returns the smallest number greater than or equal to +self+ with
- * a precision of +ndigits+ decimal digits.
+ * Returns an integer that is a "ceiling" value for `self`,
+ * as specified by the given `ndigits`,
+ * which must be an
+ * [integer-convertible object](rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects).
*
- * When the precision is negative, the returned value is an integer
- * with at least <code>ndigits.abs</code> trailing zeros:
+ * - When `self` is zero, returns zero (regardless of the value of `ndigits`):
*
- * 555.ceil(-1) # => 560
- * 555.ceil(-2) # => 600
- * -555.ceil(-2) # => -500
- * 555.ceil(-3) # => 1000
+ * ```
+ * 0.ceil(2) # => 0
+ * 0.ceil(-2) # => 0
+ * ```
*
- * Returns +self+ when +ndigits+ is zero or positive.
+ * - When `self` is non-zero and `ndigits` is non-negative, returns `self`:
*
- * 555.ceil # => 555
- * 555.ceil(50) # => 555
+ * ```
+ * 555.ceil # => 555
+ * 555.ceil(50) # => 555
+ * ```
*
- * Related: Integer#floor.
+ * - When `self` is non-zero and `ndigits` is negative,
+ * returns a value based on a computed granularity:
+ *
+ * - The granularity is `10 ** ndigits.abs`.
+ * - The returned value is the smallest multiple of the granularity
+ * that is greater than or equal to `self`.
+ *
+ * Examples with positive `self`:
*
+ * | ndigits | Granularity | 1234.ceil(ndigits) |
+ * |--------:|------------:|-------------------:|
+ * | -1 | 10 | 1240 |
+ * | -2 | 100 | 1300 |
+ * | -3 | 1000 | 2000 |
+ * | -4 | 10000 | 10000 |
+ * | -5 | 100000 | 100000 |
+ *
+ * Examples with negative `self`:
+ *
+ * | ndigits | Granularity | -1234.ceil(ndigits) |
+ * |--------:|------------:|--------------------:|
+ * | -1 | 10 | -1230 |
+ * | -2 | 100 | -1200 |
+ * | -3 | 1000 | -1000 |
+ * | -4 | 10000 | 0 |
+ * | -5 | 100000 | 0 |
+ *
+ * Related: Integer#floor.
*/
static VALUE
@@ -5860,7 +6147,11 @@ prefix##_isqrt(argtype n) \
while ((t = n/x) < (argtype)x) x = (rettype)((x + t) >> 1); \
return x; \
} \
- return (rettype)sqrt(argtype##_TO_DOUBLE(n)); \
+ rettype x = (rettype)sqrt(argtype##_TO_DOUBLE(n)); \
+ /* libm sqrt may returns a larger approximation than actual. */ \
+ /* Our isqrt always returns a smaller approximation. */ \
+ if (x * x > n) x--; \
+ return x; \
}
#if SIZEOF_LONG*CHAR_BIT > DBL_MANT_DIG
@@ -6072,7 +6363,7 @@ int_s_try_convert(VALUE self, VALUE num)
*
* == What's Here
*
- * First, what's elsewhere. \Class \Numeric:
+ * First, what's elsewhere. Class \Numeric:
*
* - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
* - Includes {module Comparable}[rdoc-ref:Comparable@What-27s+Here].
@@ -6171,10 +6462,8 @@ Init_Numeric(void)
rb_include_module(rb_cNumeric, rb_mComparable);
rb_define_method(rb_cNumeric, "coerce", num_coerce, 1);
rb_define_method(rb_cNumeric, "clone", num_clone, -1);
- rb_define_method(rb_cNumeric, "dup", num_dup, 0);
rb_define_method(rb_cNumeric, "i", num_imaginary, 0);
- rb_define_method(rb_cNumeric, "+@", num_uplus, 0);
rb_define_method(rb_cNumeric, "-@", num_uminus, 0);
rb_define_method(rb_cNumeric, "<=>", num_cmp, 1);
rb_define_method(rb_cNumeric, "eql?", num_eql, 1);
@@ -6246,7 +6535,7 @@ Init_Numeric(void)
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);
+ rb_define_method(rb_cInteger, "^", rb_int_xor, 1);
rb_define_method(rb_cInteger, "[]", int_aref, -1);
rb_define_method(rb_cInteger, "<<", rb_int_lshift, 1);
@@ -6334,7 +6623,7 @@ Init_Numeric(void)
*
* If the platform supports denormalized numbers,
* there are numbers between zero and Float::MIN.
- * 0.0.next_float returns the smallest positive floating point number
+ * +0.0.next_float+ returns the smallest positive floating point number
* including denormalized numbers.
*/
rb_define_const(rb_cFloat, "MIN", DBL2NUM(DBL_MIN));
diff --git a/numeric.rb b/numeric.rb
index 4dc406fd23..306561943d 100644
--- a/numeric.rb
+++ b/numeric.rb
@@ -1,4 +1,14 @@
class Numeric
+ # call-seq:
+ # dup -> self
+ #
+ # Returns +self+.
+ #
+ # Related: Numeric#clone.
+ #
+ def dup
+ self
+ end
# call-seq:
# real? -> true or false
@@ -70,13 +80,27 @@ class Numeric
end
alias conj conjugate
+
+ # call-seq:
+ # +self -> self
+ #
+ # Returns +self+.
+ #
+ def +@
+ self
+ end
end
class Integer
# call-seq:
- # -int -> integer
+ # -self -> integer
+ #
+ # Returns +self+, negated:
+ #
+ # -1 # => -1
+ # -(-1) # => 1
+ # -0 # => 0
#
- # Returns +self+, negated.
def -@
Primitive.attr! :leaf
Primitive.cexpr! 'rb_int_uminus(self)'
@@ -302,6 +326,29 @@ class Integer
def denominator
1
end
+
+ with_jit do
+ if Primitive.rb_builtin_basic_definition_p(:downto)
+ undef :downto
+
+ def downto(to) # :nodoc:
+ Primitive.attr! :inline_block, :c_trace
+
+ # When no block is given, return an Enumerator that enumerates from `self` to `to`.
+ # Not using `block_given?` and `to_enum` to keep them unaffected by redefinitions.
+ unless defined?(yield)
+ return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 1, &to, int_downto_size)'
+ end
+
+ from = self
+ while from >= to
+ yield from
+ from = from.pred
+ end
+ self
+ end
+ end
+ end
end
class Float
@@ -328,15 +375,16 @@ class Float
Primitive.cexpr! 'rb_float_abs(self)'
end
- def magnitude
- Primitive.attr! :leaf
- Primitive.cexpr! 'rb_float_abs(self)'
- end
+ alias magnitude abs
# call-seq:
- # -float -> float
+ # -self -> float
+ #
+ # Returns +self+, negated:
#
- # Returns +self+, negated.
+ # -3.14 # => -3.14
+ # -(-3.14) # => 3.14
+ # -0.0 # => -0.0
#
def -@
Primitive.attr! :leaf
diff --git a/object.c b/object.c
index 0a8ce4dc0f..75186a30c6 100644
--- a/object.c
+++ b/object.c
@@ -46,14 +46,9 @@
/* Flags of RObject
*
- * 1: ROBJECT_EMBED
- * The object has its instance variables embedded (the array of
- * instance variables directly follow the object, rather than being
- * on a separately allocated buffer).
- * if !SHAPE_IN_BASIC_FLAGS
- * 4-19: SHAPE_FLAG_MASK
- * Shape ID for the object.
- * endif
+ * 4: ROBJECT_HEAP
+ * The object has its instance variables in a separately allocated buffer.
+ * This can be either a flat buffer of reference, or an st_table for complex objects.
*/
/*!
@@ -87,6 +82,7 @@ static VALUE rb_cFalseClass_to_s;
#define id_init_dup idInitialize_dup
#define id_const_missing idConst_missing
#define id_to_f idTo_f
+static ID id_instance_variables_to_inspect;
#define CLASS_OR_MODULE_P(obj) \
(!SPECIAL_CONST_P(obj) && \
@@ -95,9 +91,9 @@ static VALUE rb_cFalseClass_to_s;
/*! \endcond */
size_t
-rb_obj_embedded_size(uint32_t numiv)
+rb_obj_embedded_size(uint32_t fields_count)
{
- return offsetof(struct RObject, as.ary) + (sizeof(VALUE) * numiv);
+ return offsetof(struct RObject, as.ary) + (sizeof(VALUE) * fields_count);
}
VALUE
@@ -121,28 +117,29 @@ rb_obj_reveal(VALUE obj, VALUE klass)
VALUE
rb_class_allocate_instance(VALUE klass)
{
- uint32_t index_tbl_num_entries = RCLASS_EXT(klass)->max_iv_count;
+ uint32_t index_tbl_num_entries = RCLASS_MAX_IV_COUNT(klass);
size_t size = rb_obj_embedded_size(index_tbl_num_entries);
if (!rb_gc_size_allocatable_p(size)) {
size = sizeof(struct RObject);
}
- NEWOBJ_OF(o, struct RObject, klass,
- T_OBJECT | ROBJECT_EMBED | (RGENGC_WB_PROTECTED_OBJECT ? FL_WB_PROTECTED : 0), size, 0);
+ // There might be a NEWOBJ tracepoint callback, and it may set fields.
+ // So the shape must be passed to `NEWOBJ_OF`.
+ VALUE flags = T_OBJECT | (RGENGC_WB_PROTECTED_OBJECT ? FL_WB_PROTECTED : 0);
+ NEWOBJ_OF_WITH_SHAPE(o, struct RObject, klass, flags, rb_shape_root(rb_gc_heap_id_for_size(size)), size, 0);
VALUE obj = (VALUE)o;
- RUBY_ASSERT(rb_shape_get_shape(obj)->type == SHAPE_ROOT);
-
- // Set the shape to the specific T_OBJECT shape.
- ROBJECT_SET_SHAPE_ID(obj, (shape_id_t)(rb_gc_size_pool_id_for_size(size) + FIRST_T_OBJECT_SHAPE_ID));
-
#if RUBY_DEBUG
- RUBY_ASSERT(!rb_shape_obj_too_complex(obj));
- VALUE *ptr = ROBJECT_IVPTR(obj);
- for (size_t i = 0; i < ROBJECT_IV_CAPACITY(obj); i++) {
+ RUBY_ASSERT(!rb_shape_obj_too_complex_p(obj));
+ VALUE *ptr = ROBJECT_FIELDS(obj);
+ size_t fields_count = RSHAPE_LEN(RBASIC_SHAPE_ID(obj));
+ for (size_t i = fields_count; i < ROBJECT_FIELDS_CAPACITY(obj); i++) {
ptr[i] = Qundef;
}
+ if (rb_obj_class(obj) != rb_class_real(klass)) {
+ rb_bug("Expected rb_class_allocate_instance to set the class correctly");
+ }
#endif
return obj;
@@ -151,7 +148,7 @@ rb_class_allocate_instance(VALUE klass)
VALUE
rb_obj_setup(VALUE obj, VALUE klass, VALUE type)
{
- VALUE ignored_flags = RUBY_FL_PROMOTED | RUBY_FL_SEEN_OBJ_ID;
+ VALUE ignored_flags = RUBY_FL_PROMOTED;
RBASIC(obj)->flags = (type & ~ignored_flags) | (RBASIC(obj)->flags & ignored_flags);
RBASIC_SET_CLASS(obj, klass);
return obj;
@@ -165,7 +162,7 @@ rb_obj_setup(VALUE obj, VALUE klass, VALUE type)
*
* Returns +true+ or +false+.
*
- * Like Object#==, if +object+ is an instance of Object
+ * Like Object#==, if +other+ is an instance of \Object
* (and not an instance of one of its many subclasses).
*
* This method is commonly overridden by those subclasses,
@@ -203,14 +200,18 @@ rb_eql(VALUE obj1, VALUE obj2)
/**
* call-seq:
- * obj == other -> true or false
- * obj.equal?(other) -> true or false
- * obj.eql?(other) -> true or false
+ * self == other -> true or false
+ * equal?(other) -> true or false
+ * eql?(other) -> true or false
+ *
+ * Returns whether +self+ and +other+ are the same object:
*
- * Equality --- At the Object level, #== returns <code>true</code>
- * only if +obj+ and +other+ are the same object. Typically, this
- * method is overridden in descendant classes to provide
- * class-specific meaning.
+ * object = Object.new
+ * object == object # => true
+ * object == Object.new # => false
+ *
+ * Here in class \Object, #==, #equal?, and #eql? are the same method.
+ * A subclass may override #== to provide class-specific meaning.
*
* Unlike #==, the #equal? method should never be overridden by
* subclasses as it is used to determine object identity (that is,
@@ -283,12 +284,32 @@ rb_obj_not_equal(VALUE obj1, VALUE obj2)
return rb_obj_not(result);
}
+static inline VALUE
+fake_class_p(VALUE klass)
+{
+ RUBY_ASSERT(klass);
+ RUBY_ASSERT(RB_TYPE_P(klass, T_CLASS) || RB_TYPE_P(klass, T_MODULE) || RB_TYPE_P(klass, T_ICLASS));
+ STATIC_ASSERT(t_iclass_overlap_t_class, !(T_CLASS & T_ICLASS));
+ STATIC_ASSERT(t_iclass_overlap_t_module, !(T_MODULE & T_ICLASS));
+
+ return FL_TEST_RAW(klass, T_ICLASS | FL_SINGLETON);
+}
+
+static inline VALUE
+class_real(VALUE cl)
+{
+ RUBY_ASSERT(cl);
+ while (RB_UNLIKELY(fake_class_p(cl))) {
+ cl = RCLASS_SUPER(cl);
+ }
+ return cl;
+}
+
VALUE
rb_class_real(VALUE cl)
{
- while (cl &&
- (RCLASS_SINGLETON_P(cl) || BUILTIN_TYPE(cl) == T_ICLASS)) {
- cl = RCLASS_SUPER(cl);
+ if (cl) {
+ cl = class_real(cl);
}
return cl;
}
@@ -296,7 +317,17 @@ rb_class_real(VALUE cl)
VALUE
rb_obj_class(VALUE obj)
{
- return rb_class_real(CLASS_OF(obj));
+ VALUE cl = CLASS_OF(obj);
+ if (cl) {
+ cl = class_real(cl);
+ }
+ return cl;
+}
+
+static inline VALUE
+rb_obj_class_must(VALUE obj)
+{
+ return class_real(CLASS_OF(obj));
}
/*
@@ -327,64 +358,46 @@ void
rb_obj_copy_ivar(VALUE dest, VALUE obj)
{
RUBY_ASSERT(!RB_TYPE_P(obj, T_CLASS) && !RB_TYPE_P(obj, T_MODULE));
-
RUBY_ASSERT(BUILTIN_TYPE(dest) == BUILTIN_TYPE(obj));
- rb_shape_t * src_shape = rb_shape_get_shape(obj);
-
- if (rb_shape_obj_too_complex(obj)) {
- // obj is TOO_COMPLEX so we can copy its iv_hash
- st_table *table = st_copy(ROBJECT_IV_HASH(obj));
- rb_obj_convert_to_too_complex(dest, table);
+ unsigned long src_num_ivs = rb_ivar_count(obj);
+ if (!src_num_ivs) {
return;
}
- uint32_t src_num_ivs = RBASIC_IV_COUNT(obj);
- rb_shape_t * shape_to_set_on_dest = src_shape;
- VALUE * src_buf;
- VALUE * dest_buf;
+ shape_id_t src_shape_id = RBASIC_SHAPE_ID(obj);
- if (!src_num_ivs) {
+ if (rb_shape_too_complex_p(src_shape_id)) {
+ rb_shape_copy_complex_ivars(dest, obj, src_shape_id, ROBJECT_FIELDS_HASH(obj));
return;
}
- // The copy should be mutable, so we don't want the frozen shape
- if (rb_shape_frozen_shape_p(src_shape)) {
- shape_to_set_on_dest = rb_shape_get_parent(src_shape);
- }
-
- src_buf = ROBJECT_IVPTR(obj);
- dest_buf = ROBJECT_IVPTR(dest);
-
- rb_shape_t * initial_shape = rb_shape_get_shape(dest);
-
- if (initial_shape->size_pool_index != src_shape->size_pool_index) {
- RUBY_ASSERT(initial_shape->type == SHAPE_T_OBJECT);
+ shape_id_t initial_shape_id = RBASIC_SHAPE_ID(dest);
+ RUBY_ASSERT(RSHAPE_TYPE_P(initial_shape_id, SHAPE_ROOT));
- shape_to_set_on_dest = rb_shape_rebuild_shape(initial_shape, src_shape);
- if (UNLIKELY(rb_shape_id(shape_to_set_on_dest) == OBJ_TOO_COMPLEX_SHAPE_ID)) {
- st_table * table = rb_st_init_numtable_with_size(src_num_ivs);
- rb_obj_copy_ivs_to_hash_table(obj, table);
- rb_obj_convert_to_too_complex(dest, table);
+ shape_id_t dest_shape_id = rb_shape_rebuild(initial_shape_id, src_shape_id);
+ if (UNLIKELY(rb_shape_too_complex_p(dest_shape_id))) {
+ st_table *table = rb_st_init_numtable_with_size(src_num_ivs);
+ rb_obj_copy_ivs_to_hash_table(obj, table);
+ rb_obj_init_too_complex(dest, table);
- return;
- }
+ return;
}
- RUBY_ASSERT(src_num_ivs <= shape_to_set_on_dest->capacity || rb_shape_id(shape_to_set_on_dest) == OBJ_TOO_COMPLEX_SHAPE_ID);
- if (initial_shape->capacity < shape_to_set_on_dest->capacity) {
- rb_ensure_iv_list_size(dest, initial_shape->capacity, shape_to_set_on_dest->capacity);
- dest_buf = ROBJECT_IVPTR(dest);
- }
+ VALUE *src_buf = ROBJECT_FIELDS(obj);
+ VALUE *dest_buf = ROBJECT_FIELDS(dest);
- MEMCPY(dest_buf, src_buf, VALUE, src_num_ivs);
+ attr_index_t initial_capa = RSHAPE_CAPACITY(initial_shape_id);
+ attr_index_t dest_capa = RSHAPE_CAPACITY(dest_shape_id);
- // Fire write barriers
- for (uint32_t i = 0; i < src_num_ivs; i++) {
- RB_OBJ_WRITTEN(dest, Qundef, dest_buf[i]);
+ RUBY_ASSERT(src_num_ivs <= dest_capa);
+ if (initial_capa < dest_capa) {
+ rb_ensure_iv_list_size(dest, 0, dest_capa);
+ dest_buf = ROBJECT_FIELDS(dest);
}
- rb_shape_set_shape(dest, shape_to_set_on_dest);
+ rb_shape_copy_fields(dest, dest_buf, dest_shape_id, src_buf, src_shape_id);
+ RBASIC_SET_SHAPE_ID(dest, dest_shape_id);
}
static void
@@ -393,14 +406,25 @@ init_copy(VALUE dest, VALUE obj)
if (OBJ_FROZEN(dest)) {
rb_raise(rb_eTypeError, "[bug] frozen object (%s) allocated", rb_obj_classname(dest));
}
- RBASIC(dest)->flags &= ~(T_MASK|FL_EXIVAR);
+ RBASIC(dest)->flags &= ~T_MASK;
// Copies the shape id from obj to dest
- RBASIC(dest)->flags |= RBASIC(obj)->flags & (T_MASK|FL_EXIVAR);
- rb_gc_copy_attributes(dest, obj);
- rb_copy_generic_ivar(dest, obj);
- if (RB_TYPE_P(obj, T_OBJECT)) {
+ RBASIC(dest)->flags |= RBASIC(obj)->flags & T_MASK;
+ switch (BUILTIN_TYPE(obj)) {
+ case T_IMEMO:
+ rb_bug("Unreachable");
+ break;
+ case T_CLASS:
+ case T_MODULE:
+ rb_mod_init_copy(dest, obj);
+ break;
+ case T_OBJECT:
rb_obj_copy_ivar(dest, obj);
+ break;
+ default:
+ rb_copy_generic_ivar(dest, obj);
+ break;
}
+ rb_gc_copy_attributes(dest, obj);
}
static VALUE immutable_obj_clone(VALUE obj, VALUE kwfreeze);
@@ -500,17 +524,14 @@ rb_obj_clone_setup(VALUE obj, VALUE clone, VALUE kwfreeze)
case Qnil:
rb_funcall(clone, id_init_clone, 1, obj);
RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE;
- if (CHILLED_STRING_P(obj)) {
- STR_CHILL_RAW(clone);
+
+ if (RB_TYPE_P(obj, T_STRING)) {
+ FL_SET_RAW(clone, FL_TEST_RAW(obj, STR_CHILLED));
}
- else if (RB_OBJ_FROZEN(obj)) {
- rb_shape_t * next_shape = rb_shape_transition_shape_frozen(clone);
- if (!rb_shape_obj_too_complex(clone) && next_shape->type == SHAPE_OBJ_TOO_COMPLEX) {
- rb_evict_ivars_to_hash(clone);
- }
- else {
- rb_shape_set_shape(clone, next_shape);
- }
+
+ if (RB_OBJ_FROZEN(obj)) {
+ shape_id_t next_shape_id = rb_shape_transition_frozen(clone);
+ RBASIC_SET_SHAPE_ID(clone, next_shape_id);
}
break;
case Qtrue: {
@@ -525,16 +546,7 @@ rb_obj_clone_setup(VALUE obj, VALUE clone, VALUE kwfreeze)
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;
- rb_shape_t * next_shape = rb_shape_transition_shape_frozen(clone);
- // If we're out of shapes, but we want to freeze, then we need to
- // evacuate this clone to a hash
- if (!rb_shape_obj_too_complex(clone) && next_shape->type == SHAPE_OBJ_TOO_COMPLEX) {
- rb_evict_ivars_to_hash(clone);
- }
- else {
- rb_shape_set_shape(clone, next_shape);
- }
+ OBJ_FREEZE(clone);
break;
}
case Qfalse: {
@@ -753,11 +765,17 @@ rb_inspect(VALUE obj)
static int
inspect_i(ID id, VALUE value, st_data_t a)
{
- VALUE str = (VALUE)a;
+ VALUE *args = (VALUE *)a, str = args[0], ivars = args[1];
/* need not to show internal data */
if (CLASS_OF(value) == 0) return ST_CONTINUE;
if (!rb_is_instance_id(id)) return ST_CONTINUE;
+ if (!NIL_P(ivars)) {
+ VALUE name = ID2SYM(id);
+ for (long i = 0; RARRAY_AREF(ivars, i) != name; ) {
+ if (++i >= RARRAY_LEN(ivars)) return ST_CONTINUE;
+ }
+ }
if (RSTRING_PTR(str)[0] == '-') { /* first element */
RSTRING_PTR(str)[0] = '#';
rb_str_cat2(str, " ");
@@ -772,13 +790,15 @@ inspect_i(ID id, VALUE value, st_data_t a)
}
static VALUE
-inspect_obj(VALUE obj, VALUE str, int recur)
+inspect_obj(VALUE obj, VALUE a, int recur)
{
+ VALUE *args = (VALUE *)a, str = args[0];
+
if (recur) {
rb_str_cat2(str, " ...");
}
else {
- rb_ivar_foreach(obj, inspect_i, str);
+ rb_ivar_foreach(obj, inspect_i, a);
}
rb_str_cat2(str, ">");
RSTRING_PTR(str)[0] = '#';
@@ -811,23 +831,67 @@ inspect_obj(VALUE obj, VALUE str, int recur)
* end
* end
* Bar.new.inspect #=> "#<Bar:0x0300c868 @bar=1>"
+ *
+ * If _obj_ responds to +instance_variables_to_inspect+, then only
+ * the instance variables listed in the returned array will be included
+ * in the inspect string.
+ *
+ *
+ * class DatabaseConfig
+ * def initialize(host, user, password)
+ * @host = host
+ * @user = user
+ * @password = password
+ * end
+ *
+ * private
+ * def instance_variables_to_inspect = [:@host, :@user]
+ * end
+ *
+ * conf = DatabaseConfig.new("localhost", "root", "hunter2")
+ * conf.inspect #=> #<DatabaseConfig:0x0000000104def350 @host="localhost", @user="root">
*/
static VALUE
rb_obj_inspect(VALUE obj)
{
- if (rb_ivar_count(obj) > 0) {
- VALUE str;
- VALUE c = rb_class_name(CLASS_OF(obj));
+ VALUE ivars = rb_check_funcall(obj, id_instance_variables_to_inspect, 0, 0);
+ st_index_t n = 0;
+ if (UNDEF_P(ivars) || NIL_P(ivars)) {
+ n = rb_ivar_count(obj);
+ ivars = Qnil;
+ }
+ else if (RB_TYPE_P(ivars, T_ARRAY)) {
+ n = RARRAY_LEN(ivars);
+ }
+ else {
+ rb_raise(
+ rb_eTypeError,
+ "Expected #instance_variables_to_inspect to return an Array or nil, but it returned %"PRIsVALUE,
+ rb_obj_class(ivars)
+ );
+ }
- str = rb_sprintf("-<%"PRIsVALUE":%p", c, (void*)obj);
- return rb_exec_recursive(inspect_obj, obj, str);
+ if (n > 0) {
+ VALUE c = rb_class_name(CLASS_OF(obj));
+ VALUE args[2] = {
+ rb_sprintf("-<%"PRIsVALUE":%p", c, (void*)obj),
+ ivars
+ };
+ return rb_exec_recursive(inspect_obj, obj, (VALUE)args);
}
else {
return rb_any_to_s(obj);
}
}
+/* :nodoc: */
+static VALUE
+rb_obj_instance_variables_to_inspect(VALUE obj)
+{
+ return Qnil;
+}
+
static VALUE
class_or_module_required(VALUE c)
{
@@ -1191,6 +1255,30 @@ rb_class_search_ancestor(VALUE cl, VALUE c)
*
* Added :FOO
*
+ * If we define a class using the <tt>class</tt> keyword, <tt>const_added</tt>
+ * runs before <tt>inherited</tt>:
+ *
+ * module M
+ * def self.const_added(const_name)
+ * super
+ * p :const_added
+ * end
+ *
+ * parent = Class.new do
+ * def self.inherited(subclass)
+ * super
+ * p :inherited
+ * end
+ * end
+ *
+ * class Child < parent
+ * end
+ * end
+ *
+ * <em>produces:</em>
+ *
+ * :const_added
+ * :inherited
*/
#define rb_obj_mod_const_added rb_obj_dummy1
@@ -1355,6 +1443,10 @@ rb_obj_frozen_p(VALUE obj)
* - #to_r
* - #to_s
*
+ * While +nil+ doesn't have an explicitly defined #to_hash method,
+ * it can be used in <code>**</code> unpacking, not adding any
+ * keyword arguments.
+ *
* Another method provides inspection:
*
* - #inspect
@@ -1678,21 +1770,33 @@ rb_obj_not_match(VALUE obj1, VALUE obj2)
/*
* call-seq:
- * obj <=> other -> 0 or nil
+ * self <=> other -> 0 or nil
+ *
+ * Compares +self+ and +other+.
+ *
+ * Returns:
+ *
+ * - +0+, if +self+ and +other+ are the same object,
+ * or if <tt>self == other</tt>.
+ * - +nil+, otherwise.
*
- * Returns 0 if +obj+ and +other+ are the same object
- * or <code>obj == other</code>, otherwise nil.
+ * Examples:
+ *
+ * o = Object.new
+ * o <=> o # => 0
+ * o <=> o.dup # => nil
+ *
+ * A class that includes module Comparable
+ * should override this method by defining an instance method that:
*
- * The #<=> is used by various methods to compare objects, for example
- * Enumerable#sort, Enumerable#max etc.
+ * - Take one argument, +other+.
+ * - Returns:
*
- * Your implementation of #<=> should return one of the following values: -1, 0,
- * 1 or nil. -1 means self is smaller than other. 0 means self is equal to other.
- * 1 means self is bigger than other. Nil means the two values could not be
- * compared.
+ * - +-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.
*
- * When you define #<=>, you can include Comparable to gain the
- * methods #<=, #<, #==, #>=, #> and #between?.
*/
static VALUE
rb_obj_cmp(VALUE obj1, VALUE obj2)
@@ -1792,11 +1896,12 @@ rb_mod_freeze(VALUE mod)
/*
* call-seq:
- * mod === obj -> true or false
+ * self === other -> true or false
*
- * Case Equality---Returns <code>true</code> if <i>obj</i> is an
- * instance of <i>mod</i> or an instance of one of <i>mod</i>'s descendants.
- * Of limited use for modules, but can be used in <code>case</code> statements
+ * Returns whether +other+ is an instance of +self+,
+ * or is an instance of a subclass of +self+.
+ *
+ * Of limited use for modules, but can be used in +case+ statements
* to classify objects by class.
*/
@@ -1810,11 +1915,24 @@ rb_mod_eqq(VALUE mod, VALUE arg)
* call-seq:
* mod <= other -> true, false, or nil
*
- * Returns true if <i>mod</i> is a subclass of <i>other</i> or
- * is the same as <i>other</i>. Returns
- * <code>nil</code> if there's no relationship between the two.
- * (Think of the relationship in terms of the class definition:
- * "class A < B" implies "A < B".)
+ * Returns +true+ if +self+ is a descendant of +other+
+ * (+self+ is a subclass of +other+ or +self+ includes +other+) or
+ * if +self+ is the same as +other+:
+ *
+ * Float <= Numeric # => true
+ * Array <= Enumerable # => true
+ * Float <= Float # => true
+ *
+ * Returns +false+ if +self+ is an ancestor of +other+
+ * (+self+ is a superclass of +other+ or +self+ is included in +other+):
+ *
+ * Numeric <= Float # => false
+ * Enumerable <= Array # => false
+ *
+ * Returns +nil+ if there is no relationship between the two:
+ *
+ * Float <= Hash # => nil
+ * Enumerable <= String # => nil
*/
VALUE
@@ -1860,14 +1978,26 @@ rb_class_inherited_p(VALUE mod, VALUE arg)
/*
* call-seq:
- * mod < other -> true, false, or nil
+ * self < other -> true, false, or nil
+ *
+ * Returns +true+ if +self+ is a descendant of +other+
+ * (+self+ is a subclass of +other+ or +self+ includes +other+):
*
- * Returns true if <i>mod</i> is a subclass of <i>other</i>. Returns
- * <code>false</code> if <i>mod</i> is the same as <i>other</i>
- * or <i>mod</i> is an ancestor of <i>other</i>.
- * Returns <code>nil</code> if there's no relationship between the two.
- * (Think of the relationship in terms of the class definition:
- * "class A < B" implies "A < B".)
+ * Float < Numeric # => true
+ * Array < Enumerable # => true
+ *
+ * Returns +false+ if +self+ is an ancestor of +other+
+ * (+self+ is a superclass of +other+ or +self+ is included in +other+) or
+ * if +self+ is the same as +other+:
+ *
+ * Numeric < Float # => false
+ * Enumerable < Array # => false
+ * Float < Float # => false
+ *
+ * Returns +nil+ if there is no relationship between the two:
+ *
+ * Float < Hash # => nil
+ * Enumerable < String # => nil
*
*/
@@ -1883,11 +2013,24 @@ rb_mod_lt(VALUE mod, VALUE arg)
* call-seq:
* mod >= other -> true, false, or nil
*
- * Returns true if <i>mod</i> is an ancestor of <i>other</i>, or the
- * two modules are the same. Returns
- * <code>nil</code> if there's no relationship between the two.
- * (Think of the relationship in terms of the class definition:
- * "class A < B" implies "B > A".)
+ * Returns +true+ if +self+ is an ancestor of +other+
+ * (+self+ is a superclass of +other+ or +self+ is included in +other+) or
+ * if +self+ is the same as +other+:
+ *
+ * Numeric >= Float # => true
+ * Enumerable >= Array # => true
+ * Float >= Float # => true
+ *
+ * Returns +false+ if +self+ is a descendant of +other+
+ * (+self+ is a subclass of +other+ or +self+ includes +other+):
+ *
+ * Float >= Numeric # => false
+ * Array >= Enumerable # => false
+ *
+ * Returns +nil+ if there is no relationship between the two:
+ *
+ * Float >= Hash # => nil
+ * Enumerable >= String # => nil
*
*/
@@ -1903,14 +2046,26 @@ rb_mod_ge(VALUE mod, VALUE arg)
/*
* call-seq:
- * mod > other -> true, false, or nil
+ * self > other -> true, false, or nil
*
- * Returns true if <i>mod</i> is an ancestor of <i>other</i>. Returns
- * <code>false</code> if <i>mod</i> is the same as <i>other</i>
- * or <i>mod</i> is a descendant of <i>other</i>.
- * Returns <code>nil</code> if there's no relationship between the two.
- * (Think of the relationship in terms of the class definition:
- * "class A < B" implies "B > A".)
+ * Returns +true+ if +self+ is an ancestor of +other+
+ * (+self+ is a superclass of +other+ or +self+ is included in +other+):
+ *
+ * Numeric > Float # => true
+ * Enumerable > Array # => true
+ *
+ * Returns +false+ if +self+ is a descendant of +other+
+ * (+self+ is a subclass of +other+ or +self+ includes +other+) or
+ * if +self+ is the same as +other+:
+ *
+ * Float > Numeric # => false
+ * Array > Enumerable # => false
+ * Float > Float # => false
+ *
+ * Returns +nil+ if there is no relationship between the two:
+ *
+ * Float > Hash # => nil
+ * Enumerable > String # => nil
*
*/
@@ -1923,14 +2078,30 @@ rb_mod_gt(VALUE mod, VALUE arg)
/*
* call-seq:
- * module <=> other_module -> -1, 0, +1, or nil
+ * self <=> other -> -1, 0, 1, or nil
+ *
+ * Compares +self+ and +other+.
+ *
+ * Returns:
+ *
+ * - +-1+, if +self+ includes +other+, if or +self+ is a subclass of +other+.
+ * - +0+, if +self+ and +other+ are the same.
+ * - +1+, if +other+ includes +self+, or if +other+ is a subclass of +self+.
+ * - +nil+, if none of the above is true.
+ *
+ * Examples:
*
- * Comparison---Returns -1, 0, +1 or nil depending on whether +module+
- * includes +other_module+, they are the same, or if +module+ is included by
- * +other_module+.
+ * # Class Array includes module Enumerable.
+ * Array <=> Enumerable # => -1
+ * Enumerable <=> Enumerable # => 0
+ * Enumerable <=> Array # => 1
+ * # Class File is a subclass of class IO.
+ * File <=> IO # => -1
+ * File <=> File # => 0
+ * IO <=> File # => 1
+ * # Class File has no relationship to class String.
+ * File <=> String # => nil
*
- * Returns +nil+ if +module+ has no relationship with +other_module+, if
- * +other_module+ is not a module, or if the two values are incomparable.
*/
static VALUE
@@ -2050,11 +2221,11 @@ rb_class_initialize(int argc, VALUE *argv, VALUE klass)
else {
super = argv[0];
rb_check_inheritable(super);
- if (super != rb_cBasicObject && !RCLASS_SUPER(super)) {
+ if (!RCLASS_INITIALIZED_P(super)) {
rb_raise(rb_eTypeError, "can't inherit uninitialized class");
}
}
- RCLASS_SET_SUPER(klass, super);
+ rb_class_set_super(klass, super);
rb_make_metaclass(klass, RBASIC(super)->klass);
rb_class_inherited(super, klass);
rb_mod_initialize_exec(klass);
@@ -2096,17 +2267,6 @@ static VALUE class_call_alloc_func(rb_alloc_func_t allocator, VALUE klass);
*/
static VALUE
-rb_class_alloc_m(VALUE klass)
-{
- rb_alloc_func_t allocator = class_get_alloc_func(klass);
- if (!rb_obj_respond_to(klass, rb_intern("allocate"), 1)) {
- rb_raise(rb_eTypeError, "calling %"PRIsVALUE".allocate is prohibited",
- klass);
- }
- return class_call_alloc_func(allocator, klass);
-}
-
-static VALUE
rb_class_alloc(VALUE klass)
{
rb_alloc_func_t allocator = class_get_alloc_func(klass);
@@ -2118,7 +2278,7 @@ class_get_alloc_func(VALUE klass)
{
rb_alloc_func_t allocator;
- if (RCLASS_SUPER(klass) == 0 && klass != rb_cBasicObject) {
+ if (!RCLASS_INITIALIZED_P(klass)) {
rb_raise(rb_eTypeError, "can't instantiate uninitialized class");
}
if (RCLASS_SINGLETON_P(klass)) {
@@ -2131,6 +2291,15 @@ class_get_alloc_func(VALUE klass)
return allocator;
}
+// Might return NULL.
+rb_alloc_func_t
+rb_zjit_class_get_alloc_func(VALUE klass)
+{
+ assert(RCLASS_INITIALIZED_P(klass));
+ assert(!RCLASS_SINGLETON_P(klass));
+ return rb_get_alloc_func(klass);
+}
+
static VALUE
class_call_alloc_func(rb_alloc_func_t allocator, VALUE klass)
{
@@ -2140,8 +2309,10 @@ class_call_alloc_func(rb_alloc_func_t allocator, VALUE klass)
obj = (*allocator)(klass);
- if (rb_obj_class(obj) != rb_class_real(klass)) {
- rb_raise(rb_eTypeError, "wrong instance allocation");
+ if (UNLIKELY(RBASIC_CLASS(obj) != klass)) {
+ if (rb_obj_class(obj) != rb_class_real(klass)) {
+ rb_raise(rb_eTypeError, "wrong instance allocation");
+ }
}
return obj;
}
@@ -2225,19 +2396,22 @@ rb_class_superclass(VALUE klass)
{
RUBY_ASSERT(RB_TYPE_P(klass, T_CLASS));
- VALUE super = RCLASS_SUPER(klass);
+ VALUE *superclasses = RCLASS_SUPERCLASSES(klass);
+ size_t superclasses_depth = RCLASS_SUPERCLASS_DEPTH(klass);
- if (!super) {
- if (klass == rb_cBasicObject) return Qnil;
+ if (klass == rb_cBasicObject) return Qnil;
+
+ if (!superclasses) {
+ RUBY_ASSERT(!RCLASS_SUPER(klass));
rb_raise(rb_eTypeError, "uninitialized class");
}
- if (!RCLASS_SUPERCLASS_DEPTH(klass)) {
+ if (!superclasses_depth) {
return Qnil;
}
else {
- super = RCLASS_SUPERCLASSES(klass)[RCLASS_SUPERCLASS_DEPTH(klass) - 1];
- RUBY_ASSERT(RB_TYPE_P(klass, T_CLASS));
+ VALUE super = superclasses[superclasses_depth - 1];
+ RUBY_ASSERT(RB_TYPE_P(super, T_CLASS));
return super;
}
}
@@ -2245,7 +2419,7 @@ rb_class_superclass(VALUE klass)
VALUE
rb_class_get_superclass(VALUE klass)
{
- return RCLASS(klass)->super;
+ return RCLASS_SUPER(klass);
}
static const char bad_instance_name[] = "'%1$s' is not allowed as an instance variable name";
@@ -3399,8 +3573,15 @@ rb_f_integer(rb_execution_context_t *ec, VALUE obj, VALUE arg, VALUE base, VALUE
return rb_convert_to_integer(arg, NUM2INT(base), exc);
}
+static bool
+is_digit_char(unsigned char c, int base)
+{
+ int i = ruby_digit36_to_number_table[c];
+ return (i >= 0 && i < base);
+}
+
static double
-rb_cstr_to_dbl_raise(const char *p, int badcheck, int raise, int *error)
+rb_cstr_to_dbl_raise(const char *p, rb_encoding *enc, int badcheck, int raise, int *error)
{
const char *q;
char *end;
@@ -3411,6 +3592,7 @@ rb_cstr_to_dbl_raise(const char *p, int badcheck, int raise, int *error)
#define OutOfRange() ((end - p > max_width) ? \
(w = max_width, ellipsis = "...") : \
(w = (int)(end - p), ellipsis = ""))
+ /* p...end has been parsed with strtod, should be ASCII-only */
if (!p) return 0.0;
q = p;
@@ -3439,23 +3621,37 @@ rb_cstr_to_dbl_raise(const char *p, int badcheck, int raise, int *error)
char *e = init_e;
char prev = 0;
int dot_seen = FALSE;
+ int base = 10;
+ char exp_letter = 'e';
switch (*p) {case '+': case '-': prev = *n++ = *p++;}
if (*p == '0') {
prev = *n++ = '0';
- while (*++p == '0');
+ switch (*++p) {
+ case 'x': case 'X':
+ prev = *n++ = 'x';
+ base = 16;
+ exp_letter = 'p';
+ if (*++p != '0') break;
+ /* fallthrough */
+ case '0': /* squeeze successive zeros */
+ while (*++p == '0');
+ break;
+ }
}
while (p < end && n < e) prev = *n++ = *p++;
while (*p) {
if (*p == '_') {
/* remove an underscore between digits */
- if (n == buf || !ISDIGIT(prev) || (++p, !ISDIGIT(*p))) {
+ if (n == buf ||
+ !is_digit_char(prev, base) ||
+ !is_digit_char(*++p, base)) {
if (badcheck) goto bad;
break;
}
}
prev = *p++;
- if (e == init_e && (prev == 'e' || prev == 'E' || prev == 'p' || prev == 'P')) {
+ if (e == init_e && (rb_tolower(prev) == exp_letter)) {
e = buf + sizeof(buf) - 1;
*n++ = prev;
switch (*p) {case '+': case '-': prev = *n++ = *p++;}
@@ -3463,6 +3659,10 @@ rb_cstr_to_dbl_raise(const char *p, int badcheck, int raise, int *error)
prev = *n++ = '0';
while (*++p == '0');
}
+
+ /* reset base to decimal for underscore check of
+ * binary exponent part */
+ base = 10;
continue;
}
else if (ISSPACE(prev)) {
@@ -3472,7 +3672,7 @@ rb_cstr_to_dbl_raise(const char *p, int badcheck, int raise, int *error)
break;
}
}
- else if (prev == '.' ? dot_seen++ : !ISDIGIT(prev)) {
+ else if (prev == '.' ? dot_seen++ : !is_digit_char(prev, base)) {
if (badcheck) goto bad;
break;
}
@@ -3506,7 +3706,8 @@ rb_cstr_to_dbl_raise(const char *p, int badcheck, int raise, int *error)
bad:
if (raise) {
- rb_invalid_str(q, "Float()");
+ VALUE s = rb_enc_str_new_cstr(q, enc);
+ rb_raise(rb_eArgError, "invalid value for Float(): %+"PRIsVALUE, s);
UNREACHABLE_RETURN(nan(""));
}
else {
@@ -3518,7 +3719,7 @@ rb_cstr_to_dbl_raise(const char *p, int badcheck, int raise, int *error)
double
rb_cstr_to_dbl(const char *p, int badcheck)
{
- return rb_cstr_to_dbl_raise(p, badcheck, TRUE, NULL);
+ return rb_cstr_to_dbl_raise(p, NULL, badcheck, TRUE, NULL);
}
static double
@@ -3530,6 +3731,7 @@ rb_str_to_dbl_raise(VALUE str, int badcheck, int raise, int *error)
VALUE v = 0;
StringValue(str);
+ rb_must_asciicompat(str);
s = RSTRING_PTR(str);
len = RSTRING_LEN(str);
if (s) {
@@ -3548,9 +3750,11 @@ rb_str_to_dbl_raise(VALUE str, int badcheck, int raise, int *error)
s = p;
}
}
- ret = rb_cstr_to_dbl_raise(s, badcheck, raise, error);
+ ret = rb_cstr_to_dbl_raise(s, rb_enc_get(str), badcheck, raise, error);
if (v)
ALLOCV_END(v);
+ else
+ RB_GC_GUARD(str);
return ret;
}
@@ -3816,7 +4020,7 @@ rb_String(VALUE val)
*
* String([0, 1, 2]) # => "[0, 1, 2]"
* String(0..5) # => "0..5"
- * String({foo: 0, bar: 1}) # => "{:foo=>0, :bar=>1}"
+ * String({foo: 0, bar: 1}) # => "{foo: 0, bar: 1}"
*
* Raises +TypeError+ if +object+ cannot be converted to a string.
*/
@@ -3988,7 +4192,7 @@ rb_obj_dig(int argc, VALUE *argv, VALUE obj, VALUE notfound)
* into +format_string+.
*
* For details on +format_string+, see
- * {Format Specifications}[rdoc-ref:format_specifications.rdoc].
+ * {Format Specifications}[rdoc-ref:language/format_specifications.rdoc].
*/
static VALUE
@@ -4065,57 +4269,51 @@ rb_f_loop_size(VALUE self, VALUE args, VALUE eobj)
*/
-/* Document-class: BasicObject
+/*
+ * Document-class: BasicObject
*
- * BasicObject is the parent class of all classes in Ruby. It's an explicit
- * blank class.
+ * +BasicObject+ is the parent class of all classes in Ruby.
+ * In particular, +BasicObject+ is the parent class of class Object,
+ * which is itself the default parent class of every Ruby class:
*
- * BasicObject can be used for creating object hierarchies independent of
- * Ruby's object hierarchy, proxy objects like the Delegator class, or other
- * uses where namespace pollution from Ruby's methods and classes must be
- * avoided.
+ * class Foo; end
+ * Foo.superclass # => Object
+ * Object.superclass # => BasicObject
*
- * To avoid polluting BasicObject for other users an appropriately named
- * subclass of BasicObject should be created instead of directly modifying
- * BasicObject:
+ * +BasicObject+ is the only class that has no parent:
*
- * class MyObjectSystem < BasicObject
- * end
+ * BasicObject.superclass # => nil
*
- * BasicObject does not include Kernel (for methods like +puts+) and
- * BasicObject is outside of the namespace of the standard library so common
- * classes will not be found without using a full class path.
+ * Class +BasicObject+ can be used to create an object hierarchy
+ * (e.g., class Delegator) that is independent of Ruby's object hierarchy.
+ * Such objects:
*
- * A variety of strategies can be used to provide useful portions of the
- * standard library to subclasses of BasicObject. A subclass could
- * <code>include Kernel</code> to obtain +puts+, +exit+, etc. A custom
- * Kernel-like module could be created and included or delegation can be used
- * via #method_missing:
+ * - Do not have namespace "pollution" from the many methods
+ * provided in class Object and its included module Kernel.
+ * - Do not have definitions of common classes,
+ * and so references to such common classes must be fully qualified
+ * (+::String+, not +String+).
*
- * class MyObjectSystem < BasicObject
- * DELEGATE = [:puts, :p]
+ * A variety of strategies can be used to provide useful portions
+ * of the Standard Library in subclasses of +BasicObject+:
*
- * def method_missing(name, *args, &block)
- * return super unless DELEGATE.include? name
- * ::Kernel.send(name, *args, &block)
- * end
+ * - The immediate subclass could <tt>include Kernel</tt>,
+ * which would define methods such as +puts+, +exit+, etc.
+ * - A custom Kernel-like module could be created and included.
+ * - Delegation can be used via #method_missing:
*
- * def respond_to_missing?(name, include_private = false)
- * DELEGATE.include?(name)
- * end
- * end
+ * class MyObjectSystem < BasicObject
+ * DELEGATE = [:puts, :p]
*
- * Access to classes and modules from the Ruby standard library can be
- * obtained in a BasicObject subclass by referencing the desired constant
- * from the root like <code>::File</code> or <code>::Enumerator</code>.
- * Like #method_missing, #const_missing can be used to delegate constant
- * lookup to +Object+:
+ * def method_missing(name, *args, &block)
+ * return super unless DELEGATE.include? name
+ * ::Kernel.send(name, *args, &block)
+ * end
*
- * class MyObjectSystem < BasicObject
- * def self.const_missing(name)
- * ::Object.const_get(name)
+ * def respond_to_missing?(name, include_private = false)
+ * DELEGATE.include?(name)
+ * end
* end
- * end
*
* === What's Here
*
@@ -4129,8 +4327,11 @@ rb_f_loop_size(VALUE self, VALUE args, VALUE eobj)
* - #__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.
+ * - #instance_exec: Executes the given block in the context of +self+, passing the given arguments.
+ * - #method_missing: Called when +self+ is called with a method it does not define.
+ * - #singleton_method_added: Called when a singleton method is added to +self+.
+ * - #singleton_method_removed: Called when a singleton method is removed from +self+.
+ * - #singleton_method_undefined: Called when a singleton method is undefined in +self+.
*
*/
@@ -4154,7 +4355,7 @@ rb_f_loop_size(VALUE self, VALUE args, VALUE eobj)
*
* == What's Here
*
- * First, what's elsewhere. \Class \Object:
+ * First, what's elsewhere. Class \Object:
*
* - Inherits from {class BasicObject}[rdoc-ref:BasicObject@What-27s+Here].
* - Includes {module Kernel}[rdoc-ref:Kernel@What-27s+Here].
@@ -4178,7 +4379,7 @@ rb_f_loop_size(VALUE self, VALUE args, VALUE eobj)
* - #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+.
+ * - #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 <tt>nil?</tt>.)
@@ -4188,12 +4389,12 @@ rb_f_loop_size(VALUE self, VALUE args, VALUE eobj)
* 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_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
+ * - #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+.
@@ -4274,7 +4475,7 @@ InitVM_Object(void)
*
* == What's Here
*
- * \Module \Kernel provides methods that are useful for:
+ * Module \Kernel provides methods that are useful for:
*
* - {Converting}[rdoc-ref:Kernel@Converting]
* - {Querying}[rdoc-ref:Kernel@Querying]
@@ -4342,7 +4543,7 @@ InitVM_Object(void)
* - #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 <tt.$stdout.putc(object)</tt> for the given object.
+ * - #putc: Equivalent to <tt>$stdout.putc(object)</tt> for the given object.
* - #puts: Equivalent to <tt>$stdout.puts(*objects)</tt> 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.
@@ -4432,6 +4633,7 @@ InitVM_Object(void)
rb_define_method(rb_mKernel, "to_s", rb_any_to_s, 0);
rb_define_method(rb_mKernel, "inspect", rb_obj_inspect, 0);
+ rb_define_private_method(rb_mKernel, "instance_variables_to_inspect", rb_obj_instance_variables_to_inspect, 0);
rb_define_method(rb_mKernel, "methods", rb_obj_methods, -1); /* in class.c */
rb_define_method(rb_mKernel, "singleton_methods", rb_obj_singleton_methods, -1); /* in class.c */
rb_define_method(rb_mKernel, "protected_methods", rb_obj_protected_methods, -1); /* in class.c */
@@ -4480,7 +4682,6 @@ InitVM_Object(void)
rb_define_method(rb_cModule, "<=", rb_class_inherited_p, 1);
rb_define_method(rb_cModule, ">", rb_mod_gt, 1);
rb_define_method(rb_cModule, ">=", rb_mod_ge, 1);
- rb_define_method(rb_cModule, "initialize_copy", rb_mod_init_copy, 1); /* in class.c */
rb_define_method(rb_cModule, "to_s", rb_mod_to_s, 0);
rb_define_alias(rb_cModule, "inspect", "to_s");
rb_define_method(rb_cModule, "included_modules", rb_mod_included_modules, 0); /* in class.c */
@@ -4529,8 +4730,8 @@ 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_singleton_class(rb_cClass), "allocate", rb_class_alloc, 0);
+ rb_define_method(rb_cClass, "allocate", rb_class_alloc, 0);
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);
@@ -4573,6 +4774,7 @@ void
Init_Object(void)
{
id_dig = rb_intern_const("dig");
+ id_instance_variables_to_inspect = rb_intern_const("instance_variables_to_inspect");
InitVM(Object);
}
diff --git a/pack.c b/pack.c
index 1b0d66f990..2ef826b0e2 100644
--- a/pack.c
+++ b/pack.c
@@ -193,20 +193,69 @@ VALUE_to_float(VALUE obj)
}
}
+static void
+str_expand_fill(VALUE res, int c, long len)
+{
+ long olen = RSTRING_LEN(res);
+ memset(RSTRING_PTR(res) + olen, c, len);
+ rb_str_set_len(res, olen + len);
+}
+
+static char *
+skip_to_eol(const char *p, const char *pend)
+{
+ p = memchr(p, '\n', pend - p);
+ return (char *)(p ? p + 1 : pend);
+}
+
+#define skip_blank(p, type) \
+ (ISSPACE(type) || (type == '#' && (p = skip_to_eol(p, pend), 1)))
+
+#ifndef NATINT_PACK
+# define pack_modifiers(p, t, n, e) pack_modifiers(p, t, e)
+#endif
+static char *
+pack_modifiers(const char *p, char type, int *natint, int *explicit_endian)
+{
+ while (1) {
+ switch (*p) {
+ case '_':
+ case '!':
+ if (strchr(natstr, type)) {
+#ifdef NATINT_PACK
+ *natint = 1;
+#endif
+ p++;
+ }
+ else {
+ rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, natstr);
+ }
+ break;
+
+ case '<':
+ case '>':
+ if (!strchr(endstr, type)) {
+ rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, endstr);
+ }
+ if (*explicit_endian) {
+ rb_raise(rb_eRangeError, "Can't use both '<' and '>'");
+ }
+ *explicit_endian = *p++;
+ break;
+ default:
+ return (char *)p;
+ }
+ }
+}
+
static VALUE
pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
{
- static const char nul10[] = "\0\0\0\0\0\0\0\0\0\0";
- static const char spc10[] = " ";
const char *p, *pend;
VALUE res, from, associates = 0;
- char type;
long len, idx, plen;
const char *ptr;
int enc_info = 1; /* 0 - BINARY, 1 - US-ASCII, 2 - UTF-8 */
-#ifdef NATINT_PACK
- int natint; /* native integer */
-#endif
int integer_size, bigendian_p;
StringValue(fmt);
@@ -233,50 +282,16 @@ pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
while (p < pend) {
int explicit_endian = 0;
- if (RSTRING_PTR(fmt) + RSTRING_LEN(fmt) != pend) {
+ if (RSTRING_END(fmt) != pend) {
rb_raise(rb_eRuntimeError, "format string modified");
}
- type = *p++; /* get data type */
+ const char type = *p++; /* get data type */
#ifdef NATINT_PACK
- natint = 0;
+ int natint = 0; /* native integer */
#endif
- if (ISSPACE(type)) continue;
- if (type == '#') {
- while ((p < pend) && (*p != '\n')) {
- p++;
- }
- continue;
- }
-
- {
- modifiers:
- switch (*p) {
- case '_':
- case '!':
- if (strchr(natstr, type)) {
-#ifdef NATINT_PACK
- natint = 1;
-#endif
- p++;
- }
- else {
- rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, natstr);
- }
- goto modifiers;
-
- case '<':
- case '>':
- if (!strchr(endstr, type)) {
- rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, endstr);
- }
- if (explicit_endian) {
- rb_raise(rb_eRangeError, "Can't use both '<' and '>'");
- }
- explicit_endian = *p++;
- goto modifiers;
- }
- }
+ if (skip_blank(p, type)) continue;
+ p = pack_modifiers(p, type, &natint, &explicit_endian);
if (*p == '*') { /* set data length */
len = strchr("@Xxu", type) ? 0
@@ -287,7 +302,7 @@ pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
else if (ISDIGIT(*p)) {
errno = 0;
len = STRTOUL(p, (char**)&p, 10);
- if (errno) {
+ if (len < 0 || errno) {
rb_raise(rb_eRangeError, "pack length too big");
}
}
@@ -333,16 +348,12 @@ pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
if (plen >= len) {
rb_str_buf_cat(res, ptr, len);
if (p[-1] == '*' && type == 'Z')
- rb_str_buf_cat(res, nul10, 1);
+ rb_str_buf_cat(res, "", 1);
}
else {
+ rb_str_modify_expand(res, len);
rb_str_buf_cat(res, ptr, plen);
- len -= plen;
- while (len >= 10) {
- rb_str_buf_cat(res, (type == 'A')?spc10:nul10, 10);
- len -= 10;
- }
- rb_str_buf_cat(res, (type == 'A')?spc10:nul10, len);
+ str_expand_fill(res, (type == 'A' ? ' ' : '\0'), len - plen);
}
break;
@@ -616,11 +627,8 @@ pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
case 'x': /* null byte */
grow:
- while (len >= 10) {
- rb_str_buf_cat(res, nul10, 10);
- len -= 10;
- }
- rb_str_buf_cat(res, nul10, len);
+ rb_str_modify_expand(res, len);
+ str_expand_fill(res, '\0', len);
break;
case 'X': /* back up byte */
@@ -728,7 +736,7 @@ pack_pack(rb_execution_context_t *ec, VALUE ary, VALUE fmt, VALUE buffer)
case 'w': /* BER compressed integer */
while (len-- > 0) {
- VALUE buf = rb_str_new(0, 0);
+ VALUE buf;
size_t numbytes;
int sign;
char *cp;
@@ -945,13 +953,8 @@ pack_unpack_internal(VALUE str, VALUE fmt, enum unpack_mode mode, long offset)
char *s, *send;
char *p, *pend;
VALUE ary, associates = Qfalse;
- char type;
long len;
AVOID_CC_BUG long tmp_len;
- int star;
-#ifdef NATINT_PACK
- int natint; /* native integer */
-#endif
int signed_p, integer_size, bigendian_p;
#define UNPACK_PUSH(item) do {\
VALUE item_val = (item);\
@@ -986,49 +989,14 @@ pack_unpack_internal(VALUE str, VALUE fmt, enum unpack_mode mode, long offset)
ary = mode == UNPACK_ARRAY ? rb_ary_new() : Qnil;
while (p < pend) {
int explicit_endian = 0;
- type = *p++;
-#ifdef NATINT_PACK
- natint = 0;
-#endif
-
- if (ISSPACE(type)) continue;
- if (type == '#') {
- while ((p < pend) && (*p != '\n')) {
- p++;
- }
- continue;
- }
-
- star = 0;
- {
- modifiers:
- switch (*p) {
- case '_':
- case '!':
-
- if (strchr(natstr, type)) {
+ const char type = *p++;
#ifdef NATINT_PACK
- natint = 1;
+ int natint = 0; /* native integer */
#endif
- p++;
- }
- else {
- rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, natstr);
- }
- goto modifiers;
+ int star = 0;
- case '<':
- case '>':
- if (!strchr(endstr, type)) {
- rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, endstr);
- }
- if (explicit_endian) {
- rb_raise(rb_eRangeError, "Can't use both '<' and '>'");
- }
- explicit_endian = *p++;
- goto modifiers;
- }
- }
+ if (skip_blank(p, type)) continue;
+ p = pack_modifiers(p, type, &natint, &explicit_endian);
if (p >= pend)
len = 1;
diff --git a/pack.rb b/pack.rb
index b6e29c3eab..a8b9e74514 100644
--- a/pack.rb
+++ b/pack.rb
@@ -3,19 +3,25 @@ class Array
# pack(template, buffer: nil) -> string
#
# Formats each element in +self+ into a binary string; returns that string.
- # See {Packed Data}[rdoc-ref:packed_data.rdoc].
+ # See {Packed Data}[rdoc-ref:language/packed_data.rdoc].
def pack(fmt, buffer: nil)
Primitive.pack_pack(fmt, buffer)
end
end
class String
- # call-seq:
- # unpack(template, offset: 0) -> array
+ # call-seq:
+ # unpack(template, offset: 0) {|o| .... } -> object
+ # unpack(template, offset: 0) -> array
+ #
+ # Extracts data from +self+ to form new objects;
+ # see {Packed Data}[rdoc-ref:language/packed_data.rdoc].
#
- # Extracts data from +self+, forming objects that become the elements of a new array;
- # returns that array.
- # See {Packed Data}[rdoc-ref:packed_data.rdoc].
+ # With a block given, calls the block with each unpacked object.
+ #
+ # With no block given, returns an array containing the unpacked objects.
+ #
+ # Related: see {Converting to Non-String}[rdoc-ref:String@Converting+to+Non--5CString].
def unpack(fmt, offset: 0)
Primitive.attr! :use_block
Primitive.pack_unpack(fmt, offset)
@@ -24,8 +30,10 @@ class String
# call-seq:
# unpack1(template, offset: 0) -> object
#
- # Like String#unpack, but unpacks and returns only the first extracted object.
- # See {Packed Data}[rdoc-ref:packed_data.rdoc].
+ # Like String#unpack with no block, but unpacks and returns only the first extracted object.
+ # See {Packed Data}[rdoc-ref:language/packed_data.rdoc].
+ #
+ # Related: see {Converting to Non-String}[rdoc-ref:String@Converting+to+Non--5CString].
def unpack1(fmt, offset: 0)
Primitive.pack_unpack1(fmt, offset)
end
diff --git a/parse.y b/parse.y
index 94288b2ef8..03dd1c6f92 100644
--- a/parse.y
+++ b/parse.y
@@ -9,8 +9,6 @@
**********************************************************************/
-%require "3.0"
-
%{
#if !YYPURE
@@ -78,7 +76,7 @@ syntax_error_new(void)
}
#endif
-static NODE *reg_named_capture_assign(struct parser_params* p, VALUE regexp, const YYLTYPE *loc);
+static NODE *reg_named_capture_assign(struct parser_params* p, VALUE regexp, const YYLTYPE *loc, rb_parser_assignable_func assignable);
#define compile_callback rb_suppress_tracing
#endif /* !UNIVERSAL_PARSER */
@@ -276,7 +274,7 @@ parse_isdigit(int c)
static inline int
parse_isalnum(int c)
{
- return parse_isalpha(c) || parse_isdigit(c);
+ return ISALPHA(c) || ISDIGIT(c);
}
#undef ISALNUM
@@ -285,7 +283,7 @@ parse_isalnum(int c)
static inline int
parse_isxdigit(int c)
{
- return parse_isdigit(c) || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f');
+ return ISDIGIT(c) || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f');
}
#undef ISXDIGIT
@@ -316,12 +314,15 @@ struct lex_context {
unsigned int in_argdef: 1;
unsigned int in_def: 1;
unsigned int in_class: 1;
+ unsigned int has_trailing_semicolon: 1;
BITFIELD(enum rb_parser_shareability, shareable_constant_value, 2);
BITFIELD(enum rescue_context, in_rescue, 2);
+ unsigned int cant_return: 1;
+ unsigned int in_alt_pattern: 1;
+ unsigned int capture_in_pattern: 1;
};
typedef struct RNode_DEF_TEMP rb_node_def_temp_t;
-typedef struct RNode_EXITS rb_node_exits_t;
#if defined(__GNUC__) && !defined(__clang__)
// Suppress "parameter passing for argument of type 'struct
@@ -439,6 +440,12 @@ struct local_vars {
NODE *it;
};
+typedef struct rb_locations_lambda_body_t {
+ NODE *node;
+ YYLTYPE opening_loc;
+ YYLTYPE closing_loc;
+} rb_locations_lambda_body_t;
+
enum {
ORDINAL_PARAM = -1,
NO_PARAM = 0,
@@ -474,7 +481,7 @@ typedef struct parser_string_buffer {
parser_string_buffer_elem_t *last;
} parser_string_buffer_t;
-#define AFTER_HEREDOC_WITHOUT_TERMINTOR ((rb_parser_string_t *)1)
+#define AFTER_HEREDOC_WITHOUT_TERMINATOR ((rb_parser_string_t *)1)
/*
Structure of Lexer Buffer:
@@ -539,11 +546,11 @@ struct parser_params {
int end_col;
} delayed;
- ID cur_arg;
-
rb_ast_t *ast;
int node_id;
+ st_table *warn_duplicate_keys_table;
+
int max_numparam;
ID it_id;
@@ -709,10 +716,11 @@ after_pop_stack(int len, struct parser_params *p)
#define VALID_SYMNAME_P(s, l, enc, type) (rb_enc_symname_type(s, l, enc, (1U<<(type))) == (int)(type))
#ifndef RIPPER
-static inline bool
-end_with_newline_p(struct parser_params *p, VALUE str)
+static inline int
+char_at_end(struct parser_params *p, VALUE str, int when_empty)
{
- return RSTRING_LEN(str) > 0 && RSTRING_END(str)[-1] == '\n';
+ long len = RSTRING_LEN(str);
+ return len > 0 ? (unsigned char)RSTRING_PTR(str)[len-1] : when_empty;
}
#endif
@@ -764,8 +772,6 @@ string_buffer_append(struct parser_params *p, rb_parser_string_t *str)
buf->last->buf[buf->last->used++] = str;
}
-static void rb_parser_string_free(rb_parser_t *p, rb_parser_string_t *str);
-
static void
string_buffer_free(struct parser_params *p)
{
@@ -964,7 +970,6 @@ parser_token2char(struct parser_params *p, enum yytokentype tok)
TOKEN2CHAR(tASSOC);
TOKEN2CHAR(tLPAREN);
TOKEN2CHAR(tLPAREN_ARG);
- TOKEN2CHAR(tRPAREN);
TOKEN2CHAR(tLBRACK);
TOKEN2CHAR(tLBRACE);
TOKEN2CHAR(tLBRACE_ARG);
@@ -1058,28 +1063,28 @@ rb_discard_node(struct parser_params *p, NODE *n)
rb_ast_delete_node(p->ast, n);
}
-static rb_node_scope_t *rb_node_scope_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc);
-static rb_node_scope_t *rb_node_scope_new2(struct parser_params *p, rb_ast_id_table_t *nd_tbl, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc);
+static rb_node_scope_t *rb_node_scope_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, NODE *nd_parent, const YYLTYPE *loc);
+static rb_node_scope_t *rb_node_scope_new2(struct parser_params *p, rb_ast_id_table_t *nd_tbl, rb_node_args_t *nd_args, NODE *nd_body, NODE *nd_parent, const YYLTYPE *loc);
static rb_node_block_t *rb_node_block_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc);
-static rb_node_if_t *rb_node_if_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, NODE *nd_else, const YYLTYPE *loc);
-static rb_node_unless_t *rb_node_unless_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, NODE *nd_else, const YYLTYPE *loc);
-static rb_node_case_t *rb_node_case_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc);
-static rb_node_case2_t *rb_node_case2_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc);
-static rb_node_case3_t *rb_node_case3_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc);
-static rb_node_when_t *rb_node_when_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc);
-static rb_node_in_t *rb_node_in_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc);
-static rb_node_while_t *rb_node_while_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc);
-static rb_node_until_t *rb_node_until_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc);
+static rb_node_if_t *rb_node_if_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, NODE *nd_else, const YYLTYPE *loc, const YYLTYPE* if_keyword_loc, const YYLTYPE* then_keyword_loc, const YYLTYPE* end_keyword_loc);
+static rb_node_unless_t *rb_node_unless_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, NODE *nd_else, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *then_keyword_loc, const YYLTYPE *end_keyword_loc);
+static rb_node_case_t *rb_node_case_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *case_keyword_loc, const YYLTYPE *end_keyword_loc);
+static rb_node_case2_t *rb_node_case2_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *case_keyword_loc, const YYLTYPE *end_keyword_loc);
+static rb_node_case3_t *rb_node_case3_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *case_keyword_loc, const YYLTYPE *end_keyword_loc);
+static rb_node_when_t *rb_node_when_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *then_keyword_loc);
+static rb_node_in_t *rb_node_in_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc, const YYLTYPE *in_keyword_loc, const YYLTYPE *then_keyword_loc, const YYLTYPE *operator_loc);
+static rb_node_while_t *rb_node_while_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *closing_loc);
+static rb_node_until_t *rb_node_until_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *closing_loc);
static rb_node_iter_t *rb_node_iter_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc);
-static rb_node_for_t *rb_node_for_new(struct parser_params *p, NODE *nd_iter, NODE *nd_body, const YYLTYPE *loc);
+static rb_node_for_t *rb_node_for_new(struct parser_params *p, NODE *nd_iter, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *for_keyword_loc, const YYLTYPE *in_keyword_loc, const YYLTYPE *do_keyword_loc, const YYLTYPE *end_keyword_loc);
static rb_node_for_masgn_t *rb_node_for_masgn_new(struct parser_params *p, NODE *nd_var, const YYLTYPE *loc);
static rb_node_retry_t *rb_node_retry_new(struct parser_params *p, const YYLTYPE *loc);
static rb_node_begin_t *rb_node_begin_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc);
static rb_node_rescue_t *rb_node_rescue_new(struct parser_params *p, NODE *nd_head, NODE *nd_resq, NODE *nd_else, const YYLTYPE *loc);
-static rb_node_resbody_t *rb_node_resbody_new(struct parser_params *p, NODE *nd_args, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc);
+static rb_node_resbody_t *rb_node_resbody_new(struct parser_params *p, NODE *nd_args, NODE *nd_exc_var, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc);
static rb_node_ensure_t *rb_node_ensure_new(struct parser_params *p, NODE *nd_head, NODE *nd_ensr, const YYLTYPE *loc);
-static rb_node_and_t *rb_node_and_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc);
-static rb_node_or_t *rb_node_or_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc);
+static rb_node_and_t *rb_node_and_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc, const YYLTYPE *operator_loc);
+static rb_node_or_t *rb_node_or_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc, const YYLTYPE *operator_loc);
static rb_node_masgn_t *rb_node_masgn_new(struct parser_params *p, NODE *nd_head, NODE *nd_args, const YYLTYPE *loc);
static rb_node_lasgn_t *rb_node_lasgn_new(struct parser_params *p, ID nd_vid, NODE *nd_value, const YYLTYPE *loc);
static rb_node_dasgn_t *rb_node_dasgn_new(struct parser_params *p, ID nd_vid, NODE *nd_value, const YYLTYPE *loc);
@@ -1087,8 +1092,8 @@ static rb_node_gasgn_t *rb_node_gasgn_new(struct parser_params *p, ID nd_vid, NO
static rb_node_iasgn_t *rb_node_iasgn_new(struct parser_params *p, ID nd_vid, NODE *nd_value, const YYLTYPE *loc);
static rb_node_cdecl_t *rb_node_cdecl_new(struct parser_params *p, ID nd_vid, NODE *nd_value, NODE *nd_else, enum rb_parser_shareability shareability, const YYLTYPE *loc);
static rb_node_cvasgn_t *rb_node_cvasgn_new(struct parser_params *p, ID nd_vid, NODE *nd_value, const YYLTYPE *loc);
-static rb_node_op_asgn1_t *rb_node_op_asgn1_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *index, NODE *rvalue, const YYLTYPE *loc);
-static rb_node_op_asgn2_t *rb_node_op_asgn2_new(struct parser_params *p, NODE *nd_recv, NODE *nd_value, ID nd_vid, ID nd_mid, bool nd_aid, const YYLTYPE *loc);
+static rb_node_op_asgn1_t *rb_node_op_asgn1_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *index, NODE *rvalue, const YYLTYPE *loc, const YYLTYPE *call_operator_loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc, const YYLTYPE *binary_operator_loc);
+static rb_node_op_asgn2_t *rb_node_op_asgn2_new(struct parser_params *p, NODE *nd_recv, NODE *nd_value, ID nd_vid, ID nd_mid, bool nd_aid, const YYLTYPE *loc, const YYLTYPE *call_operator_loc, const YYLTYPE *message_loc, const YYLTYPE *binary_operator_loc);
static rb_node_op_asgn_or_t *rb_node_op_asgn_or_new(struct parser_params *p, NODE *nd_head, NODE *nd_value, const YYLTYPE *loc);
static rb_node_op_asgn_and_t *rb_node_op_asgn_and_new(struct parser_params *p, NODE *nd_head, NODE *nd_value, const YYLTYPE *loc);
static rb_node_op_cdecl_t *rb_node_op_cdecl_new(struct parser_params *p, NODE *nd_head, NODE *nd_value, ID nd_aid, enum rb_parser_shareability shareability, const YYLTYPE *loc);
@@ -1097,14 +1102,14 @@ static rb_node_opcall_t *rb_node_opcall_new(struct parser_params *p, NODE *nd_re
static rb_node_fcall_t *rb_node_fcall_new(struct parser_params *p, ID nd_mid, NODE *nd_args, const YYLTYPE *loc);
static rb_node_vcall_t *rb_node_vcall_new(struct parser_params *p, ID nd_mid, const YYLTYPE *loc);
static rb_node_qcall_t *rb_node_qcall_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *nd_args, const YYLTYPE *loc);
-static rb_node_super_t *rb_node_super_new(struct parser_params *p, NODE *nd_args, const YYLTYPE *loc);
+static rb_node_super_t *rb_node_super_new(struct parser_params *p, NODE *nd_args, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *lparen_loc, const YYLTYPE *rparen_loc);
static rb_node_zsuper_t * rb_node_zsuper_new(struct parser_params *p, const YYLTYPE *loc);
static rb_node_list_t *rb_node_list_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc);
static rb_node_list_t *rb_node_list_new2(struct parser_params *p, NODE *nd_head, long nd_alen, NODE *nd_next, const YYLTYPE *loc);
static rb_node_zlist_t *rb_node_zlist_new(struct parser_params *p, const YYLTYPE *loc);
static rb_node_hash_t *rb_node_hash_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc);
-static rb_node_return_t *rb_node_return_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc);
-static rb_node_yield_t *rb_node_yield_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc);
+static rb_node_return_t *rb_node_return_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc, const YYLTYPE *keyword_loc);
+static rb_node_yield_t *rb_node_yield_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *lparen_loc, const YYLTYPE *rparen_loc);
static rb_node_lvar_t *rb_node_lvar_new(struct parser_params *p, ID nd_vid, const YYLTYPE *loc);
static rb_node_dvar_t *rb_node_dvar_new(struct parser_params *p, ID nd_vid, const YYLTYPE *loc);
static rb_node_gvar_t *rb_node_gvar_new(struct parser_params *p, ID nd_vid, const YYLTYPE *loc);
@@ -1124,8 +1129,8 @@ static rb_node_dstr_t *rb_node_dstr_new0(struct parser_params *p, rb_parser_stri
static rb_node_dstr_t *rb_node_dstr_new(struct parser_params *p, rb_parser_string_t *string, const YYLTYPE *loc);
static rb_node_xstr_t *rb_node_xstr_new(struct parser_params *p, rb_parser_string_t *string, const YYLTYPE *loc);
static rb_node_dxstr_t *rb_node_dxstr_new(struct parser_params *p, rb_parser_string_t *string, long nd_alen, NODE *nd_next, const YYLTYPE *loc);
-static rb_node_evstr_t *rb_node_evstr_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc);
-static rb_node_regx_t *rb_node_regx_new(struct parser_params *p, rb_parser_string_t *string, int options, const YYLTYPE *loc);
+static rb_node_evstr_t *rb_node_evstr_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc);
+static rb_node_regx_t *rb_node_regx_new(struct parser_params *p, rb_parser_string_t *string, int options, const YYLTYPE *loc, const YYLTYPE *opening_loc, const YYLTYPE *content_loc, const YYLTYPE *closing_loc);
static rb_node_once_t *rb_node_once_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc);
static rb_node_args_t *rb_node_args_new(struct parser_params *p, const YYLTYPE *loc);
static rb_node_args_aux_t *rb_node_args_aux_new(struct parser_params *p, ID nd_pid, int nd_plen, const YYLTYPE *loc);
@@ -1134,31 +1139,31 @@ static rb_node_kw_arg_t *rb_node_kw_arg_new(struct parser_params *p, NODE *nd_bo
static rb_node_postarg_t *rb_node_postarg_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc);
static rb_node_argscat_t *rb_node_argscat_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc);
static rb_node_argspush_t *rb_node_argspush_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc);
-static rb_node_splat_t *rb_node_splat_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc);
-static rb_node_block_pass_t *rb_node_block_pass_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc);
+static rb_node_splat_t *rb_node_splat_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc, const YYLTYPE *operator_loc);
+static rb_node_block_pass_t *rb_node_block_pass_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *operator_loc);
static rb_node_defn_t *rb_node_defn_new(struct parser_params *p, ID nd_mid, NODE *nd_defn, const YYLTYPE *loc);
static rb_node_defs_t *rb_node_defs_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *nd_defn, const YYLTYPE *loc);
-static rb_node_alias_t *rb_node_alias_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc);
-static rb_node_valias_t *rb_node_valias_new(struct parser_params *p, ID nd_alias, ID nd_orig, const YYLTYPE *loc);
+static rb_node_alias_t *rb_node_alias_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc, const YYLTYPE *keyword_loc);
+static rb_node_valias_t *rb_node_valias_new(struct parser_params *p, ID nd_alias, ID nd_orig, const YYLTYPE *loc, const YYLTYPE *keyword_loc);
static rb_node_undef_t *rb_node_undef_new(struct parser_params *p, NODE *nd_undef, const YYLTYPE *loc);
-static rb_node_class_t *rb_node_class_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, NODE *nd_super, const YYLTYPE *loc);
-static rb_node_module_t *rb_node_module_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, const YYLTYPE *loc);
-static rb_node_sclass_t *rb_node_sclass_new(struct parser_params *p, NODE *nd_recv, NODE *nd_body, const YYLTYPE *loc);
-static rb_node_colon2_t *rb_node_colon2_new(struct parser_params *p, NODE *nd_head, ID nd_mid, const YYLTYPE *loc);
-static rb_node_colon3_t *rb_node_colon3_new(struct parser_params *p, ID nd_mid, const YYLTYPE *loc);
-static rb_node_dot2_t *rb_node_dot2_new(struct parser_params *p, NODE *nd_beg, NODE *nd_end, const YYLTYPE *loc);
-static rb_node_dot3_t *rb_node_dot3_new(struct parser_params *p, NODE *nd_beg, NODE *nd_end, const YYLTYPE *loc);
+static rb_node_class_t *rb_node_class_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, NODE *nd_super, const YYLTYPE *loc, const YYLTYPE *class_keyword_loc, const YYLTYPE *inheritance_operator_loc, const YYLTYPE *end_keyword_loc);
+static rb_node_module_t *rb_node_module_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *module_keyword_loc, const YYLTYPE *end_keyword_loc);
+static rb_node_sclass_t *rb_node_sclass_new(struct parser_params *p, NODE *nd_recv, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *class_keyword_loc, const YYLTYPE *operator_loc, const YYLTYPE *end_keyword_loc);
+static rb_node_colon2_t *rb_node_colon2_new(struct parser_params *p, NODE *nd_head, ID nd_mid, const YYLTYPE *loc, const YYLTYPE *delimiter_loc, const YYLTYPE *name_loc);
+static rb_node_colon3_t *rb_node_colon3_new(struct parser_params *p, ID nd_mid, const YYLTYPE *loc, const YYLTYPE *delimiter_loc, const YYLTYPE *name_loc);
+static rb_node_dot2_t *rb_node_dot2_new(struct parser_params *p, NODE *nd_beg, NODE *nd_end, const YYLTYPE *loc, const YYLTYPE *operator_loc);
+static rb_node_dot3_t *rb_node_dot3_new(struct parser_params *p, NODE *nd_beg, NODE *nd_end, const YYLTYPE *loc, const YYLTYPE *operator_loc);
static rb_node_self_t *rb_node_self_new(struct parser_params *p, const YYLTYPE *loc);
static rb_node_nil_t *rb_node_nil_new(struct parser_params *p, const YYLTYPE *loc);
static rb_node_true_t *rb_node_true_new(struct parser_params *p, const YYLTYPE *loc);
static rb_node_false_t *rb_node_false_new(struct parser_params *p, const YYLTYPE *loc);
static rb_node_errinfo_t *rb_node_errinfo_new(struct parser_params *p, const YYLTYPE *loc);
-static rb_node_defined_t *rb_node_defined_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc);
-static rb_node_postexe_t *rb_node_postexe_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc);
+static rb_node_defined_t *rb_node_defined_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc, const YYLTYPE *keyword_loc);
+static rb_node_postexe_t *rb_node_postexe_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc);
static rb_node_sym_t *rb_node_sym_new(struct parser_params *p, VALUE str, const YYLTYPE *loc);
static rb_node_dsym_t *rb_node_dsym_new(struct parser_params *p, rb_parser_string_t *string, long nd_alen, NODE *nd_next, const YYLTYPE *loc);
static rb_node_attrasgn_t *rb_node_attrasgn_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *nd_args, const YYLTYPE *loc);
-static rb_node_lambda_t *rb_node_lambda_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc);
+static rb_node_lambda_t *rb_node_lambda_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *operator_loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc);
static rb_node_aryptn_t *rb_node_aryptn_new(struct parser_params *p, NODE *pre_args, NODE *rest_arg, NODE *post_args, const YYLTYPE *loc);
static rb_node_hshptn_t *rb_node_hshptn_new(struct parser_params *p, NODE *nd_pconst, NODE *nd_pkwargs, NODE *nd_pkwrestarg, const YYLTYPE *loc);
static rb_node_fndptn_t *rb_node_fndptn_new(struct parser_params *p, NODE *pre_rest_arg, NODE *args, NODE *post_rest_arg, const YYLTYPE *loc);
@@ -1166,28 +1171,28 @@ static rb_node_line_t *rb_node_line_new(struct parser_params *p, const YYLTYPE *
static rb_node_file_t *rb_node_file_new(struct parser_params *p, VALUE str, const YYLTYPE *loc);
static rb_node_error_t *rb_node_error_new(struct parser_params *p, const YYLTYPE *loc);
-#define NEW_SCOPE(a,b,loc) (NODE *)rb_node_scope_new(p,a,b,loc)
-#define NEW_SCOPE2(t,a,b,loc) (NODE *)rb_node_scope_new2(p,t,a,b,loc)
+#define NEW_SCOPE(a,b,c,loc) (NODE *)rb_node_scope_new(p,a,b,c,loc)
+#define NEW_SCOPE2(t,a,b,c,loc) (NODE *)rb_node_scope_new2(p,t,a,b,c,loc)
#define NEW_BLOCK(a,loc) (NODE *)rb_node_block_new(p,a,loc)
-#define NEW_IF(c,t,e,loc) (NODE *)rb_node_if_new(p,c,t,e,loc)
-#define NEW_UNLESS(c,t,e,loc) (NODE *)rb_node_unless_new(p,c,t,e,loc)
-#define NEW_CASE(h,b,loc) (NODE *)rb_node_case_new(p,h,b,loc)
-#define NEW_CASE2(b,loc) (NODE *)rb_node_case2_new(p,b,loc)
-#define NEW_CASE3(h,b,loc) (NODE *)rb_node_case3_new(p,h,b,loc)
-#define NEW_WHEN(c,t,e,loc) (NODE *)rb_node_when_new(p,c,t,e,loc)
-#define NEW_IN(c,t,e,loc) (NODE *)rb_node_in_new(p,c,t,e,loc)
-#define NEW_WHILE(c,b,n,loc) (NODE *)rb_node_while_new(p,c,b,n,loc)
-#define NEW_UNTIL(c,b,n,loc) (NODE *)rb_node_until_new(p,c,b,n,loc)
+#define NEW_IF(c,t,e,loc,ik_loc,tk_loc,ek_loc) (NODE *)rb_node_if_new(p,c,t,e,loc,ik_loc,tk_loc,ek_loc)
+#define NEW_UNLESS(c,t,e,loc,k_loc,t_loc,e_loc) (NODE *)rb_node_unless_new(p,c,t,e,loc,k_loc,t_loc,e_loc)
+#define NEW_CASE(h,b,loc,ck_loc,ek_loc) (NODE *)rb_node_case_new(p,h,b,loc,ck_loc,ek_loc)
+#define NEW_CASE2(b,loc,ck_loc,ek_loc) (NODE *)rb_node_case2_new(p,b,loc,ck_loc,ek_loc)
+#define NEW_CASE3(h,b,loc,ck_loc,ek_loc) (NODE *)rb_node_case3_new(p,h,b,loc,ck_loc,ek_loc)
+#define NEW_WHEN(c,t,e,loc,k_loc,t_loc) (NODE *)rb_node_when_new(p,c,t,e,loc,k_loc,t_loc)
+#define NEW_IN(c,t,e,loc,ik_loc,tk_loc,o_loc) (NODE *)rb_node_in_new(p,c,t,e,loc,ik_loc,tk_loc,o_loc)
+#define NEW_WHILE(c,b,n,loc,k_loc,c_loc) (NODE *)rb_node_while_new(p,c,b,n,loc,k_loc,c_loc)
+#define NEW_UNTIL(c,b,n,loc,k_loc,c_loc) (NODE *)rb_node_until_new(p,c,b,n,loc,k_loc,c_loc)
#define NEW_ITER(a,b,loc) (NODE *)rb_node_iter_new(p,a,b,loc)
-#define NEW_FOR(i,b,loc) (NODE *)rb_node_for_new(p,i,b,loc)
+#define NEW_FOR(i,b,loc,f_loc,i_loc,d_loc,e_loc) (NODE *)rb_node_for_new(p,i,b,loc,f_loc,i_loc,d_loc,e_loc)
#define NEW_FOR_MASGN(v,loc) (NODE *)rb_node_for_masgn_new(p,v,loc)
#define NEW_RETRY(loc) (NODE *)rb_node_retry_new(p,loc)
#define NEW_BEGIN(b,loc) (NODE *)rb_node_begin_new(p,b,loc)
#define NEW_RESCUE(b,res,e,loc) (NODE *)rb_node_rescue_new(p,b,res,e,loc)
-#define NEW_RESBODY(a,ex,n,loc) (NODE *)rb_node_resbody_new(p,a,ex,n,loc)
+#define NEW_RESBODY(a,v,ex,n,loc) (NODE *)rb_node_resbody_new(p,a,v,ex,n,loc)
#define NEW_ENSURE(b,en,loc) (NODE *)rb_node_ensure_new(p,b,en,loc)
-#define NEW_AND(f,s,loc) (NODE *)rb_node_and_new(p,f,s,loc)
-#define NEW_OR(f,s,loc) (NODE *)rb_node_or_new(p,f,s,loc)
+#define NEW_AND(f,s,loc,op_loc) (NODE *)rb_node_and_new(p,f,s,loc,op_loc)
+#define NEW_OR(f,s,loc,op_loc) (NODE *)rb_node_or_new(p,f,s,loc,op_loc)
#define NEW_MASGN(l,r,loc) rb_node_masgn_new(p,l,r,loc)
#define NEW_LASGN(v,val,loc) (NODE *)rb_node_lasgn_new(p,v,val,loc)
#define NEW_DASGN(v,val,loc) (NODE *)rb_node_dasgn_new(p,v,val,loc)
@@ -1195,8 +1200,8 @@ static rb_node_error_t *rb_node_error_new(struct parser_params *p, const YYLTYPE
#define NEW_IASGN(v,val,loc) (NODE *)rb_node_iasgn_new(p,v,val,loc)
#define NEW_CDECL(v,val,path,share,loc) (NODE *)rb_node_cdecl_new(p,v,val,path,share,loc)
#define NEW_CVASGN(v,val,loc) (NODE *)rb_node_cvasgn_new(p,v,val,loc)
-#define NEW_OP_ASGN1(r,id,idx,rval,loc) (NODE *)rb_node_op_asgn1_new(p,r,id,idx,rval,loc)
-#define NEW_OP_ASGN2(r,t,i,o,val,loc) (NODE *)rb_node_op_asgn2_new(p,r,val,i,o,t,loc)
+#define NEW_OP_ASGN1(r,id,idx,rval,loc,c_op_loc,o_loc,c_loc,b_op_loc) (NODE *)rb_node_op_asgn1_new(p,r,id,idx,rval,loc,c_op_loc,o_loc,c_loc,b_op_loc)
+#define NEW_OP_ASGN2(r,t,i,o,val,loc,c_op_loc,m_loc,b_op_loc) (NODE *)rb_node_op_asgn2_new(p,r,val,i,o,t,loc,c_op_loc,m_loc,b_op_loc)
#define NEW_OP_ASGN_OR(i,val,loc) (NODE *)rb_node_op_asgn_or_new(p,i,val,loc)
#define NEW_OP_ASGN_AND(i,val,loc) (NODE *)rb_node_op_asgn_and_new(p,i,val,loc)
#define NEW_OP_CDECL(v,op,val,share,loc) (NODE *)rb_node_op_cdecl_new(p,v,val,op,share,loc)
@@ -1205,14 +1210,14 @@ static rb_node_error_t *rb_node_error_new(struct parser_params *p, const YYLTYPE
#define NEW_FCALL(m,a,loc) rb_node_fcall_new(p,m,a,loc)
#define NEW_VCALL(m,loc) (NODE *)rb_node_vcall_new(p,m,loc)
#define NEW_QCALL0(r,m,a,loc) (NODE *)rb_node_qcall_new(p,r,m,a,loc)
-#define NEW_SUPER(a,loc) (NODE *)rb_node_super_new(p,a,loc)
+#define NEW_SUPER(a,loc,k_loc,l_loc,r_loc) (NODE *)rb_node_super_new(p,a,loc,k_loc,l_loc,r_loc)
#define NEW_ZSUPER(loc) (NODE *)rb_node_zsuper_new(p,loc)
#define NEW_LIST(a,loc) (NODE *)rb_node_list_new(p,a,loc)
#define NEW_LIST2(h,l,n,loc) (NODE *)rb_node_list_new2(p,h,l,n,loc)
#define NEW_ZLIST(loc) (NODE *)rb_node_zlist_new(p,loc)
#define NEW_HASH(a,loc) (NODE *)rb_node_hash_new(p,a,loc)
-#define NEW_RETURN(s,loc) (NODE *)rb_node_return_new(p,s,loc)
-#define NEW_YIELD(a,loc) (NODE *)rb_node_yield_new(p,a,loc)
+#define NEW_RETURN(s,loc,k_loc) (NODE *)rb_node_return_new(p,s,loc,k_loc)
+#define NEW_YIELD(a,loc,k_loc,l_loc,r_loc) (NODE *)rb_node_yield_new(p,a,loc,k_loc,l_loc,r_loc)
#define NEW_LVAR(v,loc) (NODE *)rb_node_lvar_new(p,v,loc)
#define NEW_DVAR(v,loc) (NODE *)rb_node_dvar_new(p,v,loc)
#define NEW_GVAR(v,loc) (NODE *)rb_node_gvar_new(p,v,loc)
@@ -1232,8 +1237,8 @@ static rb_node_error_t *rb_node_error_new(struct parser_params *p, const YYLTYPE
#define NEW_DSTR(s,loc) (NODE *)rb_node_dstr_new(p,s,loc)
#define NEW_XSTR(s,loc) (NODE *)rb_node_xstr_new(p,s,loc)
#define NEW_DXSTR(s,l,n,loc) (NODE *)rb_node_dxstr_new(p,s,l,n,loc)
-#define NEW_EVSTR(n,loc) (NODE *)rb_node_evstr_new(p,n,loc)
-#define NEW_REGX(str,opts,loc) (NODE *)rb_node_regx_new(p,str,opts,loc)
+#define NEW_EVSTR(n,loc,o_loc,c_loc) (NODE *)rb_node_evstr_new(p,n,loc,o_loc,c_loc)
+#define NEW_REGX(str,opts,loc,o_loc,ct_loc,c_loc) (NODE *)rb_node_regx_new(p,str,opts,loc,o_loc,ct_loc,c_loc)
#define NEW_ONCE(b,loc) (NODE *)rb_node_once_new(p,b,loc)
#define NEW_ARGS(loc) rb_node_args_new(p,loc)
#define NEW_ARGS_AUX(r,b,loc) rb_node_args_aux_new(p,r,b,loc)
@@ -1242,31 +1247,31 @@ static rb_node_error_t *rb_node_error_new(struct parser_params *p, const YYLTYPE
#define NEW_POSTARG(i,v,loc) (NODE *)rb_node_postarg_new(p,i,v,loc)
#define NEW_ARGSCAT(a,b,loc) (NODE *)rb_node_argscat_new(p,a,b,loc)
#define NEW_ARGSPUSH(a,b,loc) (NODE *)rb_node_argspush_new(p,a,b,loc)
-#define NEW_SPLAT(a,loc) (NODE *)rb_node_splat_new(p,a,loc)
-#define NEW_BLOCK_PASS(b,loc) rb_node_block_pass_new(p,b,loc)
+#define NEW_SPLAT(a,loc,op_loc) (NODE *)rb_node_splat_new(p,a,loc,op_loc)
+#define NEW_BLOCK_PASS(b,loc,o_loc) rb_node_block_pass_new(p,b,loc,o_loc)
#define NEW_DEFN(i,s,loc) (NODE *)rb_node_defn_new(p,i,s,loc)
#define NEW_DEFS(r,i,s,loc) (NODE *)rb_node_defs_new(p,r,i,s,loc)
-#define NEW_ALIAS(n,o,loc) (NODE *)rb_node_alias_new(p,n,o,loc)
-#define NEW_VALIAS(n,o,loc) (NODE *)rb_node_valias_new(p,n,o,loc)
+#define NEW_ALIAS(n,o,loc,k_loc) (NODE *)rb_node_alias_new(p,n,o,loc,k_loc)
+#define NEW_VALIAS(n,o,loc,k_loc) (NODE *)rb_node_valias_new(p,n,o,loc,k_loc)
#define NEW_UNDEF(i,loc) (NODE *)rb_node_undef_new(p,i,loc)
-#define NEW_CLASS(n,b,s,loc) (NODE *)rb_node_class_new(p,n,b,s,loc)
-#define NEW_MODULE(n,b,loc) (NODE *)rb_node_module_new(p,n,b,loc)
-#define NEW_SCLASS(r,b,loc) (NODE *)rb_node_sclass_new(p,r,b,loc)
-#define NEW_COLON2(c,i,loc) (NODE *)rb_node_colon2_new(p,c,i,loc)
-#define NEW_COLON3(i,loc) (NODE *)rb_node_colon3_new(p,i,loc)
-#define NEW_DOT2(b,e,loc) (NODE *)rb_node_dot2_new(p,b,e,loc)
-#define NEW_DOT3(b,e,loc) (NODE *)rb_node_dot3_new(p,b,e,loc)
+#define NEW_CLASS(n,b,s,loc,ck_loc,io_loc,ek_loc) (NODE *)rb_node_class_new(p,n,b,s,loc,ck_loc,io_loc,ek_loc)
+#define NEW_MODULE(n,b,loc,mk_loc,ek_loc) (NODE *)rb_node_module_new(p,n,b,loc,mk_loc,ek_loc)
+#define NEW_SCLASS(r,b,loc,ck_loc,op_loc,ek_loc) (NODE *)rb_node_sclass_new(p,r,b,loc,ck_loc,op_loc,ek_loc)
+#define NEW_COLON2(c,i,loc,d_loc,n_loc) (NODE *)rb_node_colon2_new(p,c,i,loc,d_loc,n_loc)
+#define NEW_COLON3(i,loc,d_loc,n_loc) (NODE *)rb_node_colon3_new(p,i,loc,d_loc,n_loc)
+#define NEW_DOT2(b,e,loc,op_loc) (NODE *)rb_node_dot2_new(p,b,e,loc,op_loc)
+#define NEW_DOT3(b,e,loc,op_loc) (NODE *)rb_node_dot3_new(p,b,e,loc,op_loc)
#define NEW_SELF(loc) (NODE *)rb_node_self_new(p,loc)
#define NEW_NIL(loc) (NODE *)rb_node_nil_new(p,loc)
#define NEW_TRUE(loc) (NODE *)rb_node_true_new(p,loc)
#define NEW_FALSE(loc) (NODE *)rb_node_false_new(p,loc)
#define NEW_ERRINFO(loc) (NODE *)rb_node_errinfo_new(p,loc)
-#define NEW_DEFINED(e,loc) (NODE *)rb_node_defined_new(p,e,loc)
-#define NEW_POSTEXE(b,loc) (NODE *)rb_node_postexe_new(p,b,loc)
+#define NEW_DEFINED(e,loc,k_loc) (NODE *)rb_node_defined_new(p,e,loc, k_loc)
+#define NEW_POSTEXE(b,loc,k_loc,o_loc,c_loc) (NODE *)rb_node_postexe_new(p,b,loc,k_loc,o_loc,c_loc)
#define NEW_SYM(str,loc) (NODE *)rb_node_sym_new(p,str,loc)
#define NEW_DSYM(s,l,n,loc) (NODE *)rb_node_dsym_new(p,s,l,n,loc)
#define NEW_ATTRASGN(r,m,a,loc) (NODE *)rb_node_attrasgn_new(p,r,m,a,loc)
-#define NEW_LAMBDA(a,b,loc) (NODE *)rb_node_lambda_new(p,a,b,loc)
+#define NEW_LAMBDA(a,b,loc,op_loc,o_loc,c_loc) (NODE *)rb_node_lambda_new(p,a,b,loc,op_loc,o_loc,c_loc)
#define NEW_ARYPTN(pre,r,post,loc) (NODE *)rb_node_aryptn_new(p,pre,r,post,loc)
#define NEW_HSHPTN(c,kw,kwrest,loc) (NODE *)rb_node_hshptn_new(p,c,kw,kwrest,loc)
#define NEW_FNDPTN(pre,a,post,loc) (NODE *)rb_node_fndptn_new(p,pre,a,post,loc)
@@ -1305,7 +1310,6 @@ struct RNode_DEF_TEMP {
ID nd_mid;
struct {
- ID cur_arg;
int max_numparam;
NODE *numparam_save;
struct lex_context ctxt;
@@ -1314,15 +1318,15 @@ struct RNode_DEF_TEMP {
#define RNODE_DEF_TEMP(node) ((struct RNode_DEF_TEMP *)(node))
-static rb_node_break_t *rb_node_break_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc);
-static rb_node_next_t *rb_node_next_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc);
-static rb_node_redo_t *rb_node_redo_new(struct parser_params *p, const YYLTYPE *loc);
+static rb_node_break_t *rb_node_break_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc, const YYLTYPE *keyword_loc);
+static rb_node_next_t *rb_node_next_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc, const YYLTYPE *keyword_loc);
+static rb_node_redo_t *rb_node_redo_new(struct parser_params *p, const YYLTYPE *loc, const YYLTYPE *keyword_loc);
static rb_node_def_temp_t *rb_node_def_temp_new(struct parser_params *p, const YYLTYPE *loc);
static rb_node_def_temp_t *def_head_save(struct parser_params *p, rb_node_def_temp_t *n);
-#define NEW_BREAK(s,loc) (NODE *)rb_node_break_new(p,s,loc)
-#define NEW_NEXT(s,loc) (NODE *)rb_node_next_new(p,s,loc)
-#define NEW_REDO(loc) (NODE *)rb_node_redo_new(p,loc)
+#define NEW_BREAK(s,loc,k_loc) (NODE *)rb_node_break_new(p,s,loc,k_loc)
+#define NEW_NEXT(s,loc,k_loc) (NODE *)rb_node_next_new(p,s,loc,k_loc)
+#define NEW_REDO(loc,k_loc) (NODE *)rb_node_redo_new(p,loc,k_loc)
#define NEW_DEF_TEMP(loc) rb_node_def_temp_new(p,loc)
/* Make a new internal node, which should not be appeared in the
@@ -1389,19 +1393,17 @@ last_expr_node(NODE *expr)
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 *new_if(struct parser_params*,NODE*,NODE*,NODE*,const YYLTYPE*,const YYLTYPE*,const YYLTYPE*,const YYLTYPE*);
+static NODE *new_unless(struct parser_params*,NODE*,NODE*,NODE*,const YYLTYPE*,const YYLTYPE*,const YYLTYPE*,const YYLTYPE*);
static NODE *logop(struct parser_params*,ID,NODE*,NODE*,const YYLTYPE*,const YYLTYPE*);
static NODE *newline_node(NODE*);
static void fixpos(NODE*,NODE*);
-static int value_expr_gen(struct parser_params*,NODE*);
+static int value_expr(struct parser_params*,NODE*);
static void void_expr(struct parser_params*,NODE*);
static 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*);
@@ -1413,7 +1415,7 @@ static NODE *arg_append(struct parser_params*,NODE*,NODE*,const YYLTYPE*);
static NODE *last_arg_append(struct parser_params *p, NODE *args, NODE *last_arg, const YYLTYPE *loc);
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_evstr(struct parser_params*,NODE*,const YYLTYPE*,const YYLTYPE*,const YYLTYPE*);
static NODE *new_dstr(struct parser_params*,NODE*,const YYLTYPE*);
static NODE *str2dstr(struct parser_params*,NODE*);
static NODE *evstr2dstr(struct parser_params*,NODE*);
@@ -1440,9 +1442,9 @@ static rb_node_kw_arg_t *new_kw_arg(struct parser_params *p, NODE *k, const YYLT
static rb_node_args_t *args_with_numbered(struct parser_params*,rb_node_args_t*,int,ID);
static NODE* negate_lit(struct parser_params*, NODE*);
+static void no_blockarg(struct parser_params*,NODE*);
static NODE *ret_args(struct parser_params*,NODE*);
static NODE *arg_blk_pass(NODE*,rb_node_block_pass_t*);
-static NODE *new_yield(struct parser_params*,NODE*,const YYLTYPE*);
static NODE *dsym_node(struct parser_params*,NODE*,const YYLTYPE*);
static NODE *gettable(struct parser_params*,ID,const YYLTYPE*);
@@ -1451,12 +1453,12 @@ static NODE *assignable(struct parser_params*,ID,NODE*,const YYLTYPE*);
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 VALUE rb_backref_error(struct parser_params*,NODE*);
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, 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_ary_op_assign(struct parser_params *p, NODE *ary, NODE *args, ID op, NODE *rhs, const YYLTYPE *args_loc, const YYLTYPE *loc, const YYLTYPE *call_operator_loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc, const YYLTYPE *binary_operator_loc);
+static NODE *new_attr_op_assign(struct parser_params *p, NODE *lhs, ID atype, ID attr, ID op, NODE *rhs, const YYLTYPE *loc, const YYLTYPE *call_operator_loc, const YYLTYPE *message_loc, const YYLTYPE *binary_operator_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);
@@ -1468,9 +1470,9 @@ static rb_node_kw_arg_t *kwd_append(rb_node_kw_arg_t*, rb_node_kw_arg_t*);
static NODE *new_hash(struct parser_params *p, NODE *hash, const YYLTYPE *loc);
static NODE *new_unique_key_hash(struct parser_params *p, NODE *hash, const YYLTYPE *loc);
-static NODE *new_defined(struct parser_params *p, NODE *expr, const YYLTYPE *loc);
+static NODE *new_defined(struct parser_params *p, NODE *expr, const YYLTYPE *loc, const YYLTYPE *keyword_loc);
-static NODE *new_regexp(struct parser_params *, NODE *, int, const YYLTYPE *);
+static NODE *new_regexp(struct parser_params *, NODE *, int, const YYLTYPE *, const YYLTYPE *, const YYLTYPE *, const YYLTYPE *);
#define make_list(list, loc) ((list) ? (nd_set_loc(list, loc), list) : NEW_ZLIST(loc))
@@ -1484,18 +1486,17 @@ static rb_ast_id_table_t *local_tbl(struct parser_params*);
static VALUE reg_compile(struct parser_params*, rb_parser_string_t*, int);
static void reg_fragment_setenc(struct parser_params*, rb_parser_string_t*, int);
-#define reg_fragment_check rb_parser_reg_fragment_check
-int reg_fragment_check(struct parser_params*, rb_parser_string_t*, int);
static int literal_concat0(struct parser_params *p, rb_parser_string_t *head, rb_parser_string_t *tail);
static NODE *heredoc_dedent(struct parser_params*,NODE*);
static void check_literal_when(struct parser_params *p, NODE *args, const YYLTYPE *loc);
+static rb_locations_lambda_body_t* new_locations_lambda_body(struct parser_params *p, NODE *node, const YYLTYPE *loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc);
+
#ifdef RIPPER
#define get_value(idx) (rb_ary_entry(p->s_value_stack, idx))
#define set_value(val) (p->s_lvalue = val)
-static VALUE backref_error(struct parser_params*, NODE *, VALUE);
static VALUE assign_error(struct parser_params *p, const char *mesg, VALUE a);
static int id_is_var(struct parser_params *p, ID id);
#endif
@@ -1516,9 +1517,10 @@ YYLTYPE *rb_parser_set_location(struct parser_params *p, YYLTYPE *yylloc);
void ruby_show_error_line(struct parser_params *p, VALUE errbuf, const YYLTYPE *yylloc, int lineno, rb_parser_string_t *str);
RUBY_SYMBOL_EXPORT_END
+static void flush_string_content(struct parser_params *p, rb_encoding *enc, size_t back);
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 ID formal_argument(struct parser_params*, ID);
+static VALUE formal_argument_error(struct parser_params*, ID);
static ID shadowing_lvar(struct parser_params*,ID);
static void new_bv(struct parser_params*,ID);
@@ -1572,7 +1574,7 @@ static void numparam_pop(struct parser_params *p, NODE *prev_inner);
#define CASE_LABELS_ENABLED_P(case_labels) (case_labels && case_labels != CHECK_LITERAL_WHEN)
#define yytnamerr(yyres, yystr) (YYSIZE_T)rb_yytnamerr(p, yyres, yystr)
-size_t rb_yytnamerr(struct parser_params *p, char *yyres, const char *yystr);
+RUBY_FUNC_EXPORTED size_t rb_yytnamerr(struct parser_params *p, char *yyres, const char *yystr);
#define TOKEN2ID(tok) ( \
tTOKEN_LOCAL_BEGIN<(tok)&&(tok)<tTOKEN_LOCAL_END ? TOKEN2LOCALID(tok) : \
@@ -1601,18 +1603,16 @@ static VALUE ripper_dispatch5(struct parser_params*,ID,VALUE,VALUE,VALUE,VALUE,V
static VALUE ripper_dispatch7(struct parser_params*,ID,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE,VALUE);
void ripper_error(struct parser_params *p);
-#define dispatch0(n) ripper_dispatch0(p, TOKEN_PASTE(ripper_id_, n))
-#define dispatch1(n,a) ripper_dispatch1(p, TOKEN_PASTE(ripper_id_, n), (a))
-#define dispatch2(n,a,b) ripper_dispatch2(p, TOKEN_PASTE(ripper_id_, n), (a), (b))
-#define dispatch3(n,a,b,c) ripper_dispatch3(p, TOKEN_PASTE(ripper_id_, n), (a), (b), (c))
-#define dispatch4(n,a,b,c,d) ripper_dispatch4(p, TOKEN_PASTE(ripper_id_, n), (a), (b), (c), (d))
-#define dispatch5(n,a,b,c,d,e) ripper_dispatch5(p, TOKEN_PASTE(ripper_id_, n), (a), (b), (c), (d), (e))
-#define dispatch7(n,a,b,c,d,e,f,g) ripper_dispatch7(p, TOKEN_PASTE(ripper_id_, n), (a), (b), (c), (d), (e), (f), (g))
+#define dispatch0(n) ripper_dispatch0(p, RIPPER_ID(n))
+#define dispatch1(n,a) ripper_dispatch1(p, RIPPER_ID(n), (a))
+#define dispatch2(n,a,b) ripper_dispatch2(p, RIPPER_ID(n), (a), (b))
+#define dispatch3(n,a,b,c) ripper_dispatch3(p, RIPPER_ID(n), (a), (b), (c))
+#define dispatch4(n,a,b,c,d) ripper_dispatch4(p, RIPPER_ID(n), (a), (b), (c), (d))
+#define dispatch5(n,a,b,c,d,e) ripper_dispatch5(p, RIPPER_ID(n), (a), (b), (c), (d), (e))
+#define dispatch7(n,a,b,c,d,e,f,g) ripper_dispatch7(p, RIPPER_ID(n), (a), (b), (c), (d), (e), (f), (g))
#define yyparse ripper_yyparse
-static VALUE ripper_formal_argument(struct parser_params *p, ID id, VALUE lhs);
-
static VALUE
aryptn_pre_args(struct parser_params *p, VALUE pre_arg, VALUE pre_args)
{
@@ -1634,11 +1634,11 @@ aryptn_pre_args(struct parser_params *p, VALUE pre_arg, VALUE pre_args)
#define KWD2EID(t, v) keyword_##t
static NODE *
-new_scope_body(struct parser_params *p, rb_node_args_t *args, NODE *body, const YYLTYPE *loc)
+new_scope_body(struct parser_params *p, rb_node_args_t *args, NODE *body, NODE *parent, const YYLTYPE *loc)
{
body = remove_begin(body);
reduce_nodes(p, &body);
- NODE *n = NEW_SCOPE(args, body, loc);
+ NODE *n = NEW_SCOPE(args, body, parent, loc);
nd_set_line(n, loc->end_pos.lineno);
set_line_body(body, loc->beg_pos.lineno);
return n;
@@ -1649,7 +1649,7 @@ 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);
+ rescue = NEW_RESBODY(0, 0, remove_begin(rescue), 0, &loc);
loc.beg_pos = arg_loc->beg_pos;
return NEW_RESCUE(arg, rescue, 0, &loc);
}
@@ -1671,7 +1671,6 @@ restore_defun(struct parser_params *p, rb_node_def_temp_t *temp)
{
/* See: def_name action */
struct lex_context ctxt = temp->save.ctxt;
- p->cur_arg = temp->save.cur_arg;
p->ctxt.in_def = ctxt.in_def;
p->ctxt.shareable_constant_value = ctxt.shareable_constant_value;
p->ctxt.in_rescue = ctxt.in_rescue;
@@ -1702,12 +1701,17 @@ endless_method_name(struct parser_params *p, ID mid, const YYLTYPE *loc)
#define begin_definition(k, loc_beg, loc_end) \
do { \
if (!(p->ctxt.in_class = (k)[0] != 0)) { \
+ /* singleton class */ \
+ p->ctxt.cant_return = !p->ctxt.in_def; \
p->ctxt.in_def = 0; \
} \
else if (p->ctxt.in_def) { \
YYLTYPE loc = code_loc_gen(loc_beg, loc_end); \
yyerror1(&loc, k " definition in method body"); \
} \
+ else { \
+ p->ctxt.cant_return = 1; \
+ } \
local_push(p, 0); \
} while (0)
@@ -1747,7 +1751,6 @@ extern const ID id_warn, id_warning, id_gets, id_assoc;
# define WARN_I(i) INT2NUM(i)
# define WARN_ID(i) rb_id2str(i)
# define PRIsWARN PRIsVALUE
-# 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
@@ -1772,7 +1775,6 @@ extern const ID id_warn, id_warning, id_gets, id_assoc;
# 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
@@ -1780,13 +1782,6 @@ PRINTF_ARGS(static void parser_compile_error(struct parser_params*, const rb_cod
# define compile_error(p, ...) parser_compile_error(p, NULL, __VA_ARGS__)
#endif
-struct RNode_EXITS {
- NODE node;
-
- NODE *nd_chain; /* Assume NODE_BREAK, NODE_NEXT, NODE_REDO have nd_chain here */
- NODE *nd_end;
-};
-
#define RNODE_EXITS(node) ((rb_node_exits_t*)(node))
static NODE *
@@ -1799,14 +1794,14 @@ add_block_exit(struct parser_params *p, NODE *node)
switch (nd_type(node)) {
case NODE_BREAK: case NODE_NEXT: case NODE_REDO: break;
default:
- compile_error(p, "unexpected node: %s", parser_node_name(nd_type(node)));
+ compile_error(p, "add_block_exit: unexpected node: %s", parser_node_name(nd_type(node)));
return node;
}
if (!p->ctxt.in_defined) {
rb_node_exits_t *exits = p->exits;
if (exits) {
- RNODE_EXITS(exits->nd_end)->nd_chain = node;
- exits->nd_end = node;
+ RNODE_EXITS(exits->nd_stts)->nd_chain = node;
+ exits->nd_stts = node;
}
}
return node;
@@ -1818,7 +1813,7 @@ init_block_exit(struct parser_params *p)
rb_node_exits_t *old = p->exits;
rb_node_exits_t *exits = NODE_NEW_INTERNAL(NODE_EXITS, rb_node_exits_t);
exits->nd_chain = 0;
- exits->nd_end = RNODE(exits);
+ exits->nd_stts = RNODE(exits);
p->exits = exits;
return old;
}
@@ -1842,7 +1837,7 @@ clear_block_exit(struct parser_params *p, bool error)
{
rb_node_exits_t *exits = p->exits;
if (!exits) return;
- if (error && !compile_for_eval) {
+ if (error) {
for (NODE *e = RNODE(exits); (e = RNODE_EXITS(e)->nd_chain) != 0; ) {
switch (nd_type(e)) {
case NODE_BREAK:
@@ -1861,7 +1856,7 @@ clear_block_exit(struct parser_params *p, bool error)
}
end_checks:;
}
- exits->nd_end = RNODE(exits);
+ exits->nd_stts = RNODE(exits);
exits->nd_chain = 0;
}
@@ -1890,7 +1885,7 @@ get_nd_value(struct parser_params *p, NODE *node)
case NODE_CDECL:
return RNODE_CDECL(node)->nd_value;
default:
- compile_error(p, "unexpected node: %s", parser_node_name(nd_type(node)));
+ compile_error(p, "get_nd_value: unexpected node: %s", parser_node_name(nd_type(node)));
return 0;
}
}
@@ -1921,7 +1916,7 @@ set_nd_value(struct parser_params *p, NODE *node, NODE *rhs)
RNODE_CVASGN(node)->nd_value = rhs;
break;
default:
- compile_error(p, "unexpected node: %s", parser_node_name(nd_type(node)));
+ compile_error(p, "set_nd_value: unexpected node: %s", parser_node_name(nd_type(node)));
break;
}
}
@@ -1943,7 +1938,7 @@ get_nd_vid(struct parser_params *p, NODE *node)
case NODE_CVASGN:
return RNODE_CVASGN(node)->nd_vid;
default:
- compile_error(p, "unexpected node: %s", parser_node_name(nd_type(node)));
+ compile_error(p, "get_nd_vid: unexpected node: %s", parser_node_name(nd_type(node)));
return 0;
}
}
@@ -1970,7 +1965,7 @@ get_nd_args(struct parser_params *p, NODE *node)
case NODE_NEXT:
return 0;
default:
- compile_error(p, "unexpected node: %s", parser_node_name(nd_type(node)));
+ compile_error(p, "get_nd_args: unexpected node: %s", parser_node_name(nd_type(node)));
return 0;
}
}
@@ -2010,10 +2005,10 @@ parser_memhash(const void *ptr, long len)
((ptrvar) = str->ptr, \
(lenvar) = str->len)
-static inline bool
-parser_string_end_with_newline_p(struct parser_params *p, rb_parser_string_t *str)
+static inline int
+parser_string_char_at_end(struct parser_params *p, rb_parser_string_t *str, int when_empty)
{
- return PARSER_STRING_LEN(str) > 0 && PARSER_STRING_END(str)[-1] == '\n';
+ return PARSER_STRING_LEN(str) > 0 ? (unsigned char)PARSER_STRING_END(str)[-1] : when_empty;
}
static rb_parser_string_t *
@@ -2054,15 +2049,15 @@ rb_str_to_parser_string(rb_parser_t *p, VALUE str)
RB_GC_GUARD(str);
return ret;
}
-#endif
-static void
+void
rb_parser_string_free(rb_parser_t *p, rb_parser_string_t *str)
{
if (!str) return;
xfree(PARSER_STRING_PTR(str));
xfree(str);
}
+#endif
static st_index_t
rb_parser_str_hash(rb_parser_string_t *str)
@@ -2209,8 +2204,7 @@ rb_parser_enc_associate(struct parser_params *p, rb_parser_string_t *str, rb_enc
{
if (rb_parser_str_get_encoding(str) == enc)
return str;
- if (!PARSER_ENC_CODERANGE_ASCIIONLY(str) ||
- !rb_enc_asciicompat(enc)) {
+ if (!PARSER_ENC_CODERANGE_ASCIIONLY(str)) {
PARSER_ENC_CODERANGE_CLEAR(str);
}
rb_parser_string_set_encoding(str, enc);
@@ -2223,30 +2217,25 @@ rb_parser_is_ascii_string(struct parser_params *p, rb_parser_string_t *str)
return rb_parser_enc_str_coderange(p, str) == RB_PARSER_ENC_CODERANGE_7BIT;
}
-static int
-rb_parser_enc_str_asciionly_p(struct parser_params *p, rb_parser_string_t *str)
+static rb_encoding *
+rb_parser_enc_compatible(struct parser_params *p, rb_parser_string_t *str1, rb_parser_string_t *str2)
{
- rb_encoding *enc = rb_parser_str_get_encoding(str);
+ rb_encoding *enc1 = rb_parser_str_get_encoding(str1);
+ rb_encoding *enc2 = rb_parser_str_get_encoding(str2);
- if (!rb_enc_asciicompat(enc))
- return FALSE;
- else if (rb_parser_is_ascii_string(p, str))
- return TRUE;
- return FALSE;
-}
+ if (enc1 == NULL || enc2 == NULL)
+ return 0;
-static rb_encoding *
-rb_parser_enc_compatible_latter(struct parser_params *p, rb_parser_string_t *str1, rb_parser_string_t *str2, rb_encoding *enc1, rb_encoding *enc2)
-{
- int cr1, cr2;
+ if (enc1 == enc2) {
+ return enc1;
+ }
if (PARSER_STRING_LEN(str2) == 0)
return enc1;
if (PARSER_STRING_LEN(str1) == 0)
- return (rb_enc_asciicompat(enc1) && rb_parser_enc_str_asciionly_p(p, str2)) ? enc1 : enc2;
- if (!rb_enc_asciicompat(enc1) || !rb_enc_asciicompat(enc2)) {
- return 0;
- }
+ return rb_parser_is_ascii_string(p, str2) ? enc1 : enc2;
+
+ int cr1, cr2;
cr1 = rb_parser_enc_str_coderange(p, str1);
cr2 = rb_parser_enc_str_coderange(p, str2);
@@ -2267,22 +2256,6 @@ rb_parser_enc_compatible_latter(struct parser_params *p, rb_parser_string_t *str
return 0;
}
-static rb_encoding *
-rb_parser_enc_compatible(struct parser_params *p, rb_parser_string_t *str1, rb_parser_string_t *str2)
-{
- rb_encoding *enc1 = rb_parser_str_get_encoding(str1);
- rb_encoding *enc2 = rb_parser_str_get_encoding(str2);
-
- if (enc1 == NULL || enc2 == NULL)
- return 0;
-
- if (enc1 == enc2) {
- return enc1;
- }
-
- return rb_parser_enc_compatible_latter(p, str1, str2, enc1, enc2);
-}
-
static void
rb_parser_str_modify(rb_parser_string_t *str)
{
@@ -2350,6 +2323,9 @@ rb_parser_str_buf_cat(struct parser_params *p, rb_parser_string_t *str, const ch
return str;
}
+#define parser_str_cat(str, ptr, len) rb_parser_str_buf_cat(p, str, ptr, len)
+#define parser_str_cat_cstr(str, lit) rb_parser_str_buf_cat(p, str, lit, strlen(lit))
+
static rb_parser_string_t *
rb_parser_enc_cr_str_buf_cat(struct parser_params *p, rb_parser_string_t *str, const char *ptr, long len,
rb_encoding *ptr_enc, int ptr_cr, int *ptr_cr_ret)
@@ -2415,7 +2391,7 @@ rb_parser_enc_cr_str_buf_cat(struct parser_params *p, rb_parser_string_t *str, c
if (len < 0) {
compile_error(p, "negative string size (or size too big)");
}
- rb_parser_str_buf_cat(p, str, ptr, len);
+ parser_str_cat(str, ptr, len);
PARSER_ENCODING_CODERANGE_SET(str, res_enc, res_cr);
return str;
@@ -2493,7 +2469,6 @@ rb_parser_string_hash_cmp(rb_parser_string_t *str1, rb_parser_string_t *str2)
memcmp(ptr1, ptr2, len1) != 0);
}
-#ifndef RIPPER
static void
rb_parser_ary_extend(rb_parser_t *p, rb_parser_ary_t *ary, long len)
{
@@ -2509,7 +2484,7 @@ rb_parser_ary_extend(rb_parser_t *p, rb_parser_ary_t *ary, long len)
/*
* Do not call this directly.
- * Use rb_parser_ary_new_capa_for_script_line() or rb_parser_ary_new_capa_for_ast_token() instead.
+ * Use rb_parser_ary_new_capa_for_XXX() instead.
*/
static rb_parser_ary_t *
parser_ary_new_capa(rb_parser_t *p, long len)
@@ -2518,6 +2493,7 @@ parser_ary_new_capa(rb_parser_t *p, long len)
rb_bug("negative array size (or size too big): %ld", len);
}
rb_parser_ary_t *ary = xcalloc(1, sizeof(rb_parser_ary_t));
+ ary->data_type = 0;
ary->len = 0;
ary->capa = len;
if (0 < len) {
@@ -2529,6 +2505,7 @@ parser_ary_new_capa(rb_parser_t *p, long len)
return ary;
}
+#ifndef RIPPER
static rb_parser_ary_t *
rb_parser_ary_new_capa_for_script_line(rb_parser_t *p, long len)
{
@@ -2544,10 +2521,19 @@ rb_parser_ary_new_capa_for_ast_token(rb_parser_t *p, long len)
ary->data_type = PARSER_ARY_DATA_AST_TOKEN;
return ary;
}
+#endif
+
+static rb_parser_ary_t *
+rb_parser_ary_new_capa_for_node(rb_parser_t *p, long len)
+{
+ rb_parser_ary_t *ary = parser_ary_new_capa(p, len);
+ ary->data_type = PARSER_ARY_DATA_NODE;
+ return ary;
+}
/*
* Do not call this directly.
- * Use rb_parser_ary_push_script_line() or rb_parser_ary_push_ast_token() instead.
+ * Use rb_parser_ary_push_XXX() instead.
*/
static rb_parser_ary_t *
parser_ary_push(rb_parser_t *p, rb_parser_ary_t *ary, rb_parser_ary_data val)
@@ -2559,6 +2545,7 @@ parser_ary_push(rb_parser_t *p, rb_parser_ary_t *ary, rb_parser_ary_data val)
return ary;
}
+#ifndef RIPPER
static rb_parser_ary_t *
rb_parser_ary_push_ast_token(rb_parser_t *p, rb_parser_ary_t *ary, rb_parser_ast_token_t *val)
{
@@ -2576,7 +2563,18 @@ rb_parser_ary_push_script_line(rb_parser_t *p, rb_parser_ary_t *ary, rb_parser_s
}
return parser_ary_push(p, ary, val);
}
+#endif
+
+static rb_parser_ary_t *
+rb_parser_ary_push_node(rb_parser_t *p, rb_parser_ary_t *ary, NODE *val)
+{
+ if (ary->data_type != PARSER_ARY_DATA_NODE) {
+ rb_bug("unexpected rb_parser_ary_data_type: %d", ary->data_type);
+ }
+ return parser_ary_push(p, ary, val);
+}
+#ifndef RIPPER
static void
rb_parser_ast_token_free(rb_parser_t *p, rb_parser_ast_token_t *token)
{
@@ -2598,11 +2596,15 @@ rb_parser_ary_free(rb_parser_t *p, rb_parser_ary_t *ary)
case PARSER_ARY_DATA_SCRIPT_LINE:
foreach_ary(data) {rb_parser_string_free(p, *data);}
break;
+ case PARSER_ARY_DATA_NODE:
+ /* Do nothing because nodes are freed when rb_ast_t is freed */
+ break;
default:
rb_bug("unexpected rb_parser_ary_data_type: %d", ary->data_type);
break;
}
# undef foreach_ary
+ xfree(ary->data);
xfree(ary);
}
@@ -2676,6 +2678,7 @@ rb_parser_ary_free(rb_parser_t *p, rb_parser_ary_t *ary)
rb_node_masgn_t *node_masgn;
rb_node_def_temp_t *node_def_temp;
rb_node_exits_t *node_exits;
+ struct rb_locations_lambda_body_t *locations_lambda_body;
ID id;
int num;
st_table *tbl;
@@ -2755,14 +2758,15 @@ rb_parser_ary_free(rb_parser_t *p, rb_parser_ary_t *ary)
%token <num> tREGEXP_END
%token <num> tDUMNY_END "dummy end"
-%type <node> singleton strings string string1 xstring regexp
+%type <node> singleton singleton_expr strings string string1 xstring regexp
%type <node> string_contents xstring_contents regexp_contents string_content
%type <node> words symbols symbol_list qwords qsymbols word_list qword_list qsym_list word
%type <node> literal numeric simple_numeric ssym dsym symbol cpath
%type <node_def_temp> defn_head defs_head k_def
%type <node_exits> block_open k_while k_until k_for allow_exits
-%type <node> top_compstmt top_stmts top_stmt begin_block endless_arg endless_command
-%type <node> bodystmt compstmt stmts stmt_or_begin stmt expr arg primary command command_call method_call
+%type <node> top_stmts top_stmt begin_block endless_arg endless_command
+%type <node> bodystmt stmts stmt_or_begin stmt expr arg ternary primary
+%type <node> command command_call command_call_value method_call
%type <node> expr_value expr_value_do arg_value primary_value rel_expr
%type <node_fcall> fcall
%type <node> if_tail opt_else case_body case_args cases opt_rescue exc_list exc_var opt_ensure
@@ -2776,23 +2780,23 @@ rb_parser_ary_free(rb_parser_t *p, rb_parser_ary_t *ary)
%type <node> command_asgn mrhs mrhs_arg superclass block_call block_command
%type <node_args> f_arglist f_opt_paren_args f_paren_args f_args
%type <node_args_aux> f_arg f_arg_item
-%type <node> f_marg f_marg_list f_rest_marg
+%type <node> f_marg f_rest_marg
%type <node_masgn> f_margs
%type <node> assoc_list assocs assoc undef_list backref string_dvar for_var
-%type <node_args> block_param opt_block_param block_param_def
-%type <node_kw_arg> f_kw f_block_kw
-%type <id> bv_decls opt_bv_decl bvar
-%type <node> lambda lambda_body brace_body do_body
+%type <node_args> block_param opt_block_param_def block_param_def opt_block_param
+%type <id> do bv_decls opt_bv_decl bvar
+%type <node> lambda brace_body do_body
+%type <locations_lambda_body> lambda_body
%type <node_args> f_larglist
%type <node> brace_block cmd_brace_block do_block lhs none fitem
-%type <node> mlhs_head mlhs_item mlhs_node mlhs_post
+%type <node> mlhs_head mlhs_item mlhs_node
%type <node_masgn> mlhs mlhs_basic mlhs_inner
%type <node> p_case_body p_cases p_top_expr p_top_expr_body
%type <node> p_expr p_as p_alt p_expr_basic p_find
%type <node> p_args p_args_head p_args_tail p_args_post p_arg p_rest
%type <node> p_value p_primitive p_variable p_var_ref p_expr_ref p_const
%type <node> p_kwargs p_kwarg p_kw
-%type <id> keyword_variable user_variable sym operation operation2 operation3
+%type <id> keyword_variable user_variable sym operation2 operation3
%type <id> cname fname op f_rest_arg f_block_arg opt_f_block_arg f_norm_arg f_bad_arg
%type <id> f_kwrest f_label f_arg_asgn call_op call_op2 reswords relop dot_or_colon
%type <id> p_kwrest p_kwnorest p_any_kwrest p_kw_label
@@ -2841,7 +2845,6 @@ rb_parser_ary_free(rb_parser_t *p, rb_parser_ary_t *ary)
%token tASSOC "=>"
%token tLPAREN "("
%token tLPAREN_ARG "( arg"
-%token tRPAREN ")"
%token tLBRACK "["
%token tLBRACE "{"
%token tLBRACE_ARG "{ arg"
@@ -2896,59 +2899,262 @@ rb_parser_ary_free(rb_parser_t *p, rb_parser_ary_t *ary)
%token tLAST_TOKEN
/*
+ * inlining rules
+ */
+%rule %inline ident_or_const
+ : tIDENTIFIER
+ | tCONSTANT
+ ;
+
+%rule %inline user_or_keyword_variable
+ : user_variable
+ | keyword_variable
+ ;
+
+/*
* parameterizing rules
*/
-%rule f_opt(value) <node_opt_arg>: f_arg_asgn f_eq value
- {
- p->cur_arg = 0;
- p->ctxt.in_argdef = 1;
- $$ = NEW_OPT_ARG(assignable(p, $1, $3, &@$), &@$);
- /*% ripper: [$:$, $:3] %*/
- }
- ;
-
-%rule f_optarg(value) <node_opt_arg>: f_opt(value)
- {
- $$ = $1;
- /*% ripper: rb_ary_new3(1, $:1) %*/
- }
- | f_optarg(value) ',' f_opt(value)
- {
- $$ = opt_arg_append($1, $3);
- /*% ripper: rb_ary_push($:1, $:3) %*/
- }
- ;
-
-%rule f_kwarg(kw) <node_kw_arg>: kw
- {
- $$ = $1;
- /*% ripper: rb_ary_new3(1, $:1) %*/
- }
- | f_kwarg(kw) ',' kw
- {
- $$ = kwd_append($1, $3);
- /*% ripper: rb_ary_push($:1, $:3) %*/
- }
- ;
-
-%rule opt_args_tail(tail) <node_args>: ',' tail
- {
- $$ = $2;
- /*% ripper: $:2 %*/
- }
- | /* none */
- {
- $$ = new_args_tail(p, 0, 0, 0, &@0);
- /*% ripper: [Qnil, Qnil, Qnil] %*/
- }
- ;
-
-%rule words(begin, word_list): begin ' '+ word_list tSTRING_END
- {
- $$ = make_list($3, &@$);
- /*% ripper: array!($:3) %*/
- }
- ;
+%rule asgn(rhs) <node>
+ : lhs '=' lex_ctxt rhs
+ {
+ $$ = node_assign(p, (NODE *)$lhs, $rhs, $lex_ctxt, &@$);
+ /*% ripper: assign!($:1, $:4) %*/
+ }
+ ;
+
+%rule args_tail_basic(value) <node_args>
+ : f_kwarg(value) ',' f_kwrest opt_f_block_arg
+ {
+ $$ = new_args_tail(p, $1, $3, $4, &@3);
+ /*% ripper: [$:1, $:3, $:4] %*/
+ }
+ | f_kwarg(value) opt_f_block_arg
+ {
+ $$ = new_args_tail(p, $1, 0, $2, &@1);
+ /*% ripper: [$:1, Qnil, $:2] %*/
+ }
+ | f_any_kwrest opt_f_block_arg
+ {
+ $$ = new_args_tail(p, 0, $1, $2, &@1);
+ /*% ripper: [Qnil, $:1, $:2] %*/
+ }
+ | f_block_arg
+ {
+ $$ = new_args_tail(p, 0, 0, $1, &@1);
+ /*% ripper: [Qnil, Qnil, $:1] %*/
+ }
+ ;
+
+%rule def_endless_method(bodystmt) <node>
+ : defn_head[head] f_opt_paren_args[args] '=' bodystmt
+ {
+ endless_method_name(p, $head->nd_mid, &@head);
+ restore_defun(p, $head);
+ ($$ = $head->nd_def)->nd_loc = @$;
+ $bodystmt = new_scope_body(p, $args, $bodystmt, $$, &@$);
+ RNODE_DEFN($$)->nd_defn = $bodystmt;
+ /*% ripper: bodystmt!($:bodystmt, Qnil, Qnil, Qnil) %*/
+ /*% ripper: def!($:head, $:args, $:$) %*/
+ local_pop(p);
+ }
+ | defs_head[head] f_opt_paren_args[args] '=' bodystmt
+ {
+ endless_method_name(p, $head->nd_mid, &@head);
+ restore_defun(p, $head);
+ ($$ = $head->nd_def)->nd_loc = @$;
+ $bodystmt = new_scope_body(p, $args, $bodystmt, $$, &@$);
+ RNODE_DEFS($$)->nd_defn = $bodystmt;
+ /*% ripper: bodystmt!($:bodystmt, Qnil, Qnil, Qnil) %*/
+ /*% ripper: defs!(*$:head[0..2], $:args, $:$) %*/
+ local_pop(p);
+ }
+ ;
+
+%rule compstmt(stmts) <node>
+ : stmts terms?
+ {
+ void_stmts(p, $$ = $stmts);
+ }
+ ;
+
+%rule f_opt(value) <node_opt_arg>
+ : f_arg_asgn f_eq value
+ {
+ p->ctxt.in_argdef = 1;
+ $$ = NEW_OPT_ARG(assignable(p, $f_arg_asgn, $value, &@$), &@$);
+ /*% ripper: [$:$, $:3] %*/
+ }
+ ;
+
+%rule f_opt_arg(value) <node_opt_arg>
+ : f_opt(value)
+ {
+ $$ = $f_opt;
+ /*% ripper: rb_ary_new3(1, $:1) %*/
+ }
+ | f_opt_arg(value) ',' f_opt(value)
+ {
+ $$ = opt_arg_append($f_opt_arg, $f_opt);
+ /*% ripper: rb_ary_push($:1, $:3) %*/
+ }
+ ;
+
+%rule f_kw(value) <node_kw_arg>
+ : f_label value
+ {
+ p->ctxt.in_argdef = 1;
+ $$ = new_kw_arg(p, assignable(p, $f_label, $value, &@$), &@$);
+ /*% ripper: [$:$, $:value] %*/
+ }
+ | f_label
+ {
+ p->ctxt.in_argdef = 1;
+ $$ = new_kw_arg(p, assignable(p, $f_label, NODE_SPECIAL_REQUIRED_KEYWORD, &@$), &@$);
+ /*% ripper: [$:$, 0] %*/
+ }
+ ;
+
+%rule f_kwarg(value) <node_kw_arg>
+ : f_kw(value)
+ {
+ $$ = $f_kw;
+ /*% ripper: rb_ary_new3(1, $:1) %*/
+ }
+ | f_kwarg(value) ',' f_kw(value)
+ {
+ $$ = kwd_append($f_kwarg, $f_kw);
+ /*% ripper: rb_ary_push($:1, $:3) %*/
+ }
+ ;
+
+%rule mlhs_items(item) <node>
+ : item
+ {
+ $$ = NEW_LIST($1, &@$);
+ /*% ripper: mlhs_add!(mlhs_new!, $:1) %*/
+ }
+ | mlhs_items(item) ',' item
+ {
+ $$ = list_append(p, $1, $3);
+ /*% ripper: mlhs_add!($:1, $:3) %*/
+ }
+ ;
+
+%rule op_asgn(rhs) <node>
+ : var_lhs tOP_ASGN lex_ctxt rhs
+ {
+ $$ = new_op_assign(p, $var_lhs, $tOP_ASGN, $rhs, $lex_ctxt, &@$);
+ /*% ripper: opassign!($:1, $:2, $:4) %*/
+ }
+ | primary_value '['[lbracket] opt_call_args rbracket tOP_ASGN lex_ctxt rhs
+ {
+ $$ = new_ary_op_assign(p, $primary_value, $opt_call_args, $tOP_ASGN, $rhs, &@opt_call_args, &@$, &NULL_LOC, &@lbracket, &@rbracket, &@tOP_ASGN);
+ /*% ripper: opassign!(aref_field!($:1, $:3), $:5, $:7) %*/
+ }
+ | primary_value call_op tIDENTIFIER tOP_ASGN lex_ctxt rhs
+ {
+ $$ = new_attr_op_assign(p, $primary_value, $call_op, $tIDENTIFIER, $tOP_ASGN, $rhs, &@$, &@call_op, &@tIDENTIFIER, &@tOP_ASGN);
+ /*% ripper: opassign!(field!($:1, $:2, $:3), $:4, $:6) %*/
+ }
+ | primary_value call_op tCONSTANT tOP_ASGN lex_ctxt rhs
+ {
+ $$ = new_attr_op_assign(p, $primary_value, $call_op, $tCONSTANT, $tOP_ASGN, $rhs, &@$, &@call_op, &@tCONSTANT, &@tOP_ASGN);
+ /*% ripper: opassign!(field!($:1, $:2, $:3), $:4, $:6) %*/
+ }
+ | primary_value tCOLON2 tIDENTIFIER tOP_ASGN lex_ctxt rhs
+ {
+ $$ = new_attr_op_assign(p, $primary_value, idCOLON2, $tIDENTIFIER, $tOP_ASGN, $rhs, &@$, &@tCOLON2, &@tIDENTIFIER, &@tOP_ASGN);
+ /*% ripper: opassign!(field!($:1, $:2, $:3), $:4, $:6) %*/
+ }
+ | primary_value tCOLON2 tCONSTANT tOP_ASGN lex_ctxt rhs
+ {
+ YYLTYPE loc = code_loc_gen(&@primary_value, &@tCONSTANT);
+ $$ = new_const_op_assign(p, NEW_COLON2($primary_value, $tCONSTANT, &loc, &@tCOLON2, &@tCONSTANT), $tOP_ASGN, $rhs, $lex_ctxt, &@$);
+ /*% ripper: opassign!(const_path_field!($:1, $:3), $:4, $:6) %*/
+ }
+ | tCOLON3 tCONSTANT tOP_ASGN lex_ctxt rhs
+ {
+ YYLTYPE loc = code_loc_gen(&@tCOLON3, &@tCONSTANT);
+ $$ = new_const_op_assign(p, NEW_COLON3($tCONSTANT, &loc, &@tCOLON3, &@tCONSTANT), $tOP_ASGN, $rhs, $lex_ctxt, &@$);
+ /*% ripper: opassign!(top_const_field!($:2), $:3, $:5) %*/
+ }
+ | backref tOP_ASGN lex_ctxt rhs
+ {
+ VALUE MAYBE_UNUSED(e) = rb_backref_error(p, $backref);
+ $$ = NEW_ERROR(&@$);
+ /*% ripper[error]: assign_error!(?e, opassign!(var_field!($:1), $:2, $:4)) %*/
+ }
+ ;
+
+%rule opt_args_tail(tail) <node_args>
+ : ',' tail
+ {
+ $$ = $tail;
+ /*% ripper: $:2 %*/
+ }
+ | /* none */
+ {
+ $$ = new_args_tail(p, 0, 0, 0, &@0);
+ /*% ripper: [Qnil, Qnil, Qnil] %*/
+ }
+ ;
+
+%rule range_expr(range) <node>
+ : range tDOT2 range
+ {
+ value_expr(p, $1);
+ value_expr(p, $3);
+ $$ = NEW_DOT2($1, $3, &@$, &@2);
+ /*% ripper: dot2!($:1, $:3) %*/
+ }
+ | range tDOT3 range
+ {
+ value_expr(p, $1);
+ value_expr(p, $3);
+ $$ = NEW_DOT3($1, $3, &@$, &@2);
+ /*% ripper: dot3!($:1, $:3) %*/
+ }
+ | range tDOT2
+ {
+ value_expr(p, $1);
+ $$ = NEW_DOT2($1, new_nil_at(p, &@2.end_pos), &@$, &@2);
+ /*% ripper: dot2!($:1, Qnil) %*/
+ }
+ | range tDOT3
+ {
+ value_expr(p, $1);
+ $$ = NEW_DOT3($1, new_nil_at(p, &@2.end_pos), &@$, &@2);
+ /*% ripper: dot3!($:1, Qnil) %*/
+ }
+ | tBDOT2 range
+ {
+ value_expr(p, $2);
+ $$ = NEW_DOT2(new_nil_at(p, &@1.beg_pos), $2, &@$, &@1);
+ /*% ripper: dot2!(Qnil, $:2) %*/
+ }
+ | tBDOT3 range
+ {
+ value_expr(p, $2);
+ $$ = NEW_DOT3(new_nil_at(p, &@1.beg_pos), $2, &@$, &@1);
+ /*% ripper: dot3!(Qnil, $:2) %*/
+ }
+ ;
+
+%rule value_expr(value) <node>
+ : value
+ {
+ value_expr(p, $1);
+ $$ = $1;
+ }
+ ;
+
+%rule words(begin, word_list) <node>
+ : begin ' '+ word_list tSTRING_END
+ {
+ $$ = make_list($word_list, &@$);
+ /*% ripper: array!($:3) %*/
+ }
+ ;
%%
program : {
@@ -2957,7 +3163,7 @@ program : {
/* jumps are possible in the top-level loop. */
if (!ifndef_ripper(p->do_loop) + 0) init_block_exit(p);
}
- top_compstmt
+ compstmt(top_stmts)
{
if ($2 && !compile_for_eval) {
NODE *node = $2;
@@ -2971,18 +3177,12 @@ program : {
node = remove_begin(node);
void_expr(p, node);
}
- p->eval_tree = NEW_SCOPE(0, block_append(p, p->eval_tree, $2), &@$);
+ p->eval_tree = NEW_SCOPE(0, block_append(p, p->eval_tree, $2), NULL, &@$);
/*% ripper[final]: program!($:2) %*/
local_pop(p);
}
;
-top_compstmt : top_stmts terms?
- {
- $$ = void_stmts(p, $1);
- }
- ;
-
top_stmts : none
{
$$ = NEW_BEGIN(0, &@$);
@@ -3014,7 +3214,7 @@ top_stmt : stmt
block_open : '{' {$$ = init_block_exit(p);};
-begin_block : block_open top_compstmt '}'
+begin_block : block_open compstmt(top_stmts) '}'
{
restore_block_exit(p, $block_open);
p->eval_tree_begin = block_append(p, p->eval_tree_begin,
@@ -3024,7 +3224,7 @@ begin_block : block_open top_compstmt '}'
}
;
-bodystmt : compstmt[body]
+bodystmt : compstmt(stmts)[body]
lex_ctxt[ctxt]
opt_rescue
k_else
@@ -3032,7 +3232,7 @@ bodystmt : compstmt[body]
if (!$opt_rescue) yyerror1(&@k_else, "else without rescue is useless");
next_rescue_context(&p->ctxt, &$ctxt, after_else);
}
- compstmt[elsebody]
+ compstmt(stmts)[elsebody]
{
next_rescue_context(&p->ctxt, &$ctxt, after_ensure);
}
@@ -3041,7 +3241,7 @@ bodystmt : compstmt[body]
$$ = new_bodystmt(p, $body, $opt_rescue, $elsebody, $opt_ensure, &@$);
/*% ripper: bodystmt!($:body, $:opt_rescue, $:elsebody, $:opt_ensure) %*/
}
- | compstmt[body]
+ | compstmt(stmts)[body]
lex_ctxt[ctxt]
opt_rescue
{
@@ -3054,12 +3254,6 @@ bodystmt : compstmt[body]
}
;
-compstmt : stmts terms?
- {
- $$ = void_stmts(p, $1);
- }
- ;
-
stmts : none
{
$$ = NEW_BEGIN(0, &@$);
@@ -3078,9 +3272,6 @@ stmts : none
;
stmt_or_begin : stmt
- {
- $$ = $1;
- }
| keyword_BEGIN
{
yyerror1(&@1, "BEGIN is permitted only at toplevel");
@@ -3102,12 +3293,12 @@ k_END : keyword_END lex_ctxt
stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
{
- $$ = NEW_ALIAS($2, $4, &@$);
+ $$ = NEW_ALIAS($2, $4, &@$, &@1);
/*% ripper: alias!($:2, $:4) %*/
}
| keyword_alias tGVAR tGVAR
{
- $$ = NEW_VALIAS($2, $3, &@$);
+ $$ = NEW_VALIAS($2, $3, &@$, &@1);
/*% ripper: var_alias!($:2, $:3) %*/
}
| keyword_alias tGVAR tBACK_REF
@@ -3115,7 +3306,7 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
char buf[2];
buf[0] = '$';
buf[1] = (char)RNODE_BACK_REF($3)->nd_nth;
- $$ = NEW_VALIAS($2, rb_intern2(buf, 2), &@$);
+ $$ = NEW_VALIAS($2, rb_intern2(buf, 2), &@$, &@1);
/*% ripper: var_alias!($:2, $:3) %*/
}
| keyword_alias tGVAR tNTH_REF
@@ -3129,18 +3320,20 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
}
| keyword_undef undef_list
{
+ nd_set_first_loc($2, @1.beg_pos);
+ RNODE_UNDEF($2)->keyword_loc = @1;
$$ = $2;
/*% ripper: undef!($:2) %*/
}
| stmt modifier_if expr_value
{
- $$ = new_if(p, $3, remove_begin($1), 0, &@$);
+ $$ = new_if(p, $3, remove_begin($1), 0, &@$, &@2, &NULL_LOC, &NULL_LOC);
fixpos($$, $3);
/*% ripper: if_mod!($:3, $:1) %*/
}
| stmt modifier_unless expr_value
{
- $$ = new_unless(p, $3, remove_begin($1), 0, &@$);
+ $$ = new_unless(p, $3, remove_begin($1), 0, &@$, &@2, &NULL_LOC, &NULL_LOC);
fixpos($$, $3);
/*% ripper: unless_mod!($:3, $:1) %*/
}
@@ -3148,10 +3341,10 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
{
clear_block_exit(p, false);
if ($1 && nd_type_p($1, NODE_BEGIN)) {
- $$ = NEW_WHILE(cond(p, $3, &@3), RNODE_BEGIN($1)->nd_body, 0, &@$);
+ $$ = NEW_WHILE(cond(p, $3, &@3), RNODE_BEGIN($1)->nd_body, 0, &@$, &@2, &NULL_LOC);
}
else {
- $$ = NEW_WHILE(cond(p, $3, &@3), $1, 1, &@$);
+ $$ = NEW_WHILE(cond(p, $3, &@3), $1, 1, &@$, &@2, &NULL_LOC);
}
/*% ripper: while_mod!($:3, $:1) %*/
}
@@ -3159,10 +3352,10 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
{
clear_block_exit(p, false);
if ($1 && nd_type_p($1, NODE_BEGIN)) {
- $$ = NEW_UNTIL(cond(p, $3, &@3), RNODE_BEGIN($1)->nd_body, 0, &@$);
+ $$ = NEW_UNTIL(cond(p, $3, &@3), RNODE_BEGIN($1)->nd_body, 0, &@$, &@2, &NULL_LOC);
}
else {
- $$ = NEW_UNTIL(cond(p, $3, &@3), $1, 1, &@$);
+ $$ = NEW_UNTIL(cond(p, $3, &@3), $1, 1, &@$, &@2, &NULL_LOC);
}
/*% ripper: until_mod!($:3, $:1) %*/
}
@@ -3171,11 +3364,11 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
p->ctxt.in_rescue = $3.in_rescue;
NODE *resq;
YYLTYPE loc = code_loc_gen(&@2, &@4);
- resq = NEW_RESBODY(0, remove_begin($4), 0, &loc);
+ resq = NEW_RESBODY(0, 0, remove_begin($4), 0, &loc);
$$ = NEW_RESCUE(remove_begin($1), resq, 0, &@$);
/*% ripper: rescue_mod!($:1, $:4) %*/
}
- | k_END allow_exits '{' compstmt '}'
+ | k_END allow_exits '{' compstmt(stmts) '}'
{
if (p->ctxt.in_def) {
rb_warn0("END in method; use at_exit");
@@ -3183,29 +3376,25 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
restore_block_exit(p, $allow_exits);
p->ctxt = $k_END;
{
- NODE *scope = NEW_SCOPE2(0 /* tbl */, 0 /* args */, $compstmt /* body */, &@$);
- $$ = NEW_POSTEXE(scope, &@$);
+ NODE *scope = NEW_SCOPE2(0 /* tbl */, 0 /* args */, $compstmt /* body */, NULL /* parent */, &@$);
+ $$ = NEW_POSTEXE(scope, &@$, &@1, &@3, &@5);
+ RNODE_SCOPE(scope)->nd_parent = $$;
}
/*% ripper: END!($:compstmt) %*/
}
| command_asgn
- | mlhs '=' lex_ctxt command_call
+ | mlhs '=' lex_ctxt command_call_value
{
- value_expr($4);
$$ = node_assign(p, (NODE *)$1, $4, $3, &@$);
/*% ripper: massign!($:1, $:4) %*/
}
- | lhs '=' lex_ctxt mrhs
- {
- $$ = node_assign(p, $1, $4, $3, &@$);
- /*% ripper: assign!($:1, $:4) %*/
- }
+ | asgn(mrhs)
| mlhs '=' lex_ctxt mrhs_arg modifier_rescue
after_rescue stmt[resbody]
{
p->ctxt.in_rescue = $3.in_rescue;
YYLTYPE loc = code_loc_gen(&@modifier_rescue, &@resbody);
- $resbody = NEW_RESBODY(0, remove_begin($resbody), 0, &loc);
+ $resbody = NEW_RESBODY(0, 0, remove_begin($resbody), 0, &loc);
loc.beg_pos = @mrhs_arg.beg_pos;
$mrhs_arg = NEW_RESCUE($mrhs_arg, $resbody, 0, &loc);
$$ = node_assign(p, (NODE *)$mlhs, $mrhs_arg, $lex_ctxt, &@$);
@@ -3224,73 +3413,9 @@ stmt : keyword_alias fitem {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
}
;
-command_asgn : lhs '=' lex_ctxt command_rhs
- {
- $$ = node_assign(p, $1, $4, $3, &@$);
- /*% ripper: assign!($:1, $:4) %*/
- }
- | var_lhs tOP_ASGN lex_ctxt command_rhs
- {
- $$ = new_op_assign(p, $1, $2, $4, $3, &@$);
- /*% ripper: opassign!($:1, $:2, $:4) %*/
- }
- | primary_value '[' opt_call_args rbracket tOP_ASGN lex_ctxt command_rhs
- {
- $$ = new_ary_op_assign(p, $1, $3, $5, $7, &@3, &@$);
- /*% ripper: opassign!(aref_field!($:1, $:3), $:5, $:7) %*/
-
- }
- | primary_value call_op tIDENTIFIER tOP_ASGN lex_ctxt command_rhs
- {
- $$ = new_attr_op_assign(p, $1, $2, $3, $4, $6, &@$);
- /*% ripper: opassign!(field!($:1, $:2, $:3), $:4, $:6) %*/
- }
- | primary_value call_op tCONSTANT tOP_ASGN lex_ctxt command_rhs
- {
- $$ = new_attr_op_assign(p, $1, $2, $3, $4, $6, &@$);
- /*% ripper: opassign!(field!($:1, $:2, $:3), $:4, $:6) %*/
- }
- | 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, $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, idCOLON2, $3, $4, $6, &@$);
- /*% ripper: opassign!(field!($:1, $:2, $:3), $:4, $:6) %*/
- }
- | defn_head[head] f_opt_paren_args[args] '=' endless_command[bodystmt]
- {
- endless_method_name(p, $head->nd_mid, &@head);
- restore_defun(p, $head);
- $bodystmt = new_scope_body(p, $args, $bodystmt, &@$);
- ($$ = $head->nd_def)->nd_loc = @$;
- RNODE_DEFN($$)->nd_defn = $bodystmt;
- /*% ripper: bodystmt!($:bodystmt, Qnil, Qnil, Qnil) %*/
- /*% ripper: def!($:head, $:args, $:$) %*/
- local_pop(p);
- }
- | defs_head[head] f_opt_paren_args[args] '=' endless_command[bodystmt]
- {
- endless_method_name(p, $head->nd_mid, &@head);
- restore_defun(p, $head);
- $bodystmt = new_scope_body(p, $args, $bodystmt, &@$);
- ($$ = $head->nd_def)->nd_loc = @$;
- RNODE_DEFS($$)->nd_defn = $bodystmt;
- /*% ripper: bodystmt!($:bodystmt, Qnil, Qnil, Qnil) %*/
- /*% ripper: defs!(*$:head[0..2], $:args, $:$) %*/
- local_pop(p);
- }
- | backref tOP_ASGN lex_ctxt command_rhs
- {
- /*%%%*/
- rb_backref_error(p, $1);
- /*% %*/
- $$ = NEW_ERROR(&@$);
- /*% ripper[error]: backref_error(p, $1, opassign!(var_field!($:1), $:2, $:4)) %*/
- }
+command_asgn : asgn(command_rhs)
+ | op_asgn(command_rhs)
+ | def_endless_method(endless_command)
;
endless_command : command
@@ -3307,17 +3432,12 @@ endless_command : command
}
;
-command_rhs : command_call %prec tOP_ASGN
- {
- value_expr($1);
- $$ = $1;
- }
- | command_call modifier_rescue after_rescue stmt
+command_rhs : command_call_value %prec tOP_ASGN
+ | command_call_value modifier_rescue after_rescue stmt
{
p->ctxt.in_rescue = $3.in_rescue;
YYLTYPE loc = code_loc_gen(&@2, &@4);
- value_expr($1);
- $$ = NEW_RESCUE($1, NEW_RESBODY(0, remove_begin($4), 0, &loc), 0, &@$);
+ $$ = NEW_RESCUE($1, NEW_RESBODY(0, 0, remove_begin($4), 0, &loc), 0, &@$);
/*% ripper: rescue_mod!($:1, $:4) %*/
}
| command_asgn
@@ -3346,7 +3466,7 @@ expr : command_call
}
| arg tASSOC
{
- value_expr($arg);
+ value_expr(p, $arg);
}
p_in_kwarg[ctxt] p_pvtbl p_pktbl
p_top_expr_body[body]
@@ -3354,12 +3474,14 @@ expr : command_call
pop_pktbl(p, $p_pktbl);
pop_pvtbl(p, $p_pvtbl);
p->ctxt.in_kwarg = $ctxt.in_kwarg;
- $$ = NEW_CASE3($arg, NEW_IN($body, 0, 0, &@body), &@$);
+ p->ctxt.in_alt_pattern = $ctxt.in_alt_pattern;
+ p->ctxt.capture_in_pattern = $ctxt.capture_in_pattern;
+ $$ = NEW_CASE3($arg, NEW_IN($body, 0, 0, &@body, &NULL_LOC, &NULL_LOC, &@2), &@$, &NULL_LOC, &NULL_LOC);
/*% ripper: case!($:arg, in!($:body, Qnil, Qnil)) %*/
}
| arg keyword_in
{
- value_expr($arg);
+ value_expr(p, $arg);
}
p_in_kwarg[ctxt] p_pvtbl p_pktbl
p_top_expr_body[body]
@@ -3367,7 +3489,9 @@ expr : command_call
pop_pktbl(p, $p_pktbl);
pop_pvtbl(p, $p_pvtbl);
p->ctxt.in_kwarg = $ctxt.in_kwarg;
- $$ = NEW_CASE3($arg, NEW_IN($body, NEW_TRUE(&@body), NEW_FALSE(&@body), &@body), &@$);
+ p->ctxt.in_alt_pattern = $ctxt.in_alt_pattern;
+ p->ctxt.capture_in_pattern = $ctxt.capture_in_pattern;
+ $$ = NEW_CASE3($arg, NEW_IN($body, NEW_TRUE(&@body), NEW_FALSE(&@body), &@body, &@keyword_in, &NULL_LOC, &NULL_LOC), &@$, &NULL_LOC, &NULL_LOC);
/*% ripper: case!($:arg, in!($:body, Qnil, Qnil)) %*/
}
| arg %prec tLBRACE_ARG
@@ -3375,13 +3499,12 @@ expr : command_call
def_name : fname
{
- ID fname = $1;
- numparam_name(p, fname);
+ numparam_name(p, $fname);
local_push(p, 0);
- p->cur_arg = 0;
p->ctxt.in_def = 1;
p->ctxt.in_rescue = before_rescue;
- $$ = $1;
+ p->ctxt.cant_return = 0;
+ $$ = $fname;
}
;
@@ -3397,7 +3520,6 @@ defn_head : k_def def_name
defs_head : k_def singleton dot_or_colon
{
SET_LEX_STATE(EXPR_FNAME);
- p->ctxt.in_argdef = 1;
}
def_name
{
@@ -3409,11 +3531,7 @@ defs_head : k_def singleton dot_or_colon
}
;
-expr_value : expr
- {
- value_expr($1);
- $$ = $1;
- }
+expr_value : value_expr(expr)
| error
{
$$ = NEW_ERROR(&@$);
@@ -3431,6 +3549,9 @@ command_call : command
| block_command
;
+command_call_value : value_expr(command_call)
+ ;
+
block_command : block_call
| block_call call_op2 operation2 command_args
{
@@ -3498,33 +3619,33 @@ command : fcall command_args %prec tLOWEST
}
| keyword_super command_args
{
- $$ = NEW_SUPER($2, &@$);
+ $$ = NEW_SUPER($2, &@$, &@1, &NULL_LOC, &NULL_LOC);
fixpos($$, $2);
/*% ripper: super!($:2) %*/
}
| k_yield command_args
{
- $$ = new_yield(p, $2, &@$);
+ $$ = NEW_YIELD($2, &@$, &@1, &NULL_LOC, &NULL_LOC);
fixpos($$, $2);
/*% ripper: yield!($:2) %*/
}
| k_return call_args
{
- $$ = NEW_RETURN(ret_args(p, $2), &@$);
+ $$ = NEW_RETURN(ret_args(p, $2), &@$, &@1);
/*% ripper: return!($:2) %*/
}
| keyword_break call_args
{
NODE *args = 0;
args = ret_args(p, $2);
- $$ = add_block_exit(p, NEW_BREAK(args, &@$));
+ $$ = add_block_exit(p, NEW_BREAK(args, &@$, &@1));
/*% ripper: break!($:2) %*/
}
| keyword_next call_args
{
NODE *args = 0;
args = ret_args(p, $2);
- $$ = add_block_exit(p, NEW_NEXT(args, &@$));
+ $$ = add_block_exit(p, NEW_NEXT(args, &@$, &@1));
/*% ripper: next!($:2) %*/
}
;
@@ -3560,7 +3681,7 @@ mlhs_basic : mlhs_head
$$ = NEW_MASGN($1, $3, &@$);
/*% ripper: mlhs_add_star!($:1, $:3) %*/
}
- | mlhs_head tSTAR mlhs_node ',' mlhs_post
+ | mlhs_head tSTAR mlhs_node ',' mlhs_items(mlhs_item)
{
$$ = NEW_MASGN($1, NEW_POSTARG($3,$5,&@$), &@$);
/*% ripper: mlhs_add_post!(mlhs_add_star!($:1, $:3), $:5) %*/
@@ -3570,7 +3691,7 @@ mlhs_basic : mlhs_head
$$ = NEW_MASGN($1, NODE_SPECIAL_NO_NAME_REST, &@$);
/*% ripper: mlhs_add_star!($:1, Qnil) %*/
}
- | mlhs_head tSTAR ',' mlhs_post
+ | mlhs_head tSTAR ',' mlhs_items(mlhs_item)
{
$$ = NEW_MASGN($1, NEW_POSTARG(NODE_SPECIAL_NO_NAME_REST, $4, &@$), &@$);
/*% ripper: mlhs_add_post!(mlhs_add_star!($:1, Qnil), $:4) %*/
@@ -3580,7 +3701,7 @@ mlhs_basic : mlhs_head
$$ = NEW_MASGN(0, $2, &@$);
/*% ripper: mlhs_add_star!(mlhs_new!, $:2) %*/
}
- | tSTAR mlhs_node ',' mlhs_post
+ | tSTAR mlhs_node ',' mlhs_items(mlhs_item)
{
$$ = NEW_MASGN(0, NEW_POSTARG($2,$4,&@$), &@$);
/*% ripper: mlhs_add_post!(mlhs_add_star!(mlhs_new!, $:2), $:4) %*/
@@ -3590,7 +3711,7 @@ mlhs_basic : mlhs_head
$$ = NEW_MASGN(0, NODE_SPECIAL_NO_NAME_REST, &@$);
/*% ripper: mlhs_add_star!(mlhs_new!, Qnil) %*/
}
- | tSTAR ',' mlhs_post
+ | tSTAR ',' mlhs_items(mlhs_item)
{
$$ = NEW_MASGN(0, NEW_POSTARG(NODE_SPECIAL_NO_NAME_REST, $3, &@$), &@$);
/*% ripper: mlhs_add_post!(mlhs_add_star!(mlhs_new!, Qnil), $:3) %*/
@@ -3617,24 +3738,8 @@ mlhs_head : mlhs_item ','
}
;
-mlhs_post : mlhs_item
- {
- $$ = NEW_LIST($1, &@$);
- /*% ripper: mlhs_add!(mlhs_new!, $:1) %*/
- }
- | mlhs_post ',' mlhs_item
- {
- $$ = list_append(p, $1, $3);
- /*% ripper: mlhs_add!($:1, $:3) %*/
- }
- ;
-mlhs_node : user_variable
- {
- /*% ripper: var_field!($:1) %*/
- $$ = assignable(p, $1, 0, &@$);
- }
- | keyword_variable
+mlhs_node : user_or_keyword_variable
{
/*% ripper: var_field!($:1) %*/
$$ = assignable(p, $1, 0, &@$);
@@ -3644,7 +3749,7 @@ mlhs_node : user_variable
$$ = aryset(p, $1, $3, &@$);
/*% ripper: aref_field!($:1, $:3) %*/
}
- | primary_value call_op tIDENTIFIER
+ | primary_value call_op ident_or_const
{
anddot_multiple_assignment_check(p, &@2, $2);
$$ = attrset(p, $1, $2, $3, &@$);
@@ -3655,38 +3760,25 @@ mlhs_node : user_variable
$$ = attrset(p, $1, idCOLON2, $3, &@$);
/*% ripper: const_path_field!($:1, $:3) %*/
}
- | primary_value call_op tCONSTANT
- {
- anddot_multiple_assignment_check(p, &@2, $2);
- $$ = attrset(p, $1, $2, $3, &@$);
- /*% ripper: field!($:1, $:2, $:3) %*/
- }
| primary_value tCOLON2 tCONSTANT
{
/*% ripper: const_path_field!($:1, $:3) %*/
- $$ = const_decl(p, NEW_COLON2($1, $3, &@$), &@$);
+ $$ = const_decl(p, NEW_COLON2($1, $3, &@$, &@2, &@3), &@$);
}
| tCOLON3 tCONSTANT
{
/*% ripper: top_const_field!($:2) %*/
- $$ = const_decl(p, NEW_COLON3($2, &@$), &@$);
+ $$ = const_decl(p, NEW_COLON3($2, &@$, &@1, &@2), &@$);
}
| backref
{
- /*%%%*/
- rb_backref_error(p, $1);
- /*% %*/
+ VALUE MAYBE_UNUSED(e) = rb_backref_error(p, $1);
$$ = NEW_ERROR(&@$);
- /*% ripper[error]: backref_error(p, $1, var_field!($:1)) %*/
+ /*% ripper[error]: assign_error!(?e, var_field!($:1)) %*/
}
;
-lhs : user_variable
- {
- /*% ripper: var_field!($:1) %*/
- $$ = assignable(p, $1, 0, &@$);
- }
- | keyword_variable
+lhs : user_or_keyword_variable
{
/*% ripper: var_field!($:1) %*/
$$ = assignable(p, $1, 0, &@$);
@@ -3696,7 +3788,7 @@ lhs : user_variable
$$ = aryset(p, $1, $3, &@$);
/*% ripper: aref_field!($:1, $:3) %*/
}
- | primary_value call_op tIDENTIFIER
+ | primary_value call_op ident_or_const
{
$$ = attrset(p, $1, $2, $3, &@$);
/*% ripper: field!($:1, $:2, $:3) %*/
@@ -3706,28 +3798,21 @@ lhs : user_variable
$$ = attrset(p, $1, idCOLON2, $3, &@$);
/*% ripper: field!($:1, $:2, $:3) %*/
}
- | primary_value call_op tCONSTANT
- {
- $$ = attrset(p, $1, $2, $3, &@$);
- /*% ripper: field!($:1, $:2, $:3) %*/
- }
| primary_value tCOLON2 tCONSTANT
{
/*% ripper: const_path_field!($:1, $:3) %*/
- $$ = const_decl(p, NEW_COLON2($1, $3, &@$), &@$);
+ $$ = const_decl(p, NEW_COLON2($1, $3, &@$, &@2, &@3), &@$);
}
| tCOLON3 tCONSTANT
{
/*% ripper: top_const_field!($:2) %*/
- $$ = const_decl(p, NEW_COLON3($2, &@$), &@$);
+ $$ = const_decl(p, NEW_COLON3($2, &@$, &@1, &@2), &@$);
}
| backref
{
- /*%%%*/
- rb_backref_error(p, $1);
- /*% %*/
+ VALUE MAYBE_UNUSED(e) = rb_backref_error(p, $1);
$$ = NEW_ERROR(&@$);
- /*% ripper[error]: backref_error(p, $1, var_field!($:1)) %*/
+ /*% ripper[error]: assign_error!(?e, var_field!($:1)) %*/
}
;
@@ -3744,24 +3829,22 @@ cname : tIDENTIFIER
cpath : tCOLON3 cname
{
- $$ = NEW_COLON3($2, &@$);
+ $$ = NEW_COLON3($2, &@$, &@1, &@2);
/*% ripper: top_const_ref!($:2) %*/
}
| cname
{
- $$ = NEW_COLON2(0, $1, &@$);
+ $$ = NEW_COLON2(0, $1, &@$, &NULL_LOC, &@1);
/*% ripper: const_ref!($:1) %*/
}
| primary_value tCOLON2 cname
{
- $$ = NEW_COLON2($1, $3, &@$);
+ $$ = NEW_COLON2($1, $3, &@$, &@2, &@3);
/*% ripper: const_path_ref!($:1, $:3) %*/
}
;
-fname : tIDENTIFIER
- | tCONSTANT
- | tFID
+fname : operation
| op
{
SET_LEX_STATE(EXPR_ENDFN);
@@ -3785,8 +3868,8 @@ undef_list : fitem
}
| undef_list ',' {SET_LEX_STATE(EXPR_FNAME|EXPR_FITEM);} fitem
{
- NODE *undef = NEW_UNDEF($4, &@4);
- $$ = block_append(p, $1, undef);
+ nd_set_last_loc($1, @4.end_pos);
+ rb_parser_ary_push_node(p, RNODE_UNDEF($1)->nd_undefs, $4);
/*% ripper: rb_ary_push($:1, $:4) %*/
}
;
@@ -3837,94 +3920,9 @@ reswords : keyword__LINE__ | keyword__FILE__ | keyword__ENCODING__
| keyword_while | keyword_until
;
-arg : lhs '=' lex_ctxt arg_rhs
- {
- $$ = node_assign(p, $1, $4, $3, &@$);
- /*% ripper: assign!($:1, $:4) %*/
- }
- | var_lhs tOP_ASGN lex_ctxt arg_rhs
- {
- $$ = new_op_assign(p, $1, $2, $4, $3, &@$);
- /*% ripper: opassign!($:1, $:2, $:4) %*/
- }
- | primary_value '[' opt_call_args rbracket tOP_ASGN lex_ctxt arg_rhs
- {
- $$ = new_ary_op_assign(p, $1, $3, $5, $7, &@3, &@$);
- /*% ripper: opassign!(aref_field!($:1, $:3), $:5, $:7) %*/
- }
- | primary_value call_op tIDENTIFIER tOP_ASGN lex_ctxt arg_rhs
- {
- $$ = new_attr_op_assign(p, $1, $2, $3, $4, $6, &@$);
- /*% ripper: opassign!(field!($:1, $:2, $:3), $:4, $:6) %*/
- }
- | primary_value call_op tCONSTANT tOP_ASGN lex_ctxt arg_rhs
- {
- $$ = new_attr_op_assign(p, $1, $2, $3, $4, $6, &@$);
- /*% ripper: opassign!(field!($:1, $:2, $:3), $:4, $:6) %*/
- }
- | primary_value tCOLON2 tIDENTIFIER tOP_ASGN lex_ctxt arg_rhs
- {
- $$ = new_attr_op_assign(p, $1, idCOLON2, $3, $4, $6, &@$);
- /*% ripper: opassign!(field!($:1, $:2, $:3), $:4, $:6) %*/
- }
- | 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, $6, $5, &@$);
- /*% ripper: opassign!(const_path_field!($:1, $:3), $:4, $:6) %*/
- }
- | tCOLON3 tCONSTANT tOP_ASGN lex_ctxt arg_rhs
- {
- 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, $:5) %*/
- }
- | backref tOP_ASGN lex_ctxt arg_rhs
- {
- rb_backref_error(p, $1);
- /*%%%*/
- $$ = NEW_ERROR(&@$);
- /*% %*/
- /*% ripper[error]: backref_error(p, $1, opassign!(var_field!($:1), $:2, $:4)) %*/
- }
- | arg tDOT2 arg
- {
- value_expr($1);
- value_expr($3);
- $$ = NEW_DOT2($1, $3, &@$);
- /*% ripper: dot2!($:1, $:3) %*/
- }
- | arg tDOT3 arg
- {
- value_expr($1);
- value_expr($3);
- $$ = NEW_DOT3($1, $3, &@$);
- /*% ripper: dot3!($:1, $:3) %*/
- }
- | arg tDOT2
- {
- value_expr($1);
- $$ = NEW_DOT2($1, new_nil_at(p, &@2.end_pos), &@$);
- /*% ripper: dot2!($:1, Qnil) %*/
- }
- | arg tDOT3
- {
- value_expr($1);
- $$ = NEW_DOT3($1, new_nil_at(p, &@2.end_pos), &@$);
- /*% ripper: dot3!($:1, Qnil) %*/
- }
- | tBDOT2 arg
- {
- value_expr($2);
- $$ = NEW_DOT2(new_nil_at(p, &@1.beg_pos), $2, &@$);
- /*% ripper: dot2!(Qnil, $:2) %*/
- }
- | tBDOT3 arg
- {
- value_expr($2);
- $$ = NEW_DOT3(new_nil_at(p, &@1.beg_pos), $2, &@$);
- /*% ripper: dot3!(Qnil, $:2) %*/
- }
+arg : asgn(arg_rhs)
+ | op_asgn(arg_rhs)
+ | range_expr(arg)
| arg '+' arg
{
$$ = call_bin_op(p, $1, '+', $3, &@2, &@$);
@@ -4049,42 +4047,22 @@ arg : lhs '=' lex_ctxt arg_rhs
| keyword_defined '\n'? begin_defined arg
{
p->ctxt.in_defined = $3.in_defined;
- $$ = new_defined(p, $4, &@$);
+ $$ = new_defined(p, $4, &@$, &@1);
+ p->ctxt.has_trailing_semicolon = $3.has_trailing_semicolon;
/*% ripper: defined!($:4) %*/
}
- | arg '?' arg '\n'? ':' arg
+ | def_endless_method(endless_arg)
+ | ternary
+ | primary
+ ;
+
+ternary : arg '?' arg '\n'? ':' arg
{
- value_expr($1);
- $$ = new_if(p, $1, $3, $6, &@$);
+ value_expr(p, $1);
+ $$ = new_if(p, $1, $3, $6, &@$, &NULL_LOC, &@5, &NULL_LOC);
fixpos($$, $1);
/*% ripper: ifop!($:1, $:3, $:6) %*/
}
- | defn_head[head] f_opt_paren_args[args] '=' endless_arg[bodystmt]
- {
- endless_method_name(p, $head->nd_mid, &@head);
- restore_defun(p, $head);
- $bodystmt = new_scope_body(p, $args, $bodystmt, &@$);
- ($$ = $head->nd_def)->nd_loc = @$;
- RNODE_DEFN($$)->nd_defn = $bodystmt;
- /*% ripper: bodystmt!($:bodystmt, Qnil, Qnil, Qnil) %*/
- /*% ripper: def!($:head, $:args, $:$) %*/
- local_pop(p);
- }
- | defs_head[head] f_opt_paren_args[args] '=' endless_arg[bodystmt]
- {
- endless_method_name(p, $head->nd_mid, &@head);
- restore_defun(p, $head);
- $bodystmt = new_scope_body(p, $args, $bodystmt, &@$);
- ($$ = $head->nd_def)->nd_loc = @$;
- RNODE_DEFS($$)->nd_defn = $bodystmt;
- /*% ripper: bodystmt!($:bodystmt, Qnil, Qnil, Qnil) %*/
- /*% ripper: defs!(*$:head[0..2], $:args, $:$) %*/
- local_pop(p);
- }
- | primary
- {
- $$ = $1;
- }
;
endless_arg : arg %prec modifier_rescue
@@ -4140,18 +4118,11 @@ after_rescue : lex_ctxt
}
;
-arg_value : arg
- {
- value_expr($1);
- $$ = $1;
- }
+arg_value : value_expr(arg)
;
aref_args : none
| args trailer
- {
- $$ = $1;
- }
| args ',' assocs trailer
{
$$ = $3 ? arg_append(p, $1, new_hash(p, $3, &@3), &@$) : $1;
@@ -4166,13 +4137,13 @@ aref_args : none
arg_rhs : arg %prec tOP_ASGN
{
- value_expr($1);
+ value_expr(p, $1);
$$ = $1;
}
| arg modifier_rescue after_rescue arg
{
p->ctxt.in_rescue = $3.in_rescue;
- value_expr($1);
+ value_expr(p, $1);
$$ = rescued_expr(p, $1, $4, &@1, &@2, &@4);
/*% ripper: rescue_mod!($:1, $:4) %*/
}
@@ -4215,9 +4186,6 @@ opt_paren_args : none
opt_call_args : none
| call_args
| args ','
- {
- $$ = $1;
- }
| args ',' assocs ','
{
$$ = $3 ? arg_append(p, $1, new_hash(p, $3, &@3), &@$) : $1;
@@ -4230,9 +4198,13 @@ opt_call_args : none
}
;
-call_args : command
+call_args : value_expr(command)
+ {
+ $$ = NEW_LIST($1, &@$);
+ /*% ripper: args_add!(args_new!, $:1) %*/
+ }
+ | def_endless_method(endless_command)
{
- value_expr($1);
$$ = NEW_LIST($1, &@$);
/*% ripper: args_add!(args_new!, $:1) %*/
}
@@ -4297,13 +4269,13 @@ command_args : {
block_arg : tAMPER arg_value
{
- $$ = NEW_BLOCK_PASS($2, &@$);
+ $$ = NEW_BLOCK_PASS($2, &@$, &@1);
/*% ripper: $:2 %*/
}
| tAMPER
{
forwarding_arg_check(p, idFWD_BLOCK, idFWD_ALL, "block");
- $$ = NEW_BLOCK_PASS(NEW_LVAR(idFWD_BLOCK, &@1), &@$);
+ $$ = NEW_BLOCK_PASS(NEW_LVAR(idFWD_BLOCK, &@1), &@$, &@1);
/*% ripper: Qnil %*/
}
;
@@ -4323,36 +4295,36 @@ opt_block_arg : ',' block_arg
/* value */
args : arg_value
{
- $$ = NEW_LIST($1, &@$);
- /*% ripper: args_add!(args_new!, $:1) %*/
+ $$ = NEW_LIST($arg_value, &@$);
+ /*% ripper: args_add!(args_new!, $:arg_value) %*/
}
| arg_splat
{
- $$ = NEW_SPLAT($arg_splat, &@$);
+ $$ = $arg_splat;
/*% ripper: args_add_star!(args_new!, $:arg_splat) %*/
}
- | args ',' arg_value
+ | args[non_last_args] ',' arg_value
{
- $$ = last_arg_append(p, $1, $3, &@$);
- /*% ripper: args_add!($:1, $:3) %*/
+ $$ = last_arg_append(p, $non_last_args, $arg_value, &@$);
+ /*% ripper: args_add!($:non_last_args, $:arg_value) %*/
}
- | args ',' arg_splat
+ | args[non_last_args] ',' arg_splat
{
- $$ = rest_arg_append(p, $1, $3, &@$);
- /*% ripper: args_add_star!($:1, $:3) %*/
+ $$ = rest_arg_append(p, $non_last_args, RNODE_SPLAT($arg_splat)->nd_head, &@$);
+ /*% ripper: args_add_star!($:non_last_args, $:arg_splat) %*/
}
;
/* value */
arg_splat : tSTAR arg_value
{
- $$ = $2;
- /*% ripper: $:2 %*/
+ $$ = NEW_SPLAT($arg_value, &@$, &@tSTAR);
+ /*% ripper: $:arg_value %*/
}
| tSTAR /* none */
{
forwarding_arg_check(p, idFWD_REST, idFWD_ALL, "rest");
- $$ = NEW_LVAR(idFWD_REST, &@1);
+ $$ = NEW_SPLAT(NEW_LVAR(idFWD_REST, &@tSTAR), &@$, &@tSTAR);
/*% ripper: Qnil %*/
}
;
@@ -4365,22 +4337,23 @@ mrhs_arg : mrhs
/* value */
mrhs : args ',' arg_value
{
- $$ = last_arg_append(p, $1, $3, &@$);
- /*% ripper: mrhs_add!(mrhs_new_from_args!($:1), $:3) %*/
+ $$ = last_arg_append(p, $args, $arg_value, &@$);
+ /*% ripper: mrhs_add!(mrhs_new_from_args!($:args), $:arg_value) %*/
}
| args ',' tSTAR arg_value
{
- $$ = rest_arg_append(p, $1, $4, &@$);
- /*% ripper: mrhs_add_star!(mrhs_new_from_args!($:1), $:4) %*/
+ $$ = rest_arg_append(p, $args, $arg_value, &@$);
+ /*% ripper: mrhs_add_star!(mrhs_new_from_args!($:args), $:arg_value) %*/
}
| tSTAR arg_value
{
- $$ = NEW_SPLAT($2, &@$);
- /*% ripper: mrhs_add_star!(mrhs_new!, $:2) %*/
+ $$ = NEW_SPLAT($arg_value, &@$, &@tSTAR);
+ /*% ripper: mrhs_add_star!(mrhs_new!, $:arg_value) %*/
}
;
-primary : literal
+%rule %inline inline_primary
+ : literal
| strings
| xstring
| regexp
@@ -4388,335 +4361,349 @@ primary : literal
| qwords
| symbols
| qsymbols
- | var_ref
- | backref
- | tFID
- {
- $$ = (NODE *)NEW_FCALL($1, 0, &@$);
- /*% ripper: method_add_arg!(fcall!($:1), args_new!) %*/
- }
- | k_begin
- {
- CMDARG_PUSH(0);
- }
- bodystmt
- k_end
- {
- CMDARG_POP();
- set_line_body($3, @1.end_pos.lineno);
- $$ = NEW_BEGIN($3, &@$);
- nd_set_line($$, @1.end_pos.lineno);
- /*% ripper: begin!($:3) %*/
- }
- | tLPAREN_ARG compstmt {SET_LEX_STATE(EXPR_ENDARG);} ')'
- {
- if (nd_type_p($2, NODE_SELF)) RNODE_SELF($2)->nd_state = 0;
- $$ = $2;
- /*% ripper: paren!($:2) %*/
- }
- | tLPAREN compstmt ')'
- {
- if (nd_type_p($2, NODE_SELF)) RNODE_SELF($2)->nd_state = 0;
- $$ = NEW_BLOCK($2, &@$);
- /*% ripper: paren!($:2) %*/
- }
- | primary_value tCOLON2 tCONSTANT
- {
- $$ = NEW_COLON2($1, $3, &@$);
- /*% ripper: const_path_ref!($:1, $:3) %*/
- }
- | tCOLON3 tCONSTANT
- {
- $$ = NEW_COLON3($2, &@$);
- /*% ripper: top_const_ref!($:2) %*/
- }
- | tLBRACK aref_args ']'
- {
- $$ = make_list($2, &@$);
- /*% ripper: array!($:2) %*/
- }
- | tLBRACE assoc_list '}'
- {
- $$ = new_hash(p, $2, &@$);
- RNODE_HASH($$)->nd_brace = TRUE;
- /*% ripper: hash!($:2) %*/
- }
- | k_return
- {
- $$ = NEW_RETURN(0, &@$);
- /*% ripper: return0! %*/
- }
- | k_yield '(' call_args rparen
- {
- $$ = new_yield(p, $3, &@$);
- /*% ripper: yield!(paren!($:3)) %*/
- }
- | k_yield '(' rparen
- {
- $$ = NEW_YIELD(0, &@$);
- /*% ripper: yield!(paren!(args_new!)) %*/
- }
- | k_yield
- {
- $$ = NEW_YIELD(0, &@$);
- /*% ripper: yield0! %*/
- }
- | keyword_defined '\n'? '(' begin_defined expr rparen
- {
- p->ctxt.in_defined = $4.in_defined;
- $$ = new_defined(p, $5, &@$);
- /*% ripper: defined!($:5) %*/
- }
- | keyword_not '(' expr rparen
- {
- $$ = call_uni_op(p, method_cond(p, $3, &@3), METHOD_NOT, &@1, &@$);
- /*% ripper: unary!(ID2VAL(idNOT), $:3) %*/
- }
- | keyword_not '(' rparen
- {
- $$ = call_uni_op(p, method_cond(p, new_nil(&@2), &@2), METHOD_NOT, &@1, &@$);
- /*% ripper: unary!(ID2VAL(idNOT), Qnil) %*/
- }
- | fcall brace_block
- {
- $$ = method_add_block(p, (NODE *)$1, $2, &@$);
- /*% ripper: method_add_block!(method_add_arg!(fcall!($:1), args_new!), $:2) %*/
- }
- | method_call
- | method_call brace_block
- {
- block_dup_check(p, get_nd_args(p, $1), $2);
- $$ = method_add_block(p, $1, $2, &@$);
- /*% ripper: method_add_block!($:1, $:2) %*/
- }
- | lambda
- | k_if expr_value then
- compstmt
- if_tail
- k_end
- {
- $$ = new_if(p, $2, $4, $5, &@$);
- fixpos($$, $2);
- /*% ripper: if!($:2, $:4, $:5) %*/
- }
- | k_unless expr_value then
- compstmt
- opt_else
- k_end
- {
- $$ = new_unless(p, $2, $4, $5, &@$);
- fixpos($$, $2);
- /*% ripper: unless!($:2, $:4, $:5) %*/
- }
- | k_while expr_value_do
- compstmt
- k_end
- {
- restore_block_exit(p, $1);
- $$ = NEW_WHILE(cond(p, $2, &@2), $3, 1, &@$);
- fixpos($$, $2);
- /*% ripper: while!($:2, $:3) %*/
- }
- | k_until expr_value_do
- compstmt
- k_end
- {
- restore_block_exit(p, $1);
- $$ = NEW_UNTIL(cond(p, $2, &@2), $3, 1, &@$);
- fixpos($$, $2);
- /*% ripper: until!($:2, $:3) %*/
- }
- | k_case expr_value terms?
- {
- $$ = p->case_labels;
- p->case_labels = CHECK_LITERAL_WHEN;
- }<labels>
- case_body
- k_end
- {
- if (CASE_LABELS_ENABLED_P(p->case_labels)) st_free_table(p->case_labels);
- p->case_labels = $4;
- $$ = NEW_CASE($2, $5, &@$);
- fixpos($$, $2);
- /*% ripper: case!($:2, $:5) %*/
- }
- | k_case terms?
- {
- $$ = p->case_labels;
- p->case_labels = 0;
- }<labels>
- case_body
- k_end
- {
- if (p->case_labels) st_free_table(p->case_labels);
- p->case_labels = $3;
- $$ = NEW_CASE2($4, &@$);
- /*% ripper: case!(Qnil, $:4) %*/
- }
- | k_case expr_value terms?
- p_case_body
- k_end
- {
- $$ = NEW_CASE3($2, $4, &@$);
- /*% ripper: case!($:2, $:4) %*/
- }
- | k_for for_var keyword_in expr_value_do
- compstmt
- k_end
- {
- restore_block_exit(p, $1);
- /*
- * for a, b, c in e
- * #=>
- * e.each{|*x| a, b, c = x}
- *
- * for a in e
- * #=>
- * e.each{|x| a, = x}
- */
- ID id = internal_id(p);
- rb_node_args_aux_t *m = NEW_ARGS_AUX(0, 0, &NULL_LOC);
- rb_node_args_t *args;
- NODE *scope, *internal_var = NEW_DVAR(id, &@2);
- 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: /* e.each {|internal_var| a = internal_var; ... } */
- set_nd_value(p, $2, 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), NO_LEX_CTXT, &@2);
- break;
- default: /* e.each {|*internal_var| @a, B, c[1], d.attr = internal_val; ... } */
- m->nd_next = node_assign(p, (NODE *)NEW_MASGN(NEW_LIST($2, &@2), 0, &@2), internal_var, NO_LEX_CTXT, &@2);
- }
- /* {|*internal_id| <m> = internal_id; ... } */
- args = new_args(p, m, 0, id, 0, new_args_tail(p, 0, 0, 0, &@2), &@2);
- scope = NEW_SCOPE2(tbl, args, $5, &@$);
- $$ = NEW_FOR($4, scope, &@$);
- fixpos($$, $2);
- /*% ripper: for!($:2, $:4, $:5) %*/
- }
- | k_class cpath superclass
- {
- begin_definition("class", &@k_class, &@cpath);
- }
- bodystmt
- k_end
- {
- $$ = NEW_CLASS($cpath, $bodystmt, $superclass, &@$);
- nd_set_line(RNODE_CLASS($$)->nd_body, @k_end.end_pos.lineno);
- set_line_body($bodystmt, @superclass.end_pos.lineno);
- nd_set_line($$, @superclass.end_pos.lineno);
- /*% ripper: class!($:cpath, $:superclass, $:bodystmt) %*/
- local_pop(p);
- p->ctxt.in_class = $k_class.in_class;
- p->ctxt.shareable_constant_value = $k_class.shareable_constant_value;
- }
- | k_class tLSHFT expr_value
- {
- begin_definition("", &@k_class, &@tLSHFT);
- }
- term
- bodystmt
- k_end
- {
- $$ = NEW_SCLASS($expr_value, $bodystmt, &@$);
- nd_set_line(RNODE_SCLASS($$)->nd_body, @k_end.end_pos.lineno);
- set_line_body($bodystmt, nd_line($expr_value));
- fixpos($$, $expr_value);
- /*% ripper: sclass!($:expr_value, $:bodystmt) %*/
- local_pop(p);
- p->ctxt.in_def = $k_class.in_def;
- p->ctxt.in_class = $k_class.in_class;
- p->ctxt.shareable_constant_value = $k_class.shareable_constant_value;
- }
- | k_module cpath
- {
- begin_definition("module", &@k_module, &@cpath);
- }
- bodystmt
- k_end
- {
- $$ = NEW_MODULE($cpath, $bodystmt, &@$);
- nd_set_line(RNODE_MODULE($$)->nd_body, @k_end.end_pos.lineno);
- set_line_body($bodystmt, @cpath.end_pos.lineno);
- nd_set_line($$, @cpath.end_pos.lineno);
- /*% ripper: module!($:cpath, $:bodystmt) %*/
- local_pop(p);
- p->ctxt.in_class = $k_module.in_class;
- p->ctxt.shareable_constant_value = $k_module.shareable_constant_value;
- }
- | defn_head[head]
- f_arglist[args]
- {
- push_end_expect_token_locations(p, &@head.beg_pos);
- }
- bodystmt
- k_end
- {
- restore_defun(p, $head);
- $bodystmt = new_scope_body(p, $args, $bodystmt, &@$);
- ($$ = $head->nd_def)->nd_loc = @$;
- RNODE_DEFN($$)->nd_defn = $bodystmt;
- /*% ripper: def!($:head, $:args, $:bodystmt) %*/
- local_pop(p);
- }
- | defs_head[head]
- f_arglist[args]
- {
- push_end_expect_token_locations(p, &@head.beg_pos);
- }
- bodystmt
- k_end
- {
- restore_defun(p, $head);
- $bodystmt = new_scope_body(p, $args, $bodystmt, &@$);
- ($$ = $head->nd_def)->nd_loc = @$;
- RNODE_DEFS($$)->nd_defn = $bodystmt;
- /*% ripper: defs!(*$:head[0..2], $:args, $:bodystmt) %*/
- local_pop(p);
- }
- | keyword_break
- {
- $$ = add_block_exit(p, NEW_BREAK(0, &@$));
- /*% ripper: break!(args_new!) %*/
- }
- | keyword_next
- {
- $$ = add_block_exit(p, NEW_NEXT(0, &@$));
- /*% ripper: next!(args_new!) %*/
- }
- | keyword_redo
- {
- $$ = add_block_exit(p, NEW_REDO(&@$));
- /*% ripper: redo! %*/
- }
- | keyword_retry
- {
- if (!p->ctxt.in_defined) {
- switch (p->ctxt.in_rescue) {
- case before_rescue: yyerror1(&@1, "Invalid retry without rescue"); break;
- case after_rescue: /* ok */ break;
- case after_else: yyerror1(&@1, "Invalid retry after else"); break;
- case after_ensure: yyerror1(&@1, "Invalid retry after ensure"); break;
- }
- }
- $$ = NEW_RETRY(&@$);
- /*% ripper: retry! %*/
- }
;
-primary_value : primary
- {
- value_expr($1);
- $$ = $1;
+primary : inline_primary
+ | var_ref
+ | backref
+ | tFID
+ {
+ $$ = (NODE *)NEW_FCALL($1, 0, &@$);
+ /*% ripper: method_add_arg!(fcall!($:1), args_new!) %*/
+ }
+ | k_begin
+ {
+ CMDARG_PUSH(0);
+ }
+ bodystmt
+ k_end
+ {
+ CMDARG_POP();
+ set_line_body($3, @1.end_pos.lineno);
+ $$ = NEW_BEGIN($3, &@$);
+ nd_set_line($$, @1.end_pos.lineno);
+ /*% ripper: begin!($:3) %*/
+ }
+ | tLPAREN_ARG compstmt(stmts) {SET_LEX_STATE(EXPR_ENDARG);} ')'
+ {
+ if (nd_type_p($2, NODE_SELF)) RNODE_SELF($2)->nd_state = 0;
+ $$ = $2;
+ /*% ripper: paren!($:2) %*/
+ }
+ | tLPAREN compstmt(stmts) ')'
+ {
+ if (nd_type_p($2, NODE_SELF)) RNODE_SELF($2)->nd_state = 0;
+ $$ = NEW_BLOCK($2, &@$);
+ /*% ripper: paren!($:2) %*/
+ }
+ | primary_value tCOLON2 tCONSTANT
+ {
+ $$ = NEW_COLON2($1, $3, &@$, &@2, &@3);
+ /*% ripper: const_path_ref!($:1, $:3) %*/
+ }
+ | tCOLON3 tCONSTANT
+ {
+ $$ = NEW_COLON3($2, &@$, &@1, &@2);
+ /*% ripper: top_const_ref!($:2) %*/
+ }
+ | tLBRACK aref_args ']'
+ {
+ $$ = make_list($2, &@$);
+ /*% ripper: array!($:2) %*/
+ }
+ | tLBRACE assoc_list '}'
+ {
+ $$ = new_hash(p, $2, &@$);
+ RNODE_HASH($$)->nd_brace = TRUE;
+ /*% ripper: hash!($:2) %*/
+ }
+ | k_return
+ {
+ $$ = NEW_RETURN(0, &@$, &@1);
+ /*% ripper: return0! %*/
+ }
+ | k_yield '(' call_args rparen
+ {
+ $$ = NEW_YIELD($3, &@$, &@1, &@2, &@4);
+ /*% ripper: yield!(paren!($:3)) %*/
+ }
+ | k_yield '(' rparen
+ {
+ $$ = NEW_YIELD(0, &@$, &@1, &@2, &@3);
+ /*% ripper: yield!(paren!(args_new!)) %*/
+ }
+ | k_yield
+ {
+ $$ = NEW_YIELD(0, &@$, &@1, &NULL_LOC, &NULL_LOC);
+ /*% ripper: yield0! %*/
+ }
+ | keyword_defined '\n'? '(' begin_defined expr rparen
+ {
+ p->ctxt.in_defined = $4.in_defined;
+ $$ = new_defined(p, $5, &@$, &@1);
+ p->ctxt.has_trailing_semicolon = $4.has_trailing_semicolon;
+ /*% ripper: defined!($:5) %*/
+ }
+ | keyword_not '(' expr rparen
+ {
+ $$ = call_uni_op(p, method_cond(p, $3, &@3), METHOD_NOT, &@1, &@$);
+ /*% ripper: unary!(ID2VAL(idNOT), $:3) %*/
+ }
+ | keyword_not '(' rparen
+ {
+ $$ = call_uni_op(p, method_cond(p, NEW_NIL(&@2), &@2), METHOD_NOT, &@1, &@$);
+ /*% ripper: unary!(ID2VAL(idNOT), Qnil) %*/
+ }
+ | fcall brace_block
+ {
+ $$ = method_add_block(p, (NODE *)$1, $2, &@$);
+ /*% ripper: method_add_block!(method_add_arg!(fcall!($:1), args_new!), $:2) %*/
+ }
+ | method_call
+ | method_call brace_block
+ {
+ block_dup_check(p, get_nd_args(p, $1), $2);
+ $$ = method_add_block(p, $1, $2, &@$);
+ /*% ripper: method_add_block!($:1, $:2) %*/
+ }
+ | lambda
+ | k_if expr_value then
+ compstmt(stmts)
+ if_tail
+ k_end
+ {
+ if ($5 && nd_type_p($5, NODE_IF))
+ RNODE_IF($5)->end_keyword_loc = @6;
+
+ $$ = new_if(p, $2, $4, $5, &@$, &@1, &@3, &@6);
+ fixpos($$, $2);
+ /*% ripper: if!($:2, $:4, $:5) %*/
+ }
+ | k_unless expr_value then
+ compstmt(stmts)
+ opt_else
+ k_end
+ {
+ $$ = new_unless(p, $2, $4, $5, &@$, &@1, &@3, &@6);
+ fixpos($$, $2);
+ /*% ripper: unless!($:2, $:4, $:5) %*/
+ }
+ | k_while expr_value_do
+ compstmt(stmts)
+ k_end
+ {
+ restore_block_exit(p, $1);
+ $$ = NEW_WHILE(cond(p, $2, &@2), $3, 1, &@$, &@1, &@4);
+ fixpos($$, $2);
+ /*% ripper: while!($:2, $:3) %*/
+ }
+ | k_until expr_value_do
+ compstmt(stmts)
+ k_end
+ {
+ restore_block_exit(p, $1);
+ $$ = NEW_UNTIL(cond(p, $2, &@2), $3, 1, &@$, &@1, &@4);
+ fixpos($$, $2);
+ /*% ripper: until!($:2, $:3) %*/
+ }
+ | k_case expr_value terms?
+ {
+ $$ = p->case_labels;
+ p->case_labels = CHECK_LITERAL_WHEN;
+ }<labels>
+ case_body
+ k_end
+ {
+ if (CASE_LABELS_ENABLED_P(p->case_labels)) st_free_table(p->case_labels);
+ p->case_labels = $4;
+ $$ = NEW_CASE($2, $5, &@$, &@1, &@6);
+ fixpos($$, $2);
+ /*% ripper: case!($:2, $:5) %*/
+ }
+ | k_case terms?
+ {
+ $$ = p->case_labels;
+ p->case_labels = 0;
+ }<labels>
+ case_body
+ k_end
+ {
+ if (p->case_labels) st_free_table(p->case_labels);
+ p->case_labels = $3;
+ $$ = NEW_CASE2($4, &@$, &@1, &@5);
+ /*% ripper: case!(Qnil, $:4) %*/
+ }
+ | k_case expr_value terms?
+ p_case_body
+ k_end
+ {
+ $$ = NEW_CASE3($2, $4, &@$, &@1, &@5);
+ /*% ripper: case!($:2, $:4) %*/
+ }
+ | k_for for_var keyword_in
+ {COND_PUSH(1);} expr_value do {COND_POP();}
+ compstmt(stmts)
+ k_end
+ {
+ restore_block_exit(p, $k_for);
+ /*
+ * for a, b, c in e
+ * #=>
+ * e.each{|*x| a, b, c = x}
+ *
+ * for a in e
+ * #=>
+ * e.each{|x| a, = x}
+ */
+ ID id = internal_id(p);
+ rb_node_args_aux_t *m = NEW_ARGS_AUX(0, 0, &NULL_LOC);
+ rb_node_args_t *args;
+ NODE *scope, *internal_var = NEW_DVAR(id, &@for_var);
+ rb_ast_id_table_t *tbl = rb_ast_new_local_table(p->ast, 1);
+ tbl->ids[0] = id; /* internal id */
+
+ switch (nd_type($for_var)) {
+ case NODE_LASGN:
+ case NODE_DASGN: /* e.each {|internal_var| a = internal_var; ... } */
+ set_nd_value(p, $for_var, internal_var);
+ id = 0;
+ m->nd_plen = 1;
+ m->nd_next = $for_var;
+ 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, $for_var, NEW_FOR_MASGN(internal_var, &@for_var), NO_LEX_CTXT, &@for_var);
+ break;
+ default: /* e.each {|*internal_var| @a, B, c[1], d.attr = internal_val; ... } */
+ m->nd_next = node_assign(p, (NODE *)NEW_MASGN(NEW_LIST($for_var, &@for_var), 0, &@for_var), internal_var, NO_LEX_CTXT, &@for_var);
+ }
+ /* {|*internal_id| <m> = internal_id; ... } */
+ args = new_args(p, m, 0, id, 0, new_args_tail(p, 0, 0, 0, &@for_var), &@for_var);
+ scope = NEW_SCOPE2(tbl, args, $compstmt, NULL, &@$);
+ YYLTYPE do_keyword_loc = $do == keyword_do_cond ? @do : NULL_LOC;
+ $$ = NEW_FOR($5, scope, &@$, &@k_for, &@keyword_in, &do_keyword_loc, &@k_end);
+ RNODE_SCOPE(scope)->nd_parent = $$;
+ fixpos($$, $for_var);
+ /*% ripper: for!($:for_var, $:expr_value, $:compstmt) %*/
+ }
+ | k_class cpath superclass
+ {
+ begin_definition("class", &@k_class, &@cpath);
+ }
+ bodystmt
+ k_end
+ {
+ YYLTYPE inheritance_operator_loc = NULL_LOC;
+ if ($superclass) {
+ inheritance_operator_loc = @superclass;
+ inheritance_operator_loc.end_pos.column = inheritance_operator_loc.beg_pos.column + 1;
+ }
+ $$ = NEW_CLASS($cpath, $bodystmt, $superclass, &@$, &@k_class, &inheritance_operator_loc, &@k_end);
+ nd_set_line(RNODE_CLASS($$)->nd_body, @k_end.end_pos.lineno);
+ set_line_body($bodystmt, @superclass.end_pos.lineno);
+ nd_set_line($$, @superclass.end_pos.lineno);
+ /*% ripper: class!($:cpath, $:superclass, $:bodystmt) %*/
+ local_pop(p);
+ p->ctxt.in_class = $k_class.in_class;
+ p->ctxt.cant_return = $k_class.cant_return;
+ p->ctxt.shareable_constant_value = $k_class.shareable_constant_value;
+ }
+ | k_class tLSHFT expr_value
+ {
+ begin_definition("", &@k_class, &@tLSHFT);
+ }
+ term
+ bodystmt
+ k_end
+ {
+ $$ = NEW_SCLASS($expr_value, $bodystmt, &@$, &@k_class, &@tLSHFT, &@k_end);
+ nd_set_line(RNODE_SCLASS($$)->nd_body, @k_end.end_pos.lineno);
+ set_line_body($bodystmt, nd_line($expr_value));
+ fixpos($$, $expr_value);
+ /*% ripper: sclass!($:expr_value, $:bodystmt) %*/
+ local_pop(p);
+ p->ctxt.in_def = $k_class.in_def;
+ p->ctxt.in_class = $k_class.in_class;
+ p->ctxt.cant_return = $k_class.cant_return;
+ p->ctxt.shareable_constant_value = $k_class.shareable_constant_value;
+ }
+ | k_module cpath
+ {
+ begin_definition("module", &@k_module, &@cpath);
+ }
+ bodystmt
+ k_end
+ {
+ $$ = NEW_MODULE($cpath, $bodystmt, &@$, &@k_module, &@k_end);
+ nd_set_line(RNODE_MODULE($$)->nd_body, @k_end.end_pos.lineno);
+ set_line_body($bodystmt, @cpath.end_pos.lineno);
+ nd_set_line($$, @cpath.end_pos.lineno);
+ /*% ripper: module!($:cpath, $:bodystmt) %*/
+ local_pop(p);
+ p->ctxt.in_class = $k_module.in_class;
+ p->ctxt.cant_return = $k_module.cant_return;
+ p->ctxt.shareable_constant_value = $k_module.shareable_constant_value;
+ }
+ | defn_head[head]
+ f_arglist[args]
+ {
+ push_end_expect_token_locations(p, &@head.beg_pos);
+ }
+ bodystmt
+ k_end
+ {
+ restore_defun(p, $head);
+ ($$ = $head->nd_def)->nd_loc = @$;
+ $bodystmt = new_scope_body(p, $args, $bodystmt, $$, &@$);
+ RNODE_DEFN($$)->nd_defn = $bodystmt;
+ /*% ripper: def!($:head, $:args, $:bodystmt) %*/
+ local_pop(p);
+ }
+ | defs_head[head]
+ f_arglist[args]
+ {
+ push_end_expect_token_locations(p, &@head.beg_pos);
+ }
+ bodystmt
+ k_end
+ {
+ restore_defun(p, $head);
+ ($$ = $head->nd_def)->nd_loc = @$;
+ $bodystmt = new_scope_body(p, $args, $bodystmt, $$, &@$);
+ RNODE_DEFS($$)->nd_defn = $bodystmt;
+ /*% ripper: defs!(*$:head[0..2], $:args, $:bodystmt) %*/
+ local_pop(p);
+ }
+ | keyword_break
+ {
+ $$ = add_block_exit(p, NEW_BREAK(0, &@$, &@1));
+ /*% ripper: break!(args_new!) %*/
+ }
+ | keyword_next
+ {
+ $$ = add_block_exit(p, NEW_NEXT(0, &@$, &@1));
+ /*% ripper: next!(args_new!) %*/
+ }
+ | keyword_redo
+ {
+ $$ = add_block_exit(p, NEW_REDO(&@$, &@1));
+ /*% ripper: redo! %*/
+ }
+ | keyword_retry
+ {
+ if (!p->ctxt.in_defined) {
+ switch (p->ctxt.in_rescue) {
+ case before_rescue: yyerror1(&@1, "Invalid retry without rescue"); break;
+ case after_rescue: /* ok */ break;
+ case after_else: yyerror1(&@1, "Invalid retry after else"); break;
+ case after_ensure: yyerror1(&@1, "Invalid retry after ensure"); break;
+ }
}
+ $$ = NEW_RETRY(&@$);
+ /*% ripper: retry! %*/
+ }
+ ;
+
+primary_value : value_expr(primary)
;
k_begin : keyword_begin
@@ -4878,7 +4865,7 @@ k_end : keyword_end
k_return : keyword_return
{
- if (p->ctxt.in_class && !p->ctxt.in_def && !dyna_in_block(p))
+ if (p->ctxt.cant_return && !dyna_in_block(p))
yyerror1(&@1, "Invalid return in class/module body");
}
;
@@ -4896,22 +4883,22 @@ then : term
;
do : term
- | keyword_do_cond
+ | keyword_do_cond { $$ = keyword_do_cond; }
;
if_tail : opt_else
| k_elsif expr_value then
- compstmt
+ compstmt(stmts)
if_tail
{
- $$ = new_if(p, $2, $4, $5, &@$);
+ $$ = new_if(p, $2, $4, $5, &@$, &@1, &@3, &NULL_LOC);
fixpos($$, $2);
/*% ripper: elsif!($:2, $:4, $:5) %*/
}
;
opt_else : none
- | k_else compstmt
+ | k_else compstmt(stmts)
{
$$ = $2;
/*% ripper: else!($:2) %*/
@@ -4934,29 +4921,18 @@ f_marg : f_norm_arg
}
;
-f_marg_list : f_marg
- {
- $$ = NEW_LIST($1, &@$);
- /*% ripper: mlhs_add!(mlhs_new!, $:1) %*/
- }
- | f_marg_list ',' f_marg
- {
- $$ = list_append(p, $1, $3);
- /*% ripper: mlhs_add!($:1, $:3) %*/
- }
- ;
-f_margs : f_marg_list
+f_margs : mlhs_items(f_marg)
{
$$ = NEW_MASGN($1, 0, &@$);
/*% ripper: $:1 %*/
}
- | f_marg_list ',' f_rest_marg
+ | mlhs_items(f_marg) ',' f_rest_marg
{
$$ = NEW_MASGN($1, $3, &@$);
/*% ripper: mlhs_add_star!($:1, $:3) %*/
}
- | f_marg_list ',' f_rest_marg ',' f_marg_list
+ | mlhs_items(f_marg) ',' f_rest_marg ',' mlhs_items(f_marg)
{
$$ = NEW_MASGN($1, NEW_POSTARG($3, $5, &@$), &@$);
/*% ripper: mlhs_add_post!(mlhs_add_star!($:1, $:3), $:5) %*/
@@ -4966,7 +4942,7 @@ f_margs : f_marg_list
$$ = NEW_MASGN(0, $1, &@$);
/*% ripper: mlhs_add_star!(mlhs_new!, $:1) %*/
}
- | f_rest_marg ',' f_marg_list
+ | f_rest_marg ',' mlhs_items(f_marg)
{
$$ = NEW_MASGN(0, NEW_POSTARG($1, $3, &@$), &@$);
/*% ripper: mlhs_add_post!(mlhs_add_star!(mlhs_new!, $:1), $:3) %*/
@@ -4996,26 +4972,7 @@ f_any_kwrest : f_kwrest
f_eq : {p->ctxt.in_argdef = 0;} '=';
-block_args_tail : f_kwarg(f_block_kw) ',' f_kwrest opt_f_block_arg
- {
- $$ = new_args_tail(p, $1, $3, $4, &@3);
- /*% ripper: [$:1, $:3, $:4] %*/
- }
- | f_kwarg(f_block_kw) opt_f_block_arg
- {
- $$ = new_args_tail(p, $1, 0, $2, &@1);
- /*% ripper: [$:1, Qnil, $:2] %*/
- }
- | f_any_kwrest opt_f_block_arg
- {
- $$ = new_args_tail(p, 0, $1, $2, &@1);
- /*% ripper: [Qnil, $:1, $:2] %*/
- }
- | f_block_arg
- {
- $$ = new_args_tail(p, 0, 0, $1, &@1);
- /*% ripper: [Qnil, Qnil, $:1] %*/
- }
+block_args_tail : args_tail_basic(primary_value)
;
excessed_comma : ','
@@ -5026,22 +4983,22 @@ excessed_comma : ','
}
;
-block_param : f_arg ',' f_optarg(primary_value) ',' f_rest_arg opt_args_tail(block_args_tail)
+block_param : f_arg ',' f_opt_arg(primary_value) ',' f_rest_arg opt_args_tail(block_args_tail)
{
$$ = new_args(p, $1, $3, $5, 0, $6, &@$);
/*% ripper: params!($:1, $:3, $:5, Qnil, *$:6[0..2]) %*/
}
- | f_arg ',' f_optarg(primary_value) ',' f_rest_arg ',' f_arg opt_args_tail(block_args_tail)
+ | f_arg ',' f_opt_arg(primary_value) ',' f_rest_arg ',' f_arg opt_args_tail(block_args_tail)
{
$$ = new_args(p, $1, $3, $5, $7, $8, &@$);
/*% ripper: params!($:1, $:3, $:5, $:7, *$:8[0..2]) %*/
}
- | f_arg ',' f_optarg(primary_value) opt_args_tail(block_args_tail)
+ | f_arg ',' f_opt_arg(primary_value) opt_args_tail(block_args_tail)
{
$$ = new_args(p, $1, $3, 0, 0, $4, &@$);
/*% ripper: params!($:1, $:3, Qnil, Qnil, *$:4[0..2]) %*/
}
- | f_arg ',' f_optarg(primary_value) ',' f_arg opt_args_tail(block_args_tail)
+ | f_arg ',' f_opt_arg(primary_value) ',' f_arg opt_args_tail(block_args_tail)
{
$$ = new_args(p, $1, $3, 0, $5, $6, &@$);
/*% ripper: params!($:1, $:3, Qnil, $:5, *$:6[0..2]) %*/
@@ -5067,22 +5024,22 @@ block_param : f_arg ',' f_optarg(primary_value) ',' f_rest_arg opt_args_tail(blo
$$ = new_args(p, $1, 0, 0, 0, $2, &@$);
/*% ripper: params!($:1, Qnil, Qnil, Qnil, *$:2[0..2]) %*/
}
- | f_optarg(primary_value) ',' f_rest_arg opt_args_tail(block_args_tail)
+ | f_opt_arg(primary_value) ',' f_rest_arg opt_args_tail(block_args_tail)
{
$$ = new_args(p, 0, $1, $3, 0, $4, &@$);
/*% ripper: params!(Qnil, $:1, $:3, Qnil, *$:4[0..2]) %*/
}
- | f_optarg(primary_value) ',' f_rest_arg ',' f_arg opt_args_tail(block_args_tail)
+ | f_opt_arg(primary_value) ',' f_rest_arg ',' f_arg opt_args_tail(block_args_tail)
{
$$ = new_args(p, 0, $1, $3, $5, $6, &@$);
/*% ripper: params!(Qnil, $:1, $:3, $:5, *$:6[0..2]) %*/
}
- | f_optarg(primary_value) opt_args_tail(block_args_tail)
+ | f_opt_arg(primary_value) opt_args_tail(block_args_tail)
{
$$ = new_args(p, 0, $1, 0, 0, $2, &@$);
/*% ripper: params!(Qnil, $:1, Qnil, Qnil, *$:2[0..2]) %*/
}
- | f_optarg(primary_value) ',' f_arg opt_args_tail(block_args_tail)
+ | f_opt_arg(primary_value) ',' f_arg opt_args_tail(block_args_tail)
{
$$ = new_args(p, 0, $1, 0, $3, $4, &@$);
/*% ripper: params!(Qnil, $:1, Qnil, $:3, *$:4[0..2]) %*/
@@ -5104,24 +5061,15 @@ block_param : f_arg ',' f_optarg(primary_value) ',' f_rest_arg opt_args_tail(blo
}
;
-opt_block_param : none
- | block_param_def
- {
- p->command_start = TRUE;
- }
- ;
+opt_block_param_def : none
+ | block_param_def
+ {
+ p->command_start = TRUE;
+ }
+ ;
-block_param_def : '|' opt_bv_decl '|'
- {
- p->cur_arg = 0;
- p->max_numparam = ORDINAL_PARAM;
- p->ctxt.in_argdef = 0;
- $$ = 0;
- /*% ripper: block_var!(params!(Qnil,Qnil,Qnil,Qnil,Qnil,Qnil,Qnil), $:2) %*/
- }
- | '|' block_param opt_bv_decl '|'
+block_param_def : '|' opt_block_param opt_bv_decl '|'
{
- p->cur_arg = 0;
p->max_numparam = ORDINAL_PARAM;
p->ctxt.in_argdef = 0;
$$ = $2;
@@ -5129,6 +5077,13 @@ block_param_def : '|' opt_bv_decl '|'
}
;
+opt_block_param : /* none */
+ {
+ $$ = 0;
+ /*% ripper: params!(Qnil,Qnil,Qnil,Qnil,Qnil,Qnil,Qnil) %*/
+ }
+ | block_param
+ ;
opt_bv_decl : '\n'?
{
@@ -5154,9 +5109,6 @@ bvar : tIDENTIFIER
/*% ripper: $:1 %*/
}
| f_bad_arg
- {
- $$ = 0;
- }
;
max_numparam : {
@@ -5170,7 +5122,7 @@ numparam : {
}
;
-it_id : {
+it_id : {
$$ = p->it_id;
p->it_id = 0;
}
@@ -5180,7 +5132,6 @@ lambda : tLAMBDA[lpar]
{
token_info_push(p, "->", &@1);
$$ = dyna_push(p);
- p->lex.lpar_beg = p->lex.paren_nest;
}[dyna]<vars>
max_numparam numparam it_id allow_exits
f_larglist[args]
@@ -5198,11 +5149,12 @@ lambda : tLAMBDA[lpar]
CMDARG_POP();
$args = args_with_numbered(p, $args, max_numparam, it_id);
{
- YYLTYPE loc = code_loc_gen(&@args, &@body);
- $$ = NEW_LAMBDA($args, $body, &loc);
+ YYLTYPE loc = code_loc_gen(&@lpar, &@body);
+ $$ = NEW_LAMBDA($args, $body->node, &loc, &@lpar, &$body->opening_loc, &$body->closing_loc);
nd_set_line(RNODE_LAMBDA($$)->nd_body, @body.end_pos.lineno);
nd_set_line($$, @args.end_pos.lineno);
nd_set_first_loc($$, @1.beg_pos);
+ xfree($body);
}
/*% ripper: lambda!($:args, $:body) %*/
numparam_pop(p, $numparam);
@@ -5213,7 +5165,7 @@ lambda : tLAMBDA[lpar]
f_larglist : '(' f_args opt_bv_decl ')'
{
p->ctxt.in_argdef = 0;
- $$ = $2;
+ $$ = $f_args;
p->max_numparam = ORDINAL_PARAM;
/*% ripper: paren!($:2) %*/
}
@@ -5222,14 +5174,14 @@ f_larglist : '(' f_args opt_bv_decl ')'
p->ctxt.in_argdef = 0;
if (!args_info_empty_p(&$1->nd_ainfo))
p->max_numparam = ORDINAL_PARAM;
- $$ = $1;
+ $$ = $f_args;
}
;
-lambda_body : tLAMBEG compstmt '}'
+lambda_body : tLAMBEG compstmt(stmts) '}'
{
token_info_pop(p, "}", &@3);
- $$ = $2;
+ $$ = new_locations_lambda_body(p, $2, &@2, &@1, &@3);
/*% ripper: $:2 %*/
}
| keyword_do_LAMBDA
@@ -5238,7 +5190,7 @@ lambda_body : tLAMBEG compstmt '}'
}
bodystmt k_end
{
- $$ = $3;
+ $$ = new_locations_lambda_body(p, $3, &@3, &@1, &@4);
/*% ripper: $:3 %*/
}
;
@@ -5275,19 +5227,21 @@ block_call : command do_block
}
| block_call call_op2 operation2 opt_paren_args brace_block
{
- bool has_args = $5 != 0;
- if (NODE_EMPTY_ARGS_P($5)) $5 = 0;
+ if (NODE_EMPTY_ARGS_P($4)) $4 = 0;
$$ = new_command_qcall(p, $2, $1, $3, $4, $5, &@3, &@$);
- /*% ripper: command_call!($:1, $:2, $:3, $:4) %*/
- if (has_args) {
- /*% ripper: method_add_block!($:$, $:5) %*/
- }
+ /*% ripper: method_add_block!(command_call!($:1, $:2, $:3, $:4), $:5) %*/
}
| block_call call_op2 operation2 command_args do_block
{
$$ = new_command_qcall(p, $2, $1, $3, $4, $5, &@3, &@$);
/*% ripper: method_add_block!(command_call!($:1, $:2, $:3, $:4), $:5) %*/
}
+ | block_call call_op2 paren_args
+ {
+ $$ = new_qcall(p, $2, $1, idCall, $3, &@2, &@$);
+ nd_set_line($$, @2.end_pos.lineno);
+ /*% ripper: method_add_arg!(call!($:1, $:2, ID2VAL(idCall)), $:3) %*/
+ }
;
method_call : fcall paren_args
@@ -5319,21 +5273,20 @@ method_call : fcall paren_args
$$ = new_qcall(p, idCOLON2, $1, $3, 0, &@3, &@$);
/*% ripper: call!($:1, $:2, $:3) %*/
}
- | primary_value call_op paren_args
+ | primary_value call_op2 paren_args
{
$$ = new_qcall(p, $2, $1, idCall, $3, &@2, &@$);
nd_set_line($$, @2.end_pos.lineno);
/*% ripper: method_add_arg!(call!($:1, $:2, ID2VAL(idCall)), $:3) %*/
}
- | primary_value tCOLON2 paren_args
- {
- $$ = new_qcall(p, idCOLON2, $1, idCall, $3, &@2, &@$);
- nd_set_line($$, @2.end_pos.lineno);
- /*% ripper: method_add_arg!(call!($:1, $:2, ID2VAL(idCall)), $:3) %*/
- }
| keyword_super paren_args
{
- $$ = NEW_SUPER($2, &@$);
+ rb_code_location_t lparen_loc = @2;
+ rb_code_location_t rparen_loc = @2;
+ lparen_loc.end_pos.column = lparen_loc.beg_pos.column + 1;
+ rparen_loc.beg_pos.column = rparen_loc.end_pos.column - 1;
+
+ $$ = NEW_SUPER($2, &@$, &@1, &lparen_loc, &rparen_loc);
/*% ripper: super!($:2) %*/
}
| keyword_super
@@ -5365,7 +5318,7 @@ brace_block : '{' brace_body '}'
brace_body : {$$ = dyna_push(p);}[dyna]<vars>
max_numparam numparam it_id allow_exits
- opt_block_param[args] compstmt
+ opt_block_param_def[args] compstmt(stmts)
{
int max_numparam = p->max_numparam;
ID it_id = p->it_id;
@@ -5385,7 +5338,7 @@ do_body : {
CMDARG_PUSH(0);
}[dyna]<vars>
max_numparam numparam it_id allow_exits
- opt_block_param[args] bodystmt
+ opt_block_param_def[args] bodystmt
{
int max_numparam = p->max_numparam;
ID it_id = p->it_id;
@@ -5403,33 +5356,33 @@ do_body : {
case_args : arg_value
{
- check_literal_when(p, $1, &@1);
- $$ = NEW_LIST($1, &@$);
- /*% ripper: args_add!(args_new!, $:1) %*/
+ check_literal_when(p, $arg_value, &@arg_value);
+ $$ = NEW_LIST($arg_value, &@$);
+ /*% ripper: args_add!(args_new!, $:arg_value) %*/
}
| tSTAR arg_value
{
- $$ = NEW_SPLAT($2, &@$);
- /*% ripper: args_add_star!(args_new!, $:2) %*/
+ $$ = NEW_SPLAT($arg_value, &@$, &@tSTAR);
+ /*% ripper: args_add_star!(args_new!, $:arg_value) %*/
}
- | case_args ',' arg_value
+ | case_args[non_last_args] ',' arg_value
{
- check_literal_when(p, $3, &@3);
- $$ = last_arg_append(p, $1, $3, &@$);
- /*% ripper: args_add!($:1, $:3) %*/
+ check_literal_when(p, $arg_value, &@arg_value);
+ $$ = last_arg_append(p, $non_last_args, $arg_value, &@$);
+ /*% ripper: args_add!($:non_last_args, $:arg_value) %*/
}
- | case_args ',' tSTAR arg_value
+ | case_args[non_last_args] ',' tSTAR arg_value
{
- $$ = rest_arg_append(p, $1, $4, &@$);
- /*% ripper: args_add_star!($:1, $:4) %*/
+ $$ = rest_arg_append(p, $non_last_args, $arg_value, &@$);
+ /*% ripper: args_add_star!($:non_last_args, $:arg_value) %*/
}
;
case_body : k_when case_args then
- compstmt
+ compstmt(stmts)
cases
{
- $$ = NEW_WHEN($2, $4, $5, &@$);
+ $$ = NEW_WHEN($2, $4, $5, &@$, &@1, &@3);
fixpos($$, $2);
/*% ripper: when!($:2, $:4, $:5) %*/
}
@@ -5447,6 +5400,8 @@ p_in_kwarg : {
SET_LEX_STATE(EXPR_BEG|EXPR_LABEL);
p->command_start = FALSE;
p->ctxt.in_kwarg = 1;
+ p->ctxt.in_alt_pattern = 0;
+ p->ctxt.capture_in_pattern = 0;
}
;
@@ -5457,11 +5412,13 @@ p_case_body : keyword_in
pop_pktbl(p, $p_pktbl);
pop_pvtbl(p, $p_pvtbl);
p->ctxt.in_kwarg = $ctxt.in_kwarg;
+ p->ctxt.in_alt_pattern = $ctxt.in_alt_pattern;
+ p->ctxt.capture_in_pattern = $ctxt.capture_in_pattern;
}
- compstmt
+ compstmt(stmts)
p_cases[cases]
{
- $$ = NEW_IN($expr, $compstmt, $cases, &@$);
+ $$ = NEW_IN($expr, $compstmt, $cases, &@$, &@keyword_in, &@then, &NULL_LOC);
/*% ripper: in!($:expr, $:compstmt, $:cases) %*/
}
;
@@ -5473,13 +5430,13 @@ p_cases : opt_else
p_top_expr : p_top_expr_body
| p_top_expr_body modifier_if expr_value
{
- $$ = new_if(p, $3, $1, 0, &@$);
+ $$ = new_if(p, $3, $1, 0, &@$, &@2, &NULL_LOC, &NULL_LOC);
fixpos($$, $3);
/*% ripper: if_mod!($:3, $:1) %*/
}
| p_top_expr_body modifier_unless expr_value
{
- $$ = new_unless(p, $3, $1, 0, &@$);
+ $$ = new_unless(p, $3, $1, 0, &@$, &@2, &NULL_LOC, &NULL_LOC);
fixpos($$, $3);
/*% ripper: unless_mod!($:3, $:1) %*/
}
@@ -5528,10 +5485,18 @@ p_as : p_expr tASSOC p_variable
| p_alt
;
-p_alt : p_alt '|' p_expr_basic
+p_alt : p_alt[left] '|'[alt]
{
- $$ = NEW_OR($1, $3, &@$);
- /*% ripper: binary!($:1, ID2VAL(idOr), $:3) %*/
+ p->ctxt.in_alt_pattern = 1;
+ }
+ p_expr_basic[right]
+ {
+ if (p->ctxt.capture_in_pattern) {
+ yyerror1(&@alt, "alternative pattern after variable capture");
+ }
+ p->ctxt.in_alt_pattern = 0;
+ $$ = NEW_OR($left, $right, &@$, &@alt);
+ /*% ripper: binary!($:left, ID2VAL(idOr), $:right) %*/
}
| p_expr_basic
;
@@ -5677,9 +5642,6 @@ p_args : p_expr
;
p_args_head : p_arg ','
- {
- $$ = $1;
- }
| p_args_head p_arg ','
{
$$ = list_concat($1, $2);
@@ -5827,57 +5789,13 @@ p_any_kwrest : p_kwrest
;
p_value : p_primitive
- | p_primitive tDOT2 p_primitive
- {
- value_expr($1);
- value_expr($3);
- $$ = NEW_DOT2($1, $3, &@$);
- /*% ripper: dot2!($:1, $:3) %*/
- }
- | p_primitive tDOT3 p_primitive
- {
- value_expr($1);
- value_expr($3);
- $$ = NEW_DOT3($1, $3, &@$);
- /*% ripper: dot3!($:1, $:3) %*/
- }
- | p_primitive tDOT2
- {
- value_expr($1);
- $$ = NEW_DOT2($1, new_nil_at(p, &@2.end_pos), &@$);
- /*% ripper: dot2!($:1, Qnil) %*/
- }
- | p_primitive tDOT3
- {
- value_expr($1);
- $$ = NEW_DOT3($1, new_nil_at(p, &@2.end_pos), &@$);
- /*% ripper: dot3!($:1, Qnil) %*/
- }
+ | range_expr(p_primitive)
| p_var_ref
| p_expr_ref
| p_const
- | tBDOT2 p_primitive
- {
- value_expr($2);
- $$ = NEW_DOT2(new_nil_at(p, &@1.beg_pos), $2, &@$);
- /*% ripper: dot2!(Qnil, $:2) %*/
- }
- | tBDOT3 p_primitive
- {
- value_expr($2);
- $$ = NEW_DOT3(new_nil_at(p, &@1.beg_pos), $2, &@$);
- /*% ripper: dot3!(Qnil, $:2) %*/
- }
;
-p_primitive : literal
- | strings
- | xstring
- | regexp
- | words
- | qwords
- | symbols
- | qsymbols
+p_primitive : inline_primary
| keyword_variable
{
if (!($$ = gettable(p, $1, &@$))) $$ = NEW_ERROR(&@$);
@@ -5922,12 +5840,12 @@ p_expr_ref : '^' tLPAREN expr_value rparen
p_const : tCOLON3 cname
{
- $$ = NEW_COLON3($2, &@$);
+ $$ = NEW_COLON3($2, &@$, &@1, &@2);
/*% ripper: top_const_ref!($:2) %*/
}
| p_const tCOLON2 cname
{
- $$ = NEW_COLON2($1, $3, &@$);
+ $$ = NEW_COLON2($1, $3, &@$, &@2, &@3);
/*% ripper: const_path_ref!($:1, $:3) %*/
}
| tCONSTANT
@@ -5938,16 +5856,15 @@ p_const : tCOLON3 cname
;
opt_rescue : k_rescue exc_list exc_var then
- compstmt
+ compstmt(stmts)
opt_rescue
{
- NODE *body = $5;
+ NODE *err = $3;
if ($3) {
- NODE *err = NEW_ERRINFO(&@3);
+ err = NEW_ERRINFO(&@3);
err = node_assign(p, $3, err, NO_LEX_CTXT, &@3);
- body = block_append(p, err, body);
}
- $$ = NEW_RESBODY($2, body, $6, &@$);
+ $$ = NEW_RESBODY($2, $3, $5, $6, &@$);
if ($2) {
fixpos($$, $2);
}
@@ -5982,10 +5899,11 @@ exc_var : tASSOC lhs
| none
;
-opt_ensure : k_ensure compstmt
+opt_ensure : k_ensure stmts terms?
{
p->ctxt.in_rescue = $1.in_rescue;
$$ = $2;
+ void_expr(p, void_stmts(p, $$));
/*% ripper: ensure!($:2) %*/
}
| none
@@ -5997,14 +5915,12 @@ literal : numeric
strings : string
{
- NODE *node = $1;
- if (!node) {
- node = NEW_STR(STRING_NEW0(), &@$);
+ if (!$1) {
+ $$ = NEW_STR(STRING_NEW0(), &@$);
}
else {
- node = evstr2dstr(p, node);
+ $$ = evstr2dstr(p, $1);
}
- $$ = node;
/*% ripper: $:1 %*/
}
;
@@ -6045,12 +5961,12 @@ xstring : tXSTRING_BEG xstring_contents tSTRING_END
regexp : tREGEXP_BEG regexp_contents tREGEXP_END
{
- $$ = new_regexp(p, $2, $3, &@$);
+ $$ = new_regexp(p, $2, $3, &@$, &@1, &@2, &@3);
/*% ripper: regexp_literal!($:2, $:3) %*/
}
;
-words : words(tWORDS_BEG, word_list) <node>
+words : words(tWORDS_BEG, word_list)
;
word_list : /* none */
@@ -6074,7 +5990,7 @@ word : string_content
}
;
-symbols : words(tSYMBOLS_BEG, symbol_list) <node>
+symbols : words(tSYMBOLS_BEG, symbol_list)
;
symbol_list : /* none */
@@ -6089,10 +6005,10 @@ symbol_list : /* none */
}
;
-qwords : words(tQWORDS_BEG, qword_list) <node>
+qwords : words(tQWORDS_BEG, qword_list)
;
-qsymbols : words(tQSYMBOLS_BEG, qsym_list) <node>
+qsymbols : words(tQSYMBOLS_BEG, qsym_list)
;
qword_list : /* none */
@@ -6119,11 +6035,9 @@ qsym_list : /* none */
}
;
-string_contents : /* none */
+string_contents : /* none */
{
$$ = 0;
- /*%%%*/
- /*% %*/
/*% ripper: string_content! %*/
}
| string_contents string_content
@@ -6145,7 +6059,7 @@ xstring_contents: /* none */
}
;
-regexp_contents: /* none */
+regexp_contents : /* none */
{
$$ = 0;
/*% ripper: regexp_new! %*/
@@ -6188,7 +6102,7 @@ string_content : tSTRING_CONTENT
string_dvar
{
p->lex.strterm = $2;
- $$ = NEW_EVSTR($3, &@$);
+ $$ = NEW_EVSTR($3, &@$, &@1, &NULL_LOC);
nd_set_line($$, @3.end_pos.lineno);
/*% ripper: string_dvar!($:3) %*/
}
@@ -6209,7 +6123,7 @@ string_content : tSTRING_CONTENT
$$ = p->heredoc_indent;
p->heredoc_indent = 0;
}[indent]<num>
- compstmt string_dend
+ compstmt(stmts) string_dend
{
COND_POP();
CMDARG_POP();
@@ -6219,7 +6133,7 @@ string_content : tSTRING_CONTENT
p->heredoc_indent = $indent;
p->heredoc_line_indent = -1;
if ($compstmt) nd_unset_fl_newline($compstmt);
- $$ = new_evstr(p, $compstmt, &@$);
+ $$ = new_evstr(p, $compstmt, &@$, &@state, &@string_dend);
/*% ripper: string_embexpr!($:compstmt) %*/
}
;
@@ -6283,13 +6197,12 @@ simple_numeric : tINTEGER
| tIMAGINARY
;
-nonlocal_var : tIVAR
+nonlocal_var : tIVAR
| tGVAR
| tCVAR
;
-user_variable : tIDENTIFIER
- | tCONSTANT
+user_variable : ident_or_const
| nonlocal_var
;
@@ -6319,12 +6232,7 @@ var_ref : user_variable
}
;
-var_lhs : user_variable
- {
- /*% ripper: var_field!($:1) %*/
- $$ = assignable(p, $1, 0, &@$);
- }
- | keyword_variable
+var_lhs : user_or_keyword_variable
{
/*% ripper: var_field!($:1) %*/
$$ = assignable(p, $1, 0, &@$);
@@ -6345,11 +6253,7 @@ superclass : '<'
$$ = $3;
/*% ripper: $:3 %*/
}
- | /* none */
- {
- $$ = 0;
- /*% ripper: Qnil %*/
- }
+ | none
;
f_opt_paren_args: f_paren_args
@@ -6390,51 +6294,40 @@ f_arglist : f_paren_args
}
;
-args_tail : f_kwarg(f_kw) ',' f_kwrest opt_f_block_arg
- {
- $$ = new_args_tail(p, $1, $3, $4, &@3);
- /*% ripper: [$:1, $:3, $:4] %*/
- }
- | f_kwarg(f_kw) opt_f_block_arg
- {
- $$ = new_args_tail(p, $1, 0, $2, &@1);
- /*% ripper: [$:1, Qnil, $:2] %*/
- }
- | f_any_kwrest opt_f_block_arg
- {
- $$ = new_args_tail(p, 0, $1, $2, &@1);
- /*% ripper: [Qnil, $:1, $:2] %*/
- }
- | f_block_arg
- {
- $$ = new_args_tail(p, 0, 0, $1, &@1);
- /*% ripper: [Qnil, Qnil, $:1] %*/
- }
+args_tail : args_tail_basic(arg_value)
| args_forward
{
- add_forwarding_args(p);
- $$ = new_args_tail(p, 0, $1, arg_FWD_BLOCK, &@1);
+ ID fwd = $args_forward;
+ if (lambda_beginning_p() ||
+ (p->lex.lpar_beg >= 0 && p->lex.lpar_beg+1 == p->lex.paren_nest)) {
+ yyerror0("unexpected ... in lambda argument");
+ fwd = 0;
+ }
+ else {
+ add_forwarding_args(p);
+ }
+ $$ = new_args_tail(p, 0, fwd, arg_FWD_BLOCK, &@1);
$$->nd_ainfo.forwarding = 1;
/*% ripper: [Qnil, $:1, Qnil] %*/
}
;
-f_args : f_arg ',' f_optarg(arg_value) ',' f_rest_arg opt_args_tail(args_tail)
+f_args : f_arg ',' f_opt_arg(arg_value) ',' f_rest_arg opt_args_tail(args_tail)
{
$$ = new_args(p, $1, $3, $5, 0, $6, &@$);
/*% ripper: params!($:1, $:3, $:5, Qnil, *$:6[0..2]) %*/
}
- | f_arg ',' f_optarg(arg_value) ',' f_rest_arg ',' f_arg opt_args_tail(args_tail)
+ | f_arg ',' f_opt_arg(arg_value) ',' f_rest_arg ',' f_arg opt_args_tail(args_tail)
{
$$ = new_args(p, $1, $3, $5, $7, $8, &@$);
/*% ripper: params!($:1, $:3, $:5, $:7, *$:8[0..2]) %*/
}
- | f_arg ',' f_optarg(arg_value) opt_args_tail(args_tail)
+ | f_arg ',' f_opt_arg(arg_value) opt_args_tail(args_tail)
{
$$ = new_args(p, $1, $3, 0, 0, $4, &@$);
/*% ripper: params!($:1, $:3, Qnil, Qnil, *$:4[0..2]) %*/
}
- | f_arg ',' f_optarg(arg_value) ',' f_arg opt_args_tail(args_tail)
+ | f_arg ',' f_opt_arg(arg_value) ',' f_arg opt_args_tail(args_tail)
{
$$ = new_args(p, $1, $3, 0, $5, $6, &@$);
/*% ripper: params!($:1, $:3, Qnil, $:5, *$:6[0..2]) %*/
@@ -6454,22 +6347,22 @@ f_args : f_arg ',' f_optarg(arg_value) ',' f_rest_arg opt_args_tail(args_tail)
$$ = new_args(p, $1, 0, 0, 0, $2, &@$);
/*% ripper: params!($:1, Qnil, Qnil, Qnil, *$:2[0..2]) %*/
}
- | f_optarg(arg_value) ',' f_rest_arg opt_args_tail(args_tail)
+ | f_opt_arg(arg_value) ',' f_rest_arg opt_args_tail(args_tail)
{
$$ = new_args(p, 0, $1, $3, 0, $4, &@$);
/*% ripper: params!(Qnil, $:1, $:3, Qnil, *$:4[0..2]) %*/
}
- | f_optarg(arg_value) ',' f_rest_arg ',' f_arg opt_args_tail(args_tail)
+ | f_opt_arg(arg_value) ',' f_rest_arg ',' f_arg opt_args_tail(args_tail)
{
$$ = new_args(p, 0, $1, $3, $5, $6, &@$);
/*% ripper: params!(Qnil, $:1, $:3, $:5, *$:6[0..2]) %*/
}
- | f_optarg(arg_value) opt_args_tail(args_tail)
+ | f_opt_arg(arg_value) opt_args_tail(args_tail)
{
$$ = new_args(p, 0, $1, 0, 0, $2, &@$);
/*% ripper: params!(Qnil, $:1, Qnil, Qnil, *$:2[0..2]) %*/
}
- | f_optarg(arg_value) ',' f_arg opt_args_tail(args_tail)
+ | f_opt_arg(arg_value) ',' f_arg opt_args_tail(args_tail)
{
$$ = new_args(p, 0, $1, 0, $3, $4, &@$);
/*% ripper: params!(Qnil, $:1, Qnil, $:3, *$:4[0..2]) %*/
@@ -6499,11 +6392,7 @@ f_args : f_arg ',' f_optarg(arg_value) ',' f_rest_arg opt_args_tail(args_tail)
args_forward : tBDOT3
{
-#ifdef FORWARD_ARGS_WITH_RUBY2_KEYWORDS
- $$ = 0;
-#else
$$ = idFWD_KWREST;
-#endif
/*% ripper: args_forward! %*/
}
;
@@ -6549,25 +6438,23 @@ f_bad_arg : tCONSTANT
f_norm_arg : f_bad_arg
| tIDENTIFIER
{
- formal_argument(p, $1);
+ VALUE e = formal_argument_error(p, $$ = $1);
+ if (e) {
+ /*% ripper[error]: param_error!(?e, $:1) %*/
+ }
p->max_numparam = ORDINAL_PARAM;
- $$ = $1;
- /*% ripper: ripper_formal_argument(p, $1, $:1) %*/
}
;
f_arg_asgn : f_norm_arg
{
- ID id = $1;
- arg_var(p, id);
- p->cur_arg = id;
+ arg_var(p, $1);
$$ = $1;
}
;
f_arg_item : f_arg_asgn
{
- p->cur_arg = 0;
$$ = NEW_ARGS_AUX($1, 1, &NULL_LOC);
/*% ripper: $:1 %*/
}
@@ -6605,42 +6492,21 @@ f_arg : f_arg_item
f_label : tLABEL
{
- arg_var(p, formal_argument(p, $1));
- p->cur_arg = $1;
+ VALUE e = formal_argument_error(p, $$ = $1);
+ if (e) {
+ $$ = 0;
+ /*% ripper[error]: param_error!(?e, $:1) %*/
+ }
+ /*
+ * Workaround for Prism::ParseTest#test_filepath for
+ * "unparser/corpus/literal/def.txt"
+ *
+ * See the discussion on https://github.com/ruby/ruby/pull/9923
+ */
+ arg_var(p, ifdef_ripper(0, $1));
+ /*% ripper: $:1 %*/
p->max_numparam = ORDINAL_PARAM;
p->ctxt.in_argdef = 0;
- $$ = $1;
- /*% ripper: ripper_formal_argument(p, $1, $:1) %*/
- }
- ;
-
-f_kw : f_label arg_value
- {
- p->cur_arg = 0;
- p->ctxt.in_argdef = 1;
- $$ = new_kw_arg(p, assignable(p, $1, $2, &@$), &@$);
- /*% ripper: [$:$, $:2] %*/
- }
- | f_label
- {
- p->cur_arg = 0;
- p->ctxt.in_argdef = 1;
- $$ = new_kw_arg(p, assignable(p, $1, NODE_SPECIAL_REQUIRED_KEYWORD, &@$), &@$);
- /*% ripper: [$:$, 0] %*/
- }
- ;
-
-f_block_kw : f_label primary_value
- {
- p->ctxt.in_argdef = 1;
- $$ = new_kw_arg(p, assignable(p, $1, $2, &@$), &@$);
- /*% ripper: [$:$, $:2] %*/
- }
- | f_label
- {
- p->ctxt.in_argdef = 1;
- $$ = new_kw_arg(p, assignable(p, $1, NODE_SPECIAL_REQUIRED_KEYWORD, &@$), &@$);
- /*% ripper: [$:$, 0] %*/
}
;
@@ -6710,20 +6576,12 @@ opt_f_block_arg : ',' f_block_arg
/*% ripper: $:2 %*/
}
| none
- {
- $$ = 0;
- /*% ripper: Qnil %*/
- }
;
-singleton : var_ref
- {
- value_expr($1);
- $$ = $1;
- }
- | '(' {SET_LEX_STATE(EXPR_BEG);} expr rparen
+
+singleton : value_expr(singleton_expr)
{
- NODE *expr = last_expr_node($3);
+ NODE *expr = last_expr_node($1);
switch (nd_type(expr)) {
case NODE_STR:
case NODE_DSTR:
@@ -6745,9 +6603,21 @@ singleton : var_ref
yyerror1(&expr->nd_loc, "can't define singleton method for literals");
break;
default:
- value_expr($3);
break;
}
+ $$ = $1;
+ }
+ ;
+
+singleton_expr : var_ref
+ | '('
+ {
+ SET_LEX_STATE(EXPR_BEG);
+ p->ctxt.in_argdef = 0;
+ }
+ expr rparen
+ {
+ p->ctxt.in_argdef = 1;
$$ = $3;
/*% ripper: paren!($:3) %*/
}
@@ -6825,10 +6695,9 @@ assoc : arg_value tASSOC arg_value
}
;
-operation : tIDENTIFIER
- | tCONSTANT
- | tFID
- ;
+%rule %inline operation : ident_or_const
+ | tFID
+ ;
operation2 : operation
| op
@@ -6864,7 +6733,14 @@ trailer : '\n'?
| ','
;
-term : ';' {yyerrok;token_flush(p);}
+term : ';'
+ {
+ yyerrok;
+ token_flush(p);
+ if (p->ctxt.in_defined) {
+ p->ctxt.has_trailing_semicolon = 1;
+ }
+ }
| '\n'
{
@$.end_pos = @$.beg_pos;
@@ -6879,6 +6755,7 @@ terms : term
none : /* none */
{
$$ = 0;
+ /*% ripper: Qnil %*/
}
;
%%
@@ -6893,11 +6770,7 @@ static void tokaddmbc(struct parser_params *p, int c, rb_encoding *enc);
static enum yytokentype parse_string(struct parser_params*,rb_strterm_literal_t*);
static enum yytokentype here_document(struct parser_params*,rb_strterm_heredoc_t*);
-#ifndef RIPPER
-#define set_parser_s_value(x) (void)(x)
-#else
-#define set_parser_s_value(x) (p->s_value = (x))
-#endif
+#define set_parser_s_value(x) (ifdef_ripper(p->s_value = (x), (void)0))
# define set_yylval_node(x) { \
YYLTYPE _cur_loc; \
@@ -6907,8 +6780,8 @@ static enum yytokentype here_document(struct parser_params*,rb_strterm_heredoc_t
}
# define set_yylval_str(x) \
do { \
- set_yylval_node(NEW_STR(rb_str_to_parser_string(p, x), &_cur_loc)); \
- set_parser_s_value(x); \
+ set_yylval_node(NEW_STR(x, &_cur_loc)); \
+ set_parser_s_value(rb_str_new_mutable_parser_string(x)); \
} while(0)
# define set_yylval_num(x) { \
yylval.num = (x); \
@@ -6969,14 +6842,13 @@ rb_parser_str_escape(struct parser_params *p, rb_parser_string_t *str)
const char *prev = ptr;
char charbuf[5] = {'\\', 'x', 0, 0, 0};
rb_parser_string_t * result = rb_parser_string_new(p, 0, 0);
- int asciicompat = rb_enc_asciicompat(enc);
while (ptr < pend) {
unsigned int c;
const char *cc;
int n = rb_enc_precise_mbclen(ptr, pend, enc);
if (!MBCLEN_CHARFOUND_P(n)) {
- if (ptr > prev) rb_parser_str_buf_cat(p, result, prev, ptr - prev);
+ if (ptr > prev) parser_str_cat(result, prev, ptr - prev);
n = rb_enc_mbminlen(enc);
if (pend < ptr + n)
n = (int)(pend - ptr);
@@ -6985,7 +6857,7 @@ rb_parser_str_escape(struct parser_params *p, rb_parser_string_t *str)
charbuf[2] = (c < 10) ? '0' + c : 'A' + c - 10;
c = *ptr & 0x0f;
charbuf[3] = (c < 10) ? '0' + c : 'A' + c - 10;
- rb_parser_str_buf_cat(p, result, charbuf, 4);
+ parser_str_cat(result, charbuf, 4);
prev = ++ptr;
}
continue;
@@ -6995,22 +6867,22 @@ rb_parser_str_escape(struct parser_params *p, rb_parser_string_t *str)
ptr += n;
cc = escaped_char(c);
if (cc) {
- if (ptr - n > prev) rb_parser_str_buf_cat(p, result, prev, ptr - n - prev);
- rb_parser_str_buf_cat(p, result, cc, strlen(cc));
+ if (ptr - n > prev) parser_str_cat(result, prev, ptr - n - prev);
+ parser_str_cat_cstr(result, cc);
prev = ptr;
}
- else if (asciicompat && rb_enc_isascii(c, enc) && ISPRINT(c)) {
+ else if (rb_enc_isascii(c, enc) && ISPRINT(c)) {
}
else {
if (ptr - n > prev) {
- rb_parser_str_buf_cat(p, result, prev, ptr - n - prev);
+ parser_str_cat(result, prev, ptr - n - prev);
prev = ptr - n;
}
- rb_parser_str_buf_cat(p, result, prev, ptr - prev);
+ parser_str_cat(result, prev, ptr - prev);
prev = ptr;
}
}
- if (ptr > prev) rb_parser_str_buf_cat(p, result, prev, ptr - prev);
+ if (ptr > prev) parser_str_cat(result, prev, ptr - prev);
return result;
}
@@ -7067,7 +6939,8 @@ parser_dispatch_delayed_token(struct parser_params *p, enum yytokentype t, int l
if (p->keep_tokens) {
/* p->delayed.token is freed by rb_parser_tokens_free */
parser_append_tokens(p, p->delayed.token, t, line);
- } else {
+ }
+ else {
rb_parser_string_free(p, p->delayed.token);
}
@@ -7130,6 +7003,16 @@ is_identchar(struct parser_params *p, const char *ptr, const char *MAYBE_UNUSED(
return rb_enc_isalnum((unsigned char)*ptr, enc) || *ptr == '_' || !ISASCII(*ptr);
}
+static inline bool
+peek_word_at(struct parser_params *p, const char *str, size_t len, int at)
+{
+ const char *ptr = p->lex.pcur + at;
+ if (lex_eol_ptr_n_p(p, ptr, len-1)) return false;
+ if (memcmp(ptr, str, len)) return false;
+ if (lex_eol_ptr_n_p(p, ptr, len)) return true;
+ return !is_identchar(p, ptr+len, p->lex.pend, p->enc);
+}
+
static inline int
parser_is_identchar(struct parser_params *p)
{
@@ -7181,10 +7064,11 @@ token_info_pop(struct parser_params *p, const char *token, const rb_code_locatio
token_info *ptinfo_beg = p->token_info;
if (!ptinfo_beg) return;
- p->token_info = ptinfo_beg->next;
/* indentation check of matched keywords (begin..end, if..end, etc.) */
token_info_warn(p, token, ptinfo_beg, 1, loc);
+
+ p->token_info = ptinfo_beg->next;
ruby_sized_xfree(ptinfo_beg, sizeof(*ptinfo_beg));
}
@@ -7334,7 +7218,7 @@ ruby_show_error_line(struct parser_params *p, VALUE errbuf, const YYLTYPE *yyllo
}
if (RTEST(errbuf)) {
mesg = rb_attr_get(errbuf, idMesg);
- if (RSTRING_LEN(mesg) > 0 && *(RSTRING_END(mesg)-1) != '\n')
+ if (char_at_end(p, mesg, '\n') != '\n')
rb_str_cat_cstr(mesg, "\n");
}
else {
@@ -7673,21 +7557,24 @@ enum string_type {
str_dsym = (STR_FUNC_SYMBOL|STR_FUNC_EXPAND)
};
-static VALUE
+static rb_parser_string_t *
parser_str_new(struct parser_params *p, const char *ptr, long len, rb_encoding *enc, int func, rb_encoding *enc0)
{
- VALUE str;
+ rb_parser_string_t *pstr;
- str = rb_enc_str_new(ptr, len, enc);
- if (!(func & STR_FUNC_REGEXP) && rb_enc_asciicompat(enc)) {
- if (is_ascii_string(str)) {
+ pstr = rb_parser_encoding_string_new(p, ptr, len, enc);
+
+ if (!(func & STR_FUNC_REGEXP)) {
+ if (rb_parser_is_ascii_string(p, pstr)) {
}
else if (rb_is_usascii_enc((void *)enc0) && enc != rb_utf8_encoding()) {
- rb_enc_associate(str, rb_ascii8bit_encoding());
+ /* everything is valid in ASCII-8BIT */
+ enc = rb_ascii8bit_encoding();
+ PARSER_ENCODING_CODERANGE_SET(pstr, enc, RB_PARSER_ENC_CODERANGE_VALID);
}
}
- return str;
+ return pstr;
}
static int
@@ -7719,16 +7606,15 @@ new_heredoc(struct parser_params *p)
#define peekc(p) peekc_n(p, 0)
#define peekc_n(p,n) (lex_eol_n_p(p, n) ? -1 : (unsigned char)(p)->lex.pcur[n])
+#define add_delayed_token(p, tok, end) parser_add_delayed_token(p, tok, end, __LINE__)
static void
-add_delayed_token(struct parser_params *p, const char *tok, const char *end, int line)
+parser_add_delayed_token(struct parser_params *p, const char *tok, const char *end, int line)
{
-#ifndef RIPPER
debug_token_line(p, "add_delayed_token", line);
-#endif
if (tok < end) {
if (has_delayed_token(p)) {
- bool next_line = parser_string_end_with_newline_p(p, p->delayed.token);
+ bool next_line = parser_string_char_at_end(p, p->delayed.token, 0) == '\n';
int end_line = (next_line ? 1 : 0) + p->delayed.end_line;
int end_col = (next_line ? 0 : p->delayed.end_col);
if (end_line != p->ruby_sourceline || end_col != tok - p->lex.pbeg) {
@@ -7741,7 +7627,7 @@ add_delayed_token(struct parser_params *p, const char *tok, const char *end, int
p->delayed.beg_line = p->ruby_sourceline;
p->delayed.beg_col = rb_long2int(tok - p->lex.pbeg);
}
- rb_parser_str_buf_cat(p, p->delayed.token, tok, end - tok);
+ parser_str_cat(p->delayed.token, tok, end - tok);
p->delayed.end_line = p->ruby_sourceline;
p->delayed.end_col = rb_long2int(end - p->lex.pbeg);
p->lex.ptok = end;
@@ -7784,11 +7670,11 @@ nextline(struct parser_params *p, int set_encoding)
#endif
p->cr_seen = FALSE;
}
- else if (str == AFTER_HEREDOC_WITHOUT_TERMINTOR) {
+ else if (str == AFTER_HEREDOC_WITHOUT_TERMINATOR) {
/* after here-document without terminator */
goto end_of_input;
}
- add_delayed_token(p, p->lex.ptok, p->lex.pend, __LINE__);
+ add_delayed_token(p, p->lex.ptok, p->lex.pend);
if (p->heredoc_end > 0) {
p->ruby_sourceline = p->heredoc_end;
p->heredoc_end = 0;
@@ -7814,7 +7700,7 @@ nextc0(struct parser_params *p, int set_encoding)
{
int c;
- if (UNLIKELY(lex_eol_p(p) || p->eofp || p->lex.nextline > AFTER_HEREDOC_WITHOUT_TERMINTOR)) {
+ if (UNLIKELY(lex_eol_p(p) || p->eofp || p->lex.nextline > AFTER_HEREDOC_WITHOUT_TERMINATOR)) {
if (nextline(p, set_encoding)) return -1;
}
c = (unsigned char)*p->lex.pcur++;
@@ -7901,6 +7787,7 @@ tok_hex(struct parser_params *p, size_t *numlen)
c = (int)ruby_scan_hex(p->lex.pcur, 2, numlen);
if (!*numlen) {
+ flush_string_content(p, p->enc, rb_strlen_lit("\\x"));
yyerror0("invalid hex escape");
dispatch_scan_event(p, tSTRING_CONTENT);
return 0;
@@ -7943,27 +7830,33 @@ escaped_control_code(int c)
static int
tokadd_codepoint(struct parser_params *p, rb_encoding **encp,
- int regexp_literal, int wide)
+ int regexp_literal, const char *begin)
{
+ const int wide = !begin;
size_t numlen;
int codepoint = (int)ruby_scan_hex(p->lex.pcur, wide ? p->lex.pend - p->lex.pcur : 4, &numlen);
+
p->lex.pcur += numlen;
if (p->lex.strterm == NULL ||
strterm_is_heredoc(p->lex.strterm) ||
(p->lex.strterm->u.literal.func != str_regexp)) {
+ if (!begin) begin = p->lex.pcur;
if (wide ? (numlen == 0 || numlen > 6) : (numlen < 4)) {
- literal_flush(p, p->lex.pcur);
+ flush_string_content(p, rb_utf8_encoding(), p->lex.pcur - begin);
yyerror0("invalid Unicode escape");
+ dispatch_scan_event(p, tSTRING_CONTENT);
return wide && numlen > 0;
}
if (codepoint > 0x10ffff) {
- literal_flush(p, p->lex.pcur);
+ flush_string_content(p, rb_utf8_encoding(), p->lex.pcur - begin);
yyerror0("invalid Unicode codepoint (too large)");
+ dispatch_scan_event(p, tSTRING_CONTENT);
return wide;
}
if ((codepoint & 0xfffff800) == 0xd800) {
- literal_flush(p, p->lex.pcur);
+ flush_string_content(p, rb_utf8_encoding(), p->lex.pcur - begin);
yyerror0("invalid Unicode codepoint");
+ dispatch_scan_event(p, tSTRING_CONTENT);
return wide;
}
}
@@ -8051,7 +7944,7 @@ tokadd_utf8(struct parser_params *p, rb_encoding **encp,
if (second == multiple_codepoints)
second = p->lex.pcur;
if (regexp_literal) tokadd(p, last);
- if (!tokadd_codepoint(p, encp, regexp_literal, TRUE)) {
+ if (!tokadd_codepoint(p, encp, regexp_literal, NULL)) {
break;
}
while (ISSPACE(c = peekc(p))) {
@@ -8064,8 +7957,9 @@ tokadd_utf8(struct parser_params *p, rb_encoding **encp,
if (c != close_brace) {
unterminated:
- token_flush(p);
+ flush_string_content(p, rb_utf8_encoding(), 0);
yyerror0("unterminated Unicode escape");
+ dispatch_scan_event(p, tSTRING_CONTENT);
return;
}
if (second && second != multiple_codepoints) {
@@ -8083,7 +7977,7 @@ tokadd_utf8(struct parser_params *p, rb_encoding **encp,
}
}
else { /* handle \uxxxx form */
- if (!tokadd_codepoint(p, encp, regexp_literal, FALSE)) {
+ if (!tokadd_codepoint(p, encp, regexp_literal, p->lex.pcur - rb_strlen_lit("\\u"))) {
token_flush(p);
return;
}
@@ -8094,7 +7988,7 @@ tokadd_utf8(struct parser_params *p, rb_encoding **encp,
#define ESCAPE_META 2
static int
-read_escape(struct parser_params *p, int flags)
+read_escape(struct parser_params *p, int flags, const char *begin)
{
int c;
size_t numlen;
@@ -8153,7 +8047,7 @@ read_escape(struct parser_params *p, int flags)
nextc(p);
goto eof;
}
- return read_escape(p, flags|ESCAPE_META) | 0x80;
+ return read_escape(p, flags|ESCAPE_META, begin) | 0x80;
}
else if (c == -1) goto eof;
else if (!ISASCII(c)) {
@@ -8186,7 +8080,7 @@ read_escape(struct parser_params *p, int flags)
nextc(p);
goto eof;
}
- c = read_escape(p, flags|ESCAPE_CONTROL);
+ c = read_escape(p, flags|ESCAPE_CONTROL, begin);
}
else if (c == '?')
return 0177;
@@ -8221,11 +8115,16 @@ read_escape(struct parser_params *p, int flags)
eof:
case -1:
+ flush_string_content(p, p->enc, p->lex.pcur - begin);
yyerror0("Invalid escape character syntax");
dispatch_scan_event(p, tSTRING_CONTENT);
return '\0';
default:
+ if (!ISASCII(c)) {
+ tokskip_mbchar(p);
+ goto eof;
+ }
return c;
}
}
@@ -8242,6 +8141,7 @@ tokadd_escape(struct parser_params *p)
{
int c;
size_t numlen;
+ const char *begin = p->lex.pcur;
switch (c = nextc(p)) {
case '\n':
@@ -8267,6 +8167,7 @@ tokadd_escape(struct parser_params *p)
eof:
case -1:
+ flush_string_content(p, p->enc, p->lex.pcur - begin);
yyerror0("Invalid escape character syntax");
token_flush(p);
return -1;
@@ -8537,7 +8438,7 @@ tokadd_string(struct parser_params *p,
case 'C':
case 'M': {
pushback(p, c);
- c = read_escape(p, 0);
+ c = read_escape(p, 0, p->lex.pcur - 1);
char *t = tokspace(p, rb_strlen_lit("\\x00"));
*t++ = '\\';
@@ -8563,7 +8464,7 @@ tokadd_string(struct parser_params *p,
else if (func & STR_FUNC_EXPAND) {
pushback(p, c);
if (func & STR_FUNC_ESCAPE) tokadd(p, '\\');
- c = read_escape(p, 0);
+ c = read_escape(p, 0, p->lex.pcur - 1);
}
else if ((func & STR_FUNC_QWORDS) && ISSPACE(c)) {
/* ignore backslashed spaces in %w */
@@ -8613,8 +8514,9 @@ tokadd_string(struct parser_params *p,
#define NEW_STRTERM(func, term, paren) new_strterm(p, func, term, paren)
static void
-flush_string_content(struct parser_params *p, rb_encoding *enc)
+flush_string_content(struct parser_params *p, rb_encoding *enc, size_t back)
{
+ p->lex.pcur -= back;
if (has_delayed_token(p)) {
ptrdiff_t len = p->lex.pcur - p->lex.ptok;
if (len > 0) {
@@ -8626,9 +8528,9 @@ flush_string_content(struct parser_params *p, rb_encoding *enc)
p->lex.ptok = p->lex.pcur;
}
dispatch_scan_event(p, tSTRING_CONTENT);
+ p->lex.pcur += back;
}
-RUBY_FUNC_EXPORTED const uint_least32_t ruby_global_name_punct_bits[(0x7e - 0x20 + 31) / 32];
/* this can be shared with ripper, since it's independent from struct
* parser_params. */
#ifndef RIPPER
@@ -8725,7 +8627,7 @@ parse_string(struct parser_params *p, rb_strterm_literal_t *quote)
int c, space = 0;
rb_encoding *enc = p->enc;
rb_encoding *base_enc = 0;
- VALUE lit;
+ rb_parser_string_t *lit;
if (func & STR_FUNC_TERM) {
if (func & STR_FUNC_QWORDS) nextc(p); /* delayed term */
@@ -8747,14 +8649,14 @@ parse_string(struct parser_params *p, rb_strterm_literal_t *quote)
if (func & STR_FUNC_QWORDS) {
quote->func |= STR_FUNC_TERM;
pushback(p, c); /* dispatch the term at tSTRING_END */
- add_delayed_token(p, p->lex.ptok, p->lex.pcur, __LINE__);
+ add_delayed_token(p, p->lex.ptok, p->lex.pcur);
return ' ';
}
return parser_string_term(p, func);
}
if (space) {
if (!ISSPACE(c)) pushback(p, c);
- add_delayed_token(p, p->lex.ptok, p->lex.pcur, __LINE__);
+ add_delayed_token(p, p->lex.ptok, p->lex.pcur);
return ' ';
}
newtok(p);
@@ -8794,7 +8696,7 @@ parse_string(struct parser_params *p, rb_strterm_literal_t *quote)
tokfix(p);
lit = STR_NEW3(tok(p), toklen(p), enc, func);
set_yylval_str(lit);
- flush_string_content(p, enc);
+ flush_string_content(p, enc, 0);
return tSTRING_CONTENT;
}
@@ -8898,7 +8800,7 @@ heredoc_restore(struct parser_params *p, rb_strterm_heredoc_t *here)
p->lex.ptok = p->lex.pbeg + here->offset - here->quote;
p->heredoc_end = p->ruby_sourceline;
p->ruby_sourceline = (int)here->sourceline;
- if (p->eofp) p->lex.nextline = AFTER_HEREDOC_WITHOUT_TERMINTOR;
+ if (p->eofp) p->lex.nextline = AFTER_HEREDOC_WITHOUT_TERMINATOR;
p->eofp = 0;
xfree(term);
}
@@ -9101,21 +9003,6 @@ set_number_literal(struct parser_params *p, enum yytokentype type, int suffix, i
return type;
}
-#ifdef RIPPER
-static void
-dispatch_heredoc_end(struct parser_params *p)
-{
- VALUE str;
- if (has_delayed_token(p))
- dispatch_delayed_token(p, tSTRING_CONTENT);
- str = STR_NEW(p->lex.ptok, p->lex.pend - p->lex.ptok);
- ripper_dispatch1(p, ripper_token2eventid(tHEREDOC_END), str);
- RUBY_SET_YYLLOC_FROM_STRTERM_HEREDOC(*p->yylloc);
- lex_goto_eol(p);
- token_flush(p);
-}
-
-#else
#define dispatch_heredoc_end(p) parser_dispatch_heredoc_end(p, __LINE__)
static void
parser_dispatch_heredoc_end(struct parser_params *p, int line)
@@ -9123,17 +9010,21 @@ parser_dispatch_heredoc_end(struct parser_params *p, int line)
if (has_delayed_token(p))
dispatch_delayed_token(p, tSTRING_CONTENT);
+#ifdef RIPPER
+ VALUE str = STR_NEW(p->lex.ptok, p->lex.pend - p->lex.ptok);
+ ripper_dispatch1(p, ripper_token2eventid(tHEREDOC_END), str);
+#else
if (p->keep_tokens) {
rb_parser_string_t *str = rb_parser_encoding_string_new(p, p->lex.ptok, p->lex.pend - p->lex.ptok, p->enc);
RUBY_SET_YYLLOC_OF_HEREDOC_END(*p->yylloc);
parser_append_tokens(p, str, tHEREDOC_END, line);
}
+#endif
RUBY_SET_YYLLOC_FROM_STRTERM_HEREDOC(*p->yylloc);
lex_goto_eol(p);
token_flush(p);
}
-#endif
static enum yytokentype
here_document(struct parser_params *p, rb_strterm_heredoc_t *here)
@@ -9141,7 +9032,7 @@ here_document(struct parser_params *p, rb_strterm_heredoc_t *here)
int c, func, indent = 0;
const char *eos, *ptr, *ptr_end;
long len;
- VALUE str = 0;
+ rb_parser_string_t *str = 0;
rb_encoding *enc = p->enc;
rb_encoding *base_enc = 0;
int bol;
@@ -9159,9 +9050,9 @@ here_document(struct parser_params *p, rb_strterm_heredoc_t *here)
if (!has_delayed_token(p)) {
dispatch_scan_event(p, tSTRING_CONTENT);
}
- else {
+ else if (p->delayed.end_line + 1 == p->ruby_sourceline) {
if ((len = p->lex.pcur - p->lex.ptok) > 0) {
- if (!(func & STR_FUNC_REGEXP) && rb_enc_asciicompat(enc)) {
+ if (!(func & STR_FUNC_REGEXP)) {
int cr = ENC_CODERANGE_UNKNOWN;
rb_str_coderange_scan_restartable(p->lex.ptok, p->lex.pcur, enc, &cr);
if (cr != ENC_CODERANGE_7BIT &&
@@ -9174,6 +9065,10 @@ here_document(struct parser_params *p, rb_strterm_heredoc_t *here)
}
dispatch_delayed_token(p, tSTRING_CONTENT);
}
+ else {
+ dispatch_delayed_token(p, tSTRING_CONTENT);
+ dispatch_scan_event(p, tSTRING_CONTENT);
+ }
lex_goto_eol(p);
#endif
heredoc_restore(p, &p->lex.strterm->u.heredoc);
@@ -9227,16 +9122,17 @@ here_document(struct parser_params *p, rb_strterm_heredoc_t *here)
}
if (str)
- rb_str_cat(str, ptr, ptr_end - ptr);
+ parser_str_cat(str, ptr, ptr_end - ptr);
else
- str = STR_NEW(ptr, ptr_end - ptr);
- if (!lex_eol_ptr_p(p, ptr_end)) rb_str_cat(str, "\n", 1);
+ str = rb_parser_encoding_string_new(p, ptr, ptr_end - ptr, enc);
+ if (!lex_eol_ptr_p(p, ptr_end)) parser_str_cat_cstr(str, "\n");
lex_goto_eol(p);
if (p->heredoc_indent > 0) {
goto flush_str;
}
if (nextc(p) == -1) {
if (str) {
+ rb_parser_string_free(p, str);
str = 0;
}
goto error;
@@ -9274,7 +9170,7 @@ here_document(struct parser_params *p, rb_strterm_heredoc_t *here)
#ifndef RIPPER
if (bol) nd_set_fl_newline(yylval.node);
#endif
- flush_string_content(p, enc);
+ flush_string_content(p, enc, 0);
return tSTRING_CONTENT;
}
tokadd(p, nextc(p));
@@ -9324,72 +9220,35 @@ arg_ambiguous(struct parser_params *p, char c)
return TRUE;
}
-static ID
-formal_argument(struct parser_params *p, ID id)
+/* returns true value if formal argument error;
+ * Qtrue, or error message if ripper */
+static VALUE
+formal_argument_error(struct parser_params *p, ID id)
{
switch (id_type(id)) {
case ID_LOCAL:
break;
-#define ERR(mesg) yyerror0(mesg)
- case ID_CONST:
- ERR("formal argument cannot be a constant");
- return 0;
- case ID_INSTANCE:
- ERR("formal argument cannot be an instance variable");
- return 0;
- case ID_GLOBAL:
- ERR("formal argument cannot be a global variable");
- return 0;
- case ID_CLASS:
- ERR("formal argument cannot be a class variable");
- return 0;
- default:
- ERR("formal argument must be local variable");
- return 0;
-#undef ERR
- }
- shadowing_lvar(p, id);
-
-/*
- * Workaround for Prism::ParseTest#test_filepath for "unparser/corpus/literal/def.txt"
- *
- * See the discussion on https://github.com/ruby/ruby/pull/9923
- */
#ifndef RIPPER
- return id;
+# define ERR(mesg) (yyerror0(mesg), Qtrue)
#else
- return 0;
+# define ERR(mesg) WARN_S(mesg)
#endif
-}
-
-#ifdef RIPPER
-static VALUE
-ripper_formal_argument(struct parser_params *p, ID id, VALUE lhs)
-{
- switch (id_type(id)) {
- case ID_LOCAL:
- break;
-#define ERR(mesg) (dispatch2(param_error, WARN_S(mesg), lhs), ripper_error(p))
case ID_CONST:
- ERR("formal argument cannot be a constant");
- break;
+ return ERR("formal argument cannot be a constant");
case ID_INSTANCE:
- ERR("formal argument cannot be an instance variable");
- break;
+ return ERR("formal argument cannot be an instance variable");
case ID_GLOBAL:
- ERR("formal argument cannot be a global variable");
- break;
+ return ERR("formal argument cannot be a global variable");
case ID_CLASS:
- ERR("formal argument cannot be a class variable");
- break;
+ return ERR("formal argument cannot be a class variable");
default:
- ERR("formal argument must be local variable");
- break;
+ return ERR("formal argument must be local variable");
#undef ERR
}
- return lhs;
+ shadowing_lvar(p, id);
+
+ return Qfalse;
}
-#endif
static int
lvar_defined(struct parser_params *p, ID id)
@@ -9443,6 +9302,10 @@ parser_set_encode(struct parser_params *p, const char *name)
rb_ary_unshift(excargs[2], rb_sprintf("%"PRIsVALUE":%d", p->ruby_sourcefile_string, p->ruby_sourceline));
VALUE exc = rb_make_exception(3, excargs);
ruby_show_error_line(p, exc, &(YYLTYPE)RUBY_INIT_YYLLOC(), p->ruby_sourceline, p->lex.lastline);
+
+ rb_ast_free(p->ast);
+ p->ast = NULL;
+
rb_exc_raise(exc);
}
enc = rb_enc_from_index(idx);
@@ -10075,7 +9938,8 @@ parse_qmark(struct parser_params *p, int space_seen)
{
rb_encoding *enc;
register int c;
- VALUE lit;
+ rb_parser_string_t *lit;
+ const char *start = p->lex.pcur;
if (IS_END()) {
SET_LEX_STATE(EXPR_VALUE);
@@ -10100,13 +9964,11 @@ parse_qmark(struct parser_params *p, int space_seen)
}
newtok(p);
enc = p->enc;
- if (!parser_isascii(p)) {
- if (tokadd_mbchar(p, c) == -1) return 0;
- }
- else if ((rb_enc_isalnum(c, p->enc) || c == '_') &&
- !lex_eol_p(p) && is_identchar(p, p->lex.pcur, p->lex.pend, p->enc)) {
+ int w = parser_precise_mbclen(p, start);
+ if (is_identchar(p, start, p->lex.pend, p->enc) &&
+ !(lex_eol_ptr_n_p(p, start, w) || !is_identchar(p, start + w, p->lex.pend, p->enc))) {
if (space_seen) {
- const char *start = p->lex.pcur - 1, *ptr = start;
+ const char *ptr = start;
do {
int n = parser_precise_mbclen(p, ptr);
if (n < 0) return -1;
@@ -10124,17 +9986,17 @@ parse_qmark(struct parser_params *p, int space_seen)
enc = rb_utf8_encoding();
tokadd_utf8(p, &enc, -1, 0, 0);
}
- else if (!ISASCII(c = peekc(p))) {
+ else if (!ISASCII(c = peekc(p)) && c != -1) {
nextc(p);
if (tokadd_mbchar(p, c) == -1) return 0;
}
else {
- c = read_escape(p, 0);
+ c = read_escape(p, 0, p->lex.pcur - rb_strlen_lit("?\\"));
tokadd(p, c);
}
}
else {
- tokadd(p, c);
+ if (tokadd_mbchar(p, c) == -1) return 0;
}
tokfix(p);
lit = STR_NEW3(tok(p), toklen(p), enc, 0);
@@ -10338,7 +10200,7 @@ parse_gvar(struct parser_params *p, const enum lex_state_e last_state)
return '$';
}
gvar:
- set_yylval_name(TOK_INTERN());
+ tokenize_ident(p);
return tGVAR;
case '&': /* $&: last match */
@@ -10505,7 +10367,7 @@ parse_ident(struct parser_params *p, int c, int cmd_state)
if (IS_LABEL_SUFFIX(0)) {
SET_LEX_STATE(EXPR_ARG|EXPR_LABELED);
nextc(p);
- set_yylval_name(TOK_INTERN());
+ tokenize_ident(p);
return tLABEL;
}
}
@@ -10722,7 +10584,24 @@ parser_yylex(struct parser_params *p)
token_flush(p);
}
goto retry;
+ case 'a':
+ if (peek_word_at(p, "nd", 2, 0)) goto leading_logical;
+ goto bol;
+ case 'o':
+ if (peek_word_at(p, "r", 1, 0)) goto leading_logical;
+ goto bol;
+ case '|':
+ if (peek(p, '|')) goto leading_logical;
+ goto bol;
case '&':
+ if (peek(p, '&')) {
+ leading_logical:
+ pushback(p, c);
+ dispatch_delayed_token(p, tIGNORED_NL);
+ cmd_state = FALSE;
+ goto retry;
+ }
+ /* fall through */
case '.': {
dispatch_delayed_token(p, tIGNORED_NL);
if (peek(p, '.') == (c == '&')) {
@@ -10731,11 +10610,15 @@ parser_yylex(struct parser_params *p)
goto retry;
}
}
+ bol:
default:
p->ruby_sourceline--;
p->lex.nextline = p->lex.lastline;
set_lastline(p, prevline);
case -1: /* EOF no decrement*/
+ if (c == -1 && space_seen) {
+ dispatch_scan_event(p, tSP);
+ }
lex_goto_eol(p);
if (c != -1) {
token_flush(p);
@@ -11049,6 +10932,7 @@ parser_yylex(struct parser_params *p)
if (c == '>') {
SET_LEX_STATE(EXPR_ENDFN);
yylval.num = p->lex.lpar_beg;
+ p->lex.lpar_beg = p->lex.paren_nest;
return tLAMBDA;
}
if (IS_BEG() || (IS_SPCARG(c) && arg_ambiguous(p, '-'))) {
@@ -11068,17 +10952,13 @@ parser_yylex(struct parser_params *p)
SET_LEX_STATE(EXPR_BEG);
if ((c = nextc(p)) == '.') {
if ((c = nextc(p)) == '.') {
- if (p->ctxt.in_argdef) {
+ if (p->ctxt.in_argdef || IS_LABEL_POSSIBLE()) {
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);
@@ -11381,24 +11261,26 @@ node_newnode(struct parser_params *p, enum node_type type, size_t size, size_t a
#define NODE_NEWNODE(node_type, type, loc) (type *)(node_newnode(p, node_type, sizeof(type), RUBY_ALIGNOF(type), loc))
static rb_node_scope_t *
-rb_node_scope_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc)
+rb_node_scope_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, NODE *nd_parent, const YYLTYPE *loc)
{
rb_ast_id_table_t *nd_tbl;
nd_tbl = local_tbl(p);
rb_node_scope_t *n = NODE_NEWNODE(NODE_SCOPE, rb_node_scope_t, loc);
n->nd_tbl = nd_tbl;
n->nd_body = nd_body;
+ n->nd_parent = nd_parent;
n->nd_args = nd_args;
return n;
}
static rb_node_scope_t *
-rb_node_scope_new2(struct parser_params *p, rb_ast_id_table_t *nd_tbl, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc)
+rb_node_scope_new2(struct parser_params *p, rb_ast_id_table_t *nd_tbl, rb_node_args_t *nd_args, NODE *nd_body, NODE *nd_parent, const YYLTYPE *loc)
{
rb_node_scope_t *n = NODE_NEWNODE(NODE_SCOPE, rb_node_scope_t, loc);
n->nd_tbl = nd_tbl;
n->nd_body = nd_body;
+ n->nd_parent = nd_parent;
n->nd_args = nd_args;
return n;
@@ -11437,11 +11319,15 @@ rb_node_block_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc)
}
static rb_node_for_t *
-rb_node_for_new(struct parser_params *p, NODE *nd_iter, NODE *nd_body, const YYLTYPE *loc)
+rb_node_for_new(struct parser_params *p, NODE *nd_iter, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *for_keyword_loc, const YYLTYPE *in_keyword_loc, const YYLTYPE *do_keyword_loc, const YYLTYPE *end_keyword_loc)
{
rb_node_for_t *n = NODE_NEWNODE(NODE_FOR, rb_node_for_t, loc);
n->nd_body = nd_body;
n->nd_iter = nd_iter;
+ n->for_keyword_loc = *for_keyword_loc;
+ n->in_keyword_loc = *in_keyword_loc;
+ n->do_keyword_loc = *do_keyword_loc;
+ n->end_keyword_loc = *end_keyword_loc;
return n;
}
@@ -11484,10 +11370,11 @@ rb_node_rescue_new(struct parser_params *p, NODE *nd_head, NODE *nd_resq, NODE *
}
static rb_node_resbody_t *
-rb_node_resbody_new(struct parser_params *p, NODE *nd_args, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc)
+rb_node_resbody_new(struct parser_params *p, NODE *nd_args, NODE *nd_exc_var, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc)
{
rb_node_resbody_t *n = NODE_NEWNODE(NODE_RESBODY, rb_node_resbody_t, loc);
n->nd_args = nd_args;
+ n->nd_exc_var = nd_exc_var;
n->nd_body = nd_body;
n->nd_next = nd_next;
@@ -11505,97 +11392,122 @@ rb_node_ensure_new(struct parser_params *p, NODE *nd_head, NODE *nd_ensr, const
}
static rb_node_and_t *
-rb_node_and_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc)
+rb_node_and_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc, const YYLTYPE *operator_loc)
{
rb_node_and_t *n = NODE_NEWNODE(NODE_AND, rb_node_and_t, loc);
n->nd_1st = nd_1st;
n->nd_2nd = nd_2nd;
+ n->operator_loc = *operator_loc;
return n;
}
static rb_node_or_t *
-rb_node_or_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc)
+rb_node_or_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc, const YYLTYPE *operator_loc)
{
rb_node_or_t *n = NODE_NEWNODE(NODE_OR, rb_node_or_t, loc);
n->nd_1st = nd_1st;
n->nd_2nd = nd_2nd;
+ n->operator_loc = *operator_loc;
return n;
}
static rb_node_return_t *
-rb_node_return_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc)
+rb_node_return_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc, const YYLTYPE *keyword_loc)
{
rb_node_return_t *n = NODE_NEWNODE(NODE_RETURN, rb_node_return_t, loc);
n->nd_stts = nd_stts;
+ n->keyword_loc = *keyword_loc;
return n;
}
static rb_node_yield_t *
-rb_node_yield_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc)
+rb_node_yield_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *lparen_loc, const YYLTYPE *rparen_loc)
{
+ if (nd_head) no_blockarg(p, nd_head);
+
rb_node_yield_t *n = NODE_NEWNODE(NODE_YIELD, rb_node_yield_t, loc);
n->nd_head = nd_head;
+ n->keyword_loc = *keyword_loc;
+ n->lparen_loc = *lparen_loc;
+ n->rparen_loc = *rparen_loc;
return n;
}
static rb_node_if_t *
-rb_node_if_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, NODE *nd_else, const YYLTYPE *loc)
+rb_node_if_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, NODE *nd_else, const YYLTYPE *loc, const YYLTYPE* if_keyword_loc, const YYLTYPE* then_keyword_loc, const YYLTYPE* end_keyword_loc)
{
rb_node_if_t *n = NODE_NEWNODE(NODE_IF, rb_node_if_t, loc);
n->nd_cond = nd_cond;
n->nd_body = nd_body;
n->nd_else = nd_else;
+ n->if_keyword_loc = *if_keyword_loc;
+ n->then_keyword_loc = *then_keyword_loc;
+ n->end_keyword_loc = *end_keyword_loc;
return n;
}
static rb_node_unless_t *
-rb_node_unless_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, NODE *nd_else, const YYLTYPE *loc)
+rb_node_unless_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, NODE *nd_else, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *then_keyword_loc, const YYLTYPE *end_keyword_loc)
{
rb_node_unless_t *n = NODE_NEWNODE(NODE_UNLESS, rb_node_unless_t, loc);
n->nd_cond = nd_cond;
n->nd_body = nd_body;
n->nd_else = nd_else;
+ n->keyword_loc = *keyword_loc;
+ n->then_keyword_loc = *then_keyword_loc;
+ n->end_keyword_loc = *end_keyword_loc;
return n;
}
static rb_node_class_t *
-rb_node_class_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, NODE *nd_super, const YYLTYPE *loc)
+rb_node_class_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, NODE *nd_super, const YYLTYPE *loc, const YYLTYPE *class_keyword_loc, const YYLTYPE *inheritance_operator_loc, const YYLTYPE *end_keyword_loc)
{
/* Keep the order of node creation */
- NODE *scope = NEW_SCOPE(0, nd_body, loc);
+ NODE *scope = NEW_SCOPE(0, nd_body, NULL, loc);
rb_node_class_t *n = NODE_NEWNODE(NODE_CLASS, rb_node_class_t, loc);
+ RNODE_SCOPE(scope)->nd_parent = &n->node;
n->nd_cpath = nd_cpath;
n->nd_body = scope;
n->nd_super = nd_super;
+ n->class_keyword_loc = *class_keyword_loc;
+ n->inheritance_operator_loc = *inheritance_operator_loc;
+ n->end_keyword_loc = *end_keyword_loc;
return n;
}
static rb_node_sclass_t *
-rb_node_sclass_new(struct parser_params *p, NODE *nd_recv, NODE *nd_body, const YYLTYPE *loc)
+rb_node_sclass_new(struct parser_params *p, NODE *nd_recv, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *class_keyword_loc, const YYLTYPE *operator_loc, const YYLTYPE *end_keyword_loc)
{
/* Keep the order of node creation */
- NODE *scope = NEW_SCOPE(0, nd_body, loc);
+ NODE *scope = NEW_SCOPE(0, nd_body, NULL, loc);
rb_node_sclass_t *n = NODE_NEWNODE(NODE_SCLASS, rb_node_sclass_t, loc);
+ RNODE_SCOPE(scope)->nd_parent = &n->node;
n->nd_recv = nd_recv;
n->nd_body = scope;
+ n->class_keyword_loc = *class_keyword_loc;
+ n->operator_loc = *operator_loc;
+ n->end_keyword_loc = *end_keyword_loc;
return n;
}
static rb_node_module_t *
-rb_node_module_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, const YYLTYPE *loc)
+rb_node_module_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *module_keyword_loc, const YYLTYPE *end_keyword_loc)
{
/* Keep the order of node creation */
- NODE *scope = NEW_SCOPE(0, nd_body, loc);
+ NODE *scope = NEW_SCOPE(0, nd_body, NULL, loc);
rb_node_module_t *n = NODE_NEWNODE(NODE_MODULE, rb_node_module_t, loc);
+ RNODE_SCOPE(scope)->nd_parent = &n->node;
n->nd_cpath = nd_cpath;
n->nd_body = scope;
+ n->module_keyword_loc = *module_keyword_loc;
+ n->end_keyword_loc = *end_keyword_loc;
return n;
}
@@ -11604,8 +11516,9 @@ static rb_node_iter_t *
rb_node_iter_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc)
{
/* Keep the order of node creation */
- NODE *scope = NEW_SCOPE(nd_args, nd_body, loc);
+ NODE *scope = NEW_SCOPE(nd_args, nd_body, NULL, loc);
rb_node_iter_t *n = NODE_NEWNODE(NODE_ITER, rb_node_iter_t, loc);
+ RNODE_SCOPE(scope)->nd_parent = &n->node;
n->nd_body = scope;
n->nd_iter = 0;
@@ -11613,125 +11526,151 @@ rb_node_iter_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body
}
static rb_node_lambda_t *
-rb_node_lambda_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc)
+rb_node_lambda_new(struct parser_params *p, rb_node_args_t *nd_args, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *operator_loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc)
{
/* Keep the order of node creation */
- NODE *scope = NEW_SCOPE(nd_args, nd_body, loc);
- rb_node_lambda_t *n = NODE_NEWNODE(NODE_LAMBDA, rb_node_lambda_t, loc);
+ NODE *scope = NEW_SCOPE(nd_args, nd_body, NULL, loc);
+ YYLTYPE lambda_loc = code_loc_gen(operator_loc, closing_loc);
+ rb_node_lambda_t *n = NODE_NEWNODE(NODE_LAMBDA, rb_node_lambda_t, &lambda_loc);
+ RNODE_SCOPE(scope)->nd_parent = &n->node;
n->nd_body = scope;
+ n->operator_loc = *operator_loc;
+ n->opening_loc = *opening_loc;
+ n->closing_loc = *closing_loc;
return n;
}
static rb_node_case_t *
-rb_node_case_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc)
+rb_node_case_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *case_keyword_loc, const YYLTYPE *end_keyword_loc)
{
rb_node_case_t *n = NODE_NEWNODE(NODE_CASE, rb_node_case_t, loc);
n->nd_head = nd_head;
n->nd_body = nd_body;
+ n->case_keyword_loc = *case_keyword_loc;
+ n->end_keyword_loc = *end_keyword_loc;
return n;
}
static rb_node_case2_t *
-rb_node_case2_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc)
+rb_node_case2_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *case_keyword_loc, const YYLTYPE *end_keyword_loc)
{
rb_node_case2_t *n = NODE_NEWNODE(NODE_CASE2, rb_node_case2_t, loc);
n->nd_head = 0;
n->nd_body = nd_body;
+ n->case_keyword_loc = *case_keyword_loc;
+ n->end_keyword_loc = *end_keyword_loc;
return n;
}
static rb_node_case3_t *
-rb_node_case3_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc)
+rb_node_case3_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *case_keyword_loc, const YYLTYPE *end_keyword_loc)
{
rb_node_case3_t *n = NODE_NEWNODE(NODE_CASE3, rb_node_case3_t, loc);
n->nd_head = nd_head;
n->nd_body = nd_body;
+ n->case_keyword_loc = *case_keyword_loc;
+ n->end_keyword_loc = *end_keyword_loc;
return n;
}
static rb_node_when_t *
-rb_node_when_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc)
+rb_node_when_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *then_keyword_loc)
{
rb_node_when_t *n = NODE_NEWNODE(NODE_WHEN, rb_node_when_t, loc);
n->nd_head = nd_head;
n->nd_body = nd_body;
n->nd_next = nd_next;
+ n->keyword_loc = *keyword_loc;
+ n->then_keyword_loc = *then_keyword_loc;
return n;
}
static rb_node_in_t *
-rb_node_in_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc)
+rb_node_in_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, NODE *nd_next, const YYLTYPE *loc, const YYLTYPE *in_keyword_loc, const YYLTYPE *then_keyword_loc, const YYLTYPE *operator_loc)
{
rb_node_in_t *n = NODE_NEWNODE(NODE_IN, rb_node_in_t, loc);
n->nd_head = nd_head;
n->nd_body = nd_body;
n->nd_next = nd_next;
+ n->in_keyword_loc = *in_keyword_loc;
+ n->then_keyword_loc = *then_keyword_loc;
+ n->operator_loc = *operator_loc;
return n;
}
static rb_node_while_t *
-rb_node_while_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc)
+rb_node_while_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *closing_loc)
{
rb_node_while_t *n = NODE_NEWNODE(NODE_WHILE, rb_node_while_t, loc);
n->nd_cond = nd_cond;
n->nd_body = nd_body;
n->nd_state = nd_state;
+ n->keyword_loc = *keyword_loc;
+ n->closing_loc = *closing_loc;
return n;
}
static rb_node_until_t *
-rb_node_until_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc)
+rb_node_until_new(struct parser_params *p, NODE *nd_cond, NODE *nd_body, long nd_state, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *closing_loc)
{
rb_node_until_t *n = NODE_NEWNODE(NODE_UNTIL, rb_node_until_t, loc);
n->nd_cond = nd_cond;
n->nd_body = nd_body;
n->nd_state = nd_state;
+ n->keyword_loc = *keyword_loc;
+ n->closing_loc = *closing_loc;
return n;
}
static rb_node_colon2_t *
-rb_node_colon2_new(struct parser_params *p, NODE *nd_head, ID nd_mid, const YYLTYPE *loc)
+rb_node_colon2_new(struct parser_params *p, NODE *nd_head, ID nd_mid, const YYLTYPE *loc, const YYLTYPE *delimiter_loc, const YYLTYPE *name_loc)
{
rb_node_colon2_t *n = NODE_NEWNODE(NODE_COLON2, rb_node_colon2_t, loc);
n->nd_head = nd_head;
n->nd_mid = nd_mid;
+ n->delimiter_loc = *delimiter_loc;
+ n->name_loc = *name_loc;
return n;
}
static rb_node_colon3_t *
-rb_node_colon3_new(struct parser_params *p, ID nd_mid, const YYLTYPE *loc)
+rb_node_colon3_new(struct parser_params *p, ID nd_mid, const YYLTYPE *loc, const YYLTYPE *delimiter_loc, const YYLTYPE *name_loc)
{
rb_node_colon3_t *n = NODE_NEWNODE(NODE_COLON3, rb_node_colon3_t, loc);
n->nd_mid = nd_mid;
+ n->delimiter_loc = *delimiter_loc;
+ n->name_loc = *name_loc;
return n;
}
static rb_node_dot2_t *
-rb_node_dot2_new(struct parser_params *p, NODE *nd_beg, NODE *nd_end, const YYLTYPE *loc)
+rb_node_dot2_new(struct parser_params *p, NODE *nd_beg, NODE *nd_end, const YYLTYPE *loc, const YYLTYPE *operator_loc)
{
rb_node_dot2_t *n = NODE_NEWNODE(NODE_DOT2, rb_node_dot2_t, loc);
n->nd_beg = nd_beg;
n->nd_end = nd_end;
+ n->operator_loc = *operator_loc;
return n;
}
static rb_node_dot3_t *
-rb_node_dot3_new(struct parser_params *p, NODE *nd_beg, NODE *nd_end, const YYLTYPE *loc)
+rb_node_dot3_new(struct parser_params *p, NODE *nd_beg, NODE *nd_end, const YYLTYPE *loc, const YYLTYPE *operator_loc)
{
rb_node_dot3_t *n = NODE_NEWNODE(NODE_DOT3, rb_node_dot3_t, loc);
n->nd_beg = nd_beg;
n->nd_end = nd_end;
+ n->operator_loc = *operator_loc;
return n;
}
@@ -11770,10 +11709,14 @@ rb_node_false_new(struct parser_params *p, const YYLTYPE *loc)
}
static rb_node_super_t *
-rb_node_super_new(struct parser_params *p, NODE *nd_args, const YYLTYPE *loc)
+rb_node_super_new(struct parser_params *p, NODE *nd_args, const YYLTYPE *loc,
+ const YYLTYPE *keyword_loc, const YYLTYPE *lparen_loc, const YYLTYPE *rparen_loc)
{
rb_node_super_t *n = NODE_NEWNODE(NODE_SUPER, rb_node_super_t, loc);
n->nd_args = nd_args;
+ n->keyword_loc = *keyword_loc;
+ n->lparen_loc = *lparen_loc;
+ n->rparen_loc = *rparen_loc;
return n;
}
@@ -11910,19 +11853,23 @@ rb_node_cvasgn_new(struct parser_params *p, ID nd_vid, NODE *nd_value, const YYL
}
static rb_node_op_asgn1_t *
-rb_node_op_asgn1_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *index, NODE *rvalue, const YYLTYPE *loc)
+rb_node_op_asgn1_new(struct parser_params *p, NODE *nd_recv, ID nd_mid, NODE *index, NODE *rvalue, const YYLTYPE *loc, const YYLTYPE *call_operator_loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc, const YYLTYPE *binary_operator_loc)
{
rb_node_op_asgn1_t *n = NODE_NEWNODE(NODE_OP_ASGN1, rb_node_op_asgn1_t, loc);
n->nd_recv = nd_recv;
n->nd_mid = nd_mid;
n->nd_index = index;
n->nd_rvalue = rvalue;
+ n->call_operator_loc = *call_operator_loc;
+ n->opening_loc = *opening_loc;
+ n->closing_loc = *closing_loc;
+ n->binary_operator_loc = *binary_operator_loc;
return n;
}
static rb_node_op_asgn2_t *
-rb_node_op_asgn2_new(struct parser_params *p, NODE *nd_recv, NODE *nd_value, ID nd_vid, ID nd_mid, bool nd_aid, const YYLTYPE *loc)
+rb_node_op_asgn2_new(struct parser_params *p, NODE *nd_recv, NODE *nd_value, ID nd_vid, ID nd_mid, bool nd_aid, const YYLTYPE *loc, const YYLTYPE *call_operator_loc, const YYLTYPE *message_loc, const YYLTYPE *binary_operator_loc)
{
rb_node_op_asgn2_t *n = NODE_NEWNODE(NODE_OP_ASGN2, rb_node_op_asgn2_t, loc);
n->nd_recv = nd_recv;
@@ -11930,6 +11877,9 @@ rb_node_op_asgn2_new(struct parser_params *p, NODE *nd_recv, NODE *nd_value, ID
n->nd_vid = nd_vid;
n->nd_mid = nd_mid;
n->nd_aid = nd_aid;
+ n->call_operator_loc = *call_operator_loc;
+ n->message_loc = *message_loc;
+ n->binary_operator_loc = *binary_operator_loc;
return n;
}
@@ -12140,20 +12090,25 @@ rb_node_dsym_new(struct parser_params *p, rb_parser_string_t *string, long nd_al
}
static rb_node_evstr_t *
-rb_node_evstr_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc)
+rb_node_evstr_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc)
{
rb_node_evstr_t *n = NODE_NEWNODE(NODE_EVSTR, rb_node_evstr_t, loc);
n->nd_body = nd_body;
+ n->opening_loc = *opening_loc;
+ n->closing_loc = *closing_loc;
return n;
}
static rb_node_regx_t *
-rb_node_regx_new(struct parser_params *p, rb_parser_string_t *string, int options, const YYLTYPE *loc)
+rb_node_regx_new(struct parser_params *p, rb_parser_string_t *string, int options, const YYLTYPE *loc, const YYLTYPE *opening_loc, const YYLTYPE *content_loc, const YYLTYPE *closing_loc)
{
rb_node_regx_t *n = NODE_NEWNODE(NODE_REGX, rb_node_regx_t, loc);
n->string = string;
n->options = options & RE_OPTION_MASK;
+ n->opening_loc = *opening_loc;
+ n->content_loc = *content_loc;
+ n->closing_loc = *closing_loc;
return n;
}
@@ -12290,40 +12245,45 @@ rb_node_argspush_new(struct parser_params *p, NODE *nd_head, NODE *nd_body, cons
}
static rb_node_splat_t *
-rb_node_splat_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc)
+rb_node_splat_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc, const YYLTYPE *operator_loc)
{
rb_node_splat_t *n = NODE_NEWNODE(NODE_SPLAT, rb_node_splat_t, loc);
n->nd_head = nd_head;
+ n->operator_loc = *operator_loc;
return n;
}
static rb_node_block_pass_t *
-rb_node_block_pass_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc)
+rb_node_block_pass_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *operator_loc)
{
rb_node_block_pass_t *n = NODE_NEWNODE(NODE_BLOCK_PASS, rb_node_block_pass_t, loc);
+ n->forwarding = 0;
n->nd_head = 0;
n->nd_body = nd_body;
+ n->operator_loc = *operator_loc;
return n;
}
static rb_node_alias_t *
-rb_node_alias_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc)
+rb_node_alias_new(struct parser_params *p, NODE *nd_1st, NODE *nd_2nd, const YYLTYPE *loc, const YYLTYPE *keyword_loc)
{
rb_node_alias_t *n = NODE_NEWNODE(NODE_ALIAS, rb_node_alias_t, loc);
n->nd_1st = nd_1st;
n->nd_2nd = nd_2nd;
+ n->keyword_loc = *keyword_loc;
return n;
}
static rb_node_valias_t *
-rb_node_valias_new(struct parser_params *p, ID nd_alias, ID nd_orig, const YYLTYPE *loc)
+rb_node_valias_new(struct parser_params *p, ID nd_alias, ID nd_orig, const YYLTYPE *loc, const YYLTYPE *keyword_loc)
{
rb_node_valias_t *n = NODE_NEWNODE(NODE_VALIAS, rb_node_valias_t, loc);
n->nd_alias = nd_alias;
n->nd_orig = nd_orig;
+ n->keyword_loc = *keyword_loc;
return n;
}
@@ -12332,7 +12292,9 @@ static rb_node_undef_t *
rb_node_undef_new(struct parser_params *p, NODE *nd_undef, const YYLTYPE *loc)
{
rb_node_undef_t *n = NODE_NEWNODE(NODE_UNDEF, rb_node_undef_t, loc);
- n->nd_undef = nd_undef;
+ n->nd_undefs = rb_parser_ary_new_capa_for_node(p, 1);
+ n->keyword_loc = NULL_LOC;
+ rb_parser_ary_push_node(p, n->nd_undefs, nd_undef);
return n;
}
@@ -12346,19 +12308,23 @@ rb_node_errinfo_new(struct parser_params *p, const YYLTYPE *loc)
}
static rb_node_defined_t *
-rb_node_defined_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc)
+rb_node_defined_new(struct parser_params *p, NODE *nd_head, const YYLTYPE *loc, const YYLTYPE *keyword_loc)
{
rb_node_defined_t *n = NODE_NEWNODE(NODE_DEFINED, rb_node_defined_t, loc);
n->nd_head = nd_head;
+ n->keyword_loc = *keyword_loc;
return n;
}
static rb_node_postexe_t *
-rb_node_postexe_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc)
+rb_node_postexe_new(struct parser_params *p, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc)
{
rb_node_postexe_t *n = NODE_NEWNODE(NODE_POSTEXE, rb_node_postexe_t, loc);
n->nd_body = nd_body;
+ n->keyword_loc = *keyword_loc;
+ n->opening_loc = *opening_loc;
+ n->closing_loc = *closing_loc;
return n;
}
@@ -12468,30 +12434,33 @@ rb_node_error_new(struct parser_params *p, const YYLTYPE *loc)
}
static rb_node_break_t *
-rb_node_break_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc)
+rb_node_break_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc, const YYLTYPE *keyword_loc)
{
rb_node_break_t *n = NODE_NEWNODE(NODE_BREAK, rb_node_break_t, loc);
n->nd_stts = nd_stts;
n->nd_chain = 0;
+ n->keyword_loc = *keyword_loc;
return n;
}
static rb_node_next_t *
-rb_node_next_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc)
+rb_node_next_new(struct parser_params *p, NODE *nd_stts, const YYLTYPE *loc, const YYLTYPE *keyword_loc)
{
rb_node_next_t *n = NODE_NEWNODE(NODE_NEXT, rb_node_next_t, loc);
n->nd_stts = nd_stts;
n->nd_chain = 0;
+ n->keyword_loc = *keyword_loc;
return n;
}
static rb_node_redo_t *
-rb_node_redo_new(struct parser_params *p, const YYLTYPE *loc)
+rb_node_redo_new(struct parser_params *p, const YYLTYPE *loc, const YYLTYPE *keyword_loc)
{
rb_node_redo_t *n = NODE_NEWNODE(NODE_REDO, rb_node_redo_t, loc);
n->nd_chain = 0;
+ n->keyword_loc = *keyword_loc;
return n;
}
@@ -12500,7 +12469,6 @@ static rb_node_def_temp_t *
rb_node_def_temp_new(struct parser_params *p, const YYLTYPE *loc)
{
rb_node_def_temp_t *n = NODE_NEWNODE((enum node_type)NODE_DEF_TEMP, rb_node_def_temp_t, loc);
- n->save.cur_arg = p->cur_arg;
n->save.numparam_save = 0;
n->save.max_numparam = 0;
n->save.ctxt = p->ctxt;
@@ -12799,12 +12767,16 @@ str2dstr(struct parser_params *p, NODE *node)
}
static NODE *
-str2regx(struct parser_params *p, NODE *node, int options)
+str2regx(struct parser_params *p, NODE *node, int options, const YYLTYPE *loc, const YYLTYPE *opening_loc, const YYLTYPE *content_loc, const YYLTYPE *closing_loc)
{
NODE *new_node = (NODE *)NODE_NEW_INTERNAL(NODE_REGX, rb_node_regx_t);
nd_copy_flag(new_node, node);
RNODE_REGX(new_node)->string = RNODE_STR(node)->string;
RNODE_REGX(new_node)->options = options;
+ nd_set_loc(new_node, loc);
+ RNODE_REGX(new_node)->opening_loc = *opening_loc;
+ RNODE_REGX(new_node)->content_loc = *content_loc;
+ RNODE_REGX(new_node)->closing_loc = *closing_loc;
RNODE_STR(node)->string = 0;
return new_node;
@@ -12820,7 +12792,7 @@ evstr2dstr(struct parser_params *p, NODE *node)
}
static NODE *
-new_evstr(struct parser_params *p, NODE *node, const YYLTYPE *loc)
+new_evstr(struct parser_params *p, NODE *node, const YYLTYPE *loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc)
{
NODE *head = node;
@@ -12834,7 +12806,7 @@ new_evstr(struct parser_params *p, NODE *node, const YYLTYPE *loc)
return node;
}
}
- return NEW_EVSTR(head, loc);
+ return NEW_EVSTR(head, loc, opening_loc, closing_loc);
}
static NODE *
@@ -12849,8 +12821,8 @@ call_bin_op(struct parser_params *p, NODE *recv, ID id, NODE *arg1,
const YYLTYPE *op_loc, const YYLTYPE *loc)
{
NODE *expr;
- value_expr(recv);
- value_expr(arg1);
+ value_expr(p, recv);
+ value_expr(p, arg1);
expr = NEW_OPCALL(recv, id, NEW_LIST(arg1, &arg1->nd_loc), loc);
nd_set_line(expr, op_loc->beg_pos.lineno);
return expr;
@@ -12860,7 +12832,7 @@ static NODE *
call_uni_op(struct parser_params *p, NODE *recv, ID id, const YYLTYPE *op_loc, const YYLTYPE *loc)
{
NODE *opcall;
- value_expr(recv);
+ value_expr(p, recv);
opcall = NEW_OPCALL(recv, id, 0, loc);
nd_set_line(opcall, op_loc->beg_pos.lineno);
return opcall;
@@ -12885,6 +12857,16 @@ new_command_qcall(struct parser_params* p, ID atype, NODE *recv, ID mid, NODE *a
return ret;
}
+static rb_locations_lambda_body_t*
+new_locations_lambda_body(struct parser_params* p, NODE *node, const YYLTYPE *loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc)
+{
+ rb_locations_lambda_body_t *body = xcalloc(1, sizeof(rb_locations_lambda_body_t));
+ body->node = node;
+ body->opening_loc = *opening_loc;
+ body->closing_loc = *closing_loc;
+ return body;
+}
+
#define nd_once_body(node) (nd_type_p((node), NODE_ONCE) ? RNODE_ONCE(node)->nd_body : node)
static NODE*
@@ -12900,8 +12882,8 @@ match_op(struct parser_params *p, NODE *node1, NODE *node2, const YYLTYPE *op_lo
NODE *n;
int line = op_loc->beg_pos.lineno;
- value_expr(node1);
- value_expr(node2);
+ value_expr(p, node1);
+ value_expr(p, node2);
if ((n = last_expr_once_body(node1)) != 0) {
switch (nd_type(n)) {
@@ -12917,7 +12899,7 @@ match_op(struct parser_params *p, NODE *node1, NODE *node2, const YYLTYPE *op_lo
const VALUE lit = rb_node_regx_string_val(n);
if (!NIL_P(lit)) {
NODE *match = NEW_MATCH2(node1, node2, loc);
- RNODE_MATCH2(match)->nd_args = reg_named_capture_assign(p, lit, loc);
+ RNODE_MATCH2(match)->nd_args = reg_named_capture_assign(p, lit, loc, assignable);
nd_set_line(match, line);
return match;
}
@@ -12961,10 +12943,10 @@ numparam_nested_p(struct parser_params *p)
NODE *inner = local->numparam.inner;
if (outer || inner) {
NODE *used = outer ? outer : inner;
- compile_error(p, "numbered parameter is already used in\n"
- "%s:%d: %s block here",
- p->ruby_sourcefile, nd_line(used),
- outer ? "outer" : "inner");
+ compile_error(p, "numbered parameter is already used in %s block\n"
+ "%s:%d: numbered parameter is already used here",
+ outer ? "outer" : "inner",
+ p->ruby_sourcefile, nd_line(used));
parser_show_error_line(p, &used->nd_loc);
return 1;
}
@@ -12976,8 +12958,8 @@ numparam_used_p(struct parser_params *p)
{
NODE *numparam = p->lvtbl->numparam.current;
if (numparam) {
- compile_error(p, "numbered parameter is already used in\n"
- "%s:%d: current block here",
+ compile_error(p, "'it' is not allowed when a numbered parameter is already used\n"
+ "%s:%d: numbered parameter is already used here",
p->ruby_sourcefile, nd_line(numparam));
parser_show_error_line(p, &numparam->nd_loc);
return 1;
@@ -12990,8 +12972,8 @@ it_used_p(struct parser_params *p)
{
NODE *it = p->lvtbl->it;
if (it) {
- compile_error(p, "'it' is already used in\n"
- "%s:%d: current block here",
+ compile_error(p, "numbered parameters are not allowed when 'it' is already used\n"
+ "%s:%d: 'it' is already used here",
p->ruby_sourcefile, nd_line(it));
parser_show_error_line(p, &it->nd_loc);
return 1;
@@ -13031,19 +13013,11 @@ gettable(struct parser_params *p, ID id, const YYLTYPE *loc)
case ID_LOCAL:
if (dyna_in_block(p) && dvar_defined_ref(p, id, &vidp)) {
if (NUMPARAM_ID_P(id) && (numparam_nested_p(p) || it_used_p(p))) return 0;
- if (id == p->cur_arg) {
- compile_error(p, "circular argument reference - %"PRIsWARN, rb_id2str(id));
- return 0;
- }
if (vidp) *vidp |= LVAR_USED;
node = NEW_DVAR(id, loc);
return node;
}
if (local_id_ref(p, id, &vidp)) {
- if (id == p->cur_arg) {
- compile_error(p, "circular argument reference - %"PRIsWARN, rb_id2str(id));
- return 0;
- }
if (vidp) *vidp |= LVAR_USED;
node = NEW_LVAR(id, loc);
return node;
@@ -13062,14 +13036,14 @@ gettable(struct parser_params *p, ID id, const YYLTYPE *loc)
}
# endif
/* method call without arguments */
- if (dyna_in_block(p) && id == rb_intern("it") && !(DVARS_TERMINAL_P(p->lvtbl->args) || DVARS_TERMINAL_P(p->lvtbl->args->prev))) {
+ if (dyna_in_block(p) && id == idIt && !(DVARS_TERMINAL_P(p->lvtbl->args) || DVARS_TERMINAL_P(p->lvtbl->args->prev))) {
if (numparam_used_p(p)) return 0;
if (p->max_numparam == ORDINAL_PARAM) {
compile_error(p, "ordinary parameter is defined");
return 0;
}
if (!p->it_id) {
- p->it_id = internal_id(p);
+ p->it_id = idItImplicit;
vtable_add(p->lvtbl->args, p->it_id);
}
NODE *node = NEW_DVAR(p->it_id, loc);
@@ -13116,8 +13090,11 @@ kwd_append(rb_node_kw_arg_t *kwlist, rb_node_kw_arg_t *kw)
}
static NODE *
-new_defined(struct parser_params *p, NODE *expr, const YYLTYPE *loc)
+new_defined(struct parser_params *p, NODE *expr, const YYLTYPE *loc, const YYLTYPE *keyword_loc)
{
+ int had_trailing_semicolon = p->ctxt.has_trailing_semicolon;
+ p->ctxt.has_trailing_semicolon = 0;
+
NODE *n = expr;
while (n) {
if (nd_type_p(n, NODE_BEGIN)) {
@@ -13130,7 +13107,13 @@ new_defined(struct parser_params *p, NODE *expr, const YYLTYPE *loc)
break;
}
}
- return NEW_DEFINED(n, loc);
+
+ if (had_trailing_semicolon && !nd_type_p(expr, NODE_BLOCK)) {
+ NODE *block = NEW_BLOCK(expr, loc);
+ return NEW_DEFINED(block, loc, keyword_loc);
+ }
+
+ return NEW_DEFINED(n, loc, keyword_loc);
}
static NODE*
@@ -13165,17 +13148,31 @@ symbol_append(struct parser_params *p, NODE *symbols, NODE *symbol)
return list_append(p, symbols, symbol);
}
-static NODE *
-new_regexp(struct parser_params *p, NODE *node, int options, const YYLTYPE *loc)
+static void
+dregex_fragment_setenc(struct parser_params *p, rb_node_dregx_t *const dreg, int options)
{
- struct RNode_LIST *list;
- NODE *prev;
+ if (dreg->string) {
+ reg_fragment_setenc(p, dreg->string, options);
+ }
+ for (struct RNode_LIST *list = dreg->nd_next; list; list = RNODE_LIST(list->nd_next)) {
+ NODE *frag = list->nd_head;
+ if (nd_type_p(frag, NODE_STR)) {
+ reg_fragment_setenc(p, RNODE_STR(frag)->string, options);
+ }
+ else if (nd_type_p(frag, NODE_DSTR)) {
+ dregex_fragment_setenc(p, RNODE_DSTR(frag), options);
+ }
+ }
+}
+static NODE *
+new_regexp(struct parser_params *p, NODE *node, int options, const YYLTYPE *loc, const YYLTYPE *opening_loc, const YYLTYPE *content_loc, const YYLTYPE *closing_loc)
+{
if (!node) {
/* Check string is valid regex */
rb_parser_string_t *str = STRING_NEW0();
reg_compile(p, str, options);
- node = NEW_REGX(str, options, loc);
+ node = NEW_REGX(str, options, loc, opening_loc, content_loc, closing_loc);
return node;
}
switch (nd_type(node)) {
@@ -13183,7 +13180,7 @@ new_regexp(struct parser_params *p, NODE *node, int options, const YYLTYPE *loc)
{
/* Check string is valid regex */
reg_compile(p, RNODE_STR(node)->string, options);
- node = str2regx(p, node, options);
+ node = str2regx(p, node, options, loc, opening_loc, content_loc, closing_loc);
}
break;
default:
@@ -13194,35 +13191,8 @@ new_regexp(struct parser_params *p, NODE *node, int options, const YYLTYPE *loc)
nd_set_loc(node, loc);
rb_node_dregx_t *const dreg = RNODE_DREGX(node);
dreg->as.nd_cflag = options & RE_OPTION_MASK;
- if (dreg->string) reg_fragment_check(p, dreg->string, options);
- prev = node;
- for (list = dreg->nd_next; list; list = RNODE_LIST(list->nd_next)) {
- NODE *frag = list->nd_head;
- enum node_type type = nd_type(frag);
- if (type == NODE_STR || (type == NODE_DSTR && !RNODE_DSTR(frag)->nd_next)) {
- rb_parser_string_t *tail = RNODE_STR(frag)->string;
- if (reg_fragment_check(p, tail, options) && prev && RNODE_DREGX(prev)->string) {
- rb_parser_string_t *lit = prev == node ? dreg->string : RNODE_STR(RNODE_LIST(prev)->nd_head)->string;
- if (!literal_concat0(p, lit, tail)) {
- return NEW_NIL(loc); /* dummy node on error */
- }
- rb_parser_str_resize(p, tail, 0);
- RNODE_LIST(prev)->nd_next = list->nd_next;
- rb_discard_node(p, list->nd_head);
- rb_discard_node(p, (NODE *)list);
- list = RNODE_LIST(prev);
- }
- else {
- prev = (NODE *)list;
- }
- }
- else {
- prev = 0;
- }
- }
- if (!dreg->nd_next) {
- /* Check string is valid regex */
- reg_compile(p, dreg->string, options);
+ if (dreg->nd_next) {
+ dregex_fragment_setenc(p, dreg, options);
}
if (options & RE_OPTION_ONCE) {
node = NEW_ONCE(node, loc);
@@ -13693,35 +13663,23 @@ attrset(struct parser_params *p, NODE *recv, ID atype, ID id, const YYLTYPE *loc
return NEW_ATTRASGN(recv, id, 0, loc);
}
-static void
-rb_backref_error(struct parser_params *p, NODE *node)
-{
- switch (nd_type(node)) {
- case NODE_NTH_REF:
- compile_error(p, "Can't set variable $%ld", RNODE_NTH_REF(node)->nd_nth);
- break;
- case NODE_BACK_REF:
- compile_error(p, "Can't set variable $%c", (int)RNODE_BACK_REF(node)->nd_nth);
- break;
- }
-}
-
-#ifdef RIPPER
static VALUE
-backref_error(struct parser_params *p, NODE *node, VALUE expr)
+rb_backref_error(struct parser_params *p, NODE *node)
{
- VALUE mesg = rb_str_new_cstr("Can't set variable ");
+#ifndef RIPPER
+# define ERR(...) (compile_error(p, __VA_ARGS__), Qtrue)
+#else
+# define ERR(...) rb_sprintf(__VA_ARGS__)
+#endif
switch (nd_type(node)) {
case NODE_NTH_REF:
- rb_str_catf(mesg, "$%ld", RNODE_NTH_REF(node)->nd_nth);
- break;
+ return ERR("Can't set variable $%ld", RNODE_NTH_REF(node)->nd_nth);
case NODE_BACK_REF:
- rb_str_catf(mesg, "$%c", (int)RNODE_BACK_REF(node)->nd_nth);
- break;
+ return ERR("Can't set variable $%c", (int)RNODE_BACK_REF(node)->nd_nth);
}
- return dispatch2(assign_error, mesg, expr);
+#undef ERR
+ UNREACHABLE_RETURN(Qfalse); /* only called on syntax error */
}
-#endif
static NODE *
arg_append(struct parser_params *p, NODE *node1, NODE *node2, const YYLTYPE *loc)
@@ -13965,7 +13923,7 @@ value_expr_check(struct parser_params *p, NODE *node)
}
static int
-value_expr_gen(struct parser_params *p, NODE *node)
+value_expr(struct parser_params *p, NODE *node)
{
NODE *void_node = value_expr_check(p, node);
if (void_node) {
@@ -14068,6 +14026,7 @@ void_expr(struct parser_params *p, NODE *node)
}
}
+/* warns useless use of block and returns the last statement node */
static NODE *
void_stmts(struct parser_params *p, NODE *node)
{
@@ -14080,7 +14039,7 @@ void_stmts(struct parser_params *p, NODE *node)
void_expr(p, RNODE_BLOCK(node)->nd_head);
node = RNODE_BLOCK(node)->nd_next;
}
- return n;
+ return RNODE_BLOCK(node)->nd_head;
}
static NODE *
@@ -14108,16 +14067,12 @@ reduce_nodes(struct parser_params *p, NODE **body)
(reduce_nodes(p, &type(node)->n1), body = &type(node)->n2, 1))
while (node) {
- int newline = (int)(nd_fl_newline(node));
+ int newline = (int)nd_fl_newline(node);
switch (nd_type(node)) {
end:
case NODE_NIL:
*body = 0;
return;
- case NODE_RETURN:
- *body = node = RNODE_RETURN(node)->nd_stts;
- if (newline && node) nd_set_fl_newline(node);
- continue;
case NODE_BEGIN:
*body = node = RNODE_BEGIN(node)->nd_body;
if (newline && node) nd_set_fl_newline(node);
@@ -14237,7 +14192,7 @@ range_op(struct parser_params *p, NODE *node, const YYLTYPE *loc)
if (node == 0) return 0;
type = nd_type(node);
- value_expr(node);
+ value_expr(p, node);
if (type == NODE_INTEGER) {
if (!e_option_supplied(p)) rb_warn0L(nd_line(node), "integer literal in flip-flop");
ID lineno = rb_intern("$.");
@@ -14315,13 +14270,7 @@ cond0(struct parser_params *p, NODE *node, enum cond_type type, const YYLTYPE *l
break;
case NODE_LINE:
- SWITCH_BY_COND_TYPE(type, warning, "");
- break;
-
case NODE_ENCODING:
- SWITCH_BY_COND_TYPE(type, warning, "");
- break;
-
case NODE_INTEGER:
case NODE_FLOAT:
case NODE_RATIONAL:
@@ -14357,22 +14306,22 @@ new_nil_at(struct parser_params *p, const rb_code_position_t *pos)
}
static NODE*
-new_if(struct parser_params *p, NODE *cc, NODE *left, NODE *right, const YYLTYPE *loc)
+new_if(struct parser_params *p, NODE *cc, NODE *left, NODE *right, const YYLTYPE *loc, const YYLTYPE* if_keyword_loc, const YYLTYPE* then_keyword_loc, const YYLTYPE* end_keyword_loc)
{
if (!cc) return right;
cc = cond0(p, cc, COND_IN_COND, loc, true);
- return newline_node(NEW_IF(cc, left, right, loc));
+ return newline_node(NEW_IF(cc, left, right, loc, if_keyword_loc, then_keyword_loc, end_keyword_loc));
}
static NODE*
-new_unless(struct parser_params *p, NODE *cc, NODE *left, NODE *right, const YYLTYPE *loc)
+new_unless(struct parser_params *p, NODE *cc, NODE *left, NODE *right, const YYLTYPE *loc, const YYLTYPE *keyword_loc, const YYLTYPE *then_keyword_loc, const YYLTYPE *end_keyword_loc)
{
if (!cc) return right;
cc = cond0(p, cc, COND_IN_COND, loc, true);
- return newline_node(NEW_UNLESS(cc, left, right, loc));
+ return newline_node(NEW_UNLESS(cc, left, right, loc, keyword_loc, then_keyword_loc, end_keyword_loc));
}
-#define NEW_AND_OR(type, f, s, loc) (type == NODE_AND ? NEW_AND(f,s,loc) : NEW_OR(f,s,loc))
+#define NEW_AND_OR(type, f, s, loc, op_loc) (type == NODE_AND ? NEW_AND(f,s,loc,op_loc) : NEW_OR(f,s,loc,op_loc))
static NODE*
logop(struct parser_params *p, ID id, NODE *left, NODE *right,
@@ -14380,18 +14329,18 @@ 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);
+ value_expr(p, left);
if (left && nd_type_p(left, type)) {
NODE *node = left, *second;
while ((second = RNODE_AND(node)->nd_2nd) != 0 && nd_type_p(second, type)) {
node = second;
}
- RNODE_AND(node)->nd_2nd = NEW_AND_OR(type, second, right, loc);
+ RNODE_AND(node)->nd_2nd = NEW_AND_OR(type, second, right, loc, op_loc);
nd_set_line(RNODE_AND(node)->nd_2nd, op_loc->beg_pos.lineno);
left->nd_loc.end_pos = loc->end_pos;
return left;
}
- op = NEW_AND_OR(type, left, right, loc);
+ op = NEW_AND_OR(type, left, right, loc, op_loc);
nd_set_line(op, op_loc->beg_pos.lineno);
return op;
}
@@ -14418,14 +14367,6 @@ ret_args(struct parser_params *p, NODE *node)
return node;
}
-static NODE *
-new_yield(struct parser_params *p, NODE *node, const YYLTYPE *loc)
-{
- if (node) no_blockarg(p, node);
-
- return NEW_YIELD(node, loc);
-}
-
static NODE*
negate_lit(struct parser_params *p, NODE* node)
{
@@ -14496,12 +14437,6 @@ new_args(struct parser_params *p, rb_node_args_aux_t *pre_args, rb_node_opt_arg_
args->opt_args = opt_args;
-#ifdef FORWARD_ARGS_WITH_RUBY2_KEYWORDS
- args->ruby2_keywords = args->forwarding;
-#else
- args->ruby2_keywords = 0;
-#endif
-
nd_set_loc(RNODE(tail), loc);
return tail;
@@ -14730,7 +14665,7 @@ static void
warn_duplicate_keys(struct parser_params *p, NODE *hash)
{
/* See https://bugs.ruby-lang.org/issues/20331 for discussion about what is warned. */
- st_table *literal_keys = st_init_table_with_size(&literal_type, RNODE_LIST(hash)->as.nd_alen / 2);
+ p->warn_duplicate_keys_table = st_init_table_with_size(&literal_type, RNODE_LIST(hash)->as.nd_alen / 2);
while (hash && RNODE_LIST(hash)->nd_next) {
NODE *head = RNODE_LIST(hash)->nd_head;
NODE *value = RNODE_LIST(hash)->nd_next;
@@ -14746,16 +14681,17 @@ warn_duplicate_keys(struct parser_params *p, NODE *hash)
if (nd_type_st_key_enable_p(head)) {
key = (st_data_t)head;
- if (st_delete(literal_keys, &key, &data)) {
+ if (st_delete(p->warn_duplicate_keys_table, &key, &data)) {
rb_warn2L(nd_line((NODE *)data),
"key %+"PRIsWARN" is duplicated and overwritten on line %d",
nd_value(p, head), WARN_I(nd_line(head)));
}
- st_insert(literal_keys, (st_data_t)key, (st_data_t)hash);
+ st_insert(p->warn_duplicate_keys_table, (st_data_t)key, (st_data_t)hash);
}
hash = next;
}
- st_free_table(literal_keys);
+ st_free_table(p->warn_duplicate_keys_table);
+ p->warn_duplicate_keys_table = NULL;
}
static NODE *
@@ -14774,7 +14710,11 @@ error_duplicate_pattern_variable(struct parser_params *p, ID id, const YYLTYPE *
if (st_is_member(p->pvtbl, id)) {
yyerror1(loc, "duplicated variable name");
}
+ else if (p->ctxt.in_alt_pattern && id) {
+ yyerror1(loc, "variable capture in alternative pattern");
+ }
else {
+ p->ctxt.capture_in_pattern = 1;
st_insert(p->pvtbl, (st_data_t)id, 0);
}
}
@@ -14831,24 +14771,26 @@ new_op_assign(struct parser_params *p, NODE *lhs, ID op, NODE *rhs, struct lex_c
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)
+ NODE *args, ID op, NODE *rhs, const YYLTYPE *args_loc, const YYLTYPE *loc,
+ const YYLTYPE *call_operator_loc, const YYLTYPE *opening_loc, const YYLTYPE *closing_loc, const YYLTYPE *binary_operator_loc)
{
NODE *asgn;
aryset_check(p, args);
args = make_list(args, args_loc);
- asgn = NEW_OP_ASGN1(ary, op, args, rhs, loc);
+ asgn = NEW_OP_ASGN1(ary, op, args, rhs, loc, call_operator_loc, opening_loc, closing_loc, binary_operator_loc);
fixpos(asgn, ary);
return asgn;
}
static NODE *
new_attr_op_assign(struct parser_params *p, NODE *lhs,
- ID atype, ID attr, ID op, NODE *rhs, const YYLTYPE *loc)
+ ID atype, ID attr, ID op, NODE *rhs, const YYLTYPE *loc,
+ const YYLTYPE *call_operator_loc, const YYLTYPE *message_loc, const YYLTYPE *binary_operator_loc)
{
NODE *asgn;
- asgn = NEW_OP_ASGN2(lhs, CALL_Q_P(atype), attr, op, rhs, loc);
+ asgn = NEW_OP_ASGN2(lhs, CALL_Q_P(atype), attr, op, rhs, loc, call_operator_loc, message_loc, binary_operator_loc);
fixpos(asgn, lhs);
return asgn;
}
@@ -15104,9 +15046,7 @@ static void
add_forwarding_args(struct parser_params *p)
{
arg_var(p, idFWD_REST);
-#ifndef FORWARD_ARGS_WITH_RUBY2_KEYWORDS
arg_var(p, idFWD_KWREST);
-#endif
arg_var(p, idFWD_BLOCK);
arg_var(p, idFWD_ALL);
}
@@ -15149,14 +15089,11 @@ static NODE *
new_args_forward_call(struct parser_params *p, NODE *leading, const YYLTYPE *loc, const YYLTYPE *argsloc)
{
NODE *rest = NEW_LVAR(idFWD_REST, loc);
-#ifndef FORWARD_ARGS_WITH_RUBY2_KEYWORDS
NODE *kwrest = list_append(p, NEW_LIST(0, loc), NEW_LVAR(idFWD_KWREST, loc));
-#endif
- rb_node_block_pass_t *block = NEW_BLOCK_PASS(NEW_LVAR(idFWD_BLOCK, loc), loc);
- NODE *args = leading ? rest_arg_append(p, leading, rest, argsloc) : NEW_SPLAT(rest, loc);
-#ifndef FORWARD_ARGS_WITH_RUBY2_KEYWORDS
- args = arg_append(p, args, new_hash(p, kwrest, loc), loc);
-#endif
+ rb_node_block_pass_t *block = NEW_BLOCK_PASS(NEW_LVAR(idFWD_BLOCK, loc), argsloc, &NULL_LOC);
+ NODE *args = leading ? rest_arg_append(p, leading, rest, argsloc) : NEW_SPLAT(rest, loc, &NULL_LOC);
+ block->forwarding = TRUE;
+ args = arg_append(p, args, new_hash(p, kwrest, loc), argsloc);
return arg_blk_pass(args, block);
}
@@ -15376,13 +15313,7 @@ rb_reg_fragment_setenc(struct parser_params* p, rb_parser_string_t *str, int opt
rb_parser_enc_associate(p, str, rb_ascii8bit_encoding());
}
else if (rb_is_usascii_enc(p->enc)) {
- if (!rb_parser_is_ascii_string(p, str)) {
- /* raise in re.c */
- rb_parser_enc_associate(p, str, rb_usascii_encoding());
- }
- else {
- rb_parser_enc_associate(p, str, rb_ascii8bit_encoding());
- }
+ rb_parser_enc_associate(p, str, rb_ascii8bit_encoding());
}
return 0;
@@ -15398,30 +15329,13 @@ reg_fragment_setenc(struct parser_params* p, rb_parser_string_t *str, int option
if (c) reg_fragment_enc_error(p, str, c);
}
-#ifndef RIPPER
-int
-reg_fragment_check(struct parser_params* p, rb_parser_string_t *str, int options)
-{
- VALUE err, str2;
- reg_fragment_setenc(p, str, options);
- /* TODO */
- str2 = rb_str_new_parser_string(str);
- err = rb_reg_check_preprocess(str2);
- if (err != Qnil) {
- err = rb_obj_as_string(err);
- compile_error(p, "%"PRIsVALUE, err);
- return 0;
- }
- return 1;
-}
-#endif
-
#ifndef UNIVERSAL_PARSER
typedef struct {
struct parser_params* parser;
rb_encoding *enc;
NODE *succ_block;
const YYLTYPE *loc;
+ rb_parser_assignable_func assignable;
} reg_named_capture_assign_t;
static int
@@ -15434,11 +15348,11 @@ reg_named_capture_assign_iter(const OnigUChar *name, const OnigUChar *name_end,
long len = name_end - name;
const char *s = (const char *)name;
- return rb_reg_named_capture_assign_iter_impl(p, s, len, enc, &arg->succ_block, arg->loc);
+ return rb_reg_named_capture_assign_iter_impl(p, s, len, enc, &arg->succ_block, arg->loc, arg->assignable);
}
static NODE *
-reg_named_capture_assign(struct parser_params* p, VALUE regexp, const YYLTYPE *loc)
+reg_named_capture_assign(struct parser_params* p, VALUE regexp, const YYLTYPE *loc, rb_parser_assignable_func assignable)
{
reg_named_capture_assign_t arg;
@@ -15446,6 +15360,7 @@ reg_named_capture_assign(struct parser_params* p, VALUE regexp, const YYLTYPE *l
arg.enc = rb_enc_get(regexp);
arg.succ_block = 0;
arg.loc = loc;
+ arg.assignable = assignable;
onig_foreach_name(RREGEXP_PTR(regexp), reg_named_capture_assign_iter, &arg);
if (!arg.succ_block) return 0;
@@ -15454,9 +15369,15 @@ reg_named_capture_assign(struct parser_params* p, VALUE regexp, const YYLTYPE *l
#endif
#ifndef RIPPER
+NODE *
+rb_parser_assignable(struct parser_params *p, ID id, NODE *val, const YYLTYPE *loc)
+{
+ return assignable(p, id, val, loc);
+}
+
int
rb_reg_named_capture_assign_iter_impl(struct parser_params *p, const char *s, long len,
- rb_encoding *enc, NODE **succ_block, const rb_code_location_t *loc)
+ rb_encoding *enc, NODE **succ_block, const rb_code_location_t *loc, rb_parser_assignable_func assignable)
{
ID var;
NODE *node, *succ;
@@ -15554,7 +15475,7 @@ parser_append_options(struct parser_params *p, NODE *node)
irs = list_append(p, irs, NEW_HASH(chomp, LOC));
}
- node = NEW_WHILE((NODE *)NEW_FCALL(idGets, irs, LOC), node, 1, LOC);
+ node = NEW_WHILE((NODE *)NEW_FCALL(idGets, irs, LOC), node, 1, LOC, &NULL_LOC, &NULL_LOC);
}
return node;
@@ -15636,6 +15557,14 @@ rb_ruby_parser_free(void *ptr)
struct parser_params *p = (struct parser_params*)ptr;
struct local_vars *local, *prev;
+ if (p->ast) {
+ rb_ast_free(p->ast);
+ }
+
+ if (p->warn_duplicate_keys_table) {
+ st_free_table(p->warn_duplicate_keys_table);
+ }
+
#ifndef RIPPER
if (p->tokens) {
rb_parser_ary_free(p, p->tokens);
@@ -15668,6 +15597,9 @@ rb_ruby_parser_free(void *ptr)
st_free_table(p->case_labels);
}
+ xfree(p->lex.strterm);
+ p->lex.strterm = 0;
+
xfree(ptr);
}
@@ -15876,23 +15808,9 @@ rb_ruby_ripper_parse0(rb_parser_t *p)
}
int
-rb_ruby_ripper_dedent_string(rb_parser_t *p, VALUE string, int width)
+rb_ruby_ripper_dedent_string(rb_parser_t *p, rb_parser_string_t *string, int width)
{
- char *str;
- long len;
- int i;
-
- RSTRING_GETMEM(string, str, len);
- i = dedent_string_column(str, len, width);
- if (!i) return 0;
-
- rb_str_modify(string);
- str = RSTRING_PTR(string);
- if (RSTRING_LEN(string) != len)
- rb_fatal("literal string changed: %+"PRIsVALUE, string);
- MEMMOVE(str, str + i, char, len - i);
- rb_str_set_len(string, len - i);
- return i;
+ return dedent_string(p, string, width);
}
int
@@ -15959,7 +15877,7 @@ rb_parser_printf(struct parser_params *p, const char *fmt, ...)
va_start(ap, fmt);
rb_str_vcatf(mesg, fmt, ap);
va_end(ap);
- if (end_with_newline_p(p, mesg)) {
+ if (char_at_end(p, mesg, 0) == '\n') {
rb_io_write(p->debug_output, mesg);
p->debug_buffer = Qnil;
}
@@ -16005,7 +15923,7 @@ count_char(const char *str, int c)
*
* "\"`class' keyword\"" => "`class' keyword"
*/
-RUBY_FUNC_EXPORTED size_t
+size_t
rb_yytnamerr(struct parser_params *p, char *yyres, const char *yystr)
{
if (*yystr == '"') {
diff --git a/parser_bits.h b/parser_bits.h
index ca7535280e..f894dde33e 100644
--- a/parser_bits.h
+++ b/parser_bits.h
@@ -30,13 +30,13 @@
#include <stdint.h> /* for uintptr_t */
#include "internal/compilers.h" /* for MSC_VERSION_SINCE */
-#if MSC_VERSION_SINCE(1310)
+#ifdef _MSC_VER
# include <stdlib.h> /* for _byteswap_uint64 */
#endif
#if defined(HAVE_X86INTRIN_H)
# include <x86intrin.h> /* for _lzcnt_u64 */
-#elif MSC_VERSION_SINCE(1310)
+#elif defined(_MSC_VER)
# include <intrin.h> /* for the following intrinsics */
#endif
@@ -50,16 +50,13 @@
# pragma intrinsic(__lzcnt64)
#endif
-#if MSC_VERSION_SINCE(1310)
+#if defined(_MSC_VER)
# 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
@@ -90,6 +87,7 @@
#define UNSIGNED_INTEGER_MAX(T) ((T)~(T)0)
+#ifndef MUL_OVERFLOW_SIGNED_INTEGER_P
#if __has_builtin(__builtin_mul_overflow_p)
# define MUL_OVERFLOW_P(a, b) \
__builtin_mul_overflow_p((a), (b), (__typeof__(a * b))0)
@@ -118,15 +116,100 @@
MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, FIXNUM_MIN, FIXNUM_MAX)
#endif
-#ifdef MUL_OVERFLOW_P
+#if defined(MUL_OVERFLOW_P) && defined(USE___BUILTIN_MUL_OVERFLOW_LONG_LONG)
# define MUL_OVERFLOW_LONG_LONG_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)
+#endif
+
+#ifdef MUL_OVERFLOW_P
# 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
+#endif
+
+#ifndef ADD_OVERFLOW_SIGNED_INTEGER_P
+#if __has_builtin(__builtin_add_overflow_p)
+# define ADD_OVERFLOW_P(a, b) \
+ __builtin_add_overflow_p((a), (b), (__typeof__(a * b))0)
+#elif __has_builtin(__builtin_add_overflow)
+# define ADD_OVERFLOW_P(a, b) \
+ __extension__ ({ __typeof__(a) c; __builtin_add_overflow((a), (b), &c); })
+#endif
+
+#define ADD_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max) ( \
+ (a) > 0 ? (b) > (max) - (a) : (b) < (min) - (a))
+
+#if __has_builtin(__builtin_add_overflow_p)
+/* __builtin_add_overflow_p can take bitfield */
+/* and GCC permits bitfields for integers other than int */
+# define ADD_OVERFLOW_FIXNUM_P(a, b) \
+ __extension__ ({ \
+ struct { long fixnum : sizeof(long) * CHAR_BIT - 1; } c = { 0 }; \
+ __builtin_add_overflow_p((a), (b), c.fixnum); \
+ })
+#else
+# define ADD_OVERFLOW_FIXNUM_P(a, b) \
+ ADD_OVERFLOW_SIGNED_INTEGER_P(a, b, FIXNUM_MIN, FIXNUM_MAX)
+#endif
+
+#if defined(ADD_OVERFLOW_P) && defined(USE___BUILTIN_ADD_OVERFLOW_LONG_LONG)
+# define ADD_OVERFLOW_LONG_LONG_P(a, b) ADD_OVERFLOW_P(a, b)
+#else
+# define ADD_OVERFLOW_LONG_LONG_P(a, b) ADD_OVERFLOW_SIGNED_INTEGER_P(a, b, LLONG_MIN, LLONG_MAX)
+#endif
+
+#ifdef ADD_OVERFLOW_P
+# define ADD_OVERFLOW_LONG_P(a, b) ADD_OVERFLOW_P(a, b)
+# define ADD_OVERFLOW_INT_P(a, b) ADD_OVERFLOW_P(a, b)
+#else
+# define ADD_OVERFLOW_LONG_P(a, b) ADD_OVERFLOW_SIGNED_INTEGER_P(a, b, LONG_MIN, LONG_MAX)
+# define ADD_OVERFLOW_INT_P(a, b) ADD_OVERFLOW_SIGNED_INTEGER_P(a, b, INT_MIN, INT_MAX)
+#endif
+#endif
+
+#ifndef SUB_OVERFLOW_SIGNED_INTEGER_P
+#if __has_builtin(__builtin_sub_overflow_p)
+# define SUB_OVERFLOW_P(a, b) \
+ __builtin_sub_overflow_p((a), (b), (__typeof__(a * b))0)
+#elif __has_builtin(__builtin_sub_overflow)
+# define SUB_OVERFLOW_P(a, b) \
+ __extension__ ({ __typeof__(a) c; __builtin_sub_overflow((a), (b), &c); })
+#endif
+
+#define SUB_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max) ( \
+ (b) > 0 ? (a) < (min) + (b) : (a) > (max) + (b))
+
+#if __has_builtin(__builtin_sub_overflow_p)
+/* __builtin_sub_overflow_p can take bitfield */
+/* and GCC permits bitfields for integers other than int */
+# define SUB_OVERFLOW_FIXNUM_P(a, b) \
+ __extension__ ({ \
+ struct { long fixnum : sizeof(long) * CHAR_BIT - 1; } c = { 0 }; \
+ __builtin_sub_overflow_p((a), (b), c.fixnum); \
+ })
+#else
+# define SUB_OVERFLOW_FIXNUM_P(a, b) \
+ SUB_OVERFLOW_SIGNED_INTEGER_P(a, b, FIXNUM_MIN, FIXNUM_MAX)
+#endif
+
+#if defined(SUB_OVERFLOW_P) && defined(USE___BUILTIN_SUB_OVERFLOW_LONG_LONG)
+# define SUB_OVERFLOW_LONG_LONG_P(a, b) SUB_OVERFLOW_P(a, b)
+#else
+# define SUB_OVERFLOW_LONG_LONG_P(a, b) SUB_OVERFLOW_SIGNED_INTEGER_P(a, b, LLONG_MIN, LLONG_MAX)
+#endif
+
+#ifdef SUB_OVERFLOW_P
+# define SUB_OVERFLOW_LONG_P(a, b) SUB_OVERFLOW_P(a, b)
+# define SUB_OVERFLOW_INT_P(a, b) SUB_OVERFLOW_P(a, b)
+#else
+# define SUB_OVERFLOW_LONG_P(a, b) SUB_OVERFLOW_SIGNED_INTEGER_P(a, b, LONG_MIN, LONG_MAX)
+# define SUB_OVERFLOW_INT_P(a, b) SUB_OVERFLOW_SIGNED_INTEGER_P(a, b, INT_MIN, INT_MAX)
+#endif
+#endif
#ifdef HAVE_UINT128_T
# define bit_length(x) \
@@ -180,7 +263,7 @@ ruby_swap16(uint16_t x)
#if __has_builtin(__builtin_bswap16)
return __builtin_bswap16(x);
-#elif MSC_VERSION_SINCE(1310)
+#elif defined(_MSC_VER)
return _byteswap_ushort(x);
#else
@@ -195,7 +278,7 @@ ruby_swap32(uint32_t x)
#if __has_builtin(__builtin_bswap32)
return __builtin_bswap32(x);
-#elif MSC_VERSION_SINCE(1310)
+#elif defined(_MSC_VER)
return _byteswap_ulong(x);
#else
@@ -212,7 +295,7 @@ ruby_swap64(uint64_t x)
#if __has_builtin(__builtin_bswap64)
return __builtin_bswap64(x);
-#elif MSC_VERSION_SINCE(1310)
+#elif defined(_MSC_VER)
return _byteswap_uint64(x);
#else
@@ -237,7 +320,7 @@ nlz_int32(uint32_t x)
#elif defined(__x86_64__) && defined(__LZCNT__)
return (unsigned int)_lzcnt_u32(x);
-#elif MSC_VERSION_SINCE(1400) /* &&! defined(__AVX2__) */
+#elif defined(_MSC_VER) /* &&! defined(__AVX2__) */
unsigned long r;
return _BitScanReverse(&r, x) ? (31 - (int)r) : 32;
@@ -266,7 +349,7 @@ nlz_int64(uint64_t x)
#elif defined(__x86_64__) && defined(__LZCNT__)
return (unsigned int)_lzcnt_u64(x);
-#elif defined(_WIN64) && MSC_VERSION_SINCE(1400) /* &&! defined(__AVX2__) */
+#elif defined(_WIN64) && defined(_MSC_VER) /* &&! defined(__AVX2__) */
unsigned long r;
return _BitScanReverse64(&r, x) ? (63u - (unsigned int)r) : 64;
@@ -394,9 +477,9 @@ rb_popcount32(uint32_t 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);
+ x = (x & 0x07070707) + (x >> 4 & 0x07070707);
+ x = (x & 0x000f000f) + (x >> 8 & 0x000f000f);
+ x = (x & 0x0000001f) + (x >>16 & 0x0000001f);
return (unsigned int)x;
#endif
@@ -424,9 +507,9 @@ rb_popcount64(uint64_t x)
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);
+ x = (x & 0x000f000f000f000f) + (x >> 8 & 0x000f000f000f000f);
+ x = (x & 0x0000001f0000001f) + (x >>16 & 0x0000001f0000001f);
+ x = (x & 0x000000000000003f) + (x >>32 & 0x000000000000003f);
return (unsigned int)x;
#endif
@@ -452,7 +535,7 @@ ntz_int32(uint32_t x)
#if defined(__x86_64__) && defined(__BMI__)
return (unsigned)_tzcnt_u32(x);
-#elif MSC_VERSION_SINCE(1400)
+#elif defined(_MSC_VER)
/* :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;
@@ -474,7 +557,7 @@ ntz_int64(uint64_t x)
#if defined(__x86_64__) && defined(__BMI__)
return (unsigned)_tzcnt_u64(x);
-#elif defined(_WIN64) && MSC_VERSION_SINCE(1400)
+#elif defined(_WIN64) && defined(_MSC_VER)
unsigned long r;
return _BitScanForward64(&r, x) ? (int)r : 64;
@@ -522,10 +605,10 @@ RUBY_BIT_ROTL(VALUE v, int 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)
+#elif defined(_MSC_VER) && (SIZEOF_VALUE * CHAR_BIT == 32)
return _rotl(v, n);
-#elif MSC_VERSION_SINCE(1310) && (SIZEOF_VALUE * CHAR_BIT == 64)
+#elif defined(_MSC_VER) && (SIZEOF_VALUE * CHAR_BIT == 64)
return _rotl64(v, n);
#elif defined(_lrotl) && (SIZEOF_VALUE == SIZEOF_LONG)
@@ -546,10 +629,10 @@ RUBY_BIT_ROTR(VALUE v, int 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)
+#elif defined(_MSC_VER) && (SIZEOF_VALUE * CHAR_BIT == 32)
return _rotr(v, n);
-#elif MSC_VERSION_SINCE(1310) && (SIZEOF_VALUE * CHAR_BIT == 64)
+#elif defined(_MSC_VER) && (SIZEOF_VALUE * CHAR_BIT == 64)
return _rotr64(v, n);
#elif defined(_lrotr) && (SIZEOF_VALUE == SIZEOF_LONG)
diff --git a/parser_st.c b/parser_st.c
index 17f669e763..c234026122 100644
--- a/parser_st.c
+++ b/parser_st.c
@@ -154,7 +154,8 @@ nonempty_memcpy(void *dest, const void *src, size_t n)
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wattributes\"") \
__attribute__((__no_sanitize__(x))) y; \
- _Pragma("GCC diagnostic pop")
+ _Pragma("GCC diagnostic pop") \
+ y
#endif
#ifndef NO_SANITIZE
diff --git a/pathname.c b/pathname.c
new file mode 100644
index 0000000000..71c78d89e7
--- /dev/null
+++ b/pathname.c
@@ -0,0 +1,117 @@
+#include "ruby.h"
+
+static VALUE rb_cPathname;
+static ID id_at_path;
+static ID id_sub;
+
+static VALUE
+get_strpath(VALUE obj)
+{
+ VALUE strpath;
+ strpath = rb_ivar_get(obj, id_at_path);
+ if (!RB_TYPE_P(strpath, T_STRING))
+ rb_raise(rb_eTypeError, "unexpected @path");
+ return strpath;
+}
+
+/*
+ * Provides a case-sensitive comparison operator for pathnames.
+ *
+ * Pathname.new('/usr') <=> Pathname.new('/usr/bin')
+ * #=> -1
+ * Pathname.new('/usr/bin') <=> Pathname.new('/usr/bin')
+ * #=> 0
+ * Pathname.new('/usr/bin') <=> Pathname.new('/USR/BIN')
+ * #=> 1
+ *
+ * It will return +-1+, +0+ or +1+ depending on the value of the left argument
+ * relative to the right argument. Or it will return +nil+ if the arguments
+ * are not comparable.
+ */
+static VALUE
+path_cmp(VALUE self, VALUE other)
+{
+ VALUE s1, s2;
+ char *p1, *p2;
+ char *e1, *e2;
+ if (!rb_obj_is_kind_of(other, rb_cPathname))
+ return Qnil;
+ s1 = get_strpath(self);
+ s2 = get_strpath(other);
+ p1 = RSTRING_PTR(s1);
+ p2 = RSTRING_PTR(s2);
+ e1 = p1 + RSTRING_LEN(s1);
+ e2 = p2 + RSTRING_LEN(s2);
+ while (p1 < e1 && p2 < e2) {
+ int c1, c2;
+ c1 = (unsigned char)*p1++;
+ c2 = (unsigned char)*p2++;
+ if (c1 == '/') c1 = '\0';
+ if (c2 == '/') c2 = '\0';
+ if (c1 != c2) {
+ if (c1 < c2)
+ return INT2FIX(-1);
+ else
+ return INT2FIX(1);
+ }
+ }
+ if (p1 < e1)
+ return INT2FIX(1);
+ if (p2 < e2)
+ return INT2FIX(-1);
+ return INT2FIX(0);
+}
+
+/*
+ * Return a pathname which is substituted by String#sub.
+ *
+ * path1 = Pathname.new('/usr/bin/perl')
+ * path1.sub('perl', 'ruby')
+ * #=> #<Pathname:/usr/bin/ruby>
+ */
+static VALUE
+path_sub(int argc, VALUE *argv, VALUE self)
+{
+ VALUE str = get_strpath(self);
+
+ if (rb_block_given_p()) {
+ str = rb_block_call(str, id_sub, argc, argv, 0, 0);
+ }
+ else {
+ str = rb_funcallv(str, id_sub, argc, argv);
+ }
+ return rb_class_new_instance(1, &str, rb_obj_class(self));
+}
+
+#include "pathname_builtin.rbinc"
+
+static void init_ids(void);
+
+void
+Init_pathname(void)
+{
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ rb_ext_ractor_safe(true);
+#endif
+
+ init_ids();
+ InitVM(pathname);
+}
+
+void
+InitVM_pathname(void)
+{
+ rb_cPathname = rb_define_class("Pathname", rb_cObject);
+ rb_define_method(rb_cPathname, "<=>", path_cmp, 1);
+ rb_define_method(rb_cPathname, "sub", path_sub, -1);
+
+ rb_provide("pathname.so");
+}
+
+void
+init_ids(void)
+{
+#undef rb_intern
+ id_at_path = rb_intern("@path");
+ id_sub = rb_intern("sub");
+}
diff --git a/pathname_builtin.rb b/pathname_builtin.rb
new file mode 100644
index 0000000000..878603d4d6
--- /dev/null
+++ b/pathname_builtin.rb
@@ -0,0 +1,1172 @@
+# frozen_string_literal: true
+#
+# = pathname.rb
+#
+# Object-Oriented Pathname Class
+#
+# Author:: Tanaka Akira <akr@m17n.org>
+# Documentation:: Author and Gavin Sinclair
+#
+# For documentation, see class Pathname.
+#
+
+#
+# Pathname represents the name of a file or directory on the filesystem,
+# but not the file itself.
+#
+# The pathname depends on the Operating System: Unix, Windows, etc.
+# This library works with pathnames of local OS, however non-Unix pathnames
+# are supported experimentally.
+#
+# A Pathname can be relative or absolute. It's not until you try to
+# reference the file that it even matters whether the file exists or not.
+#
+# Pathname is immutable. It has no method for destructive update.
+#
+# The goal of this class is to manipulate file path information in a neater
+# way than standard Ruby provides. The examples below demonstrate the
+# difference.
+#
+# *All* functionality from File, FileTest, and some from Dir and FileUtils is
+# included, in an unsurprising way. It is essentially a facade for all of
+# these, and more.
+#
+# == Examples
+#
+# === Example 1: Using Pathname
+#
+# require 'pathname'
+# pn = Pathname.new("/usr/bin/ruby")
+# size = pn.size # 27662
+# isdir = pn.directory? # false
+# dir = pn.dirname # Pathname:/usr/bin
+# base = pn.basename # Pathname:ruby
+# dir, base = pn.split # [Pathname:/usr/bin, Pathname:ruby]
+# data = pn.read
+# pn.open { |f| _ }
+# pn.each_line { |line| _ }
+#
+# === Example 2: Using standard Ruby
+#
+# pn = "/usr/bin/ruby"
+# size = File.size(pn) # 27662
+# isdir = File.directory?(pn) # false
+# dir = File.dirname(pn) # "/usr/bin"
+# base = File.basename(pn) # "ruby"
+# dir, base = File.split(pn) # ["/usr/bin", "ruby"]
+# data = File.read(pn)
+# File.open(pn) { |f| _ }
+# File.foreach(pn) { |line| _ }
+#
+# === Example 3: Special features
+#
+# p1 = Pathname.new("/usr/lib") # Pathname:/usr/lib
+# p2 = p1 + "ruby/1.8" # Pathname:/usr/lib/ruby/1.8
+# p3 = p1.parent # Pathname:/usr
+# p4 = p2.relative_path_from(p3) # Pathname:lib/ruby/1.8
+# pwd = Pathname.pwd # Pathname:/home/gavin
+# pwd.absolute? # true
+# p5 = Pathname.new "." # Pathname:.
+# p5 = p5 + "music/../articles" # Pathname:music/../articles
+# p5.cleanpath # Pathname:articles
+# p5.realpath # Pathname:/home/gavin/articles
+# p5.children # [Pathname:/home/gavin/articles/linux, ...]
+#
+# == Breakdown of functionality
+#
+# === Core methods
+#
+# These methods are effectively manipulating a String, because that's
+# all a path is. None of these access the file system except for
+# #mountpoint?, #children, #each_child, #realdirpath and #realpath.
+#
+# - +
+# - #join
+# - #parent
+# - #root?
+# - #absolute?
+# - #relative?
+# - #relative_path_from
+# - #each_filename
+# - #cleanpath
+# - #realpath
+# - #realdirpath
+# - #children
+# - #each_child
+# - #mountpoint?
+#
+# === File status predicate methods
+#
+# These methods are a facade for FileTest:
+# - #blockdev?
+# - #chardev?
+# - #directory?
+# - #executable?
+# - #executable_real?
+# - #exist?
+# - #file?
+# - #grpowned?
+# - #owned?
+# - #pipe?
+# - #readable?
+# - #world_readable?
+# - #readable_real?
+# - #setgid?
+# - #setuid?
+# - #size
+# - #size?
+# - #socket?
+# - #sticky?
+# - #symlink?
+# - #writable?
+# - #world_writable?
+# - #writable_real?
+# - #zero?
+#
+# === File property and manipulation methods
+#
+# These methods are a facade for File:
+# - #each_line(*args, &block)
+# - #read(*args)
+# - #binread(*args)
+# - #readlines(*args)
+# - #sysopen(*args)
+# - #write(*args)
+# - #binwrite(*args)
+# - #atime
+# - #birthtime
+# - #ctime
+# - #mtime
+# - #chmod(mode)
+# - #lchmod(mode)
+# - #chown(owner, group)
+# - #lchown(owner, group)
+# - #fnmatch(pattern, *args)
+# - #fnmatch?(pattern, *args)
+# - #ftype
+# - #make_link(old)
+# - #open(*args, &block)
+# - #readlink
+# - #rename(to)
+# - #stat
+# - #lstat
+# - #make_symlink(old)
+# - #truncate(length)
+# - #utime(atime, mtime)
+# - #lutime(atime, mtime)
+# - #basename(*args)
+# - #dirname
+# - #extname
+# - #expand_path(*args)
+# - #split
+#
+# === Directory methods
+#
+# These methods are a facade for Dir:
+# - Pathname.glob(*args)
+# - Pathname.getwd / Pathname.pwd
+# - #rmdir
+# - #entries
+# - #each_entry(&block)
+# - #mkdir(*args)
+# - #opendir(*args)
+#
+# === Utilities
+#
+# These methods are a mixture of Find, FileUtils, and others:
+# - #find(&block)
+# - #mkpath
+# - #rmtree
+# - #unlink / #delete
+#
+#
+# == Method documentation
+#
+# As the above section shows, most of the methods in Pathname are facades. The
+# documentation for these methods generally just says, for instance, "See
+# FileTest.writable?", as you should be familiar with the original method
+# anyway, and its documentation (e.g. through +ri+) will contain more
+# information. In some cases, a brief description will follow.
+#
+class Pathname
+
+ # The version string.
+ VERSION = "0.4.0"
+
+ # :stopdoc:
+
+ if File::FNM_SYSCASE.nonzero?
+ # Avoid #zero? here because #casecmp can return nil.
+ private def same_paths?(a, b) a.casecmp(b) == 0 end
+ else
+ private def same_paths?(a, b) a == b end
+ end
+
+ attr_reader :path
+ protected :path
+
+ # :startdoc:
+
+ #
+ # Create a Pathname object from the given String (or String-like object).
+ # If +path+ contains a NUL character (<tt>\0</tt>), an ArgumentError is raised.
+ #
+ def initialize(path)
+ @path = File.path(path).dup
+ rescue TypeError => e
+ raise e.class, "Pathname.new requires a String, #to_path or #to_str", cause: nil
+ end
+
+ #
+ # Freze self.
+ #
+ def freeze
+ super
+ @path.freeze
+ self
+ end
+
+ #
+ # Compare this pathname with +other+. The comparison is string-based.
+ # Be aware that two different paths (<tt>foo.txt</tt> and <tt>./foo.txt</tt>)
+ # can refer to the same file.
+ #
+ def ==(other)
+ return false unless Pathname === other
+ other.path == @path
+ end
+ alias === ==
+ alias eql? ==
+
+ unless method_defined?(:<=>, false)
+ # Provides for comparing pathnames, case-sensitively.
+ def <=>(other)
+ return nil unless Pathname === other
+ @path.tr('/', "\0") <=> other.path.tr('/', "\0")
+ end
+ end
+
+ def hash # :nodoc:
+ @path.hash
+ end
+
+ # Return the path as a String.
+ def to_s
+ @path.dup
+ end
+
+ # to_path is implemented so Pathname objects are usable with File.open, etc.
+ alias to_path to_s
+
+ def inspect # :nodoc:
+ "#<#{self.class}:#{@path}>"
+ end
+
+ unless method_defined?(:sub, false)
+ # Return a pathname which is substituted by String#sub.
+ def sub(pattern, *args, **kwargs, &block)
+ if block
+ path = @path.sub(pattern, *args, **kwargs) {|*sub_args|
+ begin
+ old = Thread.current[:pathname_sub_matchdata]
+ Thread.current[:pathname_sub_matchdata] = $~
+ eval("$~ = Thread.current[:pathname_sub_matchdata]", block.binding)
+ ensure
+ Thread.current[:pathname_sub_matchdata] = old
+ end
+ yield(*sub_args)
+ }
+ else
+ path = @path.sub(pattern, *args, **kwargs)
+ end
+ self.class.new(path)
+ end
+ end
+
+ # Return a pathname with +repl+ added as a suffix to the basename.
+ #
+ # If self has no extension part, +repl+ is appended.
+ #
+ # Pathname.new('/usr/bin/shutdown').sub_ext('.rb')
+ # #=> #<Pathname:/usr/bin/shutdown.rb>
+ def sub_ext(repl)
+ ext = File.extname(@path)
+
+ # File.extname("foo.bar:stream") returns ".bar" on NTFS and not ".bar:stream"
+ # (see ruby_enc_find_extname()).
+ # The behavior of Pathname#sub_ext is to replace everything
+ # from the start of the extname until the end of the path with repl.
+ unless @path.end_with?(ext)
+ ext = @path[@path.rindex(ext)..]
+ end
+
+ self.class.new(@path.chomp(ext) + repl)
+ end
+
+ if File::ALT_SEPARATOR
+ # Separator list string.
+ SEPARATOR_LIST = Regexp.quote "#{File::ALT_SEPARATOR}#{File::SEPARATOR}"
+ # Regexp that matches a separator.
+ SEPARATOR_PAT = /[#{SEPARATOR_LIST}]/
+ else
+ SEPARATOR_LIST = Regexp.quote File::SEPARATOR
+ SEPARATOR_PAT = /#{SEPARATOR_LIST}/
+ end
+ SEPARATOR_LIST.freeze
+ SEPARATOR_PAT.freeze
+ private_constant :SEPARATOR_LIST, :SEPARATOR_LIST
+
+ if File.dirname('A:') == 'A:.' # DOSish drive letter
+ # Regexp that matches an absolute path.
+ ABSOLUTE_PATH = /\A(?:[A-Za-z]:|#{SEPARATOR_PAT})/
+ else
+ ABSOLUTE_PATH = /\A#{SEPARATOR_PAT}/
+ end
+ ABSOLUTE_PATH.freeze
+ private_constant :ABSOLUTE_PATH
+
+ # :startdoc:
+
+ # Creates a full path, including any intermediate directories that don't yet
+ # exist.
+ #
+ # See FileUtils.mkpath and FileUtils.mkdir_p
+ def mkpath(mode: nil)
+ path = @path == '/' ? @path : @path.chomp('/')
+
+ stack = []
+ until File.directory?(path) || File.dirname(path) == path
+ stack.push path
+ path = File.dirname(path)
+ end
+
+ stack.reverse_each do |dir|
+ dir = dir == '/' ? dir : dir.chomp('/')
+ if mode
+ Dir.mkdir dir, mode
+ File.chmod mode, dir
+ else
+ Dir.mkdir dir
+ end
+ rescue SystemCallError
+ raise unless File.directory?(dir)
+ end
+
+ self
+ end
+
+ # chop_basename(path) -> [pre-basename, basename] or nil
+ def chop_basename(path) # :nodoc:
+ base = File.basename(path)
+ if /\A#{SEPARATOR_PAT}?\z/o.match?(base)
+ return nil
+ else
+ return path[0, path.rindex(base)], base
+ end
+ end
+ private :chop_basename
+
+ # split_names(path) -> prefix, [name, ...]
+ def split_names(path) # :nodoc:
+ names = []
+ while r = chop_basename(path)
+ path, basename = r
+ names.unshift basename
+ end
+ return path, names
+ end
+ private :split_names
+
+ def prepend_prefix(prefix, relpath) # :nodoc:
+ if relpath.empty?
+ File.dirname(prefix)
+ elsif SEPARATOR_PAT.match?(prefix)
+ prefix = File.dirname(prefix)
+ prefix = File.join(prefix, "") if File.basename(prefix + 'a') != 'a'
+ prefix + relpath
+ else
+ prefix + relpath
+ end
+ end
+ private :prepend_prefix
+
+ # Returns clean pathname of +self+ with consecutive slashes and useless dots
+ # removed. The filesystem is not accessed.
+ #
+ # If +consider_symlink+ is +true+, then a more conservative algorithm is used
+ # to avoid breaking symbolic linkages. This may retain more +..+
+ # entries than absolutely necessary, but without accessing the filesystem,
+ # this can't be avoided.
+ #
+ # See Pathname#realpath.
+ #
+ def cleanpath(consider_symlink=false)
+ if consider_symlink
+ cleanpath_conservative
+ else
+ cleanpath_aggressive
+ end
+ end
+
+ #
+ # Clean the path simply by resolving and removing excess +.+ and +..+ entries.
+ # Nothing more, nothing less.
+ #
+ def cleanpath_aggressive # :nodoc:
+ path = @path
+ names = []
+ pre = path
+ while r = chop_basename(pre)
+ pre, base = r
+ case base
+ when '.'
+ when '..'
+ names.unshift base
+ else
+ if names[0] == '..'
+ names.shift
+ else
+ names.unshift base
+ end
+ end
+ end
+ pre.tr!(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
+ if SEPARATOR_PAT.match?(File.basename(pre))
+ names.shift while names[0] == '..'
+ end
+ self.class.new(prepend_prefix(pre, File.join(*names)))
+ end
+ private :cleanpath_aggressive
+
+ # has_trailing_separator?(path) -> bool
+ def has_trailing_separator?(path) # :nodoc:
+ if r = chop_basename(path)
+ pre, basename = r
+ pre.length + basename.length < path.length
+ else
+ false
+ end
+ end
+ private :has_trailing_separator?
+
+ # add_trailing_separator(path) -> path
+ def add_trailing_separator(path) # :nodoc:
+ if File.basename(path + 'a') == 'a'
+ path
+ else
+ File.join(path, "") # xxx: Is File.join is appropriate to add separator?
+ end
+ end
+ private :add_trailing_separator
+
+ def del_trailing_separator(path) # :nodoc:
+ if r = chop_basename(path)
+ pre, basename = r
+ pre + basename
+ elsif /#{SEPARATOR_PAT}+\z/o =~ path
+ $` + File.dirname(path)[/#{SEPARATOR_PAT}*\z/o]
+ else
+ path
+ end
+ end
+ private :del_trailing_separator
+
+ def cleanpath_conservative # :nodoc:
+ path = @path
+ names = []
+ pre = path
+ while r = chop_basename(pre)
+ pre, base = r
+ names.unshift base if base != '.'
+ end
+ pre.tr!(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
+ if SEPARATOR_PAT.match?(File.basename(pre))
+ names.shift while names[0] == '..'
+ end
+ if names.empty?
+ self.class.new(File.dirname(pre))
+ else
+ if names.last != '..' && File.basename(path) == '.'
+ names << '.'
+ end
+ result = prepend_prefix(pre, File.join(*names))
+ if /\A(?:\.|\.\.)\z/ !~ names.last && has_trailing_separator?(path)
+ self.class.new(add_trailing_separator(result))
+ else
+ self.class.new(result)
+ end
+ end
+ end
+ private :cleanpath_conservative
+
+ # Returns the parent directory.
+ #
+ # This is same as <code>self + '..'</code>.
+ def parent
+ self + '..'
+ end
+
+ # Returns +true+ if +self+ points to a mountpoint.
+ def mountpoint?
+ begin
+ stat1 = self.lstat
+ stat2 = self.parent.lstat
+ stat1.dev != stat2.dev || stat1.ino == stat2.ino
+ rescue Errno::ENOENT
+ false
+ end
+ end
+
+ #
+ # Predicate method for root directories. Returns +true+ if the
+ # pathname consists of consecutive slashes.
+ #
+ # It doesn't access the filesystem. So it may return +false+ for some
+ # pathnames which points to roots such as <tt>/usr/..</tt>.
+ #
+ def root?
+ chop_basename(@path) == nil && SEPARATOR_PAT.match?(@path)
+ end
+
+ # Predicate method for testing whether a path is absolute.
+ #
+ # It returns +true+ if the pathname begins with a slash.
+ #
+ # p = Pathname.new('/im/sure')
+ # p.absolute?
+ # #=> true
+ #
+ # p = Pathname.new('not/so/sure')
+ # p.absolute?
+ # #=> false
+ def absolute?
+ ABSOLUTE_PATH.match? @path
+ end
+
+ # The opposite of Pathname#absolute?
+ #
+ # It returns +false+ if the pathname begins with a slash.
+ #
+ # p = Pathname.new('/im/sure')
+ # p.relative?
+ # #=> false
+ #
+ # p = Pathname.new('not/so/sure')
+ # p.relative?
+ # #=> true
+ def relative?
+ !absolute?
+ end
+
+ #
+ # Iterates over each component of the path.
+ #
+ # Pathname.new("/usr/bin/ruby").each_filename {|filename| ... }
+ # # yields "usr", "bin", and "ruby".
+ #
+ # Returns an Enumerator if no block was given.
+ #
+ # enum = Pathname.new("/usr/bin/ruby").each_filename
+ # # ... do stuff ...
+ # enum.each { |e| ... }
+ # # yields "usr", "bin", and "ruby".
+ #
+ def each_filename # :yield: filename
+ return to_enum(__method__) unless block_given?
+ _, names = split_names(@path)
+ names.each {|filename| yield filename }
+ nil
+ end
+
+ # Iterates over and yields a new Pathname object
+ # for each element in the given path in descending order.
+ #
+ # Pathname.new('/path/to/some/file.rb').descend {|v| p v}
+ # #<Pathname:/>
+ # #<Pathname:/path>
+ # #<Pathname:/path/to>
+ # #<Pathname:/path/to/some>
+ # #<Pathname:/path/to/some/file.rb>
+ #
+ # Pathname.new('path/to/some/file.rb').descend {|v| p v}
+ # #<Pathname:path>
+ # #<Pathname:path/to>
+ # #<Pathname:path/to/some>
+ # #<Pathname:path/to/some/file.rb>
+ #
+ # Returns an Enumerator if no block was given.
+ #
+ # enum = Pathname.new("/usr/bin/ruby").descend
+ # # ... do stuff ...
+ # enum.each { |e| ... }
+ # # yields Pathnames /, /usr, /usr/bin, and /usr/bin/ruby.
+ #
+ # It doesn't access the filesystem.
+ #
+ def descend
+ return to_enum(__method__) unless block_given?
+ vs = []
+ ascend {|v| vs << v }
+ vs.reverse_each {|v| yield v }
+ nil
+ end
+
+ # Iterates over and yields a new Pathname object
+ # for each element in the given path in ascending order.
+ #
+ # Pathname.new('/path/to/some/file.rb').ascend {|v| p v}
+ # #<Pathname:/path/to/some/file.rb>
+ # #<Pathname:/path/to/some>
+ # #<Pathname:/path/to>
+ # #<Pathname:/path>
+ # #<Pathname:/>
+ #
+ # Pathname.new('path/to/some/file.rb').ascend {|v| p v}
+ # #<Pathname:path/to/some/file.rb>
+ # #<Pathname:path/to/some>
+ # #<Pathname:path/to>
+ # #<Pathname:path>
+ #
+ # Returns an Enumerator if no block was given.
+ #
+ # enum = Pathname.new("/usr/bin/ruby").ascend
+ # # ... do stuff ...
+ # enum.each { |e| ... }
+ # # yields Pathnames /usr/bin/ruby, /usr/bin, /usr, and /.
+ #
+ # It doesn't access the filesystem.
+ #
+ def ascend
+ return to_enum(__method__) unless block_given?
+ path = @path
+ yield self
+ while r = chop_basename(path)
+ path, = r
+ break if path.empty?
+ yield self.class.new(del_trailing_separator(path))
+ end
+ end
+
+ #
+ # Appends a pathname fragment to +self+ to produce a new Pathname object.
+ # Since +other+ is considered as a path relative to +self+, if +other+ is
+ # an absolute path, the new Pathname object is created from just +other+.
+ #
+ # p1 = Pathname.new("/usr") # Pathname:/usr
+ # p2 = p1 + "bin/ruby" # Pathname:/usr/bin/ruby
+ # p3 = p1 + "/etc/passwd" # Pathname:/etc/passwd
+ #
+ # # / is aliased to +.
+ # p4 = p1 / "bin/ruby" # Pathname:/usr/bin/ruby
+ # p5 = p1 / "/etc/passwd" # Pathname:/etc/passwd
+ #
+ # This method doesn't access the file system; it is pure string manipulation.
+ #
+ def +(other)
+ other = Pathname.new(other) unless Pathname === other
+ Pathname.new(plus(@path, other.path))
+ end
+ alias / +
+
+ def plus(path1, path2) # -> path # :nodoc:
+ prefix2 = path2
+ index_list2 = []
+ basename_list2 = []
+ while r2 = chop_basename(prefix2)
+ prefix2, basename2 = r2
+ index_list2.unshift prefix2.length
+ basename_list2.unshift basename2
+ end
+ return path2 if prefix2 != ''
+ prefix1 = path1
+ while true
+ while !basename_list2.empty? && basename_list2.first == '.'
+ index_list2.shift
+ basename_list2.shift
+ end
+ break unless r1 = chop_basename(prefix1)
+ prefix1, basename1 = r1
+ next if basename1 == '.'
+ if basename1 == '..' || basename_list2.empty? || basename_list2.first != '..'
+ prefix1 = prefix1 + basename1
+ break
+ end
+ index_list2.shift
+ basename_list2.shift
+ end
+ r1 = chop_basename(prefix1)
+ if !r1 && (r1 = SEPARATOR_PAT.match?(File.basename(prefix1)))
+ while !basename_list2.empty? && basename_list2.first == '..'
+ index_list2.shift
+ basename_list2.shift
+ end
+ end
+ if !basename_list2.empty?
+ suffix2 = path2[index_list2.first..-1]
+ r1 ? File.join(prefix1, suffix2) : prefix1 + suffix2
+ else
+ r1 ? prefix1 : File.dirname(prefix1)
+ end
+ end
+ private :plus
+
+ #
+ # Joins the given pathnames onto +self+ to create a new Pathname object.
+ # This is effectively the same as using Pathname#+ to append +self+ and
+ # all arguments sequentially.
+ #
+ # path0 = Pathname.new("/usr") # Pathname:/usr
+ # path0 = path0.join("bin/ruby") # Pathname:/usr/bin/ruby
+ # # is the same as
+ # path1 = Pathname.new("/usr") + "bin/ruby" # Pathname:/usr/bin/ruby
+ # path0 == path1
+ # #=> true
+ #
+ def join(*args)
+ return self if args.empty?
+ result = args.pop
+ result = Pathname.new(result) unless Pathname === result
+ return result if result.absolute?
+ args.reverse_each {|arg|
+ arg = Pathname.new(arg) unless Pathname === arg
+ result = arg + result
+ return result if result.absolute?
+ }
+ self + result
+ end
+
+ #
+ # Returns the children of the directory (files and subdirectories, not
+ # recursive) as an array of Pathname objects.
+ #
+ # By default, the returned pathnames will have enough information to access
+ # the files. If you set +with_directory+ to +false+, then the returned
+ # pathnames will contain the filename only.
+ #
+ # For example:
+ # pn = Pathname("/usr/lib/ruby/1.8")
+ # pn.children
+ # # -> [ Pathname:/usr/lib/ruby/1.8/English.rb,
+ # Pathname:/usr/lib/ruby/1.8/Env.rb,
+ # Pathname:/usr/lib/ruby/1.8/abbrev.rb, ... ]
+ # pn.children(false)
+ # # -> [ Pathname:English.rb, Pathname:Env.rb, Pathname:abbrev.rb, ... ]
+ #
+ # Note that the results never contain the entries +.+ and +..+ in
+ # the directory because they are not children.
+ #
+ def children(with_directory=true)
+ with_directory = false if @path == '.'
+ result = []
+ Dir.foreach(@path) {|e|
+ next if e == '.' || e == '..'
+ if with_directory
+ result << self.class.new(File.join(@path, e))
+ else
+ result << self.class.new(e)
+ end
+ }
+ result
+ end
+
+ # Iterates over the children of the directory
+ # (files and subdirectories, not recursive).
+ #
+ # It yields Pathname object for each child.
+ #
+ # By default, the yielded pathnames will have enough information to access
+ # the files.
+ #
+ # If you set +with_directory+ to +false+, then the returned pathnames will
+ # contain the filename only.
+ #
+ # Pathname("/usr/local").each_child {|f| p f }
+ # #=> #<Pathname:/usr/local/share>
+ # # #<Pathname:/usr/local/bin>
+ # # #<Pathname:/usr/local/games>
+ # # #<Pathname:/usr/local/lib>
+ # # #<Pathname:/usr/local/include>
+ # # #<Pathname:/usr/local/sbin>
+ # # #<Pathname:/usr/local/src>
+ # # #<Pathname:/usr/local/man>
+ #
+ # Pathname("/usr/local").each_child(false) {|f| p f }
+ # #=> #<Pathname:share>
+ # # #<Pathname:bin>
+ # # #<Pathname:games>
+ # # #<Pathname:lib>
+ # # #<Pathname:include>
+ # # #<Pathname:sbin>
+ # # #<Pathname:src>
+ # # #<Pathname:man>
+ #
+ # Note that the results never contain the entries +.+ and +..+ in
+ # the directory because they are not children.
+ #
+ # See Pathname#children
+ #
+ def each_child(with_directory=true, &b)
+ children(with_directory).each(&b)
+ end
+
+ #
+ # Returns a relative path from the given +base_directory+ to the receiver.
+ #
+ # If +self+ is absolute, then +base_directory+ must be absolute too.
+ #
+ # If +self+ is relative, then +base_directory+ must be relative too.
+ #
+ # This method doesn't access the filesystem. It assumes no symlinks.
+ #
+ # 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.path
+ base_directory = base_directory.cleanpath.path
+ dest_prefix = dest_directory
+ dest_names = []
+ while r = chop_basename(dest_prefix)
+ dest_prefix, basename = r
+ dest_names.unshift basename if basename != '.'
+ end
+ base_prefix = base_directory
+ base_names = []
+ while r = chop_basename(base_prefix)
+ base_prefix, basename = r
+ base_names.unshift basename if basename != '.'
+ end
+ unless same_paths?(dest_prefix, base_prefix)
+ raise ArgumentError, "different prefix: #{dest_prefix.inspect} and #{base_directory.inspect}"
+ end
+ while !dest_names.empty? &&
+ !base_names.empty? &&
+ same_paths?(dest_names.first, base_names.first)
+ dest_names.shift
+ base_names.shift
+ end
+ if base_names.include? '..'
+ raise ArgumentError, "base_directory has ..: #{base_directory.inspect}"
+ end
+ base_names.fill('..')
+ relpath_names = base_names + dest_names
+ if relpath_names.empty?
+ Pathname.new('.')
+ else
+ Pathname.new(File.join(*relpath_names))
+ end
+ end
+end
+
+class Pathname # * File *
+ #
+ # #each_line iterates over the line in the file. It yields a String object
+ # for each line.
+ #
+ # This method has existed since 1.8.1.
+ #
+ def each_line(...) # :yield: line
+ File.foreach(@path, ...)
+ end
+
+ # See <tt>File.read</tt>. Returns all data from the file, or the first +N+ bytes
+ # if specified.
+ def read(...) File.read(@path, ...) end
+
+ # See <tt>File.binread</tt>. Returns all the bytes from the file, or the first +N+
+ # if specified.
+ def binread(...) File.binread(@path, ...) end
+
+ # See <tt>File.readlines</tt>. Returns all the lines from the file.
+ def readlines(...) File.readlines(@path, ...) end
+
+ # See <tt>File.sysopen</tt>.
+ def sysopen(...) File.sysopen(@path, ...) end
+
+ # Writes +contents+ to the file. See <tt>File.write</tt>.
+ def write(...) File.write(@path, ...) end
+
+ # Writes +contents+ to the file, opening it in binary mode.
+ #
+ # See File.binwrite.
+ def binwrite(...) File.binwrite(@path, ...) end
+
+ # See <tt>File.atime</tt>. Returns last access time.
+ def atime() File.atime(@path) end
+
+ # Returns the birth time for the file.
+ # If the platform doesn't have birthtime, raises NotImplementedError.
+ #
+ # See File.birthtime.
+ def birthtime() File.birthtime(@path) end
+
+ # See <tt>File.ctime</tt>. Returns last (directory entry, not file) change time.
+ def ctime() File.ctime(@path) end
+
+ # See <tt>File.mtime</tt>. Returns last modification time.
+ def mtime() File.mtime(@path) end
+
+ # See <tt>File.chmod</tt>. Changes permissions.
+ def chmod(mode) File.chmod(mode, @path) end
+
+ # See <tt>File.lchmod</tt>.
+ def lchmod(mode) File.lchmod(mode, @path) end
+
+ # See <tt>File.chown</tt>. Change owner and group of file.
+ def chown(owner, group) File.chown(owner, group, @path) end
+
+ # See <tt>File.lchown</tt>.
+ def lchown(owner, group) File.lchown(owner, group, @path) end
+
+ # See <tt>File.fnmatch</tt>. Return +true+ if the receiver matches the given
+ # pattern.
+ def fnmatch(pattern, ...) File.fnmatch(pattern, @path, ...) end
+
+ # See <tt>File.fnmatch?</tt> (same as #fnmatch).
+ def fnmatch?(pattern, ...) File.fnmatch?(pattern, @path, ...) end
+
+ # See <tt>File.ftype</tt>. Returns "type" of file ("file", "directory",
+ # etc).
+ def ftype() File.ftype(@path) end
+
+ # See <tt>File.link</tt>. Creates a hard link.
+ def make_link(old) File.link(old, @path) end
+
+ # See <tt>File.open</tt>. Opens the file for reading or writing.
+ def open(...) # :yield: file
+ File.open(@path, ...)
+ end
+
+ # See <tt>File.readlink</tt>. Read symbolic link.
+ def readlink() self.class.new(File.readlink(@path)) end
+
+ # See <tt>File.rename</tt>. Rename the file.
+ def rename(to) File.rename(@path, to) end
+
+ # See <tt>File.stat</tt>. Returns a <tt>File::Stat</tt> object.
+ def stat() File.stat(@path) end
+
+ # See <tt>File.lstat</tt>.
+ def lstat() File.lstat(@path) end
+
+ # See <tt>File.symlink</tt>. Creates a symbolic link.
+ def make_symlink(old) File.symlink(old, @path) end
+
+ # See <tt>File.truncate</tt>. Truncate the file to +length+ bytes.
+ def truncate(length) File.truncate(@path, length) end
+
+ # See <tt>File.utime</tt>. Update the access and modification times.
+ def utime(atime, mtime) File.utime(atime, mtime, @path) end
+
+ # Update the access and modification times of the file.
+ #
+ # Same as Pathname#utime, but does not follow symbolic links.
+ #
+ # See File.lutime.
+ def lutime(atime, mtime) File.lutime(atime, mtime, @path) end
+
+ # See <tt>File.basename</tt>. Returns the last component of the path.
+ def basename(...) self.class.new(File.basename(@path, ...)) end
+
+ # See <tt>File.dirname</tt>. Returns all but the last component of the path.
+ def dirname() self.class.new(File.dirname(@path)) end
+
+ # See <tt>File.extname</tt>. Returns the file's extension.
+ def extname() File.extname(@path) end
+
+ # See <tt>File.expand_path</tt>.
+ def expand_path(...) self.class.new(File.expand_path(@path, ...)) end
+
+ # See <tt>File.split</tt>. Returns the #dirname and the #basename in an
+ # Array.
+ def split()
+ array = File.split(@path)
+ raise TypeError, 'wrong argument type nil (expected Array)' unless Array === array
+ array.map {|f| self.class.new(f) }
+ end
+
+ # Returns the real (absolute) pathname for +self+ in the actual filesystem.
+ #
+ # Does not contain symlinks or useless dots, +..+ and +.+.
+ #
+ # All components of the pathname must exist when this method is called.
+ def realpath(...) self.class.new(File.realpath(@path, ...)) end
+
+ # Returns the real (absolute) pathname of +self+ in the actual filesystem.
+ #
+ # Does not contain symlinks or useless dots, +..+ and +.+.
+ #
+ # The last component of the real pathname can be nonexistent.
+ def realdirpath(...) self.class.new(File.realdirpath(@path, ...)) end
+end
+
+
+class Pathname # * FileTest *
+
+ # See <tt>FileTest.blockdev?</tt>.
+ def blockdev?() FileTest.blockdev?(@path) end
+
+ # See <tt>FileTest.chardev?</tt>.
+ def chardev?() FileTest.chardev?(@path) end
+
+ # Tests the file is empty.
+ #
+ # See Dir#empty? and FileTest.empty?.
+ def empty?
+ if FileTest.directory?(@path)
+ Dir.empty?(@path)
+ else
+ File.empty?(@path)
+ end
+ end
+
+ # See <tt>FileTest.executable?</tt>.
+ def executable?() FileTest.executable?(@path) end
+
+ # See <tt>FileTest.executable_real?</tt>.
+ def executable_real?() FileTest.executable_real?(@path) end
+
+ # See <tt>FileTest.exist?</tt>.
+ def exist?() FileTest.exist?(@path) end
+
+ # See <tt>FileTest.grpowned?</tt>.
+ def grpowned?() FileTest.grpowned?(@path) end
+
+ # See <tt>FileTest.directory?</tt>.
+ def directory?() FileTest.directory?(@path) end
+
+ # See <tt>FileTest.file?</tt>.
+ def file?() FileTest.file?(@path) end
+
+ # See <tt>FileTest.pipe?</tt>.
+ def pipe?() FileTest.pipe?(@path) end
+
+ # See <tt>FileTest.socket?</tt>.
+ def socket?() FileTest.socket?(@path) end
+
+ # See <tt>FileTest.owned?</tt>.
+ def owned?() FileTest.owned?(@path) end
+
+ # See <tt>FileTest.readable?</tt>.
+ def readable?() FileTest.readable?(@path) end
+
+ # See <tt>FileTest.world_readable?</tt>.
+ def world_readable?() File.world_readable?(@path) end
+
+ # See <tt>FileTest.readable_real?</tt>.
+ def readable_real?() FileTest.readable_real?(@path) end
+
+ # See <tt>FileTest.setuid?</tt>.
+ def setuid?() FileTest.setuid?(@path) end
+
+ # See <tt>FileTest.setgid?</tt>.
+ def setgid?() FileTest.setgid?(@path) end
+
+ # See <tt>FileTest.size</tt>.
+ def size() FileTest.size(@path) end
+
+ # See <tt>FileTest.size?</tt>.
+ def size?() FileTest.size?(@path) end
+
+ # See <tt>FileTest.sticky?</tt>.
+ def sticky?() FileTest.sticky?(@path) end
+
+ # See <tt>FileTest.symlink?</tt>.
+ def symlink?() FileTest.symlink?(@path) end
+
+ # See <tt>FileTest.writable?</tt>.
+ def writable?() FileTest.writable?(@path) end
+
+ # See <tt>FileTest.world_writable?</tt>.
+ def world_writable?() File.world_writable?(@path) end
+
+ # See <tt>FileTest.writable_real?</tt>.
+ def writable_real?() FileTest.writable_real?(@path) end
+
+ # See <tt>FileTest.zero?</tt>.
+ def zero?() FileTest.zero?(@path) end
+end
+
+
+class Pathname # * Dir *
+ # See <tt>Dir.glob</tt>. Returns or yields Pathname objects.
+ def Pathname.glob(*args, **kwargs) # :yield: pathname
+ if block_given?
+ Dir.glob(*args, **kwargs) {|f| yield self.new(f) }
+ else
+ Dir.glob(*args, **kwargs).map {|f| self.new(f) }
+ end
+ end
+
+ # Returns or yields Pathname objects.
+ #
+ # Pathname("ruby-2.4.2").glob("R*.md")
+ # #=> [#<Pathname:ruby-2.4.2/README.md>, #<Pathname:ruby-2.4.2/README.ja.md>]
+ #
+ # See Dir.glob.
+ # This method uses the +base+ keyword argument of Dir.glob.
+ def glob(*args, **kwargs) # :yield: pathname
+ if block_given?
+ Dir.glob(*args, **kwargs, base: @path) {|f| yield self + f }
+ else
+ Dir.glob(*args, **kwargs, base: @path).map {|f| self + f }
+ end
+ end
+
+ # See <tt>Dir.getwd</tt>. Returns the current working directory as a Pathname.
+ def Pathname.getwd() self.new(Dir.getwd) end
+ class << self
+ alias pwd getwd
+ end
+
+ # Return the entries (files and subdirectories) in the directory, each as a
+ # Pathname object.
+ def entries() Dir.entries(@path).map {|f| self.class.new(f) } end
+
+ # Iterates over the entries (files and subdirectories) in the directory. It
+ # yields a Pathname object for each entry.
+ #
+ # This method has existed since 1.8.1.
+ def each_entry(&block) # :yield: pathname
+ return to_enum(__method__) unless block_given?
+ Dir.foreach(@path) {|f| yield self.class.new(f) }
+ end
+
+ # See <tt>Dir.mkdir</tt>. Create the referenced directory.
+ def mkdir(...) Dir.mkdir(@path, ...) end
+
+ # See <tt>Dir.rmdir</tt>. Remove the referenced directory.
+ def rmdir() Dir.rmdir(@path) end
+
+ # See <tt>Dir.open</tt>.
+ def opendir(&block) # :yield: dir
+ Dir.open(@path, &block)
+ end
+end
+
+class Pathname # * mixed *
+ # Removes a file or directory, using <tt>File.unlink</tt> or
+ # <tt>Dir.unlink</tt> as necessary.
+ def unlink()
+ Dir.unlink @path
+ rescue Errno::ENOTDIR
+ File.unlink @path
+ end
+ alias delete unlink
+end
+
+class Pathname
+ undef =~ if Kernel.method_defined?(:=~)
+end
+
+module Kernel
+ # Creates a Pathname object.
+ def Pathname(path) # :doc:
+ return path if Pathname === path
+ Pathname.new(path)
+ end
+ module_function :Pathname
+end
diff --git a/prelude.rb b/prelude.rb
index ee78b44cc5..b6c610dd58 100644
--- a/prelude.rb
+++ b/prelude.rb
@@ -1,8 +1,18 @@
class Binding
# :nodoc:
- def irb
- require 'irb'
- irb
+ def irb(...)
+ suppress = Thread.current[:__bundled_gems_warning_suppression]
+ Thread.current[:__bundled_gems_warning_suppression] = ['reline', 'rdoc']
+
+ begin
+ require 'irb'
+ rescue LoadError, Gem::LoadError
+ Gem::BUNDLED_GEMS.force_activate 'irb'
+ require 'irb'
+ end
+ irb(...)
+ ensure
+ Thread.current[:__bundled_gems_warning_suppression] = suppress
end
# suppress redefinition warning
@@ -10,22 +20,22 @@ class Binding
end
module Kernel
+ # :stopdoc:
def pp(*objs)
require 'pp'
pp(*objs)
end
# suppress redefinition warning
- alias pp pp # :nodoc:
+ alias pp pp
private :pp
+ # :startdoc:
end
-autoload :Set, 'set'
-
module Enumerable
# Makes a set from the enumerable object with given arguments.
- def to_set(klass = Set, *args, &block)
- klass.new(self, *args, &block)
- end unless instance_methods.include?(:to_set) # RJIT could already load this from builtin prelude
+ def to_set(&block)
+ Set.new(self, &block)
+ end
end
diff --git a/prism/config.yml b/prism/config.yml
index 1fe2e36e67..4e5b077a35 100644
--- a/prism/config.yml
+++ b/prism/config.yml
@@ -15,7 +15,6 @@ errors:
- ARGUMENT_FORMAL_GLOBAL
- ARGUMENT_FORMAL_IVAR
- ARGUMENT_FORWARDING_UNBOUND
- - ARGUMENT_IN
- ARGUMENT_NO_FORWARDING_AMPERSAND
- ARGUMENT_NO_FORWARDING_ELLIPSES
- ARGUMENT_NO_FORWARDING_STAR
@@ -61,6 +60,7 @@ errors:
- CONDITIONAL_WHILE_PREDICATE
- CONSTANT_PATH_COLON_COLON_CONSTANT
- DEF_ENDLESS
+ - DEF_ENDLESS_PARAMETERS
- DEF_ENDLESS_SETTER
- DEF_NAME
- DEF_PARAMS_TERM
@@ -81,8 +81,10 @@ errors:
- ESCAPE_INVALID_META_REPEAT
- ESCAPE_INVALID_UNICODE
- ESCAPE_INVALID_UNICODE_CM_FLAGS
+ - ESCAPE_INVALID_UNICODE_LIST
- ESCAPE_INVALID_UNICODE_LITERAL
- ESCAPE_INVALID_UNICODE_LONG
+ - ESCAPE_INVALID_UNICODE_SHORT
- ESCAPE_INVALID_UNICODE_TERM
- EXPECT_ARGUMENT
- EXPECT_EOL_AFTER_STATEMENT
@@ -97,14 +99,18 @@ errors:
- EXPECT_EXPRESSION_AFTER_SPLAT
- EXPECT_EXPRESSION_AFTER_SPLAT_HASH
- EXPECT_EXPRESSION_AFTER_STAR
+ - EXPECT_FOR_DELIMITER
- EXPECT_IDENT_REQ_PARAMETER
- EXPECT_IN_DELIMITER
+ - EXPECT_LPAREN_AFTER_NOT_LPAREN
+ - EXPECT_LPAREN_AFTER_NOT_OTHER
- EXPECT_LPAREN_REQ_PARAMETER
- EXPECT_MESSAGE
- EXPECT_RBRACKET
- EXPECT_RPAREN
- EXPECT_RPAREN_AFTER_MULTI
- EXPECT_RPAREN_REQ_PARAMETER
+ - EXPECT_SINGLETON_CLASS_DELIMITER
- EXPECT_STRING_CONTENT
- EXPECT_WHEN_DELIMITER
- EXPRESSION_BARE_HASH
@@ -138,6 +144,7 @@ errors:
- INSTANCE_VARIABLE_BARE
- INVALID_BLOCK_EXIT
- INVALID_CHARACTER
+ - INVALID_COMMA
- INVALID_ENCODING_MAGIC_COMMENT
- INVALID_ESCAPE_CHARACTER
- INVALID_FLOAT_EXPONENT
@@ -183,7 +190,9 @@ errors:
- MODULE_TERM
- MULTI_ASSIGN_MULTI_SPLATS
- MULTI_ASSIGN_UNEXPECTED_REST
+ - NESTING_TOO_DEEP
- NO_LOCAL_VARIABLE
+ - NON_ASSOCIATIVE_OPERATOR
- NOT_EXPRESSION
- NUMBER_LITERAL_UNDERSCORE
- NUMBERED_PARAMETER_INNER_BLOCK
@@ -206,9 +215,11 @@ errors:
- PARAMETER_SPLAT_MULTI
- PARAMETER_STAR
- PARAMETER_UNEXPECTED_FWD
- - PARAMETER_WILD_LOOSE_COMMA
- PARAMETER_UNEXPECTED_NO_KW
+ - PARAMETER_WILD_LOOSE_COMMA
+ - PATTERN_ARRAY_MULTIPLE_RESTS
- PATTERN_CAPTURE_DUPLICATE
+ - PATTERN_CAPTURE_IN_ALTERNATIVE
- PATTERN_EXPRESSION_AFTER_BRACKET
- PATTERN_EXPRESSION_AFTER_COMMA
- PATTERN_EXPRESSION_AFTER_HROCKET
@@ -219,6 +230,7 @@ errors:
- PATTERN_EXPRESSION_AFTER_PIPE
- PATTERN_EXPRESSION_AFTER_RANGE
- PATTERN_EXPRESSION_AFTER_REST
+ - PATTERN_FIND_MISSING_INNER
- PATTERN_HASH_IMPLICIT
- PATTERN_HASH_KEY
- PATTERN_HASH_KEY_DUPLICATE
@@ -236,6 +248,7 @@ errors:
- REGEXP_INCOMPAT_CHAR_ENCODING
- REGEXP_INVALID_UNICODE_RANGE
- REGEXP_NON_ESCAPED_MBC
+ - REGEXP_PARSE_ERROR
- REGEXP_TERM
- REGEXP_UNKNOWN_OPTIONS
- REGEXP_UTF8_CHAR_NON_UTF8_REGEXP
@@ -260,11 +273,16 @@ errors:
- TERNARY_COLON
- TERNARY_EXPRESSION_FALSE
- TERNARY_EXPRESSION_TRUE
+ - UNARY_DISALLOWED
- UNARY_RECEIVER
- UNDEF_ARGUMENT
- UNEXPECTED_BLOCK_ARGUMENT
- UNEXPECTED_INDEX_BLOCK
- UNEXPECTED_INDEX_KEYWORDS
+ - UNEXPECTED_LABEL
+ - UNEXPECTED_MULTI_WRITE
+ - UNEXPECTED_PARAMETER_DEFAULT_VALUE
+ - UNEXPECTED_RANGE_OPERATOR
- UNEXPECTED_SAFE_NAVIGATION
- UNEXPECTED_TOKEN_CLOSE_CONTEXT
- UNEXPECTED_TOKEN_IGNORE
@@ -292,10 +310,11 @@ warnings:
- DUPLICATED_WHEN_CLAUSE
- FLOAT_OUT_OF_RANGE
- IGNORED_FROZEN_STRING_LITERAL
+ - INDENTATION_MISMATCH
- INTEGER_IN_FLIP_FLOP
- INVALID_CHARACTER
+ - INVALID_MAGIC_COMMENT_VALUE
- INVALID_NUMBERED_REFERENCE
- - INVALID_SHAREABLE_CONSTANT_VALUE
- KEYWORD_EOL
- LITERAL_IN_CONDITION_DEFAULT
- LITERAL_IN_CONDITION_VERBOSE
@@ -306,13 +325,44 @@ warnings:
- UNUSED_LOCAL_VARIABLE
- VOID_STATEMENT
tokens:
+ # The order of the tokens at the beginning is important, because we use them
+ # for a lookup table.
- name: EOF
value: 1
comment: final token in the file
- - name: MISSING
- comment: "a token that was expected but not found"
- - name: NOT_PROVIDED
- comment: "a token that was not present but it is okay"
+ - name: BRACE_RIGHT
+ comment: "}"
+ - name: COMMA
+ comment: ","
+ - name: EMBEXPR_END
+ comment: "}"
+ - name: KEYWORD_DO
+ comment: "do"
+ - name: KEYWORD_ELSE
+ comment: "else"
+ - name: KEYWORD_ELSIF
+ comment: "elsif"
+ - name: KEYWORD_END
+ comment: "end"
+ - name: KEYWORD_ENSURE
+ comment: "ensure"
+ - name: KEYWORD_IN
+ comment: "in"
+ - name: KEYWORD_RESCUE
+ comment: "rescue"
+ - name: KEYWORD_THEN
+ comment: "then"
+ - name: KEYWORD_WHEN
+ comment: "when"
+ - name: NEWLINE
+ comment: "a newline character outside of other tokens"
+ - name: PARENTHESIS_RIGHT
+ comment: ")"
+ - name: PIPE
+ comment: "|"
+ - name: SEMICOLON
+ comment: ";"
+ # Tokens from here on are not used for lookup, and can be in any order.
- name: AMPERSAND
comment: "&"
- name: AMPERSAND_AMPERSAND
@@ -335,8 +385,6 @@ tokens:
comment: "!~"
- name: BRACE_LEFT
comment: "{"
- - name: BRACE_RIGHT
- comment: "}"
- name: BRACKET_LEFT
comment: "["
- name: BRACKET_LEFT_ARRAY
@@ -359,8 +407,6 @@ tokens:
comment: ":"
- name: COLON_COLON
comment: "::"
- - name: COMMA
- comment: ","
- name: COMMENT
comment: "a comment"
- name: CONSTANT
@@ -379,8 +425,6 @@ tokens:
comment: "a line inside of embedded documentation"
- name: EMBEXPR_BEGIN
comment: "#{"
- - name: EMBEXPR_END
- comment: "}"
- name: EMBVAR
comment: "#"
- name: EQUAL
@@ -447,20 +491,10 @@ tokens:
comment: "def"
- name: KEYWORD_DEFINED
comment: "defined?"
- - name: KEYWORD_DO
- comment: "do"
- name: KEYWORD_DO_LOOP
comment: "do keyword for a predicate in a while, until, or for loop"
- - name: KEYWORD_ELSE
- comment: "else"
- - name: KEYWORD_ELSIF
- comment: "elsif"
- - name: KEYWORD_END
- comment: "end"
- name: KEYWORD_END_UPCASE
comment: "END"
- - name: KEYWORD_ENSURE
- comment: "ensure"
- name: KEYWORD_FALSE
comment: "false"
- name: KEYWORD_FOR
@@ -469,8 +503,6 @@ tokens:
comment: "if"
- name: KEYWORD_IF_MODIFIER
comment: "if in the modifier form"
- - name: KEYWORD_IN
- comment: "in"
- name: KEYWORD_MODULE
comment: "module"
- name: KEYWORD_NEXT
@@ -483,8 +515,6 @@ tokens:
comment: "or"
- name: KEYWORD_REDO
comment: "redo"
- - name: KEYWORD_RESCUE
- comment: "rescue"
- name: KEYWORD_RESCUE_MODIFIER
comment: "rescue in the modifier form"
- name: KEYWORD_RETRY
@@ -495,8 +525,6 @@ tokens:
comment: "self"
- name: KEYWORD_SUPER
comment: "super"
- - name: KEYWORD_THEN
- comment: "then"
- name: KEYWORD_TRUE
comment: "true"
- name: KEYWORD_UNDEF
@@ -509,8 +537,6 @@ tokens:
comment: "until"
- name: KEYWORD_UNTIL_MODIFIER
comment: "until in the modifier form"
- - name: KEYWORD_WHEN
- comment: "when"
- name: KEYWORD_WHILE
comment: "while"
- name: KEYWORD_WHILE_MODIFIER
@@ -547,16 +573,12 @@ tokens:
comment: "-="
- name: MINUS_GREATER
comment: "->"
- - name: NEWLINE
- comment: "a newline character outside of other tokens"
- name: NUMBERED_REFERENCE
comment: "a numbered reference to a capture group in the previous regular expression match"
- name: PARENTHESIS_LEFT
comment: "("
- name: PARENTHESIS_LEFT_PARENTHESES
comment: "( for a parentheses node"
- - name: PARENTHESIS_RIGHT
- comment: ")"
- name: PERCENT
comment: "%"
- name: PERCENT_EQUAL
@@ -571,8 +593,6 @@ tokens:
comment: "%I"
- name: PERCENT_UPPER_W
comment: "%W"
- - name: PIPE
- comment: "|"
- name: PIPE_EQUAL
comment: "|="
- name: PIPE_PIPE
@@ -589,8 +609,6 @@ tokens:
comment: "the beginning of a regular expression"
- name: REGEXP_END
comment: "the end of a regular expression"
- - name: SEMICOLON
- comment: ";"
- name: SLASH
comment: "/"
- name: SLASH_EQUAL
@@ -635,13 +653,23 @@ tokens:
comment: "a separator between words in a list"
- name: __END__
comment: "marker for the point in the file at which the parser should stop"
+ - name: MISSING
+ comment: "a token that was expected but not found"
+ - name: NOT_PROVIDED
+ comment: "a token that was not present but it is okay"
flags:
- name: ArgumentsNodeFlags
values:
+ - name: CONTAINS_FORWARDING
+ comment: "if the arguments contain forwarding"
- name: CONTAINS_KEYWORDS
- comment: "if arguments contain keywords"
+ comment: "if the arguments contain keywords"
- name: CONTAINS_KEYWORD_SPLAT
- comment: "if arguments contain keyword splat"
+ comment: "if the arguments contain a keyword splat"
+ - name: CONTAINS_SPLAT
+ comment: "if the arguments contain a splat"
+ - name: CONTAINS_MULTIPLE_SPLATS
+ comment: "if the arguments contain multiple splats"
comment: Flags for arguments nodes.
- name: ArrayNodeFlags
values:
@@ -699,6 +727,11 @@ flags:
- name: REPEATED_PARAMETER
comment: "a parameter name that has been repeated in the method signature"
comment: Flags for parameter nodes.
+ - name: ParenthesesNodeFlags
+ values:
+ - name: MULTIPLE_STATEMENTS
+ comment: "parentheses that contain multiple potentially void statements"
+ comment: Flags for parentheses nodes.
- name: RangeFlags
values:
- name: EXCLUDE_END
@@ -729,11 +762,6 @@ flags:
- name: FORCED_US_ASCII_ENCODING
comment: "internal bytes forced the encoding to US-ASCII"
comment: Flags for regular expression and match last line nodes.
- - name: ReturnNodeFlags
- values:
- - name: REDUNDANT
- comment: "a return statement that is redundant because it is the last statement in a method"
- comment: Flags for return nodes.
- name: ShareableConstantNodeFlags
values:
- name: LITERAL
@@ -768,15 +796,25 @@ nodes:
fields:
- name: new_name
type: node
+ kind:
+ - GlobalVariableReadNode
+ - BackReferenceReadNode
+ - NumberedReferenceReadNode
comment: |
- Represents the new name of the global variable that can be used after aliasing. This can be either a global variable, a back reference, or a numbered reference.
+ Represents the new name of the global variable that can be used after aliasing.
alias $foo $bar
^^^^
- name: old_name
type: node
+ kind:
+ - GlobalVariableReadNode
+ - BackReferenceReadNode
+ - NumberedReferenceReadNode
+ - on error: SymbolNode # alias $a b
+ - on error: MissingNode # alias $a 42
comment: |
- Represents the old name of the global variable that could be used before aliasing. This can be either a global variable, a back reference, or a numbered reference.
+ Represents the old name of the global variable that can be used before aliasing.
alias $foo $bar
^^^^
@@ -796,10 +834,45 @@ nodes:
fields:
- name: new_name
type: node
+ kind:
+ - SymbolNode
+ - InterpolatedSymbolNode
+ comment: |
+ Represents the new name of the method that will be aliased.
+
+ alias foo bar
+ ^^^
+
+ alias :foo :bar
+ ^^^^
+
+ alias :"#{foo}" :"#{bar}"
+ ^^^^^^^^^
- name: old_name
type: node
+ kind:
+ - SymbolNode
+ - InterpolatedSymbolNode
+ - on error: GlobalVariableReadNode # alias a $b
+ - on error: MissingNode # alias a 42
+ comment: |
+ Represents the old name of the method that will be aliased.
+
+ alias foo bar
+ ^^^
+
+ alias :foo :bar
+ ^^^^
+
+ alias :"#{foo}" :"#{bar}"
+ ^^^^^^^^^
- name: keyword_loc
type: location
+ comment: |
+ Represents the location of the `alias` keyword.
+
+ alias foo bar
+ ^^^^^
comment: |
Represents the use of the `alias` keyword to alias a method.
@@ -809,10 +882,27 @@ nodes:
fields:
- name: left
type: node
+ kind: pattern expression
+ comment: |
+ Represents the left side of the expression.
+
+ foo => bar | baz
+ ^^^
- name: right
type: node
+ kind: pattern expression
+ comment: |
+ Represents the right side of the expression.
+
+ foo => bar | baz
+ ^^^
- name: operator_loc
type: location
+ comment: |
+ Represents the alternation operator location.
+
+ foo => bar | baz
+ ^
comment: |
Represents an alternation pattern in pattern matching.
@@ -822,6 +912,7 @@ nodes:
fields:
- name: left
type: node
+ kind: non-void expression
comment: |
Represents the left side of the expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
@@ -832,8 +923,9 @@ nodes:
^
- name: right
type: node
+ kind: Node
comment: |
- Represents the right side of the expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+ Represents the right side of the expression.
left && right
^^^^^
@@ -853,24 +945,27 @@ nodes:
left and right
^^^^^^^^^^^^^^
- name: ArgumentsNode
+ flags: ArgumentsNodeFlags
fields:
- - name: flags
- type: flags
- kind: ArgumentsNodeFlags
- name: arguments
type: node[]
+ kind: non-void expression
+ comment: |
+ The list of arguments, if present. These can be any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+
+ foo(bar, baz)
+ ^^^^^^^^
comment: |
Represents a set of arguments to a method or a keyword.
return foo, bar, baz
^^^^^^^^^^^^^
- name: ArrayNode
+ flags: ArrayNodeFlags
fields:
- - name: flags
- type: flags
- kind: ArrayNodeFlags
- name: elements
type: node[]
+ kind: non-void expression
comment: Represent the list of zero or more [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression) within the array.
- name: opening_loc
type: location?
@@ -899,16 +994,58 @@ nodes:
fields:
- name: constant
type: node?
+ kind:
+ - ConstantPathNode
+ - ConstantReadNode
+ comment: |
+ Represents the optional constant preceding the Array
+
+ foo in Bar[]
+ ^^^
+
+ foo in Bar[1, 2, 3]
+ ^^^
+
+ foo in Bar::Baz[1, 2, 3]
+ ^^^^^^^^
- name: requireds
type: node[]
+ kind: pattern expression
+ comment: |
+ Represents the required elements of the array pattern.
+
+ foo in [1, 2]
+ ^ ^
- name: rest
type: node?
+ kind: pattern expression
+ comment: |
+ Represents the rest element of the array pattern.
+
+ foo in *bar
+ ^^^^
- name: posts
type: node[]
+ kind: pattern expression
+ comment: |
+ Represents the elements after the rest element of the array pattern.
+
+ foo in *bar, baz
+ ^^^
- name: opening_loc
type: location?
+ comment: |
+ Represents the opening location of the array pattern.
+
+ foo in [1, 2]
+ ^
- name: closing_loc
type: location?
+ comment: |
+ Represents the closing location of the array pattern.
+
+ foo in [1, 2]
+ ^
comment: |
Represents an array pattern in pattern matching.
@@ -918,8 +1055,8 @@ nodes:
foo in [1, 2]
^^^^^^^^^^^^^
- foo in *1
- ^^^^^^^^^
+ foo in *bar
+ ^^^^^^^^^^^
foo in Bar[]
^^^^^^^^^^^^
@@ -930,6 +1067,7 @@ nodes:
fields:
- name: key
type: node
+ kind: non-void expression
comment: |
The key of the association. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
@@ -943,6 +1081,7 @@ nodes:
^^^^^^^^^^
- name: value
type: node
+ kind: non-void expression
comment: |
The value of the association, if present. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
@@ -967,6 +1106,7 @@ nodes:
fields:
- name: value
type: node?
+ kind: non-void expression
comment: |
The value to be splatted, if present. Will be missing when keyword rest argument forwarding is used.
@@ -1003,20 +1143,50 @@ nodes:
fields:
- name: begin_keyword_loc
type: location?
+ comment: |
+ Represents the location of the `begin` keyword.
+
+ begin x end
+ ^^^^^
- name: statements
type: node?
kind: StatementsNode
+ comment: |
+ Represents the statements within the begin block.
+
+ begin x end
+ ^
- name: rescue_clause
type: node?
kind: RescueNode
+ comment: |
+ Represents the rescue clause within the begin block.
+
+ begin x; rescue y; end
+ ^^^^^^^^
- name: else_clause
type: node?
kind: ElseNode
+ comment: |
+ Represents the else clause within the begin block.
+
+ begin x; rescue y; else z; end
+ ^^^^^^
- name: ensure_clause
type: node?
kind: EnsureNode
+ comment: |
+ Represents the ensure clause within the begin block.
+
+ begin x; ensure y; end
+ ^^^^^^^^
- name: end_keyword_loc
type: location?
+ comment: |
+ Represents the location of the `end` keyword.
+
+ begin x end
+ ^^^
newline: false
comment: |
Represents a begin statement.
@@ -1029,20 +1199,34 @@ nodes:
fields:
- name: expression
type: node?
+ kind: non-void expression
+ comment: |
+ The expression that is being passed as a block argument. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+
+ foo(&args)
+ ^^^^^
- name: operator_loc
type: location
+ comment: |
+ Represents the location of the `&` operator.
+
+ foo(&args)
+ ^
comment: |
- Represents block method arguments.
+ Represents a block argument using `&`.
bar(&args)
^^^^^^^^^^
- name: BlockLocalVariableNode
+ flags: ParameterFlags
fields:
- - name: flags
- type: flags
- kind: ParameterFlags
- name: name
type: constant
+ comment: |
+ The name of the block local variable.
+
+ a { |; b| } # name `:b`
+ ^
comment: |
Represents a block local variable.
@@ -1052,32 +1236,83 @@ nodes:
fields:
- name: locals
type: constant[]
+ comment: |
+ The local variables declared in the block.
+
+ [1, 2, 3].each { |i| puts x } # locals: [:i]
+ ^
- name: parameters
type: node?
+ kind:
+ - BlockParametersNode
+ - NumberedParametersNode
+ - ItParametersNode
+ comment: |
+ The parameters of the block.
+
+ [1, 2, 3].each { |i| puts x }
+ ^^^
+ [1, 2, 3].each { puts _1 }
+ ^^^^^^^^^^^
+ [1, 2, 3].each { puts it }
+ ^^^^^^^^^^^
- name: body
type: node?
+ kind:
+ - StatementsNode
+ - BeginNode
+ comment: |
+ The body of the block.
+
+ [1, 2, 3].each { |i| puts x }
+ ^^^^^^
- name: opening_loc
type: location
+ comment: |
+ Represents the location of the opening `{` or `do`.
+
+ [1, 2, 3].each { |i| puts x }
+ ^
- name: closing_loc
type: location
+ comment: |
+ Represents the location of the closing `}` or `end`.
+
+ [1, 2, 3].each { |i| puts x }
+ ^
comment: |
Represents a block of ruby code.
[1, 2, 3].each { |i| puts x }
^^^^^^^^^^^^^^
- name: BlockParameterNode
+ flags: ParameterFlags
fields:
- - name: flags
- type: flags
- kind: ParameterFlags
- name: name
type: constant?
+ comment: |
+ The name of the block parameter.
+
+ def a(&b) # name `:b`
+ ^
+ end
- name: name_loc
type: location?
+ comment: |
+ Represents the location of the block parameter name.
+
+ def a(&b)
+ ^
- name: operator_loc
type: location
+ comment: |
+ Represents the location of the `&` operator.
+
+ def a(&b)
+ ^
+ end
comment: |
- Represents a block parameter to a method, block, or lambda definition.
+ Represents a block parameter of a method, block, or lambda definition.
def a(&b)
^^
@@ -1087,13 +1322,49 @@ nodes:
- name: parameters
type: node?
kind: ParametersNode
+ comment: |
+ Represents the parameters of the block.
+
+ -> (a, b = 1; local) { }
+ ^^^^^^^^
+
+ foo do |a, b = 1; local|
+ ^^^^^^^^
+ end
- name: locals
type: node[]
kind: BlockLocalVariableNode
+ comment: |
+ Represents the local variables of the block.
+
+ -> (a, b = 1; local) { }
+ ^^^^^
+
+ foo do |a, b = 1; local|
+ ^^^^^
+ end
- name: opening_loc
type: location?
+ comment: |
+ Represents the opening location of the block parameters.
+
+ -> (a, b = 1; local) { }
+ ^
+
+ foo do |a, b = 1; local|
+ ^
+ end
- name: closing_loc
type: location?
+ comment: |
+ Represents the closing location of the block parameters.
+
+ -> (a, b = 1; local) { }
+ ^
+
+ foo do |a, b = 1; local|
+ ^
+ end
comment: |
Represents a block's parameters declaration.
@@ -1126,36 +1397,70 @@ nodes:
break foo
^^^^^^^^^
- name: CallAndWriteNode
+ flags: CallNodeFlags
fields:
- - name: flags
- type: flags
- kind: CallNodeFlags
- name: receiver
type: node?
+ kind: non-void expression
+ comment: |
+ The object that the method is being called on. This can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+
+ foo.bar &&= value
+ ^^^
- name: call_operator_loc
type: location?
+ comment: |
+ Represents the location of the call operator.
+
+ foo.bar &&= value
+ ^
- name: message_loc
type: location?
+ comment: |
+ Represents the location of the message.
+
+ foo.bar &&= value
+ ^^^
- name: read_name
type: constant
+ comment: |
+ Represents the name of the method being called.
+
+ foo.bar &&= value # read_name `:bar`
+ ^^^
- name: write_name
type: constant
+ comment: |
+ Represents the name of the method being written to.
+
+ foo.bar &&= value # write_name `:bar=`
+ ^^^
- name: operator_loc
type: location
+ comment: |
+ Represents the location of the operator.
+
+ foo.bar &&= value
+ ^^^
- name: value
type: node
+ kind: non-void expression
+ comment: |
+ Represents the value being assigned.
+
+ foo.bar &&= value
+ ^^^^^
comment: |
Represents the use of the `&&=` operator on a call.
foo.bar &&= value
^^^^^^^^^^^^^^^^^
- name: CallNode
+ flags: CallNodeFlags
fields:
- - name: flags
- type: flags
- kind: CallNodeFlags
- name: receiver
type: node?
+ kind: non-void expression
comment: |
The object that the method is being called on. This can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
@@ -1169,19 +1474,69 @@ nodes:
^^^
- name: call_operator_loc
type: location?
+ comment: |
+ Represents the location of the call operator.
+
+ foo.bar
+ ^
+
+ foo&.bar
+ ^^
- name: name
type: constant
+ comment: |
+ Represents the name of the method being called.
+
+ foo.bar # name `:foo`
+ ^^^
- name: message_loc
type: location?
+ comment: |
+ Represents the location of the message.
+
+ foo.bar
+ ^^^
- name: opening_loc
type: location?
+ comment: |
+ Represents the location of the left parenthesis.
+ foo(bar)
+ ^
- name: arguments
type: node?
kind: ArgumentsNode
+ comment: |
+ Represents the arguments to the method call. These can be any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+
+ foo(bar)
+ ^^^
- name: closing_loc
type: location?
+ comment: |
+ Represents the location of the right parenthesis.
+
+ foo(bar)
+ ^
+ - name: equal_loc
+ type: location?
+ comment: |
+ Represents the location of the equal sign, in the case that this is an attribute write.
+
+ foo.bar = value
+ ^
+
+ foo[bar] = value
+ ^
- name: block
type: node?
+ kind:
+ - BlockNode
+ - BlockArgumentNode
+ comment: |
+ Represents the block that is being passed to the method.
+
+ foo { |a| a }
+ ^^^^^^^^^
comment: |
Represents a method call, in all of the various forms that can take.
@@ -1203,68 +1558,162 @@ nodes:
foo&.bar
^^^^^^^^
- name: CallOperatorWriteNode
+ flags: CallNodeFlags
fields:
- - name: flags
- type: flags
- kind: CallNodeFlags
- name: receiver
type: node?
+ kind: non-void expression
+ comment: |
+ The object that the method is being called on. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+
+ foo.bar += value
+ ^^^
- name: call_operator_loc
type: location?
+ comment: |
+ Represents the location of the call operator.
+
+ foo.bar += value
+ ^
- name: message_loc
type: location?
+ comment: |
+ Represents the location of the message.
+
+ foo.bar += value
+ ^^^
- name: read_name
type: constant
+ comment: |
+ Represents the name of the method being called.
+
+ foo.bar += value # read_name `:bar`
+ ^^^
- name: write_name
type: constant
+ comment: |
+ Represents the name of the method being written to.
+
+ foo.bar += value # write_name `:bar=`
+ ^^^
- name: binary_operator
type: constant
+ comment: |
+ Represents the binary operator being used.
+
+ foo.bar += value # binary_operator `:+`
+ ^
- name: binary_operator_loc
type: location
+ comment: |
+ Represents the location of the binary operator.
+
+ foo.bar += value
+ ^^
- name: value
type: node
+ kind: non-void expression
+ comment: |
+ Represents the value being assigned.
+
+ foo.bar += value
+ ^^^^^
comment: |
Represents the use of an assignment operator on a call.
foo.bar += baz
^^^^^^^^^^^^^^
- name: CallOrWriteNode
+ flags: CallNodeFlags
fields:
- - name: flags
- type: flags
- kind: CallNodeFlags
- name: receiver
type: node?
+ kind: non-void expression
+ comment: |
+ The object that the method is being called on. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+
+ foo.bar ||= value
+ ^^^
- name: call_operator_loc
type: location?
+ comment: |
+ Represents the location of the call operator.
+
+ foo.bar ||= value
+ ^
- name: message_loc
type: location?
+ comment: |
+ Represents the location of the message.
+
+ foo.bar ||= value
+ ^^^
- name: read_name
type: constant
+ comment: |
+ Represents the name of the method being called.
+
+ foo.bar ||= value # read_name `:bar`
+ ^^^
- name: write_name
type: constant
+ comment: |
+ Represents the name of the method being written to.
+
+ foo.bar ||= value # write_name `:bar=`
+ ^^^
- name: operator_loc
type: location
+ comment: |
+ Represents the location of the operator.
+
+ foo.bar ||= value
+ ^^^
- name: value
type: node
+ kind: non-void expression
+ comment: |
+ Represents the value being assigned.
+
+ foo.bar ||= value
+ ^^^^^
comment: |
Represents the use of the `||=` operator on a call.
foo.bar ||= value
^^^^^^^^^^^^^^^^^
- name: CallTargetNode
+ flags: CallNodeFlags
fields:
- - name: flags
- type: flags
- kind: CallNodeFlags
- name: receiver
type: node
+ kind: non-void expression
+ comment: |
+ The object that the method is being called on. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+
+ foo.bar = 1
+ ^^^
- name: call_operator_loc
type: location
+ comment: |
+ Represents the location of the call operator.
+
+ foo.bar = 1
+ ^
- name: name
type: constant
+ comment: |
+ Represents the name of the method being called.
+
+ foo.bar = 1 # name `:foo`
+ ^^^
- name: message_loc
type: location
+ comment: |
+ Represents the location of the message.
+
+ foo.bar = 1
+ ^^^
comment: |
Represents assigning to a method call.
@@ -1282,10 +1731,27 @@ nodes:
fields:
- name: value
type: node
+ kind: pattern expression
+ comment: |
+ Represents the value to capture.
+
+ foo => bar
+ ^^^
- name: target
type: node
+ kind: LocalVariableTargetNode
+ comment: |
+ Represents the target of the capture.
+
+ foo => bar
+ ^^^
- name: operator_loc
type: location
+ comment: |
+ Represents the location of the `=>` operator.
+
+ foo => bar
+ ^^
comment: |
Represents assigning to a local variable in pattern matching.
@@ -1295,15 +1761,42 @@ nodes:
fields:
- name: predicate
type: node?
+ kind: non-void expression
+ comment: |
+ Represents the predicate of the case match. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+
+ case true; in false; end
+ ^^^^
- name: conditions
type: node[]
- - name: consequent
+ kind: InNode
+ comment: |
+ Represents the conditions of the case match.
+
+ case true; in false; end
+ ^^^^^^^^
+ - name: else_clause
type: node?
kind: ElseNode
+ comment: |
+ Represents the else clause of the case match.
+
+ case true; in false; else; end
+ ^^^^
- name: case_keyword_loc
type: location
+ comment: |
+ Represents the location of the `case` keyword.
+
+ case true; in false; end
+ ^^^^
- name: end_keyword_loc
type: location
+ comment: |
+ Represents the location of the `end` keyword.
+
+ case true; in false; end
+ ^^^
comment: |
Represents the use of a case statement for pattern matching.
@@ -1315,15 +1808,42 @@ nodes:
fields:
- name: predicate
type: node?
+ kind: non-void expression
+ comment: |
+ Represents the predicate of the case statement. This can be either `nil` or any [non-void expressions](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+
+ case true; when false; end
+ ^^^^
- name: conditions
type: node[]
- - name: consequent
+ kind: WhenNode
+ comment: |
+ Represents the conditions of the case statement.
+
+ case true; when false; end
+ ^^^^^^^^^^
+ - name: else_clause
type: node?
kind: ElseNode
+ comment: |
+ Represents the else clause of the case statement.
+
+ case true; when false; else; end
+ ^^^^
- name: case_keyword_loc
type: location
+ comment: |
+ Represents the location of the `case` keyword.
+
+ case true; when false; end
+ ^^^^
- name: end_keyword_loc
type: location
+ comment: |
+ Represents the location of the `end` keyword.
+
+ case true; when false; end
+ ^^^
comment: |
Represents the use of a case statement.
@@ -1337,18 +1857,56 @@ nodes:
type: constant[]
- name: class_keyword_loc
type: location
+ comment: |
+ Represents the location of the `class` keyword.
+
+ class Foo end
+ ^^^^^
- name: constant_path
type: node
+ kind:
+ - ConstantReadNode
+ - ConstantPathNode
+ - on error: CallNode # class 0.X end
- name: inheritance_operator_loc
type: location?
+ comment: |
+ Represents the location of the `<` operator.
+
+ class Foo < Bar
+ ^
- name: superclass
type: node?
+ kind: non-void expression
+ comment: |
+ Represents the superclass of the class.
+
+ class Foo < Bar
+ ^^^
- name: body
type: node?
+ kind:
+ - StatementsNode
+ - BeginNode
+ comment: |
+ Represents the body of the class.
+
+ class Foo
+ foo
+ ^^^
- name: end_keyword_loc
type: location
+ comment: |
+ Represents the location of the `end` keyword.
+
+ class Foo end
+ ^^^
- name: name
type: constant
+ comment: |
+ The name of the class.
+
+ class Foo end # name `:Foo`
comment: |
Represents a class declaration involving the `class` keyword.
@@ -1358,12 +1916,33 @@ nodes:
fields:
- name: name
type: constant
+ comment: |
+ The name of the class variable, which is a `@@` followed by an [identifier](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#identifiers).
+
+ @@target &&= value # name `:@@target`
+ ^^^^^^^^
- name: name_loc
type: location
+ comment: |
+ Represents the location of the variable name.
+
+ @@target &&= value
+ ^^^^^^^^
- name: operator_loc
type: location
+ comment: |
+ Represents the location of the `&&=` operator.
+
+ @@target &&= value
+ ^^^
- name: value
type: node
+ kind: non-void expression
+ comment: |
+ Represents the value being assigned. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+
+ @@target &&= value
+ ^^^^^
comment: |
Represents the use of the `&&=` operator for assignment to a class variable.
@@ -1379,6 +1958,7 @@ nodes:
type: location
- name: value
type: node
+ kind: non-void expression
- name: binary_operator
type: constant
comment: |
@@ -1396,6 +1976,7 @@ nodes:
type: location
- name: value
type: node
+ kind: non-void expression
comment: |
Represents the use of the `||=` operator for assignment to a class variable.
@@ -1444,6 +2025,7 @@ nodes:
^^^^^
- name: value
type: node
+ kind: non-void expression
comment: |
The value to write to the class variable. This can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
@@ -1474,6 +2056,7 @@ nodes:
type: location
- name: value
type: node
+ kind: non-void expression
comment: |
Represents the use of the `&&=` operator for assignment to a constant.
@@ -1489,6 +2072,7 @@ nodes:
type: location
- name: value
type: node
+ kind: non-void expression
- name: binary_operator
type: constant
comment: |
@@ -1506,6 +2090,7 @@ nodes:
type: location
- name: value
type: node
+ kind: non-void expression
comment: |
Represents the use of the `||=` operator for assignment to a constant.
@@ -1520,6 +2105,7 @@ nodes:
type: location
- name: value
type: node
+ kind: non-void expression
comment: |
Represents the use of the `&&=` operator for assignment to a constant path.
@@ -1529,6 +2115,7 @@ nodes:
fields:
- name: parent
type: node?
+ kind: non-void expression
comment: |
The left-hand node of the path, if present. It can be `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression). It will be `nil` when the constant lookup is at the root of the module tree.
@@ -1577,6 +2164,7 @@ nodes:
type: location
- name: value
type: node
+ kind: non-void expression
- name: binary_operator
type: constant
comment: |
@@ -1593,6 +2181,7 @@ nodes:
type: location
- name: value
type: node
+ kind: non-void expression
comment: |
Represents the use of the `||=` operator for assignment to a constant path.
@@ -1602,6 +2191,7 @@ nodes:
fields:
- name: parent
type: node?
+ kind: non-void expression
- name: name
type: constant?
- name: delimiter_loc
@@ -1635,6 +2225,7 @@ nodes:
^
- name: value
type: node
+ kind: non-void expression
comment: |
The value to write to the constant path. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
@@ -1694,6 +2285,7 @@ nodes:
^^^
- name: value
type: node
+ kind: non-void expression
comment: |
The value to write to the constant. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
@@ -1722,11 +2314,15 @@ nodes:
type: location
- name: receiver
type: node?
+ kind: non-void expression
- name: parameters
type: node?
kind: ParametersNode
- name: body
type: node?
+ kind:
+ - StatementsNode
+ - BeginNode
- name: locals
type: constant[]
- name: def_keyword_loc
@@ -1753,6 +2349,7 @@ nodes:
type: location?
- name: value
type: node
+ kind: Node # More than non-void expression as defined?(return) is allowed, yet defined?(BEGIN{}) is SyntaxError
- name: rparen_loc
type: location?
- name: keyword_loc
@@ -1796,6 +2393,12 @@ nodes:
type: location
- name: variable
type: node
+ kind:
+ - InstanceVariableReadNode
+ - ClassVariableReadNode
+ - GlobalVariableReadNode
+ - BackReferenceReadNode
+ - NumberedReferenceReadNode
comment: |
Represents an interpolated variable.
@@ -1829,16 +2432,69 @@ nodes:
fields:
- name: constant
type: node?
+ kind:
+ - ConstantPathNode
+ - ConstantReadNode
+ comment: |
+ Represents the optional constant preceding the pattern
+
+ foo in Foo(*bar, baz, *qux)
+ ^^^
- name: left
type: node
+ kind: SplatNode
+ comment: |
+ Represents the first wildcard node in the pattern.
+
+ foo in *bar, baz, *qux
+ ^^^^
+
+ foo in Foo(*bar, baz, *qux)
+ ^^^^
- name: requireds
type: node[]
+ kind: pattern expression
+ comment: |
+ Represents the nodes in between the wildcards.
+
+ foo in *bar, baz, *qux
+ ^^^
+
+ foo in Foo(*bar, baz, 1, *qux)
+ ^^^^^^
- name: right
type: node
+ kind:
+ - SplatNode
+ - on error: MissingNode
+ comment: |
+ Represents the second wildcard node in the pattern.
+
+ foo in *bar, baz, *qux
+ ^^^^
+
+ foo in Foo(*bar, baz, *qux)
+ ^^^^
- name: opening_loc
type: location?
+ comment: |
+ The location of the opening brace.
+
+ foo in [*bar, baz, *qux]
+ ^
+
+ foo in Foo(*bar, baz, *qux)
+ ^
- name: closing_loc
type: location?
+ comment: |
+ The location of the closing brace.
+
+ foo in [*bar, baz, *qux]
+ ^
+
+ foo in Foo(*bar, baz, *qux)
+ ^
comment: |
Represents a find pattern in pattern matching.
@@ -1850,15 +2506,18 @@ nodes:
foo in Foo(*bar, baz, *qux)
^^^^^^^^^^^^^^^^^^^^
+
+ foo => *bar, baz, *qux
+ ^^^^^^^^^^^^^^^
- name: FlipFlopNode
+ flags: RangeFlags
fields:
- - name: flags
- type: flags
- kind: RangeFlags
- name: left
type: node?
+ kind: non-void expression
- name: right
type: node?
+ kind: non-void expression
- name: operator_loc
type: location
comment: |
@@ -1880,6 +2539,19 @@ nodes:
fields:
- name: index
type: node
+ kind:
+ - LocalVariableTargetNode
+ - InstanceVariableTargetNode
+ - ClassVariableTargetNode
+ - GlobalVariableTargetNode
+ - ConstantTargetNode
+ - ConstantPathTargetNode
+ - CallTargetNode
+ - IndexTargetNode
+ - MultiTargetNode
+ - on error: BackReferenceReadNode # for $& in a end
+ - on error: NumberedReferenceReadNode # for $1 in a end
+ - on error: MissingNode # for in 1..10; end
comment: |
The index expression for `for` loops.
@@ -1887,6 +2559,7 @@ nodes:
^
- name: collection
type: node
+ kind: non-void expression
comment: |
The collection to iterate over.
@@ -1955,11 +2628,18 @@ nodes:
- name: block
type: node?
kind: BlockNode
+ comment: |
+ All other arguments are forwarded as normal, except the original block is replaced with the new block.
comment: |
- Represents the use of the `super` keyword without parentheses or arguments.
+ Represents the use of the `super` keyword without parentheses or arguments, but which might have a block.
super
^^^^^
+
+ super { 123 }
+ ^^^^^^^^^^^^^
+
+ If it has any other arguments, it would be a `SuperNode` instead.
- name: GlobalVariableAndWriteNode
fields:
- name: name
@@ -1970,6 +2650,7 @@ nodes:
type: location
- name: value
type: node
+ kind: non-void expression
comment: |
Represents the use of the `&&=` operator for assignment to a global variable.
@@ -1985,6 +2666,7 @@ nodes:
type: location
- name: value
type: node
+ kind: non-void expression
- name: binary_operator
type: constant
comment: |
@@ -2002,6 +2684,7 @@ nodes:
type: location
- name: value
type: node
+ kind: non-void expression
comment: |
Represents the use of the `||=` operator for assignment to a global variable.
@@ -2050,6 +2733,7 @@ nodes:
^^^^
- name: value
type: node
+ kind: non-void expression
comment: |
The value to write to the global variable. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
@@ -2108,18 +2792,61 @@ nodes:
fields:
- name: constant
type: node?
+ kind:
+ - ConstantPathNode
+ - ConstantReadNode
+ comment: |
+ Represents the optional constant preceding the Hash.
+
+ foo => Bar[a: 1, b: 2]
+ ^^^
+
+ foo => Bar::Baz[a: 1, b: 2]
+ ^^^^^^^^
- name: elements
type: node[]
kind: AssocNode
+ comment: |
+ Represents the explicit named hash keys and values.
+
+ foo => { a: 1, b:, ** }
+ ^^^^^^^^
- name: rest
type: node?
kind:
- AssocSplatNode
- NoKeywordsParameterNode
+ comment: |
+ Represents the rest of the Hash keys and values. This can be named, unnamed, or explicitly forbidden via `**nil`, this last one results in a `NoKeywordsParameterNode`.
+
+ foo => { a: 1, b:, **c }
+ ^^^
+
+ foo => { a: 1, b:, ** }
+ ^^
+
+ foo => { a: 1, b:, **nil }
+ ^^^^^
- name: opening_loc
type: location?
+ comment: |
+ The location of the opening brace.
+
+ foo => { a: 1 }
+ ^
+
+ foo => Bar[a: 1]
+ ^
- name: closing_loc
type: location?
+ comment: |
+ The location of the closing brace.
+
+ foo => { a: 1 }
+ ^
+
+ foo => Bar[a: 1]
+ ^
comment: |
Represents a hash pattern in pattern matching.
@@ -2128,6 +2855,12 @@ nodes:
foo => { a: 1, b: 2, **c }
^^^^^^^^^^^^^^^^^^^
+
+ foo => Bar[a: 1, b: 2]
+ ^^^^^^^^^^^^^^^
+
+ foo in { a: 1, b: 2 }
+ ^^^^^^^^^^^^^^
- name: IfNode
fields:
- name: if_keyword_loc
@@ -2141,6 +2874,7 @@ nodes:
The `if_keyword_loc` field will be `nil` when the `IfNode` represents a ternary expression.
- name: predicate
type: node
+ kind: non-void expression
comment: |
The node for the condition the `IfNode` is testing.
@@ -2176,8 +2910,11 @@ nodes:
baz
^^^
end
- - name: consequent
+ - name: subsequent
type: node?
+ kind:
+ - ElseNode
+ - IfNode
comment: |
Represents an `ElseNode` or an `IfNode` when there is an `else` or an `elsif` in the `if` statement.
@@ -2230,6 +2967,11 @@ nodes:
fields:
- name: value
type: node
+ kind:
+ - LocalVariableReadNode
+ - CallNode
+ - ConstantReadNode
+ - LocalVariableTargetNode
comment: |
Represents a node that is implicitly being added to the tree but doesn't correspond directly to a node in the source.
@@ -2260,6 +3002,7 @@ nodes:
fields:
- name: pattern
type: node
+ kind: pattern expression
- name: statements
type: node?
kind: StatementsNode
@@ -2273,12 +3016,11 @@ nodes:
case a; in b then c end
^^^^^^^^^^^
- name: IndexAndWriteNode
+ flags: CallNodeFlags
fields:
- - name: flags
- type: flags
- kind: CallNodeFlags
- name: receiver
type: node?
+ kind: non-void expression
- name: call_operator_loc
type: location?
- name: opening_loc
@@ -2290,22 +3032,23 @@ nodes:
type: location
- name: block
type: node?
+ kind: BlockArgumentNode # foo[&b] &&= value, only valid on Ruby < 3.4
- name: operator_loc
type: location
- name: value
type: node
+ kind: non-void expression
comment: |
Represents the use of the `&&=` operator on a call to the `[]` method.
foo.bar[baz] &&= value
^^^^^^^^^^^^^^^^^^^^^^
- name: IndexOperatorWriteNode
+ flags: CallNodeFlags
fields:
- - name: flags
- type: flags
- kind: CallNodeFlags
- name: receiver
type: node?
+ kind: non-void expression
- name: call_operator_loc
type: location?
- name: opening_loc
@@ -2317,24 +3060,25 @@ nodes:
type: location
- name: block
type: node?
+ kind: BlockArgumentNode # foo[&b] += value, only valid on Ruby < 3.4
- name: binary_operator
type: constant
- name: binary_operator_loc
type: location
- name: value
type: node
+ kind: non-void expression
comment: |
Represents the use of an assignment operator on a call to `[]`.
foo.bar[baz] += value
^^^^^^^^^^^^^^^^^^^^^
- name: IndexOrWriteNode
+ flags: CallNodeFlags
fields:
- - name: flags
- type: flags
- kind: CallNodeFlags
- name: receiver
type: node?
+ kind: non-void expression
- name: call_operator_loc
type: location?
- name: opening_loc
@@ -2346,22 +3090,23 @@ nodes:
type: location
- name: block
type: node?
+ kind: BlockArgumentNode # foo[&b] ||= value, only valid on Ruby < 3.4
- name: operator_loc
type: location
- name: value
type: node
+ kind: non-void expression
comment: |
Represents the use of the `||=` operator on a call to `[]`.
foo.bar[baz] ||= value
^^^^^^^^^^^^^^^^^^^^^^
- name: IndexTargetNode
+ flags: CallNodeFlags
fields:
- - name: flags
- type: flags
- kind: CallNodeFlags
- name: receiver
type: node
+ kind: non-void expression
- name: opening_loc
type: location
- name: arguments
@@ -2371,6 +3116,7 @@ nodes:
type: location
- name: block
type: node?
+ kind: BlockArgumentNode # foo[&b], = 1, only valid on Ruby < 3.4
comment: |
Represents assigning to an index.
@@ -2394,6 +3140,7 @@ nodes:
type: location
- name: value
type: node
+ kind: non-void expression
comment: |
Represents the use of the `&&=` operator for assignment to an instance variable.
@@ -2409,6 +3156,7 @@ nodes:
type: location
- name: value
type: node
+ kind: non-void expression
- name: binary_operator
type: constant
comment: |
@@ -2426,6 +3174,7 @@ nodes:
type: location
- name: value
type: node
+ kind: non-void expression
comment: |
Represents the use of the `||=` operator for assignment to an instance variable.
@@ -2474,6 +3223,7 @@ nodes:
^^^
- name: value
type: node
+ kind: non-void expression
comment: |
The value to write to the instance variable. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
@@ -2495,10 +3245,8 @@ nodes:
@foo = 1
^^^^^^^^
- name: IntegerNode
+ flags: IntegerBaseFlags
fields:
- - name: flags
- type: flags
- kind: IntegerBaseFlags
- name: value
type: integer
comment: The value of the integer literal as a number.
@@ -2508,10 +3256,8 @@ nodes:
1
^
- name: InterpolatedMatchLastLineNode
+ flags: RegularExpressionFlags
fields:
- - name: flags
- type: flags
- kind: RegularExpressionFlags
- name: opening_loc
type: location
- name: parts
@@ -2529,10 +3275,8 @@ nodes:
if /foo #{bar} baz/ then end
^^^^^^^^^^^^^^^^
- name: InterpolatedRegularExpressionNode
+ flags: RegularExpressionFlags
fields:
- - name: flags
- type: flags
- kind: RegularExpressionFlags
- name: opening_loc
type: location
- name: parts
@@ -2550,10 +3294,8 @@ nodes:
/foo #{bar} baz/
^^^^^^^^^^^^^^^^
- name: InterpolatedStringNode
+ flags: InterpolatedStringNodeFlags
fields:
- - name: flags
- type: flags
- kind: InterpolatedStringNodeFlags
- name: opening_loc
type: location?
- name: parts
@@ -2563,6 +3305,10 @@ nodes:
- EmbeddedStatementsNode
- EmbeddedVariableNode
- InterpolatedStringNode # `"a" "#{b}"`
+ - on error: XStringNode # `<<`FOO` "bar"
+ - on error: InterpolatedXStringNode
+ - on error: SymbolNode
+ - on error: InterpolatedSymbolNode
- name: closing_loc
type: location?
newline: parts
@@ -2620,10 +3366,8 @@ nodes:
-> { it + it }
^^^^^^^^^^^^^^
- name: KeywordHashNode
+ flags: KeywordHashNodeFlags
fields:
- - name: flags
- type: flags
- kind: KeywordHashNodeFlags
- name: elements
type: node[]
kind:
@@ -2635,10 +3379,8 @@ nodes:
foo(a: b)
^^^^
- name: KeywordRestParameterNode
+ flags: ParameterFlags
fields:
- - name: flags
- type: flags
- kind: ParameterFlags
- name: name
type: constant?
- name: name_loc
@@ -2663,8 +3405,15 @@ nodes:
type: location
- name: parameters
type: node?
+ kind:
+ - BlockParametersNode
+ - NumberedParametersNode
+ - ItParametersNode
- name: body
type: node?
+ kind:
+ - StatementsNode
+ - BeginNode
comment: |
Represents using a lambda literal (not the lambda method call).
@@ -2678,6 +3427,7 @@ nodes:
type: location
- name: value
type: node
+ kind: non-void expression
- name: name
type: constant
- name: depth
@@ -2695,6 +3445,7 @@ nodes:
type: location
- name: value
type: node
+ kind: non-void expression
- name: name
type: constant
- name: binary_operator
@@ -2714,6 +3465,7 @@ nodes:
type: location
- name: value
type: node
+ kind: non-void expression
- name: name
type: constant
- name: depth
@@ -2764,6 +3516,9 @@ nodes:
foo, bar = baz
^^^ ^^^
+
+ foo => baz
+ ^^^
- name: LocalVariableWriteNode
fields:
- name: name
@@ -2793,6 +3548,7 @@ nodes:
^^^
- name: value
type: node
+ kind: non-void expression
comment: |
The value to write to the local variable. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
@@ -2818,10 +3574,8 @@ nodes:
foo = 1
^^^^^^^
- name: MatchLastLineNode
+ flags: RegularExpressionFlags
fields:
- - name: flags
- type: flags
- kind: RegularExpressionFlags
- name: opening_loc
type: location
- name: content_loc
@@ -2839,8 +3593,10 @@ nodes:
fields:
- name: value
type: node
+ kind: non-void expression
- name: pattern
type: node
+ kind: pattern expression
- name: operator_loc
type: location
comment: |
@@ -2852,10 +3608,66 @@ nodes:
fields:
- name: value
type: node
+ kind: non-void expression
+ comment: |
+ Represents the left-hand side of the operator.
+
+ foo => bar
+ ^^^
- name: pattern
type: node
+ kind: pattern expression
+ comment: |
+ Represents the right-hand side of the operator. The type of the node depends on the expression.
+
+ Anything that looks like a local variable name (including `_`) will result in a `LocalVariableTargetNode`.
+
+ foo => a # This is equivalent to writing `a = foo`
+ ^
+
+ Using an explicit `Array` or combining expressions with `,` will result in a `ArrayPatternNode`. This can be preceded by a constant.
+
+ foo => [a]
+ ^^^
+
+ foo => a, b
+ ^^^^
+
+ foo => Bar[a, b]
+ ^^^^^^^^^
+
+ If the array pattern contains at least two wildcard matches, a `FindPatternNode` is created instead.
+
+ foo => *, 1, *a
+ ^^^^^
+
+ Using an explicit `Hash` or a constant with square brackets and hash keys in the square brackets will result in a `HashPatternNode`.
+
+ foo => { a: 1, b: }
+
+ foo => Bar[a: 1, b:]
+
+ foo => Bar[**]
+
+ To use any variable that needs run time evaluation, pinning is required. This results in a `PinnedVariableNode`
+
+ foo => ^a
+ ^^
+
+ Similar, any expression can be used with pinning. This results in a `PinnedExpressionNode`.
+
+ foo => ^(a + 1)
+
+ Anything else will result in the regular node for that expression, for example a `ConstantReadNode`.
+
+ foo => CONST
- name: operator_loc
type: location
+ comment: |
+ The location of the operator.
+
+ foo => bar
+ ^^
comment: |
Represents the use of the `=>` operator.
@@ -2885,8 +3697,15 @@ nodes:
type: location
- name: constant_path
type: node
+ kind:
+ - ConstantReadNode
+ - ConstantPathNode
+ - on error: MissingNode # module Parent module end
- name: body
type: node?
+ kind:
+ - StatementsNode
+ - BeginNode
- name: end_keyword_loc
type: location
- name: name
@@ -2910,11 +3729,39 @@ nodes:
- CallTargetNode
- IndexTargetNode
- MultiTargetNode
- - RequiredParameterNode
- - BackReferenceReadNode # On parsing error of `$',`
- - NumberedReferenceReadNode # On parsing error of `$1,`
+ - RequiredParameterNode # def m((a,b)); end
+ - on error: BackReferenceReadNode # a, (b, $&) = z
+ - on error: NumberedReferenceReadNode # a, (b, $1) = z
+ comment: |
+ Represents the targets expressions before a splat node.
+
+ a, (b, c, *) = 1, 2, 3, 4, 5
+ ^^^^
+
+ The splat node can be absent, in that case all target expressions are in the left field.
+
+ a, (b, c) = 1, 2, 3, 4, 5
+ ^^^^
- name: rest
type: node?
+ kind:
+ - ImplicitRestNode
+ - SplatNode
+ comment: |
+ Represents a splat node in the target expression.
+
+ a, (b, *c) = 1, 2, 3, 4
+ ^^
+
+ The variable can be empty, this results in a `SplatNode` with a `nil` expression field.
+
+ a, (b, *) = 1, 2, 3, 4
+ ^
+
+ If the `*` is omitted, this field will contain an `ImplicitRestNode`
+
+ a, (b,) = 1, 2, 3, 4
+ ^
- name: rights
type: node[]
kind:
@@ -2927,17 +3774,38 @@ nodes:
- CallTargetNode
- IndexTargetNode
- MultiTargetNode
- - RequiredParameterNode
- - BackReferenceReadNode # On parsing error of `*,$'`
+ - RequiredParameterNode # def m((*,b)); end
+ - on error: BackReferenceReadNode # a, (*, $&) = z
+ - on error: NumberedReferenceReadNode # a, (*, $1) = z
+ comment: |
+ Represents the targets expressions after a splat node.
+
+ a, (*, b, c) = 1, 2, 3, 4, 5
+ ^^^^
- name: lparen_loc
type: location?
+ comment: |
+ The location of the opening parenthesis.
+
+ a, (b, c) = 1, 2, 3
+ ^
- name: rparen_loc
type: location?
+ comment: |
+ The location of the closing parenthesis.
+
+ a, (b, c) = 1, 2, 3
+ ^
comment: |
Represents a multi-target expression.
a, (b, c) = 1, 2, 3
^^^^^^
+
+ This can be a part of `MultiWriteNode` as above, or the target of a `for` loop
+
+ for a, b in [[1, 2], [3, 4]]
+ ^^^^
- name: MultiWriteNode
fields:
- name: lefts
@@ -2952,8 +3820,38 @@ nodes:
- CallTargetNode
- IndexTargetNode
- MultiTargetNode
+ - on error: BackReferenceReadNode # $&, = z
+ - on error: NumberedReferenceReadNode # $1, = z
+ comment: |
+ Represents the targets expressions before a splat node.
+
+ a, b, * = 1, 2, 3, 4, 5
+ ^^^^
+
+ The splat node can be absent, in that case all target expressions are in the left field.
+
+ a, b, c = 1, 2, 3, 4, 5
+ ^^^^^^^
- name: rest
type: node?
+ kind:
+ - ImplicitRestNode
+ - SplatNode
+ comment: |
+ Represents a splat node in the target expression.
+
+ a, b, *c = 1, 2, 3, 4
+ ^^
+
+ The variable can be empty, this results in a `SplatNode` with a `nil` expression field.
+
+ a, b, * = 1, 2, 3, 4
+ ^
+
+ If the `*` is omitted, this field will contain an `ImplicitRestNode`
+
+ a, b, = 1, 2, 3, 4
+ ^
- name: rights
type: node[]
kind:
@@ -2966,14 +3864,42 @@ nodes:
- CallTargetNode
- IndexTargetNode
- MultiTargetNode
+ - on error: BackReferenceReadNode # *, $& = z
+ - on error: NumberedReferenceReadNode # *, $1 = z
+ comment: |
+ Represents the targets expressions after a splat node.
+
+ a, *, b, c = 1, 2, 3, 4, 5
+ ^^^^
- name: lparen_loc
type: location?
+ comment: |
+ The location of the opening parenthesis.
+
+ (a, b, c) = 1, 2, 3
+ ^
- name: rparen_loc
type: location?
+ comment: |
+ The location of the closing parenthesis.
+
+ (a, b, c) = 1, 2, 3
+ ^
- name: operator_loc
type: location
+ comment: |
+ The location of the operator.
+
+ a, b, c = 1, 2, 3
+ ^
- name: value
type: node
+ kind: non-void expression
+ comment: |
+ The value to write to the targets. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+
+ a, b, c = 1, 2, 3
+ ^^^^^^^
comment: |
Represents a write to a multi-target expression.
@@ -3036,16 +3962,15 @@ nodes:
$1
^^
- name: OptionalKeywordParameterNode
+ flags: ParameterFlags
fields:
- - name: flags
- type: flags
- kind: ParameterFlags
- name: name
type: constant
- name: name_loc
type: location
- name: value
type: node
+ kind: non-void expression
comment: |
Represents an optional keyword parameter to a method, block, or lambda definition.
@@ -3053,10 +3978,8 @@ nodes:
^^^^
end
- name: OptionalParameterNode
+ flags: ParameterFlags
fields:
- - name: flags
- type: flags
- kind: ParameterFlags
- name: name
type: constant
- name: name_loc
@@ -3065,6 +3988,7 @@ nodes:
type: location
- name: value
type: node
+ kind: non-void expression
comment: |
Represents an optional parameter to a method, block, or lambda definition.
@@ -3075,6 +3999,7 @@ nodes:
fields:
- name: left
type: node
+ kind: non-void expression
comment: |
Represents the left side of the expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
@@ -3085,8 +4010,9 @@ nodes:
^
- name: right
type: node
+ kind: Node
comment: |
- Represents the right side of the expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
+ Represents the right side of the expression.
left || right
^^^^^
@@ -3126,10 +4052,10 @@ nodes:
- RequiredParameterNode
- MultiTargetNode
# On parsing error of `f(**kwargs, ...)` or `f(**nil, ...)`, the keyword_rest value is moved here:
- - KeywordRestParameterNode
- - NoKeywordsParameterNode
+ - on error: KeywordRestParameterNode
+ - on error: NoKeywordsParameterNode
# On parsing error of `f(..., ...)`, the first forwarding parameter is moved here:
- - ForwardingParameterNode
+ - on error: ForwardingParameterNode
- name: keywords
type: node[]
kind:
@@ -3151,9 +4077,11 @@ nodes:
^^^^^^^
end
- name: ParenthesesNode
+ flags: ParenthesesNodeFlags
fields:
- name: body
type: node?
+ kind: non-void expression # Usually a StatementsNode but not always e.g. `1 in (..10)`
- name: opening_loc
type: location
- name: closing_loc
@@ -3168,12 +4096,33 @@ nodes:
fields:
- name: expression
type: node
+ kind: non-void expression
+ comment: |
+ The expression used in the pinned expression
+
+ foo in ^(bar)
+ ^^^
- name: operator_loc
type: location
+ comment: |
+ The location of the `^` operator
+
+ foo in ^(bar)
+ ^
- name: lparen_loc
type: location
+ comment: |
+ The location of the opening parenthesis.
+
+ foo in ^(bar)
+ ^
- name: rparen_loc
type: location
+ comment: |
+ The location of the closing parenthesis.
+
+ foo in ^(bar)
+ ^
comment: |
Represents the use of the `^` operator for pinning an expression in a pattern matching expression.
@@ -3183,8 +4132,27 @@ nodes:
fields:
- name: variable
type: node
+ kind:
+ - LocalVariableReadNode
+ - InstanceVariableReadNode
+ - ClassVariableReadNode
+ - GlobalVariableReadNode # foo in ^$a
+ - BackReferenceReadNode # foo in ^$&
+ - NumberedReferenceReadNode # foo in ^$1
+ - ItLocalVariableReadNode # proc { 1 in ^it }
+ - on error: MissingNode # foo in ^Bar
+ comment: |
+ The variable used in the pinned expression
+
+ foo in ^bar
+ ^^^
- name: operator_loc
type: location
+ comment: |
+ The location of the `^` operator
+
+ foo in ^bar
+ ^
comment: |
Represents the use of the `^` operator for pinning a variable in a pattern matching expression.
@@ -3231,12 +4199,11 @@ nodes:
kind: StatementsNode
comment: The top level node of any parse tree.
- name: RangeNode
+ flags: RangeFlags
fields:
- - name: flags
- type: flags
- kind: RangeFlags
- name: left
type: node?
+ kind: non-void expression
comment: |
The left-hand side of the range, if present. It can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
@@ -3247,6 +4214,7 @@ nodes:
^^^^^
- name: right
type: node?
+ kind: non-void expression
comment: |
The right-hand side of the range, if present. It can be either `nil` or any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
@@ -3269,10 +4237,8 @@ nodes:
c if a =~ /left/ ... b =~ /right/
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- name: RationalNode
+ flags: IntegerBaseFlags
fields:
- - name: flags
- type: flags
- kind: IntegerBaseFlags
- name: numerator
type: integer
comment: |
@@ -3297,10 +4263,8 @@ nodes:
redo
^^^^
- name: RegularExpressionNode
+ flags: RegularExpressionFlags
fields:
- - name: flags
- type: flags
- kind: RegularExpressionFlags
- name: opening_loc
type: location
- name: content_loc
@@ -3315,10 +4279,8 @@ nodes:
/foo/i
^^^^^^
- name: RequiredKeywordParameterNode
+ flags: ParameterFlags
fields:
- - name: flags
- type: flags
- kind: ParameterFlags
- name: name
type: constant
- name: name_loc
@@ -3330,10 +4292,8 @@ nodes:
^^
end
- name: RequiredParameterNode
+ flags: ParameterFlags
fields:
- - name: flags
- type: flags
- kind: ParameterFlags
- name: name
type: constant
comment: |
@@ -3346,10 +4306,12 @@ nodes:
fields:
- name: expression
type: node
+ kind: Node
- name: keyword_loc
type: location
- name: rescue_expression
type: node
+ kind: Node
newline: expression
comment: |
Represents an expression modified with a rescue.
@@ -3362,14 +4324,29 @@ nodes:
type: location
- name: exceptions
type: node[]
+ kind: non-void expression
- name: operator_loc
type: location?
- name: reference
type: node?
+ kind:
+ - LocalVariableTargetNode
+ - InstanceVariableTargetNode
+ - ClassVariableTargetNode
+ - GlobalVariableTargetNode
+ - ConstantTargetNode
+ - ConstantPathTargetNode
+ - CallTargetNode
+ - IndexTargetNode
+ - on error: BackReferenceReadNode # => begin; rescue => $&; end
+ - on error: NumberedReferenceReadNode # => begin; rescue => $1; end
+ - on error: MissingNode # begin; rescue =>; end
+ - name: then_keyword_loc
+ type: location?
- name: statements
type: node?
kind: StatementsNode
- - name: consequent
+ - name: subsequent
type: node?
kind: RescueNode
comment: |
@@ -3381,12 +4358,10 @@ nodes:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
end
- `Foo, *splat, Bar` are in the `exceptions` field. `ex` is in the `exception` field.
+ `Foo, *splat, Bar` are in the `exceptions` field. `ex` is in the `reference` field.
- name: RestParameterNode
+ flags: ParameterFlags
fields:
- - name: flags
- type: flags
- kind: ParameterFlags
- name: name
type: constant?
- name: name_loc
@@ -3407,9 +4382,6 @@ nodes:
^^^^^
- name: ReturnNode
fields:
- - name: flags
- type: flags
- kind: ReturnNodeFlags
- name: keyword_loc
type: location
- name: arguments
@@ -3427,10 +4399,8 @@ nodes:
self
^^^^
- name: ShareableConstantNode
+ flags: ShareableConstantNodeFlags
fields:
- - name: flags
- type: flags
- kind: ShareableConstantNodeFlags
- name: write
type: node
kind:
@@ -3459,8 +4429,12 @@ nodes:
type: location
- name: expression
type: node
+ kind: non-void expression
- name: body
type: node?
+ kind:
+ - StatementsNode
+ - BeginNode
- name: end_keyword_loc
type: location
comment: |
@@ -3475,10 +4449,8 @@ nodes:
__ENCODING__
^^^^^^^^^^^^
- name: SourceFileNode
+ flags: StringFlags
fields:
- - name: flags
- type: flags
- kind: StringFlags
- name: filepath
type: string
comment: Represents the file path being parsed. This corresponds directly to the `filepath` option given to the various `Prism::parse*` APIs.
@@ -3499,6 +4471,7 @@ nodes:
type: location
- name: expression
type: node?
+ kind: non-void expression
comment: |
Represents the use of the splat operator.
@@ -3508,16 +4481,15 @@ nodes:
fields:
- name: body
type: node[]
+ kind: Node
comment: |
Represents a set of statements contained within some scope.
foo; bar; baz
^^^^^^^^^^^^^
- name: StringNode
+ flags: StringFlags
fields:
- - name: flags
- type: flags
- kind: StringFlags
- name: opening_loc
type: location?
- name: content_loc
@@ -3546,10 +4518,14 @@ nodes:
- name: arguments
type: node?
kind: ArgumentsNode
+ comment: "Can be only `nil` when there are empty parentheses, like `super()`."
- name: rparen_loc
type: location?
- name: block
type: node?
+ kind:
+ - BlockNode
+ - BlockArgumentNode
comment: |
Represents the use of the `super` keyword with parentheses or arguments.
@@ -3558,11 +4534,11 @@ nodes:
super foo, bar
^^^^^^^^^^^^^^
+
+ If no arguments are provided (except for a block), it would be a `ForwardingSuperNode` instead.
- name: SymbolNode
+ flags: SymbolFlags
fields:
- - name: flags
- type: flags
- kind: SymbolFlags
- name: opening_loc
type: location?
- name: value_loc
@@ -3613,6 +4589,7 @@ nodes:
^^^^^^
- name: predicate
type: node
+ kind: non-void expression
comment: |
The condition to be evaluated for the unless expression. It can be any [non-void expression](https://github.com/ruby/prism/blob/main/docs/parsing_rules.md#non-void-expression).
@@ -3637,7 +4614,7 @@ nodes:
unless cond then bar end
^^^
- - name: consequent
+ - name: else_clause
type: node?
kind: ElseNode
comment: |
@@ -3662,16 +4639,17 @@ nodes:
unless foo then bar end
^^^^^^^^^^^^^^^^^^^^^^^
- name: UntilNode
+ flags: LoopFlags
fields:
- - name: flags
- type: flags
- kind: LoopFlags
- name: keyword_loc
type: location
+ - name: do_keyword_loc
+ type: location?
- name: closing_loc
type: location?
- name: predicate
type: node
+ kind: non-void expression
- name: statements
type: node?
kind: StatementsNode
@@ -3690,6 +4668,7 @@ nodes:
type: location
- name: conditions
type: node[]
+ kind: non-void expression
- name: then_keyword_loc
type: location?
- name: statements
@@ -3703,16 +4682,17 @@ nodes:
^^^^^^^^^
end
- name: WhileNode
+ flags: LoopFlags
fields:
- - name: flags
- type: flags
- kind: LoopFlags
- name: keyword_loc
type: location
+ - name: do_keyword_loc
+ type: location?
- name: closing_loc
type: location?
- name: predicate
type: node
+ kind: non-void expression
- name: statements
type: node?
kind: StatementsNode
@@ -3726,10 +4706,8 @@ nodes:
while foo do bar end
^^^^^^^^^^^^^^^^^^^^
- name: XStringNode
+ flags: EncodingFlags
fields:
- - name: flags
- type: flags
- kind: EncodingFlags
- name: opening_loc
type: location
- name: content_loc
diff --git a/prism/defines.h b/prism/defines.h
index 849ca6d051..e31429c789 100644
--- a/prism/defines.h
+++ b/prism/defines.h
@@ -23,9 +23,21 @@
* some platforms they aren't included unless this is already defined.
*/
#define __STDC_FORMAT_MACROS
+// Include sys/types.h before inttypes.h to work around issue with
+// certain versions of GCC and newlib which causes omission of PRIx64
+#include <sys/types.h>
#include <inttypes.h>
/**
+ * When we are parsing using recursive descent, we want to protect against
+ * malicious payloads that could attempt to crash our parser. We do this by
+ * specifying a maximum depth to which we are allowed to recurse.
+ */
+#ifndef PRISM_DEPTH_MAXIMUM
+ #define PRISM_DEPTH_MAXIMUM 10000
+#endif
+
+/**
* By default, we compile with -fvisibility=hidden. When this is enabled, we
* need to mark certain functions as being publically-visible. This macro does
* that in a compiler-agnostic way.
@@ -119,14 +131,24 @@
#endif
/**
- * isinf on Windows is defined as accepting a float, but on POSIX systems it
- * accepts a float, a double, or a long double. We want to mirror this behavior
- * on windows.
+ * If PRISM_HAS_NO_FILESYSTEM is defined, then we want to exclude all filesystem
+ * related code from the library. All filesystem related code should be guarded
+ * by PRISM_HAS_FILESYSTEM.
*/
-#ifdef _WIN32
-# include <float.h>
-# undef isinf
-# define isinf(x) (sizeof(x) == sizeof(float) ? !_finitef(x) : !_finite(x))
+#ifndef PRISM_HAS_NO_FILESYSTEM
+# define PRISM_HAS_FILESYSTEM
+#endif
+
+/**
+ * isinf on POSIX systems it accepts a float, a double, or a long double.
+ * But mingw didn't provide an isinf macro, only an isinf function that only
+ * accepts floats, so we need to use _finite instead.
+ */
+#ifdef __MINGW64__
+ #include <float.h>
+ #define PRISM_ISINF(x) (!_finite(x))
+#else
+ #define PRISM_ISINF(x) isinf(x)
#endif
/**
@@ -203,4 +225,36 @@
#define PRISM_ENCODING_EXCLUDE_FULL
#endif
+/**
+ * Support PRISM_LIKELY and PRISM_UNLIKELY to help the compiler optimize its
+ * branch predication.
+ */
+#if defined(__GNUC__) || defined(__clang__)
+ /** The compiler should predicate that this branch will be taken. */
+ #define PRISM_LIKELY(x) __builtin_expect(!!(x), 1)
+
+ /** The compiler should predicate that this branch will not be taken. */
+ #define PRISM_UNLIKELY(x) __builtin_expect(!!(x), 0)
+#else
+ /** Void because this platform does not support branch prediction hints. */
+ #define PRISM_LIKELY(x) (x)
+
+ /** Void because this platform does not support branch prediction hints. */
+ #define PRISM_UNLIKELY(x) (x)
+#endif
+
+/**
+ * We use -Wimplicit-fallthrough to guard potentially unintended fall-through between cases of a switch.
+ * Use PRISM_FALLTHROUGH to explicitly annotate cases where the fallthrough is intentional.
+ */
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202311L // C23 or later
+ #define PRISM_FALLTHROUGH [[fallthrough]];
+#elif defined(__GNUC__) || defined(__clang__)
+ #define PRISM_FALLTHROUGH __attribute__((fallthrough));
+#elif defined(_MSC_VER)
+ #define PRISM_FALLTHROUGH __fallthrough;
+#else
+ #define PRISM_FALLTHROUGH
+#endif
+
#endif
diff --git a/prism/encoding.c b/prism/encoding.c
index a4aeed104f..d7e5616840 100644
--- a/prism/encoding.c
+++ b/prism/encoding.c
@@ -2,7 +2,7 @@
typedef uint32_t pm_unicode_codepoint_t;
-#define UNICODE_ALPHA_CODEPOINTS_LENGTH 1450
+#define UNICODE_ALPHA_CODEPOINTS_LENGTH 1508
static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEPOINTS_LENGTH] = {
0x100, 0x2C1,
0x2C6, 0x2D1,
@@ -10,7 +10,7 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x2EC, 0x2EC,
0x2EE, 0x2EE,
0x345, 0x345,
- 0x370, 0x374,
+ 0x363, 0x374,
0x376, 0x377,
0x37A, 0x37D,
0x37F, 0x37F,
@@ -50,7 +50,8 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x840, 0x858,
0x860, 0x86A,
0x870, 0x887,
- 0x889, 0x88E,
+ 0x889, 0x88F,
+ 0x897, 0x897,
0x8A0, 0x8C9,
0x8D4, 0x8DF,
0x8E3, 0x8E9,
@@ -140,7 +141,7 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0xC4A, 0xC4C,
0xC55, 0xC56,
0xC58, 0xC5A,
- 0xC5D, 0xC5D,
+ 0xC5C, 0xC5D,
0xC60, 0xC63,
0xC80, 0xC83,
0xC85, 0xC8C,
@@ -152,7 +153,7 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0xCC6, 0xCC8,
0xCCA, 0xCCC,
0xCD5, 0xCD6,
- 0xCDD, 0xCDE,
+ 0xCDC, 0xCDE,
0xCE0, 0xCE3,
0xCF1, 0xCF3,
0xD00, 0xD0C,
@@ -264,7 +265,7 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x1C00, 0x1C36,
0x1C4D, 0x1C4F,
0x1C5A, 0x1C7D,
- 0x1C80, 0x1C88,
+ 0x1C80, 0x1C8A,
0x1C90, 0x1CBA,
0x1CBD, 0x1CBF,
0x1CE9, 0x1CEC,
@@ -272,7 +273,7 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x1CF5, 0x1CF6,
0x1CFA, 0x1CFA,
0x1D00, 0x1DBF,
- 0x1DE7, 0x1DF4,
+ 0x1DD3, 0x1DF4,
0x1E00, 0x1F15,
0x1F18, 0x1F1D,
0x1F20, 0x1F45,
@@ -352,11 +353,8 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0xA67F, 0xA6EF,
0xA717, 0xA71F,
0xA722, 0xA788,
- 0xA78B, 0xA7CA,
- 0xA7D0, 0xA7D1,
- 0xA7D3, 0xA7D3,
- 0xA7D5, 0xA7D9,
- 0xA7F2, 0xA805,
+ 0xA78B, 0xA7DC,
+ 0xA7F1, 0xA805,
0xA807, 0xA827,
0xA840, 0xA873,
0xA880, 0xA8C3,
@@ -446,6 +444,7 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x105A3, 0x105B1,
0x105B3, 0x105B9,
0x105BB, 0x105BC,
+ 0x105C0, 0x105F3,
0x10600, 0x10736,
0x10740, 0x10755,
0x10760, 0x10767,
@@ -464,6 +463,7 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x108F4, 0x108F5,
0x10900, 0x10915,
0x10920, 0x10939,
+ 0x10940, 0x10959,
0x10980, 0x109B7,
0x109BE, 0x109BF,
0x10A00, 0x10A03,
@@ -483,9 +483,14 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x10C80, 0x10CB2,
0x10CC0, 0x10CF2,
0x10D00, 0x10D27,
+ 0x10D4A, 0x10D65,
+ 0x10D69, 0x10D69,
+ 0x10D6F, 0x10D85,
0x10E80, 0x10EA9,
0x10EAB, 0x10EAC,
0x10EB0, 0x10EB1,
+ 0x10EC2, 0x10EC7,
+ 0x10EFA, 0x10EFC,
0x10F00, 0x10F1C,
0x10F27, 0x10F27,
0x10F30, 0x10F45,
@@ -529,6 +534,17 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x11350, 0x11350,
0x11357, 0x11357,
0x1135D, 0x11363,
+ 0x11380, 0x11389,
+ 0x1138B, 0x1138B,
+ 0x1138E, 0x1138E,
+ 0x11390, 0x113B5,
+ 0x113B7, 0x113C0,
+ 0x113C2, 0x113C2,
+ 0x113C5, 0x113C5,
+ 0x113C7, 0x113CA,
+ 0x113CC, 0x113CD,
+ 0x113D1, 0x113D1,
+ 0x113D3, 0x113D3,
0x11400, 0x11441,
0x11443, 0x11445,
0x11447, 0x1144A,
@@ -567,6 +583,8 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x11A50, 0x11A97,
0x11A9D, 0x11A9D,
0x11AB0, 0x11AF8,
+ 0x11B60, 0x11B67,
+ 0x11BC0, 0x11BE0,
0x11C00, 0x11C08,
0x11C0A, 0x11C36,
0x11C38, 0x11C3E,
@@ -588,6 +606,7 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x11D90, 0x11D91,
0x11D93, 0x11D96,
0x11D98, 0x11D98,
+ 0x11DB0, 0x11DDB,
0x11EE0, 0x11EF6,
0x11F00, 0x11F10,
0x11F12, 0x11F3A,
@@ -599,7 +618,9 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x12F90, 0x12FF0,
0x13000, 0x1342F,
0x13441, 0x13446,
+ 0x13460, 0x143FA,
0x14400, 0x14646,
+ 0x16100, 0x1612E,
0x16800, 0x16A38,
0x16A40, 0x16A5E,
0x16A70, 0x16ABE,
@@ -608,16 +629,19 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x16B40, 0x16B43,
0x16B63, 0x16B77,
0x16B7D, 0x16B8F,
+ 0x16D40, 0x16D6C,
0x16E40, 0x16E7F,
+ 0x16EA0, 0x16EB8,
+ 0x16EBB, 0x16ED3,
0x16F00, 0x16F4A,
0x16F4F, 0x16F87,
0x16F8F, 0x16F9F,
0x16FE0, 0x16FE1,
0x16FE3, 0x16FE3,
- 0x16FF0, 0x16FF1,
- 0x17000, 0x187F7,
- 0x18800, 0x18CD5,
- 0x18D00, 0x18D08,
+ 0x16FF0, 0x16FF6,
+ 0x17000, 0x18CD5,
+ 0x18CFF, 0x18D1E,
+ 0x18D80, 0x18DF2,
0x1AFF0, 0x1AFF3,
0x1AFF5, 0x1AFFB,
0x1AFFD, 0x1AFFE,
@@ -677,6 +701,11 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x1E290, 0x1E2AD,
0x1E2C0, 0x1E2EB,
0x1E4D0, 0x1E4EB,
+ 0x1E5D0, 0x1E5ED,
+ 0x1E5F0, 0x1E5F0,
+ 0x1E6C0, 0x1E6DE,
+ 0x1E6E0, 0x1E6F5,
+ 0x1E6FE, 0x1E6FF,
0x1E7E0, 0x1E7E6,
0x1E7E8, 0x1E7EB,
0x1E7ED, 0x1E7EE,
@@ -722,16 +751,16 @@ static const pm_unicode_codepoint_t unicode_alpha_codepoints[UNICODE_ALPHA_CODEP
0x1F150, 0x1F169,
0x1F170, 0x1F189,
0x20000, 0x2A6DF,
- 0x2A700, 0x2B739,
- 0x2B740, 0x2B81D,
- 0x2B820, 0x2CEA1,
+ 0x2A700, 0x2B81D,
+ 0x2B820, 0x2CEAD,
0x2CEB0, 0x2EBE0,
+ 0x2EBF0, 0x2EE5D,
0x2F800, 0x2FA1D,
0x30000, 0x3134A,
- 0x31350, 0x323AF,
+ 0x31350, 0x33479,
};
-#define UNICODE_ALNUM_CODEPOINTS_LENGTH 1528
+#define UNICODE_ALNUM_CODEPOINTS_LENGTH 1598
static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEPOINTS_LENGTH] = {
0x100, 0x2C1,
0x2C6, 0x2D1,
@@ -739,7 +768,7 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x2EC, 0x2EC,
0x2EE, 0x2EE,
0x345, 0x345,
- 0x370, 0x374,
+ 0x363, 0x374,
0x376, 0x377,
0x37A, 0x37D,
0x37F, 0x37F,
@@ -778,7 +807,8 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x840, 0x858,
0x860, 0x86A,
0x870, 0x887,
- 0x889, 0x88E,
+ 0x889, 0x88F,
+ 0x897, 0x897,
0x8A0, 0x8C9,
0x8D4, 0x8DF,
0x8E3, 0x8E9,
@@ -872,7 +902,7 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0xC4A, 0xC4C,
0xC55, 0xC56,
0xC58, 0xC5A,
- 0xC5D, 0xC5D,
+ 0xC5C, 0xC5D,
0xC60, 0xC63,
0xC66, 0xC6F,
0xC80, 0xC83,
@@ -885,7 +915,7 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0xCC6, 0xCC8,
0xCCA, 0xCCC,
0xCD5, 0xCD6,
- 0xCDD, 0xCDE,
+ 0xCDC, 0xCDE,
0xCE0, 0xCE3,
0xCE6, 0xCEF,
0xCF1, 0xCF3,
@@ -1007,7 +1037,7 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x1C00, 0x1C36,
0x1C40, 0x1C49,
0x1C4D, 0x1C7D,
- 0x1C80, 0x1C88,
+ 0x1C80, 0x1C8A,
0x1C90, 0x1CBA,
0x1CBD, 0x1CBF,
0x1CE9, 0x1CEC,
@@ -1015,7 +1045,7 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x1CF5, 0x1CF6,
0x1CFA, 0x1CFA,
0x1D00, 0x1DBF,
- 0x1DE7, 0x1DF4,
+ 0x1DD3, 0x1DF4,
0x1E00, 0x1F15,
0x1F18, 0x1F1D,
0x1F20, 0x1F45,
@@ -1094,11 +1124,8 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0xA67F, 0xA6EF,
0xA717, 0xA71F,
0xA722, 0xA788,
- 0xA78B, 0xA7CA,
- 0xA7D0, 0xA7D1,
- 0xA7D3, 0xA7D3,
- 0xA7D5, 0xA7D9,
- 0xA7F2, 0xA805,
+ 0xA78B, 0xA7DC,
+ 0xA7F1, 0xA805,
0xA807, 0xA827,
0xA840, 0xA873,
0xA880, 0xA8C3,
@@ -1191,6 +1218,7 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x105A3, 0x105B1,
0x105B3, 0x105B9,
0x105BB, 0x105BC,
+ 0x105C0, 0x105F3,
0x10600, 0x10736,
0x10740, 0x10755,
0x10760, 0x10767,
@@ -1209,6 +1237,7 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x108F4, 0x108F5,
0x10900, 0x10915,
0x10920, 0x10939,
+ 0x10940, 0x10959,
0x10980, 0x109B7,
0x109BE, 0x109BF,
0x10A00, 0x10A03,
@@ -1229,9 +1258,14 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x10CC0, 0x10CF2,
0x10D00, 0x10D27,
0x10D30, 0x10D39,
+ 0x10D40, 0x10D65,
+ 0x10D69, 0x10D69,
+ 0x10D6F, 0x10D85,
0x10E80, 0x10EA9,
0x10EAB, 0x10EAC,
0x10EB0, 0x10EB1,
+ 0x10EC2, 0x10EC7,
+ 0x10EFA, 0x10EFC,
0x10F00, 0x10F1C,
0x10F27, 0x10F27,
0x10F30, 0x10F45,
@@ -1278,6 +1312,17 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x11350, 0x11350,
0x11357, 0x11357,
0x1135D, 0x11363,
+ 0x11380, 0x11389,
+ 0x1138B, 0x1138B,
+ 0x1138E, 0x1138E,
+ 0x11390, 0x113B5,
+ 0x113B7, 0x113C0,
+ 0x113C2, 0x113C2,
+ 0x113C5, 0x113C5,
+ 0x113C7, 0x113CA,
+ 0x113CC, 0x113CD,
+ 0x113D1, 0x113D1,
+ 0x113D3, 0x113D3,
0x11400, 0x11441,
0x11443, 0x11445,
0x11447, 0x1144A,
@@ -1297,6 +1342,7 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x11680, 0x116B5,
0x116B8, 0x116B8,
0x116C0, 0x116C9,
+ 0x116D0, 0x116E3,
0x11700, 0x1171A,
0x1171D, 0x1172A,
0x11730, 0x11739,
@@ -1322,6 +1368,9 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x11A50, 0x11A97,
0x11A9D, 0x11A9D,
0x11AB0, 0x11AF8,
+ 0x11B60, 0x11B67,
+ 0x11BC0, 0x11BE0,
+ 0x11BF0, 0x11BF9,
0x11C00, 0x11C08,
0x11C0A, 0x11C36,
0x11C38, 0x11C3E,
@@ -1346,6 +1395,8 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x11D93, 0x11D96,
0x11D98, 0x11D98,
0x11DA0, 0x11DA9,
+ 0x11DB0, 0x11DDB,
+ 0x11DE0, 0x11DE9,
0x11EE0, 0x11EF6,
0x11F00, 0x11F10,
0x11F12, 0x11F3A,
@@ -1358,7 +1409,10 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x12F90, 0x12FF0,
0x13000, 0x1342F,
0x13441, 0x13446,
+ 0x13460, 0x143FA,
0x14400, 0x14646,
+ 0x16100, 0x1612E,
+ 0x16130, 0x16139,
0x16800, 0x16A38,
0x16A40, 0x16A5E,
0x16A60, 0x16A69,
@@ -1370,16 +1424,20 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x16B50, 0x16B59,
0x16B63, 0x16B77,
0x16B7D, 0x16B8F,
+ 0x16D40, 0x16D6C,
+ 0x16D70, 0x16D79,
0x16E40, 0x16E7F,
+ 0x16EA0, 0x16EB8,
+ 0x16EBB, 0x16ED3,
0x16F00, 0x16F4A,
0x16F4F, 0x16F87,
0x16F8F, 0x16F9F,
0x16FE0, 0x16FE1,
0x16FE3, 0x16FE3,
- 0x16FF0, 0x16FF1,
- 0x17000, 0x187F7,
- 0x18800, 0x18CD5,
- 0x18D00, 0x18D08,
+ 0x16FF0, 0x16FF6,
+ 0x17000, 0x18CD5,
+ 0x18CFF, 0x18D1E,
+ 0x18D80, 0x18DF2,
0x1AFF0, 0x1AFF3,
0x1AFF5, 0x1AFFB,
0x1AFFD, 0x1AFFE,
@@ -1394,6 +1452,7 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x1BC80, 0x1BC88,
0x1BC90, 0x1BC99,
0x1BC9E, 0x1BC9E,
+ 0x1CCF0, 0x1CCF9,
0x1D400, 0x1D454,
0x1D456, 0x1D49C,
0x1D49E, 0x1D49F,
@@ -1443,6 +1502,11 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x1E2F0, 0x1E2F9,
0x1E4D0, 0x1E4EB,
0x1E4F0, 0x1E4F9,
+ 0x1E5D0, 0x1E5ED,
+ 0x1E5F0, 0x1E5FA,
+ 0x1E6C0, 0x1E6DE,
+ 0x1E6E0, 0x1E6F5,
+ 0x1E6FE, 0x1E6FF,
0x1E7E0, 0x1E7E6,
0x1E7E8, 0x1E7EB,
0x1E7ED, 0x1E7EE,
@@ -1490,16 +1554,16 @@ static const pm_unicode_codepoint_t unicode_alnum_codepoints[UNICODE_ALNUM_CODEP
0x1F170, 0x1F189,
0x1FBF0, 0x1FBF9,
0x20000, 0x2A6DF,
- 0x2A700, 0x2B739,
- 0x2B740, 0x2B81D,
- 0x2B820, 0x2CEA1,
+ 0x2A700, 0x2B81D,
+ 0x2B820, 0x2CEAD,
0x2CEB0, 0x2EBE0,
+ 0x2EBF0, 0x2EE5D,
0x2F800, 0x2FA1D,
0x30000, 0x3134A,
- 0x31350, 0x323AF,
+ 0x31350, 0x33479,
};
-#define UNICODE_ISUPPER_CODEPOINTS_LENGTH 1302
+#define UNICODE_ISUPPER_CODEPOINTS_LENGTH 1320
static const pm_unicode_codepoint_t unicode_isupper_codepoints[UNICODE_ISUPPER_CODEPOINTS_LENGTH] = {
0x100, 0x100,
0x102, 0x102,
@@ -1774,6 +1838,7 @@ static const pm_unicode_codepoint_t unicode_isupper_codepoints[UNICODE_ISUPPER_C
0x10C7, 0x10C7,
0x10CD, 0x10CD,
0x13A0, 0x13F5,
+ 0x1C89, 0x1C89,
0x1C90, 0x1CBA,
0x1CBD, 0x1CBF,
0x1E00, 0x1E00,
@@ -2103,9 +2168,15 @@ static const pm_unicode_codepoint_t unicode_isupper_codepoints[UNICODE_ISUPPER_C
0xA7C2, 0xA7C2,
0xA7C4, 0xA7C7,
0xA7C9, 0xA7C9,
+ 0xA7CB, 0xA7CC,
+ 0xA7CE, 0xA7CE,
0xA7D0, 0xA7D0,
+ 0xA7D2, 0xA7D2,
+ 0xA7D4, 0xA7D4,
0xA7D6, 0xA7D6,
0xA7D8, 0xA7D8,
+ 0xA7DA, 0xA7DA,
+ 0xA7DC, 0xA7DC,
0xA7F5, 0xA7F5,
0xFF21, 0xFF3A,
0x10400, 0x10427,
@@ -2115,8 +2186,10 @@ static const pm_unicode_codepoint_t unicode_isupper_codepoints[UNICODE_ISUPPER_C
0x1058C, 0x10592,
0x10594, 0x10595,
0x10C80, 0x10CB2,
+ 0x10D50, 0x10D65,
0x118A0, 0x118BF,
0x16E40, 0x16E5F,
+ 0x16EA0, 0x16EB8,
0x1D400, 0x1D419,
0x1D434, 0x1D44D,
0x1D468, 0x1D481,
@@ -2304,6 +2377,10 @@ pm_encoding_utf_8_char_width(const uint8_t *b, ptrdiff_t n) {
*/
size_t
pm_encoding_utf_8_alpha_char(const uint8_t *b, ptrdiff_t n) {
+ if (n == 0) {
+ return 0;
+ }
+
if (*b < 0x80) {
return (pm_encoding_unicode_table[*b] & PRISM_ENCODING_ALPHABETIC_BIT) ? 1 : 0;
}
@@ -2324,6 +2401,10 @@ pm_encoding_utf_8_alpha_char(const uint8_t *b, ptrdiff_t n) {
*/
size_t
pm_encoding_utf_8_alnum_char(const uint8_t *b, ptrdiff_t n) {
+ if (n == 0) {
+ return 0;
+ }
+
if (*b < 0x80) {
return (pm_encoding_unicode_table[*b] & (PRISM_ENCODING_ALPHANUMERIC_BIT)) ? 1 : 0;
}
@@ -2344,6 +2425,10 @@ pm_encoding_utf_8_alnum_char(const uint8_t *b, ptrdiff_t n) {
*/
bool
pm_encoding_utf_8_isupper_char(const uint8_t *b, ptrdiff_t n) {
+ if (n == 0) {
+ return 0;
+ }
+
if (*b < 0x80) {
return (pm_encoding_unicode_table[*b] & PRISM_ENCODING_UPPERCASE_BIT) ? true : false;
}
@@ -2362,7 +2447,8 @@ pm_encoding_utf_8_isupper_char(const uint8_t *b, ptrdiff_t n) {
static pm_unicode_codepoint_t
pm_cesu_8_codepoint(const uint8_t *b, ptrdiff_t n, size_t *width) {
- if (b[0] < 0x80) {
+
+ if ((n > 0) && (b[0] < 0x80)) {
*width = 1;
return (pm_unicode_codepoint_t) b[0];
}
@@ -2401,6 +2487,10 @@ pm_cesu_8_codepoint(const uint8_t *b, ptrdiff_t n, size_t *width) {
static size_t
pm_encoding_cesu_8_char_width(const uint8_t *b, ptrdiff_t n) {
+ if (n == 0) {
+ return 0;
+ }
+
size_t width;
pm_cesu_8_codepoint(b, n, &width);
return width;
@@ -2408,6 +2498,10 @@ pm_encoding_cesu_8_char_width(const uint8_t *b, ptrdiff_t n) {
static size_t
pm_encoding_cesu_8_alpha_char(const uint8_t *b, ptrdiff_t n) {
+ if (n == 0) {
+ return 0;
+ }
+
if (*b < 0x80) {
return (pm_encoding_unicode_table[*b] & PRISM_ENCODING_ALPHABETIC_BIT) ? 1 : 0;
}
@@ -2424,6 +2518,10 @@ pm_encoding_cesu_8_alpha_char(const uint8_t *b, ptrdiff_t n) {
static size_t
pm_encoding_cesu_8_alnum_char(const uint8_t *b, ptrdiff_t n) {
+ if (n == 0) {
+ return 0;
+ }
+
if (*b < 0x80) {
return (pm_encoding_unicode_table[*b] & (PRISM_ENCODING_ALPHANUMERIC_BIT)) ? 1 : 0;
}
@@ -2440,6 +2538,10 @@ pm_encoding_cesu_8_alnum_char(const uint8_t *b, ptrdiff_t n) {
static bool
pm_encoding_cesu_8_isupper_char(const uint8_t *b, ptrdiff_t n) {
+ if (n == 0) {
+ return 0;
+ }
+
if (*b < 0x80) {
return (pm_encoding_unicode_table[*b] & PRISM_ENCODING_UPPERCASE_BIT) ? true : false;
}
@@ -3855,14 +3957,14 @@ static const uint8_t pm_encoding_windows_874_table[256] = {
};
#define PRISM_ENCODING_TABLE(name) \
- static size_t pm_encoding_ ##name ## _alpha_char(const uint8_t *b, PRISM_ATTRIBUTE_UNUSED ptrdiff_t n) { \
- return (pm_encoding_ ##name ## _table[*b] & PRISM_ENCODING_ALPHABETIC_BIT); \
+ static size_t pm_encoding_ ##name ## _alpha_char(const uint8_t *b, ptrdiff_t n) { \
+ return ((n > 0) && (pm_encoding_ ##name ## _table[*b] & PRISM_ENCODING_ALPHABETIC_BIT)); \
} \
- static size_t pm_encoding_ ##name ## _alnum_char(const uint8_t *b, PRISM_ATTRIBUTE_UNUSED ptrdiff_t n) { \
- return (pm_encoding_ ##name ## _table[*b] & PRISM_ENCODING_ALPHANUMERIC_BIT) ? 1 : 0; \
+ static size_t pm_encoding_ ##name ## _alnum_char(const uint8_t *b, ptrdiff_t n) { \
+ return ((n > 0) && (pm_encoding_ ##name ## _table[*b] & PRISM_ENCODING_ALPHANUMERIC_BIT)) ? 1 : 0; \
} \
- static bool pm_encoding_ ##name ## _isupper_char(const uint8_t *b, PRISM_ATTRIBUTE_UNUSED ptrdiff_t n) { \
- return (pm_encoding_ ##name ## _table[*b] & PRISM_ENCODING_UPPERCASE_BIT); \
+ static bool pm_encoding_ ##name ## _isupper_char(const uint8_t *b, ptrdiff_t n) { \
+ return ((n > 0) && (pm_encoding_ ##name ## _table[*b] & PRISM_ENCODING_UPPERCASE_BIT)); \
}
PRISM_ENCODING_TABLE(cp850)
@@ -3931,8 +4033,8 @@ PRISM_ENCODING_TABLE(windows_874)
* means that if the top bit is not set, the character is 1 byte long.
*/
static size_t
-pm_encoding_ascii_char_width(const uint8_t *b, PRISM_ATTRIBUTE_UNUSED ptrdiff_t n) {
- return *b < 0x80 ? 1 : 0;
+pm_encoding_ascii_char_width(const uint8_t *b, ptrdiff_t n) {
+ return ((n > 0) && (*b < 0x80)) ? 1 : 0;
}
/**
@@ -3940,8 +4042,8 @@ pm_encoding_ascii_char_width(const uint8_t *b, PRISM_ATTRIBUTE_UNUSED ptrdiff_t
* alphabetical character.
*/
static size_t
-pm_encoding_ascii_alpha_char(const uint8_t *b, PRISM_ATTRIBUTE_UNUSED ptrdiff_t n) {
- return (pm_encoding_ascii_table[*b] & PRISM_ENCODING_ALPHABETIC_BIT);
+pm_encoding_ascii_alpha_char(const uint8_t *b, ptrdiff_t n) {
+ return (n > 0) ? (pm_encoding_ascii_table[*b] & PRISM_ENCODING_ALPHABETIC_BIT) : 0;
}
/**
@@ -3951,7 +4053,7 @@ pm_encoding_ascii_alpha_char(const uint8_t *b, PRISM_ATTRIBUTE_UNUSED ptrdiff_t
*/
static size_t
pm_encoding_ascii_alpha_char_7bit(const uint8_t *b, ptrdiff_t n) {
- return (*b < 0x80) ? pm_encoding_ascii_alpha_char(b, n) : 0;
+ return ((n > 0) && (*b < 0x80)) ? pm_encoding_ascii_alpha_char(b, n) : 0;
}
/**
@@ -3959,8 +4061,8 @@ pm_encoding_ascii_alpha_char_7bit(const uint8_t *b, ptrdiff_t n) {
* alphanumeric character.
*/
static size_t
-pm_encoding_ascii_alnum_char(const uint8_t *b, PRISM_ATTRIBUTE_UNUSED ptrdiff_t n) {
- return (pm_encoding_ascii_table[*b] & PRISM_ENCODING_ALPHANUMERIC_BIT) ? 1 : 0;
+pm_encoding_ascii_alnum_char(const uint8_t *b, ptrdiff_t n) {
+ return ((n > 0) && (pm_encoding_ascii_table[*b] & PRISM_ENCODING_ALPHANUMERIC_BIT)) ? 1 : 0;
}
/**
@@ -3970,7 +4072,7 @@ pm_encoding_ascii_alnum_char(const uint8_t *b, PRISM_ATTRIBUTE_UNUSED ptrdiff_t
*/
static size_t
pm_encoding_ascii_alnum_char_7bit(const uint8_t *b, ptrdiff_t n) {
- return (*b < 0x80) ? pm_encoding_ascii_alnum_char(b, n) : 0;
+ return ((n > 0) && (*b < 0x80)) ? pm_encoding_ascii_alnum_char(b, n) : 0;
}
/**
@@ -3978,8 +4080,8 @@ pm_encoding_ascii_alnum_char_7bit(const uint8_t *b, ptrdiff_t n) {
* character.
*/
static bool
-pm_encoding_ascii_isupper_char(const uint8_t *b, PRISM_ATTRIBUTE_UNUSED ptrdiff_t n) {
- return (pm_encoding_ascii_table[*b] & PRISM_ENCODING_UPPERCASE_BIT);
+pm_encoding_ascii_isupper_char(const uint8_t *b, ptrdiff_t n) {
+ return (n > 0) && (pm_encoding_ascii_table[*b] & PRISM_ENCODING_UPPERCASE_BIT);
}
/**
@@ -3998,7 +4100,7 @@ pm_encoding_single_char_width(PRISM_ATTRIBUTE_UNUSED const uint8_t *b, PRISM_ATT
static size_t
pm_encoding_euc_jp_char_width(const uint8_t *b, ptrdiff_t n) {
// These are the single byte characters.
- if (*b < 0x80) {
+ if ((n > 0) && (*b < 0x80)) {
return 1;
}
@@ -4042,6 +4144,9 @@ pm_encoding_euc_jp_isupper_char(const uint8_t *b, ptrdiff_t n) {
*/
static size_t
pm_encoding_shift_jis_char_width(const uint8_t *b, ptrdiff_t n) {
+ if (n == 0) {
+ return 0;
+ }
// These are the single byte characters.
if (b[0] < 0x80 || (b[0] >= 0xA1 && b[0] <= 0xDF)) {
return 1;
@@ -4105,7 +4210,7 @@ pm_encoding_shift_jis_isupper_char(const uint8_t *b, ptrdiff_t n) {
*/
static bool
pm_encoding_ascii_isupper_char_7bit(const uint8_t *b, ptrdiff_t n) {
- return (*b < 0x80) && pm_encoding_ascii_isupper_char(b, n);
+ return (n > 0) && (*b < 0x80) && pm_encoding_ascii_isupper_char(b, n);
}
/**
@@ -4115,7 +4220,7 @@ pm_encoding_ascii_isupper_char_7bit(const uint8_t *b, ptrdiff_t n) {
static size_t
pm_encoding_big5_char_width(const uint8_t *b, ptrdiff_t n) {
// These are the single byte characters.
- if (*b < 0x80) {
+ if ((n > 0) && (*b < 0x80)) {
return 1;
}
@@ -4134,7 +4239,7 @@ pm_encoding_big5_char_width(const uint8_t *b, ptrdiff_t n) {
static size_t
pm_encoding_cp949_char_width(const uint8_t *b, ptrdiff_t n) {
// These are the single byte characters
- if (*b <= 0x80) {
+ if ((n > 0) && (*b <= 0x80)) {
return 1;
}
@@ -4153,7 +4258,7 @@ pm_encoding_cp949_char_width(const uint8_t *b, ptrdiff_t n) {
static size_t
pm_encoding_emacs_mule_char_width(const uint8_t *b, ptrdiff_t n) {
// These are the 1 byte characters.
- if (*b < 0x80) {
+ if ((n > 0) && (*b < 0x80)) {
return 1;
}
@@ -4196,7 +4301,7 @@ pm_encoding_emacs_mule_char_width(const uint8_t *b, ptrdiff_t n) {
static size_t
pm_encoding_euc_kr_char_width(const uint8_t *b, ptrdiff_t n) {
// These are the single byte characters.
- if (*b < 0x80) {
+ if ((n > 0) && (*b < 0x80)) {
return 1;
}
@@ -4215,7 +4320,7 @@ pm_encoding_euc_kr_char_width(const uint8_t *b, ptrdiff_t n) {
static size_t
pm_encoding_euc_tw_char_width(const uint8_t *b, ptrdiff_t n) {
// These are the single byte characters.
- if (*b < 0x80) {
+ if ((n > 0) && (*b < 0x80)) {
return 1;
}
@@ -4239,7 +4344,7 @@ pm_encoding_euc_tw_char_width(const uint8_t *b, ptrdiff_t n) {
static size_t
pm_encoding_gb18030_char_width(const uint8_t *b, ptrdiff_t n) {
// These are the 1 byte characters.
- if (*b < 0x80) {
+ if ((n > 0) && (*b < 0x80)) {
return 1;
}
@@ -4263,7 +4368,7 @@ pm_encoding_gb18030_char_width(const uint8_t *b, ptrdiff_t n) {
static size_t
pm_encoding_gbk_char_width(const uint8_t *b, ptrdiff_t n) {
// These are the single byte characters.
- if (*b <= 0x80) {
+ if ((n > 0) && (*b <= 0x80)) {
return 1;
}
diff --git a/prism/extension.c b/prism/extension.c
index f692ea616c..71c2d91b98 100644
--- a/prism/extension.c
+++ b/prism/extension.c
@@ -21,35 +21,40 @@ VALUE rb_cPrismParseError;
VALUE rb_cPrismParseWarning;
VALUE rb_cPrismResult;
VALUE rb_cPrismParseResult;
+VALUE rb_cPrismLexResult;
VALUE rb_cPrismParseLexResult;
+VALUE rb_cPrismStringQuery;
+VALUE rb_cPrismScope;
+VALUE rb_cPrismCurrentVersionError;
VALUE rb_cPrismDebugEncoding;
ID rb_id_option_command_line;
ID rb_id_option_encoding;
ID rb_id_option_filepath;
+ID rb_id_option_freeze;
ID rb_id_option_frozen_string_literal;
ID rb_id_option_line;
+ID rb_id_option_main_script;
+ID rb_id_option_partial_script;
ID rb_id_option_scopes;
ID rb_id_option_version;
ID rb_id_source_for;
+ID rb_id_forwarding_positionals;
+ID rb_id_forwarding_keywords;
+ID rb_id_forwarding_block;
+ID rb_id_forwarding_all;
/******************************************************************************/
/* IO of Ruby code */
/******************************************************************************/
/**
- * Check if the given VALUE is a string. If it's nil, then return NULL. If it's
- * not a string, then raise a type error. Otherwise return the VALUE as a C
- * string.
+ * Check if the given VALUE is a string. If it's not a string, then raise a
+ * TypeError. Otherwise return the VALUE as a C string.
*/
static const char *
check_string(VALUE value) {
- // If the value is nil, then we don't need to do anything.
- if (NIL_P(value)) {
- return NULL;
- }
-
// Check if the value is a string. If it's not, then raise a type error.
if (!RB_TYPE_P(value, T_STRING)) {
rb_raise(rb_eTypeError, "wrong argument type %" PRIsVALUE " (expected String)", rb_obj_class(value));
@@ -96,14 +101,53 @@ build_options_scopes(pm_options_t *options, VALUE scopes) {
for (size_t scope_index = 0; scope_index < scopes_count; scope_index++) {
VALUE scope = rb_ary_entry(scopes, scope_index);
- // Check that the scope is an array. If it's not, then raise a type
- // error.
- if (!RB_TYPE_P(scope, T_ARRAY)) {
- rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected Array)", rb_obj_class(scope));
+ // The scope can be either an array or it can be a Prism::Scope object.
+ // Parse out the correct values here from either.
+ VALUE locals;
+ uint8_t forwarding = PM_OPTIONS_SCOPE_FORWARDING_NONE;
+
+ if (RB_TYPE_P(scope, T_ARRAY)) {
+ locals = scope;
+ } else if (rb_obj_is_kind_of(scope, rb_cPrismScope)) {
+ locals = rb_ivar_get(scope, rb_intern("@locals"));
+ if (!RB_TYPE_P(locals, T_ARRAY)) {
+ rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected Array)", rb_obj_class(locals));
+ }
+
+ VALUE names = rb_ivar_get(scope, rb_intern("@forwarding"));
+ if (!RB_TYPE_P(names, T_ARRAY)) {
+ rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected Array)", rb_obj_class(names));
+ }
+
+ size_t names_count = RARRAY_LEN(names);
+ for (size_t name_index = 0; name_index < names_count; name_index++) {
+ VALUE name = rb_ary_entry(names, name_index);
+
+ // Check that the name is a symbol. If it's not, then raise
+ // a type error.
+ if (!RB_TYPE_P(name, T_SYMBOL)) {
+ rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected Symbol)", rb_obj_class(name));
+ }
+
+ ID id = SYM2ID(name);
+ if (id == rb_id_forwarding_positionals) {
+ forwarding |= PM_OPTIONS_SCOPE_FORWARDING_POSITIONALS;
+ } else if (id == rb_id_forwarding_keywords) {
+ forwarding |= PM_OPTIONS_SCOPE_FORWARDING_KEYWORDS;
+ } else if (id == rb_id_forwarding_block) {
+ forwarding |= PM_OPTIONS_SCOPE_FORWARDING_BLOCK;
+ } else if (id == rb_id_forwarding_all) {
+ forwarding |= PM_OPTIONS_SCOPE_FORWARDING_ALL;
+ } else {
+ rb_raise(rb_eArgError, "invalid forwarding value: %" PRIsVALUE, name);
+ }
+ }
+ } else {
+ rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE" (expected Array or Prism::Scope)", rb_obj_class(scope));
}
// Initialize the scope array.
- size_t locals_count = RARRAY_LEN(scope);
+ size_t locals_count = RARRAY_LEN(locals);
pm_options_scope_t *options_scope = &options->scopes[scope_index];
if (!pm_options_scope_init(options_scope, locals_count)) {
rb_raise(rb_eNoMemError, "failed to allocate memory");
@@ -111,7 +155,7 @@ build_options_scopes(pm_options_t *options, VALUE scopes) {
// Iterate over the locals and add them to the scope.
for (size_t local_index = 0; local_index < locals_count; local_index++) {
- VALUE local = rb_ary_entry(scope, local_index);
+ VALUE local = rb_ary_entry(locals, local_index);
// Check that the local is a symbol. If it's not, then raise a
// type error.
@@ -124,6 +168,9 @@ build_options_scopes(pm_options_t *options, VALUE scopes) {
const char *name = rb_id2name(SYM2ID(local));
pm_string_constant_init(scope_local, name, strlen(name));
}
+
+ // Now set the forwarding options.
+ pm_options_scope_forwarding_set(options_scope, forwarding);
}
}
@@ -138,7 +185,13 @@ build_options_i(VALUE key, VALUE value, VALUE argument) {
if (key_id == rb_id_option_filepath) {
if (!NIL_P(value)) pm_options_filepath_set(options, check_string(value));
} else if (key_id == rb_id_option_encoding) {
- if (!NIL_P(value)) pm_options_encoding_set(options, rb_enc_name(rb_to_encoding(value)));
+ if (!NIL_P(value)) {
+ if (value == Qfalse) {
+ pm_options_encoding_locked_set(options, true);
+ } else {
+ pm_options_encoding_set(options, rb_enc_name(rb_to_encoding(value)));
+ }
+ }
} else if (key_id == rb_id_option_line) {
if (!NIL_P(value)) pm_options_line_set(options, NUM2INT(value));
} else if (key_id == rb_id_option_frozen_string_literal) {
@@ -147,7 +200,12 @@ build_options_i(VALUE key, VALUE value, VALUE argument) {
if (!NIL_P(value)) {
const char *version = check_string(value);
- if (!pm_options_version_set(options, version, RSTRING_LEN(value))) {
+ if (RSTRING_LEN(value) == 7 && strncmp(version, "current", 7) == 0) {
+ const char *current_version = RSTRING_PTR(rb_const_get(rb_cObject, rb_intern("RUBY_VERSION")));
+ if (!pm_options_version_set(options, current_version, 3)) {
+ rb_exc_raise(rb_exc_new_cstr(rb_cPrismCurrentVersionError, current_version));
+ }
+ } else if (!pm_options_version_set(options, version, RSTRING_LEN(value))) {
rb_raise(rb_eArgError, "invalid version: %" PRIsVALUE, value);
}
}
@@ -172,6 +230,12 @@ build_options_i(VALUE key, VALUE value, VALUE argument) {
pm_options_command_line_set(options, command_line);
}
+ } else if (key_id == rb_id_option_main_script) {
+ if (!NIL_P(value)) pm_options_main_script_set(options, RTEST(value));
+ } else if (key_id == rb_id_option_partial_script) {
+ if (!NIL_P(value)) pm_options_partial_script_set(options, RTEST(value));
+ } else if (key_id == rb_id_option_freeze) {
+ if (!NIL_P(value)) pm_options_freeze_set(options, RTEST(value));
} else {
rb_raise(rb_eArgError, "unknown keyword: %" PRIsVALUE, key);
}
@@ -206,6 +270,7 @@ build_options(VALUE argument) {
static void
extract_options(pm_options_t *options, VALUE filepath, VALUE keywords) {
options->line = 1; // default
+
if (!NIL_P(keywords)) {
struct build_options_data data = { .options = options, .keywords = keywords };
struct build_options_data *argument = &data;
@@ -246,27 +311,41 @@ string_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options)
* Read options for methods that look like (filepath, **options).
*/
static void
-file_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options) {
+file_options(int argc, VALUE *argv, pm_string_t *input, pm_options_t *options, VALUE *encoded_filepath) {
VALUE filepath;
VALUE keywords;
rb_scan_args(argc, argv, "1:", &filepath, &keywords);
Check_Type(filepath, T_STRING);
+ *encoded_filepath = rb_str_encode_ospath(filepath);
+ extract_options(options, *encoded_filepath, keywords);
- extract_options(options, filepath, keywords);
-
- const char * string_source = (const char *) pm_string_source(&options->filepath);
+ const char *source = (const char *) pm_string_source(&options->filepath);
+ pm_string_init_result_t result;
- if (!pm_string_file_init(input, string_source)) {
- pm_options_free(options);
+ switch (result = pm_string_file_init(input, source)) {
+ case PM_STRING_INIT_SUCCESS:
+ break;
+ case PM_STRING_INIT_ERROR_GENERIC: {
+ pm_options_free(options);
#ifdef _WIN32
- int e = rb_w32_map_errno(GetLastError());
+ int e = rb_w32_map_errno(GetLastError());
#else
- int e = errno;
+ int e = errno;
#endif
- rb_syserr_fail(e, string_source);
+ rb_syserr_fail(e, source);
+ break;
+ }
+ case PM_STRING_INIT_ERROR_DIRECTORY:
+ pm_options_free(options);
+ rb_syserr_fail(EISDIR, source);
+ break;
+ default:
+ pm_options_free(options);
+ rb_raise(rb_eRuntimeError, "Unknown error (%d) initializing file: %s", result, source);
+ break;
}
}
@@ -321,6 +400,7 @@ dump(int argc, VALUE *argv, VALUE self) {
#endif
VALUE value = dump_input(&input, &options);
+ if (options.freeze) rb_obj_freeze(value);
#ifdef PRISM_BUILD_DEBUG
xfree(dup);
@@ -344,7 +424,8 @@ dump_file(int argc, VALUE *argv, VALUE self) {
pm_string_t input;
pm_options_t options = { 0 };
- file_options(argc, argv, &input, &options);
+ VALUE encoded_filepath;
+ file_options(argc, argv, &input, &options, &encoded_filepath);
VALUE value = dump_input(&input, &options);
pm_string_free(&input);
@@ -360,55 +441,89 @@ dump_file(int argc, VALUE *argv, VALUE self) {
/******************************************************************************/
/**
+ * The same as rb_class_new_instance, but accepts an additional boolean to
+ * indicate whether or not the resulting class instance should be frozen.
+ */
+static inline VALUE
+rb_class_new_instance_freeze(int argc, const VALUE *argv, VALUE klass, bool freeze) {
+ VALUE value = rb_class_new_instance(argc, argv, klass);
+ if (freeze) rb_obj_freeze(value);
+ return value;
+}
+
+/**
+ * Create a new Location instance from the given parser and bounds.
+ */
+static inline VALUE
+parser_location(const pm_parser_t *parser, VALUE source, bool freeze, const uint8_t *start, size_t length) {
+ VALUE argv[] = { source, LONG2FIX(start - parser->start), LONG2FIX(length) };
+ return rb_class_new_instance_freeze(3, argv, rb_cPrismLocation, freeze);
+}
+
+/**
+ * Create a new Location instance from the given parser and location.
+ */
+#define PARSER_LOCATION_LOC(parser, source, freeze, loc) \
+ parser_location(parser, source, freeze, loc.start, (size_t) (loc.end - loc.start))
+
+/**
+ * Build a new Comment instance from the given parser and comment.
+ */
+static inline VALUE
+parser_comment(const pm_parser_t *parser, VALUE source, bool freeze, const pm_comment_t *comment) {
+ VALUE argv[] = { PARSER_LOCATION_LOC(parser, source, freeze, comment->location) };
+ VALUE type = (comment->type == PM_COMMENT_EMBDOC) ? rb_cPrismEmbDocComment : rb_cPrismInlineComment;
+ return rb_class_new_instance_freeze(1, argv, type, freeze);
+}
+
+/**
* Extract the comments out of the parser into an array.
*/
static VALUE
-parser_comments(pm_parser_t *parser, VALUE source) {
- VALUE comments = rb_ary_new();
-
- for (pm_comment_t *comment = (pm_comment_t *) parser->comment_list.head; comment != NULL; comment = (pm_comment_t *) comment->node.next) {
- VALUE location_argv[] = {
- source,
- LONG2FIX(comment->location.start - parser->start),
- LONG2FIX(comment->location.end - comment->location.start)
- };
-
- VALUE type = (comment->type == PM_COMMENT_EMBDOC) ? rb_cPrismEmbDocComment : rb_cPrismInlineComment;
- VALUE comment_argv[] = { rb_class_new_instance(3, location_argv, rb_cPrismLocation) };
- rb_ary_push(comments, rb_class_new_instance(1, comment_argv, type));
+parser_comments(const pm_parser_t *parser, VALUE source, bool freeze) {
+ VALUE comments = rb_ary_new_capa(parser->comment_list.size);
+
+ for (
+ const pm_comment_t *comment = (const pm_comment_t *) parser->comment_list.head;
+ comment != NULL;
+ comment = (const pm_comment_t *) comment->node.next
+ ) {
+ VALUE value = parser_comment(parser, source, freeze, comment);
+ rb_ary_push(comments, value);
}
+ if (freeze) rb_obj_freeze(comments);
return comments;
}
/**
+ * Build a new MagicComment instance from the given parser and magic comment.
+ */
+static inline VALUE
+parser_magic_comment(const pm_parser_t *parser, VALUE source, bool freeze, const pm_magic_comment_t *magic_comment) {
+ VALUE key_loc = parser_location(parser, source, freeze, magic_comment->key_start, magic_comment->key_length);
+ VALUE value_loc = parser_location(parser, source, freeze, magic_comment->value_start, magic_comment->value_length);
+ VALUE argv[] = { key_loc, value_loc };
+ return rb_class_new_instance_freeze(2, argv, rb_cPrismMagicComment, freeze);
+}
+
+/**
* Extract the magic comments out of the parser into an array.
*/
static VALUE
-parser_magic_comments(pm_parser_t *parser, VALUE source) {
- VALUE magic_comments = rb_ary_new();
-
- for (pm_magic_comment_t *magic_comment = (pm_magic_comment_t *) parser->magic_comment_list.head; magic_comment != NULL; magic_comment = (pm_magic_comment_t *) magic_comment->node.next) {
- VALUE key_loc_argv[] = {
- source,
- LONG2FIX(magic_comment->key_start - parser->start),
- LONG2FIX(magic_comment->key_length)
- };
-
- VALUE value_loc_argv[] = {
- source,
- LONG2FIX(magic_comment->value_start - parser->start),
- LONG2FIX(magic_comment->value_length)
- };
-
- VALUE magic_comment_argv[] = {
- rb_class_new_instance(3, key_loc_argv, rb_cPrismLocation),
- rb_class_new_instance(3, value_loc_argv, rb_cPrismLocation)
- };
-
- rb_ary_push(magic_comments, rb_class_new_instance(2, magic_comment_argv, rb_cPrismMagicComment));
+parser_magic_comments(const pm_parser_t *parser, VALUE source, bool freeze) {
+ VALUE magic_comments = rb_ary_new_capa(parser->magic_comment_list.size);
+
+ for (
+ const pm_magic_comment_t *magic_comment = (const pm_magic_comment_t *) parser->magic_comment_list.head;
+ magic_comment != NULL;
+ magic_comment = (const pm_magic_comment_t *) magic_comment->node.next
+ ) {
+ VALUE value = parser_magic_comment(parser, source, freeze, magic_comment);
+ rb_ary_push(magic_comments, value);
}
+ if (freeze) rb_obj_freeze(magic_comments);
return magic_comments;
}
@@ -417,17 +532,11 @@ parser_magic_comments(pm_parser_t *parser, VALUE source) {
* exists.
*/
static VALUE
-parser_data_loc(const pm_parser_t *parser, VALUE source) {
+parser_data_loc(const pm_parser_t *parser, VALUE source, bool freeze) {
if (parser->data_loc.end == NULL) {
return Qnil;
} else {
- VALUE argv[] = {
- source,
- LONG2FIX(parser->data_loc.start - parser->start),
- LONG2FIX(parser->data_loc.end - parser->data_loc.start)
- };
-
- return rb_class_new_instance(3, argv, rb_cPrismLocation);
+ return PARSER_LOCATION_LOC(parser, source, freeze, parser->data_loc);
}
}
@@ -435,16 +544,17 @@ parser_data_loc(const pm_parser_t *parser, VALUE source) {
* Extract the errors out of the parser into an array.
*/
static VALUE
-parser_errors(pm_parser_t *parser, rb_encoding *encoding, VALUE source) {
- VALUE errors = rb_ary_new();
- pm_diagnostic_t *error;
-
- for (error = (pm_diagnostic_t *) parser->error_list.head; error != NULL; error = (pm_diagnostic_t *) error->node.next) {
- VALUE location_argv[] = {
- source,
- LONG2FIX(error->location.start - parser->start),
- LONG2FIX(error->location.end - error->location.start)
- };
+parser_errors(const pm_parser_t *parser, rb_encoding *encoding, VALUE source, bool freeze) {
+ VALUE errors = rb_ary_new_capa(parser->error_list.size);
+
+ for (
+ const pm_diagnostic_t *error = (const pm_diagnostic_t *) parser->error_list.head;
+ error != NULL;
+ error = (const pm_diagnostic_t *) error->node.next
+ ) {
+ VALUE type = ID2SYM(rb_intern(pm_diagnostic_id_human(error->diag_id)));
+ VALUE message = rb_obj_freeze(rb_enc_str_new_cstr(error->message, encoding));
+ VALUE location = PARSER_LOCATION_LOC(parser, source, freeze, error->location);
VALUE level = Qnil;
switch (error->level) {
@@ -461,16 +571,12 @@ parser_errors(pm_parser_t *parser, rb_encoding *encoding, VALUE source) {
rb_raise(rb_eRuntimeError, "Unknown level: %" PRIu8, error->level);
}
- VALUE error_argv[] = {
- ID2SYM(rb_intern(pm_diagnostic_id_human(error->diag_id))),
- rb_enc_str_new_cstr(error->message, encoding),
- rb_class_new_instance(3, location_argv, rb_cPrismLocation),
- level
- };
-
- rb_ary_push(errors, rb_class_new_instance(4, error_argv, rb_cPrismParseError));
+ VALUE argv[] = { type, message, location, level };
+ VALUE value = rb_class_new_instance_freeze(4, argv, rb_cPrismParseError, freeze);
+ rb_ary_push(errors, value);
}
+ if (freeze) rb_obj_freeze(errors);
return errors;
}
@@ -478,16 +584,17 @@ parser_errors(pm_parser_t *parser, rb_encoding *encoding, VALUE source) {
* Extract the warnings out of the parser into an array.
*/
static VALUE
-parser_warnings(pm_parser_t *parser, rb_encoding *encoding, VALUE source) {
- VALUE warnings = rb_ary_new();
- pm_diagnostic_t *warning;
-
- for (warning = (pm_diagnostic_t *) parser->warning_list.head; warning != NULL; warning = (pm_diagnostic_t *) warning->node.next) {
- VALUE location_argv[] = {
- source,
- LONG2FIX(warning->location.start - parser->start),
- LONG2FIX(warning->location.end - warning->location.start)
- };
+parser_warnings(const pm_parser_t *parser, rb_encoding *encoding, VALUE source, bool freeze) {
+ VALUE warnings = rb_ary_new_capa(parser->warning_list.size);
+
+ for (
+ const pm_diagnostic_t *warning = (const pm_diagnostic_t *) parser->warning_list.head;
+ warning != NULL;
+ warning = (const pm_diagnostic_t *) warning->node.next
+ ) {
+ VALUE type = ID2SYM(rb_intern(pm_diagnostic_id_human(warning->diag_id)));
+ VALUE message = rb_obj_freeze(rb_enc_str_new_cstr(warning->message, encoding));
+ VALUE location = PARSER_LOCATION_LOC(parser, source, freeze, warning->location);
VALUE level = Qnil;
switch (warning->level) {
@@ -501,16 +608,12 @@ parser_warnings(pm_parser_t *parser, rb_encoding *encoding, VALUE source) {
rb_raise(rb_eRuntimeError, "Unknown level: %" PRIu8, warning->level);
}
- VALUE warning_argv[] = {
- ID2SYM(rb_intern(pm_diagnostic_id_human(warning->diag_id))),
- rb_enc_str_new_cstr(warning->message, encoding),
- rb_class_new_instance(3, location_argv, rb_cPrismLocation),
- level
- };
-
- rb_ary_push(warnings, rb_class_new_instance(4, warning_argv, rb_cPrismParseWarning));
+ VALUE argv[] = { type, message, location, level };
+ VALUE value = rb_class_new_instance_freeze(4, argv, rb_cPrismParseWarning, freeze);
+ rb_ary_push(warnings, value);
}
+ if (freeze) rb_obj_freeze(warnings);
return warnings;
}
@@ -518,18 +621,18 @@ parser_warnings(pm_parser_t *parser, rb_encoding *encoding, VALUE source) {
* Create a new parse result from the given parser, value, encoding, and source.
*/
static VALUE
-parse_result_create(VALUE class, pm_parser_t *parser, VALUE value, rb_encoding *encoding, VALUE source) {
+parse_result_create(VALUE class, const pm_parser_t *parser, VALUE value, rb_encoding *encoding, VALUE source, bool freeze) {
VALUE result_argv[] = {
value,
- parser_comments(parser, source),
- parser_magic_comments(parser, source),
- parser_data_loc(parser, source),
- parser_errors(parser, encoding, source),
- parser_warnings(parser, encoding, source),
+ parser_comments(parser, source, freeze),
+ parser_magic_comments(parser, source, freeze),
+ parser_data_loc(parser, source, freeze),
+ parser_errors(parser, encoding, source, freeze),
+ parser_warnings(parser, encoding, source, freeze),
source
};
- return rb_class_new_instance(7, result_argv, class);
+ return rb_class_new_instance_freeze(7, result_argv, class, freeze);
}
/******************************************************************************/
@@ -545,6 +648,7 @@ typedef struct {
VALUE source;
VALUE tokens;
rb_encoding *encoding;
+ bool freeze;
} parse_lex_data_t;
/**
@@ -556,9 +660,13 @@ static void
parse_lex_token(void *data, pm_parser_t *parser, pm_token_t *token) {
parse_lex_data_t *parse_lex_data = (parse_lex_data_t *) parser->lex_callback->data;
- VALUE yields = rb_ary_new_capa(2);
- rb_ary_push(yields, pm_token_new(parser, token, parse_lex_data->encoding, parse_lex_data->source));
- rb_ary_push(yields, INT2FIX(parser->lex_state));
+ VALUE value = pm_token_new(parser, token, parse_lex_data->encoding, parse_lex_data->source, parse_lex_data->freeze);
+ VALUE yields = rb_assoc_new(value, INT2FIX(parser->lex_state));
+
+ if (parse_lex_data->freeze) {
+ rb_obj_freeze(value);
+ rb_obj_freeze(yields);
+ }
rb_ary_push(parse_lex_data->tokens, yields);
}
@@ -578,14 +686,37 @@ parse_lex_encoding_changed_callback(pm_parser_t *parser) {
// one or two tokens, since the encoding can only change at the top of the
// file.
VALUE tokens = parse_lex_data->tokens;
+ VALUE next_tokens = rb_ary_new();
+
for (long index = 0; index < RARRAY_LEN(tokens); index++) {
VALUE yields = rb_ary_entry(tokens, index);
VALUE token = rb_ary_entry(yields, 0);
VALUE value = rb_ivar_get(token, rb_intern("@value"));
- rb_enc_associate(value, parse_lex_data->encoding);
- ENC_CODERANGE_CLEAR(value);
+ VALUE next_value = rb_str_dup(value);
+
+ rb_enc_associate(next_value, parse_lex_data->encoding);
+ if (parse_lex_data->freeze) rb_obj_freeze(next_value);
+
+ VALUE next_token_argv[] = {
+ parse_lex_data->source,
+ rb_ivar_get(token, rb_intern("@type")),
+ next_value,
+ rb_ivar_get(token, rb_intern("@location"))
+ };
+
+ VALUE next_token = rb_class_new_instance(4, next_token_argv, rb_cPrismToken);
+ VALUE next_yields = rb_assoc_new(next_token, rb_ary_entry(yields, 1));
+
+ if (parse_lex_data->freeze) {
+ rb_obj_freeze(next_token);
+ rb_obj_freeze(next_yields);
+ }
+
+ rb_ary_push(next_tokens, next_yields);
}
+
+ rb_ary_replace(parse_lex_data->tokens, next_tokens);
}
/**
@@ -599,13 +730,14 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod
pm_parser_register_encoding_changed_callback(&parser, parse_lex_encoding_changed_callback);
VALUE source_string = rb_str_new((const char *) pm_string_source(input), pm_string_length(input));
- VALUE offsets = rb_ary_new();
+ VALUE offsets = rb_ary_new_capa(parser.newline_list.size);
VALUE source = rb_funcall(rb_cPrismSource, rb_id_source_for, 3, source_string, LONG2NUM(parser.start_line), offsets);
parse_lex_data_t parse_lex_data = {
.source = source,
.tokens = rb_ary_new(),
- .encoding = rb_utf8_encoding()
+ .encoding = rb_utf8_encoding(),
+ .freeze = options->freeze,
};
parse_lex_data_t *data = &parse_lex_data;
@@ -628,16 +760,24 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod
rb_ary_push(offsets, ULONG2NUM(parser.newline_list.offsets[index]));
}
- VALUE value;
+ if (options->freeze) {
+ rb_obj_freeze(source_string);
+ rb_obj_freeze(offsets);
+ rb_obj_freeze(source);
+ rb_obj_freeze(parse_lex_data.tokens);
+ }
+
+ VALUE result;
if (return_nodes) {
- value = rb_ary_new_capa(2);
- rb_ary_push(value, pm_ast_new(&parser, node, parse_lex_data.encoding, source));
+ VALUE value = rb_ary_new_capa(2);
+ rb_ary_push(value, pm_ast_new(&parser, node, parse_lex_data.encoding, source, options->freeze));
rb_ary_push(value, parse_lex_data.tokens);
+ if (options->freeze) rb_obj_freeze(value);
+ result = parse_result_create(rb_cPrismParseLexResult, &parser, value, parse_lex_data.encoding, source, options->freeze);
} else {
- value = parse_lex_data.tokens;
+ result = parse_result_create(rb_cPrismLexResult, &parser, parse_lex_data.tokens, parse_lex_data.encoding, source, options->freeze);
}
- VALUE result = parse_result_create(rb_cPrismParseLexResult, &parser, value, parse_lex_data.encoding, source);
pm_node_destroy(&parser, node);
pm_parser_free(&parser);
@@ -646,10 +786,10 @@ parse_lex_input(pm_string_t *input, const pm_options_t *options, bool return_nod
/**
* call-seq:
- * Prism::lex(source, **options) -> Array
+ * Prism::lex(source, **options) -> LexResult
*
- * Return an array of Token instances corresponding to the given string. For
- * supported options, see Prism::parse.
+ * Return a LexResult instance that contains an array of Token instances
+ * corresponding to the given string. For supported options, see Prism::parse.
*/
static VALUE
lex(int argc, VALUE *argv, VALUE self) {
@@ -666,17 +806,18 @@ lex(int argc, VALUE *argv, VALUE self) {
/**
* call-seq:
- * Prism::lex_file(filepath, **options) -> Array
+ * Prism::lex_file(filepath, **options) -> LexResult
*
- * Return an array of Token instances corresponding to the given file. For
- * supported options, see Prism::parse.
+ * Return a LexResult instance that contains an array of Token instances
+ * corresponding to the given file. For supported options, see Prism::parse.
*/
static VALUE
lex_file(int argc, VALUE *argv, VALUE self) {
pm_string_t input;
pm_options_t options = { 0 };
- file_options(argc, argv, &input, &options);
+ VALUE encoded_filepath;
+ file_options(argc, argv, &input, &options, &encoded_filepath);
VALUE value = parse_lex_input(&input, &options, false);
pm_string_free(&input);
@@ -700,9 +841,13 @@ parse_input(pm_string_t *input, const pm_options_t *options) {
pm_node_t *node = pm_parse(&parser);
rb_encoding *encoding = rb_enc_find(parser.encoding->name);
- VALUE source = pm_source_new(&parser, encoding);
- VALUE value = pm_ast_new(&parser, node, encoding, source);
- VALUE result = parse_result_create(rb_cPrismParseResult, &parser, value, encoding, source) ;
+ VALUE source = pm_source_new(&parser, encoding, options->freeze);
+ VALUE value = pm_ast_new(&parser, node, encoding, source, options->freeze);
+ VALUE result = parse_result_create(rb_cPrismParseResult, &parser, value, encoding, source, options->freeze);
+
+ if (options->freeze) {
+ rb_obj_freeze(source);
+ }
pm_node_destroy(&parser, node);
pm_parser_free(&parser);
@@ -724,18 +869,33 @@ parse_input(pm_string_t *input, const pm_options_t *options) {
* encoding or nil.
* * `filepath` - the filepath of the source being parsed. This should be a
* string or nil.
+ * * `freeze` - whether or not to deeply freeze the AST. This should be a
+ * boolean or nil.
* * `frozen_string_literal` - whether or not the frozen string literal pragma
* has been set. This should be a boolean or nil.
* * `line` - the line number that the parse starts on. This should be an
* integer or nil. Note that this is 1-indexed.
+ * * `main_script` - a boolean indicating whether or not the source being parsed
+ * is the main script being run by the interpreter. This controls whether
+ * or not shebangs are parsed for additional flags and whether or not the
+ * parser will attempt to find a matching shebang if the first one does
+ * not contain the word "ruby".
+ * * `partial_script` - when the file being parsed is considered a "partial"
+ * script, jumps will not be marked as errors if they are not contained
+ * within loops/blocks. This is used in the case that you're parsing a
+ * script that you know will be embedded inside another script later, but
+ * you do not have that context yet. For example, when parsing an ERB
+ * template that will be evaluated inside another script.
* * `scopes` - the locals that are in scope surrounding the code that is being
* parsed. This should be an array of arrays of symbols or nil. Scopes are
* ordered from the outermost scope to the innermost one.
* * `version` - the version of Ruby syntax that prism should used to parse Ruby
- * code. By default prism assumes you want to parse with the latest version
- * of Ruby syntax (which you can trigger with `nil` or `"latest"`). You
- * may also restrict the syntax to a specific version of Ruby. The
- * supported values are `"3.3.0"` and `"3.4.0"`.
+ * code. By default prism assumes you want to parse with the latest
+ * version of Ruby syntax (which you can trigger with `nil` or
+ * `"latest"`). You may also restrict the syntax to a specific version of
+ * Ruby, e.g., with `"3.3.0"`. To parse with the same syntax version that
+ * the current Ruby is running use `version: "current"`. Raises
+ * ArgumentError if the version is not currently supported by Prism.
*/
static VALUE
parse(int argc, VALUE *argv, VALUE self) {
@@ -773,7 +933,8 @@ parse_file(int argc, VALUE *argv, VALUE self) {
pm_string_t input;
pm_options_t options = { 0 };
- file_options(argc, argv, &input, &options);
+ VALUE encoded_filepath;
+ file_options(argc, argv, &input, &options, &encoded_filepath);
VALUE value = parse_input(&input, &options);
pm_string_free(&input);
@@ -829,7 +990,9 @@ profile_file(int argc, VALUE *argv, VALUE self) {
pm_string_t input;
pm_options_t options = { 0 };
- file_options(argc, argv, &input, &options);
+ VALUE encoded_filepath;
+ file_options(argc, argv, &input, &options, &encoded_filepath);
+
profile_input(&input, &options);
pm_string_free(&input);
pm_options_free(&options);
@@ -837,6 +1000,14 @@ profile_file(int argc, VALUE *argv, VALUE self) {
return Qnil;
}
+static int
+parse_stream_eof(void *stream) {
+ if (rb_funcall((VALUE) stream, rb_intern("eof?"), 0)) {
+ return 1;
+ }
+ return 0;
+}
+
/**
* An implementation of fgets that is suitable for use with Ruby IO objects.
*/
@@ -849,8 +1020,8 @@ parse_stream_fgets(char *string, int size, void *stream) {
return NULL;
}
- const char *cstr = StringValueCStr(line);
- size_t length = strlen(cstr);
+ const char *cstr = RSTRING_PTR(line);
+ long length = RSTRING_LEN(line);
memcpy(string, cstr, length);
string[length] = '\0';
@@ -877,12 +1048,12 @@ parse_stream(int argc, VALUE *argv, VALUE self) {
pm_parser_t parser;
pm_buffer_t buffer;
- pm_node_t *node = pm_parse_stream(&parser, &buffer, (void *) stream, parse_stream_fgets, &options);
+ pm_node_t *node = pm_parse_stream(&parser, &buffer, (void *) stream, parse_stream_fgets, parse_stream_eof, &options);
rb_encoding *encoding = rb_enc_find(parser.encoding->name);
- VALUE source = pm_source_new(&parser, encoding);
- VALUE value = pm_ast_new(&parser, node, encoding, source);
- VALUE result = parse_result_create(rb_cPrismParseResult, &parser, value, encoding, source);
+ VALUE source = pm_source_new(&parser, encoding, options.freeze);
+ VALUE value = pm_ast_new(&parser, node, encoding, source, options.freeze);
+ VALUE result = parse_result_create(rb_cPrismParseResult, &parser, value, encoding, source, options.freeze);
pm_node_destroy(&parser, node);
pm_buffer_free(&buffer);
@@ -902,8 +1073,8 @@ parse_input_comments(pm_string_t *input, const pm_options_t *options) {
pm_node_t *node = pm_parse(&parser);
rb_encoding *encoding = rb_enc_find(parser.encoding->name);
- VALUE source = pm_source_new(&parser, encoding);
- VALUE comments = parser_comments(&parser, source);
+ VALUE source = pm_source_new(&parser, encoding, options->freeze);
+ VALUE comments = parser_comments(&parser, source, options->freeze);
pm_node_destroy(&parser, node);
pm_parser_free(&parser);
@@ -943,7 +1114,8 @@ parse_file_comments(int argc, VALUE *argv, VALUE self) {
pm_string_t input;
pm_options_t options = { 0 };
- file_options(argc, argv, &input, &options);
+ VALUE encoded_filepath;
+ file_options(argc, argv, &input, &options, &encoded_filepath);
VALUE value = parse_input_comments(&input, &options);
pm_string_free(&input);
@@ -954,9 +1126,9 @@ parse_file_comments(int argc, VALUE *argv, VALUE self) {
/**
* call-seq:
- * Prism::parse_lex(source, **options) -> ParseResult
+ * Prism::parse_lex(source, **options) -> ParseLexResult
*
- * Parse the given string and return a ParseResult instance that contains a
+ * Parse the given string and return a ParseLexResult instance that contains a
* 2-element array, where the first element is the AST and the second element is
* an array of Token instances.
*
@@ -981,9 +1153,9 @@ parse_lex(int argc, VALUE *argv, VALUE self) {
/**
* call-seq:
- * Prism::parse_lex_file(filepath, **options) -> ParseResult
+ * Prism::parse_lex_file(filepath, **options) -> ParseLexResult
*
- * Parse the given file and return a ParseResult instance that contains a
+ * Parse the given file and return a ParseLexResult instance that contains a
* 2-element array, where the first element is the AST and the second element is
* an array of Token instances.
*
@@ -998,7 +1170,8 @@ parse_lex_file(int argc, VALUE *argv, VALUE self) {
pm_string_t input;
pm_options_t options = { 0 };
- file_options(argc, argv, &input, &options);
+ VALUE encoded_filepath;
+ file_options(argc, argv, &input, &options, &encoded_filepath);
VALUE value = parse_lex_input(&input, &options, true);
pm_string_free(&input);
@@ -1068,7 +1241,8 @@ parse_file_success_p(int argc, VALUE *argv, VALUE self) {
pm_string_t input;
pm_options_t options = { 0 };
- file_options(argc, argv, &input, &options);
+ VALUE encoded_filepath;
+ file_options(argc, argv, &input, &options, &encoded_filepath);
VALUE result = parse_input_success_p(&input, &options);
pm_string_free(&input);
@@ -1090,6 +1264,68 @@ parse_file_failure_p(int argc, VALUE *argv, VALUE self) {
}
/******************************************************************************/
+/* String query methods */
+/******************************************************************************/
+
+/**
+ * Process the result of a call to a string query method and return an
+ * appropriate value.
+ */
+static VALUE
+string_query(pm_string_query_t result) {
+ switch (result) {
+ case PM_STRING_QUERY_ERROR:
+ rb_raise(rb_eArgError, "Invalid or non ascii-compatible encoding");
+ return Qfalse;
+ case PM_STRING_QUERY_FALSE:
+ return Qfalse;
+ case PM_STRING_QUERY_TRUE:
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+/**
+ * call-seq:
+ * Prism::StringQuery::local?(string) -> bool
+ *
+ * Returns true if the string constitutes a valid local variable name. Note that
+ * this means the names that can be set through Binding#local_variable_set, not
+ * necessarily the ones that can be set through a local variable assignment.
+ */
+static VALUE
+string_query_local_p(VALUE self, VALUE string) {
+ const uint8_t *source = (const uint8_t *) check_string(string);
+ return string_query(pm_string_query_local(source, RSTRING_LEN(string), rb_enc_get(string)->name));
+}
+
+/**
+ * call-seq:
+ * Prism::StringQuery::constant?(string) -> bool
+ *
+ * Returns true if the string constitutes a valid constant name. Note that this
+ * means the names that can be set through Module#const_set, not necessarily the
+ * ones that can be set through a constant assignment.
+ */
+static VALUE
+string_query_constant_p(VALUE self, VALUE string) {
+ const uint8_t *source = (const uint8_t *) check_string(string);
+ return string_query(pm_string_query_constant(source, RSTRING_LEN(string), rb_enc_get(string)->name));
+}
+
+/**
+ * call-seq:
+ * Prism::StringQuery::method_name?(string) -> bool
+ *
+ * Returns true if the string constitutes a valid method name.
+ */
+static VALUE
+string_query_method_name_p(VALUE self, VALUE string) {
+ const uint8_t *source = (const uint8_t *) check_string(string);
+ return string_query(pm_string_query_method_name(source, RSTRING_LEN(string), rb_enc_get(string)->name));
+}
+
+/******************************************************************************/
/* Initialization of the extension */
/******************************************************************************/
@@ -1109,6 +1345,11 @@ Init_prism(void) {
);
}
+#ifdef HAVE_RB_EXT_RACTOR_SAFE
+ // Mark this extension as Ractor-safe.
+ rb_ext_ractor_safe(true);
+#endif
+
// Grab up references to all of the constants that we're going to need to
// reference throughout this extension.
rb_cPrism = rb_define_module("Prism");
@@ -1124,23 +1365,35 @@ Init_prism(void) {
rb_cPrismParseWarning = rb_define_class_under(rb_cPrism, "ParseWarning", rb_cObject);
rb_cPrismResult = rb_define_class_under(rb_cPrism, "Result", rb_cObject);
rb_cPrismParseResult = rb_define_class_under(rb_cPrism, "ParseResult", rb_cPrismResult);
+ rb_cPrismLexResult = rb_define_class_under(rb_cPrism, "LexResult", rb_cPrismResult);
rb_cPrismParseLexResult = rb_define_class_under(rb_cPrism, "ParseLexResult", rb_cPrismResult);
+ rb_cPrismStringQuery = rb_define_class_under(rb_cPrism, "StringQuery", rb_cObject);
+ rb_cPrismScope = rb_define_class_under(rb_cPrism, "Scope", rb_cObject);
+
+ rb_cPrismCurrentVersionError = rb_const_get(rb_cPrism, rb_intern("CurrentVersionError"));
// Intern all of the IDs eagerly that we support so that we don't have to do
// it every time we parse.
rb_id_option_command_line = rb_intern_const("command_line");
rb_id_option_encoding = rb_intern_const("encoding");
rb_id_option_filepath = rb_intern_const("filepath");
+ rb_id_option_freeze = rb_intern_const("freeze");
rb_id_option_frozen_string_literal = rb_intern_const("frozen_string_literal");
rb_id_option_line = rb_intern_const("line");
+ rb_id_option_main_script = rb_intern_const("main_script");
+ rb_id_option_partial_script = rb_intern_const("partial_script");
rb_id_option_scopes = rb_intern_const("scopes");
rb_id_option_version = rb_intern_const("version");
rb_id_source_for = rb_intern("for");
+ rb_id_forwarding_positionals = rb_intern("*");
+ rb_id_forwarding_keywords = rb_intern("**");
+ rb_id_forwarding_block = rb_intern("&");
+ rb_id_forwarding_all = rb_intern("...");
/**
* The version of the prism library.
*/
- rb_define_const(rb_cPrism, "VERSION", rb_str_new2(EXPECTED_PRISM_VERSION));
+ rb_define_const(rb_cPrism, "VERSION", rb_str_freeze(rb_str_new_cstr(EXPECTED_PRISM_VERSION)));
// First, the functions that have to do with lexing and parsing.
rb_define_singleton_method(rb_cPrism, "lex", lex, -1);
@@ -1164,6 +1417,10 @@ Init_prism(void) {
rb_define_singleton_method(rb_cPrism, "dump_file", dump_file, -1);
#endif
+ rb_define_singleton_method(rb_cPrismStringQuery, "local?", string_query_local_p, 1);
+ rb_define_singleton_method(rb_cPrismStringQuery, "constant?", string_query_constant_p, 1);
+ rb_define_singleton_method(rb_cPrismStringQuery, "method_name?", string_query_method_name_p, 1);
+
// Next, initialize the other APIs.
Init_prism_api_node();
Init_prism_pack();
diff --git a/prism/extension.h b/prism/extension.h
index b15a2c5e61..510faa48e8 100644
--- a/prism/extension.h
+++ b/prism/extension.h
@@ -1,19 +1,19 @@
#ifndef PRISM_EXT_NODE_H
#define PRISM_EXT_NODE_H
-#define EXPECTED_PRISM_VERSION "0.29.0"
+#define EXPECTED_PRISM_VERSION "1.8.0"
#include <ruby.h>
#include <ruby/encoding.h>
#include "prism.h"
-VALUE pm_source_new(const pm_parser_t *parser, rb_encoding *encoding);
-VALUE pm_token_new(const pm_parser_t *parser, const pm_token_t *token, rb_encoding *encoding, VALUE source);
-VALUE pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encoding, VALUE source);
+VALUE pm_source_new(const pm_parser_t *parser, rb_encoding *encoding, bool freeze);
+VALUE pm_token_new(const pm_parser_t *parser, const pm_token_t *token, rb_encoding *encoding, VALUE source, bool freeze);
+VALUE pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encoding, VALUE source, bool freeze);
VALUE pm_integer_new(const pm_integer_t *integer);
void Init_prism_api_node(void);
void Init_prism_pack(void);
-PRISM_EXPORTED_FUNCTION void Init_prism(void);
+RUBY_FUNC_EXPORTED void Init_prism(void);
#endif
diff --git a/prism/options.c b/prism/options.c
index 664db4f061..09d2a65a6c 100644
--- a/prism/options.c
+++ b/prism/options.c
@@ -1,6 +1,15 @@
#include "prism/options.h"
/**
+ * Set the shebang callback option on the given options struct.
+ */
+PRISM_EXPORTED_FUNCTION void
+pm_options_shebang_callback_set(pm_options_t *options, pm_options_shebang_callback_t shebang_callback, void *shebang_callback_data) {
+ options->shebang_callback = shebang_callback;
+ options->shebang_callback_data = shebang_callback_data;
+}
+
+/**
* Set the filepath option on the given options struct.
*/
PRISM_EXPORTED_FUNCTION void
@@ -17,6 +26,14 @@ pm_options_encoding_set(pm_options_t *options, const char *encoding) {
}
/**
+ * Set the encoding_locked option on the given options struct.
+ */
+PRISM_EXPORTED_FUNCTION void
+pm_options_encoding_locked_set(pm_options_t *options, bool encoding_locked) {
+ options->encoding_locked = encoding_locked;
+}
+
+/**
* Set the line option on the given options struct.
*/
PRISM_EXPORTED_FUNCTION void
@@ -41,46 +58,103 @@ pm_options_command_line_set(pm_options_t *options, uint8_t command_line) {
}
/**
+ * Checks if the given slice represents a number.
+ */
+static inline bool
+is_number(const char *string, size_t length) {
+ return pm_strspn_decimal_digit((const uint8_t *) string, (ptrdiff_t) length) == length;
+}
+
+/**
* Set the version option on the given options struct by parsing the given
* string. If the string contains an invalid option, this returns false.
* Otherwise, it returns true.
*/
PRISM_EXPORTED_FUNCTION bool
pm_options_version_set(pm_options_t *options, const char *version, size_t length) {
- switch (length) {
- case 0:
- if (version == NULL) {
- options->version = PM_OPTIONS_VERSION_LATEST;
- return true;
- }
+ if (version == NULL) {
+ options->version = PM_OPTIONS_VERSION_LATEST;
+ return true;
+ }
- return false;
- case 5:
- assert(version != NULL);
+ if (length == 3) {
+ if (strncmp(version, "3.3", 3) == 0) {
+ options->version = PM_OPTIONS_VERSION_CRUBY_3_3;
+ return true;
+ }
- if ((strncmp(version, "3.3.0", length) == 0) || (strncmp(version, "3.3.1", length) == 0)) {
- options->version = PM_OPTIONS_VERSION_CRUBY_3_3;
- return true;
- }
+ if (strncmp(version, "3.4", 3) == 0) {
+ options->version = PM_OPTIONS_VERSION_CRUBY_3_4;
+ return true;
+ }
- if (strncmp(version, "3.4.0", length) == 0) {
- options->version = PM_OPTIONS_VERSION_LATEST;
- return true;
- }
+ if (strncmp(version, "3.5", 3) == 0 || strncmp(version, "4.0", 3) == 0) {
+ options->version = PM_OPTIONS_VERSION_CRUBY_4_0;
+ return true;
+ }
- return false;
- case 6:
- assert(version != NULL);
+ if (strncmp(version, "4.1", 3) == 0) {
+ options->version = PM_OPTIONS_VERSION_CRUBY_4_1;
+ return true;
+ }
- if (strncmp(version, "latest", length) == 0) {
- options->version = PM_OPTIONS_VERSION_LATEST;
- return true;
- }
+ return false;
+ }
+
+ if (length >= 4 && is_number(version + 4, length - 4)) {
+ if (strncmp(version, "3.3.", 4) == 0) {
+ options->version = PM_OPTIONS_VERSION_CRUBY_3_3;
+ return true;
+ }
+
+ if (strncmp(version, "3.4.", 4) == 0) {
+ options->version = PM_OPTIONS_VERSION_CRUBY_3_4;
+ return true;
+ }
- return false;
- default:
- return false;
+ if (strncmp(version, "3.5.", 4) == 0 || strncmp(version, "4.0.", 4) == 0) {
+ options->version = PM_OPTIONS_VERSION_CRUBY_4_0;
+ return true;
+ }
+
+ if (strncmp(version, "4.1.", 4) == 0) {
+ options->version = PM_OPTIONS_VERSION_CRUBY_4_1;
+ return true;
+ }
}
+
+ if (length >= 6) {
+ if (strncmp(version, "latest", 7) == 0) { // 7 to compare the \0 as well
+ options->version = PM_OPTIONS_VERSION_LATEST;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * Set the main script option on the given options struct.
+ */
+PRISM_EXPORTED_FUNCTION void
+pm_options_main_script_set(pm_options_t *options, bool main_script) {
+ options->main_script = main_script;
+}
+
+/**
+ * Set the partial script option on the given options struct.
+ */
+PRISM_EXPORTED_FUNCTION void
+pm_options_partial_script_set(pm_options_t *options, bool partial_script) {
+ options->partial_script = partial_script;
+}
+
+/**
+ * Set the freeze option on the given options struct.
+ */
+PRISM_EXPORTED_FUNCTION void
+pm_options_freeze_set(pm_options_t *options, bool freeze) {
+ options->freeze = freeze;
}
// For some reason, GCC analyzer thinks we're leaking allocated scopes and
@@ -117,6 +191,7 @@ PRISM_EXPORTED_FUNCTION bool
pm_options_scope_init(pm_options_scope_t *scope, size_t locals_count) {
scope->locals_count = locals_count;
scope->locals = xcalloc(locals_count, sizeof(pm_string_t));
+ scope->forwarding = PM_OPTIONS_SCOPE_FORWARDING_NONE;
return scope->locals != NULL;
}
@@ -129,6 +204,14 @@ pm_options_scope_local_get(const pm_options_scope_t *scope, size_t index) {
}
/**
+ * Set the forwarding option on the given scope struct.
+ */
+PRISM_EXPORTED_FUNCTION void
+pm_options_scope_forwarding_set(pm_options_scope_t *scope, uint8_t forwarding) {
+ scope->forwarding = forwarding;
+}
+
+/**
* Free the internal memory associated with the options.
*/
PRISM_EXPORTED_FUNCTION void
@@ -215,6 +298,10 @@ pm_options_read(pm_options_t *options, const char *data) {
options->frozen_string_literal = (int8_t) *data++;
options->command_line = (uint8_t) *data++;
options->version = (pm_options_version_t) *data++;
+ options->encoding_locked = ((uint8_t) *data++) > 0;
+ options->main_script = ((uint8_t) *data++) > 0;
+ options->partial_script = ((uint8_t) *data++) > 0;
+ options->freeze = ((uint8_t) *data++) > 0;
uint32_t scopes_count = pm_options_read_u32(data);
data += 4;
@@ -232,6 +319,9 @@ pm_options_read(pm_options_t *options, const char *data) {
return;
}
+ uint8_t forwarding = (uint8_t) *data++;
+ pm_options_scope_forwarding_set(&options->scopes[scope_index], forwarding);
+
for (size_t local_index = 0; local_index < locals_count; local_index++) {
uint32_t local_length = pm_options_read_u32(data);
data += 4;
diff --git a/prism/options.h b/prism/options.h
index a623ae0b83..c00c7bf755 100644
--- a/prism/options.h
+++ b/prism/options.h
@@ -7,6 +7,7 @@
#define PRISM_OPTIONS_H
#include "prism/defines.h"
+#include "prism/util/pm_char.h"
#include "prism/util/pm_string.h"
#include <stdbool.h>
@@ -38,25 +39,87 @@ typedef struct pm_options_scope {
/** The names of the locals in the scope. */
pm_string_t *locals;
+
+ /** Flags for the set of forwarding parameters in this scope. */
+ uint8_t forwarding;
} pm_options_scope_t;
+/** The default value for parameters. */
+static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_NONE = 0x0;
+
+/** When the scope is fowarding with the * parameter. */
+static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_POSITIONALS = 0x1;
+
+/** When the scope is fowarding with the ** parameter. */
+static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_KEYWORDS = 0x2;
+
+/** When the scope is fowarding with the & parameter. */
+static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_BLOCK = 0x4;
+
+/** When the scope is fowarding with the ... parameter. */
+static const uint8_t PM_OPTIONS_SCOPE_FORWARDING_ALL = 0x8;
+
+// Forward declaration needed by the callback typedef.
+struct pm_options;
+
+/**
+ * The callback called when additional switches are found in a shebang comment
+ * that need to be processed by the runtime.
+ *
+ * @param options The options struct that may be updated by this callback.
+ * Certain fields will be checked for changes, specifically encoding,
+ * command_line, and frozen_string_literal.
+ * @param source The source of the shebang comment.
+ * @param length The length of the source.
+ * @param shebang_callback_data Any additional data that should be passed along
+ * to the callback.
+ */
+typedef void (*pm_options_shebang_callback_t)(struct pm_options *options, const uint8_t *source, size_t length, void *shebang_callback_data);
+
/**
* The version of Ruby syntax that we should be parsing with. This is used to
* allow consumers to specify which behavior they want in case they need to
* parse in the same way as a specific version of CRuby would have.
*/
typedef enum {
- /** The current version of prism. */
- PM_OPTIONS_VERSION_LATEST = 0,
+ /** If an explicit version is not provided, the current version of prism will be used. */
+ PM_OPTIONS_VERSION_UNSET = 0,
/** The vendored version of prism in CRuby 3.3.x. */
- PM_OPTIONS_VERSION_CRUBY_3_3 = 1
+ PM_OPTIONS_VERSION_CRUBY_3_3 = 1,
+
+ /** The vendored version of prism in CRuby 3.4.x. */
+ PM_OPTIONS_VERSION_CRUBY_3_4 = 2,
+
+ /** The vendored version of prism in CRuby 4.0.x. */
+ PM_OPTIONS_VERSION_CRUBY_3_5 = 3,
+
+ /** The vendored version of prism in CRuby 4.0.x. */
+ PM_OPTIONS_VERSION_CRUBY_4_0 = 3,
+
+ /** The vendored version of prism in CRuby 4.1.x. */
+ PM_OPTIONS_VERSION_CRUBY_4_1 = 4,
+
+ /** The current version of prism. */
+ PM_OPTIONS_VERSION_LATEST = PM_OPTIONS_VERSION_CRUBY_4_1
} pm_options_version_t;
/**
* The options that can be passed to the parser.
*/
-typedef struct {
+typedef struct pm_options {
+ /**
+ * The callback to call when additional switches are found in a shebang
+ * comment.
+ */
+ pm_options_shebang_callback_t shebang_callback;
+
+ /**
+ * Any additional data that should be passed along to the shebang callback
+ * if one was set.
+ */
+ void *shebang_callback_data;
+
/** The name of the file that is currently being parsed. */
pm_string_t filepath;
@@ -103,6 +166,37 @@ typedef struct {
* - PM_OPTIONS_FROZEN_STRING_LITERAL_UNSET
*/
int8_t frozen_string_literal;
+
+ /**
+ * Whether or not the encoding magic comments should be respected. This is a
+ * niche use-case where you want to parse a file with a specific encoding
+ * but ignore any encoding magic comments at the top of the file.
+ */
+ bool encoding_locked;
+
+ /**
+ * When the file being parsed is the main script, the shebang will be
+ * considered for command-line flags (or for implicit -x). The caller needs
+ * to pass this information to the parser so that it can behave correctly.
+ */
+ bool main_script;
+
+ /**
+ * When the file being parsed is considered a "partial" script, jumps will
+ * not be marked as errors if they are not contained within loops/blocks.
+ * This is used in the case that you're parsing a script that you know will
+ * be embedded inside another script later, but you do not have that context
+ * yet. For example, when parsing an ERB template that will be evaluated
+ * inside another script.
+ */
+ bool partial_script;
+
+ /**
+ * Whether or not the parser should freeze the nodes that it creates. This
+ * makes it possible to have a deeply frozen AST that is safe to share
+ * between concurrency primitives.
+ */
+ bool freeze;
} pm_options_t;
/**
@@ -143,10 +237,24 @@ static const uint8_t PM_OPTIONS_COMMAND_LINE_P = 0x10;
static const uint8_t PM_OPTIONS_COMMAND_LINE_X = 0x20;
/**
+ * Set the shebang callback option on the given options struct.
+ *
+ * @param options The options struct to set the shebang callback on.
+ * @param shebang_callback The shebang callback to set.
+ * @param shebang_callback_data Any additional data that should be passed along
+ * to the callback.
+ *
+ * \public \memberof pm_options
+ */
+PRISM_EXPORTED_FUNCTION void pm_options_shebang_callback_set(pm_options_t *options, pm_options_shebang_callback_t shebang_callback, void *shebang_callback_data);
+
+/**
* Set the filepath option on the given options struct.
*
* @param options The options struct to set the filepath on.
* @param filepath The filepath to set.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION void pm_options_filepath_set(pm_options_t *options, const char *filepath);
@@ -155,6 +263,8 @@ PRISM_EXPORTED_FUNCTION void pm_options_filepath_set(pm_options_t *options, cons
*
* @param options The options struct to set the line on.
* @param line The line to set.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION void pm_options_line_set(pm_options_t *options, int32_t line);
@@ -163,14 +273,28 @@ PRISM_EXPORTED_FUNCTION void pm_options_line_set(pm_options_t *options, int32_t
*
* @param options The options struct to set the encoding on.
* @param encoding The encoding to set.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION void pm_options_encoding_set(pm_options_t *options, const char *encoding);
/**
+ * Set the encoding_locked option on the given options struct.
+ *
+ * @param options The options struct to set the encoding_locked value on.
+ * @param encoding_locked The encoding_locked value to set.
+ *
+ * \public \memberof pm_options
+ */
+PRISM_EXPORTED_FUNCTION void pm_options_encoding_locked_set(pm_options_t *options, bool encoding_locked);
+
+/**
* Set the frozen string literal option on the given options struct.
*
* @param options The options struct to set the frozen string literal value on.
* @param frozen_string_literal The frozen string literal value to set.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION void pm_options_frozen_string_literal_set(pm_options_t *options, bool frozen_string_literal);
@@ -179,6 +303,8 @@ PRISM_EXPORTED_FUNCTION void pm_options_frozen_string_literal_set(pm_options_t *
*
* @param options The options struct to set the command line option on.
* @param command_line The command_line value to set.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION void pm_options_command_line_set(pm_options_t *options, uint8_t command_line);
@@ -191,15 +317,49 @@ PRISM_EXPORTED_FUNCTION void pm_options_command_line_set(pm_options_t *options,
* @param version The version to set.
* @param length The length of the version string.
* @return Whether or not the version was parsed successfully.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION bool pm_options_version_set(pm_options_t *options, const char *version, size_t length);
/**
+ * Set the main script option on the given options struct.
+ *
+ * @param options The options struct to set the main script value on.
+ * @param main_script The main script value to set.
+ *
+ * \public \memberof pm_options
+ */
+PRISM_EXPORTED_FUNCTION void pm_options_main_script_set(pm_options_t *options, bool main_script);
+
+/**
+ * Set the partial script option on the given options struct.
+ *
+ * @param options The options struct to set the partial script value on.
+ * @param partial_script The partial script value to set.
+ *
+ * \public \memberof pm_options
+ */
+PRISM_EXPORTED_FUNCTION void pm_options_partial_script_set(pm_options_t *options, bool partial_script);
+
+/**
+ * Set the freeze option on the given options struct.
+ *
+ * @param options The options struct to set the freeze value on.
+ * @param freeze The freeze value to set.
+ *
+ * \public \memberof pm_options
+ */
+PRISM_EXPORTED_FUNCTION void pm_options_freeze_set(pm_options_t *options, bool freeze);
+
+/**
* Allocate and zero out the scopes array on the given options struct.
*
* @param options The options struct to initialize the scopes array on.
* @param scopes_count The number of scopes to allocate.
* @return Whether or not the scopes array was initialized successfully.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION bool pm_options_scopes_init(pm_options_t *options, size_t scopes_count);
@@ -209,6 +369,8 @@ PRISM_EXPORTED_FUNCTION bool pm_options_scopes_init(pm_options_t *options, size_
* @param options The options struct to get the scope from.
* @param index The index of the scope to get.
* @return A pointer to the scope at the given index.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION const pm_options_scope_t * pm_options_scope_get(const pm_options_t *options, size_t index);
@@ -219,6 +381,8 @@ PRISM_EXPORTED_FUNCTION const pm_options_scope_t * pm_options_scope_get(const pm
* @param scope The scope struct to initialize.
* @param locals_count The number of locals to allocate.
* @return Whether or not the scope was initialized successfully.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION bool pm_options_scope_init(pm_options_scope_t *scope, size_t locals_count);
@@ -228,13 +392,27 @@ PRISM_EXPORTED_FUNCTION bool pm_options_scope_init(pm_options_scope_t *scope, si
* @param scope The scope struct to get the local from.
* @param index The index of the local to get.
* @return A pointer to the local at the given index.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION const pm_string_t * pm_options_scope_local_get(const pm_options_scope_t *scope, size_t index);
/**
+ * Set the forwarding option on the given scope struct.
+ *
+ * @param scope The scope struct to set the forwarding on.
+ * @param forwarding The forwarding value to set.
+ *
+ * \public \memberof pm_options
+ */
+PRISM_EXPORTED_FUNCTION void pm_options_scope_forwarding_set(pm_options_scope_t *scope, uint8_t forwarding);
+
+/**
* Free the internal memory associated with the options.
*
* @param options The options struct whose internal memory should be freed.
+ *
+ * \public \memberof pm_options
*/
PRISM_EXPORTED_FUNCTION void pm_options_free(pm_options_t *options);
@@ -261,6 +439,10 @@ PRISM_EXPORTED_FUNCTION void pm_options_free(pm_options_t *options);
* | `1` | -l command line option |
* | `1` | -a command line option |
* | `1` | the version |
+ * | `1` | encoding locked |
+ * | `1` | main script |
+ * | `1` | partial script |
+ * | `1` | freeze |
* | `4` | the number of scopes |
* | ... | the scopes |
*
@@ -276,6 +458,7 @@ PRISM_EXPORTED_FUNCTION void pm_options_free(pm_options_t *options);
* | # bytes | field |
* | ------- | -------------------------- |
* | `4` | the number of locals |
+ * | `1` | the forwarding flags |
* | ... | the locals |
*
* Each local is laid out as follows:
@@ -293,8 +476,8 @@ PRISM_EXPORTED_FUNCTION void pm_options_free(pm_options_t *options);
* * The encoding can have a length of 0, in which case we'll use the default
* encoding (UTF-8). If it's not 0, it should correspond to a name of an
* encoding that can be passed to `Encoding.find` in Ruby.
- * * The frozen string literal and suppress warnings fields are booleans, so
- * their values should be either 0 or 1.
+ * * The frozen string literal, encoding locked, main script, and partial script
+ * fields are booleans, so their values should be either 0 or 1.
* * The number of scopes can be 0.
*
* @param options The options struct to deserialize into.
diff --git a/prism/parser.h b/prism/parser.h
index 2bae4b0ac3..95d7aac710 100644
--- a/prism/parser.h
+++ b/prism/parser.h
@@ -83,6 +83,23 @@ typedef enum {
} pm_heredoc_indent_t;
/**
+ * All of the information necessary to store to lexing a heredoc.
+ */
+typedef struct {
+ /** A pointer to the start of the heredoc identifier. */
+ const uint8_t *ident_start;
+
+ /** The length of the heredoc identifier. */
+ size_t ident_length;
+
+ /** The type of quote that the heredoc uses. */
+ pm_heredoc_quote_t quote;
+
+ /** The type of indentation that the heredoc uses. */
+ pm_heredoc_indent_t indent;
+} pm_heredoc_lex_mode_t;
+
+/**
* When lexing Ruby source, the lexer has a small amount of state to tell which
* kind of token it is currently lexing. For example, when we find the start of
* a string, the first token that we return is a TOKEN_STRING_BEGIN token. After
@@ -210,17 +227,10 @@ typedef struct pm_lex_mode {
} string;
struct {
- /** A pointer to the start of the heredoc identifier. */
- const uint8_t *ident_start;
-
- /** The length of the heredoc identifier. */
- size_t ident_length;
-
- /** The type of quote that the heredoc uses. */
- pm_heredoc_quote_t quote;
-
- /** The type of indentation that the heredoc uses. */
- pm_heredoc_indent_t indent;
+ /**
+ * All of the data necessary to lex a heredoc.
+ */
+ pm_heredoc_lex_mode_t base;
/**
* This is the pointer to the character where lexing should resume
@@ -233,7 +243,7 @@ typedef struct pm_lex_mode {
* line so that we know how much to dedent each line in the case of
* a tilde heredoc.
*/
- size_t common_whitespace;
+ size_t *common_whitespace;
/** True if the previous token ended with a line continuation. */
bool line_continuation;
@@ -289,6 +299,9 @@ typedef enum {
/** a rescue else statement within a do..end block */
PM_CONTEXT_BLOCK_ELSE,
+ /** expressions in block parameters `foo do |...| end ` */
+ PM_CONTEXT_BLOCK_PARAMETERS,
+
/** a rescue statement within a do..end block */
PM_CONTEXT_BLOCK_RESCUE,
@@ -364,6 +377,9 @@ typedef enum {
/** a rescue statement within a lambda expression */
PM_CONTEXT_LAMBDA_RESCUE,
+ /** the predicate clause of a loop statement */
+ PM_CONTEXT_LOOP_PREDICATE,
+
/** the top level context */
PM_CONTEXT_MAIN,
@@ -379,6 +395,9 @@ typedef enum {
/** a rescue statement within a module statement */
PM_CONTEXT_MODULE_RESCUE,
+ /** a multiple target expression */
+ PM_CONTEXT_MULTI_TARGET,
+
/** a parenthesized expression */
PM_CONTEXT_PARENS,
@@ -505,9 +524,9 @@ typedef struct {
/** The type of shareable constant value that can be set. */
typedef uint8_t pm_shareable_constant_value_t;
static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_NONE = 0x0;
-static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_LITERAL = 0x1;
-static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_EVERYTHING = 0x2;
-static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_COPY = 0x4;
+static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_LITERAL = PM_SHAREABLE_CONSTANT_NODE_FLAGS_LITERAL;
+static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_EVERYTHING = PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_EVERYTHING;
+static const pm_shareable_constant_value_t PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_COPY = PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_COPY;
/**
* This tracks an individual local variable in a certain lexical context, as
@@ -622,6 +641,13 @@ typedef uint32_t pm_state_stack_t;
* it's considering.
*/
struct pm_parser {
+ /**
+ * The next node identifier that will be assigned. This is a unique
+ * identifier used to track nodes such that the syntax tree can be dropped
+ * but the node can be found through another parse.
+ */
+ uint32_t node_id;
+
/** The current state of the lexer. */
pm_lex_state_t lex_state;
@@ -851,6 +877,13 @@ struct pm_parser {
*/
bool parsing_eval;
+ /**
+ * Whether or not we are parsing a "partial" script, which is a script that
+ * will be evaluated in the context of another script, so we should not
+ * check jumps (next/break/etc.) for validity.
+ */
+ bool partial_script;
+
/** Whether or not we're at the beginning of a command. */
bool command_start;
@@ -858,6 +891,14 @@ struct pm_parser {
bool recovering;
/**
+ * This is very specialized behavior for when you want to parse in a context
+ * that does not respect encoding comments. Its main use case is translating
+ * into the whitequark/parser AST which re-encodes source files in UTF-8
+ * before they are parsed and ignores encoding comments.
+ */
+ bool encoding_locked;
+
+ /**
* Whether or not the encoding has been changed by a magic comment. We use
* this to provide a fast path for the lexer instead of going through the
* function pointer.
@@ -884,6 +925,12 @@ struct pm_parser {
* characters.
*/
bool current_regular_expression_ascii_only;
+
+ /**
+ * By default, Ruby always warns about mismatched indentation. This can be
+ * toggled with a magic comment.
+ */
+ bool warn_mismatched_indentation;
};
#endif
diff --git a/prism/prism.c b/prism/prism.c
index 12bb55c490..b158e505b2 100644
--- a/prism/prism.c
+++ b/prism/prism.c
@@ -14,183 +14,27 @@ pm_version(void) {
*/
#define PM_TAB_WHITESPACE_SIZE 8
-#ifndef PM_DEBUG_LOGGING
-/**
- * Debugging logging will provide you with additional debugging functions as
- * well as automatically replace some functions with their debugging
- * counterparts.
- */
-#define PM_DEBUG_LOGGING 0
-#endif
-
-#if PM_DEBUG_LOGGING
+// Macros for min/max.
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#define MAX(a,b) (((a)>(b))?(a):(b))
/******************************************************************************/
-/* Debugging */
+/* Helpful AST-related macros */
/******************************************************************************/
-PRISM_ATTRIBUTE_UNUSED static const char *
-debug_context(pm_context_t context) {
- switch (context) {
- case PM_CONTEXT_BEGIN: return "BEGIN";
- case PM_CONTEXT_BEGIN_ENSURE: return "BEGIN_ENSURE";
- case PM_CONTEXT_BEGIN_ELSE: return "BEGIN_ELSE";
- case PM_CONTEXT_BEGIN_RESCUE: return "BEGIN_RESCUE";
- case PM_CONTEXT_BLOCK_BRACES: return "BLOCK_BRACES";
- case PM_CONTEXT_BLOCK_KEYWORDS: return "BLOCK_KEYWORDS";
- case PM_CONTEXT_BLOCK_ENSURE: return "BLOCK_ENSURE";
- case PM_CONTEXT_BLOCK_ELSE: return "BLOCK_ELSE";
- case PM_CONTEXT_BLOCK_RESCUE: return "BLOCK_RESCUE";
- case PM_CONTEXT_CASE_IN: return "CASE_IN";
- case PM_CONTEXT_CASE_WHEN: return "CASE_WHEN";
- case PM_CONTEXT_CLASS: return "CLASS";
- case PM_CONTEXT_CLASS_ELSE: return "CLASS_ELSE";
- case PM_CONTEXT_CLASS_ENSURE: return "CLASS_ENSURE";
- case PM_CONTEXT_CLASS_RESCUE: return "CLASS_RESCUE";
- case PM_CONTEXT_DEF: return "DEF";
- case PM_CONTEXT_DEF_PARAMS: return "DEF_PARAMS";
- case PM_CONTEXT_DEF_ENSURE: return "DEF_ENSURE";
- case PM_CONTEXT_DEF_ELSE: return "DEF_ELSE";
- case PM_CONTEXT_DEF_RESCUE: return "DEF_RESCUE";
- case PM_CONTEXT_DEFAULT_PARAMS: return "DEFAULT_PARAMS";
- case PM_CONTEXT_DEFINED: return "DEFINED";
- case PM_CONTEXT_ELSE: return "ELSE";
- case PM_CONTEXT_ELSIF: return "ELSIF";
- case PM_CONTEXT_EMBEXPR: return "EMBEXPR";
- case PM_CONTEXT_FOR_INDEX: return "FOR_INDEX";
- case PM_CONTEXT_FOR: return "FOR";
- case PM_CONTEXT_IF: return "IF";
- case PM_CONTEXT_LAMBDA_BRACES: return "LAMBDA_BRACES";
- case PM_CONTEXT_LAMBDA_DO_END: return "LAMBDA_DO_END";
- case PM_CONTEXT_LAMBDA_ENSURE: return "LAMBDA_ENSURE";
- case PM_CONTEXT_LAMBDA_ELSE: return "LAMBDA_ELSE";
- case PM_CONTEXT_LAMBDA_RESCUE: return "LAMBDA_RESCUE";
- case PM_CONTEXT_MAIN: return "MAIN";
- case PM_CONTEXT_MODULE: return "MODULE";
- case PM_CONTEXT_MODULE_ELSE: return "MODULE_ELSE";
- case PM_CONTEXT_MODULE_ENSURE: return "MODULE_ENSURE";
- case PM_CONTEXT_MODULE_RESCUE: return "MODULE_RESCUE";
- case PM_CONTEXT_NONE: return "NONE";
- case PM_CONTEXT_PARENS: return "PARENS";
- case PM_CONTEXT_POSTEXE: return "POSTEXE";
- case PM_CONTEXT_PREDICATE: return "PREDICATE";
- case PM_CONTEXT_PREEXE: return "PREEXE";
- case PM_CONTEXT_RESCUE_MODIFIER: return "RESCUE_MODIFIER";
- case PM_CONTEXT_SCLASS: return "SCLASS";
- case PM_CONTEXT_SCLASS_ENSURE: return "SCLASS_ENSURE";
- case PM_CONTEXT_SCLASS_ELSE: return "SCLASS_ELSE";
- case PM_CONTEXT_SCLASS_RESCUE: return "SCLASS_RESCUE";
- case PM_CONTEXT_TERNARY: return "TERNARY";
- case PM_CONTEXT_UNLESS: return "UNLESS";
- case PM_CONTEXT_UNTIL: return "UNTIL";
- case PM_CONTEXT_WHILE: return "WHILE";
- }
- return NULL;
-}
-
-PRISM_ATTRIBUTE_UNUSED static void
-debug_contexts(pm_parser_t *parser) {
- pm_context_node_t *context_node = parser->current_context;
- fprintf(stderr, "CONTEXTS: ");
-
- if (context_node != NULL) {
- while (context_node != NULL) {
- fprintf(stderr, "%s", debug_context(context_node->context));
- context_node = context_node->prev;
- if (context_node != NULL) {
- fprintf(stderr, " <- ");
- }
- }
- } else {
- fprintf(stderr, "NONE");
- }
+#define FL PM_NODE_FLAGS
+#define UP PM_NODE_UPCAST
- fprintf(stderr, "\n");
-}
+#define PM_TOKEN_START(token_) ((token_)->start)
+#define PM_TOKEN_END(token_) ((token_)->end)
-PRISM_ATTRIBUTE_UNUSED static void
-debug_node(const pm_parser_t *parser, const pm_node_t *node) {
- pm_buffer_t output_buffer = { 0 };
- pm_prettyprint(&output_buffer, parser, node);
+#define PM_NODE_START(node_) (UP(node_)->location.start)
+#define PM_NODE_END(node_) (UP(node_)->location.end)
- fprintf(stderr, "%.*s", (int) output_buffer.length, output_buffer.value);
- pm_buffer_free(&output_buffer);
-}
-
-PRISM_ATTRIBUTE_UNUSED static void
-debug_lex_mode(pm_parser_t *parser) {
- pm_lex_mode_t *lex_mode = parser->lex_modes.current;
- bool first = true;
-
- while (lex_mode != NULL) {
- if (first) {
- first = false;
- } else {
- fprintf(stderr, " <- ");
- }
-
- switch (lex_mode->mode) {
- case PM_LEX_DEFAULT: fprintf(stderr, "DEFAULT"); break;
- case PM_LEX_EMBEXPR: fprintf(stderr, "EMBEXPR"); break;
- case PM_LEX_EMBVAR: fprintf(stderr, "EMBVAR"); break;
- case PM_LEX_HEREDOC: fprintf(stderr, "HEREDOC"); break;
- case PM_LEX_LIST: fprintf(stderr, "LIST (terminator=%c, interpolation=%d)", lex_mode->as.list.terminator, lex_mode->as.list.interpolation); break;
- case PM_LEX_REGEXP: fprintf(stderr, "REGEXP (terminator=%c)", lex_mode->as.regexp.terminator); break;
- case PM_LEX_STRING: fprintf(stderr, "STRING (terminator=%c, interpolation=%d)", lex_mode->as.string.terminator, lex_mode->as.string.interpolation); break;
- }
-
- lex_mode = lex_mode->prev;
- }
-
- fprintf(stderr, "\n");
-}
-
-PRISM_ATTRIBUTE_UNUSED static void
-debug_state(pm_parser_t *parser) {
- fprintf(stderr, "STATE: ");
- bool first = true;
-
- if (parser->lex_state == PM_LEX_STATE_NONE) {
- fprintf(stderr, "NONE\n");
- return;
- }
-
-#define CHECK_STATE(state) \
- if (parser->lex_state & state) { \
- if (!first) fprintf(stderr, "|"); \
- fprintf(stderr, "%s", #state); \
- first = false; \
- }
-
- CHECK_STATE(PM_LEX_STATE_BEG)
- CHECK_STATE(PM_LEX_STATE_END)
- CHECK_STATE(PM_LEX_STATE_ENDARG)
- CHECK_STATE(PM_LEX_STATE_ENDFN)
- CHECK_STATE(PM_LEX_STATE_ARG)
- CHECK_STATE(PM_LEX_STATE_CMDARG)
- CHECK_STATE(PM_LEX_STATE_MID)
- CHECK_STATE(PM_LEX_STATE_FNAME)
- CHECK_STATE(PM_LEX_STATE_DOT)
- CHECK_STATE(PM_LEX_STATE_CLASS)
- CHECK_STATE(PM_LEX_STATE_LABEL)
- CHECK_STATE(PM_LEX_STATE_LABELED)
- CHECK_STATE(PM_LEX_STATE_FITEM)
-
-#undef CHECK_STATE
-
- fprintf(stderr, "\n");
-}
-
-PRISM_ATTRIBUTE_UNUSED static void
-debug_token(pm_token_t * token) {
- fprintf(stderr, "%s: \"%.*s\"\n", pm_token_type_human(token->type), (int) (token->end - token->start), token->start);
-}
-
-#endif
-
-// Macros for min/max.
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#define MAX(a,b) (((a)>(b))?(a):(b))
+#define PM_LOCATION_NULL_VALUE(parser_) ((pm_location_t) { .start = (parser_)->start, .end = (parser_)->start })
+#define PM_LOCATION_TOKEN_VALUE(token_) ((pm_location_t) { .start = PM_TOKEN_START(token_), .end = PM_TOKEN_END(token_) })
+#define PM_LOCATION_NODE_VALUE(node_) ((pm_location_t) { .start = PM_NODE_START(node_), .end = PM_NODE_END(node_) })
+#define PM_OPTIONAL_LOCATION_TOKEN_VALUE(token) ((token)->type == PM_TOKEN_NOT_PROVIDED ? ((pm_location_t) { 0 }) : PM_LOCATION_TOKEN_VALUE(token))
/******************************************************************************/
/* Lex mode manipulations */
@@ -342,6 +186,7 @@ lex_mode_push_regexp(pm_parser_t *parser, uint8_t incrementor, uint8_t terminato
breakpoints[index++] = incrementor;
}
+ parser->explicit_encoding = NULL;
return lex_mode_push(parser, lex_mode);
}
@@ -452,11 +297,6 @@ lex_state_beg_p(pm_parser_t *parser) {
}
static inline bool
-lex_state_arg_labeled_p(pm_parser_t *parser) {
- return (parser->lex_state & (PM_LEX_STATE_ARG | PM_LEX_STATE_LABELED)) == (PM_LEX_STATE_ARG | PM_LEX_STATE_LABELED);
-}
-
-static inline bool
lex_state_arg_p(pm_parser_t *parser) {
return lex_state_p(parser, PM_LEX_STATE_ARG_ANY);
}
@@ -491,8 +331,52 @@ lex_state_set(pm_parser_t *parser, pm_lex_state_t state) {
parser->lex_state = state;
}
+#ifndef PM_DEBUG_LOGGING
+/**
+ * Debugging logging will print additional information to stdout whenever the
+ * lexer state changes.
+ */
+#define PM_DEBUG_LOGGING 0
+#endif
+
#if PM_DEBUG_LOGGING
-static inline void
+PRISM_ATTRIBUTE_UNUSED static void
+debug_state(pm_parser_t *parser) {
+ fprintf(stderr, "STATE: ");
+ bool first = true;
+
+ if (parser->lex_state == PM_LEX_STATE_NONE) {
+ fprintf(stderr, "NONE\n");
+ return;
+ }
+
+#define CHECK_STATE(state) \
+ if (parser->lex_state & state) { \
+ if (!first) fprintf(stderr, "|"); \
+ fprintf(stderr, "%s", #state); \
+ first = false; \
+ }
+
+ CHECK_STATE(PM_LEX_STATE_BEG)
+ CHECK_STATE(PM_LEX_STATE_END)
+ CHECK_STATE(PM_LEX_STATE_ENDARG)
+ CHECK_STATE(PM_LEX_STATE_ENDFN)
+ CHECK_STATE(PM_LEX_STATE_ARG)
+ CHECK_STATE(PM_LEX_STATE_CMDARG)
+ CHECK_STATE(PM_LEX_STATE_MID)
+ CHECK_STATE(PM_LEX_STATE_FNAME)
+ CHECK_STATE(PM_LEX_STATE_DOT)
+ CHECK_STATE(PM_LEX_STATE_CLASS)
+ CHECK_STATE(PM_LEX_STATE_LABEL)
+ CHECK_STATE(PM_LEX_STATE_LABELED)
+ CHECK_STATE(PM_LEX_STATE_FITEM)
+
+#undef CHECK_STATE
+
+ fprintf(stderr, "\n");
+}
+
+static void
debug_lex_state_set(pm_parser_t *parser, pm_lex_state_t state, char const * caller_name, int line_number) {
fprintf(stderr, "Caller: %s:%d\nPrevious: ", caller_name, line_number);
debug_state(parser);
@@ -678,10 +562,7 @@ pm_parser_warn_node(pm_parser_t *parser, const pm_node_t *node, pm_diagnostic_id
* token.
*/
static void
-pm_parser_err_heredoc_term(pm_parser_t *parser, pm_lex_mode_t *lex_mode) {
- const uint8_t *ident_start = lex_mode->as.heredoc.ident_start;
- size_t ident_length = lex_mode->as.heredoc.ident_length;
-
+pm_parser_err_heredoc_term(pm_parser_t *parser, const uint8_t *ident_start, size_t ident_length) {
PM_PARSER_ERR_FORMAT(
parser,
ident_start,
@@ -709,7 +590,7 @@ pm_parser_scope_push(pm_parser_t *parser, bool closed) {
.locals = { 0 },
.parameters = PM_SCOPE_PARAMETERS_NONE,
.implicit_parameters = { 0 },
- .shareable_constant = (closed || parser->current_scope == NULL) ? PM_SCOPE_SHAREABLE_CONSTANT_NONE : parser->current_scope->shareable_constant,
+ .shareable_constant = parser->current_scope == NULL ? PM_SCOPE_SHAREABLE_CONSTANT_NONE : parser->current_scope->shareable_constant,
.closed = closed
};
@@ -1098,7 +979,7 @@ pm_locals_order(PRISM_ATTRIBUTE_UNUSED pm_parser_t *parser, pm_locals_t *locals,
if (local->name != PM_CONSTANT_ID_UNSET) {
pm_constant_id_list_insert(list, (size_t) local->index, local->name);
- if (warn_unused && local->reads == 0) {
+ if (warn_unused && local->reads == 0 && ((parser->start_line >= 0) || (pm_newline_list_line(&parser->newline_list, local->location.start, parser->start_line) >= 0))) {
pm_constant_t *constant = pm_constant_pool_id_to_constant(&parser->constant_pool, local->name);
if (constant->length >= 1 && *constant->start != '_') {
@@ -1166,9 +1047,9 @@ pm_parser_optional_constant_id_token(pm_parser_t *parser, const pm_token_t *toke
* If the node is value node, it returns NULL.
* If not, it returns the pointer to the node to be inspected as "void expression".
*/
-static pm_node_t*
-pm_check_value_expression(pm_node_t *node) {
- pm_node_t* void_node = NULL;
+static pm_node_t *
+pm_check_value_expression(pm_parser_t *parser, pm_node_t *node) {
+ pm_node_t *void_node = NULL;
while (node != NULL) {
switch (PM_NODE_TYPE(node)) {
@@ -1184,36 +1065,55 @@ pm_check_value_expression(pm_node_t *node) {
case PM_BEGIN_NODE: {
pm_begin_node_t *cast = (pm_begin_node_t *) node;
- if (cast->statements == NULL && cast->ensure_clause != NULL) {
- node = (pm_node_t *) cast->ensure_clause;
- }
- else {
+ if (cast->ensure_clause != NULL) {
if (cast->rescue_clause != NULL) {
- if (cast->rescue_clause->statements == NULL) {
- return NULL;
- }
- else if (cast->else_clause != NULL) {
- node = (pm_node_t *) cast->else_clause;
+ pm_node_t *vn = pm_check_value_expression(parser, UP(cast->rescue_clause));
+ if (vn != NULL) return vn;
+ }
+
+ if (cast->statements != NULL) {
+ pm_node_t *vn = pm_check_value_expression(parser, UP(cast->statements));
+ if (vn != NULL) return vn;
+ }
+
+ node = UP(cast->ensure_clause);
+ } else if (cast->rescue_clause != NULL) {
+ if (cast->statements == NULL) return NULL;
+
+ pm_node_t *vn = pm_check_value_expression(parser, UP(cast->statements));
+ if (vn == NULL) return NULL;
+ if (void_node == NULL) void_node = vn;
+
+ for (pm_rescue_node_t *rescue_clause = cast->rescue_clause; rescue_clause != NULL; rescue_clause = rescue_clause->subsequent) {
+ pm_node_t *vn = pm_check_value_expression(parser, UP(rescue_clause->statements));
+ if (vn == NULL) {
+ void_node = NULL;
+ break;
}
- else {
- node = (pm_node_t *) cast->statements;
+ if (void_node == NULL) {
+ void_node = vn;
}
}
- else {
- node = (pm_node_t *) cast->statements;
+
+ if (cast->else_clause != NULL) {
+ node = UP(cast->else_clause);
+ } else {
+ return void_node;
}
+ } else {
+ node = UP(cast->statements);
}
break;
}
case PM_ENSURE_NODE: {
pm_ensure_node_t *cast = (pm_ensure_node_t *) node;
- node = (pm_node_t *) cast->statements;
+ node = UP(cast->statements);
break;
}
case PM_PARENTHESES_NODE: {
pm_parentheses_node_t *cast = (pm_parentheses_node_t *) node;
- node = (pm_node_t *) cast->body;
+ node = UP(cast->body);
break;
}
case PM_STATEMENTS_NODE: {
@@ -1223,37 +1123,37 @@ pm_check_value_expression(pm_node_t *node) {
}
case PM_IF_NODE: {
pm_if_node_t *cast = (pm_if_node_t *) node;
- if (cast->statements == NULL || cast->consequent == NULL) {
+ if (cast->statements == NULL || cast->subsequent == NULL) {
return NULL;
}
- pm_node_t *vn = pm_check_value_expression((pm_node_t *) cast->statements);
+ pm_node_t *vn = pm_check_value_expression(parser, UP(cast->statements));
if (vn == NULL) {
return NULL;
}
if (void_node == NULL) {
void_node = vn;
}
- node = cast->consequent;
+ node = cast->subsequent;
break;
}
case PM_UNLESS_NODE: {
pm_unless_node_t *cast = (pm_unless_node_t *) node;
- if (cast->statements == NULL || cast->consequent == NULL) {
+ if (cast->statements == NULL || cast->else_clause == NULL) {
return NULL;
}
- pm_node_t *vn = pm_check_value_expression((pm_node_t *) cast->statements);
+ pm_node_t *vn = pm_check_value_expression(parser, UP(cast->statements));
if (vn == NULL) {
return NULL;
}
if (void_node == NULL) {
void_node = vn;
}
- node = (pm_node_t *) cast->consequent;
+ node = UP(cast->else_clause);
break;
}
case PM_ELSE_NODE: {
pm_else_node_t *cast = (pm_else_node_t *) node;
- node = (pm_node_t *) cast->statements;
+ node = UP(cast->statements);
break;
}
case PM_AND_NODE: {
@@ -1266,6 +1166,15 @@ pm_check_value_expression(pm_node_t *node) {
node = cast->left;
break;
}
+ case PM_LOCAL_VARIABLE_WRITE_NODE: {
+ pm_local_variable_write_node_t *cast = (pm_local_variable_write_node_t *) node;
+
+ pm_scope_t *scope = parser->current_scope;
+ for (uint32_t depth = 0; depth < cast->depth; depth++) scope = scope->previous;
+
+ pm_locals_read(&scope->locals, cast->name);
+ return NULL;
+ }
default:
return NULL;
}
@@ -1276,7 +1185,7 @@ pm_check_value_expression(pm_node_t *node) {
static inline void
pm_assert_value_expression(pm_parser_t *parser, pm_node_t *node) {
- pm_node_t *void_node = pm_check_value_expression(node);
+ pm_node_t *void_node = pm_check_value_expression(parser, node);
if (void_node != NULL) {
pm_parser_err_node(parser, void_node, PM_ERR_VOID_EXPRESSION);
}
@@ -1425,9 +1334,10 @@ pm_void_statement_check(pm_parser_t *parser, const pm_node_t *node) {
* a "void" statement.
*/
static void
-pm_void_statements_check(pm_parser_t *parser, const pm_statements_node_t *node) {
+pm_void_statements_check(pm_parser_t *parser, const pm_statements_node_t *node, bool last_value) {
assert(node->body.size > 0);
- for (size_t index = 0; index < node->body.size - 1; index++) {
+ const size_t size = node->body.size - (last_value ? 1 : 0);
+ for (size_t index = 0; index < size; index++) {
pm_void_statement_check(parser, node->body.nodes[index]);
}
}
@@ -1468,13 +1378,25 @@ static bool
pm_conditional_predicate_warn_write_literal_p(const pm_node_t *node) {
switch (PM_NODE_TYPE(node)) {
case PM_ARRAY_NODE: {
+ if (PM_NODE_FLAG_P(node, PM_NODE_FLAG_STATIC_LITERAL)) return true;
+
const pm_array_node_t *cast = (const pm_array_node_t *) node;
- const pm_node_t *element;
+ for (size_t index = 0; index < cast->elements.size; index++) {
+ if (!pm_conditional_predicate_warn_write_literal_p(cast->elements.nodes[index])) return false;
+ }
- PM_NODE_LIST_FOREACH(&cast->elements, index, element) {
- if (!pm_conditional_predicate_warn_write_literal_p(element)) {
- return false;
- }
+ return true;
+ }
+ case PM_HASH_NODE: {
+ if (PM_NODE_FLAG_P(node, PM_NODE_FLAG_STATIC_LITERAL)) return true;
+
+ const pm_hash_node_t *cast = (const pm_hash_node_t *) node;
+ for (size_t index = 0; index < cast->elements.size; index++) {
+ const pm_node_t *element = cast->elements.nodes[index];
+ if (!PM_NODE_TYPE_P(element, PM_ASSOC_NODE)) return false;
+
+ const pm_assoc_node_t *assoc = (const pm_assoc_node_t *) element;
+ if (!pm_conditional_predicate_warn_write_literal_p(assoc->key) || !pm_conditional_predicate_warn_write_literal_p(assoc->value)) return false;
}
return true;
@@ -1505,7 +1427,7 @@ pm_conditional_predicate_warn_write_literal_p(const pm_node_t *node) {
static inline void
pm_conditional_predicate_warn_write_literal(pm_parser_t *parser, const pm_node_t *node) {
if (pm_conditional_predicate_warn_write_literal_p(node)) {
- pm_parser_warn_node(parser, node, parser->version == PM_OPTIONS_VERSION_CRUBY_3_3 ? PM_WARN_EQUAL_IN_CONDITIONAL_3_3 : PM_WARN_EQUAL_IN_CONDITIONAL);
+ pm_parser_warn_node(parser, node, parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3 ? PM_WARN_EQUAL_IN_CONDITIONAL_3_3 : PM_WARN_EQUAL_IN_CONDITIONAL);
}
}
@@ -1655,13 +1577,6 @@ not_provided(pm_parser_t *parser) {
return (pm_token_t) { .type = PM_TOKEN_NOT_PROVIDED, .start = parser->start, .end = parser->start };
}
-#define PM_LOCATION_NULL_VALUE(parser) ((pm_location_t) { .start = (parser)->start, .end = (parser)->start })
-#define PM_LOCATION_TOKEN_VALUE(token) ((pm_location_t) { .start = (token)->start, .end = (token)->end })
-#define PM_LOCATION_NODE_VALUE(node) ((pm_location_t) { .start = (node)->location.start, .end = (node)->location.end })
-#define PM_LOCATION_NODE_BASE_VALUE(node) ((pm_location_t) { .start = (node)->base.location.start, .end = (node)->base.location.end })
-#define PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE ((pm_location_t) { .start = NULL, .end = NULL })
-#define PM_OPTIONAL_LOCATION_TOKEN_VALUE(token) ((token)->type == PM_TOKEN_NOT_PROVIDED ? PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE : PM_LOCATION_TOKEN_VALUE(token))
-
/**
* This is a special out parameter to the parse_arguments_list function that
* includes opening and closing parentheses in addition to the arguments since
@@ -1731,7 +1646,7 @@ pm_arguments_validate_block(pm_parser_t *parser, pm_arguments_t *arguments, pm_b
// If we didn't hit a case before this check, then at this point we need to
// add a syntax error.
- pm_parser_err_node(parser, (pm_node_t *) block, PM_ERR_ARGUMENT_UNEXPECTED_BLOCK);
+ pm_parser_err_node(parser, UP(block), PM_ERR_ARGUMENT_UNEXPECTED_BLOCK);
}
/******************************************************************************/
@@ -1745,22 +1660,25 @@ pm_arguments_validate_block(pm_parser_t *parser, pm_arguments_t *arguments, pm_b
* the function pointer or can just directly use the UTF-8 functions.
*/
static inline size_t
-char_is_identifier_start(const pm_parser_t *parser, const uint8_t *b) {
+char_is_identifier_start(const pm_parser_t *parser, const uint8_t *b, ptrdiff_t n) {
+ if (n <= 0) return 0;
+
if (parser->encoding_changed) {
size_t width;
- if ((width = parser->encoding->alpha_char(b, parser->end - b)) != 0) {
+
+ if ((width = parser->encoding->alpha_char(b, n)) != 0) {
return width;
} else if (*b == '_') {
return 1;
} else if (*b >= 0x80) {
- return parser->encoding->char_width(b, parser->end - b);
+ return parser->encoding->char_width(b, n);
} else {
return 0;
}
} else if (*b < 0x80) {
return (pm_encoding_unicode_table[*b] & PRISM_ENCODING_ALPHABETIC_BIT ? 1 : 0) || (*b == '_');
} else {
- return pm_encoding_utf_8_char_width(b, parser->end - b);
+ return pm_encoding_utf_8_char_width(b, n);
}
}
@@ -1769,11 +1687,13 @@ char_is_identifier_start(const pm_parser_t *parser, const uint8_t *b) {
* has not been changed.
*/
static inline size_t
-char_is_identifier_utf8(const uint8_t *b, const uint8_t *end) {
- if (*b < 0x80) {
+char_is_identifier_utf8(const uint8_t *b, ptrdiff_t n) {
+ if (n <= 0) {
+ return 0;
+ } else if (*b < 0x80) {
return (*b == '_') || (pm_encoding_unicode_table[*b] & PRISM_ENCODING_ALPHANUMERIC_BIT ? 1 : 0);
} else {
- return pm_encoding_utf_8_char_width(b, end - b);
+ return pm_encoding_utf_8_char_width(b, n);
}
}
@@ -1783,20 +1703,24 @@ char_is_identifier_utf8(const uint8_t *b, const uint8_t *end) {
* it's important that it be as fast as possible.
*/
static inline size_t
-char_is_identifier(const pm_parser_t *parser, const uint8_t *b) {
- if (parser->encoding_changed) {
+char_is_identifier(const pm_parser_t *parser, const uint8_t *b, ptrdiff_t n) {
+ if (n <= 0) {
+ return 0;
+ } else if (parser->encoding_changed) {
size_t width;
- if ((width = parser->encoding->alnum_char(b, parser->end - b)) != 0) {
+
+ if ((width = parser->encoding->alnum_char(b, n)) != 0) {
return width;
} else if (*b == '_') {
return 1;
} else if (*b >= 0x80) {
- return parser->encoding->char_width(b, parser->end - b);
+ return parser->encoding->char_width(b, n);
} else {
return 0;
}
+ } else {
+ return char_is_identifier_utf8(b, n);
}
- return char_is_identifier_utf8(b, parser->end);
}
// Here we're defining a perfect hash for the characters that are allowed in
@@ -1827,9 +1751,10 @@ char_is_global_name_punctuation(const uint8_t b) {
static inline bool
token_is_setter_name(pm_token_t *token) {
return (
- (token->type == PM_TOKEN_IDENTIFIER) &&
+ (token->type == PM_TOKEN_BRACKET_LEFT_RIGHT_EQUAL) ||
+ ((token->type == PM_TOKEN_IDENTIFIER) &&
(token->end - token->start >= 2) &&
- (token->end[-1] == '=')
+ (token->end[-1] == '='))
);
}
@@ -1995,7 +1920,7 @@ static pm_statements_node_t *
pm_statements_node_create(pm_parser_t *parser);
static void
-pm_statements_node_body_append(pm_parser_t *parser, pm_statements_node_t *node, pm_node_t *statement);
+pm_statements_node_body_append(pm_parser_t *parser, pm_statements_node_t *node, pm_node_t *statement, bool newline);
static size_t
pm_statements_node_body_length(pm_statements_node_t *node);
@@ -2005,7 +1930,7 @@ pm_statements_node_body_length(pm_statements_node_t *node);
* implement our own arena allocation.
*/
static inline void *
-pm_alloc_node(PRISM_ATTRIBUTE_UNUSED pm_parser_t *parser, size_t size) {
+pm_node_alloc(PRISM_ATTRIBUTE_UNUSED pm_parser_t *parser, size_t size) {
void *memory = xcalloc(1, size);
if (memory == NULL) {
fprintf(stderr, "Failed to allocate %d bytes\n", (int) size);
@@ -2014,15 +1939,35 @@ pm_alloc_node(PRISM_ATTRIBUTE_UNUSED pm_parser_t *parser, size_t size) {
return memory;
}
-#define PM_ALLOC_NODE(parser, type) (type *) pm_alloc_node(parser, sizeof(type))
+#define PM_NODE_ALLOC(parser_, type_) (type_ *) pm_node_alloc(parser_, sizeof(type_))
+#define PM_NODE_INIT(parser_, type_, flags_, start_, end_) (pm_node_t) { \
+ .type = (type_), \
+ .flags = (flags_), \
+ .node_id = ++(parser_)->node_id, \
+ .location = { .start = (start_), .end = (end_) } \
+}
+
+#define PM_NODE_INIT_UNSET(parser_, type_, flags_) PM_NODE_INIT(parser_, type_, flags_, NULL, NULL)
+#define PM_NODE_INIT_BASE(parser_, type_, flags_) PM_NODE_INIT(parser_, type_, flags_, (parser_)->start, (parser_)->start)
+#define PM_NODE_INIT_TOKEN(parser_, type_, flags_, token_) PM_NODE_INIT(parser_, type_, flags_, PM_TOKEN_START(token_), PM_TOKEN_END(token_))
+#define PM_NODE_INIT_NODE(parser_, type_, flags_, node_) PM_NODE_INIT(parser_, type_, flags_, PM_NODE_START(node_), PM_NODE_END(node_))
+
+#define PM_NODE_INIT_TOKENS(parser_, type_, flags_, left_, right_) PM_NODE_INIT(parser_, type_, flags_, PM_TOKEN_START(left_), PM_TOKEN_END(right_))
+#define PM_NODE_INIT_NODES(parser_, type_, flags_, left_, right_) PM_NODE_INIT(parser_, type_, flags_, PM_NODE_START(left_), PM_NODE_END(right_))
+#define PM_NODE_INIT_TOKEN_NODE(parser_, type_, flags_, token_, node_) PM_NODE_INIT(parser_, type_, flags_, PM_TOKEN_START(token_), PM_NODE_END(node_))
+#define PM_NODE_INIT_NODE_TOKEN(parser_, type_, flags_, node_, token_) PM_NODE_INIT(parser_, type_, flags_, PM_NODE_START(node_), PM_TOKEN_END(token_))
/**
* Allocate a new MissingNode node.
*/
static pm_missing_node_t *
pm_missing_node_create(pm_parser_t *parser, const uint8_t *start, const uint8_t *end) {
- pm_missing_node_t *node = PM_ALLOC_NODE(parser, pm_missing_node_t);
- *node = (pm_missing_node_t) {{ .type = PM_MISSING_NODE, .location = { .start = start, .end = end } }};
+ pm_missing_node_t *node = PM_NODE_ALLOC(parser, pm_missing_node_t);
+
+ *node = (pm_missing_node_t) {
+ .base = PM_NODE_INIT(parser, PM_MISSING_NODE, 0, start, end)
+ };
+
return node;
}
@@ -2032,16 +1977,10 @@ pm_missing_node_create(pm_parser_t *parser, const uint8_t *start, const uint8_t
static pm_alias_global_variable_node_t *
pm_alias_global_variable_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t *new_name, pm_node_t *old_name) {
assert(keyword->type == PM_TOKEN_KEYWORD_ALIAS);
- pm_alias_global_variable_node_t *node = PM_ALLOC_NODE(parser, pm_alias_global_variable_node_t);
+ pm_alias_global_variable_node_t *node = PM_NODE_ALLOC(parser, pm_alias_global_variable_node_t);
*node = (pm_alias_global_variable_node_t) {
- {
- .type = PM_ALIAS_GLOBAL_VARIABLE_NODE,
- .location = {
- .start = keyword->start,
- .end = old_name->location.end
- },
- },
+ .base = PM_NODE_INIT_TOKEN_NODE(parser, PM_ALIAS_GLOBAL_VARIABLE_NODE, 0, keyword, old_name),
.new_name = new_name,
.old_name = old_name,
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword)
@@ -2056,16 +1995,10 @@ pm_alias_global_variable_node_create(pm_parser_t *parser, const pm_token_t *keyw
static pm_alias_method_node_t *
pm_alias_method_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t *new_name, pm_node_t *old_name) {
assert(keyword->type == PM_TOKEN_KEYWORD_ALIAS);
- pm_alias_method_node_t *node = PM_ALLOC_NODE(parser, pm_alias_method_node_t);
+ pm_alias_method_node_t *node = PM_NODE_ALLOC(parser, pm_alias_method_node_t);
*node = (pm_alias_method_node_t) {
- {
- .type = PM_ALIAS_METHOD_NODE,
- .location = {
- .start = keyword->start,
- .end = old_name->location.end
- },
- },
+ .base = PM_NODE_INIT_TOKEN_NODE(parser, PM_ALIAS_METHOD_NODE, 0, keyword, old_name),
.new_name = new_name,
.old_name = old_name,
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword)
@@ -2079,16 +2012,10 @@ pm_alias_method_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_n
*/
static pm_alternation_pattern_node_t *
pm_alternation_pattern_node_create(pm_parser_t *parser, pm_node_t *left, pm_node_t *right, const pm_token_t *operator) {
- pm_alternation_pattern_node_t *node = PM_ALLOC_NODE(parser, pm_alternation_pattern_node_t);
+ pm_alternation_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_alternation_pattern_node_t);
*node = (pm_alternation_pattern_node_t) {
- {
- .type = PM_ALTERNATION_PATTERN_NODE,
- .location = {
- .start = left->location.start,
- .end = right->location.end
- },
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_ALTERNATION_PATTERN_NODE, 0, left, right),
.left = left,
.right = right,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator)
@@ -2104,16 +2031,10 @@ static pm_and_node_t *
pm_and_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *operator, pm_node_t *right) {
pm_assert_value_expression(parser, left);
- pm_and_node_t *node = PM_ALLOC_NODE(parser, pm_and_node_t);
+ pm_and_node_t *node = PM_NODE_ALLOC(parser, pm_and_node_t);
*node = (pm_and_node_t) {
- {
- .type = PM_AND_NODE,
- .location = {
- .start = left->location.start,
- .end = right->location.end
- },
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_AND_NODE, 0, left, right),
.left = left,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.right = right
@@ -2127,13 +2048,10 @@ pm_and_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *opera
*/
static pm_arguments_node_t *
pm_arguments_node_create(pm_parser_t *parser) {
- pm_arguments_node_t *node = PM_ALLOC_NODE(parser, pm_arguments_node_t);
+ pm_arguments_node_t *node = PM_NODE_ALLOC(parser, pm_arguments_node_t);
*node = (pm_arguments_node_t) {
- {
- .type = PM_ARGUMENTS_NODE,
- .location = PM_LOCATION_NULL_VALUE(parser)
- },
+ .base = PM_NODE_INIT_BASE(parser, PM_ARGUMENTS_NODE, 0),
.arguments = { 0 }
};
@@ -2157,8 +2075,19 @@ pm_arguments_node_arguments_append(pm_arguments_node_t *node, pm_node_t *argumen
node->base.location.start = argument->location.start;
}
- node->base.location.end = argument->location.end;
+ if (node->base.location.end < argument->location.end) {
+ node->base.location.end = argument->location.end;
+ }
+
pm_node_list_append(&node->arguments, argument);
+
+ if (PM_NODE_TYPE_P(argument, PM_SPLAT_NODE)) {
+ if (PM_NODE_FLAG_P(node, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_SPLAT)) {
+ pm_node_flag_set(UP(node), PM_ARGUMENTS_NODE_FLAGS_CONTAINS_MULTIPLE_SPLATS);
+ } else {
+ pm_node_flag_set(UP(node), PM_ARGUMENTS_NODE_FLAGS_CONTAINS_SPLAT);
+ }
+ }
}
/**
@@ -2166,14 +2095,10 @@ pm_arguments_node_arguments_append(pm_arguments_node_t *node, pm_node_t *argumen
*/
static pm_array_node_t *
pm_array_node_create(pm_parser_t *parser, const pm_token_t *opening) {
- pm_array_node_t *node = PM_ALLOC_NODE(parser, pm_array_node_t);
+ pm_array_node_t *node = PM_NODE_ALLOC(parser, pm_array_node_t);
*node = (pm_array_node_t) {
- {
- .type = PM_ARRAY_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .location = PM_LOCATION_TOKEN_VALUE(opening)
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_ARRAY_NODE, PM_NODE_FLAG_STATIC_LITERAL, opening),
.opening_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
.closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
.elements = { 0 }
@@ -2183,14 +2108,6 @@ pm_array_node_create(pm_parser_t *parser, const pm_token_t *opening) {
}
/**
- * Return the size of the given array node.
- */
-static inline size_t
-pm_array_node_size(pm_array_node_t *node) {
- return node->elements.size;
-}
-
-/**
* Append an argument to an array node.
*/
static inline void
@@ -2205,11 +2122,11 @@ pm_array_node_elements_append(pm_array_node_t *node, pm_node_t *element) {
// If the element is not a static literal, then the array is not a static
// literal. Turn that flag off.
if (PM_NODE_TYPE_P(element, PM_ARRAY_NODE) || PM_NODE_TYPE_P(element, PM_HASH_NODE) || PM_NODE_TYPE_P(element, PM_RANGE_NODE) || !PM_NODE_FLAG_P(element, PM_NODE_FLAG_STATIC_LITERAL)) {
- pm_node_flag_unset((pm_node_t *)node, PM_NODE_FLAG_STATIC_LITERAL);
+ pm_node_flag_unset(UP(node), PM_NODE_FLAG_STATIC_LITERAL);
}
if (PM_NODE_TYPE_P(element, PM_SPLAT_NODE)) {
- pm_node_flag_set((pm_node_t *)node, PM_ARRAY_NODE_FLAGS_CONTAINS_SPLAT);
+ pm_node_flag_set(UP(node), PM_ARRAY_NODE_FLAGS_CONTAINS_SPLAT);
}
}
@@ -2229,22 +2146,16 @@ pm_array_node_close_set(pm_array_node_t *node, const pm_token_t *closing) {
*/
static pm_array_pattern_node_t *
pm_array_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *nodes) {
- pm_array_pattern_node_t *node = PM_ALLOC_NODE(parser, pm_array_pattern_node_t);
+ pm_array_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_array_pattern_node_t);
*node = (pm_array_pattern_node_t) {
- {
- .type = PM_ARRAY_PATTERN_NODE,
- .location = {
- .start = nodes->nodes[0]->location.start,
- .end = nodes->nodes[nodes->size - 1]->location.end
- },
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_ARRAY_PATTERN_NODE, 0, nodes->nodes[0], nodes->nodes[nodes->size - 1]),
.constant = NULL,
.rest = NULL,
.requireds = { 0 },
.posts = { 0 },
- .opening_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
- .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
+ .opening_loc = { 0 },
+ .closing_loc = { 0 }
};
// For now we're going to just copy over each pointer manually. This could be
@@ -2271,19 +2182,16 @@ pm_array_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *node
*/
static pm_array_pattern_node_t *
pm_array_pattern_node_rest_create(pm_parser_t *parser, pm_node_t *rest) {
- pm_array_pattern_node_t *node = PM_ALLOC_NODE(parser, pm_array_pattern_node_t);
+ pm_array_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_array_pattern_node_t);
*node = (pm_array_pattern_node_t) {
- {
- .type = PM_ARRAY_PATTERN_NODE,
- .location = rest->location,
- },
+ .base = PM_NODE_INIT_NODE(parser, PM_ARRAY_PATTERN_NODE, 0, rest),
.constant = NULL,
.rest = rest,
.requireds = { 0 },
.posts = { 0 },
- .opening_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
- .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
+ .opening_loc = { 0 },
+ .closing_loc = { 0 }
};
return node;
@@ -2295,16 +2203,10 @@ pm_array_pattern_node_rest_create(pm_parser_t *parser, pm_node_t *rest) {
*/
static pm_array_pattern_node_t *
pm_array_pattern_node_constant_create(pm_parser_t *parser, pm_node_t *constant, const pm_token_t *opening, const pm_token_t *closing) {
- pm_array_pattern_node_t *node = PM_ALLOC_NODE(parser, pm_array_pattern_node_t);
+ pm_array_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_array_pattern_node_t);
*node = (pm_array_pattern_node_t) {
- {
- .type = PM_ARRAY_PATTERN_NODE,
- .location = {
- .start = constant->location.start,
- .end = closing->end
- },
- },
+ .base = PM_NODE_INIT_NODE_TOKEN(parser, PM_ARRAY_PATTERN_NODE, 0, constant, closing),
.constant = constant,
.rest = NULL,
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
@@ -2322,16 +2224,10 @@ pm_array_pattern_node_constant_create(pm_parser_t *parser, pm_node_t *constant,
*/
static pm_array_pattern_node_t *
pm_array_pattern_node_empty_create(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *closing) {
- pm_array_pattern_node_t *node = PM_ALLOC_NODE(parser, pm_array_pattern_node_t);
+ pm_array_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_array_pattern_node_t);
*node = (pm_array_pattern_node_t) {
- {
- .type = PM_ARRAY_PATTERN_NODE,
- .location = {
- .start = opening->start,
- .end = closing->end
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_ARRAY_PATTERN_NODE, 0, opening, closing),
.constant = NULL,
.rest = NULL,
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
@@ -2353,7 +2249,7 @@ pm_array_pattern_node_requireds_append(pm_array_pattern_node_t *node, pm_node_t
*/
static pm_assoc_node_t *
pm_assoc_node_create(pm_parser_t *parser, pm_node_t *key, const pm_token_t *operator, pm_node_t *value) {
- pm_assoc_node_t *node = PM_ALLOC_NODE(parser, pm_assoc_node_t);
+ pm_assoc_node_t *node = PM_NODE_ALLOC(parser, pm_assoc_node_t);
const uint8_t *end;
if (value != NULL && value->location.end > key->location.end) {
@@ -2374,19 +2270,15 @@ pm_assoc_node_create(pm_parser_t *parser, pm_node_t *key, const pm_token_t *oper
// If the key and value of this assoc node are both static literals, then
// we can mark this node as a static literal.
pm_node_flags_t flags = 0;
- if (value && !PM_NODE_TYPE_P(value, PM_ARRAY_NODE) && !PM_NODE_TYPE_P(value, PM_HASH_NODE) && !PM_NODE_TYPE_P(value, PM_RANGE_NODE)) {
+ if (
+ !PM_NODE_TYPE_P(key, PM_ARRAY_NODE) && !PM_NODE_TYPE_P(key, PM_HASH_NODE) && !PM_NODE_TYPE_P(key, PM_RANGE_NODE) &&
+ value && !PM_NODE_TYPE_P(value, PM_ARRAY_NODE) && !PM_NODE_TYPE_P(value, PM_HASH_NODE) && !PM_NODE_TYPE_P(value, PM_RANGE_NODE)
+ ) {
flags = key->flags & value->flags & PM_NODE_FLAG_STATIC_LITERAL;
}
*node = (pm_assoc_node_t) {
- {
- .type = PM_ASSOC_NODE,
- .flags = flags,
- .location = {
- .start = key->location.start,
- .end = end
- },
- },
+ .base = PM_NODE_INIT(parser, PM_ASSOC_NODE, flags, key->location.start, end),
.key = key,
.operator_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(operator),
.value = value
@@ -2401,16 +2293,14 @@ pm_assoc_node_create(pm_parser_t *parser, pm_node_t *key, const pm_token_t *oper
static pm_assoc_splat_node_t *
pm_assoc_splat_node_create(pm_parser_t *parser, pm_node_t *value, const pm_token_t *operator) {
assert(operator->type == PM_TOKEN_USTAR_STAR);
- pm_assoc_splat_node_t *node = PM_ALLOC_NODE(parser, pm_assoc_splat_node_t);
+ pm_assoc_splat_node_t *node = PM_NODE_ALLOC(parser, pm_assoc_splat_node_t);
*node = (pm_assoc_splat_node_t) {
- {
- .type = PM_ASSOC_SPLAT_NODE,
- .location = {
- .start = operator->start,
- .end = value == NULL ? operator->end : value->location.end
- },
- },
+ .base = (
+ (value == NULL)
+ ? PM_NODE_INIT_TOKEN(parser, PM_ASSOC_SPLAT_NODE, 0, operator)
+ : PM_NODE_INIT_TOKEN_NODE(parser, PM_ASSOC_SPLAT_NODE, 0, operator, value)
+ ),
.value = value,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator)
};
@@ -2424,13 +2314,10 @@ pm_assoc_splat_node_create(pm_parser_t *parser, pm_node_t *value, const pm_token
static pm_back_reference_read_node_t *
pm_back_reference_read_node_create(pm_parser_t *parser, const pm_token_t *name) {
assert(name->type == PM_TOKEN_BACK_REFERENCE);
- pm_back_reference_read_node_t *node = PM_ALLOC_NODE(parser, pm_back_reference_read_node_t);
+ pm_back_reference_read_node_t *node = PM_NODE_ALLOC(parser, pm_back_reference_read_node_t);
*node = (pm_back_reference_read_node_t) {
- {
- .type = PM_BACK_REFERENCE_READ_NODE,
- .location = PM_LOCATION_TOKEN_VALUE(name),
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_BACK_REFERENCE_READ_NODE, 0, name),
.name = pm_parser_constant_id_token(parser, name)
};
@@ -2442,19 +2329,17 @@ pm_back_reference_read_node_create(pm_parser_t *parser, const pm_token_t *name)
*/
static pm_begin_node_t *
pm_begin_node_create(pm_parser_t *parser, const pm_token_t *begin_keyword, pm_statements_node_t *statements) {
- pm_begin_node_t *node = PM_ALLOC_NODE(parser, pm_begin_node_t);
+ pm_begin_node_t *node = PM_NODE_ALLOC(parser, pm_begin_node_t);
*node = (pm_begin_node_t) {
- {
- .type = PM_BEGIN_NODE,
- .location = {
- .start = begin_keyword->start,
- .end = statements == NULL ? begin_keyword->end : statements->base.location.end
- },
- },
+ .base = (
+ (statements == NULL)
+ ? PM_NODE_INIT_TOKEN(parser, PM_BEGIN_NODE, 0, begin_keyword)
+ : PM_NODE_INIT_TOKEN_NODE(parser, PM_BEGIN_NODE, 0, begin_keyword, statements)
+ ),
.begin_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(begin_keyword),
.statements = statements,
- .end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
+ .end_keyword_loc = { 0 }
};
return node;
@@ -2507,16 +2392,14 @@ pm_begin_node_end_keyword_set(pm_begin_node_t *node, const pm_token_t *end_keywo
*/
static pm_block_argument_node_t *
pm_block_argument_node_create(pm_parser_t *parser, const pm_token_t *operator, pm_node_t *expression) {
- pm_block_argument_node_t *node = PM_ALLOC_NODE(parser, pm_block_argument_node_t);
+ pm_block_argument_node_t *node = PM_NODE_ALLOC(parser, pm_block_argument_node_t);
*node = (pm_block_argument_node_t) {
- {
- .type = PM_BLOCK_ARGUMENT_NODE,
- .location = {
- .start = operator->start,
- .end = expression == NULL ? operator->end : expression->location.end
- },
- },
+ .base = (
+ (expression == NULL)
+ ? PM_NODE_INIT_TOKEN(parser, PM_BLOCK_ARGUMENT_NODE, 0, operator)
+ : PM_NODE_INIT_TOKEN_NODE(parser, PM_BLOCK_ARGUMENT_NODE, 0, operator, expression)
+ ),
.expression = expression,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator)
};
@@ -2529,13 +2412,10 @@ pm_block_argument_node_create(pm_parser_t *parser, const pm_token_t *operator, p
*/
static pm_block_node_t *
pm_block_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const pm_token_t *opening, pm_node_t *parameters, pm_node_t *body, const pm_token_t *closing) {
- pm_block_node_t *node = PM_ALLOC_NODE(parser, pm_block_node_t);
+ pm_block_node_t *node = PM_NODE_ALLOC(parser, pm_block_node_t);
*node = (pm_block_node_t) {
- {
- .type = PM_BLOCK_NODE,
- .location = { .start = opening->start, .end = closing->end },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_BLOCK_NODE, 0, opening, closing),
.locals = *locals,
.parameters = parameters,
.body = body,
@@ -2552,16 +2432,14 @@ pm_block_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const p
static pm_block_parameter_node_t *
pm_block_parameter_node_create(pm_parser_t *parser, const pm_token_t *name, const pm_token_t *operator) {
assert(operator->type == PM_TOKEN_NOT_PROVIDED || operator->type == PM_TOKEN_UAMPERSAND || operator->type == PM_TOKEN_AMPERSAND);
- pm_block_parameter_node_t *node = PM_ALLOC_NODE(parser, pm_block_parameter_node_t);
+ pm_block_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_block_parameter_node_t);
*node = (pm_block_parameter_node_t) {
- {
- .type = PM_BLOCK_PARAMETER_NODE,
- .location = {
- .start = operator->start,
- .end = (name->type == PM_TOKEN_NOT_PROVIDED ? operator->end : name->end)
- },
- },
+ .base = (
+ (name->type == PM_TOKEN_NOT_PROVIDED)
+ ? PM_NODE_INIT_TOKEN(parser, PM_BLOCK_PARAMETER_NODE, 0, operator)
+ : PM_NODE_INIT_TOKENS(parser, PM_BLOCK_PARAMETER_NODE, 0, operator, name)
+ ),
.name = pm_parser_optional_constant_id_token(parser, name),
.name_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(name),
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator)
@@ -2575,7 +2453,7 @@ pm_block_parameter_node_create(pm_parser_t *parser, const pm_token_t *name, cons
*/
static pm_block_parameters_node_t *
pm_block_parameters_node_create(pm_parser_t *parser, pm_parameters_node_t *parameters, const pm_token_t *opening) {
- pm_block_parameters_node_t *node = PM_ALLOC_NODE(parser, pm_block_parameters_node_t);
+ pm_block_parameters_node_t *node = PM_NODE_ALLOC(parser, pm_block_parameters_node_t);
const uint8_t *start;
if (opening->type != PM_TOKEN_NOT_PROVIDED) {
@@ -2596,16 +2474,10 @@ pm_block_parameters_node_create(pm_parser_t *parser, pm_parameters_node_t *param
}
*node = (pm_block_parameters_node_t) {
- {
- .type = PM_BLOCK_PARAMETERS_NODE,
- .location = {
- .start = start,
- .end = end
- }
- },
+ .base = PM_NODE_INIT(parser, PM_BLOCK_PARAMETERS_NODE, 0, start, end),
.parameters = parameters,
.opening_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
- .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
+ .closing_loc = { 0 },
.locals = { 0 }
};
@@ -2628,13 +2500,10 @@ pm_block_parameters_node_closing_set(pm_block_parameters_node_t *node, const pm_
*/
static pm_block_local_variable_node_t *
pm_block_local_variable_node_create(pm_parser_t *parser, const pm_token_t *name) {
- pm_block_local_variable_node_t *node = PM_ALLOC_NODE(parser, pm_block_local_variable_node_t);
+ pm_block_local_variable_node_t *node = PM_NODE_ALLOC(parser, pm_block_local_variable_node_t);
*node = (pm_block_local_variable_node_t) {
- {
- .type = PM_BLOCK_LOCAL_VARIABLE_NODE,
- .location = PM_LOCATION_TOKEN_VALUE(name),
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_BLOCK_LOCAL_VARIABLE_NODE, 0, name),
.name = pm_parser_constant_id_token(parser, name)
};
@@ -2646,7 +2515,7 @@ pm_block_local_variable_node_create(pm_parser_t *parser, const pm_token_t *name)
*/
static void
pm_block_parameters_node_append_local(pm_block_parameters_node_t *node, const pm_block_local_variable_node_t *local) {
- pm_node_list_append(&node->locals, (pm_node_t *) local);
+ pm_node_list_append(&node->locals, UP(local));
if (node->base.location.start == NULL) node->base.location.start = local->base.location.start;
node->base.location.end = local->base.location.end;
@@ -2658,16 +2527,14 @@ pm_block_parameters_node_append_local(pm_block_parameters_node_t *node, const pm
static pm_break_node_t *
pm_break_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_arguments_node_t *arguments) {
assert(keyword->type == PM_TOKEN_KEYWORD_BREAK);
- pm_break_node_t *node = PM_ALLOC_NODE(parser, pm_break_node_t);
+ pm_break_node_t *node = PM_NODE_ALLOC(parser, pm_break_node_t);
*node = (pm_break_node_t) {
- {
- .type = PM_BREAK_NODE,
- .location = {
- .start = keyword->start,
- .end = (arguments == NULL ? keyword->end : arguments->base.location.end)
- },
- },
+ .base = (
+ (arguments == NULL)
+ ? PM_NODE_INIT_TOKEN(parser, PM_BREAK_NODE, 0, keyword)
+ : PM_NODE_INIT_TOKEN_NODE(parser, PM_BREAK_NODE, 0, keyword, arguments)
+ ),
.arguments = arguments,
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword)
};
@@ -2678,8 +2545,11 @@ pm_break_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_argument
// There are certain flags that we want to use internally but don't want to
// expose because they are not relevant beyond parsing. Therefore we'll define
// them here and not define them in config.yml/a header file.
-static const pm_node_flags_t PM_CALL_NODE_FLAGS_COMPARISON = 0x10;
-static const pm_node_flags_t PM_CALL_NODE_FLAGS_INDEX = 0x20;
+static const pm_node_flags_t PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY = (1 << 2);
+
+static const pm_node_flags_t PM_CALL_NODE_FLAGS_IMPLICIT_ARRAY = ((PM_CALL_NODE_FLAGS_LAST - 1) << 1);
+static const pm_node_flags_t PM_CALL_NODE_FLAGS_COMPARISON = ((PM_CALL_NODE_FLAGS_LAST - 1) << 2);
+static const pm_node_flags_t PM_CALL_NODE_FLAGS_INDEX = ((PM_CALL_NODE_FLAGS_LAST - 1) << 3);
/**
* Allocate and initialize a new CallNode node. This sets everything to NULL or
@@ -2688,20 +2558,17 @@ static const pm_node_flags_t PM_CALL_NODE_FLAGS_INDEX = 0x20;
*/
static pm_call_node_t *
pm_call_node_create(pm_parser_t *parser, pm_node_flags_t flags) {
- pm_call_node_t *node = PM_ALLOC_NODE(parser, pm_call_node_t);
+ pm_call_node_t *node = PM_NODE_ALLOC(parser, pm_call_node_t);
*node = (pm_call_node_t) {
- {
- .type = PM_CALL_NODE,
- .flags = flags,
- .location = PM_LOCATION_NULL_VALUE(parser),
- },
+ .base = PM_NODE_INIT_BASE(parser, PM_CALL_NODE, flags),
.receiver = NULL,
- .call_operator_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
- .message_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
- .opening_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
+ .call_operator_loc = { 0 },
+ .message_loc = { 0 },
+ .opening_loc = { 0 },
.arguments = NULL,
- .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
+ .closing_loc = { 0 },
+ .equal_loc = { 0 },
.block = NULL,
.name = 0
};
@@ -2773,6 +2640,8 @@ pm_call_node_binary_create(pm_parser_t *parser, pm_node_t *receiver, pm_token_t
return node;
}
+static const uint8_t * parse_operator_symbol_name(const pm_token_t *);
+
/**
* Allocate and initialize a new CallNode node from a call expression.
*/
@@ -2798,10 +2667,14 @@ pm_call_node_call_create(pm_parser_t *parser, pm_node_t *receiver, pm_token_t *o
node->block = arguments->block;
if (operator->type == PM_TOKEN_AMPERSAND_DOT) {
- pm_node_flag_set((pm_node_t *)node, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION);
+ pm_node_flag_set(UP(node), PM_CALL_NODE_FLAGS_SAFE_NAVIGATION);
}
- node->name = pm_parser_constant_id_token(parser, message);
+ /**
+ * If the final character is `@` as is the case for `foo.~@`,
+ * we should ignore the @ in the same way we do for symbols.
+ */
+ node->name = pm_parser_constant_id_location(parser, message->start, parse_operator_symbol_name(message));
return node;
}
@@ -2907,7 +2780,7 @@ pm_call_node_shorthand_create(pm_parser_t *parser, pm_node_t *receiver, pm_token
node->block = arguments->block;
if (operator->type == PM_TOKEN_AMPERSAND_DOT) {
- pm_node_flag_set((pm_node_t *)node, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION);
+ pm_node_flag_set(UP(node), PM_CALL_NODE_FLAGS_SAFE_NAVIGATION);
}
node->name = pm_parser_constant_id_constant(parser, "call", 4);
@@ -2958,7 +2831,7 @@ pm_call_node_writable_p(const pm_parser_t *parser, const pm_call_node_t *node) {
(node->message_loc.start != NULL) &&
(node->message_loc.end[-1] != '!') &&
(node->message_loc.end[-1] != '?') &&
- char_is_identifier_start(parser, node->message_loc.start) &&
+ char_is_identifier_start(parser, node->message_loc.start, parser->end - node->message_loc.start) &&
(node->opening_loc.start == NULL) &&
(node->arguments == NULL) &&
(node->block == NULL)
@@ -2992,17 +2865,10 @@ static pm_call_and_write_node_t *
pm_call_and_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) {
assert(target->block == NULL);
assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
- pm_call_and_write_node_t *node = PM_ALLOC_NODE(parser, pm_call_and_write_node_t);
+ pm_call_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_call_and_write_node_t);
*node = (pm_call_and_write_node_t) {
- {
- .type = PM_CALL_AND_WRITE_NODE,
- .flags = target->base.flags,
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CALL_AND_WRITE_NODE, FL(target), target, value),
.receiver = target->receiver,
.call_operator_loc = target->call_operator_loc,
.message_loc = target->message_loc,
@@ -3028,7 +2894,7 @@ pm_call_and_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const
*/
static void
pm_index_arguments_check(pm_parser_t *parser, const pm_arguments_node_t *arguments, const pm_node_t *block) {
- if (parser->version != PM_OPTIONS_VERSION_CRUBY_3_3) {
+ if (parser->version >= PM_OPTIONS_VERSION_CRUBY_3_4) {
if (arguments != NULL && PM_NODE_FLAG_P(arguments, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS)) {
pm_node_t *node;
PM_NODE_LIST_FOREACH(&arguments->arguments, index, node) {
@@ -3051,25 +2917,19 @@ pm_index_arguments_check(pm_parser_t *parser, const pm_arguments_node_t *argumen
static pm_index_and_write_node_t *
pm_index_and_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) {
assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
- pm_index_and_write_node_t *node = PM_ALLOC_NODE(parser, pm_index_and_write_node_t);
+ pm_index_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_index_and_write_node_t);
pm_index_arguments_check(parser, target->arguments, target->block);
+ assert(!target->block || PM_NODE_TYPE_P(target->block, PM_BLOCK_ARGUMENT_NODE));
*node = (pm_index_and_write_node_t) {
- {
- .type = PM_INDEX_AND_WRITE_NODE,
- .flags = target->base.flags,
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_INDEX_AND_WRITE_NODE, FL(target), target, value),
.receiver = target->receiver,
.call_operator_loc = target->call_operator_loc,
.opening_loc = target->opening_loc,
.arguments = target->arguments,
.closing_loc = target->closing_loc,
- .block = target->block,
+ .block = (pm_block_argument_node_t *) target->block,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.value = value
};
@@ -3088,17 +2948,10 @@ pm_index_and_write_node_create(pm_parser_t *parser, pm_call_node_t *target, cons
static pm_call_operator_write_node_t *
pm_call_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) {
assert(target->block == NULL);
- pm_call_operator_write_node_t *node = PM_ALLOC_NODE(parser, pm_call_operator_write_node_t);
+ pm_call_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_call_operator_write_node_t);
*node = (pm_call_operator_write_node_t) {
- {
- .type = PM_CALL_OPERATOR_WRITE_NODE,
- .flags = target->base.flags,
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CALL_OPERATOR_WRITE_NODE, FL(target), target, value),
.receiver = target->receiver,
.call_operator_loc = target->call_operator_loc,
.message_loc = target->message_loc,
@@ -3124,25 +2977,19 @@ pm_call_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target,
*/
static pm_index_operator_write_node_t *
pm_index_operator_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) {
- pm_index_operator_write_node_t *node = PM_ALLOC_NODE(parser, pm_index_operator_write_node_t);
+ pm_index_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_index_operator_write_node_t);
pm_index_arguments_check(parser, target->arguments, target->block);
+ assert(!target->block || PM_NODE_TYPE_P(target->block, PM_BLOCK_ARGUMENT_NODE));
*node = (pm_index_operator_write_node_t) {
- {
- .type = PM_INDEX_OPERATOR_WRITE_NODE,
- .flags = target->base.flags,
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_INDEX_OPERATOR_WRITE_NODE, FL(target), target, value),
.receiver = target->receiver,
.call_operator_loc = target->call_operator_loc,
.opening_loc = target->opening_loc,
.arguments = target->arguments,
.closing_loc = target->closing_loc,
- .block = target->block,
+ .block = (pm_block_argument_node_t *) target->block,
.binary_operator = pm_parser_constant_id_location(parser, operator->start, operator->end - 1),
.binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.value = value
@@ -3163,17 +3010,10 @@ static pm_call_or_write_node_t *
pm_call_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) {
assert(target->block == NULL);
assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL);
- pm_call_or_write_node_t *node = PM_ALLOC_NODE(parser, pm_call_or_write_node_t);
+ pm_call_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_call_or_write_node_t);
*node = (pm_call_or_write_node_t) {
- {
- .type = PM_CALL_OR_WRITE_NODE,
- .flags = target->base.flags,
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CALL_OR_WRITE_NODE, FL(target), target, value),
.receiver = target->receiver,
.call_operator_loc = target->call_operator_loc,
.message_loc = target->message_loc,
@@ -3199,25 +3039,19 @@ pm_call_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const
static pm_index_or_write_node_t *
pm_index_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const pm_token_t *operator, pm_node_t *value) {
assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL);
- pm_index_or_write_node_t *node = PM_ALLOC_NODE(parser, pm_index_or_write_node_t);
+ pm_index_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_index_or_write_node_t);
pm_index_arguments_check(parser, target->arguments, target->block);
+ assert(!target->block || PM_NODE_TYPE_P(target->block, PM_BLOCK_ARGUMENT_NODE));
*node = (pm_index_or_write_node_t) {
- {
- .type = PM_INDEX_OR_WRITE_NODE,
- .flags = target->base.flags,
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_INDEX_OR_WRITE_NODE, FL(target), target, value),
.receiver = target->receiver,
.call_operator_loc = target->call_operator_loc,
.opening_loc = target->opening_loc,
.arguments = target->arguments,
.closing_loc = target->closing_loc,
- .block = target->block,
+ .block = (pm_block_argument_node_t *) target->block,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.value = value
};
@@ -3236,20 +3070,27 @@ pm_index_or_write_node_create(pm_parser_t *parser, pm_call_node_t *target, const
*/
static pm_call_target_node_t *
pm_call_target_node_create(pm_parser_t *parser, pm_call_node_t *target) {
- pm_call_target_node_t *node = PM_ALLOC_NODE(parser, pm_call_target_node_t);
+ pm_call_target_node_t *node = PM_NODE_ALLOC(parser, pm_call_target_node_t);
*node = (pm_call_target_node_t) {
- {
- .type = PM_CALL_TARGET_NODE,
- .flags = target->base.flags,
- .location = target->base.location
- },
+ .base = PM_NODE_INIT_NODE(parser, PM_CALL_TARGET_NODE, FL(target), target),
.receiver = target->receiver,
.call_operator_loc = target->call_operator_loc,
.name = target->name,
.message_loc = target->message_loc
};
+ /* It is possible to get here where we have parsed an invalid syntax tree
+ * where the call operator was not present. In that case we will have a
+ * problem because it is a required location. In this case we need to fill
+ * it in with a fake location so that the syntax tree remains valid. */
+ if (node->call_operator_loc.start == NULL) {
+ node->call_operator_loc = (pm_location_t) {
+ .start = target->base.location.start,
+ .end = target->base.location.start
+ };
+ }
+
// Here we're going to free the target, since it is no longer necessary.
// However, we don't want to call `pm_node_destroy` because we want to keep
// around all of its children since we just reused them.
@@ -3264,22 +3105,18 @@ pm_call_target_node_create(pm_parser_t *parser, pm_call_node_t *target) {
*/
static pm_index_target_node_t *
pm_index_target_node_create(pm_parser_t *parser, pm_call_node_t *target) {
- pm_index_target_node_t *node = PM_ALLOC_NODE(parser, pm_index_target_node_t);
- pm_node_flags_t flags = target->base.flags;
+ pm_index_target_node_t *node = PM_NODE_ALLOC(parser, pm_index_target_node_t);
pm_index_arguments_check(parser, target->arguments, target->block);
+ assert(!target->block || PM_NODE_TYPE_P(target->block, PM_BLOCK_ARGUMENT_NODE));
*node = (pm_index_target_node_t) {
- {
- .type = PM_INDEX_TARGET_NODE,
- .flags = flags | PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE,
- .location = target->base.location
- },
+ .base = PM_NODE_INIT_NODE(parser, PM_INDEX_TARGET_NODE, FL(target) | PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE, target),
.receiver = target->receiver,
.opening_loc = target->opening_loc,
.arguments = target->arguments,
.closing_loc = target->closing_loc,
- .block = target->block
+ .block = (pm_block_argument_node_t *) target->block,
};
// Here we're going to free the target, since it is no longer necessary.
@@ -3294,17 +3131,11 @@ pm_index_target_node_create(pm_parser_t *parser, pm_call_node_t *target) {
* Allocate and initialize a new CapturePatternNode node.
*/
static pm_capture_pattern_node_t *
-pm_capture_pattern_node_create(pm_parser_t *parser, pm_node_t *value, pm_node_t *target, const pm_token_t *operator) {
- pm_capture_pattern_node_t *node = PM_ALLOC_NODE(parser, pm_capture_pattern_node_t);
+pm_capture_pattern_node_create(pm_parser_t *parser, pm_node_t *value, pm_local_variable_target_node_t *target, const pm_token_t *operator) {
+ pm_capture_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_capture_pattern_node_t);
*node = (pm_capture_pattern_node_t) {
- {
- .type = PM_CAPTURE_PATTERN_NODE,
- .location = {
- .start = value->location.start,
- .end = target->location.end
- },
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CAPTURE_PATTERN_NODE, 0, value, target),
.value = value,
.target = target,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator)
@@ -3318,18 +3149,12 @@ pm_capture_pattern_node_create(pm_parser_t *parser, pm_node_t *value, pm_node_t
*/
static pm_case_node_t *
pm_case_node_create(pm_parser_t *parser, const pm_token_t *case_keyword, pm_node_t *predicate, const pm_token_t *end_keyword) {
- pm_case_node_t *node = PM_ALLOC_NODE(parser, pm_case_node_t);
+ pm_case_node_t *node = PM_NODE_ALLOC(parser, pm_case_node_t);
*node = (pm_case_node_t) {
- {
- .type = PM_CASE_NODE,
- .location = {
- .start = case_keyword->start,
- .end = end_keyword->end
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_CASE_NODE, 0, case_keyword, end_keyword),
.predicate = predicate,
- .consequent = NULL,
+ .else_clause = NULL,
.case_keyword_loc = PM_LOCATION_TOKEN_VALUE(case_keyword),
.end_keyword_loc = PM_LOCATION_TOKEN_VALUE(end_keyword),
.conditions = { 0 }
@@ -3350,12 +3175,12 @@ pm_case_node_condition_append(pm_case_node_t *node, pm_node_t *condition) {
}
/**
- * Set the consequent of a CaseNode node.
+ * Set the else clause of a CaseNode node.
*/
static void
-pm_case_node_consequent_set(pm_case_node_t *node, pm_else_node_t *consequent) {
- node->consequent = consequent;
- node->base.location.end = consequent->base.location.end;
+pm_case_node_else_clause_set(pm_case_node_t *node, pm_else_node_t *else_clause) {
+ node->else_clause = else_clause;
+ node->base.location.end = else_clause->base.location.end;
}
/**
@@ -3372,18 +3197,12 @@ pm_case_node_end_keyword_loc_set(pm_case_node_t *node, const pm_token_t *end_key
*/
static pm_case_match_node_t *
pm_case_match_node_create(pm_parser_t *parser, const pm_token_t *case_keyword, pm_node_t *predicate, const pm_token_t *end_keyword) {
- pm_case_match_node_t *node = PM_ALLOC_NODE(parser, pm_case_match_node_t);
+ pm_case_match_node_t *node = PM_NODE_ALLOC(parser, pm_case_match_node_t);
*node = (pm_case_match_node_t) {
- {
- .type = PM_CASE_MATCH_NODE,
- .location = {
- .start = case_keyword->start,
- .end = end_keyword->end
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_CASE_MATCH_NODE, 0, case_keyword, end_keyword),
.predicate = predicate,
- .consequent = NULL,
+ .else_clause = NULL,
.case_keyword_loc = PM_LOCATION_TOKEN_VALUE(case_keyword),
.end_keyword_loc = PM_LOCATION_TOKEN_VALUE(end_keyword),
.conditions = { 0 }
@@ -3404,12 +3223,12 @@ pm_case_match_node_condition_append(pm_case_match_node_t *node, pm_node_t *condi
}
/**
- * Set the consequent of a CaseMatchNode node.
+ * Set the else clause of a CaseMatchNode node.
*/
static void
-pm_case_match_node_consequent_set(pm_case_match_node_t *node, pm_else_node_t *consequent) {
- node->consequent = consequent;
- node->base.location.end = consequent->base.location.end;
+pm_case_match_node_else_clause_set(pm_case_match_node_t *node, pm_else_node_t *else_clause) {
+ node->else_clause = else_clause;
+ node->base.location.end = else_clause->base.location.end;
}
/**
@@ -3426,13 +3245,10 @@ pm_case_match_node_end_keyword_loc_set(pm_case_match_node_t *node, const pm_toke
*/
static pm_class_node_t *
pm_class_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const pm_token_t *class_keyword, pm_node_t *constant_path, const pm_token_t *name, const pm_token_t *inheritance_operator, pm_node_t *superclass, pm_node_t *body, const pm_token_t *end_keyword) {
- pm_class_node_t *node = PM_ALLOC_NODE(parser, pm_class_node_t);
+ pm_class_node_t *node = PM_NODE_ALLOC(parser, pm_class_node_t);
*node = (pm_class_node_t) {
- {
- .type = PM_CLASS_NODE,
- .location = { .start = class_keyword->start, .end = end_keyword->end },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_CLASS_NODE, 0, class_keyword, end_keyword),
.locals = *locals,
.class_keyword_loc = PM_LOCATION_TOKEN_VALUE(class_keyword),
.constant_path = constant_path,
@@ -3452,16 +3268,10 @@ pm_class_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const p
static pm_class_variable_and_write_node_t *
pm_class_variable_and_write_node_create(pm_parser_t *parser, pm_class_variable_read_node_t *target, const pm_token_t *operator, pm_node_t *value) {
assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
- pm_class_variable_and_write_node_t *node = PM_ALLOC_NODE(parser, pm_class_variable_and_write_node_t);
+ pm_class_variable_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_class_variable_and_write_node_t);
*node = (pm_class_variable_and_write_node_t) {
- {
- .type = PM_CLASS_VARIABLE_AND_WRITE_NODE,
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CLASS_VARIABLE_AND_WRITE_NODE, 0, target, value),
.name = target->name,
.name_loc = target->base.location,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -3476,16 +3286,10 @@ pm_class_variable_and_write_node_create(pm_parser_t *parser, pm_class_variable_r
*/
static pm_class_variable_operator_write_node_t *
pm_class_variable_operator_write_node_create(pm_parser_t *parser, pm_class_variable_read_node_t *target, const pm_token_t *operator, pm_node_t *value) {
- pm_class_variable_operator_write_node_t *node = PM_ALLOC_NODE(parser, pm_class_variable_operator_write_node_t);
+ pm_class_variable_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_class_variable_operator_write_node_t);
*node = (pm_class_variable_operator_write_node_t) {
- {
- .type = PM_CLASS_VARIABLE_OPERATOR_WRITE_NODE,
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CLASS_VARIABLE_OPERATOR_WRITE_NODE, 0, target, value),
.name = target->name,
.name_loc = target->base.location,
.binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -3502,16 +3306,10 @@ pm_class_variable_operator_write_node_create(pm_parser_t *parser, pm_class_varia
static pm_class_variable_or_write_node_t *
pm_class_variable_or_write_node_create(pm_parser_t *parser, pm_class_variable_read_node_t *target, const pm_token_t *operator, pm_node_t *value) {
assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL);
- pm_class_variable_or_write_node_t *node = PM_ALLOC_NODE(parser, pm_class_variable_or_write_node_t);
+ pm_class_variable_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_class_variable_or_write_node_t);
*node = (pm_class_variable_or_write_node_t) {
- {
- .type = PM_CLASS_VARIABLE_OR_WRITE_NODE,
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CLASS_VARIABLE_OR_WRITE_NODE, 0, target, value),
.name = target->name,
.name_loc = target->base.location,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -3527,13 +3325,10 @@ pm_class_variable_or_write_node_create(pm_parser_t *parser, pm_class_variable_re
static pm_class_variable_read_node_t *
pm_class_variable_read_node_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_CLASS_VARIABLE);
- pm_class_variable_read_node_t *node = PM_ALLOC_NODE(parser, pm_class_variable_read_node_t);
+ pm_class_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_class_variable_read_node_t);
*node = (pm_class_variable_read_node_t) {
- {
- .type = PM_CLASS_VARIABLE_READ_NODE,
- .location = PM_LOCATION_TOKEN_VALUE(token)
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_CLASS_VARIABLE_READ_NODE, 0, token),
.name = pm_parser_constant_id_token(parser, token)
};
@@ -3541,22 +3336,31 @@ pm_class_variable_read_node_create(pm_parser_t *parser, const pm_token_t *token)
}
/**
+ * True if the given node is an implicit array node on a write, as in:
+ *
+ * a = *b
+ * a = 1, 2, 3
+ */
+static inline pm_node_flags_t
+pm_implicit_array_write_flags(const pm_node_t *node, pm_node_flags_t flags) {
+ if (PM_NODE_TYPE_P(node, PM_ARRAY_NODE) && ((const pm_array_node_t *) node)->opening_loc.start == NULL) {
+ return flags;
+ }
+ return 0;
+}
+
+/**
* Initialize a new ClassVariableWriteNode node from a ClassVariableRead node.
*/
static pm_class_variable_write_node_t *
pm_class_variable_write_node_create(pm_parser_t *parser, pm_class_variable_read_node_t *read_node, pm_token_t *operator, pm_node_t *value) {
- pm_class_variable_write_node_t *node = PM_ALLOC_NODE(parser, pm_class_variable_write_node_t);
+ pm_class_variable_write_node_t *node = PM_NODE_ALLOC(parser, pm_class_variable_write_node_t);
+ pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY);
*node = (pm_class_variable_write_node_t) {
- {
- .type = PM_CLASS_VARIABLE_WRITE_NODE,
- .location = {
- .start = read_node->base.location.start,
- .end = value->location.end
- },
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CLASS_VARIABLE_WRITE_NODE, flags, read_node, value),
.name = read_node->name,
- .name_loc = PM_LOCATION_NODE_VALUE((pm_node_t *) read_node),
+ .name_loc = PM_LOCATION_NODE_VALUE(UP(read_node)),
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.value = value
};
@@ -3570,16 +3374,10 @@ pm_class_variable_write_node_create(pm_parser_t *parser, pm_class_variable_read_
static pm_constant_path_and_write_node_t *
pm_constant_path_and_write_node_create(pm_parser_t *parser, pm_constant_path_node_t *target, const pm_token_t *operator, pm_node_t *value) {
assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
- pm_constant_path_and_write_node_t *node = PM_ALLOC_NODE(parser, pm_constant_path_and_write_node_t);
+ pm_constant_path_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_path_and_write_node_t);
*node = (pm_constant_path_and_write_node_t) {
- {
- .type = PM_CONSTANT_PATH_AND_WRITE_NODE,
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CONSTANT_PATH_AND_WRITE_NODE, 0, target, value),
.target = target,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.value = value
@@ -3593,16 +3391,10 @@ pm_constant_path_and_write_node_create(pm_parser_t *parser, pm_constant_path_nod
*/
static pm_constant_path_operator_write_node_t *
pm_constant_path_operator_write_node_create(pm_parser_t *parser, pm_constant_path_node_t *target, const pm_token_t *operator, pm_node_t *value) {
- pm_constant_path_operator_write_node_t *node = PM_ALLOC_NODE(parser, pm_constant_path_operator_write_node_t);
+ pm_constant_path_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_path_operator_write_node_t);
*node = (pm_constant_path_operator_write_node_t) {
- {
- .type = PM_CONSTANT_PATH_OPERATOR_WRITE_NODE,
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CONSTANT_PATH_OPERATOR_WRITE_NODE, 0, target, value),
.target = target,
.binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.value = value,
@@ -3618,16 +3410,10 @@ pm_constant_path_operator_write_node_create(pm_parser_t *parser, pm_constant_pat
static pm_constant_path_or_write_node_t *
pm_constant_path_or_write_node_create(pm_parser_t *parser, pm_constant_path_node_t *target, const pm_token_t *operator, pm_node_t *value) {
assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL);
- pm_constant_path_or_write_node_t *node = PM_ALLOC_NODE(parser, pm_constant_path_or_write_node_t);
+ pm_constant_path_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_path_or_write_node_t);
*node = (pm_constant_path_or_write_node_t) {
- {
- .type = PM_CONSTANT_PATH_OR_WRITE_NODE,
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CONSTANT_PATH_OR_WRITE_NODE, 0, target, value),
.target = target,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.value = value
@@ -3642,26 +3428,30 @@ pm_constant_path_or_write_node_create(pm_parser_t *parser, pm_constant_path_node
static pm_constant_path_node_t *
pm_constant_path_node_create(pm_parser_t *parser, pm_node_t *parent, const pm_token_t *delimiter, const pm_token_t *name_token) {
pm_assert_value_expression(parser, parent);
- pm_constant_path_node_t *node = PM_ALLOC_NODE(parser, pm_constant_path_node_t);
+ pm_constant_path_node_t *node = PM_NODE_ALLOC(parser, pm_constant_path_node_t);
pm_constant_id_t name = PM_CONSTANT_ID_UNSET;
if (name_token->type == PM_TOKEN_CONSTANT) {
name = pm_parser_constant_id_token(parser, name_token);
}
- *node = (pm_constant_path_node_t) {
- {
- .type = PM_CONSTANT_PATH_NODE,
- .location = {
- .start = parent == NULL ? delimiter->start : parent->location.start,
- .end = name_token->end
- },
- },
- .parent = parent,
- .name = name,
- .delimiter_loc = PM_LOCATION_TOKEN_VALUE(delimiter),
- .name_loc = PM_LOCATION_TOKEN_VALUE(name_token)
- };
+ if (parent == NULL) {
+ *node = (pm_constant_path_node_t) {
+ .base = PM_NODE_INIT_TOKENS(parser, PM_CONSTANT_PATH_NODE, 0, delimiter, name_token),
+ .parent = parent,
+ .name = name,
+ .delimiter_loc = PM_LOCATION_TOKEN_VALUE(delimiter),
+ .name_loc = PM_LOCATION_TOKEN_VALUE(name_token)
+ };
+ } else {
+ *node = (pm_constant_path_node_t) {
+ .base = PM_NODE_INIT_NODE_TOKEN(parser, PM_CONSTANT_PATH_NODE, 0, parent, name_token),
+ .parent = parent,
+ .name = name,
+ .delimiter_loc = PM_LOCATION_TOKEN_VALUE(delimiter),
+ .name_loc = PM_LOCATION_TOKEN_VALUE(name_token)
+ };
+ }
return node;
}
@@ -3671,16 +3461,11 @@ pm_constant_path_node_create(pm_parser_t *parser, pm_node_t *parent, const pm_to
*/
static pm_constant_path_write_node_t *
pm_constant_path_write_node_create(pm_parser_t *parser, pm_constant_path_node_t *target, const pm_token_t *operator, pm_node_t *value) {
- pm_constant_path_write_node_t *node = PM_ALLOC_NODE(parser, pm_constant_path_write_node_t);
+ pm_constant_path_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_path_write_node_t);
+ pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY);
*node = (pm_constant_path_write_node_t) {
- {
- .type = PM_CONSTANT_PATH_WRITE_NODE,
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- },
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CONSTANT_PATH_WRITE_NODE, flags, target, value),
.target = target,
.operator_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(operator),
.value = value
@@ -3695,16 +3480,10 @@ pm_constant_path_write_node_create(pm_parser_t *parser, pm_constant_path_node_t
static pm_constant_and_write_node_t *
pm_constant_and_write_node_create(pm_parser_t *parser, pm_constant_read_node_t *target, const pm_token_t *operator, pm_node_t *value) {
assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
- pm_constant_and_write_node_t *node = PM_ALLOC_NODE(parser, pm_constant_and_write_node_t);
+ pm_constant_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_and_write_node_t);
*node = (pm_constant_and_write_node_t) {
- {
- .type = PM_CONSTANT_AND_WRITE_NODE,
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CONSTANT_AND_WRITE_NODE, 0, target, value),
.name = target->name,
.name_loc = target->base.location,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -3719,16 +3498,10 @@ pm_constant_and_write_node_create(pm_parser_t *parser, pm_constant_read_node_t *
*/
static pm_constant_operator_write_node_t *
pm_constant_operator_write_node_create(pm_parser_t *parser, pm_constant_read_node_t *target, const pm_token_t *operator, pm_node_t *value) {
- pm_constant_operator_write_node_t *node = PM_ALLOC_NODE(parser, pm_constant_operator_write_node_t);
+ pm_constant_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_operator_write_node_t);
*node = (pm_constant_operator_write_node_t) {
- {
- .type = PM_CONSTANT_OPERATOR_WRITE_NODE,
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CONSTANT_OPERATOR_WRITE_NODE, 0, target, value),
.name = target->name,
.name_loc = target->base.location,
.binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -3745,16 +3518,10 @@ pm_constant_operator_write_node_create(pm_parser_t *parser, pm_constant_read_nod
static pm_constant_or_write_node_t *
pm_constant_or_write_node_create(pm_parser_t *parser, pm_constant_read_node_t *target, const pm_token_t *operator, pm_node_t *value) {
assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL);
- pm_constant_or_write_node_t *node = PM_ALLOC_NODE(parser, pm_constant_or_write_node_t);
+ pm_constant_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_or_write_node_t);
*node = (pm_constant_or_write_node_t) {
- {
- .type = PM_CONSTANT_OR_WRITE_NODE,
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CONSTANT_OR_WRITE_NODE, 0, target, value),
.name = target->name,
.name_loc = target->base.location,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -3770,13 +3537,10 @@ pm_constant_or_write_node_create(pm_parser_t *parser, pm_constant_read_node_t *t
static pm_constant_read_node_t *
pm_constant_read_node_create(pm_parser_t *parser, const pm_token_t *name) {
assert(name->type == PM_TOKEN_CONSTANT || name->type == PM_TOKEN_MISSING);
- pm_constant_read_node_t *node = PM_ALLOC_NODE(parser, pm_constant_read_node_t);
+ pm_constant_read_node_t *node = PM_NODE_ALLOC(parser, pm_constant_read_node_t);
*node = (pm_constant_read_node_t) {
- {
- .type = PM_CONSTANT_READ_NODE,
- .location = PM_LOCATION_TOKEN_VALUE(name)
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_CONSTANT_READ_NODE, 0, name),
.name = pm_parser_constant_id_token(parser, name)
};
@@ -3788,16 +3552,11 @@ pm_constant_read_node_create(pm_parser_t *parser, const pm_token_t *name) {
*/
static pm_constant_write_node_t *
pm_constant_write_node_create(pm_parser_t *parser, pm_constant_read_node_t *target, const pm_token_t *operator, pm_node_t *value) {
- pm_constant_write_node_t *node = PM_ALLOC_NODE(parser, pm_constant_write_node_t);
+ pm_constant_write_node_t *node = PM_NODE_ALLOC(parser, pm_constant_write_node_t);
+ pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY);
*node = (pm_constant_write_node_t) {
- {
- .type = PM_CONSTANT_WRITE_NODE,
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_CONSTANT_WRITE_NODE, flags, target, value),
.name = target->name,
.name_loc = target->base.location,
.operator_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(operator),
@@ -3815,7 +3574,7 @@ pm_def_node_receiver_check(pm_parser_t *parser, const pm_node_t *node) {
switch (PM_NODE_TYPE(node)) {
case PM_BEGIN_NODE: {
const pm_begin_node_t *cast = (pm_begin_node_t *) node;
- if (cast->statements != NULL) pm_def_node_receiver_check(parser, (pm_node_t *) cast->statements);
+ if (cast->statements != NULL) pm_def_node_receiver_check(parser, UP(cast->statements));
break;
}
case PM_PARENTHESES_NODE: {
@@ -3852,113 +3611,6 @@ pm_def_node_receiver_check(pm_parser_t *parser, const pm_node_t *node) {
}
/**
- * When a method body is created, we want to check if the last statement is a
- * return or a statement that houses a return. If it is, then we want to mark
- * that return as being redundant so that we can compile it differently but also
- * so that we can indicate that to the user.
- */
-static void
-pm_def_node_body_redundant_return(pm_node_t *node) {
- switch (PM_NODE_TYPE(node)) {
- case PM_RETURN_NODE:
- node->flags |= PM_RETURN_NODE_FLAGS_REDUNDANT;
- break;
- case PM_BEGIN_NODE: {
- pm_begin_node_t *cast = (pm_begin_node_t *) node;
-
- if (cast->statements != NULL && cast->else_clause == NULL) {
- pm_def_node_body_redundant_return((pm_node_t *) cast->statements);
- }
- break;
- }
- case PM_STATEMENTS_NODE: {
- pm_statements_node_t *cast = (pm_statements_node_t *) node;
-
- if (cast->body.size > 0) {
- pm_def_node_body_redundant_return(cast->body.nodes[cast->body.size - 1]);
- }
- break;
- }
- case PM_IF_NODE: {
- pm_if_node_t *cast = (pm_if_node_t *) node;
-
- if (cast->statements != NULL) {
- pm_def_node_body_redundant_return((pm_node_t *) cast->statements);
- }
-
- if (cast->consequent != NULL) {
- pm_def_node_body_redundant_return(cast->consequent);
- }
- break;
- }
- case PM_UNLESS_NODE: {
- pm_unless_node_t *cast = (pm_unless_node_t *) node;
-
- if (cast->statements != NULL) {
- pm_def_node_body_redundant_return((pm_node_t *) cast->statements);
- }
-
- if (cast->consequent != NULL) {
- pm_def_node_body_redundant_return((pm_node_t *) cast->consequent);
- }
- break;
- }
- case PM_ELSE_NODE: {
- pm_else_node_t *cast = (pm_else_node_t *) node;
-
- if (cast->statements != NULL) {
- pm_def_node_body_redundant_return((pm_node_t *) cast->statements);
- }
- break;
- }
- case PM_CASE_NODE: {
- pm_case_node_t *cast = (pm_case_node_t *) node;
- pm_node_t *condition;
-
- PM_NODE_LIST_FOREACH(&cast->conditions, index, condition) {
- pm_def_node_body_redundant_return(condition);
- }
-
- if (cast->consequent != NULL) {
- pm_def_node_body_redundant_return((pm_node_t *) cast->consequent);
- }
- break;
- }
- case PM_WHEN_NODE: {
- pm_when_node_t *cast = (pm_when_node_t *) node;
-
- if (cast->statements != NULL) {
- pm_def_node_body_redundant_return((pm_node_t *) cast->statements);
- }
- break;
- }
- case PM_CASE_MATCH_NODE: {
- pm_case_match_node_t *cast = (pm_case_match_node_t *) node;
- pm_node_t *condition;
-
- PM_NODE_LIST_FOREACH(&cast->conditions, index, condition) {
- pm_def_node_body_redundant_return(condition);
- }
-
- if (cast->consequent != NULL) {
- pm_def_node_body_redundant_return((pm_node_t *) cast->consequent);
- }
- break;
- }
- case PM_IN_NODE: {
- pm_in_node_t *cast = (pm_in_node_t *) node;
-
- if (cast->statements != NULL) {
- pm_def_node_body_redundant_return((pm_node_t *) cast->statements);
- }
- break;
- }
- default:
- break;
- }
-}
-
-/**
* Allocate and initialize a new DefNode node.
*/
static pm_def_node_t *
@@ -3977,28 +3629,18 @@ pm_def_node_create(
const pm_token_t *equal,
const pm_token_t *end_keyword
) {
- pm_def_node_t *node = PM_ALLOC_NODE(parser, pm_def_node_t);
- const uint8_t *end;
+ pm_def_node_t *node = PM_NODE_ALLOC(parser, pm_def_node_t);
- if (end_keyword->type == PM_TOKEN_NOT_PROVIDED) {
- end = body->location.end;
- } else {
- end = end_keyword->end;
- }
-
- if ((receiver != NULL) && PM_NODE_TYPE_P(receiver, PM_PARENTHESES_NODE)) {
+ if (receiver != NULL) {
pm_def_node_receiver_check(parser, receiver);
}
- if (body != NULL) {
- pm_def_node_body_redundant_return(body);
- }
-
*node = (pm_def_node_t) {
- {
- .type = PM_DEF_NODE,
- .location = { .start = def_keyword->start, .end = end },
- },
+ .base = (
+ (end_keyword->type == PM_TOKEN_NOT_PROVIDED)
+ ? PM_NODE_INIT_TOKEN_NODE(parser, PM_DEF_NODE, 0, def_keyword, body)
+ : PM_NODE_INIT_TOKENS(parser, PM_DEF_NODE, 0, def_keyword, end_keyword)
+ ),
.name = name,
.name_loc = PM_LOCATION_TOKEN_VALUE(name_loc),
.receiver = receiver,
@@ -4020,21 +3662,19 @@ pm_def_node_create(
* Allocate a new DefinedNode node.
*/
static pm_defined_node_t *
-pm_defined_node_create(pm_parser_t *parser, const pm_token_t *lparen, pm_node_t *value, const pm_token_t *rparen, const pm_location_t *keyword_loc) {
- pm_defined_node_t *node = PM_ALLOC_NODE(parser, pm_defined_node_t);
+pm_defined_node_create(pm_parser_t *parser, const pm_token_t *lparen, pm_node_t *value, const pm_token_t *rparen, const pm_token_t *keyword) {
+ pm_defined_node_t *node = PM_NODE_ALLOC(parser, pm_defined_node_t);
*node = (pm_defined_node_t) {
- {
- .type = PM_DEFINED_NODE,
- .location = {
- .start = keyword_loc->start,
- .end = (rparen->type == PM_TOKEN_NOT_PROVIDED ? value->location.end : rparen->end)
- },
- },
+ .base = (
+ (rparen->type == PM_TOKEN_NOT_PROVIDED)
+ ? PM_NODE_INIT_TOKEN_NODE(parser, PM_DEFINED_NODE, 0, keyword, value)
+ : PM_NODE_INIT_TOKENS(parser, PM_DEFINED_NODE, 0, keyword, rparen)
+ ),
.lparen_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(lparen),
.value = value,
.rparen_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(rparen),
- .keyword_loc = *keyword_loc
+ .keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword)
};
return node;
@@ -4045,22 +3685,14 @@ pm_defined_node_create(pm_parser_t *parser, const pm_token_t *lparen, pm_node_t
*/
static pm_else_node_t *
pm_else_node_create(pm_parser_t *parser, const pm_token_t *else_keyword, pm_statements_node_t *statements, const pm_token_t *end_keyword) {
- pm_else_node_t *node = PM_ALLOC_NODE(parser, pm_else_node_t);
- const uint8_t *end = NULL;
- if ((end_keyword->type == PM_TOKEN_NOT_PROVIDED) && (statements != NULL)) {
- end = statements->base.location.end;
- } else {
- end = end_keyword->end;
- }
+ pm_else_node_t *node = PM_NODE_ALLOC(parser, pm_else_node_t);
*node = (pm_else_node_t) {
- {
- .type = PM_ELSE_NODE,
- .location = {
- .start = else_keyword->start,
- .end = end,
- },
- },
+ .base = (
+ ((end_keyword->type == PM_TOKEN_NOT_PROVIDED) && (statements != NULL))
+ ? PM_NODE_INIT_TOKEN_NODE(parser, PM_ELSE_NODE, 0, else_keyword, statements)
+ : PM_NODE_INIT_TOKENS(parser, PM_ELSE_NODE, 0, else_keyword, end_keyword)
+ ),
.else_keyword_loc = PM_LOCATION_TOKEN_VALUE(else_keyword),
.statements = statements,
.end_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(end_keyword)
@@ -4074,16 +3706,10 @@ pm_else_node_create(pm_parser_t *parser, const pm_token_t *else_keyword, pm_stat
*/
static pm_embedded_statements_node_t *
pm_embedded_statements_node_create(pm_parser_t *parser, const pm_token_t *opening, pm_statements_node_t *statements, const pm_token_t *closing) {
- pm_embedded_statements_node_t *node = PM_ALLOC_NODE(parser, pm_embedded_statements_node_t);
+ pm_embedded_statements_node_t *node = PM_NODE_ALLOC(parser, pm_embedded_statements_node_t);
*node = (pm_embedded_statements_node_t) {
- {
- .type = PM_EMBEDDED_STATEMENTS_NODE,
- .location = {
- .start = opening->start,
- .end = closing->end
- }
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_EMBEDDED_STATEMENTS_NODE, 0, opening, closing),
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
.statements = statements,
.closing_loc = PM_LOCATION_TOKEN_VALUE(closing)
@@ -4097,16 +3723,10 @@ pm_embedded_statements_node_create(pm_parser_t *parser, const pm_token_t *openin
*/
static pm_embedded_variable_node_t *
pm_embedded_variable_node_create(pm_parser_t *parser, const pm_token_t *operator, pm_node_t *variable) {
- pm_embedded_variable_node_t *node = PM_ALLOC_NODE(parser, pm_embedded_variable_node_t);
+ pm_embedded_variable_node_t *node = PM_NODE_ALLOC(parser, pm_embedded_variable_node_t);
*node = (pm_embedded_variable_node_t) {
- {
- .type = PM_EMBEDDED_VARIABLE_NODE,
- .location = {
- .start = operator->start,
- .end = variable->location.end
- }
- },
+ .base = PM_NODE_INIT_TOKEN_NODE(parser, PM_EMBEDDED_VARIABLE_NODE, 0, operator, variable),
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.variable = variable
};
@@ -4119,16 +3739,10 @@ pm_embedded_variable_node_create(pm_parser_t *parser, const pm_token_t *operator
*/
static pm_ensure_node_t *
pm_ensure_node_create(pm_parser_t *parser, const pm_token_t *ensure_keyword, pm_statements_node_t *statements, const pm_token_t *end_keyword) {
- pm_ensure_node_t *node = PM_ALLOC_NODE(parser, pm_ensure_node_t);
+ pm_ensure_node_t *node = PM_NODE_ALLOC(parser, pm_ensure_node_t);
*node = (pm_ensure_node_t) {
- {
- .type = PM_ENSURE_NODE,
- .location = {
- .start = ensure_keyword->start,
- .end = end_keyword->end
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_ENSURE_NODE, 0, ensure_keyword, end_keyword),
.ensure_keyword_loc = PM_LOCATION_TOKEN_VALUE(ensure_keyword),
.statements = statements,
.end_keyword_loc = PM_LOCATION_TOKEN_VALUE(end_keyword)
@@ -4143,13 +3757,11 @@ pm_ensure_node_create(pm_parser_t *parser, const pm_token_t *ensure_keyword, pm_
static pm_false_node_t *
pm_false_node_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_KEYWORD_FALSE);
- pm_false_node_t *node = PM_ALLOC_NODE(parser, pm_false_node_t);
+ pm_false_node_t *node = PM_NODE_ALLOC(parser, pm_false_node_t);
- *node = (pm_false_node_t) {{
- .type = PM_FALSE_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .location = PM_LOCATION_TOKEN_VALUE(token)
- }};
+ *node = (pm_false_node_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_FALSE_NODE, PM_NODE_FLAG_STATIC_LITERAL, token)
+ };
return node;
}
@@ -4160,31 +3772,36 @@ pm_false_node_create(pm_parser_t *parser, const pm_token_t *token) {
*/
static pm_find_pattern_node_t *
pm_find_pattern_node_create(pm_parser_t *parser, pm_node_list_t *nodes) {
- pm_find_pattern_node_t *node = PM_ALLOC_NODE(parser, pm_find_pattern_node_t);
+ pm_find_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_find_pattern_node_t);
pm_node_t *left = nodes->nodes[0];
+ assert(PM_NODE_TYPE_P(left, PM_SPLAT_NODE));
+ pm_splat_node_t *left_splat_node = (pm_splat_node_t *) left;
+
pm_node_t *right;
if (nodes->size == 1) {
- right = (pm_node_t *) pm_missing_node_create(parser, left->location.end, left->location.end);
+ right = UP(pm_missing_node_create(parser, left->location.end, left->location.end));
} else {
right = nodes->nodes[nodes->size - 1];
+ assert(PM_NODE_TYPE_P(right, PM_SPLAT_NODE));
}
+#if PRISM_SERIALIZE_ONLY_SEMANTICS_FIELDS
+ // FindPatternNode#right is typed as SplatNode in this case, so replace the potential MissingNode with a SplatNode.
+ // The resulting AST will anyway be ignored, but this file still needs to compile.
+ pm_splat_node_t *right_splat_node = PM_NODE_TYPE_P(right, PM_SPLAT_NODE) ? (pm_splat_node_t *) right : left_splat_node;
+#else
+ pm_node_t *right_splat_node = right;
+#endif
*node = (pm_find_pattern_node_t) {
- {
- .type = PM_FIND_PATTERN_NODE,
- .location = {
- .start = left->location.start,
- .end = right->location.end,
- },
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_FIND_PATTERN_NODE, 0, left, right),
.constant = NULL,
- .left = left,
- .right = right,
+ .left = left_splat_node,
+ .right = right_splat_node,
.requireds = { 0 },
- .opening_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
- .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
+ .opening_loc = { 0 },
+ .closing_loc = { 0 }
};
// For now we're going to just copy over each pointer manually. This could be
@@ -4249,7 +3866,7 @@ pm_double_parse(pm_parser_t *parser, const pm_token_t *token) {
// If errno is set, then it should only be ERANGE. At this point we need to
// check if it's infinity (it should be).
- if (errno == ERANGE && isinf(value)) {
+ if (errno == ERANGE && PRISM_ISINF(value)) {
int warn_width;
const char *ellipsis;
@@ -4276,14 +3893,10 @@ pm_double_parse(pm_parser_t *parser, const pm_token_t *token) {
static pm_float_node_t *
pm_float_node_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_FLOAT);
- pm_float_node_t *node = PM_ALLOC_NODE(parser, pm_float_node_t);
+ pm_float_node_t *node = PM_NODE_ALLOC(parser, pm_float_node_t);
*node = (pm_float_node_t) {
- {
- .type = PM_FLOAT_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .location = PM_LOCATION_TOKEN_VALUE(token)
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_FLOAT_NODE, PM_NODE_FLAG_STATIC_LITERAL, token),
.value = pm_double_parse(parser, token)
};
@@ -4297,18 +3910,14 @@ static pm_imaginary_node_t *
pm_float_node_imaginary_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_FLOAT_IMAGINARY);
- pm_imaginary_node_t *node = PM_ALLOC_NODE(parser, pm_imaginary_node_t);
+ pm_imaginary_node_t *node = PM_NODE_ALLOC(parser, pm_imaginary_node_t);
*node = (pm_imaginary_node_t) {
- {
- .type = PM_IMAGINARY_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .location = PM_LOCATION_TOKEN_VALUE(token)
- },
- .numeric = (pm_node_t *) pm_float_node_create(parser, &((pm_token_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_IMAGINARY_NODE, PM_NODE_FLAG_STATIC_LITERAL, token),
+ .numeric = UP(pm_float_node_create(parser, &((pm_token_t) {
.type = PM_TOKEN_FLOAT,
.start = token->start,
.end = token->end - 1
- }))
+ })))
};
return node;
@@ -4321,13 +3930,9 @@ static pm_rational_node_t *
pm_float_node_rational_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_FLOAT_RATIONAL);
- pm_rational_node_t *node = PM_ALLOC_NODE(parser, pm_rational_node_t);
+ pm_rational_node_t *node = PM_NODE_ALLOC(parser, pm_rational_node_t);
*node = (pm_rational_node_t) {
- {
- .type = PM_RATIONAL_NODE,
- .flags = PM_INTEGER_BASE_FLAGS_DECIMAL | PM_NODE_FLAG_STATIC_LITERAL,
- .location = PM_LOCATION_TOKEN_VALUE(token)
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_RATIONAL_NODE, PM_INTEGER_BASE_FLAGS_DECIMAL | PM_NODE_FLAG_STATIC_LITERAL, token),
.numerator = { 0 },
.denominator = { 0 }
};
@@ -4347,7 +3952,7 @@ pm_float_node_rational_create(pm_parser_t *parser, const pm_token_t *token) {
const uint8_t *point = memchr(start, '.', length);
assert(point && "should have a decimal point");
- uint8_t *digits = malloc(length);
+ uint8_t *digits = xmalloc(length);
if (digits == NULL) {
fputs("[pm_float_node_rational_create] Failed to allocate memory", stderr);
abort();
@@ -4357,10 +3962,14 @@ pm_float_node_rational_create(pm_parser_t *parser, const pm_token_t *token) {
memcpy(digits + (point - start), point + 1, (unsigned long) (end - point - 1));
pm_integer_parse(&node->numerator, PM_INTEGER_BASE_DEFAULT, digits, digits + length - 1);
+ size_t fract_length = 0;
+ for (const uint8_t *fract = point; fract < end; ++fract) {
+ if (*fract != '_') ++fract_length;
+ }
digits[0] = '1';
- if (end - point > 1) memset(digits + 1, '0', (size_t) (end - point - 1));
- pm_integer_parse(&node->denominator, PM_INTEGER_BASE_DEFAULT, digits, digits + (end - point));
- free(digits);
+ if (fract_length > 1) memset(digits + 1, '0', fract_length - 1);
+ pm_integer_parse(&node->denominator, PM_INTEGER_BASE_DEFAULT, digits, digits + fract_length);
+ xfree(digits);
pm_integers_reduce(&node->numerator, &node->denominator);
return node;
@@ -4374,18 +3983,14 @@ static pm_imaginary_node_t *
pm_float_node_rational_imaginary_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_FLOAT_RATIONAL_IMAGINARY);
- pm_imaginary_node_t *node = PM_ALLOC_NODE(parser, pm_imaginary_node_t);
+ pm_imaginary_node_t *node = PM_NODE_ALLOC(parser, pm_imaginary_node_t);
*node = (pm_imaginary_node_t) {
- {
- .type = PM_IMAGINARY_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .location = PM_LOCATION_TOKEN_VALUE(token)
- },
- .numeric = (pm_node_t *) pm_float_node_rational_create(parser, &((pm_token_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_IMAGINARY_NODE, PM_NODE_FLAG_STATIC_LITERAL, token),
+ .numeric = UP(pm_float_node_rational_create(parser, &((pm_token_t) {
.type = PM_TOKEN_FLOAT_RATIONAL,
.start = token->start,
.end = token->end - 1
- }))
+ })))
};
return node;
@@ -4405,16 +4010,10 @@ pm_for_node_create(
const pm_token_t *do_keyword,
const pm_token_t *end_keyword
) {
- pm_for_node_t *node = PM_ALLOC_NODE(parser, pm_for_node_t);
+ pm_for_node_t *node = PM_NODE_ALLOC(parser, pm_for_node_t);
*node = (pm_for_node_t) {
- {
- .type = PM_FOR_NODE,
- .location = {
- .start = for_keyword->start,
- .end = end_keyword->end
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_FOR_NODE, 0, for_keyword, end_keyword),
.index = index,
.collection = collection,
.statements = statements,
@@ -4433,8 +4032,12 @@ pm_for_node_create(
static pm_forwarding_arguments_node_t *
pm_forwarding_arguments_node_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_UDOT_DOT_DOT);
- pm_forwarding_arguments_node_t *node = PM_ALLOC_NODE(parser, pm_forwarding_arguments_node_t);
- *node = (pm_forwarding_arguments_node_t) {{ .type = PM_FORWARDING_ARGUMENTS_NODE, .location = PM_LOCATION_TOKEN_VALUE(token) }};
+ pm_forwarding_arguments_node_t *node = PM_NODE_ALLOC(parser, pm_forwarding_arguments_node_t);
+
+ *node = (pm_forwarding_arguments_node_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_FORWARDING_ARGUMENTS_NODE, 0, token)
+ };
+
return node;
}
@@ -4444,8 +4047,12 @@ pm_forwarding_arguments_node_create(pm_parser_t *parser, const pm_token_t *token
static pm_forwarding_parameter_node_t *
pm_forwarding_parameter_node_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_UDOT_DOT_DOT);
- pm_forwarding_parameter_node_t *node = PM_ALLOC_NODE(parser, pm_forwarding_parameter_node_t);
- *node = (pm_forwarding_parameter_node_t) {{ .type = PM_FORWARDING_PARAMETER_NODE, .location = PM_LOCATION_TOKEN_VALUE(token) }};
+ pm_forwarding_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_forwarding_parameter_node_t);
+
+ *node = (pm_forwarding_parameter_node_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_FORWARDING_PARAMETER_NODE, 0, token)
+ };
+
return node;
}
@@ -4456,7 +4063,7 @@ static pm_forwarding_super_node_t *
pm_forwarding_super_node_create(pm_parser_t *parser, const pm_token_t *token, pm_arguments_t *arguments) {
assert(arguments->block == NULL || PM_NODE_TYPE_P(arguments->block, PM_BLOCK_NODE));
assert(token->type == PM_TOKEN_KEYWORD_SUPER);
- pm_forwarding_super_node_t *node = PM_ALLOC_NODE(parser, pm_forwarding_super_node_t);
+ pm_forwarding_super_node_t *node = PM_NODE_ALLOC(parser, pm_forwarding_super_node_t);
pm_block_node_t *block = NULL;
if (arguments->block != NULL) {
@@ -4464,13 +4071,11 @@ pm_forwarding_super_node_create(pm_parser_t *parser, const pm_token_t *token, pm
}
*node = (pm_forwarding_super_node_t) {
- {
- .type = PM_FORWARDING_SUPER_NODE,
- .location = {
- .start = token->start,
- .end = block != NULL ? block->base.location.end : token->end
- },
- },
+ .base = (
+ (block == NULL)
+ ? PM_NODE_INIT_TOKEN(parser, PM_FORWARDING_SUPER_NODE, 0, token)
+ : PM_NODE_INIT_TOKEN_NODE(parser, PM_FORWARDING_SUPER_NODE, 0, token, block)
+ ),
.block = block
};
@@ -4483,16 +4088,10 @@ pm_forwarding_super_node_create(pm_parser_t *parser, const pm_token_t *token, pm
*/
static pm_hash_pattern_node_t *
pm_hash_pattern_node_empty_create(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *closing) {
- pm_hash_pattern_node_t *node = PM_ALLOC_NODE(parser, pm_hash_pattern_node_t);
+ pm_hash_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_hash_pattern_node_t);
*node = (pm_hash_pattern_node_t) {
- {
- .type = PM_HASH_PATTERN_NODE,
- .location = {
- .start = opening->start,
- .end = closing->end
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_HASH_PATTERN_NODE, 0, opening, closing),
.constant = NULL,
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
.closing_loc = PM_LOCATION_TOKEN_VALUE(closing),
@@ -4508,15 +4107,15 @@ pm_hash_pattern_node_empty_create(pm_parser_t *parser, const pm_token_t *opening
*/
static pm_hash_pattern_node_t *
pm_hash_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *elements, pm_node_t *rest) {
- pm_hash_pattern_node_t *node = PM_ALLOC_NODE(parser, pm_hash_pattern_node_t);
+ pm_hash_pattern_node_t *node = PM_NODE_ALLOC(parser, pm_hash_pattern_node_t);
const uint8_t *start;
const uint8_t *end;
if (elements->size > 0) {
if (rest) {
- start = elements->nodes[0]->location.start;
- end = rest->location.end;
+ start = MIN(rest->location.start, elements->nodes[0]->location.start);
+ end = MAX(rest->location.end, elements->nodes[elements->size - 1]->location.end);
} else {
start = elements->nodes[0]->location.start;
end = elements->nodes[elements->size - 1]->location.end;
@@ -4528,25 +4127,15 @@ pm_hash_pattern_node_node_list_create(pm_parser_t *parser, pm_node_list_t *eleme
}
*node = (pm_hash_pattern_node_t) {
- {
- .type = PM_HASH_PATTERN_NODE,
- .location = {
- .start = start,
- .end = end
- },
- },
+ .base = PM_NODE_INIT(parser, PM_HASH_PATTERN_NODE, 0, start, end),
.constant = NULL,
.elements = { 0 },
.rest = rest,
- .opening_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
- .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
+ .opening_loc = { 0 },
+ .closing_loc = { 0 }
};
- pm_node_t *element;
- PM_NODE_LIST_FOREACH(elements, index, element) {
- pm_node_list_append(&node->elements, element);
- }
-
+ pm_node_list_concat(&node->elements, elements);
return node;
}
@@ -4576,16 +4165,10 @@ pm_global_variable_write_name(pm_parser_t *parser, const pm_node_t *target) {
static pm_global_variable_and_write_node_t *
pm_global_variable_and_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value) {
assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
- pm_global_variable_and_write_node_t *node = PM_ALLOC_NODE(parser, pm_global_variable_and_write_node_t);
+ pm_global_variable_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_and_write_node_t);
*node = (pm_global_variable_and_write_node_t) {
- {
- .type = PM_GLOBAL_VARIABLE_AND_WRITE_NODE,
- .location = {
- .start = target->location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_GLOBAL_VARIABLE_AND_WRITE_NODE, 0, target, value),
.name = pm_global_variable_write_name(parser, target),
.name_loc = target->location,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -4600,16 +4183,10 @@ pm_global_variable_and_write_node_create(pm_parser_t *parser, pm_node_t *target,
*/
static pm_global_variable_operator_write_node_t *
pm_global_variable_operator_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value) {
- pm_global_variable_operator_write_node_t *node = PM_ALLOC_NODE(parser, pm_global_variable_operator_write_node_t);
+ pm_global_variable_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_operator_write_node_t);
*node = (pm_global_variable_operator_write_node_t) {
- {
- .type = PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE,
- .location = {
- .start = target->location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE, 0, target, value),
.name = pm_global_variable_write_name(parser, target),
.name_loc = target->location,
.binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -4626,16 +4203,10 @@ pm_global_variable_operator_write_node_create(pm_parser_t *parser, pm_node_t *ta
static pm_global_variable_or_write_node_t *
pm_global_variable_or_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value) {
assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL);
- pm_global_variable_or_write_node_t *node = PM_ALLOC_NODE(parser, pm_global_variable_or_write_node_t);
+ pm_global_variable_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_or_write_node_t);
*node = (pm_global_variable_or_write_node_t) {
- {
- .type = PM_GLOBAL_VARIABLE_OR_WRITE_NODE,
- .location = {
- .start = target->location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_GLOBAL_VARIABLE_OR_WRITE_NODE, 0, target, value),
.name = pm_global_variable_write_name(parser, target),
.name_loc = target->location,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -4650,13 +4221,10 @@ pm_global_variable_or_write_node_create(pm_parser_t *parser, pm_node_t *target,
*/
static pm_global_variable_read_node_t *
pm_global_variable_read_node_create(pm_parser_t *parser, const pm_token_t *name) {
- pm_global_variable_read_node_t *node = PM_ALLOC_NODE(parser, pm_global_variable_read_node_t);
+ pm_global_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_read_node_t);
*node = (pm_global_variable_read_node_t) {
- {
- .type = PM_GLOBAL_VARIABLE_READ_NODE,
- .location = PM_LOCATION_TOKEN_VALUE(name),
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_GLOBAL_VARIABLE_READ_NODE, 0, name),
.name = pm_parser_constant_id_token(parser, name)
};
@@ -4668,13 +4236,10 @@ pm_global_variable_read_node_create(pm_parser_t *parser, const pm_token_t *name)
*/
static pm_global_variable_read_node_t *
pm_global_variable_read_node_synthesized_create(pm_parser_t *parser, pm_constant_id_t name) {
- pm_global_variable_read_node_t *node = PM_ALLOC_NODE(parser, pm_global_variable_read_node_t);
+ pm_global_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_read_node_t);
*node = (pm_global_variable_read_node_t) {
- {
- .type = PM_GLOBAL_VARIABLE_READ_NODE,
- .location = PM_LOCATION_NULL_VALUE(parser)
- },
+ .base = PM_NODE_INIT_BASE(parser, PM_GLOBAL_VARIABLE_READ_NODE, 0),
.name = name
};
@@ -4686,16 +4251,11 @@ pm_global_variable_read_node_synthesized_create(pm_parser_t *parser, pm_constant
*/
static pm_global_variable_write_node_t *
pm_global_variable_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value) {
- pm_global_variable_write_node_t *node = PM_ALLOC_NODE(parser, pm_global_variable_write_node_t);
+ pm_global_variable_write_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_write_node_t);
+ pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY);
*node = (pm_global_variable_write_node_t) {
- {
- .type = PM_GLOBAL_VARIABLE_WRITE_NODE,
- .location = {
- .start = target->location.start,
- .end = value->location.end
- },
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_GLOBAL_VARIABLE_WRITE_NODE, flags, target, value),
.name = pm_global_variable_write_name(parser, target),
.name_loc = PM_LOCATION_NODE_VALUE(target),
.operator_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(operator),
@@ -4710,13 +4270,10 @@ pm_global_variable_write_node_create(pm_parser_t *parser, pm_node_t *target, con
*/
static pm_global_variable_write_node_t *
pm_global_variable_write_node_synthesized_create(pm_parser_t *parser, pm_constant_id_t name, pm_node_t *value) {
- pm_global_variable_write_node_t *node = PM_ALLOC_NODE(parser, pm_global_variable_write_node_t);
+ pm_global_variable_write_node_t *node = PM_NODE_ALLOC(parser, pm_global_variable_write_node_t);
*node = (pm_global_variable_write_node_t) {
- {
- .type = PM_GLOBAL_VARIABLE_WRITE_NODE,
- .location = PM_LOCATION_NULL_VALUE(parser)
- },
+ .base = PM_NODE_INIT_BASE(parser, PM_GLOBAL_VARIABLE_WRITE_NODE, 0),
.name = name,
.name_loc = PM_LOCATION_NULL_VALUE(parser),
.operator_loc = PM_LOCATION_NULL_VALUE(parser),
@@ -4732,14 +4289,10 @@ pm_global_variable_write_node_synthesized_create(pm_parser_t *parser, pm_constan
static pm_hash_node_t *
pm_hash_node_create(pm_parser_t *parser, const pm_token_t *opening) {
assert(opening != NULL);
- pm_hash_node_t *node = PM_ALLOC_NODE(parser, pm_hash_node_t);
+ pm_hash_node_t *node = PM_NODE_ALLOC(parser, pm_hash_node_t);
*node = (pm_hash_node_t) {
- {
- .type = PM_HASH_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .location = PM_LOCATION_TOKEN_VALUE(opening)
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_HASH_NODE, PM_NODE_FLAG_STATIC_LITERAL, opening),
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
.closing_loc = PM_LOCATION_NULL_VALUE(parser),
.elements = { 0 }
@@ -4764,7 +4317,7 @@ pm_hash_node_elements_append(pm_hash_node_t *hash, pm_node_t *element) {
}
if (!static_literal) {
- pm_node_flag_unset((pm_node_t *)hash, PM_NODE_FLAG_STATIC_LITERAL);
+ pm_node_flag_unset(UP(hash), PM_NODE_FLAG_STATIC_LITERAL);
}
}
@@ -4783,17 +4336,17 @@ pm_if_node_create(pm_parser_t *parser,
pm_node_t *predicate,
const pm_token_t *then_keyword,
pm_statements_node_t *statements,
- pm_node_t *consequent,
+ pm_node_t *subsequent,
const pm_token_t *end_keyword
) {
pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL);
- pm_if_node_t *node = PM_ALLOC_NODE(parser, pm_if_node_t);
+ pm_if_node_t *node = PM_NODE_ALLOC(parser, pm_if_node_t);
const uint8_t *end;
if (end_keyword->type != PM_TOKEN_NOT_PROVIDED) {
end = end_keyword->end;
- } else if (consequent != NULL) {
- end = consequent->location.end;
+ } else if (subsequent != NULL) {
+ end = subsequent->location.end;
} else if (pm_statements_node_body_length(statements) != 0) {
end = statements->base.location.end;
} else {
@@ -4801,19 +4354,12 @@ pm_if_node_create(pm_parser_t *parser,
}
*node = (pm_if_node_t) {
- {
- .type = PM_IF_NODE,
- .flags = PM_NODE_FLAG_NEWLINE,
- .location = {
- .start = if_keyword->start,
- .end = end
- },
- },
+ .base = PM_NODE_INIT(parser, PM_IF_NODE, PM_NODE_FLAG_NEWLINE, if_keyword->start, end),
.if_keyword_loc = PM_LOCATION_TOKEN_VALUE(if_keyword),
.predicate = predicate,
.then_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(then_keyword),
.statements = statements,
- .consequent = consequent,
+ .subsequent = subsequent,
.end_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(end_keyword)
};
@@ -4826,26 +4372,19 @@ pm_if_node_create(pm_parser_t *parser,
static pm_if_node_t *
pm_if_node_modifier_create(pm_parser_t *parser, pm_node_t *statement, const pm_token_t *if_keyword, pm_node_t *predicate) {
pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL);
- pm_if_node_t *node = PM_ALLOC_NODE(parser, pm_if_node_t);
+ pm_if_node_t *node = PM_NODE_ALLOC(parser, pm_if_node_t);
pm_statements_node_t *statements = pm_statements_node_create(parser);
- pm_statements_node_body_append(parser, statements, statement);
+ pm_statements_node_body_append(parser, statements, statement, true);
*node = (pm_if_node_t) {
- {
- .type = PM_IF_NODE,
- .flags = PM_NODE_FLAG_NEWLINE,
- .location = {
- .start = statement->location.start,
- .end = predicate->location.end
- },
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_IF_NODE, PM_NODE_FLAG_NEWLINE, statement, predicate),
.if_keyword_loc = PM_LOCATION_TOKEN_VALUE(if_keyword),
.predicate = predicate,
- .then_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
+ .then_keyword_loc = { 0 },
.statements = statements,
- .consequent = NULL,
- .end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
+ .subsequent = NULL,
+ .end_keyword_loc = { 0 }
};
return node;
@@ -4860,31 +4399,24 @@ pm_if_node_ternary_create(pm_parser_t *parser, pm_node_t *predicate, const pm_to
pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL);
pm_statements_node_t *if_statements = pm_statements_node_create(parser);
- pm_statements_node_body_append(parser, if_statements, true_expression);
+ pm_statements_node_body_append(parser, if_statements, true_expression, true);
pm_statements_node_t *else_statements = pm_statements_node_create(parser);
- pm_statements_node_body_append(parser, else_statements, false_expression);
+ pm_statements_node_body_append(parser, else_statements, false_expression, true);
pm_token_t end_keyword = not_provided(parser);
pm_else_node_t *else_node = pm_else_node_create(parser, colon, else_statements, &end_keyword);
- pm_if_node_t *node = PM_ALLOC_NODE(parser, pm_if_node_t);
+ pm_if_node_t *node = PM_NODE_ALLOC(parser, pm_if_node_t);
*node = (pm_if_node_t) {
- {
- .type = PM_IF_NODE,
- .flags = PM_NODE_FLAG_NEWLINE,
- .location = {
- .start = predicate->location.start,
- .end = false_expression->location.end,
- },
- },
- .if_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
+ .base = PM_NODE_INIT_NODES(parser, PM_IF_NODE, PM_NODE_FLAG_NEWLINE, predicate, false_expression),
+ .if_keyword_loc = { 0 },
.predicate = predicate,
.then_keyword_loc = PM_LOCATION_TOKEN_VALUE(qmark),
.statements = if_statements,
- .consequent = (pm_node_t *)else_node,
- .end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
+ .subsequent = UP(else_node),
+ .end_keyword_loc = { 0 }
};
return node;
@@ -4908,13 +4440,10 @@ pm_else_node_end_keyword_loc_set(pm_else_node_t *node, const pm_token_t *keyword
*/
static pm_implicit_node_t *
pm_implicit_node_create(pm_parser_t *parser, pm_node_t *value) {
- pm_implicit_node_t *node = PM_ALLOC_NODE(parser, pm_implicit_node_t);
+ pm_implicit_node_t *node = PM_NODE_ALLOC(parser, pm_implicit_node_t);
*node = (pm_implicit_node_t) {
- {
- .type = PM_IMPLICIT_NODE,
- .location = value->location
- },
+ .base = PM_NODE_INIT_NODE(parser, PM_IMPLICIT_NODE, 0, value),
.value = value
};
@@ -4928,13 +4457,10 @@ static pm_implicit_rest_node_t *
pm_implicit_rest_node_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_COMMA);
- pm_implicit_rest_node_t *node = PM_ALLOC_NODE(parser, pm_implicit_rest_node_t);
+ pm_implicit_rest_node_t *node = PM_NODE_ALLOC(parser, pm_implicit_rest_node_t);
*node = (pm_implicit_rest_node_t) {
- {
- .type = PM_IMPLICIT_REST_NODE,
- .location = PM_LOCATION_TOKEN_VALUE(token)
- }
+ .base = PM_NODE_INIT_TOKEN(parser, PM_IMPLICIT_REST_NODE, 0, token)
};
return node;
@@ -4946,14 +4472,10 @@ pm_implicit_rest_node_create(pm_parser_t *parser, const pm_token_t *token) {
static pm_integer_node_t *
pm_integer_node_create(pm_parser_t *parser, pm_node_flags_t base, const pm_token_t *token) {
assert(token->type == PM_TOKEN_INTEGER);
- pm_integer_node_t *node = PM_ALLOC_NODE(parser, pm_integer_node_t);
+ pm_integer_node_t *node = PM_NODE_ALLOC(parser, pm_integer_node_t);
*node = (pm_integer_node_t) {
- {
- .type = PM_INTEGER_NODE,
- .flags = base | PM_NODE_FLAG_STATIC_LITERAL,
- .location = PM_LOCATION_TOKEN_VALUE(token)
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_INTEGER_NODE, base | PM_NODE_FLAG_STATIC_LITERAL, token),
.value = { 0 }
};
@@ -4978,18 +4500,14 @@ static pm_imaginary_node_t *
pm_integer_node_imaginary_create(pm_parser_t *parser, pm_node_flags_t base, const pm_token_t *token) {
assert(token->type == PM_TOKEN_INTEGER_IMAGINARY);
- pm_imaginary_node_t *node = PM_ALLOC_NODE(parser, pm_imaginary_node_t);
+ pm_imaginary_node_t *node = PM_NODE_ALLOC(parser, pm_imaginary_node_t);
*node = (pm_imaginary_node_t) {
- {
- .type = PM_IMAGINARY_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .location = PM_LOCATION_TOKEN_VALUE(token)
- },
- .numeric = (pm_node_t *) pm_integer_node_create(parser, base, &((pm_token_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_IMAGINARY_NODE, PM_NODE_FLAG_STATIC_LITERAL, token),
+ .numeric = UP(pm_integer_node_create(parser, base, &((pm_token_t) {
.type = PM_TOKEN_INTEGER,
.start = token->start,
.end = token->end - 1
- }))
+ })))
};
return node;
@@ -5003,13 +4521,9 @@ static pm_rational_node_t *
pm_integer_node_rational_create(pm_parser_t *parser, pm_node_flags_t base, const pm_token_t *token) {
assert(token->type == PM_TOKEN_INTEGER_RATIONAL);
- pm_rational_node_t *node = PM_ALLOC_NODE(parser, pm_rational_node_t);
+ pm_rational_node_t *node = PM_NODE_ALLOC(parser, pm_rational_node_t);
*node = (pm_rational_node_t) {
- {
- .type = PM_RATIONAL_NODE,
- .flags = base | PM_NODE_FLAG_STATIC_LITERAL,
- .location = PM_LOCATION_TOKEN_VALUE(token)
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_RATIONAL_NODE, base | PM_NODE_FLAG_STATIC_LITERAL, token),
.numerator = { 0 },
.denominator = { .value = 1, 0 }
};
@@ -5036,18 +4550,14 @@ static pm_imaginary_node_t *
pm_integer_node_rational_imaginary_create(pm_parser_t *parser, pm_node_flags_t base, const pm_token_t *token) {
assert(token->type == PM_TOKEN_INTEGER_RATIONAL_IMAGINARY);
- pm_imaginary_node_t *node = PM_ALLOC_NODE(parser, pm_imaginary_node_t);
+ pm_imaginary_node_t *node = PM_NODE_ALLOC(parser, pm_imaginary_node_t);
*node = (pm_imaginary_node_t) {
- {
- .type = PM_IMAGINARY_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .location = PM_LOCATION_TOKEN_VALUE(token)
- },
- .numeric = (pm_node_t *) pm_integer_node_rational_create(parser, base, &((pm_token_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_IMAGINARY_NODE, PM_NODE_FLAG_STATIC_LITERAL, token),
+ .numeric = UP(pm_integer_node_rational_create(parser, base, &((pm_token_t) {
.type = PM_TOKEN_INTEGER_RATIONAL,
.start = token->start,
.end = token->end - 1
- }))
+ })))
};
return node;
@@ -5058,7 +4568,7 @@ pm_integer_node_rational_imaginary_create(pm_parser_t *parser, pm_node_flags_t b
*/
static pm_in_node_t *
pm_in_node_create(pm_parser_t *parser, pm_node_t *pattern, pm_statements_node_t *statements, const pm_token_t *in_keyword, const pm_token_t *then_keyword) {
- pm_in_node_t *node = PM_ALLOC_NODE(parser, pm_in_node_t);
+ pm_in_node_t *node = PM_NODE_ALLOC(parser, pm_in_node_t);
const uint8_t *end;
if (statements != NULL) {
@@ -5070,13 +4580,7 @@ pm_in_node_create(pm_parser_t *parser, pm_node_t *pattern, pm_statements_node_t
}
*node = (pm_in_node_t) {
- {
- .type = PM_IN_NODE,
- .location = {
- .start = in_keyword->start,
- .end = end
- },
- },
+ .base = PM_NODE_INIT(parser, PM_IN_NODE, 0, in_keyword->start, end),
.pattern = pattern,
.statements = statements,
.in_loc = PM_LOCATION_TOKEN_VALUE(in_keyword),
@@ -5092,16 +4596,10 @@ pm_in_node_create(pm_parser_t *parser, pm_node_t *pattern, pm_statements_node_t
static pm_instance_variable_and_write_node_t *
pm_instance_variable_and_write_node_create(pm_parser_t *parser, pm_instance_variable_read_node_t *target, const pm_token_t *operator, pm_node_t *value) {
assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
- pm_instance_variable_and_write_node_t *node = PM_ALLOC_NODE(parser, pm_instance_variable_and_write_node_t);
+ pm_instance_variable_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_instance_variable_and_write_node_t);
*node = (pm_instance_variable_and_write_node_t) {
- {
- .type = PM_INSTANCE_VARIABLE_AND_WRITE_NODE,
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_INSTANCE_VARIABLE_AND_WRITE_NODE, 0, target, value),
.name = target->name,
.name_loc = target->base.location,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -5116,16 +4614,10 @@ pm_instance_variable_and_write_node_create(pm_parser_t *parser, pm_instance_vari
*/
static pm_instance_variable_operator_write_node_t *
pm_instance_variable_operator_write_node_create(pm_parser_t *parser, pm_instance_variable_read_node_t *target, const pm_token_t *operator, pm_node_t *value) {
- pm_instance_variable_operator_write_node_t *node = PM_ALLOC_NODE(parser, pm_instance_variable_operator_write_node_t);
+ pm_instance_variable_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_instance_variable_operator_write_node_t);
*node = (pm_instance_variable_operator_write_node_t) {
- {
- .type = PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE,
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE, 0, target, value),
.name = target->name,
.name_loc = target->base.location,
.binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -5142,16 +4634,10 @@ pm_instance_variable_operator_write_node_create(pm_parser_t *parser, pm_instance
static pm_instance_variable_or_write_node_t *
pm_instance_variable_or_write_node_create(pm_parser_t *parser, pm_instance_variable_read_node_t *target, const pm_token_t *operator, pm_node_t *value) {
assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL);
- pm_instance_variable_or_write_node_t *node = PM_ALLOC_NODE(parser, pm_instance_variable_or_write_node_t);
+ pm_instance_variable_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_instance_variable_or_write_node_t);
*node = (pm_instance_variable_or_write_node_t) {
- {
- .type = PM_INSTANCE_VARIABLE_OR_WRITE_NODE,
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_INSTANCE_VARIABLE_OR_WRITE_NODE, 0, target, value),
.name = target->name,
.name_loc = target->base.location,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -5167,13 +4653,10 @@ pm_instance_variable_or_write_node_create(pm_parser_t *parser, pm_instance_varia
static pm_instance_variable_read_node_t *
pm_instance_variable_read_node_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_INSTANCE_VARIABLE);
- pm_instance_variable_read_node_t *node = PM_ALLOC_NODE(parser, pm_instance_variable_read_node_t);
+ pm_instance_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_instance_variable_read_node_t);
*node = (pm_instance_variable_read_node_t) {
- {
- .type = PM_INSTANCE_VARIABLE_READ_NODE,
- .location = PM_LOCATION_TOKEN_VALUE(token)
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_INSTANCE_VARIABLE_READ_NODE, 0, token),
.name = pm_parser_constant_id_token(parser, token)
};
@@ -5186,17 +4669,13 @@ pm_instance_variable_read_node_create(pm_parser_t *parser, const pm_token_t *tok
*/
static pm_instance_variable_write_node_t *
pm_instance_variable_write_node_create(pm_parser_t *parser, pm_instance_variable_read_node_t *read_node, pm_token_t *operator, pm_node_t *value) {
- pm_instance_variable_write_node_t *node = PM_ALLOC_NODE(parser, pm_instance_variable_write_node_t);
+ pm_instance_variable_write_node_t *node = PM_NODE_ALLOC(parser, pm_instance_variable_write_node_t);
+ pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY);
+
*node = (pm_instance_variable_write_node_t) {
- {
- .type = PM_INSTANCE_VARIABLE_WRITE_NODE,
- .location = {
- .start = read_node->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_INSTANCE_VARIABLE_WRITE_NODE, flags, read_node, value),
.name = read_node->name,
- .name_loc = PM_LOCATION_NODE_BASE_VALUE(read_node),
+ .name_loc = PM_LOCATION_NODE_VALUE(read_node),
.operator_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(operator),
.value = value
};
@@ -5238,7 +4717,7 @@ pm_interpolated_node_append(pm_node_t *node, pm_node_list_t *parts, pm_node_t *p
break;
}
case PM_EMBEDDED_VARIABLE_NODE:
- pm_node_flag_unset((pm_node_t *) node, PM_NODE_FLAG_STATIC_LITERAL);
+ pm_node_flag_unset(UP(node), PM_NODE_FLAG_STATIC_LITERAL);
break;
default:
assert(false && "unexpected node type");
@@ -5253,17 +4732,10 @@ pm_interpolated_node_append(pm_node_t *node, pm_node_list_t *parts, pm_node_t *p
*/
static pm_interpolated_regular_expression_node_t *
pm_interpolated_regular_expression_node_create(pm_parser_t *parser, const pm_token_t *opening) {
- pm_interpolated_regular_expression_node_t *node = PM_ALLOC_NODE(parser, pm_interpolated_regular_expression_node_t);
+ pm_interpolated_regular_expression_node_t *node = PM_NODE_ALLOC(parser, pm_interpolated_regular_expression_node_t);
*node = (pm_interpolated_regular_expression_node_t) {
- {
- .type = PM_INTERPOLATED_REGULAR_EXPRESSION_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .location = {
- .start = opening->start,
- .end = NULL,
- },
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_INTERPOLATED_REGULAR_EXPRESSION_NODE, PM_NODE_FLAG_STATIC_LITERAL, opening),
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
.closing_loc = PM_LOCATION_TOKEN_VALUE(opening),
.parts = { 0 }
@@ -5281,14 +4753,14 @@ pm_interpolated_regular_expression_node_append(pm_interpolated_regular_expressio
node->base.location.end = part->location.end;
}
- pm_interpolated_node_append((pm_node_t *) node, &node->parts, part);
+ pm_interpolated_node_append(UP(node), &node->parts, part);
}
static inline void
pm_interpolated_regular_expression_node_closing_set(pm_parser_t *parser, pm_interpolated_regular_expression_node_t *node, const pm_token_t *closing) {
node->closing_loc = PM_LOCATION_TOKEN_VALUE(closing);
node->base.location.end = closing->end;
- pm_node_flag_set((pm_node_t *) node, pm_regular_expression_flags_create(parser, closing));
+ pm_node_flag_set(UP(node), pm_regular_expression_flags_create(parser, closing));
}
/**
@@ -5317,10 +4789,10 @@ pm_interpolated_regular_expression_node_closing_set(pm_parser_t *parser, pm_inte
static inline void
pm_interpolated_string_node_append(pm_interpolated_string_node_t *node, pm_node_t *part) {
#define CLEAR_FLAGS(node) \
- node->base.flags = (pm_node_flags_t) (node->base.flags & ~(PM_NODE_FLAG_STATIC_LITERAL | PM_INTERPOLATED_STRING_NODE_FLAGS_FROZEN | PM_INTERPOLATED_STRING_NODE_FLAGS_MUTABLE))
+ node->base.flags = (pm_node_flags_t) (FL(node) & ~(PM_NODE_FLAG_STATIC_LITERAL | PM_INTERPOLATED_STRING_NODE_FLAGS_FROZEN | PM_INTERPOLATED_STRING_NODE_FLAGS_MUTABLE))
#define MUTABLE_FLAGS(node) \
- node->base.flags = (pm_node_flags_t) ((node->base.flags | PM_INTERPOLATED_STRING_NODE_FLAGS_MUTABLE) & ~PM_INTERPOLATED_STRING_NODE_FLAGS_FROZEN);
+ node->base.flags = (pm_node_flags_t) ((FL(node) | PM_INTERPOLATED_STRING_NODE_FLAGS_MUTABLE) & ~PM_INTERPOLATED_STRING_NODE_FLAGS_FROZEN);
if (node->parts.size == 0 && node->opening_loc.start == NULL) {
node->base.location.start = part->location.start;
@@ -5330,7 +4802,13 @@ pm_interpolated_string_node_append(pm_interpolated_string_node_t *node, pm_node_
switch (PM_NODE_TYPE(part)) {
case PM_STRING_NODE:
- pm_node_flag_set(part, PM_NODE_FLAG_STATIC_LITERAL | PM_STRING_FLAGS_FROZEN);
+ // If inner string is not frozen, it stops being a static literal. We should *not* clear other flags,
+ // because concatenating two frozen strings (`'foo' 'bar'`) is still frozen. This holds true for
+ // as long as this interpolation only consists of other string literals.
+ if (!PM_NODE_FLAG_P(part, PM_STRING_FLAGS_FROZEN)) {
+ pm_node_flag_unset(UP(node), PM_NODE_FLAG_STATIC_LITERAL);
+ }
+ part->flags = (pm_node_flags_t) ((part->flags | PM_NODE_FLAG_STATIC_LITERAL | PM_STRING_FLAGS_FROZEN) & ~PM_STRING_FLAGS_MUTABLE);
break;
case PM_INTERPOLATED_STRING_NODE:
if (PM_NODE_FLAG_P(part, PM_NODE_FLAG_STATIC_LITERAL)) {
@@ -5354,7 +4832,7 @@ pm_interpolated_string_node_append(pm_interpolated_string_node_t *node, pm_node_
// If the embedded statement is a string, then we can make that
// string as frozen and static literal, and not touch the static
// literal status of this string.
- pm_node_flag_set(embedded, PM_NODE_FLAG_STATIC_LITERAL | PM_STRING_FLAGS_FROZEN);
+ embedded->flags = (pm_node_flags_t) ((embedded->flags | PM_NODE_FLAG_STATIC_LITERAL | PM_STRING_FLAGS_FROZEN) & ~PM_STRING_FLAGS_MUTABLE);
if (PM_NODE_FLAG_P(node, PM_NODE_FLAG_STATIC_LITERAL)) {
MUTABLE_FLAGS(node);
@@ -5379,6 +4857,14 @@ pm_interpolated_string_node_append(pm_interpolated_string_node_t *node, pm_node_
// should clear the mutability flags.
CLEAR_FLAGS(node);
break;
+ case PM_X_STRING_NODE:
+ case PM_INTERPOLATED_X_STRING_NODE:
+ case PM_SYMBOL_NODE:
+ case PM_INTERPOLATED_SYMBOL_NODE:
+ // These will only happen in error cases. But we want to handle it
+ // here so that we don't fail the assertion.
+ CLEAR_FLAGS(node);
+ break;
default:
assert(false && "unexpected node type");
break;
@@ -5395,7 +4881,7 @@ pm_interpolated_string_node_append(pm_interpolated_string_node_t *node, pm_node_
*/
static pm_interpolated_string_node_t *
pm_interpolated_string_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_node_list_t *parts, const pm_token_t *closing) {
- pm_interpolated_string_node_t *node = PM_ALLOC_NODE(parser, pm_interpolated_string_node_t);
+ pm_interpolated_string_node_t *node = PM_NODE_ALLOC(parser, pm_interpolated_string_node_t);
pm_node_flags_t flags = PM_NODE_FLAG_STATIC_LITERAL;
switch (parser->frozen_string_literal) {
@@ -5408,14 +4894,7 @@ pm_interpolated_string_node_create(pm_parser_t *parser, const pm_token_t *openin
}
*node = (pm_interpolated_string_node_t) {
- {
- .type = PM_INTERPOLATED_STRING_NODE,
- .flags = flags,
- .location = {
- .start = opening->start,
- .end = closing->end,
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_INTERPOLATED_STRING_NODE, flags, opening, closing),
.opening_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
.closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing),
.parts = { 0 }
@@ -5446,7 +4925,7 @@ pm_interpolated_symbol_node_append(pm_interpolated_symbol_node_t *node, pm_node_
node->base.location.start = part->location.start;
}
- pm_interpolated_node_append((pm_node_t *) node, &node->parts, part);
+ pm_interpolated_node_append(UP(node), &node->parts, part);
node->base.location.end = MAX(node->base.location.end, part->location.end);
}
@@ -5461,17 +4940,10 @@ pm_interpolated_symbol_node_closing_loc_set(pm_interpolated_symbol_node_t *node,
*/
static pm_interpolated_symbol_node_t *
pm_interpolated_symbol_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_node_list_t *parts, const pm_token_t *closing) {
- pm_interpolated_symbol_node_t *node = PM_ALLOC_NODE(parser, pm_interpolated_symbol_node_t);
+ pm_interpolated_symbol_node_t *node = PM_NODE_ALLOC(parser, pm_interpolated_symbol_node_t);
*node = (pm_interpolated_symbol_node_t) {
- {
- .type = PM_INTERPOLATED_SYMBOL_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .location = {
- .start = opening->start,
- .end = closing->end,
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_INTERPOLATED_SYMBOL_NODE, PM_NODE_FLAG_STATIC_LITERAL, opening, closing),
.opening_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
.closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing),
.parts = { 0 }
@@ -5492,16 +4964,10 @@ pm_interpolated_symbol_node_create(pm_parser_t *parser, const pm_token_t *openin
*/
static pm_interpolated_x_string_node_t *
pm_interpolated_xstring_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *closing) {
- pm_interpolated_x_string_node_t *node = PM_ALLOC_NODE(parser, pm_interpolated_x_string_node_t);
+ pm_interpolated_x_string_node_t *node = PM_NODE_ALLOC(parser, pm_interpolated_x_string_node_t);
*node = (pm_interpolated_x_string_node_t) {
- {
- .type = PM_INTERPOLATED_X_STRING_NODE,
- .location = {
- .start = opening->start,
- .end = closing->end
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_INTERPOLATED_X_STRING_NODE, 0, opening, closing),
.opening_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
.closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing),
.parts = { 0 }
@@ -5512,7 +4978,7 @@ pm_interpolated_xstring_node_create(pm_parser_t *parser, const pm_token_t *openi
static inline void
pm_interpolated_xstring_node_append(pm_interpolated_x_string_node_t *node, pm_node_t *part) {
- pm_interpolated_node_append((pm_node_t *) node, &node->parts, part);
+ pm_interpolated_node_append(UP(node), &node->parts, part);
node->base.location.end = part->location.end;
}
@@ -5527,13 +4993,10 @@ pm_interpolated_xstring_node_closing_set(pm_interpolated_x_string_node_t *node,
*/
static pm_it_local_variable_read_node_t *
pm_it_local_variable_read_node_create(pm_parser_t *parser, const pm_token_t *name) {
- pm_it_local_variable_read_node_t *node = PM_ALLOC_NODE(parser, pm_it_local_variable_read_node_t);
+ pm_it_local_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_it_local_variable_read_node_t);
*node = (pm_it_local_variable_read_node_t) {
- {
- .type = PM_IT_LOCAL_VARIABLE_READ_NODE,
- .location = PM_LOCATION_TOKEN_VALUE(name)
- }
+ .base = PM_NODE_INIT_TOKEN(parser, PM_IT_LOCAL_VARIABLE_READ_NODE, 0, name),
};
return node;
@@ -5544,16 +5007,10 @@ pm_it_local_variable_read_node_create(pm_parser_t *parser, const pm_token_t *nam
*/
static pm_it_parameters_node_t *
pm_it_parameters_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *closing) {
- pm_it_parameters_node_t *node = PM_ALLOC_NODE(parser, pm_it_parameters_node_t);
+ pm_it_parameters_node_t *node = PM_NODE_ALLOC(parser, pm_it_parameters_node_t);
*node = (pm_it_parameters_node_t) {
- {
- .type = PM_IT_PARAMETERS_NODE,
- .location = {
- .start = opening->start,
- .end = closing->end
- }
- }
+ .base = PM_NODE_INIT_TOKENS(parser, PM_IT_PARAMETERS_NODE, 0, opening, closing),
};
return node;
@@ -5564,14 +5021,10 @@ pm_it_parameters_node_create(pm_parser_t *parser, const pm_token_t *opening, con
*/
static pm_keyword_hash_node_t *
pm_keyword_hash_node_create(pm_parser_t *parser) {
- pm_keyword_hash_node_t *node = PM_ALLOC_NODE(parser, pm_keyword_hash_node_t);
+ pm_keyword_hash_node_t *node = PM_NODE_ALLOC(parser, pm_keyword_hash_node_t);
*node = (pm_keyword_hash_node_t) {
- .base = {
- .type = PM_KEYWORD_HASH_NODE,
- .location = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
- .flags = PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS
- },
+ .base = PM_NODE_INIT_UNSET(parser, PM_KEYWORD_HASH_NODE, PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS),
.elements = { 0 }
};
@@ -5586,7 +5039,7 @@ pm_keyword_hash_node_elements_append(pm_keyword_hash_node_t *hash, pm_node_t *el
// If the element being added is not an AssocNode or does not have a symbol
// key, then we want to turn the SYMBOL_KEYS flag off.
if (!PM_NODE_TYPE_P(element, PM_ASSOC_NODE) || !PM_NODE_TYPE_P(((pm_assoc_node_t *) element)->key, PM_SYMBOL_NODE)) {
- pm_node_flag_unset((pm_node_t *)hash, PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS);
+ pm_node_flag_unset(UP(hash), PM_KEYWORD_HASH_NODE_FLAGS_SYMBOL_KEYS);
}
pm_node_list_append(&hash->elements, element);
@@ -5601,16 +5054,10 @@ pm_keyword_hash_node_elements_append(pm_keyword_hash_node_t *hash, pm_node_t *el
*/
static pm_required_keyword_parameter_node_t *
pm_required_keyword_parameter_node_create(pm_parser_t *parser, const pm_token_t *name) {
- pm_required_keyword_parameter_node_t *node = PM_ALLOC_NODE(parser, pm_required_keyword_parameter_node_t);
+ pm_required_keyword_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_required_keyword_parameter_node_t);
*node = (pm_required_keyword_parameter_node_t) {
- {
- .type = PM_REQUIRED_KEYWORD_PARAMETER_NODE,
- .location = {
- .start = name->start,
- .end = name->end
- },
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_REQUIRED_KEYWORD_PARAMETER_NODE, 0, name),
.name = pm_parser_constant_id_location(parser, name->start, name->end - 1),
.name_loc = PM_LOCATION_TOKEN_VALUE(name),
};
@@ -5623,16 +5070,10 @@ pm_required_keyword_parameter_node_create(pm_parser_t *parser, const pm_token_t
*/
static pm_optional_keyword_parameter_node_t *
pm_optional_keyword_parameter_node_create(pm_parser_t *parser, const pm_token_t *name, pm_node_t *value) {
- pm_optional_keyword_parameter_node_t *node = PM_ALLOC_NODE(parser, pm_optional_keyword_parameter_node_t);
+ pm_optional_keyword_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_optional_keyword_parameter_node_t);
*node = (pm_optional_keyword_parameter_node_t) {
- {
- .type = PM_OPTIONAL_KEYWORD_PARAMETER_NODE,
- .location = {
- .start = name->start,
- .end = value->location.end
- },
- },
+ .base = PM_NODE_INIT_TOKEN_NODE(parser, PM_OPTIONAL_KEYWORD_PARAMETER_NODE, 0, name, value),
.name = pm_parser_constant_id_location(parser, name->start, name->end - 1),
.name_loc = PM_LOCATION_TOKEN_VALUE(name),
.value = value
@@ -5646,16 +5087,14 @@ pm_optional_keyword_parameter_node_create(pm_parser_t *parser, const pm_token_t
*/
static pm_keyword_rest_parameter_node_t *
pm_keyword_rest_parameter_node_create(pm_parser_t *parser, const pm_token_t *operator, const pm_token_t *name) {
- pm_keyword_rest_parameter_node_t *node = PM_ALLOC_NODE(parser, pm_keyword_rest_parameter_node_t);
+ pm_keyword_rest_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_keyword_rest_parameter_node_t);
*node = (pm_keyword_rest_parameter_node_t) {
- {
- .type = PM_KEYWORD_REST_PARAMETER_NODE,
- .location = {
- .start = operator->start,
- .end = (name->type == PM_TOKEN_NOT_PROVIDED ? operator->end : name->end)
- },
- },
+ .base = (
+ (name->type == PM_TOKEN_NOT_PROVIDED)
+ ? PM_NODE_INIT_TOKEN(parser, PM_KEYWORD_REST_PARAMETER_NODE, 0, operator)
+ : PM_NODE_INIT_TOKENS(parser, PM_KEYWORD_REST_PARAMETER_NODE, 0, operator, name)
+ ),
.name = pm_parser_optional_constant_id_token(parser, name),
.name_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(name),
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator)
@@ -5677,16 +5116,10 @@ pm_lambda_node_create(
pm_node_t *parameters,
pm_node_t *body
) {
- pm_lambda_node_t *node = PM_ALLOC_NODE(parser, pm_lambda_node_t);
+ pm_lambda_node_t *node = PM_NODE_ALLOC(parser, pm_lambda_node_t);
*node = (pm_lambda_node_t) {
- {
- .type = PM_LAMBDA_NODE,
- .location = {
- .start = operator->start,
- .end = closing->end
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_LAMBDA_NODE, 0, operator, closing),
.locals = *locals,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
@@ -5703,18 +5136,12 @@ pm_lambda_node_create(
*/
static pm_local_variable_and_write_node_t *
pm_local_variable_and_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value, pm_constant_id_t name, uint32_t depth) {
- assert(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_READ_NODE) || PM_NODE_TYPE_P(target, PM_CALL_NODE));
+ assert(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_READ_NODE) || PM_NODE_TYPE_P(target, PM_IT_LOCAL_VARIABLE_READ_NODE) || PM_NODE_TYPE_P(target, PM_CALL_NODE));
assert(operator->type == PM_TOKEN_AMPERSAND_AMPERSAND_EQUAL);
- pm_local_variable_and_write_node_t *node = PM_ALLOC_NODE(parser, pm_local_variable_and_write_node_t);
+ pm_local_variable_and_write_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_and_write_node_t);
*node = (pm_local_variable_and_write_node_t) {
- {
- .type = PM_LOCAL_VARIABLE_AND_WRITE_NODE,
- .location = {
- .start = target->location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_LOCAL_VARIABLE_AND_WRITE_NODE, 0, target, value),
.name_loc = target->location,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.value = value,
@@ -5730,16 +5157,10 @@ pm_local_variable_and_write_node_create(pm_parser_t *parser, pm_node_t *target,
*/
static pm_local_variable_operator_write_node_t *
pm_local_variable_operator_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value, pm_constant_id_t name, uint32_t depth) {
- pm_local_variable_operator_write_node_t *node = PM_ALLOC_NODE(parser, pm_local_variable_operator_write_node_t);
+ pm_local_variable_operator_write_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_operator_write_node_t);
*node = (pm_local_variable_operator_write_node_t) {
- {
- .type = PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE,
- .location = {
- .start = target->location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE, 0, target, value),
.name_loc = target->location,
.binary_operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.value = value,
@@ -5756,18 +5177,12 @@ pm_local_variable_operator_write_node_create(pm_parser_t *parser, pm_node_t *tar
*/
static pm_local_variable_or_write_node_t *
pm_local_variable_or_write_node_create(pm_parser_t *parser, pm_node_t *target, const pm_token_t *operator, pm_node_t *value, pm_constant_id_t name, uint32_t depth) {
- assert(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_READ_NODE) || PM_NODE_TYPE_P(target, PM_CALL_NODE));
+ assert(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_READ_NODE) || PM_NODE_TYPE_P(target, PM_IT_LOCAL_VARIABLE_READ_NODE) || PM_NODE_TYPE_P(target, PM_CALL_NODE));
assert(operator->type == PM_TOKEN_PIPE_PIPE_EQUAL);
- pm_local_variable_or_write_node_t *node = PM_ALLOC_NODE(parser, pm_local_variable_or_write_node_t);
+ pm_local_variable_or_write_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_or_write_node_t);
*node = (pm_local_variable_or_write_node_t) {
- {
- .type = PM_LOCAL_VARIABLE_OR_WRITE_NODE,
- .location = {
- .start = target->location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_LOCAL_VARIABLE_OR_WRITE_NODE, 0, target, value),
.name_loc = target->location,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.value = value,
@@ -5785,13 +5200,10 @@ static pm_local_variable_read_node_t *
pm_local_variable_read_node_create_constant_id(pm_parser_t *parser, const pm_token_t *name, pm_constant_id_t name_id, uint32_t depth, bool missing) {
if (!missing) pm_locals_read(&pm_parser_scope_find(parser, depth)->locals, name_id);
- pm_local_variable_read_node_t *node = PM_ALLOC_NODE(parser, pm_local_variable_read_node_t);
+ pm_local_variable_read_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_read_node_t);
*node = (pm_local_variable_read_node_t) {
- {
- .type = PM_LOCAL_VARIABLE_READ_NODE,
- .location = PM_LOCATION_TOKEN_VALUE(name)
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_LOCAL_VARIABLE_READ_NODE, 0, name),
.name = name_id,
.depth = depth
};
@@ -5823,16 +5235,11 @@ pm_local_variable_read_node_missing_create(pm_parser_t *parser, const pm_token_t
*/
static pm_local_variable_write_node_t *
pm_local_variable_write_node_create(pm_parser_t *parser, pm_constant_id_t name, uint32_t depth, pm_node_t *value, const pm_location_t *name_loc, const pm_token_t *operator) {
- pm_local_variable_write_node_t *node = PM_ALLOC_NODE(parser, pm_local_variable_write_node_t);
+ pm_local_variable_write_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_write_node_t);
+ pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY);
*node = (pm_local_variable_write_node_t) {
- {
- .type = PM_LOCAL_VARIABLE_WRITE_NODE,
- .location = {
- .start = name_loc->start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_TOKEN_NODE(parser, PM_LOCAL_VARIABLE_WRITE_NODE, flags, name_loc, value),
.name = name,
.depth = depth,
.value = value,
@@ -5878,13 +5285,10 @@ pm_refute_numbered_parameter(pm_parser_t *parser, const uint8_t *start, const ui
static pm_local_variable_target_node_t *
pm_local_variable_target_node_create(pm_parser_t *parser, const pm_location_t *location, pm_constant_id_t name, uint32_t depth) {
pm_refute_numbered_parameter(parser, location->start, location->end);
- pm_local_variable_target_node_t *node = PM_ALLOC_NODE(parser, pm_local_variable_target_node_t);
+ pm_local_variable_target_node_t *node = PM_NODE_ALLOC(parser, pm_local_variable_target_node_t);
*node = (pm_local_variable_target_node_t) {
- {
- .type = PM_LOCAL_VARIABLE_TARGET_NODE,
- .location = *location
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_LOCAL_VARIABLE_TARGET_NODE, 0, location),
.name = name,
.depth = depth
};
@@ -5899,16 +5303,10 @@ static pm_match_predicate_node_t *
pm_match_predicate_node_create(pm_parser_t *parser, pm_node_t *value, pm_node_t *pattern, const pm_token_t *operator) {
pm_assert_value_expression(parser, value);
- pm_match_predicate_node_t *node = PM_ALLOC_NODE(parser, pm_match_predicate_node_t);
+ pm_match_predicate_node_t *node = PM_NODE_ALLOC(parser, pm_match_predicate_node_t);
*node = (pm_match_predicate_node_t) {
- {
- .type = PM_MATCH_PREDICATE_NODE,
- .location = {
- .start = value->location.start,
- .end = pattern->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_MATCH_PREDICATE_NODE, 0, value, pattern),
.value = value,
.pattern = pattern,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator)
@@ -5924,16 +5322,10 @@ static pm_match_required_node_t *
pm_match_required_node_create(pm_parser_t *parser, pm_node_t *value, pm_node_t *pattern, const pm_token_t *operator) {
pm_assert_value_expression(parser, value);
- pm_match_required_node_t *node = PM_ALLOC_NODE(parser, pm_match_required_node_t);
+ pm_match_required_node_t *node = PM_NODE_ALLOC(parser, pm_match_required_node_t);
*node = (pm_match_required_node_t) {
- {
- .type = PM_MATCH_REQUIRED_NODE,
- .location = {
- .start = value->location.start,
- .end = pattern->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_MATCH_REQUIRED_NODE, 0, value, pattern),
.value = value,
.pattern = pattern,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator)
@@ -5947,13 +5339,10 @@ pm_match_required_node_create(pm_parser_t *parser, pm_node_t *value, pm_node_t *
*/
static pm_match_write_node_t *
pm_match_write_node_create(pm_parser_t *parser, pm_call_node_t *call) {
- pm_match_write_node_t *node = PM_ALLOC_NODE(parser, pm_match_write_node_t);
+ pm_match_write_node_t *node = PM_NODE_ALLOC(parser, pm_match_write_node_t);
*node = (pm_match_write_node_t) {
- {
- .type = PM_MATCH_WRITE_NODE,
- .location = call->base.location
- },
+ .base = PM_NODE_INIT_NODE(parser, PM_MATCH_WRITE_NODE, 0, call),
.call = call,
.targets = { 0 }
};
@@ -5966,16 +5355,10 @@ pm_match_write_node_create(pm_parser_t *parser, pm_call_node_t *call) {
*/
static pm_module_node_t *
pm_module_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const pm_token_t *module_keyword, pm_node_t *constant_path, const pm_token_t *name, pm_node_t *body, const pm_token_t *end_keyword) {
- pm_module_node_t *node = PM_ALLOC_NODE(parser, pm_module_node_t);
+ pm_module_node_t *node = PM_NODE_ALLOC(parser, pm_module_node_t);
*node = (pm_module_node_t) {
- {
- .type = PM_MODULE_NODE,
- .location = {
- .start = module_keyword->start,
- .end = end_keyword->end
- }
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_MODULE_NODE, 0, module_keyword, end_keyword),
.locals = (locals == NULL ? ((pm_constant_id_list_t) { .ids = NULL, .size = 0, .capacity = 0 }) : *locals),
.module_keyword_loc = PM_LOCATION_TOKEN_VALUE(module_keyword),
.constant_path = constant_path,
@@ -5992,18 +5375,15 @@ pm_module_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const
*/
static pm_multi_target_node_t *
pm_multi_target_node_create(pm_parser_t *parser) {
- pm_multi_target_node_t *node = PM_ALLOC_NODE(parser, pm_multi_target_node_t);
+ pm_multi_target_node_t *node = PM_NODE_ALLOC(parser, pm_multi_target_node_t);
*node = (pm_multi_target_node_t) {
- {
- .type = PM_MULTI_TARGET_NODE,
- .location = { .start = NULL, .end = NULL }
- },
+ .base = PM_NODE_INIT_UNSET(parser, PM_MULTI_TARGET_NODE, 0),
.lefts = { 0 },
.rest = NULL,
.rights = { 0 },
- .lparen_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
- .rparen_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
+ .lparen_loc = { 0 },
+ .rparen_loc = { 0 }
};
return node;
@@ -6066,16 +5446,11 @@ pm_multi_target_node_closing_set(pm_multi_target_node_t *node, const pm_token_t
*/
static pm_multi_write_node_t *
pm_multi_write_node_create(pm_parser_t *parser, pm_multi_target_node_t *target, const pm_token_t *operator, pm_node_t *value) {
- pm_multi_write_node_t *node = PM_ALLOC_NODE(parser, pm_multi_write_node_t);
+ pm_multi_write_node_t *node = PM_NODE_ALLOC(parser, pm_multi_write_node_t);
+ pm_node_flags_t flags = pm_implicit_array_write_flags(value, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY);
*node = (pm_multi_write_node_t) {
- {
- .type = PM_MULTI_WRITE_NODE,
- .location = {
- .start = target->base.location.start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_MULTI_WRITE_NODE, flags, target, value),
.lefts = target->lefts,
.rest = target->rest,
.rights = target->rights,
@@ -6098,16 +5473,14 @@ pm_multi_write_node_create(pm_parser_t *parser, pm_multi_target_node_t *target,
static pm_next_node_t *
pm_next_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_arguments_node_t *arguments) {
assert(keyword->type == PM_TOKEN_KEYWORD_NEXT);
- pm_next_node_t *node = PM_ALLOC_NODE(parser, pm_next_node_t);
+ pm_next_node_t *node = PM_NODE_ALLOC(parser, pm_next_node_t);
*node = (pm_next_node_t) {
- {
- .type = PM_NEXT_NODE,
- .location = {
- .start = keyword->start,
- .end = (arguments == NULL ? keyword->end : arguments->base.location.end)
- }
- },
+ .base = (
+ (arguments == NULL)
+ ? PM_NODE_INIT_TOKEN(parser, PM_NEXT_NODE, 0, keyword)
+ : PM_NODE_INIT_TOKEN_NODE(parser, PM_NEXT_NODE, 0, keyword, arguments)
+ ),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
.arguments = arguments
};
@@ -6121,13 +5494,11 @@ pm_next_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_arguments
static pm_nil_node_t *
pm_nil_node_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_KEYWORD_NIL);
- pm_nil_node_t *node = PM_ALLOC_NODE(parser, pm_nil_node_t);
+ pm_nil_node_t *node = PM_NODE_ALLOC(parser, pm_nil_node_t);
- *node = (pm_nil_node_t) {{
- .type = PM_NIL_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .location = PM_LOCATION_TOKEN_VALUE(token)
- }};
+ *node = (pm_nil_node_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_NIL_NODE, PM_NODE_FLAG_STATIC_LITERAL, token)
+ };
return node;
}
@@ -6139,16 +5510,10 @@ static pm_no_keywords_parameter_node_t *
pm_no_keywords_parameter_node_create(pm_parser_t *parser, const pm_token_t *operator, const pm_token_t *keyword) {
assert(operator->type == PM_TOKEN_USTAR_STAR || operator->type == PM_TOKEN_STAR_STAR);
assert(keyword->type == PM_TOKEN_KEYWORD_NIL);
- pm_no_keywords_parameter_node_t *node = PM_ALLOC_NODE(parser, pm_no_keywords_parameter_node_t);
+ pm_no_keywords_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_no_keywords_parameter_node_t);
*node = (pm_no_keywords_parameter_node_t) {
- {
- .type = PM_NO_KEYWORDS_PARAMETER_NODE,
- .location = {
- .start = operator->start,
- .end = keyword->end
- }
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_NO_KEYWORDS_PARAMETER_NODE, 0, operator, keyword),
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword)
};
@@ -6161,13 +5526,10 @@ pm_no_keywords_parameter_node_create(pm_parser_t *parser, const pm_token_t *oper
*/
static pm_numbered_parameters_node_t *
pm_numbered_parameters_node_create(pm_parser_t *parser, const pm_location_t *location, uint8_t maximum) {
- pm_numbered_parameters_node_t *node = PM_ALLOC_NODE(parser, pm_numbered_parameters_node_t);
+ pm_numbered_parameters_node_t *node = PM_NODE_ALLOC(parser, pm_numbered_parameters_node_t);
*node = (pm_numbered_parameters_node_t) {
- {
- .type = PM_NUMBERED_PARAMETERS_NODE,
- .location = *location
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_NUMBERED_PARAMETERS_NODE, 0, location),
.maximum = maximum
};
@@ -6192,7 +5554,10 @@ pm_numbered_reference_read_node_number(pm_parser_t *parser, const pm_token_t *to
const uint8_t *end = token->end;
ptrdiff_t diff = end - start;
- assert(diff > 0 && ((unsigned long) diff < SIZE_MAX));
+ assert(diff > 0);
+#if PTRDIFF_MAX > SIZE_MAX
+ assert(diff < (ptrdiff_t) SIZE_MAX);
+#endif
size_t length = (size_t) diff;
char *digits = xcalloc(length + 1, sizeof(char));
@@ -6203,14 +5568,14 @@ pm_numbered_reference_read_node_number(pm_parser_t *parser, const pm_token_t *to
errno = 0;
unsigned long value = strtoul(digits, &endptr, 10);
- if ((digits == endptr) || (*endptr != '\0') || (errno == ERANGE)) {
+ if ((digits == endptr) || (*endptr != '\0')) {
pm_parser_err(parser, start, end, PM_ERR_INVALID_NUMBER_DECIMAL);
value = 0;
}
xfree(digits);
- if (value > NTH_REF_MAX) {
+ if ((errno == ERANGE) || (value > NTH_REF_MAX)) {
PM_PARSER_WARN_FORMAT(parser, start, end, PM_WARN_INVALID_NUMBERED_REFERENCE, (int) (length + 1), (const char *) token->start);
value = 0;
}
@@ -6226,13 +5591,10 @@ pm_numbered_reference_read_node_number(pm_parser_t *parser, const pm_token_t *to
static pm_numbered_reference_read_node_t *
pm_numbered_reference_read_node_create(pm_parser_t *parser, const pm_token_t *name) {
assert(name->type == PM_TOKEN_NUMBERED_REFERENCE);
- pm_numbered_reference_read_node_t *node = PM_ALLOC_NODE(parser, pm_numbered_reference_read_node_t);
+ pm_numbered_reference_read_node_t *node = PM_NODE_ALLOC(parser, pm_numbered_reference_read_node_t);
*node = (pm_numbered_reference_read_node_t) {
- {
- .type = PM_NUMBERED_REFERENCE_READ_NODE,
- .location = PM_LOCATION_TOKEN_VALUE(name),
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_NUMBERED_REFERENCE_READ_NODE, 0, name),
.number = pm_numbered_reference_read_node_number(parser, name)
};
@@ -6244,16 +5606,10 @@ pm_numbered_reference_read_node_create(pm_parser_t *parser, const pm_token_t *na
*/
static pm_optional_parameter_node_t *
pm_optional_parameter_node_create(pm_parser_t *parser, const pm_token_t *name, const pm_token_t *operator, pm_node_t *value) {
- pm_optional_parameter_node_t *node = PM_ALLOC_NODE(parser, pm_optional_parameter_node_t);
+ pm_optional_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_optional_parameter_node_t);
*node = (pm_optional_parameter_node_t) {
- {
- .type = PM_OPTIONAL_PARAMETER_NODE,
- .location = {
- .start = name->start,
- .end = value->location.end
- }
- },
+ .base = PM_NODE_INIT_TOKEN_NODE(parser, PM_OPTIONAL_PARAMETER_NODE, 0, name, value),
.name = pm_parser_constant_id_token(parser, name),
.name_loc = PM_LOCATION_TOKEN_VALUE(name),
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -6270,16 +5626,10 @@ static pm_or_node_t *
pm_or_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *operator, pm_node_t *right) {
pm_assert_value_expression(parser, left);
- pm_or_node_t *node = PM_ALLOC_NODE(parser, pm_or_node_t);
+ pm_or_node_t *node = PM_NODE_ALLOC(parser, pm_or_node_t);
*node = (pm_or_node_t) {
- {
- .type = PM_OR_NODE,
- .location = {
- .start = left->location.start,
- .end = right->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_OR_NODE, 0, left, right),
.left = left,
.right = right,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator)
@@ -6293,13 +5643,10 @@ pm_or_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *operat
*/
static pm_parameters_node_t *
pm_parameters_node_create(pm_parser_t *parser) {
- pm_parameters_node_t *node = PM_ALLOC_NODE(parser, pm_parameters_node_t);
+ pm_parameters_node_t *node = PM_NODE_ALLOC(parser, pm_parameters_node_t);
*node = (pm_parameters_node_t) {
- {
- .type = PM_PARAMETERS_NODE,
- .location = PM_LOCATION_TOKEN_VALUE(&parser->current)
- },
+ .base = PM_NODE_INIT_UNSET(parser, PM_PARAMETERS_NODE, 0),
.rest = NULL,
.keyword_rest = NULL,
.block = NULL,
@@ -6344,8 +5691,8 @@ pm_parameters_node_requireds_append(pm_parameters_node_t *params, pm_node_t *par
*/
static void
pm_parameters_node_optionals_append(pm_parameters_node_t *params, pm_optional_parameter_node_t *param) {
- pm_parameters_node_location_set(params, (pm_node_t *) param);
- pm_node_list_append(&params->optionals, (pm_node_t *) param);
+ pm_parameters_node_location_set(params, UP(param));
+ pm_node_list_append(&params->optionals, UP(param));
}
/**
@@ -6391,7 +5738,7 @@ pm_parameters_node_keyword_rest_set(pm_parameters_node_t *params, pm_node_t *par
static void
pm_parameters_node_block_set(pm_parameters_node_t *params, pm_block_parameter_node_t *param) {
assert(params->block == NULL);
- pm_parameters_node_location_set(params, (pm_node_t *) param);
+ pm_parameters_node_location_set(params, UP(param));
params->block = param;
}
@@ -6400,16 +5747,10 @@ pm_parameters_node_block_set(pm_parameters_node_t *params, pm_block_parameter_no
*/
static pm_program_node_t *
pm_program_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, pm_statements_node_t *statements) {
- pm_program_node_t *node = PM_ALLOC_NODE(parser, pm_program_node_t);
+ pm_program_node_t *node = PM_NODE_ALLOC(parser, pm_program_node_t);
*node = (pm_program_node_t) {
- {
- .type = PM_PROGRAM_NODE,
- .location = {
- .start = statements == NULL ? parser->start : statements->base.location.start,
- .end = statements == NULL ? parser->end : statements->base.location.end
- }
- },
+ .base = PM_NODE_INIT_NODE(parser, PM_PROGRAM_NODE, 0, statements),
.locals = *locals,
.statements = statements
};
@@ -6421,17 +5762,11 @@ pm_program_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, pm_st
* Allocate and initialize new ParenthesesNode node.
*/
static pm_parentheses_node_t *
-pm_parentheses_node_create(pm_parser_t *parser, const pm_token_t *opening, pm_node_t *body, const pm_token_t *closing) {
- pm_parentheses_node_t *node = PM_ALLOC_NODE(parser, pm_parentheses_node_t);
+pm_parentheses_node_create(pm_parser_t *parser, const pm_token_t *opening, pm_node_t *body, const pm_token_t *closing, pm_node_flags_t flags) {
+ pm_parentheses_node_t *node = PM_NODE_ALLOC(parser, pm_parentheses_node_t);
*node = (pm_parentheses_node_t) {
- {
- .type = PM_PARENTHESES_NODE,
- .location = {
- .start = opening->start,
- .end = closing->end
- }
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_PARENTHESES_NODE, flags, opening, closing),
.body = body,
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
.closing_loc = PM_LOCATION_TOKEN_VALUE(closing)
@@ -6445,16 +5780,10 @@ pm_parentheses_node_create(pm_parser_t *parser, const pm_token_t *opening, pm_no
*/
static pm_pinned_expression_node_t *
pm_pinned_expression_node_create(pm_parser_t *parser, pm_node_t *expression, const pm_token_t *operator, const pm_token_t *lparen, const pm_token_t *rparen) {
- pm_pinned_expression_node_t *node = PM_ALLOC_NODE(parser, pm_pinned_expression_node_t);
+ pm_pinned_expression_node_t *node = PM_NODE_ALLOC(parser, pm_pinned_expression_node_t);
*node = (pm_pinned_expression_node_t) {
- {
- .type = PM_PINNED_EXPRESSION_NODE,
- .location = {
- .start = operator->start,
- .end = rparen->end
- }
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_PINNED_EXPRESSION_NODE, 0, operator, rparen),
.expression = expression,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.lparen_loc = PM_LOCATION_TOKEN_VALUE(lparen),
@@ -6469,16 +5798,10 @@ pm_pinned_expression_node_create(pm_parser_t *parser, pm_node_t *expression, con
*/
static pm_pinned_variable_node_t *
pm_pinned_variable_node_create(pm_parser_t *parser, const pm_token_t *operator, pm_node_t *variable) {
- pm_pinned_variable_node_t *node = PM_ALLOC_NODE(parser, pm_pinned_variable_node_t);
+ pm_pinned_variable_node_t *node = PM_NODE_ALLOC(parser, pm_pinned_variable_node_t);
*node = (pm_pinned_variable_node_t) {
- {
- .type = PM_PINNED_VARIABLE_NODE,
- .location = {
- .start = operator->start,
- .end = variable->location.end
- }
- },
+ .base = PM_NODE_INIT_TOKEN_NODE(parser, PM_PINNED_VARIABLE_NODE, 0, operator, variable),
.variable = variable,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator)
};
@@ -6491,16 +5814,10 @@ pm_pinned_variable_node_create(pm_parser_t *parser, const pm_token_t *operator,
*/
static pm_post_execution_node_t *
pm_post_execution_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_token_t *opening, pm_statements_node_t *statements, const pm_token_t *closing) {
- pm_post_execution_node_t *node = PM_ALLOC_NODE(parser, pm_post_execution_node_t);
+ pm_post_execution_node_t *node = PM_NODE_ALLOC(parser, pm_post_execution_node_t);
*node = (pm_post_execution_node_t) {
- {
- .type = PM_POST_EXECUTION_NODE,
- .location = {
- .start = keyword->start,
- .end = closing->end
- }
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_POST_EXECUTION_NODE, 0, keyword, closing),
.statements = statements,
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
@@ -6515,16 +5832,10 @@ pm_post_execution_node_create(pm_parser_t *parser, const pm_token_t *keyword, co
*/
static pm_pre_execution_node_t *
pm_pre_execution_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_token_t *opening, pm_statements_node_t *statements, const pm_token_t *closing) {
- pm_pre_execution_node_t *node = PM_ALLOC_NODE(parser, pm_pre_execution_node_t);
+ pm_pre_execution_node_t *node = PM_NODE_ALLOC(parser, pm_pre_execution_node_t);
*node = (pm_pre_execution_node_t) {
- {
- .type = PM_PRE_EXECUTION_NODE,
- .location = {
- .start = keyword->start,
- .end = closing->end
- }
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_PRE_EXECUTION_NODE, 0, keyword, closing),
.statements = statements,
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
@@ -6542,7 +5853,7 @@ pm_range_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *ope
pm_assert_value_expression(parser, left);
pm_assert_value_expression(parser, right);
- pm_range_node_t *node = PM_ALLOC_NODE(parser, pm_range_node_t);
+ pm_range_node_t *node = PM_NODE_ALLOC(parser, pm_range_node_t);
pm_node_flags_t flags = 0;
// Indicate that this node is an exclusive range if the operator is `...`.
@@ -6561,14 +5872,7 @@ pm_range_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *ope
}
*node = (pm_range_node_t) {
- {
- .type = PM_RANGE_NODE,
- .flags = flags,
- .location = {
- .start = (left == NULL ? operator->start : left->location.start),
- .end = (right == NULL ? operator->end : right->location.end)
- }
- },
+ .base = PM_NODE_INIT(parser, PM_RANGE_NODE, flags, (left == NULL ? operator->start : left->location.start), (right == NULL ? operator->end : right->location.end)),
.left = left,
.right = right,
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator)
@@ -6583,9 +5887,12 @@ pm_range_node_create(pm_parser_t *parser, pm_node_t *left, const pm_token_t *ope
static pm_redo_node_t *
pm_redo_node_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_KEYWORD_REDO);
- pm_redo_node_t *node = PM_ALLOC_NODE(parser, pm_redo_node_t);
+ pm_redo_node_t *node = PM_NODE_ALLOC(parser, pm_redo_node_t);
+
+ *node = (pm_redo_node_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_REDO_NODE, 0, token)
+ };
- *node = (pm_redo_node_t) {{ .type = PM_REDO_NODE, .location = PM_LOCATION_TOKEN_VALUE(token) }};
return node;
}
@@ -6595,17 +5902,11 @@ pm_redo_node_create(pm_parser_t *parser, const pm_token_t *token) {
*/
static pm_regular_expression_node_t *
pm_regular_expression_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *content, const pm_token_t *closing, const pm_string_t *unescaped) {
- pm_regular_expression_node_t *node = PM_ALLOC_NODE(parser, pm_regular_expression_node_t);
+ pm_regular_expression_node_t *node = PM_NODE_ALLOC(parser, pm_regular_expression_node_t);
+ pm_node_flags_t flags = pm_regular_expression_flags_create(parser, closing) | PM_NODE_FLAG_STATIC_LITERAL;
*node = (pm_regular_expression_node_t) {
- {
- .type = PM_REGULAR_EXPRESSION_NODE,
- .flags = pm_regular_expression_flags_create(parser, closing) | PM_NODE_FLAG_STATIC_LITERAL,
- .location = {
- .start = MIN(opening->start, closing->start),
- .end = MAX(opening->end, closing->end)
- }
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_REGULAR_EXPRESSION_NODE, flags, opening, closing),
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
.content_loc = PM_LOCATION_TOKEN_VALUE(content),
.closing_loc = PM_LOCATION_TOKEN_VALUE(closing),
@@ -6628,13 +5929,10 @@ pm_regular_expression_node_create(pm_parser_t *parser, const pm_token_t *opening
*/
static pm_required_parameter_node_t *
pm_required_parameter_node_create(pm_parser_t *parser, const pm_token_t *token) {
- pm_required_parameter_node_t *node = PM_ALLOC_NODE(parser, pm_required_parameter_node_t);
+ pm_required_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_required_parameter_node_t);
*node = (pm_required_parameter_node_t) {
- {
- .type = PM_REQUIRED_PARAMETER_NODE,
- .location = PM_LOCATION_TOKEN_VALUE(token)
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_REQUIRED_PARAMETER_NODE, 0, token),
.name = pm_parser_constant_id_token(parser, token)
};
@@ -6646,16 +5944,10 @@ pm_required_parameter_node_create(pm_parser_t *parser, const pm_token_t *token)
*/
static pm_rescue_modifier_node_t *
pm_rescue_modifier_node_create(pm_parser_t *parser, pm_node_t *expression, const pm_token_t *keyword, pm_node_t *rescue_expression) {
- pm_rescue_modifier_node_t *node = PM_ALLOC_NODE(parser, pm_rescue_modifier_node_t);
+ pm_rescue_modifier_node_t *node = PM_NODE_ALLOC(parser, pm_rescue_modifier_node_t);
*node = (pm_rescue_modifier_node_t) {
- {
- .type = PM_RESCUE_MODIFIER_NODE,
- .location = {
- .start = expression->location.start,
- .end = rescue_expression->location.end
- }
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_RESCUE_MODIFIER_NODE, 0, expression, rescue_expression),
.expression = expression,
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
.rescue_expression = rescue_expression
@@ -6669,18 +5961,16 @@ pm_rescue_modifier_node_create(pm_parser_t *parser, pm_node_t *expression, const
*/
static pm_rescue_node_t *
pm_rescue_node_create(pm_parser_t *parser, const pm_token_t *keyword) {
- pm_rescue_node_t *node = PM_ALLOC_NODE(parser, pm_rescue_node_t);
+ pm_rescue_node_t *node = PM_NODE_ALLOC(parser, pm_rescue_node_t);
*node = (pm_rescue_node_t) {
- {
- .type = PM_RESCUE_NODE,
- .location = PM_LOCATION_TOKEN_VALUE(keyword)
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_RESCUE_NODE, 0, keyword),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
- .operator_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
+ .operator_loc = { 0 },
+ .then_keyword_loc = { 0 },
.reference = NULL,
.statements = NULL,
- .consequent = NULL,
+ .subsequent = NULL,
.exceptions = { 0 }
};
@@ -6713,12 +6003,12 @@ pm_rescue_node_statements_set(pm_rescue_node_t *node, pm_statements_node_t *stat
}
/**
- * Set the consequent of a rescue node, and update the location.
+ * Set the subsequent of a rescue node, and update the location.
*/
static void
-pm_rescue_node_consequent_set(pm_rescue_node_t *node, pm_rescue_node_t *consequent) {
- node->consequent = consequent;
- node->base.location.end = consequent->base.location.end;
+pm_rescue_node_subsequent_set(pm_rescue_node_t *node, pm_rescue_node_t *subsequent) {
+ node->subsequent = subsequent;
+ node->base.location.end = subsequent->base.location.end;
}
/**
@@ -6735,16 +6025,14 @@ pm_rescue_node_exceptions_append(pm_rescue_node_t *node, pm_node_t *exception) {
*/
static pm_rest_parameter_node_t *
pm_rest_parameter_node_create(pm_parser_t *parser, const pm_token_t *operator, const pm_token_t *name) {
- pm_rest_parameter_node_t *node = PM_ALLOC_NODE(parser, pm_rest_parameter_node_t);
+ pm_rest_parameter_node_t *node = PM_NODE_ALLOC(parser, pm_rest_parameter_node_t);
*node = (pm_rest_parameter_node_t) {
- {
- .type = PM_REST_PARAMETER_NODE,
- .location = {
- .start = operator->start,
- .end = (name->type == PM_TOKEN_NOT_PROVIDED ? operator->end : name->end)
- }
- },
+ .base = (
+ (name->type == PM_TOKEN_NOT_PROVIDED)
+ ? PM_NODE_INIT_TOKEN(parser, PM_REST_PARAMETER_NODE, 0, operator)
+ : PM_NODE_INIT_TOKENS(parser, PM_REST_PARAMETER_NODE, 0, operator, name)
+ ),
.name = pm_parser_optional_constant_id_token(parser, name),
.name_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(name),
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator)
@@ -6759,9 +6047,12 @@ pm_rest_parameter_node_create(pm_parser_t *parser, const pm_token_t *operator, c
static pm_retry_node_t *
pm_retry_node_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_KEYWORD_RETRY);
- pm_retry_node_t *node = PM_ALLOC_NODE(parser, pm_retry_node_t);
+ pm_retry_node_t *node = PM_NODE_ALLOC(parser, pm_retry_node_t);
+
+ *node = (pm_retry_node_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_RETRY_NODE, 0, token)
+ };
- *node = (pm_retry_node_t) {{ .type = PM_RETRY_NODE, .location = PM_LOCATION_TOKEN_VALUE(token) }};
return node;
}
@@ -6770,17 +6061,14 @@ pm_retry_node_create(pm_parser_t *parser, const pm_token_t *token) {
*/
static pm_return_node_t *
pm_return_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_arguments_node_t *arguments) {
- pm_return_node_t *node = PM_ALLOC_NODE(parser, pm_return_node_t);
+ pm_return_node_t *node = PM_NODE_ALLOC(parser, pm_return_node_t);
*node = (pm_return_node_t) {
- {
- .type = PM_RETURN_NODE,
- .flags = 0,
- .location = {
- .start = keyword->start,
- .end = (arguments == NULL ? keyword->end : arguments->base.location.end)
- }
- },
+ .base = (
+ (arguments == NULL)
+ ? PM_NODE_INIT_TOKEN(parser, PM_RETURN_NODE, 0, keyword)
+ : PM_NODE_INIT_TOKEN_NODE(parser, PM_RETURN_NODE, 0, keyword, arguments)
+ ),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
.arguments = arguments
};
@@ -6794,12 +6082,11 @@ pm_return_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_argumen
static pm_self_node_t *
pm_self_node_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_KEYWORD_SELF);
- pm_self_node_t *node = PM_ALLOC_NODE(parser, pm_self_node_t);
+ pm_self_node_t *node = PM_NODE_ALLOC(parser, pm_self_node_t);
- *node = (pm_self_node_t) {{
- .type = PM_SELF_NODE,
- .location = PM_LOCATION_TOKEN_VALUE(token)
- }};
+ *node = (pm_self_node_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_SELF_NODE, 0, token)
+ };
return node;
}
@@ -6809,14 +6096,10 @@ pm_self_node_create(pm_parser_t *parser, const pm_token_t *token) {
*/
static pm_shareable_constant_node_t *
pm_shareable_constant_node_create(pm_parser_t *parser, pm_node_t *write, pm_shareable_constant_value_t value) {
- pm_shareable_constant_node_t *node = PM_ALLOC_NODE(parser, pm_shareable_constant_node_t);
+ pm_shareable_constant_node_t *node = PM_NODE_ALLOC(parser, pm_shareable_constant_node_t);
*node = (pm_shareable_constant_node_t) {
- {
- .type = PM_SHAREABLE_CONSTANT_NODE,
- .flags = (pm_node_flags_t) value,
- .location = PM_LOCATION_NODE_VALUE(write)
- },
+ .base = PM_NODE_INIT_NODE(parser, PM_SHAREABLE_CONSTANT_NODE, (pm_node_flags_t) value, write),
.write = write
};
@@ -6828,16 +6111,10 @@ pm_shareable_constant_node_create(pm_parser_t *parser, pm_node_t *write, pm_shar
*/
static pm_singleton_class_node_t *
pm_singleton_class_node_create(pm_parser_t *parser, pm_constant_id_list_t *locals, const pm_token_t *class_keyword, const pm_token_t *operator, pm_node_t *expression, pm_node_t *body, const pm_token_t *end_keyword) {
- pm_singleton_class_node_t *node = PM_ALLOC_NODE(parser, pm_singleton_class_node_t);
+ pm_singleton_class_node_t *node = PM_NODE_ALLOC(parser, pm_singleton_class_node_t);
*node = (pm_singleton_class_node_t) {
- {
- .type = PM_SINGLETON_CLASS_NODE,
- .location = {
- .start = class_keyword->start,
- .end = end_keyword->end
- }
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_SINGLETON_CLASS_NODE, 0, class_keyword, end_keyword),
.locals = *locals,
.class_keyword_loc = PM_LOCATION_TOKEN_VALUE(class_keyword),
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
@@ -6855,13 +6132,11 @@ pm_singleton_class_node_create(pm_parser_t *parser, pm_constant_id_list_t *local
static pm_source_encoding_node_t *
pm_source_encoding_node_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_KEYWORD___ENCODING__);
- pm_source_encoding_node_t *node = PM_ALLOC_NODE(parser, pm_source_encoding_node_t);
+ pm_source_encoding_node_t *node = PM_NODE_ALLOC(parser, pm_source_encoding_node_t);
- *node = (pm_source_encoding_node_t) {{
- .type = PM_SOURCE_ENCODING_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .location = PM_LOCATION_TOKEN_VALUE(token)
- }};
+ *node = (pm_source_encoding_node_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_SOURCE_ENCODING_NODE, PM_NODE_FLAG_STATIC_LITERAL, token)
+ };
return node;
}
@@ -6871,7 +6146,7 @@ pm_source_encoding_node_create(pm_parser_t *parser, const pm_token_t *token) {
*/
static pm_source_file_node_t*
pm_source_file_node_create(pm_parser_t *parser, const pm_token_t *file_keyword) {
- pm_source_file_node_t *node = PM_ALLOC_NODE(parser, pm_source_file_node_t);
+ pm_source_file_node_t *node = PM_NODE_ALLOC(parser, pm_source_file_node_t);
assert(file_keyword->type == PM_TOKEN_KEYWORD___FILE__);
pm_node_flags_t flags = 0;
@@ -6886,11 +6161,7 @@ pm_source_file_node_create(pm_parser_t *parser, const pm_token_t *file_keyword)
}
*node = (pm_source_file_node_t) {
- {
- .type = PM_SOURCE_FILE_NODE,
- .flags = flags,
- .location = PM_LOCATION_TOKEN_VALUE(file_keyword),
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_SOURCE_FILE_NODE, flags, file_keyword),
.filepath = parser->filepath
};
@@ -6903,13 +6174,11 @@ pm_source_file_node_create(pm_parser_t *parser, const pm_token_t *file_keyword)
static pm_source_line_node_t *
pm_source_line_node_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_KEYWORD___LINE__);
- pm_source_line_node_t *node = PM_ALLOC_NODE(parser, pm_source_line_node_t);
+ pm_source_line_node_t *node = PM_NODE_ALLOC(parser, pm_source_line_node_t);
- *node = (pm_source_line_node_t) {{
- .type = PM_SOURCE_LINE_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .location = PM_LOCATION_TOKEN_VALUE(token)
- }};
+ *node = (pm_source_line_node_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_SOURCE_LINE_NODE, PM_NODE_FLAG_STATIC_LITERAL, token)
+ };
return node;
}
@@ -6919,16 +6188,14 @@ pm_source_line_node_create(pm_parser_t *parser, const pm_token_t *token) {
*/
static pm_splat_node_t *
pm_splat_node_create(pm_parser_t *parser, const pm_token_t *operator, pm_node_t *expression) {
- pm_splat_node_t *node = PM_ALLOC_NODE(parser, pm_splat_node_t);
+ pm_splat_node_t *node = PM_NODE_ALLOC(parser, pm_splat_node_t);
*node = (pm_splat_node_t) {
- {
- .type = PM_SPLAT_NODE,
- .location = {
- .start = operator->start,
- .end = (expression == NULL ? operator->end : expression->location.end)
- }
- },
+ .base = (
+ (expression == NULL)
+ ? PM_NODE_INIT_TOKEN(parser, PM_SPLAT_NODE, 0, operator)
+ : PM_NODE_INIT_TOKEN_NODE(parser, PM_SPLAT_NODE, 0, operator, expression)
+ ),
.operator_loc = PM_LOCATION_TOKEN_VALUE(operator),
.expression = expression
};
@@ -6941,13 +6208,10 @@ pm_splat_node_create(pm_parser_t *parser, const pm_token_t *operator, pm_node_t
*/
static pm_statements_node_t *
pm_statements_node_create(pm_parser_t *parser) {
- pm_statements_node_t *node = PM_ALLOC_NODE(parser, pm_statements_node_t);
+ pm_statements_node_t *node = PM_NODE_ALLOC(parser, pm_statements_node_t);
*node = (pm_statements_node_t) {
- {
- .type = PM_STATEMENTS_NODE,
- .location = PM_LOCATION_NULL_VALUE(parser)
- },
+ .base = PM_NODE_INIT_BASE(parser, PM_STATEMENTS_NODE, 0),
.body = { 0 }
};
@@ -6989,7 +6253,7 @@ pm_statements_node_body_update(pm_statements_node_t *node, pm_node_t *statement)
* Append a new node to the given StatementsNode node's body.
*/
static void
-pm_statements_node_body_append(pm_parser_t *parser, pm_statements_node_t *node, pm_node_t *statement) {
+pm_statements_node_body_append(pm_parser_t *parser, pm_statements_node_t *node, pm_node_t *statement, bool newline) {
pm_statements_node_body_update(node, statement);
if (node->body.size > 0) {
@@ -7009,7 +6273,7 @@ pm_statements_node_body_append(pm_parser_t *parser, pm_statements_node_t *node,
}
pm_node_list_append(&node->body, statement);
- pm_node_flag_set(statement, PM_NODE_FLAG_NEWLINE);
+ if (newline) pm_node_flag_set(statement, PM_NODE_FLAG_NEWLINE);
}
/**
@@ -7027,7 +6291,7 @@ pm_statements_node_body_prepend(pm_statements_node_t *node, pm_node_t *statement
*/
static inline pm_string_node_t *
pm_string_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *content, const pm_token_t *closing, const pm_string_t *string) {
- pm_string_node_t *node = PM_ALLOC_NODE(parser, pm_string_node_t);
+ pm_string_node_t *node = PM_NODE_ALLOC(parser, pm_string_node_t);
pm_node_flags_t flags = 0;
switch (parser->frozen_string_literal) {
@@ -7039,15 +6303,11 @@ pm_string_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening,
break;
}
+ const uint8_t *start = (opening->type == PM_TOKEN_NOT_PROVIDED ? content->start : opening->start);
+ const uint8_t *end = (closing->type == PM_TOKEN_NOT_PROVIDED ? content->end : closing->end);
+
*node = (pm_string_node_t) {
- {
- .type = PM_STRING_NODE,
- .flags = flags,
- .location = {
- .start = (opening->type == PM_TOKEN_NOT_PROVIDED ? content->start : opening->start),
- .end = (closing->type == PM_TOKEN_NOT_PROVIDED ? content->end : closing->end)
- }
- },
+ .base = PM_NODE_INIT(parser, PM_STRING_NODE, flags, start, end),
.opening_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
.content_loc = PM_LOCATION_TOKEN_VALUE(content),
.closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing),
@@ -7082,7 +6342,7 @@ pm_string_node_create_current_string(pm_parser_t *parser, const pm_token_t *open
static pm_super_node_t *
pm_super_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_arguments_t *arguments) {
assert(keyword->type == PM_TOKEN_KEYWORD_SUPER);
- pm_super_node_t *node = PM_ALLOC_NODE(parser, pm_super_node_t);
+ pm_super_node_t *node = PM_NODE_ALLOC(parser, pm_super_node_t);
const uint8_t *end = pm_arguments_end(arguments);
if (end == NULL) {
@@ -7090,13 +6350,7 @@ pm_super_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_argument
}
*node = (pm_super_node_t) {
- {
- .type = PM_SUPER_NODE,
- .location = {
- .start = keyword->start,
- .end = end,
- }
- },
+ .base = PM_NODE_INIT(parser, PM_SUPER_NODE, 0, keyword->start, end),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
.lparen_loc = arguments->opening_loc,
.arguments = arguments->arguments,
@@ -7323,17 +6577,13 @@ parse_and_validate_regular_expression_encoding(pm_parser_t *parser, const pm_str
*/
static pm_symbol_node_t *
pm_symbol_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *value, const pm_token_t *closing, const pm_string_t *unescaped, pm_node_flags_t flags) {
- pm_symbol_node_t *node = PM_ALLOC_NODE(parser, pm_symbol_node_t);
+ pm_symbol_node_t *node = PM_NODE_ALLOC(parser, pm_symbol_node_t);
+
+ const uint8_t *start = (opening->type == PM_TOKEN_NOT_PROVIDED ? value->start : opening->start);
+ const uint8_t *end = (closing->type == PM_TOKEN_NOT_PROVIDED ? value->end : closing->end);
*node = (pm_symbol_node_t) {
- {
- .type = PM_SYMBOL_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL | flags,
- .location = {
- .start = (opening->type == PM_TOKEN_NOT_PROVIDED ? value->start : opening->start),
- .end = (closing->type == PM_TOKEN_NOT_PROVIDED ? value->end : closing->end)
- }
- },
+ .base = PM_NODE_INIT(parser, PM_SYMBOL_NODE, PM_NODE_FLAG_STATIC_LITERAL | flags, start, end),
.opening_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
.value_loc = PM_LOCATION_TOKEN_VALUE(value),
.closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing),
@@ -7378,7 +6628,7 @@ pm_symbol_node_label_create(pm_parser_t *parser, const pm_token_t *token) {
assert((label.end - label.start) >= 0);
pm_string_shared_init(&node->unescaped, label.start, label.end);
- pm_node_flag_set((pm_node_t *) node, parse_symbol_encoding(parser, &label, &node->unescaped, false));
+ pm_node_flag_set(UP(node), parse_symbol_encoding(parser, &label, &node->unescaped, false));
break;
}
@@ -7404,14 +6654,10 @@ pm_symbol_node_label_create(pm_parser_t *parser, const pm_token_t *token) {
*/
static pm_symbol_node_t *
pm_symbol_node_synthesized_create(pm_parser_t *parser, const char *content) {
- pm_symbol_node_t *node = PM_ALLOC_NODE(parser, pm_symbol_node_t);
+ pm_symbol_node_t *node = PM_NODE_ALLOC(parser, pm_symbol_node_t);
*node = (pm_symbol_node_t) {
- {
- .type = PM_SYMBOL_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL | PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING,
- .location = PM_LOCATION_NULL_VALUE(parser)
- },
+ .base = PM_NODE_INIT_BASE(parser, PM_SYMBOL_NODE, PM_NODE_FLAG_STATIC_LITERAL | PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING),
.value_loc = PM_LOCATION_NULL_VALUE(parser),
.unescaped = { 0 }
};
@@ -7446,17 +6692,10 @@ pm_symbol_node_label_p(pm_node_t *node) {
*/
static pm_symbol_node_t *
pm_string_node_to_symbol_node(pm_parser_t *parser, pm_string_node_t *node, const pm_token_t *opening, const pm_token_t *closing) {
- pm_symbol_node_t *new_node = PM_ALLOC_NODE(parser, pm_symbol_node_t);
+ pm_symbol_node_t *new_node = PM_NODE_ALLOC(parser, pm_symbol_node_t);
*new_node = (pm_symbol_node_t) {
- {
- .type = PM_SYMBOL_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .location = {
- .start = opening->start,
- .end = closing->end
- }
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_SYMBOL_NODE, PM_NODE_FLAG_STATIC_LITERAL, opening, closing),
.opening_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(opening),
.value_loc = node->content_loc,
.closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing),
@@ -7464,7 +6703,7 @@ pm_string_node_to_symbol_node(pm_parser_t *parser, pm_string_node_t *node, const
};
pm_token_t content = { .type = PM_TOKEN_IDENTIFIER, .start = node->content_loc.start, .end = node->content_loc.end };
- pm_node_flag_set((pm_node_t *) new_node, parse_symbol_encoding(parser, &content, &node->unescaped, true));
+ pm_node_flag_set(UP(new_node), parse_symbol_encoding(parser, &content, &node->unescaped, true));
// We are explicitly _not_ using pm_node_destroy here because we don't want
// to trash the unescaped string. We could instead copy the string if we
@@ -7479,7 +6718,7 @@ pm_string_node_to_symbol_node(pm_parser_t *parser, pm_string_node_t *node, const
*/
static pm_string_node_t *
pm_symbol_node_to_string_node(pm_parser_t *parser, pm_symbol_node_t *node) {
- pm_string_node_t *new_node = PM_ALLOC_NODE(parser, pm_string_node_t);
+ pm_string_node_t *new_node = PM_NODE_ALLOC(parser, pm_string_node_t);
pm_node_flags_t flags = 0;
switch (parser->frozen_string_literal) {
@@ -7492,11 +6731,7 @@ pm_symbol_node_to_string_node(pm_parser_t *parser, pm_symbol_node_t *node) {
}
*new_node = (pm_string_node_t) {
- {
- .type = PM_STRING_NODE,
- .flags = flags,
- .location = node->base.location
- },
+ .base = PM_NODE_INIT_NODE(parser, PM_STRING_NODE, flags, node),
.opening_loc = node->opening_loc,
.content_loc = node->value_loc,
.closing_loc = node->closing_loc,
@@ -7517,13 +6752,11 @@ pm_symbol_node_to_string_node(pm_parser_t *parser, pm_symbol_node_t *node) {
static pm_true_node_t *
pm_true_node_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_KEYWORD_TRUE);
- pm_true_node_t *node = PM_ALLOC_NODE(parser, pm_true_node_t);
+ pm_true_node_t *node = PM_NODE_ALLOC(parser, pm_true_node_t);
- *node = (pm_true_node_t) {{
- .type = PM_TRUE_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .location = PM_LOCATION_TOKEN_VALUE(token)
- }};
+ *node = (pm_true_node_t) {
+ .base = PM_NODE_INIT_TOKEN(parser, PM_TRUE_NODE, PM_NODE_FLAG_STATIC_LITERAL, token)
+ };
return node;
}
@@ -7533,13 +6766,11 @@ pm_true_node_create(pm_parser_t *parser, const pm_token_t *token) {
*/
static pm_true_node_t *
pm_true_node_synthesized_create(pm_parser_t *parser) {
- pm_true_node_t *node = PM_ALLOC_NODE(parser, pm_true_node_t);
+ pm_true_node_t *node = PM_NODE_ALLOC(parser, pm_true_node_t);
- *node = (pm_true_node_t) {{
- .type = PM_TRUE_NODE,
- .flags = PM_NODE_FLAG_STATIC_LITERAL,
- .location = { .start = parser->start, .end = parser->end }
- }};
+ *node = (pm_true_node_t) {
+ .base = PM_NODE_INIT_BASE(parser, PM_TRUE_NODE, PM_NODE_FLAG_STATIC_LITERAL)
+ };
return node;
}
@@ -7550,13 +6781,10 @@ pm_true_node_synthesized_create(pm_parser_t *parser) {
static pm_undef_node_t *
pm_undef_node_create(pm_parser_t *parser, const pm_token_t *token) {
assert(token->type == PM_TOKEN_KEYWORD_UNDEF);
- pm_undef_node_t *node = PM_ALLOC_NODE(parser, pm_undef_node_t);
+ pm_undef_node_t *node = PM_NODE_ALLOC(parser, pm_undef_node_t);
*node = (pm_undef_node_t) {
- {
- .type = PM_UNDEF_NODE,
- .location = PM_LOCATION_TOKEN_VALUE(token),
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_UNDEF_NODE, 0, token),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(token),
.names = { 0 }
};
@@ -7579,30 +6807,18 @@ pm_undef_node_append(pm_undef_node_t *node, pm_node_t *name) {
static pm_unless_node_t *
pm_unless_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t *predicate, const pm_token_t *then_keyword, pm_statements_node_t *statements) {
pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL);
- pm_unless_node_t *node = PM_ALLOC_NODE(parser, pm_unless_node_t);
- const uint8_t *end;
- if (statements != NULL) {
- end = statements->base.location.end;
- } else {
- end = predicate->location.end;
- }
+ pm_unless_node_t *node = PM_NODE_ALLOC(parser, pm_unless_node_t);
+ pm_node_t *end = statements == NULL ? predicate : UP(statements);
*node = (pm_unless_node_t) {
- {
- .type = PM_UNLESS_NODE,
- .flags = PM_NODE_FLAG_NEWLINE,
- .location = {
- .start = keyword->start,
- .end = end
- },
- },
+ .base = PM_NODE_INIT_TOKEN_NODE(parser, PM_UNLESS_NODE, PM_NODE_FLAG_NEWLINE, keyword, end),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
.predicate = predicate,
.then_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(then_keyword),
.statements = statements,
- .consequent = NULL,
- .end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
+ .else_clause = NULL,
+ .end_keyword_loc = { 0 }
};
return node;
@@ -7614,26 +6830,19 @@ pm_unless_node_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t
static pm_unless_node_t *
pm_unless_node_modifier_create(pm_parser_t *parser, pm_node_t *statement, const pm_token_t *unless_keyword, pm_node_t *predicate) {
pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL);
- pm_unless_node_t *node = PM_ALLOC_NODE(parser, pm_unless_node_t);
+ pm_unless_node_t *node = PM_NODE_ALLOC(parser, pm_unless_node_t);
pm_statements_node_t *statements = pm_statements_node_create(parser);
- pm_statements_node_body_append(parser, statements, statement);
+ pm_statements_node_body_append(parser, statements, statement, true);
*node = (pm_unless_node_t) {
- {
- .type = PM_UNLESS_NODE,
- .flags = PM_NODE_FLAG_NEWLINE,
- .location = {
- .start = statement->location.start,
- .end = predicate->location.end
- },
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_UNLESS_NODE, PM_NODE_FLAG_NEWLINE, statement, predicate),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(unless_keyword),
.predicate = predicate,
- .then_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
+ .then_keyword_loc = { 0 },
.statements = statements,
- .consequent = NULL,
- .end_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE
+ .else_clause = NULL,
+ .end_keyword_loc = { 0 }
};
return node;
@@ -7646,23 +6855,40 @@ pm_unless_node_end_keyword_loc_set(pm_unless_node_t *node, const pm_token_t *end
}
/**
+ * Loop modifiers could potentially modify an expression that contains block
+ * exits. In this case we need to loop through them and remove them from the
+ * list of block exits so that they do not later get marked as invalid.
+ */
+static void
+pm_loop_modifier_block_exits(pm_parser_t *parser, pm_statements_node_t *statements) {
+ assert(parser->current_block_exits != NULL);
+
+ // All of the block exits that we want to remove should be within the
+ // statements, and since we are modifying the statements, we shouldn't have
+ // to check the end location.
+ const uint8_t *start = statements->base.location.start;
+
+ for (size_t index = parser->current_block_exits->size; index > 0; index--) {
+ pm_node_t *block_exit = parser->current_block_exits->nodes[index - 1];
+ if (block_exit->location.start < start) break;
+
+ // Implicitly remove from the list by lowering the size.
+ parser->current_block_exits->size--;
+ }
+}
+
+/**
* Allocate a new UntilNode node.
*/
static pm_until_node_t *
-pm_until_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_token_t *closing, pm_node_t *predicate, pm_statements_node_t *statements, pm_node_flags_t flags) {
- pm_until_node_t *node = PM_ALLOC_NODE(parser, pm_until_node_t);
+pm_until_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_token_t *do_keyword, const pm_token_t *closing, pm_node_t *predicate, pm_statements_node_t *statements, pm_node_flags_t flags) {
+ pm_until_node_t *node = PM_NODE_ALLOC(parser, pm_until_node_t);
pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL);
*node = (pm_until_node_t) {
- {
- .type = PM_UNTIL_NODE,
- .flags = flags,
- .location = {
- .start = keyword->start,
- .end = closing->end,
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_UNTIL_NODE, flags, keyword, closing),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
+ .do_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(do_keyword),
.closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing),
.predicate = predicate,
.statements = statements
@@ -7676,20 +6902,15 @@ pm_until_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_to
*/
static pm_until_node_t *
pm_until_node_modifier_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t *predicate, pm_statements_node_t *statements, pm_node_flags_t flags) {
- pm_until_node_t *node = PM_ALLOC_NODE(parser, pm_until_node_t);
+ pm_until_node_t *node = PM_NODE_ALLOC(parser, pm_until_node_t);
pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL);
+ pm_loop_modifier_block_exits(parser, statements);
*node = (pm_until_node_t) {
- {
- .type = PM_UNTIL_NODE,
- .flags = flags,
- .location = {
- .start = statements->base.location.start,
- .end = predicate->location.end,
- },
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_UNTIL_NODE, flags, statements, predicate),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
- .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
+ .do_keyword_loc = { 0 },
+ .closing_loc = { 0 },
.predicate = predicate,
.statements = statements
};
@@ -7702,19 +6923,13 @@ pm_until_node_modifier_create(pm_parser_t *parser, const pm_token_t *keyword, pm
*/
static pm_when_node_t *
pm_when_node_create(pm_parser_t *parser, const pm_token_t *keyword) {
- pm_when_node_t *node = PM_ALLOC_NODE(parser, pm_when_node_t);
+ pm_when_node_t *node = PM_NODE_ALLOC(parser, pm_when_node_t);
*node = (pm_when_node_t) {
- {
- .type = PM_WHEN_NODE,
- .location = {
- .start = keyword->start,
- .end = NULL
- }
- },
+ .base = PM_NODE_INIT_TOKEN(parser, PM_WHEN_NODE, 0, keyword),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
.statements = NULL,
- .then_keyword_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
+ .then_keyword_loc = { 0 },
.conditions = { 0 }
};
@@ -7755,20 +6970,14 @@ pm_when_node_statements_set(pm_when_node_t *node, pm_statements_node_t *statemen
* Allocate a new WhileNode node.
*/
static pm_while_node_t *
-pm_while_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_token_t *closing, pm_node_t *predicate, pm_statements_node_t *statements, pm_node_flags_t flags) {
- pm_while_node_t *node = PM_ALLOC_NODE(parser, pm_while_node_t);
+pm_while_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_token_t *do_keyword, const pm_token_t *closing, pm_node_t *predicate, pm_statements_node_t *statements, pm_node_flags_t flags) {
+ pm_while_node_t *node = PM_NODE_ALLOC(parser, pm_while_node_t);
pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL);
*node = (pm_while_node_t) {
- {
- .type = PM_WHILE_NODE,
- .flags = flags,
- .location = {
- .start = keyword->start,
- .end = closing->end
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_WHILE_NODE, flags, keyword, closing),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
+ .do_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(do_keyword),
.closing_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(closing),
.predicate = predicate,
.statements = statements
@@ -7782,20 +6991,15 @@ pm_while_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_to
*/
static pm_while_node_t *
pm_while_node_modifier_create(pm_parser_t *parser, const pm_token_t *keyword, pm_node_t *predicate, pm_statements_node_t *statements, pm_node_flags_t flags) {
- pm_while_node_t *node = PM_ALLOC_NODE(parser, pm_while_node_t);
+ pm_while_node_t *node = PM_NODE_ALLOC(parser, pm_while_node_t);
pm_conditional_predicate(parser, predicate, PM_CONDITIONAL_PREDICATE_TYPE_CONDITIONAL);
+ pm_loop_modifier_block_exits(parser, statements);
*node = (pm_while_node_t) {
- {
- .type = PM_WHILE_NODE,
- .flags = flags,
- .location = {
- .start = statements->base.location.start,
- .end = predicate->location.end
- },
- },
+ .base = PM_NODE_INIT_NODES(parser, PM_WHILE_NODE, flags, statements, predicate),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
- .closing_loc = PM_OPTIONAL_LOCATION_NOT_PROVIDED_VALUE,
+ .do_keyword_loc = { 0 },
+ .closing_loc = { 0 },
.predicate = predicate,
.statements = statements
};
@@ -7808,14 +7012,12 @@ pm_while_node_modifier_create(pm_parser_t *parser, const pm_token_t *keyword, pm
*/
static pm_while_node_t *
pm_while_node_synthesized_create(pm_parser_t *parser, pm_node_t *predicate, pm_statements_node_t *statements) {
- pm_while_node_t *node = PM_ALLOC_NODE(parser, pm_while_node_t);
+ pm_while_node_t *node = PM_NODE_ALLOC(parser, pm_while_node_t);
*node = (pm_while_node_t) {
- {
- .type = PM_WHILE_NODE,
- .location = PM_LOCATION_NULL_VALUE(parser)
- },
+ .base = PM_NODE_INIT_BASE(parser, PM_WHILE_NODE, 0),
.keyword_loc = PM_LOCATION_NULL_VALUE(parser),
+ .do_keyword_loc = PM_LOCATION_NULL_VALUE(parser),
.closing_loc = PM_LOCATION_NULL_VALUE(parser),
.predicate = predicate,
.statements = statements
@@ -7830,17 +7032,10 @@ pm_while_node_synthesized_create(pm_parser_t *parser, pm_node_t *predicate, pm_s
*/
static pm_x_string_node_t *
pm_xstring_node_create_unescaped(pm_parser_t *parser, const pm_token_t *opening, const pm_token_t *content, const pm_token_t *closing, const pm_string_t *unescaped) {
- pm_x_string_node_t *node = PM_ALLOC_NODE(parser, pm_x_string_node_t);
+ pm_x_string_node_t *node = PM_NODE_ALLOC(parser, pm_x_string_node_t);
*node = (pm_x_string_node_t) {
- {
- .type = PM_X_STRING_NODE,
- .flags = PM_STRING_FLAGS_FROZEN,
- .location = {
- .start = opening->start,
- .end = closing->end
- },
- },
+ .base = PM_NODE_INIT_TOKENS(parser, PM_X_STRING_NODE, PM_STRING_FLAGS_FROZEN, opening, closing),
.opening_loc = PM_LOCATION_TOKEN_VALUE(opening),
.content_loc = PM_LOCATION_TOKEN_VALUE(content),
.closing_loc = PM_LOCATION_TOKEN_VALUE(closing),
@@ -7863,7 +7058,7 @@ pm_xstring_node_create(pm_parser_t *parser, const pm_token_t *opening, const pm_
*/
static pm_yield_node_t *
pm_yield_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_location_t *lparen_loc, pm_arguments_node_t *arguments, const pm_location_t *rparen_loc) {
- pm_yield_node_t *node = PM_ALLOC_NODE(parser, pm_yield_node_t);
+ pm_yield_node_t *node = PM_NODE_ALLOC(parser, pm_yield_node_t);
const uint8_t *end;
if (rparen_loc->start != NULL) {
@@ -7877,13 +7072,7 @@ pm_yield_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_lo
}
*node = (pm_yield_node_t) {
- {
- .type = PM_YIELD_NODE,
- .location = {
- .start = keyword->start,
- .end = end
- },
- },
+ .base = PM_NODE_INIT(parser, PM_YIELD_NODE, 0, keyword->start, end),
.keyword_loc = PM_LOCATION_TOKEN_VALUE(keyword),
.lparen_loc = *lparen_loc,
.arguments = arguments,
@@ -7893,8 +7082,6 @@ pm_yield_node_create(pm_parser_t *parser, const pm_token_t *keyword, const pm_lo
return node;
}
-#undef PM_ALLOC_NODE
-
/**
* Check if any of the currently visible scopes contain a local variable
* described by the given constant id.
@@ -8251,16 +7438,24 @@ parser_lex_magic_comment_encoding(pm_parser_t *parser) {
}
}
+typedef enum {
+ PM_MAGIC_COMMENT_BOOLEAN_VALUE_TRUE,
+ PM_MAGIC_COMMENT_BOOLEAN_VALUE_FALSE,
+ PM_MAGIC_COMMENT_BOOLEAN_VALUE_INVALID
+} pm_magic_comment_boolean_value_t;
+
/**
* Check if this is a magic comment that includes the frozen_string_literal
* pragma. If it does, set that field on the parser.
*/
-static void
-parser_lex_magic_comment_frozen_string_literal_value(pm_parser_t *parser, const uint8_t *start, const uint8_t *end) {
- if ((start + 4 <= end) && pm_strncasecmp(start, (const uint8_t *) "true", 4) == 0) {
- parser->frozen_string_literal = PM_OPTIONS_FROZEN_STRING_LITERAL_ENABLED;
- } else if ((start + 5 <= end) && pm_strncasecmp(start, (const uint8_t *) "false", 5) == 0) {
- parser->frozen_string_literal = PM_OPTIONS_FROZEN_STRING_LITERAL_DISABLED;
+static pm_magic_comment_boolean_value_t
+parser_lex_magic_comment_boolean_value(const uint8_t *value_start, uint32_t value_length) {
+ if (value_length == 4 && pm_strncasecmp(value_start, (const uint8_t *) "true", 4) == 0) {
+ return PM_MAGIC_COMMENT_BOOLEAN_VALUE_TRUE;
+ } else if (value_length == 5 && pm_strncasecmp(value_start, (const uint8_t *) "false", 5) == 0) {
+ return PM_MAGIC_COMMENT_BOOLEAN_VALUE_FALSE;
+ } else {
+ return PM_MAGIC_COMMENT_BOOLEAN_VALUE_INVALID;
}
}
@@ -8349,6 +7544,7 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) {
if (*cursor == '\\' && (cursor + 1 < end)) cursor++;
}
value_end = cursor;
+ if (cursor < end && *cursor == '"') cursor++;
} else {
value_start = cursor;
while (cursor < end && *cursor != '"' && *cursor != ';' && !pm_char_is_whitespace(*cursor)) cursor++;
@@ -8366,32 +7562,32 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) {
// underscores. We only need to do this if there _is_ a dash in the key.
pm_string_t key;
const size_t key_length = (size_t) (key_end - key_start);
- const uint8_t *dash = pm_memchr(key_start, '-', (size_t) key_length, parser->encoding_changed, parser->encoding);
+ const uint8_t *dash = pm_memchr(key_start, '-', key_length, parser->encoding_changed, parser->encoding);
if (dash == NULL) {
pm_string_shared_init(&key, key_start, key_end);
} else {
- size_t width = (size_t) (key_end - key_start);
- uint8_t *buffer = xmalloc(width);
+ uint8_t *buffer = xmalloc(key_length);
if (buffer == NULL) break;
- memcpy(buffer, key_start, width);
+ memcpy(buffer, key_start, key_length);
buffer[dash - key_start] = '_';
while ((dash = pm_memchr(dash + 1, '-', (size_t) (key_end - dash - 1), parser->encoding_changed, parser->encoding)) != NULL) {
buffer[dash - key_start] = '_';
}
- pm_string_owned_init(&key, buffer, width);
+ pm_string_owned_init(&key, buffer, key_length);
}
// Finally, we can start checking the key against the list of known
// magic comment keys, and potentially change state based on that.
const uint8_t *key_source = pm_string_source(&key);
+ uint32_t value_length = (uint32_t) (value_end - value_start);
// We only want to attempt to compare against encoding comments if it's
// the first line in the file (or the second in the case of a shebang).
- if (parser->current.start == parser->encoding_comment_start) {
+ if (parser->current.start == parser->encoding_comment_start && !parser->encoding_locked) {
if (
(key_length == 8 && pm_strncasecmp(key_source, (const uint8_t *) "encoding", 8) == 0) ||
(key_length == 6 && pm_strncasecmp(key_source, (const uint8_t *) "coding", 6) == 0)
@@ -8400,40 +7596,82 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) {
}
}
- // We only want to handle frozen string literal comments if it's before
- // any semantic tokens have been seen.
- if (key_length == 21 && pm_strncasecmp(key_source, (const uint8_t *) "frozen_string_literal", 21) == 0) {
- if (semantic_token_seen) {
- pm_parser_warn_token(parser, &parser->current, PM_WARN_IGNORED_FROZEN_STRING_LITERAL);
- } else {
- parser_lex_magic_comment_frozen_string_literal_value(parser, value_start, value_end);
+ if (key_length == 11) {
+ if (pm_strncasecmp(key_source, (const uint8_t *) "warn_indent", 11) == 0) {
+ switch (parser_lex_magic_comment_boolean_value(value_start, value_length)) {
+ case PM_MAGIC_COMMENT_BOOLEAN_VALUE_INVALID:
+ PM_PARSER_WARN_TOKEN_FORMAT(
+ parser,
+ parser->current,
+ PM_WARN_INVALID_MAGIC_COMMENT_VALUE,
+ (int) key_length,
+ (const char *) key_source,
+ (int) value_length,
+ (const char *) value_start
+ );
+ break;
+ case PM_MAGIC_COMMENT_BOOLEAN_VALUE_FALSE:
+ parser->warn_mismatched_indentation = false;
+ break;
+ case PM_MAGIC_COMMENT_BOOLEAN_VALUE_TRUE:
+ parser->warn_mismatched_indentation = true;
+ break;
+ }
}
- }
-
- // If we have hit a ractor pragma, attempt to lex that.
- uint32_t value_length = (uint32_t) (value_end - value_start);
- if (key_length == 24 && pm_strncasecmp(key_source, (const uint8_t *) "shareable_constant_value", 24) == 0) {
- const uint8_t *cursor = parser->current.start;
- while ((cursor > parser->start) && ((cursor[-1] == ' ') || (cursor[-1] == '\t'))) cursor--;
-
- if (!((cursor == parser->start) || (cursor[-1] == '\n'))) {
- pm_parser_warn_token(parser, &parser->current, PM_WARN_SHAREABLE_CONSTANT_VALUE_LINE);
- } else if (value_length == 4 && pm_strncasecmp(value_start, (const uint8_t *) "none", 4) == 0) {
- pm_parser_scope_shareable_constant_set(parser, PM_SCOPE_SHAREABLE_CONSTANT_NONE);
- } else if (value_length == 7 && pm_strncasecmp(value_start, (const uint8_t *) "literal", 7) == 0) {
- pm_parser_scope_shareable_constant_set(parser, PM_SCOPE_SHAREABLE_CONSTANT_LITERAL);
- } else if (value_length == 23 && pm_strncasecmp(value_start, (const uint8_t *) "experimental_everything", 23) == 0) {
- pm_parser_scope_shareable_constant_set(parser, PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_EVERYTHING);
- } else if (value_length == 17 && pm_strncasecmp(value_start, (const uint8_t *) "experimental_copy", 17) == 0) {
- pm_parser_scope_shareable_constant_set(parser, PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_COPY);
- } else {
- PM_PARSER_WARN_TOKEN_FORMAT(
- parser,
- parser->current,
- PM_WARN_INVALID_SHAREABLE_CONSTANT_VALUE,
- (int) value_length,
- (const char *) value_start
- );
+ } else if (key_length == 21) {
+ if (pm_strncasecmp(key_source, (const uint8_t *) "frozen_string_literal", 21) == 0) {
+ // We only want to handle frozen string literal comments if it's
+ // before any semantic tokens have been seen.
+ if (semantic_token_seen) {
+ pm_parser_warn_token(parser, &parser->current, PM_WARN_IGNORED_FROZEN_STRING_LITERAL);
+ } else {
+ switch (parser_lex_magic_comment_boolean_value(value_start, value_length)) {
+ case PM_MAGIC_COMMENT_BOOLEAN_VALUE_INVALID:
+ PM_PARSER_WARN_TOKEN_FORMAT(
+ parser,
+ parser->current,
+ PM_WARN_INVALID_MAGIC_COMMENT_VALUE,
+ (int) key_length,
+ (const char *) key_source,
+ (int) value_length,
+ (const char *) value_start
+ );
+ break;
+ case PM_MAGIC_COMMENT_BOOLEAN_VALUE_FALSE:
+ parser->frozen_string_literal = PM_OPTIONS_FROZEN_STRING_LITERAL_DISABLED;
+ break;
+ case PM_MAGIC_COMMENT_BOOLEAN_VALUE_TRUE:
+ parser->frozen_string_literal = PM_OPTIONS_FROZEN_STRING_LITERAL_ENABLED;
+ break;
+ }
+ }
+ }
+ } else if (key_length == 24) {
+ if (pm_strncasecmp(key_source, (const uint8_t *) "shareable_constant_value", 24) == 0) {
+ const uint8_t *cursor = parser->current.start;
+ while ((cursor > parser->start) && ((cursor[-1] == ' ') || (cursor[-1] == '\t'))) cursor--;
+
+ if (!((cursor == parser->start) || (cursor[-1] == '\n'))) {
+ pm_parser_warn_token(parser, &parser->current, PM_WARN_SHAREABLE_CONSTANT_VALUE_LINE);
+ } else if (value_length == 4 && pm_strncasecmp(value_start, (const uint8_t *) "none", 4) == 0) {
+ pm_parser_scope_shareable_constant_set(parser, PM_SCOPE_SHAREABLE_CONSTANT_NONE);
+ } else if (value_length == 7 && pm_strncasecmp(value_start, (const uint8_t *) "literal", 7) == 0) {
+ pm_parser_scope_shareable_constant_set(parser, PM_SCOPE_SHAREABLE_CONSTANT_LITERAL);
+ } else if (value_length == 23 && pm_strncasecmp(value_start, (const uint8_t *) "experimental_everything", 23) == 0) {
+ pm_parser_scope_shareable_constant_set(parser, PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_EVERYTHING);
+ } else if (value_length == 17 && pm_strncasecmp(value_start, (const uint8_t *) "experimental_copy", 17) == 0) {
+ pm_parser_scope_shareable_constant_set(parser, PM_SCOPE_SHAREABLE_CONSTANT_EXPERIMENTAL_COPY);
+ } else {
+ PM_PARSER_WARN_TOKEN_FORMAT(
+ parser,
+ parser->current,
+ PM_WARN_INVALID_MAGIC_COMMENT_VALUE,
+ (int) key_length,
+ (const char *) key_source,
+ (int) value_length,
+ (const char *) value_start
+ );
+ }
}
}
@@ -8447,7 +7685,7 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) {
magic_comment->key_start = key_start;
magic_comment->value_start = value_start;
magic_comment->key_length = (uint32_t) key_length;
- magic_comment->value_length = (uint32_t) (value_end - value_start);
+ magic_comment->value_length = value_length;
pm_list_append(&parser->magic_comment_list, (pm_list_node_t *) magic_comment);
}
}
@@ -8459,82 +7697,67 @@ parser_lex_magic_comment(pm_parser_t *parser, bool semantic_token_seen) {
/* Context manipulations */
/******************************************************************************/
-static bool
-context_terminator(pm_context_t context, pm_token_t *token) {
- switch (context) {
- case PM_CONTEXT_MAIN:
- case PM_CONTEXT_DEF_PARAMS:
- case PM_CONTEXT_DEFINED:
- case PM_CONTEXT_TERNARY:
- case PM_CONTEXT_RESCUE_MODIFIER:
- return token->type == PM_TOKEN_EOF;
- case PM_CONTEXT_DEFAULT_PARAMS:
- return token->type == PM_TOKEN_COMMA || token->type == PM_TOKEN_PARENTHESIS_RIGHT;
- case PM_CONTEXT_PREEXE:
- case PM_CONTEXT_POSTEXE:
- return token->type == PM_TOKEN_BRACE_RIGHT;
- case PM_CONTEXT_MODULE:
- case PM_CONTEXT_CLASS:
- case PM_CONTEXT_SCLASS:
- case PM_CONTEXT_LAMBDA_DO_END:
- case PM_CONTEXT_DEF:
- case PM_CONTEXT_BLOCK_KEYWORDS:
- return token->type == PM_TOKEN_KEYWORD_END || token->type == PM_TOKEN_KEYWORD_RESCUE || token->type == PM_TOKEN_KEYWORD_ENSURE;
- case PM_CONTEXT_WHILE:
- case PM_CONTEXT_UNTIL:
- case PM_CONTEXT_ELSE:
- case PM_CONTEXT_FOR:
- case PM_CONTEXT_BEGIN_ENSURE:
- case PM_CONTEXT_BLOCK_ENSURE:
- case PM_CONTEXT_CLASS_ENSURE:
- case PM_CONTEXT_DEF_ENSURE:
- case PM_CONTEXT_LAMBDA_ENSURE:
- case PM_CONTEXT_MODULE_ENSURE:
- case PM_CONTEXT_SCLASS_ENSURE:
- return token->type == PM_TOKEN_KEYWORD_END;
- case PM_CONTEXT_FOR_INDEX:
- return token->type == PM_TOKEN_KEYWORD_IN;
- case PM_CONTEXT_CASE_WHEN:
- return token->type == PM_TOKEN_KEYWORD_WHEN || token->type == PM_TOKEN_KEYWORD_END || token->type == PM_TOKEN_KEYWORD_ELSE;
- case PM_CONTEXT_CASE_IN:
- return token->type == PM_TOKEN_KEYWORD_IN || token->type == PM_TOKEN_KEYWORD_END || token->type == PM_TOKEN_KEYWORD_ELSE;
- case PM_CONTEXT_IF:
- case PM_CONTEXT_ELSIF:
- return token->type == PM_TOKEN_KEYWORD_ELSE || token->type == PM_TOKEN_KEYWORD_ELSIF || token->type == PM_TOKEN_KEYWORD_END;
- case PM_CONTEXT_UNLESS:
- return token->type == PM_TOKEN_KEYWORD_ELSE || token->type == PM_TOKEN_KEYWORD_END;
- case PM_CONTEXT_EMBEXPR:
- return token->type == PM_TOKEN_EMBEXPR_END;
- case PM_CONTEXT_BLOCK_BRACES:
- return token->type == PM_TOKEN_BRACE_RIGHT;
- case PM_CONTEXT_PARENS:
- return token->type == PM_TOKEN_PARENTHESIS_RIGHT;
- case PM_CONTEXT_BEGIN:
- case PM_CONTEXT_BEGIN_RESCUE:
- case PM_CONTEXT_BLOCK_RESCUE:
- case PM_CONTEXT_CLASS_RESCUE:
- case PM_CONTEXT_DEF_RESCUE:
- case PM_CONTEXT_LAMBDA_RESCUE:
- case PM_CONTEXT_MODULE_RESCUE:
- case PM_CONTEXT_SCLASS_RESCUE:
- return token->type == PM_TOKEN_KEYWORD_ENSURE || token->type == PM_TOKEN_KEYWORD_RESCUE || token->type == PM_TOKEN_KEYWORD_ELSE || token->type == PM_TOKEN_KEYWORD_END;
- case PM_CONTEXT_BEGIN_ELSE:
- case PM_CONTEXT_BLOCK_ELSE:
- case PM_CONTEXT_CLASS_ELSE:
- case PM_CONTEXT_DEF_ELSE:
- case PM_CONTEXT_LAMBDA_ELSE:
- case PM_CONTEXT_MODULE_ELSE:
- case PM_CONTEXT_SCLASS_ELSE:
- return token->type == PM_TOKEN_KEYWORD_ENSURE || token->type == PM_TOKEN_KEYWORD_END;
- case PM_CONTEXT_LAMBDA_BRACES:
- return token->type == PM_TOKEN_BRACE_RIGHT;
- case PM_CONTEXT_PREDICATE:
- return token->type == PM_TOKEN_KEYWORD_THEN || token->type == PM_TOKEN_NEWLINE || token->type == PM_TOKEN_SEMICOLON;
- case PM_CONTEXT_NONE:
- return false;
- }
+static const uint32_t context_terminators[] = {
+ [PM_CONTEXT_NONE] = 0,
+ [PM_CONTEXT_BEGIN] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_BEGIN_ENSURE] = (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_BEGIN_ELSE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_BEGIN_RESCUE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_BLOCK_BRACES] = (1U << PM_TOKEN_BRACE_RIGHT),
+ [PM_CONTEXT_BLOCK_KEYWORDS] = (1U << PM_TOKEN_KEYWORD_END) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ENSURE),
+ [PM_CONTEXT_BLOCK_ENSURE] = (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_BLOCK_ELSE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_BLOCK_PARAMETERS] = (1U << PM_TOKEN_PIPE),
+ [PM_CONTEXT_BLOCK_RESCUE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_CASE_WHEN] = (1U << PM_TOKEN_KEYWORD_WHEN) | (1U << PM_TOKEN_KEYWORD_END) | (1U << PM_TOKEN_KEYWORD_ELSE),
+ [PM_CONTEXT_CASE_IN] = (1U << PM_TOKEN_KEYWORD_IN) | (1U << PM_TOKEN_KEYWORD_END) | (1U << PM_TOKEN_KEYWORD_ELSE),
+ [PM_CONTEXT_CLASS] = (1U << PM_TOKEN_KEYWORD_END) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ENSURE),
+ [PM_CONTEXT_CLASS_ENSURE] = (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_CLASS_ELSE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_CLASS_RESCUE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_DEF] = (1U << PM_TOKEN_KEYWORD_END) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ENSURE),
+ [PM_CONTEXT_DEF_ENSURE] = (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_DEF_ELSE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_DEF_RESCUE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_DEF_PARAMS] = (1U << PM_TOKEN_EOF),
+ [PM_CONTEXT_DEFINED] = (1U << PM_TOKEN_EOF),
+ [PM_CONTEXT_DEFAULT_PARAMS] = (1U << PM_TOKEN_COMMA) | (1U << PM_TOKEN_PARENTHESIS_RIGHT),
+ [PM_CONTEXT_ELSE] = (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_ELSIF] = (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_ELSIF) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_EMBEXPR] = (1U << PM_TOKEN_EMBEXPR_END),
+ [PM_CONTEXT_FOR] = (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_FOR_INDEX] = (1U << PM_TOKEN_KEYWORD_IN),
+ [PM_CONTEXT_IF] = (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_ELSIF) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_LAMBDA_BRACES] = (1U << PM_TOKEN_BRACE_RIGHT),
+ [PM_CONTEXT_LAMBDA_DO_END] = (1U << PM_TOKEN_KEYWORD_END) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ENSURE),
+ [PM_CONTEXT_LAMBDA_ENSURE] = (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_LAMBDA_ELSE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_LAMBDA_RESCUE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_LOOP_PREDICATE] = (1U << PM_TOKEN_KEYWORD_DO) | (1U << PM_TOKEN_KEYWORD_THEN),
+ [PM_CONTEXT_MAIN] = (1U << PM_TOKEN_EOF),
+ [PM_CONTEXT_MODULE] = (1U << PM_TOKEN_KEYWORD_END) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ENSURE),
+ [PM_CONTEXT_MODULE_ENSURE] = (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_MODULE_ELSE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_MODULE_RESCUE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_MULTI_TARGET] = (1U << PM_TOKEN_EOF),
+ [PM_CONTEXT_PARENS] = (1U << PM_TOKEN_PARENTHESIS_RIGHT),
+ [PM_CONTEXT_POSTEXE] = (1U << PM_TOKEN_BRACE_RIGHT),
+ [PM_CONTEXT_PREDICATE] = (1U << PM_TOKEN_KEYWORD_THEN) | (1U << PM_TOKEN_NEWLINE) | (1U << PM_TOKEN_SEMICOLON),
+ [PM_CONTEXT_PREEXE] = (1U << PM_TOKEN_BRACE_RIGHT),
+ [PM_CONTEXT_RESCUE_MODIFIER] = (1U << PM_TOKEN_EOF),
+ [PM_CONTEXT_SCLASS] = (1U << PM_TOKEN_KEYWORD_END) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ENSURE),
+ [PM_CONTEXT_SCLASS_ENSURE] = (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_SCLASS_ELSE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_SCLASS_RESCUE] = (1U << PM_TOKEN_KEYWORD_ENSURE) | (1U << PM_TOKEN_KEYWORD_RESCUE) | (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_TERNARY] = (1U << PM_TOKEN_EOF),
+ [PM_CONTEXT_UNLESS] = (1U << PM_TOKEN_KEYWORD_ELSE) | (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_UNTIL] = (1U << PM_TOKEN_KEYWORD_END),
+ [PM_CONTEXT_WHILE] = (1U << PM_TOKEN_KEYWORD_END),
+};
- return false;
+static inline bool
+context_terminator(pm_context_t context, pm_token_t *token) {
+ return token->type < 32 && (context_terminators[context] & (1U << token->type));
}
/**
@@ -8635,6 +7858,7 @@ context_human(pm_context_t context) {
case PM_CONTEXT_BEGIN: return "begin statement";
case PM_CONTEXT_BLOCK_BRACES: return "'{'..'}' block";
case PM_CONTEXT_BLOCK_KEYWORDS: return "'do'..'end' block";
+ case PM_CONTEXT_BLOCK_PARAMETERS: return "'|'..'|' block parameter";
case PM_CONTEXT_CASE_WHEN: return "'when' clause";
case PM_CONTEXT_CASE_IN: return "'in' clause";
case PM_CONTEXT_CLASS: return "class definition";
@@ -8664,8 +7888,10 @@ context_human(pm_context_t context) {
case PM_CONTEXT_IF: return "if statement";
case PM_CONTEXT_LAMBDA_BRACES: return "'{'..'}' lambda block";
case PM_CONTEXT_LAMBDA_DO_END: return "'do'..'end' lambda block";
+ case PM_CONTEXT_LOOP_PREDICATE: return "loop predicate";
case PM_CONTEXT_MAIN: return "top level context";
case PM_CONTEXT_MODULE: return "module definition";
+ case PM_CONTEXT_MULTI_TARGET: return "multiple targets";
case PM_CONTEXT_PARENS: return "parentheses";
case PM_CONTEXT_POSTEXE: return "'END' block";
case PM_CONTEXT_PREDICATE: return "predicate";
@@ -8940,6 +8166,10 @@ lex_global_variable(pm_parser_t *parser) {
return PM_TOKEN_GLOBAL_VARIABLE;
}
+ // True if multiple characters are allowed after the declaration of the
+ // global variable. Not true when it starts with "$-".
+ bool allow_multiple = true;
+
switch (*parser->current.end) {
case '~': // $~: match-data
case '*': // $*: argv
@@ -8971,13 +8201,13 @@ lex_global_variable(pm_parser_t *parser) {
parser->current.end++;
size_t width;
- if (parser->current.end < parser->end && (width = char_is_identifier(parser, parser->current.end)) > 0) {
+ if ((width = char_is_identifier(parser, parser->current.end, parser->end - parser->current.end)) > 0) {
do {
parser->current.end += width;
- } while (parser->current.end < parser->end && (width = char_is_identifier(parser, parser->current.end)) > 0);
+ } while ((width = char_is_identifier(parser, parser->current.end, parser->end - parser->current.end)) > 0);
// $0 isn't allowed to be followed by anything.
- pm_diagnostic_id_t diag_id = parser->version == PM_OPTIONS_VERSION_CRUBY_3_3 ? PM_ERR_INVALID_VARIABLE_GLOBAL_3_3 : PM_ERR_INVALID_VARIABLE_GLOBAL;
+ pm_diagnostic_id_t diag_id = parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3 ? PM_ERR_INVALID_VARIABLE_GLOBAL_3_3 : PM_ERR_INVALID_VARIABLE_GLOBAL;
PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, parser->current, diag_id);
}
@@ -8998,14 +8228,15 @@ lex_global_variable(pm_parser_t *parser) {
case '-':
parser->current.end++;
- /* fallthrough */
+ allow_multiple = false;
+ PRISM_FALLTHROUGH
default: {
size_t width;
- if ((width = char_is_identifier(parser, parser->current.end)) > 0) {
+ if ((width = char_is_identifier(parser, parser->current.end, parser->end - parser->current.end)) > 0) {
do {
parser->current.end += width;
- } while (parser->current.end < parser->end && (width = char_is_identifier(parser, parser->current.end)) > 0);
+ } while (allow_multiple && (width = char_is_identifier(parser, parser->current.end, parser->end - parser->current.end)) > 0);
} else if (pm_char_is_whitespace(peek(parser))) {
// If we get here, then we have a $ followed by whitespace,
// which is not allowed.
@@ -9013,7 +8244,7 @@ lex_global_variable(pm_parser_t *parser) {
} else {
// If we get here, then we have a $ followed by something that
// isn't recognized as a global variable.
- pm_diagnostic_id_t diag_id = parser->version == PM_OPTIONS_VERSION_CRUBY_3_3 ? PM_ERR_INVALID_VARIABLE_GLOBAL_3_3 : PM_ERR_INVALID_VARIABLE_GLOBAL;
+ pm_diagnostic_id_t diag_id = parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3 ? PM_ERR_INVALID_VARIABLE_GLOBAL_3_3 : PM_ERR_INVALID_VARIABLE_GLOBAL;
const uint8_t *end = parser->current.end + parser->encoding->char_width(parser->current.end, parser->end - parser->current.end);
PM_PARSER_ERR_FORMAT(parser, parser->current.start, end, diag_id, (int) (end - parser->current.start), (const char *) parser->current.start);
}
@@ -9070,11 +8301,11 @@ lex_identifier(pm_parser_t *parser, bool previous_command_start) {
bool encoding_changed = parser->encoding_changed;
if (encoding_changed) {
- while (current_end < end && (width = char_is_identifier(parser, current_end)) > 0) {
+ while ((width = char_is_identifier(parser, current_end, end - current_end)) > 0) {
current_end += width;
}
} else {
- while (current_end < end && (width = char_is_identifier_utf8(current_end, end)) > 0) {
+ while ((width = char_is_identifier_utf8(current_end, end - current_end)) > 0) {
current_end += width;
}
}
@@ -9248,7 +8479,7 @@ lex_interpolation(pm_parser_t *parser, const uint8_t *pound) {
const uint8_t *variable = pound + 2;
if (*variable == '@' && pound + 3 < parser->end) variable++;
- if (char_is_identifier_start(parser, variable)) {
+ if (char_is_identifier_start(parser, variable, parser->end - variable)) {
// At this point we're sure that we've either hit an embedded instance
// or class variable. In this case we'll first need to check if we've
// already consumed content.
@@ -9297,7 +8528,7 @@ lex_interpolation(pm_parser_t *parser, const uint8_t *pound) {
// or a global name punctuation character, then we've hit an embedded
// global variable.
if (
- char_is_identifier_start(parser, check) ||
+ char_is_identifier_start(parser, check, parser->end - check) ||
(pound[2] != '-' && (pm_char_is_decimal_digit(pound[2]) || char_is_global_name_punctuation(pound[2])))
) {
// In this case we've hit an embedded global variable. First check to
@@ -9386,7 +8617,7 @@ escape_hexadecimal_digit(const uint8_t value) {
* validated.
*/
static inline uint32_t
-escape_unicode(pm_parser_t *parser, const uint8_t *string, size_t length) {
+escape_unicode(pm_parser_t *parser, const uint8_t *string, size_t length, const pm_location_t *error_location) {
uint32_t value = 0;
for (size_t index = 0; index < length; index++) {
if (index != 0) value <<= 4;
@@ -9396,7 +8627,11 @@ escape_unicode(pm_parser_t *parser, const uint8_t *string, size_t length) {
// Here we're going to verify that the value is actually a valid Unicode
// codepoint and not a surrogate pair.
if (value >= 0xD800 && value <= 0xDFFF) {
- pm_parser_err(parser, string, string + length, PM_ERR_ESCAPE_INVALID_UNICODE);
+ if (error_location != NULL) {
+ pm_parser_err(parser, error_location->start, error_location->end, PM_ERR_ESCAPE_INVALID_UNICODE);
+ } else {
+ pm_parser_err(parser, string, string + length, PM_ERR_ESCAPE_INVALID_UNICODE);
+ }
return 0xFFFD;
}
@@ -9429,21 +8664,7 @@ escape_write_unicode(pm_parser_t *parser, pm_buffer_t *buffer, const uint8_t fla
parser->explicit_encoding = PM_ENCODING_UTF_8_ENTRY;
}
- if (value <= 0x7F) { // 0xxxxxxx
- pm_buffer_append_byte(buffer, (uint8_t) value);
- } else if (value <= 0x7FF) { // 110xxxxx 10xxxxxx
- pm_buffer_append_byte(buffer, (uint8_t) (0xC0 | (value >> 6)));
- pm_buffer_append_byte(buffer, (uint8_t) (0x80 | (value & 0x3F)));
- } else if (value <= 0xFFFF) { // 1110xxxx 10xxxxxx 10xxxxxx
- pm_buffer_append_byte(buffer, (uint8_t) (0xE0 | (value >> 12)));
- pm_buffer_append_byte(buffer, (uint8_t) (0x80 | ((value >> 6) & 0x3F)));
- pm_buffer_append_byte(buffer, (uint8_t) (0x80 | (value & 0x3F)));
- } else if (value <= 0x10FFFF) { // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
- pm_buffer_append_byte(buffer, (uint8_t) (0xF0 | (value >> 18)));
- pm_buffer_append_byte(buffer, (uint8_t) (0x80 | ((value >> 12) & 0x3F)));
- pm_buffer_append_byte(buffer, (uint8_t) (0x80 | ((value >> 6) & 0x3F)));
- pm_buffer_append_byte(buffer, (uint8_t) (0x80 | (value & 0x3F)));
- } else {
+ if (!pm_buffer_append_unicode_codepoint(buffer, value)) {
pm_parser_err(parser, start, end, PM_ERR_ESCAPE_INVALID_UNICODE);
pm_buffer_append_byte(buffer, 0xEF);
pm_buffer_append_byte(buffer, 0xBF);
@@ -9469,28 +8690,6 @@ escape_write_byte_encoded(pm_parser_t *parser, pm_buffer_t *buffer, uint8_t byte
}
/**
- * Write each byte of the given escaped character into the buffer.
- */
-static inline void
-escape_write_escape_encoded(pm_parser_t *parser, pm_buffer_t *buffer) {
- size_t width;
- if (parser->encoding_changed) {
- width = parser->encoding->char_width(parser->current.end, parser->end - parser->current.end);
- } else {
- width = pm_encoding_utf_8_char_width(parser->current.end, parser->end - parser->current.end);
- }
-
- // TODO: If the character is invalid in the given encoding, then we'll just
- // push one byte into the buffer. This should actually be an error.
- width = (width == 0) ? 1 : width;
-
- for (size_t index = 0; index < width; index++) {
- escape_write_byte_encoded(parser, buffer, *parser->current.end);
- parser->current.end++;
- }
-}
-
-/**
* The regular expression engine doesn't support the same escape sequences as
* Ruby does. So first we have to read the escape sequence, and then we have to
* format it like the regular expression engine expects it. For example, in Ruby
@@ -9515,6 +8714,33 @@ escape_write_byte(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular
}
/**
+ * Write each byte of the given escaped character into the buffer.
+ */
+static inline void
+escape_write_escape_encoded(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expression_buffer, uint8_t flags) {
+ size_t width;
+ if (parser->encoding_changed) {
+ width = parser->encoding->char_width(parser->current.end, parser->end - parser->current.end);
+ } else {
+ width = pm_encoding_utf_8_char_width(parser->current.end, parser->end - parser->current.end);
+ }
+
+ if (width == 1) {
+ escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte(*parser->current.end++, flags));
+ } else if (width > 1) {
+ // Valid multibyte character. Just ignore escape.
+ pm_buffer_t *b = (flags & PM_ESCAPE_FLAG_REGEXP) ? regular_expression_buffer : buffer;
+ pm_buffer_append_bytes(b, parser->current.end, width);
+ parser->current.end += width;
+ } else {
+ // Assume the next character wasn't meant to be part of this escape
+ // sequence since it is invalid. Add an error and move on.
+ parser->current.end++;
+ pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_CONTROL);
+ }
+}
+
+/**
* Warn about using a space or a tab character in an escape, as opposed to using
* \\s or \\t. Note that we can quite copy the source because the warning
* message replaces \\c with \\C.
@@ -9540,7 +8766,8 @@ escape_read_warn(pm_parser_t *parser, uint8_t flags, uint8_t flag, const char *t
*/
static void
escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expression_buffer, uint8_t flags) {
- switch (peek(parser)) {
+ uint8_t peeked = peek(parser);
+ switch (peeked) {
case '\\': {
parser->current.end++;
escape_write_byte(parser, buffer, regular_expression_buffer, flags, escape_byte('\\', flags));
@@ -9610,6 +8837,7 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre
}
}
+ value = escape_byte(value, flags);
escape_write_byte(parser, buffer, regular_expression_buffer, flags, value);
return;
}
@@ -9649,11 +8877,27 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre
const uint8_t *start = parser->current.end - 1;
parser->current.end++;
- if (peek(parser) == '{') {
+ if (parser->current.end == parser->end) {
+ const uint8_t *start = parser->current.end - 2;
+ PM_PARSER_ERR_FORMAT(parser, start, parser->current.end, PM_ERR_ESCAPE_INVALID_UNICODE_SHORT, 2, start);
+ } else if (peek(parser) == '{') {
const uint8_t *unicode_codepoints_start = parser->current.end - 2;
-
parser->current.end++;
- parser->current.end += pm_strspn_whitespace(parser->current.end, parser->end - parser->current.end);
+
+ size_t whitespace;
+ while (true) {
+ if ((whitespace = pm_strspn_inline_whitespace(parser->current.end, parser->end - parser->current.end)) > 0) {
+ parser->current.end += whitespace;
+ } else if (peek(parser) == '\\' && peek_offset(parser, 1) == 'n') {
+ // This is super hacky, but it gets us nicer error
+ // messages because we can still pass it off to the
+ // regular expression engine even if we hit an
+ // unterminated regular expression.
+ parser->current.end += 2;
+ } else {
+ break;
+ }
+ }
const uint8_t *extra_codepoints_start = NULL;
int codepoints_count = 0;
@@ -9667,8 +8911,17 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre
pm_parser_err(parser, unicode_start, unicode_start + hexadecimal_length, PM_ERR_ESCAPE_INVALID_UNICODE_LONG);
} else if (hexadecimal_length == 0) {
// there are not hexadecimal characters
- pm_parser_err(parser, parser->current.end, parser->current.end, PM_ERR_ESCAPE_INVALID_UNICODE);
- pm_parser_err(parser, parser->current.end, parser->current.end, PM_ERR_ESCAPE_INVALID_UNICODE_TERM);
+
+ if (flags & PM_ESCAPE_FLAG_REGEXP) {
+ // If this is a regular expression, we are going to
+ // let the regular expression engine handle this
+ // error instead of us.
+ pm_buffer_append_bytes(regular_expression_buffer, start, (size_t) (parser->current.end - start));
+ } else {
+ pm_parser_err(parser, parser->current.end, parser->current.end, PM_ERR_ESCAPE_INVALID_UNICODE);
+ pm_parser_err(parser, parser->current.end, parser->current.end, PM_ERR_ESCAPE_INVALID_UNICODE_TERM);
+ }
+
return;
}
@@ -9678,10 +8931,10 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre
extra_codepoints_start = unicode_start;
}
- uint32_t value = escape_unicode(parser, unicode_start, hexadecimal_length);
+ uint32_t value = escape_unicode(parser, unicode_start, hexadecimal_length, NULL);
escape_write_unicode(parser, buffer, flags, unicode_start, parser->current.end, value);
- parser->current.end += pm_strspn_whitespace(parser->current.end, parser->end - parser->current.end);
+ parser->current.end += pm_strspn_inline_whitespace(parser->current.end, parser->end - parser->current.end);
}
// ?\u{nnnn} character literal should contain only one codepoint
@@ -9690,10 +8943,19 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre
pm_parser_err(parser, extra_codepoints_start, parser->current.end - 1, PM_ERR_ESCAPE_INVALID_UNICODE_LITERAL);
}
- if (peek(parser) == '}') {
+ if (parser->current.end == parser->end) {
+ PM_PARSER_ERR_FORMAT(parser, start, parser->current.end, PM_ERR_ESCAPE_INVALID_UNICODE_LIST, (int) (parser->current.end - start), start);
+ } else if (peek(parser) == '}') {
parser->current.end++;
} else {
- pm_parser_err(parser, unicode_codepoints_start, parser->current.end, PM_ERR_ESCAPE_INVALID_UNICODE_TERM);
+ if (flags & PM_ESCAPE_FLAG_REGEXP) {
+ // If this is a regular expression, we are going to let
+ // the regular expression engine handle this error
+ // instead of us.
+ pm_buffer_append_bytes(regular_expression_buffer, start, (size_t) (parser->current.end - start));
+ } else {
+ pm_parser_err(parser, unicode_codepoints_start, parser->current.end, PM_ERR_ESCAPE_INVALID_UNICODE_TERM);
+ }
}
if (flags & PM_ESCAPE_FLAG_REGEXP) {
@@ -9702,8 +8964,15 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre
} else {
size_t length = pm_strspn_hexadecimal_digit(parser->current.end, MIN(parser->end - parser->current.end, 4));
- if (length == 4) {
- uint32_t value = escape_unicode(parser, parser->current.end, 4);
+ if (length == 0) {
+ if (flags & PM_ESCAPE_FLAG_REGEXP) {
+ pm_buffer_append_bytes(regular_expression_buffer, start, (size_t) (parser->current.end - start));
+ } else {
+ const uint8_t *start = parser->current.end - 2;
+ PM_PARSER_ERR_FORMAT(parser, start, parser->current.end, PM_ERR_ESCAPE_INVALID_UNICODE_SHORT, 2, start);
+ }
+ } else if (length == 4) {
+ uint32_t value = escape_unicode(parser, parser->current.end, 4, NULL);
if (flags & PM_ESCAPE_FLAG_REGEXP) {
pm_buffer_append_bytes(regular_expression_buffer, start, (size_t) (parser->current.end + 4 - start));
@@ -9713,7 +8982,15 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre
parser->current.end += 4;
} else {
parser->current.end += length;
- pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_UNICODE);
+
+ if (flags & PM_ESCAPE_FLAG_REGEXP) {
+ // If this is a regular expression, we are going to let
+ // the regular expression engine handle this error
+ // instead of us.
+ pm_buffer_append_bytes(regular_expression_buffer, start, (size_t) (parser->current.end - start));
+ } else {
+ pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_UNICODE);
+ }
}
}
@@ -9721,6 +8998,10 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre
}
case 'c': {
parser->current.end++;
+ if (flags & PM_ESCAPE_FLAG_CONTROL) {
+ pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_CONTROL_REPEAT);
+ }
+
if (parser->current.end == parser->end) {
pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_CONTROL);
return;
@@ -9734,10 +9015,6 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre
return;
}
case '\\':
- if (flags & PM_ESCAPE_FLAG_CONTROL) {
- pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_CONTROL_REPEAT);
- return;
- }
parser->current.end++;
if (match(parser, 'u') || match(parser, 'U')) {
@@ -9771,6 +9048,10 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre
}
case 'C': {
parser->current.end++;
+ if (flags & PM_ESCAPE_FLAG_CONTROL) {
+ pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_CONTROL_REPEAT);
+ }
+
if (peek(parser) != '-') {
size_t width = parser->encoding->char_width(parser->current.end, parser->end - parser->current.end);
pm_parser_err(parser, parser->current.start, parser->current.end + width, PM_ERR_ESCAPE_INVALID_CONTROL);
@@ -9791,10 +9072,6 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre
return;
}
case '\\':
- if (flags & PM_ESCAPE_FLAG_CONTROL) {
- pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_CONTROL_REPEAT);
- return;
- }
parser->current.end++;
if (match(parser, 'u') || match(parser, 'U')) {
@@ -9829,6 +9106,10 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre
}
case 'M': {
parser->current.end++;
+ if (flags & PM_ESCAPE_FLAG_META) {
+ pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_META_REPEAT);
+ }
+
if (peek(parser) != '-') {
size_t width = parser->encoding->char_width(parser->current.end, parser->end - parser->current.end);
pm_parser_err(parser, parser->current.start, parser->current.end + width, PM_ERR_ESCAPE_INVALID_META);
@@ -9844,10 +9125,6 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre
uint8_t peeked = peek(parser);
switch (peeked) {
case '\\':
- if (flags & PM_ESCAPE_FLAG_META) {
- pm_parser_err_current(parser, PM_ERR_ESCAPE_INVALID_META_REPEAT);
- return;
- }
parser->current.end++;
if (match(parser, 'u') || match(parser, 'U')) {
@@ -9885,11 +9162,18 @@ escape_read(pm_parser_t *parser, pm_buffer_t *buffer, pm_buffer_t *regular_expre
escape_write_byte_encoded(parser, buffer, escape_byte('\n', flags));
return;
}
+ PRISM_FALLTHROUGH
}
- /* fallthrough */
default: {
+ if ((flags & (PM_ESCAPE_FLAG_CONTROL | PM_ESCAPE_FLAG_META)) && !char_is_ascii_printable(peeked)) {
+ size_t width = parser->encoding->char_width(parser->current.end, parser->end - parser->current.end);
+ pm_parser_err(parser, parser->current.start, parser->current.end + width, PM_ERR_ESCAPE_INVALID_META);
+ return;
+ }
if (parser->current.end < parser->end) {
- escape_write_escape_encoded(parser, buffer);
+ escape_write_escape_encoded(parser, buffer, regular_expression_buffer, flags);
+ } else {
+ pm_parser_err_current(parser, PM_ERR_INVALID_ESCAPE_CHARACTER);
}
return;
}
@@ -9960,7 +9244,7 @@ lex_question_mark(pm_parser_t *parser) {
!(parser->encoding->alnum_char(parser->current.end, parser->end - parser->current.end) || peek(parser) == '_') ||
(
(parser->current.end + encoding_width >= parser->end) ||
- !char_is_identifier(parser, parser->current.end + encoding_width)
+ !char_is_identifier(parser, parser->current.end + encoding_width, parser->end - (parser->current.end + encoding_width))
)
) {
lex_state_set(parser, PM_LEX_STATE_END);
@@ -9980,21 +9264,22 @@ lex_question_mark(pm_parser_t *parser) {
static pm_token_type_t
lex_at_variable(pm_parser_t *parser) {
pm_token_type_t type = match(parser, '@') ? PM_TOKEN_CLASS_VARIABLE : PM_TOKEN_INSTANCE_VARIABLE;
- size_t width;
+ const uint8_t *end = parser->end;
- if (parser->current.end < parser->end && (width = char_is_identifier_start(parser, parser->current.end)) > 0) {
+ size_t width;
+ if ((width = char_is_identifier_start(parser, parser->current.end, end - parser->current.end)) > 0) {
parser->current.end += width;
- while (parser->current.end < parser->end && (width = char_is_identifier(parser, parser->current.end)) > 0) {
+ while ((width = char_is_identifier(parser, parser->current.end, end - parser->current.end)) > 0) {
parser->current.end += width;
}
- } else if (parser->current.end < parser->end && pm_char_is_decimal_digit(*parser->current.end)) {
+ } else if (parser->current.end < end && pm_char_is_decimal_digit(*parser->current.end)) {
pm_diagnostic_id_t diag_id = (type == PM_TOKEN_CLASS_VARIABLE) ? PM_ERR_INCOMPLETE_VARIABLE_CLASS : PM_ERR_INCOMPLETE_VARIABLE_INSTANCE;
- if (parser->version == PM_OPTIONS_VERSION_CRUBY_3_3) {
+ if (parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3) {
diag_id = (type == PM_TOKEN_CLASS_VARIABLE) ? PM_ERR_INCOMPLETE_VARIABLE_CLASS_3_3 : PM_ERR_INCOMPLETE_VARIABLE_INSTANCE_3_3;
}
- size_t width = parser->encoding->char_width(parser->current.end, parser->end - parser->current.end);
+ size_t width = parser->encoding->char_width(parser->current.end, end - parser->current.end);
PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, diag_id, (int) ((parser->current.end + width) - parser->current.start), (const char *) parser->current.start);
} else {
pm_diagnostic_id_t diag_id = (type == PM_TOKEN_CLASS_VARIABLE) ? PM_ERR_CLASS_VARIABLE_BARE : PM_ERR_INSTANCE_VARIABLE_BARE;
@@ -10338,6 +9623,7 @@ pm_token_buffer_escape(pm_parser_t *parser, pm_token_buffer_t *token_buffer) {
}
const uint8_t *end = parser->current.end - 1;
+ assert(end >= start);
pm_buffer_append_bytes(&token_buffer->buffer, start, (size_t) (end - start));
token_buffer->cursor = end;
@@ -10418,9 +9704,15 @@ pm_lex_percent_delimiter(pm_parser_t *parser) {
pm_newline_list_append(&parser->newline_list, parser->current.end + eol_length - 1);
}
- const uint8_t delimiter = *parser->current.end;
- parser->current.end += eol_length;
+ uint8_t delimiter = *parser->current.end;
+
+ // If our delimiter is \r\n, we want to treat it as if it's \n.
+ // For example, %\r\nfoo\r\n should be "foo"
+ if (eol_length == 2) {
+ delimiter = *(parser->current.end + 1);
+ }
+ parser->current.end += eol_length;
return delimiter;
}
@@ -10530,6 +9822,14 @@ parser_lex(pm_parser_t *parser) {
// We'll check if we're at the end of the file. If we are, then we
// need to return the EOF token.
if (parser->current.end >= parser->end) {
+ // If we hit EOF, but the EOF came immediately after a newline,
+ // set the start of the token to the newline. This way any EOF
+ // errors will be reported as happening on that line rather than
+ // a line after. For example "foo(\n" should report an error
+ // on line 1 even though EOF technically occurs on line 2.
+ if (parser->current.start > parser->start && (*(parser->current.start - 1) == '\n')) {
+ parser->current.start -= 1;
+ }
LEX(PM_TOKEN_EOF);
}
@@ -10565,12 +9865,14 @@ parser_lex(pm_parser_t *parser) {
// pass and we're at the start of the file, then we need
// to do another pass to potentially find other patterns
// for encoding comments.
- if (length >= 10) parser_lex_magic_comment_encoding(parser);
+ if (length >= 10 && !parser->encoding_locked) {
+ parser_lex_magic_comment_encoding(parser);
+ }
}
lexed_comment = true;
}
- /* fallthrough */
+ PRISM_FALLTHROUGH
case '\r':
case '\n': {
parser->semantic_token_seen = semantic_token_seen & 0x1;
@@ -10612,7 +9914,7 @@ parser_lex(pm_parser_t *parser) {
parser->current.type = PM_TOKEN_NEWLINE;
return;
}
- /* fallthrough */
+ PRISM_FALLTHROUGH
case PM_IGNORED_NEWLINE_ALL:
if (!lexed_comment) parser_lex_ignored_newline(parser);
lexed_comment = false;
@@ -10649,14 +9951,37 @@ parser_lex(pm_parser_t *parser) {
following = next_newline(following, parser->end - following);
}
- // If the lex state was ignored, or we hit a '.' or a '&.',
- // we will lex the ignored newline
+ // If the lex state was ignored, we will lex the
+ // ignored newline.
+ if (lex_state_ignored_p(parser)) {
+ if (!lexed_comment) parser_lex_ignored_newline(parser);
+ lexed_comment = false;
+ goto lex_next_token;
+ }
+
+ // If we hit a '.' or a '&.' we will lex the ignored
+ // newline.
+ if (following && (
+ (peek_at(parser, following) == '.') ||
+ (peek_at(parser, following) == '&' && peek_at(parser, following + 1) == '.')
+ )) {
+ if (!lexed_comment) parser_lex_ignored_newline(parser);
+ lexed_comment = false;
+ goto lex_next_token;
+ }
+
+
+ // If we are parsing as CRuby 4.0 or later and we
+ // hit a '&&' or a '||' then we will lex the ignored
+ // newline.
if (
- lex_state_ignored_p(parser) ||
- (following && (
- (peek_at(parser, following) == '.') ||
- (peek_at(parser, following) == '&' && peek_at(parser, following + 1) == '.')
- ))
+ (parser->version >= PM_OPTIONS_VERSION_CRUBY_4_0) &&
+ following && (
+ (peek_at(parser, following) == '&' && peek_at(parser, following + 1) == '&') ||
+ (peek_at(parser, following) == '|' && peek_at(parser, following + 1) == '|') ||
+ (peek_at(parser, following) == 'a' && peek_at(parser, following + 1) == 'n' && peek_at(parser, following + 2) == 'd' && !char_is_identifier(parser, following + 3, parser->end - (following + 3))) ||
+ (peek_at(parser, following) == 'o' && peek_at(parser, following + 1) == 'r' && !char_is_identifier(parser, following + 2, parser->end - (following + 2)))
+ )
) {
if (!lexed_comment) parser_lex_ignored_newline(parser);
lexed_comment = false;
@@ -10696,6 +10021,63 @@ parser_lex(pm_parser_t *parser) {
parser->next_start = NULL;
LEX(PM_TOKEN_AMPERSAND_DOT);
}
+
+ if (parser->version >= PM_OPTIONS_VERSION_CRUBY_4_0) {
+ // If we hit an && then we are in a logical chain
+ // and we need to return the logical operator.
+ if (peek_at(parser, next_content) == '&' && peek_at(parser, next_content + 1) == '&') {
+ if (!lexed_comment) parser_lex_ignored_newline(parser);
+ lex_state_set(parser, PM_LEX_STATE_BEG);
+ parser->current.start = next_content;
+ parser->current.end = next_content + 2;
+ parser->next_start = NULL;
+ LEX(PM_TOKEN_AMPERSAND_AMPERSAND);
+ }
+
+ // If we hit a || then we are in a logical chain and
+ // we need to return the logical operator.
+ if (peek_at(parser, next_content) == '|' && peek_at(parser, next_content + 1) == '|') {
+ if (!lexed_comment) parser_lex_ignored_newline(parser);
+ lex_state_set(parser, PM_LEX_STATE_BEG);
+ parser->current.start = next_content;
+ parser->current.end = next_content + 2;
+ parser->next_start = NULL;
+ LEX(PM_TOKEN_PIPE_PIPE);
+ }
+
+ // If we hit an 'and' then we are in a logical chain
+ // and we need to return the logical operator.
+ if (
+ peek_at(parser, next_content) == 'a' &&
+ peek_at(parser, next_content + 1) == 'n' &&
+ peek_at(parser, next_content + 2) == 'd' &&
+ !char_is_identifier(parser, next_content + 3, parser->end - (next_content + 3))
+ ) {
+ if (!lexed_comment) parser_lex_ignored_newline(parser);
+ lex_state_set(parser, PM_LEX_STATE_BEG);
+ parser->current.start = next_content;
+ parser->current.end = next_content + 3;
+ parser->next_start = NULL;
+ parser->command_start = true;
+ LEX(PM_TOKEN_KEYWORD_AND);
+ }
+
+ // If we hit a 'or' then we are in a logical chain
+ // and we need to return the logical operator.
+ if (
+ peek_at(parser, next_content) == 'o' &&
+ peek_at(parser, next_content + 1) == 'r' &&
+ !char_is_identifier(parser, next_content + 2, parser->end - (next_content + 2))
+ ) {
+ if (!lexed_comment) parser_lex_ignored_newline(parser);
+ lex_state_set(parser, PM_LEX_STATE_BEG);
+ parser->current.start = next_content;
+ parser->current.end = next_content + 2;
+ parser->next_start = NULL;
+ parser->command_start = true;
+ LEX(PM_TOKEN_KEYWORD_OR);
+ }
+ }
}
// At this point we know this is a regular newline, and we can set the
@@ -10709,6 +10091,10 @@ parser_lex(pm_parser_t *parser) {
// ,
case ',':
+ if ((parser->previous.type == PM_TOKEN_COMMA) && (parser->enclosure_nesting > 0)) {
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_ARRAY_TERM, pm_token_type_human(parser->current.type));
+ }
+
lex_state_set(parser, PM_LEX_STATE_BEG | PM_LEX_STATE_LABEL);
LEX(PM_TOKEN_COMMA);
@@ -10961,13 +10347,13 @@ parser_lex(pm_parser_t *parser) {
if (parser->current.end >= parser->end) {
parser->current.end = end;
- } else if (quote == PM_HEREDOC_QUOTE_NONE && (width = char_is_identifier(parser, parser->current.end)) == 0) {
+ } else if (quote == PM_HEREDOC_QUOTE_NONE && (width = char_is_identifier(parser, parser->current.end, parser->end - parser->current.end)) == 0) {
parser->current.end = end;
} else {
if (quote == PM_HEREDOC_QUOTE_NONE) {
parser->current.end += width;
- while ((parser->current.end < parser->end) && (width = char_is_identifier(parser, parser->current.end))) {
+ while ((width = char_is_identifier(parser, parser->current.end, parser->end - parser->current.end))) {
parser->current.end += width;
}
} else {
@@ -10991,12 +10377,14 @@ parser_lex(pm_parser_t *parser) {
lex_mode_push(parser, (pm_lex_mode_t) {
.mode = PM_LEX_HEREDOC,
.as.heredoc = {
- .ident_start = ident_start,
- .ident_length = ident_length,
+ .base = {
+ .ident_start = ident_start,
+ .ident_length = ident_length,
+ .quote = quote,
+ .indent = indent
+ },
.next_start = parser->current.end,
- .quote = quote,
- .indent = indent,
- .common_whitespace = (size_t) -1,
+ .common_whitespace = NULL,
.line_continuation = false
}
});
@@ -11009,7 +10397,7 @@ parser_lex(pm_parser_t *parser) {
// this is not a valid heredoc declaration. In this case we
// will add an error, but we will still return a heredoc
// start.
- if (!ident_error) pm_parser_err_heredoc_term(parser, parser->lex_modes.current);
+ if (!ident_error) pm_parser_err_heredoc_term(parser, ident_start, ident_length);
body_start = parser->end;
} else {
// Otherwise, we want to indicate that the body of the
@@ -11145,7 +10533,16 @@ parser_lex(pm_parser_t *parser) {
pm_token_type_t type = PM_TOKEN_AMPERSAND;
if (lex_state_spcarg_p(parser, space_seen)) {
- pm_parser_warn_token(parser, &parser->current, PM_WARN_AMBIGUOUS_PREFIX_AMPERSAND);
+ if ((peek(parser) != ':') || (peek_offset(parser, 1) == '\0')) {
+ pm_parser_warn_token(parser, &parser->current, PM_WARN_AMBIGUOUS_PREFIX_AMPERSAND);
+ } else {
+ const uint8_t delim = peek_offset(parser, 1);
+
+ if ((delim != '\'') && (delim != '"') && !char_is_identifier(parser, parser->current.end + 1, parser->end - (parser->current.end + 1))) {
+ pm_parser_warn_token(parser, &parser->current, PM_WARN_AMBIGUOUS_PREFIX_AMPERSAND);
+ }
+ }
+
type = PM_TOKEN_UAMPERSAND;
} else if (lex_state_beg_p(parser)) {
type = PM_TOKEN_UAMPERSAND;
@@ -11281,10 +10678,7 @@ parser_lex(pm_parser_t *parser) {
if (match(parser, '.')) {
if (match(parser, '.')) {
// If we're _not_ inside a range within default parameters
- if (
- !context_p(parser, PM_CONTEXT_DEFAULT_PARAMS) &&
- context_p(parser, PM_CONTEXT_DEF_PARAMS)
- ) {
+ if (!context_p(parser, PM_CONTEXT_DEFAULT_PARAMS) && context_p(parser, PM_CONTEXT_DEF_PARAMS)) {
if (lex_state_p(parser, PM_LEX_STATE_END)) {
lex_state_set(parser, PM_LEX_STATE_BEG);
} else {
@@ -11582,7 +10976,7 @@ parser_lex(pm_parser_t *parser) {
default: {
if (*parser->current.start != '_') {
- size_t width = char_is_identifier_start(parser, parser->current.start);
+ size_t width = char_is_identifier_start(parser, parser->current.start, parser->end - parser->current.start);
// If this isn't the beginning of an identifier, then
// it's an invalid token as we've exhausted all of the
@@ -11615,7 +11009,7 @@ parser_lex(pm_parser_t *parser) {
PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_UNEXPECTED_TOKEN_IGNORE, "escaped carriage return");
break;
}
- /* fallthrough */
+ PRISM_FALLTHROUGH
default:
PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_UNEXPECTED_TOKEN_IGNORE, "backslash");
break;
@@ -11812,7 +11206,7 @@ parser_lex(pm_parser_t *parser) {
pm_token_buffer_push_byte(&token_buffer, '\r');
break;
}
- /* fallthrough */
+ PRISM_FALLTHROUGH
case '\n':
pm_token_buffer_push_byte(&token_buffer, '\n');
@@ -11916,9 +11310,28 @@ parser_lex(pm_parser_t *parser) {
pm_regexp_token_buffer_t token_buffer = { 0 };
while (breakpoint != NULL) {
+ uint8_t term = lex_mode->as.regexp.terminator;
+ bool is_terminator = (*breakpoint == term);
+
+ // If the terminator is newline, we need to consider \r\n _also_ a newline
+ // For example: `%\nfoo\r\n`
+ // The string should be "foo", not "foo\r"
+ if (*breakpoint == '\r' && peek_at(parser, breakpoint + 1) == '\n') {
+ if (term == '\n') {
+ is_terminator = true;
+ }
+
+ // If the terminator is a CR, but we see a CRLF, we need to
+ // treat the CRLF as a newline, meaning this is _not_ the
+ // terminator
+ if (term == '\r') {
+ is_terminator = false;
+ }
+ }
+
// If we hit the terminator, we need to determine what kind of
// token to return.
- if (*breakpoint == lex_mode->as.regexp.terminator) {
+ if (is_terminator) {
if (lex_mode->as.regexp.nesting > 0) {
parser->current.end = breakpoint + 1;
breakpoint = pm_strpbrk(parser, parser->current.end, breakpoints, parser->end - parser->current.end, false);
@@ -11939,7 +11352,13 @@ parser_lex(pm_parser_t *parser) {
size_t eol_length = match_eol_at(parser, breakpoint);
if (eol_length) {
parser->current.end = breakpoint + eol_length;
- pm_newline_list_append(&parser->newline_list, parser->current.end - 1);
+
+ // Track the newline if we're not in a heredoc that
+ // would have already have added the newline to the
+ // list.
+ if (parser->heredoc_end == NULL) {
+ pm_newline_list_append(&parser->newline_list, parser->current.end - 1);
+ }
} else {
parser->current.end = breakpoint + 1;
}
@@ -11980,7 +11399,7 @@ parser_lex(pm_parser_t *parser) {
pm_regexp_token_buffer_escape(parser, &token_buffer);
token_buffer.base.cursor = breakpoint;
- /* fallthrough */
+ PRISM_FALLTHROUGH
case '\n':
// If we've hit a newline, then we need to track that in
// the list of newlines.
@@ -12022,7 +11441,7 @@ parser_lex(pm_parser_t *parser) {
pm_token_buffer_push_byte(&token_buffer.base, '\r');
break;
}
- /* fallthrough */
+ PRISM_FALLTHROUGH
case '\n':
if (parser->heredoc_end) {
// ... if we are on the same line as a heredoc,
@@ -12148,10 +11567,29 @@ parser_lex(pm_parser_t *parser) {
continue;
}
+ uint8_t term = lex_mode->as.string.terminator;
+ bool is_terminator = (*breakpoint == term);
+
+ // If the terminator is newline, we need to consider \r\n _also_ a newline
+ // For example: `%r\nfoo\r\n`
+ // The string should be /foo/, not /foo\r/
+ if (*breakpoint == '\r' && peek_at(parser, breakpoint + 1) == '\n') {
+ if (term == '\n') {
+ is_terminator = true;
+ }
+
+ // If the terminator is a CR, but we see a CRLF, we need to
+ // treat the CRLF as a newline, meaning this is _not_ the
+ // terminator
+ if (term == '\r') {
+ is_terminator = false;
+ }
+ }
+
// Note that we have to check the terminator here first because we could
// potentially be parsing a % string that has a # character as the
// terminator.
- if (*breakpoint == lex_mode->as.string.terminator) {
+ if (is_terminator) {
// If this terminator doesn't actually close the string, then we need
// to continue on past it.
if (lex_mode->as.string.nesting > 0) {
@@ -12174,7 +11612,13 @@ parser_lex(pm_parser_t *parser) {
size_t eol_length = match_eol_at(parser, breakpoint);
if (eol_length) {
parser->current.end = breakpoint + eol_length;
- pm_newline_list_append(&parser->newline_list, parser->current.end - 1);
+
+ // Track the newline if we're not in a heredoc that
+ // would have already have added the newline to the
+ // list.
+ if (parser->heredoc_end == NULL) {
+ pm_newline_list_append(&parser->newline_list, parser->current.end - 1);
+ }
} else {
parser->current.end = breakpoint + 1;
}
@@ -12186,6 +11630,13 @@ parser_lex(pm_parser_t *parser) {
LEX(PM_TOKEN_LABEL_END);
}
+ // When the delimiter itself is a newline, we won't
+ // get a chance to flush heredocs in the usual places since
+ // the newline is already consumed.
+ if (term == '\n' && parser->heredoc_end) {
+ parser_flush_heredoc_end(parser);
+ }
+
lex_state_set(parser, PM_LEX_STATE_END);
lex_mode_pop(parser);
LEX(PM_TOKEN_STRING_END);
@@ -12211,7 +11662,7 @@ parser_lex(pm_parser_t *parser) {
pm_token_buffer_escape(parser, &token_buffer);
token_buffer.cursor = breakpoint;
- /* fallthrough */
+ PRISM_FALLTHROUGH
case '\n':
// When we hit a newline, we need to flush any potential
// heredocs. Note that this has to happen after we check
@@ -12256,7 +11707,7 @@ parser_lex(pm_parser_t *parser) {
pm_token_buffer_push_byte(&token_buffer, '\r');
break;
}
- /* fallthrough */
+ PRISM_FALLTHROUGH
case '\n':
if (!lex_mode->as.string.interpolation) {
pm_token_buffer_push_byte(&token_buffer, '\\');
@@ -12346,6 +11797,7 @@ parser_lex(pm_parser_t *parser) {
// Now let's grab the information about the identifier off of the
// current lex mode.
pm_lex_mode_t *lex_mode = parser->lex_modes.current;
+ pm_heredoc_lex_mode_t *heredoc_lex_mode = &lex_mode->as.heredoc.base;
bool line_continuation = lex_mode->as.heredoc.line_continuation;
lex_mode->as.heredoc.line_continuation = false;
@@ -12355,15 +11807,16 @@ parser_lex(pm_parser_t *parser) {
// terminator) but still continue parsing so that content after the
// declaration of the heredoc can be parsed.
if (parser->current.end >= parser->end) {
- pm_parser_err_heredoc_term(parser, lex_mode);
+ pm_parser_err_heredoc_term(parser, heredoc_lex_mode->ident_start, heredoc_lex_mode->ident_length);
parser->next_start = lex_mode->as.heredoc.next_start;
parser->heredoc_end = parser->current.end;
lex_state_set(parser, PM_LEX_STATE_END);
+ lex_mode_pop(parser);
LEX(PM_TOKEN_HEREDOC_END);
}
- const uint8_t *ident_start = lex_mode->as.heredoc.ident_start;
- size_t ident_length = lex_mode->as.heredoc.ident_length;
+ const uint8_t *ident_start = heredoc_lex_mode->ident_start;
+ size_t ident_length = heredoc_lex_mode->ident_length;
// If we are immediately following a newline and we have hit the
// terminator, then we need to return the ending of the heredoc.
@@ -12388,10 +11841,7 @@ parser_lex(pm_parser_t *parser) {
const uint8_t *terminator_start = ident_end - ident_length;
const uint8_t *cursor = start;
- if (
- lex_mode->as.heredoc.indent == PM_HEREDOC_INDENT_DASH ||
- lex_mode->as.heredoc.indent == PM_HEREDOC_INDENT_TILDE
- ) {
+ if (heredoc_lex_mode->indent == PM_HEREDOC_INDENT_DASH || heredoc_lex_mode->indent == PM_HEREDOC_INDENT_TILDE) {
while (cursor < terminator_start && pm_char_is_inline_whitespace(*cursor)) {
cursor++;
}
@@ -12414,17 +11864,19 @@ parser_lex(pm_parser_t *parser) {
}
lex_state_set(parser, PM_LEX_STATE_END);
+ lex_mode_pop(parser);
LEX(PM_TOKEN_HEREDOC_END);
}
}
- size_t whitespace = pm_heredoc_strspn_inline_whitespace(parser, &start, lex_mode->as.heredoc.indent);
+ size_t whitespace = pm_heredoc_strspn_inline_whitespace(parser, &start, heredoc_lex_mode->indent);
if (
- lex_mode->as.heredoc.indent == PM_HEREDOC_INDENT_TILDE &&
- (lex_mode->as.heredoc.common_whitespace > whitespace) &&
+ heredoc_lex_mode->indent == PM_HEREDOC_INDENT_TILDE &&
+ lex_mode->as.heredoc.common_whitespace != NULL &&
+ (*lex_mode->as.heredoc.common_whitespace > whitespace) &&
peek_at(parser, start) != '\n'
) {
- lex_mode->as.heredoc.common_whitespace = whitespace;
+ *lex_mode->as.heredoc.common_whitespace = whitespace;
}
}
@@ -12433,7 +11885,7 @@ parser_lex(pm_parser_t *parser) {
// strpbrk to find the first of these characters.
uint8_t breakpoints[] = "\r\n\\#";
- pm_heredoc_quote_t quote = lex_mode->as.heredoc.quote;
+ pm_heredoc_quote_t quote = heredoc_lex_mode->quote;
if (quote == PM_HEREDOC_QUOTE_SINGLE) {
breakpoints[3] = '\0';
}
@@ -12463,7 +11915,7 @@ parser_lex(pm_parser_t *parser) {
pm_token_buffer_escape(parser, &token_buffer);
token_buffer.cursor = breakpoint;
- /* fallthrough */
+ PRISM_FALLTHROUGH
case '\n': {
if (parser->heredoc_end != NULL && (parser->heredoc_end > breakpoint)) {
parser_flush_heredoc_end(parser);
@@ -12496,8 +11948,7 @@ parser_lex(pm_parser_t *parser) {
// leading whitespace if we have a - or ~ heredoc.
const uint8_t *cursor = start;
- if (lex_mode->as.heredoc.indent == PM_HEREDOC_INDENT_DASH ||
- lex_mode->as.heredoc.indent == PM_HEREDOC_INDENT_TILDE) {
+ if (heredoc_lex_mode->indent == PM_HEREDOC_INDENT_DASH || heredoc_lex_mode->indent == PM_HEREDOC_INDENT_TILDE) {
while (cursor < terminator_start && pm_char_is_inline_whitespace(*cursor)) {
cursor++;
}
@@ -12513,16 +11964,16 @@ parser_lex(pm_parser_t *parser) {
}
}
- size_t whitespace = pm_heredoc_strspn_inline_whitespace(parser, &start, lex_mode->as.heredoc.indent);
+ size_t whitespace = pm_heredoc_strspn_inline_whitespace(parser, &start, lex_mode->as.heredoc.base.indent);
// If we have hit a newline that is followed by a valid
// terminator, then we need to return the content of the
// heredoc here as string content. Then, the next time a
// token is lexed, it will match again and return the
// end of the heredoc.
- if (lex_mode->as.heredoc.indent == PM_HEREDOC_INDENT_TILDE) {
- if ((lex_mode->as.heredoc.common_whitespace > whitespace) && peek_at(parser, start) != '\n') {
- lex_mode->as.heredoc.common_whitespace = whitespace;
+ if (lex_mode->as.heredoc.base.indent == PM_HEREDOC_INDENT_TILDE) {
+ if ((lex_mode->as.heredoc.common_whitespace != NULL) && (*lex_mode->as.heredoc.common_whitespace > whitespace) && peek_at(parser, start) != '\n') {
+ *lex_mode->as.heredoc.common_whitespace = whitespace;
}
parser->current.end = breakpoint + 1;
@@ -12564,7 +12015,7 @@ parser_lex(pm_parser_t *parser) {
pm_token_buffer_push_byte(&token_buffer, '\r');
break;
}
- /* fallthrough */
+ PRISM_FALLTHROUGH
case '\n':
pm_token_buffer_push_byte(&token_buffer, '\\');
pm_token_buffer_push_byte(&token_buffer, '\n');
@@ -12584,14 +12035,17 @@ parser_lex(pm_parser_t *parser) {
pm_token_buffer_push_byte(&token_buffer, '\r');
break;
}
- /* fallthrough */
+ PRISM_FALLTHROUGH
case '\n':
// If we are in a tilde here, we should
// break out of the loop and return the
// string content.
- if (lex_mode->as.heredoc.indent == PM_HEREDOC_INDENT_TILDE) {
+ if (heredoc_lex_mode->indent == PM_HEREDOC_INDENT_TILDE) {
const uint8_t *end = parser->current.end;
- pm_newline_list_append(&parser->newline_list, end);
+
+ if (parser->heredoc_end == NULL) {
+ pm_newline_list_append(&parser->newline_list, end);
+ }
// Here we want the buffer to only
// include up to the backslash.
@@ -12735,7 +12189,7 @@ typedef struct {
pm_binding_powers_t pm_binding_powers[PM_TOKEN_MAXIMUM] = {
// rescue
- [PM_TOKEN_KEYWORD_RESCUE_MODIFIER] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_MODIFIER_RESCUE),
+ [PM_TOKEN_KEYWORD_RESCUE_MODIFIER] = { PM_BINDING_POWER_MODIFIER_RESCUE, PM_BINDING_POWER_COMPOSITION, true, false },
// if unless until while
[PM_TOKEN_KEYWORD_IF_MODIFIER] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_MODIFIER),
@@ -12815,7 +12269,7 @@ pm_binding_powers_t pm_binding_powers[PM_TOKEN_MAXIMUM] = {
[PM_TOKEN_PERCENT] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_FACTOR),
[PM_TOKEN_SLASH] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_FACTOR),
[PM_TOKEN_STAR] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_FACTOR),
- [PM_TOKEN_USTAR] = LEFT_ASSOCIATIVE(PM_BINDING_POWER_FACTOR),
+ [PM_TOKEN_USTAR] = RIGHT_ASSOCIATIVE_UNARY(PM_BINDING_POWER_FACTOR),
// -@
[PM_TOKEN_UMINUS] = RIGHT_ASSOCIATIVE_UNARY(PM_BINDING_POWER_UMINUS),
@@ -12877,14 +12331,6 @@ match4(const pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2,
}
/**
- * Returns true if the current token is any of the six given types.
- */
-static inline bool
-match6(const pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2, pm_token_type_t type3, pm_token_type_t type4, pm_token_type_t type5, pm_token_type_t type6) {
- return match1(parser, type1) || match1(parser, type2) || match1(parser, type3) || match1(parser, type4) || match1(parser, type5) || match1(parser, type6);
-}
-
-/**
* Returns true if the current token is any of the seven given types.
*/
static inline bool
@@ -12929,19 +12375,6 @@ accept2(pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2) {
}
/**
- * If the current token is any of the three given types, lex forward by one
- * token and return true. Otherwise return false.
- */
-static inline bool
-accept3(pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2, pm_token_type_t type3) {
- if (match3(parser, type1, type2, type3)) {
- parser_lex(parser);
- return true;
- }
- return false;
-}
-
-/**
* This function indicates that the parser expects a token in a specific
* position. For example, if you're parsing a BEGIN block, you know that a { is
* expected immediately after the keyword. In that case you would call this
@@ -12979,46 +12412,46 @@ expect2(pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2, pm_di
}
/**
- * This function is the same as expect2, but it expects one of three token types.
- */
-static void
-expect3(pm_parser_t *parser, pm_token_type_t type1, pm_token_type_t type2, pm_token_type_t type3, pm_diagnostic_id_t diag_id) {
- if (accept3(parser, type1, type2, type3)) return;
-
- const uint8_t *location = parser->previous.end;
- pm_parser_err(parser, location, location, diag_id);
-
- parser->previous.start = location;
- parser->previous.type = PM_TOKEN_MISSING;
-}
-
-/**
* A special expect1 that expects a heredoc terminator and handles popping the
* lex mode accordingly.
*/
static void
-expect1_heredoc_term(pm_parser_t *parser, pm_lex_mode_t *lex_mode) {
+expect1_heredoc_term(pm_parser_t *parser, const uint8_t *ident_start, size_t ident_length) {
if (match1(parser, PM_TOKEN_HEREDOC_END)) {
- lex_mode_pop(parser);
parser_lex(parser);
} else {
- pm_parser_err_heredoc_term(parser, lex_mode);
- lex_mode_pop(parser);
+ pm_parser_err_heredoc_term(parser, ident_start, ident_length);
parser->previous.start = parser->previous.end;
parser->previous.type = PM_TOKEN_MISSING;
}
}
+/**
+ * A special expect1 that attaches the error to the opening token location
+ * rather than the current position. This is useful for errors about missing
+ * closing tokens, where we want to point to the line with the opening token
+ * (e.g., `def`, `class`, `if`, `{`) rather than the end of the file.
+ */
+static void
+expect1_opening(pm_parser_t *parser, pm_token_type_t type, pm_diagnostic_id_t diag_id, const pm_token_t *opening) {
+ if (accept1(parser, type)) return;
+
+ pm_parser_err(parser, opening->start, opening->end, diag_id);
+
+ parser->previous.start = parser->previous.end;
+ parser->previous.type = PM_TOKEN_MISSING;
+}
+
static pm_node_t *
-parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id);
+parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, bool accepts_label, pm_diagnostic_id_t diag_id, uint16_t depth);
/**
* This is a wrapper of parse_expression, which also checks whether the
* resulting node is a value expression.
*/
static pm_node_t *
-parse_value_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id) {
- pm_node_t *node = parse_expression(parser, binding_power, accepts_command_call, diag_id);
+parse_value_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, bool accepts_label, pm_diagnostic_id_t diag_id, uint16_t depth) {
+ pm_node_t *node = parse_expression(parser, binding_power, accepts_command_call, accepts_label, diag_id, depth);
pm_assert_value_expression(parser, node);
return node;
}
@@ -13102,14 +12535,89 @@ token_begins_expression_p(pm_token_type_t type) {
* prefixed by the * operator.
*/
static pm_node_t *
-parse_starred_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id) {
+parse_starred_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id, uint16_t depth) {
if (accept1(parser, PM_TOKEN_USTAR)) {
pm_token_t operator = parser->previous;
- pm_node_t *expression = parse_value_expression(parser, binding_power, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR);
- return (pm_node_t *) pm_splat_node_create(parser, &operator, expression);
+ pm_node_t *expression = parse_value_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1));
+ return UP(pm_splat_node_create(parser, &operator, expression));
+ }
+
+ return parse_value_expression(parser, binding_power, accepts_command_call, false, diag_id, depth);
+}
+
+static bool
+pm_node_unreference_each(const pm_node_t *node, void *data) {
+ switch (PM_NODE_TYPE(node)) {
+ /* When we are about to destroy a set of nodes that could potentially
+ * contain block exits for the current scope, we need to check if they
+ * are contained in the list of block exits and remove them if they are.
+ */
+ case PM_BREAK_NODE:
+ case PM_NEXT_NODE:
+ case PM_REDO_NODE: {
+ pm_parser_t *parser = (pm_parser_t *) data;
+ size_t index = 0;
+
+ while (index < parser->current_block_exits->size) {
+ pm_node_t *block_exit = parser->current_block_exits->nodes[index];
+
+ if (block_exit == node) {
+ if (index + 1 < parser->current_block_exits->size) {
+ memmove(
+ &parser->current_block_exits->nodes[index],
+ &parser->current_block_exits->nodes[index + 1],
+ (parser->current_block_exits->size - index - 1) * sizeof(pm_node_t *)
+ );
+ }
+ parser->current_block_exits->size--;
+
+ /* Note returning true here because these nodes could have
+ * arguments that are themselves block exits. */
+ return true;
+ }
+
+ index++;
+ }
+
+ return true;
+ }
+ /* When an implicit local variable is written to or targeted, it becomes
+ * a regular, named local variable. This branch removes it from the list
+ * of implicit parameters when that happens. */
+ case PM_LOCAL_VARIABLE_READ_NODE:
+ case PM_IT_LOCAL_VARIABLE_READ_NODE: {
+ pm_parser_t *parser = (pm_parser_t *) data;
+ pm_node_list_t *implicit_parameters = &parser->current_scope->implicit_parameters;
+
+ for (size_t index = 0; index < implicit_parameters->size; index++) {
+ if (implicit_parameters->nodes[index] == node) {
+ /* If the node is not the last one in the list, we need to
+ * shift the remaining nodes down to fill the gap. This is
+ * extremely unlikely to happen. */
+ if (index != implicit_parameters->size - 1) {
+ memmove(&implicit_parameters->nodes[index], &implicit_parameters->nodes[index + 1], (implicit_parameters->size - index - 1) * sizeof(pm_node_t *));
+ }
+
+ implicit_parameters->size--;
+ break;
+ }
+ }
+
+ return false;
+ }
+ default:
+ return true;
}
+}
- return parse_value_expression(parser, binding_power, accepts_command_call, diag_id);
+/**
+ * When we are about to destroy a set of nodes that could potentially be
+ * referenced by one or more lists on the parser, then remove them from those
+ * lists so we don't get a use-after-free.
+ */
+static void
+pm_node_unreference(pm_parser_t *parser, const pm_node_t *node) {
+ pm_visit_node(node, pm_node_unreference_each, parser);
}
/**
@@ -13159,38 +12667,19 @@ parse_unwriteable_target(pm_parser_t *parser, pm_node_t *target) {
pm_local_variable_target_node_t *result = pm_local_variable_target_node_create(parser, &target->location, name, 0);
pm_node_destroy(parser, target);
- return (pm_node_t *) result;
-}
-
-/**
- * When an implicit local variable is written to or targeted, it becomes a
- * regular, named local variable. This function removes it from the list of
- * implicit parameters when that happens.
- */
-static void
-parse_target_implicit_parameter(pm_parser_t *parser, pm_node_t *node) {
- pm_node_list_t *implicit_parameters = &parser->current_scope->implicit_parameters;
-
- for (size_t index = 0; index < implicit_parameters->size; index++) {
- if (implicit_parameters->nodes[index] == node) {
- // If the node is not the last one in the list, we need to shift the
- // remaining nodes down to fill the gap. This is extremely unlikely
- // to happen.
- if (index != implicit_parameters->size - 1) {
- memcpy(&implicit_parameters->nodes[index], &implicit_parameters->nodes[index + 1], (implicit_parameters->size - index - 1) * sizeof(pm_node_t *));
- }
-
- implicit_parameters->size--;
- break;
- }
- }
+ return UP(result);
}
/**
* Convert the given node into a valid target node.
+ *
+ * @param multiple Whether or not this target is part of a larger set of
+ * targets. If it is, then the &. operator is not allowed.
+ * @param splat Whether or not this target is a child of a splat target. If it
+ * is, then fewer patterns are allowed.
*/
static pm_node_t *
-parse_target(pm_parser_t *parser, pm_node_t *target, bool multiple) {
+parse_target(pm_parser_t *parser, pm_node_t *target, bool multiple, bool splat_parent) {
switch (PM_NODE_TYPE(target)) {
case PM_MISSING_NODE:
return target;
@@ -13238,7 +12727,7 @@ parse_target(pm_parser_t *parser, pm_node_t *target, bool multiple) {
case PM_LOCAL_VARIABLE_READ_NODE: {
if (pm_token_is_numbered_parameter(target->location.start, target->location.end)) {
PM_PARSER_ERR_FORMAT(parser, target->location.start, target->location.end, PM_ERR_PARAMETER_NUMBERED_RESERVED, target->location.start);
- parse_target_implicit_parameter(parser, target);
+ pm_node_unreference(parser, target);
}
const pm_local_variable_read_node_t *cast = (const pm_local_variable_read_node_t *) target;
@@ -13253,9 +12742,9 @@ parse_target(pm_parser_t *parser, pm_node_t *target, bool multiple) {
}
case PM_IT_LOCAL_VARIABLE_READ_NODE: {
pm_constant_id_t name = pm_parser_local_add_constant(parser, "it", 2);
- pm_node_t *node = (pm_node_t *) pm_local_variable_target_node_create(parser, &target->location, name, 0);
+ pm_node_t *node = UP(pm_local_variable_target_node_create(parser, &target->location, name, 0));
- parse_target_implicit_parameter(parser, target);
+ pm_node_unreference(parser, target);
pm_node_destroy(parser, target);
return node;
@@ -13265,15 +12754,21 @@ parse_target(pm_parser_t *parser, pm_node_t *target, bool multiple) {
target->type = PM_INSTANCE_VARIABLE_TARGET_NODE;
return target;
case PM_MULTI_TARGET_NODE:
+ if (splat_parent) {
+ // Multi target is not accepted in all positions. If this is one
+ // of them, then we need to add an error.
+ pm_parser_err_node(parser, target, PM_ERR_WRITE_TARGET_UNEXPECTED);
+ }
+
return target;
case PM_SPLAT_NODE: {
pm_splat_node_t *splat = (pm_splat_node_t *) target;
if (splat->expression != NULL) {
- splat->expression = parse_target(parser, splat->expression, multiple);
+ splat->expression = parse_target(parser, splat->expression, multiple, true);
}
- return (pm_node_t *) splat;
+ return UP(splat);
}
case PM_CALL_NODE: {
pm_call_node_t *call = (pm_call_node_t *) target;
@@ -13304,16 +12799,16 @@ parse_target(pm_parser_t *parser, pm_node_t *target, bool multiple) {
pm_constant_id_t name = pm_parser_local_add_location(parser, message_loc.start, message_loc.end, 0);
pm_node_destroy(parser, target);
- return (pm_node_t *) pm_local_variable_target_node_create(parser, &message_loc, name, 0);
+ return UP(pm_local_variable_target_node_create(parser, &message_loc, name, 0));
}
- if (*call->message_loc.start == '_' || parser->encoding->alnum_char(call->message_loc.start, call->message_loc.end - call->message_loc.start)) {
+ if (peek_at(parser, call->message_loc.start) == '_' || parser->encoding->alnum_char(call->message_loc.start, call->message_loc.end - call->message_loc.start)) {
if (multiple && PM_NODE_FLAG_P(call, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) {
pm_parser_err_node(parser, (const pm_node_t *) call, PM_ERR_UNEXPECTED_SAFE_NAVIGATION);
}
parse_write_name(parser, &call->name);
- return (pm_node_t *) pm_call_target_node_create(parser, call);
+ return UP(pm_call_target_node_create(parser, call));
}
}
@@ -13321,10 +12816,10 @@ parse_target(pm_parser_t *parser, pm_node_t *target, bool multiple) {
// an aref expression, and we can transform it into an aset
// expression.
if (PM_NODE_FLAG_P(call, PM_CALL_NODE_FLAGS_INDEX)) {
- return (pm_node_t *) pm_index_target_node_create(parser, call);
+ return UP(pm_index_target_node_create(parser, call));
}
}
- /* fallthrough */
+ PRISM_FALLTHROUGH
default:
// In this case we have a node that we don't know how to convert
// into a target. We need to treat it as an error. For now, we'll
@@ -13340,9 +12835,10 @@ parse_target(pm_parser_t *parser, pm_node_t *target, bool multiple) {
*/
static pm_node_t *
parse_target_validate(pm_parser_t *parser, pm_node_t *target, bool multiple) {
- pm_node_t *result = parse_target(parser, target, multiple);
+ pm_node_t *result = parse_target(parser, target, multiple, false);
- // Ensure that we have one of an =, an 'in' in for indexes, and a ')' in parens after the targets.
+ // Ensure that we have one of an =, an 'in' in for indexes, and a ')' in
+ // parens after the targets.
if (
!match1(parser, PM_TOKEN_EQUAL) &&
!(context_p(parser, PM_CONTEXT_FOR_INDEX) && match1(parser, PM_TOKEN_KEYWORD_IN)) &&
@@ -13363,7 +12859,7 @@ parse_shareable_constant_write(pm_parser_t *parser, pm_node_t *write) {
pm_shareable_constant_value_t shareable_constant = pm_parser_scope_shareable_constant_get(parser);
if (shareable_constant != PM_SCOPE_SHAREABLE_CONSTANT_NONE) {
- return (pm_node_t *) pm_shareable_constant_node_create(parser, write, shareable_constant);
+ return UP(pm_shareable_constant_node_create(parser, write, shareable_constant));
}
return write;
@@ -13381,10 +12877,10 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
case PM_CLASS_VARIABLE_READ_NODE: {
pm_class_variable_write_node_t *node = pm_class_variable_write_node_create(parser, (pm_class_variable_read_node_t *) target, operator, value);
pm_node_destroy(parser, target);
- return (pm_node_t *) node;
+ return UP(node);
}
case PM_CONSTANT_PATH_NODE: {
- pm_node_t *node = (pm_node_t *) pm_constant_path_write_node_create(parser, (pm_constant_path_node_t *) target, operator, value);
+ pm_node_t *node = UP(pm_constant_path_write_node_create(parser, (pm_constant_path_node_t *) target, operator, value));
if (context_def_p(parser)) {
pm_parser_err_node(parser, node, PM_ERR_WRITE_TARGET_IN_METHOD);
@@ -13393,7 +12889,7 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
return parse_shareable_constant_write(parser, node);
}
case PM_CONSTANT_READ_NODE: {
- pm_node_t *node = (pm_node_t *) pm_constant_write_node_create(parser, (pm_constant_read_node_t *) target, operator, value);
+ pm_node_t *node = UP(pm_constant_write_node_create(parser, (pm_constant_read_node_t *) target, operator, value));
if (context_def_p(parser)) {
pm_parser_err_node(parser, node, PM_ERR_WRITE_TARGET_IN_METHOD);
@@ -13405,11 +12901,11 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
case PM_BACK_REFERENCE_READ_NODE:
case PM_NUMBERED_REFERENCE_READ_NODE:
PM_PARSER_ERR_NODE_FORMAT_CONTENT(parser, target, PM_ERR_WRITE_TARGET_READONLY);
- /* fallthrough */
+ PRISM_FALLTHROUGH
case PM_GLOBAL_VARIABLE_READ_NODE: {
pm_global_variable_write_node_t *node = pm_global_variable_write_node_create(parser, target, operator, value);
pm_node_destroy(parser, target);
- return (pm_node_t *) node;
+ return UP(node);
}
case PM_LOCAL_VARIABLE_READ_NODE: {
pm_local_variable_read_node_t *local_read = (pm_local_variable_read_node_t *) target;
@@ -13423,30 +12919,30 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
if (pm_token_is_numbered_parameter(target->location.start, target->location.end)) {
pm_diagnostic_id_t diag_id = (scope->parameters & PM_SCOPE_PARAMETERS_NUMBERED_FOUND) ? PM_ERR_EXPRESSION_NOT_WRITABLE_NUMBERED : PM_ERR_PARAMETER_NUMBERED_RESERVED;
PM_PARSER_ERR_FORMAT(parser, target->location.start, target->location.end, diag_id, target->location.start);
- parse_target_implicit_parameter(parser, target);
+ pm_node_unreference(parser, target);
}
pm_locals_unread(&scope->locals, name);
pm_node_destroy(parser, target);
- return (pm_node_t *) pm_local_variable_write_node_create(parser, name, depth, value, &name_loc, operator);
+ return UP(pm_local_variable_write_node_create(parser, name, depth, value, &name_loc, operator));
}
case PM_IT_LOCAL_VARIABLE_READ_NODE: {
pm_constant_id_t name = pm_parser_local_add_constant(parser, "it", 2);
- pm_node_t *node = (pm_node_t *) pm_local_variable_write_node_create(parser, name, 0, value, &target->location, operator);
+ pm_node_t *node = UP(pm_local_variable_write_node_create(parser, name, 0, value, &target->location, operator));
- parse_target_implicit_parameter(parser, target);
+ pm_node_unreference(parser, target);
pm_node_destroy(parser, target);
return node;
}
case PM_INSTANCE_VARIABLE_READ_NODE: {
- pm_node_t *write_node = (pm_node_t *) pm_instance_variable_write_node_create(parser, (pm_instance_variable_read_node_t *) target, operator, value);
+ pm_node_t *write_node = UP(pm_instance_variable_write_node_create(parser, (pm_instance_variable_read_node_t *) target, operator, value));
pm_node_destroy(parser, target);
return write_node;
}
case PM_MULTI_TARGET_NODE:
- return (pm_node_t *) pm_multi_write_node_create(parser, (pm_multi_target_node_t *) target, operator, value);
+ return UP(pm_multi_write_node_create(parser, (pm_multi_target_node_t *) target, operator, value));
case PM_SPLAT_NODE: {
pm_splat_node_t *splat = (pm_splat_node_t *) target;
@@ -13455,9 +12951,9 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
}
pm_multi_target_node_t *multi_target = pm_multi_target_node_create(parser);
- pm_multi_target_node_targets_append(parser, multi_target, (pm_node_t *) splat);
+ pm_multi_target_node_targets_append(parser, multi_target, UP(splat));
- return (pm_node_t *) pm_multi_write_node_create(parser, multi_target, operator, value);
+ return UP(pm_multi_write_node_create(parser, multi_target, operator, value));
}
case PM_CALL_NODE: {
pm_call_node_t *call = (pm_call_node_t *) target;
@@ -13489,13 +12985,13 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
pm_node_destroy(parser, target);
pm_constant_id_t constant_id = pm_parser_constant_id_location(parser, message.start, message.end);
- target = (pm_node_t *) pm_local_variable_write_node_create(parser, constant_id, 0, value, &message, operator);
+ target = UP(pm_local_variable_write_node_create(parser, constant_id, 0, value, &message, operator));
pm_refute_numbered_parameter(parser, message.start, message.end);
return target;
}
- if (char_is_identifier_start(parser, call->message_loc.start)) {
+ if (char_is_identifier_start(parser, call->message_loc.start, parser->end - call->message_loc.start)) {
// When we get here, we have a method call, because it was
// previously marked as a method call but now we have an =. This
// looks like:
@@ -13511,10 +13007,12 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
pm_arguments_node_arguments_append(arguments, value);
call->base.location.end = arguments->base.location.end;
+ call->equal_loc = PM_LOCATION_TOKEN_VALUE(operator);
parse_write_name(parser, &call->name);
- pm_node_flag_set((pm_node_t *) call, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE);
- return (pm_node_t *) call;
+ pm_node_flag_set(UP(call), PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE | pm_implicit_array_write_flags(value, PM_CALL_NODE_FLAGS_IMPLICIT_ARRAY));
+
+ return UP(call);
}
}
@@ -13531,18 +13029,29 @@ parse_write(pm_parser_t *parser, pm_node_t *target, pm_token_t *operator, pm_nod
// Replace the name with "[]=".
call->name = pm_parser_constant_id_constant(parser, "[]=", 3);
- pm_node_flag_set((pm_node_t *) call, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE);
+ call->equal_loc = PM_LOCATION_TOKEN_VALUE(operator);
+
+ // Ensure that the arguments for []= don't contain keywords
+ pm_index_arguments_check(parser, call->arguments, call->block);
+ pm_node_flag_set(UP(call), PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE | pm_implicit_array_write_flags(value, PM_CALL_NODE_FLAGS_IMPLICIT_ARRAY));
+
return target;
}
- // If there are arguments on the call node, then it can't be a method
- // call ending with = or a local variable write, so it must be a
- // syntax error. In this case we'll fall through to our default
+ // If there are arguments on the call node, then it can't be a
+ // method call ending with = or a local variable write, so it must
+ // be a syntax error. In this case we'll fall through to our default
// handling. We need to free the value that we parsed because there
// is no way for us to attach it to the tree at this point.
+ //
+ // Since it is possible for the value to contain an implicit
+ // parameter somewhere in its subtree, we need to walk it and remove
+ // any implicit parameters from the list of implicit parameters for
+ // the current scope.
+ pm_node_unreference(parser, value);
pm_node_destroy(parser, value);
}
- /* fallthrough */
+ PRISM_FALLTHROUGH
default:
// In this case we have a node that we don't know how to convert into a
// target. We need to treat it as an error. For now, we'll mark it as an
@@ -13571,11 +13080,11 @@ parse_unwriteable_write(pm_parser_t *parser, pm_node_t *target, const pm_token_t
default: break;
}
- pm_constant_id_t name = pm_parser_constant_id_location(parser, target->location.start, target->location.end);
+ pm_constant_id_t name = pm_parser_local_add_location(parser, target->location.start, target->location.end, 1);
pm_local_variable_write_node_t *result = pm_local_variable_write_node_create(parser, name, 0, value, &target->location, equals);
pm_node_destroy(parser, target);
- return (pm_node_t *) result;
+ return UP(result);
}
/**
@@ -13589,11 +13098,11 @@ parse_unwriteable_write(pm_parser_t *parser, pm_node_t *target, const pm_token_t
* target node or a multi-target node.
*/
static pm_node_t *
-parse_targets(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t binding_power) {
+parse_targets(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t binding_power, uint16_t depth) {
bool has_rest = PM_NODE_TYPE_P(first_target, PM_SPLAT_NODE);
pm_multi_target_node_t *result = pm_multi_target_node_create(parser);
- pm_multi_target_node_targets_append(parser, result, parse_target(parser, first_target, true));
+ pm_multi_target_node_targets_append(parser, result, parse_target(parser, first_target, true, false));
while (accept1(parser, PM_TOKEN_COMMA)) {
if (accept1(parser, PM_TOKEN_USTAR)) {
@@ -13608,28 +13117,35 @@ parse_targets(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t b
pm_node_t *name = NULL;
if (token_begins_expression_p(parser->current.type)) {
- name = parse_expression(parser, binding_power, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR);
- name = parse_target(parser, name, true);
+ name = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1));
+ name = parse_target(parser, name, true, true);
}
- pm_node_t *splat = (pm_node_t *) pm_splat_node_create(parser, &star_operator, name);
+ pm_node_t *splat = UP(pm_splat_node_create(parser, &star_operator, name));
pm_multi_target_node_targets_append(parser, result, splat);
has_rest = true;
+ } else if (match1(parser, PM_TOKEN_PARENTHESIS_LEFT)) {
+ context_push(parser, PM_CONTEXT_MULTI_TARGET);
+ pm_node_t *target = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA, (uint16_t) (depth + 1));
+ target = parse_target(parser, target, true, false);
+
+ pm_multi_target_node_targets_append(parser, result, target);
+ context_pop(parser);
} else if (token_begins_expression_p(parser->current.type)) {
- pm_node_t *target = parse_expression(parser, binding_power, false, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA);
- target = parse_target(parser, target, true);
+ pm_node_t *target = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA, (uint16_t) (depth + 1));
+ target = parse_target(parser, target, true, false);
pm_multi_target_node_targets_append(parser, result, target);
} else if (!match1(parser, PM_TOKEN_EOF)) {
// If we get here, then we have a trailing , in a multi target node.
// We'll add an implicit rest node to represent this.
- pm_node_t *rest = (pm_node_t *) pm_implicit_rest_node_create(parser, &parser->previous);
+ pm_node_t *rest = UP(pm_implicit_rest_node_create(parser, &parser->previous));
pm_multi_target_node_targets_append(parser, result, rest);
break;
}
}
- return (pm_node_t *) result;
+ return UP(result);
}
/**
@@ -13637,8 +13153,8 @@ parse_targets(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t b
* assignment.
*/
static pm_node_t *
-parse_targets_validate(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t binding_power) {
- pm_node_t *result = parse_targets(parser, first_target, binding_power);
+parse_targets_validate(pm_parser_t *parser, pm_node_t *first_target, pm_binding_power_t binding_power, uint16_t depth) {
+ pm_node_t *result = parse_targets(parser, first_target, binding_power, depth);
accept1(parser, PM_TOKEN_NEWLINE);
// Ensure that we have either an = or a ) after the targets.
@@ -13653,7 +13169,7 @@ parse_targets_validate(pm_parser_t *parser, pm_node_t *first_target, pm_binding_
* Parse a list of statements separated by newlines or semicolons.
*/
static pm_statements_node_t *
-parse_statements(pm_parser_t *parser, pm_context_t context) {
+parse_statements(pm_parser_t *parser, pm_context_t context, uint16_t depth) {
// First, skip past any optional terminators that might be at the beginning
// of the statements.
while (accept2(parser, PM_TOKEN_SEMICOLON, PM_TOKEN_NEWLINE));
@@ -13668,8 +13184,8 @@ parse_statements(pm_parser_t *parser, pm_context_t context) {
context_push(parser, context);
while (true) {
- pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_STATEMENT, true, PM_ERR_CANNOT_PARSE_EXPRESSION);
- pm_statements_node_body_append(parser, statements, node);
+ pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_STATEMENT, true, false, PM_ERR_CANNOT_PARSE_EXPRESSION, (uint16_t) (depth + 1));
+ pm_statements_node_body_append(parser, statements, node, true);
// If we're recovering from a syntax error, then we need to stop parsing
// the statements now.
@@ -13711,6 +13227,15 @@ parse_statements(pm_parser_t *parser, pm_context_t context) {
if (PM_NODE_TYPE_P(node, PM_MISSING_NODE)) {
parser_lex(parser);
+ // If we are at the end of the file, then we need to stop parsing
+ // the statements entirely at this point. Mark the parser as
+ // recovering, as we know that EOF closes the top-level context, and
+ // then break out of the loop.
+ if (match1(parser, PM_TOKEN_EOF)) {
+ parser->recovering = true;
+ break;
+ }
+
while (accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON));
if (context_terminator(context, &parser->current)) break;
} else if (!accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_EOF)) {
@@ -13724,7 +13249,16 @@ parse_statements(pm_parser_t *parser, pm_context_t context) {
}
context_pop(parser);
- pm_void_statements_check(parser, statements);
+ bool last_value = true;
+ switch (context) {
+ case PM_CONTEXT_BEGIN_ENSURE:
+ case PM_CONTEXT_DEF_ENSURE:
+ last_value = false;
+ break;
+ default:
+ break;
+ }
+ pm_void_statements_check(parser, statements, last_value);
return statements;
}
@@ -13779,7 +13313,7 @@ pm_when_clause_static_literals_add(pm_parser_t *parser, pm_static_literals_t *li
* Parse all of the elements of a hash. Return true if a double splat was found.
*/
static bool
-parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *node) {
+parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *node, uint16_t depth) {
assert(PM_NODE_TYPE_P(node, PM_HASH_NODE) || PM_NODE_TYPE_P(node, PM_KEYWORD_HASH_NODE));
bool contains_keyword_splat = false;
@@ -13798,14 +13332,14 @@ parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *nod
// inner hash to share the static literals with the outer
// hash.
parser->current_hash_keys = literals;
- value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH);
+ value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH, (uint16_t) (depth + 1));
} else if (token_begins_expression_p(parser->current.type)) {
- value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH);
+ value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH, (uint16_t) (depth + 1));
} else {
pm_parser_scope_forwarding_keywords_check(parser, &operator);
}
- element = (pm_node_t *) pm_assoc_splat_node_create(parser, value, &operator);
+ element = UP(pm_assoc_splat_node_create(parser, value, &operator));
contains_keyword_splat = true;
break;
}
@@ -13813,18 +13347,18 @@ parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *nod
pm_token_t label = parser->current;
parser_lex(parser);
- pm_node_t *key = (pm_node_t *) pm_symbol_node_label_create(parser, &label);
+ pm_node_t *key = UP(pm_symbol_node_label_create(parser, &label));
pm_hash_key_static_literals_add(parser, literals, key);
pm_token_t operator = not_provided(parser);
pm_node_t *value = NULL;
if (token_begins_expression_p(parser->current.type)) {
- value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_HASH_EXPRESSION_AFTER_LABEL);
+ value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_HASH_EXPRESSION_AFTER_LABEL, (uint16_t) (depth + 1));
} else {
if (parser->encoding->isupper_char(label.start, (label.end - 1) - label.start)) {
pm_token_t constant = { .type = PM_TOKEN_CONSTANT, .start = label.start, .end = label.end - 1 };
- value = (pm_node_t *) pm_constant_read_node_create(parser, &constant);
+ value = UP(pm_constant_read_node_create(parser, &constant));
} else {
int depth = -1;
pm_token_t identifier = { .type = PM_TOKEN_IDENTIFIER, .start = label.start, .end = label.end - 1 };
@@ -13836,21 +13370,21 @@ parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *nod
}
if (depth == -1) {
- value = (pm_node_t *) pm_call_node_variable_call_create(parser, &identifier);
+ value = UP(pm_call_node_variable_call_create(parser, &identifier));
} else {
- value = (pm_node_t *) pm_local_variable_read_node_create(parser, &identifier, (uint32_t) depth);
+ value = UP(pm_local_variable_read_node_create(parser, &identifier, (uint32_t) depth));
}
}
value->location.end++;
- value = (pm_node_t *) pm_implicit_node_create(parser, value);
+ value = UP(pm_implicit_node_create(parser, value));
}
- element = (pm_node_t *) pm_assoc_node_create(parser, key, &operator, value);
+ element = UP(pm_assoc_node_create(parser, key, &operator, value));
break;
}
default: {
- pm_node_t *key = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_HASH_KEY);
+ pm_node_t *key = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, true, PM_ERR_HASH_KEY, (uint16_t) (depth + 1));
// Hash keys that are strings are automatically frozen. We will
// mark that here.
@@ -13868,8 +13402,8 @@ parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *nod
operator = parser->previous;
}
- pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_HASH_VALUE);
- element = (pm_node_t *) pm_assoc_node_create(parser, key, &operator, value);
+ pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_HASH_VALUE, (uint16_t) (depth + 1));
+ element = UP(pm_assoc_node_create(parser, key, &operator, value));
break;
}
}
@@ -13898,6 +13432,30 @@ parse_assocs(pm_parser_t *parser, pm_static_literals_t *literals, pm_node_t *nod
return contains_keyword_splat;
}
+static inline bool
+argument_allowed_for_bare_hash(pm_parser_t *parser, pm_node_t *argument) {
+ if (pm_symbol_node_label_p(argument)) {
+ return true;
+ }
+
+ switch (PM_NODE_TYPE(argument)) {
+ case PM_CALL_NODE: {
+ pm_call_node_t *cast = (pm_call_node_t *) argument;
+ if (cast->opening_loc.start == NULL && cast->arguments != NULL) {
+ if (PM_NODE_FLAG_P(cast->arguments, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS | PM_ARGUMENTS_NODE_FLAGS_CONTAINS_SPLAT)) {
+ return false;
+ }
+ if (cast->block != NULL) {
+ return false;
+ }
+ }
+ break;
+ }
+ default: break;
+ }
+ return accept1(parser, PM_TOKEN_EQUAL_GREATER);
+}
+
/**
* Append an argument to a list of arguments.
*/
@@ -13914,11 +13472,11 @@ parse_arguments_append(pm_parser_t *parser, pm_arguments_t *arguments, pm_node_t
* Parse a list of arguments.
*/
static void
-parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_forwarding, pm_token_type_t terminator) {
+parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_forwarding, pm_token_type_t terminator, uint16_t depth) {
pm_binding_power_t binding_power = pm_binding_powers[parser->current.type].left;
- // First we need to check if the next token is one that could be the start of
- // an argument. If it's not, then we can just return.
+ // First we need to check if the next token is one that could be the start
+ // of an argument. If it's not, then we can just return.
if (
match2(parser, terminator, PM_TOKEN_EOF) ||
(binding_power != PM_BINDING_POWER_UNSET && binding_power < PM_BINDING_POWER_RANGE) ||
@@ -13933,9 +13491,6 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
bool parsed_forwarding_arguments = false;
while (!match1(parser, PM_TOKEN_EOF)) {
- if (parsed_block_argument) {
- pm_parser_err_current(parser, PM_ERR_ARGUMENT_AFTER_BLOCK);
- }
if (parsed_forwarding_arguments) {
pm_parser_err_current(parser, PM_ERR_ARGUMENT_AFTER_FORWARDING_ELLIPSES);
}
@@ -13950,16 +13505,16 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
}
pm_keyword_hash_node_t *hash = pm_keyword_hash_node_create(parser);
- argument = (pm_node_t *) hash;
+ argument = UP(hash);
pm_static_literals_t hash_keys = { 0 };
- bool contains_keyword_splat = parse_assocs(parser, &hash_keys, (pm_node_t *) hash);
+ bool contains_keyword_splat = parse_assocs(parser, &hash_keys, UP(hash), (uint16_t) (depth + 1));
parse_arguments_append(parser, arguments, argument);
pm_node_flags_t flags = PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS;
if (contains_keyword_splat) flags |= PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT;
- pm_node_flag_set((pm_node_t *) arguments->arguments, flags);
+ pm_node_flag_set(UP(arguments->arguments), flags);
pm_static_literals_free(&hash_keys);
parsed_bare_hash = true;
@@ -13972,18 +13527,22 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
pm_node_t *expression = NULL;
if (token_begins_expression_p(parser->current.type)) {
- expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_EXPECT_ARGUMENT);
+ expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_EXPECT_ARGUMENT, (uint16_t) (depth + 1));
} else {
pm_parser_scope_forwarding_block_check(parser, &operator);
}
- argument = (pm_node_t *) pm_block_argument_node_create(parser, &operator, expression);
+ argument = UP(pm_block_argument_node_create(parser, &operator, expression));
if (parsed_block_argument) {
parse_arguments_append(parser, arguments, argument);
} else {
arguments->block = argument;
}
+ if (match1(parser, PM_TOKEN_COMMA)) {
+ pm_parser_err_current(parser, PM_ERR_ARGUMENT_AFTER_BLOCK);
+ }
+
parsed_block_argument = true;
break;
}
@@ -13993,15 +13552,18 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
if (match4(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_COMMA, PM_TOKEN_SEMICOLON, PM_TOKEN_BRACKET_RIGHT)) {
pm_parser_scope_forwarding_positionals_check(parser, &operator);
- argument = (pm_node_t *) pm_splat_node_create(parser, &operator, NULL);
+ argument = UP(pm_splat_node_create(parser, &operator, NULL));
+ if (parsed_bare_hash) {
+ pm_parser_err_previous(parser, PM_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT);
+ }
} else {
- pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT);
+ pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT, (uint16_t) (depth + 1));
if (parsed_bare_hash) {
pm_parser_err(parser, operator.start, expression->location.end, PM_ERR_ARGUMENT_SPLAT_AFTER_ASSOC_SPLAT);
}
- argument = (pm_node_t *) pm_splat_node_create(parser, &operator, expression);
+ argument = UP(pm_splat_node_create(parser, &operator, expression));
}
parse_arguments_append(parser, arguments, argument);
@@ -14012,35 +13574,46 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
parser_lex(parser);
if (token_begins_expression_p(parser->current.type)) {
- // If the token begins an expression then this ... was not actually
- // argument forwarding but was instead a range.
+ // If the token begins an expression then this ... was
+ // not actually argument forwarding but was instead a
+ // range.
pm_token_t operator = parser->previous;
- pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_RANGE, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
- argument = (pm_node_t *) pm_range_node_create(parser, NULL, &operator, right);
+ pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_RANGE, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
+
+ // If we parse a range, we need to validate that we
+ // didn't accidentally violate the nonassoc rules of the
+ // ... operator.
+ if (PM_NODE_TYPE_P(right, PM_RANGE_NODE)) {
+ pm_range_node_t *range = (pm_range_node_t *) right;
+ pm_parser_err(parser, range->operator_loc.start, range->operator_loc.end, PM_ERR_UNEXPECTED_RANGE_OPERATOR);
+ }
+
+ argument = UP(pm_range_node_create(parser, NULL, &operator, right));
} else {
pm_parser_scope_forwarding_all_check(parser, &parser->previous);
if (parsed_first_argument && terminator == PM_TOKEN_EOF) {
pm_parser_err_previous(parser, PM_ERR_ARGUMENT_FORWARDING_UNBOUND);
}
- argument = (pm_node_t *) pm_forwarding_arguments_node_create(parser, &parser->previous);
+ argument = UP(pm_forwarding_arguments_node_create(parser, &parser->previous));
parse_arguments_append(parser, arguments, argument);
+ pm_node_flag_set(UP(arguments->arguments), PM_ARGUMENTS_NODE_FLAGS_CONTAINS_FORWARDING);
arguments->has_forwarding = true;
parsed_forwarding_arguments = true;
break;
}
}
}
- /* fallthrough */
+ PRISM_FALLTHROUGH
default: {
if (argument == NULL) {
- argument = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, !parsed_first_argument, PM_ERR_EXPECT_ARGUMENT);
+ argument = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, !parsed_first_argument, true, PM_ERR_EXPECT_ARGUMENT, (uint16_t) (depth + 1));
}
bool contains_keywords = false;
bool contains_keyword_splat = false;
- if (pm_symbol_node_label_p(argument) || accept1(parser, PM_TOKEN_EQUAL_GREATER)) {
+ if (argument_allowed_for_bare_hash(parser, argument)){
if (parsed_bare_hash) {
pm_parser_err_previous(parser, PM_ERR_ARGUMENT_BARE_HASH);
}
@@ -14060,25 +13633,22 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
pm_hash_key_static_literals_add(parser, &hash_keys, argument);
// Finish parsing the one we are part way through.
- pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_HASH_VALUE);
- argument = (pm_node_t *) pm_assoc_node_create(parser, argument, &operator, value);
+ pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_HASH_VALUE, (uint16_t) (depth + 1));
+ argument = UP(pm_assoc_node_create(parser, argument, &operator, value));
pm_keyword_hash_node_elements_append(bare_hash, argument);
- argument = (pm_node_t *) bare_hash;
+ argument = UP(bare_hash);
// Then parse more if we have a comma
if (accept1(parser, PM_TOKEN_COMMA) && (
token_begins_expression_p(parser->current.type) ||
match2(parser, PM_TOKEN_USTAR_STAR, PM_TOKEN_LABEL)
)) {
- contains_keyword_splat = parse_assocs(parser, &hash_keys, (pm_node_t *) bare_hash);
+ contains_keyword_splat = parse_assocs(parser, &hash_keys, UP(bare_hash), (uint16_t) (depth + 1));
}
pm_static_literals_free(&hash_keys);
parsed_bare_hash = true;
- } else if (accept1(parser, PM_TOKEN_KEYWORD_IN)) {
- // TODO: Could we solve this with binding powers instead?
- pm_parser_err_current(parser, PM_ERR_ARGUMENT_IN);
}
parse_arguments_append(parser, arguments, argument);
@@ -14086,7 +13656,7 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
pm_node_flags_t flags = 0;
if (contains_keywords) flags |= PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS;
if (contains_keyword_splat) flags |= PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORD_SPLAT;
- pm_node_flag_set((pm_node_t *) arguments->arguments, flags);
+ pm_node_flag_set(UP(arguments->arguments), flags);
break;
}
@@ -14097,23 +13667,43 @@ parse_arguments(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_for
// If parsing the argument failed, we need to stop parsing arguments.
if (PM_NODE_TYPE_P(argument, PM_MISSING_NODE) || parser->recovering) break;
- // If the terminator of these arguments is not EOF, then we have a specific
- // token we're looking for. In that case we can accept a newline here
- // because it is not functioning as a statement terminator.
- if (terminator != PM_TOKEN_EOF) accept1(parser, PM_TOKEN_NEWLINE);
+ // If the terminator of these arguments is not EOF, then we have a
+ // specific token we're looking for. In that case we can accept a
+ // newline here because it is not functioning as a statement terminator.
+ bool accepted_newline = false;
+ if (terminator != PM_TOKEN_EOF) {
+ accepted_newline = accept1(parser, PM_TOKEN_NEWLINE);
+ }
if (parser->previous.type == PM_TOKEN_COMMA && parsed_bare_hash) {
- // If we previously were on a comma and we just parsed a bare hash, then
- // we want to continue parsing arguments. This is because the comma was
- // grabbed up by the hash parser.
+ // If we previously were on a comma and we just parsed a bare hash,
+ // then we want to continue parsing arguments. This is because the
+ // comma was grabbed up by the hash parser.
+ } else if (accept1(parser, PM_TOKEN_COMMA)) {
+ // If there was a comma, then we need to check if we also accepted a
+ // newline. If we did, then this is a syntax error.
+ if (accepted_newline) {
+ pm_parser_err_previous(parser, PM_ERR_INVALID_COMMA);
+ }
+
+ // If this is a command call and an argument takes a block,
+ // there can be no further arguments. For example,
+ // `foo(bar 1 do end, 2)` should be rejected.
+ if (PM_NODE_TYPE_P(argument, PM_CALL_NODE)) {
+ pm_call_node_t *call = (pm_call_node_t *) argument;
+ if (call->opening_loc.start == NULL && call->arguments != NULL && call->block != NULL) {
+ pm_parser_err_previous(parser, PM_ERR_INVALID_COMMA);
+ break;
+ }
+ }
} else {
- // If there is no comma at the end of the argument list then we're done
- // parsing arguments and can break out of this loop.
- if (!accept1(parser, PM_TOKEN_COMMA)) break;
+ // If there is no comma at the end of the argument list then we're
+ // done parsing arguments and can break out of this loop.
+ break;
}
- // If we hit the terminator, then that means we have a trailing comma so we
- // can accept that output as well.
+ // If we hit the terminator, then that means we have a trailing comma so
+ // we can accept that output as well.
if (match1(parser, terminator)) break;
}
}
@@ -14143,33 +13733,33 @@ parse_required_destructured_parameter(pm_parser_t *parser) {
// commas, so here we'll assume this is a mistake of the user not
// knowing it's not allowed here.
if (node->lefts.size > 0 && match1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) {
- param = (pm_node_t *) pm_implicit_rest_node_create(parser, &parser->previous);
+ param = UP(pm_implicit_rest_node_create(parser, &parser->previous));
pm_multi_target_node_targets_append(parser, node, param);
pm_parser_err_current(parser, PM_ERR_PARAMETER_WILD_LOOSE_COMMA);
break;
}
if (match1(parser, PM_TOKEN_PARENTHESIS_LEFT)) {
- param = (pm_node_t *) parse_required_destructured_parameter(parser);
+ param = UP(parse_required_destructured_parameter(parser));
} else if (accept1(parser, PM_TOKEN_USTAR)) {
pm_token_t star = parser->previous;
pm_node_t *value = NULL;
if (accept1(parser, PM_TOKEN_IDENTIFIER)) {
pm_token_t name = parser->previous;
- value = (pm_node_t *) pm_required_parameter_node_create(parser, &name);
+ value = UP(pm_required_parameter_node_create(parser, &name));
if (pm_parser_parameter_name_check(parser, &name)) {
pm_node_flag_set_repeated_parameter(value);
}
pm_parser_local_add_token(parser, &name, 1);
}
- param = (pm_node_t *) pm_splat_node_create(parser, &star, value);
+ param = UP(pm_splat_node_create(parser, &star, value));
} else {
expect1(parser, PM_TOKEN_IDENTIFIER, PM_ERR_EXPECT_IDENT_REQ_PARAMETER);
pm_token_t name = parser->previous;
- param = (pm_node_t *) pm_required_parameter_node_create(parser, &name);
+ param = UP(pm_required_parameter_node_create(parser, &name));
if (pm_parser_parameter_name_check(parser, &name)) {
pm_node_flag_set_repeated_parameter(param);
}
@@ -14266,19 +13856,23 @@ parse_parameters(
pm_binding_power_t binding_power,
bool uses_parentheses,
bool allows_trailing_comma,
- bool allows_forwarding_parameters
+ bool allows_forwarding_parameters,
+ bool accepts_blocks_in_defaults,
+ bool in_block,
+ uint16_t depth
) {
- pm_parameters_node_t *params = pm_parameters_node_create(parser);
- bool looping = true;
-
pm_do_loop_stack_push(parser, false);
+
+ pm_parameters_node_t *params = pm_parameters_node_create(parser);
pm_parameters_order_t order = PM_PARAMETERS_ORDER_NONE;
- do {
+ while (true) {
+ bool parsing = true;
+
switch (parser->current.type) {
case PM_TOKEN_PARENTHESIS_LEFT: {
update_parameter_state(parser, &parser->current, &order);
- pm_node_t *param = (pm_node_t *) parse_required_destructured_parameter(parser);
+ pm_node_t *param = UP(parse_required_destructured_parameter(parser));
if (order > PM_PARAMETERS_ORDER_AFTER_OPTIONAL) {
pm_parameters_node_requireds_append(params, param);
@@ -14307,13 +13901,13 @@ parse_parameters(
pm_block_parameter_node_t *param = pm_block_parameter_node_create(parser, &name, &operator);
if (repeated) {
- pm_node_flag_set_repeated_parameter((pm_node_t *)param);
+ pm_node_flag_set_repeated_parameter(UP(param));
}
if (params->block == NULL) {
pm_parameters_node_block_set(params, param);
} else {
- pm_parser_err_node(parser, (pm_node_t *) param, PM_ERR_PARAMETER_BLOCK_MULTI);
- pm_parameters_node_posts_append(params, (pm_node_t *) param);
+ pm_parser_err_node(parser, UP(param), PM_ERR_PARAMETER_BLOCK_MULTI);
+ pm_parameters_node_posts_append(params, UP(param));
}
break;
@@ -14338,7 +13932,7 @@ parse_parameters(
params->keyword_rest = NULL;
}
- pm_parameters_node_keyword_rest_set(params, (pm_node_t *) param);
+ pm_parameters_node_keyword_rest_set(params, UP(param));
break;
}
case PM_TOKEN_CLASS_VARIABLE:
@@ -14377,25 +13971,29 @@ parse_parameters(
bool repeated = pm_parser_parameter_name_check(parser, &name);
pm_parser_local_add_token(parser, &name, 1);
- if (accept1(parser, PM_TOKEN_EQUAL)) {
- pm_token_t operator = parser->previous;
+ if (match1(parser, PM_TOKEN_EQUAL)) {
+ pm_token_t operator = parser->current;
context_push(parser, PM_CONTEXT_DEFAULT_PARAMS);
+ parser_lex(parser);
pm_constant_id_t name_id = pm_parser_constant_id_token(parser, &name);
- uint32_t reads = pm_locals_reads(&parser->current_scope->locals, name_id);
+ uint32_t reads = parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3 ? pm_locals_reads(&parser->current_scope->locals, name_id) : 0;
+
+ if (accepts_blocks_in_defaults) pm_accepts_block_stack_push(parser, true);
+ pm_node_t *value = parse_value_expression(parser, binding_power, false, false, PM_ERR_PARAMETER_NO_DEFAULT, (uint16_t) (depth + 1));
+ if (accepts_blocks_in_defaults) pm_accepts_block_stack_pop(parser);
- pm_node_t *value = parse_value_expression(parser, binding_power, false, PM_ERR_PARAMETER_NO_DEFAULT);
pm_optional_parameter_node_t *param = pm_optional_parameter_node_create(parser, &name, &operator, value);
if (repeated) {
- pm_node_flag_set_repeated_parameter((pm_node_t *)param);
+ pm_node_flag_set_repeated_parameter(UP(param));
}
pm_parameters_node_optionals_append(params, param);
// If the value of the parameter increased the number of
// reads of that parameter, then we need to warn that we
// have a circular definition.
- if (pm_locals_reads(&parser->current_scope->locals, name_id) != reads) {
+ if ((parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3) && (pm_locals_reads(&parser->current_scope->locals, name_id) != reads)) {
PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, name, PM_ERR_PARAMETER_CIRCULAR);
}
@@ -14405,28 +14003,30 @@ parse_parameters(
// then we can put a missing node in its place and stop parsing the
// parameters entirely now.
if (parser->recovering) {
- looping = false;
+ parsing = false;
break;
}
} else if (order > PM_PARAMETERS_ORDER_AFTER_OPTIONAL) {
pm_required_parameter_node_t *param = pm_required_parameter_node_create(parser, &name);
if (repeated) {
- pm_node_flag_set_repeated_parameter((pm_node_t *)param);
+ pm_node_flag_set_repeated_parameter(UP(param));
}
- pm_parameters_node_requireds_append(params, (pm_node_t *) param);
+ pm_parameters_node_requireds_append(params, UP(param));
} else {
pm_required_parameter_node_t *param = pm_required_parameter_node_create(parser, &name);
if (repeated) {
- pm_node_flag_set_repeated_parameter((pm_node_t *)param);
+ pm_node_flag_set_repeated_parameter(UP(param));
}
- pm_parameters_node_posts_append(params, (pm_node_t *) param);
+ pm_parameters_node_posts_append(params, UP(param));
}
break;
}
case PM_TOKEN_LABEL: {
- if (!uses_parentheses) parser->in_keyword_arg = true;
+ if (!uses_parentheses && !in_block) parser->in_keyword_arg = true;
update_parameter_state(parser, &parser->current, &order);
+
+ context_push(parser, PM_CONTEXT_DEFAULT_PARAMS);
parser_lex(parser);
pm_token_t name = parser->previous;
@@ -14446,24 +14046,30 @@ parse_parameters(
case PM_TOKEN_COMMA:
case PM_TOKEN_PARENTHESIS_RIGHT:
case PM_TOKEN_PIPE: {
- pm_node_t *param = (pm_node_t *) pm_required_keyword_parameter_node_create(parser, &name);
+ context_pop(parser);
+
+ pm_node_t *param = UP(pm_required_keyword_parameter_node_create(parser, &name));
if (repeated) {
pm_node_flag_set_repeated_parameter(param);
}
+
pm_parameters_node_keywords_append(params, param);
break;
}
case PM_TOKEN_SEMICOLON:
case PM_TOKEN_NEWLINE: {
+ context_pop(parser);
+
if (uses_parentheses) {
- looping = false;
+ parsing = false;
break;
}
- pm_node_t *param = (pm_node_t *) pm_required_keyword_parameter_node_create(parser, &name);
+ pm_node_t *param = UP(pm_required_keyword_parameter_node_create(parser, &name));
if (repeated) {
pm_node_flag_set_repeated_parameter(param);
}
+
pm_parameters_node_keywords_append(params, param);
break;
}
@@ -14471,33 +14077,35 @@ parse_parameters(
pm_node_t *param;
if (token_begins_expression_p(parser->current.type)) {
- context_push(parser, PM_CONTEXT_DEFAULT_PARAMS);
-
pm_constant_id_t name_id = pm_parser_constant_id_token(parser, &local);
- uint32_t reads = pm_locals_reads(&parser->current_scope->locals, name_id);
- pm_node_t *value = parse_value_expression(parser, binding_power, false, PM_ERR_PARAMETER_NO_DEFAULT_KW);
+ uint32_t reads = parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3 ? pm_locals_reads(&parser->current_scope->locals, name_id) : 0;
+
+ if (accepts_blocks_in_defaults) pm_accepts_block_stack_push(parser, true);
+ pm_node_t *value = parse_value_expression(parser, binding_power, false, false, PM_ERR_PARAMETER_NO_DEFAULT_KW, (uint16_t) (depth + 1));
+ if (accepts_blocks_in_defaults) pm_accepts_block_stack_pop(parser);
- if (pm_locals_reads(&parser->current_scope->locals, name_id) != reads) {
+ if (parser->version <= PM_OPTIONS_VERSION_CRUBY_3_3 && (pm_locals_reads(&parser->current_scope->locals, name_id) != reads)) {
PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, local, PM_ERR_PARAMETER_CIRCULAR);
}
- context_pop(parser);
- param = (pm_node_t *) pm_optional_keyword_parameter_node_create(parser, &name, value);
+ param = UP(pm_optional_keyword_parameter_node_create(parser, &name, value));
}
else {
- param = (pm_node_t *) pm_required_keyword_parameter_node_create(parser, &name);
+ param = UP(pm_required_keyword_parameter_node_create(parser, &name));
}
if (repeated) {
pm_node_flag_set_repeated_parameter(param);
}
+
+ context_pop(parser);
pm_parameters_node_keywords_append(params, param);
// If parsing the value of the parameter resulted in error recovery,
// then we can put a missing node in its place and stop parsing the
// parameters entirely now.
if (parser->recovering) {
- looping = false;
+ parsing = false;
break;
}
}
@@ -14524,7 +14132,7 @@ parse_parameters(
parser->current_scope->parameters |= PM_SCOPE_PARAMETERS_FORWARDING_POSITIONALS;
}
- pm_node_t *param = (pm_node_t *) pm_rest_parameter_node_create(parser, &operator, &name);
+ pm_node_t *param = UP(pm_rest_parameter_node_create(parser, &operator, &name));
if (repeated) {
pm_node_flag_set_repeated_parameter(param);
}
@@ -14552,7 +14160,7 @@ parse_parameters(
pm_parser_err_previous(parser, PM_ERR_PARAMETER_UNEXPECTED_NO_KW);
}
- param = (pm_node_t *) pm_no_keywords_parameter_node_create(parser, &operator, &parser->previous);
+ param = UP(pm_no_keywords_parameter_node_create(parser, &operator, &parser->previous));
} else {
pm_token_t name;
@@ -14566,7 +14174,7 @@ parse_parameters(
parser->current_scope->parameters |= PM_SCOPE_PARAMETERS_FORWARDING_KEYWORDS;
}
- param = (pm_node_t *) pm_keyword_rest_parameter_node_create(parser, &operator, &name);
+ param = UP(pm_keyword_rest_parameter_node_create(parser, &operator, &name));
if (repeated) {
pm_node_flag_set_repeated_parameter(param);
}
@@ -14583,42 +14191,160 @@ parse_parameters(
}
default:
if (parser->previous.type == PM_TOKEN_COMMA) {
- if (allows_trailing_comma) {
+ if (allows_trailing_comma && order >= PM_PARAMETERS_ORDER_NAMED) {
// If we get here, then we have a trailing comma in a
// block parameter list.
- pm_node_t *param = (pm_node_t *) pm_implicit_rest_node_create(parser, &parser->previous);
+ pm_node_t *param = UP(pm_implicit_rest_node_create(parser, &parser->previous));
if (params->rest == NULL) {
pm_parameters_node_rest_set(params, param);
} else {
- pm_parser_err_node(parser, (pm_node_t *) param, PM_ERR_PARAMETER_SPLAT_MULTI);
- pm_parameters_node_posts_append(params, (pm_node_t *) param);
+ pm_parser_err_node(parser, UP(param), PM_ERR_PARAMETER_SPLAT_MULTI);
+ pm_parameters_node_posts_append(params, UP(param));
}
} else {
pm_parser_err_previous(parser, PM_ERR_PARAMETER_WILD_LOOSE_COMMA);
}
}
- looping = false;
+ parsing = false;
break;
}
- if (looping && uses_parentheses) {
- accept1(parser, PM_TOKEN_NEWLINE);
+ // If we hit some kind of issue while parsing the parameter, this would
+ // have been set to false. In that case, we need to break out of the
+ // loop.
+ if (!parsing) break;
+
+ bool accepted_newline = false;
+ if (uses_parentheses) {
+ accepted_newline = accept1(parser, PM_TOKEN_NEWLINE);
+ }
+
+ if (accept1(parser, PM_TOKEN_COMMA)) {
+ // If there was a comma, but we also accepted a newline, then this
+ // is a syntax error.
+ if (accepted_newline) {
+ pm_parser_err_previous(parser, PM_ERR_INVALID_COMMA);
+ }
+ } else {
+ // If there was no comma, then we're done parsing parameters.
+ break;
}
- } while (looping && accept1(parser, PM_TOKEN_COMMA));
+ }
pm_do_loop_stack_pop(parser);
// If we don't have any parameters, return `NULL` instead of an empty `ParametersNode`.
if (params->base.location.start == params->base.location.end) {
- pm_node_destroy(parser, (pm_node_t *) params);
+ pm_node_destroy(parser, UP(params));
return NULL;
}
return params;
}
+/**
+ * Accepts a parser returns the index of the last newline in the file that was
+ * ecorded before the current token within the newline list.
+ */
+static size_t
+token_newline_index(const pm_parser_t *parser) {
+ if (parser->heredoc_end == NULL) {
+ // This is the common case. In this case we can look at the previously
+ // recorded newline in the newline list and subtract from the current
+ // offset.
+ return parser->newline_list.size - 1;
+ } else {
+ // This is unlikely. This is the case that we have already parsed the
+ // start of a heredoc, so we cannot rely on looking at the previous
+ // offset of the newline list, and instead must go through the whole
+ // process of a binary search for the line number.
+ return (size_t) pm_newline_list_line(&parser->newline_list, parser->current.start, 0);
+ }
+}
+
+/**
+ * Accepts a parser, a newline index, and a token and returns the column. The
+ * important piece of this is that it expands tabs out to the next tab stop.
+ */
+static int64_t
+token_column(const pm_parser_t *parser, size_t newline_index, const pm_token_t *token, bool break_on_non_space) {
+ const uint8_t *cursor = parser->start + parser->newline_list.offsets[newline_index];
+ const uint8_t *end = token->start;
+
+ // Skip over the BOM if it is present.
+ if (
+ newline_index == 0 &&
+ parser->start[0] == 0xef &&
+ parser->start[1] == 0xbb &&
+ parser->start[2] == 0xbf
+ ) cursor += 3;
+
+ int64_t column = 0;
+ for (; cursor < end; cursor++) {
+ switch (*cursor) {
+ case '\t':
+ column = ((column / PM_TAB_WHITESPACE_SIZE) + 1) * PM_TAB_WHITESPACE_SIZE;
+ break;
+ case ' ':
+ column++;
+ break;
+ default:
+ column++;
+ if (break_on_non_space) return -1;
+ break;
+ }
+ }
+
+ return column;
+}
+
+/**
+ * Accepts a parser, two newline indices, and pointers to two tokens. This
+ * function warns if the indentation of the two tokens does not match.
+ */
+static void
+parser_warn_indentation_mismatch(pm_parser_t *parser, size_t opening_newline_index, const pm_token_t *opening_token, bool if_after_else, bool allow_indent) {
+ // If these warnings are disabled (unlikely), then we can just return.
+ if (!parser->warn_mismatched_indentation) return;
+
+ // If the tokens are on the same line, we do not warn.
+ size_t closing_newline_index = token_newline_index(parser);
+ if (opening_newline_index == closing_newline_index) return;
+
+ // If the opening token has anything other than spaces or tabs before it,
+ // then we do not warn. This is unless we are matching up an `if`/`end` pair
+ // and the `if` immediately follows an `else` keyword.
+ int64_t opening_column = token_column(parser, opening_newline_index, opening_token, !if_after_else);
+ if (!if_after_else && (opening_column == -1)) return;
+
+ // Get a reference to the closing token off the current parser. This assumes
+ // that the caller has placed this in the correct position.
+ pm_token_t *closing_token = &parser->current;
+
+ // If the tokens are at the same indentation, we do not warn.
+ int64_t closing_column = token_column(parser, closing_newline_index, closing_token, true);
+ if ((closing_column == -1) || (opening_column == closing_column)) return;
+
+ // If the closing column is greater than the opening column and we are
+ // allowing indentation, then we do not warn.
+ if (allow_indent && (closing_column > opening_column)) return;
+
+ // Otherwise, add a warning.
+ PM_PARSER_WARN_FORMAT(
+ parser,
+ closing_token->start,
+ closing_token->end,
+ PM_WARN_INDENTATION_MISMATCH,
+ (int) (closing_token->end - closing_token->start),
+ (const char *) closing_token->start,
+ (int) (opening_token->end - opening_token->start),
+ (const char *) opening_token->start,
+ ((int32_t) opening_newline_index) + parser->start_line
+ );
+}
+
typedef enum {
PM_RESCUES_BEGIN = 1,
PM_RESCUES_BLOCK,
@@ -14634,10 +14360,13 @@ typedef enum {
* nodes pointing to each other from the top.
*/
static inline void
-parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, pm_rescues_type_t type) {
+parse_rescues(pm_parser_t *parser, size_t opening_newline_index, const pm_token_t *opening, pm_begin_node_t *parent_node, pm_rescues_type_t type, uint16_t depth) {
pm_rescue_node_t *current = NULL;
- while (accept1(parser, PM_TOKEN_KEYWORD_RESCUE)) {
+ while (match1(parser, PM_TOKEN_KEYWORD_RESCUE)) {
+ if (opening != NULL) parser_warn_indentation_mismatch(parser, opening_newline_index, opening, false, false);
+ parser_lex(parser);
+
pm_rescue_node_t *rescue = pm_rescue_node_create(parser, &parser->previous);
switch (parser->current.type) {
@@ -14648,8 +14377,8 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, pm_rescues_type
parser_lex(parser);
pm_rescue_node_operator_set(rescue, &parser->previous);
- pm_node_t *reference = parse_expression(parser, PM_BINDING_POWER_INDEX, false, PM_ERR_RESCUE_VARIABLE);
- reference = parse_target(parser, reference, false);
+ pm_node_t *reference = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_RESCUE_VARIABLE, (uint16_t) (depth + 1));
+ reference = parse_target(parser, reference, false, false);
pm_rescue_node_reference_set(rescue, reference);
break;
@@ -14657,8 +14386,8 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, pm_rescues_type
case PM_TOKEN_NEWLINE:
case PM_TOKEN_SEMICOLON:
case PM_TOKEN_KEYWORD_THEN:
- // Here we have a terminator for the rescue keyword, in which case we're
- // going to just continue on.
+ // Here we have a terminator for the rescue keyword, in which
+ // case we're going to just continue on.
break;
default: {
if (token_begins_expression_p(parser->current.type) || match1(parser, PM_TOKEN_USTAR)) {
@@ -14666,7 +14395,7 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, pm_rescues_type
// we'll attempt to parse it here and any others delimited by commas.
do {
- pm_node_t *expression = parse_starred_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_RESCUE_EXPRESSION);
+ pm_node_t *expression = parse_starred_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_RESCUE_EXPRESSION, (uint16_t) (depth + 1));
pm_rescue_node_exceptions_append(rescue, expression);
// If we hit a newline, then this is the end of the rescue expression. We
@@ -14678,8 +14407,8 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, pm_rescues_type
if (accept1(parser, PM_TOKEN_EQUAL_GREATER)) {
pm_rescue_node_operator_set(rescue, &parser->previous);
- pm_node_t *reference = parse_expression(parser, PM_BINDING_POWER_INDEX, false, PM_ERR_RESCUE_VARIABLE);
- reference = parse_target(parser, reference, false);
+ pm_node_t *reference = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_RESCUE_VARIABLE, (uint16_t) (depth + 1));
+ reference = parse_target(parser, reference, false, false);
pm_rescue_node_reference_set(rescue, reference);
break;
@@ -14690,9 +14419,12 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, pm_rescues_type
}
if (accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)) {
- accept1(parser, PM_TOKEN_KEYWORD_THEN);
+ if (accept1(parser, PM_TOKEN_KEYWORD_THEN)) {
+ rescue->then_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(&parser->previous);
+ }
} else {
expect1(parser, PM_TOKEN_KEYWORD_THEN, PM_ERR_RESCUE_TERM);
+ rescue->then_keyword_loc = PM_OPTIONAL_LOCATION_TOKEN_VALUE(&parser->previous);
}
if (!match3(parser, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_END)) {
@@ -14710,7 +14442,7 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, pm_rescues_type
default: assert(false && "unreachable"); context = PM_CONTEXT_BEGIN_RESCUE; break;
}
- pm_statements_node_t *statements = parse_statements(parser, context);
+ pm_statements_node_t *statements = parse_statements(parser, context, (uint16_t) (depth + 1));
if (statements != NULL) pm_rescue_node_statements_set(rescue, statements);
pm_accepts_block_stack_pop(parser);
@@ -14720,26 +14452,34 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, pm_rescues_type
if (current == NULL) {
pm_begin_node_rescue_clause_set(parent_node, rescue);
} else {
- pm_rescue_node_consequent_set(current, rescue);
+ pm_rescue_node_subsequent_set(current, rescue);
}
current = rescue;
}
// The end node locations on rescue nodes will not be set correctly
- // since we won't know the end until we've found all consequent
+ // since we won't know the end until we've found all subsequent
// clauses. This sets the end location on all rescues once we know it.
- if (current) {
+ if (current != NULL) {
const uint8_t *end_to_set = current->base.location.end;
- current = parent_node->rescue_clause;
- while (current) {
- current->base.location.end = end_to_set;
- current = current->consequent;
+ pm_rescue_node_t *clause = parent_node->rescue_clause;
+
+ while (clause != NULL) {
+ clause->base.location.end = end_to_set;
+ clause = clause->subsequent;
}
}
- if (accept1(parser, PM_TOKEN_KEYWORD_ELSE)) {
- pm_token_t else_keyword = parser->previous;
+ pm_token_t else_keyword;
+ if (match1(parser, PM_TOKEN_KEYWORD_ELSE)) {
+ if (opening != NULL) parser_warn_indentation_mismatch(parser, opening_newline_index, opening, false, false);
+ opening_newline_index = token_newline_index(parser);
+
+ else_keyword = parser->current;
+ opening = &else_keyword;
+
+ parser_lex(parser);
accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
pm_statements_node_t *else_statements = NULL;
@@ -14755,10 +14495,10 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, pm_rescues_type
case PM_RESCUES_LAMBDA: context = PM_CONTEXT_LAMBDA_ELSE; break;
case PM_RESCUES_MODULE: context = PM_CONTEXT_MODULE_ELSE; break;
case PM_RESCUES_SCLASS: context = PM_CONTEXT_SCLASS_ELSE; break;
- default: assert(false && "unreachable"); context = PM_CONTEXT_BEGIN_RESCUE; break;
+ default: assert(false && "unreachable"); context = PM_CONTEXT_BEGIN_ELSE; break;
}
- else_statements = parse_statements(parser, context);
+ else_statements = parse_statements(parser, context, (uint16_t) (depth + 1));
pm_accepts_block_stack_pop(parser);
accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
@@ -14766,10 +14506,17 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, pm_rescues_type
pm_else_node_t *else_clause = pm_else_node_create(parser, &else_keyword, else_statements, &parser->current);
pm_begin_node_else_clause_set(parent_node, else_clause);
+
+ // If we don't have a `current` rescue node, then this is a dangling
+ // else, and it's an error.
+ if (current == NULL) pm_parser_err_node(parser, UP(else_clause), PM_ERR_BEGIN_LONELY_ELSE);
}
- if (accept1(parser, PM_TOKEN_KEYWORD_ENSURE)) {
- pm_token_t ensure_keyword = parser->previous;
+ if (match1(parser, PM_TOKEN_KEYWORD_ENSURE)) {
+ if (opening != NULL) parser_warn_indentation_mismatch(parser, opening_newline_index, opening, false, false);
+ pm_token_t ensure_keyword = parser->current;
+
+ parser_lex(parser);
accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
pm_statements_node_t *ensure_statements = NULL;
@@ -14788,7 +14535,7 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, pm_rescues_type
default: assert(false && "unreachable"); context = PM_CONTEXT_BEGIN_RESCUE; break;
}
- ensure_statements = parse_statements(parser, context);
+ ensure_statements = parse_statements(parser, context, (uint16_t) (depth + 1));
pm_accepts_block_stack_pop(parser);
accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
@@ -14798,7 +14545,8 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, pm_rescues_type
pm_begin_node_ensure_clause_set(parent_node, ensure_clause);
}
- if (parser->current.type == PM_TOKEN_KEYWORD_END) {
+ if (match1(parser, PM_TOKEN_KEYWORD_END)) {
+ if (opening != NULL) parser_warn_indentation_mismatch(parser, opening_newline_index, opening, false, false);
pm_begin_node_end_keyword_set(parent_node, &parser->current);
} else {
pm_token_t end_keyword = (pm_token_t) { .type = PM_TOKEN_MISSING, .start = parser->previous.end, .end = parser->previous.end };
@@ -14811,11 +14559,11 @@ parse_rescues(pm_parser_t *parser, pm_begin_node_t *parent_node, pm_rescues_type
* class, module, def, etc.).
*/
static pm_begin_node_t *
-parse_rescues_implicit_begin(pm_parser_t *parser, const uint8_t *start, pm_statements_node_t *statements, pm_rescues_type_t type) {
+parse_rescues_implicit_begin(pm_parser_t *parser, size_t opening_newline_index, const pm_token_t *opening, const uint8_t *start, pm_statements_node_t *statements, pm_rescues_type_t type, uint16_t depth) {
pm_token_t begin_keyword = not_provided(parser);
pm_begin_node_t *node = pm_begin_node_create(parser, &begin_keyword, statements);
- parse_rescues(parser, node, type);
+ parse_rescues(parser, opening_newline_index, opening, node, type, (uint16_t) (depth + 1));
node->base.location.start = start;
return node;
@@ -14829,17 +14577,28 @@ parse_block_parameters(
pm_parser_t *parser,
bool allows_trailing_comma,
const pm_token_t *opening,
- bool is_lambda_literal
+ bool is_lambda_literal,
+ bool accepts_blocks_in_defaults,
+ uint16_t depth
) {
pm_parameters_node_t *parameters = NULL;
if (!match1(parser, PM_TOKEN_SEMICOLON)) {
+ if (!is_lambda_literal) {
+ context_push(parser, PM_CONTEXT_BLOCK_PARAMETERS);
+ }
parameters = parse_parameters(
parser,
is_lambda_literal ? PM_BINDING_POWER_DEFINED : PM_BINDING_POWER_INDEX,
false,
allows_trailing_comma,
- false
+ false,
+ accepts_blocks_in_defaults,
+ true,
+ (uint16_t) (depth + 1)
);
+ if (!is_lambda_literal) {
+ context_pop(parser);
+ }
}
pm_block_parameters_node_t *block_parameters = pm_block_parameters_node_create(parser, parameters, opening);
@@ -14874,7 +14633,7 @@ parse_block_parameters(
pm_parser_local_add_token(parser, &parser->previous, 1);
pm_block_local_variable_node_t *local = pm_block_local_variable_node_create(parser, &parser->previous);
- if (repeated) pm_node_flag_set_repeated_parameter((pm_node_t *) local);
+ if (repeated) pm_node_flag_set_repeated_parameter(UP(local));
pm_block_parameters_node_append_local(block_parameters, local);
} while (accept1(parser, PM_TOKEN_COMMA));
@@ -14978,11 +14737,11 @@ parse_blocklike_parameters(pm_parser_t *parser, pm_node_t *parameters, const pm_
}
const pm_location_t location = { .start = opening->start, .end = closing->end };
- return (pm_node_t *) pm_numbered_parameters_node_create(parser, &location, numbered_parameter);
+ return UP(pm_numbered_parameters_node_create(parser, &location, numbered_parameter));
}
if (it_parameter) {
- return (pm_node_t *) pm_it_parameters_node_create(parser, opening, closing);
+ return UP(pm_it_parameters_node_create(parser, opening, closing));
}
return NULL;
@@ -14992,7 +14751,7 @@ parse_blocklike_parameters(pm_parser_t *parser, pm_node_t *parameters, const pm_
* Parse a block.
*/
static pm_block_node_t *
-parse_block(pm_parser_t *parser) {
+parse_block(pm_parser_t *parser, uint16_t depth) {
pm_token_t opening = parser->previous;
accept1(parser, PM_TOKEN_NEWLINE);
@@ -15008,7 +14767,7 @@ parse_block(pm_parser_t *parser) {
parser->command_start = true;
parser_lex(parser);
} else {
- block_parameters = parse_block_parameters(parser, true, &block_parameters_opening, false);
+ block_parameters = parse_block_parameters(parser, true, &block_parameters_opening, false, true, (uint16_t) (depth + 1));
accept1(parser, PM_TOKEN_NEWLINE);
parser->command_start = true;
expect1(parser, PM_TOKEN_PIPE, PM_ERR_BLOCK_PARAM_PIPE_TERM);
@@ -15022,30 +14781,30 @@ parse_block(pm_parser_t *parser) {
if (opening.type == PM_TOKEN_BRACE_LEFT) {
if (!match1(parser, PM_TOKEN_BRACE_RIGHT)) {
- statements = (pm_node_t *) parse_statements(parser, PM_CONTEXT_BLOCK_BRACES);
+ statements = UP(parse_statements(parser, PM_CONTEXT_BLOCK_BRACES, (uint16_t) (depth + 1)));
}
- expect1(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_BLOCK_TERM_BRACE);
+ expect1_opening(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_BLOCK_TERM_BRACE, &opening);
} else {
if (!match1(parser, PM_TOKEN_KEYWORD_END)) {
if (!match3(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_ENSURE)) {
pm_accepts_block_stack_push(parser, true);
- statements = (pm_node_t *) parse_statements(parser, PM_CONTEXT_BLOCK_KEYWORDS);
+ statements = UP(parse_statements(parser, PM_CONTEXT_BLOCK_KEYWORDS, (uint16_t) (depth + 1)));
pm_accepts_block_stack_pop(parser);
}
if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) {
assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE));
- statements = (pm_node_t *) parse_rescues_implicit_begin(parser, opening.start, (pm_statements_node_t *) statements, PM_RESCUES_BLOCK);
+ statements = UP(parse_rescues_implicit_begin(parser, 0, NULL, opening.start, (pm_statements_node_t *) statements, PM_RESCUES_BLOCK, (uint16_t) (depth + 1)));
}
}
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_BLOCK_TERM_END);
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_BLOCK_TERM_END, &opening);
}
pm_constant_id_list_t locals;
pm_locals_order(parser, &parser->current_scope->locals, &locals, pm_parser_scope_toplevel_p(parser));
- pm_node_t *parameters = parse_blocklike_parameters(parser, (pm_node_t *) block_parameters, &opening, &parser->previous);
+ pm_node_t *parameters = parse_blocklike_parameters(parser, UP(block_parameters), &opening, &parser->previous);
pm_parser_scope_pop(parser);
pm_accepts_block_stack_pop(parser);
@@ -15059,7 +14818,7 @@ parse_block(pm_parser_t *parser) {
* arguments, or blocks).
*/
static bool
-parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_block, bool accepts_command_call) {
+parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accepts_block, bool accepts_command_call, uint16_t depth) {
bool found = false;
if (accept1(parser, PM_TOKEN_PARENTHESIS_LEFT)) {
@@ -15070,7 +14829,7 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept
arguments->closing_loc = PM_LOCATION_TOKEN_VALUE(&parser->previous);
} else {
pm_accepts_block_stack_push(parser, true);
- parse_arguments(parser, arguments, accepts_block, PM_TOKEN_PARENTHESIS_RIGHT);
+ parse_arguments(parser, arguments, accepts_block, PM_TOKEN_PARENTHESIS_RIGHT, (uint16_t) (depth + 1));
if (!accept1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) {
PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_ARGUMENT_TERM_PAREN, pm_token_type_human(parser->current.type));
@@ -15088,13 +14847,13 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept
// If we get here, then the subsequent token cannot be used as an infix
// operator. In this case we assume the subsequent token is part of an
// argument to this method call.
- parse_arguments(parser, arguments, accepts_block, PM_TOKEN_EOF);
+ parse_arguments(parser, arguments, accepts_block, PM_TOKEN_EOF, (uint16_t) (depth + 1));
// If we have done with the arguments and still not consumed the comma,
// then we have a trailing comma where we need to check whether it is
// allowed or not.
if (parser->previous.type == PM_TOKEN_COMMA && !match1(parser, PM_TOKEN_SEMICOLON)) {
- pm_parser_err_previous(parser, PM_ERR_EXPECT_ARGUMENT);
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->previous, PM_ERR_EXPECT_ARGUMENT, pm_token_type_human(parser->current.type));
}
pm_accepts_block_stack_pop(parser);
@@ -15108,18 +14867,18 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept
if (accept1(parser, PM_TOKEN_BRACE_LEFT)) {
found |= true;
- block = parse_block(parser);
+ block = parse_block(parser, (uint16_t) (depth + 1));
pm_arguments_validate_block(parser, arguments, block);
} else if (pm_accepts_block_stack_p(parser) && accept1(parser, PM_TOKEN_KEYWORD_DO)) {
found |= true;
- block = parse_block(parser);
+ block = parse_block(parser, (uint16_t) (depth + 1));
}
if (block != NULL) {
if (arguments->block == NULL && !arguments->has_forwarding) {
- arguments->block = (pm_node_t *) block;
+ arguments->block = UP(block);
} else {
- pm_parser_err_node(parser, (pm_node_t *) block, PM_ERR_ARGUMENT_BLOCK_MULTI);
+ pm_parser_err_node(parser, UP(block), PM_ERR_ARGUMENT_BLOCK_MULTI);
if (arguments->block != NULL) {
if (arguments->arguments == NULL) {
@@ -15127,7 +14886,7 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept
}
pm_arguments_node_arguments_append(arguments->arguments, arguments->block);
}
- arguments->block = (pm_node_t *) block;
+ arguments->block = UP(block);
}
}
}
@@ -15136,20 +14895,103 @@ parse_arguments_list(pm_parser_t *parser, pm_arguments_t *arguments, bool accept
}
/**
+ * Check that the return is allowed in the current context. If it isn't, add an
+ * error to the parser.
+ */
+static void
+parse_return(pm_parser_t *parser, pm_node_t *node) {
+ bool in_sclass = false;
+ for (pm_context_node_t *context_node = parser->current_context; context_node != NULL; context_node = context_node->prev) {
+ switch (context_node->context) {
+ case PM_CONTEXT_BEGIN_ELSE:
+ case PM_CONTEXT_BEGIN_ENSURE:
+ case PM_CONTEXT_BEGIN_RESCUE:
+ case PM_CONTEXT_BEGIN:
+ case PM_CONTEXT_CASE_IN:
+ case PM_CONTEXT_CASE_WHEN:
+ case PM_CONTEXT_DEFAULT_PARAMS:
+ case PM_CONTEXT_DEFINED:
+ case PM_CONTEXT_ELSE:
+ case PM_CONTEXT_ELSIF:
+ case PM_CONTEXT_EMBEXPR:
+ case PM_CONTEXT_FOR_INDEX:
+ case PM_CONTEXT_FOR:
+ case PM_CONTEXT_IF:
+ case PM_CONTEXT_LOOP_PREDICATE:
+ case PM_CONTEXT_MAIN:
+ case PM_CONTEXT_MULTI_TARGET:
+ case PM_CONTEXT_PARENS:
+ case PM_CONTEXT_POSTEXE:
+ case PM_CONTEXT_PREDICATE:
+ case PM_CONTEXT_PREEXE:
+ case PM_CONTEXT_RESCUE_MODIFIER:
+ case PM_CONTEXT_TERNARY:
+ case PM_CONTEXT_UNLESS:
+ case PM_CONTEXT_UNTIL:
+ case PM_CONTEXT_WHILE:
+ // Keep iterating up the lists of contexts, because returns can
+ // see through these.
+ continue;
+ case PM_CONTEXT_SCLASS_ELSE:
+ case PM_CONTEXT_SCLASS_ENSURE:
+ case PM_CONTEXT_SCLASS_RESCUE:
+ case PM_CONTEXT_SCLASS:
+ in_sclass = true;
+ continue;
+ case PM_CONTEXT_CLASS_ELSE:
+ case PM_CONTEXT_CLASS_ENSURE:
+ case PM_CONTEXT_CLASS_RESCUE:
+ case PM_CONTEXT_CLASS:
+ case PM_CONTEXT_MODULE_ELSE:
+ case PM_CONTEXT_MODULE_ENSURE:
+ case PM_CONTEXT_MODULE_RESCUE:
+ case PM_CONTEXT_MODULE:
+ // These contexts are invalid for a return.
+ pm_parser_err_node(parser, node, PM_ERR_RETURN_INVALID);
+ return;
+ case PM_CONTEXT_BLOCK_BRACES:
+ case PM_CONTEXT_BLOCK_ELSE:
+ case PM_CONTEXT_BLOCK_ENSURE:
+ case PM_CONTEXT_BLOCK_KEYWORDS:
+ case PM_CONTEXT_BLOCK_RESCUE:
+ case PM_CONTEXT_BLOCK_PARAMETERS:
+ case PM_CONTEXT_DEF_ELSE:
+ case PM_CONTEXT_DEF_ENSURE:
+ case PM_CONTEXT_DEF_PARAMS:
+ case PM_CONTEXT_DEF_RESCUE:
+ case PM_CONTEXT_DEF:
+ case PM_CONTEXT_LAMBDA_BRACES:
+ case PM_CONTEXT_LAMBDA_DO_END:
+ case PM_CONTEXT_LAMBDA_ELSE:
+ case PM_CONTEXT_LAMBDA_ENSURE:
+ case PM_CONTEXT_LAMBDA_RESCUE:
+ // These contexts are valid for a return, and we should not
+ // continue to loop.
+ return;
+ case PM_CONTEXT_NONE:
+ // This case should never happen.
+ assert(false && "unreachable");
+ break;
+ }
+ }
+ if (in_sclass && parser->version >= PM_OPTIONS_VERSION_CRUBY_3_4) {
+ pm_parser_err_node(parser, node, PM_ERR_RETURN_INVALID);
+ }
+}
+
+/**
* Check that the block exit (next, break, redo) is allowed in the current
* context. If it isn't, add an error to the parser.
*/
static void
-parse_block_exit(pm_parser_t *parser, pm_node_t *node, const char *type) {
- pm_context_node_t *context_node = parser->current_context;
- bool through_expression = false;
-
- while (context_node != NULL) {
+parse_block_exit(pm_parser_t *parser, pm_node_t *node) {
+ for (pm_context_node_t *context_node = parser->current_context; context_node != NULL; context_node = context_node->prev) {
switch (context_node->context) {
case PM_CONTEXT_BLOCK_BRACES:
case PM_CONTEXT_BLOCK_KEYWORDS:
case PM_CONTEXT_BLOCK_ELSE:
case PM_CONTEXT_BLOCK_ENSURE:
+ case PM_CONTEXT_BLOCK_PARAMETERS:
case PM_CONTEXT_BLOCK_RESCUE:
case PM_CONTEXT_DEFINED:
case PM_CONTEXT_FOR:
@@ -15158,6 +15000,7 @@ parse_block_exit(pm_parser_t *parser, pm_node_t *node, const char *type) {
case PM_CONTEXT_LAMBDA_ELSE:
case PM_CONTEXT_LAMBDA_ENSURE:
case PM_CONTEXT_LAMBDA_RESCUE:
+ case PM_CONTEXT_LOOP_PREDICATE:
case PM_CONTEXT_POSTEXE:
case PM_CONTEXT_UNTIL:
case PM_CONTEXT_WHILE:
@@ -15177,65 +15020,50 @@ parse_block_exit(pm_parser_t *parser, pm_node_t *node, const char *type) {
case PM_CONTEXT_SCLASS_RESCUE:
// These are the bad cases. We're not allowed to have a block
// exit in these contexts.
-
- if (through_expression) {
- // If we get here, then we're about to mark this block exit
- // as invalid. However, it could later _become_ valid if we
- // find a trailing while/until on the expression. In this
- // case instead of adding the error here, we'll add the
- // block exit to the list of exits for the expression, and
- // the node parsing will handle validating it instead.
- assert(parser->current_block_exits != NULL);
- pm_node_list_append(parser->current_block_exits, node);
- } else {
- // Otherwise, if we haven't gone through an expression
- // context, then this is just invalid and we'll add the
- // error here.
- PM_PARSER_ERR_NODE_FORMAT(parser, node, PM_ERR_INVALID_BLOCK_EXIT, type);
- }
-
+ //
+ // If we get here, then we're about to mark this block exit
+ // as invalid. However, it could later _become_ valid if we
+ // find a trailing while/until on the expression. In this
+ // case instead of adding the error here, we'll add the
+ // block exit to the list of exits for the expression, and
+ // the node parsing will handle validating it instead.
+ assert(parser->current_block_exits != NULL);
+ pm_node_list_append(parser->current_block_exits, node);
return;
- case PM_CONTEXT_NONE:
- // This case should never happen.
- assert(false && "unreachable");
- break;
- case PM_CONTEXT_BEGIN:
case PM_CONTEXT_BEGIN_ELSE:
case PM_CONTEXT_BEGIN_ENSURE:
case PM_CONTEXT_BEGIN_RESCUE:
+ case PM_CONTEXT_BEGIN:
case PM_CONTEXT_CASE_IN:
case PM_CONTEXT_CASE_WHEN:
- case PM_CONTEXT_CLASS:
case PM_CONTEXT_CLASS_ELSE:
case PM_CONTEXT_CLASS_ENSURE:
case PM_CONTEXT_CLASS_RESCUE:
+ case PM_CONTEXT_CLASS:
+ case PM_CONTEXT_DEFAULT_PARAMS:
case PM_CONTEXT_ELSE:
case PM_CONTEXT_ELSIF:
+ case PM_CONTEXT_EMBEXPR:
+ case PM_CONTEXT_FOR_INDEX:
case PM_CONTEXT_IF:
- case PM_CONTEXT_MODULE:
case PM_CONTEXT_MODULE_ELSE:
case PM_CONTEXT_MODULE_ENSURE:
case PM_CONTEXT_MODULE_RESCUE:
+ case PM_CONTEXT_MODULE:
+ case PM_CONTEXT_MULTI_TARGET:
case PM_CONTEXT_PARENS:
+ case PM_CONTEXT_PREDICATE:
case PM_CONTEXT_RESCUE_MODIFIER:
case PM_CONTEXT_TERNARY:
case PM_CONTEXT_UNLESS:
- // If we got to an expression that could be modified by a
- // trailing while/until, then we'll track that we have gotten
- // here because we need to know it if this block exit is later
- // marked as invalid.
- through_expression = true;
- break;
- case PM_CONTEXT_EMBEXPR:
- case PM_CONTEXT_DEFAULT_PARAMS:
- case PM_CONTEXT_FOR_INDEX:
- case PM_CONTEXT_PREDICATE:
// In these contexts we should continue walking up the list of
// contexts.
break;
+ case PM_CONTEXT_NONE:
+ // This case should never happen.
+ assert(false && "unreachable");
+ break;
}
-
- context_node = context_node->prev;
}
}
@@ -15251,6 +15079,30 @@ push_block_exits(pm_parser_t *parser, pm_node_list_t *current_block_exits) {
}
/**
+ * If we did not match a trailing while/until and this was the last chance to do
+ * so, then all of the block exits in the list are invalid and we need to add an
+ * error for each of them.
+ */
+static void
+flush_block_exits(pm_parser_t *parser, pm_node_list_t *previous_block_exits) {
+ pm_node_t *block_exit;
+ PM_NODE_LIST_FOREACH(parser->current_block_exits, index, block_exit) {
+ const char *type;
+
+ switch (PM_NODE_TYPE(block_exit)) {
+ case PM_BREAK_NODE: type = "break"; break;
+ case PM_NEXT_NODE: type = "next"; break;
+ case PM_REDO_NODE: type = "redo"; break;
+ default: assert(false && "unreachable"); type = ""; break;
+ }
+
+ PM_PARSER_ERR_NODE_FORMAT(parser, block_exit, PM_ERR_INVALID_BLOCK_EXIT, type);
+ }
+
+ parser->current_block_exits = previous_block_exits;
+}
+
+/**
* Pop the current level of block exits from the parser, and add errors to the
* parser if any of them are deemed to be invalid.
*/
@@ -15260,6 +15112,7 @@ pop_block_exits(pm_parser_t *parser, pm_node_list_t *previous_block_exits) {
// If we matched a trailing while/until, then all of the block exits in
// the contained list are valid. In this case we do not need to do
// anything.
+ parser->current_block_exits = previous_block_exits;
} else if (previous_block_exits != NULL) {
// If we did not matching a trailing while/until, then all of the block
// exits contained in the list are invalid for this specific context.
@@ -15267,33 +15120,20 @@ pop_block_exits(pm_parser_t *parser, pm_node_list_t *previous_block_exits) {
// there is another list above this one. In this case we'll push all of
// the block exits up to the previous list.
pm_node_list_concat(previous_block_exits, parser->current_block_exits);
+ parser->current_block_exits = previous_block_exits;
} else {
// If we did not match a trailing while/until and this was the last
// chance to do so, then all of the block exits in the list are invalid
// and we need to add an error for each of them.
- pm_node_t *block_exit;
- PM_NODE_LIST_FOREACH(parser->current_block_exits, index, block_exit) {
- const char *type;
-
- switch (PM_NODE_TYPE(block_exit)) {
- case PM_BREAK_NODE: type = "break"; break;
- case PM_NEXT_NODE: type = "next"; break;
- case PM_REDO_NODE: type = "redo"; break;
- default: assert(false && "unreachable"); type = ""; break;
- }
-
- PM_PARSER_ERR_NODE_FORMAT(parser, block_exit, PM_ERR_INVALID_BLOCK_EXIT, type);
- }
+ flush_block_exits(parser, previous_block_exits);
}
-
- parser->current_block_exits = previous_block_exits;
}
static inline pm_node_t *
-parse_predicate(pm_parser_t *parser, pm_binding_power_t binding_power, pm_context_t context, pm_token_t *then_keyword) {
+parse_predicate(pm_parser_t *parser, pm_binding_power_t binding_power, pm_context_t context, pm_token_t *then_keyword, uint16_t depth) {
context_push(parser, PM_CONTEXT_PREDICATE);
pm_diagnostic_id_t error_id = context == PM_CONTEXT_IF ? PM_ERR_CONDITIONAL_IF_PREDICATE : PM_ERR_CONDITIONAL_UNLESS_PREDICATE;
- pm_node_t *predicate = parse_value_expression(parser, binding_power, true, error_id);
+ pm_node_t *predicate = parse_value_expression(parser, binding_power, true, false, error_id, (uint16_t) (depth + 1));
// Predicates are closed by a term, a "then", or a term and then a "then".
bool predicate_closed = accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
@@ -15312,19 +15152,19 @@ parse_predicate(pm_parser_t *parser, pm_binding_power_t binding_power, pm_contex
}
static inline pm_node_t *
-parse_conditional(pm_parser_t *parser, pm_context_t context) {
+parse_conditional(pm_parser_t *parser, pm_context_t context, size_t opening_newline_index, bool if_after_else, uint16_t depth) {
pm_node_list_t current_block_exits = { 0 };
pm_node_list_t *previous_block_exits = push_block_exits(parser, &current_block_exits);
pm_token_t keyword = parser->previous;
pm_token_t then_keyword = not_provided(parser);
- pm_node_t *predicate = parse_predicate(parser, PM_BINDING_POWER_MODIFIER, context, &then_keyword);
+ pm_node_t *predicate = parse_predicate(parser, PM_BINDING_POWER_MODIFIER, context, &then_keyword, (uint16_t) (depth + 1));
pm_statements_node_t *statements = NULL;
if (!match3(parser, PM_TOKEN_KEYWORD_ELSIF, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_END)) {
pm_accepts_block_stack_push(parser, true);
- statements = parse_statements(parser, context);
+ statements = parse_statements(parser, context, (uint16_t) (depth + 1));
pm_accepts_block_stack_pop(parser);
accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
}
@@ -15334,10 +15174,10 @@ parse_conditional(pm_parser_t *parser, pm_context_t context) {
switch (context) {
case PM_CONTEXT_IF:
- parent = (pm_node_t *) pm_if_node_create(parser, &keyword, predicate, &then_keyword, statements, NULL, &end_keyword);
+ parent = UP(pm_if_node_create(parser, &keyword, predicate, &then_keyword, statements, NULL, &end_keyword));
break;
case PM_CONTEXT_UNLESS:
- parent = (pm_node_t *) pm_unless_node_create(parser, &keyword, predicate, &then_keyword, statements);
+ parent = UP(pm_unless_node_create(parser, &keyword, predicate, &then_keyword, statements));
break;
default:
assert(false && "unreachable");
@@ -15354,50 +15194,54 @@ parse_conditional(pm_parser_t *parser, pm_context_t context) {
PM_PARSER_WARN_TOKEN_FORMAT_CONTENT(parser, parser->current, PM_WARN_KEYWORD_EOL);
}
+ parser_warn_indentation_mismatch(parser, opening_newline_index, &keyword, false, false);
pm_token_t elsif_keyword = parser->current;
parser_lex(parser);
- pm_node_t *predicate = parse_predicate(parser, PM_BINDING_POWER_MODIFIER, PM_CONTEXT_ELSIF, &then_keyword);
+ pm_node_t *predicate = parse_predicate(parser, PM_BINDING_POWER_MODIFIER, PM_CONTEXT_ELSIF, &then_keyword, (uint16_t) (depth + 1));
pm_accepts_block_stack_push(parser, true);
- pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_ELSIF);
+ pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_ELSIF, (uint16_t) (depth + 1));
pm_accepts_block_stack_pop(parser);
accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
- pm_node_t *elsif = (pm_node_t *) pm_if_node_create(parser, &elsif_keyword, predicate, &then_keyword, statements, NULL, &end_keyword);
- ((pm_if_node_t *) current)->consequent = elsif;
+ pm_node_t *elsif = UP(pm_if_node_create(parser, &elsif_keyword, predicate, &then_keyword, statements, NULL, &end_keyword));
+ ((pm_if_node_t *) current)->subsequent = elsif;
current = elsif;
}
}
if (match1(parser, PM_TOKEN_KEYWORD_ELSE)) {
+ parser_warn_indentation_mismatch(parser, opening_newline_index, &keyword, false, false);
+ opening_newline_index = token_newline_index(parser);
+
parser_lex(parser);
pm_token_t else_keyword = parser->previous;
pm_accepts_block_stack_push(parser, true);
- pm_statements_node_t *else_statements = parse_statements(parser, PM_CONTEXT_ELSE);
+ pm_statements_node_t *else_statements = parse_statements(parser, PM_CONTEXT_ELSE, (uint16_t) (depth + 1));
pm_accepts_block_stack_pop(parser);
accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CONDITIONAL_TERM_ELSE);
+ parser_warn_indentation_mismatch(parser, opening_newline_index, &else_keyword, false, false);
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CONDITIONAL_TERM_ELSE, &keyword);
pm_else_node_t *else_node = pm_else_node_create(parser, &else_keyword, else_statements, &parser->previous);
switch (context) {
case PM_CONTEXT_IF:
- ((pm_if_node_t *) current)->consequent = (pm_node_t *) else_node;
+ ((pm_if_node_t *) current)->subsequent = UP(else_node);
break;
case PM_CONTEXT_UNLESS:
- ((pm_unless_node_t *) parent)->consequent = else_node;
+ ((pm_unless_node_t *) parent)->else_clause = else_node;
break;
default:
assert(false && "unreachable");
break;
}
} else {
- // We should specialize this error message to refer to 'if' or 'unless'
- // explicitly.
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CONDITIONAL_TERM);
+ parser_warn_indentation_mismatch(parser, opening_newline_index, &keyword, if_after_else, false);
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CONDITIONAL_TERM, &keyword);
}
// Set the appropriate end location for all of the nodes in the subtree.
@@ -15410,7 +15254,7 @@ parse_conditional(pm_parser_t *parser, pm_context_t context) {
switch (PM_NODE_TYPE(current)) {
case PM_IF_NODE:
pm_if_node_end_keyword_loc_set((pm_if_node_t *) current, &parser->previous);
- current = ((pm_if_node_t *) current)->consequent;
+ current = ((pm_if_node_t *) current)->subsequent;
recursing = current != NULL;
break;
case PM_ELSE_NODE:
@@ -15532,7 +15376,7 @@ parse_unescaped_encoding(const pm_parser_t *parser) {
* parsed as a string part, then NULL is returned.
*/
static pm_node_t *
-parse_string_part(pm_parser_t *parser) {
+parse_string_part(pm_parser_t *parser, uint16_t depth) {
switch (parser->current.type) {
// Here the lexer has returned to us plain string content. In this case
// we'll create a string node that has no opening or closing and return that
@@ -15544,7 +15388,7 @@ parse_string_part(pm_parser_t *parser) {
pm_token_t opening = not_provided(parser);
pm_token_t closing = not_provided(parser);
- pm_node_t *node = (pm_node_t *) pm_string_node_create_current_string(parser, &opening, &parser->current, &closing);
+ pm_node_t *node = UP(pm_string_node_create_current_string(parser, &opening, &parser->current, &closing));
pm_node_flag_set(node, parse_unescaped_encoding(parser));
parser_lex(parser);
@@ -15573,7 +15417,7 @@ parse_string_part(pm_parser_t *parser) {
if (!match1(parser, PM_TOKEN_EMBEXPR_END)) {
pm_accepts_block_stack_push(parser, true);
- statements = parse_statements(parser, PM_CONTEXT_EMBEXPR);
+ statements = parse_statements(parser, PM_CONTEXT_EMBEXPR, (uint16_t) (depth + 1));
pm_accepts_block_stack_pop(parser);
}
@@ -15590,7 +15434,7 @@ parse_string_part(pm_parser_t *parser) {
pm_node_flag_unset(statements->body.nodes[0], PM_NODE_FLAG_NEWLINE);
}
- return (pm_node_t *) pm_embedded_statements_node_create(parser, &opening, statements, &closing);
+ return UP(pm_embedded_statements_node_create(parser, &opening, statements, &closing));
}
// Here the lexer has returned the beginning of an embedded variable.
@@ -15615,42 +15459,42 @@ parse_string_part(pm_parser_t *parser) {
// create a global variable read node.
case PM_TOKEN_BACK_REFERENCE:
parser_lex(parser);
- variable = (pm_node_t *) pm_back_reference_read_node_create(parser, &parser->previous);
+ variable = UP(pm_back_reference_read_node_create(parser, &parser->previous));
break;
// In this case an nth reference is being interpolated. We'll
// create a global variable read node.
case PM_TOKEN_NUMBERED_REFERENCE:
parser_lex(parser);
- variable = (pm_node_t *) pm_numbered_reference_read_node_create(parser, &parser->previous);
+ variable = UP(pm_numbered_reference_read_node_create(parser, &parser->previous));
break;
// In this case a global variable is being interpolated. We'll
// create a global variable read node.
case PM_TOKEN_GLOBAL_VARIABLE:
parser_lex(parser);
- variable = (pm_node_t *) pm_global_variable_read_node_create(parser, &parser->previous);
+ variable = UP(pm_global_variable_read_node_create(parser, &parser->previous));
break;
// In this case an instance variable is being interpolated.
// We'll create an instance variable read node.
case PM_TOKEN_INSTANCE_VARIABLE:
parser_lex(parser);
- variable = (pm_node_t *) pm_instance_variable_read_node_create(parser, &parser->previous);
+ variable = UP(pm_instance_variable_read_node_create(parser, &parser->previous));
break;
// In this case a class variable is being interpolated. We'll
// create a class variable read node.
case PM_TOKEN_CLASS_VARIABLE:
parser_lex(parser);
- variable = (pm_node_t *) pm_class_variable_read_node_create(parser, &parser->previous);
+ variable = UP(pm_class_variable_read_node_create(parser, &parser->previous));
break;
// We can hit here if we got an invalid token. In that case
// we'll not attempt to lex this token and instead just return a
// missing node.
default:
expect1(parser, PM_TOKEN_IDENTIFIER, PM_ERR_EMBVAR_INVALID);
- variable = (pm_node_t *) pm_missing_node_create(parser, parser->current.start, parser->current.end);
+ variable = UP(pm_missing_node_create(parser, parser->current.start, parser->current.end));
break;
}
- return (pm_node_t *) pm_embedded_variable_node_create(parser, &operator, variable);
+ return UP(pm_embedded_variable_node_create(parser, &operator, variable));
}
default:
parser_lex(parser);
@@ -15670,7 +15514,7 @@ parse_operator_symbol_name(const pm_token_t *name) {
case PM_TOKEN_TILDE:
case PM_TOKEN_BANG:
if (name->end[-1] == '@') return name->end - 1;
- /* fallthrough */
+ PRISM_FALLTHROUGH
default:
return name->end;
}
@@ -15687,9 +15531,9 @@ parse_operator_symbol(pm_parser_t *parser, const pm_token_t *opening, pm_lex_sta
parser_lex(parser);
pm_string_shared_init(&symbol->unescaped, parser->previous.start, end);
- pm_node_flag_set((pm_node_t *) symbol, PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING);
+ pm_node_flag_set(UP(symbol), PM_SYMBOL_FLAGS_FORCED_US_ASCII_ENCODING);
- return (pm_node_t *) symbol;
+ return UP(symbol);
}
/**
@@ -15698,7 +15542,7 @@ parse_operator_symbol(pm_parser_t *parser, const pm_token_t *opening, pm_lex_sta
* symbols.
*/
static pm_node_t *
-parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_state) {
+parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_state, uint16_t depth) {
const pm_token_t opening = parser->previous;
if (lex_mode->mode != PM_LEX_STRING) {
@@ -15727,9 +15571,9 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s
pm_symbol_node_t *symbol = pm_symbol_node_create(parser, &opening, &parser->previous, &closing);
pm_string_shared_init(&symbol->unescaped, parser->previous.start, parser->previous.end);
- pm_node_flag_set((pm_node_t *) symbol, parse_symbol_encoding(parser, &parser->previous, &symbol->unescaped, false));
+ pm_node_flag_set(UP(symbol), parse_symbol_encoding(parser, &parser->previous, &symbol->unescaped, false));
- return (pm_node_t *) symbol;
+ return UP(symbol);
}
if (lex_mode->as.string.interpolation) {
@@ -15740,11 +15584,11 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s
pm_token_t content = not_provided(parser);
pm_token_t closing = parser->previous;
- return (pm_node_t *) pm_symbol_node_create(parser, &opening, &content, &closing);
+ return UP(pm_symbol_node_create(parser, &opening, &content, &closing));
}
// Now we can parse the first part of the symbol.
- pm_node_t *part = parse_string_part(parser);
+ pm_node_t *part = parse_string_part(parser, (uint16_t) (depth + 1));
// If we got a string part, then it's possible that we could transform
// what looks like an interpolated symbol into a regular symbol.
@@ -15752,14 +15596,14 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s
if (next_state != PM_LEX_STATE_NONE) lex_state_set(parser, next_state);
expect1(parser, PM_TOKEN_STRING_END, PM_ERR_SYMBOL_TERM_INTERPOLATED);
- return (pm_node_t *) pm_string_node_to_symbol_node(parser, (pm_string_node_t *) part, &opening, &parser->previous);
+ return UP(pm_string_node_to_symbol_node(parser, (pm_string_node_t *) part, &opening, &parser->previous));
}
pm_interpolated_symbol_node_t *symbol = pm_interpolated_symbol_node_create(parser, &opening, NULL, &opening);
if (part) pm_interpolated_symbol_node_append(symbol, part);
while (!match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) {
- if ((part = parse_string_part(parser)) != NULL) {
+ if ((part = parse_string_part(parser, (uint16_t) (depth + 1))) != NULL) {
pm_interpolated_symbol_node_append(symbol, part);
}
}
@@ -15772,7 +15616,7 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s
}
pm_interpolated_symbol_node_closing_loc_set(symbol, &parser->previous);
- return (pm_node_t *) symbol;
+ return UP(symbol);
}
pm_token_t content;
@@ -15796,10 +15640,10 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s
pm_interpolated_symbol_node_t *symbol = pm_interpolated_symbol_node_create(parser, &opening, NULL, &opening);
pm_token_t bounds = not_provided(parser);
- pm_node_t *part = (pm_node_t *) pm_string_node_create_unescaped(parser, &bounds, &content, &bounds, &unescaped);
+ pm_node_t *part = UP(pm_string_node_create_unescaped(parser, &bounds, &content, &bounds, &unescaped));
pm_interpolated_symbol_node_append(symbol, part);
- part = (pm_node_t *) pm_string_node_create_unescaped(parser, &bounds, &parser->current, &bounds, &parser->current_string);
+ part = UP(pm_string_node_create_unescaped(parser, &bounds, &parser->current, &bounds, &parser->current_string));
pm_interpolated_symbol_node_append(symbol, part);
if (next_state != PM_LEX_STATE_NONE) {
@@ -15810,7 +15654,7 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s
expect1(parser, PM_TOKEN_STRING_END, PM_ERR_SYMBOL_TERM_DYNAMIC);
pm_interpolated_symbol_node_closing_loc_set(symbol, &parser->previous);
- return (pm_node_t *) symbol;
+ return UP(symbol);
}
} else {
content = (pm_token_t) { .type = PM_TOKEN_STRING_CONTENT, .start = parser->previous.end, .end = parser->previous.end };
@@ -15827,7 +15671,7 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s
expect1(parser, PM_TOKEN_STRING_END, PM_ERR_SYMBOL_TERM_DYNAMIC);
}
- return (pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped, parse_symbol_encoding(parser, &content, &unescaped, false));
+ return UP(pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped, parse_symbol_encoding(parser, &content, &unescaped, false)));
}
/**
@@ -15835,7 +15679,7 @@ parse_symbol(pm_parser_t *parser, pm_lex_mode_t *lex_mode, pm_lex_state_t next_s
* constant, or an interpolated symbol.
*/
static inline pm_node_t *
-parse_undef_argument(pm_parser_t *parser) {
+parse_undef_argument(pm_parser_t *parser, uint16_t depth) {
switch (parser->current.type) {
case PM_CASE_OPERATOR: {
const pm_token_t opening = not_provided(parser);
@@ -15852,19 +15696,19 @@ parse_undef_argument(pm_parser_t *parser) {
pm_symbol_node_t *symbol = pm_symbol_node_create(parser, &opening, &parser->previous, &closing);
pm_string_shared_init(&symbol->unescaped, parser->previous.start, parser->previous.end);
- pm_node_flag_set((pm_node_t *) symbol, parse_symbol_encoding(parser, &parser->previous, &symbol->unescaped, false));
+ pm_node_flag_set(UP(symbol), parse_symbol_encoding(parser, &parser->previous, &symbol->unescaped, false));
- return (pm_node_t *) symbol;
+ return UP(symbol);
}
case PM_TOKEN_SYMBOL_BEGIN: {
pm_lex_mode_t lex_mode = *parser->lex_modes.current;
parser_lex(parser);
- return parse_symbol(parser, &lex_mode, PM_LEX_STATE_NONE);
+ return parse_symbol(parser, &lex_mode, PM_LEX_STATE_NONE, (uint16_t) (depth + 1));
}
default:
pm_parser_err_current(parser, PM_ERR_UNDEF_ARGUMENT);
- return (pm_node_t *) pm_missing_node_create(parser, parser->current.start, parser->current.end);
+ return UP(pm_missing_node_create(parser, parser->current.start, parser->current.end));
}
}
@@ -15875,7 +15719,7 @@ parse_undef_argument(pm_parser_t *parser) {
* between the first and second arguments.
*/
static inline pm_node_t *
-parse_alias_argument(pm_parser_t *parser, bool first) {
+parse_alias_argument(pm_parser_t *parser, bool first, uint16_t depth) {
switch (parser->current.type) {
case PM_CASE_OPERATOR: {
const pm_token_t opening = not_provided(parser);
@@ -15893,28 +15737,28 @@ parse_alias_argument(pm_parser_t *parser, bool first) {
pm_symbol_node_t *symbol = pm_symbol_node_create(parser, &opening, &parser->previous, &closing);
pm_string_shared_init(&symbol->unescaped, parser->previous.start, parser->previous.end);
- pm_node_flag_set((pm_node_t *) symbol, parse_symbol_encoding(parser, &parser->previous, &symbol->unescaped, false));
+ pm_node_flag_set(UP(symbol), parse_symbol_encoding(parser, &parser->previous, &symbol->unescaped, false));
- return (pm_node_t *) symbol;
+ return UP(symbol);
}
case PM_TOKEN_SYMBOL_BEGIN: {
pm_lex_mode_t lex_mode = *parser->lex_modes.current;
parser_lex(parser);
- return parse_symbol(parser, &lex_mode, first ? PM_LEX_STATE_FNAME | PM_LEX_STATE_FITEM : PM_LEX_STATE_NONE);
+ return parse_symbol(parser, &lex_mode, first ? PM_LEX_STATE_FNAME | PM_LEX_STATE_FITEM : PM_LEX_STATE_NONE, (uint16_t) (depth + 1));
}
case PM_TOKEN_BACK_REFERENCE:
parser_lex(parser);
- return (pm_node_t *) pm_back_reference_read_node_create(parser, &parser->previous);
+ return UP(pm_back_reference_read_node_create(parser, &parser->previous));
case PM_TOKEN_NUMBERED_REFERENCE:
parser_lex(parser);
- return (pm_node_t *) pm_numbered_reference_read_node_create(parser, &parser->previous);
+ return UP(pm_numbered_reference_read_node_create(parser, &parser->previous));
case PM_TOKEN_GLOBAL_VARIABLE:
parser_lex(parser);
- return (pm_node_t *) pm_global_variable_read_node_create(parser, &parser->previous);
+ return UP(pm_global_variable_read_node_create(parser, &parser->previous));
default:
pm_parser_err_current(parser, PM_ERR_ALIAS_ARGUMENT);
- return (pm_node_t *) pm_missing_node_create(parser, parser->current.start, parser->current.end);
+ return UP(pm_missing_node_create(parser, parser->current.start, parser->current.end));
}
}
@@ -15926,14 +15770,15 @@ static pm_node_t *
parse_variable(pm_parser_t *parser) {
pm_constant_id_t name_id = pm_parser_constant_id_token(parser, &parser->previous);
int depth;
+ bool is_numbered_param = pm_token_is_numbered_parameter(parser->previous.start, parser->previous.end);
- if ((depth = pm_parser_local_depth_constant_id(parser, name_id)) != -1) {
- return (pm_node_t *) pm_local_variable_read_node_create_constant_id(parser, &parser->previous, name_id, (uint32_t) depth, false);
+ if (!is_numbered_param && ((depth = pm_parser_local_depth_constant_id(parser, name_id)) != -1)) {
+ return UP(pm_local_variable_read_node_create_constant_id(parser, &parser->previous, name_id, (uint32_t) depth, false));
}
pm_scope_t *current_scope = parser->current_scope;
if (!current_scope->closed && !(current_scope->parameters & PM_SCOPE_PARAMETERS_IMPLICIT_DISALLOWED)) {
- if (pm_token_is_numbered_parameter(parser->previous.start, parser->previous.end)) {
+ if (is_numbered_param) {
// When you use a numbered parameter, it implies the existence of
// all of the locals that exist before it. For example, referencing
// _2 means that _1 must exist. Therefore here we loop through all
@@ -15947,12 +15792,12 @@ parse_variable(pm_parser_t *parser) {
parser->current_scope->parameters |= PM_SCOPE_PARAMETERS_NUMBERED_FOUND;
}
- pm_node_t *node = (pm_node_t *) pm_local_variable_read_node_create_constant_id(parser, &parser->previous, name_id, 0, false);
+ pm_node_t *node = UP(pm_local_variable_read_node_create_constant_id(parser, &parser->previous, name_id, 0, false));
pm_node_list_append(&current_scope->implicit_parameters, node);
return node;
- } else if ((parser->version != PM_OPTIONS_VERSION_CRUBY_3_3) && pm_token_is_it(parser->previous.start, parser->previous.end)) {
- pm_node_t *node = (pm_node_t *) pm_it_local_variable_read_node_create(parser, &parser->previous);
+ } else if ((parser->version >= PM_OPTIONS_VERSION_CRUBY_3_4) && pm_token_is_it(parser->previous.start, parser->previous.end)) {
+ pm_node_t *node = UP(pm_it_local_variable_read_node_create(parser, &parser->previous));
pm_node_list_append(&current_scope->implicit_parameters, node);
return node;
@@ -15976,9 +15821,9 @@ parse_variable_call(pm_parser_t *parser) {
}
pm_call_node_t *node = pm_call_node_variable_call_create(parser, &parser->previous);
- pm_node_flag_set((pm_node_t *)node, flags);
+ pm_node_flag_set(UP(node), flags);
- return (pm_node_t *) node;
+ return UP(node);
}
/**
@@ -16089,12 +15934,245 @@ parse_heredoc_dedent(pm_parser_t *parser, pm_node_list_t *nodes, size_t common_w
nodes->size = write_index;
}
+/**
+ * Return a string content token at a particular location that is empty.
+ */
+static pm_token_t
+parse_strings_empty_content(const uint8_t *location) {
+ return (pm_token_t) { .type = PM_TOKEN_STRING_CONTENT, .start = location, .end = location };
+}
+
+/**
+ * Parse a set of strings that could be concatenated together.
+ */
+static inline pm_node_t *
+parse_strings(pm_parser_t *parser, pm_node_t *current, bool accepts_label, uint16_t depth) {
+ assert(parser->current.type == PM_TOKEN_STRING_BEGIN);
+ bool concating = false;
+
+ while (match1(parser, PM_TOKEN_STRING_BEGIN)) {
+ pm_node_t *node = NULL;
+
+ // Here we have found a string literal. We'll parse it and add it to
+ // the list of strings.
+ const pm_lex_mode_t *lex_mode = parser->lex_modes.current;
+ assert(lex_mode->mode == PM_LEX_STRING);
+ bool lex_interpolation = lex_mode->as.string.interpolation;
+ bool label_allowed = lex_mode->as.string.label_allowed && accepts_label;
+
+ pm_token_t opening = parser->current;
+ parser_lex(parser);
+
+ if (match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) {
+ expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_EOF);
+ // If we get here, then we have an end immediately after a
+ // start. In that case we'll create an empty content token and
+ // return an uninterpolated string.
+ pm_token_t content = parse_strings_empty_content(parser->previous.start);
+ pm_string_node_t *string = pm_string_node_create(parser, &opening, &content, &parser->previous);
+
+ pm_string_shared_init(&string->unescaped, content.start, content.end);
+ node = UP(string);
+ } else if (accept1(parser, PM_TOKEN_LABEL_END)) {
+ // If we get here, then we have an end of a label immediately
+ // after a start. In that case we'll create an empty symbol
+ // node.
+ pm_token_t content = parse_strings_empty_content(parser->previous.start);
+ pm_symbol_node_t *symbol = pm_symbol_node_create(parser, &opening, &content, &parser->previous);
+
+ pm_string_shared_init(&symbol->unescaped, content.start, content.end);
+ node = UP(symbol);
+
+ if (!label_allowed) pm_parser_err_node(parser, node, PM_ERR_UNEXPECTED_LABEL);
+ } else if (!lex_interpolation) {
+ // If we don't accept interpolation then we expect the string to
+ // start with a single string content node.
+ pm_string_t unescaped;
+ pm_token_t content;
+
+ if (match1(parser, PM_TOKEN_EOF)) {
+ unescaped = PM_STRING_EMPTY;
+ content = not_provided(parser);
+ } else {
+ unescaped = parser->current_string;
+ expect1(parser, PM_TOKEN_STRING_CONTENT, PM_ERR_EXPECT_STRING_CONTENT);
+ content = parser->previous;
+ }
+
+ // It is unfortunately possible to have multiple string content
+ // nodes in a row in the case that there's heredoc content in
+ // the middle of the string, like this cursed example:
+ //
+ // <<-END+'b
+ // a
+ // END
+ // c'+'d'
+ //
+ // In that case we need to switch to an interpolated string to
+ // be able to contain all of the parts.
+ if (match1(parser, PM_TOKEN_STRING_CONTENT)) {
+ pm_node_list_t parts = { 0 };
+
+ pm_token_t delimiters = not_provided(parser);
+ pm_node_t *part = UP(pm_string_node_create_unescaped(parser, &delimiters, &content, &delimiters, &unescaped));
+ pm_node_list_append(&parts, part);
+
+ do {
+ part = UP(pm_string_node_create_current_string(parser, &delimiters, &parser->current, &delimiters));
+ pm_node_list_append(&parts, part);
+ parser_lex(parser);
+ } while (match1(parser, PM_TOKEN_STRING_CONTENT));
+
+ expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_EOF);
+ node = UP(pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous));
+
+ pm_node_list_free(&parts);
+ } else if (accept1(parser, PM_TOKEN_LABEL_END)) {
+ node = UP(pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped, parse_symbol_encoding(parser, &content, &unescaped, true)));
+ if (!label_allowed) pm_parser_err_node(parser, node, PM_ERR_UNEXPECTED_LABEL);
+ } else if (match1(parser, PM_TOKEN_EOF)) {
+ pm_parser_err_token(parser, &opening, PM_ERR_STRING_LITERAL_EOF);
+ node = UP(pm_string_node_create_unescaped(parser, &opening, &content, &parser->current, &unescaped));
+ } else if (accept1(parser, PM_TOKEN_STRING_END)) {
+ node = UP(pm_string_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped));
+ } else {
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->previous, PM_ERR_STRING_LITERAL_TERM, pm_token_type_human(parser->previous.type));
+ parser->previous.start = parser->previous.end;
+ parser->previous.type = PM_TOKEN_MISSING;
+ node = UP(pm_string_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped));
+ }
+ } else if (match1(parser, PM_TOKEN_STRING_CONTENT)) {
+ // In this case we've hit string content so we know the string
+ // at least has something in it. We'll need to check if the
+ // following token is the end (in which case we can return a
+ // plain string) or if it's not then it has interpolation.
+ pm_token_t content = parser->current;
+ pm_string_t unescaped = parser->current_string;
+ parser_lex(parser);
+
+ if (match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) {
+ node = UP(pm_string_node_create_unescaped(parser, &opening, &content, &parser->current, &unescaped));
+ pm_node_flag_set(node, parse_unescaped_encoding(parser));
+
+ // Kind of odd behavior, but basically if we have an
+ // unterminated string and it ends in a newline, we back up one
+ // character so that the error message is on the last line of
+ // content in the string.
+ if (!accept1(parser, PM_TOKEN_STRING_END)) {
+ const uint8_t *location = parser->previous.end;
+ if (location > parser->start && location[-1] == '\n') location--;
+ pm_parser_err(parser, location, location, PM_ERR_STRING_LITERAL_EOF);
+
+ parser->previous.start = parser->previous.end;
+ parser->previous.type = PM_TOKEN_MISSING;
+ }
+ } else if (accept1(parser, PM_TOKEN_LABEL_END)) {
+ node = UP(pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped, parse_symbol_encoding(parser, &content, &unescaped, true)));
+ if (!label_allowed) pm_parser_err_node(parser, node, PM_ERR_UNEXPECTED_LABEL);
+ } else {
+ // If we get here, then we have interpolation so we'll need
+ // to create a string or symbol node with interpolation.
+ pm_node_list_t parts = { 0 };
+ pm_token_t string_opening = not_provided(parser);
+ pm_token_t string_closing = not_provided(parser);
+
+ pm_node_t *part = UP(pm_string_node_create_unescaped(parser, &string_opening, &parser->previous, &string_closing, &unescaped));
+ pm_node_flag_set(part, parse_unescaped_encoding(parser));
+ pm_node_list_append(&parts, part);
+
+ while (!match3(parser, PM_TOKEN_STRING_END, PM_TOKEN_LABEL_END, PM_TOKEN_EOF)) {
+ if ((part = parse_string_part(parser, (uint16_t) (depth + 1))) != NULL) {
+ pm_node_list_append(&parts, part);
+ }
+ }
+
+ if (accept1(parser, PM_TOKEN_LABEL_END)) {
+ node = UP(pm_interpolated_symbol_node_create(parser, &opening, &parts, &parser->previous));
+ if (!label_allowed) pm_parser_err_node(parser, node, PM_ERR_UNEXPECTED_LABEL);
+ } else if (match1(parser, PM_TOKEN_EOF)) {
+ pm_parser_err_token(parser, &opening, PM_ERR_STRING_INTERPOLATED_TERM);
+ node = UP(pm_interpolated_string_node_create(parser, &opening, &parts, &parser->current));
+ } else {
+ expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_INTERPOLATED_TERM);
+ node = UP(pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous));
+ }
+
+ pm_node_list_free(&parts);
+ }
+ } else {
+ // If we get here, then the first part of the string is not plain
+ // string content, in which case we need to parse the string as an
+ // interpolated string.
+ pm_node_list_t parts = { 0 };
+ pm_node_t *part;
+
+ while (!match3(parser, PM_TOKEN_STRING_END, PM_TOKEN_LABEL_END, PM_TOKEN_EOF)) {
+ if ((part = parse_string_part(parser, (uint16_t) (depth + 1))) != NULL) {
+ pm_node_list_append(&parts, part);
+ }
+ }
+
+ if (accept1(parser, PM_TOKEN_LABEL_END)) {
+ node = UP(pm_interpolated_symbol_node_create(parser, &opening, &parts, &parser->previous));
+ if (!label_allowed) pm_parser_err_node(parser, node, PM_ERR_UNEXPECTED_LABEL);
+ } else if (match1(parser, PM_TOKEN_EOF)) {
+ pm_parser_err_token(parser, &opening, PM_ERR_STRING_INTERPOLATED_TERM);
+ node = UP(pm_interpolated_string_node_create(parser, &opening, &parts, &parser->current));
+ } else {
+ expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_INTERPOLATED_TERM);
+ node = UP(pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous));
+ }
+
+ pm_node_list_free(&parts);
+ }
+
+ if (current == NULL) {
+ // If the node we just parsed is a symbol node, then we can't
+ // concatenate it with anything else, so we can now return that
+ // node.
+ if (PM_NODE_TYPE_P(node, PM_SYMBOL_NODE) || PM_NODE_TYPE_P(node, PM_INTERPOLATED_SYMBOL_NODE)) {
+ return node;
+ }
+
+ // If we don't already have a node, then it's fine and we can just
+ // set the result to be the node we just parsed.
+ current = node;
+ } else {
+ // Otherwise we need to check the type of the node we just parsed.
+ // If it cannot be concatenated with the previous node, then we'll
+ // need to add a syntax error.
+ if (!PM_NODE_TYPE_P(node, PM_STRING_NODE) && !PM_NODE_TYPE_P(node, PM_INTERPOLATED_STRING_NODE)) {
+ pm_parser_err_node(parser, node, PM_ERR_STRING_CONCATENATION);
+ }
+
+ // If we haven't already created our container for concatenation,
+ // we'll do that now.
+ if (!concating) {
+ if (!PM_NODE_TYPE_P(current, PM_STRING_NODE) && !PM_NODE_TYPE_P(current, PM_INTERPOLATED_STRING_NODE)) {
+ pm_parser_err_node(parser, current, PM_ERR_STRING_CONCATENATION);
+ }
+
+ concating = true;
+ pm_token_t bounds = not_provided(parser);
+
+ pm_interpolated_string_node_t *container = pm_interpolated_string_node_create(parser, &bounds, NULL, &bounds);
+ pm_interpolated_string_node_append(container, current);
+ current = UP(container);
+ }
+
+ pm_interpolated_string_node_append((pm_interpolated_string_node_t *) current, node);
+ }
+ }
+
+ return current;
+}
+
#define PM_PARSE_PATTERN_SINGLE 0
#define PM_PARSE_PATTERN_TOP 1
#define PM_PARSE_PATTERN_MULTI 2
static pm_node_t *
-parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flags, pm_diagnostic_id_t diag_id);
+parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flags, pm_diagnostic_id_t diag_id, uint16_t depth);
/**
* Add the newly created local to the list of captures for this pattern matching
@@ -16104,7 +16182,7 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag
static void
parse_pattern_capture(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_constant_id_t capture, const pm_location_t *location) {
// Skip this capture if it starts with an underscore.
- if (*location->start == '_') return;
+ if (peek_at(parser, location->start) == '_') return;
if (pm_constant_id_list_includes(captures, capture)) {
pm_parser_err(parser, location->start, location->end, PM_ERR_PATTERN_CAPTURE_DUPLICATE);
@@ -16117,13 +16195,13 @@ parse_pattern_capture(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_c
* Accept any number of constants joined by :: delimiters.
*/
static pm_node_t *
-parse_pattern_constant_path(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node_t *node) {
+parse_pattern_constant_path(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node_t *node, uint16_t depth) {
// Now, if there are any :: operators that follow, parse them as constant
// path nodes.
while (accept1(parser, PM_TOKEN_COLON_COLON)) {
pm_token_t delimiter = parser->previous;
expect1(parser, PM_TOKEN_CONSTANT, PM_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT);
- node = (pm_node_t *) pm_constant_path_node_create(parser, node, &delimiter, &parser->previous);
+ node = UP(pm_constant_path_node_create(parser, node, &delimiter, &parser->previous));
}
// If there is a [ or ( that follows, then this is part of a larger pattern
@@ -16142,9 +16220,9 @@ parse_pattern_constant_path(pm_parser_t *parser, pm_constant_id_list_t *captures
accept1(parser, PM_TOKEN_NEWLINE);
if (!accept1(parser, PM_TOKEN_BRACKET_RIGHT)) {
- inner = parse_pattern(parser, captures, PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET);
+ inner = parse_pattern(parser, captures, PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET, (uint16_t) (depth + 1));
accept1(parser, PM_TOKEN_NEWLINE);
- expect1(parser, PM_TOKEN_BRACKET_RIGHT, PM_ERR_PATTERN_TERM_BRACKET);
+ expect1_opening(parser, PM_TOKEN_BRACKET_RIGHT, PM_ERR_PATTERN_TERM_BRACKET, &opening);
}
closing = parser->previous;
@@ -16154,9 +16232,9 @@ parse_pattern_constant_path(pm_parser_t *parser, pm_constant_id_list_t *captures
accept1(parser, PM_TOKEN_NEWLINE);
if (!accept1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) {
- inner = parse_pattern(parser, captures, PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_PAREN);
+ inner = parse_pattern(parser, captures, PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_PAREN, (uint16_t) (depth + 1));
accept1(parser, PM_TOKEN_NEWLINE);
- expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_PATTERN_TERM_PAREN);
+ expect1_opening(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_PATTERN_TERM_PAREN, &opening);
}
closing = parser->previous;
@@ -16165,7 +16243,7 @@ parse_pattern_constant_path(pm_parser_t *parser, pm_constant_id_list_t *captures
if (!inner) {
// If there was no inner pattern, then we have something like Foo() or
// Foo[]. In that case we'll create an array pattern with no requireds.
- return (pm_node_t *) pm_array_pattern_node_constant_create(parser, node, &opening, &closing);
+ return UP(pm_array_pattern_node_constant_create(parser, node, &opening, &closing));
}
// Now that we have the inner pattern, check to see if it's an array, find,
@@ -16184,7 +16262,7 @@ parse_pattern_constant_path(pm_parser_t *parser, pm_constant_id_list_t *captures
pattern_node->opening_loc = PM_LOCATION_TOKEN_VALUE(&opening);
pattern_node->closing_loc = PM_LOCATION_TOKEN_VALUE(&closing);
- return (pm_node_t *) pattern_node;
+ return UP(pattern_node);
}
break;
@@ -16200,7 +16278,7 @@ parse_pattern_constant_path(pm_parser_t *parser, pm_constant_id_list_t *captures
pattern_node->opening_loc = PM_LOCATION_TOKEN_VALUE(&opening);
pattern_node->closing_loc = PM_LOCATION_TOKEN_VALUE(&closing);
- return (pm_node_t *) pattern_node;
+ return UP(pattern_node);
}
break;
@@ -16216,7 +16294,7 @@ parse_pattern_constant_path(pm_parser_t *parser, pm_constant_id_list_t *captures
pattern_node->opening_loc = PM_LOCATION_TOKEN_VALUE(&opening);
pattern_node->closing_loc = PM_LOCATION_TOKEN_VALUE(&closing);
- return (pm_node_t *) pattern_node;
+ return UP(pattern_node);
}
break;
@@ -16230,7 +16308,7 @@ parse_pattern_constant_path(pm_parser_t *parser, pm_constant_id_list_t *captures
// attach our constant to it.
pm_array_pattern_node_t *pattern_node = pm_array_pattern_node_constant_create(parser, node, &opening, &closing);
pm_array_pattern_node_requireds_append(pattern_node, inner);
- return (pm_node_t *) pattern_node;
+ return UP(pattern_node);
}
/**
@@ -16255,12 +16333,12 @@ parse_pattern_rest(pm_parser_t *parser, pm_constant_id_list_t *captures) {
}
parse_pattern_capture(parser, captures, constant_id, &PM_LOCATION_TOKEN_VALUE(&identifier));
- name = (pm_node_t *) pm_local_variable_target_node_create(
+ name = UP(pm_local_variable_target_node_create(
parser,
&PM_LOCATION_TOKEN_VALUE(&identifier),
constant_id,
(uint32_t) (depth == -1 ? 0 : depth)
- );
+ ));
}
// Finally we can return the created node.
@@ -16279,7 +16357,7 @@ parse_pattern_keyword_rest(pm_parser_t *parser, pm_constant_id_list_t *captures)
pm_node_t *value = NULL;
if (accept1(parser, PM_TOKEN_KEYWORD_NIL)) {
- return (pm_node_t *) pm_no_keywords_parameter_node_create(parser, &operator, &parser->previous);
+ return UP(pm_no_keywords_parameter_node_create(parser, &operator, &parser->previous));
}
if (accept1(parser, PM_TOKEN_IDENTIFIER)) {
@@ -16291,15 +16369,15 @@ parse_pattern_keyword_rest(pm_parser_t *parser, pm_constant_id_list_t *captures)
}
parse_pattern_capture(parser, captures, constant_id, &PM_LOCATION_TOKEN_VALUE(&parser->previous));
- value = (pm_node_t *) pm_local_variable_target_node_create(
+ value = UP(pm_local_variable_target_node_create(
parser,
&PM_LOCATION_TOKEN_VALUE(&parser->previous),
constant_id,
(uint32_t) (depth == -1 ? 0 : depth)
- );
+ ));
}
- return (pm_node_t *) pm_assoc_splat_node_create(parser, value, &operator);
+ return UP(pm_assoc_splat_node_create(parser, value, &operator));
}
/**
@@ -16312,7 +16390,7 @@ pm_slice_is_valid_local(const pm_parser_t *parser, const uint8_t *start, const u
if (length == 0) return false;
// First ensure that it starts with a valid identifier starting character.
- size_t width = char_is_identifier_start(parser, start);
+ size_t width = char_is_identifier_start(parser, start, end - start);
if (width == 0) return false;
// Next, ensure that it's not an uppercase character.
@@ -16325,7 +16403,7 @@ pm_slice_is_valid_local(const pm_parser_t *parser, const uint8_t *start, const u
// Next, iterate through all of the bytes of the string to ensure that they
// are all valid identifier characters.
const uint8_t *cursor = start + width;
- while ((cursor < end) && (width = char_is_identifier(parser, cursor))) cursor += width;
+ while ((width = char_is_identifier(parser, cursor, end - cursor))) cursor += width;
return cursor == end;
}
@@ -16362,7 +16440,7 @@ parse_pattern_hash_implicit_value(pm_parser_t *parser, pm_constant_id_list_t *ca
(uint32_t) (depth == -1 ? 0 : depth)
);
- return (pm_node_t *) pm_implicit_node_create(parser, (pm_node_t *) target);
+ return UP(pm_implicit_node_create(parser, UP(target)));
}
/**
@@ -16380,7 +16458,7 @@ parse_pattern_hash_key(pm_parser_t *parser, pm_static_literals_t *keys, pm_node_
* Parse a hash pattern.
*/
static pm_hash_pattern_node_t *
-parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node_t *first_node) {
+parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node_t *first_node, uint16_t depth) {
pm_node_list_t assocs = { 0 };
pm_static_literals_t keys = { 0 };
pm_node_t *rest = NULL;
@@ -16395,24 +16473,24 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node
parse_pattern_hash_key(parser, &keys, first_node);
pm_node_t *value;
- if (match7(parser, PM_TOKEN_COMMA, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)) {
+ if (match8(parser, PM_TOKEN_COMMA, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_TOKEN_EOF)) {
// Otherwise, we will create an implicit local variable
// target for the value.
value = parse_pattern_hash_implicit_value(parser, captures, (pm_symbol_node_t *) first_node);
} else {
// Here we have a value for the first assoc in the list, so
// we will parse it now.
- value = parse_pattern(parser, captures, PM_PARSE_PATTERN_SINGLE, PM_ERR_PATTERN_EXPRESSION_AFTER_KEY);
+ value = parse_pattern(parser, captures, PM_PARSE_PATTERN_SINGLE, PM_ERR_PATTERN_EXPRESSION_AFTER_KEY, (uint16_t) (depth + 1));
}
pm_token_t operator = not_provided(parser);
- pm_node_t *assoc = (pm_node_t *) pm_assoc_node_create(parser, first_node, &operator, value);
+ pm_node_t *assoc = UP(pm_assoc_node_create(parser, first_node, &operator, value));
pm_node_list_append(&assocs, assoc);
break;
}
}
- /* fallthrough */
+ PRISM_FALLTHROUGH
default: {
// If we get anything else, then this is an error. For this we'll
// create a missing node for the value and create an assoc node for
@@ -16421,8 +16499,8 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node
pm_parser_err_node(parser, first_node, diag_id);
pm_token_t operator = not_provided(parser);
- pm_node_t *value = (pm_node_t *) pm_missing_node_create(parser, first_node->location.start, first_node->location.end);
- pm_node_t *assoc = (pm_node_t *) pm_assoc_node_create(parser, first_node, &operator, value);
+ pm_node_t *value = UP(pm_missing_node_create(parser, first_node->location.start, first_node->location.end));
+ pm_node_t *assoc = UP(pm_assoc_node_create(parser, first_node, &operator, value));
pm_node_list_append(&assocs, assoc);
break;
@@ -16432,7 +16510,12 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node
// If there are any other assocs, then we'll parse them now.
while (accept1(parser, PM_TOKEN_COMMA)) {
// Here we need to break to support trailing commas.
- if (match6(parser, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)) {
+ if (match7(parser, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_TOKEN_EOF)) {
+ // Trailing commas are not allowed to follow a rest pattern.
+ if (rest != NULL) {
+ pm_parser_err_token(parser, &parser->current, PM_ERR_PATTERN_EXPRESSION_AFTER_REST);
+ }
+
break;
}
@@ -16446,20 +16529,36 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node
pm_node_list_append(&assocs, assoc);
}
} else {
- expect1(parser, PM_TOKEN_LABEL, PM_ERR_PATTERN_LABEL_AFTER_COMMA);
- pm_node_t *key = (pm_node_t *) pm_symbol_node_label_create(parser, &parser->previous);
+ pm_node_t *key;
+
+ if (match1(parser, PM_TOKEN_STRING_BEGIN)) {
+ key = parse_strings(parser, NULL, true, (uint16_t) (depth + 1));
+
+ if (PM_NODE_TYPE_P(key, PM_INTERPOLATED_SYMBOL_NODE)) {
+ pm_parser_err_node(parser, key, PM_ERR_PATTERN_HASH_KEY_INTERPOLATED);
+ } else if (!pm_symbol_node_label_p(key)) {
+ pm_parser_err_node(parser, key, PM_ERR_PATTERN_LABEL_AFTER_COMMA);
+ }
+ } else {
+ expect1(parser, PM_TOKEN_LABEL, PM_ERR_PATTERN_LABEL_AFTER_COMMA);
+ key = UP(pm_symbol_node_label_create(parser, &parser->previous));
+ }
parse_pattern_hash_key(parser, &keys, key);
pm_node_t *value = NULL;
if (match7(parser, PM_TOKEN_COMMA, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)) {
- value = parse_pattern_hash_implicit_value(parser, captures, (pm_symbol_node_t *) key);
+ if (PM_NODE_TYPE_P(key, PM_SYMBOL_NODE)) {
+ value = parse_pattern_hash_implicit_value(parser, captures, (pm_symbol_node_t *) key);
+ } else {
+ value = UP(pm_missing_node_create(parser, key->location.end, key->location.end));
+ }
} else {
- value = parse_pattern(parser, captures, PM_PARSE_PATTERN_SINGLE, PM_ERR_PATTERN_EXPRESSION_AFTER_KEY);
+ value = parse_pattern(parser, captures, PM_PARSE_PATTERN_SINGLE, PM_ERR_PATTERN_EXPRESSION_AFTER_KEY, (uint16_t) (depth + 1));
}
pm_token_t operator = not_provided(parser);
- pm_node_t *assoc = (pm_node_t *) pm_assoc_node_create(parser, key, &operator, value);
+ pm_node_t *assoc = UP(pm_assoc_node_create(parser, key, &operator, value));
if (rest != NULL) {
pm_parser_err_node(parser, assoc, PM_ERR_PATTERN_EXPRESSION_AFTER_REST);
@@ -16480,7 +16579,7 @@ parse_pattern_hash(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node
* Parse a pattern expression primitive.
*/
static pm_node_t *
-parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_diagnostic_id_t diag_id) {
+parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_diagnostic_id_t diag_id, uint16_t depth) {
switch (parser->current.type) {
case PM_TOKEN_IDENTIFIER:
case PM_TOKEN_METHOD_NAME: {
@@ -16493,12 +16592,12 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
}
parse_pattern_capture(parser, captures, constant_id, &PM_LOCATION_TOKEN_VALUE(&parser->previous));
- return (pm_node_t *) pm_local_variable_target_node_create(
+ return UP(pm_local_variable_target_node_create(
parser,
&PM_LOCATION_TOKEN_VALUE(&parser->previous),
constant_id,
(uint32_t) (depth == -1 ? 0 : depth)
- );
+ ));
}
case PM_TOKEN_BRACKET_LEFT_ARRAY: {
pm_token_t opening = parser->current;
@@ -16507,15 +16606,15 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
if (accept1(parser, PM_TOKEN_BRACKET_RIGHT)) {
// If we have an empty array pattern, then we'll just return a new
// array pattern node.
- return (pm_node_t *) pm_array_pattern_node_empty_create(parser, &opening, &parser->previous);
+ return UP(pm_array_pattern_node_empty_create(parser, &opening, &parser->previous));
}
// Otherwise, we'll parse the inner pattern, then deal with it depending
// on the type it returns.
- pm_node_t *inner = parse_pattern(parser, captures, PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET);
+ pm_node_t *inner = parse_pattern(parser, captures, PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET, (uint16_t) (depth + 1));
accept1(parser, PM_TOKEN_NEWLINE);
- expect1(parser, PM_TOKEN_BRACKET_RIGHT, PM_ERR_PATTERN_TERM_BRACKET);
+ expect1_opening(parser, PM_TOKEN_BRACKET_RIGHT, PM_ERR_PATTERN_TERM_BRACKET, &opening);
pm_token_t closing = parser->previous;
switch (PM_NODE_TYPE(inner)) {
@@ -16528,7 +16627,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
pattern_node->opening_loc = PM_LOCATION_TOKEN_VALUE(&opening);
pattern_node->closing_loc = PM_LOCATION_TOKEN_VALUE(&closing);
- return (pm_node_t *) pattern_node;
+ return UP(pattern_node);
}
break;
@@ -16542,7 +16641,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
pattern_node->opening_loc = PM_LOCATION_TOKEN_VALUE(&opening);
pattern_node->closing_loc = PM_LOCATION_TOKEN_VALUE(&closing);
- return (pm_node_t *) pattern_node;
+ return UP(pattern_node);
}
break;
@@ -16553,7 +16652,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
pm_array_pattern_node_t *node = pm_array_pattern_node_empty_create(parser, &opening, &closing);
pm_array_pattern_node_requireds_append(node, inner);
- return (pm_node_t *) node;
+ return UP(node);
}
case PM_TOKEN_BRACE_LEFT: {
bool previous_pattern_matching_newlines = parser->pattern_matching_newlines;
@@ -16573,27 +16672,27 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
switch (parser->current.type) {
case PM_TOKEN_LABEL:
parser_lex(parser);
- first_node = (pm_node_t *) pm_symbol_node_label_create(parser, &parser->previous);
+ first_node = UP(pm_symbol_node_label_create(parser, &parser->previous));
break;
case PM_TOKEN_USTAR_STAR:
first_node = parse_pattern_keyword_rest(parser, captures);
break;
case PM_TOKEN_STRING_BEGIN:
- first_node = parse_expression(parser, PM_BINDING_POWER_MAX, false, PM_ERR_PATTERN_HASH_KEY_LABEL);
+ first_node = parse_expression(parser, PM_BINDING_POWER_MAX, false, true, PM_ERR_PATTERN_HASH_KEY_LABEL, (uint16_t) (depth + 1));
break;
default: {
PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_PATTERN_HASH_KEY, pm_token_type_human(parser->current.type));
parser_lex(parser);
- first_node = (pm_node_t *) pm_missing_node_create(parser, parser->previous.start, parser->previous.end);
+ first_node = UP(pm_missing_node_create(parser, parser->previous.start, parser->previous.end));
break;
}
}
- node = parse_pattern_hash(parser, captures, first_node);
+ node = parse_pattern_hash(parser, captures, first_node, (uint16_t) (depth + 1));
accept1(parser, PM_TOKEN_NEWLINE);
- expect1(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_PATTERN_TERM_BRACE);
+ expect1_opening(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_PATTERN_TERM_BRACE, &opening);
pm_token_t closing = parser->previous;
node->base.location.start = opening.start;
@@ -16604,7 +16703,7 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
}
parser->pattern_matching_newlines = previous_pattern_matching_newlines;
- return (pm_node_t *) node;
+ return UP(node);
}
case PM_TOKEN_UDOT_DOT:
case PM_TOKEN_UDOT_DOT_DOT: {
@@ -16615,18 +16714,31 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
// expression as the right side of the range.
switch (parser->current.type) {
case PM_CASE_PRIMITIVE: {
- pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MAX, false, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE);
- return (pm_node_t *) pm_range_node_create(parser, NULL, &operator, right);
+ pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MAX, false, false, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE, (uint16_t) (depth + 1));
+ return UP(pm_range_node_create(parser, NULL, &operator, right));
}
default: {
pm_parser_err_token(parser, &operator, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE);
- pm_node_t *right = (pm_node_t *) pm_missing_node_create(parser, operator.start, operator.end);
- return (pm_node_t *) pm_range_node_create(parser, NULL, &operator, right);
+ pm_node_t *right = UP(pm_missing_node_create(parser, operator.start, operator.end));
+ return UP(pm_range_node_create(parser, NULL, &operator, right));
}
}
}
case PM_CASE_PRIMITIVE: {
- pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_MAX, false, diag_id);
+ pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_MAX, false, true, diag_id, (uint16_t) (depth + 1));
+
+ // If we found a label, we need to immediately return to the caller.
+ if (pm_symbol_node_label_p(node)) return node;
+
+ // Call nodes (arithmetic operations) are not allowed in patterns
+ if (PM_NODE_TYPE(node) == PM_CALL_NODE) {
+ pm_parser_err_node(parser, node, diag_id);
+ pm_missing_node_t *missing_node = pm_missing_node_create(parser, node->location.start, node->location.end);
+
+ pm_node_unreference(parser, node);
+ pm_node_destroy(parser, node);
+ return UP(missing_node);
+ }
// Now that we have a primitive, we need to check if it's part of a range.
if (accept2(parser, PM_TOKEN_DOT_DOT, PM_TOKEN_DOT_DOT_DOT)) {
@@ -16637,11 +16749,11 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
// node. Otherwise, we'll create an endless range.
switch (parser->current.type) {
case PM_CASE_PRIMITIVE: {
- pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MAX, false, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE);
- return (pm_node_t *) pm_range_node_create(parser, node, &operator, right);
+ pm_node_t *right = parse_expression(parser, PM_BINDING_POWER_MAX, false, false, PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE, (uint16_t) (depth + 1));
+ return UP(pm_range_node_create(parser, node, &operator, right));
}
default:
- return (pm_node_t *) pm_range_node_create(parser, node, &operator, NULL);
+ return UP(pm_range_node_create(parser, node, &operator, NULL));
}
}
@@ -16656,44 +16768,44 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
switch (parser->current.type) {
case PM_TOKEN_IDENTIFIER: {
parser_lex(parser);
- pm_node_t *variable = (pm_node_t *) parse_variable(parser);
+ pm_node_t *variable = UP(parse_variable(parser));
if (variable == NULL) {
PM_PARSER_ERR_TOKEN_FORMAT_CONTENT(parser, parser->previous, PM_ERR_NO_LOCAL_VARIABLE);
- variable = (pm_node_t *) pm_local_variable_read_node_missing_create(parser, &parser->previous, 0);
+ variable = UP(pm_local_variable_read_node_missing_create(parser, &parser->previous, 0));
}
- return (pm_node_t *) pm_pinned_variable_node_create(parser, &operator, variable);
+ return UP(pm_pinned_variable_node_create(parser, &operator, variable));
}
case PM_TOKEN_INSTANCE_VARIABLE: {
parser_lex(parser);
- pm_node_t *variable = (pm_node_t *) pm_instance_variable_read_node_create(parser, &parser->previous);
+ pm_node_t *variable = UP(pm_instance_variable_read_node_create(parser, &parser->previous));
- return (pm_node_t *) pm_pinned_variable_node_create(parser, &operator, variable);
+ return UP(pm_pinned_variable_node_create(parser, &operator, variable));
}
case PM_TOKEN_CLASS_VARIABLE: {
parser_lex(parser);
- pm_node_t *variable = (pm_node_t *) pm_class_variable_read_node_create(parser, &parser->previous);
+ pm_node_t *variable = UP(pm_class_variable_read_node_create(parser, &parser->previous));
- return (pm_node_t *) pm_pinned_variable_node_create(parser, &operator, variable);
+ return UP(pm_pinned_variable_node_create(parser, &operator, variable));
}
case PM_TOKEN_GLOBAL_VARIABLE: {
parser_lex(parser);
- pm_node_t *variable = (pm_node_t *) pm_global_variable_read_node_create(parser, &parser->previous);
+ pm_node_t *variable = UP(pm_global_variable_read_node_create(parser, &parser->previous));
- return (pm_node_t *) pm_pinned_variable_node_create(parser, &operator, variable);
+ return UP(pm_pinned_variable_node_create(parser, &operator, variable));
}
case PM_TOKEN_NUMBERED_REFERENCE: {
parser_lex(parser);
- pm_node_t *variable = (pm_node_t *) pm_numbered_reference_read_node_create(parser, &parser->previous);
+ pm_node_t *variable = UP(pm_numbered_reference_read_node_create(parser, &parser->previous));
- return (pm_node_t *) pm_pinned_variable_node_create(parser, &operator, variable);
+ return UP(pm_pinned_variable_node_create(parser, &operator, variable));
}
case PM_TOKEN_BACK_REFERENCE: {
parser_lex(parser);
- pm_node_t *variable = (pm_node_t *) pm_back_reference_read_node_create(parser, &parser->previous);
+ pm_node_t *variable = UP(pm_back_reference_read_node_create(parser, &parser->previous));
- return (pm_node_t *) pm_pinned_variable_node_create(parser, &operator, variable);
+ return UP(pm_pinned_variable_node_create(parser, &operator, variable));
}
case PM_TOKEN_PARENTHESIS_LEFT: {
bool previous_pattern_matching_newlines = parser->pattern_matching_newlines;
@@ -16702,19 +16814,19 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
pm_token_t lparen = parser->current;
parser_lex(parser);
- pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_STATEMENT, true, PM_ERR_PATTERN_EXPRESSION_AFTER_PIN);
+ pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_STATEMENT, true, false, PM_ERR_PATTERN_EXPRESSION_AFTER_PIN, (uint16_t) (depth + 1));
parser->pattern_matching_newlines = previous_pattern_matching_newlines;
accept1(parser, PM_TOKEN_NEWLINE);
- expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_PATTERN_TERM_PAREN);
- return (pm_node_t *) pm_pinned_expression_node_create(parser, expression, &operator, &lparen, &parser->previous);
+ expect1_opening(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_PATTERN_TERM_PAREN, &lparen);
+ return UP(pm_pinned_expression_node_create(parser, expression, &operator, &lparen, &parser->previous));
}
default: {
// If we get here, then we have a pin operator followed by something
// not understood. We'll create a missing node and return that.
pm_parser_err_token(parser, &operator, PM_ERR_PATTERN_EXPRESSION_AFTER_PIN);
- pm_node_t *variable = (pm_node_t *) pm_missing_node_create(parser, operator.start, operator.end);
- return (pm_node_t *) pm_pinned_variable_node_create(parser, &operator, variable);
+ pm_node_t *variable = UP(pm_missing_node_create(parser, operator.start, operator.end));
+ return UP(pm_pinned_variable_node_create(parser, &operator, variable));
}
}
}
@@ -16725,31 +16837,54 @@ parse_pattern_primitive(pm_parser_t *parser, pm_constant_id_list_t *captures, pm
expect1(parser, PM_TOKEN_CONSTANT, PM_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT);
pm_constant_path_node_t *node = pm_constant_path_node_create(parser, NULL, &delimiter, &parser->previous);
- return parse_pattern_constant_path(parser, captures, (pm_node_t *) node);
+ return parse_pattern_constant_path(parser, captures, UP(node), (uint16_t) (depth + 1));
}
case PM_TOKEN_CONSTANT: {
pm_token_t constant = parser->current;
parser_lex(parser);
- pm_node_t *node = (pm_node_t *) pm_constant_read_node_create(parser, &constant);
- return parse_pattern_constant_path(parser, captures, node);
+ pm_node_t *node = UP(pm_constant_read_node_create(parser, &constant));
+ return parse_pattern_constant_path(parser, captures, node, (uint16_t) (depth + 1));
}
default:
pm_parser_err_current(parser, diag_id);
- return (pm_node_t *) pm_missing_node_create(parser, parser->current.start, parser->current.end);
+ return UP(pm_missing_node_create(parser, parser->current.start, parser->current.end));
+ }
+}
+
+static bool
+parse_pattern_alternation_error_each(const pm_node_t *node, void *data) {
+ switch (PM_NODE_TYPE(node)) {
+ case PM_LOCAL_VARIABLE_TARGET_NODE:
+ pm_parser_err((pm_parser_t *) data, node->location.start, node->location.end, PM_ERR_PATTERN_CAPTURE_IN_ALTERNATIVE);
+ return false;
+ default:
+ return true;
}
}
/**
+ * When we get here, we know that we already have a syntax error, because we
+ * know we have captured a variable and that we are in an alternation.
+ */
+static void
+parse_pattern_alternation_error(pm_parser_t *parser, const pm_node_t *node) {
+ pm_visit_node(node, parse_pattern_alternation_error_each, parser);
+}
+
+/**
* Parse any number of primitives joined by alternation and ended optionally by
* assignment.
*/
static pm_node_t *
-parse_pattern_primitives(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_diagnostic_id_t diag_id) {
- pm_node_t *node = NULL;
+parse_pattern_primitives(pm_parser_t *parser, pm_constant_id_list_t *captures, pm_node_t *first_node, pm_diagnostic_id_t diag_id, uint16_t depth) {
+ pm_node_t *node = first_node;
+ bool alternation = false;
- do {
- pm_token_t operator = parser->previous;
+ while ((node == NULL) || (alternation = accept1(parser, PM_TOKEN_PIPE))) {
+ if (alternation && !PM_NODE_TYPE_P(node, PM_ALTERNATION_PATTERN_NODE) && captures->size) {
+ parse_pattern_alternation_error(parser, node);
+ }
switch (parser->current.type) {
case PM_TOKEN_IDENTIFIER:
@@ -16761,46 +16896,53 @@ parse_pattern_primitives(pm_parser_t *parser, pm_constant_id_list_t *captures, p
case PM_TOKEN_UDOT_DOT:
case PM_TOKEN_UDOT_DOT_DOT:
case PM_CASE_PRIMITIVE: {
- if (node == NULL) {
- node = parse_pattern_primitive(parser, captures, diag_id);
+ if (!alternation) {
+ node = parse_pattern_primitive(parser, captures, diag_id, (uint16_t) (depth + 1));
} else {
- pm_node_t *right = parse_pattern_primitive(parser, captures, PM_ERR_PATTERN_EXPRESSION_AFTER_PIPE);
- node = (pm_node_t *) pm_alternation_pattern_node_create(parser, node, right, &operator);
+ pm_token_t operator = parser->previous;
+ pm_node_t *right = parse_pattern_primitive(parser, captures, PM_ERR_PATTERN_EXPRESSION_AFTER_PIPE, (uint16_t) (depth + 1));
+
+ if (captures->size) parse_pattern_alternation_error(parser, right);
+ node = UP(pm_alternation_pattern_node_create(parser, node, right, &operator));
}
break;
}
- case PM_TOKEN_PARENTHESIS_LEFT: {
+ case PM_TOKEN_PARENTHESIS_LEFT:
+ case PM_TOKEN_PARENTHESIS_LEFT_PARENTHESES: {
+ pm_token_t operator = parser->previous;
pm_token_t opening = parser->current;
parser_lex(parser);
- pm_node_t *body = parse_pattern(parser, captures, PM_PARSE_PATTERN_SINGLE, PM_ERR_PATTERN_EXPRESSION_AFTER_PAREN);
+ pm_node_t *body = parse_pattern(parser, captures, PM_PARSE_PATTERN_SINGLE, PM_ERR_PATTERN_EXPRESSION_AFTER_PAREN, (uint16_t) (depth + 1));
accept1(parser, PM_TOKEN_NEWLINE);
- expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_PATTERN_TERM_PAREN);
- pm_node_t *right = (pm_node_t *) pm_parentheses_node_create(parser, &opening, body, &parser->previous);
+ expect1_opening(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_PATTERN_TERM_PAREN, &opening);
+ pm_node_t *right = UP(pm_parentheses_node_create(parser, &opening, body, &parser->previous, 0));
- if (node == NULL) {
+ if (!alternation) {
node = right;
} else {
- node = (pm_node_t *) pm_alternation_pattern_node_create(parser, node, right, &operator);
+ if (captures->size) parse_pattern_alternation_error(parser, right);
+ node = UP(pm_alternation_pattern_node_create(parser, node, right, &operator));
}
break;
}
default: {
pm_parser_err_current(parser, diag_id);
- pm_node_t *right = (pm_node_t *) pm_missing_node_create(parser, parser->current.start, parser->current.end);
+ pm_node_t *right = UP(pm_missing_node_create(parser, parser->current.start, parser->current.end));
- if (node == NULL) {
+ if (!alternation) {
node = right;
} else {
- node = (pm_node_t *) pm_alternation_pattern_node_create(parser, node, right, &operator);
+ if (captures->size) parse_pattern_alternation_error(parser, right);
+ node = UP(pm_alternation_pattern_node_create(parser, node, right, &parser->previous));
}
break;
}
}
- } while (accept1(parser, PM_TOKEN_PIPE));
+ }
// If we have an =>, then we are assigning this pattern to a variable.
// In this case we should create an assignment node.
@@ -16816,14 +16958,14 @@ parse_pattern_primitives(pm_parser_t *parser, pm_constant_id_list_t *captures, p
}
parse_pattern_capture(parser, captures, constant_id, &PM_LOCATION_TOKEN_VALUE(&parser->previous));
- pm_node_t *target = (pm_node_t *) pm_local_variable_target_node_create(
+ pm_local_variable_target_node_t *target = pm_local_variable_target_node_create(
parser,
&PM_LOCATION_TOKEN_VALUE(&parser->previous),
constant_id,
(uint32_t) (depth == -1 ? 0 : depth)
);
- node = (pm_node_t *) pm_capture_pattern_node_create(parser, node, target, &operator);
+ node = UP(pm_capture_pattern_node_create(parser, node, target, &operator));
}
return node;
@@ -16833,7 +16975,7 @@ parse_pattern_primitives(pm_parser_t *parser, pm_constant_id_list_t *captures, p
* Parse a pattern matching expression.
*/
static pm_node_t *
-parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flags, pm_diagnostic_id_t diag_id) {
+parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flags, pm_diagnostic_id_t diag_id, uint16_t depth) {
pm_node_t *node = NULL;
bool leading_rest = false;
@@ -16842,8 +16984,8 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag
switch (parser->current.type) {
case PM_TOKEN_LABEL: {
parser_lex(parser);
- pm_node_t *key = (pm_node_t *) pm_symbol_node_label_create(parser, &parser->previous);
- node = (pm_node_t *) parse_pattern_hash(parser, captures, key);
+ pm_node_t *key = UP(pm_symbol_node_label_create(parser, &parser->previous));
+ node = UP(parse_pattern_hash(parser, captures, key, (uint16_t) (depth + 1)));
if (!(flags & PM_PARSE_PATTERN_TOP)) {
pm_parser_err_node(parser, node, PM_ERR_PATTERN_HASH_IMPLICIT);
@@ -16853,7 +16995,7 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag
}
case PM_TOKEN_USTAR_STAR: {
node = parse_pattern_keyword_rest(parser, captures);
- node = (pm_node_t *) parse_pattern_hash(parser, captures, node);
+ node = UP(parse_pattern_hash(parser, captures, node, (uint16_t) (depth + 1)));
if (!(flags & PM_PARSE_PATTERN_TOP)) {
pm_parser_err_node(parser, node, PM_ERR_PATTERN_HASH_IMPLICIT);
@@ -16861,75 +17003,102 @@ parse_pattern(pm_parser_t *parser, pm_constant_id_list_t *captures, uint8_t flag
return node;
}
+ case PM_TOKEN_STRING_BEGIN: {
+ // We need special handling for string beginnings because they could
+ // be dynamic symbols leading to hash patterns.
+ node = parse_pattern_primitive(parser, captures, diag_id, (uint16_t) (depth + 1));
+
+ if (pm_symbol_node_label_p(node)) {
+ node = UP(parse_pattern_hash(parser, captures, node, (uint16_t) (depth + 1)));
+
+ if (!(flags & PM_PARSE_PATTERN_TOP)) {
+ pm_parser_err_node(parser, node, PM_ERR_PATTERN_HASH_IMPLICIT);
+ }
+
+ return node;
+ }
+
+ node = parse_pattern_primitives(parser, captures, node, diag_id, (uint16_t) (depth + 1));
+ break;
+ }
case PM_TOKEN_USTAR: {
if (flags & (PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI)) {
parser_lex(parser);
- node = (pm_node_t *) parse_pattern_rest(parser, captures);
+ node = UP(parse_pattern_rest(parser, captures));
leading_rest = true;
break;
}
}
- /* fallthrough */
+ PRISM_FALLTHROUGH
default:
- node = parse_pattern_primitives(parser, captures, diag_id);
+ node = parse_pattern_primitives(parser, captures, NULL, diag_id, (uint16_t) (depth + 1));
break;
}
// If we got a dynamic label symbol, then we need to treat it like the
// beginning of a hash pattern.
if (pm_symbol_node_label_p(node)) {
- return (pm_node_t *) parse_pattern_hash(parser, captures, node);
+ return UP(parse_pattern_hash(parser, captures, node, (uint16_t) (depth + 1)));
}
if ((flags & PM_PARSE_PATTERN_MULTI) && match1(parser, PM_TOKEN_COMMA)) {
- // If we have a comma, then we are now parsing either an array pattern or a
- // find pattern. We need to parse all of the patterns, put them into a big
- // list, and then determine which type of node we have.
+ // If we have a comma, then we are now parsing either an array pattern
+ // or a find pattern. We need to parse all of the patterns, put them
+ // into a big list, and then determine which type of node we have.
pm_node_list_t nodes = { 0 };
pm_node_list_append(&nodes, node);
// Gather up all of the patterns into the list.
while (accept1(parser, PM_TOKEN_COMMA)) {
// Break early here in case we have a trailing comma.
- if (match6(parser, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_TOKEN_EOF)) {
- node = (pm_node_t *) pm_implicit_rest_node_create(parser, &parser->previous);
+ if (match7(parser, PM_TOKEN_KEYWORD_THEN, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_PARENTHESIS_RIGHT, PM_TOKEN_SEMICOLON, PM_TOKEN_KEYWORD_AND, PM_TOKEN_KEYWORD_OR)) {
+ node = UP(pm_implicit_rest_node_create(parser, &parser->previous));
pm_node_list_append(&nodes, node);
+ trailing_rest = true;
break;
}
if (accept1(parser, PM_TOKEN_USTAR)) {
- node = (pm_node_t *) parse_pattern_rest(parser, captures);
+ node = UP(parse_pattern_rest(parser, captures));
- // If we have already parsed a splat pattern, then this is an error. We
- // will continue to parse the rest of the patterns, but we will indicate
- // it as an error.
+ // If we have already parsed a splat pattern, then this is an
+ // error. We will continue to parse the rest of the patterns,
+ // but we will indicate it as an error.
if (trailing_rest) {
pm_parser_err_previous(parser, PM_ERR_PATTERN_REST);
}
trailing_rest = true;
} else {
- node = parse_pattern_primitives(parser, captures, PM_ERR_PATTERN_EXPRESSION_AFTER_COMMA);
+ node = parse_pattern_primitives(parser, captures, NULL, PM_ERR_PATTERN_EXPRESSION_AFTER_COMMA, (uint16_t) (depth + 1));
}
pm_node_list_append(&nodes, node);
}
- // If the first pattern and the last pattern are rest patterns, then we will
- // call this a find pattern, regardless of how many rest patterns are in
- // between because we know we already added the appropriate errors.
- // Otherwise we will create an array pattern.
- if (PM_NODE_TYPE_P(nodes.nodes[0], PM_SPLAT_NODE) && PM_NODE_TYPE_P(nodes.nodes[nodes.size - 1], PM_SPLAT_NODE)) {
- node = (pm_node_t *) pm_find_pattern_node_create(parser, &nodes);
+ // If the first pattern and the last pattern are rest patterns, then we
+ // will call this a find pattern, regardless of how many rest patterns
+ // are in between because we know we already added the appropriate
+ // errors. Otherwise we will create an array pattern.
+ if (leading_rest && PM_NODE_TYPE_P(nodes.nodes[nodes.size - 1], PM_SPLAT_NODE)) {
+ node = UP(pm_find_pattern_node_create(parser, &nodes));
+
+ if (nodes.size == 2) {
+ pm_parser_err_node(parser, node, PM_ERR_PATTERN_FIND_MISSING_INNER);
+ }
} else {
- node = (pm_node_t *) pm_array_pattern_node_node_list_create(parser, &nodes);
+ node = UP(pm_array_pattern_node_node_list_create(parser, &nodes));
+
+ if (leading_rest && trailing_rest) {
+ pm_parser_err_node(parser, node, PM_ERR_PATTERN_ARRAY_MULTIPLE_RESTS);
+ }
}
xfree(nodes.nodes);
} else if (leading_rest) {
- // Otherwise, if we parsed a single splat pattern, then we know we have an
- // array pattern, so we can go ahead and create that node.
- node = (pm_node_t *) pm_array_pattern_node_rest_create(parser, node);
+ // Otherwise, if we parsed a single splat pattern, then we know we have
+ // an array pattern, so we can go ahead and create that node.
+ node = UP(pm_array_pattern_node_rest_create(parser, node));
}
return node;
@@ -16972,230 +17141,6 @@ parse_negative_numeric(pm_node_t *node) {
}
/**
- * Return a string content token at a particular location that is empty.
- */
-static pm_token_t
-parse_strings_empty_content(const uint8_t *location) {
- return (pm_token_t) { .type = PM_TOKEN_STRING_CONTENT, .start = location, .end = location };
-}
-
-/**
- * Parse a set of strings that could be concatenated together.
- */
-static inline pm_node_t *
-parse_strings(pm_parser_t *parser, pm_node_t *current) {
- assert(parser->current.type == PM_TOKEN_STRING_BEGIN);
-
- bool concating = false;
- bool state_is_arg_labeled = lex_state_arg_labeled_p(parser);
-
- while (match1(parser, PM_TOKEN_STRING_BEGIN)) {
- pm_node_t *node = NULL;
-
- // Here we have found a string literal. We'll parse it and add it to
- // the list of strings.
- const pm_lex_mode_t *lex_mode = parser->lex_modes.current;
- assert(lex_mode->mode == PM_LEX_STRING);
- bool lex_interpolation = lex_mode->as.string.interpolation;
-
- pm_token_t opening = parser->current;
- parser_lex(parser);
-
- if (match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) {
- expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_EOF);
- // If we get here, then we have an end immediately after a
- // start. In that case we'll create an empty content token and
- // return an uninterpolated string.
- pm_token_t content = parse_strings_empty_content(parser->previous.start);
- pm_string_node_t *string = pm_string_node_create(parser, &opening, &content, &parser->previous);
-
- pm_string_shared_init(&string->unescaped, content.start, content.end);
- node = (pm_node_t *) string;
- } else if (accept1(parser, PM_TOKEN_LABEL_END)) {
- // If we get here, then we have an end of a label immediately
- // after a start. In that case we'll create an empty symbol
- // node.
- pm_token_t content = parse_strings_empty_content(parser->previous.start);
- pm_symbol_node_t *symbol = pm_symbol_node_create(parser, &opening, &content, &parser->previous);
-
- pm_string_shared_init(&symbol->unescaped, content.start, content.end);
- node = (pm_node_t *) symbol;
- } else if (!lex_interpolation) {
- // If we don't accept interpolation then we expect the string to
- // start with a single string content node.
- pm_string_t unescaped;
- pm_token_t content;
-
- if (match1(parser, PM_TOKEN_EOF)) {
- unescaped = PM_STRING_EMPTY;
- content = not_provided(parser);
- } else {
- unescaped = parser->current_string;
- expect1(parser, PM_TOKEN_STRING_CONTENT, PM_ERR_EXPECT_STRING_CONTENT);
- content = parser->previous;
- }
-
- // It is unfortunately possible to have multiple string content
- // nodes in a row in the case that there's heredoc content in
- // the middle of the string, like this cursed example:
- //
- // <<-END+'b
- // a
- // END
- // c'+'d'
- //
- // In that case we need to switch to an interpolated string to
- // be able to contain all of the parts.
- if (match1(parser, PM_TOKEN_STRING_CONTENT)) {
- pm_node_list_t parts = { 0 };
-
- pm_token_t delimiters = not_provided(parser);
- pm_node_t *part = (pm_node_t *) pm_string_node_create_unescaped(parser, &delimiters, &content, &delimiters, &unescaped);
- pm_node_list_append(&parts, part);
-
- do {
- part = (pm_node_t *) pm_string_node_create_current_string(parser, &delimiters, &parser->current, &delimiters);
- pm_node_list_append(&parts, part);
- parser_lex(parser);
- } while (match1(parser, PM_TOKEN_STRING_CONTENT));
-
- expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_LITERAL_EOF);
- node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous);
-
- pm_node_list_free(&parts);
- } else if (accept1(parser, PM_TOKEN_LABEL_END) && !state_is_arg_labeled) {
- node = (pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped, parse_symbol_encoding(parser, &content, &unescaped, true));
- } else if (match1(parser, PM_TOKEN_EOF)) {
- pm_parser_err_token(parser, &opening, PM_ERR_STRING_LITERAL_EOF);
- node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->current, &unescaped);
- } else if (accept1(parser, PM_TOKEN_STRING_END)) {
- node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped);
- } else {
- PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->previous, PM_ERR_STRING_LITERAL_TERM, pm_token_type_human(parser->previous.type));
- parser->previous.start = parser->previous.end;
- parser->previous.type = PM_TOKEN_MISSING;
- node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped);
- }
- } else if (match1(parser, PM_TOKEN_STRING_CONTENT)) {
- // In this case we've hit string content so we know the string
- // at least has something in it. We'll need to check if the
- // following token is the end (in which case we can return a
- // plain string) or if it's not then it has interpolation.
- pm_token_t content = parser->current;
- pm_string_t unescaped = parser->current_string;
- parser_lex(parser);
-
- if (match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) {
- node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->current, &unescaped);
- pm_node_flag_set(node, parse_unescaped_encoding(parser));
-
- // Kind of odd behavior, but basically if we have an
- // unterminated string and it ends in a newline, we back up one
- // character so that the error message is on the last line of
- // content in the string.
- if (!accept1(parser, PM_TOKEN_STRING_END)) {
- const uint8_t *location = parser->previous.end;
- if (location > parser->start && location[-1] == '\n') location--;
- pm_parser_err(parser, location, location, PM_ERR_STRING_LITERAL_EOF);
-
- parser->previous.start = parser->previous.end;
- parser->previous.type = PM_TOKEN_MISSING;
- }
- } else if (accept1(parser, PM_TOKEN_LABEL_END)) {
- node = (pm_node_t *) pm_symbol_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped, parse_symbol_encoding(parser, &content, &unescaped, true));
- } else {
- // If we get here, then we have interpolation so we'll need
- // to create a string or symbol node with interpolation.
- pm_node_list_t parts = { 0 };
- pm_token_t string_opening = not_provided(parser);
- pm_token_t string_closing = not_provided(parser);
-
- pm_node_t *part = (pm_node_t *) pm_string_node_create_unescaped(parser, &string_opening, &parser->previous, &string_closing, &unescaped);
- pm_node_flag_set(part, parse_unescaped_encoding(parser));
- pm_node_list_append(&parts, part);
-
- while (!match3(parser, PM_TOKEN_STRING_END, PM_TOKEN_LABEL_END, PM_TOKEN_EOF)) {
- if ((part = parse_string_part(parser)) != NULL) {
- pm_node_list_append(&parts, part);
- }
- }
-
- if (accept1(parser, PM_TOKEN_LABEL_END) && !state_is_arg_labeled) {
- node = (pm_node_t *) pm_interpolated_symbol_node_create(parser, &opening, &parts, &parser->previous);
- } else if (match1(parser, PM_TOKEN_EOF)) {
- pm_parser_err_token(parser, &opening, PM_ERR_STRING_INTERPOLATED_TERM);
- node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->current);
- } else {
- expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_INTERPOLATED_TERM);
- node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous);
- }
-
- pm_node_list_free(&parts);
- }
- } else {
- // If we get here, then the first part of the string is not plain
- // string content, in which case we need to parse the string as an
- // interpolated string.
- pm_node_list_t parts = { 0 };
- pm_node_t *part;
-
- while (!match3(parser, PM_TOKEN_STRING_END, PM_TOKEN_LABEL_END, PM_TOKEN_EOF)) {
- if ((part = parse_string_part(parser)) != NULL) {
- pm_node_list_append(&parts, part);
- }
- }
-
- if (accept1(parser, PM_TOKEN_LABEL_END)) {
- node = (pm_node_t *) pm_interpolated_symbol_node_create(parser, &opening, &parts, &parser->previous);
- } else if (match1(parser, PM_TOKEN_EOF)) {
- pm_parser_err_token(parser, &opening, PM_ERR_STRING_INTERPOLATED_TERM);
- node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->current);
- } else {
- expect1(parser, PM_TOKEN_STRING_END, PM_ERR_STRING_INTERPOLATED_TERM);
- node = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, &parts, &parser->previous);
- }
-
- pm_node_list_free(&parts);
- }
-
- if (current == NULL) {
- // If the node we just parsed is a symbol node, then we can't
- // concatenate it with anything else, so we can now return that
- // node.
- if (PM_NODE_TYPE_P(node, PM_SYMBOL_NODE) || PM_NODE_TYPE_P(node, PM_INTERPOLATED_SYMBOL_NODE)) {
- return node;
- }
-
- // If we don't already have a node, then it's fine and we can just
- // set the result to be the node we just parsed.
- current = node;
- } else {
- // Otherwise we need to check the type of the node we just parsed.
- // If it cannot be concatenated with the previous node, then we'll
- // need to add a syntax error.
- if (!PM_NODE_TYPE_P(node, PM_STRING_NODE) && !PM_NODE_TYPE_P(node, PM_INTERPOLATED_STRING_NODE)) {
- pm_parser_err_node(parser, node, PM_ERR_STRING_CONCATENATION);
- }
-
- // If we haven't already created our container for concatenation,
- // we'll do that now.
- if (!concating) {
- concating = true;
- pm_token_t bounds = not_provided(parser);
-
- pm_interpolated_string_node_t *container = pm_interpolated_string_node_create(parser, &bounds, NULL, &bounds);
- pm_interpolated_string_node_append(container, current);
- current = (pm_node_t *) container;
- }
-
- pm_interpolated_string_node_append((pm_interpolated_string_node_t *) current, node);
- }
- }
-
- return current;
-}
-
-/**
* Append an error to the error list on the parser using the given diagnostic
* ID. This function is a specialization that handles formatting the specific
* kind of error that is being appended.
@@ -17217,6 +17162,11 @@ pm_parser_err_prefix(pm_parser_t *parser, pm_diagnostic_id_t diag_id) {
PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->previous, diag_id, human, parser->previous.start[0]);
break;
}
+ case PM_ERR_UNARY_DISALLOWED:
+ case PM_ERR_EXPECT_ARGUMENT: {
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, diag_id, pm_token_type_human(parser->current.type));
+ break;
+ }
default:
pm_parser_err_previous(parser, diag_id);
break;
@@ -17228,7 +17178,12 @@ pm_parser_err_prefix(pm_parser_t *parser, pm_diagnostic_id_t diag_id) {
*/
static void
parse_retry(pm_parser_t *parser, const pm_node_t *node) {
+#define CONTEXT_NONE 0
+#define CONTEXT_THROUGH_ENSURE 1
+#define CONTEXT_THROUGH_ELSE 2
+
pm_context_node_t *context_node = parser->current_context;
+ int context = CONTEXT_NONE;
while (context_node != NULL) {
switch (context_node->context) {
@@ -17252,7 +17207,13 @@ parse_retry(pm_parser_t *parser, const pm_node_t *node) {
case PM_CONTEXT_SCLASS:
// These are the bad cases. We're not allowed to have a retry in
// these contexts.
- pm_parser_err_node(parser, node, PM_ERR_INVALID_RETRY_WITHOUT_RESCUE);
+ if (context == CONTEXT_NONE) {
+ pm_parser_err_node(parser, node, PM_ERR_INVALID_RETRY_WITHOUT_RESCUE);
+ } else if (context == CONTEXT_THROUGH_ENSURE) {
+ pm_parser_err_node(parser, node, PM_ERR_INVALID_RETRY_AFTER_ENSURE);
+ } else if (context == CONTEXT_THROUGH_ELSE) {
+ pm_parser_err_node(parser, node, PM_ERR_INVALID_RETRY_AFTER_ELSE);
+ }
return;
case PM_CONTEXT_BEGIN_ELSE:
case PM_CONTEXT_BLOCK_ELSE:
@@ -17263,8 +17224,8 @@ parse_retry(pm_parser_t *parser, const pm_node_t *node) {
case PM_CONTEXT_SCLASS_ELSE:
// These are also bad cases, but with a more specific error
// message indicating the else.
- pm_parser_err_node(parser, node, PM_ERR_INVALID_RETRY_AFTER_ELSE);
- return;
+ context = CONTEXT_THROUGH_ELSE;
+ break;
case PM_CONTEXT_BEGIN_ENSURE:
case PM_CONTEXT_BLOCK_ENSURE:
case PM_CONTEXT_CLASS_ENSURE:
@@ -17274,8 +17235,8 @@ parse_retry(pm_parser_t *parser, const pm_node_t *node) {
case PM_CONTEXT_SCLASS_ENSURE:
// These are also bad cases, but with a more specific error
// message indicating the ensure.
- pm_parser_err_node(parser, node, PM_ERR_INVALID_RETRY_AFTER_ENSURE);
- return;
+ context = CONTEXT_THROUGH_ENSURE;
+ break;
case PM_CONTEXT_NONE:
// This case should never happen.
assert(false && "unreachable");
@@ -17283,6 +17244,7 @@ parse_retry(pm_parser_t *parser, const pm_node_t *node) {
case PM_CONTEXT_BEGIN:
case PM_CONTEXT_BLOCK_BRACES:
case PM_CONTEXT_BLOCK_KEYWORDS:
+ case PM_CONTEXT_BLOCK_PARAMETERS:
case PM_CONTEXT_CASE_IN:
case PM_CONTEXT_CASE_WHEN:
case PM_CONTEXT_DEFAULT_PARAMS:
@@ -17294,6 +17256,8 @@ parse_retry(pm_parser_t *parser, const pm_node_t *node) {
case PM_CONTEXT_IF:
case PM_CONTEXT_LAMBDA_BRACES:
case PM_CONTEXT_LAMBDA_DO_END:
+ case PM_CONTEXT_LOOP_PREDICATE:
+ case PM_CONTEXT_MULTI_TARGET:
case PM_CONTEXT_PARENS:
case PM_CONTEXT_POSTEXE:
case PM_CONTEXT_PREDICATE:
@@ -17308,6 +17272,10 @@ parse_retry(pm_parser_t *parser, const pm_node_t *node) {
context_node = context_node->prev;
}
+
+#undef CONTEXT_NONE
+#undef CONTEXT_ENSURE
+#undef CONTEXT_ELSE
}
/**
@@ -17357,6 +17325,7 @@ parse_yield(pm_parser_t *parser, const pm_node_t *node) {
case PM_CONTEXT_BLOCK_KEYWORDS:
case PM_CONTEXT_BLOCK_ELSE:
case PM_CONTEXT_BLOCK_ENSURE:
+ case PM_CONTEXT_BLOCK_PARAMETERS:
case PM_CONTEXT_BLOCK_RESCUE:
case PM_CONTEXT_CASE_IN:
case PM_CONTEXT_CASE_WHEN:
@@ -17372,6 +17341,8 @@ parse_yield(pm_parser_t *parser, const pm_node_t *node) {
case PM_CONTEXT_LAMBDA_ELSE:
case PM_CONTEXT_LAMBDA_ENSURE:
case PM_CONTEXT_LAMBDA_RESCUE:
+ case PM_CONTEXT_LOOP_PREDICATE:
+ case PM_CONTEXT_MULTI_TARGET:
case PM_CONTEXT_PARENS:
case PM_CONTEXT_POSTEXE:
case PM_CONTEXT_PREDICATE:
@@ -17391,10 +17362,67 @@ parse_yield(pm_parser_t *parser, const pm_node_t *node) {
}
/**
+ * This struct is used to pass information between the regular expression parser
+ * and the error callback.
+ */
+typedef struct {
+ /** The parser that we are parsing the regular expression for. */
+ pm_parser_t *parser;
+
+ /** The start of the regular expression. */
+ const uint8_t *start;
+
+ /** The end of the regular expression. */
+ const uint8_t *end;
+
+ /**
+ * Whether or not the source of the regular expression is shared. This
+ * impacts the location of error messages, because if it is shared then we
+ * can use the location directly and if it is not, then we use the bounds of
+ * the regular expression itself.
+ */
+ bool shared;
+} parse_regular_expression_error_data_t;
+
+/**
+ * This callback is called when the regular expression parser encounters a
+ * syntax error.
+ */
+static void
+parse_regular_expression_error(const uint8_t *start, const uint8_t *end, const char *message, void *data) {
+ parse_regular_expression_error_data_t *callback_data = (parse_regular_expression_error_data_t *) data;
+ pm_location_t location;
+
+ if (callback_data->shared) {
+ location = (pm_location_t) { .start = start, .end = end };
+ } else {
+ location = (pm_location_t) { .start = callback_data->start, .end = callback_data->end };
+ }
+
+ PM_PARSER_ERR_FORMAT(callback_data->parser, location.start, location.end, PM_ERR_REGEXP_PARSE_ERROR, message);
+}
+
+/**
+ * Parse the errors for the regular expression and add them to the parser.
+ */
+static void
+parse_regular_expression_errors(pm_parser_t *parser, pm_regular_expression_node_t *node) {
+ const pm_string_t *unescaped = &node->unescaped;
+ parse_regular_expression_error_data_t error_data = {
+ .parser = parser,
+ .start = node->base.location.start,
+ .end = node->base.location.end,
+ .shared = unescaped->type == PM_STRING_SHARED
+ };
+
+ pm_regexp_parse(parser, pm_string_source(unescaped), pm_string_length(unescaped), PM_NODE_FLAG_P(node, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED), NULL, NULL, parse_regular_expression_error, &error_data);
+}
+
+/**
* Parse an expression that begins with the previous node that we just lexed.
*/
static inline pm_node_t *
-parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id) {
+parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, bool accepts_label, pm_diagnostic_id_t diag_id, uint16_t depth) {
switch (parser->current.type) {
case PM_TOKEN_BRACKET_LEFT_ARRAY: {
parser_lex(parser);
@@ -17404,19 +17432,31 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
bool parsed_bare_hash = false;
while (!match2(parser, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_EOF)) {
+ bool accepted_newline = accept1(parser, PM_TOKEN_NEWLINE);
+
// Handle the case where we don't have a comma and we have a
// newline followed by a right bracket.
- if (accept1(parser, PM_TOKEN_NEWLINE) && match1(parser, PM_TOKEN_BRACKET_RIGHT)) {
+ if (accepted_newline && match1(parser, PM_TOKEN_BRACKET_RIGHT)) {
break;
}
// Ensure that we have a comma between elements in the array.
- if ((pm_array_node_size(array) != 0) && !accept1(parser, PM_TOKEN_COMMA)) {
- const uint8_t *location = parser->previous.end;
- PM_PARSER_ERR_FORMAT(parser, location, location, PM_ERR_ARRAY_SEPARATOR, pm_token_type_human(parser->current.type));
+ if (array->elements.size > 0) {
+ if (accept1(parser, PM_TOKEN_COMMA)) {
+ // If there was a comma but we also accepts a newline,
+ // then this is a syntax error.
+ if (accepted_newline) {
+ pm_parser_err_previous(parser, PM_ERR_INVALID_COMMA);
+ }
+ } else {
+ // If there was no comma, then we need to add a syntax
+ // error.
+ const uint8_t *location = parser->previous.end;
+ PM_PARSER_ERR_FORMAT(parser, location, location, PM_ERR_ARRAY_SEPARATOR, pm_token_type_human(parser->current.type));
- parser->previous.start = location;
- parser->previous.type = PM_TOKEN_MISSING;
+ parser->previous.start = location;
+ parser->previous.type = PM_TOKEN_MISSING;
+ }
}
// If we have a right bracket immediately following a comma,
@@ -17433,26 +17473,26 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
if (match3(parser, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_COMMA, PM_TOKEN_EOF)) {
pm_parser_scope_forwarding_positionals_check(parser, &operator);
} else {
- expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_ARRAY_EXPRESSION_AFTER_STAR);
+ expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_ARRAY_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1));
}
- element = (pm_node_t *) pm_splat_node_create(parser, &operator, expression);
+ element = UP(pm_splat_node_create(parser, &operator, expression));
} else if (match2(parser, PM_TOKEN_LABEL, PM_TOKEN_USTAR_STAR)) {
if (parsed_bare_hash) {
pm_parser_err_current(parser, PM_ERR_EXPRESSION_BARE_HASH);
}
- element = (pm_node_t *) pm_keyword_hash_node_create(parser);
+ element = UP(pm_keyword_hash_node_create(parser));
pm_static_literals_t hash_keys = { 0 };
if (!match8(parser, PM_TOKEN_EOF, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_TOKEN_EOF, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_BRACKET_RIGHT, PM_TOKEN_KEYWORD_DO, PM_TOKEN_PARENTHESIS_RIGHT)) {
- parse_assocs(parser, &hash_keys, element);
+ parse_assocs(parser, &hash_keys, element, (uint16_t) (depth + 1));
}
pm_static_literals_free(&hash_keys);
parsed_bare_hash = true;
} else {
- element = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_ARRAY_EXPRESSION);
+ element = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, true, PM_ERR_ARRAY_EXPRESSION, (uint16_t) (depth + 1));
if (pm_symbol_node_label_p(element) || accept1(parser, PM_TOKEN_EQUAL_GREATER)) {
if (parsed_bare_hash) {
@@ -17470,13 +17510,13 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
operator = not_provided(parser);
}
- pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_HASH_VALUE);
- pm_node_t *assoc = (pm_node_t *) pm_assoc_node_create(parser, element, &operator, value);
+ pm_node_t *value = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_HASH_VALUE, (uint16_t) (depth + 1));
+ pm_node_t *assoc = UP(pm_assoc_node_create(parser, element, &operator, value));
pm_keyword_hash_node_elements_append(hash, assoc);
- element = (pm_node_t *) hash;
+ element = UP(hash);
if (accept1(parser, PM_TOKEN_COMMA) && !match1(parser, PM_TOKEN_BRACKET_RIGHT)) {
- parse_assocs(parser, &hash_keys, element);
+ parse_assocs(parser, &hash_keys, element, (uint16_t) (depth + 1));
}
pm_static_literals_free(&hash_keys);
@@ -17489,21 +17529,34 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
accept1(parser, PM_TOKEN_NEWLINE);
- expect1(parser, PM_TOKEN_BRACKET_RIGHT, PM_ERR_ARRAY_TERM);
+
+ if (!accept1(parser, PM_TOKEN_BRACKET_RIGHT)) {
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_ARRAY_TERM, pm_token_type_human(parser->current.type));
+ parser->previous.start = parser->previous.end;
+ parser->previous.type = PM_TOKEN_MISSING;
+ }
+
pm_array_node_close_set(array, &parser->previous);
pm_accepts_block_stack_pop(parser);
- return (pm_node_t *) array;
+ return UP(array);
}
case PM_TOKEN_PARENTHESIS_LEFT:
case PM_TOKEN_PARENTHESIS_LEFT_PARENTHESES: {
pm_token_t opening = parser->current;
+ pm_node_flags_t flags = 0;
pm_node_list_t current_block_exits = { 0 };
pm_node_list_t *previous_block_exits = push_block_exits(parser, &current_block_exits);
parser_lex(parser);
- while (accept2(parser, PM_TOKEN_SEMICOLON, PM_TOKEN_NEWLINE));
+ while (true) {
+ if (accept1(parser, PM_TOKEN_SEMICOLON)) {
+ flags |= PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS;
+ } else if (!accept1(parser, PM_TOKEN_NEWLINE)) {
+ break;
+ }
+ }
// If this is the end of the file or we match a right parenthesis, then
// we have an empty parentheses node, and we can immediately return.
@@ -17513,22 +17566,36 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pop_block_exits(parser, previous_block_exits);
pm_node_list_free(&current_block_exits);
- return (pm_node_t *) pm_parentheses_node_create(parser, &opening, NULL, &parser->previous);
+ return UP(pm_parentheses_node_create(parser, &opening, NULL, &parser->previous, flags));
}
// Otherwise, we're going to parse the first statement in the list
// of statements within the parentheses.
pm_accepts_block_stack_push(parser, true);
context_push(parser, PM_CONTEXT_PARENS);
- pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_STATEMENT, true, PM_ERR_CANNOT_PARSE_EXPRESSION);
+ pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_STATEMENT, true, false, PM_ERR_CANNOT_PARSE_EXPRESSION, (uint16_t) (depth + 1));
context_pop(parser);
// Determine if this statement is followed by a terminator. In the
// case of a single statement, this is fine. But in the case of
// multiple statements it's required.
- bool terminator_found = accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
+ bool terminator_found = false;
+
+ if (accept1(parser, PM_TOKEN_SEMICOLON)) {
+ terminator_found = true;
+ flags |= PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS;
+ } else if (accept1(parser, PM_TOKEN_NEWLINE)) {
+ terminator_found = true;
+ }
+
if (terminator_found) {
- while (accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON));
+ while (true) {
+ if (accept1(parser, PM_TOKEN_SEMICOLON)) {
+ flags |= PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS;
+ } else if (!accept1(parser, PM_TOKEN_NEWLINE)) {
+ break;
+ }
+ }
}
// If we hit a right parenthesis, then we're done parsing the
@@ -17566,31 +17633,51 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
multi_target->base.location.start = lparen_loc.start;
multi_target->base.location.end = rparen_loc.end;
- if (match1(parser, PM_TOKEN_COMMA)) {
- if (binding_power == PM_BINDING_POWER_STATEMENT) {
- return parse_targets_validate(parser, (pm_node_t *) multi_target, PM_BINDING_POWER_INDEX);
- }
- return (pm_node_t *) multi_target;
+ pm_node_t *result;
+ if (match1(parser, PM_TOKEN_COMMA) && (binding_power == PM_BINDING_POWER_STATEMENT)) {
+ result = parse_targets(parser, UP(multi_target), PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
+ accept1(parser, PM_TOKEN_NEWLINE);
+ } else {
+ result = UP(multi_target);
+ }
+
+ if (context_p(parser, PM_CONTEXT_MULTI_TARGET)) {
+ // All set, this is explicitly allowed by the parent
+ // context.
+ } else if (context_p(parser, PM_CONTEXT_FOR_INDEX) && match1(parser, PM_TOKEN_KEYWORD_IN)) {
+ // All set, we're inside a for loop and we're parsing
+ // multiple targets.
+ } else if (binding_power != PM_BINDING_POWER_STATEMENT) {
+ // Multi targets are not allowed when it's not a
+ // statement level.
+ pm_parser_err_node(parser, result, PM_ERR_WRITE_TARGET_UNEXPECTED);
+ } else if (!match2(parser, PM_TOKEN_EQUAL, PM_TOKEN_PARENTHESIS_RIGHT)) {
+ // Multi targets must be followed by an equal sign in
+ // order to be valid (or a right parenthesis if they are
+ // nested).
+ pm_parser_err_node(parser, result, PM_ERR_WRITE_TARGET_UNEXPECTED);
}
- return parse_target_validate(parser, (pm_node_t *) multi_target, false);
+ return result;
}
// If we have a single statement and are ending on a right parenthesis
// and we didn't return a multiple assignment node, then we can return a
// regular parentheses node now.
pm_statements_node_t *statements = pm_statements_node_create(parser);
- pm_statements_node_body_append(parser, statements, statement);
+ pm_statements_node_body_append(parser, statements, statement, true);
- return (pm_node_t *) pm_parentheses_node_create(parser, &opening, (pm_node_t *) statements, &parser->previous);
+ return UP(pm_parentheses_node_create(parser, &opening, UP(statements), &parser->previous, flags));
}
// If we have more than one statement in the set of parentheses,
// then we are going to parse all of them as a list of statements.
// We'll do that here.
context_push(parser, PM_CONTEXT_PARENS);
+ flags |= PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS;
+
pm_statements_node_t *statements = pm_statements_node_create(parser);
- pm_statements_node_body_append(parser, statements, statement);
+ pm_statements_node_body_append(parser, statements, statement, true);
// If we didn't find a terminator and we didn't find a right
// parenthesis, then this is a syntax error.
@@ -17600,8 +17687,8 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
// Parse each statement within the parentheses.
while (true) {
- pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_STATEMENT, true, PM_ERR_CANNOT_PARSE_EXPRESSION);
- pm_statements_node_body_append(parser, statements, node);
+ pm_node_t *node = parse_expression(parser, PM_BINDING_POWER_STATEMENT, true, false, PM_ERR_CANNOT_PARSE_EXPRESSION, (uint16_t) (depth + 1));
+ pm_statements_node_body_append(parser, statements, node, true);
// If we're recovering from a syntax error, then we need to stop
// parsing the statements now.
@@ -17634,11 +17721,38 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_accepts_block_stack_pop(parser);
expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_EXPECT_RPAREN);
+ // When we're parsing multi targets, we allow them to be followed by
+ // a right parenthesis if they are at the statement level. This is
+ // only possible if they are the final statement in a parentheses.
+ // We need to explicitly reject that here.
+ {
+ pm_node_t *statement = statements->body.nodes[statements->body.size - 1];
+
+ if (PM_NODE_TYPE_P(statement, PM_SPLAT_NODE)) {
+ pm_multi_target_node_t *multi_target = pm_multi_target_node_create(parser);
+ pm_multi_target_node_targets_append(parser, multi_target, statement);
+
+ statement = UP(multi_target);
+ statements->body.nodes[statements->body.size - 1] = statement;
+ }
+
+ if (PM_NODE_TYPE_P(statement, PM_MULTI_TARGET_NODE)) {
+ const uint8_t *offset = statement->location.end;
+ pm_token_t operator = { .type = PM_TOKEN_EQUAL, .start = offset, .end = offset };
+ pm_node_t *value = UP(pm_missing_node_create(parser, offset, offset));
+
+ statement = UP(pm_multi_write_node_create(parser, (pm_multi_target_node_t *) statement, &operator, value));
+ statements->body.nodes[statements->body.size - 1] = statement;
+
+ pm_parser_err_node(parser, statement, PM_ERR_WRITE_TARGET_UNEXPECTED);
+ }
+ }
+
pop_block_exits(parser, previous_block_exits);
pm_node_list_free(&current_block_exits);
- pm_void_statements_check(parser, statements);
- return (pm_node_t *) pm_parentheses_node_create(parser, &opening, (pm_node_t *) statements, &parser->previous);
+ pm_void_statements_check(parser, statements, true);
+ return UP(pm_parentheses_node_create(parser, &opening, UP(statements), &parser->previous, flags));
}
case PM_TOKEN_BRACE_LEFT: {
// If we were passed a current_hash_keys via the parser, then that
@@ -17654,14 +17768,15 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_accepts_block_stack_push(parser, true);
parser_lex(parser);
- pm_hash_node_t *node = pm_hash_node_create(parser, &parser->previous);
+ pm_token_t opening = parser->previous;
+ pm_hash_node_t *node = pm_hash_node_create(parser, &opening);
if (!match2(parser, PM_TOKEN_BRACE_RIGHT, PM_TOKEN_EOF)) {
if (current_hash_keys != NULL) {
- parse_assocs(parser, current_hash_keys, (pm_node_t *) node);
+ parse_assocs(parser, current_hash_keys, UP(node), (uint16_t) (depth + 1));
} else {
pm_static_literals_t hash_keys = { 0 };
- parse_assocs(parser, &hash_keys, (pm_node_t *) node);
+ parse_assocs(parser, &hash_keys, UP(node), (uint16_t) (depth + 1));
pm_static_literals_free(&hash_keys);
}
@@ -17669,40 +17784,48 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
pm_accepts_block_stack_pop(parser);
- expect1(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_HASH_TERM);
+ expect1_opening(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_HASH_TERM, &opening);
pm_hash_node_closing_loc_set(node, &parser->previous);
- return (pm_node_t *) node;
+ return UP(node);
}
case PM_TOKEN_CHARACTER_LITERAL: {
- parser_lex(parser);
-
- pm_token_t opening = parser->previous;
- opening.type = PM_TOKEN_STRING_BEGIN;
- opening.end = opening.start + 1;
-
- pm_token_t content = parser->previous;
- content.type = PM_TOKEN_STRING_CONTENT;
- content.start = content.start + 1;
-
pm_token_t closing = not_provided(parser);
- pm_node_t *node = (pm_node_t *) pm_string_node_create_current_string(parser, &opening, &content, &closing);
+ pm_node_t *node = UP(pm_string_node_create_current_string(
+ parser,
+ &(pm_token_t) {
+ .type = PM_TOKEN_STRING_BEGIN,
+ .start = parser->current.start,
+ .end = parser->current.start + 1
+ },
+ &(pm_token_t) {
+ .type = PM_TOKEN_STRING_CONTENT,
+ .start = parser->current.start + 1,
+ .end = parser->current.end
+ },
+ &closing
+ ));
+
pm_node_flag_set(node, parse_unescaped_encoding(parser));
+ // Skip past the character literal here, since now we have handled
+ // parser->explicit_encoding correctly.
+ parser_lex(parser);
+
// Characters can be followed by strings in which case they are
// automatically concatenated.
if (match1(parser, PM_TOKEN_STRING_BEGIN)) {
- return parse_strings(parser, node);
+ return parse_strings(parser, node, false, (uint16_t) (depth + 1));
}
return node;
}
case PM_TOKEN_CLASS_VARIABLE: {
parser_lex(parser);
- pm_node_t *node = (pm_node_t *) pm_class_variable_read_node_create(parser, &parser->previous);
+ pm_node_t *node = UP(pm_class_variable_read_node_create(parser, &parser->previous));
if (binding_power == PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_COMMA)) {
- node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX);
+ node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
}
return node;
@@ -17720,16 +17843,16 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
match1(parser, PM_TOKEN_BRACE_LEFT)
) {
pm_arguments_t arguments = { 0 };
- parse_arguments_list(parser, &arguments, true, accepts_command_call);
- return (pm_node_t *) pm_call_node_fcall_create(parser, &constant, &arguments);
+ parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1));
+ return UP(pm_call_node_fcall_create(parser, &constant, &arguments));
}
- pm_node_t *node = (pm_node_t *) pm_constant_read_node_create(parser, &parser->previous);
+ pm_node_t *node = UP(pm_constant_read_node_create(parser, &parser->previous));
if ((binding_power == PM_BINDING_POWER_STATEMENT) && match1(parser, PM_TOKEN_COMMA)) {
// If we get here, then we have a comma immediately following a
// constant, so we're going to parse this as a multiple assignment.
- node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX);
+ node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
}
return node;
@@ -17739,10 +17862,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t delimiter = parser->previous;
expect1(parser, PM_TOKEN_CONSTANT, PM_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT);
- pm_node_t *node = (pm_node_t *) pm_constant_path_node_create(parser, NULL, &delimiter, &parser->previous);
+ pm_node_t *node = UP(pm_constant_path_node_create(parser, NULL, &delimiter, &parser->previous));
if ((binding_power == PM_BINDING_POWER_STATEMENT) && match1(parser, PM_TOKEN_COMMA)) {
- node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX);
+ node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
}
return node;
@@ -17752,47 +17875,56 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t operator = parser->current;
parser_lex(parser);
- pm_node_t *right = parse_expression(parser, pm_binding_powers[operator.type].left, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
- return (pm_node_t *) pm_range_node_create(parser, NULL, &operator, right);
+ pm_node_t *right = parse_expression(parser, pm_binding_powers[operator.type].left, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
+
+ // Unary .. and ... are special because these are non-associative
+ // operators that can also be unary operators. In this case we need
+ // to explicitly reject code that has a .. or ... that follows this
+ // expression.
+ if (match2(parser, PM_TOKEN_DOT_DOT, PM_TOKEN_DOT_DOT_DOT)) {
+ pm_parser_err_current(parser, PM_ERR_UNEXPECTED_RANGE_OPERATOR);
+ }
+
+ return UP(pm_range_node_create(parser, NULL, &operator, right));
}
case PM_TOKEN_FLOAT:
parser_lex(parser);
- return (pm_node_t *) pm_float_node_create(parser, &parser->previous);
+ return UP(pm_float_node_create(parser, &parser->previous));
case PM_TOKEN_FLOAT_IMAGINARY:
parser_lex(parser);
- return (pm_node_t *) pm_float_node_imaginary_create(parser, &parser->previous);
+ return UP(pm_float_node_imaginary_create(parser, &parser->previous));
case PM_TOKEN_FLOAT_RATIONAL:
parser_lex(parser);
- return (pm_node_t *) pm_float_node_rational_create(parser, &parser->previous);
+ return UP(pm_float_node_rational_create(parser, &parser->previous));
case PM_TOKEN_FLOAT_RATIONAL_IMAGINARY:
parser_lex(parser);
- return (pm_node_t *) pm_float_node_rational_imaginary_create(parser, &parser->previous);
+ return UP(pm_float_node_rational_imaginary_create(parser, &parser->previous));
case PM_TOKEN_NUMBERED_REFERENCE: {
parser_lex(parser);
- pm_node_t *node = (pm_node_t *) pm_numbered_reference_read_node_create(parser, &parser->previous);
+ pm_node_t *node = UP(pm_numbered_reference_read_node_create(parser, &parser->previous));
if (binding_power == PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_COMMA)) {
- node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX);
+ node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
}
return node;
}
case PM_TOKEN_GLOBAL_VARIABLE: {
parser_lex(parser);
- pm_node_t *node = (pm_node_t *) pm_global_variable_read_node_create(parser, &parser->previous);
+ pm_node_t *node = UP(pm_global_variable_read_node_create(parser, &parser->previous));
if (binding_power == PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_COMMA)) {
- node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX);
+ node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
}
return node;
}
case PM_TOKEN_BACK_REFERENCE: {
parser_lex(parser);
- pm_node_t *node = (pm_node_t *) pm_back_reference_read_node_create(parser, &parser->previous);
+ pm_node_t *node = UP(pm_back_reference_read_node_create(parser, &parser->previous));
if (binding_power == PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_COMMA)) {
- node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX);
+ node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
}
return node;
@@ -17811,27 +17943,21 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_call_node_t *call = (pm_call_node_t *) node;
pm_arguments_t arguments = { 0 };
- if (parse_arguments_list(parser, &arguments, true, accepts_command_call)) {
+ if (parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1))) {
// Since we found arguments, we need to turn off the
// variable call bit in the flags.
- pm_node_flag_unset((pm_node_t *)call, PM_CALL_NODE_FLAGS_VARIABLE_CALL);
+ pm_node_flag_unset(UP(call), PM_CALL_NODE_FLAGS_VARIABLE_CALL);
call->opening_loc = arguments.opening_loc;
call->arguments = arguments.arguments;
call->closing_loc = arguments.closing_loc;
call->block = arguments.block;
- if (arguments.block != NULL) {
- call->base.location.end = arguments.block->location.end;
- } else if (arguments.closing_loc.start == NULL) {
- if (arguments.arguments != NULL) {
- call->base.location.end = arguments.arguments->base.location.end;
- } else {
- call->base.location.end = call->message_loc.end;
- }
- } else {
- call->base.location.end = arguments.closing_loc.end;
+ const uint8_t *end = pm_arguments_end(&arguments);
+ if (!end) {
+ end = call->message_loc.end;
}
+ call->base.location.end = end;
}
} else {
// Otherwise, we know the identifier is in the local table. This
@@ -17843,14 +17969,14 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
match1(parser, PM_TOKEN_BRACE_LEFT)
) {
pm_arguments_t arguments = { 0 };
- parse_arguments_list(parser, &arguments, true, accepts_command_call);
+ parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1));
pm_call_node_t *fcall = pm_call_node_fcall_create(parser, &identifier, &arguments);
if (PM_NODE_TYPE_P(node, PM_IT_LOCAL_VARIABLE_READ_NODE)) {
// If we're about to convert an 'it' implicit local
// variable read into a method call, we need to remove
// it from the list of implicit local variables.
- parse_target_implicit_parameter(parser, node);
+ pm_node_unreference(parser, node);
} else {
// Otherwise, we're about to convert a regular local
// variable read into a method call, in which case we
@@ -17859,7 +17985,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
assert(PM_NODE_TYPE_P(node, PM_LOCAL_VARIABLE_READ_NODE));
if (pm_token_is_numbered_parameter(identifier.start, identifier.end)) {
- parse_target_implicit_parameter(parser, node);
+ pm_node_unreference(parser, node);
} else {
pm_local_variable_read_node_t *cast = (pm_local_variable_read_node_t *) node;
pm_locals_unread(&pm_parser_scope_find(parser, cast->depth)->locals, cast->name);
@@ -17867,12 +17993,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
pm_node_destroy(parser, node);
- return (pm_node_t *) fcall;
+ return UP(fcall);
}
}
if ((binding_power == PM_BINDING_POWER_STATEMENT) && match1(parser, PM_TOKEN_COMMA)) {
- node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX);
+ node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
}
return node;
@@ -17880,10 +18006,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
case PM_TOKEN_HEREDOC_START: {
// Here we have found a heredoc. We'll parse it and add it to the
// list of strings.
- pm_lex_mode_t *lex_mode = parser->lex_modes.current;
- assert(lex_mode->mode == PM_LEX_HEREDOC);
- pm_heredoc_quote_t quote = lex_mode->as.heredoc.quote;
- pm_heredoc_indent_t indent = lex_mode->as.heredoc.indent;
+ assert(parser->lex_modes.current->mode == PM_LEX_HEREDOC);
+ pm_heredoc_lex_mode_t lex_mode = parser->lex_modes.current->as.heredoc.base;
+
+ size_t common_whitespace = (size_t) -1;
+ parser->lex_modes.current->as.heredoc.common_whitespace = &common_whitespace;
parser_lex(parser);
pm_token_t opening = parser->previous;
@@ -17894,24 +18021,24 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
if (match2(parser, PM_TOKEN_HEREDOC_END, PM_TOKEN_EOF)) {
// If we get here, then we have an empty heredoc. We'll create
// an empty content token and return an empty string node.
- expect1_heredoc_term(parser, lex_mode);
+ expect1_heredoc_term(parser, lex_mode.ident_start, lex_mode.ident_length);
pm_token_t content = parse_strings_empty_content(parser->previous.start);
- if (quote == PM_HEREDOC_QUOTE_BACKTICK) {
- node = (pm_node_t *) pm_xstring_node_create_unescaped(parser, &opening, &content, &parser->previous, &PM_STRING_EMPTY);
+ if (lex_mode.quote == PM_HEREDOC_QUOTE_BACKTICK) {
+ node = UP(pm_xstring_node_create_unescaped(parser, &opening, &content, &parser->previous, &PM_STRING_EMPTY));
} else {
- node = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &content, &parser->previous, &PM_STRING_EMPTY);
+ node = UP(pm_string_node_create_unescaped(parser, &opening, &content, &parser->previous, &PM_STRING_EMPTY));
}
node->location.end = opening.end;
- } else if ((part = parse_string_part(parser)) == NULL) {
+ } else if ((part = parse_string_part(parser, (uint16_t) (depth + 1))) == NULL) {
// If we get here, then we tried to find something in the
// heredoc but couldn't actually parse anything, so we'll just
// return a missing node.
//
// parse_string_part handles its own errors, so there is no need
// for us to add one here.
- node = (pm_node_t *) pm_missing_node_create(parser, parser->previous.start, parser->previous.end);
+ node = UP(pm_missing_node_create(parser, parser->previous.start, parser->previous.end));
} else if (PM_NODE_TYPE_P(part, PM_STRING_NODE) && match2(parser, PM_TOKEN_HEREDOC_END, PM_TOKEN_EOF)) {
// If we get here, then the part that we parsed was plain string
// content and we're at the end of the heredoc, so we can return
@@ -17924,18 +18051,17 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
cast->closing_loc = PM_LOCATION_TOKEN_VALUE(&parser->current);
cast->base.location = cast->opening_loc;
- if (quote == PM_HEREDOC_QUOTE_BACKTICK) {
+ if (lex_mode.quote == PM_HEREDOC_QUOTE_BACKTICK) {
assert(sizeof(pm_string_node_t) == sizeof(pm_x_string_node_t));
cast->base.type = PM_X_STRING_NODE;
}
- size_t common_whitespace = lex_mode->as.heredoc.common_whitespace;
- if (indent == PM_HEREDOC_INDENT_TILDE && (common_whitespace != (size_t) -1) && (common_whitespace != 0)) {
+ if (lex_mode.indent == PM_HEREDOC_INDENT_TILDE && (common_whitespace != (size_t) -1) && (common_whitespace != 0)) {
parse_heredoc_dedent_string(&cast->unescaped, common_whitespace);
}
- node = (pm_node_t *) cast;
- expect1_heredoc_term(parser, lex_mode);
+ node = UP(cast);
+ expect1_heredoc_term(parser, lex_mode.ident_start, lex_mode.ident_length);
} else {
// If we get here, then we have multiple parts in the heredoc,
// so we'll need to create an interpolated string node to hold
@@ -17944,40 +18070,38 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_node_list_append(&parts, part);
while (!match2(parser, PM_TOKEN_HEREDOC_END, PM_TOKEN_EOF)) {
- if ((part = parse_string_part(parser)) != NULL) {
+ if ((part = parse_string_part(parser, (uint16_t) (depth + 1))) != NULL) {
pm_node_list_append(&parts, part);
}
}
- size_t common_whitespace = lex_mode->as.heredoc.common_whitespace;
-
// Now that we have all of the parts, create the correct type of
// interpolated node.
- if (quote == PM_HEREDOC_QUOTE_BACKTICK) {
+ if (lex_mode.quote == PM_HEREDOC_QUOTE_BACKTICK) {
pm_interpolated_x_string_node_t *cast = pm_interpolated_xstring_node_create(parser, &opening, &opening);
cast->parts = parts;
- expect1_heredoc_term(parser, lex_mode);
+ expect1_heredoc_term(parser, lex_mode.ident_start, lex_mode.ident_length);
pm_interpolated_xstring_node_closing_set(cast, &parser->previous);
cast->base.location = cast->opening_loc;
- node = (pm_node_t *) cast;
+ node = UP(cast);
} else {
pm_interpolated_string_node_t *cast = pm_interpolated_string_node_create(parser, &opening, &parts, &opening);
pm_node_list_free(&parts);
- expect1_heredoc_term(parser, lex_mode);
+ expect1_heredoc_term(parser, lex_mode.ident_start, lex_mode.ident_length);
pm_interpolated_string_node_closing_set(cast, &parser->previous);
cast->base.location = cast->opening_loc;
- node = (pm_node_t *) cast;
+ node = UP(cast);
}
// If this is a heredoc that is indented with a ~, then we need
// to dedent each line by the common leading whitespace.
- if (indent == PM_HEREDOC_INDENT_TILDE && (common_whitespace != (size_t) -1) && (common_whitespace != 0)) {
+ if (lex_mode.indent == PM_HEREDOC_INDENT_TILDE && (common_whitespace != (size_t) -1) && (common_whitespace != 0)) {
pm_node_list_t *nodes;
- if (quote == PM_HEREDOC_QUOTE_BACKTICK) {
+ if (lex_mode.quote == PM_HEREDOC_QUOTE_BACKTICK) {
nodes = &((pm_interpolated_x_string_node_t *) node)->parts;
} else {
nodes = &((pm_interpolated_string_node_t *) node)->parts;
@@ -17988,17 +18112,17 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
if (match1(parser, PM_TOKEN_STRING_BEGIN)) {
- return parse_strings(parser, node);
+ return parse_strings(parser, node, false, (uint16_t) (depth + 1));
}
return node;
}
case PM_TOKEN_INSTANCE_VARIABLE: {
parser_lex(parser);
- pm_node_t *node = (pm_node_t *) pm_instance_variable_read_node_create(parser, &parser->previous);
+ pm_node_t *node = UP(pm_instance_variable_read_node_create(parser, &parser->previous));
if (binding_power == PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_COMMA)) {
- node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX);
+ node = parse_targets_validate(parser, node, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
}
return node;
@@ -18006,32 +18130,32 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
case PM_TOKEN_INTEGER: {
pm_node_flags_t base = parser->integer_base;
parser_lex(parser);
- return (pm_node_t *) pm_integer_node_create(parser, base, &parser->previous);
+ return UP(pm_integer_node_create(parser, base, &parser->previous));
}
case PM_TOKEN_INTEGER_IMAGINARY: {
pm_node_flags_t base = parser->integer_base;
parser_lex(parser);
- return (pm_node_t *) pm_integer_node_imaginary_create(parser, base, &parser->previous);
+ return UP(pm_integer_node_imaginary_create(parser, base, &parser->previous));
}
case PM_TOKEN_INTEGER_RATIONAL: {
pm_node_flags_t base = parser->integer_base;
parser_lex(parser);
- return (pm_node_t *) pm_integer_node_rational_create(parser, base, &parser->previous);
+ return UP(pm_integer_node_rational_create(parser, base, &parser->previous));
}
case PM_TOKEN_INTEGER_RATIONAL_IMAGINARY: {
pm_node_flags_t base = parser->integer_base;
parser_lex(parser);
- return (pm_node_t *) pm_integer_node_rational_imaginary_create(parser, base, &parser->previous);
+ return UP(pm_integer_node_rational_imaginary_create(parser, base, &parser->previous));
}
case PM_TOKEN_KEYWORD___ENCODING__:
parser_lex(parser);
- return (pm_node_t *) pm_source_encoding_node_create(parser, &parser->previous);
+ return UP(pm_source_encoding_node_create(parser, &parser->previous));
case PM_TOKEN_KEYWORD___FILE__:
parser_lex(parser);
- return (pm_node_t *) pm_source_file_node_create(parser, &parser->previous);
+ return UP(pm_source_file_node_create(parser, &parser->previous));
case PM_TOKEN_KEYWORD___LINE__:
parser_lex(parser);
- return (pm_node_t *) pm_source_line_node_create(parser, &parser->previous);
+ return UP(pm_source_line_node_create(parser, &parser->previous));
case PM_TOKEN_KEYWORD_ALIAS: {
if (binding_power != PM_BINDING_POWER_STATEMENT) {
pm_parser_err_current(parser, PM_ERR_STATEMENT_ALIAS);
@@ -18040,8 +18164,8 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
parser_lex(parser);
pm_token_t keyword = parser->previous;
- pm_node_t *new_name = parse_alias_argument(parser, true);
- pm_node_t *old_name = parse_alias_argument(parser, false);
+ pm_node_t *new_name = parse_alias_argument(parser, true, (uint16_t) (depth + 1));
+ pm_node_t *old_name = parse_alias_argument(parser, false, (uint16_t) (depth + 1));
switch (PM_NODE_TYPE(new_name)) {
case PM_BACK_REFERENCE_READ_NODE:
@@ -18055,7 +18179,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_parser_err_node(parser, old_name, PM_ERR_ALIAS_ARGUMENT);
}
- return (pm_node_t *) pm_alias_global_variable_node_create(parser, &keyword, new_name, old_name);
+ return UP(pm_alias_global_variable_node_create(parser, &keyword, new_name, old_name));
}
case PM_SYMBOL_NODE:
case PM_INTERPOLATED_SYMBOL_NODE: {
@@ -18063,13 +18187,15 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_parser_err_node(parser, old_name, PM_ERR_ALIAS_ARGUMENT);
}
}
- /* fallthrough */
+ PRISM_FALLTHROUGH
default:
- return (pm_node_t *) pm_alias_method_node_create(parser, &keyword, new_name, old_name);
+ return UP(pm_alias_method_node_create(parser, &keyword, new_name, old_name));
}
}
case PM_TOKEN_KEYWORD_CASE: {
+ size_t opening_newline_index = token_newline_index(parser);
parser_lex(parser);
+
pm_token_t case_keyword = parser->previous;
pm_node_t *predicate = NULL;
@@ -18084,16 +18210,19 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
} else if (!token_begins_expression_p(parser->current.type)) {
predicate = NULL;
} else {
- predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_CASE_EXPRESSION_AFTER_CASE);
+ predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_CASE_EXPRESSION_AFTER_CASE, (uint16_t) (depth + 1));
while (accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON));
}
- if (accept1(parser, PM_TOKEN_KEYWORD_END)) {
+ if (match1(parser, PM_TOKEN_KEYWORD_END)) {
+ parser_warn_indentation_mismatch(parser, opening_newline_index, &case_keyword, false, false);
+ parser_lex(parser);
+
pop_block_exits(parser, previous_block_exits);
pm_node_list_free(&current_block_exits);
pm_parser_err_token(parser, &case_keyword, PM_ERR_CASE_MISSING_CONDITIONS);
- return (pm_node_t *) pm_case_node_create(parser, &case_keyword, predicate, &parser->previous);
+ return UP(pm_case_node_create(parser, &case_keyword, predicate, &parser->previous));
}
// At this point we can create a case node, though we don't yet know
@@ -18108,21 +18237,24 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
// At this point we've seen a when keyword, so we know this is a
// case-when node. We will continue to parse the when nodes
// until we hit the end of the list.
- while (accept1(parser, PM_TOKEN_KEYWORD_WHEN)) {
+ while (match1(parser, PM_TOKEN_KEYWORD_WHEN)) {
+ parser_warn_indentation_mismatch(parser, opening_newline_index, &case_keyword, false, true);
+ parser_lex(parser);
+
pm_token_t when_keyword = parser->previous;
pm_when_node_t *when_node = pm_when_node_create(parser, &when_keyword);
do {
if (accept1(parser, PM_TOKEN_USTAR)) {
pm_token_t operator = parser->previous;
- pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR);
+ pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1));
pm_splat_node_t *splat_node = pm_splat_node_create(parser, &operator, expression);
- pm_when_node_conditions_append(when_node, (pm_node_t *) splat_node);
+ pm_when_node_conditions_append(when_node, UP(splat_node));
if (PM_NODE_TYPE_P(expression, PM_MISSING_NODE)) break;
} else {
- pm_node_t *condition = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_CASE_EXPRESSION_AFTER_WHEN);
+ pm_node_t *condition = parse_value_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_CASE_EXPRESSION_AFTER_WHEN, (uint16_t) (depth + 1));
pm_when_node_conditions_append(when_node, condition);
// If we found a missing node, then this is a syntax
@@ -18151,13 +18283,13 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
if (!match3(parser, PM_TOKEN_KEYWORD_WHEN, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_END)) {
- pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_CASE_WHEN);
+ pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_CASE_WHEN, (uint16_t) (depth + 1));
if (statements != NULL) {
pm_when_node_statements_set(when_node, statements);
}
}
- pm_case_node_condition_append(case_node, (pm_node_t *) when_node);
+ pm_case_node_condition_append(case_node, UP(when_node));
}
// If we didn't parse any conditions (in or when) then we need
@@ -18167,7 +18299,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
pm_static_literals_free(&literals);
- node = (pm_node_t *) case_node;
+ node = UP(case_node);
} else {
pm_case_match_node_t *case_node = pm_case_match_node_create(parser, &case_keyword, predicate, &end_keyword);
@@ -18181,6 +18313,8 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
// will continue to parse the in nodes until we hit the end of
// the list.
while (match1(parser, PM_TOKEN_KEYWORD_IN)) {
+ parser_warn_indentation_mismatch(parser, opening_newline_index, &case_keyword, false, true);
+
bool previous_pattern_matching_newlines = parser->pattern_matching_newlines;
parser->pattern_matching_newlines = true;
@@ -18191,7 +18325,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t in_keyword = parser->previous;
pm_constant_id_list_t captures = { 0 };
- pm_node_t *pattern = parse_pattern(parser, &captures, PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_IN);
+ pm_node_t *pattern = parse_pattern(parser, &captures, PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_IN, (uint16_t) (depth + 1));
parser->pattern_matching_newlines = previous_pattern_matching_newlines;
pm_constant_id_list_free(&captures);
@@ -18201,12 +18335,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
// `unless` statements.
if (accept1(parser, PM_TOKEN_KEYWORD_IF_MODIFIER)) {
pm_token_t keyword = parser->previous;
- pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_CONDITIONAL_IF_PREDICATE);
- pattern = (pm_node_t *) pm_if_node_modifier_create(parser, pattern, &keyword, predicate);
+ pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_CONDITIONAL_IF_PREDICATE, (uint16_t) (depth + 1));
+ pattern = UP(pm_if_node_modifier_create(parser, pattern, &keyword, predicate));
} else if (accept1(parser, PM_TOKEN_KEYWORD_UNLESS_MODIFIER)) {
pm_token_t keyword = parser->previous;
- pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_CONDITIONAL_UNLESS_PREDICATE);
- pattern = (pm_node_t *) pm_unless_node_modifier_create(parser, pattern, &keyword, predicate);
+ pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_CONDITIONAL_UNLESS_PREDICATE, (uint16_t) (depth + 1));
+ pattern = UP(pm_unless_node_modifier_create(parser, pattern, &keyword, predicate));
}
// Now we need to check for the terminator of the in node's
@@ -18230,12 +18364,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
if (match3(parser, PM_TOKEN_KEYWORD_IN, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_END)) {
statements = NULL;
} else {
- statements = parse_statements(parser, PM_CONTEXT_CASE_IN);
+ statements = parse_statements(parser, PM_CONTEXT_CASE_IN, (uint16_t) (depth + 1));
}
// Now that we have the full pattern and statements, we can
// create the node and attach it to the case node.
- pm_node_t *condition = (pm_node_t *) pm_in_node_create(parser, pattern, statements, &in_keyword, &then_keyword);
+ pm_node_t *condition = UP(pm_in_node_create(parser, pattern, statements, &in_keyword, &then_keyword));
pm_case_match_node_condition_append(case_node, condition);
}
@@ -18245,7 +18379,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_parser_err_token(parser, &case_keyword, PM_ERR_CASE_MISSING_CONDITIONS);
}
- node = (pm_node_t *) case_node;
+ node = UP(case_node);
}
accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
@@ -18254,19 +18388,21 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_else_node_t *else_node;
if (!match1(parser, PM_TOKEN_KEYWORD_END)) {
- else_node = pm_else_node_create(parser, &else_keyword, parse_statements(parser, PM_CONTEXT_ELSE), &parser->current);
+ else_node = pm_else_node_create(parser, &else_keyword, parse_statements(parser, PM_CONTEXT_ELSE, (uint16_t) (depth + 1)), &parser->current);
} else {
else_node = pm_else_node_create(parser, &else_keyword, NULL, &parser->current);
}
if (PM_NODE_TYPE_P(node, PM_CASE_NODE)) {
- pm_case_node_consequent_set((pm_case_node_t *) node, else_node);
+ pm_case_node_else_clause_set((pm_case_node_t *) node, else_node);
} else {
- pm_case_match_node_consequent_set((pm_case_match_node_t *) node, else_node);
+ pm_case_match_node_else_clause_set((pm_case_match_node_t *) node, else_node);
}
}
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CASE_TERM);
+ parser_warn_indentation_mismatch(parser, opening_newline_index, &case_keyword, false, false);
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CASE_TERM, &case_keyword);
+
if (PM_NODE_TYPE_P(node, PM_CASE_NODE)) {
pm_case_node_end_keyword_loc_set((pm_case_node_t *) node, &parser->previous);
} else {
@@ -18279,6 +18415,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
return node;
}
case PM_TOKEN_KEYWORD_BEGIN: {
+ size_t opening_newline_index = token_newline_index(parser);
parser_lex(parser);
pm_token_t begin_keyword = parser->previous;
@@ -18288,30 +18425,29 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_node_list_t *previous_block_exits = push_block_exits(parser, &current_block_exits);
pm_statements_node_t *begin_statements = NULL;
- if (!match3(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_END)) {
+ if (!match4(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_END)) {
pm_accepts_block_stack_push(parser, true);
- begin_statements = parse_statements(parser, PM_CONTEXT_BEGIN);
+ begin_statements = parse_statements(parser, PM_CONTEXT_BEGIN, (uint16_t) (depth + 1));
pm_accepts_block_stack_pop(parser);
accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
}
pm_begin_node_t *begin_node = pm_begin_node_create(parser, &begin_keyword, begin_statements);
- parse_rescues(parser, begin_node, PM_RESCUES_BEGIN);
+ parse_rescues(parser, opening_newline_index, &begin_keyword, begin_node, PM_RESCUES_BEGIN, (uint16_t) (depth + 1));
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_BEGIN_TERM, &begin_keyword);
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_BEGIN_TERM);
begin_node->base.location.end = parser->previous.end;
pm_begin_node_end_keyword_set(begin_node, &parser->previous);
- if ((begin_node->else_clause != NULL) && (begin_node->rescue_clause == NULL)) {
- pm_parser_err_node(parser, (pm_node_t *) begin_node->else_clause, PM_ERR_BEGIN_LONELY_ELSE);
- }
-
pop_block_exits(parser, previous_block_exits);
pm_node_list_free(&current_block_exits);
- return (pm_node_t *) begin_node;
+ return UP(begin_node);
}
case PM_TOKEN_KEYWORD_BEGIN_UPCASE: {
+ pm_node_list_t current_block_exits = { 0 };
+ pm_node_list_t *previous_block_exits = push_block_exits(parser, &current_block_exits);
+
if (binding_power != PM_BINDING_POWER_STATEMENT) {
pm_parser_err_current(parser, PM_ERR_STATEMENT_PREEXE_BEGIN);
}
@@ -18321,14 +18457,18 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
expect1(parser, PM_TOKEN_BRACE_LEFT, PM_ERR_BEGIN_UPCASE_BRACE);
pm_token_t opening = parser->previous;
- pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_PREEXE);
+ pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_PREEXE, (uint16_t) (depth + 1));
- expect1(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_BEGIN_UPCASE_TERM);
+ expect1_opening(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_BEGIN_UPCASE_TERM, &opening);
pm_context_t context = parser->current_context->context;
if ((context != PM_CONTEXT_MAIN) && (context != PM_CONTEXT_PREEXE)) {
pm_parser_err_token(parser, &keyword, PM_ERR_BEGIN_UPCASE_TOPLEVEL);
}
- return (pm_node_t *) pm_pre_execution_node_create(parser, &keyword, &opening, statements, &parser->previous);
+
+ flush_block_exits(parser, previous_block_exits);
+ pm_node_list_free(&current_block_exits);
+
+ return UP(pm_pre_execution_node_create(parser, &keyword, &opening, statements, &parser->previous));
}
case PM_TOKEN_KEYWORD_BREAK:
case PM_TOKEN_KEYWORD_NEXT:
@@ -18345,33 +18485,35 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_binding_power_t binding_power = pm_binding_powers[parser->current.type].left;
if (binding_power == PM_BINDING_POWER_UNSET || binding_power >= PM_BINDING_POWER_RANGE) {
- parse_arguments(parser, &arguments, false, PM_TOKEN_EOF);
+ pm_token_t next = parser->current;
+ parse_arguments(parser, &arguments, false, PM_TOKEN_EOF, (uint16_t) (depth + 1));
+
+ // Reject `foo && return bar`.
+ if (!accepts_command_call && arguments.arguments != NULL) {
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, next, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(next.type));
+ }
}
}
switch (keyword.type) {
case PM_TOKEN_KEYWORD_BREAK: {
- pm_node_t *node = (pm_node_t *) pm_break_node_create(parser, &keyword, arguments.arguments);
- if (!parser->parsing_eval) parse_block_exit(parser, node, "break");
+ pm_node_t *node = UP(pm_break_node_create(parser, &keyword, arguments.arguments));
+ if (!parser->partial_script) parse_block_exit(parser, node);
return node;
}
case PM_TOKEN_KEYWORD_NEXT: {
- pm_node_t *node = (pm_node_t *) pm_next_node_create(parser, &keyword, arguments.arguments);
- if (!parser->parsing_eval) parse_block_exit(parser, node, "next");
+ pm_node_t *node = UP(pm_next_node_create(parser, &keyword, arguments.arguments));
+ if (!parser->partial_script) parse_block_exit(parser, node);
return node;
}
case PM_TOKEN_KEYWORD_RETURN: {
- if (
- (parser->current_context->context == PM_CONTEXT_CLASS) ||
- (parser->current_context->context == PM_CONTEXT_MODULE)
- ) {
- pm_parser_err_previous(parser, PM_ERR_RETURN_INVALID);
- }
- return (pm_node_t *) pm_return_node_create(parser, &keyword, arguments.arguments);
+ pm_node_t *node = UP(pm_return_node_create(parser, &keyword, arguments.arguments));
+ parse_return(parser, node);
+ return node;
}
default:
assert(false && "unreachable");
- return (pm_node_t *) pm_missing_node_create(parser, parser->previous.start, parser->previous.end);
+ return UP(pm_missing_node_create(parser, parser->previous.start, parser->previous.end));
}
}
case PM_TOKEN_KEYWORD_SUPER: {
@@ -18379,24 +18521,24 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t keyword = parser->previous;
pm_arguments_t arguments = { 0 };
- parse_arguments_list(parser, &arguments, true, accepts_command_call);
+ parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1));
if (
arguments.opening_loc.start == NULL &&
arguments.arguments == NULL &&
((arguments.block == NULL) || PM_NODE_TYPE_P(arguments.block, PM_BLOCK_NODE))
) {
- return (pm_node_t *) pm_forwarding_super_node_create(parser, &keyword, &arguments);
+ return UP(pm_forwarding_super_node_create(parser, &keyword, &arguments));
}
- return (pm_node_t *) pm_super_node_create(parser, &keyword, &arguments);
+ return UP(pm_super_node_create(parser, &keyword, &arguments));
}
case PM_TOKEN_KEYWORD_YIELD: {
parser_lex(parser);
pm_token_t keyword = parser->previous;
pm_arguments_t arguments = { 0 };
- parse_arguments_list(parser, &arguments, false, accepts_command_call);
+ parse_arguments_list(parser, &arguments, false, accepts_command_call, (uint16_t) (depth + 1));
// It's possible that we've parsed a block argument through our
// call to parse_arguments_list. If we found one, we should mark it
@@ -18404,40 +18546,50 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
// yield node.
if (arguments.block != NULL) {
pm_parser_err_node(parser, arguments.block, PM_ERR_UNEXPECTED_BLOCK_ARGUMENT);
+ pm_node_unreference(parser, arguments.block);
pm_node_destroy(parser, arguments.block);
arguments.block = NULL;
}
- pm_node_t *node = (pm_node_t *) pm_yield_node_create(parser, &keyword, &arguments.opening_loc, arguments.arguments, &arguments.closing_loc);
- if (!parser->parsing_eval) parse_yield(parser, node);
+ pm_node_t *node = UP(pm_yield_node_create(parser, &keyword, &arguments.opening_loc, arguments.arguments, &arguments.closing_loc));
+ if (!parser->parsing_eval && !parser->partial_script) parse_yield(parser, node);
return node;
}
case PM_TOKEN_KEYWORD_CLASS: {
+ size_t opening_newline_index = token_newline_index(parser);
parser_lex(parser);
+
pm_token_t class_keyword = parser->previous;
pm_do_loop_stack_push(parser, false);
+ pm_node_list_t current_block_exits = { 0 };
+ pm_node_list_t *previous_block_exits = push_block_exits(parser, &current_block_exits);
+
if (accept1(parser, PM_TOKEN_LESS_LESS)) {
pm_token_t operator = parser->previous;
- pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_NOT, true, PM_ERR_EXPECT_EXPRESSION_AFTER_LESS_LESS);
+ pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_EXPECT_EXPRESSION_AFTER_LESS_LESS, (uint16_t) (depth + 1));
pm_parser_scope_push(parser, true);
- accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
+ if (!match2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON)) {
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_EXPECT_SINGLETON_CLASS_DELIMITER, pm_token_type_human(parser->current.type));
+ }
pm_node_t *statements = NULL;
- if (!match3(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_END)) {
+ if (!match4(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_END)) {
pm_accepts_block_stack_push(parser, true);
- statements = (pm_node_t *) parse_statements(parser, PM_CONTEXT_SCLASS);
+ statements = UP(parse_statements(parser, PM_CONTEXT_SCLASS, (uint16_t) (depth + 1)));
pm_accepts_block_stack_pop(parser);
}
if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) {
assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE));
- statements = (pm_node_t *) parse_rescues_implicit_begin(parser, class_keyword.start, (pm_statements_node_t *) statements, PM_RESCUES_SCLASS);
+ statements = UP(parse_rescues_implicit_begin(parser, opening_newline_index, &class_keyword, class_keyword.start, (pm_statements_node_t *) statements, PM_RESCUES_SCLASS, (uint16_t) (depth + 1)));
+ } else {
+ parser_warn_indentation_mismatch(parser, opening_newline_index, &class_keyword, false, false);
}
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CLASS_TERM);
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CLASS_TERM, &class_keyword);
pm_constant_id_list_t locals;
pm_locals_order(parser, &parser->current_scope->locals, &locals, false);
@@ -18445,13 +18597,13 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_parser_scope_pop(parser);
pm_do_loop_stack_pop(parser);
- return (pm_node_t *) pm_singleton_class_node_create(parser, &locals, &class_keyword, &operator, expression, statements, &parser->previous);
- }
+ flush_block_exits(parser, previous_block_exits);
+ pm_node_list_free(&current_block_exits);
- pm_node_list_t current_block_exits = { 0 };
- pm_node_list_t *previous_block_exits = push_block_exits(parser, &current_block_exits);
+ return UP(pm_singleton_class_node_create(parser, &locals, &class_keyword, &operator, expression, statements, &parser->previous));
+ }
- pm_node_t *constant_path = parse_expression(parser, PM_BINDING_POWER_INDEX, false, PM_ERR_CLASS_NAME);
+ pm_node_t *constant_path = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_CLASS_NAME, (uint16_t) (depth + 1));
pm_token_t name = parser->previous;
if (name.type != PM_TOKEN_CONSTANT) {
pm_parser_err_token(parser, &name, PM_ERR_CLASS_NAME);
@@ -18467,7 +18619,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
parser->command_start = true;
parser_lex(parser);
- superclass = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_CLASS_SUPERCLASS);
+ superclass = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_CLASS_SUPERCLASS, (uint16_t) (depth + 1));
} else {
inheritance_operator = not_provided(parser);
superclass = NULL;
@@ -18482,18 +18634,20 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
pm_node_t *statements = NULL;
- if (!match3(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_END)) {
+ if (!match4(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_END)) {
pm_accepts_block_stack_push(parser, true);
- statements = (pm_node_t *) parse_statements(parser, PM_CONTEXT_CLASS);
+ statements = UP(parse_statements(parser, PM_CONTEXT_CLASS, (uint16_t) (depth + 1)));
pm_accepts_block_stack_pop(parser);
}
if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) {
assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE));
- statements = (pm_node_t *) parse_rescues_implicit_begin(parser, class_keyword.start, (pm_statements_node_t *) statements, PM_RESCUES_CLASS);
+ statements = UP(parse_rescues_implicit_begin(parser, opening_newline_index, &class_keyword, class_keyword.start, (pm_statements_node_t *) statements, PM_RESCUES_CLASS, (uint16_t) (depth + 1)));
+ } else {
+ parser_warn_indentation_mismatch(parser, opening_newline_index, &class_keyword, false, false);
}
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CLASS_TERM);
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_CLASS_TERM, &class_keyword);
if (context_def_p(parser)) {
pm_parser_err_token(parser, &class_keyword, PM_ERR_CLASS_IN_METHOD);
@@ -18512,10 +18666,14 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pop_block_exits(parser, previous_block_exits);
pm_node_list_free(&current_block_exits);
- return (pm_node_t *) pm_class_node_create(parser, &locals, &class_keyword, constant_path, &name, &inheritance_operator, superclass, statements, &parser->previous);
+ return UP(pm_class_node_create(parser, &locals, &class_keyword, constant_path, &name, &inheritance_operator, superclass, statements, &parser->previous));
}
case PM_TOKEN_KEYWORD_DEF: {
+ pm_node_list_t current_block_exits = { 0 };
+ pm_node_list_t *previous_block_exits = push_block_exits(parser, &current_block_exits);
+
pm_token_t def_keyword = parser->current;
+ size_t opening_newline_index = token_newline_index(parser);
pm_node_t *receiver = NULL;
pm_token_t operator = not_provided(parser);
@@ -18527,6 +18685,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
context_push(parser, PM_CONTEXT_DEF_PARAMS);
parser_lex(parser);
+ // This will be false if the method name is not a valid identifier
+ // but could be followed by an operator.
+ bool valid_name = true;
+
switch (parser->current.type) {
case PM_CASE_OPERATOR:
pm_parser_scope_push(parser, true);
@@ -18556,10 +18718,12 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
break;
}
- case PM_TOKEN_CONSTANT:
case PM_TOKEN_INSTANCE_VARIABLE:
case PM_TOKEN_CLASS_VARIABLE:
case PM_TOKEN_GLOBAL_VARIABLE:
+ valid_name = false;
+ PRISM_FALLTHROUGH
+ case PM_TOKEN_CONSTANT:
case PM_TOKEN_KEYWORD_NIL:
case PM_TOKEN_KEYWORD_SELF:
case PM_TOKEN_KEYWORD_TRUE:
@@ -18579,37 +18743,37 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
switch (identifier.type) {
case PM_TOKEN_CONSTANT:
- receiver = (pm_node_t *) pm_constant_read_node_create(parser, &identifier);
+ receiver = UP(pm_constant_read_node_create(parser, &identifier));
break;
case PM_TOKEN_INSTANCE_VARIABLE:
- receiver = (pm_node_t *) pm_instance_variable_read_node_create(parser, &identifier);
+ receiver = UP(pm_instance_variable_read_node_create(parser, &identifier));
break;
case PM_TOKEN_CLASS_VARIABLE:
- receiver = (pm_node_t *) pm_class_variable_read_node_create(parser, &identifier);
+ receiver = UP(pm_class_variable_read_node_create(parser, &identifier));
break;
case PM_TOKEN_GLOBAL_VARIABLE:
- receiver = (pm_node_t *) pm_global_variable_read_node_create(parser, &identifier);
+ receiver = UP(pm_global_variable_read_node_create(parser, &identifier));
break;
case PM_TOKEN_KEYWORD_NIL:
- receiver = (pm_node_t *) pm_nil_node_create(parser, &identifier);
+ receiver = UP(pm_nil_node_create(parser, &identifier));
break;
case PM_TOKEN_KEYWORD_SELF:
- receiver = (pm_node_t *) pm_self_node_create(parser, &identifier);
+ receiver = UP(pm_self_node_create(parser, &identifier));
break;
case PM_TOKEN_KEYWORD_TRUE:
- receiver = (pm_node_t *) pm_true_node_create(parser, &identifier);
+ receiver = UP(pm_true_node_create(parser, &identifier));
break;
case PM_TOKEN_KEYWORD_FALSE:
- receiver = (pm_node_t *) pm_false_node_create(parser, &identifier);
+ receiver = UP(pm_false_node_create(parser, &identifier));
break;
case PM_TOKEN_KEYWORD___FILE__:
- receiver = (pm_node_t *) pm_source_file_node_create(parser, &identifier);
+ receiver = UP(pm_source_file_node_create(parser, &identifier));
break;
case PM_TOKEN_KEYWORD___LINE__:
- receiver = (pm_node_t *) pm_source_line_node_create(parser, &identifier);
+ receiver = UP(pm_source_line_node_create(parser, &identifier));
break;
case PM_TOKEN_KEYWORD___ENCODING__:
- receiver = (pm_node_t *) pm_source_encoding_node_create(parser, &identifier);
+ receiver = UP(pm_source_encoding_node_create(parser, &identifier));
break;
default:
break;
@@ -18617,6 +18781,10 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
name = parse_method_definition_name(parser);
} else {
+ if (!valid_name) {
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, identifier, PM_ERR_DEF_NAME, pm_token_type_human(identifier.type));
+ }
+
name = identifier;
}
break;
@@ -18630,7 +18798,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
parser_lex(parser);
pm_token_t lparen = parser->previous;
- pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_STATEMENT, true, PM_ERR_DEF_RECEIVER);
+ pm_node_t *expression = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_DEF_RECEIVER, (uint16_t) (depth + 1));
accept1(parser, PM_TOKEN_NEWLINE);
expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_EXPECT_RPAREN);
@@ -18640,7 +18808,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
expect2(parser, PM_TOKEN_DOT, PM_TOKEN_COLON_COLON, PM_ERR_DEF_RECEIVER_TERM);
operator = parser->previous;
- receiver = (pm_node_t *) pm_parentheses_node_create(parser, &lparen, expression, &rparen);
+ receiver = UP(pm_parentheses_node_create(parser, &lparen, expression, &rparen, 0));
// To push `PM_CONTEXT_DEF_PARAMS` again is for the same
// reason as described the above.
@@ -18659,6 +18827,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t rparen;
pm_parameters_node_t *params;
+ bool accept_endless_def = true;
switch (parser->current.type) {
case PM_TOKEN_PARENTHESIS_LEFT: {
parser_lex(parser);
@@ -18667,12 +18836,13 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
if (match1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) {
params = NULL;
} else {
- params = parse_parameters(parser, PM_BINDING_POWER_DEFINED, true, false, true);
+ params = parse_parameters(parser, PM_BINDING_POWER_DEFINED, true, false, true, true, false, (uint16_t) (depth + 1));
}
lex_state_set(parser, PM_LEX_STATE_BEG);
parser->command_start = true;
+ context_pop(parser);
if (!accept1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) {
PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_DEF_PARAMS_TERM_PAREN, pm_token_type_human(parser->current.type));
parser->previous.start = parser->previous.end;
@@ -18691,18 +18861,25 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
lparen = not_provided(parser);
rparen = not_provided(parser);
- params = parse_parameters(parser, PM_BINDING_POWER_DEFINED, false, false, true);
+ params = parse_parameters(parser, PM_BINDING_POWER_DEFINED, false, false, true, true, false, (uint16_t) (depth + 1));
+
+ // Reject `def * = 1` and similar. We have to specifically check
+ // for them because they create ambiguity with optional arguments.
+ accept_endless_def = false;
+
+ context_pop(parser);
break;
}
default: {
lparen = not_provided(parser);
rparen = not_provided(parser);
params = NULL;
+
+ context_pop(parser);
break;
}
}
- context_pop(parser);
pm_node_t *statements = NULL;
pm_token_t equal;
pm_token_t end_keyword;
@@ -18711,25 +18888,42 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
if (token_is_setter_name(&name)) {
pm_parser_err_token(parser, &name, PM_ERR_DEF_ENDLESS_SETTER);
}
+ if (!accept_endless_def) {
+ pm_parser_err_previous(parser, PM_ERR_DEF_ENDLESS_PARAMETERS);
+ }
+ if (
+ parser->current_context->context == PM_CONTEXT_DEFAULT_PARAMS &&
+ parser->current_context->prev->context == PM_CONTEXT_BLOCK_PARAMETERS
+ ) {
+ PM_PARSER_ERR_FORMAT(parser, def_keyword.start, parser->previous.end, PM_ERR_UNEXPECTED_PARAMETER_DEFAULT_VALUE, "endless method definition");
+ }
equal = parser->previous;
context_push(parser, PM_CONTEXT_DEF);
pm_do_loop_stack_push(parser, false);
- statements = (pm_node_t *) pm_statements_node_create(parser);
+ statements = UP(pm_statements_node_create(parser));
- pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_DEFINED + 1, binding_power < PM_BINDING_POWER_COMPOSITION, PM_ERR_DEF_ENDLESS);
+ bool allow_command_call;
+ if (parser->version >= PM_OPTIONS_VERSION_CRUBY_4_0) {
+ allow_command_call = accepts_command_call;
+ } else {
+ // Allow `def foo = puts "Hello"` but not `private def foo = puts "Hello"`
+ allow_command_call = binding_power == PM_BINDING_POWER_ASSIGNMENT || binding_power < PM_BINDING_POWER_COMPOSITION;
+ }
+
+ pm_node_t *statement = parse_expression(parser, PM_BINDING_POWER_DEFINED + 1, allow_command_call, false, PM_ERR_DEF_ENDLESS, (uint16_t) (depth + 1));
if (accept1(parser, PM_TOKEN_KEYWORD_RESCUE_MODIFIER)) {
context_push(parser, PM_CONTEXT_RESCUE_MODIFIER);
pm_token_t rescue_keyword = parser->previous;
- pm_node_t *value = parse_expression(parser, binding_power, false, PM_ERR_RESCUE_MODIFIER_VALUE);
+ pm_node_t *value = parse_expression(parser, pm_binding_powers[PM_TOKEN_KEYWORD_RESCUE_MODIFIER].right, false, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1));
context_pop(parser);
- statement = (pm_node_t *) pm_rescue_modifier_node_create(parser, statement, &rescue_keyword, value);
+ statement = UP(pm_rescue_modifier_node_create(parser, statement, &rescue_keyword, value));
}
- pm_statements_node_body_append(parser, (pm_statements_node_t *) statements, statement);
+ pm_statements_node_body_append(parser, (pm_statements_node_t *) statements, statement, false);
pm_do_loop_stack_pop(parser);
context_pop(parser);
end_keyword = not_provided(parser);
@@ -18747,20 +18941,23 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_accepts_block_stack_push(parser, true);
pm_do_loop_stack_push(parser, false);
- if (!match3(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_END)) {
+ if (!match4(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_END)) {
pm_accepts_block_stack_push(parser, true);
- statements = (pm_node_t *) parse_statements(parser, PM_CONTEXT_DEF);
+ statements = UP(parse_statements(parser, PM_CONTEXT_DEF, (uint16_t) (depth + 1)));
pm_accepts_block_stack_pop(parser);
}
- if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) {
+ if (match3(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_ELSE)) {
assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE));
- statements = (pm_node_t *) parse_rescues_implicit_begin(parser, def_keyword.start, (pm_statements_node_t *) statements, PM_RESCUES_DEF);
+ statements = UP(parse_rescues_implicit_begin(parser, opening_newline_index, &def_keyword, def_keyword.start, (pm_statements_node_t *) statements, PM_RESCUES_DEF, (uint16_t) (depth + 1)));
+ } else {
+ parser_warn_indentation_mismatch(parser, opening_newline_index, &def_keyword, false, false);
}
pm_accepts_block_stack_pop(parser);
pm_do_loop_stack_pop(parser);
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_DEF_TERM);
+
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_DEF_TERM, &def_keyword);
end_keyword = parser->previous;
}
@@ -18769,13 +18966,16 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_parser_scope_pop(parser);
/**
- * If the final character is @. As is the case when defining
+ * If the final character is `@` as is the case when defining
* methods to override the unary operators, we should ignore
* the @ in the same way we do for symbols.
*/
pm_constant_id_t name_id = pm_parser_constant_id_location(parser, name.start, parse_operator_symbol_name(&name));
- return (pm_node_t *) pm_def_node_create(
+ flush_block_exits(parser, previous_block_exits);
+ pm_node_list_free(&current_block_exits);
+
+ return UP(pm_def_node_create(
parser,
name_id,
&name,
@@ -18789,7 +18989,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
&rparen,
&equal,
&end_keyword
- );
+ ));
}
case PM_TOKEN_KEYWORD_DEFINED: {
parser_lex(parser);
@@ -18798,33 +18998,42 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t lparen;
pm_token_t rparen;
pm_node_t *expression;
+
context_push(parser, PM_CONTEXT_DEFINED);
+ bool newline = accept1(parser, PM_TOKEN_NEWLINE);
if (accept1(parser, PM_TOKEN_PARENTHESIS_LEFT)) {
lparen = parser->previous;
- expression = parse_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_DEFINED_EXPRESSION);
- if (parser->recovering) {
+ if (newline && accept1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) {
+ expression = UP(pm_parentheses_node_create(parser, &lparen, NULL, &parser->previous, 0));
+ lparen = not_provided(parser);
rparen = not_provided(parser);
} else {
- accept1(parser, PM_TOKEN_NEWLINE);
- expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_EXPECT_RPAREN);
- rparen = parser->previous;
+ expression = parse_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_DEFINED_EXPRESSION, (uint16_t) (depth + 1));
+
+ if (parser->recovering) {
+ rparen = not_provided(parser);
+ } else {
+ accept1(parser, PM_TOKEN_NEWLINE);
+ expect1(parser, PM_TOKEN_PARENTHESIS_RIGHT, PM_ERR_EXPECT_RPAREN);
+ rparen = parser->previous;
+ }
}
} else {
lparen = not_provided(parser);
rparen = not_provided(parser);
- expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_DEFINED_EXPRESSION);
+ expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_DEFINED_EXPRESSION, (uint16_t) (depth + 1));
}
context_pop(parser);
- return (pm_node_t *) pm_defined_node_create(
+ return UP(pm_defined_node_create(
parser,
&lparen,
expression,
&rparen,
- &PM_LOCATION_TOKEN_VALUE(&keyword)
- );
+ &keyword
+ ));
}
case PM_TOKEN_KEYWORD_END_UPCASE: {
if (binding_power != PM_BINDING_POWER_STATEMENT) {
@@ -18840,16 +19049,18 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
expect1(parser, PM_TOKEN_BRACE_LEFT, PM_ERR_END_UPCASE_BRACE);
pm_token_t opening = parser->previous;
- pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_POSTEXE);
+ pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_POSTEXE, (uint16_t) (depth + 1));
- expect1(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_END_UPCASE_TERM);
- return (pm_node_t *) pm_post_execution_node_create(parser, &keyword, &opening, statements, &parser->previous);
+ expect1_opening(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_END_UPCASE_TERM, &opening);
+ return UP(pm_post_execution_node_create(parser, &keyword, &opening, statements, &parser->previous));
}
case PM_TOKEN_KEYWORD_FALSE:
parser_lex(parser);
- return (pm_node_t *)pm_false_node_create(parser, &parser->previous);
+ return UP(pm_false_node_create(parser, &parser->previous));
case PM_TOKEN_KEYWORD_FOR: {
+ size_t opening_newline_index = token_newline_index(parser);
parser_lex(parser);
+
pm_token_t for_keyword = parser->previous;
pm_node_t *index;
@@ -18861,22 +19072,22 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_node_t *name = NULL;
if (token_begins_expression_p(parser->current.type)) {
- name = parse_expression(parser, PM_BINDING_POWER_INDEX, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR);
+ name = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1));
}
- index = (pm_node_t *) pm_splat_node_create(parser, &star_operator, name);
+ index = UP(pm_splat_node_create(parser, &star_operator, name));
} else if (token_begins_expression_p(parser->current.type)) {
- index = parse_expression(parser, PM_BINDING_POWER_INDEX, false, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA);
+ index = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_COMMA, (uint16_t) (depth + 1));
} else {
pm_parser_err_token(parser, &for_keyword, PM_ERR_FOR_INDEX);
- index = (pm_node_t *) pm_missing_node_create(parser, for_keyword.start, for_keyword.end);
+ index = UP(pm_missing_node_create(parser, for_keyword.start, for_keyword.end));
}
// Now, if there are multiple index expressions, parse them out.
if (match1(parser, PM_TOKEN_COMMA)) {
- index = parse_targets(parser, index, PM_BINDING_POWER_INDEX);
+ index = parse_targets(parser, index, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
} else {
- index = parse_target(parser, index, false);
+ index = parse_target(parser, index, false, false);
}
context_pop(parser);
@@ -18885,7 +19096,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
expect1(parser, PM_TOKEN_KEYWORD_IN, PM_ERR_FOR_IN);
pm_token_t in_keyword = parser->previous;
- pm_node_t *collection = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_FOR_COLLECTION);
+ pm_node_t *collection = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_FOR_COLLECTION, (uint16_t) (depth + 1));
pm_do_loop_stack_pop(parser);
pm_token_t do_keyword;
@@ -18893,25 +19104,31 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
do_keyword = parser->previous;
} else {
do_keyword = not_provided(parser);
+ if (!match2(parser, PM_TOKEN_SEMICOLON, PM_TOKEN_NEWLINE)) {
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_EXPECT_FOR_DELIMITER, pm_token_type_human(parser->current.type));
+ }
}
- accept2(parser, PM_TOKEN_SEMICOLON, PM_TOKEN_NEWLINE);
pm_statements_node_t *statements = NULL;
-
- if (!accept1(parser, PM_TOKEN_KEYWORD_END)) {
- statements = parse_statements(parser, PM_CONTEXT_FOR);
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_FOR_TERM);
+ if (!match1(parser, PM_TOKEN_KEYWORD_END)) {
+ statements = parse_statements(parser, PM_CONTEXT_FOR, (uint16_t) (depth + 1));
}
- return (pm_node_t *) pm_for_node_create(parser, index, collection, statements, &for_keyword, &in_keyword, &do_keyword, &parser->previous);
+ parser_warn_indentation_mismatch(parser, opening_newline_index, &for_keyword, false, false);
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_FOR_TERM, &for_keyword);
+
+ return UP(pm_for_node_create(parser, index, collection, statements, &for_keyword, &in_keyword, &do_keyword, &parser->previous));
}
case PM_TOKEN_KEYWORD_IF:
if (parser_end_of_line_p(parser)) {
PM_PARSER_WARN_TOKEN_FORMAT_CONTENT(parser, parser->current, PM_WARN_KEYWORD_EOL);
}
+ size_t opening_newline_index = token_newline_index(parser);
+ bool if_after_else = parser->previous.type == PM_TOKEN_KEYWORD_ELSE;
parser_lex(parser);
- return parse_conditional(parser, PM_CONTEXT_IF);
+
+ return parse_conditional(parser, PM_CONTEXT_IF, opening_newline_index, if_after_else, (uint16_t) (depth + 1));
case PM_TOKEN_KEYWORD_UNDEF: {
if (binding_power != PM_BINDING_POWER_STATEMENT) {
pm_parser_err_current(parser, PM_ERR_STATEMENT_UNDEF);
@@ -18919,7 +19136,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
parser_lex(parser);
pm_undef_node_t *undef = pm_undef_node_create(parser, &parser->previous);
- pm_node_t *name = parse_undef_argument(parser);
+ pm_node_t *name = parse_undef_argument(parser, (uint16_t) (depth + 1));
if (PM_NODE_TYPE_P(name, PM_MISSING_NODE)) {
pm_node_destroy(parser, name);
@@ -18929,7 +19146,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
while (match1(parser, PM_TOKEN_COMMA)) {
lex_state_set(parser, PM_LEX_STATE_FNAME | PM_LEX_STATE_FITEM);
parser_lex(parser);
- name = parse_undef_argument(parser);
+ name = parse_undef_argument(parser, (uint16_t) (depth + 1));
if (PM_NODE_TYPE_P(name, PM_MISSING_NODE)) {
pm_node_destroy(parser, name);
@@ -18940,7 +19157,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
}
- return (pm_node_t *) undef;
+ return UP(undef);
}
case PM_TOKEN_KEYWORD_NOT: {
parser_lex(parser);
@@ -18949,15 +19166,30 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_arguments_t arguments = { 0 };
pm_node_t *receiver = NULL;
+ // If we do not accept a command call, then we also do not accept a
+ // not without parentheses. In this case we need to reject this
+ // syntax.
+ if (!accepts_command_call && !match1(parser, PM_TOKEN_PARENTHESIS_LEFT)) {
+ if (match1(parser, PM_TOKEN_PARENTHESIS_LEFT_PARENTHESES)) {
+ pm_parser_err(parser, parser->previous.end, parser->previous.end + 1, PM_ERR_EXPECT_LPAREN_AFTER_NOT_LPAREN);
+ } else {
+ accept1(parser, PM_TOKEN_NEWLINE);
+ pm_parser_err_current(parser, PM_ERR_EXPECT_LPAREN_AFTER_NOT_OTHER);
+ }
+
+ return UP(pm_missing_node_create(parser, parser->current.start, parser->current.end));
+ }
+
accept1(parser, PM_TOKEN_NEWLINE);
if (accept1(parser, PM_TOKEN_PARENTHESIS_LEFT)) {
- arguments.opening_loc = PM_LOCATION_TOKEN_VALUE(&parser->previous);
+ pm_token_t lparen = parser->previous;
if (accept1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) {
- arguments.closing_loc = PM_LOCATION_TOKEN_VALUE(&parser->previous);
+ receiver = UP(pm_parentheses_node_create(parser, &lparen, NULL, &parser->previous, 0));
} else {
- receiver = parse_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_NOT_EXPRESSION);
+ arguments.opening_loc = PM_LOCATION_TOKEN_VALUE(&lparen);
+ receiver = parse_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_NOT_EXPRESSION, (uint16_t) (depth + 1));
if (!parser->recovering) {
accept1(parser, PM_TOKEN_NEWLINE);
@@ -18966,22 +19198,26 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
}
} else {
- receiver = parse_expression(parser, PM_BINDING_POWER_NOT, true, PM_ERR_NOT_EXPRESSION);
+ receiver = parse_expression(parser, PM_BINDING_POWER_NOT, true, false, PM_ERR_NOT_EXPRESSION, (uint16_t) (depth + 1));
}
- return (pm_node_t *) pm_call_node_not_create(parser, receiver, &message, &arguments);
+ return UP(pm_call_node_not_create(parser, receiver, &message, &arguments));
}
- case PM_TOKEN_KEYWORD_UNLESS:
+ case PM_TOKEN_KEYWORD_UNLESS: {
+ size_t opening_newline_index = token_newline_index(parser);
parser_lex(parser);
- return parse_conditional(parser, PM_CONTEXT_UNLESS);
+
+ return parse_conditional(parser, PM_CONTEXT_UNLESS, opening_newline_index, false, (uint16_t) (depth + 1));
+ }
case PM_TOKEN_KEYWORD_MODULE: {
pm_node_list_t current_block_exits = { 0 };
pm_node_list_t *previous_block_exits = push_block_exits(parser, &current_block_exits);
+ size_t opening_newline_index = token_newline_index(parser);
parser_lex(parser);
pm_token_t module_keyword = parser->previous;
- pm_node_t *constant_path = parse_expression(parser, PM_BINDING_POWER_INDEX, false, PM_ERR_MODULE_NAME);
+ pm_node_t *constant_path = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_MODULE_NAME, (uint16_t) (depth + 1));
pm_token_t name;
// If we can recover from a syntax error that occurred while parsing
@@ -18991,14 +19227,14 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_node_list_free(&current_block_exits);
pm_token_t missing = (pm_token_t) { .type = PM_TOKEN_MISSING, .start = parser->previous.end, .end = parser->previous.end };
- return (pm_node_t *) pm_module_node_create(parser, NULL, &module_keyword, constant_path, &missing, NULL, &missing);
+ return UP(pm_module_node_create(parser, NULL, &module_keyword, constant_path, &missing, NULL, &missing));
}
while (accept1(parser, PM_TOKEN_COLON_COLON)) {
pm_token_t double_colon = parser->previous;
expect1(parser, PM_TOKEN_CONSTANT, PM_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT);
- constant_path = (pm_node_t *) pm_constant_path_node_create(parser, constant_path, &double_colon, &parser->previous);
+ constant_path = UP(pm_constant_path_node_create(parser, constant_path, &double_colon, &parser->previous));
}
// Here we retrieve the name of the module. If it wasn't a constant,
@@ -19013,22 +19249,24 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
accept2(parser, PM_TOKEN_SEMICOLON, PM_TOKEN_NEWLINE);
pm_node_t *statements = NULL;
- if (!match3(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_END)) {
+ if (!match4(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_ELSE, PM_TOKEN_KEYWORD_END)) {
pm_accepts_block_stack_push(parser, true);
- statements = (pm_node_t *) parse_statements(parser, PM_CONTEXT_MODULE);
+ statements = UP(parse_statements(parser, PM_CONTEXT_MODULE, (uint16_t) (depth + 1)));
pm_accepts_block_stack_pop(parser);
}
- if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) {
+ if (match3(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE, PM_TOKEN_KEYWORD_ELSE)) {
assert(statements == NULL || PM_NODE_TYPE_P(statements, PM_STATEMENTS_NODE));
- statements = (pm_node_t *) parse_rescues_implicit_begin(parser, module_keyword.start, (pm_statements_node_t *) statements, PM_RESCUES_MODULE);
+ statements = UP(parse_rescues_implicit_begin(parser, opening_newline_index, &module_keyword, module_keyword.start, (pm_statements_node_t *) statements, PM_RESCUES_MODULE, (uint16_t) (depth + 1)));
+ } else {
+ parser_warn_indentation_mismatch(parser, opening_newline_index, &module_keyword, false, false);
}
pm_constant_id_list_t locals;
pm_locals_order(parser, &parser->current_scope->locals, &locals, false);
pm_parser_scope_pop(parser);
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_MODULE_TERM);
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_MODULE_TERM, &module_keyword);
if (context_def_p(parser)) {
pm_parser_err_token(parser, &module_keyword, PM_ERR_MODULE_IN_METHOD);
@@ -19037,91 +19275,151 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pop_block_exits(parser, previous_block_exits);
pm_node_list_free(&current_block_exits);
- return (pm_node_t *) pm_module_node_create(parser, &locals, &module_keyword, constant_path, &name, statements, &parser->previous);
+ return UP(pm_module_node_create(parser, &locals, &module_keyword, constant_path, &name, statements, &parser->previous));
}
case PM_TOKEN_KEYWORD_NIL:
parser_lex(parser);
- return (pm_node_t *) pm_nil_node_create(parser, &parser->previous);
+ return UP(pm_nil_node_create(parser, &parser->previous));
case PM_TOKEN_KEYWORD_REDO: {
parser_lex(parser);
- pm_node_t *node = (pm_node_t *) pm_redo_node_create(parser, &parser->previous);
- if (!parser->parsing_eval) parse_block_exit(parser, node, "redo");
+ pm_node_t *node = UP(pm_redo_node_create(parser, &parser->previous));
+ if (!parser->partial_script) parse_block_exit(parser, node);
return node;
}
case PM_TOKEN_KEYWORD_RETRY: {
parser_lex(parser);
- pm_node_t *node = (pm_node_t *) pm_retry_node_create(parser, &parser->previous);
+ pm_node_t *node = UP(pm_retry_node_create(parser, &parser->previous));
parse_retry(parser, node);
return node;
}
case PM_TOKEN_KEYWORD_SELF:
parser_lex(parser);
- return (pm_node_t *) pm_self_node_create(parser, &parser->previous);
+ return UP(pm_self_node_create(parser, &parser->previous));
case PM_TOKEN_KEYWORD_TRUE:
parser_lex(parser);
- return (pm_node_t *) pm_true_node_create(parser, &parser->previous);
+ return UP(pm_true_node_create(parser, &parser->previous));
case PM_TOKEN_KEYWORD_UNTIL: {
+ size_t opening_newline_index = token_newline_index(parser);
+
+ context_push(parser, PM_CONTEXT_LOOP_PREDICATE);
pm_do_loop_stack_push(parser, true);
+
parser_lex(parser);
pm_token_t keyword = parser->previous;
+ pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_CONDITIONAL_UNTIL_PREDICATE, (uint16_t) (depth + 1));
- pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_CONDITIONAL_UNTIL_PREDICATE);
pm_do_loop_stack_pop(parser);
+ context_pop(parser);
- expect3(parser, PM_TOKEN_KEYWORD_DO_LOOP, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_ERR_CONDITIONAL_UNTIL_PREDICATE);
- pm_statements_node_t *statements = NULL;
+ pm_token_t do_keyword;
+ if (accept1(parser, PM_TOKEN_KEYWORD_DO_LOOP)) {
+ do_keyword = parser->previous;
+ } else {
+ do_keyword = not_provided(parser);
+ expect2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_ERR_CONDITIONAL_UNTIL_PREDICATE);
+ }
- if (!accept1(parser, PM_TOKEN_KEYWORD_END)) {
+ pm_statements_node_t *statements = NULL;
+ if (!match1(parser, PM_TOKEN_KEYWORD_END)) {
pm_accepts_block_stack_push(parser, true);
- statements = parse_statements(parser, PM_CONTEXT_UNTIL);
+ statements = parse_statements(parser, PM_CONTEXT_UNTIL, (uint16_t) (depth + 1));
pm_accepts_block_stack_pop(parser);
accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_UNTIL_TERM);
}
- return (pm_node_t *) pm_until_node_create(parser, &keyword, &parser->previous, predicate, statements, 0);
+ parser_warn_indentation_mismatch(parser, opening_newline_index, &keyword, false, false);
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_UNTIL_TERM, &keyword);
+
+ return UP(pm_until_node_create(parser, &keyword, &do_keyword, &parser->previous, predicate, statements, 0));
}
case PM_TOKEN_KEYWORD_WHILE: {
+ size_t opening_newline_index = token_newline_index(parser);
+
+ context_push(parser, PM_CONTEXT_LOOP_PREDICATE);
pm_do_loop_stack_push(parser, true);
+
parser_lex(parser);
pm_token_t keyword = parser->previous;
+ pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, false, PM_ERR_CONDITIONAL_WHILE_PREDICATE, (uint16_t) (depth + 1));
- pm_node_t *predicate = parse_value_expression(parser, PM_BINDING_POWER_COMPOSITION, true, PM_ERR_CONDITIONAL_WHILE_PREDICATE);
pm_do_loop_stack_pop(parser);
+ context_pop(parser);
- expect3(parser, PM_TOKEN_KEYWORD_DO_LOOP, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_ERR_CONDITIONAL_WHILE_PREDICATE);
- pm_statements_node_t *statements = NULL;
+ pm_token_t do_keyword;
+ if (accept1(parser, PM_TOKEN_KEYWORD_DO_LOOP)) {
+ do_keyword = parser->previous;
+ } else {
+ do_keyword = not_provided(parser);
+ expect2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON, PM_ERR_CONDITIONAL_WHILE_PREDICATE);
+ }
- if (!accept1(parser, PM_TOKEN_KEYWORD_END)) {
+ pm_statements_node_t *statements = NULL;
+ if (!match1(parser, PM_TOKEN_KEYWORD_END)) {
pm_accepts_block_stack_push(parser, true);
- statements = parse_statements(parser, PM_CONTEXT_WHILE);
+ statements = parse_statements(parser, PM_CONTEXT_WHILE, (uint16_t) (depth + 1));
pm_accepts_block_stack_pop(parser);
accept2(parser, PM_TOKEN_NEWLINE, PM_TOKEN_SEMICOLON);
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_WHILE_TERM);
}
- return (pm_node_t *) pm_while_node_create(parser, &keyword, &parser->previous, predicate, statements, 0);
+ parser_warn_indentation_mismatch(parser, opening_newline_index, &keyword, false, false);
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_WHILE_TERM, &keyword);
+
+ return UP(pm_while_node_create(parser, &keyword, &do_keyword, &parser->previous, predicate, statements, 0));
}
case PM_TOKEN_PERCENT_LOWER_I: {
parser_lex(parser);
pm_token_t opening = parser->previous;
pm_array_node_t *array = pm_array_node_create(parser, &opening);
+ pm_node_t *current = NULL;
while (!match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) {
accept1(parser, PM_TOKEN_WORDS_SEP);
if (match1(parser, PM_TOKEN_STRING_END)) break;
- if (match1(parser, PM_TOKEN_STRING_CONTENT)) {
+ // Interpolation is not possible but nested heredocs can still lead to
+ // consecutive (disjoint) string tokens when the final newline is escaped.
+ while (match1(parser, PM_TOKEN_STRING_CONTENT)) {
pm_token_t opening = not_provided(parser);
pm_token_t closing = not_provided(parser);
- pm_array_node_elements_append(array, (pm_node_t *) pm_symbol_node_create_current_string(parser, &opening, &parser->current, &closing));
+
+ // Record the string node, moving to interpolation if needed.
+ if (current == NULL) {
+ current = UP(pm_symbol_node_create_current_string(parser, &opening, &parser->current, &closing));
+ parser_lex(parser);
+ } else if (PM_NODE_TYPE_P(current, PM_INTERPOLATED_SYMBOL_NODE)) {
+ pm_node_t *string = UP(pm_string_node_create_current_string(parser, &opening, &parser->current, &closing));
+ parser_lex(parser);
+ pm_interpolated_symbol_node_append((pm_interpolated_symbol_node_t *) current, string);
+ } else if (PM_NODE_TYPE_P(current, PM_SYMBOL_NODE)) {
+ pm_symbol_node_t *cast = (pm_symbol_node_t *) current;
+ pm_token_t bounds = not_provided(parser);
+
+ pm_token_t content = { .type = PM_TOKEN_STRING_CONTENT, .start = cast->value_loc.start, .end = cast->value_loc.end };
+ pm_node_t *first_string = UP(pm_string_node_create_unescaped(parser, &bounds, &content, &bounds, &cast->unescaped));
+ pm_node_t *second_string = UP(pm_string_node_create_current_string(parser, &opening, &parser->previous, &closing));
+ parser_lex(parser);
+
+ pm_interpolated_symbol_node_t *interpolated = pm_interpolated_symbol_node_create(parser, &opening, NULL, &closing);
+ pm_interpolated_symbol_node_append(interpolated, first_string);
+ pm_interpolated_symbol_node_append(interpolated, second_string);
+
+ xfree(current);
+ current = UP(interpolated);
+ } else {
+ assert(false && "unreachable");
+ }
}
- expect1(parser, PM_TOKEN_STRING_CONTENT, PM_ERR_LIST_I_LOWER_ELEMENT);
+ if (current) {
+ pm_array_node_elements_append(array, current);
+ current = NULL;
+ } else {
+ expect1(parser, PM_TOKEN_STRING_CONTENT, PM_ERR_LIST_I_LOWER_ELEMENT);
+ }
}
pm_token_t closing = parser->current;
@@ -19133,7 +19431,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
pm_array_node_close_set(array, &closing);
- return (pm_node_t *) array;
+ return UP(array);
}
case PM_TOKEN_PERCENT_UPPER_I: {
parser_lex(parser);
@@ -19168,13 +19466,13 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
// If we hit content and the current node is NULL, then this is
// the first string content we've seen. In that case we're going
// to create a new string node and set that to the current.
- current = (pm_node_t *) pm_symbol_node_create_current_string(parser, &opening, &parser->current, &closing);
+ current = UP(pm_symbol_node_create_current_string(parser, &opening, &parser->current, &closing));
parser_lex(parser);
} else if (PM_NODE_TYPE_P(current, PM_INTERPOLATED_SYMBOL_NODE)) {
// If we hit string content and the current node is an
// interpolated string, then we need to append the string content
// to the list of child nodes.
- pm_node_t *string = (pm_node_t *) pm_string_node_create_current_string(parser, &opening, &parser->current, &closing);
+ pm_node_t *string = UP(pm_string_node_create_current_string(parser, &opening, &parser->current, &closing));
parser_lex(parser);
pm_interpolated_symbol_node_append((pm_interpolated_symbol_node_t *) current, string);
@@ -19186,8 +19484,8 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t bounds = not_provided(parser);
pm_token_t content = { .type = PM_TOKEN_STRING_CONTENT, .start = cast->value_loc.start, .end = cast->value_loc.end };
- pm_node_t *first_string = (pm_node_t *) pm_string_node_create_unescaped(parser, &bounds, &content, &bounds, &cast->unescaped);
- pm_node_t *second_string = (pm_node_t *) pm_string_node_create_current_string(parser, &opening, &parser->previous, &closing);
+ pm_node_t *first_string = UP(pm_string_node_create_unescaped(parser, &bounds, &content, &bounds, &cast->unescaped));
+ pm_node_t *second_string = UP(pm_string_node_create_current_string(parser, &opening, &parser->previous, &closing));
parser_lex(parser);
pm_interpolated_symbol_node_t *interpolated = pm_interpolated_symbol_node_create(parser, &opening, NULL, &closing);
@@ -19195,7 +19493,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_interpolated_symbol_node_append(interpolated, second_string);
xfree(current);
- current = (pm_node_t *) interpolated;
+ current = UP(interpolated);
} else {
assert(false && "unreachable");
}
@@ -19210,7 +19508,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
// node to a new interpolated string.
pm_token_t opening = not_provided(parser);
pm_token_t closing = not_provided(parser);
- current = (pm_node_t *) pm_interpolated_symbol_node_create(parser, &opening, NULL, &closing);
+ current = UP(pm_interpolated_symbol_node_create(parser, &opening, NULL, &closing));
} else if (PM_NODE_TYPE_P(current, PM_SYMBOL_NODE)) {
// If we hit an embedded variable and the current node is a string
// node, then we'll convert the current into an interpolated
@@ -19219,17 +19517,17 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t closing = not_provided(parser);
pm_interpolated_symbol_node_t *interpolated = pm_interpolated_symbol_node_create(parser, &opening, NULL, &closing);
- current = (pm_node_t *) pm_symbol_node_to_string_node(parser, (pm_symbol_node_t *) current);
+ current = UP(pm_symbol_node_to_string_node(parser, (pm_symbol_node_t *) current));
pm_interpolated_symbol_node_append(interpolated, current);
interpolated->base.location.start = current->location.start;
start_location_set = true;
- current = (pm_node_t *) interpolated;
+ current = UP(interpolated);
} else {
// If we hit an embedded variable and the current node is an
// interpolated string, then we'll just add the embedded variable.
}
- pm_node_t *part = parse_string_part(parser);
+ pm_node_t *part = parse_string_part(parser, (uint16_t) (depth + 1));
pm_interpolated_symbol_node_append((pm_interpolated_symbol_node_t *) current, part);
if (!start_location_set) {
current->location.start = part->location.start;
@@ -19244,7 +19542,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
// node to a new interpolated string.
pm_token_t opening = not_provided(parser);
pm_token_t closing = not_provided(parser);
- current = (pm_node_t *) pm_interpolated_symbol_node_create(parser, &opening, NULL, &closing);
+ current = UP(pm_interpolated_symbol_node_create(parser, &opening, NULL, &closing));
} else if (PM_NODE_TYPE_P(current, PM_SYMBOL_NODE)) {
// If we hit an embedded expression and the current node is a
// string node, then we'll convert the current into an
@@ -19254,11 +19552,11 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t closing = not_provided(parser);
pm_interpolated_symbol_node_t *interpolated = pm_interpolated_symbol_node_create(parser, &opening, NULL, &closing);
- current = (pm_node_t *) pm_symbol_node_to_string_node(parser, (pm_symbol_node_t *) current);
+ current = UP(pm_symbol_node_to_string_node(parser, (pm_symbol_node_t *) current));
pm_interpolated_symbol_node_append(interpolated, current);
interpolated->base.location.start = current->location.start;
start_location_set = true;
- current = (pm_node_t *) interpolated;
+ current = UP(interpolated);
} else if (PM_NODE_TYPE_P(current, PM_INTERPOLATED_SYMBOL_NODE)) {
// If we hit an embedded expression and the current node is an
// interpolated string, then we'll just continue on.
@@ -19266,7 +19564,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
assert(false && "unreachable");
}
- pm_node_t *part = parse_string_part(parser);
+ pm_node_t *part = parse_string_part(parser, (uint16_t) (depth + 1));
pm_interpolated_symbol_node_append((pm_interpolated_symbol_node_t *) current, part);
if (!start_location_set) {
current->location.start = part->location.start;
@@ -19294,29 +19592,48 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
pm_array_node_close_set(array, &closing);
- return (pm_node_t *) array;
+ return UP(array);
}
case PM_TOKEN_PERCENT_LOWER_W: {
parser_lex(parser);
pm_token_t opening = parser->previous;
pm_array_node_t *array = pm_array_node_create(parser, &opening);
-
- // skip all leading whitespaces
- accept1(parser, PM_TOKEN_WORDS_SEP);
+ pm_node_t *current = NULL;
while (!match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) {
accept1(parser, PM_TOKEN_WORDS_SEP);
if (match1(parser, PM_TOKEN_STRING_END)) break;
- if (match1(parser, PM_TOKEN_STRING_CONTENT)) {
+ // Interpolation is not possible but nested heredocs can still lead to
+ // consecutive (disjoint) string tokens when the final newline is escaped.
+ while (match1(parser, PM_TOKEN_STRING_CONTENT)) {
pm_token_t opening = not_provided(parser);
pm_token_t closing = not_provided(parser);
- pm_node_t *string = (pm_node_t *) pm_string_node_create_current_string(parser, &opening, &parser->current, &closing);
- pm_array_node_elements_append(array, string);
+ pm_node_t *string = UP(pm_string_node_create_current_string(parser, &opening, &parser->current, &closing));
+
+ // Record the string node, moving to interpolation if needed.
+ if (current == NULL) {
+ current = string;
+ } else if (PM_NODE_TYPE_P(current, PM_INTERPOLATED_STRING_NODE)) {
+ pm_interpolated_string_node_append((pm_interpolated_string_node_t *) current, string);
+ } else if (PM_NODE_TYPE_P(current, PM_STRING_NODE)) {
+ pm_interpolated_string_node_t *interpolated = pm_interpolated_string_node_create(parser, &opening, NULL, &closing);
+ pm_interpolated_string_node_append(interpolated, current);
+ pm_interpolated_string_node_append(interpolated, string);
+ current = UP(interpolated);
+ } else {
+ assert(false && "unreachable");
+ }
+ parser_lex(parser);
}
- expect1(parser, PM_TOKEN_STRING_CONTENT, PM_ERR_LIST_W_LOWER_ELEMENT);
+ if (current) {
+ pm_array_node_elements_append(array, current);
+ current = NULL;
+ } else {
+ expect1(parser, PM_TOKEN_STRING_CONTENT, PM_ERR_LIST_W_LOWER_ELEMENT);
+ }
}
pm_token_t closing = parser->current;
@@ -19328,7 +19645,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
pm_array_node_close_set(array, &closing);
- return (pm_node_t *) array;
+ return UP(array);
}
case PM_TOKEN_PERCENT_UPPER_W: {
parser_lex(parser);
@@ -19364,7 +19681,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t opening = not_provided(parser);
pm_token_t closing = not_provided(parser);
- pm_node_t *string = (pm_node_t *) pm_string_node_create_current_string(parser, &opening, &parser->current, &closing);
+ pm_node_t *string = UP(pm_string_node_create_current_string(parser, &opening, &parser->current, &closing));
pm_node_flag_set(string, parse_unescaped_encoding(parser));
parser_lex(parser);
@@ -19387,7 +19704,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_interpolated_string_node_t *interpolated = pm_interpolated_string_node_create(parser, &opening, NULL, &closing);
pm_interpolated_string_node_append(interpolated, current);
pm_interpolated_string_node_append(interpolated, string);
- current = (pm_node_t *) interpolated;
+ current = UP(interpolated);
} else {
assert(false && "unreachable");
}
@@ -19402,7 +19719,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
// interpolated string.
pm_token_t opening = not_provided(parser);
pm_token_t closing = not_provided(parser);
- current = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, NULL, &closing);
+ current = UP(pm_interpolated_string_node_create(parser, &opening, NULL, &closing));
} else if (PM_NODE_TYPE_P(current, PM_STRING_NODE)) {
// If we hit an embedded variable and the current
// node is a string node, then we'll convert the
@@ -19412,14 +19729,14 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t closing = not_provided(parser);
pm_interpolated_string_node_t *interpolated = pm_interpolated_string_node_create(parser, &opening, NULL, &closing);
pm_interpolated_string_node_append(interpolated, current);
- current = (pm_node_t *) interpolated;
+ current = UP(interpolated);
} else {
// If we hit an embedded variable and the current
// node is an interpolated string, then we'll just
// add the embedded variable.
}
- pm_node_t *part = parse_string_part(parser);
+ pm_node_t *part = parse_string_part(parser, (uint16_t) (depth + 1));
pm_interpolated_string_node_append((pm_interpolated_string_node_t *) current, part);
break;
}
@@ -19431,7 +19748,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
// interpolated string.
pm_token_t opening = not_provided(parser);
pm_token_t closing = not_provided(parser);
- current = (pm_node_t *) pm_interpolated_string_node_create(parser, &opening, NULL, &closing);
+ current = UP(pm_interpolated_string_node_create(parser, &opening, NULL, &closing));
} else if (PM_NODE_TYPE_P(current, PM_STRING_NODE)) {
// If we hit an embedded expression and the current
// node is a string node, then we'll convert the
@@ -19441,7 +19758,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t closing = not_provided(parser);
pm_interpolated_string_node_t *interpolated = pm_interpolated_string_node_create(parser, &opening, NULL, &closing);
pm_interpolated_string_node_append(interpolated, current);
- current = (pm_node_t *) interpolated;
+ current = UP(interpolated);
} else if (PM_NODE_TYPE_P(current, PM_INTERPOLATED_STRING_NODE)) {
// If we hit an embedded expression and the current
// node is an interpolated string, then we'll just
@@ -19450,7 +19767,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
assert(false && "unreachable");
}
- pm_node_t *part = parse_string_part(parser);
+ pm_node_t *part = parse_string_part(parser, (uint16_t) (depth + 1));
pm_interpolated_string_node_append((pm_interpolated_string_node_t *) current, part);
break;
}
@@ -19475,7 +19792,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
pm_array_node_close_set(array, &closing);
- return (pm_node_t *) array;
+ return UP(array);
}
case PM_TOKEN_REGEXP_BEGIN: {
pm_token_t opening = parser->current;
@@ -19493,7 +19810,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
parser_lex(parser);
- pm_node_t *node = (pm_node_t *) pm_regular_expression_node_create(parser, &opening, &content, &parser->previous);
+ pm_node_t *node = UP(pm_regular_expression_node_create(parser, &opening, &content, &parser->previous));
pm_node_flag_set(node, PM_REGULAR_EXPRESSION_FLAGS_FORCED_US_ASCII_ENCODING);
return node;
@@ -19511,13 +19828,22 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
bool ascii_only = parser->current_regular_expression_ascii_only;
parser_lex(parser);
- // If we hit an end, then we can create a regular expression node
- // without interpolation, which can be represented more succinctly and
- // more easily compiled.
+ // If we hit an end, then we can create a regular expression
+ // node without interpolation, which can be represented more
+ // succinctly and more easily compiled.
if (accept1(parser, PM_TOKEN_REGEXP_END)) {
- pm_node_t *node = (pm_node_t *) pm_regular_expression_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped);
- pm_node_flag_set(node, parse_and_validate_regular_expression_encoding(parser, &unescaped, ascii_only, node->flags));
- return node;
+ pm_regular_expression_node_t *node = (pm_regular_expression_node_t *) pm_regular_expression_node_create_unescaped(parser, &opening, &content, &parser->previous, &unescaped);
+
+ // If we're not immediately followed by a =~, then we want
+ // to parse all of the errors at this point. If it is
+ // followed by a =~, then it will get parsed higher up while
+ // parsing the named captures as well.
+ if (!match1(parser, PM_TOKEN_EQUAL_TILDE)) {
+ parse_regular_expression_errors(parser, node);
+ }
+
+ pm_node_flag_set(UP(node), parse_and_validate_regular_expression_encoding(parser, &unescaped, ascii_only, FL(node)));
+ return UP(node);
}
// If we get here, then we have interpolation so we'll need to create
@@ -19526,7 +19852,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t opening = not_provided(parser);
pm_token_t closing = not_provided(parser);
- pm_node_t *part = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &parser->previous, &closing, &unescaped);
+ pm_node_t *part = UP(pm_string_node_create_unescaped(parser, &opening, &parser->previous, &closing, &unescaped));
if (parser->encoding == PM_ENCODING_US_ASCII_ENTRY) {
// This is extremely strange, but the first string part of a
@@ -19547,7 +19873,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
// parts into the list.
pm_node_t *part;
while (!match2(parser, PM_TOKEN_REGEXP_END, PM_TOKEN_EOF)) {
- if ((part = parse_string_part(parser)) != NULL) {
+ if ((part = parse_string_part(parser, (uint16_t) (depth + 1))) != NULL) {
pm_interpolated_regular_expression_node_append(interpolated, part);
}
}
@@ -19561,7 +19887,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
pm_interpolated_regular_expression_node_closing_set(parser, interpolated, &closing);
- return (pm_node_t *) interpolated;
+ return UP(interpolated);
}
case PM_TOKEN_BACKTICK:
case PM_TOKEN_PERCENT_LOWER_X: {
@@ -19583,7 +19909,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
};
parser_lex(parser);
- return (pm_node_t *) pm_xstring_node_create(parser, &opening, &content, &parser->previous);
+ return UP(pm_xstring_node_create(parser, &opening, &content, &parser->previous));
}
pm_interpolated_x_string_node_t *node;
@@ -19598,7 +19924,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
parser_lex(parser);
if (match1(parser, PM_TOKEN_STRING_END)) {
- pm_node_t *node = (pm_node_t *) pm_xstring_node_create_unescaped(parser, &opening, &content, &parser->current, &unescaped);
+ pm_node_t *node = UP(pm_xstring_node_create_unescaped(parser, &opening, &content, &parser->current, &unescaped));
pm_node_flag_set(node, parse_unescaped_encoding(parser));
parser_lex(parser);
return node;
@@ -19611,7 +19937,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_token_t opening = not_provided(parser);
pm_token_t closing = not_provided(parser);
- pm_node_t *part = (pm_node_t *) pm_string_node_create_unescaped(parser, &opening, &parser->previous, &closing, &unescaped);
+ pm_node_t *part = UP(pm_string_node_create_unescaped(parser, &opening, &parser->previous, &closing, &unescaped));
pm_node_flag_set(part, parse_unescaped_encoding(parser));
pm_interpolated_xstring_node_append(node, part);
@@ -19624,7 +19950,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_node_t *part;
while (!match2(parser, PM_TOKEN_STRING_END, PM_TOKEN_EOF)) {
- if ((part = parse_string_part(parser)) != NULL) {
+ if ((part = parse_string_part(parser, (uint16_t) (depth + 1))) != NULL) {
pm_interpolated_xstring_node_append(node, part);
}
}
@@ -19638,7 +19964,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
}
pm_interpolated_xstring_node_closing_set(node, &closing);
- return (pm_node_t *) node;
+ return UP(node);
}
case PM_TOKEN_USTAR: {
parser_lex(parser);
@@ -19648,63 +19974,73 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
// still lex past it though and create a missing node place.
if (binding_power != PM_BINDING_POWER_STATEMENT) {
pm_parser_err_prefix(parser, diag_id);
- return (pm_node_t *) pm_missing_node_create(parser, parser->previous.start, parser->previous.end);
+ return UP(pm_missing_node_create(parser, parser->previous.start, parser->previous.end));
}
pm_token_t operator = parser->previous;
pm_node_t *name = NULL;
if (token_begins_expression_p(parser->current.type)) {
- name = parse_expression(parser, PM_BINDING_POWER_INDEX, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR);
+ name = parse_expression(parser, PM_BINDING_POWER_INDEX, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_STAR, (uint16_t) (depth + 1));
}
- pm_node_t *splat = (pm_node_t *) pm_splat_node_create(parser, &operator, name);
+ pm_node_t *splat = UP(pm_splat_node_create(parser, &operator, name));
if (match1(parser, PM_TOKEN_COMMA)) {
- return parse_targets_validate(parser, splat, PM_BINDING_POWER_INDEX);
+ return parse_targets_validate(parser, splat, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
} else {
return parse_target_validate(parser, splat, true);
}
}
case PM_TOKEN_BANG: {
+ if (binding_power > PM_BINDING_POWER_UNARY) {
+ pm_parser_err_prefix(parser, PM_ERR_UNARY_DISALLOWED);
+ }
+
parser_lex(parser);
pm_token_t operator = parser->previous;
- pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, binding_power < PM_BINDING_POWER_MATCH, PM_ERR_UNARY_RECEIVER);
+ pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, binding_power < PM_BINDING_POWER_MATCH, false, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1));
pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "!");
pm_conditional_predicate(parser, receiver, PM_CONDITIONAL_PREDICATE_TYPE_NOT);
- return (pm_node_t *) node;
+ return UP(node);
}
case PM_TOKEN_TILDE: {
+ if (binding_power > PM_BINDING_POWER_UNARY) {
+ pm_parser_err_prefix(parser, PM_ERR_UNARY_DISALLOWED);
+ }
parser_lex(parser);
pm_token_t operator = parser->previous;
- pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER);
+ pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, false, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1));
pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "~");
- return (pm_node_t *) node;
+ return UP(node);
}
case PM_TOKEN_UMINUS: {
+ if (binding_power > PM_BINDING_POWER_UNARY) {
+ pm_parser_err_prefix(parser, PM_ERR_UNARY_DISALLOWED);
+ }
parser_lex(parser);
pm_token_t operator = parser->previous;
- pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER);
+ pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, false, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1));
pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "-@");
- return (pm_node_t *) node;
+ return UP(node);
}
case PM_TOKEN_UMINUS_NUM: {
parser_lex(parser);
pm_token_t operator = parser->previous;
- pm_node_t *node = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER);
+ pm_node_t *node = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, false, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1));
if (accept1(parser, PM_TOKEN_STAR_STAR)) {
pm_token_t exponent_operator = parser->previous;
- pm_node_t *exponent = parse_expression(parser, pm_binding_powers[exponent_operator.type].right, false, PM_ERR_EXPECT_ARGUMENT);
- node = (pm_node_t *) pm_call_node_binary_create(parser, node, &exponent_operator, exponent, 0);
- node = (pm_node_t *) pm_call_node_unary_create(parser, &operator, node, "-@");
+ pm_node_t *exponent = parse_expression(parser, pm_binding_powers[exponent_operator.type].right, false, false, PM_ERR_EXPECT_ARGUMENT, (uint16_t) (depth + 1));
+ node = UP(pm_call_node_binary_create(parser, node, &exponent_operator, exponent, 0));
+ node = UP(pm_call_node_unary_create(parser, &operator, node, "-@"));
} else {
switch (PM_NODE_TYPE(node)) {
case PM_INTEGER_NODE:
@@ -19714,7 +20050,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
parse_negative_numeric(node);
break;
default:
- node = (pm_node_t *) pm_call_node_unary_create(parser, &operator, node, "-@");
+ node = UP(pm_call_node_unary_create(parser, &operator, node, "-@"));
break;
}
}
@@ -19725,6 +20061,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
int previous_lambda_enclosure_nesting = parser->lambda_enclosure_nesting;
parser->lambda_enclosure_nesting = parser->enclosure_nesting;
+ size_t opening_newline_index = token_newline_index(parser);
pm_accepts_block_stack_push(parser, true);
parser_lex(parser);
@@ -19741,7 +20078,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
if (match1(parser, PM_TOKEN_PARENTHESIS_RIGHT)) {
block_parameters = pm_block_parameters_node_create(parser, NULL, &opening);
} else {
- block_parameters = parse_block_parameters(parser, false, &opening, true);
+ block_parameters = parse_block_parameters(parser, false, &opening, true, true, (uint16_t) (depth + 1));
}
accept1(parser, PM_TOKEN_NEWLINE);
@@ -19753,7 +20090,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
case PM_CASE_PARAMETER: {
pm_accepts_block_stack_push(parser, false);
pm_token_t opening = not_provided(parser);
- block_parameters = parse_block_parameters(parser, false, &opening, true);
+ block_parameters = parse_block_parameters(parser, false, &opening, true, false, (uint16_t) (depth + 1));
pm_accepts_block_stack_pop(parser);
break;
}
@@ -19770,53 +20107,60 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
if (accept1(parser, PM_TOKEN_LAMBDA_BEGIN)) {
opening = parser->previous;
- if (!accept1(parser, PM_TOKEN_BRACE_RIGHT)) {
- body = (pm_node_t *) parse_statements(parser, PM_CONTEXT_LAMBDA_BRACES);
- expect1(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_LAMBDA_TERM_BRACE);
+ if (!match1(parser, PM_TOKEN_BRACE_RIGHT)) {
+ body = UP(parse_statements(parser, PM_CONTEXT_LAMBDA_BRACES, (uint16_t) (depth + 1)));
}
+
+ parser_warn_indentation_mismatch(parser, opening_newline_index, &operator, false, false);
+ expect1_opening(parser, PM_TOKEN_BRACE_RIGHT, PM_ERR_LAMBDA_TERM_BRACE, &opening);
} else {
expect1(parser, PM_TOKEN_KEYWORD_DO, PM_ERR_LAMBDA_OPEN);
opening = parser->previous;
if (!match3(parser, PM_TOKEN_KEYWORD_END, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) {
pm_accepts_block_stack_push(parser, true);
- body = (pm_node_t *) parse_statements(parser, PM_CONTEXT_LAMBDA_DO_END);
+ body = UP(parse_statements(parser, PM_CONTEXT_LAMBDA_DO_END, (uint16_t) (depth + 1)));
pm_accepts_block_stack_pop(parser);
}
if (match2(parser, PM_TOKEN_KEYWORD_RESCUE, PM_TOKEN_KEYWORD_ENSURE)) {
assert(body == NULL || PM_NODE_TYPE_P(body, PM_STATEMENTS_NODE));
- body = (pm_node_t *) parse_rescues_implicit_begin(parser, opening.start, (pm_statements_node_t *) body, PM_RESCUES_LAMBDA);
+ body = UP(parse_rescues_implicit_begin(parser, opening_newline_index, &operator, opening.start, (pm_statements_node_t *) body, PM_RESCUES_LAMBDA, (uint16_t) (depth + 1)));
+ } else {
+ parser_warn_indentation_mismatch(parser, opening_newline_index, &operator, false, false);
}
- expect1(parser, PM_TOKEN_KEYWORD_END, PM_ERR_LAMBDA_TERM_END);
+ expect1_opening(parser, PM_TOKEN_KEYWORD_END, PM_ERR_LAMBDA_TERM_END, &operator);
}
pm_constant_id_list_t locals;
pm_locals_order(parser, &parser->current_scope->locals, &locals, pm_parser_scope_toplevel_p(parser));
- pm_node_t *parameters = parse_blocklike_parameters(parser, (pm_node_t *) block_parameters, &operator, &parser->previous);
+ pm_node_t *parameters = parse_blocklike_parameters(parser, UP(block_parameters), &operator, &parser->previous);
pm_parser_scope_pop(parser);
pm_accepts_block_stack_pop(parser);
- return (pm_node_t *) pm_lambda_node_create(parser, &locals, &operator, &opening, &parser->previous, parameters, body);
+ return UP(pm_lambda_node_create(parser, &locals, &operator, &opening, &parser->previous, parameters, body));
}
case PM_TOKEN_UPLUS: {
+ if (binding_power > PM_BINDING_POWER_UNARY) {
+ pm_parser_err_prefix(parser, PM_ERR_UNARY_DISALLOWED);
+ }
parser_lex(parser);
pm_token_t operator = parser->previous;
- pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, PM_ERR_UNARY_RECEIVER);
+ pm_node_t *receiver = parse_expression(parser, pm_binding_powers[parser->previous.type].right, false, false, PM_ERR_UNARY_RECEIVER, (uint16_t) (depth + 1));
pm_call_node_t *node = pm_call_node_unary_create(parser, &operator, receiver, "+@");
- return (pm_node_t *) node;
+ return UP(node);
}
case PM_TOKEN_STRING_BEGIN:
- return parse_strings(parser, NULL);
+ return parse_strings(parser, NULL, accepts_label, (uint16_t) (depth + 1));
case PM_TOKEN_SYMBOL_BEGIN: {
pm_lex_mode_t lex_mode = *parser->lex_modes.current;
parser_lex(parser);
- return parse_symbol(parser, &lex_mode, PM_LEX_STATE_END);
+ return parse_symbol(parser, &lex_mode, PM_LEX_STATE_END, (uint16_t) (depth + 1));
}
default: {
pm_context_t recoverable = context_recoverable(parser, &parser->current);
@@ -19844,7 +20188,7 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
pm_parser_err_prefix(parser, diag_id);
}
- return (pm_node_t *) pm_missing_node_create(parser, parser->previous.start, parser->previous.end);
+ return UP(pm_missing_node_create(parser, parser->previous.start, parser->previous.end));
}
}
}
@@ -19859,8 +20203,8 @@ parse_expression_prefix(pm_parser_t *parser, pm_binding_power_t binding_power, b
* or any of the binary operators that can be written to a variable.
*/
static pm_node_t *
-parse_assignment_value(pm_parser_t *parser, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id) {
- pm_node_t *value = parse_value_expression(parser, binding_power, previous_binding_power == PM_BINDING_POWER_ASSIGNMENT ? accepts_command_call : previous_binding_power < PM_BINDING_POWER_MATCH, diag_id);
+parse_assignment_value(pm_parser_t *parser, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id, uint16_t depth) {
+ pm_node_t *value = parse_value_expression(parser, binding_power, previous_binding_power == PM_BINDING_POWER_ASSIGNMENT ? accepts_command_call : previous_binding_power < PM_BINDING_POWER_MATCH, false, diag_id, (uint16_t) (depth + 1));
// Contradicting binding powers, the right-hand-side value of the assignment
// allows the `rescue` modifier.
@@ -19870,10 +20214,10 @@ parse_assignment_value(pm_parser_t *parser, pm_binding_power_t previous_binding_
pm_token_t rescue = parser->current;
parser_lex(parser);
- pm_node_t *right = parse_expression(parser, binding_power, false, PM_ERR_RESCUE_MODIFIER_VALUE);
+ pm_node_t *right = parse_expression(parser, pm_binding_powers[PM_TOKEN_KEYWORD_RESCUE_MODIFIER].right, false, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1));
context_pop(parser);
- return (pm_node_t *) pm_rescue_modifier_node_create(parser, value, &rescue, right);
+ return UP(pm_rescue_modifier_node_create(parser, value, &rescue, right));
}
return value;
@@ -19928,11 +20272,16 @@ parse_assignment_value_local(pm_parser_t *parser, const pm_node_t *node) {
* operator that allows multiple values after it.
*/
static pm_node_t *
-parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id) {
- pm_node_t *value = parse_starred_expression(parser, binding_power, previous_binding_power == PM_BINDING_POWER_ASSIGNMENT ? accepts_command_call : previous_binding_power < PM_BINDING_POWER_MATCH, diag_id);
- parse_assignment_value_local(parser, value);
+parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id, uint16_t depth) {
+ bool permitted = true;
+ if (previous_binding_power != PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_USTAR)) permitted = false;
+ pm_node_t *value = parse_starred_expression(parser, binding_power, previous_binding_power == PM_BINDING_POWER_ASSIGNMENT ? accepts_command_call : previous_binding_power < PM_BINDING_POWER_MODIFIER, diag_id, (uint16_t) (depth + 1));
+ if (!permitted) pm_parser_err_node(parser, value, PM_ERR_UNEXPECTED_MULTI_WRITE);
+
+ parse_assignment_value_local(parser, value);
bool single_value = true;
+
if (previous_binding_power == PM_BINDING_POWER_STATEMENT && (PM_NODE_TYPE_P(value, PM_SPLAT_NODE) || match1(parser, PM_TOKEN_COMMA))) {
single_value = false;
@@ -19940,10 +20289,10 @@ parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding
pm_array_node_t *array = pm_array_node_create(parser, &opening);
pm_array_node_elements_append(array, value);
- value = (pm_node_t *) array;
+ value = UP(array);
while (accept1(parser, PM_TOKEN_COMMA)) {
- pm_node_t *element = parse_starred_expression(parser, binding_power, false, PM_ERR_ARRAY_ELEMENT);
+ pm_node_t *element = parse_starred_expression(parser, binding_power, false, PM_ERR_ARRAY_ELEMENT, (uint16_t) (depth + 1));
pm_array_node_elements_append(array, element);
if (PM_NODE_TYPE_P(element, PM_MISSING_NODE)) break;
@@ -19971,10 +20320,10 @@ parse_assignment_values(pm_parser_t *parser, pm_binding_power_t previous_binding
}
}
- pm_node_t *right = parse_expression(parser, binding_power, accepts_command_call_inner, PM_ERR_RESCUE_MODIFIER_VALUE);
+ pm_node_t *right = parse_expression(parser, pm_binding_powers[PM_TOKEN_KEYWORD_RESCUE_MODIFIER].right, accepts_command_call_inner, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1));
context_pop(parser);
- return (pm_node_t *) pm_rescue_modifier_node_create(parser, value, &rescue, right);
+ return UP(pm_rescue_modifier_node_create(parser, value, &rescue, right));
}
return value;
@@ -19991,105 +20340,288 @@ static void
parse_call_operator_write(pm_parser_t *parser, pm_call_node_t *call_node, const pm_token_t *operator) {
if (call_node->arguments != NULL) {
pm_parser_err_token(parser, operator, PM_ERR_OPERATOR_WRITE_ARGUMENTS);
- pm_node_destroy(parser, (pm_node_t *) call_node->arguments);
+ pm_node_unreference(parser, UP(call_node->arguments));
+ pm_node_destroy(parser, UP(call_node->arguments));
call_node->arguments = NULL;
}
if (call_node->block != NULL) {
pm_parser_err_token(parser, operator, PM_ERR_OPERATOR_WRITE_BLOCK);
- pm_node_destroy(parser, (pm_node_t *) call_node->block);
+ pm_node_unreference(parser, UP(call_node->block));
+ pm_node_destroy(parser, UP(call_node->block));
call_node->block = NULL;
}
}
/**
- * Potentially change a =~ with a regular expression with named captures into a
- * match write node.
+ * This struct is used to pass information between the regular expression parser
+ * and the named capture callback.
*/
-static pm_node_t *
-parse_regular_expression_named_captures(pm_parser_t *parser, const pm_string_t *content, pm_call_node_t *call) {
- pm_string_list_t named_captures = { 0 };
- pm_node_t *result;
-
- if (pm_regexp_named_capture_group_names(pm_string_source(content), pm_string_length(content), &named_captures, parser->encoding_changed, parser->encoding) && (named_captures.length > 0)) {
- // Since we should not create a MatchWriteNode when all capture names
- // are invalid, creating a MatchWriteNode is delaid here.
- pm_match_write_node_t *match = NULL;
- pm_constant_id_list_t names = { 0 };
-
- for (size_t index = 0; index < named_captures.length; index++) {
- pm_string_t *string = &named_captures.strings[index];
-
- const uint8_t *source = pm_string_source(string);
- size_t length = pm_string_length(string);
-
- pm_location_t location;
- pm_constant_id_t name;
-
- // If the name of the capture group isn't a valid identifier, we do
- // not add it to the local table.
- if (!pm_slice_is_valid_local(parser, source, source + length)) continue;
-
- if (content->type == PM_STRING_SHARED) {
- // If the unescaped string is a slice of the source, then we can
- // copy the names directly. The pointers will line up.
- location = (pm_location_t) { .start = source, .end = source + length };
- name = pm_parser_constant_id_location(parser, location.start, location.end);
- } else {
- // Otherwise, the name is a slice of the malloc-ed owned string,
- // in which case we need to copy it out into a new string.
- location = call->receiver->location;
+typedef struct {
+ /** The parser that is parsing the regular expression. */
+ pm_parser_t *parser;
- void *memory = xmalloc(length);
- if (memory == NULL) abort();
+ /** The call node wrapping the regular expression node. */
+ pm_call_node_t *call;
- memcpy(memory, source, length);
- name = pm_parser_constant_id_owned(parser, (uint8_t *) memory, length);
- }
+ /** The match write node that is being created. */
+ pm_match_write_node_t *match;
- if (name != 0) {
- // We dont want to create duplicate targets if the capture name
- // is duplicated.
- if (pm_constant_id_list_includes(&names, name)) continue;
- pm_constant_id_list_append(&names, name);
+ /** The list of names that have been parsed. */
+ pm_constant_id_list_t names;
- int depth;
- if ((depth = pm_parser_local_depth_constant_id(parser, name)) == -1) {
- // If the identifier is not already a local, then we'll add
- // it to the local table unless it's a keyword.
- if (pm_local_is_keyword((const char *) source, length)) continue;
+ /**
+ * Whether the content of the regular expression is shared. This impacts
+ * whether or not we used owned constants or shared constants in the
+ * constant pool for the names of the captures.
+ */
+ bool shared;
+} parse_regular_expression_named_capture_data_t;
- pm_parser_local_add(parser, name, location.start, location.end, 0);
- }
+static inline const uint8_t *
+pm_named_capture_escape_hex(pm_buffer_t *unescaped, const uint8_t *cursor, const uint8_t *end) {
+ cursor++;
- // Here we lazily create the MatchWriteNode since we know we're
- // about to add a target.
- if (match == NULL) match = pm_match_write_node_create(parser, call);
+ if (cursor < end && pm_char_is_hexadecimal_digit(*cursor)) {
+ uint8_t value = escape_hexadecimal_digit(*cursor);
+ cursor++;
- // Next, create the local variable target and add it to the
- // list of targets for the match.
- pm_node_t *target = (pm_node_t *) pm_local_variable_target_node_create(parser, &location, name, depth == -1 ? 0 : (uint32_t) depth);
- pm_node_list_append(&match->targets, target);
- }
+ if (cursor < end && pm_char_is_hexadecimal_digit(*cursor)) {
+ value = (uint8_t) ((value << 4) | escape_hexadecimal_digit(*cursor));
+ cursor++;
}
- if (match != NULL) {
- result = (pm_node_t *) match;
- } else {
- result = (pm_node_t *) call;
+ pm_buffer_append_byte(unescaped, value);
+ } else {
+ pm_buffer_append_string(unescaped, "\\x", 2);
+ }
+
+ return cursor;
+}
+
+static inline const uint8_t *
+pm_named_capture_escape_octal(pm_buffer_t *unescaped, const uint8_t *cursor, const uint8_t *end) {
+ uint8_t value = (uint8_t) (*cursor - '0');
+ cursor++;
+
+ if (cursor < end && pm_char_is_octal_digit(*cursor)) {
+ value = ((uint8_t) (value << 3)) | ((uint8_t) (*cursor - '0'));
+ cursor++;
+
+ if (cursor < end && pm_char_is_octal_digit(*cursor)) {
+ value = ((uint8_t) (value << 3)) | ((uint8_t) (*cursor - '0'));
+ cursor++;
+ }
+ }
+
+ pm_buffer_append_byte(unescaped, value);
+ return cursor;
+}
+
+static inline const uint8_t *
+pm_named_capture_escape_unicode(pm_parser_t *parser, pm_buffer_t *unescaped, const uint8_t *cursor, const uint8_t *end, const pm_location_t *error_location) {
+ const uint8_t *start = cursor - 1;
+ cursor++;
+
+ if (cursor >= end) {
+ pm_buffer_append_string(unescaped, "\\u", 2);
+ return cursor;
+ }
+
+ if (*cursor != '{') {
+ size_t length = pm_strspn_hexadecimal_digit(cursor, MIN(end - cursor, 4));
+ uint32_t value = escape_unicode(parser, cursor, length, error_location);
+
+ if (!pm_buffer_append_unicode_codepoint(unescaped, value)) {
+ pm_buffer_append_string(unescaped, (const char *) start, (size_t) ((cursor + length) - start));
+ }
+
+ return cursor + length;
+ }
+
+ cursor++;
+ for (;;) {
+ while (cursor < end && *cursor == ' ') cursor++;
+
+ if (cursor >= end) break;
+ if (*cursor == '}') {
+ cursor++;
+ break;
+ }
+
+ size_t length = pm_strspn_hexadecimal_digit(cursor, end - cursor);
+ if (length == 0) {
+ break;
}
+ uint32_t value = escape_unicode(parser, cursor, length, error_location);
- pm_constant_id_list_free(&names);
+ (void) pm_buffer_append_unicode_codepoint(unescaped, value);
+ cursor += length;
+ }
+
+ return cursor;
+}
+
+static void
+pm_named_capture_escape(pm_parser_t *parser, pm_buffer_t *unescaped, const uint8_t *source, const size_t length, const uint8_t *cursor, const pm_location_t *error_location) {
+ const uint8_t *end = source + length;
+ pm_buffer_append_string(unescaped, (const char *) source, (size_t) (cursor - source));
+
+ for (;;) {
+ if (++cursor >= end) {
+ pm_buffer_append_byte(unescaped, '\\');
+ return;
+ }
+
+ switch (*cursor) {
+ case 'x':
+ cursor = pm_named_capture_escape_hex(unescaped, cursor, end);
+ break;
+ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
+ cursor = pm_named_capture_escape_octal(unescaped, cursor, end);
+ break;
+ case 'u':
+ cursor = pm_named_capture_escape_unicode(parser, unescaped, cursor, end, error_location);
+ break;
+ default:
+ pm_buffer_append_byte(unescaped, '\\');
+ break;
+ }
+
+ const uint8_t *next_cursor = pm_memchr(cursor, '\\', (size_t) (end - cursor), parser->encoding_changed, parser->encoding);
+ if (next_cursor == NULL) break;
+
+ pm_buffer_append_string(unescaped, (const char *) cursor, (size_t) (next_cursor - cursor));
+ cursor = next_cursor;
+ }
+
+ pm_buffer_append_string(unescaped, (const char *) cursor, (size_t) (end - cursor));
+}
+
+/**
+ * This callback is called when the regular expression parser encounters a named
+ * capture group.
+ */
+static void
+parse_regular_expression_named_capture(const pm_string_t *capture, void *data) {
+ parse_regular_expression_named_capture_data_t *callback_data = (parse_regular_expression_named_capture_data_t *) data;
+
+ pm_parser_t *parser = callback_data->parser;
+ pm_call_node_t *call = callback_data->call;
+ pm_constant_id_list_t *names = &callback_data->names;
+
+ const uint8_t *source = pm_string_source(capture);
+ size_t length = pm_string_length(capture);
+ pm_buffer_t unescaped = { 0 };
+
+ // First, we need to handle escapes within the name of the capture group.
+ // This is because regular expressions have three different representations
+ // in prism. The first is the plain source code. The second is the
+ // representation that will be sent to the regular expression engine, which
+ // is the value of the "unescaped" field. This is poorly named, because it
+ // actually still contains escapes, just a subset of them that the regular
+ // expression engine knows how to handle. The third representation is fully
+ // unescaped, which is what we need.
+ const uint8_t *cursor = pm_memchr(source, '\\', length, parser->encoding_changed, parser->encoding);
+ if (PRISM_UNLIKELY(cursor != NULL)) {
+ pm_named_capture_escape(parser, &unescaped, source, length, cursor, callback_data->shared ? NULL : &call->receiver->location);
+ source = (const uint8_t *) pm_buffer_value(&unescaped);
+ length = pm_buffer_length(&unescaped);
+ }
+
+ pm_location_t location;
+ pm_constant_id_t name;
+
+ // If the name of the capture group isn't a valid identifier, we do
+ // not add it to the local table.
+ if (!pm_slice_is_valid_local(parser, source, source + length)) {
+ pm_buffer_free(&unescaped);
+ return;
+ }
+
+ if (callback_data->shared) {
+ // If the unescaped string is a slice of the source, then we can
+ // copy the names directly. The pointers will line up.
+ location = (pm_location_t) { .start = source, .end = source + length };
+ name = pm_parser_constant_id_location(parser, location.start, location.end);
} else {
- result = (pm_node_t *) call;
+ // Otherwise, the name is a slice of the malloc-ed owned string,
+ // in which case we need to copy it out into a new string.
+ location = (pm_location_t) { .start = call->receiver->location.start, .end = call->receiver->location.end };
+
+ void *memory = xmalloc(length);
+ if (memory == NULL) abort();
+
+ memcpy(memory, source, length);
+ name = pm_parser_constant_id_owned(parser, (uint8_t *) memory, length);
}
- pm_string_list_free(&named_captures);
- return result;
+ // Add this name to the list of constants if it is valid, not duplicated,
+ // and not a keyword.
+ if (name != 0 && !pm_constant_id_list_includes(names, name)) {
+ pm_constant_id_list_append(names, name);
+
+ int depth;
+ if ((depth = pm_parser_local_depth_constant_id(parser, name)) == -1) {
+ // If the local is not already a local but it is a keyword, then we
+ // do not want to add a capture for this.
+ if (pm_local_is_keyword((const char *) source, length)) {
+ pm_buffer_free(&unescaped);
+ return;
+ }
+
+ // If the identifier is not already a local, then we will add it to
+ // the local table.
+ pm_parser_local_add(parser, name, location.start, location.end, 0);
+ }
+
+ // Here we lazily create the MatchWriteNode since we know we're
+ // about to add a target.
+ if (callback_data->match == NULL) {
+ callback_data->match = pm_match_write_node_create(parser, call);
+ }
+
+ // Next, create the local variable target and add it to the list of
+ // targets for the match.
+ pm_node_t *target = UP(pm_local_variable_target_node_create(parser, &location, name, depth == -1 ? 0 : (uint32_t) depth));
+ pm_node_list_append(&callback_data->match->targets, target);
+ }
+
+ pm_buffer_free(&unescaped);
+}
+
+/**
+ * Potentially change a =~ with a regular expression with named captures into a
+ * match write node.
+ */
+static pm_node_t *
+parse_regular_expression_named_captures(pm_parser_t *parser, const pm_string_t *content, pm_call_node_t *call, bool extended_mode) {
+ parse_regular_expression_named_capture_data_t callback_data = {
+ .parser = parser,
+ .call = call,
+ .names = { 0 },
+ .shared = content->type == PM_STRING_SHARED
+ };
+
+ parse_regular_expression_error_data_t error_data = {
+ .parser = parser,
+ .start = call->receiver->location.start,
+ .end = call->receiver->location.end,
+ .shared = content->type == PM_STRING_SHARED
+ };
+
+ pm_regexp_parse(parser, pm_string_source(content), pm_string_length(content), extended_mode, parse_regular_expression_named_capture, &callback_data, parse_regular_expression_error, &error_data);
+ pm_constant_id_list_free(&callback_data.names);
+
+ if (callback_data.match != NULL) {
+ return UP(callback_data.match);
+ } else {
+ return UP(call);
+ }
}
static inline pm_node_t *
-parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, bool accepts_command_call) {
+parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t previous_binding_power, pm_binding_power_t binding_power, bool accepts_command_call, uint16_t depth) {
pm_token_t token = parser->current;
switch (token.type) {
@@ -20105,10 +20637,22 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
pm_parser_local_add_location(parser, call_node->message_loc.start, call_node->message_loc.end, 0);
}
}
- /* fallthrough */
+ PRISM_FALLTHROUGH
case PM_CASE_WRITABLE: {
+ // When we have `it = value`, we need to add `it` as a local
+ // variable before parsing the value, in case the value
+ // references the variable.
+ if (PM_NODE_TYPE_P(node, PM_IT_LOCAL_VARIABLE_READ_NODE)) {
+ pm_parser_local_add_location(parser, node->location.start, node->location.end, 0);
+ }
+
parser_lex(parser);
- pm_node_t *value = parse_assignment_values(parser, previous_binding_power, PM_NODE_TYPE_P(node, PM_MULTI_TARGET_NODE) ? PM_BINDING_POWER_MULTI_ASSIGNMENT + 1 : binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL);
+ pm_node_t *value = parse_assignment_values(parser, previous_binding_power, PM_NODE_TYPE_P(node, PM_MULTI_TARGET_NODE) ? PM_BINDING_POWER_MULTI_ASSIGNMENT + 1 : binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL, (uint16_t) (depth + 1));
+
+ if (PM_NODE_TYPE_P(node, PM_MULTI_TARGET_NODE) && previous_binding_power != PM_BINDING_POWER_STATEMENT) {
+ pm_parser_err_node(parser, node, PM_ERR_UNEXPECTED_MULTI_WRITE);
+ }
+
return parse_write(parser, node, &token, value);
}
case PM_SPLAT_NODE: {
@@ -20116,8 +20660,8 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
pm_multi_target_node_targets_append(parser, multi_target, node);
parser_lex(parser);
- pm_node_t *value = parse_assignment_values(parser, previous_binding_power, PM_BINDING_POWER_MULTI_ASSIGNMENT + 1, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL);
- return parse_write(parser, (pm_node_t *) multi_target, &token, value);
+ pm_node_t *value = parse_assignment_values(parser, previous_binding_power, PM_BINDING_POWER_MULTI_ASSIGNMENT + 1, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL, (uint16_t) (depth + 1));
+ return parse_write(parser, UP(multi_target), &token, value);
}
case PM_SOURCE_ENCODING_NODE:
case PM_FALSE_NODE:
@@ -20129,7 +20673,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
// In these special cases, we have specific error messages
// and we will replace them with local variable writes.
parser_lex(parser);
- pm_node_t *value = parse_assignment_values(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL);
+ pm_node_t *value = parse_assignment_values(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_EQUAL, (uint16_t) (depth + 1));
return parse_unwriteable_write(parser, node, &token, value);
}
default:
@@ -20146,12 +20690,12 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
case PM_BACK_REFERENCE_READ_NODE:
case PM_NUMBERED_REFERENCE_READ_NODE:
PM_PARSER_ERR_NODE_FORMAT_CONTENT(parser, node, PM_ERR_WRITE_TARGET_READONLY);
- /* fallthrough */
+ PRISM_FALLTHROUGH
case PM_GLOBAL_VARIABLE_READ_NODE: {
parser_lex(parser);
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
- pm_node_t *result = (pm_node_t *) pm_global_variable_and_write_node_create(parser, node, &token, value);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1));
+ pm_node_t *result = UP(pm_global_variable_and_write_node_create(parser, node, &token, value));
pm_node_destroy(parser, node);
return result;
@@ -20159,8 +20703,8 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
case PM_CLASS_VARIABLE_READ_NODE: {
parser_lex(parser);
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
- pm_node_t *result = (pm_node_t *) pm_class_variable_and_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1));
+ pm_node_t *result = UP(pm_class_variable_and_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value));
pm_node_destroy(parser, node);
return result;
@@ -20168,16 +20712,16 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
case PM_CONSTANT_PATH_NODE: {
parser_lex(parser);
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
- pm_node_t *write = (pm_node_t *) pm_constant_path_and_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1));
+ pm_node_t *write = UP(pm_constant_path_and_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value));
return parse_shareable_constant_write(parser, write);
}
case PM_CONSTANT_READ_NODE: {
parser_lex(parser);
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
- pm_node_t *write = (pm_node_t *) pm_constant_and_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1));
+ pm_node_t *write = UP(pm_constant_and_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value));
pm_node_destroy(parser, node);
return parse_shareable_constant_write(parser, write);
@@ -20185,18 +20729,34 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
case PM_INSTANCE_VARIABLE_READ_NODE: {
parser_lex(parser);
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
- pm_node_t *result = (pm_node_t *) pm_instance_variable_and_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1));
+ pm_node_t *result = UP(pm_instance_variable_and_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value));
pm_node_destroy(parser, node);
return result;
}
+ case PM_IT_LOCAL_VARIABLE_READ_NODE: {
+ pm_constant_id_t name = pm_parser_local_add_constant(parser, "it", 2);
+ parser_lex(parser);
+
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1));
+ pm_node_t *result = UP(pm_local_variable_and_write_node_create(parser, node, &token, value, name, 0));
+
+ pm_node_unreference(parser, node);
+ pm_node_destroy(parser, node);
+ return result;
+ }
case PM_LOCAL_VARIABLE_READ_NODE: {
+ if (pm_token_is_numbered_parameter(node->location.start, node->location.end)) {
+ PM_PARSER_ERR_FORMAT(parser, node->location.start, node->location.end, PM_ERR_PARAMETER_NUMBERED_RESERVED, node->location.start);
+ pm_node_unreference(parser, node);
+ }
+
pm_local_variable_read_node_t *cast = (pm_local_variable_read_node_t *) node;
parser_lex(parser);
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
- pm_node_t *result = (pm_node_t *) pm_local_variable_and_write_node_create(parser, node, &token, value, cast->name, cast->depth);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1));
+ pm_node_t *result = UP(pm_local_variable_and_write_node_create(parser, node, &token, value, cast->name, cast->depth));
pm_node_destroy(parser, node);
return result;
@@ -20214,10 +20774,10 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
pm_constant_id_t constant_id = pm_parser_local_add_location(parser, message_loc->start, message_loc->end, 1);
parser_lex(parser);
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
- pm_node_t *result = (pm_node_t *) pm_local_variable_and_write_node_create(parser, (pm_node_t *) cast, &token, value, constant_id, 0);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1));
+ pm_node_t *result = UP(pm_local_variable_and_write_node_create(parser, UP(cast), &token, value, constant_id, 0));
- pm_node_destroy(parser, (pm_node_t *) cast);
+ pm_node_destroy(parser, UP(cast));
return result;
}
@@ -20229,8 +20789,8 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
// this is an aref expression, and we can transform it into
// an aset expression.
if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_INDEX)) {
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
- return (pm_node_t *) pm_index_and_write_node_create(parser, cast, &token, value);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1));
+ return UP(pm_index_and_write_node_create(parser, cast, &token, value));
}
// If this node cannot be writable, then we have an error.
@@ -20241,8 +20801,8 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
}
parse_call_operator_write(parser, cast, &token);
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ);
- return (pm_node_t *) pm_call_and_write_node_create(parser, cast, &token, value);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ, (uint16_t) (depth + 1));
+ return UP(pm_call_and_write_node_create(parser, cast, &token, value));
}
case PM_MULTI_WRITE_NODE: {
parser_lex(parser);
@@ -20264,12 +20824,12 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
case PM_BACK_REFERENCE_READ_NODE:
case PM_NUMBERED_REFERENCE_READ_NODE:
PM_PARSER_ERR_NODE_FORMAT_CONTENT(parser, node, PM_ERR_WRITE_TARGET_READONLY);
- /* fallthrough */
+ PRISM_FALLTHROUGH
case PM_GLOBAL_VARIABLE_READ_NODE: {
parser_lex(parser);
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
- pm_node_t *result = (pm_node_t *) pm_global_variable_or_write_node_create(parser, node, &token, value);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1));
+ pm_node_t *result = UP(pm_global_variable_or_write_node_create(parser, node, &token, value));
pm_node_destroy(parser, node);
return result;
@@ -20277,8 +20837,8 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
case PM_CLASS_VARIABLE_READ_NODE: {
parser_lex(parser);
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
- pm_node_t *result = (pm_node_t *) pm_class_variable_or_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1));
+ pm_node_t *result = UP(pm_class_variable_or_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value));
pm_node_destroy(parser, node);
return result;
@@ -20286,16 +20846,16 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
case PM_CONSTANT_PATH_NODE: {
parser_lex(parser);
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
- pm_node_t *write = (pm_node_t *) pm_constant_path_or_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1));
+ pm_node_t *write = UP(pm_constant_path_or_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value));
return parse_shareable_constant_write(parser, write);
}
case PM_CONSTANT_READ_NODE: {
parser_lex(parser);
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
- pm_node_t *write = (pm_node_t *) pm_constant_or_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1));
+ pm_node_t *write = UP(pm_constant_or_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value));
pm_node_destroy(parser, node);
return parse_shareable_constant_write(parser, write);
@@ -20303,18 +20863,34 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
case PM_INSTANCE_VARIABLE_READ_NODE: {
parser_lex(parser);
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
- pm_node_t *result = (pm_node_t *) pm_instance_variable_or_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1));
+ pm_node_t *result = UP(pm_instance_variable_or_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value));
+
+ pm_node_destroy(parser, node);
+ return result;
+ }
+ case PM_IT_LOCAL_VARIABLE_READ_NODE: {
+ pm_constant_id_t name = pm_parser_local_add_constant(parser, "it", 2);
+ parser_lex(parser);
+
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1));
+ pm_node_t *result = UP(pm_local_variable_or_write_node_create(parser, node, &token, value, name, 0));
+ pm_node_unreference(parser, node);
pm_node_destroy(parser, node);
return result;
}
case PM_LOCAL_VARIABLE_READ_NODE: {
+ if (pm_token_is_numbered_parameter(node->location.start, node->location.end)) {
+ PM_PARSER_ERR_FORMAT(parser, node->location.start, node->location.end, PM_ERR_PARAMETER_NUMBERED_RESERVED, node->location.start);
+ pm_node_unreference(parser, node);
+ }
+
pm_local_variable_read_node_t *cast = (pm_local_variable_read_node_t *) node;
parser_lex(parser);
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
- pm_node_t *result = (pm_node_t *) pm_local_variable_or_write_node_create(parser, node, &token, value, cast->name, cast->depth);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1));
+ pm_node_t *result = UP(pm_local_variable_or_write_node_create(parser, node, &token, value, cast->name, cast->depth));
pm_node_destroy(parser, node);
return result;
@@ -20332,10 +20908,10 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
pm_constant_id_t constant_id = pm_parser_local_add_location(parser, message_loc->start, message_loc->end, 1);
parser_lex(parser);
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
- pm_node_t *result = (pm_node_t *) pm_local_variable_or_write_node_create(parser, (pm_node_t *) cast, &token, value, constant_id, 0);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1));
+ pm_node_t *result = UP(pm_local_variable_or_write_node_create(parser, UP(cast), &token, value, constant_id, 0));
- pm_node_destroy(parser, (pm_node_t *) cast);
+ pm_node_destroy(parser, UP(cast));
return result;
}
@@ -20347,8 +20923,8 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
// this is an aref expression, and we can transform it into
// an aset expression.
if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_INDEX)) {
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
- return (pm_node_t *) pm_index_or_write_node_create(parser, cast, &token, value);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1));
+ return UP(pm_index_or_write_node_create(parser, cast, &token, value));
}
// If this node cannot be writable, then we have an error.
@@ -20359,8 +20935,8 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
}
parse_call_operator_write(parser, cast, &token);
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ);
- return (pm_node_t *) pm_call_or_write_node_create(parser, cast, &token, value);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ, (uint16_t) (depth + 1));
+ return UP(pm_call_or_write_node_create(parser, cast, &token, value));
}
case PM_MULTI_WRITE_NODE: {
parser_lex(parser);
@@ -20392,12 +20968,12 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
case PM_BACK_REFERENCE_READ_NODE:
case PM_NUMBERED_REFERENCE_READ_NODE:
PM_PARSER_ERR_NODE_FORMAT_CONTENT(parser, node, PM_ERR_WRITE_TARGET_READONLY);
- /* fallthrough */
+ PRISM_FALLTHROUGH
case PM_GLOBAL_VARIABLE_READ_NODE: {
parser_lex(parser);
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
- pm_node_t *result = (pm_node_t *) pm_global_variable_operator_write_node_create(parser, node, &token, value);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
+ pm_node_t *result = UP(pm_global_variable_operator_write_node_create(parser, node, &token, value));
pm_node_destroy(parser, node);
return result;
@@ -20405,8 +20981,8 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
case PM_CLASS_VARIABLE_READ_NODE: {
parser_lex(parser);
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
- pm_node_t *result = (pm_node_t *) pm_class_variable_operator_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
+ pm_node_t *result = UP(pm_class_variable_operator_write_node_create(parser, (pm_class_variable_read_node_t *) node, &token, value));
pm_node_destroy(parser, node);
return result;
@@ -20414,16 +20990,16 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
case PM_CONSTANT_PATH_NODE: {
parser_lex(parser);
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
- pm_node_t *write = (pm_node_t *) pm_constant_path_operator_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
+ pm_node_t *write = UP(pm_constant_path_operator_write_node_create(parser, (pm_constant_path_node_t *) node, &token, value));
return parse_shareable_constant_write(parser, write);
}
case PM_CONSTANT_READ_NODE: {
parser_lex(parser);
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
- pm_node_t *write = (pm_node_t *) pm_constant_operator_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
+ pm_node_t *write = UP(pm_constant_operator_write_node_create(parser, (pm_constant_read_node_t *) node, &token, value));
pm_node_destroy(parser, node);
return parse_shareable_constant_write(parser, write);
@@ -20431,18 +21007,34 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
case PM_INSTANCE_VARIABLE_READ_NODE: {
parser_lex(parser);
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
- pm_node_t *result = (pm_node_t *) pm_instance_variable_operator_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
+ pm_node_t *result = UP(pm_instance_variable_operator_write_node_create(parser, (pm_instance_variable_read_node_t *) node, &token, value));
+
+ pm_node_destroy(parser, node);
+ return result;
+ }
+ case PM_IT_LOCAL_VARIABLE_READ_NODE: {
+ pm_constant_id_t name = pm_parser_local_add_constant(parser, "it", 2);
+ parser_lex(parser);
+
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
+ pm_node_t *result = UP(pm_local_variable_operator_write_node_create(parser, node, &token, value, name, 0));
+ pm_node_unreference(parser, node);
pm_node_destroy(parser, node);
return result;
}
case PM_LOCAL_VARIABLE_READ_NODE: {
+ if (pm_token_is_numbered_parameter(node->location.start, node->location.end)) {
+ PM_PARSER_ERR_FORMAT(parser, node->location.start, node->location.end, PM_ERR_PARAMETER_NUMBERED_RESERVED, node->location.start);
+ pm_node_unreference(parser, node);
+ }
+
pm_local_variable_read_node_t *cast = (pm_local_variable_read_node_t *) node;
parser_lex(parser);
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
- pm_node_t *result = (pm_node_t *) pm_local_variable_operator_write_node_create(parser, node, &token, value, cast->name, cast->depth);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
+ pm_node_t *result = UP(pm_local_variable_operator_write_node_create(parser, node, &token, value, cast->name, cast->depth));
pm_node_destroy(parser, node);
return result;
@@ -20459,10 +21051,10 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
pm_refute_numbered_parameter(parser, message_loc->start, message_loc->end);
pm_constant_id_t constant_id = pm_parser_local_add_location(parser, message_loc->start, message_loc->end, 1);
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
- pm_node_t *result = (pm_node_t *) pm_local_variable_operator_write_node_create(parser, (pm_node_t *) cast, &token, value, constant_id, 0);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
+ pm_node_t *result = UP(pm_local_variable_operator_write_node_create(parser, UP(cast), &token, value, constant_id, 0));
- pm_node_destroy(parser, (pm_node_t *) cast);
+ pm_node_destroy(parser, UP(cast));
return result;
}
@@ -20470,8 +21062,8 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
// this is an aref expression, and we can transform it into
// an aset expression.
if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_INDEX)) {
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
- return (pm_node_t *) pm_index_operator_write_node_create(parser, cast, &token, value);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
+ return UP(pm_index_operator_write_node_create(parser, cast, &token, value));
}
// If this node cannot be writable, then we have an error.
@@ -20482,8 +21074,8 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
}
parse_call_operator_write(parser, cast, &token);
- pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
- return (pm_node_t *) pm_call_operator_write_node_create(parser, cast, &token, value);
+ pm_node_t *value = parse_assignment_value(parser, previous_binding_power, binding_power, accepts_command_call, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
+ return UP(pm_call_operator_write_node_create(parser, cast, &token, value));
}
case PM_MULTI_WRITE_NODE: {
parser_lex(parser);
@@ -20504,15 +21096,15 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
case PM_TOKEN_KEYWORD_AND: {
parser_lex(parser);
- pm_node_t *right = parse_expression(parser, binding_power, parser->previous.type == PM_TOKEN_KEYWORD_AND, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
- return (pm_node_t *) pm_and_node_create(parser, node, &token, right);
+ pm_node_t *right = parse_expression(parser, binding_power, parser->previous.type == PM_TOKEN_KEYWORD_AND, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
+ return UP(pm_and_node_create(parser, node, &token, right));
}
case PM_TOKEN_KEYWORD_OR:
case PM_TOKEN_PIPE_PIPE: {
parser_lex(parser);
- pm_node_t *right = parse_expression(parser, binding_power, parser->previous.type == PM_TOKEN_KEYWORD_OR, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
- return (pm_node_t *) pm_or_node_create(parser, node, &token, right);
+ pm_node_t *right = parse_expression(parser, binding_power, parser->previous.type == PM_TOKEN_KEYWORD_OR, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
+ return UP(pm_or_node_create(parser, node, &token, right));
}
case PM_TOKEN_EQUAL_TILDE: {
// Note that we _must_ parse the value before adding the local
@@ -20523,11 +21115,11 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
//
// In this case, `foo` should be a method call and not a local yet.
parser_lex(parser);
- pm_node_t *argument = parse_expression(parser, binding_power, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
+ pm_node_t *argument = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
// By default, we're going to create a call node and then return it.
pm_call_node_t *call = pm_call_node_binary_create(parser, node, &token, argument, 0);
- pm_node_t *result = (pm_node_t *) call;
+ pm_node_t *result = UP(call);
// If the receiver of this =~ is a regular expression node, then we
// need to introduce local variables for it based on its named
@@ -20568,14 +21160,14 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
pm_string_t owned;
pm_string_owned_init(&owned, (uint8_t *) memory, total_length);
- result = parse_regular_expression_named_captures(parser, &owned, call);
+ result = parse_regular_expression_named_captures(parser, &owned, call, PM_NODE_FLAG_P(node, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED));
pm_string_free(&owned);
}
} else if (PM_NODE_TYPE_P(node, PM_REGULAR_EXPRESSION_NODE)) {
// If we have a regular expression node, then we can just parse
// the named captures directly off the unescaped string.
const pm_string_t *content = &((pm_regular_expression_node_t *) node)->unescaped;
- result = parse_regular_expression_named_captures(parser, content, call);
+ result = parse_regular_expression_named_captures(parser, content, call, PM_NODE_FLAG_P(node, PM_REGULAR_EXPRESSION_FLAGS_EXTENDED));
}
return result;
@@ -20602,8 +21194,35 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
case PM_TOKEN_STAR:
case PM_TOKEN_STAR_STAR: {
parser_lex(parser);
- pm_node_t *argument = parse_expression(parser, binding_power, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
- return (pm_node_t *) pm_call_node_binary_create(parser, node, &token, argument, 0);
+ pm_token_t operator = parser->previous;
+ switch (PM_NODE_TYPE(node)) {
+ case PM_RESCUE_MODIFIER_NODE: {
+ pm_rescue_modifier_node_t *cast = (pm_rescue_modifier_node_t *) node;
+ if (PM_NODE_TYPE_P(cast->rescue_expression, PM_MATCH_PREDICATE_NODE) || PM_NODE_TYPE_P(cast->rescue_expression, PM_MATCH_REQUIRED_NODE)) {
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, operator, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(operator.type));
+ }
+ break;
+ }
+ case PM_AND_NODE: {
+ pm_and_node_t *cast = (pm_and_node_t *) node;
+ if (PM_NODE_TYPE_P(cast->right, PM_MATCH_PREDICATE_NODE) || PM_NODE_TYPE_P(cast->right, PM_MATCH_REQUIRED_NODE)) {
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, operator, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(operator.type));
+ }
+ break;
+ }
+ case PM_OR_NODE: {
+ pm_or_node_t *cast = (pm_or_node_t *) node;
+ if (PM_NODE_TYPE_P(cast->right, PM_MATCH_PREDICATE_NODE) || PM_NODE_TYPE_P(cast->right, PM_MATCH_REQUIRED_NODE)) {
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, operator, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(operator.type));
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ pm_node_t *argument = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
+ return UP(pm_call_node_binary_create(parser, node, &token, argument, 0));
}
case PM_TOKEN_GREATER:
case PM_TOKEN_GREATER_EQUAL:
@@ -20614,8 +21233,8 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
}
parser_lex(parser);
- pm_node_t *argument = parse_expression(parser, binding_power, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
- return (pm_node_t *) pm_call_node_binary_create(parser, node, &token, argument, PM_CALL_NODE_FLAGS_COMPARISON);
+ pm_node_t *argument = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
+ return UP(pm_call_node_binary_create(parser, node, &token, argument, PM_CALL_NODE_FLAGS_COMPARISON));
}
case PM_TOKEN_AMPERSAND_DOT:
case PM_TOKEN_DOT: {
@@ -20625,8 +21244,34 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
// This if statement handles the foo.() syntax.
if (match1(parser, PM_TOKEN_PARENTHESIS_LEFT)) {
- parse_arguments_list(parser, &arguments, true, false);
- return (pm_node_t *) pm_call_node_shorthand_create(parser, node, &operator, &arguments);
+ parse_arguments_list(parser, &arguments, true, false, (uint16_t) (depth + 1));
+ return UP(pm_call_node_shorthand_create(parser, node, &operator, &arguments));
+ }
+
+ switch (PM_NODE_TYPE(node)) {
+ case PM_RESCUE_MODIFIER_NODE: {
+ pm_rescue_modifier_node_t *cast = (pm_rescue_modifier_node_t *) node;
+ if (PM_NODE_TYPE_P(cast->rescue_expression, PM_MATCH_PREDICATE_NODE) || PM_NODE_TYPE_P(cast->rescue_expression, PM_MATCH_REQUIRED_NODE)) {
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, operator, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(operator.type));
+ }
+ break;
+ }
+ case PM_AND_NODE: {
+ pm_and_node_t *cast = (pm_and_node_t *) node;
+ if (PM_NODE_TYPE_P(cast->right, PM_MATCH_PREDICATE_NODE) || PM_NODE_TYPE_P(cast->right, PM_MATCH_REQUIRED_NODE)) {
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, operator, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(operator.type));
+ }
+ break;
+ }
+ case PM_OR_NODE: {
+ pm_or_node_t *cast = (pm_or_node_t *) node;
+ if (PM_NODE_TYPE_P(cast->right, PM_MATCH_PREDICATE_NODE) || PM_NODE_TYPE_P(cast->right, PM_MATCH_REQUIRED_NODE)) {
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, operator, PM_ERR_EXPECT_EOL_AFTER_STATEMENT, pm_token_type_human(operator.type));
+ }
+ break;
+ }
+ default:
+ break;
}
pm_token_t message;
@@ -20647,7 +21292,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
}
}
- parse_arguments_list(parser, &arguments, true, accepts_command_call);
+ parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1));
pm_call_node_t *call = pm_call_node_call_create(parser, node, &operator, &message, &arguments);
if (
@@ -20656,9 +21301,9 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
arguments.opening_loc.start == NULL &&
match1(parser, PM_TOKEN_COMMA)
) {
- return parse_targets_validate(parser, (pm_node_t *) call, PM_BINDING_POWER_INDEX);
+ return parse_targets_validate(parser, UP(call), PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
} else {
- return (pm_node_t *) call;
+ return UP(call);
}
}
case PM_TOKEN_DOT_DOT:
@@ -20667,40 +21312,40 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
pm_node_t *right = NULL;
if (token_begins_expression_p(parser->current.type)) {
- right = parse_expression(parser, binding_power, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR);
+ right = parse_expression(parser, binding_power, false, false, PM_ERR_EXPECT_EXPRESSION_AFTER_OPERATOR, (uint16_t) (depth + 1));
}
- return (pm_node_t *) pm_range_node_create(parser, node, &token, right);
+ return UP(pm_range_node_create(parser, node, &token, right));
}
case PM_TOKEN_KEYWORD_IF_MODIFIER: {
pm_token_t keyword = parser->current;
parser_lex(parser);
- pm_node_t *predicate = parse_value_expression(parser, binding_power, true, PM_ERR_CONDITIONAL_IF_PREDICATE);
- return (pm_node_t *) pm_if_node_modifier_create(parser, node, &keyword, predicate);
+ pm_node_t *predicate = parse_value_expression(parser, binding_power, true, false, PM_ERR_CONDITIONAL_IF_PREDICATE, (uint16_t) (depth + 1));
+ return UP(pm_if_node_modifier_create(parser, node, &keyword, predicate));
}
case PM_TOKEN_KEYWORD_UNLESS_MODIFIER: {
pm_token_t keyword = parser->current;
parser_lex(parser);
- pm_node_t *predicate = parse_value_expression(parser, binding_power, true, PM_ERR_CONDITIONAL_UNLESS_PREDICATE);
- return (pm_node_t *) pm_unless_node_modifier_create(parser, node, &keyword, predicate);
+ pm_node_t *predicate = parse_value_expression(parser, binding_power, true, false, PM_ERR_CONDITIONAL_UNLESS_PREDICATE, (uint16_t) (depth + 1));
+ return UP(pm_unless_node_modifier_create(parser, node, &keyword, predicate));
}
case PM_TOKEN_KEYWORD_UNTIL_MODIFIER: {
parser_lex(parser);
pm_statements_node_t *statements = pm_statements_node_create(parser);
- pm_statements_node_body_append(parser, statements, node);
+ pm_statements_node_body_append(parser, statements, node, true);
- pm_node_t *predicate = parse_value_expression(parser, binding_power, true, PM_ERR_CONDITIONAL_UNTIL_PREDICATE);
- return (pm_node_t *) pm_until_node_modifier_create(parser, &token, predicate, statements, PM_NODE_TYPE_P(node, PM_BEGIN_NODE) ? PM_LOOP_FLAGS_BEGIN_MODIFIER : 0);
+ pm_node_t *predicate = parse_value_expression(parser, binding_power, true, false, PM_ERR_CONDITIONAL_UNTIL_PREDICATE, (uint16_t) (depth + 1));
+ return UP(pm_until_node_modifier_create(parser, &token, predicate, statements, PM_NODE_TYPE_P(node, PM_BEGIN_NODE) ? PM_LOOP_FLAGS_BEGIN_MODIFIER : 0));
}
case PM_TOKEN_KEYWORD_WHILE_MODIFIER: {
parser_lex(parser);
pm_statements_node_t *statements = pm_statements_node_create(parser);
- pm_statements_node_body_append(parser, statements, node);
+ pm_statements_node_body_append(parser, statements, node, true);
- pm_node_t *predicate = parse_value_expression(parser, binding_power, true, PM_ERR_CONDITIONAL_WHILE_PREDICATE);
- return (pm_node_t *) pm_while_node_modifier_create(parser, &token, predicate, statements, PM_NODE_TYPE_P(node, PM_BEGIN_NODE) ? PM_LOOP_FLAGS_BEGIN_MODIFIER : 0);
+ pm_node_t *predicate = parse_value_expression(parser, binding_power, true, false, PM_ERR_CONDITIONAL_WHILE_PREDICATE, (uint16_t) (depth + 1));
+ return UP(pm_while_node_modifier_create(parser, &token, predicate, statements, PM_NODE_TYPE_P(node, PM_BEGIN_NODE) ? PM_LOOP_FLAGS_BEGIN_MODIFIER : 0));
}
case PM_TOKEN_QUESTION_MARK: {
context_push(parser, PM_CONTEXT_TERNARY);
@@ -20710,7 +21355,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
pm_token_t qmark = parser->current;
parser_lex(parser);
- pm_node_t *true_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_TERNARY_EXPRESSION_TRUE);
+ pm_node_t *true_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_TERNARY_EXPRESSION_TRUE, (uint16_t) (depth + 1));
if (parser->recovering) {
// If parsing the true expression of this ternary resulted in a syntax
@@ -20720,26 +21365,26 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
// accidentally move past a ':' token that occurs after the syntax
// error.
pm_token_t colon = (pm_token_t) { .type = PM_TOKEN_MISSING, .start = parser->previous.end, .end = parser->previous.end };
- pm_node_t *false_expression = (pm_node_t *) pm_missing_node_create(parser, colon.start, colon.end);
+ pm_node_t *false_expression = UP(pm_missing_node_create(parser, colon.start, colon.end));
context_pop(parser);
pop_block_exits(parser, previous_block_exits);
pm_node_list_free(&current_block_exits);
- return (pm_node_t *) pm_if_node_ternary_create(parser, node, &qmark, true_expression, &colon, false_expression);
+ return UP(pm_if_node_ternary_create(parser, node, &qmark, true_expression, &colon, false_expression));
}
accept1(parser, PM_TOKEN_NEWLINE);
expect1(parser, PM_TOKEN_COLON, PM_ERR_TERNARY_COLON);
pm_token_t colon = parser->previous;
- pm_node_t *false_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, false, PM_ERR_TERNARY_EXPRESSION_FALSE);
+ pm_node_t *false_expression = parse_expression(parser, PM_BINDING_POWER_DEFINED, false, false, PM_ERR_TERNARY_EXPRESSION_FALSE, (uint16_t) (depth + 1));
context_pop(parser);
pop_block_exits(parser, previous_block_exits);
pm_node_list_free(&current_block_exits);
- return (pm_node_t *) pm_if_node_ternary_create(parser, node, &qmark, true_expression, &colon, false_expression);
+ return UP(pm_if_node_ternary_create(parser, node, &qmark, true_expression, &colon, false_expression));
}
case PM_TOKEN_COLON_COLON: {
parser_lex(parser);
@@ -20763,16 +21408,16 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
pm_token_t message = parser->previous;
pm_arguments_t arguments = { 0 };
- parse_arguments_list(parser, &arguments, true, accepts_command_call);
- path = (pm_node_t *) pm_call_node_call_create(parser, node, &delimiter, &message, &arguments);
+ parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1));
+ path = UP(pm_call_node_call_create(parser, node, &delimiter, &message, &arguments));
} else {
// Otherwise, this is a constant path. That would look like Foo::Bar.
- path = (pm_node_t *) pm_constant_path_node_create(parser, node, &delimiter, &parser->previous);
+ path = UP(pm_constant_path_node_create(parser, node, &delimiter, &parser->previous));
}
// If this is followed by a comma then it is a multiple assignment.
if (previous_binding_power == PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_COMMA)) {
- return parse_targets_validate(parser, path, PM_BINDING_POWER_INDEX);
+ return parse_targets_validate(parser, path, PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
}
return path;
@@ -20787,27 +21432,27 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
// If we have an identifier following a '::' operator, then it is for
// sure a method call.
pm_arguments_t arguments = { 0 };
- parse_arguments_list(parser, &arguments, true, accepts_command_call);
+ parse_arguments_list(parser, &arguments, true, accepts_command_call, (uint16_t) (depth + 1));
pm_call_node_t *call = pm_call_node_call_create(parser, node, &delimiter, &message, &arguments);
// If this is followed by a comma then it is a multiple assignment.
if (previous_binding_power == PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_COMMA)) {
- return parse_targets_validate(parser, (pm_node_t *) call, PM_BINDING_POWER_INDEX);
+ return parse_targets_validate(parser, UP(call), PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
}
- return (pm_node_t *) call;
+ return UP(call);
}
case PM_TOKEN_PARENTHESIS_LEFT: {
// If we have a parenthesis following a '::' operator, then it is the
// method call shorthand. That would look like Foo::(bar).
pm_arguments_t arguments = { 0 };
- parse_arguments_list(parser, &arguments, true, false);
+ parse_arguments_list(parser, &arguments, true, false, (uint16_t) (depth + 1));
- return (pm_node_t *) pm_call_node_shorthand_create(parser, node, &delimiter, &arguments);
+ return UP(pm_call_node_shorthand_create(parser, node, &delimiter, &arguments));
}
default: {
expect1(parser, PM_TOKEN_CONSTANT, PM_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT);
- return (pm_node_t *) pm_constant_path_node_create(parser, node, &delimiter, &parser->previous);
+ return UP(pm_constant_path_node_create(parser, node, &delimiter, &parser->previous));
}
}
}
@@ -20816,10 +21461,10 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
accept1(parser, PM_TOKEN_NEWLINE);
- pm_node_t *value = parse_expression(parser, binding_power, true, PM_ERR_RESCUE_MODIFIER_VALUE);
+ pm_node_t *value = parse_expression(parser, binding_power, true, false, PM_ERR_RESCUE_MODIFIER_VALUE, (uint16_t) (depth + 1));
context_pop(parser);
- return (pm_node_t *) pm_rescue_modifier_node_create(parser, node, &token, value);
+ return UP(pm_rescue_modifier_node_create(parser, node, &token, value));
}
case PM_TOKEN_BRACKET_LEFT: {
parser_lex(parser);
@@ -20829,7 +21474,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
if (!accept1(parser, PM_TOKEN_BRACKET_RIGHT)) {
pm_accepts_block_stack_push(parser, true);
- parse_arguments(parser, &arguments, false, PM_TOKEN_BRACKET_RIGHT);
+ parse_arguments(parser, &arguments, false, PM_TOKEN_BRACKET_RIGHT, (uint16_t) (depth + 1));
pm_accepts_block_stack_pop(parser);
expect1(parser, PM_TOKEN_BRACKET_RIGHT, PM_ERR_EXPECT_RBRACKET);
}
@@ -20840,7 +21485,7 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
// assignment and we should parse the targets.
if (previous_binding_power == PM_BINDING_POWER_STATEMENT && match1(parser, PM_TOKEN_COMMA)) {
pm_call_node_t *aref = pm_call_node_aref_create(parser, node, &arguments);
- return parse_targets_validate(parser, (pm_node_t *) aref, PM_BINDING_POWER_INDEX);
+ return parse_targets_validate(parser, UP(aref), PM_BINDING_POWER_INDEX, (uint16_t) (depth + 1));
}
// If we're at the end of the arguments, we can now check if there is a
@@ -20848,25 +21493,25 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
// add it to the arguments.
pm_block_node_t *block = NULL;
if (accept1(parser, PM_TOKEN_BRACE_LEFT)) {
- block = parse_block(parser);
+ block = parse_block(parser, (uint16_t) (depth + 1));
pm_arguments_validate_block(parser, &arguments, block);
} else if (pm_accepts_block_stack_p(parser) && accept1(parser, PM_TOKEN_KEYWORD_DO)) {
- block = parse_block(parser);
+ block = parse_block(parser, (uint16_t) (depth + 1));
}
if (block != NULL) {
if (arguments.block != NULL) {
- pm_parser_err_node(parser, (pm_node_t *) block, PM_ERR_ARGUMENT_AFTER_BLOCK);
+ pm_parser_err_node(parser, UP(block), PM_ERR_ARGUMENT_AFTER_BLOCK);
if (arguments.arguments == NULL) {
arguments.arguments = pm_arguments_node_create(parser);
}
pm_arguments_node_arguments_append(arguments.arguments, arguments.block);
}
- arguments.block = (pm_node_t *) block;
+ arguments.block = UP(block);
}
- return (pm_node_t *) pm_call_node_aref_create(parser, node, &arguments);
+ return UP(pm_call_node_aref_create(parser, node, &arguments));
}
case PM_TOKEN_KEYWORD_IN: {
bool previous_pattern_matching_newlines = parser->pattern_matching_newlines;
@@ -20878,12 +21523,12 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
pm_constant_id_list_t captures = { 0 };
- pm_node_t *pattern = parse_pattern(parser, &captures, PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_IN);
+ pm_node_t *pattern = parse_pattern(parser, &captures, PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_IN, (uint16_t) (depth + 1));
parser->pattern_matching_newlines = previous_pattern_matching_newlines;
pm_constant_id_list_free(&captures);
- return (pm_node_t *) pm_match_predicate_node_create(parser, node, pattern, &operator);
+ return UP(pm_match_predicate_node_create(parser, node, pattern, &operator));
}
case PM_TOKEN_EQUAL_GREATER: {
bool previous_pattern_matching_newlines = parser->pattern_matching_newlines;
@@ -20895,12 +21540,12 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
parser_lex(parser);
pm_constant_id_list_t captures = { 0 };
- pm_node_t *pattern = parse_pattern(parser, &captures, PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_HROCKET);
+ pm_node_t *pattern = parse_pattern(parser, &captures, PM_PARSE_PATTERN_TOP | PM_PARSE_PATTERN_MULTI, PM_ERR_PATTERN_EXPRESSION_AFTER_HROCKET, (uint16_t) (depth + 1));
parser->pattern_matching_newlines = previous_pattern_matching_newlines;
pm_constant_id_list_free(&captures);
- return (pm_node_t *) pm_match_required_node_create(parser, node, pattern, &operator);
+ return UP(pm_match_required_node_create(parser, node, pattern, &operator));
}
default:
assert(false && "unreachable");
@@ -20913,6 +21558,19 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
#undef PM_PARSE_PATTERN_MULTI
/**
+ * Determine if a given call node looks like a "command", which means it has
+ * arguments but does not have parentheses.
+ */
+static inline bool
+pm_call_node_command_p(const pm_call_node_t *node) {
+ return (
+ (node->opening_loc.start == NULL) &&
+ (node->block == NULL || PM_NODE_TYPE_P(node->block, PM_BLOCK_ARGUMENT_NODE)) &&
+ (node->arguments != NULL || node->block != NULL)
+ );
+}
+
+/**
* Parse an expression at the given point of the parser using the given binding
* power to parse subsequent chains. If this function finds a syntax error, it
* will append the error message to the parser's error list.
@@ -20921,8 +21579,13 @@ parse_expression_infix(pm_parser_t *parser, pm_node_t *node, pm_binding_power_t
* determine if they need to perform additional cleanup.
*/
static pm_node_t *
-parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, pm_diagnostic_id_t diag_id) {
- pm_node_t *node = parse_expression_prefix(parser, binding_power, accepts_command_call, diag_id);
+parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool accepts_command_call, bool accepts_label, pm_diagnostic_id_t diag_id, uint16_t depth) {
+ if (PRISM_UNLIKELY(depth >= PRISM_DEPTH_MAXIMUM)) {
+ pm_parser_err_current(parser, PM_ERR_NESTING_TOO_DEEP);
+ return UP(pm_missing_node_create(parser, parser->current.start, parser->current.end));
+ }
+
+ pm_node_t *node = parse_expression_prefix(parser, binding_power, accepts_command_call, accepts_label, diag_id, depth);
switch (PM_NODE_TYPE(node)) {
case PM_MISSING_NODE:
@@ -20933,6 +21596,7 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc
case PM_POST_EXECUTION_NODE:
case PM_ALIAS_GLOBAL_VARIABLE_NODE:
case PM_ALIAS_METHOD_NODE:
+ case PM_MULTI_WRITE_NODE:
case PM_UNDEF_NODE:
// These expressions are statements, and cannot be followed by
// operators (except modifiers).
@@ -20940,12 +21604,21 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc
return node;
}
break;
- case PM_RANGE_NODE:
- // Range operators are non-associative, so that it does not
- // associate with other range operators (i.e. `..1..` should be
- // rejected). For this reason, we check such a case for unary ranges
- // here, and if so, it returns the node immediately.
- if ((((pm_range_node_t *) node)->left == NULL) && pm_binding_powers[parser->current.type].left >= PM_BINDING_POWER_RANGE) {
+ case PM_CALL_NODE:
+ // If we have a call node, then we need to check if it looks like a
+ // method call without parentheses that contains arguments. If it
+ // does, then it has different rules for parsing infix operators,
+ // namely that it only accepts composition (and/or) and modifiers
+ // (if/unless/etc.).
+ if ((pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_COMPOSITION) && pm_call_node_command_p((pm_call_node_t *) node)) {
+ return node;
+ }
+ break;
+ case PM_SYMBOL_NODE:
+ // If we have a symbol node that is being parsed as a label, then we
+ // need to immediately return, because there should never be an
+ // infix operator following this node.
+ if (pm_symbol_node_label_p(node)) {
return node;
}
break;
@@ -20956,23 +21629,81 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc
// Otherwise we'll look and see if the next token can be parsed as an infix
// operator. If it can, then we'll parse it using parse_expression_infix.
pm_binding_powers_t current_binding_powers;
+ pm_token_type_t current_token_type;
+
while (
- current_binding_powers = pm_binding_powers[parser->current.type],
+ current_token_type = parser->current.type,
+ current_binding_powers = pm_binding_powers[current_token_type],
binding_power <= current_binding_powers.left &&
current_binding_powers.binary
) {
- node = parse_expression_infix(parser, node, binding_power, current_binding_powers.right, accepts_command_call);
+ node = parse_expression_infix(parser, node, binding_power, current_binding_powers.right, accepts_command_call, (uint16_t) (depth + 1));
+
+ if (context_terminator(parser->current_context->context, &parser->current)) {
+ // If this token terminates the current context, then we need to
+ // stop parsing the expression, as it has become a statement.
+ return node;
+ }
+
+ switch (PM_NODE_TYPE(node)) {
+ case PM_MULTI_WRITE_NODE:
+ // Multi-write nodes are statements, and cannot be followed by
+ // operators except modifiers.
+ if (pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER) {
+ return node;
+ }
+ break;
+ case PM_CLASS_VARIABLE_WRITE_NODE:
+ case PM_CONSTANT_PATH_WRITE_NODE:
+ case PM_CONSTANT_WRITE_NODE:
+ case PM_GLOBAL_VARIABLE_WRITE_NODE:
+ case PM_INSTANCE_VARIABLE_WRITE_NODE:
+ case PM_LOCAL_VARIABLE_WRITE_NODE:
+ // These expressions are statements, by virtue of the right-hand
+ // side of their write being an implicit array.
+ if (PM_NODE_FLAG_P(node, PM_WRITE_NODE_FLAGS_IMPLICIT_ARRAY) && pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER) {
+ return node;
+ }
+ break;
+ case PM_CALL_NODE:
+ // These expressions are also statements, by virtue of the
+ // right-hand side of the expression (i.e., the last argument to
+ // the call node) being an implicit array.
+ if (PM_NODE_FLAG_P(node, PM_CALL_NODE_FLAGS_IMPLICIT_ARRAY) && pm_binding_powers[parser->current.type].left > PM_BINDING_POWER_MODIFIER) {
+ return node;
+ }
+ break;
+ default:
+ break;
+ }
+ // If the operator is nonassoc and we should not be able to parse the
+ // upcoming infix operator, break.
if (current_binding_powers.nonassoc) {
- bool endless_range_p = PM_NODE_TYPE_P(node, PM_RANGE_NODE) && ((pm_range_node_t *) node)->right == NULL;
- pm_binding_power_t left = endless_range_p ? PM_BINDING_POWER_TERM : current_binding_powers.left;
- if (
- left <= pm_binding_powers[parser->current.type].left ||
- // Exceptionally to operator precedences, '1.. & 2' is rejected.
- // '1.. || 2' is also an exception, but it is handled by the lexer.
- // (Here, parser->current is PM_TOKEN_PIPE, not PM_TOKEN_PIPE_PIPE).
- (endless_range_p && match1(parser, PM_TOKEN_AMPERSAND))
- ) {
+ // If this is a non-assoc operator and we are about to parse the
+ // exact same operator, then we need to add an error.
+ if (match1(parser, current_token_type)) {
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_NON_ASSOCIATIVE_OPERATOR, pm_token_type_human(parser->current.type), pm_token_type_human(current_token_type));
+ break;
+ }
+
+ // If this is an endless range, then we need to reject a couple of
+ // additional operators because it violates the normal operator
+ // precedence rules. Those patterns are:
+ //
+ // 1.. & 2
+ // 1.. * 2
+ //
+ if (PM_NODE_TYPE_P(node, PM_RANGE_NODE) && ((pm_range_node_t *) node)->right == NULL) {
+ if (match4(parser, PM_TOKEN_UAMPERSAND, PM_TOKEN_USTAR, PM_TOKEN_DOT, PM_TOKEN_AMPERSAND_DOT)) {
+ PM_PARSER_ERR_TOKEN_FORMAT(parser, parser->current, PM_ERR_NON_ASSOCIATIVE_OPERATOR, pm_token_type_human(parser->current.type), pm_token_type_human(current_token_type));
+ break;
+ }
+
+ if (PM_BINDING_POWER_TERM <= pm_binding_powers[parser->current.type].left) {
+ break;
+ }
+ } else if (current_binding_powers.left <= pm_binding_powers[parser->current.type].left) {
break;
}
}
@@ -21038,63 +21769,72 @@ parse_expression(pm_parser_t *parser, pm_binding_power_t binding_power, bool acc
static pm_statements_node_t *
wrap_statements(pm_parser_t *parser, pm_statements_node_t *statements) {
if (PM_PARSER_COMMAND_LINE_OPTION_P(parser)) {
+ if (statements == NULL) {
+ statements = pm_statements_node_create(parser);
+ }
+
pm_arguments_node_t *arguments = pm_arguments_node_create(parser);
pm_arguments_node_arguments_append(
arguments,
- (pm_node_t *) pm_global_variable_read_node_synthesized_create(parser, pm_parser_constant_id_constant(parser, "$_", 2))
+ UP(pm_global_variable_read_node_synthesized_create(parser, pm_parser_constant_id_constant(parser, "$_", 2)))
);
- pm_statements_node_body_append(parser, statements, (pm_node_t *) pm_call_node_fcall_synthesized_create(
+ pm_statements_node_body_append(parser, statements, UP(pm_call_node_fcall_synthesized_create(
parser,
arguments,
pm_parser_constant_id_constant(parser, "print", 5)
- ));
+ )), true);
}
if (PM_PARSER_COMMAND_LINE_OPTION_N(parser)) {
if (PM_PARSER_COMMAND_LINE_OPTION_A(parser)) {
+ if (statements == NULL) {
+ statements = pm_statements_node_create(parser);
+ }
+
pm_arguments_node_t *arguments = pm_arguments_node_create(parser);
pm_arguments_node_arguments_append(
arguments,
- (pm_node_t *) pm_global_variable_read_node_synthesized_create(parser, pm_parser_constant_id_constant(parser, "$;", 2))
+ UP(pm_global_variable_read_node_synthesized_create(parser, pm_parser_constant_id_constant(parser, "$;", 2)))
);
pm_global_variable_read_node_t *receiver = pm_global_variable_read_node_synthesized_create(parser, pm_parser_constant_id_constant(parser, "$_", 2));
- pm_call_node_t *call = pm_call_node_call_synthesized_create(parser, (pm_node_t *) receiver, "split", arguments);
+ pm_call_node_t *call = pm_call_node_call_synthesized_create(parser, UP(receiver), "split", arguments);
pm_global_variable_write_node_t *write = pm_global_variable_write_node_synthesized_create(
parser,
pm_parser_constant_id_constant(parser, "$F", 2),
- (pm_node_t *) call
+ UP(call)
);
- pm_statements_node_body_prepend(statements, (pm_node_t *) write);
+ pm_statements_node_body_prepend(statements, UP(write));
}
pm_arguments_node_t *arguments = pm_arguments_node_create(parser);
pm_arguments_node_arguments_append(
arguments,
- (pm_node_t *) pm_global_variable_read_node_synthesized_create(parser, pm_parser_constant_id_constant(parser, "$/", 2))
+ UP(pm_global_variable_read_node_synthesized_create(parser, pm_parser_constant_id_constant(parser, "$/", 2)))
);
if (PM_PARSER_COMMAND_LINE_OPTION_L(parser)) {
pm_keyword_hash_node_t *keywords = pm_keyword_hash_node_create(parser);
- pm_keyword_hash_node_elements_append(keywords, (pm_node_t *) pm_assoc_node_create(
+ pm_keyword_hash_node_elements_append(keywords, UP(pm_assoc_node_create(
parser,
- (pm_node_t *) pm_symbol_node_synthesized_create(parser, "chomp"),
+ UP(pm_symbol_node_synthesized_create(parser, "chomp")),
&(pm_token_t) { .type = PM_TOKEN_NOT_PROVIDED, .start = parser->start, .end = parser->start },
- (pm_node_t *) pm_true_node_synthesized_create(parser)
- ));
+ UP(pm_true_node_synthesized_create(parser))
+ )));
- pm_arguments_node_arguments_append(arguments, (pm_node_t *) keywords);
+ pm_arguments_node_arguments_append(arguments, UP(keywords));
+ pm_node_flag_set(UP(arguments), PM_ARGUMENTS_NODE_FLAGS_CONTAINS_KEYWORDS);
}
pm_statements_node_t *wrapped_statements = pm_statements_node_create(parser);
- pm_statements_node_body_append(parser, wrapped_statements, (pm_node_t *) pm_while_node_synthesized_create(
+ pm_statements_node_body_append(parser, wrapped_statements, UP(pm_while_node_synthesized_create(
parser,
- (pm_node_t *) pm_call_node_fcall_synthesized_create(parser, arguments, pm_parser_constant_id_constant(parser, "gets", 4)),
+ UP(pm_call_node_fcall_synthesized_create(parser, arguments, pm_parser_constant_id_constant(parser, "gets", 4))),
statements
- ));
+ )), true);
statements = wrapped_statements;
}
@@ -21114,12 +21854,13 @@ parse_program(pm_parser_t *parser) {
pm_parser_scope_push(parser, true);
}
+ pm_node_list_t current_block_exits = { 0 };
+ pm_node_list_t *previous_block_exits = push_block_exits(parser, &current_block_exits);
+
parser_lex(parser);
- pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_MAIN);
+ pm_statements_node_t *statements = parse_statements(parser, PM_CONTEXT_MAIN, 0);
- if (statements == NULL) {
- statements = pm_statements_node_create(parser);
- } else if (!parser->parsing_eval) {
+ if (statements != NULL && !parser->parsing_eval) {
// If we have statements, then the top-level statement should be
// explicitly checked as well. We have to do this here because
// everywhere else we check all but the last statement.
@@ -21131,20 +21872,25 @@ parse_program(pm_parser_t *parser) {
pm_locals_order(parser, &parser->current_scope->locals, &locals, true);
pm_parser_scope_pop(parser);
- // If this is an empty file, then we're still going to parse all of the
- // statements in order to gather up all of the comments and such. Here we'll
- // correct the location information.
- if (pm_statements_node_body_length(statements) == 0) {
- pm_statements_node_location_set(statements, parser->start, parser->start);
- }
-
// At the top level, see if we need to wrap the statements in a program
// node with a while loop based on the options.
if (parser->command_line & (PM_OPTIONS_COMMAND_LINE_P | PM_OPTIONS_COMMAND_LINE_N)) {
statements = wrap_statements(parser, statements);
+ } else {
+ flush_block_exits(parser, previous_block_exits);
}
- return (pm_node_t *) pm_program_node_create(parser, &locals, statements);
+ pm_node_list_free(&current_block_exits);
+
+ // If this is an empty file, then we're still going to parse all of the
+ // statements in order to gather up all of the comments and such. Here we'll
+ // correct the location information.
+ if (statements == NULL) {
+ statements = pm_statements_node_create(parser);
+ pm_statements_node_location_set(statements, parser->start, parser->start);
+ }
+
+ return UP(pm_program_node_create(parser, &locals, statements));
}
/******************************************************************************/
@@ -21164,13 +21910,16 @@ static const char *
pm_strnstr(const char *big, const char *little, size_t big_length) {
size_t little_length = strlen(little);
- for (const char *big_end = big + big_length; big < big_end; big++) {
+ for (const char *max = big + big_length - little_length; big <= max; big++) {
if (*big == *little && memcmp(big, little, little_length) == 0) return big;
}
return NULL;
}
+#ifdef _WIN32
+#define pm_parser_warn_shebang_carriage_return(parser, start, length) ((void) 0)
+#else
/**
* Potentially warn the user if the shebang that has been found to include
* "ruby" has a carriage return at the end, as that can cause problems on some
@@ -21178,10 +21927,38 @@ pm_strnstr(const char *big, const char *little, size_t big_length) {
*/
static void
pm_parser_warn_shebang_carriage_return(pm_parser_t *parser, const uint8_t *start, size_t length) {
- if (length > 2 && start[length - 1] == '\n' && start[length - 2] == '\r') {
+ if (length > 2 && start[length - 2] == '\r' && start[length - 1] == '\n') {
pm_parser_warn(parser, start, start + length, PM_WARN_SHEBANG_CARRIAGE_RETURN);
}
}
+#endif
+
+/**
+ * Process the shebang when initializing the parser. This function assumes that
+ * the shebang_callback option has already been checked for nullability.
+ */
+static void
+pm_parser_init_shebang(pm_parser_t *parser, const pm_options_t *options, const char *engine, size_t length) {
+ const char *switches = pm_strnstr(engine, " -", length);
+ if (switches == NULL) return;
+
+ pm_options_t next_options = *options;
+ options->shebang_callback(
+ &next_options,
+ (const uint8_t *) (switches + 1),
+ length - ((size_t) (switches - engine)) - 1,
+ options->shebang_callback_data
+ );
+
+ size_t encoding_length;
+ if ((encoding_length = pm_string_length(&next_options.encoding)) > 0) {
+ const uint8_t *encoding_source = pm_string_source(&next_options.encoding);
+ parser_lex_magic_comment_encoding_value(parser, encoding_source, encoding_source + encoding_length);
+ }
+
+ parser->command_line = next_options.command_line;
+ parser->frozen_string_literal = next_options.frozen_string_literal;
+}
/**
* Initialize a parser with the given start and end pointers.
@@ -21191,6 +21968,7 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm
assert(source != NULL);
*parser = (pm_parser_t) {
+ .node_id = 0,
.lex_state = PM_LEX_STATE_BEG,
.enclosure_nesting = 0,
.lambda_enclosure_nesting = -1,
@@ -21228,15 +22006,18 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm
.explicit_encoding = NULL,
.command_line = 0,
.parsing_eval = false,
+ .partial_script = false,
.command_start = true,
.recovering = false,
+ .encoding_locked = false,
.encoding_changed = false,
.pattern_matching_newlines = false,
.in_keyword_arg = false,
.current_block_exits = NULL,
.semantic_token_seen = false,
.frozen_string_literal = PM_OPTIONS_FROZEN_STRING_LITERAL_UNSET,
- .current_regular_expression_ascii_only = false
+ .current_regular_expression_ascii_only = false,
+ .warn_mismatched_indentation = true
};
// Initialize the constant pool. We're going to completely guess as to the
@@ -21277,6 +22058,9 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm
parser_lex_magic_comment_encoding_value(parser, encoding_source, encoding_source + encoding_length);
}
+ // encoding_locked option
+ parser->encoding_locked = options->encoding_locked;
+
// frozen_string_literal option
parser->frozen_string_literal = options->frozen_string_literal;
@@ -21286,8 +22070,12 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm
// version option
parser->version = options->version;
+ // partial_script
+ parser->partial_script = options->partial_script;
+
// scopes option
parser->parsing_eval = options->scopes_count > 0;
+ if (parser->parsing_eval) parser->warn_mismatched_indentation = false;
for (size_t scope_index = 0; scope_index < options->scopes_count; scope_index++) {
const pm_options_scope_t *scope = pm_options_scope_get(options, scope_index);
@@ -21295,7 +22083,7 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm
// Scopes given from the outside are not allowed to have numbered
// parameters.
- parser->current_scope->parameters |= PM_SCOPE_PARAMETERS_IMPLICIT_DISALLOWED;
+ parser->current_scope->parameters = ((pm_scope_parameters_t) scope->forwarding) | PM_SCOPE_PARAMETERS_IMPLICIT_DISALLOWED;
for (size_t local_index = 0; local_index < scope->locals_count; local_index++) {
const pm_string_t *local = pm_options_scope_local_get(scope, local_index);
@@ -21312,6 +22100,12 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm
}
}
+ // Now that we have established the user-provided options, check if
+ // a version was given and parse as the latest version otherwise.
+ if (parser->version == PM_OPTIONS_VERSION_UNSET) {
+ parser->version = PM_OPTIONS_VERSION_LATEST;
+ }
+
pm_accepts_block_stack_push(parser, true);
// Skip past the UTF-8 BOM if it exists.
@@ -21330,17 +22124,42 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm
// "ruby" and start parsing from there.
bool search_shebang = PM_PARSER_COMMAND_LINE_OPTION_X(parser);
- // If the first two bytes of the source are a shebang, then we'll indicate
- // that the encoding comment is at the end of the shebang.
- if (peek(parser) == '#' && peek_offset(parser, 1) == '!') {
- const uint8_t *newline = next_newline(parser->start, parser->end - parser->start);
- size_t length = (size_t) ((newline != NULL ? newline : parser->end) - parser->start);
+ // If the first two bytes of the source are a shebang, then we will do a bit
+ // of extra processing.
+ //
+ // First, we'll indicate that the encoding comment is at the end of the
+ // shebang. This means that when a shebang is present the encoding comment
+ // can begin on the second line.
+ //
+ // Second, we will check if the shebang includes "ruby". If it does, then we
+ // we will start parsing from there. We will also potentially warning the
+ // user if there is a carriage return at the end of the shebang. We will
+ // also potentially call the shebang callback if this is the main script to
+ // allow the caller to parse the shebang and find any command-line options.
+ // If the shebang does not include "ruby" and this is the main script being
+ // parsed, then we will start searching the file for a shebang that does
+ // contain "ruby" as if -x were passed on the command line.
+ const uint8_t *newline = next_newline(parser->current.end, parser->end - parser->current.end);
+ size_t length = (size_t) ((newline != NULL ? newline : parser->end) - parser->current.end);
+
+ if (length > 2 && parser->current.end[0] == '#' && parser->current.end[1] == '!') {
+ const char *engine;
+
+ if ((engine = pm_strnstr((const char *) parser->start, "ruby", length)) != NULL) {
+ if (newline != NULL) {
+ parser->encoding_comment_start = newline + 1;
+
+ if (options == NULL || options->main_script) {
+ pm_parser_warn_shebang_carriage_return(parser, parser->start, length + 1);
+ }
+ }
+
+ if (options != NULL && options->main_script && options->shebang_callback != NULL) {
+ pm_parser_init_shebang(parser, options, engine, length - ((size_t) (engine - (const char *) parser->start)));
+ }
- if (pm_strnstr((const char *) parser->start, "ruby", length) != NULL) {
- pm_parser_warn_shebang_carriage_return(parser, parser->start, length);
- if (newline != NULL) parser->encoding_comment_start = newline + 1;
search_shebang = false;
- } else {
+ } else if (options != NULL && options->main_script && !parser->parsing_eval) {
search_shebang = true;
}
}
@@ -21368,13 +22187,19 @@ pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm
size_t length = (size_t) ((newline != NULL ? newline : parser->end) - cursor);
if (length > 2 && cursor[0] == '#' && cursor[1] == '!') {
- if (parser->newline_list.size == 1) {
- pm_parser_warn_shebang_carriage_return(parser, cursor, length);
- }
-
- if (pm_strnstr((const char *) cursor, "ruby", length) != NULL) {
+ const char *engine;
+ if ((engine = pm_strnstr((const char *) cursor, "ruby", length)) != NULL) {
found_shebang = true;
- parser->encoding_comment_start = newline + 1;
+
+ if (newline != NULL) {
+ pm_parser_warn_shebang_carriage_return(parser, cursor, length + 1);
+ parser->encoding_comment_start = newline + 1;
+ }
+
+ if (options != NULL && options->shebang_callback != NULL) {
+ pm_parser_init_shebang(parser, options, engine, length - ((size_t) (engine - (const char *) cursor)));
+ }
+
break;
}
}
@@ -21474,22 +22299,25 @@ pm_parse(pm_parser_t *parser) {
* otherwise return true.
*/
static bool
-pm_parse_stream_read(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *fgets) {
+pm_parse_stream_read(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof) {
#define LINE_SIZE 4096
char line[LINE_SIZE];
- while (fgets(line, LINE_SIZE, stream) != NULL) {
- size_t length = strlen(line);
+ while (memset(line, '\n', LINE_SIZE), stream_fgets(line, LINE_SIZE, stream) != NULL) {
+ size_t length = LINE_SIZE;
+ while (length > 0 && line[length - 1] == '\n') length--;
- if (length == LINE_SIZE && line[length - 1] != '\n') {
+ if (length == LINE_SIZE) {
// If we read a line that is the maximum size and it doesn't end
// with a newline, then we'll just append it to the buffer and
// continue reading.
+ length--;
pm_buffer_append_string(buffer, line, length);
continue;
}
// Append the line to the buffer.
+ length--;
pm_buffer_append_string(buffer, line, length);
// Check if the line matches the __END__ marker. If it does, then stop
@@ -21507,6 +22335,12 @@ pm_parse_stream_read(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t
if (strncmp(line, "__END__\r\n", 9) == 0) return false;
break;
}
+
+ // All data should be read via gets. If the string returned by gets
+ // _doesn't_ end with a newline, then we assume we hit EOF condition.
+ if (stream_feof(stream)) {
+ break;
+ }
}
return true;
@@ -21542,16 +22376,17 @@ pm_parse_stream_unterminated_heredoc_p(pm_parser_t *parser) {
* can stream stdin in to Ruby so we need to support a streaming API.
*/
PRISM_EXPORTED_FUNCTION pm_node_t *
-pm_parse_stream(pm_parser_t *parser, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *fgets, const pm_options_t *options) {
+pm_parse_stream(pm_parser_t *parser, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options) {
pm_buffer_init(buffer);
- bool eof = pm_parse_stream_read(buffer, stream, fgets);
+ bool eof = pm_parse_stream_read(buffer, stream, stream_fgets, stream_feof);
+
pm_parser_init(parser, (const uint8_t *) pm_buffer_value(buffer), pm_buffer_length(buffer), options);
pm_node_t *node = pm_parse(parser);
while (!eof && parser->error_list.size > 0 && (parser->lex_modes.index > 0 || pm_parse_stream_unterminated_heredoc_p(parser))) {
pm_node_destroy(parser, node);
- eof = pm_parse_stream_read(buffer, stream, fgets);
+ eof = pm_parse_stream_read(buffer, stream, stream_fgets, stream_feof);
pm_parser_free(parser);
pm_parser_init(parser, (const uint8_t *) pm_buffer_value(buffer), pm_buffer_length(buffer), options);
@@ -21586,10 +22421,6 @@ pm_parse_success_p(const uint8_t *source, size_t size, const char *data) {
#undef PM_CASE_OPERATOR
#undef PM_CASE_WRITABLE
#undef PM_STRING_EMPTY
-#undef PM_LOCATION_NODE_BASE_VALUE
-#undef PM_LOCATION_NODE_VALUE
-#undef PM_LOCATION_NULL_VALUE
-#undef PM_LOCATION_TOKEN_VALUE
// We optionally support serializing to a binary string. For systems that don't
// want or need this functionality, it can be turned off with the
@@ -21643,13 +22474,13 @@ pm_serialize_parse(pm_buffer_t *buffer, const uint8_t *source, size_t size, cons
* given stream into to the given buffer.
*/
PRISM_EXPORTED_FUNCTION void
-pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *fgets, const char *data) {
+pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const char *data) {
pm_parser_t parser;
pm_options_t options = { 0 };
pm_options_read(&options, data);
pm_buffer_t parser_buffer;
- pm_node_t *node = pm_parse_stream(&parser, &parser_buffer, stream, fgets, &options);
+ pm_node_t *node = pm_parse_stream(&parser, &parser_buffer, stream, stream_fgets, stream_feof, &options);
pm_serialize_header(buffer);
pm_serialize_content(&parser, node, buffer);
pm_buffer_append_byte(buffer, '\0');
@@ -21683,3 +22514,166 @@ pm_serialize_parse_comments(pm_buffer_t *buffer, const uint8_t *source, size_t s
}
#endif
+
+/******************************************************************************/
+/* Slice queries for the Ruby API */
+/******************************************************************************/
+
+/** The category of slice returned from pm_slice_type. */
+typedef enum {
+ /** Returned when the given encoding name is invalid. */
+ PM_SLICE_TYPE_ERROR = -1,
+
+ /** Returned when no other types apply to the slice. */
+ PM_SLICE_TYPE_NONE,
+
+ /** Returned when the slice is a valid local variable name. */
+ PM_SLICE_TYPE_LOCAL,
+
+ /** Returned when the slice is a valid constant name. */
+ PM_SLICE_TYPE_CONSTANT,
+
+ /** Returned when the slice is a valid method name. */
+ PM_SLICE_TYPE_METHOD_NAME
+} pm_slice_type_t;
+
+/**
+ * Check that the slice is a valid local variable name or constant.
+ */
+pm_slice_type_t
+pm_slice_type(const uint8_t *source, size_t length, const char *encoding_name) {
+ // first, get the right encoding object
+ const pm_encoding_t *encoding = pm_encoding_find((const uint8_t *) encoding_name, (const uint8_t *) (encoding_name + strlen(encoding_name)));
+ if (encoding == NULL) return PM_SLICE_TYPE_ERROR;
+
+ // check that there is at least one character
+ if (length == 0) return PM_SLICE_TYPE_NONE;
+
+ size_t width;
+ if ((width = encoding->alpha_char(source, (ptrdiff_t) length)) != 0) {
+ // valid because alphabetical
+ } else if (*source == '_') {
+ // valid because underscore
+ width = 1;
+ } else if ((*source >= 0x80) && ((width = encoding->char_width(source, (ptrdiff_t) length)) > 0)) {
+ // valid because multibyte
+ } else {
+ // invalid because no match
+ return PM_SLICE_TYPE_NONE;
+ }
+
+ // determine the type of the slice based on the first character
+ const uint8_t *end = source + length;
+ pm_slice_type_t result = encoding->isupper_char(source, end - source) ? PM_SLICE_TYPE_CONSTANT : PM_SLICE_TYPE_LOCAL;
+
+ // next, iterate through all of the bytes of the string to ensure that they
+ // are all valid identifier characters
+ source += width;
+
+ while (source < end) {
+ if ((width = encoding->alnum_char(source, end - source)) != 0) {
+ // valid because alphanumeric
+ source += width;
+ } else if (*source == '_') {
+ // valid because underscore
+ source++;
+ } else if ((*source >= 0x80) && ((width = encoding->char_width(source, end - source)) > 0)) {
+ // valid because multibyte
+ source += width;
+ } else {
+ // invalid because no match
+ break;
+ }
+ }
+
+ // accept a ! or ? at the end of the slice as a method name
+ if (*source == '!' || *source == '?' || *source == '=') {
+ source++;
+ result = PM_SLICE_TYPE_METHOD_NAME;
+ }
+
+ // valid if we are at the end of the slice
+ return source == end ? result : PM_SLICE_TYPE_NONE;
+}
+
+/**
+ * Check that the slice is a valid local variable name.
+ */
+PRISM_EXPORTED_FUNCTION pm_string_query_t
+pm_string_query_local(const uint8_t *source, size_t length, const char *encoding_name) {
+ switch (pm_slice_type(source, length, encoding_name)) {
+ case PM_SLICE_TYPE_ERROR:
+ return PM_STRING_QUERY_ERROR;
+ case PM_SLICE_TYPE_NONE:
+ case PM_SLICE_TYPE_CONSTANT:
+ case PM_SLICE_TYPE_METHOD_NAME:
+ return PM_STRING_QUERY_FALSE;
+ case PM_SLICE_TYPE_LOCAL:
+ return PM_STRING_QUERY_TRUE;
+ }
+
+ assert(false && "unreachable");
+ return PM_STRING_QUERY_FALSE;
+}
+
+/**
+ * Check that the slice is a valid constant name.
+ */
+PRISM_EXPORTED_FUNCTION pm_string_query_t
+pm_string_query_constant(const uint8_t *source, size_t length, const char *encoding_name) {
+ switch (pm_slice_type(source, length, encoding_name)) {
+ case PM_SLICE_TYPE_ERROR:
+ return PM_STRING_QUERY_ERROR;
+ case PM_SLICE_TYPE_NONE:
+ case PM_SLICE_TYPE_LOCAL:
+ case PM_SLICE_TYPE_METHOD_NAME:
+ return PM_STRING_QUERY_FALSE;
+ case PM_SLICE_TYPE_CONSTANT:
+ return PM_STRING_QUERY_TRUE;
+ }
+
+ assert(false && "unreachable");
+ return PM_STRING_QUERY_FALSE;
+}
+
+/**
+ * Check that the slice is a valid method name.
+ */
+PRISM_EXPORTED_FUNCTION pm_string_query_t
+pm_string_query_method_name(const uint8_t *source, size_t length, const char *encoding_name) {
+#define B(p) ((p) ? PM_STRING_QUERY_TRUE : PM_STRING_QUERY_FALSE)
+#define C1(c) (*source == c)
+#define C2(s) (memcmp(source, s, 2) == 0)
+#define C3(s) (memcmp(source, s, 3) == 0)
+
+ switch (pm_slice_type(source, length, encoding_name)) {
+ case PM_SLICE_TYPE_ERROR:
+ return PM_STRING_QUERY_ERROR;
+ case PM_SLICE_TYPE_NONE:
+ break;
+ case PM_SLICE_TYPE_LOCAL:
+ // numbered parameters are not valid method names
+ return B((length != 2) || (source[0] != '_') || (source[1] == '0') || !pm_char_is_decimal_digit(source[1]));
+ case PM_SLICE_TYPE_CONSTANT:
+ // all constants are valid method names
+ case PM_SLICE_TYPE_METHOD_NAME:
+ // all method names are valid method names
+ return PM_STRING_QUERY_TRUE;
+ }
+
+ switch (length) {
+ case 1:
+ return B(C1('&') || C1('`') || C1('!') || C1('^') || C1('>') || C1('<') || C1('-') || C1('%') || C1('|') || C1('+') || C1('/') || C1('*') || C1('~'));
+ case 2:
+ return B(C2("!=") || C2("!~") || C2("[]") || C2("==") || C2("=~") || C2(">=") || C2(">>") || C2("<=") || C2("<<") || C2("**"));
+ case 3:
+ return B(C3("===") || C3("<=>") || C3("[]="));
+ default:
+ return PM_STRING_QUERY_FALSE;
+ }
+
+#undef B
+#undef C1
+#undef C2
+#undef C3
+}
diff --git a/prism/prism.h b/prism/prism.h
index 755c38fca2..c468db18be 100644
--- a/prism/prism.h
+++ b/prism/prism.h
@@ -49,10 +49,15 @@ PRISM_EXPORTED_FUNCTION const char * pm_version(void);
/**
* Initialize a parser with the given start and end pointers.
*
+ * The resulting parser must eventually be freed with `pm_parser_free()`.
+ *
* @param parser The parser to initialize.
* @param source The source to parse.
* @param size The size of the source.
- * @param options The optional options to use when parsing.
+ * @param options The optional options to use when parsing. These options must
+ * live for the whole lifetime of this parser.
+ *
+ * \public \memberof pm_parser
*/
PRISM_EXPORTED_FUNCTION void pm_parser_init(pm_parser_t *parser, const uint8_t *source, size_t size, const pm_options_t *options);
@@ -62,13 +67,20 @@ PRISM_EXPORTED_FUNCTION void pm_parser_init(pm_parser_t *parser, const uint8_t *
*
* @param parser The parser to register the callback with.
* @param callback The callback to register.
+ *
+ * \public \memberof pm_parser
*/
PRISM_EXPORTED_FUNCTION void pm_parser_register_encoding_changed_callback(pm_parser_t *parser, pm_encoding_changed_callback_t callback);
/**
* Free any memory associated with the given parser.
*
+ * This does not free the `pm_options_t` object that was used to initialize the
+ * parser.
+ *
* @param parser The parser to free.
+ *
+ * \public \memberof pm_parser
*/
PRISM_EXPORTED_FUNCTION void pm_parser_free(pm_parser_t *parser);
@@ -77,27 +89,39 @@ PRISM_EXPORTED_FUNCTION void pm_parser_free(pm_parser_t *parser);
*
* @param parser The parser to use.
* @return The AST representing the source.
+ *
+ * \public \memberof pm_parser
*/
PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse(pm_parser_t *parser);
/**
- * This function is used in pm_parse_stream to retrieve a line of input from a
+ * This function is used in pm_parse_stream() to retrieve a line of input from a
* stream. It closely mirrors that of fgets so that fgets can be used as the
* default implementation.
*/
typedef char * (pm_parse_stream_fgets_t)(char *string, int size, void *stream);
/**
+ * This function is used in pm_parse_stream to check whether a stream is EOF.
+ * It closely mirrors that of feof so that feof can be used as the
+ * default implementation.
+ */
+typedef int (pm_parse_stream_feof_t)(void *stream);
+
+/**
* Parse a stream of Ruby source and return the tree.
*
* @param parser The parser to use.
* @param buffer The buffer to use.
* @param stream The stream to parse.
- * @param fgets The function to use to read from the stream.
+ * @param stream_fgets The function to use to read from the stream.
+ * @param stream_feof The function to use to determine if the stream has hit eof.
* @param options The optional options to use when parsing.
* @return The AST representing the source.
+ *
+ * \public \memberof pm_parser
*/
-PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse_stream(pm_parser_t *parser, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *fgets, const pm_options_t *options);
+PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse_stream(pm_parser_t *parser, pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const pm_options_t *options);
// We optionally support serializing to a binary string. For systems that don't
// want or need this functionality, it can be turned off with the
@@ -110,10 +134,11 @@ PRISM_EXPORTED_FUNCTION pm_node_t * pm_parse_stream(pm_parser_t *parser, pm_buff
*
* @param buffer The buffer to serialize to.
* @param stream The stream to parse.
- * @param fgets The function to use to read from the stream.
+ * @param stream_fgets The function to use to read from the stream.
+ * @param stream_feof The function to use to tell if the stream has hit eof.
* @param data The optional data to pass to the parser.
*/
-PRISM_EXPORTED_FUNCTION void pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *fgets, const char *data);
+PRISM_EXPORTED_FUNCTION void pm_serialize_parse_stream(pm_buffer_t *buffer, void *stream, pm_parse_stream_fgets_t *stream_fgets, pm_parse_stream_feof_t *stream_feof, const char *data);
/**
* Serialize the given list of comments to the given buffer.
@@ -235,6 +260,53 @@ PRISM_EXPORTED_FUNCTION void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t
#endif
/**
+ * Represents the results of a slice query.
+ */
+typedef enum {
+ /** Returned if the encoding given to a slice query was invalid. */
+ PM_STRING_QUERY_ERROR = -1,
+
+ /** Returned if the result of the slice query is false. */
+ PM_STRING_QUERY_FALSE,
+
+ /** Returned if the result of the slice query is true. */
+ PM_STRING_QUERY_TRUE
+} pm_string_query_t;
+
+/**
+ * Check that the slice is a valid local variable name.
+ *
+ * @param source The source to check.
+ * @param length The length of the source.
+ * @param encoding_name The name of the encoding of the source.
+ * @return PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if
+ * the query is false, and PM_STRING_QUERY_ERROR if the encoding was invalid.
+ */
+PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_local(const uint8_t *source, size_t length, const char *encoding_name);
+
+/**
+ * Check that the slice is a valid constant name.
+ *
+ * @param source The source to check.
+ * @param length The length of the source.
+ * @param encoding_name The name of the encoding of the source.
+ * @return PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if
+ * the query is false, and PM_STRING_QUERY_ERROR if the encoding was invalid.
+ */
+PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_constant(const uint8_t *source, size_t length, const char *encoding_name);
+
+/**
+ * Check that the slice is a valid method name.
+ *
+ * @param source The source to check.
+ * @param length The length of the source.
+ * @param encoding_name The name of the encoding of the source.
+ * @return PM_STRING_QUERY_TRUE if the query is true, PM_STRING_QUERY_FALSE if
+ * the query is false, and PM_STRING_QUERY_ERROR if the encoding was invalid.
+ */
+PRISM_EXPORTED_FUNCTION pm_string_query_t pm_string_query_method_name(const uint8_t *source, size_t length, const char *encoding_name);
+
+/**
* @mainpage
*
* Prism is a parser for the Ruby programming language. It is designed to be
@@ -242,7 +314,7 @@ PRISM_EXPORTED_FUNCTION void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t
* dependencies. It is currently being integrated into
* [CRuby](https://github.com/ruby/ruby),
* [JRuby](https://github.com/jruby/jruby),
- * [TruffleRuby](https://github.com/oracle/truffleruby),
+ * [TruffleRuby](https://github.com/truffleruby/truffleruby),
* [Sorbet](https://github.com/sorbet/sorbet), and
* [Syntax Tree](https://github.com/ruby-syntax-tree/syntax_tree).
*
@@ -260,10 +332,10 @@ PRISM_EXPORTED_FUNCTION void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t
* to want to use and be aware of are:
*
* * `pm_parser_t` - the main parser structure
- * * `pm_parser_init` - initialize a parser
- * * `pm_parse` - parse and return the root node
- * * `pm_node_destroy` - deallocate the root node returned by `pm_parse`
- * * `pm_parser_free` - free the internal memory of the parser
+ * * `pm_parser_init()` - initialize a parser
+ * * `pm_parse()` - parse and return the root node
+ * * `pm_node_destroy()` - deallocate the root node returned by `pm_parse()`
+ * * `pm_parser_free()` - free the internal memory of the parser
*
* Putting all of this together would look something like:
*
@@ -280,8 +352,8 @@ PRISM_EXPORTED_FUNCTION void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t
* }
* ```
*
- * All of the nodes "inherit" from `pm_node_t` by embedding those structures as
- * their first member. This means you can downcast and upcast any node in the
+ * All of the nodes "inherit" from `pm_node_t` by embedding those structures
+ * as their first member. This means you can downcast and upcast any node in the
* tree to a `pm_node_t`.
*
* @section serializing Serializing
@@ -293,9 +365,9 @@ PRISM_EXPORTED_FUNCTION void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t
* use and be aware of are:
*
* * `pm_buffer_t` - a small buffer object that will hold the serialized AST
- * * `pm_buffer_free` - free the memory associated with the buffer
- * * `pm_serialize` - serialize the AST into a buffer
- * * `pm_serialize_parse` - parse and serialize the AST into a buffer
+ * * `pm_buffer_free()` - free the memory associated with the buffer
+ * * `pm_serialize()` - serialize the AST into a buffer
+ * * `pm_serialize_parse()` - parse and serialize the AST into a buffer
*
* Putting all of this together would look something like:
*
@@ -313,7 +385,7 @@ PRISM_EXPORTED_FUNCTION void pm_dump_json(pm_buffer_t *buffer, const pm_parser_t
* @section inspecting Inspecting
*
* Prism provides the ability to inspect the AST by pretty-printing nodes. You
- * can do this with the `pm_prettyprint` function, which you would use like:
+ * can do this with the `pm_prettyprint()` function, which you would use like:
*
* ```c
* void prettyprint(const uint8_t *source, size_t length) {
diff --git a/prism/regexp.c b/prism/regexp.c
index 6e0fdd295c..dcc7476244 100644
--- a/prism/regexp.c
+++ b/prism/regexp.c
@@ -1,9 +1,14 @@
#include "prism/regexp.h"
+#define PM_REGEXP_PARSE_DEPTH_MAX 4096
+
/**
* This is the parser that is going to handle parsing regular expressions.
*/
typedef struct {
+ /** The parser that is currently being used. */
+ pm_parser_t *parser;
+
/** A pointer to the start of the source that we are parsing. */
const uint8_t *start;
@@ -13,39 +18,48 @@ typedef struct {
/** A pointer to the end of the source that we are parsing. */
const uint8_t *end;
- /** A list of named captures that we've found. */
- pm_string_list_t *named_captures;
+ /**
+ * Whether or not the regular expression currently being parsed is in
+ * extended mode, wherein whitespace is ignored and comments are allowed.
+ */
+ bool extended_mode;
/** Whether the encoding has changed from the default. */
bool encoding_changed;
/** The encoding of the source. */
const pm_encoding_t *encoding;
+
+ /** The callback to call when a named capture group is found. */
+ pm_regexp_name_callback_t name_callback;
+
+ /** The data to pass to the name callback. */
+ void *name_data;
+
+ /** The callback to call when a parse error is found. */
+ pm_regexp_error_callback_t error_callback;
+
+ /** The data to pass to the error callback. */
+ void *error_data;
} pm_regexp_parser_t;
/**
- * This initializes a new parser with the given source.
+ * Append an error to the parser.
*/
-static void
-pm_regexp_parser_init(pm_regexp_parser_t *parser, const uint8_t *start, const uint8_t *end, pm_string_list_t *named_captures, bool encoding_changed, const pm_encoding_t *encoding) {
- *parser = (pm_regexp_parser_t) {
- .start = start,
- .cursor = start,
- .end = end,
- .named_captures = named_captures,
- .encoding_changed = encoding_changed,
- .encoding = encoding
- };
+static inline void
+pm_regexp_parse_error(pm_regexp_parser_t *parser, const uint8_t *start, const uint8_t *end, const char *message) {
+ parser->error_callback(start, end, message, parser->error_data);
}
/**
- * This appends a new string to the list of named captures.
+ * This appends a new string to the list of named captures. This function
+ * assumes the caller has already checked the validity of the name callback.
*/
static void
pm_regexp_parser_named_capture(pm_regexp_parser_t *parser, const uint8_t *start, const uint8_t *end) {
pm_string_t string;
pm_string_shared_init(&string, start, end);
- pm_string_list_append(parser->named_captures, &string);
+ parser->name_callback(&string, parser->name_data);
pm_string_free(&string);
}
@@ -144,6 +158,11 @@ pm_regexp_parse_range_quantifier(pm_regexp_parser_t *parser) {
} state = PM_REGEXP_RANGE_QUANTIFIER_STATE_START;
while (1) {
+ if (parser->cursor >= parser->end) {
+ parser->cursor = savepoint;
+ return true;
+ }
+
switch (state) {
case PM_REGEXP_RANGE_QUANTIFIER_STATE_START:
switch (*parser->cursor) {
@@ -217,21 +236,24 @@ pm_regexp_parse_range_quantifier(pm_regexp_parser_t *parser) {
*/
static bool
pm_regexp_parse_quantifier(pm_regexp_parser_t *parser) {
- if (pm_regexp_char_is_eof(parser)) return true;
-
- switch (*parser->cursor) {
- case '*':
- case '+':
- case '?':
- parser->cursor++;
- return true;
- case '{':
- parser->cursor++;
- return pm_regexp_parse_range_quantifier(parser);
- default:
- // In this case there is no quantifier.
- return true;
+ while (!pm_regexp_char_is_eof(parser)) {
+ switch (*parser->cursor) {
+ case '*':
+ case '+':
+ case '?':
+ parser->cursor++;
+ break;
+ case '{':
+ parser->cursor++;
+ if (!pm_regexp_parse_range_quantifier(parser)) return false;
+ break;
+ default:
+ // In this case there is no quantifier.
+ return true;
+ }
}
+
+ return true;
}
/**
@@ -255,20 +277,20 @@ pm_regexp_parse_posix_class(pm_regexp_parser_t *parser) {
// Forward declaration because character sets can be nested.
static bool
-pm_regexp_parse_lbracket(pm_regexp_parser_t *parser);
+pm_regexp_parse_lbracket(pm_regexp_parser_t *parser, uint16_t depth);
/**
* match-char-set : '[' '^'? (match-range | match-char)* ']'
* ;
*/
static bool
-pm_regexp_parse_character_set(pm_regexp_parser_t *parser) {
+pm_regexp_parse_character_set(pm_regexp_parser_t *parser, uint16_t depth) {
pm_regexp_char_accept(parser, '^');
while (!pm_regexp_char_is_eof(parser) && *parser->cursor != ']') {
switch (*parser->cursor++) {
case '[':
- pm_regexp_parse_lbracket(parser);
+ pm_regexp_parse_lbracket(parser, (uint16_t) (depth + 1));
break;
case '\\':
if (!pm_regexp_char_is_eof(parser)) {
@@ -288,7 +310,18 @@ pm_regexp_parse_character_set(pm_regexp_parser_t *parser) {
* A left bracket can either mean a POSIX class or a character set.
*/
static bool
-pm_regexp_parse_lbracket(pm_regexp_parser_t *parser) {
+pm_regexp_parse_lbracket(pm_regexp_parser_t *parser, uint16_t depth) {
+ if (depth >= PM_REGEXP_PARSE_DEPTH_MAX) {
+ pm_regexp_parse_error(parser, parser->start, parser->end, "parse depth limit over");
+ return false;
+ }
+
+ if ((parser->cursor < parser->end) && parser->cursor[0] == ']') {
+ parser->cursor++;
+ pm_regexp_parse_error(parser, parser->cursor - 1, parser->cursor, "empty char-class");
+ return true;
+ }
+
const uint8_t *reset = parser->cursor;
if ((parser->cursor + 2 < parser->end) && parser->cursor[0] == '[' && parser->cursor[1] == ':') {
@@ -298,13 +331,13 @@ pm_regexp_parse_lbracket(pm_regexp_parser_t *parser) {
parser->cursor = reset;
}
- return pm_regexp_parse_character_set(parser);
+ return pm_regexp_parse_character_set(parser, depth);
}
// Forward declaration here since parsing groups needs to go back up the grammar
// to parse expressions within them.
static bool
-pm_regexp_parse_expression(pm_regexp_parser_t *parser);
+pm_regexp_parse_expression(pm_regexp_parser_t *parser, uint16_t depth);
/**
* These are the states of the options that are configurable on the regular
@@ -397,6 +430,19 @@ pm_regexp_options_remove(pm_regexp_options_t *options, uint8_t key) {
}
/**
+ * True if the given key is set in the options.
+ */
+static uint8_t
+pm_regexp_options_state(pm_regexp_options_t *options, uint8_t key) {
+ if (key >= PRISM_REGEXP_OPTION_STATE_SLOT_MINIMUM && key <= PRISM_REGEXP_OPTION_STATE_SLOT_MAXIMUM) {
+ key = (uint8_t) (key - PRISM_REGEXP_OPTION_STATE_SLOT_MINIMUM);
+ return options->values[key];
+ }
+
+ return false;
+}
+
+/**
* Groups can have quite a few different patterns for syntax. They basically
* just wrap a set of expressions, but they can potentially have options after a
* question mark. If there _isn't_ a question mark, then it's just a set of
@@ -418,17 +464,27 @@ pm_regexp_options_remove(pm_regexp_options_t *options, uint8_t key) {
* * (?imxdau-imx:subexp) - turn on and off configuration for an expression
*/
static bool
-pm_regexp_parse_group(pm_regexp_parser_t *parser) {
+pm_regexp_parse_group(pm_regexp_parser_t *parser, uint16_t depth) {
+ const uint8_t *group_start = parser->cursor;
+
+ pm_regexp_options_t options;
+ pm_regexp_options_init(&options);
+
// First, parse any options for the group.
if (pm_regexp_char_accept(parser, '?')) {
if (pm_regexp_char_is_eof(parser)) {
+ pm_regexp_parse_error(parser, group_start, parser->cursor, "end pattern in group");
return false;
}
- pm_regexp_options_t options;
- pm_regexp_options_init(&options);
switch (*parser->cursor) {
case '#': { // inline comments
+ parser->cursor++;
+ if (pm_regexp_char_is_eof(parser)) {
+ pm_regexp_parse_error(parser, group_start, parser->cursor, "end pattern in group");
+ return false;
+ }
+
if (parser->encoding_changed && parser->encoding->multibyte) {
bool escaped = false;
@@ -472,6 +528,7 @@ pm_regexp_parse_group(pm_regexp_parser_t *parser) {
case '<':
parser->cursor++;
if (pm_regexp_char_is_eof(parser)) {
+ pm_regexp_parse_error(parser, group_start, parser->cursor, "end pattern with unmatched parenthesis");
return false;
}
@@ -485,7 +542,15 @@ pm_regexp_parse_group(pm_regexp_parser_t *parser) {
if (!pm_regexp_char_find(parser, '>')) {
return false;
}
- pm_regexp_parser_named_capture(parser, start, parser->cursor - 1);
+
+ if (parser->cursor - start == 1) {
+ pm_regexp_parse_error(parser, start, parser->cursor, "group name is empty");
+ }
+
+ if (parser->name_callback != NULL) {
+ pm_regexp_parser_named_capture(parser, start, parser->cursor - 1);
+ }
+
break;
}
}
@@ -496,7 +561,10 @@ pm_regexp_parse_group(pm_regexp_parser_t *parser) {
return false;
}
- pm_regexp_parser_named_capture(parser, start, parser->cursor - 1);
+ if (parser->name_callback != NULL) {
+ pm_regexp_parser_named_capture(parser, start, parser->cursor - 1);
+ }
+
break;
}
case '(': // conditional expression
@@ -516,11 +584,22 @@ pm_regexp_parse_group(pm_regexp_parser_t *parser) {
return false;
}
+ // If we are at the end of the group of options and there is no
+ // subexpression, then we are going to be setting the options
+ // for the parent group. In this case we are safe to return now.
+ if (*parser->cursor == ')') {
+ if (pm_regexp_options_state(&options, 'x') == PM_REGEXP_OPTION_STATE_ADDED) {
+ parser->extended_mode = true;
+ }
+
+ parser->cursor++;
+ return true;
+ }
+
// If we hit a -, then we're done parsing options.
if (*parser->cursor != '-') break;
- // Otherwise, fallthrough to the - case.
- /* fallthrough */
+ PRISM_FALLTHROUGH
case '-':
parser->cursor++;
while (!pm_regexp_char_is_eof(parser) && *parser->cursor != ':' && *parser->cursor != ')') {
@@ -533,22 +612,57 @@ pm_regexp_parse_group(pm_regexp_parser_t *parser) {
if (pm_regexp_char_is_eof(parser)) {
return false;
}
+
+ // If we are at the end of the group of options and there is no
+ // subexpression, then we are going to be setting the options
+ // for the parent group. In this case we are safe to return now.
+ if (*parser->cursor == ')') {
+ switch (pm_regexp_options_state(&options, 'x')) {
+ case PM_REGEXP_OPTION_STATE_ADDED:
+ parser->extended_mode = true;
+ break;
+ case PM_REGEXP_OPTION_STATE_REMOVED:
+ parser->extended_mode = false;
+ break;
+ }
+
+ parser->cursor++;
+ return true;
+ }
+
break;
default:
- return false;
+ parser->cursor++;
+ pm_regexp_parse_error(parser, parser->cursor - 1, parser->cursor, "undefined group option");
+ break;
}
}
+ bool extended_mode = parser->extended_mode;
+ switch (pm_regexp_options_state(&options, 'x')) {
+ case PM_REGEXP_OPTION_STATE_ADDED:
+ parser->extended_mode = true;
+ break;
+ case PM_REGEXP_OPTION_STATE_REMOVED:
+ parser->extended_mode = false;
+ break;
+ }
+
// Now, parse the expressions within this group.
while (!pm_regexp_char_is_eof(parser) && *parser->cursor != ')') {
- if (!pm_regexp_parse_expression(parser)) {
+ if (!pm_regexp_parse_expression(parser, (uint16_t) (depth + 1))) {
+ parser->extended_mode = extended_mode;
return false;
}
pm_regexp_char_accept(parser, '|');
}
// Finally, make sure we have a closing parenthesis.
- return pm_regexp_char_expect(parser, ')');
+ parser->extended_mode = extended_mode;
+ if (pm_regexp_char_expect(parser, ')')) return true;
+
+ pm_regexp_parse_error(parser, group_start, parser->cursor, "end pattern with unmatched parenthesis");
+ return false;
}
/**
@@ -564,12 +678,12 @@ pm_regexp_parse_group(pm_regexp_parser_t *parser) {
* ;
*/
static bool
-pm_regexp_parse_item(pm_regexp_parser_t *parser) {
+pm_regexp_parse_item(pm_regexp_parser_t *parser, uint16_t depth) {
switch (*parser->cursor) {
case '^':
case '$':
parser->cursor++;
- return true;
+ return pm_regexp_parse_quantifier(parser);
case '\\':
parser->cursor++;
if (!pm_regexp_char_is_eof(parser)) {
@@ -578,10 +692,26 @@ pm_regexp_parse_item(pm_regexp_parser_t *parser) {
return pm_regexp_parse_quantifier(parser);
case '(':
parser->cursor++;
- return pm_regexp_parse_group(parser) && pm_regexp_parse_quantifier(parser);
+ return pm_regexp_parse_group(parser, depth) && pm_regexp_parse_quantifier(parser);
case '[':
parser->cursor++;
- return pm_regexp_parse_lbracket(parser) && pm_regexp_parse_quantifier(parser);
+ return pm_regexp_parse_lbracket(parser, depth) && pm_regexp_parse_quantifier(parser);
+ case '*':
+ case '?':
+ case '+':
+ parser->cursor++;
+ pm_regexp_parse_error(parser, parser->cursor - 1, parser->cursor, "target of repeat operator is not specified");
+ return true;
+ case ')':
+ parser->cursor++;
+ pm_regexp_parse_error(parser, parser->cursor - 1, parser->cursor, "unmatched close parenthesis");
+ return true;
+ case '#':
+ if (parser->extended_mode) {
+ if (!pm_regexp_char_find(parser, '\n')) parser->cursor = parser->end;
+ return true;
+ }
+ PRISM_FALLTHROUGH
default: {
size_t width;
if (!parser->encoding_changed) {
@@ -603,13 +733,18 @@ pm_regexp_parse_item(pm_regexp_parser_t *parser) {
* ;
*/
static bool
-pm_regexp_parse_expression(pm_regexp_parser_t *parser) {
- if (!pm_regexp_parse_item(parser)) {
+pm_regexp_parse_expression(pm_regexp_parser_t *parser, uint16_t depth) {
+ if (depth >= PM_REGEXP_PARSE_DEPTH_MAX) {
+ pm_regexp_parse_error(parser, parser->start, parser->end, "parse depth limit over");
+ return false;
+ }
+
+ if (!pm_regexp_parse_item(parser, depth)) {
return false;
}
while (!pm_regexp_char_is_eof(parser) && *parser->cursor != ')' && *parser->cursor != '|') {
- if (!pm_regexp_parse_item(parser)) {
+ if (!pm_regexp_parse_item(parser, depth)) {
return false;
}
}
@@ -625,29 +760,31 @@ pm_regexp_parse_expression(pm_regexp_parser_t *parser) {
*/
static bool
pm_regexp_parse_pattern(pm_regexp_parser_t *parser) {
- return (
- (
- // Exit early if the pattern is empty.
- pm_regexp_char_is_eof(parser) ||
- // Parse the first expression in the pattern.
- pm_regexp_parse_expression(parser)
- ) &&
- (
- // Return now if we've parsed the entire pattern.
- pm_regexp_char_is_eof(parser) ||
- // Otherwise, we should have a pipe character.
- (pm_regexp_char_expect(parser, '|') && pm_regexp_parse_pattern(parser))
- )
- );
+ do {
+ if (pm_regexp_char_is_eof(parser)) return true;
+ if (!pm_regexp_parse_expression(parser, 0)) return false;
+ } while (pm_regexp_char_accept(parser, '|'));
+
+ return pm_regexp_char_is_eof(parser);
}
/**
* Parse a regular expression and extract the names of all of the named capture
* groups.
*/
-PRISM_EXPORTED_FUNCTION bool
-pm_regexp_named_capture_group_names(const uint8_t *source, size_t size, pm_string_list_t *named_captures, bool encoding_changed, const pm_encoding_t *encoding) {
- pm_regexp_parser_t parser;
- pm_regexp_parser_init(&parser, source, source + size, named_captures, encoding_changed, encoding);
- return pm_regexp_parse_pattern(&parser);
+PRISM_EXPORTED_FUNCTION void
+pm_regexp_parse(pm_parser_t *parser, const uint8_t *source, size_t size, bool extended_mode, pm_regexp_name_callback_t name_callback, void *name_data, pm_regexp_error_callback_t error_callback, void *error_data) {
+ pm_regexp_parse_pattern(&(pm_regexp_parser_t) {
+ .parser = parser,
+ .start = source,
+ .cursor = source,
+ .end = source + size,
+ .extended_mode = extended_mode,
+ .encoding_changed = parser->encoding_changed,
+ .encoding = parser->encoding,
+ .name_callback = name_callback,
+ .name_data = name_data,
+ .error_callback = error_callback,
+ .error_data = error_data
+ });
}
diff --git a/prism/regexp.h b/prism/regexp.h
index c5ceab11f9..5366b5a5a0 100644
--- a/prism/regexp.h
+++ b/prism/regexp.h
@@ -10,7 +10,6 @@
#include "prism/parser.h"
#include "prism/encoding.h"
#include "prism/util/pm_memchr.h"
-#include "prism/util/pm_string_list.h"
#include "prism/util/pm_string.h"
#include <stdbool.h>
@@ -18,16 +17,27 @@
#include <string.h>
/**
- * Parse a regular expression and extract the names of all of the named capture
- * groups.
+ * This callback is called by pm_regexp_parse() when a named capture group is found.
+ */
+typedef void (*pm_regexp_name_callback_t)(const pm_string_t *name, void *data);
+
+/**
+ * This callback is called by pm_regexp_parse() when a parse error is found.
+ */
+typedef void (*pm_regexp_error_callback_t)(const uint8_t *start, const uint8_t *end, const char *message, void *data);
+
+/**
+ * Parse a regular expression.
*
+ * @param parser The parser that is currently being used.
* @param source The source code to parse.
* @param size The size of the source code.
- * @param named_captures The list to add the names of the named capture groups.
- * @param encoding_changed Whether or not the encoding changed from the default.
- * @param encoding The encoding of the source code.
- * @return Whether or not the parsing was successful.
+ * @param extended_mode Whether to parse the regular expression in extended mode.
+ * @param name_callback The optional callback to call when a named capture group is found.
+ * @param name_data The optional data to pass to the name callback.
+ * @param error_callback The callback to call when a parse error is found.
+ * @param error_data The data to pass to the error callback.
*/
-PRISM_EXPORTED_FUNCTION bool pm_regexp_named_capture_group_names(const uint8_t *source, size_t size, pm_string_list_t *named_captures, bool encoding_changed, const pm_encoding_t *encoding);
+PRISM_EXPORTED_FUNCTION void pm_regexp_parse(pm_parser_t *parser, const uint8_t *source, size_t size, bool extended_mode, pm_regexp_name_callback_t name_callback, void *name_data, pm_regexp_error_callback_t error_callback, void *error_data);
#endif
diff --git a/prism/srcs.mk b/prism/srcs.mk
new file mode 100644
index 0000000000..022662a00b
--- /dev/null
+++ b/prism/srcs.mk
@@ -0,0 +1,150 @@
+PRISM_TEMPLATES_DIR = $(PRISM_SRCDIR)/templates
+PRISM_TEMPLATE = $(PRISM_TEMPLATES_DIR)/template.rb
+PRISM_CONFIG = $(PRISM_SRCDIR)/config.yml
+
+srcs uncommon.mk: prism/.srcs.mk.time
+
+prism/.srcs.mk.time: $(order_only) $(PRISM_BUILD_DIR)/.time
+prism/$(HAVE_BASERUBY:no=.srcs.mk.time):
+ touch $@
+prism/$(HAVE_BASERUBY:yes=.srcs.mk.time): \
+ $(PRISM_SRCDIR)/templates/template.rb \
+ $(PRISM_SRCDIR)/srcs.mk.in
+ $(BASERUBY) $(tooldir)/generic_erb.rb -c -t$@ -o $(PRISM_SRCDIR)/srcs.mk $(PRISM_SRCDIR)/srcs.mk.in
+
+distclean-prism-srcs::
+ $(RM) prism/.srcs.mk.time
+ $(RMDIRS) prism || $(NULLCMD)
+
+distclean-srcs-local:: distclean-prism-srcs
+
+realclean-prism-srcs:: distclean-prism-srcs
+ $(RM) $(PRISM_SRCDIR)/srcs.mk
+
+realclean-srcs-local:: realclean-prism-srcs
+
+main srcs: $(srcdir)/prism/api_node.c
+$(srcdir)/prism/api_node.c: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/ext/prism/api_node.c.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) ext/prism/api_node.c $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/prism/api_node.c
+
+main incs: $(srcdir)/prism/ast.h
+$(srcdir)/prism/ast.h: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/include/prism/ast.h.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) include/prism/ast.h $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/prism/ast.h
+
+main incs: $(srcdir)/prism/diagnostic.h
+$(srcdir)/prism/diagnostic.h: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/include/prism/diagnostic.h.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) include/prism/diagnostic.h $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/prism/diagnostic.h
+
+main srcs: $(srcdir)/lib/prism/compiler.rb
+$(srcdir)/lib/prism/compiler.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/compiler.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/compiler.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/compiler.rb
+
+main srcs: $(srcdir)/lib/prism/dispatcher.rb
+$(srcdir)/lib/prism/dispatcher.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/dispatcher.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/dispatcher.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/dispatcher.rb
+
+main srcs: $(srcdir)/lib/prism/dot_visitor.rb
+$(srcdir)/lib/prism/dot_visitor.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/dot_visitor.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/dot_visitor.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/dot_visitor.rb
+
+main srcs: $(srcdir)/lib/prism/dsl.rb
+$(srcdir)/lib/prism/dsl.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/dsl.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/dsl.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/dsl.rb
+
+main srcs: $(srcdir)/lib/prism/inspect_visitor.rb
+$(srcdir)/lib/prism/inspect_visitor.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/inspect_visitor.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/inspect_visitor.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/inspect_visitor.rb
+
+main srcs: $(srcdir)/lib/prism/mutation_compiler.rb
+$(srcdir)/lib/prism/mutation_compiler.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/mutation_compiler.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/mutation_compiler.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/mutation_compiler.rb
+
+main srcs: $(srcdir)/lib/prism/node.rb
+$(srcdir)/lib/prism/node.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/node.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/node.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/node.rb
+
+main srcs: $(srcdir)/lib/prism/reflection.rb
+$(srcdir)/lib/prism/reflection.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/reflection.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/reflection.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/reflection.rb
+
+main srcs: $(srcdir)/lib/prism/serialize.rb
+$(srcdir)/lib/prism/serialize.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/serialize.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/serialize.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/serialize.rb
+
+main srcs: $(srcdir)/lib/prism/visitor.rb
+$(srcdir)/lib/prism/visitor.rb: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/lib/prism/visitor.rb.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) lib/prism/visitor.rb $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/lib/prism/visitor.rb
+
+main srcs: $(srcdir)/prism/diagnostic.c
+$(srcdir)/prism/diagnostic.c: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/src/diagnostic.c.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) src/diagnostic.c $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/prism/diagnostic.c
+
+main srcs: $(srcdir)/prism/node.c
+$(srcdir)/prism/node.c: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/src/node.c.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) src/node.c $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/prism/node.c
+
+main srcs: $(srcdir)/prism/prettyprint.c
+$(srcdir)/prism/prettyprint.c: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/src/prettyprint.c.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) src/prettyprint.c $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/prism/prettyprint.c
+
+main srcs: $(srcdir)/prism/serialize.c
+$(srcdir)/prism/serialize.c: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/src/serialize.c.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) src/serialize.c $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/prism/serialize.c
+
+main srcs: $(srcdir)/prism/token_type.c
+$(srcdir)/prism/token_type.c: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/src/token_type.c.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) src/token_type.c $@
+
+realclean-prism-srcs::
+ $(RM) $(srcdir)/prism/token_type.c
diff --git a/prism/srcs.mk.in b/prism/srcs.mk.in
new file mode 100644
index 0000000000..cc263fd1b4
--- /dev/null
+++ b/prism/srcs.mk.in
@@ -0,0 +1,48 @@
+<% # -*- ruby -*-
+require_relative 'templates/template'
+
+script = File.basename(__FILE__)
+srcs = output ? File.basename(output) : script.chomp('.in')
+mk = 'uncommon.mk'
+
+# %>
+PRISM_TEMPLATES_DIR = $(PRISM_SRCDIR)/templates
+PRISM_TEMPLATE = $(PRISM_TEMPLATES_DIR)/template.rb
+PRISM_CONFIG = $(PRISM_SRCDIR)/config.yml
+
+srcs <%=%><%=mk%>: prism/.srcs.mk.time
+
+prism/.srcs.mk.time: $(order_only) $(PRISM_BUILD_DIR)/.time
+prism/$(HAVE_BASERUBY:no=.srcs.mk.time):
+ touch $@
+prism/$(HAVE_BASERUBY:yes=.srcs.mk.time): \
+ $(PRISM_SRCDIR)/templates/template.rb \
+ $(PRISM_SRCDIR)/<%=%><%=script%>
+ $(BASERUBY) $(tooldir)/generic_erb.rb -c -t$@ -o $(PRISM_SRCDIR)/<%=%><%=srcs%> $(PRISM_SRCDIR)/<%=%><%=script%>
+
+distclean-prism-srcs::
+ $(RM) prism/.srcs.mk.time
+ $(RMDIRS) prism || $(NULLCMD)
+
+distclean-srcs-local:: distclean-prism-srcs
+
+realclean-prism-srcs:: distclean-prism-srcs
+ $(RM) $(PRISM_SRCDIR)/<%=%><%=srcs%>
+
+realclean-srcs-local:: realclean-prism-srcs
+<% Prism::Template::TEMPLATES.map do |t|
+ /\.(?:[ch]|rb)\z/ =~ t or next
+ s = '$(srcdir)/' + t.sub(%r[\A(?:(src)|ext|include)/]) {$1 && 'prism/'}
+ s.sub!(%r[\A\$(srcdir)/prism/], '$(PRISM_SRCDIR)/')
+ target = s.end_with?('.h') ? 'incs' : 'srcs'
+# %>
+
+main <%=%><%=target%>: <%=%><%=s%>
+<%=%><%=s%>: $(PRISM_CONFIG) $(PRISM_TEMPLATE) $(PRISM_TEMPLATES_DIR)/<%=%><%=t%>.erb
+ $(Q) $(BASERUBY) $(PRISM_TEMPLATE) <%=%><%=t%> $@
+
+realclean-prism-srcs::
+ $(RM) <%=%><%=s%>
+<%
+end
+# %>
diff --git a/prism/static_literals.c b/prism/static_literals.c
index b8604321c9..9fa37b999a 100644
--- a/prism/static_literals.c
+++ b/prism/static_literals.c
@@ -501,7 +501,7 @@ pm_static_literal_inspect_node(pm_buffer_t *buffer, const pm_static_literals_met
case PM_FLOAT_NODE: {
const double value = ((const pm_float_node_t *) node)->value;
- if (isinf(value)) {
+ if (PRISM_ISINF(value)) {
if (*node->location.start == '-') {
pm_buffer_append_byte(buffer, '-');
}
diff --git a/prism/templates/ext/prism/api_node.c.erb b/prism/templates/ext/prism/api_node.c.erb
index 0e3e4d63cc..23af8886a7 100644
--- a/prism/templates/ext/prism/api_node.c.erb
+++ b/prism/templates/ext/prism/api_node.c.erb
@@ -1,4 +1,4 @@
-#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>"
+#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
#include "prism/extension.h"
extern VALUE rb_cPrism;
@@ -12,29 +12,39 @@ static VALUE rb_cPrism<%= node.name %>;
<%- end -%>
static VALUE
-pm_location_new(const pm_parser_t *parser, const uint8_t *start, const uint8_t *end) {
- uint64_t value = ((((uint64_t) (start - parser->start)) << 32) | ((uint32_t) (end - start)));
- return ULL2NUM(value);
+pm_location_new(const pm_parser_t *parser, const uint8_t *start, const uint8_t *end, VALUE source, bool freeze) {
+ if (freeze) {
+ VALUE location_argv[] = {
+ source,
+ LONG2FIX(start - parser->start),
+ LONG2FIX(end - start)
+ };
+
+ return rb_obj_freeze(rb_class_new_instance(3, location_argv, rb_cPrismLocation));
+ } else {
+ uint64_t value = ((((uint64_t) (start - parser->start)) << 32) | ((uint32_t) (end - start)));
+ return ULL2NUM(value);
+ }
}
VALUE
-pm_token_new(const pm_parser_t *parser, const pm_token_t *token, rb_encoding *encoding, VALUE source) {
+pm_token_new(const pm_parser_t *parser, const pm_token_t *token, rb_encoding *encoding, VALUE source, bool freeze) {
ID type = rb_intern(pm_token_type_name(token->type));
- VALUE location = pm_location_new(parser, token->start, token->end);
+ VALUE location = pm_location_new(parser, token->start, token->end, source, freeze);
+
+ VALUE slice = rb_enc_str_new((const char *) token->start, token->end - token->start, encoding);
+ if (freeze) rb_obj_freeze(slice);
- VALUE argv[] = {
- source,
- ID2SYM(type),
- rb_enc_str_new((const char *) token->start, token->end - token->start, encoding),
- location
- };
+ VALUE argv[] = { source, ID2SYM(type), slice, location };
+ VALUE value = rb_class_new_instance(4, argv, rb_cPrismToken);
+ if (freeze) rb_obj_freeze(value);
- return rb_class_new_instance(4, argv, rb_cPrismToken);
+ return value;
}
static VALUE
pm_string_new(const pm_string_t *string, rb_encoding *encoding) {
- return rb_enc_str_new((const char *) pm_string_source(string), pm_string_length(string), encoding);
+ return rb_obj_freeze(rb_enc_str_new((const char *) pm_string_source(string), pm_string_length(string), encoding));
}
VALUE
@@ -68,7 +78,7 @@ pm_integer_new(const pm_integer_t *integer) {
// Create a Prism::Source object from the given parser, after pm_parse() was called.
VALUE
-pm_source_new(const pm_parser_t *parser, rb_encoding *encoding) {
+pm_source_new(const pm_parser_t *parser, rb_encoding *encoding, bool freeze) {
VALUE source_string = rb_enc_str_new((const char *) parser->start, parser->end - parser->start, encoding);
VALUE offsets = rb_ary_new_capa(parser->newline_list.size);
@@ -76,7 +86,15 @@ pm_source_new(const pm_parser_t *parser, rb_encoding *encoding) {
rb_ary_push(offsets, ULONG2NUM(parser->newline_list.offsets[index]));
}
- return rb_funcall(rb_cPrismSource, rb_intern("for"), 3, source_string, LONG2NUM(parser->start_line), offsets);
+ if (freeze) {
+ rb_obj_freeze(source_string);
+ rb_obj_freeze(offsets);
+ }
+
+ VALUE source = rb_funcall(rb_cPrismSource, rb_intern("for"), 3, source_string, LONG2NUM(parser->start_line), offsets);
+ if (freeze) rb_obj_freeze(source);
+
+ return source;
}
typedef struct pm_node_stack_node {
@@ -106,7 +124,7 @@ pm_node_stack_pop(pm_node_stack_node_t **stack) {
}
VALUE
-pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encoding, VALUE source) {
+pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encoding, VALUE source, bool freeze) {
VALUE constants = rb_ary_new_capa(parser->constant_pool.size);
for (uint32_t index = 0; index < parser->constant_pool.size; index++) {
@@ -142,7 +160,7 @@ pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encodi
switch (PM_NODE_TYPE(node)) {
<%- nodes.each do |node| -%>
<%- if node.fields.any? { |field| [Prism::Template::NodeField, Prism::Template::OptionalNodeField, Prism::Template::NodeListField].include?(field.class) } -%>
-#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>"
+#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
case <%= node.type %>: {
pm_<%= node.human %>_t *cast = (pm_<%= node.human %>_t *) node;
<%- node.fields.each do |field| -%>
@@ -162,80 +180,88 @@ pm_ast_new(const pm_parser_t *parser, const pm_node_t *node, rb_encoding *encodi
default:
break;
}
-#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>"
+#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
} else {
const pm_node_t *node = pm_node_stack_pop(&node_stack);
switch (PM_NODE_TYPE(node)) {
<%- nodes.each do |node| -%>
-#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>"
+#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
case <%= node.type %>: {
- <%- if node.fields.any? { |field| ![Prism::Template::NodeField, Prism::Template::OptionalNodeField, Prism::Template::FlagsField].include?(field.class) } -%>
+ <%- if node.fields.any? { |field| ![Prism::Template::NodeField, Prism::Template::OptionalNodeField].include?(field.class) } -%>
pm_<%= node.human %>_t *cast = (pm_<%= node.human %>_t *) node;
<%- end -%>
- VALUE argv[<%= node.fields.length + 2 %>];
+ VALUE argv[<%= node.fields.length + 4 %>];
// source
argv[0] = source;
- <%- node.fields.each.with_index(1) do |field, index| -%>
+
+ // node_id
+ argv[1] = ULONG2NUM(node->node_id);
+
+ // location
+ argv[2] = pm_location_new(parser, node->location.start, node->location.end, source, freeze);
+
+ // flags
+ argv[3] = ULONG2NUM(node->flags);
+ <%- node.fields.each.with_index(4) do |field, index| -%>
// <%= field.name %>
<%- case field -%>
<%- when Prism::Template::NodeField, Prism::Template::OptionalNodeField -%>
-#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>"
+#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
argv[<%= index %>] = rb_ary_pop(value_stack);
<%- when Prism::Template::NodeListField -%>
-#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>"
+#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
argv[<%= index %>] = rb_ary_new_capa(cast-><%= field.name %>.size);
for (size_t index = 0; index < cast-><%= field.name %>.size; index++) {
rb_ary_push(argv[<%= index %>], rb_ary_pop(value_stack));
}
+ if (freeze) rb_obj_freeze(argv[<%= index %>]);
<%- when Prism::Template::StringField -%>
-#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>"
+#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
argv[<%= index %>] = pm_string_new(&cast-><%= field.name %>, encoding);
<%- when Prism::Template::ConstantField -%>
-#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>"
+#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
assert(cast-><%= field.name %> != 0);
argv[<%= index %>] = RARRAY_AREF(constants, cast-><%= field.name %> - 1);
<%- when Prism::Template::OptionalConstantField -%>
argv[<%= index %>] = cast-><%= field.name %> == 0 ? Qnil : RARRAY_AREF(constants, cast-><%= field.name %> - 1);
<%- when Prism::Template::ConstantListField -%>
-#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>"
+#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
argv[<%= index %>] = rb_ary_new_capa(cast-><%= field.name %>.size);
for (size_t index = 0; index < cast-><%= field.name %>.size; index++) {
assert(cast-><%= field.name %>.ids[index] != 0);
rb_ary_push(argv[<%= index %>], RARRAY_AREF(constants, cast-><%= field.name %>.ids[index] - 1));
}
+ if (freeze) rb_obj_freeze(argv[<%= index %>]);
<%- when Prism::Template::LocationField -%>
-#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>"
- argv[<%= index %>] = pm_location_new(parser, cast-><%= field.name %>.start, cast-><%= field.name %>.end);
+#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
+ argv[<%= index %>] = pm_location_new(parser, cast-><%= field.name %>.start, cast-><%= field.name %>.end, source, freeze);
<%- when Prism::Template::OptionalLocationField -%>
-#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>"
- argv[<%= index %>] = cast-><%= field.name %>.start == NULL ? Qnil : pm_location_new(parser, cast-><%= field.name %>.start, cast-><%= field.name %>.end);
+#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
+ argv[<%= index %>] = cast-><%= field.name %>.start == NULL ? Qnil : pm_location_new(parser, cast-><%= field.name %>.start, cast-><%= field.name %>.end, source, freeze);
<%- when Prism::Template::UInt8Field -%>
-#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>"
+#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
argv[<%= index %>] = UINT2NUM(cast-><%= field.name %>);
<%- when Prism::Template::UInt32Field -%>
-#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>"
+#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
argv[<%= index %>] = ULONG2NUM(cast-><%= field.name %>);
- <%- when Prism::Template::FlagsField -%>
-#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>"
- argv[<%= index %>] = ULONG2NUM(node->flags & ~PM_NODE_FLAG_COMMON_MASK);
<%- when Prism::Template::IntegerField -%>
-#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>"
+#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
argv[<%= index %>] = pm_integer_new(&cast-><%= field.name %>);
<%- when Prism::Template::DoubleField -%>
-#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>"
+#line <%= __LINE__ + 1 %> "prism/templates/ext/prism/<%= File.basename(__FILE__) %>"
argv[<%= index %>] = DBL2NUM(cast-><%= field.name %>);
<%- else -%>
<%- raise -%>
<%- end -%>
<%- end -%>
- // location
- argv[<%= node.fields.length + 1 %>] = pm_location_new(parser, node->location.start, node->location.end);
+ VALUE value = rb_class_new_instance(<%= node.fields.length + 4 %>, argv, rb_cPrism<%= node.name %>);
+ if (freeze) rb_obj_freeze(value);
- rb_ary_push(value_stack, rb_class_new_instance(<%= node.fields.length + 2 %>, argv, rb_cPrism<%= node.name %>));
+ rb_ary_push(value_stack, value);
break;
}
<%- end -%>
diff --git a/prism/templates/include/prism/ast.h.erb b/prism/templates/include/prism/ast.h.erb
index 0fe7905e40..790cf9ebb8 100644
--- a/prism/templates/include/prism/ast.h.erb
+++ b/prism/templates/include/prism/ast.h.erb
@@ -2,6 +2,8 @@
* @file ast.h
*
* The abstract syntax tree.
+ *
+ * --
*/
#ifndef PRISM_AST_H
#define PRISM_AST_H
@@ -100,27 +102,8 @@ typedef uint16_t pm_node_flags_t;
* We store the flags enum in every node in the tree. Some flags are common to
* all nodes (the ones listed below). Others are specific to certain node types.
*/
-#define PM_NODE_FLAG_BITS (sizeof(pm_node_flags_t) * 8)
-
-static const pm_node_flags_t PM_NODE_FLAG_NEWLINE = (1 << (PM_NODE_FLAG_BITS - 1));
-static const pm_node_flags_t PM_NODE_FLAG_STATIC_LITERAL = (1 << (PM_NODE_FLAG_BITS - 2));
-static const pm_node_flags_t PM_NODE_FLAG_COMMON_MASK = (1 << (PM_NODE_FLAG_BITS - 1)) | (1 << (PM_NODE_FLAG_BITS - 2));
-
-/**
- * Cast the type to an enum to allow the compiler to provide exhaustiveness
- * checking.
- */
-#define PM_NODE_TYPE(node) ((enum pm_node_type) (node)->type)
-
-/**
- * Return true if the type of the given node matches the given type.
- */
-#define PM_NODE_TYPE_P(node, type) (PM_NODE_TYPE(node) == (type))
-
-/**
- * Return true if the given flag is set on the given node.
- */
-#define PM_NODE_FLAG_P(node, flag) ((((pm_node_t *)(node))->flags & (flag)) != 0)
+static const pm_node_flags_t PM_NODE_FLAG_NEWLINE = 0x1;
+static const pm_node_flags_t PM_NODE_FLAG_STATIC_LITERAL = 0x2;
/**
* This is the base structure that represents a node in the syntax tree. It is
@@ -140,22 +123,57 @@ typedef struct pm_node {
pm_node_flags_t flags;
/**
+ * The unique identifier for this node, which is deterministic based on the
+ * source. It is used to identify unique nodes across parses.
+ */
+ uint32_t node_id;
+
+ /**
* This is the location of the node in the source. It's a range of bytes
* containing a start and an end.
*/
pm_location_t location;
} pm_node_t;
+
+/**
+ * Cast the given node to the base pm_node_t type.
+ */
+#define PM_NODE_UPCAST(node_) ((pm_node_t *) (node_))
+
+/**
+ * Cast the type to an enum to allow the compiler to provide exhaustiveness
+ * checking.
+ */
+#define PM_NODE_TYPE(node_) ((enum pm_node_type) (node_)->type)
+
+/**
+ * Return true if the type of the given node matches the given type.
+ */
+#define PM_NODE_TYPE_P(node_, type_) (PM_NODE_TYPE(node_) == (type_))
+
+/**
+ * Return the flags associated with the given node.
+ */
+#define PM_NODE_FLAGS(node_) (PM_NODE_UPCAST(node_)->flags)
+
+/**
+ * Return true if the given flag is set on the given node.
+ */
+#define PM_NODE_FLAG_P(node_, flag_) ((PM_NODE_FLAGS(node_) & (flag_)) != 0)
<%- nodes.each do |node| -%>
/**
* <%= node.name %>
*
- * Type: <%= node.type %>
-<%- if (node_flags = node.fields.find { |field| field.is_a? Prism::Template::FlagsField }) -%>
- * Flags:
-<%- found = flags.find { |flag| flag.name == node_flags.kind }.tap { |found| raise "Expected to find #{field.kind}" unless found } -%>
-<%- found.values.each do |value| -%>
- * PM_<%= found.human.upcase %>_<%= value.name %>
+<%- node.each_comment_line do |line| -%>
+ *<%= line %>
+<%- end -%>
+ *
+ * Type: ::<%= node.type %>
+<% if (node_flags = node.flags) %>
+ * Flags (#pm_<%= node_flags.human %>):
+<%- node_flags.values.each do |value| -%>
+ * * ::PM_<%= node_flags.human.upcase %>_<%= value.name %>
<%- end -%>
<%- end -%>
*
@@ -164,7 +182,8 @@ typedef struct pm_node {
typedef struct pm_<%= node.human %> {
/** The embedded base node. */
pm_node_t base;
-<%- node.fields.grep_v(Prism::Template::FlagsField).each do |field| -%>
+
+<%- node.fields.each do |field| -%>
/**
* <%= node.name %>#<%= field.name %>
@@ -201,8 +220,10 @@ typedef enum pm_<%= flag.human %> {
<%- flag.values.each_with_index do |value, index| -%>
<%= "\n" if index > 0 -%>
/** <%= value.comment %> */
- PM_<%= flag.human.upcase %>_<%= value.name %> = <%= 1 << index %>,
+ PM_<%= flag.human.upcase %>_<%= value.name %> = <%= 1 << (index + Prism::Template::COMMON_FLAGS_COUNT) %>,
<%- end -%>
+
+ PM_<%= flag.human.upcase %>_LAST,
} pm_<%= flag.human %>_t;
<%- end -%>
@@ -212,6 +233,6 @@ typedef enum pm_<%= flag.human %> {
* to specify that through the environment. It will never be true except for in
* those build systems.
*/
-#define PRISM_SERIALIZE_ONLY_SEMANTICS_FIELDS <%= Prism::Template::SERIALIZE_ONLY_SEMANTICS_FIELDS %>
+#define PRISM_SERIALIZE_ONLY_SEMANTICS_FIELDS <%= Prism::Template::SERIALIZE_ONLY_SEMANTICS_FIELDS ? 1 : 0 %>
#endif
diff --git a/prism/templates/lib/prism/compiler.rb.erb b/prism/templates/lib/prism/compiler.rb.erb
index 45ed88d8de..66dbe666b9 100644
--- a/prism/templates/lib/prism/compiler.rb.erb
+++ b/prism/templates/lib/prism/compiler.rb.erb
@@ -29,13 +29,15 @@ module Prism
# Visit the child nodes of the given node.
def visit_child_nodes(node)
- node.compact_child_nodes.map { |node| node.accept(self) }
+ node.each_child_node.map { |node| node.accept(self) }
end
<%- nodes.each_with_index do |node, index| -%>
<%= "\n" if index != 0 -%>
# Compile a <%= node.name %> node
- alias visit_<%= node.human %> visit_child_nodes
+ def visit_<%= node.human %>(node)
+ node.each_child_node.map { |node| node.accept(self) }
+ end
<%- end -%>
end
end
diff --git a/prism/templates/lib/prism/dispatcher.rb.erb b/prism/templates/lib/prism/dispatcher.rb.erb
index 1370ca7636..52478451c9 100644
--- a/prism/templates/lib/prism/dispatcher.rb.erb
+++ b/prism/templates/lib/prism/dispatcher.rb.erb
@@ -14,7 +14,8 @@ module Prism
# end
# end
#
- # dispatcher = Dispatcher.new
+ # listener = OctalListener.new
+ # dispatcher = Prism::Dispatcher.new
# dispatcher.register(listener, :on_integer_node_enter)
#
# Then, you can walk any number of trees and dispatch events to the listeners:
@@ -43,6 +44,19 @@ module Prism
#
# def register: (Listener, *Symbol) -> void
def register(listener, *events)
+ register_events(listener, events)
+ end
+
+ # Register all public methods of a listener that match the pattern
+ # `on_<node_name>_(enter|leave)`.
+ #
+ # def register_public_methods: (Listener) -> void
+ def register_public_methods(listener)
+ register_events(listener, listener.public_methods(false).grep(/\Aon_.+_(?:enter|leave)\z/))
+ end
+
+ # Register a listener for the given events.
+ private def register_events(listener, events)
events.each { |event| (listeners[event] ||= []) << listener }
end
diff --git a/prism/templates/lib/prism/dot_visitor.rb.erb b/prism/templates/lib/prism/dot_visitor.rb.erb
index 93c94b19ee..cd2998fe61 100644
--- a/prism/templates/lib/prism/dot_visitor.rb.erb
+++ b/prism/templates/lib/prism/dot_visitor.rb.erb
@@ -1,4 +1,5 @@
-require "cgi"
+require "cgi/escape"
+require "cgi/util" unless defined?(CGI::EscapeExt)
module Prism
# This visitor provides the ability to call Node#to_dot, which converts a
@@ -109,6 +110,11 @@ module Prism
def visit_<%= node.human %>(node)
table = Table.new("<%= node.name %>")
id = node_id(node)
+ <%- if (node_flags = node.flags) -%>
+
+ # flags
+ table.field("flags", <%= node_flags.human %>_inspect(node))
+ <%- end -%>
<%- node.fields.each do |field| -%>
# <%= field.name %>
@@ -141,9 +147,6 @@ module Prism
unless (<%= field.name %> = node.<%= field.name %>).nil?
table.field("<%= field.name %>", location_inspect(<%= field.name %>))
end
- <%- when Prism::Template::FlagsField -%>
- <%- flag = flags.find { |flag| flag.name == field.kind }.tap { |flag| raise "Expected to find #{field.kind}" unless flag } -%>
- table.field("<%= field.name %>", <%= flag.human %>_inspect(node))
<%- else -%>
<%- raise -%>
<%- end -%>
diff --git a/prism/templates/lib/prism/dsl.rb.erb b/prism/templates/lib/prism/dsl.rb.erb
index eff0d1c4fc..e16ebb7110 100644
--- a/prism/templates/lib/prism/dsl.rb.erb
+++ b/prism/templates/lib/prism/dsl.rb.erb
@@ -5,45 +5,129 @@ module Prism
# source = Prism::Source.for("[1]")
#
# Prism::ArrayNode.new(
+ # source,
+ # 0,
+ # Prism::Location.new(source, 0, 3),
+ # 0,
# [
# Prism::IntegerNode.new(
- # Prism::IntegerBaseFlags::DECIMAL,
- # 1,
+ # source,
+ # 0,
# Prism::Location.new(source, 1, 1),
- # source
+ # Prism::IntegerBaseFlags::DECIMAL,
+ # 1
# )
# ],
# Prism::Location.new(source, 0, 1),
- # Prism::Location.new(source, 2, 1),
- # source
+ # Prism::Location.new(source, 2, 1)
# )
#
# you could instead write:
#
- # source = Prism::Source.for("[1]")
+ # class Builder
+ # include Prism::DSL
#
- # ArrayNode(
- # IntegerNode(Prism::IntegerBaseFlags::DECIMAL, 1, Location(source, 1, 1)), source),
- # Location(source, 0, 1),
- # Location(source, 2, 1),
- # source
- # )
+ # attr_reader :default_source
+ #
+ # def initialize
+ # @default_source = source("[1]")
+ # end
#
- # This is mostly helpful in the context of writing tests, but can also be used
- # to generate trees programmatically.
+ # def build
+ # array_node(
+ # location: location(start_offset: 0, length: 3),
+ # elements: [
+ # integer_node(
+ # location: location(start_offset: 1, length: 1),
+ # flags: integer_base_flag(:decimal),
+ # value: 1
+ # )
+ # ],
+ # opening_loc: location(start_offset: 0, length: 1),
+ # closing_loc: location(start_offset: 2, length: 1)
+ # )
+ # end
+ # end
+ #
+ # This is mostly helpful in the context of generating trees programmatically.
module DSL
- private
+ # Provide all of these methods as module methods as well, to allow for
+ # building nodes like Prism::DSL.nil_node.
+ extend self
- # Create a new Location object
- def Location(source = nil, start_offset = 0, length = 0)
- Location.new(source, start_offset, length) # steep:ignore
+ # Create a new Source object.
+ def source(string)
+ Source.for(string)
+ end
+
+ # Create a new Location object.
+ def location(source: default_source, start_offset: 0, length: 0)
+ Location.new(source, start_offset, length)
end
<%- nodes.each do |node| -%>
- # Create a new <%= node.name %> node
- def <%= node.name %>(<%= (node.fields.map(&:name) + ["source = nil, location = Location()"]).join(", ") %>)
- <%= node.name %>.new(<%= ["source", *node.fields.map(&:name), "location"].join(", ") %>)
+ # Create a new <%= node.name %> node.
+ def <%= node.human %>(<%= ["source: default_source", "node_id: 0", "location: default_location", "flags: 0", *node.fields.map { |field|
+ case field
+ when Prism::Template::NodeField
+ kind = field.specific_kind || field.union_kind&.first
+ if kind.nil?
+ "#{field.name}: default_node(source, location)"
+ else
+ "#{field.name}: #{kind.gsub(/(?<=.)[A-Z]/, "_\\0").downcase}(source: source)"
+ end
+ when Prism::Template::ConstantField
+ "#{field.name}: :\"\""
+ when Prism::Template::OptionalNodeField, Prism::Template::OptionalConstantField, Prism::Template::OptionalLocationField
+ "#{field.name}: nil"
+ when Prism::Template::NodeListField, Prism::Template::ConstantListField
+ "#{field.name}: []"
+ when Prism::Template::StringField
+ "#{field.name}: \"\""
+ when Prism::Template::LocationField
+ "#{field.name}: location"
+ when Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::IntegerField
+ "#{field.name}: 0"
+ when Prism::Template::DoubleField
+ "#{field.name}: 0.0"
+ else
+ raise
+ end
+ }].join(", ") %>)
+ <%= node.name %>.new(<%= ["source", "node_id", "location", "flags", *node.fields.map(&:name)].join(", ") %>)
end
<%- end -%>
+ <%- flags.each do |flag| -%>
+
+ # Retrieve the value of one of the <%= flag.name %> flags.
+ def <%= flag.human.chomp("s") %>(name)
+ case name
+ <%- flag.values.each do |value| -%>
+ when :<%= value.name.downcase %> then <%= flag.name %>::<%= value.name %>
+ <%- end -%>
+ else Kernel.raise ArgumentError, "invalid <%= flag.name %> flag: #{name.inspect}"
+ end
+ end
+ <%- end -%>
+
+ private
+
+ # The default source object that gets attached to nodes and locations if no
+ # source is specified.
+ def default_source
+ Source.for("")
+ end
+
+ # The default location object that gets attached to nodes if no location is
+ # specified, which uses the given source.
+ def default_location
+ Location.new(default_source, 0, 0)
+ end
+
+ # The default node that gets attached to nodes if no node is specified for a
+ # required node field.
+ def default_node(source, location)
+ MissingNode.new(source, -1, location, 0)
+ end
end
end
diff --git a/prism/templates/lib/prism/inspect_visitor.rb.erb b/prism/templates/lib/prism/inspect_visitor.rb.erb
index 9328da636b..3cfe615d85 100644
--- a/prism/templates/lib/prism/inspect_visitor.rb.erb
+++ b/prism/templates/lib/prism/inspect_visitor.rb.erb
@@ -69,10 +69,13 @@ module Prism
# Inspect a <%= node.name %> node.
def visit_<%= node.human %>(node)
commands << [inspect_node(<%= node.name.inspect %>, node), indent]
- <%- node.fields.each_with_index do |field, index| -%>
- <%- pointer = index == node.fields.length - 1 ? "└── " : "├── " -%>
- <%- preadd = index == node.fields.length - 1 ? " " : "│ " -%>
+ <%- (fields = [node.flags || Prism::Template::Flags.empty, *node.fields]).each_with_index do |field, index| -%>
+ <%- pointer = index == fields.length - 1 ? "└── " : "├── " -%>
+ <%- preadd = index == fields.length - 1 ? " " : "│ " -%>
<%- case field -%>
+ <%- when Prism::Template::Flags -%>
+ flags = [("newline" if node.newline?), ("static_literal" if node.static_literal?), <%= field.values.map { |value| "(\"#{value.name.downcase}\" if node.#{value.name.downcase}?)" }.join(", ") %>].compact
+ commands << ["<%= pointer %>flags: #{flags.empty? ? "∅" : flags.join(", ")}\n", indent]
<%- when Prism::Template::NodeListField -%>
commands << ["<%= pointer %><%= field.name %>: (length: #{(<%= field.name %> = node.<%= field.name %>).length})\n", indent]
if <%= field.name %>.any?
@@ -101,10 +104,6 @@ module Prism
else
commands << ["<%= pointer %><%= field.name %>: #{<%= field.name %>.inspect}\n", indent]
end
- <%- when Prism::Template::FlagsField -%>
- <%- flag = flags.find { |flag| flag.name == field.kind }.tap { |flag| raise unless flag } -%>
- flags = [<%= flag.values.map { |value| "(\"#{value.name.downcase}\" if node.#{value.name.downcase}?)" }.join(", ") %>].compact
- commands << ["<%= pointer %><%= field.name %>: #{flags.empty? ? "∅" : flags.join(", ")}\n", indent]
<%- when Prism::Template::LocationField, Prism::Template::OptionalLocationField -%>
commands << ["<%= pointer %><%= field.name %>: #{inspect_location(node.<%= field.name %>)}\n", indent]
<%- end -%>
diff --git a/prism/templates/lib/prism/node.rb.erb b/prism/templates/lib/prism/node.rb.erb
index f0ce226def..8225bfb328 100644
--- a/prism/templates/lib/prism/node.rb.erb
+++ b/prism/templates/lib/prism/node.rb.erb
@@ -6,6 +6,17 @@ module Prism
attr_reader :source
private :source
+ # A unique identifier for this node. This is used in a very specific
+ # use case where you want to keep around a reference to a node without
+ # having to keep around the syntax tree in memory. This unique identifier
+ # will be consistent across multiple parses of the same source code.
+ attr_reader :node_id
+
+ # Save this node using a saved source so that it can be retrieved later.
+ def save(repository)
+ repository.enter(node_id, :itself)
+ end
+
# A Location instance that represents the location of this node in the
# source.
def location
@@ -14,6 +25,21 @@ module Prism
@location = Location.new(source, location >> 32, location & 0xFFFFFFFF)
end
+ # Save the location using a saved source so that it can be retrieved later.
+ def save_location(repository)
+ repository.enter(node_id, :location)
+ end
+
+ # Delegates to the start_line of the associated location object.
+ def start_line
+ location.start_line
+ end
+
+ # Delegates to the end_line of the associated location object.
+ def end_line
+ location.end_line
+ end
+
# The start offset of the node in the source. This method is effectively a
# delegate method to the location object.
def start_offset
@@ -28,6 +54,75 @@ module Prism
location.is_a?(Location) ? location.end_offset : ((location >> 32) + (location & 0xFFFFFFFF))
end
+ # Delegates to the start_character_offset of the associated location object.
+ def start_character_offset
+ location.start_character_offset
+ end
+
+ # Delegates to the end_character_offset of the associated location object.
+ def end_character_offset
+ location.end_character_offset
+ end
+
+ # Delegates to the cached_start_code_units_offset of the associated location
+ # object.
+ def cached_start_code_units_offset(cache)
+ location.cached_start_code_units_offset(cache)
+ end
+
+ # Delegates to the cached_end_code_units_offset of the associated location
+ # object.
+ def cached_end_code_units_offset(cache)
+ location.cached_end_code_units_offset(cache)
+ end
+
+ # Delegates to the start_column of the associated location object.
+ def start_column
+ location.start_column
+ end
+
+ # Delegates to the end_column of the associated location object.
+ def end_column
+ location.end_column
+ end
+
+ # Delegates to the start_character_column of the associated location object.
+ def start_character_column
+ location.start_character_column
+ end
+
+ # Delegates to the end_character_column of the associated location object.
+ def end_character_column
+ location.end_character_column
+ end
+
+ # Delegates to the cached_start_code_units_column of the associated location
+ # object.
+ def cached_start_code_units_column(cache)
+ location.cached_start_code_units_column(cache)
+ end
+
+ # Delegates to the cached_end_code_units_column of the associated location
+ # object.
+ def cached_end_code_units_column(cache)
+ location.cached_end_code_units_column(cache)
+ end
+
+ # Delegates to the leading_comments of the associated location object.
+ def leading_comments
+ location.leading_comments
+ end
+
+ # Delegates to the trailing_comments of the associated location object.
+ def trailing_comments
+ location.trailing_comments
+ end
+
+ # Delegates to the comments of the associated location object.
+ def comments
+ location.comments
+ end
+
# Returns all of the lines of the source code associated with this node.
def source_lines
location.source_lines
@@ -49,6 +144,21 @@ module Prism
location.slice_lines
end
+ # An bitset of flags for this node. There are certain flags that are common
+ # for all nodes, and then some nodes have specific flags.
+ attr_reader :flags
+ protected :flags
+
+ # Returns true if the node has the newline flag set.
+ def newline?
+ flags.anybits?(NodeFlags::NEWLINE)
+ end
+
+ # Returns true if the node has the static literal flag set.
+ def static_literal?
+ flags.anybits?(NodeFlags::STATIC_LITERAL)
+ end
+
# Similar to inspect, but respects the current level of indentation given by
# the pretty print object.
def pretty_print(q)
@@ -72,26 +182,15 @@ module Prism
# bytes, as opposed to characters or code units.
def tunnel(line, column)
queue = [self] #: Array[Prism::node]
- result = []
+ result = [] #: Array[Prism::node]
+
+ search_offset = source.line_to_byte_offset(line) + column
while (node = queue.shift)
result << node
- node.compact_child_nodes.each do |child_node|
- child_location = child_node.location
-
- start_line = child_location.start_line
- end_line = child_location.end_line
-
- if start_line == end_line
- if line == start_line && column >= child_location.start_column && column < child_location.end_column
- queue << child_node
- break
- end
- elsif (line == start_line && column >= child_location.start_column) || (line == end_line && column < child_location.end_column)
- queue << child_node
- break
- elsif line > start_line && line < end_line
+ node.each_child_node do |child_node|
+ if child_node.start_offset <= search_offset && search_offset < child_node.end_offset
queue << child_node
break
end
@@ -101,6 +200,23 @@ module Prism
result
end
+ # Returns the first node that matches the given block when visited in a
+ # depth-first search. This is useful for finding a node that matches a
+ # particular condition.
+ #
+ # node.breadth_first_search { |node| node.node_id == node_id }
+ #
+ def breadth_first_search(&block)
+ queue = [self] #: Array[Prism::node]
+
+ while (node = queue.shift)
+ return node if yield node
+ queue.concat(node.compact_child_nodes)
+ end
+
+ nil
+ end
+
# Returns a list of the fields that exist for this node class. Fields
# describe the structure of the node. This kind of reflection is useful for
# things like recursively visiting each node _and_ field in the tree.
@@ -132,6 +248,13 @@ module Prism
alias deconstruct child_nodes
+ # With a block given, yields each child node. Without a block, returns
+ # an enumerator that contains each child node. Excludes any `nil`s in
+ # the place of optional nodes that were not present.
+ def each_child_node
+ raise NoMethodError, "undefined method `each_child_node' for #{inspect}"
+ end
+
# Returns an array of child nodes, excluding any `nil`s in the place of
# optional nodes that were not present.
def compact_child_nodes
@@ -144,18 +267,31 @@ module Prism
raise NoMethodError, "undefined method `comment_targets' for #{inspect}"
end
- # Returns a symbol symbolizing the type of node that this represents. This
- # is particularly useful for case statements and array comparisons.
- def type
- raise NoMethodError, "undefined method `type' for #{inspect}"
- end
-
# Returns a string representation of the node.
def inspect
raise NoMethodError, "undefined method `inspect' for #{inspect}"
end
- # Returns the type of the node as a symbol.
+ # Sometimes you want to check an instance of a node against a list of
+ # classes to see what kind of behavior to perform. Usually this is done by
+ # calling `[cls1, cls2].include?(node.class)` or putting the node into a
+ # case statement and doing `case node; when cls1; when cls2; end`. Both of
+ # these approaches are relatively slow because of the constant lookups,
+ # method calls, and/or array allocations.
+ #
+ # Instead, you can call #type, which will return to you a symbol that you
+ # can use for comparison. This is faster than the other approaches because
+ # it uses a single integer comparison, but also because if you're on CRuby
+ # you can take advantage of the fact that case statements with all symbol
+ # keys will use a jump table.
+ def type
+ raise NoMethodError, "undefined method `type' for #{inspect}"
+ end
+
+ # Similar to #type, this method returns a symbol that you can use for
+ # splitting on the type of the node without having to do a long === chain.
+ # Note that like #type, it will still be slower than using == for a single
+ # class, but should be faster in a case statement or an array comparison.
def self.type
raise NoMethodError, "undefined method `type' for #{inspect}"
end
@@ -166,13 +302,15 @@ module Prism
#<%= line %>
<%- end -%>
class <%= node.name -%> < Node
- # def initialize: (<%= (node.fields.map { |field| "#{field.rbs_class} #{field.name}" } + ["Location location"]).join(", ") %>) -> void
- def initialize(source, <%= (node.fields.map(&:name) + ["location"]).join(", ") %>)
+ # Initialize a new <%= node.name %> node.
+ def initialize(<%= ["source", "node_id", "location", "flags", *node.fields.map(&:name)].join(", ") %>)
@source = source
+ @node_id = node_id
@location = location
+ @flags = flags
<%- node.fields.each do |field| -%>
<%- if Prism::Template::CHECK_FIELD_KIND && field.respond_to?(:check_field_kind) -%>
- raise <%= field.name %>.inspect unless <%= field.check_field_kind %>
+ raise "<%= node.name %>#<%= field.name %> was of unexpected type:\n#{<%= field.name %>.inspect}" unless <%= field.check_field_kind %>
<%- end -%>
@<%= field.name %> = <%= field.name %>
<%- end -%>
@@ -183,7 +321,7 @@ module Prism
visitor.visit_<%= node.human %>(self)
end
- # def child_nodes: () -> Array[nil | Node]
+ # def child_nodes: () -> Array[Node?]
def child_nodes
[<%= node.fields.map { |field|
case field
@@ -193,6 +331,22 @@ module Prism
}.compact.join(", ") %>]
end
+ # def each_child_node: () { (Prism::node) -> void } -> void | () -> Enumerator[Prism::node]
+ def each_child_node
+ return to_enum(:each_child_node) unless block_given?
+
+ <%- node.fields.each do |field| -%>
+ <%- case field -%>
+ <%- when Prism::Template::NodeField -%>
+ yield <%= field.name %>
+ <%- when Prism::Template::OptionalNodeField -%>
+ yield <%= field.name %> if <%= field.name %>
+ <%- when Prism::Template::NodeListField -%>
+ <%= field.name %>.each { |node| yield node }
+ <%- end -%>
+ <%- end -%>
+ end
+
# def compact_child_nodes: () -> Array[Node]
def compact_child_nodes
<%- if node.fields.any? { |field| field.is_a?(Prism::Template::OptionalNodeField) } -%>
@@ -228,22 +382,31 @@ module Prism
}.compact.join(", ") %>] #: Array[Prism::node | Location]
end
- # def copy: (<%= (node.fields.map { |field| "?#{field.name}: #{field.rbs_class}" } + ["?location: Location"]).join(", ") %>) -> <%= node.name %>
- def copy(<%= (node.fields.map(&:name) + ["location"]).map { |field| "#{field}: self.#{field}" }.join(", ") %>)
- <%= node.name %>.new(<%= ["source", *node.fields.map(&:name), "location"].join(", ") %>)
+ # def copy: (<%= (["?node_id: Integer", "?location: Location", "?flags: Integer"] + node.fields.map { |field| "?#{field.name}: #{field.rbs_class}" }).join(", ") %>) -> <%= node.name %>
+ def copy(<%= (["node_id", "location", "flags"] + node.fields.map(&:name)).map { |field| "#{field}: self.#{field}" }.join(", ") %>)
+ <%= node.name %>.new(<%= ["source", "node_id", "location", "flags", *node.fields.map(&:name)].join(", ") %>)
end
- # def deconstruct: () -> Array[nil | Node]
+ # def deconstruct: () -> Array[Node?]
alias deconstruct child_nodes
- # def deconstruct_keys: (Array[Symbol] keys) -> { <%= (node.fields.map { |field| "#{field.name}: #{field.rbs_class}" } + ["location: Location"]).join(", ") %> }
+ # def deconstruct_keys: (Array[Symbol] keys) -> { <%= (["node_id: Integer", "location: Location"] + node.fields.map { |field| "#{field.name}: #{field.rbs_class}" }).join(", ") %> }
def deconstruct_keys(keys)
- { <%= (node.fields.map { |field| "#{field.name}: #{field.name}" } + ["location: location"]).join(", ") %> }
+ { <%= (["node_id: node_id", "location: location"] + node.fields.map { |field| "#{field.name}: #{field.name}" }).join(", ") %> }
+ end
+ <%- if (node_flags = node.flags) -%>
+ <%- node_flags.values.each do |value| -%>
+
+ # def <%= value.name.downcase %>?: () -> bool
+ def <%= value.name.downcase %>?
+ flags.anybits?(<%= node_flags.name %>::<%= value.name %>)
end
+ <%- end -%>
+ <%- end -%>
<%- node.fields.each do |field| -%>
<%- if field.comment.nil? -%>
- # <%= "protected " if field.is_a?(Prism::Template::FlagsField) %>attr_reader <%= field.name %>: <%= field.rbs_class %>
+ # attr_reader <%= field.name %>: <%= field.rbs_class %>
<%- else -%>
<%- field.each_comment_line do |line| -%>
#<%= line %>
@@ -256,6 +419,12 @@ module Prism
return location if location.is_a?(Location)
@<%= field.name %> = Location.new(source, location >> 32, location & 0xFFFFFFFF)
end
+
+ # Save the <%= field.name %> location using the given saved source so that
+ # it can be retrieved later.
+ def save_<%= field.name %>(repository)
+ repository.enter(node_id, :<%= field.name %>)
+ end
<%- when Prism::Template::OptionalLocationField -%>
def <%= field.name %>
location = @<%= field.name %>
@@ -268,8 +437,14 @@ module Prism
@<%= field.name %> = Location.new(source, location >> 32, location & 0xFFFFFFFF)
end
end
+
+ # Save the <%= field.name %> location using the given saved source so that
+ # it can be retrieved later.
+ def save_<%= field.name %>(repository)
+ repository.enter(node_id, :<%= field.name %>) unless @<%= field.name %>.nil?
+ end
<%- else -%>
- attr_reader :<%= field.name -%><%= "\n protected :#{field.name}" if field.is_a?(Prism::Template::FlagsField) %>
+ attr_reader :<%= field.name %>
<%- end -%>
<%- end -%>
<%- node.fields.each do |field| -%>
@@ -290,14 +465,6 @@ module Prism
def <%= field.name.delete_suffix("_loc") %>
<%= field.name %>&.slice
end
- <%- when Prism::Template::FlagsField -%>
- <%- flags.find { |flag| flag.name == field.kind }.tap { |flag| raise "Expected to find #{field.kind}" unless flag }.values.each do |value| -%>
-
- # def <%= value.name.downcase %>?: () -> bool
- def <%= value.name.downcase %>?
- <%= field.name %>.anybits?(<%= field.kind %>::<%= value.name %>)
- end
- <%- end -%>
<%- end -%>
<%- end -%>
@@ -306,30 +473,12 @@ module Prism
InspectVisitor.compose(self)
end
- # Sometimes you want to check an instance of a node against a list of
- # classes to see what kind of behavior to perform. Usually this is done by
- # calling `[cls1, cls2].include?(node.class)` or putting the node into a
- # case statement and doing `case node; when cls1; when cls2; end`. Both of
- # these approaches are relatively slow because of the constant lookups,
- # method calls, and/or array allocations.
- #
- # Instead, you can call #type, which will return to you a symbol that you
- # can use for comparison. This is faster than the other approaches because
- # it uses a single integer comparison, but also because if you're on CRuby
- # you can take advantage of the fact that case statements with all symbol
- # keys will use a jump table.
- #
- # def type: () -> Symbol
+ # Return a symbol representation of this node type. See `Node#type`.
def type
:<%= node.human %>
end
- # Similar to #type, this method returns a symbol that you can use for
- # splitting on the type of the node without having to do a long === chain.
- # Note that like #type, it will still be slower than using == for a single
- # class, but should be faster in a case statement or an array comparison.
- #
- # def self.type: () -> Symbol
+ # Return a symbol representation of this node type. See `Node::type`.
def self.type
:<%= node.human %>
end
@@ -337,29 +486,42 @@ module Prism
# Implements case-equality for the node. This is effectively == but without
# comparing the value of locations. Locations are checked only for presence.
def ===(other)
- other.is_a?(<%= node.name %>)<%= " &&" if node.fields.any? %>
- <%- node.fields.each_with_index do |field, index| -%>
+ other.is_a?(<%= node.name %>)<%= " &&" if (fields = [*node.flags, *node.fields]).any? %>
+ <%- fields.each_with_index do |field, index| -%>
<%- if field.is_a?(Prism::Template::LocationField) || field.is_a?(Prism::Template::OptionalLocationField) -%>
- (<%= field.name %>.nil? == other.<%= field.name %>.nil?)<%= " &&" if index != node.fields.length - 1 %>
+ (<%= field.name %>.nil? == other.<%= field.name %>.nil?)<%= " &&" if index != fields.length - 1 %>
<%- elsif field.is_a?(Prism::Template::NodeListField) || field.is_a?(Prism::Template::ConstantListField) -%>
(<%= field.name %>.length == other.<%= field.name %>.length) &&
- <%= field.name %>.zip(other.<%= field.name %>).all? { |left, right| left === right }<%= " &&" if index != node.fields.length - 1 %>
+ <%= field.name %>.zip(other.<%= field.name %>).all? { |left, right| left === right }<%= " &&" if index != fields.length - 1 %>
+ <%- elsif field.is_a?(Prism::Template::Flags) -%>
+ (flags === other.flags)<%= " &&" if index != fields.length - 1 %>
<%- else -%>
- (<%= field.name %> === other.<%= field.name %>)<%= " &&" if index != node.fields.length - 1 %>
+ (<%= field.name %> === other.<%= field.name %>)<%= " &&" if index != fields.length - 1 %>
<%- end -%>
<%- end -%>
end
end
<%- end -%>
- <%- flags.each_with_index do |flag, flag_index| -%>
+ <%- flags.each do |flag| -%>
# <%= flag.comment %>
module <%= flag.name %>
<%- flag.values.each_with_index do |value, index| -%>
# <%= value.comment %>
- <%= value.name %> = 1 << <%= index %>
+ <%= value.name %> = 1 << <%= index + Prism::Template::COMMON_FLAGS_COUNT %>
<%= "\n" if value != flag.values.last -%>
<%- end -%>
end
<%- end -%>
+
+ # The flags that are common to all nodes.
+ module NodeFlags
+ # A flag to indicate that the node is a candidate to emit a :line event
+ # through tracepoint when compiled.
+ NEWLINE = 1
+
+ # A flag to indicate that the value that the node represents is a value that
+ # can be determined at parse-time.
+ STATIC_LITERAL = 2
+ end
end
diff --git a/prism/templates/lib/prism/reflection.rb.erb b/prism/templates/lib/prism/reflection.rb.erb
index 3c1d61c6c1..6c8b2f4d25 100644
--- a/prism/templates/lib/prism/reflection.rb.erb
+++ b/prism/templates/lib/prism/reflection.rb.erb
@@ -97,7 +97,7 @@ module Prism
case node.type
<%- nodes.each do |node| -%>
when :<%= node.human %>
- [<%= node.fields.map { |field|
+ [<%= [*node.flags, *node.fields].map { |field|
case field
when Prism::Template::NodeField
"NodeField.new(:#{field.name})"
@@ -121,9 +121,8 @@ module Prism
"IntegerField.new(:#{field.name})"
when Prism::Template::DoubleField
"FloatField.new(:#{field.name})"
- when Prism::Template::FlagsField
- found = flags.find { |flag| flag.name == field.kind }.tap { |found| raise "Expected to find #{field.kind}" unless found }
- "FlagsField.new(:#{field.name}, [#{found.values.map { |value| ":#{value.name.downcase}?" }.join(", ")}])"
+ when Prism::Template::Flags
+ "FlagsField.new(:flags, [#{field.values.map { |value| ":#{value.name.downcase}?" }.join(", ")}])"
else
raise field.class.name
end
diff --git a/prism/templates/lib/prism/serialize.rb.erb b/prism/templates/lib/prism/serialize.rb.erb
index 756821cf7d..6902df5c01 100644
--- a/prism/templates/lib/prism/serialize.rb.erb
+++ b/prism/templates/lib/prism/serialize.rb.erb
@@ -6,114 +6,322 @@ module Prism
module Serialize
# The major version of prism that we are expecting to find in the serialized
# strings.
- MAJOR_VERSION = 0
+ MAJOR_VERSION = 1
# The minor version of prism that we are expecting to find in the serialized
# strings.
- MINOR_VERSION = 29
+ MINOR_VERSION = 8
# The patch version of prism that we are expecting to find in the serialized
# strings.
PATCH_VERSION = 0
- # Deserialize the AST represented by the given string into a parse result.
- def self.load(input, serialized)
+ # Deserialize the dumped output from a request to parse or parse_file.
+ #
+ # The formatting of the source of this method is purposeful to illustrate
+ # the structure of the serialized data.
+ def self.load_parse(input, serialized, freeze)
input = input.dup
source = Source.for(input)
loader = Loader.new(source, serialized)
- result = loader.load_result
- input.force_encoding(loader.encoding)
+ loader.load_header
+ encoding = loader.load_encoding
+ start_line = loader.load_varsint
+ offsets = loader.load_line_offsets(freeze)
+
+ source.replace_start_line(start_line)
+ source.replace_offsets(offsets)
+
+ comments = loader.load_comments(freeze)
+ magic_comments = loader.load_magic_comments(freeze)
+ data_loc = loader.load_optional_location_object(freeze)
+ errors = loader.load_errors(encoding, freeze)
+ warnings = loader.load_warnings(encoding, freeze)
+ cpool_base = loader.load_uint32
+ cpool_size = loader.load_varuint
+
+ constant_pool = ConstantPool.new(input, serialized, cpool_base, cpool_size)
+
+ node = loader.load_node(constant_pool, encoding, freeze)
+ loader.load_constant_pool(constant_pool)
+ raise unless loader.eof?
+
+ result = ParseResult.new(node, comments, magic_comments, data_loc, errors, warnings, source)
+ result.freeze if freeze
+
+ input.force_encoding(encoding)
+
+ # This is an extremely niche use-case where the file was marked as binary
+ # but it contained UTF-8-encoded characters. In that case we will actually
+ # put it back to UTF-8 to give the location APIs the best chance of being
+ # correct.
+ if !input.ascii_only? && input.encoding == Encoding::BINARY
+ input.force_encoding(Encoding::UTF_8)
+ input.force_encoding(Encoding::BINARY) unless input.valid_encoding?
+ end
+
+ if freeze
+ input.freeze
+ source.deep_freeze
+ end
+
+ result
+ end
+
+ # Deserialize the dumped output from a request to lex or lex_file.
+ #
+ # The formatting of the source of this method is purposeful to illustrate
+ # the structure of the serialized data.
+ def self.load_lex(input, serialized, freeze)
+ source = Source.for(input)
+ loader = Loader.new(source, serialized)
+
+ tokens = loader.load_tokens
+ encoding = loader.load_encoding
+ start_line = loader.load_varsint
+ offsets = loader.load_line_offsets(freeze)
+
+ source.replace_start_line(start_line)
+ source.replace_offsets(offsets)
+
+ comments = loader.load_comments(freeze)
+ magic_comments = loader.load_magic_comments(freeze)
+ data_loc = loader.load_optional_location_object(freeze)
+ errors = loader.load_errors(encoding, freeze)
+ warnings = loader.load_warnings(encoding, freeze)
+ raise unless loader.eof?
+
+ result = LexResult.new(tokens, comments, magic_comments, data_loc, errors, warnings, source)
+
+ tokens.each do |token|
+ token[0].value.force_encoding(encoding)
+
+ if freeze
+ token[0].deep_freeze
+ token.freeze
+ end
+ end
+
+ if freeze
+ source.deep_freeze
+ tokens.freeze
+ result.freeze
+ end
+
result
end
- # Deserialize the tokens represented by the given string into a parse
- # result.
- def self.load_tokens(source, serialized)
- Loader.new(source, serialized).load_tokens_result
+ # Deserialize the dumped output from a request to parse_comments or
+ # parse_file_comments.
+ #
+ # The formatting of the source of this method is purposeful to illustrate
+ # the structure of the serialized data.
+ def self.load_parse_comments(input, serialized, freeze)
+ source = Source.for(input)
+ loader = Loader.new(source, serialized)
+
+ loader.load_header
+ loader.load_encoding
+ start_line = loader.load_varsint
+
+ source.replace_start_line(start_line)
+
+ result = loader.load_comments(freeze)
+ raise unless loader.eof?
+
+ source.deep_freeze if freeze
+ result
end
- class Loader # :nodoc:
- if RUBY_ENGINE == "truffleruby"
- # StringIO is synchronized and that adds a high overhead on TruffleRuby.
- class FastStringIO # :nodoc:
- attr_accessor :pos
-
- def initialize(string)
- @string = string
- @pos = 0
- end
+ # Deserialize the dumped output from a request to parse_lex or
+ # parse_lex_file.
+ #
+ # The formatting of the source of this method is purposeful to illustrate
+ # the structure of the serialized data.
+ def self.load_parse_lex(input, serialized, freeze)
+ source = Source.for(input)
+ loader = Loader.new(source, serialized)
- def getbyte
- byte = @string.getbyte(@pos)
- @pos += 1
- byte
- end
+ tokens = loader.load_tokens
+ loader.load_header
+ encoding = loader.load_encoding
+ start_line = loader.load_varsint
+ offsets = loader.load_line_offsets(freeze)
- def read(n)
- slice = @string.byteslice(@pos, n)
- @pos += n
- slice
- end
+ source.replace_start_line(start_line)
+ source.replace_offsets(offsets)
+
+ comments = loader.load_comments(freeze)
+ magic_comments = loader.load_magic_comments(freeze)
+ data_loc = loader.load_optional_location_object(freeze)
+ errors = loader.load_errors(encoding, freeze)
+ warnings = loader.load_warnings(encoding, freeze)
+ cpool_base = loader.load_uint32
+ cpool_size = loader.load_varuint
- def eof?
- @pos >= @string.bytesize
+ constant_pool = ConstantPool.new(input, serialized, cpool_base, cpool_size)
+
+ node = loader.load_node(constant_pool, encoding, freeze)
+ loader.load_constant_pool(constant_pool)
+ raise unless loader.eof?
+
+ value = [node, tokens]
+ result = ParseLexResult.new(value, comments, magic_comments, data_loc, errors, warnings, source)
+
+ tokens.each do |token|
+ token[0].value.force_encoding(encoding)
+
+ if freeze
+ token[0].deep_freeze
+ token.freeze
+ end
+ end
+
+ if freeze
+ source.deep_freeze
+ tokens.freeze
+ value.freeze
+ result.freeze
+ end
+
+ result
+ end
+
+ class ConstantPool # :nodoc:
+ attr_reader :size
+
+ def initialize(input, serialized, base, size)
+ @input = input
+ @serialized = serialized
+ @base = base
+ @size = size
+ @pool = Array.new(size, nil)
+ end
+
+ def get(index, encoding)
+ @pool[index] ||=
+ begin
+ offset = @base + index * 8
+ start = @serialized.unpack1("L", offset: offset)
+ length = @serialized.unpack1("L", offset: offset + 4)
+
+ if start.nobits?(1 << 31)
+ @input.byteslice(start, length).force_encoding(encoding).to_sym
+ else
+ @serialized.byteslice(start & ((1 << 31) - 1), length).force_encoding(encoding).to_sym
+ end
end
+ end
+ end
+
+ if RUBY_ENGINE == "truffleruby"
+ # StringIO is synchronized and that adds a high overhead on TruffleRuby.
+ class FastStringIO # :nodoc:
+ attr_accessor :pos
+
+ def initialize(string)
+ @string = string
+ @pos = 0
+ end
+
+ def getbyte
+ byte = @string.getbyte(@pos)
+ @pos += 1
+ byte
+ end
+
+ def read(n)
+ slice = @string.byteslice(@pos, n)
+ @pos += n
+ slice
+ end
+
+ def eof?
+ @pos >= @string.bytesize
end
- else
- FastStringIO = ::StringIO
end
- private_constant :FastStringIO
+ else
+ FastStringIO = ::StringIO # :nodoc:
+ end
- attr_reader :encoding, :input, :serialized, :io
- attr_reader :constant_pool_offset, :constant_pool, :source
- attr_reader :start_line
+ class Loader # :nodoc:
+ attr_reader :input, :io, :source
def initialize(source, serialized)
- @encoding = Encoding::UTF_8
-
@input = source.source.dup
raise unless serialized.encoding == Encoding::BINARY
- @serialized = serialized
@io = FastStringIO.new(serialized)
+ @source = source
+ define_load_node_lambdas if RUBY_ENGINE != "ruby"
+ end
- @constant_pool_offset = nil
- @constant_pool = nil
+ def eof?
+ io.getbyte
+ io.eof?
+ end
- @source = source
- define_load_node_lambdas unless RUBY_ENGINE == "ruby"
+ def load_constant_pool(constant_pool)
+ trailer = 0
+
+ constant_pool.size.times do |index|
+ start, length = io.read(8).unpack("L2")
+ trailer += length if start.anybits?(1 << 31)
+ end
+
+ io.read(trailer)
end
def load_header
raise "Invalid serialization" if io.read(5) != "PRISM"
raise "Invalid serialization" if io.read(3).unpack("C3") != [MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION]
- only_semantic_fields = io.getbyte
- unless only_semantic_fields == 0
- raise "Invalid serialization (location fields must be included but are not)"
- end
+ raise "Invalid serialization (location fields must be included but are not)" if io.getbyte != 0
end
def load_encoding
- @encoding = Encoding.find(io.read(load_varuint))
- @input = input.force_encoding(@encoding).freeze
- @encoding
+ encoding = Encoding.find(io.read(load_varuint))
+ @input = input.force_encoding(encoding).freeze
+ encoding
end
- def load_start_line
- source.instance_variable_set :@start_line, load_varsint
+ def load_line_offsets(freeze)
+ offsets = Array.new(load_varuint) { load_varuint }
+ offsets.freeze if freeze
+ offsets
end
- def load_line_offsets
- source.instance_variable_set :@offsets, Array.new(load_varuint) { load_varuint }
+ def load_comments(freeze)
+ comments =
+ Array.new(load_varuint) do
+ comment =
+ case load_varuint
+ when 0 then InlineComment.new(load_location_object(freeze))
+ when 1 then EmbDocComment.new(load_location_object(freeze))
+ end
+
+ comment.freeze if freeze
+ comment
+ end
+
+ comments.freeze if freeze
+ comments
end
- def load_comments
- Array.new(load_varuint) do
- case load_varuint
- when 0 then InlineComment.new(load_location_object)
- when 1 then EmbDocComment.new(load_location_object)
+ def load_magic_comments(freeze)
+ magic_comments =
+ Array.new(load_varuint) do
+ magic_comment =
+ MagicComment.new(
+ load_location_object(freeze),
+ load_location_object(freeze)
+ )
+
+ magic_comment.freeze if freeze
+ magic_comment
end
- end
+
+ magic_comments.freeze if freeze
+ magic_comments
end
DIAGNOSTIC_TYPES = [
@@ -127,60 +335,88 @@ module Prism
private_constant :DIAGNOSTIC_TYPES
- def load_metadata
- comments = load_comments
- magic_comments = Array.new(load_varuint) { MagicComment.new(load_location_object, load_location_object) }
- data_loc = load_optional_location_object
- errors = Array.new(load_varuint) { ParseError.new(DIAGNOSTIC_TYPES[load_varuint], load_embedded_string, load_location_object, load_error_level) }
- warnings = Array.new(load_varuint) { ParseWarning.new(DIAGNOSTIC_TYPES[load_varuint], load_embedded_string, load_location_object, load_warning_level) }
- [comments, magic_comments, data_loc, errors, warnings]
- end
+ def load_error_level
+ level = io.getbyte
- def load_tokens
- tokens = []
- while type = TOKEN_TYPES.fetch(load_varuint)
- start = load_varuint
- length = load_varuint
- lex_state = load_varuint
- location = Location.new(@source, start, length)
- tokens << [Token.new(source, type, location.slice, location), lex_state]
+ case level
+ when 0
+ :syntax
+ when 1
+ :argument
+ when 2
+ :load
+ else
+ raise "Unknown level: #{level}"
end
-
- tokens
end
- def load_tokens_result
- tokens = load_tokens
- encoding = load_encoding
- load_start_line
- load_line_offsets
- comments, magic_comments, data_loc, errors, warnings = load_metadata
- tokens.each { |token,| token.value.force_encoding(encoding) }
+ def load_errors(encoding, freeze)
+ errors =
+ Array.new(load_varuint) do
+ error =
+ ParseError.new(
+ DIAGNOSTIC_TYPES.fetch(load_varuint),
+ load_embedded_string(encoding),
+ load_location_object(freeze),
+ load_error_level
+ )
+
+ error.freeze if freeze
+ error
+ end
- raise "Expected to consume all bytes while deserializing" unless @io.eof?
- LexResult.new(tokens, comments, magic_comments, data_loc, errors, warnings, @source)
+ errors.freeze if freeze
+ errors
end
- def load_nodes
- load_header
- load_encoding
- load_start_line
- load_line_offsets
+ def load_warning_level
+ level = io.getbyte
- comments, magic_comments, data_loc, errors, warnings = load_metadata
+ case level
+ when 0
+ :default
+ when 1
+ :verbose
+ else
+ raise "Unknown level: #{level}"
+ end
+ end
- @constant_pool_offset = load_uint32
- @constant_pool = Array.new(load_varuint, nil)
+ def load_warnings(encoding, freeze)
+ warnings =
+ Array.new(load_varuint) do
+ warning =
+ ParseWarning.new(
+ DIAGNOSTIC_TYPES.fetch(load_varuint),
+ load_embedded_string(encoding),
+ load_location_object(freeze),
+ load_warning_level
+ )
+
+ warning.freeze if freeze
+ warning
+ end
- [load_node, comments, magic_comments, data_loc, errors, warnings]
+ warnings.freeze if freeze
+ warnings
end
- def load_result
- node, comments, magic_comments, data_loc, errors, warnings = load_nodes
- ParseResult.new(node, comments, magic_comments, data_loc, errors, warnings, @source)
- end
+ def load_tokens
+ tokens = []
- private
+ while (type = TOKEN_TYPES.fetch(load_varuint))
+ start = load_varuint
+ length = load_varuint
+ lex_state = load_varuint
+
+ location = Location.new(@source, start, length)
+ token = Token.new(@source, type, location.slice, location)
+
+ tokens << [token, lex_state]
+ end
+
+ tokens
+ end
# variable-length integer using https://en.wikipedia.org/wiki/LEB128
# This is also what protobuf uses: https://protobuf.dev/programming-guides/encoding/#varints
@@ -222,170 +458,127 @@ module Prism
io.read(4).unpack1("L")
end
- def load_optional_node
+ def load_optional_node(constant_pool, encoding, freeze)
if io.getbyte != 0
io.pos -= 1
- load_node
+ load_node(constant_pool, encoding, freeze)
end
end
- def load_embedded_string
- io.read(load_varuint).force_encoding(encoding)
+ def load_embedded_string(encoding)
+ io.read(load_varuint).force_encoding(encoding).freeze
end
- def load_string
- type = io.getbyte
- case type
+ def load_string(encoding)
+ case (type = io.getbyte)
when 1
- input.byteslice(load_varuint, load_varuint).force_encoding(encoding)
+ input.byteslice(load_varuint, load_varuint).force_encoding(encoding).freeze
when 2
- load_embedded_string
+ load_embedded_string(encoding)
else
raise "Unknown serialized string type: #{type}"
end
end
- def load_location
- (load_varuint << 32) | load_varuint
+ def load_location_object(freeze)
+ location = Location.new(source, load_varuint, load_varuint)
+ location.freeze if freeze
+ location
end
- def load_location_object
- Location.new(source, load_varuint, load_varuint)
- end
-
- def load_optional_location
- load_location if io.getbyte != 0
+ def load_location(freeze)
+ return load_location_object(freeze) if freeze
+ (load_varuint << 32) | load_varuint
end
- def load_optional_location_object
- load_location_object if io.getbyte != 0
+ def load_optional_location(freeze)
+ load_location(freeze) if io.getbyte != 0
end
- def load_constant(index)
- constant = constant_pool[index]
-
- unless constant
- offset = constant_pool_offset + index * 8
- start = @serialized.unpack1("L", offset: offset)
- length = @serialized.unpack1("L", offset: offset + 4)
-
- constant =
- if start.nobits?(1 << 31)
- input.byteslice(start, length).force_encoding(@encoding).to_sym
- else
- @serialized.byteslice(start & ((1 << 31) - 1), length).force_encoding(@encoding).to_sym
- end
-
- constant_pool[index] = constant
- end
-
- constant
+ def load_optional_location_object(freeze)
+ load_location_object(freeze) if io.getbyte != 0
end
- def load_required_constant
- load_constant(load_varuint - 1)
- end
-
- def load_optional_constant
+ def load_constant(constant_pool, encoding)
index = load_varuint
- load_constant(index - 1) if index != 0
+ constant_pool.get(index - 1, encoding)
end
- def load_error_level
- level = io.getbyte
-
- case level
- when 0
- :syntax
- when 1
- :argument
- when 2
- :load
- else
- raise "Unknown level: #{level}"
- end
- end
-
- def load_warning_level
- level = io.getbyte
-
- case level
- when 0
- :default
- when 1
- :verbose
- else
- raise "Unknown level: #{level}"
- end
+ def load_optional_constant(constant_pool, encoding)
+ index = load_varuint
+ constant_pool.get(index - 1, encoding) if index != 0
end
- if RUBY_ENGINE == 'ruby'
- def load_node
+ if RUBY_ENGINE == "ruby"
+ def load_node(constant_pool, encoding, freeze)
type = io.getbyte
- location = load_location
-
- case type
+ node_id = load_varuint
+ location = load_location(freeze)
+ value = case type
<%- nodes.each_with_index do |node, index| -%>
when <%= index + 1 %> then
<%- if node.needs_serialized_length? -%>
load_uint32
<%- end -%>
- <%= node.name %>.new(
- source, <%= (node.fields.map { |field|
+ <%= node.name %>.new(<%= ["source", "node_id", "location", "load_varuint", *node.fields.map { |field|
case field
- when Prism::Template::NodeField then "load_node"
- when Prism::Template::OptionalNodeField then "load_optional_node"
- when Prism::Template::StringField then "load_string"
- when Prism::Template::NodeListField then "Array.new(load_varuint) { load_node }"
- when Prism::Template::ConstantField then "load_required_constant"
- when Prism::Template::OptionalConstantField then "load_optional_constant"
- when Prism::Template::ConstantListField then "Array.new(load_varuint) { load_required_constant }"
- when Prism::Template::LocationField then "load_location"
- when Prism::Template::OptionalLocationField then "load_optional_location"
+ when Prism::Template::NodeField then "load_node(constant_pool, encoding, freeze)"
+ when Prism::Template::OptionalNodeField then "load_optional_node(constant_pool, encoding, freeze)"
+ when Prism::Template::StringField then "load_string(encoding)"
+ when Prism::Template::NodeListField then "Array.new(load_varuint) { load_node(constant_pool, encoding, freeze) }.tap { |nodes| nodes.freeze if freeze }"
+ when Prism::Template::ConstantField then "load_constant(constant_pool, encoding)"
+ when Prism::Template::OptionalConstantField then "load_optional_constant(constant_pool, encoding)"
+ when Prism::Template::ConstantListField then "Array.new(load_varuint) { load_constant(constant_pool, encoding) }.tap { |constants| constants.freeze if freeze }"
+ when Prism::Template::LocationField then "load_location(freeze)"
+ when Prism::Template::OptionalLocationField then "load_optional_location(freeze)"
when Prism::Template::UInt8Field then "io.getbyte"
- when Prism::Template::UInt32Field, Prism::Template::FlagsField then "load_varuint"
+ when Prism::Template::UInt32Field then "load_varuint"
when Prism::Template::IntegerField then "load_integer"
when Prism::Template::DoubleField then "load_double"
else raise
end
- } + ["location"]).join(", ") -%>)
+ }].join(", ") -%>)
<%- end -%>
end
+
+ value.freeze if freeze
+ value
end
else
- def load_node
- type = io.getbyte
- @load_node_lambdas[type].call
+ def load_node(constant_pool, encoding, freeze)
+ @load_node_lambdas[io.getbyte].call(constant_pool, encoding, freeze)
end
def define_load_node_lambdas
@load_node_lambdas = [
nil,
<%- nodes.each do |node| -%>
- -> {
- location = load_location
+ -> (constant_pool, encoding, freeze) {
+ node_id = load_varuint
+ location = load_location(freeze)
<%- if node.needs_serialized_length? -%>
load_uint32
<%- end -%>
- <%= node.name %>.new(
- source, <%= (node.fields.map { |field|
+ value = <%= node.name %>.new(<%= ["source", "node_id", "location", "load_varuint", *node.fields.map { |field|
case field
- when Prism::Template::NodeField then "load_node"
- when Prism::Template::OptionalNodeField then "load_optional_node"
- when Prism::Template::StringField then "load_string"
- when Prism::Template::NodeListField then "Array.new(load_varuint) { load_node }"
- when Prism::Template::ConstantField then "load_required_constant"
- when Prism::Template::OptionalConstantField then "load_optional_constant"
- when Prism::Template::ConstantListField then "Array.new(load_varuint) { load_required_constant }"
- when Prism::Template::LocationField then "load_location"
- when Prism::Template::OptionalLocationField then "load_optional_location"
+ when Prism::Template::NodeField then "load_node(constant_pool, encoding, freeze)"
+ when Prism::Template::OptionalNodeField then "load_optional_node(constant_pool, encoding, freeze)"
+ when Prism::Template::StringField then "load_string(encoding)"
+ when Prism::Template::NodeListField then "Array.new(load_varuint) { load_node(constant_pool, encoding, freeze) }"
+ when Prism::Template::ConstantField then "load_constant(constant_pool, encoding)"
+ when Prism::Template::OptionalConstantField then "load_optional_constant(constant_pool, encoding)"
+ when Prism::Template::ConstantListField then "Array.new(load_varuint) { load_constant(constant_pool, encoding) }"
+ when Prism::Template::LocationField then "load_location(freeze)"
+ when Prism::Template::OptionalLocationField then "load_optional_location(freeze)"
when Prism::Template::UInt8Field then "io.getbyte"
- when Prism::Template::UInt32Field, Prism::Template::FlagsField then "load_varuint"
+ when Prism::Template::UInt32Field then "load_varuint"
when Prism::Template::IntegerField then "load_integer"
when Prism::Template::DoubleField then "load_double"
else raise
end
- } + ["location"]).join(", ") -%>)
+ }].join(", ") -%>)
+ value.freeze if freeze
+ value
},
<%- end -%>
]
@@ -399,6 +592,11 @@ module Prism
<%- tokens.each do |token| -%>
<%= token.name.to_sym.inspect %>,
<%- end -%>
- ]
+ ].freeze
+
+ private_constant :MAJOR_VERSION, :MINOR_VERSION, :PATCH_VERSION
+ private_constant :ConstantPool, :FastStringIO, :Loader, :TOKEN_TYPES
end
+
+ private_constant :Serialize
end
diff --git a/prism/templates/lib/prism/visitor.rb.erb b/prism/templates/lib/prism/visitor.rb.erb
index 4b30a1815b..76f907724f 100644
--- a/prism/templates/lib/prism/visitor.rb.erb
+++ b/prism/templates/lib/prism/visitor.rb.erb
@@ -20,7 +20,7 @@ module Prism
# Visits the child nodes of `node` by calling `accept` on each one.
def visit_child_nodes(node)
# @type self: _Visitor
- node.compact_child_nodes.each { |node| node.accept(self) }
+ node.each_child_node { |node| node.accept(self) }
end
end
@@ -34,7 +34,7 @@ module Prism
#
# class FooCalls < Prism::Visitor
# def visit_call_node(node)
- # if node.name == "foo"
+ # if node.name == :foo
# # Do something with the node
# end
#
@@ -47,7 +47,9 @@ module Prism
<%- nodes.each_with_index do |node, index| -%>
<%= "\n" if index != 0 -%>
# Visit a <%= node.name %> node
- alias visit_<%= node.human %> visit_child_nodes
+ def visit_<%= node.human %>(node)
+ node.each_child_node { |node| node.accept(self) }
+ end
<%- end -%>
end
end
diff --git a/prism/templates/src/diagnostic.c.erb b/prism/templates/src/diagnostic.c.erb
index f734b66afb..121dd4b2b6 100644
--- a/prism/templates/src/diagnostic.c.erb
+++ b/prism/templates/src/diagnostic.c.erb
@@ -100,7 +100,6 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
[PM_ERR_ARGUMENT_FORMAL_GLOBAL] = { "invalid formal argument; formal argument cannot be a global variable", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_ARGUMENT_FORMAL_IVAR] = { "invalid formal argument; formal argument cannot be an instance variable", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_ARGUMENT_FORWARDING_UNBOUND] = { "unexpected `...` in an non-parenthesized call", PM_ERROR_LEVEL_SYNTAX },
- [PM_ERR_ARGUMENT_IN] = { "unexpected `in` keyword in arguments", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_ARGUMENT_NO_FORWARDING_AMPERSAND] = { "unexpected `&`; no anonymous block parameter", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_ARGUMENT_NO_FORWARDING_ELLIPSES] = { "unexpected ... when the parent method is not forwarding", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_ARGUMENT_NO_FORWARDING_STAR] = { "unexpected `*`; no anonymous rest parameter", PM_ERROR_LEVEL_SYNTAX },
@@ -113,7 +112,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
[PM_ERR_ARRAY_EXPRESSION] = { "expected an expression for the array element", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_ARRAY_EXPRESSION_AFTER_STAR] = { "expected an expression after `*` in the array", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_ARRAY_SEPARATOR] = { "unexpected %s; expected a `,` separator for the array elements", PM_ERROR_LEVEL_SYNTAX },
- [PM_ERR_ARRAY_TERM] = { "expected a `]` to close the array", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_ARRAY_TERM] = { "unexpected %s; expected a `]` to close the array", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_BEGIN_LONELY_ELSE] = { "unexpected `else` in `begin` block; else without rescue is useless", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_BEGIN_TERM] = { "expected an `end` to close the `begin` statement", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_BEGIN_UPCASE_BRACE] = { "expected a `{` after `BEGIN`", PM_ERROR_LEVEL_SYNTAX },
@@ -145,6 +144,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
[PM_ERR_CONDITIONAL_WHILE_PREDICATE] = { "expected a predicate expression for the `while` statement", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_CONSTANT_PATH_COLON_COLON_CONSTANT] = { "expected a constant after the `::` operator", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_DEF_ENDLESS] = { "could not parse the endless method body", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_DEF_ENDLESS_PARAMETERS] = { "could not parse the endless method parameters", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_DEF_ENDLESS_SETTER] = { "invalid method name; a setter method cannot be defined in an endless method definition", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_DEF_NAME] = { "unexpected %s; expected a method name", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_DEF_PARAMS_TERM] = { "expected a delimiter to close the parameters", PM_ERROR_LEVEL_SYNTAX },
@@ -165,10 +165,12 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
[PM_ERR_ESCAPE_INVALID_META_REPEAT] = { "invalid meta escape sequence; meta cannot be repeated", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_ESCAPE_INVALID_UNICODE] = { "invalid Unicode escape sequence", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_ESCAPE_INVALID_UNICODE_CM_FLAGS] = { "invalid Unicode escape sequence; Unicode cannot be combined with control or meta flags", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_ESCAPE_INVALID_UNICODE_LIST] = { "invalid Unicode list: %.*s", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_ESCAPE_INVALID_UNICODE_LITERAL] = { "invalid Unicode escape sequence; Multiple codepoints at single character literal are disallowed", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_ESCAPE_INVALID_UNICODE_LONG] = { "invalid Unicode escape sequence; maximum length is 6 digits", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_ESCAPE_INVALID_UNICODE_SHORT] = { "too short escape sequence: %.*s", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_ESCAPE_INVALID_UNICODE_TERM] = { "unterminated Unicode escape", PM_ERROR_LEVEL_SYNTAX },
- [PM_ERR_EXPECT_ARGUMENT] = { "expected an argument", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_EXPECT_ARGUMENT] = { "unexpected %s; expected an argument", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPECT_EOL_AFTER_STATEMENT] = { "unexpected %s, expecting end-of-input", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPECT_EXPRESSION_AFTER_AMPAMPEQ] = { "expected an expression after `&&=`", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPECT_EXPRESSION_AFTER_PIPEPIPEEQ] = { "expected an expression after `||=`", PM_ERROR_LEVEL_SYNTAX },
@@ -180,14 +182,18 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
[PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT] = { "expected an expression after `*` splat in an argument", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPECT_EXPRESSION_AFTER_SPLAT_HASH] = { "expected an expression after `**` in a hash", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPECT_EXPRESSION_AFTER_STAR] = { "expected an expression after `*`", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_EXPECT_FOR_DELIMITER] = { "unexpected %s; expected a 'do', newline, or ';' after the 'for' loop collection", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPECT_IDENT_REQ_PARAMETER] = { "expected an identifier for the required parameter", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPECT_IN_DELIMITER] = { "expected a delimiter after the patterns of an `in` clause", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_EXPECT_LPAREN_AFTER_NOT_LPAREN] = { "expected a `(` immediately after `not`", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_EXPECT_LPAREN_AFTER_NOT_OTHER] = { "expected a `(` after `not`", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPECT_LPAREN_REQ_PARAMETER] = { "expected a `(` to start a required parameter", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPECT_MESSAGE] = { "unexpected %s; expecting a message to send to the receiver", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPECT_RBRACKET] = { "expected a matching `]`", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPECT_RPAREN] = { "expected a matching `)`", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPECT_RPAREN_AFTER_MULTI] = { "expected a `)` after multiple assignment", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPECT_RPAREN_REQ_PARAMETER] = { "expected a `)` to end a required parameter", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_EXPECT_SINGLETON_CLASS_DELIMITER] = { "unexpected %s; expected a newline or a ';' after the singleton class", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPECT_STRING_CONTENT] = { "expected string content after opening string delimiter", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPECT_WHEN_DELIMITER] = { "expected a delimiter after the predicates of a `when` clause", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_EXPRESSION_BARE_HASH] = { "unexpected bare hash in expression", PM_ERROR_LEVEL_SYNTAX },
@@ -220,6 +226,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
[PM_ERR_INCOMPLETE_VARIABLE_INSTANCE] = { "'%.*s' is not allowed as an instance variable name", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_INSTANCE_VARIABLE_BARE] = { "'@' without identifiers is not allowed as an instance variable name", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_INVALID_BLOCK_EXIT] = { "Invalid %s", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_INVALID_COMMA] = { "invalid comma", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_INVALID_ESCAPE_CHARACTER] = { "Invalid escape character syntax", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_INVALID_FLOAT_EXPONENT] = { "invalid exponent", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_INVALID_LOCAL_VARIABLE_READ] = { "identifier %.*s is not valid to get", PM_ERROR_LEVEL_SYNTAX },
@@ -245,8 +252,8 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
[PM_ERR_INVALID_VARIABLE_GLOBAL_3_3] = { "`%.*s' is not allowed as a global variable name", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_INVALID_VARIABLE_GLOBAL] = { "'%.*s' is not allowed as a global variable name", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_INVALID_YIELD] = { "Invalid yield", PM_ERROR_LEVEL_SYNTAX },
- [PM_ERR_IT_NOT_ALLOWED_NUMBERED] = { "`it` is not allowed when a numbered parameter is already used", PM_ERROR_LEVEL_SYNTAX },
- [PM_ERR_IT_NOT_ALLOWED_ORDINARY] = { "`it` is not allowed when an ordinary parameter is defined", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_IT_NOT_ALLOWED_NUMBERED] = { "'it' is not allowed when a numbered parameter is already used", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_IT_NOT_ALLOWED_ORDINARY] = { "'it' is not allowed when an ordinary parameter is defined", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_LAMBDA_OPEN] = { "expected a `do` keyword or a `{` to open the lambda block", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_LAMBDA_TERM_BRACE] = { "expected a lambda block beginning with `{` to end with `}`", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_LAMBDA_TERM_END] = { "expected a lambda block beginning with `do` to end with `end`", PM_ERROR_LEVEL_SYNTAX },
@@ -265,8 +272,10 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
[PM_ERR_MODULE_TERM] = { "expected an `end` to close the `module` statement", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_MULTI_ASSIGN_MULTI_SPLATS] = { "multiple splats in multiple assignment", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_MULTI_ASSIGN_UNEXPECTED_REST] = { "unexpected '%.*s' resulting in multiple splats in multiple assignment", PM_ERROR_LEVEL_SYNTAX },
- [PM_ERR_NOT_EXPRESSION] = { "expected an expression after `not`", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_NESTING_TOO_DEEP] = { "nesting too deep", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_NO_LOCAL_VARIABLE] = { "%.*s: no such local variable", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_NON_ASSOCIATIVE_OPERATOR] = { "unexpected %s; %s is a non-associative operator", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_NOT_EXPRESSION] = { "expected an expression after `not`", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_NUMBER_LITERAL_UNDERSCORE] = { "number literal ending with a `_`", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_NUMBERED_PARAMETER_INNER_BLOCK] = { "numbered parameter is already used in inner block", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_NUMBERED_PARAMETER_IT] = { "numbered parameters are not allowed when 'it' is already used", PM_ERROR_LEVEL_SYNTAX },
@@ -290,7 +299,9 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
[PM_ERR_PARAMETER_UNEXPECTED_FWD] = { "unexpected `...` in parameters", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PARAMETER_WILD_LOOSE_COMMA] = { "unexpected `,` in parameters", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PARAMETER_UNEXPECTED_NO_KW] = { "unexpected **nil; no keywords marker disallowed after keywords", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_PATTERN_ARRAY_MULTIPLE_RESTS] = { "unexpected multiple '*' rest patterns in an array pattern", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PATTERN_CAPTURE_DUPLICATE] = { "duplicated variable name", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_PATTERN_CAPTURE_IN_ALTERNATIVE] = { "variable capture in alternative pattern", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PATTERN_EXPRESSION_AFTER_BRACKET] = { "expected a pattern expression after the `[` operator", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PATTERN_EXPRESSION_AFTER_COMMA] = { "expected a pattern expression after `,`", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PATTERN_EXPRESSION_AFTER_HROCKET] = { "expected a pattern expression after `=>`", PM_ERROR_LEVEL_SYNTAX },
@@ -301,6 +312,7 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
[PM_ERR_PATTERN_EXPRESSION_AFTER_PIPE] = { "expected a pattern expression after the `|` operator", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PATTERN_EXPRESSION_AFTER_RANGE] = { "expected a pattern expression after the range operator", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PATTERN_EXPRESSION_AFTER_REST] = { "unexpected pattern expression after the `**` expression", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_PATTERN_FIND_MISSING_INNER] = { "find patterns need at least one required inner pattern", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PATTERN_HASH_IMPLICIT] = { "unexpected implicit hash in pattern; use '{' to delineate", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PATTERN_HASH_KEY] = { "unexpected %s; expected a key in the hash pattern", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_PATTERN_HASH_KEY_DUPLICATE] = { "duplicated key name", PM_ERROR_LEVEL_SYNTAX },
@@ -318,7 +330,8 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
[PM_ERR_REGEXP_INCOMPAT_CHAR_ENCODING] = { "incompatible character encoding: /%.*s/", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_REGEXP_NON_ESCAPED_MBC] = { "/.../n has a non escaped non ASCII character in non ASCII-8BIT script: /%.*s/", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_REGEXP_INVALID_UNICODE_RANGE] = { "invalid Unicode range: /%.*s/", PM_ERROR_LEVEL_SYNTAX },
- [PM_ERR_REGEXP_UNKNOWN_OPTIONS] = { "unknown regexp %s: %.*s", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_REGEXP_PARSE_ERROR] = { "%s", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_REGEXP_UNKNOWN_OPTIONS] = { "unknown regexp %s - %.*s", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_REGEXP_TERM] = { "unterminated regexp meets end of file; expected a closing delimiter", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_REGEXP_UTF8_CHAR_NON_UTF8_REGEXP] = { "UTF-8 character in non UTF-8 regexp: /%s/", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_RESCUE_EXPRESSION] = { "expected a rescued expression", PM_ERROR_LEVEL_SYNTAX },
@@ -341,11 +354,16 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
[PM_ERR_TERNARY_COLON] = { "expected a `:` after the true expression of a ternary operator", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_TERNARY_EXPRESSION_FALSE] = { "expected an expression after `:` in the ternary operator", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_TERNARY_EXPRESSION_TRUE] = { "expected an expression after `?` in the ternary operator", PM_ERROR_LEVEL_SYNTAX },
- [PM_ERR_UNDEF_ARGUMENT] = { "invalid argument being passed to `undef`; expected a bare word, constant, or symbol argument", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_UNARY_RECEIVER] = { "unexpected %s, expected a receiver for unary `%c`", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_UNARY_DISALLOWED] = { "unexpected %s; unary calls are not allowed in this context", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_UNDEF_ARGUMENT] = { "invalid argument being passed to `undef`; expected a bare word, constant, or symbol argument", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_UNEXPECTED_BLOCK_ARGUMENT] = { "block argument should not be given", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_UNEXPECTED_INDEX_BLOCK] = { "unexpected block arg given in index assignment; blocks are not allowed in index assignment expressions", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_UNEXPECTED_INDEX_KEYWORDS] = { "unexpected keyword arg given in index assignment; keywords are not allowed in index assignment expressions", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_UNEXPECTED_LABEL] = { "unexpected label", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_UNEXPECTED_MULTI_WRITE] = { "unexpected multiple assignment; multiple assignment is not allowed in this context", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_UNEXPECTED_PARAMETER_DEFAULT_VALUE] = { "unexpected %s; expected a default value for a parameter", PM_ERROR_LEVEL_SYNTAX },
+ [PM_ERR_UNEXPECTED_RANGE_OPERATOR] = { "unexpected range operator; .. and ... are non-associative and cannot be chained", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_UNEXPECTED_SAFE_NAVIGATION] = { "&. inside multiple assignment destination", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_UNEXPECTED_TOKEN_CLOSE_CONTEXT] = { "unexpected %s, assuming it is closing the parent %s", PM_ERROR_LEVEL_SYNTAX },
[PM_ERR_UNEXPECTED_TOKEN_IGNORE] = { "unexpected %s, ignoring it", PM_ERROR_LEVEL_SYNTAX },
@@ -374,9 +392,10 @@ static const pm_diagnostic_data_t diagnostic_messages[PM_DIAGNOSTIC_ID_MAX] = {
[PM_WARN_END_IN_METHOD] = { "END in method; use at_exit", PM_WARNING_LEVEL_DEFAULT },
[PM_WARN_FLOAT_OUT_OF_RANGE] = { "Float %.*s%s out of range", PM_WARNING_LEVEL_VERBOSE },
[PM_WARN_IGNORED_FROZEN_STRING_LITERAL] = { "'frozen_string_literal' is ignored after any tokens", PM_WARNING_LEVEL_VERBOSE },
+ [PM_WARN_INDENTATION_MISMATCH] = { "mismatched indentations at '%.*s' with '%.*s' at %" PRIi32, PM_WARNING_LEVEL_VERBOSE },
[PM_WARN_INTEGER_IN_FLIP_FLOP] = { "integer literal in flip-flop", PM_WARNING_LEVEL_DEFAULT },
[PM_WARN_INVALID_CHARACTER] = { "invalid character syntax; use %s%s%s", PM_WARNING_LEVEL_DEFAULT },
- [PM_WARN_INVALID_SHAREABLE_CONSTANT_VALUE] = { "invalid value for shareable_constant_value: %.*s", PM_WARNING_LEVEL_VERBOSE },
+ [PM_WARN_INVALID_MAGIC_COMMENT_VALUE] = { "invalid value for %.*s: %.*s", PM_WARNING_LEVEL_VERBOSE },
[PM_WARN_INVALID_NUMBERED_REFERENCE] = { "'%.*s' is too big for a number variable, always nil", PM_WARNING_LEVEL_DEFAULT },
[PM_WARN_KEYWORD_EOL] = { "`%.*s` at the end of line without an expression", PM_WARNING_LEVEL_VERBOSE },
[PM_WARN_LITERAL_IN_CONDITION_DEFAULT] = { "%sliteral in %s", PM_WARNING_LEVEL_DEFAULT },
diff --git a/prism/templates/src/node.c.erb b/prism/templates/src/node.c.erb
index deb2ea49fc..2357e55200 100644
--- a/prism/templates/src/node.c.erb
+++ b/prism/templates/src/node.c.erb
@@ -1,4 +1,4 @@
-#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>"
+#line <%= __LINE__ + 1 %> "prism/templates/src/<%= File.basename(__FILE__) %>"
#include "prism/node.h"
/**
@@ -106,14 +106,14 @@ PRISM_EXPORTED_FUNCTION void
pm_node_destroy(pm_parser_t *parser, pm_node_t *node) {
switch (PM_NODE_TYPE(node)) {
<%- nodes.each do |node| -%>
-#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>"
+#line <%= __LINE__ + 1 %> "prism/templates/src/<%= File.basename(__FILE__) %>"
case <%= node.type %>: {
- <%- if node.fields.any? { |field| ![Prism::Template::LocationField, Prism::Template::OptionalLocationField, Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::FlagsField, Prism::Template::ConstantField, Prism::Template::OptionalConstantField, Prism::Template::DoubleField].include?(field.class) } -%>
+ <%- if node.fields.any? { |field| ![Prism::Template::LocationField, Prism::Template::OptionalLocationField, Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::ConstantField, Prism::Template::OptionalConstantField, Prism::Template::DoubleField].include?(field.class) } -%>
pm_<%= node.human %>_t *cast = (pm_<%= node.human %>_t *) node;
<%- end -%>
<%- node.fields.each do |field| -%>
<%- case field -%>
- <%- when Prism::Template::LocationField, Prism::Template::OptionalLocationField, Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::FlagsField, Prism::Template::ConstantField, Prism::Template::OptionalConstantField, Prism::Template::DoubleField -%>
+ <%- when Prism::Template::LocationField, Prism::Template::OptionalLocationField, Prism::Template::UInt8Field, Prism::Template::UInt32Field, Prism::Template::ConstantField, Prism::Template::OptionalConstantField, Prism::Template::DoubleField -%>
<%- when Prism::Template::NodeField -%>
pm_node_destroy(parser, (pm_node_t *)cast-><%= field.name %>);
<%- when Prism::Template::OptionalNodeField -%>
@@ -135,7 +135,7 @@ pm_node_destroy(pm_parser_t *parser, pm_node_t *node) {
break;
}
<%- end -%>
-#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>"
+#line <%= __LINE__ + 1 %> "prism/templates/src/<%= File.basename(__FILE__) %>"
default:
assert(false && "unreachable");
break;
@@ -244,7 +244,7 @@ pm_dump_json(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *no
const pm_<%= node.human %>_t *cast = (const pm_<%= node.human %>_t *) node;
pm_dump_json_location(buffer, parser, &cast->base.location);
- <%- node.fields.each_with_index do |field, index| -%>
+ <%- [*node.flags, *node.fields].each_with_index do |field, index| -%>
// Dump the <%= field.name %> field
pm_buffer_append_byte(buffer, ',');
@@ -301,12 +301,11 @@ pm_dump_json(pm_buffer_t *buffer, const pm_parser_t *parser, const pm_node_t *no
pm_buffer_append_format(buffer, "%" PRIu8, cast-><%= field.name %>);
<%- when Prism::Template::UInt32Field -%>
pm_buffer_append_format(buffer, "%" PRIu32, cast-><%= field.name %>);
- <%- when Prism::Template::FlagsField -%>
+ <%- when Prism::Template::Flags -%>
size_t flags = 0;
pm_buffer_append_byte(buffer, '[');
- <%- found = flags.find { |flag| flag.name == field.kind }.tap { |found| raise "Expected to find #{field.kind}" unless found } -%>
- <%- found.values.each_with_index do |value, index| -%>
- if (PM_NODE_FLAG_P(cast, PM_<%= found.human.upcase %>_<%= value.name %>)) {
+ <%- node.flags.values.each_with_index do |value, index| -%>
+ if (PM_NODE_FLAG_P(cast, PM_<%= node.flags.human.upcase %>_<%= value.name %>)) {
if (flags != 0) pm_buffer_append_byte(buffer, ',');
pm_buffer_append_string(buffer, "\"<%= value.name %>\"", <%= value.name.bytesize + 2 %>);
flags++;
diff --git a/prism/templates/src/prettyprint.c.erb b/prism/templates/src/prettyprint.c.erb
index 27f44cd996..639c2fecf3 100644
--- a/prism/templates/src/prettyprint.c.erb
+++ b/prism/templates/src/prettyprint.c.erb
@@ -31,14 +31,14 @@ prettyprint_node(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm
return;
<%- nodes.each do |node| -%>
case <%= node.type %>: {
- <%- if node.fields.any? -%>
+ <%- if !node.flags.nil? || node.fields.any? -%>
pm_<%= node.human %>_t *cast = (pm_<%= node.human %>_t *) node;
<%- end -%>
pm_buffer_append_string(output_buffer, "@ <%= node.name %> (location: ", <%= node.name.length + 14 %>);
prettyprint_location(output_buffer, parser, &node->location);
pm_buffer_append_string(output_buffer, ")\n", 2);
- <%- node.fields.each_with_index do |field, index| -%>
- <%- preadd = index == node.fields.length - 1 ? " " : "| " -%>
+ <%- (fields = [*node.flags, *node.fields]).each_with_index do |field, index| -%>
+ <%- preadd = index == fields.length - 1 ? " " : "| " -%>
// <%= field.name %>
{
@@ -123,11 +123,10 @@ prettyprint_node(pm_buffer_t *output_buffer, const pm_parser_t *parser, const pm
pm_buffer_append_format(output_buffer, " %" PRIu8 "\n", cast-><%= field.name %>);
<%- when Prism::Template::UInt32Field -%>
pm_buffer_append_format(output_buffer, " %" PRIu32 "\n", cast-><%= field.name %>);
- <%- when Prism::Template::FlagsField -%>
+ <%- when Prism::Template::Flags -%>
bool found = false;
- <%- found = flags.find { |flag| flag.name == field.kind }.tap { |found| raise "Expected to find #{field.kind}" unless found } -%>
- <%- found.values.each do |value| -%>
- if (cast->base.<%= field.name %> & PM_<%= found.human.upcase %>_<%= value.name %>) {
+ <%- field.values.each do |value| -%>
+ if (cast->base.flags & PM_<%= field.human.upcase %>_<%= value.name %>) {
if (found) pm_buffer_append_byte(output_buffer, ',');
pm_buffer_append_string(output_buffer, " <%= value.name.downcase %>", <%= value.name.bytesize + 1 %>);
found = true;
diff --git a/prism/templates/src/serialize.c.erb b/prism/templates/src/serialize.c.erb
index 97101e36d5..0f0aace445 100644
--- a/prism/templates/src/serialize.c.erb
+++ b/prism/templates/src/serialize.c.erb
@@ -74,6 +74,9 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) {
size_t offset = buffer->length;
+ <%- if Prism::Template::INCLUDE_NODE_ID -%>
+ pm_buffer_append_varuint(buffer, node->node_id);
+ <%- end -%>
pm_serialize_location(parser, &node->location, buffer);
switch (PM_NODE_TYPE(node)) {
@@ -89,6 +92,9 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) {
size_t length_offset = buffer->length;
pm_buffer_append_string(buffer, "\0\0\0\0", 4); /* consume 4 bytes, updated below */
<%- end -%>
+ <%- unless Prism::Template::SERIALIZE_ONLY_SEMANTICS_FIELDS && !node.flags -%>
+ pm_buffer_append_varuint(buffer, (uint32_t) node->flags);
+ <%- end -%>
<%- node.fields.each do |field| -%>
<%- case field -%>
<%- when Prism::Template::NodeField -%>
@@ -132,8 +138,6 @@ pm_serialize_node(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer) {
pm_buffer_append_byte(buffer, ((pm_<%= node.human %>_t *)node)-><%= field.name %>);
<%- when Prism::Template::UInt32Field -%>
pm_buffer_append_varuint(buffer, ((pm_<%= node.human %>_t *)node)-><%= field.name %>);
- <%- when Prism::Template::FlagsField -%>
- pm_buffer_append_varuint(buffer, (uint32_t)(node->flags & ~PM_NODE_FLAG_COMMON_MASK));
<%- when Prism::Template::IntegerField -%>
pm_serialize_integer(&((pm_<%= node.human %>_t *)node)-><%= field.name %>, buffer);
<%- when Prism::Template::DoubleField -%>
@@ -267,7 +271,7 @@ pm_serialize_metadata(pm_parser_t *parser, pm_buffer_t *buffer) {
pm_serialize_diagnostic_list(parser, &parser->warning_list, buffer);
}
-#line <%= __LINE__ + 1 %> "<%= File.basename(__FILE__) %>"
+#line <%= __LINE__ + 1 %> "prism/templates/src/<%= File.basename(__FILE__) %>"
/**
* Serialize the metadata, nodes, and constant pool.
*/
@@ -311,7 +315,7 @@ pm_serialize_content(pm_parser_t *parser, pm_node_t *node, pm_buffer_t *buffer)
// buffer offset. We will add a leading 1 to indicate that this
// is a buffer offset.
uint32_t content_offset = pm_sizet_to_u32(buffer->length);
- uint32_t owned_mask = (uint32_t) (1 << 31);
+ uint32_t owned_mask = 1U << 31;
assert(content_offset < owned_mask);
content_offset |= owned_mask;
diff --git a/prism/templates/template.rb b/prism/templates/template.rb
index 6f79a85371..6c3efd7e6c 100755
--- a/prism/templates/template.rb
+++ b/prism/templates/template.rb
@@ -1,5 +1,5 @@
#!/usr/bin/env ruby
-# typed: false
+# typed: ignore
require "erb"
require "fileutils"
@@ -8,10 +8,14 @@ require "yaml"
module Prism
module Template
SERIALIZE_ONLY_SEMANTICS_FIELDS = ENV.fetch("PRISM_SERIALIZE_ONLY_SEMANTICS_FIELDS", false)
+ REMOVE_ON_ERROR_TYPES = SERIALIZE_ONLY_SEMANTICS_FIELDS
CHECK_FIELD_KIND = ENV.fetch("CHECK_FIELD_KIND", false)
JAVA_BACKEND = ENV["PRISM_JAVA_BACKEND"] || "truffleruby"
JAVA_STRING_TYPE = JAVA_BACKEND == "jruby" ? "org.jruby.RubySymbol" : "String"
+ INCLUDE_NODE_ID = !SERIALIZE_ONLY_SEMANTICS_FIELDS || JAVA_BACKEND == "jruby"
+
+ COMMON_FLAGS_COUNT = 2
class Error
attr_reader :name
@@ -93,6 +97,11 @@ module Prism
# Some node fields can be specialized if they point to a specific kind of
# node and not just a generic node.
class NodeKindField < Field
+ def initialize(kind:, **options)
+ @kind = kind
+ super(**options)
+ end
+
def c_type
if specific_kind
"pm_#{specific_kind.gsub(/(?<=.)[A-Z]/, "_\\0").downcase}"
@@ -111,18 +120,18 @@ module Prism
def java_cast
if specific_kind
- "(Nodes.#{options[:kind]}) "
+ "(Nodes.#{@kind}) "
else
""
end
end
def specific_kind
- options[:kind] unless options[:kind].is_a?(Array)
+ @kind unless @kind.is_a?(Array)
end
def union_kind
- options[:kind] if options[:kind].is_a?(Array)
+ @kind if @kind.is_a?(Array)
end
end
@@ -357,27 +366,6 @@ module Prism
end
end
- # This represents a set of flags. It is very similar to the UInt32Field, but
- # can be directly embedded into the flags field on the struct and provides
- # convenient methods for checking if a flag is set.
- class FlagsField < Field
- def rbs_class
- "Integer"
- end
-
- def rbi_class
- "Integer"
- end
-
- def java_type
- "short"
- end
-
- def kind
- options.fetch(:kind)
- end
- end
-
# This represents an arbitrarily-sized integer. When it gets to Ruby it will
# be an Integer.
class IntegerField < Field
@@ -414,9 +402,9 @@ module Prism
# in YAML format. It contains information about the name of the node and the
# various child nodes it contains.
class NodeType
- attr_reader :name, :type, :human, :fields, :newline, :comment
+ attr_reader :name, :type, :human, :flags, :fields, :newline, :comment
- def initialize(config)
+ def initialize(config, flags)
@name = config.fetch("name")
type = @name.gsub(/(?<=.)[A-Z]/, "_\\0")
@@ -430,13 +418,42 @@ module Prism
options = field.transform_keys(&:to_sym)
options.delete(:type)
- # If/when we have documentation on every field, this should be changed
- # to use fetch instead of delete.
+ # If/when we have documentation on every field, this should be
+ # changed to use fetch instead of delete.
comment = options.delete(:comment)
+ if kinds = options[:kind]
+ kinds = [kinds] unless kinds.is_a?(Array)
+ kinds = kinds.map do |kind|
+ case kind
+ when "non-void expression"
+ # the actual list of types would be way too long
+ "Node"
+ when "pattern expression"
+ # the list of all possible types is too long with 37+ different classes
+ "Node"
+ when Hash
+ kind = kind.fetch("on error")
+ REMOVE_ON_ERROR_TYPES ? nil : kind
+ else
+ kind
+ end
+ end.compact
+ if kinds.size == 1
+ kinds = kinds.first
+ kinds = nil if kinds == "Node"
+ end
+ options[:kind] = kinds
+ else
+ if type < NodeKindField
+ raise "Missing kind in config.yml for field #{@name}##{options.fetch(:name)}"
+ end
+ end
+
type.new(comment: comment, **options)
end
+ @flags = config.key?("flags") ? flags.fetch(config.fetch("flags")) : nil
@newline = config.fetch("newline", true)
@comment = config.fetch("comment")
end
@@ -474,7 +491,6 @@ module Prism
when "location?" then OptionalLocationField
when "uint8" then UInt8Field
when "uint32" then UInt32Field
- when "flags" then FlagsField
when "integer" then IntegerField
when "double" then DoubleField
else raise("Unknown field type: #{name.inspect}")
@@ -514,6 +530,10 @@ module Prism
@values = config.fetch("values").map { |flag| Flag.new(flag) }
@comment = config.fetch("comment")
end
+
+ def self.empty
+ new("name" => "", "values" => [], "comment" => "")
+ end
end
class << self
@@ -531,11 +551,14 @@ module Prism
when ".rb"
<<~HEADING
# frozen_string_literal: true
+ # :markup: markdown
=begin
+ --
This file is generated by the templates/template.rb script and should not be
modified manually. See #{filepath}
if you are looking to modify the template
+ ++
=end
HEADING
@@ -559,13 +582,15 @@ module Prism
HEADING
else
<<~HEADING
- /******************************************************************************/
+ /* :markup: markdown */
+
+ /*----------------------------------------------------------------------------*/
/* This file is generated by the templates/template.rb script and should not */
/* be modified manually. See */
- /* #{filepath + " " * (74 - filepath.size) } */
+ /* #{filepath.ljust(74)} */
/* if you are looking to modify the */
/* template */
- /******************************************************************************/
+ /*----------------------------------------------------------------------------*/
HEADING
end
@@ -603,13 +628,14 @@ module Prism
@locals ||=
begin
config = YAML.load_file(File.expand_path("../config.yml", __dir__))
+ flags = config.fetch("flags").to_h { |flags| [flags["name"], Flags.new(flags)] }
{
errors: config.fetch("errors").map { |name| Error.new(name) },
warnings: config.fetch("warnings").map { |name| Warning.new(name) },
- nodes: config.fetch("nodes").map { |node| NodeType.new(node) }.sort_by(&:name),
+ nodes: config.fetch("nodes").map { |node| NodeType.new(node, flags) }.sort_by(&:name),
tokens: config.fetch("tokens").map { |token| Token.new(token) },
- flags: config.fetch("flags").map { |flags| Flags.new(flags) }
+ flags: flags.values
}
end
end
@@ -640,6 +666,7 @@ module Prism
"src/prettyprint.c",
"src/serialize.c",
"src/token_type.c",
+ "rbi/prism/dsl.rbi",
"rbi/prism/node.rbi",
"rbi/prism/visitor.rbi",
"sig/prism.rbs",
diff --git a/prism/util/pm_buffer.c b/prism/util/pm_buffer.c
index 1e79e46718..2136a7c43e 100644
--- a/prism/util/pm_buffer.c
+++ b/prism/util/pm_buffer.c
@@ -173,6 +173,46 @@ pm_buffer_append_double(pm_buffer_t *buffer, double value) {
}
/**
+ * Append a unicode codepoint to the buffer.
+ */
+bool
+pm_buffer_append_unicode_codepoint(pm_buffer_t *buffer, uint32_t value) {
+ if (value <= 0x7F) {
+ pm_buffer_append_byte(buffer, (uint8_t) value); // 0xxxxxxx
+ return true;
+ } else if (value <= 0x7FF) {
+ uint8_t bytes[] = {
+ (uint8_t) (0xC0 | ((value >> 6) & 0x3F)), // 110xxxxx
+ (uint8_t) (0x80 | (value & 0x3F)) // 10xxxxxx
+ };
+
+ pm_buffer_append_bytes(buffer, bytes, 2);
+ return true;
+ } else if (value <= 0xFFFF) {
+ uint8_t bytes[] = {
+ (uint8_t) (0xE0 | ((value >> 12) & 0x3F)), // 1110xxxx
+ (uint8_t) (0x80 | ((value >> 6) & 0x3F)), // 10xxxxxx
+ (uint8_t) (0x80 | (value & 0x3F)) // 10xxxxxx
+ };
+
+ pm_buffer_append_bytes(buffer, bytes, 3);
+ return true;
+ } else if (value <= 0x10FFFF) {
+ uint8_t bytes[] = {
+ (uint8_t) (0xF0 | ((value >> 18) & 0x3F)), // 11110xxx
+ (uint8_t) (0x80 | ((value >> 12) & 0x3F)), // 10xxxxxx
+ (uint8_t) (0x80 | ((value >> 6) & 0x3F)), // 10xxxxxx
+ (uint8_t) (0x80 | (value & 0x3F)) // 10xxxxxx
+ };
+
+ pm_buffer_append_bytes(buffer, bytes, 4);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/**
* Append a slice of source code to the buffer.
*/
void
diff --git a/prism/util/pm_buffer.h b/prism/util/pm_buffer.h
index 58f7b506cf..cb80f8b3ce 100644
--- a/prism/util/pm_buffer.h
+++ b/prism/util/pm_buffer.h
@@ -51,6 +51,8 @@ bool pm_buffer_init_capacity(pm_buffer_t *buffer, size_t capacity);
*
* @param buffer The buffer to initialize.
* @returns True if the buffer was initialized successfully, false otherwise.
+ *
+ * \public \memberof pm_buffer_t
*/
PRISM_EXPORTED_FUNCTION bool pm_buffer_init(pm_buffer_t *buffer);
@@ -59,6 +61,8 @@ PRISM_EXPORTED_FUNCTION bool pm_buffer_init(pm_buffer_t *buffer);
*
* @param buffer The buffer to get the value of.
* @returns The value of the buffer.
+ *
+ * \public \memberof pm_buffer_t
*/
PRISM_EXPORTED_FUNCTION char * pm_buffer_value(const pm_buffer_t *buffer);
@@ -67,6 +71,8 @@ PRISM_EXPORTED_FUNCTION char * pm_buffer_value(const pm_buffer_t *buffer);
*
* @param buffer The buffer to get the length of.
* @returns The length of the buffer.
+ *
+ * \public \memberof pm_buffer_t
*/
PRISM_EXPORTED_FUNCTION size_t pm_buffer_length(const pm_buffer_t *buffer);
@@ -138,6 +144,16 @@ void pm_buffer_append_varsint(pm_buffer_t *buffer, int32_t value);
void pm_buffer_append_double(pm_buffer_t *buffer, double value);
/**
+ * Append a unicode codepoint to the buffer.
+ *
+ * @param buffer The buffer to append to.
+ * @param value The character to append.
+ * @returns True if the codepoint was valid and appended successfully, false
+ * otherwise.
+ */
+bool pm_buffer_append_unicode_codepoint(pm_buffer_t *buffer, uint32_t value);
+
+/**
* The different types of escaping that can be performed by the buffer when
* appending a slice of Ruby source code.
*/
@@ -212,6 +228,8 @@ void pm_buffer_insert(pm_buffer_t *buffer, size_t index, const char *value, size
* Free the memory associated with the buffer.
*
* @param buffer The buffer to free.
+ *
+ * \public \memberof pm_buffer_t
*/
PRISM_EXPORTED_FUNCTION void pm_buffer_free(pm_buffer_t *buffer);
diff --git a/prism/util/pm_char.c b/prism/util/pm_char.c
index dce19abd1b..a51dc11645 100644
--- a/prism/util/pm_char.c
+++ b/prism/util/pm_char.c
@@ -185,7 +185,7 @@ pm_strspn_number_kind_underscores(const uint8_t *string, ptrdiff_t length, const
size++;
}
- if (string[size - 1] == '_') *invalid = string + size - 1;
+ if (size > 0 && string[size - 1] == '_') *invalid = string + size - 1;
return size;
}
diff --git a/prism/util/pm_constant_pool.c b/prism/util/pm_constant_pool.c
index 624002cec9..922ce6a18c 100644
--- a/prism/util/pm_constant_pool.c
+++ b/prism/util/pm_constant_pool.c
@@ -15,8 +15,12 @@ pm_constant_id_list_init(pm_constant_id_list_t *list) {
*/
void
pm_constant_id_list_init_capacity(pm_constant_id_list_t *list, size_t capacity) {
- list->ids = xcalloc(capacity, sizeof(pm_constant_id_t));
- if (list->ids == NULL) abort();
+ if (capacity) {
+ list->ids = xcalloc(capacity, sizeof(pm_constant_id_t));
+ if (list->ids == NULL) abort();
+ } else {
+ list->ids = NULL;
+ }
list->size = 0;
list->capacity = capacity;
@@ -260,7 +264,7 @@ pm_constant_pool_insert(pm_constant_pool_t *pool, const uint8_t *start, size_t l
// constant and replace it with the shared constant.
xfree((void *) constant->start);
constant->start = start;
- bucket->type = (unsigned int) (PM_CONSTANT_POOL_BUCKET_DEFAULT & 0x3);
+ bucket->type = (unsigned int) (type & 0x3);
}
return bucket->id;
diff --git a/prism/util/pm_integer.c b/prism/util/pm_integer.c
index 5b0f34465c..4170ecc58d 100644
--- a/prism/util/pm_integer.c
+++ b/prism/util/pm_integer.c
@@ -43,7 +43,7 @@ big_add(pm_integer_t *destination, pm_integer_t *left, pm_integer_t *right, uint
length++;
}
- *destination = (pm_integer_t) { 0, length, values, false };
+ *destination = (pm_integer_t) { length, values, 0, false };
}
/**
@@ -87,7 +87,7 @@ big_sub2(pm_integer_t *destination, pm_integer_t *a, pm_integer_t *b, pm_integer
}
while (a_length > 1 && values[a_length - 1] == 0) a_length--;
- *destination = (pm_integer_t) { 0, a_length, values, false };
+ *destination = (pm_integer_t) { a_length, values, 0, false };
}
/**
@@ -130,7 +130,7 @@ karatsuba_multiply(pm_integer_t *destination, pm_integer_t *left, pm_integer_t *
}
while (length > 1 && values[length - 1] == 0) length--;
- *destination = (pm_integer_t) { 0, length, values, false };
+ *destination = (pm_integer_t) { length, values, 0, false };
return;
}
@@ -142,16 +142,16 @@ karatsuba_multiply(pm_integer_t *destination, pm_integer_t *left, pm_integer_t *
if (end_offset > right_length) end_offset = right_length;
pm_integer_t sliced_left = {
- .value = 0,
.length = left_length,
.values = left_values,
+ .value = 0,
.negative = false
};
pm_integer_t sliced_right = {
- .value = 0,
.length = end_offset - start_offset,
.values = right_values + start_offset,
+ .value = 0,
.negative = false
};
@@ -169,15 +169,15 @@ karatsuba_multiply(pm_integer_t *destination, pm_integer_t *left, pm_integer_t *
pm_integer_free(&product);
}
- *destination = (pm_integer_t) { 0, left_length + right_length, values, false };
+ *destination = (pm_integer_t) { left_length + right_length, values, 0, false };
return;
}
size_t half = left_length / 2;
- pm_integer_t x0 = { 0, half, left_values, false };
- pm_integer_t x1 = { 0, left_length - half, left_values + half, false };
- pm_integer_t y0 = { 0, half, right_values, false };
- pm_integer_t y1 = { 0, right_length - half, right_values + half, false };
+ pm_integer_t x0 = { half, left_values, 0, false };
+ pm_integer_t x1 = { left_length - half, left_values + half, 0, false };
+ pm_integer_t y0 = { half, right_values, 0, false };
+ pm_integer_t y1 = { right_length - half, right_values + half, 0, false };
pm_integer_t z0 = { 0 };
karatsuba_multiply(&z0, &x0, &y0, base);
@@ -229,7 +229,7 @@ karatsuba_multiply(pm_integer_t *destination, pm_integer_t *left, pm_integer_t *
pm_integer_free(&y01);
pm_integer_free(&xy);
- *destination = (pm_integer_t) { 0, length, values, false };
+ *destination = (pm_integer_t) { length, values, 0, false };
}
/**
@@ -323,7 +323,7 @@ pm_integer_normalize(pm_integer_t *integer) {
bool negative = integer->negative && value != 0;
pm_integer_free(integer);
- *integer = (pm_integer_t) { .value = value, .length = 0, .values = NULL, .negative = negative };
+ *integer = (pm_integer_t) { .values = NULL, .value = value, .length = 0, .negative = negative };
}
/**
@@ -412,7 +412,7 @@ pm_integer_parse_powof2(pm_integer_t *integer, uint32_t base, const uint8_t *dig
}
while (length > 1 && values[length - 1] == 0) length--;
- *integer = (pm_integer_t) { .value = 0, .length = length, .values = values, .negative = false };
+ *integer = (pm_integer_t) { .length = length, .values = values, .value = 0, .negative = false };
pm_integer_normalize(integer);
}
@@ -438,7 +438,7 @@ pm_integer_parse_decimal(pm_integer_t *integer, const uint8_t *digits, size_t di
}
// Convert base from 10**9 to 1<<32.
- pm_integer_convert_base(integer, &((pm_integer_t) { .value = 0, .length = length, .values = values, .negative = false }), 1000000000, ((uint64_t) 1 << 32));
+ pm_integer_convert_base(integer, &((pm_integer_t) { .length = length, .values = values, .value = 0, .negative = false }), 1000000000, ((uint64_t) 1 << 32));
xfree(values);
}
diff --git a/prism/util/pm_integer.h b/prism/util/pm_integer.h
index 91b28ad2f3..304665e620 100644
--- a/prism/util/pm_integer.h
+++ b/prism/util/pm_integer.h
@@ -19,12 +19,6 @@
*/
typedef struct {
/**
- * Embedded value for small integer. This value is set to 0 if the value
- * does not fit into uint32_t.
- */
- uint32_t value;
-
- /**
* The number of allocated values. length is set to 0 if the integer fits
* into uint32_t.
*/
@@ -36,6 +30,12 @@ typedef struct {
uint32_t *values;
/**
+ * Embedded value for small integer. This value is set to 0 if the value
+ * does not fit into uint32_t.
+ */
+ uint32_t value;
+
+ /**
* Whether or not the integer is negative. It is stored this way so that a
* zeroed pm_integer_t is always positive zero.
*/
@@ -112,6 +112,8 @@ void pm_integers_reduce(pm_integer_t *numerator, pm_integer_t *denominator);
*
* @param buffer The buffer to append the string to.
* @param integer The integer to convert to a string.
+ *
+ * \public \memberof pm_integer_t
*/
PRISM_EXPORTED_FUNCTION void pm_integer_string(pm_buffer_t *buffer, const pm_integer_t *integer);
@@ -120,6 +122,8 @@ PRISM_EXPORTED_FUNCTION void pm_integer_string(pm_buffer_t *buffer, const pm_int
* the integer exceeds the size of a single node in the linked list.
*
* @param integer The integer to free.
+ *
+ * \public \memberof pm_integer_t
*/
PRISM_EXPORTED_FUNCTION void pm_integer_free(pm_integer_t *integer);
diff --git a/prism/util/pm_list.h b/prism/util/pm_list.h
index 3512dee979..f544bb2943 100644
--- a/prism/util/pm_list.h
+++ b/prism/util/pm_list.h
@@ -68,6 +68,8 @@ typedef struct {
*
* @param list The list to check.
* @return True if the given list is empty, otherwise false.
+ *
+ * \public \memberof pm_list_t
*/
PRISM_EXPORTED_FUNCTION bool pm_list_empty_p(pm_list_t *list);
@@ -76,6 +78,8 @@ PRISM_EXPORTED_FUNCTION bool pm_list_empty_p(pm_list_t *list);
*
* @param list The list to check.
* @return The size of the list.
+ *
+ * \public \memberof pm_list_t
*/
PRISM_EXPORTED_FUNCTION size_t pm_list_size(pm_list_t *list);
@@ -91,6 +95,8 @@ void pm_list_append(pm_list_t *list, pm_list_node_t *node);
* Deallocate the internal state of the given list.
*
* @param list The list to free.
+ *
+ * \public \memberof pm_list_t
*/
PRISM_EXPORTED_FUNCTION void pm_list_free(pm_list_t *list);
diff --git a/prism/util/pm_newline_list.c b/prism/util/pm_newline_list.c
index ce07ce8c8e..8331618f54 100644
--- a/prism/util/pm_newline_list.c
+++ b/prism/util/pm_newline_list.c
@@ -55,6 +55,35 @@ pm_newline_list_append(pm_newline_list_t *list, const uint8_t *cursor) {
}
/**
+ * Returns the line of the given offset. If the offset is not in the list, the
+ * line of the closest offset less than the given offset is returned.
+ */
+int32_t
+pm_newline_list_line(const pm_newline_list_t *list, const uint8_t *cursor, int32_t start_line) {
+ assert(cursor >= list->start);
+ size_t offset = (size_t) (cursor - list->start);
+
+ size_t left = 0;
+ size_t right = list->size - 1;
+
+ while (left <= right) {
+ size_t mid = left + (right - left) / 2;
+
+ if (list->offsets[mid] == offset) {
+ return ((int32_t) mid) + start_line;
+ }
+
+ if (list->offsets[mid] < offset) {
+ left = mid + 1;
+ } else {
+ right = mid - 1;
+ }
+ }
+
+ return ((int32_t) left) + start_line - 1;
+}
+
+/**
* Returns the line and column of the given offset. If the offset is not in the
* list, the line and column of the closest offset less than the given offset
* are returned.
diff --git a/prism/util/pm_newline_list.h b/prism/util/pm_newline_list.h
index 7ae9b6b3da..406abe8ba5 100644
--- a/prism/util/pm_newline_list.h
+++ b/prism/util/pm_newline_list.h
@@ -81,6 +81,17 @@ pm_newline_list_clear(pm_newline_list_t *list);
bool pm_newline_list_append(pm_newline_list_t *list, const uint8_t *cursor);
/**
+ * Returns the line of the given offset. If the offset is not in the list, the
+ * line of the closest offset less than the given offset is returned.
+ *
+ * @param list The list to search.
+ * @param cursor A pointer to the offset to search for.
+ * @param start_line The line to start counting from.
+ * @return The line of the given offset.
+ */
+int32_t pm_newline_list_line(const pm_newline_list_t *list, const uint8_t *cursor, int32_t start_line);
+
+/**
* Returns the line and column of the given offset. If the offset is not in the
* list, the line and column of the closest offset less than the given offset
* are returned.
diff --git a/prism/util/pm_string.c b/prism/util/pm_string.c
index dfc121b6a2..a7493c468b 100644
--- a/prism/util/pm_string.c
+++ b/prism/util/pm_string.c
@@ -1,5 +1,7 @@
#include "prism/util/pm_string.h"
+static const uint8_t empty_source[] = "";
+
/**
* Returns the size of the pm_string_t struct. This is necessary to allocate the
* correct amount of memory in the FFI backend.
@@ -47,6 +49,62 @@ pm_string_constant_init(pm_string_t *string, const char *source, size_t length)
};
}
+#ifdef _WIN32
+/**
+ * Represents a file handle on Windows, where the path will need to be freed
+ * when the file is closed.
+ */
+typedef struct {
+ /** The path to the file, which will become allocated memory. */
+ WCHAR *path;
+
+ /** The handle to the file, which will start as uninitialized memory. */
+ HANDLE file;
+} pm_string_file_handle_t;
+
+/**
+ * Open the file indicated by the filepath parameter for reading on Windows.
+ * Perform any kind of normalization that needs to happen on the filepath.
+ */
+static pm_string_init_result_t
+pm_string_file_handle_open(pm_string_file_handle_t *handle, const char *filepath) {
+ int length = MultiByteToWideChar(CP_UTF8, 0, filepath, -1, NULL, 0);
+ if (length == 0) return PM_STRING_INIT_ERROR_GENERIC;
+
+ handle->path = xmalloc(sizeof(WCHAR) * ((size_t) length));
+ if ((handle->path == NULL) || (MultiByteToWideChar(CP_UTF8, 0, filepath, -1, handle->path, length) == 0)) {
+ xfree(handle->path);
+ return PM_STRING_INIT_ERROR_GENERIC;
+ }
+
+ handle->file = CreateFileW(handle->path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
+ if (handle->file == INVALID_HANDLE_VALUE) {
+ pm_string_init_result_t result = PM_STRING_INIT_ERROR_GENERIC;
+
+ if (GetLastError() == ERROR_ACCESS_DENIED) {
+ DWORD attributes = GetFileAttributesW(handle->path);
+ if ((attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
+ result = PM_STRING_INIT_ERROR_DIRECTORY;
+ }
+ }
+
+ xfree(handle->path);
+ return result;
+ }
+
+ return PM_STRING_INIT_SUCCESS;
+}
+
+/**
+ * Close the file handle and free the path.
+ */
+static void
+pm_string_file_handle_close(pm_string_file_handle_t *handle) {
+ xfree(handle->path);
+ CloseHandle(handle->file);
+}
+#endif
+
/**
* Read the file indicated by the filepath parameter into source and load its
* contents and size into the given `pm_string_t`. The given `pm_string_t`
@@ -58,62 +116,65 @@ pm_string_constant_init(pm_string_t *string, const char *source, size_t length)
* `MapViewOfFile`, on POSIX systems that have access to `mmap` we'll use
* `mmap`, and on other POSIX systems we'll use `read`.
*/
-PRISM_EXPORTED_FUNCTION bool
+PRISM_EXPORTED_FUNCTION pm_string_init_result_t
pm_string_mapped_init(pm_string_t *string, const char *filepath) {
#ifdef _WIN32
// Open the file for reading.
- HANDLE file = CreateFile(filepath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-
- if (file == INVALID_HANDLE_VALUE) {
- return false;
- }
+ pm_string_file_handle_t handle;
+ pm_string_init_result_t result = pm_string_file_handle_open(&handle, filepath);
+ if (result != PM_STRING_INIT_SUCCESS) return result;
// Get the file size.
- DWORD file_size = GetFileSize(file, NULL);
+ DWORD file_size = GetFileSize(handle.file, NULL);
if (file_size == INVALID_FILE_SIZE) {
- CloseHandle(file);
- return false;
+ pm_string_file_handle_close(&handle);
+ return PM_STRING_INIT_ERROR_GENERIC;
}
// If the file is empty, then we don't need to do anything else, we'll set
// the source to a constant empty string and return.
if (file_size == 0) {
- CloseHandle(file);
- const uint8_t source[] = "";
- *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 };
- return true;
+ pm_string_file_handle_close(&handle);
+ *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = empty_source, .length = 0 };
+ return PM_STRING_INIT_SUCCESS;
}
// Create a mapping of the file.
- HANDLE mapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
+ HANDLE mapping = CreateFileMapping(handle.file, NULL, PAGE_READONLY, 0, 0, NULL);
if (mapping == NULL) {
- CloseHandle(file);
- return false;
+ pm_string_file_handle_close(&handle);
+ return PM_STRING_INIT_ERROR_GENERIC;
}
// Map the file into memory.
uint8_t *source = (uint8_t *) MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
CloseHandle(mapping);
- CloseHandle(file);
+ pm_string_file_handle_close(&handle);
if (source == NULL) {
- return false;
+ return PM_STRING_INIT_ERROR_GENERIC;
}
*string = (pm_string_t) { .type = PM_STRING_MAPPED, .source = source, .length = (size_t) file_size };
- return true;
+ return PM_STRING_INIT_SUCCESS;
#elif defined(_POSIX_MAPPED_FILES)
// Open the file for reading
int fd = open(filepath, O_RDONLY);
if (fd == -1) {
- return false;
+ return PM_STRING_INIT_ERROR_GENERIC;
}
// Stat the file to get the file size
struct stat sb;
if (fstat(fd, &sb) == -1) {
close(fd);
- return false;
+ return PM_STRING_INIT_ERROR_GENERIC;
+ }
+
+ // Ensure it is a file and not a directory
+ if (S_ISDIR(sb.st_mode)) {
+ close(fd);
+ return PM_STRING_INIT_ERROR_DIRECTORY;
}
// mmap the file descriptor to virtually get the contents
@@ -122,24 +183,21 @@ pm_string_mapped_init(pm_string_t *string, const char *filepath) {
if (size == 0) {
close(fd);
- const uint8_t source[] = "";
- *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 };
- return true;
+ *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = empty_source, .length = 0 };
+ return PM_STRING_INIT_SUCCESS;
}
source = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
if (source == MAP_FAILED) {
- return false;
+ close(fd);
+ return PM_STRING_INIT_ERROR_GENERIC;
}
close(fd);
*string = (pm_string_t) { .type = PM_STRING_MAPPED, .source = source, .length = size };
- return true;
+ return PM_STRING_INIT_SUCCESS;
#else
- (void) string;
- (void) filepath;
- perror("pm_string_mapped_init is not implemented for this platform");
- return false;
+ return pm_string_file_init(string, filepath);
#endif
}
@@ -148,100 +206,103 @@ pm_string_mapped_init(pm_string_t *string, const char *filepath) {
* contents and size into the given `pm_string_t`. The given `pm_string_t`
* should be freed using `pm_string_free` when it is no longer used.
*/
-PRISM_EXPORTED_FUNCTION bool
+PRISM_EXPORTED_FUNCTION pm_string_init_result_t
pm_string_file_init(pm_string_t *string, const char *filepath) {
#ifdef _WIN32
// Open the file for reading.
- HANDLE file = CreateFile(filepath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
-
- if (file == INVALID_HANDLE_VALUE) {
- return false;
- }
+ pm_string_file_handle_t handle;
+ pm_string_init_result_t result = pm_string_file_handle_open(&handle, filepath);
+ if (result != PM_STRING_INIT_SUCCESS) return result;
// Get the file size.
- DWORD file_size = GetFileSize(file, NULL);
+ DWORD file_size = GetFileSize(handle.file, NULL);
if (file_size == INVALID_FILE_SIZE) {
- CloseHandle(file);
- return false;
+ pm_string_file_handle_close(&handle);
+ return PM_STRING_INIT_ERROR_GENERIC;
}
// If the file is empty, then we don't need to do anything else, we'll set
// the source to a constant empty string and return.
if (file_size == 0) {
- CloseHandle(file);
- const uint8_t source[] = "";
- *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 };
- return true;
+ pm_string_file_handle_close(&handle);
+ *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = empty_source, .length = 0 };
+ return PM_STRING_INIT_SUCCESS;
}
// Create a buffer to read the file into.
uint8_t *source = xmalloc(file_size);
if (source == NULL) {
- CloseHandle(file);
- return false;
+ pm_string_file_handle_close(&handle);
+ return PM_STRING_INIT_ERROR_GENERIC;
}
// Read the contents of the file
DWORD bytes_read;
- if (!ReadFile(file, source, file_size, &bytes_read, NULL)) {
- CloseHandle(file);
- return false;
+ if (!ReadFile(handle.file, source, file_size, &bytes_read, NULL)) {
+ pm_string_file_handle_close(&handle);
+ return PM_STRING_INIT_ERROR_GENERIC;
}
// Check the number of bytes read
if (bytes_read != file_size) {
xfree(source);
- CloseHandle(file);
- return false;
+ pm_string_file_handle_close(&handle);
+ return PM_STRING_INIT_ERROR_GENERIC;
}
- CloseHandle(file);
+ pm_string_file_handle_close(&handle);
*string = (pm_string_t) { .type = PM_STRING_OWNED, .source = source, .length = (size_t) file_size };
- return true;
-#elif defined(_POSIX_MAPPED_FILES)
- FILE *file = fopen(filepath, "rb");
- if (file == NULL) {
- return false;
+ return PM_STRING_INIT_SUCCESS;
+#elif defined(PRISM_HAS_FILESYSTEM)
+ // Open the file for reading
+ int fd = open(filepath, O_RDONLY);
+ if (fd == -1) {
+ return PM_STRING_INIT_ERROR_GENERIC;
}
- fseek(file, 0, SEEK_END);
- long file_size = ftell(file);
+ // Stat the file to get the file size
+ struct stat sb;
+ if (fstat(fd, &sb) == -1) {
+ close(fd);
+ return PM_STRING_INIT_ERROR_GENERIC;
+ }
- if (file_size == -1) {
- fclose(file);
- return false;
+ // Ensure it is a file and not a directory
+ if (S_ISDIR(sb.st_mode)) {
+ close(fd);
+ return PM_STRING_INIT_ERROR_DIRECTORY;
}
- if (file_size == 0) {
- fclose(file);
- const uint8_t source[] = "";
- *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 };
- return true;
+ // Check the size to see if it's empty
+ size_t size = (size_t) sb.st_size;
+ if (size == 0) {
+ close(fd);
+ *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = empty_source, .length = 0 };
+ return PM_STRING_INIT_SUCCESS;
}
- size_t length = (size_t) file_size;
+ size_t length = (size_t) size;
uint8_t *source = xmalloc(length);
if (source == NULL) {
- fclose(file);
- return false;
+ close(fd);
+ return PM_STRING_INIT_ERROR_GENERIC;
}
- fseek(file, 0, SEEK_SET);
- size_t bytes_read = fread(source, length, 1, file);
- fclose(file);
+ long bytes_read = (long) read(fd, source, length);
+ close(fd);
- if (bytes_read != 1) {
+ if (bytes_read == -1) {
xfree(source);
- return false;
+ return PM_STRING_INIT_ERROR_GENERIC;
}
*string = (pm_string_t) { .type = PM_STRING_OWNED, .source = source, .length = length };
- return true;
+ return PM_STRING_INIT_SUCCESS;
#else
(void) string;
(void) filepath;
perror("pm_string_file_init is not implemented for this platform");
- return false;
+ return PM_STRING_INIT_ERROR_GENERIC;
#endif
}
diff --git a/prism/util/pm_string.h b/prism/util/pm_string.h
index d23792c0ba..d8456ff294 100644
--- a/prism/util/pm_string.h
+++ b/prism/util/pm_string.h
@@ -9,6 +9,7 @@
#include "prism/defines.h"
#include <assert.h>
+#include <errno.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
@@ -21,6 +22,9 @@
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
+#elif defined(PRISM_HAS_FILESYSTEM)
+#include <fcntl.h>
+#include <sys/stat.h>
#endif
/**
@@ -41,11 +45,11 @@ typedef struct {
/** This is a slice of another string, and should not be freed. */
PM_STRING_SHARED,
- /** This string owns its memory, and should be freed using `pm_string_free`. */
+ /** This string owns its memory, and should be freed using `pm_string_free()`. */
PM_STRING_OWNED,
#ifdef PRISM_HAS_MMAP
- /** This string is a memory-mapped file, and should be freed using `pm_string_free`. */
+ /** This string is a memory-mapped file, and should be freed using `pm_string_free()`. */
PM_STRING_MAPPED
#endif
} type;
@@ -93,6 +97,26 @@ void pm_string_owned_init(pm_string_t *string, uint8_t *source, size_t length);
void pm_string_constant_init(pm_string_t *string, const char *source, size_t length);
/**
+ * Represents the result of calling pm_string_mapped_init or
+ * pm_string_file_init. We need this additional information because there is
+ * not a platform-agnostic way to indicate that the file that was attempted to
+ * be opened was a directory.
+ */
+typedef enum {
+ /** Indicates that the string was successfully initialized. */
+ PM_STRING_INIT_SUCCESS = 0,
+ /**
+ * Indicates a generic error from a string_*_init function, where the type
+ * of error should be read from `errno` or `GetLastError()`.
+ */
+ PM_STRING_INIT_ERROR_GENERIC = 1,
+ /**
+ * Indicates that the file that was attempted to be opened was a directory.
+ */
+ PM_STRING_INIT_ERROR_DIRECTORY = 2
+} pm_string_init_result_t;
+
+/**
* Read the file indicated by the filepath parameter into source and load its
* contents and size into the given `pm_string_t`. The given `pm_string_t`
* should be freed using `pm_string_free` when it is no longer used.
@@ -105,9 +129,11 @@ void pm_string_constant_init(pm_string_t *string, const char *source, size_t len
*
* @param string The string to initialize.
* @param filepath The filepath to read.
- * @return Whether or not the file was successfully mapped.
+ * @return The success of the read, indicated by the value of the enum.
+ *
+ * \public \memberof pm_string_t
*/
-PRISM_EXPORTED_FUNCTION bool pm_string_mapped_init(pm_string_t *string, const char *filepath);
+PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_mapped_init(pm_string_t *string, const char *filepath);
/**
* Read the file indicated by the filepath parameter into source and load its
@@ -116,9 +142,11 @@ PRISM_EXPORTED_FUNCTION bool pm_string_mapped_init(pm_string_t *string, const ch
*
* @param string The string to initialize.
* @param filepath The filepath to read.
- * @return Whether or not the file was successfully read.
+ * @return The success of the read, indicated by the value of the enum.
+ *
+ * \public \memberof pm_string_t
*/
-PRISM_EXPORTED_FUNCTION bool pm_string_file_init(pm_string_t *string, const char *filepath);
+PRISM_EXPORTED_FUNCTION pm_string_init_result_t pm_string_file_init(pm_string_t *string, const char *filepath);
/**
* Ensure the string is owned. If it is not, then reinitialize it as owned and
@@ -145,6 +173,8 @@ int pm_string_compare(const pm_string_t *left, const pm_string_t *right);
*
* @param string The string to get the length of.
* @return The length of the string.
+ *
+ * \public \memberof pm_string_t
*/
PRISM_EXPORTED_FUNCTION size_t pm_string_length(const pm_string_t *string);
@@ -153,6 +183,8 @@ PRISM_EXPORTED_FUNCTION size_t pm_string_length(const pm_string_t *string);
*
* @param string The string to get the start pointer of.
* @return The start pointer of the string.
+ *
+ * \public \memberof pm_string_t
*/
PRISM_EXPORTED_FUNCTION const uint8_t * pm_string_source(const pm_string_t *string);
@@ -160,6 +192,8 @@ PRISM_EXPORTED_FUNCTION const uint8_t * pm_string_source(const pm_string_t *stri
* Free the associated memory of the given string.
*
* @param string The string to free.
+ *
+ * \public \memberof pm_string_t
*/
PRISM_EXPORTED_FUNCTION void pm_string_free(pm_string_t *string);
diff --git a/prism/util/pm_string_list.c b/prism/util/pm_string_list.c
deleted file mode 100644
index f6c2145987..0000000000
--- a/prism/util/pm_string_list.c
+++ /dev/null
@@ -1,28 +0,0 @@
-#include "prism/util/pm_string_list.h"
-
-/**
- * Append a pm_string_t to the given string list.
- */
-void
-pm_string_list_append(pm_string_list_t *string_list, pm_string_t *string) {
- if (string_list->length + 1 > string_list->capacity) {
- if (string_list->capacity == 0) {
- string_list->capacity = 1;
- } else {
- string_list->capacity *= 2;
- }
-
- string_list->strings = xrealloc(string_list->strings, string_list->capacity * sizeof(pm_string_t));
- if (string_list->strings == NULL) abort();
- }
-
- string_list->strings[string_list->length++] = *string;
-}
-
-/**
- * Free the memory associated with the string list
- */
-void
-pm_string_list_free(pm_string_list_t *string_list) {
- xfree(string_list->strings);
-}
diff --git a/prism/util/pm_string_list.h b/prism/util/pm_string_list.h
deleted file mode 100644
index 0d406cc5d8..0000000000
--- a/prism/util/pm_string_list.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/**
- * @file pm_string_list.h
- *
- * A list of strings.
- */
-#ifndef PRISM_STRING_LIST_H
-#define PRISM_STRING_LIST_H
-
-#include "prism/defines.h"
-#include "prism/util/pm_string.h"
-
-#include <stddef.h>
-#include <stdlib.h>
-
-/**
- * A list of strings.
- */
-typedef struct {
- /** The length of the string list. */
- size_t length;
-
- /** The capacity of the string list that has been allocated. */
- size_t capacity;
-
- /** A pointer to the start of the string list. */
- pm_string_t *strings;
-} pm_string_list_t;
-
-/**
- * Append a pm_string_t to the given string list.
- *
- * @param string_list The string list to append to.
- * @param string The string to append.
- */
-void pm_string_list_append(pm_string_list_t *string_list, pm_string_t *string);
-
-/**
- * Free the memory associated with the string list.
- *
- * @param string_list The string list to free.
- */
-PRISM_EXPORTED_FUNCTION void pm_string_list_free(pm_string_list_t *string_list);
-
-#endif
diff --git a/prism/util/pm_strncasecmp.c b/prism/util/pm_strncasecmp.c
index 2240bf8110..3f58421554 100644
--- a/prism/util/pm_strncasecmp.c
+++ b/prism/util/pm_strncasecmp.c
@@ -1,6 +1,18 @@
#include "prism/util/pm_strncasecmp.h"
/**
+ * A locale-insensitive version of `tolower(3)`
+ */
+static inline int
+pm_tolower(int c)
+{
+ if ('A' <= c && c <= 'Z') {
+ return c | 0x20;
+ }
+ return c;
+}
+
+/**
* Compare two strings, ignoring case, up to the given length. Returns 0 if the
* strings are equal, a negative number if string1 is less than string2, or a
* positive number if string1 is greater than string2.
@@ -16,7 +28,7 @@ pm_strncasecmp(const uint8_t *string1, const uint8_t *string2, size_t length) {
while (offset < length && string1[offset] != '\0') {
if (string2[offset] == '\0') return string1[offset];
- if ((difference = tolower(string1[offset]) - tolower(string2[offset])) != 0) return difference;
+ if ((difference = pm_tolower(string1[offset]) - pm_tolower(string2[offset])) != 0) return difference;
offset++;
}
diff --git a/prism/version.h b/prism/version.h
index 154e967944..0ef7435c17 100644
--- a/prism/version.h
+++ b/prism/version.h
@@ -9,12 +9,12 @@
/**
* The major version of the Prism library as an int.
*/
-#define PRISM_VERSION_MAJOR 0
+#define PRISM_VERSION_MAJOR 1
/**
* The minor version of the Prism library as an int.
*/
-#define PRISM_VERSION_MINOR 29
+#define PRISM_VERSION_MINOR 8
/**
* The patch version of the Prism library as an int.
@@ -24,6 +24,6 @@
/**
* The version of the Prism library as a constant string.
*/
-#define PRISM_VERSION "0.29.0"
+#define PRISM_VERSION "1.8.0"
#endif
diff --git a/prism_compile.c b/prism_compile.c
index ede4c3a64e..7889681130 100644
--- a/prism_compile.c
+++ b/prism_compile.c
@@ -1,7 +1,21 @@
#include "prism.h"
+#include "ruby/version.h"
+
+/**
+ * This compiler defines its own concept of the location of a node. We do this
+ * because we want to pair line information with node identifier so that we can
+ * have reproducible parses.
+ */
+typedef struct {
+ /** This is the line number of a node. */
+ int32_t line;
+
+ /** This is a unique identifier for the node. */
+ uint32_t node_id;
+} pm_node_location_t;
/******************************************************************************/
-/* These macros operate on pm_line_column_t structs as opposed to NODE*s. */
+/* These macros operate on pm_node_location_t structs as opposed to NODE*s. */
/******************************************************************************/
#define PUSH_ADJUST(seq, location, label) \
@@ -11,16 +25,16 @@
ADD_ELEM((seq), (LINK_ELEMENT *) new_adjust_body(iseq, (label), -1))
#define PUSH_INSN(seq, location, insn) \
- ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, (int) (location).line, (int) (location).column, BIN(insn), 0))
+ ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, (int) (location).line, (int) (location).node_id, BIN(insn), 0))
#define PUSH_INSN1(seq, location, insn, op1) \
- ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, (int) (location).line, (int) (location).column, BIN(insn), 1, (VALUE)(op1)))
+ ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, (int) (location).line, (int) (location).node_id, BIN(insn), 1, (VALUE)(op1)))
#define PUSH_INSN2(seq, location, insn, op1, op2) \
- ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, (int) (location).line, (int) (location).column, BIN(insn), 2, (VALUE)(op1), (VALUE)(op2)))
+ ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, (int) (location).line, (int) (location).node_id, BIN(insn), 2, (VALUE)(op1), (VALUE)(op2)))
#define PUSH_INSN3(seq, location, insn, op1, op2, op3) \
- ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, (int) (location).line, (int) (location).column, BIN(insn), 3, (VALUE)(op1), (VALUE)(op2), (VALUE)(op3)))
+ ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, (int) (location).line, (int) (location).node_id, BIN(insn), 3, (VALUE)(op1), (VALUE)(op2), (VALUE)(op3)))
#define PUSH_INSNL(seq, location, insn, label) \
(PUSH_INSN1(seq, location, insn, label), LABEL_REF(label))
@@ -29,7 +43,7 @@
ADD_ELEM((seq), (LINK_ELEMENT *) (label))
#define PUSH_SEND_R(seq, location, id, argc, block, flag, keywords) \
- ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_send(iseq, (int) (location).line, (int) (location).column, (id), (VALUE)(argc), (block), (VALUE)(flag), (keywords)))
+ ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_send(iseq, (int) (location).line, (int) (location).node_id, (id), (VALUE)(argc), (block), (VALUE)(flag), (keywords)))
#define PUSH_SEND(seq, location, id, argc) \
PUSH_SEND_R((seq), location, (id), (argc), NULL, (VALUE)INT2FIX(0), NULL)
@@ -68,34 +82,35 @@
/******************************************************************************/
static void
-pm_iseq_add_getlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, int line_no, int column, int idx, int level)
+pm_iseq_add_getlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, int line, int node_id, int idx, int level)
{
if (iseq_local_block_param_p(iseq, idx, level)) {
- ADD_ELEM(seq, (LINK_ELEMENT *) new_insn_body(iseq, line_no, column, BIN(getblockparam), 2, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level)));
+ ADD_ELEM(seq, (LINK_ELEMENT *) new_insn_body(iseq, line, node_id, BIN(getblockparam), 2, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level)));
}
else {
- ADD_ELEM(seq, (LINK_ELEMENT *) new_insn_body(iseq, line_no, column, BIN(getlocal), 2, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level)));
+ ADD_ELEM(seq, (LINK_ELEMENT *) new_insn_body(iseq, line, node_id, BIN(getlocal), 2, 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
-pm_iseq_add_setlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, int line_no, int column, int idx, int level)
+pm_iseq_add_setlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, int line, int node_id, int idx, int level)
{
if (iseq_local_block_param_p(iseq, idx, level)) {
- ADD_ELEM(seq, (LINK_ELEMENT *) new_insn_body(iseq, line_no, column, BIN(setblockparam), 2, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level)));
+ ADD_ELEM(seq, (LINK_ELEMENT *) new_insn_body(iseq, line, node_id, BIN(setblockparam), 2, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level)));
}
else {
- ADD_ELEM(seq, (LINK_ELEMENT *) new_insn_body(iseq, line_no, column, BIN(setlocal), 2, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level)));
+ ADD_ELEM(seq, (LINK_ELEMENT *) new_insn_body(iseq, line, node_id, BIN(setlocal), 2, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level)));
}
+ update_lvar_state(iseq, level, idx);
if (level > 0) access_outer_variables(iseq, level, iseq_lvar_id(iseq, idx, level), Qtrue);
}
#define PUSH_GETLOCAL(seq, location, idx, level) \
- pm_iseq_add_getlocal(iseq, (seq), (int) (location).line, (int) (location).column, (idx), (level))
+ pm_iseq_add_getlocal(iseq, (seq), (int) (location).line, (int) (location).node_id, (idx), (level))
#define PUSH_SETLOCAL(seq, location, idx, level) \
- pm_iseq_add_setlocal(iseq, (seq), (int) (location).line, (int) (location).column, (idx), (level))
+ pm_iseq_add_setlocal(iseq, (seq), (int) (location).line, (int) (location).node_id, (idx), (level))
/******************************************************************************/
/* These are helper macros for the compiler. */
@@ -125,11 +140,14 @@ pm_iseq_add_setlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, int line_no, int c
#define PM_COMPILE_NOT_POPPED(node) \
pm_compile_node(iseq, (node), ret, false, scope_node)
-#define PM_SPECIAL_CONSTANT_FLAG ((pm_constant_id_t)(1 << 31))
-#define PM_CONSTANT_AND ((pm_constant_id_t)(idAnd | PM_SPECIAL_CONSTANT_FLAG))
-#define PM_CONSTANT_DOT3 ((pm_constant_id_t)(idDot3 | PM_SPECIAL_CONSTANT_FLAG))
-#define PM_CONSTANT_MULT ((pm_constant_id_t)(idMULT | PM_SPECIAL_CONSTANT_FLAG))
-#define PM_CONSTANT_POW ((pm_constant_id_t)(idPow | PM_SPECIAL_CONSTANT_FLAG))
+#define PM_NODE_START_LOCATION(parser, node) \
+ ((pm_node_location_t) { .line = pm_newline_list_line(&(parser)->newline_list, ((const pm_node_t *) (node))->location.start, (parser)->start_line), .node_id = ((const pm_node_t *) (node))->node_id })
+
+#define PM_NODE_END_LOCATION(parser, node) \
+ ((pm_node_location_t) { .line = pm_newline_list_line(&(parser)->newline_list, ((const pm_node_t *) (node))->location.end, (parser)->start_line), .node_id = ((const pm_node_t *) (node))->node_id })
+
+#define PM_LOCATION_START_LOCATION(parser, location, id) \
+ ((pm_node_location_t) { .line = pm_newline_list_line(&(parser)->newline_list, (location)->start, (parser)->start_line), .node_id = id })
#define PM_NODE_START_LINE_COLUMN(parser, node) \
pm_newline_list_line_column(&(parser)->newline_list, ((const pm_node_t *) (node))->location.start, (parser)->start_line)
@@ -143,12 +161,12 @@ pm_iseq_add_setlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, int line_no, int c
static int
pm_node_line_number(const pm_parser_t *parser, const pm_node_t *node)
{
- return (int) PM_NODE_START_LINE_COLUMN(parser, node).line;
+ return (int) pm_newline_list_line(&parser->newline_list, node->location.start, parser->start_line);
}
static int
pm_location_line_number(const pm_parser_t *parser, const pm_location_t *location) {
- return (int) PM_LOCATION_START_LINE_COLUMN(parser, location).line;
+ return (int) pm_newline_list_line(&parser->newline_list, location->start, parser->start_line);
}
/**
@@ -183,6 +201,10 @@ parse_integer_value(const pm_integer_t *integer)
result = rb_funcall(result, rb_intern("-@"), 0);
}
+ if (!SPECIAL_CONST_P(result)) {
+ RB_OBJ_SET_SHAREABLE(result); // bignum
+ }
+
return result;
}
@@ -201,7 +223,11 @@ parse_integer(const pm_integer_node_t *node)
static VALUE
parse_float(const pm_float_node_t *node)
{
- return DBL2NUM(node->value);
+ VALUE val = DBL2NUM(node->value);
+ if (!FLONUM_P(val)) {
+ RB_OBJ_SET_SHAREABLE(val);
+ }
+ return val;
}
/**
@@ -215,7 +241,8 @@ parse_rational(const pm_rational_node_t *node)
{
VALUE numerator = parse_integer_value(&node->numerator);
VALUE denominator = parse_integer_value(&node->denominator);
- return rb_rational_new(numerator, denominator);
+
+ return rb_ractor_make_shareable(rb_rational_new(numerator, denominator));
}
/**
@@ -245,7 +272,7 @@ parse_imaginary(const pm_imaginary_node_t *node)
rb_bug("Unexpected numeric type on imaginary number %s\n", pm_node_type_to_str(PM_NODE_TYPE(node->numeric)));
}
- return rb_complex_raw(INT2FIX(0), imaginary_part);
+ return RB_OBJ_SET_SHAREABLE(rb_complex_raw(INT2FIX(0), imaginary_part));
}
static inline VALUE
@@ -297,10 +324,7 @@ parse_static_literal_string(rb_iseq_t *iseq, const pm_scope_node_t *scope_node,
if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) {
int line_number = pm_node_line_number(scope_node->parser, node);
- VALUE debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq), INT2FIX(line_number));
- value = rb_str_dup(value);
- rb_ivar_set(value, id_debug_created_info, rb_obj_freeze(debug_info));
- rb_str_freeze(value);
+ value = rb_ractor_make_shareable(rb_str_with_debug_created_info(value, rb_iseq_path(iseq), line_number));
}
return value;
@@ -483,7 +507,7 @@ parse_regexp_flags(const pm_node_t *node)
static rb_encoding *
parse_regexp_encoding(const pm_scope_node_t *scope_node, const pm_node_t *node)
{
- if (PM_NODE_FLAG_P(node, PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT)) {
+ if (PM_NODE_FLAG_P(node, PM_REGULAR_EXPRESSION_FLAGS_FORCED_BINARY_ENCODING) || PM_NODE_FLAG_P(node, PM_REGULAR_EXPRESSION_FLAGS_ASCII_8BIT)) {
return rb_ascii8bit_encoding();
}
else if (PM_NODE_FLAG_P(node, PM_REGULAR_EXPRESSION_FLAGS_UTF_8)) {
@@ -516,8 +540,7 @@ parse_regexp(rb_iseq_t *iseq, const pm_scope_node_t *scope_node, const pm_node_t
return Qnil;
}
- rb_obj_freeze(regexp);
- return regexp;
+ return RB_OBJ_SET_SHAREABLE(rb_obj_freeze(regexp));
}
static inline VALUE
@@ -527,6 +550,7 @@ parse_regexp_literal(rb_iseq_t *iseq, const pm_scope_node_t *scope_node, const p
if (regexp_encoding == NULL) regexp_encoding = scope_node->encoding;
VALUE string = rb_enc_str_new((const char *) pm_string_source(unescaped), pm_string_length(unescaped), regexp_encoding);
+ RB_OBJ_SET_SHAREABLE(string);
return parse_regexp(iseq, scope_node, node, string);
}
@@ -543,7 +567,7 @@ parse_regexp_concat(rb_iseq_t *iseq, const pm_scope_node_t *scope_node, const pm
static void pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node);
static int
-pm_interpolated_node_compile(rb_iseq_t *iseq, const pm_node_list_t *parts, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node, rb_encoding *implicit_regexp_encoding, rb_encoding *explicit_regexp_encoding)
+pm_interpolated_node_compile(rb_iseq_t *iseq, const pm_node_list_t *parts, const pm_node_location_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node, rb_encoding *implicit_regexp_encoding, rb_encoding *explicit_regexp_encoding, bool mutable_result, bool frozen_result)
{
int stack_size = 0;
size_t parts_size = parts->size;
@@ -551,7 +575,7 @@ pm_interpolated_node_compile(rb_iseq_t *iseq, const pm_node_list_t *parts, const
if (parts_size > 0) {
VALUE current_string = Qnil;
- pm_line_column_t current_location = *node_location;
+ pm_node_location_t current_location = *node_location;
for (size_t index = 0; index < parts_size; index++) {
const pm_node_t *part = parts->nodes[index];
@@ -572,7 +596,7 @@ pm_interpolated_node_compile(rb_iseq_t *iseq, const pm_node_list_t *parts, const
}
else {
current_string = string_value;
- if (index != 0) current_location = PM_NODE_END_LINE_COLUMN(scope_node->parser, part);
+ if (index != 0) current_location = PM_NODE_END_LOCATION(scope_node->parser, part);
}
}
else {
@@ -599,7 +623,7 @@ pm_interpolated_node_compile(rb_iseq_t *iseq, const pm_node_list_t *parts, const
}
else {
current_string = string_value;
- current_location = PM_NODE_START_LINE_COLUMN(scope_node->parser, part);
+ current_location = PM_NODE_START_LOCATION(scope_node->parser, part);
}
}
else {
@@ -621,19 +645,31 @@ pm_interpolated_node_compile(rb_iseq_t *iseq, const pm_node_list_t *parts, const
encoding = scope_node->encoding;
}
- current_string = rb_enc_str_new(NULL, 0, encoding);
+ if (parts_size == 1) {
+ current_string = rb_enc_str_new(NULL, 0, encoding);
+ }
+ }
+
+ if (RTEST(current_string)) {
+ VALUE operand = rb_fstring(current_string);
+ PUSH_INSN1(ret, current_location, putobject, operand);
+ stack_size++;
}
- PUSH_INSN1(ret, current_location, putobject, rb_fstring(current_string));
PM_COMPILE_NOT_POPPED(part);
- const pm_line_column_t current_location = PM_NODE_START_LINE_COLUMN(scope_node->parser, part);
+ const pm_node_location_t current_location = PM_NODE_START_LOCATION(scope_node->parser, part);
PUSH_INSN(ret, current_location, dup);
- PUSH_INSN1(ret, current_location, objtostring, new_callinfo(iseq, idTo_s, 0, VM_CALL_FCALL | VM_CALL_ARGS_SIMPLE, NULL, FALSE));
+
+ {
+ const struct rb_callinfo *callinfo = new_callinfo(iseq, idTo_s, 0, VM_CALL_FCALL | VM_CALL_ARGS_SIMPLE, NULL, FALSE);
+ PUSH_INSN1(ret, current_location, objtostring, callinfo);
+ }
+
PUSH_INSN(ret, current_location, anytostring);
current_string = Qnil;
- stack_size += 2;
+ stack_size++;
}
}
}
@@ -641,10 +677,15 @@ pm_interpolated_node_compile(rb_iseq_t *iseq, const pm_node_list_t *parts, const
if (RTEST(current_string)) {
current_string = rb_fstring(current_string);
- if (stack_size == 0 && interpolated) {
- PUSH_INSN1(ret, current_location, putstring, current_string);
- }
- else {
+ if (stack_size == 0) {
+ if (frozen_result) {
+ PUSH_INSN1(ret, current_location, putobject, current_string);
+ } else if (mutable_result || interpolated) {
+ PUSH_INSN1(ret, current_location, putstring, current_string);
+ } else {
+ PUSH_INSN1(ret, current_location, putchilledstring, current_string);
+ }
+ } else {
PUSH_INSN1(ret, current_location, putobject, current_string);
}
@@ -660,12 +701,12 @@ pm_interpolated_node_compile(rb_iseq_t *iseq, const pm_node_list_t *parts, const
}
static void
-pm_compile_regexp_dynamic(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_list_t *parts, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+pm_compile_regexp_dynamic(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_list_t *parts, const pm_node_location_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
{
rb_encoding *explicit_regexp_encoding = parse_regexp_encoding(scope_node, node);
rb_encoding *implicit_regexp_encoding = explicit_regexp_encoding != NULL ? explicit_regexp_encoding : scope_node->encoding;
- int length = pm_interpolated_node_compile(iseq, parts, node_location, ret, popped, scope_node, implicit_regexp_encoding, explicit_regexp_encoding);
+ int length = pm_interpolated_node_compile(iseq, parts, node_location, ret, popped, scope_node, implicit_regexp_encoding, explicit_regexp_encoding, false, false);
PUSH_INSN2(ret, *node_location, toregexp, INT2FIX(parse_regexp_flags(node) & 0xFF), INT2FIX(length));
}
@@ -692,9 +733,9 @@ static VALUE
pm_static_literal_string(rb_iseq_t *iseq, VALUE string, int line_number)
{
if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) {
- VALUE debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq), INT2FIX(line_number));
- rb_ivar_set(string, id_debug_created_info, rb_obj_freeze(debug_info));
- return rb_str_freeze(string);
+ VALUE str = rb_str_with_debug_created_info(string, rb_iseq_path(iseq), line_number);
+ RB_OBJ_SET_SHAREABLE(str);
+ return str;
}
else {
return rb_fstring(string);
@@ -723,7 +764,7 @@ pm_static_literal_value(rb_iseq_t *iseq, const pm_node_t *node, const pm_scope_n
rb_ary_push(value, pm_static_literal_value(iseq, elements->nodes[index], scope_node));
}
- OBJ_FREEZE(value);
+ RB_OBJ_SET_FROZEN_SHAREABLE(value);
return value;
}
case PM_FALSE_NODE:
@@ -746,7 +787,7 @@ pm_static_literal_value(rb_iseq_t *iseq, const pm_node_t *node, const pm_scope_n
rb_hash_bulk_insert(RARRAY_LEN(array), RARRAY_CONST_PTR(array), value);
value = rb_obj_hide(value);
- OBJ_FREEZE(value);
+ RB_OBJ_SET_FROZEN_SHAREABLE(value);
return value;
}
case PM_IMAGINARY_NODE:
@@ -835,10 +876,9 @@ pm_compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const pm_no
static void
pm_compile_logical(rb_iseq_t *iseq, LINK_ANCHOR *const ret, pm_node_t *cond, LABEL *then_label, LABEL *else_label, bool popped, pm_scope_node_t *scope_node)
{
- const pm_line_column_t location = PM_NODE_START_LINE_COLUMN(scope_node->parser, cond);
+ const pm_node_location_t location = PM_NODE_START_LOCATION(scope_node->parser, cond);
DECL_ANCHOR(seq);
- INIT_ANCHOR(seq);
LABEL *label = NEW_LABEL(location.line);
if (!then_label) then_label = label;
@@ -865,11 +905,14 @@ pm_compile_logical(rb_iseq_t *iseq, LINK_ANCHOR *const ret, pm_node_t *cond, LAB
static void
pm_compile_flip_flop_bound(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
{
- const pm_line_column_t location = { .line = ISEQ_BODY(iseq)->location.first_lineno, .column = -1 };
+ const pm_node_location_t location = PM_NODE_START_LOCATION(scope_node->parser, node);
if (PM_NODE_TYPE_P(node, PM_INTEGER_NODE)) {
PM_COMPILE_NOT_POPPED(node);
- PUSH_INSN1(ret, location, getglobal, ID2SYM(rb_intern("$.")));
+
+ VALUE operand = ID2SYM(rb_intern("$."));
+ PUSH_INSN1(ret, location, getglobal, operand);
+
PUSH_SEND(ret, location, idEq, INT2FIX(1));
if (popped) PUSH_INSN(ret, location, pop);
}
@@ -881,7 +924,7 @@ pm_compile_flip_flop_bound(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *
static void
pm_compile_flip_flop(const pm_flip_flop_node_t *flip_flop_node, LABEL *else_label, LABEL *then_label, rb_iseq_t *iseq, const int lineno, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
{
- const pm_line_column_t location = { .line = ISEQ_BODY(iseq)->location.first_lineno, .column = -1 };
+ const pm_node_location_t location = { .line = lineno, .node_id = -1 };
LABEL *lend = NEW_LABEL(location.line);
int again = !(flip_flop_node->base.flags & PM_RANGE_FLAGS_EXCLUDE_END);
@@ -920,12 +963,12 @@ pm_compile_flip_flop(const pm_flip_flop_node_t *flip_flop_node, LABEL *else_labe
PUSH_INSNL(ret, location, jump, then_label);
}
-static void pm_compile_defined_expr(rb_iseq_t *iseq, const pm_node_t *node, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node, bool in_condition);
+static void pm_compile_defined_expr(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_location_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node, bool in_condition);
static void
pm_compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const pm_node_t *cond, LABEL *then_label, LABEL *else_label, bool popped, pm_scope_node_t *scope_node)
{
- const pm_line_column_t location = PM_NODE_START_LINE_COLUMN(scope_node->parser, cond);
+ const pm_node_location_t location = PM_NODE_START_LOCATION(scope_node->parser, cond);
again:
switch (PM_NODE_TYPE(cond)) {
@@ -967,7 +1010,26 @@ again:
break;
}
default: {
- pm_compile_node(iseq, cond, ret, false, scope_node);
+ DECL_ANCHOR(cond_seq);
+ pm_compile_node(iseq, cond, cond_seq, false, scope_node);
+
+ if (LIST_INSN_SIZE_ONE(cond_seq)) {
+ INSN *insn = (INSN *) ELEM_FIRST_INSN(FIRST_ELEMENT(cond_seq));
+
+ if (insn->insn_id == BIN(putobject)) {
+ if (RTEST(insn->operands[0])) {
+ PUSH_INSNL(ret, location, jump, then_label);
+ // maybe unreachable
+ return;
+ }
+ else {
+ PUSH_INSNL(ret, location, jump, else_label);
+ return;
+ }
+ }
+ }
+
+ PUSH_SEQ(ret, cond_seq);
break;
}
}
@@ -980,15 +1042,14 @@ again:
* Compile an if or unless node.
*/
static void
-pm_compile_conditional(rb_iseq_t *iseq, const pm_line_column_t *line_column, pm_node_type_t type, const pm_node_t *node, const pm_statements_node_t *statements, const pm_node_t *consequent, const pm_node_t *predicate, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+pm_compile_conditional(rb_iseq_t *iseq, const pm_node_location_t *node_location, pm_node_type_t type, const pm_node_t *node, const pm_statements_node_t *statements, const pm_node_t *subsequent, const pm_node_t *predicate, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
{
- const pm_line_column_t location = *line_column;
+ const pm_node_location_t location = *node_location;
LABEL *then_label = NEW_LABEL(location.line);
LABEL *else_label = NEW_LABEL(location.line);
LABEL *end_label = NULL;
DECL_ANCHOR(cond_seq);
- INIT_ANCHOR(cond_seq);
pm_compile_branch_condition(iseq, cond_seq, predicate, then_label, else_label, false, scope_node);
PUSH_SEQ(ret, cond_seq);
@@ -1004,7 +1065,6 @@ pm_compile_conditional(rb_iseq_t *iseq, const pm_line_column_t *line_column, pm_
PUSH_LABEL(ret, then_label);
DECL_ANCHOR(then_seq);
- INIT_ANCHOR(then_seq);
if (statements != NULL) {
pm_compile_node(iseq, (const pm_node_t *) statements, then_seq, popped, scope_node);
@@ -1045,10 +1105,9 @@ pm_compile_conditional(rb_iseq_t *iseq, const pm_line_column_t *line_column, pm_
PUSH_LABEL(ret, else_label);
DECL_ANCHOR(else_seq);
- INIT_ANCHOR(else_seq);
- if (consequent != NULL) {
- pm_compile_node(iseq, consequent, else_seq, popped, scope_node);
+ if (subsequent != NULL) {
+ pm_compile_node(iseq, subsequent, else_seq, popped, scope_node);
}
else if (!popped) {
PUSH_SYNTHETIC_PUTNIL(else_seq, iseq);
@@ -1058,13 +1117,13 @@ pm_compile_conditional(rb_iseq_t *iseq, const pm_line_column_t *line_column, pm_
if (then_label->refcnt && PM_BRANCH_COVERAGE_P(iseq)) {
rb_code_location_t branch_location;
- if (consequent == NULL) {
+ if (subsequent == NULL) {
branch_location = conditional_location;
- } else if (PM_NODE_TYPE_P(consequent, PM_ELSE_NODE)) {
- const pm_else_node_t *else_node = (const pm_else_node_t *) consequent;
+ } else if (PM_NODE_TYPE_P(subsequent, PM_ELSE_NODE)) {
+ const pm_else_node_t *else_node = (const pm_else_node_t *) subsequent;
branch_location = pm_code_location(scope_node, else_node->statements != NULL ? ((const pm_node_t *) else_node->statements) : (const pm_node_t *) else_node);
} else {
- branch_location = pm_code_location(scope_node, (const pm_node_t *) consequent);
+ branch_location = pm_code_location(scope_node, (const pm_node_t *) subsequent);
}
add_trace_branch_coverage(iseq, ret, &branch_location, branch_location.beg_pos.column, 1, type == PM_IF_NODE ? "else" : "then", branches);
@@ -1084,15 +1143,14 @@ pm_compile_conditional(rb_iseq_t *iseq, const pm_line_column_t *line_column, pm_
* Compile a while or until loop.
*/
static void
-pm_compile_loop(rb_iseq_t *iseq, const pm_line_column_t *line_column, pm_node_flags_t flags, enum pm_node_type type, const pm_node_t *node, const pm_statements_node_t *statements, const pm_node_t *predicate, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+pm_compile_loop(rb_iseq_t *iseq, const pm_node_location_t *node_location, pm_node_flags_t flags, enum pm_node_type type, const pm_node_t *node, const pm_statements_node_t *statements, const pm_node_t *predicate, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
{
- const pm_line_column_t location = *line_column;
+ const pm_node_location_t location = *node_location;
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;
- // TODO: Deal with ensures in here
LABEL *next_label = ISEQ_COMPILE_DATA(iseq)->start_label = NEW_LABEL(location.line); /* next */
LABEL *redo_label = ISEQ_COMPILE_DATA(iseq)->redo_label = NEW_LABEL(location.line); /* redo */
LABEL *break_label = ISEQ_COMPILE_DATA(iseq)->end_label = NEW_LABEL(location.line); /* break */
@@ -1102,6 +1160,12 @@ pm_compile_loop(rb_iseq_t *iseq, const pm_line_column_t *line_column, pm_node_fl
LABEL *next_catch_label = NEW_LABEL(location.line);
LABEL *tmp_label = NULL;
+ // We're pushing onto the ensure stack because breaks need to break out of
+ // this loop and not break into the ensure statements within the same
+ // lexical scope.
+ struct iseq_compile_data_ensure_node_stack enl;
+ push_ensure_entry(iseq, &enl, NULL, NULL);
+
// begin; end while true
if (flags & PM_LOOP_FLAGS_BEGIN_MODIFIER) {
tmp_label = NEW_LABEL(location.line);
@@ -1154,6 +1218,8 @@ pm_compile_loop(rb_iseq_t *iseq, const pm_line_column_t *line_column, pm_node_fl
ISEQ_COMPILE_DATA(iseq)->start_label = prev_start_label;
ISEQ_COMPILE_DATA(iseq)->end_label = prev_end_label;
ISEQ_COMPILE_DATA(iseq)->redo_label = prev_redo_label;
+ ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack->prev;
+
return;
}
@@ -1209,17 +1275,24 @@ pm_new_child_iseq(rb_iseq_t *iseq, pm_scope_node_t *node, VALUE name, const rb_i
{
debugs("[new_child_iseq]> ---------------------------------------\n");
int isolated_depth = ISEQ_COMPILE_DATA(iseq)->isolated_depth;
+ int error_state;
rb_iseq_t *ret_iseq = pm_iseq_new_with_opt(node, name,
rb_iseq_path(iseq), rb_iseq_realpath(iseq),
line_no, parent,
isolated_depth ? isolated_depth + 1 : 0,
- type, ISEQ_COMPILE_DATA(iseq)->option);
+ type, ISEQ_COMPILE_DATA(iseq)->option, &error_state);
+
+ if (error_state) {
+ pm_scope_node_destroy(node);
+ RUBY_ASSERT(ret_iseq == NULL);
+ rb_jump_tag(error_state);
+ }
debugs("[new_child_iseq]< ---------------------------------------\n");
return ret_iseq;
}
static int
-pm_compile_class_path(rb_iseq_t *iseq, const pm_node_t *node, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+pm_compile_class_path(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_location_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
{
if (PM_NODE_TYPE_P(node, PM_CONSTANT_PATH_NODE)) {
const pm_node_t *parent = ((const pm_constant_path_node_t *) node)->parent;
@@ -1247,9 +1320,9 @@ pm_compile_class_path(rb_iseq_t *iseq, const pm_node_t *node, const pm_line_colu
* method calls that are followed by a ||= or &&= operator.
*/
static void
-pm_compile_call_and_or_write_node(rb_iseq_t *iseq, bool and_node, const pm_node_t *receiver, const pm_node_t *value, pm_constant_id_t write_name, pm_constant_id_t read_name, bool safe_nav, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+pm_compile_call_and_or_write_node(rb_iseq_t *iseq, bool and_node, const pm_node_t *receiver, const pm_node_t *value, pm_constant_id_t write_name, pm_constant_id_t read_name, bool safe_nav, const pm_node_location_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
{
- const pm_line_column_t location = *node_location;
+ const pm_node_location_t location = *node_location;
LABEL *lfin = NEW_LABEL(location.line);
LABEL *lcfin = NEW_LABEL(location.line);
LABEL *lskip = NULL;
@@ -1297,80 +1370,204 @@ pm_compile_call_and_or_write_node(rb_iseq_t *iseq, bool and_node, const pm_node_
if (lskip && !popped) PUSH_LABEL(ret, lskip);
}
+static void pm_compile_shareable_constant_value(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_flags_t shareability, VALUE path, LINK_ANCHOR *const ret, pm_scope_node_t *scope_node, bool top);
+
/**
* This function compiles a hash onto the stack. It is used to compile hash
* literals and keyword arguments. It is assumed that if we get here that the
* contents of the hash are not popped.
*/
static void
-pm_compile_hash_elements(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_list_t *elements, LINK_ANCHOR *const ret, pm_scope_node_t *scope_node)
+pm_compile_hash_elements(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_list_t *elements, const pm_node_flags_t shareability, VALUE path, bool argument, LINK_ANCHOR *const ret, pm_scope_node_t *scope_node)
{
- const pm_line_column_t location = PM_NODE_START_LINE_COLUMN(scope_node->parser, node);
+ const pm_node_location_t location = PM_NODE_START_LOCATION(scope_node->parser, node);
// If this element is not popped, then we need to create the hash on the
// stack. Neighboring plain assoc nodes should be grouped together (either
// by newhash or hash merge). Double splat nodes should be merged using the
// merge_kwd method call.
- int assoc_length = 0;
- bool made_hash = false;
+ const int max_stack_length = 0x100;
+ const unsigned int min_tmp_hash_length = 0x800;
+
+ int stack_length = 0;
+ bool first_chunk = true;
+
+ // This is an optimization wherein we keep track of whether or not the
+ // previous element was a static literal. If it was, then we do not attempt
+ // to check if we have a subhash that can be optimized. If it was not, then
+ // we do check.
+ bool static_literal = false;
+
+ DECL_ANCHOR(anchor);
+
+ // Convert pushed elements to a hash, and merge if needed.
+#define FLUSH_CHUNK \
+ if (stack_length) { \
+ if (first_chunk) { \
+ PUSH_SEQ(ret, anchor); \
+ PUSH_INSN1(ret, location, newhash, INT2FIX(stack_length)); \
+ first_chunk = false; \
+ } \
+ else { \
+ PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); \
+ PUSH_INSN(ret, location, swap); \
+ PUSH_SEQ(ret, anchor); \
+ PUSH_SEND(ret, location, id_core_hash_merge_ptr, INT2FIX(stack_length + 1)); \
+ } \
+ INIT_ANCHOR(anchor); \
+ stack_length = 0; \
+ }
for (size_t index = 0; index < elements->size; index++) {
const pm_node_t *element = elements->nodes[index];
switch (PM_NODE_TYPE(element)) {
case PM_ASSOC_NODE: {
+ // Pre-allocation check (this branch can be omitted).
+ if (
+ (shareability == 0) &&
+ PM_NODE_FLAG_P(element, PM_NODE_FLAG_STATIC_LITERAL) && (
+ (!static_literal && ((index + min_tmp_hash_length) < elements->size)) ||
+ (first_chunk && stack_length == 0)
+ )
+ ) {
+ // Count the elements that are statically-known.
+ size_t count = 1;
+ while (index + count < elements->size && PM_NODE_FLAG_P(elements->nodes[index + count], PM_NODE_FLAG_STATIC_LITERAL)) count++;
+
+ if ((first_chunk && stack_length == 0) || count >= min_tmp_hash_length) {
+ // The subsequence of elements in this hash is long enough
+ // to merit its own hash.
+ VALUE ary = rb_ary_hidden_new(count);
+
+ // Create a hidden hash.
+ for (size_t tmp_end = index + count; index < tmp_end; index++) {
+ const pm_assoc_node_t *assoc = (const pm_assoc_node_t *) elements->nodes[index];
+
+ VALUE elem[2] = {
+ pm_static_literal_value(iseq, assoc->key, scope_node),
+ pm_static_literal_value(iseq, assoc->value, scope_node)
+ };
+
+ rb_ary_cat(ary, elem, 2);
+ }
+ index --;
+
+ VALUE hash = rb_hash_new_with_size(RARRAY_LEN(ary) / 2);
+ rb_hash_bulk_insert(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary), hash);
+ hash = rb_obj_hide(hash);
+ RB_OBJ_SET_FROZEN_SHAREABLE(hash);
+
+ // Emit optimized code.
+ FLUSH_CHUNK;
+ if (first_chunk) {
+ PUSH_INSN1(ret, location, duphash, hash);
+ first_chunk = false;
+ }
+ else {
+ PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
+ PUSH_INSN(ret, location, swap);
+ PUSH_INSN1(ret, location, putobject, hash);
+ PUSH_SEND(ret, location, id_core_hash_merge_kwd, INT2FIX(2));
+ }
+
+ break;
+ }
+ else {
+ static_literal = true;
+ }
+ }
+ else {
+ static_literal = false;
+ }
+
// If this is a plain assoc node, then we can compile it directly
- // and then add to the number of assoc nodes we've seen so far.
- PM_COMPILE_NOT_POPPED(element);
- assoc_length++;
+ // and then add the total number of values on the stack.
+ if (shareability == 0) {
+ pm_compile_node(iseq, element, anchor, false, scope_node);
+ }
+ else {
+ const pm_assoc_node_t *assoc = (const pm_assoc_node_t *) element;
+ pm_compile_shareable_constant_value(iseq, assoc->key, shareability, path, ret, scope_node, false);
+ pm_compile_shareable_constant_value(iseq, assoc->value, shareability, path, ret, scope_node, false);
+ }
+
+ if ((stack_length += 2) >= max_stack_length) FLUSH_CHUNK;
break;
}
case PM_ASSOC_SPLAT_NODE: {
- // If we are at a splat and we have already compiled some elements
- // of the hash, then we need to either create the first hash or
- // merge the current elements into the existing hash.
- if (assoc_length > 0) {
- if (!made_hash) {
- PUSH_INSN1(ret, location, newhash, INT2FIX(assoc_length * 2));
- PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
- PUSH_INSN(ret, location, swap);
- made_hash = true;
- }
- else {
- // Here we are merging plain assoc nodes into the hash on
- // the stack.
- PUSH_SEND(ret, location, id_core_hash_merge_ptr, INT2FIX(assoc_length * 2 + 1));
+ FLUSH_CHUNK;
- // Since we already have a hash on the stack, we need to set
- // up the method call for the next merge that will occur.
- PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
- PUSH_INSN(ret, location, swap);
- }
+ const pm_assoc_splat_node_t *assoc_splat = (const pm_assoc_splat_node_t *) element;
+ bool empty_hash = assoc_splat->value != NULL && (
+ (PM_NODE_TYPE_P(assoc_splat->value, PM_HASH_NODE) && ((const pm_hash_node_t *) assoc_splat->value)->elements.size == 0) ||
+ PM_NODE_TYPE_P(assoc_splat->value, PM_NIL_NODE)
+ );
- assoc_length = 0;
- }
+ bool first_element = first_chunk && stack_length == 0;
+ bool last_element = index == elements->size - 1;
+ bool only_element = first_element && last_element;
- // If this is the first time we've seen a splat, then we need to
- // create a hash that we can merge into.
- if (!made_hash) {
- PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
- PUSH_INSN1(ret, location, newhash, INT2FIX(0));
- made_hash = true;
+ if (empty_hash) {
+ if (only_element && argument) {
+ // **{} appears at the only keyword argument in method call,
+ // so it won't be modified.
+ //
+ // This is only done for method calls and not for literal
+ // hashes, because literal hashes should always result in a
+ // new hash.
+ PUSH_INSN(ret, location, putnil);
+ }
+ else if (first_element) {
+ // **{} appears as the first keyword argument, so it may be
+ // modified. We need to create a fresh hash object.
+ PUSH_INSN1(ret, location, 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 {
+ if (only_element && argument) {
+ // ** is only keyword argument in the method call. Use it
+ // 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.
+ if (shareability == 0) {
+ PM_COMPILE_NOT_POPPED(element);
+ }
+ else {
+ pm_compile_shareable_constant_value(iseq, element, shareability, path, ret, scope_node, false);
+ }
+ }
+ 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).
+ PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
- // Now compile the splat node itself and merge it into the hash.
- PM_COMPILE_NOT_POPPED(element);
- PUSH_SEND(ret, location, id_core_hash_merge_kwd, INT2FIX(2));
+ if (first_element) {
+ PUSH_INSN1(ret, location, newhash, INT2FIX(0));
+ }
+ else {
+ PUSH_INSN(ret, location, swap);
+ }
- // We know that any subsequent elements will need to be merged in
- // using one of the special core methods. So here we will put the
- // receiver of the merge and then swap it with the hash that is
- // going to be the first argument.
- if (index != elements->size - 1) {
- PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
- PUSH_INSN(ret, location, swap);
+ if (shareability == 0) {
+ PM_COMPILE_NOT_POPPED(element);
+ }
+ else {
+ pm_compile_shareable_constant_value(iseq, element, shareability, path, ret, scope_node, false);
+ }
+
+ PUSH_SEND(ret, location, id_core_hash_merge_kwd, INT2FIX(2));
+ }
}
+ first_chunk = false;
+ static_literal = false;
break;
}
default:
@@ -1379,24 +1576,19 @@ pm_compile_hash_elements(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_l
}
}
- if (!made_hash) {
- // If we haven't already made the hash, then this means we only saw
- // plain assoc nodes. In this case, we can just create the hash
- // directly.
- PUSH_INSN1(ret, location, newhash, INT2FIX(assoc_length * 2));
- }
- else if (assoc_length > 0) {
- // If we have already made the hash, then we need to merge the remaining
- // assoc nodes into the hash on the stack.
- PUSH_SEND(ret, location, id_core_hash_merge_ptr, INT2FIX(assoc_length * 2 + 1));
- }
+ FLUSH_CHUNK;
+#undef FLUSH_CHUNK
}
+#define SPLATARRAY_FALSE 0
+#define SPLATARRAY_TRUE 1
+#define DUP_SINGLE_KW_SPLAT 2
+
// This is details. Users should call pm_setup_args() instead.
static int
-pm_setup_args_core(const pm_arguments_node_t *arguments_node, const pm_node_t *block, int *flags, const bool has_regular_blockarg, struct rb_callinfo_kwarg **kw_arg, rb_iseq_t *iseq, LINK_ANCHOR *const ret, pm_scope_node_t *scope_node, const pm_line_column_t *node_location)
+pm_setup_args_core(const pm_arguments_node_t *arguments_node, const pm_node_t *block, int *flags, const bool has_regular_blockarg, struct rb_callinfo_kwarg **kw_arg, int *dup_rest, rb_iseq_t *iseq, LINK_ANCHOR *const ret, pm_scope_node_t *scope_node, const pm_node_location_t *node_location)
{
- const pm_line_column_t location = *node_location;
+ const pm_node_location_t location = *node_location;
int orig_argc = 0;
bool has_splat = false;
@@ -1426,7 +1618,24 @@ pm_setup_args_core(const pm_arguments_node_t *arguments_node, const pm_node_t *b
if (has_keyword_splat || has_splat) {
*flags |= VM_CALL_KW_SPLAT;
has_keyword_splat = true;
- pm_compile_hash_elements(iseq, argument, elements, ret, scope_node);
+
+ if (elements->size > 1 || !(elements->size == 1 && PM_NODE_TYPE_P(elements->nodes[0], PM_ASSOC_SPLAT_NODE))) {
+ // A new hash will be created for the keyword arguments
+ // in this case, so mark the method as passing mutable
+ // keyword splat.
+ *flags |= VM_CALL_KW_SPLAT_MUT;
+ pm_compile_hash_elements(iseq, argument, elements, 0, Qundef, true, ret, scope_node);
+ }
+ else if (*dup_rest & DUP_SINGLE_KW_SPLAT) {
+ *flags |= VM_CALL_KW_SPLAT_MUT;
+ PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
+ PUSH_INSN1(ret, location, newhash, INT2FIX(0));
+ pm_compile_hash_elements(iseq, argument, elements, 0, Qundef, true, ret, scope_node);
+ PUSH_SEND(ret, location, id_core_hash_merge_kwd, INT2FIX(2));
+ }
+ else {
+ pm_compile_hash_elements(iseq, argument, elements, 0, Qundef, true, ret, scope_node);
+ }
}
else {
// We need to first figure out if all elements of the
@@ -1532,8 +1741,8 @@ pm_setup_args_core(const pm_arguments_node_t *arguments_node, const pm_node_t *b
// foo(a, *b, c)
// ^^
if (index + 1 < arguments->size || has_regular_blockarg) {
- PUSH_INSN1(ret, location, splatarray, Qtrue);
- *flags |= VM_CALL_ARGS_SPLAT_MUT;
+ PUSH_INSN1(ret, location, splatarray, (*dup_rest & SPLATARRAY_TRUE) ? Qtrue : Qfalse);
+ if (*dup_rest & SPLATARRAY_TRUE) *dup_rest &= ~SPLATARRAY_TRUE;
}
// If this is the first spalt array seen and it's the last
// parameter, we don't want splatarray to dup it.
@@ -1551,8 +1760,7 @@ pm_setup_args_core(const pm_arguments_node_t *arguments_node, const pm_node_t *b
//
// foo(a, *b, *c)
// ^^
- PUSH_INSN1(ret, location, splatarray, Qfalse);
- PUSH_INSN(ret, location, concatarray);
+ PUSH_INSN(ret, location, concattoarray);
}
has_splat = true;
@@ -1560,9 +1768,26 @@ pm_setup_args_core(const pm_arguments_node_t *arguments_node, const pm_node_t *b
break;
}
- case PM_FORWARDING_ARGUMENTS_NODE: {
- orig_argc += 2;
- *flags |= VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_SPLAT_MUT | VM_CALL_ARGS_BLOCKARG | VM_CALL_KW_SPLAT;
+ case PM_FORWARDING_ARGUMENTS_NODE: { // not counted in argc return value
+ iseq_set_use_block(ISEQ_BODY(iseq)->local_iseq);
+
+ if (ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->param.flags.forwardable) {
+ *flags |= VM_CALL_FORWARDING;
+
+ pm_local_index_t mult_local = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_DOT3, 0);
+ PUSH_GETLOCAL(ret, location, mult_local.index, mult_local.level);
+
+ break;
+ }
+
+ if (has_splat) {
+ // If we already have a splat, we're concatenating to existing array
+ orig_argc += 1;
+ } else {
+ orig_argc += 2;
+ }
+
+ *flags |= VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_BLOCKARG | VM_CALL_KW_SPLAT;
// Forwarding arguments nodes are treated as foo(*, **, &)
// So foo(...) equals foo(*, **, &) and as such the local
@@ -1571,7 +1796,13 @@ pm_setup_args_core(const pm_arguments_node_t *arguments_node, const pm_node_t *b
// Push the *
pm_local_index_t mult_local = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_MULT, 0);
PUSH_GETLOCAL(ret, location, mult_local.index, mult_local.level);
- PUSH_INSN1(ret, location, splatarray, Qtrue);
+
+ if (has_splat) {
+ // If we already have a splat, we need to concatenate arrays
+ PUSH_INSN(ret, location, concattoarray);
+ } else {
+ PUSH_INSN1(ret, location, splatarray, Qfalse);
+ }
// Push the **
pm_local_index_t pow_local = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_POW, 0);
@@ -1580,7 +1811,6 @@ pm_setup_args_core(const pm_arguments_node_t *arguments_node, const pm_node_t *b
// Push the &
pm_local_index_t and_local = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_AND, 0);
PUSH_INSN2(ret, location, getblockparamproxy, INT2FIX(and_local.index + VM_ENV_DATA_SIZE - 1), INT2FIX(and_local.level));
- PUSH_INSN(ret, location, splatkw);
break;
}
@@ -1603,6 +1833,10 @@ pm_setup_args_core(const pm_arguments_node_t *arguments_node, const pm_node_t *b
// foo(*a, b, c: :d)
// foo(*a, b, **c)
//
+ // If the next node is a forwarding argument:
+ //
+ // foo(*a, b, ...)
+ //
// If the next node is NULL (we have hit the end):
//
// foo(*a, b)
@@ -1625,6 +1859,10 @@ pm_setup_args_core(const pm_arguments_node_t *arguments_node, const pm_node_t *b
PUSH_INSN(ret, location, concatarray);
break;
}
+ case PM_FORWARDING_ARGUMENTS_NODE: {
+ PUSH_INSN1(ret, location, pushtoarray, INT2FIX(post_splat_counter));
+ break;
+ }
default:
break;
}
@@ -1643,17 +1881,121 @@ pm_setup_args_core(const pm_arguments_node_t *arguments_node, const pm_node_t *b
return orig_argc;
}
-// Compile the argument parts of a call
+/**
+ * True if the given kind of node could potentially mutate the array that is
+ * being splatted in a set of call arguments.
+ */
+static inline bool
+pm_setup_args_dup_rest_p(const pm_node_t *node)
+{
+ switch (PM_NODE_TYPE(node)) {
+ case PM_BACK_REFERENCE_READ_NODE:
+ case PM_CLASS_VARIABLE_READ_NODE:
+ case PM_CONSTANT_READ_NODE:
+ case PM_FALSE_NODE:
+ case PM_FLOAT_NODE:
+ case PM_GLOBAL_VARIABLE_READ_NODE:
+ case PM_IMAGINARY_NODE:
+ case PM_INSTANCE_VARIABLE_READ_NODE:
+ case PM_INTEGER_NODE:
+ case PM_LAMBDA_NODE:
+ case PM_LOCAL_VARIABLE_READ_NODE:
+ case PM_NIL_NODE:
+ case PM_NUMBERED_REFERENCE_READ_NODE:
+ case PM_RATIONAL_NODE:
+ case PM_REGULAR_EXPRESSION_NODE:
+ case PM_SELF_NODE:
+ case PM_STRING_NODE:
+ case PM_SYMBOL_NODE:
+ case PM_TRUE_NODE:
+ return false;
+ case PM_CONSTANT_PATH_NODE: {
+ const pm_constant_path_node_t *cast = (const pm_constant_path_node_t *) node;
+ if (cast->parent != NULL) {
+ return pm_setup_args_dup_rest_p(cast->parent);
+ }
+ return false;
+ }
+ case PM_IMPLICIT_NODE:
+ return pm_setup_args_dup_rest_p(((const pm_implicit_node_t *) node)->value);
+ case PM_ARRAY_NODE: {
+ const pm_array_node_t *cast = (const pm_array_node_t *) node;
+ for (size_t index = 0; index < cast->elements.size; index++) {
+ if (pm_setup_args_dup_rest_p(cast->elements.nodes[index])) {
+ return true;
+ }
+ }
+ return false;
+ }
+ default:
+ return true;
+ }
+}
+
+/**
+ * Compile the argument parts of a call.
+ */
static int
-pm_setup_args(const pm_arguments_node_t *arguments_node, const pm_node_t *block, int *flags, struct rb_callinfo_kwarg **kw_arg, rb_iseq_t *iseq, LINK_ANCHOR *const ret, pm_scope_node_t *scope_node, const pm_line_column_t *node_location)
+pm_setup_args(const pm_arguments_node_t *arguments_node, const pm_node_t *block, int *flags, struct rb_callinfo_kwarg **kw_arg, rb_iseq_t *iseq, LINK_ANCHOR *const ret, pm_scope_node_t *scope_node, const pm_node_location_t *node_location)
{
+ int dup_rest = SPLATARRAY_TRUE;
+
+ const pm_node_list_t *arguments;
+ size_t arguments_size;
+
+ // Calls like foo(1, *f, **hash) that use splat and kwsplat could be
+ // eligible for eliding duping the rest array (dup_reset=false).
+ if (
+ arguments_node != NULL &&
+ (arguments = &arguments_node->arguments, arguments_size = arguments->size) >= 2 &&
+ PM_NODE_FLAG_P(arguments_node, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_SPLAT) &&
+ !PM_NODE_FLAG_P(arguments_node, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_MULTIPLE_SPLATS) &&
+ PM_NODE_TYPE_P(arguments->nodes[arguments_size - 1], PM_KEYWORD_HASH_NODE)
+ ) {
+ // Start by assuming that dup_rest=false, then check each element of the
+ // hash to ensure we don't need to flip it back to true (in case one of
+ // the elements could potentially mutate the array).
+ dup_rest = SPLATARRAY_FALSE;
+
+ const pm_keyword_hash_node_t *keyword_hash = (const pm_keyword_hash_node_t *) arguments->nodes[arguments_size - 1];
+ const pm_node_list_t *elements = &keyword_hash->elements;
+
+ for (size_t index = 0; dup_rest == SPLATARRAY_FALSE && index < elements->size; index++) {
+ const pm_node_t *element = elements->nodes[index];
+
+ switch (PM_NODE_TYPE(element)) {
+ case PM_ASSOC_NODE: {
+ const pm_assoc_node_t *assoc = (const pm_assoc_node_t *) element;
+ if (pm_setup_args_dup_rest_p(assoc->key) || pm_setup_args_dup_rest_p(assoc->value)) dup_rest = SPLATARRAY_TRUE;
+ break;
+ }
+ case PM_ASSOC_SPLAT_NODE: {
+ const pm_assoc_splat_node_t *assoc = (const pm_assoc_splat_node_t *) element;
+ if (assoc->value != NULL && pm_setup_args_dup_rest_p(assoc->value)) dup_rest = SPLATARRAY_TRUE;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+
+ int initial_dup_rest = dup_rest;
+ int argc;
+
if (block && PM_NODE_TYPE_P(block, PM_BLOCK_ARGUMENT_NODE)) {
// We compile the `&block_arg` expression first and stitch it later
// since the nature of the expression influences whether splat should
// duplicate the array.
bool regular_block_arg = true;
+ const pm_node_t *block_expr = ((const pm_block_argument_node_t *)block)->expression;
+
+ if (block_expr && pm_setup_args_dup_rest_p(block_expr)) {
+ dup_rest = SPLATARRAY_TRUE | DUP_SINGLE_KW_SPLAT;
+ initial_dup_rest = dup_rest;
+ }
+
DECL_ANCHOR(block_arg);
- INIT_ANCHOR(block_arg);
pm_compile_node(iseq, block, block_arg, false, scope_node);
*flags |= VM_CALL_ARGS_BLOCKARG;
@@ -1665,19 +2007,31 @@ pm_setup_args(const pm_arguments_node_t *arguments_node, const pm_node_t *block,
if (iobj->insn_id == BIN(getblockparam)) {
iobj->insn_id = BIN(getblockparamproxy);
}
+
// Allow splat without duplication for simple one-instruction
- // block arguments like `&arg`. It is known that this optimization
- // can be too aggressive in some cases. See [Bug #16504].
+ // block arguments like `&arg`. It is known that this
+ // optimization can be too aggressive in some cases. See
+ // [Bug #16504].
regular_block_arg = false;
}
}
- int argc = pm_setup_args_core(arguments_node, block, flags, regular_block_arg, kw_arg, iseq, ret, scope_node, node_location);
+ argc = pm_setup_args_core(arguments_node, block, flags, regular_block_arg, kw_arg, &dup_rest, iseq, ret, scope_node, node_location);
PUSH_SEQ(ret, block_arg);
- return argc;
+ }
+ else {
+ argc = pm_setup_args_core(arguments_node, block, flags, false, kw_arg, &dup_rest, iseq, ret, scope_node, node_location);
}
- return pm_setup_args_core(arguments_node, block, flags, false, kw_arg, iseq, ret, scope_node, node_location);
+ // If the dup_rest flag was consumed while compiling the arguments (which
+ // effectively means we found the splat node), then it would have changed
+ // during the call to pm_setup_args_core. In this case, we want to add the
+ // VM_CALL_ARGS_SPLAT_MUT flag.
+ if (*flags & VM_CALL_ARGS_SPLAT && dup_rest != initial_dup_rest) {
+ *flags |= VM_CALL_ARGS_SPLAT_MUT;
+ }
+
+ return argc;
}
/**
@@ -1691,9 +2045,9 @@ pm_setup_args(const pm_arguments_node_t *arguments_node, const pm_node_t *block,
* and then calling the []= method with the result of the operator method.
*/
static void
-pm_compile_index_operator_write_node(rb_iseq_t *iseq, const pm_index_operator_write_node_t *node, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+pm_compile_index_operator_write_node(rb_iseq_t *iseq, const pm_index_operator_write_node_t *node, const pm_node_location_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
{
- const pm_line_column_t location = *node_location;
+ const pm_node_location_t location = *node_location;
if (!popped) PUSH_INSN(ret, location, putnil);
PM_COMPILE_NOT_POPPED(node->receiver);
@@ -1701,7 +2055,7 @@ pm_compile_index_operator_write_node(rb_iseq_t *iseq, const pm_index_operator_wr
int boff = (node->block == NULL ? 0 : 1);
int flag = PM_NODE_TYPE_P(node->receiver, PM_SELF_NODE) ? VM_CALL_FCALL : 0;
struct rb_callinfo_kwarg *keywords = NULL;
- int argc = pm_setup_args(node->arguments, node->block, &flag, &keywords, iseq, ret, scope_node, node_location);
+ int argc = pm_setup_args(node->arguments, (const pm_node_t *) node->block, &flag, &keywords, iseq, ret, scope_node, node_location);
if ((argc > 0 || boff) && (flag & VM_CALL_KW_SPLAT)) {
if (boff) {
@@ -1808,16 +2162,16 @@ pm_compile_index_operator_write_node(rb_iseq_t *iseq, const pm_index_operator_wr
* []= method.
*/
static void
-pm_compile_index_control_flow_write_node(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_t *receiver, const pm_arguments_node_t *arguments, const pm_node_t *block, const pm_node_t *value, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+pm_compile_index_control_flow_write_node(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_t *receiver, const pm_arguments_node_t *arguments, const pm_block_argument_node_t *block, const pm_node_t *value, const pm_node_location_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
{
- const pm_line_column_t location = *node_location;
+ const pm_node_location_t location = *node_location;
if (!popped) PUSH_INSN(ret, location, putnil);
PM_COMPILE_NOT_POPPED(receiver);
int boff = (block == NULL ? 0 : 1);
int flag = PM_NODE_TYPE_P(receiver, PM_SELF_NODE) ? VM_CALL_FCALL : 0;
struct rb_callinfo_kwarg *keywords = NULL;
- int argc = pm_setup_args(arguments, block, &flag, &keywords, iseq, ret, scope_node, node_location);
+ int argc = pm_setup_args(arguments, (const pm_node_t *) block, &flag, &keywords, iseq, ret, scope_node, node_location);
if ((argc > 0 || boff) && (flag & VM_CALL_KW_SPLAT)) {
if (boff) {
@@ -1942,7 +2296,7 @@ pm_compile_index_control_flow_write_node(rb_iseq_t *iseq, const pm_node_t *node,
// A forward declaration because this is the recursive function that handles
// compiling a pattern. It can be reentered by nesting patterns, as in the case
// of arrays or hashes.
-static int pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t *node, LINK_ANCHOR *const ret, LABEL *matched_label, LABEL *unmatched_label, bool in_single_pattern, bool in_alternation_pattern, bool use_deconstructed_cache, unsigned int base_index);
+static int pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t *node, LINK_ANCHOR *const ret, LABEL *matched_label, LABEL *unmatched_label, bool in_single_pattern, bool use_deconstructed_cache, unsigned int base_index);
/**
* This function generates the code to set up the error string and error_p
@@ -1951,7 +2305,7 @@ static int pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, cons
static int
pm_compile_pattern_generic_error(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t *node, LINK_ANCHOR *const ret, VALUE message, unsigned int base_index)
{
- const pm_line_column_t location = PM_NODE_START_LINE_COLUMN(scope_node->parser, node);
+ const pm_node_location_t location = PM_NODE_START_LOCATION(scope_node->parser, node);
LABEL *match_succeeded_label = NEW_LABEL(location.line);
PUSH_INSN(ret, location, dup);
@@ -1981,7 +2335,7 @@ pm_compile_pattern_generic_error(rb_iseq_t *iseq, pm_scope_node_t *scope_node, c
static int
pm_compile_pattern_length_error(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t *node, LINK_ANCHOR *const ret, VALUE message, VALUE length, unsigned int base_index)
{
- const pm_line_column_t location = PM_NODE_START_LINE_COLUMN(scope_node->parser, node);
+ const pm_node_location_t location = PM_NODE_START_LOCATION(scope_node->parser, node);
LABEL *match_succeeded_label = NEW_LABEL(location.line);
PUSH_INSN(ret, location, dup);
@@ -2014,14 +2368,16 @@ pm_compile_pattern_length_error(rb_iseq_t *iseq, pm_scope_node_t *scope_node, co
static int
pm_compile_pattern_eqq_error(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t *node, LINK_ANCHOR *const ret, unsigned int base_index)
{
- const pm_line_column_t location = PM_NODE_START_LINE_COLUMN(scope_node->parser, node);
+ const pm_node_location_t location = PM_NODE_START_LOCATION(scope_node->parser, node);
LABEL *match_succeeded_label = NEW_LABEL(location.line);
PUSH_INSN(ret, location, dup);
PUSH_INSNL(ret, location, branchif, match_succeeded_label);
-
PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
- PUSH_INSN1(ret, location, putobject, rb_fstring_lit("%p === %p does not return true"));
+
+ VALUE operand = rb_fstring_lit("%p === %p does not return true");
+ PUSH_INSN1(ret, location, putobject, operand);
+
PUSH_INSN1(ret, location, topn, INT2FIX(3));
PUSH_INSN1(ret, location, topn, INT2FIX(5));
PUSH_SEND(ret, location, id_core_sprintf, INT2FIX(3));
@@ -2046,10 +2402,10 @@ pm_compile_pattern_eqq_error(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const
* label.
*/
static int
-pm_compile_pattern_match(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t *node, LINK_ANCHOR *const ret, LABEL *unmatched_label, bool in_single_pattern, bool in_alternation_pattern, bool use_deconstructed_cache, unsigned int base_index)
+pm_compile_pattern_match(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t *node, LINK_ANCHOR *const ret, LABEL *unmatched_label, bool in_single_pattern, bool use_deconstructed_cache, unsigned int base_index)
{
LABEL *matched_label = NEW_LABEL(pm_node_line_number(scope_node->parser, node));
- CHECK(pm_compile_pattern(iseq, scope_node, node, ret, matched_label, unmatched_label, in_single_pattern, in_alternation_pattern, use_deconstructed_cache, base_index));
+ CHECK(pm_compile_pattern(iseq, scope_node, node, ret, matched_label, unmatched_label, in_single_pattern, use_deconstructed_cache, base_index));
PUSH_LABEL(ret, matched_label);
return COMPILE_OK;
}
@@ -2062,7 +2418,7 @@ pm_compile_pattern_match(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_
static int
pm_compile_pattern_deconstruct(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t *node, LINK_ANCHOR *const ret, LABEL *deconstruct_label, LABEL *match_failed_label, LABEL *deconstructed_label, LABEL *type_error_label, bool in_single_pattern, bool use_deconstructed_cache, unsigned int base_index)
{
- const pm_line_column_t location = PM_NODE_START_LINE_COLUMN(scope_node->parser, node);
+ const pm_node_location_t location = PM_NODE_START_LOCATION(scope_node->parser, node);
if (use_deconstructed_cache) {
PUSH_INSN1(ret, location, topn, INT2FIX(base_index + PM_PATTERN_BASE_INDEX_OFFSET_DECONSTRUCTED_CACHE));
@@ -2081,7 +2437,9 @@ pm_compile_pattern_deconstruct(rb_iseq_t *iseq, pm_scope_node_t *scope_node, con
PUSH_LABEL(ret, deconstruct_label);
PUSH_INSN(ret, location, dup);
- PUSH_INSN1(ret, location, putobject, ID2SYM(rb_intern("deconstruct")));
+
+ VALUE operand = ID2SYM(rb_intern("deconstruct"));
+ PUSH_INSN1(ret, location, putobject, operand);
PUSH_SEND(ret, location, idRespond_to, INT2FIX(1));
if (use_deconstructed_cache) {
@@ -2114,7 +2472,7 @@ pm_compile_pattern_deconstruct(rb_iseq_t *iseq, pm_scope_node_t *scope_node, con
static int
pm_compile_pattern_constant(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t *node, LINK_ANCHOR *const ret, LABEL *match_failed_label, bool in_single_pattern, unsigned int base_index)
{
- const pm_line_column_t location = PM_NODE_START_LINE_COLUMN(scope_node->parser, node);
+ const pm_node_location_t location = PM_NODE_START_LOCATION(scope_node->parser, node);
PUSH_INSN(ret, location, dup);
PM_COMPILE_NOT_POPPED(node);
@@ -2137,7 +2495,7 @@ pm_compile_pattern_constant(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const
static void
pm_compile_pattern_error_handler(rb_iseq_t *iseq, const pm_scope_node_t *scope_node, const pm_node_t *node, LINK_ANCHOR *const ret, LABEL *done_label, bool popped)
{
- const pm_line_column_t location = PM_NODE_START_LINE_COLUMN(scope_node->parser, node);
+ const pm_node_location_t location = PM_NODE_START_LOCATION(scope_node->parser, node);
LABEL *key_error_label = NEW_LABEL(location.line);
LABEL *cleanup_label = NEW_LABEL(location.line);
@@ -2153,7 +2511,12 @@ pm_compile_pattern_error_handler(rb_iseq_t *iseq, const pm_scope_node_t *scope_n
PUSH_INSN1(ret, location, putobject, rb_eNoMatchingPatternError);
PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
- PUSH_INSN1(ret, location, putobject, rb_fstring_lit("%p: %s"));
+
+ {
+ VALUE operand = rb_fstring_lit("%p: %s");
+ PUSH_INSN1(ret, location, putobject, operand);
+ }
+
PUSH_INSN1(ret, location, topn, INT2FIX(4));
PUSH_INSN1(ret, location, topn, INT2FIX(PM_PATTERN_BASE_INDEX_OFFSET_ERROR_STRING + 6));
PUSH_SEND(ret, location, id_core_sprintf, INT2FIX(3));
@@ -2163,7 +2526,12 @@ pm_compile_pattern_error_handler(rb_iseq_t *iseq, const pm_scope_node_t *scope_n
PUSH_LABEL(ret, key_error_label);
PUSH_INSN1(ret, location, putobject, rb_eNoMatchingPatternKeyError);
PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
- PUSH_INSN1(ret, location, putobject, rb_fstring_lit("%p: %s"));
+
+ {
+ VALUE operand = rb_fstring_lit("%p: %s");
+ PUSH_INSN1(ret, location, putobject, operand);
+ }
+
PUSH_INSN1(ret, location, topn, INT2FIX(4));
PUSH_INSN1(ret, location, topn, INT2FIX(PM_PATTERN_BASE_INDEX_OFFSET_ERROR_STRING + 6));
PUSH_SEND(ret, location, id_core_sprintf, INT2FIX(3));
@@ -2184,9 +2552,9 @@ pm_compile_pattern_error_handler(rb_iseq_t *iseq, const pm_scope_node_t *scope_n
* Compile a pattern matching expression.
*/
static int
-pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t *node, LINK_ANCHOR *const ret, LABEL *matched_label, LABEL *unmatched_label, bool in_single_pattern, bool in_alternation_pattern, bool use_deconstructed_cache, unsigned int base_index)
+pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t *node, LINK_ANCHOR *const ret, LABEL *matched_label, LABEL *unmatched_label, bool in_single_pattern, bool use_deconstructed_cache, unsigned int base_index)
{
- const pm_line_column_t location = PM_NODE_START_LINE_COLUMN(scope_node->parser, node);
+ const pm_node_location_t location = PM_NODE_START_LOCATION(scope_node->parser, node);
switch (PM_NODE_TYPE(node)) {
case PM_ARRAY_PATTERN_NODE: {
@@ -2244,7 +2612,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t
PUSH_INSN(ret, location, dup);
PUSH_INSN1(ret, location, putobject, INT2FIX(index));
PUSH_SEND(ret, location, idAREF, INT2FIX(1));
- CHECK(pm_compile_pattern_match(iseq, scope_node, required, ret, match_failed_label, in_single_pattern, in_alternation_pattern, false, base_index + 1));
+ CHECK(pm_compile_pattern_match(iseq, scope_node, required, ret, match_failed_label, in_single_pattern, false, base_index + 1));
}
if (cast->rest != NULL) {
@@ -2257,7 +2625,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t
PUSH_SEND(ret, location, idMINUS, INT2FIX(1));
PUSH_INSN1(ret, location, setn, INT2FIX(4));
PUSH_SEND(ret, location, idAREF, INT2FIX(2));
- CHECK(pm_compile_pattern_match(iseq, scope_node, ((const pm_splat_node_t *) cast->rest)->expression, ret, match_failed_label, in_single_pattern, in_alternation_pattern, false, base_index + 1));
+ CHECK(pm_compile_pattern_match(iseq, scope_node, ((const pm_splat_node_t *) cast->rest)->expression, ret, match_failed_label, in_single_pattern, false, base_index + 1));
}
else if (posts_size > 0) {
PUSH_INSN(ret, location, dup);
@@ -2277,7 +2645,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t
PUSH_INSN1(ret, location, topn, INT2FIX(3));
PUSH_SEND(ret, location, idPLUS, INT2FIX(1));
PUSH_SEND(ret, location, idAREF, INT2FIX(1));
- CHECK(pm_compile_pattern_match(iseq, scope_node, post, ret, match_failed_label, in_single_pattern, in_alternation_pattern, false, base_index + 1));
+ CHECK(pm_compile_pattern_match(iseq, scope_node, post, ret, match_failed_label, in_single_pattern, false, base_index + 1));
}
PUSH_INSN(ret, location, pop);
@@ -2294,7 +2662,12 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t
PUSH_LABEL(ret, type_error_label);
PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
PUSH_INSN1(ret, location, putobject, rb_eTypeError);
- PUSH_INSN1(ret, location, putobject, rb_fstring_lit("deconstruct must return Array"));
+
+ {
+ VALUE operand = rb_fstring_lit("deconstruct must return Array");
+ PUSH_INSN1(ret, location, putobject, operand);
+ }
+
PUSH_SEND(ret, location, id_core_raise, INT2FIX(2));
PUSH_INSN(ret, location, pop);
@@ -2369,18 +2742,17 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t
}
PUSH_SEND(ret, location, idAREF, INT2FIX(1));
- CHECK(pm_compile_pattern_match(iseq, scope_node, cast->requireds.nodes[index], ret, next_loop_label, in_single_pattern, in_alternation_pattern, false, base_index + 4));
+ CHECK(pm_compile_pattern_match(iseq, scope_node, cast->requireds.nodes[index], ret, next_loop_label, in_single_pattern, false, base_index + 4));
}
- RUBY_ASSERT(PM_NODE_TYPE_P(cast->left, PM_SPLAT_NODE));
- const pm_splat_node_t *left = (const pm_splat_node_t *) cast->left;
+ const pm_splat_node_t *left = cast->left;
if (left->expression != NULL) {
PUSH_INSN1(ret, location, topn, INT2FIX(3));
PUSH_INSN1(ret, location, putobject, INT2FIX(0));
PUSH_INSN1(ret, location, topn, INT2FIX(2));
PUSH_SEND(ret, location, idAREF, INT2FIX(2));
- CHECK(pm_compile_pattern_match(iseq, scope_node, left->expression, ret, find_failed_label, in_single_pattern, in_alternation_pattern, false, base_index + 4));
+ CHECK(pm_compile_pattern_match(iseq, scope_node, left->expression, ret, find_failed_label, in_single_pattern, false, base_index + 4));
}
RUBY_ASSERT(PM_NODE_TYPE_P(cast->right, PM_SPLAT_NODE));
@@ -2393,7 +2765,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t
PUSH_SEND(ret, location, idPLUS, INT2FIX(1));
PUSH_INSN1(ret, location, topn, INT2FIX(3));
PUSH_SEND(ret, location, idAREF, INT2FIX(2));
- pm_compile_pattern_match(iseq, scope_node, right->expression, ret, find_failed_label, in_single_pattern, in_alternation_pattern, false, base_index + 4);
+ pm_compile_pattern_match(iseq, scope_node, right->expression, ret, find_failed_label, in_single_pattern, false, base_index + 4);
}
PUSH_INSNL(ret, location, jump, find_succeeded_label);
@@ -2407,7 +2779,12 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t
PUSH_INSN1(ret, location, adjuststack, INT2FIX(3));
if (in_single_pattern) {
PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
- PUSH_INSN1(ret, location, putobject, rb_fstring_lit("%p does not match to find pattern"));
+
+ {
+ VALUE operand = rb_fstring_lit("%p does not match to find pattern");
+ PUSH_INSN1(ret, location, putobject, operand);
+ }
+
PUSH_INSN1(ret, location, topn, INT2FIX(2));
PUSH_SEND(ret, location, id_core_sprintf, INT2FIX(2));
PUSH_INSN1(ret, location, setn, INT2FIX(base_index + PM_PATTERN_BASE_INDEX_OFFSET_ERROR_STRING + 1));
@@ -2432,7 +2809,12 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t
PUSH_LABEL(ret, type_error_label);
PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
PUSH_INSN1(ret, location, putobject, rb_eTypeError);
- PUSH_INSN1(ret, location, putobject, rb_fstring_lit("deconstruct must return Array"));
+
+ {
+ VALUE operand = rb_fstring_lit("deconstruct must return Array");
+ PUSH_INSN1(ret, location, putobject, operand);
+ }
+
PUSH_SEND(ret, location, id_core_raise, INT2FIX(2));
PUSH_INSN(ret, location, pop);
@@ -2481,7 +2863,12 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t
}
PUSH_INSN(ret, location, dup);
- PUSH_INSN1(ret, location, putobject, ID2SYM(rb_intern("deconstruct_keys")));
+
+ {
+ VALUE operand = ID2SYM(rb_intern("deconstruct_keys"));
+ PUSH_INSN1(ret, location, putobject, operand);
+ }
+
PUSH_SEND(ret, location, idRespond_to, INT2FIX(1));
if (in_single_pattern) {
CHECK(pm_compile_pattern_generic_error(iseq, scope_node, node, ret, rb_fstring_lit("%p does not respond to #deconstruct_keys"), base_index + 1));
@@ -2492,8 +2879,10 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t
PUSH_INSN(ret, location, putnil);
}
else {
+ rb_obj_hide(keys);
+ RB_OBJ_SET_FROZEN_SHAREABLE(keys);
PUSH_INSN1(ret, location, duparray, keys);
- RB_OBJ_WRITTEN(iseq, Qundef, rb_obj_hide(keys));
+ RB_OBJ_WRITTEN(iseq, Qundef, keys);
}
PUSH_SEND(ret, location, rb_intern("deconstruct_keys"), INT2FIX(1));
@@ -2507,7 +2896,6 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t
if (has_keys) {
DECL_ANCHOR(match_values);
- INIT_ANCHOR(match_values);
for (size_t index = 0; index < cast->elements.size; index++) {
const pm_node_t *element = cast->elements.nodes[index];
@@ -2528,7 +2916,12 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t
PUSH_INSN(ret, location, dup);
PUSH_INSNL(ret, location, branchif, match_succeeded_label);
- PUSH_INSN1(ret, location, putobject, rb_str_freeze(rb_sprintf("key not found: %+"PRIsVALUE, symbol)));
+ {
+ VALUE operand = rb_str_freeze(rb_sprintf("key not found: %+"PRIsVALUE, symbol));
+ RB_OBJ_SET_SHAREABLE(operand);
+ PUSH_INSN1(ret, location, putobject, operand);
+ }
+
PUSH_INSN1(ret, location, setn, INT2FIX(base_index + PM_PATTERN_BASE_INDEX_OFFSET_ERROR_STRING + 2));
PUSH_INSN1(ret, location, putobject, Qtrue);
PUSH_INSN1(ret, location, setn, INT2FIX(base_index + PM_PATTERN_BASE_INDEX_OFFSET_KEY_ERROR_P + 3));
@@ -2551,7 +2944,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t
value = ((const pm_implicit_node_t *) value)->value;
}
- CHECK(pm_compile_pattern_match(iseq, scope_node, value, match_values, match_failed_label, in_single_pattern, in_alternation_pattern, false, base_index + 1));
+ CHECK(pm_compile_pattern_match(iseq, scope_node, value, match_values, match_failed_label, in_single_pattern, false, base_index + 1));
}
PUSH_SEQ(ret, match_values);
@@ -2579,7 +2972,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t
case PM_ASSOC_SPLAT_NODE: {
const pm_assoc_splat_node_t *splat = (const pm_assoc_splat_node_t *) cast->rest;
PUSH_INSN(ret, location, dup);
- pm_compile_pattern_match(iseq, scope_node, splat->value, ret, match_failed_label, in_single_pattern, in_alternation_pattern, false, base_index + 1);
+ pm_compile_pattern_match(iseq, scope_node, splat->value, ret, match_failed_label, in_single_pattern, false, base_index + 1);
break;
}
default:
@@ -2595,7 +2988,12 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t
PUSH_LABEL(ret, type_error_label);
PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
PUSH_INSN1(ret, location, putobject, rb_eTypeError);
- PUSH_INSN1(ret, location, putobject, rb_fstring_lit("deconstruct_keys must return Hash"));
+
+ {
+ VALUE operand = rb_fstring_lit("deconstruct_keys must return Hash");
+ PUSH_INSN1(ret, location, putobject, operand);
+ }
+
PUSH_SEND(ret, location, id_core_raise, INT2FIX(2));
PUSH_INSN(ret, location, pop);
@@ -2619,8 +3017,8 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t
LABEL *match_failed_label = NEW_LABEL(location.line);
PUSH_INSN(ret, location, dup);
- CHECK(pm_compile_pattern_match(iseq, scope_node, cast->value, ret, match_failed_label, in_single_pattern, in_alternation_pattern, use_deconstructed_cache, base_index + 1));
- CHECK(pm_compile_pattern(iseq, scope_node, cast->target, ret, matched_label, match_failed_label, in_single_pattern, in_alternation_pattern, false, base_index));
+ CHECK(pm_compile_pattern_match(iseq, scope_node, cast->value, ret, match_failed_label, in_single_pattern, use_deconstructed_cache, base_index + 1));
+ CHECK(pm_compile_pattern(iseq, scope_node, (const pm_node_t *) cast->target, ret, matched_label, match_failed_label, in_single_pattern, false, base_index));
PUSH_INSN(ret, location, putnil);
PUSH_LABEL(ret, match_failed_label);
@@ -2636,20 +3034,6 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t
const pm_local_variable_target_node_t *cast = (const pm_local_variable_target_node_t *) node;
pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, cast->name, cast->depth);
- // If this local variable is being written from within an alternation
- // pattern, then it cannot actually be added to the local table since
- // it's ambiguous which value should be used. So instead we indicate
- // this with a compile error.
- if (in_alternation_pattern) {
- ID id = pm_constant_id_lookup(scope_node, cast->name);
- const char *name = rb_id2name(id);
-
- if (name && strlen(name) > 0 && name[0] != '_') {
- COMPILE_ERROR(iseq, location.line, "illegal variable in alternative pattern (%"PRIsVALUE")", rb_id2str(id));
- return COMPILE_NG;
- }
- }
-
PUSH_SETLOCAL(ret, location, index.index, index.level);
PUSH_INSNL(ret, location, jump, matched_label);
break;
@@ -2665,7 +3049,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t
// First, we're going to attempt to match against the left pattern. If
// that pattern matches, then we'll skip matching the right pattern.
PUSH_INSN(ret, location, dup);
- CHECK(pm_compile_pattern(iseq, scope_node, cast->left, ret, matched_left_label, unmatched_left_label, in_single_pattern, true, true, base_index + 1));
+ CHECK(pm_compile_pattern(iseq, scope_node, cast->left, ret, matched_left_label, unmatched_left_label, in_single_pattern, use_deconstructed_cache, base_index + 1));
// If we get here, then we matched on the left pattern. In this case we
// should pop out the duplicate value that we preemptively added to
@@ -2678,7 +3062,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t
// If we get here, then we didn't match on the left pattern. In this
// case we attempt to match against the right pattern.
PUSH_LABEL(ret, unmatched_left_label);
- CHECK(pm_compile_pattern(iseq, scope_node, cast->right, ret, matched_label, unmatched_label, in_single_pattern, true, true, base_index));
+ CHECK(pm_compile_pattern(iseq, scope_node, cast->right, ret, matched_label, unmatched_label, in_single_pattern, use_deconstructed_cache, base_index));
break;
}
case PM_PARENTHESES_NODE:
@@ -2686,7 +3070,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t
// they do nothing since they can only wrap individual expressions and
// not groups. In this case we'll recurse back into this same function
// with the body of the parentheses.
- return pm_compile_pattern(iseq, scope_node, ((const pm_parentheses_node_t *) node)->body, ret, matched_label, unmatched_label, in_single_pattern, in_alternation_pattern, use_deconstructed_cache, base_index);
+ return pm_compile_pattern(iseq, scope_node, ((const pm_parentheses_node_t *) node)->body, ret, matched_label, unmatched_label, in_single_pattern, use_deconstructed_cache, base_index);
case PM_PINNED_EXPRESSION_NODE:
// Pinned expressions are a way to match against the value of an
// expression that should be evaluated at runtime. This looks like:
@@ -2703,6 +3087,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t
case PM_GLOBAL_VARIABLE_READ_NODE:
case PM_IMAGINARY_NODE:
case PM_INSTANCE_VARIABLE_READ_NODE:
+ case PM_IT_LOCAL_VARIABLE_READ_NODE:
case PM_INTEGER_NODE:
case PM_INTERPOLATED_REGULAR_EXPRESSION_NODE:
case PM_INTERPOLATED_STRING_NODE:
@@ -2746,7 +3131,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t
// looks like: foo in ^@bar. To compile these, we compile the variable
// that they hold.
const pm_pinned_variable_node_t *cast = (const pm_pinned_variable_node_t *) node;
- CHECK(pm_compile_pattern(iseq, scope_node, cast->variable, ret, matched_label, unmatched_label, in_single_pattern, in_alternation_pattern, true, base_index));
+ CHECK(pm_compile_pattern(iseq, scope_node, cast->variable, ret, matched_label, unmatched_label, in_single_pattern, true, base_index));
break;
}
case PM_IF_NODE:
@@ -2780,7 +3165,7 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t
statement = cast->statements->body.nodes[0];
}
- CHECK(pm_compile_pattern_match(iseq, scope_node, statement, ret, unmatched_label, in_single_pattern, in_alternation_pattern, use_deconstructed_cache, base_index));
+ CHECK(pm_compile_pattern_match(iseq, scope_node, statement, ret, unmatched_label, in_single_pattern, use_deconstructed_cache, base_index));
PM_COMPILE_NOT_POPPED(predicate);
if (in_single_pattern) {
@@ -2794,7 +3179,11 @@ pm_compile_pattern(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_t
PUSH_INSNL(ret, location, branchunless, match_succeeded_label);
}
- PUSH_INSN1(ret, location, putobject, rb_fstring_lit("guard clause does not return true"));
+ {
+ VALUE operand = rb_fstring_lit("guard clause does not return true");
+ PUSH_INSN1(ret, location, putobject, operand);
+ }
+
PUSH_INSN1(ret, location, setn, INT2FIX(base_index + PM_PATTERN_BASE_INDEX_OFFSET_ERROR_STRING + 1));
PUSH_INSN1(ret, location, putobject, Qfalse);
PUSH_INSN1(ret, location, setn, INT2FIX(base_index + PM_PATTERN_BASE_INDEX_OFFSET_KEY_ERROR_P + 2));
@@ -2853,6 +3242,7 @@ pm_scope_node_init(const pm_node_t *node, pm_scope_node_t *scope, pm_scope_node_
scope->filepath_encoding = previous->filepath_encoding;
scope->constants = previous->constants;
scope->coverage_enabled = previous->coverage_enabled;
+ scope->script_lines = previous->script_lines;
}
switch (PM_NODE_TYPE(node)) {
@@ -2902,13 +3292,6 @@ pm_scope_node_init(const pm_node_t *node, pm_scope_node_t *scope, pm_scope_node_
scope->parameters = cast->parameters;
scope->body = cast->body;
scope->locals = cast->locals;
-
- if (cast->parameters != NULL) {
- scope->base.location.start = cast->parameters->location.start;
- }
- else {
- scope->base.location.start = cast->operator_loc.end;
- }
break;
}
case PM_MODULE_NODE: {
@@ -2972,7 +3355,7 @@ pm_scope_node_destroy(pm_scope_node_t *scope_node)
* Normally, "send" instruction is at the last. However, qcall under branch
* coverage measurement adds some instructions after the "send".
*
- * Note that "invokesuper" appears instead of "send".
+ * Note that "invokesuper", "invokesuperforward" appears instead of "send".
*/
static void
pm_compile_retry_end_label(rb_iseq_t *iseq, LINK_ANCHOR *const ret, LABEL *retry_end_l)
@@ -2980,7 +3363,7 @@ pm_compile_retry_end_label(rb_iseq_t *iseq, LINK_ANCHOR *const ret, LABEL *retry
INSN *iobj;
LINK_ELEMENT *last_elem = LAST_ELEMENT(ret);
iobj = IS_INSN(last_elem) ? (INSN*) last_elem : (INSN*) get_prev_insn((INSN*) last_elem);
- while (INSN_OF(iobj) != BIN(send) && INSN_OF(iobj) != BIN(invokesuper)) {
+ while (!IS_INSN_ID(iobj, send) && !IS_INSN_ID(iobj, invokesuper) && !IS_INSN_ID(iobj, sendforward) && !IS_INSN_ID(iobj, invokesuperforward)) {
iobj = (INSN*) get_prev_insn(iobj);
}
ELEM_INSERT_NEXT(&iobj->link, (LINK_ELEMENT*) retry_end_l);
@@ -3028,7 +3411,7 @@ pm_iseq_builtin_function_name(const pm_scope_node_t *scope_node, const pm_node_t
// Compile Primitive.attr! :leaf, ...
static int
-pm_compile_builtin_attr(rb_iseq_t *iseq, const pm_scope_node_t *scope_node, const pm_arguments_node_t *arguments, const pm_line_column_t *node_location)
+pm_compile_builtin_attr(rb_iseq_t *iseq, const pm_scope_node_t *scope_node, const pm_arguments_node_t *arguments, const pm_node_location_t *node_location)
{
if (arguments == NULL) {
COMPILE_ERROR(iseq, node_location->line, "attr!: no argument");
@@ -3043,7 +3426,7 @@ pm_compile_builtin_attr(rb_iseq_t *iseq, const pm_scope_node_t *scope_node, cons
}
VALUE symbol = pm_static_literal_value(iseq, argument, scope_node);
- VALUE string = rb_sym_to_s(symbol);
+ VALUE string = rb_sym2str(symbol);
if (strcmp(RSTRING_PTR(string), "leaf") == 0) {
ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_LEAF;
@@ -3054,6 +3437,10 @@ pm_compile_builtin_attr(rb_iseq_t *iseq, const pm_scope_node_t *scope_node, cons
else if (strcmp(RSTRING_PTR(string), "use_block") == 0) {
iseq_set_use_block(iseq);
}
+ else if (strcmp(RSTRING_PTR(string), "c_trace") == 0) {
+ // Let the iseq act like a C method in backtraces
+ ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_C_TRACE;
+ }
else {
COMPILE_ERROR(iseq, node_location->line, "unknown argument to attr!: %s", RSTRING_PTR(string));
return COMPILE_NG;
@@ -3064,7 +3451,7 @@ pm_compile_builtin_attr(rb_iseq_t *iseq, const pm_scope_node_t *scope_node, cons
}
static int
-pm_compile_builtin_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const pm_scope_node_t *scope_node, const pm_arguments_node_t *arguments, const pm_line_column_t *node_location, int popped)
+pm_compile_builtin_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const pm_scope_node_t *scope_node, const pm_arguments_node_t *arguments, const pm_node_location_t *node_location, int popped)
{
if (arguments == NULL) {
COMPILE_ERROR(iseq, node_location->line, "arg!: no argument");
@@ -3094,7 +3481,7 @@ pm_compile_builtin_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const pm_scope_n
}
static int
-pm_compile_builtin_mandatory_only_method(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_call_node_t *call_node, const pm_line_column_t *node_location)
+pm_compile_builtin_mandatory_only_method(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_call_node_t *call_node, const pm_node_location_t *node_location)
{
const pm_node_t *ast_node = scope_node->ast_node;
if (!PM_NODE_TYPE_P(ast_node, PM_DEF_NODE)) {
@@ -3142,7 +3529,8 @@ pm_compile_builtin_mandatory_only_method(rb_iseq_t *iseq, pm_scope_node_t *scope
pm_scope_node_t next_scope_node;
pm_scope_node_init(&def.base, &next_scope_node, scope_node);
- ISEQ_BODY(iseq)->mandatory_only_iseq = pm_iseq_new_with_opt(
+ int error_state;
+ const rb_iseq_t *mandatory_only_iseq = pm_iseq_new_with_opt(
&next_scope_node,
rb_iseq_base_label(iseq),
rb_iseq_path(iseq),
@@ -3151,15 +3539,22 @@ pm_compile_builtin_mandatory_only_method(rb_iseq_t *iseq, pm_scope_node_t *scope
NULL,
0,
ISEQ_TYPE_METHOD,
- ISEQ_COMPILE_DATA(iseq)->option
+ ISEQ_COMPILE_DATA(iseq)->option,
+ &error_state
);
+ RB_OBJ_WRITE(iseq, &ISEQ_BODY(iseq)->mandatory_only_iseq, (VALUE)mandatory_only_iseq);
+
+ if (error_state) {
+ RUBY_ASSERT(ISEQ_BODY(iseq)->mandatory_only_iseq == NULL);
+ rb_jump_tag(error_state);
+ }
pm_scope_node_destroy(&next_scope_node);
return COMPILE_OK;
}
static int
-pm_compile_builtin_function_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, pm_scope_node_t *scope_node, const pm_call_node_t *call_node, const pm_line_column_t *node_location, int popped, const rb_iseq_t *parent_block, const char *builtin_func)
+pm_compile_builtin_function_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, pm_scope_node_t *scope_node, const pm_call_node_t *call_node, const pm_node_location_t *node_location, int popped, const rb_iseq_t *parent_block, const char *builtin_func)
{
const pm_arguments_node_t *arguments = call_node->arguments;
@@ -3219,7 +3614,7 @@ retry:;
if (cconst) {
typedef VALUE(*builtin_func0)(void *, VALUE);
- VALUE const_val = (*(builtin_func0)bf->func_ptr)(NULL, Qnil);
+ VALUE const_val = (*(builtin_func0)(uintptr_t)bf->func_ptr)(NULL, Qnil);
PUSH_INSN1(ret, *node_location, putobject, const_val);
return COMPILE_OK;
}
@@ -3227,7 +3622,6 @@ retry:;
// fprintf(stderr, "func_name:%s -> %p\n", builtin_func, bf->func_ptr);
DECL_ANCHOR(args_seq);
- INIT_ANCHOR(args_seq);
int flags = 0;
struct rb_callinfo_kwarg *keywords = NULL;
@@ -3260,14 +3654,15 @@ pm_compile_call(rb_iseq_t *iseq, const pm_call_node_t *call_node, LINK_ANCHOR *c
const pm_location_t *message_loc = &call_node->message_loc;
if (message_loc->start == NULL) message_loc = &call_node->base.location;
- const pm_line_column_t location = PM_LOCATION_START_LINE_COLUMN(scope_node->parser, message_loc);
+ const pm_node_location_t location = PM_LOCATION_START_LOCATION(scope_node->parser, message_loc, call_node->base.node_id);
+
LABEL *else_label = NEW_LABEL(location.line);
LABEL *end_label = NEW_LABEL(location.line);
LABEL *retry_end_l = NEW_LABEL(location.line);
VALUE branches = Qfalse;
rb_code_location_t code_location = { 0 };
- int node_id = location.column;
+ int node_id = location.node_id;
if (PM_NODE_FLAG_P(call_node, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) {
if (PM_BRANCH_COVERAGE_P(iseq)) {
@@ -3280,6 +3675,7 @@ pm_compile_call(rb_iseq_t *iseq, const pm_call_node_t *call_node, LINK_ANCHOR *c
const uint8_t *end_cursor = cursors[0];
end_cursor = (end_cursor == NULL || cursors[1] == NULL) ? cursors[1] : (end_cursor > cursors[1] ? end_cursor : cursors[1]);
end_cursor = (end_cursor == NULL || cursors[2] == NULL) ? cursors[2] : (end_cursor > cursors[2] ? end_cursor : cursors[2]);
+ if (!end_cursor) end_cursor = call_node->closing_loc.end;
const pm_line_column_t start_location = PM_NODE_START_LINE_COLUMN(scope_node->parser, call_node);
const pm_line_column_t end_location = pm_newline_list_line_column(&scope_node->parser->newline_list, end_cursor, scope_node->parser->start_line);
@@ -3298,6 +3694,8 @@ pm_compile_call(rb_iseq_t *iseq, const pm_call_node_t *call_node, LINK_ANCHOR *c
add_trace_branch_coverage(iseq, ret, &code_location, node_id, 0, "then", branches);
}
+ LINK_ELEMENT *opt_new_prelude = LAST_ELEMENT(ret);
+
int flags = 0;
struct rb_callinfo_kwarg *kw_arg = NULL;
@@ -3354,7 +3752,50 @@ pm_compile_call(rb_iseq_t *iseq, const pm_call_node_t *call_node, LINK_ANCHOR *c
PUSH_INSN(ret, location, splatkw);
}
- PUSH_SEND_R(ret, location, method_id, INT2FIX(orig_argc), block_iseq, INT2FIX(flags), kw_arg);
+ LABEL *not_basic_new = NEW_LABEL(location.line);
+ LABEL *not_basic_new_finish = NEW_LABEL(location.line);
+
+ bool inline_new = ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction &&
+ method_id == rb_intern("new") &&
+ call_node->block == NULL &&
+ (flags & VM_CALL_ARGS_BLOCKARG) == 0;
+
+ if (inline_new) {
+ if (LAST_ELEMENT(ret) == opt_new_prelude) {
+ PUSH_INSN(ret, location, putnil);
+ PUSH_INSN(ret, location, swap);
+ }
+ else {
+ ELEM_INSERT_NEXT(opt_new_prelude, &new_insn_body(iseq, location.line, location.node_id, BIN(swap), 0)->link);
+ ELEM_INSERT_NEXT(opt_new_prelude, &new_insn_body(iseq, location.line, location.node_id, BIN(putnil), 0)->link);
+ }
+
+ // Jump unless the receiver uses the "basic" implementation of "new"
+ VALUE ci;
+ if (flags & VM_CALL_FORWARDING) {
+ ci = (VALUE)new_callinfo(iseq, method_id, orig_argc + 1, flags, kw_arg, 0);
+ }
+ else {
+ ci = (VALUE)new_callinfo(iseq, method_id, orig_argc, flags, kw_arg, 0);
+ }
+
+ PUSH_INSN2(ret, location, opt_new, ci, not_basic_new);
+ LABEL_REF(not_basic_new);
+ // optimized path
+ PUSH_SEND_R(ret, location, rb_intern("initialize"), INT2FIX(orig_argc), block_iseq, INT2FIX(flags | VM_CALL_FCALL), kw_arg);
+ PUSH_INSNL(ret, location, jump, not_basic_new_finish);
+
+ PUSH_LABEL(ret, not_basic_new);
+ // Fall back to normal send
+ PUSH_SEND_R(ret, location, method_id, INT2FIX(orig_argc), block_iseq, INT2FIX(flags), kw_arg);
+ PUSH_INSN(ret, location, swap);
+
+ PUSH_LABEL(ret, not_basic_new_finish);
+ PUSH_INSN(ret, location, pop);
+ }
+ else {
+ PUSH_SEND_R(ret, location, method_id, INT2FIX(orig_argc), block_iseq, INT2FIX(flags), kw_arg);
+ }
if (block_iseq && ISEQ_BODY(block_iseq)->catch_table) {
pm_compile_retry_end_label(iseq, ret, retry_end_l);
@@ -3376,202 +3817,585 @@ pm_compile_call(rb_iseq_t *iseq, const pm_call_node_t *call_node, LINK_ANCHOR *c
ISEQ_COMPILE_DATA(iseq)->current_block = previous_block;
}
+/**
+ * Compile and return the VALUE associated with the given back reference read
+ * node.
+ */
+static inline VALUE
+pm_compile_back_reference_ref(const pm_back_reference_read_node_t *node)
+{
+ const char *type = (const char *) (node->base.location.start + 1);
+
+ // Since a back reference is `$<char>`, Ruby represents the ID as an
+ // rb_intern on the value after the `$`.
+ return INT2FIX(rb_intern2(type, 1)) << 1 | 1;
+}
+
+/**
+ * Compile and return the VALUE associated with the given numbered reference
+ * read node.
+ */
+static inline VALUE
+pm_compile_numbered_reference_ref(const pm_numbered_reference_read_node_t *node)
+{
+ return INT2FIX(node->number << 1);
+}
+
static void
-pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node, bool in_condition, LABEL **lfinish, bool explicit_receiver)
+pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_location_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node, bool in_condition, LABEL **lfinish, bool explicit_receiver)
{
+#define PUSH_VAL(type) (in_condition ? Qtrue : rb_iseq_defined_string(type))
+
// in_condition is the same as compile.c's needstr
enum defined_type dtype = DEFINED_NOT_DEFINED;
- const pm_line_column_t location = *node_location;
+ const pm_node_location_t location = *node_location;
switch (PM_NODE_TYPE(node)) {
- case PM_ARGUMENTS_NODE: {
- const pm_arguments_node_t *cast = (const pm_arguments_node_t *) node;
- const pm_node_list_t *arguments = &cast->arguments;
- for (size_t idx = 0; idx < arguments->size; idx++) {
- const pm_node_t *argument = arguments->nodes[idx];
- pm_compile_defined_expr0(iseq, argument, node_location, ret, popped, scope_node, in_condition, lfinish, explicit_receiver);
-
- if (!lfinish[1]) {
- lfinish[1] = NEW_LABEL(location.line);
- }
- PUSH_INSNL(ret, location, branchunless, lfinish[1]);
- }
- dtype = DEFINED_TRUE;
- break;
- }
+/* DEFINED_NIL ****************************************************************/
case PM_NIL_NODE:
+ // defined?(nil)
+ // ^^^
dtype = DEFINED_NIL;
break;
- case PM_PARENTHESES_NODE: {
- const pm_parentheses_node_t *cast = (const pm_parentheses_node_t *) node;
+/* DEFINED_IVAR ***************************************************************/
+ case PM_INSTANCE_VARIABLE_READ_NODE: {
+ // defined?(@a)
+ // ^^
+ const pm_instance_variable_read_node_t *cast = (const pm_instance_variable_read_node_t *) node;
+ ID name = pm_constant_id_lookup(scope_node, cast->name);
- if (cast->body == NULL) {
- // If we have empty parentheses, then we want to return "nil".
- dtype = DEFINED_NIL;
- }
- else if (PM_NODE_TYPE_P(cast->body, PM_STATEMENTS_NODE) && ((const pm_statements_node_t *) cast->body)->body.size == 1) {
- // If we have a parentheses node that is wrapping a single statement
- // then we want to recurse down to that statement and compile it.
- pm_compile_defined_expr0(iseq, ((const pm_statements_node_t *) cast->body)->body.nodes[0], node_location, ret, popped, scope_node, in_condition, lfinish, explicit_receiver);
- return;
+ PUSH_INSN3(ret, location, definedivar, ID2SYM(name), get_ivar_ic_value(iseq, name), PUSH_VAL(DEFINED_IVAR));
+
+ return;
+ }
+/* DEFINED_LVAR ***************************************************************/
+ case PM_LOCAL_VARIABLE_READ_NODE:
+ // a = 1; defined?(a)
+ // ^
+ case PM_IT_LOCAL_VARIABLE_READ_NODE:
+ // 1.then { defined?(it) }
+ // ^^
+ dtype = DEFINED_LVAR;
+ break;
+/* DEFINED_GVAR ***************************************************************/
+ case PM_GLOBAL_VARIABLE_READ_NODE: {
+ // defined?($a)
+ // ^^
+ const pm_global_variable_read_node_t *cast = (const pm_global_variable_read_node_t *) node;
+ ID name = pm_constant_id_lookup(scope_node, cast->name);
+
+ PUSH_INSN(ret, location, putnil);
+ PUSH_INSN3(ret, location, defined, INT2FIX(DEFINED_GVAR), ID2SYM(name), PUSH_VAL(DEFINED_GVAR));
+
+ return;
+ }
+/* DEFINED_CVAR ***************************************************************/
+ case PM_CLASS_VARIABLE_READ_NODE: {
+ // defined?(@@a)
+ // ^^^
+ const pm_class_variable_read_node_t *cast = (const pm_class_variable_read_node_t *) node;
+ ID name = pm_constant_id_lookup(scope_node, cast->name);
+
+ PUSH_INSN(ret, location, putnil);
+ PUSH_INSN3(ret, location, defined, INT2FIX(DEFINED_CVAR), ID2SYM(name), PUSH_VAL(DEFINED_CVAR));
+
+ return;
+ }
+/* DEFINED_CONST **************************************************************/
+ case PM_CONSTANT_READ_NODE: {
+ // defined?(A)
+ // ^
+ const pm_constant_read_node_t *cast = (const pm_constant_read_node_t *) node;
+ ID name = pm_constant_id_lookup(scope_node, cast->name);
+
+ PUSH_INSN(ret, location, putnil);
+ PUSH_INSN3(ret, location, defined, INT2FIX(DEFINED_CONST), ID2SYM(name), PUSH_VAL(DEFINED_CONST));
+
+ return;
+ }
+/* DEFINED_YIELD **************************************************************/
+ case PM_YIELD_NODE:
+ // defined?(yield)
+ // ^^^^^
+ iseq_set_use_block(ISEQ_BODY(iseq)->local_iseq);
+
+ PUSH_INSN(ret, location, putnil);
+ PUSH_INSN3(ret, location, defined, INT2FIX(DEFINED_YIELD), 0, PUSH_VAL(DEFINED_YIELD));
+
+ return;
+/* DEFINED_ZSUPER *************************************************************/
+ case PM_SUPER_NODE: {
+ // defined?(super 1, 2)
+ // ^^^^^^^^^^
+ const pm_super_node_t *cast = (const pm_super_node_t *) node;
+
+ if (cast->block != NULL && !PM_NODE_TYPE_P(cast->block, PM_BLOCK_ARGUMENT_NODE)) {
+ dtype = DEFINED_EXPR;
+ break;
}
- else {
- // Otherwise, we have parentheses wrapping multiple statements, in
- // which case this is defined as "expression".
+
+ PUSH_INSN(ret, location, putnil);
+ PUSH_INSN3(ret, location, defined, INT2FIX(DEFINED_ZSUPER), 0, PUSH_VAL(DEFINED_ZSUPER));
+ return;
+ }
+ case PM_FORWARDING_SUPER_NODE: {
+ // defined?(super)
+ // ^^^^^
+ const pm_forwarding_super_node_t *cast = (const pm_forwarding_super_node_t *) node;
+
+ if (cast->block != NULL) {
dtype = DEFINED_EXPR;
+ break;
}
- break;
+ PUSH_INSN(ret, location, putnil);
+ PUSH_INSN3(ret, location, defined, INT2FIX(DEFINED_ZSUPER), 0, PUSH_VAL(DEFINED_ZSUPER));
+ return;
}
+/* DEFINED_SELF ***************************************************************/
case PM_SELF_NODE:
+ // defined?(self)
+ // ^^^^
dtype = DEFINED_SELF;
break;
+/* DEFINED_TRUE ***************************************************************/
case PM_TRUE_NODE:
+ // defined?(true)
+ // ^^^^
dtype = DEFINED_TRUE;
break;
+/* DEFINED_FALSE **************************************************************/
case PM_FALSE_NODE:
+ // defined?(false)
+ // ^^^^^
dtype = DEFINED_FALSE;
break;
- case PM_ARRAY_NODE: {
- const pm_array_node_t *cast = (const pm_array_node_t *) node;
-
- if (!PM_NODE_FLAG_P(cast, PM_ARRAY_NODE_FLAGS_CONTAINS_SPLAT)) {
- for (size_t index = 0; index < cast->elements.size; index++) {
- pm_compile_defined_expr0(iseq, cast->elements.nodes[index], node_location, ret, popped, scope_node, true, lfinish, false);
-
- if (!lfinish[1]) {
- lfinish[1] = NEW_LABEL(location.line);
- }
-
- PUSH_INSNL(ret, location, branchunless, lfinish[1]);
- }
- }
- }
+/* DEFINED_ASGN ***************************************************************/
+ case PM_CALL_AND_WRITE_NODE:
+ // defined?(a.a &&= 1)
+ // ^^^^^^^^^
+ case PM_CALL_OPERATOR_WRITE_NODE:
+ // defined?(a.a += 1)
+ // ^^^^^^^^
+ case PM_CALL_OR_WRITE_NODE:
+ // defined?(a.a ||= 1)
+ // ^^^^^^^^^
+ case PM_CLASS_VARIABLE_AND_WRITE_NODE:
+ // defined?(@@a &&= 1)
+ // ^^^^^^^^^
+ case PM_CLASS_VARIABLE_OPERATOR_WRITE_NODE:
+ // defined?(@@a += 1)
+ // ^^^^^^^^
+ case PM_CLASS_VARIABLE_OR_WRITE_NODE:
+ // defined?(@@a ||= 1)
+ // ^^^^^^^^^
+ case PM_CLASS_VARIABLE_WRITE_NODE:
+ // defined?(@@a = 1)
+ // ^^^^^^^
+ case PM_CONSTANT_AND_WRITE_NODE:
+ // defined?(A &&= 1)
+ // ^^^^^^^
+ case PM_CONSTANT_OPERATOR_WRITE_NODE:
+ // defined?(A += 1)
+ // ^^^^^^
+ case PM_CONSTANT_OR_WRITE_NODE:
+ // defined?(A ||= 1)
+ // ^^^^^^^
+ case PM_CONSTANT_PATH_AND_WRITE_NODE:
+ // defined?(A::A &&= 1)
+ // ^^^^^^^^^^
+ case PM_CONSTANT_PATH_OPERATOR_WRITE_NODE:
+ // defined?(A::A += 1)
+ // ^^^^^^^^^
+ case PM_CONSTANT_PATH_OR_WRITE_NODE:
+ // defined?(A::A ||= 1)
+ // ^^^^^^^^^^
+ case PM_CONSTANT_PATH_WRITE_NODE:
+ // defined?(A::A = 1)
+ // ^^^^^^^^
+ case PM_CONSTANT_WRITE_NODE:
+ // defined?(A = 1)
+ // ^^^^^
+ case PM_GLOBAL_VARIABLE_AND_WRITE_NODE:
+ // defined?($a &&= 1)
+ // ^^^^^^^^
+ case PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE:
+ // defined?($a += 1)
+ // ^^^^^^^
+ case PM_GLOBAL_VARIABLE_OR_WRITE_NODE:
+ // defined?($a ||= 1)
+ // ^^^^^^^^
+ case PM_GLOBAL_VARIABLE_WRITE_NODE:
+ // defined?($a = 1)
+ // ^^^^^^
+ case PM_INDEX_AND_WRITE_NODE:
+ // defined?(a[1] &&= 1)
+ // ^^^^^^^^^^
+ case PM_INDEX_OPERATOR_WRITE_NODE:
+ // defined?(a[1] += 1)
+ // ^^^^^^^^^
+ case PM_INDEX_OR_WRITE_NODE:
+ // defined?(a[1] ||= 1)
+ // ^^^^^^^^^^
+ case PM_INSTANCE_VARIABLE_AND_WRITE_NODE:
+ // defined?(@a &&= 1)
+ // ^^^^^^^^
+ case PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE:
+ // defined?(@a += 1)
+ // ^^^^^^^
+ case PM_INSTANCE_VARIABLE_OR_WRITE_NODE:
+ // defined?(@a ||= 1)
+ // ^^^^^^^^
+ case PM_INSTANCE_VARIABLE_WRITE_NODE:
+ // defined?(@a = 1)
+ // ^^^^^^
+ case PM_LOCAL_VARIABLE_AND_WRITE_NODE:
+ // defined?(a &&= 1)
+ // ^^^^^^^
+ case PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE:
+ // defined?(a += 1)
+ // ^^^^^^
+ case PM_LOCAL_VARIABLE_OR_WRITE_NODE:
+ // defined?(a ||= 1)
+ // ^^^^^^^
+ case PM_LOCAL_VARIABLE_WRITE_NODE:
+ // defined?(a = 1)
+ // ^^^^^
+ case PM_MULTI_WRITE_NODE:
+ // defined?((a, = 1))
+ // ^^^^^^
+ dtype = DEFINED_ASGN;
+ break;
+/* DEFINED_EXPR ***************************************************************/
+ case PM_ALIAS_GLOBAL_VARIABLE_NODE:
+ // defined?((alias $a $b))
+ // ^^^^^^^^^^^
+ case PM_ALIAS_METHOD_NODE:
+ // defined?((alias a b))
+ // ^^^^^^^^^
case PM_AND_NODE:
- case PM_BEGIN_NODE:
+ // defined?(a and b)
+ // ^^^^^^^
case PM_BREAK_NODE:
- case PM_CASE_NODE:
+ // defined?(break 1)
+ // ^^^^^^^
case PM_CASE_MATCH_NODE:
+ // defined?(case 1; in 1; end)
+ // ^^^^^^^^^^^^^^^^^
+ case PM_CASE_NODE:
+ // defined?(case 1; when 1; end)
+ // ^^^^^^^^^^^^^^^^^^^
case PM_CLASS_NODE:
+ // defined?(class Foo; end)
+ // ^^^^^^^^^^^^^^
case PM_DEF_NODE:
+ // defined?(def a() end)
+ // ^^^^^^^^^^^
case PM_DEFINED_NODE:
+ // defined?(defined?(a))
+ // ^^^^^^^^^^^
+ case PM_FLIP_FLOP_NODE:
+ // defined?(not (a .. b))
+ // ^^^^^^
case PM_FLOAT_NODE:
+ // defined?(1.0)
+ // ^^^
case PM_FOR_NODE:
- case PM_HASH_NODE:
+ // defined?(for a in 1 do end)
+ // ^^^^^^^^^^^^^^^^^
case PM_IF_NODE:
+ // defined?(if a then end)
+ // ^^^^^^^^^^^^^
case PM_IMAGINARY_NODE:
+ // defined?(1i)
+ // ^^
case PM_INTEGER_NODE:
+ // defined?(1)
+ // ^
+ case PM_INTERPOLATED_MATCH_LAST_LINE_NODE:
+ // defined?(not /#{1}/)
+ // ^^^^^^
case PM_INTERPOLATED_REGULAR_EXPRESSION_NODE:
+ // defined?(/#{1}/)
+ // ^^^^^^
case PM_INTERPOLATED_STRING_NODE:
+ // defined?("#{1}")
+ // ^^^^^^
case PM_INTERPOLATED_SYMBOL_NODE:
+ // defined?(:"#{1}")
+ // ^^^^^^^
case PM_INTERPOLATED_X_STRING_NODE:
- case PM_KEYWORD_HASH_NODE:
+ // defined?(`#{1}`)
+ // ^^^^^^
case PM_LAMBDA_NODE:
+ // defined?(-> {})
+ // ^^^^^
+ case PM_MATCH_LAST_LINE_NODE:
+ // defined?(not //)
+ // ^^^^^^
case PM_MATCH_PREDICATE_NODE:
+ // defined?(1 in 1)
+ // ^^^^^^
case PM_MATCH_REQUIRED_NODE:
+ // defined?(1 => 1)
+ // ^^^^^^
case PM_MATCH_WRITE_NODE:
+ // defined?(/(?<a>)/ =~ "")
+ // ^^^^^^^^^^^^^^
case PM_MODULE_NODE:
+ // defined?(module A end)
+ // ^^^^^^^^^^^^
case PM_NEXT_NODE:
+ // defined?(next 1)
+ // ^^^^^^
case PM_OR_NODE:
+ // defined?(a or b)
+ // ^^^^^^
+ case PM_POST_EXECUTION_NODE:
+ // defined?((END {}))
+ // ^^^^^^^^
case PM_RANGE_NODE:
+ // defined?(1..1)
+ // ^^^^
case PM_RATIONAL_NODE:
+ // defined?(1r)
+ // ^^
case PM_REDO_NODE:
+ // defined?(redo)
+ // ^^^^
case PM_REGULAR_EXPRESSION_NODE:
+ // defined?(//)
+ // ^^
+ case PM_RESCUE_MODIFIER_NODE:
+ // defined?(a rescue b)
+ // ^^^^^^^^^^
case PM_RETRY_NODE:
+ // defined?(retry)
+ // ^^^^^
case PM_RETURN_NODE:
+ // defined?(return)
+ // ^^^^^^
case PM_SINGLETON_CLASS_NODE:
+ // defined?(class << self; end)
+ // ^^^^^^^^^^^^^^^^^^
case PM_SOURCE_ENCODING_NODE:
+ // defined?(__ENCODING__)
+ // ^^^^^^^^^^^^
case PM_SOURCE_FILE_NODE:
+ // defined?(__FILE__)
+ // ^^^^^^^^
case PM_SOURCE_LINE_NODE:
+ // defined?(__LINE__)
+ // ^^^^^^^^
case PM_STRING_NODE:
+ // defined?("")
+ // ^^
case PM_SYMBOL_NODE:
+ // defined?(:a)
+ // ^^
+ case PM_UNDEF_NODE:
+ // defined?((undef a))
+ // ^^^^^^^
case PM_UNLESS_NODE:
+ // defined?(unless a then end)
+ // ^^^^^^^^^^^^^^^^^
case PM_UNTIL_NODE:
+ // defined?(until a do end)
+ // ^^^^^^^^^^^^^^
case PM_WHILE_NODE:
+ // defined?(while a do end)
+ // ^^^^^^^^^^^^^^
case PM_X_STRING_NODE:
+ // defined?(``)
+ // ^^
dtype = DEFINED_EXPR;
break;
- case PM_LOCAL_VARIABLE_READ_NODE:
- dtype = DEFINED_LVAR;
- break;
-
-#define PUSH_VAL(type) (in_condition ? Qtrue : rb_iseq_defined_string(type))
-
- case PM_INSTANCE_VARIABLE_READ_NODE: {
- const pm_instance_variable_read_node_t *cast = (const pm_instance_variable_read_node_t *) node;
-
- ID name = pm_constant_id_lookup(scope_node, cast->name);
- PUSH_INSN3(ret, location, definedivar, ID2SYM(name), get_ivar_ic_value(iseq, name), PUSH_VAL(DEFINED_IVAR));
-
- return;
- }
+/* DEFINED_REF ****************************************************************/
case PM_BACK_REFERENCE_READ_NODE: {
- const char *char_ptr = (const char *) (node->location.start + 1);
- ID backref_val = INT2FIX(rb_intern2(char_ptr, 1)) << 1 | 1;
+ // defined?($+)
+ // ^^
+ const pm_back_reference_read_node_t *cast = (const pm_back_reference_read_node_t *) node;
+ VALUE ref = pm_compile_back_reference_ref(cast);
PUSH_INSN(ret, location, putnil);
- PUSH_INSN3(ret, location, defined, INT2FIX(DEFINED_REF), backref_val, PUSH_VAL(DEFINED_GVAR));
+ PUSH_INSN3(ret, location, defined, INT2FIX(DEFINED_REF), ref, PUSH_VAL(DEFINED_GVAR));
return;
}
case PM_NUMBERED_REFERENCE_READ_NODE: {
- uint32_t reference_number = ((const pm_numbered_reference_read_node_t *) node)->number;
+ // defined?($1)
+ // ^^
+ const pm_numbered_reference_read_node_t *cast = (const pm_numbered_reference_read_node_t *) node;
+ VALUE ref = pm_compile_numbered_reference_ref(cast);
PUSH_INSN(ret, location, putnil);
- PUSH_INSN3(ret, location, defined, INT2FIX(DEFINED_REF), INT2FIX(reference_number << 1), PUSH_VAL(DEFINED_GVAR));
+ PUSH_INSN3(ret, location, defined, INT2FIX(DEFINED_REF), ref, PUSH_VAL(DEFINED_GVAR));
return;
}
- case PM_GLOBAL_VARIABLE_READ_NODE: {
- const pm_global_variable_read_node_t *cast = (const pm_global_variable_read_node_t *) node;
- VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, cast->name));
+/* DEFINED_CONST_FROM *********************************************************/
+ case PM_CONSTANT_PATH_NODE: {
+ // defined?(A::A)
+ // ^^^^
+ const pm_constant_path_node_t *cast = (const pm_constant_path_node_t *) node;
+ ID name = pm_constant_id_lookup(scope_node, cast->name);
- PUSH_INSN(ret, location, putnil);
- PUSH_INSN3(ret, location, defined, INT2FIX(DEFINED_GVAR), name, PUSH_VAL(DEFINED_GVAR));
+ if (cast->parent != NULL) {
+ if (!lfinish[1]) lfinish[1] = NEW_LABEL(location.line);
+ pm_compile_defined_expr0(iseq, cast->parent, node_location, ret, popped, scope_node, true, lfinish, false);
+ PUSH_INSNL(ret, location, branchunless, lfinish[1]);
+ PM_COMPILE(cast->parent);
+ }
+ else {
+ PUSH_INSN1(ret, location, putobject, rb_cObject);
+ }
+
+ PUSH_INSN3(ret, location, defined, INT2FIX(DEFINED_CONST_FROM), ID2SYM(name), PUSH_VAL(DEFINED_CONST));
return;
}
- case PM_CLASS_VARIABLE_READ_NODE: {
- const pm_class_variable_read_node_t *cast = (const pm_class_variable_read_node_t *) node;
- VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, cast->name));
+/* Containers *****************************************************************/
+ case PM_BEGIN_NODE: {
+ // defined?(begin end)
+ // ^^^^^^^^^
+ const pm_begin_node_t *cast = (const pm_begin_node_t *) node;
- PUSH_INSN(ret, location, putnil);
- PUSH_INSN3(ret, location, defined, INT2FIX(DEFINED_CVAR), name, PUSH_VAL(DEFINED_CVAR));
+ if (cast->rescue_clause == NULL && cast->ensure_clause == NULL && cast->else_clause == NULL) {
+ if (cast->statements == NULL) {
+ // If we have empty statements, then we want to return "nil".
+ dtype = DEFINED_NIL;
+ }
+ else if (cast->statements->body.size == 1) {
+ // If we have a begin node that is wrapping a single statement
+ // then we want to recurse down to that statement and compile
+ // it.
+ pm_compile_defined_expr0(iseq, cast->statements->body.nodes[0], node_location, ret, popped, scope_node, in_condition, lfinish, false);
+ return;
+ }
+ else {
+ // Otherwise, we have a begin wrapping multiple statements, in
+ // which case this is defined as "expression".
+ dtype = DEFINED_EXPR;
+ }
+ } else {
+ // If we have any of the other clauses besides the main begin/end,
+ // this is defined as "expression".
+ dtype = DEFINED_EXPR;
+ }
- return;
+ break;
}
- case PM_CONSTANT_READ_NODE: {
- const pm_constant_read_node_t *cast = (const pm_constant_read_node_t *) node;
- VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, cast->name));
+ case PM_PARENTHESES_NODE: {
+ // defined?(())
+ // ^^
+ const pm_parentheses_node_t *cast = (const pm_parentheses_node_t *) node;
- PUSH_INSN(ret, location, putnil);
- PUSH_INSN3(ret, location, defined, INT2FIX(DEFINED_CONST), name, PUSH_VAL(DEFINED_CONST));
+ if (cast->body == NULL) {
+ // If we have empty parentheses, then we want to return "nil".
+ dtype = DEFINED_NIL;
+ }
+ else if (PM_NODE_TYPE_P(cast->body, PM_STATEMENTS_NODE) && !PM_NODE_FLAG_P(cast, PM_PARENTHESES_NODE_FLAGS_MULTIPLE_STATEMENTS)) {
+ // If we have a parentheses node that is wrapping a single statement
+ // then we want to recurse down to that statement and compile it.
+ pm_compile_defined_expr0(iseq, ((const pm_statements_node_t *) cast->body)->body.nodes[0], node_location, ret, popped, scope_node, in_condition, lfinish, false);
+ return;
+ }
+ else {
+ // Otherwise, we have parentheses wrapping multiple statements, in
+ // which case this is defined as "expression".
+ dtype = DEFINED_EXPR;
+ }
- return;
+ break;
}
- case PM_CONSTANT_PATH_NODE: {
- const pm_constant_path_node_t *cast = (const pm_constant_path_node_t *) node;
- VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, cast->name));
+ case PM_ARRAY_NODE: {
+ // defined?([])
+ // ^^
+ const pm_array_node_t *cast = (const pm_array_node_t *) node;
- if (cast->parent != NULL) {
- if (!lfinish[1]) lfinish[1] = NEW_LABEL(location.line);
- pm_compile_defined_expr0(iseq, cast->parent, node_location, ret, popped, scope_node, true, lfinish, false);
+ if (cast->elements.size > 0 && !lfinish[1]) {
+ lfinish[1] = NEW_LABEL(location.line);
+ }
+ for (size_t index = 0; index < cast->elements.size; index++) {
+ pm_compile_defined_expr0(iseq, cast->elements.nodes[index], node_location, ret, popped, scope_node, true, lfinish, false);
PUSH_INSNL(ret, location, branchunless, lfinish[1]);
- PM_COMPILE(cast->parent);
+ }
+
+ dtype = DEFINED_EXPR;
+ break;
+ }
+ case PM_HASH_NODE:
+ // defined?({ a: 1 })
+ // ^^^^^^^^
+ case PM_KEYWORD_HASH_NODE: {
+ // defined?(a(a: 1))
+ // ^^^^
+ const pm_node_list_t *elements;
+
+ if (PM_NODE_TYPE_P(node, PM_HASH_NODE)) {
+ elements = &((const pm_hash_node_t *) node)->elements;
}
else {
- PUSH_INSN1(ret, location, putobject, rb_cObject);
+ elements = &((const pm_keyword_hash_node_t *) node)->elements;
+ }
+
+ if (elements->size > 0 && !lfinish[1]) {
+ lfinish[1] = NEW_LABEL(location.line);
+ }
+
+ for (size_t index = 0; index < elements->size; index++) {
+ pm_compile_defined_expr0(iseq, elements->nodes[index], node_location, ret, popped, scope_node, true, lfinish, false);
+ PUSH_INSNL(ret, location, branchunless, lfinish[1]);
+ }
+
+ dtype = DEFINED_EXPR;
+ break;
+ }
+ case PM_ASSOC_NODE: {
+ // defined?({ a: 1 })
+ // ^^^^
+ const pm_assoc_node_t *cast = (const pm_assoc_node_t *) node;
+
+ pm_compile_defined_expr0(iseq, cast->key, node_location, ret, popped, scope_node, true, lfinish, false);
+ PUSH_INSNL(ret, location, branchunless, lfinish[1]);
+ pm_compile_defined_expr0(iseq, cast->value, node_location, ret, popped, scope_node, true, lfinish, false);
+
+ return;
+ }
+ case PM_ASSOC_SPLAT_NODE: {
+ // defined?({ **a })
+ // ^^^^
+ const pm_assoc_splat_node_t *cast = (const pm_assoc_splat_node_t *) node;
+
+ if (cast->value == NULL) {
+ dtype = DEFINED_EXPR;
+ break;
}
- PUSH_INSN3(ret, location, defined, INT2FIX(DEFINED_CONST_FROM), name, PUSH_VAL(DEFINED_CONST));
+ pm_compile_defined_expr0(iseq, cast->value, node_location, ret, popped, scope_node, true, lfinish, false);
+ return;
+ }
+ case PM_IMPLICIT_NODE: {
+ // defined?({ a: })
+ // ^^
+ const pm_implicit_node_t *cast = (const pm_implicit_node_t *) node;
+ pm_compile_defined_expr0(iseq, cast->value, node_location, ret, popped, scope_node, in_condition, lfinish, false);
return;
}
case PM_CALL_NODE: {
+#define BLOCK_P(cast) ((cast)->block != NULL && PM_NODE_TYPE_P((cast)->block, PM_BLOCK_NODE))
+
+ // defined?(a(1, 2, 3))
+ // ^^^^^^^^^^
const pm_call_node_t *cast = ((const pm_call_node_t *) node);
- ID method_id = pm_constant_id_lookup(scope_node, cast->name);
- if (cast->receiver || cast->arguments) {
+ if (BLOCK_P(cast)) {
+ dtype = DEFINED_EXPR;
+ break;
+ }
+
+ if (cast->receiver || cast->arguments || (cast->block && PM_NODE_TYPE_P(cast->block, PM_BLOCK_ARGUMENT_NODE))) {
if (!lfinish[1]) lfinish[1] = NEW_LABEL(location.line);
if (!lfinish[2]) lfinish[2] = NEW_LABEL(location.line);
}
@@ -3581,93 +4405,154 @@ pm_compile_defined_expr0(rb_iseq_t *iseq, const pm_node_t *node, const pm_line_c
PUSH_INSNL(ret, location, branchunless, lfinish[1]);
}
- if (cast->receiver) {
- pm_compile_defined_expr0(iseq, cast->receiver, node_location, ret, popped, scope_node, true, lfinish, true);
+ if (cast->block && PM_NODE_TYPE_P(cast->block, PM_BLOCK_ARGUMENT_NODE)) {
+ pm_compile_defined_expr0(iseq, cast->block, node_location, ret, popped, scope_node, true, lfinish, false);
+ PUSH_INSNL(ret, location, branchunless, lfinish[1]);
+ }
- if (PM_NODE_TYPE_P(cast->receiver, PM_CALL_NODE)) {
+ if (cast->receiver) {
+ if (PM_NODE_TYPE_P(cast->receiver, PM_CALL_NODE) && !BLOCK_P((const pm_call_node_t *) cast->receiver)) {
+ // Special behavior here where we chain calls together. This is
+ // the only path that sets explicit_receiver to true.
+ pm_compile_defined_expr0(iseq, cast->receiver, node_location, ret, popped, scope_node, true, lfinish, true);
PUSH_INSNL(ret, location, branchunless, lfinish[2]);
const pm_call_node_t *receiver = (const pm_call_node_t *) cast->receiver;
ID method_id = pm_constant_id_lookup(scope_node, receiver->name);
+
pm_compile_call(iseq, receiver, ret, popped, scope_node, method_id, NULL);
}
else {
+ pm_compile_defined_expr0(iseq, cast->receiver, node_location, ret, popped, scope_node, true, lfinish, false);
PUSH_INSNL(ret, location, branchunless, lfinish[1]);
PM_COMPILE(cast->receiver);
}
+ ID method_id = pm_constant_id_lookup(scope_node, cast->name);
+
if (explicit_receiver) PUSH_INSN(ret, location, dup);
PUSH_INSN3(ret, location, defined, INT2FIX(DEFINED_METHOD), rb_id2sym(method_id), PUSH_VAL(DEFINED_METHOD));
}
else {
+ ID method_id = pm_constant_id_lookup(scope_node, cast->name);
+
PUSH_INSN(ret, location, putself);
if (explicit_receiver) PUSH_INSN(ret, location, dup);
+
PUSH_INSN3(ret, location, defined, INT2FIX(DEFINED_FUNC), rb_id2sym(method_id), PUSH_VAL(DEFINED_METHOD));
}
return;
- }
- case PM_YIELD_NODE:
- PUSH_INSN(ret, location, putnil);
- PUSH_INSN3(ret, location, defined, INT2FIX(DEFINED_YIELD), 0, PUSH_VAL(DEFINED_YIELD));
- return;
- case PM_SUPER_NODE:
- case PM_FORWARDING_SUPER_NODE:
- PUSH_INSN(ret, location, putnil);
- PUSH_INSN3(ret, location, defined, INT2FIX(DEFINED_ZSUPER), 0, PUSH_VAL(DEFINED_ZSUPER));
- return;
- case PM_CALL_AND_WRITE_NODE:
- case PM_CALL_OPERATOR_WRITE_NODE:
- case PM_CALL_OR_WRITE_NODE:
- case PM_CONSTANT_WRITE_NODE:
- case PM_CONSTANT_OPERATOR_WRITE_NODE:
- case PM_CONSTANT_AND_WRITE_NODE:
- case PM_CONSTANT_OR_WRITE_NODE:
-
- case PM_CONSTANT_PATH_AND_WRITE_NODE:
- case PM_CONSTANT_PATH_OPERATOR_WRITE_NODE:
- case PM_CONSTANT_PATH_OR_WRITE_NODE:
- case PM_CONSTANT_PATH_WRITE_NODE:
+#undef BLOCK_P
+ }
+ case PM_ARGUMENTS_NODE: {
+ // defined?(a(1, 2, 3))
+ // ^^^^^^^
+ const pm_arguments_node_t *cast = (const pm_arguments_node_t *) node;
- case PM_GLOBAL_VARIABLE_WRITE_NODE:
- case PM_GLOBAL_VARIABLE_OPERATOR_WRITE_NODE:
- case PM_GLOBAL_VARIABLE_AND_WRITE_NODE:
- case PM_GLOBAL_VARIABLE_OR_WRITE_NODE:
+ for (size_t index = 0; index < cast->arguments.size; index++) {
+ pm_compile_defined_expr0(iseq, cast->arguments.nodes[index], node_location, ret, popped, scope_node, in_condition, lfinish, false);
+ PUSH_INSNL(ret, location, branchunless, lfinish[1]);
+ }
- case PM_CLASS_VARIABLE_WRITE_NODE:
- case PM_CLASS_VARIABLE_OPERATOR_WRITE_NODE:
- case PM_CLASS_VARIABLE_AND_WRITE_NODE:
- case PM_CLASS_VARIABLE_OR_WRITE_NODE:
+ dtype = DEFINED_EXPR;
+ break;
+ }
+ case PM_BLOCK_ARGUMENT_NODE:
+ // defined?(a(&b))
+ // ^^
+ dtype = DEFINED_EXPR;
+ break;
+ case PM_FORWARDING_ARGUMENTS_NODE:
+ // def a(...) = defined?(a(...))
+ // ^^^
+ dtype = DEFINED_EXPR;
+ break;
+ case PM_SPLAT_NODE: {
+ // def a(*) = defined?(a(*))
+ // ^
+ const pm_splat_node_t *cast = (const pm_splat_node_t *) node;
- case PM_INDEX_AND_WRITE_NODE:
- case PM_INDEX_OPERATOR_WRITE_NODE:
- case PM_INDEX_OR_WRITE_NODE:
+ if (cast->expression == NULL) {
+ dtype = DEFINED_EXPR;
+ break;
+ }
- case PM_INSTANCE_VARIABLE_WRITE_NODE:
- case PM_INSTANCE_VARIABLE_OPERATOR_WRITE_NODE:
- case PM_INSTANCE_VARIABLE_AND_WRITE_NODE:
- case PM_INSTANCE_VARIABLE_OR_WRITE_NODE:
+ pm_compile_defined_expr0(iseq, cast->expression, node_location, ret, popped, scope_node, in_condition, lfinish, false);
- case PM_LOCAL_VARIABLE_WRITE_NODE:
- case PM_LOCAL_VARIABLE_OPERATOR_WRITE_NODE:
- case PM_LOCAL_VARIABLE_AND_WRITE_NODE:
- case PM_LOCAL_VARIABLE_OR_WRITE_NODE:
+ if (!lfinish[1]) lfinish[1] = NEW_LABEL(location.line);
+ PUSH_INSNL(ret, location, branchunless, lfinish[1]);
- case PM_MULTI_WRITE_NODE:
- dtype = DEFINED_ASGN;
+ dtype = DEFINED_EXPR;
break;
- default:
- rb_bug("Unsupported node %s", pm_node_type_to_str(PM_NODE_TYPE(node)));
+ }
+ case PM_SHAREABLE_CONSTANT_NODE:
+ // # shareable_constant_value: literal
+ // defined?(A = 1)
+ // ^^^^^
+ pm_compile_defined_expr0(iseq, ((const pm_shareable_constant_node_t *) node)->write, node_location, ret, popped, scope_node, in_condition, lfinish, explicit_receiver);
+ return;
+/* Unreachable (parameters) ***************************************************/
+ case PM_BLOCK_LOCAL_VARIABLE_NODE:
+ case PM_BLOCK_PARAMETER_NODE:
+ case PM_BLOCK_PARAMETERS_NODE:
+ case PM_FORWARDING_PARAMETER_NODE:
+ case PM_IMPLICIT_REST_NODE:
+ case PM_IT_PARAMETERS_NODE:
+ case PM_PARAMETERS_NODE:
+ case PM_KEYWORD_REST_PARAMETER_NODE:
+ case PM_NO_KEYWORDS_PARAMETER_NODE:
+ case PM_NUMBERED_PARAMETERS_NODE:
+ case PM_OPTIONAL_KEYWORD_PARAMETER_NODE:
+ case PM_OPTIONAL_PARAMETER_NODE:
+ case PM_REQUIRED_KEYWORD_PARAMETER_NODE:
+ case PM_REQUIRED_PARAMETER_NODE:
+ case PM_REST_PARAMETER_NODE:
+/* Unreachable (pattern matching) *********************************************/
+ case PM_ALTERNATION_PATTERN_NODE:
+ case PM_ARRAY_PATTERN_NODE:
+ case PM_CAPTURE_PATTERN_NODE:
+ case PM_FIND_PATTERN_NODE:
+ case PM_HASH_PATTERN_NODE:
+ case PM_PINNED_EXPRESSION_NODE:
+ case PM_PINNED_VARIABLE_NODE:
+/* Unreachable (indirect writes) **********************************************/
+ case PM_CALL_TARGET_NODE:
+ case PM_CLASS_VARIABLE_TARGET_NODE:
+ case PM_CONSTANT_PATH_TARGET_NODE:
+ case PM_CONSTANT_TARGET_NODE:
+ case PM_GLOBAL_VARIABLE_TARGET_NODE:
+ case PM_INDEX_TARGET_NODE:
+ case PM_INSTANCE_VARIABLE_TARGET_NODE:
+ case PM_LOCAL_VARIABLE_TARGET_NODE:
+ case PM_MULTI_TARGET_NODE:
+/* Unreachable (clauses) ******************************************************/
+ case PM_ELSE_NODE:
+ case PM_ENSURE_NODE:
+ case PM_IN_NODE:
+ case PM_RESCUE_NODE:
+ case PM_WHEN_NODE:
+/* Unreachable (miscellaneous) ************************************************/
+ case PM_BLOCK_NODE:
+ case PM_EMBEDDED_STATEMENTS_NODE:
+ case PM_EMBEDDED_VARIABLE_NODE:
+ case PM_MISSING_NODE:
+ case PM_PRE_EXECUTION_NODE:
+ case PM_PROGRAM_NODE:
+ case PM_SCOPE_NODE:
+ case PM_STATEMENTS_NODE:
+ rb_bug("Unreachable node in defined?: %s", pm_node_type_to_str(PM_NODE_TYPE(node)));
}
RUBY_ASSERT(dtype != DEFINED_NOT_DEFINED);
PUSH_INSN1(ret, location, putobject, PUSH_VAL(dtype));
+
#undef PUSH_VAL
}
static void
-pm_defined_expr(rb_iseq_t *iseq, const pm_node_t *node, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node, bool in_condition, LABEL **lfinish, bool explicit_receiver)
+pm_defined_expr(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_location_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node, bool in_condition, LABEL **lfinish)
{
LINK_ELEMENT *lcur = ret->last;
pm_compile_defined_expr0(iseq, node, node_location, ret, popped, scope_node, in_condition, lfinish, false);
@@ -3698,7 +4583,7 @@ pm_defined_expr(rb_iseq_t *iseq, const pm_node_t *node, const pm_line_column_t *
}
static void
-pm_compile_defined_expr(rb_iseq_t *iseq, const pm_node_t *node, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node, bool in_condition)
+pm_compile_defined_expr(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_location_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node, bool in_condition)
{
LABEL *lfinish[3];
LINK_ELEMENT *last = ret->last;
@@ -3708,11 +4593,11 @@ pm_compile_defined_expr(rb_iseq_t *iseq, const pm_node_t *node, const pm_line_co
lfinish[2] = 0;
if (!popped) {
- pm_defined_expr(iseq, node, node_location, ret, popped, scope_node, in_condition, lfinish, false);
+ pm_defined_expr(iseq, node, node_location, ret, popped, scope_node, in_condition, lfinish);
}
if (lfinish[1]) {
- ELEM_INSERT_NEXT(last, &new_insn_body(iseq, node_location->line, node_location->column, BIN(putnil), 0)->link);
+ ELEM_INSERT_NEXT(last, &new_insn_body(iseq, node_location->line, node_location->node_id, BIN(putnil), 0)->link);
PUSH_INSN(ret, *node_location, swap);
if (lfinish[2]) PUSH_LABEL(ret, lfinish[2]);
@@ -3736,13 +4621,11 @@ pm_add_ensure_iseq(LINK_ANCHOR *const ret, rb_iseq_t *iseq, int is_return, pm_sc
struct iseq_compile_data_ensure_node_stack *prev_enlp = enlp;
DECL_ANCHOR(ensure);
- INIT_ANCHOR(ensure);
while (enlp) {
if (enlp->erange != NULL) {
DECL_ANCHOR(ensure_part);
LABEL *lstart = NEW_LABEL(0);
LABEL *lend = NEW_LABEL(0);
- INIT_ANCHOR(ensure_part);
add_ensure_range(iseq, enlp->erange, lstart, lend);
@@ -3880,7 +4763,7 @@ pm_compile_destructured_param_locals(const pm_multi_target_node_t *node, st_tabl
static inline void
pm_compile_destructured_param_write(rb_iseq_t *iseq, const pm_required_parameter_node_t *node, LINK_ANCHOR *const ret, const pm_scope_node_t *scope_node)
{
- const pm_line_column_t location = PM_NODE_START_LINE_COLUMN(scope_node->parser, node);
+ const pm_node_location_t location = PM_NODE_START_LOCATION(scope_node->parser, node);
pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, node->name, 0);
PUSH_SETLOCAL(ret, location, index.index, index.level);
}
@@ -3896,7 +4779,7 @@ pm_compile_destructured_param_write(rb_iseq_t *iseq, const pm_required_parameter
static void
pm_compile_destructured_param_writes(rb_iseq_t *iseq, const pm_multi_target_node_t *node, LINK_ANCHOR *const ret, const pm_scope_node_t *scope_node)
{
- const pm_line_column_t location = PM_NODE_START_LINE_COLUMN(scope_node->parser, node);
+ const pm_node_location_t location = PM_NODE_START_LOCATION(scope_node->parser, node);
bool has_rest = (node->rest && PM_NODE_TYPE_P(node->rest, PM_SPLAT_NODE) && (((const pm_splat_node_t *) node->rest)->expression) != NULL);
bool has_rights = node->rights.size > 0;
@@ -4093,7 +4976,7 @@ pm_compile_multi_target_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR
static void
pm_compile_target_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const parents, LINK_ANCHOR *const writes, LINK_ANCHOR *const cleanup, pm_scope_node_t *scope_node, pm_multi_target_state_t *state)
{
- const pm_line_column_t location = PM_NODE_START_LINE_COLUMN(scope_node->parser, node);
+ const pm_node_location_t location = PM_NODE_START_LOCATION(scope_node->parser, node);
switch (PM_NODE_TYPE(node)) {
case PM_LOCAL_VARIABLE_TARGET_NODE: {
@@ -4117,7 +5000,8 @@ pm_compile_target_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *cons
const pm_class_variable_target_node_t *cast = (const pm_class_variable_target_node_t *) node;
ID name = pm_constant_id_lookup(scope_node, cast->name);
- PUSH_INSN2(writes, location, setclassvariable, ID2SYM(name), get_cvar_ic_value(iseq, name));
+ VALUE operand = ID2SYM(name);
+ PUSH_INSN2(writes, location, setclassvariable, operand, get_cvar_ic_value(iseq, name));
break;
}
case PM_CONSTANT_TARGET_NODE: {
@@ -4129,8 +5013,9 @@ pm_compile_target_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *cons
const pm_constant_target_node_t *cast = (const pm_constant_target_node_t *) node;
ID name = pm_constant_id_lookup(scope_node, cast->name);
+ VALUE operand = ID2SYM(name);
PUSH_INSN1(writes, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE));
- PUSH_INSN1(writes, location, setconstant, ID2SYM(name));
+ PUSH_INSN1(writes, location, setconstant, operand);
break;
}
case PM_GLOBAL_VARIABLE_TARGET_NODE: {
@@ -4142,7 +5027,8 @@ pm_compile_target_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *cons
const pm_global_variable_target_node_t *cast = (const pm_global_variable_target_node_t *) node;
ID name = pm_constant_id_lookup(scope_node, cast->name);
- PUSH_INSN1(writes, location, setglobal, ID2SYM(name));
+ VALUE operand = ID2SYM(name);
+ PUSH_INSN1(writes, location, setglobal, operand);
break;
}
case PM_INSTANCE_VARIABLE_TARGET_NODE: {
@@ -4154,7 +5040,8 @@ pm_compile_target_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *cons
const pm_instance_variable_target_node_t *cast = (const pm_instance_variable_target_node_t *) node;
ID name = pm_constant_id_lookup(scope_node, cast->name);
- PUSH_INSN2(writes, location, setinstancevariable, ID2SYM(name), get_ivar_ic_value(iseq, name));
+ VALUE operand = ID2SYM(name);
+ PUSH_INSN2(writes, location, setinstancevariable, operand, get_ivar_ic_value(iseq, name));
break;
}
case PM_CONSTANT_PATH_TARGET_NODE: {
@@ -4184,7 +5071,8 @@ pm_compile_target_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *cons
pm_multi_target_state_push(state, (INSN *) LAST_ELEMENT(writes), 1);
}
- PUSH_INSN1(writes, location, setconstant, ID2SYM(name));
+ VALUE operand = ID2SYM(name);
+ PUSH_INSN1(writes, location, setconstant, operand);
if (state != NULL) {
PUSH_INSN(cleanup, location, pop);
@@ -4249,7 +5137,7 @@ pm_compile_target_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *cons
int flags = 0;
struct rb_callinfo_kwarg *kwargs = NULL;
- int argc = pm_setup_args(cast->arguments, cast->block, &flags, &kwargs, iseq, parents, scope_node, &location);
+ int argc = pm_setup_args(cast->arguments, (const pm_node_t *) cast->block, &flags, &kwargs, iseq, parents, scope_node, &location);
if (state != NULL) {
PUSH_INSN1(writes, location, topn, INT2FIX(argc + 1));
@@ -4310,6 +5198,20 @@ pm_compile_target_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *cons
break;
}
+ case PM_SPLAT_NODE: {
+ // Splat nodes capture all values into an array. They can be used
+ // as targets in assignments or for loops.
+ //
+ // for *x in []; end
+ //
+ const pm_splat_node_t *cast = (const pm_splat_node_t *) node;
+
+ if (cast->expression != NULL) {
+ pm_compile_target_node(iseq, cast->expression, parents, writes, cleanup, scope_node, state);
+ }
+
+ break;
+ }
default:
rb_bug("Unexpected node type: %s", pm_node_type_to_str(PM_NODE_TYPE(node)));
break;
@@ -4324,7 +5226,7 @@ pm_compile_target_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *cons
static void
pm_compile_multi_target_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const parents, LINK_ANCHOR *const writes, LINK_ANCHOR *const cleanup, pm_scope_node_t *scope_node, pm_multi_target_state_t *state)
{
- const pm_line_column_t location = PM_NODE_START_LINE_COLUMN(scope_node->parser, node);
+ const pm_node_location_t location = PM_NODE_START_LOCATION(scope_node->parser, node);
const pm_node_list_t *lefts;
const pm_node_t *rest;
const pm_node_list_t *rights;
@@ -4407,7 +5309,7 @@ pm_compile_multi_target_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR
static void
pm_compile_for_node_index(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, pm_scope_node_t *scope_node)
{
- const pm_line_column_t location = PM_NODE_START_LINE_COLUMN(scope_node->parser, node);
+ const pm_node_location_t location = PM_NODE_START_LOCATION(scope_node->parser, node);
switch (PM_NODE_TYPE(node)) {
case PM_LOCAL_VARIABLE_TARGET_NODE: {
@@ -4428,10 +5330,7 @@ pm_compile_for_node_index(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *c
// owning expression of this target, then retrieve the value, expand it,
// and then compile the necessary writes.
DECL_ANCHOR(writes);
- INIT_ANCHOR(writes);
-
DECL_ANCHOR(cleanup);
- INIT_ANCHOR(cleanup);
pm_multi_target_state_t state = { 0 };
state.position = 1;
@@ -4446,12 +5345,10 @@ pm_compile_for_node_index(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *c
pm_multi_target_state_update(&state);
break;
}
+ case PM_SPLAT_NODE:
case PM_MULTI_TARGET_NODE: {
DECL_ANCHOR(writes);
- INIT_ANCHOR(writes);
-
DECL_ANCHOR(cleanup);
- INIT_ANCHOR(cleanup);
pm_compile_target_node(iseq, node, ret, writes, cleanup, scope_node, NULL);
@@ -4484,6 +5381,12 @@ pm_compile_for_node_index(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *c
PUSH_INSN(ret, location, pop);
PUSH_LABEL(ret, not_single);
+
+ if (PM_NODE_TYPE_P(node, PM_SPLAT_NODE)) {
+ const pm_splat_node_t *cast = (const pm_splat_node_t *) node;
+ PUSH_INSN2(ret, location, expandarray, INT2FIX(0), INT2FIX(cast->expression == NULL ? 0 : 1));
+ }
+
PUSH_SEQ(ret, writes);
PUSH_SEQ(ret, cleanup);
break;
@@ -4495,7 +5398,7 @@ pm_compile_for_node_index(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *c
}
static void
-pm_compile_rescue(rb_iseq_t *iseq, const pm_begin_node_t *cast, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+pm_compile_rescue(rb_iseq_t *iseq, const pm_begin_node_t *cast, const pm_node_location_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
{
const pm_parser_t *parser = scope_node->parser;
@@ -4526,7 +5429,8 @@ pm_compile_rescue(rb_iseq_t *iseq, const pm_begin_node_t *cast, const pm_line_co
PM_COMPILE_NOT_POPPED((const pm_node_t *) cast->statements);
}
else {
- PUSH_SYNTHETIC_PUTNIL(ret, iseq);
+ const pm_node_location_t location = PM_NODE_START_LOCATION(parser, cast->rescue_clause);
+ PUSH_INSN(ret, location, putnil);
}
ISEQ_COMPILE_DATA(iseq)->in_rescue = prev_in_rescue;
@@ -4546,40 +5450,56 @@ pm_compile_rescue(rb_iseq_t *iseq, const pm_begin_node_t *cast, const pm_line_co
}
static void
-pm_compile_ensure(rb_iseq_t *iseq, const pm_begin_node_t *cast, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+pm_compile_ensure(rb_iseq_t *iseq, const pm_begin_node_t *cast, const pm_node_location_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
{
const pm_parser_t *parser = scope_node->parser;
const pm_statements_node_t *statements = cast->ensure_clause->statements;
- const pm_line_column_t location = statements != NULL ? PM_NODE_START_LINE_COLUMN(parser, statements) : *node_location;
- LABEL *estart = NEW_LABEL(location.line);
- LABEL *eend = NEW_LABEL(location.line);
- LABEL *econt = NEW_LABEL(location.line);
+ pm_node_location_t location;
+ if (statements != NULL) {
+ location = PM_NODE_START_LOCATION(parser, statements);
+ }
+ else {
+ location = *node_location;
+ }
+
+ LABEL *lstart = NEW_LABEL(location.line);
+ LABEL *lend = NEW_LABEL(location.line);
+ LABEL *lcont = NEW_LABEL(location.line);
struct ensure_range er;
struct iseq_compile_data_ensure_node_stack enl;
struct ensure_range *erange;
- er.begin = estart;
- er.end = eend;
+ DECL_ANCHOR(ensr);
+ if (statements != NULL) {
+ pm_compile_node(iseq, (const pm_node_t *) statements, ensr, true, scope_node);
+ }
+
+ LINK_ELEMENT *last = ensr->last;
+ bool last_leave = last && IS_INSN(last) && IS_INSN_ID(last, leave);
+
+ er.begin = lstart;
+ er.end = lend;
er.next = 0;
push_ensure_entry(iseq, &enl, &er, (void *) cast->ensure_clause);
- PUSH_LABEL(ret, estart);
- if (cast->rescue_clause) {
- pm_compile_rescue(iseq, cast, &location, ret, popped, scope_node);
+ PUSH_LABEL(ret, lstart);
+ if (cast->rescue_clause != NULL) {
+ pm_compile_rescue(iseq, cast, node_location, ret, popped | last_leave, scope_node);
}
- else {
- if (cast->statements) {
- PM_COMPILE((const pm_node_t *) cast->statements);
- }
- else if (!popped) {
- PUSH_INSN(ret, *node_location, putnil);
- }
+ else if (cast->statements != NULL) {
+ pm_compile_node(iseq, (const pm_node_t *) cast->statements, ret, popped | last_leave, scope_node);
+ }
+ else if (!(popped | last_leave)) {
+ PUSH_SYNTHETIC_PUTNIL(ret, iseq);
}
- PUSH_LABEL(ret, eend);
- PUSH_LABEL(ret, econt);
+ PUSH_LABEL(ret, lend);
+ PUSH_SEQ(ret, ensr);
+ if (!popped && last_leave) PUSH_INSN(ret, *node_location, putnil);
+ PUSH_LABEL(ret, lcont);
+ if (last_leave) PUSH_INSN(ret, *node_location, pop);
pm_scope_node_t next_scope_node;
pm_scope_node_init((const pm_node_t *) cast->ensure_clause, &next_scope_node, scope_node);
@@ -4594,19 +5514,13 @@ pm_compile_ensure(rb_iseq_t *iseq, const pm_begin_node_t *cast, const pm_line_co
pm_scope_node_destroy(&next_scope_node);
erange = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack->erange;
- if (estart->link.next != &eend->link) {
+ if (lstart->link.next != &lend->link) {
while (erange) {
- PUSH_CATCH_ENTRY(CATCH_TYPE_ENSURE, erange->begin, erange->end, child_iseq, econt);
+ PUSH_CATCH_ENTRY(CATCH_TYPE_ENSURE, erange->begin, erange->end, child_iseq, lcont);
erange = erange->next;
}
}
ISEQ_COMPILE_DATA(iseq)->ensure_node_stack = enl.prev;
-
- // Compile the ensure entry
- if (statements != NULL) {
- PM_COMPILE((const pm_node_t *) statements);
- if (!popped) PUSH_INSN(ret, *node_location, pop);
- }
}
/**
@@ -4627,55 +5541,18 @@ pm_opt_str_freeze_p(const rb_iseq_t *iseq, const pm_call_node_t *node)
}
/**
- * Returns true if the given call node can use the opt_aref_with optimization
- * with the current iseq options.
- */
-static inline bool
-pm_opt_aref_with_p(const rb_iseq_t *iseq, const pm_call_node_t *node)
-{
- return (
- !PM_NODE_FLAG_P(node, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION) &&
- node->arguments != NULL &&
- PM_NODE_TYPE_P((const pm_node_t *) node->arguments, PM_ARGUMENTS_NODE) &&
- ((const pm_arguments_node_t *) node->arguments)->arguments.size == 1 &&
- PM_NODE_TYPE_P(((const pm_arguments_node_t *) node->arguments)->arguments.nodes[0], PM_STRING_NODE) &&
- node->block == NULL &&
- !PM_NODE_FLAG_P(((const pm_arguments_node_t *) node->arguments)->arguments.nodes[0], PM_STRING_FLAGS_FROZEN) &&
- ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction
- );
-}
-
-/**
- * Returns true if the given call node can use the opt_aset_with optimization
- * with the current iseq options.
- */
-static inline bool
-pm_opt_aset_with_p(const rb_iseq_t *iseq, const pm_call_node_t *node)
-{
- return (
- !PM_NODE_FLAG_P(node, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION) &&
- node->arguments != NULL &&
- PM_NODE_TYPE_P((const pm_node_t *) node->arguments, PM_ARGUMENTS_NODE) &&
- ((const pm_arguments_node_t *) node->arguments)->arguments.size == 2 &&
- PM_NODE_TYPE_P(((const pm_arguments_node_t *) node->arguments)->arguments.nodes[0], PM_STRING_NODE) &&
- node->block == NULL &&
- !PM_NODE_FLAG_P(((const pm_arguments_node_t *) node->arguments)->arguments.nodes[0], PM_STRING_FLAGS_FROZEN) &&
- ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction
- );
-}
-
-/**
* Compile the instructions necessary to read a constant, based on the options
* of the current iseq.
*/
static void
-pm_compile_constant_read(rb_iseq_t *iseq, VALUE name, const pm_location_t *name_loc, LINK_ANCHOR *const ret, const pm_scope_node_t *scope_node)
+pm_compile_constant_read(rb_iseq_t *iseq, VALUE name, const pm_location_t *name_loc, uint32_t node_id, LINK_ANCHOR *const ret, const pm_scope_node_t *scope_node)
{
- const pm_line_column_t location = PM_LOCATION_START_LINE_COLUMN(scope_node->parser, name_loc);
+ const pm_node_location_t location = PM_LOCATION_START_LOCATION(scope_node->parser, name_loc, node_id);
if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) {
ISEQ_BODY(iseq)->ic_size++;
VALUE segments = rb_ary_new_from_args(1, name);
+ RB_OBJ_SET_SHAREABLE(segments);
PUSH_INSN1(ret, location, opt_getconstant_path, segments);
}
else {
@@ -4730,7 +5607,7 @@ pm_constant_path_parts(const pm_node_t *node, const pm_scope_node_t *scope_node)
static void
pm_compile_constant_path(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const prefix, LINK_ANCHOR *const body, bool popped, pm_scope_node_t *scope_node)
{
- const pm_line_column_t location = PM_NODE_START_LINE_COLUMN(scope_node->parser, node);
+ const pm_node_location_t location = PM_NODE_START_LOCATION(scope_node->parser, node);
switch (PM_NODE_TYPE(node)) {
case PM_CONSTANT_READ_NODE: {
@@ -4765,63 +5642,6 @@ pm_compile_constant_path(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *co
}
/**
- * When we're compiling a case node, it's possible that we can speed it up using
- * a dispatch hash, which will allow us to jump directly to the correct when
- * clause body based on a hash lookup of the value. This can only happen when
- * the conditions are literals that can be compiled into a hash key.
- *
- * This function accepts a dispatch hash and the condition of a when clause. It
- * is responsible for compiling the condition into a hash key and then adding it
- * to the dispatch hash.
- *
- * If the value can be successfully compiled into the hash, then this function
- * returns the dispatch hash with the new key added. If the value cannot be
- * compiled into the hash, then this function returns Qundef. In the case of
- * Qundef, this function is signaling that the caller should abandon the
- * optimization entirely.
- */
-static VALUE
-pm_compile_case_node_dispatch(rb_iseq_t *iseq, VALUE dispatch, const pm_node_t *node, LABEL *label, const pm_scope_node_t *scope_node)
-{
- VALUE key = Qundef;
-
- switch (PM_NODE_TYPE(node)) {
- case PM_FLOAT_NODE: {
- key = pm_static_literal_value(iseq, node, scope_node);
- double intptr;
-
- if (modf(RFLOAT_VALUE(key), &intptr) == 0.0) {
- key = (FIXABLE(intptr) ? LONG2FIX((long) intptr) : rb_dbl2big(intptr));
- }
-
- break;
- }
- case PM_FALSE_NODE:
- case PM_INTEGER_NODE:
- case PM_NIL_NODE:
- case PM_SOURCE_FILE_NODE:
- case PM_SOURCE_LINE_NODE:
- case PM_SYMBOL_NODE:
- case PM_TRUE_NODE:
- key = pm_static_literal_value(iseq, node, scope_node);
- break;
- case PM_STRING_NODE: {
- const pm_string_node_t *cast = (const pm_string_node_t *) node;
- key = parse_static_literal_string(iseq, scope_node, node, &cast->unescaped);
- break;
- }
- default:
- return Qundef;
- }
-
- if (NIL_P(rb_hash_lookup(dispatch, key))) {
- rb_hash_aset(dispatch, key, ((VALUE) label) | 1);
- }
-
- return dispatch;
-}
-
-/**
* Return the object that will be pushed onto the stack for the given node.
*/
static VALUE
@@ -4892,12 +5712,12 @@ pm_compile_shareable_constant_value(rb_iseq_t *iseq, const pm_node_t *node, cons
{
VALUE literal = pm_compile_shareable_constant_literal(iseq, node, scope_node);
if (literal != Qundef) {
- const pm_line_column_t location = PM_NODE_START_LINE_COLUMN(scope_node->parser, node);
+ const pm_node_location_t location = PM_NODE_START_LOCATION(scope_node->parser, node);
PUSH_INSN1(ret, location, putobject, literal);
return;
}
- const pm_line_column_t location = PM_NODE_START_LINE_COLUMN(scope_node->parser, node);
+ const pm_node_location_t location = PM_NODE_START_LOCATION(scope_node->parser, node);
switch (PM_NODE_TYPE(node)) {
case PM_ARRAY_NODE: {
const pm_array_node_t *cast = (const pm_array_node_t *) node;
@@ -4926,19 +5746,7 @@ pm_compile_shareable_constant_value(rb_iseq_t *iseq, const pm_node_t *node, cons
PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
}
- for (size_t index = 0; index < cast->elements.size; index++) {
- const pm_node_t *element = cast->elements.nodes[index];
-
- if (!PM_NODE_TYPE_P(element, PM_ASSOC_NODE)) {
- COMPILE_ERROR(iseq, location.line, "Ractor constant writes do not support **");
- }
-
- const pm_assoc_node_t *assoc = (const pm_assoc_node_t *) element;
- pm_compile_shareable_constant_value(iseq, assoc->key, shareability, path, ret, scope_node, false);
- pm_compile_shareable_constant_value(iseq, assoc->value, shareability, path, ret, scope_node, false);
- }
-
- PUSH_INSN1(ret, location, newhash, INT2FIX(cast->elements.size * 2));
+ pm_compile_hash_elements(iseq, (const pm_node_t *) cast, &cast->elements, shareability, path, false, ret, scope_node);
if (top) {
ID method_id = (shareability & PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_COPY) ? rb_intern("make_shareable_copy") : rb_intern("make_shareable");
@@ -4949,7 +5757,6 @@ pm_compile_shareable_constant_value(rb_iseq_t *iseq, const pm_node_t *node, cons
}
default: {
DECL_ANCHOR(value_seq);
- INIT_ANCHOR(value_seq);
pm_compile_node(iseq, node, value_seq, false, scope_node);
if (PM_NODE_TYPE_P(node, PM_INTERPOLATED_STRING_NODE)) {
@@ -4959,6 +5766,9 @@ pm_compile_shareable_constant_value(rb_iseq_t *iseq, const pm_node_t *node, cons
if (shareability & PM_SHAREABLE_CONSTANT_NODE_FLAGS_LITERAL) {
PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
PUSH_SEQ(ret, value_seq);
+ if (!RB_OBJ_SHAREABLE_P(path)) {
+ RB_OBJ_SET_SHAREABLE(path);
+ }
PUSH_INSN1(ret, location, putobject, path);
PUSH_SEND_WITH_FLAG(ret, location, rb_intern("ensure_shareable"), INT2FIX(2), INT2FIX(VM_CALL_ARGS_SIMPLE));
}
@@ -4983,9 +5793,9 @@ pm_compile_shareable_constant_value(rb_iseq_t *iseq, const pm_node_t *node, cons
* not.
*/
static void
-pm_compile_constant_write_node(rb_iseq_t *iseq, const pm_constant_write_node_t *node, const pm_node_flags_t shareability, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+pm_compile_constant_write_node(rb_iseq_t *iseq, const pm_constant_write_node_t *node, const pm_node_flags_t shareability, const pm_node_location_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
{
- const pm_line_column_t location = *node_location;
+ const pm_node_location_t location = *node_location;
ID name_id = pm_constant_id_lookup(scope_node, node->name);
if (shareability != 0) {
@@ -4997,7 +5807,9 @@ pm_compile_constant_write_node(rb_iseq_t *iseq, const pm_constant_write_node_t *
if (!popped) PUSH_INSN(ret, location, dup);
PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE));
- PUSH_INSN1(ret, location, setconstant, ID2SYM(name_id));
+
+ VALUE operand = ID2SYM(name_id);
+ PUSH_INSN1(ret, location, setconstant, operand);
}
/**
@@ -5005,14 +5817,14 @@ pm_compile_constant_write_node(rb_iseq_t *iseq, const pm_constant_write_node_t *
* or not.
*/
static void
-pm_compile_constant_and_write_node(rb_iseq_t *iseq, const pm_constant_and_write_node_t *node, const pm_node_flags_t shareability, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+pm_compile_constant_and_write_node(rb_iseq_t *iseq, const pm_constant_and_write_node_t *node, const pm_node_flags_t shareability, const pm_node_location_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
{
- const pm_line_column_t location = *node_location;
+ const pm_node_location_t location = *node_location;
VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, node->name));
LABEL *end_label = NEW_LABEL(location.line);
- pm_compile_constant_read(iseq, name, &node->name_loc, ret, scope_node);
+ pm_compile_constant_read(iseq, name, &node->name_loc, location.node_id, ret, scope_node);
if (!popped) PUSH_INSN(ret, location, dup);
PUSH_INSNL(ret, location, branchunless, end_label);
@@ -5036,9 +5848,9 @@ pm_compile_constant_and_write_node(rb_iseq_t *iseq, const pm_constant_and_write_
* not.
*/
static void
-pm_compile_constant_or_write_node(rb_iseq_t *iseq, const pm_constant_or_write_node_t *node, const pm_node_flags_t shareability, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+pm_compile_constant_or_write_node(rb_iseq_t *iseq, const pm_constant_or_write_node_t *node, const pm_node_flags_t shareability, const pm_node_location_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
{
- const pm_line_column_t location = *node_location;
+ const pm_node_location_t location = *node_location;
VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, node->name));
LABEL *set_label = NEW_LABEL(location.line);
@@ -5048,7 +5860,7 @@ pm_compile_constant_or_write_node(rb_iseq_t *iseq, const pm_constant_or_write_no
PUSH_INSN3(ret, location, defined, INT2FIX(DEFINED_CONST), name, Qtrue);
PUSH_INSNL(ret, location, branchunless, set_label);
- pm_compile_constant_read(iseq, name, &node->name_loc, ret, scope_node);
+ pm_compile_constant_read(iseq, name, &node->name_loc, location.node_id, ret, scope_node);
if (!popped) PUSH_INSN(ret, location, dup);
PUSH_INSNL(ret, location, branchif, end_label);
@@ -5073,14 +5885,14 @@ pm_compile_constant_or_write_node(rb_iseq_t *iseq, const pm_constant_or_write_no
* pragma or not.
*/
static void
-pm_compile_constant_operator_write_node(rb_iseq_t *iseq, const pm_constant_operator_write_node_t *node, const pm_node_flags_t shareability, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+pm_compile_constant_operator_write_node(rb_iseq_t *iseq, const pm_constant_operator_write_node_t *node, const pm_node_flags_t shareability, const pm_node_location_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
{
- const pm_line_column_t location = *node_location;
+ const pm_node_location_t location = *node_location;
VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, node->name));
ID method_id = pm_constant_id_lookup(scope_node, node->binary_operator);
- pm_compile_constant_read(iseq, name, &node->name_loc, ret, scope_node);
+ pm_compile_constant_read(iseq, name, &node->name_loc, location.node_id, ret, scope_node);
if (shareability != 0) {
pm_compile_shareable_constant_value(iseq, node->value, shareability, name, ret, scope_node, true);
@@ -5131,9 +5943,9 @@ pm_constant_path_path(const pm_constant_path_node_t *node, const pm_scope_node_t
* or not.
*/
static void
-pm_compile_constant_path_write_node(rb_iseq_t *iseq, const pm_constant_path_write_node_t *node, const pm_node_flags_t shareability, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+pm_compile_constant_path_write_node(rb_iseq_t *iseq, const pm_constant_path_write_node_t *node, const pm_node_flags_t shareability, const pm_node_location_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
{
- const pm_line_column_t location = *node_location;
+ const pm_node_location_t location = *node_location;
const pm_constant_path_node_t *target = node->target;
VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, target->name));
@@ -5165,9 +5977,9 @@ pm_compile_constant_path_write_node(rb_iseq_t *iseq, const pm_constant_path_writ
* pragma or not.
*/
static void
-pm_compile_constant_path_and_write_node(rb_iseq_t *iseq, const pm_constant_path_and_write_node_t *node, const pm_node_flags_t shareability, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+pm_compile_constant_path_and_write_node(rb_iseq_t *iseq, const pm_constant_path_and_write_node_t *node, const pm_node_flags_t shareability, const pm_node_location_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
{
- const pm_line_column_t location = *node_location;
+ const pm_node_location_t location = *node_location;
const pm_constant_path_node_t *target = node->target;
VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, target->name));
@@ -5216,9 +6028,9 @@ pm_compile_constant_path_and_write_node(rb_iseq_t *iseq, const pm_constant_path_
* pragma or not.
*/
static void
-pm_compile_constant_path_or_write_node(rb_iseq_t *iseq, const pm_constant_path_or_write_node_t *node, const pm_node_flags_t shareability, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+pm_compile_constant_path_or_write_node(rb_iseq_t *iseq, const pm_constant_path_or_write_node_t *node, const pm_node_flags_t shareability, const pm_node_location_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
{
- const pm_line_column_t location = *node_location;
+ const pm_node_location_t location = *node_location;
const pm_constant_path_node_t *target = node->target;
VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, target->name));
@@ -5273,9 +6085,9 @@ pm_compile_constant_path_or_write_node(rb_iseq_t *iseq, const pm_constant_path_o
* ractor pragma or not.
*/
static void
-pm_compile_constant_path_operator_write_node(rb_iseq_t *iseq, const pm_constant_path_operator_write_node_t *node, const pm_node_flags_t shareability, const pm_line_column_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+pm_compile_constant_path_operator_write_node(rb_iseq_t *iseq, const pm_constant_path_operator_write_node_t *node, const pm_node_flags_t shareability, const pm_node_location_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
{
- const pm_line_column_t location = *node_location;
+ const pm_node_location_t location = *node_location;
const pm_constant_path_node_t *target = node->target;
ID method_id = pm_constant_id_lookup(scope_node, node->binary_operator);
@@ -5311,959 +6123,2710 @@ pm_compile_constant_path_operator_write_node(rb_iseq_t *iseq, const pm_constant_
}
/**
- * Compiles a prism node into instruction sequences.
- *
- * iseq - The current instruction sequence object (used for locals)
- * node - The prism node to compile
- * ret - The linked list of instructions to append instructions onto
- * popped - True if compiling something with no side effects, so instructions don't
- * need to be added
- * scope_node - Stores parser and local information
+ * Many nodes in Prism can be marked as a static literal, which means slightly
+ * different things depending on which node it is. Occasionally we need to omit
+ * container nodes from static literal checks, which is where this macro comes
+ * in.
*/
-static void
-pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+#define PM_CONTAINER_P(node) (PM_NODE_TYPE_P(node, PM_ARRAY_NODE) || PM_NODE_TYPE_P(node, PM_HASH_NODE) || PM_NODE_TYPE_P(node, PM_RANGE_NODE))
+
+/**
+ * Compile a scope node, which is a special kind of node that represents a new
+ * lexical scope, attached to a node in the AST.
+ */
+static inline void
+pm_compile_scope_node(rb_iseq_t *iseq, pm_scope_node_t *scope_node, const pm_node_location_t *node_location, LINK_ANCHOR *const ret, bool popped)
{
- const pm_parser_t *parser = scope_node->parser;
- const pm_line_column_t location = PM_NODE_START_LINE_COLUMN(parser, node);
- int lineno = (int) location.line;
+ const pm_node_location_t location = *node_location;
+ struct rb_iseq_constant_body *body = ISEQ_BODY(iseq);
- if (PM_NODE_TYPE_P(node, PM_RETURN_NODE) && PM_NODE_FLAG_P(node, PM_RETURN_NODE_FLAGS_REDUNDANT) && ((const pm_return_node_t *) node)->arguments == NULL) {
- // If the node that we're compiling is a return node that is redundant,
- // then it cannot be considered a line node because the other parser
- // eliminates it from the parse tree. In this case we must replicate
- // this behavior.
- } else {
- if (PM_NODE_TYPE_P(node, PM_BEGIN_NODE) && (((const pm_begin_node_t *) node)->statements == NULL) && (((const pm_begin_node_t *) node)->rescue_clause != NULL)) {
- // If this node is a begin node and it has empty statements and also
- // has a rescue clause, then the other parser considers it as
- // starting on the same line as the rescue, as opposed to the
- // location of the begin keyword. We replicate that behavior here.
- lineno = (int) PM_NODE_START_LINE_COLUMN(parser, ((const pm_begin_node_t *) node)->rescue_clause).line;
+ pm_constant_id_list_t *locals = &scope_node->locals;
+ pm_parameters_node_t *parameters_node = NULL;
+ pm_node_list_t *keywords_list = NULL;
+ pm_node_list_t *optionals_list = NULL;
+ pm_node_list_t *posts_list = NULL;
+ pm_node_list_t *requireds_list = NULL;
+ pm_node_list_t *block_locals = NULL;
+ bool trailing_comma = false;
+
+ if (PM_NODE_TYPE_P(scope_node->ast_node, PM_CLASS_NODE) || PM_NODE_TYPE_P(scope_node->ast_node, PM_MODULE_NODE)) {
+ PUSH_TRACE(ret, RUBY_EVENT_CLASS);
+ }
+
+ if (scope_node->parameters != NULL) {
+ switch (PM_NODE_TYPE(scope_node->parameters)) {
+ case PM_BLOCK_PARAMETERS_NODE: {
+ pm_block_parameters_node_t *cast = (pm_block_parameters_node_t *) scope_node->parameters;
+ parameters_node = cast->parameters;
+ block_locals = &cast->locals;
+
+ if (parameters_node) {
+ if (parameters_node->rest && PM_NODE_TYPE_P(parameters_node->rest, PM_IMPLICIT_REST_NODE)) {
+ trailing_comma = true;
+ }
+ }
+ break;
+ }
+ case PM_PARAMETERS_NODE: {
+ parameters_node = (pm_parameters_node_t *) scope_node->parameters;
+ break;
+ }
+ case PM_NUMBERED_PARAMETERS_NODE: {
+ uint32_t maximum = ((const pm_numbered_parameters_node_t *) scope_node->parameters)->maximum;
+ body->param.lead_num = maximum;
+ body->param.flags.ambiguous_param0 = maximum == 1;
+ break;
+ }
+ case PM_IT_PARAMETERS_NODE:
+ body->param.lead_num = 1;
+ body->param.flags.ambiguous_param0 = true;
+ break;
+ default:
+ rb_bug("Unexpected node type for parameters: %s", pm_node_type_to_str(PM_NODE_TYPE(scope_node->parameters)));
}
+ }
- if (PM_NODE_FLAG_P(node, PM_NODE_FLAG_NEWLINE) && ISEQ_COMPILE_DATA(iseq)->last_line != lineno) {
- // If this node has the newline flag set and it is on a new line
- // from the previous nodes that have been compiled for this ISEQ,
- // then we need to emit a newline event.
- int event = RUBY_EVENT_LINE;
+ struct rb_iseq_param_keyword *keyword = NULL;
+
+ if (parameters_node) {
+ optionals_list = &parameters_node->optionals;
+ requireds_list = &parameters_node->requireds;
+ keywords_list = &parameters_node->keywords;
+ posts_list = &parameters_node->posts;
+ }
+ else if (scope_node->parameters && (PM_NODE_TYPE_P(scope_node->parameters, PM_NUMBERED_PARAMETERS_NODE) || PM_NODE_TYPE_P(scope_node->parameters, PM_IT_PARAMETERS_NODE))) {
+ body->param.opt_num = 0;
+ }
+ else {
+ body->param.lead_num = 0;
+ body->param.opt_num = 0;
+ }
+
+ //********STEP 1**********
+ // Goal: calculate the table size for the locals, accounting for
+ // hidden variables and multi target nodes
+ size_t locals_size = locals->size;
+
+ // Index lookup table buffer size is only the number of the locals
+ st_table *index_lookup_table = st_init_numtable();
+
+ int table_size = (int) locals_size;
+
+ // For nodes have a hidden iteration variable. We add that to the local
+ // table size here.
+ if (PM_NODE_TYPE_P(scope_node->ast_node, PM_FOR_NODE)) table_size++;
+
+ if (keywords_list && keywords_list->size) {
+ table_size++;
+ }
- ISEQ_COMPILE_DATA(iseq)->last_line = lineno;
- if (ISEQ_COVERAGE(iseq) && ISEQ_LINE_COVERAGE(iseq)) {
- event |= RUBY_EVENT_COVERAGE_LINE;
+ if (requireds_list) {
+ for (size_t i = 0; i < requireds_list->size; i++) {
+ // For each MultiTargetNode, we're going to have one
+ // additional anonymous local not represented in the locals table
+ // We want to account for this in our table size
+ pm_node_t *required = requireds_list->nodes[i];
+ if (PM_NODE_TYPE_P(required, PM_MULTI_TARGET_NODE)) {
+ table_size++;
+ }
+ else if (PM_NODE_TYPE_P(required, PM_REQUIRED_PARAMETER_NODE)) {
+ if (PM_NODE_FLAG_P(required, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
+ table_size++;
+ }
}
- PUSH_TRACE(ret, event);
}
}
- switch (PM_NODE_TYPE(node)) {
- case PM_ALIAS_GLOBAL_VARIABLE_NODE: {
- // alias $foo $bar
- // ^^^^^^^^^^^^^^^
- const pm_alias_global_variable_node_t *cast = (const pm_alias_global_variable_node_t *) node;
- PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
+ // If we have the `it` implicit local variable, we need to account for
+ // it in the local table size.
+ if (scope_node->parameters != NULL && PM_NODE_TYPE_P(scope_node->parameters, PM_IT_PARAMETERS_NODE)) {
+ table_size++;
+ }
- const pm_location_t *new_name_loc = &cast->new_name->location;
- PUSH_INSN1(ret, location, putobject, ID2SYM(rb_intern3((const char *) new_name_loc->start, new_name_loc->end - new_name_loc->start, scope_node->encoding)));
+ // Ensure there is enough room in the local table for any
+ // parameters that have been repeated
+ // ex: def underscore_parameters(_, _ = 1, _ = 2); _; end
+ // ^^^^^^^^^^^^
+ if (optionals_list && optionals_list->size) {
+ for (size_t i = 0; i < optionals_list->size; i++) {
+ pm_node_t * node = optionals_list->nodes[i];
+ if (PM_NODE_FLAG_P(node, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
+ table_size++;
+ }
+ }
+ }
- const pm_location_t *old_name_loc = &cast->old_name->location;
- PUSH_INSN1(ret, location, putobject, ID2SYM(rb_intern3((const char *) old_name_loc->start, old_name_loc->end - old_name_loc->start, scope_node->encoding)));
+ // If we have an anonymous "rest" node, we'll need to increase the local
+ // table size to take it in to account.
+ // def m(foo, *, bar)
+ // ^
+ if (parameters_node) {
+ if (parameters_node->rest) {
+ if (!(PM_NODE_TYPE_P(parameters_node->rest, PM_IMPLICIT_REST_NODE))) {
+ if (!((const pm_rest_parameter_node_t *) parameters_node->rest)->name || PM_NODE_FLAG_P(parameters_node->rest, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
+ table_size++;
+ }
+ }
+ }
- PUSH_SEND(ret, location, id_core_set_variable_alias, INT2FIX(2));
- if (popped) PUSH_INSN(ret, location, pop);
+ // def foo(_, **_); _; end
+ // ^^^
+ if (parameters_node->keyword_rest) {
+ // def foo(...); end
+ // ^^^
+ // When we have a `...` as the keyword_rest, it's a forwarding_parameter_node and
+ // we need to leave space for 4 locals: *, **, &, ...
+ if (PM_NODE_TYPE_P(parameters_node->keyword_rest, PM_FORWARDING_PARAMETER_NODE)) {
+ // Only optimize specifically methods like this: `foo(...)`
+ if (requireds_list->size == 0 && optionals_list->size == 0 && keywords_list->size == 0) {
+ ISEQ_BODY(iseq)->param.flags.use_block = TRUE;
+ ISEQ_BODY(iseq)->param.flags.forwardable = TRUE;
+ table_size += 1;
+ }
+ else {
+ table_size += 4;
+ }
+ }
+ else {
+ const pm_keyword_rest_parameter_node_t *kw_rest = (const pm_keyword_rest_parameter_node_t *) parameters_node->keyword_rest;
- return;
- }
- case PM_ALIAS_METHOD_NODE: {
- // alias foo bar
- // ^^^^^^^^^^^^^
- const pm_alias_method_node_t *cast = (const pm_alias_method_node_t *) node;
+ // If it's anonymous or repeated, then we need to allocate stack space
+ if (!kw_rest->name || PM_NODE_FLAG_P(kw_rest, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
+ table_size++;
+ }
+ }
+ }
+ }
- PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
- PUSH_INSN1(ret, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
- PM_COMPILE_NOT_POPPED(cast->new_name);
- PM_COMPILE_NOT_POPPED(cast->old_name);
+ if (posts_list) {
+ for (size_t i = 0; i < posts_list->size; i++) {
+ // For each MultiTargetNode, we're going to have one
+ // additional anonymous local not represented in the locals table
+ // We want to account for this in our table size
+ pm_node_t *required = posts_list->nodes[i];
+ if (PM_NODE_TYPE_P(required, PM_MULTI_TARGET_NODE) || PM_NODE_FLAG_P(required, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
+ table_size++;
+ }
+ }
+ }
- PUSH_SEND(ret, location, id_core_set_method_alias, INT2FIX(3));
- if (popped) PUSH_INSN(ret, location, pop);
+ if (keywords_list && keywords_list->size) {
+ for (size_t i = 0; i < keywords_list->size; i++) {
+ pm_node_t *keyword_parameter_node = keywords_list->nodes[i];
+ if (PM_NODE_FLAG_P(keyword_parameter_node, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
+ table_size++;
+ }
+ }
+ }
- return;
- }
- case PM_AND_NODE: {
- // a and b
- // ^^^^^^^
- const pm_and_node_t *cast = (const pm_and_node_t *) node;
- LABEL *end_label = NEW_LABEL(lineno);
+ if (parameters_node && parameters_node->block) {
+ const pm_block_parameter_node_t *block_node = (const pm_block_parameter_node_t *) parameters_node->block;
- PM_COMPILE_NOT_POPPED(cast->left);
- if (!popped) PUSH_INSN(ret, location, dup);
- PUSH_INSNL(ret, location, branchunless, end_label);
+ if (PM_NODE_FLAG_P(block_node, PM_PARAMETER_FLAGS_REPEATED_PARAMETER) || !block_node->name) {
+ table_size++;
+ }
+ }
- if (!popped) PUSH_INSN(ret, location, pop);
- PM_COMPILE(cast->right);
- PUSH_LABEL(ret, end_label);
+ // We can create local_table_for_iseq with the correct size
+ VALUE idtmp = 0;
+ rb_ast_id_table_t *local_table_for_iseq = ALLOCV(idtmp, sizeof(rb_ast_id_table_t) + table_size * sizeof(ID));
+ local_table_for_iseq->size = table_size;
+
+ //********END OF STEP 1**********
+
+ //********STEP 2**********
+ // Goal: populate iv index table as well as local table, keeping the
+ // layout of the local table consistent with the layout of the
+ // stack when calling the method
+ //
+ // Do a first pass on all of the parameters, setting their values in
+ // the local_table_for_iseq, _except_ for Multis who get a hidden
+ // variable in this step, and will get their names inserted in step 3
+
+ // local_index is a cursor that keeps track of the current
+ // index into local_table_for_iseq. The local table is actually a list,
+ // and the order of that list must match the order of the items pushed
+ // on the stack. We need to take in to account things pushed on the
+ // stack that _might not have a name_ (for example array destructuring).
+ // This index helps us know which item we're dealing with and also give
+ // those anonymous items temporary names (as below)
+ int local_index = 0;
+
+ // Here we figure out local table indices and insert them in to the
+ // index lookup table and local tables.
+ //
+ // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
+ // ^^^^^^^^^^^^^
+ if (requireds_list && requireds_list->size) {
+ for (size_t i = 0; i < requireds_list->size; i++, local_index++) {
+ ID local;
+
+ // For each MultiTargetNode, we're going to have one additional
+ // anonymous local not represented in the locals table. We want
+ // to account for this in our table size.
+ pm_node_t *required = requireds_list->nodes[i];
+
+ switch (PM_NODE_TYPE(required)) {
+ case PM_MULTI_TARGET_NODE: {
+ // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
+ // ^^^^^^^^^^
+ local = rb_make_temporary_id(local_index);
+ local_table_for_iseq->ids[local_index] = local;
+ break;
+ }
+ case PM_REQUIRED_PARAMETER_NODE: {
+ // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
+ // ^
+ const pm_required_parameter_node_t *param = (const pm_required_parameter_node_t *) required;
- return;
- }
- case PM_ARGUMENTS_NODE:
- // These are ArgumentsNodes that are not compiled directly by their
- // parent call nodes, used in the cases of NextNodes, ReturnNodes, and
- // BreakNodes. They can create an array like ArrayNode.
- case PM_ARRAY_NODE: {
- const pm_node_list_t *elements;
+ if (PM_NODE_FLAG_P(required, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
+ ID local = pm_constant_id_lookup(scope_node, param->name);
+ local_table_for_iseq->ids[local_index] = local;
+ }
+ else {
+ pm_insert_local_index(param->name, local_index, index_lookup_table, local_table_for_iseq, scope_node);
+ }
- if (PM_NODE_TYPE(node) == PM_ARGUMENTS_NODE) {
- // break foo
- // ^^^
- const pm_arguments_node_t *cast = (const pm_arguments_node_t *) node;
- elements = &cast->arguments;
+ break;
+ }
+ default:
+ rb_bug("Unsupported node in requireds in parameters %s", pm_node_type_to_str(PM_NODE_TYPE(required)));
+ }
+ }
- // If we are only returning a single element through one of the jump
- // nodes, then we will only compile that node directly.
- if (elements->size == 1) {
- PM_COMPILE(elements->nodes[0]);
- return;
+ body->param.lead_num = (int) requireds_list->size;
+ body->param.flags.has_lead = true;
+ }
+
+ if (scope_node->parameters != NULL && PM_NODE_TYPE_P(scope_node->parameters, PM_IT_PARAMETERS_NODE)) {
+ local_table_for_iseq->ids[local_index++] = idItImplicit;
+ }
+
+ // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
+ // ^^^^^
+ if (optionals_list && optionals_list->size) {
+ body->param.opt_num = (int) optionals_list->size;
+ body->param.flags.has_opt = true;
+
+ for (size_t i = 0; i < optionals_list->size; i++, local_index++) {
+ pm_node_t * node = optionals_list->nodes[i];
+ pm_constant_id_t name = ((const pm_optional_parameter_node_t *) node)->name;
+
+ if (PM_NODE_FLAG_P(node, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
+ ID local = pm_constant_id_lookup(scope_node, name);
+ local_table_for_iseq->ids[local_index] = local;
+ }
+ else {
+ pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node);
}
}
- else {
- // [foo, bar, baz]
- // ^^^^^^^^^^^^^^^
- const pm_array_node_t *cast = (const pm_array_node_t *) node;
- elements = &cast->elements;
+ }
+
+ // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
+ // ^^
+ if (parameters_node && parameters_node->rest) {
+ body->param.rest_start = local_index;
+
+ // If there's a trailing comma, we'll have an implicit rest node,
+ // and we don't want it to impact the rest variables on param
+ if (!(PM_NODE_TYPE_P(parameters_node->rest, PM_IMPLICIT_REST_NODE))) {
+ body->param.flags.has_rest = true;
+ RUBY_ASSERT(body->param.rest_start != -1);
+
+ pm_constant_id_t name = ((const pm_rest_parameter_node_t *) parameters_node->rest)->name;
+
+ if (name) {
+ // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
+ // ^^
+ if (PM_NODE_FLAG_P(parameters_node->rest, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
+ ID local = pm_constant_id_lookup(scope_node, name);
+ local_table_for_iseq->ids[local_index] = local;
+ }
+ else {
+ pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node);
+ }
+ }
+ else {
+ // def foo(a, (b, *c, d), e = 1, *, g, (h, *i, j), k:, l: 1, **m, &n)
+ // ^
+ body->param.flags.anon_rest = true;
+ pm_insert_local_special(idMULT, local_index, index_lookup_table, local_table_for_iseq);
+ }
+
+ local_index++;
}
+ }
- // If every node in the array is static, then we can compile the entire
- // array now instead of later.
- if (PM_NODE_FLAG_P(node, PM_NODE_FLAG_STATIC_LITERAL)) {
- // We're only going to compile this node if it's not popped. If it
- // is popped, then we know we don't need to do anything since it's
- // statically known.
- if (!popped) {
- if (elements->size) {
- VALUE value = pm_static_literal_value(iseq, node, scope_node);
- PUSH_INSN1(ret, location, duparray, value);
+ // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
+ // ^^^^^^^^^^^^^
+ if (posts_list && posts_list->size) {
+ body->param.post_num = (int) posts_list->size;
+ body->param.post_start = local_index;
+ body->param.flags.has_post = true;
+
+ for (size_t i = 0; i < posts_list->size; i++, local_index++) {
+ ID local;
+
+ // For each MultiTargetNode, we're going to have one additional
+ // anonymous local not represented in the locals table. We want
+ // to account for this in our table size.
+ const pm_node_t *post_node = posts_list->nodes[i];
+
+ switch (PM_NODE_TYPE(post_node)) {
+ case PM_MULTI_TARGET_NODE: {
+ // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
+ // ^^^^^^^^^^
+ local = rb_make_temporary_id(local_index);
+ local_table_for_iseq->ids[local_index] = local;
+ break;
+ }
+ case PM_REQUIRED_PARAMETER_NODE: {
+ // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
+ // ^
+ const pm_required_parameter_node_t *param = (const pm_required_parameter_node_t *) post_node;
+
+ if (PM_NODE_FLAG_P(param, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
+ ID local = pm_constant_id_lookup(scope_node, param->name);
+ local_table_for_iseq->ids[local_index] = local;
}
else {
- PUSH_INSN1(ret, location, newarray, INT2FIX(0));
+ pm_insert_local_index(param->name, local_index, index_lookup_table, local_table_for_iseq, scope_node);
}
+ break;
+ }
+ default:
+ rb_bug("Unsupported node in posts in parameters %s", pm_node_type_to_str(PM_NODE_TYPE(post_node)));
}
}
- else {
- // Here since we know there are possible side-effects inside the
- // array contents, we're going to build it entirely at runtime.
- // We'll do this by pushing all of the elements onto the stack and
- // then combining them with newarray.
- //
- // If this array is popped, then this serves only to ensure we enact
- // all side-effects (like method calls) that are contained within
- // the array contents.
- //
- // We treat all sequences of non-splat elements as their
- // own arrays, followed by a newarray, and then continually
- // concat the arrays with the SplatNode nodes.
- int new_array_size = 0;
-
- bool need_to_concat_array = false;
- bool has_kw_splat = false;
-
- for (size_t index = 0; index < elements->size; index++) {
- const pm_node_t *element = elements->nodes[index];
-
- if (PM_NODE_TYPE_P(element, PM_SPLAT_NODE)) {
- const pm_splat_node_t *splat_element = (const pm_splat_node_t *) element;
-
- // If we already have non-splat elements, we need to emit a
- // newarray instruction.
- if (new_array_size > 0) {
- PUSH_INSN1(ret, location, newarray, INT2FIX(new_array_size));
- new_array_size = 0;
-
- // We don't want to emit a concat array in the case
- // where we're seeing our first splat, and already have
- // elements.
- if (need_to_concat_array) PUSH_INSN(ret, location, concatarray);
- }
+ }
- if (splat_element->expression) {
- PM_COMPILE_NOT_POPPED(splat_element->expression);
- }
- else {
- pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_MULT, 0);
- PUSH_GETLOCAL(ret, location, index.index, index.level);
- }
+ // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
+ // ^^^^^^^^
+ // Keywords create an internal variable on the parse tree
+ if (keywords_list && keywords_list->size) {
+ keyword = ZALLOC_N(struct rb_iseq_param_keyword, 1);
+ keyword->num = (int) keywords_list->size;
+
+ const VALUE default_values = rb_ary_hidden_new(1);
+ const VALUE complex_mark = rb_str_tmp_new(0);
+
+ for (size_t i = 0; i < keywords_list->size; i++) {
+ pm_node_t *keyword_parameter_node = keywords_list->nodes[i];
+ pm_constant_id_t name;
+
+ // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
+ // ^^
+ if (PM_NODE_TYPE_P(keyword_parameter_node, PM_REQUIRED_KEYWORD_PARAMETER_NODE)) {
+ name = ((const pm_required_keyword_parameter_node_t *) keyword_parameter_node)->name;
+ keyword->required_num++;
+ ID local = pm_constant_id_lookup(scope_node, name);
+
+ if (PM_NODE_FLAG_P(keyword_parameter_node, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
+ local_table_for_iseq->ids[local_index] = local;
+ }
+ else {
+ pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node);
+ }
+ local_index++;
+ }
+ }
+
+ for (size_t i = 0; i < keywords_list->size; i++) {
+ pm_node_t *keyword_parameter_node = keywords_list->nodes[i];
+ pm_constant_id_t name;
+
+ // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
+ // ^^^^
+ if (PM_NODE_TYPE_P(keyword_parameter_node, PM_OPTIONAL_KEYWORD_PARAMETER_NODE)) {
+ const pm_optional_keyword_parameter_node_t *cast = ((const pm_optional_keyword_parameter_node_t *) keyword_parameter_node);
+
+ pm_node_t *value = cast->value;
+ name = cast->name;
+
+ if (PM_NODE_FLAG_P(value, PM_NODE_FLAG_STATIC_LITERAL) && !PM_CONTAINER_P(value)) {
+ rb_ary_push(default_values, pm_static_literal_value(iseq, value, scope_node));
+ }
+ else {
+ rb_ary_push(default_values, complex_mark);
+ }
+
+ ID local = pm_constant_id_lookup(scope_node, name);
+ if (PM_NODE_FLAG_P(keyword_parameter_node, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
+ local_table_for_iseq->ids[local_index] = local;
+ }
+ else {
+ pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node);
+ }
+ local_index++;
+ }
+
+ }
+
+ if (RARRAY_LEN(default_values)) {
+ VALUE *dvs = ALLOC_N(VALUE, RARRAY_LEN(default_values));
+
+ for (int i = 0; i < RARRAY_LEN(default_values); i++) {
+ VALUE dv = RARRAY_AREF(default_values, i);
+ if (dv == complex_mark) dv = Qundef;
+ RB_OBJ_WRITE(iseq, &dvs[i], dv);
+ }
+
+ keyword->default_values = dvs;
+ }
+
+ // Hidden local for keyword arguments
+ keyword->bits_start = local_index;
+ ID local = rb_make_temporary_id(local_index);
+ local_table_for_iseq->ids[local_index] = local;
+ local_index++;
+
+ body->param.keyword = keyword;
+ body->param.flags.has_kw = true;
+ }
- if (index > 0) {
- PUSH_INSN(ret, location, concatarray);
+ if (body->type == ISEQ_TYPE_BLOCK && local_index == 1 && requireds_list && requireds_list->size == 1 && !trailing_comma) {
+ body->param.flags.ambiguous_param0 = true;
+ }
+
+ if (parameters_node) {
+ // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
+ // ^^^
+ if (parameters_node->keyword_rest) {
+ switch (PM_NODE_TYPE(parameters_node->keyword_rest)) {
+ case PM_NO_KEYWORDS_PARAMETER_NODE: {
+ // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **nil, &n)
+ // ^^^^^
+ body->param.flags.accepts_no_kwarg = true;
+ break;
+ }
+ case PM_KEYWORD_REST_PARAMETER_NODE: {
+ // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
+ // ^^^
+ const pm_keyword_rest_parameter_node_t *kw_rest_node = (const pm_keyword_rest_parameter_node_t *) parameters_node->keyword_rest;
+ if (!body->param.flags.has_kw) {
+ body->param.keyword = keyword = ZALLOC_N(struct rb_iseq_param_keyword, 1);
+ }
+
+ keyword->rest_start = local_index;
+ body->param.flags.has_kwrest = true;
+
+ pm_constant_id_t constant_id = kw_rest_node->name;
+ if (constant_id) {
+ if (PM_NODE_FLAG_P(kw_rest_node, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
+ ID local = pm_constant_id_lookup(scope_node, constant_id);
+ local_table_for_iseq->ids[local_index] = local;
}
else {
- // If this is the first element of the array then we
- // need to splatarray the elements into the list.
- PUSH_INSN1(ret, location, splatarray, Qtrue);
+ pm_insert_local_index(constant_id, local_index, index_lookup_table, local_table_for_iseq, scope_node);
}
-
- // Since we have now seen a splat and are concat-ing arrays,
- // all subsequent splats will need to concat as well.
- need_to_concat_array = true;
- }
- else if (PM_NODE_TYPE_P(element, PM_KEYWORD_HASH_NODE)) {
- new_array_size++;
- has_kw_splat = true;
- pm_compile_hash_elements(iseq, element, &((const pm_keyword_hash_node_t *) element)->elements, ret, scope_node);
}
else {
- new_array_size++;
- PM_COMPILE_NOT_POPPED(element);
+ body->param.flags.anon_kwrest = true;
+ pm_insert_local_special(idPow, local_index, index_lookup_table, local_table_for_iseq);
}
+
+ local_index++;
+ break;
+ }
+ case PM_FORWARDING_PARAMETER_NODE: {
+ // def foo(...)
+ // ^^^
+ if (!ISEQ_BODY(iseq)->param.flags.forwardable) {
+ // Add the anonymous *
+ body->param.rest_start = local_index;
+ body->param.flags.has_rest = true;
+ body->param.flags.anon_rest = true;
+ pm_insert_local_special(idMULT, local_index++, index_lookup_table, local_table_for_iseq);
+
+ // Add the anonymous **
+ RUBY_ASSERT(!body->param.flags.has_kw);
+ body->param.flags.has_kw = false;
+ body->param.flags.has_kwrest = true;
+ body->param.flags.anon_kwrest = true;
+ body->param.keyword = keyword = ZALLOC_N(struct rb_iseq_param_keyword, 1);
+ keyword->rest_start = local_index;
+ pm_insert_local_special(idPow, local_index++, index_lookup_table, local_table_for_iseq);
+
+ // Add the anonymous &
+ body->param.block_start = local_index;
+ body->param.flags.has_block = true;
+ pm_insert_local_special(idAnd, local_index++, index_lookup_table, local_table_for_iseq);
+ }
+
+ // Add the ...
+ pm_insert_local_special(idDot3, local_index++, index_lookup_table, local_table_for_iseq);
+ break;
+ }
+ default:
+ rb_bug("node type %s not expected as keyword_rest", pm_node_type_to_str(PM_NODE_TYPE(parameters_node->keyword_rest)));
}
+ }
+
+ // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
+ // ^^
+ if (parameters_node->block) {
+ body->param.block_start = local_index;
+ body->param.flags.has_block = true;
+ iseq_set_use_block(iseq);
+
+ pm_constant_id_t name = ((const pm_block_parameter_node_t *) parameters_node->block)->name;
- if (new_array_size) {
- if (has_kw_splat) {
- PUSH_INSN1(ret, location, newarraykwsplat, INT2FIX(new_array_size));
+ if (name) {
+ if (PM_NODE_FLAG_P(parameters_node->block, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
+ ID local = pm_constant_id_lookup(scope_node, name);
+ local_table_for_iseq->ids[local_index] = local;
}
else {
- PUSH_INSN1(ret, location, newarray, INT2FIX(new_array_size));
+ pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node);
}
+ }
+ else {
+ pm_insert_local_special(idAnd, local_index, index_lookup_table, local_table_for_iseq);
+ }
+
+ local_index++;
+ }
+ }
- if (need_to_concat_array) PUSH_INSN(ret, location, concatarray);
+ //********END OF STEP 2**********
+ // The local table is now consistent with expected
+ // stack layout
+
+ // If there's only one required element in the parameters
+ // CRuby needs to recognize it as an ambiguous parameter
+
+ //********STEP 3**********
+ // Goal: fill in the names of the parameters in MultiTargetNodes
+ //
+ // Go through requireds again to set the multis
+
+ if (requireds_list && requireds_list->size) {
+ for (size_t i = 0; i < requireds_list->size; i++) {
+ // For each MultiTargetNode, we're going to have one
+ // additional anonymous local not represented in the locals table
+ // We want to account for this in our table size
+ const pm_node_t *required = requireds_list->nodes[i];
+
+ if (PM_NODE_TYPE_P(required, PM_MULTI_TARGET_NODE)) {
+ local_index = pm_compile_destructured_param_locals((const pm_multi_target_node_t *) required, index_lookup_table, local_table_for_iseq, scope_node, local_index);
}
+ }
+ }
- if (popped) PUSH_INSN(ret, location, pop);
+ // Go through posts again to set the multis
+ if (posts_list && posts_list->size) {
+ for (size_t i = 0; i < posts_list->size; i++) {
+ // For each MultiTargetNode, we're going to have one
+ // additional anonymous local not represented in the locals table
+ // We want to account for this in our table size
+ const pm_node_t *post = posts_list->nodes[i];
+
+ if (PM_NODE_TYPE_P(post, PM_MULTI_TARGET_NODE)) {
+ local_index = pm_compile_destructured_param_locals((const pm_multi_target_node_t *) post, index_lookup_table, local_table_for_iseq, scope_node, local_index);
+ }
}
- return;
- }
- case PM_ASSOC_NODE: {
- // { foo: 1 }
- // ^^^^^^
- //
- // foo(bar: 1)
- // ^^^^^^
- const pm_assoc_node_t *cast = (const pm_assoc_node_t *) node;
+ }
- PM_COMPILE(cast->key);
- PM_COMPILE(cast->value);
+ // Set any anonymous locals for the for node
+ if (PM_NODE_TYPE_P(scope_node->ast_node, PM_FOR_NODE)) {
+ if (PM_NODE_TYPE_P(((const pm_for_node_t *) scope_node->ast_node)->index, PM_LOCAL_VARIABLE_TARGET_NODE)) {
+ body->param.lead_num++;
+ }
+ else {
+ body->param.rest_start = local_index;
+ body->param.flags.has_rest = true;
+ }
- return;
+ ID local = rb_make_temporary_id(local_index);
+ local_table_for_iseq->ids[local_index] = local;
+ local_index++;
+ }
+
+ // Fill in any NumberedParameters, if they exist
+ if (scope_node->parameters && PM_NODE_TYPE_P(scope_node->parameters, PM_NUMBERED_PARAMETERS_NODE)) {
+ int maximum = ((const pm_numbered_parameters_node_t *) scope_node->parameters)->maximum;
+ RUBY_ASSERT(0 < maximum && maximum <= 9);
+ for (int i = 0; i < maximum; i++, local_index++) {
+ const uint8_t param_name[] = { '_', '1' + i };
+ pm_constant_id_t constant_id = pm_constant_pool_find(&scope_node->parser->constant_pool, param_name, 2);
+ RUBY_ASSERT(constant_id && "parser should fill in any gaps in numbered parameters");
+ pm_insert_local_index(constant_id, local_index, index_lookup_table, local_table_for_iseq, scope_node);
+ }
+ body->param.lead_num = maximum;
+ body->param.flags.has_lead = true;
+ }
+
+ // Fill in the anonymous `it` parameter, if it exists
+ if (scope_node->parameters && PM_NODE_TYPE_P(scope_node->parameters, PM_IT_PARAMETERS_NODE)) {
+ body->param.lead_num = 1;
+ body->param.flags.has_lead = true;
+ }
+
+ //********END OF STEP 3**********
+
+ //********STEP 4**********
+ // Goal: fill in the method body locals
+ // To be explicit, these are the non-parameter locals
+ // We fill in the block_locals, if they exist
+ // lambda { |x; y| y }
+ // ^
+ if (block_locals && block_locals->size) {
+ for (size_t i = 0; i < block_locals->size; i++, local_index++) {
+ pm_constant_id_t constant_id = ((const pm_block_local_variable_node_t *) block_locals->nodes[i])->name;
+ pm_insert_local_index(constant_id, local_index, index_lookup_table, local_table_for_iseq, scope_node);
+ }
+ }
+
+ // Fill in any locals we missed
+ if (scope_node->locals.size) {
+ for (size_t i = 0; i < scope_node->locals.size; i++) {
+ pm_constant_id_t constant_id = locals->ids[i];
+ if (constant_id) {
+ struct pm_local_table_insert_ctx ctx;
+ ctx.scope_node = scope_node;
+ ctx.local_table_for_iseq = local_table_for_iseq;
+ ctx.local_index = local_index;
+
+ st_update(index_lookup_table, (st_data_t)constant_id, pm_local_table_insert_func, (st_data_t)&ctx);
+
+ local_index = ctx.local_index;
+ }
+ }
+ }
+
+ //********END OF STEP 4**********
+
+ // We set the index_lookup_table on the scope node so we can
+ // refer to the parameters correctly
+ if (scope_node->index_lookup_table) {
+ st_free_table(scope_node->index_lookup_table);
+ }
+ scope_node->index_lookup_table = index_lookup_table;
+ iseq_calc_param_size(iseq);
+
+ if (ISEQ_BODY(iseq)->param.flags.forwardable) {
+ // We're treating `...` as a parameter so that frame
+ // pushing won't clobber it.
+ ISEQ_BODY(iseq)->param.size += 1;
+ }
+
+ // FIXME: args?
+ iseq_set_local_table(iseq, local_table_for_iseq, 0);
+ iseq_set_parameters_lvar_state(iseq);
+
+ scope_node->local_table_for_iseq_size = local_table_for_iseq->size;
+
+ if (keyword != NULL) {
+ size_t keyword_start_index = keyword->bits_start - keyword->num;
+ keyword->table = (ID *)&ISEQ_BODY(iseq)->local_table[keyword_start_index];
+ }
+
+ //********STEP 5************
+ // Goal: compile anything that needed to be compiled
+ if (optionals_list && optionals_list->size) {
+ LABEL **opt_table = (LABEL **) ALLOC_N(VALUE, optionals_list->size + 1);
+ LABEL *label;
+
+ // TODO: Should we make an api for NEW_LABEL where you can pass
+ // a pointer to the label it should fill out? We already
+ // have a list of labels allocated above so it seems wasteful
+ // to do the copies.
+ for (size_t i = 0; i < optionals_list->size; i++) {
+ label = NEW_LABEL(location.line);
+ opt_table[i] = label;
+ PUSH_LABEL(ret, label);
+ pm_node_t *optional_node = optionals_list->nodes[i];
+ PM_COMPILE_NOT_POPPED(optional_node);
+ }
+
+ // Set the last label
+ label = NEW_LABEL(location.line);
+ opt_table[optionals_list->size] = label;
+ PUSH_LABEL(ret, label);
+
+ body->param.opt_table = (const VALUE *) opt_table;
+ }
+
+ if (keywords_list && keywords_list->size) {
+ size_t optional_index = 0;
+ for (size_t i = 0; i < keywords_list->size; i++) {
+ pm_node_t *keyword_parameter_node = keywords_list->nodes[i];
+ pm_constant_id_t name;
+
+ switch (PM_NODE_TYPE(keyword_parameter_node)) {
+ case PM_OPTIONAL_KEYWORD_PARAMETER_NODE: {
+ // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
+ // ^^^^
+ const pm_optional_keyword_parameter_node_t *cast = ((const pm_optional_keyword_parameter_node_t *) keyword_parameter_node);
+
+ pm_node_t *value = cast->value;
+ name = cast->name;
+
+ if (!PM_NODE_FLAG_P(value, PM_NODE_FLAG_STATIC_LITERAL) || PM_CONTAINER_P(value)) {
+ LABEL *end_label = NEW_LABEL(location.line);
+
+ pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, name, 0);
+ int kw_bits_idx = table_size - body->param.keyword->bits_start;
+ PUSH_INSN2(ret, location, checkkeyword, INT2FIX(kw_bits_idx + VM_ENV_DATA_SIZE - 1), INT2FIX(optional_index));
+ PUSH_INSNL(ret, location, branchif, end_label);
+ PM_COMPILE(value);
+ PUSH_SETLOCAL(ret, location, index.index, index.level);
+ PUSH_LABEL(ret, end_label);
+ }
+ optional_index++;
+ break;
+ }
+ case PM_REQUIRED_KEYWORD_PARAMETER_NODE:
+ // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
+ // ^^
+ break;
+ default:
+ rb_bug("Unexpected keyword parameter node type %s", pm_node_type_to_str(PM_NODE_TYPE(keyword_parameter_node)));
+ }
+ }
+ }
+
+ if (requireds_list && requireds_list->size) {
+ for (size_t i = 0; i < requireds_list->size; i++) {
+ // For each MultiTargetNode, we're going to have one additional
+ // anonymous local not represented in the locals table. We want
+ // to account for this in our table size.
+ const pm_node_t *required = requireds_list->nodes[i];
+
+ if (PM_NODE_TYPE_P(required, PM_MULTI_TARGET_NODE)) {
+ PUSH_GETLOCAL(ret, location, table_size - (int)i, 0);
+ pm_compile_destructured_param_writes(iseq, (const pm_multi_target_node_t *) required, ret, scope_node);
+ }
+ }
+ }
+
+ if (posts_list && posts_list->size) {
+ for (size_t i = 0; i < posts_list->size; i++) {
+ // For each MultiTargetNode, we're going to have one additional
+ // anonymous local not represented in the locals table. We want
+ // to account for this in our table size.
+ const pm_node_t *post = posts_list->nodes[i];
+
+ if (PM_NODE_TYPE_P(post, PM_MULTI_TARGET_NODE)) {
+ PUSH_GETLOCAL(ret, location, table_size - body->param.post_start - (int) i, 0);
+ pm_compile_destructured_param_writes(iseq, (const pm_multi_target_node_t *) post, ret, scope_node);
+ }
+ }
+ }
+
+ switch (body->type) {
+ case ISEQ_TYPE_PLAIN: {
+ RUBY_ASSERT(PM_NODE_TYPE_P(scope_node->ast_node, PM_INTERPOLATED_REGULAR_EXPRESSION_NODE));
+
+ const pm_interpolated_regular_expression_node_t *cast = (const pm_interpolated_regular_expression_node_t *) scope_node->ast_node;
+ pm_compile_regexp_dynamic(iseq, (const pm_node_t *) cast, &cast->parts, &location, ret, popped, scope_node);
+
+ break;
}
- case PM_ASSOC_SPLAT_NODE: {
- // { **foo }
- // ^^^^^
- //
- // def foo(**); bar(**); end
- // ^^
- const pm_assoc_splat_node_t *cast = (const pm_assoc_splat_node_t *) node;
+ case ISEQ_TYPE_BLOCK: {
+ LABEL *start = ISEQ_COMPILE_DATA(iseq)->start_label = NEW_LABEL(0);
+ LABEL *end = ISEQ_COMPILE_DATA(iseq)->end_label = NEW_LABEL(0);
+ const pm_node_location_t block_location = { .line = body->location.first_lineno, .node_id = scope_node->ast_node->node_id };
- if (cast->value != NULL) {
- PM_COMPILE(cast->value);
+ start->rescued = LABEL_RESCUE_BEG;
+ end->rescued = LABEL_RESCUE_END;
+
+ // For nodes automatically assign the iteration variable to whatever
+ // index variable. We need to handle that write here because it has
+ // to happen in the context of the block. Note that this happens
+ // before the B_CALL tracepoint event.
+ if (PM_NODE_TYPE_P(scope_node->ast_node, PM_FOR_NODE)) {
+ pm_compile_for_node_index(iseq, ((const pm_for_node_t *) scope_node->ast_node)->index, ret, scope_node);
}
- else if (!popped) {
- pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_POW, 0);
- PUSH_GETLOCAL(ret, location, index.index, index.level);
+
+ PUSH_TRACE(ret, RUBY_EVENT_B_CALL);
+ PUSH_INSN(ret, block_location, nop);
+ PUSH_LABEL(ret, start);
+
+ if (scope_node->body != NULL) {
+ switch (PM_NODE_TYPE(scope_node->ast_node)) {
+ case PM_POST_EXECUTION_NODE: {
+ const pm_post_execution_node_t *cast = (const pm_post_execution_node_t *) scope_node->ast_node;
+ PUSH_INSN1(ret, block_location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
+
+ // We create another ScopeNode from the statements within the PostExecutionNode
+ pm_scope_node_t next_scope_node;
+ pm_scope_node_init((const pm_node_t *) cast->statements, &next_scope_node, scope_node);
+
+ const rb_iseq_t *block = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(body->parent_iseq), ISEQ_TYPE_BLOCK, location.line);
+ pm_scope_node_destroy(&next_scope_node);
+
+ PUSH_CALL_WITH_BLOCK(ret, block_location, id_core_set_postexe, INT2FIX(0), block);
+ break;
+ }
+ case PM_INTERPOLATED_REGULAR_EXPRESSION_NODE: {
+ const pm_interpolated_regular_expression_node_t *cast = (const pm_interpolated_regular_expression_node_t *) scope_node->ast_node;
+ pm_compile_regexp_dynamic(iseq, (const pm_node_t *) cast, &cast->parts, &location, ret, popped, scope_node);
+ break;
+ }
+ default:
+ pm_compile_node(iseq, scope_node->body, ret, popped, scope_node);
+ break;
+ }
+ }
+ else {
+ PUSH_INSN(ret, block_location, putnil);
}
- return;
+ PUSH_LABEL(ret, end);
+ PUSH_TRACE(ret, RUBY_EVENT_B_RETURN);
+ ISEQ_COMPILE_DATA(iseq)->last_line = body->location.code_location.end_pos.lineno;
+
+ /* wide range catch handler must put at last */
+ PUSH_CATCH_ENTRY(CATCH_TYPE_REDO, start, end, NULL, start);
+ PUSH_CATCH_ENTRY(CATCH_TYPE_NEXT, start, end, NULL, end);
+ break;
}
- case PM_BACK_REFERENCE_READ_NODE: {
- // $+
- // ^^
- if (!popped) {
- // Since a back reference is `$<char>`, ruby represents the ID as the
- // an rb_intern on the value after the `$`.
- char *char_ptr = (char *)(node->location.start) + 1;
- ID backref_val = INT2FIX(rb_intern2(char_ptr, 1)) << 1 | 1;
- PUSH_INSN2(ret, location, getspecial, INT2FIX(1), backref_val);
+ case ISEQ_TYPE_ENSURE: {
+ const pm_node_location_t statements_location = (scope_node->body != NULL ? PM_NODE_START_LOCATION(scope_node->parser, scope_node->body) : location);
+ iseq_set_exception_local_table(iseq);
+
+ if (scope_node->body != NULL) {
+ PM_COMPILE_POPPED((const pm_node_t *) scope_node->body);
}
+
+ PUSH_GETLOCAL(ret, statements_location, 1, 0);
+ PUSH_INSN1(ret, statements_location, throw, INT2FIX(0));
return;
}
- case PM_BEGIN_NODE: {
- // begin end
- // ^^^^^^^^^
- const pm_begin_node_t *cast = (const pm_begin_node_t *) node;
+ case ISEQ_TYPE_METHOD: {
+ ISEQ_COMPILE_DATA(iseq)->root_node = (const void *) scope_node->body;
+ PUSH_TRACE(ret, RUBY_EVENT_CALL);
- if (cast->ensure_clause) {
- // Compiling the ensure clause will compile the rescue clause (if
- // there is one), which will compile the begin statements.
- pm_compile_ensure(iseq, cast, &location, ret, popped, scope_node);
+ if (scope_node->body) {
+ PM_COMPILE((const pm_node_t *) scope_node->body);
}
- else if (cast->rescue_clause) {
- // Compiling rescue will compile begin statements (if applicable).
- pm_compile_rescue(iseq, cast, &location, ret, popped, scope_node);
+ else {
+ PUSH_INSN(ret, location, putnil);
+ }
+
+ ISEQ_COMPILE_DATA(iseq)->root_node = (const void *) scope_node->body;
+ PUSH_TRACE(ret, RUBY_EVENT_RETURN);
+
+ ISEQ_COMPILE_DATA(iseq)->last_line = body->location.code_location.end_pos.lineno;
+ break;
+ }
+ case ISEQ_TYPE_RESCUE: {
+ iseq_set_exception_local_table(iseq);
+ if (PM_NODE_TYPE_P(scope_node->ast_node, PM_RESCUE_MODIFIER_NODE)) {
+ LABEL *lab = NEW_LABEL(location.line);
+ LABEL *rescue_end = NEW_LABEL(location.line);
+ PUSH_GETLOCAL(ret, location, LVAR_ERRINFO, 0);
+ PUSH_INSN1(ret, location, putobject, rb_eStandardError);
+ PUSH_INSN1(ret, location, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
+ PUSH_INSNL(ret, location, branchif, lab);
+ PUSH_INSNL(ret, location, jump, rescue_end);
+ PUSH_LABEL(ret, lab);
+ PUSH_TRACE(ret, RUBY_EVENT_RESCUE);
+ PM_COMPILE((const pm_node_t *) scope_node->body);
+ PUSH_INSN(ret, location, leave);
+ PUSH_LABEL(ret, rescue_end);
+ PUSH_GETLOCAL(ret, location, LVAR_ERRINFO, 0);
}
else {
- // If there is neither ensure or rescue, the just compile the
- // statements.
- if (cast->statements != NULL) {
- PM_COMPILE((const pm_node_t *) cast->statements);
- }
- else if (!popped) {
- PUSH_SYNTHETIC_PUTNIL(ret, iseq);
- }
+ PM_COMPILE((const pm_node_t *) scope_node->ast_node);
}
+ PUSH_INSN1(ret, location, throw, INT2FIX(0));
+
return;
}
- case PM_BLOCK_ARGUMENT_NODE: {
- // foo(&bar)
- // ^^^^
- const pm_block_argument_node_t *cast = (const pm_block_argument_node_t *) node;
-
- if (cast->expression != NULL) {
- PM_COMPILE(cast->expression);
+ default:
+ if (scope_node->body) {
+ PM_COMPILE((const pm_node_t *) scope_node->body);
}
else {
- // If there's no expression, this must be block forwarding.
- pm_local_index_t local_index = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_AND, 0);
- PUSH_INSN2(ret, location, getblockparamproxy, INT2FIX(local_index.index + VM_ENV_DATA_SIZE - 1), INT2FIX(local_index.level));
+ PUSH_INSN(ret, location, putnil);
+ }
+ break;
+ }
+
+ if (PM_NODE_TYPE_P(scope_node->ast_node, PM_CLASS_NODE) || PM_NODE_TYPE_P(scope_node->ast_node, PM_MODULE_NODE)) {
+ const pm_node_location_t end_location = PM_NODE_END_LOCATION(scope_node->parser, scope_node->ast_node);
+ PUSH_TRACE(ret, RUBY_EVENT_END);
+ ISEQ_COMPILE_DATA(iseq)->last_line = end_location.line;
+ }
+
+ if (!PM_NODE_TYPE_P(scope_node->ast_node, PM_ENSURE_NODE)) {
+ const pm_node_location_t location = { .line = ISEQ_COMPILE_DATA(iseq)->last_line, .node_id = scope_node->ast_node->node_id };
+ PUSH_INSN(ret, location, leave);
+ }
+}
+
+static inline void
+pm_compile_alias_global_variable_node(rb_iseq_t *iseq, const pm_alias_global_variable_node_t *node, const pm_node_location_t *location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+{
+ // alias $foo $bar
+ // ^^^^^^^^^^^^^^^
+ PUSH_INSN1(ret, *location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
+
+ {
+ const pm_location_t *name_loc = &node->new_name->location;
+ VALUE operand = ID2SYM(rb_intern3((const char *) name_loc->start, name_loc->end - name_loc->start, scope_node->encoding));
+ PUSH_INSN1(ret, *location, putobject, operand);
+ }
+
+ {
+ const pm_location_t *name_loc = &node->old_name->location;
+ VALUE operand = ID2SYM(rb_intern3((const char *) name_loc->start, name_loc->end - name_loc->start, scope_node->encoding));
+ PUSH_INSN1(ret, *location, putobject, operand);
+ }
+
+ PUSH_SEND(ret, *location, id_core_set_variable_alias, INT2FIX(2));
+ if (popped) PUSH_INSN(ret, *location, pop);
+}
+
+static inline void
+pm_compile_alias_method_node(rb_iseq_t *iseq, const pm_alias_method_node_t *node, const pm_node_location_t *location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+{
+ PUSH_INSN1(ret, *location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
+ PUSH_INSN1(ret, *location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE));
+ PM_COMPILE_NOT_POPPED(node->new_name);
+ PM_COMPILE_NOT_POPPED(node->old_name);
+
+ PUSH_SEND(ret, *location, id_core_set_method_alias, INT2FIX(3));
+ if (popped) PUSH_INSN(ret, *location, pop);
+}
+
+static inline void
+pm_compile_and_node(rb_iseq_t *iseq, const pm_and_node_t *node, const pm_node_location_t *location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+{
+ LABEL *end_label = NEW_LABEL(location->line);
+
+ PM_COMPILE_NOT_POPPED(node->left);
+ if (!popped) PUSH_INSN(ret, *location, dup);
+ PUSH_INSNL(ret, *location, branchunless, end_label);
+
+ if (!popped) PUSH_INSN(ret, *location, pop);
+ PM_COMPILE(node->right);
+ PUSH_LABEL(ret, end_label);
+}
+
+static inline void
+pm_compile_array_node(rb_iseq_t *iseq, const pm_node_t *node, const pm_node_list_t *elements, const pm_node_location_t *location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+{
+ // If every node in the array is static, then we can compile the entire
+ // array now instead of later.
+ if (PM_NODE_FLAG_P(node, PM_NODE_FLAG_STATIC_LITERAL)) {
+ // We're only going to compile this node if it's not popped. If it
+ // is popped, then we know we don't need to do anything since it's
+ // statically known.
+ if (!popped) {
+ if (elements->size) {
+ VALUE value = pm_static_literal_value(iseq, node, scope_node);
+ RB_OBJ_SET_FROZEN_SHAREABLE(value);
+ PUSH_INSN1(ret, *location, duparray, value);
+ }
+ else {
+ PUSH_INSN1(ret, *location, newarray, INT2FIX(0));
+ }
}
return;
- }
- case PM_BREAK_NODE: {
- // break
- // ^^^^^
- //
- // break foo
- // ^^^^^^^^^
- const pm_break_node_t *cast = (const pm_break_node_t *) node;
- unsigned long throw_flag = 0;
+ }
+
+ // Here since we know there are possible side-effects inside the
+ // array contents, we're going to build it entirely at runtime.
+ // We'll do this by pushing all of the elements onto the stack and
+ // then combining them with newarray.
+ //
+ // If this array is popped, then this serves only to ensure we enact
+ // all side-effects (like method calls) that are contained within
+ // the array contents.
+ //
+ // We treat all sequences of non-splat elements as their
+ // own arrays, followed by a newarray, and then continually
+ // concat the arrays with the SplatNode nodes.
+ const int max_new_array_size = 0x100;
+ const unsigned int min_tmp_array_size = 0x40;
- if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0 && can_add_ensure_iseq(iseq)) {
- /* while/until */
- LABEL *splabel = NEW_LABEL(0);
- PUSH_LABEL(ret, splabel);
- PUSH_ADJUST(ret, location, ISEQ_COMPILE_DATA(iseq)->redo_label);
+ int new_array_size = 0;
+ bool first_chunk = true;
+
+ // This is an optimization wherein we keep track of whether or not
+ // the previous element was a static literal. If it was, then we do
+ // not attempt to check if we have a subarray that can be optimized.
+ // If it was not, then we do check.
+ bool static_literal = false;
+
+ // Either create a new array, or push to the existing array.
+#define FLUSH_CHUNK \
+ if (new_array_size) { \
+ if (first_chunk) PUSH_INSN1(ret, *location, newarray, INT2FIX(new_array_size)); \
+ else PUSH_INSN1(ret, *location, pushtoarray, INT2FIX(new_array_size)); \
+ first_chunk = false; \
+ new_array_size = 0; \
+ }
- if (cast->arguments != NULL) {
- PM_COMPILE_NOT_POPPED((const pm_node_t *) cast->arguments);
+ for (size_t index = 0; index < elements->size; index++) {
+ const pm_node_t *element = elements->nodes[index];
+
+ if (PM_NODE_TYPE_P(element, PM_SPLAT_NODE)) {
+ FLUSH_CHUNK;
+
+ const pm_splat_node_t *splat_element = (const pm_splat_node_t *) element;
+ if (splat_element->expression) {
+ PM_COMPILE_NOT_POPPED(splat_element->expression);
}
else {
- PUSH_INSN(ret, location, putnil);
+ pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_MULT, 0);
+ PUSH_GETLOCAL(ret, *location, index.index, index.level);
}
- pm_add_ensure_iseq(ret, iseq, 0, scope_node);
- PUSH_INSNL(ret, location, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
- PUSH_ADJUST_RESTORE(ret, splabel);
- if (!popped) PUSH_INSN(ret, location, putnil);
+ if (first_chunk) {
+ // If this is the first element of the array then we
+ // need to splatarray the elements into the list.
+ PUSH_INSN1(ret, *location, splatarray, Qtrue);
+ first_chunk = false;
+ }
+ else {
+ PUSH_INSN(ret, *location, concattoarray);
+ }
+
+ static_literal = false;
}
- else {
- const rb_iseq_t *ip = iseq;
+ else if (PM_NODE_TYPE_P(element, PM_KEYWORD_HASH_NODE)) {
+ if (new_array_size == 0 && first_chunk) {
+ PUSH_INSN1(ret, *location, newarray, INT2FIX(0));
+ first_chunk = false;
+ }
+ else {
+ FLUSH_CHUNK;
+ }
- while (ip) {
- if (!ISEQ_COMPILE_DATA(ip)) {
- ip = 0;
- break;
- }
+ // If we get here, then this is the last element of the
+ // array/arguments, because it cannot be followed by
+ // anything else without a syntax error. This looks like:
+ //
+ // [foo, bar, baz: qux]
+ // ^^^^^^^^
+ //
+ // [foo, bar, **baz]
+ // ^^^^^
+ //
+ const pm_keyword_hash_node_t *keyword_hash = (const pm_keyword_hash_node_t *) element;
+ pm_compile_hash_elements(iseq, element, &keyword_hash->elements, 0, Qundef, false, ret, scope_node);
- if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
- throw_flag = VM_THROW_NO_ESCAPE_FLAG;
- }
- else if (ISEQ_BODY(ip)->type == ISEQ_TYPE_BLOCK) {
- throw_flag = 0;
- }
- else if (ISEQ_BODY(ip)->type == ISEQ_TYPE_EVAL) {
- COMPILE_ERROR(iseq, location.line, "Can't escape from eval with break");
- return;
- }
- else {
- ip = ISEQ_BODY(ip)->parent_iseq;
- continue;
- }
+ // This boolean controls the manner in which we push the
+ // hash onto the array. If it's all keyword splats, then we
+ // can use the very specialized pushtoarraykwsplat
+ // instruction to check if it's empty before we push it.
+ size_t splats = 0;
+ while (splats < keyword_hash->elements.size && PM_NODE_TYPE_P(keyword_hash->elements.nodes[splats], PM_ASSOC_SPLAT_NODE)) splats++;
- /* escape from block */
- if (cast->arguments != NULL) {
- PM_COMPILE_NOT_POPPED((const pm_node_t *) cast->arguments);
+ if (keyword_hash->elements.size == splats) {
+ PUSH_INSN(ret, *location, pushtoarraykwsplat);
+ }
+ else {
+ new_array_size++;
+ }
+ }
+ else if (
+ PM_NODE_FLAG_P(element, PM_NODE_FLAG_STATIC_LITERAL) &&
+ !PM_CONTAINER_P(element) &&
+ !static_literal &&
+ ((index + min_tmp_array_size) < elements->size)
+ ) {
+ // If we have a static literal, then there's the potential
+ // to group a bunch of them together with a literal array
+ // and then concat them together.
+ size_t right_index = index + 1;
+ while (
+ right_index < elements->size &&
+ PM_NODE_FLAG_P(elements->nodes[right_index], PM_NODE_FLAG_STATIC_LITERAL) &&
+ !PM_CONTAINER_P(elements->nodes[right_index])
+ ) right_index++;
+
+ size_t tmp_array_size = right_index - index;
+ if (tmp_array_size >= min_tmp_array_size) {
+ VALUE tmp_array = rb_ary_hidden_new(tmp_array_size);
+
+ // Create the temporary array.
+ for (; tmp_array_size; tmp_array_size--)
+ rb_ary_push(tmp_array, pm_static_literal_value(iseq, elements->nodes[index++], scope_node));
+
+ index--; // about to be incremented by for loop
+ RB_OBJ_SET_FROZEN_SHAREABLE(tmp_array);
+
+ // Emit the optimized code.
+ FLUSH_CHUNK;
+ if (first_chunk) {
+ PUSH_INSN1(ret, *location, duparray, tmp_array);
+ first_chunk = false;
}
else {
- PUSH_INSN(ret, location, putnil);
+ PUSH_INSN1(ret, *location, putobject, tmp_array);
+ PUSH_INSN(ret, *location, concattoarray);
}
-
- PUSH_INSN1(ret, location, throw, INT2FIX(throw_flag | TAG_BREAK));
- if (popped) PUSH_INSN(ret, location, pop);
-
- return;
}
-
- COMPILE_ERROR(iseq, location.line, "Invalid break");
+ else {
+ PM_COMPILE_NOT_POPPED(element);
+ if (++new_array_size >= max_new_array_size) FLUSH_CHUNK;
+ static_literal = true;
+ }
+ } else {
+ PM_COMPILE_NOT_POPPED(element);
+ if (++new_array_size >= max_new_array_size) FLUSH_CHUNK;
+ static_literal = false;
}
- return;
- }
- case PM_CALL_NODE: {
- // foo
- // ^^^
- //
- // foo.bar
- // ^^^^^^^
- //
- // foo.bar() {}
- // ^^^^^^^^^^^^
- const pm_call_node_t *cast = (const pm_call_node_t *) node;
- ID method_id = pm_constant_id_lookup(scope_node, cast->name);
+ }
- const pm_location_t *message_loc = &cast->message_loc;
- if (message_loc->start == NULL) message_loc = &cast->base.location;
+ FLUSH_CHUNK;
+ if (popped) PUSH_INSN(ret, *location, pop);
- const pm_line_column_t location = PM_LOCATION_START_LINE_COLUMN(scope_node->parser, message_loc);
- const char *builtin_func;
+#undef FLUSH_CHUNK
+}
- if (UNLIKELY(iseq_has_builtin_function_table(iseq)) && (builtin_func = pm_iseq_builtin_function_name(scope_node, cast->receiver, method_id)) != NULL) {
- const pm_string_t *filepath = &scope_node->parser->filepath;
- fprintf(stderr, "COMPILING %.*s:%d:%d builtin_func:%s\n", (int) pm_string_length(filepath), pm_string_source(filepath), location.line, location.column, builtin_func);
+static inline void
+pm_compile_break_node(rb_iseq_t *iseq, const pm_break_node_t *node, const pm_node_location_t *location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+{
+ unsigned long throw_flag = 0;
- pm_compile_builtin_function_call(iseq, ret, scope_node, cast, &location, popped, ISEQ_COMPILE_DATA(iseq)->current_block, builtin_func);
- return;
+ if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0 && can_add_ensure_iseq(iseq)) {
+ /* while/until */
+ LABEL *splabel = NEW_LABEL(0);
+ PUSH_LABEL(ret, splabel);
+ PUSH_ADJUST(ret, *location, ISEQ_COMPILE_DATA(iseq)->redo_label);
+
+ if (node->arguments != NULL) {
+ PM_COMPILE_NOT_POPPED((const pm_node_t *) node->arguments);
+ }
+ else {
+ PUSH_INSN(ret, *location, putnil);
}
- LABEL *start = NEW_LABEL(location.line);
- if (cast->block) PUSH_LABEL(ret, start);
+ pm_add_ensure_iseq(ret, iseq, 0, scope_node);
+ PUSH_INSNL(ret, *location, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
+ PUSH_ADJUST_RESTORE(ret, splabel);
+ if (!popped) PUSH_INSN(ret, *location, putnil);
+ }
+ else {
+ const rb_iseq_t *ip = iseq;
- switch (method_id) {
- case idUMinus: {
- if (pm_opt_str_freeze_p(iseq, cast)) {
- VALUE value = parse_static_literal_string(iseq, scope_node, cast->receiver, &((const pm_string_node_t * ) cast->receiver)->unescaped);
- PUSH_INSN2(ret, location, opt_str_uminus, value, new_callinfo(iseq, idUMinus, 0, 0, NULL, FALSE));
- return;
+ while (ip) {
+ if (!ISEQ_COMPILE_DATA(ip)) {
+ ip = 0;
+ break;
}
- break;
- }
- case idFreeze: {
- if (pm_opt_str_freeze_p(iseq, cast)) {
- VALUE value = parse_static_literal_string(iseq, scope_node, cast->receiver, &((const pm_string_node_t * ) cast->receiver)->unescaped);
- PUSH_INSN2(ret, location, opt_str_freeze, value, new_callinfo(iseq, idFreeze, 0, 0, NULL, FALSE));
+
+ if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
+ throw_flag = VM_THROW_NO_ESCAPE_FLAG;
+ }
+ else if (ISEQ_BODY(ip)->type == ISEQ_TYPE_BLOCK) {
+ throw_flag = 0;
+ }
+ else if (ISEQ_BODY(ip)->type == ISEQ_TYPE_EVAL) {
+ COMPILE_ERROR(iseq, location->line, "Invalid break");
return;
}
- break;
- }
- case idAREF: {
- if (pm_opt_aref_with_p(iseq, cast)) {
- const pm_string_node_t *string = (const pm_string_node_t *) ((const pm_arguments_node_t *) cast->arguments)->arguments.nodes[0];
- VALUE value = parse_static_literal_string(iseq, scope_node, (const pm_node_t *) string, &string->unescaped);
+ else {
+ ip = ISEQ_BODY(ip)->parent_iseq;
+ continue;
+ }
- PM_COMPILE_NOT_POPPED(cast->receiver);
- PUSH_INSN2(ret, location, opt_aref_with, value, new_callinfo(iseq, idAREF, 1, 0, NULL, FALSE));
+ /* escape from block */
+ if (node->arguments != NULL) {
+ PM_COMPILE_NOT_POPPED((const pm_node_t *) node->arguments);
+ }
+ else {
+ PUSH_INSN(ret, *location, putnil);
+ }
- if (popped) {
- PUSH_INSN(ret, location, pop);
- }
+ PUSH_INSN1(ret, *location, throw, INT2FIX(throw_flag | TAG_BREAK));
+ if (popped) PUSH_INSN(ret, *location, pop);
- return;
- }
- break;
- }
- case idASET: {
- if (pm_opt_aset_with_p(iseq, cast)) {
- const pm_string_node_t *string = (const pm_string_node_t *) ((const pm_arguments_node_t *) cast->arguments)->arguments.nodes[0];
- VALUE value = parse_static_literal_string(iseq, scope_node, (const pm_node_t *) string, &string->unescaped);
+ return;
+ }
- PM_COMPILE_NOT_POPPED(cast->receiver);
- PM_COMPILE_NOT_POPPED(((const pm_arguments_node_t *) cast->arguments)->arguments.nodes[1]);
+ COMPILE_ERROR(iseq, location->line, "Invalid break");
+ }
+}
- if (!popped) {
- PUSH_INSN(ret, location, swap);
- PUSH_INSN1(ret, location, topn, INT2FIX(1));
- }
+static inline void
+pm_compile_call_node(rb_iseq_t *iseq, const pm_call_node_t *node, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+{
+ ID method_id = pm_constant_id_lookup(scope_node, node->name);
- PUSH_INSN2(ret, location, opt_aset_with, value, new_callinfo(iseq, idASET, 2, 0, NULL, FALSE));
- PUSH_INSN(ret, location, pop);
- return;
- }
- break;
- }
- }
+ const pm_location_t *message_loc = &node->message_loc;
+ if (message_loc->start == NULL) message_loc = &node->base.location;
- if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE) && !popped) {
- PUSH_INSN(ret, location, putnil);
+ const pm_node_location_t location = PM_LOCATION_START_LOCATION(scope_node->parser, message_loc, node->base.node_id);
+ const char *builtin_func;
+
+ if (UNLIKELY(iseq_has_builtin_function_table(iseq)) && (builtin_func = pm_iseq_builtin_function_name(scope_node, node->receiver, method_id)) != NULL) {
+ pm_compile_builtin_function_call(iseq, ret, scope_node, node, &location, popped, ISEQ_COMPILE_DATA(iseq)->current_block, builtin_func);
+ return;
+ }
+
+ LABEL *start = NEW_LABEL(location.line);
+ if (node->block) PUSH_LABEL(ret, start);
+
+ switch (method_id) {
+ case idUMinus: {
+ if (pm_opt_str_freeze_p(iseq, node)) {
+ VALUE value = parse_static_literal_string(iseq, scope_node, node->receiver, &((const pm_string_node_t * ) node->receiver)->unescaped);
+ const struct rb_callinfo *callinfo = new_callinfo(iseq, idUMinus, 0, 0, NULL, FALSE);
+ PUSH_INSN2(ret, location, opt_str_uminus, value, callinfo);
+ if (popped) PUSH_INSN(ret, location, pop);
+ return;
}
+ break;
+ }
+ case idFreeze: {
+ if (pm_opt_str_freeze_p(iseq, node)) {
+ VALUE value = parse_static_literal_string(iseq, scope_node, node->receiver, &((const pm_string_node_t * ) node->receiver)->unescaped);
+ const struct rb_callinfo *callinfo = new_callinfo(iseq, idFreeze, 0, 0, NULL, FALSE);
+ PUSH_INSN2(ret, location, opt_str_freeze, value, callinfo);
+ if (popped) PUSH_INSN(ret, location, pop);
+ return;
+ }
+ break;
+ }
+ }
- if (cast->receiver == NULL) {
- PUSH_INSN(ret, location, putself);
+ if (PM_NODE_FLAG_P(node, PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE) && !popped) {
+ PUSH_INSN(ret, location, putnil);
+ }
+
+ if (node->receiver == NULL) {
+ PUSH_INSN(ret, location, putself);
+ }
+ else {
+ if (method_id == idCall && PM_NODE_TYPE_P(node->receiver, PM_LOCAL_VARIABLE_READ_NODE)) {
+ const pm_local_variable_read_node_t *read_node_cast = (const pm_local_variable_read_node_t *) node->receiver;
+ uint32_t node_id = node->receiver->node_id;
+ int idx, level;
+
+ if (iseq_block_param_id_p(iseq, pm_constant_id_lookup(scope_node, read_node_cast->name), &idx, &level)) {
+ ADD_ELEM(ret, (LINK_ELEMENT *) new_insn_body(iseq, location.line, node_id, BIN(getblockparamproxy), 2, INT2FIX((idx) + VM_ENV_DATA_SIZE - 1), INT2FIX(level)));
+ }
+ else {
+ PM_COMPILE_NOT_POPPED(node->receiver);
+ }
}
else {
- PM_COMPILE_NOT_POPPED(cast->receiver);
+ PM_COMPILE_NOT_POPPED(node->receiver);
}
+ }
- pm_compile_call(iseq, cast, ret, popped, scope_node, method_id, start);
- return;
- }
- case PM_CALL_AND_WRITE_NODE: {
- // foo.bar &&= baz
- // ^^^^^^^^^^^^^^^
- const pm_call_and_write_node_t *cast = (const pm_call_and_write_node_t *) node;
- pm_compile_call_and_or_write_node(iseq, true, cast->receiver, cast->value, cast->write_name, cast->read_name, PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION), &location, ret, popped, scope_node);
- return;
- }
- case PM_CALL_OR_WRITE_NODE: {
- // foo.bar ||= baz
- // ^^^^^^^^^^^^^^^
- const pm_call_or_write_node_t *cast = (const pm_call_or_write_node_t *) node;
- pm_compile_call_and_or_write_node(iseq, false, cast->receiver, cast->value, cast->write_name, cast->read_name, PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION), &location, ret, popped, scope_node);
- return;
- }
- case PM_CALL_OPERATOR_WRITE_NODE: {
- // foo.bar += baz
- // ^^^^^^^^^^^^^^^
- //
- // Call operator writes occur when you have a call node on the left-hand
- // side of a write operator that is not `=`. As an example,
- // `foo.bar *= 1`. This breaks down to caching the receiver on the
- // stack and then performing three method calls, one to read the value,
- // one to compute the result, and one to write the result back to the
- // receiver.
- const pm_call_operator_write_node_t *cast = (const pm_call_operator_write_node_t *) node;
- int flag = 0;
+ pm_compile_call(iseq, node, ret, popped, scope_node, method_id, start);
+ return;
+}
- if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) {
- flag = VM_CALL_FCALL;
- }
+static inline void
+pm_compile_call_operator_write_node(rb_iseq_t *iseq, const pm_call_operator_write_node_t *node, const pm_node_location_t *location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+{
+ int flag = 0;
- PM_COMPILE_NOT_POPPED(cast->receiver);
+ if (PM_NODE_FLAG_P(node, PM_CALL_NODE_FLAGS_IGNORE_VISIBILITY)) {
+ flag = VM_CALL_FCALL;
+ }
- LABEL *safe_label = NULL;
- if (PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) {
- safe_label = NEW_LABEL(location.line);
- PUSH_INSN(ret, location, dup);
- PUSH_INSNL(ret, location, branchnil, safe_label);
- }
+ PM_COMPILE_NOT_POPPED(node->receiver);
- PUSH_INSN(ret, location, dup);
+ LABEL *safe_label = NULL;
+ if (PM_NODE_FLAG_P(node, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION)) {
+ safe_label = NEW_LABEL(location->line);
+ PUSH_INSN(ret, *location, dup);
+ PUSH_INSNL(ret, *location, branchnil, safe_label);
+ }
- ID id_read_name = pm_constant_id_lookup(scope_node, cast->read_name);
- PUSH_SEND_WITH_FLAG(ret, location, id_read_name, INT2FIX(0), INT2FIX(flag));
+ PUSH_INSN(ret, *location, dup);
- PM_COMPILE_NOT_POPPED(cast->value);
- ID id_operator = pm_constant_id_lookup(scope_node, cast->binary_operator);
- PUSH_SEND(ret, location, id_operator, INT2FIX(1));
+ ID id_read_name = pm_constant_id_lookup(scope_node, node->read_name);
+ PUSH_SEND_WITH_FLAG(ret, *location, id_read_name, INT2FIX(0), INT2FIX(flag));
- if (!popped) {
- PUSH_INSN(ret, location, swap);
- PUSH_INSN1(ret, location, topn, INT2FIX(1));
- }
+ PM_COMPILE_NOT_POPPED(node->value);
+ ID id_operator = pm_constant_id_lookup(scope_node, node->binary_operator);
+ PUSH_SEND(ret, *location, id_operator, INT2FIX(1));
+
+ if (!popped) {
+ PUSH_INSN(ret, *location, swap);
+ PUSH_INSN1(ret, *location, topn, INT2FIX(1));
+ }
- ID id_write_name = pm_constant_id_lookup(scope_node, cast->write_name);
- PUSH_SEND_WITH_FLAG(ret, location, id_write_name, INT2FIX(1), INT2FIX(flag));
+ ID id_write_name = pm_constant_id_lookup(scope_node, node->write_name);
+ PUSH_SEND_WITH_FLAG(ret, *location, id_write_name, INT2FIX(1), INT2FIX(flag));
- if (safe_label != NULL && popped) PUSH_LABEL(ret, safe_label);
- PUSH_INSN(ret, location, pop);
- if (safe_label != NULL && !popped) PUSH_LABEL(ret, safe_label);
+ if (safe_label != NULL && popped) PUSH_LABEL(ret, safe_label);
+ PUSH_INSN(ret, *location, pop);
+ if (safe_label != NULL && !popped) PUSH_LABEL(ret, safe_label);
+}
- return;
+/**
+ * When we're compiling a case node, it's possible that we can speed it up using
+ * a dispatch hash, which will allow us to jump directly to the correct when
+ * clause body based on a hash lookup of the value. This can only happen when
+ * the conditions are literals that can be compiled into a hash key.
+ *
+ * This function accepts a dispatch hash and the condition of a when clause. It
+ * is responsible for compiling the condition into a hash key and then adding it
+ * to the dispatch hash.
+ *
+ * If the value can be successfully compiled into the hash, then this function
+ * returns the dispatch hash with the new key added. If the value cannot be
+ * compiled into the hash, then this function returns Qundef. In the case of
+ * Qundef, this function is signaling that the caller should abandon the
+ * optimization entirely.
+ */
+static VALUE
+pm_compile_case_node_dispatch(rb_iseq_t *iseq, VALUE dispatch, const pm_node_t *node, LABEL *label, const pm_scope_node_t *scope_node)
+{
+ VALUE key = Qundef;
+ switch (PM_NODE_TYPE(node)) {
+ case PM_FLOAT_NODE: {
+ key = pm_static_literal_value(iseq, node, scope_node);
+ double intptr;
+
+ if (modf(RFLOAT_VALUE(key), &intptr) == 0.0) {
+ key = (FIXABLE(intptr) ? LONG2FIX((long) intptr) : rb_dbl2big(intptr));
+ }
+
+ break;
}
- case PM_CASE_NODE: {
- // case foo; when bar; end
- // ^^^^^^^^^^^^^^^^^^^^^^^
- const pm_case_node_t *cast = (const pm_case_node_t *) node;
- const pm_node_list_t *conditions = &cast->conditions;
+ case PM_FALSE_NODE:
+ case PM_INTEGER_NODE:
+ case PM_NIL_NODE:
+ case PM_SOURCE_FILE_NODE:
+ case PM_SOURCE_LINE_NODE:
+ case PM_SYMBOL_NODE:
+ case PM_TRUE_NODE:
+ key = pm_static_literal_value(iseq, node, scope_node);
+ break;
+ case PM_STRING_NODE: {
+ const pm_string_node_t *cast = (const pm_string_node_t *) node;
+ key = parse_static_literal_string(iseq, scope_node, node, &cast->unescaped);
+ break;
+ }
+ default:
+ return Qundef;
+ }
- // This is the anchor that we will compile the conditions of the various
- // `when` nodes into. If a match is found, they will need to jump into
- // the body_seq anchor to the correct spot.
- DECL_ANCHOR(cond_seq);
- INIT_ANCHOR(cond_seq);
+ if (NIL_P(rb_hash_lookup(dispatch, key))) {
+ rb_hash_aset(dispatch, key, ((VALUE) label) | 1);
+ }
+ return dispatch;
+}
- // This is the anchor that we will compile the bodies of the various
- // `when` nodes into. We'll make sure that the clauses that are compiled
- // jump into the correct spots within this anchor.
- DECL_ANCHOR(body_seq);
- INIT_ANCHOR(body_seq);
+/**
+ * Compile a case node, representing a case statement with when clauses.
+ */
+static inline void
+pm_compile_case_node(rb_iseq_t *iseq, const pm_case_node_t *cast, const pm_node_location_t *node_location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+{
+ const pm_parser_t *parser = scope_node->parser;
+ const pm_node_location_t location = *node_location;
+ const pm_node_list_t *conditions = &cast->conditions;
- // This is the label where all of the when clauses will jump to if they
- // have matched and are done executing their bodies.
- LABEL *end_label = NEW_LABEL(location.line);
+ // This is the anchor that we will compile the conditions of the various
+ // `when` nodes into. If a match is found, they will need to jump into
+ // the body_seq anchor to the correct spot.
+ DECL_ANCHOR(cond_seq);
- // If we have a predicate on this case statement, then it's going to
- // compare all of the various when clauses to the predicate. If we
- // don't, then it's basically an if-elsif-else chain.
- if (cast->predicate == NULL) {
- // Establish branch coverage for the case node.
- VALUE branches = Qfalse;
- rb_code_location_t case_location = { 0 };
- int branch_id = 0;
+ // This is the anchor that we will compile the bodies of the various
+ // `when` nodes into. We'll make sure that the clauses that are compiled
+ // jump into the correct spots within this anchor.
+ DECL_ANCHOR(body_seq);
+ // This is the label where all of the when clauses will jump to if they
+ // have matched and are done executing their bodies.
+ LABEL *end_label = NEW_LABEL(location.line);
+
+ // If we have a predicate on this case statement, then it's going to
+ // compare all of the various when clauses to the predicate. If we
+ // don't, then it's basically an if-elsif-else chain.
+ if (cast->predicate == NULL) {
+ // Establish branch coverage for the case node.
+ VALUE branches = Qfalse;
+ rb_code_location_t case_location = { 0 };
+ int branch_id = 0;
+
+ if (PM_BRANCH_COVERAGE_P(iseq)) {
+ case_location = pm_code_location(scope_node, (const pm_node_t *) cast);
+ branches = decl_branch_base(iseq, PTR2NUM(cast), &case_location, "case");
+ }
+
+ // Loop through each clauses in the case node and compile each of
+ // the conditions within them into cond_seq. If they match, they
+ // should jump into their respective bodies in body_seq.
+ for (size_t clause_index = 0; clause_index < conditions->size; clause_index++) {
+ const pm_when_node_t *clause = (const pm_when_node_t *) conditions->nodes[clause_index];
+ const pm_node_list_t *conditions = &clause->conditions;
+
+ int clause_lineno = pm_node_line_number(parser, (const pm_node_t *) clause);
+ LABEL *label = NEW_LABEL(clause_lineno);
+ PUSH_LABEL(body_seq, label);
+
+ // Establish branch coverage for the when clause.
if (PM_BRANCH_COVERAGE_P(iseq)) {
- case_location = pm_code_location(scope_node, (const pm_node_t *) cast);
- branches = decl_branch_base(iseq, PTR2NUM(cast), &case_location, "case");
+ rb_code_location_t branch_location = pm_code_location(scope_node, clause->statements != NULL ? ((const pm_node_t *) clause->statements) : ((const pm_node_t *) clause));
+ add_trace_branch_coverage(iseq, body_seq, &branch_location, branch_location.beg_pos.column, branch_id++, "when", branches);
}
- // Loop through each clauses in the case node and compile each of
- // the conditions within them into cond_seq. If they match, they
- // should jump into their respective bodies in body_seq.
- for (size_t clause_index = 0; clause_index < conditions->size; clause_index++) {
- const pm_when_node_t *clause = (const pm_when_node_t *) conditions->nodes[clause_index];
- const pm_node_list_t *conditions = &clause->conditions;
+ if (clause->statements != NULL) {
+ pm_compile_node(iseq, (const pm_node_t *) clause->statements, body_seq, popped, scope_node);
+ }
+ else if (!popped) {
+ PUSH_SYNTHETIC_PUTNIL(body_seq, iseq);
+ }
- int clause_lineno = pm_node_line_number(parser, (const pm_node_t *) clause);
- LABEL *label = NEW_LABEL(clause_lineno);
- PUSH_LABEL(body_seq, label);
+ PUSH_INSNL(body_seq, location, jump, end_label);
- // Establish branch coverage for the when clause.
- if (PM_BRANCH_COVERAGE_P(iseq)) {
- rb_code_location_t branch_location = pm_code_location(scope_node, clause->statements != NULL ? ((const pm_node_t *) clause->statements) : ((const pm_node_t *) clause));
- add_trace_branch_coverage(iseq, body_seq, &branch_location, branch_location.beg_pos.column, branch_id++, "when", branches);
- }
+ // Compile each of the conditions for the when clause into the
+ // cond_seq. Each one should have a unique condition and should
+ // jump to the subsequent one if it doesn't match.
+ for (size_t condition_index = 0; condition_index < conditions->size; condition_index++) {
+ const pm_node_t *condition = conditions->nodes[condition_index];
- if (clause->statements != NULL) {
- pm_compile_node(iseq, (const pm_node_t *) clause->statements, body_seq, popped, scope_node);
+ if (PM_NODE_TYPE_P(condition, PM_SPLAT_NODE)) {
+ pm_node_location_t cond_location = PM_NODE_START_LOCATION(parser, condition);
+ PUSH_INSN(cond_seq, cond_location, putnil);
+ pm_compile_node(iseq, condition, cond_seq, false, scope_node);
+ PUSH_INSN1(cond_seq, cond_location, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_WHEN | VM_CHECKMATCH_ARRAY));
+ PUSH_INSNL(cond_seq, cond_location, branchif, label);
}
- else if (!popped) {
- PUSH_SYNTHETIC_PUTNIL(body_seq, iseq);
+ else {
+ LABEL *next_label = NEW_LABEL(pm_node_line_number(parser, condition));
+ pm_compile_branch_condition(iseq, cond_seq, condition, label, next_label, false, scope_node);
+ PUSH_LABEL(cond_seq, next_label);
}
+ }
+ }
+
+ // Establish branch coverage for the else clause (implicit or
+ // explicit).
+ if (PM_BRANCH_COVERAGE_P(iseq)) {
+ rb_code_location_t branch_location;
- PUSH_INSNL(body_seq, location, jump, end_label);
+ if (cast->else_clause == NULL) {
+ branch_location = case_location;
+ } else if (cast->else_clause->statements == NULL) {
+ branch_location = pm_code_location(scope_node, (const pm_node_t *) cast->else_clause);
+ } else {
+ branch_location = pm_code_location(scope_node, (const pm_node_t *) cast->else_clause->statements);
+ }
- // Compile each of the conditions for the when clause into the
- // cond_seq. Each one should have a unique condition and should
- // jump to the subsequent one if it doesn't match.
- for (size_t condition_index = 0; condition_index < conditions->size; condition_index++) {
- const pm_node_t *condition = conditions->nodes[condition_index];
+ add_trace_branch_coverage(iseq, cond_seq, &branch_location, branch_location.beg_pos.column, branch_id, "else", branches);
+ }
- if (PM_NODE_TYPE_P(condition, PM_SPLAT_NODE)) {
- pm_line_column_t cond_location = PM_NODE_START_LINE_COLUMN(parser, condition);
- PUSH_INSN(cond_seq, cond_location, putnil);
- pm_compile_node(iseq, condition, cond_seq, false, scope_node);
- PUSH_INSN1(cond_seq, cond_location, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_WHEN | VM_CHECKMATCH_ARRAY));
- PUSH_INSNL(cond_seq, cond_location, branchif, label);
+ // Compile the else clause if there is one.
+ if (cast->else_clause != NULL) {
+ pm_compile_node(iseq, (const pm_node_t *) cast->else_clause, cond_seq, popped, scope_node);
+ }
+ else if (!popped) {
+ PUSH_SYNTHETIC_PUTNIL(cond_seq, iseq);
+ }
+
+ // Finally, jump to the end label if none of the other conditions
+ // have matched.
+ PUSH_INSNL(cond_seq, location, jump, end_label);
+ PUSH_SEQ(ret, cond_seq);
+ }
+ else {
+ // Establish branch coverage for the case node.
+ VALUE branches = Qfalse;
+ rb_code_location_t case_location = { 0 };
+ int branch_id = 0;
+
+ if (PM_BRANCH_COVERAGE_P(iseq)) {
+ case_location = pm_code_location(scope_node, (const pm_node_t *) cast);
+ branches = decl_branch_base(iseq, PTR2NUM(cast), &case_location, "case");
+ }
+
+ // This is the label where everything will fall into if none of the
+ // conditions matched.
+ LABEL *else_label = NEW_LABEL(location.line);
+
+ // It's possible for us to speed up the case node by using a
+ // dispatch hash. This is a hash that maps the conditions of the
+ // various when clauses to the labels of their bodies. If we can
+ // compile the conditions into a hash key, then we can use a hash
+ // lookup to jump directly to the correct when clause body.
+ VALUE dispatch = Qundef;
+ if (ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
+ dispatch = rb_hash_new();
+ RHASH_TBL_RAW(dispatch)->type = &cdhash_type;
+ }
+
+ // We're going to loop through each of the conditions in the case
+ // node and compile each of their contents into both the cond_seq
+ // and the body_seq. Each condition will use its own label to jump
+ // from its conditions into its body.
+ //
+ // Note that none of the code in the loop below should be adding
+ // anything to ret, as we're going to be laying out the entire case
+ // node instructions later.
+ for (size_t clause_index = 0; clause_index < conditions->size; clause_index++) {
+ const pm_when_node_t *clause = (const pm_when_node_t *) conditions->nodes[clause_index];
+ pm_node_location_t clause_location = PM_NODE_START_LOCATION(parser, (const pm_node_t *) clause);
+
+ const pm_node_list_t *conditions = &clause->conditions;
+ LABEL *label = NEW_LABEL(clause_location.line);
+
+ // Compile each of the conditions for the when clause into the
+ // cond_seq. Each one should have a unique comparison that then
+ // jumps into the body if it matches.
+ for (size_t condition_index = 0; condition_index < conditions->size; condition_index++) {
+ const pm_node_t *condition = conditions->nodes[condition_index];
+ const pm_node_location_t condition_location = PM_NODE_START_LOCATION(parser, condition);
+
+ // If we haven't already abandoned the optimization, then
+ // we're going to try to compile the condition into the
+ // dispatch hash.
+ if (dispatch != Qundef) {
+ dispatch = pm_compile_case_node_dispatch(iseq, dispatch, condition, label, scope_node);
+ }
+
+ if (PM_NODE_TYPE_P(condition, PM_SPLAT_NODE)) {
+ PUSH_INSN(cond_seq, condition_location, dup);
+ pm_compile_node(iseq, condition, cond_seq, false, scope_node);
+ PUSH_INSN1(cond_seq, condition_location, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE | VM_CHECKMATCH_ARRAY));
+ }
+ else {
+ if (PM_NODE_TYPE_P(condition, PM_STRING_NODE)) {
+ const pm_string_node_t *string = (const pm_string_node_t *) condition;
+ VALUE value = parse_static_literal_string(iseq, scope_node, condition, &string->unescaped);
+ PUSH_INSN1(cond_seq, condition_location, putobject, value);
}
else {
- LABEL *next_label = NEW_LABEL(pm_node_line_number(parser, condition));
- pm_compile_branch_condition(iseq, cond_seq, condition, label, next_label, false, scope_node);
- PUSH_LABEL(cond_seq, next_label);
+ pm_compile_node(iseq, condition, cond_seq, false, scope_node);
}
+
+ PUSH_INSN1(cond_seq, condition_location, topn, INT2FIX(1));
+ PUSH_SEND_WITH_FLAG(cond_seq, condition_location, idEqq, INT2NUM(1), INT2FIX(VM_CALL_FCALL | VM_CALL_ARGS_SIMPLE));
}
- }
- // Establish branch coverage for the else clause (implicit or
- // explicit).
- if (PM_BRANCH_COVERAGE_P(iseq)) {
- rb_code_location_t branch_location;
+ PUSH_INSNL(cond_seq, condition_location, branchif, label);
+ }
- if (cast->consequent == NULL) {
- branch_location = case_location;
- } else if (cast->consequent->statements == NULL) {
- branch_location = pm_code_location(scope_node, (const pm_node_t *) cast->consequent);
- } else {
- branch_location = pm_code_location(scope_node, (const pm_node_t *) cast->consequent->statements);
- }
+ // Now, add the label to the body and compile the body of the
+ // when clause. This involves popping the predicate, compiling
+ // the statements to be executed, and then compiling a jump to
+ // the end of the case node.
+ PUSH_LABEL(body_seq, label);
+ PUSH_INSN(body_seq, clause_location, pop);
- add_trace_branch_coverage(iseq, cond_seq, &branch_location, branch_location.beg_pos.column, branch_id, "else", branches);
+ // Establish branch coverage for the when clause.
+ if (PM_BRANCH_COVERAGE_P(iseq)) {
+ rb_code_location_t branch_location = pm_code_location(scope_node, clause->statements != NULL ? ((const pm_node_t *) clause->statements) : ((const pm_node_t *) clause));
+ add_trace_branch_coverage(iseq, body_seq, &branch_location, branch_location.beg_pos.column, branch_id++, "when", branches);
}
- // Compile the consequent else clause if there is one.
- if (cast->consequent != NULL) {
- pm_compile_node(iseq, (const pm_node_t *) cast->consequent, cond_seq, popped, scope_node);
+ if (clause->statements != NULL) {
+ pm_compile_node(iseq, (const pm_node_t *) clause->statements, body_seq, popped, scope_node);
}
else if (!popped) {
- PUSH_SYNTHETIC_PUTNIL(cond_seq, iseq);
+ PUSH_SYNTHETIC_PUTNIL(body_seq, iseq);
}
- // Finally, jump to the end label if none of the other conditions
- // have matched.
- PUSH_INSNL(cond_seq, location, jump, end_label);
- PUSH_SEQ(ret, cond_seq);
+ PUSH_INSNL(body_seq, clause_location, jump, end_label);
}
- else {
- // Establish branch coverage for the case node.
- VALUE branches = Qfalse;
- rb_code_location_t case_location = { 0 };
- int branch_id = 0;
+ // Now that we have compiled the conditions and the bodies of the
+ // various when clauses, we can compile the predicate, lay out the
+ // conditions, compile the fallback subsequent if there is one, and
+ // finally put in the bodies of the when clauses.
+ PM_COMPILE_NOT_POPPED(cast->predicate);
+
+ // If we have a dispatch hash, then we'll use it here to create the
+ // optimization.
+ if (dispatch != Qundef) {
+ PUSH_INSN(ret, location, dup);
+ RB_OBJ_SET_SHAREABLE(dispatch); // it is special that the hash is shareable but not frozen, because compile.c modify them. This Hahs instance is not accessible so it is safe to leave it.
+ PUSH_INSN2(ret, location, opt_case_dispatch, dispatch, else_label);
+ LABEL_REF(else_label);
+ }
+
+ PUSH_SEQ(ret, cond_seq);
+
+ // Compile either the explicit else clause or an implicit else
+ // clause.
+ PUSH_LABEL(ret, else_label);
+
+ if (cast->else_clause != NULL) {
+ pm_node_location_t else_location = PM_NODE_START_LOCATION(parser, cast->else_clause->statements != NULL ? ((const pm_node_t *) cast->else_clause->statements) : ((const pm_node_t *) cast->else_clause));
+ PUSH_INSN(ret, else_location, pop);
+
+ // Establish branch coverage for the else clause.
if (PM_BRANCH_COVERAGE_P(iseq)) {
- case_location = pm_code_location(scope_node, (const pm_node_t *) cast);
- branches = decl_branch_base(iseq, PTR2NUM(cast), &case_location, "case");
+ rb_code_location_t branch_location = pm_code_location(scope_node, cast->else_clause->statements != NULL ? ((const pm_node_t *) cast->else_clause->statements) : ((const pm_node_t *) cast->else_clause));
+ add_trace_branch_coverage(iseq, ret, &branch_location, branch_location.beg_pos.column, branch_id, "else", branches);
}
- // This is the label where everything will fall into if none of the
- // conditions matched.
- LABEL *else_label = NEW_LABEL(location.line);
+ PM_COMPILE((const pm_node_t *) cast->else_clause);
+ PUSH_INSNL(ret, else_location, jump, end_label);
+ }
+ else {
+ PUSH_INSN(ret, location, pop);
- // It's possible for us to speed up the case node by using a
- // dispatch hash. This is a hash that maps the conditions of the
- // various when clauses to the labels of their bodies. If we can
- // compile the conditions into a hash key, then we can use a hash
- // lookup to jump directly to the correct when clause body.
- VALUE dispatch = Qundef;
- if (ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) {
- dispatch = rb_hash_new();
- RHASH_TBL_RAW(dispatch)->type = &cdhash_type;
+ // Establish branch coverage for the implicit else clause.
+ if (PM_BRANCH_COVERAGE_P(iseq)) {
+ add_trace_branch_coverage(iseq, ret, &case_location, case_location.beg_pos.column, branch_id, "else", branches);
}
- // We're going to loop through each of the conditions in the case
- // node and compile each of their contents into both the cond_seq
- // and the body_seq. Each condition will use its own label to jump
- // from its conditions into its body.
- //
- // Note that none of the code in the loop below should be adding
- // anything to ret, as we're going to be laying out the entire case
- // node instructions later.
- for (size_t clause_index = 0; clause_index < conditions->size; clause_index++) {
- const pm_when_node_t *clause = (const pm_when_node_t *) conditions->nodes[clause_index];
- pm_line_column_t clause_location = PM_NODE_START_LINE_COLUMN(parser, (const pm_node_t *) clause);
-
- const pm_node_list_t *conditions = &clause->conditions;
- LABEL *label = NEW_LABEL(clause_location.line);
-
- // Compile each of the conditions for the when clause into the
- // cond_seq. Each one should have a unique comparison that then
- // jumps into the body if it matches.
- for (size_t condition_index = 0; condition_index < conditions->size; condition_index++) {
- const pm_node_t *condition = conditions->nodes[condition_index];
- const pm_line_column_t condition_location = PM_NODE_START_LINE_COLUMN(parser, condition);
-
- // If we haven't already abandoned the optimization, then
- // we're going to try to compile the condition into the
- // dispatch hash.
- if (dispatch != Qundef) {
- dispatch = pm_compile_case_node_dispatch(iseq, dispatch, condition, label, scope_node);
- }
+ if (!popped) PUSH_INSN(ret, location, putnil);
+ PUSH_INSNL(ret, location, jump, end_label);
+ }
+ }
- if (PM_NODE_TYPE_P(condition, PM_SPLAT_NODE)) {
- PUSH_INSN(cond_seq, condition_location, dup);
- pm_compile_node(iseq, condition, cond_seq, false, scope_node);
- PUSH_INSN1(cond_seq, condition_location, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE | VM_CHECKMATCH_ARRAY));
- }
- else {
- if (PM_NODE_TYPE_P(condition, PM_STRING_NODE)) {
- const pm_string_node_t *string = (const pm_string_node_t *) condition;
- VALUE value = parse_static_literal_string(iseq, scope_node, condition, &string->unescaped);
- PUSH_INSN1(cond_seq, condition_location, putobject, value);
- }
- else {
- pm_compile_node(iseq, condition, cond_seq, false, scope_node);
- }
+ PUSH_SEQ(ret, body_seq);
+ PUSH_LABEL(ret, end_label);
+}
- PUSH_INSN1(cond_seq, condition_location, topn, INT2FIX(1));
- PUSH_SEND_WITH_FLAG(cond_seq, condition_location, idEqq, INT2NUM(1), INT2FIX(VM_CALL_FCALL | VM_CALL_ARGS_SIMPLE));
- }
+static inline void
+pm_compile_case_match_node(rb_iseq_t *iseq, const pm_case_match_node_t *node, const pm_node_location_t *location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+{
+ // This is the anchor that we will compile the bodies of the various
+ // `in` nodes into. We'll make sure that the patterns that are compiled
+ // jump into the correct spots within this anchor.
+ DECL_ANCHOR(body_seq);
+
+ // This is the anchor that we will compile the patterns of the various
+ // `in` nodes into. If a match is found, they will need to jump into the
+ // body_seq anchor to the correct spot.
+ DECL_ANCHOR(cond_seq);
- PUSH_INSNL(cond_seq, condition_location, branchif, label);
- }
+ // This label is used to indicate the end of the entire node. It is
+ // jumped to after the entire stack is cleaned up.
+ LABEL *end_label = NEW_LABEL(location->line);
- // Now, add the label to the body and compile the body of the
- // when clause. This involves popping the predicate, compiling
- // the statements to be executed, and then compiling a jump to
- // the end of the case node.
- PUSH_LABEL(body_seq, label);
- PUSH_INSN(body_seq, clause_location, pop);
-
- // Establish branch coverage for the when clause.
- if (PM_BRANCH_COVERAGE_P(iseq)) {
- rb_code_location_t branch_location = pm_code_location(scope_node, clause->statements != NULL ? ((const pm_node_t *) clause->statements) : ((const pm_node_t *) clause));
- add_trace_branch_coverage(iseq, body_seq, &branch_location, branch_location.beg_pos.column, branch_id++, "when", branches);
- }
+ // This label is used as the fallback for the case match. If no match is
+ // found, then we jump to this label. This is either an `else` clause or
+ // an error handler.
+ LABEL *else_label = NEW_LABEL(location->line);
- if (clause->statements != NULL) {
- pm_compile_node(iseq, (const pm_node_t *) clause->statements, body_seq, popped, scope_node);
- }
- else if (!popped) {
- PUSH_SYNTHETIC_PUTNIL(body_seq, iseq);
- }
+ // We're going to use this to uniquely identify each branch so that we
+ // can track coverage information.
+ rb_code_location_t case_location = { 0 };
+ VALUE branches = Qfalse;
+ int branch_id = 0;
- PUSH_INSNL(body_seq, clause_location, jump, end_label);
- }
+ if (PM_BRANCH_COVERAGE_P(iseq)) {
+ case_location = pm_code_location(scope_node, (const pm_node_t *) node);
+ branches = decl_branch_base(iseq, PTR2NUM(node), &case_location, "case");
+ }
- // Now that we have compiled the conditions and the bodies of the
- // various when clauses, we can compile the predicate, lay out the
- // conditions, compile the fallback consequent if there is one, and
- // finally put in the bodies of the when clauses.
- PM_COMPILE_NOT_POPPED(cast->predicate);
+ // If there is only one pattern, then the behavior changes a bit. It
+ // effectively gets treated as a match required node (this is how it is
+ // represented in the other parser).
+ bool in_single_pattern = node->else_clause == NULL && node->conditions.size == 1;
- // If we have a dispatch hash, then we'll use it here to create the
- // optimization.
- if (dispatch != Qundef) {
- PUSH_INSN(ret, location, dup);
- PUSH_INSN2(ret, location, opt_case_dispatch, dispatch, else_label);
- LABEL_REF(else_label);
- }
+ // First, we're going to push a bunch of stuff onto the stack that is
+ // going to serve as our scratch space.
+ if (in_single_pattern) {
+ PUSH_INSN(ret, *location, putnil); // key error key
+ PUSH_INSN(ret, *location, putnil); // key error matchee
+ PUSH_INSN1(ret, *location, putobject, Qfalse); // key error?
+ PUSH_INSN(ret, *location, putnil); // error string
+ }
- PUSH_SEQ(ret, cond_seq);
+ // Now we're going to compile the value to match against.
+ PUSH_INSN(ret, *location, putnil); // deconstruct cache
+ PM_COMPILE_NOT_POPPED(node->predicate);
- // Compile either the explicit else clause or an implicit else
- // clause.
- PUSH_LABEL(ret, else_label);
+ // Next, we'll loop through every in clause and compile its body into
+ // the body_seq anchor and its pattern into the cond_seq anchor. We'll
+ // make sure the pattern knows how to jump correctly into the body if it
+ // finds a match.
+ for (size_t index = 0; index < node->conditions.size; index++) {
+ const pm_node_t *condition = node->conditions.nodes[index];
+ RUBY_ASSERT(PM_NODE_TYPE_P(condition, PM_IN_NODE));
- if (cast->consequent != NULL) {
- pm_line_column_t else_location = PM_NODE_START_LINE_COLUMN(parser, cast->consequent->statements != NULL ? ((const pm_node_t *) cast->consequent->statements) : ((const pm_node_t *) cast->consequent));
- PUSH_INSN(ret, else_location, pop);
+ const pm_in_node_t *in_node = (const pm_in_node_t *) condition;
+ const pm_node_location_t in_location = PM_NODE_START_LOCATION(scope_node->parser, in_node);
+ const pm_node_location_t pattern_location = PM_NODE_START_LOCATION(scope_node->parser, in_node->pattern);
- // Establish branch coverage for the else clause.
- if (PM_BRANCH_COVERAGE_P(iseq)) {
- rb_code_location_t branch_location = pm_code_location(scope_node, cast->consequent->statements != NULL ? ((const pm_node_t *) cast->consequent->statements) : ((const pm_node_t *) cast->consequent));
- add_trace_branch_coverage(iseq, ret, &branch_location, branch_location.beg_pos.column, branch_id, "else", branches);
- }
+ if (branch_id) {
+ PUSH_INSN(body_seq, in_location, putnil);
+ }
- PM_COMPILE((const pm_node_t *) cast->consequent);
- PUSH_INSNL(ret, else_location, jump, end_label);
- }
- else {
- PUSH_INSN(ret, location, pop);
+ LABEL *body_label = NEW_LABEL(in_location.line);
+ PUSH_LABEL(body_seq, body_label);
+ PUSH_INSN1(body_seq, in_location, adjuststack, INT2FIX(in_single_pattern ? 6 : 2));
- // Establish branch coverage for the implicit else clause.
- if (PM_BRANCH_COVERAGE_P(iseq)) {
- add_trace_branch_coverage(iseq, ret, &case_location, case_location.beg_pos.column, branch_id, "else", branches);
- }
+ // Establish branch coverage for the in clause.
+ if (PM_BRANCH_COVERAGE_P(iseq)) {
+ rb_code_location_t branch_location = pm_code_location(scope_node, in_node->statements != NULL ? ((const pm_node_t *) in_node->statements) : ((const pm_node_t *) in_node));
+ add_trace_branch_coverage(iseq, body_seq, &branch_location, branch_location.beg_pos.column, branch_id++, "in", branches);
+ }
+
+ if (in_node->statements != NULL) {
+ PM_COMPILE_INTO_ANCHOR(body_seq, (const pm_node_t *) in_node->statements);
+ }
+ else if (!popped) {
+ PUSH_SYNTHETIC_PUTNIL(body_seq, iseq);
+ }
+
+ PUSH_INSNL(body_seq, in_location, jump, end_label);
+ LABEL *next_pattern_label = NEW_LABEL(pattern_location.line);
+
+ PUSH_INSN(cond_seq, pattern_location, dup);
+ pm_compile_pattern(iseq, scope_node, in_node->pattern, cond_seq, body_label, next_pattern_label, in_single_pattern, true, 2);
+ PUSH_LABEL(cond_seq, next_pattern_label);
+ LABEL_UNREMOVABLE(next_pattern_label);
+ }
+
+ if (node->else_clause != NULL) {
+ // If we have an `else` clause, then this becomes our fallback (and
+ // there is no need to compile in code to potentially raise an
+ // error).
+ const pm_else_node_t *else_node = node->else_clause;
+
+ PUSH_LABEL(cond_seq, else_label);
+ PUSH_INSN(cond_seq, *location, pop);
+ PUSH_INSN(cond_seq, *location, pop);
+
+ // Establish branch coverage for the else clause.
+ if (PM_BRANCH_COVERAGE_P(iseq)) {
+ rb_code_location_t branch_location = pm_code_location(scope_node, else_node->statements != NULL ? ((const pm_node_t *) else_node->statements) : ((const pm_node_t *) else_node));
+ add_trace_branch_coverage(iseq, cond_seq, &branch_location, branch_location.beg_pos.column, branch_id, "else", branches);
+ }
+
+ PM_COMPILE_INTO_ANCHOR(cond_seq, (const pm_node_t *) else_node);
+ PUSH_INSNL(cond_seq, *location, jump, end_label);
+ PUSH_INSN(cond_seq, *location, putnil);
+ if (popped) PUSH_INSN(cond_seq, *location, putnil);
+ }
+ else {
+ // Otherwise, if we do not have an `else` clause, we will compile in
+ // the code to handle raising an appropriate error.
+ PUSH_LABEL(cond_seq, else_label);
+
+ // Establish branch coverage for the implicit else clause.
+ add_trace_branch_coverage(iseq, cond_seq, &case_location, case_location.beg_pos.column, branch_id, "else", branches);
+
+ if (in_single_pattern) {
+ pm_compile_pattern_error_handler(iseq, scope_node, (const pm_node_t *) node, cond_seq, end_label, popped);
+ }
+ else {
+ PUSH_INSN1(cond_seq, *location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
+ PUSH_INSN1(cond_seq, *location, putobject, rb_eNoMatchingPatternError);
+ PUSH_INSN1(cond_seq, *location, topn, INT2FIX(2));
+ PUSH_SEND(cond_seq, *location, id_core_raise, INT2FIX(2));
+
+ PUSH_INSN1(cond_seq, *location, adjuststack, INT2FIX(3));
+ if (!popped) PUSH_INSN(cond_seq, *location, putnil);
+ PUSH_INSNL(cond_seq, *location, jump, end_label);
+ PUSH_INSN1(cond_seq, *location, dupn, INT2FIX(1));
+ if (popped) PUSH_INSN(cond_seq, *location, putnil);
+ }
+ }
+
+ // At the end of all of this compilation, we will add the code for the
+ // conditions first, then the various bodies, then mark the end of the
+ // entire sequence with the end label.
+ PUSH_SEQ(ret, cond_seq);
+ PUSH_SEQ(ret, body_seq);
+ PUSH_LABEL(ret, end_label);
+}
+
+static inline void
+pm_compile_forwarding_super_node(rb_iseq_t *iseq, const pm_forwarding_super_node_t *node, const pm_node_location_t *location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+{
+ const rb_iseq_t *block = NULL;
+ const rb_iseq_t *previous_block = NULL;
+ LABEL *retry_label = NULL;
+ LABEL *retry_end_l = NULL;
+
+ if (node->block != NULL) {
+ previous_block = ISEQ_COMPILE_DATA(iseq)->current_block;
+ ISEQ_COMPILE_DATA(iseq)->current_block = NULL;
+
+ retry_label = NEW_LABEL(location->line);
+ retry_end_l = NEW_LABEL(location->line);
+
+ PUSH_LABEL(ret, retry_label);
+ }
+ else {
+ iseq_set_use_block(ISEQ_BODY(iseq)->local_iseq);
+ }
+
+ PUSH_INSN(ret, *location, putself);
+ int flag = VM_CALL_ZSUPER | VM_CALL_SUPER | VM_CALL_FCALL;
+
+ if (node->block != NULL) {
+ pm_scope_node_t next_scope_node;
+ pm_scope_node_init((const pm_node_t *) node->block, &next_scope_node, scope_node);
+
+ ISEQ_COMPILE_DATA(iseq)->current_block = block = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, location->line);
+ pm_scope_node_destroy(&next_scope_node);
+ RB_OBJ_WRITTEN(iseq, Qundef, (VALUE) block);
+ }
+
+ DECL_ANCHOR(args);
+
+ struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
+ const rb_iseq_t *local_iseq = body->local_iseq;
+ const struct rb_iseq_constant_body *const local_body = ISEQ_BODY(local_iseq);
+
+ int argc = 0;
+ int depth = get_lvar_level(iseq);
+
+ if (ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->param.flags.forwardable) {
+ flag |= VM_CALL_FORWARDING;
+ pm_local_index_t mult_local = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_DOT3, 0);
+ PUSH_GETLOCAL(ret, *location, mult_local.index, mult_local.level);
+
+ const struct rb_callinfo *callinfo = new_callinfo(iseq, 0, 0, flag, NULL, block != NULL);
+ PUSH_INSN2(ret, *location, invokesuperforward, callinfo, block);
+
+ if (popped) PUSH_INSN(ret, *location, pop);
+ if (node->block) {
+ ISEQ_COMPILE_DATA(iseq)->current_block = previous_block;
+ }
+ return;
+ }
+
+ if (local_body->param.flags.has_lead) {
+ /* required arguments */
+ for (int i = 0; i < local_body->param.lead_num; i++) {
+ int idx = local_body->local_table_size - i;
+ PUSH_GETLOCAL(args, *location, idx, depth);
+ }
+ argc += local_body->param.lead_num;
+ }
+
+ if (local_body->param.flags.has_opt) {
+ /* optional arguments */
+ for (int j = 0; j < local_body->param.opt_num; j++) {
+ int idx = local_body->local_table_size - (argc + j);
+ PUSH_GETLOCAL(args, *location, idx, depth);
+ }
+ argc += local_body->param.opt_num;
+ }
+
+ if (local_body->param.flags.has_rest) {
+ /* rest argument */
+ int idx = local_body->local_table_size - local_body->param.rest_start;
+ PUSH_GETLOCAL(args, *location, idx, depth);
+ PUSH_INSN1(args, *location, 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;
+
+ int j = 0;
+ for (; j < post_len; j++) {
+ int idx = local_body->local_table_size - (post_start + j);
+ PUSH_GETLOCAL(args, *location, idx, depth);
+ }
- if (!popped) PUSH_INSN(ret, location, putnil);
- PUSH_INSNL(ret, location, jump, end_label);
+ if (local_body->param.flags.has_rest) {
+ // argc remains unchanged from rest branch
+ PUSH_INSN1(args, *location, newarray, INT2FIX(j));
+ PUSH_INSN(args, *location, concatarray);
+ }
+ else {
+ argc = post_len + post_start;
+ }
+ }
+
+ const struct rb_iseq_param_keyword *const local_keyword = local_body->param.keyword;
+ if (local_body->param.flags.has_kw) {
+ int local_size = local_body->local_table_size;
+ argc++;
+
+ PUSH_INSN1(args, *location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
+
+ if (local_body->param.flags.has_kwrest) {
+ int idx = local_body->local_table_size - local_keyword->rest_start;
+ PUSH_GETLOCAL(args, *location, idx, depth);
+ RUBY_ASSERT(local_keyword->num > 0);
+ PUSH_SEND(args, *location, rb_intern("dup"), INT2FIX(0));
+ }
+ else {
+ PUSH_INSN1(args, *location, newhash, INT2FIX(0));
+ }
+ int i = 0;
+ for (; i < local_keyword->num; ++i) {
+ ID id = local_keyword->table[i];
+ int idx = local_size - get_local_var_idx(local_iseq, id);
+
+ {
+ VALUE operand = ID2SYM(id);
+ PUSH_INSN1(args, *location, putobject, operand);
}
+
+ PUSH_GETLOCAL(args, *location, idx, depth);
}
- PUSH_SEQ(ret, body_seq);
- PUSH_LABEL(ret, end_label);
+ PUSH_SEND(args, *location, id_core_hash_merge_ptr, INT2FIX(i * 2 + 1));
+ flag |= VM_CALL_KW_SPLAT| VM_CALL_KW_SPLAT_MUT;
+ }
+ else if (local_body->param.flags.has_kwrest) {
+ int idx = local_body->local_table_size - local_keyword->rest_start;
+ PUSH_GETLOCAL(args, *location, idx, depth);
+ argc++;
+ flag |= VM_CALL_KW_SPLAT;
+ }
+
+ PUSH_SEQ(ret, args);
+
+ {
+ const struct rb_callinfo *callinfo = new_callinfo(iseq, 0, argc, flag, NULL, block != NULL);
+ PUSH_INSN2(ret, *location, invokesuper, callinfo, block);
+ }
+
+ if (node->block != NULL) {
+ pm_compile_retry_end_label(iseq, ret, retry_end_l);
+ PUSH_CATCH_ENTRY(CATCH_TYPE_BREAK, retry_label, retry_end_l, block, retry_end_l);
+ ISEQ_COMPILE_DATA(iseq)->current_block = previous_block;
+ }
+
+ if (popped) PUSH_INSN(ret, *location, pop);
+}
+
+static inline void
+pm_compile_match_required_node(rb_iseq_t *iseq, const pm_match_required_node_t *node, const pm_node_location_t *location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+{
+ LABEL *matched_label = NEW_LABEL(location->line);
+ LABEL *unmatched_label = NEW_LABEL(location->line);
+ LABEL *done_label = NEW_LABEL(location->line);
+
+ // First, we're going to push a bunch of stuff onto the stack that is
+ // going to serve as our scratch space.
+ PUSH_INSN(ret, *location, putnil); // key error key
+ PUSH_INSN(ret, *location, putnil); // key error matchee
+ PUSH_INSN1(ret, *location, putobject, Qfalse); // key error?
+ PUSH_INSN(ret, *location, putnil); // error string
+ PUSH_INSN(ret, *location, putnil); // deconstruct cache
+
+ // Next we're going to compile the value expression such that it's on
+ // the stack.
+ PM_COMPILE_NOT_POPPED(node->value);
+
+ // Here we'll dup it so that it can be used for comparison, but also be
+ // used for error handling.
+ PUSH_INSN(ret, *location, dup);
+
+ // Next we'll compile the pattern. We indicate to the pm_compile_pattern
+ // function that this is the only pattern that will be matched against
+ // through the in_single_pattern parameter. We also indicate that the
+ // value to compare against is 2 slots from the top of the stack (the
+ // base_index parameter).
+ pm_compile_pattern(iseq, scope_node, node->pattern, ret, matched_label, unmatched_label, true, true, 2);
+
+ // If the pattern did not match the value, then we're going to compile
+ // in our error handler code. This will determine which error to raise
+ // and raise it.
+ PUSH_LABEL(ret, unmatched_label);
+ pm_compile_pattern_error_handler(iseq, scope_node, (const pm_node_t *) node, ret, done_label, popped);
+
+ // If the pattern did match, we'll clean up the values we've pushed onto
+ // the stack and then push nil onto the stack if it's not popped.
+ PUSH_LABEL(ret, matched_label);
+ PUSH_INSN1(ret, *location, adjuststack, INT2FIX(6));
+ if (!popped) PUSH_INSN(ret, *location, putnil);
+ PUSH_INSNL(ret, *location, jump, done_label);
+
+ PUSH_LABEL(ret, done_label);
+}
+static inline void
+pm_compile_match_write_node(rb_iseq_t *iseq, const pm_match_write_node_t *node, const pm_node_location_t *location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+{
+ LABEL *fail_label = NEW_LABEL(location->line);
+ LABEL *end_label = NEW_LABEL(location->line);
+
+ // First, we'll compile the call so that all of its instructions are
+ // present. Then we'll compile all of the local variable targets.
+ PM_COMPILE_NOT_POPPED((const pm_node_t *) node->call);
+
+ // Now, check if the match was successful. If it was, then we'll
+ // continue on and assign local variables. Otherwise we'll skip over the
+ // assignment code.
+ {
+ VALUE operand = rb_id2sym(idBACKREF);
+ PUSH_INSN1(ret, *location, getglobal, operand);
+ }
+
+ PUSH_INSN(ret, *location, dup);
+ PUSH_INSNL(ret, *location, branchunless, fail_label);
+
+ // If there's only a single local variable target, we can skip some of
+ // the bookkeeping, so we'll put a special branch here.
+ size_t targets_count = node->targets.size;
+
+ if (targets_count == 1) {
+ const pm_node_t *target = node->targets.nodes[0];
+ RUBY_ASSERT(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_TARGET_NODE));
+
+ const pm_local_variable_target_node_t *local_target = (const pm_local_variable_target_node_t *) target;
+ pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, local_target->name, local_target->depth);
+
+ {
+ VALUE operand = rb_id2sym(pm_constant_id_lookup(scope_node, local_target->name));
+ PUSH_INSN1(ret, *location, putobject, operand);
+ }
+
+ PUSH_SEND(ret, *location, idAREF, INT2FIX(1));
+ PUSH_LABEL(ret, fail_label);
+ PUSH_SETLOCAL(ret, *location, index.index, index.level);
+ if (popped) PUSH_INSN(ret, *location, pop);
return;
- }
- case PM_CASE_MATCH_NODE: {
- // case foo; in bar; end
- // ^^^^^^^^^^^^^^^^^^^^^
- //
- // If you use the `case` keyword to create a case match node, it will
- // match against all of the `in` clauses until it finds one that
- // matches. If it doesn't find one, it can optionally fall back to an
- // `else` clause. If none is present and a match wasn't found, it will
- // raise an appropriate error.
- const pm_case_match_node_t *cast = (const pm_case_match_node_t *) node;
+ }
- // This is the anchor that we will compile the bodies of the various
- // `in` nodes into. We'll make sure that the patterns that are compiled
- // jump into the correct spots within this anchor.
- DECL_ANCHOR(body_seq);
- INIT_ANCHOR(body_seq);
+ DECL_ANCHOR(fail_anchor);
- // This is the anchor that we will compile the patterns of the various
- // `in` nodes into. If a match is found, they will need to jump into the
- // body_seq anchor to the correct spot.
- DECL_ANCHOR(cond_seq);
- INIT_ANCHOR(cond_seq);
+ // Otherwise there is more than one local variable target, so we'll need
+ // to do some bookkeeping.
+ for (size_t targets_index = 0; targets_index < targets_count; targets_index++) {
+ const pm_node_t *target = node->targets.nodes[targets_index];
+ RUBY_ASSERT(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_TARGET_NODE));
- // This label is used to indicate the end of the entire node. It is
- // jumped to after the entire stack is cleaned up.
- LABEL *end_label = NEW_LABEL(location.line);
+ const pm_local_variable_target_node_t *local_target = (const pm_local_variable_target_node_t *) target;
+ pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, local_target->name, local_target->depth);
- // This label is used as the fallback for the case match. If no match is
- // found, then we jump to this label. This is either an `else` clause or
- // an error handler.
- LABEL *else_label = NEW_LABEL(location.line);
+ if (((size_t) targets_index) < (targets_count - 1)) {
+ PUSH_INSN(ret, *location, dup);
+ }
- // We're going to use this to uniquely identify each branch so that we
- // can track coverage information.
- rb_code_location_t case_location = { 0 };
- VALUE branches = Qfalse;
- int branch_id = 0;
+ {
+ VALUE operand = rb_id2sym(pm_constant_id_lookup(scope_node, local_target->name));
+ PUSH_INSN1(ret, *location, putobject, operand);
+ }
- if (PM_BRANCH_COVERAGE_P(iseq)) {
- case_location = pm_code_location(scope_node, (const pm_node_t *) cast);
- branches = decl_branch_base(iseq, PTR2NUM(cast), &case_location, "case");
+ PUSH_SEND(ret, *location, idAREF, INT2FIX(1));
+ PUSH_SETLOCAL(ret, *location, index.index, index.level);
+
+ PUSH_INSN(fail_anchor, *location, putnil);
+ PUSH_SETLOCAL(fail_anchor, *location, index.index, index.level);
+ }
+
+ // Since we matched successfully, now we'll jump to the end.
+ PUSH_INSNL(ret, *location, jump, end_label);
+
+ // In the case that the match failed, we'll loop through each local
+ // variable target and set all of them to `nil`.
+ PUSH_LABEL(ret, fail_label);
+ PUSH_INSN(ret, *location, pop);
+ PUSH_SEQ(ret, fail_anchor);
+
+ // Finally, we can push the end label for either case.
+ PUSH_LABEL(ret, end_label);
+ if (popped) PUSH_INSN(ret, *location, pop);
+}
+
+static inline void
+pm_compile_next_node(rb_iseq_t *iseq, const pm_next_node_t *node, const pm_node_location_t *location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+{
+ if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0 && can_add_ensure_iseq(iseq)) {
+ LABEL *splabel = NEW_LABEL(0);
+ PUSH_LABEL(ret, splabel);
+
+ if (node->arguments) {
+ PM_COMPILE_NOT_POPPED((const pm_node_t *) node->arguments);
+ }
+ else {
+ PUSH_INSN(ret, *location, putnil);
}
+ pm_add_ensure_iseq(ret, iseq, 0, scope_node);
- // If there is only one pattern, then the behavior changes a bit. It
- // effectively gets treated as a match required node (this is how it is
- // represented in the other parser).
- bool in_single_pattern = cast->consequent == NULL && cast->conditions.size == 1;
+ PUSH_ADJUST(ret, *location, ISEQ_COMPILE_DATA(iseq)->redo_label);
+ PUSH_INSNL(ret, *location, jump, ISEQ_COMPILE_DATA(iseq)->start_label);
- // First, we're going to push a bunch of stuff onto the stack that is
- // going to serve as our scratch space.
- if (in_single_pattern) {
- PUSH_INSN(ret, location, putnil); // key error key
- PUSH_INSN(ret, location, putnil); // key error matchee
- PUSH_INSN1(ret, location, putobject, Qfalse); // key error?
- PUSH_INSN(ret, location, putnil); // error string
+ PUSH_ADJUST_RESTORE(ret, splabel);
+ if (!popped) PUSH_INSN(ret, *location, putnil);
+ }
+ else if (ISEQ_COMPILE_DATA(iseq)->end_label && can_add_ensure_iseq(iseq)) {
+ LABEL *splabel = NEW_LABEL(0);
+
+ PUSH_LABEL(ret, splabel);
+ PUSH_ADJUST(ret, *location, ISEQ_COMPILE_DATA(iseq)->start_label);
+
+ if (node->arguments != NULL) {
+ PM_COMPILE_NOT_POPPED((const pm_node_t *) node->arguments);
+ }
+ else {
+ PUSH_INSN(ret, *location, putnil);
}
- // Now we're going to compile the value to match against.
- PUSH_INSN(ret, location, putnil); // deconstruct cache
- PM_COMPILE_NOT_POPPED(cast->predicate);
+ pm_add_ensure_iseq(ret, iseq, 0, scope_node);
+ PUSH_INSNL(ret, *location, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
+ PUSH_ADJUST_RESTORE(ret, splabel);
+ splabel->unremovable = FALSE;
- // Next, we'll loop through every in clause and compile its body into
- // the body_seq anchor and its pattern into the cond_seq anchor. We'll
- // make sure the pattern knows how to jump correctly into the body if it
- // finds a match.
- for (size_t index = 0; index < cast->conditions.size; index++) {
- const pm_node_t *condition = cast->conditions.nodes[index];
- RUBY_ASSERT(PM_NODE_TYPE_P(condition, PM_IN_NODE));
+ if (!popped) PUSH_INSN(ret, *location, putnil);
+ }
+ else {
+ const rb_iseq_t *ip = iseq;
+ unsigned long throw_flag = 0;
+
+ while (ip) {
+ if (!ISEQ_COMPILE_DATA(ip)) {
+ ip = 0;
+ break;
+ }
+
+ throw_flag = VM_THROW_NO_ESCAPE_FLAG;
+ if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
+ /* while loop */
+ break;
+ }
+ else if (ISEQ_BODY(ip)->type == ISEQ_TYPE_BLOCK) {
+ break;
+ }
+ else if (ISEQ_BODY(ip)->type == ISEQ_TYPE_EVAL) {
+ COMPILE_ERROR(iseq, location->line, "Invalid next");
+ return;
+ }
- const pm_in_node_t *in_node = (const pm_in_node_t *) condition;
- const pm_line_column_t in_location = PM_NODE_START_LINE_COLUMN(parser, in_node);
- const pm_line_column_t pattern_location = PM_NODE_START_LINE_COLUMN(parser, in_node->pattern);
+ ip = ISEQ_BODY(ip)->parent_iseq;
+ }
- if (branch_id) {
- PUSH_INSN(body_seq, in_location, putnil);
+ if (ip != 0) {
+ if (node->arguments) {
+ PM_COMPILE_NOT_POPPED((const pm_node_t *) node->arguments);
+ }
+ else {
+ PUSH_INSN(ret, *location, putnil);
}
- LABEL *body_label = NEW_LABEL(in_location.line);
- PUSH_LABEL(body_seq, body_label);
- PUSH_INSN1(body_seq, in_location, adjuststack, INT2FIX(in_single_pattern ? 6 : 2));
+ PUSH_INSN1(ret, *location, throw, INT2FIX(throw_flag | TAG_NEXT));
+ if (popped) PUSH_INSN(ret, *location, pop);
+ }
+ else {
+ COMPILE_ERROR(iseq, location->line, "Invalid next");
+ }
+ }
+}
- // Establish branch coverage for the in clause.
- if (PM_BRANCH_COVERAGE_P(iseq)) {
- rb_code_location_t branch_location = pm_code_location(scope_node, in_node->statements != NULL ? ((const pm_node_t *) in_node->statements) : ((const pm_node_t *) in_node));
- add_trace_branch_coverage(iseq, body_seq, &branch_location, branch_location.beg_pos.column, branch_id++, "in", branches);
+static inline void
+pm_compile_redo_node(rb_iseq_t *iseq, const pm_node_location_t *location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+{
+ if (ISEQ_COMPILE_DATA(iseq)->redo_label && can_add_ensure_iseq(iseq)) {
+ LABEL *splabel = NEW_LABEL(0);
+
+ PUSH_LABEL(ret, splabel);
+ PUSH_ADJUST(ret, *location, ISEQ_COMPILE_DATA(iseq)->redo_label);
+ pm_add_ensure_iseq(ret, iseq, 0, scope_node);
+
+ PUSH_INSNL(ret, *location, jump, ISEQ_COMPILE_DATA(iseq)->redo_label);
+ PUSH_ADJUST_RESTORE(ret, splabel);
+ if (!popped) PUSH_INSN(ret, *location, putnil);
+ }
+ else if (ISEQ_BODY(iseq)->type != ISEQ_TYPE_EVAL && ISEQ_COMPILE_DATA(iseq)->start_label && can_add_ensure_iseq(iseq)) {
+ LABEL *splabel = NEW_LABEL(0);
+
+ PUSH_LABEL(ret, splabel);
+ pm_add_ensure_iseq(ret, iseq, 0, scope_node);
+ PUSH_ADJUST(ret, *location, ISEQ_COMPILE_DATA(iseq)->start_label);
+
+ PUSH_INSNL(ret, *location, jump, ISEQ_COMPILE_DATA(iseq)->start_label);
+ PUSH_ADJUST_RESTORE(ret, splabel);
+ if (!popped) PUSH_INSN(ret, *location, putnil);
+ }
+ else {
+ const rb_iseq_t *ip = iseq;
+
+ while (ip) {
+ if (!ISEQ_COMPILE_DATA(ip)) {
+ ip = 0;
+ break;
}
- if (in_node->statements != NULL) {
- PM_COMPILE_INTO_ANCHOR(body_seq, (const pm_node_t *) in_node->statements);
+ if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
+ break;
}
- else if (!popped) {
- PUSH_SYNTHETIC_PUTNIL(body_seq, iseq);
+ else if (ISEQ_BODY(ip)->type == ISEQ_TYPE_BLOCK) {
+ break;
+ }
+ else if (ISEQ_BODY(ip)->type == ISEQ_TYPE_EVAL) {
+ COMPILE_ERROR(iseq, location->line, "Invalid redo");
+ return;
}
- PUSH_INSNL(body_seq, in_location, jump, end_label);
- LABEL *next_pattern_label = NEW_LABEL(pattern_location.line);
+ ip = ISEQ_BODY(ip)->parent_iseq;
+ }
- PUSH_INSN(cond_seq, pattern_location, dup);
- pm_compile_pattern(iseq, scope_node, in_node->pattern, cond_seq, body_label, next_pattern_label, in_single_pattern, false, true, 2);
- PUSH_LABEL(cond_seq, next_pattern_label);
- LABEL_UNREMOVABLE(next_pattern_label);
+ if (ip != 0) {
+ PUSH_INSN(ret, *location, putnil);
+ PUSH_INSN1(ret, *location, throw, INT2FIX(VM_THROW_NO_ESCAPE_FLAG | TAG_REDO));
+ if (popped) PUSH_INSN(ret, *location, pop);
}
+ else {
+ COMPILE_ERROR(iseq, location->line, "Invalid redo");
+ }
+ }
+}
- if (cast->consequent != NULL) {
- // If we have an `else` clause, then this becomes our fallback (and
- // there is no need to compile in code to potentially raise an
- // error).
- const pm_else_node_t *else_node = (const pm_else_node_t *) cast->consequent;
+static inline void
+pm_compile_rescue_node(rb_iseq_t *iseq, const pm_rescue_node_t *node, const pm_node_location_t *location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+{
+ iseq_set_exception_local_table(iseq);
- PUSH_LABEL(cond_seq, else_label);
- PUSH_INSN(cond_seq, location, pop);
- PUSH_INSN(cond_seq, location, pop);
+ // First, establish the labels that we need to be able to jump to within
+ // this compilation block.
+ LABEL *exception_match_label = NEW_LABEL(location->line);
+ LABEL *rescue_end_label = NEW_LABEL(location->line);
- // Establish branch coverage for the else clause.
- if (PM_BRANCH_COVERAGE_P(iseq)) {
- rb_code_location_t branch_location = pm_code_location(scope_node, else_node->statements != NULL ? ((const pm_node_t *) else_node->statements) : ((const pm_node_t *) else_node));
- add_trace_branch_coverage(iseq, cond_seq, &branch_location, branch_location.beg_pos.column, branch_id, "else", branches);
+ // Next, compile each of the exceptions that we're going to be
+ // handling. For each one, we'll add instructions to check if the
+ // exception matches the raised one, and if it does then jump to the
+ // exception_match_label label. Otherwise it will fall through to the
+ // subsequent check. If there are no exceptions, we'll only check
+ // StandardError.
+ const pm_node_list_t *exceptions = &node->exceptions;
+
+ if (exceptions->size > 0) {
+ for (size_t index = 0; index < exceptions->size; index++) {
+ PUSH_GETLOCAL(ret, *location, LVAR_ERRINFO, 0);
+ PM_COMPILE(exceptions->nodes[index]);
+ int checkmatch_flags = VM_CHECKMATCH_TYPE_RESCUE;
+ if (PM_NODE_TYPE_P(exceptions->nodes[index], PM_SPLAT_NODE)) {
+ checkmatch_flags |= VM_CHECKMATCH_ARRAY;
}
+ PUSH_INSN1(ret, *location, checkmatch, INT2FIX(checkmatch_flags));
+ PUSH_INSNL(ret, *location, branchif, exception_match_label);
+ }
+ }
+ else {
+ PUSH_GETLOCAL(ret, *location, LVAR_ERRINFO, 0);
+ PUSH_INSN1(ret, *location, putobject, rb_eStandardError);
+ PUSH_INSN1(ret, *location, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
+ PUSH_INSNL(ret, *location, branchif, exception_match_label);
+ }
+
+ // If none of the exceptions that we are matching against matched, then
+ // we'll jump straight to the rescue_end_label label.
+ PUSH_INSNL(ret, *location, jump, rescue_end_label);
+
+ // Here we have the exception_match_label, which is where the
+ // control-flow goes in the case that one of the exceptions matched.
+ // Here we will compile the instructions to handle the exception.
+ PUSH_LABEL(ret, exception_match_label);
+ PUSH_TRACE(ret, RUBY_EVENT_RESCUE);
+
+ // If we have a reference to the exception, then we'll compile the write
+ // into the instruction sequence. This can look quite different
+ // depending on the kind of write being performed.
+ if (node->reference) {
+ DECL_ANCHOR(writes);
+ DECL_ANCHOR(cleanup);
+
+ pm_compile_target_node(iseq, node->reference, ret, writes, cleanup, scope_node, NULL);
+ PUSH_GETLOCAL(ret, *location, LVAR_ERRINFO, 0);
+
+ PUSH_SEQ(ret, writes);
+ PUSH_SEQ(ret, cleanup);
+ }
+
+ // If we have statements to execute, we'll compile them here. Otherwise
+ // we'll push nil onto the stack.
+ if (node->statements != NULL) {
+ // We'll temporarily remove the end_label location from the iseq
+ // when compiling the statements so that next/redo statements
+ // inside the body will throw to the correct place instead of
+ // jumping straight to the end of this iseq
+ LABEL *prev_end = ISEQ_COMPILE_DATA(iseq)->end_label;
+ ISEQ_COMPILE_DATA(iseq)->end_label = NULL;
+
+ PM_COMPILE((const pm_node_t *) node->statements);
+
+ // Now restore the end_label
+ ISEQ_COMPILE_DATA(iseq)->end_label = prev_end;
+ }
+ else {
+ PUSH_INSN(ret, *location, putnil);
+ }
+
+ PUSH_INSN(ret, *location, leave);
+
+ // Here we'll insert the rescue_end_label label, which is jumped to if
+ // none of the exceptions matched. It will cause the control-flow to
+ // either jump to the next rescue clause or it will fall through to the
+ // subsequent instruction returning the raised error.
+ PUSH_LABEL(ret, rescue_end_label);
+ if (node->subsequent != NULL) {
+ PM_COMPILE((const pm_node_t *) node->subsequent);
+ }
+ else {
+ PUSH_GETLOCAL(ret, *location, 1, 0);
+ }
+}
+
+static inline void
+pm_compile_return_node(rb_iseq_t *iseq, const pm_return_node_t *node, const pm_node_location_t *location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+{
+ const pm_arguments_node_t *arguments = node->arguments;
+ enum rb_iseq_type type = ISEQ_BODY(iseq)->type;
+ LABEL *splabel = 0;
+
+ const rb_iseq_t *parent_iseq = iseq;
+ enum rb_iseq_type parent_type = ISEQ_BODY(parent_iseq)->type;
+ while (parent_type == ISEQ_TYPE_RESCUE || parent_type == ISEQ_TYPE_ENSURE) {
+ if (!(parent_iseq = ISEQ_BODY(parent_iseq)->parent_iseq)) break;
+ parent_type = ISEQ_BODY(parent_iseq)->type;
+ }
+
+ switch (parent_type) {
+ case ISEQ_TYPE_TOP:
+ case ISEQ_TYPE_MAIN:
+ if (arguments) {
+ rb_warn("argument of top-level return is ignored");
+ }
+ if (parent_iseq == iseq) {
+ type = ISEQ_TYPE_METHOD;
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (type == ISEQ_TYPE_METHOD) {
+ splabel = NEW_LABEL(0);
+ PUSH_LABEL(ret, splabel);
+ PUSH_ADJUST(ret, *location, 0);
+ }
+
+ if (arguments != NULL) {
+ PM_COMPILE_NOT_POPPED((const pm_node_t *) arguments);
+ }
+ else {
+ PUSH_INSN(ret, *location, putnil);
+ }
+
+ if (type == ISEQ_TYPE_METHOD && can_add_ensure_iseq(iseq)) {
+ pm_add_ensure_iseq(ret, iseq, 1, scope_node);
+ PUSH_TRACE(ret, RUBY_EVENT_RETURN);
+ PUSH_INSN(ret, *location, leave);
+ PUSH_ADJUST_RESTORE(ret, splabel);
+ if (!popped) PUSH_INSN(ret, *location, putnil);
+ }
+ else {
+ PUSH_INSN1(ret, *location, throw, INT2FIX(TAG_RETURN));
+ if (popped) PUSH_INSN(ret, *location, pop);
+ }
+}
+
+static inline void
+pm_compile_super_node(rb_iseq_t *iseq, const pm_super_node_t *node, const pm_node_location_t *location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+{
+ DECL_ANCHOR(args);
+
+ LABEL *retry_label = NEW_LABEL(location->line);
+ LABEL *retry_end_l = NEW_LABEL(location->line);
+
+ const rb_iseq_t *previous_block = ISEQ_COMPILE_DATA(iseq)->current_block;
+ const rb_iseq_t *current_block;
+ ISEQ_COMPILE_DATA(iseq)->current_block = current_block = NULL;
+
+ PUSH_LABEL(ret, retry_label);
+ PUSH_INSN(ret, *location, putself);
+
+ int flags = 0;
+ struct rb_callinfo_kwarg *keywords = NULL;
+ int argc = pm_setup_args(node->arguments, node->block, &flags, &keywords, iseq, ret, scope_node, location);
+ bool is_forwardable = (node->arguments != NULL) && PM_NODE_FLAG_P(node->arguments, PM_ARGUMENTS_NODE_FLAGS_CONTAINS_FORWARDING);
+ flags |= VM_CALL_SUPER | VM_CALL_FCALL;
+
+ if (node->block && PM_NODE_TYPE_P(node->block, PM_BLOCK_NODE)) {
+ pm_scope_node_t next_scope_node;
+ pm_scope_node_init(node->block, &next_scope_node, scope_node);
+
+ ISEQ_COMPILE_DATA(iseq)->current_block = current_block = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, location->line);
+ pm_scope_node_destroy(&next_scope_node);
+ }
+
+ if (!node->block) {
+ iseq_set_use_block(ISEQ_BODY(iseq)->local_iseq);
+ }
+
+ if ((flags & VM_CALL_ARGS_BLOCKARG) && (flags & VM_CALL_KW_SPLAT) && !(flags & VM_CALL_KW_SPLAT_MUT)) {
+ PUSH_INSN(args, *location, splatkw);
+ }
+
+ PUSH_SEQ(ret, args);
+ if (is_forwardable && ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->param.flags.forwardable) {
+ flags |= VM_CALL_FORWARDING;
+
+ {
+ const struct rb_callinfo *callinfo = new_callinfo(iseq, 0, argc, flags, keywords, current_block != NULL);
+ PUSH_INSN2(ret, *location, invokesuperforward, callinfo, current_block);
+ }
+ }
+ else {
+ {
+ const struct rb_callinfo *callinfo = new_callinfo(iseq, 0, argc, flags, keywords, current_block != NULL);
+ PUSH_INSN2(ret, *location, invokesuper, callinfo, current_block);
+ }
+
+ }
+
+ pm_compile_retry_end_label(iseq, ret, retry_end_l);
+
+ if (popped) PUSH_INSN(ret, *location, pop);
+ ISEQ_COMPILE_DATA(iseq)->current_block = previous_block;
+ PUSH_CATCH_ENTRY(CATCH_TYPE_BREAK, retry_label, retry_end_l, current_block, retry_end_l);
+}
+
+static inline void
+pm_compile_yield_node(rb_iseq_t *iseq, const pm_yield_node_t *node, const pm_node_location_t *location, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+{
+ switch (ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->type) {
+ case ISEQ_TYPE_TOP:
+ case ISEQ_TYPE_MAIN:
+ case ISEQ_TYPE_CLASS:
+ COMPILE_ERROR(iseq, location->line, "Invalid yield");
+ return;
+ default: /* valid */;
+ }
+
+ int argc = 0;
+ int flags = 0;
+ struct rb_callinfo_kwarg *keywords = NULL;
+
+ if (node->arguments) {
+ argc = pm_setup_args(node->arguments, NULL, &flags, &keywords, iseq, ret, scope_node, location);
+ }
+
+ const struct rb_callinfo *callinfo = new_callinfo(iseq, 0, argc, flags, keywords, FALSE);
+ PUSH_INSN1(ret, *location, invokeblock, callinfo);
+
+ iseq_set_use_block(ISEQ_BODY(iseq)->local_iseq);
+ if (popped) PUSH_INSN(ret, *location, pop);
+
+ int level = 0;
+ for (const rb_iseq_t *tmp_iseq = iseq; tmp_iseq != ISEQ_BODY(iseq)->local_iseq; level++) {
+ tmp_iseq = ISEQ_BODY(tmp_iseq)->parent_iseq;
+ }
+
+ if (level > 0) access_outer_variables(iseq, level, rb_intern("yield"), true);
+}
+
+/**
+ * Compiles a prism node into instruction sequences.
+ *
+ * iseq - The current instruction sequence object (used for locals)
+ * node - The prism node to compile
+ * ret - The linked list of instructions to append instructions onto
+ * popped - True if compiling something with no side effects, so instructions don't
+ * need to be added
+ * scope_node - Stores parser and local information
+ */
+static void
+pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret, bool popped, pm_scope_node_t *scope_node)
+{
+ const pm_parser_t *parser = scope_node->parser;
+ const pm_node_location_t location = PM_NODE_START_LOCATION(parser, node);
+ int lineno = (int) location.line;
- PM_COMPILE_INTO_ANCHOR(cond_seq, (const pm_node_t *) else_node);
- PUSH_INSNL(cond_seq, location, jump, end_label);
- PUSH_INSN(cond_seq, location, putnil);
- if (popped) PUSH_INSN(cond_seq, location, putnil);
+ if (PM_NODE_TYPE_P(node, PM_BEGIN_NODE) && (((const pm_begin_node_t *) node)->statements == NULL) && (((const pm_begin_node_t *) node)->rescue_clause != NULL)) {
+ // If this node is a begin node and it has empty statements and also
+ // has a rescue clause, then the other parser considers it as
+ // starting on the same line as the rescue, as opposed to the
+ // location of the begin keyword. We replicate that behavior here.
+ lineno = (int) PM_NODE_START_LINE_COLUMN(parser, ((const pm_begin_node_t *) node)->rescue_clause).line;
+ }
+
+ if (PM_NODE_FLAG_P(node, PM_NODE_FLAG_NEWLINE) && ISEQ_COMPILE_DATA(iseq)->last_line != lineno) {
+ // If this node has the newline flag set and it is on a new line
+ // from the previous nodes that have been compiled for this ISEQ,
+ // then we need to emit a newline event.
+ int event = RUBY_EVENT_LINE;
+
+ ISEQ_COMPILE_DATA(iseq)->last_line = lineno;
+ if (lineno > 0 && ISEQ_COVERAGE(iseq) && ISEQ_LINE_COVERAGE(iseq)) {
+ event |= RUBY_EVENT_COVERAGE_LINE;
+ }
+ PUSH_TRACE(ret, event);
+ }
+
+ switch (PM_NODE_TYPE(node)) {
+ case PM_ALIAS_GLOBAL_VARIABLE_NODE:
+ // alias $foo $bar
+ // ^^^^^^^^^^^^^^^
+ pm_compile_alias_global_variable_node(iseq, (const pm_alias_global_variable_node_t *) node, &location, ret, popped, scope_node);
+ return;
+ case PM_ALIAS_METHOD_NODE:
+ // alias foo bar
+ // ^^^^^^^^^^^^^
+ pm_compile_alias_method_node(iseq, (const pm_alias_method_node_t *) node, &location, ret, popped, scope_node);
+ return;
+ case PM_AND_NODE:
+ // a and b
+ // ^^^^^^^
+ pm_compile_and_node(iseq, (const pm_and_node_t *) node, &location, ret, popped, scope_node);
+ return;
+ case PM_ARGUMENTS_NODE: {
+ // break foo
+ // ^^^
+ //
+ // These are ArgumentsNodes that are not compiled directly by their
+ // parent call nodes, used in the cases of NextNodes, ReturnNodes, and
+ // BreakNodes. They can create an array like ArrayNode.
+ const pm_arguments_node_t *cast = (const pm_arguments_node_t *) node;
+ const pm_node_list_t *elements = &cast->arguments;
+
+ if (elements->size == 1) {
+ // If we are only returning a single element through one of the jump
+ // nodes, then we will only compile that node directly.
+ PM_COMPILE(elements->nodes[0]);
}
else {
- // Otherwise, if we do not have an `else` clause, we will compile in
- // the code to handle raising an appropriate error.
- PUSH_LABEL(cond_seq, else_label);
+ pm_compile_array_node(iseq, (const pm_node_t *) cast, elements, &location, ret, popped, scope_node);
+ }
+ return;
+ }
+ case PM_ARRAY_NODE: {
+ // [foo, bar, baz]
+ // ^^^^^^^^^^^^^^^
+ const pm_array_node_t *cast = (const pm_array_node_t *) node;
+ pm_compile_array_node(iseq, (const pm_node_t *) cast, &cast->elements, &location, ret, popped, scope_node);
+ return;
+ }
+ case PM_ASSOC_NODE: {
+ // { foo: 1 }
+ // ^^^^^^
+ //
+ // foo(bar: 1)
+ // ^^^^^^
+ const pm_assoc_node_t *cast = (const pm_assoc_node_t *) node;
- // Establish branch coverage for the implicit else clause.
- add_trace_branch_coverage(iseq, cond_seq, &case_location, case_location.beg_pos.column, branch_id, "else", branches);
+ PM_COMPILE(cast->key);
+ PM_COMPILE(cast->value);
- if (in_single_pattern) {
- pm_compile_pattern_error_handler(iseq, scope_node, node, cond_seq, end_label, popped);
- }
- else {
- PUSH_INSN1(cond_seq, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
- PUSH_INSN1(cond_seq, location, putobject, rb_eNoMatchingPatternError);
- PUSH_INSN1(cond_seq, location, topn, INT2FIX(2));
- PUSH_SEND(cond_seq, location, id_core_raise, INT2FIX(2));
+ return;
+ }
+ case PM_ASSOC_SPLAT_NODE: {
+ // { **foo }
+ // ^^^^^
+ //
+ // def foo(**); bar(**); end
+ // ^^
+ const pm_assoc_splat_node_t *cast = (const pm_assoc_splat_node_t *) node;
- PUSH_INSN1(cond_seq, location, adjuststack, INT2FIX(3));
- if (!popped) PUSH_INSN(cond_seq, location, putnil);
- PUSH_INSNL(cond_seq, location, jump, end_label);
- PUSH_INSN1(cond_seq, location, dupn, INT2FIX(1));
- if (popped) PUSH_INSN(cond_seq, location, putnil);
- }
+ if (cast->value != NULL) {
+ PM_COMPILE(cast->value);
+ }
+ else if (!popped) {
+ pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_POW, 0);
+ PUSH_GETLOCAL(ret, location, index.index, index.level);
}
- // At the end of all of this compilation, we will add the code for the
- // conditions first, then the various bodies, then mark the end of the
- // entire sequence with the end label.
- PUSH_SEQ(ret, cond_seq);
- PUSH_SEQ(ret, body_seq);
- PUSH_LABEL(ret, end_label);
+ return;
+ }
+ case PM_BACK_REFERENCE_READ_NODE: {
+ // $+
+ // ^^
+ if (!popped) {
+ const pm_back_reference_read_node_t *cast = (const pm_back_reference_read_node_t *) node;
+ VALUE backref = pm_compile_back_reference_ref(cast);
+
+ PUSH_INSN2(ret, location, getspecial, INT2FIX(1), backref);
+ }
+ return;
+ }
+ case PM_BEGIN_NODE: {
+ // begin end
+ // ^^^^^^^^^
+ const pm_begin_node_t *cast = (const pm_begin_node_t *) node;
+
+ if (cast->ensure_clause) {
+ // Compiling the ensure clause will compile the rescue clause (if
+ // there is one), which will compile the begin statements.
+ pm_compile_ensure(iseq, cast, &location, ret, popped, scope_node);
+ }
+ else if (cast->rescue_clause) {
+ // Compiling rescue will compile begin statements (if applicable).
+ pm_compile_rescue(iseq, cast, &location, ret, popped, scope_node);
+ }
+ else {
+ // If there is neither ensure or rescue, the just compile the
+ // statements.
+ if (cast->statements != NULL) {
+ PM_COMPILE((const pm_node_t *) cast->statements);
+ }
+ else if (!popped) {
+ PUSH_SYNTHETIC_PUTNIL(ret, iseq);
+ }
+ }
+ return;
+ }
+ case PM_BLOCK_ARGUMENT_NODE: {
+ // foo(&bar)
+ // ^^^^
+ const pm_block_argument_node_t *cast = (const pm_block_argument_node_t *) node;
+ if (cast->expression != NULL) {
+ PM_COMPILE(cast->expression);
+ }
+ else {
+ // If there's no expression, this must be block forwarding.
+ pm_local_index_t local_index = pm_lookup_local_index(iseq, scope_node, PM_CONSTANT_AND, 0);
+ PUSH_INSN2(ret, location, getblockparamproxy, INT2FIX(local_index.index + VM_ENV_DATA_SIZE - 1), INT2FIX(local_index.level));
+ }
+ return;
+ }
+ case PM_BREAK_NODE:
+ // break
+ // ^^^^^
+ //
+ // break foo
+ // ^^^^^^^^^
+ pm_compile_break_node(iseq, (const pm_break_node_t *) node, &location, ret, popped, scope_node);
+ return;
+ case PM_CALL_NODE:
+ // foo
+ // ^^^
+ //
+ // foo.bar
+ // ^^^^^^^
+ //
+ // foo.bar() {}
+ // ^^^^^^^^^^^^
+ pm_compile_call_node(iseq, (const pm_call_node_t *) node, ret, popped, scope_node);
+ return;
+ case PM_CALL_AND_WRITE_NODE: {
+ // foo.bar &&= baz
+ // ^^^^^^^^^^^^^^^
+ const pm_call_and_write_node_t *cast = (const pm_call_and_write_node_t *) node;
+ pm_compile_call_and_or_write_node(iseq, true, cast->receiver, cast->value, cast->write_name, cast->read_name, PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION), &location, ret, popped, scope_node);
return;
}
+ case PM_CALL_OR_WRITE_NODE: {
+ // foo.bar ||= baz
+ // ^^^^^^^^^^^^^^^
+ const pm_call_or_write_node_t *cast = (const pm_call_or_write_node_t *) node;
+ pm_compile_call_and_or_write_node(iseq, false, cast->receiver, cast->value, cast->write_name, cast->read_name, PM_NODE_FLAG_P(cast, PM_CALL_NODE_FLAGS_SAFE_NAVIGATION), &location, ret, popped, scope_node);
+ return;
+ }
+ case PM_CALL_OPERATOR_WRITE_NODE:
+ // foo.bar += baz
+ // ^^^^^^^^^^^^^^^
+ //
+ // Call operator writes occur when you have a call node on the left-hand
+ // side of a write operator that is not `=`. As an example,
+ // `foo.bar *= 1`. This breaks down to caching the receiver on the
+ // stack and then performing three method calls, one to read the value,
+ // one to compute the result, and one to write the result back to the
+ // receiver.
+ pm_compile_call_operator_write_node(iseq, (const pm_call_operator_write_node_t *) node, &location, ret, popped, scope_node);
+ return;
+ case PM_CASE_NODE:
+ // case foo; when bar; end
+ // ^^^^^^^^^^^^^^^^^^^^^^^
+ pm_compile_case_node(iseq, (const pm_case_node_t *) node, &location, ret, popped, scope_node);
+ return;
+ case PM_CASE_MATCH_NODE:
+ // case foo; in bar; end
+ // ^^^^^^^^^^^^^^^^^^^^^
+ //
+ // If you use the `case` keyword to create a case match node, it will
+ // match against all of the `in` clauses until it finds one that
+ // matches. If it doesn't find one, it can optionally fall back to an
+ // `else` clause. If none is present and a match wasn't found, it will
+ // raise an appropriate error.
+ pm_compile_case_match_node(iseq, (const pm_case_match_node_t *) node, &location, ret, popped, scope_node);
+ return;
case PM_CLASS_NODE: {
// class Foo; end
// ^^^^^^^^^^^^^^
@@ -6290,7 +8853,10 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
PUSH_INSN(ret, location, putnil);
}
- PUSH_INSN3(ret, location, defineclass, ID2SYM(class_id), class_iseq, INT2FIX(flags));
+ {
+ VALUE operand = ID2SYM(class_id);
+ PUSH_INSN3(ret, location, defineclass, operand, class_iseq, INT2FIX(flags));
+ }
RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)class_iseq);
if (popped) PUSH_INSN(ret, location, pop);
@@ -6397,14 +8963,12 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache && ((parts = pm_constant_path_parts(node, scope_node)) != Qnil)) {
ISEQ_BODY(iseq)->ic_size++;
+ RB_OBJ_SET_SHAREABLE(parts);
PUSH_INSN1(ret, location, opt_getconstant_path, parts);
}
else {
DECL_ANCHOR(prefix);
- INIT_ANCHOR(prefix);
-
DECL_ANCHOR(body);
- INIT_ANCHOR(body);
pm_compile_constant_path(iseq, node, prefix, body, popped, scope_node);
if (LIST_INSN_SIZE_ZERO(prefix)) {
@@ -6454,7 +9018,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
const pm_constant_read_node_t *cast = (const pm_constant_read_node_t *) node;
VALUE name = ID2SYM(pm_constant_id_lookup(scope_node, cast->name));
- pm_compile_constant_read(iseq, name, &cast->base.location, ret, scope_node);
+ pm_compile_constant_read(iseq, name, &cast->base.location, location.node_id, ret, scope_node);
if (popped) PUSH_INSN(ret, location, pop);
return;
@@ -6558,16 +9122,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
const pm_ensure_node_t *cast = (const pm_ensure_node_t *) node;
if (cast->statements != NULL) {
- LABEL *start = NEW_LABEL(location.line);
- LABEL *end = NEW_LABEL(location.line);
- PUSH_LABEL(ret, start);
-
- LABEL *prev_end_label = ISEQ_COMPILE_DATA(iseq)->end_label;
- ISEQ_COMPILE_DATA(iseq)->end_label = end;
-
PM_COMPILE((const pm_node_t *) cast->statements);
- ISEQ_COMPILE_DATA(iseq)->end_label = prev_end_label;
- PUSH_LABEL(ret, end);
}
return;
@@ -6610,7 +9165,8 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
// 1.0
// ^^^
if (!popped) {
- PUSH_INSN1(ret, location, putobject, parse_float((const pm_float_node_t *) node));
+ VALUE operand = parse_float((const pm_float_node_t *) node);
+ PUSH_INSN1(ret, location, putobject, operand);
}
return;
}
@@ -6647,150 +9203,17 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
PUSH_CATCH_ENTRY(CATCH_TYPE_BREAK, retry_label, retry_end_l, child_iseq, retry_end_l);
return;
}
- case PM_FORWARDING_ARGUMENTS_NODE: {
+ case PM_FORWARDING_ARGUMENTS_NODE:
rb_bug("Cannot compile a ForwardingArgumentsNode directly\n");
return;
- }
- case PM_FORWARDING_SUPER_NODE: {
+ case PM_FORWARDING_SUPER_NODE:
// super
// ^^^^^
//
// super {}
// ^^^^^^^^
- const pm_forwarding_super_node_t *cast = (const pm_forwarding_super_node_t *) node;
- const rb_iseq_t *block = NULL;
-
- const rb_iseq_t *previous_block = NULL;
- LABEL *retry_label = NULL;
- LABEL *retry_end_l = NULL;
-
- if (cast->block != NULL) {
- previous_block = ISEQ_COMPILE_DATA(iseq)->current_block;
- ISEQ_COMPILE_DATA(iseq)->current_block = NULL;
-
- retry_label = NEW_LABEL(location.line);
- retry_end_l = NEW_LABEL(location.line);
-
- PUSH_LABEL(ret, retry_label);
- }
-
- PUSH_INSN(ret, location, putself);
- int flag = VM_CALL_ZSUPER | VM_CALL_SUPER | VM_CALL_FCALL;
-
- if (cast->block != NULL) {
- pm_scope_node_t next_scope_node;
- pm_scope_node_init((const pm_node_t *) cast->block, &next_scope_node, scope_node);
-
- ISEQ_COMPILE_DATA(iseq)->current_block = block = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, location.line);
- pm_scope_node_destroy(&next_scope_node);
- RB_OBJ_WRITTEN(iseq, Qundef, (VALUE) block);
- }
-
- DECL_ANCHOR(args);
- INIT_ANCHOR(args);
-
- struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq);
- const rb_iseq_t *local_iseq = body->local_iseq;
- const struct rb_iseq_constant_body *const local_body = ISEQ_BODY(local_iseq);
-
- int argc = 0;
- int depth = get_lvar_level(iseq);
-
- if (local_body->param.flags.has_lead) {
- /* required arguments */
- for (int i = 0; i < local_body->param.lead_num; i++) {
- int idx = local_body->local_table_size - i;
- PUSH_GETLOCAL(args, location, idx, depth);
- }
- argc += local_body->param.lead_num;
- }
-
- if (local_body->param.flags.has_opt) {
- /* optional arguments */
- for (int j = 0; j < local_body->param.opt_num; j++) {
- int idx = local_body->local_table_size - (argc + j);
- PUSH_GETLOCAL(args, location, idx, depth);
- }
- argc += local_body->param.opt_num;
- }
-
- if (local_body->param.flags.has_rest) {
- /* rest argument */
- int idx = local_body->local_table_size - local_body->param.rest_start;
- PUSH_GETLOCAL(args, location, idx, depth);
- PUSH_INSN1(args, location, 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;
-
- int j = 0;
- for (; j < post_len; j++) {
- int idx = local_body->local_table_size - (post_start + j);
- PUSH_GETLOCAL(args, location, idx, depth);
- }
-
- if (local_body->param.flags.has_rest) {
- // argc remains unchanged from rest branch
- PUSH_INSN1(args, location, newarray, INT2FIX(j));
- PUSH_INSN(args, location, concatarray);
- }
- else {
- argc = post_len + post_start;
- }
- }
-
- const struct rb_iseq_param_keyword *const local_keyword = local_body->param.keyword;
- if (local_body->param.flags.has_kw) {
- int local_size = local_body->local_table_size;
- argc++;
-
- PUSH_INSN1(args, location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
-
- if (local_body->param.flags.has_kwrest) {
- int idx = local_body->local_table_size - local_keyword->rest_start;
- PUSH_GETLOCAL(args, location, idx, depth);
- RUBY_ASSERT(local_keyword->num > 0);
- PUSH_SEND(args, location, rb_intern("dup"), INT2FIX(0));
- }
- else {
- PUSH_INSN1(args, location, newhash, INT2FIX(0));
- }
- int i = 0;
- for (; i < local_keyword->num; ++i) {
- ID id = local_keyword->table[i];
- int idx = local_size - get_local_var_idx(local_iseq, id);
- PUSH_INSN1(args, location, putobject, ID2SYM(id));
- PUSH_GETLOCAL(args, location, idx, depth);
- }
-
- PUSH_SEND(args, location, id_core_hash_merge_ptr, INT2FIX(i * 2 + 1));
- flag |= VM_CALL_KW_SPLAT| VM_CALL_KW_SPLAT_MUT;
- }
- else if (local_body->param.flags.has_kwrest) {
- int idx = local_body->local_table_size - local_keyword->rest_start;
- PUSH_GETLOCAL(args, location, idx, depth);
- argc++;
- flag |= VM_CALL_KW_SPLAT;
- }
-
- PUSH_SEQ(ret, args);
- PUSH_INSN2(ret, location, invokesuper, new_callinfo(iseq, 0, argc, flag, NULL, block != NULL), block);
-
- if (cast->block != NULL) {
- pm_compile_retry_end_label(iseq, ret, retry_end_l);
- PUSH_CATCH_ENTRY(CATCH_TYPE_BREAK, retry_label, retry_end_l, block, retry_end_l);
- ISEQ_COMPILE_DATA(iseq)->current_block = previous_block;
- }
-
- if (popped) PUSH_INSN(ret, location, pop);
+ pm_compile_forwarding_super_node(iseq, (const pm_forwarding_super_node_t *) node, &location, ret, popped, scope_node);
return;
- }
case PM_GLOBAL_VARIABLE_AND_WRITE_NODE: {
// $foo &&= bar
// ^^^^^^^^^^^^
@@ -6892,9 +9315,16 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
// is popped, then we know we don't need to do anything since it's
// statically known.
if (!popped) {
- VALUE value = pm_static_literal_value(iseq, node, scope_node);
- PUSH_INSN1(ret, location, duphash, value);
- RB_OBJ_WRITTEN(iseq, Qundef, value);
+ const pm_hash_node_t *cast = (const pm_hash_node_t *) node;
+
+ if (cast->elements.size == 0) {
+ PUSH_INSN1(ret, location, newhash, INT2FIX(0));
+ }
+ else {
+ VALUE value = pm_static_literal_value(iseq, node, scope_node);
+ PUSH_INSN1(ret, location, duphash, value);
+ RB_OBJ_WRITTEN(iseq, Qundef, value);
+ }
}
}
else {
@@ -6918,7 +9348,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
}
}
else {
- pm_compile_hash_elements(iseq, node, elements, ret, scope_node);
+ pm_compile_hash_elements(iseq, node, elements, 0, Qundef, false, ret, scope_node);
}
}
@@ -6934,14 +9364,15 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
// foo ? bar : baz
// ^^^^^^^^^^^^^^^
const pm_if_node_t *cast = (const pm_if_node_t *) node;
- pm_compile_conditional(iseq, &location, PM_IF_NODE, (const pm_node_t *) cast, cast->statements, cast->consequent, cast->predicate, ret, popped, scope_node);
+ pm_compile_conditional(iseq, &location, PM_IF_NODE, (const pm_node_t *) cast, cast->statements, cast->subsequent, cast->predicate, ret, popped, scope_node);
return;
}
case PM_IMAGINARY_NODE: {
// 1i
// ^^
if (!popped) {
- PUSH_INSN1(ret, location, putobject, parse_imaginary((const pm_imaginary_node_t *) node));
+ VALUE operand = parse_imaginary((const pm_imaginary_node_t *) node);
+ PUSH_INSN1(ret, location, putobject, operand);
}
return;
}
@@ -7077,7 +9508,8 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
// 1
// ^
if (!popped) {
- PUSH_INSN1(ret, location, putobject, parse_integer((const pm_integer_node_t *) node));
+ VALUE operand = parse_integer((const pm_integer_node_t *) node);
+ PUSH_INSN1(ret, location, putobject, operand);
}
return;
}
@@ -7111,7 +9543,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
pm_scope_node_t next_scope_node;
pm_scope_node_init(node, &next_scope_node, scope_node);
- block_iseq = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, location.line);
+ block_iseq = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_PLAIN, location.line);
pm_scope_node_destroy(&next_scope_node);
ISEQ_COMPILE_DATA(iseq)->current_block = block_iseq;
@@ -7155,7 +9587,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
}
else {
const pm_interpolated_string_node_t *cast = (const pm_interpolated_string_node_t *) node;
- int length = pm_interpolated_node_compile(iseq, &cast->parts, &location, ret, popped, scope_node, NULL, NULL);
+ int length = pm_interpolated_node_compile(iseq, &cast->parts, &location, ret, popped, scope_node, NULL, NULL, PM_NODE_FLAG_P(cast, PM_INTERPOLATED_STRING_NODE_FLAGS_MUTABLE), PM_NODE_FLAG_P(cast, PM_INTERPOLATED_STRING_NODE_FLAGS_FROZEN));
if (length > 1) PUSH_INSN1(ret, location, concatstrings, INT2FIX(length));
if (popped) PUSH_INSN(ret, location, pop);
}
@@ -7166,25 +9598,17 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
// :"foo #{bar}"
// ^^^^^^^^^^^^^
const pm_interpolated_symbol_node_t *cast = (const pm_interpolated_symbol_node_t *) node;
+ int length = pm_interpolated_node_compile(iseq, &cast->parts, &location, ret, popped, scope_node, NULL, NULL, false, false);
- if (PM_NODE_FLAG_P(node, PM_NODE_FLAG_STATIC_LITERAL)) {
- if (!popped) {
- VALUE symbol = pm_static_literal_value(iseq, node, scope_node);
- PUSH_INSN1(ret, location, putobject, symbol);
- }
+ if (length > 1) {
+ PUSH_INSN1(ret, location, concatstrings, INT2FIX(length));
}
- else {
- int length = pm_interpolated_node_compile(iseq, &cast->parts, &location, ret, popped, scope_node, NULL, NULL);
- if (length > 1) {
- PUSH_INSN1(ret, location, concatstrings, INT2FIX(length));
- }
- if (!popped) {
- PUSH_INSN(ret, location, intern);
- }
- else {
- PUSH_INSN(ret, location, pop);
- }
+ if (!popped) {
+ PUSH_INSN(ret, location, intern);
+ }
+ else {
+ PUSH_INSN(ret, location, pop);
}
return;
@@ -7196,7 +9620,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
PUSH_INSN(ret, location, putself);
- int length = pm_interpolated_node_compile(iseq, &cast->parts, &location, ret, false, scope_node, NULL, NULL);
+ int length = pm_interpolated_node_compile(iseq, &cast->parts, &location, ret, false, scope_node, NULL, NULL, false, false);
if (length > 1) PUSH_INSN1(ret, location, concatstrings, INT2FIX(length));
PUSH_SEND_WITH_FLAG(ret, location, idBackquote, INT2NUM(1), INT2FIX(VM_CALL_FCALL | VM_CALL_ARGS_SIMPLE));
@@ -7208,7 +9632,19 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
// -> { it }
// ^^
if (!popped) {
- PUSH_GETLOCAL(ret, location, scope_node->local_table_for_iseq_size, 0);
+ pm_scope_node_t *current_scope_node = scope_node;
+ int level = 0;
+
+ while (current_scope_node) {
+ if (current_scope_node->parameters && PM_NODE_TYPE_P(current_scope_node->parameters, PM_IT_PARAMETERS_NODE)) {
+ PUSH_GETLOCAL(ret, location, current_scope_node->local_table_for_iseq_size, level);
+ return;
+ }
+
+ current_scope_node = current_scope_node->previous;
+ level++;
+ }
+ rb_bug("Local `it` does not exist");
}
return;
@@ -7365,7 +9801,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
LABEL *matched_label = NEW_LABEL(location.line);
LABEL *unmatched_label = NEW_LABEL(location.line);
LABEL *done_label = NEW_LABEL(location.line);
- pm_compile_pattern(iseq, scope_node, cast->pattern, ret, matched_label, unmatched_label, false, false, true, 2);
+ pm_compile_pattern(iseq, scope_node, cast->pattern, ret, matched_label, unmatched_label, false, true, 2);
// If the pattern did not match, then compile the necessary instructions
// to handle pushing false onto the stack, then jump to the end.
@@ -7387,7 +9823,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
PUSH_LABEL(ret, done_label);
return;
}
- case PM_MATCH_REQUIRED_NODE: {
+ case PM_MATCH_REQUIRED_NODE:
// foo => bar
// ^^^^^^^^^^
//
@@ -7399,52 +9835,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
// This is somewhat analogous to compiling a case match statement with a
// single pattern. In both cases, if the pattern fails it should
// immediately raise an error.
- const pm_match_required_node_t *cast = (const pm_match_required_node_t *) node;
-
- LABEL *matched_label = NEW_LABEL(location.line);
- LABEL *unmatched_label = NEW_LABEL(location.line);
- LABEL *done_label = NEW_LABEL(location.line);
-
- // First, we're going to push a bunch of stuff onto the stack that is
- // going to serve as our scratch space.
- PUSH_INSN(ret, location, putnil); // key error key
- PUSH_INSN(ret, location, putnil); // key error matchee
- PUSH_INSN1(ret, location, putobject, Qfalse); // key error?
- PUSH_INSN(ret, location, putnil); // error string
- PUSH_INSN(ret, location, putnil); // deconstruct cache
-
- // Next we're going to compile the value expression such that it's on
- // the stack.
- PM_COMPILE_NOT_POPPED(cast->value);
-
- // Here we'll dup it so that it can be used for comparison, but also be
- // used for error handling.
- PUSH_INSN(ret, location, dup);
-
- // Next we'll compile the pattern. We indicate to the pm_compile_pattern
- // function that this is the only pattern that will be matched against
- // through the in_single_pattern parameter. We also indicate that the
- // value to compare against is 2 slots from the top of the stack (the
- // base_index parameter).
- pm_compile_pattern(iseq, scope_node, cast->pattern, ret, matched_label, unmatched_label, true, false, true, 2);
-
- // If the pattern did not match the value, then we're going to compile
- // in our error handler code. This will determine which error to raise
- // and raise it.
- PUSH_LABEL(ret, unmatched_label);
- pm_compile_pattern_error_handler(iseq, scope_node, node, ret, done_label, popped);
-
- // If the pattern did match, we'll clean up the values we've pushed onto
- // the stack and then push nil onto the stack if it's not popped.
- PUSH_LABEL(ret, matched_label);
- PUSH_INSN1(ret, location, adjuststack, INT2FIX(6));
- if (!popped) PUSH_INSN(ret, location, putnil);
- PUSH_INSNL(ret, location, jump, done_label);
-
- PUSH_LABEL(ret, done_label);
+ pm_compile_match_required_node(iseq, (const pm_match_required_node_t *) node, &location, ret, popped, scope_node);
return;
- }
- case PM_MATCH_WRITE_NODE: {
+ case PM_MATCH_WRITE_NODE:
// /(?<foo>foo)/ =~ bar
// ^^^^^^^^^^^^^^^^^^^^
//
@@ -7453,81 +9846,11 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
// operator, and some value on the right. The nodes themselves simply
// wrap the call with the local variable targets that will be written
// when the call is executed.
- const pm_match_write_node_t *cast = (const pm_match_write_node_t *) node;
- LABEL *fail_label = NEW_LABEL(location.line);
- LABEL *end_label = NEW_LABEL(location.line);
-
- // First, we'll compile the call so that all of its instructions are
- // present. Then we'll compile all of the local variable targets.
- PM_COMPILE_NOT_POPPED((const pm_node_t *) cast->call);
-
- // Now, check if the match was successful. If it was, then we'll
- // continue on and assign local variables. Otherwise we'll skip over the
- // assignment code.
- PUSH_INSN1(ret, location, getglobal, rb_id2sym(idBACKREF));
- PUSH_INSN(ret, location, dup);
- PUSH_INSNL(ret, location, branchunless, fail_label);
-
- // If there's only a single local variable target, we can skip some of
- // the bookkeeping, so we'll put a special branch here.
- size_t targets_count = cast->targets.size;
-
- if (targets_count == 1) {
- const pm_node_t *target = cast->targets.nodes[0];
- RUBY_ASSERT(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_TARGET_NODE));
-
- const pm_local_variable_target_node_t *local_target = (const pm_local_variable_target_node_t *) target;
- pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, local_target->name, local_target->depth);
-
- PUSH_INSN1(ret, location, putobject, rb_id2sym(pm_constant_id_lookup(scope_node, local_target->name)));
- PUSH_SEND(ret, location, idAREF, INT2FIX(1));
- PUSH_LABEL(ret, fail_label);
- PUSH_SETLOCAL(ret, location, index.index, index.level);
- if (popped) PUSH_INSN(ret, location, pop);
- return;
- }
-
- DECL_ANCHOR(fail_anchor);
- INIT_ANCHOR(fail_anchor);
-
- // Otherwise there is more than one local variable target, so we'll need
- // to do some bookkeeping.
- for (size_t targets_index = 0; targets_index < targets_count; targets_index++) {
- const pm_node_t *target = cast->targets.nodes[targets_index];
- RUBY_ASSERT(PM_NODE_TYPE_P(target, PM_LOCAL_VARIABLE_TARGET_NODE));
-
- const pm_local_variable_target_node_t *local_target = (const pm_local_variable_target_node_t *) target;
- pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, local_target->name, local_target->depth);
-
- if (((size_t) targets_index) < (targets_count - 1)) {
- PUSH_INSN(ret, location, dup);
- }
- PUSH_INSN1(ret, location, putobject, rb_id2sym(pm_constant_id_lookup(scope_node, local_target->name)));
- PUSH_SEND(ret, location, idAREF, INT2FIX(1));
- PUSH_SETLOCAL(ret, location, index.index, index.level);
-
- PUSH_INSN(fail_anchor, location, putnil);
- PUSH_SETLOCAL(fail_anchor, location, index.index, index.level);
- }
-
- // Since we matched successfully, now we'll jump to the end.
- PUSH_INSNL(ret, location, jump, end_label);
-
- // In the case that the match failed, we'll loop through each local
- // variable target and set all of them to `nil`.
- PUSH_LABEL(ret, fail_label);
- PUSH_INSN(ret, location, pop);
- PUSH_SEQ(ret, fail_anchor);
-
- // Finally, we can push the end label for either case.
- PUSH_LABEL(ret, end_label);
- if (popped) PUSH_INSN(ret, location, pop);
+ pm_compile_match_write_node(iseq, (const pm_match_write_node_t *) node, &location, ret, popped, scope_node);
return;
- }
- case PM_MISSING_NODE: {
+ case PM_MISSING_NODE:
rb_bug("A pm_missing_node_t should not exist in prism's AST.");
return;
- }
case PM_MODULE_NODE: {
// module Foo; end
// ^^^^^^^^^^^^^^^
@@ -7571,10 +9894,7 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
const pm_multi_write_node_t *cast = (const pm_multi_write_node_t *) node;
DECL_ANCHOR(writes);
- INIT_ANCHOR(writes);
-
DECL_ANCHOR(cleanup);
- INIT_ANCHOR(cleanup);
pm_multi_target_state_t state = { 0 };
state.position = popped ? 0 : 1;
@@ -7597,96 +9917,14 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
PUSH_SEQ(ret, cleanup);
return;
}
- case PM_NEXT_NODE: {
+ case PM_NEXT_NODE:
// next
// ^^^^
//
// next foo
// ^^^^^^^^
- const pm_next_node_t *cast = (const pm_next_node_t *) node;
-
- if (ISEQ_COMPILE_DATA(iseq)->redo_label != 0 && can_add_ensure_iseq(iseq)) {
- LABEL *splabel = NEW_LABEL(0);
- PUSH_LABEL(ret, splabel);
-
- if (cast->arguments) {
- PM_COMPILE_NOT_POPPED((const pm_node_t *) cast->arguments);
- }
- else {
- PUSH_INSN(ret, location, putnil);
- }
- pm_add_ensure_iseq(ret, iseq, 0, scope_node);
-
- PUSH_ADJUST(ret, location, ISEQ_COMPILE_DATA(iseq)->redo_label);
- PUSH_INSNL(ret, location, jump, ISEQ_COMPILE_DATA(iseq)->start_label);
-
- PUSH_ADJUST_RESTORE(ret, splabel);
- if (!popped) PUSH_INSN(ret, location, putnil);
- }
- else if (ISEQ_COMPILE_DATA(iseq)->end_label && can_add_ensure_iseq(iseq)) {
- LABEL *splabel = NEW_LABEL(0);
-
- PUSH_LABEL(ret, splabel);
- PUSH_ADJUST(ret, location, ISEQ_COMPILE_DATA(iseq)->start_label);
-
- if (cast->arguments != NULL) {
- PM_COMPILE_NOT_POPPED((const pm_node_t *) cast->arguments);
- }
- else {
- PUSH_INSN(ret, location, putnil);
- }
-
- pm_add_ensure_iseq(ret, iseq, 0, scope_node);
- PUSH_INSNL(ret, location, jump, ISEQ_COMPILE_DATA(iseq)->end_label);
- PUSH_ADJUST_RESTORE(ret, splabel);
- splabel->unremovable = FALSE;
-
- if (!popped) PUSH_INSN(ret, location, putnil);
- }
- else {
- const rb_iseq_t *ip = iseq;
- unsigned long throw_flag = 0;
-
- while (ip) {
- if (!ISEQ_COMPILE_DATA(ip)) {
- ip = 0;
- break;
- }
-
- throw_flag = VM_THROW_NO_ESCAPE_FLAG;
- if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
- /* while loop */
- break;
- }
- else if (ISEQ_BODY(ip)->type == ISEQ_TYPE_BLOCK) {
- break;
- }
- else if (ISEQ_BODY(ip)->type == ISEQ_TYPE_EVAL) {
- COMPILE_ERROR(iseq, location.line, "Can't escape from eval with next");
- return;
- }
-
- ip = ISEQ_BODY(ip)->parent_iseq;
- }
- if (ip != 0) {
- if (cast->arguments) {
- PM_COMPILE_NOT_POPPED((const pm_node_t *) cast->arguments);
- }
- else {
- PUSH_INSN(ret, location, putnil);
- }
-
- PUSH_INSN1(ret, location, throw, INT2FIX(throw_flag | TAG_NEXT));
- if (popped) PUSH_INSN(ret, location, pop);
- }
- else {
- COMPILE_ERROR(iseq, location.line, "Invalid next");
- return;
- }
- }
-
+ pm_compile_next_node(iseq, (const pm_next_node_t *) node, &location, ret, popped, scope_node);
return;
- }
case PM_NIL_NODE: {
// nil
// ^^^
@@ -7706,10 +9944,11 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
// $1
// ^^
if (!popped) {
- uint32_t reference_number = ((const pm_numbered_reference_read_node_t *) node)->number;
+ const pm_numbered_reference_read_node_t *cast = (const pm_numbered_reference_read_node_t *) node;
- if (reference_number > 0) {
- PUSH_INSN2(ret, location, getspecial, INT2FIX(1), INT2FIX(reference_number << 1));
+ if (cast->number != 0) {
+ VALUE ref = pm_compile_numbered_reference_ref(cast);
+ PUSH_INSN2(ret, location, getspecial, INT2FIX(1), ref);
}
else {
PUSH_INSN(ret, location, putnil);
@@ -7776,11 +10015,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
// anchors and then join them in the correct order into the resulting
// anchor.
DECL_ANCHOR(inner_pre);
- INIT_ANCHOR(inner_pre);
scope_node->pre_execution_anchor = inner_pre;
DECL_ANCHOR(inner_body);
- INIT_ANCHOR(inner_body);
if (cast->statements != NULL) {
const pm_node_list_t *body = &cast->statements->body;
@@ -7842,23 +10079,24 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
exclude_end
);
+ RB_OBJ_SET_SHAREABLE(val);
PUSH_INSN1(ret, location, putobject, val);
}
}
else {
- if (cast->left == NULL) {
- PUSH_INSN(ret, location, putnil);
- }
- else {
+ if (cast->left != NULL) {
PM_COMPILE(cast->left);
}
-
- if (cast->right == NULL) {
+ else if (!popped) {
PUSH_INSN(ret, location, putnil);
}
- else {
+
+ if (cast->right != NULL) {
PM_COMPILE(cast->right);
}
+ else if (!popped) {
+ PUSH_INSN(ret, location, putnil);
+ }
if (!popped) {
PUSH_INSN1(ret, location, newrange, INT2FIX(exclude_end ? 1 : 0));
@@ -7874,66 +10112,11 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
}
return;
}
- case PM_REDO_NODE: {
+ case PM_REDO_NODE:
// redo
// ^^^^
- if (ISEQ_COMPILE_DATA(iseq)->redo_label && can_add_ensure_iseq(iseq)) {
- LABEL *splabel = NEW_LABEL(0);
-
- PUSH_LABEL(ret, splabel);
- PUSH_ADJUST(ret, location, ISEQ_COMPILE_DATA(iseq)->redo_label);
- pm_add_ensure_iseq(ret, iseq, 0, scope_node);
-
- PUSH_INSNL(ret, location, jump, ISEQ_COMPILE_DATA(iseq)->redo_label);
- PUSH_ADJUST_RESTORE(ret, splabel);
- if (!popped) PUSH_INSN(ret, location, putnil);
- }
- else if (ISEQ_BODY(iseq)->type != ISEQ_TYPE_EVAL && ISEQ_COMPILE_DATA(iseq)->start_label && can_add_ensure_iseq(iseq)) {
- LABEL *splabel = NEW_LABEL(0);
-
- PUSH_LABEL(ret, splabel);
- pm_add_ensure_iseq(ret, iseq, 0, scope_node);
- PUSH_ADJUST(ret, location, ISEQ_COMPILE_DATA(iseq)->start_label);
-
- PUSH_INSNL(ret, location, jump, ISEQ_COMPILE_DATA(iseq)->start_label);
- PUSH_ADJUST_RESTORE(ret, splabel);
- if (!popped) PUSH_INSN(ret, location, putnil);
- }
- else {
- const rb_iseq_t *ip = iseq;
-
- while (ip) {
- if (!ISEQ_COMPILE_DATA(ip)) {
- ip = 0;
- break;
- }
-
- if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
- break;
- }
- else if (ISEQ_BODY(ip)->type == ISEQ_TYPE_BLOCK) {
- break;
- }
- else if (ISEQ_BODY(ip)->type == ISEQ_TYPE_EVAL) {
- COMPILE_ERROR(iseq, location.line, "Can't escape from eval with redo");
- return;
- }
-
- ip = ISEQ_BODY(ip)->parent_iseq;
- }
-
- if (ip != 0) {
- PUSH_INSN(ret, location, putnil);
- PUSH_INSN1(ret, location, throw, INT2FIX(VM_THROW_NO_ESCAPE_FLAG | TAG_REDO));
- if (popped) PUSH_INSN(ret, location, pop);
- }
- else {
- COMPILE_ERROR(iseq, location.line, "Invalid redo");
- return;
- }
- }
+ pm_compile_redo_node(iseq, &location, ret, popped, scope_node);
return;
- }
case PM_REGULAR_EXPRESSION_NODE: {
// /foo/
// ^^^^^
@@ -7943,106 +10126,11 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
}
return;
}
- case PM_RESCUE_NODE: {
+ case PM_RESCUE_NODE:
// begin; rescue; end
// ^^^^^^^
- const pm_rescue_node_t *cast = (const pm_rescue_node_t *) node;
- iseq_set_exception_local_table(iseq);
-
- // First, establish the labels that we need to be able to jump to within
- // this compilation block.
- LABEL *exception_match_label = NEW_LABEL(location.line);
- LABEL *rescue_end_label = NEW_LABEL(location.line);
-
- // Next, compile each of the exceptions that we're going to be
- // handling. For each one, we'll add instructions to check if the
- // exception matches the raised one, and if it does then jump to the
- // exception_match_label label. Otherwise it will fall through to the
- // subsequent check. If there are no exceptions, we'll only check
- // StandardError.
- const pm_node_list_t *exceptions = &cast->exceptions;
-
- if (exceptions->size > 0) {
- for (size_t index = 0; index < exceptions->size; index++) {
- PUSH_GETLOCAL(ret, location, LVAR_ERRINFO, 0);
- PM_COMPILE(exceptions->nodes[index]);
- int checkmatch_flags = VM_CHECKMATCH_TYPE_RESCUE;
- if (PM_NODE_TYPE_P(exceptions->nodes[index], PM_SPLAT_NODE)) {
- checkmatch_flags |= VM_CHECKMATCH_ARRAY;
- }
- PUSH_INSN1(ret, location, checkmatch, INT2FIX(checkmatch_flags));
- PUSH_INSNL(ret, location, branchif, exception_match_label);
- }
- }
- else {
- PUSH_GETLOCAL(ret, location, LVAR_ERRINFO, 0);
- PUSH_INSN1(ret, location, putobject, rb_eStandardError);
- PUSH_INSN1(ret, location, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
- PUSH_INSNL(ret, location, branchif, exception_match_label);
- }
-
- // If none of the exceptions that we are matching against matched, then
- // we'll jump straight to the rescue_end_label label.
- PUSH_INSNL(ret, location, jump, rescue_end_label);
-
- // Here we have the exception_match_label, which is where the
- // control-flow goes in the case that one of the exceptions matched.
- // Here we will compile the instructions to handle the exception.
- PUSH_LABEL(ret, exception_match_label);
- PUSH_TRACE(ret, RUBY_EVENT_RESCUE);
-
- // If we have a reference to the exception, then we'll compile the write
- // into the instruction sequence. This can look quite different
- // depending on the kind of write being performed.
- if (cast->reference) {
- DECL_ANCHOR(writes);
- INIT_ANCHOR(writes);
-
- DECL_ANCHOR(cleanup);
- INIT_ANCHOR(cleanup);
-
- pm_compile_target_node(iseq, cast->reference, ret, writes, cleanup, scope_node, NULL);
- PUSH_GETLOCAL(ret, location, LVAR_ERRINFO, 0);
-
- PUSH_SEQ(ret, writes);
- PUSH_SEQ(ret, cleanup);
- }
-
- // If we have statements to execute, we'll compile them here. Otherwise
- // we'll push nil onto the stack.
- if (cast->statements) {
- // We'll temporarily remove the end_label location from the iseq
- // when compiling the statements so that next/redo statements
- // inside the body will throw to the correct place instead of
- // jumping straight to the end of this iseq
- LABEL *prev_end = ISEQ_COMPILE_DATA(iseq)->end_label;
- ISEQ_COMPILE_DATA(iseq)->end_label = NULL;
-
- PM_COMPILE((const pm_node_t *) cast->statements);
-
- // Now restore the end_label
- ISEQ_COMPILE_DATA(iseq)->end_label = prev_end;
- }
- else {
- PUSH_INSN(ret, location, putnil);
- }
-
- PUSH_INSN(ret, location, leave);
-
- // Here we'll insert the rescue_end_label label, which is jumped to if
- // none of the exceptions matched. It will cause the control-flow to
- // either jump to the next rescue clause or it will fall through to the
- // subsequent instruction returning the raised error.
- PUSH_LABEL(ret, rescue_end_label);
- if (cast->consequent) {
- PM_COMPILE((const pm_node_t *) cast->consequent);
- }
- else {
- PUSH_GETLOCAL(ret, location, 1, 0);
- }
-
+ pm_compile_rescue_node(iseq, (const pm_rescue_node_t *) node, &location, ret, popped, scope_node);
return;
- }
case PM_RESCUE_MODIFIER_NODE: {
// foo rescue bar
// ^^^^^^^^^^^^^^
@@ -8066,9 +10154,11 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
lstart->rescued = LABEL_RESCUE_BEG;
lend->rescued = LABEL_RESCUE_END;
+
PUSH_LABEL(ret, lstart);
PM_COMPILE_NOT_POPPED(cast->expression);
PUSH_LABEL(ret, lend);
+
PUSH_INSN(ret, location, nop);
PUSH_LABEL(ret, lcont);
if (popped) PUSH_INSN(ret, location, pop);
@@ -8077,76 +10167,14 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
PUSH_CATCH_ENTRY(CATCH_TYPE_RETRY, lend, lcont, NULL, lstart);
return;
}
- case PM_RETURN_NODE: {
+ case PM_RETURN_NODE:
// return
// ^^^^^^
//
// return 1
// ^^^^^^^^
- const pm_return_node_t *cast = (const pm_return_node_t *) node;
- const pm_arguments_node_t *arguments = cast->arguments;
-
- if (PM_NODE_FLAG_P(cast, PM_RETURN_NODE_FLAGS_REDUNDANT)) {
- if (arguments) {
- PM_COMPILE_NOT_POPPED((const pm_node_t *) arguments);
- }
- else {
- PUSH_INSN(ret, location, putnil);
- }
- }
- else {
- enum rb_iseq_type type = ISEQ_BODY(iseq)->type;
- LABEL *splabel = 0;
-
- const rb_iseq_t *parent_iseq = iseq;
- enum rb_iseq_type parent_type = ISEQ_BODY(parent_iseq)->type;
- while (parent_type == ISEQ_TYPE_RESCUE || parent_type == ISEQ_TYPE_ENSURE) {
- if (!(parent_iseq = ISEQ_BODY(parent_iseq)->parent_iseq)) break;
- parent_type = ISEQ_BODY(parent_iseq)->type;
- }
-
- switch (parent_type) {
- case ISEQ_TYPE_TOP:
- case ISEQ_TYPE_MAIN:
- if (arguments) {
- rb_warn("argument of top-level return is ignored");
- }
- if (parent_iseq == iseq) {
- type = ISEQ_TYPE_METHOD;
- }
- break;
- default:
- break;
- }
-
- if (type == ISEQ_TYPE_METHOD) {
- splabel = NEW_LABEL(0);
- PUSH_LABEL(ret, splabel);
- PUSH_ADJUST(ret, location, 0);
- }
-
- if (arguments) {
- PM_COMPILE_NOT_POPPED((const pm_node_t *) arguments);
- }
- else {
- PUSH_INSN(ret, location, putnil);
- }
-
- if (type == ISEQ_TYPE_METHOD && can_add_ensure_iseq(iseq)) {
- pm_add_ensure_iseq(ret, iseq, 1, scope_node);
- PUSH_TRACE(ret, RUBY_EVENT_RETURN);
- PUSH_INSN(ret, location, leave);
- PUSH_ADJUST_RESTORE(ret, splabel);
- if (!popped) PUSH_INSN(ret, location, putnil);
- }
- else {
- PUSH_INSN1(ret, location, throw, INT2FIX(TAG_RETURN));
- if (popped) PUSH_INSN(ret, location, pop);
- }
- }
-
+ pm_compile_return_node(iseq, (const pm_return_node_t *) node, &location, ret, popped, scope_node);
return;
- }
case PM_RETRY_NODE: {
// retry
// ^^^^^
@@ -8161,901 +10189,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
}
return;
}
- case PM_SCOPE_NODE: {
- pm_scope_node_t *scope_node = (pm_scope_node_t *) node;
- pm_constant_id_list_t *locals = &scope_node->locals;
-
- pm_parameters_node_t *parameters_node = NULL;
- pm_node_list_t *keywords_list = NULL;
- pm_node_list_t *optionals_list = NULL;
- pm_node_list_t *posts_list = NULL;
- pm_node_list_t *requireds_list = NULL;
- pm_node_list_t *block_locals = NULL;
- bool trailing_comma = false;
-
- struct rb_iseq_constant_body *body = ISEQ_BODY(iseq);
-
- if (PM_NODE_TYPE_P(scope_node->ast_node, PM_CLASS_NODE)) {
- ADD_TRACE(ret, RUBY_EVENT_CLASS);
- }
-
- if (scope_node->parameters) {
- switch (PM_NODE_TYPE(scope_node->parameters)) {
- case PM_BLOCK_PARAMETERS_NODE: {
- pm_block_parameters_node_t *cast = (pm_block_parameters_node_t *) scope_node->parameters;
- parameters_node = cast->parameters;
- block_locals = &cast->locals;
-
- if (parameters_node) {
- if (parameters_node->rest && PM_NODE_TYPE_P(parameters_node->rest, PM_IMPLICIT_REST_NODE)) {
- trailing_comma = true;
- }
- }
- break;
- }
- case PM_PARAMETERS_NODE: {
- parameters_node = (pm_parameters_node_t *) scope_node->parameters;
- break;
- }
- case PM_NUMBERED_PARAMETERS_NODE: {
- uint32_t maximum = ((const pm_numbered_parameters_node_t *) scope_node->parameters)->maximum;
- body->param.lead_num = maximum;
- body->param.flags.ambiguous_param0 = maximum == 1;
- break;
- }
- case PM_IT_PARAMETERS_NODE:
- body->param.lead_num = 1;
- body->param.flags.ambiguous_param0 = true;
- break;
- default:
- rb_bug("Unexpected node type for parameters: %s", pm_node_type_to_str(PM_NODE_TYPE(node)));
- }
- }
-
- struct rb_iseq_param_keyword *keyword = NULL;
-
- if (parameters_node) {
- optionals_list = &parameters_node->optionals;
- requireds_list = &parameters_node->requireds;
- keywords_list = &parameters_node->keywords;
- posts_list = &parameters_node->posts;
- }
- else if (scope_node->parameters && (PM_NODE_TYPE_P(scope_node->parameters, PM_NUMBERED_PARAMETERS_NODE) || PM_NODE_TYPE_P(scope_node->parameters, PM_IT_PARAMETERS_NODE))) {
- body->param.opt_num = 0;
- }
- else {
- body->param.lead_num = 0;
- body->param.opt_num = 0;
- }
-
- //********STEP 1**********
- // Goal: calculate the table size for the locals, accounting for
- // hidden variables and multi target nodes
- size_t locals_size = locals->size;
-
- // Index lookup table buffer size is only the number of the locals
- st_table *index_lookup_table = st_init_numtable();
-
- int table_size = (int) locals_size;
-
- // For nodes have a hidden iteration variable. We add that to the local
- // table size here.
- if (PM_NODE_TYPE_P(scope_node->ast_node, PM_FOR_NODE)) table_size++;
-
- if (keywords_list && keywords_list->size) {
- table_size++;
- }
-
- if (requireds_list) {
- for (size_t i = 0; i < requireds_list->size; i++) {
- // For each MultiTargetNode, we're going to have one
- // additional anonymous local not represented in the locals table
- // We want to account for this in our table size
- pm_node_t *required = requireds_list->nodes[i];
- if (PM_NODE_TYPE_P(required, PM_MULTI_TARGET_NODE)) {
- table_size++;
- }
- else if (PM_NODE_TYPE_P(required, PM_REQUIRED_PARAMETER_NODE)) {
- if (PM_NODE_FLAG_P(required, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
- table_size++;
- }
- }
- }
- }
-
- // If we have the `it` implicit local variable, we need to account for
- // it in the local table size.
- if (scope_node->parameters != NULL && PM_NODE_TYPE_P(scope_node->parameters, PM_IT_PARAMETERS_NODE)) {
- table_size++;
- }
-
- // Ensure there is enough room in the local table for any
- // parameters that have been repeated
- // ex: def underscore_parameters(_, _ = 1, _ = 2); _; end
- // ^^^^^^^^^^^^
- if (optionals_list && optionals_list->size) {
- for (size_t i = 0; i < optionals_list->size; i++) {
- pm_node_t * node = optionals_list->nodes[i];
- if (PM_NODE_FLAG_P(node, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
- table_size++;
- }
- }
- }
-
- // If we have an anonymous "rest" node, we'll need to increase the local
- // table size to take it in to account.
- // def m(foo, *, bar)
- // ^
- if (parameters_node) {
- if (parameters_node->rest) {
- if (!(PM_NODE_TYPE_P(parameters_node->rest, PM_IMPLICIT_REST_NODE))) {
- if (!((const pm_rest_parameter_node_t *) parameters_node->rest)->name || PM_NODE_FLAG_P(parameters_node->rest, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
- table_size++;
- }
- }
- }
-
- // def foo(_, **_); _; end
- // ^^^
- if (parameters_node->keyword_rest) {
- // def foo(...); end
- // ^^^
- // When we have a `...` as the keyword_rest, it's a forwarding_parameter_node and
- // we need to leave space for 4 locals: *, **, &, ...
- if (PM_NODE_TYPE_P(parameters_node->keyword_rest, PM_FORWARDING_PARAMETER_NODE)) {
- table_size += 4;
- }
- else {
- const pm_keyword_rest_parameter_node_t *kw_rest = (const pm_keyword_rest_parameter_node_t *) parameters_node->keyword_rest;
-
- // If it's anonymous or repeated, then we need to allocate stack space
- if (!kw_rest->name || PM_NODE_FLAG_P(kw_rest, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
- table_size++;
- }
- }
- }
- }
-
- if (posts_list) {
- for (size_t i = 0; i < posts_list->size; i++) {
- // For each MultiTargetNode, we're going to have one
- // additional anonymous local not represented in the locals table
- // We want to account for this in our table size
- pm_node_t *required = posts_list->nodes[i];
- if (PM_NODE_TYPE_P(required, PM_MULTI_TARGET_NODE) || PM_NODE_FLAG_P(required, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
- table_size++;
- }
- }
- }
-
- if (keywords_list && keywords_list->size) {
- for (size_t i = 0; i < keywords_list->size; i++) {
- pm_node_t *keyword_parameter_node = keywords_list->nodes[i];
- if (PM_NODE_FLAG_P(keyword_parameter_node, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
- table_size++;
- }
- }
- }
-
- if (parameters_node && parameters_node->block) {
- const pm_block_parameter_node_t *block_node = (const pm_block_parameter_node_t *) parameters_node->block;
-
- if (PM_NODE_FLAG_P(block_node, PM_PARAMETER_FLAGS_REPEATED_PARAMETER) || !block_node->name) {
- table_size++;
- }
- }
-
- // We can create local_table_for_iseq with the correct size
- VALUE idtmp = 0;
- rb_ast_id_table_t *local_table_for_iseq = ALLOCV(idtmp, sizeof(rb_ast_id_table_t) + table_size * sizeof(ID));
- local_table_for_iseq->size = table_size;
-
- //********END OF STEP 1**********
-
- //********STEP 2**********
- // Goal: populate iv index table as well as local table, keeping the
- // layout of the local table consistent with the layout of the
- // stack when calling the method
- //
- // Do a first pass on all of the parameters, setting their values in
- // the local_table_for_iseq, _except_ for Multis who get a hidden
- // variable in this step, and will get their names inserted in step 3
-
- // local_index is a cursor that keeps track of the current
- // index into local_table_for_iseq. The local table is actually a list,
- // and the order of that list must match the order of the items pushed
- // on the stack. We need to take in to account things pushed on the
- // stack that _might not have a name_ (for example array destructuring).
- // This index helps us know which item we're dealing with and also give
- // those anonymous items temporary names (as below)
- int local_index = 0;
-
- // Here we figure out local table indices and insert them in to the
- // index lookup table and local tables.
- //
- // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
- // ^^^^^^^^^^^^^
- if (requireds_list && requireds_list->size) {
- for (size_t i = 0; i < requireds_list->size; i++, local_index++) {
- ID local;
-
- // For each MultiTargetNode, we're going to have one additional
- // anonymous local not represented in the locals table. We want
- // to account for this in our table size.
- pm_node_t *required = requireds_list->nodes[i];
-
- switch (PM_NODE_TYPE(required)) {
- // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
- // ^^^^^^^^^^
- case PM_MULTI_TARGET_NODE: {
- local = rb_make_temporary_id(local_index);
- local_table_for_iseq->ids[local_index] = local;
- break;
- }
- // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
- // ^
- case PM_REQUIRED_PARAMETER_NODE: {
- const pm_required_parameter_node_t *param = (const pm_required_parameter_node_t *) required;
-
- if (PM_NODE_FLAG_P(required, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
- ID local = pm_constant_id_lookup(scope_node, param->name);
- local_table_for_iseq->ids[local_index] = local;
- }
- else {
- pm_insert_local_index(param->name, local_index, index_lookup_table, local_table_for_iseq, scope_node);
- }
-
- break;
- }
- default: {
- rb_bug("Unsupported node in requireds in parameters %s", pm_node_type_to_str(PM_NODE_TYPE(node)));
- }
- }
- }
-
- body->param.lead_num = (int) requireds_list->size;
- body->param.flags.has_lead = true;
- }
-
- if (scope_node->parameters != NULL && PM_NODE_TYPE_P(scope_node->parameters, PM_IT_PARAMETERS_NODE)) {
- ID local = rb_make_temporary_id(local_index);
- local_table_for_iseq->ids[local_index++] = local;
- }
-
- // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
- // ^^^^^
- if (optionals_list && optionals_list->size) {
- body->param.opt_num = (int) optionals_list->size;
- body->param.flags.has_opt = true;
-
- for (size_t i = 0; i < optionals_list->size; i++, local_index++) {
- pm_node_t * node = optionals_list->nodes[i];
- pm_constant_id_t name = ((const pm_optional_parameter_node_t *) node)->name;
-
- if (PM_NODE_FLAG_P(node, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
- ID local = pm_constant_id_lookup(scope_node, name);
- local_table_for_iseq->ids[local_index] = local;
- }
- else {
- pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node);
- }
- }
- }
-
- // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
- // ^^
- if (parameters_node && parameters_node->rest) {
- body->param.rest_start = local_index;
-
- // If there's a trailing comma, we'll have an implicit rest node,
- // and we don't want it to impact the rest variables on param
- if (!(PM_NODE_TYPE_P(parameters_node->rest, PM_IMPLICIT_REST_NODE))) {
- body->param.flags.has_rest = true;
- RUBY_ASSERT(body->param.rest_start != -1);
-
- pm_constant_id_t name = ((const pm_rest_parameter_node_t *) parameters_node->rest)->name;
-
- if (name) {
- // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
- // ^^
- if (PM_NODE_FLAG_P(parameters_node->rest, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
- ID local = pm_constant_id_lookup(scope_node, name);
- local_table_for_iseq->ids[local_index] = local;
- }
- else {
- pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node);
- }
- }
- else {
- // def foo(a, (b, *c, d), e = 1, *, g, (h, *i, j), k:, l: 1, **m, &n)
- // ^
- pm_insert_local_special(idMULT, local_index, index_lookup_table, local_table_for_iseq);
- }
-
- local_index++;
- }
- }
-
- // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
- // ^^^^^^^^^^^^^
- if (posts_list && posts_list->size) {
- body->param.post_num = (int) posts_list->size;
- body->param.post_start = local_index;
- body->param.flags.has_post = true;
-
- for (size_t i = 0; i < posts_list->size; i++, local_index++) {
- ID local;
-
- // For each MultiTargetNode, we're going to have one additional
- // anonymous local not represented in the locals table. We want
- // to account for this in our table size.
- const pm_node_t *post_node = posts_list->nodes[i];
-
- switch (PM_NODE_TYPE(post_node)) {
- // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
- // ^^^^^^^^^^
- case PM_MULTI_TARGET_NODE: {
- local = rb_make_temporary_id(local_index);
- local_table_for_iseq->ids[local_index] = local;
- break;
- }
- // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
- // ^
- case PM_REQUIRED_PARAMETER_NODE: {
- const pm_required_parameter_node_t *param = (const pm_required_parameter_node_t *) post_node;
-
- if (PM_NODE_FLAG_P(param, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
- ID local = pm_constant_id_lookup(scope_node, param->name);
- local_table_for_iseq->ids[local_index] = local;
- }
- else {
- pm_insert_local_index(param->name, local_index, index_lookup_table, local_table_for_iseq, scope_node);
- }
- break;
- }
- default: {
- rb_bug("Unsupported node in posts in parameters %s", pm_node_type_to_str(PM_NODE_TYPE(node)));
- }
- }
- }
- }
-
- // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
- // ^^^^^^^^
- // Keywords create an internal variable on the parse tree
- if (keywords_list && keywords_list->size) {
- body->param.keyword = keyword = ZALLOC_N(struct rb_iseq_param_keyword, 1);
- keyword->num = (int) keywords_list->size;
-
- body->param.flags.has_kw = true;
- const VALUE default_values = rb_ary_hidden_new(1);
- const VALUE complex_mark = rb_str_tmp_new(0);
-
- ID *ids = xcalloc(keywords_list->size, sizeof(ID));
-
- size_t kw_index = 0;
-
- for (size_t i = 0; i < keywords_list->size; i++) {
- pm_node_t *keyword_parameter_node = keywords_list->nodes[i];
- pm_constant_id_t name;
-
- // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
- // ^^
- if (PM_NODE_TYPE_P(keyword_parameter_node, PM_REQUIRED_KEYWORD_PARAMETER_NODE)) {
- name = ((const pm_required_keyword_parameter_node_t *) keyword_parameter_node)->name;
- keyword->required_num++;
- ID local = pm_constant_id_lookup(scope_node, name);
-
- if (PM_NODE_FLAG_P(keyword_parameter_node, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
- local_table_for_iseq->ids[local_index] = local;
- }
- else {
- pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node);
- }
- local_index++;
- ids[kw_index++] = local;
- }
- }
-
- for (size_t i = 0; i < keywords_list->size; i++) {
- pm_node_t *keyword_parameter_node = keywords_list->nodes[i];
- pm_constant_id_t name;
-
- // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
- // ^^^^
- if (PM_NODE_TYPE_P(keyword_parameter_node, PM_OPTIONAL_KEYWORD_PARAMETER_NODE)) {
- const pm_optional_keyword_parameter_node_t *cast = ((const pm_optional_keyword_parameter_node_t *) keyword_parameter_node);
-
- pm_node_t *value = cast->value;
- name = cast->name;
-
- if (PM_NODE_FLAG_P(value, PM_NODE_FLAG_STATIC_LITERAL) && !(PM_NODE_TYPE_P(value, PM_ARRAY_NODE) || PM_NODE_TYPE_P(value, PM_HASH_NODE) || PM_NODE_TYPE_P(value, PM_RANGE_NODE))) {
- rb_ary_push(default_values, pm_static_literal_value(iseq, value, scope_node));
- }
- else {
- rb_ary_push(default_values, complex_mark);
- }
-
- ID local = pm_constant_id_lookup(scope_node, name);
- if (PM_NODE_FLAG_P(keyword_parameter_node, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
- local_table_for_iseq->ids[local_index] = local;
- }
- else {
- pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node);
- }
- ids[kw_index++] = local;
- local_index++;
- }
-
- }
-
- keyword->bits_start = local_index;
- keyword->table = ids;
-
- VALUE *dvs = ALLOC_N(VALUE, RARRAY_LEN(default_values));
-
- for (int i = 0; i < RARRAY_LEN(default_values); i++) {
- VALUE dv = RARRAY_AREF(default_values, i);
- if (dv == complex_mark) dv = Qundef;
- if (!SPECIAL_CONST_P(dv)) {
- RB_OBJ_WRITTEN(iseq, Qundef, dv);
- }
- dvs[i] = dv;
- }
-
- keyword->default_values = dvs;
-
- // Hidden local for keyword arguments
- ID local = rb_make_temporary_id(local_index);
- local_table_for_iseq->ids[local_index] = local;
- local_index++;
- }
-
- if (body->type == ISEQ_TYPE_BLOCK && local_index == 1 && requireds_list && requireds_list->size == 1 && !trailing_comma) {
- body->param.flags.ambiguous_param0 = true;
- }
-
- if (parameters_node) {
- // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
- // ^^^
- if (parameters_node->keyword_rest) {
- switch (PM_NODE_TYPE(parameters_node->keyword_rest)) {
- // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **nil, &n)
- // ^^^^^
- case PM_NO_KEYWORDS_PARAMETER_NODE: {
- body->param.flags.accepts_no_kwarg = true;
- break;
- }
- // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
- // ^^^
- case PM_KEYWORD_REST_PARAMETER_NODE: {
- const pm_keyword_rest_parameter_node_t *kw_rest_node = (const pm_keyword_rest_parameter_node_t *) parameters_node->keyword_rest;
- if (!body->param.flags.has_kw) {
- body->param.keyword = keyword = ZALLOC_N(struct rb_iseq_param_keyword, 1);
- }
-
- keyword->rest_start = local_index;
- body->param.flags.has_kwrest = true;
-
- pm_constant_id_t constant_id = kw_rest_node->name;
- if (constant_id) {
- if (PM_NODE_FLAG_P(kw_rest_node, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
- ID local = pm_constant_id_lookup(scope_node, constant_id);
- local_table_for_iseq->ids[local_index] = local;
- }
- else {
- pm_insert_local_index(constant_id, local_index, index_lookup_table, local_table_for_iseq, scope_node);
- }
- }
- else {
- pm_insert_local_special(idPow, local_index, index_lookup_table, local_table_for_iseq);
- }
-
- local_index++;
- break;
- }
- // def foo(...)
- // ^^^
- case PM_FORWARDING_PARAMETER_NODE: {
- body->param.rest_start = local_index;
- body->param.flags.has_rest = true;
-
- // Add the leading *
- pm_insert_local_special(idMULT, local_index++, index_lookup_table, local_table_for_iseq);
-
- // Add the kwrest **
- RUBY_ASSERT(!body->param.flags.has_kw);
-
- // There are no keywords declared (in the text of the program)
- // but the forwarding node implies we support kwrest (**)
- body->param.flags.has_kw = false;
- body->param.flags.has_kwrest = true;
- body->param.keyword = keyword = ZALLOC_N(struct rb_iseq_param_keyword, 1);
-
- keyword->rest_start = local_index;
-
- pm_insert_local_special(idPow, local_index++, index_lookup_table, local_table_for_iseq);
-
- body->param.block_start = local_index;
- body->param.flags.has_block = true;
-
- pm_insert_local_special(idAnd, local_index++, index_lookup_table, local_table_for_iseq);
- pm_insert_local_special(idDot3, local_index++, index_lookup_table, local_table_for_iseq);
- break;
- }
- default: {
- rb_bug("node type %s not expected as keyword_rest", pm_node_type_to_str(PM_NODE_TYPE(parameters_node->keyword_rest)));
- }
- }
- }
-
- // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
- // ^^
- if (parameters_node->block) {
- body->param.block_start = local_index;
- body->param.flags.has_block = true;
-
- pm_constant_id_t name = ((const pm_block_parameter_node_t *) parameters_node->block)->name;
-
- if (name) {
- if (PM_NODE_FLAG_P(parameters_node->block, PM_PARAMETER_FLAGS_REPEATED_PARAMETER)) {
- ID local = pm_constant_id_lookup(scope_node, name);
- local_table_for_iseq->ids[local_index] = local;
- }
- else {
- pm_insert_local_index(name, local_index, index_lookup_table, local_table_for_iseq, scope_node);
- }
- }
- else {
- pm_insert_local_special(idAnd, local_index, index_lookup_table, local_table_for_iseq);
- }
-
- local_index++;
- }
- }
-
- //********END OF STEP 2**********
- // The local table is now consistent with expected
- // stack layout
-
- // If there's only one required element in the parameters
- // CRuby needs to recognize it as an ambiguous parameter
-
- //********STEP 3**********
- // Goal: fill in the names of the parameters in MultiTargetNodes
- //
- // Go through requireds again to set the multis
-
- if (requireds_list && requireds_list->size) {
- for (size_t i = 0; i < requireds_list->size; i++) {
- // For each MultiTargetNode, we're going to have one
- // additional anonymous local not represented in the locals table
- // We want to account for this in our table size
- const pm_node_t *required = requireds_list->nodes[i];
-
- if (PM_NODE_TYPE_P(required, PM_MULTI_TARGET_NODE)) {
- local_index = pm_compile_destructured_param_locals((const pm_multi_target_node_t *) required, index_lookup_table, local_table_for_iseq, scope_node, local_index);
- }
- }
- }
-
- // Go through posts again to set the multis
- if (posts_list && posts_list->size) {
- for (size_t i = 0; i < posts_list->size; i++) {
- // For each MultiTargetNode, we're going to have one
- // additional anonymous local not represented in the locals table
- // We want to account for this in our table size
- const pm_node_t *post = posts_list->nodes[i];
-
- if (PM_NODE_TYPE_P(post, PM_MULTI_TARGET_NODE)) {
- local_index = pm_compile_destructured_param_locals((const pm_multi_target_node_t *) post, index_lookup_table, local_table_for_iseq, scope_node, local_index);
- }
- }
- }
-
- // Set any anonymous locals for the for node
- if (PM_NODE_TYPE_P(scope_node->ast_node, PM_FOR_NODE)) {
- if (PM_NODE_TYPE_P(((const pm_for_node_t *) scope_node->ast_node)->index, PM_LOCAL_VARIABLE_TARGET_NODE)) {
- body->param.lead_num++;
- }
- else {
- body->param.rest_start = local_index;
- body->param.flags.has_rest = true;
- }
-
- ID local = rb_make_temporary_id(local_index);
- local_table_for_iseq->ids[local_index] = local;
- local_index++;
- }
-
- // Fill in any NumberedParameters, if they exist
- if (scope_node->parameters && PM_NODE_TYPE_P(scope_node->parameters, PM_NUMBERED_PARAMETERS_NODE)) {
- int maximum = ((const pm_numbered_parameters_node_t *) scope_node->parameters)->maximum;
- RUBY_ASSERT(0 < maximum && maximum <= 9);
- for (int i = 0; i < maximum; i++, local_index++) {
- const uint8_t param_name[] = { '_', '1' + i };
- pm_constant_id_t constant_id = pm_constant_pool_find(&parser->constant_pool, param_name, 2);
- RUBY_ASSERT(constant_id && "parser should fill in any gaps in numbered parameters");
- pm_insert_local_index(constant_id, local_index, index_lookup_table, local_table_for_iseq, scope_node);
- }
- body->param.lead_num = maximum;
- body->param.flags.has_lead = true;
- }
-
- //********END OF STEP 3**********
-
- //********STEP 4**********
- // Goal: fill in the method body locals
- // To be explicit, these are the non-parameter locals
- // We fill in the block_locals, if they exist
- // lambda { |x; y| y }
- // ^
- if (block_locals && block_locals->size) {
- for (size_t i = 0; i < block_locals->size; i++, local_index++) {
- pm_constant_id_t constant_id = ((const pm_block_local_variable_node_t *) block_locals->nodes[i])->name;
- pm_insert_local_index(constant_id, local_index, index_lookup_table, local_table_for_iseq, scope_node);
- }
- }
-
- // Fill in any locals we missed
- if (scope_node->locals.size) {
- for (size_t i = 0; i < scope_node->locals.size; i++) {
- pm_constant_id_t constant_id = locals->ids[i];
- if (constant_id) {
- struct pm_local_table_insert_ctx ctx;
- ctx.scope_node = scope_node;
- ctx.local_table_for_iseq = local_table_for_iseq;
- ctx.local_index = local_index;
-
- st_update(index_lookup_table, (st_data_t)constant_id, pm_local_table_insert_func, (st_data_t)&ctx);
-
- local_index = ctx.local_index;
- }
- }
- }
-
- //********END OF STEP 4**********
-
- // We set the index_lookup_table on the scope node so we can
- // refer to the parameters correctly
- if (scope_node->index_lookup_table) {
- st_free_table(scope_node->index_lookup_table);
- }
- scope_node->index_lookup_table = index_lookup_table;
- iseq_calc_param_size(iseq);
- iseq_set_local_table(iseq, local_table_for_iseq);
- scope_node->local_table_for_iseq_size = local_table_for_iseq->size;
-
- //********STEP 5************
- // Goal: compile anything that needed to be compiled
- if (optionals_list && optionals_list->size) {
- LABEL **opt_table = (LABEL **) ALLOC_N(VALUE, optionals_list->size + 1);
- LABEL *label;
-
- // TODO: Should we make an api for NEW_LABEL where you can pass
- // a pointer to the label it should fill out? We already
- // have a list of labels allocated above so it seems wasteful
- // to do the copies.
- for (size_t i = 0; i < optionals_list->size; i++) {
- label = NEW_LABEL(lineno);
- opt_table[i] = label;
- PUSH_LABEL(ret, label);
- pm_node_t *optional_node = optionals_list->nodes[i];
- PM_COMPILE_NOT_POPPED(optional_node);
- }
-
- // Set the last label
- label = NEW_LABEL(lineno);
- opt_table[optionals_list->size] = label;
- PUSH_LABEL(ret, label);
-
- body->param.opt_table = (const VALUE *) opt_table;
- }
-
- if (keywords_list && keywords_list->size) {
- size_t optional_index = 0;
- for (size_t i = 0; i < keywords_list->size; i++) {
- pm_node_t *keyword_parameter_node = keywords_list->nodes[i];
- pm_constant_id_t name;
-
- switch (PM_NODE_TYPE(keyword_parameter_node)) {
- // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
- // ^^^^
- case PM_OPTIONAL_KEYWORD_PARAMETER_NODE: {
- const pm_optional_keyword_parameter_node_t *cast = ((const pm_optional_keyword_parameter_node_t *) keyword_parameter_node);
-
- pm_node_t *value = cast->value;
- name = cast->name;
-
- if (!PM_NODE_FLAG_P(value, PM_NODE_FLAG_STATIC_LITERAL) || PM_NODE_TYPE_P(value, PM_ARRAY_NODE) || PM_NODE_TYPE_P(value, PM_HASH_NODE) || PM_NODE_TYPE_P(value, PM_RANGE_NODE)) {
- LABEL *end_label = NEW_LABEL(location.line);
-
- pm_local_index_t index = pm_lookup_local_index(iseq, scope_node, name, 0);
- int kw_bits_idx = table_size - body->param.keyword->bits_start;
- PUSH_INSN2(ret, location, checkkeyword, INT2FIX(kw_bits_idx + VM_ENV_DATA_SIZE - 1), INT2FIX(optional_index));
- PUSH_INSNL(ret, location, branchif, end_label);
- PM_COMPILE(value);
- PUSH_SETLOCAL(ret, location, index.index, index.level);
- PUSH_LABEL(ret, end_label);
- }
- optional_index++;
- break;
- }
- // def foo(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m, &n)
- // ^^
- case PM_REQUIRED_KEYWORD_PARAMETER_NODE: {
- break;
- }
- default: {
- rb_bug("Unexpected keyword parameter node type %s", pm_node_type_to_str(PM_NODE_TYPE(keyword_parameter_node)));
- }
- }
- }
- }
-
- if (requireds_list && requireds_list->size) {
- for (size_t i = 0; i < requireds_list->size; i++) {
- // For each MultiTargetNode, we're going to have one additional
- // anonymous local not represented in the locals table. We want
- // to account for this in our table size.
- const pm_node_t *required = requireds_list->nodes[i];
-
- if (PM_NODE_TYPE_P(required, PM_MULTI_TARGET_NODE)) {
- PUSH_GETLOCAL(ret, location, table_size - (int)i, 0);
- pm_compile_destructured_param_writes(iseq, (const pm_multi_target_node_t *) required, ret, scope_node);
- }
- }
- }
-
- if (posts_list && posts_list->size) {
- for (size_t i = 0; i < posts_list->size; i++) {
- // For each MultiTargetNode, we're going to have one additional
- // anonymous local not represented in the locals table. We want
- // to account for this in our table size.
- const pm_node_t *post = posts_list->nodes[i];
-
- if (PM_NODE_TYPE_P(post, PM_MULTI_TARGET_NODE)) {
- PUSH_GETLOCAL(ret, location, table_size - body->param.post_start - (int) i, 0);
- pm_compile_destructured_param_writes(iseq, (const pm_multi_target_node_t *) post, ret, scope_node);
- }
- }
- }
-
- switch (body->type) {
- case ISEQ_TYPE_BLOCK: {
- LABEL *start = ISEQ_COMPILE_DATA(iseq)->start_label = NEW_LABEL(0);
- LABEL *end = ISEQ_COMPILE_DATA(iseq)->end_label = NEW_LABEL(0);
- const pm_line_column_t block_location = { .line = body->location.first_lineno, .column = -1 };
-
- start->rescued = LABEL_RESCUE_BEG;
- end->rescued = LABEL_RESCUE_END;
-
- // For nodes automatically assign the iteration variable to whatever
- // index variable. We need to handle that write here because it has
- // to happen in the context of the block. Note that this happens
- // before the B_CALL tracepoint event.
- if (PM_NODE_TYPE_P(scope_node->ast_node, PM_FOR_NODE)) {
- pm_compile_for_node_index(iseq, ((const pm_for_node_t *) scope_node->ast_node)->index, ret, scope_node);
- }
-
- PUSH_TRACE(ret, RUBY_EVENT_B_CALL);
- PUSH_INSN(ret, block_location, nop);
- PUSH_LABEL(ret, start);
-
- if (scope_node->body != NULL) {
- switch (PM_NODE_TYPE(scope_node->ast_node)) {
- case PM_POST_EXECUTION_NODE: {
- const pm_post_execution_node_t *cast = (const pm_post_execution_node_t *) scope_node->ast_node;
- PUSH_INSN1(ret, block_location, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
-
- // We create another ScopeNode from the statements within the PostExecutionNode
- pm_scope_node_t next_scope_node;
- pm_scope_node_init((const pm_node_t *) cast->statements, &next_scope_node, scope_node);
-
- const rb_iseq_t *block = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(body->parent_iseq), ISEQ_TYPE_BLOCK, location.line);
- pm_scope_node_destroy(&next_scope_node);
-
- PUSH_CALL_WITH_BLOCK(ret, block_location, id_core_set_postexe, INT2FIX(0), block);
- break;
- }
- case PM_INTERPOLATED_REGULAR_EXPRESSION_NODE: {
- const pm_interpolated_regular_expression_node_t *cast = (const pm_interpolated_regular_expression_node_t *) scope_node->ast_node;
- pm_compile_regexp_dynamic(iseq, (const pm_node_t *) cast, &cast->parts, &location, ret, popped, scope_node);
- break;
- }
- default:
- pm_compile_node(iseq, scope_node->body, ret, popped, scope_node);
- break;
- }
- }
- else {
- PUSH_INSN(ret, block_location, putnil);
- }
-
- PUSH_LABEL(ret, end);
- PUSH_TRACE(ret, RUBY_EVENT_B_RETURN);
- ISEQ_COMPILE_DATA(iseq)->last_line = body->location.code_location.end_pos.lineno;
-
- /* wide range catch handler must put at last */
- PUSH_CATCH_ENTRY(CATCH_TYPE_REDO, start, end, NULL, start);
- PUSH_CATCH_ENTRY(CATCH_TYPE_NEXT, start, end, NULL, end);
- break;
- }
- case ISEQ_TYPE_ENSURE: {
- const pm_line_column_t statements_location = (scope_node->body != NULL ? PM_NODE_START_LINE_COLUMN(scope_node->parser, scope_node->body) : location);
- iseq_set_exception_local_table(iseq);
-
- if (scope_node->body != NULL) {
- PM_COMPILE_POPPED((const pm_node_t *) scope_node->body);
- }
-
- PUSH_GETLOCAL(ret, statements_location, 1, 0);
- PUSH_INSN1(ret, statements_location, throw, INT2FIX(0));
- return;
- }
- case ISEQ_TYPE_METHOD: {
- ISEQ_COMPILE_DATA(iseq)->root_node = (const void *) scope_node->body;
- PUSH_TRACE(ret, RUBY_EVENT_CALL);
-
- if (scope_node->body) {
- PM_COMPILE((const pm_node_t *) scope_node->body);
- }
- else {
- PUSH_INSN(ret, location, putnil);
- }
-
- ISEQ_COMPILE_DATA(iseq)->root_node = (const void *) scope_node->body;
- PUSH_TRACE(ret, RUBY_EVENT_RETURN);
-
- ISEQ_COMPILE_DATA(iseq)->last_line = body->location.code_location.end_pos.lineno;
- break;
- }
- case ISEQ_TYPE_RESCUE: {
- iseq_set_exception_local_table(iseq);
- if (PM_NODE_TYPE_P(scope_node->ast_node, PM_RESCUE_MODIFIER_NODE)) {
- LABEL *lab = NEW_LABEL(lineno);
- LABEL *rescue_end = NEW_LABEL(lineno);
- PUSH_GETLOCAL(ret, location, LVAR_ERRINFO, 0);
- PUSH_INSN1(ret, location, putobject, rb_eStandardError);
- PUSH_INSN1(ret, location, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE));
- PUSH_INSNL(ret, location, branchif, lab);
- PUSH_INSNL(ret, location, jump, rescue_end);
- PUSH_LABEL(ret, lab);
- PM_COMPILE((const pm_node_t *) scope_node->body);
- PUSH_INSN(ret, location, leave);
- PUSH_LABEL(ret, rescue_end);
- PUSH_GETLOCAL(ret, location, LVAR_ERRINFO, 0);
- }
- else {
- PM_COMPILE((const pm_node_t *) scope_node->ast_node);
- }
- PUSH_INSN1(ret, location, throw, INT2FIX(0));
-
- return;
- }
- default:
- if (scope_node->body) {
- PM_COMPILE((const pm_node_t *) scope_node->body);
- }
- else {
- PUSH_INSN(ret, location, putnil);
- }
- break;
- }
-
- if (PM_NODE_TYPE_P(scope_node->ast_node, PM_CLASS_NODE) || PM_NODE_TYPE_P(scope_node->ast_node, PM_MODULE_NODE)) {
- const pm_line_column_t end_location = PM_NODE_END_LINE_COLUMN(scope_node->parser, scope_node->ast_node);
- ADD_TRACE(ret, RUBY_EVENT_END);
- ISEQ_COMPILE_DATA(iseq)->last_line = end_location.line;
- }
-
- if (!PM_NODE_TYPE_P(scope_node->ast_node, PM_ENSURE_NODE)) {
- const pm_line_column_t location = { .line = ISEQ_COMPILE_DATA(iseq)->last_line, .column = -1 };
- PUSH_INSN(ret, location, leave);
- }
-
+ case PM_SCOPE_NODE:
+ pm_compile_scope_node(iseq, (pm_scope_node_t *) node, &location, ret, popped);
return;
- }
case PM_SELF_NODE: {
// self
// ^^^^
@@ -9068,31 +10204,32 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
// A value that is being written to a constant that is being marked as
// shared depending on the current lexical context.
const pm_shareable_constant_node_t *cast = (const pm_shareable_constant_node_t *) node;
+ pm_node_flags_t shareability = (cast->base.flags & (PM_SHAREABLE_CONSTANT_NODE_FLAGS_LITERAL | PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_EVERYTHING | PM_SHAREABLE_CONSTANT_NODE_FLAGS_EXPERIMENTAL_COPY));
switch (PM_NODE_TYPE(cast->write)) {
case PM_CONSTANT_WRITE_NODE:
- pm_compile_constant_write_node(iseq, (const pm_constant_write_node_t *) cast->write, cast->base.flags, &location, ret, popped, scope_node);
+ pm_compile_constant_write_node(iseq, (const pm_constant_write_node_t *) cast->write, shareability, &location, ret, popped, scope_node);
break;
case PM_CONSTANT_AND_WRITE_NODE:
- pm_compile_constant_and_write_node(iseq, (const pm_constant_and_write_node_t *) cast->write, cast->base.flags, &location, ret, popped, scope_node);
+ pm_compile_constant_and_write_node(iseq, (const pm_constant_and_write_node_t *) cast->write, shareability, &location, ret, popped, scope_node);
break;
case PM_CONSTANT_OR_WRITE_NODE:
- pm_compile_constant_or_write_node(iseq, (const pm_constant_or_write_node_t *) cast->write, cast->base.flags, &location, ret, popped, scope_node);
+ pm_compile_constant_or_write_node(iseq, (const pm_constant_or_write_node_t *) cast->write, shareability, &location, ret, popped, scope_node);
break;
case PM_CONSTANT_OPERATOR_WRITE_NODE:
- pm_compile_constant_operator_write_node(iseq, (const pm_constant_operator_write_node_t *) cast->write, cast->base.flags, &location, ret, popped, scope_node);
+ pm_compile_constant_operator_write_node(iseq, (const pm_constant_operator_write_node_t *) cast->write, shareability, &location, ret, popped, scope_node);
break;
case PM_CONSTANT_PATH_WRITE_NODE:
- pm_compile_constant_path_write_node(iseq, (const pm_constant_path_write_node_t *) cast->write, cast->base.flags, &location, ret, popped, scope_node);
+ pm_compile_constant_path_write_node(iseq, (const pm_constant_path_write_node_t *) cast->write, shareability, &location, ret, popped, scope_node);
break;
case PM_CONSTANT_PATH_AND_WRITE_NODE:
- pm_compile_constant_path_and_write_node(iseq, (const pm_constant_path_and_write_node_t *) cast->write, cast->base.flags, &location, ret, popped, scope_node);
+ pm_compile_constant_path_and_write_node(iseq, (const pm_constant_path_and_write_node_t *) cast->write, shareability, &location, ret, popped, scope_node);
break;
case PM_CONSTANT_PATH_OR_WRITE_NODE:
- pm_compile_constant_path_or_write_node(iseq, (const pm_constant_path_or_write_node_t *) cast->write, cast->base.flags, &location, ret, popped, scope_node);
+ pm_compile_constant_path_or_write_node(iseq, (const pm_constant_path_or_write_node_t *) cast->write, shareability, &location, ret, popped, scope_node);
break;
case PM_CONSTANT_PATH_OPERATOR_WRITE_NODE:
- pm_compile_constant_path_operator_write_node(iseq, (const pm_constant_path_operator_write_node_t *) cast->write, cast->base.flags, &location, ret, popped, scope_node);
+ pm_compile_constant_path_operator_write_node(iseq, (const pm_constant_path_operator_write_node_t *) cast->write, shareability, &location, ret, popped, scope_node);
break;
default:
rb_bug("Unexpected node type for shareable constant write: %s", pm_node_type_to_str(PM_NODE_TYPE(cast->write)));
@@ -9208,51 +10345,12 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
}
return;
}
- case PM_SUPER_NODE: {
+ case PM_SUPER_NODE:
+ // super()
// super(foo)
- // ^^^^^^^^^^
- const pm_super_node_t *cast = (const pm_super_node_t *) node;
-
- DECL_ANCHOR(args);
- INIT_ANCHOR(args);
-
- LABEL *retry_label = NEW_LABEL(location.line);
- LABEL *retry_end_l = NEW_LABEL(location.line);
-
- const rb_iseq_t *previous_block = ISEQ_COMPILE_DATA(iseq)->current_block;
- const rb_iseq_t *current_block;
- ISEQ_COMPILE_DATA(iseq)->current_block = current_block = NULL;
-
- PUSH_LABEL(ret, retry_label);
- PUSH_INSN(ret, location, putself);
-
- int flags = 0;
- struct rb_callinfo_kwarg *keywords = NULL;
- int argc = pm_setup_args(cast->arguments, cast->block, &flags, &keywords, iseq, ret, scope_node, &location);
- flags |= VM_CALL_SUPER | VM_CALL_FCALL;
-
- if (cast->block && PM_NODE_TYPE_P(cast->block, PM_BLOCK_NODE)) {
- pm_scope_node_t next_scope_node;
- pm_scope_node_init(cast->block, &next_scope_node, scope_node);
-
- ISEQ_COMPILE_DATA(iseq)->current_block = current_block = NEW_CHILD_ISEQ(&next_scope_node, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, lineno);
- pm_scope_node_destroy(&next_scope_node);
- }
-
- if ((flags & VM_CALL_ARGS_BLOCKARG) && (flags & VM_CALL_KW_SPLAT) && !(flags & VM_CALL_KW_SPLAT_MUT)) {
- PUSH_INSN(args, location, splatkw);
- }
-
- PUSH_SEQ(ret, args);
- PUSH_INSN2(ret, location, invokesuper, new_callinfo(iseq, 0, argc, flags, keywords, current_block != NULL), current_block);
- pm_compile_retry_end_label(iseq, ret, retry_end_l);
-
- if (popped) PUSH_INSN(ret, location, pop);
- ISEQ_COMPILE_DATA(iseq)->current_block = previous_block;
- PUSH_CATCH_ENTRY(CATCH_TYPE_BREAK, retry_label, retry_end_l, current_block, retry_end_l);
-
+ // super(...)
+ pm_compile_super_node(iseq, (const pm_super_node_t *) node, &location, ret, popped, scope_node);
return;
- }
case PM_SYMBOL_NODE: {
// :foo
// ^^^^
@@ -9298,12 +10396,12 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
// bar unless foo
// ^^^^^^^^^^^^^^
const pm_unless_node_t *cast = (const pm_unless_node_t *) node;
- const pm_statements_node_t *consequent = NULL;
- if (cast->consequent != NULL) {
- consequent = ((const pm_else_node_t *) cast->consequent)->statements;
+ const pm_statements_node_t *statements = NULL;
+ if (cast->else_clause != NULL) {
+ statements = ((const pm_else_node_t *) cast->else_clause)->statements;
}
- pm_compile_conditional(iseq, &location, PM_UNLESS_NODE, (const pm_node_t *) cast, consequent, (const pm_node_t *) cast->statements, cast->predicate, ret, popped, scope_node);
+ pm_compile_conditional(iseq, &location, PM_UNLESS_NODE, (const pm_node_t *) cast, statements, (const pm_node_t *) cast->statements, cast->predicate, ret, popped, scope_node);
return;
}
case PM_UNTIL_NODE: {
@@ -9339,49 +10437,22 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
return;
}
- case PM_YIELD_NODE: {
+ case PM_YIELD_NODE:
// yield
// ^^^^^
//
// yield 1
// ^^^^^^^
- const pm_yield_node_t *cast = (const pm_yield_node_t *) node;
-
- switch (ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->type) {
- case ISEQ_TYPE_TOP:
- case ISEQ_TYPE_MAIN:
- case ISEQ_TYPE_CLASS:
- COMPILE_ERROR(iseq, location.line, "Invalid yield");
- return;
- default: /* valid */;
- }
-
- int argc = 0;
- int flags = 0;
- struct rb_callinfo_kwarg *keywords = NULL;
-
- if (cast->arguments) {
- argc = pm_setup_args(cast->arguments, NULL, &flags, &keywords, iseq, ret, scope_node, &location);
- }
-
- PUSH_INSN1(ret, location, invokeblock, new_callinfo(iseq, 0, argc, flags, keywords, FALSE));
- if (popped) PUSH_INSN(ret, location, pop);
-
- int level = 0;
- for (const rb_iseq_t *tmp_iseq = iseq; tmp_iseq != ISEQ_BODY(iseq)->local_iseq; level++) {
- tmp_iseq = ISEQ_BODY(tmp_iseq)->parent_iseq;
- }
-
- if (level > 0) access_outer_variables(iseq, level, rb_intern("yield"), true);
+ pm_compile_yield_node(iseq, (const pm_yield_node_t *) node, &location, ret, popped, scope_node);
return;
- }
- default: {
+ default:
rb_raise(rb_eNotImpError, "node type %s not implemented", pm_node_type_to_str(PM_NODE_TYPE(node)));
return;
- }
}
}
+#undef PM_CONTAINER_P
+
/** True if the given iseq can have pre execution blocks. */
static inline bool
pm_iseq_pre_execution_p(rb_iseq_t *iseq)
@@ -9407,7 +10478,6 @@ VALUE
pm_iseq_compile_node(rb_iseq_t *iseq, pm_scope_node_t *node)
{
DECL_ANCHOR(ret);
- INIT_ANCHOR(ret);
if (pm_iseq_pre_execution_p(iseq)) {
// Because these ISEQs can have BEGIN{}, we're going to create two
@@ -9415,14 +10485,12 @@ pm_iseq_compile_node(rb_iseq_t *iseq, pm_scope_node_t *node)
// on the scope node so that when BEGIN{} is found, its contents will be
// added to the "pre" anchor.
DECL_ANCHOR(pre);
- INIT_ANCHOR(pre);
node->pre_execution_anchor = pre;
// Now we'll compile the body as normal. We won't compile directly into
// the "ret" anchor yet because we want to add the "pre" anchor to the
// beginning of the "ret" anchor first.
DECL_ANCHOR(body);
- INIT_ANCHOR(body);
pm_compile_node(iseq, (const pm_node_t *) node, body, false, node);
// Now we'll join both anchors together so that the content is in the
@@ -9447,8 +10515,12 @@ pm_iseq_compile_node(rb_iseq_t *iseq, pm_scope_node_t *node)
void
pm_parse_result_free(pm_parse_result_t *result)
{
- if (result->parsed) {
+ if (result->node.ast_node != NULL) {
pm_node_destroy(&result->parser, result->node.ast_node);
+ }
+
+ if (result->parsed) {
+ xfree(result->node.constants);
pm_scope_node_destroy(&result->node);
}
@@ -9490,7 +10562,8 @@ typedef struct {
size_t divider_length;
} pm_parse_error_format_t;
-#define PM_COLOR_GRAY "\033[38;5;102m"
+#define PM_COLOR_BOLD "\033[1m"
+#define PM_COLOR_GRAY "\033[2m"
#define PM_COLOR_RED "\033[1;31m"
#define PM_COLOR_RESET "\033[m"
#define PM_ERROR_TRUNCATE 30
@@ -9501,7 +10574,9 @@ pm_parse_errors_format_sort(const pm_parser_t *parser, const pm_list_t *error_li
if (errors == NULL) return NULL;
int32_t start_line = parser->start_line;
- for (pm_diagnostic_t *error = (pm_diagnostic_t *) error_list->head; error != NULL; error = (pm_diagnostic_t *) error->node.next) {
+ pm_diagnostic_t *finish = (pm_diagnostic_t * )error_list->tail->next;
+
+ for (pm_diagnostic_t *error = (pm_diagnostic_t *) error_list->head; error != finish; error = (pm_diagnostic_t *) error->node.next) {
pm_line_column_t start = pm_newline_list_line_column(newline_list, error->location.start, start_line);
pm_line_column_t end = pm_newline_list_line_column(newline_list, error->location.end, start_line);
@@ -9547,6 +10622,9 @@ pm_parse_errors_format_sort(const pm_parser_t *parser, const pm_list_t *error_li
return errors;
}
+/* Append a literal string to the buffer. */
+#define pm_buffer_append_literal(buffer, str) pm_buffer_append_string(buffer, str, rb_strlen_lit(str))
+
static inline void
pm_parse_errors_format_line(const pm_parser_t *parser, const pm_newline_list_t *newline_list, const char *number_prefix, int32_t line, uint32_t column_start, uint32_t column_end, pm_buffer_t *buffer) {
int32_t line_delta = line - parser->start_line;
@@ -9569,7 +10647,26 @@ pm_parse_errors_format_line(const pm_parser_t *parser, const pm_newline_list_t *
// Here we determine if we should truncate the end of the line.
bool truncate_end = false;
if ((column_end != 0) && ((end - (start + column_end)) >= PM_ERROR_TRUNCATE)) {
- end = start + column_end + PM_ERROR_TRUNCATE;
+ const uint8_t *end_candidate = start + column_end + PM_ERROR_TRUNCATE;
+
+ for (const uint8_t *ptr = start; ptr < end_candidate;) {
+ size_t char_width = parser->encoding->char_width(ptr, parser->end - ptr);
+
+ // If we failed to decode a character, then just bail out and
+ // truncate at the fixed width.
+ if (char_width == 0) break;
+
+ // If this next character would go past the end candidate,
+ // then we need to truncate before it.
+ if (ptr + char_width > end_candidate) {
+ end_candidate = ptr;
+ break;
+ }
+
+ ptr += char_width;
+ }
+
+ end = end_candidate;
truncate_end = true;
}
@@ -9592,7 +10689,7 @@ pm_parse_errors_format_line(const pm_parser_t *parser, const pm_newline_list_t *
* Format the errors on the parser into the given buffer.
*/
static void
-pm_parse_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, pm_buffer_t *buffer, bool colorize, bool inline_messages) {
+pm_parse_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, pm_buffer_t *buffer, int highlight, bool inline_messages) {
assert(error_list->size != 0);
// First, we're going to sort all of the errors by line number using an
@@ -9618,7 +10715,7 @@ pm_parse_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, p
int32_t max_line_number = first_line_number > last_line_number ? first_line_number : last_line_number;
if (max_line_number < 10) {
- if (colorize) {
+ if (highlight > 0) {
error_format = (pm_parse_error_format_t) {
.number_prefix = PM_COLOR_GRAY "%1" PRIi32 " | " PM_COLOR_RESET,
.blank_prefix = PM_COLOR_GRAY " | " PM_COLOR_RESET,
@@ -9632,7 +10729,7 @@ pm_parse_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, p
};
}
} else if (max_line_number < 100) {
- if (colorize) {
+ if (highlight > 0) {
error_format = (pm_parse_error_format_t) {
.number_prefix = PM_COLOR_GRAY "%2" PRIi32 " | " PM_COLOR_RESET,
.blank_prefix = PM_COLOR_GRAY " | " PM_COLOR_RESET,
@@ -9646,7 +10743,7 @@ pm_parse_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, p
};
}
} else if (max_line_number < 1000) {
- if (colorize) {
+ if (highlight > 0) {
error_format = (pm_parse_error_format_t) {
.number_prefix = PM_COLOR_GRAY "%3" PRIi32 " | " PM_COLOR_RESET,
.blank_prefix = PM_COLOR_GRAY " | " PM_COLOR_RESET,
@@ -9660,7 +10757,7 @@ pm_parse_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, p
};
}
} else if (max_line_number < 10000) {
- if (colorize) {
+ if (highlight > 0) {
error_format = (pm_parse_error_format_t) {
.number_prefix = PM_COLOR_GRAY "%4" PRIi32 " | " PM_COLOR_RESET,
.blank_prefix = PM_COLOR_GRAY " | " PM_COLOR_RESET,
@@ -9674,7 +10771,7 @@ pm_parse_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, p
};
}
} else {
- if (colorize) {
+ if (highlight > 0) {
error_format = (pm_parse_error_format_t) {
.number_prefix = PM_COLOR_GRAY "%5" PRIi32 " | " PM_COLOR_RESET,
.blank_prefix = PM_COLOR_GRAY " | " PM_COLOR_RESET,
@@ -9723,10 +10820,12 @@ pm_parse_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, p
// If this is the first error or we're on a new line, then we'll display
// the line that has the error in it.
if ((index == 0) || (error->line != last_line)) {
- if (colorize) {
- pm_buffer_append_string(buffer, PM_COLOR_RED "> " PM_COLOR_RESET, 12);
+ if (highlight > 1) {
+ pm_buffer_append_literal(buffer, PM_COLOR_RED "> " PM_COLOR_RESET);
+ } else if (highlight > 0) {
+ pm_buffer_append_literal(buffer, PM_COLOR_BOLD "> " PM_COLOR_RESET);
} else {
- pm_buffer_append_string(buffer, "> ", 2);
+ pm_buffer_append_literal(buffer, "> ");
}
last_column_start = error->column_start;
@@ -9769,7 +10868,8 @@ pm_parse_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, p
column += (char_width == 0 ? 1 : char_width);
}
- if (colorize) pm_buffer_append_string(buffer, PM_COLOR_RED, 7);
+ if (highlight > 1) pm_buffer_append_literal(buffer, PM_COLOR_RED);
+ else if (highlight > 0) pm_buffer_append_literal(buffer, PM_COLOR_BOLD);
pm_buffer_append_byte(buffer, '^');
size_t char_width = encoding->char_width(start + column, parser->end - (start + column));
@@ -9782,7 +10882,7 @@ pm_parse_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, p
column += (char_width == 0 ? 1 : char_width);
}
- if (colorize) pm_buffer_append_string(buffer, PM_COLOR_RESET, 3);
+ if (highlight > 0) pm_buffer_append_literal(buffer, PM_COLOR_RESET);
if (inline_messages) {
pm_buffer_append_byte(buffer, ' ');
@@ -9797,7 +10897,20 @@ pm_parse_errors_format(const pm_parser_t *parser, const pm_list_t *error_list, p
// Here we determine how many lines of padding to display after the
// error, depending on where the next error is in source.
last_line = error->line;
- int32_t next_line = (index == error_list->size - 1) ? (((int32_t) newline_list->size) + parser->start_line) : errors[index + 1].line;
+ int32_t next_line;
+
+ if (index == error_list->size - 1) {
+ next_line = (((int32_t) newline_list->size) + parser->start_line);
+
+ // If the file ends with a newline, subtract one from our "next_line"
+ // so that we don't output an extra line at the end of the file
+ if ((parser->start + newline_list->offsets[newline_list->size - 1]) == parser->end) {
+ next_line--;
+ }
+ }
+ else {
+ next_line = errors[index + 1].line;
+ }
if (next_line - last_line > 1) {
pm_buffer_append_string(buffer, " ", 2);
@@ -9857,6 +10970,12 @@ pm_parse_process_error(const pm_parse_result_t *result)
pm_buffer_t buffer = { 0 };
const pm_string_t *filepath = &parser->filepath;
+ int highlight = rb_stderr_tty_p();
+ if (highlight) {
+ const char *no_color = getenv("NO_COLOR");
+ highlight = (no_color == NULL || no_color[0] == '\0') ? 2 : 1;
+ }
+
for (const pm_diagnostic_t *error = head; error != NULL; error = (const pm_diagnostic_t *) error->node.next) {
switch (error->level) {
case PM_ERROR_LEVEL_SYNTAX:
@@ -9890,7 +11009,7 @@ pm_parse_process_error(const pm_parse_result_t *result)
pm_list_node_t *list_node = (pm_list_node_t *) error;
pm_list_t error_list = { .size = 1, .head = list_node, .tail = list_node };
- pm_parse_errors_format(parser, &error_list, &buffer, rb_stderr_tty_p(), false);
+ pm_parse_errors_format(parser, &error_list, &buffer, highlight, false);
}
VALUE value = rb_exc_new(rb_eArgError, pm_buffer_value(&buffer), pm_buffer_length(&buffer));
@@ -9920,7 +11039,7 @@ pm_parse_process_error(const pm_parse_result_t *result)
);
if (valid_utf8) {
- pm_parse_errors_format(parser, &parser->error_list, &buffer, rb_stderr_tty_p(), true);
+ pm_parse_errors_format(parser, &parser->error_list, &buffer, highlight, true);
}
else {
for (const pm_diagnostic_t *error = head; error != NULL; error = (const pm_diagnostic_t *) error->node.next) {
@@ -9947,7 +11066,7 @@ pm_parse_process_error(const pm_parse_result_t *result)
* result object is zeroed out.
*/
static VALUE
-pm_parse_process(pm_parse_result_t *result, pm_node_t *node)
+pm_parse_process(pm_parse_result_t *result, pm_node_t *node, VALUE *script_lines)
{
pm_parser_t *parser = &result->parser;
@@ -9965,6 +11084,20 @@ pm_parse_process(pm_parse_result_t *result, pm_node_t *node)
scope_node->coverage_enabled = coverage_enabled;
+ // If RubyVM.keep_script_lines is set to true, then we need to create that
+ // array of script lines here.
+ if (script_lines != NULL) {
+ *script_lines = rb_ary_new_capa(parser->newline_list.size);
+
+ for (size_t index = 0; index < parser->newline_list.size; index++) {
+ size_t offset = parser->newline_list.offsets[index];
+ size_t length = index == parser->newline_list.size - 1 ? ((size_t) (parser->end - (parser->start + offset))) : (parser->newline_list.offsets[index + 1] - offset);
+ rb_ary_push(*script_lines, rb_enc_str_new((const char *) parser->start + offset, length, scope_node->encoding));
+ }
+
+ scope_node->script_lines = script_lines;
+ }
+
// Emit all of the various warnings from the parse.
const pm_diagnostic_t *warning;
const char *warning_filepath = (const char *) pm_string_source(&parser->filepath);
@@ -9992,7 +11125,7 @@ pm_parse_process(pm_parse_result_t *result, pm_node_t *node)
// Now set up the constant pool and intern all of the various constants into
// their corresponding IDs.
scope_node->parser = parser;
- scope_node->constants = calloc(parser->constant_pool.size, sizeof(ID));
+ scope_node->constants = parser->constant_pool.size ? xcalloc(parser->constant_pool.size, sizeof(ID)) : NULL;
for (uint32_t index = 0; index < parser->constant_pool.size; index++) {
pm_constant_t *constant = &parser->constant_pool.constants[index];
@@ -10070,6 +11203,147 @@ pm_parse_file_script_lines(const pm_scope_node_t *scope_node, const pm_parser_t
return lines;
}
+// This is essentially pm_string_mapped_init(), preferring to memory map the
+// file, with additional handling for files that require blocking to properly
+// read (e.g. pipes).
+static pm_string_init_result_t
+pm_read_file(pm_string_t *string, const char *filepath)
+{
+#ifdef _WIN32
+ // Open the file for reading.
+ int length = MultiByteToWideChar(CP_UTF8, 0, filepath, -1, NULL, 0);
+ if (length == 0) return PM_STRING_INIT_ERROR_GENERIC;
+
+ WCHAR *wfilepath = xmalloc(sizeof(WCHAR) * ((size_t) length));
+ if ((wfilepath == NULL) || (MultiByteToWideChar(CP_UTF8, 0, filepath, -1, wfilepath, length) == 0)) {
+ xfree(wfilepath);
+ return PM_STRING_INIT_ERROR_GENERIC;
+ }
+
+ HANDLE file = CreateFileW(wfilepath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
+ if (file == INVALID_HANDLE_VALUE) {
+ pm_string_init_result_t result = PM_STRING_INIT_ERROR_GENERIC;
+
+ if (GetLastError() == ERROR_ACCESS_DENIED) {
+ DWORD attributes = GetFileAttributesW(wfilepath);
+ if ((attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
+ result = PM_STRING_INIT_ERROR_DIRECTORY;
+ }
+ }
+
+ xfree(wfilepath);
+ return result;
+ }
+
+ // Get the file size.
+ DWORD file_size = GetFileSize(file, NULL);
+ if (file_size == INVALID_FILE_SIZE) {
+ CloseHandle(file);
+ xfree(wfilepath);
+ return PM_STRING_INIT_ERROR_GENERIC;
+ }
+
+ // If the file is empty, then we don't need to do anything else, we'll set
+ // the source to a constant empty string and return.
+ if (file_size == 0) {
+ CloseHandle(file);
+ xfree(wfilepath);
+ const uint8_t source[] = "";
+ *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 };
+ return PM_STRING_INIT_SUCCESS;
+ }
+
+ // Create a mapping of the file.
+ HANDLE mapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL);
+ if (mapping == NULL) {
+ CloseHandle(file);
+ xfree(wfilepath);
+ return PM_STRING_INIT_ERROR_GENERIC;
+ }
+
+ // Map the file into memory.
+ uint8_t *source = (uint8_t *) MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
+ CloseHandle(mapping);
+ CloseHandle(file);
+ xfree(wfilepath);
+
+ if (source == NULL) {
+ return PM_STRING_INIT_ERROR_GENERIC;
+ }
+
+ *string = (pm_string_t) { .type = PM_STRING_MAPPED, .source = source, .length = (size_t) file_size };
+ return PM_STRING_INIT_SUCCESS;
+#elif defined(_POSIX_MAPPED_FILES)
+ // Open the file for reading
+ const int open_mode = O_RDONLY | O_NONBLOCK;
+ int fd = open(filepath, open_mode);
+ if (fd == -1) {
+ return PM_STRING_INIT_ERROR_GENERIC;
+ }
+
+ // Stat the file to get the file size
+ struct stat sb;
+ if (fstat(fd, &sb) == -1) {
+ close(fd);
+ return PM_STRING_INIT_ERROR_GENERIC;
+ }
+
+ // Ensure it is a file and not a directory
+ if (S_ISDIR(sb.st_mode)) {
+ close(fd);
+ return PM_STRING_INIT_ERROR_DIRECTORY;
+ }
+
+ // We need to wait for data first before reading from pipes and character
+ // devices. To not block the entire VM, we need to release the GVL while
+ // reading. Use IO#read to do this and let the GC handle closing the FD.
+ if (S_ISFIFO(sb.st_mode) || S_ISCHR(sb.st_mode)) {
+ VALUE io = rb_io_fdopen((int) fd, open_mode, filepath);
+ rb_io_wait(io, RB_INT2NUM(RUBY_IO_READABLE), Qnil);
+ VALUE contents = rb_funcall(io, rb_intern("read"), 0);
+
+ if (!RB_TYPE_P(contents, T_STRING)) {
+ return PM_STRING_INIT_ERROR_GENERIC;
+ }
+
+ long len = RSTRING_LEN(contents);
+ if (len < 0) {
+ return PM_STRING_INIT_ERROR_GENERIC;
+ }
+
+ size_t length = (size_t) len;
+ uint8_t *source = malloc(length);
+ memcpy(source, RSTRING_PTR(contents), length);
+ *string = (pm_string_t) { .type = PM_STRING_OWNED, .source = source, .length = length };
+
+ return PM_STRING_INIT_SUCCESS;
+ }
+
+ // mmap the file descriptor to virtually get the contents
+ size_t size = (size_t) sb.st_size;
+ uint8_t *source = NULL;
+
+ if (size == 0) {
+ close(fd);
+ const uint8_t source[] = "";
+ *string = (pm_string_t) { .type = PM_STRING_CONSTANT, .source = source, .length = 0 };
+ return PM_STRING_INIT_SUCCESS;
+ }
+
+ source = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (source == MAP_FAILED) {
+ close(fd);
+ return PM_STRING_INIT_ERROR_GENERIC;
+ }
+
+ close(fd);
+ *string = (pm_string_t) { .type = PM_STRING_MAPPED, .source = source, .length = size };
+ return PM_STRING_INIT_SUCCESS;
+#else
+ return pm_string_file_init(string, filepath);
+#endif
+}
+
/**
* Attempt to load the file into memory. Return a Ruby error if the file cannot
* be read.
@@ -10077,32 +11351,38 @@ pm_parse_file_script_lines(const pm_scope_node_t *scope_node, const pm_parser_t
VALUE
pm_load_file(pm_parse_result_t *result, VALUE filepath, bool load_error)
{
- if (!pm_string_mapped_init(&result->input, RSTRING_PTR(filepath))) {
+ pm_string_init_result_t init_result = pm_read_file(&result->input, RSTRING_PTR(filepath));
+
+ if (init_result == PM_STRING_INIT_SUCCESS) {
+ pm_options_frozen_string_literal_init(&result->options);
+ return Qnil;
+ }
+
+ int err;
+ if (init_result == PM_STRING_INIT_ERROR_DIRECTORY) {
+ err = EISDIR;
+ } else {
#ifdef _WIN32
- int e = rb_w32_map_errno(GetLastError());
+ err = rb_w32_map_errno(GetLastError());
#else
- int e = errno;
+ err = errno;
#endif
+ }
- VALUE error;
-
- if (load_error) {
- VALUE message = rb_str_buf_new_cstr(strerror(e));
- rb_str_cat2(message, " -- ");
- rb_str_append(message, filepath);
-
- error = rb_exc_new3(rb_eLoadError, message);
- rb_ivar_set(error, rb_intern_const("@path"), filepath);
- } else {
- error = rb_syserr_new(e, RSTRING_PTR(filepath));
- RB_GC_GUARD(filepath);
- }
+ VALUE error;
+ if (load_error) {
+ VALUE message = rb_str_buf_new_cstr(strerror(err));
+ rb_str_cat2(message, " -- ");
+ rb_str_append(message, filepath);
- return error;
+ error = rb_exc_new3(rb_eLoadError, message);
+ rb_ivar_set(error, rb_intern_const("@path"), filepath);
+ } else {
+ error = rb_syserr_new(err, RSTRING_PTR(filepath));
+ RB_GC_GUARD(filepath);
}
- pm_options_frozen_string_literal_init(&result->options);
- return Qnil;
+ return error;
}
/**
@@ -10112,16 +11392,18 @@ pm_load_file(pm_parse_result_t *result, VALUE filepath, bool load_error)
* is zeroed out.
*/
VALUE
-pm_parse_file(pm_parse_result_t *result, VALUE filepath)
+pm_parse_file(pm_parse_result_t *result, VALUE filepath, VALUE *script_lines)
{
result->node.filepath_encoding = rb_enc_get(filepath);
pm_options_filepath_set(&result->options, RSTRING_PTR(filepath));
RB_GC_GUARD(filepath);
+ pm_options_version_for_current_ruby_set(&result->options);
+
pm_parser_init(&result->parser, pm_string_source(&result->input), pm_string_length(&result->input), &result->options);
pm_node_t *node = pm_parse(&result->parser);
- VALUE error = pm_parse_process(result, node);
+ VALUE error = pm_parse_process(result, node, script_lines);
// If we're parsing a filepath, then we need to potentially support the
// SCRIPT_LINES__ constant, which can be a hash that has an array of lines
@@ -10129,10 +11411,10 @@ pm_parse_file(pm_parse_result_t *result, VALUE filepath)
ID id_script_lines = rb_intern("SCRIPT_LINES__");
if (rb_const_defined_at(rb_cObject, id_script_lines)) {
- VALUE script_lines = rb_const_get_at(rb_cObject, id_script_lines);
+ VALUE constant_script_lines = rb_const_get_at(rb_cObject, id_script_lines);
- if (RB_TYPE_P(script_lines, T_HASH)) {
- rb_hash_aset(script_lines, filepath, pm_parse_file_script_lines(&result->node, &result->parser));
+ if (RB_TYPE_P(constant_script_lines, T_HASH)) {
+ rb_hash_aset(constant_script_lines, filepath, pm_parse_file_script_lines(&result->node, &result->parser));
}
}
@@ -10144,11 +11426,11 @@ pm_parse_file(pm_parse_result_t *result, VALUE filepath)
* cannot be read or if it cannot be parsed properly.
*/
VALUE
-pm_load_parse_file(pm_parse_result_t *result, VALUE filepath)
+pm_load_parse_file(pm_parse_result_t *result, VALUE filepath, VALUE *script_lines)
{
VALUE error = pm_load_file(result, filepath, false);
if (NIL_P(error)) {
- error = pm_parse_file(result, filepath);
+ error = pm_parse_file(result, filepath, script_lines);
}
return error;
@@ -10161,7 +11443,7 @@ pm_load_parse_file(pm_parse_result_t *result, VALUE filepath)
* error is returned.
*/
VALUE
-pm_parse_string(pm_parse_result_t *result, VALUE source, VALUE filepath)
+pm_parse_string(pm_parse_result_t *result, VALUE source, VALUE filepath, VALUE *script_lines)
{
rb_encoding *encoding = rb_enc_get(source);
if (!rb_enc_asciicompat(encoding)) {
@@ -10176,12 +11458,28 @@ pm_parse_string(pm_parse_result_t *result, VALUE source, VALUE filepath)
pm_options_filepath_set(&result->options, RSTRING_PTR(filepath));
RB_GC_GUARD(filepath);
+ pm_options_version_for_current_ruby_set(&result->options);
+
pm_parser_init(&result->parser, pm_string_source(&result->input), pm_string_length(&result->input), &result->options);
pm_node_t *node = pm_parse(&result->parser);
- return pm_parse_process(result, node);
+ return pm_parse_process(result, node, script_lines);
+}
+
+struct rb_stdin_wrapper {
+ VALUE rb_stdin;
+ int eof_seen;
+};
+
+static int
+pm_parse_stdin_eof(void *stream)
+{
+ struct rb_stdin_wrapper * wrapped_stdin = (struct rb_stdin_wrapper *)stream;
+ return wrapped_stdin->eof_seen;
}
+VALUE rb_io_gets_limit_internal(VALUE io, long limit);
+
/**
* An implementation of fgets that is suitable for use with Ruby IO objects.
*/
@@ -10190,20 +11488,32 @@ pm_parse_stdin_fgets(char *string, int size, void *stream)
{
RUBY_ASSERT(size > 0);
- VALUE line = rb_funcall((VALUE) stream, rb_intern("gets"), 1, INT2FIX(size - 1));
+ struct rb_stdin_wrapper * wrapped_stdin = (struct rb_stdin_wrapper *)stream;
+
+ VALUE line = rb_io_gets_limit_internal(wrapped_stdin->rb_stdin, size - 1);
if (NIL_P(line)) {
return NULL;
}
- const char *cstr = StringValueCStr(line);
- size_t length = strlen(cstr);
+ const char *cstr = RSTRING_PTR(line);
+ long length = RSTRING_LEN(line);
memcpy(string, cstr, length);
string[length] = '\0';
+ // We're reading strings from stdin via gets. We'll assume that if the
+ // string is smaller than the requested length, and doesn't end with a
+ // newline, that we hit EOF.
+ if (length < (size - 1) && string[length - 1] != '\n') {
+ wrapped_stdin->eof_seen = 1;
+ }
+
return string;
}
+// We need access to this function when we're done parsing stdin.
+void rb_reset_argf_lineno(long n);
+
/**
* Parse the source off STDIN and store the resulting scope node in the given
* parse result struct. It is assumed that the parse result object is zeroed
@@ -10214,15 +11524,31 @@ pm_parse_stdin(pm_parse_result_t *result)
{
pm_options_frozen_string_literal_init(&result->options);
+ struct rb_stdin_wrapper wrapped_stdin = {
+ rb_stdin,
+ 0
+ };
+
pm_buffer_t buffer;
- pm_node_t *node = pm_parse_stream(&result->parser, &buffer, (void *) rb_stdin, pm_parse_stdin_fgets, &result->options);
+ pm_node_t *node = pm_parse_stream(&result->parser, &buffer, (void *) &wrapped_stdin, pm_parse_stdin_fgets, pm_parse_stdin_eof, &result->options);
// Copy the allocated buffer contents into the input string so that it gets
// freed. At this point we've handed over ownership, so we don't need to
// free the buffer itself.
pm_string_owned_init(&result->input, (uint8_t *) pm_buffer_value(&buffer), pm_buffer_length(&buffer));
- return pm_parse_process(result, node);
+ // When we're done parsing, we reset $. because we don't want the fact that
+ // we went through an IO object to be visible to the user.
+ rb_reset_argf_lineno(0);
+
+ return pm_parse_process(result, node, NULL);
+}
+
+#define PM_VERSION_FOR_RELEASE(major, minor) PM_VERSION_FOR_RELEASE_IMPL(major, minor)
+#define PM_VERSION_FOR_RELEASE_IMPL(major, minor) PM_OPTIONS_VERSION_CRUBY_##major##_##minor
+
+void pm_options_version_for_current_ruby_set(pm_options_t *options) {
+ options->version = PM_VERSION_FOR_RELEASE(RUBY_API_VERSION_MAJOR, RUBY_API_VERSION_MINOR);
}
#undef NEW_ISEQ
diff --git a/prism_compile.h b/prism_compile.h
index 8df82c5c7c..e588122205 100644
--- a/prism_compile.h
+++ b/prism_compile.h
@@ -30,6 +30,16 @@ typedef struct pm_scope_node {
rb_encoding *encoding;
/**
+ * This is a pointer to the list of script lines for the ISEQs that will be
+ * associated with this scope node. It is only set if
+ * RubyVM.keep_script_lines is true. If it is set, it will be set to a
+ * pointer to an array that is always stack allocated (so no GC marking is
+ * needed by this struct). If it is not set, it will be NULL. It is
+ * inherited by all child scopes.
+ */
+ VALUE *script_lines;
+
+ /**
* This is the encoding of the actual filepath object that will be used when
* a __FILE__ node is compiled or when the path has to be set on a syntax
* error.
@@ -55,7 +65,6 @@ typedef struct pm_scope_node {
void pm_scope_node_init(const pm_node_t *node, pm_scope_node_t *scope, pm_scope_node_t *previous);
void pm_scope_node_destroy(pm_scope_node_t *scope_node);
-bool *rb_ruby_prism_ptr(void);
typedef struct {
/** The parser that will do the actual parsing. */
@@ -74,17 +83,24 @@ typedef struct {
bool parsed;
} pm_parse_result_t;
+#define PM_SPECIAL_CONSTANT_FLAG ((pm_constant_id_t)(1 << 31))
+#define PM_CONSTANT_AND ((pm_constant_id_t)(idAnd | PM_SPECIAL_CONSTANT_FLAG))
+#define PM_CONSTANT_DOT3 ((pm_constant_id_t)(idDot3 | PM_SPECIAL_CONSTANT_FLAG))
+#define PM_CONSTANT_MULT ((pm_constant_id_t)(idMULT | PM_SPECIAL_CONSTANT_FLAG))
+#define PM_CONSTANT_POW ((pm_constant_id_t)(idPow | PM_SPECIAL_CONSTANT_FLAG))
+
VALUE pm_load_file(pm_parse_result_t *result, VALUE filepath, bool load_error);
-VALUE pm_parse_file(pm_parse_result_t *result, VALUE filepath);
-VALUE pm_load_parse_file(pm_parse_result_t *result, VALUE filepath);
-VALUE pm_parse_string(pm_parse_result_t *result, VALUE source, VALUE filepath);
+VALUE pm_parse_file(pm_parse_result_t *result, VALUE filepath, VALUE *script_lines);
+VALUE pm_load_parse_file(pm_parse_result_t *result, VALUE filepath, VALUE *script_lines);
+VALUE pm_parse_string(pm_parse_result_t *result, VALUE source, VALUE filepath, VALUE *script_lines);
VALUE pm_parse_stdin(pm_parse_result_t *result);
+void pm_options_version_for_current_ruby_set(pm_options_t *options);
void pm_parse_result_free(pm_parse_result_t *result);
-rb_iseq_t *pm_iseq_new(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent, enum rb_iseq_type);
-rb_iseq_t *pm_iseq_new_top(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent);
-rb_iseq_t *pm_iseq_new_main(pm_scope_node_t *node, VALUE path, VALUE realpath, const rb_iseq_t *parent, int opt);
-rb_iseq_t *pm_iseq_new_eval(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_iseq_t *parent, int isolated_depth);
-rb_iseq_t *pm_iseq_new_with_opt(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_iseq_t *parent, int isolated_depth, enum rb_iseq_type, const rb_compile_option_t*);
+rb_iseq_t *pm_iseq_new(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent, enum rb_iseq_type, int *error_state);
+rb_iseq_t *pm_iseq_new_top(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent, int *error_state);
+rb_iseq_t *pm_iseq_new_main(pm_scope_node_t *node, VALUE path, VALUE realpath, const rb_iseq_t *parent, int opt, int *error_state);
+rb_iseq_t *pm_iseq_new_eval(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_iseq_t *parent, int isolated_depth, int *error_state);
+rb_iseq_t *pm_iseq_new_with_opt(pm_scope_node_t *node, VALUE name, VALUE path, VALUE realpath, int first_lineno, const rb_iseq_t *parent, int isolated_depth, enum rb_iseq_type, const rb_compile_option_t *option, int *error_state);
VALUE pm_iseq_compile_node(rb_iseq_t *iseq, pm_scope_node_t *node);
diff --git a/proc.c b/proc.c
index 1a67a63663..5f23e5fed6 100644
--- a/proc.c
+++ b/proc.c
@@ -15,12 +15,14 @@
#include "internal/error.h"
#include "internal/eval.h"
#include "internal/gc.h"
+#include "internal/hash.h"
#include "internal/object.h"
#include "internal/proc.h"
#include "internal/symbol.h"
#include "method.h"
#include "iseq.h"
#include "vm_core.h"
+#include "ractor_core.h"
#include "yjit.h"
const rb_cref_t *rb_vm_cref_in_context(VALUE self, VALUE cbase);
@@ -296,10 +298,8 @@ rb_binding_alloc(VALUE klass)
return obj;
}
-
-/* :nodoc: */
static VALUE
-binding_dup(VALUE self)
+binding_copy(VALUE self)
{
VALUE bindval = rb_binding_alloc(rb_cBinding);
rb_binding_t *src, *dst;
@@ -308,15 +308,21 @@ binding_dup(VALUE self)
rb_vm_block_copy(bindval, &dst->block, &src->block);
RB_OBJ_WRITE(bindval, &dst->pathobj, src->pathobj);
dst->first_lineno = src->first_lineno;
- return rb_obj_dup_setup(self, bindval);
+ return bindval;
+}
+
+/* :nodoc: */
+static VALUE
+binding_dup(VALUE self)
+{
+ return rb_obj_dup_setup(self, binding_copy(self));
}
/* :nodoc: */
static VALUE
binding_clone(VALUE self)
{
- VALUE bindval = binding_dup(self);
- return rb_obj_clone_setup(self, bindval, Qnil);
+ return rb_obj_clone_setup(self, binding_copy(self), Qnil);
}
VALUE
@@ -403,7 +409,7 @@ bind_eval(int argc, VALUE *argv, VALUE bindval)
}
static const VALUE *
-get_local_variable_ptr(const rb_env_t **envp, ID lid)
+get_local_variable_ptr(const rb_env_t **envp, ID lid, bool search_outer)
{
const rb_env_t *env = *envp;
do {
@@ -413,11 +419,11 @@ get_local_variable_ptr(const rb_env_t **envp, ID lid)
}
const rb_iseq_t *iseq = env->iseq;
- unsigned int i;
VM_ASSERT(rb_obj_is_iseq((VALUE)iseq));
- for (i=0; i<ISEQ_BODY(iseq)->local_table_size; i++) {
+ const unsigned int local_table_size = ISEQ_BODY(iseq)->local_table_size;
+ for (unsigned int i=0; i<local_table_size; i++) {
if (ISEQ_BODY(iseq)->local_table[i] == lid) {
if (ISEQ_BODY(iseq)->local_iseq == iseq &&
ISEQ_BODY(iseq)->param.flags.has_block &&
@@ -430,7 +436,9 @@ get_local_variable_ptr(const rb_env_t **envp, ID lid)
}
*envp = env;
- return &env->env[i];
+ unsigned int last_lvar = env->env_size+VM_ENV_INDEX_LAST_LVAR
+ - 1 /* errinfo */;
+ return &env->env[last_lvar - (local_table_size - i)];
}
}
}
@@ -438,7 +446,7 @@ get_local_variable_ptr(const rb_env_t **envp, ID lid)
*envp = NULL;
return NULL;
}
- } while ((env = rb_vm_env_prev_env(env)) != NULL);
+ } while (search_outer && (env = rb_vm_env_prev_env(env)) != NULL);
*envp = NULL;
return NULL;
@@ -500,6 +508,18 @@ bind_local_variables(VALUE bindval)
return rb_vm_env_local_variables(env);
}
+int
+rb_numparam_id_p(ID id)
+{
+ return (tNUMPARAM_1 << ID_SCOPE_SHIFT) <= id && id < ((tNUMPARAM_1 + 9) << ID_SCOPE_SHIFT);
+}
+
+int
+rb_implicit_param_p(ID id)
+{
+ return id == idItImplicit || rb_numparam_id_p(id);
+}
+
/*
* call-seq:
* binding.local_variable_get(symbol) -> obj
@@ -526,11 +546,15 @@ bind_local_variable_get(VALUE bindval, VALUE sym)
const rb_env_t *env;
if (!lid) goto undefined;
+ if (rb_numparam_id_p(lid)) {
+ rb_name_err_raise("numbered parameter '%1$s' is not a local variable",
+ bindval, ID2SYM(lid));
+ }
GetBindingPtr(bindval, bind);
env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
- if ((ptr = get_local_variable_ptr(&env, lid)) != NULL) {
+ if ((ptr = get_local_variable_ptr(&env, lid, TRUE)) != NULL) {
return *ptr;
}
@@ -575,10 +599,14 @@ bind_local_variable_set(VALUE bindval, VALUE sym, VALUE val)
const rb_env_t *env;
if (!lid) lid = rb_intern_str(sym);
+ if (rb_numparam_id_p(lid)) {
+ rb_name_err_raise("numbered parameter '%1$s' is not a local variable",
+ bindval, ID2SYM(lid));
+ }
GetBindingPtr(bindval, bind);
env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
- if ((ptr = get_local_variable_ptr(&env, lid)) == NULL) {
+ if ((ptr = get_local_variable_ptr(&env, lid, TRUE)) == NULL) {
/* not found. create new env */
ptr = rb_binding_add_dynavars(bindval, bind, 1, &lid);
env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
@@ -618,10 +646,140 @@ bind_local_variable_defined_p(VALUE bindval, VALUE sym)
const rb_env_t *env;
if (!lid) return Qfalse;
+ if (rb_numparam_id_p(lid)) {
+ rb_name_err_raise("numbered parameter '%1$s' is not a local variable",
+ bindval, ID2SYM(lid));
+ }
GetBindingPtr(bindval, bind);
env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
- return RBOOL(get_local_variable_ptr(&env, lid));
+ return RBOOL(get_local_variable_ptr(&env, lid, TRUE));
+}
+
+/*
+ * call-seq:
+ * binding.implicit_parameters -> Array
+ *
+ * Returns the names of numbered parameters and "it" parameter
+ * that are defined in the binding.
+ *
+ * def foo
+ * [42].each do
+ * it
+ * binding.implicit_parameters #=> [:it]
+ * end
+ *
+ * { k: 42 }.each do
+ * _2
+ * binding.implicit_parameters #=> [:_1, :_2]
+ * end
+ * end
+ *
+ */
+static VALUE
+bind_implicit_parameters(VALUE bindval)
+{
+ const rb_binding_t *bind;
+ const rb_env_t *env;
+
+ GetBindingPtr(bindval, bind);
+ env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
+
+ if (get_local_variable_ptr(&env, idItImplicit, FALSE)) {
+ return rb_ary_new_from_args(1, ID2SYM(idIt));
+ }
+
+ env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
+ return rb_vm_env_numbered_parameters(env);
+}
+
+/*
+ * call-seq:
+ * binding.implicit_parameter_get(symbol) -> obj
+ *
+ * Returns the value of the numbered parameter or "it" parameter.
+ *
+ * def foo
+ * [42].each do
+ * it
+ * binding.implicit_parameter_get(:it) #=> 42
+ * end
+ *
+ * { k: 42 }.each do
+ * _2
+ * binding.implicit_parameter_get(:_1) #=> :k
+ * binding.implicit_parameter_get(:_2) #=> 42
+ * end
+ * end
+ *
+ */
+static VALUE
+bind_implicit_parameter_get(VALUE bindval, VALUE sym)
+{
+ ID lid = check_local_id(bindval, &sym);
+ const rb_binding_t *bind;
+ const VALUE *ptr;
+ const rb_env_t *env;
+
+ if (lid == idIt) lid = idItImplicit;
+
+ if (!lid || !rb_implicit_param_p(lid)) {
+ rb_name_err_raise("'%1$s' is not an implicit parameter",
+ bindval, sym);
+ }
+
+ GetBindingPtr(bindval, bind);
+
+ env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
+ if ((ptr = get_local_variable_ptr(&env, lid, FALSE)) != NULL) {
+ return *ptr;
+ }
+
+ if (lid == idItImplicit) lid = idIt;
+ rb_name_err_raise("implicit parameter '%1$s' is not defined for %2$s", bindval, ID2SYM(lid));
+ UNREACHABLE_RETURN(Qundef);
+}
+
+/*
+ * call-seq:
+ * binding.implicit_parameter_defined?(symbol) -> obj
+ *
+ * Returns +true+ if the numbered parameter or "it" parameter exists.
+ *
+ * def foo
+ * [42].each do
+ * it
+ * binding.implicit_parameter_defined?(:it) #=> true
+ * binding.implicit_parameter_defined?(:_1) #=> false
+ * end
+ *
+ * { k: 42 }.each do
+ * _2
+ * binding.implicit_parameter_defined?(:_1) #=> true
+ * binding.implicit_parameter_defined?(:_2) #=> true
+ * binding.implicit_parameter_defined?(:_3) #=> false
+ * binding.implicit_parameter_defined?(:it) #=> false
+ * end
+ * end
+ *
+ */
+static VALUE
+bind_implicit_parameter_defined_p(VALUE bindval, VALUE sym)
+{
+ ID lid = check_local_id(bindval, &sym);
+ const rb_binding_t *bind;
+ const rb_env_t *env;
+
+ if (lid == idIt) lid = idItImplicit;
+
+ if (!lid || !rb_implicit_param_p(lid)) {
+ rb_name_err_raise("'%1$s' is not an implicit parameter",
+ bindval, sym);
+ }
+
+ GetBindingPtr(bindval, bind);
+ env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block));
+ return RBOOL(get_local_variable_ptr(&env, lid, FALSE));
}
/*
@@ -679,6 +837,32 @@ cfunc_proc_new(VALUE klass, VALUE ifunc)
return procval;
}
+VALUE
+rb_func_proc_dup(VALUE src_obj)
+{
+ RUBY_ASSERT(rb_typeddata_is_instance_of(src_obj, &proc_data_type));
+
+ rb_proc_t *src_proc;
+ GetProcPtr(src_obj, src_proc);
+ RUBY_ASSERT(vm_block_type(&src_proc->block) == block_type_ifunc);
+
+ cfunc_proc_t *proc;
+ VALUE proc_obj = TypedData_Make_Struct(rb_obj_class(src_obj), cfunc_proc_t, &proc_data_type, proc);
+
+ memcpy(&proc->basic, src_proc, sizeof(rb_proc_t));
+ RB_OBJ_WRITTEN(proc_obj, Qundef, proc->basic.block.as.captured.self);
+ RB_OBJ_WRITTEN(proc_obj, Qundef, proc->basic.block.as.captured.code.val);
+
+ const VALUE *src_ep = src_proc->block.as.captured.ep;
+ VALUE *ep = *(VALUE **)&proc->basic.block.as.captured.ep = proc->env + VM_ENV_DATA_SIZE - 1;
+ ep[VM_ENV_DATA_INDEX_FLAGS] = src_ep[VM_ENV_DATA_INDEX_FLAGS];
+ ep[VM_ENV_DATA_INDEX_ME_CREF] = src_ep[VM_ENV_DATA_INDEX_ME_CREF];
+ ep[VM_ENV_DATA_INDEX_SPECVAL] = src_ep[VM_ENV_DATA_INDEX_SPECVAL];
+ RB_OBJ_WRITE(proc_obj, &ep[VM_ENV_DATA_INDEX_ENV], src_ep[VM_ENV_DATA_INDEX_ENV]);
+
+ return proc_obj;
+}
+
static VALUE
sym_proc_new(VALUE klass, VALUE sym)
{
@@ -695,11 +879,6 @@ sym_proc_new(VALUE klass, VALUE sym)
struct vm_ifunc *
rb_vm_ifunc_new(rb_block_call_func_t func, const void *data, int min_argc, int max_argc)
{
- union {
- struct vm_ifunc_argc argc;
- VALUE packed;
- } arity;
-
if (min_argc < UNLIMITED_ARGUMENTS ||
#if SIZEOF_INT * 2 > SIZEOF_VALUE
min_argc >= (int)(1U << (SIZEOF_VALUE * CHAR_BIT) / 2) ||
@@ -716,26 +895,21 @@ rb_vm_ifunc_new(rb_block_call_func_t func, const void *data, int min_argc, int m
rb_raise(rb_eRangeError, "maximum argument number out of range: %d",
max_argc);
}
- arity.argc.min = min_argc;
- arity.argc.max = max_argc;
rb_execution_context_t *ec = GET_EC();
struct vm_ifunc *ifunc = IMEMO_NEW(struct vm_ifunc, imemo_ifunc, (VALUE)rb_vm_svar_lep(ec, ec->cfp));
+
+ rb_gc_register_pinning_obj((VALUE)ifunc);
+
ifunc->func = func;
ifunc->data = data;
- ifunc->argc = arity.argc;
+ ifunc->argc.min = min_argc;
+ ifunc->argc.max = max_argc;
return ifunc;
}
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);
-}
-
-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);
@@ -840,7 +1014,7 @@ f_lambda_filter_non_literal(void)
VALUE block_handler = rb_vm_frame_block_handler(cfp);
if (block_handler == VM_BLOCK_HANDLER_NONE) {
- // no block erorr raised else where
+ // no block error raised else where
return;
}
@@ -897,13 +1071,12 @@ f_lambda(VALUE _)
* Document-method: Proc#yield
*
* call-seq:
- * prc.call(params,...) -> obj
- * prc[params,...] -> obj
- * prc.(params,...) -> obj
- * prc.yield(params,...) -> obj
+ * call(...) -> obj
+ * self[...] -> obj
+ * yield(...) -> obj
*
- * Invokes the block, setting the block's parameters to the values in
- * <i>params</i> using something close to method calling semantics.
+ * Invokes the block, setting the block's parameters to the arguments
+ * using something close to method calling semantics.
* Returns the value of the last expression evaluated in the block.
*
* a_proc = Proc.new {|scalar, *values| values.map {|value| value*scalar } }
@@ -1050,7 +1223,7 @@ rb_iseq_min_max_arity(const rb_iseq_t *iseq, int *max)
{
*max = ISEQ_BODY(iseq)->param.flags.has_rest == FALSE ?
ISEQ_BODY(iseq)->param.lead_num + ISEQ_BODY(iseq)->param.opt_num + ISEQ_BODY(iseq)->param.post_num +
- (ISEQ_BODY(iseq)->param.flags.has_kw == TRUE || ISEQ_BODY(iseq)->param.flags.has_kwrest == TRUE)
+ (ISEQ_BODY(iseq)->param.flags.has_kw == TRUE || ISEQ_BODY(iseq)->param.flags.has_kwrest == TRUE || ISEQ_BODY(iseq)->param.flags.forwardable == TRUE)
: UNLIMITED_ARGUMENTS;
return ISEQ_BODY(iseq)->param.lead_num + ISEQ_BODY(iseq)->param.post_num + (ISEQ_BODY(iseq)->param.flags.has_kw && ISEQ_BODY(iseq)->param.keyword->required_num > 0);
}
@@ -1146,10 +1319,10 @@ rb_block_pair_yield_optimizable(void)
min = rb_vm_block_min_max_arity(&block, &max);
switch (vm_block_type(&block)) {
- case block_handler_type_symbol:
+ case block_type_symbol:
return 0;
- case block_handler_type_proc:
+ case block_type_proc:
{
VALUE procval = block_handler;
rb_proc_t *proc;
@@ -1159,6 +1332,12 @@ rb_block_pair_yield_optimizable(void)
return min > 1;
}
+ case block_type_ifunc:
+ {
+ const struct vm_ifunc *ifunc = block.as.captured.code.ifunc;
+ if (ifunc->flags & IFUNC_YIELD_OPTIMIZABLE) return 1;
+ }
+
default:
return min > 1;
}
@@ -1180,10 +1359,10 @@ rb_block_arity(void)
block_setup(&block, block_handler);
switch (vm_block_type(&block)) {
- case block_handler_type_symbol:
+ case block_type_symbol:
return -1;
- case block_handler_type_proc:
+ case block_type_proc:
return rb_proc_arity(block_handler);
default:
@@ -1244,10 +1423,10 @@ rb_proc_get_iseq(VALUE self, int *is_proc)
}
/* call-seq:
- * prc == other -> true or false
- * prc.eql?(other) -> true or false
+ * self == other -> true or false
+ * eql?(other) -> true or false
*
- * Two procs are the same if, and only if, they were created from the same code block.
+ * Returns whether +self+ and +other+ were created from the same code block:
*
* def return_block(&block)
* block
@@ -1304,12 +1483,17 @@ proc_eq(VALUE self, VALUE other)
}
break;
case block_type_ifunc:
- if (self_block->as.captured.ep != \
- other_block->as.captured.ep ||
- self_block->as.captured.code.ifunc != \
+ if (self_block->as.captured.code.ifunc != \
other_block->as.captured.code.ifunc) {
return Qfalse;
}
+
+ if (memcmp(
+ ((cfunc_proc_t *)self_proc)->env,
+ ((cfunc_proc_t *)other_proc)->env,
+ sizeof(((cfunc_proc_t *)self_proc)->env))) {
+ return Qfalse;
+ }
break;
case block_type_proc:
if (self_block->as.proc != other_block->as.proc) {
@@ -1329,14 +1513,20 @@ proc_eq(VALUE self, VALUE other)
static VALUE
iseq_location(const rb_iseq_t *iseq)
{
- VALUE loc[2];
+ VALUE loc[5];
+ int i = 0;
if (!iseq) return Qnil;
rb_iseq_check(iseq);
- loc[0] = rb_iseq_path(iseq);
- loc[1] = RB_INT2NUM(ISEQ_BODY(iseq)->location.first_lineno);
+ loc[i++] = rb_iseq_path(iseq);
+ const rb_code_location_t *cl = &ISEQ_BODY(iseq)->location.code_location;
+ loc[i++] = RB_INT2NUM(cl->beg_pos.lineno);
+ loc[i++] = RB_INT2NUM(cl->beg_pos.column);
+ loc[i++] = RB_INT2NUM(cl->end_pos.lineno);
+ loc[i++] = RB_INT2NUM(cl->end_pos.column);
+ RUBY_ASSERT_ALWAYS(i == numberof(loc));
- return rb_ary_new4(2, loc);
+ return rb_ary_new_from_values(i, loc);
}
VALUE
@@ -1347,10 +1537,17 @@ rb_iseq_location(const rb_iseq_t *iseq)
/*
* call-seq:
- * prc.source_location -> [String, Integer]
+ * prc.source_location -> [String, Integer, Integer, Integer, Integer]
+ *
+ * Returns the location where the Proc was defined.
+ * The returned Array contains:
+ * (1) the Ruby source filename
+ * (2) the line number where the definition starts
+ * (3) the position where the definition starts, in number of bytes from the start of the line
+ * (4) the line number where the definition ends
+ * (5) the position where the definitions ends, in number of bytes from the start of the line
*
- * Returns the Ruby source filename and line number containing this proc
- * or +nil+ if this proc was not defined in Ruby (i.e. native).
+ * This method will return +nil+ if the Proc was not defined in Ruby (i.e. native).
*/
VALUE
@@ -1431,11 +1628,36 @@ rb_hash_proc(st_index_t hash, VALUE prc)
{
rb_proc_t *proc;
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);
+
+ switch (vm_block_type(&proc->block)) {
+ case block_type_iseq:
+ hash = rb_st_hash_uint(hash, (st_index_t)proc->block.as.captured.code.iseq->body);
+ break;
+ case block_type_ifunc:
+ hash = rb_st_hash_uint(hash, (st_index_t)proc->block.as.captured.code.ifunc->func);
+ hash = rb_st_hash_uint(hash, (st_index_t)proc->block.as.captured.code.ifunc->data);
+ break;
+ case block_type_symbol:
+ hash = rb_st_hash_uint(hash, rb_any_hash(proc->block.as.symbol));
+ break;
+ case block_type_proc:
+ hash = rb_st_hash_uint(hash, rb_any_hash(proc->block.as.proc));
+ break;
+ default:
+ rb_bug("rb_hash_proc: unknown block type %d", vm_block_type(&proc->block));
+ }
+
+ /* ifunc procs have their own allocated ep. If an ifunc is duplicated, they
+ * will point to different ep but they should return the same hash code, so
+ * we cannot include the ep in the hash. */
+ if (vm_block_type(&proc->block) != block_type_ifunc) {
+ hash = rb_hash_uint(hash, (st_index_t)proc->block.as.captured.ep);
+ }
+
+ return hash;
}
+static VALUE sym_proc_cache = Qfalse;
/*
* call-seq:
@@ -1454,29 +1676,33 @@ rb_hash_proc(st_index_t hash, VALUE prc)
VALUE
rb_sym_to_proc(VALUE sym)
{
- static VALUE sym_proc_cache = Qfalse;
enum {SYM_PROC_CACHE_SIZE = 67};
- VALUE proc;
- long index;
- ID id;
- if (!sym_proc_cache) {
- sym_proc_cache = rb_ary_hidden_new(SYM_PROC_CACHE_SIZE * 2);
- rb_vm_register_global_object(sym_proc_cache);
- rb_ary_store(sym_proc_cache, SYM_PROC_CACHE_SIZE*2 - 1, Qnil);
- }
+ if (rb_ractor_main_p()) {
+ if (!sym_proc_cache) {
+ sym_proc_cache = rb_ary_hidden_new(SYM_PROC_CACHE_SIZE);
+ rb_ary_store(sym_proc_cache, SYM_PROC_CACHE_SIZE - 1, Qnil);
+ }
+
+ ID id = SYM2ID(sym);
+ long index = (id % SYM_PROC_CACHE_SIZE);
+ VALUE procval = RARRAY_AREF(sym_proc_cache, index);
+ if (RTEST(procval)) {
+ rb_proc_t *proc;
+ GetProcPtr(procval, proc);
- id = SYM2ID(sym);
- index = (id % SYM_PROC_CACHE_SIZE) << 1;
+ if (proc->block.as.symbol == sym) {
+ return procval;
+ }
+ }
- if (RARRAY_AREF(sym_proc_cache, index) == sym) {
- return RARRAY_AREF(sym_proc_cache, index + 1);
+ procval = sym_proc_new(rb_cProc, sym);
+ RARRAY_ASET(sym_proc_cache, index, procval);
+
+ return RB_GC_GUARD(procval);
}
else {
- proc = sym_proc_new(rb_cProc, ID2SYM(id));
- RARRAY_ASET(sym_proc_cache, index, sym);
- RARRAY_ASET(sym_proc_cache, index + 1, proc);
- return proc;
+ return sym_proc_new(rb_cProc, sym);
}
}
@@ -1580,7 +1806,7 @@ static const rb_data_type_t method_data_type = {
NULL, // No external memory to report,
bm_mark_and_move,
},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE | RUBY_TYPED_FROZEN_SHAREABLE_NO_REC
};
VALUE
@@ -1728,7 +1954,7 @@ method_entry_defined_class(const rb_method_entry_t *me)
*
* Document-class: Method
*
- * Method objects are created by Object#method, and are associated
+ * +Method+ objects are created by Object#method, and are associated
* with a particular object (not just with a class). They may be
* used to invoke the method within the object, and as a block
* associated with an iterator. They may also be unbound from one
@@ -1754,10 +1980,9 @@ method_entry_defined_class(const rb_method_entry_t *me)
/*
* call-seq:
- * meth.eql?(other_meth) -> true or false
- * meth == other_meth -> true or false
+ * self == other -> true or false
*
- * Two method objects are equal if they are bound to the same
+ * Returns whether +self+ and +other+ are bound to the same
* object and refer to the same method definition and the classes
* defining the methods are the same class or module.
*/
@@ -1938,6 +2163,26 @@ method_owner(VALUE obj)
return data->owner;
}
+/*
+ * call-seq:
+ * meth.box -> box or nil
+ *
+ * Returns the Ruby::Box where +meth+ is defined in.
+ */
+static VALUE
+method_box(VALUE obj)
+{
+ struct METHOD *data;
+ const rb_box_t *box;
+
+ TypedData_Get_Struct(obj, struct METHOD, &method_data_type, data);
+ box = data->me->def->box;
+ if (!box) return Qnil;
+ if (box->box_object) return box->box_object;
+ rb_bug("Unexpected box on the method definition: %p", (void*) box);
+ UNREACHABLE_RETURN(Qnil);
+}
+
void
rb_method_name_error(VALUE klass, VALUE str)
{
@@ -1987,7 +2232,7 @@ obj_method(VALUE obj, VALUE vid, int scope)
* obj.method(sym) -> method
*
* Looks up the named method as a receiver in <i>obj</i>, returning a
- * Method object (or raising NameError). The Method object acts as a
+ * +Method+ object (or raising NameError). The +Method+ object acts as a
* closure in <i>obj</i>'s object instance, so instance variables and
* the value of <code>self</code> remain available.
*
@@ -2008,7 +2253,7 @@ obj_method(VALUE obj, VALUE vid, int scope)
* m = l.method("hello")
* m.call #=> "Hello, @iv = Fred"
*
- * Note that Method implements <code>to_proc</code> method, which
+ * Note that +Method+ implements <code>to_proc</code> method, which
* means it can be used with iterators.
*
* [ 1, 2, 3 ].each(&method(:puts)) # => prints 3 lines to stdout
@@ -2040,6 +2285,19 @@ rb_obj_public_method(VALUE obj, VALUE vid)
return obj_method(obj, vid, TRUE);
}
+static VALUE
+rb_obj_singleton_method_lookup(VALUE arg)
+{
+ VALUE *args = (VALUE *)arg;
+ return rb_obj_method(args[0], args[1]);
+}
+
+static VALUE
+rb_obj_singleton_method_lookup_fail(VALUE arg1, VALUE arg2)
+{
+ return Qfalse;
+}
+
/*
* call-seq:
* obj.singleton_method(sym) -> method
@@ -2067,11 +2325,12 @@ rb_obj_public_method(VALUE obj, VALUE vid)
VALUE
rb_obj_singleton_method(VALUE obj, VALUE vid)
{
- VALUE klass = rb_singleton_class_get(obj);
+ VALUE sc = rb_singleton_class_get(obj);
+ VALUE klass;
ID id = rb_check_id(&vid);
- if (NIL_P(klass) ||
- NIL_P(klass = RCLASS_ORIGIN(klass)) ||
+ if (NIL_P(sc) ||
+ NIL_P(klass = RCLASS_ORIGIN(sc)) ||
!NIL_P(rb_special_singleton_class(obj))) {
/* goto undef; */
}
@@ -2081,21 +2340,26 @@ rb_obj_singleton_method(VALUE obj, VALUE vid)
/* else 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);
+ VALUE args[2] = {obj, vid};
+ VALUE ruby_method = rb_rescue(rb_obj_singleton_method_lookup, (VALUE)args, rb_obj_singleton_method_lookup_fail, Qfalse);
+ if (ruby_method) {
+ struct METHOD *method = (struct METHOD *)RTYPEDDATA_GET_DATA(ruby_method);
+ VALUE lookup_class = RBASIC_CLASS(obj);
+ VALUE stop_class = rb_class_superclass(sc);
+ VALUE method_class = method->iclass;
+
+ /* Determine if method is in singleton class, or module included in or prepended to it */
+ do {
+ if (lookup_class == method_class) {
+ return ruby_method;
+ }
+ lookup_class = RCLASS_SUPER(lookup_class);
+ } while (lookup_class && lookup_class != stop_class);
}
}
/* undef: */
+ vid = ID2SYM(id);
rb_name_err_raise("undefined singleton method '%1$s' for '%2$s'",
obj, vid);
UNREACHABLE_RETURN(Qundef);
@@ -2107,29 +2371,29 @@ rb_obj_singleton_method(VALUE obj, VALUE vid)
*
* Returns an +UnboundMethod+ representing the given
* instance method in _mod_.
+ * See +UnboundMethod+ about how to utilize it
*
- * class Interpreter
- * def do_a() print "there, "; end
- * def do_d() print "Hello "; end
- * def do_e() print "!\n"; end
- * def do_v() print "Dave"; end
- * Dispatcher = {
- * "a" => instance_method(:do_a),
- * "d" => instance_method(:do_d),
- * "e" => instance_method(:do_e),
- * "v" => instance_method(:do_v)
- * }
- * def interpret(string)
- * string.each_char {|b| Dispatcher[b].bind(self).call }
- * end
- * end
+ * class Person
+ * def initialize(name)
+ * @name = name
+ * end
+ *
+ * def hi
+ * puts "Hi, I'm #{@name}!"
+ * end
+ * end
*
- * interpreter = Interpreter.new
- * interpreter.interpret('dave')
+ * dave = Person.new('Dave')
+ * thomas = Person.new('Thomas')
+ *
+ * hi = Person.instance_method(:hi)
+ * hi.bind_call(dave)
+ * hi.bind_call(thomas)
*
* <em>produces:</em>
*
- * Hello there, Dave!
+ * Hi, I'm Dave!
+ * Hi, I'm Thomas!
*/
static VALUE
@@ -2386,13 +2650,20 @@ method_dup(VALUE self)
return clone;
}
-/* Document-method: Method#===
- *
+/*
* call-seq:
- * method === obj -> result_of_method
+ * call(...) -> obj
+ * self[...] -> obj
+ * self === obj -> result_of_method
*
- * Invokes the method with +obj+ as the parameter like #call.
- * This allows a method object to be the target of a +when+ clause
+ * Invokes +self+ with the specified arguments, returning the
+ * method's return value.
+ *
+ * m = 12.method("+")
+ * m.call(3) #=> 15
+ * m.call(20) #=> 32
+ *
+ * Using Method#=== allows a method object to be the target of a +when+ clause
* in a case statement.
*
* require 'prime'
@@ -2403,32 +2674,6 @@ method_dup(VALUE self)
* end
*/
-
-/* Document-method: Method#[]
- *
- * call-seq:
- * meth[args, ...] -> obj
- *
- * Invokes the <i>meth</i> 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
- *
- * Invokes the <i>meth</i> with the specified arguments, returning the
- * method's return value.
- *
- * m = 12.method("+")
- * m.call(3) #=> 15
- * m.call(20) #=> 32
- */
-
static VALUE
rb_method_call_pass_called_kw(int argc, const VALUE *argv, VALUE method)
{
@@ -2488,7 +2733,7 @@ rb_method_call_with_block(int argc, const VALUE *argv, VALUE method, VALUE passe
*
* Document-class: UnboundMethod
*
- * Ruby supports two forms of objectified methods. Class Method is
+ * Ruby supports two forms of objectified methods. Class +Method+ is
* used to represent methods that are associated with a particular
* object: these method objects are bound to that object. Bound
* method objects for an object can be created using Object#method.
@@ -2951,10 +3196,17 @@ rb_method_entry_location(const rb_method_entry_t *me)
/*
* call-seq:
- * meth.source_location -> [String, Integer]
+ * meth.source_location -> [String, Integer, Integer, Integer, Integer]
+ *
+ * Returns the location where the method was defined.
+ * The returned Array contains:
+ * (1) the Ruby source filename
+ * (2) the line number where the definition starts
+ * (3) the position where the definition starts, in number of bytes from the start of the line
+ * (4) the line number where the definition ends
+ * (5) the position where the definitions ends, in number of bytes from the start of the line
*
- * Returns the Ruby source filename and line number containing this method
- * or nil if this method was not defined in Ruby (i.e. native).
+ * This method will return +nil+ if the method was not defined in Ruby (i.e. native).
*/
VALUE
@@ -3194,9 +3446,10 @@ method_inspect(VALUE method)
for (int i = 0; i < RARRAY_LEN(params); i++) {
pair = RARRAY_AREF(params, i);
kind = RARRAY_AREF(pair, 0);
- name = RARRAY_AREF(pair, 1);
- // FIXME: in tests it turns out that kind, name = [:req] produces name to be false. Why?..
- if (NIL_P(name) || name == Qfalse) {
+ if (RARRAY_LEN(pair) > 1) {
+ name = RARRAY_AREF(pair, 1);
+ }
+ else {
// FIXME: can it be reduced to switch/case?
if (kind == req || kind == opt) {
name = rb_str_new2("_");
@@ -3210,6 +3463,9 @@ method_inspect(VALUE method)
else if (kind == nokey) {
name = rb_str_new2("nil");
}
+ else {
+ name = Qnil;
+ }
}
if (kind == req) {
@@ -3329,7 +3585,7 @@ extern VALUE rb_find_defined_class_by_owner(VALUE current_class, VALUE target_ow
* call-seq:
* meth.super_method -> method
*
- * Returns a Method of superclass which would be called when super is used
+ * Returns a +Method+ of superclass which would be called when super is used
* or nil if there is no method on superclass.
*/
@@ -3780,19 +4036,18 @@ rb_proc_compose_to_right(VALUE self, VALUE g)
/*
* call-seq:
- * meth << g -> a_proc
+ * self << g -> a_proc
*
- * Returns a proc that is the composition of this method and the given <i>g</i>.
- * The returned proc takes a variable number of arguments, calls <i>g</i> with them
- * then calls this method with the result.
+ * Returns a proc that is the composition of the given +g+ and this method.
*
- * def f(x)
- * x * x
- * end
+ * The returned proc takes a variable number of arguments. It first calls +g+
+ * with the arguments, then calls +self+ with the return value of +g+.
+ *
+ * def f(ary) = ary << 'in f'
*
* f = self.method(:f)
- * g = proc {|x| x + x }
- * p (f << g).call(2) #=> 16
+ * g = proc { |ary| ary << 'in proc' }
+ * (f << g).call([]) # => ["in proc", "in f"]
*/
static VALUE
rb_method_compose_to_left(VALUE self, VALUE g)
@@ -3804,19 +4059,18 @@ rb_method_compose_to_left(VALUE self, VALUE g)
/*
* call-seq:
- * meth >> g -> a_proc
+ * self >> g -> a_proc
*
- * Returns a proc that is the composition of this method and the given <i>g</i>.
- * The returned proc takes a variable number of arguments, calls this method
- * with them then calls <i>g</i> with the result.
+ * Returns a proc that is the composition of this method and the given +g+.
*
- * def f(x)
- * x * x
- * end
+ * The returned proc takes a variable number of arguments. It first calls +self+
+ * with the arguments, then calls +g+ with the return value of +self+.
+ *
+ * def f(ary) = ary << 'in f'
*
* f = self.method(:f)
- * g = proc {|x| x + x }
- * p (f >> g).call(2) #=> 8
+ * g = proc { |ary| ary << 'in proc' }
+ * (f >> g).call([]) # => ["in f", "in proc"]
*/
static VALUE
rb_method_compose_to_right(VALUE self, VALUE g)
@@ -3874,12 +4128,13 @@ proc_ruby2_keywords(VALUE procval)
switch (proc->block.type) {
case block_type_iseq:
if (ISEQ_BODY(proc->block.as.captured.code.iseq)->param.flags.has_rest &&
+ !ISEQ_BODY(proc->block.as.captured.code.iseq)->param.flags.has_post &&
!ISEQ_BODY(proc->block.as.captured.code.iseq)->param.flags.has_kw &&
!ISEQ_BODY(proc->block.as.captured.code.iseq)->param.flags.has_kwrest) {
ISEQ_BODY(proc->block.as.captured.code.iseq)->param.flags.ruby2_keywords = 1;
}
else {
- rb_warn("Skipping set of ruby2_keywords flag for proc (proc accepts keywords or proc does not accept argument splat)");
+ rb_warn("Skipping set of ruby2_keywords flag for proc (proc accepts keywords or post arguments or proc does not accept argument splat)");
}
break;
default:
@@ -4123,7 +4378,6 @@ proc_ruby2_keywords(VALUE procval)
* a proc by the <code>&</code> operator, and therefore can be
* consumed by iterators.
*
-
* class Greeter
* def initialize(greeting)
* @greeting = greeting
@@ -4139,8 +4393,8 @@ proc_ruby2_keywords(VALUE procval)
* ["Bob", "Jane"].map(&hi) #=> ["Hi, Bob!", "Hi, Jane!"]
* ["Bob", "Jane"].map(&hey) #=> ["Hey, Bob!", "Hey, Jane!"]
*
- * Of the Ruby core classes, this method is implemented by Symbol,
- * Method, and Hash.
+ * Of the Ruby core classes, this method is implemented by +Symbol+,
+ * +Method+, and +Hash+.
*
* :to_s.to_proc.call(1) #=> "1"
* [1, 2].map(&:to_s) #=> ["1", "2"]
@@ -4174,19 +4428,86 @@ proc_ruby2_keywords(VALUE procval)
* Since +return+ and +break+ exits the block itself in lambdas,
* lambdas cannot be orphaned.
*
- * == Numbered parameters
+ * == Anonymous block parameters
*
- * Numbered parameters are implicitly defined block parameters intended to
- * simplify writing short blocks:
+ * To simplify writing short blocks, Ruby provides two different types of
+ * anonymous parameters: +it+ (single parameter) and numbered ones: <tt>_1</tt>,
+ * <tt>_2</tt> and so on.
*
* # Explicit parameter:
* %w[test me please].each { |str| puts str.upcase } # prints TEST, ME, PLEASE
* (1..5).map { |i| i**2 } # => [1, 4, 9, 16, 25]
*
- * # Implicit parameter:
+ * # it:
+ * %w[test me please].each { puts it.upcase } # prints TEST, ME, PLEASE
+ * (1..5).map { it**2 } # => [1, 4, 9, 16, 25]
+ *
+ * # Numbered parameter:
* %w[test me please].each { puts _1.upcase } # prints TEST, ME, PLEASE
* (1..5).map { _1**2 } # => [1, 4, 9, 16, 25]
*
+ * === +it+
+ *
+ * +it+ is a name that is available inside a block when no explicit parameters
+ * defined, as shown above.
+ *
+ * %w[test me please].each { puts it.upcase } # prints TEST, ME, PLEASE
+ * (1..5).map { it**2 } # => [1, 4, 9, 16, 25]
+ *
+ * +it+ is a "soft keyword": it is not a reserved name, and can be used as
+ * a name for methods and local variables:
+ *
+ * it = 5 # no warnings
+ * def it(&block) # RSpec-like API, no warnings
+ * # ...
+ * end
+ *
+ * +it+ can be used as a local variable even in blocks that use it as an
+ * implicit parameter (though this style is obviously confusing):
+ *
+ * [1, 2, 3].each {
+ * # takes a value of implicit parameter "it" and uses it to
+ * # define a local variable with the same name
+ * it = it**2
+ * p it
+ * }
+ *
+ * In a block with explicit parameters defined +it+ usage raises an exception:
+ *
+ * [1, 2, 3].each { |x| p it }
+ * # syntax error found (SyntaxError)
+ * # [1, 2, 3].each { |x| p it }
+ * # ^~ 'it' is not allowed when an ordinary parameter is defined
+ *
+ * But if a local name (variable or method) is available, it would be used:
+ *
+ * it = 5
+ * [1, 2, 3].each { |x| p it }
+ * # Prints 5, 5, 5
+ *
+ * Blocks using +it+ can be nested:
+ *
+ * %w[test me].each { it.each_char { p it } }
+ * # Prints "t", "e", "s", "t", "m", "e"
+ *
+ * Blocks using +it+ are considered to have one parameter:
+ *
+ * p = proc { it**2 }
+ * l = lambda { it**2 }
+ * p.parameters # => [[:opt]]
+ * p.arity # => 1
+ * l.parameters # => [[:req]]
+ * l.arity # => 1
+ *
+ * === Numbered parameters
+ *
+ * Numbered parameters are another way to name block parameters implicitly.
+ * Unlike +it+, numbered parameters allow to refer to several parameters
+ * in one block.
+ *
+ * %w[test me please].each { puts _1.upcase } # prints TEST, ME, PLEASE
+ * {a: 100, b: 200}.map { "#{_1} = #{_2}" } # => "a = 100", "b = 200"
+ *
* Parameter names from +_1+ to +_9+ are supported:
*
* [10, 20, 30].zip([40, 50, 60], [70, 80, 90]).map { _1 + _2 + _3 }
@@ -4201,11 +4522,16 @@ proc_ruby2_keywords(VALUE procval)
* [10, 20, 30].map { |x| _1**2 }
* # SyntaxError (ordinary parameter is defined)
*
+ * Numbered parameters can't be mixed with +it+ either:
+ *
+ * [10, 20, 30].map { _1 + it }
+ * # SyntaxError: 'it' is not allowed when a numbered parameter is already used
+ *
* To avoid conflicts, naming local variables or method
- * arguments +_1+, +_2+ and so on, causes a warning.
+ * arguments +_1+, +_2+ and so on, causes an error.
*
- * _1 = 'test'
- * # warning: `_1' is reserved as numbered parameter
+ * _1 = 'test'
+ * # ^~ _1 is reserved for numbered parameters (SyntaxError)
*
* Using implicit numbered parameters affects block's arity:
*
@@ -4219,14 +4545,12 @@ proc_ruby2_keywords(VALUE procval)
* Blocks with numbered parameters can't be nested:
*
* %w[test me].each { _1.each_char { p _1 } }
- * # SyntaxError (numbered parameter is already used in outer block here)
+ * # numbered parameter is already used in outer block (SyntaxError)
* # %w[test me].each { _1.each_char { p _1 } }
* # ^~
*
- * Numbered parameters were introduced in Ruby 2.7.
*/
-
void
Init_Proc(void)
{
@@ -4310,6 +4634,8 @@ Init_Proc(void)
rb_define_method(rb_mKernel, "public_method", rb_obj_public_method, 1);
rb_define_method(rb_mKernel, "singleton_method", rb_obj_singleton_method, 1);
+ rb_define_method(rb_cMethod, "box", method_box, 0);
+
/* UnboundMethod */
rb_cUnboundMethod = rb_define_class("UnboundMethod", rb_cObject);
rb_undef_alloc_func(rb_cUnboundMethod);
@@ -4381,6 +4707,8 @@ Init_Proc(void)
void
Init_Binding(void)
{
+ rb_gc_register_address(&sym_proc_cache);
+
rb_cBinding = rb_define_class("Binding", rb_cObject);
rb_undef_alloc_func(rb_cBinding);
rb_undef_method(CLASS_OF(rb_cBinding), "new");
@@ -4391,6 +4719,9 @@ Init_Binding(void)
rb_define_method(rb_cBinding, "local_variable_get", bind_local_variable_get, 1);
rb_define_method(rb_cBinding, "local_variable_set", bind_local_variable_set, 2);
rb_define_method(rb_cBinding, "local_variable_defined?", bind_local_variable_defined_p, 1);
+ rb_define_method(rb_cBinding, "implicit_parameters", bind_implicit_parameters, 0);
+ rb_define_method(rb_cBinding, "implicit_parameter_get", bind_implicit_parameter_get, 1);
+ rb_define_method(rb_cBinding, "implicit_parameter_defined?", bind_implicit_parameter_defined_p, 1);
rb_define_method(rb_cBinding, "receiver", bind_receiver, 0);
rb_define_method(rb_cBinding, "source_location", bind_location, 0);
rb_define_global_function("binding", rb_f_binding, 0);
diff --git a/process.c b/process.c
index b1f9931f06..19f3172cb8 100644
--- a/process.c
+++ b/process.c
@@ -110,11 +110,11 @@ int initgroups(const char *, rb_gid_t);
#include "internal/thread.h"
#include "internal/variable.h"
#include "internal/warnings.h"
-#include "rjit.h"
#include "ruby/io.h"
#include "ruby/st.h"
#include "ruby/thread.h"
#include "ruby/util.h"
+#include "ractor_core.h"
#include "vm_core.h"
#include "vm_sync.h"
#include "ruby/ractor.h"
@@ -875,109 +875,6 @@ pst_equal(VALUE st1, VALUE st2)
/*
* call-seq:
- * stat & mask -> integer
- *
- * This method is deprecated as #to_i value is system-specific; use
- * predicate methods like #exited? or #stopped?, or getters like #exitstatus
- * or #stopsig.
- *
- * Returns the logical AND of the value of #to_i with +mask+:
- *
- * `cat /nop`
- * stat = $? # => #<Process::Status: pid 1155508 exit 1>
- * sprintf('%x', stat.to_i) # => "100"
- * stat & 0x00 # => 0
- *
- * ArgumentError is raised if +mask+ is negative.
- */
-
-static VALUE
-pst_bitand(VALUE st1, VALUE st2)
-{
- int status = PST2INT(st1);
- int mask = NUM2INT(st2);
-
- if (mask < 0) {
- rb_raise(rb_eArgError, "negative mask value: %d", mask);
- }
-#define WARN_SUGGEST(suggest) \
- rb_warn_deprecated_to_remove_at(3.5, "Process::Status#&", suggest)
-
- switch (mask) {
- case 0x80:
- WARN_SUGGEST("Process::Status#coredump?");
- break;
- case 0x7f:
- WARN_SUGGEST("Process::Status#signaled? or Process::Status#termsig");
- break;
- case 0xff:
- WARN_SUGGEST("Process::Status#exited?, Process::Status#stopped? or Process::Status#coredump?");
- break;
- case 0xff00:
- WARN_SUGGEST("Process::Status#exitstatus or Process::Status#stopsig");
- break;
- default:
- WARN_SUGGEST("other Process::Status predicates");
- break;
- }
-#undef WARN_SUGGEST
- status &= mask;
-
- return INT2NUM(status);
-}
-
-
-/*
- * call-seq:
- * stat >> places -> integer
- *
- * This method is deprecated as #to_i value is system-specific; use
- * predicate methods like #exited? or #stopped?, or getters like #exitstatus
- * or #stopsig.
- *
- * Returns the value of #to_i, shifted +places+ to the right:
- *
- * `cat /nop`
- * stat = $? # => #<Process::Status: pid 1155508 exit 1>
- * stat.to_i # => 256
- * stat >> 1 # => 128
- * stat >> 2 # => 64
- *
- * ArgumentError is raised if +places+ is negative.
- */
-
-static VALUE
-pst_rshift(VALUE st1, VALUE st2)
-{
- int status = PST2INT(st1);
- int places = NUM2INT(st2);
-
- if (places < 0) {
- rb_raise(rb_eArgError, "negative shift value: %d", places);
- }
-#define WARN_SUGGEST(suggest) \
- rb_warn_deprecated_to_remove_at(3.5, "Process::Status#>>", suggest)
-
- switch (places) {
- case 7:
- WARN_SUGGEST("Process::Status#coredump?");
- break;
- case 8:
- WARN_SUGGEST("Process::Status#exitstatus or Process::Status#stopsig");
- break;
- default:
- WARN_SUGGEST("other Process::Status attributes");
- break;
- }
-#undef WARN_SUGGEST
- status >>= places;
-
- return INT2NUM(status);
-}
-
-
-/*
- * call-seq:
* stopped? -> true or false
*
* Returns +true+ if this process is stopped,
@@ -1200,8 +1097,10 @@ rb_process_status_wait(rb_pid_t pid, int flags)
// 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 (!UNDEF_P(result)) return result;
+ if (scheduler != Qnil) {
+ VALUE result = rb_fiber_scheduler_process_wait(scheduler, pid, flags);
+ if (!UNDEF_P(result)) return result;
+ }
}
struct waitpid_state waitpid_state;
@@ -1677,11 +1576,14 @@ static void
before_fork_ruby(void)
{
before_exec();
+ rb_gc_before_fork();
}
static void
after_fork_ruby(rb_pid_t pid)
{
+ rb_gc_after_fork(pid);
+
if (pid == 0) {
// child
clear_pid_cache();
@@ -2733,7 +2635,7 @@ rb_exec_fillarg(VALUE prog, int argc, VALUE *argv, VALUE env, VALUE opthash, VAL
}
rb_str_buf_cat(argv_str, (char *)&null, sizeof(null)); /* terminator for execve. */
eargp->invoke.cmd.argv_str =
- rb_imemo_tmpbuf_auto_free_pointer_new_from_an_RString(argv_str);
+ rb_imemo_tmpbuf_new_from_an_RString(argv_str);
}
RB_GC_GUARD(execarg_obj);
}
@@ -2824,7 +2726,7 @@ open_func(void *ptr)
static void
rb_execarg_allocate_dup2_tmpbuf(struct rb_execarg *eargp, long len)
{
- VALUE tmpbuf = rb_imemo_tmpbuf_auto_free_pointer();
+ VALUE tmpbuf = rb_imemo_tmpbuf_new();
rb_imemo_tmpbuf_set_ptr(tmpbuf, ruby_xmalloc(run_exec_dup2_tmpbuf_size(len)));
eargp->dup2_tmpbuf = tmpbuf;
}
@@ -2928,7 +2830,7 @@ rb_execarg_parent_start1(VALUE execarg_obj)
p = NULL;
rb_str_buf_cat(envp_str, (char *)&p, sizeof(p));
eargp->envp_str =
- rb_imemo_tmpbuf_auto_free_pointer_new_from_an_RString(envp_str);
+ rb_imemo_tmpbuf_new_from_an_RString(envp_str);
eargp->envp_buf = envp_buf;
/*
@@ -3055,7 +2957,7 @@ NORETURN(static VALUE f_exec(int c, const VALUE *a, VALUE _));
* - Invoking the executable at +exe_path+.
*
* This method has potential security vulnerabilities if called with untrusted input;
- * see {Command Injection}[rdoc-ref:command_injection.rdoc].
+ * see {Command Injection}[rdoc-ref:security/command_injection.rdoc].
*
* The new process is created using the
* {exec system call}[https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/functions/execve.html];
@@ -3363,6 +3265,7 @@ run_exec_dup2(VALUE ary, VALUE tmpbuf, struct rb_execarg *sargp, char *errmsg, s
// in #assert_close_on_exec because the FD_CLOEXEC is not dup'd by default
if (fd_get_cloexec(pairs[i].oldfd, errmsg, errmsg_buflen)) {
if (fd_set_cloexec(extra_fd, errmsg, errmsg_buflen)) {
+ close(extra_fd);
goto fail;
}
}
@@ -4108,7 +4011,10 @@ retry_fork_async_signal_safe(struct rb_process_status *status, int *ep,
while (1) {
prefork();
disable_child_handler_before_fork(&old);
-#ifdef HAVE_WORKING_VFORK
+
+ // Older versions of ASAN does not work with vfork
+ // See https://github.com/google/sanitizers/issues/925
+#if defined(HAVE_WORKING_VFORK) && !defined(RUBY_ASAN_ENABLED)
if (!has_privilege())
pid = vfork();
else
@@ -4196,7 +4102,7 @@ fork_check_err(struct rb_process_status *status, int (*chfunc)(void*, char *, si
* The "async_signal_safe" name is a lie, but it is used by pty.c and
* maybe other exts. fork() is not async-signal-safe due to pthread_atfork
* and future POSIX revisions will remove it from a list of signal-safe
- * functions. rb_waitpid is not async-signal-safe since RJIT, either.
+ * functions. rb_waitpid is not async-signal-safe.
* For our purposes, we do not need async-signal-safety, here
*/
rb_pid_t
@@ -4215,50 +4121,47 @@ rb_fork_async_signal_safe(int *status,
return result;
}
-static rb_pid_t
-rb_fork_ruby2(struct rb_process_status *status)
+rb_pid_t
+rb_fork_ruby(int *status)
{
+ if (UNLIKELY(!rb_ractor_main_p())) {
+ rb_raise(rb_eRactorIsolationError, "can not fork from non-main Ractors");
+ }
+
+ struct rb_process_status child = {.status = 0};
rb_pid_t pid;
- int try_gc = 1, err;
+ int try_gc = 1, err = 0;
struct child_handler_disabler_state old;
- if (status) status->status = 0;
-
- while (1) {
+ do {
prefork();
before_fork_ruby();
+ rb_thread_acquire_fork_lock();
disable_child_handler_before_fork(&old);
- {
- pid = rb_fork();
- err = errno;
- if (status) {
- status->pid = pid;
- status->error = err;
- }
- }
- disable_child_handler_fork_parent(&old); /* yes, bad name */
- after_fork_ruby(pid);
- if (pid >= 0) { /* fork succeed */
- return pid;
+ RB_VM_LOCKING() {
+ child.pid = pid = rb_fork();
+ child.error = err = errno;
}
- /* fork failed */
- if (handle_fork_error(err, status, NULL, &try_gc)) {
- return -1;
+ disable_child_handler_fork_parent(&old); /* yes, bad name */
+ if (
+#if defined(__FreeBSD__)
+ pid != 0 &&
+#endif
+ true) {
+ rb_thread_release_fork_lock();
}
- }
-}
-
-rb_pid_t
-rb_fork_ruby(int *status)
-{
- struct rb_process_status process_status = {0};
+ if (pid == 0) {
+ rb_thread_reset_fork_lock();
+ }
+ after_fork_ruby(pid);
- rb_pid_t pid = rb_fork_ruby2(&process_status);
+ /* repeat while fork failed but retryable */
+ } while (pid < 0 && handle_fork_error(err, &child, NULL, &try_gc) == 0);
- if (status) *status = process_status.status;
+ if (status) *status = child.status;
return pid;
}
@@ -4739,7 +4642,7 @@ rb_spawn(int argc, const VALUE *argv)
* - Invoking the executable at +exe_path+.
*
* This method has potential security vulnerabilities if called with untrusted input;
- * see {Command Injection}[rdoc-ref:command_injection.rdoc].
+ * see {Command Injection}[rdoc-ref:security/command_injection.rdoc].
*
* Returns:
*
@@ -4919,7 +4822,7 @@ rb_f_system(int argc, VALUE *argv, VALUE _)
* - Invoking the executable at +exe_path+.
*
* This method has potential security vulnerabilities if called with untrusted input;
- * see {Command Injection}[rdoc-ref:command_injection.rdoc].
+ * see {Command Injection}[rdoc-ref:security/command_injection.rdoc].
*
* Returns the process ID (pid) of the new process,
* without waiting for it to complete.
@@ -5720,6 +5623,12 @@ check_gid_switch(void)
#if defined(HAVE_PWD_H)
+static inline bool
+login_not_found(int err)
+{
+ return (err == ENOTTY || err == ENXIO || err == ENOENT);
+}
+
/**
* Best-effort attempt to obtain the name of the login user, if any,
* associated with the process. Processes not descended from login(1) (or
@@ -5728,18 +5637,18 @@ check_gid_switch(void)
VALUE
rb_getlogin(void)
{
-#if ( !defined(USE_GETLOGIN_R) && !defined(USE_GETLOGIN) )
+# if !defined(USE_GETLOGIN_R) && !defined(USE_GETLOGIN)
return Qnil;
-#else
+# else
char MAYBE_UNUSED(*login) = NULL;
# ifdef USE_GETLOGIN_R
-#if defined(__FreeBSD__)
+# if defined(__FreeBSD__)
typedef int getlogin_r_size_t;
-#else
+# else
typedef size_t getlogin_r_size_t;
-#endif
+# endif
long loginsize = GETLOGIN_R_SIZE_INIT; /* maybe -1 */
@@ -5753,10 +5662,8 @@ rb_getlogin(void)
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) {
+ if (login_not_found(gle)) {
rb_str_resize(maybe_result, 0);
return Qnil;
}
@@ -5776,17 +5683,19 @@ rb_getlogin(void)
return Qnil;
}
+ rb_str_set_len(maybe_result, strlen(login));
return maybe_result;
-# elif USE_GETLOGIN
+# elif defined(USE_GETLOGIN)
errno = 0;
login = getlogin();
- if (errno) {
- if (errno == ENOTTY || errno == ENXIO || errno == ENOENT) {
+ int err = errno;
+ if (err) {
+ if (login_not_found(err)) {
return Qnil;
}
- rb_syserr_fail(errno, "getlogin");
+ rb_syserr_fail(err, "getlogin");
}
return login ? rb_str_new_cstr(login) : Qnil;
@@ -5795,10 +5704,46 @@ rb_getlogin(void)
#endif
}
+/* avoid treating as errors errno values that indicate "not found" */
+static inline bool
+pwd_not_found(int err)
+{
+ switch (err) {
+ case 0:
+ case ENOENT:
+ case ESRCH:
+ case EBADF:
+ case EPERM:
+ return true;
+ default:
+ return false;
+ }
+}
+
+# if defined(USE_GETPWNAM_R)
+struct getpwnam_r_args {
+ const char *login;
+ char *buf;
+ size_t bufsize;
+ struct passwd *result;
+ struct passwd pwstore;
+};
+
+# define GETPWNAM_R_ARGS(login_, buf_, bufsize_) (struct getpwnam_r_args) \
+ {.login = login_, .buf = buf_, .bufsize = bufsize_, .result = NULL}
+
+static void *
+nogvl_getpwnam_r(void *args)
+{
+ struct getpwnam_r_args *arg = args;
+ return (void *)(VALUE)getpwnam_r(arg->login, &arg->pwstore, arg->buf, arg->bufsize, &arg->result);
+}
+# endif
+
VALUE
rb_getpwdirnam_for_login(VALUE login_name)
{
-#if ( !defined(USE_GETPWNAM_R) && !defined(USE_GETPWNAM) )
+#if !defined(USE_GETPWNAM_R) && !defined(USE_GETPWNAM)
return Qnil;
#else
@@ -5807,13 +5752,11 @@ rb_getpwdirnam_for_login(VALUE login_name)
return Qnil;
}
- char *login = RSTRING_PTR(login_name);
+ const 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 */
@@ -5825,58 +5768,77 @@ rb_getpwdirnam_for_login(VALUE login_name)
bufnm = RSTRING_PTR(getpwnm_tmp);
bufsizenm = rb_str_capacity(getpwnm_tmp);
rb_str_set_len(getpwnm_tmp, bufsizenm);
+ struct getpwnam_r_args args = GETPWNAM_R_ARGS(login, bufnm, (size_t)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 */
+ while ((enm = IO_WITHOUT_GVL_INT(nogvl_getpwnam_r, &args)) != 0) {
+ if (pwd_not_found(enm)) {
rb_str_resize(getpwnm_tmp, 0);
return Qnil;
}
- if (enm != ERANGE || bufsizenm >= GETPW_R_SIZE_LIMIT) {
+ if (enm != ERANGE || args.bufsize >= 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);
+ rb_str_modify_expand(getpwnm_tmp, (long)args.bufsize);
+ args.buf = RSTRING_PTR(getpwnm_tmp);
+ args.bufsize = (size_t)rb_str_capacity(getpwnm_tmp);
}
- if (pwptr == NULL) {
+ if (args.result == 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);
+ VALUE result = rb_str_new_cstr(args.result->pw_dir);
rb_str_resize(getpwnm_tmp, 0);
return result;
-# elif USE_GETPWNAM
+# elif defined(USE_GETPWNAM)
+ struct passwd *pwptr;
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");
+ if (!(pwptr = getpwnam(login))) {
+ int err = errno;
+
+ if (pwd_not_found(err)) {
+ return Qnil;
+ }
+
+ rb_syserr_fail(err, "getpwnam");
}
- return Qnil; /* not found */
+ /* found it */
+ return rb_str_new_cstr(pwptr->pw_dir);
# endif
#endif
}
+# if defined(USE_GETPWUID_R)
+struct getpwuid_r_args {
+ uid_t uid;
+ char *buf;
+ size_t bufsize;
+ struct passwd *result;
+ struct passwd pwstore;
+};
+
+# define GETPWUID_R_ARGS(uid_, buf_, bufsize_) (struct getpwuid_r_args) \
+ {.uid = uid_, .buf = buf_, .bufsize = bufsize_, .result = NULL}
+
+static void *
+nogvl_getpwuid_r(void *args)
+{
+ struct getpwuid_r_args *arg = args;
+ return (void *)(VALUE)getpwuid_r(arg->uid, &arg->pwstore, arg->buf, arg->bufsize, &arg->result);
+}
+# endif
+
/**
* Look up the user's dflt home dir in the password db, by uid.
*/
@@ -5889,11 +5851,8 @@ rb_getpwdiruid(void)
# 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 */
@@ -5905,53 +5864,52 @@ rb_getpwdiruid(void)
bufid = RSTRING_PTR(getpwid_tmp);
bufsizeid = rb_str_capacity(getpwid_tmp);
rb_str_set_len(getpwid_tmp, bufsizeid);
+ struct getpwuid_r_args args = GETPWUID_R_ARGS(ruid, bufid, (size_t)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 */
+ while ((eid = IO_WITHOUT_GVL_INT(nogvl_getpwuid_r, &args)) != 0) {
+ if (pwd_not_found(eid)) {
rb_str_resize(getpwid_tmp, 0);
return Qnil;
}
- if (eid != ERANGE || bufsizeid >= GETPW_R_SIZE_LIMIT) {
+ if (eid != ERANGE || args.bufsize >= 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);
+ rb_str_modify_expand(getpwid_tmp, (long)args.bufsize);
+ args.buf = RSTRING_PTR(getpwid_tmp);
+ args.bufsize = (size_t)rb_str_capacity(getpwid_tmp);
}
- if (pwptr == NULL) {
+ if (args.result == 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);
+ VALUE result = rb_str_new_cstr(args.result->pw_dir);
rb_str_resize(getpwid_tmp, 0);
return result;
# elif defined(USE_GETPWUID)
+ struct passwd *pwptr;
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");
+ if (!(pwptr = getpwuid(ruid))) {
+ int err = errno;
+
+ if (pwd_not_found(err)) {
+ return Qnil;
+ }
+
+ rb_syserr_fail(err, "getpwuid");
}
- return Qnil; /* not found */
+ /* found it */
+ return rb_str_new_cstr(pwptr->pw_dir);
# endif
#endif /* !defined(USE_GETPWUID_R) && !defined(USE_GETPWUID) */
@@ -5965,7 +5923,7 @@ rb_getpwdiruid(void)
* The Process::Sys module contains UID and GID
* functions which provide direct bindings to the system calls of the
* same names instead of the more-portable versions of the same
- * functionality found in the Process,
+ * functionality found in the +Process+,
* Process::UID, and Process::GID modules.
*/
@@ -5987,7 +5945,6 @@ obj2uid(VALUE id
const char *usrname = StringValueCStr(id);
struct passwd *pwptr;
#ifdef USE_GETPWNAM_R
- struct passwd pwbuf;
char *getpw_buf;
long getpw_buf_len;
int e;
@@ -6000,15 +5957,18 @@ obj2uid(VALUE id
getpw_buf_len = rb_str_capacity(*getpw_tmp);
rb_str_set_len(*getpw_tmp, getpw_buf_len);
errno = 0;
- while ((e = getpwnam_r(usrname, &pwbuf, getpw_buf, getpw_buf_len, &pwptr)) != 0) {
- if (e != ERANGE || getpw_buf_len >= GETPW_R_SIZE_LIMIT) {
+ struct getpwnam_r_args args = GETPWNAM_R_ARGS((char *)usrname, getpw_buf, (size_t)getpw_buf_len);
+
+ while ((e = IO_WITHOUT_GVL_INT(nogvl_getpwnam_r, &args)) != 0) {
+ if (e != ERANGE || args.bufsize >= GETPW_R_SIZE_LIMIT) {
rb_str_resize(*getpw_tmp, 0);
rb_syserr_fail(e, "getpwnam_r");
}
- rb_str_modify_expand(*getpw_tmp, getpw_buf_len);
- getpw_buf = RSTRING_PTR(*getpw_tmp);
- getpw_buf_len = rb_str_capacity(*getpw_tmp);
+ rb_str_modify_expand(*getpw_tmp, (long)args.bufsize);
+ args.buf = RSTRING_PTR(*getpw_tmp);
+ args.bufsize = (size_t)rb_str_capacity(*getpw_tmp);
}
+ pwptr = args.result;
#else
pwptr = getpwnam(usrname);
#endif
@@ -6047,6 +6007,26 @@ p_uid_from_name(VALUE self, VALUE id)
#endif
#if defined(HAVE_GRP_H)
+# if defined(USE_GETGRNAM_R)
+struct getgrnam_r_args {
+ const char *name;
+ char *buf;
+ size_t bufsize;
+ struct group *result;
+ struct group grp;
+};
+
+# define GETGRNAM_R_ARGS(name_, buf_, bufsize_) (struct getgrnam_r_args) \
+ {.name = name_, .buf = buf_, .bufsize = bufsize_, .result = NULL}
+
+static void *
+nogvl_getgrnam_r(void *args)
+{
+ struct getgrnam_r_args *arg = args;
+ return (void *)(VALUE)getgrnam_r(arg->name, &arg->grp, arg->buf, arg->bufsize, &arg->result);
+}
+# endif
+
static rb_gid_t
obj2gid(VALUE id
# ifdef USE_GETGRNAM_R
@@ -6064,7 +6044,6 @@ obj2gid(VALUE id
const char *grpname = StringValueCStr(id);
struct group *grptr;
#ifdef USE_GETGRNAM_R
- struct group grbuf;
char *getgr_buf;
long getgr_buf_len;
int e;
@@ -6077,15 +6056,18 @@ obj2gid(VALUE id
getgr_buf_len = rb_str_capacity(*getgr_tmp);
rb_str_set_len(*getgr_tmp, getgr_buf_len);
errno = 0;
- while ((e = getgrnam_r(grpname, &grbuf, getgr_buf, getgr_buf_len, &grptr)) != 0) {
- if (e != ERANGE || getgr_buf_len >= GETGR_R_SIZE_LIMIT) {
+ struct getgrnam_r_args args = GETGRNAM_R_ARGS(grpname, getgr_buf, (size_t)getgr_buf_len);
+
+ while ((e = IO_WITHOUT_GVL_INT(nogvl_getgrnam_r, &args)) != 0) {
+ if (e != ERANGE || args.bufsize >= GETGR_R_SIZE_LIMIT) {
rb_str_resize(*getgr_tmp, 0);
rb_syserr_fail(e, "getgrnam_r");
}
- rb_str_modify_expand(*getgr_tmp, getgr_buf_len);
- getgr_buf = RSTRING_PTR(*getgr_tmp);
- getgr_buf_len = rb_str_capacity(*getgr_tmp);
+ rb_str_modify_expand(*getgr_tmp, (long)args.bufsize);
+ args.buf = RSTRING_PTR(*getgr_tmp);
+ args.bufsize = (size_t)rb_str_capacity(*getgr_tmp);
}
+ grptr = args.result;
#elif defined(HAVE_GETGRNAM)
grptr = getgrnam(grpname);
#else
@@ -8248,7 +8230,7 @@ ruby_real_ms_time(void)
* - +:microsecond+: Number of microseconds as an integer.
* - +:millisecond+: Number of milliseconds as an integer.
* - +:nanosecond+: Number of nanoseconds as an integer.
- * - +::second+: Number of seconds as an integer.
+ * - +:second+: Number of seconds as an integer.
*
* Examples:
*
@@ -8780,19 +8762,19 @@ static VALUE rb_mProcID_Syscall;
static VALUE
proc_warmup(VALUE _)
{
- RB_VM_LOCK_ENTER();
- rb_gc_prepare_heap();
- RB_VM_LOCK_LEAVE();
+ RB_VM_LOCKING() {
+ rb_gc_prepare_heap();
+ }
return Qtrue;
}
/*
* Document-module: Process
*
- * \Module +Process+ represents a process in the underlying operating system.
+ * Module +Process+ represents a process in the underlying operating system.
* Its methods support management of the current process and its child processes.
*
- * == \Process Creation
+ * == Process Creation
*
* Each of the following methods executes a given command in a new process or subshell,
* or multiple commands in new processes and/or subshells.
@@ -8805,11 +8787,11 @@ proc_warmup(VALUE _)
*
* In addition:
*
- * - \Method Kernel#system executes a given command-line (string) in a subshell;
+ * - Method Kernel#system executes a given command-line (string) in a subshell;
* returns +true+, +false+, or +nil+.
- * - \Method Kernel#` executes a given command-line (string) in a subshell;
+ * - Method Kernel#` executes a given command-line (string) in a subshell;
* returns its $stdout string.
- * - \Module Open3 supports creating child processes
+ * - Module Open3 supports creating child processes
* with access to their $stdin, $stdout, and $stderr streams.
*
* === Execution Environment
@@ -9039,7 +9021,7 @@ proc_warmup(VALUE _)
*
* 0644
*
- * ==== \Process Groups (+:pgroup+ and +:new_pgroup+)
+ * ==== Process Groups (+:pgroup+ and +:new_pgroup+)
*
* By default, the new process belongs to the same
* {process group}[https://en.wikipedia.org/wiki/Process_group]
@@ -9173,7 +9155,7 @@ proc_warmup(VALUE _)
* - ::waitall: Waits for all child processes to exit;
* returns their process IDs and statuses.
*
- * === \Process Groups
+ * === Process Groups
*
* - ::getpgid: Returns the process group ID for a process.
* - ::getpriority: Returns the scheduling priority
@@ -9270,8 +9252,6 @@ InitVM_process(void)
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);
- rb_define_method(rb_cProcessStatus, ">>", pst_rshift, 1);
rb_define_method(rb_cProcessStatus, "to_i", pst_to_i, 0);
rb_define_method(rb_cProcessStatus, "to_s", pst_to_s, 0);
rb_define_method(rb_cProcessStatus, "inspect", pst_inspect, 0);
diff --git a/ractor.c b/ractor.c
index d08a009d64..2dcbbd10a0 100644
--- a/ractor.c
+++ b/ractor.c
@@ -3,21 +3,23 @@
#include "ruby/ruby.h"
#include "ruby/thread.h"
#include "ruby/ractor.h"
+#include "ruby/re.h"
#include "ruby/thread_native.h"
#include "vm_core.h"
-#include "eval_intern.h"
#include "vm_sync.h"
#include "ractor_core.h"
#include "internal/complex.h"
#include "internal/error.h"
#include "internal/gc.h"
#include "internal/hash.h"
+#include "internal/object.h"
+#include "internal/ractor.h"
#include "internal/rational.h"
#include "internal/struct.h"
#include "internal/thread.h"
#include "variable.h"
#include "yjit.h"
-#include "rjit.h"
+#include "zjit.h"
VALUE rb_cRactor;
static VALUE rb_cRactorSelector;
@@ -32,14 +34,19 @@ static VALUE rb_cRactorMovedObject;
static void vm_ractor_blocking_cnt_inc(rb_vm_t *vm, rb_ractor_t *r, const char *file, int line);
+
+#if RACTOR_CHECK_MODE > 0
+bool rb_ractor_ignore_belonging_flag = false;
+#endif
+
// Ractor locking
static void
ASSERT_ractor_unlocking(rb_ractor_t *r)
{
#if RACTOR_CHECK_MODE > 0
- // GET_EC is NULL in an RJIT worker
- if (rb_current_execution_context(false) != NULL && r->sync.locked_by == rb_ractor_self(GET_RACTOR())) {
+ const rb_execution_context_t *ec = rb_current_ec_noinline();
+ if (ec != NULL && r->sync.locked_by == rb_ractor_self(rb_ec_ractor_ptr(ec))) {
rb_bug("recursive ractor locking");
}
#endif
@@ -49,8 +56,8 @@ static void
ASSERT_ractor_locking(rb_ractor_t *r)
{
#if RACTOR_CHECK_MODE > 0
- // GET_EC is NULL in an RJIT worker
- if (rb_current_execution_context(false) != NULL && r->sync.locked_by != rb_ractor_self(GET_RACTOR())) {
+ const rb_execution_context_t *ec = rb_current_ec_noinline();
+ if (ec != NULL && r->sync.locked_by != rb_ractor_self(rb_ec_ractor_ptr(ec))) {
rp(r->sync.locked_by);
rb_bug("ractor lock is not acquired.");
}
@@ -65,10 +72,17 @@ ractor_lock(rb_ractor_t *r, const char *file, int line)
ASSERT_ractor_unlocking(r);
rb_native_mutex_lock(&r->sync.lock);
+ const rb_execution_context_t *ec = rb_current_ec_noinline();
+ if (ec) {
+ rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
+ VM_ASSERT(!cr->malloc_gc_disabled);
+ cr->malloc_gc_disabled = true;
+ }
+
#if RACTOR_CHECK_MODE > 0
- if (rb_current_execution_context(false) != NULL) { // GET_EC is NULL in an RJIT worker
- rb_ractor_t *cr = rb_current_ractor_raw(false);
- r->sync.locked_by = cr ? rb_ractor_self(cr) : Qundef;
+ if (ec != NULL) {
+ rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
+ r->sync.locked_by = rb_ractor_self(cr);
}
#endif
@@ -78,7 +92,7 @@ ractor_lock(rb_ractor_t *r, const char *file, int line)
static void
ractor_lock_self(rb_ractor_t *cr, const char *file, int line)
{
- VM_ASSERT(cr == GET_RACTOR());
+ VM_ASSERT(cr == rb_ec_ractor_ptr(rb_current_ec_noinline()));
#if RACTOR_CHECK_MODE > 0
VM_ASSERT(cr->sync.locked_by != cr->pub.self);
#endif
@@ -92,6 +106,14 @@ ractor_unlock(rb_ractor_t *r, const char *file, int line)
#if RACTOR_CHECK_MODE > 0
r->sync.locked_by = Qnil;
#endif
+
+ const rb_execution_context_t *ec = rb_current_ec_noinline();
+ if (ec) {
+ rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
+ VM_ASSERT(cr->malloc_gc_disabled);
+ cr->malloc_gc_disabled = false;
+ }
+
rb_native_mutex_unlock(&r->sync.lock);
RUBY_DEBUG_LOG2(file, line, "r:%u%s", r->pub.id, rb_current_ractor_raw(false) == r ? " (self)" : "");
@@ -100,7 +122,7 @@ ractor_unlock(rb_ractor_t *r, const char *file, int line)
static void
ractor_unlock_self(rb_ractor_t *cr, const char *file, int line)
{
- VM_ASSERT(cr == GET_RACTOR());
+ VM_ASSERT(cr == rb_ec_ractor_ptr(rb_current_ec_noinline()));
#if RACTOR_CHECK_MODE > 0
VM_ASSERT(cr->sync.locked_by == cr->pub.self);
#endif
@@ -177,62 +199,81 @@ ractor_status_p(rb_ractor_t *r, enum ractor_status status)
// Ractor data/mark/free
-static struct rb_ractor_basket *ractor_queue_at(rb_ractor_t *r, struct rb_ractor_queue *rq, int i);
static void ractor_local_storage_mark(rb_ractor_t *r);
static void ractor_local_storage_free(rb_ractor_t *r);
-static void
-ractor_queue_mark(struct rb_ractor_queue *rq)
-{
- for (int i=0; i<rq->cnt; i++) {
- struct rb_ractor_basket *b = ractor_queue_at(NULL, rq, i);
- rb_gc_mark(b->sender);
-
- switch (b->type.e) {
- case basket_type_yielding:
- case basket_type_take_basket:
- case basket_type_deleted:
- case basket_type_reserved:
- // ignore
- break;
- default:
- rb_gc_mark(b->p.send.v);
- }
+static void ractor_sync_mark(rb_ractor_t *r);
+static void ractor_sync_free(rb_ractor_t *r);
+static size_t ractor_sync_memsize(const rb_ractor_t *r);
+static void ractor_sync_init(rb_ractor_t *r);
+
+static int
+mark_targeted_hook_list(st_data_t key, st_data_t value, st_data_t _arg)
+{
+ rb_hook_list_t *hook_list = (rb_hook_list_t*)value;
+
+ if (hook_list->type == hook_list_type_targeted_iseq) {
+ rb_gc_mark((VALUE)key);
+ }
+ else {
+ rb_method_definition_t *def = (rb_method_definition_t*)key;
+ RUBY_ASSERT(hook_list->type == hook_list_type_targeted_def);
+ rb_gc_mark(def->body.bmethod.proc);
}
+ rb_hook_list_mark(hook_list);
+
+ return ST_CONTINUE;
}
static void
ractor_mark(void *ptr)
{
rb_ractor_t *r = (rb_ractor_t *)ptr;
-
- ractor_queue_mark(&r->sync.recv_queue);
- ractor_queue_mark(&r->sync.takers_queue);
-
- rb_gc_mark(r->receiving_mutex);
+ bool checking_shareable = rb_gc_checking_shareable();
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;
- ccan_list_for_each(&r->threads.set, th, lt_node) {
- VM_ASSERT(th != NULL);
- rb_gc_mark(th->self);
+
+ if (!checking_shareable) {
+ // may unshareable objects
+ rb_gc_mark(r->r_stdin);
+ rb_gc_mark(r->r_stdout);
+ rb_gc_mark(r->r_stderr);
+ rb_gc_mark(r->verbose);
+ rb_gc_mark(r->debug);
+
+ // mark received messages
+ ractor_sync_mark(r);
+
+ rb_hook_list_mark(&r->pub.hooks);
+ if (r->pub.targeted_hooks) {
+ st_foreach(r->pub.targeted_hooks, mark_targeted_hook_list, 0);
}
+
+ if (r->threads.cnt > 0) {
+ rb_thread_t *th = 0;
+ ccan_list_for_each(&r->threads.set, th, lt_node) {
+ VM_ASSERT(th != NULL);
+ rb_gc_mark(th->self);
+ }
+ }
+
+ ractor_local_storage_mark(r);
}
+}
- ractor_local_storage_mark(r);
+static int
+free_targeted_hook_lists(st_data_t key, st_data_t val, st_data_t _arg)
+{
+ rb_hook_list_t *hook_list = (rb_hook_list_t*)val;
+ rb_hook_list_free(hook_list);
+ return ST_DELETE;
}
static void
-ractor_queue_free(struct rb_ractor_queue *rq)
+free_targeted_hooks(st_table *hooks_tbl)
{
- free(rq->baskets);
+ st_foreach(hooks_tbl, free_targeted_hook_lists, 0);
}
static void
@@ -240,21 +281,24 @@ ractor_free(void *ptr)
{
rb_ractor_t *r = (rb_ractor_t *)ptr;
RUBY_DEBUG_LOG("free r:%d", rb_ractor_id(r));
+ free_targeted_hooks(r->pub.targeted_hooks);
rb_native_mutex_destroy(&r->sync.lock);
#ifdef RUBY_THREAD_WIN32_H
- rb_native_cond_destroy(&r->sync.cond);
+ rb_native_cond_destroy(&r->sync.wakeup_cond);
#endif
- ractor_queue_free(&r->sync.recv_queue);
- ractor_queue_free(&r->sync.takers_queue);
ractor_local_storage_free(r);
rb_hook_list_free(&r->pub.hooks);
- ruby_xfree(r);
-}
+ st_free_table(r->pub.targeted_hooks);
-static size_t
-ractor_queue_memsize(const struct rb_ractor_queue *rq)
-{
- return sizeof(struct rb_ractor_basket) * rq->size;
+ if (r->newobj_cache) {
+ RUBY_ASSERT(r == ruby_single_main_ractor);
+
+ rb_gc_ractor_cache_free(r->newobj_cache);
+ r->newobj_cache = NULL;
+ }
+
+ ractor_sync_free(r);
+ ruby_xfree(r);
}
static size_t
@@ -263,9 +307,7 @@ ractor_memsize(const void *ptr)
rb_ractor_t *r = (rb_ractor_t *)ptr;
// TODO: more correct?
- return sizeof(rb_ractor_t) +
- ractor_queue_memsize(&r->sync.recv_queue) +
- ractor_queue_memsize(&r->sync.takers_queue);
+ return sizeof(rb_ractor_t) + ractor_sync_memsize(r);
}
static const rb_data_type_t ractor_data_type = {
@@ -313,1595 +355,7 @@ rb_ractor_current_id(void)
}
#endif
-// Ractor queue
-
-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_head(rb_ractor_t *r, struct rb_ractor_queue *rq)
-{
- if (r != NULL) ASSERT_ractor_locking(r);
- return &rq->baskets[rq->start];
-}
-
-static struct rb_ractor_basket *
-ractor_queue_at(rb_ractor_t *r, struct rb_ractor_queue *rq, int i)
-{
- if (r != NULL) ASSERT_ractor_locking(r);
- return &rq->baskets[(rq->start + i) % rq->size];
-}
-
-static void
-ractor_queue_advance(rb_ractor_t *r, struct rb_ractor_queue *rq)
-{
- ASSERT_ractor_locking(r);
-
- if (rq->reserved_cnt == 0) {
- rq->cnt--;
- rq->start = (rq->start + 1) % rq->size;
- rq->serial++;
- }
- else {
- ractor_queue_at(r, rq, 0)->type.e = basket_type_deleted;
- }
-}
-
-static bool
-ractor_queue_skip_p(rb_ractor_t *r, struct rb_ractor_queue *rq, int i)
-{
- struct rb_ractor_basket *b = ractor_queue_at(r, rq, i);
- return basket_type_p(b, basket_type_deleted) ||
- basket_type_p(b, 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 && basket_type_p(ractor_queue_at(r, rq, 0), basket_type_deleted)) {
- ractor_queue_advance(r, 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; i<rq->cnt; i++) {
- if (!ractor_queue_skip_p(r, 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)
-{
- ASSERT_ractor_locking(r);
-
- for (int i=0; i<rq->cnt; i++) {
- if (!ractor_queue_skip_p(r, rq, i)) {
- struct rb_ractor_basket *b = ractor_queue_at(r, rq, i);
- *basket = *b;
-
- // remove from queue
- b->type.e = basket_type_deleted;
- ractor_queue_compact(r, rq);
- return true;
- }
- }
-
- return false;
-}
-
-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; i<rq->cnt; 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_queue_delete(rb_ractor_t *r, struct rb_ractor_queue *rq, struct rb_ractor_basket *basket)
-{
- basket->type.e = basket_type_deleted;
-}
-
-// Ractor basket
-
-static VALUE ractor_reset_belonging(VALUE obj); // in this file
-
-static VALUE
-ractor_basket_value(struct rb_ractor_basket *b)
-{
- switch (b->type.e) {
- case basket_type_ref:
- break;
- case basket_type_copy:
- case basket_type_move:
- case basket_type_will:
- b->type.e = basket_type_ref;
- b->p.send.v = ractor_reset_belonging(b->p.send.v);
- break;
- default:
- rb_bug("unreachable");
- }
-
- return b->p.send.v;
-}
-
-static VALUE
-ractor_basket_accept(struct rb_ractor_basket *b)
-{
- VALUE v = ractor_basket_value(b);
-
- if (b->p.send.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);
- rb_ec_setup_exception(NULL, err, cause);
- rb_exc_raise(err);
- }
-
- return v;
-}
-
-// Ractor synchronizations
-
-#if USE_RUBY_DEBUG_LOG
-static const char *
-wait_status_str(enum rb_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 rb_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");
-}
-
-static const char *
-basket_type_name(enum rb_ractor_basket_type type)
-{
- switch (type) {
- case basket_type_none: return "none";
- case basket_type_ref: return "ref";
- case basket_type_copy: return "copy";
- case basket_type_move: return "move";
- case basket_type_will: return "will";
- case basket_type_deleted: return "deleted";
- case basket_type_reserved: return "reserved";
- case basket_type_take_basket: return "take_basket";
- case basket_type_yielding: return "yielding";
- }
- VM_ASSERT(0);
- return NULL;
-}
-#endif // USE_RUBY_DEBUG_LOG
-
-static bool
-ractor_sleeping_by(const rb_ractor_t *r, enum rb_ractor_wait_status wait_status)
-{
- return (r->sync.wait.status & wait_status) && r->sync.wait.wakeup_status == wakeup_none;
-}
-
-#ifdef RUBY_THREAD_PTHREAD_H
-// thread_*.c
-void rb_ractor_sched_wakeup(rb_ractor_t *r);
-#else
-
-static void
-rb_ractor_sched_wakeup(rb_ractor_t *r)
-{
- rb_native_cond_broadcast(&r->sync.cond);
-}
-#endif
-
-
-static bool
-ractor_wakeup(rb_ractor_t *r, enum rb_ractor_wait_status wait_status, enum rb_ractor_wakeup_status wakeup_status)
-{
- ASSERT_ractor_locking(r);
-
- RUBY_DEBUG_LOG("r:%u wait_by:%s -> wait:%s wakeup:%s",
- rb_ractor_id(r),
- wait_status_str(r->sync.wait.status),
- wait_status_str(wait_status),
- wakeup_status_str(wakeup_status));
-
- if (ractor_sleeping_by(r, wait_status)) {
- r->sync.wait.wakeup_status = wakeup_status;
- rb_ractor_sched_wakeup(r);
- return true;
- }
- else {
- return false;
- }
-}
-
-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);
-}
-
-typedef void (*ractor_sleep_cleanup_function)(rb_ractor_t *cr, void *p);
-
-static void
-ractor_check_ints(rb_execution_context_t *ec, rb_ractor_t *cr, ractor_sleep_cleanup_function cf_func, void *cf_data)
-{
- if (cr->sync.wait.status != wait_none) {
- enum rb_ractor_wait_status prev_wait_status = cr->sync.wait.status;
- cr->sync.wait.status = wait_none;
- cr->sync.wait.wakeup_status = wakeup_by_interrupt;
-
- RACTOR_UNLOCK(cr);
- {
- if (cf_func) {
- enum ruby_tag_type state;
- EC_PUSH_TAG(ec);
- if ((state = EC_EXEC_TAG()) == TAG_NONE) {
- rb_thread_check_ints();
- }
- EC_POP_TAG();
-
- if (state) {
- (*cf_func)(cr, cf_data);
- EC_JUMP_TAG(ec, state);
- }
- }
- else {
- rb_thread_check_ints();
- }
- }
-
- // reachable?
- RACTOR_LOCK(cr);
- cr->sync.wait.status = prev_wait_status;
- }
-}
-
-#ifdef RUBY_THREAD_PTHREAD_H
-void rb_ractor_sched_sleep(rb_execution_context_t *ec, rb_ractor_t *cr, rb_unblock_function_t *ubf);
-#else
-
-// win32
-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 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
-rb_ractor_sched_sleep(rb_execution_context_t *ec, rb_ractor_t *cr, rb_unblock_function_t *ubf)
-{
- RACTOR_UNLOCK(cr);
- {
- rb_nogvl(ractor_sleep_wo_gvl, cr,
- ubf, cr,
- RB_NOGVL_UBF_ASYNC_SAFE | RB_NOGVL_INTR_FAIL);
- }
- RACTOR_LOCK(cr);
-}
-#endif
-
-static enum rb_ractor_wakeup_status
-ractor_sleep_with_cleanup(rb_execution_context_t *ec, rb_ractor_t *cr, enum rb_ractor_wait_status wait_status,
- ractor_sleep_cleanup_function cf_func, void *cf_data)
-{
- enum rb_ractor_wakeup_status wakeup_status;
- VM_ASSERT(GET_RACTOR() == cr);
-
- // TODO: multi-threads
- VM_ASSERT(cr->sync.wait.status == wait_none);
- VM_ASSERT(wait_status != wait_none);
- cr->sync.wait.status = wait_status;
- cr->sync.wait.wakeup_status = wakeup_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));
-
- RUBY_DEBUG_LOG("sleep by %s", wait_status_str(wait_status));
-
- while (cr->sync.wait.wakeup_status == wakeup_none) {
- rb_ractor_sched_sleep(ec, cr, ractor_sleep_interrupt);
- ractor_check_ints(ec, cr, cf_func, cf_data);
- }
-
- cr->sync.wait.status = wait_none;
-
- // TODO: multi-thread
- wakeup_status = cr->sync.wait.wakeup_status;
- cr->sync.wait.wakeup_status = wakeup_none;
-
- RUBY_DEBUG_LOG("wakeup %s", wakeup_status_str(wakeup_status));
-
- return wakeup_status;
-}
-
-static enum rb_ractor_wakeup_status
-ractor_sleep(rb_execution_context_t *ec, rb_ractor_t *cr, enum rb_ractor_wait_status wait_status)
-{
- return ractor_sleep_with_cleanup(ec, cr, wait_status, 0, NULL);
-}
-
-// Ractor.receive
-
-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 *cr, struct rb_ractor_queue *rq)
-{
- struct rb_ractor_basket basket;
- ractor_recursive_receive_if(cr);
- bool received = false;
-
- RACTOR_LOCK_SELF(cr);
- {
- RUBY_DEBUG_LOG("rq->cnt:%d", rq->cnt);
- received = ractor_queue_deq(cr, rq, &basket);
- }
- RACTOR_UNLOCK_SELF(cr);
-
- if (!received) {
- if (cr->sync.incoming_port_closed) {
- rb_raise(rb_eRactorClosedError, "The incoming port is already closed");
- }
- return Qundef;
- }
- else {
- return ractor_basket_accept(&basket);
- }
-}
-
-static void
-ractor_wait_receive(rb_execution_context_t *ec, rb_ractor_t *cr, struct rb_ractor_queue *rq)
-{
- VM_ASSERT(cr == rb_ec_ractor_ptr(ec));
- ractor_recursive_receive_if(cr);
-
- RACTOR_LOCK(cr);
- {
- while (ractor_queue_empty_p(cr, rq)) {
- ractor_sleep(ec, cr, wait_receiving);
- }
- }
- 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;
- struct rb_ractor_queue *rq = &cr->sync.recv_queue;
-
- while (UNDEF_P(v = ractor_try_receive(ec, cr, rq))) {
- ractor_wait_receive(ec, cr, rq);
- }
-
- return v;
-}
-
-#if 0
-static void
-rq_dump(struct rb_ractor_queue *rq)
-{
- bool bug = false;
- for (int i=0; i<rq->cnt; i++) {
- struct rb_ractor_basket *b = ractor_queue_at(NULL, 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 (basket_type_p(b, 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);
- rb_ractor_t *cr = data->cr;
-
- RACTOR_LOCK_SELF(cr);
- {
- struct rb_ractor_basket *b = ractor_queue_at(cr, data->rq, data->index);
- VM_ASSERT(basket_type_p(b, basket_type_reserved));
- data->rq->reserved_cnt--;
-
- if (RTEST(block_result)) {
- ractor_queue_delete(cr, data->rq, b);
- ractor_queue_compact(cr, data->rq);
- }
- else {
- b->type.e = basket_type_ref;
- }
- }
- RACTOR_UNLOCK_SELF(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;
- rb_ractor_t *cr = data->cr;
-
- if (!data->success) {
- RACTOR_LOCK_SELF(cr);
- {
- struct rb_ractor_basket *b = ractor_queue_at(cr, data->rq, data->index);
- VM_ASSERT(basket_type_p(b, basket_type_reserved));
- b->type.e = basket_type_deleted;
- data->rq->reserved_cnt--;
- }
- RACTOR_UNLOCK_SELF(cr);
- }
-
- rb_mutex_unlock(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.recv_queue;
-
- while (1) {
- VALUE v = Qundef;
-
- ractor_wait_receive(ec, cr, rq);
-
- RACTOR_LOCK_SELF(cr);
- {
- if (serial != rq->serial) {
- serial = rq->serial;
- index = 0;
- }
-
- // check newer version
- for (int i=index; i<rq->cnt; i++) {
- if (!ractor_queue_skip_p(cr, rq, i)) {
- struct rb_ractor_basket *b = ractor_queue_at(cr, rq, i);
- v = ractor_basket_value(b);
- b->type.e = basket_type_reserved;
- rq->reserved_cnt++;
- index = i;
- break;
- }
- }
- }
- RACTOR_UNLOCK_SELF(cr);
-
- if (!UNDEF_P(v)) {
- 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 (!UNDEF_P(result)) return result;
- index++;
- }
-
- RUBY_VM_CHECK_INTS(ec);
- }
-}
-
-static void
-ractor_send_basket(rb_execution_context_t *ec, rb_ractor_t *r, struct rb_ractor_basket *b)
-{
- bool closed = false;
-
- RACTOR_LOCK(r);
- {
- if (r->sync.incoming_port_closed) {
- closed = true;
- }
- else {
- ractor_queue_enq(r, &r->sync.recv_queue, b);
- ractor_wakeup(r, wait_receiving, wakeup_by_send);
- }
- }
- RACTOR_UNLOCK(r);
-
- if (closed) {
- rb_raise(rb_eRactorClosedError, "The incoming-port is already closed");
- }
-}
-
-// Ractor#send
-
-static VALUE ractor_move(VALUE obj); // in this file
-static VALUE ractor_copy(VALUE obj); // in this file
-
-static void
-ractor_basket_prepare_contents(VALUE obj, VALUE move, volatile VALUE *pobj, enum rb_ractor_basket_type *ptype)
-{
- VALUE v;
- enum rb_ractor_basket_type type;
-
- if (rb_ractor_shareable_p(obj)) {
- type = basket_type_ref;
- v = obj;
- }
- else if (!RTEST(move)) {
- v = ractor_copy(obj);
- type = basket_type_copy;
- }
- else {
- type = basket_type_move;
- v = ractor_move(obj);
- }
-
- *pobj = v;
- *ptype = type;
-}
-
-static void
-ractor_basket_fill_(rb_ractor_t *cr, struct rb_ractor_basket *basket, VALUE obj, bool exc)
-{
- VM_ASSERT(cr == GET_RACTOR());
-
- basket->sender = cr->pub.self;
- basket->p.send.exception = exc;
- basket->p.send.v = obj;
-}
-
-static void
-ractor_basket_fill(rb_ractor_t *cr, struct rb_ractor_basket *basket, VALUE obj, VALUE move, bool exc)
-{
- VALUE v;
- enum rb_ractor_basket_type type;
- ractor_basket_prepare_contents(obj, move, &v, &type);
- ractor_basket_fill_(cr, basket, v, exc);
- basket->type.e = type;
-}
-
-static void
-ractor_basket_fill_will(rb_ractor_t *cr, struct rb_ractor_basket *basket, VALUE obj, bool exc)
-{
- ractor_basket_fill_(cr, basket, obj, exc);
- basket->type.e = basket_type_will;
-}
-
-static VALUE
-ractor_send(rb_execution_context_t *ec, rb_ractor_t *r, VALUE obj, VALUE move)
-{
- struct rb_ractor_basket basket;
- // TODO: Ractor local GC
- ractor_basket_fill(rb_ec_ractor_ptr(ec), &basket, obj, move, false);
- ractor_send_basket(ec, r, &basket);
- return r->pub.self;
-}
-
-// Ractor#take
-
-static bool
-ractor_take_has_will(rb_ractor_t *r)
-{
- ASSERT_ractor_locking(r);
-
- return basket_type_p(&r->sync.will_basket, basket_type_will);
-}
-
-static bool
-ractor_take_will(rb_ractor_t *r, struct rb_ractor_basket *b)
-{
- ASSERT_ractor_locking(r);
-
- if (ractor_take_has_will(r)) {
- *b = r->sync.will_basket;
- r->sync.will_basket.type.e = basket_type_none;
- return true;
- }
- else {
- VM_ASSERT(basket_type_p(&r->sync.will_basket, basket_type_none));
- return false;
- }
-}
-
-static bool
-ractor_take_will_lock(rb_ractor_t *r, struct rb_ractor_basket *b)
-{
- ASSERT_ractor_unlocking(r);
- bool taken;
-
- RACTOR_LOCK(r);
- {
- taken = ractor_take_will(r, b);
- }
- RACTOR_UNLOCK(r);
-
- return taken;
-}
-
-static bool
-ractor_register_take(rb_ractor_t *cr, rb_ractor_t *r, struct rb_ractor_basket *take_basket,
- bool is_take, struct rb_ractor_selector_take_config *config, bool ignore_error)
-{
- struct rb_ractor_basket b = {
- .type.e = basket_type_take_basket,
- .sender = cr->pub.self,
- .p = {
- .take = {
- .basket = take_basket,
- .config = config,
- },
- },
- };
- bool closed = false;
-
- RACTOR_LOCK(r);
- {
- if (is_take && ractor_take_will(r, take_basket)) {
- RUBY_DEBUG_LOG("take over a will of r:%d", rb_ractor_id(r));
- }
- else if (!is_take && ractor_take_has_will(r)) {
- RUBY_DEBUG_LOG("has_will");
- VM_ASSERT(config != NULL);
- config->closed = true;
- }
- else if (r->sync.outgoing_port_closed) {
- closed = true;
- }
- else {
- RUBY_DEBUG_LOG("register in r:%d", rb_ractor_id(r));
- ractor_queue_enq(r, &r->sync.takers_queue, &b);
-
- if (basket_none_p(take_basket)) {
- ractor_wakeup(r, wait_yielding, wakeup_by_take);
- }
- }
- }
- RACTOR_UNLOCK(r);
-
- if (closed) {
- if (!ignore_error) rb_raise(rb_eRactorClosedError, "The outgoing-port is already closed");
- return false;
- }
- else {
- return true;
- }
-}
-
-static bool
-ractor_deregister_take(rb_ractor_t *r, struct rb_ractor_basket *take_basket)
-{
- struct rb_ractor_queue *ts = &r->sync.takers_queue;
- bool deleted = false;
-
- RACTOR_LOCK(r);
- {
- if (r->sync.outgoing_port_closed) {
- // ok
- }
- else {
- for (int i=0; i<ts->cnt; i++) {
- struct rb_ractor_basket *b = ractor_queue_at(r, ts, i);
- if (basket_type_p(b, basket_type_take_basket) && b->p.take.basket == take_basket) {
- ractor_queue_delete(r, ts, b);
- deleted = true;
- }
- }
- if (deleted) {
- ractor_queue_compact(r, ts);
- }
- }
- }
- RACTOR_UNLOCK(r);
-
- return deleted;
-}
-
-static VALUE
-ractor_try_take(rb_ractor_t *cr, rb_ractor_t *r, struct rb_ractor_basket *take_basket)
-{
- bool taken;
-
- RACTOR_LOCK_SELF(cr);
- {
- if (basket_none_p(take_basket) || basket_type_p(take_basket, basket_type_yielding)) {
- taken = false;
- }
- else {
- taken = true;
- }
- }
- RACTOR_UNLOCK_SELF(cr);
-
- if (taken) {
- RUBY_DEBUG_LOG("taken");
- if (basket_type_p(take_basket, basket_type_deleted)) {
- VM_ASSERT(r->sync.outgoing_port_closed);
- rb_raise(rb_eRactorClosedError, "The outgoing-port is already closed");
- }
- return ractor_basket_accept(take_basket);
- }
- else {
- RUBY_DEBUG_LOG("not taken");
- return Qundef;
- }
-}
-
-
-#if VM_CHECK_MODE > 0
-static bool
-ractor_check_specific_take_basket_lock(rb_ractor_t *r, struct rb_ractor_basket *tb)
-{
- bool ret = false;
- struct rb_ractor_queue *ts = &r->sync.takers_queue;
-
- RACTOR_LOCK(r);
- {
- for (int i=0; i<ts->cnt; i++) {
- struct rb_ractor_basket *b = ractor_queue_at(r, ts, i);
- if (basket_type_p(b, basket_type_take_basket) && b->p.take.basket == tb) {
- ret = true;
- break;
- }
- }
- }
- RACTOR_UNLOCK(r);
-
- return ret;
-}
-#endif
-
-static void
-ractor_take_cleanup(rb_ractor_t *cr, rb_ractor_t *r, struct rb_ractor_basket *tb)
-{
- retry:
- if (basket_none_p(tb)) { // not yielded yet
- if (!ractor_deregister_take(r, tb)) {
- // not in r's takers queue
- rb_thread_sleep(0);
- goto retry;
- }
- }
- else {
- VM_ASSERT(!ractor_check_specific_take_basket_lock(r, tb));
- }
-}
-
-struct take_wait_take_cleanup_data {
- rb_ractor_t *r;
- struct rb_ractor_basket *tb;
-};
-
-static void
-ractor_wait_take_cleanup(rb_ractor_t *cr, void *ptr)
-{
- struct take_wait_take_cleanup_data *data = (struct take_wait_take_cleanup_data *)ptr;
- ractor_take_cleanup(cr, data->r, data->tb);
-}
-
-static void
-ractor_wait_take(rb_execution_context_t *ec, rb_ractor_t *cr, rb_ractor_t *r, struct rb_ractor_basket *take_basket)
-{
- struct take_wait_take_cleanup_data data = {
- .r = r,
- .tb = take_basket,
- };
-
- RACTOR_LOCK_SELF(cr);
- {
- if (basket_none_p(take_basket) || basket_type_p(take_basket, basket_type_yielding)) {
- ractor_sleep_with_cleanup(ec, cr, wait_taking, ractor_wait_take_cleanup, &data);
- }
- }
- RACTOR_UNLOCK_SELF(cr);
-}
-
-static VALUE
-ractor_take(rb_execution_context_t *ec, rb_ractor_t *r)
-{
- RUBY_DEBUG_LOG("from r:%u", rb_ractor_id(r));
- VALUE v;
- rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
-
- struct rb_ractor_basket take_basket = {
- .type.e = basket_type_none,
- .sender = 0,
- };
-
- ractor_register_take(cr, r, &take_basket, true, NULL, false);
-
- while (UNDEF_P(v = ractor_try_take(cr, r, &take_basket))) {
- ractor_wait_take(ec, cr, r, &take_basket);
- }
-
- VM_ASSERT(!basket_none_p(&take_basket));
- VM_ASSERT(!ractor_check_specific_take_basket_lock(r, &take_basket));
-
- return v;
-}
-
-// Ractor.yield
-
-static bool
-ractor_check_take_basket(rb_ractor_t *cr, struct rb_ractor_queue *rs)
-{
- ASSERT_ractor_locking(cr);
-
- for (int i=0; i<rs->cnt; i++) {
- struct rb_ractor_basket *b = ractor_queue_at(cr, rs, i);
- if (basket_type_p(b, basket_type_take_basket) &&
- basket_none_p(b->p.take.basket)) {
- return true;
- }
- }
-
- return false;
-}
-
-static bool
-ractor_deq_take_basket(rb_ractor_t *cr, struct rb_ractor_queue *rs, struct rb_ractor_basket *b)
-{
- ASSERT_ractor_unlocking(cr);
- struct rb_ractor_basket *first_tb = NULL;
- bool found = false;
-
- RACTOR_LOCK_SELF(cr);
- {
- while (ractor_queue_deq(cr, rs, b)) {
- if (basket_type_p(b, basket_type_take_basket)) {
- struct rb_ractor_basket *tb = b->p.take.basket;
-
- if (RUBY_ATOMIC_CAS(tb->type.atomic, basket_type_none, basket_type_yielding) == basket_type_none) {
- found = true;
- break;
- }
- else {
- ractor_queue_enq(cr, rs, b);
- if (first_tb == NULL) first_tb = tb;
- struct rb_ractor_basket *head = ractor_queue_head(cr, rs);
- VM_ASSERT(head != NULL);
- if (basket_type_p(head, basket_type_take_basket) && head->p.take.basket == first_tb) {
- break; // loop detected
- }
- }
- }
- else {
- VM_ASSERT(basket_none_p(b));
- }
- }
-
- if (found && b->p.take.config && !b->p.take.config->oneshot) {
- ractor_queue_enq(cr, rs, b);
- }
- }
- RACTOR_UNLOCK_SELF(cr);
-
- return found;
-}
-
-static bool
-ractor_try_yield(rb_execution_context_t *ec, rb_ractor_t *cr, struct rb_ractor_queue *ts, volatile VALUE obj, VALUE move, bool exc, bool is_will)
-{
- ASSERT_ractor_unlocking(cr);
-
- struct rb_ractor_basket b;
-
- if (ractor_deq_take_basket(cr, ts, &b)) {
- VM_ASSERT(basket_type_p(&b, basket_type_take_basket));
- VM_ASSERT(basket_type_p(b.p.take.basket, basket_type_yielding));
-
- rb_ractor_t *tr = RACTOR_PTR(b.sender);
- struct rb_ractor_basket *tb = b.p.take.basket;
- enum rb_ractor_basket_type type;
-
- RUBY_DEBUG_LOG("basket from r:%u", rb_ractor_id(tr));
-
- if (is_will) {
- type = basket_type_will;
- }
- else {
- enum ruby_tag_type state;
-
- // begin
- EC_PUSH_TAG(ec);
- if ((state = EC_EXEC_TAG()) == TAG_NONE) {
- // TODO: Ractor local GC
- ractor_basket_prepare_contents(obj, move, &obj, &type);
- }
- EC_POP_TAG();
- // rescue
- if (state) {
- RACTOR_LOCK_SELF(cr);
- {
- b.p.take.basket->type.e = basket_type_none;
- ractor_queue_enq(cr, ts, &b);
- }
- RACTOR_UNLOCK_SELF(cr);
- EC_JUMP_TAG(ec, state);
- }
- }
-
- RACTOR_LOCK(tr);
- {
- VM_ASSERT(basket_type_p(tb, basket_type_yielding));
- // fill atomic
- RUBY_DEBUG_LOG("fill %sbasket from r:%u", is_will ? "will " : "", rb_ractor_id(tr));
- ractor_basket_fill_(cr, tb, obj, exc);
- if (RUBY_ATOMIC_CAS(tb->type.atomic, basket_type_yielding, type) != basket_type_yielding) {
- rb_bug("unreachable");
- }
- ractor_wakeup(tr, wait_taking, wakeup_by_yield);
- }
- RACTOR_UNLOCK(tr);
-
- return true;
- }
- else {
- RUBY_DEBUG_LOG("no take basket");
- return false;
- }
-}
-
-static void
-ractor_wait_yield(rb_execution_context_t *ec, rb_ractor_t *cr, struct rb_ractor_queue *ts)
-{
- RACTOR_LOCK_SELF(cr);
- {
- while (!ractor_check_take_basket(cr, ts)) {
- ractor_sleep(ec, cr, wait_yielding);
- }
- }
- RACTOR_UNLOCK_SELF(cr);
-}
-
-static VALUE
-ractor_yield(rb_execution_context_t *ec, rb_ractor_t *cr, VALUE obj, VALUE move)
-{
- struct rb_ractor_queue *ts = &cr->sync.takers_queue;
-
- while (!ractor_try_yield(ec, cr, ts, obj, move, false, false)) {
- ractor_wait_yield(ec, cr, ts);
- }
-
- return Qnil;
-}
-
-// Ractor::Selector
-
-struct rb_ractor_selector {
- rb_ractor_t *r;
- struct rb_ractor_basket take_basket;
- st_table *take_ractors; // rb_ractor_t * => (struct rb_ractor_selector_take_config *)
-};
-
-static int
-ractor_selector_mark_ractors_i(st_data_t key, st_data_t value, st_data_t data)
-{
- const rb_ractor_t *r = (rb_ractor_t *)key;
- rb_gc_mark(r->pub.self);
- return ST_CONTINUE;
-}
-
-static void
-ractor_selector_mark(void *ptr)
-{
- struct rb_ractor_selector *s = ptr;
-
- if (s->take_ractors) {
- st_foreach(s->take_ractors, ractor_selector_mark_ractors_i, 0);
- }
-
- switch (s->take_basket.type.e) {
- case basket_type_ref:
- case basket_type_copy:
- case basket_type_move:
- case basket_type_will:
- rb_gc_mark(s->take_basket.sender);
- rb_gc_mark(s->take_basket.p.send.v);
- break;
- default:
- break;
- }
-}
-
-static int
-ractor_selector_release_i(st_data_t key, st_data_t val, st_data_t data)
-{
- struct rb_ractor_selector *s = (struct rb_ractor_selector *)data;
- struct rb_ractor_selector_take_config *config = (struct rb_ractor_selector_take_config *)val;
-
- if (!config->closed) {
- ractor_deregister_take((rb_ractor_t *)key, &s->take_basket);
- }
- free(config);
- return ST_CONTINUE;
-}
-
-static void
-ractor_selector_free(void *ptr)
-{
- struct rb_ractor_selector *s = ptr;
- st_foreach(s->take_ractors, ractor_selector_release_i, (st_data_t)s);
- st_free_table(s->take_ractors);
- ruby_xfree(ptr);
-}
-
-static size_t
-ractor_selector_memsize(const void *ptr)
-{
- const struct rb_ractor_selector *s = ptr;
- return sizeof(struct rb_ractor_selector) +
- st_memsize(s->take_ractors) +
- s->take_ractors->num_entries * sizeof(struct rb_ractor_selector_take_config);
-}
-
-static const rb_data_type_t ractor_selector_data_type = {
- "ractor/selector",
- {
- ractor_selector_mark,
- ractor_selector_free,
- ractor_selector_memsize,
- NULL, // update
- },
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
-};
-
-static struct rb_ractor_selector *
-RACTOR_SELECTOR_PTR(VALUE selv)
-{
- VM_ASSERT(rb_typeddata_is_kind_of(selv, &ractor_selector_data_type));
-
- return (struct rb_ractor_selector *)DATA_PTR(selv);
-}
-
-// Ractor::Selector.new
-
-static VALUE
-ractor_selector_create(VALUE klass)
-{
- struct rb_ractor_selector *s;
- VALUE selv = TypedData_Make_Struct(klass, struct rb_ractor_selector, &ractor_selector_data_type, s);
- s->take_basket.type.e = basket_type_reserved;
- s->take_ractors = st_init_numtable(); // ractor (ptr) -> take_config
- return selv;
-}
-
-// Ractor::Selector#add(r)
-
-static VALUE
-ractor_selector_add(VALUE selv, VALUE rv)
-{
- if (!rb_ractor_p(rv)) {
- rb_raise(rb_eArgError, "Not a ractor object");
- }
-
- rb_ractor_t *r = RACTOR_PTR(rv);
- struct rb_ractor_selector *s = RACTOR_SELECTOR_PTR(selv);
-
- if (st_lookup(s->take_ractors, (st_data_t)r, NULL)) {
- rb_raise(rb_eArgError, "already added");
- }
-
- struct rb_ractor_selector_take_config *config = malloc(sizeof(struct rb_ractor_selector_take_config));
- VM_ASSERT(config != NULL);
- config->closed = false;
- config->oneshot = false;
-
- if (ractor_register_take(GET_RACTOR(), r, &s->take_basket, false, config, true)) {
- st_insert(s->take_ractors, (st_data_t)r, (st_data_t)config);
- }
-
- return rv;
-}
-
-// Ractor::Selector#remove(r)
-
-static VALUE
-ractor_selector_remove(VALUE selv, VALUE rv)
-{
- if (!rb_ractor_p(rv)) {
- rb_raise(rb_eArgError, "Not a ractor object");
- }
-
- rb_ractor_t *r = RACTOR_PTR(rv);
- struct rb_ractor_selector *s = RACTOR_SELECTOR_PTR(selv);
-
- RUBY_DEBUG_LOG("r:%u", rb_ractor_id(r));
-
- if (!st_lookup(s->take_ractors, (st_data_t)r, NULL)) {
- rb_raise(rb_eArgError, "not added yet");
- }
-
- ractor_deregister_take(r, &s->take_basket);
- struct rb_ractor_selector_take_config *config;
- st_delete(s->take_ractors, (st_data_t *)&r, (st_data_t *)&config);
- free(config);
-
- return rv;
-}
-
-// Ractor::Selector#clear
-
-struct ractor_selector_clear_data {
- VALUE selv;
- rb_execution_context_t *ec;
-};
-
-static int
-ractor_selector_clear_i(st_data_t key, st_data_t val, st_data_t data)
-{
- VALUE selv = (VALUE)data;
- rb_ractor_t *r = (rb_ractor_t *)key;
- ractor_selector_remove(selv, r->pub.self);
- return ST_CONTINUE;
-}
-
-static VALUE
-ractor_selector_clear(VALUE selv)
-{
- struct rb_ractor_selector *s = RACTOR_SELECTOR_PTR(selv);
-
- st_foreach(s->take_ractors, ractor_selector_clear_i, (st_data_t)selv);
- st_clear(s->take_ractors);
- return selv;
-}
-
-static VALUE
-ractor_selector_empty_p(VALUE selv)
-{
- struct rb_ractor_selector *s = RACTOR_SELECTOR_PTR(selv);
- return s->take_ractors->num_entries == 0 ? Qtrue : Qfalse;
-}
-
-static int
-ractor_selector_wait_i(st_data_t key, st_data_t val, st_data_t dat)
-{
- rb_ractor_t *r = (rb_ractor_t *)key;
- struct rb_ractor_basket *tb = (struct rb_ractor_basket *)dat;
- int ret;
-
- if (!basket_none_p(tb)) {
- RUBY_DEBUG_LOG("already taken:%s", basket_type_name(tb->type.e));
- return ST_STOP;
- }
-
- RACTOR_LOCK(r);
- {
- if (basket_type_p(&r->sync.will_basket, basket_type_will)) {
- RUBY_DEBUG_LOG("r:%u has will", rb_ractor_id(r));
-
- if (RUBY_ATOMIC_CAS(tb->type.atomic, basket_type_none, basket_type_will) == basket_type_none) {
- ractor_take_will(r, tb);
- ret = ST_STOP;
- }
- else {
- RUBY_DEBUG_LOG("has will, but already taken (%s)", basket_type_name(tb->type.e));
- ret = ST_CONTINUE;
- }
- }
- else if (r->sync.outgoing_port_closed) {
- RUBY_DEBUG_LOG("r:%u is closed", rb_ractor_id(r));
-
- if (RUBY_ATOMIC_CAS(tb->type.atomic, basket_type_none, basket_type_deleted) == basket_type_none) {
- tb->sender = r->pub.self;
- ret = ST_STOP;
- }
- else {
- RUBY_DEBUG_LOG("closed, but already taken (%s)", basket_type_name(tb->type.e));
- ret = ST_CONTINUE;
- }
- }
- else {
- RUBY_DEBUG_LOG("wakeup r:%u", rb_ractor_id(r));
- ractor_wakeup(r, wait_yielding, wakeup_by_take);
- ret = ST_CONTINUE;
- }
- }
- RACTOR_UNLOCK(r);
-
- return ret;
-}
-
-// Ractor::Selector#wait
-
-static void
-ractor_selector_wait_cleaup(rb_ractor_t *cr, void *ptr)
-{
- struct rb_ractor_basket *tb = (struct rb_ractor_basket *)ptr;
-
- RACTOR_LOCK_SELF(cr);
- {
- while (basket_type_p(tb, basket_type_yielding)) rb_thread_sleep(0);
- // if tb->type is not none, taking is succeeded, but interruption ignore it unfortunately.
- tb->type.e = basket_type_reserved;
- }
- RACTOR_UNLOCK_SELF(cr);
-}
-
-static VALUE
-ractor_selector__wait(VALUE selv, VALUE do_receivev, VALUE do_yieldv, VALUE yield_value, VALUE move)
-{
- rb_execution_context_t *ec = GET_EC();
- struct rb_ractor_selector *s = RACTOR_SELECTOR_PTR(selv);
- struct rb_ractor_basket *tb = &s->take_basket;
- struct rb_ractor_basket taken_basket;
- rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
- bool do_receive = !!RTEST(do_receivev);
- bool do_yield = !!RTEST(do_yieldv);
- VALUE ret_v, ret_r;
- enum rb_ractor_wait_status wait_status;
- struct rb_ractor_queue *rq = &cr->sync.recv_queue;
- struct rb_ractor_queue *ts = &cr->sync.takers_queue;
-
- RUBY_DEBUG_LOG("start");
-
- retry:
- RUBY_DEBUG_LOG("takers:%ld", s->take_ractors->num_entries);
-
- // setup wait_status
- wait_status = wait_none;
- if (s->take_ractors->num_entries > 0) wait_status |= wait_taking;
- if (do_receive) wait_status |= wait_receiving;
- if (do_yield) wait_status |= wait_yielding;
-
- RUBY_DEBUG_LOG("wait:%s", wait_status_str(wait_status));
-
- if (wait_status == wait_none) {
- rb_raise(rb_eRactorError, "no taking ractors");
- }
-
- // check recv_queue
- if (do_receive && !UNDEF_P(ret_v = ractor_try_receive(ec, cr, rq))) {
- ret_r = ID2SYM(rb_intern("receive"));
- goto success;
- }
-
- // check takers
- if (do_yield && ractor_try_yield(ec, cr, ts, yield_value, move, false, false)) {
- ret_v = Qnil;
- ret_r = ID2SYM(rb_intern("yield"));
- goto success;
- }
-
- // check take_basket
- VM_ASSERT(basket_type_p(&s->take_basket, basket_type_reserved));
- s->take_basket.type.e = basket_type_none;
- // kick all take target ractors
- st_foreach(s->take_ractors, ractor_selector_wait_i, (st_data_t)tb);
-
- RACTOR_LOCK_SELF(cr);
- {
- retry_waiting:
- while (1) {
- if (!basket_none_p(tb)) {
- RUBY_DEBUG_LOG("taken:%s from r:%u", basket_type_name(tb->type.e),
- tb->sender ? rb_ractor_id(RACTOR_PTR(tb->sender)) : 0);
- break;
- }
- if (do_receive && !ractor_queue_empty_p(cr, rq)) {
- RUBY_DEBUG_LOG("can receive (%d)", rq->cnt);
- break;
- }
- if (do_yield && ractor_check_take_basket(cr, ts)) {
- RUBY_DEBUG_LOG("can yield");
- break;
- }
-
- ractor_sleep_with_cleanup(ec, cr, wait_status, ractor_selector_wait_cleaup, tb);
- }
-
- taken_basket = *tb;
-
- // ensure
- // tb->type.e = basket_type_reserved # do it atomic in the following code
- if (taken_basket.type.e == basket_type_yielding ||
- RUBY_ATOMIC_CAS(tb->type.atomic, taken_basket.type.e, basket_type_reserved) != taken_basket.type.e) {
-
- if (basket_type_p(tb, basket_type_yielding)) {
- RACTOR_UNLOCK_SELF(cr);
- {
- rb_thread_sleep(0);
- }
- RACTOR_LOCK_SELF(cr);
- }
- goto retry_waiting;
- }
- }
- RACTOR_UNLOCK_SELF(cr);
-
- // check the taken resutl
- switch (taken_basket.type.e) {
- case basket_type_none:
- VM_ASSERT(do_receive || do_yield);
- goto retry;
- case basket_type_yielding:
- rb_bug("unreachable");
- case basket_type_deleted: {
- ractor_selector_remove(selv, taken_basket.sender);
-
- rb_ractor_t *r = RACTOR_PTR(taken_basket.sender);
- if (ractor_take_will_lock(r, &taken_basket)) {
- RUBY_DEBUG_LOG("has_will");
- }
- else {
- RUBY_DEBUG_LOG("no will");
- // rb_raise(rb_eRactorClosedError, "The outgoing-port is already closed");
- // remove and retry wait
- goto retry;
- }
- break;
- }
- case basket_type_will:
- // no more messages
- ractor_selector_remove(selv, taken_basket.sender);
- break;
- default:
- break;
- }
-
- RUBY_DEBUG_LOG("taken_basket:%s", basket_type_name(taken_basket.type.e));
-
- ret_v = ractor_basket_accept(&taken_basket);
- ret_r = taken_basket.sender;
- success:
- return rb_ary_new_from_args(2, ret_r, ret_v);
-}
-
-static VALUE
-ractor_selector_wait(int argc, VALUE *argv, VALUE selector)
-{
- VALUE options;
- ID keywords[3];
- VALUE values[3];
-
- keywords[0] = rb_intern("receive");
- keywords[1] = rb_intern("yield_value");
- keywords[2] = rb_intern("move");
-
- rb_scan_args(argc, argv, "0:", &options);
- rb_get_kwargs(options, keywords, 0, numberof(values), values);
- return ractor_selector__wait(selector,
- values[0] == Qundef ? Qfalse : RTEST(values[0]),
- values[1] != Qundef, values[1], values[2]);
-}
-
-static VALUE
-ractor_selector_new(int argc, VALUE *ractors, VALUE klass)
-{
- VALUE selector = ractor_selector_create(klass);
-
- for (int i=0; i<argc; i++) {
- ractor_selector_add(selector, ractors[i]);
- }
-
- return selector;
-}
-
-static VALUE
-ractor_select_internal(rb_execution_context_t *ec, VALUE self, VALUE ractors, VALUE do_receive, VALUE do_yield, VALUE yield_value, VALUE move)
-{
- VALUE selector = ractor_selector_new(RARRAY_LENINT(ractors), (VALUE *)RARRAY_CONST_PTR(ractors), rb_cRactorSelector);
- VALUE result;
- int state;
-
- EC_PUSH_TAG(ec);
- if ((state = EC_EXEC_TAG()) == TAG_NONE) {
- result = ractor_selector__wait(selector, do_receive, do_yield, yield_value, move);
- }
- EC_POP_TAG();
- if (state != TAG_NONE) {
- // ensure
- ractor_selector_clear(selector);
-
- // jump
- EC_JUMP_TAG(ec, state);
- }
-
- RB_GC_GUARD(ractors);
- return result;
-}
-
-// Ractor#close_incoming
-
-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(ractor_queue_empty_p(r, &r->sync.recv_queue));
- RUBY_DEBUG_LOG("cancel receiving");
- }
- }
- else {
- prev = Qtrue;
- }
- }
- RACTOR_UNLOCK(r);
- return prev;
-}
-
-// Ractor#close_outgoing
-
-static VALUE
-ractor_close_outgoing(rb_execution_context_t *ec, rb_ractor_t *r)
-{
- VALUE prev;
-
- RACTOR_LOCK(r);
- {
- struct rb_ractor_queue *ts = &r->sync.takers_queue;
- rb_ractor_t *tr;
- struct rb_ractor_basket b;
-
- if (!r->sync.outgoing_port_closed) {
- prev = Qfalse;
- r->sync.outgoing_port_closed = true;
- }
- else {
- VM_ASSERT(ractor_queue_empty_p(r, ts));
- prev = Qtrue;
- }
-
- // wakeup all taking ractors
- while (ractor_queue_deq(r, ts, &b)) {
- if (basket_type_p(&b, basket_type_take_basket)) {
- tr = RACTOR_PTR(b.sender);
- struct rb_ractor_basket *tb = b.p.take.basket;
-
- if (RUBY_ATOMIC_CAS(tb->type.atomic, basket_type_none, basket_type_yielding) == basket_type_none) {
- b.p.take.basket->sender = r->pub.self;
- if (RUBY_ATOMIC_CAS(tb->type.atomic, basket_type_yielding, basket_type_deleted) != basket_type_yielding) {
- rb_bug("unreachable");
- }
- RUBY_DEBUG_LOG("set delete for r:%u", rb_ractor_id(RACTOR_PTR(b.sender)));
- }
-
- if (b.p.take.config) {
- b.p.take.config->closed = true;
- }
-
- // TODO: deadlock-able?
- RACTOR_LOCK(tr);
- {
- ractor_wakeup(tr, wait_taking, wakeup_by_close);
- }
- RACTOR_UNLOCK(tr);
- }
- }
-
- // raising yielding Ractor
- ractor_wakeup(r, wait_yielding, wakeup_by_close);
-
- VM_ASSERT(ractor_queue_empty_p(r, ts));
- }
- RACTOR_UNLOCK(r);
- return prev;
-}
+#include "ractor_sync.c"
// creation/termination
@@ -1923,6 +377,13 @@ vm_insert_ractor0(rb_vm_t *vm, rb_ractor_t *r, bool single_ractor_mode)
ccan_list_add_tail(&vm->ractor.set, &r->vmlr_node);
vm->ractor.cnt++;
+
+ if (r->newobj_cache) {
+ VM_ASSERT(r == ruby_single_main_ractor);
+ }
+ else {
+ r->newobj_cache = rb_gc_ractor_cache_alloc(r);
+ }
}
static void
@@ -1931,15 +392,8 @@ 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();
-
- if (was_disabled) {
- rb_gc_disable();
- }
-
ruby_single_main_ractor = NULL;
+ rb_funcall(rb_cRactor, rb_intern("_activated"), 0);
}
static void
@@ -1990,8 +444,8 @@ vm_remove_ractor(rb_vm_t *vm, rb_ractor_t *cr)
}
vm->ractor.cnt--;
- /* Clear the cached freelist to prevent a memory leak. */
- rb_gc_ractor_newobj_cache_clear(&cr->newobj_cache);
+ rb_gc_ractor_cache_free(cr->newobj_cache);
+ cr->newobj_cache = NULL;
ractor_status_set(cr, ractor_terminated);
}
@@ -2005,6 +459,7 @@ ractor_alloc(VALUE klass)
VALUE rv = TypedData_Make_Struct(klass, rb_ractor_t, &ractor_data_type, r);
FL_SET_RAW(rv, RUBY_FL_SHAREABLE);
r->pub.self = rv;
+ r->next_ec_serial = 1;
VM_ASSERT(ractor_status_p(r, ractor_created));
return rv;
}
@@ -2021,12 +476,16 @@ rb_ractor_main_alloc(void)
r->loc = Qnil;
r->name = Qnil;
r->pub.self = Qnil;
+ r->newobj_cache = rb_gc_ractor_cache_alloc(r);
+ r->next_ec_serial = 1;
ruby_single_main_ractor = r;
return r;
}
#if defined(HAVE_WORKING_FORK)
+// Set up the main Ractor for the VM after fork.
+// Puts us in "single Ractor mode"
void
rb_ractor_atfork(rb_vm_t *vm, rb_thread_t *th)
{
@@ -2042,6 +501,15 @@ rb_ractor_atfork(rb_vm_t *vm, rb_thread_t *th)
VM_ASSERT(vm->ractor.blocking_cnt == 0);
VM_ASSERT(vm->ractor.cnt == 1);
}
+
+void
+rb_ractor_terminate_atfork(rb_vm_t *vm, rb_ractor_t *r)
+{
+ rb_gc_ractor_cache_free(r->newobj_cache);
+ r->newobj_cache = NULL;
+ r->status_ = ractor_terminated;
+ ractor_sync_terminate_atfork(vm, r);
+}
#endif
void rb_thread_sched_init(struct rb_thread_sched *, bool atfork);
@@ -2057,15 +525,9 @@ rb_ractor_living_threads_init(rb_ractor_t *r)
static void
ractor_init(rb_ractor_t *r, VALUE name, VALUE loc)
{
- ractor_queue_setup(&r->sync.recv_queue);
- ractor_queue_setup(&r->sync.takers_queue);
- rb_native_mutex_initialize(&r->sync.lock);
- rb_native_cond_initialize(&r->barrier_wait_cond);
-
-#ifdef RUBY_THREAD_WIN32_H
- rb_native_cond_initialize(&r->sync.cond);
- rb_native_cond_initialize(&r->barrier_wait_cond);
-#endif
+ ractor_sync_init(r);
+ r->pub.targeted_hooks = st_init_numtable();
+ r->pub.hooks.type = hook_list_type_ractor_local;
// thread management
rb_thread_sched_init(&r->threads.sched, false);
@@ -2080,20 +542,24 @@ ractor_init(rb_ractor_t *r, VALUE name, VALUE loc)
rb_raise(rb_eArgError, "ASCII incompatible encoding (%s)",
rb_enc_name(enc));
}
- name = rb_str_new_frozen(name);
+ name = RB_OBJ_SET_SHAREABLE(rb_str_new_frozen(name));
}
- r->name = name;
+
+ if (!SPECIAL_CONST_P(loc)) RB_OBJ_SET_SHAREABLE(loc);
r->loc = loc;
+ r->name = name;
}
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);
+ VALUE rv = 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);
+
+ RB_GC_GUARD(rv);
}
static VALUE
@@ -2103,7 +569,6 @@ ractor_create(rb_execution_context_t *ec, VALUE self, VALUE loc, VALUE name, VAL
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);
@@ -2112,83 +577,59 @@ ractor_create(rb_execution_context_t *ec, VALUE self, VALUE loc, VALUE name, VAL
r->debug = cr->debug;
rb_yjit_before_ractor_spawn();
- rb_rjit_before_ractor_spawn();
+ rb_zjit_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 0
+static VALUE
+ractor_create_func(VALUE klass, VALUE loc, VALUE name, VALUE args, rb_block_call_func_t func)
{
- if (cr->sync.outgoing_port_closed) {
- return;
- }
-
- ASSERT_ractor_unlocking(cr);
-
- struct rb_ractor_queue *ts = &cr->sync.takers_queue;
-
- retry:
- if (ractor_try_yield(ec, cr, ts, v, Qfalse, exc, true)) {
- // OK.
- }
- else {
- bool retry = false;
- RACTOR_LOCK(cr);
- {
- if (!ractor_check_take_basket(cr, ts)) {
- VM_ASSERT(cr->sync.wait.status == wait_none);
- RUBY_DEBUG_LOG("leave a will");
- ractor_basket_fill_will(cr, &cr->sync.will_basket, v, exc);
- }
- else {
- RUBY_DEBUG_LOG("rare timing!");
- retry = true; // another ractor is waiting for the yield.
- }
- }
- RACTOR_UNLOCK(cr);
+ VALUE block = rb_proc_new(func, Qnil);
+ return ractor_create(rb_current_ec_noinline(), klass, loc, name, args, block);
+}
+#endif
- if (retry) goto retry;
- }
+static void
+ractor_atexit(rb_execution_context_t *ec, rb_ractor_t *cr, VALUE result, bool exc)
+{
+ ractor_notify_exit(ec, cr, result, exc);
}
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);
+ ractor_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);
+ ractor_atexit(ec, cr, ec->errinfo, true);
}
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();
- {
+ RB_VM_LOCKING() {
VM_ASSERT(cr->threads.main != NULL);
cr->threads.main = NULL;
}
- RB_VM_LOCK_LEAVE();
}
void
rb_ractor_receive_parameters(rb_execution_context_t *ec, rb_ractor_t *r, int len, VALUE *ptr)
{
for (int i=0; i<len; i++) {
- ptr[i] = ractor_receive(ec, r);
+ ptr[i] = ractor_receive(ec, ractor_default_port(r));
}
}
@@ -2197,7 +638,7 @@ rb_ractor_send_parameters(rb_execution_context_t *ec, rb_ractor_t *r, VALUE args
{
int len = RARRAY_LENINT(args);
for (int i=0; i<len; i++) {
- ractor_send(ec, r, RARRAY_AREF(args, i), false);
+ ractor_send(ec, ractor_default_port(r), RARRAY_AREF(args, i), false);
}
}
@@ -2209,14 +650,6 @@ rb_ractor_main_p_(void)
return rb_ec_ractor_ptr(ec) == rb_ec_vm_ptr(ec)->ractor.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;
-}
-
int
rb_ractor_living_thread_num(const rb_ractor_t *r)
{
@@ -2313,13 +746,10 @@ ractor_check_blocking(rb_ractor_t *cr, unsigned int remained_thread_cnt, const c
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_LOCKING() {
rb_vm_ractor_blocking_cnt_inc(vm, cr, file, line);
}
- RB_VM_UNLOCK();
}
}
@@ -2371,11 +801,9 @@ rb_ractor_blocking_threads_dec(rb_ractor_t *cr, const char *file, int line)
if (cr->threads.cnt == cr->threads.blocking_cnt) {
rb_vm_t *vm = GET_VM();
- RB_VM_LOCK_ENTER();
- {
+ RB_VM_LOCKING() {
rb_vm_ractor_blocking_cnt_dec(vm, cr, __FILE__, __LINE__);
}
- RB_VM_LOCK_LEAVE();
}
cr->threads.blocking_cnt--;
@@ -2449,13 +877,11 @@ rb_ractor_terminate_all(void)
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_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();
@@ -2468,6 +894,17 @@ rb_ractor_terminate_all(void)
rb_vm_ractor_blocking_cnt_inc(vm, cr, __FILE__, __LINE__);
rb_del_running_thread(rb_ec_thread_ptr(cr->threads.running_ec));
rb_vm_cond_timedwait(vm, &vm->ractor.sync.terminate_cond, 1000 /* ms */);
+#ifdef RUBY_THREAD_PTHREAD_H
+ while (vm->ractor.sched.barrier_waiting) {
+ // A barrier is waiting. Threads relinquish the VM lock before joining the barrier and
+ // since we just acquired the VM lock back, we're blocking other threads from joining it.
+ // We loop until the barrier is over. We can't join this barrier because our thread isn't added to
+ // running_threads until the call below to `rb_add_running_thread`.
+ RB_VM_UNLOCK();
+ unsigned int lev;
+ RB_VM_LOCK_ENTER_LEV_NB(&lev);
+ }
+#endif
rb_add_running_thread(rb_ec_thread_ptr(cr->threads.running_ec));
rb_vm_ractor_blocking_cnt_dec(vm, cr, __FILE__, __LINE__);
@@ -2505,77 +942,47 @@ ractor_moved_missing(int argc, VALUE *argv, VALUE self)
rb_raise(rb_eRactorMovedError, "can not send any methods to a moved object");
}
-#ifndef USE_RACTOR_SELECTOR
-#define USE_RACTOR_SELECTOR 0
-#endif
-
-RUBY_SYMBOL_EXPORT_BEGIN
-void rb_init_ractor_selector(void);
-RUBY_SYMBOL_EXPORT_END
-
-void
-rb_init_ractor_selector(void)
-{
- rb_cRactorSelector = rb_define_class_under(rb_cRactor, "Selector", rb_cObject);
- rb_undef_alloc_func(rb_cRactorSelector);
-
- rb_define_singleton_method(rb_cRactorSelector, "new", ractor_selector_new , -1);
- rb_define_method(rb_cRactorSelector, "add", ractor_selector_add, 1);
- rb_define_method(rb_cRactorSelector, "remove", ractor_selector_remove, 1);
- rb_define_method(rb_cRactorSelector, "clear", ractor_selector_clear, 0);
- rb_define_method(rb_cRactorSelector, "empty?", ractor_selector_empty_p, 0);
- rb_define_method(rb_cRactorSelector, "wait", ractor_selector_wait, -1);
- rb_define_method(rb_cRactorSelector, "_wait", ractor_selector__wait, 4);
-}
+/*
+ * Document-class: Ractor::Error
+ *
+ * The parent class of Ractor-related error classes.
+ */
/*
* 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
+ * Ports may be closed explicitly with Ractor::Port#close
* 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"
+ * port = Ractor::Port.new
+ * port.close
+ * port << "test" # Ractor::ClosedError
+ * port.receive # Ractor::ClosedError
*
- * This will print:
+ * ClosedError is a descendant of StopIteration, so the closing of a port will break
+ * out of loops without propagating the error.
+ */
+
+/*
+ * Document-class: Ractor::IsolationError
*
- * Received: 0
- * Received: 1
- * Received: 2
- * loop exited
- * Continue successfully
+ * Raised on attempt to make a Ractor-unshareable object
+ * Ractor-shareable.
*/
/*
* Document-class: Ractor::RemoteError
*
- * Raised on attempt to Ractor#take if there was an uncaught exception in the Ractor.
+ * Raised on Ractor#join or Ractor#value 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
+ * r.value
* rescue => e
* p e # => #<Ractor::RemoteError: thrown by remote Ractor.>
* p e.ractor == r # => true
@@ -2587,7 +994,7 @@ rb_init_ractor_selector(void)
/*
* Document-class: Ractor::MovedError
*
- * Raised on an attempt to access an object which was moved in Ractor#send or Ractor.yield.
+ * Raised on an attempt to access an object which was moved in Ractor#send or Ractor::Port#send.
*
* r = Ractor.new { sleep }
*
@@ -2602,7 +1009,7 @@ rb_init_ractor_selector(void)
* 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.
+ * or Ractor::Port#send. Any attempt to access the object results in Ractor::MovedError.
*
* r = Ractor.new { receive }
*
@@ -2614,6 +1021,12 @@ rb_init_ractor_selector(void)
* # Ractor::MovedError (can not send any methods to a moved object)
*/
+/*
+ * Document-class: Ractor::UnsafeError
+ *
+ * Raised when Ractor-unsafe C-methods is invoked by a non-main Ractor.
+ */
+
// Main docs are in ractor.rb, but without this clause there are weird artifacts
// in their rendering.
/*
@@ -2648,9 +1061,7 @@ Init_Ractor(void)
rb_define_method(rb_cRactorMovedObject, "instance_eval", ractor_moved_missing, -1);
rb_define_method(rb_cRactorMovedObject, "instance_exec", ractor_moved_missing, -1);
-#if USE_RACTOR_SELECTOR
- rb_init_ractor_selector();
-#endif
+ Init_RactorPort();
}
void
@@ -2744,6 +1155,50 @@ rb_ractor_hooks(rb_ractor_t *cr)
return &cr->pub.hooks;
}
+st_table *
+rb_ractor_targeted_hooks(rb_ractor_t *cr)
+{
+ return cr->pub.targeted_hooks;
+}
+
+static void
+rb_obj_set_shareable_no_assert(VALUE obj)
+{
+ FL_SET_RAW(obj, FL_SHAREABLE);
+
+ if (rb_obj_gen_fields_p(obj)) {
+ VALUE fields = rb_obj_fields_no_ractor_check(obj);
+ if (imemo_type_p(fields, imemo_fields)) {
+ // no recursive mark
+ FL_SET_RAW(fields, FL_SHAREABLE);
+ }
+ }
+}
+
+#ifndef STRICT_VERIFY_SHAREABLE
+#define STRICT_VERIFY_SHAREABLE 0
+#endif
+
+bool
+rb_ractor_verify_shareable(VALUE obj)
+{
+#if STRICT_VERIFY_SHAREABLE
+ rb_gc_verify_shareable(obj);
+#endif
+ return true;
+}
+
+VALUE
+rb_obj_set_shareable(VALUE obj)
+{
+ RUBY_ASSERT(!RB_SPECIAL_CONST_P(obj));
+
+ rb_obj_set_shareable_no_assert(obj);
+ RUBY_ASSERT(rb_ractor_verify_shareable(obj));
+
+ return obj;
+}
+
/// traverse function
// 2: stop search
@@ -2844,6 +1299,7 @@ obj_traverse_i(VALUE obj, struct obj_traverse_data *data)
// already traversed
return 0;
}
+ RB_OBJ_WRITTEN(data->rec_hash, Qundef, obj);
struct obj_traverse_callback_data d = {
.stop = false,
@@ -2860,7 +1316,6 @@ obj_traverse_i(VALUE obj, struct obj_traverse_data *data)
case T_REGEXP:
case T_FILE:
case T_SYMBOL:
- case T_MATCH:
break;
case T_OBJECT:
@@ -2869,6 +1324,8 @@ obj_traverse_i(VALUE obj, struct obj_traverse_data *data)
case T_ARRAY:
{
+ rb_ary_cancel_sharing(obj);
+
for (int i = 0; i < RARRAY_LENINT(obj); i++) {
VALUE e = rb_ary_entry(obj, i);
if (obj_traverse_i(e, data)) return 1;
@@ -2891,7 +1348,7 @@ obj_traverse_i(VALUE obj, struct obj_traverse_data *data)
case T_STRUCT:
{
- long len = RSTRUCT_LEN(obj);
+ long len = RSTRUCT_LEN_RAW(obj);
const VALUE *ptr = RSTRUCT_CONST_PTR(obj);
for (long i=0; i<len; i++) {
@@ -2900,6 +1357,10 @@ obj_traverse_i(VALUE obj, struct obj_traverse_data *data)
}
break;
+ case T_MATCH:
+ if (obj_traverse_i(RMATCH(obj)->str, data)) return 1;
+ break;
+
case T_RATIONAL:
if (obj_traverse_i(RRATIONAL(obj)->num, data)) return 1;
if (obj_traverse_i(RRATIONAL(obj)->den, data)) return 1;
@@ -2916,11 +1377,9 @@ obj_traverse_i(VALUE obj, struct obj_traverse_data *data)
.stop = false,
.data = data,
};
- RB_VM_LOCK_ENTER_NO_BARRIER();
- {
+ RB_VM_LOCKING_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;
@@ -2982,7 +1441,7 @@ rb_obj_traverse(VALUE obj,
}
static int
-frozen_shareable_p(VALUE obj, bool *made_shareable)
+allow_frozen_shareable_p(VALUE obj)
{
if (!RB_TYPE_P(obj, T_DATA)) {
return true;
@@ -2992,55 +1451,95 @@ frozen_shareable_p(VALUE obj, bool *made_shareable)
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_freeze(VALUE obj, enum obj_traverse_iterator_result result)
+{
+ 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 result;
+}
+
+static int obj_refer_only_shareables_p(VALUE obj);
+
+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;
}
- if (!frozen_shareable_p(obj, &made_shareable)) {
- if (made_shareable) {
- return traverse_skip;
+ else if (!allow_frozen_shareable_p(obj)) {
+ VM_ASSERT(RB_TYPE_P(obj, T_DATA));
+ const rb_data_type_t *type = RTYPEDDATA_TYPE(obj);
+
+ if (type->flags & RUBY_TYPED_FROZEN_SHAREABLE_NO_REC) {
+ if (obj_refer_only_shareables_p(obj)) {
+ make_shareable_check_shareable_freeze(obj, traverse_skip);
+ RB_OBJ_SET_SHAREABLE(obj);
+ return traverse_skip;
+ }
+ else {
+ rb_raise(rb_eRactorError,
+ "can not make shareable object for %+"PRIsVALUE" because it refers unshareable objects", obj);
+ }
+ }
+ else if (rb_obj_is_proc(obj)) {
+ rb_proc_ractor_make_shareable(obj, Qundef);
+ return traverse_cont;
}
else {
- rb_raise(rb_eRactorError, "can not make shareable object for %"PRIsVALUE, obj);
+ 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;
+ switch (TYPE(obj)) {
+ case T_IMEMO:
+ return traverse_skip;
+ case T_OBJECT:
+ {
+ // If a T_OBJECT is shared and has no free capacity, we can't safely store the object_id inline,
+ // as it would require to move the object content into an external buffer.
+ // This is only a problem for T_OBJECT, given other types have external fields and can do RCU.
+ // To avoid this issue, we proactively create the object_id.
+ shape_id_t shape_id = RBASIC_SHAPE_ID(obj);
+ attr_index_t capacity = RSHAPE_CAPACITY(shape_id);
+ attr_index_t free_capacity = capacity - RSHAPE_LEN(shape_id);
+ if (!rb_shape_has_object_id(shape_id) && capacity && !free_capacity) {
+ rb_obj_id(obj);
+ }
}
+ break;
+ default:
+ break;
}
- return traverse_cont;
+ return make_shareable_check_shareable_freeze(obj, traverse_cont);
}
static enum obj_traverse_iterator_result
mark_shareable(VALUE obj)
{
- FL_SET_RAW(obj, RUBY_FL_SHAREABLE);
+ if (RB_TYPE_P(obj, T_STRING)) {
+ rb_str_make_independent(obj);
+ }
+
+ rb_obj_set_shareable_no_assert(obj);
return traverse_cont;
}
@@ -3093,7 +1592,7 @@ shareable_p_enter(VALUE obj)
return traverse_skip;
}
else if (RB_OBJ_FROZEN_RAW(obj) &&
- frozen_shareable_p(obj, NULL)) {
+ allow_frozen_shareable_p(obj)) {
return traverse_cont;
}
@@ -3114,6 +1613,12 @@ rb_ractor_shareable_p_continue(VALUE obj)
}
#if RACTOR_CHECK_MODE > 0
+void
+rb_ractor_setup_belonging(VALUE obj)
+{
+ rb_ractor_setup_belonging_to(obj, rb_ractor_current_id());
+}
+
static enum obj_traverse_iterator_result
reset_belonging_enter(VALUE obj)
{
@@ -3252,11 +1757,9 @@ static int
obj_refer_only_shareables_p(VALUE obj)
{
int cnt = 0;
- RB_VM_LOCK_ENTER_NO_BARRIER();
- {
+ RB_VM_LOCKING_NO_BARRIER() {
rb_objspace_reachable_objects_from(obj, obj_refer_only_shareables_p_i, &cnt);
}
- RB_VM_LOCK_LEAVE_NO_BARRIER();
return cnt == 0;
}
@@ -3284,30 +1787,31 @@ obj_traverse_replace_i(VALUE obj, struct obj_traverse_replace_data *data)
}
else {
st_insert(obj_traverse_replace_rec(data), (st_data_t)obj, replacement);
+ RB_OBJ_WRITTEN(data->rec_hash, Qundef, obj);
+ RB_OBJ_WRITTEN(data->rec_hash, Qundef, replacement);
}
if (!data->move) {
obj = replacement;
}
-#define CHECK_AND_REPLACE(v) do { \
+#define CHECK_AND_REPLACE(parent_obj, 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); } \
+ else if (data->replacement != _val) { RB_OBJ_WRITE(parent_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);
+ if (UNLIKELY(rb_obj_gen_fields_p(obj))) {
+ VALUE fields_obj = rb_obj_fields_no_ractor_check(obj);
- if (UNLIKELY(rb_shape_obj_too_complex(obj))) {
+ if (UNLIKELY(rb_shape_obj_too_complex_p(obj))) {
struct obj_traverse_replace_callback_data d = {
.stop = false,
.data = data,
- .src = obj,
+ .src = fields_obj,
};
rb_st_foreach_with_replace(
- ivtbl->as.complex.table,
+ rb_imemo_fields_complex_tbl(fields_obj),
obj_iv_hash_traverse_replace_foreach_i,
obj_iv_hash_traverse_replace_i,
(st_data_t)&d
@@ -3315,10 +1819,10 @@ obj_traverse_replace_i(VALUE obj, struct obj_traverse_replace_data *data)
if (d.stop) return 1;
}
else {
- for (uint32_t i = 0; i < ivtbl->as.shape.numiv; i++) {
- if (!UNDEF_P(ivtbl->as.shape.ivptr[i])) {
- CHECK_AND_REPLACE(ivtbl->as.shape.ivptr[i]);
- }
+ uint32_t fields_count = RSHAPE_LEN(RBASIC_SHAPE_ID(obj));
+ VALUE *fields = rb_imemo_fields_ptr(fields_obj);
+ for (uint32_t i = 0; i < fields_count; i++) {
+ CHECK_AND_REPLACE(fields_obj, fields[i]);
}
}
}
@@ -3330,7 +1834,6 @@ obj_traverse_replace_i(VALUE obj, struct obj_traverse_replace_data *data)
case T_REGEXP:
case T_FILE:
case T_SYMBOL:
- case T_MATCH:
break;
case T_STRING:
rb_str_make_independent(obj);
@@ -3338,14 +1841,14 @@ obj_traverse_replace_i(VALUE obj, struct obj_traverse_replace_data *data)
case T_OBJECT:
{
- if (rb_shape_obj_too_complex(obj)) {
+ if (rb_shape_obj_too_complex_p(obj)) {
struct obj_traverse_replace_callback_data d = {
.stop = false,
.data = data,
.src = obj,
};
rb_st_foreach_with_replace(
- ROBJECT_IV_HASH(obj),
+ ROBJECT_FIELDS_HASH(obj),
obj_iv_hash_traverse_replace_foreach_i,
obj_iv_hash_traverse_replace_i,
(st_data_t)&d
@@ -3353,11 +1856,11 @@ obj_traverse_replace_i(VALUE obj, struct obj_traverse_replace_data *data)
if (d.stop) return 1;
}
else {
- uint32_t len = ROBJECT_IV_COUNT(obj);
- VALUE *ptr = ROBJECT_IVPTR(obj);
+ uint32_t len = ROBJECT_FIELDS_COUNT_NOT_COMPLEX(obj);
+ VALUE *ptr = ROBJECT_FIELDS(obj);
for (uint32_t i = 0; i < len; i++) {
- CHECK_AND_REPLACE(ptr[i]);
+ CHECK_AND_REPLACE(obj, ptr[i]);
}
}
}
@@ -3406,22 +1909,26 @@ obj_traverse_replace_i(VALUE obj, struct obj_traverse_replace_data *data)
case T_STRUCT:
{
- long len = RSTRUCT_LEN(obj);
+ long len = RSTRUCT_LEN_RAW(obj);
const VALUE *ptr = RSTRUCT_CONST_PTR(obj);
for (long i=0; i<len; i++) {
- CHECK_AND_REPLACE(ptr[i]);
+ CHECK_AND_REPLACE(obj, ptr[i]);
}
}
break;
+ case T_MATCH:
+ CHECK_AND_REPLACE(obj, RMATCH(obj)->str);
+ break;
+
case T_RATIONAL:
- CHECK_AND_REPLACE(RRATIONAL(obj)->num);
- CHECK_AND_REPLACE(RRATIONAL(obj)->den);
+ CHECK_AND_REPLACE(obj, RRATIONAL(obj)->num);
+ CHECK_AND_REPLACE(obj, RRATIONAL(obj)->den);
break;
case T_COMPLEX:
- CHECK_AND_REPLACE(RCOMPLEX(obj)->real);
- CHECK_AND_REPLACE(RCOMPLEX(obj)->imag);
+ CHECK_AND_REPLACE(obj, RCOMPLEX(obj)->real);
+ CHECK_AND_REPLACE(obj, RCOMPLEX(obj)->imag);
break;
case T_DATA:
@@ -3480,37 +1987,19 @@ rb_obj_traverse_replace(VALUE obj,
}
}
-struct RVALUE {
- VALUE flags;
- VALUE klass;
- VALUE v1;
- VALUE v2;
- VALUE v3;
+static const bool wb_protected_types[RUBY_T_MASK] = {
+ [T_OBJECT] = RGENGC_WB_PROTECTED_OBJECT,
+ [T_HASH] = RGENGC_WB_PROTECTED_HASH,
+ [T_ARRAY] = RGENGC_WB_PROTECTED_ARRAY,
+ [T_STRING] = RGENGC_WB_PROTECTED_STRING,
+ [T_STRUCT] = RGENGC_WB_PROTECTED_STRUCT,
+ [T_COMPLEX] = RGENGC_WB_PROTECTED_COMPLEX,
+ [T_REGEXP] = RGENGC_WB_PROTECTED_REGEXP,
+ [T_MATCH] = RGENGC_WB_PROTECTED_MATCH,
+ [T_FLOAT] = RGENGC_WB_PROTECTED_FLOAT,
+ [T_RATIONAL] = RGENGC_WB_PROTECTED_RATIONAL,
};
-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;
-
- if (BUILTIN_TYPE(obj) == T_OBJECT) ROBJECT_SET_SHAPE_ID(obj, ROOT_SHAPE_ID);
-
- // TODO: record moved location
-}
-
static enum obj_traverse_iterator_result
move_enter(VALUE obj, struct obj_traverse_replace_data *data)
{
@@ -3519,35 +2008,45 @@ move_enter(VALUE obj, struct obj_traverse_replace_data *data)
return traverse_skip;
}
else {
- VALUE moved = rb_obj_alloc(RBASIC_CLASS(obj));
- rb_shape_set_shape(moved, rb_shape_get_shape(obj));
- data->replacement = moved;
+ VALUE type = RB_BUILTIN_TYPE(obj);
+ size_t slot_size = rb_gc_obj_slot_size(obj);
+ type |= wb_protected_types[type] ? FL_WB_PROTECTED : 0;
+ NEWOBJ_OF(moved, struct RBasic, 0, type, slot_size, 0);
+ MEMZERO(&moved[1], char, slot_size - sizeof(*moved));
+ data->replacement = (VALUE)moved;
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;
+ // Copy flags
+ VALUE ignored_flags = RUBY_FL_PROMOTED;
+ RBASIC(data->replacement)->flags = (RBASIC(obj)->flags & ~ignored_flags) | (RBASIC(data->replacement)->flags & ignored_flags);
+ // Copy contents without the flags
+ memcpy(
+ (char *)data->replacement + sizeof(VALUE),
+ (char *)obj + sizeof(VALUE),
+ rb_gc_obj_slot_size(obj) - sizeof(VALUE)
+ );
- dst->flags = (dst->flags & ~fl_users) | (src->flags & fl_users);
+ // We've copied obj's references to the replacement
+ rb_gc_writebarrier_remember(data->replacement);
- 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);
+ void rb_replace_generic_ivar(VALUE clone, VALUE obj); // variable.c
+ if (UNLIKELY(rb_obj_gen_fields_p(obj))) {
+ rb_replace_generic_ivar(data->replacement, obj);
}
- // TODO: generic_ivar
+ rb_gc_obj_id_moved(data->replacement);
+
+ VALUE flags = T_OBJECT | FL_FREEZE | (RBASIC(obj)->flags & FL_PROMOTED);
- ractor_moved_bang(obj);
+ // Avoid mutations using bind_call, etc.
+ MEMZERO((char *)obj, char, sizeof(struct RBasic));
+ RBASIC(obj)->flags = flags;
+ RBASIC_SET_CLASS_RAW(obj, rb_cRactorMovedObject);
return traverse_cont;
}
@@ -3616,7 +2115,7 @@ ractor_local_storage_mark_i(st_data_t key, st_data_t val, st_data_t dmy)
}
static enum rb_id_table_iterator_result
-idkey_local_storage_mark_i(ID id, VALUE val, void *dmy)
+idkey_local_storage_mark_i(VALUE val, void *dmy)
{
rb_gc_mark(val);
return ID_TABLE_CONTINUE;
@@ -3639,8 +2138,10 @@ ractor_local_storage_mark(rb_ractor_t *r)
}
if (r->idkey_local_storage) {
- rb_id_table_foreach(r->idkey_local_storage, idkey_local_storage_mark_i, NULL);
+ rb_id_table_foreach_values(r->idkey_local_storage, idkey_local_storage_mark_i, NULL);
}
+
+ rb_gc_mark(r->local_storage_store_lock);
}
static int
@@ -3703,15 +2204,13 @@ rb_ractor_local_storage_value_newkey(void)
void
rb_ractor_local_storage_delkey(rb_ractor_local_key_t key)
{
- RB_VM_LOCK_ENTER();
- {
+ RB_VM_LOCKING() {
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
@@ -3846,4 +2345,277 @@ ractor_local_value_set(rb_execution_context_t *ec, VALUE self, VALUE sym, VALUE
return val;
}
+struct ractor_local_storage_store_data {
+ rb_execution_context_t *ec;
+ struct rb_id_table *tbl;
+ ID id;
+ VALUE sym;
+};
+
+static VALUE
+ractor_local_value_store_i(VALUE ptr)
+{
+ VALUE val;
+ struct ractor_local_storage_store_data *data = (struct ractor_local_storage_store_data *)ptr;
+
+ if (rb_id_table_lookup(data->tbl, data->id, &val)) {
+ // after synchronization, we found already registered entry
+ }
+ else {
+ val = rb_yield(Qnil);
+ ractor_local_value_set(data->ec, Qnil, data->sym, val);
+ }
+ return val;
+}
+
+static VALUE
+ractor_local_value_store_if_absent(rb_execution_context_t *ec, VALUE self, VALUE sym)
+{
+ rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
+ struct ractor_local_storage_store_data data = {
+ .ec = ec,
+ .sym = sym,
+ .id = SYM2ID(rb_to_symbol(sym)),
+ .tbl = cr->idkey_local_storage,
+ };
+ VALUE val;
+
+ if (data.tbl == NULL) {
+ data.tbl = cr->idkey_local_storage = rb_id_table_create(2);
+ }
+ else if (rb_id_table_lookup(data.tbl, data.id, &val)) {
+ // already set
+ return val;
+ }
+
+ if (!cr->local_storage_store_lock) {
+ cr->local_storage_store_lock = rb_mutex_new();
+ }
+
+ return rb_mutex_synchronize(cr->local_storage_store_lock, ractor_local_value_store_i, (VALUE)&data);
+}
+
+// shareable_proc
+
+static VALUE
+ractor_shareable_proc(rb_execution_context_t *ec, VALUE replace_self, bool is_lambda)
+{
+ if (!rb_ractor_shareable_p(replace_self)) {
+ rb_raise(rb_eRactorIsolationError, "self should be shareable: %" PRIsVALUE, replace_self);
+ }
+ else {
+ VALUE proc = is_lambda ? rb_block_lambda() : rb_block_proc();
+ return rb_proc_ractor_make_shareable(rb_proc_dup(proc), replace_self);
+ }
+}
+
+// Ractor#require
+
+struct cross_ractor_require {
+ VALUE port;
+ bool raised;
+
+ union {
+ struct {
+ VALUE feature;
+ } require;
+
+ struct {
+ VALUE module;
+ ID name;
+ } autoload;
+ } as;
+
+ bool silent;
+};
+
+RUBY_REFERENCES(cross_ractor_require_refs) = {
+ RUBY_REF_EDGE(struct cross_ractor_require, port),
+ RUBY_REF_EDGE(struct cross_ractor_require, as.require.feature),
+ RUBY_REF_END
+};
+
+static const rb_data_type_t cross_ractor_require_data_type = {
+ "ractor/cross_ractor_require",
+ {
+ RUBY_REFS_LIST_PTR(cross_ractor_require_refs),
+ RUBY_DEFAULT_FREE,
+ NULL, // memsize
+ NULL, // compact
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_DECL_MARKING | RUBY_TYPED_EMBEDDABLE
+};
+
+static VALUE
+require_body(VALUE crr_obj)
+{
+ struct cross_ractor_require *crr;
+ TypedData_Get_Struct(crr_obj, struct cross_ractor_require, &cross_ractor_require_data_type, crr);
+ VALUE feature = crr->as.require.feature;
+
+ ID require;
+ CONST_ID(require, "require");
+
+ if (crr->silent) {
+ int rb_require_internal_silent(VALUE fname);
+ return INT2NUM(rb_require_internal_silent(feature));
+ }
+ else {
+ return rb_funcallv(Qnil, require, 1, &feature);
+ }
+}
+
+static VALUE
+require_rescue(VALUE crr_obj, VALUE errinfo)
+{
+ struct cross_ractor_require *crr;
+ TypedData_Get_Struct(crr_obj, struct cross_ractor_require, &cross_ractor_require_data_type, crr);
+ crr->raised = true;
+ return errinfo;
+}
+
+static VALUE
+require_result_send_body(VALUE ary)
+{
+ VALUE port = RARRAY_AREF(ary, 0);
+ VALUE results = RARRAY_AREF(ary, 1);
+
+ rb_execution_context_t *ec = GET_EC();
+
+ ractor_port_send(ec, port, results, Qfalse);
+ return Qnil;
+}
+
+static VALUE
+require_result_send_resuce(VALUE port, VALUE errinfo)
+{
+ // TODO: need rescue?
+ ractor_port_send(GET_EC(), port, errinfo, Qfalse);
+ return Qnil;
+}
+
+static VALUE
+ractor_require_protect(VALUE crr_obj, VALUE (*func)(VALUE))
+{
+ struct cross_ractor_require *crr;
+ TypedData_Get_Struct(crr_obj, struct cross_ractor_require, &cross_ractor_require_data_type, crr);
+
+ const bool silent = crr->silent;
+
+ VALUE debug, errinfo;
+ if (silent) {
+ debug = ruby_debug;
+ errinfo = rb_errinfo();
+ }
+
+ // get normal result or raised exception (with crr->raised == true)
+ VALUE result = rb_rescue2(func, crr_obj, require_rescue, crr_obj, rb_eException, 0);
+
+ if (silent) {
+ ruby_debug = debug;
+ rb_set_errinfo(errinfo);
+ }
+
+ rb_rescue2(require_result_send_body,
+ // [port, [result, raised]]
+ rb_ary_new_from_args(2, crr->port, rb_ary_new_from_args(2, result, crr->raised ? Qtrue : Qfalse)),
+ require_result_send_resuce, rb_eException, crr->port);
+
+ RB_GC_GUARD(crr_obj);
+ return Qnil;
+}
+
+static VALUE
+ractor_require_func(void *crr_obj)
+{
+ return ractor_require_protect((VALUE)crr_obj, require_body);
+}
+
+VALUE
+rb_ractor_require(VALUE feature, bool silent)
+{
+ // We're about to block on the main ractor, so if we're holding the global lock we'll deadlock.
+ ASSERT_vm_unlocking();
+
+ struct cross_ractor_require *crr;
+ VALUE crr_obj = TypedData_Make_Struct(0, struct cross_ractor_require, &cross_ractor_require_data_type, crr);
+ RB_OBJ_SET_SHAREABLE(crr_obj); // TODO: internal data?
+
+ // Convert feature to proper file path and make it shareable as fstring
+ RB_OBJ_WRITE(crr_obj, &crr->as.require.feature, rb_fstring(FilePathValue(feature)));
+ RB_OBJ_WRITE(crr_obj, &crr->port, rb_ractor_make_shareable(ractor_port_new(GET_RACTOR())));
+ crr->raised = false;
+ crr->silent = silent;
+
+ rb_execution_context_t *ec = GET_EC();
+ rb_ractor_t *main_r = GET_VM()->ractor.main_ractor;
+ rb_ractor_interrupt_exec(main_r, ractor_require_func, (void *)crr_obj, rb_interrupt_exec_flag_value_data);
+
+ // wait for require done
+ VALUE results = ractor_port_receive(ec, crr->port);
+ ractor_port_close(ec, crr->port);
+
+ VALUE exc = rb_ary_pop(results);
+ VALUE result = rb_ary_pop(results);
+ RB_GC_GUARD(crr_obj);
+
+ if (RTEST(exc)) {
+ rb_exc_raise(result);
+ }
+ else {
+ return result;
+ }
+}
+
+static VALUE
+ractor_require(rb_execution_context_t *ec, VALUE self, VALUE feature)
+{
+ return rb_ractor_require(feature, false);
+}
+
+static VALUE
+autoload_load_body(VALUE crr_obj)
+{
+ struct cross_ractor_require *crr;
+ TypedData_Get_Struct(crr_obj, struct cross_ractor_require, &cross_ractor_require_data_type, crr);
+ return rb_autoload_load(crr->as.autoload.module, crr->as.autoload.name);
+}
+
+static VALUE
+ractor_autoload_load_func(void *crr_obj)
+{
+ return ractor_require_protect((VALUE)crr_obj, autoload_load_body);
+}
+
+VALUE
+rb_ractor_autoload_load(VALUE module, ID name)
+{
+ struct cross_ractor_require *crr;
+ VALUE crr_obj = TypedData_Make_Struct(0, struct cross_ractor_require, &cross_ractor_require_data_type, crr);
+ RB_OBJ_SET_SHAREABLE(crr_obj); // TODO: internal data?
+
+ RB_OBJ_WRITE(crr_obj, &crr->as.autoload.module, module);
+ RB_OBJ_WRITE(crr_obj, &crr->as.autoload.name, name);
+ RB_OBJ_WRITE(crr_obj, &crr->port, rb_ractor_make_shareable(ractor_port_new(GET_RACTOR())));
+
+ rb_execution_context_t *ec = GET_EC();
+ rb_ractor_t *main_r = GET_VM()->ractor.main_ractor;
+ rb_ractor_interrupt_exec(main_r, ractor_autoload_load_func, (void *)crr_obj, rb_interrupt_exec_flag_value_data);
+
+ // wait for require done
+ VALUE results = ractor_port_receive(ec, crr->port);
+ ractor_port_close(ec, crr->port);
+
+ VALUE exc = rb_ary_pop(results);
+ VALUE result = rb_ary_pop(results);
+ RB_GC_GUARD(crr_obj);
+
+ if (RTEST(exc)) {
+ rb_exc_raise(result);
+ }
+ else {
+ return result;
+ }
+}
+
#include "ractor.rbinc"
diff --git a/ractor.rb b/ractor.rb
index d18062ca07..ac04237fc6 100644
--- a/ractor.rb
+++ b/ractor.rb
@@ -1,17 +1,15 @@
-# \Ractor is an Actor-model abstraction for Ruby that provides thread-safe parallel execution.
-#
-# Ractor.new makes a new \Ractor, which can run in parallel.
+# Ractor.new creates a new \Ractor, which can run in parallel with other ractors.
#
# # The simplest ractor
# r = Ractor.new {puts "I am in Ractor!"}
-# r.take # wait for it to finish
+# r.join # wait for it to finish
# # Here, "I am in Ractor!" is printed
#
# Ractors do not share all objects with each other. There are two main benefits to this: across ractors, thread-safety
# concerns such as data-races and race-conditions are not possible. The other benefit is parallelism.
#
# To achieve this, object sharing is limited across ractors.
-# For example, unlike in threads, ractors can't access all the objects available in other ractors. Even objects normally
+# Unlike in threads, ractors can't access all the objects available in other ractors. For example, objects normally
# available through variables in the outer scope are prohibited from being used across ractors.
#
# a = 1
@@ -23,77 +21,34 @@
# a = 1
# r = Ractor.new(a) { |a1| puts "I am in Ractor! a=#{a1}"}
#
-# On CRuby (the default implementation), Global Virtual Machine Lock (GVL) is held per ractor, so
-# ractors can perform in parallel without locking each other. This is unlike the situation with threads
-# on CRuby.
+# On CRuby (the default implementation), the Global Virtual Machine Lock (GVL) is held per ractor, so
+# ractors can run in parallel. This is unlike the situation with threads on CRuby.
#
# Instead of accessing shared state, objects should be passed to and from ractors by
# sending and receiving them as messages.
#
# a = 1
# r = Ractor.new do
-# a_in_ractor = receive # receive blocks until somebody passes a message
+# a_in_ractor = receive # receive blocks the Thread until our default port gets sent a message
# puts "I am in Ractor! a=#{a_in_ractor}"
# end
# r.send(a) # pass it
-# r.take
+# r.join
# # Here, "I am in Ractor! a=1" is 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, any arguments passed to Ractor.new are passed to the block and available there
-# as if received by Ractor.receive, and the last block value is sent outside of the
-# ractor as if sent by Ractor.yield.
-#
-# A little demonstration of a classic ping-pong:
-#
-# server = Ractor.new(name: "server") 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 to the client, and available as srv
-# puts "Client starts: #{self.inspect}"
-# received = srv.take # The client takes a message 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 to the server
-# end
-#
-# [client, server].each(&:take) # Wait until they both finish
-#
-# This will output something like:
-#
-# Server starts: #<Ractor:#2 server test.rb:1 running>
-# Server sends: ping
-# Client starts: #<Ractor:#3 test.rb:8 running>
-# Client received from #<Ractor:#2 server test.rb:1 blocking>: ping
-# Client sends to #<Ractor:#2 server test.rb:1 blocking>: pong
-# Server received: pong
-#
-# Ractors receive their messages via the <em>incoming port</em>, and send them
-# to the <em>outgoing port</em>. Either one can be disabled with Ractor#close_incoming and
-# Ractor#close_outgoing, respectively. When a ractor terminates, its ports are closed
-# automatically.
+# as if received by Ractor.receive, and the last block value can be received with Ractor#value.
#
# == Shareable and unshareable objects
#
-# When an object is sent to and from a ractor, it's important to understand whether the
+# When an object is sent to a ractor, it's important to understand whether the
# object is shareable or unshareable. Most Ruby objects are unshareable objects. Even
# frozen objects can be unshareable if they contain (through their instance variables) unfrozen
# objects.
#
-# Shareable objects are those which can be used by several threads without compromising
+# Shareable objects are those which can be used by several ractors at once without compromising
# thread-safety, for example numbers, +true+ and +false+. Ractor.shareable? allows you to check this,
-# and Ractor.make_shareable tries to make the object shareable if it's not already, and gives an error
+# and Ractor.make_shareable tries to make the object shareable if it's not already and gives an error
# if it can't do it.
#
# Ractor.shareable?(1) #=> true -- numbers and other immutable basic values are shareable
@@ -109,24 +64,24 @@
# ary[0].frozen? #=> true
# ary[1].frozen? #=> true
#
-# When a shareable object is sent (via #send or Ractor.yield), no additional processing occurs
-# on it. 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 copies the object fully by
+# When a shareable object is sent via #send, no additional processing occurs
+# on it and it becomes usable by both ractors. When an unshareable object is sent, it can be
+# either _copied_ or _moved_. Copying is the default, and it copies the object fully by
# deep cloning (Object#clone) the non-shareable parts of its structure.
#
-# data = ['foo', 'bar'.freeze]
+# data = ['foo'.dup, '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
+# r.join
# puts "Outside : #{data.object_id}, #{data[0].object_id}, #{data[1].object_id}"
#
# This will output something like:
#
-# In ractor: 340, 360, 320
-# Outside : 380, 400, 320
+# In ractor: 8, 16, 24
+# Outside : 32, 40, 24
#
# Note that the object ids of the array and the non-frozen string inside the array have changed in
# the ractor because they are different objects. The second array's element, which is a
@@ -142,7 +97,7 @@
# puts "In ractor: #{data_in_ractor.object_id}, #{data_in_ractor[0].object_id}"
# end
# r.send(data, move: true)
-# r.take
+# r.join
# puts "Outside: moved? #{Ractor::MovedObject === data}"
# puts "Outside: #{data.inspect}"
#
@@ -152,12 +107,12 @@
# 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 <tt>__id__</tt>) is inaccessible
+# Notice that even +inspect+ and more basic methods like <tt>__id__</tt> are inaccessible
# on a moved object.
#
-# Class and Module objects are shareable so the class/module definitions are shared between ractors.
-# \Ractor objects are also shareable. All operations on shareable 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.
+# +Class+ and +Module+ objects are shareable and their class/module definitions are shared between ractors.
+# \Ractor objects are also shareable. All operations on shareable objects are thread-safe across ractors.
+# Defining mutable, shareable objects in Ruby is not possible, but C extensions can introduce them.
#
# It is prohibited to access (get) instance variables of shareable objects in other ractors if the values of the
# variables aren't shareable. This can occur because modules/classes are shareable, but they can have
@@ -177,7 +132,7 @@
# puts "I can't see #{cls.tricky}"
# cls.tricky = true # doesn't get here, but this would also raise an error
# end
-# r.take
+# r.join
# # I see C
# # can not access instance variables of classes/modules from non-main Ractors (RuntimeError)
#
@@ -191,7 +146,7 @@
# puts "GOOD=#{GOOD}"
# puts "BAD=#{BAD}"
# end
-# r.take
+# r.join
# # GOOD=good
# # can not access non-shareable objects in constant Object::BAD by non-main Ractor. (NameError)
#
@@ -201,7 +156,7 @@
# puts "I see #{C}"
# puts "I can't see #{C.tricky}"
# end
-# r.take
+# r.join
# # I see C
# # can not access instance variables of classes/modules from non-main Ractors (RuntimeError)
#
@@ -217,20 +172,21 @@
# a = 1
# Thread.new {puts "Thread in ractor: a=#{a}"}.join
# end
-# r.take
+# r.join
# # Here "Thread in ractor: a=1" will be printed
#
# == Note on code examples
#
-# In the examples below, sometimes we use the following method to wait for ractors that
-# are not currently blocked to finish (or to make progress).
+# In the examples below, sometimes we use the following method to wait for ractors
+# to make progress or finish.
#
# def wait
# sleep(0.1)
# end
#
-# It is **only for demonstration purposes** and shouldn't be used in a real code.
-# Most of the time, #take is used to wait for ractors to finish.
+# This is **only for demonstration purposes** and shouldn't be used in a real code.
+# Most of the time, #join is used to wait for ractors to finish and Ractor.receive is used
+# to wait for messages.
#
# == Reference
#
@@ -241,13 +197,13 @@ class Ractor
# call-seq:
# Ractor.new(*args, name: nil) {|*args| block } -> ractor
#
- # Create a new \Ractor with args and a block.
+ # Creates a new \Ractor with args and a block.
#
- # The given block (Proc) will be isolated (can't access any outer variables). +self+
+ # The given block (Proc) is isolated (can't access any outer variables). +self+
# inside the block will refer to the current \Ractor.
#
# r = Ractor.new { puts "Hi, I am #{self.inspect}" }
- # r.take
+ # r.join
# # Prints "Hi, I am #<Ractor:#2 test.rb:1 running>"
#
# Any +args+ passed are propagated to the block arguments by the same rules as
@@ -259,14 +215,14 @@ class Ractor
# r = Ractor.new(arg) {|received_arg|
# puts "Received: #{received_arg} (##{received_arg.object_id})"
# }
- # r.take
+ # r.join
# # 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') {}; r.take
+ # r = Ractor.new(name: 'my ractor') {}; r.join
# p r
# #=> #<Ractor:#3 my ractor test.rb:1 terminated>
#
@@ -274,8 +230,8 @@ class Ractor
b = block # TODO: builtin bug
raise ArgumentError, "must be called with a block" unless block
if __builtin_cexpr!("RBOOL(ruby_single_main_ractor)")
- warn("Ractor is experimental, and the behavior may change in future versions of Ruby! " \
- "Also there are many implementation issues.", uplevel: 0, category: :experimental)
+ Kernel.warn("Ractor API is experimental and may change in future versions of Ruby.",
+ uplevel: 0, category: :experimental)
end
loc = caller_locations(1, 1).first
loc = "#{loc.path}:#{loc.lineno}"
@@ -291,13 +247,13 @@ class Ractor
}
end
- # Returns the number of Ractors currently running or blocking (waiting).
+ # Returns the number of ractors currently running or blocking (waiting).
#
# Ractor.count #=> 1
- # r = Ractor.new(name: 'example') { Ractor.yield(1) }
+ # r = Ractor.new(name: 'example') { Ractor.receive }
# Ractor.count #=> 2 (main + example ractor)
- # r.take # wait for Ractor.yield(1)
- # r.take # wait until r will finish
+ # r << 42 # r's Ractor.receive will resume
+ # r.join # wait for r's termination
# Ractor.count #=> 1
def self.count
__builtin_cexpr! %q{
@@ -307,130 +263,91 @@ class Ractor
#
# call-seq:
- # Ractor.select(*ractors, [yield_value:, move: false]) -> [ractor or symbol, obj]
- #
- # Wait for any ractor to have something in its outgoing port, read from this ractor, and
- # then return 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 #<Ractor:#2 test.rb:1 running>
- # # But could just as well print "from r2" here, either prints could be first.
- #
- # If one of the given ractors is the current ractor, and it is selected, +r+ will contain
- # the +: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'
+ # Ractor.select(*ractors_or_ports) -> [ractor or port, obj]
+ #
+ # Blocks the current Thread until one of the given ports has received a message. Returns an
+ # array of two elements where the first element is the Port and the second is the received object.
+ # This method can also accept Ractor objects themselves, and in that case will wait until one
+ # has terminated and return a two-element array where the first element is the ractor and the
+ # second is its termination value.
+ #
+ # p1, p2 = Ractor::Port.new, Ractor::Port.new
+ # ps = [p1, p2]
+ # rs = 2.times.map do |i|
+ # Ractor.new(ps.shift, i) do |p, i|
+ # sleep rand(0.99)
+ # p.send("r#{i}")
+ # sleep rand(0.99)
+ # "r#{i} done"
+ # end
# end
#
- # r, obj = Ractor.select(r1, r2, Ractor.current)
- # puts "received #{obj.inspect} from #{r.inspect}"
- # # Could print: 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 <tt>[:yield, nil]</tt> is returned:
- #
- # r1 = Ractor.new(Ractor.current) do |main|
- # puts "Received from main: #{main.take}"
+ # waiting_on = [p1, p2, *rs]
+ # until waiting_on.empty?
+ # received_on, obj = Ractor.select(*waiting_on)
+ # waiting_on.delete(received_on)
+ # puts obj
# end
#
- # puts "Trying to select"
- # r, obj = Ractor.select(r1, Ractor.current, yield_value: 123)
- # wait
- # puts "Received #{obj.inspect} from #{r.inspect}"
+ # # r0
+ # # r1
+ # # r1 done
+ # # r0 done
#
- # This will print:
+ # The following example is almost equivalent to <code>ractors.map(&:value)</code> except the thread
+ # is unblocked when any of the ractors has terminated as opposed to waiting for their termination in
+ # the array element order.
#
- # Trying to select
- # Received from main: 123
- # Received nil from :yield
+ # values = []
+ # until ractors.empty?
+ # r, val = Ractor.select(*ractors)
+ # ractors.delete(r)
+ # values << val
+ # end
#
- # +move+ boolean flag defines whether yielded value will 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?
+ def self.select(*ports)
+ raise ArgumentError, 'specify at least one Ractor::Port or Ractor' if ports.empty?
- if ractors.delete Ractor.current
- do_receive = true
- else
- do_receive = false
+ monitors = {} # Ractor::Port => Ractor
+
+ ports = ports.map do |arg|
+ case arg
+ when Ractor
+ port = Ractor::Port.new
+ monitors[port] = arg
+ arg.monitor port
+ port
+ when Ractor::Port
+ arg
+ else
+ raise ArgumentError, "should be Ractor::Port or Ractor"
+ end
end
- __builtin_ractor_select_internal ractors, do_receive, !yield_unspecified, yield_value, move
+ begin
+ result_port, obj = __builtin_ractor_select_internal(ports)
+
+ if r = monitors[result_port]
+ [r, r.value]
+ else
+ [result_port, obj]
+ end
+ ensure
+ # close all ports for join
+ monitors.each do |port, r|
+ r.unmonitor port
+ port.close
+ end
+ end
end
#
# call-seq:
- # Ractor.receive -> msg
- #
- # Receive a message from the incoming port of the current ractor (which was
- # sent there by #send from another ractor).
- #
- # r = Ractor.new do
- # v1 = Ractor.receive
- # puts "Received: #{v1}"
- # end
- # r.send('message1')
- # r.take
- # # Here will be printed: "Received: message1"
- #
- # Alternatively, the private instance method +receive+ may be used:
- #
- # r = Ractor.new do
- # v1 = receive
- # puts "Received: #{v1}"
- # end
- # r.send('message1')
- # r.take
- # # This prints: "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 the incoming queue:
- #
- # Ractor.new do
- # close_incoming
- # receive
- # end
- # wait
- # # in `receive': The incoming port is already closed => #<Ractor:#2 test.rb:1 running> (Ractor::ClosedError)
+ # Ractor.receive -> obj
#
+ # Receives a message from the current ractor's default port.
def self.receive
- __builtin_cexpr! %q{
- ractor_receive(ec, rb_ec_ractor_ptr(ec))
- }
+ Ractor.current.default_port.receive
end
class << self
@@ -439,280 +356,21 @@ class Ractor
# same as Ractor.receive
private def receive
- __builtin_cexpr! %q{
- ractor_receive(ec, rb_ec_ractor_ptr(ec))
- }
+ default_port.receive
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 be given a pattern (or any
- # filter) in a block and you can choose the messages to accept that are available in
- # your ractor's incoming queue.
- #
- # 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 is removed from the incoming queue
- # and returned.
- # Otherwise, the message remains in the incoming queue and the next 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.
- # You should not do any tasks in the block other than message filtration.
- #
- # 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
-
- # same as Ractor.receive_if
- private def receive_if &b
- Primitive.ractor_receive_if b
- end
-
- #
- # call-seq:
- # ractor.send(msg, move: false) -> self
+ # ractor.send(msg, move: false) -> self
#
- # Send a message to a Ractor's incoming queue to be accepted 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
- #
- # An attempt to send to a ractor which already finished its execution will raise Ractor::ClosedError.
- #
- # r = Ractor.new {}
- # r.take
- # p r
- # # "#<Ractor:#6 (irb):23 terminated>"
- # 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 is raised immediately, not when the ractor tries to receive
- #
- # If the +obj+ is unshareable, by default it will be copied into the receiving ractor by deep cloning.
- # If <tt>move: true</tt> is passed, the object is _moved_ into the receiving ractor and becomes
- # inaccessible to the 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 #<Ractor::MovedObject:0x000055c99b9b69b8>
- #
- # All references to the object and its parts will become invalid to the 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 is shareable, <tt>move: true</tt> 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)
- }
+ # This is equivalent to Port#send to the ractor's #default_port.
+ def send(...)
+ default_port.send(...)
+ self
end
alias << send
- #
- # call-seq:
- # Ractor.yield(msg, move: false) -> nil
- #
- # Send a message to the current ractor's outgoing port to be accepted by #take.
- #
- # r = Ractor.new {Ractor.yield 'Hello from ractor'}
- # puts r.take
- # # Prints: "Hello from ractor"
- #
- # This 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 the +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
- #
- # Get a message from the ractor's outgoing port, which was put there by Ractor.yield or at ractor's
- # termination.
- #
- # 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 sent to the outgoing port means that +take+ can be used
- # as an analog of Thread#join ("just wait until ractor finishes"). However, it will raise if
- # somebody has already consumed that message.
- #
- # 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 by take as a
- # Ractor::RemoteError.
- #
- # r = Ractor.new {raise "Something weird happened"}
- #
- # begin
- # r.take
- # rescue => e
- # p e # => #<Ractor::RemoteError: thrown by remote Ractor.>
- # p e.ractor == r # => true
- # p e.cause # => #<RuntimeError: Something weird happened>
- # end
- #
- # Ractor::ClosedError is a descendant of StopIteration, so the termination of the ractor will break
- # out of any loops that receive this message 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 }
@@ -725,49 +383,25 @@ class Ractor
alias to_s inspect
- # The name set in Ractor.new, or +nil+.
+ # Returns the name set in Ractor.new, or +nil+.
def name
__builtin_cexpr! %q{RACTOR_PTR(self)->name}
end
class RemoteError
+ # The Ractor in which the uncaught exception was raised.
attr_reader :ractor
end
#
# call-seq:
- # ractor.close_incoming -> true | false
+ # ractor.close -> true | false
#
- # Closes the incoming port and returns whether it was already closed. All further attempts
- # to Ractor.receive in the ractor, and #send to the ractor will fail with Ractor::ClosedError.
+ # Closes the default port. Closing a port is allowed only by the ractor which created the port.
+ # Therefore, the receiver must be the current ractor.
#
- # 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 whether it was already closed. 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));
- }
+ def close
+ default_port.close
end
#
@@ -776,7 +410,7 @@ class Ractor
#
# Checks if the object is shareable by ractors.
#
- # Ractor.shareable?(1) #=> true -- numbers and other immutable basic values are frozen
+ # Ractor.shareable?(1) #=> true -- numbers are shareable
# Ractor.shareable?('foo') #=> false, unless the string is frozen due to # frozen_string_literal: true
# Ractor.shareable?('foo'.freeze) #=> true
#
@@ -791,7 +425,7 @@ class Ractor
# call-seq:
# Ractor.make_shareable(obj, copy: false) -> shareable_obj
#
- # Make +obj+ shareable between ractors.
+ # Makes +obj+ shareable between ractors.
#
# +obj+ and all the objects it refers to will be frozen, unless they are
# already shareable.
@@ -834,20 +468,367 @@ class Ractor
end
end
- # get a value from ractor-local storage
+ # Gets a value from ractor-local storage for the current Ractor.
+ # Obsolete, use Ractor.[] instead.
def [](sym)
+ if (self != Ractor.current)
+ raise RuntimeError, "Cannot get ractor local storage for non-current ractor"
+ end
Primitive.ractor_local_value(sym)
end
- # set a value in ractor-local storage
+ # Sets a value in ractor-local storage for the current Ractor.
+ # Obsolete, use Ractor.[]= instead.
def []=(sym, val)
+ if (self != Ractor.current)
+ raise RuntimeError, "Cannot set ractor local storage for non-current ractor"
+ end
Primitive.ractor_local_value_set(sym, val)
end
- # returns main ractor
+ # Gets a value from ractor-local storage for the current Ractor.
+ def self.[](sym)
+ Primitive.ractor_local_value(sym)
+ end
+
+ # Sets a value in ractor-local storage for the current Ractor.
+ def self.[]=(sym, val)
+ Primitive.ractor_local_value_set(sym, val)
+ end
+
+ # call-seq:
+ # Ractor.store_if_absent(key){ init_block }
+ #
+ # If the corresponding ractor-local value is not set, yields a value with
+ # init_block and stores the value in a thread-safe manner.
+ # This method returns the stored value.
+ #
+ # (1..10).map{
+ # Thread.new(it){|i|
+ # Ractor.store_if_absent(:s){ f(); i }
+ # #=> return stored value of key :s
+ # }
+ # }.map(&:value).uniq.size #=> 1 and f() is called only once
+ #
+ def self.store_if_absent(sym)
+ Primitive.attr! :use_block
+ Primitive.ractor_local_value_store_if_absent(sym)
+ end
+
+ # Returns the main ractor.
def self.main
__builtin_cexpr! %q{
rb_ractor_self(GET_VM()->ractor.main_ractor);
}
end
+
+ # Returns true if the current ractor is the main ractor.
+ def self.main?
+ __builtin_cexpr! %q{
+ RBOOL(GET_VM()->ractor.main_ractor == rb_ec_ractor_ptr(ec))
+ }
+ end
+
+ # internal method
+ def self._require feature # :nodoc:
+ if main?
+ super feature
+ else
+ Primitive.ractor_require feature
+ end
+ end
+
+ class << self
+ private
+
+ # internal method that is called when the first "Ractor.new" is called
+ def _activated # :nodoc:
+ Kernel.prepend Module.new{|m|
+ m.set_temporary_name '<RactorRequire>'
+
+ def require feature # :nodoc: -- otherwise RDoc outputs it as a class method
+ if Ractor.main?
+ super
+ else
+ Ractor._require feature
+ end
+ end
+ }
+ end
+ end
+
+ #
+ # call-seq:
+ # ractor.default_port -> port object
+ #
+ # Returns the default port of the Ractor.
+ #
+ def default_port
+ __builtin_cexpr! %q{
+ ractor_default_port_value(RACTOR_PTR(self))
+ }
+ end
+
+ #
+ # call-seq:
+ # ractor.join -> self
+ #
+ # Waits for the termination of the Ractor.
+ # If the Ractor was aborted (terminated by an unhandled exception),
+ # the exception is raised in the current ractor.
+ #
+ # Ractor.new{}.join #=> ractor
+ #
+ # Ractor.new{ raise "foo" }.join
+ # #=> raises the exception "foo (RuntimeError)"
+ #
+ def join
+ port = Port.new
+
+ self.monitor port
+ if port.receive == :aborted
+ __builtin_ractor_value
+ end
+
+ self
+ ensure
+ port.close
+ end
+
+ #
+ # call-seq:
+ # ractor.value -> obj
+ #
+ # Waits for +ractor+ to complete and returns its value or raises the exception
+ # which terminated the Ractor. The termination value will be moved to the calling
+ # Ractor. Therefore, at most 1 Ractor can receive another ractor's termination value.
+ #
+ # r = Ractor.new{ [1, 2] }
+ # r.value #=> [1, 2] (unshareable object)
+ #
+ # Ractor.new(r){|r| r.value} #=> Ractor::Error
+ #
+ def value
+ self.join
+ __builtin_ractor_value
+ end
+
+ #
+ # call-seq:
+ # ractor.monitor(port) -> self
+ #
+ # Registers the port as a monitoring port for this ractor. When the ractor terminates,
+ # the port receives a Symbol object.
+ #
+ # * +:exited+ is sent if the ractor terminates without an unhandled exception.
+ # * +:aborted+ is sent if the ractor terminates by an unhandled exception.
+ #
+ # r = Ractor.new{ some_task() }
+ # r.monitor(port = Ractor::Port.new)
+ # port.receive #=> :exited and r is terminated
+ #
+ # r = Ractor.new{ raise "foo" }
+ # r.monitor(port = Ractor::Port.new)
+ # port.receive #=> :aborted and r is terminated by the RuntimeError "foo"
+ #
+ def monitor port
+ __builtin_ractor_monitor(port)
+ end
+
+ #
+ # call-seq:
+ # ractor.unmonitor(port) -> self
+ #
+ # Unregisters the port from the monitoring ports for this ractor.
+ #
+ def unmonitor port
+ __builtin_ractor_unmonitor(port)
+ end
+
+ #
+ # call-seq:
+ # Ractor.shareable_proc(self: nil){} -> shareable proc
+ #
+ # Returns a shareable copy of the given block's Proc. The value of +self+
+ # in the Proc will be replaced with the value passed via the `self:` keyword,
+ # or +nil+ if not given.
+ #
+ # In a shareable Proc, access to any outer variables is prohibited.
+ #
+ # a = 42
+ # Ractor.shareable_proc{ p a }
+ # #=> can not isolate a Proc because it accesses outer variables (a). (ArgumentError)
+ #
+ # The value of `self` in the Proc must be a shareable object.
+ #
+ # Ractor.shareable_proc(self: self){}
+ # #=> self should be shareable: main (Ractor::IsolationError)
+ #
+ def self.shareable_proc self: nil
+ Primitive.attr! :use_block
+
+ __builtin_cexpr!(%Q{
+ ractor_shareable_proc(ec, *LOCAL_PTR(self), false)
+ })
+ end
+
+ #
+ # call-seq:
+ # Ractor.shareable_lambda(self: nil){} -> shareable lambda
+ #
+ # Same as Ractor.shareable_proc, but returns a lambda Proc.
+ #
+ def self.shareable_lambda self: nil
+ Primitive.attr! :use_block
+
+ __builtin_cexpr!(%Q{
+ ractor_shareable_proc(ec, *LOCAL_PTR(self), true)
+ })
+ end
+
+ # \Port objects transmit messages between Ractors.
+ class Port
+ #
+ # call-seq:
+ # port.receive -> msg
+ #
+ # Receives a message from the port (which was sent there by Port#send). Only the ractor
+ # that created the port can receive messages this way.
+ #
+ # port = Ractor::Port.new
+ # r = Ractor.new port do |port|
+ # port.send('message1')
+ # end
+ #
+ # v1 = port.receive
+ # puts "Received: #{v1}"
+ # r.join
+ # # This will print: "Received: message1"
+ #
+ # The method blocks the current Thread if the message queue is empty.
+ #
+ # port = Ractor::Port.new
+ # r = Ractor.new port do |port|
+ # wait
+ # puts "Still not received"
+ # port.send('message1')
+ # wait
+ # puts "Still received only one"
+ # port.send('message2')
+ # end
+ # puts "Before first receive"
+ # v1 = port.receive
+ # puts "Received: #{v1}"
+ # v2 = port.receive
+ # puts "Received: #{v2}"
+ # r.join
+ #
+ # Output:
+ #
+ # Before first receive
+ # Still not received
+ # Received: message1
+ # Still received only one
+ # Received: message2
+ #
+ # If the port is closed and there are no more messages in the message queue,
+ # the method raises Ractor::ClosedError.
+ #
+ # port = Ractor::Port.new
+ # port.close
+ # port.receive #=> raise Ractor::ClosedError
+ #
+ def receive
+ __builtin_cexpr! %q{
+ ractor_port_receive(ec, self)
+ }
+ end
+
+ #
+ # call-seq:
+ # port.send(msg, move: false) -> self
+ #
+ # Sends a message to the port to be accepted by port.receive.
+ #
+ # port = Ractor::Port.new
+ # r = Ractor.new(port) do |port|
+ # port.send 'message'
+ # end
+ # value = port.receive
+ # puts "Received #{value}"
+ # # Prints: "Received: message"
+ #
+ # The method is non-blocking (it will return immediately even if the ractor that created the port is not ready
+ # to receive anything):
+ #
+ # port = Ractor::Port.new
+ # r = Ractor.new(port) do |port|
+ # port.send 'test'
+ # puts "Sent successfully"
+ # # Prints: "Sent successfully" immediately
+ # end
+ #
+ # An attempt to send to a closed port will raise Ractor::ClosedError.
+ #
+ # r = Ractor.new {Ractor::Port.new}
+ # r.join
+ # p r
+ # # "#<Ractor:#6 (irb):23 terminated>"
+ # port = r.value
+ # port.send('test') # raise Ractor::ClosedError
+ #
+ # If the +obj+ is unshareable, by default it will be copied into the receiving ractor by deep cloning.
+ #
+ # If the object is shareable, a reference to the object will be sent to the receiving ractor.
+ #
+ def send obj, move: false
+ __builtin_cexpr! %q{
+ ractor_port_send(ec, self, obj, move)
+ }
+ end
+
+ alias << send
+
+ #
+ # call-seq:
+ # port.close
+ #
+ # Closes the port. Sending to a closed port is prohibited.
+ # Receiving is also prohibited if there are no messages in its message queue.
+ #
+ # Only the Ractor which created the port is allowed to close it.
+ #
+ # port = Ractor::Port.new
+ # Ractor.new port do |port|
+ # port.close #=> closing port by other ractors is not allowed (Ractor::Error)
+ # end.join
+ #
+ def close
+ __builtin_cexpr! %q{
+ ractor_port_close(ec, self)
+ }
+ end
+
+ #
+ # call-seq:
+ # port.closed? -> true/false
+ #
+ # Returns whether or not the port is closed.
+ def closed?
+ __builtin_cexpr! %q{
+ ractor_port_closed_p(ec, self);
+ }
+ end
+
+ #
+ # call-seq:
+ # port.inspect -> string
+ def inspect
+ "#<Ractor::Port to:\##{
+ __builtin_cexpr! "SIZET2NUM(rb_ractor_id((RACTOR_PORT_PTR(self)->r)))"
+ } id:#{
+ __builtin_cexpr! "SIZET2NUM(ractor_port_id(RACTOR_PORT_PTR(self)))"
+ }>"
+ end
+ end
end
diff --git a/ractor_core.h b/ractor_core.h
index 36c0e91c7a..d112ff8724 100644
--- a/ractor_core.h
+++ b/ractor_core.h
@@ -9,122 +9,39 @@
#define RACTOR_CHECK_MODE (VM_CHECK_MODE || RUBY_DEBUG) && (SIZEOF_UINT64_T == SIZEOF_VALUE)
#endif
-enum rb_ractor_basket_type {
- // basket is empty
- basket_type_none,
-
- // value is available
- basket_type_ref,
- basket_type_copy,
- basket_type_move,
- basket_type_will,
-
- // basket should be deleted
- basket_type_deleted,
-
- // basket is reserved
- basket_type_reserved,
-
- // take_basket is available
- basket_type_take_basket,
-
- // basket is keeping by yielding ractor
- basket_type_yielding,
-};
-
-// per ractor taking configuration
-struct rb_ractor_selector_take_config {
- bool closed;
- bool oneshot;
-};
-
-struct rb_ractor_basket {
- union {
- enum rb_ractor_basket_type e;
- rb_atomic_t atomic;
- } type;
- VALUE sender;
-
- union {
- struct {
- VALUE v;
- bool exception;
- } send;
-
- struct {
- struct rb_ractor_basket *basket;
- struct rb_ractor_selector_take_config *config;
- } take;
- } p; // payload
-};
-
-static inline bool
-basket_type_p(struct rb_ractor_basket *b, enum rb_ractor_basket_type type)
-{
- return b->type.e == type;
-}
-
-static inline bool
-basket_none_p(struct rb_ractor_basket *b)
-{
- return basket_type_p(b, basket_type_none);
-}
-
-struct rb_ractor_queue {
- struct rb_ractor_basket *baskets;
- int start;
- int cnt;
- int size;
- unsigned int serial;
- unsigned int reserved_cnt;
-};
-
-enum rb_ractor_wait_status {
- wait_none = 0x00,
- wait_receiving = 0x01,
- wait_taking = 0x02,
- wait_yielding = 0x04,
- wait_moving = 0x08,
-};
-
-enum rb_ractor_wakeup_status {
- wakeup_none,
- wakeup_by_send,
- wakeup_by_yield,
- wakeup_by_take,
- wakeup_by_close,
- wakeup_by_interrupt,
- wakeup_by_retry,
-};
+// experimental flag because it is not sure it is the common pattern
+#define RUBY_TYPED_FROZEN_SHAREABLE_NO_REC RUBY_FL_FINALIZE
struct rb_ractor_sync {
// ractor lock
rb_nativethread_lock_t lock;
+
#if RACTOR_CHECK_MODE > 0
VALUE locked_by;
#endif
- bool incoming_port_closed;
- bool outgoing_port_closed;
+#ifndef RUBY_THREAD_PTHREAD_H
+ rb_nativethread_cond_t wakeup_cond;
+#endif
- // All sent messages will be pushed into recv_queue
- struct rb_ractor_queue recv_queue;
+ // incoming messages
+ struct ractor_queue *recv_queue;
- // The following ractors waiting for the yielding by this ractor
- struct rb_ractor_queue takers_queue;
+ // waiting threads for receiving
+ struct ccan_list_head waiters;
- // Enabled if the ractor already terminated and not taken yet.
- struct rb_ractor_basket will_basket;
+ // ports
+ VALUE default_port_value;
+ struct st_table *ports;
+ size_t next_port_id;
- struct ractor_wait {
- enum rb_ractor_wait_status status;
- enum rb_ractor_wakeup_status wakeup_status;
- rb_thread_t *waiting_thread;
- } wait;
+ // monitors
+ struct ccan_list_head monitors;
-#ifndef RUBY_THREAD_PTHREAD_H
- rb_nativethread_cond_t cond;
-#endif
+ // value
+ rb_ractor_t *successor;
+ VALUE legacy;
+ bool legacy_exc;
};
// created
@@ -150,12 +67,7 @@ enum ractor_status {
struct rb_ractor_struct {
struct rb_ractor_pub pub;
-
struct rb_ractor_sync sync;
- VALUE receiving_mutex;
-
- // vm wide barrier synchronization
- rb_nativethread_cond_t barrier_wait_cond;
// thread management
struct {
@@ -167,6 +79,7 @@ struct rb_ractor_struct {
rb_execution_context_t *running_ec;
rb_thread_t *main;
} threads;
+
VALUE thgroup_default;
VALUE name;
@@ -178,8 +91,11 @@ struct rb_ractor_struct {
// ractor local data
+ rb_serial_t next_ec_serial;
+
st_table *local_storage;
struct rb_id_table *idkey_local_storage;
+ VALUE local_storage_store_lock;
VALUE r_stdin;
VALUE r_stdout;
@@ -187,13 +103,8 @@ struct rb_ractor_struct {
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;
+ bool malloc_gc_disabled;
+ void *newobj_cache;
}; // rb_ractor_t is defined in vm_core.h
@@ -227,12 +138,17 @@ 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);
+void rb_ractor_terminate_atfork(rb_vm_t *vm, rb_ractor_t *th);
+VALUE rb_ractor_require(VALUE feature, bool silent);
+VALUE rb_ractor_autoload_load(VALUE space, ID id);
VALUE rb_ractor_ensure_shareable(VALUE obj, VALUE name);
+st_table *rb_ractor_targeted_hooks(rb_ractor_t *cr);
RUBY_SYMBOL_EXPORT_BEGIN
+void rb_ractor_finish_marking(void);
+
bool rb_ractor_shareable_p_continue(VALUE obj);
// THIS FUNCTION SHOULD NOT CALL WHILE INCREMENTAL MARKING!!
@@ -283,12 +199,16 @@ rb_ractor_sleeper_thread_num(rb_ractor_t *r)
}
static inline void
-rb_ractor_thread_switch(rb_ractor_t *cr, rb_thread_t *th)
+rb_ractor_thread_switch(rb_ractor_t *cr, rb_thread_t *th, bool always_reset)
{
RUBY_DEBUG_LOG("th:%d->%u%s",
cr->threads.running_ec ? (int)rb_th_serial(cr->threads.running_ec->thread_ptr) : -1,
rb_th_serial(th), cr->threads.running_ec == th->ec ? " (same)" : "");
+ if (cr->threads.running_ec != th->ec || always_reset) {
+ th->running_time_us = 0;
+ }
+
if (cr->threads.running_ec != th->ec) {
if (0) {
ruby_debug_printf("rb_ractor_thread_switch ec:%p->%p\n",
@@ -299,28 +219,21 @@ rb_ractor_thread_switch(rb_ractor_t *cr, rb_thread_t *th)
return;
}
- if (cr->threads.running_ec != th->ec) {
- th->running_time_us = 0;
- }
-
cr->threads.running_ec = th->ec;
VM_ASSERT(cr == GET_RACTOR());
}
#define rb_ractor_set_current_ec(cr, ec) rb_ractor_set_current_ec_(cr, ec, __FILE__, __LINE__)
+#ifdef RB_THREAD_LOCAL_SPECIFIER
+void rb_current_ec_set(rb_execution_context_t *ec);
+#endif
static inline void
rb_ractor_set_current_ec_(rb_ractor_t *cr, rb_execution_context_t *ec, const char *file, int line)
{
#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
@@ -338,6 +251,25 @@ rb_ractor_id(const rb_ractor_t *r)
return r->pub.id;
}
+static inline void
+rb_ractor_targeted_hooks_incr(rb_ractor_t *cr)
+{
+ cr->pub.targeted_hooks_cnt++;
+}
+
+static inline void
+rb_ractor_targeted_hooks_decr(rb_ractor_t *cr)
+{
+ RUBY_ASSERT(cr->pub.targeted_hooks_cnt > 0);
+ cr->pub.targeted_hooks_cnt--;
+}
+
+static inline unsigned int
+rb_ractor_targeted_hooks_cnt(rb_ractor_t *cr)
+{
+ return cr->pub.targeted_hooks_cnt;
+}
+
#if RACTOR_CHECK_MODE > 0
# define RACTOR_BELONGING_ID(obj) (*(uint32_t *)(((uintptr_t)(obj)) + rb_gc_obj_slot_size(obj)))
@@ -349,12 +281,6 @@ rb_ractor_setup_belonging_to(VALUE obj, uint32_t rid)
RACTOR_BELONGING_ID(obj) = rid;
}
-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)
{
@@ -366,9 +292,13 @@ rb_ractor_belonging(VALUE obj)
}
}
+extern bool rb_ractor_ignore_belonging_flag;
+
static inline VALUE
rb_ractor_confirm_belonging(VALUE obj)
{
+ if (rb_ractor_ignore_belonging_flag) return obj;
+
uint32_t id = rb_ractor_belonging(obj);
if (id == 0) {
@@ -388,6 +318,14 @@ rb_ractor_confirm_belonging(VALUE obj)
}
return obj;
}
+
+static inline void
+rb_ractor_ignore_belonging(bool flag)
+{
+ rb_ractor_ignore_belonging_flag = flag;
+}
+
#else
#define rb_ractor_confirm_belonging(obj) obj
+#define rb_ractor_ignore_belonging(flag) (0)
#endif
diff --git a/ractor_sync.c b/ractor_sync.c
new file mode 100644
index 0000000000..a63df7c407
--- /dev/null
+++ b/ractor_sync.c
@@ -0,0 +1,1516 @@
+
+// this file is included by ractor.c
+
+struct ractor_port {
+ rb_ractor_t *r;
+ st_data_t id_;
+};
+
+static st_data_t
+ractor_port_id(const struct ractor_port *rp)
+{
+ return rp->id_;
+}
+
+static VALUE rb_cRactorPort;
+
+static VALUE ractor_receive(rb_execution_context_t *ec, const struct ractor_port *rp);
+static VALUE ractor_send(rb_execution_context_t *ec, const struct ractor_port *rp, VALUE obj, VALUE move);
+static VALUE ractor_try_send(rb_execution_context_t *ec, const struct ractor_port *rp, VALUE obj, VALUE move);
+static void ractor_add_port(rb_ractor_t *r, st_data_t id);
+
+static void
+ractor_port_mark(void *ptr)
+{
+ const struct ractor_port *rp = (struct ractor_port *)ptr;
+
+ if (rp->r) {
+ rb_gc_mark(rp->r->pub.self);
+ }
+}
+
+static void
+ractor_port_free(void *ptr)
+{
+ xfree(ptr);
+}
+
+static size_t
+ractor_port_memsize(const void *ptr)
+{
+ return sizeof(struct ractor_port);
+}
+
+static const rb_data_type_t ractor_port_data_type = {
+ "ractor/port",
+ {
+ ractor_port_mark,
+ ractor_port_free,
+ ractor_port_memsize,
+ NULL, // update
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE,
+};
+
+static st_data_t
+ractor_genid_for_port(rb_ractor_t *cr)
+{
+ // TODO: enough?
+ return cr->sync.next_port_id++;
+}
+
+static struct ractor_port *
+RACTOR_PORT_PTR(VALUE self)
+{
+ VM_ASSERT(rb_typeddata_is_kind_of(self, &ractor_port_data_type));
+ struct ractor_port *rp = DATA_PTR(self);
+ return rp;
+}
+
+static VALUE
+ractor_port_alloc(VALUE klass)
+{
+ struct ractor_port *rp;
+ VALUE rpv = TypedData_Make_Struct(klass, struct ractor_port, &ractor_port_data_type, rp);
+ rb_obj_freeze(rpv);
+ return rpv;
+}
+
+static VALUE
+ractor_port_init(VALUE rpv, rb_ractor_t *r)
+{
+ struct ractor_port *rp = RACTOR_PORT_PTR(rpv);
+
+ rp->r = r;
+ RB_OBJ_WRITTEN(rpv, Qundef, r->pub.self);
+ rp->id_ = ractor_genid_for_port(r);
+
+ ractor_add_port(r, ractor_port_id(rp));
+
+ rb_obj_freeze(rpv);
+
+ return rpv;
+}
+
+/*
+ * call-seq:
+ * Ractor::Port.new -> new_port
+ *
+ * Returns a new Ractor::Port object.
+ */
+static VALUE
+ractor_port_initialize(VALUE self)
+{
+ return ractor_port_init(self, GET_RACTOR());
+}
+
+/* :nodoc: */
+static VALUE
+ractor_port_initialize_copy(VALUE self, VALUE orig)
+{
+ struct ractor_port *dst = RACTOR_PORT_PTR(self);
+ struct ractor_port *src = RACTOR_PORT_PTR(orig);
+ dst->r = src->r;
+ RB_OBJ_WRITTEN(self, Qundef, dst->r->pub.self);
+ dst->id_ = ractor_port_id(src);
+
+ return self;
+}
+
+static VALUE
+ractor_port_new(rb_ractor_t *r)
+{
+ VALUE rpv = ractor_port_alloc(rb_cRactorPort);
+ ractor_port_init(rpv, r);
+ return rpv;
+}
+
+static bool
+ractor_port_p(VALUE self)
+{
+ return rb_typeddata_is_kind_of(self, &ractor_port_data_type);
+}
+
+static VALUE
+ractor_port_receive(rb_execution_context_t *ec, VALUE self)
+{
+ const struct ractor_port *rp = RACTOR_PORT_PTR(self);
+
+ if (rp->r != rb_ec_ractor_ptr(ec)) {
+ rb_raise(rb_eRactorError, "only allowed from the creator Ractor of this port");
+ }
+
+ return ractor_receive(ec, rp);
+}
+
+static VALUE
+ractor_port_send(rb_execution_context_t *ec, VALUE self, VALUE obj, VALUE move)
+{
+ const struct ractor_port *rp = RACTOR_PORT_PTR(self);
+ ractor_send(ec, rp, obj, RTEST(move));
+ return self;
+}
+
+static bool ractor_closed_port_p(rb_execution_context_t *ec, rb_ractor_t *r, const struct ractor_port *rp);
+static bool ractor_close_port(rb_execution_context_t *ec, rb_ractor_t *r, const struct ractor_port *rp);
+
+static VALUE
+ractor_port_closed_p(rb_execution_context_t *ec, VALUE self)
+{
+ const struct ractor_port *rp = RACTOR_PORT_PTR(self);
+
+ if (ractor_closed_port_p(ec, rp->r, rp)) {
+ return Qtrue;
+ }
+ else {
+ return Qfalse;
+ }
+}
+
+static VALUE
+ractor_port_close(rb_execution_context_t *ec, VALUE self)
+{
+ const struct ractor_port *rp = RACTOR_PORT_PTR(self);
+ rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
+
+ if (cr != rp->r) {
+ rb_raise(rb_eRactorError, "closing port by other ractors is not allowed");
+ }
+
+ ractor_close_port(ec, cr, rp);
+ return self;
+}
+
+// ractor-internal
+
+// ractor-internal - ractor_basket
+
+enum ractor_basket_type {
+ // basket is empty
+ basket_type_none,
+
+ // value is available
+ basket_type_ref,
+ basket_type_copy,
+ basket_type_move,
+};
+
+struct ractor_basket {
+ enum ractor_basket_type type;
+ VALUE sender;
+ st_data_t port_id;
+
+ struct {
+ VALUE v;
+ bool exception;
+ } p; // payload
+
+ struct ccan_list_node node;
+};
+
+#if 0
+static inline bool
+ractor_basket_type_p(const struct ractor_basket *b, enum ractor_basket_type type)
+{
+ return b->type == type;
+}
+
+static inline bool
+ractor_basket_none_p(const struct ractor_basket *b)
+{
+ return ractor_basket_type_p(b, basket_type_none);
+}
+#endif
+
+static void
+ractor_basket_mark(const struct ractor_basket *b)
+{
+ rb_gc_mark(b->p.v);
+}
+
+static void
+ractor_basket_free(struct ractor_basket *b)
+{
+ xfree(b);
+}
+
+static struct ractor_basket *
+ractor_basket_alloc(void)
+{
+ struct ractor_basket *b = ALLOC(struct ractor_basket);
+ return b;
+}
+
+// ractor-internal - ractor_queue
+
+struct ractor_queue {
+ struct ccan_list_head set;
+ bool closed;
+};
+
+static void
+ractor_queue_init(struct ractor_queue *rq)
+{
+ ccan_list_head_init(&rq->set);
+ rq->closed = false;
+}
+
+static struct ractor_queue *
+ractor_queue_new(void)
+{
+ struct ractor_queue *rq = ALLOC(struct ractor_queue);
+ ractor_queue_init(rq);
+ return rq;
+}
+
+static void
+ractor_queue_mark(const struct ractor_queue *rq)
+{
+ const struct ractor_basket *b;
+
+ ccan_list_for_each(&rq->set, b, node) {
+ ractor_basket_mark(b);
+ }
+}
+
+static void
+ractor_queue_free(struct ractor_queue *rq)
+{
+ struct ractor_basket *b, *nxt;
+
+ ccan_list_for_each_safe(&rq->set, b, nxt, node) {
+ ccan_list_del_init(&b->node);
+ ractor_basket_free(b);
+ }
+
+ VM_ASSERT(ccan_list_empty(&rq->set));
+
+ xfree(rq);
+}
+
+RBIMPL_ATTR_MAYBE_UNUSED()
+static size_t
+ractor_queue_size(const struct ractor_queue *rq)
+{
+ size_t size = 0;
+ const struct ractor_basket *b;
+
+ ccan_list_for_each(&rq->set, b, node) {
+ size++;
+ }
+ return size;
+}
+
+static void
+ractor_queue_close(struct ractor_queue *rq)
+{
+ rq->closed = true;
+}
+
+static void
+ractor_queue_move(struct ractor_queue *dst_rq, struct ractor_queue *src_rq)
+{
+ struct ccan_list_head *src = &src_rq->set;
+ struct ccan_list_head *dst = &dst_rq->set;
+
+ dst->n.next = src->n.next;
+ dst->n.prev = src->n.prev;
+ dst->n.next->prev = &dst->n;
+ dst->n.prev->next = &dst->n;
+ ccan_list_head_init(src);
+}
+
+#if 0
+static struct ractor_basket *
+ractor_queue_head(rb_ractor_t *r, struct ractor_queue *rq)
+{
+ return ccan_list_top(&rq->set, struct ractor_basket, node);
+}
+#endif
+
+static bool
+ractor_queue_empty_p(rb_ractor_t *r, const struct ractor_queue *rq)
+{
+ return ccan_list_empty(&rq->set);
+}
+
+static struct ractor_basket *
+ractor_queue_deq(rb_ractor_t *r, struct ractor_queue *rq)
+{
+ VM_ASSERT(GET_RACTOR() == r);
+
+ return ccan_list_pop(&rq->set, struct ractor_basket, node);
+}
+
+static void
+ractor_queue_enq(rb_ractor_t *r, struct ractor_queue *rq, struct ractor_basket *basket)
+{
+ ccan_list_add_tail(&rq->set, &basket->node);
+}
+
+#if 0
+static void
+rq_dump(const struct ractor_queue *rq)
+{
+ int i=0;
+ struct ractor_basket *b;
+ ccan_list_for_each(&rq->set, b, node) {
+ fprintf(stderr, "%d type:%s %p\n", i, basket_type_name(b->type), (void *)b);
+ i++;
+ }
+}
+#endif
+
+static void ractor_delete_port(rb_ractor_t *cr, st_data_t id, bool locked);
+
+static struct ractor_queue *
+ractor_get_queue(rb_ractor_t *cr, st_data_t id, bool locked)
+{
+ VM_ASSERT(cr == GET_RACTOR());
+
+ struct ractor_queue *rq;
+
+ if (cr->sync.ports && st_lookup(cr->sync.ports, id, (st_data_t *)&rq)) {
+ if (rq->closed && ractor_queue_empty_p(cr, rq)) {
+ ractor_delete_port(cr, id, locked);
+ return NULL;
+ }
+ else {
+ return rq;
+ }
+ }
+ else {
+ return NULL;
+ }
+}
+
+// ractor-internal - ports
+
+static void
+ractor_add_port(rb_ractor_t *r, st_data_t id)
+{
+ struct ractor_queue *rq = ractor_queue_new();
+ ASSERT_ractor_unlocking(r);
+
+ RUBY_DEBUG_LOG("id:%u", (unsigned int)id);
+
+ RACTOR_LOCK(r);
+ {
+ st_insert(r->sync.ports, id, (st_data_t)rq);
+ }
+ RACTOR_UNLOCK(r);
+}
+
+static void
+ractor_delete_port_locked(rb_ractor_t *cr, st_data_t id)
+{
+ ASSERT_ractor_locking(cr);
+
+ RUBY_DEBUG_LOG("id:%u", (unsigned int)id);
+
+ struct ractor_queue *rq;
+
+ if (st_delete(cr->sync.ports, &id, (st_data_t *)&rq)) {
+ ractor_queue_free(rq);
+ }
+ else {
+ VM_ASSERT(0);
+ }
+}
+
+static void
+ractor_delete_port(rb_ractor_t *cr, st_data_t id, bool locked)
+{
+ if (locked) {
+ ractor_delete_port_locked(cr, id);
+ }
+ else {
+ RACTOR_LOCK_SELF(cr);
+ {
+ ractor_delete_port_locked(cr, id);
+ }
+ RACTOR_UNLOCK_SELF(cr);
+ }
+}
+
+static const struct ractor_port *
+ractor_default_port(rb_ractor_t *r)
+{
+ return RACTOR_PORT_PTR(r->sync.default_port_value);
+}
+
+static VALUE
+ractor_default_port_value(rb_ractor_t *r)
+{
+ return r->sync.default_port_value;
+}
+
+static bool
+ractor_closed_port_p(rb_execution_context_t *ec, rb_ractor_t *r, const struct ractor_port *rp)
+{
+ VM_ASSERT(rb_ec_ractor_ptr(ec) == rp->r ? 1 : (ASSERT_ractor_locking(rp->r), 1));
+
+ const struct ractor_queue *rq;
+
+ if (rp->r->sync.ports && st_lookup(rp->r->sync.ports, ractor_port_id(rp), (st_data_t *)&rq)) {
+ return rq->closed;
+ }
+ else {
+ return true;
+ }
+}
+
+static void ractor_deliver_incoming_messages(rb_execution_context_t *ec, rb_ractor_t *cr);
+static bool ractor_queue_empty_p(rb_ractor_t *r, const struct ractor_queue *rq);
+
+static bool
+ractor_close_port(rb_execution_context_t *ec, rb_ractor_t *cr, const struct ractor_port *rp)
+{
+ VM_ASSERT(cr == rp->r);
+ struct ractor_queue *rq = NULL;
+
+ RACTOR_LOCK_SELF(cr);
+ {
+ ractor_deliver_incoming_messages(ec, cr); // check incoming messages
+
+ if (st_lookup(rp->r->sync.ports, ractor_port_id(rp), (st_data_t *)&rq)) {
+ ractor_queue_close(rq);
+
+ if (ractor_queue_empty_p(cr, rq)) {
+ // delete from the table
+ ractor_delete_port(cr, ractor_port_id(rp), true);
+ }
+
+ // TODO: free rq
+ }
+ }
+ RACTOR_UNLOCK_SELF(cr);
+
+ return rq != NULL;
+}
+
+static int
+ractor_free_all_ports_i(st_data_t port_id, st_data_t val, st_data_t dat)
+{
+ struct ractor_queue *rq = (struct ractor_queue *)val;
+ // rb_ractor_t *cr = (rb_ractor_t *)dat;
+
+ ractor_queue_free(rq);
+ return ST_CONTINUE;
+}
+
+static void
+ractor_free_all_ports(rb_ractor_t *cr)
+{
+ if (cr->sync.ports) {
+ st_foreach(cr->sync.ports, ractor_free_all_ports_i, (st_data_t)cr);
+ st_free_table(cr->sync.ports);
+ cr->sync.ports = NULL;
+ }
+
+ if (cr->sync.recv_queue) {
+ ractor_queue_free(cr->sync.recv_queue);
+ cr->sync.recv_queue = NULL;
+ }
+}
+
+#if defined(HAVE_WORKING_FORK)
+static void
+ractor_sync_terminate_atfork(rb_vm_t *vm, rb_ractor_t *r)
+{
+ ractor_free_all_ports(r);
+ r->sync.legacy = Qnil;
+}
+#endif
+
+// Ractor#monitor
+
+struct ractor_monitor {
+ struct ractor_port port;
+ struct ccan_list_node node;
+};
+
+static void
+ractor_mark_monitors(rb_ractor_t *r)
+{
+ const struct ractor_monitor *rm;
+ ccan_list_for_each(&r->sync.monitors, rm, node) {
+ rb_gc_mark(rm->port.r->pub.self);
+ }
+}
+
+static VALUE
+ractor_exit_token(bool exc)
+{
+ if (exc) {
+ RUBY_DEBUG_LOG("aborted");
+ return ID2SYM(idAborted);
+ }
+ else {
+ RUBY_DEBUG_LOG("exited");
+ return ID2SYM(idExited);
+ }
+}
+
+static VALUE
+ractor_monitor(rb_execution_context_t *ec, VALUE self, VALUE port)
+{
+ rb_ractor_t *r = RACTOR_PTR(self);
+ bool terminated = false;
+ const struct ractor_port *rp = RACTOR_PORT_PTR(port);
+ struct ractor_monitor *rm = ALLOC(struct ractor_monitor);
+ rm->port = *rp; // copy port information
+
+ RACTOR_LOCK(r);
+ {
+ if (UNDEF_P(r->sync.legacy)) { // not terminated
+ RUBY_DEBUG_LOG("OK/r:%u -> port:%u@r%u", (unsigned int)rb_ractor_id(r), (unsigned int)ractor_port_id(&rm->port), (unsigned int)rb_ractor_id(rm->port.r));
+ ccan_list_add_tail(&r->sync.monitors, &rm->node);
+ }
+ else {
+ RUBY_DEBUG_LOG("NG/r:%u -> port:%u@r%u", (unsigned int)rb_ractor_id(r), (unsigned int)ractor_port_id(&rm->port), (unsigned int)rb_ractor_id(rm->port.r));
+ terminated = true;
+ }
+ }
+ RACTOR_UNLOCK(r);
+
+ if (terminated) {
+ xfree(rm);
+ ractor_port_send(ec, port, ractor_exit_token(r->sync.legacy_exc), Qfalse);
+
+ return Qfalse;
+ }
+ else {
+ return Qtrue;
+ }
+}
+
+static VALUE
+ractor_unmonitor(rb_execution_context_t *ec, VALUE self, VALUE port)
+{
+ rb_ractor_t *r = RACTOR_PTR(self);
+ const struct ractor_port *rp = RACTOR_PORT_PTR(port);
+
+ RACTOR_LOCK(r);
+ {
+ if (UNDEF_P(r->sync.legacy)) { // not terminated
+ struct ractor_monitor *rm, *nxt;
+
+ ccan_list_for_each_safe(&r->sync.monitors, rm, nxt, node) {
+ if (ractor_port_id(&rm->port) == ractor_port_id(rp)) {
+ RUBY_DEBUG_LOG("r:%u -> port:%u@r%u",
+ (unsigned int)rb_ractor_id(r),
+ (unsigned int)ractor_port_id(&rm->port),
+ (unsigned int)rb_ractor_id(rm->port.r));
+ ccan_list_del(&rm->node);
+ xfree(rm);
+ }
+ }
+ }
+ }
+ RACTOR_UNLOCK(r);
+
+ return self;
+}
+
+static void
+ractor_notify_exit(rb_execution_context_t *ec, rb_ractor_t *cr, VALUE legacy, bool exc)
+{
+ RUBY_DEBUG_LOG("exc:%d", exc);
+ VM_ASSERT(!UNDEF_P(legacy));
+ VM_ASSERT(cr->sync.legacy == Qundef);
+
+ RACTOR_LOCK_SELF(cr);
+ {
+ ractor_free_all_ports(cr);
+
+ cr->sync.legacy = legacy;
+ cr->sync.legacy_exc = exc;
+ }
+ RACTOR_UNLOCK_SELF(cr);
+
+ // send token
+
+ VALUE token = ractor_exit_token(exc);
+ struct ractor_monitor *rm, *nxt;
+
+ ccan_list_for_each_safe(&cr->sync.monitors, rm, nxt, node)
+ {
+ RUBY_DEBUG_LOG("port:%u@r%u", (unsigned int)ractor_port_id(&rm->port), (unsigned int)rb_ractor_id(rm->port.r));
+
+ ractor_try_send(ec, &rm->port, token, false);
+
+ ccan_list_del(&rm->node);
+ xfree(rm);
+ }
+
+ VM_ASSERT(ccan_list_empty(&cr->sync.monitors));
+}
+
+// ractor-internal - initialize, mark, free, memsize
+
+static int
+ractor_mark_ports_i(st_data_t key, st_data_t val, st_data_t data)
+{
+ // id -> ractor_queue
+ const struct ractor_queue *rq = (struct ractor_queue *)val;
+ ractor_queue_mark(rq);
+ return ST_CONTINUE;
+}
+
+static void
+ractor_sync_mark(rb_ractor_t *r)
+{
+ rb_gc_mark(r->sync.default_port_value);
+
+ if (r->sync.ports) {
+ ractor_queue_mark(r->sync.recv_queue);
+ st_foreach(r->sync.ports, ractor_mark_ports_i, 0);
+ }
+
+ ractor_mark_monitors(r);
+}
+
+static int
+ractor_sync_free_ports_i(st_data_t _key, st_data_t val, st_data_t _args)
+{
+ struct ractor_queue *queue = (struct ractor_queue *)val;
+
+ ractor_queue_free(queue);
+
+ return ST_CONTINUE;
+}
+
+static void
+ractor_sync_free(rb_ractor_t *r)
+{
+ if (r->sync.recv_queue) {
+ ractor_queue_free(r->sync.recv_queue);
+ }
+
+ // maybe NULL
+ if (r->sync.ports) {
+ st_foreach(r->sync.ports, ractor_sync_free_ports_i, 0);
+ st_free_table(r->sync.ports);
+ r->sync.ports = NULL;
+ }
+}
+
+static size_t
+ractor_sync_memsize(const rb_ractor_t *r)
+{
+ if (r->sync.ports) {
+ return st_table_size(r->sync.ports);
+ }
+ else {
+ return 0;
+ }
+}
+
+static void
+ractor_sync_init(rb_ractor_t *r)
+{
+ // lock
+ rb_native_mutex_initialize(&r->sync.lock);
+
+ // monitors
+ ccan_list_head_init(&r->sync.monitors);
+
+ // waiters
+ ccan_list_head_init(&r->sync.waiters);
+
+ // receiving queue
+ r->sync.recv_queue = ractor_queue_new();
+
+ // ports
+ r->sync.ports = st_init_numtable();
+ r->sync.default_port_value = ractor_port_new(r);
+ FL_SET_RAW(r->sync.default_port_value, RUBY_FL_SHAREABLE); // only default ports are shareable
+
+ // legacy
+ r->sync.legacy = Qundef;
+
+#ifndef RUBY_THREAD_PTHREAD_H
+ rb_native_cond_initialize(&r->sync.wakeup_cond);
+#endif
+}
+
+// Ractor#value
+
+static rb_ractor_t *
+ractor_set_successor_once(rb_ractor_t *r, rb_ractor_t *cr)
+{
+ if (r->sync.successor == NULL) {
+ rb_ractor_t *successor = ATOMIC_PTR_CAS(r->sync.successor, NULL, cr);
+ return successor == NULL ? cr : successor;
+ }
+
+ return r->sync.successor;
+}
+
+static VALUE ractor_reset_belonging(VALUE obj);
+
+static VALUE
+ractor_make_remote_exception(VALUE cause, VALUE sender)
+{
+ VALUE err = rb_exc_new_cstr(rb_eRactorRemoteError, "thrown by remote Ractor.");
+ rb_ivar_set(err, rb_intern("@ractor"), sender);
+ rb_ec_setup_exception(NULL, err, cause);
+ return err;
+}
+
+static VALUE
+ractor_value(rb_execution_context_t *ec, VALUE self)
+{
+ rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
+ rb_ractor_t *r = RACTOR_PTR(self);
+ rb_ractor_t *sr = ractor_set_successor_once(r, cr);
+
+ if (sr == cr) {
+ ractor_reset_belonging(r->sync.legacy);
+
+ if (r->sync.legacy_exc) {
+ rb_exc_raise(ractor_make_remote_exception(r->sync.legacy, self));
+ }
+ return r->sync.legacy;
+ }
+ else {
+ rb_raise(rb_eRactorError, "Only the successor ractor can take a value");
+ }
+}
+
+static VALUE ractor_move(VALUE obj); // in this file
+static VALUE ractor_copy(VALUE obj); // in this file
+
+static VALUE
+ractor_prepare_payload(rb_execution_context_t *ec, VALUE obj, enum ractor_basket_type *ptype)
+{
+ switch (*ptype) {
+ case basket_type_ref:
+ return obj;
+ case basket_type_move:
+ return ractor_move(obj);
+ default:
+ if (rb_ractor_shareable_p(obj)) {
+ *ptype = basket_type_ref;
+ return obj;
+ }
+ else {
+ *ptype = basket_type_copy;
+ return ractor_copy(obj);
+ }
+ }
+}
+
+static struct ractor_basket *
+ractor_basket_new(rb_execution_context_t *ec, VALUE obj, enum ractor_basket_type type, bool exc)
+{
+ VALUE v = ractor_prepare_payload(ec, obj, &type);
+
+ struct ractor_basket *b = ractor_basket_alloc();
+ b->type = type;
+ b->p.v = v;
+ b->p.exception = exc;
+ return b;
+}
+
+static VALUE
+ractor_basket_value(struct ractor_basket *b)
+{
+ switch (b->type) {
+ case basket_type_ref:
+ break;
+ case basket_type_copy:
+ case basket_type_move:
+ ractor_reset_belonging(b->p.v);
+ break;
+ default:
+ VM_ASSERT(0); // unreachable
+ }
+
+ VM_ASSERT(!RB_TYPE_P(b->p.v, T_NONE));
+ return b->p.v;
+}
+
+static VALUE
+ractor_basket_accept(struct ractor_basket *b)
+{
+ VALUE v = ractor_basket_value(b);
+
+ if (b->p.exception) {
+ VALUE err = ractor_make_remote_exception(v, b->sender);
+ ractor_basket_free(b);
+ rb_exc_raise(err);
+ }
+
+ ractor_basket_free(b);
+ return v;
+}
+
+// Ractor blocking by receive
+
+enum ractor_wakeup_status {
+ wakeup_none,
+ wakeup_by_send,
+ wakeup_by_interrupt,
+
+ // wakeup_by_close,
+};
+
+struct ractor_waiter {
+ enum ractor_wakeup_status wakeup_status;
+ rb_thread_t *th;
+ struct ccan_list_node node;
+};
+
+#if VM_CHECK_MODE > 0
+static bool
+ractor_waiter_included(rb_ractor_t *cr, rb_thread_t *th)
+{
+ ASSERT_ractor_locking(cr);
+
+ struct ractor_waiter *w;
+
+ ccan_list_for_each(&cr->sync.waiters, w, node) {
+ if (w->th == th) {
+ return true;
+ }
+ }
+
+ return false;
+}
+#endif
+
+#if USE_RUBY_DEBUG_LOG
+
+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_interrupt: return "by_interrupt";
+ // case wakeup_by_close: return "by_close";
+ }
+ rb_bug("unreachable");
+}
+
+static const char *
+basket_type_name(enum ractor_basket_type type)
+{
+ switch (type) {
+ case basket_type_none: return "none";
+ case basket_type_ref: return "ref";
+ case basket_type_copy: return "copy";
+ case basket_type_move: return "move";
+ }
+ VM_ASSERT(0);
+ return NULL;
+}
+
+#endif // USE_RUBY_DEBUG_LOG
+
+#ifdef RUBY_THREAD_PTHREAD_H
+
+//
+
+#else // win32
+
+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.wakeup_cond, &r->sync.lock);
+
+#if RACTOR_CHECK_MODE > 0
+ r->sync.locked_by = locked_by;
+#endif
+}
+
+static void *
+ractor_wait_no_gvl(void *ptr)
+{
+ struct ractor_waiter *waiter = (struct ractor_waiter *)ptr;
+ rb_ractor_t *cr = waiter->th->ractor;
+
+ RACTOR_LOCK_SELF(cr);
+ {
+ if (waiter->wakeup_status == wakeup_none) {
+ ractor_cond_wait(cr);
+ }
+ }
+ RACTOR_UNLOCK_SELF(cr);
+ return NULL;
+}
+
+static void
+rb_ractor_sched_wait(rb_execution_context_t *ec, rb_ractor_t *cr, rb_unblock_function_t *ubf, void *ptr)
+{
+ struct ractor_waiter *waiter = (struct ractor_waiter *)ptr;
+
+ RACTOR_UNLOCK(cr);
+ {
+ rb_nogvl(ractor_wait_no_gvl, waiter,
+ ubf, waiter,
+ RB_NOGVL_UBF_ASYNC_SAFE | RB_NOGVL_INTR_FAIL);
+ }
+ RACTOR_LOCK(cr);
+}
+
+static void
+rb_ractor_sched_wakeup(rb_ractor_t *r, rb_thread_t *th)
+{
+ // ractor lock is acquired
+ rb_native_cond_broadcast(&r->sync.wakeup_cond);
+}
+#endif
+
+static bool
+ractor_wakeup_all(rb_ractor_t *r, enum ractor_wakeup_status wakeup_status)
+{
+ ASSERT_ractor_unlocking(r);
+
+ RUBY_DEBUG_LOG("r:%u wakeup:%s", rb_ractor_id(r), wakeup_status_str(wakeup_status));
+
+ bool wakeup_p = false;
+
+ RACTOR_LOCK(r);
+ while (1) {
+ struct ractor_waiter *waiter = ccan_list_pop(&r->sync.waiters, struct ractor_waiter, node);
+
+ if (waiter) {
+ VM_ASSERT(waiter->wakeup_status == wakeup_none);
+
+ waiter->wakeup_status = wakeup_status;
+ rb_ractor_sched_wakeup(r, waiter->th);
+
+ wakeup_p = true;
+ }
+ else {
+ break;
+ }
+ }
+ RACTOR_UNLOCK(r);
+
+ return wakeup_p;
+}
+
+static void
+ubf_ractor_wait(void *ptr)
+{
+ struct ractor_waiter *waiter = (struct ractor_waiter *)ptr;
+
+ rb_thread_t *th = waiter->th;
+ rb_ractor_t *r = th->ractor;
+
+ // clear ubf and nobody can kick UBF
+ th->unblock.func = NULL;
+ th->unblock.arg = NULL;
+
+ rb_native_mutex_unlock(&th->interrupt_lock);
+ {
+ RACTOR_LOCK(r);
+ {
+ if (waiter->wakeup_status == wakeup_none) {
+ RUBY_DEBUG_LOG("waiter:%p", (void *)waiter);
+
+ waiter->wakeup_status = wakeup_by_interrupt;
+ ccan_list_del(&waiter->node);
+
+ rb_ractor_sched_wakeup(r, waiter->th);
+ }
+ }
+ RACTOR_UNLOCK(r);
+ }
+ rb_native_mutex_lock(&th->interrupt_lock);
+}
+
+static enum ractor_wakeup_status
+ractor_wait(rb_execution_context_t *ec, rb_ractor_t *cr)
+{
+ rb_thread_t *th = rb_ec_thread_ptr(ec);
+
+ struct ractor_waiter waiter = {
+ .wakeup_status = wakeup_none,
+ .th = th,
+ };
+
+ RUBY_DEBUG_LOG("wait%s", "");
+
+ ASSERT_ractor_locking(cr);
+
+ VM_ASSERT(GET_RACTOR() == cr);
+ VM_ASSERT(!ractor_waiter_included(cr, th));
+
+ ccan_list_add_tail(&cr->sync.waiters, &waiter.node);
+
+ // resume another ready thread and wait for an event
+ rb_ractor_sched_wait(ec, cr, ubf_ractor_wait, &waiter);
+
+ if (waiter.wakeup_status == wakeup_none) {
+ ccan_list_del(&waiter.node);
+ }
+
+ RUBY_DEBUG_LOG("wakeup_status:%s", wakeup_status_str(waiter.wakeup_status));
+
+ RACTOR_UNLOCK_SELF(cr);
+ {
+ rb_ec_check_ints(ec);
+ }
+ RACTOR_LOCK_SELF(cr);
+
+ VM_ASSERT(!ractor_waiter_included(cr, th));
+ return waiter.wakeup_status;
+}
+
+static void
+ractor_deliver_incoming_messages(rb_execution_context_t *ec, rb_ractor_t *cr)
+{
+ ASSERT_ractor_locking(cr);
+ struct ractor_queue *recv_q = cr->sync.recv_queue;
+
+ struct ractor_basket *b;
+ while ((b = ractor_queue_deq(cr, recv_q)) != NULL) {
+ ractor_queue_enq(cr, ractor_get_queue(cr, b->port_id, true), b);
+ }
+}
+
+static bool
+ractor_check_received(rb_ractor_t *cr, struct ractor_queue *messages)
+{
+ struct ractor_queue *received_queue = cr->sync.recv_queue;
+ bool received = false;
+
+ ASSERT_ractor_locking(cr);
+
+ if (ractor_queue_empty_p(cr, received_queue)) {
+ RUBY_DEBUG_LOG("empty");
+ }
+ else {
+ received = true;
+
+ // messages <- incoming
+ ractor_queue_init(messages);
+ ractor_queue_move(messages, received_queue);
+ }
+
+ VM_ASSERT(ractor_queue_empty_p(cr, received_queue));
+
+ RUBY_DEBUG_LOG("received:%d", received);
+ return received;
+}
+
+static void
+ractor_wait_receive(rb_execution_context_t *ec, rb_ractor_t *cr)
+{
+ struct ractor_queue messages;
+ bool deliverred = false;
+
+ RACTOR_LOCK_SELF(cr);
+ {
+ if (ractor_check_received(cr, &messages)) {
+ deliverred = true;
+ }
+ else {
+ ractor_wait(ec, cr);
+ }
+ }
+ RACTOR_UNLOCK_SELF(cr);
+
+ if (deliverred) {
+ VM_ASSERT(!ractor_queue_empty_p(cr, &messages));
+ struct ractor_basket *b;
+
+ while ((b = ractor_queue_deq(cr, &messages)) != NULL) {
+ ractor_queue_enq(cr, ractor_get_queue(cr, b->port_id, false), b);
+ }
+ }
+}
+
+static VALUE
+ractor_try_receive(rb_execution_context_t *ec, rb_ractor_t *cr, const struct ractor_port *rp)
+{
+ struct ractor_queue *rq = ractor_get_queue(cr, ractor_port_id(rp), false);
+
+ if (rq == NULL) {
+ rb_raise(rb_eRactorClosedError, "The port was already closed");
+ }
+
+ struct ractor_basket *b = ractor_queue_deq(cr, rq);
+
+ if (rq->closed && ractor_queue_empty_p(cr, rq)) {
+ ractor_delete_port(cr, ractor_port_id(rp), false);
+ }
+
+ if (b) {
+ return ractor_basket_accept(b);
+ }
+ else {
+ return Qundef;
+ }
+}
+
+static VALUE
+ractor_receive(rb_execution_context_t *ec, const struct ractor_port *rp)
+{
+ rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
+ VM_ASSERT(cr == rp->r);
+
+ RUBY_DEBUG_LOG("port:%u", (unsigned int)ractor_port_id(rp));
+
+ while (1) {
+ VALUE v = ractor_try_receive(ec, cr, rp);
+
+ if (v != Qundef) {
+ return v;
+ }
+ else {
+ ractor_wait_receive(ec, cr);
+ }
+ }
+}
+
+// Ractor#send
+
+static void
+ractor_send_basket(rb_execution_context_t *ec, const struct ractor_port *rp, struct ractor_basket *b, bool raise_on_error)
+{
+ bool closed = false;
+
+ RUBY_DEBUG_LOG("port:%u@r%u b:%s v:%p", (unsigned int)ractor_port_id(rp), rb_ractor_id(rp->r), basket_type_name(b->type), (void *)b->p.v);
+
+ RACTOR_LOCK(rp->r);
+ {
+ if (ractor_closed_port_p(ec, rp->r, rp)) {
+ closed = true;
+ }
+ else {
+ b->port_id = ractor_port_id(rp);
+ ractor_queue_enq(rp->r, rp->r->sync.recv_queue, b);
+ }
+ }
+ RACTOR_UNLOCK(rp->r);
+
+ // NOTE: ref r -> b->p.v is created, but Ractor is unprotected object, so no problem on that.
+
+ if (!closed) {
+ ractor_wakeup_all(rp->r, wakeup_by_send);
+ }
+ else {
+ RUBY_DEBUG_LOG("closed:%u@r%u", (unsigned int)ractor_port_id(rp), rb_ractor_id(rp->r));
+
+ if (raise_on_error) {
+ ractor_basket_free(b);
+ rb_raise(rb_eRactorClosedError, "The port was already closed");
+ }
+ }
+}
+
+static VALUE
+ractor_send0(rb_execution_context_t *ec, const struct ractor_port *rp, VALUE obj, VALUE move, bool raise_on_error)
+{
+ struct ractor_basket *b = ractor_basket_new(ec, obj, RTEST(move) ? basket_type_move : basket_type_none, false);
+ ractor_send_basket(ec, rp, b, raise_on_error);
+ RB_GC_GUARD(obj);
+ return rp->r->pub.self;
+}
+
+static VALUE
+ractor_send(rb_execution_context_t *ec, const struct ractor_port *rp, VALUE obj, VALUE move)
+{
+ return ractor_send0(ec, rp, obj, move, true);
+}
+
+static VALUE
+ractor_try_send(rb_execution_context_t *ec, const struct ractor_port *rp, VALUE obj, VALUE move)
+{
+ return ractor_send0(ec, rp, obj, move, false);
+}
+
+// Ractor::Selector
+
+struct ractor_selector {
+ struct st_table *ports; // rpv -> rp
+
+};
+
+static int
+ractor_selector_mark_i(st_data_t key, st_data_t val, st_data_t dmy)
+{
+ rb_gc_mark((VALUE)key); // rpv
+
+ return ST_CONTINUE;
+}
+
+static void
+ractor_selector_mark(void *ptr)
+{
+ struct ractor_selector *s = ptr;
+
+ if (s->ports) {
+ st_foreach(s->ports, ractor_selector_mark_i, 0);
+ }
+}
+
+static void
+ractor_selector_free(void *ptr)
+{
+ struct ractor_selector *s = ptr;
+ st_free_table(s->ports);
+ ruby_xfree(ptr);
+}
+
+static size_t
+ractor_selector_memsize(const void *ptr)
+{
+ const struct ractor_selector *s = ptr;
+ size_t size = sizeof(struct ractor_selector);
+ if (s->ports) {
+ size += st_memsize(s->ports);
+ }
+ return size;
+}
+
+static const rb_data_type_t ractor_selector_data_type = {
+ "ractor/selector",
+ {
+ ractor_selector_mark,
+ ractor_selector_free,
+ ractor_selector_memsize,
+ NULL, // update
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
+static struct ractor_selector *
+RACTOR_SELECTOR_PTR(VALUE selv)
+{
+ VM_ASSERT(rb_typeddata_is_kind_of(selv, &ractor_selector_data_type));
+ return (struct ractor_selector *)DATA_PTR(selv);
+}
+
+// Ractor::Selector.new
+
+static VALUE
+ractor_selector_create(VALUE klass)
+{
+ struct ractor_selector *s;
+ VALUE selv = TypedData_Make_Struct(klass, struct ractor_selector, &ractor_selector_data_type, s);
+ s->ports = st_init_numtable(); // TODO
+ return selv;
+}
+
+// Ractor::Selector#add(r)
+
+/*
+ * call-seq:
+ * add(ractor) -> ractor
+ *
+ * Adds _ractor_ to +self+. Raises an exception if _ractor_ is already added.
+ * Returns _ractor_.
+ */
+static VALUE
+ractor_selector_add(VALUE selv, VALUE rpv)
+{
+ if (!ractor_port_p(rpv)) {
+ rb_raise(rb_eArgError, "Not a Ractor::Port object");
+ }
+
+ struct ractor_selector *s = RACTOR_SELECTOR_PTR(selv);
+ const struct ractor_port *rp = RACTOR_PORT_PTR(rpv);
+
+ if (st_lookup(s->ports, (st_data_t)rpv, NULL)) {
+ rb_raise(rb_eArgError, "already added");
+ }
+
+ st_insert(s->ports, (st_data_t)rpv, (st_data_t)rp);
+ RB_OBJ_WRITTEN(selv, Qundef, rpv);
+
+ return selv;
+}
+
+// Ractor::Selector#remove(r)
+
+/* call-seq:
+ * remove(ractor) -> ractor
+ *
+ * Removes _ractor_ from +self+. Raises an exception if _ractor_ is not added.
+ * Returns the removed _ractor_.
+ */
+static VALUE
+ractor_selector_remove(VALUE selv, VALUE rpv)
+{
+ if (!ractor_port_p(rpv)) {
+ rb_raise(rb_eArgError, "Not a Ractor::Port object");
+ }
+
+ struct ractor_selector *s = RACTOR_SELECTOR_PTR(selv);
+
+ if (!st_lookup(s->ports, (st_data_t)rpv, NULL)) {
+ rb_raise(rb_eArgError, "not added yet");
+ }
+
+ st_delete(s->ports, (st_data_t *)&rpv, NULL);
+
+ return selv;
+}
+
+// Ractor::Selector#clear
+
+/*
+ * call-seq:
+ * clear -> self
+ *
+ * Removes all ractors from +self+. Raises +self+.
+ */
+static VALUE
+ractor_selector_clear(VALUE selv)
+{
+ struct ractor_selector *s = RACTOR_SELECTOR_PTR(selv);
+ st_clear(s->ports);
+ return selv;
+}
+
+/*
+ * call-seq:
+ * empty? -> true or false
+ *
+ * Returns +true+ if no ractor is added.
+ */
+static VALUE
+ractor_selector_empty_p(VALUE selv)
+{
+ struct ractor_selector *s = RACTOR_SELECTOR_PTR(selv);
+ return s->ports->num_entries == 0 ? Qtrue : Qfalse;
+}
+
+// Ractor::Selector#wait
+
+struct ractor_selector_wait_data {
+ rb_ractor_t *cr;
+ rb_execution_context_t *ec;
+ bool found;
+ VALUE v;
+ VALUE rpv;
+};
+
+static int
+ractor_selector_wait_i(st_data_t key, st_data_t val, st_data_t data)
+{
+ struct ractor_selector_wait_data *p = (struct ractor_selector_wait_data *)data;
+ const struct ractor_port *rp = (const struct ractor_port *)val;
+
+ VALUE v = ractor_try_receive(p->ec, p->cr, rp);
+
+ if (v != Qundef) {
+ p->found = true;
+ p->v = v;
+ p->rpv = (VALUE)key;
+ return ST_STOP;
+ }
+ else {
+ return ST_CONTINUE;
+ }
+}
+
+static VALUE
+ractor_selector__wait(rb_execution_context_t *ec, VALUE selector)
+{
+ rb_ractor_t *cr = rb_ec_ractor_ptr(ec);
+ struct ractor_selector *s = RACTOR_SELECTOR_PTR(selector);
+
+ struct ractor_selector_wait_data data = {
+ .ec = ec,
+ .cr = cr,
+ .found = false,
+ };
+
+ while (1) {
+ st_foreach(s->ports, ractor_selector_wait_i, (st_data_t)&data);
+
+ if (data.found) {
+ return rb_ary_new_from_args(2, data.rpv, data.v);
+ }
+
+ ractor_wait_receive(ec, cr);
+ }
+}
+
+/*
+ * call-seq:
+ * wait(receive: false, yield_value: undef, move: false) -> [ractor, value]
+ *
+ * Waits until any ractor in _selector_ can be active.
+ */
+static VALUE
+ractor_selector_wait(VALUE selector)
+{
+ return ractor_selector__wait(GET_EC(), selector);
+}
+
+static VALUE
+ractor_selector_new(int argc, VALUE *ractors, VALUE klass)
+{
+ VALUE selector = ractor_selector_create(klass);
+
+ for (int i=0; i<argc; i++) {
+ ractor_selector_add(selector, ractors[i]);
+ }
+
+ return selector;
+}
+
+static VALUE
+ractor_select_internal(rb_execution_context_t *ec, VALUE self, VALUE ports)
+{
+ VALUE selector = ractor_selector_new(RARRAY_LENINT(ports), (VALUE *)RARRAY_CONST_PTR(ports), rb_cRactorSelector);
+ VALUE result = ractor_selector__wait(ec, selector);
+
+ RB_GC_GUARD(selector);
+ RB_GC_GUARD(ports);
+ return result;
+}
+
+#ifndef USE_RACTOR_SELECTOR
+#define USE_RACTOR_SELECTOR 0
+#endif
+
+RUBY_SYMBOL_EXPORT_BEGIN
+void rb_init_ractor_selector(void);
+RUBY_SYMBOL_EXPORT_END
+
+/*
+ * Document-class: Ractor::Selector
+ * :nodoc: currently
+ *
+ * Selects multiple Ractors to be activated.
+ */
+void
+rb_init_ractor_selector(void)
+{
+ rb_cRactorSelector = rb_define_class_under(rb_cRactor, "Selector", rb_cObject);
+ rb_undef_alloc_func(rb_cRactorSelector);
+
+ rb_define_singleton_method(rb_cRactorSelector, "new", ractor_selector_new , -1);
+ rb_define_method(rb_cRactorSelector, "add", ractor_selector_add, 1);
+ rb_define_method(rb_cRactorSelector, "remove", ractor_selector_remove, 1);
+ rb_define_method(rb_cRactorSelector, "clear", ractor_selector_clear, 0);
+ rb_define_method(rb_cRactorSelector, "empty?", ractor_selector_empty_p, 0);
+ rb_define_method(rb_cRactorSelector, "wait", ractor_selector_wait, 0);
+}
+
+static void
+Init_RactorPort(void)
+{
+ rb_cRactorPort = rb_define_class_under(rb_cRactor, "Port", rb_cObject);
+ rb_define_alloc_func(rb_cRactorPort, ractor_port_alloc);
+ rb_define_method(rb_cRactorPort, "initialize", ractor_port_initialize, 0);
+ rb_define_method(rb_cRactorPort, "initialize_copy", ractor_port_initialize_copy, 1);
+
+#if USE_RACTOR_SELECTOR
+ rb_init_ractor_selector();
+#endif
+}
diff --git a/random.c b/random.c
index ea76ea656f..ad7cbca426 100644
--- a/random.c
+++ b/random.c
@@ -131,8 +131,9 @@ typedef struct {
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 void fill_random_seed(uint32_t *seed, size_t cnt, bool try_bytes);
static VALUE make_seed_value(uint32_t *ptr, size_t len);
+#define fill_random_bytes ruby_fill_random_bytes
RB_RANDOM_INTERFACE_DECLARE(rand_mt);
static const rb_random_interface_t random_mt_if = {
@@ -141,18 +142,21 @@ static const rb_random_interface_t random_mt_if = {
};
static rb_random_mt_t *
-rand_mt_start(rb_random_mt_t *r)
+rand_mt_start(rb_random_mt_t *r, VALUE obj)
{
if (!genrand_initialized(&r->mt)) {
r->base.seed = rand_init(&random_mt_if, &r->base, random_seed(Qundef));
+ if (obj) {
+ RB_OBJ_WRITTEN(obj, Qundef, r->base.seed);
+ }
}
return r;
}
static rb_random_t *
-rand_start(rb_random_mt_t *r)
+rand_start(rb_random_mt_t *r, VALUE obj)
{
- return &rand_mt_start(r)->base;
+ return &rand_mt_start(r, obj)->base;
}
static rb_ractor_local_key_t default_rand_key;
@@ -191,7 +195,13 @@ default_rand(void)
static rb_random_mt_t *
default_mt(void)
{
- return rand_mt_start(default_rand());
+ return rand_mt_start(default_rand(), Qfalse);
+}
+
+static rb_random_t *
+default_rand_start(void)
+{
+ return &default_mt()->base;
}
unsigned int
@@ -220,7 +230,7 @@ int_pair_to_real_inclusive(uint32_t a, uint32_t b)
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 && !MSC_VERSION_BEFORE(1300)
+#elif defined HAVE_UINT64_T
uint64_t x = ((uint64_t)a << dig_u) +
(((uint64_t)b + (a >> dig_u)) >> dig_r64);
r = (double)x;
@@ -262,7 +272,7 @@ const rb_data_type_t rb_random_data_type = {
random_free,
random_memsize,
},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
};
#define random_mt_mark rb_random_mark
@@ -283,7 +293,7 @@ static const rb_data_type_t random_mt_type = {
},
&rb_random_data_type,
(void *)&random_mt_if,
- RUBY_TYPED_FREE_IMMEDIATELY
+ RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
};
static rb_random_t *
@@ -292,7 +302,7 @@ get_rnd(VALUE obj)
rb_random_t *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 rand_start((rb_random_mt_t *)ptr, obj);
return ptr;
}
@@ -305,31 +315,24 @@ get_rnd_mt(VALUE obj)
}
static rb_random_t *
-try_get_rnd(VALUE obj)
+try_get_rnd(VALUE obj, const rb_random_interface_t **rng_p)
{
if (obj == rb_cRandom) {
- return rand_start(default_rand());
+ *rng_p = &random_mt_if;
+ return default_rand_start();
}
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);
+ const struct rb_data_type_struct *type = RTYPEDDATA_TYPE(obj);
+ *rng_p = type->data;
+ void *rnd = DATA_PTR(obj);
if (!rnd) {
rb_raise(rb_eArgError, "uninitialized random: %s",
RTYPEDDATA_TYPE(obj)->wrap_struct_name);
}
+ if (type == &random_mt_type) rnd = rand_start(rnd, obj);
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;
- }
- return rb_rand_if(obj);
-}
-
/* :nodoc: */
void
rb_random_base_init(rb_random_t *rnd)
@@ -354,7 +357,7 @@ rand_init_default(const rb_random_interface_t *rng, rb_random_t *rnd)
size_t len = roomof(rng->default_seed_bits, 32);
uint32_t *buf = ALLOCV_N(uint32_t, buf0, len+1);
- fill_random_seed(buf, len);
+ fill_random_seed(buf, len, true);
rng->init(rnd, buf, len);
seed = make_seed_value(buf, len);
explicit_bzero(buf, len * sizeof(*buf));
@@ -377,8 +380,8 @@ rand_init(const rb_random_interface_t *rng, rb_random_t *rnd, VALUE seed)
INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER);
if (sign < 0)
sign = -sign;
- if (len <= 1) {
- rng->init_int32(rnd, len ? buf[0] : 0);
+ if (len == 1) {
+ rng->init_int32(rnd, buf[0]);
}
else {
if (sign != 2 && buf[len-1] == 1) /* remove leading-zero-guard */
@@ -402,8 +405,8 @@ rand_init(const rb_random_interface_t *rng, rb_random_t *rnd, VALUE seed)
static VALUE
random_init(int argc, VALUE *argv, VALUE obj)
{
- rb_random_t *rnd = try_get_rnd(obj);
- const rb_random_interface_t *rng = rb_rand_if(obj);
+ const rb_random_interface_t *rng = NULL;
+ rb_random_t *rnd = try_get_rnd(obj, &rng);
if (!rng) {
rb_raise(rb_eTypeError, "undefined random interface: %s",
@@ -421,10 +424,10 @@ random_init(int argc, VALUE *argv, VALUE obj)
argc = rb_check_arity(argc, 0, 1);
rb_check_frozen(obj);
if (argc == 0) {
- rnd->seed = rand_init_default(rng, rnd);
+ RB_OBJ_WRITE(obj, &rnd->seed, rand_init_default(rng, rnd));
}
else {
- rnd->seed = rand_init(rng, rnd, rb_to_int(argv[0]));
+ RB_OBJ_WRITE(obj, &rnd->seed, rand_init(rng, rnd, rb_to_int(argv[0])));
}
return obj;
}
@@ -437,23 +440,17 @@ random_init(int argc, VALUE *argv, VALUE obj)
# define USE_DEV_URANDOM 0
#endif
-#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
+#if ! defined HAVE_GETRANDOM && defined __linux__ && defined __NR_getrandom
+# ifndef GRND_NONBLOCK
+# define GRND_NONBLOCK 0x0001 /* not defined in musl libc */
+# endif
+# define getrandom(ptr, size, flags) \
+ (ssize_t)syscall(__NR_getrandom, (ptr), (size), (flags))
+# define HAVE_GETRANDOM 1
+#endif
+
+/* fill random bytes by reading random device directly */
+#if USE_DEV_URANDOM
static int
fill_random_bytes_urandom(void *seed, size_t size)
{
@@ -493,15 +490,7 @@ fill_random_bytes_urandom(void *seed, size_t size)
# define fill_random_bytes_urandom(seed, size) -1
#endif
-#if ! defined HAVE_GETRANDOM && defined __linux__ && defined __NR_getrandom
-# ifndef GRND_NONBLOCK
-# define GRND_NONBLOCK 0x0001 /* not defined in musl libc */
-# endif
-# define getrandom(ptr, size, flags) \
- (ssize_t)syscall(__NR_getrandom, (ptr), (size), (flags))
-# define HAVE_GETRANDOM 1
-#endif
-
+/* fill random bytes by library */
#if 0
#elif defined MAC_OS_X_VERSION_10_7 && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7
@@ -519,7 +508,7 @@ fill_random_bytes_urandom(void *seed, size_t size)
# endif
static int
-fill_random_bytes_syscall(void *seed, size_t size, int unused)
+fill_random_bytes_lib(void *seed, size_t size)
{
#if USE_COMMON_RANDOM
CCRNGStatus status = CCRandomGenerateBytes(seed, size);
@@ -546,18 +535,16 @@ fill_random_bytes_syscall(void *seed, size_t size, int unused)
}
return 0;
}
-#elif defined(HAVE_ARC4RANDOM_BUF)
+#elif defined(HAVE_ARC4RANDOM_BUF) && \
+ ((defined(__OpenBSD__) && OpenBSD >= 201411) || \
+ (defined(__NetBSD__) && __NetBSD_Version__ >= 700000000) || \
+ (defined(__FreeBSD__) && __FreeBSD_version >= 1200079))
+// [Bug #15039] arc4random_buf(3) should used only if we know it is fork-safe
static int
-fill_random_bytes_syscall(void *buf, size_t size, int unused)
+fill_random_bytes_lib(void *buf, size_t size)
{
-#if (defined(__OpenBSD__) && OpenBSD >= 201411) || \
- (defined(__NetBSD__) && __NetBSD_Version__ >= 700000000) || \
- (defined(__FreeBSD__) && __FreeBSD_version >= 1200079)
arc4random_buf(buf, size);
return 0;
-#else
- return -1;
-#endif
}
#elif defined(_WIN32)
@@ -566,8 +553,6 @@ fill_random_bytes_syscall(void *buf, size_t size, int unused)
#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;
@@ -576,27 +561,33 @@ static void
release_crypt(void *p)
{
HCRYPTPROV *ptr = p;
- HCRYPTPROV prov = (HCRYPTPROV)ATOMIC_SIZE_EXCHANGE(*ptr, INVALID_HCRYPTPROV);
+ HCRYPTPROV prov = (HCRYPTPROV)ATOMIC_PTR_EXCHANGE(*ptr, INVALID_HCRYPTPROV);
if (prov && prov != INVALID_HCRYPTPROV) {
CryptReleaseContext(prov, 0);
}
}
+static const rb_data_type_t crypt_prov_type = {
+ "HCRYPTPROV",
+ {0, release_crypt,},
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_EMBEDDABLE
+};
+
static int
fill_random_bytes_crypt(void *seed, size_t size)
{
static HCRYPTPROV perm_prov;
HCRYPTPROV prov = perm_prov, old_prov;
if (!prov) {
+ VALUE wrapper = TypedData_Wrap_Struct(0, &crypt_prov_type, 0);
if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) {
prov = INVALID_HCRYPTPROV;
}
- old_prov = (HCRYPTPROV)ATOMIC_SIZE_CAS(perm_prov, 0, prov);
+ old_prov = (HCRYPTPROV)ATOMIC_PTR_CAS(perm_prov, 0, prov);
if (LIKELY(!old_prov)) { /* no other threads acquired */
if (prov != INVALID_HCRYPTPROV) {
-#undef RUBY_UNTYPED_DATA_WARNING
-#define RUBY_UNTYPED_DATA_WARNING 0
- rb_vm_register_global_object(Data_Wrap_Struct(0, 0, release_crypt, &perm_prov));
+ DATA_PTR(wrapper) = (void *)prov;
+ rb_vm_register_global_object(wrapper);
}
}
else { /* another thread acquired */
@@ -633,11 +624,17 @@ fill_random_bytes_bcrypt(void *seed, size_t size)
}
static int
-fill_random_bytes_syscall(void *seed, size_t size, int unused)
+fill_random_bytes_lib(void *seed, size_t size)
{
if (fill_random_bytes_bcrypt(seed, size) == 0) return 0;
return fill_random_bytes_crypt(seed, size);
}
+#else
+# define fill_random_bytes_lib(seed, size) -1
+#endif
+
+/* fill random bytes by dedicated syscall */
+#if 0
#elif defined HAVE_GETRANDOM
static int
fill_random_bytes_syscall(void *seed, size_t size, int need_secure)
@@ -661,6 +658,31 @@ fill_random_bytes_syscall(void *seed, size_t size, int need_secure)
}
return -1;
}
+#elif defined(HAVE_GETENTROPY)
+/*
+ * The Open Group Base Specifications Issue 8 - IEEE Std 1003.1-2024
+ * https://pubs.opengroup.org/onlinepubs/9799919799/functions/getentropy.html
+ *
+ * NOTE: `getentropy`(3) on Linux is implemented using `getrandom`(2),
+ * prefer the latter over this if both are defined.
+ */
+#ifndef GETENTROPY_MAX
+# define GETENTROPY_MAX 256
+#endif
+static int
+fill_random_bytes_syscall(void *seed, size_t size, int need_secure)
+{
+ unsigned char *p = (unsigned char *)seed;
+ while (size) {
+ size_t len = size < GETENTROPY_MAX ? size : GETENTROPY_MAX;
+ if (getentropy(p, len) != 0) {
+ return -1;
+ }
+ p += len;
+ size -= len;
+ }
+ return 0;
+}
#else
# define fill_random_bytes_syscall(seed, size, need_secure) -1
#endif
@@ -670,14 +692,13 @@ ruby_fill_random_bytes(void *seed, size_t size, int need_secure)
{
int ret = fill_random_bytes_syscall(seed, size, need_secure);
if (ret == 0) return ret;
+ if (fill_random_bytes_lib(seed, size) == 0) return 0;
return fill_random_bytes_urandom(seed, size);
}
-#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)
+fill_random_seed(uint32_t *seed, size_t cnt, bool try_bytes)
{
static rb_atomic_t n = 0;
#if defined HAVE_CLOCK_GETTIME
@@ -687,10 +708,12 @@ fill_random_seed(uint32_t *seed, size_t cnt)
#endif
size_t len = cnt * sizeof(*seed);
- memset(seed, 0, len);
-
- fill_random_bytes(seed, len, FALSE);
+ if (try_bytes) {
+ fill_random_bytes(seed, len, FALSE);
+ return;
+ }
+ memset(seed, 0, len);
#if defined HAVE_CLOCK_GETTIME
clock_gettime(CLOCK_REALTIME, &tv);
seed[0] ^= tv.tv_nsec;
@@ -725,8 +748,8 @@ 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); \
+#define with_random_seed(size, add, try_bytes) \
+ for (uint32_t seedbuf[(size)+(add)], loop = (fill_random_seed(seedbuf, (size), try_bytes), 1); \
loop; explicit_bzero(seedbuf, (size)*sizeof(seedbuf[0])), loop = 0)
/*
@@ -741,7 +764,7 @@ static VALUE
random_seed(VALUE _)
{
VALUE v;
- with_random_seed(DEFAULT_SEED_CNT, 1) {
+ with_random_seed(DEFAULT_SEED_CNT, 1, true) {
v = make_seed_value(seedbuf, DEFAULT_SEED_CNT);
}
return v;
@@ -808,6 +831,7 @@ rand_mt_copy(VALUE obj, VALUE orig)
mt = &rnd1->mt;
*rnd1 = *rnd2;
+ RB_OBJ_WRITTEN(obj, Qundef, rnd1->base.seed);
mt->next = mt->state + numberof(mt->state) - mt->left + 1;
return obj;
}
@@ -890,12 +914,12 @@ rand_mt_load(VALUE obj, VALUE dump)
sizeof(*mt->state), 0,
INTEGER_PACK_LSWORD_FIRST|INTEGER_PACK_NATIVE_BYTE_ORDER);
x = NUM2ULONG(left);
- if (x > numberof(mt->state)) {
+ if (x > numberof(mt->state) || x == 0) {
rb_raise(rb_eArgError, "wrong value");
}
mt->left = (unsigned int)x;
mt->next = mt->state + numberof(mt->state) - x + 1;
- rnd->base.seed = rb_to_int(seed);
+ RB_OBJ_WRITE(obj, &rnd->base.seed, rb_to_int(seed));
return obj;
}
@@ -954,7 +978,7 @@ static VALUE
rb_f_srand(int argc, VALUE *argv, VALUE obj)
{
VALUE seed, old;
- rb_random_mt_t *r = rand_mt_start(default_rand());
+ rb_random_mt_t *r = default_mt();
if (rb_check_arity(argc, 0, 1) == 0) {
seed = random_seed(obj);
@@ -1099,17 +1123,18 @@ random_int32(const rb_random_interface_t *rng, rb_random_t *rnd)
unsigned int
rb_random_int32(VALUE obj)
{
- rb_random_t *rnd = try_get_rnd(obj);
+ const rb_random_interface_t *rng;
+ rb_random_t *rnd = try_get_rnd(obj, &rng);
if (!rnd) {
uint32_t x;
obj_random_bytes(obj, &x, sizeof(x));
return (unsigned int)x;
}
- return random_int32(try_rand_if(obj, rnd), rnd);
+ return random_int32(rng, rnd);
}
static double
-random_real(VALUE obj, rb_random_t *rnd, int excl)
+random_real(VALUE obj, const rb_random_interface_t *rng, rb_random_t *rnd, int excl)
{
uint32_t a, b;
@@ -1120,7 +1145,6 @@ random_real(VALUE obj, rb_random_t *rnd, int excl)
b = x[1];
}
else {
- 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);
@@ -1142,7 +1166,8 @@ rb_int_pair_to_real(uint32_t a, uint32_t b, int excl)
double
rb_random_real(VALUE obj)
{
- rb_random_t *rnd = try_get_rnd(obj);
+ const rb_random_interface_t *rng;
+ rb_random_t *rnd = try_get_rnd(obj, &rng);
if (!rnd) {
VALUE v = rb_funcallv(obj, id_rand, 0, 0);
double d = NUM2DBL(v);
@@ -1154,7 +1179,7 @@ rb_random_real(VALUE obj)
}
return d;
}
- return random_real(obj, rnd, TRUE);
+ return random_real(obj, rng, rnd, TRUE);
}
static inline VALUE
@@ -1171,7 +1196,7 @@ ulong_to_num_plus_1(unsigned long n)
}
static unsigned long
-random_ulong_limited(VALUE obj, rb_random_t *rnd, unsigned long limit)
+random_ulong_limited(VALUE obj, const rb_random_interface_t *rng, rb_random_t *rnd, unsigned long limit)
{
if (!limit) return 0;
if (!rnd) {
@@ -1196,13 +1221,14 @@ random_ulong_limited(VALUE obj, rb_random_t *rnd, unsigned long limit)
} while (limit < val);
return val;
}
- return limited_rand(try_rand_if(obj, rnd), rnd, limit);
+ return limited_rand(rng, rnd, limit);
}
unsigned long
rb_random_ulong_limited(VALUE obj, unsigned long limit)
{
- rb_random_t *rnd = try_get_rnd(obj);
+ const rb_random_interface_t *rng;
+ rb_random_t *rnd = try_get_rnd(obj, &rng);
if (!rnd) {
VALUE lim = ulong_to_num_plus_1(limit);
VALUE v = rb_to_int(rb_funcallv_public(obj, id_rand, 1, &lim));
@@ -1215,11 +1241,11 @@ rb_random_ulong_limited(VALUE obj, unsigned long limit)
}
return r;
}
- return limited_rand(try_rand_if(obj, rnd), rnd, limit);
+ return limited_rand(rng, rnd, limit);
}
static VALUE
-random_ulong_limited_big(VALUE obj, rb_random_t *rnd, VALUE vmax)
+random_ulong_limited_big(VALUE obj, const rb_random_interface_t *rng, rb_random_t *rnd, VALUE vmax)
{
if (!rnd) {
VALUE v, vtmp;
@@ -1244,7 +1270,7 @@ random_ulong_limited_big(VALUE obj, rb_random_t *rnd, VALUE vmax)
ALLOCV_END(vtmp);
return v;
}
- return limited_big_rand(try_rand_if(obj, rnd), rnd, vmax);
+ return limited_big_rand(rng, rnd, vmax);
}
static VALUE
@@ -1270,8 +1296,9 @@ rand_bytes(const rb_random_interface_t *rng, rb_random_t *rnd, long n)
static VALUE
random_bytes(VALUE obj, VALUE len)
{
- rb_random_t *rnd = try_get_rnd(obj);
- return rand_bytes(rb_rand_if(obj), rnd, NUM2LONG(rb_to_int(len)));
+ const rb_random_interface_t *rng = NULL;
+ rb_random_t *rnd = try_get_rnd(obj, &rng);
+ return rand_bytes(rng, rnd, NUM2LONG(rb_to_int(len)));
}
void
@@ -1300,11 +1327,12 @@ rb_rand_bytes_int32(rb_random_get_int32_func *get_int32,
VALUE
rb_random_bytes(VALUE obj, long n)
{
- rb_random_t *rnd = try_get_rnd(obj);
+ const rb_random_interface_t *rng;
+ rb_random_t *rnd = try_get_rnd(obj, &rng);
if (!rnd) {
return obj_random_bytes(obj, NULL, n);
}
- return rand_bytes(try_rand_if(obj, rnd), rnd, n);
+ return rand_bytes(rng, rnd, n);
}
/*
@@ -1316,7 +1344,7 @@ rb_random_bytes(VALUE obj, long n)
static VALUE
random_s_bytes(VALUE obj, VALUE len)
{
- rb_random_t *rnd = rand_start(default_rand());
+ rb_random_t *rnd = default_rand_start();
return rand_bytes(&random_mt_if, rnd, NUM2LONG(rb_to_int(len)));
}
@@ -1338,7 +1366,7 @@ random_s_bytes(VALUE obj, VALUE len)
static VALUE
random_s_seed(VALUE obj)
{
- rb_random_mt_t *rnd = rand_mt_start(default_rand());
+ rb_random_mt_t *rnd = default_mt();
return rnd->base.seed;
}
@@ -1356,7 +1384,7 @@ range_values(VALUE vmax, VALUE *begp, VALUE *endp, int *exclp)
}
static VALUE
-rand_int(VALUE obj, rb_random_t *rnd, VALUE vmax, int restrictive)
+rand_int(VALUE obj, const rb_random_interface_t *rng, rb_random_t *rnd, VALUE vmax, int restrictive)
{
/* mt must be initialized */
unsigned long r;
@@ -1368,7 +1396,7 @@ rand_int(VALUE obj, rb_random_t *rnd, VALUE vmax, int restrictive)
if (restrictive) return Qnil;
max = -max;
}
- r = random_ulong_limited(obj, rnd, (unsigned long)max - 1);
+ r = random_ulong_limited(obj, rng, rnd, (unsigned long)max - 1);
return ULONG2NUM(r);
}
else {
@@ -1382,10 +1410,10 @@ rand_int(VALUE obj, rb_random_t *rnd, VALUE vmax, int restrictive)
if (FIXNUM_P(vmax)) {
long max = FIX2LONG(vmax);
if (max == -1) return Qnil;
- r = random_ulong_limited(obj, rnd, max);
+ r = random_ulong_limited(obj, rng, rnd, max);
return LONG2NUM(r);
}
- ret = random_ulong_limited_big(obj, rnd, vmax);
+ ret = random_ulong_limited_big(obj, rng, rnd, vmax);
RB_GC_GUARD(vmax);
return ret;
}
@@ -1429,7 +1457,7 @@ float_value(VALUE v)
}
static inline VALUE
-rand_range(VALUE obj, rb_random_t* rnd, VALUE range)
+rand_range(VALUE obj, const rb_random_interface_t *rng, rb_random_t* rnd, VALUE range)
{
VALUE beg = Qundef, end = Qundef, vmax, v;
int excl = 0;
@@ -1444,7 +1472,7 @@ rand_range(VALUE obj, rb_random_t* rnd, VALUE range)
fixnum:
if (FIXNUM_P(vmax)) {
if ((max = FIX2LONG(vmax) - excl) >= 0) {
- unsigned long r = random_ulong_limited(obj, rnd, (unsigned long)max);
+ unsigned long r = random_ulong_limited(obj, rng, rnd, (unsigned long)max);
v = ULONG2NUM(r);
}
}
@@ -1454,7 +1482,7 @@ rand_range(VALUE obj, rb_random_t* rnd, VALUE range)
excl = 0;
goto fixnum;
}
- v = random_ulong_limited_big(obj, rnd, vmax);
+ v = random_ulong_limited_big(obj, rng, rnd, vmax);
}
}
else if (v = rb_check_to_float(vmax), !NIL_P(v)) {
@@ -1472,7 +1500,7 @@ rand_range(VALUE obj, rb_random_t* rnd, VALUE range)
}
v = Qnil;
if (max > 0.0) {
- r = random_real(obj, rnd, excl);
+ r = random_real(obj, rng, rnd, excl);
if (scale > 1) {
return rb_float_new(+(+(+(r - 0.5) * max) * scale) + mid);
}
@@ -1505,7 +1533,7 @@ rand_range(VALUE obj, rb_random_t* rnd, VALUE range)
return v;
}
-static VALUE rand_random(int argc, VALUE *argv, VALUE obj, rb_random_t *rnd);
+static VALUE rand_random(int argc, VALUE *argv, VALUE obj, const rb_random_interface_t *rng, rb_random_t *rnd);
/*
* call-seq:
@@ -1521,9 +1549,11 @@ static VALUE rand_random(int argc, VALUE *argv, VALUE obj, rb_random_t *rnd);
* prng.rand(100) # => 42
*
* When +max+ is a Float, +rand+ returns a random floating point number
- * between 0.0 and +max+, including 0.0 and excluding +max+.
+ * between 0.0 and +max+, including 0.0 and excluding +max+. Note that it
+ * behaves differently from Kernel.rand.
*
- * prng.rand(1.5) # => 1.4600282860034115
+ * prng.rand(1.5) # => 1.4600282860034115
+ * rand(1.5) # => 0
*
* When +range+ is a Range, +rand+ returns a random number where
* <code>range.member?(number) == true</code>.
@@ -1540,24 +1570,26 @@ 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, try_get_rnd(obj));
+ const rb_random_interface_t *rng = NULL;
+ rb_random_t *rnd = try_get_rnd(obj, &rng);
+ VALUE v = rand_random(argc, argv, obj, rng, rnd);
check_random_number(v, argv);
return v;
}
static VALUE
-rand_random(int argc, VALUE *argv, VALUE obj, rb_random_t *rnd)
+rand_random(int argc, VALUE *argv, VALUE obj, const rb_random_interface_t *rng, rb_random_t *rnd)
{
VALUE vmax, v;
if (rb_check_arity(argc, 0, 1) == 0) {
- return rb_float_new(random_real(obj, rnd, TRUE));
+ return rb_float_new(random_real(obj, rng, rnd, TRUE));
}
vmax = argv[0];
if (NIL_P(vmax)) return Qnil;
if (!RB_FLOAT_TYPE_P(vmax)) {
v = rb_check_to_int(vmax);
- if (!NIL_P(v)) return rand_int(obj, rnd, v, 1);
+ if (!NIL_P(v)) return rand_int(obj, rng, rnd, v, 1);
}
v = rb_check_to_float(vmax);
if (!NIL_P(v)) {
@@ -1566,12 +1598,12 @@ rand_random(int argc, VALUE *argv, VALUE obj, rb_random_t *rnd)
return Qnil;
}
else {
- double r = random_real(obj, rnd, TRUE);
+ double r = random_real(obj, rng, rnd, TRUE);
if (max > 0.0) r *= max;
return rb_float_new(r);
}
}
- return rand_range(obj, rnd, vmax);
+ return rand_range(obj, rng, rnd, vmax);
}
/*
@@ -1589,9 +1621,10 @@ rand_random(int argc, VALUE *argv, VALUE obj, rb_random_t *rnd)
static VALUE
rand_random_number(int argc, VALUE *argv, VALUE obj)
{
- rb_random_t *rnd = try_get_rnd(obj);
- VALUE v = rand_random(argc, argv, obj, rnd);
- if (NIL_P(v)) v = rand_random(0, 0, obj, rnd);
+ const rb_random_interface_t *rng = NULL;
+ rb_random_t *rnd = try_get_rnd(obj, &rng);
+ VALUE v = rand_random(argc, argv, obj, rng, rnd);
+ if (NIL_P(v)) v = rand_random(0, 0, obj, rng, rnd);
else if (!v) invalid_argument(argv[0]);
return v;
}
@@ -1661,25 +1694,28 @@ rand_mt_equal(VALUE self, VALUE other)
* Kernel.srand may be used to ensure that sequences of random numbers are
* reproducible between different runs of a program.
*
- * See also Random.rand.
+ * Related: Random.rand.
+ * rand(100.0) # => 64 (Integer because max.to_i is 100)
+ * Random.rand(100.0) # => 30.315320967824523
*/
static VALUE
rb_f_rand(int argc, VALUE *argv, VALUE obj)
{
VALUE vmax;
- rb_random_t *rnd = rand_start(default_rand());
+ const rb_random_interface_t *rng = &random_mt_if;
+ rb_random_t *rnd = default_rand_start();
if (rb_check_arity(argc, 0, 1) && !NIL_P(vmax = argv[0])) {
- VALUE v = rand_range(obj, rnd, vmax);
+ VALUE v = rand_range(obj, rng, rnd, vmax);
if (v != Qfalse) return v;
vmax = rb_to_int(vmax);
if (vmax != INT2FIX(0)) {
- v = rand_int(obj, rnd, vmax, 0);
+ v = rand_int(obj, rng, rnd, vmax, 0);
if (!NIL_P(v)) return v;
}
}
- return DBL2NUM(random_real(obj, rnd, TRUE));
+ return DBL2NUM(random_real(obj, rng, rnd, TRUE));
}
/*
@@ -1695,7 +1731,7 @@ rb_f_rand(int argc, VALUE *argv, VALUE obj)
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, &random_mt_if, default_rand_start());
check_random_number(v, argv);
return v;
}
@@ -1770,7 +1806,7 @@ Init_RandomSeedCore(void)
*/
struct MT mt;
- with_random_seed(DEFAULT_SEED_CNT, 0) {
+ with_random_seed(DEFAULT_SEED_CNT, 0, false) {
init_by_array(&mt, seedbuf, DEFAULT_SEED_CNT);
}
diff --git a/range.c b/range.c
index a6bf0fca51..fd08a81de7 100644
--- a/range.c
+++ b/range.c
@@ -34,6 +34,7 @@ static ID id_beg, id_end, id_excl;
#define id_succ idSucc
#define id_min idMin
#define id_max idMax
+#define id_plus '+'
static VALUE r_cover_p(VALUE, VALUE, VALUE, VALUE);
@@ -46,6 +47,7 @@ static VALUE r_cover_p(VALUE, VALUE, VALUE, VALUE);
static void
range_init(VALUE range, VALUE beg, VALUE end, VALUE exclude_end)
{
+ // Changing this condition has implications for JITs. If you do, please let maintainers know.
if ((!FIXNUM_P(beg) || !FIXNUM_P(end)) && !NIL_P(beg) && !NIL_P(end)) {
VALUE v;
@@ -152,14 +154,14 @@ recursive_equal(VALUE range, VALUE obj, int recur)
* call-seq:
* self == other -> true or false
*
- * Returns +true+ if and only if:
+ * Returns whether all of the following are true:
*
* - +other+ is a range.
* - <tt>other.begin == self.begin</tt>.
* - <tt>other.end == self.end</tt>.
* - <tt>other.exclude_end? == self.exclude_end?</tt>.
*
- * Otherwise returns +false+.
+ * Examples:
*
* r = (1..5)
* r == (1..5) # => true
@@ -308,6 +310,9 @@ range_each_func(VALUE range, int (*func)(VALUE, VALUE), VALUE arg)
}
}
+// NB: Two functions below (step_i_iter, sym_step_i and step_i) are used only to maintain the
+// backward-compatible behavior for string and symbol ranges with integer steps. If that branch
+// will be removed from range_step, these two can go, too.
static bool
step_i_iter(VALUE arg)
{
@@ -400,72 +405,138 @@ range_step_size(VALUE range, VALUE args, VALUE eobj)
/*
* call-seq:
- * step(n = 1) {|element| ... } -> self
- * step(n = 1) -> enumerator
+ * step(s = 1) {|element| ... } -> self
+ * step(s = 1) -> enumerator/arithmetic_sequence
*
- * Iterates over the elements of +self+.
+ * Iterates over the elements of range in steps of +s+. The iteration is performed
+ * by <tt>+</tt> operator:
*
- * With a block given and no argument,
- * calls the block each element of the range; returns +self+:
+ * (0..6).step(2) { puts _1 } #=> 1..5
+ * # Prints: 0, 2, 4, 6
*
- * 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"]
+ * # Iterate between two dates in step of 1 day (24 hours)
+ * (Time.utc(2022, 2, 24)..Time.utc(2022, 3, 1)).step(24*60*60) { puts _1 }
+ * # Prints:
+ * # 2022-02-24 00:00:00 UTC
+ * # 2022-02-25 00:00:00 UTC
+ * # 2022-02-26 00:00:00 UTC
+ * # 2022-02-27 00:00:00 UTC
+ * # 2022-02-28 00:00:00 UTC
+ * # 2022-03-01 00:00:00 UTC
*
- * With a block given and a positive integer argument +n+ given,
- * calls the block with element +0+, element +n+, element <tt>2n</tt>, and so on:
+ * If <tt> + step</tt> decreases the value, iteration is still performed when
+ * step +begin+ is higher than the +end+:
*
- * 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"]
+ * (0..6).step(-2) { puts _1 }
+ * # Prints nothing
+ *
+ * (6..0).step(-2) { puts _1 }
+ * # Prints: 6, 4, 2, 0
+ *
+ * (Time.utc(2022, 3, 1)..Time.utc(2022, 2, 24)).step(-24*60*60) { puts _1 }
+ * # Prints:
+ * # 2022-03-01 00:00:00 UTC
+ * # 2022-02-28 00:00:00 UTC
+ * # 2022-02-27 00:00:00 UTC
+ * # 2022-02-26 00:00:00 UTC
+ * # 2022-02-25 00:00:00 UTC
+ * # 2022-02-24 00:00:00 UTC
+ *
+ * When the block is not provided, and range boundaries and step are Numeric,
+ * the method returns Enumerator::ArithmeticSequence.
+ *
+ * (1..5).step(2) # => ((1..5).step(2))
+ * (1.0..).step(1.5) #=> ((1.0..).step(1.5))
+ * (..3r).step(1/3r) #=> ((..3/1).step((1/3)))
+ *
+ * Enumerator::ArithmeticSequence can be further used as a value object for iteration
+ * or slicing of collections (see Array#[]). There is a convenience method #% with
+ * behavior similar to +step+ to produce arithmetic sequences more expressively:
+ *
+ * # Same as (1..5).step(2)
+ * (1..5) % 2 # => ((1..5).%(2))
+ *
+ * In a generic case, when the block is not provided, Enumerator is returned:
+ *
+ * ('a'..).step('b') #=> #<Enumerator: "a"..:step("b")>
+ * ('a'..).step('b').take(3) #=> ["a", "ab", "abb"]
+ *
+ * If +s+ is not provided, it is considered +1+ for ranges with numeric +begin+:
+ *
+ * (1..5).step { p _1 }
+ * # Prints: 1, 2, 3, 4, 5
+ *
+ * For non-Numeric ranges, step absence is an error:
*
- * With no block given, returns an enumerator,
- * which will be of class Enumerator::ArithmeticSequence if +self+ is numeric;
- * otherwise of class Enumerator:
+ * (Time.utc(2022, 3, 1)..Time.utc(2022, 2, 24)).step { p _1 }
+ * # raises: step is required for non-numeric ranges (ArgumentError)
*
- * e = (1..5).step(2) # => ((1..5).step(2))
- * e.class # => Enumerator::ArithmeticSequence
- * ('a'..'e').step # => #<Enumerator: ...>
+ * For backward compatibility reasons, String ranges support the iteration both with
+ * string step and with integer step. In the latter case, the iteration is performed
+ * by calculating the next values with String#succ:
+ *
+ * ('a'..'e').step(2) { p _1 }
+ * # Prints: a, c, e
+ * ('a'..'e').step { p _1 }
+ * # Default step 1; prints: a, b, c, d, e
*
- * Related: Range#%.
*/
static VALUE
range_step(int argc, VALUE *argv, VALUE range)
{
- VALUE b, e, step, tmp;
+ VALUE b, e, v, step;
+ int c, dir;
b = RANGE_BEG(range);
e = RANGE_END(range);
- step = (!rb_check_arity(argc, 0, 1) ? INT2FIX(1) : argv[0]);
+ v = b;
+
+ 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);
+ // For backward compatibility reasons (conforming to behavior before 3.4), String/Symbol
+ // supports both old behavior ('a'..).step(1) and new behavior ('a'..).step('a')
+ // Hence the additional conversion/additional checks.
+ const VALUE str_b = rb_check_string_type(b);
+ const VALUE sym_b = SYMBOL_P(b) ? rb_sym2str(b) : Qnil;
+
+ if (rb_check_arity(argc, 0, 1))
+ step = argv[0];
+ else {
+ if (b_num_p || !NIL_P(str_b) || !NIL_P(sym_b) || (NIL_P(b) && e_num_p))
+ step = INT2FIX(1);
+ else
+ rb_raise(rb_eArgError, "step is required for non-numeric ranges");
+ }
- 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 step_num_p = rb_obj_is_kind_of(step, rb_cNumeric);
+
+ if (step_num_p && b_num_p && 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)) {
+ if (!rb_block_given_p()) {
+ // This code is allowed to create even beginless ArithmeticSequence, which can be useful,
+ // e.g., for array slicing:
+ // ary[(..-1) % 3]
+ if (step_num_p && ((b_num_p && (NIL_P(e) || e_num_p)) || (NIL_P(b) && e_num_p))) {
return rb_arith_seq_new(range, ID2SYM(rb_frame_this_func()), argc, argv,
range_step_size, b, e, step, EXCL(range));
}
- RETURN_SIZED_ENUMERATOR(range, argc, argv, range_step_size);
+ // ...but generic Enumerator from beginless range is useless and probably an error.
+ if (NIL_P(b)) {
+ rb_raise(rb_eArgError, "#step for non-numeric beginless ranges is meaningless");
+ }
+
+ RETURN_SIZED_ENUMERATOR(range, argc, argv, 0);
}
- step = check_step_domain(step);
- VALUE iter[2] = {INT2FIX(1), step};
+ if (NIL_P(b)) {
+ rb_raise(rb_eArgError, "#step iteration for beginless ranges is meaningless");
+ }
if (FIXNUM_P(b) && NIL_P(e) && FIXNUM_P(step)) {
+ /* perform summation of numbers in C until their reach Fixnum limit */
long i = FIX2LONG(b), unit = FIX2LONG(step);
do {
rb_yield(LONG2FIX(i));
@@ -473,70 +544,102 @@ range_step(int argc, VALUE *argv, VALUE range)
} while (FIXABLE(i));
b = LONG2NUM(i);
+ /* then switch to Bignum API */
for (;; b = rb_big_plus(b, step))
rb_yield(b);
}
- else if (FIXNUM_P(b) && FIXNUM_P(e) && FIXNUM_P(step)) { /* fixnums are special */
+ else if (FIXNUM_P(b) && FIXNUM_P(e) && FIXNUM_P(step)) {
+ /* fixnums are special: summation is performed in C for performance */
long end = FIX2LONG(e);
long i, unit = FIX2LONG(step);
- if (!EXCL(range))
- end += 1;
- i = FIX2LONG(b);
- while (i < end) {
- rb_yield(LONG2NUM(i));
- if (i + unit < i) break;
- i += unit;
+ if (unit < 0) {
+ if (!EXCL(range))
+ end -= 1;
+ i = FIX2LONG(b);
+ while (i > end) {
+ rb_yield(LONG2NUM(i));
+ i += unit;
+ }
}
+ else {
+ if (!EXCL(range))
+ end += 1;
+ i = FIX2LONG(b);
+ while (i < end) {
+ rb_yield(LONG2NUM(i));
+ i += unit;
+ }
+ }
+ }
+ else if (b_num_p && step_num_p && ruby_float_step(b, e, step, EXCL(range), TRUE)) {
+ /* done */
+ }
+ else if (!NIL_P(str_b) && FIXNUM_P(step)) {
+ // backwards compatibility behavior for String only, when no step/Integer step is passed
+ // See discussion in https://bugs.ruby-lang.org/issues/18368
+
+ VALUE iter[2] = {INT2FIX(1), step};
+ if (NIL_P(e)) {
+ rb_str_upto_endless_each(str_b, step_i, (VALUE)iter);
+ }
+ else {
+ rb_str_upto_each(str_b, e, EXCL(range), step_i, (VALUE)iter);
+ }
}
- else if (SYMBOL_P(b) && (NIL_P(e) || SYMBOL_P(e))) { /* symbols are special */
- b = rb_sym2str(b);
+ else if (!NIL_P(sym_b) && FIXNUM_P(step)) {
+ // same as above: backward compatibility for symbols
+
+ VALUE iter[2] = {INT2FIX(1), step};
+
if (NIL_P(e)) {
- rb_str_upto_endless_each(b, sym_step_i, (VALUE)iter);
+ rb_str_upto_endless_each(sym_b, sym_step_i, (VALUE)iter);
}
else {
- rb_str_upto_each(b, rb_sym2str(e), EXCL(range), sym_step_i, (VALUE)iter);
+ rb_str_upto_each(sym_b, rb_sym2str(e), EXCL(range), sym_step_i, (VALUE)iter);
}
}
- else if (ruby_float_step(b, e, step, EXCL(range), TRUE)) {
- /* done */
+ else if (NIL_P(e)) {
+ // endless range
+ for (;; v = rb_funcall(v, id_plus, 1, step))
+ rb_yield(v);
}
- else if (rb_obj_is_kind_of(b, rb_cNumeric) ||
- !NIL_P(rb_check_to_integer(b, "to_int")) ||
- !NIL_P(rb_check_to_integer(e, "to_int"))) {
- ID op = EXCL(range) ? '<' : idLE;
- VALUE v = b;
- int i = 0;
+ else if (b_num_p && step_num_p && r_less(step, INT2FIX(0)) < 0) {
+ // iterate backwards, for consistency with ArithmeticSequence
+ if (EXCL(range)) {
+ for (; r_less(e, v) < 0; v = rb_funcall(v, id_plus, 1, step))
+ rb_yield(v);
+ }
+ else {
+ for (; (c = r_less(e, v)) <= 0; v = rb_funcall(v, id_plus, 1, step)) {
+ rb_yield(v);
+ if (!c) break;
+ }
+ }
- while (NIL_P(e) || RTEST(rb_funcall(v, op, 1, e))) {
+ }
+ else if ((dir = r_less(b, e)) == 0) {
+ if (!EXCL(range)) {
rb_yield(v);
- i++;
- v = rb_funcall(b, '+', 1, rb_funcall(INT2NUM(i), '*', 1, step));
}
}
- else {
- tmp = rb_check_string_type(b);
-
- if (!NIL_P(tmp)) {
- b = tmp;
- if (NIL_P(e)) {
- rb_str_upto_endless_each(b, step_i, (VALUE)iter);
- }
- else {
- rb_str_upto_each(b, e, EXCL(range), step_i, (VALUE)iter);
- }
+ else if (dir == r_less(b, rb_funcall(b, id_plus, 1, step))) {
+ // Direction of the comparison. We use it as a comparison operator in cycle:
+ // if begin < end, the cycle performs while value < end (iterating forward)
+ // if begin > end, the cycle performs while value > end (iterating backward with
+ // a negative step)
+ // One preliminary addition to check the step moves iteration in the same direction as
+ // from begin to end; otherwise, the iteration should be empty.
+ if (EXCL(range)) {
+ for (; r_less(v, e) == dir; v = rb_funcall(v, id_plus, 1, step))
+ rb_yield(v);
}
else {
- if (!discrete_object_p(b)) {
- rb_raise(rb_eTypeError, "can't iterate from %s",
- rb_obj_classname(b));
+ for (; (c = r_less(v, e)) == dir || c == 0; v = rb_funcall(v, id_plus, 1, step)) {
+ rb_yield(v);
+ if (!c) break;
}
- if (!NIL_P(e))
- range_each_func(range, step_i, (VALUE)iter);
- else
- for (;; b = rb_funcallv(b, id_succ, 0, 0))
- step_i(b, (VALUE)iter);
}
}
return range;
@@ -545,29 +648,24 @@ range_step(int argc, VALUE *argv, VALUE range)
/*
* call-seq:
* %(n) {|element| ... } -> self
- * %(n) -> enumerator
+ * %(n) -> enumerator or arithmetic_sequence
*
- * Iterates over the elements of +self+.
+ * Same as #step (but doesn't provide default value for +n+).
+ * The method is convenient for experssive producing of Enumerator::ArithmeticSequence.
*
- * 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"]
+ * array = [0, 1, 2, 3, 4, 5, 6]
*
- * With no block given, returns an enumerator,
- * which will be of class Enumerator::ArithmeticSequence if +self+ is numeric;
- * otherwise of class Enumerator:
+ * # slice each second element:
+ * seq = (0..) % 2 #=> ((0..).%(2))
+ * array[seq] #=> [0, 2, 4, 6]
+ * # or just
+ * array[(0..) % 2] #=> [0, 2, 4, 6]
*
- * e = (1..5) % 2 # => ((1..5).%(2))
- * e.class # => Enumerator::ArithmeticSequence
- * ('a'..'e') % 2 # => #<Enumerator: ...>
+ * Note that due to operator precedence in Ruby, parentheses are mandatory around range
+ * in this case:
*
- * Related: Range#step.
+ * (0..7) % 2 #=> ((0..7).%(2)) -- as expected
+ * 0..7 % 2 #=> 0..1 -- parsed as 0..(7 % 2)
*/
static VALUE
range_percent_step(VALUE range, VALUE step)
@@ -686,7 +784,7 @@ bsearch_integer_range(VALUE beg, VALUE end, int excl)
*
* Returns an element from +self+ selected by a binary search.
*
- * See {Binary Searching}[rdoc-ref:bsearch.rdoc].
+ * See {Binary Searching}[rdoc-ref:language/bsearch.rdoc].
*
*/
@@ -816,6 +914,10 @@ sym_each_i(VALUE v, VALUE arg)
return each_i(rb_str_intern(v), arg);
}
+#define CANT_ITERATE_FROM(x) \
+ rb_raise(rb_eTypeError, "can't iterate from %s", \
+ rb_obj_classname(x))
+
/*
* call-seq:
* size -> non_negative_integer or Infinity or nil
@@ -852,13 +954,48 @@ range_size(VALUE range)
}
if (!discrete_object_p(b)) {
- rb_raise(rb_eTypeError, "can't iterate from %s",
- rb_obj_classname(b));
+ CANT_ITERATE_FROM(b);
}
return Qnil;
}
+static VALUE
+range_reverse_size(VALUE range)
+{
+ VALUE b = RANGE_BEG(range), e = RANGE_END(range);
+
+ if (NIL_P(e)) {
+ CANT_ITERATE_FROM(e);
+ }
+
+ if (RB_INTEGER_TYPE_P(b)) {
+ if (rb_obj_is_kind_of(e, rb_cNumeric)) {
+ return ruby_num_interval_step_size(b, e, INT2FIX(1), EXCL(range));
+ }
+ else {
+ CANT_ITERATE_FROM(e);
+ }
+ }
+
+ if (NIL_P(b)) {
+ if (RB_INTEGER_TYPE_P(e)) {
+ return DBL2NUM(HUGE_VAL);
+ }
+ else {
+ CANT_ITERATE_FROM(e);
+ }
+ }
+
+ if (!discrete_object_p(b)) {
+ CANT_ITERATE_FROM(e);
+ }
+
+ return Qnil;
+}
+
+#undef CANT_ITERATE_FROM
+
/*
* call-seq:
* to_a -> array
@@ -881,12 +1018,41 @@ range_to_a(VALUE range)
return rb_call_super(0, 0);
}
+/*
+ * call-seq:
+ * to_set -> set
+ *
+ * Returns a set containing the elements in +self+, if a finite collection;
+ * raises an exception otherwise.
+ *
+ * (1..4).to_set # => Set[1, 2, 3, 4]
+ * (1...4).to_set # => Set[1, 2, 3]
+ *
+ * (1..).to_set
+ * # in 'Range#to_set': cannot convert endless range to a set (RangeError)
+ *
+ */
+static VALUE
+range_to_set(VALUE range)
+{
+ if (NIL_P(RANGE_END(range))) {
+ rb_raise(rb_eRangeError, "cannot convert endless range to a set");
+ }
+ return rb_call_super(0, NULL);
+}
+
static VALUE
range_enum_size(VALUE range, VALUE args, VALUE eobj)
{
return range_size(range);
}
+static VALUE
+range_enum_reverse_size(VALUE range, VALUE args, VALUE eobj)
+{
+ return range_reverse_size(range);
+}
+
RBIMPL_ATTR_NORETURN()
static void
range_each_bignum_endless(VALUE beg)
@@ -1133,7 +1299,7 @@ range_reverse_each_negative_bignum_section(VALUE beg, VALUE end)
static VALUE
range_reverse_each(VALUE range)
{
- RETURN_SIZED_ENUMERATOR(range, 0, 0, range_enum_size);
+ RETURN_SIZED_ENUMERATOR(range, 0, 0, range_enum_reverse_size);
VALUE beg = RANGE_BEG(range);
VALUE end = RANGE_END(range);
@@ -1263,12 +1429,29 @@ range_first(int argc, VALUE *argv, VALUE range)
return ary[1];
}
+static bool
+range_basic_each_p(VALUE range)
+{
+ return rb_method_basic_definition_p(CLASS_OF(range), idEach);
+}
+
+static bool
+integer_end_optimizable(VALUE range)
+{
+ VALUE b = RANGE_BEG(range);
+ if (!NIL_P(b) && !RB_INTEGER_TYPE_P(b)) return false;
+ VALUE e = RANGE_END(range);
+ if (!RB_INTEGER_TYPE_P(e)) return false;
+ if (RB_LIKELY(range_basic_each_p(range))) return true;
+ return false;
+}
+
static VALUE
rb_int_range_last(int argc, VALUE *argv, VALUE range)
{
static const VALUE ONE = INT2FIX(1);
- VALUE b, e, len_1, len, nv, ary;
+ VALUE b, e, len_1 = Qnil, len = Qnil, nv, ary;
int x;
long n;
@@ -1276,20 +1459,28 @@ rb_int_range_last(int argc, VALUE *argv, VALUE range)
b = RANGE_BEG(range);
e = RANGE_END(range);
- RUBY_ASSERT(RB_INTEGER_TYPE_P(b) && RB_INTEGER_TYPE_P(e));
+ RUBY_ASSERT(NIL_P(b) || RB_INTEGER_TYPE_P(b), "b=%"PRIsVALUE, rb_obj_class(b));
+ RUBY_ASSERT(RB_INTEGER_TYPE_P(e), "e=%"PRIsVALUE, rb_obj_class(e));
x = EXCL(range);
- len_1 = rb_int_minus(e, b);
- if (x) {
- e = rb_int_minus(e, ONE);
- len = len_1;
+ if (!NIL_P(b)) {
+ len_1 = rb_int_minus(e, b);
+ if (x) {
+ e = rb_int_minus(e, ONE);
+ len = len_1;
+ }
+ else {
+ len = rb_int_plus(len_1, ONE);
+ }
}
else {
- len = rb_int_plus(len_1, ONE);
+ if (x) {
+ e = rb_int_minus(e, ONE);
+ }
}
- if (FIXNUM_ZERO_P(len) || rb_num_negative_p(len)) {
+ if (!NIL_P(len) && (FIXNUM_ZERO_P(len) || rb_num_negative_p(len))) {
return rb_ary_new_capa(0);
}
@@ -1300,7 +1491,7 @@ rb_int_range_last(int argc, VALUE *argv, VALUE range)
}
nv = LONG2NUM(n);
- if (RTEST(rb_int_gt(nv, len))) {
+ if (!NIL_P(b) && RTEST(rb_int_gt(nv, len))) {
nv = len;
n = NUM2LONG(nv);
}
@@ -1354,17 +1545,11 @@ rb_int_range_last(int argc, VALUE *argv, VALUE range)
static VALUE
range_last(int argc, VALUE *argv, VALUE range)
{
- VALUE b, e;
-
if (NIL_P(RANGE_END(range))) {
rb_raise(rb_eRangeError, "cannot get the last element of endless range");
}
if (argc == 0) return RANGE_END(range);
-
- b = RANGE_BEG(range);
- e = RANGE_END(range);
- if (RB_INTEGER_TYPE_P(b) && RB_INTEGER_TYPE_P(e) &&
- RB_LIKELY(rb_method_basic_definition_p(rb_cRange, idEach))) {
+ if (integer_end_optimizable(range)) {
return rb_int_range_last(argc, argv, range);
}
return rb_ary_last(argc, argv, rb_Array(range));
@@ -1379,7 +1564,7 @@ range_last(int argc, VALUE *argv, VALUE range)
* min(n) {|a, b| ... } -> array
*
* Returns the minimum value in +self+,
- * using method <tt><=></tt> or a given block for comparison.
+ * using method <tt>#<=></tt> or a given block for comparison.
*
* With no argument and no block given,
* returns the minimum-valued element of +self+.
@@ -1487,7 +1672,7 @@ range_min(int argc, VALUE *argv, VALUE range)
* max(n) {|a, b| ... } -> array
*
* Returns the maximum value in +self+,
- * using method <tt><=></tt> or a given block for comparison.
+ * using method <tt>#<=></tt> or a given block for comparison.
*
* With no argument and no block given,
* returns the maximum-valued element of +self+.
@@ -1572,12 +1757,27 @@ range_max(int argc, VALUE *argv, VALUE range)
VALUE b = RANGE_BEG(range);
- if (rb_block_given_p() || (EXCL(range) && !nm) || argc) {
+ if (rb_block_given_p() || (EXCL(range) && !nm)) {
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 if (argc) {
+ VALUE ary[2];
+ ID reverse_each;
+ CONST_ID(reverse_each, "reverse_each");
+ rb_scan_args(argc, argv, "1", &ary[0]);
+ ary[1] = rb_ary_new2(NUM2LONG(ary[0]));
+ rb_block_call(range, reverse_each, 0, 0, first_i, (VALUE)ary);
+ return ary[1];
+#if 0
+ if (integer_end_optimizable(range)) {
+ return rb_int_range_last(argc, argv, range, true);
+ }
+ return rb_ary_reverse(rb_ary_last(argc, argv, rb_Array(range)));
+#endif
+ }
else {
int c = NIL_P(b) ? -1 : OPTIMIZED_CMP(b, e);
@@ -1588,13 +1788,13 @@ range_max(int argc, VALUE *argv, VALUE range)
rb_raise(rb_eTypeError, "cannot exclude non Integer end value");
}
if (c == 0) return Qnil;
- if (!RB_INTEGER_TYPE_P(b)) {
+ if (!NIL_P(b) && !RB_INTEGER_TYPE_P(b)) {
rb_raise(rb_eTypeError, "cannot exclude end value with non Integer begin value");
}
if (FIXNUM_P(e)) {
return LONG2NUM(FIX2LONG(e) - 1);
}
- return rb_funcall(e, '-', 1, INT2FIX(1));
+ return rb_int_minus(e,INT2FIX(1));
}
return e;
}
@@ -1606,10 +1806,10 @@ range_max(int argc, VALUE *argv, VALUE range)
* minmax {|a, b| ... } -> [object, object]
*
* Returns a 2-element array containing the minimum and maximum value in +self+,
- * either according to comparison method <tt><=></tt> or a given block.
+ * either according to comparison method <tt>#<=></tt> or a given block.
*
* With no block given, returns the minimum and maximum values,
- * using <tt><=></tt> for comparison:
+ * using <tt>#<=></tt> for comparison:
*
* (1..4).minmax # => [1, 4]
* (1...4).minmax # => [1, 3]
@@ -1854,10 +2054,9 @@ VALUE rb_str_include_range_p(VALUE beg, VALUE end, VALUE val, VALUE exclusive);
/*
* call-seq:
- * self === object -> true or false
+ * self === other -> true or false
*
- * Returns +true+ if +object+ is between <tt>self.begin</tt> and <tt>self.end</tt>.
- * +false+ otherwise:
+ * Returns whether +other+ is between <tt>self.begin</tt> and <tt>self.end</tt>:
*
* (1..4) === 2 # => true
* (1..4) === 5 # => false
@@ -2059,7 +2258,7 @@ static int r_cover_range_p(VALUE range, VALUE beg, VALUE end, VALUE val);
* Returns +false+ if either:
*
* - The begin value of +self+ is larger than its end value.
- * - An internal call to <tt><=></tt> returns +nil+;
+ * - An internal call to <tt>#<=></tt> returns +nil+;
* that is, the operands are not comparable.
*
* Beginless ranges cover all values of the same type before the end,
@@ -2307,7 +2506,7 @@ empty_region_p(VALUE beg, VALUE end, int excl)
*
* (1..3).overlap?(1) # TypeError
*
- * Returns +false+ if an internal call to <tt><=></tt> returns +nil+;
+ * Returns +false+ if an internal call to <tt>#<=></tt> returns +nil+;
* that is, the operands are not comparable.
*
* (1..3).overlap?('a'..'d') # => false
@@ -2385,7 +2584,7 @@ range_overlap(VALUE range, VALUE other)
/* if both begin values are equal, no more comparisons needed */
if (rb_cmpint(cmp, self_beg, other_beg) == 0) return Qtrue;
}
- else if (NIL_P(self_beg) && NIL_P(other_beg)) {
+ else if (NIL_P(self_beg) && !NIL_P(self_end) && NIL_P(other_beg) && !NIL_P(other_end)) {
VALUE cmp = rb_funcall(self_end, id_cmp, 1, other_end);
return RBOOL(!NIL_P(cmp));
}
@@ -2410,7 +2609,7 @@ range_overlap(VALUE range, VALUE other)
* (1...4).to_a # => [1, 2, 3]
* ('a'...'d').to_a # => ["a", "b", "c"]
*
- * A range may be created using method Range.new:
+ * - Method Range.new:
*
* # Ranges that by default include the given end value.
* Range.new(1, 4).to_a # => [1, 2, 3, 4]
@@ -2438,10 +2637,14 @@ range_overlap(VALUE range, VALUE other)
* A beginless range may be used to slice an array:
*
* a = [1, 2, 3, 4]
- * r = (..2) # => nil...2
- * a[r] # => [1, 2]
+ * # Include the third array element in the slice
+ * r = (..2) # => nil..2
+ * a[r] # => [1, 2, 3]
+ * # Exclude the third array element from the slice
+ * r = (...2) # => nil...2
+ * a[r] # => [1, 2]
*
- * \Method +each+ for a beginless range raises an exception.
+ * Method +each+ for a beginless range raises an exception.
*
* == Endless Ranges
*
@@ -2471,7 +2674,7 @@ range_overlap(VALUE range, VALUE other)
* r = (2..) # => 2..
* a[r] # => [3, 4]
*
- * \Method +each+ for an endless range calls the given block indefinitely:
+ * Method +each+ for an endless range calls the given block indefinitely:
*
* a = []
* r = (1..)
@@ -2481,19 +2684,19 @@ range_overlap(VALUE range, VALUE other)
* end
* a # => [2, 4, 6, 8, 10]
*
- * A range can be both beginless and endless. For literal beginless, endless
+ * A range can be both beginless and endless. For literal beginless, endless
* ranges, at least the beginning or end of the range must be given as an
* explicit nil value. It is recommended to use an explicit nil beginning and
- * implicit nil end, since that is what Ruby uses for Range#inspect:
+ * end, since that is what Ruby uses for Range#inspect:
*
- * (nil..) # => (nil..)
- * (..nil) # => (nil..)
- * (nil..nil) # => (nil..)
+ * (nil..) # => (nil..nil)
+ * (..nil) # => (nil..nil)
+ * (nil..nil) # => (nil..nil)
*
* == Ranges and Other Classes
*
* An object may be put into a range if its class implements
- * instance method <tt><=></tt>.
+ * instance method <tt>#<=></tt>.
* Ruby core classes that do so include Array, Complex, File::Stat,
* Float, Integer, Kernel, Module, Numeric, Rational, String, Symbol, and Time.
*
@@ -2525,15 +2728,15 @@ range_overlap(VALUE range, VALUE other)
* == Ranges and User-Defined Classes
*
* A user-defined class that is to be used in a range
- * must implement instance <tt><=></tt>;
+ * must implement instance method <tt>#<=></tt>;
* see Integer#<=>.
* To make iteration available, it must also implement
* instance method +succ+; see Integer#succ.
*
- * The class below implements both <tt><=></tt> and +succ+,
+ * The class below implements both <tt>#<=></tt> 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 <tt>==</tt> method is defined in terms of <tt><=></tt>.
+ * so the <tt>==</tt> method is defined in terms of <tt>#<=></tt>.
*
* # Represent a string of 'X' characters.
* class Xs
@@ -2563,7 +2766,7 @@ range_overlap(VALUE range, VALUE other)
*
* == What's Here
*
- * First, what's elsewhere. \Class \Range:
+ * First, what's elsewhere. Class \Range:
*
* - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
* - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here],
@@ -2664,6 +2867,7 @@ Init_Range(void)
rb_define_method(rb_cRange, "minmax", range_minmax, 0);
rb_define_method(rb_cRange, "size", range_size, 0);
rb_define_method(rb_cRange, "to_a", range_to_a, 0);
+ rb_define_method(rb_cRange, "to_set", range_to_set, 0);
rb_define_method(rb_cRange, "entries", range_to_a, 0);
rb_define_method(rb_cRange, "to_s", range_to_s, 0);
rb_define_method(rb_cRange, "inspect", range_inspect, 0);
diff --git a/rational.c b/rational.c
index 014cbb6c6a..51078f81ad 100644
--- a/rational.c
+++ b/rational.c
@@ -22,9 +22,6 @@
# define USE_GMP 0
#endif
#endif
-#if USE_GMP
-#include <gmp.h>
-#endif
#include "id.h"
#include "internal.h"
@@ -36,6 +33,15 @@
#include "internal/rational.h"
#include "ruby_assert.h"
+#if USE_GMP
+RBIMPL_WARNING_PUSH()
+# ifdef _MSC_VER
+RBIMPL_WARNING_IGNORED(4146) /* for mpn_neg() */
+# endif
+# include <gmp.h>
+RBIMPL_WARNING_POP()
+#endif
+
#define ZERO INT2FIX(0)
#define ONE INT2FIX(1)
#define TWO INT2FIX(2)
@@ -603,9 +609,13 @@ nurat_denominator(VALUE self)
/*
* call-seq:
- * -rat -> rational
+ * -self -> rational
+ *
+ * Returns +self+, negated:
+ *
+ * -(1/3r) # => (-1/3)
+ * -(-1/3r) # => (1/3)
*
- * Negates +rat+.
*/
VALUE
rb_rational_uminus(VALUE self)
@@ -709,16 +719,27 @@ f_addsub(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k)
static double nurat_to_double(VALUE self);
/*
- * call-seq:
- * rat + numeric -> numeric
+ * call-seq:
+ * self + other -> numeric
+ *
+ * Returns the sum of +self+ and +other+:
+ *
+ * Rational(2, 3) + 0 # => (2/3)
+ * Rational(2, 3) + 1 # => (5/3)
+ * Rational(2, 3) + -1 # => (-1/3)
+ *
+ * Rational(2, 3) + Complex(1, 0) # => ((5/3)+0i)
+ *
+ * Rational(2, 3) + Rational(1, 1) # => (5/3)
+ * Rational(2, 3) + Rational(3, 2) # => (13/6)
+ * Rational(2, 3) + Rational(3.0, 2.0) # => (13/6)
+ * Rational(2, 3) + Rational(3.1, 2.1) # => (30399297484750849/14186338826217063)
*
- * Performs addition.
+ * For a computation involving Floats, the result may be inexact (see Float#+):
+ *
+ * Rational(2, 3) + 1.0 # => 1.6666666666666665
+ * Rational(2, 3) + Complex(1.0, 0.0) # => (1.6666666666666665+0.0i)
*
- * Rational(2, 3) + Rational(2, 3) #=> (4/3)
- * Rational(900) + Rational(1) #=> (901/1)
- * Rational(-2, 9) + Rational(-9, 2) #=> (-85/18)
- * Rational(9, 8) + 4 #=> (41/8)
- * Rational(20, 9) + 9.8 #=> 12.022222222222222
*/
VALUE
rb_rational_plus(VALUE self, VALUE other)
@@ -751,9 +772,9 @@ rb_rational_plus(VALUE self, VALUE other)
/*
* call-seq:
- * rat - numeric -> numeric
+ * self - other -> numeric
*
- * Performs subtraction.
+ * Returns the difference of +self+ and +other+:
*
* Rational(2, 3) - Rational(2, 3) #=> (0/1)
* Rational(900) - Rational(1) #=> (899/1)
@@ -847,15 +868,17 @@ f_muldiv(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k)
/*
* call-seq:
- * rat * numeric -> numeric
+ * self * other -> numeric
+ *
+ * Returns the numeric product of +self+ and +other+:
*
- * Performs multiplication.
+ * Rational(9, 8) * 4 #=> (9/2)
+ * Rational(20, 9) * 9.8 #=> 21.77777777777778
+ * Rational(9, 8) * Complex(1, 2) # => ((9/8)+(9/4)*i)
+ * Rational(2, 3) * Rational(2, 3) #=> (4/9)
+ * Rational(900) * Rational(1) #=> (900/1)
+ * Rational(-2, 9) * Rational(-9, 2) #=> (1/1)
*
- * Rational(2, 3) * Rational(2, 3) #=> (4/9)
- * Rational(900) * Rational(1) #=> (900/1)
- * Rational(-2, 9) * Rational(-9, 2) #=> (1/1)
- * Rational(9, 8) * 4 #=> (9/2)
- * Rational(20, 9) * 9.8 #=> 21.77777777777778
*/
VALUE
rb_rational_mul(VALUE self, VALUE other)
@@ -888,10 +911,9 @@ rb_rational_mul(VALUE self, VALUE other)
/*
* call-seq:
- * rat / numeric -> numeric
- * rat.quo(numeric) -> numeric
+ * self / other -> numeric
*
- * Performs division.
+ * Returns the quotient of +self+ and +other+:
*
* Rational(2, 3) / Rational(2, 3) #=> (1/1)
* Rational(900) / Rational(1) #=> (900/1)
@@ -965,9 +987,9 @@ nurat_fdiv(VALUE self, VALUE other)
/*
* call-seq:
- * rat ** numeric -> numeric
+ * self ** exponent -> numeric
*
- * Performs exponentiation.
+ * Returns +self+ raised to the power +exponent+:
*
* Rational(2) ** Rational(3) #=> (8/1)
* Rational(10) ** -2 #=> (1/100)
@@ -1042,8 +1064,7 @@ rb_rational_pow(VALUE self, VALUE other)
}
}
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);
+ rb_raise(rb_eArgError, "exponent is too large");
}
else if (RB_FLOAT_TYPE_P(other) || RB_TYPE_P(other, T_RATIONAL)) {
return rb_float_pow(nurat_to_f(self), other);
@@ -1056,20 +1077,30 @@ rb_rational_pow(VALUE self, VALUE other)
/*
* call-seq:
- * rational <=> numeric -> -1, 0, +1, or nil
+ * self <=> other -> -1, 0, 1, or nil
+ *
+ * Compares +self+ and +other+.
+ *
+ * Returns:
+ *
+ * - +-1+, if +self+ is less than +other+.
+ * - +0+, if the two values are the same.
+ * - +1+, if +self+ is greater than +other+.
+ * - +nil+, if the two values are incomparable.
*
- * Returns -1, 0, or +1 depending on whether +rational+ is
- * less than, equal to, or greater than +numeric+.
+ * Examples:
*
- * +nil+ is returned if the two values are incomparable.
+ * Rational(2, 3) <=> Rational(4, 3) # => -1
+ * Rational(2, 1) <=> Rational(2, 1) # => 0
+ * Rational(2, 1) <=> 2 # => 0
+ * Rational(2, 1) <=> 2.0 # => 0
+ * Rational(2, 1) <=> Complex(2, 0) # => 0
+ * Rational(4, 3) <=> Rational(2, 3) # => 1
+ * Rational(4, 3) <=> :foo # => nil
*
- * Rational(2, 3) <=> Rational(2, 3) #=> 0
- * Rational(5) <=> 5 #=> 0
- * Rational(2, 3) <=> Rational(1, 3) #=> 1
- * Rational(1, 3) <=> 1 #=> -1
- * Rational(1, 3) <=> 0.3 #=> 1
+ * \Class \Rational includes module Comparable,
+ * each of whose methods uses Rational#<=> for comparison.
*
- * Rational(1, 3) <=> "0.3" #=> nil
*/
VALUE
rb_rational_cmp(VALUE self, VALUE other)
@@ -1114,9 +1145,9 @@ rb_rational_cmp(VALUE self, VALUE other)
/*
* call-seq:
- * rat == object -> true or false
+ * self == other -> true or false
*
- * Returns +true+ if +rat+ equals +object+ numerically.
+ * Returns whether +self+ and +other+ are numerically equal:
*
* Rational(2, 3) == Rational(2, 3) #=> true
* Rational(5) == 5 #=> true
@@ -2104,39 +2135,6 @@ rb_float_denominator(VALUE self)
/*
* call-seq:
- * to_r -> (0/1)
- *
- * Returns zero as a Rational:
- *
- * nil.to_r # => (0/1)
- *
- */
-static VALUE
-nilclass_to_r(VALUE self)
-{
- return rb_rational_new1(INT2FIX(0));
-}
-
-/*
- * call-seq:
- * rationalize(eps = nil) -> (0/1)
- *
- * Returns zero as a Rational:
- *
- * nil.rationalize # => (0/1)
- *
- * Argument +eps+ is ignored.
- *
- */
-static VALUE
-nilclass_rationalize(int argc, VALUE *argv, VALUE self)
-{
- rb_check_arity(argc, 0, 1);
- return nilclass_to_r(self);
-}
-
-/*
- * call-seq:
* int.to_r -> rational
*
* Returns the value as a rational.
@@ -2495,31 +2493,32 @@ string_to_r_strict(VALUE self, int raise)
/*
* call-seq:
- * str.to_r -> rational
- *
- * Returns the result of interpreting leading characters in +str+
- * as a rational. Leading whitespace and extraneous characters
- * past the end of a valid number are ignored.
- * Digit sequences can be separated by an underscore.
- * If there is not a valid number at the start of +str+,
- * zero is returned. This method never raises an exception.
- *
- * ' 2 '.to_r #=> (2/1)
- * '300/2'.to_r #=> (150/1)
- * '-9.2'.to_r #=> (-46/5)
- * '-9.2e2'.to_r #=> (-920/1)
- * '1_234_567'.to_r #=> (1234567/1)
- * '21 June 09'.to_r #=> (21/1)
- * '21/06/09'.to_r #=> (7/2)
- * 'BWV 1079'.to_r #=> (0/1)
- *
- * NOTE: "0.3".to_r isn't the same as 0.3.to_r. The former is
- * equivalent to "3/10".to_r, but the latter isn't so.
+ * str.to_r -> rational
*
- * "0.3".to_r == 3/10r #=> true
- * 0.3.to_r == 3/10r #=> false
+ * Returns the result of interpreting leading characters in +self+ as a rational value:
+ *
+ * '123'.to_r # => (123/1) # Integer literal.
+ * '300/2'.to_r # => (150/1) # Rational literal.
+ * '-9.2'.to_r # => (-46/5) # Float literal.
+ * '-9.2e2'.to_r # => (-920/1) # Float literal.
+ *
+ * Ignores leading and trailing whitespace, and trailing non-numeric characters:
+ *
+ * ' 2 '.to_r # => (2/1)
+ * '21-Jun-09'.to_r # => (21/1)
+ *
+ * Returns \Rational zero if there are no leading numeric characters.
+ *
+ * 'BWV 1079'.to_r # => (0/1)
+ *
+ * NOTE: <tt>'0.3'.to_r</tt> is equivalent to <tt>3/10r</tt>,
+ * but is different from <tt>0.3.to_r</tt>:
+ *
+ * '0.3'.to_r # => (3/10)
+ * 3/10r # => (3/10)
+ * 0.3.to_r # => (5404319552844595/18014398509481984)
*
- * See also Kernel#Rational.
+ * Related: see {Converting to Non-String}[rdoc-ref:String@Converting+to+Non--5CString].
*/
static VALUE
string_to_r(VALUE self)
@@ -2710,7 +2709,7 @@ nurat_s_convert(int argc, VALUE *argv, VALUE klass)
*
* You can convert certain objects to Rationals with:
*
- * - \Method #Rational.
+ * - Method #Rational.
*
* Examples
*
@@ -2818,8 +2817,6 @@ Init_Rational(void)
rb_define_method(rb_cFloat, "numerator", rb_float_numerator, 0);
rb_define_method(rb_cFloat, "denominator", rb_float_denominator, 0);
- rb_define_method(rb_cNilClass, "to_r", nilclass_to_r, 0);
- rb_define_method(rb_cNilClass, "rationalize", nilclass_rationalize, -1);
rb_define_method(rb_cInteger, "to_r", integer_to_r, 0);
rb_define_method(rb_cInteger, "rationalize", integer_rationalize, -1);
rb_define_method(rb_cFloat, "to_r", float_to_r, 0);
diff --git a/re.c b/re.c
index c8940ff887..82e9407a0a 100644
--- a/re.c
+++ b/re.c
@@ -17,6 +17,7 @@
#include "hrtime.h"
#include "internal.h"
#include "internal/encoding.h"
+#include "internal/error.h"
#include "internal/hash.h"
#include "internal/imemo.h"
#include "internal/re.h"
@@ -28,6 +29,7 @@
#include "ruby/encoding.h"
#include "ruby/re.h"
#include "ruby/util.h"
+#include "ractor_core.h"
VALUE rb_eRegexpError, rb_eRegexpTimeoutError;
@@ -289,11 +291,6 @@ rb_memsearch(const void *x0, long m, const void *y0, long n, rb_encoding *enc)
#define KCODE_FIXED FL_USER4
-#define ARG_REG_OPTION_MASK \
- (ONIG_OPTION_IGNORECASE|ONIG_OPTION_MULTILINE|ONIG_OPTION_EXTEND)
-#define ARG_ENCODING_FIXED 16
-#define ARG_ENCODING_NONE 32
-
static int
char_to_option(int c)
{
@@ -961,7 +958,7 @@ make_regexp(const char *s, long len, rb_encoding *enc, int flags, onig_errmsg_bu
* * <code>$'</code> is Regexp.last_match<code>.post_match</code>;
* * <code>$+</code> is Regexp.last_match<code>[ -1 ]</code> (the last capture).
*
- * See also "Special global variables" section in Regexp documentation.
+ * See also Regexp@Global+Variables.
*/
VALUE rb_cMatch;
@@ -1017,6 +1014,7 @@ update_char_offset(VALUE match)
char *s, *p, *q;
rb_encoding *enc;
pair_t *pairs;
+ VALUE pairs_obj = Qnil;
if (rm->char_offset_num_allocated)
return;
@@ -1038,7 +1036,7 @@ update_char_offset(VALUE match)
return;
}
- pairs = ALLOCA_N(pair_t, num_regs*2);
+ pairs = RB_ALLOCV_N(pair_t, pairs_obj, num_regs * 2);
num_pos = 0;
for (i = 0; i < num_regs; i++) {
if (BEG(i) < 0)
@@ -1073,6 +1071,8 @@ update_char_offset(VALUE match)
found = bsearch(&key, pairs, num_pos, sizeof(pair_t), pair_byte_cmp);
rm->char_offset[i].end = found->char_pos;
}
+
+ RB_ALLOCV_END(pairs_obj);
}
static VALUE
@@ -1298,6 +1298,54 @@ match_byteoffset(VALUE match, VALUE n)
/*
* call-seq:
+ * bytebegin(n) -> integer
+ * bytebegin(name) -> integer
+ *
+ * :include: doc/matchdata/bytebegin.rdoc
+ *
+ */
+
+static VALUE
+match_bytebegin(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;
+ return LONG2NUM(BEG(i));
+}
+
+
+/*
+ * call-seq:
+ * byteend(n) -> integer
+ * byteend(name) -> integer
+ *
+ * :include: doc/matchdata/byteend.rdoc
+ *
+ */
+
+static VALUE
+match_byteend(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;
+ return LONG2NUM(END(i));
+}
+
+
+/*
+ * call-seq:
* begin(n) -> integer
* begin(name) -> integer
*
@@ -1473,7 +1521,7 @@ match_set_string(VALUE m, VALUE string, long pos, long len)
rmatch->regs.end[0] = pos + len;
}
-void
+VALUE
rb_backref_set_string(VALUE string, long pos, long len)
{
VALUE match = rb_backref_get();
@@ -1482,6 +1530,7 @@ rb_backref_set_string(VALUE string, long pos, long len)
}
match_set_string(match, string, pos, len);
rb_backref_set(match);
+ return match;
}
/*
@@ -1617,7 +1666,7 @@ rb_reg_prepare_re(VALUE re, VALUE str)
RSTRING_GETMEM(unescaped, ptr, len);
/* If there are no other users of this regex, then we can directly overwrite it. */
- if (RREGEXP(re)->usecnt == 0) {
+ if (ruby_single_main_ractor && RREGEXP(re)->usecnt == 0) {
regex_t tmp_reg;
r = onig_new_without_alloc(&tmp_reg, (UChar *)ptr, (UChar *)(ptr + len),
reg->options, enc,
@@ -1671,10 +1720,16 @@ rb_reg_onig_match(VALUE re, VALUE str,
if (result < 0) {
onig_region_free(regs, 0);
- if (result != ONIG_MISMATCH) {
+ switch (result) {
+ case ONIG_MISMATCH:
+ break;
+ case ONIGERR_TIMEOUT:
+ rb_raise(rb_eRegexpTimeoutError, "regexp match timeout");
+ default: {
onig_errmsg_buffer err = "";
onig_error_code_to_str((UChar*)err, (int)result);
rb_reg_raise(err, re);
+ }
}
}
@@ -1735,23 +1790,6 @@ reg_onig_search(regex_t *reg, VALUE str, struct re_registers *regs, void *args_p
ONIG_OPTION_NONE);
}
-struct rb_reg_onig_match_args {
- VALUE re;
- VALUE str;
- struct reg_onig_search_args args;
- struct re_registers regs;
-
- OnigPosition result;
-};
-
-static VALUE
-rb_reg_onig_match_try(VALUE value_args)
-{
- struct rb_reg_onig_match_args *args = (struct rb_reg_onig_match_args *)value_args;
- args->result = rb_reg_onig_match(args->re, args->str, reg_onig_search, &args->args, &args->regs);
- return Qnil;
-}
-
/* returns byte offset */
static long
rb_reg_search_set_match(VALUE re, VALUE str, long pos, int reverse, int set_backref_str, VALUE *set_match)
@@ -1762,41 +1800,45 @@ rb_reg_search_set_match(VALUE re, VALUE str, long pos, int reverse, int set_back
return -1;
}
- struct rb_reg_onig_match_args args = {
- .re = re,
- .str = str,
- .args = {
- .pos = pos,
- .range = reverse ? 0 : len,
- },
- .regs = {0}
+ struct reg_onig_search_args args = {
+ .pos = pos,
+ .range = reverse ? 0 : len,
};
+ struct re_registers regs = {0};
- /* If there is a timeout set, then rb_reg_onig_match could raise a
- * Regexp::TimeoutError so we want to protect it from leaking memory. */
- if (rb_reg_match_time_limit) {
- int state;
- rb_protect(rb_reg_onig_match_try, (VALUE)&args, &state);
- if (state) {
- onig_region_free(&args.regs, false);
- rb_jump_tag(state);
- }
- }
- else {
- rb_reg_onig_match_try((VALUE)&args);
- }
+ OnigPosition result = rb_reg_onig_match(re, str, reg_onig_search, &args, &regs);
- if (args.result == ONIG_MISMATCH) {
+ if (result == ONIG_MISMATCH) {
rb_backref_set(Qnil);
return ONIG_MISMATCH;
}
- VALUE match = match_alloc(rb_cMatch);
+ VALUE match = Qnil;
+ if (set_match) {
+ match = *set_match;
+ }
+
+ if (NIL_P(match)) {
+ match = rb_backref_get();
+ }
+
+ if (!NIL_P(match) && FL_TEST(match, MATCH_BUSY)) {
+ match = Qnil;
+ }
+
+ if (NIL_P(match)) {
+ match = match_alloc(rb_cMatch);
+ }
+ else {
+ onig_region_free(&RMATCH_EXT(match)->regs, false);
+ }
+
rb_matchext_t *rm = RMATCH_EXT(match);
- rm->regs = args.regs;
+ rm->regs = regs;
if (set_backref_str) {
RB_OBJ_WRITE(match, &RMATCH(match)->str, rb_str_new4(str));
+ rb_obj_reveal(match, rb_cMatch);
}
else {
/* Note that a MatchData object with RMATCH(match)->str == 0 is incomplete!
@@ -1810,19 +1852,19 @@ rb_reg_search_set_match(VALUE re, VALUE str, long pos, int reverse, int set_back
rb_backref_set(match);
if (set_match) *set_match = match;
- return args.result;
+ return result;
}
long
-rb_reg_search0(VALUE re, VALUE str, long pos, int reverse, int set_backref_str)
+rb_reg_search0(VALUE re, VALUE str, long pos, int reverse, int set_backref_str, VALUE *match)
{
- return rb_reg_search_set_match(re, str, pos, reverse, set_backref_str, NULL);
+ return rb_reg_search_set_match(re, str, pos, reverse, set_backref_str, match);
}
long
rb_reg_search(VALUE re, VALUE str, long pos, int reverse)
{
- return rb_reg_search0(re, str, pos, reverse, 1);
+ return rb_reg_search_set_match(re, str, pos, reverse, 1, NULL);
}
static OnigPosition
@@ -2174,12 +2216,12 @@ match_ary_aref(VALUE match, VALUE idx, VALUE result)
/*
* call-seq:
- * matchdata[index] -> string or nil
- * matchdata[start, length] -> array
- * matchdata[range] -> array
- * matchdata[name] -> string or nil
+ * self[offset] -> string or nil
+ * self[offset, size] -> array
+ * self[range] -> array
+ * self[name] -> string or nil
*
- * When arguments +index+, +start and +length+, or +range+ are given,
+ * When arguments +offset+, +offset+ and +size+, or +range+ are given,
* returns match and captures in the style of Array#[]:
*
* m = /(.)(.)(\d+)(\d)/.match("THX1138.")
@@ -2430,7 +2472,7 @@ match_named_captures(int argc, VALUE *argv, VALUE match)
}
hash = rb_hash_new();
- memo = MEMO_NEW(hash, match, symbolize_names);
+ memo = rb_imemo_memo_new(hash, match, symbolize_names);
onig_foreach_name(RREGEXP(RMATCH(match)->regexp)->ptr, match_named_captures_iter, (void*)memo);
@@ -2469,7 +2511,7 @@ match_deconstruct_keys(VALUE match, VALUE keys)
h = rb_hash_new_with_size(onig_number_of_names(RREGEXP_PTR(RMATCH(match)->regexp)));
struct MEMO *memo;
- memo = MEMO_NEW(h, match, 1);
+ memo = rb_imemo_memo_new(h, match, 1);
onig_foreach_name(RREGEXP_PTR(RMATCH(match)->regexp), match_named_captures_iter, (void*)memo);
@@ -2575,6 +2617,7 @@ match_inspect(VALUE match)
struct re_registers *regs = RMATCH_REGS(match);
int num_regs = regs->num_regs;
struct backref_name_tag *names;
+ VALUE names_obj = Qnil;
VALUE regexp = RMATCH(match)->regexp;
if (regexp == 0) {
@@ -2585,7 +2628,7 @@ match_inspect(VALUE match)
cname, rb_reg_nth_match(0, match));
}
- names = ALLOCA_N(struct backref_name_tag, num_regs);
+ names = RB_ALLOCV_N(struct backref_name_tag, names_obj, num_regs);
MEMZERO(names, struct backref_name_tag, num_regs);
onig_foreach_name(RREGEXP_PTR(regexp),
@@ -2613,6 +2656,7 @@ match_inspect(VALUE match)
}
rb_str_buf_cat2(str, ">");
+ RB_ALLOCV_END(names_obj);
return str;
}
@@ -3331,10 +3375,13 @@ static void
reg_set_source(VALUE reg, VALUE str, rb_encoding *enc)
{
rb_encoding *regenc = rb_enc_get(reg);
+
if (regenc != enc) {
- str = rb_enc_associate(rb_str_dup(str), enc = regenc);
+ VALUE dup = rb_str_dup(str);
+ str = rb_enc_associate(dup, enc = regenc);
}
- RB_OBJ_WRITE(reg, &RREGEXP(reg)->src, rb_fstring(str));
+ str = rb_fstring(str);
+ RB_OBJ_WRITE(reg, &RREGEXP(reg)->src, str);
}
static int
@@ -3457,12 +3504,17 @@ static VALUE reg_cache;
VALUE
rb_reg_regcomp(VALUE str)
{
- if (reg_cache && RREGEXP_SRC_LEN(reg_cache) == RSTRING_LEN(str)
- && ENCODING_GET(reg_cache) == ENCODING_GET(str)
- && memcmp(RREGEXP_SRC_PTR(reg_cache), RSTRING_PTR(str), RSTRING_LEN(str)) == 0)
- return reg_cache;
+ if (rb_ractor_main_p()) {
+ if (reg_cache && RREGEXP_SRC_LEN(reg_cache) == RSTRING_LEN(str)
+ && ENCODING_GET(reg_cache) == ENCODING_GET(str)
+ && memcmp(RREGEXP_SRC_PTR(reg_cache), RSTRING_PTR(str), RSTRING_LEN(str)) == 0)
+ return reg_cache;
- return reg_cache = rb_reg_new_str(str, 0);
+ return reg_cache = rb_reg_new_str(str, 0);
+ }
+ else {
+ return rb_reg_new_str(str, 0);
+ }
}
static st_index_t reg_hash(VALUE re);
@@ -3497,10 +3549,10 @@ reg_hash(VALUE re)
/*
* call-seq:
- * regexp == object -> true or false
+ * self == other -> true or false
*
- * Returns +true+ if +object+ is another \Regexp whose pattern,
- * flags, and encoding are the same as +self+, +false+ otherwise:
+ * Returns whether +other+ is another \Regexp whose pattern,
+ * flags, and encoding are the same as +self+:
*
* /foo/ == Regexp.new('foo') # => true
* /foo/ == /foo/i # => false
@@ -3552,11 +3604,11 @@ match_hash(VALUE match)
/*
* call-seq:
- * matchdata == object -> true or false
+ * self == other -> true or false
*
- * Returns +true+ if +object+ is another \MatchData object
+ * Returns whether +other+ is another \MatchData object
* whose target string, regexp, match, and captures
- * are the same as +self+, +false+ otherwise.
+ * are the same as +self+.
*/
static VALUE
@@ -3616,12 +3668,11 @@ reg_match_pos(VALUE re, VALUE *strp, long pos, VALUE* set_match)
/*
* call-seq:
- * regexp =~ string -> integer or nil
+ * self =~ other -> integer or nil
*
* Returns the integer index (in characters) of the first match
- * for +self+ and +string+, or +nil+ if none;
- * also sets the
- * {rdoc-ref:Regexp global variables}[rdoc-ref:Regexp@Global+Variables]:
+ * for +self+ and +other+, or +nil+ if none;
+ * updates {Regexp-related global variables}[rdoc-ref:Regexp@Global+Variables].
*
* /at/ =~ 'input data' # => 7
* $~ # => #<MatchData "at">
@@ -3632,7 +3683,7 @@ reg_match_pos(VALUE re, VALUE *strp, long pos, VALUE* set_match)
* if and only if +self+:
*
* - Is a regexp literal;
- * see {Regexp Literals}[rdoc-ref:literals.rdoc@Regexp+Literals].
+ * see {Regexp Literals}[rdoc-ref:syntax/literals.rdoc@Regexp+Literals].
* - Does not contain interpolations;
* see {Regexp interpolation}[rdoc-ref:Regexp@Interpolation+Mode].
* - Is at the left of the expression.
@@ -3681,9 +3732,9 @@ rb_reg_match(VALUE re, VALUE str)
/*
* call-seq:
- * regexp === string -> true or false
+ * self === other -> true or false
*
- * Returns +true+ if +self+ finds a match in +string+:
+ * Returns whether +self+ finds a match in +other+:
*
* /^[a-z]*$/ === 'HELLO' # => false
* /^[A-Z]*$/ === 'HELLO' # => true
@@ -3924,7 +3975,6 @@ struct reg_init_args {
static VALUE reg_extract_args(int argc, VALUE *argv, struct reg_init_args *args);
static VALUE reg_init_args(VALUE self, VALUE str, rb_encoding *enc, int flags);
-void rb_warn_deprecated_to_remove(const char *removal, const char *fmt, const char *suggest, ...);
/*
* call-seq:
@@ -4586,7 +4636,7 @@ match_setter(VALUE val, ID _x, VALUE *_y)
* Regexp.last_match(n) -> string or nil
* Regexp.last_match(name) -> string or nil
*
- * With no argument, returns the value of <tt>$!</tt>,
+ * With no argument, returns the value of <tt>$~</tt>,
* which is the result of the most recent pattern match
* (see {Regexp global variables}[rdoc-ref:Regexp@Global+Variables]):
*
@@ -4672,12 +4722,6 @@ rb_reg_timeout_p(regex_t *reg, void *end_time_)
return false;
}
-void
-rb_reg_raise_timeout(void)
-{
- rb_raise(rb_eRegexpTimeoutError, "regexp match timeout");
-}
-
/*
* call-seq:
* Regexp.timeout -> float or nil
@@ -4813,6 +4857,7 @@ Init_Regexp(void)
rb_define_method(rb_cRegexp, "named_captures", rb_reg_named_captures, 0);
rb_define_method(rb_cRegexp, "timeout", rb_reg_timeout_get, 0);
+ /* Raised when regexp matching timed out. */
rb_eRegexpTimeoutError = rb_define_class_under(rb_cRegexp, "TimeoutError", rb_eRegexpError);
rb_define_singleton_method(rb_cRegexp, "timeout", rb_reg_s_timeout_get, 0);
rb_define_singleton_method(rb_cRegexp, "timeout=", rb_reg_s_timeout_set, 1);
@@ -4842,6 +4887,8 @@ Init_Regexp(void)
rb_define_method(rb_cMatch, "length", match_size, 0);
rb_define_method(rb_cMatch, "offset", match_offset, 1);
rb_define_method(rb_cMatch, "byteoffset", match_byteoffset, 1);
+ rb_define_method(rb_cMatch, "bytebegin", match_bytebegin, 1);
+ rb_define_method(rb_cMatch, "byteend", match_byteend, 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);
diff --git a/regcomp.c b/regcomp.c
index 38bfed5631..320cf520e9 100644
--- a/regcomp.c
+++ b/regcomp.c
@@ -2,8 +2,8 @@
regcomp.c - Onigmo (Oniguruma-mod) (regular expression library)
**********************************************************************/
/*-
- * Copyright (c) 2002-2013 K.Kosako <sndgk393 AT ybb DOT ne DOT jp>
- * Copyright (c) 2011-2016 K.Takata <kentkt AT csc DOT jp>
+ * Copyright (c) 2002-2018 K.Kosako <sndgk393 AT ybb DOT ne DOT jp>
+ * Copyright (c) 2011-2019 K.Takata <kentkt AT csc DOT jp>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -640,17 +640,17 @@ compile_cclass_node(CClassNode* cc, regex_t* reg)
else {
if (ONIGENC_MBC_MINLEN(reg->enc) > 1 || bitset_is_empty(cc->bs)) {
if (IS_NCCLASS_NOT(cc))
- add_opcode(reg, OP_CCLASS_MB_NOT);
+ add_opcode(reg, OP_CCLASS_MB_NOT);
else
- add_opcode(reg, OP_CCLASS_MB);
+ add_opcode(reg, OP_CCLASS_MB);
r = add_multi_byte_cclass(cc->mbuf, reg);
}
else {
if (IS_NCCLASS_NOT(cc))
- add_opcode(reg, OP_CCLASS_MIX_NOT);
+ add_opcode(reg, OP_CCLASS_MIX_NOT);
else
- add_opcode(reg, OP_CCLASS_MIX);
+ add_opcode(reg, OP_CCLASS_MIX);
r = add_bitset(reg, cc->bs);
if (r) return r;
@@ -762,9 +762,9 @@ compile_length_quantifier_node(QtfrNode* qn, regex_t* reg)
if (NTYPE(qn->target) == NT_CANY) {
if (qn->greedy && infinite) {
if (IS_NOT_NULL(qn->next_head_exact) && !CKN_ON)
- return SIZE_OP_ANYCHAR_STAR_PEEK_NEXT + tlen * qn->lower + cklen;
+ return SIZE_OP_ANYCHAR_STAR_PEEK_NEXT + tlen * qn->lower + cklen;
else
- return SIZE_OP_ANYCHAR_STAR + tlen * qn->lower + cklen;
+ return SIZE_OP_ANYCHAR_STAR + tlen * qn->lower + cklen;
}
}
@@ -776,17 +776,17 @@ compile_length_quantifier_node(QtfrNode* qn, regex_t* reg)
if (infinite && qn->lower <= 1) {
if (qn->greedy) {
if (qn->lower == 1)
- len = SIZE_OP_JUMP;
+ len = SIZE_OP_JUMP;
else
- len = 0;
+ len = 0;
len += SIZE_OP_PUSH + cklen + mod_tlen + SIZE_OP_JUMP;
}
else {
if (qn->lower == 0)
- len = SIZE_OP_JUMP;
+ len = SIZE_OP_JUMP;
else
- len = 0;
+ len = 0;
len += mod_tlen + SIZE_OP_PUSH + cklen;
}
@@ -800,10 +800,10 @@ compile_length_quantifier_node(QtfrNode* qn, regex_t* reg)
else if (qn->upper == 1 && qn->greedy) {
if (qn->lower == 0) {
if (CKN_ON) {
- len = SIZE_OP_STATE_CHECK_PUSH + tlen;
+ len = SIZE_OP_STATE_CHECK_PUSH + tlen;
}
else {
- len = SIZE_OP_PUSH + tlen;
+ len = SIZE_OP_PUSH + tlen;
}
}
else {
@@ -841,31 +841,31 @@ compile_quantifier_node(QtfrNode* qn, regex_t* reg)
if (r) return r;
if (IS_NOT_NULL(qn->next_head_exact) && !CKN_ON) {
if (IS_MULTILINE(reg->options))
- r = add_opcode(reg, OP_ANYCHAR_ML_STAR_PEEK_NEXT);
+ r = add_opcode(reg, OP_ANYCHAR_ML_STAR_PEEK_NEXT);
else
- r = add_opcode(reg, OP_ANYCHAR_STAR_PEEK_NEXT);
+ r = add_opcode(reg, OP_ANYCHAR_STAR_PEEK_NEXT);
if (r) return r;
if (CKN_ON) {
- r = add_state_check_num(reg, ckn);
- if (r) return r;
+ r = add_state_check_num(reg, ckn);
+ if (r) return r;
}
return add_bytes(reg, NSTR(qn->next_head_exact)->s, 1);
}
else {
if (IS_MULTILINE(reg->options)) {
- r = add_opcode(reg, (CKN_ON ?
- OP_STATE_CHECK_ANYCHAR_ML_STAR
- : OP_ANYCHAR_ML_STAR));
+ r = add_opcode(reg, (CKN_ON ?
+ OP_STATE_CHECK_ANYCHAR_ML_STAR
+ : OP_ANYCHAR_ML_STAR));
}
else {
- r = add_opcode(reg, (CKN_ON ?
- OP_STATE_CHECK_ANYCHAR_STAR
- : OP_ANYCHAR_STAR));
+ r = add_opcode(reg, (CKN_ON ?
+ OP_STATE_CHECK_ANYCHAR_STAR
+ : OP_ANYCHAR_STAR));
}
if (r) return r;
if (CKN_ON)
- r = add_state_check_num(reg, ckn);
+ r = add_state_check_num(reg, ckn);
return r;
}
@@ -879,45 +879,45 @@ compile_quantifier_node(QtfrNode* qn, regex_t* reg)
if (infinite && qn->lower <= 1) {
if (qn->greedy) {
if (qn->lower == 1) {
- r = add_opcode_rel_addr(reg, OP_JUMP,
- (CKN_ON ? SIZE_OP_STATE_CHECK_PUSH : SIZE_OP_PUSH));
- if (r) return r;
+ r = add_opcode_rel_addr(reg, OP_JUMP,
+ (CKN_ON ? SIZE_OP_STATE_CHECK_PUSH : SIZE_OP_PUSH));
+ if (r) return r;
}
if (CKN_ON) {
- r = add_opcode(reg, OP_STATE_CHECK_PUSH);
- if (r) return r;
- r = add_state_check_num(reg, ckn);
- if (r) return r;
- r = add_rel_addr(reg, mod_tlen + SIZE_OP_JUMP);
+ r = add_opcode(reg, OP_STATE_CHECK_PUSH);
+ if (r) return r;
+ r = add_state_check_num(reg, ckn);
+ if (r) return r;
+ r = add_rel_addr(reg, mod_tlen + SIZE_OP_JUMP);
}
else {
- r = add_opcode_rel_addr(reg, OP_PUSH, mod_tlen + SIZE_OP_JUMP);
+ r = add_opcode_rel_addr(reg, OP_PUSH, mod_tlen + SIZE_OP_JUMP);
}
if (r) return r;
r = compile_tree_empty_check(qn->target, reg, empty_info);
if (r) return r;
r = add_opcode_rel_addr(reg, OP_JUMP,
- -(mod_tlen + (int )SIZE_OP_JUMP
- + (int )(CKN_ON ? SIZE_OP_STATE_CHECK_PUSH : SIZE_OP_PUSH)));
+ -(mod_tlen + (int )SIZE_OP_JUMP
+ + (int )(CKN_ON ? SIZE_OP_STATE_CHECK_PUSH : SIZE_OP_PUSH)));
}
else {
if (qn->lower == 0) {
- r = add_opcode_rel_addr(reg, OP_JUMP, mod_tlen);
- if (r) return r;
+ r = add_opcode_rel_addr(reg, OP_JUMP, mod_tlen);
+ if (r) return r;
}
r = compile_tree_empty_check(qn->target, reg, empty_info);
if (r) return r;
if (CKN_ON) {
- r = add_opcode(reg, OP_STATE_CHECK_PUSH_OR_JUMP);
- if (r) return r;
- r = add_state_check_num(reg, ckn);
- if (r) return r;
- r = add_rel_addr(reg,
- -(mod_tlen + (int )SIZE_OP_STATE_CHECK_PUSH_OR_JUMP));
+ r = add_opcode(reg, OP_STATE_CHECK_PUSH_OR_JUMP);
+ if (r) return r;
+ r = add_state_check_num(reg, ckn);
+ if (r) return r;
+ r = add_rel_addr(reg,
+ -(mod_tlen + (int )SIZE_OP_STATE_CHECK_PUSH_OR_JUMP));
}
else
- r = add_opcode_rel_addr(reg, OP_PUSH, -(mod_tlen + (int )SIZE_OP_PUSH));
+ r = add_opcode_rel_addr(reg, OP_PUSH, -(mod_tlen + (int )SIZE_OP_PUSH));
}
}
else if (qn->upper == 0) {
@@ -932,14 +932,14 @@ compile_quantifier_node(QtfrNode* qn, regex_t* reg)
else if (qn->upper == 1 && qn->greedy) {
if (qn->lower == 0) {
if (CKN_ON) {
- r = add_opcode(reg, OP_STATE_CHECK_PUSH);
- if (r) return r;
- r = add_state_check_num(reg, ckn);
- if (r) return r;
- r = add_rel_addr(reg, tlen);
+ r = add_opcode(reg, OP_STATE_CHECK_PUSH);
+ if (r) return r;
+ r = add_state_check_num(reg, ckn);
+ if (r) return r;
+ r = add_rel_addr(reg, tlen);
}
else {
- r = add_opcode_rel_addr(reg, OP_PUSH, tlen);
+ r = add_opcode_rel_addr(reg, OP_PUSH, tlen);
}
if (r) return r;
}
@@ -991,9 +991,9 @@ compile_length_quantifier_node(QtfrNode* qn, regex_t* reg)
if (NTYPE(qn->target) == NT_CANY) {
if (qn->greedy && infinite) {
if (IS_NOT_NULL(qn->next_head_exact))
- return SIZE_OP_ANYCHAR_STAR_PEEK_NEXT + tlen * qn->lower;
+ return SIZE_OP_ANYCHAR_STAR_PEEK_NEXT + tlen * qn->lower;
else
- return SIZE_OP_ANYCHAR_STAR + tlen * qn->lower;
+ return SIZE_OP_ANYCHAR_STAR + tlen * qn->lower;
}
}
@@ -1014,13 +1014,13 @@ compile_length_quantifier_node(QtfrNode* qn, regex_t* reg)
if (qn->greedy) {
#ifdef USE_OP_PUSH_OR_JUMP_EXACT
if (IS_NOT_NULL(qn->head_exact))
- len += SIZE_OP_PUSH_OR_JUMP_EXACT1 + mod_tlen + SIZE_OP_JUMP;
+ len += SIZE_OP_PUSH_OR_JUMP_EXACT1 + mod_tlen + SIZE_OP_JUMP;
else
#endif
if (IS_NOT_NULL(qn->next_head_exact))
- len += SIZE_OP_PUSH_IF_PEEK_NEXT + mod_tlen + SIZE_OP_JUMP;
+ len += SIZE_OP_PUSH_IF_PEEK_NEXT + mod_tlen + SIZE_OP_JUMP;
else
- len += SIZE_OP_PUSH + mod_tlen + SIZE_OP_JUMP;
+ len += SIZE_OP_PUSH + mod_tlen + SIZE_OP_JUMP;
}
else
len += SIZE_OP_JUMP + mod_tlen + SIZE_OP_PUSH;
@@ -1060,17 +1060,17 @@ compile_quantifier_node(QtfrNode* qn, regex_t* reg)
if (r) return r;
if (IS_NOT_NULL(qn->next_head_exact)) {
if (IS_MULTILINE(reg->options))
- r = add_opcode(reg, OP_ANYCHAR_ML_STAR_PEEK_NEXT);
+ r = add_opcode(reg, OP_ANYCHAR_ML_STAR_PEEK_NEXT);
else
- r = add_opcode(reg, OP_ANYCHAR_STAR_PEEK_NEXT);
+ r = add_opcode(reg, OP_ANYCHAR_STAR_PEEK_NEXT);
if (r) return r;
return add_bytes(reg, NSTR(qn->next_head_exact)->s, 1);
}
else {
if (IS_MULTILINE(reg->options))
- return add_opcode(reg, OP_ANYCHAR_ML_STAR);
+ return add_opcode(reg, OP_ANYCHAR_ML_STAR);
else
- return add_opcode(reg, OP_ANYCHAR_STAR);
+ return add_opcode(reg, OP_ANYCHAR_STAR);
}
}
@@ -1084,17 +1084,17 @@ compile_quantifier_node(QtfrNode* qn, regex_t* reg)
if (qn->lower == 1 && tlen > QUANTIFIER_EXPAND_LIMIT_SIZE) {
if (qn->greedy) {
#ifdef USE_OP_PUSH_OR_JUMP_EXACT
- if (IS_NOT_NULL(qn->head_exact))
- r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH_OR_JUMP_EXACT1);
- else
+ if (IS_NOT_NULL(qn->head_exact))
+ r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH_OR_JUMP_EXACT1);
+ else
#endif
- if (IS_NOT_NULL(qn->next_head_exact))
- r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH_IF_PEEK_NEXT);
- else
- r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH);
+ if (IS_NOT_NULL(qn->next_head_exact))
+ r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH_IF_PEEK_NEXT);
+ else
+ r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_PUSH);
}
else {
- r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_JUMP);
+ r = add_opcode_rel_addr(reg, OP_JUMP, SIZE_OP_JUMP);
}
if (r) return r;
}
@@ -1106,34 +1106,34 @@ compile_quantifier_node(QtfrNode* qn, regex_t* reg)
if (qn->greedy) {
#ifdef USE_OP_PUSH_OR_JUMP_EXACT
if (IS_NOT_NULL(qn->head_exact)) {
- r = add_opcode_rel_addr(reg, OP_PUSH_OR_JUMP_EXACT1,
- mod_tlen + SIZE_OP_JUMP);
- if (r) return r;
- add_bytes(reg, NSTR(qn->head_exact)->s, 1);
- r = compile_tree_empty_check(qn->target, reg, empty_info);
- if (r) return r;
- r = add_opcode_rel_addr(reg, OP_JUMP,
- -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH_OR_JUMP_EXACT1));
+ r = add_opcode_rel_addr(reg, OP_PUSH_OR_JUMP_EXACT1,
+ mod_tlen + SIZE_OP_JUMP);
+ if (r) return r;
+ add_bytes(reg, NSTR(qn->head_exact)->s, 1);
+ r = compile_tree_empty_check(qn->target, reg, empty_info);
+ if (r) return r;
+ r = add_opcode_rel_addr(reg, OP_JUMP,
+ -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH_OR_JUMP_EXACT1));
}
else
#endif
if (IS_NOT_NULL(qn->next_head_exact)) {
- r = add_opcode_rel_addr(reg, OP_PUSH_IF_PEEK_NEXT,
- mod_tlen + SIZE_OP_JUMP);
- if (r) return r;
- add_bytes(reg, NSTR(qn->next_head_exact)->s, 1);
- r = compile_tree_empty_check(qn->target, reg, empty_info);
- if (r) return r;
- r = add_opcode_rel_addr(reg, OP_JUMP,
+ r = add_opcode_rel_addr(reg, OP_PUSH_IF_PEEK_NEXT,
+ mod_tlen + SIZE_OP_JUMP);
+ if (r) return r;
+ add_bytes(reg, NSTR(qn->next_head_exact)->s, 1);
+ r = compile_tree_empty_check(qn->target, reg, empty_info);
+ if (r) return r;
+ r = add_opcode_rel_addr(reg, OP_JUMP,
-(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH_IF_PEEK_NEXT));
}
else {
- r = add_opcode_rel_addr(reg, OP_PUSH, mod_tlen + SIZE_OP_JUMP);
- if (r) return r;
- r = compile_tree_empty_check(qn->target, reg, empty_info);
- if (r) return r;
- r = add_opcode_rel_addr(reg, OP_JUMP,
- -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH));
+ r = add_opcode_rel_addr(reg, OP_PUSH, mod_tlen + SIZE_OP_JUMP);
+ if (r) return r;
+ r = compile_tree_empty_check(qn->target, reg, empty_info);
+ if (r) return r;
+ r = add_opcode_rel_addr(reg, OP_JUMP,
+ -(mod_tlen + (int )SIZE_OP_JUMP + (int )SIZE_OP_PUSH));
}
}
else {
@@ -1159,7 +1159,7 @@ compile_quantifier_node(QtfrNode* qn, regex_t* reg)
for (i = 0; i < n; i++) {
r = add_opcode_rel_addr(reg, OP_PUSH,
- (n - i) * tlen + (n - i - 1) * SIZE_OP_PUSH);
+ (n - i) * tlen + (n - i - 1) * SIZE_OP_PUSH);
if (r) return r;
r = compile_tree(qn->target, reg);
if (r) return r;
@@ -1246,29 +1246,29 @@ compile_length_enclose_node(EncloseNode* node, regex_t* reg)
#ifdef USE_SUBEXP_CALL
if (IS_ENCLOSE_CALLED(node)) {
len = SIZE_OP_MEMORY_START_PUSH + tlen
- + SIZE_OP_CALL + SIZE_OP_JUMP + SIZE_OP_RETURN;
+ + SIZE_OP_CALL + SIZE_OP_JUMP + SIZE_OP_RETURN;
if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))
- len += (IS_ENCLOSE_RECURSION(node)
- ? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_PUSH);
+ len += (IS_ENCLOSE_RECURSION(node)
+ ? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_PUSH);
else
- len += (IS_ENCLOSE_RECURSION(node)
- ? SIZE_OP_MEMORY_END_REC : SIZE_OP_MEMORY_END);
+ len += (IS_ENCLOSE_RECURSION(node)
+ ? SIZE_OP_MEMORY_END_REC : SIZE_OP_MEMORY_END);
}
else if (IS_ENCLOSE_RECURSION(node)) {
len = SIZE_OP_MEMORY_START_PUSH;
len += tlen + (BIT_STATUS_AT(reg->bt_mem_end, node->regnum)
- ? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_REC);
+ ? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_REC);
}
else
#endif
{
if (BIT_STATUS_AT(reg->bt_mem_start, node->regnum))
- len = SIZE_OP_MEMORY_START_PUSH;
+ len = SIZE_OP_MEMORY_START_PUSH;
else
- len = SIZE_OP_MEMORY_START;
+ len = SIZE_OP_MEMORY_START;
len += tlen + (BIT_STATUS_AT(reg->bt_mem_end, node->regnum)
- ? SIZE_OP_MEMORY_END_PUSH : SIZE_OP_MEMORY_END);
+ ? SIZE_OP_MEMORY_END_PUSH : SIZE_OP_MEMORY_END);
}
break;
@@ -1283,7 +1283,7 @@ compile_length_enclose_node(EncloseNode* node, regex_t* reg)
if (tlen < 0) return tlen;
len = tlen * qn->lower
- + SIZE_OP_PUSH + tlen + SIZE_OP_POP + SIZE_OP_JUMP;
+ + SIZE_OP_PUSH + tlen + SIZE_OP_POP + SIZE_OP_JUMP;
}
else {
#endif
@@ -1348,11 +1348,11 @@ compile_enclose_node(EncloseNode* node, regex_t* reg)
len = compile_length_tree(node->target, reg);
len += (SIZE_OP_MEMORY_START_PUSH + SIZE_OP_RETURN);
if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))
- len += (IS_ENCLOSE_RECURSION(node)
- ? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_PUSH);
+ len += (IS_ENCLOSE_RECURSION(node)
+ ? SIZE_OP_MEMORY_END_PUSH_REC : SIZE_OP_MEMORY_END_PUSH);
else
- len += (IS_ENCLOSE_RECURSION(node)
- ? SIZE_OP_MEMORY_END_REC : SIZE_OP_MEMORY_END);
+ len += (IS_ENCLOSE_RECURSION(node)
+ ? SIZE_OP_MEMORY_END_REC : SIZE_OP_MEMORY_END);
r = add_opcode_rel_addr(reg, OP_JUMP, len);
if (r) return r;
@@ -1370,11 +1370,11 @@ compile_enclose_node(EncloseNode* node, regex_t* reg)
#ifdef USE_SUBEXP_CALL
if (IS_ENCLOSE_CALLED(node)) {
if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))
- r = add_opcode(reg, (IS_ENCLOSE_RECURSION(node)
- ? OP_MEMORY_END_PUSH_REC : OP_MEMORY_END_PUSH));
+ r = add_opcode(reg, (IS_ENCLOSE_RECURSION(node)
+ ? OP_MEMORY_END_PUSH_REC : OP_MEMORY_END_PUSH));
else
- r = add_opcode(reg, (IS_ENCLOSE_RECURSION(node)
- ? OP_MEMORY_END_REC : OP_MEMORY_END));
+ r = add_opcode(reg, (IS_ENCLOSE_RECURSION(node)
+ ? OP_MEMORY_END_REC : OP_MEMORY_END));
if (r) return r;
r = add_mem_num(reg, node->regnum);
@@ -1383,9 +1383,9 @@ compile_enclose_node(EncloseNode* node, regex_t* reg)
}
else if (IS_ENCLOSE_RECURSION(node)) {
if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))
- r = add_opcode(reg, OP_MEMORY_END_PUSH_REC);
+ r = add_opcode(reg, OP_MEMORY_END_PUSH_REC);
else
- r = add_opcode(reg, OP_MEMORY_END_REC);
+ r = add_opcode(reg, OP_MEMORY_END_REC);
if (r) return r;
r = add_mem_num(reg, node->regnum);
}
@@ -1393,9 +1393,9 @@ compile_enclose_node(EncloseNode* node, regex_t* reg)
#endif
{
if (BIT_STATUS_AT(reg->bt_mem_end, node->regnum))
- r = add_opcode(reg, OP_MEMORY_END_PUSH);
+ r = add_opcode(reg, OP_MEMORY_END_PUSH);
else
- r = add_opcode(reg, OP_MEMORY_END);
+ r = add_opcode(reg, OP_MEMORY_END);
if (r) return r;
r = add_mem_num(reg, node->regnum);
}
@@ -1421,7 +1421,7 @@ compile_enclose_node(EncloseNode* node, regex_t* reg)
r = add_opcode(reg, OP_POP);
if (r) return r;
r = add_opcode_rel_addr(reg, OP_JUMP,
- -((int )SIZE_OP_PUSH + len + (int )SIZE_OP_POP + (int )SIZE_OP_JUMP));
+ -((int )SIZE_OP_PUSH + len + (int )SIZE_OP_POP + (int )SIZE_OP_JUMP));
}
else {
#endif
@@ -1579,11 +1579,11 @@ compile_anchor_node(AnchorNode* node, regex_t* reg)
r = add_opcode(reg, OP_LOOK_BEHIND);
if (r) return r;
if (node->char_len < 0) {
- r = get_char_length_tree(node->target, reg, &n);
- if (r) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
+ r = get_char_length_tree(node->target, reg, &n);
+ if (r) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
}
else
- n = node->char_len;
+ n = node->char_len;
r = add_length(reg, n);
if (r) return r;
r = compile_tree(node->target, reg);
@@ -1595,14 +1595,14 @@ compile_anchor_node(AnchorNode* node, regex_t* reg)
int n;
len = compile_length_tree(node->target, reg);
r = add_opcode_rel_addr(reg, OP_PUSH_LOOK_BEHIND_NOT,
- len + SIZE_OP_FAIL_LOOK_BEHIND_NOT);
+ len + SIZE_OP_FAIL_LOOK_BEHIND_NOT);
if (r) return r;
if (node->char_len < 0) {
- r = get_char_length_tree(node->target, reg, &n);
- if (r) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
+ r = get_char_length_tree(node->target, reg, &n);
+ if (r) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
}
else
- n = node->char_len;
+ n = node->char_len;
r = add_length(reg, n);
if (r) return r;
r = compile_tree(node->target, reg);
@@ -1641,10 +1641,10 @@ compile_length_tree(Node* node, regex_t* reg)
int n = 0;
len = 0;
do {
- r = compile_length_tree(NCAR(node), reg);
- if (r < 0) return r;
- len += r;
- n++;
+ r = compile_length_tree(NCAR(node), reg);
+ if (r < 0) return r;
+ len += r;
+ n++;
} while (IS_NOT_NULL(node = NCDR(node)));
r = len;
r += (SIZE_OP_PUSH + SIZE_OP_JUMP) * (n - 1);
@@ -1673,17 +1673,17 @@ compile_length_tree(Node* node, regex_t* reg)
#ifdef USE_BACKREF_WITH_LEVEL
if (IS_BACKREF_NEST_LEVEL(br)) {
- r = SIZE_OPCODE + SIZE_OPTION + SIZE_LENGTH +
+ r = SIZE_OPCODE + SIZE_OPTION + SIZE_LENGTH +
SIZE_LENGTH + (SIZE_MEMNUM * br->back_num);
}
else
#endif
if (br->back_num == 1) {
- r = ((!IS_IGNORECASE(reg->options) && br->back_static[0] <= 2)
- ? SIZE_OPCODE : (SIZE_OPCODE + SIZE_MEMNUM));
+ r = ((!IS_IGNORECASE(reg->options) && br->back_static[0] <= 2)
+ ? SIZE_OPCODE : (SIZE_OPCODE + SIZE_MEMNUM));
}
else {
- r = SIZE_OPCODE + SIZE_LENGTH + (SIZE_MEMNUM * br->back_num);
+ r = SIZE_OPCODE + SIZE_LENGTH + (SIZE_MEMNUM * br->back_num);
}
}
break;
@@ -1732,26 +1732,26 @@ compile_tree(Node* node, regex_t* reg)
Node* x = node;
len = 0;
do {
- len += compile_length_tree(NCAR(x), reg);
- if (NCDR(x) != NULL) {
- len += SIZE_OP_PUSH + SIZE_OP_JUMP;
- }
+ len += compile_length_tree(NCAR(x), reg);
+ if (NCDR(x) != NULL) {
+ len += SIZE_OP_PUSH + SIZE_OP_JUMP;
+ }
} while (IS_NOT_NULL(x = NCDR(x)));
pos = reg->used + len; /* goal position */
do {
- len = compile_length_tree(NCAR(node), reg);
- if (IS_NOT_NULL(NCDR(node))) {
- r = add_opcode_rel_addr(reg, OP_PUSH, len + SIZE_OP_JUMP);
- if (r) break;
- }
- r = compile_tree(NCAR(node), reg);
- if (r) break;
- if (IS_NOT_NULL(NCDR(node))) {
- len = pos - (reg->used + SIZE_OP_JUMP);
- r = add_opcode_rel_addr(reg, OP_JUMP, len);
- if (r) break;
- }
+ len = compile_length_tree(NCAR(node), reg);
+ if (IS_NOT_NULL(NCDR(node))) {
+ r = add_opcode_rel_addr(reg, OP_PUSH, len + SIZE_OP_JUMP);
+ if (r) break;
+ }
+ r = compile_tree(NCAR(node), reg);
+ if (r) break;
+ if (IS_NOT_NULL(NCDR(node))) {
+ len = pos - (reg->used + SIZE_OP_JUMP);
+ r = add_opcode_rel_addr(reg, OP_JUMP, len);
+ if (r) break;
+ }
} while (IS_NOT_NULL(node = NCDR(node)));
}
break;
@@ -1773,18 +1773,18 @@ compile_tree(Node* node, regex_t* reg)
switch (NCTYPE(node)->ctype) {
case ONIGENC_CTYPE_WORD:
- if (NCTYPE(node)->ascii_range != 0) {
- if (NCTYPE(node)->not != 0) op = OP_NOT_ASCII_WORD;
- else op = OP_ASCII_WORD;
- }
- else {
- if (NCTYPE(node)->not != 0) op = OP_NOT_WORD;
- else op = OP_WORD;
- }
- break;
+ if (NCTYPE(node)->ascii_range != 0) {
+ if (NCTYPE(node)->not != 0) op = OP_NOT_ASCII_WORD;
+ else op = OP_ASCII_WORD;
+ }
+ else {
+ if (NCTYPE(node)->not != 0) op = OP_NOT_WORD;
+ else op = OP_WORD;
+ }
+ break;
default:
- return ONIGERR_TYPE_BUG;
- break;
+ return ONIGERR_TYPE_BUG;
+ break;
}
r = add_opcode(reg, op);
}
@@ -1803,58 +1803,58 @@ compile_tree(Node* node, regex_t* reg)
#ifdef USE_BACKREF_WITH_LEVEL
if (IS_BACKREF_NEST_LEVEL(br)) {
- r = add_opcode(reg, OP_BACKREF_WITH_LEVEL);
- if (r) return r;
- r = add_option(reg, (reg->options & ONIG_OPTION_IGNORECASE));
- if (r) return r;
- r = add_length(reg, br->nest_level);
- if (r) return r;
-
- goto add_bacref_mems;
+ r = add_opcode(reg, OP_BACKREF_WITH_LEVEL);
+ if (r) return r;
+ r = add_option(reg, (reg->options & ONIG_OPTION_IGNORECASE));
+ if (r) return r;
+ r = add_length(reg, br->nest_level);
+ if (r) return r;
+
+ goto add_bacref_mems;
}
else
#endif
if (br->back_num == 1) {
- n = br->back_static[0];
- if (IS_IGNORECASE(reg->options)) {
- r = add_opcode(reg, OP_BACKREFN_IC);
- if (r) return r;
- r = add_mem_num(reg, n);
- }
- else {
- switch (n) {
- case 1: r = add_opcode(reg, OP_BACKREF1); break;
- case 2: r = add_opcode(reg, OP_BACKREF2); break;
- default:
- r = add_opcode(reg, OP_BACKREFN);
- if (r) return r;
- r = add_mem_num(reg, n);
- break;
- }
- }
+ n = br->back_static[0];
+ if (IS_IGNORECASE(reg->options)) {
+ r = add_opcode(reg, OP_BACKREFN_IC);
+ if (r) return r;
+ r = add_mem_num(reg, n);
+ }
+ else {
+ switch (n) {
+ case 1: r = add_opcode(reg, OP_BACKREF1); break;
+ case 2: r = add_opcode(reg, OP_BACKREF2); break;
+ default:
+ r = add_opcode(reg, OP_BACKREFN);
+ if (r) return r;
+ r = add_mem_num(reg, n);
+ break;
+ }
+ }
}
else {
- int i;
- int* p;
+ int i;
+ int* p;
- if (IS_IGNORECASE(reg->options)) {
- r = add_opcode(reg, OP_BACKREF_MULTI_IC);
- }
- else {
- r = add_opcode(reg, OP_BACKREF_MULTI);
- }
- if (r) return r;
+ if (IS_IGNORECASE(reg->options)) {
+ r = add_opcode(reg, OP_BACKREF_MULTI_IC);
+ }
+ else {
+ r = add_opcode(reg, OP_BACKREF_MULTI);
+ }
+ if (r) return r;
#ifdef USE_BACKREF_WITH_LEVEL
add_bacref_mems:
#endif
- r = add_length(reg, br->back_num);
- if (r) return r;
- p = BACKREFS_P(br);
- for (i = br->back_num - 1; i >= 0; i--) {
- r = add_mem_num(reg, p[i]);
- if (r) return r;
- }
+ r = add_length(reg, br->back_num);
+ if (r) return r;
+ p = BACKREFS_P(br);
+ for (i = br->back_num - 1; i >= 0; i--) {
+ r = add_mem_num(reg, p[i]);
+ if (r) return r;
+ }
}
}
break;
@@ -1909,7 +1909,7 @@ noname_disable_map(Node** plink, GroupNumRemap* map, int* counter)
Node* old = *ptarget;
r = noname_disable_map(ptarget, map, counter);
if (*ptarget != old && NTYPE(*ptarget) == NT_QTFR) {
- onig_reduce_nested_quantifier(node, *ptarget);
+ onig_reduce_nested_quantifier(node, *ptarget);
}
}
break;
@@ -1918,18 +1918,18 @@ noname_disable_map(Node** plink, GroupNumRemap* map, int* counter)
{
EncloseNode* en = NENCLOSE(node);
if (en->type == ENCLOSE_MEMORY) {
- if (IS_ENCLOSE_NAMED_GROUP(en)) {
- (*counter)++;
- map[en->regnum].new_val = *counter;
- en->regnum = *counter;
- }
- else if (en->regnum != 0) {
- *plink = en->target;
- en->target = NULL_NODE;
- onig_node_free(node);
- r = noname_disable_map(plink, map, counter);
- break;
- }
+ if (IS_ENCLOSE_NAMED_GROUP(en)) {
+ (*counter)++;
+ map[en->regnum].new_val = *counter;
+ en->regnum = *counter;
+ }
+ else if (en->regnum != 0) {
+ *plink = en->target;
+ en->target = NULL_NODE;
+ onig_node_free(node);
+ r = noname_disable_map(plink, map, counter);
+ break;
+ }
}
r = noname_disable_map(&(en->target), map, counter);
}
@@ -1995,8 +1995,8 @@ renumber_by_map(Node* node, GroupNumRemap* map, const int num_mem)
{
EncloseNode* en = NENCLOSE(node);
if (en->type == ENCLOSE_CONDITION) {
- if (en->regnum > num_mem) return ONIGERR_INVALID_BACKREF;
- en->regnum = map[en->regnum].new_val;
+ if (en->regnum > num_mem) return ONIGERR_INVALID_BACKREF;
+ en->regnum = map[en->regnum].new_val;
}
r = renumber_by_map(en->target, map, num_mem);
}
@@ -2127,8 +2127,8 @@ quantifiers_memory_node_info(Node* node)
{
int v;
do {
- v = quantifiers_memory_node_info(NCAR(node));
- if (v > r) r = v;
+ v = quantifiers_memory_node_info(NCAR(node));
+ if (v > r) r = v;
} while (v >= 0 && IS_NOT_NULL(node = NCDR(node)));
}
break;
@@ -2147,7 +2147,7 @@ quantifiers_memory_node_info(Node* node)
{
QtfrNode* qn = NQTFR(node);
if (qn->upper != 0) {
- r = quantifiers_memory_node_info(qn->target);
+ r = quantifiers_memory_node_info(qn->target);
}
}
break;
@@ -2157,17 +2157,17 @@ quantifiers_memory_node_info(Node* node)
EncloseNode* en = NENCLOSE(node);
switch (en->type) {
case ENCLOSE_MEMORY:
- return NQ_TARGET_IS_EMPTY_MEM;
- break;
+ return NQ_TARGET_IS_EMPTY_MEM;
+ break;
case ENCLOSE_OPTION:
case ENCLOSE_STOP_BACKTRACK:
case ENCLOSE_CONDITION:
case ENCLOSE_ABSENT:
- r = quantifiers_memory_node_info(en->target);
- break;
+ r = quantifiers_memory_node_info(en->target);
+ break;
default:
- break;
+ break;
}
}
break;
@@ -2207,10 +2207,10 @@ get_min_match_length(Node* node, OnigDistance *min, ScanEnv* env)
r = get_min_match_length(nodes[backs[0]], min, env);
if (r != 0) break;
for (i = 1; i < br->back_num; i++) {
- if (backs[i] > env->num_mem) return ONIGERR_INVALID_BACKREF;
- r = get_min_match_length(nodes[backs[i]], &tmin, env);
- if (r != 0) break;
- if (*min > tmin) *min = tmin;
+ if (backs[i] > env->num_mem) return ONIGERR_INVALID_BACKREF;
+ r = get_min_match_length(nodes[backs[i]], &tmin, env);
+ if (r != 0) break;
+ if (*min > tmin) *min = tmin;
}
}
break;
@@ -2220,7 +2220,7 @@ get_min_match_length(Node* node, OnigDistance *min, ScanEnv* env)
if (IS_CALL_RECURSION(NCALL(node))) {
EncloseNode* en = NENCLOSE(NCALL(node)->target);
if (IS_ENCLOSE_MIN_FIXED(en))
- *min = en->min_len;
+ *min = en->min_len;
}
else
r = get_min_match_length(NCALL(node)->target, min, env);
@@ -2239,11 +2239,11 @@ get_min_match_length(Node* node, OnigDistance *min, ScanEnv* env)
Node *x, *y;
y = node;
do {
- x = NCAR(y);
- r = get_min_match_length(x, &tmin, env);
- if (r != 0) break;
- if (y == node) *min = tmin;
- else if (*min > tmin) *min = tmin;
+ x = NCAR(y);
+ r = get_min_match_length(x, &tmin, env);
+ if (r != 0) break;
+ if (y == node) *min = tmin;
+ else if (*min > tmin) *min = tmin;
} while (r == 0 && IS_NOT_NULL(y = NCDR(y)));
}
break;
@@ -2269,9 +2269,9 @@ get_min_match_length(Node* node, OnigDistance *min, ScanEnv* env)
QtfrNode* qn = NQTFR(node);
if (qn->lower > 0) {
- r = get_min_match_length(qn->target, min, env);
- if (r == 0)
- *min = distance_multiply(*min, qn->lower);
+ r = get_min_match_length(qn->target, min, env);
+ if (r == 0)
+ *min = distance_multiply(*min, qn->lower);
}
}
break;
@@ -2284,28 +2284,28 @@ get_min_match_length(Node* node, OnigDistance *min, ScanEnv* env)
if (IS_ENCLOSE_MIN_FIXED(en))
*min = en->min_len;
else {
- if (IS_ENCLOSE_MARK1(NENCLOSE(node)))
- *min = 0; /* recursive */
- else {
- SET_ENCLOSE_STATUS(node, NST_MARK1);
- r = get_min_match_length(en->target, min, env);
- CLEAR_ENCLOSE_STATUS(node, NST_MARK1);
- if (r == 0) {
- en->min_len = *min;
- SET_ENCLOSE_STATUS(node, NST_MIN_FIXED);
- }
- }
+ if (IS_ENCLOSE_MARK1(NENCLOSE(node)))
+ *min = 0; /* recursive */
+ else {
+ SET_ENCLOSE_STATUS(node, NST_MARK1);
+ r = get_min_match_length(en->target, min, env);
+ CLEAR_ENCLOSE_STATUS(node, NST_MARK1);
+ if (r == 0) {
+ en->min_len = *min;
+ SET_ENCLOSE_STATUS(node, NST_MIN_FIXED);
+ }
+ }
}
break;
case ENCLOSE_OPTION:
case ENCLOSE_STOP_BACKTRACK:
case ENCLOSE_CONDITION:
- r = get_min_match_length(en->target, min, env);
- break;
+ r = get_min_match_length(en->target, min, env);
+ break;
case ENCLOSE_ABSENT:
- break;
+ break;
}
}
break;
@@ -2330,7 +2330,7 @@ get_max_match_length(Node* node, OnigDistance *max, ScanEnv* env)
do {
r = get_max_match_length(NCAR(node), &tmax, env);
if (r == 0)
- *max = distance_add(*max, tmax);
+ *max = distance_add(*max, tmax);
} while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
break;
@@ -2364,15 +2364,15 @@ get_max_match_length(Node* node, OnigDistance *max, ScanEnv* env)
Node** nodes = SCANENV_MEM_NODES(env);
BRefNode* br = NBREF(node);
if (br->state & NST_RECURSION) {
- *max = ONIG_INFINITE_DISTANCE;
- break;
+ *max = ONIG_INFINITE_DISTANCE;
+ break;
}
backs = BACKREFS_P(br);
for (i = 0; i < br->back_num; i++) {
- if (backs[i] > env->num_mem) return ONIGERR_INVALID_BACKREF;
- r = get_max_match_length(nodes[backs[i]], &tmax, env);
- if (r != 0) break;
- if (*max < tmax) *max = tmax;
+ if (backs[i] > env->num_mem) return ONIGERR_INVALID_BACKREF;
+ r = get_max_match_length(nodes[backs[i]], &tmax, env);
+ if (r != 0) break;
+ if (*max < tmax) *max = tmax;
}
}
break;
@@ -2391,13 +2391,13 @@ get_max_match_length(Node* node, OnigDistance *max, ScanEnv* env)
QtfrNode* qn = NQTFR(node);
if (qn->upper != 0) {
- r = get_max_match_length(qn->target, max, env);
- if (r == 0 && *max != 0) {
- if (! IS_REPEAT_INFINITE(qn->upper))
- *max = distance_multiply(*max, qn->upper);
- else
- *max = ONIG_INFINITE_DISTANCE;
- }
+ r = get_max_match_length(qn->target, max, env);
+ if (r == 0 && *max != 0) {
+ if (! IS_REPEAT_INFINITE(qn->upper))
+ *max = distance_multiply(*max, qn->upper);
+ else
+ *max = ONIG_INFINITE_DISTANCE;
+ }
}
}
break;
@@ -2407,31 +2407,31 @@ get_max_match_length(Node* node, OnigDistance *max, ScanEnv* env)
EncloseNode* en = NENCLOSE(node);
switch (en->type) {
case ENCLOSE_MEMORY:
- if (IS_ENCLOSE_MAX_FIXED(en))
- *max = en->max_len;
- else {
- if (IS_ENCLOSE_MARK1(NENCLOSE(node)))
- *max = ONIG_INFINITE_DISTANCE;
- else {
- SET_ENCLOSE_STATUS(node, NST_MARK1);
- r = get_max_match_length(en->target, max, env);
- CLEAR_ENCLOSE_STATUS(node, NST_MARK1);
- if (r == 0) {
- en->max_len = *max;
- SET_ENCLOSE_STATUS(node, NST_MAX_FIXED);
- }
- }
- }
- break;
+ if (IS_ENCLOSE_MAX_FIXED(en))
+ *max = en->max_len;
+ else {
+ if (IS_ENCLOSE_MARK1(NENCLOSE(node)))
+ *max = ONIG_INFINITE_DISTANCE;
+ else {
+ SET_ENCLOSE_STATUS(node, NST_MARK1);
+ r = get_max_match_length(en->target, max, env);
+ CLEAR_ENCLOSE_STATUS(node, NST_MARK1);
+ if (r == 0) {
+ en->max_len = *max;
+ SET_ENCLOSE_STATUS(node, NST_MAX_FIXED);
+ }
+ }
+ }
+ break;
case ENCLOSE_OPTION:
case ENCLOSE_STOP_BACKTRACK:
case ENCLOSE_CONDITION:
- r = get_max_match_length(en->target, max, env);
- break;
+ r = get_max_match_length(en->target, max, env);
+ break;
case ENCLOSE_ABSENT:
- break;
+ break;
}
}
break;
@@ -2461,7 +2461,7 @@ get_char_length_tree1(Node* node, regex_t* reg, int* len, int level)
do {
r = get_char_length_tree1(NCAR(node), reg, &tlen, level);
if (r == 0)
- *len = (int )distance_add(*len, tlen);
+ *len = (int )distance_add(*len, tlen);
} while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
break;
@@ -2472,21 +2472,21 @@ get_char_length_tree1(Node* node, regex_t* reg, int* len, int level)
r = get_char_length_tree1(NCAR(node), reg, &tlen, level);
while (r == 0 && IS_NOT_NULL(node = NCDR(node))) {
- r = get_char_length_tree1(NCAR(node), reg, &tlen2, level);
- if (r == 0) {
- if (tlen != tlen2)
- varlen = 1;
- }
+ r = get_char_length_tree1(NCAR(node), reg, &tlen2, level);
+ if (r == 0) {
+ if (tlen != tlen2)
+ varlen = 1;
+ }
}
if (r == 0) {
- if (varlen != 0) {
- if (level == 1)
- r = GET_CHAR_LEN_TOP_ALT_VARLEN;
- else
- r = GET_CHAR_LEN_VARLEN;
- }
- else
- *len = tlen;
+ if (varlen != 0) {
+ if (level == 1)
+ r = GET_CHAR_LEN_TOP_ALT_VARLEN;
+ else
+ r = GET_CHAR_LEN_VARLEN;
+ }
+ else
+ *len = tlen;
}
}
break;
@@ -2496,8 +2496,8 @@ get_char_length_tree1(Node* node, regex_t* reg, int* len, int level)
StrNode* sn = NSTR(node);
UChar *s = sn->s;
while (s < sn->end) {
- s += enclen(reg->enc, s, sn->end);
- (*len)++;
+ s += enclen(reg->enc, s, sn->end);
+ (*len)++;
}
}
break;
@@ -2506,12 +2506,12 @@ get_char_length_tree1(Node* node, regex_t* reg, int* len, int level)
{
QtfrNode* qn = NQTFR(node);
if (qn->lower == qn->upper) {
- r = get_char_length_tree1(qn->target, reg, &tlen, level);
- if (r == 0)
- *len = (int )distance_multiply(tlen, qn->lower);
+ r = get_char_length_tree1(qn->target, reg, &tlen, level);
+ if (r == 0)
+ *len = (int )distance_multiply(tlen, qn->lower);
}
else
- r = GET_CHAR_LEN_VARLEN;
+ r = GET_CHAR_LEN_VARLEN;
}
break;
@@ -2539,25 +2539,25 @@ get_char_length_tree1(Node* node, regex_t* reg, int* len, int level)
switch (en->type) {
case ENCLOSE_MEMORY:
#ifdef USE_SUBEXP_CALL
- if (IS_ENCLOSE_CLEN_FIXED(en))
- *len = en->char_len;
- else {
- r = get_char_length_tree1(en->target, reg, len, level);
- if (r == 0) {
- en->char_len = *len;
- SET_ENCLOSE_STATUS(node, NST_CLEN_FIXED);
- }
- }
- break;
+ if (IS_ENCLOSE_CLEN_FIXED(en))
+ *len = en->char_len;
+ else {
+ r = get_char_length_tree1(en->target, reg, len, level);
+ if (r == 0) {
+ en->char_len = *len;
+ SET_ENCLOSE_STATUS(node, NST_CLEN_FIXED);
+ }
+ }
+ break;
#endif
case ENCLOSE_OPTION:
case ENCLOSE_STOP_BACKTRACK:
case ENCLOSE_CONDITION:
- r = get_char_length_tree1(en->target, reg, len, level);
- break;
+ r = get_char_length_tree1(en->target, reg, len, level);
+ break;
case ENCLOSE_ABSENT:
default:
- break;
+ break;
}
}
break;
@@ -2596,29 +2596,29 @@ is_not_included(Node* x, Node* y, regex_t* reg)
{
switch (ytype) {
case NT_CTYPE:
- if (NCTYPE(y)->ctype == NCTYPE(x)->ctype &&
- NCTYPE(y)->not != NCTYPE(x)->not &&
- NCTYPE(y)->ascii_range == NCTYPE(x)->ascii_range)
- return 1;
- else
- return 0;
- break;
+ if (NCTYPE(y)->ctype == NCTYPE(x)->ctype &&
+ NCTYPE(y)->not != NCTYPE(x)->not &&
+ NCTYPE(y)->ascii_range == NCTYPE(x)->ascii_range)
+ return 1;
+ else
+ return 0;
+ break;
case NT_CCLASS:
swap:
- {
- Node* tmp;
- tmp = x; x = y; y = tmp;
- goto retry;
- }
- break;
+ {
+ Node* tmp;
+ tmp = x; x = y; y = tmp;
+ goto retry;
+ }
+ break;
case NT_STR:
- goto swap;
- break;
+ goto swap;
+ break;
default:
- break;
+ break;
}
}
break;
@@ -2628,80 +2628,80 @@ is_not_included(Node* x, Node* y, regex_t* reg)
CClassNode* xc = NCCLASS(x);
switch (ytype) {
case NT_CTYPE:
- switch (NCTYPE(y)->ctype) {
- case ONIGENC_CTYPE_WORD:
- if (NCTYPE(y)->not == 0) {
- if (IS_NULL(xc->mbuf) && !IS_NCCLASS_NOT(xc)) {
- for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
- if (BITSET_AT(xc->bs, i)) {
- if (NCTYPE(y)->ascii_range) {
- if (IS_CODE_SB_WORD(reg->enc, i)) return 0;
- }
- else {
- if (ONIGENC_IS_CODE_WORD(reg->enc, i)) return 0;
- }
- }
- }
- return 1;
- }
- return 0;
- }
- else {
- if (IS_NOT_NULL(xc->mbuf)) return 0;
- for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
- int is_word;
- if (NCTYPE(y)->ascii_range)
- is_word = IS_CODE_SB_WORD(reg->enc, i);
- else
- is_word = ONIGENC_IS_CODE_WORD(reg->enc, i);
- if (! is_word) {
- if (!IS_NCCLASS_NOT(xc)) {
- if (BITSET_AT(xc->bs, i))
- return 0;
- }
- else {
- if (! BITSET_AT(xc->bs, i))
- return 0;
- }
- }
- }
- return 1;
- }
- break;
-
- default:
- break;
- }
- break;
+ switch (NCTYPE(y)->ctype) {
+ case ONIGENC_CTYPE_WORD:
+ if (NCTYPE(y)->not == 0) {
+ if (IS_NULL(xc->mbuf) && !IS_NCCLASS_NOT(xc)) {
+ for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
+ if (BITSET_AT(xc->bs, i)) {
+ if (NCTYPE(y)->ascii_range) {
+ if (IS_CODE_SB_WORD(reg->enc, i)) return 0;
+ }
+ else {
+ if (ONIGENC_IS_CODE_WORD(reg->enc, i)) return 0;
+ }
+ }
+ }
+ return 1;
+ }
+ return 0;
+ }
+ else {
+ if (IS_NOT_NULL(xc->mbuf)) return 0;
+ for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
+ int is_word;
+ if (NCTYPE(y)->ascii_range)
+ is_word = IS_CODE_SB_WORD(reg->enc, i);
+ else
+ is_word = ONIGENC_IS_CODE_WORD(reg->enc, i);
+ if (! is_word) {
+ if (!IS_NCCLASS_NOT(xc)) {
+ if (BITSET_AT(xc->bs, i))
+ return 0;
+ }
+ else {
+ if (! BITSET_AT(xc->bs, i))
+ return 0;
+ }
+ }
+ }
+ return 1;
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
case NT_CCLASS:
- {
- int v;
- CClassNode* yc = NCCLASS(y);
-
- for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
- v = BITSET_AT(xc->bs, i);
- if ((v != 0 && !IS_NCCLASS_NOT(xc)) ||
- (v == 0 && IS_NCCLASS_NOT(xc))) {
- v = BITSET_AT(yc->bs, i);
- if ((v != 0 && !IS_NCCLASS_NOT(yc)) ||
- (v == 0 && IS_NCCLASS_NOT(yc)))
- return 0;
- }
- }
- if ((IS_NULL(xc->mbuf) && !IS_NCCLASS_NOT(xc)) ||
- (IS_NULL(yc->mbuf) && !IS_NCCLASS_NOT(yc)))
- return 1;
- return 0;
- }
- break;
+ {
+ int v;
+ CClassNode* yc = NCCLASS(y);
+
+ for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
+ v = BITSET_AT(xc->bs, i);
+ if ((v != 0 && !IS_NCCLASS_NOT(xc)) ||
+ (v == 0 && IS_NCCLASS_NOT(xc))) {
+ v = BITSET_AT(yc->bs, i);
+ if ((v != 0 && !IS_NCCLASS_NOT(yc)) ||
+ (v == 0 && IS_NCCLASS_NOT(yc)))
+ return 0;
+ }
+ }
+ if ((IS_NULL(xc->mbuf) && !IS_NCCLASS_NOT(xc)) ||
+ (IS_NULL(yc->mbuf) && !IS_NCCLASS_NOT(yc)))
+ return 1;
+ return 0;
+ }
+ break;
case NT_STR:
- goto swap;
- break;
+ goto swap;
+ break;
default:
- break;
+ break;
}
}
break;
@@ -2710,60 +2710,60 @@ is_not_included(Node* x, Node* y, regex_t* reg)
{
StrNode* xs = NSTR(x);
if (NSTRING_LEN(x) == 0)
- break;
+ break;
switch (ytype) {
case NT_CTYPE:
- switch (NCTYPE(y)->ctype) {
- case ONIGENC_CTYPE_WORD:
- if (NCTYPE(y)->ascii_range) {
- if (ONIGENC_IS_MBC_ASCII_WORD(reg->enc, xs->s, xs->end))
- return NCTYPE(y)->not;
- else
- return !(NCTYPE(y)->not);
- }
- else {
- if (ONIGENC_IS_MBC_WORD(reg->enc, xs->s, xs->end))
- return NCTYPE(y)->not;
- else
- return !(NCTYPE(y)->not);
- }
- break;
- default:
- break;
- }
- break;
+ switch (NCTYPE(y)->ctype) {
+ case ONIGENC_CTYPE_WORD:
+ if (NCTYPE(y)->ascii_range) {
+ if (ONIGENC_IS_MBC_ASCII_WORD(reg->enc, xs->s, xs->end))
+ return NCTYPE(y)->not;
+ else
+ return !(NCTYPE(y)->not);
+ }
+ else {
+ if (ONIGENC_IS_MBC_WORD(reg->enc, xs->s, xs->end))
+ return NCTYPE(y)->not;
+ else
+ return !(NCTYPE(y)->not);
+ }
+ break;
+ default:
+ break;
+ }
+ break;
case NT_CCLASS:
- {
- CClassNode* cc = NCCLASS(y);
+ {
+ CClassNode* cc = NCCLASS(y);
- code = ONIGENC_MBC_TO_CODE(reg->enc, xs->s,
- xs->s + ONIGENC_MBC_MAXLEN(reg->enc));
- return (onig_is_code_in_cc(reg->enc, code, cc) != 0 ? 0 : 1);
- }
- break;
+ code = ONIGENC_MBC_TO_CODE(reg->enc, xs->s,
+ xs->s + ONIGENC_MBC_MAXLEN(reg->enc));
+ return (onig_is_code_in_cc(reg->enc, code, cc) != 0 ? 0 : 1);
+ }
+ break;
case NT_STR:
- {
- UChar *q;
- StrNode* ys = NSTR(y);
- len = NSTRING_LEN(x);
- if (len > NSTRING_LEN(y)) len = NSTRING_LEN(y);
- if (NSTRING_IS_AMBIG(x) || NSTRING_IS_AMBIG(y)) {
- /* tiny version */
- return 0;
- }
- else {
- for (i = 0, p = ys->s, q = xs->s; (OnigDistance )i < len; i++, p++, q++) {
- if (*p != *q) return 1;
- }
- }
- }
- break;
+ {
+ UChar *q;
+ StrNode* ys = NSTR(y);
+ len = NSTRING_LEN(x);
+ if (len > NSTRING_LEN(y)) len = NSTRING_LEN(y);
+ if (NSTRING_IS_AMBIG(x) || NSTRING_IS_AMBIG(y)) {
+ /* tiny version */
+ return 0;
+ }
+ else {
+ for (i = 0, p = ys->s, q = xs->s; (OnigDistance )i < len; i++, p++, q++) {
+ if (*p != *q) return 1;
+ }
+ }
+ }
+ break;
default:
- break;
+ break;
}
}
break;
@@ -2803,15 +2803,12 @@ get_head_value_node(Node* node, int exact, regex_t* reg)
case NT_STR:
{
StrNode* sn = NSTR(node);
-
if (sn->end <= sn->s)
- break;
+ break;
- if (exact != 0 &&
- !NSTRING_IS_RAW(node) && IS_IGNORECASE(reg->options)) {
- }
- else {
- n = node;
+ if (exact == 0 ||
+ NSTRING_IS_RAW(node) || !IS_IGNORECASE(reg->options)) {
+ n = node;
}
}
break;
@@ -2821,11 +2818,11 @@ get_head_value_node(Node* node, int exact, regex_t* reg)
QtfrNode* qn = NQTFR(node);
if (qn->lower > 0) {
#ifdef USE_OP_PUSH_OR_JUMP_EXACT
- if (IS_NOT_NULL(qn->head_exact))
- n = qn->head_exact;
- else
+ if (IS_NOT_NULL(qn->head_exact))
+ n = qn->head_exact;
+ else
#endif
- n = get_head_value_node(qn->target, exact, reg);
+ n = get_head_value_node(qn->target, exact, reg);
}
}
break;
@@ -2835,23 +2832,23 @@ get_head_value_node(Node* node, int exact, regex_t* reg)
EncloseNode* en = NENCLOSE(node);
switch (en->type) {
case ENCLOSE_OPTION:
- {
- OnigOptionType options = reg->options;
+ {
+ OnigOptionType options = reg->options;
- reg->options = NENCLOSE(node)->option;
- n = get_head_value_node(NENCLOSE(node)->target, exact, reg);
- reg->options = options;
- }
- break;
+ reg->options = NENCLOSE(node)->option;
+ n = get_head_value_node(NENCLOSE(node)->target, exact, reg);
+ reg->options = options;
+ }
+ break;
case ENCLOSE_MEMORY:
case ENCLOSE_STOP_BACKTRACK:
case ENCLOSE_CONDITION:
- n = get_head_value_node(en->target, exact, reg);
- break;
+ n = get_head_value_node(en->target, exact, reg);
+ break;
case ENCLOSE_ABSENT:
- break;
+ break;
}
}
break;
@@ -2882,20 +2879,20 @@ check_type_tree(Node* node, int type_mask, int enclose_mask, int anchor_mask)
case NT_ALT:
do {
r = check_type_tree(NCAR(node), type_mask, enclose_mask,
- anchor_mask);
+ anchor_mask);
} while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
break;
case NT_QTFR:
r = check_type_tree(NQTFR(node)->target, type_mask, enclose_mask,
- anchor_mask);
+ anchor_mask);
break;
case NT_ENCLOSE:
{
EncloseNode* en = NENCLOSE(node);
if ((en->type & enclose_mask) == 0)
- return 1;
+ return 1;
r = check_type_tree(en->target, type_mask, enclose_mask, anchor_mask);
}
@@ -2908,7 +2905,7 @@ check_type_tree(Node* node, int type_mask, int enclose_mask, int anchor_mask)
if (NANCHOR(node)->target)
r = check_type_tree(NANCHOR(node)->target,
- type_mask, enclose_mask, anchor_mask);
+ type_mask, enclose_mask, anchor_mask);
break;
default:
@@ -2938,14 +2935,14 @@ subexp_inf_recursive_check(Node* node, ScanEnv* env, int head)
x = node;
do {
- ret = subexp_inf_recursive_check(NCAR(x), env, head);
- if (ret < 0 || ret == RECURSION_INFINITE) return ret;
- r |= ret;
- if (head) {
- ret = get_min_match_length(NCAR(x), &min, env);
- if (ret != 0) return ret;
- if (min != 0) head = 0;
- }
+ ret = subexp_inf_recursive_check(NCAR(x), env, head);
+ if (ret < 0 || ret == RECURSION_INFINITE) return ret;
+ r |= ret;
+ if (head) {
+ ret = get_min_match_length(NCAR(x), &min, env);
+ if (ret != 0) return ret;
+ if (min != 0) head = 0;
+ }
} while (IS_NOT_NULL(x = NCDR(x)));
}
break;
@@ -2955,9 +2952,9 @@ subexp_inf_recursive_check(Node* node, ScanEnv* env, int head)
int ret;
r = RECURSION_EXIST;
do {
- ret = subexp_inf_recursive_check(NCAR(node), env, head);
- if (ret < 0 || ret == RECURSION_INFINITE) return ret;
- r &= ret;
+ ret = subexp_inf_recursive_check(NCAR(node), env, head);
+ if (ret < 0 || ret == RECURSION_INFINITE) return ret;
+ r &= ret;
} while (IS_NOT_NULL(node = NCDR(node)));
}
break;
@@ -2977,8 +2974,8 @@ subexp_inf_recursive_check(Node* node, ScanEnv* env, int head)
case ANCHOR_PREC_READ_NOT:
case ANCHOR_LOOK_BEHIND:
case ANCHOR_LOOK_BEHIND_NOT:
- r = subexp_inf_recursive_check(an->target, env, head);
- break;
+ r = subexp_inf_recursive_check(an->target, env, head);
+ break;
}
}
break;
@@ -3033,8 +3030,8 @@ subexp_inf_recursive_check_trav(Node* node, ScanEnv* env)
case ANCHOR_PREC_READ_NOT:
case ANCHOR_LOOK_BEHIND:
case ANCHOR_LOOK_BEHIND_NOT:
- r = subexp_inf_recursive_check_trav(an->target, env);
- break;
+ r = subexp_inf_recursive_check_trav(an->target, env);
+ break;
}
}
break;
@@ -3044,10 +3041,10 @@ subexp_inf_recursive_check_trav(Node* node, ScanEnv* env)
EncloseNode* en = NENCLOSE(node);
if (IS_ENCLOSE_RECURSION(en)) {
- SET_ENCLOSE_STATUS(node, NST_MARK1);
- r = subexp_inf_recursive_check(en->target, env, 1);
- if (r > 0) return ONIGERR_NEVER_ENDING_RECURSION;
- CLEAR_ENCLOSE_STATUS(node, NST_MARK1);
+ SET_ENCLOSE_STATUS(node, NST_MARK1);
+ r = subexp_inf_recursive_check(en->target, env, 1);
+ if (r > 0) return ONIGERR_NEVER_ENDING_RECURSION;
+ CLEAR_ENCLOSE_STATUS(node, NST_MARK1);
}
r = subexp_inf_recursive_check_trav(en->target, env);
}
@@ -3086,8 +3083,8 @@ subexp_recursive_check(Node* node)
case ANCHOR_PREC_READ_NOT:
case ANCHOR_LOOK_BEHIND:
case ANCHOR_LOOK_BEHIND_NOT:
- r = subexp_recursive_check(an->target);
- break;
+ r = subexp_recursive_check(an->target);
+ break;
}
}
break;
@@ -3132,9 +3129,9 @@ subexp_recursive_check_trav(Node* node, ScanEnv* env)
{
int ret;
do {
- ret = subexp_recursive_check_trav(NCAR(node), env);
- if (ret == FOUND_CALLED_NODE) r = FOUND_CALLED_NODE;
- else if (ret < 0) return ret;
+ ret = subexp_recursive_check_trav(NCAR(node), env);
+ if (ret == FOUND_CALLED_NODE) r = FOUND_CALLED_NODE;
+ else if (ret < 0) return ret;
} while (IS_NOT_NULL(node = NCDR(node)));
}
break;
@@ -3143,7 +3140,7 @@ subexp_recursive_check_trav(Node* node, ScanEnv* env)
r = subexp_recursive_check_trav(NQTFR(node)->target, env);
if (NQTFR(node)->upper == 0) {
if (r == FOUND_CALLED_NODE)
- NQTFR(node)->is_referred = 1;
+ NQTFR(node)->is_referred = 1;
}
break;
@@ -3155,8 +3152,8 @@ subexp_recursive_check_trav(Node* node, ScanEnv* env)
case ANCHOR_PREC_READ_NOT:
case ANCHOR_LOOK_BEHIND:
case ANCHOR_LOOK_BEHIND_NOT:
- r = subexp_recursive_check_trav(an->target, env);
- break;
+ r = subexp_recursive_check_trav(an->target, env);
+ break;
}
}
break;
@@ -3166,16 +3163,16 @@ subexp_recursive_check_trav(Node* node, ScanEnv* env)
EncloseNode* en = NENCLOSE(node);
if (! IS_ENCLOSE_RECURSION(en)) {
- if (IS_ENCLOSE_CALLED(en)) {
- SET_ENCLOSE_STATUS(node, NST_MARK1);
- r = subexp_recursive_check(en->target);
- if (r != 0) SET_ENCLOSE_STATUS(node, NST_RECURSION);
- CLEAR_ENCLOSE_STATUS(node, NST_MARK1);
- }
+ if (IS_ENCLOSE_CALLED(en)) {
+ SET_ENCLOSE_STATUS(node, NST_MARK1);
+ r = subexp_recursive_check(en->target);
+ if (r != 0) SET_ENCLOSE_STATUS(node, NST_RECURSION);
+ CLEAR_ENCLOSE_STATUS(node, NST_MARK1);
+ }
}
r = subexp_recursive_check_trav(en->target, env);
if (IS_ENCLOSE_CALLED(en))
- r |= FOUND_CALLED_NODE;
+ r |= FOUND_CALLED_NODE;
}
break;
@@ -3219,60 +3216,60 @@ setup_subexp_call(Node* node, ScanEnv* env)
Node** nodes = SCANENV_MEM_NODES(env);
if (cn->group_num != 0) {
- int gnum = cn->group_num;
+ int gnum = cn->group_num;
# ifdef USE_NAMED_GROUP
- if (env->num_named > 0 &&
- IS_SYNTAX_BV(env->syntax, ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP) &&
- !ONIG_IS_OPTION_ON(env->option, ONIG_OPTION_CAPTURE_GROUP)) {
- return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;
- }
+ if (env->num_named > 0 &&
+ IS_SYNTAX_BV(env->syntax, ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP) &&
+ !ONIG_IS_OPTION_ON(env->option, ONIG_OPTION_CAPTURE_GROUP)) {
+ return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;
+ }
# endif
- if (gnum > env->num_mem) {
- onig_scan_env_set_error_string(env,
- ONIGERR_UNDEFINED_GROUP_REFERENCE, cn->name, cn->name_end);
- return ONIGERR_UNDEFINED_GROUP_REFERENCE;
- }
+ if (gnum > env->num_mem) {
+ onig_scan_env_set_error_string(env,
+ ONIGERR_UNDEFINED_GROUP_REFERENCE, cn->name, cn->name_end);
+ return ONIGERR_UNDEFINED_GROUP_REFERENCE;
+ }
# ifdef USE_NAMED_GROUP
set_call_attr:
# endif
- cn->target = nodes[cn->group_num];
- if (IS_NULL(cn->target)) {
- onig_scan_env_set_error_string(env,
- ONIGERR_UNDEFINED_NAME_REFERENCE, cn->name, cn->name_end);
- return ONIGERR_UNDEFINED_NAME_REFERENCE;
- }
- SET_ENCLOSE_STATUS(cn->target, NST_CALLED);
- BIT_STATUS_ON_AT(env->bt_mem_start, cn->group_num);
- cn->unset_addr_list = env->unset_addr_list;
+ cn->target = nodes[cn->group_num];
+ if (IS_NULL(cn->target)) {
+ onig_scan_env_set_error_string(env,
+ ONIGERR_UNDEFINED_NAME_REFERENCE, cn->name, cn->name_end);
+ return ONIGERR_UNDEFINED_NAME_REFERENCE;
+ }
+ SET_ENCLOSE_STATUS(cn->target, NST_CALLED);
+ BIT_STATUS_ON_AT(env->bt_mem_start, cn->group_num);
+ cn->unset_addr_list = env->unset_addr_list;
}
# ifdef USE_NAMED_GROUP
# ifdef USE_PERL_SUBEXP_CALL
else if (cn->name == cn->name_end) {
- goto set_call_attr;
+ goto set_call_attr;
}
# endif
else {
- int *refs;
-
- int n = onig_name_to_group_numbers(env->reg, cn->name, cn->name_end,
- &refs);
- if (n <= 0) {
- onig_scan_env_set_error_string(env,
- ONIGERR_UNDEFINED_NAME_REFERENCE, cn->name, cn->name_end);
- return ONIGERR_UNDEFINED_NAME_REFERENCE;
- }
- else if (n > 1 &&
- ! IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME_CALL)) {
- onig_scan_env_set_error_string(env,
- ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL, cn->name, cn->name_end);
- return ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL;
- }
- else {
- cn->group_num = refs[0];
- goto set_call_attr;
- }
+ int *refs;
+
+ int n = onig_name_to_group_numbers(env->reg, cn->name, cn->name_end,
+ &refs);
+ if (n <= 0) {
+ onig_scan_env_set_error_string(env,
+ ONIGERR_UNDEFINED_NAME_REFERENCE, cn->name, cn->name_end);
+ return ONIGERR_UNDEFINED_NAME_REFERENCE;
+ }
+ else if (n > 1 &&
+ ! IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME_CALL)) {
+ onig_scan_env_set_error_string(env,
+ ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL, cn->name, cn->name_end);
+ return ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL;
+ }
+ else {
+ cn->group_num = refs[0];
+ goto set_call_attr;
+ }
}
# endif
}
@@ -3287,8 +3284,8 @@ setup_subexp_call(Node* node, ScanEnv* env)
case ANCHOR_PREC_READ_NOT:
case ANCHOR_LOOK_BEHIND:
case ANCHOR_LOOK_BEHIND_NOT:
- r = setup_subexp_call(an->target, env);
- break;
+ r = setup_subexp_call(an->target, env);
+ break;
}
}
break;
@@ -3301,6 +3298,14 @@ setup_subexp_call(Node* node, ScanEnv* env)
}
#endif
+#define IN_ALT (1<<0)
+#define IN_NOT (1<<1)
+#define IN_REPEAT (1<<2)
+#define IN_VAR_REPEAT (1<<3)
+#define IN_CALL (1<<4)
+#define IN_RECCALL (1<<5)
+#define IN_LOOK_BEHIND (1<<6)
+
/* divide different length alternatives in look-behind.
(?<=A|B) ==> (?<=A)|(?<=B)
(?<!A|B) ==> (?<!A)(?<!B)
@@ -3370,26 +3375,26 @@ next_setup(Node* node, Node* next_node, regex_t* reg)
Node* n = get_head_value_node(next_node, 1, reg);
/* '\0': for UTF-16BE etc... */
if (IS_NOT_NULL(n) && NSTR(n)->s[0] != '\0') {
- qn->next_head_exact = n;
+ qn->next_head_exact = n;
}
#endif
/* automatic possessification a*b ==> (?>a*)b */
if (qn->lower <= 1) {
- int ttype = NTYPE(qn->target);
- if (IS_NODE_TYPE_SIMPLE(ttype)) {
- Node *x, *y;
- x = get_head_value_node(qn->target, 0, reg);
- if (IS_NOT_NULL(x)) {
- y = get_head_value_node(next_node, 0, reg);
- if (IS_NOT_NULL(y) && is_not_included(x, y, reg)) {
- Node* en = onig_node_new_enclose(ENCLOSE_STOP_BACKTRACK);
- CHECK_NULL_RETURN_MEMERR(en);
- SET_ENCLOSE_STATUS(en, NST_STOP_BT_SIMPLE_REPEAT);
- swap_node(node, en);
- NENCLOSE(node)->target = en;
- }
- }
- }
+ int ttype = NTYPE(qn->target);
+ if (IS_NODE_TYPE_SIMPLE(ttype)) {
+ Node *x, *y;
+ x = get_head_value_node(qn->target, 0, reg);
+ if (IS_NOT_NULL(x)) {
+ y = get_head_value_node(next_node, 0, reg);
+ if (IS_NOT_NULL(y) && is_not_included(x, y, reg)) {
+ Node* en = onig_node_new_enclose(ENCLOSE_STOP_BACKTRACK);
+ CHECK_NULL_RETURN_MEMERR(en);
+ SET_ENCLOSE_STATUS(en, NST_STOP_BT_SIMPLE_REPEAT);
+ swap_node(node, en);
+ NENCLOSE(node)->target = en;
+ }
+ }
+ }
}
}
}
@@ -3425,15 +3430,15 @@ update_string_node_case_fold(regex_t* reg, Node *node)
len = ONIGENC_MBC_CASE_FOLD(reg->enc, reg->case_fold_flag, &p, end, buf);
for (i = 0; i < len; i++) {
if (sp >= ebuf) {
- UChar* p = (UChar* )xrealloc(sbuf, sbuf_size * 2);
- if (IS_NULL(p)) {
- xfree(sbuf);
- return ONIGERR_MEMORY;
- }
- sbuf = p;
- sp = sbuf + sbuf_size;
- sbuf_size *= 2;
- ebuf = sbuf + sbuf_size;
+ UChar* p = (UChar* )xrealloc(sbuf, sbuf_size * 2);
+ if (IS_NULL(p)) {
+ xfree(sbuf);
+ return ONIGERR_MEMORY;
+ }
+ sbuf = p;
+ sp = sbuf + sbuf_size;
+ sbuf_size *= 2;
+ ebuf = sbuf + sbuf_size;
}
*sp++ = buf[i];
@@ -3448,7 +3453,7 @@ update_string_node_case_fold(regex_t* reg, Node *node)
static int
expand_case_fold_make_rem_string(Node** rnode, UChar *s, UChar *end,
- regex_t* reg)
+ regex_t* reg)
{
int r;
Node *node;
@@ -3470,7 +3475,7 @@ expand_case_fold_make_rem_string(Node** rnode, UChar *s, UChar *end,
static int
is_case_fold_variable_len(int item_num, OnigCaseFoldCodeItem items[],
- int slen)
+ int slen)
{
int i;
@@ -3487,8 +3492,8 @@ is_case_fold_variable_len(int item_num, OnigCaseFoldCodeItem items[],
static int
expand_case_fold_string_alt(int item_num, OnigCaseFoldCodeItem items[],
- UChar *p, int slen, UChar *end,
- regex_t* reg, Node **rnode)
+ UChar *p, int slen, UChar *end,
+ regex_t* reg, Node **rnode)
{
int r, i, j, len, varlen;
Node *anode, *var_anode, *snode, *xnode, *an;
@@ -3533,8 +3538,8 @@ expand_case_fold_string_alt(int item_num, OnigCaseFoldCodeItem items[],
for (j = 0; j < items[i].code_len; j++) {
len = ONIGENC_CODE_TO_MBC(reg->enc, items[i].code[j], buf);
if (len < 0) {
- r = len;
- goto mem_err2;
+ r = len;
+ goto mem_err2;
}
r = onig_node_str_cat(snode, buf, buf + len);
@@ -3551,29 +3556,29 @@ expand_case_fold_string_alt(int item_num, OnigCaseFoldCodeItem items[],
UChar *q = p + items[i].byte_len;
if (q < end) {
- r = expand_case_fold_make_rem_string(&rem, q, end, reg);
- if (r != 0) {
- onig_node_free(an);
- goto mem_err2;
- }
+ r = expand_case_fold_make_rem_string(&rem, q, end, reg);
+ if (r != 0) {
+ onig_node_free(an);
+ goto mem_err2;
+ }
- xnode = onig_node_list_add(NULL_NODE, snode);
- if (IS_NULL(xnode)) {
- onig_node_free(an);
- onig_node_free(rem);
- goto mem_err2;
- }
- if (IS_NULL(onig_node_list_add(xnode, rem))) {
- onig_node_free(an);
- onig_node_free(xnode);
- onig_node_free(rem);
- goto mem_err;
- }
+ xnode = onig_node_list_add(NULL_NODE, snode);
+ if (IS_NULL(xnode)) {
+ onig_node_free(an);
+ onig_node_free(rem);
+ goto mem_err2;
+ }
+ if (IS_NULL(onig_node_list_add(xnode, rem))) {
+ onig_node_free(an);
+ onig_node_free(xnode);
+ onig_node_free(rem);
+ goto mem_err;
+ }
- NCAR(an) = xnode;
+ NCAR(an) = xnode;
}
else {
- NCAR(an) = snode;
+ NCAR(an) = snode;
}
NCDR(var_anode) = an;
@@ -3597,31 +3602,36 @@ expand_case_fold_string_alt(int item_num, OnigCaseFoldCodeItem items[],
return ONIGERR_MEMORY;
}
-static int
-expand_case_fold_string(Node* node, regex_t* reg)
-{
#define THRESHOLD_CASE_FOLD_ALT_FOR_EXPANSION 8
+static int
+expand_case_fold_string(Node* node, regex_t* reg, int state)
+{
int r, n, len, alt_num;
int varlen = 0;
+ int is_in_look_behind;
UChar *start, *end, *p;
Node *top_root, *root, *snode, *prev_node;
OnigCaseFoldCodeItem items[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM];
- StrNode* sn = NSTR(node);
+ StrNode* sn;
if (NSTRING_IS_AMBIG(node)) return 0;
+ sn = NSTR(node);
+
start = sn->s;
end = sn->end;
if (start >= end) return 0;
+ is_in_look_behind = (state & IN_LOOK_BEHIND) != 0;
+
r = 0;
top_root = root = prev_node = snode = NULL_NODE;
alt_num = 1;
p = start;
while (p < end) {
n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(reg->enc, reg->case_fold_flag,
- p, end, items);
+ p, end, items);
if (n < 0) {
r = n;
goto err;
@@ -3630,25 +3640,25 @@ expand_case_fold_string(Node* node, regex_t* reg)
len = enclen(reg->enc, p, end);
varlen = is_case_fold_variable_len(n, items, len);
- if (n == 0 || varlen == 0) {
+ if (n == 0 || varlen == 0 || is_in_look_behind) {
if (IS_NULL(snode)) {
- if (IS_NULL(root) && IS_NOT_NULL(prev_node)) {
+ if (IS_NULL(root) && IS_NOT_NULL(prev_node)) {
onig_node_free(top_root);
- top_root = root = onig_node_list_add(NULL_NODE, prev_node);
- if (IS_NULL(root)) {
- onig_node_free(prev_node);
- goto mem_err;
- }
- }
+ top_root = root = onig_node_list_add(NULL_NODE, prev_node);
+ if (IS_NULL(root)) {
+ onig_node_free(prev_node);
+ goto mem_err;
+ }
+ }
- prev_node = snode = onig_node_new_str(NULL, NULL);
- if (IS_NULL(snode)) goto mem_err;
- if (IS_NOT_NULL(root)) {
- if (IS_NULL(onig_node_list_add(root, snode))) {
- onig_node_free(snode);
- goto mem_err;
- }
- }
+ prev_node = snode = onig_node_new_str(NULL, NULL);
+ if (IS_NULL(snode)) goto mem_err;
+ if (IS_NOT_NULL(root)) {
+ if (IS_NULL(onig_node_list_add(root, snode))) {
+ onig_node_free(snode);
+ goto mem_err;
+ }
+ }
}
r = onig_node_str_cat(snode, p, p + len);
@@ -3659,42 +3669,42 @@ expand_case_fold_string(Node* node, regex_t* reg)
if (alt_num > THRESHOLD_CASE_FOLD_ALT_FOR_EXPANSION) break;
if (IS_NOT_NULL(snode)) {
- r = update_string_node_case_fold(reg, snode);
- if (r == 0) {
- NSTRING_SET_AMBIG(snode);
- }
+ r = update_string_node_case_fold(reg, snode);
+ if (r == 0) {
+ NSTRING_SET_AMBIG(snode);
+ }
}
if (IS_NULL(root) && IS_NOT_NULL(prev_node)) {
onig_node_free(top_root);
- top_root = root = onig_node_list_add(NULL_NODE, prev_node);
- if (IS_NULL(root)) {
- onig_node_free(prev_node);
- goto mem_err;
- }
+ top_root = root = onig_node_list_add(NULL_NODE, prev_node);
+ if (IS_NULL(root)) {
+ onig_node_free(prev_node);
+ goto mem_err;
+ }
}
r = expand_case_fold_string_alt(n, items, p, len, end, reg, &prev_node);
if (r < 0) goto mem_err;
if (r == 1) {
- if (IS_NULL(root)) {
- top_root = prev_node;
- }
- else {
- if (IS_NULL(onig_node_list_add(root, prev_node))) {
- onig_node_free(prev_node);
- goto mem_err;
- }
- }
+ if (IS_NULL(root)) {
+ top_root = prev_node;
+ }
+ else {
+ if (IS_NULL(onig_node_list_add(root, prev_node))) {
+ onig_node_free(prev_node);
+ goto mem_err;
+ }
+ }
- root = NCAR(prev_node);
+ root = NCAR(prev_node);
}
else { /* r == 0 */
- if (IS_NOT_NULL(root)) {
- if (IS_NULL(onig_node_list_add(root, prev_node))) {
- onig_node_free(prev_node);
- goto mem_err;
- }
- }
+ if (IS_NOT_NULL(root)) {
+ if (IS_NULL(onig_node_list_add(root, prev_node))) {
+ onig_node_free(prev_node);
+ goto mem_err;
+ }
+ }
}
snode = NULL_NODE;
@@ -3719,9 +3729,9 @@ expand_case_fold_string(Node* node, regex_t* reg)
onig_node_free(top_root);
top_root = root = onig_node_list_add(NULL_NODE, prev_node);
if (IS_NULL(root)) {
- onig_node_free(srem);
- onig_node_free(prev_node);
- goto mem_err;
+ onig_node_free(srem);
+ onig_node_free(prev_node);
+ goto mem_err;
}
}
@@ -3730,8 +3740,8 @@ expand_case_fold_string(Node* node, regex_t* reg)
}
else {
if (IS_NULL(onig_node_list_add(root, srem))) {
- onig_node_free(srem);
- goto mem_err;
+ onig_node_free(srem);
+ goto mem_err;
}
}
}
@@ -3771,7 +3781,7 @@ setup_comb_exp_check(Node* node, int state, ScanEnv* env)
case NT_LIST:
{
do {
- r = setup_comb_exp_check(NCAR(node), r, env);
+ r = setup_comb_exp_check(NCAR(node), r, env);
} while (r >= 0 && IS_NOT_NULL(node = NCDR(node)));
}
break;
@@ -3780,8 +3790,8 @@ setup_comb_exp_check(Node* node, int state, ScanEnv* env)
{
int ret;
do {
- ret = setup_comb_exp_check(NCAR(node), state, env);
- r |= ret;
+ ret = setup_comb_exp_check(NCAR(node), state, env);
+ r |= ret;
} while (ret >= 0 && IS_NOT_NULL(node = NCDR(node)));
}
break;
@@ -3795,55 +3805,55 @@ setup_comb_exp_check(Node* node, int state, ScanEnv* env)
int var_num;
if (! IS_REPEAT_INFINITE(qn->upper)) {
- if (qn->upper > 1) {
- /* {0,1}, {1,1} are allowed */
- child_state |= CEC_IN_FINITE_REPEAT;
-
- /* check (a*){n,m}, (a+){n,m} => (a*){n,n}, (a+){n,n} */
- if (env->backrefed_mem == 0) {
- if (NTYPE(qn->target) == NT_ENCLOSE) {
- EncloseNode* en = NENCLOSE(qn->target);
- if (en->type == ENCLOSE_MEMORY) {
- if (NTYPE(en->target) == NT_QTFR) {
- QtfrNode* q = NQTFR(en->target);
- if (IS_REPEAT_INFINITE(q->upper)
- && q->greedy == qn->greedy) {
- qn->upper = (qn->lower == 0 ? 1 : qn->lower);
- if (qn->upper == 1)
- child_state = state;
- }
- }
- }
- }
- }
- }
+ if (qn->upper > 1) {
+ /* {0,1}, {1,1} are allowed */
+ child_state |= CEC_IN_FINITE_REPEAT;
+
+ /* check (a*){n,m}, (a+){n,m} => (a*){n,n}, (a+){n,n} */
+ if (env->backrefed_mem == 0) {
+ if (NTYPE(qn->target) == NT_ENCLOSE) {
+ EncloseNode* en = NENCLOSE(qn->target);
+ if (en->type == ENCLOSE_MEMORY) {
+ if (NTYPE(en->target) == NT_QTFR) {
+ QtfrNode* q = NQTFR(en->target);
+ if (IS_REPEAT_INFINITE(q->upper)
+ && q->greedy == qn->greedy) {
+ qn->upper = (qn->lower == 0 ? 1 : qn->lower);
+ if (qn->upper == 1)
+ child_state = state;
+ }
+ }
+ }
+ }
+ }
+ }
}
if (state & CEC_IN_FINITE_REPEAT) {
- qn->comb_exp_check_num = -1;
+ qn->comb_exp_check_num = -1;
}
else {
- if (IS_REPEAT_INFINITE(qn->upper)) {
- var_num = CEC_INFINITE_NUM;
- child_state |= CEC_IN_INFINITE_REPEAT;
- }
- else {
- var_num = qn->upper - qn->lower;
- }
+ if (IS_REPEAT_INFINITE(qn->upper)) {
+ var_num = CEC_INFINITE_NUM;
+ child_state |= CEC_IN_INFINITE_REPEAT;
+ }
+ else {
+ var_num = qn->upper - qn->lower;
+ }
- if (var_num >= CEC_THRES_NUM_BIG_REPEAT)
- add_state |= CEC_CONT_BIG_REPEAT;
-
- if (((state & CEC_IN_INFINITE_REPEAT) != 0 && var_num != 0) ||
- ((state & CEC_CONT_BIG_REPEAT) != 0 &&
- var_num >= CEC_THRES_NUM_BIG_REPEAT)) {
- if (qn->comb_exp_check_num == 0) {
- env->num_comb_exp_check++;
- qn->comb_exp_check_num = env->num_comb_exp_check;
- if (env->curr_max_regnum > env->comb_exp_max_regnum)
- env->comb_exp_max_regnum = env->curr_max_regnum;
- }
- }
+ if (var_num >= CEC_THRES_NUM_BIG_REPEAT)
+ add_state |= CEC_CONT_BIG_REPEAT;
+
+ if (((state & CEC_IN_INFINITE_REPEAT) != 0 && var_num != 0) ||
+ ((state & CEC_CONT_BIG_REPEAT) != 0 &&
+ var_num >= CEC_THRES_NUM_BIG_REPEAT)) {
+ if (qn->comb_exp_check_num == 0) {
+ env->num_comb_exp_check++;
+ qn->comb_exp_check_num = env->num_comb_exp_check;
+ if (env->curr_max_regnum > env->comb_exp_max_regnum)
+ env->comb_exp_max_regnum = env->curr_max_regnum;
+ }
+ }
}
r = setup_comb_exp_check(target, child_state, env);
@@ -3857,17 +3867,17 @@ setup_comb_exp_check(Node* node, int state, ScanEnv* env)
switch (en->type) {
case ENCLOSE_MEMORY:
- {
- if (env->curr_max_regnum < en->regnum)
- env->curr_max_regnum = en->regnum;
+ {
+ if (env->curr_max_regnum < en->regnum)
+ env->curr_max_regnum = en->regnum;
- r = setup_comb_exp_check(en->target, state, env);
- }
- break;
+ r = setup_comb_exp_check(en->target, state, env);
+ }
+ break;
default:
- r = setup_comb_exp_check(en->target, state, env);
- break;
+ r = setup_comb_exp_check(en->target, state, env);
+ break;
}
}
break;
@@ -3889,13 +3899,6 @@ setup_comb_exp_check(Node* node, int state, ScanEnv* env)
}
#endif
-#define IN_ALT (1<<0)
-#define IN_NOT (1<<1)
-#define IN_REPEAT (1<<2)
-#define IN_VAR_REPEAT (1<<3)
-#define IN_CALL (1<<4)
-#define IN_RECCALL (1<<5)
-
/* setup_tree does the following work.
1. check empty loop. (set qn->target_empty_info)
2. expand ignore-case in char class.
@@ -3917,11 +3920,11 @@ restart:
{
Node* prev = NULL_NODE;
do {
- r = setup_tree(NCAR(node), reg, state, env);
- if (IS_NOT_NULL(prev) && r == 0) {
- r = next_setup(prev, NCAR(node), reg);
- }
- prev = NCAR(node);
+ r = setup_tree(NCAR(node), reg, state, env);
+ if (IS_NOT_NULL(prev) && r == 0) {
+ r = next_setup(prev, NCAR(node), reg);
+ }
+ prev = NCAR(node);
} while (r == 0 && IS_NOT_NULL(node = NCDR(node)));
}
break;
@@ -3937,7 +3940,7 @@ restart:
case NT_STR:
if (IS_IGNORECASE(reg->options) && !NSTRING_IS_RAW(node)) {
- r = expand_case_fold_string(node, reg);
+ r = expand_case_fold_string(node, reg, state);
}
break;
@@ -3958,15 +3961,15 @@ restart:
BRefNode* br = NBREF(node);
p = BACKREFS_P(br);
for (i = 0; i < br->back_num; i++) {
- if (p[i] > env->num_mem) return ONIGERR_INVALID_BACKREF;
- BIT_STATUS_ON_AT(env->backrefed_mem, p[i]);
- BIT_STATUS_ON_AT(env->bt_mem_start, p[i]);
+ if (p[i] > env->num_mem) return ONIGERR_INVALID_BACKREF;
+ BIT_STATUS_ON_AT(env->backrefed_mem, p[i]);
+ BIT_STATUS_ON_AT(env->bt_mem_start, p[i]);
#ifdef USE_BACKREF_WITH_LEVEL
- if (IS_BACKREF_NEST_LEVEL(br)) {
- BIT_STATUS_ON_AT(env->bt_mem_end, p[i]);
- }
+ if (IS_BACKREF_NEST_LEVEL(br)) {
+ BIT_STATUS_ON_AT(env->bt_mem_end, p[i]);
+ }
#endif
- SET_ENCLOSE_STATUS(nodes[p[i]], NST_MEM_BACKREFED);
+ SET_ENCLOSE_STATUS(nodes[p[i]], NST_MEM_BACKREFED);
}
}
break;
@@ -3978,100 +3981,100 @@ restart:
Node* target = qn->target;
if ((state & IN_REPEAT) != 0) {
- qn->state |= NST_IN_REPEAT;
+ qn->state |= NST_IN_REPEAT;
}
if (IS_REPEAT_INFINITE(qn->upper) || qn->upper >= 1) {
- r = get_min_match_length(target, &d, env);
- if (r) break;
- if (d == 0) {
- qn->target_empty_info = NQ_TARGET_IS_EMPTY;
+ r = get_min_match_length(target, &d, env);
+ if (r) break;
+ if (d == 0) {
+ qn->target_empty_info = NQ_TARGET_IS_EMPTY;
#ifdef USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT
- r = quantifiers_memory_node_info(target);
- if (r < 0) break;
- if (r > 0) {
- qn->target_empty_info = r;
- }
+ r = quantifiers_memory_node_info(target);
+ if (r < 0) break;
+ if (r > 0) {
+ qn->target_empty_info = r;
+ }
#endif
#if 0
- r = get_max_match_length(target, &d, env);
- if (r == 0 && d == 0) {
- /* ()* ==> ()?, ()+ ==> () */
- qn->upper = 1;
- if (qn->lower > 1) qn->lower = 1;
- if (NTYPE(target) == NT_STR) {
- qn->upper = qn->lower = 0; /* /(?:)+/ ==> // */
- }
- }
+ r = get_max_match_length(target, &d, env);
+ if (r == 0 && d == 0) {
+ /* ()* ==> ()?, ()+ ==> () */
+ qn->upper = 1;
+ if (qn->lower > 1) qn->lower = 1;
+ if (NTYPE(target) == NT_STR) {
+ qn->upper = qn->lower = 0; /* /(?:)+/ ==> // */
+ }
+ }
#endif
- }
+ }
}
state |= IN_REPEAT;
if (qn->lower != qn->upper)
- state |= IN_VAR_REPEAT;
+ state |= IN_VAR_REPEAT;
r = setup_tree(target, reg, state, env);
if (r) break;
/* expand string */
#define EXPAND_STRING_MAX_LENGTH 100
if (NTYPE(target) == NT_STR) {
- if (qn->lower > 1) {
- int i, n = qn->lower;
- OnigDistance len = NSTRING_LEN(target);
- StrNode* sn = NSTR(target);
- Node* np;
-
- np = onig_node_new_str(sn->s, sn->end);
- if (IS_NULL(np)) return ONIGERR_MEMORY;
- NSTR(np)->flag = sn->flag;
-
- for (i = 1; i < n && (i+1) * len <= EXPAND_STRING_MAX_LENGTH; i++) {
- r = onig_node_str_cat(np, sn->s, sn->end);
- if (r) {
- onig_node_free(np);
- return r;
- }
- }
- if (i < qn->upper || IS_REPEAT_INFINITE(qn->upper)) {
- Node *np1, *np2;
-
- qn->lower -= i;
- if (! IS_REPEAT_INFINITE(qn->upper))
- qn->upper -= i;
-
- np1 = onig_node_new_list(np, NULL);
- if (IS_NULL(np1)) {
- onig_node_free(np);
- return ONIGERR_MEMORY;
- }
- swap_node(np1, node);
- np2 = onig_node_list_add(node, np1);
- if (IS_NULL(np2)) {
- onig_node_free(np1);
- return ONIGERR_MEMORY;
- }
- }
- else {
- swap_node(np, node);
- onig_node_free(np);
- }
- break; /* break case NT_QTFR: */
- }
+ if (qn->lower > 1) {
+ int i, n = qn->lower;
+ OnigDistance len = NSTRING_LEN(target);
+ StrNode* sn = NSTR(target);
+ Node* np;
+
+ np = onig_node_new_str(sn->s, sn->end);
+ if (IS_NULL(np)) return ONIGERR_MEMORY;
+ NSTR(np)->flag = sn->flag;
+
+ for (i = 1; i < n && (i+1) * len <= EXPAND_STRING_MAX_LENGTH; i++) {
+ r = onig_node_str_cat(np, sn->s, sn->end);
+ if (r) {
+ onig_node_free(np);
+ return r;
+ }
+ }
+ if (i < qn->upper || IS_REPEAT_INFINITE(qn->upper)) {
+ Node *np1, *np2;
+
+ qn->lower -= i;
+ if (! IS_REPEAT_INFINITE(qn->upper))
+ qn->upper -= i;
+
+ np1 = onig_node_new_list(np, NULL);
+ if (IS_NULL(np1)) {
+ onig_node_free(np);
+ return ONIGERR_MEMORY;
+ }
+ swap_node(np1, node);
+ np2 = onig_node_list_add(node, np1);
+ if (IS_NULL(np2)) {
+ onig_node_free(np1);
+ return ONIGERR_MEMORY;
+ }
+ }
+ else {
+ swap_node(np, node);
+ onig_node_free(np);
+ }
+ break; /* break case NT_QTFR: */
+ }
}
#ifdef USE_OP_PUSH_OR_JUMP_EXACT
if (qn->greedy && (qn->target_empty_info != 0)) {
- if (NTYPE(target) == NT_QTFR) {
- QtfrNode* tqn = NQTFR(target);
- if (IS_NOT_NULL(tqn->head_exact)) {
- qn->head_exact = tqn->head_exact;
- tqn->head_exact = NULL;
- }
- }
- else {
- qn->head_exact = get_head_value_node(qn->target, 1, reg);
- }
+ if (NTYPE(target) == NT_QTFR) {
+ QtfrNode* tqn = NQTFR(target);
+ if (IS_NOT_NULL(tqn->head_exact)) {
+ qn->head_exact = tqn->head_exact;
+ tqn->head_exact = NULL;
+ }
+ }
+ else {
+ qn->head_exact = get_head_value_node(qn->target, 1, reg);
+ }
}
#endif
}
@@ -4083,61 +4086,61 @@ restart:
switch (en->type) {
case ENCLOSE_OPTION:
- {
- OnigOptionType options = reg->options;
- reg->options = NENCLOSE(node)->option;
- r = setup_tree(NENCLOSE(node)->target, reg, state, env);
- reg->options = options;
- }
- break;
+ {
+ OnigOptionType options = reg->options;
+ reg->options = NENCLOSE(node)->option;
+ r = setup_tree(NENCLOSE(node)->target, reg, state, env);
+ reg->options = options;
+ }
+ break;
case ENCLOSE_MEMORY:
- if ((state & (IN_ALT | IN_NOT | IN_VAR_REPEAT | IN_CALL)) != 0) {
- BIT_STATUS_ON_AT(env->bt_mem_start, en->regnum);
- /* SET_ENCLOSE_STATUS(node, NST_MEM_IN_ALT_NOT); */
- }
- if (IS_ENCLOSE_CALLED(en))
- state |= IN_CALL;
- if (IS_ENCLOSE_RECURSION(en))
- state |= IN_RECCALL;
- else if ((state & IN_RECCALL) != 0)
- SET_CALL_RECURSION(node);
- r = setup_tree(en->target, reg, state, env);
- break;
+ if ((state & (IN_ALT | IN_NOT | IN_VAR_REPEAT | IN_CALL)) != 0) {
+ BIT_STATUS_ON_AT(env->bt_mem_start, en->regnum);
+ /* SET_ENCLOSE_STATUS(node, NST_MEM_IN_ALT_NOT); */
+ }
+ if (IS_ENCLOSE_CALLED(en))
+ state |= IN_CALL;
+ if (IS_ENCLOSE_RECURSION(en))
+ state |= IN_RECCALL;
+ else if ((state & IN_RECCALL) != 0)
+ SET_CALL_RECURSION(node);
+ r = setup_tree(en->target, reg, state, env);
+ break;
case ENCLOSE_STOP_BACKTRACK:
- {
- Node* target = en->target;
- r = setup_tree(target, reg, state, env);
- if (NTYPE(target) == NT_QTFR) {
- QtfrNode* tqn = NQTFR(target);
- if (IS_REPEAT_INFINITE(tqn->upper) && tqn->lower <= 1 &&
- tqn->greedy != 0) { /* (?>a*), a*+ etc... */
- int qtype = NTYPE(tqn->target);
- if (IS_NODE_TYPE_SIMPLE(qtype))
- SET_ENCLOSE_STATUS(node, NST_STOP_BT_SIMPLE_REPEAT);
- }
- }
- }
- break;
+ {
+ Node* target = en->target;
+ r = setup_tree(target, reg, state, env);
+ if (NTYPE(target) == NT_QTFR) {
+ QtfrNode* tqn = NQTFR(target);
+ if (IS_REPEAT_INFINITE(tqn->upper) && tqn->lower <= 1 &&
+ tqn->greedy != 0) { /* (?>a*), a*+ etc... */
+ int qtype = NTYPE(tqn->target);
+ if (IS_NODE_TYPE_SIMPLE(qtype))
+ SET_ENCLOSE_STATUS(node, NST_STOP_BT_SIMPLE_REPEAT);
+ }
+ }
+ }
+ break;
case ENCLOSE_CONDITION:
#ifdef USE_NAMED_GROUP
- if (! IS_ENCLOSE_NAME_REF(NENCLOSE(node)) &&
- env->num_named > 0 &&
- IS_SYNTAX_BV(env->syntax, ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP) &&
- !ONIG_IS_OPTION_ON(env->option, ONIG_OPTION_CAPTURE_GROUP)) {
- return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;
- }
+ if (! IS_ENCLOSE_NAME_REF(NENCLOSE(node)) &&
+ env->num_named > 0 &&
+ IS_SYNTAX_BV(env->syntax, ONIG_SYN_CAPTURE_ONLY_NAMED_GROUP) &&
+ !ONIG_IS_OPTION_ON(env->option, ONIG_OPTION_CAPTURE_GROUP)) {
+ return ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED;
+ }
#endif
- if (NENCLOSE(node)->regnum > env->num_mem)
- return ONIGERR_INVALID_BACKREF;
- r = setup_tree(NENCLOSE(node)->target, reg, state, env);
- break;
+ if (NENCLOSE(node)->regnum > env->num_mem)
+ return ONIGERR_INVALID_BACKREF;
+ r = setup_tree(NENCLOSE(node)->target, reg, state, env);
+ break;
case ENCLOSE_ABSENT:
- r = setup_tree(NENCLOSE(node)->target, reg, state, env);
- break;
+ r = setup_tree(NENCLOSE(node)->target, reg, state, env);
+ break;
}
}
break;
@@ -4148,11 +4151,11 @@ restart:
switch (an->type) {
case ANCHOR_PREC_READ:
- r = setup_tree(an->target, reg, state, env);
- break;
+ r = setup_tree(an->target, reg, state, env);
+ break;
case ANCHOR_PREC_READ_NOT:
- r = setup_tree(an->target, reg, (state | IN_NOT), env);
- break;
+ r = setup_tree(an->target, reg, (state | IN_NOT), env);
+ break;
/* allowed node types in look-behind */
#define ALLOWED_TYPE_IN_LB \
@@ -4174,30 +4177,31 @@ restart:
ANCHOR_WORD_BEGIN | ANCHOR_WORD_END )
case ANCHOR_LOOK_BEHIND:
- {
- r = check_type_tree(an->target, ALLOWED_TYPE_IN_LB,
- ALLOWED_ENCLOSE_IN_LB, ALLOWED_ANCHOR_IN_LB);
- if (r < 0) return r;
- if (r > 0) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
- if (NTYPE(node) != NT_ANCHOR) goto restart;
- r = setup_tree(an->target, reg, state, env);
- if (r != 0) return r;
- r = setup_look_behind(node, reg, env);
- }
- break;
+ {
+ r = check_type_tree(an->target, ALLOWED_TYPE_IN_LB,
+ ALLOWED_ENCLOSE_IN_LB, ALLOWED_ANCHOR_IN_LB);
+ if (r < 0) return r;
+ if (r > 0) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
+ if (NTYPE(node) != NT_ANCHOR) goto restart;
+ r = setup_tree(an->target, reg, (state | IN_LOOK_BEHIND), env);
+ if (r != 0) return r;
+ r = setup_look_behind(node, reg, env);
+ }
+ break;
case ANCHOR_LOOK_BEHIND_NOT:
- {
- r = check_type_tree(an->target, ALLOWED_TYPE_IN_LB,
- ALLOWED_ENCLOSE_IN_LB_NOT, ALLOWED_ANCHOR_IN_LB_NOT);
- if (r < 0) return r;
- if (r > 0) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
- if (NTYPE(node) != NT_ANCHOR) goto restart;
- r = setup_tree(an->target, reg, (state | IN_NOT), env);
- if (r != 0) return r;
- r = setup_look_behind(node, reg, env);
- }
- break;
+ {
+ r = check_type_tree(an->target, ALLOWED_TYPE_IN_LB,
+ ALLOWED_ENCLOSE_IN_LB_NOT, ALLOWED_ANCHOR_IN_LB_NOT);
+ if (r < 0) return r;
+ if (r > 0) return ONIGERR_INVALID_LOOK_BEHIND_PATTERN;
+ if (NTYPE(node) != NT_ANCHOR) goto restart;
+ r = setup_tree(an->target, reg, (state | IN_NOT | IN_LOOK_BEHIND),
+ env);
+ if (r != 0) return r;
+ r = setup_look_behind(node, reg, env);
+ }
+ break;
}
}
break;
@@ -4209,169 +4213,73 @@ restart:
return r;
}
-#ifndef USE_SUNDAY_QUICK_SEARCH
-/* set skip map for Boyer-Moore search */
+/* set skip map for Sunday's quick search */
static int
set_bm_skip(UChar* s, UChar* end, regex_t* reg,
- UChar skip[], int** int_skip, int ignore_case)
+ UChar skip[], int ignore_case)
{
OnigDistance i, len;
int clen, flen, n, j, k;
- UChar *p, buf[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM][ONIGENC_MBC_CASE_FOLD_MAXLEN];
+ UChar *p, buf[ONIGENC_MBC_CASE_FOLD_MAXLEN];
OnigCaseFoldCodeItem items[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM];
OnigEncoding enc = reg->enc;
len = end - s;
- if (len < ONIG_CHAR_TABLE_SIZE) {
- for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) skip[i] = (UChar )len;
-
- n = 0;
- for (i = 0; i < len - 1; i += clen) {
- p = s + i;
- if (ignore_case)
- n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc, reg->case_fold_flag,
- p, end, items);
- clen = enclen(enc, p, end);
- if (p + clen > end)
- clen = (int )(end - p);
-
- for (j = 0; j < n; j++) {
- if ((items[j].code_len != 1) || (items[j].byte_len != clen))
- return 1; /* different length isn't supported. */
- flen = ONIGENC_CODE_TO_MBC(enc, items[j].code[0], buf[j]);
- if (flen != clen)
- return 1; /* different length isn't supported. */
- }
- for (j = 0; j < clen; j++) {
- skip[s[i + j]] = (UChar )(len - 1 - i - j);
- for (k = 0; k < n; k++) {
- skip[buf[k][j]] = (UChar )(len - 1 - i - j);
- }
- }
- }
- }
- else {
-# if OPT_EXACT_MAXLEN < ONIG_CHAR_TABLE_SIZE
+ if (len >= ONIG_CHAR_TABLE_SIZE) {
/* This should not happen. */
return ONIGERR_TYPE_BUG;
-# else
- if (IS_NULL(*int_skip)) {
- *int_skip = (int* )xmalloc(sizeof(int) * ONIG_CHAR_TABLE_SIZE);
- if (IS_NULL(*int_skip)) return ONIGERR_MEMORY;
- }
- for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) (*int_skip)[i] = (int )len;
-
- n = 0;
- for (i = 0; i < len - 1; i += clen) {
- p = s + i;
- if (ignore_case)
- n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc, reg->case_fold_flag,
- p, end, items);
- clen = enclen(enc, p, end);
- if (p + clen > end)
- clen = (int )(end - p);
-
- for (j = 0; j < n; j++) {
- if ((items[j].code_len != 1) || (items[j].byte_len != clen))
- return 1; /* different length isn't supported. */
- flen = ONIGENC_CODE_TO_MBC(enc, items[j].code[0], buf[j]);
- if (flen != clen)
- return 1; /* different length isn't supported. */
- }
- for (j = 0; j < clen; j++) {
- (*int_skip)[s[i + j]] = (int )(len - 1 - i - j);
- for (k = 0; k < n; k++) {
- (*int_skip)[buf[k][j]] = (int )(len - 1 - i - j);
- }
- }
- }
-# endif
}
- return 0;
-}
-
-#else /* USE_SUNDAY_QUICK_SEARCH */
-
-/* set skip map for Sunday's quick search */
-static int
-set_bm_skip(UChar* s, UChar* end, regex_t* reg,
- UChar skip[], int** int_skip, int ignore_case)
-{
- OnigDistance i, len;
- int clen, flen, n, j, k;
- UChar *p, buf[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM][ONIGENC_MBC_CASE_FOLD_MAXLEN];
- OnigCaseFoldCodeItem items[ONIGENC_GET_CASE_FOLD_CODES_MAX_NUM];
- OnigEncoding enc = reg->enc;
-
- len = end - s;
- if (len < ONIG_CHAR_TABLE_SIZE) {
- for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) skip[i] = (UChar )(len + 1);
- n = 0;
+ if (ignore_case) {
for (i = 0; i < len; i += clen) {
p = s + i;
- if (ignore_case)
- n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc, reg->case_fold_flag,
- p, end, items);
+ n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc, reg->case_fold_flag,
+ p, end, items);
clen = enclen(enc, p, end);
if (p + clen > end)
- clen = (int )(end - p);
+ clen = (int )(end - p);
for (j = 0; j < n; j++) {
- if ((items[j].code_len != 1) || (items[j].byte_len != clen))
- return 1; /* different length isn't supported. */
- flen = ONIGENC_CODE_TO_MBC(enc, items[j].code[0], buf[j]);
- if (flen != clen)
- return 1; /* different length isn't supported. */
- }
- for (j = 0; j < clen; j++) {
- skip[s[i + j]] = (UChar )(len - i - j);
- for (k = 0; k < n; k++) {
- skip[buf[k][j]] = (UChar )(len - i - j);
+ if ((items[j].code_len != 1) || (items[j].byte_len != clen)) {
+ /* Different length isn't supported. Stop optimization at here. */
+ end = p;
+ goto endcheck;
+ }
+ flen = ONIGENC_CODE_TO_MBC(enc, items[j].code[0], buf);
+ if (flen != clen) {
+ /* Different length isn't supported. Stop optimization at here. */
+ end = p;
+ goto endcheck;
}
}
}
+endcheck:
+ len = end - s;
}
- else {
-# if OPT_EXACT_MAXLEN < ONIG_CHAR_TABLE_SIZE
- /* This should not happen. */
- return ONIGERR_TYPE_BUG;
-# else
- if (IS_NULL(*int_skip)) {
- *int_skip = (int* )xmalloc(sizeof(int) * ONIG_CHAR_TABLE_SIZE);
- if (IS_NULL(*int_skip)) return ONIGERR_MEMORY;
- }
- for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) (*int_skip)[i] = (int )(len + 1);
-
- n = 0;
- for (i = 0; i < len; i += clen) {
- p = s + i;
- if (ignore_case)
- n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc, reg->case_fold_flag,
- p, end, items);
- clen = enclen(enc, p, end);
- if (p + clen > end)
- clen = (int )(end - p);
- for (j = 0; j < n; j++) {
- if ((items[j].code_len != 1) || (items[j].byte_len != clen))
- return 1; /* different length isn't supported. */
- flen = ONIGENC_CODE_TO_MBC(enc, items[j].code[0], buf[j]);
- if (flen != clen)
- return 1; /* different length isn't supported. */
- }
- for (j = 0; j < clen; j++) {
- (*int_skip)[s[i + j]] = (int )(len - i - j);
- for (k = 0; k < n; k++) {
- (*int_skip)[buf[k][j]] = (int )(len - i - j);
- }
+ for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++)
+ skip[i] = (UChar )(len + 1);
+ n = 0;
+ for (i = 0; i < len; i += clen) {
+ p = s + i;
+ if (ignore_case)
+ n = ONIGENC_GET_CASE_FOLD_CODES_BY_STR(enc, reg->case_fold_flag,
+ p, end, items);
+ clen = enclen(enc, p, end);
+ if (p + clen > end)
+ clen = (int )(end - p);
+
+ for (j = 0; j < clen; j++) {
+ skip[s[i + j]] = (UChar )(len - i - j);
+ for (k = 0; k < n; k++) {
+ ONIGENC_CODE_TO_MBC(enc, items[k].code[0], buf);
+ skip[buf[j]] = (UChar )(len - i - j);
}
}
-# endif
}
- return 0;
+
+ return (int )len;
}
-#endif /* USE_SUNDAY_QUICK_SEARCH */
typedef struct {
OnigDistance min; /* min byte length */
@@ -4562,7 +4470,7 @@ copy_opt_anc_info(OptAncInfo* to, OptAncInfo* from)
static void
concat_opt_anc_info(OptAncInfo* to, OptAncInfo* left, OptAncInfo* right,
- OnigDistance left_len, OnigDistance right_len)
+ OnigDistance left_len, OnigDistance right_len)
{
clear_opt_anc_info(to);
@@ -4678,7 +4586,7 @@ concat_opt_exact_info(OptExactInfo* to, OptExactInfo* add, OnigEncoding enc)
static void
concat_opt_exact_info_str(OptExactInfo* to, UChar* s, UChar* end,
- int raw ARG_UNUSED, OnigEncoding enc)
+ int raw ARG_UNUSED, OnigEncoding enc)
{
int i, j, len;
UChar *p;
@@ -4923,7 +4831,7 @@ concat_left_node_opt_info(OnigEncoding enc, NodeOptInfo* to, NodeOptInfo* add)
if (add->exb.len > 0 && to->len.max == 0) {
concat_opt_anc_info(&tanc, &to->anc, &add->exb.anc,
- to->len.max, add->len.max);
+ to->len.max, add->len.max);
copy_opt_anc_info(&add->exb.anc, &tanc);
}
@@ -4954,12 +4862,12 @@ concat_left_node_opt_info(OnigEncoding enc, NodeOptInfo* to, NodeOptInfo* add)
if (to->expr.len > 0) {
if (add->len.max > 0) {
if (to->expr.len > (int )add->len.max)
- to->expr.len = (int )add->len.max;
+ to->expr.len = (int )add->len.max;
if (to->expr.mmd.max == 0)
- select_opt_exact_info(enc, &to->exb, &to->expr);
+ select_opt_exact_info(enc, &to->exb, &to->expr);
else
- select_opt_exact_info(enc, &to->exm, &to->expr);
+ select_opt_exact_info(enc, &to->exm, &to->expr);
}
}
else if (add->expr.len > 0) {
@@ -5005,11 +4913,11 @@ optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env)
copy_opt_env(&nenv, env);
do {
- r = optimize_node_left(NCAR(nd), &nopt, &nenv);
- if (r == 0) {
- add_mml(&nenv.mmd, &nopt.len);
- concat_left_node_opt_info(env->enc, opt, &nopt);
- }
+ r = optimize_node_left(NCAR(nd), &nopt, &nenv);
+ if (r == 0) {
+ add_mml(&nenv.mmd, &nopt.len);
+ concat_left_node_opt_info(env->enc, opt, &nopt);
+ }
} while (r == 0 && IS_NOT_NULL(nd = NCDR(nd)));
}
break;
@@ -5020,11 +4928,11 @@ optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env)
Node* nd = node;
do {
- r = optimize_node_left(NCAR(nd), &nopt, env);
- if (r == 0) {
- if (nd == node) copy_node_opt_info(opt, &nopt);
- else alt_merge_node_opt_info(opt, &nopt, env);
- }
+ r = optimize_node_left(NCAR(nd), &nopt, env);
+ if (r == 0) {
+ if (nd == node) copy_node_opt_info(opt, &nopt);
+ else alt_merge_node_opt_info(opt, &nopt, env);
+ }
} while ((r == 0) && IS_NOT_NULL(nd = NCDR(nd)));
}
break;
@@ -5036,40 +4944,40 @@ optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env)
int is_raw = NSTRING_IS_RAW(node);
if (! NSTRING_IS_AMBIG(node)) {
- concat_opt_exact_info_str(&opt->exb, sn->s, sn->end,
- is_raw, env->enc);
- opt->exb.ignore_case = 0;
- if (slen > 0) {
- add_char_opt_map_info(&opt->map, *(sn->s), env->enc);
- }
- set_mml(&opt->len, slen, slen);
+ concat_opt_exact_info_str(&opt->exb, sn->s, sn->end,
+ is_raw, env->enc);
+ opt->exb.ignore_case = 0;
+ if (slen > 0) {
+ add_char_opt_map_info(&opt->map, *(sn->s), env->enc);
+ }
+ set_mml(&opt->len, slen, slen);
}
else {
- OnigDistance max;
+ OnigDistance max;
- 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) * (OnigDistance)n;
- }
- else {
- concat_opt_exact_info_str(&opt->exb, sn->s, sn->end,
- is_raw, env->enc);
- opt->exb.ignore_case = 1;
-
- if (slen > 0) {
- r = add_char_amb_opt_map_info(&opt->map, sn->s, sn->end,
- env->enc, env->case_fold_flag);
- if (r != 0) break;
- }
-
- max = slen;
- }
+ if (NSTRING_IS_DONT_GET_OPT_INFO(node)) {
+ int n = onigenc_strlen(env->enc, sn->s, sn->end);
+ max = (OnigDistance )ONIGENC_MBC_MAXLEN_DIST(env->enc) * (OnigDistance)n;
+ }
+ else {
+ concat_opt_exact_info_str(&opt->exb, sn->s, sn->end,
+ is_raw, env->enc);
+ opt->exb.ignore_case = 1;
- set_mml(&opt->len, slen, max);
+ if (slen > 0) {
+ r = add_char_amb_opt_map_info(&opt->map, sn->s, sn->end,
+ env->enc, env->case_fold_flag);
+ if (r != 0) break;
+ }
+
+ max = slen;
+ }
+
+ set_mml(&opt->len, slen, max);
}
if ((OnigDistance )opt->exb.len == slen)
- opt->exb.reach_end = 1;
+ opt->exb.reach_end = 1;
}
break;
@@ -5081,19 +4989,19 @@ optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env)
/* no need to check ignore case. (set in setup_tree()) */
if (IS_NOT_NULL(cc->mbuf) || IS_NCCLASS_NOT(cc)) {
- OnigDistance min = ONIGENC_MBC_MINLEN(env->enc);
- OnigDistance max = ONIGENC_MBC_MAXLEN_DIST(env->enc);
+ OnigDistance min = ONIGENC_MBC_MINLEN(env->enc);
+ OnigDistance max = ONIGENC_MBC_MAXLEN_DIST(env->enc);
- set_mml(&opt->len, min, max);
+ set_mml(&opt->len, min, max);
}
else {
- for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
- z = BITSET_AT(cc->bs, i);
- if ((z && !IS_NCCLASS_NOT(cc)) || (!z && IS_NCCLASS_NOT(cc))) {
- add_char_opt_map_info(&opt->map, (UChar )i, env->enc);
- }
- }
- set_mml(&opt->len, 1, 1);
+ for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
+ z = BITSET_AT(cc->bs, i);
+ if ((z && !IS_NCCLASS_NOT(cc)) || (!z && IS_NCCLASS_NOT(cc))) {
+ add_char_opt_map_info(&opt->map, (UChar )i, env->enc);
+ }
+ }
+ set_mml(&opt->len, 1, 1);
}
}
break;
@@ -5106,30 +5014,30 @@ optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env)
max = ONIGENC_MBC_MAXLEN_DIST(env->enc);
if (max == 1) {
- min = 1;
-
- maxcode = NCTYPE(node)->ascii_range ? 0x80 : SINGLE_BYTE_SIZE;
- switch (NCTYPE(node)->ctype) {
- case ONIGENC_CTYPE_WORD:
- if (NCTYPE(node)->not != 0) {
- for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
- if (! ONIGENC_IS_CODE_WORD(env->enc, i) || i >= maxcode) {
- add_char_opt_map_info(&opt->map, (UChar )i, env->enc);
- }
- }
- }
- else {
- for (i = 0; i < maxcode; i++) {
- if (ONIGENC_IS_CODE_WORD(env->enc, i)) {
- add_char_opt_map_info(&opt->map, (UChar )i, env->enc);
- }
- }
- }
- break;
- }
+ min = 1;
+
+ maxcode = NCTYPE(node)->ascii_range ? 0x80 : SINGLE_BYTE_SIZE;
+ switch (NCTYPE(node)->ctype) {
+ case ONIGENC_CTYPE_WORD:
+ if (NCTYPE(node)->not != 0) {
+ for (i = 0; i < SINGLE_BYTE_SIZE; i++) {
+ if (! ONIGENC_IS_CODE_WORD(env->enc, i) || i >= maxcode) {
+ add_char_opt_map_info(&opt->map, (UChar )i, env->enc);
+ }
+ }
+ }
+ else {
+ for (i = 0; i < maxcode; i++) {
+ if (ONIGENC_IS_CODE_WORD(env->enc, i)) {
+ add_char_opt_map_info(&opt->map, (UChar )i, env->enc);
+ }
+ }
+ }
+ break;
+ }
}
else {
- min = ONIGENC_MBC_MINLEN(env->enc);
+ min = ONIGENC_MBC_MINLEN(env->enc);
}
set_mml(&opt->len, min, max);
}
@@ -5158,20 +5066,20 @@ optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env)
case ANCHOR_PREC_READ:
{
- NodeOptInfo nopt;
+ NodeOptInfo nopt;
- r = optimize_node_left(NANCHOR(node)->target, &nopt, env);
- if (r == 0) {
- if (nopt.exb.len > 0)
- copy_opt_exact_info(&opt->expr, &nopt.exb);
- else if (nopt.exm.len > 0)
- copy_opt_exact_info(&opt->expr, &nopt.exm);
+ r = optimize_node_left(NANCHOR(node)->target, &nopt, env);
+ if (r == 0) {
+ if (nopt.exb.len > 0)
+ copy_opt_exact_info(&opt->expr, &nopt.exb);
+ else if (nopt.exm.len > 0)
+ copy_opt_exact_info(&opt->expr, &nopt.exm);
- opt->expr.reach_end = 0;
+ opt->expr.reach_end = 0;
- if (nopt.map.value > 0)
- copy_opt_map_info(&opt->map, &nopt.map);
- }
+ if (nopt.map.value > 0)
+ copy_opt_map_info(&opt->map, &nopt.map);
+ }
}
break;
@@ -5189,8 +5097,8 @@ optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env)
BRefNode* br = NBREF(node);
if (br->state & NST_RECURSION) {
- set_mml(&opt->len, 0, ONIG_INFINITE_DISTANCE);
- break;
+ set_mml(&opt->len, 0, ONIG_INFINITE_DISTANCE);
+ break;
}
backs = BACKREFS_P(br);
r = get_min_match_length(nodes[backs[0]], &min, env->scan_env);
@@ -5198,12 +5106,12 @@ optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env)
r = get_max_match_length(nodes[backs[0]], &max, env->scan_env);
if (r != 0) break;
for (i = 1; i < br->back_num; i++) {
- r = get_min_match_length(nodes[backs[i]], &tmin, env->scan_env);
- if (r != 0) break;
- r = get_max_match_length(nodes[backs[i]], &tmax, env->scan_env);
- if (r != 0) break;
- if (min > tmin) min = tmin;
- if (max < tmax) max = tmax;
+ r = get_min_match_length(nodes[backs[i]], &tmin, env->scan_env);
+ if (r != 0) break;
+ r = get_max_match_length(nodes[backs[i]], &tmax, env->scan_env);
+ if (r != 0) break;
+ if (min > tmin) min = tmin;
+ if (max < tmax) max = tmax;
}
if (r == 0) set_mml(&opt->len, min, max);
}
@@ -5232,45 +5140,45 @@ optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env)
r = optimize_node_left(qn->target, &nopt, env);
if (r) break;
- if (/*qn->lower == 0 &&*/ IS_REPEAT_INFINITE(qn->upper)) {
- if (env->mmd.max == 0 &&
- NTYPE(qn->target) == NT_CANY && qn->greedy) {
- if (IS_MULTILINE(env->options))
- /* implicit anchor: /.*a/ ==> /\A.*a/ */
- add_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR_ML);
- else
- add_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR);
- }
+ if (qn->lower == 0 && IS_REPEAT_INFINITE(qn->upper)) {
+ if (env->mmd.max == 0 &&
+ NTYPE(qn->target) == NT_CANY && qn->greedy) {
+ if (IS_MULTILINE(env->options))
+ /* implicit anchor: /.*a/ ==> /\A.*a/ */
+ add_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR_ML);
+ else
+ add_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR);
+ }
}
else {
- if (qn->lower > 0) {
- copy_node_opt_info(opt, &nopt);
- if (nopt.exb.len > 0) {
- if (nopt.exb.reach_end) {
- for (i = 2; i <= qn->lower &&
- ! is_full_opt_exact_info(&opt->exb); i++) {
- concat_opt_exact_info(&opt->exb, &nopt.exb, env->enc);
- }
- if (i < qn->lower) {
- opt->exb.reach_end = 0;
- }
- }
- }
-
- if (qn->lower != qn->upper) {
- opt->exb.reach_end = 0;
- opt->exm.reach_end = 0;
- }
- if (qn->lower > 1)
- opt->exm.reach_end = 0;
- }
+ if (qn->lower > 0) {
+ copy_node_opt_info(opt, &nopt);
+ if (nopt.exb.len > 0) {
+ if (nopt.exb.reach_end) {
+ for (i = 2; i <= qn->lower &&
+ ! is_full_opt_exact_info(&opt->exb); i++) {
+ concat_opt_exact_info(&opt->exb, &nopt.exb, env->enc);
+ }
+ if (i < qn->lower) {
+ opt->exb.reach_end = 0;
+ }
+ }
+ }
+
+ if (qn->lower != qn->upper) {
+ opt->exb.reach_end = 0;
+ opt->exm.reach_end = 0;
+ }
+ if (qn->lower > 1)
+ opt->exm.reach_end = 0;
+ }
}
min = distance_multiply(nopt.len.min, qn->lower);
if (IS_REPEAT_INFINITE(qn->upper))
- max = (nopt.len.max > 0 ? ONIG_INFINITE_DISTANCE : 0);
+ max = (nopt.len.max > 0 ? ONIG_INFINITE_DISTANCE : 0);
else
- max = distance_multiply(nopt.len.max, qn->upper);
+ max = distance_multiply(nopt.len.max, qn->upper);
set_mml(&opt->len, min, max);
}
@@ -5282,47 +5190,47 @@ optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env)
switch (en->type) {
case ENCLOSE_OPTION:
- {
- OnigOptionType save = env->options;
+ {
+ OnigOptionType save = env->options;
- env->options = en->option;
- r = optimize_node_left(en->target, opt, env);
- env->options = save;
- }
- break;
+ env->options = en->option;
+ r = optimize_node_left(en->target, opt, env);
+ env->options = save;
+ }
+ break;
case ENCLOSE_MEMORY:
#ifdef USE_SUBEXP_CALL
- en->opt_count++;
- if (en->opt_count > MAX_NODE_OPT_INFO_REF_COUNT) {
- OnigDistance min, max;
-
- min = 0;
- max = ONIG_INFINITE_DISTANCE;
- if (IS_ENCLOSE_MIN_FIXED(en)) min = en->min_len;
- if (IS_ENCLOSE_MAX_FIXED(en)) max = en->max_len;
- set_mml(&opt->len, min, max);
- }
- else
+ en->opt_count++;
+ if (en->opt_count > MAX_NODE_OPT_INFO_REF_COUNT) {
+ OnigDistance min, max;
+
+ min = 0;
+ max = ONIG_INFINITE_DISTANCE;
+ if (IS_ENCLOSE_MIN_FIXED(en)) min = en->min_len;
+ if (IS_ENCLOSE_MAX_FIXED(en)) max = en->max_len;
+ set_mml(&opt->len, min, max);
+ }
+ else
#endif
- {
- r = optimize_node_left(en->target, opt, env);
+ {
+ r = optimize_node_left(en->target, opt, env);
- if (is_set_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR_MASK)) {
- if (BIT_STATUS_AT(env->scan_env->backrefed_mem, en->regnum))
- remove_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR_MASK);
- }
- }
- break;
+ if (is_set_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR_MASK)) {
+ if (BIT_STATUS_AT(env->scan_env->backrefed_mem, en->regnum))
+ remove_opt_anc_info(&opt->anc, ANCHOR_ANYCHAR_STAR_MASK);
+ }
+ }
+ break;
case ENCLOSE_STOP_BACKTRACK:
case ENCLOSE_CONDITION:
- r = optimize_node_left(en->target, opt, env);
- break;
+ r = optimize_node_left(en->target, opt, env);
+ break;
case ENCLOSE_ABSENT:
- set_mml(&opt->len, 0, ONIG_INFINITE_DISTANCE);
- break;
+ set_mml(&opt->len, 0, ONIG_INFINITE_DISTANCE);
+ break;
}
}
break;
@@ -5330,7 +5238,7 @@ optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env)
default:
#ifdef ONIG_DEBUG
fprintf(stderr, "optimize_node_left: undefined node type %d\n",
- NTYPE(node));
+ NTYPE(node));
#endif
r = ONIGERR_TYPE_BUG;
break;
@@ -5342,7 +5250,6 @@ optimize_node_left(Node* node, NodeOptInfo* opt, OptEnv* env)
static int
set_optimize_exact_info(regex_t* reg, OptExactInfo* e)
{
- int r;
int allow_reverse;
if (e->len == 0) return 0;
@@ -5353,18 +5260,27 @@ set_optimize_exact_info(regex_t* reg, OptExactInfo* e)
reg->exact_end = reg->exact + e->len;
allow_reverse =
- ONIGENC_IS_ALLOWED_REVERSE_MATCH(reg->enc, reg->exact, reg->exact_end);
+ ONIGENC_IS_ALLOWED_REVERSE_MATCH(reg->enc, reg->exact, reg->exact_end);
if (e->ignore_case > 0) {
if (e->len >= 3 || (e->len >= 2 && allow_reverse)) {
- r = set_bm_skip(reg->exact, reg->exact_end, reg,
- reg->map, &(reg->int_map), 1);
- if (r == 0) {
- reg->optimize = (allow_reverse != 0
- ? ONIG_OPTIMIZE_EXACT_BM_IC : ONIG_OPTIMIZE_EXACT_BM_NOT_REV_IC);
+ int orig_len = e->len;
+ e->len = set_bm_skip(reg->exact, reg->exact_end, reg,
+ reg->map, 1);
+ if (e->len >= 3) {
+ reg->exact_end = reg->exact + e->len;
+ reg->optimize = (allow_reverse != 0
+ ? ONIG_OPTIMIZE_EXACT_BM_IC : ONIG_OPTIMIZE_EXACT_BM_NOT_REV_IC);
}
else {
- reg->optimize = ONIG_OPTIMIZE_EXACT_IC;
+ /* Even if BM skip table can't be built (e.g., pattern starts with
+ 's' or 'k' which have multi-byte case fold variants), we should
+ still use EXACT_IC optimization with the original pattern.
+ Without this fallback, patterns like /slackware/i have no
+ optimization at all, causing severe performance regression
+ especially with non-ASCII strings. See [Bug #21824] */
+ e->len = orig_len; /* Restore original length for EXACT_IC */
+ reg->optimize = ONIG_OPTIMIZE_EXACT_IC;
}
}
else {
@@ -5373,15 +5289,10 @@ set_optimize_exact_info(regex_t* reg, OptExactInfo* e)
}
else {
if (e->len >= 3 || (e->len >= 2 && allow_reverse)) {
- r = set_bm_skip(reg->exact, reg->exact_end, reg,
- reg->map, &(reg->int_map), 0);
- if (r == 0) {
- reg->optimize = (allow_reverse != 0
- ? ONIG_OPTIMIZE_EXACT_BM : ONIG_OPTIMIZE_EXACT_BM_NOT_REV);
- }
- else {
- reg->optimize = ONIG_OPTIMIZE_EXACT;
- }
+ set_bm_skip(reg->exact, reg->exact_end, reg,
+ reg->map, 0);
+ reg->optimize = (allow_reverse != 0
+ ? ONIG_OPTIMIZE_EXACT_BM : ONIG_OPTIMIZE_EXACT_BM_NOT_REV);
}
else {
reg->optimize = ONIG_OPTIMIZE_EXACT;
@@ -5451,7 +5362,7 @@ set_optimize_info_from_tree(Node* node, regex_t* reg, ScanEnv* scan_env)
reg->anchor &= ~ANCHOR_ANYCHAR_STAR_ML;
reg->anchor |= opt.anc.right_anchor & (ANCHOR_END_BUF | ANCHOR_SEMI_END_BUF |
- ANCHOR_PREC_READ_NOT);
+ ANCHOR_PREC_READ_NOT);
if (reg->anchor & (ANCHOR_END_BUF | ANCHOR_SEMI_END_BUF)) {
reg->anchor_dmin = opt.len.min;
@@ -5461,7 +5372,7 @@ set_optimize_info_from_tree(Node* node, regex_t* reg, ScanEnv* scan_env)
if (opt.exb.len > 0 || opt.exm.len > 0) {
select_opt_exact_info(reg->enc, &opt.exb, &opt.exm);
if (opt.map.value > 0 &&
- comp_opt_exact_or_map_info(&opt.exb, &opt.map) > 0) {
+ comp_opt_exact_or_map_info(&opt.exb, &opt.map) > 0) {
goto set_map;
}
else {
@@ -5503,7 +5414,7 @@ clear_optimize_info(regex_t* reg)
#ifdef ONIG_DEBUG
static void print_enc_string(FILE* fp, OnigEncoding enc,
- const UChar *s, const UChar *end)
+ const UChar *s, const UChar *end)
{
fprintf(fp, "\nPATTERN: /");
@@ -5515,10 +5426,10 @@ static void print_enc_string(FILE* fp, OnigEncoding enc,
while (p < end) {
code = ONIGENC_MBC_TO_CODE(enc, p, end);
if (code >= 0x80) {
- fprintf(fp, " 0x%04x ", (int )code);
+ fprintf(fp, " 0x%04x ", (int )code);
}
else {
- fputc((int )code, fp);
+ fputc((int )code, fp);
}
p += enclen(enc, p, end);
@@ -5639,15 +5550,15 @@ print_optimize_info(FILE* f, regex_t* reg)
c = 0;
fputc('[', f);
for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++) {
- if (reg->map[i] != 0) {
- if (c > 0) fputs(", ", f);
- c++;
- if (ONIGENC_MBC_MAXLEN(reg->enc) == 1 &&
- ONIGENC_IS_CODE_PRINT(reg->enc, (OnigCodePoint )i))
- fputc(i, f);
- else
- fprintf(f, "%d", i);
- }
+ if (reg->map[i] != 0) {
+ if (c > 0) fputs(", ", f);
+ c++;
+ if (ONIGENC_MBC_MAXLEN(reg->enc) == 1 &&
+ ONIGENC_IS_CODE_PRINT(reg->enc, (OnigCodePoint )i))
+ fputc(i, f);
+ else
+ fprintf(f, "%d", i);
+ }
}
fprintf(f, "]\n");
}
@@ -5662,8 +5573,6 @@ onig_free_body(regex_t* reg)
if (IS_NOT_NULL(reg)) {
xfree(reg->p);
xfree(reg->exact);
- xfree(reg->int_map);
- xfree(reg->int_map_backward);
xfree(reg->repeat_range);
onig_free(reg->chain);
@@ -5710,14 +5619,6 @@ onig_reg_copy(regex_t** nreg, regex_t* oreg)
(reg)->exact_end = (reg)->exact + exact_size;
}
- if (IS_NOT_NULL(reg->int_map)) {
- if (COPY_FAILED(int_map, sizeof(int) * ONIG_CHAR_TABLE_SIZE))
- goto err_int_map;
- }
- if (IS_NOT_NULL(reg->int_map_backward)) {
- if (COPY_FAILED(int_map_backward, sizeof(int) * ONIG_CHAR_TABLE_SIZE))
- goto err_int_map_backward;
- }
if (IS_NOT_NULL(reg->p)) {
if (COPY_FAILED(p, reg->alloc))
goto err_p;
@@ -5744,10 +5645,6 @@ onig_reg_copy(regex_t** nreg, regex_t* oreg)
err_repeat_range:
xfree(reg->p);
err_p:
- xfree(reg->int_map_backward);
- err_int_map_backward:
- xfree(reg->int_map);
- err_int_map:
xfree(reg->exact);
err:
xfree(reg);
@@ -5764,8 +5661,6 @@ onig_memsize(const regex_t *reg)
if (IS_NULL(reg)) return 0;
if (IS_NOT_NULL(reg->p)) size += reg->alloc;
if (IS_NOT_NULL(reg->exact)) size += reg->exact_end - reg->exact;
- if (IS_NOT_NULL(reg->int_map)) size += sizeof(int) * ONIG_CHAR_TABLE_SIZE;
- if (IS_NOT_NULL(reg->int_map_backward)) size += sizeof(int) * ONIG_CHAR_TABLE_SIZE;
if (IS_NOT_NULL(reg->repeat_range)) size += reg->repeat_range_alloc * sizeof(OnigRepeatRange);
if (IS_NOT_NULL(reg->chain)) size += onig_memsize(reg->chain);
@@ -5806,7 +5701,7 @@ static void print_tree(FILE* f, Node* node);
#ifdef RUBY
extern int
onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end,
- OnigErrorInfo* einfo)
+ OnigErrorInfo* einfo)
{
return onig_compile_ruby(reg, pattern, pattern_end, einfo, NULL, 0);
}
@@ -5815,11 +5710,11 @@ onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end,
#ifdef RUBY
extern int
onig_compile_ruby(regex_t* reg, const UChar* pattern, const UChar* pattern_end,
- OnigErrorInfo* einfo, const char *sourcefile, int sourceline)
+ OnigErrorInfo* einfo, const char *sourcefile, int sourceline)
#else
extern int
onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end,
- OnigErrorInfo* einfo)
+ OnigErrorInfo* einfo)
#endif
{
#define COMPILE_INIT_SIZE 20
@@ -5936,10 +5831,10 @@ onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end,
if (scan_env.comb_exp_max_regnum > 0) {
int i;
for (i = 1; i <= scan_env.comb_exp_max_regnum; i++) {
- if (BIT_STATUS_AT(scan_env.backrefed_mem, i) != 0) {
- scan_env.num_comb_exp_check = 0;
- break;
- }
+ if (BIT_STATUS_AT(scan_env.backrefed_mem, i) != 0) {
+ scan_env.num_comb_exp_check = 0;
+ break;
+ }
}
}
}
@@ -5973,9 +5868,9 @@ onig_compile(regex_t* reg, const UChar* pattern, const UChar* pattern_end,
reg->stack_pop_level = STACK_POP_LEVEL_ALL;
else {
if (reg->bt_mem_start != 0)
- reg->stack_pop_level = STACK_POP_LEVEL_MEM_START;
+ reg->stack_pop_level = STACK_POP_LEVEL_MEM_START;
else
- reg->stack_pop_level = STACK_POP_LEVEL_FREE;
+ reg->stack_pop_level = STACK_POP_LEVEL_FREE;
}
}
#ifdef USE_SUBEXP_CALL
@@ -6021,8 +5916,8 @@ static int onig_inited = 0;
extern int
onig_reg_init(regex_t* reg, OnigOptionType option,
- OnigCaseFoldType case_fold_flag,
- OnigEncoding enc, const OnigSyntaxType* syntax)
+ OnigCaseFoldType case_fold_flag,
+ OnigEncoding enc, const OnigSyntaxType* syntax)
{
if (! onig_inited)
onig_init();
@@ -6030,6 +5925,12 @@ onig_reg_init(regex_t* reg, OnigOptionType option,
if (IS_NULL(reg))
return ONIGERR_INVALID_ARGUMENT;
+ (reg)->exact = (UChar* )NULL;
+ (reg)->chain = (regex_t* )NULL;
+ (reg)->p = (UChar* )NULL;
+ (reg)->name_table = (void* )NULL;
+ (reg)->repeat_range = (OnigRepeatRange* )NULL;
+
if (ONIGENC_IS_UNDEF(enc))
return ONIGERR_DEFAULT_ENCODING_IS_NOT_SET;
@@ -6049,15 +5950,9 @@ onig_reg_init(regex_t* reg, OnigOptionType option,
(reg)->options = option;
(reg)->syntax = syntax;
(reg)->optimize = 0;
- (reg)->exact = (UChar* )NULL;
- (reg)->int_map = (int* )NULL;
- (reg)->int_map_backward = (int* )NULL;
- (reg)->chain = (regex_t* )NULL;
- (reg)->p = (UChar* )NULL;
(reg)->alloc = 0;
(reg)->used = 0;
- (reg)->name_table = (void* )NULL;
(reg)->case_fold_flag = case_fold_flag;
@@ -6082,8 +5977,8 @@ onig_new_without_alloc(regex_t* reg, const UChar* pattern,
extern int
onig_new(regex_t** reg, const UChar* pattern, const UChar* pattern_end,
- OnigOptionType option, OnigEncoding enc, const OnigSyntaxType* syntax,
- OnigErrorInfo* einfo)
+ OnigOptionType option, OnigEncoding enc, const OnigSyntaxType* syntax,
+ OnigErrorInfo* einfo)
{
*reg = (regex_t* )xmalloc(sizeof(regex_t));
if (IS_NULL(*reg)) return ONIGERR_MEMORY;
@@ -6436,9 +6331,9 @@ onig_print_compiled_byte_code(FILE* f, UChar* bp, UChar* bpend, UChar** nextp,
break;
case ARG_OPTION:
{
- OnigOptionType option = *((OnigOptionType* )bp);
- bp += SIZE_OPTION;
- fprintf(f, ":%d", option);
+ OnigOptionType option = *((OnigOptionType* )bp);
+ bp += SIZE_OPTION;
+ fprintf(f, ":%d", option);
}
break;
@@ -6487,13 +6382,13 @@ onig_print_compiled_byte_code(FILE* f, UChar* bp, UChar* bpend, UChar** nextp,
break;
case OP_EXACTMBN:
{
- int mb_len;
+ int mb_len;
- GET_LENGTH_INC(mb_len, bp);
- GET_LENGTH_INC(len, bp);
- fprintf(f, ":%d:%d:", mb_len, len);
- n = len * mb_len;
- while (n-- > 0) { fputc(*bp++, f); }
+ GET_LENGTH_INC(mb_len, bp);
+ GET_LENGTH_INC(len, bp);
+ fprintf(f, ":%d:%d:", mb_len, len);
+ n = len * mb_len;
+ while (n-- > 0) { fputc(*bp++, f); }
}
break;
@@ -6557,40 +6452,40 @@ onig_print_compiled_byte_code(FILE* f, UChar* bp, UChar* bpend, UChar** nextp,
fputs(" ", f);
GET_LENGTH_INC(len, bp);
for (i = 0; i < len; i++) {
- GET_MEMNUM_INC(mem, bp);
- if (i > 0) fputs(", ", f);
- fprintf(f, "%d", mem);
+ GET_MEMNUM_INC(mem, bp);
+ if (i > 0) fputs(", ", f);
+ fprintf(f, "%d", mem);
}
break;
case OP_BACKREF_WITH_LEVEL:
{
- OnigOptionType option;
- LengthType level;
-
- GET_OPTION_INC(option, bp);
- fprintf(f, ":%d", option);
- GET_LENGTH_INC(level, bp);
- fprintf(f, ":%d", level);
-
- fputs(" ", f);
- GET_LENGTH_INC(len, bp);
- for (i = 0; i < len; i++) {
- GET_MEMNUM_INC(mem, bp);
- if (i > 0) fputs(", ", f);
- fprintf(f, "%d", mem);
- }
+ OnigOptionType option;
+ LengthType level;
+
+ GET_OPTION_INC(option, bp);
+ fprintf(f, ":%d", option);
+ GET_LENGTH_INC(level, bp);
+ fprintf(f, ":%d", level);
+
+ fputs(" ", f);
+ GET_LENGTH_INC(len, bp);
+ for (i = 0; i < len; i++) {
+ GET_MEMNUM_INC(mem, bp);
+ if (i > 0) fputs(", ", f);
+ fprintf(f, "%d", mem);
+ }
}
break;
case OP_REPEAT:
case OP_REPEAT_NG:
{
- mem = *((MemNumType* )bp);
- bp += SIZE_MEMNUM;
- addr = *((RelAddrType* )bp);
- bp += SIZE_RELADDR;
- fprintf(f, ":%d:%d", mem, addr);
+ mem = *((MemNumType* )bp);
+ bp += SIZE_MEMNUM;
+ addr = *((RelAddrType* )bp);
+ bp += SIZE_RELADDR;
+ fprintf(f, ":%d:%d", mem, addr);
}
break;
@@ -6631,7 +6526,7 @@ onig_print_compiled_byte_code(FILE* f, UChar* bp, UChar* bpend, UChar** nextp,
default:
fprintf(stderr, "onig_print_compiled_byte_code: undefined code %d\n",
- bp[-1]);
+ bp[-1]);
}
}
fputs("]", f);
@@ -6688,8 +6583,8 @@ print_indent_tree(FILE* f, Node* node, int indent)
print_indent_tree(f, NCAR(node), indent + add);
while (IS_NOT_NULL(node = NCDR(node))) {
if (NTYPE(node) != type) {
- fprintf(f, "ERROR: list/alt right is not a cons. %d\n", NTYPE(node));
- exit(0);
+ fprintf(f, "ERROR: list/alt right is not a cons. %d\n", NTYPE(node));
+ exit(0);
}
print_indent_tree(f, NCAR(node), indent + add);
}
@@ -6697,12 +6592,12 @@ print_indent_tree(FILE* f, Node* node, int indent)
case NT_STR:
fprintf(f, "<string%s:%"PRIxPTR">",
- (NSTRING_IS_RAW(node) ? "-raw" : ""), (intptr_t )node);
+ (NSTRING_IS_RAW(node) ? "-raw" : ""), (intptr_t )node);
for (p = NSTR(node)->s; p < NSTR(node)->end; p++) {
if (*p >= 0x20 && *p < 0x7f)
- fputc(*p, f);
+ fputc(*p, f);
else {
- fprintf(f, " 0x%02x", *p);
+ fprintf(f, " 0x%02x", *p);
}
}
break;
@@ -6716,8 +6611,8 @@ print_indent_tree(FILE* f, Node* node, int indent)
OnigCodePoint* end = (OnigCodePoint* )(bbuf->p + bbuf->used);
fprintf(f, "%d", *data++);
for (; data < end; data+=2) {
- fprintf(f, ",");
- fprintf(f, "%04x-%04x", data[0], data[1]);
+ fprintf(f, ",");
+ fprintf(f, "%04x-%04x", data[0], data[1]);
}
}
break;
@@ -6727,9 +6622,9 @@ print_indent_tree(FILE* f, Node* node, int indent)
switch (NCTYPE(node)->ctype) {
case ONIGENC_CTYPE_WORD:
if (NCTYPE(node)->not != 0)
- fputs("not word", f);
+ fputs("not word", f);
else
- fputs("word", f);
+ fputs("word", f);
break;
default:
@@ -6777,8 +6672,8 @@ print_indent_tree(FILE* f, Node* node, int indent)
p = BACKREFS_P(br);
fprintf(f, "<backref:%"PRIxPTR">", (intptr_t )node);
for (i = 0; i < br->back_num; i++) {
- if (i > 0) fputs(", ", f);
- fprintf(f, "%d", p[i]);
+ if (i > 0) fputs(", ", f);
+ fprintf(f, "%d", p[i]);
}
}
break;
@@ -6795,8 +6690,8 @@ print_indent_tree(FILE* f, Node* node, int indent)
case NT_QTFR:
fprintf(f, "<quantifier:%"PRIxPTR">{%d,%d}%s\n", (intptr_t )node,
- NQTFR(node)->lower, NQTFR(node)->upper,
- (NQTFR(node)->greedy ? "" : "?"));
+ NQTFR(node)->lower, NQTFR(node)->upper,
+ (NQTFR(node)->greedy ? "" : "?"));
print_indent_tree(f, NQTFR(node)->target, indent + add);
break;
diff --git a/regenc.c b/regenc.c
index eb523e1ae5..c595f44b29 100644
--- a/regenc.c
+++ b/regenc.c
@@ -3,7 +3,7 @@
**********************************************************************/
/*-
* Copyright (c) 2002-2007 K.Kosako <sndgk393 AT ybb DOT ne DOT jp>
- * Copyright (c) 2011-2016 K.Takata <kentkt AT csc DOT jp>
+ * Copyright (c) 2011-2019 K.Takata <kentkt AT csc DOT jp>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -89,7 +89,7 @@ onigenc_get_right_adjust_char_head(OnigEncoding enc, const UChar* start, const U
extern UChar*
onigenc_get_right_adjust_char_head_with_prev(OnigEncoding enc,
- const UChar* start, const UChar* s, const UChar* end, const UChar** prev)
+ const UChar* start, const UChar* s, const UChar* end, const UChar** prev)
{
UChar* p = ONIGENC_LEFT_ADJUST_CHAR_HEAD(enc, start, s, end);
@@ -425,8 +425,8 @@ const OnigPairCaseFoldCodes OnigAsciiLowerMap[] = {
extern int
onigenc_ascii_apply_all_case_fold(OnigCaseFoldType flag ARG_UNUSED,
- OnigApplyAllCaseFoldFunc f, void* arg,
- OnigEncoding enc ARG_UNUSED)
+ OnigApplyAllCaseFoldFunc f, void* arg,
+ OnigEncoding enc ARG_UNUSED)
{
OnigCodePoint code;
int i, r;
@@ -446,8 +446,8 @@ onigenc_ascii_apply_all_case_fold(OnigCaseFoldType flag ARG_UNUSED,
extern int
onigenc_ascii_get_case_fold_codes_by_str(OnigCaseFoldType flag ARG_UNUSED,
- const OnigUChar* p, const OnigUChar* end ARG_UNUSED,
- OnigCaseFoldCodeItem items[], OnigEncoding enc ARG_UNUSED)
+ const OnigUChar* p, const OnigUChar* end ARG_UNUSED,
+ OnigCaseFoldCodeItem items[], OnigEncoding enc ARG_UNUSED)
{
if (0x41 <= *p && *p <= 0x5a) {
items[0].byte_len = 1;
@@ -467,7 +467,7 @@ onigenc_ascii_get_case_fold_codes_by_str(OnigCaseFoldType flag ARG_UNUSED,
static int
ss_apply_all_case_fold(OnigCaseFoldType flag ARG_UNUSED,
- OnigApplyAllCaseFoldFunc f, void* arg)
+ OnigApplyAllCaseFoldFunc f, void* arg)
{
OnigCodePoint ss[] = { 0x73, 0x73 };
@@ -513,7 +513,7 @@ onigenc_get_case_fold_codes_by_str_with_map(int map_size,
items[0].code_len = 1;
items[0].code[0] = (OnigCodePoint )(*p + 0x20);
if (*p == 0x53 && ess_tsett_flag != 0 && end > p + 1
- && (*(p+1) == 0x53 || *(p+1) == 0x73)) {
+ && (*(p+1) == 0x53 || *(p+1) == 0x73)) {
/* SS */
items[1].byte_len = 2;
items[1].code_len = 1;
@@ -528,7 +528,7 @@ onigenc_get_case_fold_codes_by_str_with_map(int map_size,
items[0].code_len = 1;
items[0].code[0] = (OnigCodePoint )(*p - 0x20);
if (*p == 0x73 && ess_tsett_flag != 0 && end > p + 1
- && (*(p+1) == 0x73 || *(p+1) == 0x53)) {
+ && (*(p+1) == 0x73 || *(p+1) == 0x53)) {
/* ss */
items[1].byte_len = 2;
items[1].code_len = 1;
@@ -566,16 +566,16 @@ onigenc_get_case_fold_codes_by_str_with_map(int map_size,
for (i = 0; i < map_size; i++) {
if (*p == map[i].from) {
- items[0].byte_len = 1;
- items[0].code_len = 1;
- items[0].code[0] = map[i].to;
- return 1;
+ items[0].byte_len = 1;
+ items[0].code_len = 1;
+ items[0].code[0] = map[i].to;
+ return 1;
}
else if (*p == map[i].to) {
- items[0].byte_len = 1;
- items[0].code_len = 1;
- items[0].code[0] = map[i].from;
- return 1;
+ items[0].byte_len = 1;
+ items[0].code_len = 1;
+ items[0].code[0] = map[i].from;
+ return 1;
}
}
}
@@ -586,9 +586,9 @@ onigenc_get_case_fold_codes_by_str_with_map(int map_size,
extern int
onigenc_not_support_get_ctype_code_range(OnigCtype ctype ARG_UNUSED,
- OnigCodePoint* sb_out ARG_UNUSED,
- const OnigCodePoint* ranges[] ARG_UNUSED,
- OnigEncoding enc)
+ OnigCodePoint* sb_out ARG_UNUSED,
+ const OnigCodePoint* ranges[] ARG_UNUSED,
+ OnigEncoding enc)
{
return ONIG_NO_SUPPORT_CONFIG;
}
@@ -605,7 +605,7 @@ onigenc_is_mbc_newline_0x0a(const UChar* p, const UChar* end, OnigEncoding enc A
/* for single byte encodings */
extern int
onigenc_ascii_mbc_case_fold(OnigCaseFoldType flag ARG_UNUSED, const UChar** p,
- const UChar* end, UChar* lower, OnigEncoding enc ARG_UNUSED)
+ const UChar* end, UChar* lower, OnigEncoding enc ARG_UNUSED)
{
*lower = ONIGENC_ASCII_CODE_TO_LOWER_CASE(**p);
@@ -616,7 +616,7 @@ onigenc_ascii_mbc_case_fold(OnigCaseFoldType flag ARG_UNUSED, const UChar** p,
#if 0
extern int
onigenc_ascii_is_mbc_ambiguous(OnigCaseFoldType flag ARG_UNUSED,
- const UChar** pp, const UChar* end ARG_UNUSED)
+ const UChar** pp, const UChar* end ARG_UNUSED)
{
const UChar* p = *pp;
@@ -627,56 +627,57 @@ onigenc_ascii_is_mbc_ambiguous(OnigCaseFoldType flag ARG_UNUSED,
extern int
onigenc_single_byte_mbc_enc_len(const UChar* p ARG_UNUSED, const UChar* e ARG_UNUSED,
- OnigEncoding enc ARG_UNUSED)
+ OnigEncoding enc ARG_UNUSED)
{
return 1;
}
extern OnigCodePoint
onigenc_single_byte_mbc_to_code(const UChar* p, const UChar* end ARG_UNUSED,
- OnigEncoding enc ARG_UNUSED)
+ OnigEncoding enc ARG_UNUSED)
{
return (OnigCodePoint )(*p);
}
extern int
-onigenc_single_byte_code_to_mbclen(OnigCodePoint code ARG_UNUSED, OnigEncoding enc ARG_UNUSED)
+onigenc_single_byte_code_to_mbclen(OnigCodePoint code, OnigEncoding enc ARG_UNUSED)
{
+ if (code > 0xff)
+ return ONIGERR_INVALID_CODE_POINT_VALUE;
return 1;
}
extern int
onigenc_single_byte_code_to_mbc(OnigCodePoint code, UChar *buf, OnigEncoding enc ARG_UNUSED)
{
-#ifdef RUBY
- if (code > 0xff)
- rb_raise(rb_eRangeError, "%u out of char range", code);
-#endif
+ if (code > 0xff) {
+ return ONIGERR_INVALID_CODE_POINT_VALUE;
+ }
*buf = (UChar )(code & 0xff);
return 1;
}
extern UChar*
onigenc_single_byte_left_adjust_char_head(const UChar* start ARG_UNUSED,
- const UChar* s,
- const UChar* end ARG_UNUSED,
- OnigEncoding enc ARG_UNUSED)
+ const UChar* s,
+ const UChar* end ARG_UNUSED,
+ OnigEncoding enc ARG_UNUSED)
{
return (UChar* )s;
}
extern int
onigenc_always_true_is_allowed_reverse_match(const UChar* s ARG_UNUSED,
- const UChar* end ARG_UNUSED,
- OnigEncoding enc ARG_UNUSED)
+ const UChar* end ARG_UNUSED,
+ OnigEncoding enc ARG_UNUSED)
{
return TRUE;
}
extern int
onigenc_always_false_is_allowed_reverse_match(const UChar* s ARG_UNUSED,
- const UChar* end ARG_UNUSED,
- OnigEncoding enc ARG_UNUSED)
+ const UChar* end ARG_UNUSED,
+ OnigEncoding enc ARG_UNUSED)
{
return FALSE;
}
@@ -712,7 +713,7 @@ onigenc_mbn_mbc_to_code(OnigEncoding enc, const UChar* p, const UChar* end)
extern int
onigenc_mbn_mbc_case_fold(OnigEncoding enc, OnigCaseFoldType flag ARG_UNUSED,
const UChar** pp, const UChar* end ARG_UNUSED,
- UChar* lower)
+ UChar* lower)
{
int len;
const UChar *p = *pp;
@@ -843,7 +844,7 @@ onigenc_minimum_property_name_to_ctype(OnigEncoding enc, const UChar* p, const U
extern int
onigenc_mb2_is_code_ctype(OnigEncoding enc, OnigCodePoint code,
- unsigned int ctype)
+ unsigned int ctype)
{
if (code < 128)
return ONIGENC_IS_ASCII_CODE_CTYPE(code, ctype);
@@ -858,7 +859,7 @@ onigenc_mb2_is_code_ctype(OnigEncoding enc, OnigCodePoint code,
extern int
onigenc_mb4_is_code_ctype(OnigEncoding enc, OnigCodePoint code,
- unsigned int ctype)
+ unsigned int ctype)
{
if (code < 128)
return ONIGENC_IS_ASCII_CODE_CTYPE(code, ctype);
@@ -961,14 +962,15 @@ onigenc_property_list_add_property(UChar* name, const OnigCodePoint* prop,
*pnum = *pnum + 1;
onig_st_insert_strend(*table, name, name + strlen((char* )name),
- (hash_data_type )(*pnum + ONIGENC_MAX_STD_CTYPE));
+ (hash_data_type )(*pnum + ONIGENC_MAX_STD_CTYPE));
return 0;
}
#endif
+#ifdef USE_CASE_MAP_API
extern int
onigenc_ascii_only_case_map(OnigCaseFoldType* flagP, const OnigUChar** pp, const OnigUChar* end,
- OnigUChar* to, OnigUChar* to_end, const struct OnigEncodingTypeST* enc)
+ OnigUChar* to, OnigUChar* to_end, const struct OnigEncodingTypeST* enc)
{
OnigCodePoint code;
OnigUChar *to_start = to;
@@ -984,9 +986,10 @@ onigenc_ascii_only_case_map(OnigCaseFoldType* flagP, const OnigUChar** pp, const
if (code >= 'a' && code <= 'z' && (flags & ONIGENC_CASE_UPCASE)) {
flags |= ONIGENC_CASE_MODIFIED;
- code += 'A' - 'a';
- } else if (code >= 'A' && code <= 'Z' &&
- (flags & (ONIGENC_CASE_DOWNCASE | ONIGENC_CASE_FOLD))) {
+ code -= 'a' - 'A';
+ }
+ else if (code >= 'A' && code <= 'Z' &&
+ (flags & (ONIGENC_CASE_DOWNCASE | ONIGENC_CASE_FOLD))) {
flags |= ONIGENC_CASE_MODIFIED;
code += 'a' - 'A';
}
@@ -1000,8 +1003,8 @@ onigenc_ascii_only_case_map(OnigCaseFoldType* flagP, const OnigUChar** pp, const
extern int
onigenc_single_byte_ascii_only_case_map(OnigCaseFoldType* flagP, const OnigUChar** pp,
- const OnigUChar* end, OnigUChar* to, OnigUChar* to_end,
- const struct OnigEncodingTypeST* enc)
+ const OnigUChar* end, OnigUChar* to, OnigUChar* to_end,
+ const struct OnigEncodingTypeST* enc)
{
OnigCodePoint code;
OnigUChar *to_start = to;
@@ -1012,9 +1015,10 @@ onigenc_single_byte_ascii_only_case_map(OnigCaseFoldType* flagP, const OnigUChar
if (code >= 'a' && code <= 'z' && (flags & ONIGENC_CASE_UPCASE)) {
flags |= ONIGENC_CASE_MODIFIED;
- code += 'A' - 'a';
- } else if (code >= 'A' && code <= 'Z' &&
- (flags & (ONIGENC_CASE_DOWNCASE | ONIGENC_CASE_FOLD))) {
+ code -= 'a' - 'A';
+ }
+ else if (code >= 'A' && code <= 'Z' &&
+ (flags & (ONIGENC_CASE_DOWNCASE | ONIGENC_CASE_FOLD))) {
flags |= ONIGENC_CASE_MODIFIED;
code += 'a' - 'A';
}
@@ -1025,3 +1029,4 @@ onigenc_single_byte_ascii_only_case_map(OnigCaseFoldType* flagP, const OnigUChar
*flagP = flags;
return (int )(to - to_start);
}
+#endif
diff --git a/regenc.h b/regenc.h
index 352a8d7980..fe0440dd74 100644
--- a/regenc.h
+++ b/regenc.h
@@ -5,7 +5,7 @@
**********************************************************************/
/*-
* Copyright (c) 2002-2008 K.Kosako <sndgk393 AT ybb DOT ne DOT jp>
- * Copyright (c) 2011-2016 K.Takata <kentkt AT csc DOT jp>
+ * Copyright (c) 2011-2019 K.Takata <kentkt AT csc DOT jp>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -118,6 +118,11 @@ typedef struct {
typedef struct {
short int len;
+#if defined(__has_attribute)
+# if __has_attribute(nonstring)
+ __attribute__((nonstring))
+# endif
+#endif
const UChar name[6];
int ctype;
} PosixBracketEntryType;
@@ -129,11 +134,13 @@ typedef struct {
#define roomof(x, y) (((x) + (y) - 1) / (y))
#define type_roomof(x, y) roomof(sizeof(x), sizeof(y))
+/* config */
#define USE_CRNL_AS_LINE_TERMINATOR
#define USE_UNICODE_PROPERTIES
#define USE_UNICODE_AGE_PROPERTIES
/* #define USE_UNICODE_CASE_FOLD_TURKISH_AZERI */
/* #define USE_UNICODE_ALL_LINE_TERMINATORS */ /* see Unicode.org UTS #18 */
+#define USE_CASE_MAP_API
#define ONIG_ENCODING_INIT_DEFAULT ONIG_ENCODING_ASCII
@@ -187,8 +194,8 @@ ONIG_EXTERN int onigenc_unicode_apply_all_case_fold(OnigCaseFoldType flag, OnigA
#define UTF16_IS_SURROGATE_SECOND(c) (((c) & 0xfc) == 0xdc)
#define UTF16_IS_SURROGATE(c) (((c) & 0xf8) == 0xd8)
#define UNICODE_VALID_CODEPOINT_P(c) ( \
- ((c) <= 0x10ffff) && \
- !((c) < 0x10000 && UTF16_IS_SURROGATE((c) >> 8)))
+ ((c) <= 0x10ffff) && \
+ !((c) < 0x10000 && UTF16_IS_SURROGATE((c) >> 8)))
#define ONIGENC_ISO_8859_1_TO_LOWER_CASE(c) \
OnigEncISO_8859_1_ToLowerCaseTable[c]
@@ -234,8 +241,8 @@ extern int ONIG_ENC_REGISTER(const char *, OnigEncoding);
# define OnigEncodingDefine(f,n) \
OnigEncodingDeclare(n); \
void Init_##f(void) { \
- ONIG_ENC_REGISTER(OnigEncodingName(n).name, \
- &OnigEncodingName(n)); \
+ ONIG_ENC_REGISTER(OnigEncodingName(n).name, \
+ &OnigEncodingName(n)); \
} \
OnigEncodingDeclare(n)
#else
diff --git a/regerror.c b/regerror.c
index b18fc2e88b..e772feee81 100644
--- a/regerror.c
+++ b/regerror.c
@@ -3,7 +3,7 @@
**********************************************************************/
/*-
* Copyright (c) 2002-2007 K.Kosako <sndgk393 AT ybb DOT ne DOT jp>
- * Copyright (c) 2011-2016 K.Takata <kentkt AT csc DOT jp>
+ * Copyright (c) 2011-2019 K.Takata <kentkt AT csc DOT jp>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -63,14 +63,18 @@ onig_error_code_to_format(OnigPosition code)
p = "parse depth limit over"; break;
case ONIGERR_DEFAULT_ENCODING_IS_NOT_SET:
p = "default multibyte-encoding is not set"; break;
+#if 0
case ONIGERR_SPECIFIED_ENCODING_CANT_CONVERT_TO_WIDE_CHAR:
p = "can't convert to wide-char on specified multibyte-encoding"; break;
+#endif
case ONIGERR_INVALID_ARGUMENT:
p = "invalid argument"; break;
case ONIGERR_END_PATTERN_AT_LEFT_BRACE:
p = "end pattern at left brace"; break;
+#if 0
case ONIGERR_END_PATTERN_AT_LEFT_BRACKET:
p = "end pattern at left bracket"; break;
+#endif
case ONIGERR_EMPTY_CHAR_CLASS:
p = "empty char-class"; break;
case ONIGERR_PREMATURE_END_OF_CHAR_CLASS:
@@ -87,16 +91,20 @@ onig_error_code_to_format(OnigPosition code)
p = "invalid control-code syntax"; break;
case ONIGERR_CHAR_CLASS_VALUE_AT_END_OF_RANGE:
p = "char-class value at end of range"; break;
+#if 0
case ONIGERR_CHAR_CLASS_VALUE_AT_START_OF_RANGE:
p = "char-class value at start of range"; break;
+#endif
case ONIGERR_UNMATCHED_RANGE_SPECIFIER_IN_CHAR_CLASS:
p = "unmatched range specifier in char-class"; break;
case ONIGERR_TARGET_OF_REPEAT_OPERATOR_NOT_SPECIFIED:
p = "target of repeat operator is not specified"; break;
case ONIGERR_TARGET_OF_REPEAT_OPERATOR_INVALID:
p = "target of repeat operator is invalid"; break;
+#if 0
case ONIGERR_NESTED_REPEAT_OPERATOR:
p = "nested repeat operator"; break;
+#endif
case ONIGERR_UNMATCHED_CLOSE_PARENTHESIS:
p = "unmatched close parenthesis"; break;
case ONIGERR_END_PATTERN_WITH_UNMATCHED_PARENTHESIS:
@@ -121,14 +129,18 @@ onig_error_code_to_format(OnigPosition code)
p = "upper is smaller than lower in repeat range"; break;
case ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS:
p = "empty range in char class"; break;
+#if 0
case ONIGERR_MISMATCH_CODE_LENGTH_IN_CLASS_RANGE:
p = "mismatch multibyte code length in char-class range"; break;
+#endif
case ONIGERR_TOO_MANY_MULTI_BYTE_RANGES:
p = "too many multibyte code ranges are specified"; break;
case ONIGERR_TOO_SHORT_MULTI_BYTE_STRING:
p = "too short multibyte code string"; break;
+#if 0
case ONIGERR_TOO_BIG_BACKREF_NUMBER:
p = "too big backref number"; break;
+#endif
case ONIGERR_INVALID_BACKREF:
#ifdef USE_NAMED_GROUP
p = "invalid backref number/name"; break;
@@ -161,8 +173,10 @@ onig_error_code_to_format(OnigPosition code)
p = "multiplex definition name <%n> call"; break;
case ONIGERR_NEVER_ENDING_RECURSION:
p = "never ending recursion"; break;
+#ifdef USE_CAPTURE_HISTORY
case ONIGERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY:
p = "group number is too big for capture history"; break;
+#endif
case ONIGERR_INVALID_CHAR_PROPERTY_NAME:
p = "invalid character property name {%n}"; break;
case ONIGERR_TOO_MANY_CAPTURE_GROUPS:
@@ -194,7 +208,7 @@ static void sprint_byte_with_x(char* s, unsigned int v)
}
static int to_ascii(OnigEncoding enc, UChar *s, UChar *end,
- UChar buf[], int buf_size, int *is_over)
+ UChar buf[], int buf_size, int *is_over)
{
int len;
UChar *p;
@@ -206,24 +220,24 @@ static int to_ascii(OnigEncoding enc, UChar *s, UChar *end,
while (p < end) {
code = ONIGENC_MBC_TO_CODE(enc, p, end);
if (code >= 0x80) {
- if (code > 0xffff && len + 10 <= buf_size) {
- sprint_byte_with_x((char*)(&(buf[len])), (unsigned int)(code >> 24));
- sprint_byte((char*)(&(buf[len+4])), (unsigned int)(code >> 16));
- sprint_byte((char*)(&(buf[len+6])), (unsigned int)(code >> 8));
- sprint_byte((char*)(&(buf[len+8])), (unsigned int)code);
- len += 10;
- }
- else if (len + 6 <= buf_size) {
- sprint_byte_with_x((char*)(&(buf[len])), (unsigned int)(code >> 8));
- sprint_byte((char*)(&(buf[len+4])), (unsigned int)code);
- len += 6;
- }
- else {
- break;
- }
+ if (code > 0xffff && len + 10 <= buf_size) {
+ sprint_byte_with_x((char*)(&(buf[len])), (unsigned int)(code >> 24));
+ sprint_byte((char*)(&(buf[len+4])), (unsigned int)(code >> 16));
+ sprint_byte((char*)(&(buf[len+6])), (unsigned int)(code >> 8));
+ sprint_byte((char*)(&(buf[len+8])), (unsigned int)code);
+ len += 10;
+ }
+ else if (len + 6 <= buf_size) {
+ sprint_byte_with_x((char*)(&(buf[len])), (unsigned int)(code >> 8));
+ sprint_byte((char*)(&(buf[len+4])), (unsigned int)code);
+ len += 6;
+ }
+ else {
+ break;
+ }
}
else {
- buf[len++] = (UChar )code;
+ buf[len++] = (UChar )code;
}
p += enclen(enc, p, end);
@@ -267,27 +281,27 @@ onig_error_code_to_str(UChar* s, OnigPosition code, ...)
case ONIGERR_INVALID_CHAR_PROPERTY_NAME:
einfo = va_arg(vargs, OnigErrorInfo*);
len = to_ascii(einfo->enc, einfo->par, einfo->par_end,
- parbuf, MAX_ERROR_PAR_LEN - 3, &is_over);
+ parbuf, MAX_ERROR_PAR_LEN - 3, &is_over);
q = onig_error_code_to_format(code);
p = s;
while (*q != '\0') {
if (*q == '%') {
- q++;
- if (*q == 'n') { /* '%n': name */
- xmemcpy(p, parbuf, len);
- p += len;
- if (is_over != 0) {
- xmemcpy(p, "...", 3);
- p += 3;
- }
- q++;
- }
- else
- goto normal_char;
+ q++;
+ if (*q == 'n') { /* '%n': name */
+ xmemcpy(p, parbuf, len);
+ p += len;
+ if (is_over != 0) {
+ xmemcpy(p, "...", 3);
+ p += 3;
+ }
+ q++;
+ }
+ else
+ goto normal_char;
}
else {
normal_char:
- *p++ = *q++;
+ *p++ = *q++;
}
}
*p = '\0';
@@ -299,7 +313,8 @@ onig_error_code_to_str(UChar* s, OnigPosition code, ...)
if (q) {
len = onigenc_str_bytelen_null(ONIG_ENCODING_ASCII, q);
xmemcpy(s, q, len);
- } else {
+ }
+ else {
len = 0;
}
s[len] = '\0';
@@ -347,24 +362,24 @@ onig_vsnprintf_with_pattern(UChar buf[], int bufsize, OnigEncoding enc,
}
}
else if (*p == '\\') {
- *s++ = *p++;
- len = enclen(enc, p, pat_end);
- while (len-- > 0) *s++ = *p++;
+ *s++ = *p++;
+ len = enclen(enc, p, pat_end);
+ while (len-- > 0) *s++ = *p++;
}
else if (*p == '/') {
- *s++ = (unsigned char )'\\';
- *s++ = *p++;
+ *s++ = (unsigned char )'\\';
+ *s++ = *p++;
}
else if (!ONIGENC_IS_CODE_PRINT(enc, *p) &&
- (!ONIGENC_IS_CODE_SPACE(enc, *p) ||
+ (!ONIGENC_IS_CODE_SPACE(enc, *p) ||
ONIGENC_IS_CODE_CNTRL(enc, *p))) {
- sprint_byte_with_x((char* )bs, (unsigned int )(*p++));
- len = onigenc_str_bytelen_null(ONIG_ENCODING_ASCII, bs);
+ sprint_byte_with_x((char* )bs, (unsigned int )(*p++));
+ len = onigenc_str_bytelen_null(ONIG_ENCODING_ASCII, bs);
bp = bs;
- while (len-- > 0) *s++ = *bp++;
+ while (len-- > 0) *s++ = *bp++;
}
else {
- *s++ = *p++;
+ *s++ = *p++;
}
}
@@ -381,7 +396,7 @@ onig_snprintf_with_pattern(UChar buf[], int bufsize, OnigEncoding enc,
va_list args;
va_start(args, fmt);
onig_vsnprintf_with_pattern(buf, bufsize, enc,
- pat, pat_end, fmt, args);
+ pat, pat_end, fmt, args);
va_end(args);
}
#endif
diff --git a/regexec.c b/regexec.c
index 6d82429e03..3210c7cc1b 100644
--- a/regexec.c
+++ b/regexec.c
@@ -2,8 +2,8 @@
regexec.c - Onigmo (Oniguruma-mod) (regular expression library)
**********************************************************************/
/*-
- * Copyright (c) 2002-2008 K.Kosako <sndgk393 AT ybb DOT ne DOT jp>
- * Copyright (c) 2011-2016 K.Takata <kentkt AT csc DOT jp>
+ * Copyright (c) 2002-2018 K.Kosako <sndgk393 AT ybb DOT ne DOT jp>
+ * Copyright (c) 2011-2019 K.Takata <kentkt AT csc DOT jp>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -55,7 +55,7 @@ rb_enc_asciicompat(OnigEncoding enc)
# define ONIGENC_IS_MBC_ASCII_WORD(enc,s,end) \
(rb_enc_asciicompat(enc) ? (ISALNUM(*s) || *s=='_') : \
onigenc_ascii_is_code_ctype( \
- ONIGENC_MBC_TO_CODE(enc,s,end),ONIGENC_CTYPE_WORD,enc))
+ ONIGENC_MBC_TO_CODE(enc,s,end),ONIGENC_CTYPE_WORD,enc))
#endif /* RUBY */
#ifdef USE_CRNL_AS_LINE_TERMINATOR
@@ -66,28 +66,28 @@ rb_enc_asciicompat(OnigEncoding enc)
is_mbc_newline_ex((enc),(p),(start),(end),(option),(check_prev))
static int
is_mbc_newline_ex(OnigEncoding enc, const UChar *p, const UChar *start,
- const UChar *end, OnigOptionType option, int check_prev)
+ const UChar *end, OnigOptionType option, int check_prev)
{
if (IS_NEWLINE_CRLF(option)) {
if (ONIGENC_MBC_TO_CODE(enc, p, end) == 0x0a) {
if (check_prev) {
- const UChar *prev = onigenc_get_prev_char_head(enc, start, p, end);
- if ((prev != NULL) && ONIGENC_MBC_TO_CODE(enc, prev, end) == 0x0d)
- return 0;
- else
- return 1;
+ const UChar *prev = onigenc_get_prev_char_head(enc, start, p, end);
+ if ((prev != NULL) && ONIGENC_MBC_TO_CODE(enc, prev, end) == 0x0d)
+ return 0;
+ else
+ return 1;
}
else
- return 1;
+ return 1;
}
else {
const UChar *pnext = p + enclen(enc, p, end);
if (pnext < end &&
- ONIGENC_MBC_TO_CODE(enc, p, end) == 0x0d &&
- ONIGENC_MBC_TO_CODE(enc, pnext, end) == 0x0a)
- return 1;
+ ONIGENC_MBC_TO_CODE(enc, p, end) == 0x0d &&
+ ONIGENC_MBC_TO_CODE(enc, pnext, end) == 0x0a)
+ return 1;
if (ONIGENC_IS_MBC_NEWLINE(enc, p, end))
- return 1;
+ return 1;
return 0;
}
}
@@ -111,7 +111,7 @@ history_tree_clear(OnigCaptureTreeNode* node)
if (IS_NOT_NULL(node)) {
for (i = 0; i < node->num_childs; i++) {
if (IS_NOT_NULL(node->childs[i])) {
- history_tree_free(node->childs[i]);
+ history_tree_free(node->childs[i]);
}
}
for (i = 0; i < node->allocated; i++) {
@@ -170,18 +170,18 @@ history_tree_add_child(OnigCaptureTreeNode* parent, OnigCaptureTreeNode* child)
if (IS_NULL(parent->childs)) {
n = HISTORY_TREE_INIT_ALLOC_SIZE;
parent->childs =
- (OnigCaptureTreeNode** )xmalloc(sizeof(OnigCaptureTreeNode*) * n);
+ (OnigCaptureTreeNode** )xmalloc(sizeof(OnigCaptureTreeNode*) * n);
CHECK_NULL_RETURN_MEMERR(parent->childs);
}
else {
OnigCaptureTreeNode** tmp;
n = parent->allocated * 2;
tmp =
- (OnigCaptureTreeNode** )xrealloc(parent->childs,
- sizeof(OnigCaptureTreeNode*) * n);
+ (OnigCaptureTreeNode** )xrealloc(parent->childs,
+ sizeof(OnigCaptureTreeNode*) * n);
if (tmp == 0) {
- history_tree_clear(parent);
- return ONIGERR_MEMORY;
+ history_tree_clear(parent);
+ return ONIGERR_MEMORY;
}
parent->childs = tmp;
}
@@ -240,11 +240,11 @@ Glossary for "match cache"
The `Regexp#match` optimization by using a cache.
"cache opcode"
-A cachable opcode (e.g. `OP_PUSH`, `OP_REPEAT`, etc).
+A cacheable opcode (e.g. `OP_PUSH`, `OP_REPEAT`, etc).
It is corresponding to some cache points.
"cache point"
-A cachable point on matching.
+A cacheable point on matching.
Usually, one-to-one corresponding between a cache opcode and a cache point exists,
but cache opcodes between `OP_REPEAT` and `OP_REPEAT_INC` have some corresponding
cache points depending on repetition counts.
@@ -276,7 +276,7 @@ static OnigPosition count_num_cache_opcodes_inner(
switch (*p++) {
case OP_FINISH:
case OP_END:
- break;
+ break;
case OP_EXACT1: p++; break;
case OP_EXACT2: p += 2; break;
@@ -284,50 +284,50 @@ static OnigPosition count_num_cache_opcodes_inner(
case OP_EXACT4: p += 4; break;
case OP_EXACT5: p += 5; break;
case OP_EXACTN:
- GET_LENGTH_INC(len, p); p += len; break;
+ GET_LENGTH_INC(len, p); p += len; break;
case OP_EXACTMB2N1: p += 2; break;
case OP_EXACTMB2N2: p += 4; break;
case OP_EXACTMB2N3: p += 6; break;
case OP_EXACTMB2N:
- GET_LENGTH_INC(len, p); p += len * 2; break;
+ GET_LENGTH_INC(len, p); p += len * 2; break;
case OP_EXACTMB3N:
- GET_LENGTH_INC(len, p); p += len * 3; break;
+ GET_LENGTH_INC(len, p); p += len * 3; break;
case OP_EXACTMBN:
- {
- int mb_len;
- GET_LENGTH_INC(mb_len, p);
- GET_LENGTH_INC(len, p);
- p += mb_len * len;
- }
- break;
+ {
+ int mb_len;
+ GET_LENGTH_INC(mb_len, p);
+ GET_LENGTH_INC(len, p);
+ p += mb_len * len;
+ }
+ break;
case OP_EXACT1_IC:
- len = enclen(enc, p, pend); p += len; break;
+ len = enclen(enc, p, pend); p += len; break;
case OP_EXACTN_IC:
- GET_LENGTH_INC(len, p); p += len; break;
+ GET_LENGTH_INC(len, p); p += len; break;
case OP_CCLASS:
case OP_CCLASS_NOT:
- p += SIZE_BITSET; break;
+ p += SIZE_BITSET; break;
case OP_CCLASS_MB:
case OP_CCLASS_MB_NOT:
- GET_LENGTH_INC(len, p); p += len; break;
+ GET_LENGTH_INC(len, p); p += len; break;
case OP_CCLASS_MIX:
case OP_CCLASS_MIX_NOT:
- p += SIZE_BITSET;
- GET_LENGTH_INC(len, p);
- p += len;
- break;
+ p += SIZE_BITSET;
+ GET_LENGTH_INC(len, p);
+ p += len;
+ break;
case OP_ANYCHAR:
case OP_ANYCHAR_ML:
- break;
+ break;
case OP_ANYCHAR_STAR:
case OP_ANYCHAR_ML_STAR:
- num_cache_opcodes++; break;
+ num_cache_opcodes++; break;
case OP_ANYCHAR_STAR_PEEK_NEXT:
case OP_ANYCHAR_ML_STAR_PEEK_NEXT:
- p++; num_cache_opcodes++; break;
+ p++; num_cache_opcodes++; break;
case OP_WORD:
case OP_NOT_WORD:
@@ -335,7 +335,7 @@ static OnigPosition count_num_cache_opcodes_inner(
case OP_NOT_WORD_BOUND:
case OP_WORD_BEGIN:
case OP_WORD_END:
- break;
+ break;
case OP_ASCII_WORD:
case OP_NOT_ASCII_WORD:
@@ -343,7 +343,7 @@ static OnigPosition count_num_cache_opcodes_inner(
case OP_NOT_ASCII_WORD_BOUND:
case OP_ASCII_WORD_BEGIN:
case OP_ASCII_WORD_END:
- break;
+ break;
case OP_BEGIN_BUF:
case OP_END_BUF:
@@ -351,7 +351,7 @@ static OnigPosition count_num_cache_opcodes_inner(
case OP_END_LINE:
case OP_SEMI_END_BUF:
case OP_BEGIN_POSITION:
- break;
+ break;
case OP_BACKREF1:
case OP_BACKREF2:
@@ -360,7 +360,7 @@ static OnigPosition count_num_cache_opcodes_inner(
case OP_BACKREF_MULTI:
case OP_BACKREF_MULTI_IC:
case OP_BACKREF_WITH_LEVEL:
- goto impossible;
+ goto impossible;
case OP_MEMORY_START:
case OP_MEMORY_START_PUSH:
@@ -368,152 +368,158 @@ static OnigPosition count_num_cache_opcodes_inner(
case OP_MEMORY_END_PUSH_REC:
case OP_MEMORY_END:
case OP_MEMORY_END_REC:
- p += SIZE_MEMNUM;
- // A memory (capture) in look-around is found.
- if (lookaround_nesting != 0) {
- goto impossible;
+ p += SIZE_MEMNUM;
+ // A memory (capture) in look-around is found.
+ if (lookaround_nesting != 0) {
+ goto impossible;
}
- break;
+ break;
case OP_KEEP:
- break;
+ break;
case OP_FAIL:
- break;
+ break;
case OP_JUMP:
- p += SIZE_RELADDR;
- break;
+ p += SIZE_RELADDR;
+ break;
case OP_PUSH:
- p += SIZE_RELADDR;
- num_cache_opcodes++;
- break;
+ p += SIZE_RELADDR;
+ num_cache_opcodes++;
+ break;
case OP_POP:
- break;
+ break;
case OP_PUSH_OR_JUMP_EXACT1:
case OP_PUSH_IF_PEEK_NEXT:
- p += SIZE_RELADDR + 1; num_cache_opcodes++; break;
+ p += SIZE_RELADDR + 1; num_cache_opcodes++; break;
case OP_REPEAT:
case OP_REPEAT_NG:
- if (current_repeat_mem != -1) {
- // A nested OP_REPEAT is not yet supported.
- goto impossible;
- }
- GET_MEMNUM_INC(repeat_mem, p);
- p += SIZE_RELADDR;
- if (reg->repeat_range[repeat_mem].lower == 0) {
- num_cache_opcodes++;
- }
- result = count_num_cache_opcodes_inner(reg, repeat_mem, lookaround_nesting, &p, &num_cache_opcodes);
- if (result < 0 || num_cache_opcodes < 0) {
- goto fail;
- }
- {
- OnigRepeatRange *repeat_range = &reg->repeat_range[repeat_mem];
- if (repeat_range->lower < repeat_range->upper) {
- num_cache_opcodes++;
- }
+ if (current_repeat_mem != -1) {
+ // A nested OP_REPEAT is not yet supported.
+ goto impossible;
}
- break;
+ GET_MEMNUM_INC(repeat_mem, p);
+ p += SIZE_RELADDR;
+ if (reg->repeat_range[repeat_mem].lower == 0 && reg->repeat_range[repeat_mem].upper == 0) {
+ long dummy_num_cache_opcodes = 0;
+ result = count_num_cache_opcodes_inner(reg, repeat_mem, lookaround_nesting, &p, &dummy_num_cache_opcodes);
+ if (result < 0 || dummy_num_cache_opcodes < 0) {
+ goto fail;
+ }
+ } else {
+ if (reg->repeat_range[repeat_mem].lower == 0) {
+ num_cache_opcodes++;
+ }
+ result = count_num_cache_opcodes_inner(reg, repeat_mem, lookaround_nesting, &p, &num_cache_opcodes);
+ if (result < 0 || num_cache_opcodes < 0) {
+ goto fail;
+ }
+ OnigRepeatRange *repeat_range = &reg->repeat_range[repeat_mem];
+ if (repeat_range->lower < repeat_range->upper) {
+ num_cache_opcodes++;
+ }
+ }
+ break;
case OP_REPEAT_INC:
case OP_REPEAT_INC_NG:
- GET_MEMNUM_INC(repeat_mem, p);
- if (repeat_mem != current_repeat_mem) {
- // A lone or invalid OP_REPEAT_INC is found.
- goto impossible;
- }
- goto exit;
+ GET_MEMNUM_INC(repeat_mem, p);
+ if (repeat_mem != current_repeat_mem) {
+ // A lone or invalid OP_REPEAT_INC is found.
+ goto impossible;
+ }
+ goto exit;
case OP_REPEAT_INC_SG:
case OP_REPEAT_INC_NG_SG:
- goto impossible;
+ goto impossible;
case OP_NULL_CHECK_START:
- p += SIZE_MEMNUM;
- break;
+ p += SIZE_MEMNUM;
+ break;
case OP_NULL_CHECK_END:
case OP_NULL_CHECK_END_MEMST_PUSH:
- p += SIZE_MEMNUM;
- break;
+ p += SIZE_MEMNUM;
+ break;
case OP_NULL_CHECK_END_MEMST:
- p += SIZE_MEMNUM;
- break;
+ p += SIZE_MEMNUM;
+ break;
case OP_PUSH_POS:
- if (lookaround_nesting < 0) {
- // A look-around nested in a atomic grouping is found.
- goto impossible;
- }
- result = count_num_cache_opcodes_inner(reg, current_repeat_mem, lookaround_nesting + 1, &p, &num_cache_opcodes);
- if (result < 0 || num_cache_opcodes < 0) {
- goto fail;
- }
- break;
+ if (lookaround_nesting < 0) {
+ // A look-around nested in a atomic grouping is found.
+ goto impossible;
+ }
+ result = count_num_cache_opcodes_inner(reg, current_repeat_mem, lookaround_nesting + 1, &p, &num_cache_opcodes);
+ if (result < 0 || num_cache_opcodes < 0) {
+ goto fail;
+ }
+ break;
case OP_PUSH_POS_NOT:
- if (lookaround_nesting < 0) {
- // A look-around nested in a atomic grouping is found.
- goto impossible;
- }
- p += SIZE_RELADDR;
- result = count_num_cache_opcodes_inner(reg, current_repeat_mem, lookaround_nesting + 1, &p, &num_cache_opcodes);
- if (result < 0 || num_cache_opcodes < 0) {
- goto fail;
- }
- break;
+ if (lookaround_nesting < 0) {
+ // A look-around nested in a atomic grouping is found.
+ goto impossible;
+ }
+ p += SIZE_RELADDR;
+ result = count_num_cache_opcodes_inner(reg, current_repeat_mem, lookaround_nesting + 1, &p, &num_cache_opcodes);
+ if (result < 0 || num_cache_opcodes < 0) {
+ goto fail;
+ }
+ break;
case OP_PUSH_LOOK_BEHIND_NOT:
- if (lookaround_nesting < 0) {
- // A look-around nested in a atomic grouping is found.
- goto impossible;
- }
- p += SIZE_RELADDR;
- p += SIZE_LENGTH;
- result = count_num_cache_opcodes_inner(reg, current_repeat_mem, lookaround_nesting + 1, &p, &num_cache_opcodes);
- if (result < 0 || num_cache_opcodes < 0) {
- goto fail;
- }
- break;
+ if (lookaround_nesting < 0) {
+ // A look-around nested in a atomic grouping is found.
+ goto impossible;
+ }
+ p += SIZE_RELADDR;
+ p += SIZE_LENGTH;
+ result = count_num_cache_opcodes_inner(reg, current_repeat_mem, lookaround_nesting + 1, &p, &num_cache_opcodes);
+ if (result < 0 || num_cache_opcodes < 0) {
+ goto fail;
+ }
+ break;
case OP_PUSH_STOP_BT:
- if (lookaround_nesting != 0) {
- // A nested atomic grouping is found.
- goto impossible;
- }
- result = count_num_cache_opcodes_inner(reg, current_repeat_mem, -1, &p, &num_cache_opcodes);
- if (result < 0 || num_cache_opcodes < 0) {
- goto fail;
- }
- break;
+ if (lookaround_nesting != 0) {
+ // A nested atomic grouping is found.
+ goto impossible;
+ }
+ result = count_num_cache_opcodes_inner(reg, current_repeat_mem, -1, &p, &num_cache_opcodes);
+ if (result < 0 || num_cache_opcodes < 0) {
+ goto fail;
+ }
+ break;
case OP_POP_POS:
case OP_FAIL_POS:
case OP_FAIL_LOOK_BEHIND_NOT:
case OP_POP_STOP_BT:
- goto exit;
+ goto exit;
case OP_LOOK_BEHIND:
- p += SIZE_LENGTH;
- break;
+ p += SIZE_LENGTH;
+ break;
case OP_PUSH_ABSENT_POS:
case OP_ABSENT_END:
case OP_ABSENT:
- goto impossible;
+ goto impossible;
case OP_CALL:
case OP_RETURN:
- goto impossible;
+ goto impossible;
case OP_CONDITION:
- goto impossible;
+ goto impossible;
case OP_STATE_CHECK_PUSH:
case OP_STATE_CHECK_PUSH_OR_JUMP:
case OP_STATE_CHECK:
case OP_STATE_CHECK_ANYCHAR_STAR:
case OP_STATE_CHECK_ANYCHAR_ML_STAR:
- goto impossible;
+ goto impossible;
case OP_SET_OPTION_PUSH:
case OP_SET_OPTION:
- p += SIZE_OPTION;
- break;
+ p += SIZE_OPTION;
+ break;
default:
- goto bytecode_error;
+ goto bytecode_error;
}
}
@@ -565,7 +571,7 @@ init_cache_opcodes_inner(
OnigCacheOpcode *cache_opcodes = *cache_opcodes_ptr;
OnigPosition result;
-# define INC_CACHE_OPCODES do {\
+# define INC_CACHE_OPCODES if (cache_opcodes != NULL) {\
cache_opcodes->addr = pbegin;\
cache_opcodes->cache_point = cache_point;\
cache_opcodes->outer_repeat_mem = current_repeat_mem;\
@@ -575,14 +581,14 @@ init_cache_opcodes_inner(
cache_opcodes->match_addr = NULL;\
cache_point += lookaround_nesting != 0 ? 2 : 1;\
cache_opcodes++;\
- } while (0)
+ }
while (p < pend) {
pbegin = p;
switch (*p++) {
case OP_FINISH:
case OP_END:
- break;
+ break;
case OP_EXACT1: p++; break;
case OP_EXACT2: p += 2; break;
@@ -590,53 +596,53 @@ init_cache_opcodes_inner(
case OP_EXACT4: p += 4; break;
case OP_EXACT5: p += 5; break;
case OP_EXACTN:
- GET_LENGTH_INC(len, p); p += len; break;
+ GET_LENGTH_INC(len, p); p += len; break;
case OP_EXACTMB2N1: p += 2; break;
case OP_EXACTMB2N2: p += 4; break;
case OP_EXACTMB2N3: p += 6; break;
case OP_EXACTMB2N:
- GET_LENGTH_INC(len, p); p += len * 2; break;
+ GET_LENGTH_INC(len, p); p += len * 2; break;
case OP_EXACTMB3N:
- GET_LENGTH_INC(len, p); p += len * 3; break;
+ GET_LENGTH_INC(len, p); p += len * 3; break;
case OP_EXACTMBN:
- {
- int mb_len;
- GET_LENGTH_INC(mb_len, p);
- GET_LENGTH_INC(len, p);
- p += mb_len * len;
- }
- break;
+ {
+ int mb_len;
+ GET_LENGTH_INC(mb_len, p);
+ GET_LENGTH_INC(len, p);
+ p += mb_len * len;
+ }
+ break;
case OP_EXACT1_IC:
- len = enclen(enc, p, pend); p += len; break;
+ len = enclen(enc, p, pend); p += len; break;
case OP_EXACTN_IC:
- GET_LENGTH_INC(len, p); p += len; break;
+ GET_LENGTH_INC(len, p); p += len; break;
case OP_CCLASS:
case OP_CCLASS_NOT:
- p += SIZE_BITSET; break;
+ p += SIZE_BITSET; break;
case OP_CCLASS_MB:
case OP_CCLASS_MB_NOT:
- GET_LENGTH_INC(len, p); p += len; break;
+ GET_LENGTH_INC(len, p); p += len; break;
case OP_CCLASS_MIX:
case OP_CCLASS_MIX_NOT:
- p += SIZE_BITSET;
- GET_LENGTH_INC(len, p);
- p += len;
- break;
+ p += SIZE_BITSET;
+ GET_LENGTH_INC(len, p);
+ p += len;
+ break;
case OP_ANYCHAR:
case OP_ANYCHAR_ML:
- break;
+ break;
case OP_ANYCHAR_STAR:
case OP_ANYCHAR_ML_STAR:
- INC_CACHE_OPCODES;
- break;
+ INC_CACHE_OPCODES;
+ break;
case OP_ANYCHAR_STAR_PEEK_NEXT:
case OP_ANYCHAR_ML_STAR_PEEK_NEXT:
- p++;
- INC_CACHE_OPCODES;
- break;
+ p++;
+ INC_CACHE_OPCODES;
+ break;
case OP_WORD:
case OP_NOT_WORD:
@@ -644,7 +650,7 @@ init_cache_opcodes_inner(
case OP_NOT_WORD_BOUND:
case OP_WORD_BEGIN:
case OP_WORD_END:
- break;
+ break;
case OP_ASCII_WORD:
case OP_NOT_ASCII_WORD:
@@ -652,7 +658,7 @@ init_cache_opcodes_inner(
case OP_NOT_ASCII_WORD_BOUND:
case OP_ASCII_WORD_BEGIN:
case OP_ASCII_WORD_END:
- break;
+ break;
case OP_BEGIN_BUF:
case OP_END_BUF:
@@ -660,7 +666,7 @@ init_cache_opcodes_inner(
case OP_END_LINE:
case OP_SEMI_END_BUF:
case OP_BEGIN_POSITION:
- break;
+ break;
case OP_BACKREF1:
case OP_BACKREF2:
@@ -669,7 +675,7 @@ init_cache_opcodes_inner(
case OP_BACKREF_MULTI:
case OP_BACKREF_MULTI_IC:
case OP_BACKREF_WITH_LEVEL:
- goto unexpected_bytecode_error;
+ goto unexpected_bytecode_error;
case OP_MEMORY_START:
case OP_MEMORY_START_PUSH:
@@ -677,149 +683,158 @@ init_cache_opcodes_inner(
case OP_MEMORY_END_PUSH_REC:
case OP_MEMORY_END:
case OP_MEMORY_END_REC:
- p += SIZE_MEMNUM;
- if (lookaround_nesting != 0) {
- goto unexpected_bytecode_error;
- }
- break;
+ p += SIZE_MEMNUM;
+ if (lookaround_nesting != 0) {
+ goto unexpected_bytecode_error;
+ }
+ break;
case OP_KEEP:
- break;
+ break;
case OP_FAIL:
- break;
+ break;
case OP_JUMP:
- p += SIZE_RELADDR;
- break;
+ p += SIZE_RELADDR;
+ break;
case OP_PUSH:
- p += SIZE_RELADDR;
- INC_CACHE_OPCODES;
- break;
+ p += SIZE_RELADDR;
+ INC_CACHE_OPCODES;
+ break;
case OP_POP:
- break;
+ break;
case OP_PUSH_OR_JUMP_EXACT1:
case OP_PUSH_IF_PEEK_NEXT:
- p += SIZE_RELADDR + 1;
- INC_CACHE_OPCODES;
- break;
+ p += SIZE_RELADDR + 1;
+ INC_CACHE_OPCODES;
+ break;
case OP_REPEAT:
case OP_REPEAT_NG:
- GET_MEMNUM_INC(repeat_mem, p);
- p += SIZE_RELADDR;
- if (reg->repeat_range[repeat_mem].lower == 0) {
- INC_CACHE_OPCODES;
- }
- {
- long num_cache_points_in_repeat = 0;
- long num_cache_points_at_repeat = cache_point;
- OnigCacheOpcode* cache_opcodes_in_repeat = cache_opcodes;
- result = init_cache_opcodes_inner(reg, repeat_mem, lookaround_nesting, &cache_opcodes, &p, &num_cache_points_in_repeat);
- if (result != 0) {
- goto fail;
- }
- OnigRepeatRange *repeat_range = &reg->repeat_range[repeat_mem];
- if (repeat_range->lower < repeat_range->upper) {
- INC_CACHE_OPCODES;
- cache_point -= lookaround_nesting != 0 ? 2 : 1;
- }
- int repeat_bounds = repeat_range->upper == 0x7fffffff ? 1 : repeat_range->upper - repeat_range->lower;
- cache_point += num_cache_points_in_repeat * repeat_range->lower + (num_cache_points_in_repeat + (lookaround_nesting != 0 ? 2 : 1)) * repeat_bounds;
- for (; cache_opcodes_in_repeat < cache_opcodes; cache_opcodes_in_repeat++) {
- cache_opcodes_in_repeat->num_cache_points_at_outer_repeat = num_cache_points_at_repeat;
- cache_opcodes_in_repeat->num_cache_points_in_outer_repeat = num_cache_points_in_repeat;
- }
- }
- break;
+ GET_MEMNUM_INC(repeat_mem, p);
+ p += SIZE_RELADDR;
+ if (reg->repeat_range[repeat_mem].lower == 0 && reg->repeat_range[repeat_mem].upper == 0) {
+ long dummy_num_cache_points = 0;
+ OnigCacheOpcode* dummy_cache_opcodes = NULL;
+ result = init_cache_opcodes_inner(reg, repeat_mem, lookaround_nesting, &dummy_cache_opcodes, &p, &dummy_num_cache_points);
+ if (result != 0) {
+ goto fail;
+ }
+ } else {
+ if (reg->repeat_range[repeat_mem].lower == 0) {
+ INC_CACHE_OPCODES;
+ }
+ {
+ long num_cache_points_in_repeat = 0;
+ long num_cache_points_at_repeat = cache_point;
+ OnigCacheOpcode* cache_opcodes_in_repeat = cache_opcodes;
+ result = init_cache_opcodes_inner(reg, repeat_mem, lookaround_nesting, &cache_opcodes, &p, &num_cache_points_in_repeat);
+ if (result != 0) {
+ goto fail;
+ }
+ OnigRepeatRange *repeat_range = &reg->repeat_range[repeat_mem];
+ if (repeat_range->lower < repeat_range->upper) {
+ INC_CACHE_OPCODES;
+ cache_point -= lookaround_nesting != 0 ? 2 : 1;
+ }
+ int repeat_bounds = repeat_range->upper == 0x7fffffff ? 1 : repeat_range->upper - repeat_range->lower;
+ cache_point += num_cache_points_in_repeat * repeat_range->lower + (num_cache_points_in_repeat + (lookaround_nesting != 0 ? 2 : 1)) * repeat_bounds;
+ for (; cache_opcodes_in_repeat < cache_opcodes; cache_opcodes_in_repeat++) {
+ cache_opcodes_in_repeat->num_cache_points_at_outer_repeat = num_cache_points_at_repeat;
+ cache_opcodes_in_repeat->num_cache_points_in_outer_repeat = num_cache_points_in_repeat;
+ }
+ }
+ }
+ break;
case OP_REPEAT_INC:
case OP_REPEAT_INC_NG:
- p += SIZE_MEMNUM;
+ p += SIZE_MEMNUM;
goto exit;
case OP_REPEAT_INC_SG:
case OP_REPEAT_INC_NG_SG:
- goto unexpected_bytecode_error;
+ goto unexpected_bytecode_error;
case OP_NULL_CHECK_START:
- p += SIZE_MEMNUM;
- break;
+ p += SIZE_MEMNUM;
+ break;
case OP_NULL_CHECK_END:
case OP_NULL_CHECK_END_MEMST_PUSH:
- p += SIZE_MEMNUM;
- break;
+ p += SIZE_MEMNUM;
+ break;
case OP_NULL_CHECK_END_MEMST:
- p += SIZE_MEMNUM;
- break;
+ p += SIZE_MEMNUM;
+ break;
case OP_PUSH_POS:
- lookaround:
- {
- OnigCacheOpcode* cache_opcodes_in_lookaround = cache_opcodes;
- result = init_cache_opcodes_inner(reg, current_repeat_mem, lookaround_nesting + 1, &cache_opcodes, &p, &cache_point);
- if (result != 0) {
- goto fail;
- }
- UChar* match_addr = p - 1;
- for (; cache_opcodes_in_lookaround < cache_opcodes; cache_opcodes_in_lookaround++) {
- if (cache_opcodes_in_lookaround->match_addr == NULL) {
- cache_opcodes_in_lookaround->match_addr = match_addr;
- }
- }
- }
- break;
+ lookaround:
+ {
+ OnigCacheOpcode* cache_opcodes_in_lookaround = cache_opcodes;
+ result = init_cache_opcodes_inner(reg, current_repeat_mem, lookaround_nesting + 1, &cache_opcodes, &p, &cache_point);
+ if (result != 0) {
+ goto fail;
+ }
+ UChar* match_addr = p - 1;
+ for (; cache_opcodes_in_lookaround < cache_opcodes; cache_opcodes_in_lookaround++) {
+ if (cache_opcodes_in_lookaround->match_addr == NULL) {
+ cache_opcodes_in_lookaround->match_addr = match_addr;
+ }
+ }
+ }
+ break;
case OP_PUSH_POS_NOT:
- p += SIZE_RELADDR;
+ p += SIZE_RELADDR;
goto lookaround;
case OP_PUSH_LOOK_BEHIND_NOT:
- p += SIZE_RELADDR;
- p += SIZE_LENGTH;
+ p += SIZE_RELADDR;
+ p += SIZE_LENGTH;
goto lookaround;
case OP_PUSH_STOP_BT:
- {
- OnigCacheOpcode* cache_opcodes_in_atomic = cache_opcodes;
- result = init_cache_opcodes_inner(reg, current_repeat_mem, -1, &cache_opcodes, &p, &cache_point);
- if (result != 0) {
- goto fail;
- }
- UChar* match_addr = p - 1;
- for (; cache_opcodes_in_atomic < cache_opcodes; cache_opcodes_in_atomic++) {
- if (cache_opcodes_in_atomic->match_addr == NULL) {
- cache_opcodes_in_atomic->match_addr = match_addr;
- }
- }
- }
- break;
+ {
+ OnigCacheOpcode* cache_opcodes_in_atomic = cache_opcodes;
+ result = init_cache_opcodes_inner(reg, current_repeat_mem, -1, &cache_opcodes, &p, &cache_point);
+ if (result != 0) {
+ goto fail;
+ }
+ UChar* match_addr = p - 1;
+ for (; cache_opcodes_in_atomic < cache_opcodes; cache_opcodes_in_atomic++) {
+ if (cache_opcodes_in_atomic->match_addr == NULL) {
+ cache_opcodes_in_atomic->match_addr = match_addr;
+ }
+ }
+ }
+ break;
case OP_POP_POS:
case OP_FAIL_POS:
case OP_FAIL_LOOK_BEHIND_NOT:
case OP_POP_STOP_BT:
- goto exit;
+ goto exit;
case OP_LOOK_BEHIND:
- p += SIZE_LENGTH;
- break;
+ p += SIZE_LENGTH;
+ break;
case OP_ABSENT_END:
case OP_ABSENT:
- goto unexpected_bytecode_error;
+ goto unexpected_bytecode_error;
case OP_CALL:
case OP_RETURN:
- goto unexpected_bytecode_error;
+ goto unexpected_bytecode_error;
case OP_CONDITION:
- goto unexpected_bytecode_error;
+ goto unexpected_bytecode_error;
case OP_STATE_CHECK_PUSH:
case OP_STATE_CHECK_PUSH_OR_JUMP:
case OP_STATE_CHECK:
case OP_STATE_CHECK_ANYCHAR_STAR:
case OP_STATE_CHECK_ANYCHAR_ML_STAR:
- goto unexpected_bytecode_error;
+ goto unexpected_bytecode_error;
case OP_SET_OPTION_PUSH:
case OP_SET_OPTION:
- p += SIZE_OPTION;
- break;
+ p += SIZE_OPTION;
+ break;
default:
- goto bytecode_error;
+ goto bytecode_error;
}
}
@@ -1159,13 +1174,15 @@ onig_region_copy(OnigRegion* to, const OnigRegion* from)
stk_base = stk_alloc;\
stk = stk_base;\
stk_end = stk_base + msa->stack_n;\
- } else {\
+ }\
+ else {\
stk_alloc = (OnigStackType* )xalloca(sizeof(OnigStackType) * (stack_num));\
stk_base = stk_alloc;\
stk = stk_base;\
stk_end = stk_base + (stack_num);\
}\
- } else if (msa->stack_p) {\
+ }\
+ else if (msa->stack_p) {\
alloc_addr = (char* )xalloca(sizeof(OnigStackIndex) * (ptr_num));\
heap_addr = NULL;\
stk_alloc = (OnigStackType* )(msa->stack_p);\
@@ -1175,7 +1192,7 @@ onig_region_copy(OnigRegion* to, const OnigRegion* from)
}\
else {\
alloc_addr = (char* )xalloca(sizeof(OnigStackIndex) * (ptr_num)\
- + sizeof(OnigStackType) * (stack_num));\
+ + sizeof(OnigStackType) * (stack_num));\
heap_addr = NULL;\
stk_alloc = (OnigStackType* )(alloc_addr + sizeof(OnigStackIndex) * (ptr_num));\
stk_base = stk_alloc;\
@@ -1208,7 +1225,7 @@ onig_set_match_stack_limit_size(unsigned int size)
static int
stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
- OnigStackType** arg_stk, OnigStackType* stk_alloc, OnigMatchArg* msa)
+ OnigStackType** arg_stk, OnigStackType* stk_alloc, OnigMatchArg* msa)
{
size_t n;
OnigStackType *x, *stk_base, *stk_end, *stk;
@@ -1232,9 +1249,9 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
n *= 2;
if (limit_size != 0 && n > limit_size) {
if ((unsigned int )(stk_end - stk_base) == limit_size)
- return ONIGERR_MATCH_STACK_LIMIT_OVER;
+ return ONIGERR_MATCH_STACK_LIMIT_OVER;
else
- n = limit_size;
+ n = limit_size;
}
x = (OnigStackType* )xrealloc(stk_base, sizeof(OnigStackType) * n);
if (IS_NULL(x)) {
@@ -1517,7 +1534,8 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
if (stk->type == STK_MATCH_CACHE_POINT) {\
msa->match_cache_buf[stk->u.match_cache_point.index] |= stk->u.match_cache_point.mask;\
MATCH_CACHE_DEBUG_MEMOIZE(stk);\
- } else if (stk->type == STK_ATOMIC_MATCH_CACHE_POINT) {\
+ }\
+ else if (stk->type == STK_ATOMIC_MATCH_CACHE_POINT) {\
memoize_extended_match_cache_point(msa->match_cache_buf, stk->u.match_cache_point.index, stk->u.match_cache_point.mask);\
MATCH_CACHE_DEBUG_MEMOIZE(stkp);\
}\
@@ -1538,7 +1556,7 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
#else
# define INC_NUM_FAILS ((void) 0)
# define MEMOIZE_MATCH_CACHE_POINT ((void) 0)
-# define MEMOIZE_LOOKAROUND_MATCH_CACHE_POINT ((void) 0)
+# define MEMOIZE_LOOKAROUND_MATCH_CACHE_POINT(stkp) ((void) 0)
#endif
#define STACK_POP_ONE do {\
@@ -1883,7 +1901,7 @@ stack_double(OnigStackType** arg_stk_base, OnigStackType** arg_stk_end,
} while(0)
static int string_cmp_ic(OnigEncoding enc, int case_fold_flag,
- UChar* s1, UChar** ps2, OnigDistance mblen, const UChar* text_end)
+ UChar* s1, UChar** ps2, OnigDistance mblen, const UChar* text_end)
{
UChar buf1[ONIGENC_MBC_CASE_FOLD_MAXLEN];
UChar buf2[ONIGENC_MBC_CASE_FOLD_MAXLEN];
@@ -1970,29 +1988,29 @@ make_capture_history_tree(OnigCaptureTreeNode* node, OnigStackType** kp,
if (k->type == STK_MEM_START) {
n = k->u.mem.num;
if (n <= ONIG_MAX_CAPTURE_HISTORY_GROUP &&
- BIT_STATUS_AT(reg->capture_history, n) != 0) {
- child = history_node_new();
- CHECK_NULL_RETURN_MEMERR(child);
- child->group = n;
- child->beg = k->u.mem.pstr - str;
- r = history_tree_add_child(node, child);
- if (r != 0) {
- history_tree_free(child);
- return r;
- }
- *kp = (k + 1);
- r = make_capture_history_tree(child, kp, stk_top, str, reg);
- if (r != 0) return r;
+ BIT_STATUS_AT(reg->capture_history, n) != 0) {
+ child = history_node_new();
+ CHECK_NULL_RETURN_MEMERR(child);
+ child->group = n;
+ child->beg = k->u.mem.pstr - str;
+ r = history_tree_add_child(node, child);
+ if (r != 0) {
+ history_tree_free(child);
+ return r;
+ }
+ *kp = (k + 1);
+ r = make_capture_history_tree(child, kp, stk_top, str, reg);
+ if (r != 0) return r;
- k = *kp;
- child->end = k->u.mem.pstr - str;
+ k = *kp;
+ child->end = k->u.mem.pstr - str;
}
}
else if (k->type == STK_MEM_END) {
if (k->u.mem.num == node->group) {
- node->end = k->u.mem.pstr - str;
- *kp = k;
- return 0;
+ node->end = k->u.mem.pstr - str;
+ *kp = k;
+ return 0;
}
}
k++;
@@ -2017,9 +2035,9 @@ mem_is_in_memp(int mem, int num, UChar* memp)
}
static int backref_match_at_nested_level(regex_t* reg,
- OnigStackType* top, OnigStackType* stk_base,
- int ignore_case, int case_fold_flag,
- int nest, int mem_num, UChar* memp, UChar** s, const UChar* send)
+ OnigStackType* top, OnigStackType* stk_base,
+ int ignore_case, int case_fold_flag,
+ int nest, int mem_num, UChar* memp, UChar** s, const UChar* send)
{
UChar *ss, *p, *pstart, *pend = NULL_UCHARP;
int level;
@@ -2037,33 +2055,33 @@ static int backref_match_at_nested_level(regex_t* reg,
}
else if (level == nest) {
if (k->type == STK_MEM_START) {
- if (mem_is_in_memp(k->u.mem.num, mem_num, memp)) {
- pstart = k->u.mem.pstr;
- if (pend != NULL_UCHARP) {
- if (pend - pstart > send - *s) return 0; /* or goto next_mem; */
- p = pstart;
- ss = *s;
-
- if (ignore_case != 0) {
- if (string_cmp_ic(reg->enc, case_fold_flag,
- pstart, &ss, pend - pstart, send) == 0)
- return 0; /* or goto next_mem; */
- }
- else {
- while (p < pend) {
- if (*p++ != *ss++) return 0; /* or goto next_mem; */
- }
- }
-
- *s = ss;
- return 1;
- }
- }
+ if (mem_is_in_memp(k->u.mem.num, mem_num, memp)) {
+ pstart = k->u.mem.pstr;
+ if (pend != NULL_UCHARP) {
+ if (pend - pstart > send - *s) return 0; /* or goto next_mem; */
+ p = pstart;
+ ss = *s;
+
+ if (ignore_case != 0) {
+ if (string_cmp_ic(reg->enc, case_fold_flag,
+ pstart, &ss, pend - pstart, send) == 0)
+ return 0; /* or goto next_mem; */
+ }
+ else {
+ while (p < pend) {
+ if (*p++ != *ss++) return 0; /* or goto next_mem; */
+ }
+ }
+
+ *s = ss;
+ return 1;
+ }
+ }
}
else if (k->type == STK_MEM_END) {
- if (mem_is_in_memp(k->u.mem.num, mem_num, memp)) {
- pend = k->u.mem.pstr;
- }
+ if (mem_is_in_memp(k->u.mem.num, mem_num, memp)) {
+ pend = k->u.mem.pstr;
+ }
}
}
k--;
@@ -2081,7 +2099,7 @@ static int backref_match_at_nested_level(regex_t* reg,
static LARGE_INTEGER ts, te, freq;
# define GETTIME(t) QueryPerformanceCounter(&(t))
# define TIMEDIFF(te,ts) (unsigned long )(((te).QuadPart - (ts).QuadPart) \
- * 1000000 / freq.QuadPart)
+ * 1000000 / freq.QuadPart)
# else /* _WIN32 */
# define USE_TIMEOFDAY
@@ -2147,7 +2165,7 @@ onig_print_statistics(FILE* f)
fprintf(f, " count prev time\n");
for (i = 0; OnigOpInfo[i].opcode >= 0; i++) {
fprintf(f, "%8d: %8d: %10lu: %s\n",
- OpCounter[i], OpPrevCounter[i], OpTime[i], OnigOpInfo[i].name);
+ OpCounter[i], OpPrevCounter[i], OpTime[i], OnigOpInfo[i].name);
}
fprintf(f, "\nmax stack depth: %d\n", MaxStackDepth);
}
@@ -2262,19 +2280,25 @@ find_cache_point(regex_t* reg, const OnigCacheOpcode* cache_opcodes, long num_ca
cache_point;
}
-static int check_extended_match_cache_point(uint8_t *match_cache_buf, long match_cache_point_index, uint8_t match_cache_point_mask) {
+static int
+check_extended_match_cache_point(uint8_t *match_cache_buf, long match_cache_point_index, uint8_t match_cache_point_mask)
+{
if (match_cache_point_mask & 0x80) {
return (match_cache_buf[match_cache_point_index + 1] & 0x01) > 0;
- } else {
+ }
+ else {
return (match_cache_buf[match_cache_point_index] & (match_cache_point_mask << 1)) > 0;
}
}
-static void memoize_extended_match_cache_point(uint8_t *match_cache_buf, long match_cache_point_index, uint8_t match_cache_point_mask) {
+static void
+memoize_extended_match_cache_point(uint8_t *match_cache_buf, long match_cache_point_index, uint8_t match_cache_point_mask)
+{
match_cache_buf[match_cache_point_index] |= match_cache_point_mask;
if (match_cache_point_mask & 0x80) {
match_cache_buf[match_cache_point_index + 1] |= 0x01;
- } else {
+ }
+ else {
match_cache_buf[match_cache_point_index] |= match_cache_point_mask << 1;
}
}
@@ -2286,9 +2310,9 @@ static void memoize_extended_match_cache_point(uint8_t *match_cache_buf, long ma
static OnigPosition
match_at(regex_t* reg, const UChar* str, const UChar* end,
#ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE
- const UChar* right_range,
+ const UChar* right_range,
#endif
- const UChar* sstart, UChar* sprev, OnigMatchArg* msa)
+ const UChar* sstart, UChar* sprev, OnigMatchArg* msa)
{
static const UChar FinishCode[] = { OP_FINISH };
@@ -2538,16 +2562,16 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
}
#ifndef USE_SUBEXP_CALL
mem_start_stk--; /* for index start from 1,
- mem_start_stk[1]..mem_start_stk[num_mem] */
+ mem_start_stk[1]..mem_start_stk[num_mem] */
mem_end_stk--; /* for index start from 1,
- mem_end_stk[1]..mem_end_stk[num_mem] */
+ mem_end_stk[1]..mem_end_stk[num_mem] */
#endif
#ifdef ONIG_DEBUG_MATCH
fprintf(stderr, "match_at: str: %"PRIuPTR" (%p), end: %"PRIuPTR" (%p), start: %"PRIuPTR" (%p), sprev: %"PRIuPTR" (%p)\n",
- (uintptr_t )str, str, (uintptr_t )end, end, (uintptr_t )sstart, sstart, (uintptr_t )sprev, sprev);
+ (uintptr_t )str, str, (uintptr_t )end, end, (uintptr_t )sstart, sstart, (uintptr_t )sprev, sprev);
fprintf(stderr, "size: %d, start offset: %d\n",
- (int )(end - str), (int )(sstart - str));
+ (int )(end - str), (int )(sstart - str));
fprintf(stderr, "\n ofs> str stk:type addr:opcode\n");
#endif
@@ -2567,10 +2591,10 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
bp = buf; \
q = s; \
if (*op != OP_FINISH) { /* s may not be a valid pointer if OP_FINISH. */ \
- for (i = 0; i < 7 && q < end; i++) { \
- len = enclen(encode, q, end); \
- while (len-- > 0) *bp++ = *q++; \
- } \
+ for (i = 0; i < 7 && q < end; i++) { \
+ len = enclen(encode, q, end); \
+ while (len-- > 0) *bp++ = *q++; \
+ } \
if (q < end) { xmemcpy(bp, "...", 3); bp += 3; } \
} \
xmemcpy(bp, "\"", 1); bp += 1; \
@@ -2578,9 +2602,9 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
fputs((char* )buf, stderr); \
for (i = 0; i < 20 - (bp - buf); i++) fputc(' ', stderr); \
fprintf(stderr, "%4"PRIdPTR":%s %4"PRIdPTR":", \
- stk - stk_base - 1, \
- (stk > stk_base) ? stack_type_str(stk[-1].type) : " ", \
- (op == FinishCode) ? (ptrdiff_t )-1 : op - reg->p); \
+ stk - stk_base - 1, \
+ (stk > stk_base) ? stack_type_str(stk[-1].type) : " ", \
+ (op == FinishCode) ? (ptrdiff_t )-1 : op - reg->p); \
onig_print_compiled_byte_code(stderr, op, reg->p+reg->used, NULL, encode); \
fprintf(stderr, "\n"); \
}
@@ -2609,19 +2633,22 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
uint8_t match_cache_point_mask = 1 << (match_cache_point & 7);\
MATCH_CACHE_DEBUG;\
if (msa->match_cache_buf[match_cache_point_index] & match_cache_point_mask) {\
- MATCH_CACHE_DEBUG_HIT; MATCH_CACHE_HIT;\
- if (cache_opcode->lookaround_nesting == 0) goto fail;\
- else if (cache_opcode->lookaround_nesting < 0) {\
- if (check_extended_match_cache_point(msa->match_cache_buf, match_cache_point_index, match_cache_point_mask)) {\
+ MATCH_CACHE_DEBUG_HIT; MATCH_CACHE_HIT;\
+ if (cache_opcode->lookaround_nesting == 0) goto fail;\
+ else if (cache_opcode->lookaround_nesting < 0) {\
+ if (check_extended_match_cache_point(msa->match_cache_buf, match_cache_point_index, match_cache_point_mask)) {\
STACK_STOP_BT_FAIL;\
goto fail;\
- } else goto fail;\
- } else {\
- if (check_extended_match_cache_point(msa->match_cache_buf, match_cache_point_index, match_cache_point_mask)) {\
- p = cache_opcode->match_addr;\
+ }\
+ else goto fail;\
+ }\
+ else {\
+ if (check_extended_match_cache_point(msa->match_cache_buf, match_cache_point_index, match_cache_point_mask)) {\
+ p = cache_opcode->match_addr;\
MOP_OUT;\
JUMP;\
- } else goto fail;\
+ }\
+ else goto fail;\
}\
}\
STACK_PUSH_MATCH_CACHE_POINT(match_cache_point_index, match_cache_point_mask);\
@@ -2636,66 +2663,66 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_END) MOP_IN(OP_END);
n = s - sstart;
if (n > best_len) {
- OnigRegion* region;
+ OnigRegion* region;
#ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE
- if (IS_FIND_LONGEST(option)) {
- if (n > msa->best_len) {
- msa->best_len = n;
- msa->best_s = (UChar* )sstart;
- }
- else
- goto end_best_len;
- }
+ if (IS_FIND_LONGEST(option)) {
+ if (n > msa->best_len) {
+ msa->best_len = n;
+ msa->best_s = (UChar* )sstart;
+ }
+ else
+ goto end_best_len;
+ }
#endif
- best_len = n;
- region = msa->region;
- if (region) {
- region->beg[0] = ((pkeep > s) ? s : pkeep) - str;
- region->end[0] = s - str;
- for (i = 1; i <= num_mem; i++) {
- if (mem_end_stk[i] != INVALID_STACK_INDEX) {
- if (BIT_STATUS_AT(reg->bt_mem_start, i))
- region->beg[i] = STACK_AT(mem_start_stk[i])->u.mem.pstr - str;
- else
- region->beg[i] = (UChar* )((void* )mem_start_stk[i]) - str;
-
- region->end[i] = (BIT_STATUS_AT(reg->bt_mem_end, i)
- ? STACK_AT(mem_end_stk[i])->u.mem.pstr
- : (UChar* )((void* )mem_end_stk[i])) - str;
- }
- else {
- region->beg[i] = region->end[i] = ONIG_REGION_NOTPOS;
- }
- }
+ best_len = n;
+ region = msa->region;
+ if (region) {
+ region->beg[0] = ((pkeep > s) ? s : pkeep) - str;
+ region->end[0] = s - str;
+ for (i = 1; i <= num_mem; i++) {
+ if (mem_end_stk[i] != INVALID_STACK_INDEX) {
+ if (BIT_STATUS_AT(reg->bt_mem_start, i))
+ region->beg[i] = STACK_AT(mem_start_stk[i])->u.mem.pstr - str;
+ else
+ region->beg[i] = (UChar* )((void* )mem_start_stk[i]) - str;
+
+ region->end[i] = (BIT_STATUS_AT(reg->bt_mem_end, i)
+ ? STACK_AT(mem_end_stk[i])->u.mem.pstr
+ : (UChar* )((void* )mem_end_stk[i])) - str;
+ }
+ else {
+ region->beg[i] = region->end[i] = ONIG_REGION_NOTPOS;
+ }
+ }
#ifdef USE_CAPTURE_HISTORY
- if (reg->capture_history != 0) {
- int r;
- OnigCaptureTreeNode* node;
-
- if (IS_NULL(region->history_root)) {
- region->history_root = node = history_node_new();
- CHECK_NULL_RETURN_MEMERR(node);
- }
- else {
- node = region->history_root;
- history_tree_clear(node);
- }
-
- node->group = 0;
- node->beg = ((pkeep > s) ? s : pkeep) - str;
- node->end = s - str;
-
- stkp = stk_base;
- r = make_capture_history_tree(region->history_root, &stkp,
- stk, (UChar* )str, reg);
- if (r < 0) {
- best_len = r; /* error code */
- goto finish;
- }
- }
+ if (reg->capture_history != 0) {
+ int r;
+ OnigCaptureTreeNode* node;
+
+ if (IS_NULL(region->history_root)) {
+ region->history_root = node = history_node_new();
+ CHECK_NULL_RETURN_MEMERR(node);
+ }
+ else {
+ node = region->history_root;
+ history_tree_clear(node);
+ }
+
+ node->group = 0;
+ node->beg = ((pkeep > s) ? s : pkeep) - str;
+ node->end = s - str;
+
+ stkp = stk_base;
+ r = make_capture_history_tree(region->history_root, &stkp,
+ stk, (UChar* )str, reg);
+ if (r < 0) {
+ best_len = r; /* error code */
+ goto finish;
+ }
+ }
#endif /* USE_CAPTURE_HISTORY */
- } /* if (region) */
+ } /* if (region) */
} /* n > best_len */
#ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE
@@ -2704,18 +2731,17 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
MOP_OUT;
if (IS_FIND_CONDITION(option)) {
- if (IS_FIND_NOT_EMPTY(option) && s == sstart) {
- best_len = ONIG_MISMATCH;
- goto fail; /* for retry */
- }
- if (IS_FIND_LONGEST(option) && DATA_ENSURE_CHECK1) {
- goto fail; /* for retry */
- }
+ if (IS_FIND_NOT_EMPTY(option) && s == sstart) {
+ best_len = ONIG_MISMATCH;
+ goto fail; /* for retry */
+ }
+ if (IS_FIND_LONGEST(option) && DATA_ENSURE_CHECK1) {
+ goto fail; /* for retry */
+ }
}
/* default behavior: return first-matching result. */
goto finish;
- NEXT;
CASE(OP_EXACT1) MOP_IN(OP_EXACT1);
DATA_ENSURE(1);
@@ -2726,22 +2752,22 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_EXACT1_IC) MOP_IN(OP_EXACT1_IC);
{
- int len;
- UChar *q, lowbuf[ONIGENC_MBC_CASE_FOLD_MAXLEN];
-
- DATA_ENSURE(1);
- len = ONIGENC_MBC_CASE_FOLD(encode,
- /* DISABLE_CASE_FOLD_MULTI_CHAR(case_fold_flag), */
- case_fold_flag,
- &s, end, lowbuf);
- DATA_ENSURE(0);
- q = lowbuf;
- while (len-- > 0) {
- if (*p != *q) {
- goto fail;
- }
- p++; q++;
- }
+ int len;
+ UChar *q, lowbuf[ONIGENC_MBC_CASE_FOLD_MAXLEN];
+
+ DATA_ENSURE(1);
+ len = ONIGENC_MBC_CASE_FOLD(encode,
+ /* DISABLE_CASE_FOLD_MULTI_CHAR(case_fold_flag), */
+ case_fold_flag,
+ &s, end, lowbuf);
+ DATA_ENSURE(0);
+ q = lowbuf;
+ while (len-- > 0) {
+ if (*p != *q) {
+ goto fail;
+ }
+ p++; q++;
+ }
}
MOP_OUT;
NEXT;
@@ -2802,7 +2828,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
GET_LENGTH_INC(tlen, p);
DATA_ENSURE(tlen);
while (tlen-- > 0) {
- if (*p++ != *s++) goto fail;
+ if (*p++ != *s++) goto fail;
}
sprev = s - 1;
MOP_OUT;
@@ -2810,26 +2836,26 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_EXACTN_IC) MOP_IN(OP_EXACTN_IC);
{
- int len;
- UChar *q, *endp, lowbuf[ONIGENC_MBC_CASE_FOLD_MAXLEN];
-
- GET_LENGTH_INC(tlen, p);
- endp = p + tlen;
-
- while (p < endp) {
- sprev = s;
- DATA_ENSURE(1);
- len = ONIGENC_MBC_CASE_FOLD(encode,
- /* DISABLE_CASE_FOLD_MULTI_CHAR(case_fold_flag), */
- case_fold_flag,
- &s, end, lowbuf);
- DATA_ENSURE(0);
- q = lowbuf;
- while (len-- > 0) {
- if (*p != *q) goto fail;
- p++; q++;
- }
- }
+ int len;
+ UChar *q, *endp, lowbuf[ONIGENC_MBC_CASE_FOLD_MAXLEN];
+
+ GET_LENGTH_INC(tlen, p);
+ endp = p + tlen;
+
+ while (p < endp) {
+ sprev = s;
+ DATA_ENSURE(1);
+ len = ONIGENC_MBC_CASE_FOLD(encode,
+ /* DISABLE_CASE_FOLD_MULTI_CHAR(case_fold_flag), */
+ case_fold_flag,
+ &s, end, lowbuf);
+ DATA_ENSURE(0);
+ q = lowbuf;
+ while (len-- > 0) {
+ if (*p != *q) goto fail;
+ p++; q++;
+ }
+ }
}
MOP_OUT;
@@ -2880,10 +2906,10 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
GET_LENGTH_INC(tlen, p);
DATA_ENSURE(tlen * 2);
while (tlen-- > 0) {
- if (*p != *s) goto fail;
- p++; s++;
- if (*p != *s) goto fail;
- p++; s++;
+ if (*p != *s) goto fail;
+ p++; s++;
+ if (*p != *s) goto fail;
+ p++; s++;
}
sprev = s - 2;
MOP_OUT;
@@ -2893,12 +2919,12 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
GET_LENGTH_INC(tlen, p);
DATA_ENSURE(tlen * 3);
while (tlen-- > 0) {
- if (*p != *s) goto fail;
- p++; s++;
- if (*p != *s) goto fail;
- p++; s++;
- if (*p != *s) goto fail;
- p++; s++;
+ if (*p != *s) goto fail;
+ p++; s++;
+ if (*p != *s) goto fail;
+ p++; s++;
+ if (*p != *s) goto fail;
+ p++; s++;
}
sprev = s - 3;
MOP_OUT;
@@ -2910,8 +2936,8 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
tlen2 *= tlen;
DATA_ENSURE(tlen2);
while (tlen2-- > 0) {
- if (*p != *s) goto fail;
- p++; s++;
+ if (*p != *s) goto fail;
+ p++; s++;
}
sprev = s - tlen;
MOP_OUT;
@@ -2931,23 +2957,23 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
cclass_mb:
GET_LENGTH_INC(tlen, p);
{
- OnigCodePoint code;
- UChar *ss;
- int mb_len;
+ OnigCodePoint code;
+ UChar *ss;
+ int mb_len;
- DATA_ENSURE(1);
- mb_len = enclen_approx(encode, s, end);
- DATA_ENSURE(mb_len);
- ss = s;
- s += mb_len;
- code = ONIGENC_MBC_TO_CODE(encode, ss, s);
+ DATA_ENSURE(1);
+ mb_len = enclen_approx(encode, s, end);
+ DATA_ENSURE(mb_len);
+ ss = s;
+ s += mb_len;
+ code = ONIGENC_MBC_TO_CODE(encode, ss, s);
#ifdef PLATFORM_UNALIGNED_WORD_ACCESS
- if (! onig_is_in_code_range(p, code)) goto fail;
+ if (! onig_is_in_code_range(p, code)) goto fail;
#else
- q = p;
- ALIGNMENT_RIGHT(q);
- if (! onig_is_in_code_range(q, code)) goto fail;
+ q = p;
+ ALIGNMENT_RIGHT(q);
+ if (! onig_is_in_code_range(q, code)) goto fail;
#endif
}
p += tlen;
@@ -2957,17 +2983,17 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_CCLASS_MIX) MOP_IN(OP_CCLASS_MIX);
DATA_ENSURE(1);
if (ONIGENC_IS_MBC_HEAD(encode, s, end)) {
- p += SIZE_BITSET;
- goto cclass_mb;
+ p += SIZE_BITSET;
+ goto cclass_mb;
}
else {
- if (BITSET_AT(((BitSetRef )p), *s) == 0)
- goto fail;
+ if (BITSET_AT(((BitSetRef )p), *s) == 0)
+ goto fail;
- p += SIZE_BITSET;
- GET_LENGTH_INC(tlen, p);
- p += tlen;
- s++;
+ p += SIZE_BITSET;
+ GET_LENGTH_INC(tlen, p);
+ p += tlen;
+ s++;
}
MOP_OUT;
NEXT;
@@ -2983,36 +3009,36 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_CCLASS_MB_NOT) MOP_IN(OP_CCLASS_MB_NOT);
DATA_ENSURE(1);
if (! ONIGENC_IS_MBC_HEAD(encode, s, end)) {
- s++;
- GET_LENGTH_INC(tlen, p);
- p += tlen;
- goto cc_mb_not_success;
+ s++;
+ GET_LENGTH_INC(tlen, p);
+ p += tlen;
+ goto cc_mb_not_success;
}
cclass_mb_not:
GET_LENGTH_INC(tlen, p);
{
- OnigCodePoint code;
- UChar *ss;
- int mb_len = enclen(encode, s, end);
-
- if (! DATA_ENSURE_CHECK(mb_len)) {
- DATA_ENSURE(1);
- s = (UChar* )end;
- p += tlen;
- goto cc_mb_not_success;
- }
+ OnigCodePoint code;
+ UChar *ss;
+ int mb_len = enclen(encode, s, end);
+
+ if (! DATA_ENSURE_CHECK(mb_len)) {
+ DATA_ENSURE(1);
+ s = (UChar* )end;
+ p += tlen;
+ goto cc_mb_not_success;
+ }
- ss = s;
- s += mb_len;
- code = ONIGENC_MBC_TO_CODE(encode, ss, s);
+ ss = s;
+ s += mb_len;
+ code = ONIGENC_MBC_TO_CODE(encode, ss, s);
#ifdef PLATFORM_UNALIGNED_WORD_ACCESS
- if (onig_is_in_code_range(p, code)) goto fail;
+ if (onig_is_in_code_range(p, code)) goto fail;
#else
- q = p;
- ALIGNMENT_RIGHT(q);
- if (onig_is_in_code_range(q, code)) goto fail;
+ q = p;
+ ALIGNMENT_RIGHT(q);
+ if (onig_is_in_code_range(q, code)) goto fail;
#endif
}
p += tlen;
@@ -3024,17 +3050,17 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_CCLASS_MIX_NOT) MOP_IN(OP_CCLASS_MIX_NOT);
DATA_ENSURE(1);
if (ONIGENC_IS_MBC_HEAD(encode, s, end)) {
- p += SIZE_BITSET;
- goto cclass_mb_not;
+ p += SIZE_BITSET;
+ goto cclass_mb_not;
}
else {
- if (BITSET_AT(((BitSetRef )p), *s) != 0)
- goto fail;
+ if (BITSET_AT(((BitSetRef )p), *s) != 0)
+ goto fail;
- p += SIZE_BITSET;
- GET_LENGTH_INC(tlen, p);
- p += tlen;
- s++;
+ p += SIZE_BITSET;
+ GET_LENGTH_INC(tlen, p);
+ p += tlen;
+ s++;
}
MOP_OUT;
NEXT;
@@ -3058,52 +3084,52 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_ANYCHAR_STAR) MOP_IN(OP_ANYCHAR_STAR);
while (DATA_ENSURE_CHECK1) {
- CHECK_MATCH_CACHE;
- STACK_PUSH_ALT(p, s, sprev, pkeep);
- n = enclen_approx(encode, s, end);
- DATA_ENSURE(n);
- if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0)) goto fail;
- sprev = s;
- s += n;
+ CHECK_MATCH_CACHE;
+ STACK_PUSH_ALT(p, s, sprev, pkeep);
+ n = enclen_approx(encode, s, end);
+ DATA_ENSURE(n);
+ if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0)) goto fail;
+ sprev = s;
+ s += n;
}
MOP_OUT;
JUMP;
CASE(OP_ANYCHAR_ML_STAR) MOP_IN(OP_ANYCHAR_ML_STAR);
while (DATA_ENSURE_CHECK1) {
- CHECK_MATCH_CACHE;
- STACK_PUSH_ALT(p, s, sprev, pkeep);
- n = enclen_approx(encode, s, end);
- if (n > 1) {
- DATA_ENSURE(n);
- sprev = s;
- s += n;
- }
- else {
- sprev = s;
- s++;
- }
+ CHECK_MATCH_CACHE;
+ STACK_PUSH_ALT(p, s, sprev, pkeep);
+ n = enclen_approx(encode, s, end);
+ if (n > 1) {
+ DATA_ENSURE(n);
+ sprev = s;
+ s += n;
+ }
+ else {
+ sprev = s;
+ s++;
+ }
}
MOP_OUT;
JUMP;
CASE(OP_ANYCHAR_STAR_PEEK_NEXT) MOP_IN(OP_ANYCHAR_STAR_PEEK_NEXT);
while (DATA_ENSURE_CHECK1) {
- CHECK_MATCH_CACHE;
- if (*p == *s) {
- STACK_PUSH_ALT(p + 1, s, sprev, pkeep);
- } else {
+ CHECK_MATCH_CACHE;
+ if (*p == *s) {
+ STACK_PUSH_ALT(p + 1, s, sprev, pkeep);
+ } else {
#ifdef USE_MATCH_CACHE
- /* We need to increment num_fails here, for invoking a cache optimization correctly. */
- /* Actually, the matching will be failed if we use `OP_ANYCHAR_STAR` simply in this case.*/
- msa->num_fails++;
+ /* We need to increment num_fails here, for invoking a cache optimization correctly. */
+ /* Actually, the matching will be failed if we use `OP_ANYCHAR_STAR` simply in this case.*/
+ msa->num_fails++;
#endif
- }
- n = enclen_approx(encode, s, end);
- DATA_ENSURE(n);
- if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0)) goto fail;
- sprev = s;
- s += n;
+ }
+ n = enclen_approx(encode, s, end);
+ DATA_ENSURE(n);
+ if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0)) goto fail;
+ sprev = s;
+ s += n;
}
p++;
MOP_OUT;
@@ -3111,26 +3137,26 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_ANYCHAR_ML_STAR_PEEK_NEXT)MOP_IN(OP_ANYCHAR_ML_STAR_PEEK_NEXT);
while (DATA_ENSURE_CHECK1) {
- CHECK_MATCH_CACHE;
- if (*p == *s) {
- STACK_PUSH_ALT(p + 1, s, sprev, pkeep);
- } else {
+ CHECK_MATCH_CACHE;
+ if (*p == *s) {
+ STACK_PUSH_ALT(p + 1, s, sprev, pkeep);
+ } else {
#ifdef USE_MATCH_CACHE
- /* We need to increment num_fails here, for invoking a cache optimization correctly. */
- /* Actually, the matching will be failed if we use `OP_ANYCHAR_STAR_ML` simply in this case.*/
- msa->num_fails++;
+ /* We need to increment num_fails here, for invoking a cache optimization correctly. */
+ /* Actually, the matching will be failed if we use `OP_ANYCHAR_STAR_ML` simply in this case.*/
+ msa->num_fails++;
#endif
- }
- n = enclen_approx(encode, s, end);
- if (n > 1) {
- DATA_ENSURE(n);
- sprev = s;
- s += n;
- }
- else {
- sprev = s;
- s++;
- }
+ }
+ n = enclen_approx(encode, s, end);
+ if (n > 1) {
+ DATA_ENSURE(n);
+ sprev = s;
+ s += n;
+ }
+ else {
+ sprev = s;
+ s++;
+ }
}
p++;
MOP_OUT;
@@ -3140,15 +3166,15 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_STATE_CHECK_ANYCHAR_STAR) MOP_IN(OP_STATE_CHECK_ANYCHAR_STAR);
GET_STATE_CHECK_NUM_INC(mem, p);
while (DATA_ENSURE_CHECK1) {
- STATE_CHECK_VAL(scv, mem);
- if (scv) goto fail;
-
- STACK_PUSH_ALT_WITH_STATE_CHECK(p, s, sprev, mem, pkeep);
- n = enclen_approx(encode, s, end);
- DATA_ENSURE(n);
- if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0)) goto fail;
- sprev = s;
- s += n;
+ STATE_CHECK_VAL(scv, mem);
+ if (scv) goto fail;
+
+ STACK_PUSH_ALT_WITH_STATE_CHECK(p, s, sprev, mem, pkeep);
+ n = enclen_approx(encode, s, end);
+ DATA_ENSURE(n);
+ if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 0)) goto fail;
+ sprev = s;
+ s += n;
}
MOP_OUT;
NEXT;
@@ -3158,20 +3184,20 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
GET_STATE_CHECK_NUM_INC(mem, p);
while (DATA_ENSURE_CHECK1) {
- STATE_CHECK_VAL(scv, mem);
- if (scv) goto fail;
-
- STACK_PUSH_ALT_WITH_STATE_CHECK(p, s, sprev, mem, pkeep);
- n = enclen_approx(encode, s, end);
- if (n > 1) {
- DATA_ENSURE(n);
- sprev = s;
- s += n;
- }
- else {
- sprev = s;
- s++;
- }
+ STATE_CHECK_VAL(scv, mem);
+ if (scv) goto fail;
+
+ STACK_PUSH_ALT_WITH_STATE_CHECK(p, s, sprev, mem, pkeep);
+ n = enclen_approx(encode, s, end);
+ if (n > 1) {
+ DATA_ENSURE(n);
+ sprev = s;
+ s += n;
+ }
+ else {
+ sprev = s;
+ s++;
+ }
}
MOP_OUT;
NEXT;
@@ -3180,7 +3206,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_WORD) MOP_IN(OP_WORD);
DATA_ENSURE(1);
if (! ONIGENC_IS_MBC_WORD(encode, s, end))
- goto fail;
+ goto fail;
s += enclen(encode, s, end);
MOP_OUT;
@@ -3189,7 +3215,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_ASCII_WORD) MOP_IN(OP_ASCII_WORD);
DATA_ENSURE(1);
if (! ONIGENC_IS_MBC_ASCII_WORD(encode, s, end))
- goto fail;
+ goto fail;
s += enclen(encode, s, end);
MOP_OUT;
@@ -3198,7 +3224,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_NOT_WORD) MOP_IN(OP_NOT_WORD);
DATA_ENSURE(1);
if (ONIGENC_IS_MBC_WORD(encode, s, end))
- goto fail;
+ goto fail;
s += enclen(encode, s, end);
MOP_OUT;
@@ -3207,7 +3233,7 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_NOT_ASCII_WORD) MOP_IN(OP_NOT_ASCII_WORD);
DATA_ENSURE(1);
if (ONIGENC_IS_MBC_ASCII_WORD(encode, s, end))
- goto fail;
+ goto fail;
s += enclen(encode, s, end);
MOP_OUT;
@@ -3215,70 +3241,70 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_WORD_BOUND) MOP_IN(OP_WORD_BOUND);
if (ON_STR_BEGIN(s)) {
- DATA_ENSURE(1);
- if (! ONIGENC_IS_MBC_WORD(encode, s, end))
- goto fail;
+ DATA_ENSURE(1);
+ if (! ONIGENC_IS_MBC_WORD(encode, s, end))
+ goto fail;
}
else if (ON_STR_END(s)) {
- if (! ONIGENC_IS_MBC_WORD(encode, sprev, end))
- goto fail;
+ if (! ONIGENC_IS_MBC_WORD(encode, sprev, end))
+ goto fail;
}
else {
- if (ONIGENC_IS_MBC_WORD(encode, s, end)
- == ONIGENC_IS_MBC_WORD(encode, sprev, end))
- goto fail;
+ if (ONIGENC_IS_MBC_WORD(encode, s, end)
+ == ONIGENC_IS_MBC_WORD(encode, sprev, end))
+ goto fail;
}
MOP_OUT;
JUMP;
CASE(OP_ASCII_WORD_BOUND) MOP_IN(OP_ASCII_WORD_BOUND);
if (ON_STR_BEGIN(s)) {
- DATA_ENSURE(1);
- if (! ONIGENC_IS_MBC_ASCII_WORD(encode, s, end))
- goto fail;
+ DATA_ENSURE(1);
+ if (! ONIGENC_IS_MBC_ASCII_WORD(encode, s, end))
+ goto fail;
}
else if (ON_STR_END(s)) {
- if (! ONIGENC_IS_MBC_ASCII_WORD(encode, sprev, end))
- goto fail;
+ if (! ONIGENC_IS_MBC_ASCII_WORD(encode, sprev, end))
+ goto fail;
}
else {
- if (ONIGENC_IS_MBC_ASCII_WORD(encode, s, end)
- == ONIGENC_IS_MBC_ASCII_WORD(encode, sprev, end))
- goto fail;
+ if (ONIGENC_IS_MBC_ASCII_WORD(encode, s, end)
+ == ONIGENC_IS_MBC_ASCII_WORD(encode, sprev, end))
+ goto fail;
}
MOP_OUT;
JUMP;
CASE(OP_NOT_WORD_BOUND) MOP_IN(OP_NOT_WORD_BOUND);
if (ON_STR_BEGIN(s)) {
- if (DATA_ENSURE_CHECK1 && ONIGENC_IS_MBC_WORD(encode, s, end))
- goto fail;
+ if (DATA_ENSURE_CHECK1 && ONIGENC_IS_MBC_WORD(encode, s, end))
+ goto fail;
}
else if (ON_STR_END(s)) {
- if (ONIGENC_IS_MBC_WORD(encode, sprev, end))
- goto fail;
+ if (ONIGENC_IS_MBC_WORD(encode, sprev, end))
+ goto fail;
}
else {
- if (ONIGENC_IS_MBC_WORD(encode, s, end)
- != ONIGENC_IS_MBC_WORD(encode, sprev, end))
- goto fail;
+ if (ONIGENC_IS_MBC_WORD(encode, s, end)
+ != ONIGENC_IS_MBC_WORD(encode, sprev, end))
+ goto fail;
}
MOP_OUT;
JUMP;
CASE(OP_NOT_ASCII_WORD_BOUND) MOP_IN(OP_NOT_ASCII_WORD_BOUND);
if (ON_STR_BEGIN(s)) {
- if (DATA_ENSURE_CHECK1 && ONIGENC_IS_MBC_ASCII_WORD(encode, s, end))
- goto fail;
+ if (DATA_ENSURE_CHECK1 && ONIGENC_IS_MBC_ASCII_WORD(encode, s, end))
+ goto fail;
}
else if (ON_STR_END(s)) {
- if (ONIGENC_IS_MBC_ASCII_WORD(encode, sprev, end))
- goto fail;
+ if (ONIGENC_IS_MBC_ASCII_WORD(encode, sprev, end))
+ goto fail;
}
else {
- if (ONIGENC_IS_MBC_ASCII_WORD(encode, s, end)
- != ONIGENC_IS_MBC_ASCII_WORD(encode, sprev, end))
- goto fail;
+ if (ONIGENC_IS_MBC_ASCII_WORD(encode, s, end)
+ != ONIGENC_IS_MBC_ASCII_WORD(encode, sprev, end))
+ goto fail;
}
MOP_OUT;
JUMP;
@@ -3286,43 +3312,39 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
#ifdef USE_WORD_BEGIN_END
CASE(OP_WORD_BEGIN) MOP_IN(OP_WORD_BEGIN);
if (DATA_ENSURE_CHECK1 && ONIGENC_IS_MBC_WORD(encode, s, end)) {
- if (ON_STR_BEGIN(s) || !ONIGENC_IS_MBC_WORD(encode, sprev, end)) {
- MOP_OUT;
- JUMP;
+ if (ON_STR_BEGIN(s) || !ONIGENC_IS_MBC_WORD(encode, sprev, end)) {
+ MOP_OUT;
+ JUMP;
}
}
goto fail;
- NEXT;
CASE(OP_ASCII_WORD_BEGIN) MOP_IN(OP_ASCII_WORD_BEGIN);
if (DATA_ENSURE_CHECK1 && ONIGENC_IS_MBC_ASCII_WORD(encode, s, end)) {
- if (ON_STR_BEGIN(s) || !ONIGENC_IS_MBC_ASCII_WORD(encode, sprev, end)) {
- MOP_OUT;
- JUMP;
+ if (ON_STR_BEGIN(s) || !ONIGENC_IS_MBC_ASCII_WORD(encode, sprev, end)) {
+ MOP_OUT;
+ JUMP;
}
}
goto fail;
- NEXT;
CASE(OP_WORD_END) MOP_IN(OP_WORD_END);
if (!ON_STR_BEGIN(s) && ONIGENC_IS_MBC_WORD(encode, sprev, end)) {
- if (ON_STR_END(s) || !ONIGENC_IS_MBC_WORD(encode, s, end)) {
- MOP_OUT;
- JUMP;
+ if (ON_STR_END(s) || !ONIGENC_IS_MBC_WORD(encode, s, end)) {
+ MOP_OUT;
+ JUMP;
}
}
goto fail;
- NEXT;
CASE(OP_ASCII_WORD_END) MOP_IN(OP_ASCII_WORD_END);
if (!ON_STR_BEGIN(s) && ONIGENC_IS_MBC_ASCII_WORD(encode, sprev, end)) {
- if (ON_STR_END(s) || !ONIGENC_IS_MBC_ASCII_WORD(encode, s, end)) {
- MOP_OUT;
- JUMP;
+ if (ON_STR_END(s) || !ONIGENC_IS_MBC_ASCII_WORD(encode, s, end)) {
+ MOP_OUT;
+ JUMP;
}
}
goto fail;
- NEXT;
#endif
CASE(OP_BEGIN_BUF) MOP_IN(OP_BEGIN_BUF);
@@ -3341,76 +3363,73 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_BEGIN_LINE) MOP_IN(OP_BEGIN_LINE);
if (ON_STR_BEGIN(s)) {
- if (IS_NOTBOL(msa->options)) goto fail;
- MOP_OUT;
- JUMP;
+ if (IS_NOTBOL(msa->options)) goto fail;
+ MOP_OUT;
+ JUMP;
}
else if (ONIGENC_IS_MBC_NEWLINE(encode, sprev, end)
#ifdef USE_CRNL_AS_LINE_TERMINATOR
- && !(IS_NEWLINE_CRLF(option)
- && ONIGENC_IS_MBC_CRNL(encode, sprev, end))
+ && !(IS_NEWLINE_CRLF(option)
+ && ONIGENC_IS_MBC_CRNL(encode, sprev, end))
#endif
- && !ON_STR_END(s)) {
- MOP_OUT;
+ && !ON_STR_END(s)) {
+ MOP_OUT;
JUMP;
}
goto fail;
- NEXT;
CASE(OP_END_LINE) MOP_IN(OP_END_LINE);
if (ON_STR_END(s)) {
#ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE
- if (IS_EMPTY_STR || !ONIGENC_IS_MBC_NEWLINE_EX(encode, sprev, str, end, option, 1)) {
+ if (IS_EMPTY_STR || !ONIGENC_IS_MBC_NEWLINE_EX(encode, sprev, str, end, option, 1)) {
#endif
- if (IS_NOTEOL(msa->options)) goto fail;
- MOP_OUT;
- JUMP;
+ if (IS_NOTEOL(msa->options)) goto fail;
+ MOP_OUT;
+ JUMP;
#ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE
- }
+ }
#endif
}
else if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 1)) {
- MOP_OUT;
+ MOP_OUT;
JUMP;
}
goto fail;
- NEXT;
CASE(OP_SEMI_END_BUF) MOP_IN(OP_SEMI_END_BUF);
if (ON_STR_END(s)) {
#ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE
- if (IS_EMPTY_STR || !ONIGENC_IS_MBC_NEWLINE_EX(encode, sprev, str, end, option, 1)) {
+ if (IS_EMPTY_STR || !ONIGENC_IS_MBC_NEWLINE_EX(encode, sprev, str, end, option, 1)) {
#endif
- if (IS_NOTEOL(msa->options)) goto fail;
- MOP_OUT;
- JUMP;
+ if (IS_NOTEOL(msa->options)) goto fail;
+ MOP_OUT;
+ JUMP;
#ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE
- }
+ }
#endif
}
else if (ONIGENC_IS_MBC_NEWLINE_EX(encode, s, str, end, option, 1)) {
- UChar* ss = s + enclen(encode, s, end);
- if (ON_STR_END(ss)) {
- MOP_OUT;
- JUMP;
- }
+ UChar* ss = s + enclen(encode, s, end);
+ if (ON_STR_END(ss)) {
+ MOP_OUT;
+ JUMP;
+ }
#ifdef USE_CRNL_AS_LINE_TERMINATOR
- else if (IS_NEWLINE_CRLF(option)
- && ONIGENC_IS_MBC_CRNL(encode, s, end)) {
- ss += enclen(encode, ss, end);
- if (ON_STR_END(ss)) {
- MOP_OUT;
- JUMP;
- }
- }
+ else if (IS_NEWLINE_CRLF(option)
+ && ONIGENC_IS_MBC_CRNL(encode, s, end)) {
+ ss += enclen(encode, ss, end);
+ if (ON_STR_END(ss)) {
+ MOP_OUT;
+ JUMP;
+ }
+ }
#endif
}
goto fail;
- NEXT;
CASE(OP_BEGIN_POSITION) MOP_IN(OP_BEGIN_POSITION);
if (s != msa->gpos)
- goto fail;
+ goto fail;
MOP_OUT;
JUMP;
@@ -3460,9 +3479,9 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
STACK_GET_MEM_START(mem, stkp);
if (BIT_STATUS_AT(reg->bt_mem_start, mem))
- mem_start_stk[mem] = GET_STACK_INDEX(stkp);
+ mem_start_stk[mem] = GET_STACK_INDEX(stkp);
else
- mem_start_stk[mem] = (OnigStackIndex )((void* )stkp->u.mem.pstr);
+ mem_start_stk[mem] = (OnigStackIndex )((void* )stkp->u.mem.pstr);
STACK_PUSH_MEM_END_MARK(mem);
MOP_OUT;
@@ -3472,178 +3491,176 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_BACKREF1) MOP_IN(OP_BACKREF1);
mem = 1;
goto backref;
- NEXT;
CASE(OP_BACKREF2) MOP_IN(OP_BACKREF2);
mem = 2;
goto backref;
- NEXT;
CASE(OP_BACKREFN) MOP_IN(OP_BACKREFN);
GET_MEMNUM_INC(mem, p);
backref:
{
- int len;
- UChar *pstart, *pend;
-
- /* if you want to remove following line,
- you should check in parse and compile time. */
- if (mem > num_mem) goto fail;
- if (mem_end_stk[mem] == INVALID_STACK_INDEX) goto fail;
- if (mem_start_stk[mem] == INVALID_STACK_INDEX) goto fail;
-
- if (BIT_STATUS_AT(reg->bt_mem_start, mem))
- pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;
- else
- pstart = (UChar* )((void* )mem_start_stk[mem]);
-
- pend = (BIT_STATUS_AT(reg->bt_mem_end, mem)
- ? STACK_AT(mem_end_stk[mem])->u.mem.pstr
- : (UChar* )((void* )mem_end_stk[mem]));
- n = pend - pstart;
- DATA_ENSURE(n);
- sprev = s;
- STRING_CMP(pstart, s, n);
- while (sprev + (len = enclen_approx(encode, sprev, end)) < s)
- sprev += len;
-
- MOP_OUT;
- JUMP;
+ int len;
+ UChar *pstart, *pend;
+
+ /* if you want to remove following line,
+ you should check in parse and compile time. */
+ if (mem > num_mem) goto fail;
+ if (mem_end_stk[mem] == INVALID_STACK_INDEX) goto fail;
+ if (mem_start_stk[mem] == INVALID_STACK_INDEX) goto fail;
+
+ if (BIT_STATUS_AT(reg->bt_mem_start, mem))
+ pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;
+ else
+ pstart = (UChar* )((void* )mem_start_stk[mem]);
+
+ pend = (BIT_STATUS_AT(reg->bt_mem_end, mem)
+ ? STACK_AT(mem_end_stk[mem])->u.mem.pstr
+ : (UChar* )((void* )mem_end_stk[mem]));
+ n = pend - pstart;
+ DATA_ENSURE(n);
+ sprev = s;
+ STRING_CMP(pstart, s, n);
+ while (sprev + (len = enclen_approx(encode, sprev, end)) < s)
+ sprev += len;
+
+ MOP_OUT;
+ JUMP;
}
CASE(OP_BACKREFN_IC) MOP_IN(OP_BACKREFN_IC);
GET_MEMNUM_INC(mem, p);
{
- int len;
- UChar *pstart, *pend;
-
- /* if you want to remove following line,
- you should check in parse and compile time. */
- if (mem > num_mem) goto fail;
- if (mem_end_stk[mem] == INVALID_STACK_INDEX) goto fail;
- if (mem_start_stk[mem] == INVALID_STACK_INDEX) goto fail;
-
- if (BIT_STATUS_AT(reg->bt_mem_start, mem))
- pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;
- else
- pstart = (UChar* )((void* )mem_start_stk[mem]);
-
- pend = (BIT_STATUS_AT(reg->bt_mem_end, mem)
- ? STACK_AT(mem_end_stk[mem])->u.mem.pstr
- : (UChar* )((void* )mem_end_stk[mem]));
- n = pend - pstart;
- DATA_ENSURE(n);
- sprev = s;
- STRING_CMP_IC(case_fold_flag, pstart, &s, n, end);
- while (sprev + (len = enclen_approx(encode, sprev, end)) < s)
- sprev += len;
-
- MOP_OUT;
- JUMP;
+ int len;
+ UChar *pstart, *pend;
+
+ /* if you want to remove following line,
+ you should check in parse and compile time. */
+ if (mem > num_mem) goto fail;
+ if (mem_end_stk[mem] == INVALID_STACK_INDEX) goto fail;
+ if (mem_start_stk[mem] == INVALID_STACK_INDEX) goto fail;
+
+ if (BIT_STATUS_AT(reg->bt_mem_start, mem))
+ pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;
+ else
+ pstart = (UChar* )((void* )mem_start_stk[mem]);
+
+ pend = (BIT_STATUS_AT(reg->bt_mem_end, mem)
+ ? STACK_AT(mem_end_stk[mem])->u.mem.pstr
+ : (UChar* )((void* )mem_end_stk[mem]));
+ n = pend - pstart;
+ DATA_ENSURE(n);
+ sprev = s;
+ STRING_CMP_IC(case_fold_flag, pstart, &s, n, end);
+ while (sprev + (len = enclen_approx(encode, sprev, end)) < s)
+ sprev += len;
+
+ MOP_OUT;
+ JUMP;
}
NEXT;
CASE(OP_BACKREF_MULTI) MOP_IN(OP_BACKREF_MULTI);
{
- int len, is_fail;
- UChar *pstart, *pend, *swork;
-
- GET_LENGTH_INC(tlen, p);
- for (i = 0; i < tlen; i++) {
- GET_MEMNUM_INC(mem, p);
-
- if (mem_end_stk[mem] == INVALID_STACK_INDEX) continue;
- if (mem_start_stk[mem] == INVALID_STACK_INDEX) continue;
-
- if (BIT_STATUS_AT(reg->bt_mem_start, mem))
- pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;
- else
- pstart = (UChar* )((void* )mem_start_stk[mem]);
-
- pend = (BIT_STATUS_AT(reg->bt_mem_end, mem)
- ? STACK_AT(mem_end_stk[mem])->u.mem.pstr
- : (UChar* )((void* )mem_end_stk[mem]));
- n = pend - pstart;
- DATA_ENSURE_CONTINUE(n);
- sprev = s;
- swork = s;
- STRING_CMP_VALUE(pstart, swork, n, is_fail);
- if (is_fail) continue;
- s = swork;
- while (sprev + (len = enclen_approx(encode, sprev, end)) < s)
- sprev += len;
-
- p += (SIZE_MEMNUM * (tlen - i - 1));
- break; /* success */
- }
- if (i == tlen) goto fail;
- MOP_OUT;
- JUMP;
+ int len, is_fail;
+ UChar *pstart, *pend, *swork;
+
+ GET_LENGTH_INC(tlen, p);
+ for (i = 0; i < tlen; i++) {
+ GET_MEMNUM_INC(mem, p);
+
+ if (mem_end_stk[mem] == INVALID_STACK_INDEX) continue;
+ if (mem_start_stk[mem] == INVALID_STACK_INDEX) continue;
+
+ if (BIT_STATUS_AT(reg->bt_mem_start, mem))
+ pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;
+ else
+ pstart = (UChar* )((void* )mem_start_stk[mem]);
+
+ pend = (BIT_STATUS_AT(reg->bt_mem_end, mem)
+ ? STACK_AT(mem_end_stk[mem])->u.mem.pstr
+ : (UChar* )((void* )mem_end_stk[mem]));
+ n = pend - pstart;
+ DATA_ENSURE_CONTINUE(n);
+ sprev = s;
+ swork = s;
+ STRING_CMP_VALUE(pstart, swork, n, is_fail);
+ if (is_fail) continue;
+ s = swork;
+ while (sprev + (len = enclen_approx(encode, sprev, end)) < s)
+ sprev += len;
+
+ p += (SIZE_MEMNUM * (tlen - i - 1));
+ break; /* success */
+ }
+ if (i == tlen) goto fail;
+ MOP_OUT;
+ JUMP;
}
NEXT;
CASE(OP_BACKREF_MULTI_IC) MOP_IN(OP_BACKREF_MULTI_IC);
{
- int len, is_fail;
- UChar *pstart, *pend, *swork;
-
- GET_LENGTH_INC(tlen, p);
- for (i = 0; i < tlen; i++) {
- GET_MEMNUM_INC(mem, p);
-
- if (mem_end_stk[mem] == INVALID_STACK_INDEX) continue;
- if (mem_start_stk[mem] == INVALID_STACK_INDEX) continue;
-
- if (BIT_STATUS_AT(reg->bt_mem_start, mem))
- pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;
- else
- pstart = (UChar* )((void* )mem_start_stk[mem]);
-
- pend = (BIT_STATUS_AT(reg->bt_mem_end, mem)
- ? STACK_AT(mem_end_stk[mem])->u.mem.pstr
- : (UChar* )((void* )mem_end_stk[mem]));
- n = pend - pstart;
- DATA_ENSURE_CONTINUE(n);
- sprev = s;
- swork = s;
- STRING_CMP_VALUE_IC(case_fold_flag, pstart, &swork, n, end, is_fail);
- if (is_fail) continue;
- s = swork;
- while (sprev + (len = enclen(encode, sprev, end)) < s)
- sprev += len;
-
- p += (SIZE_MEMNUM * (tlen - i - 1));
- break; /* success */
- }
- if (i == tlen) goto fail;
- MOP_OUT;
- JUMP;
+ int len, is_fail;
+ UChar *pstart, *pend, *swork;
+
+ GET_LENGTH_INC(tlen, p);
+ for (i = 0; i < tlen; i++) {
+ GET_MEMNUM_INC(mem, p);
+
+ if (mem_end_stk[mem] == INVALID_STACK_INDEX) continue;
+ if (mem_start_stk[mem] == INVALID_STACK_INDEX) continue;
+
+ if (BIT_STATUS_AT(reg->bt_mem_start, mem))
+ pstart = STACK_AT(mem_start_stk[mem])->u.mem.pstr;
+ else
+ pstart = (UChar* )((void* )mem_start_stk[mem]);
+
+ pend = (BIT_STATUS_AT(reg->bt_mem_end, mem)
+ ? STACK_AT(mem_end_stk[mem])->u.mem.pstr
+ : (UChar* )((void* )mem_end_stk[mem]));
+ n = pend - pstart;
+ DATA_ENSURE_CONTINUE(n);
+ sprev = s;
+ swork = s;
+ STRING_CMP_VALUE_IC(case_fold_flag, pstart, &swork, n, end, is_fail);
+ if (is_fail) continue;
+ s = swork;
+ while (sprev + (len = enclen(encode, sprev, end)) < s)
+ sprev += len;
+
+ p += (SIZE_MEMNUM * (tlen - i - 1));
+ break; /* success */
+ }
+ if (i == tlen) goto fail;
+ MOP_OUT;
+ JUMP;
}
#ifdef USE_BACKREF_WITH_LEVEL
CASE(OP_BACKREF_WITH_LEVEL)
{
- int len;
- OnigOptionType ic;
- LengthType level;
+ int len;
+ OnigOptionType ic;
+ LengthType level;
- GET_OPTION_INC(ic, p);
- GET_LENGTH_INC(level, p);
- GET_LENGTH_INC(tlen, p);
+ GET_OPTION_INC(ic, p);
+ GET_LENGTH_INC(level, p);
+ GET_LENGTH_INC(tlen, p);
- sprev = s;
- if (backref_match_at_nested_level(reg, stk, stk_base, ic,
- case_fold_flag, (int )level, (int )tlen, p, &s, end)) {
- while (sprev + (len = enclen(encode, sprev, end)) < s)
- sprev += len;
+ sprev = s;
+ if (backref_match_at_nested_level(reg, stk, stk_base, ic,
+ case_fold_flag, (int )level, (int )tlen, p, &s, end)) {
+ while (sprev + (len = enclen(encode, sprev, end)) < s)
+ sprev += len;
- p += (SIZE_MEMNUM * tlen);
- }
- else
- goto fail;
+ p += (SIZE_MEMNUM * tlen);
+ }
+ else
+ goto fail;
- MOP_OUT;
- JUMP;
+ MOP_OUT;
+ JUMP;
}
#endif
@@ -3670,33 +3687,33 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_NULL_CHECK_END) MOP_IN(OP_NULL_CHECK_END);
{
- int isnull;
+ int isnull;
- GET_MEMNUM_INC(mem, p); /* mem: null check id */
- STACK_NULL_CHECK(isnull, mem, s);
- if (isnull) {
+ GET_MEMNUM_INC(mem, p); /* mem: null check id */
+ STACK_NULL_CHECK(isnull, mem, s);
+ if (isnull) {
#ifdef ONIG_DEBUG_MATCH
- fprintf(stderr, "NULL_CHECK_END: skip id:%d, s:%"PRIuPTR" (%p)\n",
- (int )mem, (uintptr_t )s, s);
+ fprintf(stderr, "NULL_CHECK_END: skip id:%d, s:%"PRIuPTR" (%p)\n",
+ (int )mem, (uintptr_t )s, s);
#endif
- null_check_found:
- /* empty loop founded, skip next instruction */
- switch (*p++) {
- case OP_JUMP:
- case OP_PUSH:
- p += SIZE_RELADDR;
- break;
- case OP_REPEAT_INC:
- case OP_REPEAT_INC_NG:
- case OP_REPEAT_INC_SG:
- case OP_REPEAT_INC_NG_SG:
- p += SIZE_MEMNUM;
- break;
- default:
- goto unexpected_bytecode_error;
- break;
- }
- }
+ null_check_found:
+ /* empty loop founded, skip next instruction */
+ switch (*p++) {
+ case OP_JUMP:
+ case OP_PUSH:
+ p += SIZE_RELADDR;
+ break;
+ case OP_REPEAT_INC:
+ case OP_REPEAT_INC_NG:
+ case OP_REPEAT_INC_SG:
+ case OP_REPEAT_INC_NG_SG:
+ p += SIZE_MEMNUM;
+ break;
+ default:
+ goto unexpected_bytecode_error;
+ break;
+ }
+ }
}
MOP_OUT;
JUMP;
@@ -3704,18 +3721,18 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
#ifdef USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT
CASE(OP_NULL_CHECK_END_MEMST) MOP_IN(OP_NULL_CHECK_END_MEMST);
{
- int isnull;
+ int isnull;
- GET_MEMNUM_INC(mem, p); /* mem: null check id */
- STACK_NULL_CHECK_MEMST(isnull, mem, s, reg);
- if (isnull) {
+ GET_MEMNUM_INC(mem, p); /* mem: null check id */
+ STACK_NULL_CHECK_MEMST(isnull, mem, s, reg);
+ if (isnull) {
# ifdef ONIG_DEBUG_MATCH
- fprintf(stderr, "NULL_CHECK_END_MEMST: skip id:%d, s:%"PRIuPTR" (%p)\n",
- (int )mem, (uintptr_t )s, s);
+ fprintf(stderr, "NULL_CHECK_END_MEMST: skip id:%d, s:%"PRIuPTR" (%p)\n",
+ (int )mem, (uintptr_t )s, s);
# endif
- if (isnull == -1) goto fail;
- goto null_check_found;
- }
+ if (isnull == -1) goto fail;
+ goto null_check_found;
+ }
}
MOP_OUT;
JUMP;
@@ -3725,25 +3742,25 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_NULL_CHECK_END_MEMST_PUSH)
MOP_IN(OP_NULL_CHECK_END_MEMST_PUSH);
{
- int isnull;
+ int isnull;
- GET_MEMNUM_INC(mem, p); /* mem: null check id */
+ GET_MEMNUM_INC(mem, p); /* mem: null check id */
# ifdef USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT
- STACK_NULL_CHECK_MEMST_REC(isnull, mem, s, reg);
+ STACK_NULL_CHECK_MEMST_REC(isnull, mem, s, reg);
# else
- STACK_NULL_CHECK_REC(isnull, mem, s);
+ STACK_NULL_CHECK_REC(isnull, mem, s);
# endif
- if (isnull) {
+ if (isnull) {
# ifdef ONIG_DEBUG_MATCH
- fprintf(stderr, "NULL_CHECK_END_MEMST_PUSH: skip id:%d, s:%"PRIuPTR" (%p)\n",
- (int )mem, (uintptr_t )s, s);
+ fprintf(stderr, "NULL_CHECK_END_MEMST_PUSH: skip id:%d, s:%"PRIuPTR" (%p)\n",
+ (int )mem, (uintptr_t )s, s);
# endif
- if (isnull == -1) goto fail;
- goto null_check_found;
- }
- else {
- STACK_PUSH_NULL_CHECK_END(mem);
- }
+ if (isnull == -1) goto fail;
+ goto null_check_found;
+ }
+ else {
+ STACK_PUSH_NULL_CHECK_END(mem);
+ }
}
MOP_OUT;
JUMP;
@@ -3779,10 +3796,10 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
GET_RELADDR_INC(addr, p);
STATE_CHECK_VAL(scv, mem);
if (scv) {
- p += addr;
+ p += addr;
}
else {
- STACK_PUSH_ALT_WITH_STATE_CHECK(p + addr, s, sprev, mem, pkeep);
+ STACK_PUSH_ALT_WITH_STATE_CHECK(p + addr, s, sprev, mem, pkeep);
}
MOP_OUT;
JUMP;
@@ -3811,11 +3828,11 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_PUSH_OR_JUMP_EXACT1) MOP_IN(OP_PUSH_OR_JUMP_EXACT1);
GET_RELADDR_INC(addr, p);
if (*p == *s && DATA_ENSURE_CHECK1) {
- p++;
- CHECK_MATCH_CACHE;
- STACK_PUSH_ALT(p + addr, s, sprev, pkeep);
- MOP_OUT;
- JUMP;
+ p++;
+ CHECK_MATCH_CACHE;
+ STACK_PUSH_ALT(p + addr, s, sprev, pkeep);
+ MOP_OUT;
+ JUMP;
}
p += (addr + 1);
MOP_OUT;
@@ -3826,10 +3843,10 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
GET_RELADDR_INC(addr, p);
CHECK_MATCH_CACHE;
if (*p == *s) {
- p++;
- STACK_PUSH_ALT(p + addr, s, sprev, pkeep);
- MOP_OUT;
- JUMP;
+ p++;
+ STACK_PUSH_ALT(p + addr, s, sprev, pkeep);
+ MOP_OUT;
+ JUMP;
}
p++;
INC_NUM_FAILS;
@@ -3838,35 +3855,35 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_REPEAT) MOP_IN(OP_REPEAT);
{
- GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */
- GET_RELADDR_INC(addr, p);
+ GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */
+ GET_RELADDR_INC(addr, p);
- STACK_ENSURE(1);
- repeat_stk[mem] = GET_STACK_INDEX(stk);
- STACK_PUSH_REPEAT(mem, p);
+ STACK_ENSURE(1);
+ repeat_stk[mem] = GET_STACK_INDEX(stk);
+ STACK_PUSH_REPEAT(mem, p);
- if (reg->repeat_range[mem].lower == 0) {
- CHECK_MATCH_CACHE;
- STACK_PUSH_ALT(p + addr, s, sprev, pkeep);
- }
+ if (reg->repeat_range[mem].lower == 0) {
+ CHECK_MATCH_CACHE;
+ STACK_PUSH_ALT(p + addr, s, sprev, pkeep);
+ }
}
MOP_OUT;
JUMP;
CASE(OP_REPEAT_NG) MOP_IN(OP_REPEAT_NG);
{
- GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */
- GET_RELADDR_INC(addr, p);
+ GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */
+ GET_RELADDR_INC(addr, p);
- STACK_ENSURE(1);
- repeat_stk[mem] = GET_STACK_INDEX(stk);
- STACK_PUSH_REPEAT(mem, p);
+ STACK_ENSURE(1);
+ repeat_stk[mem] = GET_STACK_INDEX(stk);
+ STACK_PUSH_REPEAT(mem, p);
- if (reg->repeat_range[mem].lower == 0) {
- CHECK_MATCH_CACHE;
- STACK_PUSH_ALT(p, s, sprev, pkeep);
- p += addr;
- }
+ if (reg->repeat_range[mem].lower == 0) {
+ CHECK_MATCH_CACHE;
+ STACK_PUSH_ALT(p, s, sprev, pkeep);
+ p += addr;
+ }
}
MOP_OUT;
JUMP;
@@ -3879,23 +3896,23 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
repeat_inc:
stkp->u.repeat.count++;
if (stkp->u.repeat.count >= reg->repeat_range[mem].upper) {
- /* end of repeat. Nothing to do. */
+ /* end of repeat. Nothing to do. */
}
else if (stkp->u.repeat.count >= reg->repeat_range[mem].lower) {
#ifdef USE_MATCH_CACHE
- if (*pbegin == OP_REPEAT_INC) {
+ if (*pbegin == OP_REPEAT_INC) {
#undef MATCH_CACHE_HIT
#define MATCH_CACHE_HIT stkp->u.repeat.count--;
- CHECK_MATCH_CACHE;
+ CHECK_MATCH_CACHE;
#undef MATCH_CACHE_HIT
#define MATCH_CACHE_HIT ((void) 0)
- }
+ }
#endif
- STACK_PUSH_ALT(p, s, sprev, pkeep);
- p = STACK_AT(si)->u.repeat.pcode; /* Don't use stkp after PUSH. */
+ STACK_PUSH_ALT(p, s, sprev, pkeep);
+ p = STACK_AT(si)->u.repeat.pcode; /* Don't use stkp after PUSH. */
}
else {
- p = stkp->u.repeat.pcode;
+ p = stkp->u.repeat.pcode;
}
STACK_PUSH_REPEAT_INC(si);
MOP_OUT;
@@ -3907,7 +3924,6 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
STACK_GET_REPEAT(mem, stkp);
si = GET_STACK_INDEX(stkp);
goto repeat_inc;
- NEXT;
CASE(OP_REPEAT_INC_NG) MOP_IN(OP_REPEAT_INC_NG);
GET_MEMNUM_INC(mem, p); /* mem: OP_REPEAT ID */
@@ -3917,22 +3933,22 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
repeat_inc_ng:
stkp->u.repeat.count++;
if (stkp->u.repeat.count < reg->repeat_range[mem].upper) {
- if (stkp->u.repeat.count >= reg->repeat_range[mem].lower) {
- UChar* pcode = stkp->u.repeat.pcode;
-
- STACK_PUSH_REPEAT_INC(si);
- if (*pbegin == OP_REPEAT_INC_NG) {
- CHECK_MATCH_CACHE;
- }
- STACK_PUSH_ALT(pcode, s, sprev, pkeep);
- }
- else {
- p = stkp->u.repeat.pcode;
- STACK_PUSH_REPEAT_INC(si);
- }
+ if (stkp->u.repeat.count >= reg->repeat_range[mem].lower) {
+ UChar* pcode = stkp->u.repeat.pcode;
+
+ STACK_PUSH_REPEAT_INC(si);
+ if (*pbegin == OP_REPEAT_INC_NG) {
+ CHECK_MATCH_CACHE;
+ }
+ STACK_PUSH_ALT(pcode, s, sprev, pkeep);
+ }
+ else {
+ p = stkp->u.repeat.pcode;
+ STACK_PUSH_REPEAT_INC(si);
+ }
}
else if (stkp->u.repeat.count == reg->repeat_range[mem].upper) {
- STACK_PUSH_REPEAT_INC(si);
+ STACK_PUSH_REPEAT_INC(si);
}
MOP_OUT;
CHECK_INTERRUPT_IN_MATCH_AT;
@@ -3943,7 +3959,6 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
STACK_GET_REPEAT(mem, stkp);
si = GET_STACK_INDEX(stkp);
goto repeat_inc_ng;
- NEXT;
CASE(OP_PUSH_POS) MOP_IN(OP_PUSH_POS);
STACK_PUSH_POS(s, sprev, pkeep);
@@ -3952,9 +3967,9 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_POP_POS) MOP_IN(OP_POP_POS);
{
- STACK_POS_END(stkp);
- s = stkp->u.state.pstr;
- sprev = stkp->u.state.pstr_prev;
+ STACK_POS_END(stkp);
+ s = stkp->u.state.pstr;
+ sprev = stkp->u.state.pstr_prev;
}
MOP_OUT;
JUMP;
@@ -3968,7 +3983,6 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_FAIL_POS) MOP_IN(OP_FAIL_POS);
STACK_POP_TIL_POS_NOT;
goto fail;
- NEXT;
CASE(OP_PUSH_STOP_BT) MOP_IN(OP_PUSH_STOP_BT);
STACK_PUSH_STOP_BT;
@@ -3993,15 +4007,15 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
GET_LENGTH_INC(tlen, p);
q = (UChar* )ONIGENC_STEP_BACK(encode, str, s, end, (int )tlen);
if (IS_NULL(q)) {
- /* too short case -> success. ex. /(?<!XXX)a/.match("a")
- If you want to change to fail, replace following line. */
- p += addr;
- /* goto fail; */
+ /* too short case -> success. ex. /(?<!XXX)a/.match("a")
+ If you want to change to fail, replace following line. */
+ p += addr;
+ /* goto fail; */
}
else {
- STACK_PUSH_LOOK_BEHIND_NOT(p + addr, s, sprev, pkeep);
- s = q;
- sprev = (UChar* )onigenc_get_prev_char_head(encode, str, s, end);
+ STACK_PUSH_LOOK_BEHIND_NOT(p + addr, s, sprev, pkeep);
+ s = q;
+ sprev = (UChar* )onigenc_get_prev_char_head(encode, str, s, end);
}
MOP_OUT;
JUMP;
@@ -4009,7 +4023,6 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_FAIL_LOOK_BEHIND_NOT) MOP_IN(OP_FAIL_LOOK_BEHIND_NOT);
STACK_POP_TIL_LOOK_BEHIND_NOT;
goto fail;
- NEXT;
CASE(OP_PUSH_ABSENT_POS) MOP_IN(OP_PUSH_ABSENT_POS);
/* Save the absent-start-pos and the original end-pos. */
@@ -4019,44 +4032,44 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
CASE(OP_ABSENT) MOP_IN(OP_ABSENT);
{
- const UChar* aend = ABSENT_END_POS;
- UChar* absent;
- UChar* selfp = p - 1;
+ const UChar* aend = ABSENT_END_POS;
+ UChar* absent;
+ UChar* selfp = p - 1;
- STACK_POP_ABSENT_POS(absent, ABSENT_END_POS); /* Restore end-pos. */
- GET_RELADDR_INC(addr, p);
+ STACK_POP_ABSENT_POS(absent, ABSENT_END_POS); /* Restore end-pos. */
+ GET_RELADDR_INC(addr, p);
#ifdef ONIG_DEBUG_MATCH
- fprintf(stderr, "ABSENT: s:%p, end:%p, absent:%p, aend:%p\n", s, end, absent, aend);
+ fprintf(stderr, "ABSENT: s:%p, end:%p, absent:%p, aend:%p\n", s, end, absent, aend);
#endif
- if ((absent > aend) && (s > absent)) {
- /* An empty match occurred in (?~...) at the start point.
- * Never match. */
- STACK_POP;
- goto fail;
- }
- else if ((s >= aend) && (s > absent)) {
- if (s > aend) {
- /* Only one (or less) character matched in the last iteration.
- * This is not a possible point. */
- goto fail;
- }
- /* All possible points were found. Try matching after (?~...). */
- DATA_ENSURE(0);
- p += addr;
- }
- else if (s == end) {
- /* At the end of the string, just match with it */
- DATA_ENSURE(0);
- p += addr;
- }
- else {
- STACK_PUSH_ALT(p + addr, s, sprev, pkeep); /* Push possible point. */
- n = enclen(encode, s, end);
- STACK_PUSH_ABSENT_POS(absent, ABSENT_END_POS); /* Save the original pos. */
- STACK_PUSH_ALT(selfp, s + n, s, pkeep); /* Next iteration. */
- STACK_PUSH_ABSENT;
- ABSENT_END_POS = aend;
- }
+ if ((absent > aend) && (s > absent)) {
+ /* An empty match occurred in (?~...) at the start point.
+ * Never match. */
+ STACK_POP;
+ goto fail;
+ }
+ else if ((s >= aend) && (s > absent)) {
+ if (s > aend) {
+ /* Only one (or less) character matched in the last iteration.
+ * This is not a possible point. */
+ goto fail;
+ }
+ /* All possible points were found. Try matching after (?~...). */
+ DATA_ENSURE(0);
+ p += addr;
+ }
+ else if (s == end) {
+ /* At the end of the string, just match with it */
+ DATA_ENSURE(0);
+ p += addr;
+ }
+ else {
+ STACK_PUSH_ALT(p + addr, s, sprev, pkeep); /* Push possible point. */
+ n = enclen(encode, s, end);
+ STACK_PUSH_ABSENT_POS(absent, ABSENT_END_POS); /* Save the original pos. */
+ STACK_PUSH_ALT(selfp, s + n, s, pkeep); /* Next iteration. */
+ STACK_PUSH_ABSENT;
+ ABSENT_END_POS = aend;
+ }
}
MOP_OUT;
JUMP;
@@ -4065,13 +4078,12 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
/* The pattern inside (?~...) was matched.
* Set the end-pos temporary and go to next iteration. */
if (sprev < ABSENT_END_POS)
- ABSENT_END_POS = sprev;
+ ABSENT_END_POS = sprev;
#ifdef ONIG_DEBUG_MATCH
fprintf(stderr, "ABSENT_END: end:%p\n", ABSENT_END_POS);
#endif
STACK_POP_TIL_ABSENT;
goto fail;
- NEXT;
#ifdef USE_SUBEXP_CALL
CASE(OP_CALL) MOP_IN(OP_CALL);
@@ -4092,22 +4104,21 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
GET_MEMNUM_INC(mem, p);
GET_RELADDR_INC(addr, p);
if ((mem > num_mem) ||
- (mem_end_stk[mem] == INVALID_STACK_INDEX) ||
- (mem_start_stk[mem] == INVALID_STACK_INDEX)) {
- p += addr;
+ (mem_end_stk[mem] == INVALID_STACK_INDEX) ||
+ (mem_start_stk[mem] == INVALID_STACK_INDEX)) {
+ p += addr;
}
MOP_OUT;
JUMP;
CASE(OP_FINISH)
goto finish;
- NEXT;
CASE(OP_FAIL)
if (0) {
- /* fall */
+ /* fall */
fail:
- MOP_OUT;
+ MOP_OUT;
}
MOP_IN(OP_FAIL);
STACK_POP;
@@ -4118,71 +4129,71 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
#ifdef USE_MATCH_CACHE
if (
- msa->match_cache_status != MATCH_CACHE_STATUS_DISABLED &&
- ++msa->num_fails >= (long)(end - str) * msa->num_cache_opcodes
+ msa->match_cache_status != MATCH_CACHE_STATUS_DISABLED &&
+ ++msa->num_fails >= (long)(end - str) * msa->num_cache_opcodes
) {
- if (msa->match_cache_status == MATCH_CACHE_STATUS_UNINIT) {
- msa->match_cache_status = MATCH_CACHE_STATUS_INIT;
- OnigPosition r = count_num_cache_opcodes(reg, &msa->num_cache_opcodes);
- if (r < 0) goto bytecode_error;
- }
- if (msa->num_cache_opcodes == NUM_CACHE_OPCODES_IMPOSSIBLE || msa->num_cache_opcodes == 0) {
- msa->match_cache_status = MATCH_CACHE_STATUS_DISABLED;
- goto fail_match_cache;
- }
- if (msa->num_fails < (long)(end - str) * msa->num_cache_opcodes) {
- goto fail_match_cache;
- }
- if (msa->cache_opcodes == NULL) {
- msa->match_cache_status = MATCH_CACHE_STATUS_ENABLED;
- OnigCacheOpcode* cache_opcodes = (OnigCacheOpcode*)xmalloc(msa->num_cache_opcodes * sizeof(OnigCacheOpcode));
- if (cache_opcodes == NULL) {
- return ONIGERR_MEMORY;
- }
- OnigPosition r = init_cache_opcodes(reg, cache_opcodes, &msa->num_cache_points);
- if (r < 0) {
- if (r == ONIGERR_UNEXPECTED_BYTECODE) goto unexpected_bytecode_error;
- else goto bytecode_error;
- }
- msa->cache_opcodes = cache_opcodes;
+ if (msa->match_cache_status == MATCH_CACHE_STATUS_UNINIT) {
+ msa->match_cache_status = MATCH_CACHE_STATUS_INIT;
+ OnigPosition r = count_num_cache_opcodes(reg, &msa->num_cache_opcodes);
+ if (r < 0) goto bytecode_error;
+ }
+ if (msa->num_cache_opcodes == NUM_CACHE_OPCODES_IMPOSSIBLE || msa->num_cache_opcodes == 0) {
+ msa->match_cache_status = MATCH_CACHE_STATUS_DISABLED;
+ goto fail_match_cache;
+ }
+ if (msa->num_fails < (long)(end - str) * msa->num_cache_opcodes) {
+ goto fail_match_cache;
+ }
+ if (msa->cache_opcodes == NULL) {
+ msa->match_cache_status = MATCH_CACHE_STATUS_ENABLED;
+ OnigCacheOpcode* cache_opcodes = (OnigCacheOpcode*)xmalloc(msa->num_cache_opcodes * sizeof(OnigCacheOpcode));
+ if (cache_opcodes == NULL) {
+ return ONIGERR_MEMORY;
+ }
+ OnigPosition r = init_cache_opcodes(reg, cache_opcodes, &msa->num_cache_points);
+ if (r < 0) {
+ if (r == ONIGERR_UNEXPECTED_BYTECODE) goto unexpected_bytecode_error;
+ else goto bytecode_error;
+ }
+ msa->cache_opcodes = cache_opcodes;
#ifdef ONIG_DEBUG_MATCH_CACHE
- fprintf(stderr, "MATCH CACHE: #cache opcodes = %ld\n", msa->num_cache_opcodes);
- fprintf(stderr, "MATCH CACHE: #cache points = %ld\n", msa->num_cache_points);
- fprintf(stderr, "MATCH CACHE: cache opcodes (%p):\n", msa->cache_opcodes);
- for (int i = 0; i < msa->num_cache_opcodes; i++) {
- fprintf(stderr, "MATCH CACHE: [%p] cache_point=%ld outer_repeat_mem=%d num_cache_opcodes_at_outer_repeat=%ld num_cache_opcodes_in_outer_repeat=%ld lookaround_nesting=%d match_addr=%p\n", msa->cache_opcodes[i].addr, msa->cache_opcodes[i].cache_point, msa->cache_opcodes[i].outer_repeat_mem, msa->cache_opcodes[i].num_cache_points_at_outer_repeat, msa->cache_opcodes[i].num_cache_points_in_outer_repeat, msa->cache_opcodes[i].lookaround_nesting, msa->cache_opcodes[i].match_addr);
- }
+ fprintf(stderr, "MATCH CACHE: #cache opcodes = %ld\n", msa->num_cache_opcodes);
+ fprintf(stderr, "MATCH CACHE: #cache points = %ld\n", msa->num_cache_points);
+ fprintf(stderr, "MATCH CACHE: cache opcodes (%p):\n", msa->cache_opcodes);
+ for (int i = 0; i < msa->num_cache_opcodes; i++) {
+ fprintf(stderr, "MATCH CACHE: [%p] cache_point=%ld outer_repeat_mem=%d num_cache_opcodes_at_outer_repeat=%ld num_cache_opcodes_in_outer_repeat=%ld lookaround_nesting=%d match_addr=%p\n", msa->cache_opcodes[i].addr, msa->cache_opcodes[i].cache_point, msa->cache_opcodes[i].outer_repeat_mem, msa->cache_opcodes[i].num_cache_points_at_outer_repeat, msa->cache_opcodes[i].num_cache_points_in_outer_repeat, msa->cache_opcodes[i].lookaround_nesting, msa->cache_opcodes[i].match_addr);
+ }
#endif
- }
- if (msa->match_cache_buf == NULL) {
- size_t length = (end - str) + 1;
- size_t num_match_cache_points = (size_t)msa->num_cache_points * length;
+ }
+ if (msa->match_cache_buf == NULL) {
+ size_t length = (end - str) + 1;
+ size_t num_match_cache_points = (size_t)msa->num_cache_points * length;
#ifdef ONIG_DEBUG_MATCH_CACHE
- fprintf(stderr, "MATCH CACHE: #match cache points = %ld (length = %zu)\n", num_match_cache_points, length);
+ fprintf(stderr, "MATCH CACHE: #match cache points = %zu (length = %zu)\n", num_match_cache_points, length);
#endif
- /* Overflow check */
- if (num_match_cache_points / length != (size_t)msa->num_cache_points) {
- return ONIGERR_MEMORY;
- }
- if (num_match_cache_points >= LONG_MAX_LIMIT) {
- return ONIGERR_MEMORY;
- }
- size_t match_cache_buf_length = (num_match_cache_points >> 3) + (num_match_cache_points & 7 ? 1 : 0) + 1;
- uint8_t* match_cache_buf = (uint8_t*)xmalloc(match_cache_buf_length * sizeof(uint8_t));
- if (match_cache_buf == NULL) {
- return ONIGERR_MEMORY;
- }
- xmemset(match_cache_buf, 0, match_cache_buf_length * sizeof(uint8_t));
- msa->match_cache_buf = match_cache_buf;
- }
+ /* Overflow check */
+ if (num_match_cache_points / length != (size_t)msa->num_cache_points) {
+ return ONIGERR_MEMORY;
+ }
+ if (num_match_cache_points >= LONG_MAX_LIMIT) {
+ return ONIGERR_MEMORY;
+ }
+ size_t match_cache_buf_length = (num_match_cache_points >> 3) + (num_match_cache_points & 7 ? 1 : 0) + 1;
+ uint8_t* match_cache_buf = (uint8_t*)xmalloc(match_cache_buf_length * sizeof(uint8_t));
+ if (match_cache_buf == NULL) {
+ return ONIGERR_MEMORY;
+ }
+ xmemset(match_cache_buf, 0, match_cache_buf_length * sizeof(uint8_t));
+ msa->match_cache_buf = match_cache_buf;
+ }
}
fail_match_cache:
#endif
#ifdef USE_COMBINATION_EXPLOSION_CHECK
if (stk->u.state.state_check != 0) {
- stk->type = STK_STATE_CHECK_MARK;
- stk++;
+ stk->type = STK_STATE_CHECK_MARK;
+ stk++;
}
#endif
@@ -4217,16 +4228,15 @@ match_at(regex_t* reg, const UChar* str, const UChar* end,
return ONIGERR_UNEXPECTED_BYTECODE;
timeout:
+ STACK_SAVE;
xfree(xmalloc_base);
- if (stk_base != stk_alloc || IS_NOT_NULL(msa->stack_p))
- xfree(stk_base);
- HANDLE_REG_TIMEOUT_IN_MATCH_AT;
+ return ONIGERR_TIMEOUT;
}
static UChar*
slow_search(OnigEncoding enc, UChar* target, UChar* target_end,
- const UChar* text, const UChar* text_end, UChar* text_range)
+ const UChar* text, const UChar* text_end, UChar* text_range)
{
UChar *t, *p, *s, *end;
@@ -4242,10 +4252,10 @@ slow_search(OnigEncoding enc, UChar* target, UChar* target_end,
while (s < end) {
if (*s == *target) {
- p = s + 1;
- t = target + 1;
- if (target_end == t || memcmp(t, p, target_end - t) == 0)
- return s;
+ p = s + 1;
+ t = target + 1;
+ if (target_end == t || memcmp(t, p, target_end - t) == 0)
+ return s;
}
s += n;
}
@@ -4256,7 +4266,7 @@ slow_search(OnigEncoding enc, UChar* target, UChar* target_end,
p = s + 1;
t = target + 1;
if (target_end == t || memcmp(t, p, target_end - t) == 0)
- return s;
+ return s;
}
s += enclen(enc, s, text_end);
}
@@ -4266,8 +4276,8 @@ slow_search(OnigEncoding enc, UChar* target, UChar* target_end,
static int
str_lower_case_match(OnigEncoding enc, int case_fold_flag,
- const UChar* t, const UChar* tend,
- const UChar* p, const UChar* end)
+ const UChar* t, const UChar* tend,
+ const UChar* p, const UChar* end)
{
int lowlen;
UChar *q, lowbuf[ONIGENC_MBC_CASE_FOLD_MAXLEN];
@@ -4286,8 +4296,8 @@ str_lower_case_match(OnigEncoding enc, int case_fold_flag,
static UChar*
slow_search_ic(OnigEncoding enc, int case_fold_flag,
- UChar* target, UChar* target_end,
- const UChar* text, const UChar* text_end, UChar* text_range)
+ UChar* target, UChar* target_end,
+ const UChar* text, const UChar* text_end, UChar* text_range)
{
UChar *s, *end;
@@ -4300,7 +4310,7 @@ slow_search_ic(OnigEncoding enc, int case_fold_flag,
while (s < end) {
if (str_lower_case_match(enc, case_fold_flag, target, target_end,
- s, text_end))
+ s, text_end))
return s;
s += enclen(enc, s, text_end);
@@ -4311,8 +4321,8 @@ slow_search_ic(OnigEncoding enc, int case_fold_flag,
static UChar*
slow_search_backward(OnigEncoding enc, UChar* target, UChar* target_end,
- const UChar* text, const UChar* adjust_text,
- const UChar* text_end, const UChar* text_start)
+ const UChar* text, const UChar* adjust_text,
+ const UChar* text_end, const UChar* text_start)
{
UChar *t, *p, *s;
@@ -4328,12 +4338,12 @@ slow_search_backward(OnigEncoding enc, UChar* target, UChar* target_end,
p = s + 1;
t = target + 1;
while (t < target_end) {
- if (*t != *p++)
- break;
- t++;
+ if (*t != *p++)
+ break;
+ t++;
}
if (t == target_end)
- return s;
+ return s;
}
s = (UChar* )onigenc_get_prev_char_head(enc, adjust_text, s, text_end);
}
@@ -4343,9 +4353,9 @@ slow_search_backward(OnigEncoding enc, UChar* target, UChar* target_end,
static UChar*
slow_search_backward_ic(OnigEncoding enc, int case_fold_flag,
- UChar* target, UChar* target_end,
- const UChar* text, const UChar* adjust_text,
- const UChar* text_end, const UChar* text_start)
+ UChar* target, UChar* target_end,
+ const UChar* text, const UChar* adjust_text,
+ const UChar* text_end, const UChar* text_start)
{
UChar *s;
@@ -4358,7 +4368,7 @@ slow_search_backward_ic(OnigEncoding enc, int case_fold_flag,
while (s >= text) {
if (str_lower_case_match(enc, case_fold_flag,
- target, target_end, s, text_end))
+ target, target_end, s, text_end))
return s;
s = (UChar* )onigenc_get_prev_char_head(enc, adjust_text, s, text_end);
@@ -4367,224 +4377,11 @@ slow_search_backward_ic(OnigEncoding enc, int case_fold_flag,
return (UChar* )NULL;
}
-#ifndef USE_SUNDAY_QUICK_SEARCH
-/* Boyer-Moore-Horspool search applied to a multibyte string */
-static UChar*
-bm_search_notrev(regex_t* reg, const UChar* target, const UChar* target_end,
- const UChar* text, const UChar* text_end,
- const UChar* text_range)
-{
- const UChar *s, *se, *t, *p, *end;
- const UChar *tail;
- ptrdiff_t skip, tlen1;
-
-# ifdef ONIG_DEBUG_SEARCH
- fprintf(stderr, "bm_search_notrev: text: %"PRIuPTR" (%p), text_end: %"PRIuPTR" (%p), text_range: %"PRIuPTR" (%p)\n",
- (uintptr_t )text, text, (uintptr_t )text_end, text_end, (uintptr_t )text_range, text_range);
-# endif
-
- tail = target_end - 1;
- tlen1 = tail - target;
- end = text_range;
- if (end + tlen1 > text_end)
- end = text_end - tlen1;
-
- s = text;
-
- if (IS_NULL(reg->int_map)) {
- while (s < end) {
- p = se = s + tlen1;
- t = tail;
- while (*p == *t) {
- if (t == target) return (UChar* )s;
- p--; t--;
- }
- skip = reg->map[*se];
- t = s;
- do {
- s += enclen(reg->enc, s, end);
- } while ((s - t) < skip && s < end);
- }
- }
- else {
-# if OPT_EXACT_MAXLEN >= ONIG_CHAR_TABLE_SIZE
- while (s < end) {
- p = se = s + tlen1;
- t = tail;
- while (*p == *t) {
- if (t == target) return (UChar* )s;
- p--; t--;
- }
- skip = reg->int_map[*se];
- t = s;
- do {
- s += enclen(reg->enc, s, end);
- } while ((s - t) < skip && s < end);
- }
-# endif
- }
-
- return (UChar* )NULL;
-}
-
-/* Boyer-Moore-Horspool search */
-static UChar*
-bm_search(regex_t* reg, const UChar* target, const UChar* target_end,
- const UChar* text, const UChar* text_end, const UChar* text_range)
-{
- const UChar *s, *t, *p, *end;
- const UChar *tail;
-
-# ifdef ONIG_DEBUG_SEARCH
- fprintf(stderr, "bm_search: text: %"PRIuPTR" (%p), text_end: %"PRIuPTR" (%p), text_range: %"PRIuPTR" (%p)\n",
- (uintptr_t )text, text, (uintptr_t )text_end, text_end, (uintptr_t )text_range, text_range);
-# endif
-
- end = text_range + (target_end - target) - 1;
- if (end > text_end)
- end = text_end;
-
- tail = target_end - 1;
- s = text + (target_end - target) - 1;
- if (IS_NULL(reg->int_map)) {
- while (s < end) {
- p = s;
- t = tail;
-# ifdef ONIG_DEBUG_SEARCH
- fprintf(stderr, "bm_search_loop: pos: %"PRIdPTR" %s\n",
- (intptr_t )(s - text), s);
-# endif
- while (*p == *t) {
- if (t == target) return (UChar* )p;
- p--; t--;
- }
- s += reg->map[*s];
- }
- }
- else { /* see int_map[] */
-# if OPT_EXACT_MAXLEN >= ONIG_CHAR_TABLE_SIZE
- while (s < end) {
- p = s;
- t = tail;
- while (*p == *t) {
- if (t == target) return (UChar* )p;
- p--; t--;
- }
- s += reg->int_map[*s];
- }
-# endif
- }
- return (UChar* )NULL;
-}
-
-/* Boyer-Moore-Horspool search applied to a multibyte string (ignore case) */
-static UChar*
-bm_search_notrev_ic(regex_t* reg, const UChar* target, const UChar* target_end,
- const UChar* text, const UChar* text_end,
- const UChar* text_range)
-{
- const UChar *s, *se, *t, *end;
- const UChar *tail;
- ptrdiff_t skip, tlen1;
- OnigEncoding enc = reg->enc;
- int case_fold_flag = reg->case_fold_flag;
-
-# ifdef ONIG_DEBUG_SEARCH
- fprintf(stderr, "bm_search_notrev_ic: text: %d (%p), text_end: %d (%p), text_range: %d (%p)\n",
- (int )text, text, (int )text_end, text_end, (int )text_range, text_range);
-# endif
-
- tail = target_end - 1;
- tlen1 = tail - target;
- end = text_range;
- if (end + tlen1 > text_end)
- end = text_end - tlen1;
-
- s = text;
-
- if (IS_NULL(reg->int_map)) {
- while (s < end) {
- se = s + tlen1;
- if (str_lower_case_match(enc, case_fold_flag, target, target_end,
- s, se + 1))
- return (UChar* )s;
- skip = reg->map[*se];
- t = s;
- do {
- s += enclen(reg->enc, s, end);
- } while ((s - t) < skip && s < end);
- }
- }
- else {
-# if OPT_EXACT_MAXLEN >= ONIG_CHAR_TABLE_SIZE
- while (s < end) {
- se = s + tlen1;
- if (str_lower_case_match(enc, case_fold_flag, target, target_end,
- s, se + 1))
- return (UChar* )s;
- skip = reg->int_map[*se];
- t = s;
- do {
- s += enclen(reg->enc, s, end);
- } while ((s - t) < skip && s < end);
- }
-# endif
- }
-
- return (UChar* )NULL;
-}
-
-/* Boyer-Moore-Horspool search (ignore case) */
-static UChar*
-bm_search_ic(regex_t* reg, const UChar* target, const UChar* target_end,
- const UChar* text, const UChar* text_end, const UChar* text_range)
-{
- const UChar *s, *p, *end;
- const UChar *tail;
- OnigEncoding enc = reg->enc;
- int case_fold_flag = reg->case_fold_flag;
-
-# ifdef ONIG_DEBUG_SEARCH
- fprintf(stderr, "bm_search_ic: text: %d (%p), text_end: %d (%p), text_range: %d (%p)\n",
- (int )text, text, (int )text_end, text_end, (int )text_range, text_range);
-# endif
-
- end = text_range + (target_end - target) - 1;
- if (end > text_end)
- end = text_end;
-
- tail = target_end - 1;
- s = text + (target_end - target) - 1;
- if (IS_NULL(reg->int_map)) {
- while (s < end) {
- p = s - (target_end - target) + 1;
- if (str_lower_case_match(enc, case_fold_flag, target, target_end,
- p, s + 1))
- return (UChar* )p;
- s += reg->map[*s];
- }
- }
- else { /* see int_map[] */
-# if OPT_EXACT_MAXLEN >= ONIG_CHAR_TABLE_SIZE
- while (s < end) {
- p = s - (target_end - target) + 1;
- if (str_lower_case_match(enc, case_fold_flag, target, target_end,
- p, s + 1))
- return (UChar* )p;
- s += reg->int_map[*s];
- }
-# endif
- }
- return (UChar* )NULL;
-}
-
-#else /* USE_SUNDAY_QUICK_SEARCH */
-
/* Sunday's quick search applied to a multibyte string */
static UChar*
bm_search_notrev(regex_t* reg, const UChar* target, const UChar* target_end,
- const UChar* text, const UChar* text_end,
- const UChar* text_range)
+ const UChar* text, const UChar* text_end,
+ const UChar* text_range)
{
const UChar *s, *se, *t, *p, *end;
const UChar *tail;
@@ -4593,7 +4390,7 @@ bm_search_notrev(regex_t* reg, const UChar* target, const UChar* target_end,
# ifdef ONIG_DEBUG_SEARCH
fprintf(stderr, "bm_search_notrev: text: %"PRIuPTR" (%p), text_end: %"PRIuPTR" (%p), text_range: %"PRIuPTR" (%p)\n",
- (uintptr_t )text, text, (uintptr_t )text_end, text_end, (uintptr_t )text_range, text_range);
+ (uintptr_t )text, text, (uintptr_t )text_end, text_end, (uintptr_t )text_range, text_range);
# endif
tail = target_end - 1;
@@ -4604,39 +4401,19 @@ bm_search_notrev(regex_t* reg, const UChar* target, const UChar* target_end,
s = text;
- if (IS_NULL(reg->int_map)) {
- while (s < end) {
- p = se = s + tlen1;
- t = tail;
- while (*p == *t) {
- if (t == target) return (UChar* )s;
- p--; t--;
- }
- if (s + 1 >= end) break;
- skip = reg->map[se[1]];
- t = s;
- do {
- s += enclen(enc, s, end);
- } while ((s - t) < skip && s < end);
- }
- }
- else {
-# if OPT_EXACT_MAXLEN >= ONIG_CHAR_TABLE_SIZE
- while (s < end) {
- p = se = s + tlen1;
- t = tail;
- while (*p == *t) {
- if (t == target) return (UChar* )s;
- p--; t--;
- }
- if (s + 1 >= end) break;
- skip = reg->int_map[se[1]];
- t = s;
- do {
- s += enclen(enc, s, end);
- } while ((s - t) < skip && s < end);
+ while (s < end) {
+ p = se = s + tlen1;
+ t = tail;
+ while (*p == *t) {
+ if (t == target) return (UChar* )s;
+ p--; t--;
}
-# endif
+ if (s + 1 >= end) break;
+ skip = reg->map[se[1]];
+ t = s;
+ do {
+ s += enclen(enc, s, end);
+ } while ((s - t) < skip && s < end);
}
return (UChar* )NULL;
@@ -4645,7 +4422,7 @@ bm_search_notrev(regex_t* reg, const UChar* target, const UChar* target_end,
/* Sunday's quick search */
static UChar*
bm_search(regex_t* reg, const UChar* target, const UChar* target_end,
- const UChar* text, const UChar* text_end, const UChar* text_range)
+ const UChar* text, const UChar* text_end, const UChar* text_range)
{
const UChar *s, *t, *p, *end;
const UChar *tail;
@@ -4653,7 +4430,7 @@ bm_search(regex_t* reg, const UChar* target, const UChar* target_end,
# ifdef ONIG_DEBUG_SEARCH
fprintf(stderr, "bm_search: text: %"PRIuPTR" (%p), text_end: %"PRIuPTR" (%p), text_range: %"PRIuPTR" (%p)\n",
- (uintptr_t )text, text, (uintptr_t )text_end, text_end, (uintptr_t )text_range, text_range);
+ (uintptr_t )text, text, (uintptr_t )text_end, text_end, (uintptr_t )text_range, text_range);
# endif
tail = target_end - 1;
@@ -4663,40 +4440,25 @@ bm_search(regex_t* reg, const UChar* target, const UChar* target_end,
end = text_end;
s = text + tlen1;
- if (IS_NULL(reg->int_map)) {
- while (s < end) {
- p = s;
- t = tail;
- while (*p == *t) {
- if (t == target) return (UChar* )p;
- p--; t--;
- }
- if (s + 1 >= end) break;
- s += reg->map[s[1]];
- }
- }
- else { /* see int_map[] */
-# if OPT_EXACT_MAXLEN >= ONIG_CHAR_TABLE_SIZE
- while (s < end) {
- p = s;
- t = tail;
- while (*p == *t) {
- if (t == target) return (UChar* )p;
- p--; t--;
- }
- if (s + 1 >= end) break;
- s += reg->int_map[s[1]];
+ while (s < end) {
+ p = s;
+ t = tail;
+ while (*p == *t) {
+ if (t == target) return (UChar* )p;
+ p--; t--;
}
-# endif
+ if (s + 1 >= end) break;
+ s += reg->map[s[1]];
}
+
return (UChar* )NULL;
}
/* Sunday's quick search applied to a multibyte string (ignore case) */
static UChar*
bm_search_notrev_ic(regex_t* reg, const UChar* target, const UChar* target_end,
- const UChar* text, const UChar* text_end,
- const UChar* text_range)
+ const UChar* text, const UChar* text_end,
+ const UChar* text_range)
{
const UChar *s, *se, *t, *end;
const UChar *tail;
@@ -4706,7 +4468,7 @@ bm_search_notrev_ic(regex_t* reg, const UChar* target, const UChar* target_end,
# ifdef ONIG_DEBUG_SEARCH
fprintf(stderr, "bm_search_notrev_ic: text: %"PRIuPTR" (%p), text_end: %"PRIuPTR" (%p), text_range: %"PRIuPTR" (%p)\n",
- (uintptr_t )text, text, (uintptr_t )text_end, text_end, (uintptr_t )text_range, text_range);
+ (uintptr_t )text, text, (uintptr_t )text_end, text_end, (uintptr_t )text_range, text_range);
# endif
tail = target_end - 1;
@@ -4717,35 +4479,17 @@ bm_search_notrev_ic(regex_t* reg, const UChar* target, const UChar* target_end,
s = text;
- if (IS_NULL(reg->int_map)) {
- while (s < end) {
- se = s + tlen1;
- if (str_lower_case_match(enc, case_fold_flag, target, target_end,
- s, se + 1))
- return (UChar* )s;
- if (s + 1 >= end) break;
- skip = reg->map[se[1]];
- t = s;
- do {
- s += enclen(enc, s, end);
- } while ((s - t) < skip && s < end);
- }
- }
- else {
-# if OPT_EXACT_MAXLEN >= ONIG_CHAR_TABLE_SIZE
- while (s < end) {
- se = s + tlen1;
- if (str_lower_case_match(enc, case_fold_flag, target, target_end,
- s, se + 1))
- return (UChar* )s;
- if (s + 1 >= end) break;
- skip = reg->int_map[se[1]];
- t = s;
- do {
- s += enclen(enc, s, end);
- } while ((s - t) < skip && s < end);
- }
-# endif
+ while (s < end) {
+ se = s + tlen1;
+ if (str_lower_case_match(enc, case_fold_flag, target, target_end,
+ s, se + 1))
+ return (UChar* )s;
+ if (s + 1 >= end) break;
+ skip = reg->map[se[1]];
+ t = s;
+ do {
+ s += enclen(enc, s, end);
+ } while ((s - t) < skip && s < end);
}
return (UChar* )NULL;
@@ -4754,7 +4498,7 @@ bm_search_notrev_ic(regex_t* reg, const UChar* target, const UChar* target_end,
/* Sunday's quick search (ignore case) */
static UChar*
bm_search_ic(regex_t* reg, const UChar* target, const UChar* target_end,
- const UChar* text, const UChar* text_end, const UChar* text_range)
+ const UChar* text, const UChar* text_end, const UChar* text_range)
{
const UChar *s, *p, *end;
const UChar *tail;
@@ -4764,7 +4508,7 @@ bm_search_ic(regex_t* reg, const UChar* target, const UChar* target_end,
# ifdef ONIG_DEBUG_SEARCH
fprintf(stderr, "bm_search_ic: text: %"PRIuPTR" (%p), text_end: %"PRIuPTR" (%p), text_range: %"PRIuPTR" (%p)\n",
- (uintptr_t )text, text, (uintptr_t )text_end, text_end, (uintptr_t )text_range, text_range);
+ (uintptr_t )text, text, (uintptr_t )text_end, text_end, (uintptr_t )text_range, text_range);
# endif
tail = target_end - 1;
@@ -4774,87 +4518,21 @@ bm_search_ic(regex_t* reg, const UChar* target, const UChar* target_end,
end = text_end;
s = text + tlen1;
- if (IS_NULL(reg->int_map)) {
- while (s < end) {
- p = s - tlen1;
- if (str_lower_case_match(enc, case_fold_flag, target, target_end,
- p, s + 1))
- return (UChar* )p;
- if (s + 1 >= end) break;
- s += reg->map[s[1]];
- }
- }
- else { /* see int_map[] */
-# if OPT_EXACT_MAXLEN >= ONIG_CHAR_TABLE_SIZE
- while (s < end) {
- p = s - tlen1;
- if (str_lower_case_match(enc, case_fold_flag, target, target_end,
- p, s + 1))
- return (UChar* )p;
- if (s + 1 >= end) break;
- s += reg->int_map[s[1]];
- }
-# endif
- }
- return (UChar* )NULL;
-}
-#endif /* USE_SUNDAY_QUICK_SEARCH */
-
-#ifdef USE_INT_MAP_BACKWARD
-static int
-set_bm_backward_skip(UChar* s, UChar* end, OnigEncoding enc ARG_UNUSED,
- int** skip)
-{
- int i, len;
-
- if (IS_NULL(*skip)) {
- *skip = (int* )xmalloc(sizeof(int) * ONIG_CHAR_TABLE_SIZE);
- if (IS_NULL(*skip)) return ONIGERR_MEMORY;
- }
-
- len = (int )(end - s);
- for (i = 0; i < ONIG_CHAR_TABLE_SIZE; i++)
- (*skip)[i] = len;
-
- for (i = len - 1; i > 0; i--)
- (*skip)[s[i]] = i;
-
- return 0;
-}
-
-static UChar*
-bm_search_backward(regex_t* reg, const UChar* target, const UChar* target_end,
- const UChar* text, const UChar* adjust_text,
- const UChar* text_end, const UChar* text_start)
-{
- const UChar *s, *t, *p;
-
- s = text_end - (target_end - target);
- if (text_start < s)
- s = text_start;
- else
- s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, adjust_text, s, text_end);
-
- while (s >= text) {
- p = s;
- t = target;
- while (t < target_end && *p == *t) {
- p++; t++;
- }
- if (t == target_end)
- return (UChar* )s;
-
- s -= reg->int_map_backward[*s];
- s = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, adjust_text, s, text_end);
+ while (s < end) {
+ p = s - tlen1;
+ if (str_lower_case_match(enc, case_fold_flag, target, target_end,
+ p, s + 1))
+ return (UChar* )p;
+ if (s + 1 >= end) break;
+ s += reg->map[s[1]];
}
return (UChar* )NULL;
}
-#endif
static UChar*
map_search(OnigEncoding enc, UChar map[],
- const UChar* text, const UChar* text_range, const UChar* text_end)
+ const UChar* text, const UChar* text_range, const UChar* text_end)
{
const UChar *s = text;
@@ -4868,8 +4546,8 @@ map_search(OnigEncoding enc, UChar map[],
static UChar*
map_search_backward(OnigEncoding enc, UChar map[],
- const UChar* text, const UChar* adjust_text,
- const UChar* text_start, const UChar* text_end)
+ const UChar* text, const UChar* adjust_text,
+ const UChar* text_start, const UChar* text_end)
{
const UChar *s = text_start;
@@ -4883,7 +4561,7 @@ map_search_backward(OnigEncoding enc, UChar map[],
extern OnigPosition
onig_match(regex_t* reg, const UChar* str, const UChar* end, const UChar* at, OnigRegion* region,
- OnigOptionType option)
+ OnigOptionType option)
{
ptrdiff_t r;
UChar *prev;
@@ -4907,9 +4585,9 @@ onig_match(regex_t* reg, const UChar* str, const UChar* end, const UChar* at, On
prev = (UChar* )onigenc_get_prev_char_head(reg->enc, str, at, end);
r = match_at(reg, str, end,
#ifdef USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE
- end,
+ end,
#endif
- at, prev, &msa);
+ at, prev, &msa);
}
MATCH_ARG_FREE(msa);
@@ -4918,14 +4596,14 @@ onig_match(regex_t* reg, const UChar* str, const UChar* end, const UChar* at, On
static int
forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
- UChar* range, UChar** low, UChar** high, UChar** low_prev)
+ UChar* range, UChar** low, UChar** high, UChar** low_prev)
{
UChar *p, *pprev = (UChar* )NULL;
size_t input_len = end - str;
#ifdef ONIG_DEBUG_SEARCH
fprintf(stderr, "forward_search_range: str: %"PRIuPTR" (%p), end: %"PRIuPTR" (%p), s: %"PRIuPTR" (%p), range: %"PRIuPTR" (%p)\n",
- (uintptr_t )str, str, (uintptr_t )end, end, (uintptr_t )s, s, (uintptr_t )range, range);
+ (uintptr_t )str, str, (uintptr_t )end, end, (uintptr_t )s, s, (uintptr_t )range, range);
#endif
if (reg->dmin > input_len) {
@@ -4933,14 +4611,14 @@ forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
}
p = s;
- if (reg->dmin > 0) {
+ if (reg->dmin != 0) {
+ if ((OnigDistance)(end - p) <= reg->dmin) return 0; /* fail */
if (ONIGENC_IS_SINGLEBYTE(reg->enc)) {
p += reg->dmin;
}
else {
UChar *q = p + reg->dmin;
- if (q >= end) return 0; /* fail */
while (p < q) p += enclen(reg->enc, p, end);
}
}
@@ -4952,7 +4630,7 @@ forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
break;
case ONIG_OPTIMIZE_EXACT_IC:
p = slow_search_ic(reg->enc, reg->case_fold_flag,
- reg->exact, reg->exact_end, p, end, range);
+ reg->exact, reg->exact_end, p, end, range);
break;
case ONIG_OPTIMIZE_EXACT_BM:
@@ -4977,7 +4655,7 @@ forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
}
if (p && p < range) {
- if (p - reg->dmin < s) {
+ if ((OnigDistance)(p - s) < reg->dmin) {
retry_gate:
pprev = p;
p += enclen(reg->enc, p, end);
@@ -4989,70 +4667,74 @@ forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
switch (reg->sub_anchor) {
case ANCHOR_BEGIN_LINE:
- if (!ON_STR_BEGIN(p)) {
- prev = onigenc_get_prev_char_head(reg->enc,
- (pprev ? pprev : str), p, end);
- if (!ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, prev, str, end, reg->options, 0))
- goto retry_gate;
- }
- break;
+ if (!ON_STR_BEGIN(p)) {
+ prev = onigenc_get_prev_char_head(reg->enc,
+ (pprev ? pprev : str), p, end);
+ if (!ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, prev, str, end, reg->options, 0))
+ goto retry_gate;
+ }
+ break;
case ANCHOR_END_LINE:
- if (ON_STR_END(p)) {
+ if (ON_STR_END(p)) {
#ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE
- prev = (UChar* )onigenc_get_prev_char_head(reg->enc,
- (pprev ? pprev : str), p);
- if (prev && ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, prev, str, end, reg->options, 1))
- goto retry_gate;
+ prev = (UChar* )onigenc_get_prev_char_head(reg->enc,
+ (pprev ? pprev : str), p);
+ if (prev && ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, prev, str, end, reg->options, 1))
+ goto retry_gate;
#endif
- }
- else if (! ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, p, str, end, reg->options, 1))
- goto retry_gate;
- break;
+ }
+ else if (! ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, p, str, end, reg->options, 1))
+ goto retry_gate;
+ break;
}
}
if (reg->dmax == 0) {
*low = p;
if (low_prev) {
- if (*low > s)
- *low_prev = onigenc_get_prev_char_head(reg->enc, s, p, end);
- else
- *low_prev = onigenc_get_prev_char_head(reg->enc,
- (pprev ? pprev : str), p, end);
+ if (*low > s)
+ *low_prev = onigenc_get_prev_char_head(reg->enc, s, p, end);
+ else
+ *low_prev = onigenc_get_prev_char_head(reg->enc,
+ (pprev ? pprev : str), p, end);
}
+ *high = p;
}
else {
if (reg->dmax != ONIG_INFINITE_DISTANCE) {
- if (p < str + reg->dmax) {
- *low = (UChar* )str;
- if (low_prev)
- *low_prev = onigenc_get_prev_char_head(reg->enc, str, *low, end);
- }
- else {
- *low = p - reg->dmax;
- if (*low > s) {
- *low = onigenc_get_right_adjust_char_head_with_prev(reg->enc, s,
- *low, end, (const UChar** )low_prev);
- if (low_prev && IS_NULL(*low_prev))
- *low_prev = onigenc_get_prev_char_head(reg->enc,
- (pprev ? pprev : s), *low, end);
- }
- else {
- if (low_prev)
- *low_prev = onigenc_get_prev_char_head(reg->enc,
- (pprev ? pprev : str), *low, end);
- }
- }
+ if ((OnigDistance)(p - str) < reg->dmax) {
+ *low = (UChar* )str;
+ if (low_prev)
+ *low_prev = onigenc_get_prev_char_head(reg->enc, str, *low, end);
+ }
+ else {
+ *low = p - reg->dmax;
+ if (*low > s) {
+ *low = onigenc_get_right_adjust_char_head_with_prev(reg->enc, s,
+ *low, end, (const UChar** )low_prev);
+ if (low_prev && IS_NULL(*low_prev))
+ *low_prev = onigenc_get_prev_char_head(reg->enc,
+ (pprev ? pprev : s), *low, end);
+ }
+ else {
+ if (low_prev)
+ *low_prev = onigenc_get_prev_char_head(reg->enc,
+ (pprev ? pprev : str), *low, end);
+ }
+ }
}
+ /* no needs to adjust *high, *high is used as range check only */
+ if ((OnigDistance)(p - str) < reg->dmin)
+ *high = (UChar* )str;
+ else
+ *high = p - reg->dmin;
}
- /* no needs to adjust *high, *high is used as range check only */
- *high = p - reg->dmin;
#ifdef ONIG_DEBUG_SEARCH
fprintf(stderr,
"forward_search_range success: low: %"PRIdPTR", high: %"PRIdPTR", dmin: %"PRIdPTR", dmax: %"PRIdPTR"\n",
- *low - str, *high - str, reg->dmin, reg->dmax);
+ *low - str, *high - str, reg->dmin, reg->dmax);
#endif
return 1; /* success */
}
@@ -5064,8 +4746,8 @@ forward_search_range(regex_t* reg, const UChar* str, const UChar* end, UChar* s,
static int
backward_search_range(regex_t* reg, const UChar* str, const UChar* end,
- UChar* s, const UChar* range, UChar* adjrange,
- UChar** low, UChar** high)
+ UChar* s, const UChar* range, UChar* adjrange,
+ UChar** low, UChar** high)
{
UChar *p;
size_t input_len = end - str;
@@ -5074,7 +4756,6 @@ backward_search_range(regex_t* reg, const UChar* str, const UChar* end,
return 0;
}
- range += reg->dmin;
p = s;
retry:
@@ -5082,34 +4763,20 @@ backward_search_range(regex_t* reg, const UChar* str, const UChar* end,
case ONIG_OPTIMIZE_EXACT:
exact_method:
p = slow_search_backward(reg->enc, reg->exact, reg->exact_end,
- range, adjrange, end, p);
+ range, adjrange, end, p);
break;
case ONIG_OPTIMIZE_EXACT_IC:
case ONIG_OPTIMIZE_EXACT_BM_IC:
case ONIG_OPTIMIZE_EXACT_BM_NOT_REV_IC:
p = slow_search_backward_ic(reg->enc, reg->case_fold_flag,
- reg->exact, reg->exact_end,
- range, adjrange, end, p);
+ reg->exact, reg->exact_end,
+ range, adjrange, end, p);
break;
case ONIG_OPTIMIZE_EXACT_BM:
case ONIG_OPTIMIZE_EXACT_BM_NOT_REV:
-#ifdef USE_INT_MAP_BACKWARD
- if (IS_NULL(reg->int_map_backward)) {
- int r;
- if (s - range < BM_BACKWARD_SEARCH_LENGTH_THRESHOLD)
- goto exact_method;
-
- r = set_bm_backward_skip(reg->exact, reg->exact_end, reg->enc,
- &(reg->int_map_backward));
- if (r) return r;
- }
- p = bm_search_backward(reg, reg->exact, reg->exact_end, range, adjrange,
- end, p);
-#else
goto exact_method;
-#endif
break;
case ONIG_OPTIMIZE_MAP:
@@ -5123,45 +4790,57 @@ backward_search_range(regex_t* reg, const UChar* str, const UChar* end,
switch (reg->sub_anchor) {
case ANCHOR_BEGIN_LINE:
- if (!ON_STR_BEGIN(p)) {
- prev = onigenc_get_prev_char_head(reg->enc, str, p, end);
- if (!ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, prev, str, end, reg->options, 0)) {
- p = prev;
- goto retry;
- }
- }
- break;
+ if (!ON_STR_BEGIN(p)) {
+ prev = onigenc_get_prev_char_head(reg->enc, str, p, end);
+ if (!ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, prev, str, end, reg->options, 0)) {
+ p = prev;
+ goto retry;
+ }
+ }
+ break;
case ANCHOR_END_LINE:
- if (ON_STR_END(p)) {
+ if (ON_STR_END(p)) {
#ifndef USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE
- prev = onigenc_get_prev_char_head(reg->enc, adjrange, p);
- if (IS_NULL(prev)) goto fail;
- if (ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, prev, str, end, reg->options, 1)) {
- p = prev;
- goto retry;
- }
+ prev = onigenc_get_prev_char_head(reg->enc, adjrange, p);
+ if (IS_NULL(prev)) goto fail;
+ if (ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, prev, str, end, reg->options, 1)) {
+ p = prev;
+ goto retry;
+ }
#endif
- }
- else if (! ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, p, str, end, reg->options, 1)) {
- p = onigenc_get_prev_char_head(reg->enc, adjrange, p, end);
- if (IS_NULL(p)) goto fail;
- goto retry;
- }
- break;
+ }
+ else if (! ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, p, str, end, reg->options, 1)) {
+ p = onigenc_get_prev_char_head(reg->enc, adjrange, p, end);
+ if (IS_NULL(p)) goto fail;
+ goto retry;
+ }
+ break;
}
}
- /* no needs to adjust *high, *high is used as range check only */
if (reg->dmax != ONIG_INFINITE_DISTANCE) {
- *low = p - reg->dmax;
- *high = p - reg->dmin;
+ if ((OnigDistance)(p - str) < reg->dmax)
+ *low = (UChar* )str;
+ else
+ *low = p - reg->dmax;
+
+ if (reg->dmin != 0) {
+ if ((OnigDistance)(p - str) < reg->dmin)
+ *high = (UChar* )str;
+ else
+ *high = p - reg->dmin;
+ }
+ else {
+ *high = p;
+ }
+
*high = onigenc_get_right_adjust_char_head(reg->enc, adjrange, *high, end);
}
#ifdef ONIG_DEBUG_SEARCH
fprintf(stderr, "backward_search_range: low: %d, high: %d\n",
- (int )(*low - str), (int )(*high - str));
+ (int )(*low - str), (int )(*high - str));
#endif
return 1; /* success */
}
@@ -5176,15 +4855,15 @@ backward_search_range(regex_t* reg, const UChar* str, const UChar* end,
extern OnigPosition
onig_search(regex_t* reg, const UChar* str, const UChar* end,
- const UChar* start, const UChar* range, OnigRegion* region, OnigOptionType option)
+ const UChar* start, const UChar* range, OnigRegion* region, OnigOptionType option)
{
return onig_search_gpos(reg, str, end, start, start, range, region, option);
}
extern OnigPosition
onig_search_gpos(regex_t* reg, const UChar* str, const UChar* end,
- const UChar* global_pos,
- const UChar* start, const UChar* range, OnigRegion* region, OnigOptionType option)
+ const UChar* global_pos,
+ const UChar* start, const UChar* range, OnigRegion* region, OnigOptionType option)
{
ptrdiff_t r;
UChar *s, *prev;
@@ -5212,44 +4891,64 @@ onig_search_gpos(regex_t* reg, const UChar* str, const UChar* end,
# ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE
# define MATCH_AND_RETURN_CHECK(upper_range) \
r = match_at(reg, str, end, (upper_range), s, prev, &msa); \
- if (r != ONIG_MISMATCH) {\
- if (r >= 0) {\
- if (! IS_FIND_LONGEST(reg->options)) {\
- goto match;\
+ switch (r) { \
+ case ONIG_MISMATCH: \
+ break; \
+ case ONIGERR_TIMEOUT: \
+ goto timeout; \
+ default: \
+ if (r >= 0) { \
+ if (! IS_FIND_LONGEST(reg->options)) { \
+ goto match; \
+ }\
}\
- }\
- else goto finish; /* error */ \
+ else goto finish; /* error */ \
}
# else
# define MATCH_AND_RETURN_CHECK(upper_range) \
r = match_at(reg, str, end, (upper_range), s, prev, &msa); \
- if (r != ONIG_MISMATCH) {\
- if (r >= 0) {\
- goto match;\
- }\
- else goto finish; /* error */ \
+ switch (r) { \
+ case ONIG_MISMATCH: \
+ break; \
+ case ONIGERR_TIMEOUT: \
+ goto timeout; \
+ default: \
+ if (r >= 0) { \
+ goto match; \
+ }\
+ else goto finish; /* error */ \
}
# endif /* USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE */
#else
# ifdef USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE
# define MATCH_AND_RETURN_CHECK(none) \
r = match_at(reg, str, end, s, prev, &msa);\
- if (r != ONIG_MISMATCH) {\
- if (r >= 0) {\
- if (! IS_FIND_LONGEST(reg->options)) {\
- goto match;\
- }\
- }\
- else goto finish; /* error */ \
+ switch (r) { \
+ case ONIG_MISMATCH: \
+ break; \
+ case ONIGERR_TIMEOUT: \
+ goto timeout; \
+ default: \
+ if (r >= 0) { \
+ if (! IS_FIND_LONGEST(reg->options)) { \
+ goto match; \
+ } \
+ } \
+ else goto finish; /* error */ \
}
# else
# define MATCH_AND_RETURN_CHECK(none) \
r = match_at(reg, str, end, s, prev, &msa);\
- if (r != ONIG_MISMATCH) {\
- if (r >= 0) {\
- goto match;\
- }\
- else goto finish; /* error */ \
+ switch (r) { \
+ case ONIG_MISMATCH: \
+ break; \
+ case ONIGERR_TIMEOUT: \
+ goto timeout; \
+ default: \
+ if (r >= 0) { \
+ goto match; \
+ } \
+ else goto finish; /* error */ \
}
# endif /* USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE */
#endif /* USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE */
@@ -5264,62 +4963,69 @@ onig_search_gpos(regex_t* reg, const UChar* str, const UChar* end,
begin_position:
if (range > start)
{
- if (global_pos > start)
- {
- if (global_pos < range)
- range = global_pos + 1;
- }
- else
- range = start + 1;
+ if (global_pos > start)
+ {
+ if (global_pos < range)
+ range = global_pos + 1;
+ }
+ else
+ range = start + 1;
}
else
- range = start;
+ range = start;
}
else if (reg->anchor & ANCHOR_BEGIN_BUF) {
/* search str-position only */
if (range > start) {
- if (start != str) goto mismatch_no_msa;
- range = str + 1;
+ if (start != str) goto mismatch_no_msa;
+ range = str + 1;
}
else {
- if (range <= str) {
- start = str;
- range = str;
- }
- else
- goto mismatch_no_msa;
+ if (range <= str) {
+ start = str;
+ range = str;
+ }
+ else
+ goto mismatch_no_msa;
}
}
else if (reg->anchor & ANCHOR_END_BUF) {
min_semi_end = max_semi_end = (UChar* )end;
end_buf:
- if ((OnigDistance )(max_semi_end - str) < reg->anchor_dmin)
- goto mismatch_no_msa;
+ if ((OnigDistance)(max_semi_end - str) < reg->anchor_dmin)
+ goto mismatch_no_msa;
if (range > start) {
- if ((OnigDistance )(min_semi_end - start) > reg->anchor_dmax) {
- start = min_semi_end - reg->anchor_dmax;
- if (start < end)
- start = onigenc_get_right_adjust_char_head(reg->enc, str, start, end);
- }
- if ((OnigDistance )(max_semi_end - (range - 1)) < reg->anchor_dmin) {
- range = max_semi_end - reg->anchor_dmin + 1;
- }
+ if ((OnigDistance)(min_semi_end - start) > reg->anchor_dmax) {
+ start = min_semi_end - reg->anchor_dmax;
+ if (start < end)
+ start = onigenc_get_right_adjust_char_head(reg->enc, str, start, end);
+ }
+ if ((OnigDistance)(max_semi_end - (range - 1)) < reg->anchor_dmin) {
+ if ((OnigDistance)(max_semi_end - str + 1) < reg->anchor_dmin)
+ goto mismatch_no_msa;
+ else
+ range = max_semi_end - reg->anchor_dmin + 1;
+ }
- if (start > range) goto mismatch_no_msa;
- /* If start == range, match with empty at end.
- Backward search is used. */
+ if (start > range) goto mismatch_no_msa;
+ /* If start == range, match with empty at end.
+ Backward search is used. */
}
else {
- if ((OnigDistance )(min_semi_end - range) > reg->anchor_dmax) {
- range = min_semi_end - reg->anchor_dmax;
- }
- if ((OnigDistance )(max_semi_end - start) < reg->anchor_dmin) {
- start = max_semi_end - reg->anchor_dmin;
- start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, start, end);
- }
- if (range > start) goto mismatch_no_msa;
+ if ((OnigDistance)(min_semi_end - range) > reg->anchor_dmax) {
+ range = min_semi_end - reg->anchor_dmax;
+ }
+ if ((OnigDistance)(max_semi_end - start) < reg->anchor_dmin) {
+ if ((OnigDistance)(max_semi_end - str) < reg->anchor_dmin)
+ goto mismatch_no_msa;
+ else {
+ start = max_semi_end - reg->anchor_dmin;
+ start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, start, end);
+ }
+ }
+ if (range > start) goto mismatch_no_msa;
}
}
else if (reg->anchor & ANCHOR_SEMI_END_BUF) {
@@ -5327,23 +5033,23 @@ onig_search_gpos(regex_t* reg, const UChar* str, const UChar* end,
max_semi_end = (UChar* )end;
if (ONIGENC_IS_MBC_NEWLINE(reg->enc, pre_end, end)) {
- min_semi_end = pre_end;
+ min_semi_end = pre_end;
#ifdef USE_CRNL_AS_LINE_TERMINATOR
- pre_end = ONIGENC_STEP_BACK(reg->enc, str, pre_end, end, 1);
- if (IS_NOT_NULL(pre_end) &&
- IS_NEWLINE_CRLF(reg->options) &&
- ONIGENC_IS_MBC_CRNL(reg->enc, pre_end, end)) {
- min_semi_end = pre_end;
- }
+ pre_end = ONIGENC_STEP_BACK(reg->enc, str, pre_end, end, 1);
+ if (IS_NOT_NULL(pre_end) &&
+ IS_NEWLINE_CRLF(reg->options) &&
+ ONIGENC_IS_MBC_CRNL(reg->enc, pre_end, end)) {
+ min_semi_end = pre_end;
+ }
#endif
- if (min_semi_end > str && start <= min_semi_end) {
- goto end_buf;
- }
+ if (min_semi_end > str && start <= min_semi_end) {
+ goto end_buf;
+ }
}
else {
- min_semi_end = (UChar* )end;
- goto end_buf;
+ min_semi_end = (UChar* )end;
+ goto end_buf;
}
}
else if ((reg->anchor & ANCHOR_ANYCHAR_STAR_ML)) {
@@ -5375,7 +5081,7 @@ onig_search_gpos(regex_t* reg, const UChar* str, const UChar* end,
#ifdef ONIG_DEBUG_SEARCH
fprintf(stderr, "onig_search(apply anchor): end: %d, start: %d, range: %d\n",
- (int )(end - str), (int )(start - str), (int )(range - str));
+ (int )(end - str), (int )(start - str), (int )(range - str));
#endif
MATCH_ARG_INIT(msa, option, region, start, global_pos);
@@ -5396,55 +5102,59 @@ onig_search_gpos(regex_t* reg, const UChar* str, const UChar* end,
if (reg->optimize != ONIG_OPTIMIZE_NONE) {
UChar *sch_range, *low, *high, *low_prev;
- sch_range = (UChar* )range;
if (reg->dmax != 0) {
- if (reg->dmax == ONIG_INFINITE_DISTANCE)
- sch_range = (UChar* )end;
- else {
- sch_range += reg->dmax;
- if (sch_range > end) sch_range = (UChar* )end;
- }
+ if (reg->dmax == ONIG_INFINITE_DISTANCE)
+ sch_range = (UChar* )end;
+ else {
+ if ((OnigDistance)(end - range) < reg->dmax)
+ sch_range = (UChar* )end;
+ else {
+ sch_range = (UChar* )range + reg->dmax;
+ }
+ }
}
+ else
+ sch_range = (UChar* )range;
if ((end - start) < reg->threshold_len)
- goto mismatch;
+ goto mismatch;
if (reg->dmax != ONIG_INFINITE_DISTANCE) {
- do {
- if (! forward_search_range(reg, str, end, s, sch_range,
- &low, &high, &low_prev)) goto mismatch;
- if (s < low) {
- s = low;
- prev = low_prev;
- }
- while (s <= high) {
- MATCH_AND_RETURN_CHECK(orig_range);
- prev = s;
- s += enclen(reg->enc, s, end);
- }
- } while (s < range);
- goto mismatch;
+ do {
+ if (! forward_search_range(reg, str, end, s, sch_range,
+ &low, &high, &low_prev)) goto mismatch;
+ if (s < low) {
+ s = low;
+ prev = low_prev;
+ }
+ while (s <= high) {
+ MATCH_AND_RETURN_CHECK(orig_range);
+ prev = s;
+ s += enclen(reg->enc, s, end);
+ }
+ } while (s < range);
+ goto mismatch;
}
else { /* check only. */
- if (! forward_search_range(reg, str, end, s, sch_range,
- &low, &high, (UChar** )NULL)) goto mismatch;
-
- if ((reg->anchor & ANCHOR_ANYCHAR_STAR) != 0) {
- do {
- MATCH_AND_RETURN_CHECK(orig_range);
- prev = s;
- s += enclen(reg->enc, s, end);
-
- if ((reg->anchor & (ANCHOR_LOOK_BEHIND | ANCHOR_PREC_READ_NOT)) == 0) {
- while (!ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, prev, str, end, reg->options, 0)
- && s < range) {
- prev = s;
- s += enclen(reg->enc, s, end);
- }
- }
- } while (s < range);
- goto mismatch;
- }
+ if (! forward_search_range(reg, str, end, s, sch_range,
+ &low, &high, (UChar** )NULL)) goto mismatch;
+
+ if ((reg->anchor & ANCHOR_ANYCHAR_STAR) != 0) {
+ do {
+ MATCH_AND_RETURN_CHECK(orig_range);
+ prev = s;
+ s += enclen(reg->enc, s, end);
+
+ if ((reg->anchor & (ANCHOR_LOOK_BEHIND | ANCHOR_PREC_READ_NOT)) == 0) {
+ while (!ONIGENC_IS_MBC_NEWLINE_EX(reg->enc, prev, str, end, reg->options, 0)
+ && s < range) {
+ prev = s;
+ s += enclen(reg->enc, s, end);
+ }
+ }
+ } while (s < range);
+ goto mismatch;
+ }
}
}
@@ -5461,49 +5171,61 @@ onig_search_gpos(regex_t* reg, const UChar* str, const UChar* end,
else { /* backward search */
if (reg->optimize != ONIG_OPTIMIZE_NONE) {
UChar *low, *high, *adjrange, *sch_start;
+ const UChar *min_range;
if (range < end)
- adjrange = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, range, end);
+ adjrange = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc, str, range, end);
+ else
+ adjrange = (UChar* )end;
+
+ if ((OnigDistance)(end - range) > reg->dmin)
+ min_range = range + reg->dmin;
else
- adjrange = (UChar* )end;
+ min_range = end;
if (reg->dmax != ONIG_INFINITE_DISTANCE &&
- (end - range) >= reg->threshold_len) {
- do {
- sch_start = s + reg->dmax;
- if (sch_start > end) sch_start = (UChar* )end;
- if (backward_search_range(reg, str, end, sch_start, range, adjrange,
- &low, &high) <= 0)
- goto mismatch;
-
- if (s > high)
- s = high;
-
- while (s >= low) {
- prev = onigenc_get_prev_char_head(reg->enc, str, s, end);
- MATCH_AND_RETURN_CHECK(orig_start);
- s = prev;
- }
- } while (s >= range);
- goto mismatch;
+ end - range >= reg->threshold_len) {
+ do {
+ if ((OnigDistance)(end - s) > reg->dmax)
+ sch_start = s + reg->dmax;
+ else
+ sch_start = (UChar* )end;
+
+ if (backward_search_range(reg, str, end, sch_start, min_range, adjrange,
+ &low, &high) <= 0)
+ goto mismatch;
+
+ if (s > high)
+ s = high;
+
+ while (s >= low) {
+ prev = onigenc_get_prev_char_head(reg->enc, str, s, end);
+ MATCH_AND_RETURN_CHECK(orig_start);
+ s = prev;
+ }
+ } while (s >= range);
+ goto mismatch;
}
else { /* check only. */
- if ((end - range) < reg->threshold_len) goto mismatch;
-
- sch_start = s;
- if (reg->dmax != 0) {
- if (reg->dmax == ONIG_INFINITE_DISTANCE)
- sch_start = (UChar* )end;
- else {
- sch_start += reg->dmax;
- if (sch_start > end) sch_start = (UChar* )end;
- else
- sch_start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc,
- start, sch_start, end);
- }
- }
- if (backward_search_range(reg, str, end, sch_start, range, adjrange,
- &low, &high) <= 0) goto mismatch;
+ if (end - range < reg->threshold_len) goto mismatch;
+
+ if (reg->dmax != 0) {
+ if (reg->dmax == ONIG_INFINITE_DISTANCE)
+ sch_start = (UChar* )end;
+ else {
+ if ((OnigDistance)(end - s) > reg->dmax) {
+ sch_start = s + reg->dmax;
+ sch_start = ONIGENC_LEFT_ADJUST_CHAR_HEAD(reg->enc,
+ start, sch_start, end);
+ } else
+ sch_start = (UChar* )end;
+ }
+ }
+ else
+ sch_start = (UChar* )s;
+
+ if (backward_search_range(reg, str, end, sch_start, min_range, adjrange,
+ &low, &high) <= 0) goto mismatch;
}
}
@@ -5552,13 +5274,17 @@ onig_search_gpos(regex_t* reg, const UChar* str, const UChar* end,
match:
MATCH_ARG_FREE(msa);
return s - str;
+
+timeout:
+ MATCH_ARG_FREE(msa);
+ return ONIGERR_TIMEOUT;
}
extern OnigPosition
onig_scan(regex_t* reg, const UChar* str, const UChar* end,
- OnigRegion* region, OnigOptionType option,
- int (*scan_callback)(OnigPosition, OnigPosition, OnigRegion*, void*),
- void* callback_arg)
+ OnigRegion* region, OnigOptionType option,
+ int (*scan_callback)(OnigPosition, OnigPosition, OnigRegion*, void*),
+ void* callback_arg)
{
OnigPosition r;
OnigPosition n;
@@ -5573,17 +5299,17 @@ onig_scan(regex_t* reg, const UChar* str, const UChar* end,
rs = scan_callback(n, r, region, callback_arg);
n++;
if (rs != 0)
- return rs;
+ return rs;
if (region->end[0] == start - str) {
- if (start >= end) break;
- start += enclen(reg->enc, start, end);
+ if (start >= end) break;
+ start += enclen(reg->enc, start, end);
}
else
- start = str + region->end[0];
+ start = str + region->end[0];
if (start > end)
- break;
+ break;
}
else if (r == ONIG_MISMATCH) {
break;
diff --git a/regint.h b/regint.h
index 57cbb81654..3f4aa919e5 100644
--- a/regint.h
+++ b/regint.h
@@ -5,7 +5,7 @@
**********************************************************************/
/*-
* Copyright (c) 2002-2013 K.Kosako <sndgk393 AT ybb DOT ne DOT jp>
- * Copyright (c) 2011-2016 K.Takata <kentkt AT csc DOT jp>
+ * Copyright (c) 2011-2019 K.Takata <kentkt AT csc DOT jp>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -86,13 +86,12 @@
/* #define USE_OP_PUSH_OR_JUMP_EXACT */
#define USE_QTFR_PEEK_NEXT
#define USE_ST_LIBRARY
-#define USE_SUNDAY_QUICK_SEARCH
#define INIT_MATCH_STACK_SIZE 160
#define DEFAULT_MATCH_STACK_LIMIT_SIZE 0 /* unlimited */
#define DEFAULT_PARSE_DEPTH_LIMIT 4096
-#define OPT_EXACT_MAXLEN 24
+#define OPT_EXACT_MAXLEN 24 /* This must be smaller than ONIG_CHAR_TABLE_SIZE. */
/* check config */
#if defined(USE_PERL_SUBEXP_CALL) || defined(USE_CAPITAL_P_NAMED_GROUP)
@@ -163,9 +162,6 @@
rb_thread_check_ints(); \
} \
} while(0)
-# define HANDLE_REG_TIMEOUT_IN_MATCH_AT do { \
- rb_reg_raise_timeout(); \
-} while (0)
# define onig_st_init_table st_init_table
# define onig_st_init_table_with_size st_init_table_with_size
# define onig_st_init_numtable st_init_numtable
@@ -219,9 +215,7 @@
#define xmemcpy memcpy
#define xmemmove memmove
-#if ((defined(RUBY_MSVCRT_VERSION) && RUBY_MSVCRT_VERSION >= 90) \
- || (!defined(RUBY_MSVCRT_VERSION) && defined(_WIN32))) \
- && !defined(__GNUC__)
+#if defined(_WIN32) && !defined(__GNUC__)
# define xalloca _alloca
# define xvsnprintf(buf,size,fmt,args) _vsnprintf_s(buf,size,_TRUNCATE,fmt,args)
# define xsnprintf sprintf_s
@@ -270,19 +264,6 @@
# include <stdio.h>
#endif
-#ifdef _WIN32
-# if defined(_MSC_VER) && (_MSC_VER < 1300)
-# ifndef _INTPTR_T_DEFINED
-# define _INTPTR_T_DEFINED
-typedef int intptr_t;
-# endif
-# ifndef _UINTPTR_T_DEFINED
-# define _UINTPTR_T_DEFINED
-typedef unsigned int uintptr_t;
-# endif
-# endif
-#endif /* _WIN32 */
-
#ifndef PRIdPTR
# ifdef _WIN64
# define PRIdPTR "I64d"
@@ -1002,7 +983,6 @@ extern int onig_st_insert_strend(hash_table_type* table, const UChar* str_key, c
extern size_t onig_memsize(const regex_t *reg);
extern size_t onig_region_memsize(const struct re_registers *regs);
bool rb_reg_timeout_p(regex_t *reg, void *end_time);
-NORETURN(void rb_reg_raise_timeout(void));
#endif
RUBY_SYMBOL_EXPORT_END
diff --git a/regparse.c b/regparse.c
index 33815f2445..123b3015a5 100644
--- a/regparse.c
+++ b/regparse.c
@@ -3,7 +3,7 @@
**********************************************************************/
/*-
* Copyright (c) 2002-2008 K.Kosako <sndgk393 AT ybb DOT ne DOT jp>
- * Copyright (c) 2011-2016 K.Takata <kentkt AT csc DOT jp>
+ * Copyright (c) 2011-2019 K.Takata <kentkt AT csc DOT jp>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -329,7 +329,7 @@ strdup_with_null(OnigEncoding enc, const UChar* s, const UChar* end)
static UChar*
strcat_capa(UChar* dest, UChar* dest_end, const UChar* src, const UChar* src_end,
- size_t capa)
+ size_t capa)
{
UChar* r;
@@ -346,7 +346,7 @@ strcat_capa(UChar* dest, UChar* dest_end, const UChar* src, const UChar* src_end
/* dest on static area */
static UChar*
strcat_capa_from_static(UChar* dest, UChar* dest_end,
- const UChar* src, const UChar* src_end, size_t capa)
+ const UChar* src, const UChar* src_end, size_t capa)
{
UChar* r;
@@ -426,7 +426,7 @@ onig_st_init_strend_table_with_size(st_index_t size)
extern int
onig_st_lookup_strend(hash_table_type* table, const UChar* str_key,
- const UChar* end_key, hash_data_type *value)
+ const UChar* end_key, hash_data_type *value)
{
st_str_end_key key;
@@ -438,7 +438,7 @@ onig_st_lookup_strend(hash_table_type* table, const UChar* str_key,
extern int
onig_st_insert_strend(hash_table_type* table, const UChar* str_key,
- const UChar* end_key, hash_data_type value)
+ const UChar* end_key, hash_data_type value)
{
st_str_end_key* key;
int result;
@@ -629,10 +629,10 @@ i_names(HashDataType key_ ARG_UNUSED, HashDataType e_, HashDataType arg_)
NameEntry* e = (NameEntry *)e_;
INamesArg* arg = (INamesArg *)arg_;
int r = (*(arg->func))(e->name,
- e->name + e->name_len,
- e->back_num,
- (e->back_num > 1 ? e->back_refs : &(e->back_ref1)),
- arg->reg, arg->arg);
+ e->name + e->name_len,
+ e->back_num,
+ (e->back_num > 1 ? e->back_refs : &(e->back_ref1)),
+ arg->reg, arg->arg);
if (r != 0) {
arg->ret = r;
return ST_STOP;
@@ -724,16 +724,16 @@ onig_print_names(FILE* fp, regex_t* reg)
e = &(t->e[i]);
fprintf(fp, "%s: ", e->name);
if (e->back_num == 0) {
- fputs("-", fp);
+ fputs("-", fp);
}
else if (e->back_num == 1) {
- fprintf(fp, "%d", e->back_ref1);
+ fprintf(fp, "%d", e->back_ref1);
}
else {
- for (j = 0; j < e->back_num; j++) {
- if (j > 0) fprintf(fp, ", ");
- fprintf(fp, "%d", e->back_refs[j]);
- }
+ for (j = 0; j < e->back_num; j++) {
+ if (j > 0) fprintf(fp, ", ");
+ fprintf(fp, "%d", e->back_refs[j]);
+ }
}
fputs("\n", fp);
}
@@ -754,13 +754,13 @@ names_clear(regex_t* reg)
for (i = 0; i < t->num; i++) {
e = &(t->e[i]);
if (IS_NOT_NULL(e->name)) {
- xfree(e->name);
- e->name = NULL;
- e->name_len = 0;
- e->back_num = 0;
- e->back_alloc = 0;
- xfree(e->back_refs);
- e->back_refs = (int* )NULL;
+ xfree(e->name);
+ e->name = NULL;
+ e->name_len = 0;
+ e->back_num = 0;
+ e->back_alloc = 0;
+ xfree(e->back_refs);
+ e->back_refs = (int* )NULL;
}
}
@@ -840,7 +840,7 @@ name_find(regex_t* reg, const UChar* name, const UChar* name_end)
for (i = 0; i < t->num; i++) {
e = &(t->e[i]);
if (len == e->name_len && onig_strncmp(name, e->name, len) == 0)
- return e;
+ return e;
}
}
return (NameEntry* )NULL;
@@ -858,8 +858,8 @@ onig_foreach_name(regex_t* reg,
for (i = 0; i < t->num; i++) {
e = &(t->e[i]);
r = (*func)(e->name, e->name + e->name_len, e->back_num,
- (e->back_num > 1 ? e->back_refs : &(e->back_ref1)),
- reg, arg);
+ (e->back_num > 1 ? e->back_refs : &(e->back_ref1)),
+ reg, arg);
if (r != 0) return r;
}
}
@@ -948,8 +948,8 @@ name_add(regex_t* reg, UChar* name, UChar* name_end, int backref, ScanEnv* env)
t->e = (NameEntry* )xmalloc(sizeof(NameEntry) * alloc);
if (IS_NULL(t->e)) {
- xfree(t);
- return ONIGERR_MEMORY;
+ xfree(t);
+ return ONIGERR_MEMORY;
}
t->alloc = alloc;
reg->name_table = t;
@@ -967,11 +967,11 @@ name_add(regex_t* reg, UChar* name, UChar* name_end, int backref, ScanEnv* env)
clear:
for (i = t->num; i < t->alloc; i++) {
- t->e[i].name = NULL;
- t->e[i].name_len = 0;
- t->e[i].back_num = 0;
- t->e[i].back_alloc = 0;
- t->e[i].back_refs = (int* )NULL;
+ t->e[i].name = NULL;
+ t->e[i].name_len = 0;
+ t->e[i].back_num = 0;
+ t->e[i].back_alloc = 0;
+ t->e[i].back_refs = (int* )NULL;
}
}
e = &(t->e[t->num]);
@@ -985,7 +985,7 @@ name_add(regex_t* reg, UChar* name, UChar* name_end, int backref, ScanEnv* env)
if (e->back_num >= 1 &&
! IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_MULTIPLEX_DEFINITION_NAME)) {
onig_scan_env_set_error_string(env, ONIGERR_MULTIPLEX_DEFINED_NAME,
- name, name_end);
+ name, name_end);
return ONIGERR_MULTIPLEX_DEFINED_NAME;
}
@@ -1004,12 +1004,12 @@ name_add(regex_t* reg, UChar* name, UChar* name_end, int backref, ScanEnv* env)
}
else {
if (e->back_num > e->back_alloc) {
- int* p;
- alloc = e->back_alloc * 2;
- p = (int* )xrealloc(e->back_refs, sizeof(int) * alloc);
- CHECK_NULL_RETURN_MEMERR(p);
- e->back_refs = p;
- e->back_alloc = alloc;
+ int* p;
+ alloc = e->back_alloc * 2;
+ p = (int* )xrealloc(e->back_refs, sizeof(int) * alloc);
+ CHECK_NULL_RETURN_MEMERR(p);
+ e->back_refs = p;
+ e->back_alloc = alloc;
}
e->back_refs[e->back_num - 1] = backref;
}
@@ -1020,7 +1020,7 @@ name_add(regex_t* reg, UChar* name, UChar* name_end, int backref, ScanEnv* env)
extern int
onig_name_to_group_numbers(regex_t* reg, const UChar* name,
- const UChar* name_end, int** nums)
+ const UChar* name_end, int** nums)
{
NameEntry* e = name_find(reg, name, name_end);
@@ -1042,7 +1042,7 @@ onig_name_to_group_numbers(regex_t* reg, const UChar* name,
extern int
onig_name_to_backref_number(regex_t* reg, const UChar* name,
- const UChar* name_end, const OnigRegion *region)
+ const UChar* name_end, const OnigRegion *region)
{
int i, n, *nums;
@@ -1056,8 +1056,8 @@ onig_name_to_backref_number(regex_t* reg, const UChar* name,
else {
if (IS_NOT_NULL(region)) {
for (i = n - 1; i >= 0; i--) {
- if (region->beg[nums[i]] != ONIG_REGION_NOTPOS)
- return nums[i];
+ if (region->beg[nums[i]] != ONIG_REGION_NOTPOS)
+ return nums[i];
}
}
return nums[n - 1];
@@ -1068,14 +1068,14 @@ onig_name_to_backref_number(regex_t* reg, const UChar* name,
extern int
onig_name_to_group_numbers(regex_t* reg, const UChar* name,
- const UChar* name_end, int** nums)
+ const UChar* name_end, int** nums)
{
return ONIG_NO_SUPPORT_CONFIG;
}
extern int
onig_name_to_backref_number(regex_t* reg, const UChar* name,
- const UChar* name_end, const OnigRegion* region)
+ const UChar* name_end, const OnigRegion* region)
{
return ONIG_NO_SUPPORT_CONFIG;
}
@@ -1164,20 +1164,20 @@ scan_env_add_mem_entry(ScanEnv* env)
if (need >= SCANENV_MEMNODES_SIZE) {
if (env->mem_alloc <= need) {
if (IS_NULL(env->mem_nodes_dynamic)) {
- alloc = INIT_SCANENV_MEMNODES_ALLOC_SIZE;
- p = (Node** )xmalloc(sizeof(Node*) * alloc);
- CHECK_NULL_RETURN_MEMERR(p);
- xmemcpy(p, env->mem_nodes_static,
- sizeof(Node*) * SCANENV_MEMNODES_SIZE);
+ alloc = INIT_SCANENV_MEMNODES_ALLOC_SIZE;
+ p = (Node** )xmalloc(sizeof(Node*) * alloc);
+ CHECK_NULL_RETURN_MEMERR(p);
+ xmemcpy(p, env->mem_nodes_static,
+ sizeof(Node*) * SCANENV_MEMNODES_SIZE);
}
else {
- alloc = env->mem_alloc * 2;
- p = (Node** )xrealloc(env->mem_nodes_dynamic, sizeof(Node*) * alloc);
- CHECK_NULL_RETURN_MEMERR(p);
+ alloc = env->mem_alloc * 2;
+ p = (Node** )xrealloc(env->mem_nodes_dynamic, sizeof(Node*) * alloc);
+ CHECK_NULL_RETURN_MEMERR(p);
}
for (i = env->num_mem + 1; i < alloc; i++)
- p[i] = NULL_NODE;
+ p[i] = NULL_NODE;
env->mem_nodes_dynamic = p;
env->mem_alloc = alloc;
@@ -1208,7 +1208,7 @@ onig_node_free(Node* node)
switch (NTYPE(node)) {
case NT_STR:
if (NSTR(node)->capa != 0 &&
- IS_NOT_NULL(NSTR(node)->s) && NSTR(node)->s != NSTR(node)->buf) {
+ IS_NOT_NULL(NSTR(node)->s) && NSTR(node)->s != NSTR(node)->buf) {
xfree(NSTR(node)->s);
}
break;
@@ -1371,9 +1371,9 @@ onig_node_new_anchor(int type)
static Node*
node_new_backref(int back_num, int* backrefs, int by_name,
#ifdef USE_BACKREF_WITH_LEVEL
- int exist_level, int nest_level,
+ int exist_level, int nest_level,
#endif
- ScanEnv* env)
+ ScanEnv* env)
{
int i;
Node* node = node_new();
@@ -1396,7 +1396,7 @@ node_new_backref(int back_num, int* backrefs, int by_name,
for (i = 0; i < back_num; i++) {
if (backrefs[i] <= env->num_mem &&
- IS_NULL(SCANENV_MEM_NODES(env)[backrefs[i]])) {
+ IS_NULL(SCANENV_MEM_NODES(env)[backrefs[i]])) {
NBREF(node)->state |= NST_RECURSION; /* /...(\1).../ */
break;
}
@@ -1521,18 +1521,18 @@ onig_node_str_cat(Node* node, const UChar* s, const UChar* end)
ptrdiff_t capa = len + addlen + NODE_STR_MARGIN;
if (capa <= NSTR(node)->capa) {
- onig_strcpy(NSTR(node)->s + len, s, end);
+ onig_strcpy(NSTR(node)->s + len, s, end);
}
else {
- if (NSTR(node)->s == NSTR(node)->buf)
- p = strcat_capa_from_static(NSTR(node)->s, NSTR(node)->end,
- s, end, capa);
- else
- p = strcat_capa(NSTR(node)->s, NSTR(node)->end, s, end, capa);
+ if (NSTR(node)->s == NSTR(node)->buf)
+ p = strcat_capa_from_static(NSTR(node)->s, NSTR(node)->end,
+ s, end, capa);
+ else
+ p = strcat_capa(NSTR(node)->s, NSTR(node)->end, s, end, capa);
- CHECK_NULL_RETURN_MEMERR(p);
- NSTR(node)->s = p;
- NSTR(node)->capa = (int )capa;
+ CHECK_NULL_RETURN_MEMERR(p);
+ NSTR(node)->s = p;
+ NSTR(node)->capa = (int )capa;
}
}
else {
@@ -1654,7 +1654,7 @@ str_node_split_last_char(StrNode* sn, OnigEncoding enc)
if (p && p > sn->s) { /* can be split. */
n = node_new_str(p, sn->end);
if (IS_NOT_NULL(n) && (sn->flag & NSTR_RAW) != 0)
- NSTRING_SET_RAW(n);
+ NSTRING_SET_RAW(n);
sn->end = (UChar* )p;
}
}
@@ -1702,7 +1702,7 @@ onig_scan_unsigned_number(UChar** src, const UChar* end, OnigEncoding enc)
if (ONIGENC_IS_CODE_DIGIT(enc, c)) {
val = (unsigned int )DIGITVAL(c);
if ((INT_MAX_LIMIT - val) / 10UL < num)
- return -1; /* overflow */
+ return -1; /* overflow */
num = num * 10 + val;
}
@@ -1717,7 +1717,7 @@ onig_scan_unsigned_number(UChar** src, const UChar* end, OnigEncoding enc)
static int
scan_unsigned_hexadecimal_number(UChar** src, UChar* end, int minlen,
- int maxlen, OnigEncoding enc)
+ int maxlen, OnigEncoding enc)
{
OnigCodePoint c;
unsigned int num, val;
@@ -1732,7 +1732,7 @@ scan_unsigned_hexadecimal_number(UChar** src, UChar* end, int minlen,
if (ONIGENC_IS_CODE_XDIGIT(enc, c)) {
val = (unsigned int )XDIGITVAL(enc,c);
if ((INT_MAX_LIMIT - val) / 16UL < num)
- return -1; /* overflow */
+ return -1; /* overflow */
num = (num << 4) + XDIGITVAL(enc,c);
}
@@ -1750,7 +1750,7 @@ scan_unsigned_hexadecimal_number(UChar** src, UChar* end, int minlen,
static int
scan_unsigned_octal_number(UChar** src, UChar* end, int maxlen,
- OnigEncoding enc)
+ OnigEncoding enc)
{
OnigCodePoint c;
unsigned int num, val;
@@ -1763,7 +1763,7 @@ scan_unsigned_octal_number(UChar** src, UChar* end, int maxlen,
if (ONIGENC_IS_CODE_DIGIT(enc, c) && c < '8') {
val = ODIGITVAL(c);
if ((INT_MAX_LIMIT - val) / 8UL < num)
- return -1; /* overflow */
+ return -1; /* overflow */
num = (num << 3) + val;
}
@@ -1804,7 +1804,7 @@ new_code_range(BBuf** pbuf)
static int
add_code_range_to_buf0(BBuf** pbuf, ScanEnv* env, OnigCodePoint from, OnigCodePoint to,
- int checkdup)
+ int checkdup)
{
int r, inc_n, pos;
OnigCodePoint low, high, bound, x;
@@ -1855,7 +1855,7 @@ add_code_range_to_buf0(BBuf** pbuf, ScanEnv* env, OnigCodePoint from, OnigCodePo
if (inc_n != 1) {
if (checkdup && from <= data[low*2+1]
- && (data[low*2] <= from || data[low*2+1] <= to))
+ && (data[low*2] <= from || data[low*2+1] <= to))
CC_DUP_WARN(env, from, to);
if (from > data[low*2])
from = data[low*2];
@@ -1869,8 +1869,8 @@ add_code_range_to_buf0(BBuf** pbuf, ScanEnv* env, OnigCodePoint from, OnigCodePo
if (inc_n > 0) {
if (high < n) {
- int size = (n - high) * 2 * SIZE_CODE_POINT;
- BBUF_MOVE_RIGHT(bbuf, from_pos, to_pos, size);
+ int size = (n - high) * 2 * SIZE_CODE_POINT;
+ BBUF_MOVE_RIGHT(bbuf, from_pos, to_pos, size);
}
}
else {
@@ -1980,10 +1980,10 @@ or_code_range_buf(OnigEncoding enc, BBuf* bbuf1, int not1,
}
else {
if (not2 == 0) {
- return bbuf_clone(pbuf, bbuf2);
+ return bbuf_clone(pbuf, bbuf2);
}
else {
- return not_code_range_buf(enc, bbuf2, pbuf, env);
+ return not_code_range_buf(enc, bbuf2, pbuf, env);
}
}
}
@@ -2014,7 +2014,7 @@ or_code_range_buf(OnigEncoding enc, BBuf* bbuf1, int not1,
static int
and_code_range1(BBuf** pbuf, ScanEnv* env, OnigCodePoint from1, OnigCodePoint to1,
- OnigCodePoint* data, int n)
+ OnigCodePoint* data, int n)
{
int i, r;
OnigCodePoint from2, to2;
@@ -2025,19 +2025,19 @@ and_code_range1(BBuf** pbuf, ScanEnv* env, OnigCodePoint from1, OnigCodePoint to
if (from2 < from1) {
if (to2 < from1) continue;
else {
- from1 = to2 + 1;
+ from1 = to2 + 1;
}
}
else if (from2 <= to1) {
if (to2 < to1) {
- if (from1 <= from2 - 1) {
- r = add_code_range_to_buf(pbuf, env, from1, from2-1);
- if (r != 0) return r;
- }
- from1 = to2 + 1;
+ if (from1 <= from2 - 1) {
+ r = add_code_range_to_buf(pbuf, env, from1, from2-1);
+ if (r != 0) return r;
+ }
+ from1 = to2 + 1;
}
else {
- to1 = from2 - 1;
+ to1 = from2 - 1;
}
}
else {
@@ -2086,14 +2086,14 @@ and_code_range_buf(BBuf* bbuf1, int not1, BBuf* bbuf2, int not2, BBuf** pbuf, Sc
from1 = data1[i*2];
to1 = data1[i*2+1];
for (j = 0; j < n2; j++) {
- from2 = data2[j*2];
- to2 = data2[j*2+1];
- if (from2 > to1) break;
- if (to2 < from1) continue;
- from = MAX(from1, from2);
- to = MIN(to1, to2);
- r = add_code_range_to_buf(pbuf, env, from, to);
- if (r != 0) return r;
+ from2 = data2[j*2];
+ to2 = data2[j*2+1];
+ if (from2 > to1) break;
+ if (to2 < from1) continue;
+ from = MAX(from1, from2);
+ to = MIN(to1, to2);
+ r = add_code_range_to_buf(pbuf, env, from, to);
+ if (r != 0) return r;
}
}
}
@@ -2149,10 +2149,10 @@ and_cclass(CClassNode* dest, CClassNode* cc, ScanEnv* env)
else {
r = and_code_range_buf(buf1, not1, buf2, not2, &pbuf, env);
if (r == 0 && not1 != 0) {
- BBuf *tbuf = 0;
- r = not_code_range_buf(enc, pbuf, &tbuf, env);
- bbuf_free(pbuf);
- pbuf = tbuf;
+ BBuf *tbuf = 0;
+ r = not_code_range_buf(enc, pbuf, &tbuf, env);
+ bbuf_free(pbuf);
+ pbuf = tbuf;
}
}
if (r != 0) {
@@ -2207,10 +2207,10 @@ or_cclass(CClassNode* dest, CClassNode* cc, ScanEnv* env)
else {
r = or_code_range_buf(enc, buf1, not1, buf2, not2, &pbuf, env);
if (r == 0 && not1 != 0) {
- BBuf *tbuf = 0;
- r = not_code_range_buf(enc, pbuf, &tbuf, env);
- bbuf_free(pbuf);
- pbuf = tbuf;
+ BBuf *tbuf = 0;
+ r = not_code_range_buf(enc, pbuf, &tbuf, env);
+ bbuf_free(pbuf);
+ pbuf = tbuf;
}
}
if (r != 0) {
@@ -2242,12 +2242,12 @@ conv_backslash_value(OnigCodePoint c, ScanEnv* env)
case 'e': return '\033';
case 'v':
if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_ESC_V_VTAB))
- return '\v';
+ return '\v';
break;
default:
if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z'))
- UNKNOWN_ESC_WARN(env, c);
+ UNKNOWN_ESC_WARN(env, c);
break;
}
}
@@ -2506,7 +2506,7 @@ fetch_range_quantifier(UChar** src, UChar* end, OnigToken* tok, ScanEnv* env)
if (p == prev) {
if (non_low != 0)
- goto invalid;
+ goto invalid;
up = REPEAT_INFINITE; /* {n,} : {n,infinite} */
}
}
@@ -2566,8 +2566,8 @@ fetch_escaped_value(UChar** src, UChar* end, ScanEnv* env, OnigCodePoint* val)
if (PEND) return ONIGERR_END_PATTERN_AT_META;
PFETCH_S(c);
if (c == MC_ESC(env->syntax)) {
- v = fetch_escaped_value(&p, end, env, &c);
- if (v < 0) return v;
+ v = fetch_escaped_value(&p, end, env, &c);
+ if (v < 0) return v;
}
c = ((c & 0xff) | 0x80);
}
@@ -2591,14 +2591,14 @@ fetch_escaped_value(UChar** src, UChar* end, ScanEnv* env, OnigCodePoint* val)
if (PEND) return ONIGERR_END_PATTERN_AT_CONTROL;
PFETCH_S(c);
if (c == '?') {
- c = 0177;
+ c = 0177;
}
else {
- if (c == MC_ESC(env->syntax)) {
- v = fetch_escaped_value(&p, end, env, &c);
- if (v < 0) return v;
- }
- c &= 0x9f;
+ if (c == MC_ESC(env->syntax)) {
+ v = fetch_escaped_value(&p, end, env, &c);
+ if (v < 0) return v;
+ }
+ c &= 0x9f;
}
break;
}
@@ -2649,8 +2649,8 @@ get_name_end_code_point(OnigCodePoint start)
*/
static int
fetch_name_with_level(OnigCodePoint start_code, UChar** src, UChar* end,
- UChar** rname_end, ScanEnv* env,
- int* rback_num, int* rlevel)
+ UChar** rname_end, ScanEnv* env,
+ int* rback_num, int* rlevel)
{
int r, sign, is_num, exist_level;
OnigCodePoint end_code;
@@ -2701,11 +2701,11 @@ fetch_name_with_level(OnigCodePoint start_code, UChar** src, UChar* end,
if (is_num != 0) {
if (ONIGENC_IS_CODE_DIGIT(enc, c)) {
- is_num = 1;
+ is_num = 1;
}
else {
- r = ONIGERR_INVALID_GROUP_NAME;
- is_num = 0;
+ r = ONIGERR_INVALID_GROUP_NAME;
+ is_num = 0;
}
}
else if (!ONIGENC_IS_CODE_NAME(enc, c)) {
@@ -2719,8 +2719,8 @@ fetch_name_with_level(OnigCodePoint start_code, UChar** src, UChar* end,
int flag = (c == '-' ? -1 : 1);
if (PEND) {
- r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
- goto end;
+ r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
+ goto end;
}
PFETCH(c);
if (! ONIGENC_IS_CODE_DIGIT(enc, c)) goto err;
@@ -2731,9 +2731,9 @@ fetch_name_with_level(OnigCodePoint start_code, UChar** src, UChar* end,
exist_level = 1;
if (!PEND) {
- PFETCH(c);
- if (c == end_code)
- goto end;
+ PFETCH(c);
+ if (c == end_code)
+ goto end;
}
}
@@ -2769,7 +2769,7 @@ fetch_name_with_level(OnigCodePoint start_code, UChar** src, UChar* end,
*/
static int
fetch_name(OnigCodePoint start_code, UChar** src, UChar* end,
- UChar** rname_end, ScanEnv* env, int* rback_num, int ref)
+ UChar** rname_end, ScanEnv* env, int* rback_num, int ref)
{
int r, is_num, sign;
OnigCodePoint end_code;
@@ -2798,21 +2798,21 @@ fetch_name(OnigCodePoint start_code, UChar** src, UChar* end,
if (ONIGENC_IS_CODE_DIGIT(enc, c)) {
if (ref == 1)
- is_num = 1;
+ is_num = 1;
else {
- r = ONIGERR_INVALID_GROUP_NAME;
- is_num = 0;
+ r = ONIGERR_INVALID_GROUP_NAME;
+ is_num = 0;
}
}
else if (c == '-') {
if (ref == 1) {
- is_num = 2;
- sign = -1;
- pnum_head = p;
+ is_num = 2;
+ sign = -1;
+ pnum_head = p;
}
else {
- r = ONIGERR_INVALID_GROUP_NAME;
- is_num = 0;
+ r = ONIGERR_INVALID_GROUP_NAME;
+ is_num = 0;
}
}
else if (!ONIGENC_IS_CODE_NAME(enc, c)) {
@@ -2825,30 +2825,30 @@ fetch_name(OnigCodePoint start_code, UChar** src, UChar* end,
name_end = p;
PFETCH_S(c);
if (c == end_code || c == ')') {
- if (is_num == 2) {
- r = ONIGERR_INVALID_GROUP_NAME;
- goto teardown;
- }
- break;
+ if (is_num == 2) {
+ r = ONIGERR_INVALID_GROUP_NAME;
+ goto teardown;
+ }
+ break;
}
if (is_num != 0) {
- if (ONIGENC_IS_CODE_DIGIT(enc, c)) {
- is_num = 1;
- }
- else {
- if (!ONIGENC_IS_CODE_WORD(enc, c))
- r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
- else
- r = ONIGERR_INVALID_GROUP_NAME;
- goto teardown;
- }
+ if (ONIGENC_IS_CODE_DIGIT(enc, c)) {
+ is_num = 1;
+ }
+ else {
+ if (!ONIGENC_IS_CODE_WORD(enc, c))
+ r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
+ else
+ r = ONIGERR_INVALID_GROUP_NAME;
+ goto teardown;
+ }
}
else {
- if (!ONIGENC_IS_CODE_NAME(enc, c)) {
- r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
- goto teardown;
- }
+ if (!ONIGENC_IS_CODE_NAME(enc, c)) {
+ r = ONIGERR_INVALID_CHAR_IN_GROUP_NAME;
+ goto teardown;
+ }
}
}
@@ -2862,8 +2862,8 @@ fetch_name(OnigCodePoint start_code, UChar** src, UChar* end,
*rback_num = onig_scan_unsigned_number(&pnum_head, name_end, enc);
if (*rback_num < 0) return ONIGERR_TOO_BIG_NUMBER;
else if (*rback_num == 0) {
- r = ONIGERR_INVALID_GROUP_NAME;
- goto err;
+ r = ONIGERR_INVALID_GROUP_NAME;
+ goto err;
}
*rback_num *= sign;
@@ -2879,7 +2879,7 @@ teardown:
name_end = p;
PFETCH_S(c);
if (c == end_code || c == ')')
- break;
+ break;
}
if (PEND)
name_end = end;
@@ -2892,7 +2892,7 @@ teardown:
#else
static int
fetch_name(OnigCodePoint start_code, UChar** src, UChar* end,
- UChar** rname_end, ScanEnv* env, int* rback_num, int ref)
+ UChar** rname_end, ScanEnv* env, int* rback_num, int ref)
{
int r, is_num, sign;
OnigCodePoint end_code;
@@ -2980,8 +2980,8 @@ onig_syntax_warn(ScanEnv *env, const char *fmt, ...)
UChar buf[WARN_BUFSIZE];
va_start(args, fmt);
onig_vsnprintf_with_pattern(buf, WARN_BUFSIZE, env->enc,
- env->pattern, env->pattern_end,
- fmt, args);
+ env->pattern, env->pattern_end,
+ fmt, args);
va_end(args);
#ifdef RUBY
if (env->sourcefile == NULL)
@@ -3043,7 +3043,7 @@ UNKNOWN_ESC_WARN(ScanEnv *env, int c)
static UChar*
find_str_position(OnigCodePoint s[], int n, UChar* from, UChar* to,
- UChar **next, OnigEncoding enc)
+ UChar **next, OnigEncoding enc)
{
int i;
OnigCodePoint x;
@@ -3055,14 +3055,14 @@ find_str_position(OnigCodePoint s[], int n, UChar* from, UChar* to,
q = p + enclen(enc, p, to);
if (x == s[0]) {
for (i = 1; i < n && q < to; i++) {
- x = ONIGENC_MBC_TO_CODE(enc, q, to);
- if (x != s[i]) break;
- q += enclen(enc, q, to);
+ x = ONIGENC_MBC_TO_CODE(enc, q, to);
+ if (x != s[i]) break;
+ q += enclen(enc, q, to);
}
if (i >= n) {
- if (IS_NOT_NULL(next))
- *next = q;
- return p;
+ if (IS_NOT_NULL(next))
+ *next = q;
+ return p;
}
}
p = q;
@@ -3072,7 +3072,7 @@ find_str_position(OnigCodePoint s[], int n, UChar* from, UChar* to,
static int
str_exist_check_with_esc(OnigCodePoint s[], int n, UChar* from, UChar* to,
- OnigCodePoint bad, OnigEncoding enc, const OnigSyntaxType* syn)
+ OnigCodePoint bad, OnigEncoding enc, const OnigSyntaxType* syn)
{
int i, in_esc;
OnigCodePoint x;
@@ -3089,19 +3089,19 @@ str_exist_check_with_esc(OnigCodePoint s[], int n, UChar* from, UChar* to,
x = ONIGENC_MBC_TO_CODE(enc, p, to);
q = p + enclen(enc, p, to);
if (x == s[0]) {
- for (i = 1; i < n && q < to; i++) {
- x = ONIGENC_MBC_TO_CODE(enc, q, to);
- if (x != s[i]) break;
- q += enclen(enc, q, to);
- }
- if (i >= n) return 1;
- p += enclen(enc, p, to);
+ for (i = 1; i < n && q < to; i++) {
+ x = ONIGENC_MBC_TO_CODE(enc, q, to);
+ if (x != s[i]) break;
+ q += enclen(enc, q, to);
+ }
+ if (i >= n) return 1;
+ p += enclen(enc, p, to);
}
else {
- x = ONIGENC_MBC_TO_CODE(enc, p, to);
- if (x == bad) return 0;
- else if (x == MC_ESC(syn)) in_esc = 1;
- p = q;
+ x = ONIGENC_MBC_TO_CODE(enc, p, to);
+ if (x == bad) return 0;
+ else if (x == MC_ESC(syn)) in_esc = 1;
+ p = q;
}
}
}
@@ -3195,22 +3195,22 @@ fetch_token_in_cc(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
c2 = PPEEK;
if (c2 == '{' &&
- IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY)) {
- PINC;
- tok->type = TK_CHAR_PROPERTY;
- tok->u.prop.not = (c == 'P' ? 1 : 0);
-
- if (!PEND && IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT)) {
- PFETCH(c2);
- if (c2 == '^') {
- tok->u.prop.not = (tok->u.prop.not == 0 ? 1 : 0);
- }
- else
- PUNFETCH;
- }
+ IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY)) {
+ PINC;
+ tok->type = TK_CHAR_PROPERTY;
+ tok->u.prop.not = (c == 'P' ? 1 : 0);
+
+ if (!PEND && IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT)) {
+ PFETCH(c2);
+ if (c2 == '^') {
+ tok->u.prop.not = (tok->u.prop.not == 0 ? 1 : 0);
+ }
+ else
+ PUNFETCH;
+ }
}
else {
- onig_syntax_warn(env, "invalid Unicode Property \\%c", c);
+ onig_syntax_warn(env, "invalid Unicode Property \\%c", c);
}
break;
@@ -3219,35 +3219,35 @@ fetch_token_in_cc(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
prev = p;
if (PPEEK_IS('{') && IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_X_BRACE_HEX8)) {
- PINC;
- num = scan_unsigned_hexadecimal_number(&p, end, 0, 8, enc);
- if (num < 0) return ONIGERR_TOO_BIG_WIDE_CHAR_VALUE;
- if (!PEND) {
- c2 = PPEEK;
- if (ONIGENC_IS_CODE_XDIGIT(enc, c2))
- return ONIGERR_TOO_LONG_WIDE_CHAR_VALUE;
- }
-
- if (p > prev + enclen(enc, prev, end) && !PEND && (PPEEK_IS('}'))) {
- PINC;
- tok->type = TK_CODE_POINT;
- tok->base = 16;
- tok->u.code = (OnigCodePoint )num;
- }
- else {
- /* can't read nothing or invalid format */
- p = prev;
- }
+ PINC;
+ num = scan_unsigned_hexadecimal_number(&p, end, 0, 8, enc);
+ if (num < 0) return ONIGERR_TOO_BIG_WIDE_CHAR_VALUE;
+ if (!PEND) {
+ c2 = PPEEK;
+ if (ONIGENC_IS_CODE_XDIGIT(enc, c2))
+ return ONIGERR_TOO_LONG_WIDE_CHAR_VALUE;
+ }
+
+ if (p > prev + enclen(enc, prev, end) && !PEND && (PPEEK_IS('}'))) {
+ PINC;
+ tok->type = TK_CODE_POINT;
+ tok->base = 16;
+ tok->u.code = (OnigCodePoint )num;
+ }
+ else {
+ /* can't read nothing or invalid format */
+ p = prev;
+ }
}
else if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_X_HEX2)) {
- num = scan_unsigned_hexadecimal_number(&p, end, 0, 2, enc);
- if (num < 0) return ONIGERR_TOO_BIG_NUMBER;
- if (p == prev) { /* can't read nothing. */
- num = 0; /* but, it's not error */
- }
- tok->type = TK_RAW_BYTE;
- tok->base = 16;
- tok->u.c = num;
+ num = scan_unsigned_hexadecimal_number(&p, end, 0, 2, enc);
+ if (num < 0) return ONIGERR_TOO_BIG_NUMBER;
+ if (p == prev) { /* can't read nothing. */
+ num = 0; /* but, it's not error */
+ }
+ tok->type = TK_RAW_BYTE;
+ tok->base = 16;
+ tok->u.c = num;
}
break;
@@ -3256,15 +3256,15 @@ fetch_token_in_cc(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
prev = p;
if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_U_HEX4)) {
- num = scan_unsigned_hexadecimal_number(&p, end, 4, 4, enc);
- if (num < -1) return ONIGERR_TOO_SHORT_DIGITS;
- else if (num < 0) return ONIGERR_TOO_BIG_NUMBER;
- if (p == prev) { /* can't read nothing. */
- num = 0; /* but, it's not error */
- }
- tok->type = TK_CODE_POINT;
- tok->base = 16;
- tok->u.code = (OnigCodePoint )num;
+ num = scan_unsigned_hexadecimal_number(&p, end, 4, 4, enc);
+ if (num < -1) return ONIGERR_TOO_SHORT_DIGITS;
+ else if (num < 0) return ONIGERR_TOO_BIG_NUMBER;
+ if (p == prev) { /* can't read nothing. */
+ num = 0; /* but, it's not error */
+ }
+ tok->type = TK_CODE_POINT;
+ tok->base = 16;
+ tok->u.code = (OnigCodePoint )num;
}
break;
@@ -3273,41 +3273,41 @@ fetch_token_in_cc(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
prev = p;
if (PPEEK_IS('{') && IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_O_BRACE_OCTAL)) {
- PINC;
- num = scan_unsigned_octal_number(&p, end, 11, enc);
- if (num < 0) return ONIGERR_TOO_BIG_WIDE_CHAR_VALUE;
- if (!PEND) {
- c2 = PPEEK;
- if (ONIGENC_IS_CODE_DIGIT(enc, c2) && c2 < '8')
- return ONIGERR_TOO_LONG_WIDE_CHAR_VALUE;
- }
-
- if (p > prev + enclen(enc, prev, end) && !PEND && (PPEEK_IS('}'))) {
- PINC;
- tok->type = TK_CODE_POINT;
- tok->base = 8;
- tok->u.code = (OnigCodePoint )num;
- }
- else {
- /* can't read nothing or invalid format */
- p = prev;
- }
+ PINC;
+ num = scan_unsigned_octal_number(&p, end, 11, enc);
+ if (num < 0) return ONIGERR_TOO_BIG_WIDE_CHAR_VALUE;
+ if (!PEND) {
+ c2 = PPEEK;
+ if (ONIGENC_IS_CODE_DIGIT(enc, c2) && c2 < '8')
+ return ONIGERR_TOO_LONG_WIDE_CHAR_VALUE;
+ }
+
+ if (p > prev + enclen(enc, prev, end) && !PEND && (PPEEK_IS('}'))) {
+ PINC;
+ tok->type = TK_CODE_POINT;
+ tok->base = 8;
+ tok->u.code = (OnigCodePoint )num;
+ }
+ else {
+ /* can't read nothing or invalid format */
+ p = prev;
+ }
}
break;
case '0':
case '1': case '2': case '3': case '4': case '5': case '6': case '7':
if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_OCTAL3)) {
- PUNFETCH;
- prev = p;
- num = scan_unsigned_octal_number(&p, end, 3, enc);
- if (num < 0 || 0xff < num) return ONIGERR_TOO_BIG_NUMBER;
- if (p == prev) { /* can't read nothing. */
- num = 0; /* but, it's not error */
- }
- tok->type = TK_RAW_BYTE;
- tok->base = 8;
- tok->u.c = num;
+ PUNFETCH;
+ prev = p;
+ num = scan_unsigned_octal_number(&p, end, 3, enc);
+ if (num < 0 || 0xff < num) return ONIGERR_TOO_BIG_NUMBER;
+ if (p == prev) { /* can't read nothing. */
+ num = 0; /* but, it's not error */
+ }
+ tok->type = TK_RAW_BYTE;
+ tok->base = 8;
+ tok->u.c = num;
}
break;
@@ -3316,8 +3316,8 @@ fetch_token_in_cc(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
num = fetch_escaped_value(&p, end, env, &c2);
if (num < 0) return num;
if ((OnigCodePoint )tok->u.c != c2) {
- tok->u.code = (OnigCodePoint )c2;
- tok->type = TK_CODE_POINT;
+ tok->u.code = (OnigCodePoint )c2;
+ tok->type = TK_CODE_POINT;
}
break;
}
@@ -3329,26 +3329,26 @@ fetch_token_in_cc(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
PINC;
if (str_exist_check_with_esc(send, 2, p, end,
(OnigCodePoint )']', enc, syn)) {
- tok->type = TK_POSIX_BRACKET_OPEN;
+ tok->type = TK_POSIX_BRACKET_OPEN;
}
else {
- PUNFETCH;
- goto cc_in_cc;
+ PUNFETCH;
+ goto cc_in_cc;
}
}
else {
cc_in_cc:
if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_CCLASS_SET_OP)) {
- tok->type = TK_CC_CC_OPEN;
+ tok->type = TK_CC_CC_OPEN;
}
else {
- CC_ESC_WARN(env, (UChar* )"[");
+ CC_ESC_WARN(env, (UChar* )"[");
}
}
}
else if (c == '&') {
if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_CCLASS_SET_OP) &&
- !PEND && (PPEEK_IS('&'))) {
+ !PEND && (PPEEK_IS('&'))) {
PINC;
tok->type = TK_CC_AND;
}
@@ -3362,7 +3362,7 @@ fetch_token_in_cc(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
#ifdef USE_NAMED_GROUP
static int
fetch_named_backref_token(OnigCodePoint c, OnigToken* tok, UChar** src,
- UChar* end, ScanEnv* env)
+ UChar* end, ScanEnv* env)
{
int r, num;
const OnigSyntaxType* syn = env->syntax;
@@ -3377,7 +3377,7 @@ fetch_named_backref_token(OnigCodePoint c, OnigToken* tok, UChar** src,
# ifdef USE_BACKREF_WITH_LEVEL
name_end = NULL_UCHARP; /* no need. escape gcc warning. */
r = fetch_name_with_level(c, &p, end, &name_end,
- env, &back_num, &tok->u.backref.level);
+ env, &back_num, &tok->u.backref.level);
if (r == 1) tok->u.backref.exist_level = 1;
else tok->u.backref.exist_level = 0;
# else
@@ -3389,13 +3389,13 @@ fetch_named_backref_token(OnigCodePoint c, OnigToken* tok, UChar** src,
if (back_num < 0) {
back_num = BACKREF_REL_TO_ABS(back_num, env);
if (back_num <= 0)
- return ONIGERR_INVALID_BACKREF;
+ return ONIGERR_INVALID_BACKREF;
}
if (IS_SYNTAX_BV(syn, ONIG_SYN_STRICT_CHECK_BACKREF)) {
if (back_num > env->num_mem ||
- IS_NULL(SCANENV_MEM_NODES(env)[back_num]))
- return ONIGERR_INVALID_BACKREF;
+ IS_NULL(SCANENV_MEM_NODES(env)[back_num]))
+ return ONIGERR_INVALID_BACKREF;
}
tok->type = TK_BACKREF;
tok->u.backref.by_name = 0;
@@ -3406,15 +3406,15 @@ fetch_named_backref_token(OnigCodePoint c, OnigToken* tok, UChar** src,
num = onig_name_to_group_numbers(env->reg, prev, name_end, &backs);
if (num <= 0) {
onig_scan_env_set_error_string(env,
- ONIGERR_UNDEFINED_NAME_REFERENCE, prev, name_end);
+ ONIGERR_UNDEFINED_NAME_REFERENCE, prev, name_end);
return ONIGERR_UNDEFINED_NAME_REFERENCE;
}
if (IS_SYNTAX_BV(syn, ONIG_SYN_STRICT_CHECK_BACKREF)) {
int i;
for (i = 0; i < num; i++) {
- if (backs[i] > env->num_mem ||
- IS_NULL(SCANENV_MEM_NODES(env)[backs[i]]))
- return ONIGERR_INVALID_BACKREF;
+ if (backs[i] > env->num_mem ||
+ IS_NULL(SCANENV_MEM_NODES(env)[backs[i]]))
+ return ONIGERR_INVALID_BACKREF;
}
}
@@ -3488,26 +3488,26 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
tok->u.repeat.upper = 1;
greedy_check:
if (!PEND && PPEEK_IS('?') &&
- IS_SYNTAX_OP(syn, ONIG_SYN_OP_QMARK_NON_GREEDY)) {
- PFETCH(c);
- tok->u.repeat.greedy = 0;
- tok->u.repeat.possessive = 0;
+ IS_SYNTAX_OP(syn, ONIG_SYN_OP_QMARK_NON_GREEDY)) {
+ PFETCH(c);
+ tok->u.repeat.greedy = 0;
+ tok->u.repeat.possessive = 0;
}
else {
possessive_check:
- if (!PEND && PPEEK_IS('+') &&
- ((IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_PLUS_POSSESSIVE_REPEAT) &&
- tok->type != TK_INTERVAL) ||
- (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_PLUS_POSSESSIVE_INTERVAL) &&
- tok->type == TK_INTERVAL))) {
- PFETCH(c);
- tok->u.repeat.greedy = 1;
- tok->u.repeat.possessive = 1;
- }
- else {
- tok->u.repeat.greedy = 1;
- tok->u.repeat.possessive = 0;
- }
+ if (!PEND && PPEEK_IS('+') &&
+ ((IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_PLUS_POSSESSIVE_REPEAT) &&
+ tok->type != TK_INTERVAL) ||
+ (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_PLUS_POSSESSIVE_INTERVAL) &&
+ tok->type == TK_INTERVAL))) {
+ PFETCH(c);
+ tok->u.repeat.greedy = 1;
+ tok->u.repeat.possessive = 1;
+ }
+ else {
+ tok->u.repeat.greedy = 1;
+ tok->u.repeat.possessive = 0;
+ }
}
break;
@@ -3517,10 +3517,10 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
if (r < 0) return r; /* error */
if (r == 0) goto greedy_check;
else if (r == 2) { /* {n} */
- if (IS_SYNTAX_BV(syn, ONIG_SYN_FIXED_INTERVAL_IS_GREEDY_ONLY))
- goto possessive_check;
+ if (IS_SYNTAX_BV(syn, ONIG_SYN_FIXED_INTERVAL_IS_GREEDY_ONLY))
+ goto possessive_check;
- goto greedy_check;
+ goto greedy_check;
}
/* r == 1 : normal char */
break;
@@ -3559,7 +3559,7 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
tok->type = TK_ANCHOR;
tok->u.anchor.subtype = ANCHOR_WORD_BOUND;
tok->u.anchor.ascii_range = IS_ASCII_RANGE(env->option)
- && ! IS_WORD_BOUND_ALL_RANGE(env->option);
+ && ! IS_WORD_BOUND_ALL_RANGE(env->option);
break;
case 'B':
@@ -3567,7 +3567,7 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
tok->type = TK_ANCHOR;
tok->u.anchor.subtype = ANCHOR_NOT_WORD_BOUND;
tok->u.anchor.ascii_range = IS_ASCII_RANGE(env->option)
- && ! IS_WORD_BOUND_ALL_RANGE(env->option);
+ && ! IS_WORD_BOUND_ALL_RANGE(env->option);
break;
#ifdef USE_WORD_BEGIN_END
@@ -3669,33 +3669,33 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
prev = p;
if (PPEEK_IS('{') && IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_X_BRACE_HEX8)) {
- PINC;
- num = scan_unsigned_hexadecimal_number(&p, end, 0, 8, enc);
- if (num < 0) return ONIGERR_TOO_BIG_WIDE_CHAR_VALUE;
- if (!PEND) {
- if (ONIGENC_IS_CODE_XDIGIT(enc, PPEEK))
- return ONIGERR_TOO_LONG_WIDE_CHAR_VALUE;
- }
-
- if ((p > prev + enclen(enc, prev, end)) && !PEND && PPEEK_IS('}')) {
- PINC;
- tok->type = TK_CODE_POINT;
- tok->u.code = (OnigCodePoint )num;
- }
- else {
- /* can't read nothing or invalid format */
- p = prev;
- }
+ PINC;
+ num = scan_unsigned_hexadecimal_number(&p, end, 0, 8, enc);
+ if (num < 0) return ONIGERR_TOO_BIG_WIDE_CHAR_VALUE;
+ if (!PEND) {
+ if (ONIGENC_IS_CODE_XDIGIT(enc, PPEEK))
+ return ONIGERR_TOO_LONG_WIDE_CHAR_VALUE;
+ }
+
+ if ((p > prev + enclen(enc, prev, end)) && !PEND && PPEEK_IS('}')) {
+ PINC;
+ tok->type = TK_CODE_POINT;
+ tok->u.code = (OnigCodePoint )num;
+ }
+ else {
+ /* can't read nothing or invalid format */
+ p = prev;
+ }
}
else if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_X_HEX2)) {
- num = scan_unsigned_hexadecimal_number(&p, end, 0, 2, enc);
- if (num < 0) return ONIGERR_TOO_BIG_NUMBER;
- if (p == prev) { /* can't read nothing. */
- num = 0; /* but, it's not error */
- }
- tok->type = TK_RAW_BYTE;
- tok->base = 16;
- tok->u.c = num;
+ num = scan_unsigned_hexadecimal_number(&p, end, 0, 2, enc);
+ if (num < 0) return ONIGERR_TOO_BIG_NUMBER;
+ if (p == prev) { /* can't read nothing. */
+ num = 0; /* but, it's not error */
+ }
+ tok->type = TK_RAW_BYTE;
+ tok->base = 16;
+ tok->u.c = num;
}
break;
@@ -3704,15 +3704,15 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
prev = p;
if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_U_HEX4)) {
- num = scan_unsigned_hexadecimal_number(&p, end, 4, 4, enc);
- if (num < -1) return ONIGERR_TOO_SHORT_DIGITS;
- else if (num < 0) return ONIGERR_TOO_BIG_NUMBER;
- if (p == prev) { /* can't read nothing. */
- num = 0; /* but, it's not error */
- }
- tok->type = TK_CODE_POINT;
- tok->base = 16;
- tok->u.code = (OnigCodePoint )num;
+ num = scan_unsigned_hexadecimal_number(&p, end, 4, 4, enc);
+ if (num < -1) return ONIGERR_TOO_SHORT_DIGITS;
+ else if (num < 0) return ONIGERR_TOO_BIG_NUMBER;
+ if (p == prev) { /* can't read nothing. */
+ num = 0; /* but, it's not error */
+ }
+ tok->type = TK_CODE_POINT;
+ tok->base = 16;
+ tok->u.code = (OnigCodePoint )num;
}
break;
@@ -3721,24 +3721,24 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
prev = p;
if (PPEEK_IS('{') && IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_O_BRACE_OCTAL)) {
- PINC;
- num = scan_unsigned_octal_number(&p, end, 11, enc);
- if (num < 0) return ONIGERR_TOO_BIG_WIDE_CHAR_VALUE;
- if (!PEND) {
- OnigCodePoint c = PPEEK;
- if (ONIGENC_IS_CODE_DIGIT(enc, c) && c < '8')
- return ONIGERR_TOO_LONG_WIDE_CHAR_VALUE;
- }
-
- if ((p > prev + enclen(enc, prev, end)) && !PEND && PPEEK_IS('}')) {
- PINC;
- tok->type = TK_CODE_POINT;
- tok->u.code = (OnigCodePoint )num;
- }
- else {
- /* can't read nothing or invalid format */
- p = prev;
- }
+ PINC;
+ num = scan_unsigned_octal_number(&p, end, 11, enc);
+ if (num < 0) return ONIGERR_TOO_BIG_WIDE_CHAR_VALUE;
+ if (!PEND) {
+ OnigCodePoint c = PPEEK;
+ if (ONIGENC_IS_CODE_DIGIT(enc, c) && c < '8')
+ return ONIGERR_TOO_LONG_WIDE_CHAR_VALUE;
+ }
+
+ if ((p > prev + enclen(enc, prev, end)) && !PEND && PPEEK_IS('}')) {
+ PINC;
+ tok->type = TK_CODE_POINT;
+ tok->u.code = (OnigCodePoint )num;
+ }
+ else {
+ /* can't read nothing or invalid format */
+ p = prev;
+ }
}
break;
@@ -3748,64 +3748,64 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
prev = p;
num = onig_scan_unsigned_number(&p, end, enc);
if (num < 0 || num > ONIG_MAX_BACKREF_NUM) {
- goto skip_backref;
+ goto skip_backref;
}
if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_DECIMAL_BACKREF) &&
- (num <= env->num_mem || num <= 9)) { /* This spec. from GNU regex */
- if (IS_SYNTAX_BV(syn, ONIG_SYN_STRICT_CHECK_BACKREF)) {
- if (num > env->num_mem || IS_NULL(SCANENV_MEM_NODES(env)[num]))
- return ONIGERR_INVALID_BACKREF;
- }
-
- tok->type = TK_BACKREF;
- tok->u.backref.num = 1;
- tok->u.backref.ref1 = num;
- tok->u.backref.by_name = 0;
+ (num <= env->num_mem || num <= 9)) { /* This spec. from GNU regex */
+ if (IS_SYNTAX_BV(syn, ONIG_SYN_STRICT_CHECK_BACKREF)) {
+ if (num > env->num_mem || IS_NULL(SCANENV_MEM_NODES(env)[num]))
+ return ONIGERR_INVALID_BACKREF;
+ }
+
+ tok->type = TK_BACKREF;
+ tok->u.backref.num = 1;
+ tok->u.backref.ref1 = num;
+ tok->u.backref.by_name = 0;
#ifdef USE_BACKREF_WITH_LEVEL
- tok->u.backref.exist_level = 0;
+ tok->u.backref.exist_level = 0;
#endif
- break;
+ break;
}
skip_backref:
if (c == '8' || c == '9') {
- /* normal char */
- p = prev; PINC;
- break;
+ /* normal char */
+ p = prev; PINC;
+ break;
}
p = prev;
/* fall through */
case '0':
if (IS_SYNTAX_OP(syn, ONIG_SYN_OP_ESC_OCTAL3)) {
- prev = p;
- num = scan_unsigned_octal_number(&p, end, (c == '0' ? 2:3), enc);
- if (num < 0 || 0xff < num) return ONIGERR_TOO_BIG_NUMBER;
- if (p == prev) { /* can't read nothing. */
- num = 0; /* but, it's not error */
- }
- tok->type = TK_RAW_BYTE;
- tok->base = 8;
- tok->u.c = num;
+ prev = p;
+ num = scan_unsigned_octal_number(&p, end, (c == '0' ? 2:3), enc);
+ if (num < 0 || 0xff < num) return ONIGERR_TOO_BIG_NUMBER;
+ if (p == prev) { /* can't read nothing. */
+ num = 0; /* but, it's not error */
+ }
+ tok->type = TK_RAW_BYTE;
+ tok->base = 8;
+ tok->u.c = num;
}
else if (c != '0') {
- PINC;
+ PINC;
}
break;
#ifdef USE_NAMED_GROUP
case 'k':
if (!PEND && IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_K_NAMED_BACKREF)) {
- PFETCH(c);
- if (c == '<' || c == '\'') {
- r = fetch_named_backref_token(c, tok, &p, end, env);
- if (r < 0) return r;
- }
- else {
- PUNFETCH;
- onig_syntax_warn(env, "invalid back reference");
- }
+ PFETCH(c);
+ if (c == '<' || c == '\'') {
+ r = fetch_named_backref_token(c, tok, &p, end, env);
+ if (r < 0) return r;
+ }
+ else {
+ PUNFETCH;
+ onig_syntax_warn(env, "invalid back reference");
+ }
}
break;
#endif
@@ -3814,52 +3814,52 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
case 'g':
# ifdef USE_NAMED_GROUP
if (!PEND && IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_G_BRACE_BACKREF)) {
- PFETCH(c);
- if (c == '{') {
- r = fetch_named_backref_token(c, tok, &p, end, env);
- if (r < 0) return r;
- }
- else
- PUNFETCH;
+ PFETCH(c);
+ if (c == '{') {
+ r = fetch_named_backref_token(c, tok, &p, end, env);
+ if (r < 0) return r;
+ }
+ else
+ PUNFETCH;
}
# endif
# ifdef USE_SUBEXP_CALL
if (!PEND && IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_G_SUBEXP_CALL)) {
- PFETCH(c);
- if (c == '<' || c == '\'') {
- int gnum = -1, rel = 0;
- UChar* name_end;
- OnigCodePoint cnext;
-
- cnext = PPEEK;
- if (cnext == '0') {
- PINC;
- if (PPEEK_IS(get_name_end_code_point(c))) { /* \g<0>, \g'0' */
- PINC;
- name_end = p;
- gnum = 0;
- }
- }
- else if (cnext == '+') {
- PINC;
- rel = 1;
- }
- prev = p;
- if (gnum < 0) {
- r = fetch_name((OnigCodePoint )c, &p, end, &name_end, env, &gnum, 1);
- if (r < 0) return r;
- }
-
- tok->type = TK_CALL;
- tok->u.call.name = prev;
- tok->u.call.name_end = name_end;
- tok->u.call.gnum = gnum;
- tok->u.call.rel = rel;
- }
- else {
- onig_syntax_warn(env, "invalid subexp call");
- PUNFETCH;
- }
+ PFETCH(c);
+ if (c == '<' || c == '\'') {
+ int gnum = -1, rel = 0;
+ UChar* name_end;
+ OnigCodePoint cnext;
+
+ cnext = PPEEK;
+ if (cnext == '0') {
+ PINC;
+ if (PPEEK_IS(get_name_end_code_point(c))) { /* \g<0>, \g'0' */
+ PINC;
+ name_end = p;
+ gnum = 0;
+ }
+ }
+ else if (cnext == '+') {
+ PINC;
+ rel = 1;
+ }
+ prev = p;
+ if (gnum < 0) {
+ r = fetch_name((OnigCodePoint )c, &p, end, &name_end, env, &gnum, 1);
+ if (r < 0) return r;
+ }
+
+ tok->type = TK_CALL;
+ tok->u.call.name = prev;
+ tok->u.call.name_end = name_end;
+ tok->u.call.gnum = gnum;
+ tok->u.call.rel = rel;
+ }
+ else {
+ onig_syntax_warn(env, "invalid subexp call");
+ PUNFETCH;
+ }
}
# endif
break;
@@ -3867,65 +3867,65 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
case 'Q':
if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_CAPITAL_Q_QUOTE)) {
- tok->type = TK_QUOTE_OPEN;
+ tok->type = TK_QUOTE_OPEN;
}
break;
case 'p':
case 'P':
if (PPEEK_IS('{') &&
- IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY)) {
- PINC;
- tok->type = TK_CHAR_PROPERTY;
- tok->u.prop.not = (c == 'P' ? 1 : 0);
-
- if (!PEND && IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT)) {
- PFETCH(c);
- if (c == '^') {
- tok->u.prop.not = (tok->u.prop.not == 0 ? 1 : 0);
- }
- else
- PUNFETCH;
- }
+ IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CHAR_PROPERTY)) {
+ PINC;
+ tok->type = TK_CHAR_PROPERTY;
+ tok->u.prop.not = (c == 'P' ? 1 : 0);
+
+ if (!PEND && IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_P_BRACE_CIRCUMFLEX_NOT)) {
+ PFETCH(c);
+ if (c == '^') {
+ tok->u.prop.not = (tok->u.prop.not == 0 ? 1 : 0);
+ }
+ else
+ PUNFETCH;
+ }
}
else {
- onig_syntax_warn(env, "invalid Unicode Property \\%c", c);
+ onig_syntax_warn(env, "invalid Unicode Property \\%c", c);
}
break;
case 'R':
if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_CAPITAL_R_LINEBREAK)) {
- tok->type = TK_LINEBREAK;
+ tok->type = TK_LINEBREAK;
}
break;
case 'X':
if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_CAPITAL_X_EXTENDED_GRAPHEME_CLUSTER)) {
- tok->type = TK_EXTENDED_GRAPHEME_CLUSTER;
+ tok->type = TK_EXTENDED_GRAPHEME_CLUSTER;
}
break;
case 'K':
if (IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_ESC_CAPITAL_K_KEEP)) {
- tok->type = TK_KEEP;
+ tok->type = TK_KEEP;
}
break;
default:
{
- OnigCodePoint c2;
-
- PUNFETCH;
- num = fetch_escaped_value(&p, end, env, &c2);
- if (num < 0) return num;
- /* set_raw: */
- if ((OnigCodePoint )tok->u.c != c2) {
- tok->type = TK_CODE_POINT;
- tok->u.code = (OnigCodePoint )c2;
- }
- else { /* string */
- p = tok->backp + enclen(enc, tok->backp, end);
- }
+ OnigCodePoint c2;
+
+ PUNFETCH;
+ num = fetch_escaped_value(&p, end, env, &c2);
+ if (num < 0) return num;
+ /* set_raw: */
+ if ((OnigCodePoint )tok->u.c != c2) {
+ tok->type = TK_CODE_POINT;
+ tok->u.code = (OnigCodePoint )c2;
+ }
+ else { /* string */
+ p = tok->backp + enclen(enc, tok->backp, end);
+ }
}
break;
}
@@ -3936,18 +3936,18 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
#ifdef USE_VARIABLE_META_CHARS
if ((c != ONIG_INEFFECTIVE_META_CHAR) &&
- IS_SYNTAX_OP(syn, ONIG_SYN_OP_VARIABLE_META_CHARACTERS)) {
+ IS_SYNTAX_OP(syn, ONIG_SYN_OP_VARIABLE_META_CHARACTERS)) {
if (c == MC_ANYCHAR(syn))
- goto any_char;
+ goto any_char;
else if (c == MC_ANYTIME(syn))
- goto anytime;
+ goto anytime;
else if (c == MC_ZERO_OR_ONE_TIME(syn))
- goto zero_or_one_time;
+ goto zero_or_one_time;
else if (c == MC_ONE_OR_MORE_TIME(syn))
- goto one_or_more_time;
+ goto one_or_more_time;
else if (c == MC_ANYCHAR_ANYTIME(syn)) {
- tok->type = TK_ANYCHAR_ANYTIME;
- goto out;
+ tok->type = TK_ANYCHAR_ANYTIME;
+ goto out;
}
}
#endif
@@ -4000,10 +4000,10 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
if (r < 0) return r; /* error */
if (r == 0) goto greedy_check;
else if (r == 2) { /* {n} */
- if (IS_SYNTAX_BV(syn, ONIG_SYN_FIXED_INTERVAL_IS_GREEDY_ONLY))
- goto possessive_check;
+ if (IS_SYNTAX_BV(syn, ONIG_SYN_FIXED_INTERVAL_IS_GREEDY_ONLY))
+ goto possessive_check;
- goto greedy_check;
+ goto greedy_check;
}
/* r == 1 : normal char */
break;
@@ -4015,114 +4015,118 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
case '(':
if (PPEEK_IS('?') &&
- IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_QMARK_GROUP_EFFECT)) {
- PINC;
- if (PPEEK_IS('#')) {
- PFETCH(c);
- while (1) {
- if (PEND) return ONIGERR_END_PATTERN_IN_GROUP;
- PFETCH(c);
- if (c == MC_ESC(syn)) {
- if (!PEND) PFETCH(c);
- }
- else {
- if (c == ')') break;
- }
- }
- goto start;
- }
+ IS_SYNTAX_OP2(syn, ONIG_SYN_OP2_QMARK_GROUP_EFFECT)) {
+ PINC;
+ if (PPEEK_IS('#')) {
+ PFETCH(c);
+ while (1) {
+ if (PEND) return ONIGERR_END_PATTERN_IN_GROUP;
+ PFETCH(c);
+ if (c == MC_ESC(syn)) {
+ if (!PEND) PFETCH(c);
+ }
+ else {
+ if (c == ')') break;
+ }
+ }
+ goto start;
+ }
#ifdef USE_PERL_SUBEXP_CALL
- /* (?&name), (?n), (?R), (?0), (?+n), (?-n) */
- c = PPEEK;
- if ((c == '&' || c == 'R' || ONIGENC_IS_CODE_DIGIT(enc, c)) &&
- IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_SUBEXP_CALL)) {
- /* (?&name), (?n), (?R), (?0) */
- int gnum;
- UChar *name;
- UChar *name_end;
-
- if (c == 'R' || c == '0') {
- PINC; /* skip 'R' / '0' */
- if (!PPEEK_IS(')')) return ONIGERR_INVALID_GROUP_NAME;
- PINC; /* skip ')' */
- name_end = name = p;
- gnum = 0;
- }
- else {
- int numref = 1;
- if (c == '&') { /* (?&name) */
- PINC;
- numref = 0; /* don't allow number name */
- }
- name = p;
- r = fetch_name((OnigCodePoint )'(', &p, end, &name_end, env, &gnum, numref);
- if (r < 0) return r;
- }
-
- tok->type = TK_CALL;
- tok->u.call.name = name;
- tok->u.call.name_end = name_end;
- tok->u.call.gnum = gnum;
- tok->u.call.rel = 0;
- break;
- }
- else if ((c == '-' || c == '+') &&
- IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_SUBEXP_CALL)) {
- /* (?+n), (?-n) */
- int gnum;
- UChar *name;
- UChar *name_end;
- OnigCodePoint cnext;
- PFETCH_READY;
-
- PINC; /* skip '-' / '+' */
- cnext = PPEEK;
- if (ONIGENC_IS_CODE_DIGIT(enc, cnext)) {
- if (c == '-') PUNFETCH;
- name = p;
- r = fetch_name((OnigCodePoint )'(', &p, end, &name_end, env, &gnum, 1);
- if (r < 0) return r;
-
- tok->type = TK_CALL;
- tok->u.call.name = name;
- tok->u.call.name_end = name_end;
- tok->u.call.gnum = gnum;
- tok->u.call.rel = 1;
- break;
- }
- }
+ /* (?&name), (?n), (?R), (?0), (?+n), (?-n) */
+ c = PPEEK;
+ if ((c == '&' || c == 'R' || ONIGENC_IS_CODE_DIGIT(enc, c)) &&
+ IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_SUBEXP_CALL)) {
+ /* (?&name), (?n), (?R), (?0) */
+ int gnum;
+ UChar *name;
+ UChar *name_end;
+
+ if (c == 'R' || c == '0') {
+ PINC; /* skip 'R' / '0' */
+ if (!PPEEK_IS(')')) {
+ r = ONIGERR_INVALID_GROUP_NAME;
+ onig_scan_env_set_error_string(env, r, p - 1, p + 1);
+ return r;
+ }
+ PINC; /* skip ')' */
+ name_end = name = p;
+ gnum = 0;
+ }
+ else {
+ int numref = 1;
+ if (c == '&') { /* (?&name) */
+ PINC;
+ numref = 0; /* don't allow number name */
+ }
+ name = p;
+ r = fetch_name((OnigCodePoint )'(', &p, end, &name_end, env, &gnum, numref);
+ if (r < 0) return r;
+ }
+
+ tok->type = TK_CALL;
+ tok->u.call.name = name;
+ tok->u.call.name_end = name_end;
+ tok->u.call.gnum = gnum;
+ tok->u.call.rel = 0;
+ break;
+ }
+ else if ((c == '-' || c == '+') &&
+ IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_SUBEXP_CALL)) {
+ /* (?+n), (?-n) */
+ int gnum;
+ UChar *name;
+ UChar *name_end;
+ OnigCodePoint cnext;
+ PFETCH_READY;
+
+ PINC; /* skip '-' / '+' */
+ cnext = PPEEK;
+ if (ONIGENC_IS_CODE_DIGIT(enc, cnext)) {
+ if (c == '-') PUNFETCH;
+ name = p;
+ r = fetch_name((OnigCodePoint )'(', &p, end, &name_end, env, &gnum, 1);
+ if (r < 0) return r;
+
+ tok->type = TK_CALL;
+ tok->u.call.name = name;
+ tok->u.call.name_end = name_end;
+ tok->u.call.gnum = gnum;
+ tok->u.call.rel = 1;
+ break;
+ }
+ }
#endif /* USE_PERL_SUBEXP_CALL */
#ifdef USE_CAPITAL_P_NAMED_GROUP
- if (PPEEK_IS('P') &&
- IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_CAPITAL_P_NAMED_GROUP)) {
- int gnum;
- UChar *name;
- UChar *name_end;
- PFETCH_READY;
-
- PINC; /* skip 'P' */
- if (PEND) return ONIGERR_UNDEFINED_GROUP_OPTION;
- PFETCH(c);
- if (c == '=') { /* (?P=name): backref */
- r = fetch_named_backref_token((OnigCodePoint )'(', tok, &p, end, env);
- if (r < 0) return r;
- break;
- }
- else if (c == '>') { /* (?P>name): subexp call */
- name = p;
- r = fetch_name((OnigCodePoint )'(', &p, end, &name_end, env, &gnum, 0);
- if (r < 0) return r;
-
- tok->type = TK_CALL;
- tok->u.call.name = name;
- tok->u.call.name_end = name_end;
- tok->u.call.gnum = gnum;
- tok->u.call.rel = 0;
- break;
- }
- }
+ if (PPEEK_IS('P') &&
+ IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_CAPITAL_P_NAMED_GROUP)) {
+ int gnum;
+ UChar *name;
+ UChar *name_end;
+ PFETCH_READY;
+
+ PINC; /* skip 'P' */
+ if (PEND) return ONIGERR_UNDEFINED_GROUP_OPTION;
+ PFETCH(c);
+ if (c == '=') { /* (?P=name): backref */
+ r = fetch_named_backref_token((OnigCodePoint )'(', tok, &p, end, env);
+ if (r < 0) return r;
+ break;
+ }
+ else if (c == '>') { /* (?P>name): subexp call */
+ name = p;
+ r = fetch_name((OnigCodePoint )'(', &p, end, &name_end, env, &gnum, 0);
+ if (r < 0) return r;
+
+ tok->type = TK_CALL;
+ tok->u.call.name = name;
+ tok->u.call.name_end = name_end;
+ tok->u.call.gnum = gnum;
+ tok->u.call.rel = 0;
+ break;
+ }
+ }
#endif /* USE_CAPITAL_P_NAMED_GROUP */
- PUNFETCH;
+ PUNFETCH;
}
if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_LPAREN_SUBEXP)) break;
@@ -4138,14 +4142,14 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_LINE_ANCHOR)) break;
tok->type = TK_ANCHOR;
tok->u.anchor.subtype = (IS_SINGLELINE(env->option)
- ? ANCHOR_BEGIN_BUF : ANCHOR_BEGIN_LINE);
+ ? ANCHOR_BEGIN_BUF : ANCHOR_BEGIN_LINE);
break;
case '$':
if (! IS_SYNTAX_OP(syn, ONIG_SYN_OP_LINE_ANCHOR)) break;
tok->type = TK_ANCHOR;
tok->u.anchor.subtype = (IS_SINGLELINE(env->option)
- ? ANCHOR_SEMI_END_BUF : ANCHOR_END_LINE);
+ ? ANCHOR_SEMI_END_BUF : ANCHOR_END_LINE);
break;
case '[':
@@ -4155,24 +4159,24 @@ fetch_token(OnigToken* tok, UChar** src, UChar* end, ScanEnv* env)
case ']':
if (*src > env->pattern) /* /].../ is allowed. */
- CLOSE_BRACKET_WITHOUT_ESC_WARN(env, (UChar* )"]");
+ CLOSE_BRACKET_WITHOUT_ESC_WARN(env, (UChar* )"]");
break;
case '#':
if (IS_EXTEND(env->option)) {
- while (!PEND) {
- PFETCH(c);
- if (ONIGENC_IS_CODE_NEWLINE(enc, c))
- break;
- }
- goto start;
- break;
+ while (!PEND) {
+ PFETCH(c);
+ if (ONIGENC_IS_CODE_NEWLINE(enc, c))
+ break;
+ }
+ goto start;
+ break;
}
break;
case ' ': case '\t': case '\n': case '\r': case '\f':
if (IS_EXTEND(env->option))
- goto start;
+ goto start;
break;
default:
@@ -4201,18 +4205,18 @@ add_ctype_to_cc_by_range(CClassNode* cc, int ctype ARG_UNUSED, int not,
if (not == 0) {
for (i = 0; i < n; i++) {
for (j = ONIGENC_CODE_RANGE_FROM(mbr, i);
- j <= ONIGENC_CODE_RANGE_TO(mbr, i); j++) {
- if (j >= sb_out) {
- if (j > ONIGENC_CODE_RANGE_FROM(mbr, i)) {
- r = add_code_range_to_buf(&(cc->mbuf), env, j,
- ONIGENC_CODE_RANGE_TO(mbr, i));
- if (r != 0) return r;
- i++;
- }
+ j <= ONIGENC_CODE_RANGE_TO(mbr, i); j++) {
+ if (j >= sb_out) {
+ if (j > ONIGENC_CODE_RANGE_FROM(mbr, i)) {
+ r = add_code_range_to_buf(&(cc->mbuf), env, j,
+ ONIGENC_CODE_RANGE_TO(mbr, i));
+ if (r != 0) return r;
+ i++;
+ }
- goto sb_end;
- }
- BITSET_SET_BIT_CHKDUP(cc->bs, j);
+ goto sb_end;
+ }
+ BITSET_SET_BIT_CHKDUP(cc->bs, j);
}
}
@@ -4229,11 +4233,11 @@ add_ctype_to_cc_by_range(CClassNode* cc, int ctype ARG_UNUSED, int not,
for (i = 0; i < n; i++) {
for (j = prev;
- j < ONIGENC_CODE_RANGE_FROM(mbr, i); j++) {
- if (j >= sb_out) {
- goto sb_end2;
- }
- BITSET_SET_BIT_CHKDUP(cc->bs, j);
+ j < ONIGENC_CODE_RANGE_FROM(mbr, i); j++) {
+ if (j >= sb_out) {
+ goto sb_end2;
+ }
+ BITSET_SET_BIT_CHKDUP(cc->bs, j);
}
prev = ONIGENC_CODE_RANGE_TO(mbr, i) + 1;
}
@@ -4246,9 +4250,9 @@ add_ctype_to_cc_by_range(CClassNode* cc, int ctype ARG_UNUSED, int not,
for (i = 0; i < n; i++) {
if (prev < ONIGENC_CODE_RANGE_FROM(mbr, i)) {
- r = add_code_range_to_buf(&(cc->mbuf), env, prev,
+ r = add_code_range_to_buf(&(cc->mbuf), env, prev,
ONIGENC_CODE_RANGE_FROM(mbr, i) - 1);
- if (r != 0) return r;
+ if (r != 0) return r;
}
prev = ONIGENC_CODE_RANGE_TO(mbr, i) + 1;
}
@@ -4276,30 +4280,30 @@ add_ctype_to_cc(CClassNode* cc, int ctype, int not, int ascii_range, ScanEnv* en
CClassNode ccwork;
initialize_cclass(&ccwork);
r = add_ctype_to_cc_by_range(&ccwork, ctype, not, env, sb_out,
- ranges);
+ ranges);
if (r == 0) {
- if (not) {
- r = add_code_range_to_buf0(&(ccwork.mbuf), env, 0x80, ONIG_LAST_CODE_POINT, FALSE);
- }
- else {
- CClassNode ccascii;
- initialize_cclass(&ccascii);
- if (ONIGENC_MBC_MINLEN(env->enc) > 1) {
- r = add_code_range(&(ccascii.mbuf), env, 0x00, 0x7F);
- }
- else {
- bitset_set_range(env, ccascii.bs, 0x00, 0x7F);
- r = 0;
- }
- if (r == 0) {
- r = and_cclass(&ccwork, &ccascii, env);
- }
- if (IS_NOT_NULL(ccascii.mbuf)) bbuf_free(ccascii.mbuf);
- }
- if (r == 0) {
- r = or_cclass(cc, &ccwork, env);
- }
- if (IS_NOT_NULL(ccwork.mbuf)) bbuf_free(ccwork.mbuf);
+ if (not) {
+ r = add_code_range_to_buf0(&(ccwork.mbuf), env, 0x80, ONIG_LAST_CODE_POINT, FALSE);
+ }
+ else {
+ CClassNode ccascii;
+ initialize_cclass(&ccascii);
+ if (ONIGENC_MBC_MINLEN(env->enc) > 1) {
+ r = add_code_range(&(ccascii.mbuf), env, 0x00, 0x7F);
+ }
+ else {
+ bitset_set_range(env, ccascii.bs, 0x00, 0x7F);
+ r = 0;
+ }
+ if (r == 0) {
+ r = and_cclass(&ccwork, &ccascii, env);
+ }
+ if (IS_NOT_NULL(ccascii.mbuf)) bbuf_free(ccascii.mbuf);
+ }
+ if (r == 0) {
+ r = or_cclass(cc, &ccwork, env);
+ }
+ if (IS_NOT_NULL(ccwork.mbuf)) bbuf_free(ccwork.mbuf);
}
}
else {
@@ -4327,15 +4331,15 @@ add_ctype_to_cc(CClassNode* cc, int ctype, int not, int ascii_range, ScanEnv* en
case ONIGENC_CTYPE_ALNUM:
if (not != 0) {
for (c = 0; c < SINGLE_BYTE_SIZE; c++) {
- if (! ONIGENC_IS_CODE_CTYPE(enc, (OnigCodePoint )c, ctype))
- BITSET_SET_BIT_CHKDUP(cc->bs, c);
+ if (! ONIGENC_IS_CODE_CTYPE(enc, (OnigCodePoint )c, ctype))
+ BITSET_SET_BIT_CHKDUP(cc->bs, c);
}
ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf);
}
else {
for (c = 0; c < SINGLE_BYTE_SIZE; c++) {
- if (ONIGENC_IS_CODE_CTYPE(enc, (OnigCodePoint )c, ctype))
- BITSET_SET_BIT_CHKDUP(cc->bs, c);
+ if (ONIGENC_IS_CODE_CTYPE(enc, (OnigCodePoint )c, ctype))
+ BITSET_SET_BIT_CHKDUP(cc->bs, c);
}
}
break;
@@ -4344,39 +4348,39 @@ add_ctype_to_cc(CClassNode* cc, int ctype, int not, int ascii_range, ScanEnv* en
case ONIGENC_CTYPE_PRINT:
if (not != 0) {
for (c = 0; c < SINGLE_BYTE_SIZE; c++) {
- if (! ONIGENC_IS_CODE_CTYPE(enc, (OnigCodePoint )c, ctype)
- || c >= maxcode)
- BITSET_SET_BIT_CHKDUP(cc->bs, c);
+ if (! ONIGENC_IS_CODE_CTYPE(enc, (OnigCodePoint )c, ctype)
+ || c >= maxcode)
+ BITSET_SET_BIT_CHKDUP(cc->bs, c);
}
if (ascii_range)
- ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf);
+ ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf);
}
else {
for (c = 0; c < maxcode; c++) {
- if (ONIGENC_IS_CODE_CTYPE(enc, (OnigCodePoint )c, ctype))
- BITSET_SET_BIT_CHKDUP(cc->bs, c);
+ if (ONIGENC_IS_CODE_CTYPE(enc, (OnigCodePoint )c, ctype))
+ BITSET_SET_BIT_CHKDUP(cc->bs, c);
}
if (! ascii_range)
- ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf);
+ ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf);
}
break;
case ONIGENC_CTYPE_WORD:
if (not == 0) {
for (c = 0; c < maxcode; c++) {
- if (ONIGENC_IS_CODE_WORD(enc, c)) BITSET_SET_BIT_CHKDUP(cc->bs, c);
+ if (ONIGENC_IS_CODE_WORD(enc, c)) BITSET_SET_BIT_CHKDUP(cc->bs, c);
}
if (! ascii_range)
- ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf);
+ ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf);
}
else {
for (c = 0; c < SINGLE_BYTE_SIZE; c++) {
- if ((ONIGENC_CODE_TO_MBCLEN(enc, c) > 0) /* check invalid code point */
- && (! ONIGENC_IS_CODE_WORD(enc, c) || c >= maxcode))
- BITSET_SET_BIT_CHKDUP(cc->bs, c);
+ if ((ONIGENC_CODE_TO_MBCLEN(enc, c) > 0) /* check invalid code point */
+ && (! ONIGENC_IS_CODE_WORD(enc, c) || c >= maxcode))
+ BITSET_SET_BIT_CHKDUP(cc->bs, c);
}
if (ascii_range)
- ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf);
+ ADD_ALL_MULTI_BYTE_RANGE(enc, cc->mbuf);
}
break;
@@ -4390,7 +4394,7 @@ add_ctype_to_cc(CClassNode* cc, int ctype, int not, int ascii_range, ScanEnv* en
static int
parse_posix_bracket(CClassNode* cc, CClassNode* asc_cc,
- UChar** src, UChar* end, ScanEnv* env)
+ UChar** src, UChar* end, ScanEnv* env)
{
#define POSIX_BRACKET_CHECK_LIMIT_LENGTH 20
#define POSIX_BRACKET_NAME_MIN_LEN 4
@@ -4430,22 +4434,22 @@ parse_posix_bracket(CClassNode* cc, CClassNode* asc_cc,
goto not_posix_bracket;
ascii_range = IS_ASCII_RANGE(env->option) &&
- ! IS_POSIX_BRACKET_ALL_RANGE(env->option);
+ ! IS_POSIX_BRACKET_ALL_RANGE(env->option);
for (pb = PBS; pb < PBS + numberof(PBS); pb++) {
if (onigenc_with_ascii_strncmp(enc, p, end, pb->name, pb->len) == 0) {
p = (UChar* )onigenc_step(enc, p, end, pb->len);
if (onigenc_with_ascii_strncmp(enc, p, end, (UChar* )":]", 2) != 0)
- return ONIGERR_INVALID_POSIX_BRACKET_TYPE;
+ return ONIGERR_INVALID_POSIX_BRACKET_TYPE;
r = add_ctype_to_cc(cc, pb->ctype, not, ascii_range, env);
if (r != 0) return r;
if (IS_NOT_NULL(asc_cc)) {
- if (pb->ctype != ONIGENC_CTYPE_WORD &&
- pb->ctype != ONIGENC_CTYPE_ASCII &&
- !ascii_range)
- r = add_ctype_to_cc(asc_cc, pb->ctype, not, ascii_range, env);
- if (r != 0) return r;
+ if (pb->ctype != ONIGENC_CTYPE_WORD &&
+ pb->ctype != ONIGENC_CTYPE_ASCII &&
+ !ascii_range)
+ r = add_ctype_to_cc(asc_cc, pb->ctype, not, ascii_range, env);
+ if (r != 0) return r;
}
PINC_S; PINC_S;
@@ -4466,7 +4470,7 @@ parse_posix_bracket(CClassNode* cc, CClassNode* asc_cc,
if (! PEND) {
PFETCH_S(c);
if (c == ']')
- return ONIGERR_INVALID_POSIX_BRACKET_TYPE;
+ return ONIGERR_INVALID_POSIX_BRACKET_TYPE;
}
}
@@ -4507,7 +4511,7 @@ static int cclass_case_fold(Node** np, CClassNode* cc, CClassNode* asc_cc, ScanE
static int
parse_char_property(Node** np, OnigToken* tok, UChar** src, UChar* end,
- ScanEnv* env)
+ ScanEnv* env)
{
int r, ctype;
CClassNode* cc;
@@ -4545,8 +4549,8 @@ enum CCVALTYPE {
static int
next_state_class(CClassNode* cc, CClassNode* asc_cc,
- OnigCodePoint* vs, enum CCVALTYPE* type,
- enum CCSTATE* state, ScanEnv* env)
+ OnigCodePoint* vs, enum CCVALTYPE* type,
+ enum CCSTATE* state, ScanEnv* env)
{
int r;
@@ -4557,14 +4561,14 @@ next_state_class(CClassNode* cc, CClassNode* asc_cc,
if (*type == CCV_SB) {
BITSET_SET_BIT_CHKDUP(cc->bs, (int )(*vs));
if (IS_NOT_NULL(asc_cc))
- BITSET_SET_BIT(asc_cc->bs, (int )(*vs));
+ BITSET_SET_BIT(asc_cc->bs, (int )(*vs));
}
else if (*type == CCV_CODE_POINT) {
r = add_code_range(&(cc->mbuf), env, *vs, *vs);
if (r < 0) return r;
if (IS_NOT_NULL(asc_cc)) {
- r = add_code_range0(&(asc_cc->mbuf), env, *vs, *vs, 0);
- if (r < 0) return r;
+ r = add_code_range0(&(asc_cc->mbuf), env, *vs, *vs, 0);
+ if (r < 0) return r;
}
}
}
@@ -4576,10 +4580,10 @@ next_state_class(CClassNode* cc, CClassNode* asc_cc,
static int
next_state_val(CClassNode* cc, CClassNode* asc_cc,
- OnigCodePoint *from, OnigCodePoint to,
- int* from_israw, int to_israw,
- enum CCVALTYPE intype, enum CCVALTYPE* type,
- enum CCSTATE* state, ScanEnv* env)
+ OnigCodePoint *from, OnigCodePoint to,
+ int* from_israw, int to_israw,
+ enum CCVALTYPE intype, enum CCVALTYPE* type,
+ enum CCSTATE* state, ScanEnv* env)
{
int r;
@@ -4588,14 +4592,14 @@ next_state_val(CClassNode* cc, CClassNode* asc_cc,
if (*type == CCV_SB) {
BITSET_SET_BIT_CHKDUP(cc->bs, (int )(*from));
if (IS_NOT_NULL(asc_cc))
- BITSET_SET_BIT(asc_cc->bs, (int )(*from));
+ BITSET_SET_BIT(asc_cc->bs, (int )(*from));
}
else if (*type == CCV_CODE_POINT) {
r = add_code_range(&(cc->mbuf), env, *from, *from);
if (r < 0) return r;
if (IS_NOT_NULL(asc_cc)) {
- r = add_code_range0(&(asc_cc->mbuf), env, *from, *from, 0);
- if (r < 0) return r;
+ r = add_code_range0(&(asc_cc->mbuf), env, *from, *from, 0);
+ if (r < 0) return r;
}
}
break;
@@ -4603,42 +4607,42 @@ next_state_val(CClassNode* cc, CClassNode* asc_cc,
case CCS_RANGE:
if (intype == *type) {
if (intype == CCV_SB) {
- if (*from > 0xff || to > 0xff)
- return ONIGERR_INVALID_CODE_POINT_VALUE;
-
- if (*from > to) {
- if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC))
- goto ccs_range_end;
- else
- return ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS;
- }
- bitset_set_range(env, cc->bs, (int )*from, (int )to);
- if (IS_NOT_NULL(asc_cc))
- bitset_set_range(env, asc_cc->bs, (int )*from, (int )to);
+ if (*from > 0xff || to > 0xff)
+ return ONIGERR_INVALID_CODE_POINT_VALUE;
+
+ if (*from > to) {
+ if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC))
+ goto ccs_range_end;
+ else
+ return ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS;
+ }
+ bitset_set_range(env, cc->bs, (int )*from, (int )to);
+ if (IS_NOT_NULL(asc_cc))
+ bitset_set_range(env, asc_cc->bs, (int )*from, (int )to);
}
else {
- r = add_code_range(&(cc->mbuf), env, *from, to);
- if (r < 0) return r;
- if (IS_NOT_NULL(asc_cc)) {
- r = add_code_range0(&(asc_cc->mbuf), env, *from, to, 0);
- if (r < 0) return r;
- }
+ r = add_code_range(&(cc->mbuf), env, *from, to);
+ if (r < 0) return r;
+ if (IS_NOT_NULL(asc_cc)) {
+ r = add_code_range0(&(asc_cc->mbuf), env, *from, to, 0);
+ if (r < 0) return r;
+ }
}
}
else {
if (*from > to) {
- if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC))
- goto ccs_range_end;
- else
- return ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS;
+ if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_EMPTY_RANGE_IN_CC))
+ goto ccs_range_end;
+ else
+ return ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS;
}
bitset_set_range(env, cc->bs, (int )*from, (int )(to < 0xff ? to : 0xff));
r = add_code_range(&(cc->mbuf), env, (OnigCodePoint )*from, to);
if (r < 0) return r;
if (IS_NOT_NULL(asc_cc)) {
- bitset_set_range(env, asc_cc->bs, (int )*from, (int )(to < 0xff ? to : 0xff));
- r = add_code_range0(&(asc_cc->mbuf), env, (OnigCodePoint )*from, to, 0);
- if (r < 0) return r;
+ bitset_set_range(env, asc_cc->bs, (int )*from, (int )(to < 0xff ? to : 0xff));
+ r = add_code_range0(&(asc_cc->mbuf), env, (OnigCodePoint )*from, to, 0);
+ if (r < 0) return r;
}
}
ccs_range_end:
@@ -4662,7 +4666,7 @@ next_state_val(CClassNode* cc, CClassNode* asc_cc,
static int
code_exist_check(OnigCodePoint c, UChar* from, UChar* end, int ignore_escaped,
- ScanEnv* env)
+ ScanEnv* env)
{
int in_esc;
OnigCodePoint code;
@@ -4685,7 +4689,7 @@ code_exist_check(OnigCodePoint c, UChar* from, UChar* end, int ignore_escaped,
static int
parse_char_class(Node** np, Node** asc_np, OnigToken* tok, UChar** src, UChar* end,
- ScanEnv* env)
+ ScanEnv* env)
{
int r, neg, len, fetched, and_start;
OnigCodePoint v, vs;
@@ -4746,16 +4750,16 @@ parse_char_class(Node** np, Node** asc_np, OnigToken* tok, UChar** src, UChar* e
switch (r) {
case TK_CHAR:
if ((tok->u.code >= SINGLE_BYTE_SIZE) ||
- (len = ONIGENC_CODE_TO_MBCLEN(env->enc, tok->u.c)) > 1) {
- in_type = CCV_CODE_POINT;
+ (len = ONIGENC_CODE_TO_MBCLEN(env->enc, tok->u.c)) > 1) {
+ in_type = CCV_CODE_POINT;
}
else if (len < 0) {
- r = len;
- goto err;
+ r = len;
+ goto err;
}
else {
sb_char:
- in_type = CCV_SB;
+ in_type = CCV_SB;
}
v = (OnigCodePoint )tok->u.c;
in_israw = 0;
@@ -4765,54 +4769,54 @@ parse_char_class(Node** np, Node** asc_np, OnigToken* tok, UChar** src, UChar* e
case TK_RAW_BYTE:
/* tok->base != 0 : octal or hexadec. */
if (! ONIGENC_IS_SINGLEBYTE(env->enc) && tok->base != 0) {
- UChar buf[ONIGENC_CODE_TO_MBC_MAXLEN];
- UChar* bufe = buf + ONIGENC_CODE_TO_MBC_MAXLEN;
- UChar* psave = p;
- int i, base = tok->base;
-
- buf[0] = (UChar )tok->u.c;
- for (i = 1; i < ONIGENC_MBC_MAXLEN(env->enc); i++) {
- r = fetch_token_in_cc(tok, &p, end, env);
- if (r < 0) goto err;
- if (r != TK_RAW_BYTE || tok->base != base) {
- fetched = 1;
- break;
- }
- buf[i] = (UChar )tok->u.c;
- }
-
- if (i < ONIGENC_MBC_MINLEN(env->enc)) {
- r = ONIGERR_TOO_SHORT_MULTI_BYTE_STRING;
- goto err;
- }
-
- len = enclen(env->enc, buf, buf + i);
- if (i < len) {
- r = ONIGERR_TOO_SHORT_MULTI_BYTE_STRING;
- goto err;
- }
- else if (i > len) { /* fetch back */
- p = psave;
- for (i = 1; i < len; i++) {
- (void)fetch_token_in_cc(tok, &p, end, env);
- /* no need to check the return value (already checked above) */
- }
- fetched = 0;
- }
-
- if (i == 1) {
- v = (OnigCodePoint )buf[0];
- goto raw_single;
- }
- else {
- v = ONIGENC_MBC_TO_CODE(env->enc, buf, bufe);
- in_type = CCV_CODE_POINT;
- }
+ UChar buf[ONIGENC_CODE_TO_MBC_MAXLEN];
+ UChar* bufe = buf + ONIGENC_CODE_TO_MBC_MAXLEN;
+ UChar* psave = p;
+ int i, base = tok->base;
+
+ buf[0] = (UChar )tok->u.c;
+ for (i = 1; i < ONIGENC_MBC_MAXLEN(env->enc); i++) {
+ r = fetch_token_in_cc(tok, &p, end, env);
+ if (r < 0) goto err;
+ if (r != TK_RAW_BYTE || tok->base != base) {
+ fetched = 1;
+ break;
+ }
+ buf[i] = (UChar )tok->u.c;
+ }
+
+ if (i < ONIGENC_MBC_MINLEN(env->enc)) {
+ r = ONIGERR_TOO_SHORT_MULTI_BYTE_STRING;
+ goto err;
+ }
+
+ len = enclen(env->enc, buf, buf + i);
+ if (i < len) {
+ r = ONIGERR_TOO_SHORT_MULTI_BYTE_STRING;
+ goto err;
+ }
+ else if (i > len) { /* fetch back */
+ p = psave;
+ for (i = 1; i < len; i++) {
+ (void)fetch_token_in_cc(tok, &p, end, env);
+ /* no need to check the return value (already checked above) */
+ }
+ fetched = 0;
+ }
+
+ if (i == 1) {
+ v = (OnigCodePoint )buf[0];
+ goto raw_single;
+ }
+ else {
+ v = ONIGENC_MBC_TO_CODE(env->enc, buf, bufe);
+ in_type = CCV_CODE_POINT;
+ }
}
else {
- v = (OnigCodePoint )tok->u.c;
+ v = (OnigCodePoint )tok->u.c;
raw_single:
- in_type = CCV_SB;
+ in_type = CCV_SB;
}
in_israw = 1;
goto val_entry2;
@@ -4824,13 +4828,13 @@ parse_char_class(Node** np, Node** asc_np, OnigToken* tok, UChar** src, UChar* e
val_entry:
len = ONIGENC_CODE_TO_MBCLEN(env->enc, v);
if (len < 0) {
- r = len;
- goto err;
+ r = len;
+ goto err;
}
in_type = (len == 1 ? CCV_SB : CCV_CODE_POINT);
val_entry2:
r = next_state_val(cc, asc_cc, &vs, v, &val_israw, in_israw, in_type, &val_type,
- &state, env);
+ &state, env);
if (r != 0) goto err;
break;
@@ -4838,24 +4842,24 @@ parse_char_class(Node** np, Node** asc_np, OnigToken* tok, UChar** src, UChar* e
r = parse_posix_bracket(cc, asc_cc, &p, end, env);
if (r < 0) goto err;
if (r == 1) { /* is not POSIX bracket */
- CC_ESC_WARN(env, (UChar* )"[");
- p = tok->backp;
- v = (OnigCodePoint )tok->u.c;
- in_israw = 0;
- goto val_entry;
+ CC_ESC_WARN(env, (UChar* )"[");
+ p = tok->backp;
+ v = (OnigCodePoint )tok->u.c;
+ in_israw = 0;
+ goto val_entry;
}
goto next_class;
break;
case TK_CHAR_TYPE:
r = add_ctype_to_cc(cc, tok->u.prop.ctype, tok->u.prop.not,
- IS_ASCII_RANGE(env->option), env);
+ IS_ASCII_RANGE(env->option), env);
if (r != 0) return r;
if (IS_NOT_NULL(asc_cc)) {
- if (tok->u.prop.ctype != ONIGENC_CTYPE_WORD)
- r = add_ctype_to_cc(asc_cc, tok->u.prop.ctype, tok->u.prop.not,
- IS_ASCII_RANGE(env->option), env);
- if (r != 0) return r;
+ if (tok->u.prop.ctype != ONIGENC_CTYPE_WORD)
+ r = add_ctype_to_cc(asc_cc, tok->u.prop.ctype, tok->u.prop.not,
+ IS_ASCII_RANGE(env->option), env);
+ if (r != 0) return r;
}
next_class:
@@ -4865,133 +4869,133 @@ parse_char_class(Node** np, Node** asc_np, OnigToken* tok, UChar** src, UChar* e
case TK_CHAR_PROPERTY:
{
- int ctype;
-
- ctype = fetch_char_property_to_ctype(&p, end, env);
- if (ctype < 0) return ctype;
- r = add_ctype_to_cc(cc, ctype, tok->u.prop.not, 0, env);
- if (r != 0) return r;
- if (IS_NOT_NULL(asc_cc)) {
- if (ctype != ONIGENC_CTYPE_ASCII)
- r = add_ctype_to_cc(asc_cc, ctype, tok->u.prop.not, 0, env);
- if (r != 0) return r;
- }
- goto next_class;
+ int ctype;
+
+ ctype = fetch_char_property_to_ctype(&p, end, env);
+ if (ctype < 0) return ctype;
+ r = add_ctype_to_cc(cc, ctype, tok->u.prop.not, 0, env);
+ if (r != 0) return r;
+ if (IS_NOT_NULL(asc_cc)) {
+ if (ctype != ONIGENC_CTYPE_ASCII)
+ r = add_ctype_to_cc(asc_cc, ctype, tok->u.prop.not, 0, env);
+ if (r != 0) return r;
+ }
+ goto next_class;
}
break;
case TK_CC_RANGE:
if (state == CCS_VALUE) {
- r = fetch_token_in_cc(tok, &p, end, env);
- if (r < 0) goto err;
- fetched = 1;
- if (r == TK_CC_CLOSE) { /* allow [x-] */
- range_end_val:
- v = (OnigCodePoint )'-';
- in_israw = 0;
- goto val_entry;
- }
- else if (r == TK_CC_AND) {
- CC_ESC_WARN(env, (UChar* )"-");
- goto range_end_val;
- }
-
- if (val_type == CCV_CLASS) {
- r = ONIGERR_UNMATCHED_RANGE_SPECIFIER_IN_CHAR_CLASS;
- goto err;
- }
-
- state = CCS_RANGE;
+ r = fetch_token_in_cc(tok, &p, end, env);
+ if (r < 0) goto err;
+ fetched = 1;
+ if (r == TK_CC_CLOSE) { /* allow [x-] */
+ range_end_val:
+ v = (OnigCodePoint )'-';
+ in_israw = 0;
+ goto val_entry;
+ }
+ else if (r == TK_CC_AND) {
+ CC_ESC_WARN(env, (UChar* )"-");
+ goto range_end_val;
+ }
+
+ if (val_type == CCV_CLASS) {
+ r = ONIGERR_UNMATCHED_RANGE_SPECIFIER_IN_CHAR_CLASS;
+ goto err;
+ }
+
+ state = CCS_RANGE;
}
else if (state == CCS_START) {
- /* [-xa] is allowed */
- v = (OnigCodePoint )tok->u.c;
- in_israw = 0;
+ /* [-xa] is allowed */
+ v = (OnigCodePoint )tok->u.c;
+ in_israw = 0;
- r = fetch_token_in_cc(tok, &p, end, env);
- if (r < 0) goto err;
- fetched = 1;
- /* [--x] or [a&&-x] is warned. */
- if (r == TK_CC_RANGE || and_start != 0)
- CC_ESC_WARN(env, (UChar* )"-");
+ r = fetch_token_in_cc(tok, &p, end, env);
+ if (r < 0) goto err;
+ fetched = 1;
+ /* [--x] or [a&&-x] is warned. */
+ if (r == TK_CC_RANGE || and_start != 0)
+ CC_ESC_WARN(env, (UChar* )"-");
- goto val_entry;
+ goto val_entry;
}
else if (state == CCS_RANGE) {
- CC_ESC_WARN(env, (UChar* )"-");
- goto sb_char; /* [!--x] is allowed */
+ CC_ESC_WARN(env, (UChar* )"-");
+ goto sb_char; /* [!--x] is allowed */
}
else { /* CCS_COMPLETE */
- r = fetch_token_in_cc(tok, &p, end, env);
- if (r < 0) goto err;
- fetched = 1;
- if (r == TK_CC_CLOSE) goto range_end_val; /* allow [a-b-] */
- else if (r == TK_CC_AND) {
- CC_ESC_WARN(env, (UChar* )"-");
- goto range_end_val;
- }
-
- if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_DOUBLE_RANGE_OP_IN_CC)) {
- CC_ESC_WARN(env, (UChar* )"-");
- goto range_end_val; /* [0-9-a] is allowed as [0-9\-a] */
- }
- r = ONIGERR_UNMATCHED_RANGE_SPECIFIER_IN_CHAR_CLASS;
- goto err;
+ r = fetch_token_in_cc(tok, &p, end, env);
+ if (r < 0) goto err;
+ fetched = 1;
+ if (r == TK_CC_CLOSE) goto range_end_val; /* allow [a-b-] */
+ else if (r == TK_CC_AND) {
+ CC_ESC_WARN(env, (UChar* )"-");
+ goto range_end_val;
+ }
+
+ if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_ALLOW_DOUBLE_RANGE_OP_IN_CC)) {
+ CC_ESC_WARN(env, (UChar* )"-");
+ goto range_end_val; /* [0-9-a] is allowed as [0-9\-a] */
+ }
+ r = ONIGERR_UNMATCHED_RANGE_SPECIFIER_IN_CHAR_CLASS;
+ goto err;
}
break;
case TK_CC_CC_OPEN: /* [ */
{
- Node *anode, *aasc_node;
- CClassNode* acc;
-
- r = parse_char_class(&anode, &aasc_node, tok, &p, end, env);
- if (r == 0) {
- acc = NCCLASS(anode);
- r = or_cclass(cc, acc, env);
- }
- if (r == 0 && IS_NOT_NULL(aasc_node)) {
- acc = NCCLASS(aasc_node);
- r = or_cclass(asc_cc, acc, env);
- }
- onig_node_free(anode);
- onig_node_free(aasc_node);
- if (r != 0) goto err;
+ Node *anode, *aasc_node;
+ CClassNode* acc;
+
+ r = parse_char_class(&anode, &aasc_node, tok, &p, end, env);
+ if (r == 0) {
+ acc = NCCLASS(anode);
+ r = or_cclass(cc, acc, env);
+ }
+ if (r == 0 && IS_NOT_NULL(aasc_node)) {
+ acc = NCCLASS(aasc_node);
+ r = or_cclass(asc_cc, acc, env);
+ }
+ onig_node_free(anode);
+ onig_node_free(aasc_node);
+ if (r != 0) goto err;
}
break;
case TK_CC_AND: /* && */
{
- if (state == CCS_VALUE) {
- r = next_state_val(cc, asc_cc, &vs, 0, &val_israw, 0, val_type,
- &val_type, &state, env);
- if (r != 0) goto err;
- }
- /* initialize local variables */
- and_start = 1;
- state = CCS_START;
-
- if (IS_NOT_NULL(prev_cc)) {
- r = and_cclass(prev_cc, cc, env);
- if (r != 0) goto err;
- bbuf_free(cc->mbuf);
- if (IS_NOT_NULL(asc_cc)) {
- r = and_cclass(asc_prev_cc, asc_cc, env);
- if (r != 0) goto err;
- bbuf_free(asc_cc->mbuf);
- }
- }
- else {
- prev_cc = cc;
- cc = &work_cc;
- if (IS_NOT_NULL(asc_cc)) {
- asc_prev_cc = asc_cc;
- asc_cc = &asc_work_cc;
- }
- }
- initialize_cclass(cc);
- if (IS_NOT_NULL(asc_cc))
- initialize_cclass(asc_cc);
+ if (state == CCS_VALUE) {
+ r = next_state_val(cc, asc_cc, &vs, 0, &val_israw, 0, val_type,
+ &val_type, &state, env);
+ if (r != 0) goto err;
+ }
+ /* initialize local variables */
+ and_start = 1;
+ state = CCS_START;
+
+ if (IS_NOT_NULL(prev_cc)) {
+ r = and_cclass(prev_cc, cc, env);
+ if (r != 0) goto err;
+ bbuf_free(cc->mbuf);
+ if (IS_NOT_NULL(asc_cc)) {
+ r = and_cclass(asc_prev_cc, asc_cc, env);
+ if (r != 0) goto err;
+ bbuf_free(asc_cc->mbuf);
+ }
+ }
+ else {
+ prev_cc = cc;
+ cc = &work_cc;
+ if (IS_NOT_NULL(asc_cc)) {
+ asc_prev_cc = asc_cc;
+ asc_cc = &asc_work_cc;
+ }
+ }
+ initialize_cclass(cc);
+ if (IS_NOT_NULL(asc_cc))
+ initialize_cclass(asc_cc);
}
break;
@@ -5015,7 +5019,7 @@ parse_char_class(Node** np, Node** asc_np, OnigToken* tok, UChar** src, UChar* e
if (state == CCS_VALUE) {
r = next_state_val(cc, asc_cc, &vs, 0, &val_israw, 0, val_type,
- &val_type, &state, env);
+ &val_type, &state, env);
if (r != 0) goto err;
}
@@ -5054,12 +5058,12 @@ parse_char_class(Node** np, Node** asc_np, OnigToken* tok, UChar** src, UChar* e
#define NEWLINE_CODE 0x0a
if (ONIGENC_IS_CODE_NEWLINE(env->enc, NEWLINE_CODE)) {
- if (ONIGENC_CODE_TO_MBCLEN(env->enc, NEWLINE_CODE) == 1)
- BITSET_SET_BIT_CHKDUP(cc->bs, NEWLINE_CODE);
- else {
- r = add_code_range(&(cc->mbuf), env, NEWLINE_CODE, NEWLINE_CODE);
- if (r < 0) goto err;
- }
+ if (ONIGENC_CODE_TO_MBCLEN(env->enc, NEWLINE_CODE) == 1)
+ BITSET_SET_BIT_CHKDUP(cc->bs, NEWLINE_CODE);
+ else {
+ r = add_code_range(&(cc->mbuf), env, NEWLINE_CODE, NEWLINE_CODE);
+ if (r < 0) goto err;
+ }
}
}
}
@@ -5076,11 +5080,11 @@ parse_char_class(Node** np, Node** asc_np, OnigToken* tok, UChar** src, UChar* e
}
static int parse_subexp(Node** top, OnigToken* tok, int term,
- UChar** src, UChar* end, ScanEnv* env);
+ UChar** src, UChar* end, ScanEnv* env);
static int
parse_enclose(Node** np, OnigToken* tok, int term, UChar** src, UChar* end,
- ScanEnv* env)
+ ScanEnv* env)
{
int r = 0, num;
Node *target, *work1 = NULL, *work2 = NULL;
@@ -5127,28 +5131,28 @@ parse_enclose(Node** np, OnigToken* tok, int term, UChar** src, UChar* end,
break;
case '~': /* (?~...) absent operator */
if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_TILDE_ABSENT)) {
- *np = node_new_enclose(ENCLOSE_ABSENT);
+ *np = node_new_enclose(ENCLOSE_ABSENT);
}
else {
- return ONIGERR_UNDEFINED_GROUP_OPTION;
+ return ONIGERR_UNDEFINED_GROUP_OPTION;
}
break;
#ifdef USE_NAMED_GROUP
case '\'':
if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP)) {
- goto named_group1;
+ goto named_group1;
}
else
- return ONIGERR_UNDEFINED_GROUP_OPTION;
+ return ONIGERR_UNDEFINED_GROUP_OPTION;
break;
# ifdef USE_CAPITAL_P_NAMED_GROUP
case 'P': /* (?P<name>...) */
if (!PEND &&
- IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_CAPITAL_P_NAMED_GROUP)) {
- PFETCH(c);
- if (c == '<') goto named_group1;
+ IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_CAPITAL_P_NAMED_GROUP)) {
+ PFETCH(c);
+ if (c == '<') goto named_group1;
}
return ONIGERR_UNDEFINED_GROUP_OPTION;
break;
@@ -5159,49 +5163,49 @@ parse_enclose(Node** np, OnigToken* tok, int term, UChar** src, UChar* end,
if (PEND) return ONIGERR_END_PATTERN_WITH_UNMATCHED_PARENTHESIS;
PFETCH(c);
if (c == '=')
- *np = onig_node_new_anchor(ANCHOR_LOOK_BEHIND);
+ *np = onig_node_new_anchor(ANCHOR_LOOK_BEHIND);
else if (c == '!')
- *np = onig_node_new_anchor(ANCHOR_LOOK_BEHIND_NOT);
+ *np = onig_node_new_anchor(ANCHOR_LOOK_BEHIND_NOT);
#ifdef USE_NAMED_GROUP
else { /* (?<name>...) */
- if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP)) {
- UChar *name;
- UChar *name_end;
+ if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP)) {
+ UChar *name;
+ UChar *name_end;
- PUNFETCH;
- c = '<';
+ PUNFETCH;
+ c = '<';
- named_group1:
- list_capture = 0;
+ named_group1:
+ list_capture = 0;
# ifdef USE_CAPTURE_HISTORY
- named_group2:
+ named_group2:
# endif
- name = p;
- r = fetch_name((OnigCodePoint )c, &p, end, &name_end, env, &num, 0);
- if (r < 0) return r;
-
- num = scan_env_add_mem_entry(env);
- if (num < 0) return num;
- if (list_capture != 0 && num >= (int )BIT_STATUS_BITS_NUM)
- return ONIGERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY;
-
- r = name_add(env->reg, name, name_end, num, env);
- if (r != 0) return r;
- *np = node_new_enclose_memory(env->option, 1);
- CHECK_NULL_RETURN_MEMERR(*np);
- NENCLOSE(*np)->regnum = num;
- if (list_capture != 0)
- BIT_STATUS_ON_AT_SIMPLE(env->capture_history, num);
- env->num_named++;
- }
- else {
- return ONIGERR_UNDEFINED_GROUP_OPTION;
- }
+ name = p;
+ r = fetch_name((OnigCodePoint )c, &p, end, &name_end, env, &num, 0);
+ if (r < 0) return r;
+
+ num = scan_env_add_mem_entry(env);
+ if (num < 0) return num;
+ if (list_capture != 0 && num >= (int )BIT_STATUS_BITS_NUM)
+ return ONIGERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY;
+
+ r = name_add(env->reg, name, name_end, num, env);
+ if (r != 0) return r;
+ *np = node_new_enclose_memory(env->option, 1);
+ CHECK_NULL_RETURN_MEMERR(*np);
+ NENCLOSE(*np)->regnum = num;
+ if (list_capture != 0)
+ BIT_STATUS_ON_AT_SIMPLE(env->capture_history, num);
+ env->num_named++;
+ }
+ else {
+ return ONIGERR_UNDEFINED_GROUP_OPTION;
+ }
}
#else
else {
- return ONIGERR_UNDEFINED_GROUP_OPTION;
+ return ONIGERR_UNDEFINED_GROUP_OPTION;
}
#endif
break;
@@ -5210,122 +5214,122 @@ parse_enclose(Node** np, OnigToken* tok, int term, UChar** src, UChar* end,
case '@':
if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_ATMARK_CAPTURE_HISTORY)) {
# ifdef USE_NAMED_GROUP
- if (!PEND &&
- IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP)) {
- PFETCH(c);
- if (c == '<' || c == '\'') {
- list_capture = 1;
- goto named_group2; /* (?@<name>...) */
- }
- PUNFETCH;
- }
+ if (!PEND &&
+ IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_LT_NAMED_GROUP)) {
+ PFETCH(c);
+ if (c == '<' || c == '\'') {
+ list_capture = 1;
+ goto named_group2; /* (?@<name>...) */
+ }
+ PUNFETCH;
+ }
# endif
- *np = node_new_enclose_memory(env->option, 0);
- CHECK_NULL_RETURN_MEMERR(*np);
- num = scan_env_add_mem_entry(env);
- if (num < 0) return num;
- if (num >= (int )BIT_STATUS_BITS_NUM)
- return ONIGERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY;
+ *np = node_new_enclose_memory(env->option, 0);
+ CHECK_NULL_RETURN_MEMERR(*np);
+ num = scan_env_add_mem_entry(env);
+ if (num < 0) return num;
+ if (num >= (int )BIT_STATUS_BITS_NUM)
+ return ONIGERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY;
- NENCLOSE(*np)->regnum = num;
- BIT_STATUS_ON_AT_SIMPLE(env->capture_history, num);
+ NENCLOSE(*np)->regnum = num;
+ BIT_STATUS_ON_AT_SIMPLE(env->capture_history, num);
}
else {
- return ONIGERR_UNDEFINED_GROUP_OPTION;
+ return ONIGERR_UNDEFINED_GROUP_OPTION;
}
break;
#endif /* USE_CAPTURE_HISTORY */
case '(': /* conditional expression: (?(cond)yes), (?(cond)yes|no) */
if (!PEND &&
- IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_LPAREN_CONDITION)) {
- UChar *name = NULL;
- UChar *name_end;
- PFETCH(c);
- if (ONIGENC_IS_CODE_DIGIT(enc, c)) { /* (n) */
- PUNFETCH;
- r = fetch_name((OnigCodePoint )'(', &p, end, &name_end, env, &num, 1);
- if (r < 0) return r;
+ IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_LPAREN_CONDITION)) {
+ UChar *name = NULL;
+ UChar *name_end;
+ PFETCH(c);
+ if (ONIGENC_IS_CODE_DIGIT(enc, c)) { /* (n) */
+ PUNFETCH;
+ r = fetch_name((OnigCodePoint )'(', &p, end, &name_end, env, &num, 1);
+ if (r < 0) return r;
#if 0
- /* Relative number is not currently supported. (same as Perl) */
- if (num < 0) {
- num = BACKREF_REL_TO_ABS(num, env);
- if (num <= 0)
- return ONIGERR_INVALID_BACKREF;
- }
+ /* Relative number is not currently supported. (same as Perl) */
+ if (num < 0) {
+ num = BACKREF_REL_TO_ABS(num, env);
+ if (num <= 0)
+ return ONIGERR_INVALID_BACKREF;
+ }
#endif
- if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_STRICT_CHECK_BACKREF)) {
- if (num > env->num_mem ||
- IS_NULL(SCANENV_MEM_NODES(env)[num]))
- return ONIGERR_INVALID_BACKREF;
- }
- }
+ if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_STRICT_CHECK_BACKREF)) {
+ if (num > env->num_mem ||
+ IS_NULL(SCANENV_MEM_NODES(env)[num]))
+ return ONIGERR_INVALID_BACKREF;
+ }
+ }
#ifdef USE_NAMED_GROUP
- else if (c == '<' || c == '\'') { /* (<name>), ('name') */
- name = p;
- r = fetch_named_backref_token(c, tok, &p, end, env);
- if (r < 0) return r;
- if (!PPEEK_IS(')')) return ONIGERR_UNDEFINED_GROUP_OPTION;
- PINC;
-
- if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_USE_LEFT_MOST_NAMED_GROUP)) {
- num = tok->u.backref.ref1;
- }
- else {
- /* FIXME:
- * Use left most named group for now. This is the same as Perl.
- * However this should use the same strategy as normal back-
- * references on Ruby syntax; search right to left. */
- int len = tok->u.backref.num;
- num = len > 1 ? tok->u.backref.refs[0] : tok->u.backref.ref1;
- }
- }
+ else if (c == '<' || c == '\'') { /* (<name>), ('name') */
+ name = p;
+ r = fetch_named_backref_token(c, tok, &p, end, env);
+ if (r < 0) return r;
+ if (!PPEEK_IS(')')) return ONIGERR_UNDEFINED_GROUP_OPTION;
+ PINC;
+
+ if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_USE_LEFT_MOST_NAMED_GROUP)) {
+ num = tok->u.backref.ref1;
+ }
+ else {
+ /* FIXME:
+ * Use left most named group for now. This is the same as Perl.
+ * However this should use the same strategy as normal back-
+ * references on Ruby syntax; search right to left. */
+ int len = tok->u.backref.num;
+ num = len > 1 ? tok->u.backref.refs[0] : tok->u.backref.ref1;
+ }
+ }
#endif
- else
- return ONIGERR_INVALID_CONDITION_PATTERN;
- *np = node_new_enclose(ENCLOSE_CONDITION);
- CHECK_NULL_RETURN_MEMERR(*np);
- NENCLOSE(*np)->regnum = num;
- if (IS_NOT_NULL(name)) NENCLOSE(*np)->state |= NST_NAME_REF;
+ else
+ return ONIGERR_INVALID_CONDITION_PATTERN;
+ *np = node_new_enclose(ENCLOSE_CONDITION);
+ CHECK_NULL_RETURN_MEMERR(*np);
+ NENCLOSE(*np)->regnum = num;
+ if (IS_NOT_NULL(name)) NENCLOSE(*np)->state |= NST_NAME_REF;
}
else
- return ONIGERR_UNDEFINED_GROUP_OPTION;
+ return ONIGERR_UNDEFINED_GROUP_OPTION;
break;
#if 0
case '|': /* branch reset: (?|...) */
if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_QMARK_VBAR_BRANCH_RESET)) {
- /* TODO */
+ /* TODO */
}
else
- return ONIGERR_UNDEFINED_GROUP_OPTION;
+ return ONIGERR_UNDEFINED_GROUP_OPTION;
break;
#endif
case '^': /* loads default options */
if (!PEND && IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL)) {
- /* d-imsx */
- ONOFF(option, ONIG_OPTION_ASCII_RANGE, 1);
- ONOFF(option, ONIG_OPTION_IGNORECASE, 1);
- ONOFF(option, ONIG_OPTION_SINGLELINE, 0);
- ONOFF(option, ONIG_OPTION_MULTILINE, 1);
- ONOFF(option, ONIG_OPTION_EXTEND, 1);
- PFETCH(c);
+ /* d-imsx */
+ ONOFF(option, ONIG_OPTION_ASCII_RANGE, 1);
+ ONOFF(option, ONIG_OPTION_IGNORECASE, 1);
+ ONOFF(option, ONIG_OPTION_SINGLELINE, 0);
+ ONOFF(option, ONIG_OPTION_MULTILINE, 1);
+ ONOFF(option, ONIG_OPTION_EXTEND, 1);
+ PFETCH(c);
}
#if 0
else if (!PEND && IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_RUBY)) {
- /* d-imx */
- ONOFF(option, ONIG_OPTION_ASCII_RANGE, 0);
- ONOFF(option, ONIG_OPTION_POSIX_BRACKET_ALL_RANGE, 0);
- ONOFF(option, ONIG_OPTION_WORD_BOUND_ALL_RANGE, 0);
- ONOFF(option, ONIG_OPTION_IGNORECASE, 1);
- ONOFF(option, ONIG_OPTION_MULTILINE, 1);
- ONOFF(option, ONIG_OPTION_EXTEND, 1);
- PFETCH(c);
+ /* d-imx */
+ ONOFF(option, ONIG_OPTION_ASCII_RANGE, 0);
+ ONOFF(option, ONIG_OPTION_POSIX_BRACKET_ALL_RANGE, 0);
+ ONOFF(option, ONIG_OPTION_WORD_BOUND_ALL_RANGE, 0);
+ ONOFF(option, ONIG_OPTION_IGNORECASE, 1);
+ ONOFF(option, ONIG_OPTION_MULTILINE, 1);
+ ONOFF(option, ONIG_OPTION_EXTEND, 1);
+ PFETCH(c);
}
#endif
else {
- return ONIGERR_UNDEFINED_GROUP_OPTION;
+ return ONIGERR_UNDEFINED_GROUP_OPTION;
}
/* fall through */
#ifdef USE_POSIXLINE_OPTION
@@ -5334,120 +5338,120 @@ parse_enclose(Node** np, OnigToken* tok, int term, UChar** src, UChar* end,
case '-': case 'i': case 'm': case 's': case 'x':
case 'a': case 'd': case 'l': case 'u':
{
- int neg = 0;
-
- while (1) {
- switch (c) {
- case ':':
- case ')':
- break;
-
- case '-': neg = 1; break;
- case 'x': ONOFF(option, ONIG_OPTION_EXTEND, neg); break;
- case 'i': ONOFF(option, ONIG_OPTION_IGNORECASE, neg); break;
- case 's':
- if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL)) {
- ONOFF(option, ONIG_OPTION_MULTILINE, neg);
- }
- else
- return ONIGERR_UNDEFINED_GROUP_OPTION;
- break;
-
- case 'm':
- if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL)) {
- ONOFF(option, ONIG_OPTION_SINGLELINE, (neg == 0 ? 1 : 0));
- }
- else if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_RUBY)) {
- ONOFF(option, ONIG_OPTION_MULTILINE, neg);
- }
- else
- return ONIGERR_UNDEFINED_GROUP_OPTION;
- break;
+ int neg = 0;
+
+ while (1) {
+ switch (c) {
+ case ':':
+ case ')':
+ break;
+
+ case '-': neg = 1; break;
+ case 'x': ONOFF(option, ONIG_OPTION_EXTEND, neg); break;
+ case 'i': ONOFF(option, ONIG_OPTION_IGNORECASE, neg); break;
+ case 's':
+ if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL)) {
+ ONOFF(option, ONIG_OPTION_MULTILINE, neg);
+ }
+ else
+ return ONIGERR_UNDEFINED_GROUP_OPTION;
+ break;
+
+ case 'm':
+ if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL)) {
+ ONOFF(option, ONIG_OPTION_SINGLELINE, (neg == 0 ? 1 : 0));
+ }
+ else if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_RUBY)) {
+ ONOFF(option, ONIG_OPTION_MULTILINE, neg);
+ }
+ else
+ return ONIGERR_UNDEFINED_GROUP_OPTION;
+ break;
#ifdef USE_POSIXLINE_OPTION
- case 'p':
- ONOFF(option, ONIG_OPTION_MULTILINE|ONIG_OPTION_SINGLELINE, neg);
- break;
+ case 'p':
+ ONOFF(option, ONIG_OPTION_MULTILINE|ONIG_OPTION_SINGLELINE, neg);
+ break;
#endif
- case 'a': /* limits \d, \s, \w and POSIX brackets to ASCII range */
- if ((IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL) ||
- IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_RUBY)) &&
- (neg == 0)) {
- ONOFF(option, ONIG_OPTION_ASCII_RANGE, 0);
- ONOFF(option, ONIG_OPTION_POSIX_BRACKET_ALL_RANGE, 1);
- ONOFF(option, ONIG_OPTION_WORD_BOUND_ALL_RANGE, 1);
- }
- else
- return ONIGERR_UNDEFINED_GROUP_OPTION;
- break;
-
- case 'u':
- if ((IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL) ||
- IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_RUBY)) &&
- (neg == 0)) {
- ONOFF(option, ONIG_OPTION_ASCII_RANGE, 1);
- ONOFF(option, ONIG_OPTION_POSIX_BRACKET_ALL_RANGE, 1);
- ONOFF(option, ONIG_OPTION_WORD_BOUND_ALL_RANGE, 1);
- }
- else
- return ONIGERR_UNDEFINED_GROUP_OPTION;
- break;
-
- case 'd':
- if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL) &&
- (neg == 0)) {
- ONOFF(option, ONIG_OPTION_ASCII_RANGE, 1);
- }
- else if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_RUBY) &&
- (neg == 0)) {
- ONOFF(option, ONIG_OPTION_ASCII_RANGE, 0);
- ONOFF(option, ONIG_OPTION_POSIX_BRACKET_ALL_RANGE, 0);
- ONOFF(option, ONIG_OPTION_WORD_BOUND_ALL_RANGE, 0);
- }
- else
- return ONIGERR_UNDEFINED_GROUP_OPTION;
- break;
-
- case 'l':
- if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL) && (neg == 0)) {
- ONOFF(option, ONIG_OPTION_ASCII_RANGE, 1);
- }
- else
- return ONIGERR_UNDEFINED_GROUP_OPTION;
- break;
-
- default:
- return ONIGERR_UNDEFINED_GROUP_OPTION;
- }
-
- if (c == ')') {
- *np = node_new_option(option);
- CHECK_NULL_RETURN_MEMERR(*np);
- *src = p;
- return 2; /* option only */
- }
- else if (c == ':') {
- OnigOptionType prev = env->option;
-
- env->option = option;
- r = fetch_token(tok, &p, end, env);
- if (r < 0) {
- env->option = prev;
- return r;
- }
- r = parse_subexp(&target, tok, term, &p, end, env);
- env->option = prev;
- if (r < 0) return r;
- *np = node_new_option(option);
- CHECK_NULL_RETURN_MEMERR(*np);
- NENCLOSE(*np)->target = target;
- *src = p;
- return 0;
- }
-
- if (PEND) return ONIGERR_END_PATTERN_IN_GROUP;
- PFETCH(c);
- }
+ case 'a': /* limits \d, \s, \w and POSIX brackets to ASCII range */
+ if ((IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL) ||
+ IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_RUBY)) &&
+ (neg == 0)) {
+ ONOFF(option, ONIG_OPTION_ASCII_RANGE, 0);
+ ONOFF(option, ONIG_OPTION_POSIX_BRACKET_ALL_RANGE, 1);
+ ONOFF(option, ONIG_OPTION_WORD_BOUND_ALL_RANGE, 1);
+ }
+ else
+ return ONIGERR_UNDEFINED_GROUP_OPTION;
+ break;
+
+ case 'u':
+ if ((IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL) ||
+ IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_RUBY)) &&
+ (neg == 0)) {
+ ONOFF(option, ONIG_OPTION_ASCII_RANGE, 1);
+ ONOFF(option, ONIG_OPTION_POSIX_BRACKET_ALL_RANGE, 1);
+ ONOFF(option, ONIG_OPTION_WORD_BOUND_ALL_RANGE, 1);
+ }
+ else
+ return ONIGERR_UNDEFINED_GROUP_OPTION;
+ break;
+
+ case 'd':
+ if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL) &&
+ (neg == 0)) {
+ ONOFF(option, ONIG_OPTION_ASCII_RANGE, 1);
+ }
+ else if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_RUBY) &&
+ (neg == 0)) {
+ ONOFF(option, ONIG_OPTION_ASCII_RANGE, 0);
+ ONOFF(option, ONIG_OPTION_POSIX_BRACKET_ALL_RANGE, 0);
+ ONOFF(option, ONIG_OPTION_WORD_BOUND_ALL_RANGE, 0);
+ }
+ else
+ return ONIGERR_UNDEFINED_GROUP_OPTION;
+ break;
+
+ case 'l':
+ if (IS_SYNTAX_OP2(env->syntax, ONIG_SYN_OP2_OPTION_PERL) && (neg == 0)) {
+ ONOFF(option, ONIG_OPTION_ASCII_RANGE, 1);
+ }
+ else
+ return ONIGERR_UNDEFINED_GROUP_OPTION;
+ break;
+
+ default:
+ return ONIGERR_UNDEFINED_GROUP_OPTION;
+ }
+
+ if (c == ')') {
+ *np = node_new_option(option);
+ CHECK_NULL_RETURN_MEMERR(*np);
+ *src = p;
+ return 2; /* option only */
+ }
+ else if (c == ':') {
+ OnigOptionType prev = env->option;
+
+ env->option = option;
+ r = fetch_token(tok, &p, end, env);
+ if (r < 0) {
+ env->option = prev;
+ return r;
+ }
+ r = parse_subexp(&target, tok, term, &p, end, env);
+ env->option = prev;
+ if (r < 0) return r;
+ *np = node_new_option(option);
+ CHECK_NULL_RETURN_MEMERR(*np);
+ NENCLOSE(*np)->target = target;
+ *src = p;
+ return 0;
+ }
+
+ if (PEND) return ONIGERR_END_PATTERN_IN_GROUP;
+ PFETCH(c);
+ }
}
break;
@@ -5486,14 +5490,14 @@ parse_enclose(Node** np, OnigToken* tok, int term, UChar** src, UChar* end,
}
else if (NENCLOSE(*np)->type == ENCLOSE_CONDITION) {
if (NTYPE(target) != NT_ALT) {
- /* convert (?(cond)yes) to (?(cond)yes|empty) */
- work1 = node_new_empty();
- if (IS_NULL(work1)) goto err;
- work2 = onig_node_new_alt(work1, NULL_NODE);
- if (IS_NULL(work2)) goto err;
- work1 = onig_node_new_alt(target, work2);
- if (IS_NULL(work1)) goto err;
- NENCLOSE(*np)->target = work1;
+ /* convert (?(cond)yes) to (?(cond)yes|empty) */
+ work1 = node_new_empty();
+ if (IS_NULL(work1)) goto err;
+ work2 = onig_node_new_alt(work1, NULL_NODE);
+ if (IS_NULL(work2)) goto err;
+ work1 = onig_node_new_alt(target, work2);
+ if (IS_NULL(work1)) goto err;
+ NENCLOSE(*np)->target = work1;
}
}
}
@@ -5532,11 +5536,11 @@ set_quantifier(Node* qnode, Node* target, int group, ScanEnv* env)
if (! group) {
StrNode* sn = NSTR(target);
if (str_node_can_be_split(sn, env->enc)) {
- Node* n = str_node_split_last_char(sn, env->enc);
- if (IS_NOT_NULL(n)) {
- qn->target = n;
- return 2;
- }
+ Node* n = str_node_split_last_char(sn, env->enc);
+ if (IS_NOT_NULL(n)) {
+ qn->target = n;
+ return 2;
+ }
}
}
break;
@@ -5550,43 +5554,43 @@ set_quantifier(Node* qnode, Node* target, int group, ScanEnv* env)
#ifdef USE_WARNING_REDUNDANT_NESTED_REPEAT_OPERATOR
if (nestq_num >= 0 && targetq_num >= 0 &&
- IS_SYNTAX_BV(env->syntax, ONIG_SYN_WARN_REDUNDANT_NESTED_REPEAT)) {
- switch (ReduceTypeTable[targetq_num][nestq_num]) {
- case RQ_ASIS:
- break;
-
- case RQ_DEL:
- if (onig_warn != onig_null_warn) {
- onig_syntax_warn(env, "regular expression has redundant nested repeat operator '%s'",
- PopularQStr[targetq_num]);
- }
- goto warn_exit;
- break;
-
- default:
- if (onig_warn != onig_null_warn) {
- onig_syntax_warn(env, "nested repeat operator '%s' and '%s' was replaced with '%s' in regular expression",
- PopularQStr[targetq_num], PopularQStr[nestq_num],
- ReduceQStr[ReduceTypeTable[targetq_num][nestq_num]]);
- }
- goto warn_exit;
- break;
- }
+ IS_SYNTAX_BV(env->syntax, ONIG_SYN_WARN_REDUNDANT_NESTED_REPEAT)) {
+ switch (ReduceTypeTable[targetq_num][nestq_num]) {
+ case RQ_ASIS:
+ break;
+
+ case RQ_DEL:
+ if (onig_warn != onig_null_warn) {
+ onig_syntax_warn(env, "regular expression has redundant nested repeat operator '%s'",
+ PopularQStr[targetq_num]);
+ }
+ goto warn_exit;
+ break;
+
+ default:
+ if (onig_warn != onig_null_warn) {
+ onig_syntax_warn(env, "nested repeat operator '%s' and '%s' was replaced with '%s' in regular expression",
+ PopularQStr[targetq_num], PopularQStr[nestq_num],
+ ReduceQStr[ReduceTypeTable[targetq_num][nestq_num]]);
+ }
+ goto warn_exit;
+ break;
+ }
}
warn_exit:
#endif
if (targetq_num >= 0) {
- if (nestq_num >= 0) {
- onig_reduce_nested_quantifier(qnode, target);
- goto q_exit;
- }
- else if (targetq_num == 1 || targetq_num == 2) { /* * or + */
- /* (?:a*){n,m}, (?:a+){n,m} => (?:a*){n,n}, (?:a+){n,n} */
- if (! IS_REPEAT_INFINITE(qn->upper) && qn->upper > 1 && qn->greedy) {
- qn->upper = (qn->lower == 0 ? 1 : qn->lower);
- }
- }
+ if (nestq_num >= 0) {
+ onig_reduce_nested_quantifier(qnode, target);
+ goto q_exit;
+ }
+ else if (targetq_num == 1 || targetq_num == 2) { /* * or + */
+ /* (?:a*){n,m}, (?:a+){n,m} => (?:a*){n,n}, (?:a+){n,n} */
+ if (! IS_REPEAT_INFINITE(qn->upper) && qn->upper > 1 && qn->greedy) {
+ qn->upper = (qn->lower == 0 ? 1 : qn->lower);
+ }
+ }
}
}
break;
@@ -5626,6 +5630,22 @@ clear_not_flag_cclass(CClassNode* cc, OnigEncoding enc)
}
#endif /* CASE_FOLD_IS_APPLIED_INSIDE_NEGATIVE_CCLASS */
+static inline bool
+is_singlebyte_range(OnigCodePoint code, OnigEncoding enc)
+{
+ /* single byte encoding */
+ if (ONIGENC_MBC_MAXLEN(enc) == 1) {
+ return true;
+ }
+
+ /* wide char encoding */
+ if (ONIGENC_MBC_MINLEN(enc) > 1) {
+ return false;
+ }
+
+ return (code < 0x80);
+}
+
typedef struct {
ScanEnv* env;
CClassNode* cc;
@@ -5636,7 +5656,7 @@ typedef struct {
static int
i_apply_case_fold(OnigCodePoint from, OnigCodePoint to[],
- int to_len, void* arg)
+ int to_len, void* arg)
{
IApplyCaseFoldArg* iarg;
ScanEnv* env;
@@ -5667,33 +5687,33 @@ i_apply_case_fold(OnigCodePoint from, OnigCodePoint to[],
int is_in = onig_is_code_in_cc(env->enc, from, cc);
#ifdef CASE_FOLD_IS_APPLIED_INSIDE_NEGATIVE_CCLASS
if ((is_in != 0 && !IS_NCCLASS_NOT(cc)) ||
- (is_in == 0 && IS_NCCLASS_NOT(cc))) {
+ (is_in == 0 && IS_NCCLASS_NOT(cc))) {
if (add_flag) {
- if (ONIGENC_MBC_MINLEN(env->enc) > 1 || *to >= SINGLE_BYTE_SIZE) {
- r = add_code_range0(&(cc->mbuf), env, *to, *to, 0);
- if (r < 0) return r;
- }
- else {
- BITSET_SET_BIT(bs, *to);
- }
+ if (is_singlebyte_range(*to, env->enc)) {
+ BITSET_SET_BIT(bs, *to);
+ }
+ else {
+ r = add_code_range0(&(cc->mbuf), env, *to, *to, 0);
+ if (r < 0) return r;
+ }
}
}
#else
if (is_in != 0) {
if (add_flag) {
- if (ONIGENC_MBC_MINLEN(env->enc) > 1 || *to >= SINGLE_BYTE_SIZE) {
- if (IS_NCCLASS_NOT(cc)) clear_not_flag_cclass(cc, env->enc);
- r = add_code_range0(&(cc->mbuf), env, *to, *to, 0);
- if (r < 0) return r;
- }
- else {
- if (IS_NCCLASS_NOT(cc)) {
- BITSET_CLEAR_BIT(bs, *to);
- }
- else {
- BITSET_SET_BIT(bs, *to);
- }
- }
+ if (is_singlebyte_range(*to, env->enc)) {
+ if (IS_NCCLASS_NOT(cc)) {
+ BITSET_CLEAR_BIT(bs, *to);
+ }
+ else {
+ BITSET_SET_BIT(bs, *to);
+ }
+ }
+ else {
+ if (IS_NCCLASS_NOT(cc)) clear_not_flag_cclass(cc, env->enc);
+ r = add_code_range0(&(cc->mbuf), env, *to, *to, 0);
+ if (r < 0) return r;
+ }
}
}
#endif /* CASE_FOLD_IS_APPLIED_INSIDE_NEGATIVE_CCLASS */
@@ -5705,26 +5725,26 @@ i_apply_case_fold(OnigCodePoint from, OnigCodePoint to[],
if (onig_is_code_in_cc(env->enc, from, cc)
#ifdef CASE_FOLD_IS_APPLIED_INSIDE_NEGATIVE_CCLASS
- && !IS_NCCLASS_NOT(cc)
+ && !IS_NCCLASS_NOT(cc)
#endif
- ) {
+ ) {
for (i = 0; i < to_len; i++) {
- len = ONIGENC_CODE_TO_MBC(env->enc, to[i], buf);
- if (i == 0) {
- snode = onig_node_new_str(buf, buf + len);
- CHECK_NULL_RETURN_MEMERR(snode);
-
- /* char-class expanded multi-char only
- compare with string folded at match time. */
- NSTRING_SET_AMBIG(snode);
- }
- else {
- r = onig_node_str_cat(snode, buf, buf + len);
- if (r < 0) {
- onig_node_free(snode);
- return r;
- }
- }
+ len = ONIGENC_CODE_TO_MBC(env->enc, to[i], buf);
+ if (i == 0) {
+ snode = onig_node_new_str(buf, buf + len);
+ CHECK_NULL_RETURN_MEMERR(snode);
+
+ /* char-class expanded multi-char only
+ compare with string folded at match time. */
+ NSTRING_SET_AMBIG(snode);
+ }
+ else {
+ r = onig_node_str_cat(snode, buf, buf + len);
+ if (r < 0) {
+ onig_node_free(snode);
+ return r;
+ }
+ }
}
*(iarg->ptail) = onig_node_new_alt(snode, NULL_NODE);
@@ -5749,7 +5769,7 @@ cclass_case_fold(Node** np, CClassNode* cc, CClassNode* asc_cc, ScanEnv* env)
iarg.ptail = &(iarg.alt_root);
r = ONIGENC_APPLY_ALL_CASE_FOLD(env->enc, env->case_fold_flag,
- i_apply_case_fold, &iarg);
+ i_apply_case_fold, &iarg);
if (r != 0) {
onig_node_free(iarg.alt_root);
return r;
@@ -5937,19 +5957,21 @@ create_node_from_array(int kind, Node **np, Node **node_array)
* nodes of the source to NULL_NODE, we can overlap the target array
* as long as we do not override the actual target location.
*
- * Target Array name Index
+ * Target Array name Index
*
- * node_array 0 1 2 3 4 5 6 7 8 9 A B C D E F
- * top_alts alts[5] 0 1 2 3 4*
- * alts+1 list[4] 0 1 2 3*
- * list+1 core_alts[7] 0 1 2 3 4 5 6*
- * core_alts+0 H_list[4] 0 1 2 3*
- * H_list+1 H_alt2[4] 0 1 2 3*
- * h_alt2+1 H_list2[3] 0 1 2*
- * core_alts+4 XP_list[4] 0 1 2 3*
- * XP_list+1 Ex_list[4] 0 1 2 3*
+ * node_array 0 1 2 3 4 5 6 7 8 9 A B C D E F G H
+ * top_alts alts[5] 0 1 2 3 4*
+ * alts+2 list[4] 0 1 2 3*
+ * list+1 core_alts[8] 0 1 2 3 4 5 6 7*
+ * core_alts+0 H_list[4] 0 1 2 3*
+ * H_list+1 H_alt2[4] 0 1 2 3*
+ * H_alt2+1 H_list2[3] 0 1 2*
+ * core_alts+4 XP_list[3] 0 1 2*
+ * XP_list+1 Ex_list[4] 0 1 2 3*
+ * core_alts+5 CC_list[3] 0 1 2*
+ * CC_list+1 CC_inner_list[5] 0 1 2 3 4*
*/
-#define NODE_COMMON_SIZE 16
+#define NODE_COMMON_SIZE 18
static int
node_extended_grapheme_cluster(Node** np, ScanEnv* env)
@@ -6016,9 +6038,10 @@ node_extended_grapheme_cluster(Node** np, ScanEnv* env)
/* core := hangul-syllable
* | ri-sequence
* | xpicto-sequence
+ * | conjunctCluster
* | [^Control CR LF] */
{
- Node **core_alts = list + 2; /* size: 7 */
+ Node **core_alts = list + 2; /* size: 8 */
/* hangul-syllable :=
* L* (V+ | LV V* | LVT) T*
@@ -6086,10 +6109,49 @@ node_extended_grapheme_cluster(Node** np, ScanEnv* env)
R_ERR(create_node_from_array(LIST, core_alts+4, XP_list));
}
+ /* conjunctCluster := \p{InCB=Consonant} ([\p{InCB=Extend} \p{InCB=Linker}]* \p{InCB=Linker} [\p{InCB=Extend} \p{InCB=Linker}]* \p{InCB=Consonant})+ */
+ {
+ // \p{InCB=Consonant}
+ Node **CC_list = core_alts + 6; /* size: 3 */
+ R_ERR(create_property_node(CC_list+0, env, "InCB=Consonant"));
+
+ {
+ Node **CC_inner_list = CC_list + 2; /* size: 5 */
+ {
+ // [\p{InCB=Extend} \p{InCB=Linker}]*
+ R_ERR(create_property_node(CC_inner_list+0, env, "InCB=Extend"));
+ R_ERR(add_property_to_cc(NCCLASS(CC_inner_list[0]), "InCB=Linker", 0, env));
+ R_ERR(quantify_node(CC_inner_list+0, 0, REPEAT_INFINITE));
+ }
+
+ // \p{InCB=Linker}
+ R_ERR(create_property_node(CC_inner_list+1, env, "InCB=Linker"));
+
+ {
+ // [\p{InCB=Extend} \p{InCB=Linker}]*
+ R_ERR(create_property_node(CC_inner_list+2, env, "InCB=Extend"));
+ R_ERR(add_property_to_cc(NCCLASS(CC_inner_list[2]), "InCB=Linker", 0, env));
+ R_ERR(quantify_node(CC_inner_list+2, 0, REPEAT_INFINITE));
+ }
+
+ // \p{InCB=Consonant}
+ R_ERR(create_property_node(CC_inner_list+3, env, "InCB=Consonant"));
+
+ // ([\p{InCB=Extend} \p{InCB=Linker}]* \p{InCB=Linker} [\p{InCB=Extend} \p{InCB=Linker}]* \p{InCB=Consonant})
+ R_ERR(create_node_from_array(LIST, CC_list+1, CC_inner_list));
+
+ // (...)+
+ R_ERR(quantify_node(CC_list+1, 1, REPEAT_INFINITE));
+ }
+
+ // \p{InCB=Consonant} ([\p{InCB=Extend} \p{InCB=Linker}]* \p{InCB=Linker} [\p{InCB=Extend} \p{InCB=Linker}]* \p{InCB=Consonant})+
+ R_ERR(create_node_from_array(LIST, core_alts+5, CC_list));
+ }
+
/* [^Control CR LF] */
- core_alts[5] = node_new_cclass();
- if (IS_NULL(core_alts[5])) goto err;
- cc = NCCLASS(core_alts[5]);
+ core_alts[6] = node_new_cclass();
+ if (IS_NULL(core_alts[6])) goto err;
+ cc = NCCLASS(core_alts[6]);
if (ONIGENC_MBC_MINLEN(env->enc) > 1) { /* UTF-16/UTF-32 */
BBuf *inverted_buf = NULL;
@@ -6212,8 +6274,8 @@ is_onechar_cclass(CClassNode* cc, OnigCodePoint* code)
/* only one char found in the bbuf, save the code point. */
c = data[0];
if (((c < SINGLE_BYTE_SIZE) && BITSET_AT(cc->bs, c))) {
- /* skip if c is included in the bitset */
- c = not_found;
+ /* skip if c is included in the bitset */
+ c = not_found;
}
}
else {
@@ -6226,9 +6288,10 @@ is_onechar_cclass(CClassNode* cc, OnigCodePoint* code)
Bits b1 = cc->bs[i];
if (b1 != 0) {
if (((b1 & (b1 - 1)) == 0) && (c == not_found)) {
- c = BITS_IN_ROOM * i + countbits(b1 - 1);
- } else {
- return 0; /* the character class contains multiple chars */
+ c = BITS_IN_ROOM * i + countbits(b1 - 1);
+ }
+ else {
+ return 0; /* the character class contains multiple chars */
}
}
}
@@ -6245,16 +6308,19 @@ is_onechar_cclass(CClassNode* cc, OnigCodePoint* code)
static int
parse_exp(Node** np, OnigToken* tok, int term,
- UChar** src, UChar* end, ScanEnv* env)
+ UChar** src, UChar* end, ScanEnv* env)
{
int r, len, group = 0;
Node* qn;
Node** targetp;
+ unsigned int parse_depth;
*np = NULL;
if (tok->type == (enum TokenSyms )term)
goto end_of_token;
+ parse_depth = env->parse_depth;
+
switch (tok->type) {
case TK_ALT:
case TK_EOT:
@@ -6274,14 +6340,14 @@ parse_exp(Node** np, OnigToken* tok, int term,
env->option = NENCLOSE(*np)->option;
r = fetch_token(tok, src, end, env);
if (r < 0) {
- env->option = prev;
- return r;
+ env->option = prev;
+ return r;
}
r = parse_subexp(&target, tok, term, src, end, env);
env->option = prev;
if (r < 0) {
- onig_node_free(target);
- return r;
+ onig_node_free(target);
+ return r;
}
NENCLOSE(*np)->target = target;
return tok->type;
@@ -6319,20 +6385,20 @@ parse_exp(Node** np, OnigToken* tok, int term,
string_loop:
while (1) {
- r = fetch_token(tok, src, end, env);
- if (r < 0) return r;
- if (r == TK_STRING) {
- r = onig_node_str_cat(*np, tok->backp, *src);
- }
+ r = fetch_token(tok, src, end, env);
+ if (r < 0) return r;
+ if (r == TK_STRING) {
+ r = onig_node_str_cat(*np, tok->backp, *src);
+ }
#ifndef NUMBERED_CHAR_IS_NOT_CASE_AMBIG
- else if (r == TK_CODE_POINT) {
- r = node_str_cat_codepoint(*np, env->enc, tok->u.code);
- }
+ else if (r == TK_CODE_POINT) {
+ r = node_str_cat_codepoint(*np, env->enc, tok->u.code);
+ }
#endif
- else {
- break;
- }
- if (r < 0) return r;
+ else {
+ break;
+ }
+ if (r < 0) return r;
}
string_end:
@@ -6348,36 +6414,36 @@ parse_exp(Node** np, OnigToken* tok, int term,
CHECK_NULL_RETURN_MEMERR(*np);
len = 1;
while (1) {
- if (len >= ONIGENC_MBC_MINLEN(env->enc)) {
- if (len == enclen(env->enc, NSTR(*np)->s, NSTR(*np)->end)) {
- r = fetch_token(tok, src, end, env);
- NSTRING_CLEAR_RAW(*np);
- goto string_end;
- }
- }
-
- r = fetch_token(tok, src, end, env);
- if (r < 0) return r;
- if (r != TK_RAW_BYTE) {
- /* Don't use this, it is wrong for little endian encodings. */
+ if (len >= ONIGENC_MBC_MINLEN(env->enc)) {
+ if (len == enclen(env->enc, NSTR(*np)->s, NSTR(*np)->end)) {
+ r = fetch_token(tok, src, end, env);
+ NSTRING_CLEAR_RAW(*np);
+ goto string_end;
+ }
+ }
+
+ r = fetch_token(tok, src, end, env);
+ if (r < 0) return r;
+ if (r != TK_RAW_BYTE) {
+ /* Don't use this, it is wrong for little endian encodings. */
#ifdef USE_PAD_TO_SHORT_BYTE_CHAR
- int rem;
- if (len < ONIGENC_MBC_MINLEN(env->enc)) {
- rem = ONIGENC_MBC_MINLEN(env->enc) - len;
- (void )node_str_head_pad(NSTR(*np), rem, (UChar )0);
- if (len + rem == enclen(env->enc, NSTR(*np)->s)) {
- NSTRING_CLEAR_RAW(*np);
- goto string_end;
- }
- }
+ int rem;
+ if (len < ONIGENC_MBC_MINLEN(env->enc)) {
+ rem = ONIGENC_MBC_MINLEN(env->enc) - len;
+ (void )node_str_head_pad(NSTR(*np), rem, (UChar )0);
+ if (len + rem == enclen(env->enc, NSTR(*np)->s)) {
+ NSTRING_CLEAR_RAW(*np);
+ goto string_end;
+ }
+ }
#endif
- return ONIGERR_TOO_SHORT_MULTI_BYTE_STRING;
- }
+ return ONIGERR_TOO_SHORT_MULTI_BYTE_STRING;
+ }
- r = node_str_cat_char(*np, (UChar )tok->u.c);
- if (r < 0) return r;
+ r = node_str_cat_char(*np, (UChar )tok->u.c);
+ if (r < 0) return r;
- len++;
+ len++;
}
}
break;
@@ -6406,7 +6472,7 @@ parse_exp(Node** np, OnigToken* tok, int term,
qstart = *src;
qend = find_str_position(end_op, 2, qstart, end, &nextp, env->enc);
if (IS_NULL(qend)) {
- nextp = qend = end;
+ nextp = qend = end;
}
*np = node_new_str(qstart, qend);
CHECK_NULL_RETURN_MEMERR(*np);
@@ -6418,30 +6484,30 @@ parse_exp(Node** np, OnigToken* tok, int term,
{
switch (tok->u.prop.ctype) {
case ONIGENC_CTYPE_WORD:
- *np = node_new_ctype(tok->u.prop.ctype, tok->u.prop.not,
- IS_ASCII_RANGE(env->option));
- CHECK_NULL_RETURN_MEMERR(*np);
- break;
+ *np = node_new_ctype(tok->u.prop.ctype, tok->u.prop.not,
+ IS_ASCII_RANGE(env->option));
+ CHECK_NULL_RETURN_MEMERR(*np);
+ break;
case ONIGENC_CTYPE_SPACE:
case ONIGENC_CTYPE_DIGIT:
case ONIGENC_CTYPE_XDIGIT:
- {
- CClassNode* cc;
-
- *np = node_new_cclass();
- CHECK_NULL_RETURN_MEMERR(*np);
- cc = NCCLASS(*np);
- r = add_ctype_to_cc(cc, tok->u.prop.ctype, 0,
- IS_ASCII_RANGE(env->option), env);
- if (r != 0) return r;
- if (tok->u.prop.not != 0) NCCLASS_SET_NOT(cc);
- }
- break;
+ {
+ CClassNode* cc;
+
+ *np = node_new_cclass();
+ CHECK_NULL_RETURN_MEMERR(*np);
+ cc = NCCLASS(*np);
+ r = add_ctype_to_cc(cc, tok->u.prop.ctype, 0,
+ IS_ASCII_RANGE(env->option), env);
+ if (r != 0) return r;
+ if (tok->u.prop.not != 0) NCCLASS_SET_NOT(cc);
+ }
+ break;
default:
- return ONIGERR_PARSER_BUG;
- break;
+ return ONIGERR_PARSER_BUG;
+ break;
}
}
break;
@@ -6459,26 +6525,26 @@ parse_exp(Node** np, OnigToken* tok, int term,
r = parse_char_class(np, &asc_node, tok, src, end, env);
if (r != 0) {
- onig_node_free(asc_node);
- return r;
+ onig_node_free(asc_node);
+ return r;
}
cc = NCCLASS(*np);
if (is_onechar_cclass(cc, &code)) {
- onig_node_free(*np);
- onig_node_free(asc_node);
- *np = node_new_empty();
- CHECK_NULL_RETURN_MEMERR(*np);
- r = node_str_cat_codepoint(*np, env->enc, code);
- if (r != 0) return r;
- goto string_loop;
+ onig_node_free(*np);
+ onig_node_free(asc_node);
+ *np = node_new_empty();
+ CHECK_NULL_RETURN_MEMERR(*np);
+ r = node_str_cat_codepoint(*np, env->enc, code);
+ if (r != 0) return r;
+ goto string_loop;
}
if (IS_IGNORECASE(env->option)) {
- r = cclass_case_fold(np, cc, NCCLASS(asc_node), env);
- if (r != 0) {
- onig_node_free(asc_node);
- return r;
- }
+ r = cclass_case_fold(np, cc, NCCLASS(asc_node), env);
+ if (r != 0) {
+ onig_node_free(asc_node);
+ return r;
+ }
}
onig_node_free(asc_node);
}
@@ -6501,13 +6567,13 @@ parse_exp(Node** np, OnigToken* tok, int term,
case TK_BACKREF:
len = tok->u.backref.num;
*np = node_new_backref(len,
- (len > 1 ? tok->u.backref.refs : &(tok->u.backref.ref1)),
- tok->u.backref.by_name,
+ (len > 1 ? tok->u.backref.refs : &(tok->u.backref.ref1)),
+ tok->u.backref.by_name,
#ifdef USE_BACKREF_WITH_LEVEL
- tok->u.backref.exist_level,
- tok->u.backref.level,
+ tok->u.backref.exist_level,
+ tok->u.backref.level,
#endif
- env);
+ env);
CHECK_NULL_RETURN_MEMERR(*np);
break;
@@ -6517,10 +6583,10 @@ parse_exp(Node** np, OnigToken* tok, int term,
int gnum = tok->u.call.gnum;
if (gnum < 0 || tok->u.call.rel != 0) {
- if (gnum > 0) gnum--;
- gnum = BACKREF_REL_TO_ABS(gnum, env);
- if (gnum <= 0)
- return ONIGERR_INVALID_BACKREF;
+ if (gnum > 0) gnum--;
+ gnum = BACKREF_REL_TO_ABS(gnum, env);
+ if (gnum <= 0)
+ return ONIGERR_INVALID_BACKREF;
}
*np = node_new_call(tok->u.call.name, tok->u.call.name_end, gnum);
CHECK_NULL_RETURN_MEMERR(*np);
@@ -6539,9 +6605,9 @@ parse_exp(Node** np, OnigToken* tok, int term,
case TK_INTERVAL:
if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_CONTEXT_INDEP_REPEAT_OPS)) {
if (IS_SYNTAX_BV(env->syntax, ONIG_SYN_CONTEXT_INVALID_REPEAT_OPS))
- return ONIGERR_TARGET_OF_REPEAT_OPERATOR_NOT_SPECIFIED;
+ return ONIGERR_TARGET_OF_REPEAT_OPERATOR_NOT_SPECIFIED;
else
- *np = node_new_empty();
+ *np = node_new_empty();
}
else {
goto tk_byte;
@@ -6563,49 +6629,53 @@ parse_exp(Node** np, OnigToken* tok, int term,
repeat:
if (r == TK_OP_REPEAT || r == TK_INTERVAL) {
if (is_invalid_quantifier_target(*targetp))
- return ONIGERR_TARGET_OF_REPEAT_OPERATOR_INVALID;
+ return ONIGERR_TARGET_OF_REPEAT_OPERATOR_INVALID;
+
+ parse_depth++;
+ if (parse_depth > ParseDepthLimit)
+ return ONIGERR_PARSE_DEPTH_LIMIT_OVER;
qn = node_new_quantifier(tok->u.repeat.lower, tok->u.repeat.upper,
- (r == TK_INTERVAL ? 1 : 0));
+ (r == TK_INTERVAL ? 1 : 0));
CHECK_NULL_RETURN_MEMERR(qn);
NQTFR(qn)->greedy = tok->u.repeat.greedy;
r = set_quantifier(qn, *targetp, group, env);
if (r < 0) {
- onig_node_free(qn);
- return r;
+ onig_node_free(qn);
+ return r;
}
if (tok->u.repeat.possessive != 0) {
- Node* en;
- en = node_new_enclose(ENCLOSE_STOP_BACKTRACK);
- if (IS_NULL(en)) {
- onig_node_free(qn);
- return ONIGERR_MEMORY;
- }
- NENCLOSE(en)->target = qn;
- qn = en;
+ Node* en;
+ en = node_new_enclose(ENCLOSE_STOP_BACKTRACK);
+ if (IS_NULL(en)) {
+ onig_node_free(qn);
+ return ONIGERR_MEMORY;
+ }
+ NENCLOSE(en)->target = qn;
+ qn = en;
}
if (r == 0) {
- *targetp = qn;
+ *targetp = qn;
}
else if (r == 1) {
- onig_node_free(qn);
+ onig_node_free(qn);
}
else if (r == 2) { /* split case: /abc+/ */
- Node *tmp;
-
- *targetp = node_new_list(*targetp, NULL);
- if (IS_NULL(*targetp)) {
- onig_node_free(qn);
- return ONIGERR_MEMORY;
- }
- tmp = NCDR(*targetp) = node_new_list(qn, NULL);
- if (IS_NULL(tmp)) {
- onig_node_free(qn);
- return ONIGERR_MEMORY;
- }
- targetp = &(NCAR(tmp));
+ Node *tmp;
+
+ *targetp = node_new_list(*targetp, NULL);
+ if (IS_NULL(*targetp)) {
+ onig_node_free(qn);
+ return ONIGERR_MEMORY;
+ }
+ tmp = NCDR(*targetp) = node_new_list(qn, NULL);
+ if (IS_NULL(tmp)) {
+ onig_node_free(qn);
+ return ONIGERR_MEMORY;
+ }
+ targetp = &(NCAR(tmp));
}
goto re_entry;
}
@@ -6616,7 +6686,7 @@ parse_exp(Node** np, OnigToken* tok, int term,
static int
parse_branch(Node** top, OnigToken* tok, int term,
- UChar** src, UChar* end, ScanEnv* env)
+ UChar** src, UChar* end, ScanEnv* env)
{
int r;
Node *node, **headp;
@@ -6637,18 +6707,18 @@ parse_branch(Node** top, OnigToken* tok, int term,
while (r != TK_EOT && r != term && r != TK_ALT) {
r = parse_exp(&node, tok, term, src, end, env);
if (r < 0) {
- onig_node_free(node);
- return r;
+ onig_node_free(node);
+ return r;
}
if (NTYPE(node) == NT_LIST) {
- *headp = node;
- while (IS_NOT_NULL(NCDR(node))) node = NCDR(node);
- headp = &(NCDR(node));
+ *headp = node;
+ while (IS_NOT_NULL(NCDR(node))) node = NCDR(node);
+ headp = &(NCDR(node));
}
else {
- *headp = node_new_list(node, NULL);
- headp = &(NCDR(*headp));
+ *headp = node_new_list(node, NULL);
+ headp = &(NCDR(*headp));
}
}
}
@@ -6659,10 +6729,10 @@ parse_branch(Node** top, OnigToken* tok, int term,
/* term_tok: TK_EOT or TK_SUBEXP_CLOSE */
static int
parse_subexp(Node** top, OnigToken* tok, int term,
- UChar** src, UChar* end, ScanEnv* env)
+ UChar** src, UChar* end, ScanEnv* env)
{
int r;
- Node *node, **headp;
+ Node *node, *topnode, **headp;
*top = NULL;
env->parse_depth++;
@@ -6678,23 +6748,29 @@ parse_subexp(Node** top, OnigToken* tok, int term,
*top = node;
}
else if (r == TK_ALT) {
- *top = onig_node_new_alt(node, NULL);
- headp = &(NCDR(*top));
+ topnode = onig_node_new_alt(node, NULL);
+ headp = &(NCDR(topnode));
while (r == TK_ALT) {
r = fetch_token(tok, src, end, env);
- if (r < 0) return r;
+ if (r < 0) {
+ onig_node_free(topnode);
+ return r;
+ }
r = parse_branch(&node, tok, term, src, end, env);
if (r < 0) {
- onig_node_free(node);
- return r;
+ onig_node_free(topnode);
+ return r;
}
*headp = onig_node_new_alt(node, NULL);
- headp = &(NCDR(*headp));
+ headp = &(NCDR(*headp));
}
- if (tok->type != (enum TokenSyms )term)
+ if (tok->type != (enum TokenSyms )term) {
+ onig_node_free(topnode);
goto err;
+ }
+ *top = topnode;
}
else {
onig_node_free(node);
@@ -6731,8 +6807,8 @@ parse_regexp(Node** top, UChar** src, UChar* end, ScanEnv* env)
NENCLOSE(np)->target = *top;
r = scan_env_set_mem_node(env, num, np);
if (r != 0) {
- onig_node_free(np);
- return r;
+ onig_node_free(np);
+ return r;
}
*top = np;
}
@@ -6742,7 +6818,7 @@ parse_regexp(Node** top, UChar** src, UChar* end, ScanEnv* env)
extern int
onig_parse_make_tree(Node** root, const UChar* pattern, const UChar* end,
- regex_t* reg, ScanEnv* env)
+ regex_t* reg, ScanEnv* env)
{
int r;
UChar* p;
@@ -6769,7 +6845,7 @@ onig_parse_make_tree(Node** root, const UChar* pattern, const UChar* end,
extern void
onig_scan_env_set_error_string(ScanEnv* env, int ecode ARG_UNUSED,
- UChar* arg, UChar* arg_end)
+ UChar* arg, UChar* arg_end)
{
env->error = arg;
env->error_end = arg_end;
diff --git a/regparse.h b/regparse.h
index de980d0ac8..65da835a55 100644
--- a/regparse.h
+++ b/regparse.h
@@ -5,7 +5,7 @@
**********************************************************************/
/*-
* Copyright (c) 2002-2007 K.Kosako <sndgk393 AT ybb DOT ne DOT jp>
- * Copyright (c) 2011-2016 K.Takata <kentkt AT csc DOT jp>
+ * Copyright (c) 2011-2019 K.Takata <kentkt AT csc DOT jp>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -69,8 +69,8 @@ RUBY_SYMBOL_EXPORT_BEGIN
#define NTYPE(node) ((node)->u.base.type)
#define SET_NTYPE(node, ntype) \
do { \
- int value = ntype; \
- memcpy(&((node)->u.base.type), &value, sizeof(int)); \
+ int value = ntype; \
+ memcpy(&((node)->u.base.type), &value, sizeof(int)); \
} while (0)
#define NSTR(node) (&((node)->u.str))
diff --git a/rjit.c b/rjit.c
deleted file mode 100644
index 72660394b3..0000000000
--- a/rjit.c
+++ /dev/null
@@ -1,501 +0,0 @@
-/**********************************************************************
-
- rjit.c - Ruby JIT compiler functions
-
- Copyright (C) 2023 Takashi Kokubun <k0kubun@ruby-lang.org>.
-
-**********************************************************************/
-
-#include "rjit.h" // defines USE_RJIT
-
-#if USE_RJIT
-
-#include "constant.h"
-#include "id_table.h"
-#include "internal.h"
-#include "internal/class.h"
-#include "internal/cmdlineopt.h"
-#include "internal/cont.h"
-#include "internal/file.h"
-#include "internal/hash.h"
-#include "internal/process.h"
-#include "internal/warnings.h"
-#include "vm_sync.h"
-#include "ractor_core.h"
-
-#ifdef __sun
-#define __EXTENSIONS__ 1
-#endif
-
-#include "vm_core.h"
-#include "vm_callinfo.h"
-#include "rjit_c.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"
-#include "internal/gc.h"
-
-#include <sys/wait.h>
-#include <sys/time.h>
-#include <dlfcn.h>
-#include <errno.h>
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h>
-#endif
-#include "dln.h"
-
-// For mmapp(), sysconf()
-#ifndef _WIN32
-#include <unistd.h>
-#include <sys/mman.h>
-#endif
-
-#include "ruby/util.h"
-
-// A copy of RJIT portion of MRI options since RJIT initialization. We
-// need them as RJIT threads still can work when the most MRI data were
-// freed.
-struct rb_rjit_options rb_rjit_opts;
-
-// true if RJIT is enabled.
-bool rb_rjit_enabled = false;
-// true if --rjit-stats (used before rb_rjit_opts is set)
-bool rb_rjit_stats_enabled = false;
-// true if --rjit-trace-exits (used before rb_rjit_opts is set)
-bool rb_rjit_trace_exits_enabled = false;
-// true if JIT-ed code should be called. When `ruby_vm_event_enabled_global_flags & ISEQ_TRACE_EVENTS`
-// and `rb_rjit_call_p == false`, any JIT-ed code execution is cancelled as soon as possible.
-bool rb_rjit_call_p = false;
-// A flag to communicate that rb_rjit_call_p should be disabled while it's temporarily false.
-static bool rjit_cancel_p = false;
-
-// `rb_ec_ractor_hooks(ec)->events` is moved to this variable during compilation.
-rb_event_flag_t rb_rjit_global_events = 0;
-
-// Basically rb_rjit_opts.stats, but this becomes false during RJIT compilation.
-static bool rjit_stats_p = false;
-
-// RubyVM::RJIT
-static VALUE rb_mRJIT = 0;
-// RubyVM::RJIT::C
-static VALUE rb_mRJITC = 0;
-// RubyVM::RJIT::Compiler
-static VALUE rb_RJITCompiler = 0;
-// RubyVM::RJIT::CPointer::Struct_rb_iseq_t
-static VALUE rb_cRJITIseqPtr = 0;
-// RubyVM::RJIT::CPointer::Struct_rb_control_frame_t
-static VALUE rb_cRJITCfpPtr = 0;
-// RubyVM::RJIT::Hooks
-static VALUE rb_mRJITHooks = 0;
-
-// Frames for --rjit-trace-exits
-VALUE rb_rjit_raw_samples = 0;
-// Line numbers for --rjit-trace-exits
-VALUE rb_rjit_line_samples = 0;
-
-// Postponed job handle for triggering rjit_iseq_update_references
-static rb_postponed_job_handle_t rjit_iseq_update_references_pjob;
-
-// A default threshold used to add iseq to JIT.
-#define DEFAULT_CALL_THRESHOLD 10
-// Size of executable memory block in MiB.
-#define DEFAULT_EXEC_MEM_SIZE 64
-
-#define opt_match_noarg(s, l, name) \
- opt_match(s, l, name) && (*(s) ? (rb_warn("argument to --rjit-" name " is ignored"), 1) : 1)
-#define opt_match_arg(s, l, name) \
- opt_match(s, l, name) && (*(s) ? 1 : (rb_raise(rb_eRuntimeError, "--rjit-" name " needs an argument"), 0))
-
-void
-rb_rjit_setup_options(const char *s, struct rb_rjit_options *rjit_opt)
-{
- const size_t l = strlen(s);
- if (l == 0) {
- return;
- }
- else if (opt_match_arg(s, l, "exec-mem-size")) {
- rjit_opt->exec_mem_size = atoi(s + 1);
- }
- else if (opt_match_arg(s, l, "call-threshold")) {
- rjit_opt->call_threshold = atoi(s + 1);
- }
- else if (opt_match_noarg(s, l, "stats")) {
- rjit_opt->stats = true;
- }
- else if (opt_match_noarg(s, l, "disable")) {
- rjit_opt->disable = true;
- }
- else if (opt_match_noarg(s, l, "trace")) {
- rjit_opt->trace = true;
- }
- else if (opt_match_noarg(s, l, "trace-exits")) {
- rjit_opt->trace_exits = true;
- }
- else if (opt_match_noarg(s, l, "dump-disasm")) {
- rjit_opt->dump_disasm = true;
- }
- else if (opt_match_noarg(s, l, "verify-ctx")) {
- rjit_opt->verify_ctx = true;
- }
- else {
- rb_raise(rb_eRuntimeError,
- "invalid RJIT option '%s' (--help will show valid RJIT options)", s);
- }
-}
-
-#define M(shortopt, longopt, desc) RUBY_OPT_MESSAGE(shortopt, longopt, desc)
-const struct ruby_opt_message rb_rjit_option_messages[] = {
- M("--rjit-exec-mem-size=num", "", "Size of executable memory block in MiB (default: " STRINGIZE(DEFAULT_EXEC_MEM_SIZE) ")."),
- M("--rjit-call-threshold=num", "", "Number of calls to trigger JIT (default: " STRINGIZE(DEFAULT_CALL_THRESHOLD) ")."),
- M("--rjit-stats", "", "Enable collecting RJIT statistics."),
- M("--rjit-disable", "", "Disable RJIT for lazily enabling it with RubyVM::RJIT.enable."),
- M("--rjit-trace", "", "Allow TracePoint during JIT compilation."),
- M("--rjit-trace-exits", "", "Trace side exit locations."),
-#ifdef HAVE_LIBCAPSTONE
- M("--rjit-dump-disasm", "", "Dump all JIT code"),
-#endif
- {0}
-};
-#undef M
-
-struct rb_rjit_runtime_counters rb_rjit_counters = { 0 };
-
-extern VALUE rb_gc_enable(void);
-extern VALUE rb_gc_disable(void);
-extern uint64_t rb_vm_insns_count;
-
-// Disable GC, TracePoint, JIT, stats, and $!
-#define WITH_RJIT_ISOLATED_USING_PC(using_pc, stmt) do { \
- VALUE was_disabled = rb_gc_disable(); \
- \
- rb_hook_list_t *global_hooks = rb_ec_ractor_hooks(GET_EC()); \
- rb_rjit_global_events = global_hooks->events; \
- \
- const VALUE *pc = NULL; \
- if (rb_rjit_opts.trace) { \
- pc = GET_EC()->cfp->pc; \
- if (!using_pc) GET_EC()->cfp->pc = 0; /* avoid crashing on calc_lineno */ \
- } \
- else global_hooks->events = 0; \
- \
- bool original_call_p = rb_rjit_call_p; \
- rb_rjit_call_p = false; \
- \
- rjit_stats_p = false; \
- uint64_t insns_count = rb_vm_insns_count; \
- \
- VALUE err = rb_errinfo(); \
- \
- stmt; \
- \
- rb_set_errinfo(err); \
- \
- rb_vm_insns_count = insns_count; \
- rjit_stats_p = rb_rjit_opts.stats; \
- \
- rb_rjit_call_p = (rjit_cancel_p ? false : original_call_p); \
- \
- if (rb_rjit_opts.trace) GET_EC()->cfp->pc = pc; \
- else global_hooks->events = rb_rjit_global_events; \
- \
- if (!was_disabled) rb_gc_enable(); \
-} while (0);
-#define WITH_RJIT_ISOLATED(stmt) WITH_RJIT_ISOLATED_USING_PC(false, stmt)
-
-void
-rb_rjit_cancel_all(const char *reason)
-{
- if (!rb_rjit_enabled)
- return;
-
- rb_rjit_call_p = false;
- rjit_cancel_p = true;
-}
-
-void
-rb_rjit_bop_redefined(int redefined_flag, enum ruby_basic_operators bop)
-{
- if (!rb_rjit_call_p) return;
- rb_rjit_call_p = false;
-}
-
-static void
-rjit_cme_invalidate(void *data)
-{
- if (!rb_rjit_enabled || !rb_rjit_call_p || !rb_mRJITHooks) return;
- WITH_RJIT_ISOLATED({
- rb_funcall(rb_mRJITHooks, rb_intern("on_cme_invalidate"), 1, SIZET2NUM((size_t)data));
- });
-}
-
-extern int rb_workqueue_register(unsigned flags, rb_postponed_job_func_t func, void *data);
-
-void
-rb_rjit_cme_invalidate(rb_callable_method_entry_t *cme)
-{
- if (!rb_rjit_enabled || !rb_rjit_call_p || !rb_mRJITHooks) return;
- // Asynchronously hook the Ruby code since running Ruby in the middle of cme invalidation is dangerous.
- rb_workqueue_register(0, rjit_cme_invalidate, (void *)cme);
-}
-
-void
-rb_rjit_before_ractor_spawn(void)
-{
- if (!rb_rjit_call_p) return;
- rb_rjit_call_p = false;
-}
-
-static void
-rjit_constant_state_changed(void *data)
-{
- if (!rb_rjit_enabled || !rb_rjit_call_p || !rb_mRJITHooks) return;
- RB_VM_LOCK_ENTER();
- rb_vm_barrier();
-
- WITH_RJIT_ISOLATED({
- rb_funcall(rb_mRJITHooks, rb_intern("on_constant_state_changed"), 1, SIZET2NUM((size_t)data));
- });
-
- RB_VM_LOCK_LEAVE();
-}
-
-void
-rb_rjit_constant_state_changed(ID id)
-{
- if (!rb_rjit_enabled || !rb_rjit_call_p || !rb_mRJITHooks) return;
- // Asynchronously hook the Ruby code since this is hooked during a "Ruby critical section".
- rb_workqueue_register(0, rjit_constant_state_changed, (void *)id);
-}
-
-void
-rb_rjit_constant_ic_update(const rb_iseq_t *const iseq, IC ic, unsigned insn_idx)
-{
- if (!rb_rjit_enabled || !rb_rjit_call_p || !rb_mRJITHooks) return;
-
- RB_VM_LOCK_ENTER();
- rb_vm_barrier();
-
- WITH_RJIT_ISOLATED({
- rb_funcall(rb_mRJITHooks, rb_intern("on_constant_ic_update"), 3,
- SIZET2NUM((size_t)iseq), SIZET2NUM((size_t)ic), UINT2NUM(insn_idx));
- });
-
- RB_VM_LOCK_LEAVE();
-}
-
-void
-rb_rjit_tracing_invalidate_all(rb_event_flag_t new_iseq_events)
-{
- if (!rb_rjit_enabled || !rb_rjit_call_p || !rb_mRJITHooks) return;
- WITH_RJIT_ISOLATED({
- rb_funcall(rb_mRJITHooks, rb_intern("on_tracing_invalidate_all"), 1, UINT2NUM(new_iseq_events));
- });
-}
-
-static void
-rjit_iseq_update_references(void *data)
-{
- if (!rb_rjit_enabled || !rb_rjit_call_p || !rb_mRJITHooks) return;
- WITH_RJIT_ISOLATED({
- rb_funcall(rb_mRJITHooks, rb_intern("on_update_references"), 0);
- });
-}
-
-void
-rb_rjit_iseq_update_references(struct rb_iseq_constant_body *const body)
-{
- if (!rb_rjit_enabled) return;
-
- if (body->rjit_blocks) {
- body->rjit_blocks = rb_gc_location(body->rjit_blocks);
- }
-
- // Asynchronously hook the Ruby code to avoid allocation during GC.compact.
- // Using _one because it's too slow to invalidate all for each ISEQ. Thus
- // not giving an ISEQ pointer.
- rb_postponed_job_trigger(rjit_iseq_update_references_pjob);
-}
-
-void
-rb_rjit_iseq_mark(VALUE rjit_blocks)
-{
- if (!rb_rjit_enabled) return;
-
- // Note: This wasn't enough for some reason.
- // We actually rely on RubyVM::RJIT::GC_REFS to mark this.
- if (rjit_blocks) {
- rb_gc_mark_movable(rjit_blocks);
- }
-}
-
-// Called by rb_vm_mark()
-void
-rb_rjit_mark(void)
-{
- if (!rb_rjit_enabled)
- return;
- RUBY_MARK_ENTER("rjit");
-
- // Pin object pointers used in this file
- rb_gc_mark(rb_RJITCompiler);
- rb_gc_mark(rb_cRJITIseqPtr);
- rb_gc_mark(rb_cRJITCfpPtr);
- rb_gc_mark(rb_mRJITHooks);
- rb_gc_mark(rb_rjit_raw_samples);
- rb_gc_mark(rb_rjit_line_samples);
-
- RUBY_MARK_LEAVE("rjit");
-}
-
-void
-rb_rjit_free_iseq(const rb_iseq_t *iseq)
-{
- // TODO: implement this. GC_REFS should remove this iseq's mjit_blocks
-}
-
-// TODO: Use this in more places
-VALUE
-rb_rjit_iseq_new(rb_iseq_t *iseq)
-{
- return rb_funcall(rb_cRJITIseqPtr, rb_intern("new"), 1, SIZET2NUM((size_t)iseq));
-}
-
-void
-rb_rjit_compile(const rb_iseq_t *iseq)
-{
- RB_VM_LOCK_ENTER();
- rb_vm_barrier();
-
- WITH_RJIT_ISOLATED_USING_PC(true, {
- VALUE iseq_ptr = rb_funcall(rb_cRJITIseqPtr, rb_intern("new"), 1, SIZET2NUM((size_t)iseq));
- VALUE cfp_ptr = rb_funcall(rb_cRJITCfpPtr, rb_intern("new"), 1, SIZET2NUM((size_t)GET_EC()->cfp));
- rb_funcall(rb_RJITCompiler, rb_intern("compile"), 2, iseq_ptr, cfp_ptr);
- });
-
- RB_VM_LOCK_LEAVE();
-}
-
-void *
-rb_rjit_entry_stub_hit(VALUE branch_stub)
-{
- VALUE result;
-
- RB_VM_LOCK_ENTER();
- rb_vm_barrier();
-
- rb_control_frame_t *cfp = GET_EC()->cfp;
-
- WITH_RJIT_ISOLATED_USING_PC(true, {
- VALUE cfp_ptr = rb_funcall(rb_cRJITCfpPtr, rb_intern("new"), 1, SIZET2NUM((size_t)cfp));
- result = rb_funcall(rb_RJITCompiler, rb_intern("entry_stub_hit"), 2, branch_stub, cfp_ptr);
- });
-
- RB_VM_LOCK_LEAVE();
-
- return (void *)NUM2SIZET(result);
-}
-
-void *
-rb_rjit_branch_stub_hit(VALUE branch_stub, int sp_offset, int target0_p)
-{
- VALUE result;
-
- RB_VM_LOCK_ENTER();
- rb_vm_barrier();
-
- rb_control_frame_t *cfp = GET_EC()->cfp;
- cfp->sp += sp_offset; // preserve stack values, also using the actual sp_offset to make jit.peek_at_stack work
-
- WITH_RJIT_ISOLATED({
- VALUE cfp_ptr = rb_funcall(rb_cRJITCfpPtr, rb_intern("new"), 1, SIZET2NUM((size_t)cfp));
- result = rb_funcall(rb_RJITCompiler, rb_intern("branch_stub_hit"), 3, branch_stub, cfp_ptr, RBOOL(target0_p));
- });
-
- cfp->sp -= sp_offset; // reset for consistency with the code without the stub
-
- RB_VM_LOCK_LEAVE();
-
- return (void *)NUM2SIZET(result);
-}
-
-void
-rb_rjit_init(const struct rb_rjit_options *opts)
-{
- VM_ASSERT(rb_rjit_enabled);
-
- // Normalize options
- rb_rjit_opts = *opts;
- if (rb_rjit_opts.exec_mem_size == 0)
- rb_rjit_opts.exec_mem_size = DEFAULT_EXEC_MEM_SIZE;
- if (rb_rjit_opts.call_threshold == 0)
- rb_rjit_opts.call_threshold = DEFAULT_CALL_THRESHOLD;
-#ifndef HAVE_LIBCAPSTONE
- if (rb_rjit_opts.dump_disasm)
- rb_warn("libcapstone has not been linked. Ignoring --rjit-dump-disasm.");
-#endif
-
- // RJIT doesn't support miniruby, but it might reach here by RJIT_FORCE_ENABLE.
- rb_mRJIT = rb_const_get(rb_cRubyVM, rb_intern("RJIT"));
- if (!rb_const_defined(rb_mRJIT, rb_intern("Compiler"))) {
- rb_warn("Disabling RJIT because RubyVM::RJIT::Compiler is not defined");
- rb_rjit_enabled = false;
- return;
- }
- rjit_iseq_update_references_pjob = rb_postponed_job_preregister(0, rjit_iseq_update_references, NULL);
- if (rjit_iseq_update_references_pjob == POSTPONED_JOB_HANDLE_INVALID) {
- rb_bug("Could not preregister postponed job for RJIT");
- }
- rb_mRJITC = rb_const_get(rb_mRJIT, rb_intern("C"));
- VALUE rb_cRJITCompiler = rb_const_get(rb_mRJIT, rb_intern("Compiler"));
- rb_RJITCompiler = rb_funcall(rb_cRJITCompiler, rb_intern("new"), 0);
- rb_cRJITIseqPtr = rb_funcall(rb_mRJITC, rb_intern("rb_iseq_t"), 0);
- rb_cRJITCfpPtr = rb_funcall(rb_mRJITC, rb_intern("rb_control_frame_t"), 0);
- rb_mRJITHooks = rb_const_get(rb_mRJIT, rb_intern("Hooks"));
- if (rb_rjit_opts.trace_exits) {
- rb_rjit_raw_samples = rb_ary_new();
- rb_rjit_line_samples = rb_ary_new();
- }
-
- // Enable RJIT and stats from here
- rb_rjit_call_p = !rb_rjit_opts.disable;
- rjit_stats_p = rb_rjit_opts.stats;
-}
-
-//
-// Primitive for rjit.rb
-//
-
-// Same as `rb_rjit_opts.stats`, but this is used before rb_rjit_opts is set.
-static VALUE
-rjit_stats_enabled_p(rb_execution_context_t *ec, VALUE self)
-{
- return RBOOL(rb_rjit_stats_enabled);
-}
-
-// Same as `rb_rjit_opts.trace_exits`, but this is used before rb_rjit_opts is set.
-static VALUE
-rjit_trace_exits_enabled_p(rb_execution_context_t *ec, VALUE self)
-{
- return RBOOL(rb_rjit_trace_exits_enabled);
-}
-
-// Disable anything that could impact stats. It ends up disabling JIT calls as well.
-static VALUE
-rjit_stop_stats(rb_execution_context_t *ec, VALUE self)
-{
- rb_rjit_call_p = false;
- rjit_stats_p = false;
- return Qnil;
-}
-
-#include "rjit.rbinc"
-
-#endif // USE_RJIT
diff --git a/rjit.h b/rjit.h
deleted file mode 100644
index 26d1d67fb1..0000000000
--- a/rjit.h
+++ /dev/null
@@ -1,101 +0,0 @@
-#ifndef RUBY_RJIT_H
-#define RUBY_RJIT_H 1
-/**********************************************************************
-
- rjit.h - Interface to RJIT
-
- Copyright (C) 2023 Takashi Kokubun <k0kubun@ruby-lang.org>.
-
-**********************************************************************/
-
-#include "ruby/internal/config.h" // defines USE_RJIT
-#include "ruby/internal/stdbool.h"
-#include "vm_core.h"
-
-# if USE_RJIT
-
-#include "ruby.h"
-#include "vm_core.h"
-
-// RJIT options which can be defined on the MRI command line.
-struct rb_rjit_options {
- // Converted from "rjit" feature flag to tell the enablement
- // information to ruby_show_version().
- bool on;
- // Size of executable memory block in MiB
- unsigned int exec_mem_size;
- // Number of calls to trigger JIT compilation
- unsigned int call_threshold;
- // Collect RJIT statistics
- bool stats;
- // Do not start RJIT until RJIT.enable is called
- bool disable;
- // Allow TracePoint during JIT compilation
- bool trace;
- // Trace side exit locations
- bool trace_exits;
- // Enable disasm of all JIT code
- bool dump_disasm;
- // Verify context objects
- bool verify_ctx;
-};
-
-RUBY_SYMBOL_EXPORT_BEGIN
-RUBY_EXTERN struct rb_rjit_options rb_rjit_opts;
-RUBY_EXTERN bool rb_rjit_call_p;
-
-#define rb_rjit_call_threshold() rb_rjit_opts.call_threshold
-
-extern void rb_rjit_compile(const rb_iseq_t *iseq);
-RUBY_SYMBOL_EXPORT_END
-
-extern void rb_rjit_cancel_all(const char *reason);
-extern void rb_rjit_init(const struct rb_rjit_options *opts);
-extern void rb_rjit_free_iseq(const rb_iseq_t *iseq);
-extern void rb_rjit_iseq_update_references(struct rb_iseq_constant_body *const body);
-extern void rb_rjit_mark(void);
-extern void rb_rjit_iseq_mark(VALUE rjit_blocks);
-extern void rjit_notify_waitpid(int exit_code);
-
-extern void rb_rjit_bop_redefined(int redefined_flag, enum ruby_basic_operators bop);
-extern void rb_rjit_cme_invalidate(rb_callable_method_entry_t *cme);
-extern void rb_rjit_before_ractor_spawn(void);
-extern void rb_rjit_constant_state_changed(ID id);
-extern void rb_rjit_constant_ic_update(const rb_iseq_t *const iseq, IC ic, unsigned insn_idx);
-extern void rb_rjit_tracing_invalidate_all(rb_event_flag_t new_iseq_events);
-
-extern void rb_rjit_bop_redefined(int redefined_flag, enum ruby_basic_operators bop);
-extern void rb_rjit_before_ractor_spawn(void);
-extern void rb_rjit_tracing_invalidate_all(rb_event_flag_t new_iseq_events);
-extern void rb_rjit_collect_vm_usage_insn(int insn);
-
-extern bool rb_rjit_enabled;
-extern bool rb_rjit_stats_enabled;
-extern bool rb_rjit_trace_exits_enabled;
-
-# else // USE_RJIT
-
-static inline void rb_rjit_compile(const rb_iseq_t *iseq){}
-
-static inline void rb_rjit_cancel_all(const char *reason){}
-static inline void rb_rjit_free_iseq(const rb_iseq_t *iseq){}
-static inline void rb_rjit_mark(void){}
-
-static inline void rb_rjit_bop_redefined(int redefined_flag, enum ruby_basic_operators bop) {}
-static inline void rb_rjit_cme_invalidate(rb_callable_method_entry_t *cme) {}
-static inline void rb_rjit_before_ractor_spawn(void) {}
-static inline void rb_rjit_constant_state_changed(ID id) {}
-static inline void rb_rjit_constant_ic_update(const rb_iseq_t *const iseq, IC ic, unsigned insn_idx) {}
-static inline void rb_rjit_tracing_invalidate_all(rb_event_flag_t new_iseq_events) {}
-
-#define rb_rjit_enabled false
-#define rb_rjit_call_p false
-#define rb_rjit_stats_enabled false
-#define rb_rjit_trace_exits_enabled false
-
-#define rb_rjit_call_threshold() UINT_MAX
-
-static inline void rb_rjit_collect_vm_usage_insn(int insn) {}
-
-# endif // USE_RJIT
-#endif // RUBY_RJIT_H
diff --git a/rjit.rb b/rjit.rb
deleted file mode 100644
index 12fc10c91e..0000000000
--- a/rjit.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-module RubyVM::RJIT
- # Return true if \RJIT is enabled.
- def self.enabled?
- Primitive.cexpr! 'RBOOL(rb_rjit_enabled)'
- end
-
- # Start JIT compilation after \--rjit-disable.
- def self.enable
- Primitive.cstmt! %{
- rb_rjit_call_p = true;
- return Qnil;
- }
- end
-
- if Primitive.rjit_stats_enabled_p
- at_exit do
- Primitive.rjit_stop_stats
- print_stats
- end
- end
- if Primitive.rjit_trace_exits_enabled_p
- at_exit do
- Primitive.rjit_stop_stats
- dump_trace_exits
- end
- end
-end
-
-if RubyVM::RJIT.enabled?
- begin
- require 'fiddle'
- require 'fiddle/import'
- rescue LoadError
- return # miniruby doesn't support RJIT
- end
-
- require 'ruby_vm/rjit/c_type'
- require 'ruby_vm/rjit/compiler'
- require 'ruby_vm/rjit/hooks'
- require 'ruby_vm/rjit/stats'
-end
diff --git a/rjit_c.c b/rjit_c.c
deleted file mode 100644
index e9863129a1..0000000000
--- a/rjit_c.c
+++ /dev/null
@@ -1,543 +0,0 @@
-/**********************************************************************
-
- rjit_c.c - C helpers for RJIT
-
- Copyright (C) 2017 Takashi Kokubun <k0kubun@ruby-lang.org>.
-
-**********************************************************************/
-
-#include "rjit.h" // defines USE_RJIT
-
-#if USE_RJIT
-
-#include "rjit_c.h"
-#include "include/ruby/assert.h"
-#include "include/ruby/debug.h"
-#include "internal.h"
-#include "internal/compile.h"
-#include "internal/fixnum.h"
-#include "internal/hash.h"
-#include "internal/sanitizers.h"
-#include "internal/gc.h"
-#include "internal/proc.h"
-#include "yjit.h"
-#include "vm_insnhelper.h"
-#include "probes.h"
-#include "probes_helper.h"
-
-#include "insns.inc"
-#include "insns_info.inc"
-
-// For mmapp(), sysconf()
-#ifndef _WIN32
-#include <unistd.h>
-#include <sys/mman.h>
-#endif
-
-#include <errno.h>
-
-#if defined(MAP_FIXED_NOREPLACE) && defined(_SC_PAGESIZE)
-// 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;
-}
-#endif
-
-// Address space reservation. Memory pages are mapped on an as needed basis.
-// See the Rust mm module for details.
-static uint8_t *
-rjit_reserve_addr_space(uint32_t mem_size)
-{
-#ifndef _WIN32
- uint8_t *mem_block;
-
- // On Linux
- #if defined(MAP_FIXED_NOREPLACE) && defined(_SC_PAGESIZE)
- uint32_t const page_size = (uint32_t)sysconf(_SC_PAGESIZE);
- uint8_t *const cfunc_sample_addr = (void *)&rjit_reserve_addr_space;
- uint8_t *const probe_region_end = cfunc_sample_addr + INT32_MAX;
- // Align the requested address to page size
- uint8_t *req_addr = align_ptr(cfunc_sample_addr, page_size);
-
- // Probe for addresses close to this function using MAP_FIXED_NOREPLACE
- // to improve odds of being in range for 32-bit relative call instructions.
- do {
- mem_block = mmap(
- req_addr,
- mem_size,
- PROT_NONE,
- 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 < probe_region_end);
-
- // On MacOS and other platforms
- #else
- // Try to map a chunk of memory as executable
- mem_block = mmap(
- (void *)rjit_reserve_addr_space,
- mem_size,
- PROT_NONE,
- MAP_PRIVATE | MAP_ANONYMOUS,
- -1,
- 0
- );
- #endif
-
- // Fallback
- if (mem_block == MAP_FAILED) {
- // Try again without the address hint (e.g., valgrind)
- mem_block = mmap(
- NULL,
- mem_size,
- PROT_NONE,
- MAP_PRIVATE | MAP_ANONYMOUS,
- -1,
- 0
- );
- }
-
- // Check that the memory mapping was successful
- if (mem_block == MAP_FAILED) {
- perror("ruby: yjit: mmap:");
- if(errno == ENOMEM) {
- // No crash report if it's only insufficient memory
- exit(EXIT_FAILURE);
- }
- rb_bug("mmap failed");
- }
-
- return mem_block;
-#else
- // Windows not supported for now
- return NULL;
-#endif
-}
-
-static VALUE
-mprotect_write(rb_execution_context_t *ec, VALUE self, VALUE rb_mem_block, VALUE rb_mem_size)
-{
- void *mem_block = (void *)NUM2SIZET(rb_mem_block);
- uint32_t mem_size = NUM2UINT(rb_mem_size);
- return RBOOL(mprotect(mem_block, mem_size, PROT_READ | PROT_WRITE) == 0);
-}
-
-static VALUE
-mprotect_exec(rb_execution_context_t *ec, VALUE self, VALUE rb_mem_block, VALUE rb_mem_size)
-{
- void *mem_block = (void *)NUM2SIZET(rb_mem_block);
- uint32_t mem_size = NUM2UINT(rb_mem_size);
- if (mem_size == 0) return Qfalse; // Some platforms return an error for mem_size 0.
-
- if (mprotect(mem_block, mem_size, PROT_READ | PROT_EXEC)) {
- rb_bug("Couldn't make JIT page (%p, %lu bytes) executable, errno: %s",
- mem_block, (unsigned long)mem_size, strerror(errno));
- }
- return Qtrue;
-}
-
-static VALUE
-rjit_optimized_call(VALUE *recv, rb_execution_context_t *ec, int argc, VALUE *argv, int kw_splat, VALUE block_handler)
-{
- rb_proc_t *proc;
- GetProcPtr(recv, proc);
- return rb_vm_invoke_proc(ec, proc, argc, argv, kw_splat, block_handler);
-}
-
-static VALUE
-rjit_str_neq_internal(VALUE str1, VALUE str2)
-{
- return rb_str_eql_internal(str1, str2) == Qtrue ? Qfalse : Qtrue;
-}
-
-static VALUE
-rjit_str_simple_append(VALUE str1, VALUE str2)
-{
- return rb_str_cat(str1, RSTRING_PTR(str2), RSTRING_LEN(str2));
-}
-
-static VALUE
-rjit_rb_ary_subseq_length(VALUE ary, long beg)
-{
- long len = RARRAY_LEN(ary);
- return rb_ary_subseq(ary, beg, len);
-}
-
-static VALUE
-rjit_build_kwhash(const struct rb_callinfo *ci, VALUE *sp)
-{
- const struct rb_callinfo_kwarg *kw_arg = vm_ci_kwarg(ci);
- int kw_len = kw_arg->keyword_len;
- VALUE hash = rb_hash_new_with_size(kw_len);
-
- for (int i = 0; i < kw_len; i++) {
- VALUE key = kw_arg->keywords[i];
- VALUE val = *(sp - kw_len + i);
- rb_hash_aset(hash, key, val);
- }
- return hash;
-}
-
-// 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
-rjit_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++;
-}
-
-static rb_proc_t *
-rjit_get_proc_ptr(VALUE procv)
-{
- rb_proc_t *proc;
- GetProcPtr(procv, proc);
- return proc;
-}
-
-// Use the same buffer size as Stackprof.
-#define BUFF_LEN 2048
-
-extern VALUE rb_rjit_raw_samples;
-extern VALUE rb_rjit_line_samples;
-
-static void
-rjit_record_exit_stack(const VALUE *exit_pc)
-{
- // Let Primitive.rjit_stop_stats stop this
- if (!rb_rjit_call_p) return;
-
- // Get the opcode from the encoded insn handler at this PC
- int insn = rb_vm_insn_addr2opcode((void *)*exit_pc);
-
- // Create 2 array buffers to be used to collect frames and lines.
- VALUE frames_buffer[BUFF_LEN] = { 0 };
- int lines_buffer[BUFF_LEN] = { 0 };
-
- // Records call frame and line information for each method entry into two
- // temporary buffers. Returns the number of times we added to the buffer (ie
- // the length of the stack).
- //
- // Call frame info is stored in the frames_buffer, line number information
- // in the lines_buffer. The first argument is the start point and the second
- // argument is the buffer limit, set at 2048.
- int stack_length = rb_profile_frames(0, BUFF_LEN, frames_buffer, lines_buffer);
- int samples_length = stack_length + 3; // 3: length, insn, count
-
- // If yjit_raw_samples is less than or equal to the current length of the samples
- // we might have seen this stack trace previously.
- int prev_stack_len_index = (int)RARRAY_LEN(rb_rjit_raw_samples) - samples_length;
- VALUE prev_stack_len_obj;
- if (RARRAY_LEN(rb_rjit_raw_samples) >= samples_length && FIXNUM_P(prev_stack_len_obj = RARRAY_AREF(rb_rjit_raw_samples, prev_stack_len_index))) {
- int prev_stack_len = NUM2INT(prev_stack_len_obj);
- int idx = stack_length - 1;
- int prev_frame_idx = 0;
- bool seen_already = true;
-
- // If the previous stack length and current stack length are equal,
- // loop and compare the current frame to the previous frame. If they are
- // not equal, set seen_already to false and break out of the loop.
- if (prev_stack_len == stack_length) {
- while (idx >= 0) {
- VALUE current_frame = frames_buffer[idx];
- VALUE prev_frame = RARRAY_AREF(rb_rjit_raw_samples, prev_stack_len_index + prev_frame_idx + 1);
-
- // If the current frame and previous frame are not equal, set
- // seen_already to false and break out of the loop.
- if (current_frame != prev_frame) {
- seen_already = false;
- break;
- }
-
- idx--;
- prev_frame_idx++;
- }
-
- // If we know we've seen this stack before, increment the counter by 1.
- if (seen_already) {
- int prev_idx = (int)RARRAY_LEN(rb_rjit_raw_samples) - 1;
- int prev_count = NUM2INT(RARRAY_AREF(rb_rjit_raw_samples, prev_idx));
- int new_count = prev_count + 1;
-
- rb_ary_store(rb_rjit_raw_samples, prev_idx, INT2NUM(new_count));
- rb_ary_store(rb_rjit_line_samples, prev_idx, INT2NUM(new_count));
- return;
- }
- }
- }
-
- rb_ary_push(rb_rjit_raw_samples, INT2NUM(stack_length));
- rb_ary_push(rb_rjit_line_samples, INT2NUM(stack_length));
-
- int idx = stack_length - 1;
-
- while (idx >= 0) {
- VALUE frame = frames_buffer[idx];
- int line = lines_buffer[idx];
-
- rb_ary_push(rb_rjit_raw_samples, frame);
- rb_ary_push(rb_rjit_line_samples, INT2NUM(line));
-
- idx--;
- }
-
- // Push the insn value into the yjit_raw_samples Vec.
- rb_ary_push(rb_rjit_raw_samples, INT2NUM(insn));
-
- // Push the current line onto the yjit_line_samples Vec. This
- // points to the line in insns.def.
- int line = (int)RARRAY_LEN(rb_rjit_line_samples) - 1;
- rb_ary_push(rb_rjit_line_samples, INT2NUM(line));
-
- // Push number of times seen onto the stack, which is 1
- // because it's the first time we've seen it.
- rb_ary_push(rb_rjit_raw_samples, INT2NUM(1));
- rb_ary_push(rb_rjit_line_samples, INT2NUM(1));
-}
-
-// For a given raw_sample (frame), set the hash with the caller's
-// name, file, and line number. Return the hash with collected frame_info.
-static void
-rjit_add_frame(VALUE hash, VALUE frame)
-{
- VALUE frame_id = SIZET2NUM(frame);
-
- if (RTEST(rb_hash_aref(hash, frame_id))) {
- return;
- }
- else {
- VALUE frame_info = rb_hash_new();
- // Full label for the frame
- VALUE name = rb_profile_frame_full_label(frame);
- // Absolute path of the frame from rb_iseq_realpath
- VALUE file = rb_profile_frame_absolute_path(frame);
- // Line number of the frame
- VALUE line = rb_profile_frame_first_lineno(frame);
-
- // If absolute path isn't available use the rb_iseq_path
- if (NIL_P(file)) {
- file = rb_profile_frame_path(frame);
- }
-
- rb_hash_aset(frame_info, ID2SYM(rb_intern("name")), name);
- rb_hash_aset(frame_info, ID2SYM(rb_intern("file")), file);
- rb_hash_aset(frame_info, ID2SYM(rb_intern("samples")), INT2NUM(0));
- rb_hash_aset(frame_info, ID2SYM(rb_intern("total_samples")), INT2NUM(0));
- rb_hash_aset(frame_info, ID2SYM(rb_intern("edges")), rb_hash_new());
- rb_hash_aset(frame_info, ID2SYM(rb_intern("lines")), rb_hash_new());
-
- if (line != INT2FIX(0)) {
- rb_hash_aset(frame_info, ID2SYM(rb_intern("line")), line);
- }
-
- rb_hash_aset(hash, frame_id, frame_info);
- }
-}
-
-static VALUE
-rjit_exit_traces(void)
-{
- int samples_len = (int)RARRAY_LEN(rb_rjit_raw_samples);
- RUBY_ASSERT(samples_len == RARRAY_LEN(rb_rjit_line_samples));
-
- VALUE result = rb_hash_new();
- VALUE raw_samples = rb_ary_new_capa(samples_len);
- VALUE line_samples = rb_ary_new_capa(samples_len);
- VALUE frames = rb_hash_new();
- int idx = 0;
-
- // While the index is less than samples_len, parse yjit_raw_samples and
- // yjit_line_samples, then add casted values to raw_samples and line_samples array.
- while (idx < samples_len) {
- int num = NUM2INT(RARRAY_AREF(rb_rjit_raw_samples, idx));
- int line_num = NUM2INT(RARRAY_AREF(rb_rjit_line_samples, idx));
- idx++;
-
- rb_ary_push(raw_samples, SIZET2NUM(num));
- rb_ary_push(line_samples, INT2NUM(line_num));
-
- // Loop through the length of samples_len and add data to the
- // frames hash. Also push the current value onto the raw_samples
- // and line_samples array respectively.
- for (int o = 0; o < num; o++) {
- rjit_add_frame(frames, RARRAY_AREF(rb_rjit_raw_samples, idx));
- rb_ary_push(raw_samples, SIZET2NUM(RARRAY_AREF(rb_rjit_raw_samples, idx)));
- rb_ary_push(line_samples, RARRAY_AREF(rb_rjit_line_samples, idx));
- idx++;
- }
-
- // insn BIN and lineno
- rb_ary_push(raw_samples, RARRAY_AREF(rb_rjit_raw_samples, idx));
- rb_ary_push(line_samples, RARRAY_AREF(rb_rjit_line_samples, idx));
- idx++;
-
- // Number of times seen
- rb_ary_push(raw_samples, RARRAY_AREF(rb_rjit_raw_samples, idx));
- rb_ary_push(line_samples, RARRAY_AREF(rb_rjit_line_samples, idx));
- idx++;
- }
-
- // Set add the raw_samples, line_samples, and frames to the results
- // hash.
- rb_hash_aset(result, ID2SYM(rb_intern("raw")), raw_samples);
- rb_hash_aset(result, ID2SYM(rb_intern("lines")), line_samples);
- rb_hash_aset(result, ID2SYM(rb_intern("frames")), frames);
-
- return result;
-}
-
-// An offsetof implementation that works for unnamed struct and union.
-// Multiplying 8 for compatibility with libclang's offsetof.
-#define OFFSETOF(ptr, member) RB_SIZE2NUM(((char *)&ptr.member - (char*)&ptr) * 8)
-
-#define SIZEOF(type) RB_SIZE2NUM(sizeof(type))
-#define SIGNED_TYPE_P(type) RBOOL((type)(-1) < (type)(1))
-
-// Insn side exit counters
-static size_t rjit_insn_exits[VM_INSTRUCTION_SIZE] = { 0 };
-
-// macOS: brew install capstone
-// Ubuntu/Debian: apt-get install libcapstone-dev
-// Fedora: dnf -y install capstone-devel
-#ifdef HAVE_LIBCAPSTONE
-#include <capstone/capstone.h>
-#endif
-
-// Return an array of [address, mnemonic, op_str]
-static VALUE
-dump_disasm(rb_execution_context_t *ec, VALUE self, VALUE from, VALUE to, VALUE test)
-{
- VALUE result = rb_ary_new();
-#ifdef HAVE_LIBCAPSTONE
- // Prepare for calling cs_disasm
- static csh handle;
- if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle) != CS_ERR_OK) {
- rb_raise(rb_eRuntimeError, "failed to make Capstone handle");
- }
- size_t from_addr = NUM2SIZET(from);
- size_t to_addr = NUM2SIZET(to);
-
- // Call cs_disasm and convert results to a Ruby array
- cs_insn *insns;
- size_t base_addr = RTEST(test) ? 0 : from_addr; // On tests, start from 0 for output stability.
- size_t count = cs_disasm(handle, (const uint8_t *)from_addr, to_addr - from_addr, base_addr, 0, &insns);
- 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(result, vals);
- }
-
- // Free memory used by capstone
- cs_free(insns, count);
- cs_close(&handle);
-#endif
- return result;
-}
-
-// Same as `RubyVM::RJIT.enabled?`, but this is used before it's defined.
-static VALUE
-rjit_enabled_p(rb_execution_context_t *ec, VALUE self)
-{
- return RBOOL(rb_rjit_enabled);
-}
-
-static int
-for_each_iseq_i(void *vstart, void *vend, size_t stride, void *data)
-{
- VALUE block = (VALUE)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)) {
- extern VALUE rb_rjit_iseq_new(rb_iseq_t *iseq);
- rb_iseq_t *iseq = (rb_iseq_t *)v;
- rb_funcall(block, rb_intern("call"), 1, rb_rjit_iseq_new(iseq));
- }
-
- asan_poison_object_if(ptr, v);
- }
- return 0;
-}
-
-static VALUE
-rjit_for_each_iseq(rb_execution_context_t *ec, VALUE self, VALUE block)
-{
- rb_objspace_each_objects(for_each_iseq_i, (void *)block);
- return Qnil;
-}
-
-// bindgen references
-extern ID rb_get_symbol_id(VALUE name);
-extern VALUE rb_fix_aref(VALUE fix, VALUE idx);
-extern VALUE rb_str_getbyte(VALUE str, VALUE index);
-extern VALUE rb_vm_concat_array(VALUE ary1, VALUE ary2st);
-extern VALUE rb_vm_get_ev_const(rb_execution_context_t *ec, VALUE orig_klass, ID id, VALUE allow_nil);
-extern VALUE rb_vm_getclassvariable(const rb_iseq_t *iseq, const rb_control_frame_t *cfp, ID id, ICVARC ic);
-extern VALUE rb_vm_opt_newarray_min(rb_execution_context_t *ec, rb_num_t num, const VALUE *ptr);
-extern VALUE rb_vm_opt_newarray_max(rb_execution_context_t *ec, rb_num_t num, const VALUE *ptr);
-extern VALUE rb_vm_opt_newarray_hash(rb_execution_context_t *ec, rb_num_t num, const VALUE *ptr);
-extern VALUE rb_vm_opt_newarray_pack(rb_execution_context_t *ec, rb_num_t num, const VALUE *ptr, VALUE fmt);
-extern VALUE rb_vm_splat_array(VALUE flag, VALUE array);
-extern bool rb_simple_iseq_p(const rb_iseq_t *iseq);
-extern bool rb_vm_defined(rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t op_type, VALUE obj, VALUE v);
-extern bool rb_vm_ic_hit_p(IC ic, const VALUE *reg_ep);
-extern rb_event_flag_t rb_rjit_global_events;
-extern void rb_vm_setinstancevariable(const rb_iseq_t *iseq, VALUE obj, ID id, VALUE val, IVC ic);
-extern VALUE rb_vm_throw(const rb_execution_context_t *ec, rb_control_frame_t *reg_cfp, rb_num_t throw_state, VALUE throwobj);
-extern VALUE rb_reg_new_ary(VALUE ary, int opt);
-extern void rb_vm_setclassvariable(const rb_iseq_t *iseq, const rb_control_frame_t *cfp, ID id, VALUE val, ICVARC ic);
-extern VALUE rb_str_bytesize(VALUE str);
-extern const rb_callable_method_entry_t *rb_callable_method_entry_or_negative(VALUE klass, ID mid);
-extern VALUE rb_vm_yield_with_cfunc(rb_execution_context_t *ec, const struct rb_captured_block *captured, int argc, const VALUE *argv);
-extern VALUE rb_vm_set_ivar_id(VALUE obj, ID id, VALUE val);
-extern VALUE rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary);
-extern void* rb_rjit_entry_stub_hit(VALUE branch_stub);
-extern void* rb_rjit_branch_stub_hit(VALUE branch_stub, int sp_offset, int target0_p);
-extern uint64_t rb_vm_insns_count;
-
-#include "rjit_c.rbinc"
-
-#endif // USE_RJIT
diff --git a/rjit_c.h b/rjit_c.h
deleted file mode 100644
index 029f811637..0000000000
--- a/rjit_c.h
+++ /dev/null
@@ -1,165 +0,0 @@
-// This file is parsed by tool/rjit/generate.rb to generate rjit_c.rb
-#ifndef RJIT_C_H
-#define RJIT_C_H
-
-#include "ruby/internal/config.h"
-#include "internal/string.h"
-#include "internal/struct.h"
-#include "internal/variable.h"
-#include "vm_core.h"
-#include "vm_callinfo.h"
-#include "builtin.h"
-#include "ccan/list/list.h"
-#include "rjit.h"
-#include "shape.h"
-
-extern uint8_t *rb_rjit_mem_block;
-
-#define RJIT_RUNTIME_COUNTERS(...) struct rb_rjit_runtime_counters { size_t __VA_ARGS__; };
-RJIT_RUNTIME_COUNTERS(
- rjit_insns_count,
-
- send_args_splat_kw_splat,
- send_args_splat,
- send_args_splat_not_array,
- send_args_splat_length_not_equal,
- send_args_splat_cfunc_var_args,
- send_args_splat_arity_error,
- send_args_splat_ruby2_hash,
- send_args_splat_cfunc_zuper,
- send_args_splat_cfunc_ruby2_keywords,
- send_kw_splat,
- send_kwarg,
- send_klass_megamorphic,
- send_missing_cme,
- send_private,
- send_protected_check_failed,
- send_tailcall,
- send_notimplemented,
- send_missing,
- send_bmethod,
- send_alias,
- send_undef,
- send_zsuper,
- send_refined,
- send_stackoverflow,
- send_arity,
- send_c_tracing,
- send_is_a_class_mismatch,
- send_instance_of_class_mismatch,
- send_keywords,
-
- send_blockiseq,
- send_block_handler,
- send_block_setup,
- send_block_not_nil,
- send_block_not_proxy,
- send_block_arg,
-
- send_iseq_kwparam,
- send_iseq_accepts_no_kwarg,
- send_iseq_has_opt,
- send_iseq_has_kwrest,
- send_iseq_ruby2_keywords,
- send_iseq_has_rest_and_captured,
- send_iseq_has_rest_and_kw_supplied,
- send_iseq_has_no_kw,
- send_iseq_zsuper,
- send_iseq_materialized_block,
- send_iseq_has_rest,
- send_iseq_block_arg0_splat,
- send_iseq_kw_call,
- send_iseq_kw_splat,
- send_iseq_splat,
- send_iseq_has_rest_and_optional,
- send_iseq_arity_error,
- send_iseq_missing_optional_kw,
- send_iseq_too_many_kwargs,
- send_iseq_kwargs_mismatch,
- send_iseq_splat_with_kw,
- send_iseq_splat_arity_error,
- send_iseq_has_rest_and_splat_not_equal,
-
- send_cfunc_variadic,
- send_cfunc_too_many_args,
- send_cfunc_ruby_array_varg,
- send_cfunc_splat_with_kw,
- send_cfunc_tracing,
- send_cfunc_argc_mismatch,
- send_cfunc_toomany_args,
-
- send_attrset_splat,
- send_attrset_kwarg,
- send_attrset_method,
-
- send_ivar_splat,
- send_ivar_opt_send,
-
- send_optimized_send_no_args,
- send_optimized_send_not_sym_or_str,
- send_optimized_send_mid_class_changed,
- send_optimized_send_mid_id_changed,
- send_optimized_send_null_mid,
- send_optimized_send_send,
- send_optimized_call_block,
- send_optimized_call_kwarg,
- send_optimized_call_splat,
- send_optimized_struct_aref_error,
-
- send_optimized_block_call,
- send_optimized_struct_aset,
-
- send_bmethod_not_iseq,
- send_bmethod_blockarg,
-
- invokesuper_me_changed,
- invokesuper_block,
-
- invokeblock_none,
- invokeblock_symbol,
- invokeblock_proc,
- invokeblock_tag_changed,
- invokeblock_iseq_block_changed,
- invokeblock_iseq_arity,
- invokeblock_iseq_arg0_splat,
- invokeblock_ifunc_args_splat,
- invokeblock_ifunc_kw_splat,
- invokeblock_iseq_arg0_args_splat,
- invokeblock_iseq_arg0_has_kw,
-
- getivar_megamorphic,
- getivar_not_heap,
- getivar_special_const,
- getivar_too_complex,
-
- optaref_arg_not_fixnum,
- optaref_argc_not_one,
- optaref_recv_not_array,
- optaref_recv_not_hash,
- optaref_send,
-
- optgetconst_not_cached,
- optgetconst_cref,
- optgetconst_cache_miss,
-
- setivar_frozen,
- setivar_not_heap,
- setivar_megamorphic,
- setivar_too_complex,
-
- expandarray_splat,
- expandarray_postarg,
- expandarray_not_array,
- expandarray_rhs_too_small,
-
- getblockpp_block_param_modified,
- getblockpp_block_handler_none,
- getblockpp_not_gc_guarded,
- getblockpp_not_iseq_block,
-
- compiled_block_count
-)
-#undef RJIT_RUNTIME_COUNTERS
-extern struct rb_rjit_runtime_counters rb_rjit_counters;
-
-#endif /* RJIT_C_H */
diff --git a/rjit_c.rb b/rjit_c.rb
deleted file mode 100644
index f6d4826135..0000000000
--- a/rjit_c.rb
+++ /dev/null
@@ -1,1670 +0,0 @@
-# frozen_string_literal: true
-# Part of this file is generated by tool/rjit/bindgen.rb.
-# Run `make rjit-bindgen` to update code between "RJIT bindgen begin" and "RJIT bindgen end".
-module RubyVM::RJIT # :nodoc: all
- #
- # Main: Used by RJIT
- #
- # This `class << C` section is for calling C functions with Primitive.
- # For importing variables or macros, use tool/rjit/bindgen.rb instead.
- class << C = Module.new
- def mmap(mem_size)
- Primitive.cexpr! 'SIZET2NUM((size_t)rjit_reserve_addr_space(NUM2UINT(mem_size)))'
- end
-
- def mprotect_write(mem_block, mem_size)
- Primitive.mprotect_write(mem_block, mem_size)
- end
-
- def mprotect_exec(mem_block, mem_size)
- Primitive.mprotect_exec(mem_block, mem_size)
- end
-
- def rjit_insn_exits
- addr = Primitive.cexpr! 'SIZET2NUM((size_t)rjit_insn_exits)'
- CType::Immediate.parse("size_t").new(addr)
- end
-
- def rb_rjit_counters
- addr = Primitive.cexpr! 'SIZET2NUM((size_t)&rb_rjit_counters)'
- rb_rjit_runtime_counters.new(addr)
- end
-
- # @param from [Integer] - From address
- # @param to [Integer] - To address
- def dump_disasm(from, to, test: false)
- Primitive.dump_disasm(from, to, test)
- end
-
- # Convert a Ruby object to a VALUE in Integer
- def to_value(obj)
- Primitive.cexpr! 'SIZET2NUM((size_t)obj)'
- end
-
- def BASIC_OP_UNREDEFINED_P(op, klass)
- Primitive.cexpr! 'RBOOL(BASIC_OP_UNREDEFINED_P(NUM2INT(op), NUM2INT(klass)))'
- end
-
- def rb_iseq_line_no(iseq, pos)
- _iseq_addr = iseq.to_i
- Primitive.cexpr! 'UINT2NUM(rb_iseq_line_no((const rb_iseq_t *)NUM2SIZET(_iseq_addr), NUM2SIZET(pos)))'
- end
-
- def rb_class_of(obj)
- Primitive.cexpr! 'rb_class_of(obj)'
- end
-
- def rb_callable_method_entry(klass, mid)
- cme_addr = Primitive.cexpr! 'SIZET2NUM((size_t)rb_callable_method_entry(klass, NUM2UINT(mid)))'
- return nil if cme_addr == 0
- rb_callable_method_entry_t.new(cme_addr)
- end
-
- def METHOD_ENTRY_VISI(cme)
- _cme_addr = cme.to_i
- Primitive.cexpr! 'UINT2NUM(METHOD_ENTRY_VISI((const rb_callable_method_entry_t *)NUM2SIZET(_cme_addr)))'
- end
-
- def rb_simple_iseq_p(iseq)
- _iseq_addr = iseq.to_i
- Primitive.cexpr! 'RBOOL(rb_simple_iseq_p((rb_iseq_t *)NUM2SIZET(_iseq_addr)))'
- end
-
- def SPECIAL_CONST_P(obj)
- _value = to_value(obj)
- Primitive.cexpr! 'RBOOL(SPECIAL_CONST_P((VALUE)NUM2SIZET(_value)))'
- end
-
- def BUILTIN_TYPE(obj)
- _value = to_value(obj)
- Primitive.cexpr! 'INT2NUM(BUILTIN_TYPE((VALUE)NUM2SIZET(_value)))'
- end
-
- def RB_TYPE_P(obj, type)
- Primitive.cexpr! 'RBOOL(RB_TYPE_P(obj, NUM2UINT(type)))'
- end
-
- def rb_shape_get_shape_id(obj)
- _value = to_value(obj)
- Primitive.cexpr! 'UINT2NUM((unsigned int)rb_shape_get_shape_id((VALUE)NUM2SIZET(_value)))'
- end
-
- def rb_shape_id_offset
- Primitive.cexpr! 'INT2NUM(rb_shape_id_offset())'
- end
-
- def rb_shape_get_iv_index(shape_id, ivar_id)
- Primitive.cstmt! %{
- rb_shape_t *shape = rb_shape_get_shape_by_id((shape_id_t)NUM2SIZET(shape_id));
- attr_index_t index;
- bool found = rb_shape_get_iv_index(shape, (ID)NUM2SIZET(ivar_id), &index);
- return found ? UINT2NUM(index) : Qnil;
- }
- end
-
- def FL_TEST_RAW(obj, flags)
- Primitive.cexpr! 'RBOOL(FL_TEST_RAW(obj, (VALUE)NUM2SIZET(flags)))'
- end
-
- def FL_TEST(obj, flags)
- Primitive.cexpr! 'RBOOL(FL_TEST(obj, (VALUE)NUM2SIZET(flags)))'
- end
-
- def rjit_for_each_iseq(&block)
- Primitive.rjit_for_each_iseq(block)
- end
-
- def get_symbol_id(name)
- Primitive.cexpr! 'SIZET2NUM((size_t)rb_get_symbol_id(name))'
- end
-
- def rb_vm_frame_method_entry(cfp)
- _cfp = cfp.to_i
- cme_addr = Primitive.cexpr! 'SIZET2NUM((size_t)rb_vm_frame_method_entry((const rb_control_frame_t *)NUM2SIZET(_cfp)))'
- return nil if cme_addr == 0
- rb_callable_method_entry_t.new(cme_addr)
- end
-
- def rb_class_get_superclass(klass)
- Primitive.cexpr! 'rb_class_get_superclass(klass)'
- end
-
- def ID2SYM(id)
- Primitive.cexpr! 'ID2SYM((ID)NUM2SIZET(id))'
- end
-
- def obj_is_kind_of(obj, c)
- Primitive.cexpr! 'rb_obj_is_kind_of(obj, c)'
- end
-
- def imemo_type_p(ptr, type)
- _ptr = ptr.to_i
- Primitive.cexpr! 'RBOOL(imemo_type_p((VALUE)NUM2SIZET(_ptr), NUM2UINT(type)))'
- end
-
- def rb_iseq_only_optparam_p(iseq)
- _iseq = iseq.to_i
- Primitive.cstmt! %{
- extern bool rb_iseq_only_optparam_p(const rb_iseq_t *iseq);
- return RBOOL(rb_iseq_only_optparam_p((rb_iseq_t *)NUM2SIZET(_iseq)));
- }
- end
-
- def rb_iseq_only_kwparam_p(iseq)
- _iseq = iseq.to_i
- Primitive.cstmt! %{
- extern bool rb_iseq_only_kwparam_p(const rb_iseq_t *iseq);
- return RBOOL(rb_iseq_only_kwparam_p((rb_iseq_t *)NUM2SIZET(_iseq)));
- }
- end
-
- def rb_obj_frozen_p(obj)
- Primitive.cexpr! 'rb_obj_frozen_p(obj)'
- end
-
- def rb_intern(str)
- Primitive.cexpr! 'SIZET2NUM((size_t)rb_intern(RSTRING_PTR(str)))'
- end
-
- def rb_method_entry_at(klass, mid)
- me_addr = Primitive.cexpr! 'SIZET2NUM((size_t)rb_method_entry_at(klass, (ID)NUM2SIZET(mid)))'
- me_addr == 0 ? nil : rb_method_entry_t.new(me_addr)
- end
-
- def rb_shape_get_next(shape, obj, id)
- _shape = shape.to_i
- shape_addr = Primitive.cexpr! 'SIZET2NUM((size_t)rb_shape_get_next((rb_shape_t *)NUM2SIZET(_shape), obj, (ID)NUM2SIZET(id)))'
- rb_shape_t.new(shape_addr)
- end
-
- def rb_shape_id(shape)
- _shape = shape.to_i
- Primitive.cexpr! 'SIZET2NUM((size_t)rb_shape_id((rb_shape_t *)NUM2SIZET(_shape)))'
- end
-
- def rb_class_attached_object(klass)
- Primitive.cexpr! 'rb_class_attached_object(klass)'
- end
-
- def rb_singleton_class(obj)
- Primitive.cexpr! 'rb_singleton_class(obj)'
- end
-
- def rb_aliased_callable_method_entry(cme)
- _cme = cme.to_i
- cme_addr = Primitive.cstmt! %{
- extern const rb_callable_method_entry_t * rb_aliased_callable_method_entry(const rb_callable_method_entry_t *me);
- return SIZET2NUM((size_t)rb_aliased_callable_method_entry((const rb_callable_method_entry_t *)NUM2SIZET(_cme)));
- }
- rb_callable_method_entry_t.new(cme_addr)
- end
-
- def rb_yjit_get_proc_ptr(proc_addr)
- proc_t_addr = Primitive.cstmt! %{
- extern rb_proc_t * rjit_get_proc_ptr(VALUE procv);
- return SIZET2NUM((size_t)rjit_get_proc_ptr((VALUE)NUM2SIZET(proc_addr)));
- }
- rb_proc_t.new(proc_t_addr)
- end
-
- def rb_shape_get_shape_by_id(shape_id)
- _shape_id = shape_id.to_i
- shape_addr = Primitive.cexpr! 'SIZET2NUM((VALUE)rb_shape_get_shape_by_id((shape_id_t)NUM2UINT(_shape_id)))'
- rb_shape_t.new(shape_addr)
- end
-
- def rb_iseq_check(iseq)
- _iseq_addr = iseq.to_i
- iseq_addr = Primitive.cexpr! 'SIZET2NUM((VALUE)rb_iseq_check((rb_iseq_t *)NUM2SIZET(_iseq_addr)))'
- rb_iseq_t.new(iseq_addr)
- end
-
- def rb_iseq_path(iseq)
- _iseq_addr = iseq.to_i
- Primitive.cexpr! 'rb_iseq_path((rb_iseq_t *)NUM2SIZET(_iseq_addr))'
- end
-
- def vm_ci_argc(ci)
- _ci_addr = ci.to_i
- Primitive.cexpr! 'UINT2NUM(vm_ci_argc((CALL_INFO)NUM2SIZET(_ci_addr)))'
- end
-
- def vm_ci_flag(ci)
- _ci_addr = ci.to_i
- Primitive.cexpr! 'UINT2NUM(vm_ci_flag((CALL_INFO)NUM2SIZET(_ci_addr)))'
- end
-
- def vm_ci_kwarg(ci)
- _ci_addr = ci.to_i
- kwarg_addr = Primitive.cexpr! 'SIZET2NUM((size_t)vm_ci_kwarg((CALL_INFO)NUM2SIZET(_ci_addr)))'
- kwarg_addr == 0 ? nil : rb_callinfo_kwarg.new(kwarg_addr)
- end
-
- def vm_ci_mid(ci)
- _ci_addr = ci.to_i
- Primitive.cexpr! 'SIZET2NUM((size_t)vm_ci_mid((CALL_INFO)NUM2SIZET(_ci_addr)))'
- end
-
- def rjit_opts
- addr = Primitive.cexpr! 'SIZET2NUM((VALUE)&rb_rjit_opts)'
- rb_rjit_options.new(addr)
- end
-
- def rjit_cancel_all(reason)
- Primitive.cstmt! %{
- rb_rjit_cancel_all(RSTRING_PTR(reason));
- return Qnil;
- }
- end
-
- # Convert an encoded VM pointer to an insn BIN.
- def rb_vm_insn_decode(encoded)
- # Using rb_vm_insn_addr2opcode to return trace_ insns
- Primitive.cexpr! 'INT2NUM(rb_vm_insn_addr2opcode((void *)NUM2SIZET(encoded)))'
- end
-
- # Convert Integer VALUE to an actual Ruby object
- def to_ruby(value)
- Primitive.cexpr! '(VALUE)NUM2SIZET(value)'
- end
-
- def HAVE_LIBCAPSTONE
- Primitive.cstmt! %{
- #ifdef HAVE_LIBCAPSTONE
- return Qtrue;
- #else
- return Qfalse;
- #endif
- }
- end
-
- def rjit_exit_traces
- Primitive.cexpr! 'rjit_exit_traces()'
- end
-
- def rb_vm_ep_local_ep(ep)
- _ep = ep.to_i
- lep_addr = Primitive.cexpr! 'SIZET2NUM((size_t)rb_vm_ep_local_ep((const VALUE *)NUM2SIZET(_ep)))'
- C.VALUE.new(lep_addr)
- end
-
- def rb_hash_keys(hash)
- Primitive.cexpr! 'rb_hash_keys(hash)'
- end
-
- def rb_hash_stlike_lookup(hash, key)
- Primitive.cstmt! %{
- VALUE result = Qnil;
- rb_hash_stlike_lookup(hash, key, &result);
- return result;
- }
- end
-
- def rb_obj_class(obj)
- Primitive.cexpr! 'rb_obj_class(obj)'
- end
-
- def rb_sym2id(sym)
- Primitive.cexpr! 'SIZET2NUM((size_t)rb_sym2id(sym))'
- end
-
- def rb_callable_method_entry_or_negative(klass, mid)
- cme_addr = Primitive.cexpr! 'SIZET2NUM((size_t)rb_callable_method_entry_or_negative(klass, (ID)NUM2SIZET(mid)))'
- return nil if cme_addr == 0
- rb_callable_method_entry_t.new(cme_addr)
- end
-
- def rb_method_basic_definition_p(klass, mid)
- Primitive.cexpr! 'RBOOL(rb_method_basic_definition_p(klass, (ID)NUM2SIZET(mid)))'
- end
-
- def UNDEFINED_METHOD_ENTRY_P(cme)
- _cme_addr = cme.to_i
- Primitive.cexpr! 'RBOOL(UNDEFINED_METHOD_ENTRY_P((const rb_callable_method_entry_t *)NUM2SIZET(_cme_addr)))'
- end
-
- def RCLASS_ORIGIN(klass)
- Primitive.cexpr! 'RCLASS_ORIGIN(klass)'
- end
-
- def RCLASS_SINGLETON_P(klass)
- Primitive.cexpr! 'RCLASS_SINGLETON_P(klass)'
- end
- end
-
- #
- # Utilities: Not used by RJIT, but useful for debugging
- #
- class << C
- # Convert insn BINs to encoded VM pointers.
- def rb_vm_insn_encode(bin)
- Primitive.cexpr! 'SIZET2NUM((VALUE)rb_vm_get_insns_address_table()[NUM2INT(bin)])'
- end
-
- # Convert RubyVM::InstructionSequence to C.rb_iseq_t.
- def rb_iseqw_to_iseq(iseqw)
- iseq_addr = Primitive.cexpr! 'SIZET2NUM((VALUE)rb_iseqw_to_iseq(iseqw))'
- rb_iseq_t.new(iseq_addr)
- end
- end
-
- ### RJIT bindgen begin ###
-
- C::UNLIMITED_ARGUMENTS = Primitive.cexpr! %q{ LONG2NUM(UNLIMITED_ARGUMENTS) }
- C::VM_ENV_DATA_INDEX_ME_CREF = Primitive.cexpr! %q{ LONG2NUM(VM_ENV_DATA_INDEX_ME_CREF) }
- C::VM_ENV_DATA_INDEX_SPECVAL = Primitive.cexpr! %q{ LONG2NUM(VM_ENV_DATA_INDEX_SPECVAL) }
- C::ARRAY_REDEFINED_OP_FLAG = Primitive.cexpr! %q{ SIZET2NUM(ARRAY_REDEFINED_OP_FLAG) }
- C::BOP_AND = Primitive.cexpr! %q{ SIZET2NUM(BOP_AND) }
- C::BOP_AREF = Primitive.cexpr! %q{ SIZET2NUM(BOP_AREF) }
- C::BOP_EQ = Primitive.cexpr! %q{ SIZET2NUM(BOP_EQ) }
- C::BOP_EQQ = Primitive.cexpr! %q{ SIZET2NUM(BOP_EQQ) }
- C::BOP_FREEZE = Primitive.cexpr! %q{ SIZET2NUM(BOP_FREEZE) }
- C::BOP_GE = Primitive.cexpr! %q{ SIZET2NUM(BOP_GE) }
- C::BOP_GT = Primitive.cexpr! %q{ SIZET2NUM(BOP_GT) }
- C::BOP_LE = Primitive.cexpr! %q{ SIZET2NUM(BOP_LE) }
- C::BOP_LT = Primitive.cexpr! %q{ SIZET2NUM(BOP_LT) }
- C::BOP_MINUS = Primitive.cexpr! %q{ SIZET2NUM(BOP_MINUS) }
- C::BOP_MOD = Primitive.cexpr! %q{ SIZET2NUM(BOP_MOD) }
- C::BOP_OR = Primitive.cexpr! %q{ SIZET2NUM(BOP_OR) }
- C::BOP_PLUS = Primitive.cexpr! %q{ SIZET2NUM(BOP_PLUS) }
- C::BUILTIN_ATTR_LEAF = Primitive.cexpr! %q{ SIZET2NUM(BUILTIN_ATTR_LEAF) }
- C::HASH_REDEFINED_OP_FLAG = Primitive.cexpr! %q{ SIZET2NUM(HASH_REDEFINED_OP_FLAG) }
- C::INTEGER_REDEFINED_OP_FLAG = Primitive.cexpr! %q{ SIZET2NUM(INTEGER_REDEFINED_OP_FLAG) }
- C::INVALID_SHAPE_ID = Primitive.cexpr! %q{ SIZET2NUM(INVALID_SHAPE_ID) }
- C::METHOD_VISI_PRIVATE = Primitive.cexpr! %q{ SIZET2NUM(METHOD_VISI_PRIVATE) }
- C::METHOD_VISI_PROTECTED = Primitive.cexpr! %q{ SIZET2NUM(METHOD_VISI_PROTECTED) }
- C::METHOD_VISI_PUBLIC = Primitive.cexpr! %q{ SIZET2NUM(METHOD_VISI_PUBLIC) }
- C::METHOD_VISI_UNDEF = Primitive.cexpr! %q{ SIZET2NUM(METHOD_VISI_UNDEF) }
- C::OBJ_TOO_COMPLEX_SHAPE_ID = Primitive.cexpr! %q{ SIZET2NUM(OBJ_TOO_COMPLEX_SHAPE_ID) }
- C::OPTIMIZED_METHOD_TYPE_BLOCK_CALL = Primitive.cexpr! %q{ SIZET2NUM(OPTIMIZED_METHOD_TYPE_BLOCK_CALL) }
- C::OPTIMIZED_METHOD_TYPE_CALL = Primitive.cexpr! %q{ SIZET2NUM(OPTIMIZED_METHOD_TYPE_CALL) }
- C::OPTIMIZED_METHOD_TYPE_SEND = Primitive.cexpr! %q{ SIZET2NUM(OPTIMIZED_METHOD_TYPE_SEND) }
- C::OPTIMIZED_METHOD_TYPE_STRUCT_AREF = Primitive.cexpr! %q{ SIZET2NUM(OPTIMIZED_METHOD_TYPE_STRUCT_AREF) }
- C::OPTIMIZED_METHOD_TYPE_STRUCT_ASET = Primitive.cexpr! %q{ SIZET2NUM(OPTIMIZED_METHOD_TYPE_STRUCT_ASET) }
- C::RARRAY_EMBED_FLAG = Primitive.cexpr! %q{ SIZET2NUM(RARRAY_EMBED_FLAG) }
- C::RARRAY_EMBED_LEN_MASK = Primitive.cexpr! %q{ SIZET2NUM(RARRAY_EMBED_LEN_MASK) }
- C::RARRAY_EMBED_LEN_SHIFT = Primitive.cexpr! %q{ SIZET2NUM(RARRAY_EMBED_LEN_SHIFT) }
- C::RHASH_PASS_AS_KEYWORDS = Primitive.cexpr! %q{ SIZET2NUM(RHASH_PASS_AS_KEYWORDS) }
- C::RMODULE_IS_REFINEMENT = Primitive.cexpr! %q{ SIZET2NUM(RMODULE_IS_REFINEMENT) }
- C::ROBJECT_EMBED = Primitive.cexpr! %q{ SIZET2NUM(ROBJECT_EMBED) }
- C::RSTRUCT_EMBED_LEN_MASK = Primitive.cexpr! %q{ SIZET2NUM(RSTRUCT_EMBED_LEN_MASK) }
- C::RUBY_ENCODING_MASK = Primitive.cexpr! %q{ SIZET2NUM(RUBY_ENCODING_MASK) }
- C::RUBY_EVENT_CLASS = Primitive.cexpr! %q{ SIZET2NUM(RUBY_EVENT_CLASS) }
- C::RUBY_EVENT_C_CALL = Primitive.cexpr! %q{ SIZET2NUM(RUBY_EVENT_C_CALL) }
- C::RUBY_EVENT_C_RETURN = Primitive.cexpr! %q{ SIZET2NUM(RUBY_EVENT_C_RETURN) }
- C::RUBY_FIXNUM_FLAG = Primitive.cexpr! %q{ SIZET2NUM(RUBY_FIXNUM_FLAG) }
- C::RUBY_FLONUM_FLAG = Primitive.cexpr! %q{ SIZET2NUM(RUBY_FLONUM_FLAG) }
- C::RUBY_FLONUM_MASK = Primitive.cexpr! %q{ SIZET2NUM(RUBY_FLONUM_MASK) }
- C::RUBY_FL_FREEZE = Primitive.cexpr! %q{ SIZET2NUM(RUBY_FL_FREEZE) }
- C::RUBY_IMMEDIATE_MASK = Primitive.cexpr! %q{ SIZET2NUM(RUBY_IMMEDIATE_MASK) }
- C::RUBY_SPECIAL_SHIFT = Primitive.cexpr! %q{ SIZET2NUM(RUBY_SPECIAL_SHIFT) }
- C::RUBY_SYMBOL_FLAG = Primitive.cexpr! %q{ SIZET2NUM(RUBY_SYMBOL_FLAG) }
- C::RUBY_T_ARRAY = Primitive.cexpr! %q{ SIZET2NUM(RUBY_T_ARRAY) }
- C::RUBY_T_CLASS = Primitive.cexpr! %q{ SIZET2NUM(RUBY_T_CLASS) }
- C::RUBY_T_HASH = Primitive.cexpr! %q{ SIZET2NUM(RUBY_T_HASH) }
- C::RUBY_T_ICLASS = Primitive.cexpr! %q{ SIZET2NUM(RUBY_T_ICLASS) }
- C::RUBY_T_MASK = Primitive.cexpr! %q{ SIZET2NUM(RUBY_T_MASK) }
- C::RUBY_T_MODULE = Primitive.cexpr! %q{ SIZET2NUM(RUBY_T_MODULE) }
- C::RUBY_T_OBJECT = Primitive.cexpr! %q{ SIZET2NUM(RUBY_T_OBJECT) }
- C::RUBY_T_STRING = Primitive.cexpr! %q{ SIZET2NUM(RUBY_T_STRING) }
- C::RUBY_T_SYMBOL = Primitive.cexpr! %q{ SIZET2NUM(RUBY_T_SYMBOL) }
- C::SHAPE_FLAG_SHIFT = Primitive.cexpr! %q{ SIZET2NUM(SHAPE_FLAG_SHIFT) }
- C::SHAPE_FROZEN = Primitive.cexpr! %q{ SIZET2NUM(SHAPE_FROZEN) }
- C::SHAPE_ID_NUM_BITS = Primitive.cexpr! %q{ SIZET2NUM(SHAPE_ID_NUM_BITS) }
- C::SHAPE_IVAR = Primitive.cexpr! %q{ SIZET2NUM(SHAPE_IVAR) }
- C::SHAPE_MASK = Primitive.cexpr! %q{ SIZET2NUM(SHAPE_MASK) }
- C::SHAPE_ROOT = Primitive.cexpr! %q{ SIZET2NUM(SHAPE_ROOT) }
- C::STRING_REDEFINED_OP_FLAG = Primitive.cexpr! %q{ SIZET2NUM(STRING_REDEFINED_OP_FLAG) }
- C::T_OBJECT = Primitive.cexpr! %q{ SIZET2NUM(T_OBJECT) }
- C::VM_BLOCK_HANDLER_NONE = Primitive.cexpr! %q{ SIZET2NUM(VM_BLOCK_HANDLER_NONE) }
- C::VM_CALL_ARGS_BLOCKARG = Primitive.cexpr! %q{ SIZET2NUM(VM_CALL_ARGS_BLOCKARG) }
- C::VM_CALL_ARGS_SPLAT = Primitive.cexpr! %q{ SIZET2NUM(VM_CALL_ARGS_SPLAT) }
- C::VM_CALL_FCALL = Primitive.cexpr! %q{ SIZET2NUM(VM_CALL_FCALL) }
- C::VM_CALL_KWARG = Primitive.cexpr! %q{ SIZET2NUM(VM_CALL_KWARG) }
- C::VM_CALL_KW_SPLAT = Primitive.cexpr! %q{ SIZET2NUM(VM_CALL_KW_SPLAT) }
- C::VM_CALL_KW_SPLAT_MUT = Primitive.cexpr! %q{ SIZET2NUM(VM_CALL_KW_SPLAT_MUT) }
- C::VM_CALL_KW_SPLAT_bit = Primitive.cexpr! %q{ SIZET2NUM(VM_CALL_KW_SPLAT_bit) }
- C::VM_CALL_OPT_SEND = Primitive.cexpr! %q{ SIZET2NUM(VM_CALL_OPT_SEND) }
- C::VM_CALL_TAILCALL = Primitive.cexpr! %q{ SIZET2NUM(VM_CALL_TAILCALL) }
- C::VM_CALL_TAILCALL_bit = Primitive.cexpr! %q{ SIZET2NUM(VM_CALL_TAILCALL_bit) }
- C::VM_CALL_ZSUPER = Primitive.cexpr! %q{ SIZET2NUM(VM_CALL_ZSUPER) }
- C::VM_ENV_DATA_INDEX_FLAGS = Primitive.cexpr! %q{ SIZET2NUM(VM_ENV_DATA_INDEX_FLAGS) }
- C::VM_ENV_DATA_SIZE = Primitive.cexpr! %q{ SIZET2NUM(VM_ENV_DATA_SIZE) }
- C::VM_ENV_FLAG_LOCAL = Primitive.cexpr! %q{ SIZET2NUM(VM_ENV_FLAG_LOCAL) }
- C::VM_ENV_FLAG_WB_REQUIRED = Primitive.cexpr! %q{ SIZET2NUM(VM_ENV_FLAG_WB_REQUIRED) }
- C::VM_FRAME_FLAG_BMETHOD = Primitive.cexpr! %q{ SIZET2NUM(VM_FRAME_FLAG_BMETHOD) }
- C::VM_FRAME_FLAG_CFRAME = Primitive.cexpr! %q{ SIZET2NUM(VM_FRAME_FLAG_CFRAME) }
- C::VM_FRAME_FLAG_CFRAME_KW = Primitive.cexpr! %q{ SIZET2NUM(VM_FRAME_FLAG_CFRAME_KW) }
- C::VM_FRAME_FLAG_LAMBDA = Primitive.cexpr! %q{ SIZET2NUM(VM_FRAME_FLAG_LAMBDA) }
- C::VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM = Primitive.cexpr! %q{ SIZET2NUM(VM_FRAME_FLAG_MODIFIED_BLOCK_PARAM) }
- C::VM_FRAME_MAGIC_BLOCK = Primitive.cexpr! %q{ SIZET2NUM(VM_FRAME_MAGIC_BLOCK) }
- C::VM_FRAME_MAGIC_CFUNC = Primitive.cexpr! %q{ SIZET2NUM(VM_FRAME_MAGIC_CFUNC) }
- C::VM_FRAME_MAGIC_METHOD = Primitive.cexpr! %q{ SIZET2NUM(VM_FRAME_MAGIC_METHOD) }
- C::VM_METHOD_TYPE_ALIAS = Primitive.cexpr! %q{ SIZET2NUM(VM_METHOD_TYPE_ALIAS) }
- C::VM_METHOD_TYPE_ATTRSET = Primitive.cexpr! %q{ SIZET2NUM(VM_METHOD_TYPE_ATTRSET) }
- C::VM_METHOD_TYPE_BMETHOD = Primitive.cexpr! %q{ SIZET2NUM(VM_METHOD_TYPE_BMETHOD) }
- C::VM_METHOD_TYPE_CFUNC = Primitive.cexpr! %q{ SIZET2NUM(VM_METHOD_TYPE_CFUNC) }
- C::VM_METHOD_TYPE_ISEQ = Primitive.cexpr! %q{ SIZET2NUM(VM_METHOD_TYPE_ISEQ) }
- C::VM_METHOD_TYPE_IVAR = Primitive.cexpr! %q{ SIZET2NUM(VM_METHOD_TYPE_IVAR) }
- C::VM_METHOD_TYPE_MISSING = Primitive.cexpr! %q{ SIZET2NUM(VM_METHOD_TYPE_MISSING) }
- C::VM_METHOD_TYPE_NOTIMPLEMENTED = Primitive.cexpr! %q{ SIZET2NUM(VM_METHOD_TYPE_NOTIMPLEMENTED) }
- C::VM_METHOD_TYPE_OPTIMIZED = Primitive.cexpr! %q{ SIZET2NUM(VM_METHOD_TYPE_OPTIMIZED) }
- C::VM_METHOD_TYPE_REFINED = Primitive.cexpr! %q{ SIZET2NUM(VM_METHOD_TYPE_REFINED) }
- C::VM_METHOD_TYPE_UNDEF = Primitive.cexpr! %q{ SIZET2NUM(VM_METHOD_TYPE_UNDEF) }
- C::VM_METHOD_TYPE_ZSUPER = Primitive.cexpr! %q{ SIZET2NUM(VM_METHOD_TYPE_ZSUPER) }
- C::VM_SPECIAL_OBJECT_VMCORE = Primitive.cexpr! %q{ SIZET2NUM(VM_SPECIAL_OBJECT_VMCORE) }
-
- def C.block_type_iseq = Primitive.cexpr!(%q{ SIZET2NUM(block_type_iseq) })
- def C.idRespond_to_missing = Primitive.cexpr!(%q{ SIZET2NUM(idRespond_to_missing) })
- def C.imemo_callinfo = Primitive.cexpr!(%q{ SIZET2NUM(imemo_callinfo) })
- def C.imemo_iseq = Primitive.cexpr!(%q{ SIZET2NUM(imemo_iseq) })
- def C.rb_block_param_proxy = Primitive.cexpr!(%q{ SIZET2NUM(rb_block_param_proxy) })
- def C.rb_cArray = Primitive.cexpr!(%q{ SIZET2NUM(rb_cArray) })
- def C.rb_cFalseClass = Primitive.cexpr!(%q{ SIZET2NUM(rb_cFalseClass) })
- def C.rb_cFloat = Primitive.cexpr!(%q{ SIZET2NUM(rb_cFloat) })
- def C.rb_cInteger = Primitive.cexpr!(%q{ SIZET2NUM(rb_cInteger) })
- def C.rb_cNilClass = Primitive.cexpr!(%q{ SIZET2NUM(rb_cNilClass) })
- def C.rb_cString = Primitive.cexpr!(%q{ SIZET2NUM(rb_cString) })
- def C.rb_cSymbol = Primitive.cexpr!(%q{ SIZET2NUM(rb_cSymbol) })
- def C.rb_cTrueClass = Primitive.cexpr!(%q{ SIZET2NUM(rb_cTrueClass) })
- def C.rb_mRubyVMFrozenCore = Primitive.cexpr!(%q{ SIZET2NUM(rb_mRubyVMFrozenCore) })
- def C.rb_rjit_global_events = Primitive.cexpr!(%q{ SIZET2NUM(rb_rjit_global_events) })
- def C.rb_vm_insns_count = Primitive.cexpr!(%q{ SIZET2NUM(rb_vm_insns_count) })
-
- def C.rb_ary_clear
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ary_clear) }
- end
-
- def C.rb_ary_dup
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ary_dup) }
- end
-
- def C.rb_ary_entry_internal
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ary_entry_internal) }
- end
-
- def C.rb_ary_push
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ary_push) }
- end
-
- def C.rb_ary_resurrect
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ary_resurrect) }
- end
-
- def C.rb_ary_store
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ary_store) }
- end
-
- def C.rb_ary_tmp_new_from_values
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ary_tmp_new_from_values) }
- end
-
- def C.rb_ary_unshift_m
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ary_unshift_m) }
- end
-
- def C.rb_backref_get
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_backref_get) }
- end
-
- def C.rb_ec_ary_new_from_values
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ec_ary_new_from_values) }
- end
-
- def C.rb_ec_str_resurrect
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ec_str_resurrect) }
- end
-
- def C.rb_ensure_iv_list_size
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ensure_iv_list_size) }
- end
-
- def C.rb_fix_aref
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_fix_aref) }
- end
-
- def C.rb_fix_div_fix
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_fix_div_fix) }
- end
-
- def C.rb_fix_mod_fix
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_fix_mod_fix) }
- end
-
- def C.rb_fix_mul_fix
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_fix_mul_fix) }
- end
-
- def C.rb_gc_writebarrier
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_gc_writebarrier) }
- end
-
- def C.rb_get_symbol_id
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_get_symbol_id) }
- end
-
- def C.rb_gvar_get
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_gvar_get) }
- end
-
- def C.rb_hash_aref
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_hash_aref) }
- end
-
- def C.rb_hash_aset
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_hash_aset) }
- end
-
- def C.rb_hash_bulk_insert
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_hash_bulk_insert) }
- end
-
- def C.rb_hash_new
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_hash_new) }
- end
-
- def C.rb_hash_new_with_size
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_hash_new_with_size) }
- end
-
- def C.rb_hash_resurrect
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_hash_resurrect) }
- end
-
- def C.rb_ivar_defined
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ivar_defined) }
- end
-
- def C.rb_ivar_get
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_ivar_get) }
- end
-
- def C.rb_obj_as_string_result
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_obj_as_string_result) }
- end
-
- def C.rb_obj_is_kind_of
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_obj_is_kind_of) }
- end
-
- def C.rb_range_new
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_range_new) }
- end
-
- def C.rb_reg_last_match
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_reg_last_match) }
- end
-
- def C.rb_reg_match_last
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_reg_match_last) }
- end
-
- def C.rb_reg_match_post
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_reg_match_post) }
- end
-
- def C.rb_reg_match_pre
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_reg_match_pre) }
- end
-
- def C.rb_reg_new_ary
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_reg_new_ary) }
- end
-
- def C.rb_reg_nth_match
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_reg_nth_match) }
- end
-
- def C.rb_rjit_branch_stub_hit
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_rjit_branch_stub_hit) }
- end
-
- def C.rb_rjit_entry_stub_hit
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_rjit_entry_stub_hit) }
- end
-
- def C.rb_str_buf_append
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_str_buf_append) }
- end
-
- def C.rb_str_bytesize
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_str_bytesize) }
- end
-
- def C.rb_str_concat_literals
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_str_concat_literals) }
- end
-
- def C.rb_str_dup
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_str_dup) }
- end
-
- def C.rb_str_eql_internal
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_str_eql_internal) }
- end
-
- def C.rb_str_getbyte
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_str_getbyte) }
- end
-
- def C.rb_str_intern
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_str_intern) }
- end
-
- def C.rb_sym_to_proc
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_sym_to_proc) }
- end
-
- def C.rb_vm_bh_to_procval
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_bh_to_procval) }
- end
-
- def C.rb_vm_concat_array
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_concat_array) }
- end
-
- def C.rb_vm_defined
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_defined) }
- end
-
- def C.rb_vm_get_ev_const
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_get_ev_const) }
- end
-
- def C.rb_vm_getclassvariable
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_getclassvariable) }
- end
-
- def C.rb_vm_ic_hit_p
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_ic_hit_p) }
- end
-
- def C.rb_vm_opt_newarray_hash
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_opt_newarray_hash) }
- end
-
- def C.rb_vm_opt_newarray_max
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_opt_newarray_max) }
- end
-
- def C.rb_vm_opt_newarray_min
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_opt_newarray_min) }
- end
-
- def C.rb_vm_opt_newarray_pack
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_opt_newarray_pack) }
- end
-
- def C.rb_vm_set_ivar_id
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_set_ivar_id) }
- end
-
- def C.rb_vm_setclassvariable
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_setclassvariable) }
- end
-
- def C.rb_vm_setinstancevariable
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_setinstancevariable) }
- end
-
- def C.rb_vm_splat_array
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_splat_array) }
- end
-
- def C.rb_vm_throw
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_throw) }
- end
-
- def C.rb_vm_yield_with_cfunc
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rb_vm_yield_with_cfunc) }
- end
-
- def C.rjit_build_kwhash
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rjit_build_kwhash) }
- end
-
- def C.rjit_full_cfunc_return
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rjit_full_cfunc_return) }
- end
-
- def C.rjit_optimized_call
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rjit_optimized_call) }
- end
-
- def C.rjit_rb_ary_subseq_length
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rjit_rb_ary_subseq_length) }
- end
-
- def C.rjit_record_exit_stack
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rjit_record_exit_stack) }
- end
-
- def C.rjit_str_neq_internal
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rjit_str_neq_internal) }
- end
-
- def C.rjit_str_simple_append
- Primitive.cexpr! %q{ SIZET2NUM((size_t)rjit_str_simple_append) }
- end
-
- def C.CALL_DATA
- @CALL_DATA ||= self.rb_call_data
- end
-
- def C.IC
- @IC ||= self.iseq_inline_constant_cache
- end
-
- def C.ID
- @ID ||= CType::Immediate.parse("unsigned long")
- end
-
- def C.IVC
- @IVC ||= self.iseq_inline_iv_cache_entry
- end
-
- def C.RArray
- @RArray ||= CType::Struct.new(
- "RArray", Primitive.cexpr!("SIZEOF(struct RArray)"),
- basic: [self.RBasic, Primitive.cexpr!("OFFSETOF((*((struct RArray *)NULL)), basic)")],
- as: [CType::Union.new(
- "", Primitive.cexpr!("SIZEOF(((struct RArray *)NULL)->as)"),
- heap: CType::Struct.new(
- "", Primitive.cexpr!("SIZEOF(((struct RArray *)NULL)->as.heap)"),
- len: [CType::Immediate.parse("long"), Primitive.cexpr!("OFFSETOF(((struct RArray *)NULL)->as.heap, len)")],
- aux: [CType::Union.new(
- "", Primitive.cexpr!("SIZEOF(((struct RArray *)NULL)->as.heap.aux)"),
- capa: CType::Immediate.parse("long"),
- shared_root: self.VALUE,
- ), Primitive.cexpr!("OFFSETOF(((struct RArray *)NULL)->as.heap, aux)")],
- ptr: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF(((struct RArray *)NULL)->as.heap, ptr)")],
- ),
- ary: CType::Array.new { self.VALUE },
- ), Primitive.cexpr!("OFFSETOF((*((struct RArray *)NULL)), as)")],
- )
- end
-
- def C.RB_BUILTIN
- @RB_BUILTIN ||= self.rb_builtin_function
- end
-
- def C.RBasic
- @RBasic ||= CType::Struct.new(
- "RBasic", Primitive.cexpr!("SIZEOF(struct RBasic)"),
- flags: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct RBasic *)NULL)), flags)")],
- klass: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct RBasic *)NULL)), klass)")],
- )
- end
-
- def C.RObject
- @RObject ||= CType::Struct.new(
- "RObject", Primitive.cexpr!("SIZEOF(struct RObject)"),
- basic: [self.RBasic, Primitive.cexpr!("OFFSETOF((*((struct RObject *)NULL)), basic)")],
- as: [CType::Union.new(
- "", Primitive.cexpr!("SIZEOF(((struct RObject *)NULL)->as)"),
- heap: CType::Struct.new(
- "", Primitive.cexpr!("SIZEOF(((struct RObject *)NULL)->as.heap)"),
- ivptr: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF(((struct RObject *)NULL)->as.heap, ivptr)")],
- iv_index_tbl: [CType::Pointer.new { self.rb_id_table }, Primitive.cexpr!("OFFSETOF(((struct RObject *)NULL)->as.heap, iv_index_tbl)")],
- ),
- ary: CType::Array.new { self.VALUE },
- ), Primitive.cexpr!("OFFSETOF((*((struct RObject *)NULL)), as)")],
- )
- end
-
- def C.RString
- @RString ||= CType::Struct.new(
- "RString", Primitive.cexpr!("SIZEOF(struct RString)"),
- basic: [self.RBasic, Primitive.cexpr!("OFFSETOF((*((struct RString *)NULL)), basic)")],
- len: [CType::Immediate.parse("long"), Primitive.cexpr!("OFFSETOF((*((struct RString *)NULL)), len)")],
- as: [CType::Union.new(
- "", Primitive.cexpr!("SIZEOF(((struct RString *)NULL)->as)"),
- heap: CType::Struct.new(
- "", Primitive.cexpr!("SIZEOF(((struct RString *)NULL)->as.heap)"),
- ptr: [CType::Pointer.new { CType::Immediate.parse("char") }, Primitive.cexpr!("OFFSETOF(((struct RString *)NULL)->as.heap, ptr)")],
- aux: [CType::Union.new(
- "", Primitive.cexpr!("SIZEOF(((struct RString *)NULL)->as.heap.aux)"),
- capa: CType::Immediate.parse("long"),
- shared: self.VALUE,
- ), Primitive.cexpr!("OFFSETOF(((struct RString *)NULL)->as.heap, aux)")],
- ),
- embed: CType::Struct.new(
- "", Primitive.cexpr!("SIZEOF(((struct RString *)NULL)->as.embed)"),
- ary: [CType::Array.new { CType::Immediate.parse("char") }, Primitive.cexpr!("OFFSETOF(((struct RString *)NULL)->as.embed, ary)")],
- ),
- ), Primitive.cexpr!("OFFSETOF((*((struct RString *)NULL)), as)")],
- )
- end
-
- def C.RStruct
- @RStruct ||= CType::Struct.new(
- "RStruct", Primitive.cexpr!("SIZEOF(struct RStruct)"),
- basic: [self.RBasic, Primitive.cexpr!("OFFSETOF((*((struct RStruct *)NULL)), basic)")],
- as: [CType::Union.new(
- "", Primitive.cexpr!("SIZEOF(((struct RStruct *)NULL)->as)"),
- heap: CType::Struct.new(
- "", Primitive.cexpr!("SIZEOF(((struct RStruct *)NULL)->as.heap)"),
- len: [CType::Immediate.parse("long"), Primitive.cexpr!("OFFSETOF(((struct RStruct *)NULL)->as.heap, len)")],
- ptr: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF(((struct RStruct *)NULL)->as.heap, ptr)")],
- ),
- ary: CType::Array.new { self.VALUE },
- ), Primitive.cexpr!("OFFSETOF((*((struct RStruct *)NULL)), as)")],
- )
- end
-
- def C.attr_index_t
- @attr_index_t ||= CType::Immediate.parse("uint32_t")
- end
-
- def C.iseq_inline_constant_cache
- @iseq_inline_constant_cache ||= CType::Struct.new(
- "iseq_inline_constant_cache", Primitive.cexpr!("SIZEOF(struct iseq_inline_constant_cache)"),
- entry: [CType::Pointer.new { self.iseq_inline_constant_cache_entry }, Primitive.cexpr!("OFFSETOF((*((struct iseq_inline_constant_cache *)NULL)), entry)")],
- segments: [CType::Pointer.new { self.ID }, Primitive.cexpr!("OFFSETOF((*((struct iseq_inline_constant_cache *)NULL)), segments)")],
- )
- end
-
- def C.iseq_inline_constant_cache_entry
- @iseq_inline_constant_cache_entry ||= CType::Struct.new(
- "iseq_inline_constant_cache_entry", Primitive.cexpr!("SIZEOF(struct iseq_inline_constant_cache_entry)"),
- flags: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct iseq_inline_constant_cache_entry *)NULL)), flags)")],
- value: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct iseq_inline_constant_cache_entry *)NULL)), value)")],
- _unused1: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct iseq_inline_constant_cache_entry *)NULL)), _unused1)")],
- _unused2: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct iseq_inline_constant_cache_entry *)NULL)), _unused2)")],
- ic_cref: [CType::Pointer.new { self.rb_cref_t }, Primitive.cexpr!("OFFSETOF((*((struct iseq_inline_constant_cache_entry *)NULL)), ic_cref)")],
- )
- end
-
- def C.iseq_inline_iv_cache_entry
- @iseq_inline_iv_cache_entry ||= CType::Struct.new(
- "iseq_inline_iv_cache_entry", Primitive.cexpr!("SIZEOF(struct iseq_inline_iv_cache_entry)"),
- value: [CType::Immediate.parse("uintptr_t"), Primitive.cexpr!("OFFSETOF((*((struct iseq_inline_iv_cache_entry *)NULL)), value)")],
- iv_set_name: [self.ID, Primitive.cexpr!("OFFSETOF((*((struct iseq_inline_iv_cache_entry *)NULL)), iv_set_name)")],
- )
- end
-
- def C.iseq_inline_storage_entry
- @iseq_inline_storage_entry ||= CType::Union.new(
- "iseq_inline_storage_entry", Primitive.cexpr!("SIZEOF(union iseq_inline_storage_entry)"),
- once: CType::Struct.new(
- "", Primitive.cexpr!("SIZEOF(((union iseq_inline_storage_entry *)NULL)->once)"),
- running_thread: [CType::Pointer.new { self.rb_thread_struct }, Primitive.cexpr!("OFFSETOF(((union iseq_inline_storage_entry *)NULL)->once, running_thread)")],
- value: [self.VALUE, Primitive.cexpr!("OFFSETOF(((union iseq_inline_storage_entry *)NULL)->once, value)")],
- ),
- ic_cache: self.iseq_inline_constant_cache,
- iv_cache: self.iseq_inline_iv_cache_entry,
- )
- end
-
- def C.method_optimized_type
- @method_optimized_type ||= CType::Immediate.parse("int")
- end
-
- def C.rb_block
- @rb_block ||= CType::Struct.new(
- "rb_block", Primitive.cexpr!("SIZEOF(struct rb_block)"),
- as: [CType::Union.new(
- "", Primitive.cexpr!("SIZEOF(((struct rb_block *)NULL)->as)"),
- captured: self.rb_captured_block,
- symbol: self.VALUE,
- proc: self.VALUE,
- ), Primitive.cexpr!("OFFSETOF((*((struct rb_block *)NULL)), as)")],
- type: [self.rb_block_type, Primitive.cexpr!("OFFSETOF((*((struct rb_block *)NULL)), type)")],
- )
- end
-
- def C.rb_block_type
- @rb_block_type ||= CType::Immediate.parse("int")
- end
-
- def C.rb_builtin_function
- @rb_builtin_function ||= CType::Struct.new(
- "rb_builtin_function", Primitive.cexpr!("SIZEOF(struct rb_builtin_function)"),
- func_ptr: [CType::Immediate.parse("void *"), Primitive.cexpr!("OFFSETOF((*((struct rb_builtin_function *)NULL)), func_ptr)")],
- argc: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct rb_builtin_function *)NULL)), argc)")],
- index: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct rb_builtin_function *)NULL)), index)")],
- name: [CType::Pointer.new { CType::Immediate.parse("char") }, Primitive.cexpr!("OFFSETOF((*((struct rb_builtin_function *)NULL)), name)")],
- )
- end
-
- def C.rb_call_data
- @rb_call_data ||= CType::Struct.new(
- "rb_call_data", Primitive.cexpr!("SIZEOF(struct rb_call_data)"),
- ci: [CType::Pointer.new { self.rb_callinfo }, Primitive.cexpr!("OFFSETOF((*((struct rb_call_data *)NULL)), ci)")],
- cc: [CType::Pointer.new { self.rb_callcache }, Primitive.cexpr!("OFFSETOF((*((struct rb_call_data *)NULL)), cc)")],
- )
- end
-
- def C.rb_callable_method_entry_struct
- @rb_callable_method_entry_struct ||= CType::Struct.new(
- "rb_callable_method_entry_struct", Primitive.cexpr!("SIZEOF(struct rb_callable_method_entry_struct)"),
- flags: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_callable_method_entry_struct *)NULL)), flags)")],
- defined_class: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_callable_method_entry_struct *)NULL)), defined_class)"), true],
- def: [CType::Pointer.new { self.rb_method_definition_struct }, Primitive.cexpr!("OFFSETOF((*((struct rb_callable_method_entry_struct *)NULL)), def)")],
- called_id: [self.ID, Primitive.cexpr!("OFFSETOF((*((struct rb_callable_method_entry_struct *)NULL)), called_id)")],
- owner: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_callable_method_entry_struct *)NULL)), owner)")],
- )
- end
-
- def C.rb_callable_method_entry_t
- @rb_callable_method_entry_t ||= CType::Struct.new(
- "rb_callable_method_entry_struct", Primitive.cexpr!("SIZEOF(struct rb_callable_method_entry_struct)"),
- flags: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_callable_method_entry_struct *)NULL)), flags)")],
- defined_class: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_callable_method_entry_struct *)NULL)), defined_class)"), true],
- def: [CType::Pointer.new { self.rb_method_definition_struct }, Primitive.cexpr!("OFFSETOF((*((struct rb_callable_method_entry_struct *)NULL)), def)")],
- called_id: [self.ID, Primitive.cexpr!("OFFSETOF((*((struct rb_callable_method_entry_struct *)NULL)), called_id)")],
- owner: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_callable_method_entry_struct *)NULL)), owner)")],
- )
- end
-
- def C.rb_callcache
- @rb_callcache ||= CType::Struct.new(
- "rb_callcache", Primitive.cexpr!("SIZEOF(struct rb_callcache)"),
- flags: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_callcache *)NULL)), flags)")],
- klass: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_callcache *)NULL)), klass)")],
- cme_: [CType::Pointer.new { self.rb_callable_method_entry_struct }, Primitive.cexpr!("OFFSETOF((*((struct rb_callcache *)NULL)), cme_)")],
- call_: [self.vm_call_handler, Primitive.cexpr!("OFFSETOF((*((struct rb_callcache *)NULL)), call_)")],
- aux_: [CType::Union.new(
- "", Primitive.cexpr!("SIZEOF(((struct rb_callcache *)NULL)->aux_)"),
- attr: CType::Struct.new(
- "", Primitive.cexpr!("SIZEOF(((struct rb_callcache *)NULL)->aux_.attr)"),
- value: [CType::Immediate.parse("uintptr_t"), Primitive.cexpr!("OFFSETOF(((struct rb_callcache *)NULL)->aux_.attr, value)")],
- ),
- method_missing_reason: self.method_missing_reason,
- v: self.VALUE,
- bf: CType::Pointer.new { self.rb_builtin_function },
- ), Primitive.cexpr!("OFFSETOF((*((struct rb_callcache *)NULL)), aux_)")],
- )
- end
-
- def C.rb_callinfo
- @rb_callinfo ||= CType::Struct.new(
- "rb_callinfo", Primitive.cexpr!("SIZEOF(struct rb_callinfo)"),
- flags: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_callinfo *)NULL)), flags)")],
- kwarg: [CType::Pointer.new { self.rb_callinfo_kwarg }, Primitive.cexpr!("OFFSETOF((*((struct rb_callinfo *)NULL)), kwarg)")],
- mid: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_callinfo *)NULL)), mid)")],
- flag: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_callinfo *)NULL)), flag)")],
- argc: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_callinfo *)NULL)), argc)")],
- )
- end
-
- def C.rb_callinfo_kwarg
- @rb_callinfo_kwarg ||= CType::Struct.new(
- "rb_callinfo_kwarg", Primitive.cexpr!("SIZEOF(struct rb_callinfo_kwarg)"),
- keyword_len: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct rb_callinfo_kwarg *)NULL)), keyword_len)")],
- references: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct rb_callinfo_kwarg *)NULL)), references)")],
- keywords: [CType::Immediate.parse("void *"), Primitive.cexpr!("OFFSETOF((*((struct rb_callinfo_kwarg *)NULL)), keywords)")],
- )
- end
-
- def C.rb_captured_block
- @rb_captured_block ||= CType::Struct.new(
- "rb_captured_block", Primitive.cexpr!("SIZEOF(struct rb_captured_block)"),
- self: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_captured_block *)NULL)), self)")],
- ep: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF((*((struct rb_captured_block *)NULL)), ep)")],
- code: [CType::Union.new(
- "", Primitive.cexpr!("SIZEOF(((struct rb_captured_block *)NULL)->code)"),
- iseq: CType::Pointer.new { self.rb_iseq_t },
- ifunc: CType::Pointer.new { self.vm_ifunc },
- val: self.VALUE,
- ), Primitive.cexpr!("OFFSETOF((*((struct rb_captured_block *)NULL)), code)")],
- )
- end
-
- def C.rb_cfunc_t
- @rb_cfunc_t ||= self.VALUE
- end
-
- def C.rb_control_frame_t
- @rb_control_frame_t ||= CType::Struct.new(
- "rb_control_frame_struct", Primitive.cexpr!("SIZEOF(struct rb_control_frame_struct)"),
- pc: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF((*((struct rb_control_frame_struct *)NULL)), pc)")],
- sp: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF((*((struct rb_control_frame_struct *)NULL)), sp)")],
- iseq: [CType::Pointer.new { self.rb_iseq_t }, Primitive.cexpr!("OFFSETOF((*((struct rb_control_frame_struct *)NULL)), iseq)")],
- self: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_control_frame_struct *)NULL)), self)")],
- ep: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF((*((struct rb_control_frame_struct *)NULL)), ep)")],
- block_code: [CType::Immediate.parse("void *"), Primitive.cexpr!("OFFSETOF((*((struct rb_control_frame_struct *)NULL)), block_code)")],
- jit_return: [CType::Pointer.new { CType::Immediate.parse("void") }, Primitive.cexpr!("OFFSETOF((*((struct rb_control_frame_struct *)NULL)), jit_return)")],
- )
- end
-
- def C.rb_cref_t
- @rb_cref_t ||= CType::Struct.new(
- "rb_cref_struct", Primitive.cexpr!("SIZEOF(struct rb_cref_struct)"),
- flags: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_cref_struct *)NULL)), flags)")],
- refinements: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_cref_struct *)NULL)), refinements)")],
- klass_or_self: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_cref_struct *)NULL)), klass_or_self)")],
- next: [CType::Pointer.new { self.rb_cref_struct }, Primitive.cexpr!("OFFSETOF((*((struct rb_cref_struct *)NULL)), next)")],
- scope_visi: [self.rb_scope_visibility_t, Primitive.cexpr!("OFFSETOF((*((struct rb_cref_struct *)NULL)), scope_visi)")],
- )
- end
-
- def C.rb_execution_context_struct
- @rb_execution_context_struct ||= CType::Struct.new(
- "rb_execution_context_struct", Primitive.cexpr!("SIZEOF(struct rb_execution_context_struct)"),
- vm_stack: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), vm_stack)")],
- vm_stack_size: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), vm_stack_size)")],
- cfp: [CType::Pointer.new { self.rb_control_frame_t }, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), cfp)")],
- tag: [CType::Pointer.new { self.rb_vm_tag }, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), tag)")],
- interrupt_flag: [self.rb_atomic_t, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), interrupt_flag)")],
- interrupt_mask: [self.rb_atomic_t, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), interrupt_mask)")],
- fiber_ptr: [CType::Pointer.new { self.rb_fiber_t }, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), fiber_ptr)")],
- thread_ptr: [CType::Pointer.new { self.rb_thread_struct }, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), thread_ptr)")],
- local_storage: [CType::Pointer.new { self.rb_id_table }, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), local_storage)")],
- local_storage_recursive_hash: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), local_storage_recursive_hash)")],
- local_storage_recursive_hash_for_trace: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), local_storage_recursive_hash_for_trace)")],
- storage: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), storage)")],
- root_lep: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), root_lep)")],
- root_svar: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), root_svar)")],
- ensure_list: [CType::Pointer.new { self.rb_ensure_list_t }, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), ensure_list)")],
- trace_arg: [CType::Pointer.new { self.rb_trace_arg_struct }, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), trace_arg)")],
- errinfo: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), errinfo)")],
- passed_block_handler: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), passed_block_handler)")],
- raised_flag: [CType::Immediate.parse("uint8_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), raised_flag)")],
- private_const_reference: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), private_const_reference)")],
- machine: [CType::Struct.new(
- "", Primitive.cexpr!("SIZEOF(((struct rb_execution_context_struct *)NULL)->machine)"),
- stack_start: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF(((struct rb_execution_context_struct *)NULL)->machine, stack_start)")],
- stack_end: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF(((struct rb_execution_context_struct *)NULL)->machine, stack_end)")],
- stack_maxsize: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF(((struct rb_execution_context_struct *)NULL)->machine, stack_maxsize)")],
- ), Primitive.cexpr!("OFFSETOF((*((struct rb_execution_context_struct *)NULL)), machine)")],
- )
- end
-
- def C.rb_execution_context_t
- @rb_execution_context_t ||= self.rb_execution_context_struct
- end
-
- def C.rb_iseq_constant_body
- @rb_iseq_constant_body ||= CType::Struct.new(
- "rb_iseq_constant_body", Primitive.cexpr!("SIZEOF(struct rb_iseq_constant_body)"),
- type: [self.rb_iseq_type, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), type)")],
- iseq_size: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), iseq_size)")],
- iseq_encoded: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), iseq_encoded)")],
- param: [CType::Struct.new(
- "", Primitive.cexpr!("SIZEOF(((struct rb_iseq_constant_body *)NULL)->param)"),
- flags: [CType::Struct.new(
- "", Primitive.cexpr!("SIZEOF(((struct rb_iseq_constant_body *)NULL)->param.flags)"),
- has_lead: [CType::BitField.new(1, 0), 0],
- has_opt: [CType::BitField.new(1, 1), 1],
- has_rest: [CType::BitField.new(1, 2), 2],
- has_post: [CType::BitField.new(1, 3), 3],
- has_kw: [CType::BitField.new(1, 4), 4],
- has_kwrest: [CType::BitField.new(1, 5), 5],
- has_block: [CType::BitField.new(1, 6), 6],
- ambiguous_param0: [CType::BitField.new(1, 7), 7],
- accepts_no_kwarg: [CType::BitField.new(1, 0), 8],
- ruby2_keywords: [CType::BitField.new(1, 1), 9],
- anon_rest: [CType::BitField.new(1, 2), 10],
- anon_kwrest: [CType::BitField.new(1, 3), 11],
- use_block: [CType::BitField.new(1, 4), 12],
- ), Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->param, flags)")],
- size: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->param, size)")],
- lead_num: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->param, lead_num)")],
- opt_num: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->param, opt_num)")],
- rest_start: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->param, rest_start)")],
- post_start: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->param, post_start)")],
- post_num: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->param, post_num)")],
- block_start: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->param, block_start)")],
- opt_table: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->param, opt_table)")],
- keyword: [CType::Pointer.new { self.rb_iseq_param_keyword }, Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->param, keyword)")],
- ), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), param)")],
- location: [self.rb_iseq_location_t, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), location)")],
- insns_info: [self.iseq_insn_info, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), insns_info)")],
- local_table: [CType::Pointer.new { self.ID }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), local_table)")],
- catch_table: [CType::Pointer.new { self.iseq_catch_table }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), catch_table)")],
- parent_iseq: [CType::Pointer.new { self.rb_iseq_struct }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), parent_iseq)")],
- local_iseq: [CType::Pointer.new { self.rb_iseq_struct }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), local_iseq)")],
- is_entries: [CType::Pointer.new { self.iseq_inline_storage_entry }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), is_entries)")],
- call_data: [CType::Pointer.new { self.rb_call_data }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), call_data)")],
- variable: [CType::Struct.new(
- "", Primitive.cexpr!("SIZEOF(((struct rb_iseq_constant_body *)NULL)->variable)"),
- flip_count: [self.rb_snum_t, Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->variable, flip_count)")],
- script_lines: [self.VALUE, Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->variable, script_lines)")],
- coverage: [self.VALUE, Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->variable, coverage)")],
- pc2branchindex: [self.VALUE, Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->variable, pc2branchindex)")],
- original_iseq: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF(((struct rb_iseq_constant_body *)NULL)->variable, original_iseq)")],
- ), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), variable)")],
- local_table_size: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), local_table_size)")],
- ic_size: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), ic_size)")],
- ise_size: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), ise_size)")],
- ivc_size: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), ivc_size)")],
- icvarc_size: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), icvarc_size)")],
- ci_size: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), ci_size)")],
- stack_max: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), stack_max)")],
- builtin_attrs: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), builtin_attrs)")],
- prism: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), prism)")],
- mark_bits: [CType::Union.new(
- "", Primitive.cexpr!("SIZEOF(((struct rb_iseq_constant_body *)NULL)->mark_bits)"),
- list: CType::Pointer.new { self.iseq_bits_t },
- single: self.iseq_bits_t,
- ), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), mark_bits)")],
- outer_variables: [CType::Pointer.new { self.rb_id_table }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), outer_variables)")],
- mandatory_only_iseq: [CType::Pointer.new { self.rb_iseq_t }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), mandatory_only_iseq)")],
- jit_entry: [self.rb_jit_func_t, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), jit_entry)")],
- jit_entry_calls: [CType::Immediate.parse("unsigned long"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), jit_entry_calls)")],
- rjit_blocks: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_constant_body *)NULL)), rjit_blocks)"), true],
- )
- end
-
- def C.rb_iseq_location_t
- @rb_iseq_location_t ||= CType::Struct.new(
- "rb_iseq_location_struct", Primitive.cexpr!("SIZEOF(struct rb_iseq_location_struct)"),
- pathobj: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_location_struct *)NULL)), pathobj)"), true],
- base_label: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_location_struct *)NULL)), base_label)"), true],
- label: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_location_struct *)NULL)), label)"), true],
- first_lineno: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_location_struct *)NULL)), first_lineno)")],
- node_id: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_location_struct *)NULL)), node_id)")],
- code_location: [self.rb_code_location_t, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_location_struct *)NULL)), code_location)")],
- )
- end
-
- def C.rb_iseq_param_keyword
- @rb_iseq_param_keyword ||= CType::Struct.new(
- "rb_iseq_param_keyword", Primitive.cexpr!("SIZEOF(struct rb_iseq_param_keyword)"),
- num: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_param_keyword *)NULL)), num)")],
- required_num: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_param_keyword *)NULL)), required_num)")],
- bits_start: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_param_keyword *)NULL)), bits_start)")],
- rest_start: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_param_keyword *)NULL)), rest_start)")],
- table: [CType::Pointer.new { self.ID }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_param_keyword *)NULL)), table)")],
- default_values: [CType::Pointer.new { self.VALUE }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_param_keyword *)NULL)), default_values)")],
- )
- end
-
- def C.rb_iseq_struct
- @rb_iseq_struct ||= CType::Struct.new(
- "rb_iseq_struct", Primitive.cexpr!("SIZEOF(struct rb_iseq_struct)"),
- flags: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_struct *)NULL)), flags)")],
- wrapper: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_struct *)NULL)), wrapper)")],
- body: [CType::Pointer.new { self.rb_iseq_constant_body }, Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_struct *)NULL)), body)")],
- aux: [CType::Union.new(
- "", Primitive.cexpr!("SIZEOF(((struct rb_iseq_struct *)NULL)->aux)"),
- compile_data: CType::Pointer.new { self.iseq_compile_data },
- loader: CType::Struct.new(
- "", Primitive.cexpr!("SIZEOF(((struct rb_iseq_struct *)NULL)->aux.loader)"),
- obj: [self.VALUE, Primitive.cexpr!("OFFSETOF(((struct rb_iseq_struct *)NULL)->aux.loader, obj)")],
- index: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF(((struct rb_iseq_struct *)NULL)->aux.loader, index)")],
- ),
- exec: CType::Struct.new(
- "", Primitive.cexpr!("SIZEOF(((struct rb_iseq_struct *)NULL)->aux.exec)"),
- local_hooks: [CType::Pointer.new { self.rb_hook_list_struct }, Primitive.cexpr!("OFFSETOF(((struct rb_iseq_struct *)NULL)->aux.exec, local_hooks)")],
- global_trace_events: [self.rb_event_flag_t, Primitive.cexpr!("OFFSETOF(((struct rb_iseq_struct *)NULL)->aux.exec, global_trace_events)")],
- ),
- ), Primitive.cexpr!("OFFSETOF((*((struct rb_iseq_struct *)NULL)), aux)")],
- )
- end
-
- def C.rb_iseq_t
- @rb_iseq_t ||= self.rb_iseq_struct
- end
-
- def C.rb_jit_func_t
- @rb_jit_func_t ||= CType::Immediate.parse("void *")
- end
-
- def C.rb_method_attr_t
- @rb_method_attr_t ||= CType::Struct.new(
- "rb_method_attr_struct", Primitive.cexpr!("SIZEOF(struct rb_method_attr_struct)"),
- id: [self.ID, Primitive.cexpr!("OFFSETOF((*((struct rb_method_attr_struct *)NULL)), id)")],
- location: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_method_attr_struct *)NULL)), location)")],
- )
- end
-
- def C.rb_method_bmethod_t
- @rb_method_bmethod_t ||= CType::Struct.new(
- "rb_method_bmethod_struct", Primitive.cexpr!("SIZEOF(struct rb_method_bmethod_struct)"),
- proc: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_method_bmethod_struct *)NULL)), proc)")],
- hooks: [CType::Pointer.new { self.rb_hook_list_struct }, Primitive.cexpr!("OFFSETOF((*((struct rb_method_bmethod_struct *)NULL)), hooks)")],
- defined_ractor: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_method_bmethod_struct *)NULL)), defined_ractor)")],
- )
- end
-
- def C.rb_method_cfunc_t
- @rb_method_cfunc_t ||= CType::Struct.new(
- "rb_method_cfunc_struct", Primitive.cexpr!("SIZEOF(struct rb_method_cfunc_struct)"),
- func: [self.rb_cfunc_t, Primitive.cexpr!("OFFSETOF((*((struct rb_method_cfunc_struct *)NULL)), func)")],
- invoker: [CType::Immediate.parse("void *"), Primitive.cexpr!("OFFSETOF((*((struct rb_method_cfunc_struct *)NULL)), invoker)")],
- argc: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF((*((struct rb_method_cfunc_struct *)NULL)), argc)")],
- )
- end
-
- def C.rb_method_definition_struct
- @rb_method_definition_struct ||= CType::Struct.new(
- "rb_method_definition_struct", Primitive.cexpr!("SIZEOF(struct rb_method_definition_struct)"),
- type: [CType::BitField.new(4, 0), 0],
- iseq_overload: [CType::BitField.new(1, 4), 4],
- no_redef_warning: [CType::BitField.new(1, 5), 5],
- aliased: [CType::BitField.new(1, 6), 6],
- reference_count: [CType::BitField.new(28, 0), 32],
- body: [CType::Union.new(
- "", Primitive.cexpr!("SIZEOF(((struct rb_method_definition_struct *)NULL)->body)"),
- iseq: self.rb_method_iseq_t,
- cfunc: self.rb_method_cfunc_t,
- attr: self.rb_method_attr_t,
- alias: self.rb_method_alias_t,
- refined: self.rb_method_refined_t,
- bmethod: self.rb_method_bmethod_t,
- optimized: self.rb_method_optimized_t,
- ), Primitive.cexpr!("OFFSETOF((*((struct rb_method_definition_struct *)NULL)), body)")],
- original_id: [self.ID, Primitive.cexpr!("OFFSETOF((*((struct rb_method_definition_struct *)NULL)), original_id)")],
- method_serial: [CType::Immediate.parse("uintptr_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_method_definition_struct *)NULL)), method_serial)")],
- )
- end
-
- def C.rb_method_entry_t
- @rb_method_entry_t ||= CType::Struct.new(
- "rb_method_entry_struct", Primitive.cexpr!("SIZEOF(struct rb_method_entry_struct)"),
- flags: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_method_entry_struct *)NULL)), flags)")],
- defined_class: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_method_entry_struct *)NULL)), defined_class)")],
- def: [CType::Pointer.new { self.rb_method_definition_struct }, Primitive.cexpr!("OFFSETOF((*((struct rb_method_entry_struct *)NULL)), def)")],
- called_id: [self.ID, Primitive.cexpr!("OFFSETOF((*((struct rb_method_entry_struct *)NULL)), called_id)")],
- owner: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_method_entry_struct *)NULL)), owner)")],
- )
- end
-
- def C.rb_method_iseq_t
- @rb_method_iseq_t ||= CType::Struct.new(
- "rb_method_iseq_struct", Primitive.cexpr!("SIZEOF(struct rb_method_iseq_struct)"),
- iseqptr: [CType::Pointer.new { self.rb_iseq_t }, Primitive.cexpr!("OFFSETOF((*((struct rb_method_iseq_struct *)NULL)), iseqptr)")],
- cref: [CType::Pointer.new { self.rb_cref_t }, Primitive.cexpr!("OFFSETOF((*((struct rb_method_iseq_struct *)NULL)), cref)")],
- )
- end
-
- def C.rb_method_optimized_t
- @rb_method_optimized_t ||= CType::Struct.new(
- "rb_method_optimized", Primitive.cexpr!("SIZEOF(struct rb_method_optimized)"),
- type: [self.method_optimized_type, Primitive.cexpr!("OFFSETOF((*((struct rb_method_optimized *)NULL)), type)")],
- index: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_method_optimized *)NULL)), index)")],
- )
- end
-
- def C.rb_method_type_t
- @rb_method_type_t ||= CType::Immediate.parse("int")
- end
-
- def C.rb_proc_t
- @rb_proc_t ||= CType::Struct.new(
- "", Primitive.cexpr!("SIZEOF(rb_proc_t)"),
- block: [self.rb_block, Primitive.cexpr!("OFFSETOF((*((rb_proc_t *)NULL)), block)")],
- )
- end
-
- def C.rb_rjit_options
- @rb_rjit_options ||= CType::Struct.new(
- "rb_rjit_options", Primitive.cexpr!("SIZEOF(struct rb_rjit_options)"),
- on: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_options *)NULL)), on)")],
- exec_mem_size: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_options *)NULL)), exec_mem_size)")],
- call_threshold: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_options *)NULL)), call_threshold)")],
- stats: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_options *)NULL)), stats)")],
- disable: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_options *)NULL)), disable)")],
- trace: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_options *)NULL)), trace)")],
- trace_exits: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_options *)NULL)), trace_exits)")],
- dump_disasm: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_options *)NULL)), dump_disasm)")],
- verify_ctx: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_options *)NULL)), verify_ctx)")],
- )
- end
-
- def C.rb_rjit_runtime_counters
- @rb_rjit_runtime_counters ||= CType::Struct.new(
- "rb_rjit_runtime_counters", Primitive.cexpr!("SIZEOF(struct rb_rjit_runtime_counters)"),
- rjit_insns_count: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), rjit_insns_count)")],
- send_args_splat_kw_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_args_splat_kw_splat)")],
- send_args_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_args_splat)")],
- send_args_splat_not_array: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_args_splat_not_array)")],
- send_args_splat_length_not_equal: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_args_splat_length_not_equal)")],
- send_args_splat_cfunc_var_args: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_args_splat_cfunc_var_args)")],
- send_args_splat_arity_error: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_args_splat_arity_error)")],
- send_args_splat_ruby2_hash: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_args_splat_ruby2_hash)")],
- send_args_splat_cfunc_zuper: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_args_splat_cfunc_zuper)")],
- send_args_splat_cfunc_ruby2_keywords: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_args_splat_cfunc_ruby2_keywords)")],
- send_kw_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_kw_splat)")],
- send_kwarg: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_kwarg)")],
- send_klass_megamorphic: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_klass_megamorphic)")],
- send_missing_cme: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_missing_cme)")],
- send_private: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_private)")],
- send_protected_check_failed: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_protected_check_failed)")],
- send_tailcall: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_tailcall)")],
- send_notimplemented: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_notimplemented)")],
- send_missing: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_missing)")],
- send_bmethod: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_bmethod)")],
- send_alias: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_alias)")],
- send_undef: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_undef)")],
- send_zsuper: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_zsuper)")],
- send_refined: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_refined)")],
- send_stackoverflow: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_stackoverflow)")],
- send_arity: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_arity)")],
- send_c_tracing: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_c_tracing)")],
- send_is_a_class_mismatch: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_is_a_class_mismatch)")],
- send_instance_of_class_mismatch: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_instance_of_class_mismatch)")],
- send_keywords: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_keywords)")],
- send_blockiseq: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_blockiseq)")],
- send_block_handler: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_block_handler)")],
- send_block_setup: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_block_setup)")],
- send_block_not_nil: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_block_not_nil)")],
- send_block_not_proxy: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_block_not_proxy)")],
- send_block_arg: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_block_arg)")],
- send_iseq_kwparam: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_kwparam)")],
- send_iseq_accepts_no_kwarg: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_accepts_no_kwarg)")],
- send_iseq_has_opt: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_has_opt)")],
- send_iseq_has_kwrest: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_has_kwrest)")],
- send_iseq_ruby2_keywords: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_ruby2_keywords)")],
- send_iseq_has_rest_and_captured: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_has_rest_and_captured)")],
- send_iseq_has_rest_and_kw_supplied: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_has_rest_and_kw_supplied)")],
- send_iseq_has_no_kw: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_has_no_kw)")],
- send_iseq_zsuper: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_zsuper)")],
- send_iseq_materialized_block: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_materialized_block)")],
- send_iseq_has_rest: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_has_rest)")],
- send_iseq_block_arg0_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_block_arg0_splat)")],
- send_iseq_kw_call: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_kw_call)")],
- send_iseq_kw_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_kw_splat)")],
- send_iseq_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_splat)")],
- send_iseq_has_rest_and_optional: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_has_rest_and_optional)")],
- send_iseq_arity_error: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_arity_error)")],
- send_iseq_missing_optional_kw: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_missing_optional_kw)")],
- send_iseq_too_many_kwargs: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_too_many_kwargs)")],
- send_iseq_kwargs_mismatch: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_kwargs_mismatch)")],
- send_iseq_splat_with_kw: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_splat_with_kw)")],
- send_iseq_splat_arity_error: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_splat_arity_error)")],
- send_iseq_has_rest_and_splat_not_equal: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_iseq_has_rest_and_splat_not_equal)")],
- send_cfunc_variadic: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_cfunc_variadic)")],
- send_cfunc_too_many_args: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_cfunc_too_many_args)")],
- send_cfunc_ruby_array_varg: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_cfunc_ruby_array_varg)")],
- send_cfunc_splat_with_kw: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_cfunc_splat_with_kw)")],
- send_cfunc_tracing: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_cfunc_tracing)")],
- send_cfunc_argc_mismatch: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_cfunc_argc_mismatch)")],
- send_cfunc_toomany_args: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_cfunc_toomany_args)")],
- send_attrset_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_attrset_splat)")],
- send_attrset_kwarg: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_attrset_kwarg)")],
- send_attrset_method: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_attrset_method)")],
- send_ivar_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_ivar_splat)")],
- send_ivar_opt_send: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_ivar_opt_send)")],
- send_optimized_send_no_args: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_optimized_send_no_args)")],
- send_optimized_send_not_sym_or_str: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_optimized_send_not_sym_or_str)")],
- send_optimized_send_mid_class_changed: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_optimized_send_mid_class_changed)")],
- send_optimized_send_mid_id_changed: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_optimized_send_mid_id_changed)")],
- send_optimized_send_null_mid: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_optimized_send_null_mid)")],
- send_optimized_send_send: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_optimized_send_send)")],
- send_optimized_call_block: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_optimized_call_block)")],
- send_optimized_call_kwarg: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_optimized_call_kwarg)")],
- send_optimized_call_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_optimized_call_splat)")],
- send_optimized_struct_aref_error: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_optimized_struct_aref_error)")],
- send_optimized_block_call: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_optimized_block_call)")],
- send_optimized_struct_aset: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_optimized_struct_aset)")],
- send_bmethod_not_iseq: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_bmethod_not_iseq)")],
- send_bmethod_blockarg: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), send_bmethod_blockarg)")],
- invokesuper_me_changed: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), invokesuper_me_changed)")],
- invokesuper_block: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), invokesuper_block)")],
- invokeblock_none: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), invokeblock_none)")],
- invokeblock_symbol: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), invokeblock_symbol)")],
- invokeblock_proc: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), invokeblock_proc)")],
- invokeblock_tag_changed: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), invokeblock_tag_changed)")],
- invokeblock_iseq_block_changed: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), invokeblock_iseq_block_changed)")],
- invokeblock_iseq_arity: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), invokeblock_iseq_arity)")],
- invokeblock_iseq_arg0_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), invokeblock_iseq_arg0_splat)")],
- invokeblock_ifunc_args_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), invokeblock_ifunc_args_splat)")],
- invokeblock_ifunc_kw_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), invokeblock_ifunc_kw_splat)")],
- invokeblock_iseq_arg0_args_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), invokeblock_iseq_arg0_args_splat)")],
- invokeblock_iseq_arg0_has_kw: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), invokeblock_iseq_arg0_has_kw)")],
- getivar_megamorphic: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), getivar_megamorphic)")],
- getivar_not_heap: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), getivar_not_heap)")],
- getivar_special_const: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), getivar_special_const)")],
- getivar_too_complex: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), getivar_too_complex)")],
- optaref_arg_not_fixnum: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), optaref_arg_not_fixnum)")],
- optaref_argc_not_one: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), optaref_argc_not_one)")],
- optaref_recv_not_array: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), optaref_recv_not_array)")],
- optaref_recv_not_hash: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), optaref_recv_not_hash)")],
- optaref_send: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), optaref_send)")],
- optgetconst_not_cached: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), optgetconst_not_cached)")],
- optgetconst_cref: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), optgetconst_cref)")],
- optgetconst_cache_miss: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), optgetconst_cache_miss)")],
- setivar_frozen: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), setivar_frozen)")],
- setivar_not_heap: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), setivar_not_heap)")],
- setivar_megamorphic: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), setivar_megamorphic)")],
- setivar_too_complex: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), setivar_too_complex)")],
- expandarray_splat: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), expandarray_splat)")],
- expandarray_postarg: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), expandarray_postarg)")],
- expandarray_not_array: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), expandarray_not_array)")],
- expandarray_rhs_too_small: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), expandarray_rhs_too_small)")],
- getblockpp_block_param_modified: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), getblockpp_block_param_modified)")],
- getblockpp_block_handler_none: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), getblockpp_block_handler_none)")],
- getblockpp_not_gc_guarded: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), getblockpp_not_gc_guarded)")],
- getblockpp_not_iseq_block: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), getblockpp_not_iseq_block)")],
- compiled_block_count: [CType::Immediate.parse("size_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_rjit_runtime_counters *)NULL)), compiled_block_count)")],
- )
- end
-
- def C.rb_serial_t
- @rb_serial_t ||= CType::Immediate.parse("unsigned long long")
- end
-
- def C.rb_shape
- @rb_shape ||= CType::Struct.new(
- "rb_shape", Primitive.cexpr!("SIZEOF(struct rb_shape)"),
- edges: [CType::Pointer.new { self.rb_id_table }, Primitive.cexpr!("OFFSETOF((*((struct rb_shape *)NULL)), edges)")],
- edge_name: [self.ID, Primitive.cexpr!("OFFSETOF((*((struct rb_shape *)NULL)), edge_name)")],
- next_iv_index: [self.attr_index_t, Primitive.cexpr!("OFFSETOF((*((struct rb_shape *)NULL)), next_iv_index)")],
- capacity: [CType::Immediate.parse("uint32_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_shape *)NULL)), capacity)")],
- type: [CType::Immediate.parse("uint8_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_shape *)NULL)), type)")],
- size_pool_index: [CType::Immediate.parse("uint8_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_shape *)NULL)), size_pool_index)")],
- parent_id: [self.shape_id_t, Primitive.cexpr!("OFFSETOF((*((struct rb_shape *)NULL)), parent_id)")],
- ancestor_index: [CType::Pointer.new { self.redblack_node_t }, Primitive.cexpr!("OFFSETOF((*((struct rb_shape *)NULL)), ancestor_index)")],
- )
- end
-
- def C.rb_shape_t
- @rb_shape_t ||= self.rb_shape
- end
-
- def C.rb_thread_struct
- @rb_thread_struct ||= CType::Struct.new(
- "rb_thread_struct", Primitive.cexpr!("SIZEOF(struct rb_thread_struct)"),
- lt_node: [self.ccan_list_node, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), lt_node)")],
- self: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), self)")],
- ractor: [CType::Pointer.new { self.rb_ractor_t }, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), ractor)")],
- vm: [CType::Pointer.new { self.rb_vm_t }, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), vm)")],
- nt: [CType::Pointer.new { self.rb_native_thread }, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), nt)")],
- ec: [CType::Pointer.new { self.rb_execution_context_t }, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), ec)")],
- sched: [self.rb_thread_sched_item, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), sched)")],
- mn_schedulable: [self._Bool, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), mn_schedulable)")],
- serial: [self.rb_atomic_t, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), serial)")],
- last_status: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), last_status)")],
- calling: [CType::Pointer.new { self.rb_calling_info }, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), calling)")],
- top_self: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), top_self)")],
- top_wrapper: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), top_wrapper)")],
- priority: [CType::Immediate.parse("int8_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), priority)")],
- running_time_us: [CType::Immediate.parse("uint32_t"), Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), running_time_us)")],
- blocking_region_buffer: [CType::Pointer.new { CType::Immediate.parse("void") }, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), blocking_region_buffer)")],
- thgroup: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), thgroup)")],
- value: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), value)")],
- pending_interrupt_queue: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), pending_interrupt_queue)")],
- pending_interrupt_mask_stack: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), pending_interrupt_mask_stack)")],
- interrupt_lock: [self.rb_nativethread_lock_t, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), interrupt_lock)")],
- unblock: [self.rb_unblock_callback, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), unblock)")],
- locking_mutex: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), locking_mutex)")],
- keeping_mutexes: [CType::Pointer.new { self.rb_mutex_struct }, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), keeping_mutexes)")],
- join_list: [CType::Pointer.new { self.rb_waiting_list }, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), join_list)")],
- invoke_arg: [CType::Union.new(
- "", Primitive.cexpr!("SIZEOF(((struct rb_thread_struct *)NULL)->invoke_arg)"),
- proc: CType::Struct.new(
- "", Primitive.cexpr!("SIZEOF(((struct rb_thread_struct *)NULL)->invoke_arg.proc)"),
- proc: [self.VALUE, Primitive.cexpr!("OFFSETOF(((struct rb_thread_struct *)NULL)->invoke_arg.proc, proc)")],
- args: [self.VALUE, Primitive.cexpr!("OFFSETOF(((struct rb_thread_struct *)NULL)->invoke_arg.proc, args)")],
- kw_splat: [CType::Immediate.parse("int"), Primitive.cexpr!("OFFSETOF(((struct rb_thread_struct *)NULL)->invoke_arg.proc, kw_splat)")],
- ),
- func: CType::Struct.new(
- "", Primitive.cexpr!("SIZEOF(((struct rb_thread_struct *)NULL)->invoke_arg.func)"),
- func: [CType::Immediate.parse("void *"), Primitive.cexpr!("OFFSETOF(((struct rb_thread_struct *)NULL)->invoke_arg.func, func)")],
- arg: [CType::Pointer.new { CType::Immediate.parse("void") }, Primitive.cexpr!("OFFSETOF(((struct rb_thread_struct *)NULL)->invoke_arg.func, arg)")],
- ),
- ), Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), invoke_arg)")],
- invoke_type: [self.thread_invoke_type, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), invoke_type)")],
- stat_insn_usage: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), stat_insn_usage)")],
- root_fiber: [CType::Pointer.new { self.rb_fiber_t }, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), root_fiber)")],
- scheduler: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), scheduler)")],
- blocking: [CType::Immediate.parse("unsigned int"), Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), blocking)")],
- name: [self.VALUE, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), name)")],
- specific_storage: [CType::Pointer.new { CType::Pointer.new { CType::Immediate.parse("void") } }, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), specific_storage)")],
- ext_config: [self.rb_ext_config, Primitive.cexpr!("OFFSETOF((*((struct rb_thread_struct *)NULL)), ext_config)")],
- )
- end
-
- def C.VALUE
- @VALUE ||= CType::Immediate.find(
- Primitive.cexpr!("SIZEOF(VALUE)"),
- Primitive.cexpr!("SIGNED_TYPE_P(VALUE)"),
- )
- end
-
- def C.shape_id_t
- @shape_id_t ||= CType::Immediate.find(
- Primitive.cexpr!("SIZEOF(shape_id_t)"),
- Primitive.cexpr!("SIGNED_TYPE_P(shape_id_t)"),
- )
- end
-
- def C.rb_id_table
- CType::Stub.new(:rb_id_table)
- end
-
- def C.vm_call_handler
- CType::Stub.new(:vm_call_handler)
- end
-
- def C.method_missing_reason
- CType::Stub.new(:method_missing_reason)
- end
-
- def C.vm_ifunc
- CType::Stub.new(:vm_ifunc)
- end
-
- def C.rb_cref_struct
- CType::Stub.new(:rb_cref_struct)
- end
-
- def C.rb_scope_visibility_t
- CType::Stub.new(:rb_scope_visibility_t)
- end
-
- def C.rb_vm_tag
- CType::Stub.new(:rb_vm_tag)
- end
-
- def C.rb_atomic_t
- CType::Stub.new(:rb_atomic_t)
- end
-
- def C.rb_fiber_t
- CType::Stub.new(:rb_fiber_t)
- end
-
- def C.rb_ensure_list_t
- CType::Stub.new(:rb_ensure_list_t)
- end
-
- def C.rb_trace_arg_struct
- CType::Stub.new(:rb_trace_arg_struct)
- end
-
- def C.rb_iseq_type
- CType::Stub.new(:rb_iseq_type)
- end
-
- def C.iseq_insn_info
- CType::Stub.new(:iseq_insn_info)
- end
-
- def C.iseq_catch_table
- CType::Stub.new(:iseq_catch_table)
- end
-
- def C.rb_snum_t
- CType::Stub.new(:rb_snum_t)
- end
-
- def C._Bool
- CType::Bool.new
- end
-
- def C.iseq_bits_t
- CType::Stub.new(:iseq_bits_t)
- end
-
- def C.rb_code_location_t
- CType::Stub.new(:rb_code_location_t)
- end
-
- def C.iseq_compile_data
- CType::Stub.new(:iseq_compile_data)
- end
-
- def C.rb_hook_list_struct
- CType::Stub.new(:rb_hook_list_struct)
- end
-
- def C.rb_event_flag_t
- CType::Stub.new(:rb_event_flag_t)
- end
-
- def C.rb_method_alias_t
- CType::Stub.new(:rb_method_alias_t)
- end
-
- def C.rb_method_refined_t
- CType::Stub.new(:rb_method_refined_t)
- end
-
- def C.redblack_node_t
- CType::Stub.new(:redblack_node_t)
- end
-
- def C.ccan_list_node
- CType::Stub.new(:ccan_list_node)
- end
-
- def C.rb_ractor_t
- CType::Stub.new(:rb_ractor_t)
- end
-
- def C.rb_vm_t
- CType::Stub.new(:rb_vm_t)
- end
-
- def C.rb_native_thread
- CType::Stub.new(:rb_native_thread)
- end
-
- def C.rb_thread_sched_item
- CType::Stub.new(:rb_thread_sched_item)
- end
-
- def C.rb_calling_info
- CType::Stub.new(:rb_calling_info)
- end
-
- def C.rb_nativethread_lock_t
- CType::Stub.new(:rb_nativethread_lock_t)
- end
-
- def C.rb_unblock_callback
- CType::Stub.new(:rb_unblock_callback)
- end
-
- def C.rb_mutex_struct
- CType::Stub.new(:rb_mutex_struct)
- end
-
- def C.rb_waiting_list
- CType::Stub.new(:rb_waiting_list)
- end
-
- def C.thread_invoke_type
- CType::Stub.new(:thread_invoke_type)
- end
-
- def C.rb_ext_config
- CType::Stub.new(:rb_ext_config)
- end
-
- ### RJIT bindgen end ###
-end if Primitive.rjit_enabled_p
diff --git a/ruby-runner.c b/ruby-runner.c
index 48acf4396e..295ef47cc3 100644
--- a/ruby-runner.c
+++ b/ruby-runner.c
@@ -60,6 +60,9 @@ insert_env_path(const char *envname, const char *paths, size_t size, int prepend
setenv(envname, env, 1);
}
+#define insert_env_path_lit(env, path, prep) \
+ insert_env_path(env, path, sizeof(path), prep)
+
#define EXTOUT_DIR BUILDDIR"/"EXTOUT
int
main(int argc, char **argv)
@@ -81,6 +84,12 @@ main(int argc, char **argv)
insert_env_path(LIBPATHENV, builddir, dirsize, 1);
insert_env_path("RUBYLIB", rubylib, sizeof(rubylib), 0);
+ if (!getenv("GEM_PATH")) {
+ insert_env_path_lit("GEM_PATH", ABS_SRCDIR"/.bundle", 1);
+ insert_env_path_lit("GEM_PATH", BUILDDIR"/.bundle", 1);
+ setenv("GEM_HOME", BUILDDIR"/.bundle", 0);
+ }
+
if (!(p = strrchr(arg0, '/'))) p = arg0; else p++;
if (strlen(p) < namesize - 1) {
argv[0] = malloc(p - arg0 + namesize);
diff --git a/ruby.c b/ruby.c
index a8de48d2a6..28f43176d6 100644
--- a/ruby.c
+++ b/ruby.c
@@ -105,9 +105,9 @@ void rb_warning_category_update(unsigned int mask, unsigned int bits);
SEP \
X(frozen_string_literal) \
SEP \
- X(rjit) \
- SEP \
X(yjit) \
+ SEP \
+ X(zjit) \
/* END OF FEATURES */
#define EACH_DEBUG_FEATURES(X, SEP) \
X(frozen_string_literal) \
@@ -117,13 +117,14 @@ void rb_warning_category_update(unsigned int mask, unsigned int bits);
#define DEFINE_DEBUG_FEATURE(bit) feature_debug_##bit
enum feature_flag_bits {
EACH_FEATURES(DEFINE_FEATURE, COMMA),
+ DEFINE_FEATURE(frozen_string_literal_set),
feature_debug_flag_first,
-#if defined(RJIT_FORCE_ENABLE) || !USE_YJIT
- DEFINE_FEATURE(jit) = feature_rjit,
+#if !USE_YJIT && USE_ZJIT
+ DEFINE_FEATURE(jit) = feature_zjit,
#else
DEFINE_FEATURE(jit) = feature_yjit,
#endif
- feature_jit_mask = FEATURE_BIT(rjit) | FEATURE_BIT(yjit),
+ feature_jit_mask = FEATURE_BIT(yjit) | FEATURE_BIT(zjit),
feature_debug_flag_begin = feature_debug_flag_first - 1,
EACH_DEBUG_FEATURES(DEFINE_DEBUG_FEATURE, COMMA),
@@ -189,6 +190,7 @@ enum {
COMPILATION_FEATURES = (
0
| FEATURE_BIT(frozen_string_literal)
+ | FEATURE_BIT(frozen_string_literal_set)
| FEATURE_BIT(debug_frozen_string_literal)
),
DEFAULT_FEATURES = (
@@ -197,6 +199,7 @@ enum {
& ~FEATURE_BIT(gems)
#endif
& ~FEATURE_BIT(frozen_string_literal)
+ & ~FEATURE_BIT(frozen_string_literal_set)
& ~feature_jit_mask
)
};
@@ -214,9 +217,7 @@ cmdline_options_init(ruby_cmdline_options_t *opt)
opt->ext.enc.index = -1;
opt->intern.enc.index = -1;
opt->features.set = DEFAULT_FEATURES;
-#ifdef RJIT_FORCE_ENABLE /* to use with: ./configure cppflags="-DRJIT_FORCE_ENABLE" */
- opt->features.set |= FEATURE_BIT(rjit);
-#elif defined(YJIT_FORCE_ENABLE)
+#if defined(YJIT_FORCE_ENABLE)
opt->features.set |= FEATURE_BIT(yjit);
#endif
opt->dump |= DUMP_BIT(opt_optimize);
@@ -304,15 +305,17 @@ ruby_show_usage_line(const char *name, const char *secondary, const char *descri
description, help, highlight, width, columns);
}
+RUBY_EXTERN const char ruby_api_version_name[];
+
static void
usage(const char *name, int help, int highlight, int columns)
{
#define M(shortopt, longopt, desc) RUBY_OPT_MESSAGE(shortopt, longopt, desc)
#if USE_YJIT
-# define PLATFORM_JIT_OPTION "--yjit"
-#else
-# define PLATFORM_JIT_OPTION "--rjit (experimental)"
+# define DEFAULT_JIT_OPTION "--yjit"
+#elif USE_ZJIT
+# define DEFAULT_JIT_OPTION "--zjit"
#endif
/* This message really ought to be max 23 lines.
@@ -323,14 +326,14 @@ usage(const char *name, int help, int highlight, int columns)
M("-a", "", "Split each input line ($_) into fields ($F)."),
M("-c", "", "Check syntax (no execution)."),
M("-Cdirpath", "", "Execute program in specified directory."),
- M("-d", ", --debug", "Set debugging flag ($DEBUG) to true."),
+ M("-d", ", --debug", "Set debugging flag ($DEBUG) and $VERBOSE to true."),
M("-e 'code'", "", "Execute given Ruby code; multiple -e allowed."),
M("-Eex[:in]", ", --encoding=ex[:in]", "Set default external and internal encodings."),
M("-Fpattern", "", "Set input field separator ($;); used with -a."),
M("-i[extension]", "", "Set ARGF in-place mode;\n"
"create backup files with given extension."),
- M("-Idirpath", "", "Add specified directory to load paths ($LOAD_PATH);\n"
- "multiple -I allowed."),
+ M("-Idirpath", "", "Prepend specified directory to load paths ($LOAD_PATH);\n"
+ "relative paths are expanded; multiple -I are allowed."),
M("-l", "", "Set output record separator ($\\) to $/;\n"
"used for line-oriented output."),
M("-n", "", "Run program in gets loop."),
@@ -343,16 +346,18 @@ usage(const char *name, int help, int highlight, int columns)
M("-W[level=2|:category]", "", "Set warning flag ($-W):\n"
"0 for silent; 1 for moderate; 2 for verbose."),
M("-x[dirpath]", "", "Execute Ruby code starting from a #!ruby line."),
- M("--jit", "", "Enable JIT for the platform; same as " PLATFORM_JIT_OPTION "."),
+#if USE_YJIT || USE_ZJIT
+ M("--jit", "", "Enable the default JIT for the build; same as " DEFAULT_JIT_OPTION "."),
+#endif
#if USE_YJIT
M("--yjit", "", "Enable in-process JIT compiler."),
#endif
-#if USE_RJIT
- M("--rjit", "", "Enable pure-Ruby JIT compiler (experimental)."),
+#if USE_ZJIT
+ M("--zjit", "", "Enable method-based JIT compiler."),
#endif
M("-h", "", "Print this help message; use --help for longer message."),
};
- STATIC_ASSERT(usage_msg_size, numberof(usage_msg) < 25);
+ STATIC_ASSERT(usage_msg_size, numberof(usage_msg) < 26);
static const struct ruby_opt_message help_msg[] = {
M("--backtrace-limit=num", "", "Set backtrace limit."),
@@ -375,7 +380,7 @@ usage(const char *name, int help, int highlight, int columns)
M("parsetree", "", "Abstract syntax tree (AST)."),
M("-optimize", "", "Disable optimization (affects insns)."),
M("+error-tolerant", "", "Error-tolerant parsing (affects yydebug, parsetree)."),
- M("+comment", "", "Add comments to AST (affects parsetree)."),
+ M("+comment", "", "Add comments to AST (affects parsetree with --parser=parse.y)."),
};
static const struct ruby_opt_message features[] = {
M("gems", "", "Rubygems (only for debugging, default: "DEFAULT_RUBYGEMS_ENABLED")."),
@@ -387,18 +392,16 @@ usage(const char *name, int help, int highlight, int columns)
#if USE_YJIT
M("yjit", "", "In-process JIT compiler (default: disabled)."),
#endif
-#if USE_RJIT
- M("rjit", "", "Pure-Ruby JIT compiler (experimental, default: disabled)."),
+#if USE_ZJIT
+ M("zjit", "", "Method-based JIT compiler (default: disabled)."),
#endif
};
static const struct ruby_opt_message warn_categories[] = {
M("deprecated", "", "Deprecated features."),
M("experimental", "", "Experimental features."),
M("performance", "", "Performance issues."),
+ M("strict_unused_block", "", "Warning unused block strictly"),
};
-#if USE_RJIT
- extern const struct ruby_opt_message rb_rjit_option_messages[];
-#endif
int i;
const char *sb = highlight ? esc_standout+1 : esc_none;
const char *se = highlight ? esc_reset : esc_none;
@@ -429,10 +432,10 @@ usage(const char *name, int help, int highlight, int columns)
printf("%s""YJIT options:%s\n", sb, se);
rb_yjit_show_usage(help, highlight, w, columns);
#endif
-#if USE_RJIT
- printf("%s""RJIT options (experimental):%s\n", sb, se);
- for (i = 0; rb_rjit_option_messages[i].str; ++i)
- SHOW(rb_rjit_option_messages[i]);
+#if USE_ZJIT
+ printf("%s""ZJIT options:%s\n", sb, se);
+ extern void rb_zjit_show_usage(int help, int highlight, unsigned int width, int columns);
+ rb_zjit_show_usage(help, highlight, w, columns);
#endif
}
@@ -443,7 +446,7 @@ ruby_push_include(const char *path, VALUE (*filter)(VALUE))
{
const char sep = PATH_SEP_CHAR;
const char *p, *s;
- VALUE load_path = GET_VM()->load_path;
+ VALUE load_path = rb_root_box()->load_path;
#ifdef __CYGWIN__
char rubylib[FILENAME_MAX];
VALUE buf = 0;
@@ -556,6 +559,8 @@ translit_char_bin(char *p, int from, int to)
#endif
#ifdef _WIN32
+# undef chdir
+# define chdir rb_w32_uchdir
# define UTF8_PATH 1
#endif
@@ -746,7 +751,7 @@ ruby_init_loadpath(void)
rb_gc_register_address(&ruby_archlibdir_path);
ruby_archlibdir_path = archlibdir;
- load_path = GET_VM()->load_path;
+ load_path = rb_root_box()->load_path;
ruby_push_include(getenv("RUBYLIB"), identical_path);
@@ -758,8 +763,6 @@ ruby_init_loadpath(void)
rb_ary_push(load_path, path);
paths += len + 1;
}
-
- rb_const_set(rb_cObject, rb_intern_const("TMP_RUBY_PREFIX"), ruby_prefix_path);
}
@@ -910,7 +913,9 @@ moreswitches(const char *s, ruby_cmdline_options_t *opt, int envopt)
argc = RSTRING_LEN(argary) / sizeof(ap);
ap = 0;
rb_str_cat(argary, (char *)&ap, sizeof(ap));
- argv = ptr = ALLOC_N(char *, argc);
+
+ VALUE ptr_obj;
+ argv = ptr = RB_ALLOCV_N(char *, ptr_obj, argc);
MEMMOVE(argv, RSTRING_PTR(argary), char *, argc);
while ((i = proc_options(argc, argv, opt, envopt)) > 1 && envopt && (argc -= i) > 0) {
@@ -942,7 +947,8 @@ moreswitches(const char *s, ruby_cmdline_options_t *opt, int envopt)
opt->crash_report = crash_report;
}
- ruby_xfree(ptr);
+ RB_ALLOCV_END(ptr_obj);
+
/* get rid of GC */
rb_str_resize(argary, 0);
rb_str_resize(argstr, 0);
@@ -1005,7 +1011,7 @@ feature_option(const char *str, int len, void *arg, const unsigned int enable)
goto found;
}
if (NAME_MATCH_P("all", str, len)) {
- // YJIT and RJIT cannot be enabled at the same time. We enable only one for --enable=all.
+ // We enable only one JIT for --enable=all.
mask &= ~feature_jit_mask | FEATURE_BIT(jit);
goto found;
}
@@ -1033,6 +1039,9 @@ feature_option(const char *str, int len, void *arg, const unsigned int enable)
found:
FEATURE_SET_TO(*argp, mask, (mask & enable));
+ if (NAME_MATCH_P("frozen_string_literal", str, len)) {
+ FEATURE_SET_TO(*argp, FEATURE_BIT(frozen_string_literal_set), FEATURE_BIT(frozen_string_literal_set));
+ }
return;
}
@@ -1194,6 +1203,19 @@ setup_yjit_options(const char *s)
}
#endif
+#if USE_ZJIT
+static void
+setup_zjit_options(const char *s)
+{
+ // The option parsing is done in zjit/src/options.rs
+ extern bool rb_zjit_parse_option(const char *s);
+
+ if (!rb_zjit_parse_option(s)) {
+ rb_raise(rb_eRuntimeError, "invalid ZJIT option '%s' (--help will show valid zjit options)", s);
+ }
+}
+#endif
+
/*
* Following proc_*_option functions are tree kinds:
*
@@ -1225,6 +1247,9 @@ proc_W_option(ruby_cmdline_options_t *opt, const char *s, int *warning)
else if (NAME_MATCH_P("performance", s, len)) {
bits = 1U << RB_WARN_CATEGORY_PERFORMANCE;
}
+ else if (NAME_MATCH_P("strict_unused_block", s, len)) {
+ bits = 1U << RB_WARN_CATEGORY_STRICT_UNUSED_BLOCK;
+ }
else {
rb_warn("unknown warning category: '%s'", s);
}
@@ -1335,11 +1360,11 @@ proc_0_option(ruby_cmdline_options_t *opt, const char *s)
if (v > 0377)
rb_rs = Qnil;
else if (v == 0 && numlen >= 2) {
- rb_rs = rb_str_new2("");
+ rb_rs = rb_fstring_lit("");
}
else {
c = v & 0xff;
- rb_rs = rb_str_new(&c, 1);
+ rb_rs = rb_str_freeze(rb_str_new(&c, 1));
}
return s;
}
@@ -1422,10 +1447,10 @@ proc_long_options(ruby_cmdline_options_t *opt, const char *s, long argc, char **
}
else if (is_option_with_arg("parser", Qfalse, Qtrue)) {
if (strcmp("prism", s) == 0) {
- (*rb_ruby_prism_ptr()) = true;
+ rb_ruby_default_parser_set(RB_DEFAULT_PARSER_PRISM);
}
else if (strcmp("parse.y", s) == 0) {
- // default behavior
+ rb_ruby_default_parser_set(RB_DEFAULT_PARSER_PARSE_Y);
}
else {
rb_raise(rb_eRuntimeError, "unknown parser %s", s);
@@ -1445,21 +1470,12 @@ proc_long_options(ruby_cmdline_options_t *opt, const char *s, long argc, char **
ruby_verbose = Qtrue;
}
else if (strcmp("jit", s) == 0) {
-#if USE_YJIT || USE_RJIT
+#if USE_YJIT || USE_ZJIT
FEATURE_SET(opt->features, FEATURE_BIT(jit));
#else
rb_warn("Ruby was built without JIT support");
#endif
}
- else if (is_option_with_optarg("rjit", '-', true, false, false)) {
-#if USE_RJIT
- extern void rb_rjit_setup_options(const char *s, struct rb_rjit_options *rjit_opt);
- FEATURE_SET(opt->features, FEATURE_BIT(rjit));
- rb_rjit_setup_options(s, &opt->rjit);
-#else
- rb_warn("RJIT support is disabled.");
-#endif
- }
else if (is_option_with_optarg("yjit", '-', true, false, false)) {
#if USE_YJIT
FEATURE_SET(opt->features, FEATURE_BIT(yjit));
@@ -1469,6 +1485,15 @@ proc_long_options(ruby_cmdline_options_t *opt, const char *s, long argc, char **
" You may need to install rustc to build Ruby with YJIT.");
#endif
}
+ else if (is_option_with_optarg("zjit", '-', true, false, false)) {
+#if USE_ZJIT
+ FEATURE_SET(opt->features, FEATURE_BIT(zjit));
+ setup_zjit_options(s);
+#else
+ rb_warn("Ruby was built without ZJIT support."
+ " You may need to install rustc to build Ruby with ZJIT.");
+#endif
+ }
else if (strcmp("yydebug", s) == 0) {
if (envopt) goto noenvopt_long;
opt->dump |= DUMP_BIT(yydebug);
@@ -1709,11 +1734,27 @@ proc_options(long argc, char **argv, ruby_cmdline_options_t *opt, int envopt)
if (!s[1])
break;
- default:
+ default: {
+ rb_encoding *enc = IF_UTF8_PATH(rb_utf8_encoding(), rb_locale_encoding());
+ const char *e = s + strlen(s);
+ int r = rb_enc_precise_mbclen(s, e, enc);
+ unsigned int c = (unsigned char)*s;
+ if (r > 0) {
+ c = rb_enc_mbc_to_codepoint(s, e, enc);
+ if (ONIGENC_IS_CODE_GRAPH(enc, c) ||
+ ((s = ruby_escaped_char(c)) != 0 &&
+ (r = (int)strlen(s), /* 3 at most */ 1))) {
+ rb_enc_raise(enc, rb_eRuntimeError,
+ "invalid option -%.*s (-h will show valid options)",
+ r, s);
+ }
+ }
rb_raise(rb_eRuntimeError,
- "invalid option -%c (-h will show valid options)",
- (int)(unsigned char)*s);
+ "invalid option -\\x%.2x (-h will show valid options)",
+ c);
+
goto switch_end;
+ }
noenvopt:
/* "EIdvwWrKU" only */
@@ -1736,7 +1777,6 @@ static void
ruby_init_prelude(void)
{
Init_builtin_features();
- rb_const_remove(rb_cObject, rb_intern_const("TMP_RUBY_PREFIX"));
}
void rb_call_builtin_inits(void);
@@ -1771,28 +1811,6 @@ ruby_opt_init(ruby_cmdline_options_t *opt)
}
}
- /* [Feature #19785] Warning for removed GC environment variable.
- * Remove this in Ruby 3.4. */
- if (getenv("RUBY_GC_HEAP_INIT_SLOTS")) {
- rb_warn_deprecated("The environment variable RUBY_GC_HEAP_INIT_SLOTS",
- "environment variables RUBY_GC_HEAP_%d_INIT_SLOTS");
- }
-
- if (getenv("RUBY_FREE_AT_EXIT")) {
- rb_warn("Free at exit is experimental and may be unstable");
- rb_free_at_exit = true;
- }
-
-#if USE_RJIT
- // rb_call_builtin_inits depends on RubyVM::RJIT.enabled?
- if (opt->rjit.on)
- rb_rjit_enabled = true;
- if (opt->rjit.stats)
- rb_rjit_stats_enabled = true;
- if (opt->rjit.trace_exits)
- rb_rjit_trace_exits_enabled = true;
-#endif
-
Init_ext(); /* load statically linked extensions before rubygems */
Init_extra_exts();
@@ -1803,15 +1821,20 @@ ruby_opt_init(ruby_cmdline_options_t *opt)
ruby_init_prelude();
- // Initialize JITs after prelude because JITing prelude is typically not optimal.
-#if USE_RJIT
- // Also, rb_rjit_init is safe only after rb_call_builtin_inits() defines RubyVM::RJIT::Compiler.
- if (opt->rjit.on)
- rb_rjit_init(&opt->rjit);
-#endif
+ /* Initialize the main box after loading libraries (including rubygems)
+ * to enable those in both root and main */
+ if (rb_box_available())
+ rb_initialize_main_box();
+ rb_box_init_done();
+
+ // Initialize JITs after ruby_init_prelude() because JITing prelude is typically not optimal.
#if USE_YJIT
rb_yjit_init(opt->yjit);
#endif
+#if USE_ZJIT
+ extern void rb_zjit_init(bool);
+ rb_zjit_init(opt->zjit);
+#endif
ruby_set_script_name(opt->script_name);
require_libraries(&opt->req_list);
@@ -1977,7 +2000,7 @@ copy_str(VALUE str, rb_encoding *enc, bool intern)
return rb_enc_interned_str(RSTRING_PTR(str), RSTRING_LEN(str), enc);
}
-#if USE_YJIT
+#if USE_YJIT || USE_ZJIT
// Check that an environment variable is set to a truthy value
static bool
env_var_truthy(const char *name)
@@ -2098,24 +2121,46 @@ process_script(ruby_cmdline_options_t *opt)
return ast_value;
}
-/**
- * Call ruby_opt_init to set up the global state based on the command line
- * options, and then warn if prism is enabled and the experimental warning
- * category is enabled.
- */
+static uint8_t
+prism_script_command_line(ruby_cmdline_options_t *opt)
+{
+ uint8_t command_line = 0;
+ if (opt->do_split) command_line |= PM_OPTIONS_COMMAND_LINE_A;
+ if (opt->do_line) command_line |= PM_OPTIONS_COMMAND_LINE_L;
+ if (opt->do_loop) command_line |= PM_OPTIONS_COMMAND_LINE_N;
+ if (opt->do_print) command_line |= PM_OPTIONS_COMMAND_LINE_P;
+ if (opt->xflag) command_line |= PM_OPTIONS_COMMAND_LINE_X;
+ return command_line;
+}
+
static void
-prism_opt_init(ruby_cmdline_options_t *opt)
+prism_script_shebang_callback(pm_options_t *options, const uint8_t *source, size_t length, void *data)
{
- ruby_opt_init(opt);
+ ruby_cmdline_options_t *opt = (ruby_cmdline_options_t *) data;
+ opt->warning = 0;
+
+ char *switches = malloc(length + 1);
+ memcpy(switches, source, length);
+ switches[length] = '\0';
+
+ int no_src_enc = !opt->src.enc.name;
+ int no_ext_enc = !opt->ext.enc.name;
+ int no_int_enc = !opt->intern.enc.name;
- if (rb_warning_category_enabled_p(RB_WARN_CATEGORY_EXPERIMENTAL)) {
- rb_category_warn(
- RB_WARN_CATEGORY_EXPERIMENTAL,
- "The compiler based on the Prism parser is currently experimental "
- "and compatibility with the compiler based on parse.y is not yet "
- "complete. Please report any issues you find on the `ruby/prism` "
- "issue tracker."
- );
+ moreswitches(switches, opt, 0);
+ free(switches);
+
+ pm_options_command_line_set(options, prism_script_command_line(opt));
+
+ if (no_src_enc && opt->src.enc.name) {
+ opt->src.enc.index = opt_enc_index(opt->src.enc.name);
+ pm_options_encoding_set(options, StringValueCStr(opt->ext.enc.name));
+ }
+ if (no_ext_enc && opt->ext.enc.name) {
+ opt->ext.enc.index = opt_enc_index(opt->ext.enc.name);
+ }
+ if (no_int_enc && opt->intern.enc.name) {
+ opt->intern.enc.index = opt_enc_index(opt->intern.enc.name);
}
}
@@ -2130,44 +2175,63 @@ prism_script(ruby_cmdline_options_t *opt, pm_parse_result_t *result)
pm_options_t *options = &result->options;
pm_options_line_set(options, 1);
+ pm_options_main_script_set(options, true);
- if (opt->ext.enc.name != 0) {
- pm_options_encoding_set(options, StringValueCStr(opt->ext.enc.name));
- }
+ const bool read_stdin = (strcmp(opt->script, "-") == 0);
- uint8_t command_line = 0;
- if (opt->do_split) command_line |= PM_OPTIONS_COMMAND_LINE_A;
- if (opt->do_line) command_line |= PM_OPTIONS_COMMAND_LINE_L;
- if (opt->do_loop) command_line |= PM_OPTIONS_COMMAND_LINE_N;
- if (opt->do_print) command_line |= PM_OPTIONS_COMMAND_LINE_P;
- if (opt->xflag) command_line |= PM_OPTIONS_COMMAND_LINE_X;
+ if (read_stdin) {
+ pm_options_encoding_set(options, rb_enc_name(rb_locale_encoding()));
+ }
+ if (opt->src.enc.name != 0) {
+ pm_options_encoding_set(options, StringValueCStr(opt->src.enc.name));
+ }
+ uint8_t command_line = prism_script_command_line(opt);
VALUE error;
- if (strcmp(opt->script, "-") == 0) {
+
+ if (read_stdin) {
pm_options_command_line_set(options, command_line);
pm_options_filepath_set(options, "-");
+ pm_options_shebang_callback_set(options, prism_script_shebang_callback, (void *) opt);
- prism_opt_init(opt);
+ ruby_opt_init(opt);
error = pm_parse_stdin(result);
+
+ // If we found an __END__ marker, then we're going to define a global
+ // DATA constant that is a file object that can be read to read the
+ // contents after the marker.
+ if (NIL_P(error) && result->parser.data_loc.start != NULL) {
+ rb_define_global_const("DATA", rb_stdin);
+ }
}
else if (opt->e_script) {
- command_line |= PM_OPTIONS_COMMAND_LINE_E;
+ command_line = (uint8_t) ((command_line | PM_OPTIONS_COMMAND_LINE_E) & ~PM_OPTIONS_COMMAND_LINE_X);
pm_options_command_line_set(options, command_line);
- prism_opt_init(opt);
+ ruby_opt_init(opt);
result->node.coverage_enabled = 0;
- error = pm_parse_string(result, opt->e_script, rb_str_new2("-e"));
+ error = pm_parse_string(result, opt->e_script, rb_str_new2("-e"), NULL);
}
else {
+ VALUE script_name = rb_str_encode_ospath(opt->script_name);
+
pm_options_command_line_set(options, command_line);
- error = pm_load_file(result, opt->script_name, true);
+ pm_options_shebang_callback_set(options, prism_script_shebang_callback, (void *) opt);
+
+ error = pm_load_file(result, script_name, true);
// If reading the file did not error, at that point we load the command
// line options. We do it in this order so that if the main script fails
// to load, it doesn't require files required by -r.
if (NIL_P(error)) {
- prism_opt_init(opt);
- error = pm_parse_file(result, opt->script_name);
+ ruby_opt_init(opt);
+ error = pm_parse_file(result, opt->script_name, NULL);
+ }
+
+ // Check if (after requiring all of the files through -r flags) we have
+ // coverage enabled and need to enable coverage on the main script.
+ if (RTEST(rb_get_coverages())) {
+ result->node.coverage_enabled = 1;
}
// If we found an __END__ marker, then we're going to define a global
@@ -2175,7 +2239,7 @@ prism_script(ruby_cmdline_options_t *opt, pm_parse_result_t *result)
// contents after the marker.
if (NIL_P(error) && result->parser.data_loc.start != NULL) {
int xflag = opt->xflag;
- VALUE file = open_load_file(opt->script_name, &xflag);
+ VALUE file = open_load_file(script_name, &xflag);
const pm_parser_t *parser = &result->parser;
size_t offset = parser->data_loc.start - parser->start + 7;
@@ -2258,8 +2322,8 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
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);
+ const rb_box_t *box = rb_root_box();
+ const long loaded_before_enc = RARRAY_LEN(box->loaded_features);
if (opt->dump & (DUMP_BIT(usage)|DUMP_BIT(help))) {
const char *const progname =
@@ -2289,20 +2353,33 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
FEATURE_SET(opt->features, FEATURE_BIT(yjit));
}
#endif
+#if USE_ZJIT
+ if (!FEATURE_USED_P(opt->features, zjit) && env_var_truthy("RUBY_ZJIT_ENABLE")) {
+ FEATURE_SET(opt->features, FEATURE_BIT(zjit));
+
+ // When the --zjit flag is specified, we would have call setup_zjit_options(""),
+ // which would have called rb_zjit_prepare_options() internally. This ensures we
+ // go through the same set up but with less overhead than setup_zjit_options("").
+ extern void rb_zjit_prepare_options();
+ rb_zjit_prepare_options();
+ }
+#endif
}
if (MULTI_BITS_P(FEATURE_SET_BITS(opt->features) & feature_jit_mask)) {
- rb_warn("RJIT and YJIT cannot both be enabled at the same time. Exiting");
+ rb_warn("Only one JIT can be enabled at the same time. Exiting");
return Qfalse;
}
-#if USE_RJIT
- if (FEATURE_SET_P(opt->features, rjit)) {
- opt->rjit.on = true; // set opt->rjit.on for Init_ruby_description() and calling rb_rjit_init()
- }
-#endif
#if USE_YJIT
if (FEATURE_SET_P(opt->features, yjit)) {
- opt->yjit = true; // set opt->yjit for Init_ruby_description() and calling rb_yjit_init()
+ bool rb_yjit_option_disable(void);
+ opt->yjit = !rb_yjit_option_disable(); // set opt->yjit for Init_ruby_description() and calling rb_yjit_init()
+ }
+#endif
+#if USE_ZJIT
+ if (FEATURE_SET_P(opt->features, zjit)) {
+ bool rb_zjit_option_enable(void);
+ opt->zjit = rb_zjit_option_enable(); // set opt->zjit for Init_ruby_description() and calling rb_zjit_init()
}
#endif
@@ -2399,7 +2476,7 @@ 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;
- VALUE load_path = vm->load_path;
+ VALUE load_path = box->load_path;
const ID id_initial_load_path_mark = INITIAL_LOAD_PATH_MARK;
int modifiable = FALSE;
@@ -2422,11 +2499,11 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
RARRAY_ASET(load_path, i, path);
}
if (modifiable) {
- rb_ary_replace(vm->load_path_snapshot, load_path);
+ rb_ary_replace(box->load_path_snapshot, load_path);
}
}
{
- VALUE loaded_features = vm->loaded_features;
+ VALUE loaded_features = box->loaded_features;
bool modified = false;
for (long i = loaded_before_enc; i < RARRAY_LEN(loaded_features); ++i) {
VALUE path = RARRAY_AREF(loaded_features, i);
@@ -2438,7 +2515,7 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
RARRAY_ASET(loaded_features, i, path);
}
if (modified) {
- rb_ary_replace(vm->loaded_features_snapshot, loaded_features);
+ rb_ary_replace(box->loaded_features_snapshot, loaded_features);
}
}
@@ -2447,7 +2524,10 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
#define SET_COMPILE_OPTION(h, o, name) \
rb_hash_aset((h), ID2SYM(rb_intern_const(#name)), \
RBOOL(FEATURE_SET_P(o->features, name)))
- SET_COMPILE_OPTION(option, opt, frozen_string_literal);
+
+ if (FEATURE_SET_P(opt->features, frozen_string_literal_set)) {
+ 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);
#undef SET_COMPILE_OPTION
@@ -2474,7 +2554,7 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
rb_enc_associate(opt->e_script, eenc);
}
- if (!(*rb_ruby_prism_ptr())) {
+ if (!rb_ruby_prism_p()) {
ast_value = process_script(opt);
if (!(result.ast = rb_ruby_ast_data_get(ast_value))) return Qfalse;
}
@@ -2510,7 +2590,10 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
if (dump & DUMP_BIT(syntax)) {
printf("Syntax OK\n");
dump &= ~DUMP_BIT(syntax);
- if (!dump) return Qtrue;
+ if (!dump) {
+ dispose_result();
+ return Qtrue;
+ }
}
if (dump & DUMP_BIT(parsetree)) {
@@ -2553,8 +2636,15 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt)
if (!result.ast) {
pm_parse_result_t *pm = &result.prism;
- iseq = pm_iseq_new_main(&pm->node, opt->script_name, path, parent, optimize);
+ int error_state;
+ iseq = pm_iseq_new_main(&pm->node, opt->script_name, path, parent, optimize, &error_state);
+
pm_parse_result_free(pm);
+
+ if (error_state) {
+ RUBY_ASSERT(iseq == NULL);
+ rb_jump_tag(error_state);
+ }
}
else {
rb_ast_t *ast = result.ast;
@@ -3088,8 +3178,6 @@ ruby_process_options(int argc, char **argv)
VALUE iseq;
const char *script_name = (argc > 0 && argv[0]) ? argv[0] : ruby_engine;
- (*rb_ruby_prism_ptr()) = false;
-
if (!origarg.argv || origarg.argc <= 0) {
origarg.argc = argc;
origarg.argv = argv;
@@ -3102,12 +3190,18 @@ ruby_process_options(int argc, char **argv)
ruby_init_setproctitle(argc, argv);
#endif
+ if (getenv("RUBY_FREE_AT_EXIT")) {
+ rb_free_at_exit = true;
+ rb_category_warn(RB_WARN_CATEGORY_EXPERIMENTAL, "Free at exit is experimental and may be unstable");
+ }
+
iseq = process_options(argc, argv, cmdline_options_init(&opt));
if (opt.crash_report && *opt.crash_report) {
void ruby_set_crash_report(const char *template);
ruby_set_crash_report(opt.crash_report);
}
+
return (void*)(struct RData*)iseq;
}
@@ -3153,3 +3247,9 @@ ruby_sysinit(int *argc, char ***argv)
}
fill_standard_fds();
}
+
+#ifdef RUBY_ASAN_ENABLED
+RUBY_SYMBOL_EXPORT_BEGIN
+const char ruby_asan_default_options[] = "use_sigaltstack=0:detect_leaks=0";
+RUBY_SYMBOL_EXPORT_END
+#endif
diff --git a/ruby.rs b/ruby.rs
new file mode 100644
index 0000000000..b66b2d21ca
--- /dev/null
+++ b/ruby.rs
@@ -0,0 +1,4 @@
+#[cfg(feature = "yjit")]
+pub use yjit::*;
+#[cfg(feature = "zjit")]
+pub use zjit::*;
diff --git a/ruby_atomic.h b/ruby_atomic.h
index 57d341082d..cbcfe682ce 100644
--- a/ruby_atomic.h
+++ b/ruby_atomic.h
@@ -1,4 +1,12 @@
+#ifndef INTERNAL_ATOMIC_H
+#define INTERNAL_ATOMIC_H
+
#include "ruby/atomic.h"
+#ifdef HAVE_STDATOMIC_H
+# include <stdatomic.h>
+#endif
+
+#define RUBY_ATOMIC_VALUE_LOAD(x) rbimpl_atomic_value_load(&(x), RBIMPL_ATOMIC_SEQ_CST)
/* shim macros only */
#define ATOMIC_ADD(var, val) RUBY_ATOMIC_ADD(var, val)
@@ -21,3 +29,45 @@
#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)
+
+#define ATOMIC_LOAD_RELAXED(var) rbimpl_atomic_load(&(var), RBIMPL_ATOMIC_RELAXED)
+
+typedef RBIMPL_ALIGNAS(8) uint64_t rbimpl_atomic_uint64_t;
+
+static inline uint64_t
+rbimpl_atomic_u64_load_relaxed(const volatile rbimpl_atomic_uint64_t *value)
+{
+#if defined(HAVE_GCC_ATOMIC_BUILTINS_64)
+ return __atomic_load_n(value, __ATOMIC_RELAXED);
+#elif defined(_WIN32)
+ uint64_t val = *value;
+ return InterlockedCompareExchange64(RBIMPL_CAST((uint64_t *)value), val, val);
+#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx))
+ uint64_t val = *value;
+ return atomic_cas_64(value, val, val);
+#else
+ // TODO: stdatomic
+
+ return *value;
+#endif
+}
+#define ATOMIC_U64_LOAD_RELAXED(var) rbimpl_atomic_u64_load_relaxed(&(var))
+
+static inline void
+rbimpl_atomic_u64_set_relaxed(volatile rbimpl_atomic_uint64_t *address, uint64_t value)
+{
+#if defined(HAVE_GCC_ATOMIC_BUILTINS_64)
+ __atomic_store_n(address, value, __ATOMIC_RELAXED);
+#elif defined(_WIN32)
+ InterlockedExchange64(address, value);
+#elif defined(__sun) && defined(HAVE_ATOMIC_H) && (defined(_LP64) || defined(_I32LPx))
+ atomic_swap_64(address, value);
+#else
+ // TODO: stdatomic
+
+ *address = value;
+#endif
+}
+#define ATOMIC_U64_SET_RELAXED(var, val) rbimpl_atomic_u64_set_relaxed(&(var), val)
+
+#endif
diff --git a/ruby_parser.c b/ruby_parser.c
index 93901ea4d9..267f619bf9 100644
--- a/ruby_parser.c
+++ b/ruby_parser.c
@@ -34,12 +34,6 @@
#define parser_encoding const void
-static int
-is_ascii_string2(VALUE str)
-{
- return is_ascii_string(str);
-}
-
RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 6, 0)
static VALUE
syntax_error_append(VALUE exc, VALUE file, int line, int column,
@@ -144,12 +138,6 @@ utf8_encoding(void)
return rb_utf8_encoding();
}
-static VALUE
-enc_associate(VALUE obj, parser_encoding *enc)
-{
- return rb_enc_associate(obj, enc);
-}
-
static parser_encoding *
ascii8bit_encoding(void)
{
@@ -186,12 +174,6 @@ intern3(const char *name, long len, parser_encoding *enc)
return rb_intern3(name, len, enc);
}
-static parser_encoding *
-usascii_encoding(void)
-{
- return rb_usascii_encoding();
-}
-
static int
enc_symname_type(const char *name, long len, parser_encoding *enc, unsigned int allowed_attrset)
{
@@ -203,6 +185,7 @@ typedef struct {
rb_encoding *enc;
NODE *succ_block;
const rb_code_location_t *loc;
+ rb_parser_assignable_func assignable;
} reg_named_capture_assign_t;
static int
@@ -216,11 +199,12 @@ reg_named_capture_assign_iter(const OnigUChar *name, const OnigUChar *name_end,
long len = name_end - name;
const char *s = (const char *)name;
- return rb_reg_named_capture_assign_iter_impl(p, s, len, enc, &arg->succ_block, loc);
+ return rb_reg_named_capture_assign_iter_impl(p, s, len, enc, &arg->succ_block, loc, arg->assignable);
}
static NODE *
-reg_named_capture_assign(struct parser_params* p, VALUE regexp, const rb_code_location_t *loc)
+reg_named_capture_assign(struct parser_params* p, VALUE regexp, const rb_code_location_t *loc,
+ rb_parser_assignable_func assignable)
{
reg_named_capture_assign_t arg;
@@ -228,6 +212,7 @@ reg_named_capture_assign(struct parser_params* p, VALUE regexp, const rb_code_lo
arg.enc = rb_enc_get(regexp);
arg.succ_block = 0;
arg.loc = loc;
+ arg.assignable = assignable;
onig_foreach_name(RREGEXP_PTR(regexp), reg_named_capture_assign_iter, &arg);
if (!arg.succ_block) return 0;
@@ -347,8 +332,6 @@ static const rb_parser_config_t rb_global_parser_config = {
.attr_get = rb_attr_get,
- .ary_new = rb_ary_new,
- .ary_push = rb_ary_push,
.ary_new_from_args = rb_ary_new_from_args,
.ary_unshift = rb_ary_unshift,
@@ -367,25 +350,18 @@ static const rb_parser_config_t rb_global_parser_config = {
.id2name = rb_id2name,
.id2str = rb_id2str,
.id2sym = rb_id2sym,
- .sym2id = rb_sym2id,
.str_catf = rb_str_catf,
.str_cat_cstr = rb_str_cat_cstr,
- .str_modify = rb_str_modify,
- .str_set_len = rb_str_set_len,
- .str_cat = rb_str_cat,
.str_resize = rb_str_resize,
.str_new = rb_str_new,
.str_new_cstr = rb_str_new_cstr,
.str_to_interned_str = rb_str_to_interned_str,
- .is_ascii_string = is_ascii_string2,
.enc_str_new = enc_str_new,
.str_vcatf = rb_str_vcatf,
.rb_sprintf = rb_sprintf,
.rstring_ptr = RSTRING_PTR,
- .rstring_end = RSTRING_END,
.rstring_len = RSTRING_LEN,
- .obj_as_string = rb_obj_as_string,
.int2num = rb_int2num_inline,
@@ -408,7 +384,6 @@ static const rb_parser_config_t rb_global_parser_config = {
.enc_get = enc_get,
.enc_asciicompat = enc_asciicompat,
.utf8_encoding = utf8_encoding,
- .enc_associate = enc_associate,
.ascii8bit_encoding = ascii8bit_encoding,
.enc_codelen = enc_codelen,
.enc_mbcput = enc_mbcput,
@@ -417,8 +392,6 @@ static const rb_parser_config_t rb_global_parser_config = {
.enc_isspace = enc_isspace,
.enc_coderange_7bit = ENC_CODERANGE_7BIT,
.enc_coderange_unknown = ENC_CODERANGE_UNKNOWN,
- .usascii_encoding = usascii_encoding,
- .enc_coderange_broken = ENC_CODERANGE_BROKEN,
.enc_mbminlen = enc_mbminlen,
.enc_isascii = enc_isascii,
.enc_mbc_to_codepoint = enc_mbc_to_codepoint,
@@ -432,7 +405,6 @@ static const rb_parser_config_t rb_global_parser_config = {
.errinfo = rb_errinfo,
.set_errinfo = rb_set_errinfo,
- .exc_raise = rb_exc_raise,
.make_exception = rb_make_exception,
.sized_xfree = ruby_sized_xfree,
diff --git a/rubyparser.h b/rubyparser.h
index c98f4a91a5..5af8f6db62 100644
--- a/rubyparser.h
+++ b/rubyparser.h
@@ -224,8 +224,9 @@ typedef struct rb_parser_ast_token {
typedef void* rb_parser_ary_data;
enum rb_parser_ary_data_type {
- PARSER_ARY_DATA_AST_TOKEN,
- PARSER_ARY_DATA_SCRIPT_LINE
+ PARSER_ARY_DATA_AST_TOKEN = 1,
+ PARSER_ARY_DATA_SCRIPT_LINE,
+ PARSER_ARY_DATA_NODE
};
typedef struct rb_parser_ary {
@@ -247,6 +248,7 @@ typedef struct RNode_SCOPE {
rb_ast_id_table_t *nd_tbl;
struct RNode *nd_body;
+ struct RNode *nd_parent;
struct RNode_ARGS *nd_args;
} rb_node_scope_t;
@@ -264,6 +266,9 @@ typedef struct RNode_IF {
struct RNode *nd_cond;
struct RNode *nd_body;
struct RNode *nd_else;
+ rb_code_location_t if_keyword_loc;
+ rb_code_location_t then_keyword_loc;
+ rb_code_location_t end_keyword_loc;
} rb_node_if_t;
typedef struct RNode_UNLESS {
@@ -272,6 +277,9 @@ typedef struct RNode_UNLESS {
struct RNode *nd_cond;
struct RNode *nd_body;
struct RNode *nd_else;
+ rb_code_location_t keyword_loc;
+ rb_code_location_t then_keyword_loc;
+ rb_code_location_t end_keyword_loc;
} rb_node_unless_t;
typedef struct RNode_CASE {
@@ -279,6 +287,8 @@ typedef struct RNode_CASE {
struct RNode *nd_head;
struct RNode *nd_body;
+ rb_code_location_t case_keyword_loc;
+ rb_code_location_t end_keyword_loc;
} rb_node_case_t;
typedef struct RNode_CASE2 {
@@ -286,6 +296,8 @@ typedef struct RNode_CASE2 {
struct RNode *nd_head;
struct RNode *nd_body;
+ rb_code_location_t case_keyword_loc;
+ rb_code_location_t end_keyword_loc;
} rb_node_case2_t;
typedef struct RNode_CASE3 {
@@ -293,6 +305,8 @@ typedef struct RNode_CASE3 {
struct RNode *nd_head;
struct RNode *nd_body;
+ rb_code_location_t case_keyword_loc;
+ rb_code_location_t end_keyword_loc;
} rb_node_case3_t;
typedef struct RNode_WHEN {
@@ -301,6 +315,8 @@ typedef struct RNode_WHEN {
struct RNode *nd_head;
struct RNode *nd_body;
struct RNode *nd_next;
+ rb_code_location_t keyword_loc;
+ rb_code_location_t then_keyword_loc;
} rb_node_when_t;
typedef struct RNode_IN {
@@ -309,26 +325,21 @@ typedef struct RNode_IN {
struct RNode *nd_head;
struct RNode *nd_body;
struct RNode *nd_next;
+ rb_code_location_t in_keyword_loc;
+ rb_code_location_t then_keyword_loc;
+ rb_code_location_t operator_loc;
} rb_node_in_t;
-/* RNode_WHILE and RNode_UNTIL should be same structure */
-typedef struct RNode_WHILE {
+typedef struct RNode_LOOP {
NODE node;
struct RNode *nd_cond;
struct RNode *nd_body;
long nd_state;
-} rb_node_while_t;
+ rb_code_location_t keyword_loc;
+ rb_code_location_t closing_loc;
+} rb_node_while_t, rb_node_until_t;
-typedef struct RNode_UNTIL {
- NODE node;
-
- struct RNode *nd_cond;
- struct RNode *nd_body;
- long nd_state;
-} rb_node_until_t;
-
-/* RNode_ITER and RNode_FOR should be same structure */
typedef struct RNode_ITER {
NODE node;
@@ -341,6 +352,10 @@ typedef struct RNode_FOR {
struct RNode *nd_body;
struct RNode *nd_iter;
+ rb_code_location_t for_keyword_loc;
+ rb_code_location_t in_keyword_loc;
+ rb_code_location_t do_keyword_loc;
+ rb_code_location_t end_keyword_loc;
} rb_node_for_t;
typedef struct RNode_FOR_MASGN {
@@ -349,26 +364,13 @@ typedef struct RNode_FOR_MASGN {
struct RNode *nd_var;
} rb_node_for_masgn_t;
-/* RNode_BREAK, RNode_NEXT and RNode_REDO should be same structure */
-typedef struct RNode_BREAK {
- NODE node;
-
- struct RNode *nd_chain;
- struct RNode *nd_stts;
-} rb_node_break_t;
-
-typedef struct RNode_NEXT {
+typedef struct RNode_EXITS {
NODE node;
struct RNode *nd_chain;
struct RNode *nd_stts;
-} rb_node_next_t;
-
-typedef struct RNode_REDO {
- NODE node;
-
- struct RNode *nd_chain;
-} rb_node_redo_t;
+ rb_code_location_t keyword_loc;
+} rb_node_exits_t, rb_node_break_t, rb_node_next_t, rb_node_redo_t;
typedef struct RNode_RETRY {
NODE node;
@@ -392,6 +394,7 @@ typedef struct RNode_RESBODY {
NODE node;
struct RNode *nd_args;
+ struct RNode *nd_exc_var;
struct RNode *nd_body;
struct RNode *nd_next;
} rb_node_resbody_t;
@@ -403,20 +406,13 @@ typedef struct RNode_ENSURE {
struct RNode *nd_ensr;
} rb_node_ensure_t;
-/* RNode_AND and RNode_OR should be same structure */
-typedef struct RNode_AND {
- NODE node;
-
- struct RNode *nd_1st;
- struct RNode *nd_2nd;
-} rb_node_and_t;
-
-typedef struct RNode_OR {
+typedef struct {
NODE node;
struct RNode *nd_1st;
struct RNode *nd_2nd;
-} rb_node_or_t;
+ rb_code_location_t operator_loc;
+} rb_node_and_t, rb_node_or_t;
typedef struct RNode_MASGN {
NODE node;
@@ -477,6 +473,10 @@ typedef struct RNode_OP_ASGN1 {
ID nd_mid;
struct RNode *nd_index;
struct RNode *nd_rvalue;
+ rb_code_location_t call_operator_loc;
+ rb_code_location_t opening_loc;
+ rb_code_location_t closing_loc;
+ rb_code_location_t binary_operator_loc;
} rb_node_op_asgn1_t;
typedef struct RNode_OP_ASGN2 {
@@ -487,6 +487,9 @@ typedef struct RNode_OP_ASGN2 {
ID nd_vid;
ID nd_mid;
bool nd_aid;
+ rb_code_location_t call_operator_loc;
+ rb_code_location_t message_loc;
+ rb_code_location_t binary_operator_loc;
} rb_node_op_asgn2_t;
typedef struct RNode_OP_ASGN_AND {
@@ -553,6 +556,9 @@ typedef struct RNode_SUPER {
NODE node;
struct RNode *nd_args;
+ rb_code_location_t keyword_loc;
+ rb_code_location_t lparen_loc;
+ rb_code_location_t rparen_loc;
} rb_node_super_t;
typedef struct RNode_ZSUPER {
@@ -568,8 +574,6 @@ typedef struct RNode_ZSUPER {
* alen (length of list) | * nd_end (point to the last LIST)
* next -----------------+ * next
-
- RNode_LIST and RNode_VALUES should be same structure
*/
typedef struct RNode_LIST {
NODE node;
@@ -586,14 +590,6 @@ typedef struct RNode_ZLIST {
NODE node;
} rb_node_zlist_t;
-typedef struct RNode_VALUES {
- NODE node;
-
- struct RNode *nd_head;
- long nd_alen;
- struct RNode *nd_next;
-} rb_node_values_t;
-
typedef struct RNode_HASH {
NODE node;
@@ -605,12 +601,16 @@ typedef struct RNode_RETURN {
NODE node;
struct RNode *nd_stts;
+ rb_code_location_t keyword_loc;
} rb_node_return_t;
typedef struct RNode_YIELD {
NODE node;
struct RNode *nd_head;
+ rb_code_location_t keyword_loc;
+ rb_code_location_t lparen_loc;
+ rb_code_location_t rparen_loc;
} rb_node_yield_t;
typedef struct RNode_LVAR {
@@ -661,14 +661,6 @@ typedef struct RNode_BACK_REF {
long nd_nth;
} rb_node_back_ref_t;
-/* RNode_MATCH and RNode_REGX should be same structure */
-typedef struct RNode_MATCH {
- NODE node;
-
- struct rb_parser_string *string;
- int options;
-} rb_node_match_t;
-
typedef struct RNode_MATCH2 {
NODE node;
@@ -724,14 +716,13 @@ typedef struct RNode_IMAGINARY {
enum rb_numeric_type type;
} rb_node_imaginary_t;
-/* RNode_STR and RNode_XSTR should be same structure */
typedef struct RNode_STR {
NODE node;
struct rb_parser_string *string;
} rb_node_str_t;
-/* RNode_DSTR, RNode_DXSTR, RNode_DREGX and RNode_DSYM should be same structure */
+/* NODE_DSTR, NODE_DXSTR, NODE_DREGX, NODE_DSYM */
typedef struct RNode_DSTR {
NODE node;
@@ -752,14 +743,19 @@ typedef struct RNode_EVSTR {
NODE node;
struct RNode *nd_body;
+ rb_code_location_t opening_loc;
+ rb_code_location_t closing_loc;
} rb_node_evstr_t;
-typedef struct RNode_REGX {
+typedef struct RNode_REGX { /* also RNode_MATCH */
NODE node;
struct rb_parser_string *string;
int options;
-} rb_node_regx_t;
+ rb_code_location_t opening_loc;
+ rb_code_location_t content_loc;
+ rb_code_location_t closing_loc;
+} rb_node_regx_t, rb_node_match_t;
typedef rb_node_dstr_t rb_node_dregx_t;
@@ -786,7 +782,6 @@ struct rb_args_info {
struct RNode_OPT_ARG *opt_args;
unsigned int no_kwarg: 1;
- unsigned int ruby2_keywords: 1;
unsigned int forwarding: 1;
};
@@ -843,6 +838,7 @@ typedef struct RNode_SPLAT {
NODE node;
struct RNode *nd_head;
+ rb_code_location_t operator_loc;
} rb_node_splat_t;
typedef struct RNode_BLOCK_PASS {
@@ -850,6 +846,8 @@ typedef struct RNode_BLOCK_PASS {
struct RNode *nd_head;
struct RNode *nd_body;
+ unsigned int forwarding: 1;
+ rb_code_location_t operator_loc;
} rb_node_block_pass_t;
typedef struct RNode_DEFN {
@@ -872,6 +870,7 @@ typedef struct RNode_ALIAS {
struct RNode *nd_1st;
struct RNode *nd_2nd;
+ rb_code_location_t keyword_loc;
} rb_node_alias_t;
typedef struct RNode_VALIAS {
@@ -879,12 +878,14 @@ typedef struct RNode_VALIAS {
ID nd_alias;
ID nd_orig;
+ rb_code_location_t keyword_loc;
} rb_node_valias_t;
typedef struct RNode_UNDEF {
NODE node;
- struct RNode *nd_undef;
+ rb_parser_ary_t *nd_undefs;
+ rb_code_location_t keyword_loc;
} rb_node_undef_t;
typedef struct RNode_CLASS {
@@ -893,6 +894,9 @@ typedef struct RNode_CLASS {
struct RNode *nd_cpath;
struct RNode *nd_body;
struct RNode *nd_super;
+ rb_code_location_t class_keyword_loc;
+ rb_code_location_t inheritance_operator_loc;
+ rb_code_location_t end_keyword_loc;
} rb_node_class_t;
typedef struct RNode_MODULE {
@@ -900,6 +904,8 @@ typedef struct RNode_MODULE {
struct RNode *nd_cpath;
struct RNode *nd_body;
+ rb_code_location_t module_keyword_loc;
+ rb_code_location_t end_keyword_loc;
} rb_node_module_t;
typedef struct RNode_SCLASS {
@@ -907,6 +913,9 @@ typedef struct RNode_SCLASS {
struct RNode *nd_recv;
struct RNode *nd_body;
+ rb_code_location_t class_keyword_loc;
+ rb_code_location_t operator_loc;
+ rb_code_location_t end_keyword_loc;
} rb_node_sclass_t;
typedef struct RNode_COLON2 {
@@ -914,31 +923,26 @@ typedef struct RNode_COLON2 {
struct RNode *nd_head;
ID nd_mid;
+ rb_code_location_t delimiter_loc;
+ rb_code_location_t name_loc;
} rb_node_colon2_t;
typedef struct RNode_COLON3 {
NODE node;
ID nd_mid;
+ rb_code_location_t delimiter_loc;
+ rb_code_location_t name_loc;
} rb_node_colon3_t;
-/* RNode_DOT2, RNode_DOT3, RNode_FLIP2 and RNode_FLIP3 should be same structure */
-typedef struct RNode_DOT2 {
- NODE node;
-
- struct RNode *nd_beg;
- struct RNode *nd_end;
-} rb_node_dot2_t;
-
-typedef struct RNode_DOT3 {
+/* NODE_DOT2, NODE_DOT3, NODE_FLIP2, NODE_FLIP3 */
+typedef struct RNode_DOTS {
NODE node;
struct RNode *nd_beg;
struct RNode *nd_end;
-} rb_node_dot3_t;
-
-typedef rb_node_dot2_t rb_node_flip2_t;
-typedef rb_node_dot3_t rb_node_flip3_t;
+ rb_code_location_t operator_loc;
+} rb_node_dot2_t, rb_node_dot3_t, rb_node_flip2_t, rb_node_flip3_t;
typedef struct RNode_SELF {
NODE node;
@@ -966,12 +970,16 @@ typedef struct RNode_DEFINED {
NODE node;
struct RNode *nd_head;
+ rb_code_location_t keyword_loc;
} rb_node_defined_t;
typedef struct RNode_POSTEXE {
NODE node;
struct RNode *nd_body;
+ rb_code_location_t keyword_loc;
+ rb_code_location_t opening_loc;
+ rb_code_location_t closing_loc;
} rb_node_postexe_t;
typedef struct RNode_SYM {
@@ -994,6 +1002,9 @@ typedef struct RNode_LAMBDA {
NODE node;
struct RNode *nd_body;
+ rb_code_location_t operator_loc;
+ rb_code_location_t opening_loc;
+ rb_code_location_t closing_loc;
} rb_node_lambda_t;
typedef struct RNode_ARYPTN {
@@ -1155,7 +1166,7 @@ typedef struct RNode_ERROR {
#define RNODE_FILE(node) ((rb_node_file_t *)(node))
#define RNODE_ENCODING(node) ((rb_node_encoding_t *)(node))
-/* FL : 0..4: T_TYPES, 5: KEEP_WB, 6: PROMOTED, 7: FINALIZE, 8: UNUSED, 9: UNUSED, 10: EXIVAR, 11: FREEZE */
+/* FL : 0..4: T_TYPES, 5: KEEP_WB, 6: PROMOTED, 7: FINALIZE, 8..10: UNUSED, 11: FREEZE */
/* NODE_FL: 0..4: UNUSED, 5: UNUSED, 6: UNUSED, 7: NODE_FL_NEWLINE,
* 8..14: nd_type,
* 15..: nd_line
@@ -1165,9 +1176,9 @@ typedef struct RNode_ERROR {
#define NODE_TYPESHIFT 8
#define NODE_TYPEMASK (((VALUE)0x7f)<<NODE_TYPESHIFT)
-#define nd_fl_newline(n) (n)->flags & NODE_FL_NEWLINE
-#define nd_set_fl_newline(n) (n)->flags |= NODE_FL_NEWLINE
-#define nd_unset_fl_newline(n) (n)->flags &= ~NODE_FL_NEWLINE
+#define nd_fl_newline(n) ((n)->flags & NODE_FL_NEWLINE)
+#define nd_set_fl_newline(n) ((n)->flags |= NODE_FL_NEWLINE)
+#define nd_unset_fl_newline(n) ((n)->flags &= ~NODE_FL_NEWLINE)
#define nd_type(n) ((int) ((RNODE(n)->flags & NODE_TYPEMASK)>>NODE_TYPESHIFT))
#define nd_set_type(n,t) \
@@ -1208,6 +1219,8 @@ typedef struct parser_params rb_parser_t;
typedef struct rb_imemo_tmpbuf_struct rb_imemo_tmpbuf_t;
#endif
+typedef NODE *(*rb_parser_assignable_func)(struct parser_params *p, ID id, NODE *val, const rb_code_location_t *loc);
+
#ifdef UNIVERSAL_PARSER
typedef struct rb_parser_config_struct {
/* Memory */
@@ -1225,14 +1238,12 @@ typedef struct rb_parser_config_struct {
// VALUE rb_suppress_tracing(VALUE (*func)(VALUE), VALUE arg);
VALUE (*compile_callback)(VALUE (*func)(VALUE), VALUE arg);
- NODE *(*reg_named_capture_assign)(struct parser_params* p, VALUE regexp, const rb_code_location_t *loc);
+ NODE *(*reg_named_capture_assign)(struct parser_params* p, VALUE regexp, const rb_code_location_t *loc, rb_parser_assignable_func assignable);
/* Variable */
VALUE (*attr_get)(VALUE obj, ID id);
/* Array */
- VALUE (*ary_new)(void);
- VALUE (*ary_push)(VALUE ary, VALUE elem);
VALUE (*ary_new_from_args)(long n, ...);
VALUE (*ary_unshift)(VALUE ary, VALUE item);
@@ -1252,29 +1263,22 @@ typedef struct rb_parser_config_struct {
const char *(*id2name)(ID id);
VALUE (*id2str)(ID id);
VALUE (*id2sym)(ID x);
- ID (*sym2id)(VALUE sym);
/* String */
RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3)
VALUE (*str_catf)(VALUE str, const char *format, ...);
VALUE (*str_cat_cstr)(VALUE str, const char *ptr);
- void (*str_modify)(VALUE str);
- void (*str_set_len)(VALUE str, long len);
- VALUE (*str_cat)(VALUE str, const char *ptr, long len);
VALUE (*str_resize)(VALUE str, long len);
VALUE (*str_new)(const char *ptr, long len);
VALUE (*str_new_cstr)(const char *ptr);
VALUE (*str_to_interned_str)(VALUE);
- int (*is_ascii_string)(VALUE str);
VALUE (*enc_str_new)(const char *ptr, long len, rb_encoding *enc);
RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 0)
VALUE (*str_vcatf)(VALUE str, const char *fmt, va_list ap);
RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 2)
VALUE (*rb_sprintf)(const char *format, ...);
char *(*rstring_ptr)(VALUE str);
- char *(*rstring_end)(VALUE str);
long (*rstring_len)(VALUE str);
- VALUE (*obj_as_string)(VALUE);
/* Numeric */
VALUE (*int2num)(int v);
@@ -1301,15 +1305,12 @@ typedef struct rb_parser_config_struct {
rb_encoding* (*enc_get)(VALUE obj);
int (*enc_asciicompat)(rb_encoding *enc);
rb_encoding *(*utf8_encoding)(void);
- VALUE (*enc_associate)(VALUE obj, rb_encoding *enc);
rb_encoding *(*ascii8bit_encoding)(void);
int (*enc_codelen)(int c, rb_encoding *enc);
int (*enc_mbcput)(unsigned int c, void *buf, rb_encoding *enc);
int (*enc_find_index)(const char *name);
rb_encoding *(*enc_from_index)(int idx);
int (*enc_isspace)(OnigCodePoint c, rb_encoding *enc);
- rb_encoding *(*usascii_encoding)(void);
- int enc_coderange_broken;
int (*enc_mbminlen)(rb_encoding *enc);
bool (*enc_isascii)(OnigCodePoint c, rb_encoding *enc);
OnigCodePoint (*enc_mbc_to_codepoint)(const char *p, const char *e, rb_encoding *enc);
@@ -1330,7 +1331,6 @@ typedef struct rb_parser_config_struct {
/* Eval */
VALUE (*errinfo)(void);
void (*set_errinfo)(VALUE err);
- void (*exc_raise)(VALUE mesg);
VALUE (*make_exception)(int argc, const VALUE *argv);
/* GC */
@@ -1388,9 +1388,6 @@ rb_parser_t *rb_ruby_parser_allocate(const rb_parser_config_t *config);
rb_parser_t *rb_ruby_parser_new(const rb_parser_config_t *config);
#endif
-long rb_parser_string_length(rb_parser_string_t *str);
-char *rb_parser_string_pointer(rb_parser_string_t *str);
-
RUBY_SYMBOL_EXPORT_END
#endif /* RUBY_RUBYPARSER_H */
diff --git a/sample/drb/README.ja.rdoc b/sample/drb/README.ja.rdoc
deleted file mode 100644
index 1697b1b704..0000000000
--- a/sample/drb/README.ja.rdoc
+++ /dev/null
@@ -1,59 +0,0 @@
-= サンプルスクリプト
-
-* Arrayをリモートから利用してイテレータを試す。
- * darray.rb --- server
- * darrayc.rb --- client
-
-* 簡易チャット
- * dchats.rb --- server
- * dchatc.rb --- client
-
-* 分散chasen
- * dhasen.rb --- server
- * dhasenc.rb --- client
-
-* 簡易ログサーバ
- * dlogd.rb --- server
- * dlogc.rb --- client
-
-* Queueサーバ。
- クライアントdqin.rbはQueueサーバの知らないオブジェクト(DQEntry)を
- pushするがDRbUnknownによりクライアントdqout.rbがpopできる。
- * dqueue.rb --- server
- * dqin.rb --- client。DQEntryオブジェクトをpushする
- * dqout.rb --- client。DQEntryオブジェクトをpopする
- * dqlib.rb --- DQEntryを定義したライブラリ
-
-* 名前による参照
- IdConvをカスタマイズしてidでなく名前で参照する例
- * name.rb --- server
- * namec.rb --- client
-
-* extservのサンプル
- * extserv_test.rb
-
-* TimerIdConvの使用例
- * holders.rb --- server。ruby -d hodlers.rbとするとTimerIdConvを使用する。
- * holderc.rb --- client
-
-* rinda.rbの使用例
- * rinda_ts.rb --- TupleSpaceサーバ。
- * rindac.rb --- TupleSpaceのclientでアプリケーションのclient
- * rindas.rb --- TupleSpaceのclientでアプリケーションのserver
-
-* observerの使用例
- cdbiff - http://namazu.org/~satoru/cdbiff/
- * dbiff.rb --- dcdbiff server
- * dcdbiff.rb --- dcdbiff client
-
-* drbsslの使用例
- * drbssl_s.rb
- * drbssl_c.rb
-
-* DRbProtocolの追加例
- * http0.rb
- * http0serv.rb
-
-* ringの使用例
- * ring_place.rb
- * ring_echo.rb
diff --git a/sample/drb/README.rdoc b/sample/drb/README.rdoc
deleted file mode 100644
index e6b457bc5c..0000000000
--- a/sample/drb/README.rdoc
+++ /dev/null
@@ -1,56 +0,0 @@
-= Sample scripts
-
-* array and iterator
- * darray.rb --- server
- * darrayc.rb --- client
-
-* simple chat
- * dchats.rb --- server
- * dchatc.rb --- client
-
-* distributed chasen (for Japanese)
- * dhasen.rb --- server
- * dhasenc.rb --- client
-
-* simple log server
- * dlogd.rb --- server
- * dlogc.rb --- client
-
-* Queue server, and DRbUnknown demo
- * dqueue.rb --- server
- * dqin.rb --- client. push DQEntry objects.
- * dqout.rb --- client. pop DQEntry objects.
- * dqlib.rb --- define DQEntry
-
-* IdConv customize demo: reference by name
- * name.rb --- server
- * namec.rb --- client
-
-* extserv
- * extserv_test.rb
-
-* IdConv customize demo 2: using TimerIdConv
- * holders.rb --- server
- * holderc.rb --- client
-
-* rinda, remote tuplespace
- * rinda_ts.rb --- TupleSpace server.
- * rindas.rb --- provide simple service via TupleSpace.
- * rindac.rb --- service user
-
-* observer
- cdbiff - http://namazu.org/~satoru/cdbiff/
- * dbiff.rb --- dcdbiff server
- * dcdbiff.rb --- dcdbiff client
-
-* drbssl
- * drbssl_s.rb
- * drbssl_c.rb
-
-* add DRbProtocol
- * http0.rb
- * http0serv.rb
-
-* Rinda::Ring
- * ring_place.rb
- * ring_echo.rb
diff --git a/sample/drb/acl.rb b/sample/drb/acl.rb
deleted file mode 100644
index d93eb9c1fc..0000000000
--- a/sample/drb/acl.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-require 'drb/acl'
-
-list = %w(deny all
- allow 192.168.1.1
- allow ::ffff:192.168.1.2
- allow 192.168.1.3
-)
-
-addr = ["AF_INET", 10, "lc630", "192.168.1.3"]
-
-acl = ACL.new
-p acl.allow_addr?(addr)
-
-acl = ACL.new(list, ACL::DENY_ALLOW)
-p acl.allow_addr?(addr)
diff --git a/sample/drb/darray.rb b/sample/drb/darray.rb
deleted file mode 100644
index d2ac39513f..0000000000
--- a/sample/drb/darray.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-=begin
- distributed Ruby --- Array
- Copyright (c) 1999-2001 Masatoshi SEKI
-=end
-
-require 'drb/drb'
-
-here = ARGV.shift
-DRb.start_service(here, [1, 2, "III", 4, "five", 6])
-puts DRb.uri
-DRb.thread.join
-
diff --git a/sample/drb/darrayc.rb b/sample/drb/darrayc.rb
deleted file mode 100644
index 579e11564e..0000000000
--- a/sample/drb/darrayc.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-=begin
- distributed Ruby --- Array client
- Copyright (c) 1999-2001 Masatoshi SEKI
-=end
-
-require 'drb/drb'
-
-there = ARGV.shift || raise("usage: #{$0} <server_uri>")
-
-DRb.start_service(nil, nil)
-ro = DRbObject.new(nil, there)
-p ro.size
-
-puts "# collect"
-a = ro.collect { |x|
- x + x
-}
-p a
-
-puts "# find"
-p ro.find { |x| x.kind_of? String }
-
-puts "# each, break"
-ro.each do |x|
- next if x == "five"
- puts x
-end
-
-puts "# each, break"
-ro.each do |x|
- break if x == "five"
- puts x
-end
-
-puts "# each, next"
-ro.each do |x|
- next if x == "five"
- puts x
-end
-
-puts "# each, redo"
-count = 0
-ro.each do |x|
- count += 1
- puts count
- redo if count == 3
-end
diff --git a/sample/drb/dbiff.rb b/sample/drb/dbiff.rb
deleted file mode 100644
index 290eb1d28b..0000000000
--- a/sample/drb/dbiff.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-#
-# dbiff.rb - distributed cdbiff (server)
-# * original: cdbiff by Satoru Takabayashi <http://namazu.org/~satoru/cdbiff>
-
-require 'drb/drb'
-require 'drb/eq'
-require 'drb/observer'
-
-class Biff
- include DRb::DRbObservable
-
- def initialize(filename, interval)
- super()
- @filename = filename
- @interval = interval
- end
-
- def run
- last = Time.now
- while true
- begin
- sleep(@interval)
- current = File::mtime(@filename)
- if current > last
- changed
- begin
- notify_observers(@filename, current)
- rescue Error
- end
- last = current
- end
- rescue
- next
- end
- end
- end
-end
-
-def main
- filename = "/var/mail/#{ENV['USER']}"
- interval = 15
- uri = 'druby://:19903'
-
- biff = Biff.new(filename, interval)
-
- DRb.start_service(uri, biff)
- biff.run
-end
-
-main
-
diff --git a/sample/drb/dcdbiff.rb b/sample/drb/dcdbiff.rb
deleted file mode 100644
index 6a24680c33..0000000000
--- a/sample/drb/dcdbiff.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-#
-# dcdbiff.rb - distributed cdbiff (client)
-# * original: cdbiff by Satoru Takabayashi <http://namazu.org/~satoru/cdbiff>
-
-require 'drb/drb'
-require 'drb/eq'
-
-class Notify
- include DRbUndumped
-
- def initialize(biff, command)
- @biff = biff
- @command = command
-
- @biff.add_observer(self)
- end
-
- def update(filename, time)
- p [filename, time] if $DEBUG
- system(@command)
- end
-
- def done
- begin
- @biff.delete_observer(self)
- rescue
- end
- end
-end
-
-def main
- command = 'eject'
- uri = 'druby://localhost:19903'
-
- DRb.start_service
- biff = DRbObject.new(nil, uri)
- notify = Notify.new(biff, command)
-
- trap("INT"){ notify.done }
- DRb.thread.join
-end
-
-main
diff --git a/sample/drb/dchatc.rb b/sample/drb/dchatc.rb
deleted file mode 100644
index 2b8ddbf4cc..0000000000
--- a/sample/drb/dchatc.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-=begin
- distributed Ruby --- chat client
- Copyright (c) 1999-2000 Masatoshi SEKI
-=end
-
-require 'drb/drb'
-
-class ChatClient
- include DRbUndumped
-
- def initialize(name)
- @name = name
- @key = nil
- end
- attr_reader(:name)
- attr_accessor(:key)
-
- def message(there, str)
- raise 'invalid key' unless @key == there
- puts str
- end
-end
-
-if __FILE__ == $0
- begin
- there = ARGV.shift
- name = ARGV.shift
- raise "usage" unless (there and name)
- rescue
- $stderr.puts("usage: #{$0} <server_uri> <your_name>")
- exit 1
- end
- DRb.start_service
- ro = DRbObject.new(nil, there)
-
- chat = ChatClient.new(name)
- entry = ro.add_member(chat)
- while gets
- entry.say($_)
- end
-end
diff --git a/sample/drb/dchats.rb b/sample/drb/dchats.rb
deleted file mode 100644
index c96486a452..0000000000
--- a/sample/drb/dchats.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-=begin
- distributed Ruby --- chat server
- Copyright (c) 1999-2000 Masatoshi SEKI
-=end
-require 'drb/drb'
-
-class ChatEntry
- include DRbUndumped
-
- def initialize(server, there)
- @server = server
- @there = there
- @name = there.name
- @key = there.key = Time.now
- end
- attr :name, true
- attr :there
-
- def say(str)
- @server.distribute(@there, str)
- end
-
- def listen(str)
- @there.message(@key, str)
- end
-end
-
-
-class ChatServer
- def initialize
- @mutex = Thread::Mutex.new
- @members = {}
- end
-
- def add_member(there)
- client = ChatEntry.new(self, there)
- @mutex.synchronize do
- @members[there] = client
- end
- client
- end
-
- def distribute(there, str)
- name = @members[there].name
- msg = "<#{name}> #{str}"
- msg2 = ">#{name}< #{str}"
- @mutex.synchronize do
- for m in @members.keys
- begin
- if m == there
- @members[m].listen(msg2)
- else
- @members[m].listen(msg)
- end
- rescue
- p $!
- @members.delete(m)
- end
- end
- end
- end
-end
-
-if __FILE__ == $0
- here = ARGV.shift
- DRb.start_service(here, ChatServer.new)
- puts DRb.uri
- DRb.thread.join
-end
diff --git a/sample/drb/dhasen.rb b/sample/drb/dhasen.rb
deleted file mode 100644
index 13ff38940e..0000000000
--- a/sample/drb/dhasen.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-=begin
- distributed Ruby --- dRuby Sample Server --- chasen server
- Copyright (c) 1999-2001 Masatoshi SEKI
-=end
-
-=begin
- How to play.
-
- Terminal 1
- | % ruby dhasen.rb
- | druby://yourhost:7640
-
- Terminal 2
- | % ruby dhasenc.rb druby://yourhost:7640
-
-=end
-
-require 'drb/drb'
-require 'chasen'
-
-class Dhasen
- include DRbUndumped
-
- def initialize
- @mutex = Thread::Mutex.new
- end
-
- def sparse(str, *arg)
- @mutex.synchronize do
- Chasen.getopt(*arg)
- Chasen.sparse(str)
- end
- end
-end
-
-if __FILE__ == $0
- DRb.start_service(nil, Dhasen.new)
- puts DRb.uri
- DRb.thread.join
-end
-
diff --git a/sample/drb/dhasenc.rb b/sample/drb/dhasenc.rb
deleted file mode 100644
index dddac9882c..0000000000
--- a/sample/drb/dhasenc.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# -*- coding: utf-8 -*-
-=begin
- distributed Ruby --- dRuby Sample Client -- chasen client
- Copyright (c) 1999-2001 Masatoshi SEKI
-=end
-
-require 'drb/drb'
-
-there = ARGV.shift || raise("usage: #{$0} <server_uri>")
-DRb.start_service
-dhasen = DRbObject.new(nil, there)
-
-print dhasen.sparse("本日は、晴天なり。", "-F", '(%BB %m %M)\n', "-j")
-print dhasen.sparse("本日は、晴天なり。", "-F", '(%m %M)\n')
diff --git a/sample/drb/dlogc.rb b/sample/drb/dlogc.rb
deleted file mode 100644
index 3939a71827..0000000000
--- a/sample/drb/dlogc.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-=begin
- distributed Ruby --- Log test
- Copyright (c) 1999-2001 Masatoshi SEKI
-=end
-
-require 'drb/drb'
-
-there = ARGV.shift || raise("usage: #{$0} <server_uri>")
-
-DRb.start_service
-ro = DRbObject.new(nil, there)
-ro.log(123)
-ro.log("hello")
-sleep 2
-ro.log("wakeup")
-
diff --git a/sample/drb/dlogd.rb b/sample/drb/dlogd.rb
deleted file mode 100644
index a87e660346..0000000000
--- a/sample/drb/dlogd.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-=begin
- distributed Ruby --- Log server
- Copyright (c) 1999-2000 Masatoshi SEKI
-=end
-
-require 'drb/drb'
-
-class Logger
- def initialize(fname)
- @fname = fname.to_s
- @fp = File.open(@fname, "a+")
- @queue = Thread::Queue.new
- @th = Thread.new { self.flush }
- end
-
- def log(str)
- @queue.push("#{Time.now}\t" + str.to_s)
- end
-
- def flush
- begin
- while(1)
- @fp.puts(@queue.pop)
- @fp.flush
- end
- ensure
- @fp.close
- end
- end
-end
-
-if __FILE__ == $0
- here = ARGV.shift
- DRb.start_service(here, Logger.new('/usr/tmp/dlogd.log'))
- puts DRb.uri
- DRb.thread.join
-end
-
diff --git a/sample/drb/dqin.rb b/sample/drb/dqin.rb
deleted file mode 100644
index 4751335fff..0000000000
--- a/sample/drb/dqin.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-=begin
- distributed Ruby --- store
- Copyright (c) 1999-2000 Masatoshi SEKI
-=end
-
-require 'drb/drb'
-require 'dqlib'
-
-there = ARGV.shift || raise("usage: #{$0} <server_uri>")
-
-DRb.start_service
-queue = DRbObject.new(nil, there)
-queue.push(DQEntry.new(DRb.uri))
diff --git a/sample/drb/dqlib.rb b/sample/drb/dqlib.rb
deleted file mode 100644
index 75f2e6115b..0000000000
--- a/sample/drb/dqlib.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-class DQEntry
- def initialize(name)
- @name = name
- end
-
- def greeting
- "Hello, This is #{@name}."
- end
- alias to_s greeting
-end
-
-if __FILE__ == $0
- puts DQEntry.new('DQEntry')
-end
diff --git a/sample/drb/dqout.rb b/sample/drb/dqout.rb
deleted file mode 100644
index f2b0b4ac95..0000000000
--- a/sample/drb/dqout.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-=begin
- distributed Ruby --- fetch
- Copyright (c) 1999-2000 Masatoshi SEKI
-=end
-
-require 'drb/drb'
-require 'dqlib'
-
-there = ARGV.shift || raise("usage: #{$0} <server_uri>")
-
-DRb.start_service
-queue = DRbObject.new(nil, there)
-entry = queue.pop
-puts entry.greeting
diff --git a/sample/drb/dqueue.rb b/sample/drb/dqueue.rb
deleted file mode 100644
index a9afa8c858..0000000000
--- a/sample/drb/dqueue.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-=begin
- distributed Ruby --- Queue
- Copyright (c) 1999-2000 Masatoshi SEKI
-=end
-
-require 'drb/drb'
-
-DRb.start_service(nil, Thread::Queue.new)
-puts DRb.uri
-DRb.thread.join
-
diff --git a/sample/drb/drbc.rb b/sample/drb/drbc.rb
deleted file mode 100644
index 50a86c39e8..0000000000
--- a/sample/drb/drbc.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-=begin
- distributed Ruby --- dRuby Sample Client
- Copyright (c) 1999-2000 Masatoshi SEKI
-=end
-
-require 'drb/drb'
-
-class DRbEx2
- include DRbUndumped
-
- def initialize(n)
- @n = n
- end
-
- def to_i
- @n.to_i
- end
-end
-
-if __FILE__ == $0
- there = ARGV.shift
- unless there
- $stderr.puts("usage: #{$0} <server_uri>")
- exit 1
- end
-
- DRb.start_service()
- ro = DRbObject.new_with_uri(there)
-
- puts ro
- p ro.to_a
- puts ro.hello
- p ro.hello
- puts ro.sample(DRbEx2.new(1), 2, 3)
- puts ro.sample(1, ro.sample(DRbEx2.new(1), 2, 3), DRbEx2.new(3))
-
- begin
- ro.err
- rescue DRb::DRbUnknownError
- p $!
- p $!.unknown
- rescue RuntimeError
- p $!
- end
-end
diff --git a/sample/drb/drbch.rb b/sample/drb/drbch.rb
deleted file mode 100644
index 07fdcd5fae..0000000000
--- a/sample/drb/drbch.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-=begin
- distributed Ruby --- dRuby Sample Client
- Copyright (c) 1999-2000 Masatoshi SEKI
-=end
-
-require 'drb/drb'
-require 'drb/http'
-
-class DRbEx2
- include DRbUndumped
-
- def initialize(n)
- @n = n
- end
-
- def to_i
- @n.to_i
- end
-end
-
-if __FILE__ == $0
- there = ARGV.shift
- unless there
- $stderr.puts("usage: #{$0} <server_uri>")
- exit 1
- end
-
- DRb::DRbConn.proxy_map['x68k'] = 'http://x68k/~mas/http_cgi.rb'
-
- DRb.start_service()
- ro = DRbObject.new(nil, there)
-
- puts ro
- p ro.to_a
- puts ro.hello
- p ro.hello
- puts ro.sample(DRbEx2.new(1), 2, 3)
- puts ro.sample(1, ro.sample(DRbEx2.new(1), 2, 3), DRbEx2.new(3))
-
- begin
- ro.err
- rescue DRb::DRbUnknownError
- p $!
- p $!.unknown
- rescue RuntimeError
- p $!
- end
-end
diff --git a/sample/drb/drbm.rb b/sample/drb/drbm.rb
deleted file mode 100644
index 3390608cd1..0000000000
--- a/sample/drb/drbm.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-=begin
- multiple DRbServer
- Copyright (c) 1999-2002 Masatoshi SEKI
-=end
-
-=begin
- How to play.
-
- Terminal 1
- | % ruby drbm.rb
- | druby://yourhost:7640 druby://yourhost:7641
-
- Terminal 2
- | % ruby drbmc.rb druby://yourhost:7640 druby://yourhost:7641
- | [#<DRb::DRbObject .... @uri="druby://yourhost:7640">, "FOO"]
- | [#<DRb::DRbObject .... @uri="druby://yourhost:7641">, "FOO"]
-
-=end
-
-require 'drb/drb'
-
-class Hoge
- include DRbUndumped
- def initialize(s)
- @str = s
- end
-
- def to_s
- @str
- end
-end
-
-class Foo
- def initialize(s='FOO')
- @hoge = Hoge.new(s)
- end
-
- def hello
- @hoge
- end
-end
-
-class Bar < Foo
- def initialize(foo)
- @hoge = foo.hello
- end
-end
-
-
-if __FILE__ == $0
- foo = Foo.new
- s1 = DRb::DRbServer.new('druby://:7640', foo)
- s2 = DRb::DRbServer.new('druby://:7641', Bar.new(foo))
-
- puts "#{s1.uri} #{s2.uri}"
-
- s1.thread.join
- s2.thread.join
-end
-
diff --git a/sample/drb/drbmc.rb b/sample/drb/drbmc.rb
deleted file mode 100644
index fd191401e6..0000000000
--- a/sample/drb/drbmc.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-=begin
- multiple DRbServer client
- Copyright (c) 1999-2002 Masatoshi SEKI
-=end
-
-require 'drb/drb'
-
-if __FILE__ == $0
- s1 = ARGV.shift
- s2 = ARGV.shift
- unless s1 && s2
- $stderr.puts("usage: #{$0} <server_uri1> <server_uri2>")
- exit 1
- end
-
- DRb.start_service()
- r1 = DRbObject.new(nil, s1)
- r2 = DRbObject.new(nil, s2)
-
- p [r1.hello, r1.hello.to_s]
- p [r2.hello, r2.hello.to_s]
-end
diff --git a/sample/drb/drbs-acl.rb b/sample/drb/drbs-acl.rb
deleted file mode 100644
index 71c4f7bf42..0000000000
--- a/sample/drb/drbs-acl.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-=begin
- distributed Ruby --- dRuby Sample Server
- Copyright (c) 1999-2000 Masatoshi SEKI
-=end
-
-=begin
- How to play.
-
- Terminal 1
- | % ruby drbs.rb
- | druby://yourhost:7640
-
- Terminal 2
- | % ruby drbc.rb druby://yourhost:7640
- | "hello"
- | 6
- | 10
-
-=end
-
-require 'drb/drb'
-require 'acl'
-
-class DRbEx
- def initialize
- @hello = 'hello'
- end
-
- def hello
- info = Thread.current['DRb']
- p info['socket'].peeraddr if info
- @hello
- end
-
- def sample(a, b, c)
- a.to_i + b.to_i + c.to_i
- end
-end
-
-if __FILE__ == $0
- acl = ACL.new(%w(deny all
- allow 192.168.1.*
- allow localhost))
-
- DRb.install_acl(acl)
-
- DRb.start_service(nil, DRbEx.new)
- puts DRb.uri
- DRb.thread.join
-end
-
diff --git a/sample/drb/drbs.rb b/sample/drb/drbs.rb
deleted file mode 100644
index 5a913d9918..0000000000
--- a/sample/drb/drbs.rb
+++ /dev/null
@@ -1,64 +0,0 @@
-=begin
- distributed Ruby --- dRuby Sample Server
- Copyright (c) 1999-2000,2002 Masatoshi SEKI
-=end
-
-=begin
- How to play.
-
- Terminal 1
- | % ruby drbs.rb
- | druby://yourhost:7640
-
- Terminal 2
- | % ruby drbc.rb druby://yourhost:7640
- | "hello"
- | ....
-
-=end
-
-require 'drb/drb'
-
-class DRbEx
- include DRbUndumped
-
- def initialize
- @hello = 'hello'
- end
-
- def hello
- cntxt = Thread.current['DRb']
- if cntxt
- p cntxt['server'].uri
- p cntxt['client'].peeraddr
- end
- Foo::Unknown.new
- end
-
- def err
- raise FooError
- end
-
- def sample(a, b, c)
- a.to_i + b.to_i + c.to_i
- end
-end
-
-class Foo
- class Unknown
- end
-end
-
-class FooError < RuntimeError
-end
-
-if __FILE__ == $0
- DRb.start_service(ARGV.shift || 'druby://:7640', DRbEx.new)
- puts DRb.uri
- Thread.new do
- sleep 10
- DRb.stop_service
- end
- DRb.thread.join
-end
-
diff --git a/sample/drb/drbssl_c.rb b/sample/drb/drbssl_c.rb
deleted file mode 100644
index 65112f6e78..0000000000
--- a/sample/drb/drbssl_c.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/usr/bin/env ruby
-
-require 'drb'
-require 'drb/ssl'
-
-there = ARGV.shift || "drbssl://localhost:3456"
-
-config = Hash.new
-config[:SSLVerifyMode] = OpenSSL::SSL::VERIFY_PEER
-config[:SSLVerifyCallback] = lambda{|ok,x509_store|
- p [ok, x509_store.error_string]
- true
-}
-
-DRb.start_service(nil,nil,config)
-h = DRbObject.new(nil, there)
-while line = gets
- p h.hello(line.chomp)
-end
diff --git a/sample/drb/drbssl_s.rb b/sample/drb/drbssl_s.rb
deleted file mode 100644
index 4d96f591d4..0000000000
--- a/sample/drb/drbssl_s.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/usr/bin/env ruby
-
-require 'drb'
-require 'drb/ssl'
-
-here = ARGV.shift || "drbssl://localhost:3456"
-
-class HelloWorld
- include DRbUndumped
-
- def hello(name)
- "Hello, #{name}."
- end
-end
-
-config = Hash.new
-config[:verbose] = true
-begin
- data = open("sample.key"){|io| io.read }
- config[:SSLPrivateKey] = OpenSSL::PKey::RSA.new(data)
- data = open("sample.crt"){|io| io.read }
- config[:SSLCertificate] = OpenSSL::X509::Certificate.new(data)
-rescue
- $stderr.puts "Switching to use self-signed certificate"
- config[:SSLCertName] =
- [ ["C","JP"], ["O","Foo.DRuby.Org"], ["CN", "Sample"] ]
-end
-
-DRb.start_service(here, HelloWorld.new, config)
-puts DRb.uri
-DRb.thread.join
diff --git a/sample/drb/extserv_test.rb b/sample/drb/extserv_test.rb
deleted file mode 100644
index 2c4f485dc6..0000000000
--- a/sample/drb/extserv_test.rb
+++ /dev/null
@@ -1,80 +0,0 @@
-=begin
- dRuby sample
- Copyright (c) 2000 Masatoshi SEKI
-
-= How to play
-
-* Terminal 1
-
- % ruby -I. extserv_test.rb server
- druby://yourhost:12345
-
-* Terminal 2
-
- % ruby -I. extserv_test.rb druby://yourhost:12345
- ...
-
-=end
-
-require 'drb/drb'
-
-def ARGV.shift
- it = super()
- raise "usage:\nserver: #{$0} server [<uri>]\nclient: #{$0} [quit] <uri>" unless it
- it
-end
-
-class Foo
- include DRbUndumped
-
- def initialize(str)
- @str = str
- end
-
- def hello(it)
- "#{it}: #{self}"
- end
-
- def to_s
- @str
- end
-end
-
-cmd = ARGV.shift
-case cmd
-when 'itest1', 'itest2'
- require 'drb/extserv'
-
- front = Foo.new(cmd)
- server = DRb::DRbServer.new(nil, front)
- es = DRb::ExtServ.new(ARGV.shift, ARGV.shift, server)
- server.thread.join
-
-when 'server'
- require 'drb/extservm'
-
- DRb::ExtServManager.command['itest1'] = "ruby -I. #{$0} itest1"
- DRb::ExtServManager.command['itest2'] = "ruby -I. #{$0} itest2"
-
- s = DRb::ExtServManager.new
- DRb.start_service(ARGV.shift, s)
- puts DRb.uri
- DRb.thread.join
-
-
-else
- uri = (cmd == 'quit') ? ARGV.shift : cmd
-
- DRb.start_service
- s = DRbObject.new(nil, uri)
- t1 = s.service('itest1').front
- puts t1
- t2 = s.service('itest2').front
- puts t2
- puts t1.hello(t2)
- if (cmd == 'quit')
- s.service('itest1').stop_service
- s.service('itest2').stop_service
- end
-end
-
diff --git a/sample/drb/gw_ct.rb b/sample/drb/gw_ct.rb
deleted file mode 100644
index 0622784018..0000000000
--- a/sample/drb/gw_ct.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-require 'drb/drb'
-
-class Foo
- include DRbUndumped
-
- def foo(n)
- n + n
- end
-
- def bar(n)
- yield(n) + yield(n)
- end
-end
-
-DRb.start_service(nil)
-puts DRb.uri
-
-ro = DRbObject.new(nil, ARGV.shift)
-ro[:tcp] = Foo.new
-gets
-
-it = ro[:unix]
-p [it, it.foo(1)]
-gets
-
-p it.bar('2') {|n| n * 3}
-gets
-
-
diff --git a/sample/drb/gw_cu.rb b/sample/drb/gw_cu.rb
deleted file mode 100644
index 8079cbdc4f..0000000000
--- a/sample/drb/gw_cu.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-require 'drb/drb'
-require 'drb/unix'
-
-class Foo
- include DRbUndumped
-
- def foo(n)
- n + n
- end
-
- def bar(n)
- yield(n) + yield(n)
- end
-end
-
-DRb.start_service('drbunix:', nil)
-puts DRb.uri
-
-ro = DRbObject.new(nil, ARGV.shift)
-ro[:unix] = Foo.new
-gets
-
-it = ro[:tcp]
-p [it, it.foo(1)]
-gets
-
-p it.bar('2') {|n| n * 3}
-gets
diff --git a/sample/drb/gw_s.rb b/sample/drb/gw_s.rb
deleted file mode 100644
index c2bea0baad..0000000000
--- a/sample/drb/gw_s.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-require 'drb/drb'
-require 'drb/unix'
-require 'drb/gw'
-
-DRb.install_id_conv(DRb::GWIdConv.new)
-gw = DRb::GW.new
-s1 = DRb::DRbServer.new(ARGV.shift, gw)
-s2 = DRb::DRbServer.new(ARGV.shift, gw)
-s1.thread.join
-s2.thread.join
diff --git a/sample/drb/holderc.rb b/sample/drb/holderc.rb
deleted file mode 100644
index e627916d76..0000000000
--- a/sample/drb/holderc.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-require 'drb/drb'
-
-begin
- there = ARGV.shift || raise
-rescue
- $stderr.puts("usage: #{$0} <server_uri>")
- exit 1
-end
-
-DRb.start_service()
-ro = DRbObject.new(nil, there)
-
-ary = []
-10.times do
- ary.push(ro.gen)
-end
-
-sleep 5 if $DEBUG
-
-ary.each do |e|
- p e.sample([1])
-end
diff --git a/sample/drb/holders.rb b/sample/drb/holders.rb
deleted file mode 100644
index 293426faa5..0000000000
--- a/sample/drb/holders.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-=begin
-= How to play.
-
-== with timeridconv:
- % ruby -d holders.rb
- druby://yourhost:1234
-
- % ruby holderc.rb druby://yourhost:1234
-
-
-== without timeridconv:
- % ruby holders.rb
- druby://yourhost:1234
-
- % ruby holderc.rb druby://yourhost:1234
-=end
-
-
-require 'drb/drb'
-
-class DRbEx3
- include DRbUndumped
-
- def initialize(n)
- @v = n
- end
-
- def sample(list)
- sum = 0
- list.each do |e|
- sum += e.to_i
- end
- @v * sum
- end
-end
-
-class DRbEx4
- include DRbUndumped
-
- def initialize
- @curr = 1
- end
-
- def gen
- begin
- @curr += 1
- DRbEx3.new(@curr)
- ensure
- GC.start
- end
- end
-end
-
-if __FILE__ == $0
- if $DEBUG
- require 'drb/timeridconv'
- DRb.install_id_conv(DRb::TimerIdConv.new(2))
- end
-
- DRb.start_service(nil, DRbEx4.new)
- puts DRb.uri
- DRb.thread.join
-end
diff --git a/sample/drb/http0.rb b/sample/drb/http0.rb
deleted file mode 100644
index e40d810311..0000000000
--- a/sample/drb/http0.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-require 'drb/drb'
-require 'net/http'
-require 'uri'
-
-module DRb
- module HTTP0
- class StrStream
- def initialize(str='')
- @buf = str
- end
- attr_reader :buf
-
- def read(n)
- begin
- return @buf[0,n]
- ensure
- @buf[0,n] = ''
- end
- end
-
- def write(s)
- @buf.concat s
- end
- end
-
- def self.uri_option(uri, config)
- return uri, nil
- end
-
- def self.open(uri, config)
- unless /^http:/ =~ uri
- raise(DRbBadScheme, uri) unless uri =~ /^http:/
- raise(DRbBadURI, 'can\'t parse uri:' + uri)
- end
- ClientSide.new(uri, config)
- end
-
- class ClientSide
- def initialize(uri, config)
- @uri = uri
- @res = nil
- @config = config
- @msg = DRbMessage.new(config)
- @proxy = ENV['HTTP_PROXY']
- end
-
- def close; end
- def alive?; false; end
-
- def send_request(ref, msg_id, *arg, &b)
- stream = StrStream.new
- @msg.send_request(stream, ref, msg_id, *arg, &b)
- @reply_stream = StrStream.new
- post(@uri, stream.buf)
- end
-
- def recv_reply
- @msg.recv_reply(@reply_stream)
- end
-
- def post(url, data)
- it = URI.parse(url)
- path = [(it.path=='' ? '/' : it.path), it.query].compact.join('?')
- http = Net::HTTP.new(it.host, it.port)
- sio = StrStream.new
- http.post(path, data, {'Content-Type'=>'application/octetstream;'}) do |str|
- sio.write(str)
- if @config[:load_limit] < sio.buf.size
- raise TypeError, 'too large packet'
- end
- end
- @reply_stream = sio
- end
- end
- end
- DRbProtocol.add_protocol(HTTP0)
-end
diff --git a/sample/drb/http0serv.rb b/sample/drb/http0serv.rb
deleted file mode 100644
index 2e853312e1..0000000000
--- a/sample/drb/http0serv.rb
+++ /dev/null
@@ -1,120 +0,0 @@
-require 'webrick'
-require 'drb/drb'
-require_relative 'http0'
-
-module DRb
- module HTTP0
-
- def self.open_server(uri, config)
- unless /^http:/ =~ uri
- raise(DRbBadScheme, uri) unless uri =~ /^http:/
- raise(DRbBadURI, 'can\'t parse uri:' + uri)
- end
- Server.new(uri, config)
- end
-
- class Callback < WEBrick::HTTPServlet::AbstractServlet
- def initialize(config, drb)
- @config = config
- @drb = drb
- @queue = Thread::Queue.new
- end
-
- def do_POST(req, res)
- @req = req
- @res = res
- @drb.push(self)
- @res.body = @queue.pop
- @res['content-type'] = 'application/octet-stream;'
- end
-
- def req_body
- @req.body
- end
-
- def reply(body)
- @queue.push(body)
- end
-
- def close
- @queue.push('')
- end
- end
-
- class Server
- def initialize(uri, config)
- @uri = uri
- @config = config
- @queue = Thread::Queue.new
- setup_webrick(uri)
- end
- attr_reader :uri
-
- def close
- @server.shutdown if @server
- @server = nil
- end
-
- def push(callback)
- @queue.push(callback)
- end
-
- def accept
- client = @queue.pop
- ServerSide.new(uri, client, @config)
- end
-
- def setup_webrick(uri)
- logger = WEBrick::Log::new($stderr, WEBrick::Log::FATAL)
- u = URI.parse(uri)
- s = WEBrick::HTTPServer.new(:Port => u.port,
- :AddressFamily => Socket::AF_INET,
- :BindAddress => u.host,
- :Logger => logger,
- :ServerType => Thread)
- s.mount(u.path, Callback, self)
- @server = s
- s.start
- end
- end
-
- class ServerSide
- def initialize(uri, callback, config)
- @uri = uri
- @callback = callback
- @config = config
- @msg = DRbMessage.new(@config)
- @req_stream = StrStream.new(@callback.req_body)
- end
- attr_reader :uri
-
- def close
- @callback.close if @callback
- @callback = nil
- end
-
- def alive?; false; end
-
- def recv_request
- begin
- @msg.recv_request(@req_stream)
- rescue
- close
- raise $!
- end
- end
-
- def send_reply(succ, result)
- begin
- return unless @callback
- stream = StrStream.new
- @msg.send_reply(stream, succ, result)
- @callback.reply(stream.buf)
- rescue
- close
- raise $!
- end
- end
- end
- end
-end
diff --git a/sample/drb/name.rb b/sample/drb/name.rb
deleted file mode 100644
index 6d88186dab..0000000000
--- a/sample/drb/name.rb
+++ /dev/null
@@ -1,117 +0,0 @@
-=begin
- distributed Ruby --- NamedObject Sample
- Copyright (c) 2000-2001 Masatoshi SEKI
-=end
-
-=begin
-How to play.
-
-* start server
- Terminal 1
- | % ruby name.rb druby://yourhost:7640
- | druby://yourhost:7640
- | [return] to exit
-
-* start client
- Terminal 2
- | % ruby namec.rb druby://yourhost:7640
- | #<DRb::DRbObject:0x40164174 @uri="druby://yourhost:7640", @ref="seq">
- | #<DRb::DRbObject:0x40163c9c @uri="druby://yourhost:7640", @ref="mutex">
- | 1
- | 2
- | [return] to continue
-
-* restart server
- Terminal 1
- type [return]
- | % ruby name.rb druby://yourhost:7640
- | druby://yourhost:7640
- | [return] to exit
-
-* continue client
- Terminal 2
- type [return]
- | 1
- | 2
-=end
-
-require 'drb/drb'
-
-module DRbNamedObject
- DRbNAMEDICT = {}
- DRBNAMEMUTEX = Thread::Mutex.new
- attr_reader(:drb_name)
-
- def drb_name=(name)
- @drb_name = name
- DRBNAMEMUTEX.synchronize do
- raise(IndexError, name) if DRbNAMEDICT[name]
- DRbNAMEDICT[name] = self
- end
- end
-end
-
-class DRbNamedIdConv < DRb::DRbIdConv
- def initialize
- @dict = DRbNamedObject::DRbNAMEDICT
- end
-
- def to_obj(ref)
- @dict.fetch(ref) do super end
- end
-
- def to_id(obj)
- if obj.kind_of? DRbNamedObject
- return obj.drb_name
- else
- return super
- end
- end
-end
-
-class Seq
- include DRbUndumped
- include DRbNamedObject
-
- def initialize(v, name)
- @counter = v
- @mutex = Thread::Mutex.new
- self.drb_name = name
- end
-
- def next_value
- @mutex.synchronize do
- @counter += 1
- return @counter
- end
- end
-end
-
-class Front
- def initialize
- seq = Seq.new(0, 'seq')
- mutex = Thread::Mutex.new
- mutex.extend(DRbUndumped)
- mutex.extend(DRbNamedObject)
- mutex.drb_name = 'mutex'
- @name = {}
- @name['seq'] = seq
- @name['mutex'] = mutex
- end
-
- def [](k)
- @name[k]
- end
-end
-
-if __FILE__ == $0
- uri = ARGV.shift
-
- name_conv = DRbNamedIdConv.new
-
- DRb.install_id_conv(name_conv)
- DRb.start_service(uri, Front.new)
- puts DRb.uri
- DRb.thread.join
-end
-
diff --git a/sample/drb/namec.rb b/sample/drb/namec.rb
deleted file mode 100644
index 98b9d0e532..0000000000
--- a/sample/drb/namec.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-=begin
- distributed Ruby --- NamedObject Sample Client
- Copyright (c) 2000-2001 Masatoshi SEKI
-=end
-
-require 'drb/drb'
-
-begin
- there = ARGV.shift || raise
-rescue
- puts "usage: #{$0} <server_uri>"
- exit 1
-end
-
-DRb.start_service()
-ro = DRbObject.new(nil, there)
-
-seq = ro["seq"]
-mutex = ro["mutex"]
-
-p seq
-p mutex
-
-mutex.synchronize do
- p seq.next_value
- p seq.next_value
-end
-
-puts '[return] to continue'
-gets
-
-mutex.synchronize do
- p seq.next_value
- p seq.next_value
-end
-
diff --git a/sample/drb/old_tuplespace.rb b/sample/drb/old_tuplespace.rb
deleted file mode 100644
index 2d5310086e..0000000000
--- a/sample/drb/old_tuplespace.rb
+++ /dev/null
@@ -1,212 +0,0 @@
-#!/usr/local/bin/ruby
-# TupleSpace
-# Copyright (c) 1999-2000 Masatoshi SEKI
-# You can redistribute it and/or modify it under the same terms as Ruby.
-
-class TupleSpace
- class Template
- def initialize(list)
- @list = list
- @check_idx = []
- @list.each_with_index do |x, i|
- @check_idx.push i if x
- end
- @size = @list.size
- end
-
- attr :size
- alias length size
-
- def match(tuple)
- return nil if tuple.size != self.size
- @check_idx.each do |i|
- unless @list[i] === tuple[i]
- return false
- end
- end
- return true
- end
- end
-
- def initialize
- @que = {}
- @waiting = {}
- @que.taint # enable tainted communication
- @waiting.taint
- self.taint
- end
-
- def wakeup_waiting(tuple)
- sz = tuple.length
- return nil unless @waiting[sz]
-
- x = nil
- i = -1
- found = false
- @waiting[sz] = @waiting[sz].find_all { |x|
- if x[0].match(tuple)
- begin
- x[1].wakeup
- rescue ThreadError
- end
- false
- else
- true
- end
- }
- end
-
- def put_waiting(template, thread)
- sz = template.length
- @waiting[sz] = [] unless @waiting[sz]
- @waiting[sz].push([Template.new(template), thread])
- end
- private :wakeup_waiting
- private :put_waiting
-
- def get_que(template)
- sz = template.length
- return nil unless @que[sz]
-
- template = Template.new(template)
-
- x = nil
- i = -1
- found = false
- @que[sz].each_with_index do |x, i|
- if template.match(x)
- found = true
- break
- end
- end
- return nil unless found
-
- @que[sz].delete_at(i)
-
- return x
- end
-
- def put_que(tuple)
- sz = tuple.length
- @que[sz] = [] unless @que[sz]
- @que[sz].push tuple
- end
- private :get_que
- private :put_que
-
- def out(*tuples)
- tuples.each do |tuple|
- Thread.critical = true
- put_que(tuple)
- wakeup_waiting(tuple)
- Thread.critical = false
- end
- end
- alias put out
- alias write out
-
- def in(template, non_block=false)
- begin
- loop do
- Thread.critical = true
- tuple = get_que(template)
- unless tuple
- if non_block
- raise ThreadError, "queue empty"
- end
- put_waiting(template, Thread.current)
- Thread.stop
- else
- return tuple
- end
- end
- ensure
- Thread.critical = false
- end
- end
- alias get in
- alias take in
-
- def rd(template, non_block=false)
- tuple = self.in(template, non_block)
- out(tuple)
- tuple
- end
- alias read rd
-
- def mv(dest, template, non_block=false)
- tuple = self.in(template, non_block)
- begin
- dest.out(tuple)
- rescue
- self.out(tuple)
- end
- end
- alias move mv
-end
-
-if __FILE__ == $0
- ts = TupleSpace.new
- clients = []
- servers = []
-
- def server(ts, id)
- Thread.start {
- loop do
- req = ts.in(['req', nil, nil])
- ac = req[1]
- num = req[2]
- sleep id
- ts.out([ac, id, num, num * num])
- end
- }
- end
-
- def client(ts, n)
- Thread.start {
- ac = Object.new
- tuples = (1..10).collect { |i|
- ['req', ac, i * 10 + n]
- }
- ts.out(*tuples)
- ts.out(tuples[0])
- puts "out: #{n}"
- 11.times do |i|
- ans = ts.in([ac, nil, nil, nil])
- puts "client(#{n}) server(#{ans[1]}) #{ans[2]} #{ans[3]}"
- end
- }
- end
-
- def watcher(ts)
- Thread.start {
- loop do
- begin
- sleep 1
- p ts.rd(['req', nil, nil], true)
- rescue ThreadError
- puts "'req' not found."
- end
- end
- }
- end
-
- (0..3).each do |n|
- servers.push(server(ts, n))
- end
-
- (1..6).each do |n|
- clients.push(client(ts, n))
- end
-
- (1..3).each do
- watcher(ts)
- end
-
- clients.each do |t|
- t.join
- end
-end
-
-
-
diff --git a/sample/drb/rinda_ts.rb b/sample/drb/rinda_ts.rb
deleted file mode 100644
index 6f2fae5c0f..0000000000
--- a/sample/drb/rinda_ts.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-require 'drb/drb'
-require 'rinda/tuplespace'
-
-uri = ARGV.shift
-DRb.start_service(uri, Rinda::TupleSpace.new)
-puts DRb.uri
-DRb.thread.join
diff --git a/sample/drb/rindac.rb b/sample/drb/rindac.rb
deleted file mode 100644
index 72be09deaf..0000000000
--- a/sample/drb/rindac.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-require 'drb/drb'
-require 'rinda/rinda'
-
-uri = ARGV.shift || raise("usage: #{$0} <server_uri>")
-
-DRb.start_service
-ts = Rinda::TupleSpaceProxy.new(DRbObject.new(nil, uri))
-
-(1..10).each do |n|
- ts.write(['sum', DRb.uri, n])
-end
-
-(1..10).each do |n|
- ans = ts.take(['ans', DRb.uri, n, nil])
- p [ans[2], ans[3]]
-end
-
diff --git a/sample/drb/rindas.rb b/sample/drb/rindas.rb
deleted file mode 100644
index 9fd9ada2d1..0000000000
--- a/sample/drb/rindas.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require 'drb/drb'
-require 'rinda/rinda'
-
-def do_it(v)
- puts "do_it(#{v})"
- v + v
-end
-
-uri = ARGV.shift || raise("usage: #{$0} <server_uri>")
-
-DRb.start_service
-ts = Rinda::TupleSpaceProxy.new(DRbObject.new(nil, uri))
-
-while true
- r = ts.take(['sum', nil, nil])
- v = do_it(r[2])
- ts.write(['ans', r[1], r[2], v])
-end
diff --git a/sample/drb/ring_echo.rb b/sample/drb/ring_echo.rb
deleted file mode 100644
index c54628b54c..0000000000
--- a/sample/drb/ring_echo.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-require 'drb/drb'
-require 'drb/eq'
-require 'rinda/ring'
-
-class RingEcho
- include DRbUndumped
- def initialize(name)
- @name = name
- end
-
- def echo(str)
- "#{@name}: #{str}"
- end
-end
-
-DRb.start_service
-
-renewer = Rinda::SimpleRenewer.new
-
-finder = Rinda::RingFinger.new
-ts = finder.lookup_ring_any
-ts.read_all([:name, :RingEcho, nil, nil]).each do |tuple|
- p tuple[2]
- puts tuple[2].echo('Hello, World') rescue nil
-end
-ts.write([:name, :RingEcho, RingEcho.new(DRb.uri), ''], renewer)
-
-DRb.thread.join
-
diff --git a/sample/drb/ring_inspect.rb b/sample/drb/ring_inspect.rb
deleted file mode 100644
index c096cd7034..0000000000
--- a/sample/drb/ring_inspect.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-require 'rinda/ring'
-require 'drb/drb'
-
-class Inspector
- def initialize
- end
-
- def primary
- Rinda::RingFinger.primary
- end
-
- def list_place
- Rinda::RingFinger.to_a
- end
-
- def list(idx = -1)
- if idx < 0
- ts = primary
- else
- ts = list_place[idx]
- raise "RingNotFound" unless ts
- end
- ts.read_all([:name, nil, nil, nil])
- end
-end
-
-def main
- DRb.start_service
- r = Inspector.new
-end
diff --git a/sample/drb/ring_place.rb b/sample/drb/ring_place.rb
deleted file mode 100644
index 11c6c2fe80..0000000000
--- a/sample/drb/ring_place.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-require 'drb/drb'
-require 'rinda/ring'
-require 'rinda/tuplespace'
-
-unless $DEBUG
- # Run as a daemon...
- exit!( 0 ) if fork
- Process.setsid
- exit!( 0 ) if fork
-end
-
-DRb.start_service(ARGV.shift)
-
-ts = Rinda::TupleSpace.new
-place = Rinda::RingServer.new(ts)
-
-if $DEBUG
- puts DRb.uri
- DRb.thread.join
-else
- STDIN.reopen(IO::NULL)
- STDOUT.reopen(IO::NULL, 'w')
- STDERR.reopen(IO::NULL, 'w')
- DRb.thread.join
-end
diff --git a/sample/drb/simpletuple.rb b/sample/drb/simpletuple.rb
deleted file mode 100644
index 4bb4b1cff9..0000000000
--- a/sample/drb/simpletuple.rb
+++ /dev/null
@@ -1,89 +0,0 @@
-#!/usr/local/bin/ruby
-# SimpleTupleSpace
-# Copyright (c) 1999-2000 Masatoshi SEKI
-# You can redistribute it and/or modify it under the same terms as Ruby.
-
-class SimpleTupleSpace
- def initialize
- @hash = {}
- @waiting = {}
- @hash.taint
- @waiting.taint
- self.taint
- end
-
- def out(key, obj)
- Thread.critical = true
- @hash[key] ||= []
- @waiting[key] ||= []
- @hash[key].push obj
- begin
- t = @waiting[key].shift
- @waiting.delete(key) if @waiting[key].length == 0
- t.wakeup if t
- rescue ThreadError
- retry
- ensure
- Thread.critical = false
- end
- end
-
- def in(key)
- Thread.critical = true
- @hash[key] ||= []
- @waiting[key] ||= []
- begin
- loop do
- if @hash[key].length == 0
- @waiting[key].push Thread.current
- Thread.stop
- else
- return @hash[key].shift
- end
- end
- ensure
- @hash.delete(key) if @hash[key].length == 0
- Thread.critical = false
- end
- end
-end
-
-if __FILE__ == $0
- ts = SimpleTupleSpace.new
- clients = []
- servers = []
-
- def server(ts)
- Thread.start {
- loop do
- req = ts.in('req')
- ac = req[0]
- num = req[1]
- ts.out(ac, num * num)
- end
- }
- end
-
- def client(ts, n)
- Thread.start {
- ac = Object.new
- ts.out('req', [ac, n])
- ans = ts.in(ac)
- puts "#{n}: #{ans}"
- }
- end
-
- 3.times do
- servers.push(server(ts))
- end
-
- (1..6).each do |n|
- clients.push(client(ts, n))
- end
-
- clients.each do |t|
- t.join
- end
-end
-
-
diff --git a/sample/drb/speedc.rb b/sample/drb/speedc.rb
deleted file mode 100644
index 64b8a65021..0000000000
--- a/sample/drb/speedc.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/usr/local/bin/ruby
-
-uri = ARGV.shift || raise("usage: #{$0} URI")
-N = (ARGV.shift || 100).to_i
-
-case uri
-when /^tcpromp:/, /^unixromp:/
- require 'romp'
-
- client = ROMP::Client.new(uri, false)
- foo = client.resolve("foo")
-when /^druby:/
- require 'drb/drb'
-
- DRb.start_service
- foo = DRbObject.new(nil, uri)
-end
-
-N.times do |n|
- foo.foo(n)
-end
diff --git a/sample/drb/speeds.rb b/sample/drb/speeds.rb
deleted file mode 100644
index 7984059423..0000000000
--- a/sample/drb/speeds.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-class Foo
- attr_reader :i
- def initialize
- @i = 0
- end
-
- def foo(i)
- @i = i
- i + i
- end
-end
-
-# server = ROMP::Server.new('tcpromp://localhost:4242', nil, true)
-
-uri = ARGV.shift || raise("usage: #{$0} URI")
-foo = Foo.new
-
-case uri
-when /^tcpromp:/, /^unixromp:/
- require 'romp'
-
- server = ROMP::Server.new(uri, nil, true)
- server.bind(foo, "foo")
-
-when /^druby:/
- require 'drb/drb'
-
- DRb.start_service(uri, Foo.new)
-end
-
-DRb.thread.join
diff --git a/sample/openssl/c_rehash.rb b/sample/openssl/c_rehash.rb
index de4b66e902..8b005bbb84 100644
--- a/sample/openssl/c_rehash.rb
+++ b/sample/openssl/c_rehash.rb
@@ -156,7 +156,7 @@ private
end
def hash_name(name)
- sprintf("%x", name.hash)
+ sprintf("%08x", name.hash)
end
def fingerprint(der)
diff --git a/sample/prism/find_calls.rb b/sample/prism/find_calls.rb
new file mode 100644
index 0000000000..30af56c719
--- /dev/null
+++ b/sample/prism/find_calls.rb
@@ -0,0 +1,105 @@
+# This script finds calls to a specific method with a certain keyword parameter
+# within a given source file.
+
+require "prism"
+require "pp"
+
+# For deprecation or refactoring purposes, it's often useful to find all of the
+# places that call a specific method with a specific k eyword parameter. This is
+# easily accomplished with a visitor such as this one.
+class QuxParameterVisitor < Prism::Visitor
+ def initialize(calls)
+ @calls = calls
+ end
+
+ def visit_call_node(node)
+ @calls << node if qux?(node)
+ super
+ end
+
+ private
+
+ def qux?(node)
+ # All nodes implement pattern matching, so you can use the `in` operator to
+ # pull out all of their individual fields. As you can see by this extensive
+ # pattern match, this is quite a powerful feature.
+ node in {
+ # This checks that the receiver is the constant Qux or the constant path
+ # ::Qux. We are assuming relative constants are fine in this case.
+ receiver: (
+ Prism::ConstantReadNode[name: :Qux] |
+ Prism::ConstantPathNode[parent: nil, name: :Qux]
+ ),
+ # This checks that the name of the method is qux. We purposefully are not
+ # checking the call operator (., ::, or &.) because we want all of them.
+ # In other ASTs, this would be multiple node types, but prism combines
+ # them all into one for convenience.
+ name: :qux,
+ arguments: Prism::ArgumentsNode[
+ # Here we're going to use the "find" pattern to find the keyword hash
+ # node that has the correct key.
+ arguments: [
+ *,
+ Prism::KeywordHashNode[
+ # Here we'll use another "find" pattern to find the key that we are
+ # specifically looking for.
+ elements: [
+ *,
+ # Finally, we can assert against the key itself. Note that we are
+ # not looking at the value of hash pair, because we are only
+ # specifically looking for a key.
+ Prism::AssocNode[key: Prism::SymbolNode[unescaped: "qux"]],
+ *
+ ]
+ ],
+ *
+ ]
+ ]
+ }
+ end
+end
+
+calls = []
+Prism.parse_stream(DATA).value.accept(QuxParameterVisitor.new(calls))
+
+calls.each do |call|
+ print "CallNode "
+ puts PP.pp(call.location, +"")
+ print " "
+ puts call.slice
+end
+
+# =>
+# CallNode (5,6)-(5,29)
+# Qux.qux(222, qux: true)
+# CallNode (9,6)-(9,30)
+# Qux&.qux(333, qux: true)
+# CallNode (20,6)-(20,51)
+# Qux::qux(888, qux: ::Qux.qux(999, qux: true))
+# CallNode (20,25)-(20,50)
+# ::Qux.qux(999, qux: true)
+
+__END__
+module Foo
+ class Bar
+ def baz1
+ Qux.qux(111)
+ Qux.qux(222, qux: true)
+ end
+
+ def baz2
+ Qux&.qux(333, qux: true)
+ Qux&.qux(444)
+ end
+
+ def baz3
+ qux(555, qux: false)
+ 666.qux(666)
+ end
+
+ def baz4
+ Qux::qux(777)
+ Qux::qux(888, qux: ::Qux.qux(999, qux: true))
+ end
+ end
+end
diff --git a/sample/prism/find_comments.rb b/sample/prism/find_comments.rb
new file mode 100644
index 0000000000..6a26cd32b7
--- /dev/null
+++ b/sample/prism/find_comments.rb
@@ -0,0 +1,100 @@
+# This script finds all of the comments within a given source file for a method.
+
+require "prism"
+
+class FindMethodComments < Prism::Visitor
+ def initialize(target, comments, nesting = [])
+ @target = target
+ @comments = comments
+ @nesting = nesting
+ end
+
+ # These visit methods are specific to each class. Defining a visitor allows
+ # you to group functionality that applies to all node types into a single
+ # class. You can find which method corresponds to which node type by looking
+ # at the class name, calling #type on the node, or by looking at the #accept
+ # method definition on the node.
+ def visit_module_node(node)
+ visitor = FindMethodComments.new(@target, @comments, [*@nesting, node.name])
+ node.compact_child_nodes.each { |child| child.accept(visitor) }
+ end
+
+ def visit_class_node(node)
+ # We could keep track of an internal state where we push the class name here
+ # and then pop it after the visit is complete. However, it is often simpler
+ # and cleaner to generate a new visitor instance when the state changes,
+ # because then the state is immutable and it's easier to reason about. This
+ # also provides for more debugging opportunity in the initializer.
+ visitor = FindMethodComments.new(@target, @comments, [*@nesting, node.name])
+ node.compact_child_nodes.each { |child| child.accept(visitor) }
+ end
+
+ def visit_def_node(node)
+ if [*@nesting, node.name] == @target
+ # Comments are always attached to locations (either inner locations on a
+ # node like the location of a keyword or the location on the node itself).
+ # Nodes are considered either "leading" or "trailing", which means that
+ # they occur before or after the location, respectively. In this case of
+ # documentation, we only want to consider leading comments. You can also
+ # fetch all of the comments on a location with #comments.
+ @comments.concat(node.location.leading_comments)
+ else
+ super
+ end
+ end
+end
+
+# Most of the time, the concept of "finding" something in the AST can be
+# accomplished either with a queue or with a visitor. In this case we will use a
+# visitor, but a queue would work just as well.
+def find_comments(result, path)
+ target = path.split(/::|#/).map(&:to_sym)
+ comments = []
+
+ result.value.accept(FindMethodComments.new(target, comments))
+ comments
+end
+
+result = Prism.parse_stream(DATA)
+result.attach_comments!
+
+find_comments(result, "Foo#foo").each do |comment|
+ puts comment.inspect
+ puts comment.slice
+end
+
+# =>
+# #<Prism::InlineComment @location=#<Prism::Location @start_offset=205 @length=27 start_line=13>>
+# # This is the documentation
+# #<Prism::InlineComment @location=#<Prism::Location @start_offset=235 @length=21 start_line=14>>
+# # for the foo method.
+
+find_comments(result, "Foo::Bar#bar").each do |comment|
+ puts comment.inspect
+ puts comment.slice
+end
+
+# =>
+# #<Prism::InlineComment @location=#<Prism::Location @start_offset=126 @length=23 start_line=7>>
+# # This is documentation
+# #<Prism::InlineComment @location=#<Prism::Location @start_offset=154 @length=21 start_line=8>>
+# # for the bar method.
+
+__END__
+# This is the documentation
+# for the Foo module.
+module Foo
+ # This is documentation
+ # for the Bar class.
+ class Bar
+ # This is documentation
+ # for the bar method.
+ def bar
+ end
+ end
+
+ # This is the documentation
+ # for the foo method.
+ def foo
+ end
+end
diff --git a/sample/prism/locate_nodes.rb b/sample/prism/locate_nodes.rb
new file mode 100644
index 0000000000..7a51db4367
--- /dev/null
+++ b/sample/prism/locate_nodes.rb
@@ -0,0 +1,84 @@
+# This script locates a set of nodes determined by a line and column (in bytes).
+
+require "prism"
+require "pp"
+
+# This method determines if the given location covers the given line and column.
+# It's important to note that columns (and offsets) in prism are always in
+# bytes. This is because prism supports all 90 source encodings that Ruby
+# supports. You can always retrieve the column (or offset) of a location in
+# other units with other provided APIs, like #start_character_column or
+# #start_code_units_column.
+def covers?(location, line:, column:)
+ start_line = location.start_line
+ end_line = location.end_line
+
+ if start_line == end_line
+ # If the location only spans one line, then we only check if the line
+ # matches and that the column is covered by the column range.
+ line == start_line && (location.start_column...location.end_column).cover?(column)
+ else
+ # Otherwise, we check that it is on the start line and the column is greater
+ # than or equal to the start column, or that it is on the end line and the
+ # column is less than the end column, or that it is between the start and
+ # end lines.
+ (line == start_line && column >= location.start_column) ||
+ (line == end_line && column < location.end_column) ||
+ (line > start_line && line < end_line)
+ end
+end
+
+# This method descends down into the AST whose root is `node` and returns the
+# array of all of the nodes that cover the given line and column.
+def locate(node, line:, column:)
+ queue = [node]
+ result = []
+
+ # We could use a recursive method here instead if we wanted, but it's
+ # important to note that that will not work for ASTs that are nested deeply
+ # enough to cause a stack overflow.
+ while (node = queue.shift)
+ result << node
+
+ # Nodes have `child_nodes` and `compact_child_nodes`. `child_nodes` have
+ # consistent indices but include `nil` for optional fields that are not
+ # present, whereas `compact_child_nodes` has inconsistent indices but does
+ # not include `nil` for optional fields that are not present.
+ node.compact_child_nodes.find do |child|
+ queue << child if covers?(child.location, line: line, column: column)
+ end
+ end
+
+ result
+end
+
+result = Prism.parse_stream(DATA)
+locate(result.value, line: 4, column: 14).each_with_index do |node, index|
+ print " " * index
+ print node.class.name.split("::", 2).last
+ print " "
+ puts PP.pp(node.location, +"")
+end
+
+# =>
+# ProgramNode (1,0)-(7,3)
+# StatementsNode (1,0)-(7,3)
+# ModuleNode (1,0)-(7,3)
+# StatementsNode (2,2)-(6,5)
+# ClassNode (2,2)-(6,5)
+# StatementsNode (3,4)-(5,7)
+# DefNode (3,4)-(5,7)
+# StatementsNode (4,6)-(4,21)
+# CallNode (4,6)-(4,21)
+# CallNode (4,6)-(4,15)
+# ArgumentsNode (4,12)-(4,15)
+# IntegerNode (4,12)-(4,15)
+
+__END__
+module Foo
+ class Bar
+ def baz
+ 111 + 222 + 333
+ end
+ end
+end
diff --git a/sample/prism/make_tags.rb b/sample/prism/make_tags.rb
new file mode 100644
index 0000000000..dc770ab1b0
--- /dev/null
+++ b/sample/prism/make_tags.rb
@@ -0,0 +1,302 @@
+# This script generates a tags file using Prism to parse the Ruby files.
+
+require "prism"
+
+# This visitor is responsible for visiting the nodes in the AST and generating
+# the appropriate tags. The tags are stored in the entries array as strings.
+class TagsVisitor < Prism::Visitor
+ # This represents an entry in the tags file, which is a tab-separated line. It
+ # houses the logic for how an entry is constructed.
+ class Entry
+ attr_reader :parts
+
+ def initialize(name, filepath, pattern, type)
+ @parts = [name, filepath, pattern, type]
+ end
+
+ def attribute(key, value)
+ parts << "#{key}:#{value}"
+ end
+
+ def attribute_class(nesting, names)
+ return if nesting.empty? && names.length == 1
+ attribute("class", [*nesting, names].flatten.tap(&:pop).join("."))
+ end
+
+ def attribute_inherits(names)
+ attribute("inherits", names.join(".")) if names
+ end
+
+ def to_line
+ parts.join("\t")
+ end
+ end
+
+ private_constant :Entry
+
+ attr_reader :entries, :filepath, :lines, :nesting, :singleton
+
+ # Initialize the visitor with the given parameters. The first three parameters
+ # are constant throughout the visit, while the last two are controlled by the
+ # visitor as it traverses the AST. These are treated as immutable by virtue of
+ # the visit methods constructing new visitors when they need to change.
+ def initialize(entries, filepath, lines, nesting = [], singleton = false)
+ @entries = entries
+ @filepath = filepath
+ @lines = lines
+ @nesting = nesting
+ @singleton = singleton
+ end
+
+ # Visit a method alias node and generate the appropriate tags.
+ #
+ # alias m2 m1
+ #
+ def visit_alias_method_node(node)
+ enter(node.new_name.unescaped.to_sym, node, "a") do |entry|
+ entry.attribute_class(nesting, [nil])
+ end
+
+ super
+ end
+
+ # Visit a method call to attr_reader, attr_writer, or attr_accessor without a
+ # receiver and generate the appropriate tags. Note that this ignores the fact
+ # that these methods could be overridden, which is a limitation of this
+ # script.
+ #
+ # attr_accessor :m1
+ #
+ def visit_call_node(node)
+ if !node.receiver && %i[attr_reader attr_writer attr_accessor].include?(name = node.name)
+ (node.arguments&.arguments || []).grep(Prism::SymbolNode).each do |argument|
+ if name != :attr_writer
+ enter(:"#{argument.unescaped}", argument, singleton ? "F" : "f") do |entry|
+ entry.attribute_class(nesting, [nil])
+ end
+ end
+
+ if name != :attr_reader
+ enter(:"#{argument.unescaped}=", argument, singleton ? "F" : "f") do |entry|
+ entry.attribute_class(nesting, [nil])
+ end
+ end
+ end
+ end
+
+ super
+ end
+
+ # Visit a class node and generate the appropriate tags.
+ #
+ # class C1
+ # end
+ #
+ def visit_class_node(node)
+ if (names = names_for(node.constant_path))
+ enter(names.last, node, "c") do |entry|
+ entry.attribute_class(nesting, names)
+ entry.attribute_inherits(names_for(node.superclass))
+ end
+
+ node.body&.accept(copy_visitor([*nesting, names], singleton))
+ end
+ end
+
+ # Visit a constant path write node and generate the appropriate tags.
+ #
+ # C1::C2 = 1
+ #
+ def visit_constant_path_write_node(node)
+ if (names = names_for(node.target))
+ enter(names.last, node, "C") do |entry|
+ entry.attribute_class(nesting, names)
+ end
+ end
+
+ super
+ end
+
+ # Visit a constant write node and generate the appropriate tags.
+ #
+ # C1 = 1
+ #
+ def visit_constant_write_node(node)
+ enter(node.name, node, "C") do |entry|
+ entry.attribute_class(nesting, [nil])
+ end
+
+ super
+ end
+
+ # Visit a method definition node and generate the appropriate tags.
+ #
+ # def m1; end
+ #
+ def visit_def_node(node)
+ enter(node.name, node, (node.receiver || singleton) ? "F" : "f") do |entry|
+ entry.attribute_class(nesting, [nil])
+ end
+
+ super
+ end
+
+ # Visit a module node and generate the appropriate tags.
+ #
+ # module M1
+ # end
+ #
+ def visit_module_node(node)
+ if (names = names_for(node.constant_path))
+ enter(names.last, node, "m") do |entry|
+ entry.attribute_class(nesting, names)
+ end
+
+ node.body&.accept(copy_visitor([*nesting, names], singleton))
+ end
+ end
+
+ # Visit a singleton class node and generate the appropriate tags.
+ #
+ # class << self
+ # end
+ #
+ def visit_singleton_class_node(node)
+ case node.expression
+ when Prism::SelfNode
+ node.body&.accept(copy_visitor(nesting, true))
+ when Prism::ConstantReadNode, Prism::ConstantPathNode
+ if (names = names_for(node.expression))
+ node.body&.accept(copy_visitor([*nesting, names], true))
+ end
+ else
+ node.body&.accept(copy_visitor([*nesting, nil], true))
+ end
+ end
+
+ private
+
+ # Generate a new visitor with the given dynamic options. The static options
+ # are copied over automatically.
+ def copy_visitor(nesting, singleton)
+ TagsVisitor.new(entries, filepath, lines, nesting, singleton)
+ end
+
+ # Generate a new entry for the given name, node, and type and add it into the
+ # list of entries. The block is used to add additional attributes to the
+ # entry.
+ def enter(name, node, type)
+ line = lines[node.location.start_line - 1].chomp
+ pattern = "/^#{line.gsub("\\", "\\\\\\\\").gsub("/", "\\/")}$/;\""
+
+ entry = Entry.new(name, filepath, pattern, type)
+ yield entry
+
+ entries << entry.to_line
+ end
+
+ # Retrieve the names for the given node. This is used to construct the class
+ # attribute for the tags.
+ def names_for(node)
+ case node
+ when Prism::ConstantPathNode
+ names = names_for(node.parent)
+ return unless names
+
+ names << node.name
+ when Prism::ConstantReadNode
+ [node.name]
+ when Prism::SelfNode
+ [:self]
+ else
+ # dynamic
+ end
+ end
+end
+
+# Parse the Ruby file and visit all of the nodes in the resulting AST. Once all
+# of the nodes have been visited, the entries array should be populated with the
+# tags.
+result = Prism.parse_stream(DATA)
+result.value.accept(TagsVisitor.new(entries = [], __FILE__, result.source.lines))
+
+# Print the tags to STDOUT.
+puts "!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;\" to lines/"
+puts "!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/"
+puts entries.sort
+
+# =>
+# !_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
+# !_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
+# C1 sample/prism/make_tags.rb /^ class C1$/;" c class:M1.M2
+# C2 sample/prism/make_tags.rb /^ class C2 < Object$/;" c class:M1.M2.C1 inherits:Object
+# C6 sample/prism/make_tags.rb /^ C6 = 1$/;" C class:M1
+# C7 sample/prism/make_tags.rb /^ C7 = 2$/;" C class:M1
+# C9 sample/prism/make_tags.rb /^ C8::C9 = 3$/;" C class:M1.C8
+# M1 sample/prism/make_tags.rb /^module M1$/;" m
+# M2 sample/prism/make_tags.rb /^ module M2$/;" m class:M1
+# M4 sample/prism/make_tags.rb /^ module M3::M4$/;" m class:M1.M3
+# M5 sample/prism/make_tags.rb /^ module self::M5$/;" m class:M1.self
+# m1 sample/prism/make_tags.rb /^ def m1; end$/;" f class:M1.M2.C1.C2
+# m10 sample/prism/make_tags.rb /^ attr_accessor :m10, :m11$/;" f class:M1.M3.M4
+# m10= sample/prism/make_tags.rb /^ attr_accessor :m10, :m11$/;" f class:M1.M3.M4
+# m11 sample/prism/make_tags.rb /^ attr_accessor :m10, :m11$/;" f class:M1.M3.M4
+# m11= sample/prism/make_tags.rb /^ attr_accessor :m10, :m11$/;" f class:M1.M3.M4
+# m12 sample/prism/make_tags.rb /^ attr_reader :m12, :m13, :m14$/;" f class:M1.M3.M4
+# m13 sample/prism/make_tags.rb /^ attr_reader :m12, :m13, :m14$/;" f class:M1.M3.M4
+# m14 sample/prism/make_tags.rb /^ attr_reader :m12, :m13, :m14$/;" f class:M1.M3.M4
+# m15= sample/prism/make_tags.rb /^ attr_writer :m15$/;" f class:M1.M3.M4
+# m2 sample/prism/make_tags.rb /^ def m2; end$/;" f class:M1.M2.C1.C2
+# m3 sample/prism/make_tags.rb /^ alias m3 m1$/;" a class:M1.M2.C1.C2
+# m4 sample/prism/make_tags.rb /^ alias :m4 :m2$/;" a class:M1.M2.C1.C2
+# m5 sample/prism/make_tags.rb /^ def self.m5; end$/;" F class:M1.M2.C1.C2
+# m6 sample/prism/make_tags.rb /^ def m6; end$/;" F class:M1.M2.C1.C2
+# m7 sample/prism/make_tags.rb /^ def m7; end$/;" F class:M1.M2.C1.C2.C3
+# m8 sample/prism/make_tags.rb /^ def m8; end$/;" F class:M1.M2.C1.C2.C4.C5
+# m9 sample/prism/make_tags.rb /^ def m9; end$/;" F class:M1.M2.C1.C2.
+
+__END__
+module M1
+ module M2
+ class C1
+ class C2 < Object
+ def m1; end
+ def m2; end
+
+ alias m3 m1
+ alias :m4 :m2
+
+ def self.m5; end
+
+ class << self
+ def m6; end
+ end
+
+ class << C3
+ def m7; end
+ end
+
+ class << C4::C5
+ def m8; end
+ end
+
+ class << c
+ def m9; end
+ end
+ end
+ end
+ end
+
+ module M3::M4
+ attr_accessor :m10, :m11
+ attr_reader :m12, :m13, :m14
+ attr_writer :m15
+ end
+
+ module self::M5
+ end
+
+ C6 = 1
+ C7 = 2
+ C8::C9 = 3
+end
diff --git a/sample/prism/multiplex_constants.rb b/sample/prism/multiplex_constants.rb
new file mode 100644
index 0000000000..e39f2c36f6
--- /dev/null
+++ b/sample/prism/multiplex_constants.rb
@@ -0,0 +1,138 @@
+# This script indexes the classes and modules within a set of files using the
+# saved source functionality.
+
+require "prism"
+require "etc"
+require "tempfile"
+
+module Indexer
+ # A class that implements the #enter functionality so that it can be passed to
+ # the various save* APIs. This effectively bundles up all of the node_id and
+ # field_name pairs so that they can be written back to the parent process.
+ class Repository
+ attr_reader :scope, :entries
+
+ def initialize
+ @scope = []
+ @entries = []
+ end
+
+ def with(next_scope)
+ previous_scope = scope
+ @scope = scope + next_scope
+ yield
+ @scope = previous_scope
+ end
+
+ def empty?
+ entries.empty?
+ end
+
+ def enter(node_id, field_name)
+ entries << [scope.join("::"), node_id, field_name]
+ end
+ end
+
+ # Visit the classes and modules in the AST and save their locations into the
+ # repository.
+ class Visitor < Prism::Visitor
+ attr_reader :repository
+
+ def initialize(repository)
+ @repository = repository
+ end
+
+ def visit_class_node(node)
+ repository.with(node.constant_path.full_name_parts) do
+ node.constant_path.save_location(repository)
+ visit(node.body)
+ end
+ end
+
+ def visit_module_node(node)
+ repository.with(node.constant_path.full_name_parts) do
+ node.constant_path.save_location(repository)
+ visit(node.body)
+ end
+ end
+ end
+
+ # Index the classes and modules within a file. If there are any entries,
+ # return them as a serialized string to the parent process.
+ def self.index(filepath)
+ repository = Repository.new
+ Prism.parse_file(filepath).value.accept(Visitor.new(repository))
+ "#{filepath}|#{repository.entries.join("|")}" unless repository.empty?
+ end
+end
+
+def index_glob(glob, count = Etc.nprocessors - 1)
+ process_ids = []
+ filepath_writers = []
+ index_reader, index_writer = IO.pipe
+
+ # For each number in count, fork off a worker that has access to two pipes.
+ # The first pipe is the index_writer, to which it writes all of the results of
+ # indexing the various files. The second pipe is the filepath_reader, from
+ # which it reads the filepaths that it needs to index.
+ count.times do
+ filepath_reader, filepath_writer = IO.pipe
+
+ process_ids << fork do
+ filepath_writer.close
+ index_reader.close
+
+ while (filepath = filepath_reader.gets(chomp: true))
+ results = Indexer.index(filepath)
+ index_writer.puts(results) if results
+ end
+ end
+
+ filepath_reader.close
+ filepath_writers << filepath_writer
+ end
+
+ index_writer.close
+
+ # In a separate thread, write all of the filepaths to the various worker
+ # processes. This is done in a separate threads since puts will eventually
+ # block when each of the pipe buffers fills up. We write in a round-robin
+ # fashion to the various workers. This could be improved using a work-stealing
+ # algorithm, but is fine if you don't end up having a ton of variety in the
+ # size of your files.
+ writer_thread =
+ Thread.new do
+ Dir[glob].each_with_index do |filepath, index|
+ filepath_writers[index % count].puts(filepath)
+ end
+ end
+
+ index = Hash.new { |hash, key| hash[key] = [] }
+
+ # In a separate thread, read all of the results from the various worker
+ # processes and store them in the index. This is done in a separate thread so
+ # that reads and writes can be interleaved. This is important so that the
+ # index pipe doesn't fill up and block the writer.
+ reader_thread =
+ Thread.new do
+ while (line = index_reader.gets(chomp: true))
+ filepath, *entries = line.split("|")
+ repository = Prism::Relocation.filepath(filepath).filepath.lines.code_unit_columns(Encoding::UTF_16LE).leading_comments
+
+ entries.each_slice(3) do |(name, node_id, field_name)|
+ index[name] << repository.enter(Integer(node_id), field_name.to_sym)
+ end
+ end
+ end
+
+ writer_thread.join
+ filepath_writers.each(&:close)
+
+ reader_thread.join
+ index_reader.close
+
+ process_ids.each { |process_id| Process.wait(process_id) }
+ index
+end
+
+index_glob(File.expand_path("../../lib/**/*.rb", __dir__))
diff --git a/sample/prism/relocate_constants.rb b/sample/prism/relocate_constants.rb
new file mode 100644
index 0000000000..faa48f6388
--- /dev/null
+++ b/sample/prism/relocate_constants.rb
@@ -0,0 +1,43 @@
+# This script finds the declaration of all classes and modules and stores them
+# in a hash for an in-memory database of constants.
+
+require "prism"
+
+class RelocationVisitor < Prism::Visitor
+ attr_reader :index, :repository, :scope
+
+ def initialize(index, repository, scope = [])
+ @index = index
+ @repository = repository
+ @scope = scope
+ end
+
+ def visit_class_node(node)
+ next_scope = scope + node.constant_path.full_name_parts
+ index[next_scope.join("::")] << node.constant_path.save(repository)
+ node.body&.accept(RelocationVisitor.new(index, repository, next_scope))
+ end
+
+ def visit_module_node(node)
+ next_scope = scope + node.constant_path.full_name_parts
+ index[next_scope.join("::")] << node.constant_path.save(repository)
+ node.body&.accept(RelocationVisitor.new(index, repository, next_scope))
+ end
+end
+
+# Create an index that will store a mapping between the names of constants to a
+# list of the locations where they are declared or re-opened.
+index = Hash.new { |hash, key| hash[key] = [] }
+
+# Loop through every file in the lib directory of this repository and parse them
+# with Prism. Then visit them using the RelocateVisitor to store their
+# repository entries in the index.
+Dir[File.expand_path("../../lib/**/*.rb", __dir__)].each do |filepath|
+ repository = Prism::Relocation.filepath(filepath).filepath.lines.code_unit_columns(Encoding::UTF_16LE)
+ Prism.parse_file(filepath).value.accept(RelocationVisitor.new(index, repository))
+end
+
+puts index["Prism::ParametersNode"].map { |entry| "#{entry.filepath}:#{entry.start_line}:#{entry.start_code_units_column}" }
+# =>
+# prism/lib/prism/node.rb:13889:8
+# prism/lib/prism/node_ext.rb:267:8
diff --git a/sample/prism/visit_nodes.rb b/sample/prism/visit_nodes.rb
new file mode 100644
index 0000000000..5ba703b0a3
--- /dev/null
+++ b/sample/prism/visit_nodes.rb
@@ -0,0 +1,63 @@
+# This script visits all of the nodes of a specific type within a given source
+# file. It uses the visitor class to traverse the AST.
+
+require "prism"
+require "pp"
+
+class CaseInsensitiveRegularExpressionVisitor < Prism::Visitor
+ def initialize(regexps)
+ @regexps = regexps
+ end
+
+ # As the visitor is walking the tree, this method will only be called when it
+ # encounters a regular expression node. We can then call any regular
+ # expression -specific APIs. In this case, we are only interested in the
+ # regular expressions that are case-insensitive, which we can retrieve with
+ # the #ignore_case? method.
+ def visit_regular_expression_node(node)
+ @regexps << node if node.ignore_case?
+ super
+ end
+
+ def visit_interpolated_regular_expression_node(node)
+ @regexps << node if node.ignore_case?
+
+ # The default behavior of the visitor is to continue visiting the children
+ # of the node. Because Ruby is so dynamic, it's actually possible for
+ # another regular expression to be interpolated in statements contained
+ # within the #{} contained in this interpolated regular expression node. By
+ # calling `super`, we ensure the visitor will continue. Failing to call
+ # `super` will cause the visitor to stop the traversal of the tree, which
+ # can also be useful in some cases.
+ super
+ end
+end
+
+result = Prism.parse_stream(DATA)
+regexps = []
+
+result.value.accept(CaseInsensitiveRegularExpressionVisitor.new(regexps))
+regexps.each do |node|
+ print node.class.name.split("::", 2).last
+ print " "
+ puts PP.pp(node.location, +"")
+
+ if node.is_a?(Prism::RegularExpressionNode)
+ print " "
+ p node.unescaped
+ end
+end
+
+# =>
+# InterpolatedRegularExpressionNode (3,9)-(3,47)
+# RegularExpressionNode (3,16)-(3,22)
+# "bar"
+# RegularExpressionNode (4,9)-(4,15)
+# "bar"
+
+__END__
+class Foo
+ REG1 = /foo/
+ REG2 = /foo #{/bar/i =~ "" ? "bar" : "baz"}/i
+ REG3 = /bar/i
+end
diff --git a/sample/trick2025/01-omoikane/authors.markdown b/sample/trick2025/01-omoikane/authors.markdown
new file mode 100644
index 0000000000..5c6823c077
--- /dev/null
+++ b/sample/trick2025/01-omoikane/authors.markdown
@@ -0,0 +1,5 @@
+* Don Yang
+ * omoikane@uguu.org
+ * cctld: us
+ * bsky.app/profile/omoikane.bsky.social
+ * twitter.com/uguu_org
diff --git a/sample/trick2025/01-omoikane/bf.rb b/sample/trick2025/01-omoikane/bf.rb
new file mode 100644
index 0000000000..74f5abe7e4
--- /dev/null
+++ b/sample/trick2025/01-omoikane/bf.rb
@@ -0,0 +1,81 @@
+#!/usr/bin/ruby -w
+# Simple BF interpretor.
+#
+# This works by translating input code into ruby and evaluating the
+# translated ruby code. Doing it this way runs much faster than
+# interpreting BF on our own.
+#
+# There is no error reporting whatsoever. A malformed input may result in
+# a syntax error at run time, but good luck in finding where it came from.
+
+
+# Setup empty tape and initial pointer position. Note that tape size is
+# fixed. We can make it infinite by initializing it to "[]" here and
+# adding some nil checks in the generated code, but avoiding those checks
+# makes the program run ~10% faster.
+$code = "t=Array.new(30000,0); p=0;"
+
+# Counters for pending add or shift operations. We buffer incoming +-<>
+# operators and output a single merged operation when we encounter a
+# different operator.
+$buffered_add = 0
+$buffered_shift = 0
+
+# Flush pending add operations, if any.
+def flush_add
+ if $buffered_add != 0
+ $code += "t[p]+=#{$buffered_add};"
+ $buffered_add = 0
+ end
+end
+
+# Flush pending shift operations, if any.
+def flush_shift
+ if $buffered_shift != 0
+ $code += "p+=#{$buffered_shift};"
+ $buffered_shift = 0
+ end
+end
+
+def flush_pending_ops
+ flush_add
+ flush_shift
+end
+
+# Convert input characters to ruby.
+ARGF.each_char{|c|
+ case c
+ when '+'
+ flush_shift
+ $buffered_add += 1
+ when '-'
+ flush_shift
+ $buffered_add -= 1
+ when '<'
+ flush_add
+ $buffered_shift -= 1
+ when '>'
+ flush_add
+ $buffered_shift += 1
+ when ','
+ flush_pending_ops
+ $code += "if c=STDIN.getc;" +
+ "t[p]=c.ord;" +
+ "else;" +
+ "t[p]=-1;" + # EOF is interpreted as -1.
+ "end;"
+ when '.'
+ flush_pending_ops
+ $code += "print t[p].chr;"
+ when '['
+ flush_pending_ops
+ $code += "while t[p]!=0;"
+ when ']'
+ flush_pending_ops
+ $code += "end;"
+ end
+}
+flush_pending_ops
+
+# Evaluate converted code.
+eval $code
diff --git a/sample/trick2025/01-omoikane/entry.rb b/sample/trick2025/01-omoikane/entry.rb
new file mode 100644
index 0000000000..c84f8079ae
--- /dev/null
+++ b/sample/trick2025/01-omoikane/entry.rb
@@ -0,0 +1,32 @@
+ a=+Math::PI/13
+ #Z---z';#za-mRUBY
+ #A-ZaA-Mn--\[+>+>++
+ '"N-Z(\++\[->++++@"
+ b=\[->+> +>+>\[h_
+ p%{} eact
+ zoraq ;%{ GF. rin);
+ %{eb} r A R p *""\]
+ <<<{{{ }<\]<b
+ ]<l(%w| } ; a;a=%Y/
+ evar{|c)} <][ #pgny\W{f
+ chaa,b)]>++[ ->+>>>>>[40v
+ .tr(= ' ;eval(%w{r=u=b= y =0;%{
+ (ct;c ) ; ] <<->--<<< < < ] >>[>,
+ exi}; a * = A RGV.siz e > 0 ? -1:1;
+ z=[] ; A R G F .ea c h _ l i n e{|i
+|i.eac h _ g r aph e m e _ c l u ster
+{|j|i f ( k = j.o r d ) < 3 3 ; r+=k<
+32?k==9? 8 - r%8 : k = = 1 0 | |k==13
+?[u+=1,-r][ 1]: 0 : 1 ; e lse;z+=[[u,
+r,j]];b+=r;y+=u;r+=1;end;}};if(s=z.si
+ze)>0;b/=s;y/=s;m,n=z[0];i=Math::tan(
+a/2);j=Math::sin(a);z.map!{|d|p=d[1]-
+b;q=d[0]-y;p-=(i*q).round;m=[m,q+=(j*
+ p).round].min;n=[n,p-=(i*q).round].
+ min;[q,p,d[2]]};r=n;u=m;z.sort.eac
+ h{|d|p,b=d;r=(u<p)?n:r;print"\n"
+ *(p-u),"\40"*(b-r),d[2];u=p;r=
+ b+1};print"\n";end}*"");%(]>
+ "tyvuts(}}.--.>--.>+.<++'
+ )b\40"gena.(c)2025<<<
+ #)#ehol""+a*.^_^
diff --git a/sample/trick2025/01-omoikane/remarks.markdown b/sample/trick2025/01-omoikane/remarks.markdown
new file mode 100644
index 0000000000..2aa77d64e4
--- /dev/null
+++ b/sample/trick2025/01-omoikane/remarks.markdown
@@ -0,0 +1,71 @@
+### Summary
+
+This is a rot13 filter. Given an input text, it will **rotate** the text by **pi/13** radians. Two modes of operation are available, selected based on number of command line arguments.
+
+Rotate clockwise:
+
+ ruby entry.rb < input.txt
+
+Rotate counterclockwise:
+
+ ruby entry.rb input.txt
+ ruby entry.rb - < input.txt
+
+### Details
+
+This program interprets input as an ASCII art with each character representing individual square pixels, and produces a rotated image to stdout. All non-whitespace characters are preserved in output, only the positions of those characters are adjusted. While all the characters are preserved, the words and sentences will not be as readable in their newly rotated form. This makes the program suitable for obfuscating text.
+
+ ruby entry.rb original.txt > rotated.txt
+ ruby entry.rb < rotated.txt > unrotated.txt
+
+But note that while `unrotated.txt` is often the same as `original.txt`, there is no hard guarantee due to integer rounding intricacies. Whether the original text can be recovered depends a lot on its shape, be sure to check that the output is reversible if you are using this rot13 filter to post spoilers and such.
+
+Reversibility does hold for `entry.rb`:
+
+ ruby entry.rb entry.rb | ruby entry.rb | diff entry.rb -
+ ruby entry.rb < entry.rb | ruby entry.rb - | diff entry.rb -
+
+Also, there is a bit of text embedded in the rotated version:
+
+ ruby entry.rb entry.rb | ruby
+
+But this text is encrypted! No problem, just rotate `entry.rb` the other way for the decryption tool:
+
+ ruby entry.rb < entry.rb > caesar_cipher_shift_13.rb
+ ruby entry.rb entry.rb | ruby | ruby caesar_cipher_shift_13.rb
+
+If current shell is `bash` or `zsh`, this can be done all in one line:
+
+ ruby entry.rb entry.rb | ruby | ruby <(ruby entry.rb < entry.rb)
+
+### Miscellaneous features
+
+To rotate to a different angle, edit the first line of `entry.rb`. Angles between -pi/2 and pi/2 will work best, anything outside that range produces more distortion than rotation, although the output might still be reversible.
+
+Setting angle to zero makes this program a filter that expands tabs, trim whitespaces, and canonicalize end-of-line sequences.
+
+This program preserves non-ASCII characters since input is tokenized with `each_grapheme_cluster`, although all characters that's not an ASCII space/tab/newline are given the same treatment. For example, the full-width space character (U+3000) will be transformed as if it's a half-width non-whitespace ASCII character.
+
+If input contains only whitespace characters, output will be empty.
+
+The layout is meant to resemble a daruma doll. There was still ~119 bytes of space left after fitting in 3 ruby programs, so I embedded a brainfuck program as well.
+
+ ruby bf.rb entry.rb
+
+A `sample_input.txt` has been included for testing. After rotating this file 26 times either clockwise or counterclockwise, you should get back the original `sample_input.txt`.
+
+ ruby entry.rb < sample_input.txt | ruby entry.rb | ruby entry.rb | ruby entry.rb | ruby entry.rb | ruby entry.rb | ruby entry.rb | ruby entry.rb | ruby entry.rb | ruby entry.rb | ruby entry.rb | ruby entry.rb | ruby entry.rb | ruby entry.rb | ruby entry.rb | ruby entry.rb | ruby entry.rb | ruby entry.rb | ruby entry.rb | ruby entry.rb | ruby entry.rb | ruby entry.rb | ruby entry.rb | ruby entry.rb | ruby entry.rb | ruby entry.rb | diff sample_input.txt -
+ ruby entry.rb sample_input.txt | ruby entry.rb - | ruby entry.rb - | ruby entry.rb - | ruby entry.rb - | ruby entry.rb - | ruby entry.rb - | ruby entry.rb - | ruby entry.rb - | ruby entry.rb - | ruby entry.rb - | ruby entry.rb - | ruby entry.rb - | ruby entry.rb - | ruby entry.rb - | ruby entry.rb - | ruby entry.rb - | ruby entry.rb - | ruby entry.rb - | ruby entry.rb - | ruby entry.rb - | ruby entry.rb - | ruby entry.rb - | ruby entry.rb - | ruby entry.rb - | ruby entry.rb - | diff sample_input.txt -
+
+Additional development notes can be found in `spoiler_rot13.txt` (rotate clockwise to decode).
+
+ ruby entry.rb < spoiler_rot13.txt
+
+### Compatibility
+
+Program has been verified to work under these environments:
+
+ * ruby 3.2.2 on cygwin.
+ * ruby 2.5.1p57 on linux.
+ * ruby 2.7.4p191 on linux.
+ * ruby 2.7.1p83 on jslinux.
diff --git a/sample/trick2025/01-omoikane/sample_input.txt b/sample/trick2025/01-omoikane/sample_input.txt
new file mode 100644
index 0000000000..244530f265
--- /dev/null
+++ b/sample/trick2025/01-omoikane/sample_input.txt
@@ -0,0 +1,35 @@
+ T U
+ S V
+
+ R T U W
+ S V
+
+ Q R W X
+
+ Q X
+ P i h g f Y
+ j e
+ P k d Y
+
+ O l c Z
+ O Z
+ m b
+
+* N N n + a A A *
+
+ o z
+ M B
+ M p y B
+
+ L q x C
+ r w
+ L s t u v C
+ K D
+
+ K J E D
+
+ I F
+ J H G E
+
+ I F
+ H G
diff --git a/sample/trick2025/01-omoikane/spoiler_rot13.txt b/sample/trick2025/01-omoikane/spoiler_rot13.txt
new file mode 100644
index 0000000000..91636176b8
--- /dev/null
+++ b/sample/trick2025/01-omoikane/spoiler_rot13.txt
@@ -0,0 +1,470 @@
+ .
+ text
+ ted t to
+ rota tex
+ dit HTML
+ to etes oss
+ sier wri acr
+ t earb"), ions .
+ ke itry. etat text
+ o ma "en erpr tive
+ ge te.g. e int: erna
+ L paut ( tiplsteps alt edit,he
+ a HTM inp muling cted ach dit tu
+ -w tes nt as havellow expe er ely ere yo
+ uby neragume can e fo the aftrect whethis
+ in/rt gee ar hat y th t. has stepindicesshat
+ usr/bcripingl ext tt tr texsult ion to prois w
+#!/his s a s of t migh inale re rotatededis aich ts.
+# TTakest. ece you origf th tra ts neike , wh tex
+ # stdou a piles, the ck i e exemenuld lusly ated the
+ # ite ang s tod che f th movu wotaneo rot pen
+ # To wrrent edit, an se orsort yoimul and nd o ne.
+ # diffe ome tion1-2. ecaue cu Whats s inal t, a en do
+ # ke srotaeps ous be thve. tex orig ayou t wh
+ # 1. Maply t st tediecausuitiated hold he l tex this
+ # 2. Apepea is lt bunint rot to rom ted. ated but
+ # 3. R cessficu is l and ough le fenabl upd nce, in
+ # pro diftextgina e en L fiipt the atie dable
+ # Thisalsoive ori larg HTMascr paste of p reay
+ # and rnat thedes: at's te a jav opy& bit its. t is Rubke },
+ # alteeditrovi t th nerawith en c fair l ed thar ine-li, %w{
+ # can pt p ayou to geser , th h a manua textasiequot %()
+ # scri a l ipt brow page witose ing 's eple %{},
+ # Make scrin a TML textn th writt itulti of ter
+ ## 1. thisTML the H dit ly o lly:l, buas m use Ras t
+ # Run ut H via ly euick ficaiviauby hakestes. eral wan
+ # 2. outp its anualte q peciy trse R.rb m quo Gen nd we
+ # y ed to mitera by sactlecauntryouble for rs a
+ # Appl eed you g Rut exs, b. ele+d ithm acte
+ # 3. ll nlet ardins nouageientsing Algor char paperpplyg
+ # stiill regons ilangnvenmon ast ces: are nal ply ardin
+ # Youol w hingtatither e co com "A Feren els rigi sim regato
+ # to re trienny o quit the on diff r pix . O andailsnter
+ # e mole oo ma areourse asedtwo e ous. tionates detn ce o
+ # Onltiped tthatof c is bith sincalue rotardine toatio is n
+ # mumparors and ithm h, w ls, er v r of coot du rot here ns d
+ # coerat//, lgor Paet pixeract enteinput, but to r, tratio, an.
+ # op{}, on aAlan ing cha ng cthe as isspecion. ente opeinput two
+ # %W tati by blendinal ardiing ues th reunct on ctionthe ne or
+ # e roion" for orig reghift vale witer f tatirota of a li
+ # Thotat ort the tionut snate car_cen e roise hapeextr
+ # R supperve idera aboordixtra get stablockwhe s an ons.
+ # No pres consthingd coed e see ore terclon tting tatiugh
+ # - to nal any-basee neble, a mcoun lot nser e roltho
+ # itio sayto 0ng, wersi tingise/ds a by i oducd, a
+ # Addsn'trms undit rev elecockwepenible ] prstea
+ # - doensfor routpu in se clIt dvers pi/2t in ly to
+ # trategehe o care utivt. e re i/2, tex ical
+ # inke t tra onsecr ou mad [-pt the omat
+ # ma h exat c othen be weenstorible. aut
+ # wite theachon ca beto divers sted
+ # Evenantecel tati glesnd te re adju s.
+ # guar cane ro y ane tell b l be ment
+ # willn th Onlrang sti wil ele
+ # ofte gle.that ight idth text
+ # n anide ion m . W ble erialink
+ atiooutsrmat/ 13 entss. edita les. he scan l
+ Rotles nsfo:PI elemcell all tup . T we
+ # Ang traath: edit ter to eme) textthat
+ # the = M of harac ched graph ate uch her.
+ #NGLE ightre c.9em" atta al, rotD, sh ot
+ A e hesqua= "0 be seri me toue I eac
+ Linure GHT me to x, aphe uniqs to
+ # ens_HEI s na (y, d grme aation
+ #LINE clas "t" t of s anaphe rot
+ yle SS = a lis nateh grrent
+ # St_CLA as ordi eaciffe
+ EDIT nput he cogivess d
+ ad i ed td to acro
+ # Lo y neaddeheme
+ # onl is grap 0
+ # Wemberame put _y = {|c|
+ # nuhe sd_in] ursor ster
+ # t loa = [ = c ine|_clu 8
+ defdataor_x 0 ne{|lheme x %
+ cursal =h_li_grap 1 sor_r\n" ]
+ seri.eaceach= " "x +=" cur= "\ , c]
+ ARGFine. c =rsor_ "\t 8 - c = rial
+ l if cu c ==x +=" || x, se
+ lsifrsor_ "\n0 sor_
+ e cu c ==x = 1 cur
+ lsifrsor_y += r_y, t
+ e cursor_ urso thay
+ cu [[c= 1 ilityed bext.
+ lse ta +=_x +1 obabollowal t
+ e daursor += e pron frigin
+ cerial ass. s thtatihe o
+ s of m easee roin t l be hat
+ end nter incrkwislts wilges thave
+ m ce nter clocresu heret ed We
+ } a fro n cee. a sa) o, taighion.
+ dat nter atio, i.e ver zer strotat
+ } turn n ce rotible vic frome.g.he r ,
+ re tatio s asvers (or away er, er t tione.
+ nd e ro mase retion und cent aftcts: rotaitiv
+ e mput er ofll brota e rotionld betifa o. ox. ftern pos
+ # Co centon wiise ow wrotashouse ar zerng box aemai r
+ # ing tatilockw to hthe hey the d ofunding bon r othey
+ # Use roterc due ear an tduce nsteaf bounditati s atbilittion
+ # thcoun ely, ts nd tho re ty iter of bor ro factersiul op
+ # a unattifacaggegs t fini cenner oafte arti revusef f
+ # forte arore jthin e ino be cor and get theost er or
+ # Unsiblut mious itivon to before we losehe m centr fo
+ # vime o var postation ts be thatlso be t theedito
+ # coried owardf rotatinate e is we a to ause an and the t
+ # t nd tter of roordi thes andpears ll catesaddsm in tha
+ # Rou center ol co of ter,s ap s wienerrts rithd for
+ # - Set cenat al all cen mas cterly guppoalgo neer).
+ # - Seth th with ther of charat onso sion reatithe
+ # - suc ened d ofente. ing script alotat a gol e
+ # happnsteang cacts emovhis r thahe re iss to
+ # hat es i Usirtif nd rhy tditoent tther thi
+ # Wplacure.the a ng ais wan eplemsure for
+ # featite ertiich ave reimnot need
+ # desp t ins, whTo h to am any
+ # thashiftt. need. Ie is
+ # Note to g texill riptther
+ # massacin we wvascure
+ # repltes,ed jaot sa)
+ # deleerat am n(dat ze
+ # genl (Ienter ta.si
+ # tooet_cy = 0t| / da
+ #ef g = cach{|1] cy
+ d cxta.e+= t[0] ize,
+ da cx += t[ ta.s es.
+ cy / da inat
+ n cx oorda)
+ } etur to ccy, .
+ r ion cx, 2) gain
+ end rotatta, (a / X a
+ ply te(da:tan(a) | r in
+ # AprotaMath::sinp{|tnts. shea
+ def x = Math:a.maonte then
+ ry = n dater c cx Y,
+ retur Cent1] - cy r in me).
+ r # = t[0] - shead aphe eme.
+ x = t[ X, round , gr graph
+ y r in y).round erial ach
+ Shearx * x).roun x, s nd e
+ # -= (ry * y). (y, arou
+ x += (rx * ted ] pan
+ y -= ( updat[3] ne s
+ x urn 2], ith o
+ # Ret, t[ xt wfix)
+ [y, x L te_pre
+ HTM, id
+ } k ofdata0] n
+ d blocock(ata[ ].min
+ en rate e_bl = d t[1]].mi
+ Geneneratin_xt| _x, t[0]
+ # f ge_y, mch{|[min_y,
+ de minta.eax = [min >\n"
+ da min_y = ix}\"
+ min_ x pref
+ min_y {id_
+ } x = min_=\"# r_y)
+ rsor_y = e id{|t| curso
+ cursor_"<preach y -
+ cuxt = ort.t < y * (
+ teata.sx = or_y"\n"
+ d y, curs += = yin_x
+ if textor_y = m
+ cursor_x
+ curs [3] &" "
+ = t== "amp;"
+ end textext = "&= "<
+ ner_er_text xt =lt;"" ' +
+ in inner_tr_te= "&= "> '">
+ if inninneext xt =gt;" SS +_s +
+ sif er_tr_te= "& x) +_CLA].to
+ el inninneext rsor_EDIT t[2
+ sif er_t - cu"' + ix +
+ el inn (x ass=_pref
+ d " *n cl+ id low.
+ en += "<spa="' t + er be
+ ext '" id_tex numb
+ t 'nneran>" ial ns.
+ i</sp+ 1 ser colum
+ "= x re>" next. by
+ r_x n</p the airs them
+ urso + "\ find er p oup
+ c ext er, numbta) d gr
+ } rn t numbrialap(das an
+ retu ial f sewn_my row
+ nd serst or_dors b
+ e eacha liursoumbe
+ For rns te_cal n ]]
+ # Retuneraseri} |t| ] [t[2
+ #ef geort = {ach{t[1]] += ]
+ d # Sumnsrt.emns[t[1] [t[2]
+ cola.socolumns[ ] = n.
+ dat if colu t[1] olum 0]]) .
+ e mns[ ch c [r[ ight
+ elscolu or ea 1] + he r by
+ rs f e - to t sortnext
+ end umbe .siz mber we the
+ al n r| [1, r l nu o if us
+ } seri [] |_, ip(r eria s, s get
+ Add ls =ach{ r.z xt s inateould )
+ # erians.es += e ners. oordhat w [0]]
+ solumrial s d th pai n) c1, t ials
+ c se rial , finmberta) olum by [ser a
+ n se mberal nup(daw, cials 1] + extr
+ }etur l nuseriht_ma (ro ser e - one
+ r eria of _rig with all .siz get
+ end ch slistrsortartotate [2]}ials . e we ,'
+ r eas a e_cues snd r t| t ser airs sinc + '"
+ # Foturnerattuples a. map{|s[1, ue p) ine, o_s
+ # Re genput tuplbersort.erial valairsnewl 1].t
+ def# Input numta.sip(s keyal_ping + t[
+ # inrial= dals.z s asserirail efix
+ # seals eria pairix, ut t + pr
+ serirn s mber(prefitho "'
+ retu l nu_mapies wate. '":
+ eriarsorentrtempl|t| _s +
+ end at st_cumap the .map{].to
+ Formnverate rom airs+ t[0
+ # f coenerne fal_pfix
+ de # Gewliseri pre es.
+ # nurn "' + valu
+ ret' " nate
+ "\n ordi
+ } * f co) a[0]
+ d ge odata dat
+ en ranize(_x =
+ Getet_s minn_x
+ #ef gn_y,= min_y min 1
+ d mix_x = mi|t| , x].max y +
+ max_y ach{t in_x, x].min min_
+ mata.ex = = [max_x, y].max y -
+ da y, n_x = [min_y, y]. max_
+ mix_x = [max_y 1,
+ man_y = [m n_x +
+ mix_y - mi
+ ma x_x
+ n ma
+ }etur
+ r ut
+ end _inp
+ loadty? ) a) GLE)) /td>
+ a = .emp (data(dat -ANNGLE ")}< >
+ datdatarn nter_size cy,y, A d> r> , "Ltd> }</td
+ if retu t_ce get cx,x, c /hea "><tdata)}</"R")
+ = geht = data,a, c le>< ng="4eft_ "M"ta,
+ end cy heig ate(e(dat /tit addiock(lata,t_da
+ cx,th, rototat est< ellpe_block(drigh
+ wid ta = = r te t 1" cerate_bllock(
+ t_dadata >Rota ng="{generatte_b l>
+ lefght_ OT" itle pacip">#{gennera labe
+ ri <<"Ed><t cells="top">##{ge le)</
+ int <hea "1" align="toop"> "> togg or
+ prtml> der=t" valignn="t edit to l> errght,
+ <hody> bor"left" vvalig id="(ESC"><u izes-hei
+ <bableign="lefft" ox" dit nonet. minimline
+ <td align=="le heckble elay: tex hat sing
+ <td allignble>e="c>Enabdisplace . ne tcreap.
+ <ttd a</ta typdit"yle=" repor. anel he oy deerla
+ </tr>nputr="e" sters =cursct p ep tis bo ov
+ <p><il fohelpractmove sele nd keo thes t
+ <labeid=" chas = ab = s, also d lin
+ <div SCII keyft+to. "> aluean ae the ;
+ <li>Arrow shi und riptng vWe ccaus ght)
+ <li>Aab /+Z = vascpacio. ill tHei
+ <li>TCtrliv> xt/jaer-sratich wM");; offse
+ <<li>></d ="te lettect o muId("HT}" / p.
+ </ul typerentd aspt tontByHEIG dth
+ ipt iffesireg thalemeINE_ etWi
+ <scrry de deasin.getE"#{L 2) offs
+ // To thecrementht = 0.0 - p.
+ // tut ddocuHeig x += em";ght}
+ // bp = line= 0; 2; .0; + "{hei
+ var yle.t_x or =x < 2 = x / #
+ p.st bes_err 0; cingdth}
+ var min x = erSpa#{wi
+ var(var lett.abs( )
+ for yle.Mathr > e
+ { p.ste = erro ; ;
+ var min_ r = e"em"
+ if( erro x + t_x;); }";
+ { min__x = bes("L"IGHT
+ best ng =ByIdE_HE
+ Spaciment{LINt_x;"); T}";
+ } tteretEle= "# besd("REIGH
+ e.lent.gight ng =tByINE_H;
+ } stylcumeneHeSpaciemen#{LIst_x
+ p.= doe.littergetEl = "= be
+ p style.leent.eighting
+ p.stylocumineHrSpac ta))}
+ p. = dle.lette e; t_da }
+ p.style.l tate.fals . (lefa))}ata))
+ p.sty le sit = tion ns. _map(datht_d
+ p itabe_ed posi itio down_map(rig
+ / Wrnabl rsor ; pos rsor_down_map )}
+ /ar e t cu "M0" rsor e_cursor_down data)
+ v rrenor = t cu erate_cursor_ eft_)} ))}
+ / Cucurs o nex generate_cu ap(lata)_data
+ /var ng t "L", generat ht_map(dight
+ appi = map("M", gen _right_map(r
+ // Mdown rsor_map("R", ursor_right_m
+ var t_cursor_map( te_cursor_rig
+ { nvert_cursor_ nerate_cursor
+ #{convert_cu , generate_c
+ #{conver ("L", genera rs.
+ #{co ht = _map("M", ge ) pai
+ }; rig ursor_map("R" text
+ var rt_cursor_map nal
+ { onvert_cursor rigi
+ #{convert_c x, o n))
+ #{conve uffi . (dow
+ #{c (id s []; ions tries
+ }; of ist = osit t.en )
+ Listdo_l or p bjec ght)
+ // r un curs of O s(ri
+ va erse}; ue] ntrie
+ Rev = { {}; val ct.e
+ //r upft =[key, Obje
+ var lenst key; of
+ var(co e] = lue]
+ fo valu , va on.
+ { up[ [key ey; siti
+ onst = k e po ;
+ }or(c alue] . e sam tyle;
+ f ft[v okes$/; t th = style;
+ { le ystr!-~] rs a tyle = style
+ ed ke /^[ actele) x).style = s
+ } cepteys = char sty suffix).style
+ / AcditK for (id, (1);" + suffix).s
+ /ar e tyle tyle bstrd("L" + suffi
+ v et s setS d.sutById("M" +
+ // Stion = iementById("R .
+ func uffixetElementByI tion
+ { ar sent.getElemen posi
+ vocument.getEl n. sor
+ document.g itio s cur . 0";
+ docum posd) viou tion ff808
+ d rsoror(i pre posi nd:# ;
+ } te cuCurs t at rsor ); grou xt])
+ Updan set ligh""); w cu f80"back erTe
+ // ctio highor, t ne :#80f = " .inn
+ fun lear curs ht a oundstyle ion. fix)
+ { // Ctyle( hlig ckgrid). osit suf
+ setS hig "bayId( me p "M" +t;
+ pdate id;sor,entB at sa yId(= text;
+ // Usor =(curElem ers entBext = text;
+ curStyle.get ractxt) ElemnerText = tex
+ setument cha, te .get).innerText
+ doc fort(id 1); umentffix).innerT
+ texteTex str( doc + suffix).in
+ } lace plac .subfix,("L" + suffix
+ Repon re = id[sufById("M" + su
+ //ncti fix ush(mentById("R"
+ fu r sufst.ptElementById
+ { vado_lit.getElement
+ uncument.getEle
+ document.ge it. [1];
+ documen t ed ) ntry[1];
+ do ecen = 0 t = entry[1];
+ st r() th = rText = entry
+ } do moundo leng innerText = e
+ / Untion ist. ); ix).innerTex
+ /func do_l pop( suffix).inne
+ { f( un ist. L" + suffix).
+ i urn; do_l[0];Id("M" + suff
+ { ret = unntryntById("R" +
+ try = elementById("
+ }ar enffixgetElementBy x);
+ var suent.getEleme suffi
+ vdocument.getEit ) ] +
+ document.e_ed or[0
+ documnabl curs ";
+ if( e sor( line
+ { tCur "in
+ se us. lay =
+ } statt() it; disp
+ dit _edi e_ed yle. ;
+ } ge eggle nabl ).st one"
+ Chann to = !e) elp" = "n
+ //nctio dit dit ; Id("h play ;
+ fu le_ele_e sor)ntBy .dis edit
+ { enabenab (curleme tyle able_ )
+ if( rsorgetE ").s = en S}")
+ { etCuent. ; help ked CLAS
+ socum "")yId(" chec DIT_
+ d sor,entB t"). ("#{E
+ } e (curElem ("edi Name
+ els tyle.get ById lass
+ { setSment ment sByC {
+ docu tEle ment =>
+ t.ge s. etEle ent)
+ } umen enernt.g (ev
+ doc listcume ick",
+ ent f do ("cl
+ } d ev t o ener ) => {
+ // Adonst Listedit nt) ) )
+ for(c ventble_ id); (eve "Z"
+ { addE ena r(t. n", y ==
+ t. if( urso ydow t.ke
+ { setC r("ke even
+ tene ||
+ } tLis) e" ) = "z"
+ ); Evendit Escap ey =
+ } .addle_e == " nt.k ) )
+ } mentenab key (eve "Z"
+ docuf( ! ent. (); && y ==
+ i ( ev edit rlKey t.ke
+ { if gle_ t.ct even
+ { tog even " ||
+ if( = "z
+ }lse ; ey =
+ e do() nt.k
+ { un (eve
+ n; y && s) )
+ }etur rlKe tKey
+ r t.ct (edi );
+ } even match .key
+ if( (); key. vent
+ { undo ent. or, er]); )
+ ( ev curscurso wUp" e" )
+ } e if ext(ght[ Arro spac
+ els aceTr(ri == " Back
+ { replurso .key ); n" ) == "
+ setC vent rsor] wDow key
+ f( e p[cu Arro vent. )
+ } se i or(u == " || e " "
+ el Curs .key r]); ft" ==
+ { set vent curso owLe .key
+ f( e own[ "Arr event
+ } se i or(d y == ; || M"}
+ el Curs t.ke or]) ght" ": "L"};
+ { set even [curs owRi , "R": "
+ if( left "Arr "L", "R
+ } lse sor( y == ); "M": "R"
+ e tCur t.ke sor] "R", "M":;
+ { se even t[cur b" ) L": "M", r(1)
+ if( righ "Ta ? {"L": subst
+ }lse sor( ey == Key : {"sor.
+ e tCur nt.k hift cur {
+ { se eve ent.s ]] + ) =>
+ if( = ev or[0 vent
+ }else ext [curs " ) , (e
+ { ar n nextsor); cape ick"
+ v r = (cur "Es ("cl
+ ursorsor ey == ener
+ cetCu nt.k tList
+ s eve ); Even
+ } if( dit( (); .add
+ else le_e fault it")
+ { togg ntDe ("ed
+ reve tById
+ } nt.p emen
+ eve etEl();
+ ; nt.gedit
+ })cumegle_
+ do tog
+ ; pt> >
+ })scri html
+ </ y></
+ /bod
+ <OT
+ E
diff --git a/sample/trick2025/02-mame/authors.markdown b/sample/trick2025/02-mame/authors.markdown
new file mode 100644
index 0000000000..0e420fdf5d
--- /dev/null
+++ b/sample/trick2025/02-mame/authors.markdown
@@ -0,0 +1,3 @@
+* Yusuke Endoh
+ * mame@ruby-lang.org
+ * cctld: jp
diff --git a/sample/trick2025/02-mame/entry.rb b/sample/trick2025/02-mame/entry.rb
new file mode 100644
index 0000000000..d5de370dc9
--- /dev/null
+++ b/sample/trick2025/02-mame/entry.rb
@@ -0,0 +1,34 @@
+From:pd <pd-@example.com> (`)
+Date:Wed,01 Jan 2025 00:00:00 +0000
+Subject:[PATCH] +an(/.{40}/));exit].gsub(/X.*X|\n(\h+\s)?\+?/,E=""))#TRICK2025]}
+
+--- /dev/null
++++ pd.rb
+@@ -0,0 +1,27 @@
++%;`);;BEGIN{eval$s=%q[eval(%q[F=File;puts((dup)?(q="%;`);;BEGIN
++{eval$s=%q[#$s]}";U,*,V=R=(0..33.0).map{|t|q.gsub(/./){i=$`.siz
++e;c=(i/64*2i-26i+i%64-31)*1i**(t/16.5);x,y=c.rect;r=c.abs;r<13?
++4<=r&&r<6&&x>-4||-5<x&&x<=-3&&-6<y&&y<11??.:?X:$&}};B,A="---|%s
++\n+++|%s\n@@|-%s,%s|+%s,%s|@@\nFrom:pd|<pd-@example.com>|(`)\nD
++ate:%a,%d|%b|%Y|%T|%z\nSubject:[PATCH]|".tr(?|,z="\s")[/@.*\n/]
++,$`;(i=R.index(q))?(S,T=i<33?R[i,(f=->i{(Time.gm(2025)+86400*i)
++.strftime$'};o=f[i+1]+(fXXXXXXXXXXXXXXX[0]+q[/.*\z/]+?\n*2+A%["
++/dev/null",v="pd.rb"]+XXXXXXXXXXXXXXXXXXXB%[0,0,1,27]+U.gsub(/^
++/,?+)).lines[-i-2],EXXXXXXXXXXXXXXXXXXXXXXX,a=A%[v,v];V<<"\n(`\
++n#{a+B%[0,0,1,1]}+dXXXXXXXXXXXXXXXXXXXXXXXXXup=(`)";2)]:($*.siz
++e!=2&&abort(["usagXXXXXXXXX.........XXXXXXXXXe:",$0,F,F]*z);$*.
++map{o=A%$*;F.read(XXXXXXXXX..XXXXXX..XXXXXXXX_1)});a=[i=0]*v=(s
++=[s]+S.lines).sizeXXXXXXXXX..XXXXXX..XXXXXXXX;c=b=s.map{c=_1&&[
++c,?-+_1,i+=1]||0};XXXXXXXXX..XXXXXX..XXXXXXXXT.lines{|t|s.map{|
++s|a<<((s)?[x=a[-1]XXXXXXXXX.........XXXXXXXXX,y=a[-v]].max+((f=
++s==t)?1:0):0);c,d=(XXXXXXXX..XXXXXXXXXXXXXXXf)?[v+1,z+t]:s&&(x>
++y)?[1,?-+s]:[v,?++t]XXXXXXX..XXXXXXXXXXXXXX;b<<[b[-c],d,i+=1]}}
++;c=b[-1].flatten;b=c[(XXXXX..XXXXXXXXXXXX1..)%2];(b.map{_1[0]}*
++E).scan(/\s{,3}([-+]\s{,XXXXXXXXXXXXXXX6})*[-+]\s{,3}/){n=c[2*i
++=$`.size];o=o,B%[n%v+1-1/v,(m=c[2.*i+j=$&.size]-n)%v,T>""?n/v+1
++:0,m/v],b[i,j]}):(o=[];a,b=[A,B].map{_1.sub(?+){'\+'}%(['(\S+)'
++]*4)};$<.read=~//;F.write$2,(s=F.readlines$1;o<<[:patching,F,$2
++]*z;(*,n,i,m=[*$~].map{_1.to_i};n+=m;($'=~/\A((-)|\+)?(.*\n)/;$
++2?s[i-=1,1]=[]:$1?s[i-1,0]=$3:n-=1;i+=1;n-=1)while+n>0)while/\A
++#{b}/=~$';s*E)while$'=~/^#{a}/);o):([*[?l]*799,1].shuffle*E).sc
++an(/.{40}/));exit].gsub(/X.*X|\n(\h+\s)?\+?/,E=""))#TRICK2025]}
diff --git a/sample/trick2025/02-mame/remarks.markdown b/sample/trick2025/02-mame/remarks.markdown
new file mode 100644
index 0000000000..8be86ebc2d
--- /dev/null
+++ b/sample/trick2025/02-mame/remarks.markdown
@@ -0,0 +1,141 @@
+# A Lesser "Patch" Program
+
+This program is a minimalistic version of the traditional "patch" command, which looks like a patch.
+
+## Usage as a "Patch" Command
+
+The program reads a unified diff file from standard input and applies the changes to the specified files.
+
+To apply `test.patch` to `sample.rb`, use the following commands:
+
+```
+$ cp sample.orig.rb sample.rb
+$ ruby entry.rb < test.patch
+```
+
+After running these commands, verify that `sample.rb` has been modified.
+
+## Usage as a Patch File
+
+Interestingly, this program is not just a patch-like tools -- it *is* a patch.
+This duality allows it to be applied like a regular patch file.
+
+The following will create a file named pd.rb.
+
+```
+$ patch < entry.rb
+```
+
+Alternatively, you can achieve the same result using `entry.rb`:
+
+```
+$ ruby entry.rb < entry.rb
+```
+
+The generated `pd.rb` produces a new patch.
+
+```
+$ ruby pd.rb
+```
+
+The produced patch is self-referential, targeting `pd.rb` itself.
+To apply it:
+
+```
+$ ruby pd.rb | ruby entry.rb
+```
+
+You'll notice the `p` logo rotates slightly counterclockwise.
+
+The modified `pd.rb` outputs the patch for itself again, apply the patch repeatedly--a total of 33 times!
+
+## From `p` to `d`
+
+The center `p` logo symbolizes a "patch."
+When rotated 180 degrees, it resembles a `d`, signifying a transformation in functionality.
+`pd.rb` now operates as a simplified "diff" command:
+
+```
+$ ruby pd.rb
+usage: pd.rb File File
+
+$ ruby pd.rb sample.orig.rb sample.rb
+--- sample.orig.rb
++++ sample.rb
+...
+```
+
+## Integration with Git
+
+The patches are compatible with Git's `git am` command, which imports patches in mbox format.
+
+Start fresh by removing `pd.rb` and initializing a Git repository:
+
+```
+$ rm -f pd.rb
+$ git init
+Initialized empty Git repository in /home/...
+```
+
+And import `entry.rb` as a patch to the repository:
+
+```
+$ git am --committer-date-is-author-date entry.rb
+Applying: +(/.{40}/));exit].gsub(/X.*X|\n(\h+\s)?\+?/,E=""))#_TRICK2025_]}
+applying to an empty history
+```
+
+Verify the commit history:
+
+```
+$ git log
+commit 1e32693f11c1df77bd797c7b3e9f108a3e139824 (HEAD -> main)
+Author: pd (`) <pd-@example.com>
+Date: Wed Jan 1 00:00:00 2025 +0000
+
+ +an(/.{40}/));exit].gsub(/X.*X|\n(\h+\s)?\+?/,E=""))#TRICK2025]}
+```
+
+Notice that the Author and Date are properly set.
+
+To apply subsequent patches:
+
+```
+$ for i in `seq 0 32`; do ruby pd.rb | git am --committer-date-is-author-date; done
+```
+
+*(A fun details: you will see the `b` logo!)*
+
+Now, view a commit history by the following command:
+
+```
+$ git log --oneline
+```
+
+You will rediscover the original `entry.rb` unexpectedly.
+
+If you set `--committer-date-is-author-date` appropriately, you should be able to run the output of `git log --oneline` as is.
+
+Try this unusual command:
+
+```
+$ git log --oneline | ruby - test.patch
+```
+
+## A Little Something Extra
+
+Interestingly, `pd.rb` -- functioning as a diff command -- is a patch to itself.
+Reveal hidden details with:
+
+```
+$ ruby entry.rb pd.rb
+$ ruby pd.rb
+```
+
+Can you spot the difference?
+
+## Limitations
+
+* I tested it with ruby 3.3.6, git 2.45.2, and GNU patch 2.7.6.
+* No error check at all. The lesser patch do not care if there is a discrepancy between what is written in the patch and the input file, and will write over the existing file without prompt.
+* It is assumed that the text files have a new line at the end.
diff --git a/sample/trick2025/02-mame/sample.orig.rb b/sample/trick2025/02-mame/sample.orig.rb
new file mode 100644
index 0000000000..3d880b387d
--- /dev/null
+++ b/sample/trick2025/02-mame/sample.orig.rb
@@ -0,0 +1,8 @@
+def add(a, b)
+ a + b
+end
+
+if __FILE__ == $0
+ result = add(3, 5)
+ puts "Three plus five is #{ result }"
+end
diff --git a/sample/trick2025/02-mame/test.patch b/sample/trick2025/02-mame/test.patch
new file mode 100644
index 0000000000..0a63ae8a4c
--- /dev/null
+++ b/sample/trick2025/02-mame/test.patch
@@ -0,0 +1,16 @@
+--- sample.rb
++++ sample.rb
+@@ -2,7 +2,13 @@
+ a + b
+ end
+
++def sub(a, b)
++ a - b
++end
++
+ if __FILE__ == $0
+ result = add(3, 5)
+ puts "Three plus five is #{ result }"
++ result = sub(5, 3)
++ puts "five minus three is #{ result }"
+ end
diff --git a/sample/trick2025/03-tompng/authors.markdown b/sample/trick2025/03-tompng/authors.markdown
new file mode 100644
index 0000000000..26ebe24da6
--- /dev/null
+++ b/sample/trick2025/03-tompng/authors.markdown
@@ -0,0 +1,3 @@
+* Tomoya Ishida (tompng)
+ * tomoyapenguin@gmail.com
+ * cctld: jp
diff --git a/sample/trick2025/03-tompng/entry.rb b/sample/trick2025/03-tompng/entry.rb
new file mode 100644
index 0000000000..0de2244979
--- /dev/null
+++ b/sample/trick2025/03-tompng/entry.rb
@@ -0,0 +1,74 @@
+eval->{%w[u=*? a..?i;l=*?j..? r;o=*?s..?z,?_
+;m='#-*&|^`!@$ '.chars;s=[[3] ,[0,1,3,4,6],[
+1,5],[1,4],[0, 4,6],[2,4],[2] ,[1,3,4,6],[],
+ [4], ];a= (0.. 7).m ap{[
+ ?;*_ 1+'a 4',: a1,? x*(_
+ 1+2) ]*"T /#{? x.*6 7-_1
+ }/x; "};v =([c =[?x *150
+ ]*4, a.reverse,[[6, 3,0].map{"a#{_
+ 1}T/ #{?x*15}/x"}*( ?;*42)+';xx']*
+ 30,a .map{_1.tr'14' ,'25'},c,]*n=$
+ /).g sub( /(^| ;)(;
+ *);/ ){$1 +?x* $2.s
+ ize+ ?;}; p,e= [0,1
+ ].ma p{|t |g=( ["(m
+ fT/' /;#{a=(0..9).m ap{"f#{_1}T/l#
+ {_1} =1./"}*?;};C"' ;#{a.tr'l',?u}
+ ;?C" ",(0..9).map{| i|a="l#{i}T/'/
+
+
+;C"' ;";b ="#{o[i-1]+?=i fTi>0}%+";(1..
+9).m ap{a <<l[_1-1]+"T/% #{c=m[_1]}/;";
+b<<c +";# {(d=_1+i)>10?' ca='+o[d-11]:d
+>9?' ca': o[d- 1]}=
+%"+c };a+ b+[m [1..
+],?+ ,?"] *';? '},"
+caT/ '/;C "';" +(1.
+.8).map{u[8-_1 ]+"T/#{u[9-_1] }=1./;"}*''+u[
+0]+h='=1;?"',( 1..9).map{|i|" u#{i}T/'/;C"';
+"+(0..8-i).map {u[8-i-_1]+"T/ #{u[8-_1]}=1./
+ ;"}* ''+u [i-1 ]+h}
+ ]*?; ).sp lit( /([^
+ ;]+; )/); ((0. .43)
+ .map {|y| c='' ;q=-
+ >{a= (y-22).abs;b=( c.size+_1-78).
+ abs; [a<7&&b<59||b< 15,(b-30).abs<
+ 14][ t]};110.times{ c+=q[8]?g.shif
+
+
+ t||? ;:q[-t]??;:'T' };c.gsub(';T',
+ 'TT' ).rstrip}*n).g sub(/(;|T)(;;+
+ )(;| $)/){$1+'/'+?x *($2.size-2)+'
+ /'+$ 3}}; F=Fi
+ le;1 0.ti mes{
+ |i|a ="(n fT/m
+ f=l# {i}= '/;n
+ f=f# {i}=?';def/("+ s[i].map!{"a#{
+ _1}" }*','+')=(';F. write"#{i}",a+
+ ?x*( 150-a.size)+n+ v[..-5]+'))&&'
+ +n}; a,*b ="/)
+ &&de f((C nCn<
+ <A"; c=") )./(
+ ";d= 'T}' ,?A,
+ '__= <<B';u.map{|v| b<<v+"TT%(T<<#
+ {v}T )TT";d=d,v,"AC n#{v}=<<B"};o.
+ zip( l,m){a+=?;+_1+ "T/%#{_3}/";c+
+
+
+=(_3[?#]||?#+_
+3)+"))./("+_2+
+?,};F.write'+'
+,n*2 6+[p [..-
+10]+ (a+c ).tr ('!@',%("')).g
+sub( /%([ '"`] )/,){$1},'#{TT
+T'+b *';T T'+d *n,?B,')=']*n+
+n;a, b=[u ,o].map{|v|(0.
+.8). map{ t=s[9-_1];t[0]
+&&t+ =[1] ;v[8-_1]+"T/#{
+t*?= }#/" }*?; +';a3='+?x*25}
+;F.w rite '=', [n*26]*2*e+a+n
++v+n +(b+ n+v) .tr(?a,?b)[..-
+9]+' )if~ exit
+'+n].join.tr('
+TRICK',_1)}[+"
+\x2025"<<-?\\]
diff --git a/sample/trick2025/03-tompng/remarks.markdown b/sample/trick2025/03-tompng/remarks.markdown
new file mode 100644
index 0000000000..7f3f4ac6cf
--- /dev/null
+++ b/sample/trick2025/03-tompng/remarks.markdown
@@ -0,0 +1,146 @@
+### Remarks
+
+Run it with no argument. It will generate 12 files: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + and =.
+
+```sh
+ruby entry.rb
+```
+
+Concat and syntax highlight them.
+
+```sh
+cat 2 0 + 2 5 = | ruby -run -e colorize
+cat 4 + 1 5 + 4 + 1 8 = | ruby -run -e colorize
+```
+
+I confirmed the following implementations/platforms:
+
+* ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +YJIT +MN +PRISM [arm64-darwin22]
+* ruby 3.3.0 (2023-12-25 revision 5124f9ac75) +YJIT +MN [arm64-darwin22]
+
+### Description
+
+Did you know that Ruby syntax can perform additive operations on two-digit numbers without Ruby runtime? This entry demonstrates a syntax level computation of Ruby grammar.
+
+`ruby entry.rb` will generate 12 files: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + and =.
+These files constitute a calculator system that runs on Ruby parser.
+
+To calculate `6 + 7`, concat `6`, `+`, `7` and `=`.
+
+```sh
+cat 6 + 7 =
+```
+
+The concatenated output is a Ruby script that does nothing. It is also an ASCII art of `█ + █ = ██` rotated 90 degrees.
+Now, let's try syntax highlighting that code.
+
+```sh
+cat 6 + 7 = | ruby -run -e colorize
+```
+
+Wow! You can see the calculation result `6 + 7 = 13` as a colorized ASCII art!
+
+This system can also add more than two numbers. All numbers should be one or two digits, and the answer should be less than 100.
+
+```sh
+cat 3 1 + 4 + 1 5 + 9 = | ruby -run -e colorize
+cat 1 + 2 + 4 + 8 + 1 6 + 3 2 = | ruby -run -e colorize
+cat 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 1 0 = | ruby -run -e colorize
+```
+
+If the syntax highlighting is hard to see, use this command to change the terminal color.
+
+```sh
+printf "\e]11;#000000\a\e]10;#333333\a\e]4;1;#ffaaaa\a"
+```
+
+### Internals
+
+To perform calculation, you need a storage and a control flow statement.
+Local variable existence can be used as a storage.
+Ruby syntax provides conditional local variable definition and local variable reset with state carry over which can be used as a control flow statement.
+
+#### Conditional Local Variable Definition
+
+Ruby syntax can define new local variables conditionally.
+
+```ruby
+# Defines x and y if a is defined
+a /x = y = 1./
+# Defines x and y if a is not defined
+a /1#/; x = y = 1
+# Defines x or y depend on the existence of local variable a
+a /(x=1);'/;(y=1);?'
+```
+
+#### Local Variables Reset
+
+Local variables can be cleared by creating a new `def` scope.
+
+```ruby
+x = y = z = 1
+def f
+# x, y, z are cleared
+```
+
+#### State Carry Over
+
+Some state should be carried over to the next `def` scope. There are two tricks to do it.
+
+```ruby
+a /%+/i; b /%-/i; def f(x)# +; def f(y) # -; def f(z)
+```
+
+```ruby
+a %(<<A); b %(<<B); def f
+x=<<C
+A
+y=<<C
+B
+z=<<C
+C
+```
+
+In both examples above, local variable defined in the new scope will be:
+
+```ruby
+x # if both a and b are not defined
+y # if a is defined
+z # if b is defined
+```
+
+Combining these two tricks, Ruby syntax can carry over two states to the next `def` scope. In this system, two states represents upper digit and lower digit.
+
+### File Structure
+
+```ruby
+# File 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
+(code) &&
+```
+
+```ruby
+# File +
+(code) && def f(arg)=
+```
+
+```ruby
+# File =
+(code) if exit
+```
+
+```ruby
+# cat 1 2 + 3 + 4 5 =
+(one) &&
+(two) &&
+(plus) && def f(arg)=
+(three) &&
+(plus) && def f(arg)=
+(four) &&
+(five) &&
+(equal) if exit
+```
+
+### Limitation
+
+Number to be added must be one or two digits.
+Answer of the addition must be less than 100.
diff --git a/sample/trick2025/04-tompng/authors.markdown b/sample/trick2025/04-tompng/authors.markdown
new file mode 100644
index 0000000000..26ebe24da6
--- /dev/null
+++ b/sample/trick2025/04-tompng/authors.markdown
@@ -0,0 +1,3 @@
+* Tomoya Ishida (tompng)
+ * tomoyapenguin@gmail.com
+ * cctld: jp
diff --git a/sample/trick2025/04-tompng/entry.rb b/sample/trick2025/04-tompng/entry.rb
new file mode 100644
index 0000000000..881c1af871
--- /dev/null
+++ b/sample/trick2025/04-tompng/entry.rb
@@ -0,0 +1,36 @@
+ $c=%q@E="
+ \e[4%d;37m%s\e[m"
+ ;n=32.chr;pu ts"\e
+ [H\e[J#{$c=n*54+' $c=%
+ q'+[64.chr]*2*$c+';e val$
+ c.'+n*10+"\n"+n*57+"spl it*'
+ '"+n*15}";n=l=0;R=->y=0 {n+=1
+ ;l=$c.lines. map{|m|m=(0..79).chunk{380-n+
+ 36*Math.sin(0.04.*it-n )<9*y}.map{a=_2.map{m[it]}*''
+ ;_1&&E%[6,a]||a}*'';m!=l[~-y +=1]&&$><<"\e[#{y}H#{m}\e[37H
+ ";m}};N=(Integer$* [-1]resc ue+30)*H=44100;alias:r:rand
+ ;F=->e,w=1{a=b=c=0;d=( 1-e)**0 .5*20;->v=r-0.5{a=a*w*e+v
+ ;b=b*w*e*e+v;d.*a-2*b+c=c*w *e**3+ v}};A=->u,n,t{(0..n).
+ map{|i|u=u.shuffle.map{|w|R[]; a=u.s ample;b,c,d=[[0.5
+ ,(0.2+r)*H/3*1.1**i,[[1+r/10,1+r/ 10]][ i]||[1.2+
+ r/10,1.3+r/5]],[0.3,r*H/2,[1,1+r/5 ]]][t
+];e,f=d.shuffle;g=b+r;h=b+r;(0..[w. size/e, a.size/f
++c].max).map{g*(w[it*e]||0)+h*(a[[it-c,0].ma x*f]||0)}}}};j=A[A
+[(0..9).map{a=F[0.998,1i**0.02];(0..28097).m ap{a[].real.*0.1**(8.0*i
+t/H)-8e-6}},14,0].transpose.map{|d|a=[0]*3e3 ;15.times{|i|R [];b=r
+ (3e3);d[i].each_with_index{a[c=_2+b]=(a[c] ||0)+_1*0.63**i}} ;a},9,
+ 1][4..].flatten(1).shuffle;y=(0..3).map{F[ 1-1e-5]};m=[-1,1].map {[F[1
+ -1e-4],F[1-5e-5],it]};u=v=w=0;k=[],[],[] ;z=F[0.7,1i**0.5];File.o pen($
+ *.grep(/[^\d]/)[0]||'output.wav','wb') {|f|f<<'RIFF'+[N*4+36,'WA VEfmt
+ ',32,16,1,2,H,H*4,4,16,'data',N*4].p ack('Va7cVvvVVvva4V');N.tim es{|
+ i|$><<E%[4,?#]if(i+1)*80/N!=i*80 /N;t=[i/1e5,(N-i)/2e5,1].min;a,b,c=k
+ .map{it.shift||(j[20*r,0]=[g =j.pop];a=1+r/3;it[0..]=(0..g.size).m
+ ap{g[it*a]||0};0)};u=u *0.96+r-0.5;v=v*0.99+d=r-0.5;w=w*0.8+d
+ ;x=(z[].*1+0 .59i).imag;e=y.map(&:[]);f.<<m.map{|o,
+ p,q|r=a+(b+c)/2+(b-c)*q/5;s=o[r.abs]
+ ;r=t*t*(3-2*t)*(r+s*w/1e4+p[s]*x/1
+ e7+[[u,0],[v,1]].sum{_1*1.5**(e[
+ _2]+q*e[_2+2]/9)}/32)/9;r/(1
+ +r*r)**0.5*32768}.pack'v
+ *'}};puts@;eval$c.
+ split*''
diff --git a/sample/trick2025/04-tompng/remarks.markdown b/sample/trick2025/04-tompng/remarks.markdown
new file mode 100644
index 0000000000..b2d848c07c
--- /dev/null
+++ b/sample/trick2025/04-tompng/remarks.markdown
@@ -0,0 +1,43 @@
+# Seashore - Nature Sound
+
+Listen to the relaxing sound of ocean waves generated by Ruby.
+
+## Usage
+
+```sh
+ruby entry.rb
+ruby entry.rb seashore.wav 60
+```
+
+The default filename is `output.wav` and the default duration is 30 seconds.
+
+Tested with ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +YJIT +MN +PRISM [arm64-darwin22]
+
+## Noise
+
+Noise sound is created by applying low-pass/band-pass filter to a white noise signal.
+Volume of the noise should change over time. This is also calculated by using low-pass filter.
+
+## Wave
+
+Sound of a single ocean wave is composed of hundreds of water splash sounds.
+Each water splash sound is composed of thousands of water drops and bubbles.
+This program creates this complicated sound by repeating sound mixing.
+
+```ruby
+sound2 = mix(sound1.change_pitch(rand), sound1.change_pitch(rand).delay(rand))
+sound4 = mix(sound2.change_pitch(rand), sound2.change_pitch(rand).delay(rand))
+...
+sound32768 = mix(sound16384.change_pitch(rand), sound16384.change_pitch(rand).delay(rand))
+
+splash1 = mix(sound1.delay(rand), sound2.delay(rand), sound4.delay(rand), ..., sound16384.delay(rand))
+splash2 = mix(splash1.change_pitch(rand), splash1.change_pitch(rand).delay(rand))
+splash4 = mix(splash2.change_pitch(rand), splash2.change_pitch(rand).delay(rand))
+...
+splash1024 = mix(splash512.change_pitch(rand), splash512.change_pitch(rand).delay(rand))
+
+wave_sound = [splash32, splash64, ..., splash1024].sample
+```
+
+This kind of repetition is often used in fractal rendering. In other words, this operation is rendering a fractal shape to the spectrogram canvas.
+It's an efficient way to create complex structure with low computational cost.
diff --git a/sample/trick2025/05-tompng/authors.markdown b/sample/trick2025/05-tompng/authors.markdown
new file mode 100644
index 0000000000..26ebe24da6
--- /dev/null
+++ b/sample/trick2025/05-tompng/authors.markdown
@@ -0,0 +1,3 @@
+* Tomoya Ishida (tompng)
+ * tomoyapenguin@gmail.com
+ * cctld: jp
diff --git a/sample/trick2025/05-tompng/entry.rb b/sample/trick2025/05-tompng/entry.rb
new file mode 100644
index 0000000000..4d30c5b5a9
--- /dev/null
+++ b/sample/trick2025/05-tompng/entry.rb
@@ -0,0 +1,118 @@
+module ReadableFizzBuzz
+ module Chain
+ end
+end
+
+include ReadableFizzBuzz
+
+Chain::Itself = Chain
+
+module Chain::Itself
+ module Void
+ A = B = C = D = E = F = G = H = I = J = K = L = M = Void
+ N = O = P = Q = R = S = T = U = V = W = X = Y = Z = Void
+
+ module Set
+ end
+
+ module Put
+ end
+
+ module WriteBack
+ end
+
+ module Not
+ include Void
+ end
+ end
+
+ module Off
+ include Void
+ end
+
+ module Nil
+ A = B = C = D = E = F = G = H = I = J = K = L = M = Off
+ N = O = P = Q = R = S = T = U = V = W = X = Y = Z = Off
+ end
+
+ module Next
+ include Nil
+ end
+
+ module Current
+ include Nil
+
+ Not = Off
+ Set = Put = Next
+ WriteBack = Current
+ end
+
+ True = If = Current
+ On = Next
+
+ module On
+ INT = 1
+ FIZZ = 'Fizz'
+ BUZZ = 'Buzz'
+ PREFIX = '0b'
+ FORMAT = "%d%s%s\n"
+ NEXT = __FILE__
+ end
+
+ module Off
+ INT = 0
+ FIZZ = BUZZ = nil
+ PREFIX = '0b1'
+ FORMAT = "%2$s%3$s\n"
+ NEXT = '/dev/null'
+ Not = True
+ end
+
+ module Initial
+ C = D = True
+ end
+
+ module ReadableFizzBuzz::Chain::Current
+ include Initial
+ end
+
+ If::C::Set::E = If::E::Set::F = If::F::Set::C = On
+ If::D::Set::G = If::G::Set::H = If::H::Set::I = If::I::Set::J = If::J::Set::D = On
+ If::F::Not::J::Not::Set::B = On
+ If::K::Not::Set::K = On
+ If::K::WriteBack::L = True
+ If::L::Not::M::Set::M = On
+ If::L::M::Not::Put::M = On
+ If::L::M::WriteBack::N = True
+ If::N::Not::O::Set::O = On
+ If::N::O::Not::Put::O = On
+ If::N::O::WriteBack::P = True
+ If::P::Not::Q::Set::Q = On
+ If::P::Q::Not::Put::Q = On
+ If::P::Q::WriteBack::R = True
+ If::R::Not::S::Set::S = On
+ If::R::S::Not::Put::S = On
+ If::R::S::WriteBack::T = True
+ If::T::Not::U::Set::U = On
+ If::T::U::Not::Put::U = On
+ If::T::U::WriteBack::V = True
+ If::V::Not::W::Set::W = On
+ If::V::W::Not::Put::W = On
+ If::V::W::WriteBack::X = True
+ If::X::Not::Y::Set::Y = On
+ If::X::Y::Not::Put::Y = On
+ If::X::Y::WriteBack::Z = True
+ If::Z::Not::Set::A = On
+end
+
+module Chain::Chain
+ Current = Chain::Next
+end
+
+include Chain
+
+module Chain::Current
+ NUMBER = A::PREFIX, Y::INT, W::INT, U::INT, S::INT, Q::INT, O::INT, M::INT, K::INT
+ printf B::FORMAT, NUMBER.join, C::FIZZ, D::BUZZ
+ load A::NEXT
+end
diff --git a/sample/trick2025/05-tompng/remarks.markdown b/sample/trick2025/05-tompng/remarks.markdown
new file mode 100644
index 0000000000..adb4bf4df8
--- /dev/null
+++ b/sample/trick2025/05-tompng/remarks.markdown
@@ -0,0 +1,106 @@
+### Remarks
+
+Just run it with no argument:
+
+```sh
+ruby entry.rb
+```
+
+I confirmed the following implementations/platforms:
+
+- ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +YJIT +MN +PRISM [arm64-darwin22]
+- ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [aarch64-linux-musl]
+
+### Description
+
+Readability is important even for a simple fizz buzz program.
+
+These are the major ingredients of a spaghetti that makes program tasty and valuable but unreadable.
+
+- Many class definitions
+- Many method definitions
+- Many method calls
+- Many variables
+- Conditional branches
+
+These are what is acceptable for a readable program.
+
+- Many modules: Using only a single module in a program is not good.
+- Many constants: Better than magic numbers.
+- Module#include: Mixins are what module is for.
+- Many file loads: Usually better than loading a large file only once.
+- Minimal method calls: Needed for printing output.
+
+This program is doing something slightly difficult in the last few lines: print output and load ruby program.
+In contrast, the rest part of this program is extremely simple and easy. Module definition, constant definition and module inclusion. That's all.
+
+### Internals
+
+Called methods
+
+- `Module#include`
+- `Array#join`
+- `Kernel#printf`
+- `Kernel#load`
+
+Deeply nested module chain to avoid constant reassignment
+
+```ruby
+10.times do
+ module Root
+ module Chain
+ module X; end
+ module Y; end
+ module Z; end
+ end
+ end
+ include Root
+
+ module Chain::Chain
+ # Not a constant reassignment because Chain::Chain is always a new module
+ X = Chain::Y
+ Y = Chain::Z
+ Z = Chain::X
+ end
+ include Chain
+ p x: X, chain: Chain
+end
+```
+
+Constant allocation
+
+| Constant | Purpose |
+| ---------------------- | ----------------------- |
+| A | Loop condition |
+| B | Format (!Fizz && !Buzz) |
+| C, E, F | Fizz rotation |
+| D, G, H, I, J | Buzz rotation |
+| K, M, O, Q, S, U, W, Y | Iteration bits |
+| L, N, P, R, T, V, X, Z | Temporary carry bits |
+
+Instruction sequence with constant lookup magic
+
+```ruby
+# B = 1 if A
+If::A::Set::B = On
+
+# B = 1 if !A
+If::A::Not::Set::B = On
+
+# C = 1 if !A && B
+If::A::Not::B::Set::C = On
+
+# C = 1 if !A && !B
+If::A::Not::B::Not::Set::C = On
+```
+
+Loop with `load __FILE__`
+
+```ruby
+# A::NEXT is __FILE__ or '/dev/null'
+load A::NEXT
+```
+
+### Limitation
+
+Needs `/dev/null`
diff --git a/sample/trick2025/README.md b/sample/trick2025/README.md
new file mode 100644
index 0000000000..1d71f54620
--- /dev/null
+++ b/sample/trick2025/README.md
@@ -0,0 +1,16 @@
+This directory contains the top-five entries of
+the 5th Transcendental Ruby Imbroglio Contest for rubyKaigi (TRICK 2025).
+
+THESE ARE BAD EXAMPLES! You must NOT use them as a sample code.
+
+* 1st: "Most Revolutionary" - Don Yang
+* 2nd: "Most Useful" - Yusuke Endoh
+* 3rd: "Most Arithmetic" - Tomoya Ishida
+* 4th: "Best ASMR" - Tomoya Ishida
+* 5th: "Most Maintainable" - Tomoya Ishida
+
+These files are licensed under MIT license.
+
+For the contest outline and other winning entries, see:
+
+https://github.com/tric/trick2025
diff --git a/sample/win32ole/excel1.rb b/sample/win32ole/excel1.rb
deleted file mode 100644
index 4fe1d0c2a9..0000000000
--- a/sample/win32ole/excel1.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: false
-require 'win32ole'
-
-application = WIN32OLE.new('Excel.Application')
-
-application.visible = true
-workbook = application.Workbooks.Add();
-worksheet = workbook.Worksheets(1);
-
-=begin
-worksheet.Range("A1:D1").value = ["North","South","East","West"];
-worksheet.Range("A2:B2").value = [5.2, 10];
-
-worksheet.Range("C2").value = 8;
-worksheet.Range("D2").value = 20;
-=end
-
-worksheet.Range("A1:B2").value = [["North","South"],
- [5.2, 10]];
-
-vals = WIN32OLE_VARIANT.new([["East","West"],
- [8, 20]],
- WIN32OLE::VARIANT::VT_ARRAY)
-worksheet.Range("C1:D2").value = vals
-
-range = worksheet.Range("A1:D2");
-range.Select
-chart = workbook.Charts.Add;
-
-workbook.saved = true;
-
-print "Now quit Excel... Please enter."
-gets
-
-application.ActiveWorkbook.Close(0);
-application.Quit();
-
diff --git a/sample/win32ole/excel2.rb b/sample/win32ole/excel2.rb
deleted file mode 100644
index 47a5715f84..0000000000
--- a/sample/win32ole/excel2.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: false
-require 'win32ole'
-
-# -4100 is the value for the Excel constant xl3DColumn.
-ChartTypeVal = -4100;
-
-# Creates OLE object to Excel
-excel = WIN32OLE.new("excel.application")
-
-# Create and rotate the chart
-excel.visible = true;
-excel.Workbooks.Add();
-excel.Range("a1").value = 3;
-excel.Range("a2").value = 2;
-excel.Range("a3").value = 1;
-excel.Range("a1:a3").Select();
-excelchart = excel.Charts.Add();
-excelchart.type = ChartTypeVal;
-
-i = 0
-i.step(180, 10) do |rot|
- excelchart.rotation=rot;
- sleep 0.1
-end
-# Done, bye
-
-print "Now quit Excel... Please enter."
-gets
-
-excel.ActiveWorkbook.Close(0);
-excel.Quit();
diff --git a/sample/win32ole/excel3.rb b/sample/win32ole/excel3.rb
deleted file mode 100644
index 72aee2a929..0000000000
--- a/sample/win32ole/excel3.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: false
-require 'win32ole'
-
-#application = WIN32OLE.new('Excel.Application.5')
-application = WIN32OLE.new('Excel.Application')
-
-application.visible = true
-workbook = application.Workbooks.Add();
-sheet = workbook.Worksheets(1);
-sheetS = workbook.Worksheets
-puts "The number of sheets is #{sheetS.count}"
-puts "Now add 2 sheets after of `#{sheet.name}`"
-sheetS.add({'count'=>2, 'after'=>sheet})
-puts "The number of sheets is #{sheetS.count}"
-
-print "Now quit Excel... Please enter."
-gets
-
-application.ActiveWorkbook.Close(0);
-application.Quit();
-
diff --git a/sample/win32ole/ie.rb b/sample/win32ole/ie.rb
deleted file mode 100644
index 4db64eed30..0000000000
--- a/sample/win32ole/ie.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-# frozen_string_literal: false
-require 'win32ole'
-url = 'http://www.ruby-lang.org/'
-ie = WIN32OLE.new('InternetExplorer.Application')
-ie.visible = true
-ie.gohome
-print "Now navigate Ruby home page... Please enter."
-gets
-ie.navigate(url)
-print "Now quit Internet Explorer... Please enter."
-gets
-ie.Quit()
diff --git a/sample/win32ole/ieconst.rb b/sample/win32ole/ieconst.rb
deleted file mode 100644
index 363a4f8153..0000000000
--- a/sample/win32ole/ieconst.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: false
-require 'win32ole'
-
-ie = WIN32OLE.new('InternetExplorer.Application')
-=begin
-WIN32OLE.const_load(ie)
-WIN32OLE.constants.sort.each do |c|
- puts "#{c} = #{WIN32OLE.const_get(c)}"
-end
-=end
-
-module IE_CONST
-end
-
-WIN32OLE.const_load(ie, IE_CONST)
-IE_CONST.constants.sort.each do |c|
- puts "#{c} = #{IE_CONST.const_get(c)}"
-end
-
-#------------------------------------------------------------
-# Remark!!! CONSTANTS has not tested enoughly!!!
-# CONSTANTS is alpha release.
-# If there are constants which first letter is not [a-zA-Z],
-# like a '_Foo', then maybe you can access the value by
-# using CONSTANTS['_Foo']
-#------------------------------------------------------------
-IE_CONST::CONSTANTS.each do |k, v|
- puts "#{k} = #{v}"
-end
-
-puts WIN32OLE::VERSION
-ie.quit
-
diff --git a/sample/win32ole/ienavi.rb b/sample/win32ole/ienavi.rb
deleted file mode 100644
index 5d0536028b..0000000000
--- a/sample/win32ole/ienavi.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: false
-require 'win32ole'
-
-$urls = []
-
-def navigate(url)
- $urls << url
-end
-
-def stop_msg_loop
- puts "Now Stop IE..."
- $LOOP = false;
-end
-
-def default_handler(event, *args)
- case event
- when "BeforeNavigate"
- puts "Now Navigate #{args[0]}..."
- end
-end
-
-ie = WIN32OLE.new('InternetExplorer.Application')
-ie.visible = true
-ie.gohome
-
-ev = WIN32OLE_EVENT.new(ie, 'DWebBrowserEvents')
-
-ev.on_event {|*args| default_handler(*args)}
-ev.on_event("NavigateComplete") {|url| navigate(url)}
-ev.on_event("Quit") {|*args| stop_msg_loop}
-
-$LOOP = true
-while ($LOOP)
- WIN32OLE_EVENT.message_loop
-end
-
-puts "You Navigated the URLs ..."
-$urls.each_with_index do |url, i|
- puts "(#{i+1}) #{url}"
-end
-
diff --git a/sample/win32ole/ienavi2.rb b/sample/win32ole/ienavi2.rb
deleted file mode 100644
index 3248393077..0000000000
--- a/sample/win32ole/ienavi2.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: false
-require 'win32ole'
-
-class IEHandler
- attr_reader :loop
- def initialize
- @urls = []
- @loop = true
- end
- def method_missing(event, *args)
- case event
- when "BeforeNavigate2"
- puts "Now Navigate #{args[1]}..."
- end
- end
- def onNavigateComplete2(pdisp, url)
- @urls << url
- end
- def onOnQuit
- puts "Now Stop IE..."
- @loop = false
- end
- def put_urls
- puts "You Navigated the URLs ..."
- @urls.each_with_index do |url, i|
- puts "(#{i+1}) #{url}"
- end
- end
-end
-
-ie = WIN32OLE.new('InternetExplorer.Application')
-ie.visible = true
-ie.gohome
-
-ev = WIN32OLE_EVENT.new(ie)
-ev.handler = IEHandler.new
-
-while (ev.handler.loop)
- WIN32OLE_EVENT.message_loop
-end
-ev.handler.put_urls
diff --git a/sample/win32ole/oledirs.rb b/sample/win32ole/oledirs.rb
deleted file mode 100644
index e52a0fd7ac..0000000000
--- a/sample/win32ole/oledirs.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: false
-#
-# You need WSH(Windows Scripting Host) to run this script.
-#
-
-require "win32ole"
-
-def listup(items)
-# items.each do |i|
- for i in items
- puts i.name
- end
-end
-
-fs = WIN32OLE.new("Scripting.FileSystemObject")
-
-folder = fs.GetFolder(".")
-
-puts "--- folder of #{folder.path} ---"
-listup(folder.SubFolders)
-
-puts "--- files of #{folder.path} ---"
-listup(folder.Files)
-
diff --git a/sample/win32ole/olegen.rb b/sample/win32ole/olegen.rb
deleted file mode 100644
index 9398194cf1..0000000000
--- a/sample/win32ole/olegen.rb
+++ /dev/null
@@ -1,348 +0,0 @@
-# frozen_string_literal: false
-#-----------------------------
-# olegen.rb
-# $Revision$
-#-----------------------------
-
-require 'win32ole'
-
-class WIN32COMGen
- def initialize(typelib)
- @typelib = typelib
- @receiver = ""
- end
- attr_reader :typelib
-
- def ole_classes(typelib)
- begin
- @ole = WIN32OLE.new(typelib)
- [@ole.ole_obj_help]
- rescue
- WIN32OLE_TYPE.ole_classes(typelib)
- end
- end
-
- def generate_args(method)
- args = []
- if method.size_opt_params >= 0
- size_required_params = method.size_params - method.size_opt_params
- else
- size_required_params = method.size_params - 1
- end
- size_required_params.times do |i|
- if method.params[i] && method.params[i].optional?
- args.push "arg#{i}=nil"
- else
- args.push "arg#{i}"
- end
- end
- if method.size_opt_params >= 0
- method.size_opt_params.times do |i|
- args.push "arg#{i + size_required_params}=nil"
- end
- else
- args.push "*arg"
- end
- args.join(", ")
- end
-
- def generate_argtype(typedetails)
- ts = ''
- typedetails.each do |t|
- case t
- when 'CARRAY', 'VOID', 'UINT', 'RESULT', 'DECIMAL', 'I8', 'UI8'
-# raise "Sorry type\"" + t + "\" not supported"
- ts << "\"??? NOT SUPPORTED TYPE:`#{t}'\""
- when 'USERDEFINED', 'Unknown Type 9'
- ts << 'VT_DISPATCH'
- break;
- when 'SAFEARRAY'
- ts << 'VT_ARRAY|'
- when 'PTR'
- ts << 'VT_BYREF|'
- when 'INT'
- ts << 'VT_I4'
- else
- if String === t
- ts << 'VT_' + t
- end
- end
- end
- if ts.empty?
- ts = 'VT_VARIANT'
- elsif ts.end_with?(?|)
- ts += 'VT_VARIANT'
- end
- ts
- end
-
- def generate_argtypes(method, proptypes)
- types = method.params.collect{|param|
- generate_argtype(param.ole_type_detail)
- }.join(", ")
- if proptypes
- types += ", " if types.size > 0
- types += generate_argtype(proptypes)
- end
- types
- end
-
- def generate_method_body(method, disptype, types=nil)
- " ret = #{@receiver}#{disptype}(#{method.dispid}, [" +
- generate_args(method).gsub("=nil", "") +
- "], [" +
- generate_argtypes(method, types) +
- "])\n" +
- " @lastargs = WIN32OLE::ARGV\n" +
- " ret"
- end
-
- def generate_method_help(method, type = nil)
- str = " # "
- if type
- str += type
- else
- str += method.return_type
- end
- str += " #{method.name}"
- if method.event?
- str += " EVENT"
- str += " in #{method.event_interface}"
- end
- if method.helpstring && method.helpstring != ""
- str += "\n # "
- str += method.helpstring
- end
- args_help = generate_method_args_help(method)
- if args_help
- str += "\n"
- str += args_help
- end
- str
- end
-
- def generate_method_args_help(method)
- args = []
- method.params.each_with_index {|param, i|
- h = " # #{param.ole_type} arg#{i} --- #{param.name}"
- inout = []
- inout.push "IN" if param.input?
- inout.push "OUT" if param.output?
- h += " [#{inout.join('/')}]"
- h += " ( = #{param.default})" if param.default
- args.push h
- }
- if args.size > 0
- args.join("\n")
- else
- nil
- end
- end
-
- def generate_method(method, disptype, io = STDOUT, types = nil)
- io.puts "\n"
- io.puts generate_method_help(method)
- if method.invoke_kind == 'PROPERTYPUT'
- io.print " def #{method.name}=("
- else
- io.print " def #{method.name}("
- end
- io.print generate_args(method)
- io.puts ")"
- io.puts generate_method_body(method, disptype, types)
- io.puts " end"
- end
-
- def generate_propputref_methods(klass, io = STDOUT)
- klass.ole_methods.select {|method|
- method.invoke_kind == 'PROPERTYPUTREF' && method.visible?
- }.each do |method|
- generate_method(method, io)
- end
- end
-
- def generate_properties_with_args(klass, io = STDOUT)
- klass.ole_methods.select {|method|
- method.invoke_kind == 'PROPERTYGET' &&
- method.visible? &&
- method.size_params > 0
- }.each do |method|
- types = method.return_type_detail
- io.puts "\n"
- io.puts generate_method_help(method, types[0])
- io.puts " def #{method.name}"
- if klass.ole_type == "Class"
- io.print " OLEProperty.new(@dispatch, #{method.dispid}, ["
- else
- io.print " OLEProperty.new(self, #{method.dispid}, ["
- end
- io.print generate_argtypes(method, nil)
- io.print "], ["
- io.print generate_argtypes(method, types)
- io.puts "])"
- io.puts " end"
- end
- end
-
- def generate_propput_methods(klass, io = STDOUT)
- klass.ole_methods.select {|method|
- method.invoke_kind == 'PROPERTYPUT' && method.visible? &&
- method.size_params == 1
- }.each do |method|
- ms = klass.ole_methods.select {|m|
- m.invoke_kind == 'PROPERTYGET' &&
- m.dispid == method.dispid
- }
- types = []
- if ms.size == 1
- types = ms[0].return_type_detail
- end
- generate_method(method, '_setproperty', io, types)
- end
- end
-
- def generate_propget_methods(klass, io = STDOUT)
- klass.ole_methods.select {|method|
- method.invoke_kind == 'PROPERTYGET' && method.visible? &&
- method.size_params == 0
- }.each do |method|
- generate_method(method, '_getproperty', io)
- end
- end
-
- def generate_func_methods(klass, io = STDOUT)
- klass.ole_methods.select {|method|
- method.invoke_kind == "FUNC" && method.visible?
- }.each do |method|
- generate_method(method, '_invoke', io)
- end
- end
-
- def generate_methods(klass, io = STDOUT)
- generate_propget_methods(klass, io)
- generate_propput_methods(klass, io)
- generate_properties_with_args(klass, io)
- generate_func_methods(klass, io)
-# generate_propputref_methods(klass, io)
- end
-
- def generate_constants(klass, io = STDOUT)
- klass.variables.select {|v|
- v.visible? && v.variable_kind == 'CONSTANT'
- }.each do |v|
- io.print " "
- io.print v.name.sub(/^./){$&.upcase}
- io.print " = "
- io.puts v.value
- end
- end
-
- def class_name(klass)
- klass_name = klass.name
- if klass.ole_type == "Class" &&
- klass.guid &&
- klass.progid
- klass_name = klass.progid.gsub(/\./, '_')
- end
- if /^[A-Z]/ !~ klass_name || Module.constants.include?(klass_name)
- klass_name = 'OLE' + klass_name
- end
- klass_name
- end
-
- def define_initialize(klass)
- <<STR
-
- def initialize(obj = nil)
- @clsid = "#{klass.guid}"
- @progid = "#{klass.progid}"
- if obj.nil?
- @dispatch = WIN32OLE.new @progid
- else
- @dispatch = obj
- end
- end
-STR
- end
-
- def define_include
- " include WIN32OLE::VARIANT"
- end
-
- def define_instance_variables
- " attr_reader :lastargs"
- end
-
- def define_method_missing
- <<STR
-
- def method_missing(cmd, *arg)
- @dispatch.method_missing(cmd, *arg)
- end
-STR
- end
-
- def define_class(klass, io = STDOUT)
- io.puts "class #{class_name(klass)} # #{klass.name}"
- io.puts define_include
- io.puts define_instance_variables
- io.puts " attr_reader :dispatch"
- io.puts " attr_reader :clsid"
- io.puts " attr_reader :progid"
- io.puts define_initialize(klass)
- io.puts define_method_missing
- end
-
- def define_module(klass, io = STDOUT)
- io.puts "module #{class_name(klass)}"
- io.puts define_include
- io.puts define_instance_variables
- end
-
- def generate_class(klass, io = STDOUT)
- io.puts "\n# #{klass.helpstring}"
- if klass.ole_type == "Class" &&
- klass.guid &&
- klass.progid
- @receiver = "@dispatch."
- define_class(klass, io)
- else
- @receiver = ""
- define_module(klass, io)
- end
- generate_constants(klass, io)
- generate_methods(klass, io)
- io.puts "end"
- end
-
- def generate(io = STDOUT)
- io.puts "require 'win32ole'"
- io.puts "require 'win32ole/property'"
-
- ole_classes(typelib).select{|klass|
- klass.visible? &&
- (klass.ole_type == "Class" ||
- klass.ole_type == "Interface" ||
- klass.ole_type == "Dispatch" ||
- klass.ole_type == "Enum")
- }.each do |klass|
- generate_class(klass, io)
- end
- begin
- @ole.quit if @ole
- rescue
- end
- end
-end
-
-require 'win32ole'
-if __FILE__ == $0
- if ARGV.size == 0
- $stderr.puts "usage: #{$0} Type Library [...]"
- exit 1
- end
- ARGV.each do |typelib|
- comgen = WIN32COMGen.new(typelib)
- comgen.generate
- end
-end
diff --git a/sample/win32ole/xml.rb b/sample/win32ole/xml.rb
deleted file mode 100644
index 5a239c9336..0000000000
--- a/sample/win32ole/xml.rb
+++ /dev/null
@@ -1,7307 +0,0 @@
-# frozen_string_literal: false
-#
-# This file created by olegen.rb as following.
-# ruby olegen.rb 'Microsoft XML, version 2.0' > xml.rb
-#
-require 'win32ole'
-require 'win32ole/property'
-
-#
-module IXMLDOMImplementation
- include WIN32OLE::VARIANT
- attr_reader :lastargs
-
- # BOOL hasFeature
- # BSTR arg0 --- feature [IN]
- # BSTR arg1 --- version [IN]
- def hasFeature(arg0, arg1)
- ret = _invoke(145, [arg0, arg1], [VT_BSTR, VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-end
-
-# Core DOM node interface
-module IXMLDOMNode
- include WIN32OLE::VARIANT
- attr_reader :lastargs
-
- # BSTR nodeName
- # name of the node
- def nodeName()
- ret = _getproperty(2, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeValue
- # value stored in the node
- def nodeValue()
- ret = _getproperty(3, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # DOMNodeType nodeType
- # the node's type
- def nodeType()
- ret = _getproperty(4, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode parentNode
- # parent of the node
- def parentNode()
- ret = _getproperty(6, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList childNodes
- # the collection of the node's children
- def childNodes()
- ret = _getproperty(7, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode firstChild
- # first child of the node
- def firstChild()
- ret = _getproperty(8, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode lastChild
- # first child of the node
- def lastChild()
- ret = _getproperty(9, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode previousSibling
- # left sibling of the node
- def previousSibling()
- ret = _getproperty(10, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode nextSibling
- # right sibling of the node
- def nextSibling()
- ret = _getproperty(11, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNamedNodeMap attributes
- # the collection of the node's attributes
- def attributes()
- ret = _getproperty(12, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMDocument ownerDocument
- # document that contains the node
- def ownerDocument()
- ret = _getproperty(18, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR nodeTypeString
- # the type of node in string form
- def nodeTypeString()
- ret = _getproperty(21, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR text
- # text content of the node and subtree
- def text()
- ret = _getproperty(24, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL specified
- # indicates whether node is a default value
- def specified()
- ret = _getproperty(22, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode definition
- # pointer to the definition of the node in the DTD or schema
- def definition()
- ret = _getproperty(23, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue()
- ret = _getproperty(25, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT dataType
- # the data type of the node
- def dataType()
- ret = _getproperty(26, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR xml
- # return the XML source for the node and each of its descendants
- def xml()
- ret = _getproperty(27, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL parsed
- # has sub-tree been completely parsed
- def parsed()
- ret = _getproperty(31, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR namespaceURI
- # the URI for the namespace applying to the node
- def namespaceURI()
- ret = _getproperty(32, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR prefix
- # the prefix for the namespace applying to the node
- def prefix()
- ret = _getproperty(33, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR baseName
- # the base name of the node (nodename with the prefix stripped off)
- def baseName()
- ret = _getproperty(34, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeValue
- # value stored in the node
- def nodeValue=(arg0)
- ret = _setproperty(3, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID text
- # text content of the node and subtree
- def text=(arg0)
- ret = _setproperty(24, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue=(arg0)
- ret = _setproperty(25, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID dataType
- # the data type of the node
- def dataType=(arg0)
- ret = _setproperty(26, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode insertBefore
- # insert a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # VARIANT arg1 --- refChild [IN]
- def insertBefore(arg0, arg1)
- ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode replaceChild
- # replace a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # IXMLDOMNode arg1 --- oldChild [IN]
- def replaceChild(arg0, arg1)
- ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode removeChild
- # remove a child node
- # IXMLDOMNode arg0 --- childNode [IN]
- def removeChild(arg0)
- ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode appendChild
- # append a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- def appendChild(arg0)
- ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL hasChildNodes
- def hasChildNodes()
- ret = _invoke(17, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode cloneNode
- # BOOL arg0 --- deep [IN]
- def cloneNode(arg0)
- ret = _invoke(19, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR transformNode
- # apply the stylesheet to the subtree
- # IXMLDOMNode arg0 --- stylesheet [IN]
- def transformNode(arg0)
- ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList selectNodes
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectNodes(arg0)
- ret = _invoke(29, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode selectSingleNode
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectSingleNode(arg0)
- ret = _invoke(30, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID transformNodeToObject
- # apply the stylesheet to the subtree, returning the result through a document or a stream
- # IXMLDOMNode arg0 --- stylesheet [IN]
- # VARIANT arg1 --- outputObject [IN]
- def transformNodeToObject(arg0, arg1)
- ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-end
-
-# Constants that define a node's type
-module OLEtagDOMNodeType
- include WIN32OLE::VARIANT
- attr_reader :lastargs
- NODE_INVALID = 0
- NODE_ELEMENT = 1
- NODE_ATTRIBUTE = 2
- NODE_TEXT = 3
- NODE_CDATA_SECTION = 4
- NODE_ENTITY_REFERENCE = 5
- NODE_ENTITY = 6
- NODE_PROCESSING_INSTRUCTION = 7
- NODE_COMMENT = 8
- NODE_DOCUMENT = 9
- NODE_DOCUMENT_TYPE = 10
- NODE_DOCUMENT_FRAGMENT = 11
- NODE_NOTATION = 12
-end
-
-#
-module IXMLDOMNodeList
- include WIN32OLE::VARIANT
- attr_reader :lastargs
-
- # I4 length
- # number of nodes in the collection
- def length()
- ret = _getproperty(74, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # PTR item
- # collection of nodes
- # I4 arg0 --- index [IN]
- def item
- OLEProperty.new(self, 0, [VT_I4], [VT_I4, VT_BYREF|VT_DISPATCH])
- end
-
- # IXMLDOMNode nextNode
- # get next node from iterator
- def nextNode()
- ret = _invoke(76, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID reset
- # reset the position of iterator
- def reset()
- ret = _invoke(77, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-end
-
-#
-module IXMLDOMNamedNodeMap
- include WIN32OLE::VARIANT
- attr_reader :lastargs
-
- # I4 length
- # number of nodes in the collection
- def length()
- ret = _getproperty(74, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # PTR item
- # collection of nodes
- # I4 arg0 --- index [IN]
- def item
- OLEProperty.new(self, 0, [VT_I4], [VT_I4, VT_BYREF|VT_DISPATCH])
- end
-
- # IXMLDOMNode getNamedItem
- # lookup item by name
- # BSTR arg0 --- name [IN]
- def getNamedItem(arg0)
- ret = _invoke(83, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode setNamedItem
- # set item by name
- # IXMLDOMNode arg0 --- newItem [IN]
- def setNamedItem(arg0)
- ret = _invoke(84, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode removeNamedItem
- # remove item by name
- # BSTR arg0 --- name [IN]
- def removeNamedItem(arg0)
- ret = _invoke(85, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode getQualifiedItem
- # lookup the item by name and namespace
- # BSTR arg0 --- baseName [IN]
- # BSTR arg1 --- namespaceURI [IN]
- def getQualifiedItem(arg0, arg1)
- ret = _invoke(87, [arg0, arg1], [VT_BSTR, VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode removeQualifiedItem
- # remove the item by name and namespace
- # BSTR arg0 --- baseName [IN]
- # BSTR arg1 --- namespaceURI [IN]
- def removeQualifiedItem(arg0, arg1)
- ret = _invoke(88, [arg0, arg1], [VT_BSTR, VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode nextNode
- # get next node from iterator
- def nextNode()
- ret = _invoke(89, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID reset
- # reset the position of iterator
- def reset()
- ret = _invoke(90, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-end
-
-#
-module IXMLDOMDocument
- include WIN32OLE::VARIANT
- attr_reader :lastargs
-
- # BSTR nodeName
- # name of the node
- def nodeName()
- ret = _getproperty(2, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeValue
- # value stored in the node
- def nodeValue()
- ret = _getproperty(3, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # DOMNodeType nodeType
- # the node's type
- def nodeType()
- ret = _getproperty(4, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode parentNode
- # parent of the node
- def parentNode()
- ret = _getproperty(6, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList childNodes
- # the collection of the node's children
- def childNodes()
- ret = _getproperty(7, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode firstChild
- # first child of the node
- def firstChild()
- ret = _getproperty(8, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode lastChild
- # first child of the node
- def lastChild()
- ret = _getproperty(9, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode previousSibling
- # left sibling of the node
- def previousSibling()
- ret = _getproperty(10, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode nextSibling
- # right sibling of the node
- def nextSibling()
- ret = _getproperty(11, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNamedNodeMap attributes
- # the collection of the node's attributes
- def attributes()
- ret = _getproperty(12, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMDocument ownerDocument
- # document that contains the node
- def ownerDocument()
- ret = _getproperty(18, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR nodeTypeString
- # the type of node in string form
- def nodeTypeString()
- ret = _getproperty(21, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR text
- # text content of the node and subtree
- def text()
- ret = _getproperty(24, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL specified
- # indicates whether node is a default value
- def specified()
- ret = _getproperty(22, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode definition
- # pointer to the definition of the node in the DTD or schema
- def definition()
- ret = _getproperty(23, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue()
- ret = _getproperty(25, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT dataType
- # the data type of the node
- def dataType()
- ret = _getproperty(26, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR xml
- # return the XML source for the node and each of its descendants
- def xml()
- ret = _getproperty(27, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL parsed
- # has sub-tree been completely parsed
- def parsed()
- ret = _getproperty(31, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR namespaceURI
- # the URI for the namespace applying to the node
- def namespaceURI()
- ret = _getproperty(32, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR prefix
- # the prefix for the namespace applying to the node
- def prefix()
- ret = _getproperty(33, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR baseName
- # the base name of the node (nodename with the prefix stripped off)
- def baseName()
- ret = _getproperty(34, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMDocumentType doctype
- # node corresponding to the DOCTYPE
- def doctype()
- ret = _getproperty(38, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMImplementation implementation
- # info on this DOM implementation
- def implementation()
- ret = _getproperty(39, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMElement documentElement
- # the root of the tree
- def documentElement()
- ret = _getproperty(40, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # I4 readyState
- # get the state of the XML document
- def readyState()
- ret = _getproperty(-525, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMParseError parseError
- # get the last parser error
- def parseError()
- ret = _getproperty(59, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR url
- # get the URL for the loaded XML document
- def url()
- ret = _getproperty(60, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL async
- # flag for asynchronous download
- def async()
- ret = _getproperty(61, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL validateOnParse
- # indicates whether the parser performs validation
- def validateOnParse()
- ret = _getproperty(65, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL resolveExternals
- # indicates whether the parser resolves references to external DTD/Entities/Schema
- def resolveExternals()
- ret = _getproperty(66, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL preserveWhiteSpace
- # indicates whether the parser preserves whitespace
- def preserveWhiteSpace()
- ret = _getproperty(67, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeValue
- # value stored in the node
- def nodeValue=(arg0)
- ret = _setproperty(3, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID text
- # text content of the node and subtree
- def text=(arg0)
- ret = _setproperty(24, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue=(arg0)
- ret = _setproperty(25, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID dataType
- # the data type of the node
- def dataType=(arg0)
- ret = _setproperty(26, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID async
- # flag for asynchronous download
- def async=(arg0)
- ret = _setproperty(61, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID validateOnParse
- # indicates whether the parser performs validation
- def validateOnParse=(arg0)
- ret = _setproperty(65, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID resolveExternals
- # indicates whether the parser resolves references to external DTD/Entities/Schema
- def resolveExternals=(arg0)
- ret = _setproperty(66, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID preserveWhiteSpace
- # indicates whether the parser preserves whitespace
- def preserveWhiteSpace=(arg0)
- ret = _setproperty(67, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID onreadystatechange
- # register a readystatechange event handler
- def onreadystatechange=(arg0)
- ret = _setproperty(68, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID ondataavailable
- # register an ondataavailable event handler
- def ondataavailable=(arg0)
- ret = _setproperty(69, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID ontransformnode
- # register an ontransformnode event handler
- def ontransformnode=(arg0)
- ret = _setproperty(70, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode insertBefore
- # insert a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # VARIANT arg1 --- refChild [IN]
- def insertBefore(arg0, arg1)
- ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode replaceChild
- # replace a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # IXMLDOMNode arg1 --- oldChild [IN]
- def replaceChild(arg0, arg1)
- ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode removeChild
- # remove a child node
- # IXMLDOMNode arg0 --- childNode [IN]
- def removeChild(arg0)
- ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode appendChild
- # append a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- def appendChild(arg0)
- ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL hasChildNodes
- def hasChildNodes()
- ret = _invoke(17, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode cloneNode
- # BOOL arg0 --- deep [IN]
- def cloneNode(arg0)
- ret = _invoke(19, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR transformNode
- # apply the stylesheet to the subtree
- # IXMLDOMNode arg0 --- stylesheet [IN]
- def transformNode(arg0)
- ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList selectNodes
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectNodes(arg0)
- ret = _invoke(29, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode selectSingleNode
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectSingleNode(arg0)
- ret = _invoke(30, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID transformNodeToObject
- # apply the stylesheet to the subtree, returning the result through a document or a stream
- # IXMLDOMNode arg0 --- stylesheet [IN]
- # VARIANT arg1 --- outputObject [IN]
- def transformNodeToObject(arg0, arg1)
- ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMElement createElement
- # create an Element node
- # BSTR arg0 --- tagName [IN]
- def createElement(arg0)
- ret = _invoke(41, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMDocumentFragment createDocumentFragment
- # create a DocumentFragment node
- def createDocumentFragment()
- ret = _invoke(42, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMText createTextNode
- # create a text node
- # BSTR arg0 --- data [IN]
- def createTextNode(arg0)
- ret = _invoke(43, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMComment createComment
- # create a comment node
- # BSTR arg0 --- data [IN]
- def createComment(arg0)
- ret = _invoke(44, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMCDATASection createCDATASection
- # create a CDATA section node
- # BSTR arg0 --- data [IN]
- def createCDATASection(arg0)
- ret = _invoke(45, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMProcessingInstruction createProcessingInstruction
- # create a processing instruction node
- # BSTR arg0 --- target [IN]
- # BSTR arg1 --- data [IN]
- def createProcessingInstruction(arg0, arg1)
- ret = _invoke(46, [arg0, arg1], [VT_BSTR, VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMAttribute createAttribute
- # create an attribute node
- # BSTR arg0 --- name [IN]
- def createAttribute(arg0)
- ret = _invoke(47, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMEntityReference createEntityReference
- # create an entity reference node
- # BSTR arg0 --- name [IN]
- def createEntityReference(arg0)
- ret = _invoke(49, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList getElementsByTagName
- # build a list of elements by name
- # BSTR arg0 --- tagName [IN]
- def getElementsByTagName(arg0)
- ret = _invoke(50, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode createNode
- # create a node of the specified node type and name
- # VARIANT arg0 --- type [IN]
- # BSTR arg1 --- name [IN]
- # BSTR arg2 --- namespaceURI [IN]
- def createNode(arg0, arg1, arg2)
- ret = _invoke(54, [arg0, arg1, arg2], [VT_VARIANT, VT_BSTR, VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode nodeFromID
- # retrieve node from it's ID
- # BSTR arg0 --- idString [IN]
- def nodeFromID(arg0)
- ret = _invoke(56, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL load
- # load document from the specified XML source
- # VARIANT arg0 --- xmlSource [IN]
- def load(arg0)
- ret = _invoke(58, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID abort
- # abort an asynchronous download
- def abort()
- ret = _invoke(62, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL loadXML
- # load the document from a string
- # BSTR arg0 --- bstrXML [IN]
- def loadXML(arg0)
- ret = _invoke(63, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID save
- # save the document to a specified destination
- # VARIANT arg0 --- destination [IN]
- def save(arg0)
- ret = _invoke(64, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-end
-
-#
-module IXMLDOMDocumentType
- include WIN32OLE::VARIANT
- attr_reader :lastargs
-
- # BSTR nodeName
- # name of the node
- def nodeName()
- ret = _getproperty(2, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeValue
- # value stored in the node
- def nodeValue()
- ret = _getproperty(3, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # DOMNodeType nodeType
- # the node's type
- def nodeType()
- ret = _getproperty(4, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode parentNode
- # parent of the node
- def parentNode()
- ret = _getproperty(6, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList childNodes
- # the collection of the node's children
- def childNodes()
- ret = _getproperty(7, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode firstChild
- # first child of the node
- def firstChild()
- ret = _getproperty(8, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode lastChild
- # first child of the node
- def lastChild()
- ret = _getproperty(9, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode previousSibling
- # left sibling of the node
- def previousSibling()
- ret = _getproperty(10, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode nextSibling
- # right sibling of the node
- def nextSibling()
- ret = _getproperty(11, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNamedNodeMap attributes
- # the collection of the node's attributes
- def attributes()
- ret = _getproperty(12, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMDocument ownerDocument
- # document that contains the node
- def ownerDocument()
- ret = _getproperty(18, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR nodeTypeString
- # the type of node in string form
- def nodeTypeString()
- ret = _getproperty(21, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR text
- # text content of the node and subtree
- def text()
- ret = _getproperty(24, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL specified
- # indicates whether node is a default value
- def specified()
- ret = _getproperty(22, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode definition
- # pointer to the definition of the node in the DTD or schema
- def definition()
- ret = _getproperty(23, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue()
- ret = _getproperty(25, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT dataType
- # the data type of the node
- def dataType()
- ret = _getproperty(26, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR xml
- # return the XML source for the node and each of its descendants
- def xml()
- ret = _getproperty(27, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL parsed
- # has sub-tree been completely parsed
- def parsed()
- ret = _getproperty(31, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR namespaceURI
- # the URI for the namespace applying to the node
- def namespaceURI()
- ret = _getproperty(32, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR prefix
- # the prefix for the namespace applying to the node
- def prefix()
- ret = _getproperty(33, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR baseName
- # the base name of the node (nodename with the prefix stripped off)
- def baseName()
- ret = _getproperty(34, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR name
- # name of the document type (root of the tree)
- def name()
- ret = _getproperty(131, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNamedNodeMap entities
- # a list of entities in the document
- def entities()
- ret = _getproperty(132, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNamedNodeMap notations
- # a list of notations in the document
- def notations()
- ret = _getproperty(133, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeValue
- # value stored in the node
- def nodeValue=(arg0)
- ret = _setproperty(3, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID text
- # text content of the node and subtree
- def text=(arg0)
- ret = _setproperty(24, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue=(arg0)
- ret = _setproperty(25, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID dataType
- # the data type of the node
- def dataType=(arg0)
- ret = _setproperty(26, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode insertBefore
- # insert a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # VARIANT arg1 --- refChild [IN]
- def insertBefore(arg0, arg1)
- ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode replaceChild
- # replace a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # IXMLDOMNode arg1 --- oldChild [IN]
- def replaceChild(arg0, arg1)
- ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode removeChild
- # remove a child node
- # IXMLDOMNode arg0 --- childNode [IN]
- def removeChild(arg0)
- ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode appendChild
- # append a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- def appendChild(arg0)
- ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL hasChildNodes
- def hasChildNodes()
- ret = _invoke(17, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode cloneNode
- # BOOL arg0 --- deep [IN]
- def cloneNode(arg0)
- ret = _invoke(19, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR transformNode
- # apply the stylesheet to the subtree
- # IXMLDOMNode arg0 --- stylesheet [IN]
- def transformNode(arg0)
- ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList selectNodes
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectNodes(arg0)
- ret = _invoke(29, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode selectSingleNode
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectSingleNode(arg0)
- ret = _invoke(30, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID transformNodeToObject
- # apply the stylesheet to the subtree, returning the result through a document or a stream
- # IXMLDOMNode arg0 --- stylesheet [IN]
- # VARIANT arg1 --- outputObject [IN]
- def transformNodeToObject(arg0, arg1)
- ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-end
-
-#
-module IXMLDOMElement
- include WIN32OLE::VARIANT
- attr_reader :lastargs
-
- # BSTR nodeName
- # name of the node
- def nodeName()
- ret = _getproperty(2, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeValue
- # value stored in the node
- def nodeValue()
- ret = _getproperty(3, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # DOMNodeType nodeType
- # the node's type
- def nodeType()
- ret = _getproperty(4, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode parentNode
- # parent of the node
- def parentNode()
- ret = _getproperty(6, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList childNodes
- # the collection of the node's children
- def childNodes()
- ret = _getproperty(7, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode firstChild
- # first child of the node
- def firstChild()
- ret = _getproperty(8, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode lastChild
- # first child of the node
- def lastChild()
- ret = _getproperty(9, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode previousSibling
- # left sibling of the node
- def previousSibling()
- ret = _getproperty(10, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode nextSibling
- # right sibling of the node
- def nextSibling()
- ret = _getproperty(11, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNamedNodeMap attributes
- # the collection of the node's attributes
- def attributes()
- ret = _getproperty(12, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMDocument ownerDocument
- # document that contains the node
- def ownerDocument()
- ret = _getproperty(18, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR nodeTypeString
- # the type of node in string form
- def nodeTypeString()
- ret = _getproperty(21, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR text
- # text content of the node and subtree
- def text()
- ret = _getproperty(24, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL specified
- # indicates whether node is a default value
- def specified()
- ret = _getproperty(22, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode definition
- # pointer to the definition of the node in the DTD or schema
- def definition()
- ret = _getproperty(23, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue()
- ret = _getproperty(25, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT dataType
- # the data type of the node
- def dataType()
- ret = _getproperty(26, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR xml
- # return the XML source for the node and each of its descendants
- def xml()
- ret = _getproperty(27, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL parsed
- # has sub-tree been completely parsed
- def parsed()
- ret = _getproperty(31, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR namespaceURI
- # the URI for the namespace applying to the node
- def namespaceURI()
- ret = _getproperty(32, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR prefix
- # the prefix for the namespace applying to the node
- def prefix()
- ret = _getproperty(33, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR baseName
- # the base name of the node (nodename with the prefix stripped off)
- def baseName()
- ret = _getproperty(34, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR tagName
- # get the tagName of the element
- def tagName()
- ret = _getproperty(97, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeValue
- # value stored in the node
- def nodeValue=(arg0)
- ret = _setproperty(3, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID text
- # text content of the node and subtree
- def text=(arg0)
- ret = _setproperty(24, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue=(arg0)
- ret = _setproperty(25, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID dataType
- # the data type of the node
- def dataType=(arg0)
- ret = _setproperty(26, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode insertBefore
- # insert a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # VARIANT arg1 --- refChild [IN]
- def insertBefore(arg0, arg1)
- ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode replaceChild
- # replace a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # IXMLDOMNode arg1 --- oldChild [IN]
- def replaceChild(arg0, arg1)
- ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode removeChild
- # remove a child node
- # IXMLDOMNode arg0 --- childNode [IN]
- def removeChild(arg0)
- ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode appendChild
- # append a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- def appendChild(arg0)
- ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL hasChildNodes
- def hasChildNodes()
- ret = _invoke(17, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode cloneNode
- # BOOL arg0 --- deep [IN]
- def cloneNode(arg0)
- ret = _invoke(19, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR transformNode
- # apply the stylesheet to the subtree
- # IXMLDOMNode arg0 --- stylesheet [IN]
- def transformNode(arg0)
- ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList selectNodes
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectNodes(arg0)
- ret = _invoke(29, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode selectSingleNode
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectSingleNode(arg0)
- ret = _invoke(30, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID transformNodeToObject
- # apply the stylesheet to the subtree, returning the result through a document or a stream
- # IXMLDOMNode arg0 --- stylesheet [IN]
- # VARIANT arg1 --- outputObject [IN]
- def transformNodeToObject(arg0, arg1)
- ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT getAttribute
- # look up the string value of an attribute by name
- # BSTR arg0 --- name [IN]
- def getAttribute(arg0)
- ret = _invoke(99, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID setAttribute
- # set the string value of an attribute by name
- # BSTR arg0 --- name [IN]
- # VARIANT arg1 --- value [IN]
- def setAttribute(arg0, arg1)
- ret = _invoke(100, [arg0, arg1], [VT_BSTR, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID removeAttribute
- # remove an attribute by name
- # BSTR arg0 --- name [IN]
- def removeAttribute(arg0)
- ret = _invoke(101, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMAttribute getAttributeNode
- # look up the attribute node by name
- # BSTR arg0 --- name [IN]
- def getAttributeNode(arg0)
- ret = _invoke(102, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMAttribute setAttributeNode
- # set the specified attribute on the element
- # IXMLDOMAttribute arg0 --- DOMAttribute [IN]
- def setAttributeNode(arg0)
- ret = _invoke(103, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMAttribute removeAttributeNode
- # remove the specified attribute
- # IXMLDOMAttribute arg0 --- DOMAttribute [IN]
- def removeAttributeNode(arg0)
- ret = _invoke(104, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList getElementsByTagName
- # build a list of elements by name
- # BSTR arg0 --- tagName [IN]
- def getElementsByTagName(arg0)
- ret = _invoke(105, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID normalize
- # collapse all adjacent text nodes in sub-tree
- def normalize()
- ret = _invoke(106, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-end
-
-#
-module IXMLDOMAttribute
- include WIN32OLE::VARIANT
- attr_reader :lastargs
-
- # BSTR nodeName
- # name of the node
- def nodeName()
- ret = _getproperty(2, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeValue
- # value stored in the node
- def nodeValue()
- ret = _getproperty(3, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # DOMNodeType nodeType
- # the node's type
- def nodeType()
- ret = _getproperty(4, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode parentNode
- # parent of the node
- def parentNode()
- ret = _getproperty(6, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList childNodes
- # the collection of the node's children
- def childNodes()
- ret = _getproperty(7, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode firstChild
- # first child of the node
- def firstChild()
- ret = _getproperty(8, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode lastChild
- # first child of the node
- def lastChild()
- ret = _getproperty(9, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode previousSibling
- # left sibling of the node
- def previousSibling()
- ret = _getproperty(10, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode nextSibling
- # right sibling of the node
- def nextSibling()
- ret = _getproperty(11, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNamedNodeMap attributes
- # the collection of the node's attributes
- def attributes()
- ret = _getproperty(12, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMDocument ownerDocument
- # document that contains the node
- def ownerDocument()
- ret = _getproperty(18, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR nodeTypeString
- # the type of node in string form
- def nodeTypeString()
- ret = _getproperty(21, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR text
- # text content of the node and subtree
- def text()
- ret = _getproperty(24, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL specified
- # indicates whether node is a default value
- def specified()
- ret = _getproperty(22, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode definition
- # pointer to the definition of the node in the DTD or schema
- def definition()
- ret = _getproperty(23, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue()
- ret = _getproperty(25, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT dataType
- # the data type of the node
- def dataType()
- ret = _getproperty(26, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR xml
- # return the XML source for the node and each of its descendants
- def xml()
- ret = _getproperty(27, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL parsed
- # has sub-tree been completely parsed
- def parsed()
- ret = _getproperty(31, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR namespaceURI
- # the URI for the namespace applying to the node
- def namespaceURI()
- ret = _getproperty(32, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR prefix
- # the prefix for the namespace applying to the node
- def prefix()
- ret = _getproperty(33, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR baseName
- # the base name of the node (nodename with the prefix stripped off)
- def baseName()
- ret = _getproperty(34, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR name
- # get name of the attribute
- def name()
- ret = _getproperty(118, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT value
- # string value of the attribute
- def value()
- ret = _getproperty(120, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeValue
- # value stored in the node
- def nodeValue=(arg0)
- ret = _setproperty(3, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID text
- # text content of the node and subtree
- def text=(arg0)
- ret = _setproperty(24, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue=(arg0)
- ret = _setproperty(25, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID dataType
- # the data type of the node
- def dataType=(arg0)
- ret = _setproperty(26, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID value
- # string value of the attribute
- def value=(arg0)
- ret = _setproperty(120, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode insertBefore
- # insert a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # VARIANT arg1 --- refChild [IN]
- def insertBefore(arg0, arg1)
- ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode replaceChild
- # replace a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # IXMLDOMNode arg1 --- oldChild [IN]
- def replaceChild(arg0, arg1)
- ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode removeChild
- # remove a child node
- # IXMLDOMNode arg0 --- childNode [IN]
- def removeChild(arg0)
- ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode appendChild
- # append a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- def appendChild(arg0)
- ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL hasChildNodes
- def hasChildNodes()
- ret = _invoke(17, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode cloneNode
- # BOOL arg0 --- deep [IN]
- def cloneNode(arg0)
- ret = _invoke(19, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR transformNode
- # apply the stylesheet to the subtree
- # IXMLDOMNode arg0 --- stylesheet [IN]
- def transformNode(arg0)
- ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList selectNodes
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectNodes(arg0)
- ret = _invoke(29, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode selectSingleNode
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectSingleNode(arg0)
- ret = _invoke(30, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID transformNodeToObject
- # apply the stylesheet to the subtree, returning the result through a document or a stream
- # IXMLDOMNode arg0 --- stylesheet [IN]
- # VARIANT arg1 --- outputObject [IN]
- def transformNodeToObject(arg0, arg1)
- ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-end
-
-#
-module IXMLDOMDocumentFragment
- include WIN32OLE::VARIANT
- attr_reader :lastargs
-
- # BSTR nodeName
- # name of the node
- def nodeName()
- ret = _getproperty(2, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeValue
- # value stored in the node
- def nodeValue()
- ret = _getproperty(3, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # DOMNodeType nodeType
- # the node's type
- def nodeType()
- ret = _getproperty(4, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode parentNode
- # parent of the node
- def parentNode()
- ret = _getproperty(6, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList childNodes
- # the collection of the node's children
- def childNodes()
- ret = _getproperty(7, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode firstChild
- # first child of the node
- def firstChild()
- ret = _getproperty(8, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode lastChild
- # first child of the node
- def lastChild()
- ret = _getproperty(9, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode previousSibling
- # left sibling of the node
- def previousSibling()
- ret = _getproperty(10, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode nextSibling
- # right sibling of the node
- def nextSibling()
- ret = _getproperty(11, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNamedNodeMap attributes
- # the collection of the node's attributes
- def attributes()
- ret = _getproperty(12, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMDocument ownerDocument
- # document that contains the node
- def ownerDocument()
- ret = _getproperty(18, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR nodeTypeString
- # the type of node in string form
- def nodeTypeString()
- ret = _getproperty(21, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR text
- # text content of the node and subtree
- def text()
- ret = _getproperty(24, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL specified
- # indicates whether node is a default value
- def specified()
- ret = _getproperty(22, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode definition
- # pointer to the definition of the node in the DTD or schema
- def definition()
- ret = _getproperty(23, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue()
- ret = _getproperty(25, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT dataType
- # the data type of the node
- def dataType()
- ret = _getproperty(26, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR xml
- # return the XML source for the node and each of its descendants
- def xml()
- ret = _getproperty(27, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL parsed
- # has sub-tree been completely parsed
- def parsed()
- ret = _getproperty(31, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR namespaceURI
- # the URI for the namespace applying to the node
- def namespaceURI()
- ret = _getproperty(32, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR prefix
- # the prefix for the namespace applying to the node
- def prefix()
- ret = _getproperty(33, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR baseName
- # the base name of the node (nodename with the prefix stripped off)
- def baseName()
- ret = _getproperty(34, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeValue
- # value stored in the node
- def nodeValue=(arg0)
- ret = _setproperty(3, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID text
- # text content of the node and subtree
- def text=(arg0)
- ret = _setproperty(24, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue=(arg0)
- ret = _setproperty(25, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID dataType
- # the data type of the node
- def dataType=(arg0)
- ret = _setproperty(26, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode insertBefore
- # insert a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # VARIANT arg1 --- refChild [IN]
- def insertBefore(arg0, arg1)
- ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode replaceChild
- # replace a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # IXMLDOMNode arg1 --- oldChild [IN]
- def replaceChild(arg0, arg1)
- ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode removeChild
- # remove a child node
- # IXMLDOMNode arg0 --- childNode [IN]
- def removeChild(arg0)
- ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode appendChild
- # append a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- def appendChild(arg0)
- ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL hasChildNodes
- def hasChildNodes()
- ret = _invoke(17, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode cloneNode
- # BOOL arg0 --- deep [IN]
- def cloneNode(arg0)
- ret = _invoke(19, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR transformNode
- # apply the stylesheet to the subtree
- # IXMLDOMNode arg0 --- stylesheet [IN]
- def transformNode(arg0)
- ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList selectNodes
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectNodes(arg0)
- ret = _invoke(29, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode selectSingleNode
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectSingleNode(arg0)
- ret = _invoke(30, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID transformNodeToObject
- # apply the stylesheet to the subtree, returning the result through a document or a stream
- # IXMLDOMNode arg0 --- stylesheet [IN]
- # VARIANT arg1 --- outputObject [IN]
- def transformNodeToObject(arg0, arg1)
- ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-end
-
-#
-module IXMLDOMText
- include WIN32OLE::VARIANT
- attr_reader :lastargs
-
- # BSTR nodeName
- # name of the node
- def nodeName()
- ret = _getproperty(2, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeValue
- # value stored in the node
- def nodeValue()
- ret = _getproperty(3, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # DOMNodeType nodeType
- # the node's type
- def nodeType()
- ret = _getproperty(4, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode parentNode
- # parent of the node
- def parentNode()
- ret = _getproperty(6, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList childNodes
- # the collection of the node's children
- def childNodes()
- ret = _getproperty(7, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode firstChild
- # first child of the node
- def firstChild()
- ret = _getproperty(8, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode lastChild
- # first child of the node
- def lastChild()
- ret = _getproperty(9, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode previousSibling
- # left sibling of the node
- def previousSibling()
- ret = _getproperty(10, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode nextSibling
- # right sibling of the node
- def nextSibling()
- ret = _getproperty(11, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNamedNodeMap attributes
- # the collection of the node's attributes
- def attributes()
- ret = _getproperty(12, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMDocument ownerDocument
- # document that contains the node
- def ownerDocument()
- ret = _getproperty(18, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR nodeTypeString
- # the type of node in string form
- def nodeTypeString()
- ret = _getproperty(21, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR text
- # text content of the node and subtree
- def text()
- ret = _getproperty(24, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL specified
- # indicates whether node is a default value
- def specified()
- ret = _getproperty(22, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode definition
- # pointer to the definition of the node in the DTD or schema
- def definition()
- ret = _getproperty(23, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue()
- ret = _getproperty(25, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT dataType
- # the data type of the node
- def dataType()
- ret = _getproperty(26, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR xml
- # return the XML source for the node and each of its descendants
- def xml()
- ret = _getproperty(27, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL parsed
- # has sub-tree been completely parsed
- def parsed()
- ret = _getproperty(31, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR namespaceURI
- # the URI for the namespace applying to the node
- def namespaceURI()
- ret = _getproperty(32, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR prefix
- # the prefix for the namespace applying to the node
- def prefix()
- ret = _getproperty(33, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR baseName
- # the base name of the node (nodename with the prefix stripped off)
- def baseName()
- ret = _getproperty(34, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR data
- # value of the node
- def data()
- ret = _getproperty(109, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # I4 length
- # number of characters in value
- def length()
- ret = _getproperty(110, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeValue
- # value stored in the node
- def nodeValue=(arg0)
- ret = _setproperty(3, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID text
- # text content of the node and subtree
- def text=(arg0)
- ret = _setproperty(24, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue=(arg0)
- ret = _setproperty(25, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID dataType
- # the data type of the node
- def dataType=(arg0)
- ret = _setproperty(26, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID data
- # value of the node
- def data=(arg0)
- ret = _setproperty(109, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode insertBefore
- # insert a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # VARIANT arg1 --- refChild [IN]
- def insertBefore(arg0, arg1)
- ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode replaceChild
- # replace a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # IXMLDOMNode arg1 --- oldChild [IN]
- def replaceChild(arg0, arg1)
- ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode removeChild
- # remove a child node
- # IXMLDOMNode arg0 --- childNode [IN]
- def removeChild(arg0)
- ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode appendChild
- # append a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- def appendChild(arg0)
- ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL hasChildNodes
- def hasChildNodes()
- ret = _invoke(17, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode cloneNode
- # BOOL arg0 --- deep [IN]
- def cloneNode(arg0)
- ret = _invoke(19, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR transformNode
- # apply the stylesheet to the subtree
- # IXMLDOMNode arg0 --- stylesheet [IN]
- def transformNode(arg0)
- ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList selectNodes
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectNodes(arg0)
- ret = _invoke(29, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode selectSingleNode
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectSingleNode(arg0)
- ret = _invoke(30, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID transformNodeToObject
- # apply the stylesheet to the subtree, returning the result through a document or a stream
- # IXMLDOMNode arg0 --- stylesheet [IN]
- # VARIANT arg1 --- outputObject [IN]
- def transformNodeToObject(arg0, arg1)
- ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR substringData
- # retrieve substring of value
- # I4 arg0 --- offset [IN]
- # I4 arg1 --- count [IN]
- def substringData(arg0, arg1)
- ret = _invoke(111, [arg0, arg1], [VT_I4, VT_I4])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID appendData
- # append string to value
- # BSTR arg0 --- data [IN]
- def appendData(arg0)
- ret = _invoke(112, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID insertData
- # insert string into value
- # I4 arg0 --- offset [IN]
- # BSTR arg1 --- data [IN]
- def insertData(arg0, arg1)
- ret = _invoke(113, [arg0, arg1], [VT_I4, VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID deleteData
- # delete string within the value
- # I4 arg0 --- offset [IN]
- # I4 arg1 --- count [IN]
- def deleteData(arg0, arg1)
- ret = _invoke(114, [arg0, arg1], [VT_I4, VT_I4])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID replaceData
- # replace string within the value
- # I4 arg0 --- offset [IN]
- # I4 arg1 --- count [IN]
- # BSTR arg2 --- data [IN]
- def replaceData(arg0, arg1, arg2)
- ret = _invoke(115, [arg0, arg1, arg2], [VT_I4, VT_I4, VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMText splitText
- # split the text node into two text nodes at the position specified
- # I4 arg0 --- offset [IN]
- def splitText(arg0)
- ret = _invoke(123, [arg0], [VT_I4])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-end
-
-#
-module IXMLDOMCharacterData
- include WIN32OLE::VARIANT
- attr_reader :lastargs
-
- # BSTR nodeName
- # name of the node
- def nodeName()
- ret = _getproperty(2, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeValue
- # value stored in the node
- def nodeValue()
- ret = _getproperty(3, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # DOMNodeType nodeType
- # the node's type
- def nodeType()
- ret = _getproperty(4, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode parentNode
- # parent of the node
- def parentNode()
- ret = _getproperty(6, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList childNodes
- # the collection of the node's children
- def childNodes()
- ret = _getproperty(7, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode firstChild
- # first child of the node
- def firstChild()
- ret = _getproperty(8, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode lastChild
- # first child of the node
- def lastChild()
- ret = _getproperty(9, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode previousSibling
- # left sibling of the node
- def previousSibling()
- ret = _getproperty(10, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode nextSibling
- # right sibling of the node
- def nextSibling()
- ret = _getproperty(11, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNamedNodeMap attributes
- # the collection of the node's attributes
- def attributes()
- ret = _getproperty(12, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMDocument ownerDocument
- # document that contains the node
- def ownerDocument()
- ret = _getproperty(18, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR nodeTypeString
- # the type of node in string form
- def nodeTypeString()
- ret = _getproperty(21, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR text
- # text content of the node and subtree
- def text()
- ret = _getproperty(24, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL specified
- # indicates whether node is a default value
- def specified()
- ret = _getproperty(22, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode definition
- # pointer to the definition of the node in the DTD or schema
- def definition()
- ret = _getproperty(23, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue()
- ret = _getproperty(25, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT dataType
- # the data type of the node
- def dataType()
- ret = _getproperty(26, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR xml
- # return the XML source for the node and each of its descendants
- def xml()
- ret = _getproperty(27, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL parsed
- # has sub-tree been completely parsed
- def parsed()
- ret = _getproperty(31, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR namespaceURI
- # the URI for the namespace applying to the node
- def namespaceURI()
- ret = _getproperty(32, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR prefix
- # the prefix for the namespace applying to the node
- def prefix()
- ret = _getproperty(33, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR baseName
- # the base name of the node (nodename with the prefix stripped off)
- def baseName()
- ret = _getproperty(34, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR data
- # value of the node
- def data()
- ret = _getproperty(109, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # I4 length
- # number of characters in value
- def length()
- ret = _getproperty(110, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeValue
- # value stored in the node
- def nodeValue=(arg0)
- ret = _setproperty(3, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID text
- # text content of the node and subtree
- def text=(arg0)
- ret = _setproperty(24, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue=(arg0)
- ret = _setproperty(25, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID dataType
- # the data type of the node
- def dataType=(arg0)
- ret = _setproperty(26, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID data
- # value of the node
- def data=(arg0)
- ret = _setproperty(109, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode insertBefore
- # insert a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # VARIANT arg1 --- refChild [IN]
- def insertBefore(arg0, arg1)
- ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode replaceChild
- # replace a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # IXMLDOMNode arg1 --- oldChild [IN]
- def replaceChild(arg0, arg1)
- ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode removeChild
- # remove a child node
- # IXMLDOMNode arg0 --- childNode [IN]
- def removeChild(arg0)
- ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode appendChild
- # append a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- def appendChild(arg0)
- ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL hasChildNodes
- def hasChildNodes()
- ret = _invoke(17, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode cloneNode
- # BOOL arg0 --- deep [IN]
- def cloneNode(arg0)
- ret = _invoke(19, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR transformNode
- # apply the stylesheet to the subtree
- # IXMLDOMNode arg0 --- stylesheet [IN]
- def transformNode(arg0)
- ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList selectNodes
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectNodes(arg0)
- ret = _invoke(29, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode selectSingleNode
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectSingleNode(arg0)
- ret = _invoke(30, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID transformNodeToObject
- # apply the stylesheet to the subtree, returning the result through a document or a stream
- # IXMLDOMNode arg0 --- stylesheet [IN]
- # VARIANT arg1 --- outputObject [IN]
- def transformNodeToObject(arg0, arg1)
- ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR substringData
- # retrieve substring of value
- # I4 arg0 --- offset [IN]
- # I4 arg1 --- count [IN]
- def substringData(arg0, arg1)
- ret = _invoke(111, [arg0, arg1], [VT_I4, VT_I4])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID appendData
- # append string to value
- # BSTR arg0 --- data [IN]
- def appendData(arg0)
- ret = _invoke(112, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID insertData
- # insert string into value
- # I4 arg0 --- offset [IN]
- # BSTR arg1 --- data [IN]
- def insertData(arg0, arg1)
- ret = _invoke(113, [arg0, arg1], [VT_I4, VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID deleteData
- # delete string within the value
- # I4 arg0 --- offset [IN]
- # I4 arg1 --- count [IN]
- def deleteData(arg0, arg1)
- ret = _invoke(114, [arg0, arg1], [VT_I4, VT_I4])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID replaceData
- # replace string within the value
- # I4 arg0 --- offset [IN]
- # I4 arg1 --- count [IN]
- # BSTR arg2 --- data [IN]
- def replaceData(arg0, arg1, arg2)
- ret = _invoke(115, [arg0, arg1, arg2], [VT_I4, VT_I4, VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-end
-
-#
-module IXMLDOMComment
- include WIN32OLE::VARIANT
- attr_reader :lastargs
-
- # BSTR nodeName
- # name of the node
- def nodeName()
- ret = _getproperty(2, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeValue
- # value stored in the node
- def nodeValue()
- ret = _getproperty(3, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # DOMNodeType nodeType
- # the node's type
- def nodeType()
- ret = _getproperty(4, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode parentNode
- # parent of the node
- def parentNode()
- ret = _getproperty(6, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList childNodes
- # the collection of the node's children
- def childNodes()
- ret = _getproperty(7, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode firstChild
- # first child of the node
- def firstChild()
- ret = _getproperty(8, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode lastChild
- # first child of the node
- def lastChild()
- ret = _getproperty(9, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode previousSibling
- # left sibling of the node
- def previousSibling()
- ret = _getproperty(10, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode nextSibling
- # right sibling of the node
- def nextSibling()
- ret = _getproperty(11, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNamedNodeMap attributes
- # the collection of the node's attributes
- def attributes()
- ret = _getproperty(12, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMDocument ownerDocument
- # document that contains the node
- def ownerDocument()
- ret = _getproperty(18, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR nodeTypeString
- # the type of node in string form
- def nodeTypeString()
- ret = _getproperty(21, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR text
- # text content of the node and subtree
- def text()
- ret = _getproperty(24, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL specified
- # indicates whether node is a default value
- def specified()
- ret = _getproperty(22, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode definition
- # pointer to the definition of the node in the DTD or schema
- def definition()
- ret = _getproperty(23, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue()
- ret = _getproperty(25, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT dataType
- # the data type of the node
- def dataType()
- ret = _getproperty(26, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR xml
- # return the XML source for the node and each of its descendants
- def xml()
- ret = _getproperty(27, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL parsed
- # has sub-tree been completely parsed
- def parsed()
- ret = _getproperty(31, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR namespaceURI
- # the URI for the namespace applying to the node
- def namespaceURI()
- ret = _getproperty(32, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR prefix
- # the prefix for the namespace applying to the node
- def prefix()
- ret = _getproperty(33, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR baseName
- # the base name of the node (nodename with the prefix stripped off)
- def baseName()
- ret = _getproperty(34, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR data
- # value of the node
- def data()
- ret = _getproperty(109, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # I4 length
- # number of characters in value
- def length()
- ret = _getproperty(110, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeValue
- # value stored in the node
- def nodeValue=(arg0)
- ret = _setproperty(3, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID text
- # text content of the node and subtree
- def text=(arg0)
- ret = _setproperty(24, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue=(arg0)
- ret = _setproperty(25, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID dataType
- # the data type of the node
- def dataType=(arg0)
- ret = _setproperty(26, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID data
- # value of the node
- def data=(arg0)
- ret = _setproperty(109, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode insertBefore
- # insert a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # VARIANT arg1 --- refChild [IN]
- def insertBefore(arg0, arg1)
- ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode replaceChild
- # replace a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # IXMLDOMNode arg1 --- oldChild [IN]
- def replaceChild(arg0, arg1)
- ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode removeChild
- # remove a child node
- # IXMLDOMNode arg0 --- childNode [IN]
- def removeChild(arg0)
- ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode appendChild
- # append a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- def appendChild(arg0)
- ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL hasChildNodes
- def hasChildNodes()
- ret = _invoke(17, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode cloneNode
- # BOOL arg0 --- deep [IN]
- def cloneNode(arg0)
- ret = _invoke(19, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR transformNode
- # apply the stylesheet to the subtree
- # IXMLDOMNode arg0 --- stylesheet [IN]
- def transformNode(arg0)
- ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList selectNodes
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectNodes(arg0)
- ret = _invoke(29, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode selectSingleNode
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectSingleNode(arg0)
- ret = _invoke(30, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID transformNodeToObject
- # apply the stylesheet to the subtree, returning the result through a document or a stream
- # IXMLDOMNode arg0 --- stylesheet [IN]
- # VARIANT arg1 --- outputObject [IN]
- def transformNodeToObject(arg0, arg1)
- ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR substringData
- # retrieve substring of value
- # I4 arg0 --- offset [IN]
- # I4 arg1 --- count [IN]
- def substringData(arg0, arg1)
- ret = _invoke(111, [arg0, arg1], [VT_I4, VT_I4])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID appendData
- # append string to value
- # BSTR arg0 --- data [IN]
- def appendData(arg0)
- ret = _invoke(112, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID insertData
- # insert string into value
- # I4 arg0 --- offset [IN]
- # BSTR arg1 --- data [IN]
- def insertData(arg0, arg1)
- ret = _invoke(113, [arg0, arg1], [VT_I4, VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID deleteData
- # delete string within the value
- # I4 arg0 --- offset [IN]
- # I4 arg1 --- count [IN]
- def deleteData(arg0, arg1)
- ret = _invoke(114, [arg0, arg1], [VT_I4, VT_I4])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID replaceData
- # replace string within the value
- # I4 arg0 --- offset [IN]
- # I4 arg1 --- count [IN]
- # BSTR arg2 --- data [IN]
- def replaceData(arg0, arg1, arg2)
- ret = _invoke(115, [arg0, arg1, arg2], [VT_I4, VT_I4, VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-end
-
-#
-module IXMLDOMCDATASection
- include WIN32OLE::VARIANT
- attr_reader :lastargs
-
- # BSTR nodeName
- # name of the node
- def nodeName()
- ret = _getproperty(2, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeValue
- # value stored in the node
- def nodeValue()
- ret = _getproperty(3, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # DOMNodeType nodeType
- # the node's type
- def nodeType()
- ret = _getproperty(4, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode parentNode
- # parent of the node
- def parentNode()
- ret = _getproperty(6, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList childNodes
- # the collection of the node's children
- def childNodes()
- ret = _getproperty(7, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode firstChild
- # first child of the node
- def firstChild()
- ret = _getproperty(8, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode lastChild
- # first child of the node
- def lastChild()
- ret = _getproperty(9, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode previousSibling
- # left sibling of the node
- def previousSibling()
- ret = _getproperty(10, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode nextSibling
- # right sibling of the node
- def nextSibling()
- ret = _getproperty(11, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNamedNodeMap attributes
- # the collection of the node's attributes
- def attributes()
- ret = _getproperty(12, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMDocument ownerDocument
- # document that contains the node
- def ownerDocument()
- ret = _getproperty(18, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR nodeTypeString
- # the type of node in string form
- def nodeTypeString()
- ret = _getproperty(21, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR text
- # text content of the node and subtree
- def text()
- ret = _getproperty(24, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL specified
- # indicates whether node is a default value
- def specified()
- ret = _getproperty(22, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode definition
- # pointer to the definition of the node in the DTD or schema
- def definition()
- ret = _getproperty(23, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue()
- ret = _getproperty(25, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT dataType
- # the data type of the node
- def dataType()
- ret = _getproperty(26, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR xml
- # return the XML source for the node and each of its descendants
- def xml()
- ret = _getproperty(27, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL parsed
- # has sub-tree been completely parsed
- def parsed()
- ret = _getproperty(31, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR namespaceURI
- # the URI for the namespace applying to the node
- def namespaceURI()
- ret = _getproperty(32, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR prefix
- # the prefix for the namespace applying to the node
- def prefix()
- ret = _getproperty(33, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR baseName
- # the base name of the node (nodename with the prefix stripped off)
- def baseName()
- ret = _getproperty(34, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR data
- # value of the node
- def data()
- ret = _getproperty(109, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # I4 length
- # number of characters in value
- def length()
- ret = _getproperty(110, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeValue
- # value stored in the node
- def nodeValue=(arg0)
- ret = _setproperty(3, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID text
- # text content of the node and subtree
- def text=(arg0)
- ret = _setproperty(24, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue=(arg0)
- ret = _setproperty(25, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID dataType
- # the data type of the node
- def dataType=(arg0)
- ret = _setproperty(26, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID data
- # value of the node
- def data=(arg0)
- ret = _setproperty(109, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode insertBefore
- # insert a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # VARIANT arg1 --- refChild [IN]
- def insertBefore(arg0, arg1)
- ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode replaceChild
- # replace a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # IXMLDOMNode arg1 --- oldChild [IN]
- def replaceChild(arg0, arg1)
- ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode removeChild
- # remove a child node
- # IXMLDOMNode arg0 --- childNode [IN]
- def removeChild(arg0)
- ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode appendChild
- # append a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- def appendChild(arg0)
- ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL hasChildNodes
- def hasChildNodes()
- ret = _invoke(17, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode cloneNode
- # BOOL arg0 --- deep [IN]
- def cloneNode(arg0)
- ret = _invoke(19, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR transformNode
- # apply the stylesheet to the subtree
- # IXMLDOMNode arg0 --- stylesheet [IN]
- def transformNode(arg0)
- ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList selectNodes
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectNodes(arg0)
- ret = _invoke(29, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode selectSingleNode
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectSingleNode(arg0)
- ret = _invoke(30, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID transformNodeToObject
- # apply the stylesheet to the subtree, returning the result through a document or a stream
- # IXMLDOMNode arg0 --- stylesheet [IN]
- # VARIANT arg1 --- outputObject [IN]
- def transformNodeToObject(arg0, arg1)
- ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR substringData
- # retrieve substring of value
- # I4 arg0 --- offset [IN]
- # I4 arg1 --- count [IN]
- def substringData(arg0, arg1)
- ret = _invoke(111, [arg0, arg1], [VT_I4, VT_I4])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID appendData
- # append string to value
- # BSTR arg0 --- data [IN]
- def appendData(arg0)
- ret = _invoke(112, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID insertData
- # insert string into value
- # I4 arg0 --- offset [IN]
- # BSTR arg1 --- data [IN]
- def insertData(arg0, arg1)
- ret = _invoke(113, [arg0, arg1], [VT_I4, VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID deleteData
- # delete string within the value
- # I4 arg0 --- offset [IN]
- # I4 arg1 --- count [IN]
- def deleteData(arg0, arg1)
- ret = _invoke(114, [arg0, arg1], [VT_I4, VT_I4])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID replaceData
- # replace string within the value
- # I4 arg0 --- offset [IN]
- # I4 arg1 --- count [IN]
- # BSTR arg2 --- data [IN]
- def replaceData(arg0, arg1, arg2)
- ret = _invoke(115, [arg0, arg1, arg2], [VT_I4, VT_I4, VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMText splitText
- # split the text node into two text nodes at the position specified
- # I4 arg0 --- offset [IN]
- def splitText(arg0)
- ret = _invoke(123, [arg0], [VT_I4])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-end
-
-#
-module IXMLDOMProcessingInstruction
- include WIN32OLE::VARIANT
- attr_reader :lastargs
-
- # BSTR nodeName
- # name of the node
- def nodeName()
- ret = _getproperty(2, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeValue
- # value stored in the node
- def nodeValue()
- ret = _getproperty(3, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # DOMNodeType nodeType
- # the node's type
- def nodeType()
- ret = _getproperty(4, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode parentNode
- # parent of the node
- def parentNode()
- ret = _getproperty(6, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList childNodes
- # the collection of the node's children
- def childNodes()
- ret = _getproperty(7, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode firstChild
- # first child of the node
- def firstChild()
- ret = _getproperty(8, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode lastChild
- # first child of the node
- def lastChild()
- ret = _getproperty(9, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode previousSibling
- # left sibling of the node
- def previousSibling()
- ret = _getproperty(10, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode nextSibling
- # right sibling of the node
- def nextSibling()
- ret = _getproperty(11, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNamedNodeMap attributes
- # the collection of the node's attributes
- def attributes()
- ret = _getproperty(12, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMDocument ownerDocument
- # document that contains the node
- def ownerDocument()
- ret = _getproperty(18, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR nodeTypeString
- # the type of node in string form
- def nodeTypeString()
- ret = _getproperty(21, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR text
- # text content of the node and subtree
- def text()
- ret = _getproperty(24, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL specified
- # indicates whether node is a default value
- def specified()
- ret = _getproperty(22, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode definition
- # pointer to the definition of the node in the DTD or schema
- def definition()
- ret = _getproperty(23, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue()
- ret = _getproperty(25, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT dataType
- # the data type of the node
- def dataType()
- ret = _getproperty(26, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR xml
- # return the XML source for the node and each of its descendants
- def xml()
- ret = _getproperty(27, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL parsed
- # has sub-tree been completely parsed
- def parsed()
- ret = _getproperty(31, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR namespaceURI
- # the URI for the namespace applying to the node
- def namespaceURI()
- ret = _getproperty(32, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR prefix
- # the prefix for the namespace applying to the node
- def prefix()
- ret = _getproperty(33, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR baseName
- # the base name of the node (nodename with the prefix stripped off)
- def baseName()
- ret = _getproperty(34, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR target
- # the target
- def target()
- ret = _getproperty(127, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR data
- # the data
- def data()
- ret = _getproperty(128, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeValue
- # value stored in the node
- def nodeValue=(arg0)
- ret = _setproperty(3, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID text
- # text content of the node and subtree
- def text=(arg0)
- ret = _setproperty(24, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue=(arg0)
- ret = _setproperty(25, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID dataType
- # the data type of the node
- def dataType=(arg0)
- ret = _setproperty(26, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID data
- # the data
- def data=(arg0)
- ret = _setproperty(128, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode insertBefore
- # insert a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # VARIANT arg1 --- refChild [IN]
- def insertBefore(arg0, arg1)
- ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode replaceChild
- # replace a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # IXMLDOMNode arg1 --- oldChild [IN]
- def replaceChild(arg0, arg1)
- ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode removeChild
- # remove a child node
- # IXMLDOMNode arg0 --- childNode [IN]
- def removeChild(arg0)
- ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode appendChild
- # append a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- def appendChild(arg0)
- ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL hasChildNodes
- def hasChildNodes()
- ret = _invoke(17, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode cloneNode
- # BOOL arg0 --- deep [IN]
- def cloneNode(arg0)
- ret = _invoke(19, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR transformNode
- # apply the stylesheet to the subtree
- # IXMLDOMNode arg0 --- stylesheet [IN]
- def transformNode(arg0)
- ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList selectNodes
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectNodes(arg0)
- ret = _invoke(29, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode selectSingleNode
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectSingleNode(arg0)
- ret = _invoke(30, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID transformNodeToObject
- # apply the stylesheet to the subtree, returning the result through a document or a stream
- # IXMLDOMNode arg0 --- stylesheet [IN]
- # VARIANT arg1 --- outputObject [IN]
- def transformNodeToObject(arg0, arg1)
- ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-end
-
-#
-module IXMLDOMEntityReference
- include WIN32OLE::VARIANT
- attr_reader :lastargs
-
- # BSTR nodeName
- # name of the node
- def nodeName()
- ret = _getproperty(2, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeValue
- # value stored in the node
- def nodeValue()
- ret = _getproperty(3, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # DOMNodeType nodeType
- # the node's type
- def nodeType()
- ret = _getproperty(4, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode parentNode
- # parent of the node
- def parentNode()
- ret = _getproperty(6, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList childNodes
- # the collection of the node's children
- def childNodes()
- ret = _getproperty(7, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode firstChild
- # first child of the node
- def firstChild()
- ret = _getproperty(8, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode lastChild
- # first child of the node
- def lastChild()
- ret = _getproperty(9, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode previousSibling
- # left sibling of the node
- def previousSibling()
- ret = _getproperty(10, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode nextSibling
- # right sibling of the node
- def nextSibling()
- ret = _getproperty(11, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNamedNodeMap attributes
- # the collection of the node's attributes
- def attributes()
- ret = _getproperty(12, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMDocument ownerDocument
- # document that contains the node
- def ownerDocument()
- ret = _getproperty(18, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR nodeTypeString
- # the type of node in string form
- def nodeTypeString()
- ret = _getproperty(21, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR text
- # text content of the node and subtree
- def text()
- ret = _getproperty(24, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL specified
- # indicates whether node is a default value
- def specified()
- ret = _getproperty(22, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode definition
- # pointer to the definition of the node in the DTD or schema
- def definition()
- ret = _getproperty(23, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue()
- ret = _getproperty(25, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT dataType
- # the data type of the node
- def dataType()
- ret = _getproperty(26, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR xml
- # return the XML source for the node and each of its descendants
- def xml()
- ret = _getproperty(27, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL parsed
- # has sub-tree been completely parsed
- def parsed()
- ret = _getproperty(31, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR namespaceURI
- # the URI for the namespace applying to the node
- def namespaceURI()
- ret = _getproperty(32, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR prefix
- # the prefix for the namespace applying to the node
- def prefix()
- ret = _getproperty(33, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR baseName
- # the base name of the node (nodename with the prefix stripped off)
- def baseName()
- ret = _getproperty(34, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeValue
- # value stored in the node
- def nodeValue=(arg0)
- ret = _setproperty(3, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID text
- # text content of the node and subtree
- def text=(arg0)
- ret = _setproperty(24, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue=(arg0)
- ret = _setproperty(25, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID dataType
- # the data type of the node
- def dataType=(arg0)
- ret = _setproperty(26, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode insertBefore
- # insert a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # VARIANT arg1 --- refChild [IN]
- def insertBefore(arg0, arg1)
- ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode replaceChild
- # replace a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # IXMLDOMNode arg1 --- oldChild [IN]
- def replaceChild(arg0, arg1)
- ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode removeChild
- # remove a child node
- # IXMLDOMNode arg0 --- childNode [IN]
- def removeChild(arg0)
- ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode appendChild
- # append a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- def appendChild(arg0)
- ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL hasChildNodes
- def hasChildNodes()
- ret = _invoke(17, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode cloneNode
- # BOOL arg0 --- deep [IN]
- def cloneNode(arg0)
- ret = _invoke(19, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR transformNode
- # apply the stylesheet to the subtree
- # IXMLDOMNode arg0 --- stylesheet [IN]
- def transformNode(arg0)
- ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList selectNodes
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectNodes(arg0)
- ret = _invoke(29, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode selectSingleNode
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectSingleNode(arg0)
- ret = _invoke(30, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID transformNodeToObject
- # apply the stylesheet to the subtree, returning the result through a document or a stream
- # IXMLDOMNode arg0 --- stylesheet [IN]
- # VARIANT arg1 --- outputObject [IN]
- def transformNodeToObject(arg0, arg1)
- ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-end
-
-# structure for reporting parser errors
-module IXMLDOMParseError
- include WIN32OLE::VARIANT
- attr_reader :lastargs
-
- # I4 errorCode
- # the error code
- def errorCode()
- ret = _getproperty(0, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR url
- # the URL of the XML document containing the error
- def url()
- ret = _getproperty(179, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR reason
- # the cause of the error
- def reason()
- ret = _getproperty(180, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR srcText
- # the data where the error occurred
- def srcText()
- ret = _getproperty(181, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # I4 line
- # the line number in the XML document where the error occurred
- def line()
- ret = _getproperty(182, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # I4 linepos
- # the character position in the line containing the error
- def linepos()
- ret = _getproperty(183, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # I4 filepos
- # the absolute file position in the XML document containing the error
- def filepos()
- ret = _getproperty(184, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-end
-
-#
-module IXMLDOMNotation
- include WIN32OLE::VARIANT
- attr_reader :lastargs
-
- # BSTR nodeName
- # name of the node
- def nodeName()
- ret = _getproperty(2, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeValue
- # value stored in the node
- def nodeValue()
- ret = _getproperty(3, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # DOMNodeType nodeType
- # the node's type
- def nodeType()
- ret = _getproperty(4, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode parentNode
- # parent of the node
- def parentNode()
- ret = _getproperty(6, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList childNodes
- # the collection of the node's children
- def childNodes()
- ret = _getproperty(7, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode firstChild
- # first child of the node
- def firstChild()
- ret = _getproperty(8, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode lastChild
- # first child of the node
- def lastChild()
- ret = _getproperty(9, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode previousSibling
- # left sibling of the node
- def previousSibling()
- ret = _getproperty(10, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode nextSibling
- # right sibling of the node
- def nextSibling()
- ret = _getproperty(11, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNamedNodeMap attributes
- # the collection of the node's attributes
- def attributes()
- ret = _getproperty(12, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMDocument ownerDocument
- # document that contains the node
- def ownerDocument()
- ret = _getproperty(18, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR nodeTypeString
- # the type of node in string form
- def nodeTypeString()
- ret = _getproperty(21, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR text
- # text content of the node and subtree
- def text()
- ret = _getproperty(24, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL specified
- # indicates whether node is a default value
- def specified()
- ret = _getproperty(22, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode definition
- # pointer to the definition of the node in the DTD or schema
- def definition()
- ret = _getproperty(23, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue()
- ret = _getproperty(25, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT dataType
- # the data type of the node
- def dataType()
- ret = _getproperty(26, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR xml
- # return the XML source for the node and each of its descendants
- def xml()
- ret = _getproperty(27, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL parsed
- # has sub-tree been completely parsed
- def parsed()
- ret = _getproperty(31, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR namespaceURI
- # the URI for the namespace applying to the node
- def namespaceURI()
- ret = _getproperty(32, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR prefix
- # the prefix for the namespace applying to the node
- def prefix()
- ret = _getproperty(33, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR baseName
- # the base name of the node (nodename with the prefix stripped off)
- def baseName()
- ret = _getproperty(34, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT publicId
- # the public ID
- def publicId()
- ret = _getproperty(136, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT systemId
- # the system ID
- def systemId()
- ret = _getproperty(137, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeValue
- # value stored in the node
- def nodeValue=(arg0)
- ret = _setproperty(3, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID text
- # text content of the node and subtree
- def text=(arg0)
- ret = _setproperty(24, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue=(arg0)
- ret = _setproperty(25, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID dataType
- # the data type of the node
- def dataType=(arg0)
- ret = _setproperty(26, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode insertBefore
- # insert a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # VARIANT arg1 --- refChild [IN]
- def insertBefore(arg0, arg1)
- ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode replaceChild
- # replace a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # IXMLDOMNode arg1 --- oldChild [IN]
- def replaceChild(arg0, arg1)
- ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode removeChild
- # remove a child node
- # IXMLDOMNode arg0 --- childNode [IN]
- def removeChild(arg0)
- ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode appendChild
- # append a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- def appendChild(arg0)
- ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL hasChildNodes
- def hasChildNodes()
- ret = _invoke(17, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode cloneNode
- # BOOL arg0 --- deep [IN]
- def cloneNode(arg0)
- ret = _invoke(19, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR transformNode
- # apply the stylesheet to the subtree
- # IXMLDOMNode arg0 --- stylesheet [IN]
- def transformNode(arg0)
- ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList selectNodes
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectNodes(arg0)
- ret = _invoke(29, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode selectSingleNode
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectSingleNode(arg0)
- ret = _invoke(30, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID transformNodeToObject
- # apply the stylesheet to the subtree, returning the result through a document or a stream
- # IXMLDOMNode arg0 --- stylesheet [IN]
- # VARIANT arg1 --- outputObject [IN]
- def transformNodeToObject(arg0, arg1)
- ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-end
-
-#
-module IXMLDOMEntity
- include WIN32OLE::VARIANT
- attr_reader :lastargs
-
- # BSTR nodeName
- # name of the node
- def nodeName()
- ret = _getproperty(2, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeValue
- # value stored in the node
- def nodeValue()
- ret = _getproperty(3, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # DOMNodeType nodeType
- # the node's type
- def nodeType()
- ret = _getproperty(4, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode parentNode
- # parent of the node
- def parentNode()
- ret = _getproperty(6, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList childNodes
- # the collection of the node's children
- def childNodes()
- ret = _getproperty(7, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode firstChild
- # first child of the node
- def firstChild()
- ret = _getproperty(8, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode lastChild
- # first child of the node
- def lastChild()
- ret = _getproperty(9, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode previousSibling
- # left sibling of the node
- def previousSibling()
- ret = _getproperty(10, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode nextSibling
- # right sibling of the node
- def nextSibling()
- ret = _getproperty(11, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNamedNodeMap attributes
- # the collection of the node's attributes
- def attributes()
- ret = _getproperty(12, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMDocument ownerDocument
- # document that contains the node
- def ownerDocument()
- ret = _getproperty(18, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR nodeTypeString
- # the type of node in string form
- def nodeTypeString()
- ret = _getproperty(21, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR text
- # text content of the node and subtree
- def text()
- ret = _getproperty(24, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL specified
- # indicates whether node is a default value
- def specified()
- ret = _getproperty(22, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode definition
- # pointer to the definition of the node in the DTD or schema
- def definition()
- ret = _getproperty(23, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue()
- ret = _getproperty(25, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT dataType
- # the data type of the node
- def dataType()
- ret = _getproperty(26, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR xml
- # return the XML source for the node and each of its descendants
- def xml()
- ret = _getproperty(27, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL parsed
- # has sub-tree been completely parsed
- def parsed()
- ret = _getproperty(31, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR namespaceURI
- # the URI for the namespace applying to the node
- def namespaceURI()
- ret = _getproperty(32, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR prefix
- # the prefix for the namespace applying to the node
- def prefix()
- ret = _getproperty(33, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR baseName
- # the base name of the node (nodename with the prefix stripped off)
- def baseName()
- ret = _getproperty(34, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT publicId
- # the public ID
- def publicId()
- ret = _getproperty(140, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT systemId
- # the system ID
- def systemId()
- ret = _getproperty(141, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR notationName
- # the name of the notation
- def notationName()
- ret = _getproperty(142, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeValue
- # value stored in the node
- def nodeValue=(arg0)
- ret = _setproperty(3, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID text
- # text content of the node and subtree
- def text=(arg0)
- ret = _setproperty(24, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue=(arg0)
- ret = _setproperty(25, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID dataType
- # the data type of the node
- def dataType=(arg0)
- ret = _setproperty(26, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode insertBefore
- # insert a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # VARIANT arg1 --- refChild [IN]
- def insertBefore(arg0, arg1)
- ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode replaceChild
- # replace a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # IXMLDOMNode arg1 --- oldChild [IN]
- def replaceChild(arg0, arg1)
- ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode removeChild
- # remove a child node
- # IXMLDOMNode arg0 --- childNode [IN]
- def removeChild(arg0)
- ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode appendChild
- # append a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- def appendChild(arg0)
- ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL hasChildNodes
- def hasChildNodes()
- ret = _invoke(17, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode cloneNode
- # BOOL arg0 --- deep [IN]
- def cloneNode(arg0)
- ret = _invoke(19, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR transformNode
- # apply the stylesheet to the subtree
- # IXMLDOMNode arg0 --- stylesheet [IN]
- def transformNode(arg0)
- ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList selectNodes
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectNodes(arg0)
- ret = _invoke(29, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode selectSingleNode
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectSingleNode(arg0)
- ret = _invoke(30, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID transformNodeToObject
- # apply the stylesheet to the subtree, returning the result through a document or a stream
- # IXMLDOMNode arg0 --- stylesheet [IN]
- # VARIANT arg1 --- outputObject [IN]
- def transformNodeToObject(arg0, arg1)
- ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-end
-
-# XTL runtime object
-module IXTLRuntime
- include WIN32OLE::VARIANT
- attr_reader :lastargs
-
- # BSTR nodeName
- # name of the node
- def nodeName()
- ret = _getproperty(2, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeValue
- # value stored in the node
- def nodeValue()
- ret = _getproperty(3, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # DOMNodeType nodeType
- # the node's type
- def nodeType()
- ret = _getproperty(4, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode parentNode
- # parent of the node
- def parentNode()
- ret = _getproperty(6, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList childNodes
- # the collection of the node's children
- def childNodes()
- ret = _getproperty(7, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode firstChild
- # first child of the node
- def firstChild()
- ret = _getproperty(8, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode lastChild
- # first child of the node
- def lastChild()
- ret = _getproperty(9, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode previousSibling
- # left sibling of the node
- def previousSibling()
- ret = _getproperty(10, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode nextSibling
- # right sibling of the node
- def nextSibling()
- ret = _getproperty(11, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNamedNodeMap attributes
- # the collection of the node's attributes
- def attributes()
- ret = _getproperty(12, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMDocument ownerDocument
- # document that contains the node
- def ownerDocument()
- ret = _getproperty(18, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR nodeTypeString
- # the type of node in string form
- def nodeTypeString()
- ret = _getproperty(21, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR text
- # text content of the node and subtree
- def text()
- ret = _getproperty(24, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL specified
- # indicates whether node is a default value
- def specified()
- ret = _getproperty(22, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode definition
- # pointer to the definition of the node in the DTD or schema
- def definition()
- ret = _getproperty(23, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue()
- ret = _getproperty(25, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT dataType
- # the data type of the node
- def dataType()
- ret = _getproperty(26, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR xml
- # return the XML source for the node and each of its descendants
- def xml()
- ret = _getproperty(27, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL parsed
- # has sub-tree been completely parsed
- def parsed()
- ret = _getproperty(31, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR namespaceURI
- # the URI for the namespace applying to the node
- def namespaceURI()
- ret = _getproperty(32, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR prefix
- # the prefix for the namespace applying to the node
- def prefix()
- ret = _getproperty(33, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR baseName
- # the base name of the node (nodename with the prefix stripped off)
- def baseName()
- ret = _getproperty(34, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeValue
- # value stored in the node
- def nodeValue=(arg0)
- ret = _setproperty(3, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID text
- # text content of the node and subtree
- def text=(arg0)
- ret = _setproperty(24, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue=(arg0)
- ret = _setproperty(25, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID dataType
- # the data type of the node
- def dataType=(arg0)
- ret = _setproperty(26, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode insertBefore
- # insert a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # VARIANT arg1 --- refChild [IN]
- def insertBefore(arg0, arg1)
- ret = _invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode replaceChild
- # replace a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # IXMLDOMNode arg1 --- oldChild [IN]
- def replaceChild(arg0, arg1)
- ret = _invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode removeChild
- # remove a child node
- # IXMLDOMNode arg0 --- childNode [IN]
- def removeChild(arg0)
- ret = _invoke(15, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode appendChild
- # append a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- def appendChild(arg0)
- ret = _invoke(16, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL hasChildNodes
- def hasChildNodes()
- ret = _invoke(17, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode cloneNode
- # BOOL arg0 --- deep [IN]
- def cloneNode(arg0)
- ret = _invoke(19, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR transformNode
- # apply the stylesheet to the subtree
- # IXMLDOMNode arg0 --- stylesheet [IN]
- def transformNode(arg0)
- ret = _invoke(28, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList selectNodes
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectNodes(arg0)
- ret = _invoke(29, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode selectSingleNode
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectSingleNode(arg0)
- ret = _invoke(30, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID transformNodeToObject
- # apply the stylesheet to the subtree, returning the result through a document or a stream
- # IXMLDOMNode arg0 --- stylesheet [IN]
- # VARIANT arg1 --- outputObject [IN]
- def transformNodeToObject(arg0, arg1)
- ret = _invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # I4 uniqueID
- # IXMLDOMNode arg0 --- pNode [IN]
- def uniqueID(arg0)
- ret = _invoke(187, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # I4 depth
- # IXMLDOMNode arg0 --- pNode [IN]
- def depth(arg0)
- ret = _invoke(188, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # I4 childNumber
- # IXMLDOMNode arg0 --- pNode [IN]
- def childNumber(arg0)
- ret = _invoke(189, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # I4 ancestorChildNumber
- # BSTR arg0 --- bstrNodeName [IN]
- # IXMLDOMNode arg1 --- pNode [IN]
- def ancestorChildNumber(arg0, arg1)
- ret = _invoke(190, [arg0, arg1], [VT_BSTR, VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # I4 absoluteChildNumber
- # IXMLDOMNode arg0 --- pNode [IN]
- def absoluteChildNumber(arg0)
- ret = _invoke(191, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR formatIndex
- # I4 arg0 --- lIndex [IN]
- # BSTR arg1 --- bstrFormat [IN]
- def formatIndex(arg0, arg1)
- ret = _invoke(192, [arg0, arg1], [VT_I4, VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR formatNumber
- # R8 arg0 --- dblNumber [IN]
- # BSTR arg1 --- bstrFormat [IN]
- def formatNumber(arg0, arg1)
- ret = _invoke(193, [arg0, arg1], [VT_R8, VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR formatDate
- # VARIANT arg0 --- varDate [IN]
- # BSTR arg1 --- bstrFormat [IN]
- # VARIANT arg2 --- varDestLocale [IN]
- def formatDate(arg0, arg1, arg2=nil)
- ret = _invoke(194, [arg0, arg1, arg2], [VT_VARIANT, VT_BSTR, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR formatTime
- # VARIANT arg0 --- varTime [IN]
- # BSTR arg1 --- bstrFormat [IN]
- # VARIANT arg2 --- varDestLocale [IN]
- def formatTime(arg0, arg1, arg2=nil)
- ret = _invoke(195, [arg0, arg1, arg2], [VT_VARIANT, VT_BSTR, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-end
-
-# W3C-DOM XML Document
-class Microsoft_XMLDOM_1_0 # DOMDocument
- include WIN32OLE::VARIANT
- attr_reader :lastargs
- attr_reader :dispatch
- attr_reader :clsid
- attr_reader :progid
-
- def initialize(obj = nil)
- @clsid = "{2933BF90-7B36-11D2-B20E-00C04F983E60}"
- @progid = "Microsoft.XMLDOM.1.0"
- if obj.nil?
- @dispatch = WIN32OLE.new(@progid)
- else
- @dispatch = obj
- end
- end
-
- def method_missing(cmd, *arg)
- @dispatch.method_missing(cmd, *arg)
- end
-
- # BSTR nodeName
- # name of the node
- def nodeName()
- ret = @dispatch._getproperty(2, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeValue
- # value stored in the node
- def nodeValue()
- ret = @dispatch._getproperty(3, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # DOMNodeType nodeType
- # the node's type
- def nodeType()
- ret = @dispatch._getproperty(4, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode parentNode
- # parent of the node
- def parentNode()
- ret = @dispatch._getproperty(6, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList childNodes
- # the collection of the node's children
- def childNodes()
- ret = @dispatch._getproperty(7, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode firstChild
- # first child of the node
- def firstChild()
- ret = @dispatch._getproperty(8, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode lastChild
- # first child of the node
- def lastChild()
- ret = @dispatch._getproperty(9, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode previousSibling
- # left sibling of the node
- def previousSibling()
- ret = @dispatch._getproperty(10, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode nextSibling
- # right sibling of the node
- def nextSibling()
- ret = @dispatch._getproperty(11, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNamedNodeMap attributes
- # the collection of the node's attributes
- def attributes()
- ret = @dispatch._getproperty(12, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMDocument ownerDocument
- # document that contains the node
- def ownerDocument()
- ret = @dispatch._getproperty(18, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR nodeTypeString
- # the type of node in string form
- def nodeTypeString()
- ret = @dispatch._getproperty(21, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR text
- # text content of the node and subtree
- def text()
- ret = @dispatch._getproperty(24, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL specified
- # indicates whether node is a default value
- def specified()
- ret = @dispatch._getproperty(22, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode definition
- # pointer to the definition of the node in the DTD or schema
- def definition()
- ret = @dispatch._getproperty(23, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue()
- ret = @dispatch._getproperty(25, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT dataType
- # the data type of the node
- def dataType()
- ret = @dispatch._getproperty(26, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR xml
- # return the XML source for the node and each of its descendants
- def xml()
- ret = @dispatch._getproperty(27, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL parsed
- # has sub-tree been completely parsed
- def parsed()
- ret = @dispatch._getproperty(31, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR namespaceURI
- # the URI for the namespace applying to the node
- def namespaceURI()
- ret = @dispatch._getproperty(32, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR prefix
- # the prefix for the namespace applying to the node
- def prefix()
- ret = @dispatch._getproperty(33, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR baseName
- # the base name of the node (nodename with the prefix stripped off)
- def baseName()
- ret = @dispatch._getproperty(34, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMDocumentType doctype
- # node corresponding to the DOCTYPE
- def doctype()
- ret = @dispatch._getproperty(38, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMImplementation implementation
- # info on this DOM implementation
- def implementation()
- ret = @dispatch._getproperty(39, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMElement documentElement
- # the root of the tree
- def documentElement()
- ret = @dispatch._getproperty(40, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # I4 readyState
- # get the state of the XML document
- def readyState()
- ret = @dispatch._getproperty(-525, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMParseError parseError
- # get the last parser error
- def parseError()
- ret = @dispatch._getproperty(59, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR url
- # get the URL for the loaded XML document
- def url()
- ret = @dispatch._getproperty(60, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL async
- # flag for asynchronous download
- def async()
- ret = @dispatch._getproperty(61, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL validateOnParse
- # indicates whether the parser performs validation
- def validateOnParse()
- ret = @dispatch._getproperty(65, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL resolveExternals
- # indicates whether the parser resolves references to external DTD/Entities/Schema
- def resolveExternals()
- ret = @dispatch._getproperty(66, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL preserveWhiteSpace
- # indicates whether the parser preserves whitespace
- def preserveWhiteSpace()
- ret = @dispatch._getproperty(67, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeValue
- # value stored in the node
- def nodeValue=(arg0)
- ret = @dispatch._setproperty(3, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID text
- # text content of the node and subtree
- def text=(arg0)
- ret = @dispatch._setproperty(24, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue=(arg0)
- ret = @dispatch._setproperty(25, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID dataType
- # the data type of the node
- def dataType=(arg0)
- ret = @dispatch._setproperty(26, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID async
- # flag for asynchronous download
- def async=(arg0)
- ret = @dispatch._setproperty(61, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID validateOnParse
- # indicates whether the parser performs validation
- def validateOnParse=(arg0)
- ret = @dispatch._setproperty(65, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID resolveExternals
- # indicates whether the parser resolves references to external DTD/Entities/Schema
- def resolveExternals=(arg0)
- ret = @dispatch._setproperty(66, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID preserveWhiteSpace
- # indicates whether the parser preserves whitespace
- def preserveWhiteSpace=(arg0)
- ret = @dispatch._setproperty(67, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID onreadystatechange
- # register a readystatechange event handler
- def onreadystatechange=(arg0)
- ret = @dispatch._setproperty(68, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID ondataavailable
- # register an ondataavailable event handler
- def ondataavailable=(arg0)
- ret = @dispatch._setproperty(69, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID ontransformnode
- # register an ontransformnode event handler
- def ontransformnode=(arg0)
- ret = @dispatch._setproperty(70, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode insertBefore
- # insert a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # VARIANT arg1 --- refChild [IN]
- def insertBefore(arg0, arg1)
- ret = @dispatch._invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode replaceChild
- # replace a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # IXMLDOMNode arg1 --- oldChild [IN]
- def replaceChild(arg0, arg1)
- ret = @dispatch._invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode removeChild
- # remove a child node
- # IXMLDOMNode arg0 --- childNode [IN]
- def removeChild(arg0)
- ret = @dispatch._invoke(15, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode appendChild
- # append a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- def appendChild(arg0)
- ret = @dispatch._invoke(16, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL hasChildNodes
- def hasChildNodes()
- ret = @dispatch._invoke(17, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode cloneNode
- # BOOL arg0 --- deep [IN]
- def cloneNode(arg0)
- ret = @dispatch._invoke(19, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR transformNode
- # apply the stylesheet to the subtree
- # IXMLDOMNode arg0 --- stylesheet [IN]
- def transformNode(arg0)
- ret = @dispatch._invoke(28, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList selectNodes
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectNodes(arg0)
- ret = @dispatch._invoke(29, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode selectSingleNode
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectSingleNode(arg0)
- ret = @dispatch._invoke(30, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID transformNodeToObject
- # apply the stylesheet to the subtree, returning the result through a document or a stream
- # IXMLDOMNode arg0 --- stylesheet [IN]
- # VARIANT arg1 --- outputObject [IN]
- def transformNodeToObject(arg0, arg1)
- ret = @dispatch._invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMElement createElement
- # create an Element node
- # BSTR arg0 --- tagName [IN]
- def createElement(arg0)
- ret = @dispatch._invoke(41, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMDocumentFragment createDocumentFragment
- # create a DocumentFragment node
- def createDocumentFragment()
- ret = @dispatch._invoke(42, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMText createTextNode
- # create a text node
- # BSTR arg0 --- data [IN]
- def createTextNode(arg0)
- ret = @dispatch._invoke(43, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMComment createComment
- # create a comment node
- # BSTR arg0 --- data [IN]
- def createComment(arg0)
- ret = @dispatch._invoke(44, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMCDATASection createCDATASection
- # create a CDATA section node
- # BSTR arg0 --- data [IN]
- def createCDATASection(arg0)
- ret = @dispatch._invoke(45, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMProcessingInstruction createProcessingInstruction
- # create a processing instruction node
- # BSTR arg0 --- target [IN]
- # BSTR arg1 --- data [IN]
- def createProcessingInstruction(arg0, arg1)
- ret = @dispatch._invoke(46, [arg0, arg1], [VT_BSTR, VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMAttribute createAttribute
- # create an attribute node
- # BSTR arg0 --- name [IN]
- def createAttribute(arg0)
- ret = @dispatch._invoke(47, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMEntityReference createEntityReference
- # create an entity reference node
- # BSTR arg0 --- name [IN]
- def createEntityReference(arg0)
- ret = @dispatch._invoke(49, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList getElementsByTagName
- # build a list of elements by name
- # BSTR arg0 --- tagName [IN]
- def getElementsByTagName(arg0)
- ret = @dispatch._invoke(50, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode createNode
- # create a node of the specified node type and name
- # VARIANT arg0 --- type [IN]
- # BSTR arg1 --- name [IN]
- # BSTR arg2 --- namespaceURI [IN]
- def createNode(arg0, arg1, arg2)
- ret = @dispatch._invoke(54, [arg0, arg1, arg2], [VT_VARIANT, VT_BSTR, VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode nodeFromID
- # retrieve node from it's ID
- # BSTR arg0 --- idString [IN]
- def nodeFromID(arg0)
- ret = @dispatch._invoke(56, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL load
- # load document from the specified XML source
- # VARIANT arg0 --- xmlSource [IN]
- def load(arg0)
- ret = @dispatch._invoke(58, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID abort
- # abort an asynchronous download
- def abort()
- ret = @dispatch._invoke(62, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL loadXML
- # load the document from a string
- # BSTR arg0 --- bstrXML [IN]
- def loadXML(arg0)
- ret = @dispatch._invoke(63, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID save
- # save the document to a specified destination
- # VARIANT arg0 --- destination [IN]
- def save(arg0)
- ret = @dispatch._invoke(64, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # HRESULT ondataavailable EVENT in XMLDOMDocumentEvents
- def ondataavailable()
- ret = @dispatch._invoke(198, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # HRESULT onreadystatechange EVENT in XMLDOMDocumentEvents
- def onreadystatechange()
- ret = @dispatch._invoke(-609, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-end
-
-# W3C-DOM XML Document (Apartment)
-class Microsoft_FreeThreadedXMLDOM_1_0 # DOMFreeThreadedDocument
- include WIN32OLE::VARIANT
- attr_reader :lastargs
- attr_reader :dispatch
- attr_reader :clsid
- attr_reader :progid
-
- def initialize(obj = nil)
- @clsid = "{2933BF91-7B36-11D2-B20E-00C04F983E60}"
- @progid = "Microsoft.FreeThreadedXMLDOM.1.0"
- if obj.nil?
- @dispatch = WIN32OLE.new(@progid)
- else
- @dispatch = obj
- end
- end
-
- def method_missing(cmd, *arg)
- @dispatch.method_missing(cmd, *arg)
- end
-
- # BSTR nodeName
- # name of the node
- def nodeName()
- ret = @dispatch._getproperty(2, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeValue
- # value stored in the node
- def nodeValue()
- ret = @dispatch._getproperty(3, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # DOMNodeType nodeType
- # the node's type
- def nodeType()
- ret = @dispatch._getproperty(4, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode parentNode
- # parent of the node
- def parentNode()
- ret = @dispatch._getproperty(6, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList childNodes
- # the collection of the node's children
- def childNodes()
- ret = @dispatch._getproperty(7, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode firstChild
- # first child of the node
- def firstChild()
- ret = @dispatch._getproperty(8, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode lastChild
- # first child of the node
- def lastChild()
- ret = @dispatch._getproperty(9, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode previousSibling
- # left sibling of the node
- def previousSibling()
- ret = @dispatch._getproperty(10, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode nextSibling
- # right sibling of the node
- def nextSibling()
- ret = @dispatch._getproperty(11, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNamedNodeMap attributes
- # the collection of the node's attributes
- def attributes()
- ret = @dispatch._getproperty(12, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMDocument ownerDocument
- # document that contains the node
- def ownerDocument()
- ret = @dispatch._getproperty(18, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR nodeTypeString
- # the type of node in string form
- def nodeTypeString()
- ret = @dispatch._getproperty(21, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR text
- # text content of the node and subtree
- def text()
- ret = @dispatch._getproperty(24, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL specified
- # indicates whether node is a default value
- def specified()
- ret = @dispatch._getproperty(22, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode definition
- # pointer to the definition of the node in the DTD or schema
- def definition()
- ret = @dispatch._getproperty(23, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue()
- ret = @dispatch._getproperty(25, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT dataType
- # the data type of the node
- def dataType()
- ret = @dispatch._getproperty(26, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR xml
- # return the XML source for the node and each of its descendants
- def xml()
- ret = @dispatch._getproperty(27, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL parsed
- # has sub-tree been completely parsed
- def parsed()
- ret = @dispatch._getproperty(31, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR namespaceURI
- # the URI for the namespace applying to the node
- def namespaceURI()
- ret = @dispatch._getproperty(32, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR prefix
- # the prefix for the namespace applying to the node
- def prefix()
- ret = @dispatch._getproperty(33, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR baseName
- # the base name of the node (nodename with the prefix stripped off)
- def baseName()
- ret = @dispatch._getproperty(34, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMDocumentType doctype
- # node corresponding to the DOCTYPE
- def doctype()
- ret = @dispatch._getproperty(38, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMImplementation implementation
- # info on this DOM implementation
- def implementation()
- ret = @dispatch._getproperty(39, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMElement documentElement
- # the root of the tree
- def documentElement()
- ret = @dispatch._getproperty(40, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # I4 readyState
- # get the state of the XML document
- def readyState()
- ret = @dispatch._getproperty(-525, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMParseError parseError
- # get the last parser error
- def parseError()
- ret = @dispatch._getproperty(59, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR url
- # get the URL for the loaded XML document
- def url()
- ret = @dispatch._getproperty(60, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL async
- # flag for asynchronous download
- def async()
- ret = @dispatch._getproperty(61, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL validateOnParse
- # indicates whether the parser performs validation
- def validateOnParse()
- ret = @dispatch._getproperty(65, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL resolveExternals
- # indicates whether the parser resolves references to external DTD/Entities/Schema
- def resolveExternals()
- ret = @dispatch._getproperty(66, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL preserveWhiteSpace
- # indicates whether the parser preserves whitespace
- def preserveWhiteSpace()
- ret = @dispatch._getproperty(67, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeValue
- # value stored in the node
- def nodeValue=(arg0)
- ret = @dispatch._setproperty(3, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID text
- # text content of the node and subtree
- def text=(arg0)
- ret = @dispatch._setproperty(24, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID nodeTypedValue
- # get the strongly typed value of the node
- def nodeTypedValue=(arg0)
- ret = @dispatch._setproperty(25, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID dataType
- # the data type of the node
- def dataType=(arg0)
- ret = @dispatch._setproperty(26, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID async
- # flag for asynchronous download
- def async=(arg0)
- ret = @dispatch._setproperty(61, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID validateOnParse
- # indicates whether the parser performs validation
- def validateOnParse=(arg0)
- ret = @dispatch._setproperty(65, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID resolveExternals
- # indicates whether the parser resolves references to external DTD/Entities/Schema
- def resolveExternals=(arg0)
- ret = @dispatch._setproperty(66, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID preserveWhiteSpace
- # indicates whether the parser preserves whitespace
- def preserveWhiteSpace=(arg0)
- ret = @dispatch._setproperty(67, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID onreadystatechange
- # register a readystatechange event handler
- def onreadystatechange=(arg0)
- ret = @dispatch._setproperty(68, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID ondataavailable
- # register an ondataavailable event handler
- def ondataavailable=(arg0)
- ret = @dispatch._setproperty(69, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID ontransformnode
- # register an ontransformnode event handler
- def ontransformnode=(arg0)
- ret = @dispatch._setproperty(70, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode insertBefore
- # insert a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # VARIANT arg1 --- refChild [IN]
- def insertBefore(arg0, arg1)
- ret = @dispatch._invoke(13, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode replaceChild
- # replace a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- # IXMLDOMNode arg1 --- oldChild [IN]
- def replaceChild(arg0, arg1)
- ret = @dispatch._invoke(14, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode removeChild
- # remove a child node
- # IXMLDOMNode arg0 --- childNode [IN]
- def removeChild(arg0)
- ret = @dispatch._invoke(15, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode appendChild
- # append a child node
- # IXMLDOMNode arg0 --- newChild [IN]
- def appendChild(arg0)
- ret = @dispatch._invoke(16, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL hasChildNodes
- def hasChildNodes()
- ret = @dispatch._invoke(17, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode cloneNode
- # BOOL arg0 --- deep [IN]
- def cloneNode(arg0)
- ret = @dispatch._invoke(19, [arg0], [VT_BOOL])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR transformNode
- # apply the stylesheet to the subtree
- # IXMLDOMNode arg0 --- stylesheet [IN]
- def transformNode(arg0)
- ret = @dispatch._invoke(28, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList selectNodes
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectNodes(arg0)
- ret = @dispatch._invoke(29, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode selectSingleNode
- # execute query on the subtree
- # BSTR arg0 --- queryString [IN]
- def selectSingleNode(arg0)
- ret = @dispatch._invoke(30, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID transformNodeToObject
- # apply the stylesheet to the subtree, returning the result through a document or a stream
- # IXMLDOMNode arg0 --- stylesheet [IN]
- # VARIANT arg1 --- outputObject [IN]
- def transformNodeToObject(arg0, arg1)
- ret = @dispatch._invoke(35, [arg0, arg1], [VT_BYREF|VT_DISPATCH, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMElement createElement
- # create an Element node
- # BSTR arg0 --- tagName [IN]
- def createElement(arg0)
- ret = @dispatch._invoke(41, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMDocumentFragment createDocumentFragment
- # create a DocumentFragment node
- def createDocumentFragment()
- ret = @dispatch._invoke(42, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMText createTextNode
- # create a text node
- # BSTR arg0 --- data [IN]
- def createTextNode(arg0)
- ret = @dispatch._invoke(43, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMComment createComment
- # create a comment node
- # BSTR arg0 --- data [IN]
- def createComment(arg0)
- ret = @dispatch._invoke(44, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMCDATASection createCDATASection
- # create a CDATA section node
- # BSTR arg0 --- data [IN]
- def createCDATASection(arg0)
- ret = @dispatch._invoke(45, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMProcessingInstruction createProcessingInstruction
- # create a processing instruction node
- # BSTR arg0 --- target [IN]
- # BSTR arg1 --- data [IN]
- def createProcessingInstruction(arg0, arg1)
- ret = @dispatch._invoke(46, [arg0, arg1], [VT_BSTR, VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMAttribute createAttribute
- # create an attribute node
- # BSTR arg0 --- name [IN]
- def createAttribute(arg0)
- ret = @dispatch._invoke(47, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMEntityReference createEntityReference
- # create an entity reference node
- # BSTR arg0 --- name [IN]
- def createEntityReference(arg0)
- ret = @dispatch._invoke(49, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNodeList getElementsByTagName
- # build a list of elements by name
- # BSTR arg0 --- tagName [IN]
- def getElementsByTagName(arg0)
- ret = @dispatch._invoke(50, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode createNode
- # create a node of the specified node type and name
- # VARIANT arg0 --- type [IN]
- # BSTR arg1 --- name [IN]
- # BSTR arg2 --- namespaceURI [IN]
- def createNode(arg0, arg1, arg2)
- ret = @dispatch._invoke(54, [arg0, arg1, arg2], [VT_VARIANT, VT_BSTR, VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # IXMLDOMNode nodeFromID
- # retrieve node from it's ID
- # BSTR arg0 --- idString [IN]
- def nodeFromID(arg0)
- ret = @dispatch._invoke(56, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL load
- # load document from the specified XML source
- # VARIANT arg0 --- xmlSource [IN]
- def load(arg0)
- ret = @dispatch._invoke(58, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID abort
- # abort an asynchronous download
- def abort()
- ret = @dispatch._invoke(62, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BOOL loadXML
- # load the document from a string
- # BSTR arg0 --- bstrXML [IN]
- def loadXML(arg0)
- ret = @dispatch._invoke(63, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID save
- # save the document to a specified destination
- # VARIANT arg0 --- destination [IN]
- def save(arg0)
- ret = @dispatch._invoke(64, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # HRESULT ondataavailable EVENT in XMLDOMDocumentEvents
- def ondataavailable()
- ret = @dispatch._invoke(198, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # HRESULT onreadystatechange EVENT in XMLDOMDocumentEvents
- def onreadystatechange()
- ret = @dispatch._invoke(-609, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-end
-
-# IXMLHttpRequest Interface
-module IXMLHttpRequest
- include WIN32OLE::VARIANT
- attr_reader :lastargs
-
- # I4 status
- # Get HTTP status code
- def status()
- ret = _getproperty(7, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR statusText
- # Get HTTP status text
- def statusText()
- ret = _getproperty(8, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # DISPATCH responseXML
- # Get response body
- def responseXML()
- ret = _getproperty(9, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR responseText
- # Get response body
- def responseText()
- ret = _getproperty(10, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT responseBody
- # Get response body
- def responseBody()
- ret = _getproperty(11, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT responseStream
- # Get response body
- def responseStream()
- ret = _getproperty(12, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # I4 readyState
- # Get ready state
- def readyState()
- ret = _getproperty(13, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID onreadystatechange
- # Register a complete event handler
- def onreadystatechange=(arg0)
- ret = _setproperty(14, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID open
- # Open HTTP connection
- # BSTR arg0 --- bstrMethod [IN]
- # BSTR arg1 --- bstrUrl [IN]
- # VARIANT arg2 --- varAsync [IN]
- # VARIANT arg3 --- bstrUser [IN]
- # VARIANT arg4 --- bstrPassword [IN]
- def open(arg0, arg1, arg2=nil, arg3=nil, arg4=nil)
- ret = _invoke(1, [arg0, arg1, arg2, arg3, arg4], [VT_BSTR, VT_BSTR, VT_VARIANT, VT_VARIANT, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID setRequestHeader
- # Add HTTP request header
- # BSTR arg0 --- bstrHeader [IN]
- # BSTR arg1 --- bstrValue [IN]
- def setRequestHeader(arg0, arg1)
- ret = _invoke(2, [arg0, arg1], [VT_BSTR, VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR getResponseHeader
- # Get HTTP response header
- # BSTR arg0 --- bstrHeader [IN]
- def getResponseHeader(arg0)
- ret = _invoke(3, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR getAllResponseHeaders
- # Get all HTTP response headers
- def getAllResponseHeaders()
- ret = _invoke(4, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID send
- # Send HTTP request
- # VARIANT arg0 --- varBody [IN]
- def send(arg0=nil)
- ret = _invoke(5, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID abort
- # Abort HTTP request
- def abort()
- ret = _invoke(6, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-end
-
-# XML HTTP Request class.
-class Microsoft_XMLHTTP_1 # XMLHTTPRequest
- include WIN32OLE::VARIANT
- attr_reader :lastargs
- attr_reader :dispatch
- attr_reader :clsid
- attr_reader :progid
-
- def initialize(obj = nil)
- @clsid = "{ED8C108E-4349-11D2-91A4-00C04F7969E8}"
- @progid = "Microsoft.XMLHTTP.1"
- if obj.nil?
- @dispatch = WIN32OLE.new(@progid)
- else
- @dispatch = obj
- end
- end
-
- def method_missing(cmd, *arg)
- @dispatch.method_missing(cmd, *arg)
- end
-
- # I4 status
- # Get HTTP status code
- def status()
- ret = @dispatch._getproperty(7, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR statusText
- # Get HTTP status text
- def statusText()
- ret = @dispatch._getproperty(8, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # DISPATCH responseXML
- # Get response body
- def responseXML()
- ret = @dispatch._getproperty(9, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR responseText
- # Get response body
- def responseText()
- ret = @dispatch._getproperty(10, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT responseBody
- # Get response body
- def responseBody()
- ret = @dispatch._getproperty(11, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VARIANT responseStream
- # Get response body
- def responseStream()
- ret = @dispatch._getproperty(12, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # I4 readyState
- # Get ready state
- def readyState()
- ret = @dispatch._getproperty(13, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID onreadystatechange
- # Register a complete event handler
- def onreadystatechange=(arg0)
- ret = @dispatch._setproperty(14, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID open
- # Open HTTP connection
- # BSTR arg0 --- bstrMethod [IN]
- # BSTR arg1 --- bstrUrl [IN]
- # VARIANT arg2 --- varAsync [IN]
- # VARIANT arg3 --- bstrUser [IN]
- # VARIANT arg4 --- bstrPassword [IN]
- def open(arg0, arg1, arg2=nil, arg3=nil, arg4=nil)
- ret = @dispatch._invoke(1, [arg0, arg1, arg2, arg3, arg4], [VT_BSTR, VT_BSTR, VT_VARIANT, VT_VARIANT, VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID setRequestHeader
- # Add HTTP request header
- # BSTR arg0 --- bstrHeader [IN]
- # BSTR arg1 --- bstrValue [IN]
- def setRequestHeader(arg0, arg1)
- ret = @dispatch._invoke(2, [arg0, arg1], [VT_BSTR, VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR getResponseHeader
- # Get HTTP response header
- # BSTR arg0 --- bstrHeader [IN]
- def getResponseHeader(arg0)
- ret = @dispatch._invoke(3, [arg0], [VT_BSTR])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # BSTR getAllResponseHeaders
- # Get all HTTP response headers
- def getAllResponseHeaders()
- ret = @dispatch._invoke(4, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID send
- # Send HTTP request
- # VARIANT arg0 --- varBody [IN]
- def send(arg0=nil)
- ret = @dispatch._invoke(5, [arg0], [VT_VARIANT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID abort
- # Abort HTTP request
- def abort()
- ret = @dispatch._invoke(6, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-end
-
-# XML Data Source Object
-class Microsoft_XMLDSO_1_0 # XMLDSOControl
- include WIN32OLE::VARIANT
- attr_reader :lastargs
- attr_reader :dispatch
- attr_reader :clsid
- attr_reader :progid
-
- def initialize(obj = nil)
- @clsid = "{550DDA30-0541-11D2-9CA9-0060B0EC3D39}"
- @progid = "Microsoft.XMLDSO.1.0"
- if obj.nil?
- @dispatch = WIN32OLE.new(@progid)
- else
- @dispatch = obj
- end
- end
-
- def method_missing(cmd, *arg)
- @dispatch.method_missing(cmd, *arg)
- end
-
- # IXMLDOMDocument XMLDocument
- def XMLDocument()
- ret = @dispatch._getproperty(65537, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # I4 JavaDSOCompatible
- def JavaDSOCompatible()
- ret = @dispatch._getproperty(65538, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # I4 readyState
- def readyState()
- ret = @dispatch._getproperty(-525, [], [])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID XMLDocument
- def XMLDocument=(arg0)
- ret = @dispatch._setproperty(65537, [arg0], [VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # VOID JavaDSOCompatible
- def JavaDSOCompatible=(arg0)
- ret = @dispatch._setproperty(65538, [arg0], [VT_I4])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-end
-
-# Constants that define types for IXMLElement.
-module OLEtagXMLEMEM_TYPE
- include WIN32OLE::VARIANT
- attr_reader :lastargs
- XMLELEMTYPE_ELEMENT = 0
- XMLELEMTYPE_TEXT = 1
- XMLELEMTYPE_COMMENT = 2
- XMLELEMTYPE_DOCUMENT = 3
- XMLELEMTYPE_DTD = 4
- XMLELEMTYPE_PI = 5
- XMLELEMTYPE_OTHER = 6
-end
-
-# XMLDocument extends IXML Document. It is obsolete. You should use DOMDocument. This object should not be confused with the XMLDocument property on the XML data island.
-class Msxml # XMLDocument
- include WIN32OLE::VARIANT
- attr_reader :lastargs
- attr_reader :dispatch
- attr_reader :clsid
- attr_reader :progid
-
- def initialize(obj = nil)
- @clsid = "{CFC399AF-D876-11D0-9C10-00C04FC99C8E}"
- @progid = "Msxml"
- if obj.nil?
- @dispatch = WIN32OLE.new(@progid)
- else
- @dispatch = obj
- end
- end
-
- def method_missing(cmd, *arg)
- @dispatch.method_missing(cmd, *arg)
- end
-
- # HRESULT url
- # set URL to load an XML document from the URL.
- # BSTR arg0 --- p [IN]
- def url=(arg0)
- ret = @dispatch._setproperty(65641, [arg0], [VT_BSTR, VT_HRESULT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # HRESULT charset
- # get encoding.
- # BSTR arg0 --- p [IN]
- def charset=(arg0)
- ret = @dispatch._setproperty(65645, [arg0], [VT_BSTR, VT_HRESULT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # HRESULT async
- # get asynchronous loading flag.
- # BOOL arg0 --- pf [IN]
- def async=(arg0)
- ret = @dispatch._setproperty(65649, [arg0], [VT_BOOL, VT_HRESULT])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-
- # HRESULT root
- # get root IXMLElement of the XML document.
- # IXMLElement2,IXMLElement2 arg0 --- p [OUT]
- def root
- OLEProperty.new(@dispatch, 65637, [VT_BYREF|VT_BYREF|VT_DISPATCH], [VT_BYREF|VT_BYREF|VT_DISPATCH, VT_HRESULT])
- end
-
- # HRESULT url
- # set URL to load an XML document from the URL.
- # BSTR arg0 --- p [OUT]
- def url
- OLEProperty.new(@dispatch, 65641, [VT_BYREF|VT_BSTR], [VT_BYREF|VT_BSTR, VT_HRESULT])
- end
-
- # HRESULT readyState
- # get ready state.
- # I4 arg0 --- pl [OUT]
- def readyState
- OLEProperty.new(@dispatch, 65643, [VT_BYREF|VT_I4], [VT_BYREF|VT_I4, VT_HRESULT])
- end
-
- # HRESULT charset
- # get encoding.
- # BSTR arg0 --- p [OUT]
- def charset
- OLEProperty.new(@dispatch, 65645, [VT_BYREF|VT_BSTR], [VT_BYREF|VT_BSTR, VT_HRESULT])
- end
-
- # HRESULT version
- # get XML version number.
- # BSTR arg0 --- p [OUT]
- def version
- OLEProperty.new(@dispatch, 65646, [VT_BYREF|VT_BSTR], [VT_BYREF|VT_BSTR, VT_HRESULT])
- end
-
- # HRESULT doctype
- # get document type.
- # BSTR arg0 --- p [OUT]
- def doctype
- OLEProperty.new(@dispatch, 65647, [VT_BYREF|VT_BSTR], [VT_BYREF|VT_BSTR, VT_HRESULT])
- end
-
- # HRESULT async
- # get asynchronous loading flag.
- # BOOL arg0 --- pf [OUT]
- def async
- OLEProperty.new(@dispatch, 65649, [VT_BYREF|VT_BOOL], [VT_BYREF|VT_BOOL, VT_HRESULT])
- end
-
- # HRESULT createElement
- # create different types of IXMLElements.
- # VARIANT arg0 --- vType [IN]
- # VARIANT arg1 --- var1 [IN]
- # IXMLElement2,IXMLElement2 arg2 --- ppElem [OUT]
- def createElement(arg0, arg1=nil, arg2=nil)
- ret = @dispatch._invoke(65644, [arg0, arg1, arg2], [VT_VARIANT, VT_VARIANT, VT_BYREF|VT_BYREF|VT_DISPATCH])
- @lastargs = WIN32OLE::ARGV
- ret
- end
-end
diff --git a/scheduler.c b/scheduler.c
index 3159635dba..b23ddad41e 100644
--- a/scheduler.c
+++ b/scheduler.c
@@ -9,18 +9,27 @@
**********************************************************************/
#include "vm_core.h"
+#include "eval_intern.h"
#include "ruby/fiber/scheduler.h"
#include "ruby/io.h"
#include "ruby/io/buffer.h"
+#include "ruby/thread.h"
+
+// For `ruby_thread_has_gvl_p`:
#include "internal/thread.h"
+// For atomic operations:
+#include "ruby_atomic.h"
+
static ID id_close;
static ID id_scheduler_close;
static ID id_block;
static ID id_unblock;
+static ID id_yield;
+
static ID id_timeout_after;
static ID id_kernel_sleep;
static ID id_process_wait;
@@ -33,9 +42,229 @@ static ID id_io_close;
static ID id_address_resolve;
+static ID id_blocking_operation_wait;
+static ID id_fiber_interrupt;
+
static ID id_fiber_schedule;
+// Our custom blocking operation class
+static VALUE rb_cFiberSchedulerBlockingOperation;
+
/*
+ * Custom blocking operation structure for blocking operations
+ * This replaces the use of Ruby procs to avoid use-after-free issues
+ * and provides a cleaner C API for native work pools.
+ */
+
+typedef enum {
+ RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_QUEUED, // Submitted but not started
+ RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_EXECUTING, // Currently running
+ RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_COMPLETED, // Finished (success/error)
+ RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_CANCELLED // Cancelled
+} rb_fiber_blocking_operation_status_t;
+
+struct rb_fiber_scheduler_blocking_operation {
+ void *(*function)(void *);
+ void *data;
+
+ rb_unblock_function_t *unblock_function;
+ void *data2;
+
+ int flags;
+ struct rb_fiber_scheduler_blocking_operation_state *state;
+
+ // Execution status
+ volatile rb_atomic_t status;
+};
+
+static void
+blocking_operation_mark(void *ptr)
+{
+ // No Ruby objects to mark in our struct
+}
+
+static void
+blocking_operation_free(void *ptr)
+{
+ rb_fiber_scheduler_blocking_operation_t *blocking_operation = (rb_fiber_scheduler_blocking_operation_t *)ptr;
+ ruby_xfree(blocking_operation);
+}
+
+static size_t
+blocking_operation_memsize(const void *ptr)
+{
+ return sizeof(rb_fiber_scheduler_blocking_operation_t);
+}
+
+static const rb_data_type_t blocking_operation_data_type = {
+ "Fiber::Scheduler::BlockingOperation",
+ {
+ blocking_operation_mark,
+ blocking_operation_free,
+ blocking_operation_memsize,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
+};
+
+/*
+ * Allocate a new blocking operation
+ */
+static VALUE
+blocking_operation_alloc(VALUE klass)
+{
+ rb_fiber_scheduler_blocking_operation_t *blocking_operation;
+ VALUE obj = TypedData_Make_Struct(klass, rb_fiber_scheduler_blocking_operation_t, &blocking_operation_data_type, blocking_operation);
+
+ blocking_operation->function = NULL;
+ blocking_operation->data = NULL;
+ blocking_operation->unblock_function = NULL;
+ blocking_operation->data2 = NULL;
+ blocking_operation->flags = 0;
+ blocking_operation->state = NULL;
+ blocking_operation->status = RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_QUEUED;
+
+ return obj;
+}
+
+/*
+ * Get the blocking operation struct from a Ruby object
+ */
+static rb_fiber_scheduler_blocking_operation_t *
+get_blocking_operation(VALUE obj)
+{
+ rb_fiber_scheduler_blocking_operation_t *blocking_operation;
+ TypedData_Get_Struct(obj, rb_fiber_scheduler_blocking_operation_t, &blocking_operation_data_type, blocking_operation);
+ return blocking_operation;
+}
+
+/*
+ * Document-method: Fiber::Scheduler::BlockingOperation#call
+ *
+ * Execute the blocking operation. This method releases the GVL and calls
+ * the blocking function, then restores the errno value.
+ *
+ * Returns nil. The actual result is stored in the associated state object.
+ */
+static VALUE
+blocking_operation_call(VALUE self)
+{
+ rb_fiber_scheduler_blocking_operation_t *blocking_operation = get_blocking_operation(self);
+
+ if (blocking_operation->status != RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_QUEUED) {
+ rb_raise(rb_eRuntimeError, "Blocking operation has already been executed!");
+ }
+
+ if (blocking_operation->function == NULL) {
+ rb_raise(rb_eRuntimeError, "Blocking operation has no function to execute!");
+ }
+
+ if (blocking_operation->state == NULL) {
+ rb_raise(rb_eRuntimeError, "Blocking operation has no result object!");
+ }
+
+ // Mark as executing
+ blocking_operation->status = RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_EXECUTING;
+
+ // Execute the blocking operation without GVL
+ blocking_operation->state->result = rb_nogvl(blocking_operation->function, blocking_operation->data,
+ blocking_operation->unblock_function, blocking_operation->data2,
+ blocking_operation->flags);
+ blocking_operation->state->saved_errno = rb_errno();
+
+ // Mark as completed
+ blocking_operation->status = RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_COMPLETED;
+
+ return Qnil;
+}
+
+/*
+ * C API: Extract blocking operation struct from Ruby object (GVL required)
+ *
+ * This function safely extracts the opaque struct from a BlockingOperation VALUE
+ * while holding the GVL. The returned pointer can be passed to worker threads
+ * and used with rb_fiber_scheduler_blocking_operation_execute_opaque_nogvl.
+ *
+ * Returns the opaque struct pointer on success, NULL on error.
+ * Must be called while holding the GVL.
+ */
+rb_fiber_scheduler_blocking_operation_t *
+rb_fiber_scheduler_blocking_operation_extract(VALUE self)
+{
+ return get_blocking_operation(self);
+}
+
+/*
+ * C API: Execute blocking operation from opaque struct (GVL not required)
+ *
+ * This function executes a blocking operation using the opaque struct pointer
+ * obtained from rb_fiber_scheduler_blocking_operation_extract.
+ * It can be called from native threads without holding the GVL.
+ *
+ * Returns 0 on success, -1 on error.
+ */
+int
+rb_fiber_scheduler_blocking_operation_execute(rb_fiber_scheduler_blocking_operation_t *blocking_operation)
+{
+ if (blocking_operation == NULL) {
+ return -1;
+ }
+
+ if (blocking_operation->function == NULL || blocking_operation->state == NULL) {
+ return -1; // Invalid blocking operation
+ }
+
+ // Resolve sentinel values for unblock_function and data2:
+ rb_thread_resolve_unblock_function(&blocking_operation->unblock_function, &blocking_operation->data2, GET_THREAD());
+
+ // Atomically check if we can transition from QUEUED to EXECUTING
+ rb_atomic_t expected = RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_QUEUED;
+ if (RUBY_ATOMIC_CAS(blocking_operation->status, expected, RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_EXECUTING) != expected) {
+ // Already cancelled or in wrong state
+ return -1;
+ }
+
+ // Now we're executing - call the function
+ blocking_operation->state->result = blocking_operation->function(blocking_operation->data);
+ blocking_operation->state->saved_errno = errno;
+
+ // Atomically transition to completed (unless cancelled during execution)
+ expected = RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_EXECUTING;
+ if (RUBY_ATOMIC_CAS(blocking_operation->status, expected, RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_COMPLETED) == expected) {
+ // Successfully completed
+ return 0;
+ } else {
+ // Was cancelled during execution
+ blocking_operation->state->saved_errno = EINTR;
+ return -1;
+ }
+}
+
+/*
+ * C API: Create a new blocking operation
+ *
+ * This creates a blocking operation that can be executed by native work pools.
+ * The blocking operation holds references to the function and data safely.
+ */
+VALUE
+rb_fiber_scheduler_blocking_operation_new(void *(*function)(void *), void *data,
+ rb_unblock_function_t *unblock_function, void *data2,
+ int flags, struct rb_fiber_scheduler_blocking_operation_state *state)
+{
+ VALUE self = blocking_operation_alloc(rb_cFiberSchedulerBlockingOperation);
+ rb_fiber_scheduler_blocking_operation_t *blocking_operation = get_blocking_operation(self);
+
+ blocking_operation->function = function;
+ blocking_operation->data = data;
+ blocking_operation->unblock_function = unblock_function;
+ blocking_operation->data2 = data2;
+ blocking_operation->flags = flags;
+ blocking_operation->state = state;
+
+ return self;
+}
+
+/*
+ *
* Document-class: Fiber::Scheduler
*
* This is not an existing class, but documentation of the interface that Scheduler
@@ -64,12 +293,15 @@ static ID id_fiber_schedule;
*
* Hook methods are:
*
- * * #io_wait, #io_read, #io_write, #io_pread, #io_pwrite, and #io_select, #io_close
+ * * #io_wait, #io_read, #io_write, #io_pread, #io_pwrite #io_select, and #io_close
* * #process_wait
* * #kernel_sleep
* * #timeout_after
* * #address_resolve
* * #block and #unblock
+ * * #blocking_operation_wait
+ * * #fiber_interrupt
+ * * #yield
* * (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
@@ -93,6 +325,7 @@ Init_Fiber_Scheduler(void)
id_block = rb_intern_const("block");
id_unblock = rb_intern_const("unblock");
+ id_yield = rb_intern_const("yield");
id_timeout_after = rb_intern_const("timeout_after");
id_kernel_sleep = rb_intern_const("kernel_sleep");
@@ -109,8 +342,20 @@ Init_Fiber_Scheduler(void)
id_address_resolve = rb_intern_const("address_resolve");
+ id_blocking_operation_wait = rb_intern_const("blocking_operation_wait");
+ id_fiber_interrupt = rb_intern_const("fiber_interrupt");
+
id_fiber_schedule = rb_intern_const("fiber");
+ // Define an anonymous BlockingOperation class for internal use only
+ // This is completely hidden from Ruby code and cannot be instantiated directly
+ rb_cFiberSchedulerBlockingOperation = rb_class_new(rb_cObject);
+ rb_define_alloc_func(rb_cFiberSchedulerBlockingOperation, blocking_operation_alloc);
+ rb_define_method(rb_cFiberSchedulerBlockingOperation, "call", blocking_operation_call, 0);
+
+ // Register the anonymous class as a GC root so it doesn't get collected
+ rb_gc_register_mark_object(rb_cFiberSchedulerBlockingOperation);
+
#if 0 /* for RDoc */
rb_cFiberScheduler = rb_define_class_under(rb_cFiber, "Scheduler", rb_cObject);
rb_define_method(rb_cFiberScheduler, "close", rb_fiber_scheduler_close, 0);
@@ -126,17 +371,21 @@ Init_Fiber_Scheduler(void)
rb_define_method(rb_cFiberScheduler, "timeout_after", rb_fiber_scheduler_timeout_after, 3);
rb_define_method(rb_cFiberScheduler, "block", rb_fiber_scheduler_block, 2);
rb_define_method(rb_cFiberScheduler, "unblock", rb_fiber_scheduler_unblock, 2);
- rb_define_method(rb_cFiberScheduler, "fiber", rb_fiber_scheduler, -2);
+ rb_define_method(rb_cFiberScheduler, "fiber", rb_fiber_scheduler_fiber, -2);
+ rb_define_method(rb_cFiberScheduler, "blocking_operation_wait", rb_fiber_scheduler_blocking_operation_wait, -2);
+ rb_define_method(rb_cFiberScheduler, "yield", rb_fiber_scheduler_yield, 0);
+ rb_define_method(rb_cFiberScheduler, "fiber_interrupt", rb_fiber_scheduler_fiber_interrupt, 2);
+ rb_define_method(rb_cFiberScheduler, "io_close", rb_fiber_scheduler_io_close, 1);
#endif
}
VALUE
rb_fiber_scheduler_get(void)
{
- VM_ASSERT(ruby_thread_has_gvl_p());
+ RUBY_ASSERT(ruby_thread_has_gvl_p());
rb_thread_t *thread = GET_THREAD();
- VM_ASSERT(thread);
+ RUBY_ASSERT(thread);
return thread->scheduler;
}
@@ -159,6 +408,10 @@ verify_interface(VALUE scheduler)
if (!rb_respond_to(scheduler, id_io_wait)) {
rb_raise(rb_eArgError, "Scheduler must implement #io_wait");
}
+
+ if (!rb_respond_to(scheduler, id_fiber_interrupt)) {
+ rb_warn("Scheduler should implement #fiber_interrupt");
+ }
}
static VALUE
@@ -179,10 +432,10 @@ fiber_scheduler_close_ensure(VALUE _thread)
VALUE
rb_fiber_scheduler_set(VALUE scheduler)
{
- VM_ASSERT(ruby_thread_has_gvl_p());
+ RUBY_ASSERT(ruby_thread_has_gvl_p());
rb_thread_t *thread = GET_THREAD();
- VM_ASSERT(thread);
+ RUBY_ASSERT(thread);
if (scheduler != Qnil) {
verify_interface(scheduler);
@@ -203,9 +456,9 @@ rb_fiber_scheduler_set(VALUE scheduler)
}
static VALUE
-rb_fiber_scheduler_current_for_threadptr(rb_thread_t *thread)
+fiber_scheduler_current_for_threadptr(rb_thread_t *thread)
{
- VM_ASSERT(thread);
+ RUBY_ASSERT(thread);
if (thread->blocking == 0) {
return thread->scheduler;
@@ -215,15 +468,22 @@ rb_fiber_scheduler_current_for_threadptr(rb_thread_t *thread)
}
}
-VALUE
-rb_fiber_scheduler_current(void)
+VALUE rb_fiber_scheduler_current(void)
{
- return rb_fiber_scheduler_current_for_threadptr(GET_THREAD());
+ RUBY_ASSERT(ruby_thread_has_gvl_p());
+
+ return fiber_scheduler_current_for_threadptr(GET_THREAD());
}
+// This function is allowed to be called without holding the GVL.
VALUE rb_fiber_scheduler_current_for_thread(VALUE thread)
{
- return rb_fiber_scheduler_current_for_threadptr(rb_thread_ptr(thread));
+ return fiber_scheduler_current_for_threadptr(rb_thread_ptr(thread));
+}
+
+VALUE rb_fiber_scheduler_current_for_threadptr(rb_thread_t *thread)
+{
+ return fiber_scheduler_current_for_threadptr(thread);
}
/*
@@ -239,7 +499,7 @@ VALUE rb_fiber_scheduler_current_for_thread(VALUE thread)
VALUE
rb_fiber_scheduler_close(VALUE scheduler)
{
- VM_ASSERT(ruby_thread_has_gvl_p());
+ RUBY_ASSERT(ruby_thread_has_gvl_p());
VALUE result;
@@ -262,7 +522,7 @@ 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 rb_float_new((double)timeout->tv_sec + (0.000001 * timeout->tv_usec));
}
return Qnil;
@@ -272,7 +532,7 @@ rb_fiber_scheduler_make_timeout(struct timeval *timeout)
* Document-method: Fiber::Scheduler#kernel_sleep
* call-seq: kernel_sleep(duration = nil)
*
- * Invoked by Kernel#sleep and Mutex#sleep and is expected to provide
+ * Invoked by Kernel#sleep and Thread::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
@@ -291,6 +551,23 @@ rb_fiber_scheduler_kernel_sleepv(VALUE scheduler, int argc, VALUE * argv)
return rb_funcallv(scheduler, id_kernel_sleep, argc, argv);
}
+/**
+ * Document-method: Fiber::Scheduler#yield
+ * call-seq: yield
+ *
+ * Yield to the scheduler, to be resumed on the next scheduling cycle.
+ */
+VALUE
+rb_fiber_scheduler_yield(VALUE scheduler)
+{
+ // First try to call the scheduler's yield method, if it exists:
+ VALUE result = rb_check_funcall(scheduler, id_yield, 0, NULL);
+ if (!UNDEF_P(result)) return result;
+
+ // Otherwise, we can emulate yield by sleeping for 0 seconds:
+ return rb_fiber_scheduler_kernel_sleep(scheduler, RB_INT2NUM(0));
+}
+
#if 0
/*
* Document-method: Fiber::Scheduler#timeout_after
@@ -314,7 +591,7 @@ rb_fiber_scheduler_kernel_sleepv(VALUE scheduler, int argc, VALUE * argv)
* 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)+.
+ * <tt>sleep(0)</tt>.
*
* If the block is executed successfully, its result will be returned.
*
@@ -369,7 +646,7 @@ rb_fiber_scheduler_process_wait(VALUE scheduler, rb_pid_t pid, int flags)
* Document-method: Fiber::Scheduler#block
* call-seq: block(blocker, timeout = nil)
*
- * Invoked by methods like Thread.join, and by Mutex, to signify that current
+ * Invoked by methods like Thread.join, and by Thread::Mutex, to signify that current
* Fiber is blocked until further notice (e.g. #unblock) or until +timeout+ has
* elapsed.
*
@@ -389,8 +666,8 @@ rb_fiber_scheduler_block(VALUE scheduler, VALUE blocker, VALUE timeout)
* Document-method: Fiber::Scheduler#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
+ * Invoked to wake up Fiber previously blocked with #block (for example, Thread::Mutex#lock
+ * calls #block and Thread::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
@@ -401,9 +678,38 @@ rb_fiber_scheduler_block(VALUE scheduler, VALUE blocker, VALUE timeout)
VALUE
rb_fiber_scheduler_unblock(VALUE scheduler, VALUE blocker, VALUE fiber)
{
- VM_ASSERT(rb_obj_is_fiber(fiber));
+ RUBY_ASSERT(rb_obj_is_fiber(fiber));
- return rb_funcall(scheduler, id_unblock, 2, blocker, fiber);
+ VALUE result;
+ enum ruby_tag_type state;
+
+ // `rb_fiber_scheduler_unblock` can be called from points where `errno` is expected to be preserved. Therefore, we should save and restore it. For example `io_binwrite` calls `rb_fiber_scheduler_unblock` and if `errno` is reset to 0 by user code, it will break the error handling in `io_write`.
+ //
+ // If we explicitly preserve `errno` in `io_binwrite` and other similar functions (e.g. by returning it), this code is no longer needed. I hope in the future we will be able to remove it.
+ int saved_errno = errno;
+
+ // We must prevent interrupts while invoking the unblock method, because otherwise fibers can be left permanently blocked if an interrupt occurs during the execution of user code. See also `rb_fiber_scheduler_fiber_interrupt`.
+ rb_execution_context_t *ec = GET_EC();
+ int saved_interrupt_mask = ec->interrupt_mask;
+ ec->interrupt_mask |= PENDING_INTERRUPT_MASK;
+
+ EC_PUSH_TAG(ec);
+ if ((state = EC_EXEC_TAG()) == TAG_NONE) {
+ result = rb_funcall(scheduler, id_unblock, 2, blocker, fiber);
+ }
+ EC_POP_TAG();
+
+ ec->interrupt_mask = saved_interrupt_mask;
+
+ if (state) {
+ EC_JUMP_TAG(ec, state);
+ }
+
+ RUBY_VM_CHECK_INTS(ec);
+
+ errno = saved_errno;
+
+ return result;
}
/*
@@ -425,10 +731,25 @@ rb_fiber_scheduler_unblock(VALUE scheduler, VALUE blocker, VALUE fiber)
* Expected to return the subset of events that are ready immediately.
*
*/
+static VALUE
+fiber_scheduler_io_wait(VALUE _argument) {
+ VALUE *arguments = (VALUE*)_argument;
+
+ return rb_funcallv(arguments[0], id_io_wait, 3, arguments + 1);
+}
+
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 arguments[] = {
+ scheduler, io, events, timeout
+ };
+
+ if (rb_respond_to(scheduler, id_fiber_interrupt)) {
+ return rb_thread_io_blocking_operation(io, fiber_scheduler_io_wait, (VALUE)&arguments);
+ } else {
+ return fiber_scheduler_io_wait((VALUE)&arguments);
+ }
}
VALUE
@@ -498,18 +819,33 @@ VALUE rb_fiber_scheduler_io_selectv(VALUE scheduler, int argc, VALUE *argv)
*
* The method should be considered _experimental_.
*/
+static VALUE
+fiber_scheduler_io_read(VALUE _argument) {
+ VALUE *arguments = (VALUE*)_argument;
+
+ return rb_funcallv(arguments[0], id_io_read, 4, arguments + 1);
+}
+
VALUE
rb_fiber_scheduler_io_read(VALUE scheduler, VALUE io, VALUE buffer, size_t length, size_t offset)
{
+ if (!rb_respond_to(scheduler, id_io_read)) {
+ return RUBY_Qundef;
+ }
+
VALUE arguments[] = {
- io, buffer, SIZET2NUM(length), SIZET2NUM(offset)
+ scheduler, io, buffer, SIZET2NUM(length), SIZET2NUM(offset)
};
- return rb_check_funcall(scheduler, id_io_read, 4, arguments);
+ if (rb_respond_to(scheduler, id_fiber_interrupt)) {
+ return rb_thread_io_blocking_operation(io, fiber_scheduler_io_read, (VALUE)&arguments);
+ } else {
+ return fiber_scheduler_io_read((VALUE)&arguments);
+ }
}
/*
- * Document-method: Fiber::Scheduler#io_read
+ * Document-method: Fiber::Scheduler#io_pread
* call-seq: io_pread(io, buffer, from, length, offset) -> read length or -errno
*
* Invoked by IO#pread or IO::Buffer#pread to read +length+ bytes from +io+
@@ -522,18 +858,33 @@ rb_fiber_scheduler_io_read(VALUE scheduler, VALUE io, VALUE buffer, size_t lengt
*
* The method should be considered _experimental_.
*/
+static VALUE
+fiber_scheduler_io_pread(VALUE _argument) {
+ VALUE *arguments = (VALUE*)_argument;
+
+ return rb_funcallv(arguments[0], id_io_pread, 5, arguments + 1);
+}
+
VALUE
rb_fiber_scheduler_io_pread(VALUE scheduler, VALUE io, rb_off_t from, VALUE buffer, size_t length, size_t offset)
{
+ if (!rb_respond_to(scheduler, id_io_pread)) {
+ return RUBY_Qundef;
+ }
+
VALUE arguments[] = {
- io, buffer, OFFT2NUM(from), SIZET2NUM(length), SIZET2NUM(offset)
+ scheduler, io, buffer, OFFT2NUM(from), SIZET2NUM(length), SIZET2NUM(offset)
};
- return rb_check_funcall(scheduler, id_io_pread, 5, arguments);
+ if (rb_respond_to(scheduler, id_fiber_interrupt)) {
+ return rb_thread_io_blocking_operation(io, fiber_scheduler_io_pread, (VALUE)&arguments);
+ } else {
+ return fiber_scheduler_io_pread((VALUE)&arguments);
+ }
}
/*
- * Document-method: Scheduler#io_write
+ * Document-method: Fiber::Scheduler#io_write
* call-seq: io_write(io, buffer, length, offset) -> written length or -errno
*
* Invoked by IO#write or IO::Buffer#write to write +length+ bytes to +io+ from
@@ -560,14 +911,29 @@ rb_fiber_scheduler_io_pread(VALUE scheduler, VALUE io, rb_off_t from, VALUE buff
*
* The method should be considered _experimental_.
*/
+static VALUE
+fiber_scheduler_io_write(VALUE _argument) {
+ VALUE *arguments = (VALUE*)_argument;
+
+ return rb_funcallv(arguments[0], id_io_write, 4, arguments + 1);
+}
+
VALUE
rb_fiber_scheduler_io_write(VALUE scheduler, VALUE io, VALUE buffer, size_t length, size_t offset)
{
+ if (!rb_respond_to(scheduler, id_io_write)) {
+ return RUBY_Qundef;
+ }
+
VALUE arguments[] = {
- io, buffer, SIZET2NUM(length), SIZET2NUM(offset)
+ scheduler, io, buffer, SIZET2NUM(length), SIZET2NUM(offset)
};
- return rb_check_funcall(scheduler, id_io_write, 4, arguments);
+ if (rb_respond_to(scheduler, id_fiber_interrupt)) {
+ return rb_thread_io_blocking_operation(io, fiber_scheduler_io_write, (VALUE)&arguments);
+ } else {
+ return fiber_scheduler_io_write((VALUE)&arguments);
+ }
}
/*
@@ -585,14 +951,31 @@ rb_fiber_scheduler_io_write(VALUE scheduler, VALUE io, VALUE buffer, size_t leng
* The method should be considered _experimental_.
*
*/
+static VALUE
+fiber_scheduler_io_pwrite(VALUE _argument) {
+ VALUE *arguments = (VALUE*)_argument;
+
+ return rb_funcallv(arguments[0], id_io_pwrite, 5, arguments + 1);
+}
+
VALUE
rb_fiber_scheduler_io_pwrite(VALUE scheduler, VALUE io, rb_off_t from, VALUE buffer, size_t length, size_t offset)
{
+
+
+ if (!rb_respond_to(scheduler, id_io_pwrite)) {
+ return RUBY_Qundef;
+ }
+
VALUE arguments[] = {
- io, buffer, OFFT2NUM(from), SIZET2NUM(length), SIZET2NUM(offset)
+ scheduler, io, buffer, OFFT2NUM(from), SIZET2NUM(length), SIZET2NUM(offset)
};
- return rb_check_funcall(scheduler, id_io_pwrite, 5, arguments);
+ if (rb_respond_to(scheduler, id_fiber_interrupt)) {
+ return rb_thread_io_blocking_operation(io, fiber_scheduler_io_pwrite, (VALUE)&arguments);
+ } else {
+ return fiber_scheduler_io_pwrite((VALUE)&arguments);
+ }
}
VALUE
@@ -643,6 +1026,14 @@ rb_fiber_scheduler_io_pwrite_memory(VALUE scheduler, VALUE io, rb_off_t from, co
return result;
}
+/*
+ * Document-method: Fiber::Scheduler#io_close
+ * call-seq: io_close(fd)
+ *
+ * Invoked by Ruby's core methods to notify scheduler that the IO object is closed. Note that
+ * the method will receive an integer file descriptor of the closed object, not an object
+ * itself.
+ */
VALUE
rb_fiber_scheduler_io_close(VALUE scheduler, VALUE io)
{
@@ -694,6 +1085,94 @@ rb_fiber_scheduler_address_resolve(VALUE scheduler, VALUE hostname)
}
/*
+ * Document-method: Fiber::Scheduler#blocking_operation_wait
+ * call-seq: blocking_operation_wait(blocking_operation)
+ *
+ * Invoked by Ruby's core methods to run a blocking operation in a non-blocking way.
+ * The blocking_operation is an opaque object that encapsulates the blocking operation
+ * and responds to a <tt>#call</tt> method without any arguments.
+ *
+ * If the scheduler doesn't implement this method, or if the scheduler doesn't execute
+ * the blocking operation, Ruby will fall back to the non-scheduler implementation.
+ *
+ * Minimal suggested implementation is:
+ *
+ * def blocking_operation_wait(blocking_operation)
+ * Thread.new { blocking_operation.call }.join
+ * end
+ */
+VALUE rb_fiber_scheduler_blocking_operation_wait(VALUE scheduler, void* (*function)(void *), void *data, rb_unblock_function_t *unblock_function, void *data2, int flags, struct rb_fiber_scheduler_blocking_operation_state *state)
+{
+ // Check if scheduler supports blocking_operation_wait before creating the object
+ if (!rb_respond_to(scheduler, id_blocking_operation_wait)) {
+ return Qundef;
+ }
+
+ // Create a new BlockingOperation with the blocking operation
+ VALUE blocking_operation = rb_fiber_scheduler_blocking_operation_new(function, data, unblock_function, data2, flags, state);
+
+ VALUE result = rb_funcall(scheduler, id_blocking_operation_wait, 1, blocking_operation);
+
+ // Get the operation data to check if it was executed
+ rb_fiber_scheduler_blocking_operation_t *operation = get_blocking_operation(blocking_operation);
+ rb_atomic_t current_status = RUBY_ATOMIC_LOAD(operation->status);
+
+ // Invalidate the operation now that we're done with it
+ operation->function = NULL;
+ operation->state = NULL;
+ operation->data = NULL;
+ operation->data2 = NULL;
+ operation->unblock_function = NULL;
+
+ // If the blocking operation was never executed, return Qundef to signal the caller to use rb_nogvl instead
+ if (current_status == RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_QUEUED) {
+ return Qundef;
+ }
+
+ return result;
+}
+
+/*
+ * Document-method: Fiber::Scheduler#fiber_interrupt
+ * call-seq: fiber_interrupt(fiber, exception)
+ *
+ * Invoked by Ruby's core methods to notify the scheduler that the blocked fiber should be interrupted
+ * with an exception. For example, IO#close uses this method to interrupt fibers that are performing
+ * blocking IO operations.
+ *
+ */
+VALUE rb_fiber_scheduler_fiber_interrupt(VALUE scheduler, VALUE fiber, VALUE exception)
+{
+ VALUE arguments[] = {
+ fiber, exception
+ };
+
+ VALUE result;
+ enum ruby_tag_type state;
+
+ // We must prevent interrupts while invoking the fiber_interrupt method, because otherwise fibers can be left permanently blocked if an interrupt occurs during the execution of user code. See also `rb_fiber_scheduler_unblock`.
+ rb_execution_context_t *ec = GET_EC();
+ int saved_interrupt_mask = ec->interrupt_mask;
+ ec->interrupt_mask |= PENDING_INTERRUPT_MASK;
+
+ EC_PUSH_TAG(ec);
+ if ((state = EC_EXEC_TAG()) == TAG_NONE) {
+ result = rb_check_funcall(scheduler, id_fiber_interrupt, 2, arguments);
+ }
+ EC_POP_TAG();
+
+ ec->interrupt_mask = saved_interrupt_mask;
+
+ if (state) {
+ EC_JUMP_TAG(ec, state);
+ }
+
+ RUBY_VM_CHECK_INTS(ec);
+
+ return result;
+}
+
+/*
* Document-method: Fiber::Scheduler#fiber
* call-seq: fiber(&block)
*
@@ -713,3 +1192,54 @@ rb_fiber_scheduler_fiber(VALUE scheduler, int argc, VALUE *argv, int kw_splat)
{
return rb_funcall_passing_block_kw(scheduler, id_fiber_schedule, argc, argv, kw_splat);
}
+
+/*
+ * C API: Cancel a blocking operation
+ *
+ * This function cancels a blocking operation. If the operation is queued,
+ * it just marks it as cancelled. If it's executing, it marks it as cancelled
+ * and calls the unblock function to interrupt the operation.
+ *
+ * Returns 1 if unblock function was called, 0 if just marked cancelled, -1 on error.
+ */
+int
+rb_fiber_scheduler_blocking_operation_cancel(rb_fiber_scheduler_blocking_operation_t *blocking_operation)
+{
+ if (blocking_operation == NULL) {
+ return -1;
+ }
+
+ rb_atomic_t current_state = RUBY_ATOMIC_LOAD(blocking_operation->status);
+
+ switch (current_state) {
+ case RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_QUEUED:
+ // Work hasn't started - just mark as cancelled:
+ if (RUBY_ATOMIC_CAS(blocking_operation->status, current_state, RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_CANCELLED) == current_state) {
+ // Successfully cancelled before execution:
+ return 0;
+ }
+ // Fall through if state changed between load and CAS
+
+ case RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_EXECUTING:
+ // Work is running - mark cancelled AND call unblock function
+ if (RUBY_ATOMIC_CAS(blocking_operation->status, current_state, RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_CANCELLED) != current_state) {
+ // State changed between load and CAS - operation may have completed:
+ return 0;
+ }
+ // Otherwise, we successfully marked it as cancelled, so we can call the unblock function:
+ rb_unblock_function_t *unblock_function = blocking_operation->unblock_function;
+ if (unblock_function) {
+ RUBY_ASSERT(unblock_function != (rb_unblock_function_t *)-1 && "unblock_function is still sentinel value -1, should have been resolved earlier");
+ blocking_operation->unblock_function(blocking_operation->data2);
+ }
+ // Cancelled during execution (unblock function called):
+ return 1;
+
+ case RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_COMPLETED:
+ case RB_FIBER_SCHEDULER_BLOCKING_OPERATION_STATUS_CANCELLED:
+ // Already finished or cancelled:
+ return 0;
+ }
+
+ return 0;
+}
diff --git a/set.c b/set.c
new file mode 100644
index 0000000000..4d8178ffc0
--- /dev/null
+++ b/set.c
@@ -0,0 +1,2293 @@
+/* This implements sets using the same hash table implementation as in
+ st.c, but without a value for each hash entry. This results in the
+ same basic performance characteristics as when using an st table,
+ but uses 1/3 less memory.
+ */
+
+#include "id.h"
+#include "internal.h"
+#include "internal/bits.h"
+#include "internal/error.h"
+#include "internal/hash.h"
+#include "internal/proc.h"
+#include "internal/sanitizers.h"
+#include "internal/set_table.h"
+#include "internal/symbol.h"
+#include "internal/variable.h"
+#include "ruby_assert.h"
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#include <string.h>
+
+#ifndef SET_DEBUG
+#define SET_DEBUG 0
+#endif
+
+#if SET_DEBUG
+#include "internal/gc.h"
+#endif
+
+static st_index_t
+dbl_to_index(double d)
+{
+ union {double d; st_index_t i;} u;
+ u.d = d;
+ return u.i;
+}
+
+static const uint64_t prime1 = ((uint64_t)0x2e0bb864 << 32) | 0xe9ea7df5;
+static const uint32_t prime2 = 0x830fcab9;
+
+static inline uint64_t
+mult_and_mix(uint64_t m1, uint64_t m2)
+{
+#if defined HAVE_UINT128_T
+ uint128_t r = (uint128_t) m1 * (uint128_t) m2;
+ return (uint64_t) (r >> 64) ^ (uint64_t) r;
+#else
+ uint64_t hm1 = m1 >> 32, hm2 = m2 >> 32;
+ uint64_t lm1 = m1, lm2 = m2;
+ uint64_t v64_128 = hm1 * hm2;
+ uint64_t v32_96 = hm1 * lm2 + lm1 * hm2;
+ uint64_t v1_32 = lm1 * lm2;
+
+ return (v64_128 + (v32_96 >> 32)) ^ ((v32_96 << 32) + v1_32);
+#endif
+}
+
+static inline uint64_t
+key64_hash(uint64_t key, uint32_t seed)
+{
+ return mult_and_mix(key + seed, prime1);
+}
+
+/* Should cast down the result for each purpose */
+#define set_index_hash(index) key64_hash(rb_hash_start(index), prime2)
+
+static st_index_t
+set_ident_hash(st_data_t n)
+{
+#ifdef USE_FLONUM /* RUBY */
+ /*
+ * - flonum (on 64-bit) is pathologically bad, mix the actual
+ * float value in, but do not use the float value as-is since
+ * many integers get interpreted as 2.0 or -2.0 [Bug #10761]
+ */
+ if (FLONUM_P(n)) {
+ n ^= dbl_to_index(rb_float_value(n));
+ }
+#endif
+
+ return (st_index_t)set_index_hash((st_index_t)n);
+}
+
+static const struct st_hash_type identhash = {
+ rb_st_numcmp,
+ set_ident_hash,
+};
+
+static const struct st_hash_type objhash = {
+ rb_any_cmp,
+ rb_any_hash,
+};
+
+VALUE rb_cSet;
+
+#define id_each idEach
+static ID id_each_entry;
+static ID id_any_p;
+static ID id_new;
+static ID id_i_hash;
+static ID id_set_iter_lev;
+static ID id_subclass_compatible;
+static ID id_class_methods;
+
+#define RSET_INITIALIZED FL_USER1
+#define RSET_LEV_MASK (FL_USER13 | FL_USER14 | FL_USER15 | /* FL 13..19 */ \
+ FL_USER16 | FL_USER17 | FL_USER18 | FL_USER19)
+#define RSET_LEV_SHIFT (FL_USHIFT + 13)
+#define RSET_LEV_MAX 127 /* 7 bits */
+
+#define SET_ASSERT(expr) RUBY_ASSERT_MESG_WHEN(SET_DEBUG, expr, #expr)
+
+#define RSET_SIZE(set) set_table_size(RSET_TABLE(set))
+#define RSET_EMPTY(set) (RSET_SIZE(set) == 0)
+#define RSET_SIZE_NUM(set) SIZET2NUM(RSET_SIZE(set))
+#define RSET_IS_MEMBER(set, item) set_table_lookup(RSET_TABLE(set), (st_data_t)(item))
+#define RSET_COMPARE_BY_IDENTITY(set) (RSET_TABLE(set)->type == &identhash)
+
+struct set_object {
+ set_table table;
+};
+
+static int
+mark_key(st_data_t key, st_data_t data)
+{
+ rb_gc_mark_movable((VALUE)key);
+
+ return ST_CONTINUE;
+}
+
+static void
+set_mark(void *ptr)
+{
+ struct set_object *sobj = ptr;
+ if (sobj->table.entries) set_table_foreach(&sobj->table, mark_key, 0);
+}
+
+static void
+set_free_embedded(struct set_object *sobj)
+{
+ free((&sobj->table)->entries);
+}
+
+static void
+set_free(void *ptr)
+{
+ struct set_object *sobj = ptr;
+ set_free_embedded(sobj);
+ memset(&sobj->table, 0, sizeof(sobj->table));
+}
+
+static size_t
+set_size(const void *ptr)
+{
+ const struct set_object *sobj = ptr;
+ /* Do not count the table size twice, as it is embedded */
+ return (unsigned long)set_memsize(&sobj->table) - sizeof(sobj->table);
+}
+
+static int
+set_foreach_replace(st_data_t key, st_data_t argp, int error)
+{
+ if (rb_gc_location((VALUE)key) != (VALUE)key) {
+ return ST_REPLACE;
+ }
+
+ return ST_CONTINUE;
+}
+
+static int
+set_replace_ref(st_data_t *key, st_data_t argp, int existing)
+{
+ rb_gc_mark_and_move((VALUE *)key);
+
+ return ST_CONTINUE;
+}
+
+static void
+set_update_references(void *ptr)
+{
+ struct set_object *sobj = ptr;
+ set_foreach_with_replace(&sobj->table, set_foreach_replace, set_replace_ref, 0);
+}
+
+static const rb_data_type_t set_data_type = {
+ .wrap_struct_name = "set",
+ .function = {
+ .dmark = set_mark,
+ .dfree = set_free,
+ .dsize = set_size,
+ .dcompact = set_update_references,
+ },
+ .flags = RUBY_TYPED_EMBEDDABLE | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE
+};
+
+static inline set_table *
+RSET_TABLE(VALUE set)
+{
+ struct set_object *sobj;
+ TypedData_Get_Struct(set, struct set_object, &set_data_type, sobj);
+ return &sobj->table;
+}
+
+static unsigned long
+iter_lev_in_ivar(VALUE set)
+{
+ VALUE levval = rb_ivar_get(set, id_set_iter_lev);
+ SET_ASSERT(FIXNUM_P(levval));
+ long lev = FIX2LONG(levval);
+ SET_ASSERT(lev >= 0);
+ return (unsigned long)lev;
+}
+
+void rb_ivar_set_internal(VALUE obj, ID id, VALUE val);
+
+static void
+iter_lev_in_ivar_set(VALUE set, unsigned long lev)
+{
+ SET_ASSERT(lev >= RSET_LEV_MAX);
+ SET_ASSERT(POSFIXABLE(lev)); /* POSFIXABLE means fitting to long */
+ rb_ivar_set_internal(set, id_set_iter_lev, LONG2FIX((long)lev));
+}
+
+static inline unsigned long
+iter_lev_in_flags(VALUE set)
+{
+ return (unsigned long)((RBASIC(set)->flags >> RSET_LEV_SHIFT) & RSET_LEV_MAX);
+}
+
+static inline void
+iter_lev_in_flags_set(VALUE set, unsigned long lev)
+{
+ SET_ASSERT(lev <= RSET_LEV_MAX);
+ RBASIC(set)->flags = ((RBASIC(set)->flags & ~RSET_LEV_MASK) | ((VALUE)lev << RSET_LEV_SHIFT));
+}
+
+static inline bool
+set_iterating_p(VALUE set)
+{
+ return iter_lev_in_flags(set) > 0;
+}
+
+static void
+set_iter_lev_inc(VALUE set)
+{
+ unsigned long lev = iter_lev_in_flags(set);
+ if (lev == RSET_LEV_MAX) {
+ lev = iter_lev_in_ivar(set) + 1;
+ if (!POSFIXABLE(lev)) { /* paranoiac check */
+ rb_raise(rb_eRuntimeError, "too much nested iterations");
+ }
+ }
+ else {
+ lev += 1;
+ iter_lev_in_flags_set(set, lev);
+ if (lev < RSET_LEV_MAX) return;
+ }
+ iter_lev_in_ivar_set(set, lev);
+}
+
+static void
+set_iter_lev_dec(VALUE set)
+{
+ unsigned long lev = iter_lev_in_flags(set);
+ if (lev == RSET_LEV_MAX) {
+ lev = iter_lev_in_ivar(set);
+ if (lev > RSET_LEV_MAX) {
+ iter_lev_in_ivar_set(set, lev-1);
+ return;
+ }
+ rb_attr_delete(set, id_set_iter_lev);
+ }
+ else if (lev == 0) {
+ rb_raise(rb_eRuntimeError, "iteration level underflow");
+ }
+ iter_lev_in_flags_set(set, lev - 1);
+}
+
+static VALUE
+set_foreach_ensure(VALUE set)
+{
+ set_iter_lev_dec(set);
+ return 0;
+}
+
+typedef int set_foreach_func(VALUE, VALUE);
+
+struct set_foreach_arg {
+ VALUE set;
+ set_foreach_func *func;
+ VALUE arg;
+};
+
+static int
+set_iter_status_check(int status)
+{
+ if (status == ST_CONTINUE) {
+ return ST_CHECK;
+ }
+
+ return status;
+}
+
+static int
+set_foreach_iter(st_data_t key, st_data_t argp, int error)
+{
+ struct set_foreach_arg *arg = (struct set_foreach_arg *)argp;
+
+ if (error) return ST_STOP;
+
+ set_table *tbl = RSET_TABLE(arg->set);
+ int status = (*arg->func)((VALUE)key, arg->arg);
+
+ if (RSET_TABLE(arg->set) != tbl) {
+ rb_raise(rb_eRuntimeError, "reset occurred during iteration");
+ }
+
+ return set_iter_status_check(status);
+}
+
+static VALUE
+set_foreach_call(VALUE arg)
+{
+ VALUE set = ((struct set_foreach_arg *)arg)->set;
+ int ret = 0;
+ ret = set_foreach_check(RSET_TABLE(set), set_foreach_iter,
+ (st_data_t)arg, (st_data_t)Qundef);
+ if (ret) {
+ rb_raise(rb_eRuntimeError, "ret: %d, set modified during iteration", ret);
+ }
+ return Qnil;
+}
+
+static void
+set_iter(VALUE set, set_foreach_func *func, VALUE farg)
+{
+ struct set_foreach_arg arg;
+
+ if (RSET_EMPTY(set))
+ return;
+ arg.set = set;
+ arg.func = func;
+ arg.arg = farg;
+ if (RB_OBJ_FROZEN(set)) {
+ set_foreach_call((VALUE)&arg);
+ }
+ else {
+ set_iter_lev_inc(set);
+ rb_ensure(set_foreach_call, (VALUE)&arg, set_foreach_ensure, set);
+ }
+}
+
+NORETURN(static void no_new_item(void));
+static void
+no_new_item(void)
+{
+ rb_raise(rb_eRuntimeError, "can't add a new item into set during iteration");
+}
+
+static void
+set_compact_after_delete(VALUE set)
+{
+ if (!set_iterating_p(set)) {
+ set_compact_table(RSET_TABLE(set));
+ }
+}
+
+static int
+set_table_insert_wb(set_table *tab, VALUE set, VALUE key, VALUE *key_addr)
+{
+ if (tab->type != &identhash && rb_obj_class(key) == rb_cString && !RB_OBJ_FROZEN(key)) {
+ key = rb_hash_key_str(key);
+ if (key_addr) *key_addr = key;
+ }
+ int ret = set_insert(tab, (st_data_t)key);
+ if (ret == 0) RB_OBJ_WRITTEN(set, Qundef, key);
+ return ret;
+}
+
+static int
+set_insert_wb(VALUE set, VALUE key, VALUE *key_addr)
+{
+ return set_table_insert_wb(RSET_TABLE(set), set, key, key_addr);
+}
+
+static VALUE
+set_alloc_with_size(VALUE klass, st_index_t size)
+{
+ VALUE set;
+ struct set_object *sobj;
+
+ set = TypedData_Make_Struct(klass, struct set_object, &set_data_type, sobj);
+ set_init_table_with_size(&sobj->table, &objhash, size);
+
+ return set;
+}
+
+
+static VALUE
+set_s_alloc(VALUE klass)
+{
+ return set_alloc_with_size(klass, 0);
+}
+
+/*
+ * call-seq:
+ * Set[*objects] -> new_set
+ *
+ * Returns a new Set object populated with the given objects,
+ * See Set::new.
+ */
+static VALUE
+set_s_create(int argc, VALUE *argv, VALUE klass)
+{
+ VALUE set = set_alloc_with_size(klass, argc);
+ set_table *table = RSET_TABLE(set);
+ int i;
+
+ for (i=0; i < argc; i++) {
+ set_table_insert_wb(table, set, argv[i], NULL);
+ }
+
+ return set;
+}
+
+static VALUE
+set_s_inherited(VALUE klass, VALUE subclass)
+{
+ if (klass == rb_cSet) {
+ // When subclassing directly from Set, include the compatibility layer
+ rb_require("set/subclass_compatible.rb");
+ VALUE subclass_compatible = rb_const_get(klass, id_subclass_compatible);
+ rb_include_module(subclass, subclass_compatible);
+ rb_extend_object(subclass, rb_const_get(subclass_compatible, id_class_methods));
+ }
+ return Qnil;
+}
+
+static void
+check_set(VALUE arg)
+{
+ if (!rb_obj_is_kind_of(arg, rb_cSet)) {
+ rb_raise(rb_eArgError, "value must be a set");
+ }
+}
+
+static ID
+enum_method_id(VALUE other)
+{
+ if (rb_respond_to(other, id_each_entry)) {
+ return id_each_entry;
+ }
+ else if (rb_respond_to(other, id_each)) {
+ return id_each;
+ }
+ else {
+ rb_raise(rb_eArgError, "value must be enumerable");
+ }
+}
+
+static VALUE
+set_enum_size(VALUE set, VALUE args, VALUE eobj)
+{
+ return RSET_SIZE_NUM(set);
+}
+
+static VALUE
+set_initialize_without_block(RB_BLOCK_CALL_FUNC_ARGLIST(i, set))
+{
+ VALUE element = i;
+ set_insert_wb(set, element, &element);
+ return element;
+}
+
+static VALUE
+set_initialize_with_block(RB_BLOCK_CALL_FUNC_ARGLIST(i, set))
+{
+ VALUE element = rb_yield(i);
+ set_insert_wb(set, element, &element);
+ return element;
+}
+
+/*
+ * call-seq:
+ * Set.new -> new_set
+ * Set.new(enum) -> new_set
+ * Set.new(enum) { |elem| ... } -> new_set
+ *
+ * Creates a new set containing the elements of the given enumerable
+ * object.
+ *
+ * If a block is given, the elements of enum are preprocessed by the
+ * given block.
+ *
+ * Set.new([1, 2]) #=> Set[1, 2]
+ * Set.new([1, 2, 1]) #=> Set[1, 2]
+ * Set.new([1, 'c', :s]) #=> Set[1, "c", :s]
+ * Set.new(1..5) #=> Set[1, 2, 3, 4, 5]
+ * Set.new([1, 2, 3]) { |x| x * x } #=> Set[1, 4, 9]
+ */
+static VALUE
+set_i_initialize(int argc, VALUE *argv, VALUE set)
+{
+ if (RBASIC(set)->flags & RSET_INITIALIZED) {
+ rb_raise(rb_eRuntimeError, "cannot reinitialize set");
+ }
+ RBASIC(set)->flags |= RSET_INITIALIZED;
+
+ VALUE other;
+ rb_check_arity(argc, 0, 1);
+
+ if (argc > 0 && (other = argv[0]) != Qnil) {
+ if (RB_TYPE_P(other, T_ARRAY)) {
+ long i;
+ int block_given = rb_block_given_p();
+ set_table *into = RSET_TABLE(set);
+ for (i=0; i<RARRAY_LEN(other); i++) {
+ VALUE key = RARRAY_AREF(other, i);
+ if (block_given) key = rb_yield(key);
+ set_table_insert_wb(into, set, key, NULL);
+ }
+ }
+ else {
+ rb_block_call(other, enum_method_id(other), 0, 0,
+ rb_block_given_p() ? set_initialize_with_block : set_initialize_without_block,
+ set);
+ }
+ }
+
+ return set;
+}
+
+/* :nodoc: */
+static VALUE
+set_i_initialize_copy(VALUE set, VALUE other)
+{
+ if (set == other) return set;
+
+ if (set_iterating_p(set)) {
+ rb_raise(rb_eRuntimeError, "cannot replace set during iteration");
+ }
+
+ struct set_object *sobj;
+ TypedData_Get_Struct(set, struct set_object, &set_data_type, sobj);
+
+ set_free_embedded(sobj);
+ set_copy(&sobj->table, RSET_TABLE(other));
+ rb_gc_writebarrier_remember(set);
+
+ return set;
+}
+
+static int
+set_inspect_i(st_data_t key, st_data_t arg)
+{
+ VALUE *args = (VALUE*)arg;
+ VALUE str = args[0];
+ if (args[1] == Qtrue) {
+ rb_str_buf_cat_ascii(str, ", ");
+ }
+ else {
+ args[1] = Qtrue;
+ }
+ rb_str_buf_append(str, rb_inspect((VALUE)key));
+
+ return ST_CONTINUE;
+}
+
+static VALUE
+set_inspect(VALUE set, VALUE dummy, int recur)
+{
+ VALUE str;
+ VALUE klass_name = rb_class_path(CLASS_OF(set));
+
+ if (recur) {
+ str = rb_sprintf("%"PRIsVALUE"[...]", klass_name);
+ return rb_str_export_to_enc(str, rb_usascii_encoding());
+ }
+
+ str = rb_sprintf("%"PRIsVALUE"[", klass_name);
+ VALUE args[2] = {str, Qfalse};
+ set_iter(set, set_inspect_i, (st_data_t)args);
+ rb_str_buf_cat2(str, "]");
+
+ return str;
+}
+
+/*
+ * call-seq:
+ * inspect -> new_string
+ *
+ * Returns a new string containing the set entries:
+ *
+ * s = Set.new
+ * s.inspect # => "Set[]"
+ * s.add(1)
+ * s.inspect # => "Set[1]"
+ * s.add(2)
+ * s.inspect # => "Set[1, 2]"
+ *
+ * Related: see {Methods for Converting}[rdoc-ref:Set@Methods+for+Converting].
+ */
+static VALUE
+set_i_inspect(VALUE set)
+{
+ return rb_exec_recursive(set_inspect, set, 0);
+}
+
+static int
+set_to_a_i(st_data_t key, st_data_t arg)
+{
+ rb_ary_push((VALUE)arg, (VALUE)key);
+ return ST_CONTINUE;
+}
+
+/*
+ * call-seq:
+ * to_a -> array
+ *
+ * Returns an array containing all elements in the set.
+ *
+ * Set[1, 2].to_a #=> [1, 2]
+ * Set[1, 'c', :s].to_a #=> [1, "c", :s]
+ */
+static VALUE
+set_i_to_a(VALUE set)
+{
+ st_index_t size = RSET_SIZE(set);
+ VALUE ary = rb_ary_new_capa(size);
+
+ if (size == 0) return ary;
+
+ if (ST_DATA_COMPATIBLE_P(VALUE)) {
+ RARRAY_PTR_USE(ary, ptr, {
+ size = set_keys(RSET_TABLE(set), ptr, size);
+ });
+ rb_gc_writebarrier_remember(ary);
+ rb_ary_set_len(ary, size);
+ }
+ else {
+ set_iter(set, set_to_a_i, (st_data_t)ary);
+ }
+ return ary;
+}
+
+/*
+ * call-seq:
+ * to_set(&block) -> self or new_set
+ *
+ * Without a block, if +self+ is an instance of +Set+, returns +self+.
+ * Otherwise, calls <tt>Set.new(self, &block)</tt>.
+ *
+ * A form with arguments is _deprecated_. It converts the set to another
+ * with <tt>klass.new(self, *args, &block)</tt>.
+ */
+static VALUE
+set_i_to_set(VALUE set)
+{
+ if (rb_obj_is_instance_of(set, rb_cSet) && !rb_block_given_p()) {
+ return set;
+ }
+
+ return rb_funcall_passing_block(rb_cSet, id_new, 0, NULL);
+}
+
+/*
+ * call-seq:
+ * join(separator=nil)-> new_string
+ *
+ * Returns a string created by converting each element of the set to a string.
+ */
+static VALUE
+set_i_join(int argc, VALUE *argv, VALUE set)
+{
+ rb_check_arity(argc, 0, 1);
+ return rb_ary_join(set_i_to_a(set), argc == 0 ? Qnil : argv[0]);
+}
+
+/*
+ * call-seq:
+ * add(obj) -> self
+ *
+ * Adds the given object to the set and returns self. Use Set#merge to
+ * add many elements at once.
+ *
+ * Set[1, 2].add(3) #=> Set[1, 2, 3]
+ * Set[1, 2].add([3, 4]) #=> Set[1, 2, [3, 4]]
+ * Set[1, 2].add(2) #=> Set[1, 2]
+ */
+static VALUE
+set_i_add(VALUE set, VALUE item)
+{
+ rb_check_frozen(set);
+ if (set_iterating_p(set)) {
+ if (!set_table_lookup(RSET_TABLE(set), (st_data_t)item)) {
+ no_new_item();
+ }
+ }
+ else {
+ set_insert_wb(set, item, NULL);
+ }
+ return set;
+}
+
+/*
+ * call-seq:
+ * add?(obj) -> self or nil
+ *
+ * Adds the given object to the set and returns self. If the object is
+ * already in the set, returns nil.
+ *
+ * Set[1, 2].add?(3) #=> Set[1, 2, 3]
+ * Set[1, 2].add?([3, 4]) #=> Set[1, 2, [3, 4]]
+ * Set[1, 2].add?(2) #=> nil
+ */
+static VALUE
+set_i_add_p(VALUE set, VALUE item)
+{
+ rb_check_frozen(set);
+ if (set_iterating_p(set)) {
+ if (!set_table_lookup(RSET_TABLE(set), (st_data_t)item)) {
+ no_new_item();
+ }
+ return Qnil;
+ }
+ else {
+ return set_insert_wb(set, item, NULL) ? Qnil : set;
+ }
+}
+
+/*
+ * call-seq:
+ * delete(obj) -> self
+ *
+ * Deletes the given object from the set and returns self. Use subtract
+ * to delete many items at once.
+ */
+static VALUE
+set_i_delete(VALUE set, VALUE item)
+{
+ rb_check_frozen(set);
+ if (set_table_delete(RSET_TABLE(set), (st_data_t *)&item)) {
+ set_compact_after_delete(set);
+ }
+ return set;
+}
+
+/*
+ * call-seq:
+ * delete?(obj) -> self or nil
+ *
+ * Deletes the given object from the set and returns self. If the
+ * object is not in the set, returns nil.
+ */
+static VALUE
+set_i_delete_p(VALUE set, VALUE item)
+{
+ rb_check_frozen(set);
+ if (set_table_delete(RSET_TABLE(set), (st_data_t *)&item)) {
+ set_compact_after_delete(set);
+ return set;
+ }
+ return Qnil;
+}
+
+static int
+set_delete_if_i(st_data_t key, st_data_t dummy)
+{
+ return RTEST(rb_yield((VALUE)key)) ? ST_DELETE : ST_CONTINUE;
+}
+
+/*
+ * call-seq:
+ * delete_if { |o| ... } -> self
+ * delete_if -> enumerator
+ *
+ * Deletes every element of the set for which block evaluates to
+ * true, and returns self. Returns an enumerator if no block is given.
+ */
+static VALUE
+set_i_delete_if(VALUE set)
+{
+ RETURN_SIZED_ENUMERATOR(set, 0, 0, set_enum_size);
+ rb_check_frozen(set);
+ set_iter(set, set_delete_if_i, 0);
+ set_compact_after_delete(set);
+ return set;
+}
+
+/*
+ * call-seq:
+ * reject! { |o| ... } -> self
+ * reject! -> enumerator
+ *
+ * Equivalent to Set#delete_if, but returns nil if no changes were made.
+ * Returns an enumerator if no block is given.
+ */
+static VALUE
+set_i_reject(VALUE set)
+{
+ RETURN_SIZED_ENUMERATOR(set, 0, 0, set_enum_size);
+ rb_check_frozen(set);
+
+ set_table *table = RSET_TABLE(set);
+ size_t n = set_table_size(table);
+ set_iter(set, set_delete_if_i, 0);
+
+ if (n == set_table_size(table)) return Qnil;
+
+ set_compact_after_delete(set);
+ return set;
+}
+
+static int
+set_classify_i(st_data_t key, st_data_t tmp)
+{
+ VALUE* args = (VALUE*)tmp;
+ VALUE hash = args[0];
+ VALUE hash_key = rb_yield(key);
+ VALUE set = rb_hash_lookup2(hash, hash_key, Qundef);
+ if (set == Qundef) {
+ set = set_s_alloc(args[1]);
+ rb_hash_aset(hash, hash_key, set);
+ }
+ set_i_add(set, key);
+
+ return ST_CONTINUE;
+}
+
+/*
+ * call-seq:
+ * classify { |o| ... } -> hash
+ * classify -> enumerator
+ *
+ * Classifies the set by the return value of the given block and
+ * returns a hash of {value => set of elements} pairs. The block is
+ * called once for each element of the set, passing the element as
+ * parameter.
+ *
+ * files = Set.new(Dir.glob("*.rb"))
+ * hash = files.classify { |f| File.mtime(f).year }
+ * hash #=> {2000 => Set["a.rb", "b.rb"],
+ * # 2001 => Set["c.rb", "d.rb", "e.rb"],
+ * # 2002 => Set["f.rb"]}
+ *
+ * Returns an enumerator if no block is given.
+ */
+static VALUE
+set_i_classify(VALUE set)
+{
+ RETURN_SIZED_ENUMERATOR(set, 0, 0, set_enum_size);
+ VALUE args[2];
+ args[0] = rb_hash_new();
+ args[1] = rb_obj_class(set);
+ set_iter(set, set_classify_i, (st_data_t)args);
+ return args[0];
+}
+
+// Union-find with path compression
+static long
+set_divide_union_find_root(long *uf_parents, long index, long *tmp_array)
+{
+ long root = uf_parents[index];
+ long update_size = 0;
+ while (root != index) {
+ tmp_array[update_size++] = index;
+ index = root;
+ root = uf_parents[index];
+ }
+ for (long j = 0; j < update_size; j++) {
+ long idx = tmp_array[j];
+ uf_parents[idx] = root;
+ }
+ return root;
+}
+
+static void
+set_divide_union_find_merge(long *uf_parents, long i, long j, long *tmp_array)
+{
+ long root_i = set_divide_union_find_root(uf_parents, i, tmp_array);
+ long root_j = set_divide_union_find_root(uf_parents, j, tmp_array);
+ if (root_i != root_j) uf_parents[root_j] = root_i;
+}
+
+static VALUE
+set_divide_arity2(VALUE set)
+{
+ VALUE tmp, uf;
+ long size, *uf_parents, *tmp_array;
+ VALUE set_class = rb_obj_class(set);
+ VALUE items = set_i_to_a(set);
+ rb_ary_freeze(items);
+ size = RARRAY_LEN(items);
+ tmp_array = ALLOCV_N(long, tmp, size);
+ uf_parents = ALLOCV_N(long, uf, size);
+ for (long i = 0; i < size; i++) {
+ uf_parents[i] = i;
+ }
+ for (long i = 0; i < size - 1; i++) {
+ VALUE item1 = RARRAY_AREF(items, i);
+ for (long j = i + 1; j < size; j++) {
+ VALUE item2 = RARRAY_AREF(items, j);
+ if (RTEST(rb_yield_values(2, item1, item2)) &&
+ RTEST(rb_yield_values(2, item2, item1))) {
+ set_divide_union_find_merge(uf_parents, i, j, tmp_array);
+ }
+ }
+ }
+ VALUE final_set = set_s_create(0, 0, rb_cSet);
+ VALUE hash = rb_hash_new();
+ for (long i = 0; i < size; i++) {
+ VALUE v = RARRAY_AREF(items, i);
+ long root = set_divide_union_find_root(uf_parents, i, tmp_array);
+ VALUE set = rb_hash_aref(hash, LONG2FIX(root));
+ if (set == Qnil) {
+ set = set_s_create(0, 0, set_class);
+ rb_hash_aset(hash, LONG2FIX(root), set);
+ set_i_add(final_set, set);
+ }
+ set_i_add(set, v);
+ }
+ ALLOCV_END(tmp);
+ ALLOCV_END(uf);
+ return final_set;
+}
+
+static void set_merge_enum_into(VALUE set, VALUE arg);
+
+/*
+ * call-seq:
+ * divide { |o1, o2| ... } -> set
+ * divide { |o| ... } -> set
+ * divide -> enumerator
+ *
+ * Divides the set into a set of subsets according to the commonality
+ * defined by the given block.
+ *
+ * If the arity of the block is 2, elements o1 and o2 are in common
+ * if both block.call(o1, o2) and block.call(o2, o1) are true.
+ * Otherwise, elements o1 and o2 are in common if
+ * block.call(o1) == block.call(o2).
+ *
+ * numbers = Set[1, 3, 4, 6, 9, 10, 11]
+ * set = numbers.divide { |i,j| (i - j).abs == 1 }
+ * set #=> Set[Set[1],
+ * # Set[3, 4],
+ * # Set[6],
+ * # Set[9, 10, 11]]
+ *
+ * Returns an enumerator if no block is given.
+ */
+static VALUE
+set_i_divide(VALUE set)
+{
+ RETURN_SIZED_ENUMERATOR(set, 0, 0, set_enum_size);
+
+ if (rb_block_arity() == 2) {
+ return set_divide_arity2(set);
+ }
+
+ VALUE values = rb_hash_values(set_i_classify(set));
+ set = set_alloc_with_size(rb_cSet, RARRAY_LEN(values));
+ set_merge_enum_into(set, values);
+ return set;
+}
+
+static int
+set_clear_i(st_data_t key, st_data_t dummy)
+{
+ return ST_DELETE;
+}
+
+/*
+ * call-seq:
+ * clear -> self
+ *
+ * Removes all elements and returns self.
+ *
+ * set = Set[1, 'c', :s] #=> Set[1, "c", :s]
+ * set.clear #=> Set[]
+ * set #=> Set[]
+ */
+static VALUE
+set_i_clear(VALUE set)
+{
+ rb_check_frozen(set);
+ if (RSET_SIZE(set) == 0) return set;
+ if (set_iterating_p(set)) {
+ set_iter(set, set_clear_i, 0);
+ }
+ else {
+ set_table_clear(RSET_TABLE(set));
+ set_compact_after_delete(set);
+ }
+ return set;
+}
+
+struct set_intersection_data {
+ VALUE set;
+ set_table *into;
+ set_table *other;
+};
+
+static int
+set_intersection_i(st_data_t key, st_data_t tmp)
+{
+ struct set_intersection_data *data = (struct set_intersection_data *)tmp;
+ if (set_table_lookup(data->other, key)) {
+ set_table_insert_wb(data->into, data->set, key, NULL);
+ }
+
+ return ST_CONTINUE;
+}
+
+static VALUE
+set_intersection_block(RB_BLOCK_CALL_FUNC_ARGLIST(i, data))
+{
+ set_intersection_i((st_data_t)i, (st_data_t)data);
+ return i;
+}
+
+/*
+ * call-seq:
+ * set & enum -> new_set
+ *
+ * Returns a new set containing elements common to the set and the given
+ * enumerable object.
+ *
+ * Set[1, 3, 5] & Set[3, 2, 1] #=> Set[3, 1]
+ * Set['a', 'b', 'z'] & ['a', 'b', 'c'] #=> Set["a", "b"]
+ */
+static VALUE
+set_i_intersection(VALUE set, VALUE other)
+{
+ VALUE new_set = set_s_alloc(rb_obj_class(set));
+ set_table *stable = RSET_TABLE(set);
+ set_table *ntable = RSET_TABLE(new_set);
+
+ if (rb_obj_is_kind_of(other, rb_cSet)) {
+ set_table *otable = RSET_TABLE(other);
+ if (set_table_size(stable) >= set_table_size(otable)) {
+ /* Swap so we iterate over the smaller set */
+ otable = stable;
+ set = other;
+ }
+
+ struct set_intersection_data data = {
+ .set = new_set,
+ .into = ntable,
+ .other = otable
+ };
+ set_iter(set, set_intersection_i, (st_data_t)&data);
+ }
+ else {
+ struct set_intersection_data data = {
+ .set = new_set,
+ .into = ntable,
+ .other = stable
+ };
+ rb_block_call(other, enum_method_id(other), 0, 0, set_intersection_block, (VALUE)&data);
+ }
+
+ return new_set;
+}
+
+/*
+ * call-seq:
+ * include?(item) -> true or false
+ *
+ * Returns true if the set contains the given object:
+ *
+ * Set[1, 2, 3].include? 2 #=> true
+ * Set[1, 2, 3].include? 4 #=> false
+ *
+ * Note that <code>include?</code> and <code>member?</code> do not test member
+ * equality using <code>==</code> as do other Enumerables.
+ *
+ * This is aliased to #===, so it is usable in +case+ expressions:
+ *
+ * case :apple
+ * when Set[:potato, :carrot]
+ * "vegetable"
+ * when Set[:apple, :banana]
+ * "fruit"
+ * end
+ * # => "fruit"
+ *
+ * See also Enumerable#include?
+ */
+static VALUE
+set_i_include(VALUE set, VALUE item)
+{
+ return RBOOL(RSET_IS_MEMBER(set, item));
+}
+
+struct set_merge_args {
+ VALUE set;
+ set_table *into;
+};
+
+static int
+set_merge_i(st_data_t key, st_data_t data)
+{
+ struct set_merge_args *args = (struct set_merge_args *)data;
+ set_table_insert_wb(args->into, args->set, key, NULL);
+ return ST_CONTINUE;
+}
+
+static VALUE
+set_merge_block(RB_BLOCK_CALL_FUNC_ARGLIST(key, set))
+{
+ VALUE element = key;
+ set_insert_wb(set, element, &element);
+ return element;
+}
+
+static void
+set_merge_enum_into(VALUE set, VALUE arg)
+{
+ if (rb_obj_is_kind_of(arg, rb_cSet)) {
+ struct set_merge_args args = {
+ .set = set,
+ .into = RSET_TABLE(set)
+ };
+ set_iter(arg, set_merge_i, (st_data_t)&args);
+ }
+ else if (RB_TYPE_P(arg, T_ARRAY)) {
+ long i;
+ set_table *into = RSET_TABLE(set);
+ for (i=0; i<RARRAY_LEN(arg); i++) {
+ set_table_insert_wb(into, set, RARRAY_AREF(arg, i), NULL);
+ }
+ }
+ else {
+ rb_block_call(arg, enum_method_id(arg), 0, 0, set_merge_block, (VALUE)set);
+ }
+}
+
+/*
+ * call-seq:
+ * merge(*enums, **nil) -> self
+ *
+ * Merges the elements of the given enumerable objects to the set and
+ * returns self.
+ */
+static VALUE
+set_i_merge(int argc, VALUE *argv, VALUE set)
+{
+ if (rb_keyword_given_p()) {
+ rb_raise(rb_eArgError, "no keywords accepted");
+ }
+
+ if (set_iterating_p(set)) {
+ rb_raise(rb_eRuntimeError, "cannot add to set during iteration");
+ }
+
+ rb_check_frozen(set);
+
+ int i;
+
+ for (i=0; i < argc; i++) {
+ set_merge_enum_into(set, argv[i]);
+ }
+
+ return set;
+}
+
+static VALUE
+set_reset_table_with_type(VALUE set, const struct st_hash_type *type)
+{
+ rb_check_frozen(set);
+
+ struct set_object *sobj;
+ TypedData_Get_Struct(set, struct set_object, &set_data_type, sobj);
+ set_table *old = &sobj->table;
+
+ size_t size = set_table_size(old);
+ if (size > 0) {
+ set_table *new = set_init_table_with_size(NULL, type, size);
+ struct set_merge_args args = {
+ .set = set,
+ .into = new
+ };
+ set_iter(set, set_merge_i, (st_data_t)&args);
+ set_free_embedded(sobj);
+ memcpy(&sobj->table, new, sizeof(*new));
+ free(new);
+ }
+ else {
+ sobj->table.type = type;
+ }
+
+ return set;
+}
+
+/*
+ * call-seq:
+ * compare_by_identity -> self
+ *
+ * Makes the set compare its elements by their identity and returns self.
+ */
+static VALUE
+set_i_compare_by_identity(VALUE set)
+{
+ if (RSET_COMPARE_BY_IDENTITY(set)) return set;
+
+ if (set_iterating_p(set)) {
+ rb_raise(rb_eRuntimeError, "compare_by_identity during iteration");
+ }
+
+ return set_reset_table_with_type(set, &identhash);
+}
+
+/*
+ * call-seq:
+ * compare_by_identity? -> true or false
+ *
+ * Returns true if the set will compare its elements by their
+ * identity. Also see Set#compare_by_identity.
+ */
+static VALUE
+set_i_compare_by_identity_p(VALUE set)
+{
+ return RBOOL(RSET_COMPARE_BY_IDENTITY(set));
+}
+
+/*
+ * call-seq:
+ * size -> integer
+ *
+ * Returns the number of elements.
+ */
+static VALUE
+set_i_size(VALUE set)
+{
+ return RSET_SIZE_NUM(set);
+}
+
+/*
+ * call-seq:
+ * empty? -> true or false
+ *
+ * Returns true if the set contains no elements.
+ */
+static VALUE
+set_i_empty(VALUE set)
+{
+ return RBOOL(RSET_EMPTY(set));
+}
+
+static int
+set_xor_i(st_data_t key, st_data_t data)
+{
+ VALUE element = (VALUE)key;
+ VALUE set = (VALUE)data;
+ set_table *table = RSET_TABLE(set);
+ if (set_table_insert_wb(table, set, element, &element)) {
+ set_table_delete(table, &element);
+ }
+ return ST_CONTINUE;
+}
+
+/*
+ * call-seq:
+ * set ^ enum -> new_set
+ *
+ * Returns a new set containing elements exclusive between the set and the
+ * given enumerable object. <tt>(set ^ enum)</tt> is equivalent to
+ * <tt>((set | enum) - (set & enum))</tt>.
+ *
+ * Set[1, 2] ^ Set[2, 3] #=> Set[3, 1]
+ * Set[1, 'b', 'c'] ^ ['b', 'd'] #=> Set["d", 1, "c"]
+ */
+static VALUE
+set_i_xor(VALUE set, VALUE other)
+{
+ VALUE new_set = rb_obj_dup(set);
+
+ if (rb_obj_is_kind_of(other, rb_cSet)) {
+ set_iter(other, set_xor_i, (st_data_t)new_set);
+ }
+ else {
+ VALUE tmp = set_s_alloc(rb_cSet);
+ set_merge_enum_into(tmp, other);
+ set_iter(tmp, set_xor_i, (st_data_t)new_set);
+ }
+
+ return new_set;
+}
+
+/*
+ * call-seq:
+ * set | enum -> new_set
+ *
+ * Returns a new set built by merging the set and the elements of the
+ * given enumerable object.
+ *
+ * Set[1, 2, 3] | Set[2, 4, 5] #=> Set[1, 2, 3, 4, 5]
+ * Set[1, 5, 'z'] | (1..6) #=> Set[1, 5, "z", 2, 3, 4, 6]
+ */
+static VALUE
+set_i_union(VALUE set, VALUE other)
+{
+ set = rb_obj_dup(set);
+ set_merge_enum_into(set, other);
+ return set;
+}
+
+static int
+set_remove_i(st_data_t key, st_data_t from)
+{
+ set_table_delete((struct set_table *)from, (st_data_t *)&key);
+ return ST_CONTINUE;
+}
+
+static VALUE
+set_remove_block(RB_BLOCK_CALL_FUNC_ARGLIST(key, set))
+{
+ rb_check_frozen(set);
+ set_table_delete(RSET_TABLE(set), (st_data_t *)&key);
+ return key;
+}
+
+static void
+set_remove_enum_from(VALUE set, VALUE arg)
+{
+ if (rb_obj_is_kind_of(arg, rb_cSet)) {
+ set_iter(arg, set_remove_i, (st_data_t)RSET_TABLE(set));
+ }
+ else {
+ rb_block_call(arg, enum_method_id(arg), 0, 0, set_remove_block, (VALUE)set);
+ }
+}
+
+/*
+ * call-seq:
+ * subtract(enum) -> self
+ *
+ * Deletes every element that appears in the given enumerable object
+ * and returns self.
+ */
+static VALUE
+set_i_subtract(VALUE set, VALUE other)
+{
+ rb_check_frozen(set);
+ set_remove_enum_from(set, other);
+ return set;
+}
+
+/*
+ * call-seq:
+ * set - enum -> new_set
+ *
+ * Returns a new set built by duplicating the set, removing every
+ * element that appears in the given enumerable object.
+ *
+ * Set[1, 3, 5] - Set[1, 5] #=> Set[3]
+ * Set['a', 'b', 'z'] - ['a', 'c'] #=> Set["b", "z"]
+ */
+static VALUE
+set_i_difference(VALUE set, VALUE other)
+{
+ return set_i_subtract(rb_obj_dup(set), other);
+}
+
+static int
+set_each_i(st_data_t key, st_data_t dummy)
+{
+ rb_yield(key);
+ return ST_CONTINUE;
+}
+
+/*
+ * call-seq:
+ * each { |o| ... } -> self
+ * each -> enumerator
+ *
+ * Calls the given block once for each element in the set, passing
+ * the element as parameter. Returns an enumerator if no block is
+ * given.
+ */
+static VALUE
+set_i_each(VALUE set)
+{
+ RETURN_SIZED_ENUMERATOR(set, 0, 0, set_enum_size);
+ set_iter(set, set_each_i, 0);
+ return set;
+}
+
+static int
+set_collect_i(st_data_t key, st_data_t data)
+{
+ set_insert_wb((VALUE)data, rb_yield((VALUE)key), NULL);
+ return ST_CONTINUE;
+}
+
+/*
+ * call-seq:
+ * collect! { |o| ... } -> self
+ * collect! -> enumerator
+ *
+ * Replaces the elements with ones returned by +collect+.
+ * Returns an enumerator if no block is given.
+ */
+static VALUE
+set_i_collect(VALUE set)
+{
+ RETURN_SIZED_ENUMERATOR(set, 0, 0, set_enum_size);
+ rb_check_frozen(set);
+
+ VALUE new_set = set_s_alloc(rb_obj_class(set));
+ set_iter(set, set_collect_i, (st_data_t)new_set);
+ set_i_initialize_copy(set, new_set);
+
+ return set;
+}
+
+static int
+set_keep_if_i(st_data_t key, st_data_t into)
+{
+ if (!RTEST(rb_yield((VALUE)key))) {
+ set_table_delete((set_table *)into, &key);
+ }
+ return ST_CONTINUE;
+}
+
+/*
+ * call-seq:
+ * keep_if { |o| ... } -> self
+ * keep_if -> enumerator
+ *
+ * Deletes every element of the set for which block evaluates to false, and
+ * returns self. Returns an enumerator if no block is given.
+ */
+static VALUE
+set_i_keep_if(VALUE set)
+{
+ RETURN_SIZED_ENUMERATOR(set, 0, 0, set_enum_size);
+ rb_check_frozen(set);
+
+ set_iter(set, set_keep_if_i, (st_data_t)RSET_TABLE(set));
+
+ return set;
+}
+
+/*
+ * call-seq:
+ * select! { |o| ... } -> self
+ * select! -> enumerator
+ *
+ * Equivalent to Set#keep_if, but returns nil if no changes were made.
+ * Returns an enumerator if no block is given.
+ */
+static VALUE
+set_i_select(VALUE set)
+{
+ RETURN_SIZED_ENUMERATOR(set, 0, 0, set_enum_size);
+ rb_check_frozen(set);
+
+ set_table *table = RSET_TABLE(set);
+ size_t n = set_table_size(table);
+ set_iter(set, set_keep_if_i, (st_data_t)table);
+
+ return (n == set_table_size(table)) ? Qnil : set;
+}
+
+/*
+ * call-seq:
+ * replace(enum) -> self
+ *
+ * Replaces the contents of the set with the contents of the given
+ * enumerable object and returns self.
+ *
+ * set = Set[1, 'c', :s] #=> Set[1, "c", :s]
+ * set.replace([1, 2]) #=> Set[1, 2]
+ * set #=> Set[1, 2]
+ */
+static VALUE
+set_i_replace(VALUE set, VALUE other)
+{
+ rb_check_frozen(set);
+
+ if (rb_obj_is_kind_of(other, rb_cSet)) {
+ set_i_initialize_copy(set, other);
+ }
+ else {
+ if (set_iterating_p(set)) {
+ rb_raise(rb_eRuntimeError, "cannot replace set during iteration");
+ }
+
+ // make sure enum is enumerable before calling clear
+ enum_method_id(other);
+
+ set_table_clear(RSET_TABLE(set));
+ set_merge_enum_into(set, other);
+ }
+
+ return set;
+}
+
+/*
+ * call-seq:
+ * reset -> self
+ *
+ * Resets the internal state after modification to existing elements
+ * and returns self. Elements will be reindexed and deduplicated.
+ */
+static VALUE
+set_i_reset(VALUE set)
+{
+ if (set_iterating_p(set)) {
+ rb_raise(rb_eRuntimeError, "reset during iteration");
+ }
+
+ return set_reset_table_with_type(set, RSET_TABLE(set)->type);
+}
+
+static void set_flatten_merge(VALUE set, VALUE from, VALUE seen);
+
+static int
+set_flatten_merge_i(st_data_t item, st_data_t arg)
+{
+ VALUE *args = (VALUE *)arg;
+ VALUE set = args[0];
+ if (rb_obj_is_kind_of(item, rb_cSet)) {
+ VALUE e_id = rb_obj_id(item);
+ VALUE hash = args[2];
+ switch(rb_hash_aref(hash, e_id)) {
+ case Qfalse:
+ return ST_CONTINUE;
+ case Qtrue:
+ rb_raise(rb_eArgError, "tried to flatten recursive Set");
+ default:
+ break;
+ }
+
+ rb_hash_aset(hash, e_id, Qtrue);
+ set_flatten_merge(set, item, hash);
+ rb_hash_aset(hash, e_id, Qfalse);
+ }
+ else {
+ set_i_add(set, item);
+ }
+ return ST_CONTINUE;
+}
+
+static void
+set_flatten_merge(VALUE set, VALUE from, VALUE hash)
+{
+ VALUE args[3] = {set, from, hash};
+ set_iter(from, set_flatten_merge_i, (st_data_t)args);
+}
+
+/*
+ * call-seq:
+ * flatten -> set
+ *
+ * Returns a new set that is a copy of the set, flattening each
+ * containing set recursively.
+ */
+static VALUE
+set_i_flatten(VALUE set)
+{
+ VALUE new_set = set_s_alloc(rb_obj_class(set));
+ set_flatten_merge(new_set, set, rb_hash_new());
+ return new_set;
+}
+
+static int
+set_contains_set_i(st_data_t item, st_data_t arg)
+{
+ if (rb_obj_is_kind_of(item, rb_cSet)) {
+ *(bool *)arg = true;
+ return ST_STOP;
+ }
+ return ST_CONTINUE;
+}
+
+/*
+ * call-seq:
+ * flatten! -> self
+ *
+ * Equivalent to Set#flatten, but replaces the receiver with the
+ * result in place. Returns nil if no modifications were made.
+ */
+static VALUE
+set_i_flatten_bang(VALUE set)
+{
+ bool contains_set = false;
+ set_iter(set, set_contains_set_i, (st_data_t)&contains_set);
+ if (!contains_set) return Qnil;
+ rb_check_frozen(set);
+ return set_i_replace(set, set_i_flatten(set));
+}
+
+struct set_subset_data {
+ set_table *table;
+ VALUE result;
+};
+
+static int
+set_le_i(st_data_t key, st_data_t arg)
+{
+ struct set_subset_data *data = (struct set_subset_data *)arg;
+ if (set_table_lookup(data->table, key)) return ST_CONTINUE;
+ data->result = Qfalse;
+ return ST_STOP;
+}
+
+static VALUE
+set_le(VALUE set, VALUE other)
+{
+ struct set_subset_data data = {
+ .table = RSET_TABLE(other),
+ .result = Qtrue
+ };
+ set_iter(set, set_le_i, (st_data_t)&data);
+ return data.result;
+}
+
+/*
+ * call-seq:
+ * proper_subset?(set) -> true or false
+ *
+ * Returns true if the set is a proper subset of the given set.
+ */
+static VALUE
+set_i_proper_subset(VALUE set, VALUE other)
+{
+ check_set(other);
+ if (RSET_SIZE(set) >= RSET_SIZE(other)) return Qfalse;
+ return set_le(set, other);
+}
+
+/*
+ * call-seq:
+ * subset?(set) -> true or false
+ *
+ * Returns true if the set is a subset of the given set.
+ */
+static VALUE
+set_i_subset(VALUE set, VALUE other)
+{
+ check_set(other);
+ if (RSET_SIZE(set) > RSET_SIZE(other)) return Qfalse;
+ return set_le(set, other);
+}
+
+/*
+ * call-seq:
+ * proper_superset?(set) -> true or false
+ *
+ * Returns true if the set is a proper superset of the given set.
+ */
+static VALUE
+set_i_proper_superset(VALUE set, VALUE other)
+{
+ check_set(other);
+ if (RSET_SIZE(set) <= RSET_SIZE(other)) return Qfalse;
+ return set_le(other, set);
+}
+
+/*
+ * call-seq:
+ * superset?(set) -> true or false
+ *
+ * Returns true if the set is a superset of the given set.
+ */
+static VALUE
+set_i_superset(VALUE set, VALUE other)
+{
+ check_set(other);
+ if (RSET_SIZE(set) < RSET_SIZE(other)) return Qfalse;
+ return set_le(other, set);
+}
+
+static int
+set_intersect_i(st_data_t key, st_data_t arg)
+{
+ VALUE *args = (VALUE *)arg;
+ if (set_table_lookup((set_table *)args[0], key)) {
+ args[1] = Qtrue;
+ return ST_STOP;
+ }
+ return ST_CONTINUE;
+}
+
+/*
+ * call-seq:
+ * intersect?(set) -> true or false
+ *
+ * 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? 4..5 #=> false
+ * Set[1, 2, 3].intersect? [3, 4] #=> true
+ */
+static VALUE
+set_i_intersect(VALUE set, VALUE other)
+{
+ if (rb_obj_is_kind_of(other, rb_cSet)) {
+ size_t set_size = RSET_SIZE(set);
+ size_t other_size = RSET_SIZE(other);
+ VALUE args[2];
+ args[1] = Qfalse;
+ VALUE iter_arg;
+
+ if (set_size < other_size) {
+ iter_arg = set;
+ args[0] = (VALUE)RSET_TABLE(other);
+ }
+ else {
+ iter_arg = other;
+ args[0] = (VALUE)RSET_TABLE(set);
+ }
+ set_iter(iter_arg, set_intersect_i, (st_data_t)args);
+ return args[1];
+ }
+ else if (rb_obj_is_kind_of(other, rb_mEnumerable)) {
+ return rb_funcall(other, id_any_p, 1, set);
+ }
+ else {
+ rb_raise(rb_eArgError, "value must be enumerable");
+ }
+}
+
+/*
+ * call-seq:
+ * disjoint?(set) -> true or false
+ *
+ * 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? [3, 4] #=> false
+ * Set[1, 2, 3].disjoint? 4..5 #=> true
+ */
+static VALUE
+set_i_disjoint(VALUE set, VALUE other)
+{
+ return RBOOL(!RTEST(set_i_intersect(set, other)));
+}
+
+/*
+ * call-seq:
+ * set <=> other -> -1, 0, 1, or nil
+ *
+ * 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.
+ */
+static VALUE
+set_i_compare(VALUE set, VALUE other)
+{
+ if (rb_obj_is_kind_of(other, rb_cSet)) {
+ size_t set_size = RSET_SIZE(set);
+ size_t other_size = RSET_SIZE(other);
+
+ if (set_size < other_size) {
+ if (set_le(set, other) == Qtrue) {
+ return INT2NUM(-1);
+ }
+ }
+ else if (set_size > other_size) {
+ if (set_le(other, set) == Qtrue) {
+ return INT2NUM(1);
+ }
+ }
+ else if (set_le(set, other) == Qtrue) {
+ return INT2NUM(0);
+ }
+ }
+
+ return Qnil;
+}
+
+struct set_equal_data {
+ VALUE result;
+ VALUE set;
+};
+
+static int
+set_eql_i(st_data_t item, st_data_t arg)
+{
+ struct set_equal_data *data = (struct set_equal_data *)arg;
+
+ if (!set_table_lookup(RSET_TABLE(data->set), item)) {
+ data->result = Qfalse;
+ return ST_STOP;
+ }
+ return ST_CONTINUE;
+}
+
+static VALUE
+set_recursive_eql(VALUE set, VALUE dt, int recur)
+{
+ if (recur) return Qtrue;
+ struct set_equal_data *data = (struct set_equal_data*)dt;
+ data->result = Qtrue;
+ set_iter(set, set_eql_i, dt);
+ return data->result;
+}
+
+/*
+ * call-seq:
+ * set == other -> true or false
+ *
+ * Returns true if two sets are equal.
+ */
+static VALUE
+set_i_eq(VALUE set, VALUE other)
+{
+ if (!rb_obj_is_kind_of(other, rb_cSet)) return Qfalse;
+ if (set == other) return Qtrue;
+
+ set_table *stable = RSET_TABLE(set);
+ set_table *otable = RSET_TABLE(other);
+ size_t ssize = set_table_size(stable);
+ size_t osize = set_table_size(otable);
+
+ if (ssize != osize) return Qfalse;
+ if (ssize == 0 && osize == 0) return Qtrue;
+ if (stable->type != otable->type) return Qfalse;
+
+ struct set_equal_data data;
+ data.set = other;
+ return rb_exec_recursive_paired(set_recursive_eql, set, other, (VALUE)&data);
+}
+
+static int
+set_hash_i(st_data_t item, st_data_t(arg))
+{
+ st_index_t *hval = (st_index_t *)arg;
+ st_index_t ival = rb_hash(item);
+ *hval ^= rb_st_hash(&ival, sizeof(st_index_t), 0);
+ return ST_CONTINUE;
+}
+
+/*
+ * call-seq:
+ * hash -> integer
+ *
+ * Returns hash code for set.
+ */
+static VALUE
+set_i_hash(VALUE set)
+{
+ st_index_t size = RSET_SIZE(set);
+ st_index_t hval = rb_st_hash_start(size);
+ hval = rb_hash_uint(hval, (st_index_t)set_i_hash);
+ if (size) {
+ set_iter(set, set_hash_i, (VALUE)&hval);
+ }
+ hval = rb_st_hash_end(hval);
+ return ST2FIX(hval);
+}
+
+/* :nodoc: */
+static int
+set_to_hash_i(st_data_t key, st_data_t arg)
+{
+ rb_hash_aset((VALUE)arg, (VALUE)key, Qtrue);
+ return ST_CONTINUE;
+}
+
+static VALUE
+set_i_to_h(VALUE set)
+{
+ st_index_t size = RSET_SIZE(set);
+ VALUE hash;
+ if (RSET_COMPARE_BY_IDENTITY(set)) {
+ hash = rb_ident_hash_new_with_size(size);
+ }
+ else {
+ hash = rb_hash_new_with_size(size);
+ }
+ rb_hash_set_default(hash, Qfalse);
+
+ if (size == 0) return hash;
+
+ set_iter(set, set_to_hash_i, (st_data_t)hash);
+ return hash;
+}
+
+static VALUE
+compat_dumper(VALUE set)
+{
+ VALUE dumper = rb_class_new_instance(0, 0, rb_cObject);
+ rb_ivar_set(dumper, id_i_hash, set_i_to_h(set));
+ return dumper;
+}
+
+static int
+set_i_from_hash_i(st_data_t key, st_data_t val, st_data_t set)
+{
+ if ((VALUE)val != Qtrue) {
+ rb_raise(rb_eRuntimeError, "expect true as Set value: %"PRIsVALUE, rb_obj_class((VALUE)val));
+ }
+ set_i_add((VALUE)set, (VALUE)key);
+ return ST_CONTINUE;
+}
+
+static VALUE
+set_i_from_hash(VALUE set, VALUE hash)
+{
+ Check_Type(hash, T_HASH);
+ if (rb_hash_compare_by_id_p(hash)) set_i_compare_by_identity(set);
+ rb_hash_stlike_foreach(hash, set_i_from_hash_i, (st_data_t)set);
+ return set;
+}
+
+static VALUE
+compat_loader(VALUE self, VALUE a)
+{
+ return set_i_from_hash(self, rb_ivar_get(a, id_i_hash));
+}
+
+/* C-API functions */
+
+void
+rb_set_foreach(VALUE set, int (*func)(VALUE element, VALUE arg), VALUE arg)
+{
+ set_iter(set, func, arg);
+}
+
+VALUE
+rb_set_new(void)
+{
+ return set_alloc_with_size(rb_cSet, 0);
+}
+
+VALUE
+rb_set_new_capa(size_t capa)
+{
+ return set_alloc_with_size(rb_cSet, (st_index_t)capa);
+}
+
+bool
+rb_set_lookup(VALUE set, VALUE element)
+{
+ return RSET_IS_MEMBER(set, element);
+}
+
+bool
+rb_set_add(VALUE set, VALUE element)
+{
+ return set_i_add_p(set, element) != Qnil;
+}
+
+VALUE
+rb_set_clear(VALUE set)
+{
+ return set_i_clear(set);
+}
+
+bool
+rb_set_delete(VALUE set, VALUE element)
+{
+ return set_i_delete_p(set, element) != Qnil;
+}
+
+size_t
+rb_set_size(VALUE set)
+{
+ return RSET_SIZE(set);
+}
+
+/*
+ * Document-class: Set
+ *
+ * The Set class implements a collection of unordered values with no
+ * duplicates. It 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).
+ * 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.
+ *
+ * Set uses a data structure similar to Hash for storage, except that
+ * it only has keys and no values.
+ *
+ * * Equality of elements is determined according to Object#eql? and
+ * Object#hash. Use Set#compare_by_identity to make a set compare
+ * its elements by their identity.
+ * * Set assumes that the identity of each element does not change
+ * while it is stored. Modifying an element of a set will render the
+ * set to an unreliable state.
+ * * 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 <tt><</tt>, <tt>></tt>, <tt><=</tt>, and
+ * <tt>>=</tt> are implemented as shorthand for the
+ * {proper_,}{subset?,superset?} methods. The <tt><=></tt>
+ * operator reflects this order, or returns +nil+ for sets that both
+ * have distinct elements (<tt>{x, y}</tt> vs. <tt>{x, z}</tt> for example).
+ *
+ * == Example
+ *
+ * s1 = Set[1, 2] #=> Set[1, 2]
+ * s2 = [1, 2].to_set #=> Set[1, 2]
+ * s1 == s2 #=> true
+ * s1.add("foo") #=> Set[1, 2, "foo"]
+ * s1.merge([2, 6]) #=> Set[1, 2, "foo", 6]
+ * s1.subset?(s2) #=> false
+ * s2.subset?(s1) #=> true
+ *
+ * == Contact
+ *
+ * - Akinori MUSHA <knu@iDaemons.org> (current maintainer)
+ *
+ * == Inheriting from \Set
+ *
+ * Before Ruby 4.0 (released December 2025), \Set had a different, less
+ * efficient implementation. It was reimplemented in C, and the behavior
+ * of some of the core methods were adjusted.
+ *
+ * To keep backward compatibility, when a class is inherited from \Set,
+ * additional module +Set::SubclassCompatible+ is included, which makes
+ * the inherited class behavior, as well as internal method names,
+ * closer to what it was before Ruby 4.0.
+ *
+ * It can be easily seen, for example, in the #inspect method behavior:
+ *
+ * p Set[1, 2, 3]
+ * # prints "Set[1, 2, 3]"
+ *
+ * class MySet < Set
+ * end
+ * p MySet[1, 2, 3]
+ * # prints "#<MySet: {1, 2, 3}>", like it was in Ruby 3.4
+ *
+ * For new code, if backward compatibility is not necessary,
+ * it is recommended to instead inherit from +Set::CoreSet+, which
+ * avoids including the "compatibility" layer:
+ *
+ * class MyCoreSet < Set::CoreSet
+ * end
+ * p MyCoreSet[1, 2, 3]
+ * # prints "MyCoreSet[1, 2, 3]"
+ *
+ * == Set's methods
+ *
+ * First, what's elsewhere. \Class \Set:
+ *
+ * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
+ * - Includes {module Enumerable}[rdoc-ref:Enumerable@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}[rdoc-ref:Set@Methods+for+Creating+a+Set]
+ * - {Set Operations}[rdoc-ref:Set@Methods+for+Set+Operations]
+ * - {Comparing}[rdoc-ref:Set@Methods+for+Comparing]
+ * - {Querying}[rdoc-ref:Set@Methods+for+Querying]
+ * - {Assigning}[rdoc-ref:Set@Methods+for+Assigning]
+ * - {Deleting}[rdoc-ref:Set@Methods+for+Deleting]
+ * - {Converting}[rdoc-ref:Set@Methods+for+Converting]
+ * - {Iterating}[rdoc-ref:Set@Methods+for+Iterating]
+ * - {And more....}[rdoc-ref:Set@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
+ *
+ * - #| (aliased as #union and #+):
+ * Returns a new set containing all elements from +self+
+ * and all elements from a given enumerable (no duplicates).
+ * - #& (aliased as #intersection):
+ * Returns a new set containing all elements common to +self+
+ * and a given enumerable.
+ * - #- (aliased as #difference):
+ * Returns a copy of +self+ with all elements
+ * in a given enumerable removed.
+ * - #^: Returns a new set containing all elements from +self+
+ * and a given enumerable except those common to both.
+ *
+ * === Methods for Comparing
+ *
+ * - #<=>: Returns -1, 0, or 1 as +self+ is less than, equal to,
+ * or greater than a given object.
+ * - #==: 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 #<=):
+ * Returns whether a given object is a subset of the set.
+ * - #proper_subset? (aliased as #<):
+ * Returns whether a given enumerable is a proper subset of the set.
+ * - #superset? (aliased as #>=):
+ * Returns whether a given enumerable is a superset of the set.
+ * - #proper_superset? (aliased as #>):
+ * 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:
+ * Merges the elements of each given enumerable 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.
+ *
+ */
+void
+Init_Set(void)
+{
+ rb_cSet = rb_define_class("Set", rb_cObject);
+ rb_include_module(rb_cSet, rb_mEnumerable);
+
+ id_each_entry = rb_intern_const("each_entry");
+ id_any_p = rb_intern_const("any?");
+ id_new = rb_intern_const("new");
+ id_i_hash = rb_intern_const("@hash");
+ id_subclass_compatible = rb_intern_const("SubclassCompatible");
+ id_class_methods = rb_intern_const("ClassMethods");
+ id_set_iter_lev = rb_make_internal_id();
+
+ rb_define_alloc_func(rb_cSet, set_s_alloc);
+ rb_define_singleton_method(rb_cSet, "[]", set_s_create, -1);
+
+ rb_define_method(rb_cSet, "initialize", set_i_initialize, -1);
+ rb_define_method(rb_cSet, "initialize_copy", set_i_initialize_copy, 1);
+
+ rb_define_method(rb_cSet, "&", set_i_intersection, 1);
+ rb_define_alias(rb_cSet, "intersection", "&");
+ rb_define_method(rb_cSet, "-", set_i_difference, 1);
+ rb_define_alias(rb_cSet, "difference", "-");
+ rb_define_method(rb_cSet, "^", set_i_xor, 1);
+ rb_define_method(rb_cSet, "|", set_i_union, 1);
+ rb_define_alias(rb_cSet, "+", "|");
+ rb_define_alias(rb_cSet, "union", "|");
+ rb_define_method(rb_cSet, "<=>", set_i_compare, 1);
+ rb_define_method(rb_cSet, "==", set_i_eq, 1);
+ rb_define_alias(rb_cSet, "eql?", "==");
+ rb_define_method(rb_cSet, "add", set_i_add, 1);
+ rb_define_alias(rb_cSet, "<<", "add");
+ rb_define_method(rb_cSet, "add?", set_i_add_p, 1);
+ rb_define_method(rb_cSet, "classify", set_i_classify, 0);
+ rb_define_method(rb_cSet, "clear", set_i_clear, 0);
+ rb_define_method(rb_cSet, "collect!", set_i_collect, 0);
+ rb_define_alias(rb_cSet, "map!", "collect!");
+ rb_define_method(rb_cSet, "compare_by_identity", set_i_compare_by_identity, 0);
+ rb_define_method(rb_cSet, "compare_by_identity?", set_i_compare_by_identity_p, 0);
+ rb_define_method(rb_cSet, "delete", set_i_delete, 1);
+ rb_define_method(rb_cSet, "delete?", set_i_delete_p, 1);
+ rb_define_method(rb_cSet, "delete_if", set_i_delete_if, 0);
+ rb_define_method(rb_cSet, "disjoint?", set_i_disjoint, 1);
+ rb_define_method(rb_cSet, "divide", set_i_divide, 0);
+ rb_define_method(rb_cSet, "each", set_i_each, 0);
+ rb_define_method(rb_cSet, "empty?", set_i_empty, 0);
+ rb_define_method(rb_cSet, "flatten", set_i_flatten, 0);
+ rb_define_method(rb_cSet, "flatten!", set_i_flatten_bang, 0);
+ rb_define_method(rb_cSet, "hash", set_i_hash, 0);
+ rb_define_method(rb_cSet, "include?", set_i_include, 1);
+ rb_define_alias(rb_cSet, "member?", "include?");
+ rb_define_alias(rb_cSet, "===", "include?");
+ rb_define_method(rb_cSet, "inspect", set_i_inspect, 0);
+ rb_define_alias(rb_cSet, "to_s", "inspect");
+ rb_define_method(rb_cSet, "intersect?", set_i_intersect, 1);
+ rb_define_method(rb_cSet, "join", set_i_join, -1);
+ rb_define_method(rb_cSet, "keep_if", set_i_keep_if, 0);
+ rb_define_method(rb_cSet, "merge", set_i_merge, -1);
+ rb_define_method(rb_cSet, "proper_subset?", set_i_proper_subset, 1);
+ rb_define_alias(rb_cSet, "<", "proper_subset?");
+ rb_define_method(rb_cSet, "proper_superset?", set_i_proper_superset, 1);
+ rb_define_alias(rb_cSet, ">", "proper_superset?");
+ rb_define_method(rb_cSet, "reject!", set_i_reject, 0);
+ rb_define_method(rb_cSet, "replace", set_i_replace, 1);
+ rb_define_method(rb_cSet, "reset", set_i_reset, 0);
+ rb_define_method(rb_cSet, "size", set_i_size, 0);
+ rb_define_alias(rb_cSet, "length", "size");
+ rb_define_method(rb_cSet, "select!", set_i_select, 0);
+ rb_define_alias(rb_cSet, "filter!", "select!");
+ rb_define_method(rb_cSet, "subset?", set_i_subset, 1);
+ rb_define_alias(rb_cSet, "<=", "subset?");
+ rb_define_method(rb_cSet, "subtract", set_i_subtract, 1);
+ rb_define_method(rb_cSet, "superset?", set_i_superset, 1);
+ rb_define_alias(rb_cSet, ">=", "superset?");
+ rb_define_method(rb_cSet, "to_a", set_i_to_a, 0);
+ rb_define_method(rb_cSet, "to_set", set_i_to_set, 0);
+
+ /* :nodoc: */
+ VALUE compat = rb_define_class_under(rb_cSet, "compatible", rb_cObject);
+ rb_marshal_define_compat(rb_cSet, compat, compat_dumper, compat_loader);
+
+ // Create Set::CoreSet before defining inherited, so it does not include
+ // the backwards compatibility layer.
+ rb_define_class_under(rb_cSet, "CoreSet", rb_cSet);
+ rb_define_private_method(rb_singleton_class(rb_cSet), "inherited", set_s_inherited, 1);
+
+ rb_provide("set.rb");
+}
diff --git a/shape.c b/shape.c
index 0f9e3d54fa..90036722f1 100644
--- a/shape.c
+++ b/shape.c
@@ -20,62 +20,53 @@
#define SHAPE_DEBUG (VM_CHECK_MODE > 0)
#endif
-#if SIZEOF_SHAPE_T == 4
-#if RUBY_DEBUG
-#define SHAPE_BUFFER_SIZE 0x8000
-#else
-#define SHAPE_BUFFER_SIZE 0x80000
-#endif
-#else
-#define SHAPE_BUFFER_SIZE 0x8000
-#endif
-
#define REDBLACK_CACHE_SIZE (SHAPE_BUFFER_SIZE * 32)
+/* This depends on that the allocated memory by Ruby's allocator or
+ * mmap is not located at an odd address. */
#define SINGLE_CHILD_TAG 0x1
-#define TAG_SINGLE_CHILD(x) (struct rb_id_table *)((uintptr_t)x | SINGLE_CHILD_TAG)
+#define TAG_SINGLE_CHILD(x) (VALUE)((uintptr_t)(x) | SINGLE_CHILD_TAG)
#define SINGLE_CHILD_MASK (~((uintptr_t)SINGLE_CHILD_TAG))
-#define SINGLE_CHILD_P(x) (((uintptr_t)x) & SINGLE_CHILD_TAG)
-#define SINGLE_CHILD(x) (rb_shape_t *)((uintptr_t)x & SINGLE_CHILD_MASK)
+#define SINGLE_CHILD_P(x) ((uintptr_t)(x) & SINGLE_CHILD_TAG)
+#define SINGLE_CHILD(x) (rb_shape_t *)((uintptr_t)(x) & SINGLE_CHILD_MASK)
#define ANCESTOR_CACHE_THRESHOLD 10
#define MAX_SHAPE_ID (SHAPE_BUFFER_SIZE - 1)
#define ANCESTOR_SEARCH_MAX_DEPTH 2
-static ID id_frozen;
-static ID id_t_object;
+static ID id_object_id;
#define LEAF 0
#define BLACK 0x0
#define RED 0x1
static redblack_node_t *
-redblack_left(redblack_node_t * node)
+redblack_left(redblack_node_t *node)
{
if (node->l == LEAF) {
return LEAF;
}
else {
- RUBY_ASSERT(node->l < GET_SHAPE_TREE()->cache_size);
- redblack_node_t * left = &GET_SHAPE_TREE()->shape_cache[node->l - 1];
+ RUBY_ASSERT(node->l < rb_shape_tree.cache_size);
+ redblack_node_t *left = &rb_shape_tree.shape_cache[node->l - 1];
return left;
}
}
static redblack_node_t *
-redblack_right(redblack_node_t * node)
+redblack_right(redblack_node_t *node)
{
if (node->r == LEAF) {
return LEAF;
}
else {
- RUBY_ASSERT(node->r < GET_SHAPE_TREE()->cache_size);
- redblack_node_t * right = &GET_SHAPE_TREE()->shape_cache[node->r - 1];
+ RUBY_ASSERT(node->r < rb_shape_tree.cache_size);
+ redblack_node_t *right = &rb_shape_tree.shape_cache[node->r - 1];
return right;
}
}
static redblack_node_t *
-redblack_find(redblack_node_t * tree, ID key)
+redblack_find(redblack_node_t *tree, ID key)
{
if (tree == LEAF) {
return LEAF;
@@ -98,45 +89,45 @@ redblack_find(redblack_node_t * tree, ID key)
}
}
+static inline rb_shape_t *
+redblack_value(redblack_node_t *node)
+{
+ // Color is stored in the bottom bit of the shape pointer
+ // Mask away the bit so we get the actual pointer back
+ return (rb_shape_t *)((uintptr_t)node->value & ~(uintptr_t)1);
+}
+
+#ifdef HAVE_MMAP
static inline char
-redblack_color(redblack_node_t * node)
+redblack_color(redblack_node_t *node)
{
return node && ((uintptr_t)node->value & RED);
}
static inline bool
-redblack_red_p(redblack_node_t * node)
+redblack_red_p(redblack_node_t *node)
{
return redblack_color(node) == RED;
}
-static inline rb_shape_t *
-redblack_value(redblack_node_t * node)
-{
- // Color is stored in the bottom bit of the shape pointer
- // Mask away the bit so we get the actual pointer back
- return (rb_shape_t *)((uintptr_t)node->value & (((uintptr_t)-1) - 1));
-}
-
-#ifdef HAVE_MMAP
static redblack_id_t
-redblack_id_for(redblack_node_t * node)
+redblack_id_for(redblack_node_t *node)
{
RUBY_ASSERT(node || node == LEAF);
if (node == LEAF) {
return 0;
}
else {
- redblack_node_t * redblack_nodes = GET_SHAPE_TREE()->shape_cache;
+ redblack_node_t *redblack_nodes = rb_shape_tree.shape_cache;
redblack_id_t id = (redblack_id_t)(node - redblack_nodes);
return id + 1;
}
}
static redblack_node_t *
-redblack_new(char color, ID key, rb_shape_t * value, redblack_node_t * left, redblack_node_t * right)
+redblack_new(char color, ID key, rb_shape_t *value, redblack_node_t *left, redblack_node_t *right)
{
- if (GET_SHAPE_TREE()->cache_size + 1 >= REDBLACK_CACHE_SIZE) {
+ if (rb_shape_tree.cache_size + 1 >= REDBLACK_CACHE_SIZE) {
// We're out of cache, just quit
return LEAF;
}
@@ -144,8 +135,8 @@ redblack_new(char color, ID key, rb_shape_t * value, redblack_node_t * left, red
RUBY_ASSERT(left == LEAF || left->key < key);
RUBY_ASSERT(right == LEAF || right->key > key);
- redblack_node_t * redblack_nodes = GET_SHAPE_TREE()->shape_cache;
- redblack_node_t * node = &redblack_nodes[(GET_SHAPE_TREE()->cache_size)++];
+ redblack_node_t *redblack_nodes = rb_shape_tree.shape_cache;
+ redblack_node_t *node = &redblack_nodes[(rb_shape_tree.cache_size)++];
node->key = key;
node->value = (rb_shape_t *)((uintptr_t)value | color);
node->l = redblack_id_for(left);
@@ -154,7 +145,7 @@ redblack_new(char color, ID key, rb_shape_t * value, redblack_node_t * left, red
}
static redblack_node_t *
-redblack_balance(char color, ID key, rb_shape_t * value, redblack_node_t * left, redblack_node_t * right)
+redblack_balance(char color, ID key, rb_shape_t *value, redblack_node_t *left, redblack_node_t *right)
{
if (color == BLACK) {
ID new_key, new_left_key, new_right_key;
@@ -241,7 +232,7 @@ redblack_balance(char color, ID key, rb_shape_t * value, redblack_node_t * left,
}
static redblack_node_t *
-redblack_insert_aux(redblack_node_t * tree, ID key, rb_shape_t * value)
+redblack_insert_aux(redblack_node_t *tree, ID key, rb_shape_t *value)
{
if (tree == LEAF) {
return redblack_new(RED, key, value, LEAF, LEAF);
@@ -275,16 +266,16 @@ redblack_insert_aux(redblack_node_t * tree, ID key, rb_shape_t * value)
}
static redblack_node_t *
-redblack_force_black(redblack_node_t * node)
+redblack_force_black(redblack_node_t *node)
{
node->value = redblack_value(node);
return node;
}
static redblack_node_t *
-redblack_insert(redblack_node_t * tree, ID key, rb_shape_t * value)
+redblack_insert(redblack_node_t *tree, ID key, rb_shape_t *value)
{
- redblack_node_t * root = redblack_insert_aux(tree, key, value);
+ redblack_node_t *root = redblack_insert_aux(tree, key, value);
if (redblack_red_p(root)) {
return redblack_force_black(root);
@@ -295,128 +286,153 @@ redblack_insert(redblack_node_t * tree, ID key, rb_shape_t * value)
}
#endif
-rb_shape_tree_t *rb_shape_tree_ptr = NULL;
+rb_shape_tree_t rb_shape_tree = { 0 };
+static VALUE shape_tree_obj = Qfalse;
-/*
- * Shape getters
- */
rb_shape_t *
rb_shape_get_root_shape(void)
{
- return GET_SHAPE_TREE()->root_shape;
+ return rb_shape_tree.root_shape;
}
-shape_id_t
-rb_shape_id(rb_shape_t * shape)
-{
- return (shape_id_t)(shape - GET_SHAPE_TREE()->shape_list);
-}
-
-void
-rb_shape_each_shape(each_shape_callback callback, void *data)
+static void
+shape_tree_mark_and_move(void *data)
{
rb_shape_t *cursor = rb_shape_get_root_shape();
- rb_shape_t *end = rb_shape_get_shape_by_id(GET_SHAPE_TREE()->next_shape_id);
- while (cursor < end) {
- callback(cursor, data);
- cursor += 1;
+ rb_shape_t *end = RSHAPE(rb_shape_tree.next_shape_id - 1);
+ while (cursor <= end) {
+ if (cursor->edges && !SINGLE_CHILD_P(cursor->edges)) {
+ rb_gc_mark_and_move(&cursor->edges);
+ }
+ cursor++;
}
}
-RUBY_FUNC_EXPORTED rb_shape_t *
-rb_shape_get_shape_by_id(shape_id_t shape_id)
+static size_t
+shape_tree_memsize(const void *data)
{
- RUBY_ASSERT(shape_id != INVALID_SHAPE_ID);
+ return rb_shape_tree.cache_size * sizeof(redblack_node_t);
+}
- rb_shape_t *shape = &GET_SHAPE_TREE()->shape_list[shape_id];
- return shape;
+static const rb_data_type_t shape_tree_type = {
+ .wrap_struct_name = "VM/shape_tree",
+ .function = {
+ .dmark = shape_tree_mark_and_move,
+ .dfree = NULL, // Nothing to free, done at VM exit in rb_shape_free_all,
+ .dsize = shape_tree_memsize,
+ .dcompact = shape_tree_mark_and_move,
+ },
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
+
+/*
+ * Shape getters
+ */
+
+static inline shape_id_t
+raw_shape_id(rb_shape_t *shape)
+{
+ RUBY_ASSERT(shape);
+ return (shape_id_t)(shape - rb_shape_tree.shape_list);
}
-rb_shape_t *
-rb_shape_get_parent(rb_shape_t * shape)
+static inline shape_id_t
+shape_id(rb_shape_t *shape, shape_id_t previous_shape_id)
{
- return rb_shape_get_shape_by_id(shape->parent_id);
+ RUBY_ASSERT(shape);
+ shape_id_t raw_id = (shape_id_t)(shape - rb_shape_tree.shape_list);
+ return raw_id | (previous_shape_id & SHAPE_ID_FLAGS_MASK);
}
-#if !SHAPE_IN_BASIC_FLAGS
-shape_id_t rb_generic_shape_id(VALUE obj);
+#if RUBY_DEBUG
+static inline bool
+shape_frozen_p(shape_id_t shape_id)
+{
+ return shape_id & SHAPE_ID_FL_FROZEN;
+}
#endif
+void
+rb_shape_each_shape_id(each_shape_callback callback, void *data)
+{
+ rb_shape_t *start = rb_shape_get_root_shape();
+ rb_shape_t *cursor = start;
+ rb_shape_t *end = RSHAPE(rb_shapes_count());
+ while (cursor < end) {
+ callback((shape_id_t)(cursor - start), data);
+ cursor += 1;
+ }
+}
+
RUBY_FUNC_EXPORTED shape_id_t
-rb_shape_get_shape_id(VALUE obj)
+rb_obj_shape_id(VALUE obj)
{
if (RB_SPECIAL_CONST_P(obj)) {
- return SPECIAL_CONST_SHAPE_ID;
+ rb_bug("rb_obj_shape_id: called on a special constant");
}
-#if SHAPE_IN_BASIC_FLAGS
- return RBASIC_SHAPE_ID(obj);
-#else
- switch (BUILTIN_TYPE(obj)) {
- case T_OBJECT:
- return ROBJECT_SHAPE_ID(obj);
- break;
- case T_CLASS:
- case T_MODULE:
- return RCLASS_SHAPE_ID(obj);
- default:
- return rb_generic_shape_id(obj);
+ if (BUILTIN_TYPE(obj) == T_CLASS || BUILTIN_TYPE(obj) == T_MODULE) {
+ VALUE fields_obj = RCLASS_WRITABLE_FIELDS_OBJ(obj);
+ if (fields_obj) {
+ return RBASIC_SHAPE_ID(fields_obj);
+ }
+ return ROOT_SHAPE_ID;
}
-#endif
+ return RBASIC_SHAPE_ID(obj);
}
size_t
-rb_shape_depth(rb_shape_t * shape)
+rb_shape_depth(shape_id_t shape_id)
{
size_t depth = 1;
+ rb_shape_t *shape = RSHAPE(shape_id);
while (shape->parent_id != INVALID_SHAPE_ID) {
depth++;
- shape = rb_shape_get_parent(shape);
+ shape = RSHAPE(shape->parent_id);
}
return depth;
}
-rb_shape_t*
-rb_shape_get_shape(VALUE obj)
-{
- return rb_shape_get_shape_by_id(rb_shape_get_shape_id(obj));
-}
-
static rb_shape_t *
shape_alloc(void)
{
- shape_id_t shape_id = GET_SHAPE_TREE()->next_shape_id;
- GET_SHAPE_TREE()->next_shape_id++;
+ shape_id_t current, new_id;
- if (shape_id == (MAX_SHAPE_ID + 1)) {
- // TODO: Make an OutOfShapesError ??
- rb_bug("Out of shapes");
- }
+ do {
+ current = RUBY_ATOMIC_LOAD(rb_shape_tree.next_shape_id);
+ if (current > MAX_SHAPE_ID) {
+ return NULL; // Out of shapes
+ }
+ new_id = current + 1;
+ } while (current != RUBY_ATOMIC_CAS(rb_shape_tree.next_shape_id, current, new_id));
- return &GET_SHAPE_TREE()->shape_list[shape_id];
+ return &rb_shape_tree.shape_list[current];
}
static rb_shape_t *
rb_shape_alloc_with_parent_id(ID edge_name, shape_id_t parent_id)
{
- rb_shape_t * shape = shape_alloc();
+ rb_shape_t *shape = shape_alloc();
+ if (!shape) return NULL;
shape->edge_name = edge_name;
- shape->next_iv_index = 0;
+ shape->next_field_index = 0;
shape->parent_id = parent_id;
- shape->edges = NULL;
+ shape->edges = 0;
return shape;
}
static rb_shape_t *
-rb_shape_alloc(ID edge_name, rb_shape_t * parent, enum shape_type type)
+rb_shape_alloc(ID edge_name, rb_shape_t *parent, enum shape_type type)
{
- rb_shape_t * shape = rb_shape_alloc_with_parent_id(edge_name, rb_shape_id(parent));
+ rb_shape_t *shape = rb_shape_alloc_with_parent_id(edge_name, raw_shape_id(parent));
+ if (!shape) return NULL;
+
shape->type = (uint8_t)type;
- shape->size_pool_index = parent->size_pool_index;
shape->capacity = parent->capacity;
shape->edges = 0;
return shape;
@@ -424,12 +440,12 @@ rb_shape_alloc(ID edge_name, rb_shape_t * parent, enum shape_type type)
#ifdef HAVE_MMAP
static redblack_node_t *
-redblack_cache_ancestors(rb_shape_t * shape)
+redblack_cache_ancestors(rb_shape_t *shape)
{
if (!(shape->ancestor_index || shape->parent_id == INVALID_SHAPE_ID)) {
- redblack_node_t * parent_index;
+ redblack_node_t *parent_index;
- parent_index = redblack_cache_ancestors(rb_shape_get_parent(shape));
+ parent_index = redblack_cache_ancestors(RSHAPE(shape->parent_id));
if (shape->type == SHAPE_IVAR) {
shape->ancestor_index = redblack_insert(parent_index, shape->edge_name, shape);
@@ -451,35 +467,51 @@ redblack_cache_ancestors(rb_shape_t * shape)
}
#else
static redblack_node_t *
-redblack_cache_ancestors(rb_shape_t * shape)
+redblack_cache_ancestors(rb_shape_t *shape)
{
return LEAF;
}
#endif
+static attr_index_t
+shape_grow_capa(attr_index_t current_capa)
+{
+ const attr_index_t *capacities = rb_shape_tree.capacities;
+
+ // First try to use the next size that will be embeddable in a larger object slot.
+ attr_index_t capa;
+ while ((capa = *capacities)) {
+ if (capa > current_capa) {
+ return capa;
+ }
+ capacities++;
+ }
+
+ return (attr_index_t)rb_malloc_grow_capa(current_capa, sizeof(VALUE));
+}
+
static rb_shape_t *
-rb_shape_alloc_new_child(ID id, rb_shape_t * shape, enum shape_type shape_type)
+rb_shape_alloc_new_child(ID id, rb_shape_t *shape, enum shape_type shape_type)
{
- rb_shape_t * new_shape = rb_shape_alloc(id, shape, shape_type);
+ rb_shape_t *new_shape = rb_shape_alloc(id, shape, shape_type);
+ if (!new_shape) return NULL;
switch (shape_type) {
+ case SHAPE_OBJ_ID:
case SHAPE_IVAR:
- if (UNLIKELY(shape->next_iv_index >= shape->capacity)) {
- RUBY_ASSERT(shape->next_iv_index == shape->capacity);
- new_shape->capacity = (uint32_t)rb_malloc_grow_capa(shape->capacity, sizeof(VALUE));
+ if (UNLIKELY(shape->next_field_index >= shape->capacity)) {
+ RUBY_ASSERT(shape->next_field_index == shape->capacity);
+ new_shape->capacity = shape_grow_capa(shape->capacity);
}
- RUBY_ASSERT(new_shape->capacity > shape->next_iv_index);
- new_shape->next_iv_index = shape->next_iv_index + 1;
- if (new_shape->next_iv_index > ANCESTOR_CACHE_THRESHOLD) {
- redblack_cache_ancestors(new_shape);
+ RUBY_ASSERT(new_shape->capacity > shape->next_field_index);
+ new_shape->next_field_index = shape->next_field_index + 1;
+ if (new_shape->next_field_index > ANCESTOR_CACHE_THRESHOLD) {
+ RB_VM_LOCKING() {
+ redblack_cache_ancestors(new_shape);
+ }
}
break;
- case SHAPE_FROZEN:
- new_shape->next_iv_index = shape->next_iv_index;
- break;
- case SHAPE_OBJ_TOO_COMPLEX:
case SHAPE_ROOT:
- case SHAPE_T_OBJECT:
rb_bug("Unreachable");
break;
}
@@ -487,259 +519,325 @@ rb_shape_alloc_new_child(ID id, rb_shape_t * shape, enum shape_type shape_type)
return new_shape;
}
-static rb_shape_t*
-get_next_shape_internal(rb_shape_t * shape, ID id, enum shape_type shape_type, bool * variation_created, bool new_variations_allowed)
+static rb_shape_t *
+get_next_shape_internal_atomic(rb_shape_t *shape, ID id, enum shape_type shape_type, bool *variation_created, bool new_variations_allowed)
{
rb_shape_t *res = NULL;
- // There should never be outgoing edges from "too complex"
- RUBY_ASSERT(rb_shape_id(shape) != OBJ_TOO_COMPLEX_SHAPE_ID);
-
*variation_created = false;
-
- RB_VM_LOCK_ENTER();
- {
- // If the current shape has children
- if (shape->edges) {
- // Check if it only has one child
- if (SINGLE_CHILD_P(shape->edges)) {
- rb_shape_t * child = SINGLE_CHILD(shape->edges);
- // If the one child has a matching edge name, then great,
- // we found what we want.
- if (child->edge_name == id) {
- res = child;
- }
+ VALUE edges_table;
+
+retry:
+ edges_table = RUBY_ATOMIC_VALUE_LOAD(shape->edges);
+
+ // If the current shape has children
+ if (edges_table) {
+ // Check if it only has one child
+ if (SINGLE_CHILD_P(edges_table)) {
+ rb_shape_t *child = SINGLE_CHILD(edges_table);
+ // If the one child has a matching edge name, then great,
+ // we found what we want.
+ if (child->edge_name == id) {
+ res = child;
}
- else {
- // If it has more than one child, do a hash lookup to find it.
- VALUE lookup_result;
- if (rb_id_table_lookup(shape->edges, id, &lookup_result)) {
- res = (rb_shape_t *)lookup_result;
- }
+ }
+ else {
+ // If it has more than one child, do a hash lookup to find it.
+ VALUE lookup_result;
+ if (rb_managed_id_table_lookup(edges_table, id, &lookup_result)) {
+ res = (rb_shape_t *)lookup_result;
}
}
+ }
+
+ // If we didn't find the shape we're looking for and we're allowed more variations we create it.
+ if (!res && new_variations_allowed) {
+ VALUE new_edges = 0;
+
+ rb_shape_t *new_shape = rb_shape_alloc_new_child(id, shape, shape_type);
- // If we didn't find the shape we're looking for we create it.
- if (!res) {
- // If we're not allowed to create a new variation, of if we're out of shapes
- // we return TOO_COMPLEX_SHAPE.
- if (!new_variations_allowed || GET_SHAPE_TREE()->next_shape_id > MAX_SHAPE_ID) {
- res = rb_shape_get_shape_by_id(OBJ_TOO_COMPLEX_SHAPE_ID);
+ // If we're out of shapes, return NULL
+ if (new_shape) {
+ if (!edges_table) {
+ // If the shape had no edge yet, we can directly set the new child
+ new_edges = TAG_SINGLE_CHILD(new_shape);
}
else {
- rb_shape_t * new_shape = rb_shape_alloc_new_child(id, shape, shape_type);
-
- if (!shape->edges) {
- // If the shape had no edge yet, we can directly set the new child
- shape->edges = TAG_SINGLE_CHILD(new_shape);
+ // If the edge was single child we need to allocate a table.
+ if (SINGLE_CHILD_P(edges_table)) {
+ rb_shape_t *old_child = SINGLE_CHILD(edges_table);
+ new_edges = rb_managed_id_table_new(2);
+ rb_managed_id_table_insert(new_edges, old_child->edge_name, (VALUE)old_child);
}
else {
- // If the edge was single child we need to allocate a table.
- if (SINGLE_CHILD_P(shape->edges)) {
- rb_shape_t * old_child = SINGLE_CHILD(shape->edges);
- shape->edges = rb_id_table_create(2);
- rb_id_table_insert(shape->edges, old_child->edge_name, (VALUE)old_child);
- }
-
- rb_id_table_insert(shape->edges, new_shape->edge_name, (VALUE)new_shape);
- *variation_created = true;
+ new_edges = rb_managed_id_table_dup(edges_table);
}
- res = new_shape;
+ rb_managed_id_table_insert(new_edges, new_shape->edge_name, (VALUE)new_shape);
+ *variation_created = true;
+ }
+
+ if (edges_table != RUBY_ATOMIC_VALUE_CAS(shape->edges, edges_table, new_edges)) {
+ // Another thread updated the table;
+ goto retry;
}
+ RB_OBJ_WRITTEN(shape_tree_obj, Qundef, new_edges);
+ res = new_shape;
+ RB_GC_GUARD(new_edges);
}
}
- RB_VM_LOCK_LEAVE();
return res;
}
-int
-rb_shape_frozen_shape_p(rb_shape_t* shape)
-{
- return SHAPE_FROZEN == (enum shape_type)shape->type;
-}
-
static rb_shape_t *
-remove_shape_recursive(rb_shape_t *shape, ID id, rb_shape_t **removed_shape)
+get_next_shape_internal(rb_shape_t *shape, ID id, enum shape_type shape_type, bool *variation_created, bool new_variations_allowed)
{
- if (shape->parent_id == INVALID_SHAPE_ID) {
- // We've hit the top of the shape tree and couldn't find the
- // IV we wanted to remove, so return NULL
- return NULL;
+ if (rb_multi_ractor_p()) {
+ return get_next_shape_internal_atomic(shape, id, shape_type, variation_created, new_variations_allowed);
}
- else {
- if (shape->type == SHAPE_IVAR && shape->edge_name == id) {
- *removed_shape = shape;
- return rb_shape_get_parent(shape);
+ rb_shape_t *res = NULL;
+ *variation_created = false;
+
+ VALUE edges_table = shape->edges;
+
+ // If the current shape has children
+ if (edges_table) {
+ // Check if it only has one child
+ if (SINGLE_CHILD_P(edges_table)) {
+ rb_shape_t *child = SINGLE_CHILD(edges_table);
+ // If the one child has a matching edge name, then great,
+ // we found what we want.
+ if (child->edge_name == id) {
+ res = child;
+ }
}
else {
- // This isn't the IV we want to remove, keep walking up.
- rb_shape_t *new_parent = remove_shape_recursive(rb_shape_get_parent(shape), id, removed_shape);
-
- // We found a new parent. Create a child of the new parent that
- // has the same attributes as this shape.
- if (new_parent) {
- if (UNLIKELY(new_parent->type == SHAPE_OBJ_TOO_COMPLEX)) {
- return new_parent;
- }
-
- bool dont_care;
- rb_shape_t *new_child = get_next_shape_internal(new_parent, shape->edge_name, shape->type, &dont_care, true);
- if (UNLIKELY(new_child->type == SHAPE_OBJ_TOO_COMPLEX)) {
- return new_child;
- }
+ // If it has more than one child, do a hash lookup to find it.
+ VALUE lookup_result;
+ if (rb_managed_id_table_lookup(edges_table, id, &lookup_result)) {
+ res = (rb_shape_t *)lookup_result;
+ }
+ }
+ }
- RUBY_ASSERT(new_child->capacity <= shape->capacity);
+ // If we didn't find the shape we're looking for we create it.
+ if (!res) {
+ // If we're not allowed to create a new variation, of if we're out of shapes
+ // we return TOO_COMPLEX_SHAPE.
+ if (!new_variations_allowed || rb_shapes_count() > MAX_SHAPE_ID) {
+ res = NULL;
+ }
+ else {
+ rb_shape_t *new_shape = rb_shape_alloc_new_child(id, shape, shape_type);
- return new_child;
+ if (!edges_table) {
+ // If the shape had no edge yet, we can directly set the new child
+ shape->edges = TAG_SINGLE_CHILD(new_shape);
}
else {
- // We went all the way to the top of the shape tree and couldn't
- // find an IV to remove, so return NULL
- return NULL;
+ // If the edge was single child we need to allocate a table.
+ if (SINGLE_CHILD_P(edges_table)) {
+ rb_shape_t *old_child = SINGLE_CHILD(edges_table);
+ VALUE new_edges = rb_managed_id_table_new(2);
+ rb_managed_id_table_insert(new_edges, old_child->edge_name, (VALUE)old_child);
+ RB_OBJ_WRITE(shape_tree_obj, &shape->edges, new_edges);
+ }
+
+ rb_managed_id_table_insert(shape->edges, new_shape->edge_name, (VALUE)new_shape);
+ *variation_created = true;
}
+
+ res = new_shape;
}
}
+
+ return res;
}
-bool
-rb_shape_transition_shape_remove_ivar(VALUE obj, ID id, rb_shape_t *shape, VALUE *removed)
+static inline shape_id_t transition_complex(shape_id_t shape_id);
+
+static shape_id_t
+shape_transition_object_id(shape_id_t original_shape_id)
{
- if (UNLIKELY(shape->type == SHAPE_OBJ_TOO_COMPLEX)) {
- return false;
+ RUBY_ASSERT(!rb_shape_has_object_id(original_shape_id));
+
+ bool dont_care;
+ rb_shape_t *shape = get_next_shape_internal(RSHAPE(original_shape_id), id_object_id, SHAPE_OBJ_ID, &dont_care, true);
+ if (!shape) {
+ shape = RSHAPE(ROOT_SHAPE_WITH_OBJ_ID);
+ return transition_complex(shape_id(shape, original_shape_id) | SHAPE_ID_FL_HAS_OBJECT_ID);
}
- rb_shape_t *removed_shape = NULL;
- rb_shape_t *new_shape = remove_shape_recursive(shape, id, &removed_shape);
- if (new_shape) {
- RUBY_ASSERT(removed_shape != NULL);
+ RUBY_ASSERT(shape);
+ return shape_id(shape, original_shape_id) | SHAPE_ID_FL_HAS_OBJECT_ID;
+}
- if (UNLIKELY(new_shape->type == SHAPE_OBJ_TOO_COMPLEX)) {
- return false;
- }
+shape_id_t
+rb_shape_transition_object_id(VALUE obj)
+{
+ return shape_transition_object_id(RBASIC_SHAPE_ID(obj));
+}
- RUBY_ASSERT(new_shape->next_iv_index == shape->next_iv_index - 1);
+shape_id_t
+rb_shape_object_id(shape_id_t original_shape_id)
+{
+ RUBY_ASSERT(rb_shape_has_object_id(original_shape_id));
- VALUE *ivptr;
- switch(BUILTIN_TYPE(obj)) {
- case T_CLASS:
- case T_MODULE:
- ivptr = RCLASS_IVPTR(obj);
- break;
- case T_OBJECT:
- ivptr = ROBJECT_IVPTR(obj);
- break;
- default: {
- struct gen_ivtbl *ivtbl;
- rb_gen_ivtbl_get(obj, id, &ivtbl);
- ivptr = ivtbl->as.shape.ivptr;
- break;
- }
+ rb_shape_t *shape = RSHAPE(original_shape_id);
+ while (shape->type != SHAPE_OBJ_ID) {
+ if (UNLIKELY(shape->parent_id == INVALID_SHAPE_ID)) {
+ rb_bug("Missing object_id in shape tree");
}
+ shape = RSHAPE(shape->parent_id);
+ }
- *removed = ivptr[removed_shape->next_iv_index - 1];
+ return shape_id(shape, original_shape_id) | SHAPE_ID_FL_HAS_OBJECT_ID;
+}
- memmove(&ivptr[removed_shape->next_iv_index - 1], &ivptr[removed_shape->next_iv_index],
- ((new_shape->next_iv_index + 1) - removed_shape->next_iv_index) * sizeof(VALUE));
+static inline shape_id_t
+transition_complex(shape_id_t shape_id)
+{
+ uint8_t heap_index = rb_shape_heap_index(shape_id);
+ shape_id_t next_shape_id;
- // Re-embed objects when instances become small enough
- // This is necessary because YJIT assumes that objects with the same shape
- // have the same embeddedness for efficiency (avoid extra checks)
- if (BUILTIN_TYPE(obj) == T_OBJECT &&
- !RB_FL_TEST_RAW(obj, ROBJECT_EMBED) &&
- rb_obj_embedded_size(new_shape->next_iv_index) <= rb_gc_obj_slot_size(obj)) {
- RB_FL_SET_RAW(obj, ROBJECT_EMBED);
- memcpy(ROBJECT_IVPTR(obj), ivptr, new_shape->next_iv_index * sizeof(VALUE));
- xfree(ivptr);
+ if (heap_index) {
+ next_shape_id = rb_shape_root(heap_index - 1) | SHAPE_ID_FL_TOO_COMPLEX;
+ if (rb_shape_has_object_id(shape_id)) {
+ next_shape_id = shape_transition_object_id(next_shape_id);
}
-
- rb_shape_set_shape(obj, new_shape);
}
- return true;
+ else {
+ if (rb_shape_has_object_id(shape_id)) {
+ next_shape_id = ROOT_TOO_COMPLEX_WITH_OBJ_ID | (shape_id & SHAPE_ID_FLAGS_MASK);
+ }
+ else {
+ next_shape_id = ROOT_TOO_COMPLEX_SHAPE_ID | (shape_id & SHAPE_ID_FLAGS_MASK);
+ }
+ }
+
+ RUBY_ASSERT(rb_shape_has_object_id(shape_id) == rb_shape_has_object_id(next_shape_id));
+
+ return next_shape_id;
}
-rb_shape_t *
-rb_shape_transition_shape_frozen(VALUE obj)
+shape_id_t
+rb_shape_transition_frozen(VALUE obj)
{
- rb_shape_t* shape = rb_shape_get_shape(obj);
- RUBY_ASSERT(shape);
RUBY_ASSERT(RB_OBJ_FROZEN(obj));
- if (rb_shape_frozen_shape_p(shape) || rb_shape_obj_too_complex(obj)) {
- return shape;
- }
-
- rb_shape_t* next_shape;
+ shape_id_t shape_id = rb_obj_shape_id(obj);
+ return shape_id | SHAPE_ID_FL_FROZEN;
+}
- if (shape == rb_shape_get_root_shape()) {
- return rb_shape_get_shape_by_id(SPECIAL_CONST_SHAPE_ID);
- }
+shape_id_t
+rb_shape_transition_complex(VALUE obj)
+{
+ return transition_complex(RBASIC_SHAPE_ID(obj));
+}
- bool dont_care;
- next_shape = get_next_shape_internal(shape, (ID)id_frozen, SHAPE_FROZEN, &dont_care, true);
+shape_id_t
+rb_shape_transition_heap(VALUE obj, size_t heap_index)
+{
+ return (RBASIC_SHAPE_ID(obj) & (~SHAPE_ID_HEAP_INDEX_MASK)) | rb_shape_root(heap_index);
+}
- RUBY_ASSERT(next_shape);
- return next_shape;
+void
+rb_set_boxed_class_shape_id(VALUE obj, shape_id_t shape_id)
+{
+ RBASIC_SET_SHAPE_ID(RCLASS_WRITABLE_ENSURE_FIELDS_OBJ(obj), shape_id);
+ // FIXME: How to do multi-shape?
+ RBASIC_SET_SHAPE_ID(obj, shape_id);
}
/*
* This function is used for assertions where we don't want to increment
* max_iv_count
*/
-rb_shape_t *
-rb_shape_get_next_iv_shape(rb_shape_t* shape, ID id)
+static inline rb_shape_t *
+shape_get_next_iv_shape(rb_shape_t *shape, ID id)
{
RUBY_ASSERT(!is_instance_id(id) || RTEST(rb_sym2str(ID2SYM(id))));
bool dont_care;
return get_next_shape_internal(shape, id, SHAPE_IVAR, &dont_care, true);
}
-rb_shape_t *
-rb_shape_get_next(rb_shape_t *shape, VALUE obj, ID id)
+shape_id_t
+rb_shape_get_next_iv_shape(shape_id_t shape_id, ID id)
{
- RUBY_ASSERT(!is_instance_id(id) || RTEST(rb_sym2str(ID2SYM(id))));
- if (UNLIKELY(shape->type == SHAPE_OBJ_TOO_COMPLEX)) {
- return shape;
+ rb_shape_t *shape = RSHAPE(shape_id);
+ rb_shape_t *next_shape = shape_get_next_iv_shape(shape, id);
+ if (!next_shape) {
+ return INVALID_SHAPE_ID;
}
+ return raw_shape_id(next_shape);
+}
+
+static bool
+shape_get_iv_index(rb_shape_t *shape, ID id, attr_index_t *value)
+{
+ while (shape->parent_id != INVALID_SHAPE_ID) {
+ if (shape->edge_name == id) {
+ enum shape_type shape_type;
+ shape_type = (enum shape_type)shape->type;
+
+ switch (shape_type) {
+ case SHAPE_IVAR:
+ RUBY_ASSERT(shape->next_field_index > 0);
+ *value = shape->next_field_index - 1;
+ return true;
+ case SHAPE_ROOT:
+ return false;
+ case SHAPE_OBJ_ID:
+ rb_bug("Ivar should not exist on transition");
+ }
+ }
+
+ shape = RSHAPE(shape->parent_id);
+ }
+
+ return false;
+}
+
+static inline rb_shape_t *
+shape_get_next(rb_shape_t *shape, enum shape_type shape_type, VALUE klass, ID id, bool emit_warnings)
+{
+ RUBY_ASSERT(!is_instance_id(id) || RTEST(rb_sym2str(ID2SYM(id))));
#if RUBY_DEBUG
attr_index_t index;
- if (rb_shape_get_iv_index(shape, id, &index)) {
+ if (shape_get_iv_index(shape, id, &index)) {
rb_bug("rb_shape_get_next: trying to create ivar that already exists at index %u", index);
}
#endif
- bool allow_new_shape = true;
+ bool allow_new_shape = RCLASS_VARIATION_COUNT(klass) < SHAPE_MAX_VARIATIONS;
+ bool variation_created = false;
+ rb_shape_t *new_shape = get_next_shape_internal(shape, id, shape_type, &variation_created, allow_new_shape);
- if (BUILTIN_TYPE(obj) == T_OBJECT) {
- VALUE klass = rb_obj_class(obj);
- allow_new_shape = RCLASS_EXT(klass)->variation_count < SHAPE_MAX_VARIATIONS;
+ if (!new_shape) {
+ // We could create a new variation, transitioning to TOO_COMPLEX.
+ return NULL;
}
- bool variation_created = false;
- rb_shape_t *new_shape = get_next_shape_internal(shape, id, SHAPE_IVAR, &variation_created, allow_new_shape);
-
// Check if we should update max_iv_count on the object's class
- if (BUILTIN_TYPE(obj) == T_OBJECT) {
- VALUE klass = rb_obj_class(obj);
- if (new_shape->next_iv_index > RCLASS_EXT(klass)->max_iv_count) {
- RCLASS_EXT(klass)->max_iv_count = new_shape->next_iv_index;
- }
+ if (new_shape->next_field_index > RCLASS_MAX_IV_COUNT(klass)) {
+ RCLASS_SET_MAX_IV_COUNT(klass, new_shape->next_field_index);
+ }
- if (variation_created) {
- RCLASS_EXT(klass)->variation_count++;
- if (rb_warning_category_enabled_p(RB_WARN_CATEGORY_PERFORMANCE)) {
- if (RCLASS_EXT(klass)->variation_count >= SHAPE_MAX_VARIATIONS) {
- rb_category_warn(
- RB_WARN_CATEGORY_PERFORMANCE,
- "The class %"PRIsVALUE" reached %d shape variations, instance variables accesses will be slower and memory usage increased.\n"
- "It is recommended to define instance variables in a consistent order, for instance by eagerly defining them all in the #initialize method.",
- rb_class_path(klass),
- SHAPE_MAX_VARIATIONS
- );
- }
+ if (variation_created) {
+ RCLASS_VARIATION_COUNT(klass)++;
+
+ if (emit_warnings && rb_warning_category_enabled_p(RB_WARN_CATEGORY_PERFORMANCE)) {
+ if (RCLASS_VARIATION_COUNT(klass) >= SHAPE_MAX_VARIATIONS) {
+ rb_category_warn(
+ RB_WARN_CATEGORY_PERFORMANCE,
+ "The class %"PRIsVALUE" reached %d shape variations, instance variables accesses will be slower and memory usage increased.\n"
+ "It is recommended to define instance variables in a consistent order, for instance by eagerly defining them all in the #initialize method.",
+ rb_class_path(klass),
+ SHAPE_MAX_VARIATIONS
+ );
}
}
}
@@ -747,50 +845,168 @@ rb_shape_get_next(rb_shape_t *shape, VALUE obj, ID id)
return new_shape;
}
+static VALUE
+obj_get_owner_class(VALUE obj)
+{
+ VALUE klass;
+ if (IMEMO_TYPE_P(obj, imemo_fields)) {
+ VALUE owner = rb_imemo_fields_owner(obj);
+ switch (BUILTIN_TYPE(owner)) {
+ case T_CLASS:
+ case T_MODULE:
+ klass = rb_singleton_class(owner);
+ break;
+ default:
+ klass = rb_obj_class(owner);
+ break;
+ }
+ }
+ else {
+ klass = rb_obj_class(obj);
+ }
+ return klass;
+}
+
+static rb_shape_t *
+remove_shape_recursive(VALUE obj, rb_shape_t *shape, ID id, rb_shape_t **removed_shape)
+{
+ if (shape->parent_id == INVALID_SHAPE_ID) {
+ // We've hit the top of the shape tree and couldn't find the
+ // IV we wanted to remove, so return NULL
+ *removed_shape = NULL;
+ return NULL;
+ }
+ else {
+ if (shape->type == SHAPE_IVAR && shape->edge_name == id) {
+ *removed_shape = shape;
+
+ return RSHAPE(shape->parent_id);
+ }
+ else {
+ // This isn't the IV we want to remove, keep walking up.
+ rb_shape_t *new_parent = remove_shape_recursive(obj, RSHAPE(shape->parent_id), id, removed_shape);
+
+ // We found a new parent. Create a child of the new parent that
+ // has the same attributes as this shape.
+ if (new_parent) {
+ VALUE klass = obj_get_owner_class(obj);
+ rb_shape_t *new_child = shape_get_next(new_parent, shape->type, klass, shape->edge_name, true);
+ RUBY_ASSERT(!new_child || new_child->capacity <= shape->capacity);
+ return new_child;
+ }
+ else {
+ // We went all the way to the top of the shape tree and couldn't
+ // find an IV to remove so return NULL.
+ return NULL;
+ }
+ }
+ }
+}
+
+shape_id_t
+rb_shape_transition_remove_ivar(VALUE obj, ID id, shape_id_t *removed_shape_id)
+{
+ shape_id_t original_shape_id = RBASIC_SHAPE_ID(obj);
+ RUBY_ASSERT(!shape_frozen_p(original_shape_id));
+
+ if (rb_shape_too_complex_p(original_shape_id)) {
+ return original_shape_id;
+ }
+
+ rb_shape_t *removed_shape = NULL;
+ rb_shape_t *new_shape = remove_shape_recursive(obj, RSHAPE(original_shape_id), id, &removed_shape);
+
+ if (removed_shape) {
+ *removed_shape_id = raw_shape_id(removed_shape);
+ }
+
+ if (new_shape) {
+ return shape_id(new_shape, original_shape_id);
+ }
+ else if (removed_shape) {
+ // We found the shape to remove, but couldn't create a new variation.
+ // We must transition to TOO_COMPLEX.
+ shape_id_t next_shape_id = transition_complex(original_shape_id);
+ RUBY_ASSERT(rb_shape_has_object_id(next_shape_id) == rb_shape_has_object_id(original_shape_id));
+ return next_shape_id;
+ }
+ return original_shape_id;
+}
+
+shape_id_t
+rb_shape_transition_add_ivar(VALUE obj, ID id)
+{
+ shape_id_t original_shape_id = RBASIC_SHAPE_ID(obj);
+ RUBY_ASSERT(!shape_frozen_p(original_shape_id));
+
+ VALUE klass = obj_get_owner_class(obj);
+ rb_shape_t *next_shape = shape_get_next(RSHAPE(original_shape_id), SHAPE_IVAR, klass, id, true);
+ if (next_shape) {
+ return shape_id(next_shape, original_shape_id);
+ }
+ else {
+ return transition_complex(original_shape_id);
+ }
+}
+
+shape_id_t
+rb_shape_transition_add_ivar_no_warnings(VALUE klass, shape_id_t original_shape_id, ID id)
+{
+ RUBY_ASSERT(!shape_frozen_p(original_shape_id));
+
+ rb_shape_t *next_shape = shape_get_next(RSHAPE(original_shape_id), SHAPE_IVAR, klass, id, false);
+ if (next_shape) {
+ return shape_id(next_shape, original_shape_id);
+ }
+ else {
+ return transition_complex(original_shape_id);
+ }
+}
+
// Same as rb_shape_get_iv_index, but uses a provided valid shape id and index
// to return a result faster if branches of the shape tree are closely related.
bool
rb_shape_get_iv_index_with_hint(shape_id_t shape_id, ID id, attr_index_t *value, shape_id_t *shape_id_hint)
{
attr_index_t index_hint = *value;
- rb_shape_t *shape = rb_shape_get_shape_by_id(shape_id);
- rb_shape_t *initial_shape = shape;
if (*shape_id_hint == INVALID_SHAPE_ID) {
*shape_id_hint = shape_id;
- return rb_shape_get_iv_index(shape, id, value);
+ return rb_shape_get_iv_index(shape_id, id, value);
}
- rb_shape_t * shape_hint = rb_shape_get_shape_by_id(*shape_id_hint);
+ rb_shape_t *shape = RSHAPE(shape_id);
+ rb_shape_t *initial_shape = shape;
+ rb_shape_t *shape_hint = RSHAPE(*shape_id_hint);
// We assume it's likely shape_id_hint and shape_id have a close common
// ancestor, so we check up to ANCESTOR_SEARCH_MAX_DEPTH ancestors before
// eventually using the index, as in case of a match it will be faster.
// However if the shape doesn't have an index, we walk the entire tree.
int depth = INT_MAX;
- if (shape->ancestor_index && shape->next_iv_index >= ANCESTOR_CACHE_THRESHOLD) {
+ if (shape->ancestor_index && shape->next_field_index >= ANCESTOR_CACHE_THRESHOLD) {
depth = ANCESTOR_SEARCH_MAX_DEPTH;
}
- while (depth > 0 && shape->next_iv_index > index_hint) {
- while (shape_hint->next_iv_index > shape->next_iv_index) {
- shape_hint = rb_shape_get_parent(shape_hint);
+ while (depth > 0 && shape->next_field_index > index_hint) {
+ while (shape_hint->next_field_index > shape->next_field_index) {
+ shape_hint = RSHAPE(shape_hint->parent_id);
}
if (shape_hint == shape) {
// We've found a common ancestor so use the index hint
*value = index_hint;
- *shape_id_hint = rb_shape_id(shape);
+ *shape_id_hint = raw_shape_id(shape);
return true;
}
if (shape->edge_name == id) {
// We found the matching id before a common ancestor
- *value = shape->next_iv_index - 1;
- *shape_id_hint = rb_shape_id(shape);
+ *value = shape->next_field_index - 1;
+ *shape_id_hint = raw_shape_id(shape);
return true;
}
- shape = rb_shape_get_parent(shape);
+ shape = RSHAPE(shape->parent_id);
depth--;
}
@@ -800,87 +1016,78 @@ rb_shape_get_iv_index_with_hint(shape_id_t shape_id, ID id, attr_index_t *value,
shape = initial_shape;
}
*shape_id_hint = shape_id;
- return rb_shape_get_iv_index(shape, id, value);
+ return shape_get_iv_index(shape, id, value);
}
static bool
-shape_get_iv_index(rb_shape_t *shape, ID id, attr_index_t *value)
+shape_cache_find_ivar(rb_shape_t *shape, ID id, rb_shape_t **ivar_shape)
{
- while (shape->parent_id != INVALID_SHAPE_ID) {
- if (shape->edge_name == id) {
- enum shape_type shape_type;
- shape_type = (enum shape_type)shape->type;
+ if (shape->ancestor_index && shape->next_field_index >= ANCESTOR_CACHE_THRESHOLD) {
+ redblack_node_t *node = redblack_find(shape->ancestor_index, id);
+ if (node) {
+ *ivar_shape = redblack_value(node);
- switch (shape_type) {
- case SHAPE_IVAR:
- RUBY_ASSERT(shape->next_iv_index > 0);
- *value = shape->next_iv_index - 1;
- return true;
- case SHAPE_ROOT:
- case SHAPE_T_OBJECT:
- return false;
- case SHAPE_OBJ_TOO_COMPLEX:
- case SHAPE_FROZEN:
- rb_bug("Ivar should not exist on transition");
- }
+ return true;
}
-
- shape = rb_shape_get_parent(shape);
}
return false;
}
static bool
-shape_cache_get_iv_index(rb_shape_t *shape, ID id, attr_index_t *value)
+shape_find_ivar(rb_shape_t *shape, ID id, rb_shape_t **ivar_shape)
{
- if (shape->ancestor_index && shape->next_iv_index >= ANCESTOR_CACHE_THRESHOLD) {
- redblack_node_t *node = redblack_find(shape->ancestor_index, id);
- if (node) {
- rb_shape_t *shape = redblack_value(node);
- *value = shape->next_iv_index - 1;
-
-#if RUBY_DEBUG
- attr_index_t shape_tree_index;
- RUBY_ASSERT(shape_get_iv_index(shape, id, &shape_tree_index));
- RUBY_ASSERT(shape_tree_index == *value);
-#endif
-
+ while (shape->parent_id != INVALID_SHAPE_ID) {
+ if (shape->edge_name == id) {
+ RUBY_ASSERT(shape->type == SHAPE_IVAR);
+ *ivar_shape = shape;
return true;
}
- /* Verify the cache is correct by checking that this instance variable
- * does not exist in the shape tree either. */
- RUBY_ASSERT(!shape_get_iv_index(shape, id, value));
+ shape = RSHAPE(shape->parent_id);
}
return false;
}
bool
-rb_shape_get_iv_index(rb_shape_t *shape, ID id, attr_index_t *value)
+rb_shape_find_ivar(shape_id_t current_shape_id, ID id, shape_id_t *ivar_shape_id)
{
- // It doesn't make sense to ask for the index of an IV that's stored
- // on an object that is "too complex" as it uses a hash for storing IVs
- RUBY_ASSERT(rb_shape_id(shape) != OBJ_TOO_COMPLEX_SHAPE_ID);
+ RUBY_ASSERT(!rb_shape_too_complex_p(current_shape_id));
+
+ rb_shape_t *shape = RSHAPE(current_shape_id);
+ rb_shape_t *ivar_shape;
- if (!shape_cache_get_iv_index(shape, id, value)) {
+ if (!shape_cache_find_ivar(shape, id, &ivar_shape)) {
// If it wasn't in the ancestor cache, then don't do a linear search
- if (shape->ancestor_index && shape->next_iv_index >= ANCESTOR_CACHE_THRESHOLD) {
+ if (shape->ancestor_index && shape->next_field_index >= ANCESTOR_CACHE_THRESHOLD) {
return false;
}
else {
- return shape_get_iv_index(shape, id, value);
+ if (!shape_find_ivar(shape, id, &ivar_shape)) {
+ return false;
+ }
}
}
+ *ivar_shape_id = shape_id(ivar_shape, current_shape_id);
+
return true;
}
-void
-rb_shape_set_shape(VALUE obj, rb_shape_t* shape)
+bool
+rb_shape_get_iv_index(shape_id_t shape_id, ID id, attr_index_t *value)
{
- rb_shape_set_shape_id(obj, rb_shape_id(shape));
+ // It doesn't make sense to ask for the index of an IV that's stored
+ // on an object that is "too complex" as it uses a hash for storing IVs
+ RUBY_ASSERT(!rb_shape_too_complex_p(shape_id));
+
+ shape_id_t ivar_shape_id;
+ if (rb_shape_find_ivar(shape_id, id, &ivar_shape_id)) {
+ *value = RSHAPE_INDEX(ivar_shape_id);
+ return true;
+ }
+ return false;
}
int32_t
@@ -889,139 +1096,255 @@ rb_shape_id_offset(void)
return sizeof(uintptr_t) - SHAPE_ID_NUM_BITS / sizeof(uintptr_t);
}
-rb_shape_t *
-rb_shape_traverse_from_new_root(rb_shape_t *initial_shape, rb_shape_t *dest_shape)
+// Rebuild a similar shape with the same ivars but starting from
+// a different SHAPE_T_OBJECT, and don't cary over non-canonical transitions
+// such as SHAPE_OBJ_ID.
+static rb_shape_t *
+shape_rebuild(rb_shape_t *initial_shape, rb_shape_t *dest_shape)
{
- RUBY_ASSERT(initial_shape->type == SHAPE_T_OBJECT);
- rb_shape_t *next_shape = initial_shape;
+ rb_shape_t *midway_shape;
+
+ RUBY_ASSERT(initial_shape->type == SHAPE_ROOT);
if (dest_shape->type != initial_shape->type) {
- next_shape = rb_shape_traverse_from_new_root(initial_shape, rb_shape_get_parent(dest_shape));
- if (!next_shape) {
+ midway_shape = shape_rebuild(initial_shape, RSHAPE(dest_shape->parent_id));
+ if (UNLIKELY(!midway_shape)) {
return NULL;
}
}
+ else {
+ midway_shape = initial_shape;
+ }
switch ((enum shape_type)dest_shape->type) {
case SHAPE_IVAR:
- case SHAPE_FROZEN:
- if (!next_shape->edges) {
- return NULL;
- }
-
- VALUE lookup_result;
- if (SINGLE_CHILD_P(next_shape->edges)) {
- rb_shape_t * child = SINGLE_CHILD(next_shape->edges);
- if (child->edge_name == dest_shape->edge_name) {
- return child;
- }
- else {
- return NULL;
- }
- }
- else {
- if (rb_id_table_lookup(next_shape->edges, dest_shape->edge_name, &lookup_result)) {
- next_shape = (rb_shape_t *)lookup_result;
- }
- else {
- return NULL;
- }
- }
+ midway_shape = shape_get_next_iv_shape(midway_shape, dest_shape->edge_name);
break;
+ case SHAPE_OBJ_ID:
case SHAPE_ROOT:
- case SHAPE_T_OBJECT:
- break;
- case SHAPE_OBJ_TOO_COMPLEX:
- rb_bug("Unreachable");
break;
}
- return next_shape;
+ return midway_shape;
}
-rb_shape_t *
-rb_shape_rebuild_shape(rb_shape_t * initial_shape, rb_shape_t * dest_shape)
+// Rebuild `dest_shape_id` starting from `initial_shape_id`, and keep only SHAPE_IVAR transitions.
+// SHAPE_OBJ_ID and frozen status are lost.
+shape_id_t
+rb_shape_rebuild(shape_id_t initial_shape_id, shape_id_t dest_shape_id)
{
- RUBY_ASSERT(rb_shape_id(initial_shape) != OBJ_TOO_COMPLEX_SHAPE_ID);
- RUBY_ASSERT(rb_shape_id(dest_shape) != OBJ_TOO_COMPLEX_SHAPE_ID);
+ RUBY_ASSERT(!rb_shape_too_complex_p(initial_shape_id));
+ RUBY_ASSERT(!rb_shape_too_complex_p(dest_shape_id));
- rb_shape_t * midway_shape;
+ rb_shape_t *next_shape = shape_rebuild(RSHAPE(initial_shape_id), RSHAPE(dest_shape_id));
+ if (next_shape) {
+ return shape_id(next_shape, initial_shape_id);
+ }
+ else {
+ return transition_complex(initial_shape_id | (dest_shape_id & SHAPE_ID_FL_HAS_OBJECT_ID));
+ }
+}
- RUBY_ASSERT(initial_shape->type == SHAPE_T_OBJECT);
+void
+rb_shape_copy_fields(VALUE dest, VALUE *dest_buf, shape_id_t dest_shape_id, VALUE *src_buf, shape_id_t src_shape_id)
+{
+ rb_shape_t *dest_shape = RSHAPE(dest_shape_id);
+ rb_shape_t *src_shape = RSHAPE(src_shape_id);
- if (dest_shape->type != initial_shape->type) {
- midway_shape = rb_shape_rebuild_shape(initial_shape, rb_shape_get_parent(dest_shape));
- if (UNLIKELY(rb_shape_id(midway_shape) == OBJ_TOO_COMPLEX_SHAPE_ID)) {
- return midway_shape;
+ if (src_shape->next_field_index == dest_shape->next_field_index) {
+ // Happy path, we can just memcpy the ivptr content
+ MEMCPY(dest_buf, src_buf, VALUE, dest_shape->next_field_index);
+
+ // Fire write barriers
+ for (uint32_t i = 0; i < dest_shape->next_field_index; i++) {
+ RB_OBJ_WRITTEN(dest, Qundef, dest_buf[i]);
}
}
else {
- midway_shape = initial_shape;
- }
+ while (src_shape->parent_id != INVALID_SHAPE_ID) {
+ if (src_shape->type == SHAPE_IVAR) {
+ while (dest_shape->edge_name != src_shape->edge_name) {
+ if (UNLIKELY(dest_shape->parent_id == INVALID_SHAPE_ID)) {
+ rb_bug("Lost field %s", rb_id2name(src_shape->edge_name));
+ }
+ dest_shape = RSHAPE(dest_shape->parent_id);
+ }
- switch ((enum shape_type)dest_shape->type) {
- case SHAPE_IVAR:
- midway_shape = rb_shape_get_next_iv_shape(midway_shape, dest_shape->edge_name);
- break;
- case SHAPE_ROOT:
- case SHAPE_FROZEN:
- case SHAPE_T_OBJECT:
- break;
- case SHAPE_OBJ_TOO_COMPLEX:
- rb_bug("Unreachable");
- break;
+ RB_OBJ_WRITE(dest, &dest_buf[dest_shape->next_field_index - 1], src_buf[src_shape->next_field_index - 1]);
+ }
+ src_shape = RSHAPE(src_shape->parent_id);
+ }
}
-
- return midway_shape;
}
-RUBY_FUNC_EXPORTED bool
-rb_shape_obj_too_complex(VALUE obj)
+void
+rb_shape_copy_complex_ivars(VALUE dest, VALUE obj, shape_id_t src_shape_id, st_table *fields_table)
{
- return rb_shape_get_shape_id(obj) == OBJ_TOO_COMPLEX_SHAPE_ID;
+ // obj is TOO_COMPLEX so we can copy its iv_hash
+ st_table *table = st_copy(fields_table);
+ if (rb_shape_has_object_id(src_shape_id)) {
+ st_data_t id = (st_data_t)id_object_id;
+ st_delete(table, &id, NULL);
+ }
+ rb_obj_init_too_complex(dest, table);
+ rb_gc_writebarrier_remember(dest);
}
size_t
-rb_shape_edges_count(rb_shape_t *shape)
+rb_shape_edges_count(shape_id_t shape_id)
{
+ rb_shape_t *shape = RSHAPE(shape_id);
if (shape->edges) {
if (SINGLE_CHILD_P(shape->edges)) {
return 1;
}
else {
- return rb_id_table_size(shape->edges);
+ return rb_managed_id_table_size(shape->edges);
}
}
return 0;
}
size_t
-rb_shape_memsize(rb_shape_t *shape)
+rb_shape_memsize(shape_id_t shape_id)
{
+ rb_shape_t *shape = RSHAPE(shape_id);
+
size_t memsize = sizeof(rb_shape_t);
if (shape->edges && !SINGLE_CHILD_P(shape->edges)) {
- memsize += rb_id_table_memsize(shape->edges);
+ memsize += rb_managed_id_table_size(shape->edges);
}
return memsize;
}
+bool
+rb_shape_foreach_field(shape_id_t initial_shape_id, rb_shape_foreach_transition_callback func, void *data)
+{
+ RUBY_ASSERT(!rb_shape_too_complex_p(initial_shape_id));
+
+ rb_shape_t *shape = RSHAPE(initial_shape_id);
+ if (shape->type == SHAPE_ROOT) {
+ return true;
+ }
+
+ shape_id_t parent_id = shape_id(RSHAPE(shape->parent_id), initial_shape_id);
+ if (rb_shape_foreach_field(parent_id, func, data)) {
+ switch (func(shape_id(shape, initial_shape_id), data)) {
+ case ST_STOP:
+ return false;
+ case ST_CHECK:
+ case ST_CONTINUE:
+ break;
+ default:
+ rb_bug("unreachable");
+ }
+ }
+ return true;
+}
+
+#if RUBY_DEBUG
+bool
+rb_shape_verify_consistency(VALUE obj, shape_id_t shape_id)
+{
+ if (shape_id == ROOT_SHAPE_ID) {
+ return true;
+ }
+
+ if (shape_id == INVALID_SHAPE_ID) {
+ rb_bug("Can't set INVALID_SHAPE_ID on an object");
+ }
+
+ rb_shape_t *shape = RSHAPE(shape_id);
+
+ bool has_object_id = false;
+ while (shape->parent_id != INVALID_SHAPE_ID) {
+ if (shape->type == SHAPE_OBJ_ID) {
+ has_object_id = true;
+ break;
+ }
+ shape = RSHAPE(shape->parent_id);
+ }
+
+ if (rb_shape_has_object_id(shape_id)) {
+ if (!has_object_id) {
+ rb_p(obj);
+ rb_bug("shape_id claim having obj_id but doesn't shape_id=%u, obj=%s", shape_id, rb_obj_info(obj));
+ }
+ }
+ else {
+ if (has_object_id) {
+ rb_p(obj);
+ rb_bug("shape_id claim not having obj_id but it does shape_id=%u, obj=%s", shape_id, rb_obj_info(obj));
+ }
+ }
+
+ // Make sure SHAPE_ID_HAS_IVAR_MASK is valid.
+ if (rb_shape_too_complex_p(shape_id)) {
+ RUBY_ASSERT(shape_id & SHAPE_ID_HAS_IVAR_MASK);
+
+ // Ensure complex object don't appear as embedded
+ if (RB_TYPE_P(obj, T_OBJECT) || IMEMO_TYPE_P(obj, imemo_fields)) {
+ RUBY_ASSERT(FL_TEST_RAW(obj, ROBJECT_HEAP));
+ }
+ }
+ else {
+ attr_index_t ivar_count = RSHAPE_LEN(shape_id);
+ if (has_object_id) {
+ ivar_count--;
+ }
+ if (ivar_count) {
+ RUBY_ASSERT(shape_id & SHAPE_ID_HAS_IVAR_MASK);
+ }
+ else {
+ RUBY_ASSERT(!(shape_id & SHAPE_ID_HAS_IVAR_MASK));
+ }
+ }
+
+ uint8_t flags_heap_index = rb_shape_heap_index(shape_id);
+ if (RB_TYPE_P(obj, T_OBJECT)) {
+ RUBY_ASSERT(flags_heap_index > 0);
+ size_t shape_id_slot_size = rb_shape_tree.capacities[flags_heap_index - 1] * sizeof(VALUE) + sizeof(struct RBasic);
+ size_t actual_slot_size = rb_gc_obj_slot_size(obj);
+
+ if (shape_id_slot_size != actual_slot_size) {
+ rb_bug("shape_id heap_index flags mismatch: shape_id_slot_size=%zu, gc_slot_size=%zu\n", shape_id_slot_size, actual_slot_size);
+ }
+ }
+ else {
+ if (flags_heap_index) {
+ rb_bug("shape_id indicate heap_index > 0 but object is not T_OBJECT: %s", rb_obj_info(obj));
+ }
+ }
+
+ return true;
+}
+#endif
+
#if SHAPE_DEBUG
+
/*
- * Exposing Shape to Ruby via RubyVM.debug_shape
+ * Exposing Shape to Ruby via RubyVM::Shape.of(object)
*/
-/* :nodoc: */
static VALUE
-rb_shape_too_complex(VALUE self)
+shape_too_complex(VALUE self)
{
- rb_shape_t * shape;
- shape = rb_shape_get_shape_by_id(NUM2INT(rb_struct_getmember(self, rb_intern("id"))));
- if (rb_shape_id(shape) == OBJ_TOO_COMPLEX_SHAPE_ID) {
- return Qtrue;
- }
- else {
- return Qfalse;
- }
+ shape_id_t shape_id = NUM2INT(rb_struct_getmember(self, rb_intern("id")));
+ return RBOOL(rb_shape_too_complex_p(shape_id));
+}
+
+static VALUE
+shape_frozen(VALUE self)
+{
+ shape_id_t shape_id = NUM2INT(rb_struct_getmember(self, rb_intern("id")));
+ return RBOOL(shape_id & SHAPE_ID_FL_FROZEN);
+}
+
+static VALUE
+shape_has_object_id_p(VALUE self)
+{
+ shape_id_t shape_id = NUM2INT(rb_struct_getmember(self, rb_intern("id")));
+ return RBOOL(rb_shape_has_object_id(shape_id));
}
static VALUE
@@ -1033,21 +1356,23 @@ parse_key(ID key)
return LONG2NUM(key);
}
-static VALUE rb_shape_edge_name(rb_shape_t * shape);
+static VALUE rb_shape_edge_name(rb_shape_t *shape);
static VALUE
-rb_shape_t_to_rb_cShape(rb_shape_t *shape)
+shape_id_t_to_rb_cShape(shape_id_t shape_id)
{
VALUE rb_cShape = rb_const_get(rb_cRubyVM, rb_intern("Shape"));
+ rb_shape_t *shape = RSHAPE(shape_id);
VALUE obj = rb_struct_new(rb_cShape,
- INT2NUM(rb_shape_id(shape)),
+ INT2NUM(shape_id),
+ INT2NUM(shape_id & SHAPE_ID_OFFSET_MASK),
INT2NUM(shape->parent_id),
rb_shape_edge_name(shape),
- INT2NUM(shape->next_iv_index),
- INT2NUM(shape->size_pool_index),
+ INT2NUM(shape->next_field_index),
+ INT2NUM(rb_shape_heap_index(shape_id)),
INT2NUM(shape->type),
- INT2NUM(shape->capacity));
+ INT2NUM(RSHAPE_CAPACITY(shape_id)));
rb_obj_freeze(obj);
return obj;
}
@@ -1055,27 +1380,26 @@ rb_shape_t_to_rb_cShape(rb_shape_t *shape)
static enum rb_id_table_iterator_result
rb_edges_to_hash(ID key, VALUE value, void *ref)
{
- rb_hash_aset(*(VALUE *)ref, parse_key(key), rb_shape_t_to_rb_cShape((rb_shape_t*)value));
+ rb_hash_aset(*(VALUE *)ref, parse_key(key), shape_id_t_to_rb_cShape(raw_shape_id((rb_shape_t *)value)));
return ID_TABLE_CONTINUE;
}
-/* :nodoc: */
static VALUE
rb_shape_edges(VALUE self)
{
- rb_shape_t* shape;
-
- shape = rb_shape_get_shape_by_id(NUM2INT(rb_struct_getmember(self, rb_intern("id"))));
+ rb_shape_t *shape = RSHAPE(NUM2INT(rb_struct_getmember(self, rb_intern("id"))));
VALUE hash = rb_hash_new();
if (shape->edges) {
if (SINGLE_CHILD_P(shape->edges)) {
- rb_shape_t * child = SINGLE_CHILD(shape->edges);
+ rb_shape_t *child = SINGLE_CHILD(shape->edges);
rb_edges_to_hash(child->edge_name, (VALUE)child, &hash);
}
else {
- rb_id_table_foreach(shape->edges, rb_edges_to_hash, &hash);
+ VALUE edges = shape->edges;
+ rb_managed_id_table_foreach(edges, rb_edges_to_hash, &hash);
+ RB_GC_GUARD(edges);
}
}
@@ -1083,7 +1407,7 @@ rb_shape_edges(VALUE self)
}
static VALUE
-rb_shape_edge_name(rb_shape_t * shape)
+rb_shape_edge_name(rb_shape_t *shape)
{
if (shape->edge_name) {
if (is_instance_id(shape->edge_name)) {
@@ -1094,88 +1418,85 @@ rb_shape_edge_name(rb_shape_t * shape)
return Qnil;
}
-/* :nodoc: */
static VALUE
rb_shape_export_depth(VALUE self)
{
- rb_shape_t* shape;
- shape = rb_shape_get_shape_by_id(NUM2INT(rb_struct_getmember(self, rb_intern("id"))));
- return SIZET2NUM(rb_shape_depth(shape));
+ shape_id_t shape_id = NUM2INT(rb_struct_getmember(self, rb_intern("id")));
+ return SIZET2NUM(rb_shape_depth(shape_id));
}
-/* :nodoc: */
static VALUE
rb_shape_parent(VALUE self)
{
- rb_shape_t * shape;
- shape = rb_shape_get_shape_by_id(NUM2INT(rb_struct_getmember(self, rb_intern("id"))));
+ rb_shape_t *shape;
+ shape = RSHAPE(NUM2INT(rb_struct_getmember(self, rb_intern("id"))));
if (shape->parent_id != INVALID_SHAPE_ID) {
- return rb_shape_t_to_rb_cShape(rb_shape_get_parent(shape));
+ return shape_id_t_to_rb_cShape(shape->parent_id);
}
else {
return Qnil;
}
}
-/* :nodoc: */
static VALUE
rb_shape_debug_shape(VALUE self, VALUE obj)
{
- return rb_shape_t_to_rb_cShape(rb_shape_get_shape(obj));
+ if (RB_SPECIAL_CONST_P(obj)) {
+ rb_raise(rb_eArgError, "Can't get shape of special constant");
+ }
+ return shape_id_t_to_rb_cShape(rb_obj_shape_id(obj));
}
-/* :nodoc: */
static VALUE
rb_shape_root_shape(VALUE self)
{
- return rb_shape_t_to_rb_cShape(rb_shape_get_root_shape());
+ return shape_id_t_to_rb_cShape(ROOT_SHAPE_ID);
}
-/* :nodoc: */
static VALUE
rb_shape_shapes_available(VALUE self)
{
- return INT2NUM(MAX_SHAPE_ID - (GET_SHAPE_TREE()->next_shape_id - 1));
+ return INT2NUM(MAX_SHAPE_ID - (rb_shapes_count() - 1));
}
-/* :nodoc: */
static VALUE
rb_shape_exhaust(int argc, VALUE *argv, VALUE self)
{
rb_check_arity(argc, 0, 1);
int offset = argc == 1 ? NUM2INT(argv[0]) : 0;
- GET_SHAPE_TREE()->next_shape_id = MAX_SHAPE_ID - offset + 1;
+ RUBY_ATOMIC_SET(rb_shape_tree.next_shape_id, MAX_SHAPE_ID - offset + 1);
return Qnil;
}
-VALUE rb_obj_shape(rb_shape_t* shape);
+static VALUE shape_to_h(rb_shape_t *shape);
static enum rb_id_table_iterator_result collect_keys_and_values(ID key, VALUE value, void *ref)
{
- rb_hash_aset(*(VALUE *)ref, parse_key(key), rb_obj_shape((rb_shape_t*)value));
+ rb_hash_aset(*(VALUE *)ref, parse_key(key), shape_to_h((rb_shape_t *)value));
return ID_TABLE_CONTINUE;
}
-static VALUE edges(struct rb_id_table* edges)
+static VALUE edges(VALUE edges)
{
VALUE hash = rb_hash_new();
- if (SINGLE_CHILD_P(edges)) {
- rb_shape_t * child = SINGLE_CHILD(edges);
- collect_keys_and_values(child->edge_name, (VALUE)child, &hash);
- }
- else {
- rb_id_table_foreach(edges, collect_keys_and_values, &hash);
+ if (edges) {
+ if (SINGLE_CHILD_P(edges)) {
+ rb_shape_t *child = SINGLE_CHILD(edges);
+ collect_keys_and_values(child->edge_name, (VALUE)child, &hash);
+ }
+ else {
+ rb_managed_id_table_foreach(edges, collect_keys_and_values, &hash);
+ }
}
return hash;
}
-/* :nodoc: */
-VALUE
-rb_obj_shape(rb_shape_t* shape)
+static VALUE
+shape_to_h(rb_shape_t *shape)
{
VALUE rb_shape = rb_hash_new();
- rb_hash_aset(rb_shape, ID2SYM(rb_intern("id")), INT2NUM(rb_shape_id(shape)));
+ rb_hash_aset(rb_shape, ID2SYM(rb_intern("id")), INT2NUM(raw_shape_id(shape)));
rb_hash_aset(rb_shape, ID2SYM(rb_intern("edges")), edges(shape->edges));
if (shape == rb_shape_get_root_shape()) {
@@ -1189,22 +1510,20 @@ rb_obj_shape(rb_shape_t* shape)
return rb_shape;
}
-/* :nodoc: */
static VALUE
shape_transition_tree(VALUE self)
{
- return rb_obj_shape(rb_shape_get_root_shape());
+ return shape_to_h(rb_shape_get_root_shape());
}
-/* :nodoc: */
static VALUE
rb_shape_find_by_id(VALUE mod, VALUE id)
{
shape_id_t shape_id = NUM2UINT(id);
- if (shape_id >= GET_SHAPE_TREE()->next_shape_id) {
+ if (shape_id >= rb_shapes_count()) {
rb_raise(rb_eArgError, "Shape ID %d is out of bounds\n", shape_id);
}
- return rb_shape_t_to_rb_cShape(rb_shape_get_shape_by_id(shape_id));
+ return shape_id_t_to_rb_cShape(shape_id);
}
#endif
@@ -1215,86 +1534,98 @@ rb_shape_find_by_id(VALUE mod, VALUE id)
void
Init_default_shapes(void)
{
- rb_shape_tree_ptr = xcalloc(1, sizeof(rb_shape_tree_t));
+ size_t *heap_sizes = rb_gc_heap_sizes();
+ size_t heaps_count = 0;
+ while (heap_sizes[heaps_count]) {
+ heaps_count++;
+ }
+ attr_index_t *capacities = ALLOC_N(attr_index_t, heaps_count + 1);
+ capacities[heaps_count] = 0;
+ size_t index;
+ for (index = 0; index < heaps_count; index++) {
+ capacities[index] = (heap_sizes[index] - sizeof(struct RBasic)) / sizeof(VALUE);
+ }
+ rb_shape_tree.capacities = capacities;
#ifdef HAVE_MMAP
- rb_shape_tree_ptr->shape_list = (rb_shape_t *)mmap(NULL, rb_size_mul_or_raise(SHAPE_BUFFER_SIZE, sizeof(rb_shape_t), rb_eRuntimeError),
+ size_t shape_list_mmap_size = rb_size_mul_or_raise(SHAPE_BUFFER_SIZE, sizeof(rb_shape_t), rb_eRuntimeError);
+ rb_shape_tree.shape_list = (rb_shape_t *)mmap(NULL, shape_list_mmap_size,
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (GET_SHAPE_TREE()->shape_list == MAP_FAILED) {
- GET_SHAPE_TREE()->shape_list = 0;
+ if (rb_shape_tree.shape_list == MAP_FAILED) {
+ rb_shape_tree.shape_list = 0;
+ }
+ else {
+ ruby_annotate_mmap(rb_shape_tree.shape_list, shape_list_mmap_size, "Ruby:Init_default_shapes:shape_list");
}
#else
- GET_SHAPE_TREE()->shape_list = xcalloc(SHAPE_BUFFER_SIZE, sizeof(rb_shape_t));
+ rb_shape_tree.shape_list = xcalloc(SHAPE_BUFFER_SIZE, sizeof(rb_shape_t));
#endif
- if (!GET_SHAPE_TREE()->shape_list) {
+ if (!rb_shape_tree.shape_list) {
rb_memerror();
}
- id_frozen = rb_make_internal_id();
- id_t_object = rb_make_internal_id();
+ id_object_id = rb_make_internal_id();
#ifdef HAVE_MMAP
- rb_shape_tree_ptr->shape_cache = (redblack_node_t *)mmap(NULL, rb_size_mul_or_raise(REDBLACK_CACHE_SIZE, sizeof(redblack_node_t), rb_eRuntimeError),
+ size_t shape_cache_mmap_size = rb_size_mul_or_raise(REDBLACK_CACHE_SIZE, sizeof(redblack_node_t), rb_eRuntimeError);
+ rb_shape_tree.shape_cache = (redblack_node_t *)mmap(NULL, shape_cache_mmap_size,
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- rb_shape_tree_ptr->cache_size = 0;
+ rb_shape_tree.cache_size = 0;
// If mmap fails, then give up on the redblack tree cache.
// We set the cache size such that the redblack node allocators think
// the cache is full.
- if (GET_SHAPE_TREE()->shape_cache == MAP_FAILED) {
- GET_SHAPE_TREE()->shape_cache = 0;
- GET_SHAPE_TREE()->cache_size = REDBLACK_CACHE_SIZE;
+ if (rb_shape_tree.shape_cache == MAP_FAILED) {
+ rb_shape_tree.shape_cache = 0;
+ rb_shape_tree.cache_size = REDBLACK_CACHE_SIZE;
+ }
+ else {
+ ruby_annotate_mmap(rb_shape_tree.shape_cache, shape_cache_mmap_size, "Ruby:Init_default_shapes:shape_cache");
}
#endif
+ rb_gc_register_address(&shape_tree_obj);
+ shape_tree_obj = TypedData_Wrap_Struct(0, &shape_tree_type, (void *)1);
+
// Root shape
rb_shape_t *root = rb_shape_alloc_with_parent_id(0, INVALID_SHAPE_ID);
root->capacity = 0;
root->type = SHAPE_ROOT;
- root->size_pool_index = 0;
- GET_SHAPE_TREE()->root_shape = root;
- RUBY_ASSERT(rb_shape_id(GET_SHAPE_TREE()->root_shape) == ROOT_SHAPE_ID);
+ rb_shape_tree.root_shape = root;
+ RUBY_ASSERT(raw_shape_id(rb_shape_tree.root_shape) == ROOT_SHAPE_ID);
+ RUBY_ASSERT(!(raw_shape_id(rb_shape_tree.root_shape) & SHAPE_ID_HAS_IVAR_MASK));
+
+ bool dontcare;
+ rb_shape_t *root_with_obj_id = get_next_shape_internal(root, id_object_id, SHAPE_OBJ_ID, &dontcare, true);
+ RUBY_ASSERT(root_with_obj_id);
+ RUBY_ASSERT(raw_shape_id(root_with_obj_id) == ROOT_SHAPE_WITH_OBJ_ID);
+ RUBY_ASSERT(root_with_obj_id->type == SHAPE_OBJ_ID);
+ RUBY_ASSERT(root_with_obj_id->edge_name == id_object_id);
+ RUBY_ASSERT(root_with_obj_id->next_field_index == 1);
+ RUBY_ASSERT(!(raw_shape_id(root_with_obj_id) & SHAPE_ID_HAS_IVAR_MASK));
+ (void)root_with_obj_id;
+}
- bool dont_care;
- // Special const shape
-#if RUBY_DEBUG
- rb_shape_t *special_const_shape =
-#endif
- get_next_shape_internal(root, (ID)id_frozen, SHAPE_FROZEN, &dont_care, true);
- RUBY_ASSERT(rb_shape_id(special_const_shape) == SPECIAL_CONST_SHAPE_ID);
- RUBY_ASSERT(SPECIAL_CONST_SHAPE_ID == (GET_SHAPE_TREE()->next_shape_id - 1));
- RUBY_ASSERT(rb_shape_frozen_shape_p(special_const_shape));
-
- rb_shape_t *too_complex_shape = rb_shape_alloc_with_parent_id(0, ROOT_SHAPE_ID);
- too_complex_shape->type = SHAPE_OBJ_TOO_COMPLEX;
- too_complex_shape->size_pool_index = 0;
- RUBY_ASSERT(OBJ_TOO_COMPLEX_SHAPE_ID == (GET_SHAPE_TREE()->next_shape_id - 1));
- RUBY_ASSERT(rb_shape_id(too_complex_shape) == OBJ_TOO_COMPLEX_SHAPE_ID);
-
- // Make shapes for T_OBJECT
- size_t *sizes = rb_gc_size_pool_sizes();
- for (int i = 0; sizes[i] > 0; i++) {
- rb_shape_t *t_object_shape = rb_shape_alloc_with_parent_id(0, INVALID_SHAPE_ID);
- t_object_shape->type = SHAPE_T_OBJECT;
- t_object_shape->size_pool_index = i;
- t_object_shape->capacity = (uint32_t)((sizes[i] - offsetof(struct RObject, as.ary)) / sizeof(VALUE));
- t_object_shape->edges = rb_id_table_create(0);
- t_object_shape->ancestor_index = LEAF;
- RUBY_ASSERT(rb_shape_id(t_object_shape) == (shape_id_t)(i + FIRST_T_OBJECT_SHAPE_ID));
- }
+void
+rb_shape_free_all(void)
+{
+ xfree((void *)rb_shape_tree.capacities);
}
void
Init_shape(void)
{
#if SHAPE_DEBUG
+ /* Document-class: RubyVM::Shape
+ * :nodoc: */
VALUE rb_cShape = rb_struct_define_under(rb_cRubyVM, "Shape",
"id",
+ "raw_id",
"parent_id",
"edge_name",
- "next_iv_index",
- "size_pool_index",
+ "next_field_index",
+ "heap_index",
"type",
"capacity",
NULL);
@@ -1302,16 +1633,14 @@ Init_shape(void)
rb_define_method(rb_cShape, "parent", rb_shape_parent, 0);
rb_define_method(rb_cShape, "edges", rb_shape_edges, 0);
rb_define_method(rb_cShape, "depth", rb_shape_export_depth, 0);
- rb_define_method(rb_cShape, "too_complex?", rb_shape_too_complex, 0);
+ rb_define_method(rb_cShape, "too_complex?", shape_too_complex, 0);
+ rb_define_method(rb_cShape, "shape_frozen?", shape_frozen, 0);
+ rb_define_method(rb_cShape, "has_object_id?", shape_has_object_id_p, 0);
+
rb_define_const(rb_cShape, "SHAPE_ROOT", INT2NUM(SHAPE_ROOT));
rb_define_const(rb_cShape, "SHAPE_IVAR", INT2NUM(SHAPE_IVAR));
- rb_define_const(rb_cShape, "SHAPE_T_OBJECT", INT2NUM(SHAPE_T_OBJECT));
- rb_define_const(rb_cShape, "SHAPE_FROZEN", INT2NUM(SHAPE_FROZEN));
rb_define_const(rb_cShape, "SHAPE_ID_NUM_BITS", INT2NUM(SHAPE_ID_NUM_BITS));
rb_define_const(rb_cShape, "SHAPE_FLAG_SHIFT", INT2NUM(SHAPE_FLAG_SHIFT));
- rb_define_const(rb_cShape, "SPECIAL_CONST_SHAPE_ID", INT2NUM(SPECIAL_CONST_SHAPE_ID));
- rb_define_const(rb_cShape, "OBJ_TOO_COMPLEX_SHAPE_ID", INT2NUM(OBJ_TOO_COMPLEX_SHAPE_ID));
- rb_define_const(rb_cShape, "FIRST_T_OBJECT_SHAPE_ID", INT2NUM(FIRST_T_OBJECT_SHAPE_ID));
rb_define_const(rb_cShape, "SHAPE_MAX_VARIATIONS", INT2NUM(SHAPE_MAX_VARIATIONS));
rb_define_const(rb_cShape, "SIZEOF_RB_SHAPE_T", INT2NUM(sizeof(rb_shape_t)));
rb_define_const(rb_cShape, "SIZEOF_REDBLACK_NODE_T", INT2NUM(sizeof(redblack_node_t)));
diff --git a/shape.h b/shape.h
index 07eb2c979f..96c78f2bc1 100644
--- a/shape.h
+++ b/shape.h
@@ -2,61 +2,96 @@
#define RUBY_SHAPE_H
#include "internal/gc.h"
+#include "internal/struct.h"
-#if (SIZEOF_UINT64_T <= SIZEOF_VALUE)
-
-#define SIZEOF_SHAPE_T 4
-#define SHAPE_IN_BASIC_FLAGS 1
-typedef uint32_t attr_index_t;
+typedef uint16_t attr_index_t;
typedef uint32_t shape_id_t;
-# define SHAPE_ID_NUM_BITS 32
+#define SHAPE_ID_NUM_BITS 32
+#define SHAPE_ID_OFFSET_NUM_BITS 19
-#else
+STATIC_ASSERT(shape_id_num_bits, SHAPE_ID_NUM_BITS == sizeof(shape_id_t) * CHAR_BIT);
-#define SIZEOF_SHAPE_T 2
-#define SHAPE_IN_BASIC_FLAGS 0
-typedef uint16_t attr_index_t;
-typedef uint16_t shape_id_t;
-# define SHAPE_ID_NUM_BITS 16
+#define SHAPE_BUFFER_SIZE (1 << SHAPE_ID_OFFSET_NUM_BITS)
+#define SHAPE_ID_OFFSET_MASK (SHAPE_BUFFER_SIZE - 1)
-#endif
+#define SHAPE_ID_HEAP_INDEX_BITS 3
+#define SHAPE_ID_HEAP_INDEX_MAX ((1 << SHAPE_ID_HEAP_INDEX_BITS) - 1)
-typedef uint32_t redblack_id_t;
+#define SHAPE_ID_FL_USHIFT (SHAPE_ID_OFFSET_NUM_BITS + SHAPE_ID_HEAP_INDEX_BITS)
+#define SHAPE_ID_HEAP_INDEX_OFFSET SHAPE_ID_FL_USHIFT
+
+// shape_id_t bits:
+// 0-18 SHAPE_ID_OFFSET_MASK
+// index in rb_shape_tree.shape_list. Allow to access `rb_shape_t *`.
+// 19-21 SHAPE_ID_HEAP_INDEX_MASK
+// index in rb_shape_tree.capacities. Allow to access slot size.
+// Always 0 except for T_OBJECT.
+// 22 SHAPE_ID_FL_FROZEN
+// Whether the object is frozen or not.
+// 23 SHAPE_ID_FL_HAS_OBJECT_ID
+// Whether the object has an `SHAPE_OBJ_ID` transition.
+// 24 SHAPE_ID_FL_TOO_COMPLEX
+// The object is backed by a `st_table`.
-#define MAX_IVARS (attr_index_t)(-1)
+enum shape_id_fl_type {
+#define RBIMPL_SHAPE_ID_FL(n) (1<<(SHAPE_ID_FL_USHIFT+n))
-# define SHAPE_MASK (((uintptr_t)1 << SHAPE_ID_NUM_BITS) - 1)
-# define SHAPE_FLAG_MASK (((VALUE)-1) >> SHAPE_ID_NUM_BITS)
+ SHAPE_ID_HEAP_INDEX_MASK = RBIMPL_SHAPE_ID_FL(0) | RBIMPL_SHAPE_ID_FL(1) | RBIMPL_SHAPE_ID_FL(2),
-# define SHAPE_FLAG_SHIFT ((SIZEOF_VALUE * 8) - SHAPE_ID_NUM_BITS)
+ SHAPE_ID_FL_FROZEN = RBIMPL_SHAPE_ID_FL(3),
+ SHAPE_ID_FL_HAS_OBJECT_ID = RBIMPL_SHAPE_ID_FL(4),
+ SHAPE_ID_FL_TOO_COMPLEX = RBIMPL_SHAPE_ID_FL(5),
-# define SHAPE_MAX_VARIATIONS 8
+ SHAPE_ID_FL_NON_CANONICAL_MASK = SHAPE_ID_FL_FROZEN | SHAPE_ID_FL_HAS_OBJECT_ID,
+ SHAPE_ID_FLAGS_MASK = SHAPE_ID_HEAP_INDEX_MASK | SHAPE_ID_FL_NON_CANONICAL_MASK | SHAPE_ID_FL_TOO_COMPLEX,
-# define INVALID_SHAPE_ID SHAPE_MASK
-# define ROOT_SHAPE_ID 0x0
+#undef RBIMPL_SHAPE_ID_FL
+};
-# define SPECIAL_CONST_SHAPE_ID (ROOT_SHAPE_ID + 1)
-# define OBJ_TOO_COMPLEX_SHAPE_ID (SPECIAL_CONST_SHAPE_ID + 1)
-# define FIRST_T_OBJECT_SHAPE_ID (OBJ_TOO_COMPLEX_SHAPE_ID + 1)
+// This mask allows to check if a shape_id contains any ivar.
+// It relies on ROOT_SHAPE_WITH_OBJ_ID==1.
+enum shape_id_mask {
+ SHAPE_ID_HAS_IVAR_MASK = SHAPE_ID_FL_TOO_COMPLEX | (SHAPE_ID_OFFSET_MASK - 1),
+};
+
+// The interpreter doesn't care about frozen status or slot size when reading ivars.
+// So we normalize shape_id by clearing these bits to improve cache hits.
+// JITs however might care about it.
+#define SHAPE_ID_READ_ONLY_MASK (~(SHAPE_ID_FL_FROZEN | SHAPE_ID_HEAP_INDEX_MASK))
+
+typedef uint32_t redblack_id_t;
+
+#define SHAPE_MAX_FIELDS (attr_index_t)(-1)
+#define SHAPE_FLAG_SHIFT ((SIZEOF_VALUE * CHAR_BIT) - SHAPE_ID_NUM_BITS)
+#define SHAPE_FLAG_MASK (((VALUE)-1) >> SHAPE_ID_NUM_BITS)
+
+#define SHAPE_MAX_VARIATIONS 8
+
+#define INVALID_SHAPE_ID ((shape_id_t)-1)
+#define ATTR_INDEX_NOT_SET ((attr_index_t)-1)
+
+#define ROOT_SHAPE_ID 0x0
+#define ROOT_SHAPE_WITH_OBJ_ID 0x1
+#define ROOT_TOO_COMPLEX_SHAPE_ID (ROOT_SHAPE_ID | SHAPE_ID_FL_TOO_COMPLEX)
+#define ROOT_TOO_COMPLEX_WITH_OBJ_ID (ROOT_SHAPE_WITH_OBJ_ID | SHAPE_ID_FL_TOO_COMPLEX | SHAPE_ID_FL_HAS_OBJECT_ID)
typedef struct redblack_node redblack_node_t;
struct rb_shape {
- struct rb_id_table * edges; // id_table from ID (ivar) to next shape
+ VALUE edges; // id_table from ID (ivar) to next shape
ID edge_name; // ID (ivar) for transition from parent to rb_shape
- attr_index_t next_iv_index;
- uint32_t capacity; // Total capacity of the object with this shape
- uint8_t type;
- uint8_t size_pool_index;
+ redblack_node_t *ancestor_index;
shape_id_t parent_id;
- redblack_node_t * ancestor_index;
+ attr_index_t next_field_index; // Fields are either ivars or internal properties like `object_id`
+ attr_index_t capacity; // Total capacity of the object with this shape
+ uint8_t type;
};
typedef struct rb_shape rb_shape_t;
struct redblack_node {
ID key;
- rb_shape_t * value;
+ rb_shape_t *value;
redblack_id_t l;
redblack_id_t r;
};
@@ -64,170 +99,386 @@ struct redblack_node {
enum shape_type {
SHAPE_ROOT,
SHAPE_IVAR,
- SHAPE_FROZEN,
- SHAPE_T_OBJECT,
- SHAPE_OBJ_TOO_COMPLEX,
+ SHAPE_OBJ_ID,
+};
+
+enum shape_flags {
+ SHAPE_FL_FROZEN = 1 << 0,
+ SHAPE_FL_HAS_OBJECT_ID = 1 << 1,
+ SHAPE_FL_TOO_COMPLEX = 1 << 2,
+
+ SHAPE_FL_NON_CANONICAL_MASK = SHAPE_FL_FROZEN | SHAPE_FL_HAS_OBJECT_ID,
};
typedef struct {
/* object shapes */
rb_shape_t *shape_list;
rb_shape_t *root_shape;
- shape_id_t next_shape_id;
+ const attr_index_t *capacities;
+ rb_atomic_t next_shape_id;
redblack_node_t *shape_cache;
unsigned int cache_size;
} rb_shape_tree_t;
-RUBY_EXTERN rb_shape_tree_t *rb_shape_tree_ptr;
-static inline rb_shape_tree_t *
-rb_current_shape_tree(void)
+RUBY_SYMBOL_EXPORT_BEGIN
+RUBY_EXTERN rb_shape_tree_t rb_shape_tree;
+RUBY_SYMBOL_EXPORT_END
+
+static inline shape_id_t
+rb_shapes_count(void)
{
- return rb_shape_tree_ptr;
+ return (shape_id_t)RUBY_ATOMIC_LOAD(rb_shape_tree.next_shape_id);
}
-#define GET_SHAPE_TREE() rb_current_shape_tree()
+
+union rb_attr_index_cache {
+ uint64_t pack;
+ struct {
+ shape_id_t shape_id;
+ attr_index_t index;
+ } unpack;
+};
static inline shape_id_t
-get_shape_id_from_flags(VALUE obj)
+RBASIC_SHAPE_ID(VALUE obj)
{
RUBY_ASSERT(!RB_SPECIAL_CONST_P(obj));
- return (shape_id_t)(SHAPE_MASK & ((RBASIC(obj)->flags) >> SHAPE_FLAG_SHIFT));
+ RUBY_ASSERT(!RB_TYPE_P(obj, T_IMEMO) || IMEMO_TYPE_P(obj, imemo_fields));
+#if RBASIC_SHAPE_ID_FIELD
+ return (shape_id_t)((RBASIC(obj)->shape_id));
+#else
+ return (shape_id_t)((RBASIC(obj)->flags) >> SHAPE_FLAG_SHIFT);
+#endif
+}
+
+// Same as RBASIC_SHAPE_ID but with flags that have no impact
+// on reads removed. e.g. Remove FL_FROZEN.
+static inline shape_id_t
+RBASIC_SHAPE_ID_FOR_READ(VALUE obj)
+{
+ return RBASIC_SHAPE_ID(obj) & SHAPE_ID_READ_ONLY_MASK;
}
+#if RUBY_DEBUG
+bool rb_shape_verify_consistency(VALUE obj, shape_id_t shape_id);
+#endif
+
static inline void
-set_shape_id_in_flags(VALUE obj, shape_id_t shape_id)
+RBASIC_SET_SHAPE_ID_NO_CHECKS(VALUE obj, shape_id_t shape_id)
{
- // Ractors are occupying the upper 32 bits of flags, but only in debug mode
+#if RBASIC_SHAPE_ID_FIELD
+ RBASIC(obj)->shape_id = (VALUE)shape_id;
+#else
// Object shapes are occupying top bits
RBASIC(obj)->flags &= SHAPE_FLAG_MASK;
RBASIC(obj)->flags |= ((VALUE)(shape_id) << SHAPE_FLAG_SHIFT);
+#endif
}
-
-#if SHAPE_IN_BASIC_FLAGS
-static inline shape_id_t
-RBASIC_SHAPE_ID(VALUE obj)
+static inline void
+RBASIC_SET_SHAPE_ID(VALUE obj, shape_id_t shape_id)
{
- return get_shape_id_from_flags(obj);
+ RUBY_ASSERT(!RB_SPECIAL_CONST_P(obj));
+ RUBY_ASSERT(!RB_TYPE_P(obj, T_IMEMO) || IMEMO_TYPE_P(obj, imemo_fields));
+
+ RBASIC_SET_SHAPE_ID_NO_CHECKS(obj, shape_id);
+
+ RUBY_ASSERT(rb_shape_verify_consistency(obj, shape_id));
}
+void rb_set_boxed_class_shape_id(VALUE obj, shape_id_t shape_id);
+
static inline void
-RBASIC_SET_SHAPE_ID(VALUE obj, shape_id_t shape_id)
+RB_SET_SHAPE_ID(VALUE obj, shape_id_t shape_id)
{
- set_shape_id_in_flags(obj, shape_id);
+ switch (BUILTIN_TYPE(obj)) {
+ case T_CLASS:
+ case T_MODULE:
+ rb_set_boxed_class_shape_id(obj, shape_id);
+ break;
+ default:
+ RBASIC_SET_SHAPE_ID(obj, shape_id);
+ break;
+ }
}
-#endif
-static inline shape_id_t
-ROBJECT_SHAPE_ID(VALUE obj)
+static inline rb_shape_t *
+RSHAPE(shape_id_t shape_id)
{
- RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
- return get_shape_id_from_flags(obj);
+ uint32_t offset = (shape_id & SHAPE_ID_OFFSET_MASK);
+ RUBY_ASSERT(offset != INVALID_SHAPE_ID);
+
+ return &rb_shape_tree.shape_list[offset];
}
-static inline void
-ROBJECT_SET_SHAPE_ID(VALUE obj, shape_id_t shape_id)
+int32_t rb_shape_id_offset(void);
+
+RUBY_FUNC_EXPORTED shape_id_t rb_obj_shape_id(VALUE obj);
+shape_id_t rb_shape_get_next_iv_shape(shape_id_t shape_id, ID id);
+bool rb_shape_get_iv_index(shape_id_t shape_id, ID id, attr_index_t *value);
+bool rb_shape_get_iv_index_with_hint(shape_id_t shape_id, ID id, attr_index_t *value, shape_id_t *shape_id_hint);
+bool rb_shape_find_ivar(shape_id_t shape_id, ID id, shape_id_t *ivar_shape);
+
+typedef int rb_shape_foreach_transition_callback(shape_id_t shape_id, void *data);
+bool rb_shape_foreach_field(shape_id_t shape_id, rb_shape_foreach_transition_callback func, void *data);
+
+shape_id_t rb_shape_transition_frozen(VALUE obj);
+shape_id_t rb_shape_transition_complex(VALUE obj);
+shape_id_t rb_shape_transition_remove_ivar(VALUE obj, ID id, shape_id_t *removed_shape_id);
+shape_id_t rb_shape_transition_add_ivar(VALUE obj, ID id);
+shape_id_t rb_shape_transition_add_ivar_no_warnings(VALUE klass, shape_id_t original_shape_id, ID id);
+shape_id_t rb_shape_transition_object_id(VALUE obj);
+shape_id_t rb_shape_transition_heap(VALUE obj, size_t heap_index);
+shape_id_t rb_shape_object_id(shape_id_t original_shape_id);
+
+void rb_shape_free_all(void);
+
+shape_id_t rb_shape_rebuild(shape_id_t initial_shape_id, shape_id_t dest_shape_id);
+void rb_shape_copy_fields(VALUE dest, VALUE *dest_buf, shape_id_t dest_shape_id, VALUE *src_buf, shape_id_t src_shape_id);
+void rb_shape_copy_complex_ivars(VALUE dest, VALUE obj, shape_id_t src_shape_id, st_table *fields_table);
+
+static inline bool
+rb_shape_too_complex_p(shape_id_t shape_id)
{
- RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
- set_shape_id_in_flags(obj, shape_id);
+ return shape_id & SHAPE_ID_FL_TOO_COMPLEX;
+}
+
+static inline bool
+rb_shape_obj_too_complex_p(VALUE obj)
+{
+ return !RB_SPECIAL_CONST_P(obj) && rb_shape_too_complex_p(RBASIC_SHAPE_ID(obj));
+}
+
+static inline bool
+rb_shape_has_object_id(shape_id_t shape_id)
+{
+ return shape_id & SHAPE_ID_FL_HAS_OBJECT_ID;
+}
+
+static inline bool
+rb_shape_canonical_p(shape_id_t shape_id)
+{
+ return !(shape_id & SHAPE_ID_FL_NON_CANONICAL_MASK);
+}
+
+static inline uint8_t
+rb_shape_heap_index(shape_id_t shape_id)
+{
+ return (uint8_t)((shape_id & SHAPE_ID_HEAP_INDEX_MASK) >> SHAPE_ID_HEAP_INDEX_OFFSET);
}
static inline shape_id_t
-RCLASS_SHAPE_ID(VALUE obj)
+rb_shape_root(size_t heap_id)
{
- RUBY_ASSERT(RB_TYPE_P(obj, T_CLASS) || RB_TYPE_P(obj, T_MODULE));
- return get_shape_id_from_flags(obj);
+ shape_id_t heap_index = (shape_id_t)(heap_id + 1);
+ shape_id_t heap_flags = heap_index << SHAPE_ID_HEAP_INDEX_OFFSET;
+
+ RUBY_ASSERT((heap_flags & SHAPE_ID_HEAP_INDEX_MASK) == heap_flags);
+ RUBY_ASSERT(rb_shape_heap_index(heap_flags) == heap_index);
+
+ return ROOT_SHAPE_ID | heap_flags;
}
-static inline void
-RCLASS_SET_SHAPE_ID(VALUE obj, shape_id_t shape_id)
+static inline shape_id_t
+RSHAPE_PARENT_RAW_ID(shape_id_t shape_id)
{
- RUBY_ASSERT(RB_TYPE_P(obj, T_CLASS) || RB_TYPE_P(obj, T_MODULE));
- set_shape_id_in_flags(obj, shape_id);
+ return RSHAPE(shape_id)->parent_id;
}
-rb_shape_t * rb_shape_get_root_shape(void);
-int32_t rb_shape_id_offset(void);
+static inline bool
+RSHAPE_DIRECT_CHILD_P(shape_id_t parent_id, shape_id_t child_id)
+{
+ return (parent_id & SHAPE_ID_FLAGS_MASK) == (child_id & SHAPE_ID_FLAGS_MASK) &&
+ RSHAPE(child_id)->parent_id == (parent_id & SHAPE_ID_OFFSET_MASK);
+}
+
+static inline enum shape_type
+RSHAPE_TYPE(shape_id_t shape_id)
+{
+ return RSHAPE(shape_id)->type;
+}
+
+static inline bool
+RSHAPE_TYPE_P(shape_id_t shape_id, enum shape_type type)
+{
+ return RSHAPE_TYPE(shape_id) == type;
+}
-rb_shape_t * rb_shape_get_parent(rb_shape_t * shape);
+static inline attr_index_t
+RSHAPE_EMBEDDED_CAPACITY(shape_id_t shape_id)
+{
+ uint8_t heap_index = rb_shape_heap_index(shape_id);
+ if (heap_index) {
+ return rb_shape_tree.capacities[heap_index - 1];
+ }
+ return 0;
+}
-RUBY_FUNC_EXPORTED rb_shape_t *rb_shape_get_shape_by_id(shape_id_t shape_id);
-RUBY_FUNC_EXPORTED shape_id_t rb_shape_get_shape_id(VALUE obj);
-rb_shape_t * rb_shape_get_next_iv_shape(rb_shape_t * shape, ID id);
-bool rb_shape_get_iv_index(rb_shape_t * shape, ID id, attr_index_t * value);
-bool rb_shape_get_iv_index_with_hint(shape_id_t shape_id, ID id, attr_index_t * value, shape_id_t *shape_id_hint);
-RUBY_FUNC_EXPORTED bool rb_shape_obj_too_complex(VALUE obj);
+static inline attr_index_t
+RSHAPE_CAPACITY(shape_id_t shape_id)
+{
+ attr_index_t embedded_capacity = RSHAPE_EMBEDDED_CAPACITY(shape_id);
-void rb_shape_set_shape(VALUE obj, rb_shape_t* shape);
-rb_shape_t* rb_shape_get_shape(VALUE obj);
-int rb_shape_frozen_shape_p(rb_shape_t* shape);
-rb_shape_t* rb_shape_transition_shape_frozen(VALUE obj);
-bool rb_shape_transition_shape_remove_ivar(VALUE obj, ID id, rb_shape_t *shape, VALUE * removed);
-rb_shape_t* rb_shape_get_next(rb_shape_t* shape, VALUE obj, ID id);
+ if (embedded_capacity > RSHAPE(shape_id)->capacity) {
+ return embedded_capacity;
+ }
+ else {
+ return RSHAPE(shape_id)->capacity;
+ }
+}
+
+static inline attr_index_t
+RSHAPE_LEN(shape_id_t shape_id)
+{
+ return RSHAPE(shape_id)->next_field_index;
+}
-rb_shape_t * rb_shape_rebuild_shape(rb_shape_t * initial_shape, rb_shape_t * dest_shape);
+static inline attr_index_t
+RSHAPE_INDEX(shape_id_t shape_id)
+{
+ RUBY_ASSERT(RSHAPE_LEN(shape_id) > 0);
+ return RSHAPE_LEN(shape_id) - 1;
+}
+
+static inline ID
+RSHAPE_EDGE_NAME(shape_id_t shape_id)
+{
+ return RSHAPE(shape_id)->edge_name;
+}
static inline uint32_t
-ROBJECT_IV_CAPACITY(VALUE obj)
+ROBJECT_FIELDS_CAPACITY(VALUE obj)
{
RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
// Asking for capacity doesn't make sense when the object is using
// a hash table for storing instance variables
- RUBY_ASSERT(!rb_shape_obj_too_complex(obj));
- return rb_shape_get_shape_by_id(ROBJECT_SHAPE_ID(obj))->capacity;
+ RUBY_ASSERT(!rb_shape_obj_too_complex_p(obj));
+ return RSHAPE_CAPACITY(RBASIC_SHAPE_ID(obj));
}
static inline st_table *
-ROBJECT_IV_HASH(VALUE obj)
+ROBJECT_FIELDS_HASH(VALUE obj)
{
RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
- RUBY_ASSERT(rb_shape_obj_too_complex(obj));
- return (st_table *)ROBJECT(obj)->as.heap.ivptr;
+ RUBY_ASSERT(rb_shape_obj_too_complex_p(obj));
+ RUBY_ASSERT(FL_TEST_RAW(obj, ROBJECT_HEAP));
+
+ return (st_table *)ROBJECT(obj)->as.heap.fields;
}
static inline void
-ROBJECT_SET_IV_HASH(VALUE obj, const st_table *tbl)
+ROBJECT_SET_FIELDS_HASH(VALUE obj, const st_table *tbl)
{
RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
- RUBY_ASSERT(rb_shape_obj_too_complex(obj));
- ROBJECT(obj)->as.heap.ivptr = (VALUE *)tbl;
+ RUBY_ASSERT(rb_shape_obj_too_complex_p(obj));
+ RUBY_ASSERT(FL_TEST_RAW(obj, ROBJECT_HEAP));
+
+ ROBJECT(obj)->as.heap.fields = (VALUE *)tbl;
}
-size_t rb_id_table_size(const struct rb_id_table *tbl);
+static inline uint32_t
+ROBJECT_FIELDS_COUNT_COMPLEX(VALUE obj)
+{
+ return (uint32_t)rb_st_table_size(ROBJECT_FIELDS_HASH(obj));
+}
static inline uint32_t
-ROBJECT_IV_COUNT(VALUE obj)
+ROBJECT_FIELDS_COUNT_NOT_COMPLEX(VALUE obj)
{
- if (rb_shape_obj_too_complex(obj)) {
- return (uint32_t)rb_st_table_size(ROBJECT_IV_HASH(obj));
+ RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
+ RUBY_ASSERT(!rb_shape_obj_too_complex_p(obj));
+ return RSHAPE(RBASIC_SHAPE_ID(obj))->next_field_index;
+}
+
+static inline uint32_t
+ROBJECT_FIELDS_COUNT(VALUE obj)
+{
+ if (rb_shape_obj_too_complex_p(obj)) {
+ return ROBJECT_FIELDS_COUNT_COMPLEX(obj);
}
else {
- RBIMPL_ASSERT_TYPE(obj, RUBY_T_OBJECT);
- RUBY_ASSERT(!rb_shape_obj_too_complex(obj));
- return rb_shape_get_shape_by_id(ROBJECT_SHAPE_ID(obj))->next_iv_index;
+ return ROBJECT_FIELDS_COUNT_NOT_COMPLEX(obj);
}
}
static inline uint32_t
-RBASIC_IV_COUNT(VALUE obj)
+RBASIC_FIELDS_COUNT(VALUE obj)
+{
+ return RSHAPE(RBASIC_SHAPE_ID(obj))->next_field_index;
+}
+
+static inline bool
+rb_shape_obj_has_id(VALUE obj)
+{
+ return rb_shape_has_object_id(RBASIC_SHAPE_ID(obj));
+}
+
+static inline bool
+rb_shape_has_ivars(shape_id_t shape_id)
{
- return rb_shape_get_shape_by_id(rb_shape_get_shape_id(obj))->next_iv_index;
+ return shape_id & SHAPE_ID_HAS_IVAR_MASK;
}
-rb_shape_t *rb_shape_traverse_from_new_root(rb_shape_t *initial_shape, rb_shape_t *orig_shape);
+static inline bool
+rb_shape_obj_has_ivars(VALUE obj)
+{
+ return rb_shape_has_ivars(RBASIC_SHAPE_ID(obj));
+}
-bool rb_shape_set_shape_id(VALUE obj, shape_id_t shape_id);
+static inline bool
+rb_shape_has_fields(shape_id_t shape_id)
+{
+ return shape_id & (SHAPE_ID_OFFSET_MASK | SHAPE_ID_FL_TOO_COMPLEX);
+}
-VALUE rb_obj_debug_shape(VALUE self, VALUE obj);
+static inline bool
+rb_shape_obj_has_fields(VALUE obj)
+{
+ return rb_shape_has_fields(RBASIC_SHAPE_ID(obj));
+}
+
+static inline bool
+rb_obj_gen_fields_p(VALUE obj)
+{
+ switch (TYPE(obj)) {
+ case T_NONE:
+ case T_OBJECT:
+ case T_CLASS:
+ case T_MODULE:
+ case T_IMEMO:
+ return false;
+ default:
+ break;
+ }
+ return rb_shape_obj_has_fields(obj);
+}
+
+static inline bool
+rb_obj_using_gen_fields_table_p(VALUE obj)
+{
+ switch (BUILTIN_TYPE(obj)) {
+ case T_DATA:
+ if (RTYPEDDATA_P(obj)) return false;
+ break;
+
+ case T_STRUCT:
+ if (!FL_TEST_RAW(obj, RSTRUCT_GEN_FIELDS)) return false;
+ break;
+
+ default:
+ break;
+ }
+
+ return rb_obj_gen_fields_p(obj);
+}
// For ext/objspace
RUBY_SYMBOL_EXPORT_BEGIN
-typedef void each_shape_callback(rb_shape_t * shape, void *data);
-void rb_shape_each_shape(each_shape_callback callback, void *data);
-size_t rb_shape_memsize(rb_shape_t *shape);
-size_t rb_shape_edges_count(rb_shape_t *shape);
-size_t rb_shape_depth(rb_shape_t *shape);
-shape_id_t rb_shape_id(rb_shape_t * shape);
+typedef void each_shape_callback(shape_id_t shape_id, void *data);
+void rb_shape_each_shape_id(each_shape_callback callback, void *data);
+size_t rb_shape_memsize(shape_id_t shape);
+size_t rb_shape_edges_count(shape_id_t shape_id);
+size_t rb_shape_depth(shape_id_t shape_id);
RUBY_SYMBOL_EXPORT_END
#endif
diff --git a/signal.c b/signal.c
index 1c8f8c112b..5110ea4401 100644
--- a/signal.c
+++ b/signal.c
@@ -45,6 +45,7 @@
#include "ruby_atomic.h"
#include "vm_core.h"
#include "ractor_core.h"
+#include "ruby/internal/attr/nonstring.h"
#ifdef NEED_RUBY_ATOMIC_OPS
rb_atomic_t
@@ -402,7 +403,6 @@ interrupt_init(int argc, VALUE *argv, VALUE self)
return rb_call_super(2, args);
}
-void rb_malloc_info_show_results(void); /* gc.c */
#if defined(USE_SIGALTSTACK) || defined(_WIN32)
static void reset_sigmask(int sig);
#endif
@@ -413,7 +413,6 @@ ruby_default_signal(int sig)
#if USE_DEBUG_COUNTER
rb_debug_counter_show_results("killed by signal.");
#endif
- rb_malloc_info_show_results();
signal(sig, SIG_DFL);
#if defined(USE_SIGALTSTACK) || defined(_WIN32)
@@ -665,6 +664,10 @@ ruby_nativethread_signal(int signum, sighandler_t handler)
#endif
#endif
+#if !defined(POSIX_SIGNAL) && !defined(SIG_GET)
+static rb_nativethread_lock_t sig_check_lock;
+#endif
+
static int
signal_ignored(int sig)
{
@@ -674,9 +677,16 @@ signal_ignored(int sig)
(void)VALGRIND_MAKE_MEM_DEFINED(&old, sizeof(old));
if (sigaction(sig, NULL, &old) < 0) return FALSE;
func = old.sa_handler;
+#elif defined SIG_GET
+ // https://learn.microsoft.com/en-us/cpp/c-runtime-library/signal-action-constants
+ // SIG_GET: Returns the current value of the signal.
+ func = signal(sig, SIG_GET);
#else
- sighandler_t old = signal(sig, SIG_DFL);
+ sighandler_t old;
+ rb_native_mutex_lock(&sig_check_lock);
+ old = signal(sig, SIG_DFL);
signal(sig, old);
+ rb_native_mutex_unlock(&sig_check_lock);
func = old;
#endif
if (func == SIG_IGN) return 1;
@@ -708,7 +718,7 @@ sighandler(int sig)
int
rb_signal_buff_size(void)
{
- return signal_buff.size;
+ return RUBY_ATOMIC_LOAD(signal_buff.size);
}
static void
@@ -736,7 +746,7 @@ rb_get_next_signal(void)
{
int i, sig = 0;
- if (signal_buff.size != 0) {
+ if (rb_signal_buff_size() != 0) {
for (i=1; i<RUBY_NSIG; i++) {
if (signal_buff.cnt[i] > 0) {
ATOMIC_DEC(signal_buff.cnt[i]);
@@ -751,13 +761,15 @@ rb_get_next_signal(void)
#if defined SIGSEGV || defined SIGBUS || defined SIGILL || defined SIGFPE
static const char *received_signal;
-# define clear_received_signal() (void)(ruby_disable_gc = 0, received_signal = 0)
+# define clear_received_signal() do { \
+ if (GET_VM() != NULL) rb_gc_enable(); \
+ received_signal = 0; \
+} while (0)
#else
# define clear_received_signal() ((void)0)
#endif
#if defined(USE_SIGALTSTACK) || defined(_WIN32)
-NORETURN(void rb_ec_stack_overflow(rb_execution_context_t *ec, int crit));
# if defined __HAIKU__
# define USE_UCONTEXT_REG 1
# elif !(defined(HAVE_UCONTEXT_H) && (defined __i386__ || defined __x86_64__ || defined __amd64__))
@@ -803,7 +815,8 @@ check_stack_overflow(int sig, const uintptr_t addr, const ucontext_t *ctx)
const greg_t bp = mctx->gregs[REG_EBP];
# endif
# elif defined __APPLE__
-# if __DARWIN_UNIX03
+# include <AvailabilityMacros.h>
+# if defined(MAC_OS_X_VERSION_10_5) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
# define MCTX_SS_REG(reg) __ss.__##reg
# else
# define MCTX_SS_REG(reg) ss.reg
@@ -842,13 +855,17 @@ check_stack_overflow(int sig, const uintptr_t addr, const ucontext_t *ctx)
if (sp_page == fault_page || sp_page == fault_page + 1 ||
(sp_page <= fault_page && fault_page <= bp_page)) {
rb_execution_context_t *ec = GET_EC();
- int crit = FALSE;
+ ruby_stack_overflow_critical_level crit = rb_stack_overflow_signal;
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;
+ if (!ec->tag->prev || !--uplevel) {
+ crit = rb_stack_overflow_fatal;
+ break;
+ }
+ rb_vm_tag_jmpbuf_deinit(&ec->tag->buf);
ec->tag = ec->tag->prev;
}
reset_sigmask(sig);
@@ -860,10 +877,12 @@ static void
check_stack_overflow(int sig, const void *addr)
{
int ruby_stack_overflowed_p(const rb_thread_t *, const void *);
- rb_thread_t *th = GET_THREAD();
+ rb_execution_context_t *ec = rb_current_execution_context(false);
+ if (!ec) return;
+ rb_thread_t *th = rb_ec_thread_ptr(ec);
if (ruby_stack_overflowed_p(th, addr)) {
reset_sigmask(sig);
- rb_ec_stack_overflow(th->ec, FALSE);
+ rb_ec_stack_overflow(th->ec, 1);
}
}
# endif
@@ -930,6 +949,20 @@ sigsegv(int sig SIGINFO_ARG)
}
#endif
+#ifdef SIGABRT
+
+static sighandler_t default_sigabrt_handler;
+NORETURN(static ruby_sigaction_t sigabrt);
+
+static void
+sigabrt(int sig SIGINFO_ARG)
+{
+ check_reserved_signal("ABRT");
+ CHECK_STACK_OVERFLOW();
+ rb_bug_for_fatal_signal(default_sigabrt_handler, sig, SIGINFO_CTX, "Aborted" MESSAGE_FAULT_ADDRESS);
+}
+#endif
+
#ifdef SIGILL
static sighandler_t default_sigill_handler;
@@ -971,7 +1004,7 @@ check_reserved_signal_(const char *name, size_t name_len, int signo)
if (prev) {
ssize_t RB_UNUSED_VAR(err);
static const int stderr_fd = 2;
-#define NOZ(name, str) name[sizeof(str)-1] = str
+#define NOZ(name, str) RBIMPL_ATTR_NONSTRING() name[sizeof(str)-1] = str
static const char NOZ(msg1, " received in ");
static const char NOZ(msg2, " handler\n");
@@ -1000,7 +1033,9 @@ check_reserved_signal_(const char *name, size_t name_len, int signo)
ruby_abort();
}
- ruby_disable_gc = 1;
+ if (GET_VM() != NULL) {
+ rb_gc_disable_no_rest();
+ }
}
#endif
@@ -1031,7 +1066,7 @@ signal_exec(VALUE cmd, int sig)
EC_PUSH_TAG(ec);
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
VALUE signum = INT2NUM(sig);
- rb_eval_cmd_kw(cmd, rb_ary_new3(1, signum), RB_NO_KEYWORDS);
+ rb_eval_cmd_call_kw(cmd, 1, &signum, RB_NO_KEYWORDS);
}
EC_POP_TAG();
ec = GET_EC();
@@ -1217,11 +1252,6 @@ trap_handler(VALUE *cmd, int sig)
break;
}
}
- else {
- rb_proc_t *proc;
- GetProcPtr(*cmd, proc);
- (void)proc;
- }
}
return func;
@@ -1316,31 +1346,36 @@ reserved_signal_p(int signo)
/*
* call-seq:
- * Signal.trap( signal, command ) -> obj
- * Signal.trap( signal ) {| | block } -> obj
+ * Signal.trap(signal, command) -> obj
+ * Signal.trap(signal) { ... } -> obj
*
- * Specifies the handling of signals. The first parameter is a signal
- * name (a string such as ``SIGALRM'', ``SIGUSR1'', and so on) or a
- * signal number. The characters ``SIG'' may be omitted from the
- * signal name. The command or block specifies code to be run when the
+ * Specifies the handling of signals. Returns the previous handler for
+ * the given signal.
+ *
+ * Argument +signal+ is a signal name (a string or symbol such
+ * as +SIGALRM+ or +SIGUSR1+) or an integer signal number. When +signal+
+ * is a string or symbol, the leading characters +SIG+ may be omitted.
+ *
+ * Argument +command+ or block provided specifies code to be run when the
* signal is raised.
- * If the command is the string ``IGNORE'' or ``SIG_IGN'', the signal
- * will be ignored.
- * If the command is ``DEFAULT'' or ``SIG_DFL'', the Ruby's default handler
- * will be invoked.
- * If the command is ``EXIT'', the script will be terminated by the signal.
- * If the command is ``SYSTEM_DEFAULT'', the operating system's default
- * handler will be invoked.
- * Otherwise, the given command or block will be run.
- * The special signal name ``EXIT'' or signal number zero will be
- * invoked just prior to program termination.
- * trap returns the previous handler for the given signal.
+ *
+ * Argument +command+ may also be a string or symbol with the following special
+ * values:
+ *
+ * - +IGNORE+, +SIG_IGN+: the signal will be ignored.
+ * - +DEFAULT+, +SIG_DFL+: Ruby's default handler will be invoked.
+ * - +EXIT+: the process will be terminated by the signal.
+ * - +SYSTEM_DEFAULT+: the operating system's default handler will be invoked.
+ *
+ * The special signal name +EXIT+ or signal number zero will be
+ * invoked just prior to program termination:
*
* Signal.trap(0, proc { puts "Terminating: #{$$}" })
* Signal.trap("CLD") { puts "Child died" }
* fork && Process.wait
*
- * <em>produces:</em>
+ * Outputs:
+ *
* Terminating: 27461
* Child died
* Terminating: 27460
@@ -1496,6 +1531,9 @@ Init_signal(void)
rb_define_method(rb_eSignal, "signo", esignal_signo, 0);
rb_alias(rb_eSignal, rb_intern_const("signm"), rb_intern_const("message"));
rb_define_method(rb_eInterrupt, "initialize", interrupt_init, -1);
+#if !defined(POSIX_SIGNAL) && !defined(SIG_GET)
+ rb_native_mutex_initialize(&sig_check_lock);
+#endif
// It should be ready to call rb_signal_exec()
VM_ASSERT(GET_THREAD()->pending_interrupt_queue);
@@ -1534,6 +1572,10 @@ Init_signal(void)
RB_ALTSTACK_INIT(GET_VM()->main_altstack, rb_allocate_sigaltstack());
force_install_sighandler(SIGSEGV, (sighandler_t)sigsegv, &default_sigsegv_handler);
#endif
+
+#ifdef SIGABRT
+ force_install_sighandler(SIGABRT, (sighandler_t)sigabrt, &default_sigabrt_handler);
+#endif
}
#ifdef SIGPIPE
install_sighandler(SIGPIPE, sig_do_nothing);
@@ -1548,3 +1590,11 @@ Init_signal(void)
rb_enable_interrupt();
}
+
+void
+rb_signal_atfork(void)
+{
+#if defined(HAVE_WORKING_FORK) && !defined(POSIX_SIGNAL) && !defined(SIG_GET)
+ rb_native_mutex_initialize(&sig_check_lock);
+#endif
+}
diff --git a/siphash.c b/siphash.c
index 61b8604fc9..62de622778 100644
--- a/siphash.c
+++ b/siphash.c
@@ -140,6 +140,9 @@ xor64_to(uint64_t *v, const uint64_t s)
#endif
static const union {
+#if defined(__has_attribute) && __has_attribute(nonstring)
+ __attribute__((nonstring))
+#endif
char bin[32];
uint64_t u64[4];
} sip_init_state_bin = {"uespemos""modnarod""arenegyl""setybdet"};
diff --git a/spec/bin/bundle b/spec/bin/bundle
new file mode 100755
index 0000000000..8f8b535295
--- /dev/null
+++ b/spec/bin/bundle
@@ -0,0 +1,6 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+require_relative "../bundler/support/activate"
+
+load File.expand_path("bundle", Spec::Path.exedir)
diff --git a/spec/bin/parallel_rspec b/spec/bin/parallel_rspec
new file mode 100755
index 0000000000..412defa58b
--- /dev/null
+++ b/spec/bin/parallel_rspec
@@ -0,0 +1,7 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+require_relative "../bundler/support/setup"
+
+require "turbo_tests"
+TurboTests::CLI.new(ARGV).run
diff --git a/spec/bin/rspec b/spec/bin/rspec
new file mode 100755
index 0000000000..1f61e3c64c
--- /dev/null
+++ b/spec/bin/rspec
@@ -0,0 +1,6 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+require_relative "../bundler/support/rubygems_ext"
+
+Spec::Rubygems.gem_load("rspec-core", "rspec")
diff --git a/spec/bundled_gems.mspec b/spec/bundled_gems.mspec
index 762fa1c165..f7edb34c75 100644
--- a/spec/bundled_gems.mspec
+++ b/spec/bundled_gems.mspec
@@ -1,6 +1,14 @@
load File.dirname(__FILE__) + '/default.mspec'
class MSpecScript
- set :library, get(:stdlibs).to_a & get(:bundled_gems).to_a
+ test_bundled_gems = get(:stdlibs).to_a & get(:bundled_gems).to_a
+ unless ENV["BUNDLED_GEMS"].nil? || ENV["BUNDLED_GEMS"].empty?
+ test_bundled_gems = ENV["BUNDLED_GEMS"].split(",").map do |gem|
+ gem = "openstruct" if gem == "ostruct"
+ test_bundled_gems.find{|test_gem| test_gem.include?(gem) }
+ end.compact
+ exit if test_bundled_gems.empty?
+ end
+ set :library, test_bundled_gems
set :files, get(:library)
end
diff --git a/spec/bundled_gems_spec.rb b/spec/bundled_gems_spec.rb
new file mode 100644
index 0000000000..d985ddad41
--- /dev/null
+++ b/spec/bundled_gems_spec.rb
@@ -0,0 +1,427 @@
+require "bundled_gems"
+
+require "bundler"
+require "fileutils"
+
+require_relative "bundler/support/builders"
+require_relative "bundler/support/helpers"
+require_relative "bundler/support/path"
+
+module Gem
+ def self.ruby=(ruby)
+ @ruby = ruby
+ end
+end
+
+RSpec.configure do |config|
+ config.include Spec::Builders
+ config.include Spec::Helpers
+ config.include Spec::Path
+
+ config.before(:suite) do
+ Gem.ruby = ENV["RUBY"] if ENV["RUBY"]
+
+ require_relative "bundler/support/rubygems_ext"
+ Spec::Rubygems.test_setup
+ Spec::Helpers.install_dev_bundler
+ FileUtils.mkdir_p Spec::Path.gem_path
+ end
+
+ config.around(:each) do |example|
+ FileUtils.cp_r Spec::Path.pristine_system_gem_path, Spec::Path.system_gem_path
+ FileUtils.mkdir_p Spec::Path.base_system_gem_path.join("gems")
+ %w[sinatra rack tilt rack-protection rack-session rack-test mustermann base64 logger compact_index].each do |gem|
+ path, = Dir[File.expand_path("../.bundle/gems/#{gem}-*", __dir__)]
+ FileUtils.cp_r path, Spec::Path.base_system_gem_path.join("gems")
+ end
+
+ 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
+
+ config.after :suite do
+ FileUtils.rm_rf Spec::Path.pristine_system_gem_path
+ end
+end
+
+RSpec.describe "bundled_gems.rb" do
+ let(:stub_code) {
+ <<~STUB
+ Gem::BUNDLED_GEMS.send(:remove_const, :LIBDIR)
+ Gem::BUNDLED_GEMS.send(:remove_const, :ARCHDIR)
+ Gem::BUNDLED_GEMS.send(:remove_const, :SINCE)
+ Gem::BUNDLED_GEMS.const_set(:LIBDIR, File.expand_path(File.join(__dir__, "../../..", "lib")) + "/")
+ Gem::BUNDLED_GEMS.const_set(:ARCHDIR, File.expand_path($LOAD_PATH.find{|path| path.include?(".ext/common") }) + "/")
+ Gem::BUNDLED_GEMS.const_set(:SINCE, { "openssl" => RUBY_VERSION, "fileutils" => RUBY_VERSION, "csv" => "3.4.0", "net-smtp" => "3.1.0" })
+ STUB
+ }
+
+ def script(code, options = {})
+ options[:artifice] ||= "compact_index"
+ code = <<~RUBY
+ #{stub_code}
+ require 'bundler/inline'
+
+ #{code}
+ RUBY
+ ruby(code, options)
+ end
+
+ it "Show warning require and LoadError" do
+ script <<-RUBY
+ gemfile do
+ source "https://rubygems.org"
+ end
+
+ begin
+ require "csv"
+ rescue LoadError
+ end
+ require "openssl"
+ RUBY
+
+ expect(err).to include(/csv used to be loaded from (.*) since Ruby 3.4.0/)
+ expect(err).to include(/-e:15/)
+ expect(err).to include(/openssl used to be loaded from (.*) since Ruby #{RUBY_VERSION}/)
+ expect(err).to include(/-e:18/)
+ end
+
+ it "Show warning when bundled gems called as dependency" do
+ build_lib "activesupport", "7.0.7.2" do |s|
+ s.write "lib/active_support/all.rb", "require 'openssl'"
+ end
+
+ script <<-RUBY, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
+ gemfile do
+ source "https://gem.repo1"
+ path "#{lib_path}" do
+ gem "activesupport", "7.0.7.2"
+ end
+ end
+
+ require "active_support/all"
+ RUBY
+
+ expect(err).to include(/openssl used to be loaded from (.*) since Ruby #{RUBY_VERSION}/)
+ expect(err).to include(/lib\/active_support\/all\.rb:1/)
+ end
+
+ it "Show warning dash gem like net/smtp" do
+ script <<-RUBY
+ gemfile do
+ source "https://rubygems.org"
+ end
+
+ begin
+ require "net/smtp"
+ rescue LoadError
+ end
+ RUBY
+
+ expect(err).to include(/net\/smtp used to be loaded from (.*) since Ruby 3.1.0/)
+ expect(err).to include(/-e:15/)
+ expect(err).to include("You can add net-smtp")
+ end
+
+ it "Show warning sub-feature like openssl/bn" do
+ skip "This test is not working on Windows" if Gem.win_platform?
+
+ script <<-RUBY
+ gemfile do
+ source "https://rubygems.org"
+ end
+
+ require "openssl/bn"
+ RUBY
+
+ expect(err).to include(/openssl\/bn is found in openssl, (.*) part of the default gems since Ruby #{RUBY_VERSION}/)
+ expect(err).to include(/-e:14/)
+ end
+
+ it "Show warning when bundle exec with ruby and script" do
+ code = <<-RUBY
+ #{stub_code}
+ require "openssl"
+ RUBY
+ create_file("script.rb", code)
+ create_file("Gemfile", "source 'https://rubygems.org'")
+
+ bundle "exec ruby script.rb"
+
+ expect(err).to include(/openssl used to be loaded from (.*) since Ruby #{RUBY_VERSION}/)
+ expect(err).to include(/script\.rb:8/)
+ end
+
+ it "Show warning when bundle exec with shebang's script" do
+ skip "This test is not working on Windows" if Gem.win_platform?
+
+ code = <<-RUBY
+ #!/usr/bin/env ruby
+ #{stub_code}
+ require "openssl"
+ RUBY
+ create_file("script.rb", code)
+ FileUtils.chmod(0o777, bundled_app("script.rb"))
+ create_file("Gemfile", "source 'https://rubygems.org'")
+
+ bundle "exec ./script.rb"
+
+ expect(err).to include(/openssl used to be loaded from (.*) since Ruby #{RUBY_VERSION}/)
+ expect(err).to include(/script\.rb:9/)
+ end
+
+ it "Show warning when bundle exec with -r option" do
+ create_file("stub.rb", stub_code)
+ create_file("Gemfile", "source 'https://rubygems.org'")
+ bundle "exec ruby -r./stub -ropenssl -e ''"
+
+ expect(err).to include(/openssl used to be loaded from (.*) since Ruby #{RUBY_VERSION}/)
+ end
+
+ it "Show warning when warn is not the standard one in the current scope" do
+ script <<-RUBY
+ module My
+ def warn(msg)
+ end
+
+ def my
+ gemfile do
+ source "https://rubygems.org"
+ end
+
+ require "openssl"
+ end
+
+ extend self
+ end
+
+ My.my
+ RUBY
+
+ expect(err).to include(/openssl used to be loaded from (.*) since Ruby #{RUBY_VERSION}/)
+ expect(err).to include(/-e:19/)
+ end
+
+ it "Don't show warning when bundled gems called as dependency" do
+ build_lib "activesupport", "7.0.7.2" do |s|
+ s.write "lib/active_support/all.rb", "require 'openssl'"
+ end
+ build_lib "openssl", "1.0.0" do |s|
+ s.write "lib/openssl.rb", "puts 'openssl'"
+ end
+
+ script <<-RUBY, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
+ gemfile do
+ source "https://gem.repo1"
+ path "#{lib_path}" do
+ gem "activesupport", "7.0.7.2"
+ gem "openssl"
+ end
+ end
+
+ require "active_support/all"
+ RUBY
+
+ expect(err).to be_empty
+ end
+
+ it "Show warning with bootsnap cases" do
+ script <<-RUBY
+ gemfile do
+ source "https://rubygems.org"
+ # gem "bootsnap", require: false
+ end
+
+ # require 'bootsnap'
+ # Bootsnap.setup(cache_dir: 'tmp/cache')
+
+ # bootsnap expand required feature to full path
+ # require 'openssl'
+ require Gem::BUNDLED_GEMS::ARCHDIR + 'openssl'
+ RUBY
+
+ expect(err).to include(/openssl used to be loaded from (.*) since Ruby #{RUBY_VERSION}/)
+ # TODO: We should assert caller location like below:
+ # test_warn_bootsnap.rb:14: warning: ...
+ end
+
+ it "Show warning with bootsnap for gem with native extension" do
+ script <<-RUBY
+ gemfile do
+ source "https://rubygems.org"
+ # gem "bootsnap", require: false
+ end
+
+ # require 'bootsnap'
+ # Bootsnap.setup(cache_dir: 'tmp/cache')
+
+ # bootsnap expand required feature to full path
+ # require 'openssl'
+ require Gem::BUNDLED_GEMS::ARCHDIR + "openssl"
+ RUBY
+
+ expect(err).to include(/openssl used to be loaded from (.*) since Ruby #{RUBY_VERSION}/)
+ # TODO: We should assert caller location like below:
+ # test_warn_bootsnap_rubyarchdir_gem.rb:14: warning: ...
+ end
+
+ it "Show warning with bootsnap and some gem in Gemfile" do
+ # Original issue is childprocess 5.0.0 and logger.
+ build_lib "fileutils2", "5.0.0" do |s|
+ # bootsnap expand required feature to full path
+ rubylibpath = File.expand_path(File.join(__dir__, "..", "lib"))
+ s.write "lib/fileutils2.rb", "require '#{rubylibpath}/fileutils'"
+ end
+
+ script <<-RUBY
+ gemfile do
+ source "https://rubygems.org"
+ # gem "bootsnap", require: false
+ path "#{lib_path}" do
+ gem "fileutils2", "5.0.0"
+ end
+ end
+
+ # require 'bootsnap'
+ # Bootsnap.setup(cache_dir: 'tmp/cache')
+
+ # bootsnap expand required feature to full path
+ require Gem.loaded_specs["fileutils2"].full_gem_path + '/lib/fileutils2'
+ RUBY
+
+ expect(err).to include(/fileutils used to be loaded from (.*) since Ruby #{RUBY_VERSION}/)
+ # TODO: We should assert caller location like below:
+ # $GEM_HOME/gems/childprocess-5.0.0/lib/childprocess.rb:7: warning:
+ end
+
+ it "Show warning with zeitwerk" do
+ libpath = Dir[File.expand_path("../.bundle/gems/{zeitwerk}-*/lib", __dir__)].map(&:to_s).first
+ code = <<-RUBY
+ #{stub_code}
+ $LOAD_PATH.unshift("#{libpath}")
+ require "zeitwerk"
+ loader = Zeitwerk::Loader.for_gem(warn_on_extra_files: false)
+ loader.setup
+
+ require 'openssl'
+ RUBY
+ create_file("script.rb", code)
+ create_file("Gemfile", "source 'https://rubygems.org'")
+ bundle "exec ruby script.rb"
+
+ expect(err).to include(/openssl used to be loaded from (.*) since Ruby #{RUBY_VERSION}/)
+ expect(err).to include(/script\.rb:13/)
+ end
+
+ it "Don't show warning openssl/bn when openssl on Gemfile" do
+ build_lib "openssl", "1.0.0" do |s|
+ s.write "lib/openssl.rb", "puts 'openssl'"
+ s.write "lib/openssl/bn.rb", "puts 'openssl/bn'"
+ end
+
+ script <<-RUBY, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
+ gemfile do
+ source "https://gem.repo1"
+ path "#{lib_path}" do
+ gem "openssl"
+ end
+ end
+
+ require "openssl/bn"
+ RUBY
+
+ expect(err).to be_empty
+ end
+
+ it "Don't show warning with net/smtp when net-smtp on Gemfile" do
+ build_lib "net-smtp", "1.0.0" do |s|
+ s.write "lib/net/smtp.rb", "puts 'net-smtp'"
+ end
+
+ script <<-RUBY, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
+ gemfile do
+ source "https://gem.repo1"
+ path "#{lib_path}" do
+ gem "net-smtp"
+ end
+ end
+
+ require "net/smtp"
+ RUBY
+
+ expect(err).to be_empty
+ end
+
+ describe ".force_activate" do
+ before do
+ allow_any_instance_of(Bundler::Runtime).to receive(:setup).and_raise(Bundler::GemNotFound)
+ end
+
+ context "with bundle environment" do
+ before do
+ code = <<-RUBY
+ #!/usr/bin/env ruby
+
+ Gem::BUNDLED_GEMS.force_activate("csv")
+ RUBY
+ create_file("script.rb", code)
+ create_file("Gemfile", "source 'https://rubygems.org'")
+ end
+
+ it "lockfile is available" do
+ bundle "install"
+ bundle "exec ./script.rb"
+
+ expect(err).to include("gem install csv")
+ end
+
+ it "lockfile is not available" do
+ bundle "exec ./script.rb"
+
+ expect(err).to include("gem install csv")
+ end
+ end
+
+ context "with bundler/inline" do
+ it "foo is available on LOAD_PATH" do
+ build_lib "foo", "1.0.0" do |s|
+ s.write "lib/foo.rb", "puts :foo"
+ end
+
+ script <<-RUBY, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
+ #!/usr/bin/env ruby
+ gemfile do
+ source "https://gem.repo1"
+ path "#{lib_path}" do
+ gem "foo", "1.0.0"
+ end
+ end
+
+ Gem::BUNDLED_GEMS.force_activate("csv")
+ puts $LOAD_PATH
+ RUBY
+
+ expect(err).to include("gem install csv")
+ expect(out).to include("foo-1.0.0/lib")
+ end
+ end
+
+ context "without bundle environment" do
+ it "warns about installation requirement" do
+ expect_any_instance_of(Object).to receive(:warn)
+ Gem::BUNDLED_GEMS.force_activate("csv")
+ end
+ end
+ end
+end
diff --git a/spec/bundler/bundler/build_metadata_spec.rb b/spec/bundler/bundler/build_metadata_spec.rb
index afa2d1716f..2e69821f68 100644
--- a/spec/bundler/bundler/build_metadata_spec.rb
+++ b/spec/bundler/bundler/build_metadata_spec.rb
@@ -6,18 +6,20 @@ require "bundler/build_metadata"
RSpec.describe Bundler::BuildMetadata do
before do
allow(Time).to receive(:now).and_return(Time.at(0))
- Bundler::BuildMetadata.instance_variable_set(:@built_at, nil)
+ Bundler::BuildMetadata.instance_variable_set(:@timestamp, nil)
end
- describe "#built_at" do
- it "returns %Y-%m-%d formatted time" do
- expect(Bundler::BuildMetadata.built_at).to eq "1970-01-01"
+ describe "#timestamp" do
+ it "returns %Y-%m-%d formatted current time if built_at not set" do
+ Bundler::BuildMetadata.instance_variable_set(:@built_at, nil)
+ expect(Bundler::BuildMetadata.timestamp).to eq "1970-01-01"
end
- end
- describe "#release?" do
- it "returns false as default" do
- expect(Bundler::BuildMetadata.release?).to be_falsey
+ it "returns %Y-%m-%d formatted current time if built_at not set" do
+ Bundler::BuildMetadata.instance_variable_set(:@built_at, "2025-01-01")
+ expect(Bundler::BuildMetadata.timestamp).to eq "2025-01-01"
+ ensure
+ Bundler::BuildMetadata.instance_variable_set(:@built_at, nil)
end
end
@@ -40,10 +42,9 @@ RSpec.describe Bundler::BuildMetadata do
describe "#to_h" do
subject { Bundler::BuildMetadata.to_h }
- it "returns a hash includes Built At, Git SHA and Released Version" do
- expect(subject["Built At"]).to eq "1970-01-01"
+ it "returns a hash includes Timestamp, and Git SHA" do
+ expect(subject["Timestamp"]).to eq "1970-01-01"
expect(subject["Git SHA"]).to be_instance_of(String)
- expect(subject["Released Version"]).to be_falsey
end
end
end
diff --git a/spec/bundler/bundler/bundler_spec.rb b/spec/bundler/bundler/bundler_spec.rb
index 6a2e435e54..bddcbdaef3 100644
--- a/spec/bundler/bundler/bundler_spec.rb
+++ b/spec/bundler/bundler/bundler_spec.rb
@@ -52,10 +52,10 @@ RSpec.describe Bundler do
s.description = "Bundler manages an application's dependencies through its entire life, across many machines, systematically and repeatably"
s.email = ["team@bundler.io"]
s.homepage = "https://bundler.io"
- s.metadata = { "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",
+ s.metadata = { "bug_tracker_uri" => "https://github.com/ruby/rubygems/issues?q=is%3Aopen+is%3Aissue+label%3ABundler",
+ "changelog_uri" => "https://github.com/ruby/rubygems/blob/master/bundler/CHANGELOG.md",
"homepage_uri" => "https://bundler.io/",
- "source_code_uri" => "https://github.com/rubygems/rubygems/tree/master/bundler" }
+ "source_code_uri" => "https://github.com/ruby/rubygems/tree/master/bundler" }
s.require_paths = ["lib"]
s.required_ruby_version = Gem::Requirement.new([">= 2.6.0"])
s.required_rubygems_version = Gem::Requirement.new([">= 3.0.1"])
@@ -164,53 +164,36 @@ RSpec.describe Bundler do
end
describe "#which" do
- let(:executable) { "executable" }
+ it "can detect relative path" do
+ script_path = bundled_app("tmp/test_command")
+ create_file(script_path, "#!/usr/bin/env ruby\n")
- 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]
+ result = Dir.chdir script_path.dirname.dirname do
+ Bundler.which("test_command")
end
- end
-
- let(:expected) { "executable" }
-
- before do
- ENV["PATH"] = path.join(File::PATH_SEPARATOR)
+ expect(result).to eq(nil)
- allow(File).to receive(:file?).and_return(false)
- allow(File).to receive(:executable?).and_return(false)
- if expected
- expect(File).to receive(:file?).with(expected).and_return(true)
- expect(File).to receive(:executable?).with(expected).and_return(true)
+ result = Dir.chdir script_path.dirname do
+ Bundler.which("test_command")
end
- end
-
- subject { described_class.which(executable) }
- shared_examples_for "it returns the correct executable" do
- it "returns the expected file" do
- expect(subject).to eq(expected)
- end
+ expect(result).to eq("test_command") unless Gem.win_platform?
+ expect(result).to eq("test_command.bat") if Gem.win_platform?
end
- it_behaves_like "it returns the correct executable"
+ it "can detect absolute path" do
+ create_file("test_command", "#!/usr/bin/env ruby\n")
- context "when the executable in inside a quoted path" do
- let(:expected) do
- if Gem.win_platform?
- "C:/e/executable"
- else
- "/e/executable"
- end
- end
- it_behaves_like "it returns the correct executable"
+ ENV["PATH"] = bundled_app("test_command").parent.to_s
+
+ result = Bundler.which("test_command")
+ expect(result).to eq(bundled_app("test_command").to_s) unless Gem.win_platform?
+ expect(result).to eq(bundled_app("test_command.bat").to_s) if Gem.win_platform?
end
- context "when the executable is not found" do
- let(:expected) { nil }
- it_behaves_like "it returns the correct executable"
+ it "returns nil when not found" do
+ result = Bundler.which("test_command")
+ expect(result).to eq(nil)
end
end
@@ -227,14 +210,14 @@ RSpec.describe Bundler do
describe "#mkdir_p" do
it "creates a folder at the given path" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
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
+ Bundler.mkdir_p(bundled_app("foo", "bar"))
+ expect(bundled_app("foo", "bar")).to exist
end
end
@@ -267,6 +250,7 @@ RSpec.describe Bundler do
it "should issue a warning and return a temporary user home" do
allow(Bundler.rubygems).to receive(:user_home).and_return(path)
allow(File).to receive(:directory?).with(path).and_return true
+ allow(File).to receive(:writable?).and_call_original
allow(File).to receive(:writable?).with(path).and_return false
allow(File).to receive(:directory?).with(dotbundle).and_return false
allow(Bundler).to receive(:tmp).and_return(Pathname.new("/tmp/trulyrandom"))
diff --git a/spec/bundler/bundler/cli_common_spec.rb b/spec/bundler/bundler/cli_common_spec.rb
new file mode 100644
index 0000000000..015894b3a1
--- /dev/null
+++ b/spec/bundler/bundler/cli_common_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require "bundler/cli"
+
+RSpec.describe Bundler::CLI::Common do
+ describe "gem_not_found_message" do
+ it "should suggest alternate gem names" do
+ message = subject.gem_not_found_message("ralis", ["BOGUS"])
+ expect(message).to match("Could not find gem 'ralis'.$")
+ message = subject.gem_not_found_message("ralis", ["rails"])
+ expect(message).to match("Did you mean 'rails'?")
+ message = subject.gem_not_found_message("Rails", ["rails"])
+ expect(message).to match("Did you mean 'rails'?")
+ message = subject.gem_not_found_message("meail", %w[email fail eval])
+ expect(message).to match("Did you mean 'email'?")
+ message = subject.gem_not_found_message("nokogri", %w[nokogiri rails sidekiq dog])
+ expect(message).to match("Did you mean 'nokogiri'?")
+ message = subject.gem_not_found_message("methosd", %w[method methods bogus])
+ expect(message).to match(/Did you mean 'method(|s)' or 'method(|s)'?/)
+ end
+ end
+end
diff --git a/spec/bundler/bundler/cli_spec.rb b/spec/bundler/bundler/cli_spec.rb
index c71fc8e9e7..e2c64b9394 100644
--- a/spec/bundler/bundler/cli_spec.rb
+++ b/spec/bundler/bundler/cli_spec.rb
@@ -87,45 +87,69 @@ RSpec.describe "bundle executable" do
end
context "with no arguments" do
- it "prints a concise help message", bundler: "3" do
- bundle ""
- expect(err).to be_empty
+ it "tries to installs by default but print help on missing Gemfile" do
+ bundle "", raise_on_error: false
+ expect(err).to include("Could not locate Gemfile")
+ expect(out).to include("In a future version of Bundler")
+
expect(out).to include("Bundler version #{Bundler::VERSION}").
and include("\n\nBundler commands:\n\n").
and include("\n\n Primary commands:\n").
and include("\n\n Utilities:\n").
and include("\n\nOptions:\n")
end
+
+ it "runs bundle install when default_cli_command set to install" do
+ bundle "config set default_cli_command install"
+ bundle "", raise_on_error: false
+ expect(out).to_not include("In a future version of Bundler")
+ expect(err).to include("Could not locate Gemfile")
+ expect(exitstatus).to_not be_zero
+ end
end
context "when ENV['BUNDLE_GEMFILE'] is set to an empty string" do
it "ignores it" do
gemfile bundled_app_gemfile, <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
bundle :install, env: { "BUNDLE_GEMFILE" => "" }
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
context "with --verbose" do
+ before do
+ gemfile "source 'https://gem.repo1'"
+ end
+
it "prints the running command" do
- 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 "source \"#{file_uri_for(gem_repo1)}\"", verbose: true
+ bundle "install", verbose: true
expect(out).to start_with("Running `bundle install --verbose` with bundler #{Bundler::VERSION}")
end
- it "doesn't print defaults" do
- install_gemfile "source \"#{file_uri_for(gem_repo1)}\"", verbose: true
- expect(out).to start_with("Running `bundle install --verbose` with bundler #{Bundler::VERSION}")
+ it "prints the simulated version too when setting is enabled" do
+ bundle "config simulate_version 4", verbose: true
+ bundle "info bundler", verbose: true
+ expect(out).to start_with("Running `bundle info bundler --verbose` with bundler #{Bundler::VERSION} (simulating Bundler 4)")
+ end
+ end
+
+ context "with verbose configuration" do
+ before do
+ bundle "config verbose true"
+ end
+
+ it "prints the running command" do
+ gemfile "source 'https://gem.repo1'"
+ bundle "info bundler"
+ expect(out).to start_with("Running `bundle info bundler` with bundler #{Bundler::VERSION}")
end
end
@@ -138,8 +162,8 @@ RSpec.describe "bundle executable" do
before do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", '0.9.1'
+ source "https://gem.repo1"
+ gem "myrack", '0.9.1'
G
end
@@ -149,8 +173,8 @@ RSpec.describe "bundle executable" do
it "prints a message when there are outdated gems" do
run_command
- expect(out).to include("Gem Current Latest Requested Groups")
- expect(out).to include("rack 0.9.1 1.0.0 = 0.9.1 default")
+ expect(out).to include("Gem Current Latest Requested Groups")
+ expect(out).to include("myrack 0.9.1 1.0.0 = 0.9.1 default")
end
end
@@ -160,7 +184,7 @@ RSpec.describe "bundle executable" do
it "prints a message when there are outdated gems" do
run_command
- expect(out).to include("rack (newest 1.0.0, installed 0.9.1, requested = 0.9.1)")
+ expect(out).to include("myrack (newest 1.0.0, installed 0.9.1, requested = 0.9.1)")
end
end
@@ -170,7 +194,7 @@ RSpec.describe "bundle executable" do
it "prints a simplified message when there are outdated gems" do
run_command
- expect(out).to include("rack (newest 1.0.0, installed 0.9.1, requested = 0.9.1)")
+ expect(out).to include("myrack (newest 1.0.0, installed 0.9.1, requested = 0.9.1)")
end
end
end
@@ -179,7 +203,7 @@ RSpec.describe "bundle executable" do
shared_examples_for "no warning" do
it "prints no warning" do
bundle "fail", env: { "BUNDLER_VERSION" => bundler_version }, raise_on_error: false
- expect(last_command.stdboth).to eq("Could not find command \"fail\".")
+ expect(stdboth).to eq("Could not find command \"fail\".")
end
end
@@ -228,10 +252,10 @@ To update to the most recent version, run `bundle update --bundler`
context "running a parseable command" do
it "prints no warning" do
bundle "config get --parseable foo", env: { "BUNDLER_VERSION" => bundler_version }
- expect(last_command.stdboth).to eq ""
+ expect(stdboth).to eq ""
bundle "platform --ruby", env: { "BUNDLER_VERSION" => bundler_version }, raise_on_error: false
- expect(last_command.stdboth).to eq "Could not locate Gemfile"
+ expect(stdboth).to eq "Could not locate Gemfile"
end
end
@@ -250,13 +274,23 @@ To update to the most recent version, run `bundle update --bundler`
end
RSpec.describe "bundler executable" do
- it "shows the bundler version just as the `bundle` executable does", bundler: "< 3" do
+ it "shows the bundler version just as the `bundle` executable does" do
bundler "--version"
- expect(out).to eq("Bundler version #{Bundler::VERSION}")
- end
+ expect(out).to eq(Bundler::VERSION.to_s)
- it "shows the bundler version just as the `bundle` executable does", bundler: "3" do
+ bundle "config simulate_version 5"
bundler "--version"
- expect(out).to eq(Bundler::VERSION)
+ expect(out).to eq("#{Bundler::VERSION} (simulating Bundler 5)")
+ end
+
+ it "shows cli_help when bundler install and no Gemfile is found" do
+ bundler "install", raise_on_error: false
+ expect(err).to include("Could not locate Gemfile")
+
+ expect(out).to include("Bundler version #{Bundler::VERSION}").
+ and include("\n\nBundler commands:\n\n").
+ and include("\n\n Primary commands:\n").
+ and include("\n\n Utilities:\n").
+ and include("\n\nOptions:\n")
end
end
diff --git a/spec/bundler/bundler/compact_index_client/parser_spec.rb b/spec/bundler/bundler/compact_index_client/parser_spec.rb
index 45a08fd9ff..1f6b9e593b 100644
--- a/spec/bundler/bundler/compact_index_client/parser_spec.rb
+++ b/spec/bundler/bundler/compact_index_client/parser_spec.rb
@@ -89,11 +89,6 @@ RSpec.describe Bundler::CompactIndexClient::Parser do
compact_index.versions = +""
expect(parser).not_to be_available
end
-
- it "returns false when versions ends improperly without a newline" do
- compact_index.versions = "a 1.0.0 aaa1"
- expect(parser).not_to be_available
- end
end
describe "#names" do
@@ -143,108 +138,78 @@ RSpec.describe Bundler::CompactIndexClient::Parser do
end
describe "#info" do
- it "returns the info for example gem 'a' which has no deps" do
- expect(parser.info("a")).to eq(
+ let(:a_result) do
+ [
[
- [
- "a",
- "1.0.0",
- nil,
- [],
- [
- ["checksum", ["aaa1"]],
- ["ruby", [">= 3.0.0"]],
- ["rubygems", [">= 3.2.3"]],
- ],
- ],
- [
- "a",
- "1.0.1",
- nil,
- [],
- [
- ["checksum", ["aaa2"]],
- ["ruby", [">= 3.0.0"]],
- ["rubygems", [">= 3.2.3"]],
- ],
- ],
- [
- "a",
- "1.1.0",
- nil,
- [],
- [
- ["checksum", ["aaa3"]],
- ["ruby", [">= 3.0.0"]],
- ["rubygems", [">= 3.2.3"]],
- ],
- ],
- ]
- )
+ "a",
+ "1.0.0",
+ nil,
+ [],
+ [["checksum", ["aaa1"]], ["ruby", [">= 3.0.0"]], ["rubygems", [">= 3.2.3"]]],
+ ],
+ [
+ "a",
+ "1.0.1",
+ nil,
+ [],
+ [["checksum", ["aaa2"]], ["ruby", [">= 3.0.0"]], ["rubygems", [">= 3.2.3"]]],
+ ],
+ [
+ "a",
+ "1.1.0",
+ nil,
+ [],
+ [["checksum", ["aaa3"]], ["ruby", [">= 3.0.0"]], ["rubygems", [">= 3.2.3"]]],
+ ],
+ ]
+ end
+ let(:b_result) do
+ [
+ [
+ "b",
+ "2.0.0",
+ nil,
+ [["a", ["~> 1.0", "<= 3.0"]]],
+ [["checksum", ["bbb1"]]],
+ ],
+ [
+ "b",
+ "2.0.0",
+ "java",
+ [["a", ["~> 1.0", "<= 3.0"]]],
+ [["checksum", ["bbb2"]]],
+ ],
+ ]
+ end
+ let(:c_result) do
+ [
+ [
+ "c",
+ "3.0.0",
+ nil,
+ [["a", ["= 1.0.0"]], ["b", ["~> 2.0"]]],
+ [["checksum", ["ccc1"]], ["ruby", [">= 2.7.0"]], ["rubygems", [">= 3.0.0"]]],
+ ],
+ [
+ "c",
+ "3.3.3",
+ nil,
+ [["a", [">= 1.1.0"]], ["b", ["~> 2.0"]]],
+ [["checksum", ["ccc3"]], ["ruby", [">= 3.0.0"]], ["rubygems", [">= 3.2.3"]]],
+ ],
+ ]
+ end
+
+ it "returns the info for example gem 'a' which has no deps" do
+ expect(parser.info("a")).to eq(a_result)
end
it "returns the info for example gem 'b' which has platform and compound deps" do
- expect(parser.info("b")).to eq(
- [
- [
- "b",
- "2.0.0",
- nil,
- [
- ["a", ["~> 1.0", "<= 3.0"]],
- ],
- [
- ["checksum", ["bbb1"]],
- ],
- ],
- [
- "b",
- "2.0.0",
- "java",
- [
- ["a", ["~> 1.0", "<= 3.0"]],
- ],
- [
- ["checksum", ["bbb2"]],
- ],
- ],
- ]
- )
+ expect(parser.info("b")).to eq(b_result)
end
it "returns the info for example gem 'c' which has deps and yanked version (requires use of correct info checksum)" do
- expect(parser.info("c")).to eq(
- [
- [
- "c",
- "3.0.0",
- nil,
- [
- ["a", ["= 1.0.0"]],
- ["b", ["~> 2.0"]],
- ],
- [
- ["checksum", ["ccc1"]],
- ["ruby", [">= 2.7.0"]],
- ["rubygems", [">= 3.0.0"]],
- ],
- ],
- [
- "c",
- "3.3.3",
- nil,
- [
- ["a", [">= 1.1.0"]],
- ["b", ["~> 2.0"]],
- ],
- [
- ["checksum", ["ccc3"]],
- ["ruby", [">= 3.0.0"]],
- ["rubygems", [">= 3.2.3"]],
- ],
- ],
- ]
- )
+ expect(parser.info("c")).to eq(c_result)
end
it "returns an empty array when the info is empty" do
@@ -255,5 +220,18 @@ RSpec.describe Bundler::CompactIndexClient::Parser do
it "returns an empty array when the info is not readable" do
expect(parser.info("d")).to eq([])
end
+
+ it "handles empty lines in the versions file (Artifactory bug that they have yet to fix)" do
+ compact_index.versions = +<<~VERSIONS
+ created_at: 2024-05-01T00:00:04Z
+ ---
+ a 1.0.0,1.0.1,1.1.0 aaa111
+ b 2.0.0,2.0.0-java bbb222
+
+ c 3.0.0,3.0.3,3.3.3 ccc333
+ c -3.0.3 ccc333yanked
+ VERSIONS
+ expect(parser.info("a")).to eq(a_result)
+ end
end
end
diff --git a/spec/bundler/bundler/compact_index_client/updater_spec.rb b/spec/bundler/bundler/compact_index_client/updater_spec.rb
index 87a73d993f..fd63a652a4 100644
--- a/spec/bundler/bundler/compact_index_client/updater_spec.rb
+++ b/spec/bundler/bundler/compact_index_client/updater_spec.rb
@@ -115,6 +115,23 @@ RSpec.describe Bundler::CompactIndexClient::Updater do
expect(local_path.read).to eq(full_body)
expect(etag_path.read).to eq("NewEtag")
end
+
+ it "tries the request again if the partial response is blank" do
+ allow(response).to receive(:[]).with("Repr-Digest") { "sha-256=:baddigest:" }
+ allow(response).to receive(:body) { "" }
+ allow(response).to receive(:is_a?).with(Gem::Net::HTTPPartialContent) { true }
+ expect(fetcher).to receive(:call).once.with(remote_path, headers).and_return(response)
+
+ full_response = double(:full_response, body: full_body, is_a?: false)
+ allow(full_response).to receive(:[]).with("Repr-Digest") { "sha-256=:#{digest}:" }
+ allow(full_response).to receive(:[]).with("ETag") { '"NewEtag"' }
+ expect(fetcher).to receive(:call).once.with(remote_path, { "If-None-Match" => '"LocalEtag"' }).and_return(full_response)
+
+ updater.update(remote_path, local_path, etag_path)
+
+ expect(local_path.read).to eq(full_body)
+ expect(etag_path.read).to eq("NewEtag")
+ end
end
context "without an etag file" do
diff --git a/spec/bundler/bundler/current_ruby_spec.rb b/spec/bundler/bundler/current_ruby_spec.rb
new file mode 100644
index 0000000000..79eb802aa5
--- /dev/null
+++ b/spec/bundler/bundler/current_ruby_spec.rb
@@ -0,0 +1,157 @@
+# frozen_string_literal: true
+
+RSpec.describe Bundler::CurrentRuby do
+ describe "PLATFORM_MAP" do
+ subject { described_class::PLATFORM_MAP }
+
+ # rubocop:disable Naming/VariableNumber
+ let(:platforms) do
+ { ruby: Gem::Platform::RUBY,
+ ruby_18: Gem::Platform::RUBY,
+ ruby_19: Gem::Platform::RUBY,
+ ruby_20: Gem::Platform::RUBY,
+ ruby_21: Gem::Platform::RUBY,
+ ruby_22: Gem::Platform::RUBY,
+ ruby_23: Gem::Platform::RUBY,
+ ruby_24: Gem::Platform::RUBY,
+ ruby_25: Gem::Platform::RUBY,
+ ruby_26: Gem::Platform::RUBY,
+ ruby_27: Gem::Platform::RUBY,
+ ruby_30: Gem::Platform::RUBY,
+ ruby_31: Gem::Platform::RUBY,
+ ruby_32: Gem::Platform::RUBY,
+ ruby_33: Gem::Platform::RUBY,
+ ruby_34: Gem::Platform::RUBY,
+ ruby_40: Gem::Platform::RUBY,
+ ruby_41: Gem::Platform::RUBY,
+ mri: Gem::Platform::RUBY,
+ mri_18: Gem::Platform::RUBY,
+ mri_19: Gem::Platform::RUBY,
+ mri_20: Gem::Platform::RUBY,
+ mri_21: Gem::Platform::RUBY,
+ mri_22: Gem::Platform::RUBY,
+ mri_23: Gem::Platform::RUBY,
+ mri_24: Gem::Platform::RUBY,
+ mri_25: Gem::Platform::RUBY,
+ mri_26: Gem::Platform::RUBY,
+ mri_27: Gem::Platform::RUBY,
+ mri_30: Gem::Platform::RUBY,
+ mri_31: Gem::Platform::RUBY,
+ mri_32: Gem::Platform::RUBY,
+ mri_33: Gem::Platform::RUBY,
+ mri_34: Gem::Platform::RUBY,
+ mri_40: Gem::Platform::RUBY,
+ mri_41: Gem::Platform::RUBY,
+ rbx: Gem::Platform::RUBY,
+ truffleruby: Gem::Platform::RUBY,
+ jruby: Gem::Platform::JAVA,
+ jruby_18: Gem::Platform::JAVA,
+ jruby_19: Gem::Platform::JAVA,
+ windows: Gem::Platform::WINDOWS,
+ windows_18: Gem::Platform::WINDOWS,
+ windows_19: Gem::Platform::WINDOWS,
+ windows_20: Gem::Platform::WINDOWS,
+ windows_21: Gem::Platform::WINDOWS,
+ windows_22: Gem::Platform::WINDOWS,
+ windows_23: Gem::Platform::WINDOWS,
+ windows_24: Gem::Platform::WINDOWS,
+ windows_25: Gem::Platform::WINDOWS,
+ windows_26: Gem::Platform::WINDOWS,
+ windows_27: Gem::Platform::WINDOWS,
+ windows_30: Gem::Platform::WINDOWS,
+ windows_31: Gem::Platform::WINDOWS,
+ windows_32: Gem::Platform::WINDOWS,
+ windows_33: Gem::Platform::WINDOWS,
+ windows_34: Gem::Platform::WINDOWS,
+ windows_40: Gem::Platform::WINDOWS,
+ windows_41: Gem::Platform::WINDOWS }
+ end
+
+ let(:deprecated) do
+ { mswin: Gem::Platform::MSWIN,
+ mswin_18: Gem::Platform::MSWIN,
+ mswin_19: Gem::Platform::MSWIN,
+ mswin_20: Gem::Platform::MSWIN,
+ mswin_21: Gem::Platform::MSWIN,
+ mswin_22: Gem::Platform::MSWIN,
+ mswin_23: Gem::Platform::MSWIN,
+ mswin_24: Gem::Platform::MSWIN,
+ mswin_25: Gem::Platform::MSWIN,
+ mswin_26: Gem::Platform::MSWIN,
+ mswin_27: Gem::Platform::MSWIN,
+ mswin_30: Gem::Platform::MSWIN,
+ mswin_31: Gem::Platform::MSWIN,
+ mswin_32: Gem::Platform::MSWIN,
+ mswin_33: Gem::Platform::MSWIN,
+ mswin_34: Gem::Platform::MSWIN,
+ mswin_40: Gem::Platform::MSWIN,
+ mswin_41: Gem::Platform::MSWIN,
+ mswin64: Gem::Platform::MSWIN64,
+ mswin64_19: Gem::Platform::MSWIN64,
+ mswin64_20: Gem::Platform::MSWIN64,
+ mswin64_21: Gem::Platform::MSWIN64,
+ mswin64_22: Gem::Platform::MSWIN64,
+ mswin64_23: Gem::Platform::MSWIN64,
+ mswin64_24: Gem::Platform::MSWIN64,
+ mswin64_25: Gem::Platform::MSWIN64,
+ mswin64_26: Gem::Platform::MSWIN64,
+ mswin64_27: Gem::Platform::MSWIN64,
+ mswin64_30: Gem::Platform::MSWIN64,
+ mswin64_31: Gem::Platform::MSWIN64,
+ mswin64_32: Gem::Platform::MSWIN64,
+ mswin64_33: Gem::Platform::MSWIN64,
+ mswin64_34: Gem::Platform::MSWIN64,
+ mswin64_40: Gem::Platform::MSWIN64,
+ mswin64_41: Gem::Platform::MSWIN64,
+ mingw: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_18: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_19: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_20: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_21: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_22: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_23: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_24: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_25: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_26: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_27: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_30: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_31: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_32: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_33: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_34: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_40: Gem::Platform::UNIVERSAL_MINGW,
+ mingw_41: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_20: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_21: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_22: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_23: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_24: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_25: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_26: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_27: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_30: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_31: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_32: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_33: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_34: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_40: Gem::Platform::UNIVERSAL_MINGW,
+ x64_mingw_41: Gem::Platform::UNIVERSAL_MINGW }
+ end
+ # rubocop:enable Naming/VariableNumber
+
+ it "includes all platforms" do
+ expect(subject).to eq(platforms.merge(deprecated))
+ end
+ end
+
+ describe "Deprecated platform" do
+ it "outputs an error and aborts when calling maglev?" do
+ expect { Bundler.current_ruby.maglev? }.to raise_error(Bundler::RemovedError, /`CurrentRuby#maglev\?` was removed with no replacement./)
+ end
+
+ it "outputs an error and aborts when calling maglev_31?" do
+ expect { Bundler.current_ruby.maglev_31? }.to raise_error(Bundler::RemovedError, /`CurrentRuby#maglev_31\?` was removed with no replacement./)
+ end
+ end
+end
diff --git a/spec/bundler/bundler/definition_spec.rb b/spec/bundler/bundler/definition_spec.rb
index 28c04e0860..9524c70193 100644
--- a/spec/bundler/bundler/definition_spec.rb
+++ b/spec/bundler/bundler/definition_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe Bundler::Definition do
it "raises an PermissionError with explanation" do
allow(File).to receive(:open).and_call_original
expect(File).to receive(:open).with(bundled_app_lock, "wb").
- and_raise(Errno::EACCES)
+ and_raise(Errno::EACCES.new(bundled_app_lock.to_s))
expect { subject.lock }.
to raise_error(Bundler::PermissionError, /Gemfile\.lock/)
end
@@ -33,7 +33,7 @@ RSpec.describe Bundler::Definition do
before { Bundler::Definition.no_lock = true }
after { Bundler::Definition.no_lock = false }
- it "does not create a lock file" do
+ it "does not create a lockfile" do
subject.lock
expect(bundled_app_lock).not_to be_file
end
@@ -45,17 +45,17 @@ RSpec.describe Bundler::Definition do
build_lib "foo", "1.0", path: lib_path("foo")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :path => "#{lib_path("foo")}"
G
build_lib "foo", "1.0", path: lib_path("foo") do |s|
- s.add_dependency "rack", "1.0"
+ s.add_dependency "myrack", "1.0"
end
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "foo", "1.0"
- c.checksum gem_repo1, "rack", "1.0.0"
+ c.checksum gem_repo1, "myrack", "1.0.0"
end
bundle :install, env: { "DEBUG" => "1" }
@@ -66,12 +66,12 @@ RSpec.describe Bundler::Definition do
remote: #{lib_path("foo")}
specs:
foo (1.0)
- rack (= 1.0)
+ myrack (= 1.0)
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
@@ -80,7 +80,7 @@ RSpec.describe Bundler::Definition do
foo!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
@@ -91,7 +91,7 @@ RSpec.describe Bundler::Definition do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "ffi"
G
@@ -104,17 +104,17 @@ RSpec.describe Bundler::Definition do
it "for a path gem with deps and no changes" do
build_lib "foo", "1.0", path: lib_path("foo") do |s|
- s.add_dependency "rack", "1.0"
+ s.add_dependency "myrack", "1.0"
s.add_development_dependency "net-ssh", "1.0"
end
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "foo", "1.0"
- c.checksum gem_repo1, "rack", "1.0.0"
+ c.checksum gem_repo1, "myrack", "1.0.0"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :path => "#{lib_path("foo")}"
G
@@ -123,12 +123,12 @@ RSpec.describe Bundler::Definition do
remote: #{lib_path("foo")}
specs:
foo (1.0)
- rack (= 1.0)
+ myrack (= 1.0)
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
@@ -137,7 +137,7 @@ RSpec.describe Bundler::Definition do
foo!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
expect(lockfile).to eq(expected_lockfile)
@@ -149,22 +149,22 @@ RSpec.describe Bundler::Definition do
end
it "for a locked gem for another platform" do
- checksums = checksums_section_when_existing do |c|
- c.no_checksum "only_java", "1.1", "java"
- end
-
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "only_java", platform: :jruby
G
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo1, "only_java", "1.1", "java"
+ end
+
bundle "lock --add-platform java"
bundle :check, env: { "DEBUG" => "1" }
expect(out).to match(/using resolution from the lockfile/)
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
only_java (1.1-java)
@@ -175,17 +175,17 @@ RSpec.describe Bundler::Definition do
only_java
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "for a rubygems gem" do
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo1, "foo", "1.0"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo"
G
@@ -194,7 +194,7 @@ RSpec.describe Bundler::Definition do
expect(out).to match(/using resolution from the lockfile/)
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
foo (1.0)
@@ -205,7 +205,7 @@ RSpec.describe Bundler::Definition do
foo
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
end
@@ -215,13 +215,13 @@ RSpec.describe Bundler::Definition do
context "eager unlock" do
let(:source_list) do
Bundler::SourceList.new.tap do |source_list|
- source_list.add_global_rubygems_remote(file_uri_for(gem_repo4))
+ source_list.add_global_rubygems_remote("https://gem.repo4")
end
end
before do
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem 'isolated_owner'
gem 'shared_owner_a'
@@ -230,7 +230,7 @@ RSpec.describe Bundler::Definition do
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo4)}
+ remote: https://gem.repo4
specs:
isolated_dep (2.0.1)
isolated_owner (1.0.1)
@@ -299,10 +299,6 @@ RSpec.describe Bundler::Definition do
[]
end
- def rubygems_remotes
- []
- end
-
def replace_sources!(arg)
nil
end
diff --git a/spec/bundler/bundler/dependency_spec.rb b/spec/bundler/bundler/dependency_spec.rb
index a953372742..f930459571 100644
--- a/spec/bundler/bundler/dependency_spec.rb
+++ b/spec/bundler/bundler/dependency_spec.rb
@@ -35,133 +35,15 @@ RSpec.describe Bundler::Dependency do
end
end
- describe "PLATFORM_MAP" do
- subject { described_class::PLATFORM_MAP }
+ it "is on the current platform" do
+ engine = Gem.win_platform? ? "windows" : RUBY_ENGINE
- # rubocop:disable Naming/VariableNumber
- let(:platforms) do
- { ruby: Gem::Platform::RUBY,
- ruby_18: Gem::Platform::RUBY,
- ruby_19: Gem::Platform::RUBY,
- ruby_20: Gem::Platform::RUBY,
- ruby_21: Gem::Platform::RUBY,
- ruby_22: Gem::Platform::RUBY,
- ruby_23: Gem::Platform::RUBY,
- ruby_24: Gem::Platform::RUBY,
- ruby_25: Gem::Platform::RUBY,
- ruby_26: Gem::Platform::RUBY,
- ruby_27: Gem::Platform::RUBY,
- ruby_30: Gem::Platform::RUBY,
- ruby_31: Gem::Platform::RUBY,
- ruby_32: Gem::Platform::RUBY,
- ruby_33: Gem::Platform::RUBY,
- ruby_34: Gem::Platform::RUBY,
- mri: Gem::Platform::RUBY,
- mri_18: Gem::Platform::RUBY,
- mri_19: Gem::Platform::RUBY,
- mri_20: Gem::Platform::RUBY,
- mri_21: Gem::Platform::RUBY,
- mri_22: Gem::Platform::RUBY,
- mri_23: Gem::Platform::RUBY,
- mri_24: Gem::Platform::RUBY,
- mri_25: Gem::Platform::RUBY,
- mri_26: Gem::Platform::RUBY,
- mri_27: Gem::Platform::RUBY,
- mri_30: Gem::Platform::RUBY,
- mri_31: Gem::Platform::RUBY,
- mri_32: Gem::Platform::RUBY,
- mri_33: Gem::Platform::RUBY,
- mri_34: Gem::Platform::RUBY,
- rbx: Gem::Platform::RUBY,
- truffleruby: Gem::Platform::RUBY,
- jruby: Gem::Platform::JAVA,
- jruby_18: Gem::Platform::JAVA,
- jruby_19: Gem::Platform::JAVA,
- windows: Gem::Platform::WINDOWS,
- windows_18: Gem::Platform::WINDOWS,
- windows_19: Gem::Platform::WINDOWS,
- windows_20: Gem::Platform::WINDOWS,
- windows_21: Gem::Platform::WINDOWS,
- windows_22: Gem::Platform::WINDOWS,
- windows_23: Gem::Platform::WINDOWS,
- windows_24: Gem::Platform::WINDOWS,
- windows_25: Gem::Platform::WINDOWS,
- windows_26: Gem::Platform::WINDOWS,
- windows_27: Gem::Platform::WINDOWS,
- windows_30: Gem::Platform::WINDOWS,
- windows_31: Gem::Platform::WINDOWS,
- windows_32: Gem::Platform::WINDOWS,
- windows_33: Gem::Platform::WINDOWS,
- windows_34: Gem::Platform::WINDOWS }
- end
-
- let(:deprecated) do
- { mswin: Gem::Platform::MSWIN,
- mswin_18: Gem::Platform::MSWIN,
- mswin_19: Gem::Platform::MSWIN,
- mswin_20: Gem::Platform::MSWIN,
- mswin_21: Gem::Platform::MSWIN,
- mswin_22: Gem::Platform::MSWIN,
- mswin_23: Gem::Platform::MSWIN,
- mswin_24: Gem::Platform::MSWIN,
- mswin_25: Gem::Platform::MSWIN,
- mswin_26: Gem::Platform::MSWIN,
- mswin_27: Gem::Platform::MSWIN,
- mswin_30: Gem::Platform::MSWIN,
- mswin_31: Gem::Platform::MSWIN,
- mswin_32: Gem::Platform::MSWIN,
- mswin_33: Gem::Platform::MSWIN,
- mswin_34: Gem::Platform::MSWIN,
- mswin64: Gem::Platform::MSWIN64,
- mswin64_19: Gem::Platform::MSWIN64,
- mswin64_20: Gem::Platform::MSWIN64,
- mswin64_21: Gem::Platform::MSWIN64,
- mswin64_22: Gem::Platform::MSWIN64,
- mswin64_23: Gem::Platform::MSWIN64,
- mswin64_24: Gem::Platform::MSWIN64,
- mswin64_25: Gem::Platform::MSWIN64,
- mswin64_26: Gem::Platform::MSWIN64,
- mswin64_27: Gem::Platform::MSWIN64,
- mswin64_30: Gem::Platform::MSWIN64,
- mswin64_31: Gem::Platform::MSWIN64,
- mswin64_32: Gem::Platform::MSWIN64,
- mswin64_33: Gem::Platform::MSWIN64,
- mswin64_34: Gem::Platform::MSWIN64,
- mingw: Gem::Platform::MINGW,
- mingw_18: Gem::Platform::MINGW,
- mingw_19: Gem::Platform::MINGW,
- mingw_20: Gem::Platform::MINGW,
- mingw_21: Gem::Platform::MINGW,
- mingw_22: Gem::Platform::MINGW,
- mingw_23: Gem::Platform::MINGW,
- mingw_24: Gem::Platform::MINGW,
- mingw_25: Gem::Platform::MINGW,
- mingw_26: Gem::Platform::MINGW,
- mingw_27: Gem::Platform::MINGW,
- mingw_30: Gem::Platform::MINGW,
- mingw_31: Gem::Platform::MINGW,
- mingw_32: Gem::Platform::MINGW,
- mingw_33: Gem::Platform::MINGW,
- mingw_34: Gem::Platform::MINGW,
- x64_mingw: Gem::Platform::X64_MINGW,
- x64_mingw_20: Gem::Platform::X64_MINGW,
- x64_mingw_21: Gem::Platform::X64_MINGW,
- x64_mingw_22: Gem::Platform::X64_MINGW,
- x64_mingw_23: Gem::Platform::X64_MINGW,
- x64_mingw_24: Gem::Platform::X64_MINGW,
- x64_mingw_25: Gem::Platform::X64_MINGW,
- x64_mingw_26: Gem::Platform::X64_MINGW,
- x64_mingw_27: Gem::Platform::X64_MINGW,
- x64_mingw_30: Gem::Platform::X64_MINGW,
- x64_mingw_31: Gem::Platform::X64_MINGW,
- x64_mingw_32: Gem::Platform::X64_MINGW,
- x64_mingw_33: Gem::Platform::X64_MINGW,
- x64_mingw_34: Gem::Platform::X64_MINGW }
- end
- # rubocop:enable Naming/VariableNumber
+ dep = described_class.new(
+ "test_gem",
+ "1.0.0",
+ { "platforms" => "#{engine}_#{RbConfig::CONFIG["MAJOR"]}#{RbConfig::CONFIG["MINOR"]}" },
+ )
- it "includes all platforms" do
- expect(subject).to eq(platforms.merge(deprecated))
- end
+ expect(dep.current_platform?).to be_truthy
end
end
diff --git a/spec/bundler/bundler/dsl_spec.rb b/spec/bundler/bundler/dsl_spec.rb
index 3c3b6c26c3..a19f251be5 100644
--- a/spec/bundler/bundler/dsl_spec.rb
+++ b/spec/bundler/bundler/dsl_spec.rb
@@ -103,7 +103,7 @@ RSpec.describe Bundler::Dsl do
)
end
- context "default hosts", bundler: "< 3" do
+ context "default hosts" do
it "converts :github to URI using https" do
subject.gem("sparks", github: "indirect/sparks")
github_uri = "https://github.com/indirect/sparks.git"
@@ -175,7 +175,7 @@ RSpec.describe Bundler::Dsl do
it "handles syntax errors with a useful message" do
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./)
+ to raise_error(Bundler::GemfileError, /There was an error parsing `Gemfile`: (syntax error, unexpected tSTRING_DEND|(compile error - )?syntax error, unexpected '\}'|.+?unexpected '}', ignoring it\n). Bundler cannot continue./m)
end
it "distinguishes syntax errors from evaluation errors" do
@@ -201,8 +201,8 @@ RSpec.describe Bundler::Dsl do
describe "#gem" do
# rubocop:disable Naming/VariableNumber
[:ruby, :ruby_18, :ruby_19, :ruby_20, :ruby_21, :ruby_22, :ruby_23, :ruby_24, :ruby_25, :ruby_26, :ruby_27,
- :ruby_30, :ruby_31, :ruby_32, :ruby_33, :mri, :mri_18, :mri_19, :mri_20, :mri_21, :mri_22, :mri_23, :mri_24,
- :mri_25, :mri_26, :mri_27, :mri_30, :mri_31, :mri_32, :mri_33, :jruby, :rbx, :truffleruby].each do |platform|
+ :ruby_30, :ruby_31, :ruby_32, :ruby_33, :ruby_34, :ruby_40, :mri, :mri_18, :mri_19, :mri_20, :mri_21, :mri_22, :mri_23, :mri_24,
+ :mri_25, :mri_26, :mri_27, :mri_30, :mri_31, :mri_32, :mri_33, :mri_34, :mri_40, :jruby, :rbx, :truffleruby].each do |platform|
it "allows #{platform} as a valid platform" do
subject.gem("foo", platform: platform)
end
@@ -211,7 +211,9 @@ RSpec.describe Bundler::Dsl do
it "allows platforms matching the running Ruby version" do
platform = "ruby_#{RbConfig::CONFIG["MAJOR"]}#{RbConfig::CONFIG["MINOR"]}"
- subject.gem("foo", platform: platform)
+
+ expect { subject.gem("foo", platform: platform) }.not_to raise_error
+ expect(Bundler.current_ruby.respond_to?("#{platform}?")).to be_truthy
end
it "rejects invalid platforms" do
@@ -219,6 +221,11 @@ RSpec.describe Bundler::Dsl do
to raise_error(Bundler::GemfileError, /is not a valid platform/)
end
+ it "warn for legacy windows platforms" do
+ expect(Bundler::SharedHelpers).to receive(:feature_deprecated!).with(/\APlatform :mswin, :x64_mingw will be removed in the future./)
+ subject.gem("foo", platforms: [:mswin, :jruby, :x64_mingw])
+ end
+
it "rejects empty gem name" do
expect { subject.gem("") }.
to raise_error(Bundler::GemfileError, /an empty gem name is not valid/)
@@ -283,6 +290,15 @@ RSpec.describe Bundler::Dsl do
end
end
+ describe "#platforms" do
+ it "warn for legacy windows platforms" do
+ expect(Bundler::SharedHelpers).to receive(:feature_deprecated!).with(/\APlatform :mswin64, :mingw will be removed in the future./)
+ subject.platforms(:mswin64, :jruby, :mingw) do
+ subject.gem("foo")
+ end
+ end
+ end
+
context "can bundle groups of gems with" do
# git "https://github.com/rails/rails.git" do
# gem "railties"
@@ -322,7 +338,7 @@ RSpec.describe Bundler::Dsl 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) }.
- to raise_error(Bundler::GemfileError, /There was an error parsing `Gemfile`:( compile error -)? unknown regexp options - trg.+ Bundler cannot continue./)
+ to raise_error(Bundler::GemfileError, /There was an error parsing `Gemfile`:( compile error -)?.+?unknown regexp options - trg.+ Bundler cannot continue./m)
end
end
@@ -350,21 +366,4 @@ RSpec.describe Bundler::Dsl do
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/spec/bundler/bundler/endpoint_specification_spec.rb b/spec/bundler/bundler/endpoint_specification_spec.rb
index e7e10730cf..6518f125ba 100644
--- a/spec/bundler/bundler/endpoint_specification_spec.rb
+++ b/spec/bundler/bundler/endpoint_specification_spec.rb
@@ -42,7 +42,7 @@ RSpec.describe Bundler::EndpointSpecification do
expect { subject }.to raise_error(
Bundler::GemspecError,
a_string_including("There was an error parsing the metadata for the gem foo (1.0.0)").
- and(a_string_including('The metadata was {"rubygems"=>">\n"}'))
+ and(a_string_including("The metadata was #{{ "rubygems" => ">\n" }.inspect}"))
)
end
end
diff --git a/spec/bundler/bundler/env_spec.rb b/spec/bundler/bundler/env_spec.rb
index 7997cb0c40..e0ab0a45e3 100644
--- a/spec/bundler/bundler/env_spec.rb
+++ b/spec/bundler/bundler/env_spec.rb
@@ -70,16 +70,16 @@ RSpec.describe Bundler::Env do
context "when there is a Gemfile and a lockfile and print_gemfile is true" do
before do
- gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem 'rack', '1.0.0'"
+ gemfile "source 'https://gem.repo1'; gem 'myrack', '1.0.0'"
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
DEPENDENCIES
- rack
+ myrack
BUNDLED WITH
1.10.0
@@ -92,12 +92,12 @@ RSpec.describe Bundler::Env do
it "prints the Gemfile" do
expect(output).to include("Gemfile")
- expect(output).to include("'rack', '1.0.0'")
+ expect(output).to include("'myrack', '1.0.0'")
end
it "prints the lockfile" do
expect(output).to include("Gemfile.lock")
- expect(output).to include("rack (1.0.0)")
+ expect(output).to include("myrack (1.0.0)")
end
end
@@ -148,9 +148,9 @@ RSpec.describe Bundler::Env do
end
before do
- gemfile("source \"#{file_uri_for(gem_repo1)}\"; gemspec")
+ gemfile("source 'https://gem.repo1'; gemspec")
- File.open(bundled_app.join("foo.gemspec"), "wb") do |f|
+ File.open(bundled_app("foo.gemspec"), "wb") do |f|
f.write(gemspec)
end
@@ -167,10 +167,10 @@ RSpec.describe Bundler::Env do
context "when eval_gemfile is used" do
it "prints all gemfiles" do
- 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)}"
+ gemfile bundled_app("other/Gemfile-other"), "gem 'myrack'"
+ gemfile bundled_app("other/Gemfile"), "eval_gemfile 'Gemfile-other'"
+ gemfile bundled_app("Gemfile-alt"), <<-G
+ source "https://gem.repo1"
eval_gemfile "other/Gemfile"
G
gemfile "eval_gemfile #{bundled_app("Gemfile-alt").to_s.dump}"
@@ -190,7 +190,7 @@ RSpec.describe Bundler::Env do
### Gemfile-alt
```ruby
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
eval_gemfile "other/Gemfile"
```
@@ -203,7 +203,7 @@ RSpec.describe Bundler::Env do
### other/Gemfile-other
```ruby
- gem 'rack'
+ gem 'myrack'
```
### Gemfile.lock
diff --git a/spec/bundler/bundler/fetcher/dependency_spec.rb b/spec/bundler/bundler/fetcher/dependency_spec.rb
index c420b7c07f..61e32acfd9 100644
--- a/spec/bundler/bundler/fetcher/dependency_spec.rb
+++ b/spec/bundler/bundler/fetcher/dependency_spec.rb
@@ -212,7 +212,7 @@ RSpec.describe Bundler::Fetcher::Dependency do
let(:dep_api_uri) { double(:dep_api_uri) }
let(:unmarshalled_gems) { double(:unmarshalled_gems) }
let(:fetch_response) { double(:fetch_response, body: double(:body)) }
- let(:rubygems_limit) { 50 }
+ let(:rubygems_limit) { 100 }
before { allow(subject).to receive(:dependency_api_uri).with(gem_names).and_return(dep_api_uri) }
diff --git a/spec/bundler/bundler/fetcher/downloader_spec.rb b/spec/bundler/bundler/fetcher/downloader_spec.rb
index d5c32f4730..36b9b94990 100644
--- a/spec/bundler/bundler/fetcher/downloader_spec.rb
+++ b/spec/bundler/bundler/fetcher/downloader_spec.rb
@@ -83,12 +83,12 @@ RSpec.describe Bundler::Fetcher::Downloader do
/Authentication is required for www.uri-to-fetch.com/)
end
- it "should raise a Bundler::Fetcher::AuthenticationRequiredError with advices" do
+ it "should raise a Bundler::Fetcher::AuthenticationRequiredError with advice" 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
+ context "when there are credentials provided in the request" do
let(:uri) { Gem::URI("http://user:password@www.uri-to-fetch.com") }
it "should raise a Bundler::Fetcher::BadAuthenticationError that doesn't contain the password" do
@@ -116,7 +116,7 @@ RSpec.describe Bundler::Fetcher::Downloader do
to raise_error(Bundler::Fetcher::FallbackError, "Gem::Net::HTTPNotFound: http://www.uri-to-fetch.com/api/v2/endpoint")
end
- context "when the there are credentials provided in the request" do
+ context "when there are credentials provided in the request" do
let(:uri) { Gem::URI("http://username:password@www.uri-to-fetch.com/api/v2/endpoint") }
it "should raise a Bundler::Fetcher::FallbackError that doesn't contain the password" do
@@ -154,35 +154,39 @@ RSpec.describe Bundler::Fetcher::Downloader do
context "that contains cgi escaped characters" do
let(:uri) { Gem::URI("http://username:password%24@www.uri-to-fetch.com/api/v2/endpoint") }
- it "should request basic authentication with the username and password" do
+ it "should request basic authentication with the username and password, and log the HTTP GET request to debug, without the password" do
expect(net_http_get).to receive(:basic_auth).with("username", "password$")
+ expect(Bundler).to receive_message_chain(:ui, :debug).with("HTTP GET http://username@www.uri-to-fetch.com/api/v2/endpoint")
subject.request(uri, options)
end
end
context "that is all unescaped characters" do
let(:uri) { Gem::URI("http://username:password@www.uri-to-fetch.com/api/v2/endpoint") }
- it "should request basic authentication with the username and proper cgi compliant password" do
+ it "should request basic authentication with the username and proper cgi compliant password, and log the HTTP GET request to debug, without the password" do
expect(net_http_get).to receive(:basic_auth).with("username", "password")
+ expect(Bundler).to receive_message_chain(:ui, :debug).with("HTTP GET http://username@www.uri-to-fetch.com/api/v2/endpoint")
subject.request(uri, options)
end
end
end
- context "and there is no password provided" do
+ context "and it's used as the authentication token" do
let(:uri) { Gem::URI("http://username@www.uri-to-fetch.com/api/v2/endpoint") }
- it "should request basic authentication with just the user" do
+ it "should request basic authentication with just the user, and log the HTTP GET request to debug, without the token" do
expect(net_http_get).to receive(:basic_auth).with("username", nil)
+ expect(Bundler).to receive_message_chain(:ui, :debug).with("HTTP GET http://www.uri-to-fetch.com/api/v2/endpoint")
subject.request(uri, options)
end
end
- context "that contains cgi escaped characters" do
+ context "and it's used as the authentication token, and contains cgi escaped characters" do
let(:uri) { Gem::URI("http://username%24@www.uri-to-fetch.com/api/v2/endpoint") }
- it "should request basic authentication with the proper cgi compliant password user" do
+ it "should request basic authentication with the proper cgi compliant password user, and log the HTTP GET request to debug, without the token" do
expect(net_http_get).to receive(:basic_auth).with("username$", nil)
+ expect(Bundler).to receive_message_chain(:ui, :debug).with("HTTP GET http://www.uri-to-fetch.com/api/v2/endpoint")
subject.request(uri, options)
end
end
@@ -197,39 +201,29 @@ RSpec.describe Bundler::Fetcher::Downloader do
end
end
- context "when the request response causes an error included in HTTP_ERRORS" do
- let(:message) { nil }
- let(:error) { RuntimeError.new(message) }
+ context "when the request response causes an HTTP error" do
+ let(:message) { "error about network" }
+ let(:error) { error_class.new(message) }
before do
- stub_const("Bundler::Fetcher::HTTP_ERRORS", [RuntimeError])
allow(connection).to receive(:request).with(uri, net_http_get) { raise error }
end
- it "should trace log the error" do
- allow(Bundler).to receive_message_chain(:ui, :debug)
- expect(Bundler).to receive_message_chain(:ui, :trace).with(error)
- expect { subject.request(uri, options) }.to raise_error(Bundler::HTTPError)
- end
-
- context "when error message is about the host being down" do
- let(:message) { "host down: http://www.uri-to-fetch.com" }
+ context "that it's retryable" do
+ let(:error_class) { Gem::Timeout::Error }
- 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/)
+ it "should trace log the error" do
+ allow(Bundler).to receive_message_chain(:ui, :debug)
+ expect(Bundler).to receive_message_chain(:ui, :trace).with(error)
+ expect { subject.request(uri, options) }.to raise_error(Bundler::HTTPError)
end
- end
-
- context "when error message is not about host down" do
- let(:message) { "other error about network" }
it "should raise a Bundler::HTTPError" do
expect { subject.request(uri, options) }.to raise_error(Bundler::HTTPError,
- "Network error while fetching http://www.uri-to-fetch.com/api/v2/endpoint (other error about network)")
+ "Network error while fetching http://www.uri-to-fetch.com/api/v2/endpoint (error about network)")
end
- context "when the there are credentials provided in the request" do
+ context "when there are credentials provided in the request" do
let(:uri) { Gem::URI("http://username:password@www.uri-to-fetch.com/api/v2/endpoint") }
before do
allow(net_http_get).to receive(:basic_auth).with("username", "password")
@@ -237,17 +231,38 @@ RSpec.describe Bundler::Fetcher::Downloader do
it "should raise a Bundler::HTTPError that doesn't contain the password" do
expect { subject.request(uri, options) }.to raise_error(Bundler::HTTPError,
- "Network error while fetching http://username@www.uri-to-fetch.com/api/v2/endpoint (other error about network)")
+ "Network error while fetching http://username@www.uri-to-fetch.com/api/v2/endpoint (error about network)")
end
end
end
- context "when error message is about no route to host" do
+ context "when error is about the host being down" do
+ let(:error_class) { Gem::Net::HTTP::Persistent::Error }
+ let(:message) { "host down: 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 is about connection refused" do
+ let(:error_class) { Gem::Net::HTTP::Persistent::Error }
+ let(:message) { "connection refused down: 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 is about no route to host" do
+ let(:error_class) { SocketError }
let(:message) { "Failed to open TCP connection to www.uri-to-fetch.com:443 " }
- it "should raise a Bundler::Fetcher::HTTPError" do
- expect { subject.request(uri, options) }.to raise_error(Bundler::HTTPError,
- "Network error while fetching http://www.uri-to-fetch.com/api/v2/endpoint (#{message})")
+ 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
end
diff --git a/spec/bundler/bundler/fetcher/gem_remote_fetcher_spec.rb b/spec/bundler/bundler/fetcher/gem_remote_fetcher_spec.rb
new file mode 100644
index 0000000000..df1a58d843
--- /dev/null
+++ b/spec/bundler/bundler/fetcher/gem_remote_fetcher_spec.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require "rubygems/remote_fetcher"
+require "bundler/fetcher/gem_remote_fetcher"
+require_relative "../../support/artifice/helpers/artifice"
+require "bundler/vendored_persistent.rb"
+
+RSpec.describe Bundler::Fetcher::GemRemoteFetcher do
+ describe "Parallel download" do
+ it "download using multiple connections from the pool" do
+ unless Bundler.rubygems.provides?(">= 4.0.0.dev")
+ skip "This example can only run when RubyGems supports multiple http connection pool"
+ end
+
+ require_relative "../../support/artifice/helpers/endpoint"
+ concurrent_ruby_path = Dir[scoped_base_system_gem_path.join("gems/concurrent-ruby-*/lib/concurrent-ruby")].first
+ $LOAD_PATH.unshift(concurrent_ruby_path)
+ require "concurrent-ruby"
+
+ require_rack_test
+ responses = []
+
+ latch1 = Concurrent::CountDownLatch.new
+ latch2 = Concurrent::CountDownLatch.new
+ previous_client = Gem::Request::ConnectionPools.client
+ dummy_endpoint = Class.new(Endpoint) do
+ get "/foo" do
+ latch2.count_down
+ latch1.wait
+
+ responses << "foo"
+ end
+
+ get "/bar" do
+ responses << "bar"
+
+ latch1.count_down
+ end
+ end
+
+ Artifice.activate_with(dummy_endpoint)
+ Gem::Request::ConnectionPools.client = Gem::Net::HTTP
+
+ first_request = Thread.new do
+ subject.fetch_path("https://example.org/foo")
+ end
+ second_request = Thread.new do
+ latch2.wait
+ subject.fetch_path("https://example.org/bar")
+ end
+
+ [first_request, second_request].each(&:join)
+
+ expect(responses).to eq(["bar", "foo"])
+ ensure
+ Artifice.deactivate
+ Gem::Request::ConnectionPools.client = previous_client
+ end
+ end
+end
diff --git a/spec/bundler/bundler/fetcher/index_spec.rb b/spec/bundler/bundler/fetcher/index_spec.rb
index dff9ccc3cc..a6a18efd98 100644
--- a/spec/bundler/bundler/fetcher/index_spec.rb
+++ b/spec/bundler/bundler/fetcher/index_spec.rb
@@ -4,7 +4,9 @@ require "rubygems/remote_fetcher"
RSpec.describe Bundler::Fetcher::Index do
let(:downloader) { nil }
- let(:remote) { nil }
+ let(:remote) { double(:remote, uri: remote_uri) }
+ let(:remote_uri) { Gem::URI("http://#{userinfo}remote-uri.org") }
+ let(:userinfo) { "" }
let(:display_uri) { "http://sample_uri.com" }
let(:rubygems) { double(:rubygems) }
let(:gem_names) { %w[foo bar] }
@@ -20,10 +22,8 @@ RSpec.describe Bundler::Fetcher::Index do
end
context "error handling" do
- let(:remote_uri) { Gem::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
@@ -38,25 +38,17 @@ RSpec.describe Bundler::Fetcher::Index do
context "when a 401 response occurs" do
let(:error_message) { "401" }
- 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
context "and there was userinfo" do
- let(:userinfo) { double(:userinfo) }
+ let(:userinfo) { "user:pass@" }
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 "and there was no userinfo" do
- let(:userinfo) { nil }
-
- 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})
+ %r{Bad username or password for http://user@remote-uri.org})
end
end
end
diff --git a/spec/bundler/bundler/friendly_errors_spec.rb b/spec/bundler/bundler/friendly_errors_spec.rb
index cda2ef31de..426e3c856d 100644
--- a/spec/bundler/bundler/friendly_errors_spec.rb
+++ b/spec/bundler/bundler/friendly_errors_spec.rb
@@ -2,7 +2,8 @@
require "bundler"
require "bundler/friendly_errors"
-require "cgi"
+require "cgi/escape"
+require "cgi/util" unless defined?(CGI::EscapeExt)
RSpec.describe Bundler, "friendly errors" do
context "with invalid YAML in .gemrc" do
@@ -18,8 +19,8 @@ RSpec.describe Bundler, "friendly errors" do
it "reports a relevant friendly error message" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle :install, env: { "DEBUG" => "true" }
@@ -130,17 +131,13 @@ RSpec.describe Bundler, "friendly errors" do
# Does nothing
end
- context "Java::JavaLang::OutOfMemoryError" do
- module Java
- module JavaLang
- class OutOfMemoryError < StandardError; end
- end
- end
-
+ context "Java::JavaLang::OutOfMemoryError", :jruby_only do
it "Bundler.ui receive error" do
- error = Java::JavaLang::OutOfMemoryError.new
- expect(Bundler.ui).to receive(:error).with(/JVM has run out of memory/)
- Bundler::FriendlyErrors.log_error(error)
+ install_gemfile <<-G, raise_on_error: false, env: { "JRUBY_OPTS" => "-J-Xmx32M" }, artifice: nil
+ source "https://gem.repo1"
+ G
+
+ expect(err).to include("JVM has run out of memory")
end
end
@@ -200,7 +197,7 @@ RSpec.describe Bundler, "friendly errors" do
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/rubygems/rubygems/search?q=Exception+message&type=Issues")
+ expect(Bundler::FriendlyErrors.issues_url(exception)).to eq("https://github.com/ruby/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
@@ -209,7 +206,7 @@ First line of the exception message
Second line of the exception message
END
- expect(Bundler::FriendlyErrors.issues_url(exception)).to eq("https://github.com/rubygems/rubygems/search?q=First+line+of+the+exception+message&type=Issues")
+ expect(Bundler::FriendlyErrors.issues_url(exception)).to eq("https://github.com/ruby/rubygems/search?q=First+line+of+the+exception+message&type=Issues")
end
it "generates the url without colons" do
@@ -218,7 +215,7 @@ Exception ::: with ::: colons :::
END
issues_url = Bundler::FriendlyErrors.issues_url(exception)
expect(issues_url).not_to include("%3A")
- expect(issues_url).to eq("https://github.com/rubygems/rubygems/search?q=#{CGI.escape("Exception with colons ")}&type=Issues")
+ expect(issues_url).to eq("https://github.com/ruby/rubygems/search?q=#{CGI.escape("Exception with colons ")}&type=Issues")
end
it "removes information after - for Errono::EACCES" do
@@ -228,7 +225,7 @@ 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/rubygems/rubygems/search?q=#{CGI.escape("Errno EACCES Permission denied @ dir_s_mkdir ")}&type=Issues")
+ expect(issues_url).to eq("https://github.com/ruby/rubygems/search?q=#{CGI.escape("Errno EACCES Permission denied @ dir_s_mkdir ")}&type=Issues")
end
end
end
diff --git a/spec/bundler/bundler/gem_helper_spec.rb b/spec/bundler/bundler/gem_helper_spec.rb
index 940e5df9de..94f66537d3 100644
--- a/spec/bundler/bundler/gem_helper_spec.rb
+++ b/spec/bundler/bundler/gem_helper_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe Bundler::GemHelper do
before(:each) do
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"
- sys_exec("git config --global init.defaultBranch main")
+ git("config --global init.defaultBranch main")
bundle "gem #{app_name}"
prepare_gemspec(app_gemspec_path)
end
@@ -253,11 +253,11 @@ RSpec.describe Bundler::GemHelper do
end
before do
- 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)
+ git("init", app_path)
+ git("config user.email \"you@example.com\"", app_path)
+ git("config user.name \"name\"", app_path)
+ git("config commit.gpgsign false", app_path)
+ git("config push.default simple", app_path)
# silence messages
allow(Bundler.ui).to receive(:confirm)
@@ -271,13 +271,13 @@ RSpec.describe Bundler::GemHelper do
end
it "when there are uncommitted files" do
- sys_exec("git add .", dir: app_path)
+ git("add .", 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
- sys_exec("git commit -a -m \"initial commit\"", dir: app_path)
+ git("commit -a -m \"initial commit\"", app_path)
expect { Rake.application["release"].invoke }.to raise_error(RuntimeError)
end
end
@@ -286,8 +286,8 @@ RSpec.describe Bundler::GemHelper do
let(:repo) { build_git("foo", bare: true) }
before do
- 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)
+ git("remote add origin #{repo.path}", app_path)
+ git('commit -a -m "initial commit"', app_path)
end
context "on releasing" do
@@ -296,7 +296,7 @@ RSpec.describe Bundler::GemHelper do
mock_confirm_message "Tagged v#{app_version}."
mock_confirm_message "Pushed git commits and release tag."
- sys_exec("git push -u origin main", dir: app_path)
+ git("push -u origin main", app_path)
end
it "calls rubygem_push with proper arguments" do
@@ -314,8 +314,8 @@ RSpec.describe Bundler::GemHelper do
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)
+ git("checkout -b v#{app_version}", app_path)
+ git("push -u origin v#{app_version}", app_path)
expect(subject).to receive(:rubygem_push).with(app_gem_path.to_s)
@@ -323,7 +323,7 @@ RSpec.describe Bundler::GemHelper do
end
it "also works with releasing from a branch not yet pushed" do
- sys_exec("git checkout -b module_function", dir: app_path)
+ git("checkout -b module_function", app_path)
expect(subject).to receive(:rubygem_push).with(app_gem_path.to_s)
@@ -337,7 +337,7 @@ RSpec.describe Bundler::GemHelper do
mock_build_message app_name, app_version
mock_confirm_message "Pushed git commits and release tag."
- sys_exec("git push -u origin main", dir: app_path)
+ git("push -u origin main", app_path)
expect(subject).to receive(:rubygem_push).with(app_gem_path.to_s)
end
@@ -353,7 +353,7 @@ RSpec.describe Bundler::GemHelper do
mock_confirm_message "Tag v#{app_version} has already been created."
expect(subject).to receive(:rubygem_push).with(app_gem_path.to_s)
- sys_exec("git tag -a -m \"Version #{app_version}\" v#{app_version}", dir: app_path)
+ git("tag -a -m \"Version #{app_version}\" v#{app_version}", app_path)
Rake.application["release"].invoke
end
@@ -374,10 +374,10 @@ RSpec.describe Bundler::GemHelper do
end
before do
- 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)
+ git("init", app_path)
+ git("config user.email \"you@example.com\"", app_path)
+ git("config user.name \"name\"", app_path)
+ git("config push.gpgsign simple", app_path)
# silence messages
allow(Bundler.ui).to receive(:confirm)
diff --git a/spec/bundler/bundler/gem_version_promoter_spec.rb b/spec/bundler/bundler/gem_version_promoter_spec.rb
index 917daba95d..0e1b7c9cc8 100644
--- a/spec/bundler/bundler/gem_version_promoter_spec.rb
+++ b/spec/bundler/bundler/gem_version_promoter_spec.rb
@@ -20,13 +20,13 @@ RSpec.describe Bundler::GemVersionPromoter do
end
end
- def build_package(name, version, locked = [])
- Bundler::Resolver::Package.new(name, [], locked_specs: Bundler::SpecSet.new(build_spec(name, version)), unlock: locked)
+ def build_package(name, version, unlock)
+ Bundler::Resolver::Package.new(name, [], locked_specs: Bundler::SpecSet.new(build_spec(name, version)), unlock: unlock)
end
- def sorted_versions(candidates:, current:, name: "foo", locked: [])
+ def sorted_versions(candidates:, current:, unlock: true)
gvp.sort_versions(
- build_package(name, current, locked),
+ build_package("foo", current, unlock),
build_candidates(candidates)
).flatten.map(&:version).map(&:to_s)
end
@@ -127,7 +127,7 @@ RSpec.describe Bundler::GemVersionPromoter do
before { gvp.level = :minor }
it "keeps the current version first" do
- versions = sorted_versions(candidates: %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.1.0 2.0.1], current: "0.3.0", locked: ["bar"])
+ versions = sorted_versions(candidates: %w[0.2.0 0.3.0 0.3.1 0.9.0 1.0.0 2.1.0 2.0.1], current: "0.3.0", unlock: [])
expect(versions.first).to eq("0.3.0")
end
end
diff --git a/spec/bundler/bundler/installer/gem_installer_spec.rb b/spec/bundler/bundler/installer/gem_installer_spec.rb
index ea506c36c8..dbd4e1d2c8 100644
--- a/spec/bundler/bundler/installer/gem_installer_spec.rb
+++ b/spec/bundler/bundler/installer/gem_installer_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe Bundler::GemInstaller do
let(:installer) { instance_double("Installer", definition: definition) }
let(:spec_source) { instance_double("SpecSource") }
let(:spec) { instance_double("Specification", name: "dummy", version: "0.0.1", loaded_from: "dummy", source: spec_source) }
+ let(:base_options) { { force: false, local: false, previous_spec: nil } }
subject { described_class.new(spec, installer) }
@@ -14,7 +15,7 @@ RSpec.describe Bundler::GemInstaller do
it "invokes install method with empty build_args" do
allow(spec_source).to receive(:install).with(
spec,
- { force: false, build_args: [], previous_spec: nil }
+ base_options.merge(build_args: [])
)
subject.install_from_spec
end
@@ -22,13 +23,11 @@ RSpec.describe Bundler::GemInstaller do
context "spec_settings is build option" do
it "invokes install method with build_args" do
- allow(Bundler.settings).to receive(:[]).with(:bin)
- allow(Bundler.settings).to receive(:[]).with(:inline)
- allow(Bundler.settings).to receive(:[]).with(:forget_cli_options)
+ allow(Bundler.settings).to receive(:[])
allow(Bundler.settings).to receive(:[]).with("build.dummy").and_return("--with-dummy-config=dummy")
expect(spec_source).to receive(:install).with(
spec,
- { force: false, build_args: ["--with-dummy-config=dummy"], previous_spec: nil }
+ base_options.merge(build_args: ["--with-dummy-config=dummy"])
)
subject.install_from_spec
end
@@ -36,13 +35,11 @@ RSpec.describe Bundler::GemInstaller do
context "spec_settings is build option with spaces" do
it "invokes install method with build_args" do
- allow(Bundler.settings).to receive(:[]).with(:bin)
- allow(Bundler.settings).to receive(:[]).with(:inline)
- allow(Bundler.settings).to receive(:[]).with(:forget_cli_options)
+ allow(Bundler.settings).to receive(:[])
allow(Bundler.settings).to receive(:[]).with("build.dummy").and_return("--with-dummy-config=dummy --with-another-dummy-config")
expect(spec_source).to receive(:install).with(
spec,
- { force: false, build_args: ["--with-dummy-config=dummy", "--with-another-dummy-config"], previous_spec: nil }
+ base_options.merge(build_args: ["--with-dummy-config=dummy", "--with-another-dummy-config"])
)
subject.install_from_spec
end
diff --git a/spec/bundler/bundler/lockfile_parser_spec.rb b/spec/bundler/bundler/lockfile_parser_spec.rb
index 88932bf009..f38da2c993 100644
--- a/spec/bundler/bundler/lockfile_parser_spec.rb
+++ b/spec/bundler/bundler/lockfile_parser_spec.rb
@@ -111,11 +111,11 @@ RSpec.describe Bundler::LockfileParser do
end
let(:specs) do
[
- Bundler::LazySpecification.new("peiji-san", v("1.2.0"), rb),
- Bundler::LazySpecification.new("rake", v("10.3.2"), rb),
+ Bundler::LazySpecification.new("peiji-san", v("1.2.0"), Gem::Platform::RUBY),
+ Bundler::LazySpecification.new("rake", v("10.3.2"), Gem::Platform::RUBY),
]
end
- let(:platforms) { [rb] }
+ let(:platforms) { [Gem::Platform::RUBY] }
let(:bundler_version) { Gem::Version.new("1.12.0.rc.2") }
let(:ruby_version) { "ruby 2.1.3p242" }
let(:lockfile_path) { Bundler.default_lockfile.relative_path_from(Dir.pwd) }
@@ -138,7 +138,7 @@ RSpec.describe Bundler::LockfileParser do
expect(subject.ruby_version).to eq ruby_version
rake_spec = specs.last
checksums = subject.sources.last.checksum_store.to_lock(specs.last)
- expect(checksums).to eq("#{rake_spec.name_tuple.lock_name} #{rake_checksums.map(&:to_lock).sort.join(",")}")
+ expect(checksums).to eq("#{rake_spec.lock_name} #{rake_checksums.map(&:to_lock).sort.join(",")}")
end
end
diff --git a/spec/bundler/bundler/plugin/events_spec.rb b/spec/bundler/bundler/plugin/events_spec.rb
index 28d70c6fdd..77e5fdb74c 100644
--- a/spec/bundler/bundler/plugin/events_spec.rb
+++ b/spec/bundler/bundler/plugin/events_spec.rb
@@ -2,7 +2,17 @@
RSpec.describe Bundler::Plugin::Events do
context "plugin events" do
- before { Bundler::Plugin::Events.send :reset }
+ before do
+ @old_constants = Bundler::Plugin::Events.constants.map {|name| [name, Bundler::Plugin::Events.const_get(name)] }
+ Bundler::Plugin::Events.send :reset
+ end
+
+ after do
+ Bundler::Plugin::Events.send(:reset)
+ Hash[@old_constants].each do |name, value|
+ Bundler::Plugin::Events.send(:define, name, value)
+ end
+ end
describe "#define" do
it "raises when redefining a constant" do
diff --git a/spec/bundler/bundler/plugin/index_spec.rb b/spec/bundler/bundler/plugin/index_spec.rb
index 5a7047459f..565fc9b088 100644
--- a/spec/bundler/bundler/plugin/index_spec.rb
+++ b/spec/bundler/bundler/plugin/index_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Bundler::Plugin::Index do
before do
allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
- gemfile "source \"#{file_uri_for(gem_repo1)}\""
+ gemfile "source 'https://gem.repo1'"
path = lib_path(plugin_name)
index.register_plugin("new-plugin", path.to_s, [path.join("lib").to_s], commands, sources, hooks)
end
@@ -193,12 +193,4 @@ RSpec.describe Bundler::Plugin::Index do
include_examples "it cleans up"
end
end
-
- describe "readonly disk without home" do
- it "ignores being unable to create temp home dir" do
- expect_any_instance_of(Bundler::Plugin::Index).to receive(:global_index_file).
- and_raise(Bundler::GenericSystemCallError.new("foo", "bar"))
- Bundler::Plugin::Index.new
- end
- end
end
diff --git a/spec/bundler/bundler/plugin/installer_spec.rb b/spec/bundler/bundler/plugin/installer_spec.rb
index ed40029f5a..c200a98afa 100644
--- a/spec/bundler/bundler/plugin/installer_spec.rb
+++ b/spec/bundler/bundler/plugin/installer_spec.rb
@@ -47,6 +47,13 @@ RSpec.describe Bundler::Plugin::Installer do
build_plugin "re-plugin"
build_plugin "ma-plugin"
end
+
+ @previous_ui = Bundler.ui
+ Bundler.ui = Bundler::UI::Silent.new
+ end
+
+ after do
+ Bundler.ui = @previous_ui
end
context "git plugins" do
@@ -57,7 +64,7 @@ RSpec.describe Bundler::Plugin::Installer do
end
let(:result) do
- installer.install(["ga-plugin"], git: file_uri_for(lib_path("ga-plugin")))
+ installer.install(["ga-plugin"], git: lib_path("ga-plugin").to_s)
end
it "returns the installed spec after installing" do
diff --git a/spec/bundler/bundler/plugin_spec.rb b/spec/bundler/bundler/plugin_spec.rb
index f41b4eff3a..e416772a36 100644
--- a/spec/bundler/bundler/plugin_spec.rb
+++ b/spec/bundler/bundler/plugin_spec.rb
@@ -247,7 +247,7 @@ RSpec.describe Bundler::Plugin do
end
it "returns plugin dir in app .bundle path" do
- expect(subject.root).to eq(bundled_app.join(".bundle/plugin"))
+ expect(subject.root).to eq(bundled_app(".bundle/plugin"))
end
end
@@ -257,7 +257,7 @@ RSpec.describe Bundler::Plugin do
end
it "returns plugin dir in global bundle path" do
- expect(subject.root).to eq(home.join(".bundle/plugin"))
+ expect(subject.root).to eq(home(".bundle/plugin"))
end
end
end
@@ -279,6 +279,7 @@ RSpec.describe Bundler::Plugin do
s.write "plugins.rb", code
end
+ @old_constants = Bundler::Plugin::Events.constants.map {|name| [name, Bundler::Plugin::Events.const_get(name)] }
Bundler::Plugin::Events.send(:reset)
Bundler::Plugin::Events.send(:define, :EVENT1, "event-1")
Bundler::Plugin::Events.send(:define, :EVENT2, "event-2")
@@ -291,6 +292,13 @@ RSpec.describe Bundler::Plugin do
allow(index).to receive(:load_paths).with("foo-plugin").and_return([])
end
+ after do
+ Bundler::Plugin::Events.send(:reset)
+ Hash[@old_constants].each do |name, value|
+ Bundler::Plugin::Events.send(:define, name, value)
+ end
+ end
+
let(:code) { <<-RUBY }
Bundler::Plugin::API.hook("event-1") { puts "hook for event 1" }
RUBY
@@ -333,5 +341,28 @@ RSpec.describe Bundler::Plugin do
end.to output("win\n").to_stdout
end
end
+
+ context "the plugin load_path is invalid" do
+ before do
+ allow(index).to receive(:load_paths).with("foo-plugin").
+ and_return(["invalid-file-name1", "invalid-file-name2"])
+ end
+
+ it "outputs a useful warning" do
+ msg =
+ "The following plugin paths don't exist: invalid-file-name1, invalid-file-name2.\n\n" \
+ "This can happen if the plugin was " \
+ "installed with a different version of Ruby that has since been uninstalled.\n\n" \
+ "If you would like to reinstall the plugin, run:\n\n" \
+ "bundler plugin uninstall foo-plugin && bundler plugin install foo-plugin\n\n" \
+ "Continuing without installing plugin foo-plugin.\n"
+
+ expect(Bundler.ui).to receive(:warn).with(msg)
+
+ Plugin.hook(Bundler::Plugin::Events::EVENT1)
+
+ expect(subject.loaded?("foo-plugin")).to be_falsey
+ end
+ end
end
end
diff --git a/spec/bundler/bundler/resolver/candidate_spec.rb b/spec/bundler/bundler/resolver/candidate_spec.rb
index f7b378d32b..aefad3316e 100644
--- a/spec/bundler/bundler/resolver/candidate_spec.rb
+++ b/spec/bundler/bundler/resolver/candidate_spec.rb
@@ -2,20 +2,19 @@
RSpec.describe Bundler::Resolver::Candidate do
it "compares fine" do
- version1 = described_class.new("1.12.5", specs: [Gem::Specification.new("foo", "1.12.5") {|s| s.platform = Gem::Platform::RUBY }])
- version2 = described_class.new("1.12.5") # passing no specs creates a platform specific candidate, so sorts higher
+ version1 = described_class.new("1.12.5", priority: -1)
+ version2 = described_class.new("1.12.5", priority: 1)
- expect(version2 >= version1).to be true
+ expect(version2 > version1).to be true
- expect(version1.generic! == version2.generic!).to be true
- expect(version1.platform_specific! == version2.platform_specific!).to be true
+ version1 = described_class.new("1.12.5")
+ version2 = described_class.new("1.12.5")
- expect(version1.platform_specific! >= version2.generic!).to be true
- expect(version2.platform_specific! >= version1.generic!).to be true
+ expect(version2 == version1).to be true
- version1 = described_class.new("1.12.5", specs: [Gem::Specification.new("foo", "1.12.5") {|s| s.platform = Gem::Platform::RUBY }])
- version2 = described_class.new("1.12.5", specs: [Gem::Specification.new("foo", "1.12.5") {|s| s.platform = Gem::Platform::X64_LINUX }])
+ version1 = described_class.new("1.12.5", priority: 1)
+ version2 = described_class.new("1.12.5", priority: -1)
- expect(version2 >= version1).to be true
+ expect(version2 < version1).to be true
end
end
diff --git a/spec/bundler/bundler/retry_spec.rb b/spec/bundler/bundler/retry_spec.rb
index b893580d72..7481622a96 100644
--- a/spec/bundler/bundler/retry_spec.rb
+++ b/spec/bundler/bundler/retry_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe Bundler::Retry do
end
it "returns the first valid result" do
- jobs = [proc { raise "foo" }, proc { :bar }, proc { raise "foo" }]
+ jobs = [proc { raise "job 1 failed" }, proc { :bar }, proc { raise "job 2 failed" }]
attempts = 0
result = Bundler::Retry.new(nil, nil, 3).attempt do
attempts += 1
@@ -68,7 +68,7 @@ RSpec.describe Bundler::Retry do
it "print error message with newlines" do
allow(Bundler.ui).to receive(:debug?).and_return(false)
expect(Bundler.ui).to receive(:info).with("").twice
- expect(Bundler.ui).to receive(:warn).with(failure_message, false)
+ expect(Bundler.ui).to receive(:warn).with(failure_message, true)
expect do
Bundler::Retry.new("test", [], 1).attempt do
diff --git a/spec/bundler/bundler/ruby_dsl_spec.rb b/spec/bundler/bundler/ruby_dsl_spec.rb
index 384ac4b8b2..45a37c5795 100644
--- a/spec/bundler/bundler/ruby_dsl_spec.rb
+++ b/spec/bundler/bundler/ruby_dsl_spec.rb
@@ -80,7 +80,7 @@ RSpec.describe Bundler::RubyDsl do
context "with two requirements in the same string" do
let(:ruby_version) { ">= 2.0.0, < 3.0" }
it "raises an error" do
- expect { subject }.to raise_error(ArgumentError)
+ expect { subject }.to raise_error(Bundler::InvalidArgumentError)
end
end
@@ -168,7 +168,43 @@ RSpec.describe Bundler::RubyDsl do
let(:file_content) { "ruby-#{version}@gemset\n" }
it "raises an error" do
- expect { subject }.to raise_error(Gem::Requirement::BadRequirementError, "Illformed requirement [\"#{version}@gemset\"]")
+ expect { subject }.to raise_error(Bundler::InvalidArgumentError, "2.0.0@gemset is not a valid requirement on the Ruby version")
+ end
+ end
+
+ context "with a mise.toml file format" do
+ let(:file) { "mise.toml" }
+ let(:ruby_version_arg) { nil }
+ let(:file_content) do
+ <<~TOML
+ [tools]
+ ruby = #{quote}#{version}#{quote}
+ TOML
+ end
+
+ context "with double quotes" do
+ let(:quote) { '"' }
+
+ it_behaves_like "it stores the ruby version"
+ end
+
+ context "with single quotes" do
+ let(:quote) { "'" }
+
+ it_behaves_like "it stores the ruby version"
+ end
+
+ context "with mismatched quotes" do
+ let(:file_content) do
+ <<~TOML
+ [tools]
+ ruby = "#{version}'
+ TOML
+ end
+
+ it "raises an error" do
+ expect { subject }.to raise_error(Bundler::InvalidArgumentError, "= is not a valid requirement on the Ruby version")
+ end
end
end
@@ -197,6 +233,16 @@ RSpec.describe Bundler::RubyDsl do
it_behaves_like "it stores the ruby version"
end
end
+
+ context "when the file does not exist" do
+ let(:ruby_version_file_path) { nil }
+ let(:ruby_version_arg) { nil }
+ let(:file) { "nonexistent.txt" }
+
+ it "raises an error" do
+ expect { subject }.to raise_error(Bundler::GemfileError, /Could not find version file nonexistent.txt/)
+ end
+ end
end
end
end
diff --git a/spec/bundler/bundler/ruby_version_spec.rb b/spec/bundler/bundler/ruby_version_spec.rb
index 39d0571361..b96893cefe 100644
--- a/spec/bundler/bundler/ruby_version_spec.rb
+++ b/spec/bundler/bundler/ruby_version_spec.rb
@@ -100,7 +100,7 @@ RSpec.describe "Bundler::RubyVersion and its subclasses" do
describe "#to_s" do
it "should return info string with the ruby version, patchlevel, engine, and engine version" do
- expect(subject.to_s).to eq("ruby 2.0.0p645 (jruby 2.0.1)")
+ expect(subject.to_s).to eq("ruby 2.0.0 (jruby 2.0.1)")
end
context "no patchlevel" do
@@ -115,7 +115,7 @@ RSpec.describe "Bundler::RubyVersion and its subclasses" do
let(:engine) { "ruby" }
it "should return info string with the ruby version and patchlevel" do
- expect(subject.to_s).to eq("ruby 2.0.0p645")
+ expect(subject.to_s).to eq("ruby 2.0.0")
end
end
@@ -149,12 +149,6 @@ RSpec.describe "Bundler::RubyVersion and its subclasses" do
it_behaves_like "two ruby versions are not equal"
end
- context "the patchlevels do not match" do
- let(:other_patchlevel) { "21" }
-
- it_behaves_like "two ruby versions are not equal"
- end
-
context "the engines do not match" do
let(:other_engine) { "ruby" }
diff --git a/spec/bundler/bundler/rubygems_integration_spec.rb b/spec/bundler/bundler/rubygems_integration_spec.rb
index b6bda9f43e..a2c63a7ca0 100644
--- a/spec/bundler/bundler/rubygems_integration_spec.rb
+++ b/spec/bundler/bundler/rubygems_integration_spec.rb
@@ -11,14 +11,14 @@ RSpec.describe Bundler::RubygemsIntegration do
end
subject { Bundler.rubygems.validate(spec) }
- it "validates with packaging mode disabled" do
- expect(spec).to receive(:validate).with(false)
+ it "validates for resolution" do
+ expect(spec).to receive(:validate_for_resolution)
subject
end
context "with an invalid spec" do
before do
- expect(spec).to receive(:validate).with(false).
+ expect(spec).to receive(:validate_for_resolution).
and_raise(Gem::InvalidSpecificationException.new("TODO is not an author"))
end
@@ -32,7 +32,6 @@ RSpec.describe Bundler::RubygemsIntegration do
describe "#download_gem" do
let(:bundler_retry) { double(Bundler::Retry) }
- let(:uri) { Gem::URI.parse("https://foo.bar") }
let(:cache_dir) { "#{Gem.path.first}/cache" }
let(:spec) do
spec = Gem::Specification.new("Foo", Gem::Version.new("2.5.2"))
@@ -41,13 +40,47 @@ RSpec.describe Bundler::RubygemsIntegration do
end
let(:fetcher) { double("gem_remote_fetcher") }
- it "successfully downloads gem with retries" do
- 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(:cache_update_path)
+ context "when uri is public" do
+ let(:uri) { Gem::URI.parse("https://foo.bar") }
- Bundler.rubygems.download_gem(spec, uri, cache_dir, fetcher)
+ it "successfully downloads gem with retries" do
+ 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(:cache_update_path)
+
+ Bundler.rubygems.download_gem(spec, uri, cache_dir, fetcher)
+ end
+ end
+
+ context "when uri contains userinfo part" do
+ let(:uri) { Gem::URI.parse("https://#{userinfo}@foo.bar") }
+
+ context "with user and password" do
+ let(:userinfo) { "user:password" }
+
+ it "successfully downloads gem with retries with filtered log" do
+ expect(Bundler::Retry).to receive(:new).with("download gem from https://user:REDACTED@foo.bar/").
+ and_return(bundler_retry)
+ expect(bundler_retry).to receive(:attempts).and_yield
+ expect(fetcher).to receive(:cache_update_path)
+
+ Bundler.rubygems.download_gem(spec, uri, cache_dir, fetcher)
+ end
+ end
+
+ context "with token [as user]" do
+ let(:userinfo) { "token" }
+
+ it "successfully downloads gem with retries with filtered log" do
+ expect(Bundler::Retry).to receive(:new).with("download gem from https://REDACTED@foo.bar/").
+ and_return(bundler_retry)
+ expect(bundler_retry).to receive(:attempts).and_yield
+ expect(fetcher).to receive(:cache_update_path)
+
+ Bundler.rubygems.download_gem(spec, uri, cache_dir, fetcher)
+ end
+ end
end
end
diff --git a/spec/bundler/bundler/settings_spec.rb b/spec/bundler/bundler/settings_spec.rb
index 768372c608..592db81e9b 100644
--- a/spec/bundler/bundler/settings_spec.rb
+++ b/spec/bundler/bundler/settings_spec.rb
@@ -121,12 +121,13 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow
end
end
- context "when it's not possible to write to the file" do
+ context "when it's not possible to create the settings directory" do
it "raises an PermissionError with explanation" do
- expect(::Bundler::FileUtils).to receive(:mkdir_p).with(settings.send(:local_config_file).dirname).
- and_raise(Errno::EACCES)
+ settings_dir = settings.send(:local_config_file).dirname
+ expect(::Bundler::FileUtils).to receive(:mkdir_p).with(settings_dir).
+ and_raise(Errno::EACCES.new(settings_dir.to_s))
expect { settings.set_local :frozen, "1" }.
- to raise_error(Bundler::PermissionError, /config/)
+ to raise_error(Bundler::PermissionError, /#{settings_dir}/)
end
end
end
@@ -164,12 +165,13 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow
end
describe "#set_global" do
- context "when it's not possible to write to the file" do
+ context "when it's not possible to write to create the settings directory" do
it "raises an PermissionError with explanation" do
- expect(::Bundler::FileUtils).to receive(:mkdir_p).with(settings.send(:global_config_file).dirname).
- and_raise(Errno::EACCES)
+ settings_dir = settings.send(:global_config_file).dirname
+ expect(::Bundler::FileUtils).to receive(:mkdir_p).with(settings_dir).
+ and_raise(Errno::EACCES.new(settings_dir.to_s))
expect { settings.set_global(:frozen, "1") }.
- to raise_error(Bundler::PermissionError, %r{\.bundle/config})
+ to raise_error(Bundler::PermissionError, /#{settings_dir}/)
end
end
end
@@ -198,7 +200,7 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow
end
context "with a configured mirror" do
- let(:mirror_uri) { Gem::URI("https://rubygems-mirror.org/") }
+ let(:mirror_uri) { Gem::URI("https://example-mirror.rubygems.org/") }
before { settings.set_local "mirror.https://rubygems.org/", mirror_uri.to_s }
@@ -275,12 +277,12 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow
end
it "normalizes HTTP URIs in mirror configuration" do
- settings.set_local "mirror.http://rubygems.org", "http://rubygems-mirror.org"
+ settings.set_local "mirror.http://rubygems.org", "http://example-mirror.rubygems.org"
expect(settings.all).to include("mirror.http://rubygems.org/")
end
it "normalizes HTTPS URIs in mirror configuration" do
- settings.set_local "mirror.https://rubygems.org", "http://rubygems-mirror.org"
+ settings.set_local "mirror.https://rubygems.org", "http://example-mirror.rubygems.org"
expect(settings.all).to include("mirror.https://rubygems.org/")
end
@@ -295,9 +297,9 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow
end
it "reads older keys without trailing slashes" do
- settings.set_local "mirror.https://rubygems.org", "http://rubygems-mirror.org"
+ settings.set_local "mirror.https://rubygems.org", "http://example-mirror.rubygems.org"
expect(settings.mirror_for("https://rubygems.org/")).to eq(
- Gem::URI("http://rubygems-mirror.org/")
+ Gem::URI("http://example-mirror.rubygems.org/")
)
end
@@ -316,13 +318,13 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow
let(:settings) { described_class.new(bundled_app(".bundle")) }
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")
+ config("BUNDLE_MY__PERSONAL.MYRACK" => "~/Work/git/myrack")
+ expect(settings["my.personal.myrack"]).to eq("~/Work/git/myrack")
end
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")
+ config("BUNDLE_MIRROR__HTTPS://RUBYGEMS.ORG" => "http://example-mirror.rubygems.org")
+ expect(settings["mirror.https://rubygems.org/"]).to eq("http://example-mirror.rubygems.org")
end
it "ignores commented out keys" do
@@ -345,8 +347,8 @@ that would suck --ehhh=oh geez it looks like i might have broken bundler somehow
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")
+ config("BUNDLE_MIRROR__HTTPS://RUBYGEMS__ORG/" => "http://example-mirror.rubygems.org")
+ expect(settings["mirror.https://rubygems.org/"]).to eq("http://example-mirror.rubygems.org")
end
end
end
diff --git a/spec/bundler/bundler/shared_helpers_spec.rb b/spec/bundler/bundler/shared_helpers_spec.rb
index 918f73b337..c93c3e9814 100644
--- a/spec/bundler/bundler/shared_helpers_spec.rb
+++ b/spec/bundler/bundler/shared_helpers_spec.rb
@@ -59,7 +59,7 @@ RSpec.describe Bundler::SharedHelpers do
before { allow(subject).to receive(:default_gemfile).and_return(gemfile_path) }
- it "returns the lock file path" do
+ it "returns the lockfile path" do
expect(subject.default_lockfile).to eq(expected_lockfile_path)
end
end
@@ -159,7 +159,7 @@ RSpec.describe Bundler::SharedHelpers do
let(:pwd_stub) { nil }
it "returns the current absolute path" do
- expect(subject.pwd).to eq(source_root)
+ expect(subject.pwd).to eq(source_root.to_s)
end
end
@@ -258,8 +258,7 @@ RSpec.describe Bundler::SharedHelpers do
it "ensures bundler's ruby version lib path is in ENV['RUBYLIB']" do
subject.set_bundle_environment
- paths = (ENV["RUBYLIB"]).split(File::PATH_SEPARATOR)
- expect(paths).to include(ruby_lib_path)
+ expect(rubylib).to include(ruby_lib_path)
end
end
@@ -276,8 +275,7 @@ RSpec.describe Bundler::SharedHelpers do
subject.set_bundle_environment
- paths = (ENV["RUBYLIB"]).split(File::PATH_SEPARATOR)
- expect(paths.count(RbConfig::CONFIG["rubylibdir"])).to eq(0)
+ expect(rubylib.count(RbConfig::CONFIG["rubylibdir"])).to eq(0)
end
it "exits if bundle path contains the unix-like path separator" do
@@ -356,7 +354,7 @@ RSpec.describe Bundler::SharedHelpers do
it "ENV['PATH'] should only contain one instance of bundle bin path" do
subject.set_bundle_environment
- paths = (ENV["PATH"]).split(File::PATH_SEPARATOR)
+ paths = ENV["PATH"].split(File::PATH_SEPARATOR)
expect(paths.count(bundle_path)).to eq(1)
end
end
@@ -425,7 +423,7 @@ RSpec.describe Bundler::SharedHelpers do
it "sets BUNDLE_BIN_PATH to the bundle executable file" do
subject.set_bundle_environment
bin_path = ENV["BUNDLE_BIN_PATH"]
- expect(bin_path).to eq(bindir.join("bundle").to_s)
+ expect(bin_path).to eq(exedir.join("bundle").to_s)
expect(File.exist?(bin_path)).to be true
end
end
@@ -441,8 +439,7 @@ RSpec.describe Bundler::SharedHelpers do
it "ENV['RUBYLIB'] should only contain one instance of bundler's ruby version lib path" do
subject.set_bundle_environment
- paths = (ENV["RUBYLIB"]).split(File::PATH_SEPARATOR)
- expect(paths.count(ruby_lib_path)).to eq(1)
+ expect(rubylib.count(ruby_lib_path)).to eq(1)
end
end
end
@@ -458,7 +455,7 @@ RSpec.describe Bundler::SharedHelpers do
end
context "system throws Errno::EACESS" do
- let(:file_op_block) { proc {|_path| raise Errno::EACCES } }
+ let(:file_op_block) { proc {|_path| raise Errno::EACCES.new("/path") } }
it "raises a PermissionError" do
expect { subject.filesystem_access("/path", &file_op_block) }.to raise_error(
@@ -513,39 +510,9 @@ RSpec.describe Bundler::SharedHelpers do
it "raises a GenericSystemCallError" do
expect { subject.filesystem_access("/path", &file_op_block) }.to raise_error(
- Bundler::GenericSystemCallError, /error accessing.+underlying.+Shields down/m
+ Bundler::GenericSystemCallError, /error creating.+underlying.+Shields down/m
)
end
end
end
-
- describe "#major_deprecation" do
- before { allow(Bundler).to receive(:bundler_major_version).and_return(37) }
- before { allow(Bundler.ui).to receive(:warn) }
-
- it "prints and raises nothing below the deprecated major version" do
- subject.major_deprecation(38, "Message")
- subject.major_deprecation(39, "Message", removed_message: "Removal", print_caller_location: true)
- expect(Bundler.ui).not_to have_received(:warn)
- end
-
- it "prints but does not raise _at_ the deprecated major version" do
- subject.major_deprecation(37, "Message")
- subject.major_deprecation(37, "Message", removed_message: "Removal")
- expect(Bundler.ui).to have_received(:warn).with("[DEPRECATED] Message").twice
-
- subject.major_deprecation(37, "Message", print_caller_location: true)
- expect(Bundler.ui).to have_received(:warn).
- with(a_string_matching(/^\[DEPRECATED\] Message \(called at .*:\d+\)$/))
- end
-
- it "raises the appropriate errors when _past_ the deprecated major version" do
- expect { subject.major_deprecation(36, "Message") }.
- to raise_error(Bundler::DeprecatedError, "[REMOVED] Message")
- expect { subject.major_deprecation(36, "Message", removed_message: "Removal") }.
- to raise_error(Bundler::DeprecatedError, "[REMOVED] Removal")
- expect { subject.major_deprecation(35, "Message", removed_message: "Removal", print_caller_location: true) }.
- to raise_error(Bundler::DeprecatedError, /^\[REMOVED\] Removal \(called at .*:\d+\)$/)
- end
- end
end
diff --git a/spec/bundler/bundler/source/git/git_proxy_spec.rb b/spec/bundler/bundler/source/git/git_proxy_spec.rb
index f7c883eed4..b2b7ab5c54 100644
--- a/spec/bundler/bundler/source/git/git_proxy_spec.rb
+++ b/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/rubygems/rubygems.git" }
+ let(:uri) { "https://github.com/ruby/rubygems.git" }
let(:ref) { nil }
let(:branch) { nil }
let(:tag) { nil }
@@ -64,7 +64,7 @@ RSpec.describe Bundler::Source::Git::GitProxy do
it "adds username and password to URI" do
Bundler.settings.temporary(uri => "u:p") do
allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0")
- expect(git_proxy).to receive(:capture).with([*base_clone_args, "--", "https://u:p@github.com/rubygems/rubygems.git", path.to_s], nil).and_return(["", "", clone_result])
+ expect(git_proxy).to receive(:capture).with([*base_clone_args, "--", "https://u:p@github.com/ruby/rubygems.git", path.to_s], nil).and_return(["", "", clone_result])
subject.checkout
end
end
@@ -72,13 +72,13 @@ RSpec.describe Bundler::Source::Git::GitProxy do
it "adds username and password to URI for host" do
Bundler.settings.temporary("github.com" => "u:p") do
allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0")
- expect(git_proxy).to receive(:capture).with([*base_clone_args, "--", "https://u:p@github.com/rubygems/rubygems.git", path.to_s], nil).and_return(["", "", clone_result])
+ expect(git_proxy).to receive(:capture).with([*base_clone_args, "--", "https://u:p@github.com/ruby/rubygems.git", path.to_s], nil).and_return(["", "", clone_result])
subject.checkout
end
end
it "does not add username and password to mismatched URI" do
- Bundler.settings.temporary("https://u:p@github.com/rubygems/rubygems-mismatch.git" => "u:p") do
+ Bundler.settings.temporary("https://u:p@github.com/ruby/rubygems-mismatch.git" => "u:p") do
allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0")
expect(git_proxy).to receive(:capture).with([*base_clone_args, "--", uri, path.to_s], nil).and_return(["", "", clone_result])
subject.checkout
@@ -87,7 +87,7 @@ RSpec.describe Bundler::Source::Git::GitProxy do
it "keeps original userinfo" do
Bundler.settings.temporary("github.com" => "u:p") do
- original = "https://orig:info@github.com/rubygems/rubygems.git"
+ original = "https://orig:info@github.com/ruby/rubygems.git"
git_proxy = described_class.new(Pathname("path"), original, options)
allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0")
expect(git_proxy).to receive(:capture).with([*base_clone_args, "--", original, path.to_s], nil).and_return(["", "", clone_result])
@@ -199,7 +199,7 @@ RSpec.describe Bundler::Source::Git::GitProxy do
end
context "URI is HTTP" do
- let(:uri) { "http://github.com/rubygems/rubygems.git" }
+ let(:uri) { "http://github.com/ruby/rubygems.git" }
let(:without_depth_arguments) { ["clone", "--bare", "--no-hardlinks", "--quiet", "--no-tags", "--single-branch"] }
let(:fail_clone_result) { double(Process::Status, success?: false) }
@@ -211,4 +211,127 @@ RSpec.describe Bundler::Source::Git::GitProxy do
subject.checkout
end
end
+
+ describe "#installed_to?" do
+ let(:destination) { "install/dir" }
+ let(:destination_dir_exists) { true }
+ let(:children) { ["gem.gemspec", "README.me", ".git", "Rakefile"] }
+
+ before do
+ allow(Dir).to receive(:exist?).with(destination).and_return(destination_dir_exists)
+ allow(Dir).to receive(:children).with(destination).and_return(children)
+ end
+
+ context "when destination dir exists with children other than just .git" do
+ it "returns true" do
+ expect(git_proxy.installed_to?(destination)).to be true
+ end
+ end
+
+ context "when destination dir does not exist" do
+ let(:destination_dir_exists) { false }
+
+ it "returns false" do
+ expect(git_proxy.installed_to?(destination)).to be false
+ end
+ end
+
+ context "when destination dir is empty" do
+ let(:children) { [] }
+
+ it "returns false" do
+ expect(git_proxy.installed_to?(destination)).to be false
+ end
+ end
+
+ context "when destination dir has only .git directory" do
+ let(:children) { [".git"] }
+
+ it "returns false" do
+ expect(git_proxy.installed_to?(destination)).to be false
+ end
+ end
+ end
+
+ describe "#checkout" do
+ context "when the repository isn't cloned" do
+ before do
+ allow(path).to receive(:exist?).and_return(false)
+ end
+
+ it "clones the repository" do
+ allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0")
+ expect(git_proxy).to receive(:capture).with([*base_clone_args, "--", uri, path.to_s], nil).and_return(["", "", clone_result])
+ subject.checkout
+ end
+ end
+
+ context "when the repository is cloned" do
+ before do
+ allow(path).to receive(:exist?).and_return(true)
+ end
+
+ context "with a locked revision" do
+ let(:revision) { Digest::SHA1.hexdigest("ruby") }
+
+ context "when the revision exists locally" do
+ it "uses the cached revision" do
+ allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0")
+ expect(git_proxy).to receive(:git).with("cat-file", "-e", revision, dir: path).and_return(true)
+ subject.checkout
+ end
+ end
+
+ context "when the revision doesn't exist locally" do
+ it "fetches the specific revision" do
+ allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0")
+ expect(git_proxy).to receive(:git).with("cat-file", "-e", revision, dir: path).and_raise(Bundler::GitError)
+ expect(git_proxy).to receive(:capture).with(["fetch", "--force", "--quiet", "--no-tags", "--depth", "1", "--", uri, "#{revision}:refs/#{revision}-sha"], path).and_return(["", "", clone_result])
+ subject.checkout
+ end
+ end
+ end
+
+ context "with no explicit ref" do
+ it "fetches the HEAD revision" do
+ parsed_revision = Digest::SHA1.hexdigest("ruby")
+ allow(git_proxy).to receive(:git_local).with("rev-parse", "--abbrev-ref", "HEAD", dir: path).and_return(parsed_revision)
+ allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0")
+ expect(git_proxy).to receive(:capture).with(["fetch", "--force", "--quiet", "--no-tags", "--depth", "1", "--", uri, "refs/heads/#{parsed_revision}:refs/heads/#{parsed_revision}"], path).and_return(["", "", clone_result])
+ subject.checkout
+ end
+ end
+
+ context "with a commit ref" do
+ let(:ref) { Digest::SHA1.hexdigest("ruby") }
+
+ context "when the revision exists locally" do
+ it "uses the cached revision" do
+ allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0")
+ expect(git_proxy).to receive(:git).with("cat-file", "-e", ref, dir: path).and_return(true)
+ subject.checkout
+ end
+ end
+
+ context "when the revision doesn't exist locally" do
+ it "fetches the specific revision" do
+ allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0")
+ expect(git_proxy).to receive(:git).with("cat-file", "-e", ref, dir: path).and_raise(Bundler::GitError)
+ expect(git_proxy).to receive(:capture).with(["fetch", "--force", "--quiet", "--no-tags", "--depth", "1", "--", uri, "#{ref}:refs/#{ref}-sha"], path).and_return(["", "", clone_result])
+ subject.checkout
+ end
+ end
+ end
+
+ context "with a non-commit ref" do
+ let(:ref) { "HEAD" }
+
+ it "fetches all revisions" do
+ allow(git_proxy).to receive(:git_local).with("--version").and_return("git version 2.14.0")
+ expect(git_proxy).to receive(:capture).with(["fetch", "--force", "--quiet", "--no-tags", "--", uri, "refs/*:refs/*"], path).and_return(["", "", clone_result])
+ subject.checkout
+ end
+ end
+ end
+ end
end
diff --git a/spec/bundler/bundler/source/git_spec.rb b/spec/bundler/bundler/source/git_spec.rb
index feef54bbf4..14e91c6bdc 100644
--- a/spec/bundler/bundler/source/git_spec.rb
+++ b/spec/bundler/bundler/source/git_spec.rb
@@ -70,4 +70,54 @@ RSpec.describe Bundler::Source::Git do
end
end
end
+
+ describe "#locked_revision_checked_out?" do
+ let(:revision) { "abc" }
+ let(:git_proxy_revision) { revision }
+ let(:git_proxy_installed) { true }
+ let(:git_proxy) { subject.send(:git_proxy) }
+ let(:options) do
+ {
+ "uri" => uri,
+ "revision" => revision,
+ }
+ end
+
+ before do
+ allow(git_proxy).to receive(:revision).and_return(git_proxy_revision)
+ allow(git_proxy).to receive(:installed_to?).with(subject.install_path).and_return(git_proxy_installed)
+ end
+
+ context "when the locked revision is checked out" do
+ it "returns true" do
+ expect(subject.send(:locked_revision_checked_out?)).to be true
+ end
+ end
+
+ context "when no revision is provided" do
+ let(:options) do
+ { "uri" => uri }
+ end
+
+ it "returns falsey value" do
+ expect(subject.send(:locked_revision_checked_out?)).to be_falsey
+ end
+ end
+
+ context "when the git proxy revision is different than the git revision" do
+ let(:git_proxy_revision) { revision.next }
+
+ it "returns falsey value" do
+ expect(subject.send(:locked_revision_checked_out?)).to be_falsey
+ end
+ end
+
+ context "when the gem hasn't been installed" do
+ let(:git_proxy_installed) { false }
+
+ it "returns falsey value" do
+ expect(subject.send(:locked_revision_checked_out?)).to be_falsey
+ end
+ end
+ end
end
diff --git a/spec/bundler/bundler/source/rubygems/remote_spec.rb b/spec/bundler/bundler/source/rubygems/remote_spec.rb
index 56f3bee459..f2214ca8fe 100644
--- a/spec/bundler/bundler/source/rubygems/remote_spec.rb
+++ b/spec/bundler/bundler/source/rubygems/remote_spec.rb
@@ -106,8 +106,8 @@ RSpec.describe Bundler::Source::Rubygems::Remote do
context "when a mirror with inline credentials is configured for the URI" do
let(:uri) { Gem::URI("https://rubygems.org/") }
- let(:mirror_uri_with_auth) { Gem::URI("https://username:password@rubygems-mirror.org/") }
- let(:mirror_uri_no_auth) { Gem::URI("https://rubygems-mirror.org/") }
+ let(:mirror_uri_with_auth) { Gem::URI("https://username:password@example-mirror.rubygems.org/") }
+ let(:mirror_uri_no_auth) { Gem::URI("https://example-mirror.rubygems.org/") }
before { Bundler.settings.temporary("mirror.https://rubygems.org/" => mirror_uri_with_auth.to_s) }
@@ -132,8 +132,8 @@ RSpec.describe Bundler::Source::Rubygems::Remote do
context "when a mirror with configured credentials is configured for the URI" do
let(:uri) { Gem::URI("https://rubygems.org/") }
- let(:mirror_uri_with_auth) { Gem::URI("https://#{credentials}@rubygems-mirror.org/") }
- let(:mirror_uri_no_auth) { Gem::URI("https://rubygems-mirror.org/") }
+ let(:mirror_uri_with_auth) { Gem::URI("https://#{credentials}@example-mirror.rubygems.org/") }
+ let(:mirror_uri_no_auth) { Gem::URI("https://example-mirror.rubygems.org/") }
before do
Bundler.settings.temporary("mirror.https://rubygems.org/" => mirror_uri_no_auth.to_s)
diff --git a/spec/bundler/bundler/source/rubygems_spec.rb b/spec/bundler/bundler/source/rubygems_spec.rb
index 884fa81046..dde4e4ed47 100644
--- a/spec/bundler/bundler/source/rubygems_spec.rb
+++ b/spec/bundler/bundler/source/rubygems_spec.rb
@@ -44,4 +44,22 @@ RSpec.describe Bundler::Source::Rubygems do
end
end
end
+
+ describe "log debug information" do
+ it "log the time spent downloading and installing a gem" do
+ build_repo2 do
+ build_gem "warning"
+ end
+
+ gemfile_content = <<~G
+ source "https://gem.repo2"
+ gem "warning"
+ G
+
+ stdout = install_gemfile(gemfile_content, env: { "DEBUG" => "1" })
+
+ expect(stdout).to match(/Downloaded warning in: \d+\.\d+s/)
+ expect(stdout).to match(/Installed warning in: \d+\.\d+s/)
+ end
+ end
end
diff --git a/spec/bundler/bundler/source_list_spec.rb b/spec/bundler/bundler/source_list_spec.rb
index 13453cb2a3..6e0be6c92f 100644
--- a/spec/bundler/bundler/source_list_spec.rb
+++ b/spec/bundler/bundler/source_list_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe Bundler::SourceList do
subject(:source_list) { Bundler::SourceList.new }
- let(:rubygems_aggregate) { Bundler::Source::Rubygems.new }
+ let(:global_rubygems_source) { Bundler::Source::Rubygems.new }
let(:metadata_source) { Bundler::Source::Metadata.new }
describe "adding sources" do
@@ -118,11 +118,11 @@ RSpec.describe Bundler::SourceList do
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
+ it "returns the global 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
+ it "adds the provided remote to the beginning of the global source" do
source_list.add_global_rubygems_remote("https://othersource.org")
expect(returned_source.remotes).to eq [
Gem::URI("https://othersource.org/"),
@@ -156,21 +156,21 @@ RSpec.describe Bundler::SourceList do
end
describe "#all_sources" do
- it "includes the aggregate rubygems source when rubygems sources have been added" do
+ it "includes the global rubygems source when rubygems sources have been added" do
source_list.add_git_source("uri" => "git://host/path.git")
source_list.add_rubygems_source("remotes" => ["https://rubygems.org"])
source_list.add_path_source("path" => "/path/to/gem")
source_list.add_plugin_source("new_source", "uri" => "https://some.url/a")
- expect(source_list.all_sources).to include rubygems_aggregate
+ expect(source_list.all_sources).to include global_rubygems_source
end
- it "includes the aggregate rubygems source when no rubygems sources have been added" do
+ it "includes the global rubygems source when no rubygems sources have been added" do
source_list.add_git_source("uri" => "git://host/path.git")
source_list.add_path_source("path" => "/path/to/gem")
source_list.add_plugin_source("new_source", "uri" => "https://some.url/a")
- expect(source_list.all_sources).to include rubygems_aggregate
+ expect(source_list.all_sources).to include global_rubygems_source
end
it "returns sources of the same type in the reverse order that they were added" do
@@ -204,7 +204,7 @@ RSpec.describe Bundler::SourceList do
Bundler::Source::Rubygems.new("remotes" => ["https://third-rubygems.org"]),
Bundler::Source::Rubygems.new("remotes" => ["https://fourth-rubygems.org"]),
Bundler::Source::Rubygems.new("remotes" => ["https://fifth-rubygems.org"]),
- rubygems_aggregate,
+ global_rubygems_source,
metadata_source,
]
end
@@ -297,19 +297,19 @@ RSpec.describe Bundler::SourceList do
end
describe "#rubygems_sources" do
- it "includes the aggregate rubygems source when rubygems sources have been added" do
+ it "includes the global rubygems source when rubygems sources have been added" do
source_list.add_git_source("uri" => "git://host/path.git")
source_list.add_rubygems_source("remotes" => ["https://rubygems.org"])
source_list.add_path_source("path" => "/path/to/gem")
- expect(source_list.rubygems_sources).to include rubygems_aggregate
+ expect(source_list.rubygems_sources).to include global_rubygems_source
end
- it "returns only the aggregate rubygems source when no rubygems sources have been added" do
+ it "returns only the global rubygems source when no rubygems sources have been added" do
source_list.add_git_source("uri" => "git://host/path.git")
source_list.add_path_source("path" => "/path/to/gem")
- expect(source_list.rubygems_sources).to eq [rubygems_aggregate]
+ expect(source_list.rubygems_sources).to eq [global_rubygems_source]
end
it "returns rubygems sources in the reverse order that they were added" do
@@ -331,7 +331,7 @@ RSpec.describe Bundler::SourceList do
Bundler::Source::Rubygems.new("remotes" => ["https://third-rubygems.org"]),
Bundler::Source::Rubygems.new("remotes" => ["https://fourth-rubygems.org"]),
Bundler::Source::Rubygems.new("remotes" => ["https://fifth-rubygems.org"]),
- rubygems_aggregate,
+ global_rubygems_source,
]
end
end
diff --git a/spec/bundler/bundler/source_spec.rb b/spec/bundler/bundler/source_spec.rb
index 3b49c37431..01b57ce9e8 100644
--- a/spec/bundler/bundler/source_spec.rb
+++ b/spec/bundler/bundler/source_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe Bundler::Source do
end
describe "#version_message" do
- let(:spec) { double(:spec, name: "nokogiri", version: ">= 1.6", platform: rb) }
+ let(:spec) { double(:spec, name: "nokogiri", version: ">= 1.6", platform: Gem::Platform::RUBY) }
shared_examples_for "the lockfile specs are not relevant" do
it "should return a string with the spec name and version" do
@@ -70,7 +70,7 @@ RSpec.describe Bundler::Source do
end
context "with a more recent version" do
- let(:spec) { double(:spec, name: "nokogiri", version: "1.6.1", platform: rb) }
+ let(:spec) { double(:spec, name: "nokogiri", version: "1.6.1", platform: Gem::Platform::RUBY) }
let(:locked_gem) { double(:locked_gem, name: "nokogiri", version: "1.7.0") }
context "with color", :no_color_tty do
@@ -97,7 +97,7 @@ RSpec.describe Bundler::Source do
end
context "with an older version" do
- let(:spec) { double(:spec, name: "nokogiri", version: "1.7.1", platform: rb) }
+ let(:spec) { double(:spec, name: "nokogiri", version: "1.7.1", platform: Gem::Platform::RUBY) }
let(:locked_gem) { double(:locked_gem, name: "nokogiri", version: "1.7.0") }
context "with color", :no_color_tty do
diff --git a/spec/bundler/bundler/specifications/foo.gemspec b/spec/bundler/bundler/specifications/foo.gemspec
index 46eb068cd1..19b7724e81 100644
--- a/spec/bundler/bundler/specifications/foo.gemspec
+++ b/spec/bundler/bundler/specifications/foo.gemspec
@@ -8,6 +8,6 @@ Gem::Specification.new do |s|
s.version = "1.0.0"
s.loaded_from = __FILE__
s.extensions = "ext/foo"
- s.required_ruby_version = ">= 3.0.0"
+ s.required_ruby_version = ">= 3.2.0"
end
# rubocop:enable Style/FrozenStringLiteralComment
diff --git a/spec/bundler/bundler/stub_specification_spec.rb b/spec/bundler/bundler/stub_specification_spec.rb
index dae9f3cfba..beb966b3ce 100644
--- a/spec/bundler/bundler/stub_specification_spec.rb
+++ b/spec/bundler/bundler/stub_specification_spec.rb
@@ -55,4 +55,24 @@ RSpec.describe Bundler::StubSpecification do
expect(stub.missing_extensions?).to be true
end
end
+
+ describe "#activated?" do
+ it "returns true after activation" do
+ stub = described_class.from_stub(with_bundler_stub_spec)
+
+ expect(stub.activated?).to be_falsey
+ stub.activated = true
+ expect(stub.activated?).to be true
+ end
+
+ it "returns true after activation if the underlying stub is a `Gem::StubSpecification`" do
+ spec_path = File.join(File.dirname(__FILE__), "specifications", "foo.gemspec")
+ gem_stub = Gem::StubSpecification.new(spec_path, File.dirname(__FILE__),"","")
+ stub = described_class.from_stub(gem_stub)
+
+ expect(stub.activated?).to be_falsey
+ stub.activated = true
+ expect(stub.activated?).to be true
+ end
+ end
end
diff --git a/spec/bundler/bundler/ui/shell_spec.rb b/spec/bundler/bundler/ui/shell_spec.rb
index 15120a8a41..83f147191e 100644
--- a/spec/bundler/bundler/ui/shell_spec.rb
+++ b/spec/bundler/bundler/ui/shell_spec.rb
@@ -10,6 +10,13 @@ RSpec.describe Bundler::UI::Shell do
it "prints to stdout" do
expect { subject.info("info") }.to output("info\n").to_stdout
end
+
+ context "when output_stream is :stderr" do
+ before { subject.output_stream = :stderr }
+ it "prints to stderr" do
+ expect { subject.info("info") }.to output("info\n").to_stderr
+ end
+ end
end
describe "#confirm" do
@@ -17,19 +24,36 @@ RSpec.describe Bundler::UI::Shell do
it "prints to stdout" do
expect { subject.confirm("confirm") }.to output("confirm\n").to_stdout
end
+
+ context "when output_stream is :stderr" do
+ before { subject.output_stream = :stderr }
+ it "prints to stderr" do
+ expect { subject.confirm("confirm") }.to output("confirm\n").to_stderr
+ end
+ end
end
describe "#warn" do
before { subject.level = "warn" }
- it "prints to stderr" do
+ it "prints to stderr, implicitly adding a newline" do
expect { subject.warn("warning") }.to output("warning\n").to_stderr
end
+ it "can be told not to emit a newline" do
+ expect { subject.warn("warning", false) }.to output("warning").to_stderr
+ end
end
describe "#debug" do
it "prints to stdout" do
expect { subject.debug("debug") }.to output("debug\n").to_stdout
end
+
+ context "when output_stream is :stderr" do
+ before { subject.output_stream = :stderr }
+ it "prints to stderr" do
+ expect { subject.debug("debug") }.to output("debug\n").to_stderr
+ end
+ end
end
describe "#error" do
@@ -57,4 +81,32 @@ RSpec.describe Bundler::UI::Shell do
end
end
end
+
+ describe "threads" do
+ it "is thread safe when using with_level" do
+ stop_thr1 = false
+ stop_thr2 = false
+
+ expect(subject.level).to eq("debug")
+
+ thr1 = Thread.new do
+ subject.silence do
+ sleep(0.1) until stop_thr1
+ end
+
+ stop_thr2 = true
+ end
+
+ thr2 = Thread.new do
+ subject.silence do
+ stop_thr1 = true
+ sleep(0.1) until stop_thr2
+ end
+ end
+
+ [thr1, thr2].each(&:join)
+
+ expect(subject.level).to eq("debug")
+ end
+ end
end
diff --git a/spec/bundler/bundler/uri_credentials_filter_spec.rb b/spec/bundler/bundler/uri_credentials_filter_spec.rb
index ed24744a1c..641f0addb4 100644
--- a/spec/bundler/bundler/uri_credentials_filter_spec.rb
+++ b/spec/bundler/bundler/uri_credentials_filter_spec.rb
@@ -31,6 +31,16 @@ RSpec.describe Bundler::URICredentialsFilter do
it_behaves_like "original type of uri is maintained"
end
+
+ context "specified without empty username" do
+ let(:credentials) { "oauth_token@" }
+
+ it "returns the uri without the oauth token" do
+ expect(subject.credential_filtered_uri(uri).to_s).to eq(Gem::URI("https://github.com/company/private-repo").to_s)
+ end
+
+ it_behaves_like "original type of uri is maintained"
+ end
end
context "authentication using login credentials" do
diff --git a/spec/bundler/bundler/uri_normalizer_spec.rb b/spec/bundler/bundler/uri_normalizer_spec.rb
new file mode 100644
index 0000000000..1308e86014
--- /dev/null
+++ b/spec/bundler/bundler/uri_normalizer_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+RSpec.describe Bundler::URINormalizer do
+ describe ".normalize_suffix" do
+ context "when trailing_slash is true" do
+ it "adds a trailing slash when missing" do
+ expect(described_class.normalize_suffix("https://example.com", trailing_slash: true)).to eq("https://example.com/")
+ end
+
+ it "keeps the trailing slash when present" do
+ expect(described_class.normalize_suffix("https://example.com/", trailing_slash: true)).to eq("https://example.com/")
+ end
+ end
+
+ context "when trailing_slash is false" do
+ it "removes a trailing slash when present" do
+ expect(described_class.normalize_suffix("https://example.com/", trailing_slash: false)).to eq("https://example.com")
+ end
+
+ it "keeps the value unchanged when no trailing slash exists" do
+ expect(described_class.normalize_suffix("https://example.com", trailing_slash: false)).to eq("https://example.com")
+ end
+ end
+ end
+end
diff --git a/spec/bundler/bundler/yaml_serializer_spec.rb b/spec/bundler/bundler/yaml_serializer_spec.rb
index de437f764a..9ff1579b76 100644
--- a/spec/bundler/bundler/yaml_serializer_spec.rb
+++ b/spec/bundler/bundler/yaml_serializer_spec.rb
@@ -112,10 +112,10 @@ RSpec.describe Bundler::YAMLSerializer do
it "handles colon in key/value" do
yaml = <<~YAML
- BUNDLE_MIRROR__HTTPS://RUBYGEMS__ORG/: http://rubygems-mirror.org
+ BUNDLE_MIRROR__HTTPS://RUBYGEMS__ORG/: http://example-mirror.rubygems.org
YAML
- expect(serializer.load(yaml)).to eq("BUNDLE_MIRROR__HTTPS://RUBYGEMS__ORG/" => "http://rubygems-mirror.org")
+ expect(serializer.load(yaml)).to eq("BUNDLE_MIRROR__HTTPS://RUBYGEMS__ORG/" => "http://example-mirror.rubygems.org")
end
it "handles arrays inside hashes" do
diff --git a/spec/bundler/cache/cache_path_spec.rb b/spec/bundler/cache/cache_path_spec.rb
index 12385427b1..d5bd14965b 100644
--- a/spec/bundler/cache/cache_path_spec.rb
+++ b/spec/bundler/cache/cache_path_spec.rb
@@ -3,15 +3,15 @@
RSpec.describe "bundle package" do
before do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
end
context "with --cache-path" do
it "caches gems at given path" do
bundle :cache, "cache-path" => "vendor/cache-foo"
- expect(bundled_app("vendor/cache-foo/rack-1.0.0.gem")).to exist
+ expect(bundled_app("vendor/cache-foo/myrack-1.0.0.gem")).to exist
end
end
@@ -19,14 +19,14 @@ RSpec.describe "bundle package" do
it "caches gems at given path" do
bundle "config set cache_path vendor/cache-foo"
bundle :cache
- expect(bundled_app("vendor/cache-foo/rack-1.0.0.gem")).to exist
+ expect(bundled_app("vendor/cache-foo/myrack-1.0.0.gem")).to exist
end
end
context "with absolute --cache-path" do
it "caches gems at given path" do
- bundle :cache, "cache-path" => "/tmp/cache-foo"
- expect(bundled_app("/tmp/cache-foo/rack-1.0.0.gem")).to exist
+ bundle :cache, "cache-path" => bundled_app("vendor/cache-foo")
+ expect(bundled_app("vendor/cache-foo/myrack-1.0.0.gem")).to exist
end
end
end
diff --git a/spec/bundler/cache/gems_spec.rb b/spec/bundler/cache/gems_spec.rb
index 3c734b79c3..c9b85556e1 100644
--- a/spec/bundler/cache/gems_spec.rb
+++ b/spec/bundler/cache/gems_spec.rb
@@ -4,23 +4,23 @@ RSpec.describe "bundle cache" do
shared_examples_for "when there are only gemsources" do
before :each do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
- system_gems "rack-1.0.0", path: path
+ system_gems "myrack-1.0.0", path: path
bundle :cache
end
it "copies the .gem file to vendor/cache" do
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
end
it "uses the cache as a source when installing gems" do
build_gem "omg", path: bundled_app("vendor/cache")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "omg"
G
@@ -31,44 +31,44 @@ RSpec.describe "bundle cache" do
system_gems [], path: default_bundle_path
bundle "install --local"
- expect(the_bundle).to include_gems("rack 1.0.0")
+ expect(the_bundle).to include_gems("myrack 1.0.0")
end
it "does not reinstall gems from the cache if they exist on the system" do
- build_gem "rack", "1.0.0", path: bundled_app("vendor/cache") do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
+ build_gem "myrack", "1.0.0", path: bundled_app("vendor/cache") do |s|
+ s.write "lib/myrack.rb", "MYRACK = 'FAIL'"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- expect(the_bundle).to include_gems("rack 1.0.0")
+ expect(the_bundle).to include_gems("myrack 1.0.0")
end
it "does not reinstall gems from the cache if they exist in the bundle" do
- system_gems "rack-1.0.0", path: default_bundle_path
+ system_gems "myrack-1.0.0", path: default_bundle_path
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- build_gem "rack", "1.0.0", path: bundled_app("vendor/cache") do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
+ build_gem "myrack", "1.0.0", path: bundled_app("vendor/cache") do |s|
+ s.write "lib/myrack.rb", "MYRACK = 'FAIL'"
end
bundle :install, local: true
- expect(the_bundle).to include_gems("rack 1.0.0")
+ expect(the_bundle).to include_gems("myrack 1.0.0")
end
it "creates a lockfile" do
- cache_gems "rack-1.0.0"
+ cache_gems "myrack-1.0.0"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle "cache"
@@ -103,27 +103,36 @@ RSpec.describe "bundle cache" do
end
end
- it "uses remote gems when installing to system gems" do
- bundle "config set path.system true"
- install_gemfile %(source "#{file_uri_for(gem_repo2)}"; gem 'json', '#{default_json_version}'), verbose: true
+ it "uses remote gems when installing" do
+ install_gemfile %(source "https://gem.repo2"; gem 'json', '#{default_json_version}'), verbose: true
expect(out).to include("Installing json #{default_json_version}")
end
+ it "does not use remote gems when installing with --local flag" do
+ install_gemfile %(source "https://gem.repo2"; gem 'json', '#{default_json_version}'), verbose: true, local: true
+ expect(out).to include("Using json #{default_json_version}")
+ end
+
+ it "does not use remote gems when installing with --prefer-local flag" do
+ install_gemfile %(source "https://gem.repo2"; gem 'json', '#{default_json_version}'), verbose: true, "prefer-local": 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)}"
+ source "https://gem.repo2"
gem 'json', '#{default_json_version}'
- gem 'rack', '1.0.0'
+ gem 'myrack', '1.0.0'
G
bundle :cache
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
expect(bundled_app("vendor/cache/json-#{default_json_version}.gem")).to exist
end
it "caches builtin gems when cache_all_platforms is set" do
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "json"
G
@@ -134,12 +143,10 @@ RSpec.describe "bundle cache" do
end
it "doesn't make remote request after caching the gem" do
- build_gem "builtin_gem_2", "1.0.2", path: bundled_app("vendor/cache") do |s|
- s.summary = "This builtin_gem is bundled with Ruby"
- end
+ build_gem "builtin_gem_2", "1.0.2", path: bundled_app("vendor/cache"), default: true
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem 'builtin_gem_2', '1.0.2'
G
@@ -149,9 +156,10 @@ RSpec.describe "bundle cache" do
end
context "when a remote gem is not available for caching" do
- it "uses builtin gems when installing to system gems" do
+ it "warns, but uses builtin gems when installing to system gems" do
bundle "config set path.system true"
- install_gemfile %(source "#{file_uri_for(gem_repo1)}"; gem 'json', '#{default_json_version}'), verbose: true
+ install_gemfile %(source "https://gem.repo1"; gem 'json', '#{default_json_version}'), verbose: true
+ expect(err).to include("json-#{default_json_version} is built in to Ruby, and can't be cached")
expect(out).to include("Using json #{default_json_version}")
end
@@ -159,12 +167,12 @@ RSpec.describe "bundle cache" do
bundle "config set path.system true"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'json', '#{default_json_version}'
G
bundle :cache, raise_on_error: false
- expect(exitstatus).to_not eq(0)
+ expect(last_command).to be_failure
expect(err).to include("json-#{default_json_version} is built in to Ruby, and can't be cached")
end
end
@@ -173,14 +181,14 @@ RSpec.describe "bundle cache" do
describe "when there are also git sources" do
before do
build_git "foo"
- system_gems "rack-1.0.0"
+ system_gems "myrack-1.0.0"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}" do
gem 'foo'
end
- gem 'rack'
+ gem 'myrack'
G
end
@@ -190,7 +198,7 @@ RSpec.describe "bundle cache" do
system_gems []
bundle "install --local"
- expect(the_bundle).to include_gems("rack 1.0.0", "foo 1.0")
+ expect(the_bundle).to include_gems("myrack 1.0.0", "foo 1.0")
end
it "should not explode if the lockfile is not present" do
@@ -203,41 +211,44 @@ RSpec.describe "bundle cache" do
end
describe "when previously cached" do
- before :each do
+ let :setup_main_repo do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack"
+ source "https://gem.repo2"
+ gem "myrack"
gem "actionpack"
G
bundle :cache
- expect(cached_gem("rack-1.0.0")).to exist
+ expect(cached_gem("myrack-1.0.0")).to exist
expect(cached_gem("actionpack-2.3.2")).to exist
expect(cached_gem("activesupport-2.3.2")).to exist
end
it "re-caches during install" do
- cached_gem("rack-1.0.0").rmtree
+ setup_main_repo
+ FileUtils.rm_rf cached_gem("myrack-1.0.0")
bundle :install
expect(out).to include("Updating files in vendor/cache")
- expect(cached_gem("rack-1.0.0")).to exist
+ expect(cached_gem("myrack-1.0.0")).to exist
end
it "adds and removes when gems are updated" do
+ setup_main_repo
update_repo2 do
- build_gem "rack", "1.2" do |s|
- s.executables = "rackup"
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
end
end
bundle "update", all: true
- expect(cached_gem("rack-1.2")).to exist
- expect(cached_gem("rack-1.0.0")).not_to exist
+ expect(cached_gem("myrack-1.2")).to exist
+ expect(cached_gem("myrack-1.0.0")).not_to exist
end
it "adds new gems and dependencies" do
+ setup_main_repo
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "rails"
G
expect(cached_gem("rails-2.3.2")).to exist
@@ -245,24 +256,26 @@ RSpec.describe "bundle cache" do
end
it "removes .gems for removed gems and dependencies" do
+ setup_main_repo
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack"
+ source "https://gem.repo2"
+ gem "myrack"
G
- expect(cached_gem("rack-1.0.0")).to exist
+ expect(cached_gem("myrack-1.0.0")).to exist
expect(cached_gem("actionpack-2.3.2")).not_to exist
expect(cached_gem("activesupport-2.3.2")).not_to exist
end
it "removes .gems when gem changes to git source" do
- build_git "rack"
+ setup_main_repo
+ build_git "myrack"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack", :git => "#{lib_path("rack-1.0")}"
+ source "https://gem.repo2"
+ gem "myrack", :git => "#{lib_path("myrack-1.0")}"
gem "actionpack"
G
- expect(cached_gem("rack-1.0.0")).not_to exist
+ expect(cached_gem("myrack-1.0.0")).not_to exist
expect(cached_gem("actionpack-2.3.2")).to exist
expect(cached_gem("activesupport-2.3.2")).to exist
end
@@ -270,7 +283,7 @@ RSpec.describe "bundle cache" do
it "doesn't remove gems that are for another platform" do
simulate_platform "java" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "platform_specific"
G
@@ -278,84 +291,111 @@ RSpec.describe "bundle cache" do
expect(cached_gem("platform_specific-1.0-java")).to exist
end
- simulate_new_machine
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "platform_specific"
- G
+ pristine_system_gems
+
+ simulate_platform "x86-darwin-100" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "platform_specific"
+ G
- expect(cached_gem("platform_specific-1.0-#{Bundler.local_platform}")).to exist
- expect(cached_gem("platform_specific-1.0-java")).to exist
+ expect(cached_gem("platform_specific-1.0-x86-darwin-100")).to exist
+ expect(cached_gem("platform_specific-1.0-java")).to exist
+ end
end
- it "doesn't remove gems with mismatched :rubygems_version or :date" do
- cached_gem("rack-1.0.0").rmtree
- build_gem "rack", "1.0.0",
- path: bundled_app("vendor/cache"),
+ it "doesn't remove gems cached gems that don't match their remote counterparts, but also refuses to install and prints an error" do
+ setup_main_repo
+ cached_myrack = cached_gem("myrack-1.0.0")
+ FileUtils.rm_rf cached_myrack
+ build_gem "myrack", "1.0.0",
+ path: cached_myrack.parent,
rubygems_version: "1.3.2"
- # This test is only really valid if the checksum isn't saved. It otherwise can't be the same gem. Tested below.
- bundled_app_lock.write remove_checksums_from_lockfile(bundled_app_lock.read, "rack (1.0.0)")
- simulate_new_machine
- bundle :install
- expect(cached_gem("rack-1.0.0")).to exist
+ FileUtils.rm_r default_bundle_path
+ default_system_gems
+
+ FileUtils.rm bundled_app_lock
+ bundle :install, raise_on_error: false
+
+ expect(err).to eq <<~E.strip
+ Bundler found mismatched checksums. This is a potential security risk.
+ #{checksum_to_lock(gem_repo2, "myrack", "1.0.0")}
+ from the API at https://gem.repo2/
+ #{checksum_from_package(cached_myrack, "myrack", "1.0.0")}
+ from the gem at #{cached_myrack}
+
+ If you trust the API at https://gem.repo2/, to resolve this issue you can:
+ 1. remove the gem at #{cached_myrack}
+ 2. run `bundle install`
+
+ To ignore checksum security warnings, disable checksum validation with
+ `bundle config set --local disable_checksum_validation true`
+ E
+
+ expect(cached_gem("myrack-1.0.0")).to exist
end
- it "raises an error when the gem is altered and produces a different checksum" do
- cached_gem("rack-1.0.0").rmtree
- build_gem "rack", "1.0.0", path: bundled_app("vendor/cache")
+ it "raises an error when a cached gem is altered and produces a different checksum than the remote gem" do
+ setup_main_repo
+ FileUtils.rm_rf cached_gem("myrack-1.0.0")
+ build_gem "myrack", "1.0.0", path: bundled_app("vendor/cache")
checksums = checksums_section do |c|
- c.checksum gem_repo1, "rack", "1.0.0"
+ c.checksum gem_repo1, "myrack", "1.0.0"
end
- simulate_new_machine
+ FileUtils.rm_r default_bundle_path
+ default_system_gems
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
#{checksums}
L
bundle :install, raise_on_error: false
expect(exitstatus).to eq(37)
expect(err).to include("Bundler found mismatched checksums.")
- expect(err).to include("1. remove the gem at #{cached_gem("rack-1.0.0")}")
+ expect(err).to include("1. remove the gem at #{cached_gem("myrack-1.0.0")}")
- expect(cached_gem("rack-1.0.0")).to exist
- cached_gem("rack-1.0.0").rmtree
+ expect(cached_gem("myrack-1.0.0")).to exist
+ FileUtils.rm_rf cached_gem("myrack-1.0.0")
bundle :install
- expect(cached_gem("rack-1.0.0")).to exist
+ expect(cached_gem("myrack-1.0.0")).to exist
end
- it "installs a modified gem with a non-matching checksum when checksums is not opted in" do
- cached_gem("rack-1.0.0").rmtree
- build_gem "rack", "1.0.0", path: bundled_app("vendor/cache")
- simulate_new_machine
+ it "installs a modified gem with a non-matching checksum when the API implementation does not provide checksums" do
+ setup_main_repo
+ FileUtils.rm_rf cached_gem("myrack-1.0.0")
+ build_gem "myrack", "1.0.0", path: bundled_app("vendor/cache")
+ pristine_system_gems
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
L
- bundle :install
- expect(cached_gem("rack-1.0.0")).to exist
+ bundle :install, artifice: "endpoint", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+ expect(cached_gem("myrack-1.0.0")).to exist
end
it "handles directories and non .gem files in the cache" do
+ setup_main_repo
bundled_app("vendor/cache/foo").mkdir
File.open(bundled_app("vendor/cache/bar"), "w") {|f| f.write("not a gem") }
bundle :cache
end
it "does not say that it is removing gems when it isn't actually doing so" do
+ setup_main_repo
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle "cache"
bundle "install"
@@ -363,9 +403,10 @@ RSpec.describe "bundle cache" do
end
it "does not warn about all if it doesn't have any git/path dependency" do
+ setup_main_repo
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle "cache"
expect(out).not_to match(/\-\-all/)
@@ -376,7 +417,7 @@ RSpec.describe "bundle cache" do
path: bundled_app("vendor/cache")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo-bundler"
G
diff --git a/spec/bundler/cache/git_spec.rb b/spec/bundler/cache/git_spec.rb
index 4b3cd4d2eb..860f97d434 100644
--- a/spec/bundler/cache/git_spec.rb
+++ b/spec/bundler/cache/git_spec.rb
@@ -13,22 +13,37 @@ RSpec.describe "git base name" do
end
RSpec.describe "bundle cache with git" do
+ it "does not copy repository to vendor cache when cache_all set to false" do
+ git = build_git "foo"
+ ref = git.ref_for("main", 11)
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
+
+ bundle "config cache_all false"
+ bundle :cache
+ expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).not_to exist
+
+ expect(the_bundle).to include_gems "foo 1.0"
+ end
+
it "copies repository to vendor cache and uses it" do
git = build_git "foo"
ref = git.ref_for("main", 11)
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
- bundle "config set cache_all true"
bundle :cache
expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).to exist
expect(bundled_app("vendor/cache/foo-1.0-#{ref}/.git")).not_to exist
expect(bundled_app("vendor/cache/foo-1.0-#{ref}/.bundlecache")).to be_file
- FileUtils.rm_rf lib_path("foo-1.0")
+ FileUtils.rm_r lib_path("foo-1.0")
expect(the_bundle).to include_gems "foo 1.0"
end
@@ -37,19 +52,18 @@ RSpec.describe "bundle cache with git" do
ref = git.ref_for("main", 11)
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
bundle "config set --local path vendor/bundle"
bundle "install"
- bundle "config set cache_all true"
bundle :cache
expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).to exist
expect(bundled_app("vendor/cache/foo-1.0-#{ref}/.git")).not_to exist
- FileUtils.rm_rf lib_path("foo-1.0")
+ FileUtils.rm_r lib_path("foo-1.0")
expect(the_bundle).to include_gems "foo 1.0"
end
@@ -57,16 +71,15 @@ RSpec.describe "bundle cache with git" do
build_git "foo"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
- bundle "config set cache_all true"
bundle :cache
bundle :cache
expect(out).to include "Updating files in vendor/cache"
- FileUtils.rm_rf lib_path("foo-1.0")
+ FileUtils.rm_r lib_path("foo-1.0")
expect(the_bundle).to include_gems "foo 1.0"
end
@@ -75,11 +88,10 @@ RSpec.describe "bundle cache with git" do
old_ref = git.ref_for("main", 11)
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
- bundle "config set cache_all true"
bundle :cache
update_git "foo" do |s|
@@ -95,7 +107,7 @@ RSpec.describe "bundle cache with git" do
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")
+ FileUtils.rm_r lib_path("foo-1.0")
run "require 'foo'"
expect(out).to eq("CACHE")
end
@@ -105,11 +117,10 @@ RSpec.describe "bundle cache with git" do
old_ref = git.ref_for("main", 11)
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
- bundle "config set cache_all true"
bundle :cache
update_git "foo" do |s|
@@ -124,7 +135,7 @@ RSpec.describe "bundle cache with git" do
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")
+ FileUtils.rm_r lib_path("foo-1.0")
run "require 'foo'"
expect(out).to eq("CACHE")
end
@@ -134,13 +145,12 @@ RSpec.describe "bundle cache with git" do
ref = git.ref_for("main", 11)
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => '#{lib_path("foo-invalid")}', :branch => :main
G
bundle %(config set local.foo #{lib_path("foo-1.0")})
bundle "install"
- bundle "config set cache_all true"
bundle :cache
expect(bundled_app("vendor/cache/foo-invalid-#{ref}")).to exist
@@ -154,6 +164,167 @@ RSpec.describe "bundle cache with git" do
expect(out).to eq("LOCAL")
end
+ it "can use gems after copying install folder to a different machine with git not installed" do
+ build_git "foo"
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
+ bundle "config set path vendor/bundle"
+ bundle :install
+
+ pristine_system_gems
+ with_path_as "" do
+ bundle "config set deployment true"
+ bundle "install --local"
+ expect(the_bundle).to include_gem "foo 1.0"
+ end
+ end
+
+ it "can install after bundle cache without cloning remote repositories" do
+ build_git "foo"
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
+ bundle :cache, "all-platforms" => true
+
+ pristine_system_gems
+ bundle "config set frozen true"
+ bundle "install --local --verbose"
+ expect(out).to_not include("Fetching")
+ expect(the_bundle).to include_gem "foo 1.0"
+ end
+
+ it "can install after bundle cache without cloning remote repositories even without the original cache" do
+ build_git "foo"
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
+ bundle :cache, "all-platforms" => true
+
+ pristine_system_gems
+ bundle "config set frozen true"
+ bundle "install --local --verbose"
+ expect(out).to_not include("Fetching")
+ expect(the_bundle).to include_gem "foo 1.0"
+ end
+
+ it "can install after bundle cache without cloning remote repositories with only git tracked files" do
+ build_git "foo"
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
+ bundle :cache, "all-platforms" => true
+
+ pristine_system_gems
+ bundle "config set frozen true"
+
+ # Remove untracked files (including the empty refs dir in the cache)
+ Dir.chdir(bundled_app) do
+ system(*%W[git init --quiet])
+ system(*%W[git add --all])
+ system(*%W[git clean -d --force --quiet])
+ end
+
+ bundle "install --local --verbose"
+ expect(out).to_not include("Fetching")
+ expect(the_bundle).to include_gem "foo 1.0"
+ end
+
+ it "installs properly a bundler 2.5.17-2.5.23 cache as a bare repository without cloning remote repositories" do
+ git = build_git "foo"
+
+ short_ref = git.ref_for("main", 11)
+ cache_dir = bundled_app("vendor/cache/foo-1.0-#{short_ref}")
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
+ bundle "config set global_gem_cache false"
+ bundle "config path vendor/bundle"
+ bundle :install
+
+ # Simulate old cache by copying the real cache folder to vendor/cache
+ FileUtils.mkdir_p bundled_app("vendor/cache")
+ FileUtils.cp_r "#{Dir.glob(vendored_gems("cache/bundler/git/foo-1.0-*")).first}/.", cache_dir
+ FileUtils.rm_r bundled_app("vendor/bundle")
+
+ bundle "install --local --verbose"
+ expect(err).to include("Installing from cache in old \"bare repository\" format for compatibility")
+
+ expect(out).to_not include("Fetching")
+
+ # leaves old cache alone
+ expect(cache_dir.join("lib/foo.rb")).not_to exist
+ expect(cache_dir.join("HEAD")).to exist
+
+ expect(the_bundle).to include_gem "foo 1.0"
+ end
+
+ it "migrates a bundler 2.5.17-2.5.23 cache as a bare repository when not running with --local" do
+ git = build_git "foo"
+
+ short_ref = git.ref_for("main", 11)
+ cache_dir = bundled_app("vendor/cache/foo-1.0-#{short_ref}")
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
+ bundle "config set global_gem_cache false"
+ bundle "config path vendor/bundle"
+ bundle :install
+
+ # Simulate old cache by copying the real cache folder to vendor/cache
+ FileUtils.mkdir_p bundled_app("vendor/cache")
+ FileUtils.cp_r "#{Dir.glob(vendored_gems("cache/bundler/git/foo-1.0-*")).first}/.", cache_dir
+ FileUtils.rm_r bundled_app("vendor/bundle")
+
+ bundle "install --verbose"
+ expect(out).to include("Fetching")
+
+ # migrates old cache alone
+ expect(cache_dir.join("lib/foo.rb")).to exist
+ expect(cache_dir.join("HEAD")).not_to exist
+
+ expect(the_bundle).to include_gem "foo 1.0"
+ end
+
+ it "migrates a bundler 2.5.17-2.5.23 cache as a bare repository when running `bundle cache`, even if gems already installed" do
+ git = build_git "foo"
+
+ short_ref = git.ref_for("main", 11)
+ cache_dir = bundled_app("vendor/cache/foo-1.0-#{short_ref}")
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{lib_path("foo-1.0")}'
+ G
+ bundle "config set global_gem_cache false"
+ bundle "config path vendor/bundle"
+ bundle :install
+
+ # Simulate old cache by copying the real cache folder to vendor/cache
+ FileUtils.mkdir_p bundled_app("vendor/cache")
+ FileUtils.cp_r "#{Dir.glob(vendored_gems("cache/bundler/git/foo-1.0-*")).first}/.", cache_dir
+
+ bundle "cache"
+
+ # migrates old cache alone
+ expect(cache_dir.join("lib/foo.rb")).to exist
+ expect(cache_dir.join("HEAD")).not_to exist
+
+ expect(the_bundle).to include_gem "foo 1.0"
+ end
+
it "copies repository to vendor cache, including submodules" do
# CVE-2022-39253: https://lore.kernel.org/lkml/xmqq4jw1uku5.fsf@gitster.g/
system(*%W[git config --global protocol.file.allow always])
@@ -164,18 +335,17 @@ RSpec.describe "bundle cache with git" do
s.add_dependency "submodule"
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")
+ git "submodule add #{lib_path("submodule-1.0")} submodule-1.0", lib_path("has_submodule-1.0")
+ git "commit -m \"submodulator\"", lib_path("has_submodule-1.0")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{lib_path("has_submodule-1.0")}", :submodules => true do
gem "has_submodule"
end
G
ref = git.ref_for("main", 11)
- bundle "config set cache_all true"
bundle :cache
expect(bundled_app("vendor/cache/has_submodule-1.0-#{ref}")).to exist
@@ -192,10 +362,9 @@ RSpec.describe "bundle cache with git" do
update_git("foo") {|s| s.write "foo.gemspec", spec_lines.join("\n") }
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
- bundle "config set cache_all true"
bundle :cache
ref = git.ref_for("main", 11)
@@ -207,13 +376,12 @@ RSpec.describe "bundle cache with git" do
build_git "foo"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
- bundle "config set cache_all true"
bundle :cache, "all-platforms" => true, :install => false
- simulate_new_machine
+ pristine_system_gems
with_path_as "" do
bundle "config set deployment true"
bundle :install, local: true
@@ -221,15 +389,54 @@ RSpec.describe "bundle cache with git" do
end
end
+ it "can install after bundle cache generated with an older Bundler that kept checkouts in the cache" do
+ git = build_git("foo")
+ locked_revision = git.ref_for("main")
+ path_revision = git.ref_for("main", 11)
+
+ git_path = lib_path("foo-1.0")
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => '#{git_path}'
+ G
+ lockfile <<~L
+ GIT
+ remote: #{git_path}/
+ revision: #{locked_revision}
+ specs:
+ foo (1.0)
+
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ # Simulate an old incorrect situation where vendor/cache would be the install location of git gems
+ FileUtils.mkdir_p bundled_app("vendor/cache")
+ FileUtils.cp_r git_path, bundled_app("vendor/cache/foo-1.0-#{path_revision}")
+ FileUtils.rm_r bundled_app("vendor/cache/foo-1.0-#{path_revision}/.git")
+
+ bundle :install, env: { "BUNDLE_DEPLOYMENT" => "true", "BUNDLE_CACHE_ALL" => "true" }
+ end
+
it "respects the --no-install flag" do
git = build_git "foo", &:add_c_extension
ref = git.ref_for("main", 11)
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
- bundle "config set cache_all true"
# The algorithm for the cache location for a git checkout is
# in Bundle::Source::Git#cache_path
@@ -245,7 +452,7 @@ RSpec.describe "bundle cache with git" do
bundle :cache, "all-platforms" => true, :install => false
# it did _NOT_ actually install the gem - neither in $GEM_HOME (bundler 2 mode),
- # nor in .bundle (bundler 3 mode)
+ # nor in .bundle (bundler 4 mode)
expect(Pathname.new(File.join(default_bundle_path, "gems/foo-1.0-#{ref}"))).to_not exist
# it _did_ cache the gem in vendor/
expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).to exist
@@ -273,4 +480,32 @@ RSpec.describe "bundle cache with git" do
R
expect(last_command).to_not be_failure
end
+
+ it "doesn't fail when git gem has extensions and an empty cache folder is present before bundle install" do
+ build_git "puma" do |s|
+ s.add_dependency "rake"
+ s.extensions << "Rakefile"
+ s.executables = "puma"
+ s.write "Rakefile", <<-RUBY
+ task :default do
+ path = File.expand_path("../lib", __FILE__)
+ FileUtils.mkdir_p(path)
+ File.open("\#{path}/puma.rb", "w") do |f|
+ f.puts "PUMA = 'YES'"
+ end
+ end
+ RUBY
+ end
+
+ FileUtils.mkdir_p(bundled_app("vendor/cache"))
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "puma", :git => "#{lib_path("puma-1.0")}"
+ G
+
+ bundle "exec puma"
+
+ expect(out).to eq("YES")
+ end
end
diff --git a/spec/bundler/cache/path_spec.rb b/spec/bundler/cache/path_spec.rb
index 2c8a52617a..6865e54b32 100644
--- a/spec/bundler/cache/path_spec.rb
+++ b/spec/bundler/cache/path_spec.rb
@@ -5,11 +5,10 @@ RSpec.describe "bundle cache with path" do
build_lib "foo", path: bundled_app("lib/foo")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :path => '#{bundled_app("lib/foo")}'
G
- bundle "config set cache_all true"
bundle :cache
expect(bundled_app("vendor/cache/foo-1.0")).not_to exist
expect(the_bundle).to include_gems "foo 1.0"
@@ -19,11 +18,10 @@ RSpec.describe "bundle cache with path" do
build_lib "foo"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://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
expect(bundled_app("vendor/cache/foo-1.0/.bundlecache")).to be_file
@@ -38,11 +36,10 @@ RSpec.describe "bundle cache with path" do
build_lib libname, path: libpath
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "#{libname}", :path => '#{libpath}'
G
- bundle "config set cache_all true"
bundle :cache
expect(bundled_app("vendor/cache/#{libname}")).to exist
expect(bundled_app("vendor/cache/#{libname}/.bundlecache")).to be_file
@@ -54,11 +51,10 @@ RSpec.describe "bundle cache with path" do
build_lib "foo"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :path => '#{lib_path("foo-1.0")}'
G
- bundle "config set cache_all true"
bundle :cache
build_lib "foo" do |s|
@@ -77,11 +73,10 @@ RSpec.describe "bundle cache with path" do
build_lib "foo"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://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
@@ -89,7 +84,7 @@ RSpec.describe "bundle cache with path" do
build_lib "bar"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "bar", :path => '#{lib_path("bar-1.0")}'
G
@@ -97,24 +92,25 @@ RSpec.describe "bundle cache with path" do
expect(bundled_app("vendor/cache/foo-1.0")).not_to exist
end
- it "does not cache path gems by default", bundler: "< 3" do
+ it "does not cache path gems if cache_all is set to false" do
build_lib "foo"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :path => '#{lib_path("foo-1.0")}'
G
+ bundle "config cache_all false"
bundle :cache
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
+ it "caches path gems by default" do
build_lib "foo"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :path => '#{lib_path("foo-1.0")}'
G
@@ -122,48 +118,4 @@ RSpec.describe "bundle cache with path" do
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
-
- bundle "config set cache_all true"
- bundle :cache
- 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
-
- bundle :cache
- expect(bundled_app("vendor/cache/bar-1.0")).to exist
- end
-
- it "can rewind chosen configuration" do
- 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
- 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", raise_on_error: false
- expect(bundled_app("vendor/cache/baz-1.0")).not_to exist
- end
end
diff --git a/spec/bundler/cache/platform_spec.rb b/spec/bundler/cache/platform_spec.rb
index 36db954c79..71c0eaee8e 100644
--- a/spec/bundler/cache/platform_spec.rb
+++ b/spec/bundler/cache/platform_spec.rb
@@ -3,10 +3,10 @@
RSpec.describe "bundle cache with multiple platforms" do
before :each do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
platforms :mri, :rbx do
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
end
platforms :jruby do
@@ -16,9 +16,9 @@ RSpec.describe "bundle cache with multiple platforms" do
lockfile <<-G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
activesupport (2.3.5)
PLATFORMS
@@ -26,24 +26,24 @@ RSpec.describe "bundle cache with multiple platforms" do
java
DEPENDENCIES
- rack (1.0.0)
+ myrack (1.0.0)
activesupport (2.3.5)
G
- cache_gems "rack-1.0.0", "activesupport-2.3.5"
+ cache_gems "myrack-1.0.0", "activesupport-2.3.5"
end
it "ensures that a successful bundle install does not delete gems for other platforms" do
bundle "install"
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
+ expect(bundled_app("vendor/cache/myrack-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
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
expect(bundled_app("vendor/cache/activesupport-2.3.5.gem")).to exist
end
end
diff --git a/spec/bundler/commands/add_spec.rb b/spec/bundler/commands/add_spec.rb
index 36e286793b..ed98a914f3 100644
--- a/spec/bundler/commands/add_spec.rb
+++ b/spec/bundler/commands/add_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe "bundle add" do
build_git "foo", "2.0"
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "weakling", "~> 0.0.1"
G
end
@@ -28,6 +28,15 @@ RSpec.describe "bundle add" do
end
end
+ context "when Gemfile is empty, and frozen mode is set" do
+ it "shows error" do
+ gemfile 'source "https://gem.repo2"'
+ bundle "add bar", raise_on_error: false, env: { "BUNDLE_FROZEN" => "true" }
+
+ expect(err).to include("Frozen mode is set, but there's no lockfile")
+ end
+ end
+
describe "without version specified" do
it "version requirement becomes ~> major.minor.patch when resolved version is < 1.0" do
bundle "add 'bar'"
@@ -79,34 +88,34 @@ RSpec.describe "bundle add" do
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"})
+ 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/)
+ 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
describe "with --source" do
it "adds dependency with specified source" do
- bundle "add 'foo' --source='#{file_uri_for(gem_repo2)}'"
+ bundle "add 'foo' --source='https://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(%r{gem "foo", "~> 2.0", source: "https://gem.repo2"})
expect(the_bundle).to include_gems "foo 2.0"
end
end
@@ -115,7 +124,7 @@ RSpec.describe "bundle add" do
it "adds dependency with specified path" do
bundle "add 'foo' --path='#{lib_path("foo-2.0")}'"
- expect(bundled_app_gemfile.read).to match(/gem "foo", "~> 2.0", :path => "#{lib_path("foo-2.0")}"/)
+ expect(bundled_app_gemfile.read).to match(/gem "foo", "~> 2.0", path: "#{lib_path("foo-2.0")}"/)
expect(the_bundle).to include_gems "foo 2.0"
end
end
@@ -124,7 +133,7 @@ RSpec.describe "bundle add" 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
@@ -137,7 +146,7 @@ RSpec.describe "bundle add" 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
@@ -146,32 +155,53 @@ RSpec.describe "bundle add" 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(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", :realworld do
+ before do
+ build_git "rake", "13.0"
+ git("config --global url.file://#{lib_path("rake-13.0")}.insteadOf https://github.com/ruby/rake.git")
+ end
+
+ 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\.\d+", :github => "ruby\/rake"})
+ expect(bundled_app_gemfile.read).to match(%r{gem "rake", "~> 13\.\d+", github: "ruby\/rake"})
end
- end
- describe "with --github and --branch" do
- it "adds dependency with specified github source and branch", :realworld do
- bundle "add rake --github=ruby/rake --branch=master"
+ it "adds dependency with specified github source and branch" do
+ bundle "add rake --github=ruby/rake --branch=main"
- expect(bundled_app_gemfile.read).to match(%r{gem "rake", "~> 13\.\d+", :github => "ruby\/rake", :branch => "master"})
+ expect(bundled_app_gemfile.read).to match(%r{gem "rake", "~> 13\.\d+", github: "ruby\/rake", branch: "main"})
+ end
+
+ it "adds dependency with specified github source and ref" do
+ ref = revision_for(lib_path("rake-13.0"))
+ bundle "add rake --github=ruby/rake --ref=#{ref}"
+
+ expect(bundled_app_gemfile.read).to match(%r{gem "rake", "~> 13\.\d+", github: "ruby\/rake", ref: "#{ref}"})
+ end
+
+ it "adds dependency with specified github source and glob" do
+ bundle "add rake --github=ruby/rake --glob='./*.gemspec'"
+
+ expect(bundled_app_gemfile.read).to match(%r{gem "rake", "~> 13\.\d+", github: "ruby\/rake", glob: "\.\/\*\.gemspec"})
end
- end
- describe "with --github and --ref" do
- it "adds dependency with specified github source and ref", :realworld do
- bundle "add rake --github=ruby/rake --ref=5c60da8"
+ it "adds dependency with specified github source, branch and glob" do
+ bundle "add rake --github=ruby/rake --branch=main --glob='./*.gemspec'"
- expect(bundled_app_gemfile.read).to match(%r{gem "rake", "~> 13\.\d+", :github => "ruby\/rake", :ref => "5c60da8"})
+ expect(bundled_app_gemfile.read).to match(%r{gem "rake", "~> 13\.\d+", github: "ruby\/rake", branch: "main", glob: "\.\/\*\.gemspec"})
+ end
+
+ it "adds dependency with specified github source, ref and glob" do
+ ref = revision_for(lib_path("rake-13.0"))
+ bundle "add rake --github=ruby/rake --ref=#{ref} --glob='./*.gemspec'"
+
+ expect(bundled_app_gemfile.read).to match(%r{gem "rake", "~> 13\.\d+", github: "ruby\/rake", ref: "#{ref}", glob: "\.\/\*\.gemspec"})
end
end
@@ -179,7 +209,7 @@ RSpec.describe "bundle add" do
it "adds dependency with specified git source" do
bundle "add foo --git=#{lib_path("foo-2.0")} --glob='./*.gemspec'"
- expect(bundled_app_gemfile.read).to match(%r{gem "foo", "~> 2.0", :git => "#{lib_path("foo-2.0")}", :glob => "\./\*\.gemspec"})
+ expect(bundled_app_gemfile.read).to match(%r{gem "foo", "~> 2.0", git: "#{lib_path("foo-2.0")}", glob: "\./\*\.gemspec"})
expect(the_bundle).to include_gems "foo 2.0"
end
end
@@ -192,7 +222,7 @@ RSpec.describe "bundle add" do
it "adds dependency with specified git source and branch" do
bundle "add foo --git=#{lib_path("foo-2.0")} --branch=test --glob='./*.gemspec'"
- expect(bundled_app_gemfile.read).to match(%r{gem "foo", "~> 2.0", :git => "#{lib_path("foo-2.0")}", :branch => "test", :glob => "\./\*\.gemspec"})
+ expect(bundled_app_gemfile.read).to match(%r{gem "foo", "~> 2.0", git: "#{lib_path("foo-2.0")}", branch: "test", glob: "\./\*\.gemspec"})
expect(the_bundle).to include_gems "foo 2.0"
end
end
@@ -201,32 +231,42 @@ RSpec.describe "bundle add" 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"))} --glob='./*.gemspec'"
- expect(bundled_app_gemfile.read).to match(%r{gem "foo", "~> 2\.0", :git => "#{lib_path("foo-2.0")}", :ref => "#{revision_for(lib_path("foo-2.0"))}", :glob => "\./\*\.gemspec"})
+ expect(bundled_app_gemfile.read).to match(%r{gem "foo", "~> 2\.0", git: "#{lib_path("foo-2.0")}", ref: "#{revision_for(lib_path("foo-2.0"))}", glob: "\./\*\.gemspec"})
expect(the_bundle).to include_gems "foo 2.0"
end
end
- describe "with --github and --glob" do
- it "adds dependency with specified github source", :realworld do
- bundle "add rake --github=ruby/rake --glob='./*.gemspec'"
+ describe "with mismatched pair in --git/--github, --branch/--ref" do
+ describe "with --git and --github" do
+ it "throws error" do
+ bundle "add 'foo' --git x --github y", raise_on_error: false
- expect(bundled_app_gemfile.read).to match(%r{gem "rake", "~> 13\.\d+", :github => "ruby\/rake", :glob => "\.\/\*\.gemspec"})
+ expect(err).to include("You cannot specify `--git` and `--github` at the same time.")
+ end
end
- end
- describe "with --github and --branch --and glob" do
- it "adds dependency with specified github source and branch", :realworld do
- bundle "add rake --github=ruby/rake --branch=master --glob='./*.gemspec'"
+ describe "with --branch and --ref with --git" do
+ it "throws error" do
+ bundle "add 'foo' --branch x --ref y --git file://git", raise_on_error: false
- expect(bundled_app_gemfile.read).to match(%r{gem "rake", "~> 13\.\d+", :github => "ruby\/rake", :branch => "master", :glob => "\.\/\*\.gemspec"})
+ expect(err).to include("You cannot specify `--branch` and `--ref` at the same time.")
+ end
+ end
+
+ describe "with --branch but without --git or --github" do
+ it "throws error" do
+ bundle "add 'foo' --branch x", raise_on_error: false
+
+ expect(err).to include("You cannot specify `--branch` unless `--git` or `--github` is specified.")
+ end
end
- end
- describe "with --github and --ref and --glob" do
- it "adds dependency with specified github source and ref", :realworld do
- bundle "add rake --github=ruby/rake --ref=5c60da8 --glob='./*.gemspec'"
+ describe "with --ref but without --git or --github" do
+ it "throws error" do
+ bundle "add 'foo' --ref y", raise_on_error: false
- expect(bundled_app_gemfile.read).to match(%r{gem "rake", "~> 13\.\d+", :github => "ruby\/rake", :ref => "5c60da8", :glob => "\.\/\*\.gemspec"})
+ expect(err).to include("You cannot specify `--ref` unless `--git` or `--github` is specified.")
+ end
end
end
@@ -240,8 +280,8 @@ RSpec.describe "bundle add" do
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)}")
+ bundle "add 'foo' -s='https://gem.repo2' -g='development' -v='~>1.0'"
+ expect(bundled_app_gemfile.read).to include %(gem "foo", "~> 1.0", group: :development, source: "https://gem.repo2")
expect(the_bundle).to include_gems "foo 1.1"
end
@@ -255,12 +295,12 @@ RSpec.describe "bundle add" do
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)}'", raise_on_error: false
+ bundle "add 'werk_it' -s='https://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'", raise_on_error: false
+ bundle "add 'baz' --source='http://badhostasdf'", raise_on_error: false, artifice: "fail"
expect(err).to include("Could not reach host badhostasdf. Check your network connection and try again.")
bundle "add 'baz' --source='file://does/not/exist'", raise_on_error: false
@@ -275,6 +315,38 @@ RSpec.describe "bundle add" do
end
end
+ describe "with --quiet option" do
+ it "is quiet when there are no warnings" do
+ bundle "add 'foo' --quiet"
+ expect(out).to be_empty
+ expect(err).to be_empty
+ end
+
+ it "still displays warning and errors" do
+ create_file("add_with_warning.rb", <<~RUBY)
+ require "#{lib_dir}/bundler"
+ require "#{lib_dir}/bundler/cli"
+ require "#{lib_dir}/bundler/cli/add"
+
+ module RunWithWarning
+ def run
+ super
+ rescue
+ Bundler.ui.warn "This is a warning"
+ raise
+ end
+ end
+
+ Bundler::CLI::Add.prepend(RunWithWarning)
+ RUBY
+
+ bundle "add 'non-existing-gem' --quiet", raise_on_error: false, env: { "RUBYOPT" => "-r#{bundled_app("add_with_warning.rb")}" }
+ expect(out).to be_empty
+ expect(err).to include("Could not find gem 'non-existing-gem'")
+ expect(err).to include("This is a warning")
+ end
+ end
+
describe "with --strict option" do
it "adds strict version" do
bundle "add 'foo' --strict"
@@ -295,7 +367,7 @@ RSpec.describe "bundle add" do
it "throws error" do
bundle "add 'foo' --strict --optimistic", raise_on_error: false
- expect(err).to include("You can not specify `--strict` and `--optimistic` at the same time")
+ expect(err).to include("You cannot specify `--strict` and `--optimistic` at the same time")
end
end
@@ -318,41 +390,41 @@ RSpec.describe "bundle add" do
describe "when a gem is added which is already specified in Gemfile with version" do
it "shows an error when added with different version requirement" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack", "1.0"
+ source "https://gem.repo2"
+ gem "myrack", "1.0"
G
- bundle "add 'rack' --version=1.1", raise_on_error: false
+ bundle "add 'myrack' --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")
+ expect(err).to include("If you want to update the gem version, run `bundle update myrack`. You may also need to change the version requirement specified in the Gemfile if it's too restrictive")
end
it "shows error when added without version requirements" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack", "1.0"
+ source "https://gem.repo2"
+ gem "myrack", "1.0"
G
- bundle "add 'rack'", raise_on_error: false
+ bundle "add 'myrack'", 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")
- expect(err).not_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")
+ expect(err).not_to include("If you want to update the gem version, run `bundle update myrack`. You may also need to change the version requirement specified in the Gemfile if it's too restrictive")
end
end
describe "when a gem is added which is already specified in Gemfile without version" do
it "shows an error when added with different version requirement" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack"
+ source "https://gem.repo2"
+ gem "myrack"
G
- bundle "add 'rack' --version=1.1", raise_on_error: false
+ bundle "add 'myrack' --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`.")
+ expect(err).to include("If you want to update the gem version, run `bundle update myrack`.")
expect(err).not_to include("You may also need to change the version requirement specified in the Gemfile if it's too restrictive")
end
end
@@ -361,8 +433,8 @@ RSpec.describe "bundle add" do
it "caches all new dependencies added for the specified gem" do
bundle :cache
- bundle "add 'rack' --version=1.0.0"
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
+ bundle "add 'myrack' --version=1.0.0"
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
end
end
end
diff --git a/spec/bundler/commands/binstubs_spec.rb b/spec/bundler/commands/binstubs_spec.rb
index 6c3dc7bb2d..306cbbc412 100644
--- a/spec/bundler/commands/binstubs_spec.rb
+++ b/spec/bundler/commands/binstubs_spec.rb
@@ -4,44 +4,44 @@ RSpec.describe "bundle binstubs <gem>" do
context "when the gem exists in the lockfile" do
it "sets up the binstub" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "binstubs rack"
+ bundle "binstubs myrack"
- expect(bundled_app("bin/rackup")).to exist
+ expect(bundled_app("bin/myrackup")).to exist
end
it "does not install other binstubs" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
gem "rails"
G
bundle "binstubs rails"
- expect(bundled_app("bin/rackup")).not_to exist
+ expect(bundled_app("bin/myrackup")).not_to exist
expect(bundled_app("bin/rails")).to exist
end
it "does install multiple binstubs" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
gem "rails"
G
- bundle "binstubs rails rack"
+ bundle "binstubs rails myrack"
- expect(bundled_app("bin/rackup")).to exist
+ expect(bundled_app("bin/myrackup")).to exist
expect(bundled_app("bin/rails")).to exist
end
it "allows installing all binstubs" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
G
@@ -53,20 +53,20 @@ RSpec.describe "bundle binstubs <gem>" do
it "allows installing binstubs for all platforms" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "binstubs rack --all-platforms"
+ bundle "binstubs myrack --all-platforms"
- expect(bundled_app("bin/rackup")).to exist
- expect(bundled_app("bin/rackup.cmd")).to exist
+ expect(bundled_app("bin/myrackup")).to exist
+ expect(bundled_app("bin/myrackup.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"
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle "binstubs", raise_on_error: false
@@ -76,228 +76,15 @@ RSpec.describe "bundle binstubs <gem>" do
it "displays an error when used with --all and gems" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "binstubs rack", all: true, raise_on_error: false
+ bundle "binstubs myrack", all: true, raise_on_error: false
expect(last_command).to be_failure
expect(err).to include("Cannot specify --all with specific gems")
end
- context "when generating bundle binstub outside bundler" do
- it "should abort" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- G
-
- bundle "binstubs rack"
-
- File.open(bundled_app("bin/bundle"), "wb") do |file|
- file.print "OMG"
- end
-
- sys_exec "bin/rackup", raise_on_error: false
-
- expect(err).to include("was not generated by Bundler")
- end
- end
-
- context "the bundle binstub" do
- before do
- 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| s.default_gem? }
- puts specs.map(&:full_name).sort.inspect
- R
- end
- end
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack"
- gem "prints_loaded_gems"
- G
- bundle "binstubs bundler rack prints_loaded_gems"
- end
-
- let(:system_bundler_version) { Bundler::VERSION }
-
- it "runs bundler" do
- 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 "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
-
- context "when a lockfile exists with a locked bundler version" do
- context "and the version is newer" do
- before do
- lockfile lockfile.gsub(system_bundler_version, "999.999")
- end
-
- it "runs the correct version of bundler" do
- 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
- end
-
- context "and the version is newer when given `gems.rb` and `gems.locked`" do
- before do
- gemfile bundled_app("gems.rb"), gemfile
- lockfile bundled_app("gems.locked"), lockfile.gsub(system_bundler_version, "999.999")
- end
-
- it "runs the correct version of bundler" do
- sys_exec "bin/bundle install", env: { "BUNDLE_GEMFILE" => "gems.rb" }, 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
- end
-
- context "and the version is older and a different major" do
- let(:system_bundler_version) { "55" }
-
- before do
- lockfile lockfile.gsub(/BUNDLED WITH\n .*$/m, "BUNDLED WITH\n 44.0")
- end
-
- it "runs the correct version of bundler" do
- 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 a different major when given `gems.rb` and `gems.locked`" do
- let(:system_bundler_version) { "55" }
-
- before do
- gemfile bundled_app("gems.rb"), gemfile
- lockfile bundled_app("gems.locked"), lockfile.gsub(/BUNDLED WITH\n .*$/m, "BUNDLED WITH\n 44.0")
- end
-
- it "runs the correct version of bundler" do
- sys_exec "bin/bundle install", env: { "BUNDLE_GEMFILE" => "gems.rb" }, 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) { "2.999.999" }
-
- before do
- 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", realworld: true 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", 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
-
- context "and the version is a pre-releaser" do
- let(:system_bundler_version) { "55" }
-
- before do
- lockfile lockfile.gsub(/BUNDLED WITH\n .*$/m, "BUNDLED WITH\n 2.12.0.a")
- end
-
- it "runs the correct version of bundler when the version is a pre-release" do
- 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
- end
- end
-
- context "when update --bundler is called" do
- before { lockfile.gsub(system_bundler_version, "1.1.1") }
-
- it "calls through to the latest bundler version", :realworld do
- sys_exec "bin/bundle update --bundler", env: { "DEBUG" => "1" }
- using_bundler_line = /Using bundler ([\w\.]+)\n/.match(out)
- expect(using_bundler_line).to_not be_nil
- latest_version = using_bundler_line[1]
- expect(Gem::Version.new(latest_version)).to be >= Gem::Version.new(system_bundler_version)
- end
-
- it "calls through to the explicit bundler version" do
- 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_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
- it "loads all gems" do
- 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
-
- context "when requesting a different bundler version" do
- before { lockfile lockfile.gsub(Bundler::VERSION, "999.999.999") }
-
- it "attempts to load that version" do
- 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
- end
- end
- end
-
it "installs binstubs from git gems" do
FileUtils.mkdir_p(lib_path("foo/bin"))
FileUtils.touch(lib_path("foo/bin/foo"))
@@ -305,7 +92,7 @@ RSpec.describe "bundle binstubs <gem>" do
s.executables = %w[foo]
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo")}"
G
@@ -321,7 +108,7 @@ RSpec.describe "bundle binstubs <gem>" do
s.executables = %w[foo]
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :path => "#{lib_path("foo")}"
G
@@ -333,12 +120,12 @@ RSpec.describe "bundle binstubs <gem>" do
it "sets correct permissions for binstubs" do
with_umask(0o002) do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "binstubs rack"
- binary = bundled_app("bin/rackup")
+ bundle "binstubs myrack"
+ binary = bundled_app("bin/myrackup")
expect(File.stat(binary).mode.to_s(8)).to eq(Gem.win_platform? ? "100644" : "100775")
end
end
@@ -346,12 +133,12 @@ RSpec.describe "bundle binstubs <gem>" do
context "when using --shebang" do
it "sets the specified shebang for the binstub" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "binstubs rack --shebang jruby"
- expect(File.readlines(bundled_app("bin/rackup")).first).to eq("#!/usr/bin/env jruby\n")
+ bundle "binstubs myrack --shebang jruby"
+ expect(File.readlines(bundled_app("bin/myrackup")).first).to eq("#!/usr/bin/env jruby\n")
end
end
end
@@ -359,7 +146,7 @@ RSpec.describe "bundle binstubs <gem>" do
context "when the gem doesn't exist" do
it "displays an error with correct status" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
bundle "binstubs doesnt_exist", raise_on_error: false
@@ -369,63 +156,53 @@ RSpec.describe "bundle binstubs <gem>" do
end
end
- context "--path" do
- it "sets the binstubs dir" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- G
-
- bundle "binstubs rack --path exec"
-
- expect(bundled_app("exec/rackup")).to exist
+ context "with the binstubs dir configured" do
+ before do
+ bundle "config bin exec"
end
- it "setting is saved for bundle install", bundler: "< 3" do
+ it "creates the binstubs in the configured dir" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- gem "rails"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "binstubs rack", path: "exec"
- bundle :install
+ bundle "binstubs myrack"
- expect(bundled_app("exec/rails")).to exist
+ expect(bundled_app("exec/myrackup")).to exist
end
end
context "with --standalone option" do
before do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
gem "rails"
G
end
it "generates a standalone binstub" do
- bundle "binstubs rack --standalone"
- expect(bundled_app("bin/rackup")).to exist
+ bundle "binstubs myrack --standalone"
+ expect(bundled_app("bin/myrackup")).to exist
end
it "generates a binstub that does not depend on rubygems or bundler" do
- bundle "binstubs rack --standalone"
- expect(File.read(bundled_app("bin/rackup"))).to_not include("Gem.bin_path")
+ bundle "binstubs myrack --standalone"
+ expect(File.read(bundled_app("bin/myrackup"))).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"
- expect(bundled_app("foo/rackup")).to exist
- end
+ it "generates a standalone binstub at the given path when configured" do
+ bundle "config bin foo"
+ bundle "binstubs myrack --standalone"
+ expect(bundled_app("foo/myrackup")).to exist
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
+ bundle "binstubs myrack --standalone --all-platforms"
+ expect(bundled_app("bin/myrackup")).to exist
+ expect(bundled_app("bin/myrackup.cmd")).to exist
end
end
@@ -441,7 +218,7 @@ RSpec.describe "bundle binstubs <gem>" do
context "when specified --all option" do
it "generates standalone binstubs for all gems except bundler" do
bundle "binstubs --standalone --all"
- expect(bundled_app("bin/rackup")).to exist
+ expect(bundled_app("bin/myrackup")).to exist
expect(bundled_app("bin/rails")).to exist
expect(bundled_app("bin/bundle")).not_to exist
expect(bundled_app("bin/bundler")).not_to exist
@@ -453,39 +230,39 @@ RSpec.describe "bundle binstubs <gem>" do
context "when the bin already exists" do
it "doesn't overwrite and warns" do
FileUtils.mkdir_p(bundled_app("bin"))
- File.open(bundled_app("bin/rackup"), "wb") do |file|
+ File.open(bundled_app("bin/myrackup"), "wb") do |file|
file.print "OMG"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "binstubs rack"
+ bundle "binstubs myrack"
- expect(bundled_app("bin/rackup")).to exist
- expect(File.read(bundled_app("bin/rackup"))).to eq("OMG")
- expect(err).to include("Skipped rackup")
+ expect(bundled_app("bin/myrackup")).to exist
+ expect(File.read(bundled_app("bin/myrackup"))).to eq("OMG")
+ expect(err).to include("Skipped myrackup")
expect(err).to include("overwrite skipped stubs, use --force")
end
context "when using --force" do
it "overwrites the binstub" do
FileUtils.mkdir_p(bundled_app("bin"))
- File.open(bundled_app("bin/rackup"), "wb") do |file|
+ File.open(bundled_app("bin/myrackup"), "wb") do |file|
file.print "OMG"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "binstubs rack --force"
+ bundle "binstubs myrack --force"
- expect(bundled_app("bin/rackup")).to exist
- expect(File.read(bundled_app("bin/rackup"))).not_to eq("OMG")
+ expect(bundled_app("bin/myrackup")).to exist
+ expect(File.read(bundled_app("bin/myrackup"))).not_to eq("OMG")
end
end
end
@@ -493,18 +270,18 @@ RSpec.describe "bundle binstubs <gem>" do
context "when the gem has no bins" do
it "suggests child gems if they have bins" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack-obama"
+ source "https://gem.repo1"
+ gem "myrack-obama"
G
- bundle "binstubs rack-obama"
- expect(err).to include("rack-obama has no executables")
- expect(err).to include("rack has: rackup")
+ bundle "binstubs myrack-obama"
+ expect(err).to include("myrack-obama has no executables")
+ expect(err).to include("myrack has: myrackup")
end
it "works if child gems don't have bins" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "actionpack"
G
@@ -520,7 +297,7 @@ RSpec.describe "bundle binstubs <gem>" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "with_development_dependency"
G
@@ -532,25 +309,25 @@ RSpec.describe "bundle binstubs <gem>" do
context "when BUNDLE_INSTALL is specified" do
it "performs an automatic bundle install" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle "config set auto_install 1"
- bundle "binstubs rack"
- expect(out).to include("Installing rack 1.0.0")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ bundle "binstubs myrack"
+ expect(out).to include("Installing myrack 1.0.0")
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "does nothing when already up to date" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle "config set auto_install 1"
- bundle "binstubs rack", env: { "BUNDLE_INSTALL" => "1" }
- expect(out).not_to include("Installing rack 1.0.0")
+ bundle "binstubs myrack", env: { "BUNDLE_INSTALL" => "1" }
+ expect(out).not_to include("Installing myrack 1.0.0")
end
end
end
diff --git a/spec/bundler/commands/cache_spec.rb b/spec/bundler/commands/cache_spec.rb
index 37d8b3ac1a..bd92a84e18 100644
--- a/spec/bundler/commands/cache_spec.rb
+++ b/spec/bundler/commands/cache_spec.rb
@@ -3,8 +3,8 @@
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"
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle :cache
@@ -17,30 +17,30 @@ RSpec.describe "bundle cache" do
context "with --gemfile" do
it "finds the gemfile" do
gemfile bundled_app("NotGemfile"), <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
bundle "cache --gemfile=NotGemfile"
ENV["BUNDLE_GEMFILE"] = "NotGemfile"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
- context "with --all" do
+ context "with cache_all configured" do
context "without a gemspec" do
it "caches all dependencies except bundler itself" do
gemfile <<-D
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
gem 'bundler'
D
bundle "config set cache_all true"
bundle :cache
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
expect(bundled_app("vendor/cache/bundler-0.9.gem")).to_not exist
end
end
@@ -63,15 +63,15 @@ RSpec.describe "bundle cache" do
it "caches all dependencies except bundler and the gemspec specified gem" do
gemfile <<-D
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
gemspec
D
bundle "config set cache_all true"
bundle :cache
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
expect(bundled_app("vendor/cache/nokogiri-1.4.2.gem")).to exist
expect(bundled_app("vendor/cache/mygem-0.1.1.gem")).to_not exist
expect(bundled_app("vendor/cache/bundler-0.9.gem")).to_not exist
@@ -95,15 +95,15 @@ RSpec.describe "bundle cache" do
it "caches all dependencies except bundler and the gemspec specified gem" do
gemfile <<-D
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
gemspec
D
bundle "config set cache_all true"
bundle :cache
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
expect(bundled_app("vendor/cache/nokogiri-1.4.2.gem")).to exist
expect(bundled_app("vendor/cache/mygem-0.1.1.gem")).to_not exist
expect(bundled_app("vendor/cache/bundler-0.9.gem")).to_not exist
@@ -139,8 +139,8 @@ RSpec.describe "bundle cache" do
it "caches all dependencies except bundler and the gemspec specified gems" do
gemfile <<-D
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
gemspec :name => 'mygem'
gemspec :name => 'mygem_test'
D
@@ -148,7 +148,7 @@ RSpec.describe "bundle cache" do
bundle "config set cache_all true"
bundle :cache
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
expect(bundled_app("vendor/cache/nokogiri-1.4.2.gem")).to exist
expect(bundled_app("vendor/cache/weakling-0.0.3.gem")).to exist
expect(bundled_app("vendor/cache/mygem-0.1.1.gem")).to_not exist
@@ -158,77 +158,64 @@ RSpec.describe "bundle cache" do
end
end
- context "with --path", bundler: "< 3" do
- it "sets root directory for gems" do
- gemfile <<-D
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
- D
-
- bundle "cache --path #{bundled_app("test")}"
-
- expect(the_bundle).to include_gems "rack 1.0.0"
- expect(bundled_app("test/vendor/cache/")).to exist
- end
- end
-
context "with --no-install" do
it "puts the gems in vendor/cache but does not install them" do
gemfile <<-D
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
D
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
+ expect(the_bundle).not_to include_gems "myrack 1.0.0"
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
end
it "does not prevent installing gems with bundle install" do
gemfile <<-D
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
D
bundle "cache --no-install"
bundle "install"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "does not prevent installing gems with bundle update" do
gemfile <<-D
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "1.0.0"
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0"
D
bundle "cache --no-install"
bundle "update --all"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
context "with --all-platforms" do
- it "puts the gems in vendor/cache even for other rubies", bundler: ">= 2.4.0" do
+ it "puts the gems in vendor/cache even for other rubies" do
gemfile <<-D
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack', :platforms => [:ruby_20, :windows_20]
+ source "https://gem.repo1"
+ gem 'myrack', :platforms => [:ruby_20, :windows_20]
D
bundle "cache --all-platforms"
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
end
- it "puts the gems in vendor/cache even for legacy windows rubies", bundler: ">= 2.4.0" do
+ it "prints a warn when using legacy windows rubies" do
gemfile <<-D
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack', :platforms => [:ruby_20, :x64_mingw_20]
+ source "https://gem.repo1"
+ gem 'myrack', :platforms => [:ruby_20, :x64_mingw_20]
D
- bundle "cache --all-platforms"
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
+ bundle "cache --all-platforms", raise_on_error: false
+ expect(err).to include("will be removed in the future")
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
end
it "does not attempt to install gems in without groups" do
@@ -241,71 +228,145 @@ RSpec.describe "bundle cache" do
end
bundle "config set --local without wo"
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ install_gemfile <<-G, artifice: "compact_index_extra_api"
+ source "https://main.repo"
+ gem "myrack"
group :wo do
gem "weakling"
- gem "uninstallable", :source => "#{file_uri_for(gem_repo4)}"
+ gem "uninstallable", :source => "https://main.repo/extra"
end
G
- bundle :cache, "all-platforms" => true
+ bundle :cache, "all-platforms" => true, artifice: "compact_index_extra_api"
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).to include_gem "myrack 1.0"
expect(the_bundle).not_to include_gems "weakling", "uninstallable"
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"
+ bundle :install, artifice: "compact_index_extra_api"
+ expect(the_bundle).to include_gem "myrack 1.0"
+ expect(the_bundle).not_to include_gems "weakling"
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"
+ source "https://gem.repo1"
+ gem "myrack"
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 }
+ bundle :lock
+ bundle :cache, "all-platforms" => true
expect(bundled_app("vendor/cache/weakling-0.0.3.gem")).to exist
end
end
context "with frozen configured" do
- before do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- G
- bundle "install"
- end
+ let(:app_cache) { bundled_app("vendor/cache") }
- subject do
+ before 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"
+ it "tries to install but fails when the lockfile is out of sync" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- gem "rack-obama"
+ source "https://gem.repo1"
+ gem "myrack"
G
- subject
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo1/
+ specs:
+ myrack (1.0.0)
+ myrack-obama (1.0)
+ myrack
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack
+ myrack-obama
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ bundle :cache, raise_on_error: false
expect(exitstatus).to eq(16)
expect(err).to include("frozen mode")
- expect(err).to include("You have added to the Gemfile")
- expect(err).to include("* rack-obama")
+ expect(err).to include("You have deleted from the Gemfile")
+ expect(err).to include("* myrack-obama")
bundle "env"
- expect(out).to include("frozen").or include("deployment")
+ expect(out).to include("frozen")
+ end
+
+ it "caches gems without installing when lockfile is in sync, and --no-install is passed, even if vendor/cache directory is initially empty" do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo1/
+ specs:
+ myrack (1.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ FileUtils.mkdir_p app_cache
+
+ bundle "cache --no-install"
+ expect(out).not_to include("Installing myrack 1.0.0")
+ expect(out).to include("Fetching myrack 1.0.0")
+ expect(app_cache.join("myrack-1.0.0.gem")).to exist
+ end
+
+ it "completes a partial cache when lockfile is in sync, even if the already cached gem is no longer available remotely" do
+ build_repo4 do
+ build_gem "foo", "1.0.0"
+ end
+
+ build_gem "bar", "1.0.0", path: bundled_app("vendor/cache")
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "foo"
+ gem "bar"
+ G
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ foo (1.0.0)
+ bar (1.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo
+ bar
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "cache --no-install"
+ expect(out).to include("Fetching foo 1.0.0")
+ expect(out).not_to include("Fetching bar 1.0.0")
+ expect(app_cache.join("foo-1.0.0.gem")).to exist
+ expect(app_cache.join("bar-1.0.0.gem")).to exist
end
end
@@ -315,12 +376,12 @@ RSpec.describe "bundle cache" do
build_gem "racc", "2.0" do |s|
s.add_dependency "rake"
s.extensions << "Rakefile"
- s.write "Rakefile", "task(:default) { puts 'INSTALLING rack' }"
+ s.write "Rakefile", "task(:default) { puts 'INSTALLING myrack' }"
end
end
gemfile <<~G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "racc"
G
@@ -339,51 +400,67 @@ RSpec.describe "bundle install with gem sources" do
it "does not hit the remote at all" do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack"
+ source "https://gem.repo2"
+ gem "myrack"
G
bundle :cache
- simulate_new_machine
- FileUtils.rm_rf gem_repo2
+ pristine_system_gems
+ FileUtils.rm_r gem_repo2
bundle "install --local"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
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"
+ source "https://gem.repo2"
+ gem "myrack"
G
bundle :cache
- simulate_new_machine
- FileUtils.rm_rf gem_repo2
+ pristine_system_gems
+ FileUtils.rm_r 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"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ it "does not hit the remote at all in non frozen mode either" do
+ build_repo2
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "myrack"
+ G
+
+ bundle :cache
+ pristine_system_gems
+ FileUtils.rm_r gem_repo2
+
+ bundle "config set --local path vendor/bundle"
+ bundle :install
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "does not hit the remote at all when cache_all_platforms configured" do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack"
+ source "https://gem.repo2"
+ gem "myrack"
G
bundle :cache
- simulate_new_machine
- FileUtils.rm_rf gem_repo2
+ pristine_system_gems
+ FileUtils.rm_r gem_repo2
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"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "uses cached gems for secondary sources when cache_all_platforms configured" do
@@ -398,20 +475,20 @@ RSpec.describe "bundle install with gem sources" do
end
gemfile <<~G
- source "https://gems.repo2"
+ source "https://gem.repo2"
- source "https://gems.repo4" do
+ source "https://gem.repo4" do
gem "foo"
end
G
lockfile <<~L
GEM
- remote: https://gems.repo2/
+ remote: https://gem.repo2/
specs:
GEM
- remote: https://gems.repo4/
+ remote: https://gem.repo4/
specs:
foo (1.0.0-x86_64-linux)
foo (1.0.0-arm64-darwin)
@@ -425,7 +502,7 @@ RSpec.describe "bundle install with gem sources" do
foo
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
simulate_platform "x86_64-linux" do
@@ -433,12 +510,11 @@ RSpec.describe "bundle install with gem sources" do
bundle "config set path vendor/bundle"
bundle :cache, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
- build_repo4 do
- # simulate removal of all remote gems
- end
+ # simulate removal of all remote gems
+ empty_repo4
# delete compact index cache
- FileUtils.rm_rf home(".bundle/cache/compact_index")
+ FileUtils.rm_r home(".bundle/cache/compact_index")
bundle "install", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
@@ -448,45 +524,91 @@ RSpec.describe "bundle install with gem sources" do
it "does not reinstall already-installed gems" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle :cache
- build_gem "rack", "1.0.0", path: bundled_app("vendor/cache") do |s|
- s.write "lib/rack.rb", "raise 'omg'"
+ build_gem "myrack", "1.0.0", path: bundled_app("vendor/cache") do |s|
+ s.write "lib/myrack.rb", "raise 'omg'"
end
bundle :install
expect(err).to be_empty
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
it "ignores cached gems for the wrong platform" do
simulate_platform "java" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "platform_specific"
G
bundle :cache
end
- simulate_new_machine
+ pristine_system_gems
bundle "config set --local force_ruby_platform true"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "platform_specific"
G
- run "require 'platform_specific' ; puts PLATFORM_SPECIFIC"
- expect(out).to eq("1.0.0 RUBY")
+ expect(the_bundle).to include_gems("platform_specific 1.0 ruby")
+ end
+
+ it "keeps gems that are locked and cached for the current platform, even if incompatible with the current ruby" do
+ build_repo4 do
+ build_gem "bcrypt_pbkdf", "1.1.1"
+ build_gem "bcrypt_pbkdf", "1.1.1" do |s|
+ s.platform = "arm64-darwin"
+ s.required_ruby_version = "< #{current_ruby_minor}"
+ end
+ end
+
+ app_cache = bundled_app("vendor/cache")
+ FileUtils.mkdir_p app_cache
+ FileUtils.cp gem_repo4("gems/bcrypt_pbkdf-1.1.1-arm64-darwin.gem"), app_cache
+ FileUtils.cp gem_repo4("gems/bcrypt_pbkdf-1.1.1.gem"), app_cache
+
+ bundle "config cache_all_platforms true"
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ bcrypt_pbkdf (1.1.1)
+ bcrypt_pbkdf (1.1.1-arm64-darwin)
+
+ PLATFORMS
+ arm64-darwin
+ ruby
+
+ DEPENDENCIES
+ bcrypt_pbkdf
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "arm64-darwin-23" do
+ install_gemfile <<~G, verbose: true
+ source "https://gem.repo4"
+ gem "bcrypt_pbkdf"
+ G
+
+ expect(out).to include("Updating files in vendor/cache")
+ expect(err).to be_empty
+ expect(app_cache.join("bcrypt_pbkdf-1.1.1-arm64-darwin.gem")).to exist
+ expect(app_cache.join("bcrypt_pbkdf-1.1.1.gem")).to exist
+ end
end
it "does not update the cache if --no-cache is passed" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
bundled_app("vendor/cache").mkpath
expect(bundled_app("vendor/cache").children).to be_empty
diff --git a/spec/bundler/commands/check_spec.rb b/spec/bundler/commands/check_spec.rb
index 02f9bb5b7a..72da24fb0b 100644
--- a/spec/bundler/commands/check_spec.rb
+++ b/spec/bundler/commands/check_spec.rb
@@ -3,7 +3,7 @@
RSpec.describe "bundle check" do
it "returns success when the Gemfile is satisfied" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
G
@@ -13,7 +13,7 @@ RSpec.describe "bundle check" do
it "works with the --gemfile flag when not in the directory" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
G
@@ -23,7 +23,7 @@ RSpec.describe "bundle check" do
it "creates a Gemfile.lock by default if one does not exist" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
G
@@ -36,7 +36,7 @@ RSpec.describe "bundle check" do
it "does not create a Gemfile.lock if --dry-run was passed" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
G
@@ -47,26 +47,57 @@ RSpec.describe "bundle check" do
expect(bundled_app_lock).not_to exist
end
- it "prints a generic error if the missing gems are unresolvable" do
- system_gems ["rails-2.3.2"]
+ it "prints an error that shows missing gems" do
+ system_gems ["rails-2.3.2"], path: default_bundle_path
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
G
bundle :check, raise_on_error: false
- expect(err).to include("Bundler can't satisfy your Gemfile's dependencies.")
+ expect(err).to include("The following gems are missing")
+ expect(err).to include(" * rake (#{rake_version})")
+ expect(err).to include(" * actionpack (2.3.2)")
+ expect(err).to include(" * activerecord (2.3.2)")
+ expect(err).to include(" * actionmailer (2.3.2)")
+ expect(err).to include(" * activeresource (2.3.2)")
+ expect(err).to include(" * activesupport (2.3.2)")
+ expect(err).to include("Install missing gems with `bundle install`")
end
- it "prints a generic error if a Gemfile.lock does not exist and a toplevel dependency does not exist" do
+ it "prints an error that shows missing gems if a Gemfile.lock does not exist and a toplevel dependency is missing" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
G
bundle :check, raise_on_error: false
expect(exitstatus).to be > 0
+ expect(err).to include("The following gems are missing")
+ expect(err).to include(" * rails (2.3.2)")
+ expect(err).to include(" * rake (#{rake_version})")
+ expect(err).to include(" * actionpack (2.3.2)")
+ expect(err).to include(" * activerecord (2.3.2)")
+ expect(err).to include(" * actionmailer (2.3.2)")
+ expect(err).to include(" * activeresource (2.3.2)")
+ expect(err).to include(" * activesupport (2.3.2)")
+ expect(err).to include("Install missing gems with `bundle install`")
+ end
+
+ it "prints a generic error if gem git source is not checked out" do
+ build_git "foo", path: lib_path("foo")
+
+ bundle "config path vendor/bundle"
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", git: "#{lib_path("foo")}"
+ G
+
+ FileUtils.rm_r bundled_app("vendor/bundle")
+ bundle :check, raise_on_error: false
+ expect(exitstatus).to eq 1
expect(err).to include("Bundler can't satisfy your Gemfile's dependencies.")
end
@@ -78,12 +109,12 @@ RSpec.describe "bundle check" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem 'rails'
G
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "rails"
gem "rails_pinned_to_old_activesupport"
G
@@ -92,25 +123,12 @@ RSpec.describe "bundle check" do
expect(err).to include("Bundler can't satisfy your Gemfile's dependencies.")
end
- it "remembers --without option from install", bundler: "< 3" do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- group :foo do
- gem "rack"
- end
- G
-
- 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
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
group :foo do
- gem "rack"
+ gem "myrack"
end
G
@@ -120,63 +138,63 @@ RSpec.describe "bundle check" do
it "ensures that gems are actually installed and not just cached" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :group => :foo
+ source "https://gem.repo1"
+ gem "myrack", :group => :foo
G
bundle "config set --local without foo"
bundle :install
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle "check", raise_on_error: false
- expect(err).to include("* rack (1.0.0)")
+ expect(err).to include("* myrack (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"
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle "config set --local path vendor/bundle"
bundle :cache
- gem_command "uninstall rack", env: { "GEM_HOME" => vendored_gems.to_s }
+ gem_command "uninstall myrack", env: { "GEM_HOME" => vendored_gems.to_s }
bundle "check", raise_on_error: false
- expect(err).to include("* rack (1.0.0)")
+ expect(err).to include("* myrack (1.0.0)")
expect(exitstatus).to eq(1)
end
it "ignores missing gems restricted to other platforms" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
platforms :#{not_local_tag} do
gem "activesupport"
end
G
- system_gems "rack-1.0.0", path: default_bundle_path
+ system_gems "myrack-1.0.0", path: default_bundle_path
lockfile <<-G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
activesupport (2.3.5)
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{generic_local_platform}
#{not_local}
DEPENDENCIES
- rack
+ myrack
activesupport
G
@@ -186,28 +204,28 @@ RSpec.describe "bundle check" do
it "works with env conditionals" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
env :NOT_GOING_TO_BE_SET do
gem "activesupport"
end
G
- system_gems "rack-1.0.0", path: default_bundle_path
+ system_gems "myrack-1.0.0", path: default_bundle_path
lockfile <<-G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
activesupport (2.3.5)
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{generic_local_platform}
#{not_local}
DEPENDENCIES
- rack
+ myrack
activesupport
G
@@ -227,9 +245,9 @@ RSpec.describe "bundle check" do
expect(err).not_to include("Unfortunately, a fatal error has occurred. ")
end
- it "fails when there's no lock file and frozen is set" do
+ it "fails when there's no lockfile and frozen is set" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo"
G
@@ -241,52 +259,12 @@ RSpec.describe "bundle check" do
expect(last_command).to be_failure
end
- context "--path", bundler: "< 3" do
- context "after installing gems in the proper directory" do
- before do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rails"
- G
- bundle "install --path vendor/bundle"
-
- FileUtils.rm_rf(bundled_app(".bundle"))
- end
-
- it "returns success" do
- 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"
- end
- end
-
- context "after installing gems on a different directory" do
- before do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rails"
- G
-
- bundle "check --path vendor/bundle", raise_on_error: false
- end
-
- it "returns false" do
- expect(exitstatus).to eq(1)
- expect(err).to match(/The following gems are missing/)
- end
- end
- end
-
describe "when locked" do
before :each do
- system_gems "rack-1.0.0"
+ system_gems "myrack-1.0.0"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "1.0"
+ source "https://gem.repo1"
+ gem "myrack", "1.0"
G
end
@@ -297,29 +275,30 @@ RSpec.describe "bundle check" do
end
it "shows what is missing with the current Gemfile if it is not satisfied" do
- simulate_new_machine
+ FileUtils.rm_r default_bundle_path
+ default_system_gems
bundle :check, raise_on_error: false
expect(err).to match(/The following gems are missing/)
- expect(err).to include("* rack (1.0")
+ expect(err).to include("* myrack (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"
+ build_gem "depends_on_myrack" do |s|
+ s.add_dependency "myrack", ">= 1.0"
end
- build_gem "also_depends_on_rack" do |s|
- s.add_dependency "rack", "~> 1.0"
+ build_gem "also_depends_on_myrack" do |s|
+ s.add_dependency "myrack", "~> 1.0"
end
- build_gem "rack"
+ build_gem "myrack"
end
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
- gem "depends_on_rack"
- gem "also_depends_on_rack"
+ source "https://gem.repo4"
+ gem "depends_on_myrack"
+ gem "also_depends_on_myrack"
G
bundle "lock"
@@ -328,59 +307,59 @@ RSpec.describe "bundle check" do
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
+ expect(err).to include("* myrack (1.0").once
end
end
describe "when locked under multiple platforms" do
before :each do
build_repo4 do
- build_gem "rack"
+ build_gem "myrack"
end
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
- gem "rack"
+ source "https://gem.repo4"
+ gem "myrack"
G
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
- rack (1.0)
+ myrack (1.0)
PLATFORMS
ruby
#{local_platform}
DEPENDENCIES
- rack
+ myrack
BUNDLED WITH
- #{Bundler::VERSION}
+ #{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
+ expect(err).to include("* myrack (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"
+ source "https://gem.repo2"
+ source "https://gem.repo1" do
+ gem "myrack"
end
G
end
it "returns success when the Gemfile is satisfied" do
- system_gems "rack-1.0.0", path: default_bundle_path
- bundle :check
+ system_gems "myrack-1.0.0", path: default_bundle_path
+ bundle :check, artifice: "compact_index"
expect(out).to include("The Gemfile's dependencies are satisfied")
end
end
@@ -388,51 +367,51 @@ RSpec.describe "bundle check" do
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"
+ build_gem "depends_on_myrack" do |s|
+ s.add_dependency "myrack"
end
- build_gem "rack"
+ build_gem "myrack"
end
gemfile <<~G
- source "#{file_uri_for(gem_repo1)}"
- source "#{file_uri_for(gem_repo4)}" do
- gem "depends_on_rack"
+ source "https://gem.repo1"
+ source "https://gem.repo4" do
+ gem "depends_on_myrack"
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
+ system_gems "depends_on_myrack-1.0", "myrack-1.0", gem_repo: gem_repo4, path: default_bundle_path
+ bundle :check, artifice: "compact_index"
- checksums = checksums_section_when_existing do |c|
- c.no_checksum "depends_on_rack", "1.0"
- c.no_checksum "rack", "1.0"
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "depends_on_myrack", "1.0"
+ c.checksum gem_repo4, "myrack", "1.0"
end
expect(out).to include("The Gemfile's dependencies are satisfied")
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
- depends_on_rack (1.0)
- rack
- rack (1.0)
+ depends_on_myrack (1.0)
+ myrack
+ myrack (1.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- depends_on_rack!
+ depends_on_myrack!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
@@ -447,7 +426,7 @@ RSpec.describe "bundle check" do
build_gem "dex-dispatch-engine"
end
- build_lib("bundle-check-issue", path: tmp.join("bundle-check-issue")) do |s|
+ build_lib("bundle-check-issue", path: tmp("bundle-check-issue")) do |s|
s.write "Gemfile", <<-G
source "https://localgemserver.test"
@@ -461,22 +440,24 @@ RSpec.describe "bundle check" do
s.add_dependency "awesome_print"
end
- bundle "install", artifice: "compact_index_extra", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }, dir: tmp.join("bundle-check-issue")
+ bundle "install", artifice: "compact_index_extra", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }, dir: tmp("bundle-check-issue")
end
it "does not corrupt lockfile when changing version" do
- version_file = tmp.join("bundle-check-issue/bundle-check-issue.gemspec")
+ version_file = tmp("bundle-check-issue/bundle-check-issue.gemspec")
File.write(version_file, File.read(version_file).gsub(/s\.version = .+/, "s.version = '9999'"))
- bundle "check --verbose", dir: tmp.join("bundle-check-issue")
+ bundle "check --verbose", dir: tmp("bundle-check-issue")
- checksums = checksums_section_when_existing do |c|
+ lockfile = File.read(tmp("bundle-check-issue/Gemfile.lock"))
+
+ checksums = checksums_section_when_enabled(lockfile) do |c|
c.checksum gem_repo4, "awesome_print", "1.0"
c.no_checksum "bundle-check-issue", "9999"
c.checksum gem_repo2, "dex-dispatch-engine", "1.0"
end
- expect(File.read(tmp.join("bundle-check-issue/Gemfile.lock"))).to eq <<~L
+ expect(lockfile).to eq <<~L
PATH
remote: .
specs:
@@ -501,24 +482,78 @@ RSpec.describe "bundle check" do
dex-dispatch-engine!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
+ context "with scoped and unscoped sources" do
+ it "does not corrupt lockfile" do
+ build_repo2 do
+ build_gem "foo"
+ build_gem "wadus"
+ build_gem("baz") {|s| s.add_dependency "wadus" }
+ end
+
+ build_repo4 do
+ build_gem "bar"
+ end
+
+ bundle "config set path.system true"
+
+ # Add all gems to ensure all gems are installed so that a bundle check
+ # would be successful
+ install_gemfile(<<-G, artifice: "compact_index_extra")
+ source "https://gem.repo2"
+
+ source "https://gem.repo4" do
+ gem "bar"
+ end
+
+ gem "foo"
+ gem "baz"
+ G
+
+ original_lockfile = lockfile
+
+ # Remove "baz" gem from the Gemfile, and bundle install again to generate
+ # a functional lockfile with no "baz" dependency or "wadus" transitive
+ # dependency
+ install_gemfile(<<-G, artifice: "compact_index_extra")
+ source "https://gem.repo2"
+
+ source "https://gem.repo4" do
+ gem "bar"
+ end
+
+ gem "foo"
+ G
+
+ # Add back "baz" gem back to the Gemfile, but _crucially_ we do not perform a
+ # bundle install
+ gemfile(gemfile + 'gem "baz"')
+
+ bundle :check, verbose: true
+
+ # Bundle check should succeed and restore the lockfile to its original
+ # state
+ expect(lockfile).to eq(original_lockfile)
+ end
+ end
+
describe "BUNDLED WITH" do
def lock_with(bundler_version = nil)
lock = <<~L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
L
if bundler_version
@@ -532,8 +567,8 @@ RSpec.describe "bundle check" do
bundle "config set --local path vendor/bundle"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
end
diff --git a/spec/bundler/commands/clean_spec.rb b/spec/bundler/commands/clean_spec.rb
index 0b559a87c8..793aacf5c2 100644
--- a/spec/bundler/commands/clean_spec.rb
+++ b/spec/bundler/commands/clean_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe "bundle clean" do
it "removes unused gems that are different" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "thin"
gem "foo"
@@ -30,7 +30,7 @@ RSpec.describe "bundle clean" do
bundle "install"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "thin"
G
@@ -40,17 +40,17 @@ RSpec.describe "bundle clean" do
expect(out).to include("Removing foo (1.0)")
- should_have_gems "thin-1.0", "rack-1.0.0"
+ should_have_gems "thin-1.0", "myrack-1.0.0"
should_not_have_gems "foo-1.0"
- expect(vendored_gems("bin/rackup")).to exist
+ expect(vendored_gems("bin/myrackup")).to exist
end
it "removes old version of gem if unused" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack", "0.9.1"
+ gem "myrack", "0.9.1"
gem "foo"
G
@@ -59,28 +59,28 @@ RSpec.describe "bundle clean" do
bundle "install"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
gem "foo"
G
bundle "install"
bundle :clean
- expect(out).to include("Removing rack (0.9.1)")
+ expect(out).to include("Removing myrack (0.9.1)")
- should_have_gems "foo-1.0", "rack-1.0.0"
- should_not_have_gems "rack-0.9.1"
+ should_have_gems "foo-1.0", "myrack-1.0.0"
+ should_not_have_gems "myrack-0.9.1"
- expect(vendored_gems("bin/rackup")).to exist
+ expect(vendored_gems("bin/myrackup")).to exist
end
it "removes new version of gem if unused" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
gem "foo"
G
@@ -89,31 +89,31 @@ RSpec.describe "bundle clean" do
bundle "install"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack", "0.9.1"
+ gem "myrack", "0.9.1"
gem "foo"
G
- bundle "update rack"
+ bundle "update myrack"
bundle :clean
- expect(out).to include("Removing rack (1.0.0)")
+ expect(out).to include("Removing myrack (1.0.0)")
- should_have_gems "foo-1.0", "rack-0.9.1"
- should_not_have_gems "rack-1.0.0"
+ should_have_gems "foo-1.0", "myrack-0.9.1"
+ should_not_have_gems "myrack-1.0.0"
- expect(vendored_gems("bin/rackup")).to exist
+ expect(vendored_gems("bin/myrackup")).to exist
end
it "removes gems in bundle without groups" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo"
group :test_group do
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
end
G
@@ -123,12 +123,12 @@ RSpec.describe "bundle clean" do
bundle "install"
bundle :clean
- expect(out).to include("Removing rack (1.0.0)")
+ expect(out).to include("Removing myrack (1.0.0)")
should_have_gems "foo-1.0"
- should_not_have_gems "rack-1.0.0"
+ should_not_have_gems "myrack-1.0.0"
- expect(vendored_gems("bin/rackup")).to_not exist
+ expect(vendored_gems("bin/myrackup")).to_not exist
end
it "does not remove cached git dir if it's being used" do
@@ -137,9 +137,9 @@ RSpec.describe "bundle clean" do
git_path = lib_path("foo-1.0")
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
git "#{git_path}", :ref => "#{revision}" do
gem "foo"
end
@@ -151,7 +151,7 @@ RSpec.describe "bundle clean" do
bundle :clean
digest = Digest(:SHA1).hexdigest(git_path.to_s)
- cache_path = Bundler::VERSION.start_with?("2.") ? vendored_gems("cache/bundler/git/foo-1.0-#{digest}") : home(".bundle/cache/git/foo-1.0-#{digest}")
+ cache_path = vendored_gems("cache/bundler/git/foo-1.0-#{digest}")
expect(cache_path).to exist
end
@@ -161,9 +161,9 @@ RSpec.describe "bundle clean" do
revision = revision_for(git_path)
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
git "#{git_path}", :ref => "#{revision}" do
gem "foo"
end
@@ -173,9 +173,9 @@ RSpec.describe "bundle clean" do
bundle "install"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
G
bundle "install"
@@ -183,14 +183,14 @@ RSpec.describe "bundle clean" do
expect(out).to include("Removing foo (#{revision[0..11]})")
- expect(vendored_gems("gems/rack-1.0.0")).to exist
+ expect(vendored_gems("gems/myrack-1.0.0")).to exist
expect(vendored_gems("bundler/gems/foo-#{revision[0..11]}")).not_to exist
digest = Digest(:SHA1).hexdigest(git_path.to_s)
expect(vendored_gems("cache/bundler/git/foo-#{digest}")).not_to exist
- expect(vendored_gems("specifications/rack-1.0.0.gemspec")).to exist
+ expect(vendored_gems("specifications/myrack-1.0.0.gemspec")).to exist
- expect(vendored_gems("bin/rackup")).to exist
+ expect(vendored_gems("bin/myrackup")).to exist
end
it "keeps used git gems even if installed to a symlinked location" do
@@ -199,9 +199,9 @@ RSpec.describe "bundle clean" do
revision = revision_for(git_path)
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
git "#{git_path}", :ref => "#{revision}" do
gem "foo"
end
@@ -220,14 +220,14 @@ RSpec.describe "bundle clean" do
expect(bundled_app("symlink-path/#{Bundler.ruby_scope}/bundler/gems/foo-#{revision[0..11]}")).to exist
end
- it "removes old git gems" do
+ it "removes old git gems on bundle update" do
build_git "foo-bar", path: lib_path("foo-bar")
revision = revision_for(lib_path("foo-bar"))
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
git "#{lib_path("foo-bar")}" do
gem "foo-bar"
end
@@ -244,13 +244,13 @@ RSpec.describe "bundle clean" do
expect(out).to include("Removing foo-bar (#{revision[0..11]})")
- expect(vendored_gems("gems/rack-1.0.0")).to exist
+ expect(vendored_gems("gems/myrack-1.0.0")).to exist
expect(vendored_gems("bundler/gems/foo-bar-#{revision[0..11]}")).not_to exist
expect(vendored_gems("bundler/gems/foo-bar-#{revision2[0..11]}")).to exist
- expect(vendored_gems("specifications/rack-1.0.0.gemspec")).to exist
+ expect(vendored_gems("specifications/myrack-1.0.0.gemspec")).to exist
- expect(vendored_gems("bin/rackup")).to exist
+ expect(vendored_gems("bin/myrackup")).to exist
end
it "does not remove nested gems in a git repo" do
@@ -261,7 +261,7 @@ RSpec.describe "bundle clean" do
revision = revision_for(lib_path("rails"))
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "activesupport", :git => "#{lib_path("rails")}", :ref => '#{revision}'
G
@@ -279,9 +279,9 @@ RSpec.describe "bundle clean" do
revision = revision_for(git_path)
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
group :test do
git "#{git_path}", :ref => "#{revision}" do
gem "foo"
@@ -302,9 +302,9 @@ RSpec.describe "bundle clean" do
it "does not blow up when using without groups" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
group :development do
gem "foo"
@@ -321,9 +321,9 @@ RSpec.describe "bundle clean" do
it "displays an error when used without --path" do
bundle "config set path.system true"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
G
bundle :clean, raise_on_error: false
@@ -335,7 +335,7 @@ RSpec.describe "bundle clean" do
# handling bundle clean upgrade path from the pre's
it "removes .gem/.gemspec file even if there's no corresponding gem dir" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "thin"
gem "foo"
@@ -345,77 +345,52 @@ RSpec.describe "bundle clean" do
bundle "install"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo"
G
bundle "install"
- FileUtils.rm(vendored_gems("bin/rackup"))
- FileUtils.rm_rf(vendored_gems("gems/thin-1.0"))
- FileUtils.rm_rf(vendored_gems("gems/rack-1.0.0"))
+ FileUtils.rm(vendored_gems("bin/myrackup"))
+ FileUtils.rm_r(vendored_gems("gems/thin-1.0"))
+ FileUtils.rm_r(vendored_gems("gems/myrack-1.0.0"))
bundle :clean
- should_not_have_gems "thin-1.0", "rack-1.0"
+ should_not_have_gems "thin-1.0", "myrack-1.0"
should_have_gems "foo-1.0"
- expect(vendored_gems("bin/rackup")).not_to exist
+ expect(vendored_gems("bin/myrackup")).not_to exist
end
it "does not call clean automatically when using system gems" do
bundle "config set path.system true"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "thin"
- gem "rack"
+ gem "myrack"
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
G
gem_command :list
- expect(out).to include("rack (1.0.0)").and include("thin (1.0)")
+ expect(out).to include("myrack (1.0.0)").and include("thin (1.0)")
end
- it "--clean should override the bundle setting on install", bundler: "< 3" do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
-
- gem "thin"
- gem "rack"
- G
- bundle "config set path vendor/bundle"
- bundle "config set clean false"
- bundle "install --clean true"
-
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
-
- gem "rack"
- G
- bundle "install"
-
- should_have_gems "rack-1.0.0"
- should_not_have_gems "thin-1.0"
- end
-
- it "--clean should override the bundle setting on update", bundler: "< 3" do
+ it "does not clean on bundle update when path has not been set" do
build_repo2
- gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ install_gemfile <<-G
+ source "https://gem.repo2"
gem "foo"
G
- bundle "config set path vendor/bundle"
- bundle "config set clean false"
- bundle "install --clean true"
update_repo2 do
build_gem "foo", "1.0.1"
@@ -423,15 +398,31 @@ RSpec.describe "bundle clean" do
bundle "update", all: true
- should_have_gems "foo-1.0.1"
- should_not_have_gems "foo-1.0"
+ files = Pathname.glob(default_bundle_path("*", "*"))
+ files.map! {|f| f.to_s.sub(default_bundle_path.to_s, "") }
+ expected_files = %W[
+ /bin/bundle
+ /bin/bundler
+ /cache/bundler-#{Bundler::VERSION}.gem
+ /cache/foo-1.0.1.gem
+ /cache/foo-1.0.gem
+ /gems/bundler-#{Bundler::VERSION}
+ /gems/foo-1.0
+ /gems/foo-1.0.1
+ /specifications/bundler-#{Bundler::VERSION}.gemspec
+ /specifications/foo-1.0.1.gemspec
+ /specifications/foo-1.0.gemspec
+ ]
+ expected_files += ["/bin/bundle.bat", "/bin/bundler.bat"] if Gem.win_platform?
+
+ expect(files.sort).to eq(expected_files.sort)
end
- it "automatically cleans when path has not been set", bundler: "3" do
+ it "will automatically clean on bundle update when path has not been set", bundler: "5" do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "foo"
G
@@ -442,8 +433,8 @@ RSpec.describe "bundle clean" do
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, "") }
+ files = Pathname.glob(local_gem_path("*", "*"))
+ files.map! {|f| f.to_s.sub(local_gem_path.to_s, "") }
expect(files.sort).to eq %w[
/cache/foo-1.0.1.gem
/gems/foo-1.0.1
@@ -451,31 +442,31 @@ RSpec.describe "bundle clean" do
]
end
- it "does not clean automatically on --path" do
+ it "does not clean automatically when path configured" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "thin"
- gem "rack"
+ gem "myrack"
G
bundle "config set path vendor/bundle"
bundle "install"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
G
bundle "install"
- should_have_gems "rack-1.0.0", "thin-1.0"
+ should_have_gems "myrack-1.0.0", "thin-1.0"
end
- it "does not clean on bundle update with --path" do
+ it "does not clean on bundle update when path configured" do
build_repo2
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "foo"
G
@@ -490,13 +481,13 @@ RSpec.describe "bundle clean" do
should_have_gems "foo-1.0", "foo-1.0.1"
end
- it "does not clean on bundle update when using --system" do
+ it "does not clean on bundle update when installing to system gems" do
bundle "config set path.system true"
build_repo2
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "foo"
G
@@ -515,17 +506,17 @@ RSpec.describe "bundle clean" do
bundle "config set path.system true"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo"
- gem "rack"
+ gem "myrack"
G
bundle :install
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
G
bundle :install
bundle "clean --force"
@@ -533,7 +524,7 @@ RSpec.describe "bundle clean" do
expect(out).to include("Removing foo (1.0)")
gem_command :list
expect(out).not_to include("foo (1.0)")
- expect(out).to include("rack (1.0.0)")
+ expect(out).to include("myrack (1.0.0)")
end
describe "when missing permissions", :permissions do
@@ -544,17 +535,17 @@ RSpec.describe "bundle clean" do
end
it "returns a helpful error message" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo"
- gem "rack"
+ gem "myrack"
G
bundle :install
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
G
bundle :install
@@ -567,7 +558,7 @@ RSpec.describe "bundle clean" do
gem_command :list
expect(out).to include("foo (1.0)")
- expect(out).to include("rack (1.0.0)")
+ expect(out).to include("myrack (1.0.0)")
end
end
@@ -576,7 +567,7 @@ RSpec.describe "bundle clean" do
revision = revision_for(lib_path("foo-1.0"))
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
@@ -612,7 +603,7 @@ RSpec.describe "bundle clean" do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "bindir"
G
@@ -625,7 +616,7 @@ RSpec.describe "bundle clean" do
expect(out).to eq("1.0")
end
- it "when using --force, it doesn't remove default gem binaries", :realworld do
+ it "when using --force, it doesn't remove default gem binaries" do
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?
@@ -634,10 +625,8 @@ RSpec.describe "bundle clean" do
s.executables = "irb"
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)}"
+ source "https://gem.repo2"
G
bundle "clean --force", env: { "BUNDLER_GEM_DEFAULT_DIR" => system_gem_path.to_s }
@@ -654,7 +643,7 @@ RSpec.describe "bundle clean" do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo"
gem "bar", "1.0", :path => "#{relative_path}"
@@ -667,7 +656,7 @@ RSpec.describe "bundle clean" do
it "doesn't remove gems in dry-run mode with path set" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "thin"
gem "foo"
@@ -678,7 +667,7 @@ RSpec.describe "bundle clean" do
bundle "install"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "thin"
G
@@ -690,14 +679,14 @@ RSpec.describe "bundle clean" do
expect(out).not_to include("Removing foo (1.0)")
expect(out).to include("Would have removed foo (1.0)")
- should_have_gems "thin-1.0", "rack-1.0.0", "foo-1.0"
+ should_have_gems "thin-1.0", "myrack-1.0.0", "foo-1.0"
- expect(vendored_gems("bin/rackup")).to exist
+ expect(vendored_gems("bin/myrackup")).to exist
end
it "doesn't remove gems in dry-run mode with no path set" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "thin"
gem "foo"
@@ -708,7 +697,7 @@ RSpec.describe "bundle clean" do
bundle "install"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "thin"
G
@@ -720,14 +709,14 @@ RSpec.describe "bundle clean" do
expect(out).not_to include("Removing foo (1.0)")
expect(out).to include("Would have removed foo (1.0)")
- should_have_gems "thin-1.0", "rack-1.0.0", "foo-1.0"
+ should_have_gems "thin-1.0", "myrack-1.0.0", "foo-1.0"
- expect(vendored_gems("bin/rackup")).to exist
+ expect(vendored_gems("bin/myrackup")).to exist
end
it "doesn't store dry run as a config setting" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "thin"
gem "foo"
@@ -739,7 +728,7 @@ RSpec.describe "bundle clean" do
bundle "config set dry_run false"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "thin"
G
@@ -751,15 +740,15 @@ RSpec.describe "bundle clean" do
expect(out).to include("Removing foo (1.0)")
expect(out).not_to include("Would have removed foo (1.0)")
- should_have_gems "thin-1.0", "rack-1.0.0"
+ should_have_gems "thin-1.0", "myrack-1.0.0"
should_not_have_gems "foo-1.0"
- expect(vendored_gems("bin/rackup")).to exist
+ expect(vendored_gems("bin/myrackup")).to exist
end
it "performs an automatic bundle install" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "thin"
gem "foo"
@@ -770,7 +759,7 @@ RSpec.describe "bundle clean" do
bundle "install"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "thin"
gem "weakling"
@@ -779,7 +768,7 @@ RSpec.describe "bundle clean" do
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_have_gems "thin-1.0", "myrack-1.0.0", "weakling-0.0.3"
should_not_have_gems "foo-1.0"
end
@@ -789,7 +778,7 @@ RSpec.describe "bundle clean" do
revision = revision_for(lib_path("very_simple_git_binary-1.0"))
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "very_simple_git_binary", :git => "#{lib_path("very_simple_git_binary-1.0")}", :ref => "#{revision}"
G
@@ -808,7 +797,7 @@ RSpec.describe "bundle clean" do
it "removes extension directories" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "thin"
gem "very_simple_binary"
@@ -828,7 +817,7 @@ RSpec.describe "bundle clean" do
expect(simple_binary_extensions_dir).to exist
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "thin"
gem "simple_binary"
@@ -849,7 +838,7 @@ RSpec.describe "bundle clean" do
short_revision = revision[0..11]
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "thin"
gem "very_simple_git_binary", :git => "#{lib_path("very_simple_git_binary-1.0")}", :ref => "#{revision}"
@@ -864,7 +853,7 @@ RSpec.describe "bundle clean" do
expect(very_simple_binary_extensions_dir).to exist
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "very_simple_git_binary", :git => "#{lib_path("very_simple_git_binary-1.0")}", :ref => "#{revision}"
G
@@ -874,7 +863,7 @@ RSpec.describe "bundle clean" do
expect(very_simple_binary_extensions_dir).to exist
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
bundle "install"
@@ -891,7 +880,7 @@ RSpec.describe "bundle clean" do
short_revision = revision[0..11]
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
group :development do
gem "very_simple_git_binary", :git => "#{lib_path("very_simple_git_binary-1.0")}", :ref => "#{revision}"
@@ -909,4 +898,41 @@ RSpec.describe "bundle clean" do
expect(very_simple_binary_extensions_dir).to be_nil
end
+
+ it "does not remove the bundler version currently running" do
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ gem "myrack"
+ G
+
+ bundle "config set path vendor/bundle"
+ bundle "install"
+
+ version = Bundler.gem_version.to_s
+ # Simulate that the locked bundler version is installed in the bundle path
+ # by creating the gem directory and gemspec (as would happen after bundle install with that version)
+ Pathname(vendored_gems("cache/bundler-#{version}.gem")).tap do |path|
+ path.basename.mkpath
+ FileUtils.touch(path)
+ end
+ FileUtils.touch(vendored_gems("gems/bundler-#{version}"))
+ Pathname(vendored_gems("specifications/bundler-#{version}.gemspec")).tap do |path|
+ path.basename.mkpath
+ path.write(<<~GEMSPEC)
+ Gem::Specification.new do |s|
+ s.name = "bundler"
+ s.version = "#{version}"
+ s.authors = ["bundler team"]
+ s.summary = "The best way to manage your application's dependencies"
+ end
+ GEMSPEC
+ end
+
+ should_have_gems "bundler-#{version}"
+
+ bundle :clean
+
+ should_have_gems "bundler-#{version}"
+ end
end
diff --git a/spec/bundler/commands/config_spec.rb b/spec/bundler/commands/config_spec.rb
index a1a6b3bd34..954cae09d8 100644
--- a/spec/bundler/commands/config_spec.rb
+++ b/spec/bundler/commands/config_spec.rb
@@ -38,8 +38,8 @@ RSpec.describe ".bundle/config" do
describe "location with a gemfile" do
before :each do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "1.0.0"
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0"
G
end
@@ -56,7 +56,7 @@ RSpec.describe ".bundle/config" do
expect(bundled_app(".bundle")).not_to exist
expect(tmp("foo/bar/config")).to exist
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "can provide a relative path with the environment variable" do
@@ -68,7 +68,7 @@ RSpec.describe ".bundle/config" do
expect(bundled_app(".bundle")).not_to exist
expect(bundled_app("../foo/config")).to exist
- expect(the_bundle).to include_gems "rack 1.0.0", dir: bundled_app("omg")
+ expect(the_bundle).to include_gems "myrack 1.0.0", dir: bundled_app("omg")
end
end
@@ -123,8 +123,8 @@ RSpec.describe ".bundle/config" do
describe "global" do
before(:each) do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "1.0.0"
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0"
G
end
@@ -215,8 +215,8 @@ RSpec.describe ".bundle/config" do
describe "local" do
before(:each) do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "1.0.0"
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0"
G
end
@@ -271,8 +271,8 @@ RSpec.describe ".bundle/config" do
describe "env" do
before(:each) do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "1.0.0"
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0"
G
end
@@ -344,8 +344,8 @@ RSpec.describe ".bundle/config" do
describe "gem mirrors" do
before(:each) do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "1.0.0"
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0"
G
end
@@ -358,10 +358,16 @@ end
E
expect(out).to eq("http://gems.example.org/ => http://gem-mirror.example.org/")
end
+
+ it "allows configuring fallback timeout for each mirror, and does not duplicate configs", rubygems: ">= 3.5.12" do
+ bundle "config set --global mirror.https://rubygems.org.fallback_timeout 1"
+ bundle "config set --global mirror.https://rubygems.org.fallback_timeout 2"
+ expect(File.read(home(".bundle/config"))).to include("BUNDLE_MIRROR").once
+ end
end
describe "quoting" do
- before(:each) { gemfile "source \"#{file_uri_for(gem_repo1)}\"" }
+ before(:each) { gemfile "source 'https://gem.repo1'" }
let(:long_string) do
"--with-xml2-include=/usr/pkg/include/libxml2 --with-xml2-lib=/usr/pkg/lib " \
"--with-xslt-dir=/usr/pkg"
@@ -411,8 +417,8 @@ E
describe "very long lines" do
before(:each) do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "1.0.0"
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0"
G
end
@@ -447,7 +453,7 @@ E
it "does not make bundler crash and ignores the configuration" do
bundle "config list --parseable"
- expect(out).to eq("#mirror.https://rails-assets.org/=http://localhost:9292")
+ expect(out).to be_empty
expect(err).to be_empty
ruby(<<~RUBY)
@@ -574,8 +580,8 @@ RSpec.describe "setting gemfile via config" do
context "when only the non-default Gemfile exists" do
it "persists the gemfile location to .bundle/config" do
gemfile bundled_app("NotGemfile"), <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
bundle "config set --local gemfile #{bundled_app("NotGemfile")}"
@@ -586,3 +592,20 @@ RSpec.describe "setting gemfile via config" do
end
end
end
+
+RSpec.describe "setting lockfile via config" do
+ it "persists the lockfile location to .bundle/config" do
+ gemfile bundled_app("NotGemfile"), <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
+ G
+
+ bundle "config set --local gemfile #{bundled_app("NotGemfile")}"
+ bundle "config set --local lockfile #{bundled_app("ReallyNotGemfile.lock")}"
+ expect(File.exist?(bundled_app(".bundle/config"))).to eq(true)
+
+ bundle "config list"
+ expect(out).to include("NotGemfile")
+ expect(out).to include("ReallyNotGemfile.lock")
+ end
+end
diff --git a/spec/bundler/commands/console_spec.rb b/spec/bundler/commands/console_spec.rb
index a41432b88a..ec44fe59f3 100644
--- a/spec/bundler/commands/console_spec.rb
+++ b/spec/bundler/commands/console_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.describe "bundle console", bundler: "< 3", readline: true do
+RSpec.describe "bundle console", readline: true do
before :each do
build_repo2 do
# A minimal fake pry console
@@ -35,107 +35,180 @@ RSpec.describe "bundle console", bundler: "< 3", readline: true do
end
RUBY
end
- end
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack"
- gem "activesupport", :group => :test
- gem "rack_middleware", :group => :development
- G
+ build_dummy_irb
+ end
end
- it "starts IRB with the default group loaded" do
- bundle "console" do |input, _, _|
- input.puts("puts RACK")
- input.puts("exit")
+ context "when the library requires a non-existent file" do
+ before do
+ build_lib "loadfuuu", "1.0.0" do |s|
+ s.write "lib/loadfuuu.rb", "require_relative 'loadfuuu/bar'"
+ s.write "lib/loadfuuu/bar.rb", "require 'not-in-bundle'"
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "irb"
+ path "#{lib_path}" do
+ gem "loadfuuu", require: true
+ end
+ G
end
- expect(out).to include("0.9.1")
- end
- it "uses IRB as default console" do
- bundle "console" do |input, _, _|
- input.puts("__FILE__")
- input.puts("exit")
+ it "does not show the bug report template" do
+ bundle("console", raise_on_error: false) do |input, _, _|
+ input.puts("exit")
+ end
+
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
end
- expect(out).to include("(irb)")
end
- it "starts another REPL if configured as such" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "pry"
- G
- bundle "config set console pry"
+ context "when the library references a non-existent constant" do
+ before do
+ build_lib "loadfuuu", "1.0.0" do |s|
+ s.write "lib/loadfuuu.rb", "Some::NonExistent::Constant"
+ end
- bundle "console" do |input, _, _|
- input.puts("__method__")
- input.puts("exit")
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "irb"
+ path "#{lib_path}" do
+ gem "loadfuuu", require: true
+ end
+ G
end
- expect(out).to include(":__pry__")
- end
- it "falls back to IRB if the other REPL isn't available" do
- bundle "config set console pry"
- # make sure pry isn't there
+ it "does not show the bug report template" do
+ bundle("console", raise_on_error: false) do |input, _, _|
+ input.puts("exit")
+ end
- bundle "console" do |input, _, _|
- input.puts("__FILE__")
- input.puts("exit")
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
end
- expect(out).to include("(irb)")
end
- it "doesn't load any other groups" do
- bundle "console" do |input, _, _|
- input.puts("puts ACTIVESUPPORT")
- input.puts("exit")
+ context "when the library does not have any errors" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "irb"
+ gem "myrack"
+ gem "activesupport", :group => :test
+ gem "myrack_middleware", :group => :development
+ G
end
- expect(out).to include("NameError")
- end
- describe "when given a group" do
- it "loads the given group" do
- bundle "console test" do |input, _, _|
- input.puts("puts ACTIVESUPPORT")
+ it "starts IRB with the default group loaded" do
+ bundle "console" do |input, _, _|
+ input.puts("puts MYRACK")
input.puts("exit")
end
- expect(out).to include("2.3.5")
+ expect(out).to include("0.9.1")
end
- it "loads the default group" do
- bundle "console test" do |input, _, _|
- input.puts("puts RACK")
+ it "uses IRB as default console" do
+ skip "Does not work in a ruby-core context if irb is in the default $LOAD_PATH because it enables the real IRB, not our dummy one" if ruby_core? && Gem.ruby_version < Gem::Version.new("3.5.0.a")
+
+ bundle "console" do |input, _, _|
+ input.puts("__method__")
input.puts("exit")
end
- expect(out).to include("0.9.1")
+ expect(out).to include("__irb__")
+ end
+
+ it "starts another REPL if configured as such" do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "irb"
+ gem "pry"
+ G
+ bundle "config set console pry"
+
+ bundle "console" do |input, _, _|
+ input.puts("__method__")
+ input.puts("exit")
+ end
+ expect(out).to include(":__pry__")
+ end
+
+ it "falls back to IRB if the other REPL isn't available" do
+ skip "Does not work in a ruby-core context if irb is in the default $LOAD_PATH because it enables the real IRB, not our dummy one" if ruby_core? && Gem.ruby_version < Gem::Version.new("3.5.0.a")
+
+ bundle "config set console pry"
+ # make sure pry isn't there
+
+ bundle "console" do |input, _, _|
+ input.puts("__method__")
+ input.puts("exit")
+ end
+ expect(out).to include("__irb__")
+ end
+
+ it "does not try IRB twice if no console is configured and IRB is not available" do
+ create_file("irb.rb", "raise LoadError, 'irb is not available'")
+
+ bundle("console", env: { "RUBYOPT" => "-I#{bundled_app} #{ENV["RUBYOPT"]}" }, raise_on_error: false) do |input, _, _|
+ input.puts("puts ACTIVESUPPORT")
+ input.puts("exit")
+ end
+ expect(err).not_to include("falling back to irb")
+ expect(err).to include("irb is not available")
end
- it "doesn't load other groups" do
- bundle "console test" do |input, _, _|
- input.puts("puts RACK_MIDDLEWARE")
+ it "doesn't load any other groups" do
+ bundle "console" do |input, _, _|
+ input.puts("puts ACTIVESUPPORT")
input.puts("exit")
end
expect(out).to include("NameError")
end
- end
- it "performs an automatic bundle install" do
- gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack"
- gem "activesupport", :group => :test
- gem "rack_middleware", :group => :development
- gem "foo"
- G
-
- bundle "config set auto_install 1"
- bundle :console do |input, _, _|
- input.puts("puts 'hello'")
- input.puts("exit")
+ describe "when given a group" do
+ it "loads the given group" do
+ bundle "console test" do |input, _, _|
+ input.puts("puts ACTIVESUPPORT")
+ input.puts("exit")
+ end
+ expect(out).to include("2.3.5")
+ end
+
+ it "loads the default group" do
+ bundle "console test" do |input, _, _|
+ input.puts("puts MYRACK")
+ input.puts("exit")
+ end
+ expect(out).to include("0.9.1")
+ end
+
+ it "doesn't load other groups" do
+ bundle "console test" do |input, _, _|
+ input.puts("puts MYRACK_MIDDLEWARE")
+ input.puts("exit")
+ end
+ expect(out).to include("NameError")
+ end
+ end
+
+ it "performs an automatic bundle install" do
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "irb"
+ gem "myrack"
+ gem "activesupport", :group => :test
+ gem "myrack_middleware", :group => :development
+ gem "foo"
+ G
+
+ bundle "config set auto_install 1"
+ bundle :console do |input, _, _|
+ input.puts("puts 'hello'")
+ input.puts("exit")
+ end
+ expect(out).to include("Installing foo 1.0")
+ expect(out).to include("hello")
+ expect(the_bundle).to include_gems "foo 1.0"
end
- expect(out).to include("Installing foo 1.0")
- expect(out).to include("hello")
- expect(the_bundle).to include_gems "foo 1.0"
end
end
diff --git a/spec/bundler/commands/doctor_spec.rb b/spec/bundler/commands/doctor_spec.rb
index 666b23a141..5ceaf37f29 100644
--- a/spec/bundler/commands/doctor_spec.rb
+++ b/spec/bundler/commands/doctor_spec.rb
@@ -4,17 +4,18 @@ require "find"
require "stringio"
require "bundler/cli"
require "bundler/cli/doctor"
+require "bundler/cli/doctor/diagnose"
RSpec.describe "bundle doctor" do
before(:each) do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
@stdout = StringIO.new
- [:error, :warn].each do |method|
+ [:error, :warn, :info].each do |method|
allow(Bundler.ui).to receive(method).and_wrap_original do |m, message|
m.call message
@stdout.puts message
@@ -45,29 +46,37 @@ RSpec.describe "bundle doctor" do
allow(File).to receive(:writable?).with(File.expand_path("..", Gem.default_dir))
end
- it "exits with no message if the installed gem has no C extensions" do
- expect { Bundler::CLI::Doctor.new({}).run }.not_to raise_error
- expect(@stdout.string).to be_empty
+ it "exits with a success message if the installed gem has no C extensions" do
+ doctor = Bundler::CLI::Doctor::Diagnose.new({})
+ allow(doctor).to receive(:lookup_with_fiddle).and_return(false)
+ expect { doctor.run }.not_to raise_error
+ expect(@stdout.string).to include("No issues")
end
- it "exits with no message if the installed gem's C extension dylib breakage is fine" do
- doctor = Bundler::CLI::Doctor.new({})
- expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/rack/rack.bundle"]
+ it "exits with a success message if the installed gem's C extension dylib breakage is fine" do
+ doctor = Bundler::CLI::Doctor::Diagnose.new({})
+ expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/myrack/myrack.bundle"]
expect(doctor).to receive(:dylibs).exactly(2).times.and_return ["/usr/lib/libSystem.dylib"]
- allow(Fiddle).to receive(:dlopen).with("/usr/lib/libSystem.dylib").and_return(true)
+ allow(doctor).to receive(:lookup_with_fiddle).with("/usr/lib/libSystem.dylib").and_return(false)
expect { doctor.run }.not_to raise_error
- expect(@stdout.string).to be_empty
+ expect(@stdout.string).to include("No issues")
+ end
+
+ it "parses otool output correctly" do
+ doctor = Bundler::CLI::Doctor::Diagnose.new({})
+ expect(doctor).to receive(:`).with("/usr/bin/otool -L fake").and_return("/home/gem/ruby/3.4.3/gems/blake3-rb-1.5.4.4/lib/digest/blake3/blake3_ext.bundle:\n\t (compatibility version 0.0.0, current version 0.0.0)\n\t/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1351.0.0)")
+ expect(doctor.dylibs_darwin("fake")).to eq(["/usr/lib/libSystem.B.dylib"])
end
it "exits with a message if one of the linked libraries is missing" do
- doctor = Bundler::CLI::Doctor.new({})
- expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/rack/rack.bundle"]
+ doctor = Bundler::CLI::Doctor::Diagnose.new({})
+ expect(doctor).to receive(:bundles_for_gem).exactly(2).times.and_return ["/path/to/myrack/myrack.bundle"]
expect(doctor).to receive(:dylibs).exactly(2).times.and_return ["/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib"]
- allow(Fiddle).to receive(:dlopen).with("/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib").and_raise(Fiddle::DLError)
+ allow(doctor).to receive(:lookup_with_fiddle).with("/usr/local/opt/icu4c/lib/libicui18n.57.1.dylib").and_return(true)
expect { doctor.run }.to raise_error(Bundler::ProductionError, <<~E.strip), @stdout.string
The following gems are missing OS dependencies:
* bundler: /usr/local/opt/icu4c/lib/libicui18n.57.1.dylib
- * rack: /usr/local/opt/icu4c/lib/libicui18n.57.1.dylib
+ * myrack: /usr/local/opt/icu4c/lib/libicui18n.57.1.dylib
E
end
end
@@ -82,7 +91,9 @@ RSpec.describe "bundle doctor" do
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
+ doctor = Bundler::CLI::Doctor::Diagnose.new({})
+ allow(doctor).to receive(:lookup_with_fiddle).and_return(false)
+ expect { doctor.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}"
)
@@ -101,38 +112,57 @@ RSpec.describe "bundle doctor" do
allow(File).to receive(:stat).with(@unwritable_file) { @stat }
end
- it "exits with an error if home contains files that are not readable/writable" do
+ it "exits with an error if home contains files that are not readable" do
+ doctor = Bundler::CLI::Doctor::Diagnose.new({})
+ allow(doctor).to receive(:lookup_with_fiddle).and_return(false)
allow(@stat).to receive(:uid) { Process.uid }
allow(File).to receive(:writable?).with(@unwritable_file) { false }
allow(File).to receive(:readable?).with(@unwritable_file) { false }
- expect { Bundler::CLI::Doctor.new({}).run }.not_to raise_error
+ expect { doctor.run }.not_to raise_error
expect(@stdout.string).to include(
- "Files exist in the Bundler home that are not readable/writable by the current user. These files are:\n - #{@unwritable_file}"
+ "Files exist in the Bundler home that are not readable by the current user. These files are:\n - #{@unwritable_file}"
)
expect(@stdout.string).not_to include("No issues")
end
+ it "exits without an error if home contains files that are not writable" do
+ doctor = Bundler::CLI::Doctor::Diagnose.new({})
+ allow(doctor).to receive(:lookup_with_fiddle).and_return(false)
+ allow(@stat).to receive(:uid) { Process.uid }
+ allow(File).to receive(:writable?).with(@unwritable_file) { false }
+ allow(File).to receive(:readable?).with(@unwritable_file) { true }
+ expect { doctor.run }.not_to raise_error
+ expect(@stdout.string).not_to include(
+ "Files exist in the Bundler home that are not readable by the current user. These files are:\n - #{@unwritable_file}"
+ )
+ expect(@stdout.string).to include("No issues")
+ end
+
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
it "exits with an error if home contains files that are not readable/writable and are not owned by the current user" do
+ doctor = Bundler::CLI::Doctor::Diagnose.new({})
+ allow(doctor).to receive(:lookup_with_fiddle).and_return(false)
allow(File).to receive(:writable?).with(@unwritable_file) { false }
allow(File).to receive(:readable?).with(@unwritable_file) { false }
- expect { Bundler::CLI::Doctor.new({}).run }.not_to raise_error
+ expect { doctor.run }.not_to raise_error
expect(@stdout.string).to include(
- "Files exist in the Bundler home that are owned by another user, and are not readable/writable. These files are:\n - #{@unwritable_file}"
+ "Files exist in the Bundler home that are owned by another user, and are not readable. These files are:\n - #{@unwritable_file}"
)
expect(@stdout.string).not_to include("No issues")
end
it "exits with a warning if home contains files that are read/write but not owned by current user" do
+ doctor = Bundler::CLI::Doctor::Diagnose.new({})
+ allow(doctor).to receive(:lookup_with_fiddle).and_return(false)
allow(File).to receive(:writable?).with(@unwritable_file) { true }
allow(File).to receive(:readable?).with(@unwritable_file) { true }
- expect { Bundler::CLI::Doctor.new({}).run }.not_to raise_error
+ expect { doctor.run }.not_to raise_error
expect(@stdout.string).to include(
- "Files exist in the Bundler home that are owned by another user, but are still readable/writable. These files are:\n - #{@unwritable_file}"
+ "Files exist in the Bundler home that are owned by another user, but are still readable. These files are:\n - #{@unwritable_file}"
)
expect(@stdout.string).not_to include("No issues")
end
@@ -141,7 +171,7 @@ RSpec.describe "bundle doctor" do
context "when home contains filenames with special characters" do
it "escape filename before command execute" do
- doctor = Bundler::CLI::Doctor.new({})
+ doctor = Bundler::CLI::Doctor::Diagnose.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")
diff --git a/spec/bundler/commands/exec_spec.rb b/spec/bundler/commands/exec_spec.rb
index 9f5f12739a..19e836053f 100644
--- a/spec/bundler/commands/exec_spec.rb
+++ b/spec/bundler/commands/exec_spec.rb
@@ -1,145 +1,126 @@
# frozen_string_literal: true
RSpec.describe "bundle exec" do
- let(:system_gems_to_install) { %w[rack-1.0.0 rack-0.9.1] }
-
it "works with --gemfile flag" do
- system_gems(system_gems_to_install, path: default_bundle_path)
+ system_gems(%w[myrack-1.0.0 myrack-0.9.1], path: default_bundle_path)
- create_file "CustomGemfile", <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "1.0.0"
+ gemfile "CustomGemfile", <<-G
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0"
G
- bundle "exec --gemfile CustomGemfile rackup"
+ bundle "exec --gemfile CustomGemfile myrackup"
expect(out).to eq("1.0.0")
end
it "activates the correct gem" do
- system_gems(system_gems_to_install, path: default_bundle_path)
+ system_gems(%w[myrack-1.0.0 myrack-0.9.1], path: default_bundle_path)
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "0.9.1"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
G
- bundle "exec rackup"
+ bundle "exec myrackup"
expect(out).to eq("0.9.1")
end
it "works and prints no warnings when HOME is not writable" do
- system_gems(system_gems_to_install, path: default_bundle_path)
+ system_gems(%w[myrack-1.0.0 myrack-0.9.1], path: default_bundle_path)
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "0.9.1"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
G
- bundle "exec rackup", env: { "HOME" => "/" }
+ bundle "exec myrackup", 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"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "exec rackup"
+ bundle "exec myrackup"
expect(out).to eq("1.0.0")
end
it "works when running from a random directory" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "exec 'cd #{tmp("gems")} && rackup'"
+ bundle "exec 'cd #{tmp("gems")} && myrackup'"
expect(out).to eq("1.0.0")
end
it "works when exec'ing something else" do
- install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\""
+ install_gemfile "source \"https://gem.repo1\"; gem \"myrack\""
bundle "exec echo exec"
expect(out).to eq("exec")
end
it "works when exec'ing to ruby" do
- install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\""
+ install_gemfile "source \"https://gem.repo1\"; gem \"myrack\""
bundle "exec ruby -e 'puts %{hi}'"
expect(out).to eq("hi")
end
it "works when exec'ing to rubygems" do
- install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\""
+ install_gemfile "source \"https://gem.repo1\"; gem \"myrack\""
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 "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\""
+ install_gemfile "source \"https://gem.repo1\"; gem \"myrack\""
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
+ it "works when exec'ing back to bundler to run a remote resolve" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "0.9.1"
+ source "https://gem.repo1"
+ gem "myrack", "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)
+ bundle "exec bundle lock", env: { "BUNDLER_VERSION" => Bundler::VERSION }
- BUNDLED WITH
- 2.1.4
- L
-
- bundle "exec bundle cache", env: { "BUNDLER_VERSION" => Bundler::VERSION }
-
- expect(out).to include("Updating files in vendor/cache")
+ expect(out).to include("Writing lockfile")
end
it "respects custom process title when loading through ruby" do
- skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+ skip "https://github.com/ruby/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")
puts `ps -ocommand= -p#{$$}`
RUBY
- create_file "Gemfile", "source \"#{file_uri_for(gem_repo1)}\""
+ gemfile "Gemfile", "source \"https://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")
end
it "accepts --verbose" do
- install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\""
+ install_gemfile "source \"https://gem.repo1\"; gem \"myrack\""
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 "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\""
+ install_gemfile "source \"https://gem.repo1\"; gem \"myrack\""
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?
+ skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform?
require "tempfile"
@@ -157,24 +138,24 @@ RSpec.describe "bundle exec" do
end
G
- install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
- sys_exec "#{Gem.ruby} #{command.path}"
+ install_gemfile "source \"https://gem.repo1\""
+ in_bundled_app "#{Gem.ruby} #{command.path}"
expect(out).to be_empty
expect(err).to be_empty
end
it "accepts --keep-file-descriptors" do
- install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
+ install_gemfile "source \"https://gem.repo1\""
bundle "exec --keep-file-descriptors echo foobar"
expect(err).to be_empty
end
it "can run a command named --verbose" do
- skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+ skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform?
- install_gemfile "source \"#{file_uri_for(gem_repo1)}\"; gem \"rack\""
+ install_gemfile "source \"https://gem.repo1\"; gem \"myrack\""
File.open(bundled_app("--verbose"), "w") do |f|
f.puts "#!/bin/sh"
f.puts "echo foobar"
@@ -188,189 +169,182 @@ RSpec.describe "bundle exec" do
it "handles different versions in different bundles" do
build_repo2 do
- build_gem "rack_two", "1.0.0" do |s|
- s.executables = "rackup"
+ build_gem "myrack_two", "1.0.0" do |s|
+ s.executables = "myrackup"
end
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "0.9.1"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
G
install_gemfile bundled_app2("Gemfile"), <<-G, dir: bundled_app2
- source "#{file_uri_for(gem_repo2)}"
- gem "rack_two", "1.0.0"
+ source "https://gem.repo2"
+ gem "myrack_two", "1.0.0"
G
- bundle "exec rackup"
+ bundle "exec myrackup"
expect(out).to eq("0.9.1")
- bundle "exec rackup", dir: bundled_app2
+ bundle "exec myrackup", dir: bundled_app2
expect(out).to eq("1.0.0")
end
context "with default gems" do
- let(:default_irb_version) { ruby "gem 'irb', '< 999999'; require 'irb'; puts IRB::VERSION", raise_on_error: false }
+ # TODO: Switch to ERB::VERSION once Ruby 3.4 support is dropped, so all
+ # supported rubies include an `erb` gem version where `ERB::VERSION` is
+ # public
+ let(:default_erb_version) { ruby "require 'erb/version'; puts ERB.const_get(:VERSION)" }
context "when not specified in Gemfile" do
before do
- skip "irb isn't a default gem" if default_irb_version.empty?
-
- install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
+ install_gemfile "source \"https://gem.repo1\""
end
it "uses version provided by ruby" do
- bundle "exec irb --version"
+ bundle "exec erb --version"
- expect(out).to include(default_irb_version)
+ expect(stdboth).to eq(default_erb_version)
end
end
context "when specified in Gemfile directly" do
- let(:specified_irb_version) { "0.9.6" }
+ let(:specified_erb_version) { "2.0.0" }
before do
- skip "irb isn't a default gem" if default_irb_version.empty?
-
build_repo2 do
- build_gem "irb", specified_irb_version do |s|
- s.executables = "irb"
+ build_gem "erb", specified_erb_version do |s|
+ s.executables = "erb"
end
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "irb", "#{specified_irb_version}"
+ source "https://gem.repo2"
+ gem "erb", "#{specified_erb_version}"
G
end
it "uses version specified" do
- bundle "exec irb --version"
+ bundle "exec erb --version"
- expect(out).to eq(specified_irb_version)
- expect(err).to be_empty
+ expect(stdboth).to eq(specified_erb_version)
end
end
context "when specified in Gemfile indirectly" do
- let(:indirect_irb_version) { "0.9.6" }
+ let(:indirect_erb_version) { "2.0.0" }
before do
- skip "irb isn't a default gem" if default_irb_version.empty?
-
build_repo2 do
- build_gem "irb", indirect_irb_version do |s|
- s.executables = "irb"
+ build_gem "erb", indirect_erb_version do |s|
+ s.executables = "erb"
end
- build_gem "gem_depending_on_old_irb" do |s|
- s.add_dependency "irb", indirect_irb_version
+ build_gem "gem_depending_on_old_erb" do |s|
+ s.add_dependency "erb", indirect_erb_version
end
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "gem_depending_on_old_irb"
+ source "https://gem.repo2"
+ gem "gem_depending_on_old_erb"
G
-
- bundle "exec irb --version"
end
it "uses resolved version" do
- expect(out).to eq(indirect_irb_version)
- expect(err).to be_empty
+ bundle "exec erb --version"
+
+ expect(stdboth).to eq(indirect_erb_version)
end
end
end
it "warns about executable conflicts" do
build_repo2 do
- build_gem "rack_two", "1.0.0" do |s|
- s.executables = "rackup"
+ build_gem "myrack_two", "1.0.0" do |s|
+ s.executables = "myrackup"
end
end
bundle "config set --global path.system true"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "0.9.1"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
G
install_gemfile bundled_app2("Gemfile"), <<-G, dir: bundled_app2
- source "#{file_uri_for(gem_repo2)}"
- gem "rack_two", "1.0.0"
+ source "https://gem.repo2"
+ gem "myrack_two", "1.0.0"
G
- bundle "exec rackup"
+ bundle "exec myrackup"
expect(last_command.stderr).to eq(
- "Bundler is using a binstub that was created for a different gem (rack).\n" \
- "You should run `bundle binstub rack_two` to work around a system/bundle conflict."
+ "Bundler is using a binstub that was created for a different gem (myrack).\n" \
+ "You should run `bundle binstub myrack_two` to work around a system/bundle conflict."
)
end
it "handles gems installed with --without" do
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
+ source "https://gem.repo1"
+ gem "myrack" # myrack 0.9.1 and 1.0 exist
group :middleware do
- gem "rack_middleware" # rack_middleware depends on rack 0.9.1
+ gem "myrack_middleware" # myrack_middleware depends on myrack 0.9.1
end
G
- bundle "exec rackup"
+ bundle "exec myrackup"
expect(out).to eq("0.9.1")
- expect(the_bundle).not_to include_gems "rack_middleware 1.0"
+ expect(the_bundle).not_to include_gems "myrack_middleware 1.0"
end
it "does not duplicate already exec'ed RUBYOPT" do
- skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
-
+ create_file("echoopt", "#!/usr/bin/env ruby\nprint ENV['RUBYOPT']")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
bundler_setup_opt = "-r#{lib_dir}/bundler/setup"
rubyopt = opt_add(bundler_setup_opt, ENV["RUBYOPT"])
- bundle "exec 'echo $RUBYOPT'"
+ bundle "exec echoopt"
expect(out.split(" ").count(bundler_setup_opt)).to eq(1)
- bundle "exec 'echo $RUBYOPT'", env: { "RUBYOPT" => rubyopt }
+ bundle "exec echoopt", env: { "RUBYOPT" => 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?
-
+ create_file("echolib", "#!/usr/bin/env ruby\nprint ENV['RUBYLIB']")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
rubylib = ENV["RUBYLIB"]
rubylib = rubylib.to_s.split(File::PATH_SEPARATOR).unshift lib_dir.to_s
rubylib = rubylib.uniq.join(File::PATH_SEPARATOR)
- bundle "exec 'echo $RUBYLIB'"
+ bundle "exec echolib"
expect(out).to include(rubylib)
- bundle "exec 'echo $RUBYLIB'", env: { "RUBYLIB" => rubylib }
+ bundle "exec echolib", env: { "RUBYLIB" => rubylib }
expect(out).to include(rubylib)
end
it "errors nicely when the argument doesn't exist" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle "exec foobarbaz", raise_on_error: false
@@ -381,11 +355,11 @@ RSpec.describe "bundle exec" do
it "errors nicely when the argument is not executable" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "exec touch foo"
+ bundled_app("foo").write("")
bundle "exec ./foo", raise_on_error: false
expect(exitstatus).to eq(126)
expect(err).to include("bundler: not executable: ./foo")
@@ -393,8 +367,8 @@ RSpec.describe "bundle exec" do
it "errors nicely when no arguments are passed" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle "exec", raise_on_error: false
@@ -403,17 +377,17 @@ RSpec.describe "bundle exec" do
end
it "raises a helpful error when exec'ing to something outside of the bundle" do
- system_gems(system_gems_to_install, path: default_bundle_path)
+ system_gems(%w[myrack-1.0.0 myrack-0.9.1], path: default_bundle_path)
- bundle "config set clean false" # want to keep the rackup binstub
+ bundle "config set clean false" # want to keep the myrackup binstub
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo"
G
[true, false].each do |l|
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?"
+ bundle "exec myrackup", raise_on_error: false
+ expect(err).to include "can't find executable myrackup for gem myrack. myrack is not currently included in the bundle, perhaps you meant to add it to your Gemfile?"
end
end
@@ -424,18 +398,15 @@ RSpec.describe "bundle exec" do
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"
+ source "https://gem.repo1"
+ gem "myrack"
G
create_file("print_args", <<-'RUBY')
#!/usr/bin/env ruby
puts "args: #{ARGV.inspect}"
RUBY
- bundled_app("print_args").chmod(0o755)
end
it "shows executable's man page when --help is after the executable" do
@@ -456,6 +427,7 @@ RSpec.describe "bundle exec" do
it "shows executable's man page when the executable has a -" do
FileUtils.mv(bundled_app("print_args"), bundled_app("docker-template"))
+ FileUtils.mv(bundled_app("print_args.bat"), bundled_app("docker-template.bat")) if Gem.win_platform?
bundle "#{exec} docker-template build discourse --help"
expect(out).to eq('args: ["build", "discourse", "--help"]')
end
@@ -472,7 +444,7 @@ RSpec.describe "bundle exec" do
it "shows bundle-exec's man page when --help is between exec and the executable" do
with_fake_man do
- bundle "#{exec} --help cat"
+ bundle "#{exec} --help echo"
end
expect(out).to include(%(["#{man_dir}/bundle-exec.1"]))
end
@@ -512,19 +484,19 @@ RSpec.describe "bundle exec" do
describe "run from a random directory" do
before(:each) do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
end
it "works when unlocked" do
- bundle "exec 'cd #{tmp("gems")} && rackup'"
+ bundle "exec 'cd #{tmp("gems")} && myrackup'"
expect(out).to eq("1.0.0")
end
it "works when locked" do
expect(the_bundle).to be_locked
- bundle "exec 'cd #{tmp("gems")} && rackup'"
+ bundle "exec 'cd #{tmp("gems")} && myrackup'"
expect(out).to eq("1.0.0")
end
end
@@ -536,7 +508,7 @@ RSpec.describe "bundle exec" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "fizz", :path => "#{File.expand_path(home("fizz"))}"
G
end
@@ -561,7 +533,7 @@ RSpec.describe "bundle exec" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "fizz_git", :git => "#{lib_path("fizz_git-1.0")}"
G
end
@@ -585,7 +557,7 @@ RSpec.describe "bundle exec" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "fizz_no_gemspec", "1.0", :git => "#{lib_path("fizz_no_gemspec-1.0")}"
G
end
@@ -605,13 +577,13 @@ RSpec.describe "bundle exec" do
it "performs an automatic bundle install" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "0.9.1"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
gem "foo"
G
bundle "config set auto_install 1"
- bundle "exec rackup"
+ bundle "exec myrackup", artifice: "compact_index"
expect(out).to include("Installing foo 1.0")
end
@@ -620,23 +592,19 @@ RSpec.describe "bundle exec" do
s.executables = "foo"
end
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "0.9.1"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
bundle "config set auto_install 1"
- bundle "exec foo"
- expect(out).to include("Fetching rack 0.9.1")
+ bundle "exec foo", artifice: "compact_index"
+ expect(out).to include("Fetching myrack 0.9.1")
expect(out).to include("Fetching #{lib_path("foo-1.0")}")
expect(out.lines).to end_with("1.0")
end
it "loads the correct optparse when `auto_install` is set, and optparse is a dependency" do
- if 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"
@@ -653,11 +621,11 @@ RSpec.describe "bundle exec" do
bundle "config set --local path vendor/bundle"
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "fastlane"
G
- bundle "exec fastlane"
+ bundle "exec fastlane", artifice: "compact_index"
expect(out).to include("Installing optparse 999.999.999")
expect(out).to include("2.192.0")
end
@@ -674,28 +642,27 @@ RSpec.describe "bundle exec" do
s.version = '1.0'
s.summary = 'TODO: Add summary'
s.authors = 'Me'
+ s.rubygems_version = nil
end
G
end
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :path => "#{lib_path("foo-1.0")}"
G
- bundle "exec irb", raise_on_error: false
+ bundle "exec erb", 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')
+ expect(err).to match(/missing value for attribute rubygems_version|rubygems_version must not be nil/)
end
end
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)}"
+ source "https://gem.repo1"
module Monkey
def bin_path(a,b,c)
@@ -711,49 +678,90 @@ RSpec.describe "bundle exec" do
end
end
+ describe "bundle exec gem uninstall" do
+ before do
+ build_repo4 do
+ build_gem "foo"
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "foo"
+ G
+ end
+
+ it "works" do
+ bundle "exec #{gem_cmd} uninstall foo"
+ expect(out).to eq("Successfully uninstalled foo-1.0")
+ end
+ end
+
+ describe "running gem commands in presence of rubygems plugins" do
+ before do
+ build_repo4 do
+ build_gem "foo" do |s|
+ s.write "lib/rubygems_plugin.rb", "puts 'FAIL'"
+ end
+ end
+
+ system_gems "foo-1.0", path: default_bundle_path, gem_repo: gem_repo4
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ G
+ end
+
+ it "does not load plugins outside of the bundle" do
+ bundle "exec #{gem_cmd} -v"
+ expect(out).not_to include("FAIL")
+ end
+ end
+
context "`load`ing a ruby file instead of `exec`ing" do
let(:path) { bundled_app("ruby_executable") }
let(:shebang) { "#!/usr/bin/env ruby" }
let(:executable) { <<~RUBY.strip }
#{shebang}
- require "rack"
+ require "myrack"
puts "EXEC: \#{caller.grep(/load/).empty? ? 'exec' : 'load'}"
puts "ARGS: \#{$0} \#{ARGV.join(' ')}"
- puts "RACK: \#{RACK}"
- process_title = `ps -o args -p \#{Process.pid}`.split("\n", 2).last.strip
+ puts "MYRACK: \#{MYRACK}"
+ if Gem.win_platform?
+ process_title = "ruby"
+ else
+ process_title = `ps -o args -p \#{Process.pid}`.split("\n", 2).last.strip
+ end
puts "PROCESS: \#{process_title}"
RUBY
before do
- system_gems(system_gems_to_install, path: default_bundle_path)
-
- bundled_app(path).open("w") {|f| f << executable }
- bundled_app(path).chmod(0o755)
+ create_file(bundled_app(path), executable)
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
end
let(:exec) { "EXEC: load" }
let(:args) { "ARGS: #{path} arg1 arg2" }
- let(:rack) { "RACK: 1.0.0" }
+ let(:myrack) { "MYRACK: 1.0.0" }
let(:process) do
- title = "PROCESS: #{path}"
- title += " arg1 arg2"
- title
+ if Gem.win_platform?
+ "PROCESS: ruby"
+ else
+ "PROCESS: #{path} arg1 arg2"
+ end
end
let(:exit_code) { 0 }
- let(:expected) { [exec, args, rack, process].join("\n") }
+ let(:expected) { [exec, args, myrack, process].join("\n") }
let(:expected_err) { "" }
subject { bundle "exec #{path} arg1 arg2", raise_on_error: false }
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)
@@ -765,8 +773,6 @@ RSpec.describe "bundle exec" do
context "with exit 0" do
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)
@@ -778,8 +784,6 @@ RSpec.describe "bundle exec" do
let(:exit_code) { 99 }
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)
@@ -801,7 +805,7 @@ RSpec.describe "bundle exec" do
end
it "runs" do
- skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+ skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform?
subject
expect(exitstatus).to eq(exit_code)
@@ -818,7 +822,12 @@ RSpec.describe "bundle exec" do
let(:expected) { "" }
it "runs" do
- skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+ # it's empty, so `create_file` won't add executable permission and bat scripts on Windows
+ bundled_app(path).chmod(0o755)
+ path.sub_ext(".bat").write <<~SCRIPT if Gem.win_platform?
+ @ECHO OFF
+ @"ruby.exe" "%~dpn0" %*
+ SCRIPT
subject
expect(exitstatus).to eq(exit_code)
@@ -831,12 +840,10 @@ RSpec.describe "bundle exec" do
let(:executable) { super() << "\nraise 'ERROR'" }
let(:exit_code) { 1 }
let(:expected_err) do
- /\Abundler: failed to load command: #{Regexp.quote(path.to_s)} \(#{Regexp.quote(path.to_s)}\)\n#{Regexp.quote(path.to_s)}:10:in [`']<top \(required\)>': ERROR \(RuntimeError\)/
+ /\Abundler: failed to load command: #{Regexp.quote(path.to_s)} \(#{Regexp.quote(path.to_s)}\)\n#{Regexp.quote(path.to_s)}:[0-9]+:in [`']<top \(required\)>': 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 match(expected_err)
@@ -851,8 +858,6 @@ RSpec.describe "bundle exec" do
let(:expected) { super() }
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)
@@ -864,8 +869,6 @@ RSpec.describe "bundle exec" do
let(:shebang) { "#!#{Gem.ruby}" }
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)
@@ -873,58 +876,29 @@ RSpec.describe "bundle exec" do
end
end
- context "when Bundler.setup fails", bundler: "< 3" do
+ context "when Bundler.setup fails" do
before do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack', '2'
- G
- ENV["BUNDLER_FORCE_TTY"] = "true"
- end
+ system_gems(%w[myrack-1.0.0 myrack-0.9.1], path: default_bundle_path)
- let(:exit_code) { Bundler::GemNotFound.new.status_code }
- let(:expected) { "" }
- let(:expected_err) { <<-EOS.strip }
-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 "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'
+ source "https://gem.repo1"
+ gem 'myrack', '2'
G
ENV["BUNDLER_FORCE_TTY"] = "true"
end
let(:exit_code) { Bundler::GemNotFound.new.status_code }
let(:expected) { "" }
- let(:expected_err) { <<-EOS.strip }
-Could not find gem 'rack (= 2)' in locally installed gems.
+ let(:expected_err) { <<~EOS.strip }
+ Could not find gem 'myrack (= 2)' in locally installed gems.
-The source contains the following gems matching 'rack':
- * rack-1.0.0
-Run `bundle install` to install missing gems.
+ The source contains the following gems matching 'myrack':
+ * myrack-0.9.1
+ * myrack-1.0.0
+ Run `bundle install` to install missing gems.
EOS
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)
@@ -934,9 +908,9 @@ Run `bundle install` to install missing gems.
context "when Bundler.setup fails and Gemfile is not the default" do
before do
- create_file "CustomGemfile", <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack', '2'
+ gemfile "CustomGemfile", <<-G
+ source "https://gem.repo1"
+ gem 'myrack', '2'
G
ENV["BUNDLER_FORCE_TTY"] = "true"
ENV["BUNDLE_GEMFILE"] = "CustomGemfile"
@@ -947,8 +921,6 @@ Run `bundle install` to install missing gems.
let(:expected) { "" }
it "prints proper suggestion" do
- skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
-
subject
expect(exitstatus).to eq(exit_code)
expect(err).to include("Run `bundle install --gemfile CustomGemfile` to install missing gems.")
@@ -961,8 +933,6 @@ Run `bundle install` to install missing gems.
let(:exit_code) { 1 }
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)
@@ -972,15 +942,19 @@ Run `bundle install` to install missing gems.
context "when disable_exec_load is set" do
let(:exec) { "EXEC: exec" }
- let(:process) { "PROCESS: ruby #{path} arg1 arg2" }
+ let(:process) do
+ if Gem.win_platform?
+ "PROCESS: ruby"
+ else
+ "PROCESS: ruby #{path} arg1 arg2"
+ end
+ end
before do
bundle "config set disable_exec_load true"
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)
@@ -995,27 +969,30 @@ Run `bundle install` to install missing gems.
puts "__FILE__: #{__FILE__.inspect}"
RUBY
- let(:expected) { super() + <<-EOS.chomp }
+ context "when the path is absolute" do
+ let(:expected) { super() + <<~EOS.chomp }
-$0: #{path.to_s.inspect}
-__FILE__: #{path.to_s.inspect}
- EOS
-
- it "runs" do
- skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+ $0: #{path.to_s.inspect}
+ __FILE__: #{path.to_s.inspect}
+ EOS
- subject
- expect(exitstatus).to eq(exit_code)
- expect(err).to eq(expected_err)
- expect(out).to eq(expected)
+ it "runs" do
+ 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" do
let(:path) { super().relative_path_from(bundled_app) }
+ let(:expected) { super() + <<~EOS.chomp }
- it "runs" do
- skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+ $0: #{path.to_s.inspect}
+ __FILE__: #{path.to_s.inspect}
+ EOS
+ it "runs" do
subject
expect(exitstatus).to eq(exit_code)
expect(err).to eq(expected_err)
@@ -1025,15 +1002,25 @@ __FILE__: #{path.to_s.inspect}
context "when the path is relative with a leading ./" do
let(:path) { Pathname.new("./#{super().relative_path_from(bundled_app)}") }
+ let(:expected) { super() + <<~EOS.chomp }
+
+ $0: #{path.to_s.inspect}
+ __FILE__: #{File.expand_path(path, bundled_app).inspect}
+ EOS
- pending "relative paths with ./ have absolute __FILE__"
+ it "runs" do
+ subject
+ expect(exitstatus).to eq(exit_code)
+ expect(err).to eq(expected_err)
+ expect(out).to eq(expected)
+ end
end
end
context "signal handling" do
let(:test_signals) do
open3_reserved_signals = %w[CHLD CLD PIPE]
- reserved_signals = %w[SEGV BUS ILL FPE VTALRM KILL STOP EXIT]
+ reserved_signals = %w[SEGV BUS ILL FPE ABRT IOT VTALRM KILL STOP EXIT]
bundler_signals = %w[INT]
Signal.list.keys - (bundler_signals + reserved_signals + open3_reserved_signals)
@@ -1047,7 +1034,7 @@ __FILE__: #{path.to_s.inspect}
puts 'Started' # For process sync
STDOUT.flush
sleep 1 # ignore quality_spec
- raise "Didn't receive INT at all"
+ raise RuntimeError, "Didn't receive expected INT"
end.join
rescue Interrupt
puts "foo"
@@ -1055,7 +1042,7 @@ __FILE__: #{path.to_s.inspect}
RUBY
it "receives the signal" do
- skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+ skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform?
bundle("exec #{path}") do |_, o, thr|
o.gets # Consumes 'Started' and ensures that thread has started
@@ -1078,7 +1065,7 @@ __FILE__: #{path.to_s.inspect}
RUBY
it "makes sure no unexpected signals are restored to DEFAULT" do
- skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+ skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform?
test_signals.each do |n|
Signal.trap(n, "IGNORE")
@@ -1095,11 +1082,11 @@ __FILE__: #{path.to_s.inspect}
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?
+ skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform?
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle "config set path vendor/bundler"
bundle :install
@@ -1119,9 +1106,9 @@ __FILE__: #{path.to_s.inspect}
context "when Kernel.require uses extra monkeypatches" do
before do
- skip "https://github.com/rubygems/rubygems/issues/3351" if Gem.win_platform?
+ skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform?
- install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
+ install_gemfile "source \"https://gem.repo1\""
end
it "does not undo the monkeypatches" do
@@ -1162,8 +1149,6 @@ __FILE__: #{path.to_s.inspect}
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"
@@ -1171,18 +1156,18 @@ __FILE__: #{path.to_s.inspect}
end
bundle "config set path vendor/bundle"
- bundle "config set gemfile gemfiles/rack_6_1.gemfile"
+ bundle "config set gemfile gemfiles/myrack_6_1.gemfile"
- create_file(bundled_app("gemfiles/rack_6_1.gemfile"), <<~RUBY)
- source "#{file_uri_for(gem_repo2)}"
+ gemfile(bundled_app("gemfiles/myrack_6_1.gemfile"), <<~RUBY)
+ source "https://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)}\"")
+ gemfile "source 'https://gem.repo1'"
- bundle "install"
+ bundle "install", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
end
it "can still find gems after a nested subprocess" do
@@ -1201,22 +1186,39 @@ __FILE__: #{path.to_s.inspect}
expect(err).to be_empty
expect(out).to eq("6.1.0")
end
+
+ it "can still find gems after a nested subprocess when using bundler (with a final r) executable" do
+ script = bundled_app("bin/myscript")
+
+ create_file(script, <<~RUBY)
+ #!#{Gem.ruby}
+
+ puts `bundler 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, 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?
+ default_openssl_version = ruby "require 'openssl'; puts OpenSSL::VERSION"
+
+ skip "https://github.com/ruby/rubygems/issues/3351" if Gem.win_platform?
- install_gemfile "source \"#{file_uri_for(gem_repo1)}\"" # must happen before installing the broken system gem
+ install_gemfile "source \"https://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", <<-RUBY)
- raise "custom openssl should not be loaded, it's not in the gemfile!"
+ raise ArgumentError, "custom openssl should not be loaded"
RUBY
end
end
@@ -1234,10 +1236,10 @@ __FILE__: #{path.to_s.inspect}
env = { "PATH" => path }
aggregate_failures do
- 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)
+ expect(bundle("exec #{file}", env: env)).to eq(default_openssl_version)
+ expect(bundle("exec bundle exec #{file}", env: env)).to eq(default_openssl_version)
+ expect(bundle("exec ruby #{file}", env: env)).to eq(default_openssl_version)
+ expect(run(file.read, artifice: nil, env: env)).to eq(default_openssl_version)
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?
@@ -1252,7 +1254,7 @@ __FILE__: #{path.to_s.inspect}
build_git "simple_git_binary", &:add_c_extension
bundle "config set --local path .bundle"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "simple_git_binary", :git => '#{lib_path("simple_git_binary-1.0")}'
G
end
@@ -1262,7 +1264,7 @@ __FILE__: #{path.to_s.inspect}
end
it "allows calling bundle install after removing gem.build_complete" do
- FileUtils.rm_rf Dir[bundled_app(".bundle/**/gem.build_complete")]
+ FileUtils.rm_r Dir[bundled_app(".bundle/**/gem.build_complete")]
bundle "exec #{Gem.ruby} -S bundle install"
end
end
diff --git a/spec/bundler/commands/fund_spec.rb b/spec/bundler/commands/fund_spec.rb
index 5415b88eeb..6f4e61da30 100644
--- a/spec/bundler/commands/fund_spec.rb
+++ b/spec/bundler/commands/fund_spec.rb
@@ -30,22 +30,22 @@ RSpec.describe "bundle fund" do
it "prints fund information for all gems in the bundle" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem 'has_funding_and_other_metadata'
gem 'has_funding'
- gem 'rack-obama'
+ gem 'myrack-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")
+ expect(out).to_not include("myrack-obama")
end
it "does not consider fund information for gem dependencies" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem 'gem_with_dependent_funding'
G
@@ -55,10 +55,46 @@ RSpec.describe "bundle fund" do
expect(out).to_not include("gem_with_dependent_funding")
end
+ it "does not consider fund information for uninstalled optional dependencies" do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ group :whatever, optional: true do
+ gem 'has_funding_and_other_metadata'
+ end
+ gem 'has_funding'
+ gem 'myrack-obama'
+ G
+
+ bundle "fund"
+
+ expect(out).to include("* has_funding (1.2.3)\n Funding: https://example.com/has_funding/funding")
+ expect(out).to_not include("has_funding_and_other_metadata")
+ expect(out).to_not include("myrack-obama")
+ end
+
+ it "considers fund information for installed optional dependencies" do
+ bundle "config set with whatever"
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ group :whatever, optional: true do
+ gem 'has_funding_and_other_metadata'
+ end
+ gem 'has_funding'
+ gem 'myrack-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("myrack-obama")
+ 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'
+ source "https://gem.repo2"
+ gem 'myrack-obama'
G
bundle "fund"
@@ -69,7 +105,7 @@ RSpec.describe "bundle fund" do
describe "with --group option" do
it "prints fund message for only specified group gems" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem 'has_funding_and_other_metadata', :group => :development
gem 'has_funding'
G
diff --git a/spec/bundler/commands/help_spec.rb b/spec/bundler/commands/help_spec.rb
index 0c7031e813..f9ad9fff14 100644
--- a/spec/bundler/commands/help_spec.rb
+++ b/spec/bundler/commands/help_spec.rb
@@ -29,11 +29,6 @@ RSpec.describe "bundle help" do
expect(out).to match(/bundle-install/)
end
- it "still outputs the old help for commands that do not have man pages yet" do
- bundle "help fund"
- expect(out).to include("Lists information about gems seeking funding assistance")
- end
-
it "looks for a binary and executes it with --help option if it's named bundler-<task>" do
skip "Could not find command testtasks, probably because not a windows friendly executable" if Gem.win_platform?
diff --git a/spec/bundler/commands/info_spec.rb b/spec/bundler/commands/info_spec.rb
index a5a09bc147..f403db684f 100644
--- a/spec/bundler/commands/info_spec.rb
+++ b/spec/bundler/commands/info_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe "bundle info" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "rails"
gem "has_metadata"
gem "thin"
@@ -56,12 +56,12 @@ RSpec.describe "bundle info" do
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
+ it "doesn't claim that bundler is missing, 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)
+ expect(err).not_to match(/The gem bundler is missing/i)
end
it "complains if gem not in bundle" do
@@ -69,27 +69,27 @@ RSpec.describe "bundle info" do
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"))
+ it "warns if path does not exist on disk, but specification is there" do
+ FileUtils.rm_r(default_bundle_path("gems", "rails-2.3.2"))
bundle "info rails --path"
- expect(err).to include("The gem rails has been deleted.")
+ expect(err).to include("The gem rails is missing.")
expect(err).to include(default_bundle_path("gems", "rails-2.3.2").to_s)
bundle "info rail --path"
- expect(err).to include("The gem rails has been deleted.")
+ expect(err).to include("The gem rails is missing.")
expect(err).to include(default_bundle_path("gems", "rails-2.3.2").to_s)
bundle "info rails"
- expect(err).to include("The gem rails has been deleted.")
+ expect(err).to include("The gem rails is missing.")
expect(err).to include(default_bundle_path("gems", "rails-2.3.2").to_s)
end
- context "given a default gem shippped in ruby", :ruby_repo do
+ context "given a default gem shipped in ruby", :ruby_repo do
it "prints information about the default gem" do
- bundle "info rdoc"
- expect(out).to include("* rdoc")
+ bundle "info json"
+ expect(out).to include("* json")
expect(out).to include("Default Gem: yes")
end
end
@@ -127,9 +127,9 @@ RSpec.describe "bundle info" do
context "when gem has a reverse dependency on any version" do
it "prints the details" do
- bundle "info rack"
+ bundle "info myrack"
- expect(out).to include("Reverse Dependencies: \n\t\tthin (1.0) depends on rack (>= 0)")
+ expect(out).to include("Reverse Dependencies: \n\t\tthin (1.0) depends on myrack (>= 0)")
end
end
@@ -157,7 +157,7 @@ RSpec.describe "bundle info" do
it "prints out git info" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
expect(the_bundle).to include_gems "foo 1.0"
@@ -173,7 +173,7 @@ RSpec.describe "bundle info" do
@revision = revision_for(lib_path("foo-1.0"))[0...6]
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}", :branch => "omg"
G
expect(the_bundle).to include_gems "foo 1.0.omg"
@@ -185,7 +185,7 @@ RSpec.describe "bundle info" do
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)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}", :ref => "#{sha}"
G
@@ -196,7 +196,7 @@ RSpec.describe "bundle info" do
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)}"
+ source "https://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"
@@ -209,20 +209,20 @@ RSpec.describe "bundle info" do
context "with a valid regexp for gem name" do
it "presents alternatives", :readline do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- gem "rack-obama"
+ source "https://gem.repo1"
+ gem "myrack"
+ gem "myrack-obama"
G
bundle "info rac"
- expect(out).to match(/\A1 : rack\n2 : rack-obama\n0 : - exit -(\n>.*)?\z/)
+ expect(out).to match(/\A1 : myrack\n2 : myrack-obama\n0 : - exit -(\n>|\z)/)
end
end
context "with an invalid regexp for gem name" do
it "does not find the gem" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
G
@@ -238,7 +238,7 @@ RSpec.describe "bundle info" do
bundle "config without test"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails", group: :test
G
diff --git a/spec/bundler/commands/init_spec.rb b/spec/bundler/commands/init_spec.rb
index 0a1336572a..538e61fd47 100644
--- a/spec/bundler/commands/init_spec.rb
+++ b/spec/bundler/commands/init_spec.rb
@@ -32,7 +32,7 @@ RSpec.describe "bundle init" do
context "when a Gemfile already exists" do
before do
- create_file "Gemfile", <<-G
+ gemfile <<-G
gem "rails"
G
end
@@ -79,14 +79,14 @@ RSpec.describe "bundle init" do
end
context "given --gemspec option" do
- let(:spec_file) { tmp.join("test.gemspec") }
+ let(:spec_file) { tmp("test.gemspec") }
it "should generate from an existing gemspec" do
File.open(spec_file, "w") do |file|
file << <<-S
Gem::Specification.new do |s|
s.name = 'test'
- s.add_dependency 'rack', '= 1.0.1'
+ s.add_dependency 'myrack', '= 1.0.1'
s.add_development_dependency 'rspec', '1.2'
end
S
@@ -96,7 +96,7 @@ RSpec.describe "bundle init" do
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 "myrack", "= 1.0.1"/).size).to eq(1)
expect(gemfile.scan(/gem "rspec", "= 1.2"/).size).to eq(1)
expect(gemfile.scan(/group :development/).size).to eq(1)
end
@@ -129,7 +129,7 @@ RSpec.describe "bundle init" do
context "when gems.rb already exists" do
before do
- create_file("gems.rb", <<-G)
+ gemfile("gems.rb", <<-G)
gem "rails"
G
end
@@ -160,14 +160,14 @@ RSpec.describe "bundle init" do
end
context "given --gemspec option" do
- let(:spec_file) { tmp.join("test.gemspec") }
+ let(:spec_file) { tmp("test.gemspec") }
before do
File.open(spec_file, "w") do |file|
file << <<-S
Gem::Specification.new do |s|
s.name = 'test'
- s.add_dependency 'rack', '= 1.0.1'
+ s.add_dependency 'myrack', '= 1.0.1'
s.add_development_dependency 'rspec', '1.2'
end
S
@@ -179,7 +179,7 @@ RSpec.describe "bundle init" do
gemfile = bundled_app("gems.rb").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 "myrack", "= 1.0.1"/).size).to eq(1)
expect(gemfile.scan(/gem "rspec", "= 1.2"/).size).to eq(1)
expect(gemfile.scan(/group :development/).size).to eq(1)
end
diff --git a/spec/bundler/commands/inject_spec.rb b/spec/bundler/commands/inject_spec.rb
deleted file mode 100644
index 255a03c135..0000000000
--- a/spec/bundler/commands/inject_spec.rb
+++ /dev/null
@@ -1,117 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe "bundle inject", bundler: "< 3" do
- before :each do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- G
- end
-
- context "without a lockfile" do
- it "locks with the injected gems" do
- expect(bundled_app_lock).not_to exist
- bundle "inject 'rack-obama' '> 0'"
- expect(bundled_app_lock.read).to match(/rack-obama/)
- end
- end
-
- context "with a lockfile" do
- before do
- bundle "install"
- end
-
- it "adds the injected gems to the Gemfile" do
- expect(bundled_app_gemfile.read).not_to match(/rack-obama/)
- bundle "inject 'rack-obama' '> 0'"
- expect(bundled_app_gemfile.read).to match(/rack-obama/)
- end
-
- it "locks with the injected gems" do
- expect(bundled_app_lock.read).not_to match(/rack-obama/)
- bundle "inject 'rack-obama' '> 0'"
- 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'", 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", 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"
- E
- end
- end
-
- 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
- str = "gem \"foo\", \"> 0\", :source => \"#{file_uri_for(gem_repo1)}\""
- expect(gemfile).to include str
- end
- end
-
- 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
- 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
- str = "gem \"rack-obama\", \"> 0\", :groups => [:development, :test]"
- expect(gemfile).to include str
- end
- end
-
- context "when frozen" do
- before do
- bundle "install"
- if Bundler.feature_flag.bundler_3_mode?
- bundle "config set --local deployment true"
- else
- 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/)
- end
-
- it "locks with the injected gems" do
- expect(bundled_app_lock.read).not_to match(/rack-obama/)
- bundle "inject 'rack-obama' '> 0'"
- expect(bundled_app_lock.read).to match(/rack-obama/)
- end
-
- it "restores frozen afterwards" do
- bundle "inject 'rack-obama' '> 0'"
- config = Psych.load(bundled_app(".bundle/config").read)
- expect(config["BUNDLE_DEPLOYMENT"] || config["BUNDLE_FROZEN"]).to eq("true")
- end
-
- it "doesn't allow Gemfile changes" do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack-obama"
- G
- bundle "inject 'rack' '> 0'", raise_on_error: false
- expect(err).to match(/the lockfile can't be updated because frozen mode is set/)
-
- expect(bundled_app_lock.read).not_to match(/rack-obama/)
- end
- end
-end
diff --git a/spec/bundler/commands/install_spec.rb b/spec/bundler/commands/install_spec.rb
index edc5887d7b..ae651bf981 100644
--- a/spec/bundler/commands/install_spec.rb
+++ b/spec/bundler/commands/install_spec.rb
@@ -4,7 +4,7 @@ RSpec.describe "bundle install with gem sources" do
describe "the simple case" do
it "prints output and returns if no dependencies are specified" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
bundle :install
@@ -22,37 +22,91 @@ RSpec.describe "bundle install with gem sources" do
it "creates a Gemfile.lock" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
expect(bundled_app_lock).to exist
end
- it "does not create ./.bundle by default", bundler: "< 3" do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ it "creates lockfile based on the lockfile method in Gemfile" do
+ install_gemfile <<-G
+ lockfile "OmgFile.lock"
+ source "https://gem.repo1"
+ gem "myrack", "1.0"
+ G
+
+ bundle "install"
+
+ expect(bundled_app("OmgFile.lock")).to exist
+ end
+
+ it "creates lockfile using BUNDLE_LOCKFILE instead of lockfile method" do
+ ENV["BUNDLE_LOCKFILE"] = "ReallyOmgFile.lock"
+ install_gemfile <<-G
+ lockfile "OmgFile.lock"
+ source "https://gem.repo1"
+ gem "myrack", "1.0"
+ G
+
+ expect(bundled_app("ReallyOmgFile.lock")).to exist
+ expect(bundled_app("OmgFile.lock")).not_to exist
+ ensure
+ ENV.delete("BUNDLE_LOCKFILE")
+ end
+
+ it "creates lockfile based on --lockfile option is given" do
+ gemfile bundled_app("OmgFile"), <<-G
+ source "https://gem.repo1"
+ gem "myrack", "1.0"
+ G
+
+ bundle "install --gemfile OmgFile --lockfile ReallyOmgFile.lock"
+
+ expect(bundled_app("ReallyOmgFile.lock")).to exist
+ end
+
+ it "does not make a lockfile if lockfile false is used in Gemfile" do
+ install_gemfile <<-G
+ lockfile false
+ source "https://gem.repo1"
+ gem 'myrack'
+ G
+
+ expect(bundled_app_lock).not_to exist
+ end
+
+ it "does not create ./.bundle by default" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle :install # can't use install_gemfile since it sets retry
expect(bundled_app(".bundle")).not_to exist
end
+ it "will create a ./.bundle by default", bundler: "5" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ expect(bundled_app(".bundle")).to exist
+ end
+
it "does not create ./.bundle by default when installing to system gems" do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ install_gemfile <<-G, env: { "BUNDLE_PATH__SYSTEM" => "true" }
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle :install, env: { "BUNDLE_PATH__SYSTEM" => "true" } # can't use install_gemfile since it sets retry
expect(bundled_app(".bundle")).not_to exist
end
- it "creates lock files based on the Gemfile name" do
+ it "creates lockfiles based on the Gemfile name" do
gemfile bundled_app("OmgFile"), <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "1.0"
+ source "https://gem.repo1"
+ gem "myrack", "1.0"
G
bundle "install --gemfile OmgFile"
@@ -60,10 +114,33 @@ RSpec.describe "bundle install with gem sources" do
expect(bundled_app("OmgFile.lock")).to exist
end
+ it "doesn't create a lockfile if --no-lock option is given" do
+ gemfile bundled_app("OmgFile"), <<-G
+ source "https://gem.repo1"
+ gem "myrack", "1.0"
+ G
+
+ bundle "install --gemfile OmgFile --no-lock"
+
+ expect(bundled_app("OmgFile.lock")).not_to exist
+ end
+
+ it "doesn't create a lockfile if --no-lock and --lockfile options are given" do
+ gemfile bundled_app("OmgFile"), <<-G
+ source "https://gem.repo1"
+ gem "myrack", "1.0"
+ G
+
+ bundle "install --gemfile OmgFile --no-lock --lockfile ReallyOmgFile.lock"
+
+ expect(bundled_app("OmgFile.lock")).not_to exist
+ expect(bundled_app("ReallyOmgFile.lock")).not_to exist
+ end
+
it "doesn't delete the lockfile if one already exists" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
lockfile = File.read(bundled_app_lock)
@@ -77,8 +154,8 @@ RSpec.describe "bundle install with gem sources" do
it "does not touch the lockfile if nothing changed" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
expect { run "1" }.not_to change { File.mtime(bundled_app_lock) }
@@ -86,60 +163,77 @@ RSpec.describe "bundle install with gem sources" do
it "fetches gems" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
- expect(default_bundle_path("gems/rack-1.0.0")).to exist
- expect(the_bundle).to include_gems("rack 1.0.0")
+ expect(default_bundle_path("gems/myrack-1.0.0")).to exist
+ expect(the_bundle).to include_gems("myrack 1.0.0")
end
it "auto-heals missing gems" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
- FileUtils.rm_rf(default_bundle_path("gems/rack-1.0.0"))
+ FileUtils.rm_r(default_bundle_path("gems/myrack-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")
+ expect(out).to include("Installing myrack 1.0.0")
+ expect(default_bundle_path("gems/myrack-1.0.0")).to exist
+ expect(the_bundle).to include_gems("myrack 1.0.0")
+ end
+
+ it "does not state that it's constantly reinstalling empty gems" do
+ build_repo4 do
+ build_gem "empty", "1.0.0", no_default: true
+ end
+
+ install_gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "empty"
+ G
+ gem_dir = default_bundle_path("gems/empty-1.0.0")
+ expect(gem_dir).to be_empty
+
+ bundle "install --verbose"
+ expect(out).not_to include("Installing empty")
end
it "fetches gems when multiple versions are specified" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack', "> 0.9", "< 1.0"
+ source "https://gem.repo1"
+ gem 'myrack', "> 0.9", "< 1.0"
G
- expect(default_bundle_path("gems/rack-0.9.1")).to exist
- expect(the_bundle).to include_gems("rack 0.9.1")
+ expect(default_bundle_path("gems/myrack-0.9.1")).to exist
+ expect(the_bundle).to include_gems("myrack 0.9.1")
end
it "fetches gems when multiple versions are specified take 2" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack', "< 1.0", "> 0.9"
+ source "https://gem.repo1"
+ gem 'myrack', "< 1.0", "> 0.9"
G
- expect(default_bundle_path("gems/rack-0.9.1")).to exist
- expect(the_bundle).to include_gems("rack 0.9.1")
+ expect(default_bundle_path("gems/myrack-0.9.1")).to exist
+ expect(the_bundle).to include_gems("myrack 0.9.1")
end
it "raises an appropriate error when gems are specified using symbols" do
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo1)}"
- gem :rack
+ source "https://gem.repo1"
+ gem :myrack
G
expect(exitstatus).to eq(4)
end
it "pulls in dependencies" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
G
@@ -148,11 +242,11 @@ RSpec.describe "bundle install with gem sources" do
it "does the right version" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "0.9.1"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
G
- expect(the_bundle).to include_gems "rack 0.9.1"
+ expect(the_bundle).to include_gems "myrack 0.9.1"
end
it "does not install the development dependency" do
@@ -163,7 +257,7 @@ RSpec.describe "bundle install with gem sources" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "with_development_dependency"
G
@@ -173,7 +267,7 @@ RSpec.describe "bundle install with gem sources" do
it "resolves correctly" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "activemerchant"
gem "rails"
G
@@ -183,12 +277,12 @@ RSpec.describe "bundle install with gem sources" do
it "activates gem correctly according to the resolved gems" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "activesupport", "2.3.5"
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "activemerchant"
gem "rails"
G
@@ -206,7 +300,7 @@ RSpec.describe "bundle install with gem sources" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activerecord", "2.3.2"
G
@@ -216,148 +310,128 @@ RSpec.describe "bundle install with gem sources" do
it "works when the gemfile specifies gems that only exist in the system" do
build_gem "foo", to_bundle: true
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
gem "foo"
G
- expect(the_bundle).to include_gems "rack 1.0.0", "foo 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0", "foo 1.0.0"
end
it "prioritizes local gems over remote gems" do
- build_gem "rack", "1.0.0", to_bundle: true do |s|
- s.add_dependency "activesupport", "2.3.5"
- end
+ build_gem "myrack", "9.0.0", to_bundle: true
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- expect(the_bundle).to include_gems "rack 1.0.0", "activesupport 2.3.5"
+ expect(the_bundle).to include_gems "myrack 9.0.0"
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"
+ install_gemfile <<-G, env: { "RUBYLIB" => rubylib.unshift(bundled_app("plugins").to_s).join(File::PATH_SEPARATOR) }
+ source "https://gem.repo1"
+ gem "myrack"
G
- expect(last_command.stdboth).to include(plugin_msg)
+ expect(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?
+ simulate_platform "x86-darwin-100" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "platform_specific"
+ G
- 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 #{Bundler.local_platform}")
+ expect(the_bundle).to include_gems("platform_specific 1.0 x86-darwin-100")
+ end
end
it "falls back on plain ruby" do
- simulate_platform "foo-bar-baz"
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "platform_specific"
- G
+ simulate_platform "foo-bar-baz" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "platform_specific"
+ G
- run "require 'platform_specific' ; puts PLATFORM_SPECIFIC"
- expect(out).to eq("1.0.0 RUBY")
+ expect(the_bundle).to include_gems("platform_specific 1.0 ruby")
+ end
end
it "installs gems for java" do
- simulate_platform "java"
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "platform_specific"
- G
+ simulate_platform "java" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "platform_specific"
+ G
- run "require 'platform_specific' ; puts PLATFORM_SPECIFIC"
- expect(out).to eq("1.0.0 JAVA")
+ expect(the_bundle).to include_gems("platform_specific 1.0 java")
+ end
end
it "installs gems for windows" do
- simulate_platform x86_mswin32
+ simulate_platform "x86-mswin32" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "platform_specific"
+ G
- 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 x86-mswin32")
+ expect(the_bundle).to include_gems("platform_specific 1.0 x86-mswin32")
+ end
end
- end
- describe "doing bundle install foo" do
- before do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- G
- end
+ it "installs gems for aarch64-mingw-ucrt" do
+ simulate_platform "aarch64-mingw-ucrt" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "platform_specific"
+ G
+ end
- it "works" do
- bundle "config set --local path vendor"
- bundle "install"
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(out).to include("Installing platform_specific 1.0 (aarch64-mingw-ucrt)")
end
+ end
- it "allows running bundle install --system without deleting foo", bundler: "< 3" do
- bundle "install --path vendor"
- bundle "install --system"
- FileUtils.rm_rf(bundled_app("vendor"))
- expect(the_bundle).to include_gems "rack 1.0"
- end
+ it "gives useful errors if no global sources are set, and gems not installed locally, with and without a lockfile" do
+ install_gemfile <<-G, raise_on_error: false
+ gem "myrack"
+ G
- it "allows running bundle install --system after deleting foo", bundler: "< 3" do
- bundle "install --path vendor"
- FileUtils.rm_rf(bundled_app("vendor"))
- bundle "install --system"
- expect(the_bundle).to include_gems "rack 1.0"
- end
- end
+ expect(err).to eq("Could not find gem 'myrack' in locally installed gems.")
- it "finds gems in multiple sources", bundler: "< 3" do
- build_repo2 do
- build_gem "rack", "1.2" do |s|
- s.executables = "rackup"
- end
- end
+ lockfile <<~L
+ GEM
+ specs:
+ myrack (1.0.0)
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- source "#{file_uri_for(gem_repo2)}"
+ PLATFORMS
+ #{lockfile_platforms}
- gem "activesupport", "1.2.3"
- gem "rack", "1.2"
- G
+ DEPENDENCIES
+ myrack
- expect(the_bundle).to include_gems "rack 1.2", "activesupport 1.2.3"
- end
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
- it "gives a useful error if no sources are set" do
- install_gemfile <<-G, raise_on_error: false
- gem "rack"
- G
+ bundle "install", raise_on_error: false
- 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\".")
+ expect(err).to include(
+ "Because your Gemfile specifies no global remote source, your bundle is locked to " \
+ "myrack (1.0.0) from locally installed gems. However, myrack (1.0.0) is not installed. " \
+ "You'll need to either add a global remote source to your Gemfile or make sure myrack (1.0.0) " \
+ "is available locally before rerunning Bundler."
+ )
end
it "creates a Gemfile.lock on a blank Gemfile" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
expect(File.exist?(bundled_app_lock)).to eq(true)
@@ -367,12 +441,12 @@ RSpec.describe "bundle install with gem sources" do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack"
- gem "rack"
+ source "https://gem.repo2"
+ gem "myrack"
+ gem "myrack"
G
- expect(err).to include("Your Gemfile lists the gem rack (>= 0) more than once.")
+ expect(err).to include("Your Gemfile lists the gem myrack (>= 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
@@ -381,12 +455,12 @@ RSpec.describe "bundle install with gem sources" do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack", "1.0"
- gem "rack", "1.0"
+ source "https://gem.repo2"
+ gem "myrack", "1.0"
+ gem "myrack", "1.0"
G
- expect(err).to include("Your Gemfile lists the gem rack (= 1.0) more than once.")
+ expect(err).to include("Your Gemfile lists the gem myrack (= 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
@@ -395,14 +469,14 @@ RSpec.describe "bundle install with gem sources" do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack", :platform => :jruby
- gem "rack"
+ source "https://gem.repo2"
+ gem "myrack", :platform => :jruby
+ gem "myrack"
G
bundle "install"
- expect(err).to include("Your Gemfile lists the gem rack (>= 0) more than once.")
+ expect(err).to include("Your Gemfile lists the gem myrack (>= 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
@@ -417,7 +491,7 @@ RSpec.describe "bundle install with gem sources" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gemspec
@@ -430,7 +504,7 @@ RSpec.describe "bundle install with gem sources" do
expect(the_bundle).to include_gems("my-private-gem 1.0")
end
- it "throws a warning if a gem is added once in Gemfile and also inside a gemspec as a development dependency, with different requirements" do
+ it "does not warn if a gem is added once in Gemfile and also inside a gemspec as a development dependency, with compatible requirements" do
build_lib "my-gem", path: bundled_app do |s|
s.add_development_dependency "rubocop", "~> 1.36.0"
end
@@ -441,7 +515,7 @@ RSpec.describe "bundle install with gem sources" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gemspec
@@ -450,19 +524,37 @@ RSpec.describe "bundle install with gem sources" do
bundle :install
- expect(err).to include("A gemspec development dependency (rubocop, ~> 1.36.0) is being overridden by a Gemfile dependency (rubocop, >= 0).")
- expect(err).to include("This behaviour may change in the future. Please remove either of them, or make sure they both have the same requirement")
+ expect(err).to be_empty
+
+ expect(the_bundle).to include_gems("rubocop 1.36.0")
+ end
+
+ it "raises an error if a gem is added once in Gemfile and also inside a gemspec as a development dependency, with incompatible requirements" do
+ build_lib "my-gem", path: bundled_app do |s|
+ s.add_development_dependency "rubocop", "~> 1.36.0"
+ end
+
+ build_repo4 do
+ build_gem "rubocop", "1.36.0"
+ build_gem "rubocop", "1.37.1"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gemspec
+
+ gem "rubocop", "~> 1.37.0", group: :development
+ G
+
+ bundle :install, raise_on_error: false
- # This is not the best behavior I believe, it would be better if both
- # requirements are considered if they are compatible, and a version
- # satisfying both is chosen. But not sure about changing it right now, so
- # I went with a warning for the time being.
- expect(the_bundle).to include_gems("rubocop 1.37.1")
+ expect(err).to include("The rubocop dependency has conflicting requirements in Gemfile (~> 1.37.0) and gemspec (~> 1.36.0)")
end
it "includes the gem without warning if two gemspecs add it with the same requirement" do
- gem1 = tmp.join("my-gem-1")
- gem2 = tmp.join("my-gem-2")
+ gem1 = tmp("my-gem-1")
+ gem2 = tmp("my-gem-2")
build_lib "my-gem", path: gem1 do |s|
s.add_development_dependency "rubocop", "~> 1.36.0"
@@ -477,7 +569,7 @@ RSpec.describe "bundle install with gem sources" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gemspec path: "#{gem1}"
gemspec path: "#{gem2}"
@@ -489,33 +581,85 @@ RSpec.describe "bundle install with gem sources" do
expect(the_bundle).to include_gems("rubocop 1.36.0")
end
- it "warns when a Gemfile dependency is overriding a gemspec development dependency, with different requirements" do
- build_lib "my-gem", path: bundled_app do |s|
- s.add_development_dependency "rails", ">= 5"
+ it "includes the gem without warning if two gemspecs add it with compatible requirements" do
+ gem1 = tmp("my-gem-1")
+ gem2 = tmp("my-gem-2")
+
+ build_lib "my-gem", path: gem1 do |s|
+ s.add_development_dependency "rubocop", "~> 1.0"
+ end
+
+ build_lib "my-gem-2", path: gem2 do |s|
+ s.add_development_dependency "rubocop", "~> 1.36.0"
end
build_repo4 do
- build_gem "rails", "7.0.8"
+ build_gem "rubocop", "1.36.0"
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
-
- gem "rails", "~> 7.0.8"
+ source "https://gem.repo4"
- gemspec
+ gemspec path: "#{gem1}"
+ gemspec path: "#{gem2}"
G
bundle :install
- expect(err).to include("A gemspec development dependency (rails, >= 5) is being overridden by a Gemfile dependency (rails, ~> 7.0.8).")
- expect(err).to include("This behaviour may change in the future. Please remove either of them, or make sure they both have the same requirement")
+ expect(err).to be_empty
+ expect(the_bundle).to include_gems("rubocop 1.36.0")
+ end
- # This is not the best behavior I believe, it would be better if both
- # requirements are considered if they are compatible, and a version
- # satisfying both is chosen. But not sure about changing it right now, so
- # I went with a warning for the time being.
- expect(the_bundle).to include_gems("rails 7.0.8")
+ it "errors out if two gemspecs add it with incompatible requirements" do
+ gem1 = tmp("my-gem-1")
+ gem2 = tmp("my-gem-2")
+
+ build_lib "my-gem", path: gem1 do |s|
+ s.add_development_dependency "rubocop", "~> 2.0"
+ end
+
+ build_lib "my-gem-2", path: gem2 do |s|
+ s.add_development_dependency "rubocop", "~> 1.36.0"
+ end
+
+ build_repo4 do
+ build_gem "rubocop", "1.36.0"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gemspec path: "#{gem1}"
+ gemspec path: "#{gem2}"
+ G
+
+ bundle :install, raise_on_error: false
+
+ expect(err).to include("Two gemspec development dependencies have conflicting requirements on the same gem: rubocop (~> 1.36.0) and rubocop (~> 2.0). Bundler cannot continue.")
+ end
+
+ it "errors out if a gem is specified in a gemspec and in the Gemfile" do
+ gem = tmp("my-gem-1")
+
+ build_lib "rubocop", path: gem do |s|
+ s.add_development_dependency "rubocop", "~> 1.0"
+ end
+
+ build_repo4 do
+ build_gem "rubocop"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "rubocop", :path => "#{gem}"
+ gemspec path: "#{gem}"
+ G
+
+ bundle :install, raise_on_error: false
+
+ expect(err).to include("There was an error parsing `Gemfile`: You cannot specify the same gem twice coming from different sources.")
+ expect(err).to include("You specified that rubocop (>= 0) should come from source at `#{gem}` and gemspec at `#{gem}`")
end
it "does not warn if a gem is added once in Gemfile and also inside a gemspec as a development dependency, with same requirements, and different sources" do
@@ -530,11 +674,11 @@ RSpec.describe "bundle install with gem sources" do
build_git "activesupport", "1.0", path: lib_path("activesupport")
install_gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gemspec
- gem "activesupport", :git => "#{file_uri_for(lib_path("activesupport"))}"
+ gem "activesupport", :git => "#{lib_path("activesupport")}"
G
expect(err).to be_empty
@@ -542,9 +686,9 @@ RSpec.describe "bundle install with gem sources" do
# if the Gemfile dependency is specified first
install_gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
- gem "activesupport", :git => "#{file_uri_for(lib_path("activesupport"))}"
+ gem "activesupport", :git => "#{lib_path("activesupport")}"
gemspec
G
@@ -564,7 +708,7 @@ RSpec.describe "bundle install with gem sources" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gemspec
@@ -579,60 +723,57 @@ RSpec.describe "bundle install with gem sources" do
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"
+ source "https://gem.repo2"
+ gem "myrack"
+ gem "myrack", "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).")
+ expect(err).to include("You specified: myrack (>= 0) and myrack (= 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"
+ source "https://gem.repo2"
+ gem "myrack", "1.0"
+ gem "myrack", "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).")
+ expect(err).to include("You specified: myrack (= 1.0) and myrack (= 1.1).")
end
it "gracefully handles error when rubygems server is unavailable" do
- skip "networking issue" if Gem.win_platform?
-
install_gemfile <<-G, artifice: nil, raise_on_error: false
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
source "http://0.0.0.0:9384" do
gem 'foo'
end
G
- expect(err).to include("Could not fetch specs from http://0.0.0.0:9384/")
+ expect(err).to eq("Could not reach host 0.0.0.0:9384. Check your network connection and try again.")
expect(err).not_to include("file://")
end
it "fails gracefully when downloading an invalid specification from the full index" do
build_repo2(build_compact_index: false) do
build_gem "ajp-rails", "0.0.0", gemspec: false, skip_validation: true do |s|
- bad_deps = [["ruby-ajp", ">= 0.2.0"], ["rails", ">= 0.14"]]
+ invalid_deps = [["ruby-ajp", ">= 0.2.0"], ["rails", ">= 0.14"]]
s.
instance_variable_get(:@spec).
- instance_variable_set(:@dependencies, bad_deps)
-
- raise "failed to set bad deps" unless s.dependencies == bad_deps
+ instance_variable_set(:@dependencies, invalid_deps)
end
+
build_gem "ruby-ajp", "1.0.0"
end
install_gemfile <<-G, full_index: true, raise_on_error: false
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "ajp-rails", "0.0.0"
G
- expect(last_command.stdboth).not_to match(/Error Report/i)
+ expect(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("Bundler::APIResponseInvalidDependenciesError")
end
@@ -642,7 +783,7 @@ RSpec.describe "bundle install with gem sources" do
FileUtils.touch(bundled_app(".bundle/config"))
install_gemfile(<<-G)
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'foo'
G
@@ -653,7 +794,7 @@ RSpec.describe "bundle install with gem sources" do
FileUtils.touch("#{Bundler.rubygems.user_home}/.bundle/config")
install_gemfile(<<-G)
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'foo'
G
@@ -665,7 +806,7 @@ RSpec.describe "bundle install with gem sources" do
it "prints an error" do
install_gemfile <<-G, raise_on_error: false
ruby '~> 1.2'
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
expect(err).to include("Your Ruby version is #{Gem.ruby_version}, but your Gemfile specified ~> 1.2")
end
@@ -675,15 +816,15 @@ RSpec.describe "bundle install with gem sources" do
before do
install_gemfile <<-G
ruby '~> #{Gem.ruby_version}'
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
end
it "writes current Ruby version to Gemfile.lock" do
- checksums = checksums_section_when_existing
+ checksums = checksums_section_when_enabled
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
@@ -692,24 +833,24 @@ RSpec.describe "bundle install with gem sources" do
DEPENDENCIES
#{checksums}
RUBY VERSION
- #{Bundler::RubyVersion.system}
+ #{Bundler::RubyVersion.system}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
it "updates Gemfile.lock with updated yet still compatible ruby version" do
install_gemfile <<-G
ruby '~> #{current_ruby_minor}'
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
- checksums = checksums_section_when_existing
+ checksums = checksums_section_when_enabled
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
@@ -718,16 +859,16 @@ RSpec.describe "bundle install with gem sources" do
DEPENDENCIES
#{checksums}
RUBY VERSION
- #{Bundler::RubyVersion.system}
+ #{Bundler::RubyVersion.system}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
it "does not crash when unlocking" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
ruby '>= 2.1.0'
G
@@ -746,7 +887,7 @@ RSpec.describe "bundle install with gem sources" do
build_lib "foo"
gemfile = <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'foo', :path => "#{lib_path("foo-1.0")}"
G
File.open("#{root_dir}/Gemfile", "w") do |file|
@@ -763,7 +904,7 @@ RSpec.describe "bundle install with gem sources" do
build_lib "foo", path: root_dir
gemfile = <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gemspec
G
File.open("#{root_dir}/Gemfile", "w") do |file|
@@ -779,8 +920,8 @@ RSpec.describe "bundle install with gem sources" do
bundle "config set force_ruby_platform true"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
bundle :install, quiet: true
@@ -809,7 +950,7 @@ RSpec.describe "bundle install with gem sources" do
RUBY
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'non-existing-gem'
G
@@ -820,14 +961,14 @@ RSpec.describe "bundle install with gem sources" do
end
end
- describe "when bundle path does not have write access", :permissions do
+ describe "when bundle path does not have cd permission", :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'
+ source "https://gem.repo1"
+ gem 'myrack'
G
end
@@ -837,18 +978,18 @@ RSpec.describe "bundle install with gem sources" do
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")
+ expect(err).to include("grant executable permissions")
end
end
- describe "when bundle gems path does not have write access", :permissions do
+ describe "when bundle gems path does not have cd permission", :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'
+ source "https://gem.repo1"
+ gem 'myrack'
G
end
@@ -865,19 +1006,109 @@ RSpec.describe "bundle install with gem sources" do
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")}`. " \
+ "There was an error while trying to create `#{gems_path.join("myrack-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 there's an empty install folder (like with default gems) without cd permissions", :permissions do
+ let(:full_gem_path) { bundled_app("vendor/#{Bundler.ruby_scope}/gems/myrack-1.0.0") }
+
+ before do
+ FileUtils.mkdir_p(full_gem_path)
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
+ G
+ end
+
+ it "should display a proper message to explain the problem" do
+ FileUtils.chmod("-x", full_gem_path)
+ bundle "config set --local path vendor"
+
+ begin
+ bundle :install, raise_on_error: false
+ ensure
+ FileUtils.chmod("+x", full_gem_path)
+ end
+
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
+
+ expect(err).to include(
+ "There was an error while trying to write to `#{full_gem_path}`. " \
+ "It is likely that you need to grant write permissions for that path."
+ )
+ end
+ end
+
+ describe "when bundle bin dir does not have cd permission", :permissions do
+ let(:bin_dir) { bundled_app("vendor/#{Bundler.ruby_scope}/bin") }
+
+ before do
+ FileUtils.mkdir_p(bin_dir)
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
+ G
+ end
+
+ it "should display a proper message to explain the problem" do
+ FileUtils.chmod("-x", bin_dir)
+ bundle "config set --local path vendor"
+
+ begin
+ bundle :install, raise_on_error: false
+ ensure
+ FileUtils.chmod("+x", bin_dir)
+ end
+
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
+
+ expect(err).to include(
+ "There was an error while trying to write to `#{bin_dir}`. " \
+ "It is likely that you need to grant write permissions for that path."
+ )
+ end
+ end
+
+ describe "when bundle bin dir does not have write access", :permissions do
+ let(:bin_dir) { bundled_app("vendor/#{Bundler.ruby_scope}/bin") }
+
+ before do
+ FileUtils.mkdir_p(bin_dir)
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+ end
+
+ it "should display a proper message to explain the problem" do
+ FileUtils.chmod("-w", bin_dir)
+ bundle "config set --local path vendor"
+
+ begin
+ bundle :install, raise_on_error: false
+ ensure
+ FileUtils.chmod("+w", bin_dir)
+ end
+
+ expect(err).not_to include("ERROR REPORT TEMPLATE")
+
+ expect(err).to include(
+ "There was an error while trying to write to `#{bin_dir}`. " \
+ "It is likely that you need to grant write permissions for that path."
+ )
+ end
+ end
+
describe "when bundle extensions path does not have write access", :permissions do
let(:extensions_path) { bundled_app("vendor/#{Bundler.ruby_scope}/extensions/#{Gem::Platform.local}/#{Gem.extension_api_version}") }
before do
FileUtils.mkdir_p(extensions_path)
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'simple_binary'
G
end
@@ -901,7 +1132,7 @@ RSpec.describe "bundle install with gem sources" do
end
end
- describe "when the path of a specific gem is not writable", :permissions do
+ describe "when the path of a specific gem does not have cd permission", :permissions do
let(:gems_path) { bundled_app("vendor/#{Bundler.ruby_scope}/gems") }
let(:foo_path) { gems_path.join("foo-1.0.0") }
@@ -913,7 +1144,7 @@ RSpec.describe "bundle install with gem sources" do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem 'foo'
G
end
@@ -927,7 +1158,7 @@ RSpec.describe "bundle install with gem sources" do
FileUtils.chmod("-x", foo_path)
begin
- bundle "install --redownload", raise_on_error: false
+ bundle "install --force", raise_on_error: false
ensure
FileUtils.chmod("+x", foo_path)
end
@@ -949,12 +1180,12 @@ RSpec.describe "bundle install with gem sources" do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem 'foo'
G
end
- it "should display a proper message to explain the problem" do
+ it "should still work" do
bundle "config set --local path vendor"
bundle :install
expect(out).to include("Bundle complete!")
@@ -963,7 +1194,7 @@ RSpec.describe "bundle install with gem sources" do
FileUtils.chmod("-w", gem_home)
begin
- bundle "install --redownload"
+ bundle "install --force"
ensure
FileUtils.chmod("+w", gem_home)
end
@@ -984,7 +1215,7 @@ RSpec.describe "bundle install with gem sources" do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem 'foo'
G
end
@@ -997,9 +1228,37 @@ RSpec.describe "bundle install with gem sources" do
FileUtils.chmod(0o777, gems_path)
- bundle "install --redownload", raise_on_error: false
+ bundle "install --force", raise_on_error: false
- expect(err).to include("The installation path is insecure. Bundler cannot continue.")
+ expect(err).to include("Bundler cannot reinstall foo-1.0.0 because there's a previous installation of it at #{gems_path}/foo-1.0.0 that is unsafe to remove")
+ end
+ end
+
+ describe "when gems path is world writable (no sticky bit set), but previous install is just an empty dir (like it happens with default gems)", :permissions do
+ let(:gems_path) { bundled_app("vendor/#{Bundler.ruby_scope}/gems") }
+ let(:full_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 "https://gem.repo4"
+ gem 'foo'
+ G
+ end
+
+ it "does not try to remove the directory and thus don't abort with an error about unsafe directory removal" do
+ bundle "config set --local path vendor"
+
+ FileUtils.mkdir_p(gems_path)
+ FileUtils.chmod(0o777, gems_path)
+ Dir.mkdir(full_path)
+
+ bundle "install"
end
end
@@ -1009,8 +1268,8 @@ RSpec.describe "bundle install with gem sources" do
before do
FileUtils.mkdir_p(cache_path)
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
end
@@ -1025,12 +1284,12 @@ RSpec.describe "bundle install with gem sources" do
end
describe "when gemspecs are unreadable", :permissions do
- let(:gemspec_path) { vendored_gems("specifications/rack-1.0.0.gemspec") }
+ let(:gemspec_path) { vendored_gems("specifications/myrack-1.0.0.gemspec") }
before do
gemfile <<~G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
bundle "config path vendor/bundle"
bundle :install
@@ -1047,19 +1306,121 @@ RSpec.describe "bundle install with gem sources" do
end
end
+ describe "parallel make" do
+ before do
+ unless Gem::Installer.private_method_defined?(:build_jobs)
+ skip "This example is runnable when RubyGems::Installer implements `build_jobs`"
+ end
+
+ @old_makeflags = ENV["MAKEFLAGS"]
+ @gemspec = nil
+
+ extconf_code = <<~CODE
+ require "mkmf"
+ create_makefile("foo")
+ CODE
+
+ build_repo4 do
+ build_gem "mypsych", "4.0.6" do |s|
+ @gemspec = s
+ extension = "ext/mypsych/extconf.rb"
+ s.extensions = extension
+
+ s.write(extension, extconf_code)
+ end
+ end
+ end
+
+ after do
+ if @old_makeflags
+ ENV["MAKEFLAGS"] = @old_makeflags
+ else
+ ENV.delete("MAKEFLAGS")
+ end
+ end
+
+ it "doesn't pass down -j to make when MAKEFLAGS is set" do
+ ENV["MAKEFLAGS"] = "-j1"
+
+ install_gemfile(<<~G, env: { "BUNDLE_JOBS" => "8" })
+ source "https://gem.repo4"
+ gem "mypsych"
+ G
+
+ gem_make_out = File.read(File.join(@gemspec.extension_dir, "gem_make.out"))
+
+ expect(gem_make_out).not_to include("make -j8")
+ end
+
+ it "pass down the BUNDLE_JOBS to RubyGems when running the compilation of an extension" do
+ ENV.delete("MAKEFLAGS")
+
+ install_gemfile(<<~G, env: { "BUNDLE_JOBS" => "8" })
+ source "https://gem.repo4"
+ gem "mypsych"
+ G
+
+ gem_make_out = File.read(File.join(@gemspec.extension_dir, "gem_make.out"))
+
+ expect(gem_make_out).to include("make -j8")
+ end
+
+ it "uses nprocessors by default" do
+ ENV.delete("MAKEFLAGS")
+
+ install_gemfile(<<~G)
+ source "https://gem.repo4"
+ gem "mypsych"
+ G
+
+ gem_make_out = File.read(File.join(@gemspec.extension_dir, "gem_make.out"))
+
+ expect(gem_make_out).to include("make -j#{Etc.nprocessors + 1}")
+ end
+ end
+
+ describe "when configured path is UTF-8 and a file inside a gem package too" do
+ let(:app_path) do
+ path = tmp("♥")
+ FileUtils.mkdir_p(path)
+ path
+ end
+
+ let(:path) do
+ root.join("vendor/bundle")
+ end
+
+ before do
+ build_repo4 do
+ build_gem "mygem" do |s|
+ s.write "spec/fixtures/_posts/2016-04-01-错误.html"
+ end
+ end
+ end
+
+ it "works" do
+ bundle "config path #{app_path}/vendor/bundle", dir: app_path
+
+ install_gemfile app_path.join("Gemfile"),<<~G, dir: app_path
+ source "https://gem.repo4"
+ gem "mygem", "1.0"
+ G
+ end
+ end
+
context "after installing with --standalone" do
before do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle "config set --local path bundle"
bundle "install", standalone: true
end
it "includes the standalone path" do
- bundle "binstubs rack", standalone: true
- standalone_line = File.read(bundled_app("bin/rackup")).each_line.find {|line| line.include? "$:.unshift" }.strip
+ bundle "binstubs myrack", standalone: true
+ standalone_line = File.read(bundled_app("bin/myrackup")).each_line.find {|line| line.include? "$:.unshift" }.strip
expect(standalone_line).to eq %($:.unshift File.expand_path "../bundle", __dir__)
end
end
@@ -1080,23 +1441,27 @@ RSpec.describe "bundle install with gem sources" do
end
end
- context "in a frozen bundle" do
- before do
+ context "when current platform not included in the lockfile" do
+ around do |example|
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-linux"
+ end
end
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "libv8"
G
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
libv8 (8.4.255.0-x86_64-darwin-19)
@@ -1107,14 +1472,40 @@ RSpec.describe "bundle install with gem sources" do
libv8
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
- bundle "config set --local deployment true"
+ simulate_platform("x86_64-linux", &example)
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 }
+ it "adds the current platform to the lockfile" do
+ bundle "install --verbose"
+
+ expect(out).to include("re-resolving dependencies because your lockfile is missing the current platform")
+ expect(out).not_to include("you are adding a new platform to your lockfile")
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ libv8 (8.4.255.0-x86_64-darwin-19)
+ libv8 (8.4.255.0-x86_64-linux)
+
+ PLATFORMS
+ x86_64-darwin-19
+ x86_64-linux
+
+ DEPENDENCIES
+ libv8
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "fails loudly if frozen mode set" do
+ bundle "config set --local deployment true"
+ 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. " \
@@ -1130,19 +1521,19 @@ RSpec.describe "bundle install with gem sources" do
build_gem "nokogiri", "1.12.4" do |s|
s.platform = "x86_64-darwin"
- s.add_runtime_dependency "racca", "~> 1.4"
+ s.add_dependency "racca", "~> 1.4"
end
build_gem "nokogiri", "1.12.4" do |s|
s.platform = "x86_64-linux"
- s.add_runtime_dependency "racca", "~> 1.4"
+ s.add_dependency "racca", "~> 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"
+ s.add_dependency "crass", "~> 1.0.2"
+ s.add_dependency "nokogiri", ">= 1.5.9"
end
end
@@ -1184,7 +1575,7 @@ RSpec.describe "bundle install with gem sources" do
#{Bundler::RubyVersion.system}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
@@ -1195,7 +1586,7 @@ RSpec.describe "bundle install with gem sources" do
bundle "install", artifice: "compact_index"
end
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo4, "crass", "1.0.6"
c.checksum gem_repo4, "loofah", "2.12.0"
c.checksum gem_repo4, "nokogiri", "1.12.4", "x86_64-darwin"
@@ -1225,25 +1616,74 @@ RSpec.describe "bundle install with gem sources" do
loofah (~> 2.12.0)
#{checksums}
RUBY VERSION
- #{Bundler::RubyVersion.system}
+ #{Bundler::RubyVersion.system}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ context "when lockfile has incorrect dependencies" do
+ before do
+ build_repo2
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "myrack_middleware"
+ G
+
+ system_gems "myrack_middleware-1.0", path: default_bundle_path
+
+ # we want to raise when the 1.0 line should be followed by " myrack (= 0.9.1)" but isn't
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ myrack_middleware (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack_middleware
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
L
end
+
+ it "raises a clear error message when frozen" do
+ bundle "config set frozen true"
+ bundle "install", raise_on_error: false
+
+ expect(exitstatus).to eq(41)
+ expect(err).to eq("Bundler found incorrect dependencies in the lockfile for myrack_middleware-1.0")
+ end
+
+ it "updates the lockfile when not frozen" do
+ missing_dep = "myrack (0.9.1)"
+ expect(lockfile).not_to include(missing_dep)
+
+ bundle "config set frozen false"
+ bundle :install
+
+ expect(lockfile).to include(missing_dep)
+ expect(out).to include("now installed")
+ end
end
context "with --local flag" do
before do
- system_gems "rack-1.0.0", path: default_bundle_path
+ system_gems "myrack-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://gem.repo1"
source "https://not-existing-source" do
- gem "rack"
+ gem "myrack"
end
G
@@ -1258,40 +1698,108 @@ RSpec.describe "bundle install with gem sources" do
it "installs only gems of the specified groups" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
- gem "rack", group: :a
+ gem "myrack", group: :a
gem "rake", group: :b
gem "yard", group: :c
G
- expect(out).to include("Installing rack")
+ expect(out).to include("Installing myrack")
expect(out).to include("Installing rake")
expect(out).not_to include("Installing yard")
end
end
context "with --prefer-local flag" do
- before do
- build_repo4 do
- build_gem "foo", "1.0.1"
- build_gem "foo", "1.0.0"
- build_gem "bar", "1.0.0"
+ context "and gems available locally" do
+ before do
+ build_repo4 do
+ build_gem "foo", "1.0.1"
+ build_gem "foo", "1.0.0"
+ build_gem "bar", "1.0.0"
+
+ build_gem "a", "1.0.0" do |s|
+ s.add_dependency "foo", "~> 1.0.0"
+ end
+
+ build_gem "b", "1.0.0" do |s|
+ s.add_dependency "foo", "~> 1.0.1"
+ end
+ end
+
+ system_gems "foo-1.0.0", path: default_bundle_path, gem_repo: gem_repo4
+ end
+
+ it "fetches remote sources when not available locally" do
+ install_gemfile <<-G, "prefer-local": true, verbose: true
+ source "https://gem.repo4"
+
+ gem "foo"
+ gem "bar"
+ G
+
+ expect(out).to include("Using foo 1.0.0").and include("Fetching bar 1.0.0").and include("Installing bar 1.0.0")
+ expect(last_command).to be_success
+ end
+
+ it "fetches remote sources when local version does not match requirements" do
+ install_gemfile <<-G, "prefer-local": true, verbose: true
+ source "https://gem.repo4"
+
+ gem "foo", "1.0.1"
+ gem "bar"
+ G
+
+ expect(out).to include("Fetching foo 1.0.1").and include("Installing foo 1.0.1").and include("Fetching bar 1.0.0").and include("Installing bar 1.0.0")
+ expect(last_command).to be_success
end
- system_gems "foo-1.0.0", path: default_bundle_path, gem_repo: gem_repo4
+ it "uses the locally available version for sub-dependencies when possible" do
+ install_gemfile <<-G, "prefer-local": true, verbose: true
+ source "https://gem.repo4"
+
+ gem "a"
+ G
+
+ expect(out).to include("Using foo 1.0.0").and include("Fetching a 1.0.0").and include("Installing a 1.0.0")
+ expect(last_command).to be_success
+ end
+
+ it "fetches remote sources for sub-dependencies when the locally available version does not satisfy the requirement" do
+ install_gemfile <<-G, "prefer-local": true, verbose: true
+ source "https://gem.repo4"
+
+ gem "b"
+ G
+
+ expect(out).to include("Fetching foo 1.0.1").and include("Installing foo 1.0.1").and include("Fetching b 1.0.0").and include("Installing b 1.0.0")
+ expect(last_command).to be_success
+ end
end
- it "fetches remote sources only when not available locally" do
- install_gemfile <<-G, "prefer-local": true, verbose: true
- source "#{file_uri_for(gem_repo4)}"
+ context "and no gems available locally" do
+ before do
+ build_repo4 do
+ build_gem "myreline", "0.3.8"
+ build_gem "debug", "0.2.1"
- gem "foo"
- gem "bar"
- G
+ build_gem "debug", "1.10.0" do |s|
+ s.add_dependency "myreline"
+ end
+ end
+ end
- expect(out).to include("Using foo 1.0.0").and include("Fetching bar 1.0.0").and include("Installing bar 1.0.0")
- expect(last_command).to be_success
+ it "resolves to the latest version if no gems are available locally" do
+ install_gemfile <<~G, "prefer-local": true, verbose: true
+ source "https://gem.repo4"
+
+ gem "debug"
+ G
+
+ expect(out).to include("Fetching debug 1.10.0").and include("Installing debug 1.10.0").and include("Fetching myreline 0.3.8").and include("Installing myreline 0.3.8")
+ expect(last_command).to be_success
+ end
end
end
@@ -1321,7 +1829,7 @@ RSpec.describe "bundle install with gem sources" do
it "installs fine" do
install_gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "binman"
G
@@ -1343,7 +1851,7 @@ RSpec.describe "bundle install with gem sources" do
it "does not crash unexpectedly" do
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "autobuild", "1.10.rc2"
G
@@ -1366,7 +1874,7 @@ RSpec.describe "bundle install with gem sources" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "aaa"
gem "zzz"
@@ -1374,7 +1882,7 @@ RSpec.describe "bundle install with gem sources" do
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
aaa (0.2.0)
zzz (< 0.2.0)
@@ -1388,7 +1896,7 @@ RSpec.describe "bundle install with gem sources" do
zzz!
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
@@ -1400,7 +1908,7 @@ RSpec.describe "bundle install with gem sources" do
context "when --jobs option given" do
before do
- install_gemfile "source \"#{file_uri_for(gem_repo1)}\"", jobs: 1
+ install_gemfile "source 'https://gem.repo1'", jobs: 1
end
it "does not save the flag to config" do
@@ -1418,7 +1926,7 @@ RSpec.describe "bundle install with gem sources" do
it "shows a proper error" do
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
@@ -1430,10 +1938,98 @@ RSpec.describe "bundle install with gem sources" do
9.99.8
L
- install_gemfile "source \"#{file_uri_for(gem_repo1)}\"", env: { "BUNDLER_VERSION" => "9.99.8" }, raise_on_error: false
+ install_gemfile "source \"https://gem.repo1\"", env: { "BUNDLER_VERSION" => "9.99.8" }, raise_on_error: false
expect(err).not_to include("ERROR REPORT TEMPLATE")
expect(err).to include("The running version of Bundler (9.99.9) does not match the version of the specification installed for it (9.99.8)")
end
end
+
+ it "only installs executable files in bin" do
+ bundle "config set --local path vendor/bundle"
+
+ install_gemfile <<~G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ expected_executables = [vendored_gems("bin/myrackup").to_s]
+ expected_executables << vendored_gems("bin/myrackup.bat").to_s if Gem.win_platform?
+ expect(Dir.glob(vendored_gems("bin/*"))).to eq(expected_executables)
+ end
+
+ it "prevents removing binstubs when BUNDLE_CLEAN is set" do
+ build_repo4 do
+ build_gem "kamal", "4.0.6" do |s|
+ s.executables = ["kamal"]
+ end
+ end
+
+ gemfile = <<~G
+ source "https://gem.repo4"
+ gem "kamal"
+ G
+
+ install_gemfile(gemfile, env: { "BUNDLE_CLEAN" => "true", "BUNDLE_PATH" => "vendor/bundle" })
+
+ expected_executables = [vendored_gems("bin/kamal").to_s]
+ expected_executables << vendored_gems("bin/kamal.bat").to_s if Gem.win_platform?
+ expect(Dir.glob(vendored_gems("bin/*"))).to eq(expected_executables)
+ end
+
+ it "preserves lockfile versions conservatively" do
+ build_repo4 do
+ build_gem "mypsych", "4.0.6" do |s|
+ s.add_dependency "mystringio"
+ end
+
+ build_gem "mypsych", "5.1.2" do |s|
+ s.add_dependency "mystringio"
+ end
+
+ build_gem "mystringio", "3.1.0"
+ build_gem "mystringio", "3.1.1"
+ end
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ mypsych (4.0.6)
+ mystringio
+ mystringio (3.1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ mypsych (~> 4.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ install_gemfile <<~G
+ source "https://gem.repo4"
+ gem "mypsych", "~> 5.0"
+ G
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ mypsych (5.1.2)
+ mystringio
+ mystringio (3.1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ mypsych (~> 5.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
end
diff --git a/spec/bundler/commands/issue_spec.rb b/spec/bundler/commands/issue_spec.rb
index 143f6333ce..346cdedc42 100644
--- a/spec/bundler/commands/issue_spec.rb
+++ b/spec/bundler/commands/issue_spec.rb
@@ -3,7 +3,7 @@
RSpec.describe "bundle issue" do
it "exits with a message" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
G
diff --git a/spec/bundler/commands/licenses_spec.rb b/spec/bundler/commands/licenses_spec.rb
index a203984890..bfec938efd 100644
--- a/spec/bundler/commands/licenses_spec.rb
+++ b/spec/bundler/commands/licenses_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe "bundle licenses" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "rails"
gem "with_license"
G
@@ -24,7 +24,7 @@ RSpec.describe "bundle licenses" do
it "performs an automatic bundle install" do
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "rails"
gem "with_license"
gem "foo"
diff --git a/spec/bundler/commands/list_spec.rb b/spec/bundler/commands/list_spec.rb
index 5ac2077d81..c890646a81 100644
--- a/spec/bundler/commands/list_spec.rb
+++ b/spec/bundler/commands/list_spec.rb
@@ -1,6 +1,28 @@
# frozen_string_literal: true
+require "json"
+
RSpec.describe "bundle list" do
+ def find_gem_name(json:, name:)
+ parse_json(json)["gems"].detect {|h| h["name"] == name }
+ end
+
+ def parse_json(json)
+ JSON.parse(json)
+ end
+
+ context "in verbose mode" do
+ it "logs the actual flags passed to the command" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ G
+
+ bundle "list --verbose"
+
+ expect(out).to include("Running `bundle list --verbose`")
+ end
+ end
+
context "with name-only and paths option" do
it "raises an error" do
bundle "list --name-only --paths", raise_on_error: false
@@ -17,12 +39,26 @@ RSpec.describe "bundle list" do
end
end
+ context "with invalid format option" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ G
+ end
+
+ it "raises an error" do
+ bundle "list --format=nope", raise_on_error: false
+
+ expect(err).to eq "Unknown option`--format=nope`. Supported formats: `json`"
+ end
+ end
+
describe "with without-group option" do
before do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
gem "rspec", :group => [:test]
gem "rails", :group => [:production]
G
@@ -32,10 +68,21 @@ RSpec.describe "bundle list" do
it "prints the gems not in the specified group" do
bundle "list --without-group test"
- expect(out).to include(" * rack (1.0.0)")
+ expect(out).to include(" * myrack (1.0.0)")
expect(out).to include(" * rails (2.3.2)")
expect(out).not_to include(" * rspec (1.2.7)")
end
+
+ it "prints the gems not in the specified group with json" do
+ bundle "list --without-group test --format=json"
+
+ gem = find_gem_name(json: out, name: "myrack")
+ expect(gem["version"]).to eq("1.0.0")
+ gem = find_gem_name(json: out, name: "rails")
+ expect(gem["version"]).to eq("2.3.2")
+ gem = find_gem_name(json: out, name: "rspec")
+ expect(gem).to be_nil
+ end
end
context "when group is not found" do
@@ -50,19 +97,30 @@ RSpec.describe "bundle list" 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).to include(" * myrack (1.0.0)")
expect(out).not_to include(" * rails (2.3.2)")
expect(out).not_to include(" * rspec (1.2.7)")
end
+
+ it "prints the gems not in the specified groups with json" do
+ bundle "list --without-group test production --format=json"
+
+ gem = find_gem_name(json: out, name: "myrack")
+ expect(gem["version"]).to eq("1.0.0")
+ gem = find_gem_name(json: out, name: "rails")
+ expect(gem).to be_nil
+ gem = find_gem_name(json: out, name: "rspec")
+ expect(gem).to be_nil
+ end
end
end
describe "with only-group option" do
before do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
gem "rspec", :group => [:test]
gem "rails", :group => [:production]
G
@@ -72,9 +130,18 @@ RSpec.describe "bundle list" do
it "prints the gems in the specified group" do
bundle "list --only-group default"
- expect(out).to include(" * rack (1.0.0)")
+ expect(out).to include(" * myrack (1.0.0)")
expect(out).not_to include(" * rspec (1.2.7)")
end
+
+ it "prints the gems in the specified group with json" do
+ bundle "list --only-group default --format=json"
+
+ gem = find_gem_name(json: out, name: "myrack")
+ expect(gem["version"]).to eq("1.0.0")
+ gem = find_gem_name(json: out, name: "rspec")
+ expect(gem).to be_nil
+ end
end
context "when group is not found" do
@@ -89,19 +156,30 @@ RSpec.describe "bundle list" 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(" * myrack (1.0.0)")
expect(out).to include(" * rails (2.3.2)")
expect(out).not_to include(" * rspec (1.2.7)")
end
+
+ it "prints the gems in the specified groups with json" do
+ bundle "list --only-group default production --format=json"
+
+ gem = find_gem_name(json: out, name: "myrack")
+ expect(gem["version"]).to eq("1.0.0")
+ gem = find_gem_name(json: out, name: "rails")
+ expect(gem["version"]).to eq("2.3.2")
+ gem = find_gem_name(json: out, name: "rspec")
+ expect(gem).to be_nil
+ end
end
end
context "with name-only option" do
before do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
gem "rspec", :group => [:test]
G
end
@@ -109,16 +187,25 @@ RSpec.describe "bundle list" do
it "prints only the name of the gems in the bundle" do
bundle "list --name-only"
- expect(out).to include("rack")
+ expect(out).to include("myrack")
expect(out).to include("rspec")
end
+
+ it "prints only the name of the gems in the bundle with json" do
+ bundle "list --name-only --format=json"
+
+ gem = find_gem_name(json: out, name: "myrack")
+ expect(gem.keys).to eq(["name"])
+ gem = find_gem_name(json: out, name: "rspec")
+ expect(gem.keys).to eq(["name"])
+ end
end
context "with paths option" do
before do
build_repo2 do
- build_gem "rack", "1.2" do |s|
- s.executables = "rackup"
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
end
build_gem "bar"
@@ -126,32 +213,53 @@ RSpec.describe "bundle list" do
build_git "git_test", "1.0.0", path: lib_path("git_test")
- build_lib("gemspec_test", path: tmp.join("gemspec_test")) do |s|
+ build_lib("gemspec_test", path: tmp("gemspec_test")) do |s|
s.add_dependency "bar", "=1.0.0"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack"
+ source "https://gem.repo2"
+ gem "myrack"
gem "rails"
gem "git_test", :git => "#{lib_path("git_test")}"
- gemspec :path => "#{tmp.join("gemspec_test")}"
+ gemspec :path => "#{tmp("gemspec_test")}"
G
end
it "prints the path of each gem in the bundle" do
bundle "list --paths"
expect(out).to match(%r{.*\/rails\-2\.3\.2})
- expect(out).to match(%r{.*\/rack\-1\.2})
+ expect(out).to match(%r{.*\/myrack\-1\.2})
expect(out).to match(%r{.*\/git_test\-\w})
expect(out).to match(%r{.*\/gemspec_test})
end
+
+ it "prints the path of each gem in the bundle with json" do
+ bundle "list --paths --format=json"
+
+ gem = find_gem_name(json: out, name: "rails")
+ expect(gem["path"]).to match(%r{.*\/rails\-2\.3\.2})
+ expect(gem["git_version"]).to be_nil
+
+ gem = find_gem_name(json: out, name: "myrack")
+ expect(gem["path"]).to match(%r{.*\/myrack\-1\.2})
+ expect(gem["git_version"]).to be_nil
+
+ gem = find_gem_name(json: out, name: "git_test")
+ expect(gem["path"]).to match(%r{.*\/git_test\-\w})
+ expect(gem["git_version"]).to be_truthy
+ expect(gem["git_version"].strip).to eq(gem["git_version"])
+
+ gem = find_gem_name(json: out, name: "gemspec_test")
+ expect(gem["path"]).to match(%r{.*\/gemspec_test})
+ expect(gem["git_version"]).to be_nil
+ end
end
context "when no gems are in the gemfile" do
before do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
end
@@ -159,30 +267,42 @@ RSpec.describe "bundle list" do
bundle "list"
expect(out).to include("No gems in the Gemfile")
end
+
+ it "prints empty json" do
+ bundle "list --format=json"
+ expect(parse_json(out)["gems"]).to eq([])
+ end
end
context "without options" do
before do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
gem "rspec", :group => [:test]
G
end
it "lists gems installed in the bundle" do
bundle "list"
- expect(out).to include(" * rack (1.0.0)")
+ expect(out).to include(" * myrack (1.0.0)")
+ end
+
+ it "lists gems installed in the bundle with json" do
+ bundle "list --format=json"
+
+ gem = find_gem_name(json: out, name: "myrack")
+ expect(gem["version"]).to eq("1.0.0")
end
end
context "when using the ls alias" do
before do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
gem "rspec", :group => [:test]
G
end
diff --git a/spec/bundler/commands/lock_spec.rb b/spec/bundler/commands/lock_spec.rb
index b0d6fa9134..c8af9c8dd4 100644
--- a/spec/bundler/commands/lock_spec.rb
+++ b/spec/bundler/commands/lock_spec.rb
@@ -1,31 +1,22 @@
# frozen_string_literal: true
RSpec.describe "bundle lock" do
- let(:repo) { gem_repo1 }
-
- before :each do
- gemfile <<-G
- source "#{file_uri_for(repo)}"
- gem "rails"
- gem "weakling"
- gem "foo"
- G
-
- checksums = checksums_section_when_existing do |c|
- c.checksum repo, "actionmailer", "2.3.2"
- c.checksum repo, "actionpack", "2.3.2"
- c.checksum repo, "activerecord", "2.3.2"
- c.checksum repo, "activeresource", "2.3.2"
- c.checksum repo, "activesupport", "2.3.2"
- c.checksum repo, "foo", "1.0"
- c.checksum repo, "rails", "2.3.2"
- c.checksum repo, "rake", rake_version
- c.checksum repo, "weakling", "0.0.3"
+ let(:expected_lockfile) do
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "actionmailer", "2.3.2"
+ c.checksum gem_repo4, "actionpack", "2.3.2"
+ c.checksum gem_repo4, "activerecord", "2.3.2"
+ c.checksum gem_repo4, "activeresource", "2.3.2"
+ c.checksum gem_repo4, "activesupport", "2.3.2"
+ c.checksum gem_repo4, "foo", "1.0"
+ c.checksum gem_repo4, "rails", "2.3.2"
+ c.checksum gem_repo4, "rake", rake_version
+ c.checksum gem_repo4, "weakling", "0.0.3"
end
- @lockfile = <<~L
+ <<~L
GEM
- remote: #{file_uri_for(repo)}/
+ remote: https://gem.repo4/
specs:
actionmailer (2.3.2)
activesupport (= 2.3.2)
@@ -55,48 +46,151 @@ RSpec.describe "bundle lock" do
weakling
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
+ L
+ end
+
+ let(:outdated_lockfile) do
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "actionmailer", "2.3.1"
+ c.checksum gem_repo4, "actionpack", "2.3.1"
+ c.checksum gem_repo4, "activerecord", "2.3.1"
+ c.checksum gem_repo4, "activeresource", "2.3.1"
+ c.checksum gem_repo4, "activesupport", "2.3.1"
+ c.checksum gem_repo4, "foo", "1.0"
+ c.checksum gem_repo4, "rails", "2.3.1"
+ c.checksum gem_repo4, "rake", rake_version
+ c.checksum gem_repo4, "weakling", "0.0.3"
+ end
+
+ <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ actionmailer (2.3.1)
+ activesupport (= 2.3.1)
+ actionpack (2.3.1)
+ activesupport (= 2.3.1)
+ activerecord (2.3.1)
+ activesupport (= 2.3.1)
+ activeresource (2.3.1)
+ activesupport (= 2.3.1)
+ activesupport (2.3.1)
+ foo (1.0)
+ rails (2.3.1)
+ actionmailer (= 2.3.1)
+ actionpack (= 2.3.1)
+ activerecord (= 2.3.1)
+ activeresource (= 2.3.1)
+ rake (= #{rake_version})
+ rake (#{rake_version})
+ weakling (0.0.3)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo
+ rails
+ weakling
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
L
end
+ let(:gemfile_with_rails_weakling_and_foo_from_repo4) do
+ build_repo4 do
+ build_gem "rake", "10.0.1"
+ build_gem "rake", rake_version
+
+ %w[2.3.1 2.3.2].each do |version|
+ build_gem "rails", version do |s|
+ s.executables = "rails"
+ s.add_dependency "rake", version == "2.3.1" ? "10.0.1" : rake_version
+ s.add_dependency "actionpack", version
+ s.add_dependency "activerecord", version
+ s.add_dependency "actionmailer", version
+ s.add_dependency "activeresource", version
+ end
+ build_gem "actionpack", version do |s|
+ s.add_dependency "activesupport", version
+ end
+ build_gem "activerecord", version do |s|
+ s.add_dependency "activesupport", version
+ end
+ build_gem "actionmailer", version do |s|
+ s.add_dependency "activesupport", version
+ end
+ build_gem "activeresource", version do |s|
+ s.add_dependency "activesupport", version
+ end
+ build_gem "activesupport", version
+ end
+
+ build_gem "weakling", "0.0.3"
+
+ build_gem "foo"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "rails"
+ gem "weakling"
+ gem "foo"
+ G
+ end
+
it "prints a lockfile when there is no existing lockfile with --print" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
bundle "lock --print"
- expect(out).to eq(@lockfile.chomp)
+ expect(out).to eq(expected_lockfile.chomp)
end
it "prints a lockfile when there is an existing lockfile with --print" do
- lockfile remove_checksums_section_from_lockfile(@lockfile)
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ lockfile expected_lockfile
bundle "lock --print"
- expect(out).to eq(remove_checksums_section_from_lockfile(@lockfile).chomp)
+ expect(out).to eq(expected_lockfile.chomp)
end
it "prints a lockfile when there is an existing checksums lockfile with --print" do
- lockfile @lockfile
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ lockfile expected_lockfile
bundle "lock --print"
- expect(out).to eq(@lockfile.chomp)
+ expect(out).to eq(expected_lockfile.chomp)
end
it "writes a lockfile when there is no existing lockfile" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
bundle "lock"
- expect(read_lockfile).to eq(@lockfile)
+ expect(read_lockfile).to eq(expected_lockfile)
end
it "prints a lockfile without fetching new checksums if the existing lockfile had no checksums" do
- lockfile remove_checksums_from_lockfile(@lockfile)
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ lockfile expected_lockfile
bundle "lock --print"
- expect(out).to eq(remove_checksums_from_lockfile(@lockfile).chomp)
+ expect(out).to eq(expected_lockfile.chomp)
end
it "touches the lockfile when there is an existing lockfile that does not need changes" do
- lockfile @lockfile
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ lockfile expected_lockfile
expect do
bundle "lock"
@@ -104,7 +198,9 @@ RSpec.describe "bundle lock" do
end
it "does not touch lockfile with --print" do
- lockfile @lockfile
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ lockfile expected_lockfile
expect do
bundle "lock --print"
@@ -112,56 +208,82 @@ RSpec.describe "bundle lock" do
end
it "writes a lockfile when there is an outdated lockfile using --update" do
- lockfile remove_checksums_from_lockfile(@lockfile.gsub("2.3.2", "2.3.1"), " (2.3.1)")
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ lockfile outdated_lockfile
bundle "lock --update"
- expect(read_lockfile).to eq(remove_checksums_from_lockfile(@lockfile))
+ expect(read_lockfile).to eq(expected_lockfile)
end
- it "writes a lockfile with checksums on --update when checksums exist" do
- lockfile @lockfile.gsub("2.3.2", "2.3.1")
+ it "prints an updated lockfile when there is an outdated lockfile using --print --update" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
- bundle "lock --update"
+ lockfile outdated_lockfile
+
+ bundle "lock --print --update"
- expect(read_lockfile).to eq(@lockfile)
+ expect(out).to eq(expected_lockfile.rstrip)
+ end
+
+ it "emits info messages to stderr when updating an outdated lockfile using --print --update" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ lockfile outdated_lockfile
+
+ bundle "lock --print --update"
+
+ expect(err).to eq(<<~STDERR.rstrip)
+ Fetching gem metadata from https://gem.repo4/...
+ Resolving dependencies...
+ STDERR
end
it "writes a lockfile when there is an outdated lockfile and bundle is frozen" do
- lockfile @lockfile.gsub("2.3.2", "2.3.1")
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ lockfile outdated_lockfile
bundle "lock --update", env: { "BUNDLE_FROZEN" => "true" }
- expect(read_lockfile).to eq(@lockfile)
+ expect(read_lockfile).to eq(expected_lockfile)
end
it "does not fetch remote specs when using the --local option" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
bundle "lock --update --local", raise_on_error: false
expect(err).to match(/locally installed gems/)
end
it "does not fetch remote checksums with --local" do
- lockfile remove_checksums_from_lockfile(@lockfile)
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ lockfile expected_lockfile
bundle "lock --print --local"
- # No checksums because --local prevents fetching them
- expect(out).to eq(remove_checksums_from_lockfile(@lockfile).chomp)
+ expect(out).to eq(expected_lockfile.chomp)
end
it "works with --gemfile flag" do
- create_file "CustomGemfile", <<-G
- source "#{file_uri_for(repo)}"
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ gemfile "CustomGemfile", <<-G
+ source "https://gem.repo4"
gem "foo"
G
- checksums = checksums_section_when_existing do |c|
- c.no_checksum "foo", "1.0"
+ bundle "lock --gemfile CustomGemfile"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "foo", "1.0"
end
lockfile = <<~L
GEM
- remote: #{file_uri_for(repo)}/
+ remote: https://gem.repo4/
specs:
foo (1.0)
@@ -172,42 +294,82 @@ RSpec.describe "bundle lock" do
foo
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
- bundle "lock --gemfile CustomGemfile"
-
expect(out).to match(/Writing lockfile to.+CustomGemfile\.lock/)
expect(read_lockfile("CustomGemfile.lock")).to eq(lockfile)
expect { read_lockfile }.to raise_error(Errno::ENOENT)
end
it "writes to a custom location using --lockfile" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
bundle "lock --lockfile=lock"
expect(out).to match(/Writing lockfile to.+lock/)
- expect(read_lockfile("lock")).to eq(remove_checksums_from_lockfile(@lockfile))
+ expect(read_lockfile("lock")).to eq(expected_lockfile)
expect { read_lockfile }.to raise_error(Errno::ENOENT)
end
+ it "updates a specific gem and write to a custom location" do
+ build_repo4 do
+ build_gem "foo", %w[1.0.2 1.0.3]
+ build_gem "warning", %w[1.4.0 1.5.0]
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "foo"
+ gem "warning"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4
+ specs:
+ foo (1.0.2)
+ warning (1.4.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ uri
+ warning
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock --update foo --lockfile=lock"
+
+ lockfile_content = read_lockfile("lock")
+ expect(lockfile_content).to include("foo (1.0.3)")
+ expect(lockfile_content).to include("warning (1.4.0)")
+ end
+
it "writes to custom location using --lockfile when a default lockfile is present" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
bundle "install"
bundle "lock --lockfile=lock"
- checksums = checksums_section_when_existing do |c|
- c.checksum repo, "actionmailer", "2.3.2"
- c.checksum repo, "actionpack", "2.3.2"
- c.checksum repo, "activerecord", "2.3.2"
- c.checksum repo, "activeresource", "2.3.2"
- c.checksum repo, "activesupport", "2.3.2"
- c.checksum repo, "foo", "1.0"
- c.checksum repo, "rails", "2.3.2"
- c.checksum repo, "rake", rake_version
- c.checksum repo, "weakling", "0.0.3"
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "actionmailer", "2.3.2"
+ c.checksum gem_repo4, "actionpack", "2.3.2"
+ c.checksum gem_repo4, "activerecord", "2.3.2"
+ c.checksum gem_repo4, "activeresource", "2.3.2"
+ c.checksum gem_repo4, "activesupport", "2.3.2"
+ c.checksum gem_repo4, "foo", "1.0"
+ c.checksum gem_repo4, "rails", "2.3.2"
+ c.checksum gem_repo4, "rake", rake_version
+ c.checksum gem_repo4, "weakling", "0.0.3"
end
lockfile = <<~L
GEM
- remote: #{file_uri_for(repo)}/
+ remote: https://gem.repo4/
specs:
actionmailer (2.3.2)
activesupport (= 2.3.2)
@@ -237,7 +399,7 @@ RSpec.describe "bundle lock" do
weakling
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
expect(out).to match(/Writing lockfile to.+lock/)
@@ -245,11 +407,60 @@ RSpec.describe "bundle lock" do
end
it "update specific gems using --update" do
- lockfile @lockfile.gsub("2.3.2", "2.3.1").gsub(rake_version, "10.0.1")
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "actionmailer", "2.3.1"
+ c.checksum gem_repo4, "actionpack", "2.3.1"
+ c.checksum gem_repo4, "activerecord", "2.3.1"
+ c.checksum gem_repo4, "activeresource", "2.3.1"
+ c.checksum gem_repo4, "activesupport", "2.3.1"
+ c.checksum gem_repo4, "foo", "1.0"
+ c.checksum gem_repo4, "rails", "2.3.1"
+ c.checksum gem_repo4, "rake", "10.0.1"
+ c.checksum gem_repo4, "weakling", "0.0.3"
+ end
+
+ lockfile_with_outdated_rails_and_rake = <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ actionmailer (2.3.1)
+ activesupport (= 2.3.1)
+ actionpack (2.3.1)
+ activesupport (= 2.3.1)
+ activerecord (2.3.1)
+ activesupport (= 2.3.1)
+ activeresource (2.3.1)
+ activesupport (= 2.3.1)
+ activesupport (2.3.1)
+ foo (1.0)
+ rails (2.3.1)
+ actionmailer (= 2.3.1)
+ actionpack (= 2.3.1)
+ activerecord (= 2.3.1)
+ activeresource (= 2.3.1)
+ rake (= 10.0.1)
+ rake (10.0.1)
+ weakling (0.0.3)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo
+ rails
+ weakling
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ lockfile lockfile_with_outdated_rails_and_rake
bundle "lock --update rails rake"
- expect(read_lockfile).to eq(remove_checksums_from_lockfile(@lockfile, "(2.3.2)", "(#{rake_version})"))
+ expect(read_lockfile).to eq(expected_lockfile)
end
it "updates specific gems using --update, even if that requires unlocking other top level gems" do
@@ -275,7 +486,7 @@ RSpec.describe "bundle lock" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "tapioca"
gem "ruby-lsp"
@@ -283,7 +494,7 @@ RSpec.describe "bundle lock" do
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}
+ remote: https://gem.repo4
specs:
prism (0.15.1)
ruby-lsp (0.12.0)
@@ -299,7 +510,7 @@ RSpec.describe "bundle lock" do
tapioca
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "lock --update tapioca --verbose"
@@ -338,7 +549,7 @@ RSpec.describe "bundle lock" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "tapioca"
gem "ruby-lsp"
@@ -347,7 +558,7 @@ RSpec.describe "bundle lock" do
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}
+ remote: https://gem.repo4
specs:
other-prism-dependent (1.0.0)
prism (>= 0.15.1)
@@ -365,7 +576,7 @@ RSpec.describe "bundle lock" do
tapioca
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "lock --update tapioca"
@@ -375,7 +586,9 @@ RSpec.describe "bundle lock" do
end
it "preserves unknown checksum algorithms" do
- lockfile @lockfile.gsub(/(sha256=[a-f0-9]+)$/, "constant=true,\\1,xyz=123")
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ lockfile expected_lockfile.gsub(/(sha256=[a-f0-9]+)$/, "constant=true,\\1,xyz=123")
previous_lockfile = read_lockfile
@@ -385,17 +598,19 @@ RSpec.describe "bundle lock" do
end
it "does not unlock git sources when only uri shape changes" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
build_git("foo")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "foo", :git => "#{file_uri_for(lib_path("foo-1.0"))}"
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo-1.0")}"
G
# Change uri format to end with "/" and reinstall
install_gemfile <<-G, verbose: true
- source "#{file_uri_for(gem_repo1)}"
- gem "foo", :git => "#{file_uri_for(lib_path("foo-1.0"))}/"
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo-1.0")}/"
G
expect(out).to include("using resolution from the lockfile")
@@ -403,24 +618,26 @@ RSpec.describe "bundle lock" do
end
it "updates specific gems using --update using the locked revision of unrelated git gems for resolving" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
ref = build_git("foo").ref_for("HEAD")
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rake"
- gem "foo", :git => "#{file_uri_for(lib_path("foo-1.0"))}", :branch => "deadbeef"
+ gem "foo", :git => "#{lib_path("foo-1.0")}", :branch => "deadbeef"
G
lockfile <<~L
GIT
- remote: #{file_uri_for(lib_path("foo-1.0"))}
+ remote: #{lib_path("foo-1.0")}
revision: #{ref}
branch: deadbeef
specs:
foo (1.0)
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
rake (10.0.1)
@@ -432,7 +649,7 @@ RSpec.describe "bundle lock" do
rake
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "lock --update rake --verbose"
@@ -441,20 +658,24 @@ RSpec.describe "bundle lock" do
end
it "errors when updating a missing specific gems using --update" do
- lockfile @lockfile
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ lockfile expected_lockfile
bundle "lock --update blahblah", raise_on_error: false
expect(err).to eq("Could not find gem 'blahblah'.")
- expect(read_lockfile).to eq(@lockfile)
+ expect(read_lockfile).to eq(expected_lockfile)
end
it "can lock without downloading gems" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "thin"
- gem "rack_middleware", :group => "test"
+ gem "myrack_middleware", :group => "test"
G
bundle "config set without test"
bundle "config set path vendor/bundle"
@@ -485,7 +706,7 @@ RSpec.describe "bundle lock" do
# establish a lockfile set to 1.4.3
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem 'foo', '1.4.3'
gem 'bar', '2.0.3'
gem 'qux', '1.0.0'
@@ -494,7 +715,7 @@ RSpec.describe "bundle lock" do
# remove 1.4.3 requirement and bar altogether
# to setup update specs below
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem 'foo'
gem 'qux'
G
@@ -505,19 +726,19 @@ RSpec.describe "bundle lock" do
it "single gem updates dependent gem to minor" do
bundle "lock --update foo --patch"
- expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[foo-1.4.5 bar-2.1.1 qux-1.0.0].sort)
+ expect(the_bundle.locked_specs).to eq(%w[foo-1.4.5 bar-2.1.1 qux-1.0.0].sort)
end
it "minor preferred with strict" do
bundle "lock --update --minor --strict"
- expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[foo-1.5.0 bar-2.1.1 qux-1.1.0].sort)
+ expect(the_bundle.locked_specs).to eq(%w[foo-1.5.0 bar-2.1.1 qux-1.1.0].sort)
end
it "shows proper error when Gemfile changes forbid patch upgrades, and --patch --strict is given" do
# force next minor via Gemfile
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem 'foo', '1.5.0'
gem 'qux'
G
@@ -534,25 +755,25 @@ RSpec.describe "bundle lock" do
it "defaults to major" do
bundle "lock --update --pre"
- expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[foo-2.0.0.pre bar-4.0.0.pre qux-2.0.0].sort)
+ expect(the_bundle.locked_specs).to eq(%w[foo-2.0.0.pre bar-4.0.0.pre qux-2.0.0].sort)
end
it "patch preferred" do
bundle "lock --update --patch --pre"
- expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[foo-1.4.5 bar-2.1.2.pre qux-1.0.1].sort)
+ expect(the_bundle.locked_specs).to eq(%w[foo-1.4.5 bar-2.1.2.pre qux-1.0.1].sort)
end
it "minor preferred" do
bundle "lock --update --minor --pre"
- expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[foo-1.5.1 bar-3.1.0.pre qux-1.1.0].sort)
+ expect(the_bundle.locked_specs).to eq(%w[foo-1.5.1 bar-3.1.0.pre qux-1.1.0].sort)
end
it "major preferred" do
bundle "lock --update --major --pre"
- expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[foo-2.0.0.pre bar-4.0.0.pre qux-2.0.0].sort)
+ expect(the_bundle.locked_specs).to eq(%w[foo-2.0.0.pre bar-4.0.0.pre qux-2.0.0].sort)
end
end
end
@@ -568,13 +789,13 @@ RSpec.describe "bundle lock" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem 'sequel'
G
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
sequel (5.71.0)
@@ -585,7 +806,7 @@ RSpec.describe "bundle lock" do
sequel
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
@@ -594,7 +815,7 @@ RSpec.describe "bundle lock" do
it "adds the latest version of the new dependency" do
bundle "lock --minor --update sequel"
- expect(the_bundle.locked_gems.specs.map(&:full_name)).to eq(%w[sequel-5.72.0 bigdecimal-99.1.4].sort)
+ expect(the_bundle.locked_specs).to eq(%w[sequel-5.72.0 bigdecimal-99.1.4].sort)
end
end
@@ -606,33 +827,104 @@ RSpec.describe "bundle lock" do
system_gems "bundler-55", gem_repo: gem_repo4
install_gemfile <<-G, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
- source "https://gems.repo4"
+ source "https://gem.repo4"
G
lockfile lockfile.sub(/(^\s*)#{Bundler::VERSION}($)/, '\11.0.0\2')
bundle "lock --update --bundler --verbose", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
- expect(lockfile).to end_with("BUNDLED WITH\n 55\n")
+ expect(lockfile).to end_with("BUNDLED WITH\n 55\n")
- update_repo4 do
+ build_repo4 do
build_gem "bundler", "99"
end
bundle "lock --update --bundler --verbose", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
- expect(lockfile).to end_with("BUNDLED WITH\n 99\n")
+ expect(lockfile).to end_with("BUNDLED WITH\n 99\n")
end
- it "supports adding new platforms" do
- bundle "lock --add-platform java x86-mingw32"
+ it "supports adding new platforms when there's no previous lockfile" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ bundle "lock --add-platform java x86-mingw32 --verbose"
+ expect(out).to include("Resolving dependencies because there's no lockfile")
allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
- lockfile = Bundler::LockfileParser.new(read_lockfile)
- expect(lockfile.platforms).to match_array(default_platform_list(java, x86_mingw32))
+ expect(the_bundle.locked_platforms).to match_array(default_platform_list("java", "x86-mingw32"))
+ end
+
+ it "supports adding new platforms when a previous lockfile exists" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ bundle "lock"
+ bundle "lock --add-platform java x86-mingw32 --verbose"
+ expect(out).to include("Found changes from the lockfile, re-resolving dependencies because you are adding a new platform to your lockfile")
+
+ allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
+ expect(the_bundle.locked_platforms).to match_array(default_platform_list("java", "x86-mingw32"))
+ end
+
+ it "supports adding new platforms, when most specific locked platform is not the current platform, and current resolve is not compatible with the target platform" do
+ simulate_platform "arm64-darwin-23" do
+ build_repo4 do
+ build_gem "foo" do |s|
+ s.platform = "arm64-darwin"
+ end
+
+ build_gem "foo" do |s|
+ s.platform = "java"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "foo"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ foo (1.0-arm64-darwin)
+
+ PLATFORMS
+ arm64-darwin
+
+ DEPENDENCIES
+ foo
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock --add-platform java"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ foo (1.0-arm64-darwin)
+ foo (1.0-java)
+
+ PLATFORMS
+ arm64-darwin
+ java
+
+ DEPENDENCIES
+ foo
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
end
it "supports adding new platforms with force_ruby_platform = true" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
platform_specific (1.0)
platform_specific (1.0-x86-64_linux)
@@ -649,34 +941,37 @@ RSpec.describe "bundle lock" do
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, x86_mingw32)
+ expect(the_bundle.locked_platforms).to contain_exactly(Gem::Platform::RUBY, "x86_64-linux", "java", "x86-mingw32")
end
it "supports adding the `ruby` platform" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
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(default_platform_list("ruby"))
+ expect(the_bundle.locked_platforms).to match_array(default_platform_list("ruby"))
end
- it "warns when adding an unknown platform" do
- bundle "lock --add-platform foobarbaz"
- expect(err).to include("The platform `foobarbaz` is unknown to RubyGems and adding it will likely lead to resolution errors")
+ it "fails when adding an unknown platform" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ bundle "lock --add-platform foobarbaz", raise_on_error: false
+ expect(err).to include("The platform `foobarbaz` is unknown to RubyGems and can't be added to the lockfile")
+ expect(last_command).to be_failure
end
it "allows removing platforms" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
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(default_platform_list(java, x86_mingw32))
+ expect(the_bundle.locked_platforms).to match_array(default_platform_list("java", "x86-mingw32"))
bundle "lock --remove-platform java"
- lockfile = Bundler::LockfileParser.new(read_lockfile)
- expect(lockfile.platforms).to match_array(default_platform_list(x86_mingw32))
+ expect(the_bundle.locked_platforms).to match_array(default_platform_list("x86-mingw32"))
end
it "also cleans up redundant platform gems when removing platforms" do
@@ -687,14 +982,14 @@ RSpec.describe "bundle lock" do
end
end
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo4, "nokogiri", "1.12.0"
c.checksum gem_repo4, "nokogiri", "1.12.0", "x86_64-darwin"
end
simulate_platform "x86_64-darwin-22" do
install_gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "nokogiri"
G
@@ -702,7 +997,7 @@ RSpec.describe "bundle lock" do
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
nokogiri (1.12.0)
nokogiri (1.12.0-x86_64-darwin)
@@ -715,7 +1010,7 @@ RSpec.describe "bundle lock" do
nokogiri
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
checksums.delete("nokogiri", Gem::Platform::RUBY)
@@ -726,7 +1021,7 @@ RSpec.describe "bundle lock" do
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
nokogiri (1.12.0-x86_64-darwin)
@@ -737,11 +1032,13 @@ RSpec.describe "bundle lock" do
nokogiri
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
it "errors when removing all platforms" do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
bundle "lock --remove-platform #{local_platform}", raise_on_error: false
expect(err).to include("Removing all platforms from the bundle is not allowed")
end
@@ -751,7 +1048,7 @@ RSpec.describe "bundle lock" do
build_repo4 do
build_gem "ffi", "1.9.14"
build_gem "ffi", "1.9.14" do |s|
- s.platform = x86_mingw32
+ s.platform = "x86-mingw32"
end
build_gem "gssapi", "0.1"
@@ -777,24 +1074,24 @@ RSpec.describe "bundle lock" do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "mixlib-shellout"
gem "gssapi"
G
- checksums = checksums_section_when_existing do |c|
- c.no_checksum "ffi", "1.9.14", "x86-mingw32"
- c.no_checksum "gssapi", "1.2.0"
- c.no_checksum "mixlib-shellout", "2.2.6", "universal-mingw32"
- c.no_checksum "win32-process", "0.8.3"
- end
+ simulate_platform("x86-mingw32") { bundle :lock }
- simulate_platform(x86_mingw32) { bundle :lock }
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "ffi", "1.9.14", "x86-mingw32"
+ c.checksum gem_repo4, "gssapi", "1.2.0"
+ c.checksum gem_repo4, "mixlib-shellout", "2.2.6", "universal-mingw32"
+ c.checksum gem_repo4, "win32-process", "0.8.3"
+ end
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
ffi (1.9.14-x86-mingw32)
gssapi (1.2.0)
@@ -812,18 +1109,18 @@ RSpec.describe "bundle lock" do
mixlib-shellout
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
bundle "config set --local force_ruby_platform true"
bundle :lock
- checksums.no_checksum "ffi", "1.9.14"
- checksums.no_checksum "mixlib-shellout", "2.2.6"
+ checksums.checksum gem_repo4, "ffi", "1.9.14"
+ checksums.checksum gem_repo4, "mixlib-shellout", "2.2.6"
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
ffi (1.9.14)
ffi (1.9.14-x86-mingw32)
@@ -844,7 +1141,7 @@ RSpec.describe "bundle lock" do
mixlib-shellout
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
@@ -861,14 +1158,14 @@ RSpec.describe "bundle lock" do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "libv8"
G
lockfile <<-G
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
libv8 (8.4.255.0)
libv8 (8.4.255.0-x86_64-darwin-19)
@@ -881,10 +1178,10 @@ RSpec.describe "bundle lock" do
libv8
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
- simulate_platform(Gem::Platform.new("x86_64-darwin-19")) { bundle "lock --update" }
+ simulate_platform("x86_64-darwin-19") { bundle "lock --update" }
expect(out).to match(/Writing lockfile to.+Gemfile\.lock/)
end
@@ -901,21 +1198,21 @@ RSpec.describe "bundle lock" do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "libv8"
G
- simulate_platform(Gem::Platform.new("x86_64-darwin-19")) { bundle "lock" }
+ simulate_platform("x86_64-darwin-19") { bundle "lock" }
- checksums = checksums_section_when_existing do |c|
- c.no_checksum "libv8", "8.4.255.0", "x86_64-darwin-19"
- c.no_checksum "libv8", "8.4.255.0", "x86_64-darwin-20"
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "libv8", "8.4.255.0", "x86_64-darwin-19"
+ c.checksum gem_repo4, "libv8", "8.4.255.0", "x86_64-darwin-20"
end
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
libv8 (8.4.255.0-x86_64-darwin-19)
libv8 (8.4.255.0-x86_64-darwin-20)
@@ -928,7 +1225,7 @@ RSpec.describe "bundle lock" do
libv8
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
@@ -943,20 +1240,20 @@ RSpec.describe "bundle lock" do
end
end
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo4, "libv8", "8.4.255.0", "x86_64-darwin-19"
c.checksum gem_repo4, "libv8", "8.4.255.0", "x86_64-darwin-20"
end
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "libv8"
G
lockfile <<-G
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
libv8 (8.4.255.0-x86_64-darwin-19)
libv8 (8.4.255.0-x86_64-darwin-20)
@@ -968,13 +1265,13 @@ RSpec.describe "bundle lock" do
libv8
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{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
+ simulate_platform(platform) do
bundle "lock"
expect(lockfile).to eq(previous_lockfile)
@@ -997,25 +1294,20 @@ RSpec.describe "bundle lock" do
end
build_gem "raygun-apm", "1.0.78" do |s|
- s.platform = "x64-mingw32"
- s.required_ruby_version = "< #{next_ruby_minor}.dev"
- end
-
- build_gem "raygun-apm", "1.0.78" do |s|
s.platform = "x64-mingw-ucrt"
s.required_ruby_version = "< #{next_ruby_minor}.dev"
end
end
gemfile <<-G
- source "https://localgemserver.test"
+ source "https://gem.repo4"
gem "raygun-apm"
G
lockfile <<-L
GEM
- remote: https://localgemserver.test/
+ remote: https://gem.repo4/
specs:
raygun-apm (1.0.78-universal-darwin)
@@ -1026,66 +1318,106 @@ RSpec.describe "bundle lock" do
raygun-apm
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
- bundle "lock --add-platform x86_64-linux", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ bundle "lock --add-platform x86_64-linux"
end
- it "does not crash on conflicting ruby requirements between platform versions in two different gems" do
+ it "adds platform specific gems as necessary, even when adding the current platform" do
build_repo4 do
- build_gem "unf_ext", "0.0.8.2"
+ build_gem "nokogiri", "1.16.0"
- build_gem "unf_ext", "0.0.8.2" do |s|
- s.required_ruby_version = [">= 2.4", "< #{previous_ruby_minor}"]
- s.platform = "x64-mingw32"
+ build_gem "nokogiri", "1.16.0" do |s|
+ s.platform = "x86_64-linux"
end
+ end
- build_gem "unf_ext", "0.0.8.2" do |s|
- s.required_ruby_version = [">= #{previous_ruby_minor}", "< #{current_ruby_minor}"]
- s.platform = "x64-mingw-ucrt"
- end
+ gemfile <<-G
+ source "https://gem.repo4"
- build_gem "google-protobuf", "3.21.12"
+ gem "nokogiri"
+ G
- build_gem "google-protobuf", "3.21.12" do |s|
- s.required_ruby_version = [">= 2.5", "< #{previous_ruby_minor}"]
- s.platform = "x64-mingw32"
- end
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.16.0)
- build_gem "google-protobuf", "3.21.12" do |s|
- s.required_ruby_version = [">= #{previous_ruby_minor}", "< #{current_ruby_minor}"]
- s.platform = "x64-mingw-ucrt"
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "x86_64-linux" do
+ bundle "lock --add-platform x86_64-linux"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.16.0)
+ nokogiri (1.16.0-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "refuses to add platforms incompatible with the lockfile" do
+ build_repo4 do
+ build_gem "sorbet-static", "0.5.11989" do |s|
+ s.platform = "x86_64-linux"
end
end
gemfile <<~G
source "https://gem.repo4"
- gem "google-protobuf"
- gem "unf_ext"
+ gem "sorbet-static"
G
lockfile <<~L
GEM
remote: https://gem.repo4/
specs:
- google-protobuf (3.21.12)
- unf_ext (0.0.8.2)
+ sorbet-static (0.5.11989-x86_64-linux)
PLATFORMS
- x64-mingw-ucrt
- x64-mingw32
+ x86_64-linux
DEPENDENCIES
- google-protobuf
- unf_ext
+ sorbet-static
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
- bundle "install --verbose", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s, "DEBUG_RESOLVER" => "1" }
+ simulate_platform "x86_64-linux" do
+ bundle "lock --add-platform ruby", raise_on_error: false
+ end
+
+ nice_error = <<~E.strip
+ Could not find gems matching 'sorbet-static' valid for all resolution platforms (x86_64-linux, ruby) in rubygems repository https://gem.repo4/ or installed locally.
+
+ The source contains the following gems matching 'sorbet-static':
+ * sorbet-static-0.5.11989-x86_64-linux
+ E
+ expect(err).to include(nice_error)
end
it "respects lower bound ruby requirements" do
@@ -1114,42 +1446,41 @@ RSpec.describe "bundle lock" do
our_private_gem
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "install", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
end
context "when an update is available" do
- let(:repo) do
- build_repo2 do
+ before do
+ gemfile_with_rails_weakling_and_foo_from_repo4
+
+ build_repo4 do
build_gem "foo", "2.0"
end
- gem_repo2
- end
- before do
- lockfile(@lockfile)
+ lockfile(expected_lockfile)
end
it "does not implicitly update" do
bundle "lock"
- checksums = checksums_section_when_existing do |c|
- c.checksum repo, "actionmailer", "2.3.2"
- c.checksum repo, "actionpack", "2.3.2"
- c.checksum repo, "activerecord", "2.3.2"
- c.checksum repo, "activeresource", "2.3.2"
- c.checksum repo, "activesupport", "2.3.2"
- c.checksum repo, "foo", "1.0"
- c.checksum repo, "rails", "2.3.2"
- c.checksum repo, "rake", rake_version
- c.checksum repo, "weakling", "0.0.3"
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "actionmailer", "2.3.2"
+ c.checksum gem_repo4, "actionpack", "2.3.2"
+ c.checksum gem_repo4, "activerecord", "2.3.2"
+ c.checksum gem_repo4, "activeresource", "2.3.2"
+ c.checksum gem_repo4, "activesupport", "2.3.2"
+ c.checksum gem_repo4, "foo", "1.0"
+ c.checksum gem_repo4, "rails", "2.3.2"
+ c.checksum gem_repo4, "rake", rake_version
+ c.checksum gem_repo4, "weakling", "0.0.3"
end
expected_lockfile = <<~L
GEM
- remote: #{file_uri_for(repo)}/
+ remote: https://gem.repo4/
specs:
actionmailer (2.3.2)
activesupport (= 2.3.2)
@@ -1179,7 +1510,7 @@ RSpec.describe "bundle lock" do
weakling
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
expect(read_lockfile).to eq(expected_lockfile)
@@ -1189,21 +1520,21 @@ RSpec.describe "bundle lock" do
gemfile gemfile.gsub('"foo"', '"foo", "2.0"')
bundle "lock"
- checksums = checksums_section_when_existing do |c|
- c.checksum repo, "actionmailer", "2.3.2"
- c.checksum repo, "actionpack", "2.3.2"
- c.checksum repo, "activerecord", "2.3.2"
- c.checksum repo, "activeresource", "2.3.2"
- c.checksum repo, "activesupport", "2.3.2"
- c.no_checksum "foo", "2.0"
- c.checksum repo, "rails", "2.3.2"
- c.checksum repo, "rake", rake_version
- c.checksum repo, "weakling", "0.0.3"
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "actionmailer", "2.3.2"
+ c.checksum gem_repo4, "actionpack", "2.3.2"
+ c.checksum gem_repo4, "activerecord", "2.3.2"
+ c.checksum gem_repo4, "activeresource", "2.3.2"
+ c.checksum gem_repo4, "activesupport", "2.3.2"
+ c.checksum gem_repo4, "foo", "2.0"
+ c.checksum gem_repo4, "rails", "2.3.2"
+ c.checksum gem_repo4, "rake", rake_version
+ c.checksum gem_repo4, "weakling", "0.0.3"
end
expected_lockfile = <<~L
GEM
- remote: #{file_uri_for(repo)}/
+ remote: https://gem.repo4/
specs:
actionmailer (2.3.2)
activesupport (= 2.3.2)
@@ -1233,7 +1564,7 @@ RSpec.describe "bundle lock" do
weakling
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
expect(read_lockfile).to eq(expected_lockfile)
@@ -1262,14 +1593,19 @@ RSpec.describe "bundle lock" do
it "respects the existing lockfile, even when reresolving" do
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "debug"
G
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "debug", "1.6.3"
+ c.checksum gem_repo4, "irb", "1.5.0"
+ end
+
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
debug (1.6.3)
irb (>= 1.3.6)
@@ -1280,23 +1616,18 @@ RSpec.describe "bundle lock" do
DEPENDENCIES
debug
- #{checksums_section}
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
simulate_platform "arm64-darwin-22" do
bundle "lock"
end
- checksums = checksums_section do |c|
- c.no_checksum "debug", "1.6.3"
- c.no_checksum "irb", "1.5.0"
- end
-
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
debug (1.6.3)
irb (>= 1.3.6)
@@ -1310,7 +1641,65 @@ RSpec.describe "bundle lock" do
debug
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ context "when a system gem has incorrect dependencies, different from remote gems" do
+ before do
+ build_repo4 do
+ build_gem "foo", "1.0.0" do |s|
+ s.add_dependency "bar"
+ end
+
+ build_gem "bar", "1.0.0"
+ end
+
+ system_gems "foo-1.0.0", gem_repo: gem_repo4, path: default_bundle_path
+
+ # simulate gemspec with wrong empty dependencies
+ foo_gemspec_path = default_bundle_path("specifications/foo-1.0.0.gemspec")
+ foo_gemspec = Gem::Specification.load(foo_gemspec_path.to_s)
+ foo_gemspec.dependencies.clear
+ File.write(foo_gemspec_path, foo_gemspec.to_ruby)
+ end
+
+ it "generates a lockfile using remote dependencies, and prints a warning" do
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "foo"
+ G
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "foo", "1.0.0"
+ c.checksum gem_repo4, "bar", "1.0.0"
+ end
+
+ simulate_platform "x86_64-linux" do
+ bundle "lock --verbose"
+ end
+
+ expect(err).to eq("Local specification for foo-1.0.0 has different dependencies than the remote gem, ignoring it")
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ bar (1.0.0)
+ foo (1.0.0)
+ bar
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ foo
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
L
end
end
@@ -1335,7 +1724,7 @@ RSpec.describe "bundle lock" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "rails", ">= 7.0.3.1"
gem "activeadmin", "2.13.1"
@@ -1349,7 +1738,7 @@ RSpec.describe "bundle lock" do
Because rails >= 7.0.4 depends on railties = 7.0.4
and rails < 7.0.4 depends on railties = 7.0.3.1,
railties = 7.0.3.1 OR = 7.0.4 is required.
- So, because railties = 7.0.3.1 OR = 7.0.4 could not be found in rubygems repository #{file_uri_for(gem_repo4)}/ or installed locally,
+ So, because railties = 7.0.3.1 OR = 7.0.4 could not be found in rubygems repository https://gem.repo4/ or installed locally,
version solving has failed.
ERR
end
@@ -1390,7 +1779,7 @@ RSpec.describe "bundle lock" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "rails", ">= 7.0.2.3"
gem "activeadmin", "= 2.13.1"
@@ -1398,7 +1787,7 @@ RSpec.describe "bundle lock" do
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
activeadmin (2.13.1)
ransack (= 3.1.0)
@@ -1413,57 +1802,37 @@ RSpec.describe "bundle lock" do
ransack (= 3.1.0)
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
- bundle "lock", raise_on_error: false
-
- expect(err).to eq <<~ERR.strip
+ expected_error = <<~ERR.strip
Could not find compatible versions
- Because every version of activemodel depends on activesupport = 6.0.4
- and rails >= 7.0.2.3, < 7.0.3.1 depends on activesupport = 7.0.2.3,
- every version of activemodel is incompatible with rails >= 7.0.2.3, < 7.0.3.1.
- And because rails >= 7.0.2.3, < 7.0.3.1 depends on activemodel = 7.0.2.3,
- rails >= 7.0.2.3, < 7.0.3.1 cannot be used.
- (1) So, because rails >= 7.0.3.1, < 7.0.4 depends on activemodel = 7.0.3.1
- and rails >= 7.0.4 depends on activemodel = 7.0.4,
- rails >= 7.0.2.3 requires activemodel = 7.0.3.1 OR = 7.0.4.
+ Because rails >= 7.0.4 depends on activemodel = 7.0.4
+ and rails >= 7.0.3.1, < 7.0.4 depends on activemodel = 7.0.3.1,
+ rails >= 7.0.3.1 requires activemodel = 7.0.3.1 OR = 7.0.4.
+ (1) So, because rails >= 7.0.2.3, < 7.0.3.1 depends on activemodel = 7.0.2.3
+ and every version of activemodel depends on activesupport = 6.0.4,
+ rails >= 7.0.2.3 requires activesupport = 6.0.4.
- Because rails >= 7.0.2.3, < 7.0.3.1 depends on activemodel = 7.0.2.3
+ Because rails >= 7.0.2.3, < 7.0.3.1 depends on activesupport = 7.0.2.3
and rails >= 7.0.3.1, < 7.0.4 depends on activesupport = 7.0.3.1,
- rails >= 7.0.2.3, < 7.0.4 requires activemodel = 7.0.2.3 or activesupport = 7.0.3.1.
- And because rails >= 7.0.4 depends on activesupport = 7.0.4
- and every version of activemodel depends on activesupport = 6.0.4,
- activemodel != 7.0.2.3 is incompatible with rails >= 7.0.2.3.
- And because rails >= 7.0.2.3 requires activemodel = 7.0.3.1 OR = 7.0.4 (1),
+ rails >= 7.0.2.3, < 7.0.4 requires activesupport = 7.0.2.3 OR = 7.0.3.1.
+ And because rails >= 7.0.4 depends on activesupport = 7.0.4,
+ rails >= 7.0.2.3 requires activesupport = 7.0.2.3 OR = 7.0.3.1 OR = 7.0.4.
+ And because rails >= 7.0.2.3 requires activesupport = 6.0.4 (1),
rails >= 7.0.2.3 cannot be used.
So, because Gemfile depends on rails >= 7.0.2.3,
version solving has failed.
ERR
- lockfile lockfile.gsub(/PLATFORMS\n #{local_platform}/m, "PLATFORMS\n #{lockfile_platforms("ruby")}")
-
bundle "lock", raise_on_error: false
+ expect(err).to eq(expected_error)
- expect(err).to eq <<~ERR.strip
- Could not find compatible versions
+ lockfile lockfile.gsub(/PLATFORMS\n #{local_platform}/m, "PLATFORMS\n #{lockfile_platforms("ruby")}")
- Because rails >= 7.0.3.1, < 7.0.4 depends on activemodel = 7.0.3.1
- and rails >= 7.0.2.3, < 7.0.3.1 depends on activemodel = 7.0.2.3,
- rails >= 7.0.2.3, < 7.0.4 requires activemodel = 7.0.2.3 OR = 7.0.3.1.
- And because every version of activemodel depends on activesupport = 6.0.4,
- rails >= 7.0.2.3, < 7.0.4 requires activesupport = 6.0.4.
- Because rails >= 7.0.3.1, < 7.0.4 depends on activesupport = 7.0.3.1
- and rails >= 7.0.2.3, < 7.0.3.1 depends on activesupport = 7.0.2.3,
- rails >= 7.0.2.3, < 7.0.4 requires activesupport = 7.0.2.3 OR = 7.0.3.1.
- Thus, rails >= 7.0.2.3, < 7.0.4 cannot be used.
- And because rails >= 7.0.4 depends on activemodel = 7.0.4,
- rails >= 7.0.2.3 requires activemodel = 7.0.4.
- So, because activemodel = 7.0.4 could not be found in rubygems repository #{file_uri_for(gem_repo4)}/ or installed locally
- and Gemfile depends on rails >= 7.0.2.3,
- version solving has failed.
- ERR
+ bundle "lock", raise_on_error: false
+ expect(err).to eq(expected_error)
end
it "does not accidentally resolves to prereleases" do
@@ -1483,7 +1852,7 @@ RSpec.describe "bundle lock" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "autoproj", ">= 2.0.0"
G
@@ -1508,7 +1877,7 @@ RSpec.describe "bundle lock" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "rails"
G
@@ -1531,7 +1900,7 @@ RSpec.describe "bundle lock" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "activerecord", "6.0.6"
gem "activerecord-jdbc-adapter", "61.0"
G
@@ -1544,6 +1913,408 @@ RSpec.describe "bundle lock" do
expect(err).not_to include("ERROR REPORT TEMPLATE")
end
+ it "adds checksums to an existing lockfile, when re-resolving is necessary" do
+ build_repo4 do
+ build_gem "nokogiri", "1.14.2"
+ build_gem "nokogiri", "1.14.2" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ G
+
+ # lockfile has a typo (nogokiri) in the dependencies section, so Bundler
+ # sees dependencies have changed, and re-resolves
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.2)
+ nokogiri (1.14.2-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nogokiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "x86_64-linux" do
+ bundle "lock --add-checksums"
+ end
+
+ checksums = checksums_section do |c|
+ c.checksum gem_repo4, "nokogiri", "1.14.2"
+ c.checksum gem_repo4, "nokogiri", "1.14.2", "x86_64-linux"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.2)
+ nokogiri (1.14.2-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "adds checksums to an existing lockfile, when no re-resolve is necessary" do
+ build_repo4 do
+ build_gem "nokogiri", "1.14.2"
+ build_gem "nokogiri", "1.14.2" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.2)
+ nokogiri (1.14.2-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "x86_64-linux" do
+ bundle "lock --add-checksums"
+ end
+
+ checksums = checksums_section do |c|
+ c.checksum gem_repo4, "nokogiri", "1.14.2"
+ c.checksum gem_repo4, "nokogiri", "1.14.2", "x86_64-linux"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.2)
+ nokogiri (1.14.2-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "adds checksums when source is not specified" do
+ system_gems(%w[myrack-1.0.0], path: default_bundle_path)
+
+ gemfile <<-G
+ gem "myrack"
+ G
+
+ lockfile <<~L
+ GEM
+ specs:
+ myrack (1.0.0)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ myrack
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "x86_64-linux" do
+ bundle "lock --add-checksums"
+ end
+
+ # myrack is coming from gem_repo1
+ # but it's simulated to install in the system gems path
+ checksums = checksums_section do |c|
+ c.checksum gem_repo1, "myrack", "1.0.0"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ specs:
+ myrack (1.0.0)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ myrack
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "adds checksums to an existing lockfile, when gems are already installed" do
+ build_repo4 do
+ build_gem "nokogiri", "1.14.2"
+ build_gem "nokogiri", "1.14.2" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.2)
+ nokogiri (1.14.2-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "x86_64-linux" do
+ bundle "install"
+
+ bundle "lock --add-checksums"
+ end
+
+ checksums = checksums_section do |c|
+ c.checksum gem_repo4, "nokogiri", "1.14.2"
+ c.checksum gem_repo4, "nokogiri", "1.14.2", "x86_64-linux"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.2)
+ nokogiri (1.14.2-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "generates checksums by default" do
+ build_repo4 do
+ build_gem "nokogiri", "1.14.2"
+ build_gem "nokogiri", "1.14.2" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ simulate_platform "x86_64-linux" do
+ install_gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ G
+ end
+
+ checksums = checksums_section do |c|
+ c.checksum gem_repo4, "nokogiri", "1.14.2"
+ c.checksum gem_repo4, "nokogiri", "1.14.2", "x86_64-linux"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.2)
+ nokogiri (1.14.2-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "disables checksums if configured to do so" do
+ build_repo4 do
+ build_gem "nokogiri", "1.14.2"
+ build_gem "nokogiri", "1.14.2" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ bundle "config lockfile_checksums false"
+
+ simulate_platform "x86_64-linux" do
+ install_gemfile <<-G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ G
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.2)
+ nokogiri (1.14.2-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "add checksums for gems installed on disk" do
+ build_repo4 do
+ build_gem "warning", "18.0.0"
+ end
+
+ bundle "config lockfile_checksums false"
+
+ simulate_platform "x86_64-linux" do
+ install_gemfile(<<-G, artifice: "endpoint")
+ source "https://gem.repo4"
+
+ gem "warning"
+ G
+
+ bundle "config --delete lockfile_checksums"
+ bundle("lock --add-checksums", artifice: "endpoint")
+ end
+
+ checksums = checksums_section do |c|
+ c.checksum gem_repo4, "warning", "18.0.0"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ warning (18.0.0)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ warning
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "doesn't add checksum for gems not installed on disk" do
+ lockfile(<<~L)
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ warning (18.0.0)
+
+ PLATFORMS
+ #{local_platform}
+
+ DEPENDENCIES
+ warning
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ gemfile(<<~G)
+ source "https://gem.repo4"
+
+ gem "warning"
+ G
+
+ build_repo4 do
+ build_gem "warning", "18.0.0"
+ end
+
+ FileUtils.rm_rf("#{gem_repo4}/gems")
+
+ bundle("lock --add-checksums", artifice: "endpoint")
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ warning (18.0.0)
+
+ PLATFORMS
+ #{local_platform}
+
+ DEPENDENCIES
+ warning
+
+ CHECKSUMS
+ warning (18.0.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
context "when re-resolving to include prereleases" do
before do
build_repo4 do
@@ -1557,7 +2328,7 @@ RSpec.describe "bundle lock" do
it "does not end up including gems scoped to other platforms in the lockfile" do
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "rails"
gem "tzinfo-data", platform: :windows
G
@@ -1584,15 +2355,16 @@ RSpec.describe "bundle lock" do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gemspec
G
end
- it "locks ruby specs" do
- checksums = checksums_section_when_existing do |c|
+ it "locks both ruby and platform specific specs" do
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "foo", "1.0"
- c.no_checksum "nokogiri", "1.14.2"
+ c.checksum gem_repo4, "nokogiri", "1.14.2"
+ c.checksum gem_repo4, "nokogiri", "1.14.2", "x86_64-linux"
end
simulate_platform "x86_64-linux" do
@@ -1607,20 +2379,88 @@ RSpec.describe "bundle lock" do
nokogiri
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
nokogiri (1.14.2)
+ nokogiri (1.14.2-x86_64-linux)
PLATFORMS
- #{lockfile_platforms}
+ ruby
+ x86_64-linux
DEPENDENCIES
foo!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
+
+ context "and a lockfile with platform specific gems only already exists" do
+ before do
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ c.checksum gem_repo4, "nokogiri", "1.14.2", "x86_64-linux"
+ end
+
+ lockfile <<~L
+ PATH
+ remote: .
+ specs:
+ foo (1.0)
+ nokogiri
+
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.2-x86_64-linux)
+
+ PLATFORMS
+ x86_64-linux
+
+ DEPENDENCIES
+ foo!
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "keeps platform specific gems" do
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ c.checksum gem_repo4, "nokogiri", "1.14.2"
+ c.checksum gem_repo4, "nokogiri", "1.14.2", "x86_64-linux"
+ end
+
+ simulate_platform "x86_64-linux" do
+ bundle "install"
+ end
+
+ expect(lockfile).to eq <<~L
+ PATH
+ remote: .
+ specs:
+ foo (1.0)
+ nokogiri
+
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.14.2)
+ nokogiri (1.14.2-x86_64-linux)
+
+ PLATFORMS
+ x86_64-linux
+
+ DEPENDENCIES
+ foo!
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
end
context "when adding a new gem that requires unlocking other transitive deps" do
@@ -1644,7 +2484,7 @@ RSpec.describe "bundle lock" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "govuk_app_config"
gem "activesupport", "7.0.4.3"
@@ -1655,7 +2495,7 @@ RSpec.describe "bundle lock" do
# version
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
actionpack (7.0.4.1)
activesupport (7.0.4.1)
@@ -1672,12 +2512,12 @@ RSpec.describe "bundle lock" do
govuk_app_config
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
it "does not downgrade top level dependencies" do
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "actionpack", "7.0.4.3"
c.no_checksum "activesupport", "7.0.4.3"
c.no_checksum "govuk_app_config", "4.13.0"
@@ -1690,7 +2530,7 @@ RSpec.describe "bundle lock" do
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
actionpack (7.0.4.3)
activesupport (7.0.4.3)
@@ -1708,8 +2548,329 @@ RSpec.describe "bundle lock" do
govuk_app_config
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ context "when lockfile has incorrectly indented platforms" do
+ before do
+ build_repo4 do
+ build_gem "ffi", "1.1.0" do |s|
+ s.platform = "x86_64-linux"
+ end
+
+ build_gem "ffi", "1.1.0" do |s|
+ s.platform = "arm64-darwin"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "ffi"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ ffi (1.1.0-arm64-darwin)
+
+ PLATFORMS
+ arm64-darwin
+
+ DEPENDENCIES
+ ffi
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "does not remove any gems" do
+ simulate_platform "x86_64-linux" do
+ bundle "lock --update"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ ffi (1.1.0-arm64-darwin)
+ ffi (1.1.0-x86_64-linux)
+
+ PLATFORMS
+ arm64-darwin
+ x86_64-linux
+
+ DEPENDENCIES
+ ffi
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ describe "--normalize-platforms on linux" do
+ let(:normalized_lockfile) do
+ <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ irb (1.0.0)
+ irb (1.0.0-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ irb
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ before do
+ build_repo4 do
+ build_gem "irb", "1.0.0"
+
+ build_gem "irb", "1.0.0" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "irb"
+ G
+ end
+
+ context "when already normalized" do
+ before do
+ lockfile normalized_lockfile
+ end
+
+ it "is a noop" do
+ simulate_platform "x86_64-linux" do
+ bundle "lock --normalize-platforms"
+ end
+
+ expect(lockfile).to eq(normalized_lockfile)
+ end
+ end
+
+ context "when not already normalized" do
+ before do
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ irb (1.0.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ irb
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "normalizes the list of platforms and native gems in the lockfile" do
+ simulate_platform "x86_64-linux" do
+ bundle "lock --normalize-platforms"
+ end
+
+ expect(lockfile).to eq(normalized_lockfile)
+ end
+ end
+ end
+
+ describe "--normalize-platforms on darwin" do
+ let(:normalized_lockfile) do
+ <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ irb (1.0.0)
+ irb (1.0.0-arm64-darwin)
+
+ PLATFORMS
+ arm64-darwin
+ ruby
+
+ DEPENDENCIES
+ irb
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
L
end
+
+ before do
+ build_repo4 do
+ build_gem "irb", "1.0.0"
+
+ build_gem "irb", "1.0.0" do |s|
+ s.platform = "arm64-darwin"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "irb"
+ G
+ end
+
+ context "when already normalized" do
+ before do
+ lockfile normalized_lockfile
+ end
+
+ it "is a noop" do
+ simulate_platform "arm64-darwin-23" do
+ bundle "lock --normalize-platforms"
+ end
+
+ expect(lockfile).to eq(normalized_lockfile)
+ end
+ end
+
+ context "when having only ruby" do
+ before do
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ irb (1.0.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ irb
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "normalizes the list of platforms and native gems in the lockfile" do
+ simulate_platform "arm64-darwin-23" do
+ bundle "lock --normalize-platforms"
+ end
+
+ expect(lockfile).to eq(normalized_lockfile)
+ end
+ end
+
+ context "when having only the current platform with version" do
+ before do
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ irb (1.0.0-arm64-darwin)
+
+ PLATFORMS
+ arm64-darwin-23
+
+ DEPENDENCIES
+ irb
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "normalizes the list of platforms by removing version" do
+ simulate_platform "arm64-darwin-23" do
+ bundle "lock --normalize-platforms"
+ end
+
+ expect(lockfile).to eq(normalized_lockfile)
+ end
+ end
+
+ context "when having other platforms with version" do
+ before do
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ irb (1.0.0-arm64-darwin)
+
+ PLATFORMS
+ arm64-darwin-22
+
+ DEPENDENCIES
+ irb
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "normalizes the list of platforms by removing version" do
+ simulate_platform "arm64-darwin-23" do
+ bundle "lock --normalize-platforms"
+ end
+
+ expect(lockfile).to eq(normalized_lockfile)
+ end
+ end
+ end
+
+ describe "--normalize-platforms with gems without generic variant" do
+ let(:original_lockfile) do
+ <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ sorbet-static (1.0-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ sorbet-static
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ before do
+ build_repo4 do
+ build_gem "sorbet-static" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "sorbet-static"
+ G
+
+ lockfile original_lockfile
+ end
+
+ it "removes invalid platforms" do
+ simulate_platform "x86_64-linux" do
+ bundle "lock --normalize-platforms"
+ end
+
+ expect(lockfile).to eq(original_lockfile.gsub(/^ ruby\n/m, ""))
+ end
end
end
diff --git a/spec/bundler/commands/newgem_spec.rb b/spec/bundler/commands/newgem_spec.rb
index 53d0f9d6eb..06c226f9e5 100644
--- a/spec/bundler/commands/newgem_spec.rb
+++ b/spec/bundler/commands/newgem_spec.rb
@@ -6,39 +6,49 @@ RSpec.describe "bundle gem" do
expect(bundled_app("#{gem_name}/README.md")).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}/lib/#{gem_name}.rb")).to exist
+ expect(bundled_app("#{gem_name}/lib/#{gem_name}/version.rb")).to exist
+
+ expect(ignore_paths).to include("bin/")
+ expect(ignore_paths).to include("Gemfile")
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 "config set path #{rubocop_gem_path}", 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 "config set path #{standard_gem_path}", 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" }
+ def ignore_paths
+ generated = bundled_app("#{gem_name}/#{gem_name}.gemspec").read
+ matched = generated.match(/^\s+f\.start_with\?\(\*%w\[(?<ignored>.*)\]\)$/)
+ matched[:ignored]&.split(" ")
+ end
- let(:require_path) { "mygem" }
+ def installed_go?
+ sys_exec("go version", raise_on_error: true)
+ true
+ rescue StandardError
+ false
+ end
- let(:minitest_test_file_path) { "test/test_mygem.rb" }
+ let(:generated_gemspec) { Bundler.load_gemspec_uncached(bundled_app(gem_name).join("#{gem_name}.gemspec")) }
- let(:minitest_test_class_name) { "class TestMygem < Minitest::Test" }
+ let(:gem_name) { "mygem" }
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")
+ git("config --global user.name 'Bundler User'")
+ git("config --global user.email user@example.com")
+ git("config --global github.user bundleuser")
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__CI" => "false", "BUNDLE_GEM__CHANGELOG" => "false", "BUNDLE_GEM__BUNDLE" => "false"
end
describe "git repo initialization" do
@@ -109,7 +119,7 @@ RSpec.describe "bundle gem" do
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")
+ git("config --global init.defaultBranch main")
bundle "gem #{gem_name} --coc"
expect(bundled_app("#{gem_name}/README.md").read).to include("## Code of Conduct")
@@ -152,64 +162,23 @@ RSpec.describe "bundle gem" do
end
end
- shared_examples_for "--rubocop flag" do
- context "is deprecated", bundler: "< 3" do
- before do
- global_config "BUNDLE_GEM__LINTER" => nil
- 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
+ shared_examples_for "--bundle flag" do
+ before do
+ bundle "gem #{gem_name} --bundle"
+ end
+ it "generates a gem skeleton with bundle install" do
+ gem_skeleton_assertions
+ expect(out).to include("Running bundle install in the new gem directory.")
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
+ shared_examples_for "--no-bundle flag" do
+ before do
+ bundle "gem #{gem_name} --no-bundle"
+ end
+ it "generates a gem skeleton without bundle install" do
+ gem_skeleton_assertions
+ expect(out).to_not include("Running bundle install in the new gem directory.")
end
end
@@ -220,7 +189,7 @@ RSpec.describe "bundle gem" do
it "generates a gem skeleton with rubocop" do
gem_skeleton_assertions
- expect(bundled_app("test-gem/Rakefile")).to read_as(
+ expect(bundled_app("#{gem_name}/Rakefile")).to read_as(
include("# frozen_string_literal: true").
and(include('require "rubocop/rake_task"').
and(include("RuboCop::RakeTask.new").
@@ -240,6 +209,10 @@ RSpec.describe "bundle gem" do
it "generates a default .rubocop.yml" do
expect(bundled_app("#{gem_name}/.rubocop.yml")).to exist
end
+
+ it "includes .rubocop.yml into ignore list" do
+ expect(ignore_paths).to include(".rubocop.yml")
+ end
end
shared_examples_for "--linter=standard flag" do
@@ -249,7 +222,7 @@ RSpec.describe "bundle gem" do
it "generates a gem skeleton with standard" do
gem_skeleton_assertions
- expect(bundled_app("test-gem/Rakefile")).to read_as(
+ expect(bundled_app("#{gem_name}/Rakefile")).to read_as(
include('require "standard/rake"').
and(match(/default:.+:standard/))
)
@@ -267,19 +240,23 @@ RSpec.describe "bundle gem" do
it "generates a default .standard.yml" do
expect(bundled_app("#{gem_name}/.standard.yml")).to exist
end
+
+ it "includes .standard.yml into ignore list" do
+ expect(ignore_paths).to include(".standard.yml")
+ end
end
- shared_examples_for "--linter=none flag" do
+ shared_examples_for "--no-linter flag" do
define_negated_matcher :exclude, :include
before do
- bundle "gem #{gem_name} --linter=none"
+ bundle "gem #{gem_name} --no-linter"
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"))
+ expect(bundled_app("#{gem_name}/Rakefile")).to read_as(exclude("rubocop"))
+ expect(bundled_app("#{gem_name}/#{gem_name}.gemspec")).to read_as(exclude("rubocop"))
end
it "does not include rubocop in generated Gemfile" do
@@ -304,9 +281,17 @@ RSpec.describe "bundle gem" do
expect(bundled_app("#{gem_name}/.rubocop.yml")).to_not exist
end
+ it "does not add .rubocop.yml into ignore list" do
+ expect(ignore_paths).not_to include(".rubocop.yml")
+ end
+
it "doesn't generate a default .standard.yml" do
expect(bundled_app("#{gem_name}/.standard.yml")).to_not exist
end
+
+ it "does not add .standard.yml into ignore list" do
+ expect(ignore_paths).not_to include(".standard.yml")
+ end
end
it "has no rubocop offenses when using --linter=rubocop flag" do
@@ -353,7 +338,6 @@ RSpec.describe "bundle gem" do
it "has no rubocop offenses when using --ext=rust and --linter=rubocop flag" do
skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
- skip "RubyGems incompatible with Rust builder" if ::Gem::Version.new("3.3.11") > ::Gem.rubygems_version
bundle "gem #{gem_name} --ext=rust --linter=rubocop"
bundle_exec_rubocop
@@ -362,7 +346,6 @@ RSpec.describe "bundle gem" do
it "has no rubocop offenses when using --ext=rust, --test=minitest, and --linter=rubocop flag" do
skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
- skip "RubyGems incompatible with Rust builder" if ::Gem::Version.new("3.3.11") > ::Gem.rubygems_version
bundle "gem #{gem_name} --ext=rust --test=minitest --linter=rubocop"
bundle_exec_rubocop
@@ -371,7 +354,6 @@ RSpec.describe "bundle gem" do
it "has no rubocop offenses when using --ext=rust, --test=rspec, and --linter=rubocop flag" do
skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
- skip "RubyGems incompatible with Rust builder" if ::Gem::Version.new("3.3.11") > ::Gem.rubygems_version
bundle "gem #{gem_name} --ext=rust --test=rspec --linter=rubocop"
bundle_exec_rubocop
@@ -380,7 +362,6 @@ RSpec.describe "bundle gem" do
it "has no rubocop offenses when using --ext=rust, --test=test-unit, and --linter=rubocop flag" do
skip "ruby_core has an 'ast.rb' file that gets in the middle and breaks this spec" if ruby_core?
- skip "RubyGems incompatible with Rust builder" if ::Gem::Version.new("3.3.11") > ::Gem.rubygems_version
bundle "gem #{gem_name} --ext=rust --test=test-unit --linter=rubocop"
bundle_exec_rubocop
@@ -398,11 +379,17 @@ RSpec.describe "bundle gem" 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/#{gem_name}_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/#{gem_name}.rb")).to_not exist
expect(bundled_app("#{gem_name}/test/test_helper.rb")).to_not exist
end
+
+ it "does not add any test framework files into ignore list" do
+ expect(ignore_paths).not_to include("test/")
+ expect(ignore_paths).not_to include(".rspec")
+ expect(ignore_paths).not_to include("spec/")
+ end
end
context "README.md" do
@@ -419,7 +406,7 @@ RSpec.describe "bundle gem" do
context "git config github.user is absent" do
before do
- sys_exec("git config --global --unset github.user")
+ git("config --global --unset github.user")
bundle "gem #{gem_name}"
end
@@ -428,6 +415,22 @@ RSpec.describe "bundle gem" do
expect(bundled_app("#{gem_name}/README.md").read).not_to include("github.com/bundleuser")
end
end
+
+ describe "test task name on readme" do
+ shared_examples_for "test task name on readme" do |framework, task_name|
+ before do
+ bundle "gem #{gem_name} --test=#{framework}"
+ end
+
+ it "renders with correct name" do
+ expect(bundled_app("#{gem_name}/README.md").read).to include("Then, run `rake #{task_name}` to run the tests.")
+ end
+ end
+
+ it_behaves_like "test task name on readme", "test-unit", "test"
+ it_behaves_like "test task name on readme", "minitest", "test"
+ it_behaves_like "test task name on readme", "rspec", "spec"
+ end
end
it "creates a new git repository" do
@@ -438,10 +441,7 @@ RSpec.describe "bundle gem" do
context "when git is not available" 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}", env: { "PATH" => "" }
+ bundle "gem #{gem_name}", env: { "PATH" => "" }
end
it "creates the gem without the need for git" do
@@ -455,19 +455,25 @@ RSpec.describe "bundle gem" do
it "doesn't create a .gitignore file" do
expect(bundled_app("#{gem_name}/.gitignore")).to_not exist
end
+
+ it "does not add .gitignore into ignore list" do
+ expect(ignore_paths).not_to include(".gitignore")
+ end
end
- it "generates a valid gemspec", :ruby_repo do
+ it "generates a valid gemspec" do
bundle "gem newgem --bin"
prepare_gemspec(bundled_app("newgem", "newgem.gemspec"))
- gems = ["rake-#{rake_version}"]
- path = Bundler.feature_flag.default_install_uses_path? ? local_gem_path(base: bundled_app("newgem")) : system_gem_path
- system_gems gems, path: path
+ build_repo2 do
+ build_dummy_irb "9.9.9"
+ end
+ gems = ["rake-#{rake_version}", "irb-9.9.9"]
+ system_gems gems, path: system_gem_path, gem_repo: gem_repo2
bundle "exec rake build", dir: bundled_app("newgem")
- expect(last_command.stdboth).not_to include("ERROR")
+ expect(stdboth).not_to include("ERROR")
end
context "gem naming with relative paths" do
@@ -549,820 +555,1096 @@ RSpec.describe "bundle gem" do
end
end
- shared_examples_for "generating a gem" do
- it "generates a gem skeleton" do
- 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
+ it "generates a gem skeleton" do
+ bundle "gem #{gem_name}"
- expect(bundled_app("#{gem_name}/bin/setup")).to exist
- expect(bundled_app("#{gem_name}/bin/console")).to exist
+ 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/#{gem_name}.rb")).to exist
+ expect(bundled_app("#{gem_name}/lib/#{gem_name}/version.rb")).to exist
+ expect(bundled_app("#{gem_name}/sig/#{gem_name}.rbs")).to exist
+ expect(bundled_app("#{gem_name}/.gitignore")).to exist
- unless Gem.win_platform?
- expect(bundled_app("#{gem_name}/bin/setup")).to be_executable
- expect(bundled_app("#{gem_name}/bin/console")).to be_executable
- end
+ 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").read).to start_with("#!")
- expect(bundled_app("#{gem_name}/bin/console").read).to start_with("#!")
+ unless Gem.win_platform?
+ expect(bundled_app("#{gem_name}/bin/setup")).to be_executable
+ expect(bundled_app("#{gem_name}/bin/console")).to be_executable
end
- it "starts with version 0.1.0" do
+ expect(bundled_app("#{gem_name}/bin/setup").read).to start_with("#!")
+ expect(bundled_app("#{gem_name}/bin/console").read).to start_with("#!")
+ end
+
+ it "includes bin/ into ignore list" do
+ bundle "gem #{gem_name}"
+
+ expect(ignore_paths).to include("bin/")
+ end
+
+ it "includes Gemfile into ignore list" do
+ bundle "gem #{gem_name}"
+
+ expect(ignore_paths).to include("Gemfile")
+ end
+
+ it "includes .gitignore into ignore list" do
+ bundle "gem #{gem_name}"
+
+ expect(ignore_paths).to include(".gitignore")
+ end
+
+ it "starts with version 0.1.0" do
+ bundle "gem #{gem_name}"
+
+ expect(bundled_app("#{gem_name}/lib/#{gem_name}/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/#{gem_name}.rbs").read).to match(/VERSION: String/)
+ end
+
+ context "git config user.{name,email} is set" do
+ before do
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
- expect(bundled_app("#{gem_name}/lib/#{require_path}/version.rb").read).to match(/VERSION = "0.1.0"/)
+ it "sets gemspec email to git user.email if available" do
+ expect(generated_gemspec.email.first).to eq("user@example.com")
end
+ end
- it "declare String type for VERSION constant" do
+ context "git config user.{name,email} is not set" do
+ before do
+ git("config --global --unset user.name")
+ git("config --global --unset user.email")
bundle "gem #{gem_name}"
+ end
- expect(bundled_app("#{gem_name}/sig/#{require_path}.rbs").read).to match(/VERSION: String/)
+ 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
- context "git config user.{name,email} is set" do
- before do
- bundle "gem #{gem_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 author to git user.name if available" do
- expect(generated_gemspec.authors.first).to eq("Bundler User")
- end
+ it "sets gemspec metadata['allowed_push_host']" do
+ bundle "gem #{gem_name}"
+
+ expect(generated_gemspec.metadata["allowed_push_host"]).
+ to match(/example\.com/)
+ end
- it "sets gemspec email to git user.email if available" do
- expect(generated_gemspec.email.first).to eq("user@example.com")
+ it "sets a minimum ruby version" do
+ bundle "gem #{gem_name}"
+
+ expect(generated_gemspec.required_ruby_version.to_s).to start_with(">=")
+ end
+
+ it "does not include the gemspec file in files" do
+ bundle "gem #{gem_name}"
+
+ bundler_gemspec = Bundler::GemHelper.new(bundled_app(gem_name), gem_name).gemspec
+
+ expect(bundler_gemspec.files).not_to include("#{gem_name}.gemspec")
+ end
+
+ it "does not include the Gemfile file in files" do
+ bundle "gem #{gem_name}"
+
+ bundler_gemspec = Bundler::GemHelper.new(bundled_app(gem_name), gem_name).gemspec
+
+ expect(bundler_gemspec.files).not_to include("Gemfile")
+ end
+
+ it "runs rake without problems" do
+ bundle "gem #{gem_name}"
+
+ system_gems ["rake-#{rake_version}"]
+
+ rakefile = <<~RAKEFILE
+ task :default do
+ puts 'SUCCESS'
end
+ RAKEFILE
+ File.open(bundled_app("#{gem_name}/Rakefile"), "w") do |file|
+ file.puts rakefile
end
- context "git config user.{name,email} is not set" do
- before do
- sys_exec("git config --global --unset user.name")
- sys_exec("git config --global --unset user.email")
- bundle "gem #{gem_name}"
- end
+ sys_exec("rake", dir: bundled_app(gem_name))
+ expect(out).to include("SUCCESS")
+ end
- 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
+ context "--exe parameter set" do
+ before do
+ bundle "gem #{gem_name} --exe"
+ 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")
+ it "builds exe skeleton" do
+ expect(bundled_app("#{gem_name}/exe/#{gem_name}")).to exist
+ unless Gem.win_platform?
+ expect(bundled_app("#{gem_name}/exe/#{gem_name}")).to be_executable
end
end
+ end
- it "sets gemspec metadata['allowed_push_host']" do
- bundle "gem #{gem_name}"
+ context "--bin parameter set" do
+ before do
+ bundle "gem #{gem_name} --bin"
+ end
- expect(generated_gemspec.metadata["allowed_push_host"]).
- to match(/example\.com/)
+ it "builds exe skeleton" do
+ expect(bundled_app("#{gem_name}/exe/#{gem_name}")).to exist
end
+ end
- it "sets a minimum ruby version" do
+ context "no --test parameter" do
+ before do
bundle "gem #{gem_name}"
+ end
+
+ it_behaves_like "test framework is absent"
+ end
- expect(generated_gemspec.required_ruby_version.to_s).to start_with(">=")
+ context "--test parameter set to rspec" do
+ before do
+ bundle "gem #{gem_name} --test=rspec"
end
- it "requires the version file" do
- bundle "gem #{gem_name}"
+ it "builds spec skeleton" do
+ expect(bundled_app("#{gem_name}/.rspec")).to exist
+ expect(bundled_app("#{gem_name}/spec/#{gem_name}_spec.rb")).to exist
+ expect(bundled_app("#{gem_name}/spec/spec_helper.rb")).to exist
+ end
- expect(bundled_app("#{gem_name}/lib/#{require_path}.rb").read).to match(%r{require_relative "#{require_relative_path}/version"})
+ it "includes .rspec and spec/ into ignore list" do
+ expect(ignore_paths).to include(".rspec")
+ expect(ignore_paths).to include("spec/")
end
- it "creates a base error class" do
+ it "depends on a specific version of rspec 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
+ rspec_dep = builder.dependencies.find {|d| d.name == "rspec" }
+ expect(rspec_dep).to be_specific
+ end
+ end
+
+ context "init_gems_rb setting to true" do
+ before do
+ bundle "config set init_gems_rb true"
bundle "gem #{gem_name}"
+ end
- expect(bundled_app("#{gem_name}/lib/#{require_path}.rb").read).to match(/class Error < StandardError; end$/)
+ it "generates gems.rb instead of Gemfile" do
+ expect(bundled_app("#{gem_name}/gems.rb")).to exist
+ expect(bundled_app("#{gem_name}/Gemfile")).to_not exist
end
- it "does not include the gemspec file in files" do
+ it "includes gems.rb and gems.locked into ignore list" do
+ expect(ignore_paths).to include("gems.rb")
+ expect(ignore_paths).to include("gems.locked")
+ expect(ignore_paths).not_to include("Gemfile")
+ end
+ end
+
+ context "init_gems_rb setting to false" do
+ before do
+ bundle "config set init_gems_rb false"
bundle "gem #{gem_name}"
+ end
- bundler_gemspec = Bundler::GemHelper.new(bundled_app(gem_name), gem_name).gemspec
+ it "generates Gemfile instead of gems.rb" do
+ expect(bundled_app("#{gem_name}/gems.rb")).to_not exist
+ expect(bundled_app("#{gem_name}/Gemfile")).to exist
+ end
- expect(bundler_gemspec.files).not_to include("#{gem_name}.gemspec")
+ it "includes Gemfile into ignore list" do
+ expect(ignore_paths).to include("Gemfile")
+ expect(ignore_paths).not_to include("gems.rb")
+ expect(ignore_paths).not_to include("gems.locked")
end
+ end
- it "does not include the Gemfile file in files" do
+ context "gem.test setting set to rspec" do
+ before do
+ bundle "config set gem.test rspec"
bundle "gem #{gem_name}"
+ end
- bundler_gemspec = Bundler::GemHelper.new(bundled_app(gem_name), gem_name).gemspec
+ it "builds spec skeleton" do
+ expect(bundled_app("#{gem_name}/.rspec")).to exist
+ expect(bundled_app("#{gem_name}/spec/#{gem_name}_spec.rb")).to exist
+ expect(bundled_app("#{gem_name}/spec/spec_helper.rb")).to exist
+ end
- expect(bundler_gemspec.files).not_to include("Gemfile")
+ it "includes .rspec and spec/ into ignore list" do
+ expect(ignore_paths).to include(".rspec")
+ expect(ignore_paths).to include("spec/")
end
+ end
- it "runs rake without problems" do
- bundle "gem #{gem_name}"
+ context "gem.test setting set to rspec and --test is set to minitest" do
+ before do
+ bundle "config set gem.test rspec"
+ bundle "gem #{gem_name} --test=minitest"
+ end
+
+ it "builds spec skeleton" do
+ expect(bundled_app("#{gem_name}/test/test_#{gem_name}.rb")).to exist
+ expect(bundled_app("#{gem_name}/test/test_helper.rb")).to exist
+ end
+
+ it "includes test/ into ignore list" do
+ expect(ignore_paths).to include("test/")
+ end
+ end
- system_gems ["rake-#{rake_version}"]
+ context "--test parameter set to minitest" do
+ before do
+ bundle "gem #{gem_name} --test=minitest"
+ end
+ it "depends on a specific version of minitest" 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
+ 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/test_#{gem_name}.rb")).to exist
+ expect(bundled_app("#{gem_name}/test/test_helper.rb")).to exist
+ end
+
+ it "includes test/ into ignore list" do
+ expect(ignore_paths).to include("test/")
+ end
+
+ it "creates a default rake task to run the test suite" do
rakefile = <<~RAKEFILE
- task :default do
- puts 'SUCCESS'
- end
+ # frozen_string_literal: true
+
+ require "bundler/gem_tasks"
+ require "minitest/test_task"
+
+ Minitest::TestTask.create
+
+ task default: :test
RAKEFILE
- File.open(bundled_app("#{gem_name}/Rakefile"), "w") do |file|
- file.puts rakefile
- end
- sys_exec(rake, dir: bundled_app(gem_name))
- expect(out).to include("SUCCESS")
+ expect(bundled_app("#{gem_name}/Rakefile").read).to eq(rakefile)
end
+ end
- context "--exe parameter set" do
- before do
- bundle "gem #{gem_name} --exe"
- end
+ context "gem.test setting set to minitest" do
+ before do
+ bundle "config set gem.test minitest"
+ bundle "gem #{gem_name}"
+ end
- it "builds exe skeleton" do
- expect(bundled_app("#{gem_name}/exe/#{gem_name}")).to exist
- end
+ it "creates a default rake task to run the test suite" do
+ rakefile = <<~RAKEFILE
+ # frozen_string_literal: true
- it "requires the main file" do
- expect(bundled_app("#{gem_name}/exe/#{gem_name}").read).to match(/require "#{require_path}"/)
- end
- end
+ require "bundler/gem_tasks"
+ require "minitest/test_task"
- context "--bin parameter set" do
- before do
- bundle "gem #{gem_name} --bin"
- end
+ Minitest::TestTask.create
- it "builds exe skeleton" do
- expect(bundled_app("#{gem_name}/exe/#{gem_name}")).to exist
- end
+ task default: :test
+ RAKEFILE
- it "requires the main file" do
- expect(bundled_app("#{gem_name}/exe/#{gem_name}").read).to match(/require "#{require_path}"/)
- end
+ expect(bundled_app("#{gem_name}/Rakefile").read).to eq(rakefile)
end
+ end
- context "no --test parameter" do
- before do
- bundle "gem #{gem_name}"
- 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_behaves_like "test framework is absent"
+ it "builds spec skeleton" do
+ expect(bundled_app("#{gem_name}/test/#{gem_name}_test.rb")).to exist
+ expect(bundled_app("#{gem_name}/test/test_helper.rb")).to exist
end
- context "--test parameter set to rspec" do
- before do
- bundle "gem #{gem_name} --test=rspec"
- end
+ it "includes test/ into ignore list" do
+ expect(ignore_paths).to include("test/")
+ end
- 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
- end
+ it "creates a default rake task to run the test suite" do
+ rakefile = <<~RAKEFILE
+ # frozen_string_literal: true
- it "depends on a specific version of rspec 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
- rspec_dep = builder.dependencies.find {|d| d.name == "rspec" }
- expect(rspec_dep).to be_specific
- end
+ require "bundler/gem_tasks"
+ require "rake/testtask"
- it "requires the main file" do
- expect(bundled_app("#{gem_name}/spec/spec_helper.rb").read).to include(%(require "#{require_path}"))
- end
+ Rake::TestTask.new(:test) do |t|
+ t.libs << "test"
+ t.libs << "lib"
+ t.test_files = FileList["test/**/*_test.rb"]
+ end
- it "creates a default test which fails" do
- expect(bundled_app("#{gem_name}/spec/#{require_path}_spec.rb").read).to include("expect(false).to eq(true)")
- end
+ task default: :test
+ RAKEFILE
+
+ expect(bundled_app("#{gem_name}/Rakefile").read).to eq(rakefile)
end
+ end
- context "gem.test setting set to rspec" do
- before do
- bundle "config set gem.test rspec"
- bundle "gem #{gem_name}"
- end
+ context "--test parameter set to an invalid value" do
+ before do
+ bundle "gem #{gem_name} --test=foo", raise_on_error: false
+ end
- 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
- end
+ it "fails loudly" do
+ expect(last_command).to be_failure
+ expect(err).to match(/Expected '--test' to be one of .*; got foo/)
end
+ end
- context "gem.test setting set to rspec and --test is set to minitest" do
- before do
- bundle "config set gem.test rspec"
- bundle "gem #{gem_name} --test=minitest"
- end
+ context "gem.test set to rspec and --test with no arguments" do
+ before do
+ bundle "config set gem.test rspec"
+ bundle "gem #{gem_name} --test"
+ end
- it "builds spec skeleton" do
- expect(bundled_app("#{gem_name}/#{minitest_test_file_path}")).to exist
- expect(bundled_app("#{gem_name}/test/test_helper.rb")).to exist
- end
+ it "builds spec skeleton" do
+ expect(bundled_app("#{gem_name}/.rspec")).to exist
+ expect(bundled_app("#{gem_name}/spec/#{gem_name}_spec.rb")).to exist
+ expect(bundled_app("#{gem_name}/spec/spec_helper.rb")).to exist
end
- context "--test parameter set to minitest" do
- before do
- bundle "gem #{gem_name} --test=minitest"
- end
+ it "includes .rspec and spec/ into ignore list" do
+ expect(ignore_paths).to include(".rspec")
+ expect(ignore_paths).to include("spec/")
+ end
- it "depends on a specific version of minitest" 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
- minitest_dep = builder.dependencies.find {|d| d.name == "minitest" }
- expect(minitest_dep).to be_specific
- end
+ it "hints that --test is already configured" do
+ expect(out).to match("rspec is already configured, ignoring --test flag.")
+ end
+ end
- it "builds spec skeleton" do
- expect(bundled_app("#{gem_name}/#{minitest_test_file_path}")).to exist
- expect(bundled_app("#{gem_name}/test/test_helper.rb")).to exist
+ context "gem.test setting set to false and --test with no arguments", :readline do
+ before do
+ bundle "config set gem.test false"
+ bundle "gem #{gem_name} --test" do |input, _, _|
+ input.puts
end
+ end
- it "requires the main file" do
- expect(bundled_app("#{gem_name}/test/test_helper.rb").read).to include(%(require "#{require_path}"))
- end
+ it "asks to generate test files" do
+ expect(out).to match("Do you want to generate tests with your gem?")
+ end
- it "requires 'test_helper'" do
- expect(bundled_app("#{gem_name}/#{minitest_test_file_path}").read).to include(%(require "test_helper"))
- 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 "defines valid test class name" do
- expect(bundled_app("#{gem_name}/#{minitest_test_file_path}").read).to include(minitest_test_class_name)
- end
+ it_behaves_like "test framework is absent"
+ end
- it "creates a default test which fails" do
- expect(bundled_app("#{gem_name}/#{minitest_test_file_path}").read).to include("assert false")
+ context "gem.test setting not set and --test with no arguments", :readline do
+ before do
+ global_config "BUNDLE_GEM__TEST" => nil
+ bundle "gem #{gem_name} --test" do |input, _, _|
+ input.puts
end
end
- context "gem.test setting set to minitest" do
- before do
- bundle "config set gem.test minitest"
- bundle "gem #{gem_name}"
- end
+ it "asks to generate test files" do
+ expect(out).to match("Do you want to generate tests with your gem?")
+ end
- it "creates a default rake task to run the test suite" do
- rakefile = <<~RAKEFILE
- # frozen_string_literal: true
+ 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
- require "bundler/gem_tasks"
- require "minitest/test_task"
+ it_behaves_like "test framework is absent"
+ end
- Minitest::TestTask.create
+ context "gem.test setting set to a test framework and --no-test" do
+ before do
+ bundle "config set gem.test rspec"
+ bundle "gem #{gem_name} --no-test"
+ end
- task default: :test
- RAKEFILE
+ it_behaves_like "test framework is absent"
+ end
- expect(bundled_app("#{gem_name}/Rakefile").read).to eq(rakefile)
- end
+ context "--ci with no argument" do
+ before do
+ bundle "gem #{gem_name}"
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 "does not generate any CI config" do
+ expect(bundled_app("#{gem_name}/.github/workflows/main.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
- 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 "does not add any CI config files into ignore list" do
+ expect(ignore_paths).not_to include(".github/")
+ expect(ignore_paths).not_to include(".gitlab-ci.yml")
+ expect(ignore_paths).not_to include(".circleci/")
+ end
+ end
- it "requires the main file" do
- expect(bundled_app("#{gem_name}/test/test_helper.rb").read).to include(%(require "#{require_path}"))
- end
+ context "--ci set to github" do
+ before do
+ bundle "gem #{gem_name} --ci=github"
+ end
- it "requires 'test_helper'" do
- expect(bundled_app("#{gem_name}/test/#{require_path}_test.rb").read).to include(%(require "test_helper"))
- end
+ it "generates a GitHub Actions config file" do
+ expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to exist
+ 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
+ it "includes .github/ into ignore list" do
+ expect(ignore_paths).to include(".github/")
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
+ context "--ci set to gitlab" do
+ before do
+ bundle "gem #{gem_name} --ci=gitlab"
+ end
- it "creates a default rake task to run the test suite" do
- rakefile = <<~RAKEFILE
- # frozen_string_literal: true
+ it "generates a GitLab CI config file" do
+ expect(bundled_app("#{gem_name}/.gitlab-ci.yml")).to exist
+ end
- require "bundler/gem_tasks"
- require "rake/testtask"
+ it "includes .gitlab-ci.yml into ignore list" do
+ expect(ignore_paths).to include(".gitlab-ci.yml")
+ end
+ end
- Rake::TestTask.new(:test) do |t|
- t.libs << "test"
- t.libs << "lib"
- t.test_files = FileList["test/**/*_test.rb"]
- end
+ context "--ci set to circle" do
+ before do
+ bundle "gem #{gem_name} --ci=circle"
+ end
- task default: :test
- RAKEFILE
+ it "generates a CircleCI config file" do
+ expect(bundled_app("#{gem_name}/.circleci/config.yml")).to exist
+ end
- expect(bundled_app("#{gem_name}/Rakefile").read).to eq(rakefile)
- end
+ it "includes .circleci/ into ignore list" do
+ expect(ignore_paths).to include(".circleci/")
end
+ end
- context "gem.test set to rspec and --test with no arguments" do
- before do
- bundle "config set gem.test rspec"
- bundle "gem #{gem_name} --test"
- end
+ context "--ci set to an invalid value" do
+ before do
+ bundle "gem #{gem_name} --ci=foo", raise_on_error: false
+ end
- 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
- end
+ it "fails loudly" do
+ expect(last_command).to be_failure
+ expect(err).to match(/Expected '--ci' to be one of .*; got foo/)
+ end
+ end
- it "hints that --test is already configured" do
- expect(out).to match("rspec is already configured, ignoring --test flag.")
- 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}/.gitlab-ci.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.circleci/config.yml")).to_not exist
end
+ end
- context "gem.test setting set to false and --test with no arguments", :readline do
- before do
- bundle "config set gem.test false"
- bundle "gem #{gem_name} --test" do |input, _, _|
- input.puts
- 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}"
- it "asks to generate test files" do
- expect(out).to match("Do you want to generate tests with your gem?")
- end
+ expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to exist
+ end
+ 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
+ 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}"
- it_behaves_like "test framework is absent"
+ expect(bundled_app("#{gem_name}/.gitlab-ci.yml")).to exist
end
+ end
- context "gem.test setting not set and --test with no arguments", :readline do
- before do
- global_config "BUNDLE_GEM__TEST" => nil
- bundle "gem #{gem_name} --test" do |input, _, _|
- input.puts
- 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}"
- it "asks to generate test files" do
- expect(out).to match("Do you want to generate tests with your gem?")
- end
+ expect(bundled_app("#{gem_name}/.circleci/config.yml")).to exist
+ end
+ 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
+ context "gem.ci set to github and --ci with no arguments" do
+ before do
+ bundle "config set gem.ci github"
+ bundle "gem #{gem_name} --ci"
+ end
- it_behaves_like "test framework is absent"
+ it "generates a GitHub Actions config file" do
+ expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to exist
end
- context "--ci with no argument" do
- it "does not generate any CI config" do
- bundle "gem #{gem_name}"
+ it "hints that --ci is already configured" do
+ expect(out).to match("github is already configured, ignoring --ci flag.")
+ end
+ end
- expect(bundled_app("#{gem_name}/.github/workflows/main.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
+ context "gem.ci setting set to false and --ci with no arguments", :readline do
+ before do
+ bundle "config set gem.ci false"
+ bundle "gem #{gem_name} --ci" do |input, _, _|
+ input.puts "github"
end
end
- context "--ci set to github" do
- it "generates a GitHub Actions config file" do
- bundle "gem #{gem_name} --ci=github"
+ 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
- expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to exist
+ context "gem.ci setting not set and --ci with no arguments", :readline do
+ before do
+ global_config "BUNDLE_GEM__CI" => nil
+ bundle "gem #{gem_name} --ci" do |input, _, _|
+ input.puts "github"
end
+ end
- it "contained .gitlab-ci.yml into ignore list" do
- bundle "gem #{gem_name} --ci=github"
+ it "asks to setup CI" do
+ expect(out).to match("Do you want to set up continuous integration for your gem?")
+ end
- expect(bundled_app("#{gem_name}/#{gem_name}.gemspec").read).to include(".git .github appveyor")
- 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 "--ci set to gitlab" do
- it "generates a GitLab CI config file" do
- bundle "gem #{gem_name} --ci=gitlab"
+ context "gem.ci setting set to a CI service and --no-ci" do
+ before do
+ bundle "config set gem.ci github"
+ bundle "gem #{gem_name} --no-ci"
+ end
- expect(bundled_app("#{gem_name}/.gitlab-ci.yml")).to exist
- end
+ it "does not generate any CI config" do
+ expect(bundled_app("#{gem_name}/.github/workflows/main.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
- it "contained .gitlab-ci.yml into ignore list" do
- bundle "gem #{gem_name} --ci=gitlab"
+ context "--linter with no argument" do
+ before do
+ bundle "gem #{gem_name}"
+ end
- expect(bundled_app("#{gem_name}/#{gem_name}.gemspec").read).to include(".git .gitlab-ci.yml appveyor")
- end
+ it "does not generate any linter config" do
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.standard.yml")).to_not exist
end
- context "--ci set to circle" do
- it "generates a CircleCI config file" do
- bundle "gem #{gem_name} --ci=circle"
+ it "does not add any linter config files into ignore list" do
+ expect(ignore_paths).not_to include(".rubocop.yml")
+ expect(ignore_paths).not_to include(".standard.yml")
+ end
+ end
- expect(bundled_app("#{gem_name}/.circleci/config.yml")).to exist
- end
+ context "--linter set to rubocop" do
+ before do
+ bundle "gem #{gem_name} --linter=rubocop"
+ end
- it "contained .circleci into ignore list" do
- bundle "gem #{gem_name} --ci=circle"
+ it "generates a RuboCop config" do
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to exist
+ expect(bundled_app("#{gem_name}/.standard.yml")).to_not exist
+ end
- expect(bundled_app("#{gem_name}/#{gem_name}.gemspec").read).to include(".git .circleci appveyor")
- end
+ it "includes .rubocop.yml into ignore list" do
+ expect(ignore_paths).to include(".rubocop.yml")
+ expect(ignore_paths).not_to include(".standard.yml")
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}/.gitlab-ci.yml")).to_not exist
- expect(bundled_app("#{gem_name}/.circleci/config.yml")).to_not exist
- end
+ context "--linter set to standard" do
+ before do
+ bundle "gem #{gem_name} --linter=standard"
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}"
+ it "generates a Standard config" do
+ expect(bundled_app("#{gem_name}/.standard.yml")).to exist
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to_not exist
+ end
- expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to exist
- end
+ it "includes .standard.yml into ignore list" do
+ expect(ignore_paths).to include(".standard.yml")
+ expect(ignore_paths).not_to include(".rubocop.yml")
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}"
+ context "--linter set to an invalid value" do
+ before do
+ bundle "gem #{gem_name} --linter=foo", raise_on_error: false
+ end
- expect(bundled_app("#{gem_name}/.gitlab-ci.yml")).to exist
- end
+ it "fails loudly" do
+ expect(last_command).to be_failure
+ expect(err).to match(/Expected '--linter' to be one of .*; got foo/)
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}"
+ context "gem.linter setting set to none" do
+ before do
+ bundle "gem #{gem_name}"
+ end
- expect(bundled_app("#{gem_name}/.circleci/config.yml")).to exist
- end
+ it "doesn't generate any linter config" do
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.standard.yml")).to_not exist
end
- context "gem.ci set to github and --ci with no arguments" do
- before do
- bundle "config set gem.ci github"
- bundle "gem #{gem_name} --ci"
- end
+ it "does not add any linter config files into ignore list" do
+ expect(ignore_paths).not_to include(".rubocop.yml")
+ expect(ignore_paths).not_to include(".standard.yml")
+ end
+ end
- it "generates a GitHub Actions config file" do
- expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to exist
- end
+ context "gem.linter setting set to rubocop" do
+ before do
+ bundle "config set gem.linter rubocop"
+ bundle "gem #{gem_name}"
+ end
- it "hints that --ci is already configured" do
- expect(out).to match("github is already configured, ignoring --ci flag.")
- end
+ it "generates a RuboCop config file" do
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to exist
end
- context "gem.ci setting set to false and --ci with no arguments", :readline do
- before do
- bundle "config set gem.ci false"
- bundle "gem #{gem_name} --ci" do |input, _, _|
- input.puts "github"
- end
- end
+ it "includes .rubocop.yml into ignore list" do
+ expect(ignore_paths).to include(".rubocop.yml")
+ end
+ end
- it "asks to setup CI" do
- expect(out).to match("Do you want to set up continuous integration for your gem?")
- end
+ context "gem.linter setting set to standard" do
+ before do
+ bundle "config set gem.linter standard"
+ bundle "gem #{gem_name}"
+ 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 "generates a Standard config file" do
+ expect(bundled_app("#{gem_name}/.standard.yml")).to exist
end
- context "gem.ci setting not set and --ci with no arguments", :readline do
- before do
- global_config "BUNDLE_GEM__CI" => nil
- bundle "gem #{gem_name} --ci" do |input, _, _|
- input.puts "github"
- end
- end
+ it "includes .standard.yml into ignore list" do
+ expect(ignore_paths).to include(".standard.yml")
+ end
+ end
- it "asks to setup CI" do
- expect(out).to match("Do you want to set up continuous integration for your gem?")
- end
+ context "gem.linter set to rubocop and --linter with no arguments" do
+ before do
+ bundle "config set gem.linter rubocop"
+ bundle "gem #{gem_name} --linter"
+ 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
+ it "generates a RuboCop config file" do
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to exist
end
- context "--linter with no argument" do
- it "does not generate any linter config" do
- bundle "gem #{gem_name}"
+ it "includes .rubocop.yml into ignore list" do
+ expect(ignore_paths).to include(".rubocop.yml")
+ end
- expect(bundled_app("#{gem_name}/.rubocop.yml")).to_not exist
- expect(bundled_app("#{gem_name}/.standard.yml")).to_not exist
+ 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", :readline do
+ before do
+ bundle "config set gem.linter false"
+ bundle "gem #{gem_name} --linter" do |input, _, _|
+ input.puts "rubocop"
end
end
- context "--linter set to rubocop" do
- it "generates a RuboCop config" do
- bundle "gem #{gem_name} --linter=rubocop"
+ 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
- expect(bundled_app("#{gem_name}/.rubocop.yml")).to exist
- expect(bundled_app("#{gem_name}/.standard.yml")).to_not exist
+ context "gem.linter setting not set and --linter with no arguments", :readline do
+ before do
+ global_config "BUNDLE_GEM__LINTER" => nil
+ bundle "gem #{gem_name} --linter" do |input, _, _|
+ input.puts "rubocop"
end
end
- context "--linter set to standard" do
- it "generates a Standard config" do
- bundle "gem #{gem_name} --linter=standard"
+ 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
- expect(bundled_app("#{gem_name}/.standard.yml")).to exist
- expect(bundled_app("#{gem_name}/.rubocop.yml")).to_not exist
- 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 "gem.linter setting set to none" do
- it "doesn't generate any linter config" do
- bundle "gem #{gem_name}"
+ context "gem.linter setting set to a linter and --no-linter" do
+ before do
+ bundle "config set gem.linter rubocop"
+ bundle "gem #{gem_name} --no-linter"
+ end
- expect(bundled_app("#{gem_name}/.rubocop.yml")).to_not exist
- expect(bundled_app("#{gem_name}/.standard.yml")).to_not exist
- end
+ it "does not generate any linter config" do
+ expect(bundled_app("#{gem_name}/.rubocop.yml")).to_not exist
+ expect(bundled_app("#{gem_name}/.standard.yml")).to_not exist
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}"
+ it "does not add any linter config files into ignore list" do
+ expect(ignore_paths).not_to include(".rubocop.yml")
+ expect(ignore_paths).not_to include(".standard.yml")
+ end
+ end
- expect(bundled_app("#{gem_name}/.rubocop.yml")).to exist
- 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(bundled_app, gem_name, "#{gem_name}.gemspec")
+ expect(output).to include("echo \"#{gemspec_path}\"")
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}"
+ shared_examples_for "paths that depend on gem name" do
+ it "generates entrypoint, version file and signatures file at the proper path, with the proper content" do
+ bundle "gem #{gem_name}"
- expect(bundled_app("#{gem_name}/.standard.yml")).to exist
- end
+ expect(bundled_app("#{gem_name}/lib/#{require_path}.rb")).to exist
+ expect(bundled_app("#{gem_name}/lib/#{require_path}.rb").read).to match(%r{require_relative "#{require_relative_path}/version"})
+ expect(bundled_app("#{gem_name}/lib/#{require_path}.rb").read).to match(/class Error < StandardError; end$/)
+
+ expect(bundled_app("#{gem_name}/lib/#{require_path}/version.rb")).to exist
+ expect(bundled_app("#{gem_name}/sig/#{require_path}.rbs")).to exist
end
- context "gem.rubocop setting set to true", bundler: "< 3" do
+ context "--exe parameter set" do
before do
- global_config "BUNDLE_GEM__LINTER" => nil
- bundle "config set gem.rubocop true"
- bundle "gem #{gem_name}"
+ bundle "gem #{gem_name} --exe"
end
- it "generates rubocop config" do
- expect(bundled_app("#{gem_name}/.rubocop.yml")).to exist
+ it "builds an exe file that requires the proper entrypoint" do
+ expect(bundled_app("#{gem_name}/exe/#{gem_name}")).to exist
+ expect(bundled_app("#{gem_name}/exe/#{gem_name}").read).to match(/require "#{require_path}"/)
end
+ end
- it "unsets gem.rubocop" do
- bundle "config gem.rubocop"
- expect(out).to include("You have not configured a value for `gem.rubocop`")
+ context "--bin parameter set" do
+ before do
+ bundle "gem #{gem_name} --bin"
end
- it "sets gem.linter=rubocop instead" do
- bundle "config gem.linter"
- expect(out).to match(/Set for the current user .*: "rubocop"/)
+ it "builds an exe file that requires the proper entrypoint" do
+ expect(bundled_app("#{gem_name}/exe/#{gem_name}")).to exist
+ expect(bundled_app("#{gem_name}/exe/#{gem_name}").read).to match(/require "#{require_path}"/)
end
end
- context "gem.linter set to rubocop and --linter with no arguments" do
+ context "--test parameter set to rspec" 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
+ bundle "gem #{gem_name} --test=rspec"
end
- it "hints that --linter is already configured" do
- expect(out).to match("rubocop is already configured, ignoring --linter flag.")
+ it "builds a spec helper that requires the proper entrypoint, and a default test in the proper path which fails" do
+ expect(bundled_app("#{gem_name}/spec/spec_helper.rb")).to exist
+ expect(bundled_app("#{gem_name}/spec/spec_helper.rb").read).to include(%(require "#{require_path}"))
+ expect(bundled_app("#{gem_name}/spec/#{require_path}_spec.rb")).to exist
+ expect(bundled_app("#{gem_name}/spec/#{require_path}_spec.rb").read).to include("expect(false).to eq(true)")
end
end
- context "gem.linter setting set to false and --linter with no arguments", :readline do
+ context "--test parameter set to minitest" do
before do
- bundle "config set gem.linter false"
- bundle "gem #{gem_name} --linter" do |input, _, _|
- input.puts "rubocop"
- end
+ bundle "gem #{gem_name} --test=minitest"
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 "builds a test helper that requires the proper entrypoint, and default test file in the proper path that defines the proper test class name, requires helper, and fails" do
+ expect(bundled_app("#{gem_name}/test/test_helper.rb")).to exist
+ expect(bundled_app("#{gem_name}/test/test_helper.rb").read).to include(%(require "#{require_path}"))
- 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.")
+ expect(bundled_app("#{gem_name}/#{minitest_test_file_path}")).to exist
+ expect(bundled_app("#{gem_name}/#{minitest_test_file_path}").read).to include(minitest_test_class_name)
+ expect(bundled_app("#{gem_name}/#{minitest_test_file_path}").read).to include(%(require "test_helper"))
+ expect(bundled_app("#{gem_name}/#{minitest_test_file_path}").read).to include("assert false")
end
end
- context "gem.linter setting not set and --linter with no arguments", :readline do
+ context "--test parameter set to test-unit" do
before do
- global_config "BUNDLE_GEM__LINTER" => nil
- bundle "gem #{gem_name} --linter" do |input, _, _|
- input.puts "rubocop"
- end
+ bundle "gem #{gem_name} --test=test-unit"
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?")
+ it "builds a test helper that requires the proper entrypoint, and default test file in the proper path which requires helper and fails" do
+ expect(bundled_app("#{gem_name}/test/test_helper.rb")).to exist
+ expect(bundled_app("#{gem_name}/test/test_helper.rb").read).to include(%(require "#{require_path}"))
+ expect(bundled_app("#{gem_name}/test/#{require_path}_test.rb")).to exist
+ expect(bundled_app("#{gem_name}/test/#{require_path}_test.rb").read).to include(%(require "test_helper"))
+ expect(bundled_app("#{gem_name}/test/#{require_path}_test.rb").read).to include("assert_equal(\"expected\", \"actual\")")
end
+ end
+ 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
+ context "with mit option in bundle config settings set to true" do
+ before do
+ global_config "BUNDLE_GEM__MIT" => "true"
end
+ it_behaves_like "--mit flag"
+ it_behaves_like "--no-mit flag"
+ 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(bundled_app, gem_name, "#{gem_name}.gemspec")
- expect(output).to include("echo \"#{gemspec_path}\"")
- 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 "testing --mit and --coc options against bundle config settings" do
- let(:gem_name) { "test-gem" }
+ context "with coc option in bundle config settings set to true" do
+ before do
+ global_config "BUNDLE_GEM__COC" => "true"
+ end
+ it_behaves_like "--coc flag"
+ it_behaves_like "--no-coc flag"
+ end
- let(:require_path) { "test/gem" }
+ 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 mit option in bundle config settings set to true" do
- before do
- global_config "BUNDLE_GEM__MIT" => "true"
- end
- it_behaves_like "--mit flag"
- it_behaves_like "--no-mit flag"
+ 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 "--no-linter 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"
+ 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 "--no-linter flag"
+ end
- context "with coc option in bundle config settings set to true" do
- before do
- global_config "BUNDLE_GEM__COC" => "true"
- end
- it_behaves_like "--coc flag"
- it_behaves_like "--no-coc flag"
+ 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 "--no-linter 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"
+ 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 "--no-linter 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"
+ 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 "--no-linter 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"
+ 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 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"
+ 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
+
+ context "with bundle option in bundle config settings set to true" do
+ before do
+ global_config "BUNDLE_GEM__BUNDLE" => "true"
end
+ it_behaves_like "--bundle flag"
+ it_behaves_like "--no-bundle flag"
- context "with linter option in bundle config settings set to standard" do
+ it "runs bundle install" do
+ bundle "gem #{gem_name}"
+ expect(out).to include("Running bundle install in the new gem directory.")
+ end
+ end
+
+ context "with bundle option in bundle config settings set to false" do
+ before do
+ global_config "BUNDLE_GEM__BUNDLE" => "false"
+ end
+ it_behaves_like "--bundle flag"
+ it_behaves_like "--no-bundle flag"
+
+ it "does not run bundle install" do
+ bundle "gem #{gem_name}"
+ expect(out).to_not include("Running bundle install in the new gem directory.")
+ end
+ end
+
+ context "without git config github.user set" do
+ before do
+ 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__LINTER" => "standard"
+ global_config "BUNDLE_GEM__GITHUB_USERNAME" => "different_username"
end
- it_behaves_like "--linter=rubocop flag"
- it_behaves_like "--linter=standard flag"
- it_behaves_like "--linter=none flag"
+ it_behaves_like "--github-username option", "gh_user"
end
- context "with linter option in bundle config settings set to false" do
+ it_behaves_like "github_username configuration"
+
+ context "with github-username option in bundle config settings set to false" do
before do
- global_config "BUNDLE_GEM__LINTER" => "false"
+ global_config "BUNDLE_GEM__GITHUB_USERNAME" => "false"
end
- it_behaves_like "--linter=rubocop flag"
- it_behaves_like "--linter=standard flag"
- it_behaves_like "--linter=none flag"
+ it_behaves_like "--github-username option", "gh_user"
end
- context "with changelog option in bundle config settings set to true" do
- before do
- global_config "BUNDLE_GEM__CHANGELOG" => "true"
+ context "when changelog is enabled" do
+ it "sets gemspec changelog_uri, homepage, homepage_uri, source_code_uri to TODOs" do
+ bundle "gem #{gem_name} --changelog"
+
+ expect(generated_gemspec.metadata["changelog_uri"]).
+ to eq("TODO: Put your gem's CHANGELOG.md URL here.")
+ expect(generated_gemspec.homepage).to eq("TODO: Put your gem's website or public repo URL here.")
+ expect(generated_gemspec.metadata["homepage_uri"]).to eq("TODO: Put your gem's website or public repo URL here.")
+ expect(generated_gemspec.metadata["source_code_uri"]).to eq("TODO: Put your gem's public repo URL here.")
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"
+ context "when changelog is not enabled" do
+ it "sets gemspec homepage, homepage_uri, source_code_uri to TODOs and changelog_uri to nil" do
+ bundle "gem #{gem_name}"
+
+ expect(generated_gemspec.metadata["changelog_uri"]).to be_nil
+ expect(generated_gemspec.homepage).to eq("TODO: Put your gem's website or public repo URL here.")
+ expect(generated_gemspec.metadata["homepage_uri"]).to eq("TODO: Put your gem's website or public repo URL here.")
+ expect(generated_gemspec.metadata["source_code_uri"]).to eq("TODO: Put your gem's public repo URL here.")
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" do
- context "without git config set" do
+ context "with git config github.user set" do
+ context "with github-username option in bundle config settings set to some value" 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"
+ 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"
+ it_behaves_like "github_username configuration"
+
+ 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
- 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"
+ context "when changelog is enabled" do
+ it "sets gemspec changelog_uri, homepage, homepage_uri, source_code_uri based on git username" do
+ bundle "gem #{gem_name} --changelog"
+
+ expect(generated_gemspec.metadata["changelog_uri"]).
+ to eq("https://github.com/bundleuser/#{gem_name}/blob/main/CHANGELOG.md")
+ expect(generated_gemspec.homepage).to eq("https://github.com/bundleuser/#{gem_name}")
+ expect(generated_gemspec.metadata["homepage_uri"]).to eq("https://github.com/bundleuser/#{gem_name}")
+ expect(generated_gemspec.metadata["source_code_uri"]).to eq("https://github.com/bundleuser/#{gem_name}")
end
+ 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"
+ context "when changelog is not enabled" do
+ it "sets gemspec source_code_uri, homepage, homepage_uri but not changelog_uri" do
+ bundle "gem #{gem_name}"
+
+ expect(generated_gemspec.metadata["changelog_uri"]).to be_nil
+ expect(generated_gemspec.homepage).to eq("https://github.com/bundleuser/#{gem_name}")
+ expect(generated_gemspec.metadata["homepage_uri"]).to eq("https://github.com/bundleuser/#{gem_name}")
+ expect(generated_gemspec.metadata["source_code_uri"]).to eq("https://github.com/bundleuser/#{gem_name}")
end
end
end
- context "testing github_username bundle config against git config settings" do
- context "without git config set" do
- before do
- sys_exec("git config --global --unset github.user")
- end
+ context "standard gem naming" do
+ let(:require_path) { gem_name }
- it_behaves_like "github_username configuration"
- end
+ let(:require_relative_path) { gem_name }
- context "with git config set" do
- it_behaves_like "github_username configuration"
- end
+ let(:minitest_test_file_path) { "test/test_#{gem_name}.rb" }
+
+ let(:minitest_test_class_name) { "class TestMygem < Minitest::Test" }
+
+ include_examples "paths that depend on gem name"
end
context "gem naming with underscore" do
@@ -1384,25 +1666,7 @@ RSpec.describe "bundle gem" do
expect(bundled_app("#{gem_name}/lib/#{require_path}.rb").read).to match(/module TestGem/)
end
- include_examples "generating a gem"
-
- context "--ext parameter with no value" do
- context "is deprecated", bundler: "< 3" do
- it "prints deprecation when used after gem name" do
- bundle ["gem", "--ext", gem_name].compact.join(" ")
- expect(err).to include "[DEPRECATED]"
- expect(err).to include "`--ext` with no arguments has been deprecated"
- expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.c")).to exist
- end
-
- it "prints deprecation when used before gem name" do
- bundle ["gem", gem_name, "--ext"].compact.join(" ")
- expect(err).to include "[DEPRECATED]"
- expect(err).to include "`--ext` with no arguments has been deprecated"
- expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.c")).to exist
- end
- end
- end
+ include_examples "paths that depend on gem name"
context "--ext parameter set with C" do
let(:flags) { "--ext=c" }
@@ -1411,20 +1675,23 @@ RSpec.describe "bundle gem" do
bundle ["gem", gem_name, flags].compact.join(" ")
end
- it "is not deprecated" do
- expect(err).not_to include "[DEPRECATED] Option `--ext` without explicit value is deprecated."
- 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
expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.c")).to exist
end
+ it "generates native extension loading code" do
+ expect(bundled_app("#{gem_name}/lib/#{gem_name}.rb").read).to include(<<~RUBY)
+ require_relative "test_gem/version"
+ require "#{gem_name}/#{gem_name}"
+ RUBY
+ end
+
it "includes rake-compiler, but no Rust related changes" do
expect(bundled_app("#{gem_name}/Gemfile").read).to include('gem "rake-compiler"')
- expect(bundled_app("#{gem_name}/Gemfile").read).to_not include('gem "rb_sys"')
+ expect(bundled_app("#{gem_name}/#{gem_name}.gemspec").read).to_not include('spec.add_dependency "rb_sys"')
expect(bundled_app("#{gem_name}/#{gem_name}.gemspec").read).to_not include('spec.required_rubygems_version = ">= ')
end
@@ -1450,24 +1717,10 @@ RSpec.describe "bundle gem" do
end
end
- context "--ext parameter set with rust and old RubyGems" do
- it "fails in friendly way" do
- if ::Gem::Version.new("3.3.11") <= ::Gem.rubygems_version
- skip "RubyGems compatible with Rust builder"
- end
-
- expect do
- bundle ["gem", gem_name, "--ext=rust"].compact.join(" ")
- end.to raise_error(RuntimeError, /too old to build Rust extension/)
- end
- end
-
context "--ext parameter set with rust" do
let(:flags) { "--ext=rust" }
before do
- skip "RubyGems incompatible with Rust builder" if ::Gem::Version.new("3.3.11") > ::Gem.rubygems_version
-
bundle ["gem", gem_name, flags].compact.join(" ")
end
@@ -1484,7 +1737,7 @@ RSpec.describe "bundle gem" do
it "includes rake-compiler, rb_sys gems and required_rubygems_version constraint" do
expect(bundled_app("#{gem_name}/Gemfile").read).to include('gem "rake-compiler"')
- expect(bundled_app("#{gem_name}/Gemfile").read).to include('gem "rb_sys"')
+ expect(bundled_app("#{gem_name}/#{gem_name}.gemspec").read).to include('spec.add_dependency "rb_sys"')
expect(bundled_app("#{gem_name}/#{gem_name}.gemspec").read).to include('spec.required_rubygems_version = ">= ')
end
@@ -1509,6 +1762,158 @@ RSpec.describe "bundle gem" do
expect(bundled_app("#{gem_name}/Rakefile").read).to eq(rakefile)
end
end
+
+ context "--ext parameter set with go" do
+ let(:flags) { "--ext=go" }
+
+ before do
+ bundle ["gem", gem_name, flags].compact.join(" ")
+ end
+
+ after do
+ sys_exec("go clean -modcache", raise_on_error: true) if installed_go?
+ end
+
+ it "is not deprecated" do
+ expect(err).not_to include "[DEPRECATED] Option `--ext` without explicit value is deprecated."
+ end
+
+ it "builds ext skeleton" do
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.c")).to exist
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.go")).to exist
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.h")).to exist
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/extconf.rb")).to exist
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/go.mod")).to exist
+ end
+
+ it "includes extconf.rb in gem_name.gemspec" do
+ expect(bundled_app("#{gem_name}/#{gem_name}.gemspec").read).to include(%(spec.extensions = ["ext/#{gem_name}/extconf.rb"]))
+ end
+
+ it "includes go_gem in gem_name.gemspec" do
+ expect(bundled_app("#{gem_name}/#{gem_name}.gemspec").read).to include('spec.add_dependency "go_gem", "~> 0.2"')
+ end
+
+ it "includes go_gem extension in extconf.rb" do
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/extconf.rb").read).to include(<<~RUBY)
+ require "mkmf"
+ require "go_gem/mkmf"
+ RUBY
+
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/extconf.rb").read).to include(%(create_go_makefile("#{gem_name}/#{gem_name}")))
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/extconf.rb").read).not_to include("create_makefile")
+ end
+
+ it "includes go_gem extension in gem_name.c" do
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.c").read).to eq(<<~C)
+ #include "#{gem_name}.h"
+ #include "_cgo_export.h"
+ C
+ end
+
+ it "includes skeleton code in gem_name.go" do
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.go").read).to include(<<~GO)
+ /*
+ #include "#{gem_name}.h"
+
+ VALUE rb_#{gem_name}_sum(VALUE self, VALUE a, VALUE b);
+ */
+ import "C"
+ GO
+
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.go").read).to include(<<~GO)
+ //export rb_#{gem_name}_sum
+ func rb_#{gem_name}_sum(_ C.VALUE, a C.VALUE, b C.VALUE) C.VALUE {
+ GO
+
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/#{gem_name}.go").read).to include(<<~GO)
+ //export Init_#{gem_name}
+ func Init_#{gem_name}() {
+ GO
+ end
+
+ it "includes valid module name in go.mod" do
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/go.mod").read).to include("module github.com/bundleuser/#{gem_name}")
+ end
+
+ it "includes go_gem extension in Rakefile" do
+ expect(bundled_app("#{gem_name}/Rakefile").read).to include(<<~RUBY)
+ require "go_gem/rake_task"
+
+ GoGem::RakeTask.new("#{gem_name}")
+ RUBY
+ end
+
+ context "with --no-ci" do
+ let(:flags) { "--ext=go --no-ci" }
+
+ it_behaves_like "CI config is absent"
+ end
+
+ context "--ci set to github" do
+ let(:flags) { "--ext=go --ci=github" }
+
+ it "generates .github/workflows/main.yml" do
+ expect(bundled_app("#{gem_name}/.github/workflows/main.yml")).to exist
+ expect(bundled_app("#{gem_name}/.github/workflows/main.yml").read).to include("go-version-file: ext/#{gem_name}/go.mod")
+ end
+ end
+
+ context "--ci set to circle" do
+ let(:flags) { "--ext=go --ci=circle" }
+
+ it "generates a .circleci/config.yml" do
+ expect(bundled_app("#{gem_name}/.circleci/config.yml")).to exist
+
+ expect(bundled_app("#{gem_name}/.circleci/config.yml").read).to include(<<-YAML.strip)
+ environment:
+ GO_VERSION:
+ YAML
+
+ expect(bundled_app("#{gem_name}/.circleci/config.yml").read).to include(<<-YAML)
+ - run:
+ name: Install Go
+ command: |
+ wget https://go.dev/dl/go$GO_VERSION.linux-amd64.tar.gz -O /tmp/go.tar.gz
+ tar -C /usr/local -xzf /tmp/go.tar.gz
+ echo 'export PATH=/usr/local/go/bin:"$PATH"' >> "$BASH_ENV"
+ YAML
+ end
+ end
+
+ context "--ci set to gitlab" do
+ let(:flags) { "--ext=go --ci=gitlab" }
+
+ it "generates a .gitlab-ci.yml" do
+ expect(bundled_app("#{gem_name}/.gitlab-ci.yml")).to exist
+
+ expect(bundled_app("#{gem_name}/.gitlab-ci.yml").read).to include(<<-YAML)
+ - wget https://go.dev/dl/go$GO_VERSION.linux-amd64.tar.gz -O /tmp/go.tar.gz
+ - tar -C /usr/local -xzf /tmp/go.tar.gz
+ - export PATH=/usr/local/go/bin:$PATH
+ YAML
+
+ expect(bundled_app("#{gem_name}/.gitlab-ci.yml").read).to include(<<-YAML.strip)
+ variables:
+ GO_VERSION:
+ YAML
+ end
+ end
+
+ context "without github.user" do
+ before do
+ # FIXME: GitHub Actions Windows Runner hang up here for some reason...
+ skip "Workaround for hung up" if Gem.win_platform?
+
+ git("config --global --unset github.user")
+ bundle ["gem", gem_name, flags].compact.join(" ")
+ end
+
+ it "includes valid module name in go.mod" do
+ expect(bundled_app("#{gem_name}/ext/#{gem_name}/go.mod").read).to include("module github.com/username/#{gem_name}")
+ end
+ end
+ end
end
context "gem naming with dashed" do
@@ -1528,7 +1933,7 @@ RSpec.describe "bundle gem" do
expect(bundled_app("#{gem_name}/lib/#{require_path}.rb").read).to match(/module Test\n module Gem/)
end
- include_examples "generating a gem"
+ include_examples "paths that depend on gem name"
end
describe "uncommon gem names" do
@@ -1622,7 +2027,7 @@ Usage: "bundle gem NAME [OPTIONS]"
expect(bundled_app("foobar/.github/workflows/main.yml")).to exist
end
- it "asks about MIT license" do
+ it "asks about MIT license just once" do
global_config "BUNDLE_GEM__MIT" => nil
bundle "config list"
@@ -1632,9 +2037,10 @@ Usage: "bundle gem NAME [OPTIONS]"
end
expect(bundled_app("foobar/LICENSE.txt")).to exist
+ expect(out).to include("Using a MIT license means").once
end
- it "asks about CoC" do
+ it "asks about CoC just once" do
global_config "BUNDLE_GEM__COC" => nil
bundle "gem foobar" do |input, _, _|
@@ -1642,9 +2048,10 @@ Usage: "bundle gem NAME [OPTIONS]"
end
expect(bundled_app("foobar/CODE_OF_CONDUCT.md")).to exist
+ expect(out).to include("Codes of conduct can increase contributions to your project").once
end
- it "asks about CHANGELOG" do
+ it "asks about CHANGELOG just once" do
global_config "BUNDLE_GEM__CHANGELOG" => nil
bundle "gem foobar" do |input, _, _|
@@ -1652,6 +2059,7 @@ Usage: "bundle gem NAME [OPTIONS]"
end
expect(bundled_app("foobar/CHANGELOG.md")).to exist
+ expect(out).to include("A changelog is a file which contains").once
end
end
diff --git a/spec/bundler/commands/open_spec.rb b/spec/bundler/commands/open_spec.rb
index 5348580448..77e7815017 100644
--- a/spec/bundler/commands/open_spec.rb
+++ b/spec/bundler/commands/open_spec.rb
@@ -4,7 +4,7 @@ RSpec.describe "bundle open" do
context "when opening a regular gem" do
before do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
G
end
@@ -39,17 +39,17 @@ RSpec.describe "bundle open" do
ref = git.ref_for("main", 11)
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'foo', :git => "#{lib_path("foo-1.0")}"
G
bundle "open foo", env: { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }
- expect(out).to include("editor #{default_bundle_path.join("bundler", "gems", "foo-1.0-#{ref}")}")
+ expect(out).to include("editor #{default_bundle_path("bundler", "gems", "foo-1.0-#{ref}")}")
end
it "suggests alternatives for similar-sounding gems" do
bundle "open Rails", env: { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }, raise_on_error: false
- expect(err).to match(/did you mean rails\?/i)
+ expect(err).to match(/did you mean 'rails'\?/i)
end
it "opens the gem with short words" do
@@ -80,12 +80,12 @@ RSpec.describe "bundle open" do
it "suggests alternatives for similar-sounding gems when using subpath" do
bundle "open Rails --path README.md", env: { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }, raise_on_error: false
- expect(err).to match(/did you mean rails\?/i)
+ expect(err).to match(/did you mean 'rails'\?/i)
end
it "suggests alternatives for similar-sounding gems when using deep subpath" do
bundle "open Rails --path some/path/here", env: { "EDITOR" => "echo editor", "VISUAL" => "", "BUNDLER_EDITOR" => "" }, raise_on_error: false
- expect(err).to match(/did you mean rails\?/i)
+ expect(err).to match(/did you mean 'rails'\?/i)
end
it "opens subpath of the short worded gem" do
@@ -134,7 +134,7 @@ RSpec.describe "bundle open" do
it "performs an automatic bundle install" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
gem "foo"
G
@@ -163,7 +163,7 @@ RSpec.describe "bundle open" do
skip "No default gems available on this test run" if default_gems.empty?
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
end
diff --git a/spec/bundler/commands/outdated_spec.rb b/spec/bundler/commands/outdated_spec.rb
index e7edc67e57..d8633d12e8 100644
--- a/spec/bundler/commands/outdated_spec.rb
+++ b/spec/bundler/commands/outdated_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe "bundle outdated" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
@@ -46,7 +46,7 @@ RSpec.describe "bundle outdated" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "AAA", "1.0.0"
G
@@ -77,7 +77,7 @@ RSpec.describe "bundle outdated" do
it "adds gem group to dependency output when repo is updated" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "terranova", '8'
@@ -109,7 +109,7 @@ RSpec.describe "bundle outdated" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
@@ -126,14 +126,14 @@ RSpec.describe "bundle outdated" do
update_repo2 { build_gem "terranova", "9" }
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "terranova", '9'
gem 'activesupport', '2.3.5'
G
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "terranova", '8'
gem 'activesupport', '2.3.5'
@@ -151,72 +151,6 @@ RSpec.describe "bundle outdated" do
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
- #{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
@@ -225,7 +159,7 @@ RSpec.describe "bundle outdated" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "weakling", "~> 0.0.1"
gem "terranova", '8'
@@ -251,6 +185,14 @@ RSpec.describe "bundle outdated" do
expect(out).to end_with("Bundle up to date!")
end
+ it "works when only out of date gems are not in given group" do
+ update_repo2 do
+ build_gem "terranova", "9"
+ end
+ bundle "outdated --group development"
+ 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")
@@ -301,7 +243,7 @@ RSpec.describe "bundle outdated" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "bar_dependant", '7.0'
G
@@ -331,7 +273,7 @@ RSpec.describe "bundle outdated" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "weakling", "~> 0.0.1"
gem "terranova", '8'
@@ -375,7 +317,7 @@ RSpec.describe "bundle outdated" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "weakling", "~> 0.0.1"
gem "terranova", '8'
@@ -394,7 +336,7 @@ RSpec.describe "bundle outdated" do
bundle "config set clean false"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport", "2.3.4"
G
@@ -409,7 +351,7 @@ RSpec.describe "bundle outdated" do
end
it "doesn't hit repo2" do
- FileUtils.rm_rf(gem_repo2)
+ FileUtils.rm_r(gem_repo2)
bundle "outdated --local"
expect(out).not_to match(/Fetching (gem|version|dependency) metadata from/)
@@ -428,7 +370,7 @@ RSpec.describe "bundle outdated" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
@@ -438,19 +380,40 @@ RSpec.describe "bundle outdated" do
G
end
- it "outputs a sorted list of outdated gems with a more minimal format" do
+ it "outputs a sorted list of outdated gems with a more minimal format to stdout" do
minimal_output = "activesupport (newest 3.0, installed 2.3.5, requested = 2.3.5)\n" \
"weakling (newest 0.2, installed 0.0.3, requested ~> 0.0.1)"
subject
expect(out).to eq(minimal_output)
end
+
+ it "outputs progress to stderr" do
+ subject
+ expect(err).to include("Fetching gem metadata")
+ end
end
context "and no gems are outdated" do
- it "has empty output" do
+ before do
+ build_repo2 do
+ build_gem "activesupport", "3.0"
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "activesupport", "3.0"
+ G
+ end
+
+ it "does not output to stdout" do
subject
expect(out).to be_empty
end
+
+ it "outputs progress to stderr" do
+ subject
+ expect(err).to include("Fetching gem metadata")
+ end
end
end
@@ -474,7 +437,7 @@ RSpec.describe "bundle outdated" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
@@ -497,6 +460,44 @@ RSpec.describe "bundle outdated" do
expect(out).to match(Regexp.new(expected_output))
end
+
+ it "does not require gems to be installed" do
+ build_repo4 do
+ build_gem "zeitwerk", "1.0.0"
+ build_gem "zeitwerk", "2.0.0"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "zeitwerk"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ zeitwerk (1.0.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ zeitwerk
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "outdated zeitwerk", raise_on_error: false
+
+ expected_output = <<~TABLE.tr(".", "\.").strip
+ Gem Current Latest Requested Groups
+ zeitwerk 1.0.0 2.0.0 >= 0 default
+ TABLE
+
+ expect(out).to match(Regexp.new(expected_output))
+ expect(err).to be_empty
+ end
end
describe "pre-release gems" do
@@ -507,7 +508,7 @@ RSpec.describe "bundle outdated" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
@@ -554,7 +555,7 @@ RSpec.describe "bundle outdated" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport", "3.0.0.beta.1"
G
@@ -578,7 +579,7 @@ RSpec.describe "bundle outdated" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
@@ -622,7 +623,7 @@ RSpec.describe "bundle outdated" do
it "doesn't crash when some deps unused on the current platform" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport", platforms: [:ruby_22]
G
@@ -633,8 +634,8 @@ RSpec.describe "bundle outdated" do
it "only reports gem dependencies when they can actually be updated" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack_middleware", "1.0"
+ source "https://gem.repo2"
+ gem "myrack_middleware", "1.0"
G
bundle :outdated, "filter-strict": true
@@ -645,7 +646,7 @@ RSpec.describe "bundle outdated" do
describe "and filter options" do
it "only reports gems that match requirement and patch filter level" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport", "~> 2.3"
gem "weakling", ">= 0.0.1"
G
@@ -667,7 +668,7 @@ RSpec.describe "bundle outdated" do
it "only reports gems that match requirement and minor filter level" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport", "~> 2.3"
gem "weakling", ">= 0.0.1"
G
@@ -689,7 +690,7 @@ RSpec.describe "bundle outdated" do
it "only reports gems that match requirement and major filter level" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport", "~> 2.3"
gem "weakling", ">= 0.0.1"
G
@@ -719,7 +720,7 @@ RSpec.describe "bundle outdated" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
@@ -742,8 +743,8 @@ RSpec.describe "bundle outdated" do
it "performs an automatic bundle install" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "0.9.1"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
gem "foo"
G
@@ -752,18 +753,18 @@ RSpec.describe "bundle outdated" do
expect(out).to include("Installing foo 1.0")
end
- context "after bundle install --deployment", bundler: "< 3" do
+ context "in deployment mode" do
before do
build_repo2
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
- gem "rack"
+ gem "myrack"
gem "foo"
G
bundle :lock
- bundle :install, deployment: true
+ bundle "config deployment true"
end
it "outputs a helpful message about being in deployment mode" do
@@ -786,9 +787,9 @@ RSpec.describe "bundle outdated" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
- gem "rack"
+ gem "myrack"
gem "foo"
G
bundle "config set --local deployment true"
@@ -811,7 +812,7 @@ RSpec.describe "bundle outdated" do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "laduradura", '= 5.15.2'
G
end
@@ -829,7 +830,7 @@ RSpec.describe "bundle outdated" do
it "reports that updates are available if the Ruby platform is used" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "laduradura", '= 5.15.2', :platforms => [:ruby, :jruby]
G
@@ -839,7 +840,7 @@ RSpec.describe "bundle outdated" do
it "reports that updates are available if the JRuby platform is used", :jruby_only do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "laduradura", '= 5.15.2', :platforms => [:ruby, :jruby]
G
@@ -872,7 +873,7 @@ RSpec.describe "bundle outdated" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
@@ -898,7 +899,7 @@ RSpec.describe "bundle outdated" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
@@ -907,7 +908,7 @@ RSpec.describe "bundle outdated" do
gem "terranova", '8'
G
- simulate_new_machine
+ pristine_system_gems
update_git "foo", path: lib_path("foo")
update_repo2 do
@@ -928,7 +929,7 @@ RSpec.describe "bundle outdated" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
@@ -954,7 +955,7 @@ RSpec.describe "bundle outdated" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
@@ -987,7 +988,7 @@ RSpec.describe "bundle outdated" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
@@ -1013,7 +1014,7 @@ RSpec.describe "bundle outdated" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
@@ -1039,7 +1040,7 @@ RSpec.describe "bundle outdated" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "zebra", :git => "#{lib_path("zebra")}"
gem "foo", :git => "#{lib_path("foo")}"
gem "activesupport", "2.3.5"
@@ -1123,7 +1124,7 @@ RSpec.describe "bundle outdated" do
# establish a lockfile set to 1.0.0
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem 'patch', '1.0.0'
gem 'minor', '1.0.0'
gem 'major', '1.0.0'
@@ -1131,7 +1132,7 @@ RSpec.describe "bundle outdated" do
# remove all version requirements
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem 'patch'
gem 'minor'
gem 'major'
@@ -1196,7 +1197,7 @@ RSpec.describe "bundle outdated" do
# establish a lockfile set to 1.4.3
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem 'foo', '1.4.3'
gem 'bar', '2.0.3'
gem 'qux', '1.0.0'
@@ -1205,7 +1206,7 @@ RSpec.describe "bundle outdated" do
# remove 1.4.3 requirement and bar altogether
# to setup update specs below
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem 'foo'
gem 'qux'
G
@@ -1246,13 +1247,13 @@ RSpec.describe "bundle outdated" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem 'weakling', '0.2'
gem 'bar', '2.1'
G
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem 'weakling'
G
@@ -1283,7 +1284,7 @@ RSpec.describe "bundle outdated" do
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
nokogiri (1.11.1)
nokogiri (1.11.1-#{Bundler.local_platform})
@@ -1296,11 +1297,11 @@ RSpec.describe "bundle outdated" do
nokogiri
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "nokogiri"
G
end
@@ -1330,14 +1331,14 @@ RSpec.describe "bundle outdated" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "mini_portile2"
G
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
mini_portile2 (2.5.2)
net-ftp (~> 0.1)
@@ -1350,7 +1351,7 @@ RSpec.describe "bundle outdated" do
mini_portile2
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
diff --git a/spec/bundler/commands/platform_spec.rb b/spec/bundler/commands/platform_spec.rb
index 61e615acae..71ccbb0909 100644
--- a/spec/bundler/commands/platform_spec.rb
+++ b/spec/bundler/commands/platform_spec.rb
@@ -4,7 +4,7 @@ RSpec.describe "bundle platform" do
context "without flags" do
it "returns all the output" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
#{ruby_version_correct}
@@ -27,7 +27,7 @@ G
it "returns all the output including the patchlevel" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
#{ruby_version_correct_patchlevel}
@@ -50,7 +50,7 @@ G
it "doesn't print ruby version requirement if it isn't specified" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo"
G
@@ -68,7 +68,7 @@ G
it "doesn't match the ruby version requirement" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
#{ruby_version_incorrect}
@@ -93,7 +93,7 @@ G
context "--ruby" do
it "returns ruby version when explicit" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
ruby "1.9.3", :engine => 'ruby', :engine_version => '1.9.3'
gem "foo"
@@ -106,7 +106,7 @@ G
it "defaults to MRI" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
ruby "1.9.3"
gem "foo"
@@ -119,7 +119,7 @@ G
it "handles jruby" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
ruby "1.8.7", :engine => 'jruby', :engine_version => '1.6.5'
gem "foo"
@@ -132,7 +132,7 @@ G
it "handles rbx" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
ruby "1.8.7", :engine => 'rbx', :engine_version => '1.2.4'
gem "foo"
@@ -145,7 +145,7 @@ G
it "handles truffleruby" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
ruby "2.5.1", :engine => 'truffleruby', :engine_version => '1.0.0-rc6'
gem "foo"
@@ -158,7 +158,7 @@ G
it "raises an error if engine is used but engine version is not" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
ruby "1.8.7", :engine => 'rbx'
gem "foo"
@@ -171,7 +171,7 @@ G
it "raises an error if engine_version is used but engine is not" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
ruby "1.8.7", :engine_version => '1.2.4'
gem "foo"
@@ -184,7 +184,7 @@ G
it "raises an error if engine version doesn't match ruby version for MRI" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
ruby "1.8.7", :engine => 'ruby', :engine_version => '1.2.4'
gem "foo"
@@ -197,7 +197,7 @@ G
it "should print if no ruby version is specified" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo"
G
@@ -209,13 +209,13 @@ G
it "handles when there is a locked requirement" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
ruby "< 1.8.7"
G
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
@@ -227,7 +227,7 @@ G
ruby 1.0.0p127
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "platform --ruby"
@@ -236,12 +236,12 @@ G
it "handles when there is a lockfile with no requirement" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
@@ -250,7 +250,7 @@ G
DEPENDENCIES
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "platform --ruby"
@@ -259,7 +259,7 @@ G
it "handles when there is a requirement in the gemfile" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
ruby ">= 1.8.7"
G
@@ -269,7 +269,7 @@ G
it "handles when there are multiple requirements in the gemfile" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
ruby ">= 1.8.7", "< 2.0.0"
G
@@ -315,8 +315,8 @@ G
context "bundle install" do
it "installs fine when the ruby version matches" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
#{ruby_version_correct}
G
@@ -326,8 +326,8 @@ G
it "installs fine with any engine", :jruby_only do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
#{ruby_version_correct_engineless}
G
@@ -337,8 +337,8 @@ G
it "installs fine when the patchlevel matches" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
#{ruby_version_correct_patchlevel}
G
@@ -348,8 +348,8 @@ G
it "doesn't install when the ruby version doesn't match" do
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
#{ruby_version_incorrect}
G
@@ -360,8 +360,8 @@ G
it "doesn't install when engine doesn't match" do
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
#{engine_incorrect}
G
@@ -372,8 +372,8 @@ G
it "doesn't install when engine version doesn't match", :jruby_only do
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
#{engine_version_incorrect}
G
@@ -384,8 +384,8 @@ G
it "doesn't install when patchlevel doesn't match" do
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
#{patchlevel_incorrect}
G
@@ -398,13 +398,13 @@ G
context "bundle check" do
it "checks fine when the ruby version matches" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
#{ruby_version_correct}
G
@@ -415,13 +415,13 @@ G
it "checks fine with any engine", :jruby_only do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
#{ruby_version_correct_engineless}
G
@@ -432,13 +432,13 @@ G
it "fails when ruby version doesn't match" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
#{ruby_version_incorrect}
G
@@ -449,13 +449,13 @@ G
it "fails when engine doesn't match" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
#{engine_incorrect}
G
@@ -466,13 +466,13 @@ G
it "fails when engine version doesn't match", :jruby_only do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
#{engine_version_incorrect}
G
@@ -483,13 +483,13 @@ G
it "fails when patchlevel doesn't match" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
#{patchlevel_incorrect}
G
@@ -504,57 +504,57 @@ G
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport"
- gem "rack-obama"
+ gem "myrack-obama"
G
end
it "updates successfully when the ruby version matches" do
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport"
- gem "rack-obama"
+ gem "myrack-obama"
#{ruby_version_correct}
G
update_repo2 do
- build_gem "rack", "1.2" do |s|
- s.executables = "rackup"
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
end
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"
+ expect(the_bundle).to include_gems "myrack 1.2", "myrack-obama 1.0", "activesupport 3.0"
end
it "updates fine with any engine", :jruby_only do
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport"
- gem "rack-obama"
+ gem "myrack-obama"
#{ruby_version_correct_engineless}
G
update_repo2 do
- build_gem "rack", "1.2" do |s|
- s.executables = "rackup"
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
end
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"
+ expect(the_bundle).to include_gems "myrack 1.2", "myrack-obama 1.0", "activesupport 3.0"
end
it "fails when ruby version doesn't match" do
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport"
- gem "rack-obama"
+ gem "myrack-obama"
#{ruby_version_incorrect}
G
@@ -568,9 +568,9 @@ G
it "fails when ruby engine doesn't match", :jruby_only do
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport"
- gem "rack-obama"
+ gem "myrack-obama"
#{engine_incorrect}
G
@@ -584,9 +584,9 @@ G
it "fails when ruby engine version doesn't match", :jruby_only do
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport"
- gem "rack-obama"
+ gem "myrack-obama"
#{engine_version_incorrect}
G
@@ -600,8 +600,8 @@ G
it "fails when patchlevel doesn't match" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
#{patchlevel_incorrect}
G
@@ -617,14 +617,14 @@ G
context "bundle info" do
before do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
G
end
it "prints path if ruby version is correct" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
#{ruby_version_correct}
@@ -636,7 +636,7 @@ G
it "prints path if ruby version is correct for any engine", :jruby_only do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
#{ruby_version_correct_engineless}
@@ -646,9 +646,9 @@ G
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
+ it "fails if ruby version doesn't match" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
#{ruby_version_incorrect}
@@ -658,9 +658,9 @@ G
should_be_ruby_version_incorrect
end
- it "fails if engine doesn't match", bundler: "< 3" do
+ it "fails if engine doesn't match" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
#{engine_incorrect}
@@ -670,9 +670,9 @@ G
should_be_engine_incorrect
end
- it "fails if engine version doesn't match", bundler: "< 3", jruby_only: true do
+ it "fails if engine version doesn't match", jruby_only: true do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
#{engine_version_incorrect}
@@ -682,10 +682,10 @@ G
should_be_engine_version_incorrect
end
- it "fails when patchlevel doesn't match", bundler: "< 3" do
+ it "fails when patchlevel doesn't match" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
#{patchlevel_incorrect}
G
@@ -701,39 +701,39 @@ G
context "bundle cache" do
before do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
end
it "copies the .gem file to vendor/cache when ruby version matches" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
#{ruby_version_correct}
G
bundle :cache
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
end
it "copies the .gem file to vendor/cache when ruby version matches for any engine", :jruby_only do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
#{ruby_version_correct_engineless}
G
bundle :cache
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
+ expect(bundled_app("vendor/cache/myrack-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'
+ source "https://gem.repo1"
+ gem 'myrack'
#{ruby_version_incorrect}
G
@@ -744,8 +744,8 @@ G
it "fails if the engine doesn't match" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
#{engine_incorrect}
G
@@ -756,8 +756,8 @@ G
it "fails if the engine version doesn't match", :jruby_only do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
#{engine_version_incorrect}
G
@@ -768,8 +768,8 @@ G
it "fails when patchlevel doesn't match" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
#{patchlevel_incorrect}
G
@@ -782,39 +782,39 @@ G
context "bundle pack" do
before do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
end
it "copies the .gem file to vendor/cache when ruby version matches" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
#{ruby_version_correct}
G
bundle :cache
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
end
it "copies the .gem file to vendor/cache when ruby version matches any engine", :jruby_only do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
#{ruby_version_correct_engineless}
G
bundle :cache
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
+ expect(bundled_app("vendor/cache/myrack-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'
+ source "https://gem.repo1"
+ gem 'myrack'
#{ruby_version_incorrect}
G
@@ -825,8 +825,8 @@ G
it "fails if the engine doesn't match" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
#{engine_incorrect}
G
@@ -837,8 +837,8 @@ G
it "fails if the engine version doesn't match", :jruby_only do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
#{engine_version_incorrect}
G
@@ -849,8 +849,8 @@ G
it "fails when patchlevel doesn't match" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
#{patchlevel_incorrect}
G
@@ -863,177 +863,140 @@ G
context "bundle exec" do
before do
ENV["BUNDLER_FORCE_TTY"] = "true"
- system_gems "rack-1.0.0", "rack-0.9.1", path: default_bundle_path
+ system_gems "myrack-1.0.0", "myrack-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"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
#{ruby_version_correct}
G
- bundle "exec rackup"
+ bundle "exec myrackup"
expect(out).to include("0.9.1")
end
it "activates the correct gem when ruby version matches any engine", :jruby_only do
- system_gems "rack-1.0.0", "rack-0.9.1", path: default_bundle_path
+ system_gems "myrack-1.0.0", "myrack-0.9.1", path: default_bundle_path
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "0.9.1"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
#{ruby_version_correct_engineless}
G
- bundle "exec rackup"
+ bundle "exec myrackup"
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"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
#{ruby_version_incorrect}
G
- bundle "exec rackup", raise_on_error: false
+ bundle "exec myrackup", 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"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
#{engine_incorrect}
G
- bundle "exec rackup", raise_on_error: false
+ bundle "exec myrackup", raise_on_error: false
should_be_engine_incorrect
end
- # it "fails when the engine version doesn't match", :jruby_only do
- # gemfile <<-G
- # gem "rack", "0.9.1"
- #
- # #{engine_version_incorrect}
- # G
- #
- # bundle "exec rackup"
- # should_be_engine_version_incorrect
- # end
+ it "fails when the engine version doesn't match", :jruby_only do
+ gemfile <<-G
+ gem "myrack", "0.9.1"
+
+ #{engine_version_incorrect}
+ G
+
+ bundle "exec myrackup", raise_on_error: false
+ should_be_engine_version_incorrect
+ end
it "fails when patchlevel doesn't match" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
#{patchlevel_incorrect}
G
- bundle "exec rackup", raise_on_error: false
+ bundle "exec myrackup", raise_on_error: false
should_be_patchlevel_incorrect
end
end
- context "bundle console", bundler: "< 3" do
+ context "bundle console" do
before do
+ build_repo2 do
+ build_dummy_irb
+ end
+
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo2"
+ gem "irb"
+ gem "myrack"
gem "activesupport", :group => :test
- gem "rack_middleware", :group => :development
+ gem "myrack_middleware", :group => :development
G
end
it "starts IRB with the default group loaded when ruby version matches", :readline do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- gem "activesupport", :group => :test
- gem "rack_middleware", :group => :development
-
- #{ruby_version_correct}
- G
+ gemfile gemfile + "\n\n#{ruby_version_correct}\n"
bundle "console" do |input, _, _|
- input.puts("puts RACK")
+ input.puts("puts MYRACK")
input.puts("exit")
end
expect(out).to include("0.9.1")
end
it "starts IRB with the default group loaded when ruby version matches", :readline, :jruby_only 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
+ gemfile gemfile + "\n\n#{ruby_version_correct_engineless}\n"
bundle "console" do |input, _, _|
- input.puts("puts RACK")
+ input.puts("puts MYRACK")
input.puts("exit")
end
expect(out).to include("0.9.1")
end
it "fails when ruby version doesn't match" do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- gem "activesupport", :group => :test
- gem "rack_middleware", :group => :development
-
- #{ruby_version_incorrect}
- G
+ gemfile gemfile + "\n\n#{ruby_version_incorrect}\n"
bundle "console", raise_on_error: false
should_be_ruby_version_incorrect
end
it "fails when engine doesn't match" do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- gem "activesupport", :group => :test
- gem "rack_middleware", :group => :development
-
- #{engine_incorrect}
- G
+ gemfile gemfile + "\n\n#{engine_incorrect}\n"
bundle "console", raise_on_error: false
should_be_engine_incorrect
end
it "fails when engine version doesn't match", :jruby_only do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- gem "activesupport", :group => :test
- gem "rack_middleware", :group => :development
-
- #{engine_version_incorrect}
- G
+ gemfile gemfile + "\n\n#{engine_version_incorrect}\n"
bundle "console", raise_on_error: false
should_be_engine_version_incorrect
end
it "fails when patchlevel doesn't match" do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- gem "activesupport", :group => :test
- gem "rack_middleware", :group => :development
-
- #{patchlevel_incorrect}
- G
+ gemfile gemfile + "\n\n#{patchlevel_incorrect}\n"
bundle "console", raise_on_error: false
should_be_patchlevel_incorrect
@@ -1043,9 +1006,9 @@ G
context "Bundler.setup" do
before do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "yard"
- gem "rack", :group => :test
+ gem "myrack", :group => :test
G
ENV["BUNDLER_FORCE_TTY"] = "true"
@@ -1053,9 +1016,9 @@ G
it "makes a Gemfile.lock if setup succeeds" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "yard"
- gem "rack"
+ gem "myrack"
#{ruby_version_correct}
G
@@ -1068,9 +1031,9 @@ G
it "makes a Gemfile.lock if setup succeeds for any engine", :jruby_only do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "yard"
- gem "rack"
+ gem "myrack"
#{ruby_version_correct_engineless}
G
@@ -1083,9 +1046,9 @@ G
it "fails when ruby version doesn't match" do
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "yard"
- gem "rack"
+ gem "myrack"
#{ruby_version_incorrect}
G
@@ -1100,9 +1063,9 @@ G
it "fails when engine doesn't match" do
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "yard"
- gem "rack"
+ gem "myrack"
#{engine_incorrect}
G
@@ -1117,9 +1080,9 @@ G
it "fails when engine version doesn't match", :jruby_only do
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "yard"
- gem "rack"
+ gem "myrack"
#{engine_version_incorrect}
G
@@ -1134,9 +1097,9 @@ G
it "fails when patchlevel doesn't match" do
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "yard"
- gem "rack"
+ gem "myrack"
#{patchlevel_incorrect}
G
@@ -1157,7 +1120,7 @@ G
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport", "2.3.5"
gem "foo", :git => "#{lib_path("foo")}"
G
@@ -1170,7 +1133,7 @@ G
end
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport", "2.3.5"
gem "foo", :git => "#{lib_path("foo")}"
@@ -1196,7 +1159,7 @@ G
end
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport", "2.3.5"
gem "foo", :git => "#{lib_path("foo")}"
@@ -1221,7 +1184,7 @@ G
end
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport", "2.3.5"
gem "foo", :git => "#{lib_path("foo")}"
@@ -1239,7 +1202,7 @@ G
end
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport", "2.3.5"
gem "foo", :git => "#{lib_path("foo")}"
@@ -1257,7 +1220,7 @@ G
end
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport", "2.3.5"
gem "foo", :git => "#{lib_path("foo")}"
@@ -1275,7 +1238,7 @@ G
end
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport", "2.3.5"
gem "foo", :git => "#{lib_path("foo")}"
@@ -1293,7 +1256,7 @@ G
end
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport", "2.3.5"
gem "foo", :git => "#{lib_path("foo")}"
diff --git a/spec/bundler/commands/post_bundle_message_spec.rb b/spec/bundler/commands/post_bundle_message_spec.rb
index 3c7fd3486d..9eecff593f 100644
--- a/spec/bundler/commands/post_bundle_message_spec.rb
+++ b/spec/bundler/commands/post_bundle_message_spec.rb
@@ -3,13 +3,13 @@
RSpec.describe "post bundle message" do
before :each do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
gem "activesupport", "2.3.5", :group => [:emo, :test]
group :test do
gem "rspec"
end
- gem "rack-obama", :group => :obama
+ gem "myrack-obama", :group => :obama
G
end
@@ -18,162 +18,140 @@ RSpec.describe "post bundle message" do
let(:bundle_show_path_message) { "Bundled gems are installed into `#{bundle_path}`" }
let(:bundle_complete_message) { "Bundle complete!" }
let(:bundle_updated_message) { "Bundle updated!" }
- let(:installed_gems_stats) { "4 Gemfile dependencies, 5 gems now installed." }
- let(:bundle_show_message) { Bundler::VERSION.split(".").first.to_i < 3 ? bundle_show_system_message : bundle_show_path_message }
+ let(:installed_gems_stats) { "4 Gemfile dependencies, 4 gems now installed." }
+
+ describe "when installing to system gems" do
+ before do
+ bundle "config set --local path.system true"
+ end
- describe "for fresh bundle install" do
it "shows proper messages according to the configured groups" do
bundle :install
- expect(out).to include(bundle_show_message)
+ expect(out).to include(bundle_show_system_message)
expect(out).not_to include("Gems in the group")
expect(out).to include(bundle_complete_message)
expect(out).to include(installed_gems_stats)
bundle "config set --local without emo"
bundle :install
- expect(out).to include(bundle_show_message)
+ expect(out).to include(bundle_show_system_message)
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)
bundle "config set --local without emo test"
bundle :install
- expect(out).to include(bundle_show_message)
+ expect(out).to include(bundle_show_system_message)
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.")
+ expect(out).to include("4 Gemfile dependencies, 2 gems now installed.")
bundle "config set --local without emo obama test"
bundle :install
- expect(out).to include(bundle_show_message)
+ expect(out).to include(bundle_show_system_message)
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` configured" do
- let(:bundle_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)
-
- 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(bundle_complete_message)
-
- 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(bundle_complete_message)
-
- 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(bundle_complete_message)
- end
+ expect(out).to include("4 Gemfile dependencies, 1 gem now installed.")
end
- describe "with an absolute `path` inside the cwd configured" do
- let(:bundle_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")
+ describe "for second bundle install run" do
+ it "without any options" do
+ 2.times { bundle :install }
+ expect(out).to include(bundle_show_system_message)
+ expect(out).to_not include("Gems in the groups")
expect(out).to include(bundle_complete_message)
+ expect(out).to include(installed_gems_stats)
end
end
+ end
- describe "with `path` configured to an absolute path outside the cwd" do
- let(:bundle_path) { tmp("not_bundled_app") }
+ describe "with `path` configured" do
+ let(:bundle_path) { "./vendor" }
- 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)
- end
- end
+ 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)
- describe "with misspelled or non-existent gem name" do
- before do
- bundle "config set force_ruby_platform true"
- end
+ 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(bundle_complete_message)
- 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.
- EOS
- end
+ 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(bundle_complete_message)
- it "should report a helpful error message with reference to cache if available" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- G
- bundle :cache
- expect(bundled_app("vendor/cache/rack-1.0.0.gem")).to exist
- 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("Could not find gem 'not-a-gem' in").
- and include("or in gems cached in vendor/cache.")
- end
+ 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(bundle_complete_message)
end
end
- 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)
- expect(out).to_not include("Gems in the groups")
- expect(out).to include(bundle_complete_message)
- expect(out).to include(installed_gems_stats)
- end
+ describe "with an absolute `path` inside the cwd configured" do
+ let(:bundle_path) { bundled_app("cache") }
- it "with --without one group" do
- bundle "install --without emo"
+ it "shows proper messages according to the configured groups" do
+ bundle "config set --local path #{bundle_path}"
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("Bundled gems are installed into `./cache`")
+ expect(out).to_not include("Gems in the group")
expect(out).to include(bundle_complete_message)
- expect(out).to include(installed_gems_stats)
end
+ end
+
+ describe "with `path` configured to an absolute path outside the cwd" do
+ let(:bundle_path) { tmp("not_bundled_app") }
- it "with --without two groups" do
- bundle "install --without emo test"
+ it "shows proper messages according to the configured groups" do
+ bundle "config set --local path #{bundle_path}"
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("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)
end
+ end
+
+ describe "with misspelled or non-existent gem name" do
+ before do
+ bundle "config set force_ruby_platform true"
+ end
- it "with --without more groups" do
- 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(bundle_complete_message)
+ it "should report a helpful error message" do
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo1"
+ gem "myrack"
+ gem "not-a-gem", :group => :development
+ G
+ expect(err).to include <<~EOS.strip
+ Could not find gem 'not-a-gem' in rubygems repository https://gem.repo1/ or installed locally.
+ EOS
+ end
+
+ it "should report a helpful error message with reference to cache if available" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+ bundle :cache
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo1"
+ gem "myrack"
+ gem "not-a-gem", :group => :development
+ G
+ expect(err).to include("Could not find gem 'not-a-gem' in").
+ and include("or in gems cached in vendor/cache.")
end
end
diff --git a/spec/bundler/commands/pristine_spec.rb b/spec/bundler/commands/pristine_spec.rb
index 1aec37f850..daeafea43b 100644
--- a/spec/bundler/commands/pristine_spec.rb
+++ b/spec/bundler/commands/pristine_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe "bundle pristine" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "weakling"
gem "very_simple_binary"
gem "foo", :git => "#{lib_path("foo")}", :branch => "main"
@@ -49,13 +49,7 @@ RSpec.describe "bundle pristine" do
bundle "pristine"
bundle "-v"
- expected = if Bundler::VERSION < "3.0"
- "Bundler version"
- else
- Bundler::VERSION
- end
-
- expect(out).to start_with(expected)
+ expect(out).to end_with(Bundler::VERSION)
end
end
@@ -95,6 +89,66 @@ RSpec.describe "bundle pristine" do
expect(changes_txt).to be_file
expect(err).to include("Cannot pristine #{spec.name} (#{spec.version}#{spec.git_version}). Gem is locally overridden.")
end
+
+ it "doesn't run multiple git processes for the same repository" do
+ nested_gems = [
+ "actioncable",
+ "actionmailer",
+ "actionpack",
+ "actionview",
+ "activejob",
+ "activemodel",
+ "activerecord",
+ "activestorage",
+ "activesupport",
+ "railties",
+ ]
+
+ build_repo2 do
+ nested_gems.each do |gem|
+ build_lib gem, path: lib_path("rails/#{gem}")
+ end
+
+ build_git "rails", path: lib_path("rails") do |s|
+ nested_gems.each do |gem|
+ s.add_dependency gem
+ end
+ end
+ end
+
+ install_gemfile <<-G
+ source 'https://rubygems.org'
+
+ git "#{lib_path("rails")}" do
+ gem "rails"
+ gem "actioncable"
+ gem "actionmailer"
+ gem "actionpack"
+ gem "actionview"
+ gem "activejob"
+ gem "activemodel"
+ gem "activerecord"
+ gem "activestorage"
+ gem "activesupport"
+ gem "railties"
+ end
+ G
+
+ changed_files = []
+ diff = "#Pristine spec changes"
+
+ nested_gems.each do |gem|
+ spec = find_spec(gem)
+ changed_files << Pathname.new(spec.full_gem_path).join("lib/#{gem}.rb")
+ File.open(changed_files.last, "a") {|f| f.puts diff }
+ end
+
+ bundle "pristine"
+
+ changed_files.each do |changed_file|
+ expect(File.read(changed_file)).to_not include(diff)
+ end
+ end
end
context "when sourced from gemspec" do
diff --git a/spec/bundler/commands/remove_spec.rb b/spec/bundler/commands/remove_spec.rb
index 197fcde091..8a2e6778ea 100644
--- a/spec/bundler/commands/remove_spec.rb
+++ b/spec/bundler/commands/remove_spec.rb
@@ -4,7 +4,7 @@ RSpec.describe "bundle remove" do
context "when no gems are specified" do
it "throws error" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
bundle "remove", raise_on_error: false
@@ -16,85 +16,70 @@ RSpec.describe "bundle remove" do
context "after 'bundle install' is run" do
describe "running 'bundle remove GEM_NAME'" do
it "removes it from the lockfile" do
- rack_dep = <<~L
+ myrack_dep = <<~L
DEPENDENCIES
- rack
+ myrack
L
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
G
bundle "install"
- expect(lockfile).to include(rack_dep)
+ expect(lockfile).to include(myrack_dep)
- bundle "remove rack"
+ bundle "remove myrack"
expect(gemfile).to eq <<~G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
- expect(lockfile).to_not include(rack_dep)
+ expect(lockfile).to_not include(myrack_dep)
end
end
end
- context "when --install flag is specified", bundler: "< 3" do
- it "removes gems from .bundle" do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
-
- gem "rack"
- G
-
- bundle "remove rack --install"
-
- expect(out).to include("rack was removed.")
- expect(the_bundle).to_not include_gems "rack"
- end
- end
-
describe "remove single gem from gemfile" do
context "when gem is present in gemfile" do
it "shows success for removed gem" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
G
- bundle "remove rack"
+ bundle "remove myrack"
- expect(out).to include("rack was removed.")
- expect(the_bundle).to_not include_gems "rack"
+ expect(out).to include("myrack was removed.")
+ expect(the_bundle).to_not include_gems "myrack"
expect(gemfile).to eq <<~G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
end
context "when gem is specified in multiple lines" do
it "shows success for removed gem" do
- build_git "rack"
+ build_git "myrack"
gemfile <<-G
- source '#{file_uri_for(gem_repo1)}'
+ source 'https://gem.repo1'
gem 'git'
- gem 'rack',
- git: "#{lib_path("rack-1.0")}",
+ gem 'myrack',
+ git: "#{lib_path("myrack-1.0")}",
branch: 'main'
gem 'nokogiri'
G
- bundle "remove rack"
+ bundle "remove myrack"
- expect(out).to include("rack was removed.")
+ expect(out).to include("myrack was removed.")
expect(gemfile).to eq <<~G
- source '#{file_uri_for(gem_repo1)}'
+ source 'https://gem.repo1'
gem 'git'
gem 'nokogiri'
@@ -106,12 +91,12 @@ RSpec.describe "bundle remove" do
context "when gem is not present in gemfile" do
it "shows warning for gem that could not be removed" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
- bundle "remove rack", raise_on_error: false
+ bundle "remove myrack", 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("`myrack` is not specified in #{bundled_app_gemfile} so it could not be removed.")
end
end
end
@@ -120,18 +105,18 @@ RSpec.describe "bundle remove" do
context "when all gems are present in gemfile" do
it "shows success fir all removed gems" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
gem "rails"
G
- bundle "remove rack rails"
+ bundle "remove myrack rails"
- expect(out).to include("rack was removed.")
+ expect(out).to include("myrack was removed.")
expect(out).to include("rails was removed.")
expect(gemfile).to eq <<~G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
end
end
@@ -139,18 +124,18 @@ RSpec.describe "bundle remove" do
context "when some gems are not present in the gemfile" do
it "shows warning for those not present and success for those that can be removed" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
gem "minitest"
gem "rspec"
G
- bundle "remove rails rack minitest", raise_on_error: false
+ bundle "remove rails myrack minitest", 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("`myrack` is not specified in #{bundled_app_gemfile} so it could not be removed.")
expect(gemfile).to eq <<~G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
gem "minitest"
@@ -163,16 +148,16 @@ RSpec.describe "bundle remove" do
context "with inline groups" do
it "removes the specified gem" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack", :group => [:dev]
+ gem "myrack", :group => [:dev]
G
- bundle "remove rack"
+ bundle "remove myrack"
- expect(out).to include("rack was removed.")
+ expect(out).to include("myrack was removed.")
expect(gemfile).to eq <<~G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
end
end
@@ -181,7 +166,7 @@ RSpec.describe "bundle remove" do
context "when single group block with gem to be removed is present" do
it "removes the group block" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
group :test do
gem "rspec"
@@ -192,7 +177,7 @@ RSpec.describe "bundle remove" do
expect(out).to include("rspec was removed.")
expect(gemfile).to eq <<~G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
end
end
@@ -200,19 +185,19 @@ RSpec.describe "bundle remove" do
context "when gem to be removed is outside block" do
it "does not modify group" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
group :test do
gem "coffee-script-source"
end
G
- bundle "remove rack"
+ bundle "remove myrack"
- expect(out).to include("rack was removed.")
+ expect(out).to include("myrack was removed.")
expect(gemfile).to eq <<~G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
group :test do
gem "coffee-script-source"
@@ -224,7 +209,7 @@ RSpec.describe "bundle remove" do
context "when an empty block is also present" do
it "removes all empty blocks" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
group :test do
gem "rspec"
@@ -238,7 +223,7 @@ RSpec.describe "bundle remove" do
expect(out).to include("rspec was removed.")
expect(gemfile).to eq <<~G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
end
end
@@ -246,7 +231,7 @@ RSpec.describe "bundle remove" do
context "when the gem belongs to multiple groups" do
it "removes the groups" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
group :test, :serioustest do
gem "rspec"
@@ -257,7 +242,7 @@ RSpec.describe "bundle remove" do
expect(out).to include("rspec was removed.")
expect(gemfile).to eq <<~G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
end
end
@@ -265,7 +250,7 @@ RSpec.describe "bundle remove" 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)}"
+ source "https://gem.repo1"
group :one do
gem "rspec"
@@ -280,7 +265,7 @@ RSpec.describe "bundle remove" do
expect(out).to include("rspec was removed.")
expect(gemfile).to eq <<~G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
end
end
@@ -290,7 +275,7 @@ RSpec.describe "bundle remove" do
context "when all the groups will be empty after removal" do
it "removes the empty nested blocks" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
group :test do
group :serioustest do
@@ -303,7 +288,7 @@ RSpec.describe "bundle remove" do
expect(out).to include("rspec was removed.")
expect(gemfile).to eq <<~G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
end
end
@@ -311,10 +296,10 @@ RSpec.describe "bundle remove" do
context "when outer group will not be empty after removal" do
it "removes only empty blocks" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
group :test do
- gem "rack-test"
+ gem "myrack-test"
group :serioustest do
gem "rspec"
@@ -326,10 +311,10 @@ RSpec.describe "bundle remove" do
expect(out).to include("rspec was removed.")
expect(gemfile).to eq <<~G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
group :test do
- gem "rack-test"
+ gem "myrack-test"
end
G
@@ -339,12 +324,12 @@ RSpec.describe "bundle remove" do
context "when inner group will not be empty after removal" do
it "removes only empty blocks" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
group :test do
group :serioustest do
gem "rspec"
- gem "rack-test"
+ gem "myrack-test"
end
end
G
@@ -353,11 +338,11 @@ RSpec.describe "bundle remove" do
expect(out).to include("rspec was removed.")
expect(gemfile).to eq <<~G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
group :test do
group :serioustest do
- gem "rack-test"
+ gem "myrack-test"
end
end
G
@@ -369,16 +354,16 @@ RSpec.describe "bundle remove" 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"
+ source "https://gem.repo1"
+ gem "myrack"; gem "rails"
G
bundle "remove rails", raise_on_error: false
- expect(err).to include("Gems could not be removed. rack (>= 0) would also have been removed.")
+ expect(err).to include("Gems could not be removed. myrack (>= 0) would also have been removed.")
expect(gemfile).to eq <<~G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"; gem "rails"
+ source "https://gem.repo1"
+ gem "myrack"; gem "rails"
G
end
end
@@ -386,21 +371,21 @@ RSpec.describe "bundle remove" do
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, raise_on_error: false
- source "#{file_uri_for(gem_repo1)}"
- gem"rack"
+ source "https://gem.repo1"
+ gem"myrack"
gem"rspec"
gem "rails"
gem "minitest"
G
- bundle "remove rails rack rspec minitest"
+ bundle "remove rails myrack 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.")
+ expect(out).to include("myrack, rspec could not be removed.")
expect(gemfile).to eq <<~G
- source "#{file_uri_for(gem_repo1)}"
- gem"rack"
+ source "https://gem.repo1"
+ gem"myrack"
gem"rspec"
G
end
@@ -409,18 +394,18 @@ RSpec.describe "bundle remove" do
context "with sources" do
before do
- build_repo gem_repo3 do
+ build_repo3 do
build_gem "rspec"
end
end
it "removes gems and empty source blocks" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
- source "#{file_uri_for(gem_repo3)}" do
+ source "https://gem.repo3" do
gem "rspec"
end
G
@@ -431,9 +416,9 @@ RSpec.describe "bundle remove" do
expect(out).to include("rspec was removed.")
expect(gemfile).to eq <<~G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
G
end
end
@@ -441,40 +426,40 @@ RSpec.describe "bundle remove" do
describe "with eval_gemfile" do
context "when gems are present in both gemfiles" do
it "removes the gems" do
- create_file "Gemfile-other", <<-G
- gem "rack"
+ gemfile "Gemfile-other", <<-G
+ gem "myrack"
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
eval_gemfile "Gemfile-other"
- gem "rack"
+ gem "myrack"
G
- bundle "remove rack"
+ bundle "remove myrack"
- expect(out).to include("rack was removed.")
+ expect(out).to include("myrack was removed.")
end
end
context "when gems are present in other gemfile" do
it "removes the gems" do
- create_file "Gemfile-other", <<-G
- gem "rack"
+ gemfile "Gemfile-other", <<-G
+ gem "myrack"
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
eval_gemfile "Gemfile-other"
G
- bundle "remove rack"
+ bundle "remove myrack"
- expect(bundled_app("Gemfile-other").read).to_not include("gem \"rack\"")
- expect(out).to include("rack was removed.")
+ expect(bundled_app("Gemfile-other").read).to_not include("gem \"myrack\"")
+ expect(out).to include("myrack was removed.")
end
end
@@ -486,36 +471,36 @@ RSpec.describe "bundle remove" do
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
eval_gemfile "Gemfile-other"
G
- bundle "remove rack", raise_on_error: false
+ bundle "remove myrack", 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("`myrack` is not specified in #{bundled_app_gemfile} so it could not be removed.")
end
end
context "when the gem is present in parent file but not in gemfile specified by eval_gemfile" do
it "removes the gem" do
- create_file "Gemfile-other", <<-G
+ gemfile "Gemfile-other", <<-G
gem "rails"
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
eval_gemfile "Gemfile-other"
- gem "rack"
+ gem "myrack"
G
- bundle "remove rack", raise_on_error: false
+ bundle "remove myrack", 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.")
+ expect(out).to include("myrack was removed.")
+ expect(err).to include("`myrack` is not specified in #{bundled_app("Gemfile-other")} so it could not be removed.")
expect(gemfile).to eq <<~G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
eval_gemfile "Gemfile-other"
G
@@ -524,23 +509,23 @@ RSpec.describe "bundle remove" do
context "when gems cannot be removed from other gemfile" do
it "shows error" do
- create_file "Gemfile-other", <<-G
- gem "rails"; gem "rack"
+ gemfile "Gemfile-other", <<-G
+ gem "rails"; gem "myrack"
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
eval_gemfile "Gemfile-other"
- gem "rack"
+ gem "myrack"
G
- bundle "remove rack", raise_on_error: false
+ bundle "remove myrack", raise_on_error: false
- expect(out).to include("rack was removed.")
+ expect(out).to include("myrack was removed.")
expect(err).to include("Gems could not be removed. rails (>= 0) would also have been removed.")
expect(gemfile).to eq <<~G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
eval_gemfile "Gemfile-other"
G
@@ -549,47 +534,47 @@ RSpec.describe "bundle remove" do
context "when gems could not be removed from parent gemfile" do
it "shows error" do
- create_file "Gemfile-other", <<-G
- gem "rack"
+ gemfile "Gemfile-other", <<-G
+ gem "myrack"
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
eval_gemfile "Gemfile-other"
- gem "rails"; gem "rack"
+ gem "rails"; gem "myrack"
G
- bundle "remove rack", raise_on_error: false
+ bundle "remove myrack", 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\"")
+ expect(bundled_app("Gemfile-other").read).to include("gem \"myrack\"")
expect(gemfile).to eq <<~G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
eval_gemfile "Gemfile-other"
- gem "rails"; gem "rack"
+ gem "rails"; gem "myrack"
G
end
end
context "when gem present in gemfiles but could not be removed from one from one of them" do
it "removes gem which can be removed and shows warning for file from which it cannot be removed" do
- create_file "Gemfile-other", <<-G
- gem "rack"
+ gemfile "Gemfile-other", <<-G
+ gem "myrack"
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
eval_gemfile "Gemfile-other"
- gem"rack"
+ gem"myrack"
G
- bundle "remove rack"
+ bundle "remove myrack"
- expect(out).to include("rack was removed.")
- expect(bundled_app("Gemfile-other").read).to_not include("gem \"rack\"")
+ expect(out).to include("myrack was removed.")
+ expect(bundled_app("Gemfile-other").read).to_not include("gem \"myrack\"")
end
end
end
@@ -597,18 +582,18 @@ RSpec.describe "bundle remove" do
context "with install_if" do
it "removes gems inside blocks and empty blocks" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
install_if(lambda { false }) do
- gem "rack"
+ gem "myrack"
end
G
- bundle "remove rack"
+ bundle "remove myrack"
- expect(out).to include("rack was removed.")
+ expect(out).to include("myrack was removed.")
expect(gemfile).to eq <<~G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
end
end
@@ -616,32 +601,32 @@ RSpec.describe "bundle remove" do
context "with env" do
it "removes gems inside blocks and empty blocks" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
env "BUNDLER_TEST" do
- gem "rack"
+ gem "myrack"
end
G
- bundle "remove rack"
+ bundle "remove myrack"
- expect(out).to include("rack was removed.")
+ expect(out).to include("myrack was removed.")
expect(gemfile).to eq <<~G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
end
end
context "with gemspec" do
it "should not remove the gem" do
- build_lib("foo", path: tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp("foo")) do |s|
s.write("foo.gemspec", "")
- s.add_dependency "rack"
+ s.add_dependency "myrack"
end
install_gemfile(<<-G)
- source "#{file_uri_for(gem_repo1)}"
- gemspec :path => '#{tmp.join("foo")}', :name => 'foo'
+ source "https://gem.repo1"
+ gemspec :path => '#{tmp("foo")}', :name => 'foo'
G
bundle "remove foo"
@@ -654,19 +639,19 @@ RSpec.describe "bundle remove" 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)}"
+ source "https://gem.repo1"
- # gem "rack" might be used in the future
- gem "rack"
+ # gem "myrack" might be used in the future
+ gem "myrack"
G
- bundle "remove rack"
+ bundle "remove myrack"
- expect(out).to include("rack was removed.")
+ expect(out).to include("myrack was removed.")
expect(gemfile).to eq <<~G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- # gem "rack" might be used in the future
+ # gem "myrack" might be used in the future
G
end
end
@@ -674,16 +659,16 @@ RSpec.describe "bundle remove" do
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)}"
+ source "https://gem.repo1"
- gem "rack" # this can be removed
+ gem "myrack" # this can be removed
G
- bundle "remove rack"
+ bundle "remove myrack"
- expect(out).to include("rack was removed.")
+ expect(out).to include("myrack was removed.")
expect(gemfile).to eq <<~G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
end
end
@@ -691,19 +676,19 @@ RSpec.describe "bundle remove" do
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"
+ source "https://gem.repo1"
+ gem "puma" # implements interface provided by gem "myrack"
- gem "rack"
+ gem "myrack"
G
- bundle "remove rack"
+ bundle "remove myrack"
expect(out).to_not include("puma was removed.")
- expect(out).to include("rack was removed.")
+ expect(out).to include("myrack was removed.")
expect(gemfile).to eq <<~G
- source "#{file_uri_for(gem_repo1)}"
- gem "puma" # implements interface provided by gem "rack"
+ source "https://gem.repo1"
+ gem "puma" # implements interface provided by gem "myrack"
G
end
end
@@ -711,22 +696,41 @@ RSpec.describe "bundle remove" do
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"
+ source "https://gem.repo1"
+ gem "puma" # implements interface provided by gem "myrack"
- gem "rack"
+ gem "myrack"
G
bundle "remove puma"
expect(out).to include("puma was removed.")
- expect(out).to_not include("rack was removed.")
+ expect(out).to_not include("myrack was removed.")
expect(gemfile).to eq <<~G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
G
end
end
end
+
+ context "when gem definition has parentheses" do
+ it "removes the gem" do
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ gem("myrack")
+ gem("myrack", ">= 0")
+ gem("myrack", require: false)
+ G
+
+ bundle "remove myrack"
+
+ expect(out).to include("myrack was removed.")
+ expect(gemfile).to eq <<~G
+ source "https://gem.repo1"
+ G
+ end
+ end
end
diff --git a/spec/bundler/commands/show_spec.rb b/spec/bundler/commands/show_spec.rb
index 2b6d4d2d00..34e809f135 100644
--- a/spec/bundler/commands/show_spec.rb
+++ b/spec/bundler/commands/show_spec.rb
@@ -1,10 +1,12 @@
# frozen_string_literal: true
-RSpec.describe "bundle show", bundler: "< 3" do
+RSpec.describe "bundle show" do
context "with a standard Gemfile" do
before :each do
+ build_repo2
+
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo2"
gem "rails"
G
end
@@ -35,12 +37,12 @@ RSpec.describe "bundle show", bundler: "< 3" do
expect(out).to eq(default_bundle_path("gems", "rails-2.3.2").to_s)
end
- it "warns if path no longer exists on disk" do
- FileUtils.rm_rf(default_bundle_path("gems", "rails-2.3.2"))
+ it "warns if specification is installed, but path does not exist on disk" do
+ FileUtils.rm_r(default_bundle_path("gems", "rails-2.3.2"))
bundle "show rails"
- expect(err).to match(/has been deleted/i)
+ expect(err).to match(/is missing/i)
expect(err).to match(default_bundle_path("gems", "rails-2.3.2").to_s)
end
@@ -86,6 +88,24 @@ RSpec.describe "bundle show", bundler: "< 3" do
\tStatus: Up to date
MSG
end
+
+ it "includes up to date status in summary of gems" do
+ update_repo2 do
+ build_gem "rails", "3.0.0"
+ end
+
+ bundle "show --verbose"
+
+ expect(out).to include <<~MSG
+ * rails (2.3.2)
+ \tSummary: This is just a fake gem for testing
+ \tHomepage: http://example.com
+ \tStatus: Outdated - 2.3.2 < 3.0.0
+ MSG
+
+ # check lockfile is not accidentally updated
+ expect(lockfile).to include("actionmailer (2.3.2)")
+ end
end
context "with a git repo in the Gemfile" do
@@ -155,7 +175,7 @@ RSpec.describe "bundle show", bundler: "< 3" do
it "performs an automatic bundle install" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo"
G
@@ -167,20 +187,20 @@ RSpec.describe "bundle show", bundler: "< 3" do
context "with a valid regexp for gem name" do
it "presents alternatives", :readline do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- gem "rack-obama"
+ source "https://gem.repo1"
+ gem "myrack"
+ gem "myrack-obama"
G
bundle "show rac"
- expect(out).to match(/\A1 : rack\n2 : rack-obama\n0 : - exit -(\n>.*)?\z/)
+ expect(out).to match(/\A1 : myrack\n2 : myrack-obama\n0 : - exit -(\n>|\z)/)
end
end
context "with an invalid regexp for gem name" do
it "does not find the gem" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
G
@@ -190,35 +210,8 @@ RSpec.describe "bundle show", bundler: "< 3" do
expect(err).to include("Could not find gem '#{invalid_regexp}'.")
end
end
-
- context "--outdated option" do
- # 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
- source "#{file_uri_for(gem_repo2)}"
- gem "rails"
- G
-
- expect(the_bundle).to include_gem("rails 2.3.2")
-
- update_repo2 do
- build_gem "rails", "3.0.0" do |s|
- s.executables = "rails"
- end
- end
-
- bundle "show --outdated"
-
- bundle "install"
- expect(the_bundle).to include_gem("rails 2.3.2")
- end
- end
end
-RSpec.describe "bundle show", bundler: "3" do
+RSpec.describe "bundle show", bundler: "5" do
pending "shows a friendly error about the command removal"
end
diff --git a/spec/bundler/commands/ssl_spec.rb b/spec/bundler/commands/ssl_spec.rb
new file mode 100644
index 0000000000..4220731b69
--- /dev/null
+++ b/spec/bundler/commands/ssl_spec.rb
@@ -0,0 +1,373 @@
+# frozen_string_literal: true
+
+require "bundler/cli"
+require "bundler/cli/doctor"
+require "bundler/cli/doctor/ssl"
+require_relative "../support/artifice/helpers/artifice"
+require "bundler/vendored_persistent.rb"
+
+RSpec.describe "bundle doctor ssl" do
+ before(:each) do
+ require_rack_test
+ require_relative "../support/artifice/helpers/endpoint"
+
+ @dummy_endpoint = Class.new(Endpoint) do
+ get "/" do
+ end
+ end
+
+ @previous_ui = Bundler.ui
+ Bundler.ui = Bundler::UI::Shell.new
+ Bundler.ui.level = "info"
+
+ @previous_client = Gem::Request::ConnectionPools.client
+ Artifice.activate_with(@dummy_endpoint)
+ Gem::Request::ConnectionPools.client = Gem::Net::HTTP
+ end
+
+ after(:each) do
+ Bundler.ui = @previous_ui
+ Artifice.deactivate
+ Gem::Request::ConnectionPools.client = @previous_client
+ end
+
+ context "when a diagnostic fails" do
+ it "prints the diagnostic when openssl can't be loaded" do
+ subject = Bundler::CLI::Doctor::SSL.new({})
+ allow(subject).to receive(:require).with("openssl").and_raise(LoadError)
+
+ expected_err = <<~MSG
+ Oh no! Your Ruby doesn't have OpenSSL, so it can't connect to rubygems.org.
+ You'll need to recompile or reinstall Ruby with OpenSSL support and try again.
+ MSG
+
+ expect { subject.run }.to output("").to_stdout.and output(expected_err).to_stderr
+ end
+
+ it "fails due to certificate verification", :ruby_repo do
+ net_http = Class.new(Artifice::Net::HTTP) do
+ def connect
+ raise OpenSSL::SSL::SSLError, "certificate verify failed"
+ end
+ end
+
+ Artifice.replace_net_http(net_http)
+ Gem::Request::ConnectionPools.client = net_http
+ Gem::RemoteFetcher.fetcher.close_all
+
+ expected_out = <<~MSG
+ Here's your OpenSSL environment:
+
+ OpenSSL: #{OpenSSL::VERSION}
+ Compiled with: #{OpenSSL::OPENSSL_VERSION}
+ Loaded with: #{OpenSSL::OPENSSL_LIBRARY_VERSION}
+
+ Trying connections to https://rubygems.org:
+ MSG
+
+ expected_err = <<~MSG
+ Bundler: failed (certificate verification)
+ RubyGems: failed (certificate verification)
+ Ruby net/http: failed
+
+ Unfortunately, this Ruby can't connect to rubygems.org.
+
+ Below affect only Ruby net/http connections:
+ SSL_CERT_FILE: exists #{OpenSSL::X509::DEFAULT_CERT_FILE}
+ SSL_CERT_DIR: exists #{OpenSSL::X509::DEFAULT_CERT_DIR}
+
+ Your Ruby can't connect to rubygems.org because you are missing the certificate files OpenSSL needs to verify you are connecting to the genuine rubygems.org servers.
+
+ MSG
+
+ subject = Bundler::CLI::Doctor::SSL.new({})
+ expect { subject.run }.to output(expected_out).to_stdout.and output(expected_err).to_stderr
+ end
+
+ it "fails due to a too old tls version" do
+ subject = Bundler::CLI::Doctor::SSL.new({})
+
+ net_http = Class.new(Artifice::Net::HTTP) do
+ def connect
+ raise OpenSSL::SSL::SSLError, "read server hello A"
+ end
+ end
+
+ Artifice.replace_net_http(net_http)
+ Gem::Request::ConnectionPools.client = Gem::Net::HTTP
+ Gem::RemoteFetcher.fetcher.close_all
+
+ expected_out = <<~MSG
+ Here's your OpenSSL environment:
+
+ OpenSSL: #{OpenSSL::VERSION}
+ Compiled with: #{OpenSSL::OPENSSL_VERSION}
+ Loaded with: #{OpenSSL::OPENSSL_LIBRARY_VERSION}
+
+ Trying connections to https://rubygems.org:
+ MSG
+
+ expected_err = <<~MSG
+ Bundler: failed (SSL/TLS protocol version mismatch)
+ RubyGems: failed (SSL/TLS protocol version mismatch)
+ Ruby net/http: failed
+
+ Unfortunately, this Ruby can't connect to rubygems.org.
+
+ Your Ruby can't connect to rubygems.org because your version of OpenSSL is too old.
+ You'll need to upgrade your OpenSSL install and/or recompile Ruby to use a newer OpenSSL.
+
+ MSG
+
+ expect { subject.run }.to output(expected_out).to_stdout.and output(expected_err).to_stderr
+ end
+
+ it "fails due to unsupported tls 1.3 version" do
+ net_http = Class.new(Artifice::Net::HTTP) do
+ def connect
+ raise OpenSSL::SSL::SSLError, "read server hello A"
+ end
+ end
+
+ Artifice.replace_net_http(net_http)
+ Gem::Request::ConnectionPools.client = net_http
+ Gem::RemoteFetcher.fetcher.close_all
+
+ expected_out = <<~MSG
+ Here's your OpenSSL environment:
+
+ OpenSSL: #{OpenSSL::VERSION}
+ Compiled with: #{OpenSSL::OPENSSL_VERSION}
+ Loaded with: #{OpenSSL::OPENSSL_LIBRARY_VERSION}
+
+ Trying connections to https://rubygems.org:
+ MSG
+
+ expected_err = <<~MSG
+ Bundler: failed (SSL/TLS protocol version mismatch)
+ RubyGems: failed (SSL/TLS protocol version mismatch)
+ Ruby net/http: failed
+
+ Unfortunately, this Ruby can't connect to rubygems.org.
+
+ Your Ruby can't connect to rubygems.org because TLS1_3 isn't supported yet.
+
+ MSG
+
+ subject = Bundler::CLI::Doctor::SSL.new("tls-version": "1.3")
+ expect { subject.run }.to output(expected_out).to_stdout.and output(expected_err).to_stderr
+ end
+
+ it "fails due to a bundler and rubygems connection error" do
+ endpoint = Class.new(Endpoint) do
+ get "/" do
+ raise OpenSSL::SSL::SSLError, "read server hello A"
+ end
+ end
+
+ Artifice.activate_with(endpoint)
+ Gem::Request::ConnectionPools.client = Gem::Net::HTTP
+
+ expected_out = <<~MSG
+ Here's your OpenSSL environment:
+
+ OpenSSL: #{OpenSSL::VERSION}
+ Compiled with: #{OpenSSL::OPENSSL_VERSION}
+ Loaded with: #{OpenSSL::OPENSSL_LIBRARY_VERSION}
+
+ Trying connections to https://rubygems.org:
+ Ruby net/http: success
+
+ For some reason, your Ruby installation can connect to rubygems.org, but neither RubyGems nor Bundler can.
+ The most likely fix is to manually upgrade RubyGems by following the instructions at http://ruby.to/ssl-check-failed.
+ After you've done that, run `gem install bundler` to upgrade Bundler, and then run this script again to make sure everything worked. ❣
+
+ MSG
+
+ expected_err = <<~MSG
+ Bundler: failed (SSL/TLS protocol version mismatch)
+ RubyGems: failed (SSL/TLS protocol version mismatch)
+ MSG
+
+ subject = Bundler::CLI::Doctor::SSL.new({})
+ expect { subject.run }.to output(expected_out).to_stdout.and output(expected_err).to_stderr
+ end
+
+ it "fails due to a bundler connection error" do
+ endpoint = Class.new(Endpoint) do
+ get "/" do
+ if request.user_agent.include?("bundler")
+ raise OpenSSL::SSL::SSLError, "read server hello A"
+ end
+ end
+ end
+
+ Artifice.activate_with(endpoint)
+ Gem::Request::ConnectionPools.client = Gem::Net::HTTP
+
+ expected_out = <<~MSG
+ Here's your OpenSSL environment:
+
+ OpenSSL: #{OpenSSL::VERSION}
+ Compiled with: #{OpenSSL::OPENSSL_VERSION}
+ Loaded with: #{OpenSSL::OPENSSL_LIBRARY_VERSION}
+
+ Trying connections to https://rubygems.org:
+ RubyGems: success
+ Ruby net/http: success
+
+ Although your Ruby installation and RubyGems can both connect to rubygems.org, Bundler is having trouble.
+ The most likely way to fix this is to upgrade Bundler by running `gem install bundler`.
+ Run this script again after doing that to make sure everything is all set.
+ If you're still having trouble, check out the troubleshooting guide at http://ruby.to/ssl-check-failed.
+
+ MSG
+
+ expected_err = <<~MSG
+ Bundler: failed (SSL/TLS protocol version mismatch)
+ MSG
+
+ subject = Bundler::CLI::Doctor::SSL.new({})
+ expect { subject.run }.to output(expected_out).to_stdout.and output(expected_err).to_stderr
+ end
+
+ it "fails due to a RubyGems connection error" do
+ endpoint = Class.new(Endpoint) do
+ get "/" do
+ if request.user_agent.include?("Ruby, RubyGems")
+ raise OpenSSL::SSL::SSLError, "read server hello A"
+ end
+ end
+ end
+
+ Artifice.activate_with(endpoint)
+ Gem::Request::ConnectionPools.client = Gem::Net::HTTP
+
+ expected_out = <<~MSG
+ Here's your OpenSSL environment:
+
+ OpenSSL: #{OpenSSL::VERSION}
+ Compiled with: #{OpenSSL::OPENSSL_VERSION}
+ Loaded with: #{OpenSSL::OPENSSL_LIBRARY_VERSION}
+
+ Trying connections to https://rubygems.org:
+ Bundler: success
+ Ruby net/http: success
+
+ It looks like Ruby and Bundler can connect to rubygems.org, but RubyGems itself cannot.
+ You can likely solve this by manually downloading and installing a RubyGems update.
+ Visit http://ruby.to/ssl-check-failed for instructions on how to manually upgrade RubyGems.
+
+ MSG
+
+ expected_err = <<~MSG
+ RubyGems: failed (SSL/TLS protocol version mismatch)
+ MSG
+
+ subject = Bundler::CLI::Doctor::SSL.new({})
+ expect { subject.run }.to output(expected_out).to_stdout.and output(expected_err).to_stderr
+ end
+ end
+
+ context "when no diagnostic fails" do
+ it "prints the SSL environment" do
+ expected_out = <<~MSG
+ Here's your OpenSSL environment:
+
+ OpenSSL: #{OpenSSL::VERSION}
+ Compiled with: #{OpenSSL::OPENSSL_VERSION}
+ Loaded with: #{OpenSSL::OPENSSL_LIBRARY_VERSION}
+
+ Trying connections to https://rubygems.org:
+ Bundler: success
+ RubyGems: success
+ Ruby net/http: success
+
+ Hooray! This Ruby can connect to rubygems.org.
+ You are all set to use Bundler and RubyGems.
+
+ MSG
+
+ subject = Bundler::CLI::Doctor::SSL.new({})
+ expect { subject.run }.to output(expected_out).to_stdout.and output("").to_stderr
+ end
+
+ it "uses the tls_version verify mode and host when given as option" do
+ net_http = Class.new(Artifice::Net::HTTP) do
+ class << self
+ attr_accessor :verify_mode, :min_version, :max_version
+ end
+
+ def connect
+ self.class.verify_mode = verify_mode
+ self.class.min_version = min_version
+ self.class.max_version = max_version
+
+ super
+ end
+ end
+
+ net_http.endpoint = @dummy_endpoint
+ Artifice.replace_net_http(net_http)
+ Gem::Request::ConnectionPools.client = net_http
+ Gem::RemoteFetcher.fetcher.close_all
+
+ expected_out = <<~MSG
+ Here's your OpenSSL environment:
+
+ OpenSSL: #{OpenSSL::VERSION}
+ Compiled with: #{OpenSSL::OPENSSL_VERSION}
+ Loaded with: #{OpenSSL::OPENSSL_LIBRARY_VERSION}
+
+ Trying connections to https://example.org:
+ Bundler: success
+ RubyGems: success
+ Ruby net/http: success
+
+ Hooray! This Ruby can connect to example.org.
+ You are all set to use Bundler and RubyGems.
+
+ MSG
+
+ subject = Bundler::CLI::Doctor::SSL.new("tls-version": "1.3", "verify-mode": :none, host: "example.org")
+ expect { subject.run }.to output(expected_out).to_stdout.and output("").to_stderr
+ expect(net_http.verify_mode).to eq(0)
+ expect(net_http.min_version.to_s).to eq("TLS1_3")
+ expect(net_http.max_version.to_s).to eq("TLS1_3")
+ end
+
+ it "warns when TLS1.2 is not supported" do
+ expected_out = <<~MSG
+ Here's your OpenSSL environment:
+
+ OpenSSL: #{OpenSSL::VERSION}
+ Compiled with: #{OpenSSL::OPENSSL_VERSION}
+ Loaded with: #{OpenSSL::OPENSSL_LIBRARY_VERSION}
+
+ Trying connections to https://rubygems.org:
+ Bundler: success
+ RubyGems: success
+ Ruby net/http: success
+
+ Hooray! This Ruby can connect to rubygems.org.
+ You are all set to use Bundler and RubyGems.
+
+ MSG
+
+ expected_err = <<~MSG
+
+ WARNING: Although your Ruby can connect to rubygems.org today, your OpenSSL is very old!
+ WARNING: You will need to upgrade OpenSSL to use rubygems.org.
+
+ MSG
+
+ previous_version = OpenSSL::SSL::TLS1_2_VERSION
+ OpenSSL::SSL.send(:remove_const, :TLS1_2_VERSION)
+
+ subject = Bundler::CLI::Doctor::SSL.new({})
+ expect { subject.run }.to output(expected_out).to_stdout.and output(expected_err).to_stderr
+ ensure
+ OpenSSL::SSL.const_set(:TLS1_2_VERSION, previous_version)
+ end
+ end
+end
diff --git a/spec/bundler/commands/update_spec.rb b/spec/bundler/commands/update_spec.rb
index d5d38b81f1..cdaeb75c4a 100644
--- a/spec/bundler/commands/update_spec.rb
+++ b/spec/bundler/commands/update_spec.rb
@@ -6,17 +6,17 @@ RSpec.describe "bundle update" do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport"
- gem "rack-obama"
+ gem "myrack-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"
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
end
build_gem "activesupport", "3.0"
@@ -24,14 +24,14 @@ RSpec.describe "bundle update" do
bundle "update"
expect(out).to include("Bundle updated!")
- expect(the_bundle).to include_gems "rack 1.2", "rack-obama 1.0", "activesupport 3.0"
+ expect(the_bundle).to include_gems "myrack 1.2", "myrack-obama 1.0", "activesupport 3.0"
end
it "doesn't delete the Gemfile.lock file if something goes wrong" do
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport"
- gem "rack-obama"
+ gem "myrack-obama"
exit!
G
bundle "update", raise_on_error: false
@@ -39,22 +39,39 @@ RSpec.describe "bundle update" do
end
end
+ describe "with --verbose" do
+ before do
+ build_repo2
+
+ install_gemfile <<~G
+ source "https://gem.repo2"
+ gem "myrack"
+ G
+ end
+
+ it "logs the reason for re-resolving" do
+ bundle "update --verbose"
+ expect(out).not_to include("Found changes from the lockfile")
+ expect(out).to include("Re-resolving dependencies because bundler is unlocking")
+ end
+ end
+
describe "with --all" do
before do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport"
- gem "rack-obama"
+ gem "myrack-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"
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
end
build_gem "activesupport", "3.0"
@@ -62,16 +79,16 @@ RSpec.describe "bundle update" do
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"
+ expect(the_bundle).to include_gems "myrack 1.2", "myrack-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)}\""
+ install_gemfile "source 'https://gem.repo1'"
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport"
- gem "rack-obama"
+ gem "myrack-obama"
exit!
G
bundle "update", all: true, raise_on_error: false
@@ -80,10 +97,10 @@ RSpec.describe "bundle update" do
end
describe "with --gemfile" do
- it "creates lock files based on the Gemfile name" do
+ it "creates lockfiles based on the Gemfile name" do
gemfile bundled_app("OmgFile"), <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "1.0"
+ source "https://gem.repo1"
+ gem "myrack", "1.0"
G
bundle "update --gemfile OmgFile", all: true
@@ -96,19 +113,19 @@ RSpec.describe "bundle update" do
before { bundle "config set update_requires_all_flag true" }
it "errors when passed nothing" do
- install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
+ install_gemfile "source 'https://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 "source \"#{file_uri_for(gem_repo1)}\""
+ install_gemfile "source 'https://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 "source \"#{file_uri_for(gem_repo1)}\""
+ install_gemfile "source 'https://gem.repo1'"
bundle "update --all"
expect(out).to include("Bundle updated!")
end
@@ -119,9 +136,9 @@ RSpec.describe "bundle update" do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport"
- gem "rack-obama"
+ gem "myrack-obama"
gem "platform_specific"
G
end
@@ -137,24 +154,24 @@ RSpec.describe "bundle update" do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport"
- gem "rack-obama"
+ gem "myrack-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"
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
end
build_gem "activesupport", "3.0"
end
- bundle "update rack-obama"
- expect(the_bundle).to include_gems "rack 1.2", "rack-obama 1.0", "activesupport 2.3.5"
+ bundle "update myrack-obama"
+ expect(the_bundle).to include_gems "myrack 1.2", "myrack-obama 1.0", "activesupport 2.3.5"
end
end
@@ -163,9 +180,9 @@ RSpec.describe "bundle update" do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport"
- gem "rack-obama"
+ gem "myrack-obama"
gem "platform_specific"
G
end
@@ -176,7 +193,7 @@ RSpec.describe "bundle update" do
end
it "should suggest alternatives" do
bundle "update platformspecific", raise_on_error: false
- expect(err).to include "Did you mean platform_specific?"
+ expect(err).to include "Did you mean 'platform_specific'?"
end
end
@@ -185,22 +202,22 @@ RSpec.describe "bundle update" do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport"
- gem "rack-obama"
+ gem "myrack-obama"
gem "platform_specific"
G
end
it "should update the child dependency" do
update_repo2 do
- build_gem "rack", "1.2" do |s|
- s.executables = "rackup"
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
end
end
- bundle "update rack"
- expect(the_bundle).to include_gems "rack 1.2"
+ bundle "update myrack"
+ expect(the_bundle).to include_gems "myrack 1.2"
end
end
@@ -223,14 +240,14 @@ RSpec.describe "bundle update" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://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_repo4 do
build_gem "slim", "4.0.0" do |s|
s.add_dependency "tilt", [">= 2.0.6", "< 2.1"]
end
@@ -269,20 +286,20 @@ RSpec.describe "bundle update" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "country_select"
gem "countries"
G
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum(gem_repo4, "countries", "3.1.0")
c.checksum(gem_repo4, "country_select", "5.1.0")
end
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
countries (3.1.0)
country_select (5.1.0)
@@ -296,7 +313,7 @@ RSpec.describe "bundle update" do
country_select
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
previous_lockfile = lockfile
@@ -331,7 +348,7 @@ RSpec.describe "bundle update" do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "oauth2"
gem "quickbooks-ruby"
@@ -339,7 +356,7 @@ RSpec.describe "bundle update" do
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
faraday (2.5.2)
multi_json (1.15.0)
@@ -357,7 +374,7 @@ RSpec.describe "bundle update" do
quickbooks-ruby
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "update --conservative --verbose"
@@ -390,7 +407,7 @@ RSpec.describe "bundle update" do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gemspec
@@ -404,7 +421,7 @@ RSpec.describe "bundle update" do
specs:
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
rake (13.0.6)
sneakers (2.11.0)
@@ -418,7 +435,7 @@ RSpec.describe "bundle update" do
sneakers
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "update --verbose"
@@ -428,6 +445,115 @@ RSpec.describe "bundle update" do
expect(out).to include("Installing sneakers 2.11.0").and include("Installing rake 13.0.6")
end
+ it "downgrades indirect dependencies if required to fulfill an explicit upgrade request" do
+ build_repo4 do
+ build_gem "rbs", "3.6.1"
+ build_gem "rbs", "3.9.4"
+
+ build_gem "solargraph", "0.56.0" do |s|
+ s.add_dependency "rbs", "~> 3.3"
+ end
+
+ build_gem "solargraph", "0.56.2" do |s|
+ s.add_dependency "rbs", "~> 3.6.1"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem 'solargraph', '~> 0.56.0'
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ rbs (3.9.4)
+ solargraph (0.56.0)
+ rbs (~> 3.3)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ solargraph (~> 0.56.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock --update solargraph"
+
+ expect(lockfile).to include("solargraph (0.56.2)")
+ end
+
+ it "does not downgrade direct dependencies unnecessarily" do
+ build_repo4 do
+ build_gem "redis", "4.8.1"
+ build_gem "redis", "5.3.0"
+
+ build_gem "sidekiq", "6.5.5" do |s|
+ s.add_dependency "redis", ">= 4.5.0"
+ end
+
+ build_gem "sidekiq", "6.5.12" do |s|
+ s.add_dependency "redis", ">= 4.5.0", "< 5"
+ end
+
+ # one version of sidekiq above Gemfile's range is needed to make the
+ # resolver choose `redis` first and trying to upgrade it, reproducing
+ # the accidental sidekiq downgrade as a result
+ build_gem "sidekiq", "7.0.0 " do |s|
+ s.add_dependency "redis", ">= 4.2.0"
+ end
+
+ build_gem "sentry-sidekiq", "5.22.0" do |s|
+ s.add_dependency "sidekiq", ">= 3.0"
+ end
+
+ build_gem "sentry-sidekiq", "5.22.4" do |s|
+ s.add_dependency "sidekiq", ">= 3.0"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "redis"
+ gem "sidekiq", "~> 6.5"
+ gem "sentry-sidekiq"
+ G
+
+ original_lockfile = <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ redis (4.8.1)
+ sentry-sidekiq (5.22.0)
+ sidekiq (>= 3.0)
+ sidekiq (6.5.12)
+ redis (>= 4.5.0, < 5)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ redis
+ sentry-sidekiq
+ sidekiq (~> 6.5)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ lockfile original_lockfile
+
+ bundle "lock --update sentry-sidekiq"
+
+ expect(lockfile).to eq(original_lockfile.sub("sentry-sidekiq (5.22.0)", "sentry-sidekiq (5.22.4)"))
+ end
+
it "does not downgrade indirect dependencies unnecessarily" do
build_repo4 do
build_gem "a" do |s|
@@ -440,13 +566,13 @@ RSpec.describe "bundle update" do
end
install_gemfile <<-G, verbose: true
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "a"
G
expect(the_bundle).to include_gems("a 1.0", "b 1.0", "c 2.0")
- update_repo4 do
+ build_repo4 do
build_gem "b", "2.0" do |s|
s.add_dependency "c", "< 2"
end
@@ -464,7 +590,7 @@ RSpec.describe "bundle update" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "a"
gem "b"
G
@@ -472,7 +598,7 @@ RSpec.describe "bundle update" do
expect(the_bundle).to include_gems("a 1.0", "b 2.0")
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "a"
gem "b", "1.0"
G
@@ -497,27 +623,27 @@ RSpec.describe "bundle update" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://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)}"
+ source "https://gem.repo4"
gem "activesupport", "~> 6.0.0"
G
original_lockfile = lockfile
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo4, "activesupport", "6.0.4.1"
c.checksum gem_repo4, "tzinfo", "1.2.9"
end
expected_lockfile = <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
activesupport (6.0.4.1)
tzinfo (~> 1.1)
@@ -530,17 +656,13 @@ RSpec.describe "bundle update" do
activesupport (~> 6.0.0)
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{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)
- # needed because regressing to versions already present on the system
- # won't add a checksum
- expected_lockfile = remove_checksums_from_lockfile(expected_lockfile)
-
lockfile original_lockfile
bundle "update"
expect(the_bundle).to include_gems("activesupport 6.0.4.1", "tzinfo 1.2.9")
@@ -558,42 +680,44 @@ RSpec.describe "bundle update" do
build_repo2
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport"
- gem "rack-obama"
+ gem "myrack-obama"
gem "platform_specific"
G
-
- lockfile <<~L
- GEM
- remote: #{file_uri_for(gem_repo2)}/
- specs:
- activesupport (2.3.5)
- platform_specific (1.0-#{local_platform})
- rack (1.0.0)
- rack-obama (1.0)
- rack
-
- PLATFORMS
- #{local_platform}
-
- DEPENDENCIES
- activesupport
- platform_specific
- rack-obama
-
- BUNDLED WITH
- #{Bundler::VERSION}
- L
-
- bundle "install"
end
it "doesn't hit repo2" do
- FileUtils.rm_rf(gem_repo2)
-
- bundle "update --local --all"
- expect(out).not_to include("Fetching source index")
+ simulate_platform "x86-darwin-100" do
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ activesupport (2.3.5)
+ platform_specific (1.0-x86-darwin-100)
+ myrack (1.0.0)
+ myrack-obama (1.0)
+ myrack
+
+ PLATFORMS
+ x86-darwin-100
+
+ DEPENDENCIES
+ activesupport
+ platform_specific
+ myrack-obama
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install"
+
+ FileUtils.rm_r(gem_repo2)
+
+ bundle "update --local --all"
+ expect(out).not_to include("Fetching source index")
+ end
end
end
@@ -604,26 +728,26 @@ RSpec.describe "bundle update" do
it "should update only specified group gems" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport", :group => :development
- gem "rack"
+ gem "myrack"
G
update_repo2 do
- build_gem "rack", "1.2" do |s|
- s.executables = "rackup"
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
end
build_gem "activesupport", "3.0"
end
bundle "update --group development"
expect(the_bundle).to include_gems "activesupport 3.0"
- expect(the_bundle).not_to include_gems "rack 1.2"
+ expect(the_bundle).not_to include_gems "myrack 1.2"
end
context "when conservatively updating a group with non-group sub-deps" do
it "should update only specified group gems" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activemerchant", :group => :development
gem "activesupport"
G
@@ -641,7 +765,7 @@ RSpec.describe "bundle update" do
before do
build_git "foo", path: lib_path("activesupport")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport", :group => :development
gem "foo", :git => "#{lib_path("activesupport")}"
G
@@ -660,13 +784,13 @@ RSpec.describe "bundle update" do
context "when bundler itself is a transitive dependency" do
it "executes without error" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "activesupport", :group => :development
- gem "rack"
+ gem "myrack"
G
update_repo2 do
- build_gem "rack", "1.2" do |s|
- s.executables = "rackup"
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
end
build_gem "activesupport", "3.0"
@@ -674,7 +798,7 @@ RSpec.describe "bundle update" do
bundle "update --group development"
expect(the_bundle).to include_gems "activesupport 2.3.5"
expect(the_bundle).to include_gems "bundler #{Bundler::VERSION}"
- expect(the_bundle).not_to include_gems "rack 1.2"
+ expect(the_bundle).not_to include_gems "myrack 1.2"
end
end
end
@@ -684,40 +808,48 @@ RSpec.describe "bundle update" do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport"
- gem "rack-obama"
+ gem "myrack-obama"
gem "platform_specific"
G
end
- it "should fail loudly", bundler: "< 3" do
- bundle "install --deployment"
+ it "should fail loudly" do
+ bundle "config deployment true"
bundle "update", all: true, raise_on_error: false
expect(last_command).to be_failure
- expect(err).to match(/Bundler is unlocking, but the lockfile can't be updated because frozen mode is set/)
- expect(err).to match(/freeze by running `bundle config set frozen false`./)
+ expect(err).to eq <<~ERROR.strip
+ Bundler is unlocking, but the lockfile can't be updated because frozen mode is set
+
+ If this is a development machine, remove the Gemfile.lock freeze by running `bundle config set frozen false`.
+ ERROR
end
it "should fail loudly when frozen is set globally" do
bundle "config set --global frozen 1"
bundle "update", all: true, raise_on_error: false
- expect(err).to match(/Bundler is unlocking, but the lockfile can't be updated because frozen mode is set/).
- and match(/freeze by running `bundle config set frozen false`./)
+ expect(err).to eq <<~ERROR.strip
+ Bundler is unlocking, but the lockfile can't be updated because frozen mode is set
+
+ If this is a development machine, remove the Gemfile.lock freeze by running `bundle config set frozen false`.
+ ERROR
end
it "should fail loudly when deployment is set globally" do
bundle "config set --global deployment true"
bundle "update", all: true, raise_on_error: false
- expect(err).to match(/Bundler is unlocking, but the lockfile can't be updated because frozen mode is set/).
- and match(/freeze by running `bundle config set frozen false`./)
+ expect(err).to eq <<~ERROR.strip
+ Bundler is unlocking, but the lockfile can't be updated because frozen mode is set
+
+ If this is a development machine, remove the Gemfile.lock freeze by running `bundle config set frozen false`.
+ ERROR
end
it "should not suggest any command to unfreeze bundler if frozen is set through ENV" do
bundle "update", all: true, raise_on_error: false, env: { "BUNDLE_FROZEN" => "true" }
- expect(err).to match(/Bundler is unlocking, but the lockfile can't be updated because frozen mode is set/)
- expect(err).not_to match(/by running/)
+ expect(err).to eq("Bundler is unlocking, but the lockfile can't be updated because frozen mode is set")
end
end
@@ -728,7 +860,7 @@ RSpec.describe "bundle update" do
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)}"
+ source "https://gem.repo2"
gem "activesupport"
G
update_repo2 { build_gem "activesupport", "3.0" }
@@ -739,7 +871,7 @@ RSpec.describe "bundle update" do
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)}"
+ source "https://gem.repo2"
gem "activesupport"
G
update_repo2 { build_gem "activesupport", "3.0" }
@@ -759,7 +891,7 @@ RSpec.describe "bundle update" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "harry"
gem "fred"
G
@@ -791,7 +923,7 @@ RSpec.describe "bundle update" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "harry"
gem "fred"
G
@@ -814,7 +946,7 @@ RSpec.describe "bundle update" do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport"
G
@@ -836,7 +968,7 @@ RSpec.describe "bundle update" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "bar"
gem "foo"
G
@@ -844,7 +976,7 @@ RSpec.describe "bundle update" do
bundle "update", all: true
expect(out).to match(/Resolving dependencies\.\.\.\.*\nBundle updated!/)
- update_repo4 do
+ build_repo4 do
build_gem "foo", "2.0"
end
@@ -854,7 +986,7 @@ RSpec.describe "bundle update" do
it "shows error message when Gemfile.lock is not preset and gem is specified" do
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activesupport"
G
@@ -866,10 +998,10 @@ RSpec.describe "bundle update" do
context "with multiple sources and caching enabled" do
before do
build_repo2 do
- build_gem "rack", "1.0.0"
+ build_gem "myrack", "1.0.0"
build_gem "request_store", "1.0.0" do |s|
- s.add_dependency "rack", "1.0.0"
+ s.add_dependency "myrack", "1.0.0"
end
end
@@ -878,24 +1010,24 @@ RSpec.describe "bundle update" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "request_store"
- source "#{file_uri_for(gem_repo4)}" do
+ source "https://gem.repo4" do
end
G
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
request_store (1.0.0)
- rack (= 1.0.0)
+ myrack (= 1.0.0)
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
PLATFORMS
@@ -905,7 +1037,7 @@ RSpec.describe "bundle update" do
request_store
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
@@ -915,7 +1047,7 @@ RSpec.describe "bundle update" do
update_repo2 do
build_gem "request_store", "1.1.0" do |s|
- s.add_dependency "rack", "1.0.0"
+ s.add_dependency "myrack", "1.0.0"
end
end
@@ -925,14 +1057,14 @@ RSpec.describe "bundle update" do
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
request_store (1.1.0)
- rack (= 1.0.0)
+ myrack (= 1.0.0)
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
PLATFORMS
@@ -942,71 +1074,9 @@ RSpec.describe "bundle update" do
request_store
BUNDLED WITH
- #{Bundler::VERSION}
- L
- end
- 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
-
- 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
- #{local_platform}
-
- DEPENDENCIES
- dotenv
- pkg-gem-flowbyte-with-dep!
- vcr!
-
- BUNDLED WITH
- #{Bundler::VERSION}
+ #{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
@@ -1017,49 +1087,49 @@ RSpec.describe "bundle update in more complicated situations" do
it "will eagerly unlock dependencies of a specified gem" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "thin"
- gem "rack-obama"
+ gem "myrack-obama"
G
update_repo2 do
- build_gem "rack", "1.2" do |s|
- s.executables = "rackup"
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
end
build_gem "thin", "2.0" do |s|
- s.add_dependency "rack"
+ s.add_dependency "myrack"
end
end
bundle "update thin"
- expect(the_bundle).to include_gems "thin 2.0", "rack 1.2", "rack-obama 1.0"
+ expect(the_bundle).to include_gems "thin 2.0", "myrack 1.2", "myrack-obama 1.0"
end
it "will warn when some explicitly updated gems are not updated" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "thin"
- gem "rack-obama"
+ gem "myrack-obama"
G
update_repo2 do
- build_gem("thin", "2.0") {|s| s.add_dependency "rack" }
- build_gem "rack", "10.0"
+ build_gem("thin", "2.0") {|s| s.add_dependency "myrack" }
+ build_gem "myrack", "10.0"
end
- 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"
+ bundle "update thin myrack-obama"
+ expect(stdboth).to include "Bundler attempted to update myrack-obama but its version stayed the same"
+ expect(the_bundle).to include_gems "thin 2.0", "myrack 10.0", "myrack-obama 1.0"
end
it "will not warn when an explicitly updated git gem changes sha but not version" do
build_git "foo"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => '#{lib_path("foo-1.0")}'
G
@@ -1069,32 +1139,32 @@ RSpec.describe "bundle update in more complicated situations" do
bundle "update foo"
- expect(last_command.stdboth).not_to include "attempted to update"
+ expect(stdboth).not_to include "attempted to update"
end
it "will not warn when changing gem sources but not versions" do
- build_git "rack"
+ build_git "myrack"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack", :git => '#{lib_path("rack-1.0")}'
+ source "https://gem.repo2"
+ gem "myrack", :git => '#{lib_path("myrack-1.0")}'
G
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "update rack"
+ bundle "update myrack"
- expect(last_command.stdboth).not_to include "attempted to update"
+ expect(stdboth).not_to include "attempted to update"
end
it "will update only from pinned source" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
- source "#{file_uri_for(gem_repo1)}" do
+ source "https://gem.repo1" do
gem "thin"
end
G
@@ -1103,12 +1173,12 @@ RSpec.describe "bundle update in more complicated situations" do
build_gem "thin", "2.0"
end
- bundle "update"
+ bundle "update", artifice: "compact_index"
expect(the_bundle).to include_gems "thin 1.0"
end
context "when the lockfile is for a different platform" do
- before do
+ around do |example|
build_repo4 do
build_gem("a", "0.9")
build_gem("a", "0.9") {|s| s.platform = "java" }
@@ -1117,13 +1187,13 @@ RSpec.describe "bundle update in more complicated situations" do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "a"
G
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo4)}
+ remote: https://gem.repo4
specs:
a (0.9-java)
@@ -1134,7 +1204,7 @@ RSpec.describe "bundle update in more complicated situations" do
a
L
- simulate_platform linux
+ simulate_platform "x86_64-linux", &example
end
it "allows updating" do
@@ -1156,13 +1226,13 @@ RSpec.describe "bundle update in more complicated situations" do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "a", platform: :jruby
G
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo4)}
+ remote: https://gem.repo4
specs:
a (0.9-java)
@@ -1172,14 +1242,14 @@ RSpec.describe "bundle update in more complicated situations" do
DEPENDENCIES
a
L
-
- simulate_platform linux
end
it "is not updated because it is not actually included in the bundle" do
- 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"
+ simulate_platform "x86_64-linux" do
+ bundle "update a"
+ expect(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
end
end
end
@@ -1189,14 +1259,14 @@ RSpec.describe "bundle update without a Gemfile.lock" do
build_repo2
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
- gem "rack", "1.0"
+ gem "myrack", "1.0"
G
bundle "update", all: true
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
@@ -1204,23 +1274,23 @@ RSpec.describe "bundle update when a gem depends on a newer version of bundler"
before do
build_repo2 do
build_gem "rails", "3.0.1" do |s|
- s.add_dependency "bundler", Bundler::VERSION.succ
+ s.add_dependency "bundler", "9.9.9"
end
- build_gem "bundler", Bundler::VERSION.succ
+ build_gem "bundler", "9.9.9"
end
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "rails", "3.0.1"
G
end
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(stdboth).not_to match(/in snapshot/i)
expect(err).to match(/current Bundler version/i).
- and match(/Install the necessary version with `gem install bundler:#{Bundler::VERSION.succ}`/i)
+ and match(/Install the necessary version with `gem install bundler:9\.9\.9`/i)
end
end
@@ -1229,11 +1299,11 @@ RSpec.describe "bundle update --ruby" do
before do
install_gemfile <<-G
ruby '~> #{Gem.ruby_version}'
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
end
@@ -1242,16 +1312,16 @@ RSpec.describe "bundle update --ruby" do
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
-
+ #{checksums_section_when_enabled}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
@@ -1260,12 +1330,12 @@ RSpec.describe "bundle update --ruby" do
before do
install_gemfile <<-G
ruby '~> #{Gem.ruby_version}'
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
gemfile <<-G
ruby '~> #{current_ruby_minor}'
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
end
@@ -1274,19 +1344,19 @@ RSpec.describe "bundle update --ruby" do
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
-
+ #{checksums_section_when_enabled}
RUBY VERSION
- #{Bundler::RubyVersion.system}
+ #{Bundler::RubyVersion.system}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
@@ -1295,12 +1365,12 @@ RSpec.describe "bundle update --ruby" do
before do
install_gemfile <<-G
ruby '~> #{Gem.ruby_version}'
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
gemfile <<-G
ruby '~> 2.1.0'
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
end
it "shows a helpful error message" do
@@ -1314,7 +1384,7 @@ RSpec.describe "bundle update --ruby" do
before do
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
@@ -1328,12 +1398,12 @@ RSpec.describe "bundle update --ruby" do
ruby 2.1.4p222
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
gemfile <<-G
ruby '~> #{Gem.ruby_version}'
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
end
@@ -1342,7 +1412,7 @@ RSpec.describe "bundle update --ruby" do
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
@@ -1353,10 +1423,10 @@ RSpec.describe "bundle update --ruby" do
CHECKSUMS
RUBY VERSION
- #{Bundler::RubyVersion.system}
+ #{Bundler::RubyVersion.system}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
@@ -1365,171 +1435,166 @@ end
RSpec.describe "bundle update --bundler" do
it "updates the bundler version in the lockfile" do
build_repo4 do
- build_gem "rack", "1.0"
+ build_gem "bundler", "2.5.9"
+ build_gem "myrack", "1.0"
end
- checksums = checksums_section_when_existing do |c|
- c.checksum(gem_repo4, "rack", "1.0")
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum(gem_repo4, "myrack", "1.0")
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
- gem "rack"
+ source "https://gem.repo4"
+ gem "myrack"
G
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
- rack (1.0)
+ myrack (1.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
lockfile lockfile.sub(/(^\s*)#{Bundler::VERSION}($)/, '\11.0.0\2')
- bundle :update, bundler: true, artifice: "compact_index", verbose: true
+ bundle :update, bundler: true, verbose: true
expect(out).to include("Using bundler #{Bundler::VERSION}")
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
- rack (1.0)
+ myrack (1.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
- expect(the_bundle).to include_gem "rack 1.0"
+ expect(the_bundle).to include_gem "myrack 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.9"
-
build_repo4 do
- build_gem "rack", "1.0"
+ build_gem "bundler", "2.3.9"
+ build_gem "myrack", "1.0"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
- gem "rack"
+ source "https://gem.repo4"
+ gem "myrack"
G
lockfile lockfile.sub(/(^\s*)#{Bundler::VERSION}($)/, "2.3.9")
- checksums = checksums_section_when_existing do |c|
- c.checksum(gem_repo4, "rack", "1.0")
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum(gem_repo4, "myrack", "1.0")
end
- bundle :update, bundler: true, artifice: "compact_index", verbose: true
+ bundle :update, bundler: true, verbose: true
expect(out).to include("Using bundler #{Bundler::VERSION}")
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
- rack (1.0)
+ myrack (1.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
- expect(the_bundle).to include_gem "rack 1.0"
+ expect(the_bundle).to include_gem "myrack 1.0"
end
it "updates the bundler version in the lockfile even if the latest version is not installed", :ruby_repo do
- pristine_system_gems "bundler-2.3.9"
+ bundle "config path.system true"
+
+ pristine_system_gems "bundler-9.0.0"
build_repo4 do
- build_gem "rack", "1.0"
+ build_gem "myrack", "1.0"
build_bundler "999.0.0"
end
- install_gemfile <<-G, artifice: nil, env: { "BUNDLER_IGNORE_DEFAULT_GEM" => "true" }
- source "#{file_uri_for(gem_repo4)}"
- gem "rack"
- G
- lockfile lockfile.sub(/(^\s*)#{Bundler::VERSION}($)/, "2.3.9")
-
- bundle :update, bundler: true, artifice: "compact_index", verbose: true, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ checksums = checksums_section do |c|
+ c.checksum(gem_repo4, "myrack", "1.0")
+ end
- # Only updates properly on modern RubyGems.
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem "myrack"
+ G
- if Gem.rubygems_version >= Gem::Version.new("3.3.0.dev")
- expect(out).to include("Updating bundler to 999.0.0")
- expect(out).to include("Using bundler 999.0.0")
- expect(out).not_to include("Installing Bundler 2.3.9 and restarting using that version.")
+ bundle :update, bundler: true, verbose: true
- expect(lockfile).to eq <<~L
- GEM
- remote: #{file_uri_for(gem_repo4)}/
- specs:
- rack (1.0)
+ expect(out).to include("Updating bundler to 999.0.0")
+ expect(out).to include("Running `bundle update --bundler \"> 0.a\" --verbose` with bundler 999.0.0")
+ expect(out).not_to include("Installing Bundler 2.99.9 and restarting using that version.")
- PLATFORMS
- #{lockfile_platforms}
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ myrack (1.0)
- DEPENDENCIES
- rack
+ PLATFORMS
+ #{lockfile_platforms}
- BUNDLED WITH
- 999.0.0
- L
+ DEPENDENCIES
+ myrack
+ #{checksums}
+ BUNDLED WITH
+ 999.0.0
+ L
- expect(the_bundle).to include_gems "bundler 999.0.0"
- expect(the_bundle).to include_gems "rack 1.0"
- else
- # Old RubyGems versions do not trampoline but they still change BUNDLED
- # WITH to the latest bundler version. This means the below check fails
- # because it tries to use bundler 999.0.0 which did not get installed.
- # Workaround the bug by forcing the version we know is installed.
- expect(the_bundle).to include_gems "rack 1.0", env: { "BUNDLER_VERSION" => "2.3.9" }
- end
+ expect(the_bundle).to include_gems "bundler 999.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
it "does not claim to update to Bundler version to a wrong version when cached gems are present" do
- pristine_system_gems "bundler-2.99.0"
+ pristine_system_gems "bundler-4.99.0"
build_repo4 do
- build_gem "rack", "3.0.9.1"
+ build_gem "myrack", "3.0.9.1"
- build_bundler "2.99.0"
+ build_bundler "4.99.0"
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
- gem "rack"
+ source "https://gem.repo4"
+ gem "myrack"
G
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
- rack (3.0.9.1)
+ myrack (3.0.9.1)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
BUNDLED WITH
2.99.0
@@ -1537,168 +1602,180 @@ RSpec.describe "bundle update --bundler" do
bundle :cache, verbose: true
- bundle :update, bundler: true, artifice: "compact_index", verbose: true, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ bundle :update, bundler: true, verbose: true
expect(out).not_to include("Updating bundler to")
end
it "does not update the bundler version in the lockfile if the latest version is not compatible with current ruby", :ruby_repo do
- pristine_system_gems "bundler-2.3.9"
+ pristine_system_gems "bundler-9.9.9"
build_repo4 do
- build_gem "rack", "1.0"
+ build_gem "myrack", "1.0"
- build_bundler "2.3.9"
+ build_bundler "9.9.9"
build_bundler "999.0.0" do |s|
s.required_ruby_version = "> #{Gem.ruby_version}"
end
end
- install_gemfile <<-G, env: { "BUNDLER_IGNORE_DEFAULT_GEM" => "true" }
- source "#{file_uri_for(gem_repo4)}"
- gem "rack"
+ checksums = checksums_section do |c|
+ c.checksum(gem_repo4, "myrack", "1.0")
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem "myrack"
G
- lockfile lockfile.sub(/(^\s*)#{Bundler::VERSION}($)/, "2.3.9")
- bundle :update, bundler: true, artifice: "compact_index", verbose: true, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s, "BUNDLER_IGNORE_DEFAULT_GEM" => "true" }
+ bundle :update, bundler: true, verbose: true
- expect(out).to include("Using bundler 2.3.9")
+ expect(out).to include("Using bundler 9.9.9")
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
- rack (1.0)
+ myrack (1.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
-
+ myrack
+ #{checksums}
BUNDLED WITH
- 2.3.9
+ 9.9.9
L
- expect(the_bundle).to include_gems "bundler 2.3.9"
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "bundler 9.9.9"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
it "errors if the explicit target version does not exist" do
- pristine_system_gems "bundler-2.3.9"
+ pristine_system_gems "bundler-9.9.9"
build_repo4 do
- build_gem "rack", "1.0"
+ build_gem "myrack", "1.0"
end
- install_gemfile <<-G, env: { "BUNDLER_IGNORE_DEFAULT_GEM" => "true" }
- source "#{file_uri_for(gem_repo4)}"
- gem "rack"
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem "myrack"
G
- lockfile lockfile.sub(/(^\s*)#{Bundler::VERSION}($)/, "2.3.9")
- bundle :update, bundler: "999.999.999", artifice: "compact_index", raise_on_error: false
+ bundle :update, bundler: "999.999.999", raise_on_error: false
- # Only gives a meaningful error message on modern RubyGems.
+ expect(last_command).to be_failure
+ expect(err).to eq("The `bundle update --bundler` target version (999.999.999) does not exist")
+ end
- 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")
+ it "errors if the explicit target version does not exist, even if auto switching is disabled" do
+ pristine_system_gems "bundler-9.9.9"
+
+ build_repo4 do
+ build_gem "myrack", "1.0"
end
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem "myrack"
+ G
+
+ bundle :update, bundler: "999.999.999", raise_on_error: false, env: { "BUNDLER_VERSION" => "9.9.9" }
+
+ expect(last_command).to be_failure
+ expect(err).to eq("The `bundle update --bundler` target version (999.999.999) does not exist")
end
it "allows updating to development versions if already installed locally" do
- system_gems "bundler-2.3.0.dev"
+ system_gems "bundler-9.9.9"
build_repo4 do
- build_gem "rack", "1.0"
+ build_gem "myrack", "1.0"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
- gem "rack"
+ source "https://gem.repo4"
+ gem "myrack"
G
- bundle :update, bundler: "2.3.0.dev", verbose: "true"
+ system_gems "bundler-9.0.0.dev", path: local_gem_path
+ bundle :update, bundler: "9.0.0.dev", verbose: "true"
- # Only updates properly on modern RubyGems.
- if Gem.rubygems_version >= Gem::Version.new("3.3.0.dev")
- checksums = checksums_section_when_existing do |c|
- c.checksum(gem_repo4, "rack", "1.0")
- end
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum(gem_repo4, "myrack", "1.0")
+ end
- expect(lockfile).to eq <<~L
+ expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
- rack (1.0)
+ myrack (1.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
#{checksums}
BUNDLED WITH
- 2.3.0.dev
+ 9.0.0.dev
L
- expect(out).to include("Using bundler 2.3.0.dev")
- end
+ expect(out).to include("Using bundler 9.0.0.dev")
end
it "does not touch the network if not necessary" do
- system_gems "bundler-2.3.9"
+ system_gems "bundler-9.9.9"
build_repo4 do
- build_gem "rack", "1.0"
+ build_gem "myrack", "1.0"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
- gem "rack"
+ source "https://gem.repo4"
+ gem "myrack"
G
-
- bundle :update, bundler: "2.3.9", verbose: true
+ system_gems "bundler-9.0.0", path: local_gem_path
+ bundle :update, bundler: "9.0.0", verbose: true
expect(out).not_to include("Fetching gem metadata from https://rubygems.org/")
# Only updates properly on modern RubyGems.
- checksums = checksums_section_when_existing do |c|
- c.checksum(gem_repo4, "rack", "1.0")
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum(gem_repo4, "myrack", "1.0")
end
- if Gem.rubygems_version >= Gem::Version.new("3.3.0.dev")
- expect(lockfile).to eq <<~L
+ expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
- rack (1.0)
+ myrack (1.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
#{checksums}
BUNDLED WITH
- 2.3.9
+ 9.0.0
L
- expect(out).to include("Using bundler 2.3.9")
- end
+ expect(out).to include("Using bundler 9.0.0")
end
it "prints an error when trying to update bundler in frozen mode" do
- system_gems "bundler-2.3.9"
+ system_gems "bundler-9.0.0"
gemfile <<~G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
G
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
PLATFORMS
@@ -1707,11 +1784,13 @@ RSpec.describe "bundle update --bundler" do
DEPENDENCIES
BUNDLED WITH
- 2.1.4
+ 9.0.0
L
- bundle "update --bundler=2.3.9", env: { "BUNDLE_FROZEN" => "true" }, raise_on_error: false
- expect(err).to include("An update to the version of bundler itself was requested, but the lockfile can't be updated because frozen mode is set")
+ system_gems "bundler-9.9.9", path: local_gem_path
+
+ bundle "update --bundler=9.9.9", env: { "BUNDLE_FROZEN" => "true" }, raise_on_error: false
+ expect(err).to include("An update to the version of Bundler itself was requested, but the lockfile can't be updated because frozen mode is set")
end
end
@@ -1738,7 +1817,7 @@ RSpec.describe "bundle update conservative" do
# establish a lockfile set to 1.4.3
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem 'foo', '1.4.3'
gem 'bar', '2.0.3'
gem 'qux', '1.0.0'
@@ -1747,7 +1826,7 @@ RSpec.describe "bundle update conservative" do
# remove 1.4.3 requirement and bar altogether
# to setup update specs below
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem 'foo'
gem 'qux'
G
@@ -1843,7 +1922,7 @@ RSpec.describe "bundle update conservative" do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem 'isolated_owner'
gem 'shared_owner_a'
@@ -1852,7 +1931,7 @@ RSpec.describe "bundle update conservative" do
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
isolated_dep (2.0.1)
isolated_owner (1.0.1)
@@ -1874,7 +1953,7 @@ RSpec.describe "bundle update conservative" do
CHECKSUMS
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
@@ -1905,9 +1984,17 @@ RSpec.describe "bundle update conservative" do
it "should only change direct dependencies when updating the lockfile with --conservative" do
bundle "lock --update --conservative"
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "isolated_dep", "2.0.1"
+ c.checksum gem_repo4, "isolated_owner", "1.0.2"
+ c.checksum gem_repo4, "shared_dep", "5.0.1"
+ c.checksum gem_repo4, "shared_owner_a", "3.0.2"
+ c.checksum gem_repo4, "shared_owner_b", "4.0.2"
+ end
+
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
isolated_dep (2.0.1)
isolated_owner (1.0.2)
@@ -1925,22 +2012,15 @@ RSpec.describe "bundle update conservative" do
isolated_owner
shared_owner_a
shared_owner_b
-
- CHECKSUMS
- isolated_dep (2.0.1)
- isolated_owner (1.0.2)
- shared_dep (5.0.1)
- shared_owner_a (3.0.2)
- shared_owner_b (4.0.2)
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
it "should match bundle install conservative update behavior when not eagerly unlocking" do
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem 'isolated_owner', '1.0.2'
gem 'shared_owner_a', '3.0.2'
@@ -1949,7 +2029,7 @@ RSpec.describe "bundle update conservative" do
bundle "install"
- 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
end
@@ -1968,14 +2048,14 @@ RSpec.describe "bundle update conservative" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "nokogiri", ">=1.16.4"
gem "prism", ">=0.25.0"
G
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
nokogiri (1.16.4-arm64-darwin)
nokogiri (1.16.4-x86_64-linux)
@@ -1988,7 +2068,7 @@ RSpec.describe "bundle update conservative" do
nokogiri (>= 1.16.4)
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
@@ -2001,7 +2081,7 @@ RSpec.describe "bundle update conservative" do
context "error handling" do
before do
- gemfile "source \"#{file_uri_for(gem_repo1)}\""
+ gemfile "source 'https://gem.repo1'"
end
it "raises if too many flags are provided" do
diff --git a/spec/bundler/commands/version_spec.rb b/spec/bundler/commands/version_spec.rb
index 307058a5dd..995a6e1e20 100644
--- a/spec/bundler/commands/version_spec.rb
+++ b/spec/bundler/commands/version_spec.rb
@@ -10,38 +10,56 @@ RSpec.describe "bundle version" do
end
context "with -v" do
- it "outputs the version", bundler: "< 3" do
+ it "outputs the version and virtual version if set" do
bundle "-v"
- expect(out).to eq("Bundler version #{Bundler::VERSION}")
- end
+ expect(out).to eq(Bundler::VERSION.to_s)
- it "outputs the version", bundler: "3" do
+ bundle "config simulate_version 5"
bundle "-v"
- expect(out).to eq(Bundler::VERSION)
+ expect(out).to eq("#{Bundler::VERSION} (simulating Bundler 5)")
end
end
context "with --version" do
- it "outputs the version", bundler: "< 3" do
+ it "outputs the version and virtual version if set" do
bundle "--version"
- expect(out).to eq("Bundler version #{Bundler::VERSION}")
- end
+ expect(out).to eq(Bundler::VERSION.to_s)
- it "outputs the version", bundler: "3" do
+ bundle "config simulate_version 5"
bundle "--version"
- expect(out).to eq(Bundler::VERSION)
+ expect(out).to eq("#{Bundler::VERSION} (simulating Bundler 5)")
end
end
context "with version" do
- it "outputs the version with build metadata", bundler: "< 3" do
- bundle "version"
- expect(out).to match(/\ABundler version #{Regexp.escape(Bundler::VERSION)} \(\d{4}-\d{2}-\d{2} commit #{COMMIT_HASH}\)\z/)
+ context "when released", :ruby_repo do
+ before do
+ system_gems "bundler-4.9.9", released: true
+ end
+
+ it "outputs the version, virtual version if set, and build metadata" do
+ bundle "version"
+ expect(out).to match(/\A4\.9\.9 \(2100-01-01 commit #{COMMIT_HASH}\)\z/)
+
+ bundle "config simulate_version 5"
+ bundle "version"
+ expect(out).to match(/\A4\.9\.9 \(simulating Bundler 5\) \(2100-01-01 commit #{COMMIT_HASH}\)\z/)
+ end
end
- it "outputs the version with build metadata", bundler: "3" do
- bundle "version"
- expect(out).to match(/\A#{Regexp.escape(Bundler::VERSION)} \(\d{4}-\d{2}-\d{2} commit #{COMMIT_HASH}\)\z/)
+ context "when not released" do
+ before do
+ system_gems "bundler-4.9.9", released: false
+ end
+
+ it "outputs the version, virtual version if set, and build metadata" do
+ bundle "version"
+ expect(out).to match(/\A4\.9\.9 \(20\d{2}-\d{2}-\d{2} commit #{COMMIT_HASH}\)\z/)
+
+ bundle "config simulate_version 5"
+ bundle "version"
+ expect(out).to match(/\A4\.9\.9 \(simulating Bundler 5\) \(20\d{2}-\d{2}-\d{2} commit #{COMMIT_HASH}\)\z/)
+ end
end
end
end
diff --git a/spec/bundler/commands/viz_spec.rb b/spec/bundler/commands/viz_spec.rb
deleted file mode 100644
index f8b5f7836e..0000000000
--- a/spec/bundler/commands/viz_spec.rb
+++ /dev/null
@@ -1,144 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe "bundle viz", bundler: "< 3", if: Bundler.which("dot"), realworld: true do
- before do
- realworld_system_gems "ruby-graphviz --version 1.2.5"
- end
-
- it "graphs gems from the Gemfile" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- gem "rack-obama"
- G
-
- bundle "viz"
- expect(out).to include("gem_graph.png")
-
- bundle "viz", format: "debug"
- expect(out).to eq(<<~DOT.strip)
- digraph Gemfile {
- concentrate = "true";
- normalize = "true";
- nodesep = "0.55";
- edge[ weight = "2"];
- node[ fontname = "Arial, Helvetica, SansSerif"];
- edge[ fontname = "Arial, Helvetica, SansSerif" , fontsize = "12"];
- default [style = "filled", fillcolor = "#B9B9D5", shape = "box3d", fontsize = "16", label = "default"];
- rack [style = "filled", fillcolor = "#B9B9D5", label = "rack"];
- default -> rack [constraint = "false"];
- "rack-obama" [style = "filled", fillcolor = "#B9B9D5", label = "rack-obama"];
- default -> "rack-obama" [constraint = "false"];
- "rack-obama" -> rack;
- }
- debugging bundle viz...
- DOT
- end
-
- it "graphs gems that are prereleases" do
- build_repo2 do
- build_gem "rack", "1.3.pre"
- end
-
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack", "= 1.3.pre"
- gem "rack-obama"
- G
-
- bundle "viz"
- expect(out).to include("gem_graph.png")
-
- bundle "viz", format: :debug, version: true
- expect(out).to eq(<<~EOS.strip)
- digraph Gemfile {
- concentrate = "true";
- normalize = "true";
- nodesep = "0.55";
- edge[ weight = "2"];
- node[ fontname = "Arial, Helvetica, SansSerif"];
- edge[ fontname = "Arial, Helvetica, SansSerif" , fontsize = "12"];
- default [style = "filled", fillcolor = "#B9B9D5", shape = "box3d", fontsize = "16", label = "default"];
- rack [style = "filled", fillcolor = "#B9B9D5", label = "rack\\n1.3.pre"];
- default -> rack [constraint = "false"];
- "rack-obama" [style = "filled", fillcolor = "#B9B9D5", label = "rack-obama\\n1.0"];
- default -> "rack-obama" [constraint = "false"];
- "rack-obama" -> rack;
- }
- debugging bundle viz...
- EOS
- end
-
- context "with another gem that has a graphviz file" do
- before do
- build_repo4 do
- build_gem "graphviz", "999" do |s|
- s.write("lib/graphviz.rb", "abort 'wrong graphviz gem loaded'")
- end
- end
-
- system_gems "graphviz-999", gem_repo: gem_repo4
- end
-
- it "loads the correct ruby-graphviz gem" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- gem "rack-obama"
- G
-
- bundle "viz", format: "debug"
- expect(out).to eq(<<~DOT.strip)
- digraph Gemfile {
- concentrate = "true";
- normalize = "true";
- nodesep = "0.55";
- edge[ weight = "2"];
- node[ fontname = "Arial, Helvetica, SansSerif"];
- edge[ fontname = "Arial, Helvetica, SansSerif" , fontsize = "12"];
- default [style = "filled", fillcolor = "#B9B9D5", shape = "box3d", fontsize = "16", label = "default"];
- rack [style = "filled", fillcolor = "#B9B9D5", label = "rack"];
- default -> rack [constraint = "false"];
- "rack-obama" [style = "filled", fillcolor = "#B9B9D5", label = "rack-obama"];
- default -> "rack-obama" [constraint = "false"];
- "rack-obama" -> rack;
- }
- debugging bundle viz...
- DOT
- end
- end
-
- context "--without option" do
- it "one group" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "activesupport"
-
- group :rails do
- gem "rails"
- end
- G
-
- bundle "viz --without=rails"
- expect(out).to include("gem_graph.png")
- end
-
- it "two groups" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "activesupport"
-
- group :rack do
- gem "rack"
- end
-
- group :rails do
- gem "rails"
- end
- G
-
- bundle "viz --without=rails:rack"
- expect(out).to include("gem_graph.png")
- end
- end
-end
diff --git a/spec/bundler/install/allow_offline_install_spec.rb b/spec/bundler/install/allow_offline_install_spec.rb
index 8da94718e0..4889dbc943 100644
--- a/spec/bundler/install/allow_offline_install_spec.rb
+++ b/spec/bundler/install/allow_offline_install_spec.rb
@@ -1,23 +1,19 @@
# frozen_string_literal: true
-RSpec.describe "bundle install with :allow_offline_install" do
- before do
- bundle "config set allow_offline_install true"
- end
-
+RSpec.describe "bundle install allows offline install" do
context "with no cached data locally" do
it "still installs" do
install_gemfile <<-G, artifice: "compact_index"
source "http://testgemserver.local"
- gem "rack-obama"
+ gem "myrack-obama"
G
- expect(the_bundle).to include_gem("rack 1.0")
+ expect(the_bundle).to include_gem("myrack 1.0")
end
it "still fails when the network is down" do
install_gemfile <<-G, artifice: "fail", raise_on_error: false
source "http://testgemserver.local"
- gem "rack-obama"
+ gem "myrack-obama"
G
expect(err).to include("Could not reach host testgemserver.local.")
expect(the_bundle).to_not be_locked
@@ -26,26 +22,26 @@ RSpec.describe "bundle install with :allow_offline_install" do
context "with cached data locally" do
it "will install from the compact index" do
- system_gems ["rack-1.0.0"], path: default_bundle_path
+ system_gems ["myrack-1.0.0"], path: default_bundle_path
bundle "config set clean false"
install_gemfile <<-G, artifice: "compact_index"
source "http://testgemserver.local"
- gem "rack-obama"
- gem "rack", "< 1.0"
+ gem "myrack-obama"
+ gem "myrack", "< 1.0"
G
- expect(the_bundle).to include_gems("rack-obama 1.0", "rack 0.9.1")
+ expect(the_bundle).to include_gems("myrack-obama 1.0", "myrack 0.9.1")
gemfile <<-G
source "http://testgemserver.local"
- gem "rack-obama"
+ gem "myrack-obama"
G
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(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")
+ expect(the_bundle).to include_gems("myrack-obama 1.0", "myrack 1.0.0")
end
def break_git_remote_ops!
@@ -53,10 +49,10 @@ RSpec.describe "bundle install with :allow_offline_install" do
File.open(tmp("broken_path/git"), "w", 0o755) do |f|
f.puts <<~RUBY
#!/usr/bin/env ruby
- fetch_args = %w(fetch --force --quiet)
+ fetch_args = %w(fetch --force --quiet --no-tags)
clone_args = %w(clone --bare --no-hardlinks --quiet)
- if (fetch_args.-(ARGV).empty? || clone_args.-(ARGV).empty?) && ARGV.any? {|arg| arg.start_with?("file://") }
+ if (fetch_args.-(ARGV).empty? || clone_args.-(ARGV).empty?) && File.exist?(ARGV[ARGV.index("--") + 1])
warn "git remote ops have been disabled"
exit 1
end
@@ -78,7 +74,7 @@ RSpec.describe "bundle install with :allow_offline_install" do
git = build_git "a", "1.0.0", path: lib_path("a")
update_git("a", path: git.path, branch: "new_branch")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "a", :git => #{git.path.to_s.dump}
G
@@ -88,7 +84,7 @@ RSpec.describe "bundle install with :allow_offline_install" do
break_git_remote_ops! do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "a", :git => #{git.path.to_s.dump}, :branch => "new_branch"
G
end
diff --git a/spec/bundler/install/binstubs_spec.rb b/spec/bundler/install/binstubs_spec.rb
index 928ba80b15..00765ac6dd 100644
--- a/spec/bundler/install/binstubs_spec.rb
+++ b/spec/bundler/install/binstubs_spec.rb
@@ -6,14 +6,14 @@ RSpec.describe "bundle install" do
expect(Pathname.new("/usr/bin")).not_to be_writable
gemfile <<-G
def Gem.bindir; "/usr/bin"; end
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
config "BUNDLE_SYSTEM_BINDIR" => system_gem_path("altbin").to_s
bundle :install
- expect(the_bundle).to include_gems "rack 1.0.0"
- expect(system_gem_path("altbin/rackup")).to exist
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ expect(system_gem_path("altbin/myrackup")).to exist
end
end
@@ -21,26 +21,26 @@ RSpec.describe "bundle install" do
before do
build_repo2 do
build_gem "fake", "14" do |s|
- s.executables = "rackup"
+ s.executables = "myrackup"
end
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "fake"
- gem "rack"
+ gem "myrack"
G
end
it "warns about the situation" do
- bundle "exec rackup"
+ bundle "exec myrackup"
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" \
+ "The `myrackup` executable in the `fake` gem is being loaded, but it's also present in other gems (myrack).\n" \
"If you meant to run the executable for another gem, make sure you use a project specific binstub (`bundle binstub <gem_name>`).\n" \
"If you plan to use multiple conflicting executables, generate binstubs for them and disambiguate their names."
).or include(
- "The `rackup` executable in the `rack` gem is being loaded, but it's also present in other gems (fake).\n" \
+ "The `myrackup` executable in the `myrack` gem is being loaded, but it's also present in other gems (fake).\n" \
"If you meant to run the executable for another gem, make sure you use a project specific binstub (`bundle binstub <gem_name>`).\n" \
"If you plan to use multiple conflicting executables, generate binstubs for them and disambiguate their names."
)
diff --git a/spec/bundler/install/bundler_spec.rb b/spec/bundler/install/bundler_spec.rb
index 19911f1154..56f8431181 100644
--- a/spec/bundler/install/bundler_spec.rb
+++ b/spec/bundler/install/bundler_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe "bundle install" do
before(:each) do
build_repo2 do
build_gem "rails", "3.0" do |s|
- s.add_dependency "bundler", ">= 0.9.0.pre"
+ s.add_dependency "bundler", ">= 0.9.0"
end
build_gem "bundler", "0.9.1"
build_gem "bundler", Bundler::VERSION
@@ -14,7 +14,7 @@ RSpec.describe "bundle install" do
it "are forced to the current bundler version" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "rails", "3.0"
G
@@ -23,15 +23,15 @@ RSpec.describe "bundle install" 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"
+ source "https://gem.repo1"
+ gem "myrack"
G
expect(the_bundle).to include_gems "bundler #{Bundler::VERSION}"
end
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)}"
+ source "https://gem.repo2"
gem "rails", "3.0"
gem "bundler", "0.9.1"
G
@@ -51,7 +51,7 @@ RSpec.describe "bundle install" do
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)}"
+ source "https://gem.repo2"
gem "rails", "3.0"
gem "bundler", "~> 0.8"
G
@@ -59,8 +59,8 @@ RSpec.describe "bundle install" do
nice_error = <<~E.strip
Could not find compatible versions
- Because rails >= 3.0 depends on bundler >= 0.9.0.pre
- and the current Bundler version (#{Bundler::VERSION}) does not satisfy bundler >= 0.9.0.pre, < 1.A,
+ Because rails >= 3.0 depends on bundler >= 0.9.0
+ and the current Bundler version (#{Bundler::VERSION}) does not satisfy bundler >= 0.9.0, < 1.A,
rails >= 3.0 requires bundler >= 1.A.
So, because Gemfile depends on rails = 3.0
and Gemfile depends on bundler ~> 0.8,
@@ -74,7 +74,7 @@ RSpec.describe "bundle install" do
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)}"
+ source "https://gem.repo2"
gem "rails", "3.0"
gem "bundler", "0.9.2"
G
@@ -99,16 +99,16 @@ RSpec.describe "bundle install" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "multiple_versioned_deps"
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "multiple_versioned_deps"
- gem "rack"
+ gem "myrack"
G
expect(the_bundle).to include_gems "multiple_versioned_deps 1.0.0"
@@ -116,7 +116,7 @@ RSpec.describe "bundle install" do
it "includes bundler in the bundle when it's a child dependency" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "rails", "3.0"
G
@@ -126,8 +126,8 @@ RSpec.describe "bundle install" do
it "allows gem 'bundler' when Bundler is not in the Gemfile or its dependencies" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack"
+ source "https://gem.repo2"
+ gem "myrack"
G
run "begin; gem 'bundler'; puts 'WIN'; rescue Gem::LoadError => e; puts e.backtrace; end"
@@ -144,7 +144,7 @@ RSpec.describe "bundle install" do
end
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "activemerchant"
gem "rails_pinned_to_old_activesupport"
G
@@ -172,7 +172,7 @@ RSpec.describe "bundle install" do
end
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "rails_pinned_to_old_activesupport"
gem "activesupport", "2.3.5"
G
@@ -197,12 +197,12 @@ RSpec.describe "bundle install" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem 'rails', "2.3.2"
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "rails_pinned_to_old_activesupport"
G
@@ -219,17 +219,17 @@ RSpec.describe "bundle install" do
bundle "config set path.system true"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem 'rails', "7.0.4"
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem 'rails', "7.0.3"
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem 'rails', "7.0.4"
G
@@ -243,7 +243,7 @@ RSpec.describe "bundle install" do
system_gems "bundler-99999999.99.1"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "rails", "3.0"
G
@@ -257,7 +257,7 @@ RSpec.describe "bundle install" do
system_gems "bundler-99999999.99.1"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "rails", "3.0"
G
diff --git a/spec/bundler/install/deploy_spec.rb b/spec/bundler/install/deploy_spec.rb
index d89fdea6f1..6d845e03d1 100644
--- a/spec/bundler/install/deploy_spec.rb
+++ b/spec/bundler/install/deploy_spec.rb
@@ -3,90 +3,36 @@
RSpec.describe "install in deployment or frozen mode" do
before do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
end
- context "with CLI flags", bundler: "< 3" do
- it "fails without a lockfile and says that --deployment requires a lock" do
- bundle "install --deployment", raise_on_error: false
- expect(err).to include("The --deployment flag requires a lockfile")
- end
-
- it "fails without a lockfile and says that --frozen requires a lock" do
- bundle "install --frozen", raise_on_error: false
- expect(err).to include("The --frozen flag requires a lockfile")
- end
-
- it "disallows --deployment --system" do
- 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)
- end
-
- it "disallows --deployment --path --system" do
- 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)
- end
-
- it "doesn't mess up a subsequent `bundle install` after you try to deploy without a lock" do
- bundle "install --deployment", raise_on_error: false
- bundle :install
- expect(the_bundle).to include_gems "rack 1.0"
- end
-
- it "installs gems by default to vendor/bundle" do
- bundle :lock
- bundle "install --deployment"
- expect(out).to include("vendor/bundle")
- end
-
- it "installs gems to custom path if specified" do
- bundle :lock
- bundle "install --path vendor/bundle2 --deployment"
- expect(out).to include("vendor/bundle2")
- end
-
- it "works with the --frozen flag" do
- bundle :lock
- bundle "install --frozen"
- end
-
- it "explodes with the --deployment flag if you make a change and don't check in the lockfile" do
- bundle :lock
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- gem "rack-obama"
- G
+ it "fails without a lockfile and says that deployment requires a lock" do
+ bundle "config deployment true"
+ bundle "install", raise_on_error: false
+ expect(err).to include("The deployment setting requires a lockfile")
+ end
- bundle "install --deployment", raise_on_error: false
- expect(err).to include("frozen mode")
- expect(err).to include("You have added to the Gemfile")
- expect(err).to include("* rack-obama")
- expect(err).not_to include("You have deleted from the Gemfile")
- expect(err).not_to include("You have changed in the Gemfile")
- end
+ it "fails without a lockfile and says that frozen requires a lock" do
+ bundle "config frozen true"
+ bundle "install", raise_on_error: false
+ expect(err).to include("The frozen setting requires a lockfile")
end
it "still works if you are not in the app directory and specify --gemfile" do
bundle "install"
- simulate_new_machine
+ pristine_system_gems
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"
+ expect(the_bundle).to include_gems "myrack 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)}"
+ source "https://gem.repo1"
group :test do
gem "foo", :git => "#{lib_path("foo-1.0")}"
end
@@ -110,7 +56,7 @@ RSpec.describe "install in deployment or frozen mode" 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)}"
+ source "https://gem.repo1"
gem "foo", "1.0", :path => "#{lib_path("nested")}"
gem "bar", :path => "#{lib_path("nested")}"
G
@@ -123,7 +69,7 @@ RSpec.describe "install in deployment or frozen mode" do
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)}"
+ source "https://gem.repo1"
gem "foo", :path => "#{lib_path("nested/foo")}"
gem "foo", :path => "#{lib_path("nested/foo")}"
G
@@ -137,7 +83,7 @@ RSpec.describe "install in deployment or frozen mode" do
install_gemfile(<<-G, artifice: "endpoint_strict_basic_authentication", quiet: true)
source "http://user:pass@localgemserver.test/"
- gem "rack-obama", ">= 1.0"
+ gem "myrack-obama", ">= 1.0"
G
bundle "config set --local deployment true"
@@ -146,16 +92,16 @@ RSpec.describe "install in deployment or frozen mode" do
it "works with sources given by a block" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- source "#{file_uri_for(gem_repo1)}" do
- gem "rack"
+ source "https://gem.repo1"
+ source "https://gem.repo1" do
+ gem "myrack"
end
G
bundle "config set --local deployment true"
bundle :install
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
context "when replacing a host with the same host with credentials" do
@@ -164,20 +110,20 @@ RSpec.describe "install in deployment or frozen mode" do
bundle "install"
gemfile <<-G
source "http://user_name:password@localgemserver.test/"
- gem "rack"
+ gem "myrack"
G
lockfile <<-G
GEM
remote: http://localgemserver.test/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{generic_local_platform}
DEPENDENCIES
- rack
+ myrack
G
bundle "config set --local deployment true"
@@ -231,16 +177,16 @@ RSpec.describe "install in deployment or frozen mode" do
it "explodes with the `deployment` setting if you make a change and don't check in the lockfile" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- gem "rack-obama"
+ source "https://gem.repo1"
+ gem "myrack"
+ gem "myrack-obama"
G
bundle "config set --local deployment true"
bundle :install, raise_on_error: false
expect(err).to include("frozen mode")
expect(err).to include("You have added to the Gemfile")
- expect(err).to include("* rack-obama")
+ expect(err).to include("* myrack-obama")
expect(err).not_to include("You have deleted from the Gemfile")
expect(err).not_to include("You have changed in the Gemfile")
end
@@ -248,7 +194,7 @@ RSpec.describe "install in deployment or frozen mode" do
it "works if a path gem is missing but is in a without group" do
build_lib "path_gem"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rake"
gem "path_gem", :path => "#{lib_path("path_gem-1.0")}", :group => :development
G
@@ -267,9 +213,9 @@ RSpec.describe "install in deployment or frozen mode" do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
- source "#{file_uri_for(gem_repo1)}" do
+ source "https://gem.repo1" do
gem "rake", platform: :#{not_local_tag}
end
G
@@ -305,17 +251,17 @@ RSpec.describe "install in deployment or frozen mode" do
bar
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle :install, env: { "BUNDLE_FROZEN" => "true" }, raise_on_error: false, artifice: "compact_index"
- expect(err).to include("Your lock file is missing \"bar\", but the lockfile can't be updated because frozen mode is set")
+ expect(err).to include("Your lockfile is missing \"bar\", but can't be updated because frozen mode is set")
end
it "explodes if a path gem is missing" do
build_lib "path_gem"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rake"
gem "path_gem", :path => "#{lib_path("path_gem-1.0")}", :group => :development
G
@@ -330,32 +276,32 @@ RSpec.describe "install in deployment or frozen mode" do
it "can have --frozen set via an environment variable" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- gem "rack-obama"
+ source "https://gem.repo1"
+ gem "myrack"
+ gem "myrack-obama"
G
ENV["BUNDLE_FROZEN"] = "1"
bundle "install", raise_on_error: false
expect(err).to include("frozen mode")
expect(err).to include("You have added to the Gemfile")
- expect(err).to include("* rack-obama")
+ expect(err).to include("* myrack-obama")
expect(err).not_to include("You have deleted from the Gemfile")
expect(err).not_to include("You have changed in the Gemfile")
end
it "can have --deployment set via an environment variable" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- gem "rack-obama"
+ source "https://gem.repo1"
+ gem "myrack"
+ gem "myrack-obama"
G
ENV["BUNDLE_DEPLOYMENT"] = "true"
bundle "install", raise_on_error: false
expect(err).to include("frozen mode")
expect(err).to include("You have added to the Gemfile")
- expect(err).to include("* rack-obama")
+ expect(err).to include("* myrack-obama")
expect(err).not_to include("You have deleted from the Gemfile")
expect(err).not_to include("You have changed in the Gemfile")
end
@@ -375,9 +321,9 @@ RSpec.describe "install in deployment or frozen mode" do
it "can have --frozen set to false via an environment variable" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- gem "rack-obama"
+ source "https://gem.repo1"
+ gem "myrack"
+ gem "myrack-obama"
G
ENV["BUNDLE_FROZEN"] = "false"
@@ -385,12 +331,12 @@ RSpec.describe "install in deployment or frozen mode" do
bundle "install"
expect(out).not_to include("frozen mode")
expect(out).not_to include("You have added to the Gemfile")
- expect(out).not_to include("* rack-obama")
+ expect(out).not_to include("* myrack-obama")
end
- it "explodes if you remove a gem and don't check in the lockfile" do
+ it "explodes if you replace a gem and don't check in the lockfile" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "activesupport"
G
@@ -398,34 +344,45 @@ RSpec.describe "install in deployment or frozen mode" do
bundle :install, raise_on_error: false
expect(err).to include("frozen 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")
+ expect(err).to include("You have deleted from the Gemfile:\n* myrack")
+ expect(err).not_to include("You have changed in the Gemfile")
+ end
+
+ it "explodes if you remove a gem and don't check in the lockfile" do
+ gemfile 'source "https://gem.repo1"'
+
+ bundle "config set --local deployment true"
+ bundle :install, raise_on_error: false
+ expect(err).to include("Some dependencies were deleted")
+ expect(err).to include("frozen mode")
+ expect(err).to include("You have deleted from the Gemfile:\n* myrack")
expect(err).not_to include("You have changed in the Gemfile")
end
it "explodes if you add a source" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "git://hubz.com"
+ source "https://gem.repo1"
+ gem "myrack", :git => "git://hubz.com"
G
bundle "config set --local deployment true"
bundle :install, raise_on_error: false
expect(err).to include("frozen mode")
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`")
+ expect(err).to include("You have changed in the Gemfile:\n* myrack from `no specified source` to `git://hubz.com`")
end
- it "explodes if you change a source" do
- build_git "rack"
+ it "explodes if you change a source from git to the default" do
+ build_git "myrack"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-1.0")}"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-1.0")}"
G
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle "config set --local deployment true"
@@ -433,29 +390,50 @@ RSpec.describe "install in deployment or frozen mode" do
expect(err).to include("frozen mode")
expect(err).not_to include("You have deleted from 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 `#{lib_path("rack-1.0")}` to `no specified source`")
+ expect(err).to include("You have changed in the Gemfile:\n* myrack from `#{lib_path("myrack-1.0")}` to `no specified source`")
end
- it "explodes if you change a source" do
- build_lib "foo", path: lib_path("rack/foo")
- build_git "rack", path: lib_path("rack")
+ it "explodes if you change a source from git to the default, in presence of other git sources" do
+ build_lib "foo", path: lib_path("myrack/foo")
+ build_git "myrack", path: lib_path("myrack")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack")}"
- gem "foo", :git => "#{lib_path("rack")}"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack")}"
+ gem "foo", :git => "#{lib_path("myrack")}"
G
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- gem "foo", :git => "#{lib_path("rack")}"
+ source "https://gem.repo1"
+ gem "myrack"
+ gem "foo", :git => "#{lib_path("myrack")}"
G
bundle "config set --local deployment true"
bundle :install, raise_on_error: false
expect(err).to include("frozen mode")
- expect(err).to include("You have changed in the Gemfile:\n* rack from `#{lib_path("rack")}` to `no specified source`")
+ expect(err).to include("You have changed in the Gemfile:\n* myrack from `#{lib_path("myrack")}` 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 "explodes if you change a source from path to git" do
+ build_git "myrack", path: lib_path("myrack")
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", :path => "#{lib_path("myrack")}"
+ G
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack", :git => "https:/my-git-repo-for-myrack"
+ G
+
+ bundle "config set --local frozen true"
+ bundle :install, raise_on_error: false
+ expect(err).to include("frozen mode")
+ expect(err).to include("You have changed in the Gemfile:\n* myrack from `#{lib_path("myrack")}` to `https:/my-git-repo-for-myrack`")
expect(err).not_to include("You have added to the Gemfile")
expect(err).not_to include("You have deleted from the Gemfile")
end
@@ -466,21 +444,21 @@ RSpec.describe "install in deployment or frozen mode" do
bundle "config set --local deployment true"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "1.0.0"
- gem "rack-obama"
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0"
+ gem "myrack-obama"
G
- run "require 'rack'", raise_on_error: false
+ run "require 'myrack'", raise_on_error: false
expect(err).to include <<~E.strip
The dependencies in your gemfile changed, but the lockfile can't be updated because frozen mode is set (Bundler::ProductionError)
You have added to the Gemfile:
- * rack (= 1.0.0)
- * rack-obama
+ * myrack (= 1.0.0)
+ * myrack-obama
You have deleted from the Gemfile:
- * rack
+ * myrack
E
end
end
@@ -489,24 +467,23 @@ RSpec.describe "install in deployment or frozen mode" do
it "works fine after bundle package and bundle install --local" do
build_lib "foo", path: lib_path("foo")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :path => "#{lib_path("foo")}"
G
bundle :install
expect(the_bundle).to include_gems "foo 1.0"
- bundle "config set cache_all true"
bundle :cache
expect(bundled_app("vendor/cache/foo")).to be_directory
bundle "install --local"
expect(out).to include("Updating files in vendor/cache")
- simulate_new_machine
+ pristine_system_gems
bundle "config set --local deployment true"
bundle "install --verbose"
- expect(out).not_to include("but the lockfile can't be updated because frozen mode is set")
+ expect(out).not_to include("can't be updated because frozen mode is set")
expect(out).not_to include("You have added to the Gemfile")
expect(out).not_to include("You have deleted from the Gemfile")
expect(out).to include("vendor/cache/foo")
diff --git a/spec/bundler/install/failure_spec.rb b/spec/bundler/install/failure_spec.rb
index f972a37bf6..2c2773e849 100644
--- a/spec/bundler/install/failure_spec.rb
+++ b/spec/bundler/install/failure_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe "bundle install" do
end
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "rails"
G
expect(err).to start_with("Gem::Ext::BuildError: ERROR: Failed to build gem native extension.")
@@ -40,7 +40,7 @@ In Gemfile:
it "removes the downloaded .gem" do
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "a"
G
diff --git a/spec/bundler/install/force_spec.rb b/spec/bundler/install/force_spec.rb
new file mode 100644
index 0000000000..e0f6fb6364
--- /dev/null
+++ b/spec/bundler/install/force_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundle install" do
+ before :each do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+ end
+
+ shared_examples_for "an option to force reinstalling gems" do
+ it "re-installs installed gems" do
+ myrack_lib = default_bundle_path("gems/myrack-1.0.0/lib/myrack.rb")
+
+ bundle :install
+ myrack_lib.open("w") {|f| f.write("blah blah blah") }
+ bundle :install, flag => true
+
+ expect(out).to include "Installing myrack 1.0.0"
+ expect(myrack_lib.open(&:read)).to eq("MYRACK = '1.0.0'\n")
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ it "works on first bundle install" do
+ bundle :install, flag => true
+
+ expect(out).to include "Installing myrack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ context "with a git gem" do
+ let!(:ref) { build_git("foo", "1.0").ref_for("HEAD", 11) }
+
+ before do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo-1.0")}"
+ G
+ end
+
+ it "re-installs installed gems" do
+ foo_lib = default_bundle_path("bundler/gems/foo-1.0-#{ref}/lib/foo.rb")
+
+ bundle :install
+ foo_lib.open("w") {|f| f.write("blah blah blah") }
+ 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
+
+ expect(the_bundle).to include_gems "foo 1.0"
+ end
+ end
+ end
+
+ describe "with --force" do
+ it_behaves_like "an option to force reinstalling gems" do
+ let(:flag) { "force" }
+ end
+ end
+
+ describe "with --redownload" do
+ it_behaves_like "an option to force reinstalling gems" do
+ let(:flag) { "redownload" }
+ end
+ end
+end
diff --git a/spec/bundler/install/gemfile/eval_gemfile_spec.rb b/spec/bundler/install/gemfile/eval_gemfile_spec.rb
index cfa66e5986..a507e52485 100644
--- a/spec/bundler/install/gemfile/eval_gemfile_spec.rb
+++ b/spec/bundler/install/gemfile/eval_gemfile_spec.rb
@@ -2,7 +2,7 @@
RSpec.describe "bundle install with gemfile that uses eval_gemfile" do
before do
- build_lib("gunks", path: bundled_app.join("gems/gunks")) do |s|
+ build_lib("gunks", path: bundled_app("gems/gunks")) do |s|
s.name = "gunks"
s.version = "0.0.1"
end
@@ -10,15 +10,15 @@ RSpec.describe "bundle install with gemfile that uses eval_gemfile" do
context "eval-ed Gemfile points to an internal gemspec" do
before do
- create_file "Gemfile-other", <<-G
- source "#{file_uri_for(gem_repo1)}"
+ gemfile "Gemfile-other", <<-G
+ source "https://gem.repo1"
gemspec :path => 'gems/gunks'
G
end
it "installs the gemspec specified gem" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
eval_gemfile 'Gemfile-other'
G
expect(out).to include("Resolving dependencies")
@@ -36,12 +36,12 @@ RSpec.describe "bundle install with gemfile that uses eval_gemfile" do
build_gem "zip-zip", "0.3"
end
- create_file bundled_app("gems/Gemfile"), <<-G
- source "#{file_uri_for(gem_repo2)}"
+ gemfile bundled_app("gems/Gemfile"), <<-G
+ source "https://gem.repo2"
gemspec :path => "\#{__dir__}/gunks"
- source "#{file_uri_for(gem_repo2)}" do
+ source "https://gem.repo2" do
gem "zip-zip"
end
G
@@ -49,7 +49,7 @@ RSpec.describe "bundle install with gemfile that uses eval_gemfile" do
it "installs and finds gems correctly" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "rails"
@@ -65,13 +65,13 @@ RSpec.describe "bundle install with gemfile that uses eval_gemfile" do
context "eval-ed Gemfile has relative-path gems" do
before do
build_lib("a", path: bundled_app("gems/a"))
- create_file bundled_app("nested/Gemfile-nested"), <<-G
- source "#{file_uri_for(gem_repo1)}"
+ gemfile bundled_app("nested/Gemfile-nested"), <<-G
+ source "https://gem.repo1"
gem "a", :path => "../gems/a"
G
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
eval_gemfile "nested/Gemfile-nested"
G
end
@@ -95,7 +95,7 @@ RSpec.describe "bundle install with gemfile that uses eval_gemfile" do
it "installs the gemspec specified gem" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
eval_gemfile 'other/Gemfile-other'
gemspec :path => 'gems/gunks'
G
@@ -108,15 +108,15 @@ RSpec.describe "bundle install with gemfile that uses eval_gemfile" do
context "eval-ed Gemfile references other gemfiles" do
it "works with relative paths" do
- create_file "other/Gemfile-other", "gem 'rack'"
- create_file "other/Gemfile", "eval_gemfile 'Gemfile-other'"
- create_file "Gemfile-alt", <<-G
- source "#{file_uri_for(gem_repo1)}"
+ gemfile "other/Gemfile-other", "gem 'myrack'"
+ gemfile "other/Gemfile", "eval_gemfile 'Gemfile-other'"
+ gemfile "Gemfile-alt", <<-G
+ source "https://gem.repo1"
eval_gemfile "other/Gemfile"
G
install_gemfile "eval_gemfile File.expand_path('Gemfile-alt')"
- expect(the_bundle).to include_gem "rack 1.0.0"
+ expect(the_bundle).to include_gem "myrack 1.0.0"
end
end
end
diff --git a/spec/bundler/install/gemfile/force_ruby_platform_spec.rb b/spec/bundler/install/gemfile/force_ruby_platform_spec.rb
index a29b79ad62..bcc1f36823 100644
--- a/spec/bundler/install/gemfile/force_ruby_platform_spec.rb
+++ b/spec/bundler/install/gemfile/force_ruby_platform_spec.rb
@@ -5,77 +5,68 @@ RSpec.describe "bundle install with force_ruby_platform DSL option", :jruby do
before do
build_repo4 do
# Build a gem with platform specific versions
- build_gem("platform_specific") do |s|
- s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 RUBY'"
- end
+ build_gem("platform_specific")
build_gem("platform_specific") do |s|
s.platform = Bundler.local_platform
- s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 #{Bundler.local_platform}'"
end
# Build the exact same gem with a different name to compare using vs not using the option
- build_gem("platform_specific_forced") do |s|
- s.write "lib/platform_specific_forced.rb", "PLATFORM_SPECIFIC_FORCED = '1.0.0 RUBY'"
- end
+ build_gem("platform_specific_forced")
build_gem("platform_specific_forced") do |s|
s.platform = Bundler.local_platform
- s.write "lib/platform_specific_forced.rb", "PLATFORM_SPECIFIC_FORCED = '1.0.0 #{Bundler.local_platform}'"
end
end
end
it "pulls the pure ruby variant of the given gem" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "platform_specific_forced", :force_ruby_platform => true
gem "platform_specific"
G
- expect(the_bundle).to include_gems "platform_specific_forced 1.0.0 RUBY"
- expect(the_bundle).to include_gems "platform_specific 1.0.0 #{Bundler.local_platform}"
+ expect(the_bundle).to include_gems "platform_specific_forced 1.0 ruby"
+ expect(the_bundle).to include_gems "platform_specific 1.0 #{Bundler.local_platform}"
end
it "still respects a global `force_ruby_platform` config" do
install_gemfile <<-G, env: { "BUNDLE_FORCE_RUBY_PLATFORM" => "true" }
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "platform_specific_forced", :force_ruby_platform => true
gem "platform_specific"
G
- expect(the_bundle).to include_gems "platform_specific_forced 1.0.0 RUBY"
- expect(the_bundle).to include_gems "platform_specific 1.0.0 RUBY"
+ expect(the_bundle).to include_gems "platform_specific_forced 1.0 ruby"
+ expect(the_bundle).to include_gems "platform_specific 1.0 ruby"
end
end
context "when also a transitive dependency" do
before do
build_repo4 do
- build_gem("depends_on_platform_specific") {|s| s.add_runtime_dependency "platform_specific" }
+ build_gem("depends_on_platform_specific") {|s| s.add_dependency "platform_specific" }
- build_gem("platform_specific") do |s|
- s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 RUBY'"
- end
+ build_gem("platform_specific")
build_gem("platform_specific") do |s|
s.platform = Bundler.local_platform
- s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 #{Bundler.local_platform}'"
end
end
end
it "still pulls the ruby variant" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "depends_on_platform_specific"
gem "platform_specific", :force_ruby_platform => true
G
- expect(the_bundle).to include_gems "platform_specific 1.0.0 RUBY"
+ expect(the_bundle).to include_gems "platform_specific 1.0 ruby"
end
end
@@ -83,42 +74,39 @@ RSpec.describe "bundle install with force_ruby_platform DSL option", :jruby do
before do
build_repo4 do
build_gem("depends_on_platform_specific") do |s|
- s.add_runtime_dependency "platform_specific"
- s.write "lib/depends_on_platform_specific.rb", "DEPENDS_ON_PLATFORM_SPECIFIC = '1.0.0 RUBY'"
+ s.add_dependency "platform_specific"
end
build_gem("depends_on_platform_specific") do |s|
- s.add_runtime_dependency "platform_specific"
+ s.add_dependency "platform_specific"
s.platform = Bundler.local_platform
- s.write "lib/depends_on_platform_specific.rb", "DEPENDS_ON_PLATFORM_SPECIFIC = '1.0.0 #{Bundler.local_platform}'"
end
- build_gem("platform_specific") do |s|
- s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 RUBY'"
- end
+ build_gem("platform_specific")
build_gem("platform_specific") do |s|
s.platform = Bundler.local_platform
- s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 #{Bundler.local_platform}'"
end
end
end
it "ignores ruby variants for the transitive dependencies" do
install_gemfile <<-G, env: { "DEBUG_RESOLVER" => "true" }
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "depends_on_platform_specific", :force_ruby_platform => true
G
- expect(the_bundle).to include_gems "depends_on_platform_specific 1.0.0 RUBY"
- expect(the_bundle).to include_gems "platform_specific 1.0.0 #{Bundler.local_platform}"
+ expect(the_bundle).to include_gems "depends_on_platform_specific 1.0 ruby"
+ expect(the_bundle).to include_gems "platform_specific 1.0 #{Bundler.local_platform}"
end
- it "reinstalls the ruby variant when a platform specific variant is already installed, the lockile has only RUBY platform, and :force_ruby_platform is used in the Gemfile" do
+ it "reinstalls the ruby variant when a platform specific variant is already installed, the lockile has only ruby platform, and :force_ruby_platform is used in the Gemfile" do
+ skip "Can't simulate platform reliably on JRuby, installing a platform specific gem fails to activate io-wait because only the -java version is present, and we're simulating a different platform" if RUBY_ENGINE == "jruby"
+
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo4)}
+ remote: https://gem.repo4
specs:
platform_specific (1.0)
@@ -129,18 +117,20 @@ RSpec.describe "bundle install with force_ruby_platform DSL option", :jruby do
platform_specific
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
- system_gems "platform_specific-1.0-#{Gem::Platform.local}", path: default_bundle_path
+ simulate_platform "x86-darwin-100" do
+ system_gems "platform_specific-1.0-x86-darwin-100", path: default_bundle_path
- install_gemfile <<-G, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }, artifice: "compact_index"
- source "#{file_uri_for(gem_repo4)}"
+ install_gemfile <<-G, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }, artifice: "compact_index"
+ source "https://gem.repo4"
- gem "platform_specific", :force_ruby_platform => true
- G
+ gem "platform_specific", :force_ruby_platform => true
+ G
- expect(the_bundle).to include_gems "platform_specific 1.0.0 RUBY"
+ expect(the_bundle).to include_gems "platform_specific 1.0 ruby"
+ end
end
end
end
diff --git a/spec/bundler/install/gemfile/gemspec_spec.rb b/spec/bundler/install/gemfile/gemspec_spec.rb
index 63778567cf..3d9766d21f 100644
--- a/spec/bundler/install/gemfile/gemspec_spec.rb
+++ b/spec/bundler/install/gemfile/gemspec_spec.rb
@@ -8,45 +8,15 @@ RSpec.describe "bundle install from an existing gemspec" do
end
end
- let(:x64_mingw_archs) do
- if RUBY_PLATFORM == "x64-mingw-ucrt"
- if Gem.rubygems_version >= Gem::Version.new("3.2.28")
- ["x64-mingw-ucrt", "x64-mingw32"]
- else
- ["x64-mingw32", "x64-unknown"]
- end
- else
- ["x64-mingw32"]
- end
- end
-
- let(:x64_mingw_gems) do
- x64_mingw_archs.map {|p| "platform_specific (1.0-#{p})" }.join("\n ")
- end
-
- let(:x64_mingw_platforms) do
- x64_mingw_archs.join("\n ")
- end
-
- def x64_mingw_checksums(checksums)
- x64_mingw_archs.each do |arch|
- if arch == "x64-mingw-ucrt"
- checksums.no_checksum "platform_specific", "1.0", arch
- else
- checksums.checksum gem_repo2, "platform_specific", "1.0", arch
- end
- end
- end
-
it "should install runtime and development dependencies" do
- build_lib("foo", path: tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp("foo")) do |s|
s.write("Gemfile", "source :rubygems\ngemspec")
s.add_dependency "bar", "=1.0.0"
s.add_development_dependency "bar-dev", "=1.0.0"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gemspec :path => '#{tmp.join("foo")}'
+ source "https://gem.repo2"
+ gemspec :path => '#{tmp("foo")}'
G
expect(the_bundle).to include_gems "bar 1.0.0"
@@ -54,16 +24,16 @@ RSpec.describe "bundle install from an existing gemspec" do
end
it "that is hidden should install runtime and development dependencies" do
- build_lib("foo", path: tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp("foo")) do |s|
s.write("Gemfile", "source :rubygems\ngemspec")
s.add_dependency "bar", "=1.0.0"
s.add_development_dependency "bar-dev", "=1.0.0"
end
- FileUtils.mv tmp.join("foo", "foo.gemspec"), tmp.join("foo", ".gemspec")
+ FileUtils.mv tmp("foo", "foo.gemspec"), tmp("foo", ".gemspec")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gemspec :path => '#{tmp.join("foo")}'
+ source "https://gem.repo2"
+ gemspec :path => '#{tmp("foo")}'
G
expect(the_bundle).to include_gems "bar 1.0.0"
@@ -76,50 +46,50 @@ RSpec.describe "bundle install from an existing gemspec" do
build_gem "baz", "1.1"
end
- build_lib("foo", path: tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp("foo")) do |s|
s.write("Gemfile", "source :rubygems\ngemspec")
s.add_dependency "baz", ">= 1.0", "< 1.1"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gemspec :path => '#{tmp.join("foo")}'
+ source "https://gem.repo2"
+ gemspec :path => '#{tmp("foo")}'
G
expect(the_bundle).to include_gems "baz 1.0"
end
it "should raise if there are no gemspecs available" do
- build_lib("foo", path: tmp.join("foo"), gemspec: false)
+ build_lib("foo", path: tmp("foo"), gemspec: false)
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo2)}"
- gemspec :path => '#{tmp.join("foo")}'
+ source "https://gem.repo2"
+ gemspec :path => '#{tmp("foo")}'
G
- expect(err).to match(/There are no gemspecs at #{tmp.join("foo")}/)
+ expect(err).to match(/There are no gemspecs at #{tmp("foo")}/)
end
it "should raise if there are too many gemspecs available" do
- build_lib("foo", path: tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp("foo")) do |s|
s.write("foo2.gemspec", build_spec("foo", "4.0").first.to_ruby)
end
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo2)}"
- gemspec :path => '#{tmp.join("foo")}'
+ source "https://gem.repo2"
+ gemspec :path => '#{tmp("foo")}'
G
- expect(err).to match(/There are multiple gemspecs at #{tmp.join("foo")}/)
+ expect(err).to match(/There are multiple gemspecs at #{tmp("foo")}/)
end
it "should pick a specific gemspec" do
- build_lib("foo", path: tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp("foo")) do |s|
s.write("foo2.gemspec", "")
s.add_dependency "bar", "=1.0.0"
s.add_development_dependency "bar-dev", "=1.0.0"
end
install_gemfile(<<-G)
- source "#{file_uri_for(gem_repo2)}"
- gemspec :path => '#{tmp.join("foo")}', :name => 'foo'
+ source "https://gem.repo2"
+ gemspec :path => '#{tmp("foo")}', :name => 'foo'
G
expect(the_bundle).to include_gems "bar 1.0.0"
@@ -127,15 +97,15 @@ RSpec.describe "bundle install from an existing gemspec" do
end
it "should use a specific group for development dependencies" do
- build_lib("foo", path: tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp("foo")) do |s|
s.write("foo2.gemspec", "")
s.add_dependency "bar", "=1.0.0"
s.add_development_dependency "bar-dev", "=1.0.0"
end
install_gemfile(<<-G)
- source "#{file_uri_for(gem_repo2)}"
- gemspec :path => '#{tmp.join("foo")}', :name => 'foo', :development_group => :dev
+ source "https://gem.repo2"
+ gemspec :path => '#{tmp("foo")}', :name => 'foo', :development_group => :dev
G
expect(the_bundle).to include_gems "bar 1.0.0"
@@ -144,33 +114,33 @@ RSpec.describe "bundle install from an existing gemspec" do
end
it "should match a lockfile even if the gemspec defines development dependencies" do
- build_lib("foo", path: tmp.join("foo")) do |s|
- s.write("Gemfile", "source '#{file_uri_for(gem_repo1)}'\ngemspec")
+ build_lib("foo", path: tmp("foo")) do |s|
+ s.write("Gemfile", "source 'https://gem.repo1'\ngemspec")
s.add_dependency "actionpack", "=2.3.2"
s.add_development_dependency "rake", rake_version
end
- bundle "install", dir: tmp.join("foo")
+ bundle "install", dir: tmp("foo"), artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
# 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"))
+ output = bundle("install", dir: tmp("foo"), artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s })
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(/the lockfile can't be updated because frozen mode is set/)
end
it "should match a lockfile without needing to re-resolve" do
- build_lib("foo", path: tmp.join("foo")) do |s|
- s.add_dependency "rack"
+ build_lib("foo", path: tmp("foo")) do |s|
+ s.add_dependency "myrack"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gemspec :path => '#{tmp.join("foo")}'
+ source "https://gem.repo1"
+ gemspec :path => '#{tmp("foo")}'
G
bundle "install", verbose: true
@@ -180,49 +150,49 @@ RSpec.describe "bundle install from an existing gemspec" do
end
it "should match a lockfile without needing to re-resolve with development dependencies" do
- simulate_platform java
-
- build_lib("foo", path: tmp.join("foo")) do |s|
- s.add_dependency "rack"
- s.add_development_dependency "thin"
- end
+ simulate_platform "java" do
+ build_lib("foo", path: tmp("foo")) do |s|
+ s.add_dependency "myrack"
+ s.add_development_dependency "thin"
+ end
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gemspec :path => '#{tmp.join("foo")}'
- G
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gemspec :path => '#{tmp("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)
+ message = "Found no changes, using resolution from the lockfile"
+ expect(out.scan(message).size).to eq(1)
+ end
end
it "should match a lockfile on non-ruby platforms with a transitive platform dependency", :jruby_only do
- build_lib("foo", path: tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp("foo")) do |s|
s.add_dependency "platform_specific"
end
system_gems "platform_specific-1.0-java", path: default_bundle_path
install_gemfile <<-G
- gemspec :path => '#{tmp.join("foo")}'
+ gemspec :path => '#{tmp("foo")}'
G
bundle "update --bundler", artifice: "compact_index", verbose: true
- expect(the_bundle).to include_gems "foo 1.0", "platform_specific 1.0 JAVA"
+ expect(the_bundle).to include_gems "foo 1.0", "platform_specific 1.0 java"
end
it "should evaluate the gemspec in its directory" do
- build_lib("foo", path: tmp.join("foo"))
- File.open(tmp.join("foo/foo.gemspec"), "w") do |s|
- s.write "raise 'ahh' unless Dir.pwd == '#{tmp.join("foo")}'"
+ build_lib("foo", path: tmp("foo"))
+ File.open(tmp("foo/foo.gemspec"), "w") do |s|
+ s.write "raise 'ahh' unless Dir.pwd == '#{tmp("foo")}'"
end
install_gemfile <<-G, raise_on_error: false
- gemspec :path => '#{tmp.join("foo")}'
+ gemspec :path => '#{tmp("foo")}'
G
- expect(last_command.stdboth).not_to include("ahh")
+ expect(stdboth).not_to include("ahh")
end
it "allows the gemspec to activate other gems" do
@@ -231,16 +201,16 @@ RSpec.describe "bundle install from an existing gemspec" do
#
# issue was caused by rubygems having an unresolved gem during a require,
# so emulate that
- system_gems %w[rack-1.0.0 rack-0.9.1 rack-obama-1.0]
+ system_gems %w[myrack-1.0.0 myrack-0.9.1 myrack-obama-1.0]
build_lib("foo", path: bundled_app)
gemspec = bundled_app("foo.gemspec").read
bundled_app("foo.gemspec").open("w") do |f|
- f.write "#{gemspec.strip}.tap { gem 'rack-obama'; require 'rack/obama' }"
+ f.write "#{gemspec.strip}.tap { gem 'myrack-obama'; require 'myrack/obama' }"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gemspec
G
@@ -248,7 +218,7 @@ RSpec.describe "bundle install from an existing gemspec" do
end
it "allows conflicts" do
- build_lib("foo", path: tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp("foo")) do |s|
s.version = "1.0.0"
s.add_dependency "bar", "= 1.0.0"
end
@@ -258,16 +228,16 @@ RSpec.describe "bundle install from an existing gemspec" do
build_gem "foo", "0.0.1", to_bundle: true
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "deps"
- gemspec :path => '#{tmp.join("foo")}', :name => 'foo'
+ gemspec :path => '#{tmp("foo")}', :name => 'foo'
G
expect(the_bundle).to include_gems "foo 1.0.0"
end
it "does not break Gem.finish_resolve with conflicts" do
- build_lib("foo", path: tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp("foo")) do |s|
s.version = "1.0.0"
s.add_dependency "bar", "= 1.0.0"
end
@@ -279,9 +249,9 @@ RSpec.describe "bundle install from an existing gemspec" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "deps"
- gemspec :path => '#{tmp.join("foo")}', :name => 'foo'
+ gemspec :path => '#{tmp("foo")}', :name => 'foo'
G
expect(the_bundle).to include_gems "foo 1.0.0"
@@ -290,11 +260,30 @@ RSpec.describe "bundle install from an existing gemspec" do
expect(out).to eq("WIN")
end
+ it "does not make Gem.try_activate warn when local gem has extensions" do
+ build_lib("foo", path: tmp("foo")) do |s|
+ s.version = "1.0.0"
+ s.add_c_extension
+ end
+ build_repo2
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gemspec :path => '#{tmp("foo")}'
+ G
+
+ expect(the_bundle).to include_gems "foo 1.0.0"
+
+ run "Gem.try_activate('irb/lc/es/error.rb'); puts 'WIN'"
+ expect(out).to eq("WIN")
+ expect(err).to be_empty
+ end
+
it "handles downgrades" do
build_lib "omg", "2.0", path: lib_path("omg")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gemspec :path => "#{lib_path("omg")}"
G
@@ -313,7 +302,7 @@ RSpec.describe "bundle install from an existing gemspec" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gemspec
G
@@ -335,23 +324,23 @@ RSpec.describe "bundle install from an existing gemspec" do
before do
# build the "parent" gem that depends on another gem in the same repo
build_lib "source_conflict", path: bundled_app do |s|
- s.add_dependency "rack_middleware"
+ s.add_dependency "myrack_middleware"
end
# build the "child" gem that is the same version as a released gem, but
# has completely different and conflicting dependency requirements
- build_lib "rack_middleware", "1.0", path: bundled_app("rack_middleware") do |s|
- s.add_dependency "rack", "1.0" # anything other than 0.9.1
+ build_lib "myrack_middleware", "1.0", path: bundled_app("myrack_middleware") do |s|
+ s.add_dependency "myrack", "1.0" # anything other than 0.9.1
end
end
it "should install the child gemspec's deps" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gemspec
G
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
end
@@ -359,8 +348,8 @@ RSpec.describe "bundle install from an existing gemspec" do
let(:source_uri) { "http://localgemserver.test" }
before do
- build_lib("foo", path: tmp.join("foo")) do |s|
- s.add_dependency "rack", "=1.0.0"
+ build_lib("foo", path: tmp("foo")) do |s|
+ s.add_dependency "myrack", "=1.0.0"
end
gemfile <<-G
@@ -368,7 +357,7 @@ RSpec.describe "bundle install from an existing gemspec" do
gemspec :path => "../foo"
G
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "foo", "1.0"
end
@@ -377,30 +366,30 @@ RSpec.describe "bundle install from an existing gemspec" do
remote: ../foo
specs:
foo (1.0)
- rack (= 1.0.0)
+ myrack (= 1.0.0)
GEM
remote: #{source_uri}
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
- #{generic_local_platform}
+ ruby
DEPENDENCIES
foo!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
context "using JRuby with explicit platform", :jruby_only do
before do
create_file(
- tmp.join("foo", "foo-java.gemspec"),
+ tmp("foo", "foo-java.gemspec"),
build_spec("foo", "1.0", "java") do
- dep "rack", "=1.0.0"
+ dep "myrack", "=1.0.0"
@spec.authors = "authors"
@spec.summary = "summary"
end.first.to_ruby
@@ -409,15 +398,15 @@ RSpec.describe "bundle install from an existing gemspec" do
it "should install" 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"
+ expect(results).to include("Installing myrack 1.0.0")
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
it "should install", :jruby 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"
+ expect(results).to include("Installing myrack 1.0.0")
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
context "bundled for multiple platforms" do
@@ -431,17 +420,18 @@ RSpec.describe "bundle install from an existing gemspec" do
end
build_lib "foo", path: bundled_app do |s|
- if platform_specific_type == :runtime
+ case platform_specific_type
+ when :runtime
s.add_runtime_dependency dependency
- elsif platform_specific_type == :development
+ when :development
s.add_development_dependency dependency
else
- raise "wrong dependency type #{platform_specific_type}, can only be :development or :runtime"
+ raise ArgumentError, "wrong dependency type #{platform_specific_type}, can only be :development or :runtime"
end
end
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gemspec
G
@@ -450,7 +440,8 @@ RSpec.describe "bundle install from an existing gemspec" do
simulate_new_machine
simulate_platform("jruby") { bundle "install" }
- simulate_platform(x64_mingw32) { bundle "install" }
+ expect(lockfile).to include("platform_specific (1.0-java)")
+ simulate_platform("x64-mingw-ucrt") { bundle "install" }
end
context "on ruby" do
@@ -461,13 +452,13 @@ RSpec.describe "bundle install from an existing gemspec" do
context "as a runtime dependency" do
it "keeps all platform dependencies in the lockfile" do
- expect(the_bundle).to include_gems "foo 1.0", "platform_specific 1.0 RUBY"
+ expect(the_bundle).to include_gems "foo 1.0", "platform_specific 1.0 ruby"
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "foo", "1.0"
c.checksum gem_repo2, "platform_specific", "1.0"
c.checksum gem_repo2, "platform_specific", "1.0", "java"
- x64_mingw_checksums(c)
+ c.checksum gem_repo2, "platform_specific", "1.0", "x64-mingw-ucrt"
end
expect(lockfile).to eq <<~L
@@ -478,22 +469,22 @@ RSpec.describe "bundle install from an existing gemspec" do
platform_specific
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
platform_specific (1.0)
platform_specific (1.0-java)
- #{x64_mingw_gems}
+ platform_specific (1.0-x64-mingw-ucrt)
PLATFORMS
java
ruby
- #{x64_mingw_platforms}
+ x64-mingw-ucrt
DEPENDENCIES
foo!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
@@ -502,13 +493,13 @@ RSpec.describe "bundle install from an existing gemspec" do
let(:platform_specific_type) { :development }
it "keeps all platform dependencies in the lockfile" do
- expect(the_bundle).to include_gems "foo 1.0", "platform_specific 1.0 RUBY"
+ expect(the_bundle).to include_gems "foo 1.0", "platform_specific 1.0 ruby"
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "foo", "1.0"
c.checksum gem_repo2, "platform_specific", "1.0"
c.checksum gem_repo2, "platform_specific", "1.0", "java"
- x64_mingw_checksums(c)
+ c.checksum gem_repo2, "platform_specific", "1.0", "x64-mingw-ucrt"
end
expect(lockfile).to eq <<~L
@@ -518,23 +509,23 @@ RSpec.describe "bundle install from an existing gemspec" do
foo (1.0)
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
platform_specific (1.0)
platform_specific (1.0-java)
- #{x64_mingw_gems}
+ platform_specific (1.0-x64-mingw-ucrt)
PLATFORMS
java
ruby
- #{x64_mingw_platforms}
+ x64-mingw-ucrt
DEPENDENCIES
foo!
platform_specific
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
@@ -544,14 +535,14 @@ RSpec.describe "bundle install from an existing gemspec" do
let(:dependency) { "indirect_platform_specific" }
it "keeps all platform dependencies in the lockfile" do
- expect(the_bundle).to include_gems "foo 1.0", "indirect_platform_specific 1.0", "platform_specific 1.0 RUBY"
+ expect(the_bundle).to include_gems "foo 1.0", "indirect_platform_specific 1.0", "platform_specific 1.0 ruby"
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "foo", "1.0"
c.checksum gem_repo2, "indirect_platform_specific", "1.0"
c.checksum gem_repo2, "platform_specific", "1.0"
c.checksum gem_repo2, "platform_specific", "1.0", "java"
- x64_mingw_checksums(c)
+ c.checksum gem_repo2, "platform_specific", "1.0", "x64-mingw-ucrt"
end
expect(lockfile).to eq <<~L
@@ -561,25 +552,25 @@ RSpec.describe "bundle install from an existing gemspec" do
foo (1.0)
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
indirect_platform_specific (1.0)
platform_specific
platform_specific (1.0)
platform_specific (1.0-java)
- #{x64_mingw_gems}
+ platform_specific (1.0-x64-mingw-ucrt)
PLATFORMS
java
ruby
- #{x64_mingw_platforms}
+ x64-mingw-ucrt
DEPENDENCIES
foo!
indirect_platform_specific
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
@@ -589,10 +580,10 @@ RSpec.describe "bundle install from an existing gemspec" do
context "with multiple platforms" do
before do
- build_lib("foo", path: tmp.join("foo")) do |s|
+ build_lib("foo", path: tmp("foo")) do |s|
s.version = "1.0.0"
- s.add_development_dependency "rack"
- s.write "foo-universal-java.gemspec", build_spec("foo", "1.0.0", "universal-java") {|sj| sj.runtime "rack", "1.0.0" }.first.to_ruby
+ s.add_development_dependency "myrack"
+ s.write "foo-universal-java.gemspec", build_spec("foo", "1.0.0", "universal-java") {|sj| sj.runtime "myrack", "1.0.0" }.first.to_ruby
end
end
@@ -600,11 +591,11 @@ RSpec.describe "bundle install from an existing gemspec" do
bundle "config set --local force_ruby_platform true"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gemspec :path => '#{tmp.join("foo")}', :name => 'foo'
+ source "https://gem.repo1"
+ gemspec :path => '#{tmp("foo")}', :name => 'foo'
G
- expect(the_bundle).to include_gems "foo 1.0.0", "rack 1.0.0"
+ expect(the_bundle).to include_gems "foo 1.0.0", "myrack 1.0.0"
end
it "installs the ruby platform gemspec and skips dev deps with `without development` configured" do
@@ -612,39 +603,39 @@ RSpec.describe "bundle install from an existing gemspec" do
bundle "config set --local without development"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gemspec :path => '#{tmp.join("foo")}', :name => 'foo'
+ source "https://gem.repo1"
+ gemspec :path => '#{tmp("foo")}', :name => 'foo'
G
expect(the_bundle).to include_gem "foo 1.0.0"
- expect(the_bundle).not_to include_gem "rack"
+ expect(the_bundle).not_to include_gem "myrack"
end
end
context "with multiple platforms and resolving for more specific platforms" do
before do
- build_lib("chef", path: tmp.join("chef")) do |s|
+ build_lib("chef", path: tmp("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
+ s.write "chef-universal-mingw-ucrt.gemspec", build_spec("chef", "17.1.17", "universal-mingw-ucrt") {|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"
+ s.platform = "universal-mingw-ucrt"
end
end
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gemspec :path => "../chef"
G
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "chef", "17.1.17"
- c.no_checksum "chef", "17.1.17", "universal-mingw32"
- c.checksum gem_repo4, "win32-api", "1.5.3", "universal-mingw32"
+ c.no_checksum "chef", "17.1.17", "universal-mingw-ucrt"
+ c.checksum gem_repo4, "win32-api", "1.5.3", "universal-mingw-ucrt"
end
initial_lockfile = <<~L
@@ -652,24 +643,22 @@ RSpec.describe "bundle install from an existing gemspec" do
remote: ../chef
specs:
chef (17.1.17)
- chef (17.1.17-universal-mingw32)
+ chef (17.1.17-universal-mingw-ucrt)
win32-api (~> 1.5.3)
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
- win32-api (1.5.3-universal-mingw32)
+ win32-api (1.5.3-universal-mingw-ucrt)
PLATFORMS
- ruby
- #{x64_mingw_platforms}
- x86-mingw32
+ #{lockfile_platforms("ruby", "x64-mingw-ucrt", "x86-mingw32")}
DEPENDENCIES
chef!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
lockfile initial_lockfile
@@ -682,7 +671,7 @@ RSpec.describe "bundle install from an existing gemspec" do
context "with multiple locked platforms" do
before do
- build_lib("activeadmin", path: tmp.join("activeadmin")) do |s|
+ build_lib("activeadmin", path: tmp("activeadmin")) do |s|
s.version = "2.9.0"
s.add_dependency "railties", ">= 5.2", "< 6.2"
end
@@ -696,7 +685,7 @@ RSpec.describe "bundle install from an existing gemspec" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gemspec :path => "../activeadmin"
gem "jruby-openssl", :platform => :jruby
G
@@ -705,9 +694,9 @@ RSpec.describe "bundle install from an existing gemspec" do
end
it "does not remove the platform specific specs from the lockfile when re-resolving due to gemspec changes" do
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "activeadmin", "2.9.0"
- c.no_checksum "jruby-openssl", "0.10.7", "java"
+ c.checksum gem_repo4, "jruby-openssl", "0.10.7", "java"
c.checksum gem_repo4, "railties", "6.1.4"
end
@@ -719,7 +708,7 @@ RSpec.describe "bundle install from an existing gemspec" do
railties (>= 5.2, < 6.2)
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
jruby-openssl (0.10.7-java)
railties (6.1.4)
@@ -732,10 +721,10 @@ RSpec.describe "bundle install from an existing gemspec" do
jruby-openssl
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
- gemspec = tmp.join("activeadmin/activeadmin.gemspec")
+ gemspec = tmp("activeadmin/activeadmin.gemspec")
File.write(gemspec, File.read(gemspec).sub(">= 5.2", ">= 6.0"))
previous_lockfile = lockfile
diff --git a/spec/bundler/install/gemfile/git_spec.rb b/spec/bundler/install/gemfile/git_spec.rb
index 24cf30eadb..ed1c52f099 100644
--- a/spec/bundler/install/gemfile/git_spec.rb
+++ b/spec/bundler/install/gemfile/git_spec.rb
@@ -2,20 +2,25 @@
RSpec.describe "bundle install with git sources" do
describe "when floating on main" do
- before :each do
- build_git "foo" do |s|
- s.executables = "foobar"
- end
-
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ let(:base_gemfile) do
+ <<-G
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}" do
gem 'foo'
end
G
end
+ let(:install_base_gemfile) do
+ build_git "foo" do |s|
+ s.executables = "foobar"
+ end
+
+ install_gemfile base_gemfile
+ end
+
it "fetches gems" do
+ install_base_gemfile
expect(the_bundle).to include_gems("foo 1.0")
run <<-RUBY
@@ -26,19 +31,58 @@ RSpec.describe "bundle install with git sources" do
expect(out).to eq("WIN")
end
- it "caches the git repo", bundler: "< 3" do
- expect(Dir["#{default_bundle_path}/cache/bundler/git/foo-1.0-*"]).to have_attributes size: 1
+ it "does not (yet?) enforce CHECKSUMS" do
+ build_git "foo"
+ revision = revision_for(lib_path("foo-1.0"))
+
+ bundle "config set lockfile_checksums true"
+ gemfile base_gemfile
+
+ lockfile <<~L
+ GIT
+ remote: #{lib_path("foo-1.0")}
+ revision: #{revision}
+ specs:
+ foo (1.0)
+
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+
+ CHECKSUMS
+ foo (1.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "config set frozen true"
+
+ bundle "install"
+ expect(the_bundle).to include_gems("foo 1.0")
+ end
+
+ it "caches the git repo" do
+ install_base_gemfile
+ expect(Dir["#{default_cache_path}/git/foo-1.0-*"]).to have_attributes size: 1
end
it "does not write to cache on bundler/setup" do
- cache_path = default_bundle_path.join("cache")
- FileUtils.rm_rf(cache_path)
+ install_base_gemfile
+ FileUtils.rm_r(default_cache_path)
ruby "require 'bundler/setup'"
- expect(cache_path).not_to exist
+ expect(default_cache_path).not_to exist
end
it "caches the git repo globally and properly uses the cached repo on the next invocation" do
- simulate_new_machine
+ install_base_gemfile
+ pristine_system_gems
bundle "config set global_gem_cache true"
bundle :install
expect(Dir["#{home}/.bundle/cache/git/foo-1.0-*"]).to have_attributes size: 1
@@ -49,6 +93,7 @@ RSpec.describe "bundle install with git sources" do
end
it "caches the evaluated gemspec" do
+ install_base_gemfile
git = update_git "foo" do |s|
s.executables = ["foobar"] # we added this the first time, so keep it now
s.files = ["bin/foobar"] # updating git nukes the files list
@@ -59,7 +104,7 @@ RSpec.describe "bundle install with git sources" do
bundle "update foo"
sha = git.ref_for("main", 11)
- spec_file = default_bundle_path.join("bundler/gems/foo-1.0-#{sha}/foo.gemspec")
+ spec_file = default_bundle_path("bundler/gems/foo-1.0-#{sha}/foo.gemspec")
expect(spec_file).to exist
ruby_code = Gem::Specification.load(spec_file.to_s).to_ruby
file_code = File.read(spec_file)
@@ -67,10 +112,11 @@ RSpec.describe "bundle install with git sources" do
end
it "does not update the git source implicitly" do
+ install_base_gemfile
update_git "foo"
install_gemfile bundled_app2("Gemfile"), <<-G, dir: bundled_app2
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}" do
gem 'foo'
end
@@ -85,6 +131,7 @@ RSpec.describe "bundle install with git sources" do
end
it "sets up git gem executables on the path" do
+ install_base_gemfile
bundle "exec foobar"
expect(out).to eq("1.0")
end
@@ -93,7 +140,7 @@ RSpec.describe "bundle install with git sources" do
build_git "foo"
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", "1.1", :git => "#{lib_path("foo-1.0")}"
G
@@ -106,7 +153,7 @@ RSpec.describe "bundle install with git sources" do
end
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
platforms :jruby do
gem "only_java", "1.2", :git => "#{lib_path("only_java-1.0-java")}"
end
@@ -126,7 +173,7 @@ RSpec.describe "bundle install with git sources" do
end
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
platforms :jruby do
gem "only_java", "1.2", :git => "#{lib_path("only_java-1.1-java")}"
end
@@ -137,7 +184,7 @@ RSpec.describe "bundle install with git sources" do
it "still works after moving the application directory" do
bundle "config set --local path vendor/bundle"
- bundle "install"
+ install_base_gemfile
FileUtils.mv bundled_app, tmp("bundled_app.bck")
@@ -146,24 +193,24 @@ RSpec.describe "bundle install with git sources" do
it "can still install after moving the application directory" do
bundle "config set --local path vendor/bundle"
- bundle "install"
+ install_base_gemfile
FileUtils.mv bundled_app, tmp("bundled_app.bck")
update_git "foo", "1.1", path: lib_path("foo-1.0")
gemfile tmp("bundled_app.bck/Gemfile"), <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}" do
gem 'foo'
end
- gem "rack", "1.0"
+ gem "myrack", "1.0"
G
bundle "update foo", dir: tmp("bundled_app.bck")
- expect(the_bundle).to include_gems "foo 1.1", "rack 1.0", dir: tmp("bundled_app.bck")
+ expect(the_bundle).to include_gems "foo 1.1", "myrack 1.0", dir: tmp("bundled_app.bck")
end
end
@@ -171,8 +218,8 @@ RSpec.describe "bundle install with git sources" do
before do
build_git "foo"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
git "#{lib_path("foo-1.0")}" do
# this page left intentionally blank
@@ -182,7 +229,7 @@ RSpec.describe "bundle install with git sources" do
it "does not explode" do
bundle "install"
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
end
@@ -195,7 +242,7 @@ RSpec.describe "bundle install with git sources" do
it "works" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}", :ref => "#{@revision}" do
gem "foo"
end
@@ -212,7 +259,7 @@ RSpec.describe "bundle install with git sources" do
it "works when the revision is a symbol" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}", :ref => #{@revision.to_sym.inspect} do
gem "foo"
end
@@ -229,14 +276,14 @@ RSpec.describe "bundle install with git sources" do
it "works when an abbreviated revision is added after an initial, potentially shallow clone" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}" do
gem "foo"
end
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}", :ref => #{@revision[0..7].inspect} do
gem "foo"
end
@@ -246,11 +293,11 @@ RSpec.describe "bundle install with git sources" do
it "works when a tag that does not look like a commit hash is used as the value of :ref" do
build_git "foo"
@remote = build_git("bar", bare: true)
- update_git "foo", remote: file_uri_for(@remote.path)
+ update_git "foo", remote: @remote.path
update_git "foo", push: "main"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'foo', :git => "#{@remote.path}"
G
@@ -259,7 +306,7 @@ RSpec.describe "bundle install with git sources" do
update_git "foo", push: "v1.0.0"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'foo', :git => "#{@remote.path}", :ref => "v1.0.0"
G
@@ -272,7 +319,7 @@ RSpec.describe "bundle install with git sources" do
s.write("lib/foo.rb", "raise 'FAIL'")
end
- sys_exec("git update-ref -m \"Bundler Spec!\" refs/bundler/1 main~1", dir: lib_path("foo-1.0"))
+ git("update-ref -m \"Bundler Spec!\" refs/bundler/1 main~1", 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|
@@ -280,7 +327,7 @@ RSpec.describe "bundle install with git sources" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}", :ref => "refs/bundler/1" do
gem "foo"
end
@@ -297,7 +344,7 @@ RSpec.describe "bundle install with git sources" do
it "works when the revision is a non-head ref and it was previously downloaded" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}" do
gem "foo"
end
@@ -308,7 +355,7 @@ RSpec.describe "bundle install with git sources" do
s.write("lib/foo.rb", "raise 'FAIL'")
end
- sys_exec("git update-ref -m \"Bundler Spec!\" refs/bundler/1 main~1", dir: lib_path("foo-1.0"))
+ git("update-ref -m \"Bundler Spec!\" refs/bundler/1 main~1", 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|
@@ -316,7 +363,7 @@ RSpec.describe "bundle install with git sources" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}", :ref => "refs/bundler/1" do
gem "foo"
end
@@ -332,12 +379,12 @@ RSpec.describe "bundle install with git sources" do
end
it "does not download random non-head refs" do
- sys_exec("git update-ref -m \"Bundler Spec!\" refs/bundler/1 main~1", dir: lib_path("foo-1.0"))
+ git("update-ref -m \"Bundler Spec!\" refs/bundler/1 main~1", lib_path("foo-1.0"))
bundle "config set global_gem_cache true"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}" do
gem "foo"
end
@@ -346,7 +393,7 @@ RSpec.describe "bundle install with git sources" do
# ensure we also git fetch after cloning
bundle :update, all: true
- sys_exec("git ls-remote .", dir: Dir[home(".bundle/cache/git/foo-*")].first)
+ git("ls-remote .", Dir[home(".bundle/cache/git/foo-*")].first)
expect(out).not_to include("refs/bundler/1")
end
@@ -360,7 +407,7 @@ RSpec.describe "bundle install with git sources" do
update_git("foo", path: repo, branch: branch)
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{repo}", :branch => #{branch.dump} do
gem "foo"
end
@@ -377,7 +424,7 @@ RSpec.describe "bundle install with git sources" do
update_git("foo", path: repo, branch: branch)
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{repo}", :branch => #{branch.dump} do
gem "foo"
end
@@ -395,7 +442,7 @@ RSpec.describe "bundle install with git sources" do
update_git("foo", path: repo, branch: branch)
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{repo}", :branch => #{branch.dump} do
gem "foo"
end
@@ -414,7 +461,7 @@ RSpec.describe "bundle install with git sources" do
update_git("foo", path: repo, tag: tag)
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{repo}", :tag => #{tag.dump} do
gem "foo"
end
@@ -431,7 +478,7 @@ RSpec.describe "bundle install with git sources" do
update_git("foo", path: repo, tag: tag)
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{repo}", :tag => #{tag.dump} do
gem "foo"
end
@@ -449,7 +496,7 @@ RSpec.describe "bundle install with git sources" do
update_git("foo", path: repo, tag: tag)
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{repo}", :tag => #{tag.dump} do
gem "foo"
end
@@ -462,100 +509,100 @@ RSpec.describe "bundle install with git sources" do
describe "when specifying local override" do
it "uses the local repository instead of checking a new one out" do
- build_git "rack", "0.8", path: lib_path("local-rack") do |s|
- s.write "lib/rack.rb", "puts :LOCAL"
+ build_git "myrack", "0.8", path: lib_path("local-myrack") do |s|
+ s.write "lib/myrack.rb", "puts :LOCAL"
end
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
G
- bundle %(config set local.rack #{lib_path("local-rack")})
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
bundle :install
- run "require 'rack'"
+ run "require 'myrack'"
expect(out).to eq("LOCAL")
end
it "chooses the local repository on runtime" do
- build_git "rack", "0.8"
+ build_git "myrack", "0.8"
- FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
+ FileUtils.cp_r("#{lib_path("myrack-0.8")}/.", lib_path("local-myrack"))
- update_git "rack", "0.8", path: lib_path("local-rack") do |s|
- s.write "lib/rack.rb", "puts :LOCAL"
+ update_git "myrack", "0.8", path: lib_path("local-myrack") do |s|
+ s.write "lib/myrack.rb", "puts :LOCAL"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
G
- bundle %(config set local.rack #{lib_path("local-rack")})
- run "require 'rack'"
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
+ run "require 'myrack'"
expect(out).to eq("LOCAL")
end
it "unlocks the source when the dependencies have changed while switching to the local" do
- build_git "rack", "0.8"
+ build_git "myrack", "0.8"
- FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
+ FileUtils.cp_r("#{lib_path("myrack-0.8")}/.", lib_path("local-myrack"))
- update_git "rack", "0.8", path: lib_path("local-rack") do |s|
- s.write "rack.gemspec", build_spec("rack", "0.8") { runtime "rspec", "> 0" }.first.to_ruby
- s.write "lib/rack.rb", "puts :LOCAL"
+ update_git "myrack", "0.8", path: lib_path("local-myrack") do |s|
+ s.write "myrack.gemspec", build_spec("myrack", "0.8") { runtime "rspec", "> 0" }.first.to_ruby
+ s.write "lib/myrack.rb", "puts :LOCAL"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
G
- bundle %(config set local.rack #{lib_path("local-rack")})
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
bundle :install
- run "require 'rack'"
+ run "require 'myrack'"
expect(out).to eq("LOCAL")
end
it "updates specs on runtime" do
system_gems "nokogiri-1.4.2"
- build_git "rack", "0.8"
+ build_git "myrack", "0.8"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
G
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|
+ FileUtils.cp_r("#{lib_path("myrack-0.8")}/.", lib_path("local-myrack"))
+ update_git "myrack", "0.8", path: lib_path("local-myrack") do |s|
s.add_dependency "nokogiri", "1.4.2"
end
- bundle %(config set local.rack #{lib_path("local-rack")})
- run "require 'rack'"
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
+ run "require 'myrack'"
lockfile1 = File.read(bundled_app_lock)
expect(lockfile1).not_to eq(lockfile0)
end
it "updates ref on install" do
- build_git "rack", "0.8"
+ build_git "myrack", "0.8"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
G
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")
+ FileUtils.cp_r("#{lib_path("myrack-0.8")}/.", lib_path("local-myrack"))
+ update_git "myrack", "0.8", path: lib_path("local-myrack")
- bundle %(config set local.rack #{lib_path("local-rack")})
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
bundle :install
lockfile1 = File.read(bundled_app_lock)
@@ -563,18 +610,18 @@ RSpec.describe "bundle install with git sources" do
end
it "explodes and gives correct solution if given path does not exist on install" do
- build_git "rack", "0.8"
+ build_git "myrack", "0.8"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
G
- bundle %(config set local.rack #{lib_path("local-rack")})
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
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/)
+ expect(err).to match(/Cannot use local override for myrack-0.8 because #{Regexp.escape(lib_path("local-myrack").to_s)} does not exist/)
- solution = "config unset local.rack"
+ solution = "config unset local.myrack"
expect(err).to match(/Run `bundle #{solution}` to remove the local override/)
bundle solution
@@ -584,19 +631,19 @@ RSpec.describe "bundle install with git sources" do
end
it "explodes and gives correct solution if branch is not given on install" do
- build_git "rack", "0.8"
- FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
+ build_git "myrack", "0.8"
+ FileUtils.cp_r("#{lib_path("myrack-0.8")}/.", lib_path("local-myrack"))
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}"
G
- bundle %(config set local.rack #{lib_path("local-rack")})
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
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/)
+ expect(err).to match(/Cannot use local override for myrack-0.8 at #{Regexp.escape(lib_path("local-myrack").to_s)} because :branch is not specified in Gemfile/)
- solution = "config unset local.rack"
+ solution = "config unset local.myrack"
expect(err).to match(/Specify a branch or run `bundle #{solution}` to remove the local override/)
bundle solution
@@ -606,69 +653,69 @@ RSpec.describe "bundle install with git sources" do
end
it "does not explode if disable_local_branch_check is given" do
- build_git "rack", "0.8"
- FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
+ build_git "myrack", "0.8"
+ FileUtils.cp_r("#{lib_path("myrack-0.8")}/.", lib_path("local-myrack"))
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}"
G
- bundle %(config set local.rack #{lib_path("local-rack")})
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
bundle %(config set disable_local_branch_check true)
bundle :install
expect(out).to match(/Bundle complete!/)
end
it "explodes on different branches on install" do
- build_git "rack", "0.8"
+ build_git "myrack", "0.8"
- FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
+ FileUtils.cp_r("#{lib_path("myrack-0.8")}/.", lib_path("local-myrack"))
- update_git "rack", "0.8", path: lib_path("local-rack"), branch: "another" do |s|
- s.write "lib/rack.rb", "puts :LOCAL"
+ update_git "myrack", "0.8", path: lib_path("local-myrack"), branch: "another" do |s|
+ s.write "lib/myrack.rb", "puts :LOCAL"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
G
- bundle %(config set local.rack #{lib_path("local-rack")})
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
bundle :install, raise_on_error: false
expect(err).to match(/is using branch another but Gemfile specifies main/)
end
it "explodes on invalid revision on install" do
- build_git "rack", "0.8"
+ build_git "myrack", "0.8"
- build_git "rack", "0.8", path: lib_path("local-rack") do |s|
- s.write "lib/rack.rb", "puts :LOCAL"
+ build_git "myrack", "0.8", path: lib_path("local-myrack") do |s|
+ s.write "lib/myrack.rb", "puts :LOCAL"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
G
- bundle %(config set local.rack #{lib_path("local-rack")})
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
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 "myrack", "0.8"
- build_git "rack", "0.8", path: lib_path("local-rack") do |s|
- s.write "lib/rack.rb", "puts :LOCAL"
+ build_git "myrack", "0.8", path: lib_path("local-myrack") do |s|
+ s.write "lib/myrack.rb", "puts :LOCAL"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
G
- bundle %(config set local.rack #{lib_path("local-rack")})
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
bundle %(config set disable_local_revision_check true)
bundle :install
expect(out).to match(/Bundle complete!/)
@@ -693,66 +740,66 @@ RSpec.describe "bundle install with git sources" do
# end
it "installs from git even if a newer gem is available elsewhere" do
- build_git "rack", "0.8"
+ build_git "myrack", "0.8"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}"
G
- expect(the_bundle).to include_gems "rack 0.8"
+ expect(the_bundle).to include_gems "myrack 0.8"
end
it "installs dependencies from git even if a newer gem is available elsewhere" do
- system_gems "rack-1.0.0"
+ system_gems "myrack-1.0.0"
- build_lib "rack", "1.0", path: lib_path("nested/bar") do |s|
- s.write "lib/rack.rb", "puts 'WIN OVERRIDE'"
+ build_lib "myrack", "1.0", path: lib_path("nested/bar") do |s|
+ s.write "lib/myrack.rb", "puts 'WIN OVERRIDE'"
end
build_git "foo", path: lib_path("nested") do |s|
- s.add_dependency "rack", "= 1.0"
+ s.add_dependency "myrack", "= 1.0"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("nested")}"
G
- run "require 'rack'"
+ run "require 'myrack'"
expect(out).to eq("WIN OVERRIDE")
end
it "correctly unlocks when changing to a git source" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "0.9.1"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
G
- build_git "rack", path: lib_path("rack")
+ build_git "myrack", path: lib_path("myrack")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "1.0.0", :git => "#{lib_path("rack")}"
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0", :git => "#{lib_path("myrack")}"
G
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "correctly unlocks when changing to a git source without versions" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- build_git "rack", "1.2", path: lib_path("rack")
+ build_git "myrack", "1.2", path: lib_path("myrack")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack")}"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack")}"
G
- expect(the_bundle).to include_gems "rack 1.2"
+ expect(the_bundle).to include_gems "myrack 1.2"
end
end
@@ -762,7 +809,7 @@ RSpec.describe "bundle install with git sources" do
build_lib "hi2u", path: lib_path("hi2u")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
path "#{lib_path("hi2u")}" do
gem "omg"
gem "hi2u"
@@ -779,7 +826,7 @@ RSpec.describe "bundle install with git sources" do
update_git "foo"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}", :ref => "#{@revision}"
G
@@ -797,7 +844,7 @@ RSpec.describe "bundle install with git sources" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
gem "rails", "2.3.2"
G
@@ -827,7 +874,7 @@ RSpec.describe "bundle install with git sources" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "bar", :git => "#{lib_path("foo")}"
gem "rails", "2.3.2"
G
@@ -836,6 +883,32 @@ RSpec.describe "bundle install with git sources" do
expect(the_bundle).to include_gems "rails 2.3.2"
end
+ it "runs the gemspec in the context of its parent directory, when using local overrides" do
+ build_git "foo", path: lib_path("foo"), gemspec: false do |s|
+ s.write lib_path("foo/lib/foo/version.rb"), %(FOO_VERSION = '1.0')
+ s.write "foo.gemspec", <<-G
+ $:.unshift Dir.pwd
+ require 'lib/foo/version'
+ Gem::Specification.new do |s|
+ s.name = 'foo'
+ s.author = 'no one'
+ s.version = FOO_VERSION
+ s.summary = 'Foo'
+ s.files = Dir["lib/**/*.rb"]
+ end
+ G
+ end
+
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => "https://github.com/gems/foo", branch: "main"
+ G
+
+ bundle %(config set local.foo #{lib_path("foo")})
+
+ expect(the_bundle).to include_gems "foo 1.0"
+ end
+
it "installs from git even if a rubygems gem is present" do
build_gem "foo", "1.0", path: lib_path("fake_foo"), to_system: true do |s|
s.write "lib/foo.rb", "raise 'FAIL'"
@@ -844,7 +917,7 @@ RSpec.describe "bundle install with git sources" do
build_git "foo", "1.0"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", "1.0", :git => "#{lib_path("foo-1.0")}"
G
@@ -855,7 +928,7 @@ RSpec.describe "bundle install with git sources" do
build_git "foo", gemspec: false
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", "1.0", :git => "#{lib_path("foo-1.0")}"
gem "rails", "2.3.2"
G
@@ -866,7 +939,7 @@ RSpec.describe "bundle install with git sources" do
it "catches git errors and spits out useful output" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", "1.0", :git => "omgomg"
G
@@ -881,7 +954,7 @@ RSpec.describe "bundle install with git sources" do
build_git "foo", path: lib_path("foo space-1.0")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo space-1.0")}"
G
@@ -892,7 +965,7 @@ RSpec.describe "bundle install with git sources" do
build_git "forced", "1.0"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{lib_path("forced-1.0")}" do
gem 'forced'
end
@@ -906,7 +979,7 @@ RSpec.describe "bundle install with git sources" do
bundle "update", all: true
expect(the_bundle).to include_gems "forced 1.1"
- sys_exec("git reset --hard HEAD^", dir: lib_path("forced-1.0"))
+ git("reset --hard HEAD^", lib_path("forced-1.0"))
bundle "update", all: true
expect(the_bundle).to include_gems "forced 1.0"
@@ -920,16 +993,16 @@ RSpec.describe "bundle install with git sources" do
build_git "has_submodule", "1.0" do |s|
s.add_dependency "submodule"
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")
+ git "submodule add #{lib_path("submodule-1.0")} submodule-1.0", lib_path("has_submodule-1.0")
+ git "commit -m \"submodulator\"", lib_path("has_submodule-1.0")
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{lib_path("has_submodule-1.0")}" do
gem "has_submodule"
end
G
- expect(err).to match(%r{submodule >= 0 could not be found in rubygems repository #{file_uri_for(gem_repo1)}/ or installed locally})
+ expect(err).to match(%r{submodule >= 0 could not be found in rubygems repository https://gem.repo1/ or installed locally})
expect(the_bundle).not_to include_gems "has_submodule 1.0"
end
@@ -942,11 +1015,11 @@ RSpec.describe "bundle install with git sources" do
build_git "has_submodule", "1.0" do |s|
s.add_dependency "submodule"
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")
+ git "submodule add #{lib_path("submodule-1.0")} submodule-1.0", lib_path("has_submodule-1.0")
+ git "commit -m \"submodulator\"", lib_path("has_submodule-1.0")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{lib_path("has_submodule-1.0")}", :submodules => true do
gem "has_submodule"
end
@@ -962,11 +1035,11 @@ RSpec.describe "bundle install with git sources" 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")
+ git "submodule add #{lib_path("submodule-1.0")} submodule-1.0", lib_path("has_submodule-1.0")
+ git "commit -m \"submodulator\"", lib_path("has_submodule-1.0")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{lib_path("has_submodule-1.0")}" do
gem "has_submodule"
end
@@ -981,7 +1054,7 @@ RSpec.describe "bundle install with git sources" do
git = build_git "foo"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}" do
gem "foo"
end
@@ -991,7 +1064,7 @@ RSpec.describe "bundle install with git sources" do
update_git "foo"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}", :ref => "#{git.ref_for("HEAD^")}" do
gem "foo"
end
@@ -1009,11 +1082,11 @@ RSpec.describe "bundle install with git sources" do
build_git "foo"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
- FileUtils.rm_rf(lib_path("foo-1.0"))
+ FileUtils.rm_r(lib_path("foo-1.0"))
bundle "install"
expect(out).not_to match(/updating/i)
@@ -1023,7 +1096,7 @@ RSpec.describe "bundle install with git sources" do
build_git "foo"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
@@ -1038,11 +1111,11 @@ RSpec.describe "bundle install with git sources" do
FileUtils.touch(default_bundle_path("bundler"))
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
- expect(exitstatus).to_not eq(0)
+ expect(last_command).to be_failure
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")}")
@@ -1056,7 +1129,7 @@ RSpec.describe "bundle install with git sources" do
build_git "bar", path: lib_path("nested")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("nested")}"
gem "bar", :git => "#{lib_path("nested")}"
G
@@ -1075,12 +1148,12 @@ RSpec.describe "bundle install with git sources" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "bar", :path => "#{lib_path("bar")}"
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "bar", :git => "#{lib_path("bar")}"
G
@@ -1089,24 +1162,67 @@ RSpec.describe "bundle install with git sources" do
it "doesn't explode when switching Gem to Git source" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack-obama"
- gem "rack", "1.0.0"
+ source "https://gem.repo1"
+ gem "myrack-obama"
+ gem "myrack", "1.0.0"
G
- build_git "rack", "1.0" do |s|
+ build_git "myrack", "1.0" do |s|
s.write "lib/new_file.rb", "puts 'USING GIT'"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack-obama"
- gem "rack", "1.0.0", :git => "#{lib_path("rack-1.0")}"
+ source "https://gem.repo1"
+ gem "myrack-obama"
+ gem "myrack", "1.0.0", :git => "#{lib_path("myrack-1.0")}"
G
run "require 'new_file'"
expect(out).to eq("USING GIT")
end
+
+ it "doesn't explode when removing an explicit exact version from a git gem with dependencies" do
+ build_lib "activesupport", "7.1.4", path: lib_path("rails/activesupport")
+ build_git "rails", "7.1.4", path: lib_path("rails") do |s|
+ s.add_dependency "activesupport", "= 7.1.4"
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "rails", "7.1.4", :git => "#{lib_path("rails")}"
+ G
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "rails", :git => "#{lib_path("rails")}"
+ G
+
+ expect(the_bundle).to include_gem "rails 7.1.4", "activesupport 7.1.4"
+ end
+
+ it "doesn't explode when adding an explicit ref to a git gem with dependencies" do
+ lib_root = lib_path("rails")
+
+ build_lib "activesupport", "7.1.4", path: lib_root.join("activesupport")
+ build_git "rails", "7.1.4", path: lib_root do |s|
+ s.add_dependency "activesupport", "= 7.1.4"
+ end
+
+ old_revision = revision_for(lib_root)
+ update_git "rails", "7.1.4", path: lib_root
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "rails", "7.1.4", :git => "#{lib_root}"
+ G
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "rails", :git => "#{lib_root}", :ref => "#{old_revision}"
+ G
+
+ expect(the_bundle).to include_gem "rails 7.1.4", "activesupport 7.1.4"
+ end
end
describe "bundle install after the remote has been updated" do
@@ -1114,8 +1230,8 @@ RSpec.describe "bundle install with git sources" do
build_git "valim"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "valim", :git => "#{file_uri_for(lib_path("valim-1.0"))}"
+ source "https://gem.repo1"
+ gem "valim", :git => "#{lib_path("valim-1.0")}"
G
old_revision = revision_for(lib_path("valim-1.0"))
@@ -1140,14 +1256,14 @@ RSpec.describe "bundle install with git sources" do
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}"
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo-1.0")}", :ref => "#{revision}"
G
expect(out).to_not match(/Revision.*does not exist/)
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"
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo-1.0")}", :ref => "deadbeef"
G
expect(err).to include("Revision deadbeef does not exist in the repository")
end
@@ -1156,8 +1272,8 @@ RSpec.describe "bundle install with git sources" do
build_git "foo"
install_gemfile <<-G, env: { "LANG" => "en" }, raise_on_error: false
- source "#{file_uri_for(gem_repo1)}"
- gem "foo", :git => "#{file_uri_for(lib_path("foo-1.0"))}", :branch => "deadbeef"
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo-1.0")}", :branch => "deadbeef"
G
expect(err).to include("Revision deadbeef does not exist in the repository")
@@ -1169,11 +1285,11 @@ RSpec.describe "bundle install with git sources" do
build_git "valim", path: lib_path("valim")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "valim", "= 1.0", :git => "#{lib_path("valim")}"
G
- simulate_new_machine
+ pristine_system_gems
bundle "config set --local deployment true"
bundle :install
@@ -1184,7 +1300,7 @@ RSpec.describe "bundle install with git sources" do
it "runs pre-install hooks" do
build_git "foo"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
@@ -1204,7 +1320,7 @@ RSpec.describe "bundle install with git sources" do
it "runs post-install hooks" do
build_git "foo"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
@@ -1224,7 +1340,7 @@ RSpec.describe "bundle install with git sources" do
it "complains if the install hook fails" do
build_git "foo"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
@@ -1258,7 +1374,7 @@ RSpec.describe "bundle install with git sources" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
@@ -1292,12 +1408,12 @@ RSpec.describe "bundle install with git sources" do
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 -m \"commit for iteration #{i}\" ext/foo.c", git_reader.path)
git_commit_sha = git_reader.ref_for("HEAD")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}", :ref => "#{git_commit_sha}"
G
@@ -1322,7 +1438,7 @@ RSpec.describe "bundle install with git sources" do
end
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
@@ -1352,7 +1468,7 @@ In Gemfile:
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
@@ -1365,7 +1481,7 @@ In Gemfile:
expect(installed_time).to match(/\A\d+\.\d+\z/)
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
@@ -1393,8 +1509,8 @@ In Gemfile:
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "0.9.1"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
@@ -1407,8 +1523,8 @@ In Gemfile:
expect(installed_time).to match(/\A\d+\.\d+\z/)
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "1.0.0"
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
@@ -1436,7 +1552,7 @@ In Gemfile:
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
@@ -1452,7 +1568,7 @@ In Gemfile:
expect(installed_time).to match(/\A\d+\.\d+\z/)
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}", :branch => "branch2"
G
@@ -1485,7 +1601,7 @@ In Gemfile:
ENV["GIT_WORK_TREE"] = "bar"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{lib_path("xxxxxx-1.0")}" do
gem 'xxxxxx'
end
@@ -1499,7 +1615,7 @@ In Gemfile:
describe "without git installed" do
it "prints a better error message when installing" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rake", git: "https://github.com/ruby/rake"
G
@@ -1522,7 +1638,7 @@ In Gemfile:
rake!
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
with_path_as("") do
@@ -1536,7 +1652,7 @@ In Gemfile:
build_git "foo"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}" do
gem 'foo'
end
@@ -1549,18 +1665,18 @@ In Gemfile:
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 "installs a packaged git gem successfully" do
+ it "doesn't need git in the new machine if an installed git gem is copied to another machine" do
build_git "foo"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}" do
gem 'foo'
end
G
- bundle "config set cache_all true"
- bundle :cache
- simulate_new_machine
+ bundle "config set --global path vendor/bundle"
+ bundle :install
+ pristine_system_gems
bundle "install", env: { "PATH" => "" }
expect(out).to_not include("You need to install git to be able to use gems from git repositories.")
@@ -1583,7 +1699,7 @@ In Gemfile:
build_git "foo", "1.0", path: lib_path("foo")
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo")}", :branch => "main"
G
@@ -1599,13 +1715,13 @@ In Gemfile:
it "does not display the password" do
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "https://#{credentials}@github.com/company/private-repo" do
gem "foo"
end
G
- expect(last_command.stdboth).to_not include("password1")
+ expect(stdboth).to_not include("password1")
expect(out).to include("Fetching https://user1@github.com/company/private-repo")
end
end
@@ -1615,13 +1731,13 @@ In Gemfile:
it "displays the oauth scheme but not the oauth token" do
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "https://#{credentials}:x-oauth-basic@github.com/company/private-repo" do
gem "foo"
end
G
- expect(last_command.stdboth).to_not include("oauth_token")
+ expect(stdboth).to_not include("oauth_token")
expect(out).to include("Fetching https://x-oauth-basic@github.com/company/private-repo")
end
end
diff --git a/spec/bundler/install/gemfile/groups_spec.rb b/spec/bundler/install/gemfile/groups_spec.rb
index f7907a9cad..4727d5ef9b 100644
--- a/spec/bundler/install/gemfile/groups_spec.rb
+++ b/spec/bundler/install/gemfile/groups_spec.rb
@@ -4,8 +4,8 @@ RSpec.describe "bundle install with groups" do
describe "installing with no options" do
before :each do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
group :emo do
gem "activesupport", "2.3.5"
end
@@ -14,7 +14,7 @@ RSpec.describe "bundle install with groups" do
end
it "installs gems in the default group" do
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "installs gems in a group block into that group" do
@@ -25,7 +25,7 @@ RSpec.describe "bundle install with groups" do
puts ACTIVESUPPORT
R
- expect(err_without_deprecations).to eq("ZOMG LOAD ERROR")
+ expect(err_without_deprecations).to match(/cannot load such file -- activesupport/)
end
it "installs gems with inline :groups into those groups" do
@@ -36,11 +36,11 @@ RSpec.describe "bundle install with groups" do
puts THIN
R
- expect(err_without_deprecations).to eq("ZOMG LOAD ERROR")
+ expect(err_without_deprecations).to match(/cannot load such file -- thin/)
end
it "sets up everything if Bundler.setup is used with no groups" do
- output = run("require 'rack'; puts RACK")
+ output = run("require 'myrack'; puts MYRACK")
expect(output).to eq("1.0.0")
output = run("require 'activesupport'; puts ACTIVESUPPORT")
@@ -57,7 +57,7 @@ RSpec.describe "bundle install with groups" do
puts THIN
RUBY
- expect(err_without_deprecations).to eq("ZOMG LOAD ERROR")
+ expect(err_without_deprecations).to match(/cannot load such file -- thin/)
end
it "sets up old groups when they have previously been removed" do
@@ -74,8 +74,8 @@ RSpec.describe "bundle install with groups" do
describe "with gems assigned to a single group" do
before :each do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
group :emo do
gem "activesupport", "2.3.5"
end
@@ -88,19 +88,19 @@ RSpec.describe "bundle install with groups" do
it "installs gems in the default group" do
bundle "config set --local without emo"
bundle :install
- expect(the_bundle).to include_gems "rack 1.0.0", groups: [:default]
+ expect(the_bundle).to include_gems "myrack 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]
+ expect(the_bundle).to include_gems "myrack 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
+ it "allows running application where groups where configured by a different user" do
bundle "config set without emo"
bundle :install
bundle "exec ruby -e 'puts 42'", env: { "BUNDLE_USER_HOME" => tmp("new_home").to_s }
@@ -113,13 +113,6 @@ RSpec.describe "bundle install with groups" do
expect(the_bundle).not_to include_gems "activesupport 2.3.5", groups: [:default]
end
- 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 "config set --local without emo"
bundle :install
@@ -129,13 +122,13 @@ RSpec.describe "bundle install with groups" do
it "allows Bundler.setup for specific groups" do
bundle "config set --local without emo"
bundle :install
- run("require 'rack'; puts RACK", :default)
+ run("require 'myrack'; puts MYRACK", :default)
expect(out).to eq("1.0.0")
end
it "does not effect the resolve" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "activesupport"
group :emo do
gem "rails", "2.3.2"
@@ -153,26 +146,12 @@ RSpec.describe "bundle install with groups" do
bundle :install
expect(out).not_to include("activesupport")
- expect(the_bundle).to include_gems "rack 1.0.0", groups: [:default]
+ expect(the_bundle).to include_gems "myrack 1.0.0", groups: [:default]
expect(the_bundle).not_to include_gems "activesupport 2.3.5", groups: [:default]
ENV["BUNDLE_WITHOUT"] = nil
end
- it "clears --without when passed an empty list", bundler: "< 3" do
- bundle "install --without emo"
-
- bundle "install --without ''"
- expect(the_bundle).to include_gems "activesupport 2.3.5"
- end
-
- 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"
- end
-
it "does not install gems from the optional group" do
bundle :install
expect(the_bundle).not_to include_gems "thin 1.0"
@@ -184,13 +163,6 @@ RSpec.describe "bundle install with groups" do
expect(the_bundle).to include_gems "thin 1.0"
end
- 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 "installs gems from the optional groups requested with BUNDLE_WITH" do
ENV["BUNDLE_WITH"] = "debugging"
bundle :install
@@ -198,30 +170,6 @@ RSpec.describe "bundle install with groups" do
ENV["BUNDLE_WITH"] = nil
end
- 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 "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 "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 --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
-
it "allows the BUNDLE_WITH setting to override BUNDLE_WITHOUT" do
ENV["BUNDLE_WITH"] = "debugging"
@@ -235,12 +183,6 @@ RSpec.describe "bundle install with groups" do
expect(the_bundle).to include_gem "thin 1.0"
end
- 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 "has no effect when listing a not optional group in with" do
bundle "config set --local with emo"
bundle :install
@@ -257,8 +199,8 @@ RSpec.describe "bundle install with groups" do
describe "with gems assigned to multiple groups" do
before :each do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
group :emo, :lolercoaster do
gem "activesupport", "2.3.5"
end
@@ -268,20 +210,20 @@ RSpec.describe "bundle install with groups" do
it "installs gems in the default group" do
bundle "config set --local without emo lolercoaster"
bundle :install
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "installs the gem if any of its groups are installed" do
bundle "config set --local without emo"
bundle :install
- expect(the_bundle).to include_gems "rack 1.0.0", "activesupport 2.3.5"
+ expect(the_bundle).to include_gems "myrack 1.0.0", "activesupport 2.3.5"
end
describe "with a gem defined multiple times in different groups" do
before :each do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
group :emo do
gem "activesupport", "2.3.5"
@@ -316,8 +258,8 @@ RSpec.describe "bundle install with groups" do
describe "nesting groups" do
before :each do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
group :emo do
group :lolercoaster do
gem "activesupport", "2.3.5"
@@ -329,13 +271,13 @@ RSpec.describe "bundle install with groups" do
it "installs gems in the default group" do
bundle "config set --local without emo lolercoaster"
bundle :install
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "installs the gem if any of its groups are installed" do
bundle "config set --local without emo"
bundle :install
- expect(the_bundle).to include_gems "rack 1.0.0", "activesupport 2.3.5"
+ expect(the_bundle).to include_gems "myrack 1.0.0", "activesupport 2.3.5"
end
end
end
@@ -343,8 +285,8 @@ RSpec.describe "bundle install with groups" do
describe "when loading only the default group" do
it "should not load all groups" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
gem "activesupport", :groups => :development
G
@@ -352,7 +294,7 @@ RSpec.describe "bundle install with groups" do
require "bundler"
Bundler.setup :default
Bundler.require :default
- puts RACK
+ puts MYRACK
begin
require "activesupport"
rescue LoadError
@@ -365,39 +307,39 @@ RSpec.describe "bundle install with groups" do
end
end
- describe "when locked and installed with `without` option" do
+ describe "when locked and installed with `without` setting" do
before(:each) do
build_repo2
- system_gems "rack-0.9.1"
+ system_gems "myrack-0.9.1"
- bundle "config set --local without rack"
+ bundle "config set --local without myrack"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack"
+ source "https://gem.repo2"
+ gem "myrack"
- group :rack do
- gem "rack_middleware"
+ group :myrack do
+ gem "myrack_middleware"
end
G
end
- it "uses the correct versions even if --without was used on the original" do
- expect(the_bundle).to include_gems "rack 0.9.1"
- expect(the_bundle).not_to include_gems "rack_middleware 1.0"
+ it "uses versions from excluded gems in a machine without the without configuration" do
+ expect(the_bundle).to include_gems "myrack 0.9.1"
+ expect(the_bundle).not_to include_gems "myrack_middleware 1.0"
simulate_new_machine
bundle :install
- expect(the_bundle).to include_gems "rack 0.9.1"
- expect(the_bundle).to include_gems "rack_middleware 1.0"
+ expect(the_bundle).to include_gems "myrack 0.9.1"
+ expect(the_bundle).to include_gems "myrack_middleware 1.0"
end
it "does not hit the remote a second time" do
- FileUtils.rm_rf gem_repo2
- bundle "config set --local without rack"
+ FileUtils.rm_r gem_repo2
+ bundle "config set --local without myrack"
bundle :install, verbose: true
- expect(last_command.stdboth).not_to match(/fetching/i)
+ expect(stdboth).not_to match(/fetching/i)
end
end
end
diff --git a/spec/bundler/install/gemfile/install_if_spec.rb b/spec/bundler/install/gemfile/install_if_spec.rb
index c7640d07e1..05a6d15129 100644
--- a/spec/bundler/install/gemfile/install_if_spec.rb
+++ b/spec/bundler/install/gemfile/install_if_spec.rb
@@ -3,7 +3,7 @@
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)}"
+ source "https://gem.repo1"
install_if(lambda { true }) do
gem "activesupport", "2.3.5"
end
@@ -11,29 +11,29 @@ RSpec.describe "bundle install with install_if conditionals" do
install_if(lambda { false }) do
gem "foo"
end
- gem "rack"
+ gem "myrack"
G
- expect(the_bundle).to include_gems("rack 1.0", "activesupport 2.3.5")
+ expect(the_bundle).to include_gems("myrack 1.0", "activesupport 2.3.5")
expect(the_bundle).not_to include_gems("thin")
expect(the_bundle).not_to include_gems("foo")
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo1, "activesupport", "2.3.5"
- c.no_checksum "foo", "1.0"
- c.checksum gem_repo1, "rack", "1.0.0"
- c.no_checksum "thin", "1.0"
+ c.checksum gem_repo1, "foo", "1.0"
+ c.checksum gem_repo1, "myrack", "1.0.0"
+ c.checksum gem_repo1, "thin", "1.0"
end
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
activesupport (2.3.5)
foo (1.0)
- rack (1.0.0)
+ myrack (1.0.0)
thin (1.0)
- rack
+ myrack
PLATFORMS
#{lockfile_platforms}
@@ -41,11 +41,11 @@ RSpec.describe "bundle install with install_if conditionals" do
DEPENDENCIES
activesupport (= 2.3.5)
foo
- rack
+ myrack
thin
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
diff --git a/spec/bundler/install/gemfile/lockfile_spec.rb b/spec/bundler/install/gemfile/lockfile_spec.rb
index 4601d3e2a8..ee747c05de 100644
--- a/spec/bundler/install/gemfile/lockfile_spec.rb
+++ b/spec/bundler/install/gemfile/lockfile_spec.rb
@@ -2,17 +2,13 @@
RSpec.describe "bundle install with a lockfile present" do
let(:gf) { <<-G }
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
G
- subject do
- install_gemfile(gf)
- end
-
it "touches the lockfile on install even when nothing has changed" do
- subject
+ install_gemfile(gf)
expect { bundle :install }.to change { bundled_app_lock.mtime }
end
@@ -22,31 +18,24 @@ RSpec.describe "bundle install with a lockfile present" do
context "with plugins disabled" do
before do
bundle "config set plugins false"
- subject
end
- it "does not evaluate the gemfile twice" do
+ it "does not evaluate the gemfile twice when the gem is already installed" do
+ install_gemfile(gf)
bundle :install
- with_env_vars("BUNDLER_SPEC_NO_APPEND" => "1") { expect(the_bundle).to include_gem "rack 1.0.0" }
+ with_env_vars("BUNDLER_SPEC_NO_APPEND" => "1") { expect(the_bundle).to include_gem "myrack 1.0.0" }
- # The first eval is from the initial install, we're testing that the
- # second install doesn't double-eval
expect(bundled_app("evals").read.lines.to_a.size).to eq(2)
end
- context "when the gem is not installed" do
- before { FileUtils.rm_rf bundled_app(".bundle") }
-
- it "does not evaluate the gemfile twice" do
- bundle :install
+ it "does not evaluate the gemfile twice when the gem is not installed" do
+ gemfile(gf)
+ bundle :install
- with_env_vars("BUNDLER_SPEC_NO_APPEND" => "1") { expect(the_bundle).to include_gem "rack 1.0.0" }
+ with_env_vars("BUNDLER_SPEC_NO_APPEND" => "1") { expect(the_bundle).to include_gem "myrack 1.0.0" }
- # The first eval is from the initial install, we're testing that the
- # second install doesn't double-eval
- expect(bundled_app("evals").read.lines.to_a.size).to eq(2)
- end
+ expect(bundled_app("evals").read.lines.to_a.size).to eq(1)
end
end
end
diff --git a/spec/bundler/install/gemfile/path_spec.rb b/spec/bundler/install/gemfile/path_spec.rb
index a57b7ee560..13a8c663e0 100644
--- a/spec/bundler/install/gemfile/path_spec.rb
+++ b/spec/bundler/install/gemfile/path_spec.rb
@@ -1,22 +1,10 @@
# frozen_string_literal: true
RSpec.describe "bundle install with explicit source paths" do
- it "fetches gems with a global path source", bundler: "< 3" do
- build_lib "foo"
-
- install_gemfile <<-G
- path "#{lib_path("foo-1.0")}"
- gem 'foo'
- G
-
- expect(the_bundle).to include_gems("foo 1.0")
- end
-
it "fetches gems" do
build_lib "foo"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
path "#{lib_path("foo-1.0")}" do
gem 'foo'
end
@@ -29,7 +17,6 @@ RSpec.describe "bundle install with explicit source paths" do
build_lib "foo"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
gem 'foo', :path => "#{lib_path("foo-1.0")}"
G
@@ -42,7 +29,6 @@ RSpec.describe "bundle install with explicit source paths" do
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
@@ -55,7 +41,6 @@ RSpec.describe "bundle install with explicit source paths" do
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
@@ -70,7 +55,6 @@ RSpec.describe "bundle install with explicit source paths" do
relative_path = lib_path("foo-1.0").relative_path_from(Pathname.new("/home/#{username}").expand_path)
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}`.")
@@ -81,7 +65,6 @@ RSpec.describe "bundle install with explicit source paths" do
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
@@ -93,12 +76,12 @@ RSpec.describe "bundle install with explicit source paths" do
build_lib "aaa", path: lib_path("demo/aaa")
gemfile lib_path("demo/Gemfile"), <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gemspec
gem "aaa", :path => "./aaa"
G
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "aaa", "1.0"
c.no_checksum "demo", "1.0"
end
@@ -115,7 +98,7 @@ RSpec.describe "bundle install with explicit source paths" do
aaa (1.0)
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
@@ -126,7 +109,7 @@ RSpec.describe "bundle install with explicit source paths" do
demo!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle :install, dir: lib_path("demo")
@@ -139,7 +122,6 @@ RSpec.describe "bundle install with explicit source 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", __dir__)
G
@@ -148,22 +130,21 @@ RSpec.describe "bundle install with explicit source paths" do
end
it "installs dependencies from the path even if a newer gem is available elsewhere" do
- system_gems "rack-1.0.0"
+ system_gems "myrack-1.0.0"
- build_lib "rack", "1.0", path: lib_path("nested/bar") do |s|
- s.write "lib/rack.rb", "puts 'WIN OVERRIDE'"
+ build_lib "myrack", "1.0", path: lib_path("nested/bar") do |s|
+ s.write "lib/myrack.rb", "puts 'WIN OVERRIDE'"
end
build_lib "foo", path: lib_path("nested") do |s|
- s.add_dependency "rack", "= 1.0"
+ s.add_dependency "myrack", "= 1.0"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => "#{lib_path("nested")}"
G
- run "require 'rack'"
+ run "require 'myrack'"
expect(out).to eq("WIN OVERRIDE")
end
@@ -179,7 +160,6 @@ RSpec.describe "bundle install with explicit source paths" do
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
@@ -190,7 +170,7 @@ RSpec.describe "bundle install with explicit source paths" do
build_lib "foo", "0.0.0.dev", path: lib_path("foo")
gemfile <<~G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :path => "#{lib_path("foo")}"
G
@@ -201,7 +181,7 @@ RSpec.describe "bundle install with explicit source paths" do
foo (0.0.0.dev)
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
@@ -223,7 +203,7 @@ RSpec.describe "bundle install with explicit source paths" do
build_lib "foo", "0.0.0.SNAPSHOT", path: lib_path("foo")
gemfile <<~G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :path => "#{lib_path("foo")}"
G
@@ -234,7 +214,7 @@ RSpec.describe "bundle install with explicit source paths" do
foo (0.0.0.SNAPSHOT)
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
@@ -256,7 +236,6 @@ RSpec.describe "bundle install with explicit source paths" 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
@@ -280,7 +259,6 @@ RSpec.describe "bundle install with explicit source paths" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
gem "premailer", :path => "#{lib_path("premailer")}"
G
@@ -302,11 +280,9 @@ RSpec.describe "bundle install with explicit source paths" do
end
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("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'/)
expect(err).to match(/You have one or more invalid gemspecs that need to be fixed/)
@@ -314,17 +290,17 @@ RSpec.describe "bundle install with explicit source paths" do
it "supports gemspec syntax" do
build_lib "foo", "1.0", path: lib_path("foo") do |s|
- s.add_dependency "rack", "1.0"
+ s.add_dependency "myrack", "1.0"
end
gemfile lib_path("foo/Gemfile"), <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gemspec
G
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")
+ expect(the_bundle).to include_gems "myrack 1.0", dir: lib_path("foo")
end
it "does not unlock dependencies of path sources" do
@@ -340,13 +316,13 @@ RSpec.describe "bundle install with explicit source paths" do
gemfile_path = lib_path("foo/Gemfile")
gemfile gemfile_path, <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gemspec
G
lockfile_path = lib_path("foo/Gemfile.lock")
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "foo", "0.1.0"
c.checksum gem_repo4, "graphql", "2.0.15"
end
@@ -359,7 +335,7 @@ RSpec.describe "bundle install with explicit source paths" do
graphql (~> 2.0)
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
graphql (2.0.15)
@@ -370,7 +346,7 @@ RSpec.describe "bundle install with explicit source paths" do
foo!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
lockfile lockfile_path, original_lockfile
@@ -385,53 +361,53 @@ RSpec.describe "bundle install with explicit source paths" do
it "supports gemspec syntax with an alternative path" do
build_lib "foo", "1.0", path: lib_path("foo") do |s|
- s.add_dependency "rack", "1.0"
+ s.add_dependency "myrack", "1.0"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gemspec :path => "#{lib_path("foo")}"
G
expect(the_bundle).to include_gems "foo 1.0"
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
it "doesn't automatically unlock dependencies when using the gemspec syntax" do
build_lib "foo", "1.0", path: lib_path("foo") do |s|
- s.add_dependency "rack", ">= 1.0"
+ s.add_dependency "myrack", ">= 1.0"
end
install_gemfile lib_path("foo/Gemfile"), <<-G, dir: lib_path("foo")
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gemspec
G
- build_gem "rack", "1.0.1", to_system: true
+ build_gem "myrack", "1.0.1", to_system: true
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")
+ expect(the_bundle).to include_gems "myrack 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
build_lib "foo", "1.0", path: lib_path("foo") do |s|
- s.add_dependency "rack", ">= 1.0"
+ s.add_dependency "myrack", ">= 1.0"
s.add_development_dependency "activesupport"
end
install_gemfile lib_path("foo/Gemfile"), <<-G, dir: lib_path("foo")
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gemspec
G
- build_gem "rack", "1.0.1", to_system: true
+ build_gem "myrack", "1.0.1", to_system: true
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")
+ expect(the_bundle).to include_gems "myrack 1.0", dir: lib_path("foo")
end
it "raises if there are multiple gemspecs" do
@@ -440,7 +416,6 @@ RSpec.describe "bundle install with explicit source paths" do
end
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo1)}"
gemspec :path => "#{lib_path("foo")}"
G
@@ -454,7 +429,6 @@ RSpec.describe "bundle install with explicit source paths" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
gemspec :path => "#{lib_path("foo")}", :name => "foo"
G
@@ -467,7 +441,6 @@ RSpec.describe "bundle install with explicit source paths" do
end
install_gemfile <<-G, verbose: true
- source "#{file_uri_for(gem_repo1)}"
path "#{lib_path("foo-1.0")}" do
gem 'foo'
end
@@ -481,11 +454,10 @@ RSpec.describe "bundle install with explicit source paths" do
it "handles directories in bin/" do
build_lib "foo"
- lib_path("foo-1.0").join("foo.gemspec").rmtree
+ FileUtils.rm_rf lib_path("foo-1.0").join("foo.gemspec")
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
@@ -495,7 +467,6 @@ RSpec.describe "bundle install with explicit source paths" do
build_lib "foo"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
gem 'foo', :path => "#{lib_path("foo-1.0")}"
G
@@ -508,7 +479,6 @@ RSpec.describe "bundle install with explicit source paths" do
build_lib "hi2u"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
path "#{lib_path}" do
gem "omg"
gem "hi2u"
@@ -527,7 +497,6 @@ RSpec.describe "bundle install with explicit source paths" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => "#{lib_path("foo")}"
gem "omg", :path => "#{lib_path("omg")}"
G
@@ -539,7 +508,6 @@ RSpec.describe "bundle install with explicit source paths" do
build_lib "foo", gemspec: false
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
gem "foo", "1.0", :path => "#{lib_path("foo-1.0")}"
G
@@ -553,15 +521,11 @@ RSpec.describe "bundle install with explicit source paths" do
PATH
remote: vendor/bar
specs:
-
- GEM
- remote: http://rubygems.org/
L
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
end
@@ -569,18 +533,18 @@ RSpec.describe "bundle install with explicit source paths" do
context "existing lockfile" do
it "rubygems gems don't re-resolve without changes" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack-obama', '1.0'
+ source "https://gem.repo1"
+ gem 'myrack-obama', '1.0'
gem 'net-ssh', '1.0'
G
bundle :check, env: { "DEBUG" => "1" }
expect(out).to match(/using resolution from the lockfile/)
- expect(the_bundle).to include_gems "rack-obama 1.0", "net-ssh 1.0"
+ expect(the_bundle).to include_gems "myrack-obama 1.0", "net-ssh 1.0"
end
it "source path gems w/deps don't re-resolve without changes" do
- build_lib "rack-obama", "1.0", path: lib_path("omg") do |s|
+ build_lib "myrack-obama", "1.0", path: lib_path("omg") do |s|
s.add_dependency "yard"
end
@@ -589,14 +553,14 @@ RSpec.describe "bundle install with explicit source paths" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack-obama', :path => "#{lib_path("omg")}"
+ source "https://gem.repo1"
+ gem 'myrack-obama', :path => "#{lib_path("omg")}"
gem 'net-ssh', :path => "#{lib_path("omg")}"
G
bundle :check, env: { "DEBUG" => "1" }
expect(out).to match(/using resolution from the lockfile/)
- expect(the_bundle).to include_gems "rack-obama 1.0", "net-ssh 1.0"
+ expect(the_bundle).to include_gems "myrack-obama 1.0", "net-ssh 1.0"
end
end
@@ -606,7 +570,6 @@ RSpec.describe "bundle install with explicit source paths" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
gem "foo", :path => "#{lib_path("foo-1.0")}"
G
@@ -622,7 +585,6 @@ RSpec.describe "bundle install with explicit source paths" do
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
@@ -651,33 +613,33 @@ RSpec.describe "bundle install with explicit source paths" do
build_lib "foo", "1.0", path: lib_path("foo")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :path => "#{lib_path("foo")}"
G
end
it "gets dependencies that are updated in the path" do
build_lib "foo", "1.0", path: lib_path("foo") do |s|
- s.add_dependency "rack"
+ s.add_dependency "myrack"
end
bundle "install"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "keeps using the same version if it's compatible" do
build_lib "foo", "1.0", path: lib_path("foo") do |s|
- s.add_dependency "rack", "0.9.1"
+ s.add_dependency "myrack", "0.9.1"
end
bundle "install"
- expect(the_bundle).to include_gems "rack 0.9.1"
+ expect(the_bundle).to include_gems "myrack 0.9.1"
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "foo", "1.0"
- c.checksum gem_repo1, "rack", "0.9.1"
+ c.checksum gem_repo1, "myrack", "0.9.1"
end
expect(lockfile).to eq <<~G
@@ -685,12 +647,12 @@ RSpec.describe "bundle install with explicit source paths" do
remote: #{lib_path("foo")}
specs:
foo (1.0)
- rack (= 0.9.1)
+ myrack (= 0.9.1)
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
- rack (0.9.1)
+ myrack (0.9.1)
PLATFORMS
#{lockfile_platforms}
@@ -699,11 +661,11 @@ RSpec.describe "bundle install with explicit source paths" do
foo!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
build_lib "foo", "1.0", path: lib_path("foo") do |s|
- s.add_dependency "rack"
+ s.add_dependency "myrack"
end
bundle "install"
@@ -713,12 +675,12 @@ RSpec.describe "bundle install with explicit source paths" do
remote: #{lib_path("foo")}
specs:
foo (1.0)
- rack
+ myrack
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
- rack (0.9.1)
+ myrack (0.9.1)
PLATFORMS
#{lockfile_platforms}
@@ -727,24 +689,24 @@ RSpec.describe "bundle install with explicit source paths" do
foo!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
- expect(the_bundle).to include_gems "rack 0.9.1"
+ expect(the_bundle).to include_gems "myrack 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"
+ s.add_dependency "myrack", "0.9.1"
end
bundle "install"
- expect(the_bundle).to include_gems "rack 0.9.1"
+ expect(the_bundle).to include_gems "myrack 0.9.1"
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "foo", "1.0"
- c.checksum gem_repo1, "rack", "0.9.1"
+ c.checksum gem_repo1, "myrack", "0.9.1"
end
expect(lockfile).to eq <<~G
@@ -752,12 +714,12 @@ RSpec.describe "bundle install with explicit source paths" do
remote: #{lib_path("foo")}
specs:
foo (1.0)
- rack (= 0.9.1)
+ myrack (= 0.9.1)
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
- rack (0.9.1)
+ myrack (0.9.1)
PLATFORMS
#{lockfile_platforms}
@@ -766,11 +728,11 @@ RSpec.describe "bundle install with explicit source paths" do
foo!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
build_lib "foo", "1.0", path: lib_path("foo") do |s|
- s.add_dependency "rack"
+ s.add_dependency "myrack"
s.add_dependency "rake", rake_version
end
@@ -783,13 +745,13 @@ RSpec.describe "bundle install with explicit source paths" do
remote: #{lib_path("foo")}
specs:
foo (1.0)
- rack
+ myrack
rake (= #{rake_version})
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
- rack (0.9.1)
+ myrack (0.9.1)
rake (#{rake_version})
PLATFORMS
@@ -799,18 +761,18 @@ RSpec.describe "bundle install with explicit source paths" do
foo!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
- expect(the_bundle).to include_gems "rack 0.9.1"
+ expect(the_bundle).to include_gems "myrack 0.9.1"
end
it "does not remove existing ruby platform" do
build_lib "foo", "1.0", path: lib_path("foo") do |s|
- s.add_dependency "rack", "0.9.1"
+ s.add_dependency "myrack", "0.9.1"
end
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "foo", "1.0"
end
@@ -827,24 +789,24 @@ RSpec.describe "bundle install with explicit source paths" do
foo!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "lock"
- checksums.no_checksum "rack", "0.9.1"
+ checksums.checksum gem_repo1, "myrack", "0.9.1"
expect(lockfile).to eq <<~G
PATH
remote: #{lib_path("foo")}
specs:
foo (1.0)
- rack (= 0.9.1)
+ myrack (= 0.9.1)
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
- rack (0.9.1)
+ myrack (0.9.1)
PLATFORMS
#{lockfile_platforms("ruby")}
@@ -853,11 +815,60 @@ RSpec.describe "bundle install with explicit source paths" do
foo!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
end
+ context "when platform specific version locked, and having less dependencies that the generic version that's actually installed" do
+ before do
+ build_repo4 do
+ build_gem "racc", "1.8.1"
+ build_gem "mini_portile2", "2.8.2"
+ end
+
+ build_lib "nokogiri", "1.18.9", path: lib_path("nokogiri") do |s|
+ s.add_dependency "mini_portile2", "~> 2.8.2"
+ s.add_dependency "racc", "~> 1.4"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "nokogiri", path: "#{lib_path("nokogiri")}"
+ G
+
+ lockfile <<~L
+ PATH
+ remote: #{lib_path("nokogiri")}
+ specs:
+ nokogiri (1.18.9)
+ mini_portile2 (~> 2.8.2)
+ racc (~> 1.4)
+ nokogiri (1.18.9-arm64-darwin)
+ racc (~> 1.4)
+
+ GEM
+ remote: https://rubygems.org/
+ specs:
+ racc (1.8.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ nokogiri!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "works" do
+ bundle "install"
+ end
+ end
+
describe "switching sources" do
it "doesn't switch pinned git sources to rubygems when pinning the parent gem to a path source" do
build_gem "foo", "1.0", to_system: true do |s|
@@ -869,12 +880,10 @@ RSpec.describe "bundle install with explicit source paths" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
gem "bar", :git => "#{lib_path("bar")}"
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
gem "bar", :path => "#{lib_path("bar")}"
G
@@ -888,7 +897,7 @@ RSpec.describe "bundle install with explicit source paths" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "bar"
path "#{lib_path("foo")}" do
gem "foo"
@@ -898,7 +907,7 @@ RSpec.describe "bundle install with explicit source paths" do
build_lib "bar", "1.0", path: lib_path("foo/bar")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
path "#{lib_path("foo")}" do
gem "foo"
gem "bar"
@@ -915,13 +924,13 @@ RSpec.describe "bundle install with explicit source paths" do
gemfile lib_path("private_lib/Gemfile"), <<-G
source "http://localgemserver.test"
gemspec
- gem 'rack'
+ gem 'myrack'
G
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).to match(%r{^HTTP GET http://localgemserver\.test/api/v1/dependencies\?gems=myrack$})
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")
+ expect(the_bundle).to include_gems "myrack 1.0", dir: lib_path("private_lib")
end
end
@@ -929,7 +938,6 @@ RSpec.describe "bundle install with explicit source paths" do
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
@@ -949,7 +957,6 @@ RSpec.describe "bundle install with explicit source paths" do
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
@@ -969,7 +976,6 @@ RSpec.describe "bundle install with explicit source paths" do
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
@@ -1000,7 +1006,6 @@ RSpec.describe "bundle install with explicit source paths" do
end
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/spec/bundler/install/gemfile/platform_spec.rb b/spec/bundler/install/gemfile/platform_spec.rb
index d90dacdc02..6c5e5452c9 100644
--- a/spec/bundler/install/gemfile/platform_spec.rb
+++ b/spec/bundler/install/gemfile/platform_spec.rb
@@ -4,30 +4,30 @@ RSpec.describe "bundle install across platforms" do
it "maintains the same lockfile if all gems are compatible across platforms" do
lockfile <<-G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
- rack (0.9.1)
+ myrack (0.9.1)
PLATFORMS
#{not_local}
DEPENDENCIES
- rack
+ myrack
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
G
- expect(the_bundle).to include_gems "rack 0.9.1"
+ expect(the_bundle).to include_gems "myrack 0.9.1"
end
it "pulls in the correct platform specific gem" do
lockfile <<-G
GEM
- remote: #{file_uri_for(gem_repo1)}
+ remote: https://gem.repo1
specs:
platform_specific (1.0)
platform_specific (1.0-java)
@@ -40,20 +40,21 @@ RSpec.describe "bundle install across platforms" do
platform_specific
G
- simulate_platform "java"
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ simulate_platform "java" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
- gem "platform_specific"
- G
+ gem "platform_specific"
+ G
- expect(the_bundle).to include_gems "platform_specific 1.0 JAVA"
+ expect(the_bundle).to include_gems "platform_specific 1.0 java"
+ end
end
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_only do
lockfile <<-G
GEM
- remote: #{file_uri_for(gem_repo1)}
+ remote: https://gem.repo1
specs:
platform_specific (1.0)
@@ -67,12 +68,13 @@ RSpec.describe "bundle install across platforms" do
bundle "config set --local frozen true"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "platform_specific"
G
- expect(the_bundle).to include_gems "platform_specific 1.0 RUBY"
+ expect(the_bundle).to include_gems "platform_specific 1.0 ruby"
+ expect(err).to be_empty
end
context "on universal Rubies" do
@@ -80,15 +82,12 @@ RSpec.describe "bundle install across platforms" do
build_repo4 do
build_gem "darwin_single_arch" do |s|
s.platform = "ruby"
- s.write "lib/darwin_single_arch.rb", "DARWIN_SINGLE_ARCH = '1.0 RUBY'"
end
build_gem "darwin_single_arch" do |s|
s.platform = "arm64-darwin"
- s.write "lib/darwin_single_arch.rb", "DARWIN_SINGLE_ARCH = '1.0 arm64-darwin'"
end
build_gem "darwin_single_arch" do |s|
s.platform = "x86_64-darwin"
- s.write "lib/darwin_single_arch.rb", "DARWIN_SINGLE_ARCH = '1.0 x86_64-darwin'"
end
end
end
@@ -96,7 +95,7 @@ RSpec.describe "bundle install across platforms" do
it "pulls in the correct architecture gem" do
lockfile <<-G
GEM
- remote: #{file_uri_for(gem_repo4)}
+ remote: https://gem.repo4
specs:
darwin_single_arch (1.0)
darwin_single_arch (1.0-arm64-darwin)
@@ -109,22 +108,23 @@ RSpec.describe "bundle install across platforms" do
darwin_single_arch
G
- simulate_platform "universal-darwin-21"
- simulate_ruby_platform "universal.x86_64-darwin21" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ simulate_platform "universal-darwin-21" do
+ simulate_ruby_platform "universal.x86_64-darwin21" do
+ install_gemfile <<-G
+ source "https://gem.repo4"
- gem "darwin_single_arch"
- G
+ gem "darwin_single_arch"
+ G
- expect(the_bundle).to include_gems "darwin_single_arch 1.0 x86_64-darwin"
+ expect(the_bundle).to include_gems "darwin_single_arch 1.0 x86_64-darwin"
+ end
end
end
it "pulls in the correct architecture gem on arm64e macOS Ruby" do
lockfile <<-G
GEM
- remote: #{file_uri_for(gem_repo4)}
+ remote: https://gem.repo4
specs:
darwin_single_arch (1.0)
darwin_single_arch (1.0-arm64-darwin)
@@ -137,41 +137,42 @@ RSpec.describe "bundle install across platforms" do
darwin_single_arch
G
- simulate_platform "universal-darwin-21"
- simulate_ruby_platform "universal.arm64e-darwin21" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ simulate_platform "universal-darwin-21" do
+ simulate_ruby_platform "universal.arm64e-darwin21" do
+ install_gemfile <<-G
+ source "https://gem.repo4"
- gem "darwin_single_arch"
- G
+ gem "darwin_single_arch"
+ G
- expect(the_bundle).to include_gems "darwin_single_arch 1.0 arm64-darwin"
+ expect(the_bundle).to include_gems "darwin_single_arch 1.0 arm64-darwin"
+ end
end
end
end
it "works with gems that have different dependencies" do
- simulate_platform "java"
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ simulate_platform "java" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
- gem "nokogiri"
- G
+ gem "nokogiri"
+ G
- expect(the_bundle).to include_gems "nokogiri 1.4.2 JAVA", "weakling 0.0.3"
+ 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"
+ pristine_system_gems
+ 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"
+ 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"
+ simulate_new_machine
+ bundle "install"
- expect(the_bundle).to include_gems "nokogiri 1.4.2 JAVA", "weakling 0.0.3"
+ expect(the_bundle).to include_gems "nokogiri 1.4.2 java", "weakling 0.0.3"
+ end
end
it "does not keep unneeded platforms for gems that are used" do
@@ -179,187 +180,189 @@ RSpec.describe "bundle install across platforms" do
build_gem "empyrean", "0.1.0"
build_gem "coderay", "1.1.2"
build_gem "method_source", "0.9.0"
- build_gem("spoon", "0.0.6") {|s| s.add_runtime_dependency "ffi" }
+ build_gem("spoon", "0.0.6") {|s| s.add_dependency "ffi" }
build_gem "pry", "0.11.3" do |s|
s.platform = "java"
- s.add_runtime_dependency "coderay", "~> 1.1.0"
- s.add_runtime_dependency "method_source", "~> 0.9.0"
- s.add_runtime_dependency "spoon", "~> 0.0"
+ s.add_dependency "coderay", "~> 1.1.0"
+ s.add_dependency "method_source", "~> 0.9.0"
+ s.add_dependency "spoon", "~> 0.0"
end
build_gem "pry", "0.11.3" do |s|
- s.add_runtime_dependency "coderay", "~> 1.1.0"
- s.add_runtime_dependency "method_source", "~> 0.9.0"
+ s.add_dependency "coderay", "~> 1.1.0"
+ s.add_dependency "method_source", "~> 0.9.0"
end
build_gem("ffi", "1.9.23") {|s| s.platform = "java" }
build_gem("ffi", "1.9.23")
end
- simulate_platform java
-
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
-
- gem "empyrean", "0.1.0"
- gem "pry"
- G
-
- checksums = checksums_section_when_existing do |c|
- c.checksum gem_repo4, "coderay", "1.1.2"
- c.checksum gem_repo4, "empyrean", "0.1.0"
- c.checksum gem_repo4, "ffi", "1.9.23", "java"
- c.checksum gem_repo4, "method_source", "0.9.0"
- c.checksum gem_repo4, "pry", "0.11.3", "java"
- c.checksum gem_repo4, "spoon", "0.0.6"
- end
-
- expect(lockfile).to eq <<~L
- GEM
- remote: #{file_uri_for(gem_repo4)}/
- specs:
- coderay (1.1.2)
- empyrean (0.1.0)
- ffi (1.9.23-java)
- method_source (0.9.0)
- pry (0.11.3-java)
- coderay (~> 1.1.0)
- method_source (~> 0.9.0)
- spoon (~> 0.0)
- spoon (0.0.6)
- ffi
-
- PLATFORMS
- java
+ simulate_platform "java" do
+ install_gemfile <<-G
+ source "https://gem.repo4"
- DEPENDENCIES
- empyrean (= 0.1.0)
- pry
- #{checksums}
- BUNDLED WITH
- #{Bundler::VERSION}
- L
+ gem "empyrean", "0.1.0"
+ gem "pry"
+ G
- bundle "lock --add-platform ruby"
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "coderay", "1.1.2"
+ c.checksum gem_repo4, "empyrean", "0.1.0"
+ c.checksum gem_repo4, "ffi", "1.9.23", "java"
+ c.checksum gem_repo4, "method_source", "0.9.0"
+ c.checksum gem_repo4, "pry", "0.11.3", "java"
+ c.checksum gem_repo4, "spoon", "0.0.6"
+ end
- good_lockfile = <<~L
- GEM
- remote: #{file_uri_for(gem_repo4)}/
- specs:
- coderay (1.1.2)
- empyrean (0.1.0)
- ffi (1.9.23-java)
- method_source (0.9.0)
- pry (0.11.3)
- coderay (~> 1.1.0)
- method_source (~> 0.9.0)
- pry (0.11.3-java)
- coderay (~> 1.1.0)
- method_source (~> 0.9.0)
- spoon (~> 0.0)
- spoon (0.0.6)
- ffi
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ coderay (1.1.2)
+ empyrean (0.1.0)
+ ffi (1.9.23-java)
+ method_source (0.9.0)
+ pry (0.11.3-java)
+ coderay (~> 1.1.0)
+ method_source (~> 0.9.0)
+ spoon (~> 0.0)
+ spoon (0.0.6)
+ ffi
- PLATFORMS
- java
- ruby
+ PLATFORMS
+ java
- DEPENDENCIES
- empyrean (= 0.1.0)
- pry
- #{checksums}
- BUNDLED WITH
- #{Bundler::VERSION}
- L
+ DEPENDENCIES
+ empyrean (= 0.1.0)
+ pry
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
- expect(lockfile).to eq good_lockfile
+ bundle "lock --add-platform ruby"
- bad_lockfile = <<~L
- GEM
- remote: #{file_uri_for(gem_repo4)}/
- specs:
- coderay (1.1.2)
- empyrean (0.1.0)
- ffi (1.9.23)
- ffi (1.9.23-java)
- method_source (0.9.0)
- pry (0.11.3)
- coderay (~> 1.1.0)
- method_source (~> 0.9.0)
- pry (0.11.3-java)
- coderay (~> 1.1.0)
- method_source (~> 0.9.0)
- spoon (~> 0.0)
- spoon (0.0.6)
- ffi
+ checksums.checksum gem_repo4, "pry", "0.11.3"
- PLATFORMS
- java
- ruby
+ good_lockfile = <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ coderay (1.1.2)
+ empyrean (0.1.0)
+ ffi (1.9.23-java)
+ method_source (0.9.0)
+ pry (0.11.3)
+ coderay (~> 1.1.0)
+ method_source (~> 0.9.0)
+ pry (0.11.3-java)
+ coderay (~> 1.1.0)
+ method_source (~> 0.9.0)
+ spoon (~> 0.0)
+ spoon (0.0.6)
+ ffi
- DEPENDENCIES
- empyrean (= 0.1.0)
- pry
- #{checksums}
- BUNDLED WITH
- 1.16.1
- L
+ PLATFORMS
+ java
+ ruby
- aggregate_failures do
- lockfile bad_lockfile
- bundle :install, env: { "BUNDLER_VERSION" => Bundler::VERSION }
- expect(lockfile).to eq good_lockfile
+ DEPENDENCIES
+ empyrean (= 0.1.0)
+ pry
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
- lockfile bad_lockfile
- bundle :update, all: true, env: { "BUNDLER_VERSION" => Bundler::VERSION }
expect(lockfile).to eq good_lockfile
- lockfile bad_lockfile
- bundle "update ffi", env: { "BUNDLER_VERSION" => Bundler::VERSION }
- expect(lockfile).to eq good_lockfile
+ bad_lockfile = <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ coderay (1.1.2)
+ empyrean (0.1.0)
+ ffi (1.9.23)
+ ffi (1.9.23-java)
+ method_source (0.9.0)
+ pry (0.11.3)
+ coderay (~> 1.1.0)
+ method_source (~> 0.9.0)
+ pry (0.11.3-java)
+ coderay (~> 1.1.0)
+ method_source (~> 0.9.0)
+ spoon (~> 0.0)
+ spoon (0.0.6)
+ ffi
- lockfile bad_lockfile
- bundle "update empyrean", env: { "BUNDLER_VERSION" => Bundler::VERSION }
- expect(lockfile).to eq good_lockfile
+ PLATFORMS
+ java
+ ruby
- lockfile bad_lockfile
- bundle :lock, env: { "BUNDLER_VERSION" => Bundler::VERSION }
- expect(lockfile).to eq good_lockfile
+ DEPENDENCIES
+ empyrean (= 0.1.0)
+ pry
+ #{checksums}
+ BUNDLED WITH
+ 1.16.1
+ L
+
+ aggregate_failures do
+ lockfile bad_lockfile
+ bundle :install, env: { "BUNDLER_VERSION" => Bundler::VERSION }
+ expect(lockfile).to eq good_lockfile
+
+ lockfile bad_lockfile
+ bundle :update, all: true, env: { "BUNDLER_VERSION" => Bundler::VERSION }
+ expect(lockfile).to eq good_lockfile
+
+ lockfile bad_lockfile
+ bundle "update ffi", env: { "BUNDLER_VERSION" => Bundler::VERSION }
+ expect(lockfile).to eq good_lockfile
+
+ lockfile bad_lockfile
+ bundle "update empyrean", env: { "BUNDLER_VERSION" => Bundler::VERSION }
+ expect(lockfile).to eq good_lockfile
+
+ lockfile bad_lockfile
+ bundle :lock, env: { "BUNDLER_VERSION" => Bundler::VERSION }
+ expect(lockfile).to eq good_lockfile
+ end
end
end
it "works with gems with platform-specific dependency having different requirements order" do
- simulate_platform x64_mac
-
- update_repo2 do
- 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 "fspath", "< 4", ">= 2.1"
+ simulate_platform "x86_64-darwin-15" do
+ update_repo2 do
+ build_gem "fspath", "3"
+ build_gem "image_optim_pack", "1.2.3" do |s|
+ s.add_dependency "fspath", ">= 2.1", "< 4"
+ end
+ build_gem "image_optim_pack", "1.2.3" do |s|
+ s.platform = "universal-darwin"
+ s.add_dependency "fspath", "< 4", ">= 2.1"
+ end
end
- end
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- G
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ G
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ install_gemfile <<-G
+ source "https://gem.repo2"
- gem "image_optim_pack"
- G
+ gem "image_optim_pack"
+ G
- expect(err).not_to include "Unable to use the platform-specific"
+ expect(err).not_to include "Unable to use the platform-specific"
- expect(the_bundle).to include_gem "image_optim_pack 1.2.3 universal-darwin"
+ expect(the_bundle).to include_gem "image_optim_pack 1.2.3 universal-darwin"
+ end
end
it "fetches gems again after changing the version of Ruby" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
G
bundle "config set --local path vendor/bundle"
@@ -368,18 +371,18 @@ RSpec.describe "bundle install across platforms" do
FileUtils.mv(vendored_gems, bundled_app("vendor/bundle", Gem.ruby_engine, "1.8"))
bundle :install
- expect(vendored_gems("gems/rack-1.0.0")).to exist
+ expect(vendored_gems("gems/myrack-1.0.0")).to exist
end
it "keeps existing platforms when installing with force_ruby_platform" do
- checksums = checksums_section do |c|
- c.no_checksum "platform_specific", "1.0"
- c.no_checksum "platform_specific", "1.0", "java"
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo1, "platform_specific", "1.0"
+ c.checksum gem_repo1, "platform_specific", "1.0", "java"
end
lockfile <<-G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
platform_specific (1.0-java)
@@ -394,17 +397,17 @@ RSpec.describe "bundle install across platforms" do
bundle "config set --local force_ruby_platform true"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "platform_specific"
G
checksums.checksum gem_repo1, "platform_specific", "1.0"
- expect(the_bundle).to include_gem "platform_specific 1.0 RUBY"
+ expect(the_bundle).to include_gem "platform_specific 1.0 ruby"
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
platform_specific (1.0)
platform_specific (1.0-java)
@@ -417,7 +420,7 @@ RSpec.describe "bundle install across platforms" do
platform_specific
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
end
@@ -425,7 +428,7 @@ end
RSpec.describe "bundle install with platform conditionals" do
it "installs gems tagged w/ the current platforms" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
platforms :#{local_tag} do
gem "nokogiri"
@@ -437,14 +440,14 @@ RSpec.describe "bundle install with platform conditionals" do
it "does not install gems tagged w/ another platforms" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
platforms :#{not_local_tag} do
gem "nokogiri"
end
G
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
expect(the_bundle).not_to include_gems "nokogiri 1.4.2"
end
@@ -458,7 +461,7 @@ RSpec.describe "bundle install with platform conditionals" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "activesupport"
@@ -469,7 +472,7 @@ RSpec.describe "bundle install with platform conditionals" do
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
activesupport (6.1.4.1)
tzinfo (~> 2.0)
@@ -483,7 +486,7 @@ RSpec.describe "bundle install with platform conditionals" do
tzinfo (~> 1.2)
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "install --verbose"
@@ -493,7 +496,7 @@ RSpec.describe "bundle install with platform conditionals" do
it "installs gems tagged w/ the current platforms inline" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "nokogiri", :platforms => :#{local_tag}
G
expect(the_bundle).to include_gems "nokogiri 1.4.2"
@@ -501,17 +504,17 @@ RSpec.describe "bundle install with platform conditionals" do
it "does not install gems tagged w/ another platforms inline" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
gem "nokogiri", :platforms => :#{not_local_tag}
G
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
expect(the_bundle).not_to include_gems "nokogiri 1.4.2"
end
it "installs gems tagged w/ the current platform inline" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "nokogiri", :platform => :#{local_tag}
G
expect(the_bundle).to include_gems "nokogiri 1.4.2"
@@ -519,7 +522,7 @@ RSpec.describe "bundle install with platform conditionals" do
it "doesn't install gems tagged w/ another platform inline" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "nokogiri", :platform => :#{not_local_tag}
G
expect(the_bundle).not_to include_gems "nokogiri 1.4.2"
@@ -529,7 +532,7 @@ RSpec.describe "bundle install with platform conditionals" do
build_git "foo"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
platform :#{not_local_tag} do
gem "foo", :git => "#{lib_path("foo-1.0")}"
end
@@ -542,7 +545,7 @@ RSpec.describe "bundle install with platform conditionals" do
bundle "config set --local force_ruby_platform true"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "some_gem", :platform => :rbx
G
@@ -553,7 +556,7 @@ RSpec.describe "bundle install with platform conditionals" do
it "does not attempt to install gems from other rubies when using --local" do
bundle "config set --local force_ruby_platform true"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "some_gem", platform: :ruby_22
G
@@ -565,9 +568,9 @@ RSpec.describe "bundle install with platform conditionals" do
bundle "config set --local force_ruby_platform true"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack", :platform => [:windows, :mswin, :mswin64, :mingw, :x64_mingw, :jruby]
+ gem "myrack", :platform => [:windows, :jruby]
G
bundle "install"
@@ -576,17 +579,17 @@ RSpec.describe "bundle install with platform conditionals" do
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
ruby
DEPENDENCIES
- rack
- #{checksums_section_when_existing}
+ myrack
+ #{checksums_section_when_enabled}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
@@ -602,7 +605,7 @@ RSpec.describe "bundle install with platform conditionals" do
end
install_gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "listen"
gem "ffi", :platform => :windows
@@ -613,23 +616,23 @@ end
RSpec.describe "when a gem has no architecture" do
it "still installs correctly" do
- simulate_platform x86_mswin32
-
- 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'"
+ simulate_platform "x86-mswin32" do
+ 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
- end
- gemfile <<-G
- # Try to install gem with nil arch
- source "http://localgemserver.test/"
- gem "rcov"
- G
+ gemfile <<-G
+ # Try to install gem with nil arch
+ source "http://localgemserver.test/"
+ gem "rcov"
+ G
- bundle :install, artifice: "windows", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
- expect(the_bundle).to include_gems "rcov 1.0.0"
+ 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
end
diff --git a/spec/bundler/install/gemfile/ruby_spec.rb b/spec/bundler/install/gemfile/ruby_spec.rb
index b64d633fd3..d937abd714 100644
--- a/spec/bundler/install/gemfile/ruby_spec.rb
+++ b/spec/bundler/install/gemfile/ruby_spec.rb
@@ -10,112 +10,112 @@ RSpec.describe "ruby requirement" do
# requirement. This test verifies the fix, committed in bfbad5c5.
it "allows adding gems" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
ruby "#{Gem.ruby_version}"
- gem "rack"
+ gem "myrack"
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
ruby "#{Gem.ruby_version}"
- gem "rack"
- gem "rack-obama"
+ gem "myrack"
+ gem "myrack-obama"
G
- expect(the_bundle).to include_gems "rack-obama 1.0"
+ expect(the_bundle).to include_gems "myrack-obama 1.0"
end
it "allows removing the ruby version requirement" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
ruby "~> #{Gem.ruby_version}"
- gem "rack"
+ gem "myrack"
G
expect(lockfile).to include("RUBY VERSION")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
expect(lockfile).not_to include("RUBY VERSION")
end
it "allows changing the ruby version requirement to something compatible" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
ruby ">= #{current_ruby_minor}"
- gem "rack"
+ gem "myrack"
G
allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
expect(locked_ruby_version).to eq(Bundler::RubyVersion.system)
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
ruby ">= #{Gem.ruby_version}"
- gem "rack"
+ gem "myrack"
G
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
expect(locked_ruby_version).to eq(Bundler::RubyVersion.system)
end
it "allows changing the ruby version requirement to something incompatible" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
ruby ">= 1.0.0"
- gem "rack"
+ gem "myrack"
G
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
RUBY VERSION
- ruby 2.1.4p422
+ ruby 2.1.4
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
ruby ">= #{current_ruby_minor}"
- gem "rack"
+ gem "myrack"
G
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
expect(locked_ruby_version).to eq(Bundler::RubyVersion.system)
end
it "allows requirements with trailing whitespace" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
ruby "#{Gem.ruby_version}\\n \t\\n"
- gem "rack"
+ gem "myrack"
G
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "fails gracefully with malformed requirements" do
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
ruby ">= 0", "-.\\0"
- gem "rack"
+ gem "myrack"
G
expect(err).to include("There was an error parsing") # i.e. DSL error, not error template
@@ -125,9 +125,9 @@ RSpec.describe "ruby requirement" do
create_file ".ruby-version", Gem.ruby_version.to_s
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
ruby file: ".ruby-version"
- gem "rack"
+ gem "myrack"
G
expect(lockfile).to include("RUBY VERSION")
@@ -137,16 +137,16 @@ RSpec.describe "ruby requirement" do
create_file ".ruby-version", Gem.ruby_version.to_s
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
ruby file: ".ruby-version"
- gem "rack"
+ gem "myrack"
G
nested_dir = bundled_app(".ruby-lsp")
FileUtils.mkdir nested_dir
- create_file ".ruby-lsp/Gemfile", <<-G
+ gemfile ".ruby-lsp/Gemfile", <<-G
eval_gemfile(File.expand_path("../Gemfile", __dir__))
G
diff --git a/spec/bundler/install/gemfile/sources_spec.rb b/spec/bundler/install/gemfile/sources_spec.rb
index daee8a2744..90f87ed0c5 100644
--- a/spec/bundler/install/gemfile/sources_spec.rb
+++ b/spec/bundler/install/gemfile/sources_spec.rb
@@ -2,167 +2,20 @@
RSpec.describe "bundle install with gems on multiple sources" do
# repo1 is built automatically before all of the specs run
- # it contains rack-obama 1.0.0 and rack 0.9.1 & 1.0.0 amongst other gems
-
- context "without source affinity" do
- before do
- # Oh no! Someone evil is trying to hijack rack :(
- # need this to be broken to check for correct source ordering
- build_repo gem_repo3 do
- build_gem "rack", repo3_rack_version do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
- end
- end
- end
-
- context "with multiple toplevel sources" do
- let(:repo3_rack_version) { "1.0.0" }
-
- before do
- gemfile <<-G
- source "https://gem.repo3"
- source "https://gem.repo1"
- gem "rack-obama"
- gem "rack"
- G
- end
-
- it "refuses to install mismatched checksum because one gem has been tampered with", bundler: "< 3" do
- lockfile <<~L
- GEM
- remote: https://gem.repo3/
- remote: https://gem.repo1/
- specs:
- rack (1.0.0)
-
- PLATFORMS
- #{local_platform}
-
- DEPENDENCIES
- depends_on_rack!
-
- BUNDLED WITH
- #{Bundler::VERSION}
- L
-
- bundle :install, artifice: "compact_index", raise_on_error: false
-
- expect(exitstatus).to eq(37)
- expect(err).to eq <<~E.strip
- [DEPRECATED] Your Gemfile contains multiple global 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.
- Bundler found mismatched checksums. This is a potential security risk.
- #{checksum_to_lock(gem_repo1, "rack", "1.0.0")}
- from the API at https://gem.repo1/
- #{checksum_to_lock(gem_repo3, "rack", "1.0.0")}
- from the API at https://gem.repo3/
-
- Mismatched checksums each have an authoritative source:
- 1. the API at https://gem.repo1/
- 2. the API at https://gem.repo3/
- You may need to alter your Gemfile sources to resolve this issue.
-
- To ignore checksum security warnings, disable checksum validation with
- `bundle config set --local disable_checksum_validation true`
- E
- end
-
- context "when checksum validation is disabled" do
- before do
- bundle "config set --local disable_checksum_validation true"
- end
-
- 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: https://gem.repo1")
- expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0", source: "remote1")
- end
-
- it "does not use the full index unnecessarily", bundler: "< 3" do
- bundle :install, artifice: "compact_index", verbose: true
-
- expect(out).to include("https://gem.repo1/versions")
- expect(out).to include("https://gem.repo3/versions")
- expect(out).not_to include("https://gem.repo1/quick/Marshal.4.8/")
- expect(out).not_to include("https://gem.repo3/quick/Marshal.4.8/")
- 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 different versions of the same gem are in multiple sources" do
- let(:repo3_rack_version) { "1.2" }
-
- before do
- gemfile <<-G
- 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
- end
-
- 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: 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)
- end
- end
- end
-
- context "without source affinity, and a stdlib gem present in one of the sources", :ruby_repo do
- let(:default_json_version) { ruby "gem 'json'; require 'json'; puts JSON::VERSION" }
-
- before do
- build_repo2 do
- build_gem "json", default_json_version
- end
-
- build_repo4 do
- build_gem "foo" do |s|
- s.add_dependency "json", default_json_version
- end
- end
-
- gemfile <<-G
- source "https://gem.repo2"
- source "https://gem.repo4"
-
- gem "foo"
- G
- end
-
- it "works in standalone mode", bundler: "< 3" do
- gem_checksum = checksum_digest(gem_repo4, "foo", "1.0")
- bundle "install --standalone", artifice: "compact_index", env: { "BUNDLER_SPEC_FOO_CHECKSUM" => gem_checksum }
- end
- end
+ # it contains myrack-obama 1.0.0 and myrack 0.9.1 & 1.0.0 amongst other gems
context "with source affinity" do
context "with sources given by a block" do
before do
- # Oh no! Someone evil is trying to hijack rack :(
+ # Oh no! Someone evil is trying to hijack myrack :(
# need this to be broken to check for correct source ordering
- build_repo gem_repo3 do
- build_gem "rack", "1.0.0" do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
+ build_repo3 do
+ build_gem "myrack", "1.0.0" do |s|
+ s.write "lib/myrack.rb", "MYRACK = 'FAIL'"
end
- build_gem "rack-obama" do |s|
- s.add_dependency "rack"
+ build_gem "myrack-obama" do |s|
+ s.add_dependency "myrack"
end
end
@@ -170,76 +23,76 @@ RSpec.describe "bundle install with gems on multiple sources" do
source "https://gem.repo3"
source "https://gem.repo1" do
gem "thin" # comes first to test name sorting
- gem "rack"
+ gem "myrack"
end
- gem "rack-obama" # should come from repo3!
+ gem "myrack-obama" # should come from repo3!
G
end
it "installs the gems without any warning" do
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")
+ expect(the_bundle).to include_gems("myrack-obama 1.0.0")
+ expect(the_bundle).to include_gems("myrack 1.0.0", source: "remote1")
end
it "can cache and deploy" do
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
+ expect(bundled_app("vendor/cache/myrack-1.0.0.gem")).to exist
+ expect(bundled_app("vendor/cache/myrack-obama-1.0.gem")).to exist
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")
+ expect(the_bundle).to include_gems("myrack-obama 1.0.0", "myrack 1.0.0")
end
end
context "with sources set by an option" do
before do
- # Oh no! Someone evil is trying to hijack rack :(
+ # Oh no! Someone evil is trying to hijack myrack :(
# need this to be broken to check for correct source ordering
- build_repo gem_repo3 do
- build_gem "rack", "1.0.0" do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
+ build_repo3 do
+ build_gem "myrack", "1.0.0" do |s|
+ s.write "lib/myrack.rb", "MYRACK = 'FAIL'"
end
- build_gem "rack-obama" do |s|
- s.add_dependency "rack"
+ build_gem "myrack-obama" do |s|
+ s.add_dependency "myrack"
end
end
install_gemfile <<-G, artifice: "compact_index"
source "https://gem.repo3"
- gem "rack-obama" # should come from repo3!
- gem "rack", :source => "https://gem.repo1"
+ gem "myrack-obama" # should come from repo3!
+ gem "myrack", :source => "https://gem.repo1"
G
end
it "installs the gems without any warning" do
expect(err).not_to include("Warning")
- expect(the_bundle).to include_gems("rack-obama 1.0.0", "rack 1.0.0")
+ expect(the_bundle).to include_gems("myrack-obama 1.0.0", "myrack 1.0.0")
end
end
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"
+ build_repo3 do
+ build_gem "depends_on_myrack", "1.0.1" do |s|
+ s.add_dependency "myrack"
end
end
- # we need a working rack gem in repo3
+ # we need a working myrack gem in repo3
update_repo gem_repo3 do
- build_gem "rack", "1.0.0"
+ build_gem "myrack", "1.0.0"
end
gemfile <<-G
source "https://gem.repo2"
source "https://gem.repo3" do
- gem "depends_on_rack"
+ gem "depends_on_myrack"
end
G
end
@@ -252,7 +105,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
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")
+ expect(the_bundle).to include_gems("depends_on_myrack 1.0.1", "myrack 1.0.0", source: "remote3")
end
end
@@ -260,8 +113,8 @@ RSpec.describe "bundle install with gems on multiple sources" 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'"
+ build_gem "myrack", "1.0.0" do |s|
+ s.write "lib/myrack.rb", "MYRACK = 'FAIL'"
end
end
end
@@ -269,32 +122,32 @@ RSpec.describe "bundle install with gems on multiple sources" do
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")
+ expect(err).not_to include("Warning: the gem 'myrack' was found in multiple sources.")
+ expect(the_bundle).to include_gems("depends_on_myrack 1.0.1", "myrack 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
+ # when there is already a lockfile, 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")
+ expect(err).not_to include("Warning: the gem 'myrack' was found in multiple sources.")
+ expect(the_bundle).to include_gems("depends_on_myrack 1.0.1", "myrack 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
+ # In these tests, we need a working myrack 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"
+ build_repo3 do
+ build_gem "depends_on_myrack", "1.0.1" do |s|
+ s.add_dependency "myrack"
end
end
build_repo gem_repo2 do
- build_gem "rack", "1.0.0"
+ build_gem "myrack", "1.0.0"
end
end
@@ -303,197 +156,14 @@ RSpec.describe "bundle install with gems on multiple sources" do
install_gemfile <<-G, artifice: "compact_index"
source "https://gem.repo2"
source "https://gem.repo3" do
- gem "depends_on_rack"
+ gem "depends_on_myrack"
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 "https://gem.repo1"
- source "https://gem.repo2"
- source "https://gem.repo3" do
- gem "depends_on_rack"
- end
- G
- end
-
- it "fails when the two sources don't have the same checksum", bundler: "< 3" do
- bundle :install, artifice: "compact_index", raise_on_error: false
-
- expect(err).to eq(<<~E.strip)
- [DEPRECATED] Your Gemfile contains multiple global 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.
- Bundler found mismatched checksums. This is a potential security risk.
- #{checksum_to_lock(gem_repo2, "rack", "1.0.0")}
- from the API at https://gem.repo2/
- #{checksum_to_lock(gem_repo1, "rack", "1.0.0")}
- from the API at https://gem.repo1/
-
- Mismatched checksums each have an authoritative source:
- 1. the API at https://gem.repo2/
- 2. the API at https://gem.repo1/
- You may need to alter your Gemfile sources to resolve this issue.
-
- To ignore checksum security warnings, disable checksum validation with
- `bundle config set --local disable_checksum_validation true`
- E
- expect(exitstatus).to eq(37)
- end
-
- it "fails when the two sources agree, but the local gem calculates a different checksum", bundler: "< 3" do
- rack_checksum = "c0ffee11" * 8
- bundle :install, artifice: "compact_index", env: { "BUNDLER_SPEC_RACK_CHECKSUM" => rack_checksum }, raise_on_error: false
-
- expect(err).to eq(<<~E.strip)
- [DEPRECATED] Your Gemfile contains multiple global 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.
- Bundler found mismatched checksums. This is a potential security risk.
- rack (1.0.0) sha256=#{rack_checksum}
- from the API at https://gem.repo2/
- and the API at https://gem.repo1/
- #{checksum_to_lock(gem_repo2, "rack", "1.0.0")}
- from the gem at #{default_bundle_path("cache", "rack-1.0.0.gem")}
-
- If you trust the API at https://gem.repo2/, to resolve this issue you can:
- 1. remove the gem at #{default_bundle_path("cache", "rack-1.0.0.gem")}
- 2. run `bundle install`
-
- To ignore checksum security warnings, disable checksum validation with
- `bundle config set --local disable_checksum_validation true`
- E
- expect(exitstatus).to eq(37)
- end
-
- it "installs from the other source and warns about ambiguous gems when the sources have the same checksum", bundler: "< 3" do
- gem_checksum = checksum_digest(gem_repo2, "rack", "1.0.0")
- bundle :install, artifice: "compact_index", env: { "BUNDLER_SPEC_RACK_CHECKSUM" => gem_checksum, "DEBUG" => "1" }
-
- expect(err).to include("Warning: the gem 'rack' was found in multiple sources.")
- expect(err).to include("Installed from: https://gem.repo2")
-
- checksums = checksums_section_when_existing do |c|
- c.checksum gem_repo3, "depends_on_rack", "1.0.1"
- c.checksum gem_repo2, "rack", "1.0.0"
- end
-
- 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
- #{lockfile_platforms}
-
- DEPENDENCIES
- depends_on_rack!
- #{checksums}
- 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 other source and warns about ambiguous gems when checksum validation is disabled", bundler: "< 3" do
- bundle "config set --local disable_checksum_validation true"
- 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")
-
- checksums = checksums_section_when_existing do |c|
- c.no_checksum "depends_on_rack", "1.0.1"
- c.no_checksum "rack", "1.0.0"
- end
-
- 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
- #{lockfile_platforms}
-
- DEPENDENCIES
- depends_on_rack!
- #{checksums}
- 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 "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 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
-
- gemfile <<-G
- source "https://gem.repo3" # contains depends_on_rack
- source "https://gem.repo2" # contains broken rack
-
- gem "depends_on_rack" # installed from gem_repo3
- gem "rack", :source => "https://gem.repo1"
- G
- end
-
- it "installs the dependency from the pinned source without warning", bundler: "< 3" 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")
-
- # 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)
+ expect(the_bundle).to include_gems("depends_on_myrack 1.0.1", "myrack 1.0.0")
end
end
end
@@ -502,7 +172,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
before do
build_repo2
- build_repo gem_repo3 do
+ build_repo3 do
build_gem "private_gem_1", "1.0.0"
build_gem "private_gem_2", "1.0.0"
end
@@ -524,55 +194,22 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
end
- context "when an indirect dependency can't be found in the aggregate rubygems source", bundler: "< 3" do
- before do
- build_repo2
-
- build_repo gem_repo3 do
- build_gem "depends_on_missing", "1.0.1" do |s|
- s.add_dependency "missing"
- end
- end
-
- 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 end_with <<~E.strip
- Could not find compatible versions
-
- Because every version of depends_on_missing depends on missing >= 0
- and missing >= 0 could not be found in any of the sources,
- depends_on_missing cannot be used.
- So, because Gemfile depends on depends_on_missing >= 0,
- version solving has failed.
- E
- end
- end
-
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"
+ build_gem "depends_on_myrack", "1.0.1" do |s|
+ s.add_dependency "myrack"
end
end
- build_repo gem_repo3 do
+ build_repo3 do
build_gem "unrelated_gem", "1.0.0"
end
gemfile <<-G
source "https://gem.repo2"
- gem "depends_on_rack"
+ gem "depends_on_myrack"
source "https://gem.repo3" do
gem "unrelated_gem"
@@ -583,15 +220,15 @@ RSpec.describe "bundle install with gems on multiple sources" do
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"
+ build_gem "myrack", "1.0.0"
end
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("depends_on_myrack 1.0.1", "myrack 1.0.0", "unrelated_gem 1.0.0")
+ expect(the_bundle).to include_gems("depends_on_myrack 1.0.1", "myrack 1.0.0", source: "remote2")
expect(the_bundle).to include_gems("unrelated_gem 1.0.0", source: "remote3")
end
end
@@ -599,8 +236,8 @@ RSpec.describe "bundle install with gems on multiple sources" do
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'"
+ build_gem "myrack", "1.0.0" do |s|
+ s.write "lib/myrack.rb", "MYRACK = 'FAIL'"
end
end
end
@@ -610,10 +247,10 @@ RSpec.describe "bundle install with gems on multiple sources" do
expect(err).to end_with <<~E.strip
Could not find compatible versions
- Because every version of depends_on_rack depends on rack >= 0
- and rack >= 0 could not be found in rubygems repository https://gem.repo2/ or installed locally,
- depends_on_rack cannot be used.
- So, because Gemfile depends on depends_on_rack >= 0,
+ Because every version of depends_on_myrack depends on myrack >= 0
+ and myrack >= 0 could not be found in rubygems repository https://gem.repo2/ or installed locally,
+ depends_on_myrack cannot be used.
+ So, because Gemfile depends on depends_on_myrack >= 0,
version solving has failed.
E
end
@@ -622,12 +259,12 @@ RSpec.describe "bundle install with gems on multiple sources" do
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"
+ build_gem "myrack", "1.0.0"
end
update_repo gem_repo3 do
- build_gem "rack", "1.0.0" do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
+ build_gem "myrack", "1.0.0" do |s|
+ s.write "lib/myrack.rb", "MYRACK = 'FAIL'"
end
end
end
@@ -635,9 +272,9 @@ RSpec.describe "bundle install with gems on multiple sources" do
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(run("require 'myrack'; puts MYRACK")).to eq("1.0.0")
+ expect(the_bundle).to include_gems("depends_on_myrack 1.0.1", "myrack 1.0.0", "unrelated_gem 1.0.0")
+ expect(the_bundle).to include_gems("depends_on_myrack 1.0.1", "myrack 1.0.0", source: "remote2")
expect(the_bundle).to include_gems("unrelated_gem 1.0.0", source: "remote3")
end
end
@@ -645,13 +282,13 @@ RSpec.describe "bundle install with gems on multiple sources" do
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"
+ build_repo3 do
+ build_gem "depends_on_depends_on_myrack", "1.0.1" do |s|
+ s.add_dependency "depends_on_myrack"
end
- build_gem "depends_on_rack", "1.0.1" do |s|
- s.add_dependency "rack"
+ build_gem "depends_on_myrack", "1.0.1" do |s|
+ s.add_dependency "myrack"
end
end
@@ -659,7 +296,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
source "https://gem.repo2"
source "https://gem.repo3" do
- gem "depends_on_depends_on_rack"
+ gem "depends_on_depends_on_myrack"
end
G
end
@@ -667,15 +304,15 @@ RSpec.describe "bundle install with gems on multiple sources" do
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"
+ build_gem "myrack", "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")
+ expect(the_bundle).to include_gems("depends_on_depends_on_myrack 1.0.1", "depends_on_myrack 1.0.1", "myrack 1.0.0")
+ expect(the_bundle).to include_gems("myrack 1.0.0", source: "remote2")
+ expect(the_bundle).to include_gems("depends_on_depends_on_myrack 1.0.1", "depends_on_myrack 1.0.1", source: "remote3")
end
end
@@ -684,367 +321,36 @@ RSpec.describe "bundle install with gems on multiple sources" do
build_repo2
update_repo gem_repo3 do
- build_gem "rack", "1.0.0"
+ build_gem "myrack", "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")
+ expect(the_bundle).to include_gems("depends_on_depends_on_myrack 1.0.1", "depends_on_myrack 1.0.1", "myrack 1.0.0", source: "remote3")
end
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" do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
+ build_gem "myrack", "1.0.0" do |s|
+ s.write "lib/myrack.rb", "MYRACK = 'FAIL'"
end
end
update_repo gem_repo3 do
- build_gem "rack", "1.0.0"
+ build_gem "myrack", "1.0.0"
end
end
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")
+ expect(the_bundle).to include_gems("depends_on_depends_on_myrack 1.0.1", "depends_on_myrack 1.0.1", "myrack 1.0.0", source: "remote3")
end
end
end
- 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
-
- 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
-
- 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
-
- build_gem "tzinfo", "2.0.4" do |s|
- s.add_dependency "concurrent-ruby", "~> 1.0"
- end
-
- build_gem "zeitwerk", "2.4.2"
- 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
-
- source "https://gem.repo2"
-
- gem "activesupport"
-
- source "https://gem.repo3" do
- gem "sidekiq-pro"
- end
- G
-
- @locked_checksums = checksums_section_when_existing do |c|
- c.checksum gem_repo2, "activesupport", "6.0.3.4"
- c.checksum gem_repo2, "concurrent-ruby", "1.1.8"
- c.checksum gem_repo2, "connection_pool", "2.2.3"
- c.checksum gem_repo2, "i18n", "1.8.9"
- c.checksum gem_repo2, "minitest", "5.14.3"
- c.checksum gem_repo2, "rack", "2.2.3"
- c.checksum gem_repo2, "redis", "4.2.5"
- c.checksum gem_repo2, "sidekiq", "6.1.3"
- c.checksum gem_repo3, "sidekiq-pro", "5.2.1"
- c.checksum gem_repo2, "thread_safe", "0.3.6"
- c.checksum gem_repo2, "tzinfo", "1.2.9"
- c.checksum gem_repo2, "zeitwerk", "2.4.2"
- end
-
- 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
- #{lockfile_platforms}
-
- DEPENDENCIES
- activesupport
- sidekiq-pro!
- #{@locked_checksums}
- 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
- #{lockfile_platforms}
-
- DEPENDENCIES
- activesupport
- sidekiq-pro!
- #{@locked_checksums}
- 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")
- @locked_checksums.checksum gem_repo2, "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")
- @locked_checksums.checksum gem_repo2, "tzinfo", "2.0.4"
- @locked_checksums.delete "thread_safe"
-
- expect(the_bundle).not_to include_gems("concurrent-ruby 1.1.8")
- expect(the_bundle).to include_gems("concurrent-ruby 1.1.9")
- @locked_checksums.checksum gem_repo2, "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
- #{lockfile_platforms}
-
- DEPENDENCIES
- activesupport
- sidekiq-pro!
- #{@locked_checksums}
- 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")
-
- @locked_checksums.checksum gem_repo2, "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.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
- #{lockfile_platforms}
-
- DEPENDENCIES
- activesupport
- sidekiq-pro!
- #{@locked_checksums}
- 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")
@@ -1080,7 +386,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
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_repo3 do
build_gem "handsoap", "0.2.5.5" do |s|
s.add_dependency "nokogiri", ">= 1.2.3"
end
@@ -1106,7 +412,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
it "installs from the default source without any warnings or errors and generates a proper lockfile" do
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo3, "handsoap", "0.2.5.5"
c.checksum gem_repo2, "nokogiri", "1.11.1"
c.checksum gem_repo2, "racca", "1.5.2"
@@ -1134,7 +440,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
nokogiri
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "install --verbose", artifice: "compact_index"
@@ -1157,7 +463,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
context "with a gem that is only found in the wrong source" do
before do
- build_repo gem_repo3 do
+ build_repo3 do
build_gem "not_in_repo1", "1.0.0"
end
@@ -1174,7 +480,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
context "with an existing lockfile" do
before do
- system_gems "rack-0.9.1", "rack-1.0.0", path: default_bundle_path
+ system_gems "myrack-0.9.1", "myrack-1.0.0", path: default_bundle_path
lockfile <<-L
GEM
@@ -1184,132 +490,26 @@ RSpec.describe "bundle install with gems on multiple sources" do
GEM
remote: https://gem.repo3
specs:
- rack (0.9.1)
+ myrack (0.9.1)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack!
+ myrack!
L
gemfile <<-G
source "https://gem.repo1"
source "https://gem.repo3" do
- gem 'rack'
+ gem 'myrack'
end
G
end
# 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
- #{lockfile_platforms}
-
- DEPENDENCIES
- rack!
- #{checksums_section}
- 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
- #{lockfile_platforms}
-
- 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 when checksum validation is disabled", bundler: "< 3" do
- bundle "config set --local deployment true"
- bundle "config set --local disable_checksum_validation 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 "prints a checksum warning when the checksums from both sources do not match", bundler: "< 3" do
- bundle "config set --local deployment true"
-
- bundle "install", artifice: "compact_index", raise_on_error: false
-
- api_checksum1 = checksum_digest(gem_repo1, "rack", "0.9.1")
- api_checksum3 = checksum_digest(gem_repo3, "rack", "0.9.1")
-
- expect(exitstatus).to eq(37)
- expect(err).to eq(<<~E.strip)
- [DEPRECATED] 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 found mismatched checksums. This is a potential security risk.
- rack (0.9.1) sha256=#{api_checksum3}
- from the API at https://gem.repo3/
- rack (0.9.1) sha256=#{api_checksum1}
- from the API at https://gem.repo1/
-
- Mismatched checksums each have an authoritative source:
- 1. the API at https://gem.repo3/
- 2. the API at https://gem.repo1/
- You may need to alter your Gemfile sources to resolve this issue.
-
- To ignore checksum security warnings, disable checksum validation with
- `bundle config set --local disable_checksum_validation true`
- E
- 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
+ expect(the_bundle).to include_gems("myrack 0.9.1")
end
end
@@ -1318,8 +518,8 @@ RSpec.describe "bundle install with gems on multiple sources" do
build_lib "foo"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :source => "https://gem.repo1"
+ source "https://gem.repo1"
+ gem "myrack", :source => "https://gem.repo1"
gem "foo", :path => "#{lib_path("foo-1.0")}"
G
end
@@ -1336,17 +536,17 @@ RSpec.describe "bundle install with gems on multiple sources" do
context "when an older version of the same gem also ships with Ruby" do
before do
- system_gems "rack-0.9.1"
+ system_gems "myrack-0.9.1"
install_gemfile <<-G, artifice: "compact_index"
source "https://gem.repo1"
- gem "rack" # should come from repo1!
+ gem "myrack" # should come from repo1!
G
end
it "installs the gems without any warning" do
expect(err).not_to include("Warning")
- expect(the_bundle).to include_gems("rack 1.0.0")
+ expect(the_bundle).to include_gems("myrack 1.0.0")
end
end
@@ -1361,7 +561,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
# Installing this gemfile...
gemfile <<-G
source 'https://gem.repo1'
- gem 'rack'
+ gem 'myrack'
gem 'foo', '~> 0.1', :source => 'https://gem.repo4'
gem 'bar', '~> 0.1', :source => 'https://gem.repo4'
G
@@ -1370,7 +570,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
bundle :install, artifice: "compact_index"
# And then we add some new versions...
- update_repo4 do
+ build_repo4 do
build_gem "foo", "0.2"
build_gem "bar", "0.3"
end
@@ -1380,7 +580,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
# And install this gemfile, updating only foo.
install_gemfile <<-G, artifice: "compact_index"
source 'https://gem.repo1'
- gem 'rack'
+ gem 'myrack'
gem 'foo', '~> 0.2', :source => 'https://gem.repo4'
gem 'bar', '~> 0.1', :source => 'https://gem.repo4'
G
@@ -1393,8 +593,8 @@ RSpec.describe "bundle install with gems on multiple sources" do
context "re-resolving" do
context "when there is a mix of sources in the gemfile" do
before do
- build_repo gem_repo3 do
- build_gem "rack"
+ build_repo3 do
+ build_gem "myrack"
end
build_lib "path1"
@@ -1407,7 +607,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
gem "rails"
source "https://gem.repo3" do
- gem "rack"
+ gem "myrack"
end
gem "path1", :path => "#{lib_path("path1-1.0")}"
@@ -1429,14 +629,14 @@ RSpec.describe "bundle install with gems on multiple sources" do
before do
install_gemfile <<-G, artifice: "compact_index"
source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
G
end
context "and the gemfile changes" do
it "is still able to find that gem from remote sources" do
build_repo4 do
- build_gem "rack", "2.0.1.1.forked"
+ build_gem "myrack", "2.0.1.1.forked"
build_gem "thor", "0.19.1.1.forked"
end
@@ -1445,10 +645,10 @@ RSpec.describe "bundle install with gems on multiple sources" do
source "https://gem.repo1"
source "https://gem.repo4" do
- gem "rack", "2.0.1.1.forked"
+ gem "myrack", "2.0.1.1.forked"
gem "thor"
end
- gem "rack-obama"
+ gem "myrack-obama"
G
# Then we change the Gemfile by adding a version to thor
@@ -1456,13 +656,13 @@ RSpec.describe "bundle install with gems on multiple sources" do
source "https://gem.repo1"
source "https://gem.repo4" do
- gem "rack", "2.0.1.1.forked"
+ gem "myrack", "2.0.1.1.forked"
gem "thor", "0.19.1.1.forked"
end
- gem "rack-obama"
+ gem "myrack-obama"
G
- # But we should still be able to find rack 2.0.1.1.forked and install it
+ # But we should still be able to find myrack 2.0.1.1.forked and install it
bundle :install, artifice: "compact_index"
end
end
@@ -1473,30 +673,30 @@ RSpec.describe "bundle install with gems on multiple sources" do
install_gemfile <<-G, artifice: "compact_index"
source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
G
build_repo2 do
- build_gem "rack", "1.2" do |s|
- s.executables = "rackup"
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
end
build_gem "bar"
end
- build_lib("gemspec_test", path: tmp.join("gemspec_test")) do |s|
+ build_lib("gemspec_test", path: tmp("gemspec_test")) do |s|
s.add_dependency "bar", "=1.0.0"
end
install_gemfile <<-G, artifice: "compact_index"
source "https://gem.repo2"
- gem "rack"
- gemspec :path => "#{tmp.join("gemspec_test")}"
+ gem "myrack"
+ gemspec :path => "#{tmp("gemspec_test")}"
G
end
it "conservatively installs the existing locked version" do
- expect(the_bundle).to include_gems("rack 1.0.0")
+ expect(the_bundle).to include_gems("myrack 1.0.0")
end
end
@@ -1506,7 +706,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
build_gem "bar"
end
- build_lib("gemspec_test", path: tmp.join("gemspec_test")) do |s|
+ build_lib("gemspec_test", path: tmp("gemspec_test")) do |s|
s.add_development_dependency "bar"
end
@@ -1517,7 +717,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
gem "bar"
end
- gemspec :path => "#{tmp.join("gemspec_test")}"
+ gemspec :path => "#{tmp("gemspec_test")}"
G
end
@@ -1583,143 +783,37 @@ RSpec.describe "bundle install with gems on multiple sources" do
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
+ context "when an indirect dependency is available from multiple ambiguous sources" do
+ it "raises, suggesting a source block" do
build_repo4 do
- build_gem "depends_on_rack" do |s|
- s.add_dependency "rack"
+ build_gem "depends_on_myrack" do |s|
+ s.add_dependency "myrack"
end
- build_gem "rack"
+ build_gem "myrack"
end
- install_gemfile <<-G, artifice: "compact_index", raise_on_error: false
- source "#{file_uri_for(gem_repo1)}"
+ install_gemfile <<-G, artifice: "compact_index_extra_api", raise_on_error: false
+ source "https://global.source"
- source "https://gem.repo4" do
- gem "depends_on_rack"
+ source "https://scoped.source/extra" do
+ gem "depends_on_myrack"
end
- source "https://gem.repo1" do
- gem "thin"
- end
- G
- expect(err).to eq <<~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 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|
- 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
- source "https://gem.repo1" do
+ source "https://scoped.source" do
gem "thin"
end
G
expect(last_command).to be_failure
expect(err).to eq <<~EOS.strip
- The gem 'rack' was found in multiple relevant sources.
- * rubygems repository https://gem.repo1/
- * rubygems repository https://gem.repo4/
+ The gem 'myrack' was found in multiple relevant sources.
+ * rubygems repository https://scoped.source/
+ * rubygems repository https://scoped.source/extra/
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
- #{lockfile_platforms}
-
- DEPENDENCIES
- capybara (~> 2.5.0)
- mime-types (~> 3.0)!
-
- CHECKSUMS
- L
- end
-
- it "upgrades the lockfile correctly" do
- bundle "lock --update", artifice: "compact_index"
-
- checksums = checksums_section_when_existing do |c|
- c.checksum gem_repo2, "capybara", "2.5.0"
- c.checksum gem_repo4, "mime-types", "3.0.0"
- end
-
- 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
- #{lockfile_platforms}
-
- DEPENDENCIES
- capybara (~> 2.5.0)
- mime-types (~> 3.0)!
- #{checksums}
- BUNDLED WITH
- #{Bundler::VERSION}
- L
- end
- end
-
context "when default source includes old gems with nil required_ruby_version" do
before do
build_repo2 do
@@ -1740,28 +834,28 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
gemfile <<~G
- source "https://localgemserver.test"
+ source "https://gem.repo4"
- gem "ruport", "= 1.7.0.3", :source => "https://localgemserver.test/extra"
+ gem "ruport", "= 1.7.0.3", :source => "https://gem.repo4/extra"
G
end
it "handles that fine" do
- bundle "install", artifice: "compact_index_extra", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ bundle "install", artifice: "compact_index_extra"
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo4, "pdf-writer", "1.1.8"
c.checksum gem_repo2, "ruport", "1.7.0.3"
end
expect(lockfile).to eq <<~L
GEM
- remote: https://localgemserver.test/
+ remote: https://gem.repo4/
specs:
pdf-writer (1.1.8)
GEM
- remote: https://localgemserver.test/extra/
+ remote: https://gem.repo4/extra/
specs:
ruport (1.7.0.3)
pdf-writer (= 1.1.8)
@@ -1773,7 +867,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
ruport (= 1.7.0.3)!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
@@ -1798,28 +892,28 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
gemfile <<~G
- source "https://localgemserver.test"
+ source "https://gem.repo4"
- gem "ruport", "= 1.7.0.3", :source => "https://localgemserver.test/extra"
+ gem "ruport", "= 1.7.0.3", :source => "https://gem.repo4/extra"
G
end
it "handles that fine" do
- bundle "install", artifice: "compact_index_extra", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ bundle "install", artifice: "compact_index_extra"
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo4, "pdf-writer", "1.1.8"
c.checksum gem_repo2, "ruport", "1.7.0.3"
end
expect(lockfile).to eq <<~L
GEM
- remote: https://localgemserver.test/
+ remote: https://gem.repo4/
specs:
pdf-writer (1.1.8)
GEM
- remote: https://localgemserver.test/extra/
+ remote: https://gem.repo4/extra/
specs:
ruport (1.7.0.3)
pdf-writer (= 1.1.8)
@@ -1831,7 +925,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
ruport (= 1.7.0.3)!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
@@ -1850,22 +944,22 @@ RSpec.describe "bundle install with gems on multiple sources" do
end
gemfile <<~G
- source "https://localgemserver.test"
+ source "https://gem.repo4"
gem "pdf-writer", "= 1.1.8"
G
end
it "handles that fine" do
- bundle "install --verbose", artifice: "endpoint", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ bundle "install --verbose", artifice: "endpoint"
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo4, "pdf-writer", "1.1.8"
end
expect(lockfile).to eq <<~L
GEM
- remote: https://localgemserver.test/
+ remote: https://gem.repo4/
specs:
pdf-writer (1.1.8)
@@ -1876,7 +970,7 @@ RSpec.describe "bundle install with gems on multiple sources" do
pdf-writer (= 1.1.8)
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
@@ -1919,4 +1013,186 @@ RSpec.describe "bundle install with gems on multiple sources" do
expect(err).to include("Could not find gem 'example' in rubygems repository https://gem.repo4/")
end
end
+
+ context "when a gem has versions in two sources, but only the locked one has updates" do
+ let(:original_lockfile) do
+ <<~L
+ GEM
+ remote: https://main.source/
+ specs:
+ activesupport (1.0)
+ bigdecimal
+ bigdecimal (1.0.0)
+
+ GEM
+ remote: https://main.source/extra/
+ specs:
+ foo (1.0)
+ bigdecimal
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ activesupport
+ foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ before do
+ build_repo3 do
+ build_gem "activesupport" do |s|
+ s.add_dependency "bigdecimal"
+ end
+
+ build_gem "bigdecimal", "1.0.0"
+ build_gem "bigdecimal", "3.3.1"
+ end
+
+ build_repo4 do
+ build_gem "foo" do |s|
+ s.add_dependency "bigdecimal"
+ end
+
+ build_gem "bigdecimal", "1.0.0"
+ end
+
+ gemfile <<~G
+ source "https://main.source"
+
+ gem "activesupport"
+
+ source "https://main.source/extra" do
+ gem "foo"
+ end
+ G
+
+ lockfile original_lockfile
+ end
+
+ it "properly upgrades the lockfile when updating that specific gem" do
+ bundle "update bigdecimal --conservative", artifice: "compact_index_extra_api", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo3.to_s }
+
+ expect(lockfile).to eq original_lockfile.gsub("bigdecimal (1.0.0)", "bigdecimal (3.3.1)")
+ end
+ end
+
+ context "when switching a gem with components from rubygems to git source" do
+ before do
+ build_repo2 do
+ build_gem "rails", "7.0.0" do |s|
+ s.add_dependency "actionpack", "7.0.0"
+ s.add_dependency "activerecord", "7.0.0"
+ end
+ build_gem "actionpack", "7.0.0"
+ build_gem "activerecord", "7.0.0"
+ # propshaft also depends on actionpack, creating the conflict
+ build_gem "propshaft", "1.0.0" do |s|
+ s.add_dependency "actionpack", ">= 7.0.0"
+ end
+ end
+
+ build_git "rails", "7.0.0", path: lib_path("rails") do |s|
+ s.add_dependency "actionpack", "7.0.0"
+ s.add_dependency "activerecord", "7.0.0"
+ end
+
+ build_git "actionpack", "7.0.0", path: lib_path("rails")
+ build_git "activerecord", "7.0.0", path: lib_path("rails")
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "rails", "7.0.0"
+ gem "propshaft"
+ G
+ end
+
+ it "moves component gems to the git source in the lockfile" do
+ expect(lockfile).to include("remote: https://gem.repo2")
+ expect(lockfile).to include("rails (7.0.0)")
+ expect(lockfile).to include("actionpack (7.0.0)")
+ expect(lockfile).to include("activerecord (7.0.0)")
+ expect(lockfile).to include("propshaft (1.0.0)")
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "rails", git: "#{lib_path("rails")}"
+ gem "propshaft"
+ G
+
+ bundle "install"
+
+ expect(lockfile).to include("remote: #{lib_path("rails")}")
+ expect(lockfile).to include("rails (7.0.0)")
+ expect(lockfile).to include("actionpack (7.0.0)")
+ expect(lockfile).to include("activerecord (7.0.0)")
+
+ # Component gems should NOT remain in the GEM section
+ # Extract just the GEM section by splitting on GIT first, then GEM
+ gem_section = lockfile.split("GEM\n").last.split(/\n(PLATFORMS|DEPENDENCIES)/)[0]
+ expect(gem_section).not_to include("actionpack (7.0.0)")
+ expect(gem_section).not_to include("activerecord (7.0.0)")
+ end
+ end
+
+ context "when switching a gem with components from rubygems to path source" do
+ before do
+ build_repo2 do
+ build_gem "rails", "7.0.0" do |s|
+ s.add_dependency "actionpack", "7.0.0"
+ s.add_dependency "activerecord", "7.0.0"
+ end
+ build_gem "actionpack", "7.0.0"
+ build_gem "activerecord", "7.0.0"
+ # propshaft also depends on actionpack, creating the conflict
+ build_gem "propshaft", "1.0.0" do |s|
+ s.add_dependency "actionpack", ">= 7.0.0"
+ end
+ end
+
+ build_lib "rails", "7.0.0", path: lib_path("rails") do |s|
+ s.add_dependency "actionpack", "7.0.0"
+ s.add_dependency "activerecord", "7.0.0"
+ end
+
+ build_lib "actionpack", "7.0.0", path: lib_path("rails")
+ build_lib "activerecord", "7.0.0", path: lib_path("rails")
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "rails", "7.0.0"
+ gem "propshaft"
+ G
+ end
+
+ it "moves component gems to the path source in the lockfile" do
+ expect(lockfile).to include("remote: https://gem.repo2")
+ expect(lockfile).to include("rails (7.0.0)")
+ expect(lockfile).to include("actionpack (7.0.0)")
+ expect(lockfile).to include("activerecord (7.0.0)")
+ expect(lockfile).to include("propshaft (1.0.0)")
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem "rails", path: "#{lib_path("rails")}"
+ gem "propshaft"
+ G
+
+ bundle "install"
+
+ expect(lockfile).to include("remote: #{lib_path("rails")}")
+ expect(lockfile).to include("rails (7.0.0)")
+ expect(lockfile).to include("actionpack (7.0.0)")
+ expect(lockfile).to include("activerecord (7.0.0)")
+
+ # Component gems should NOT remain in the GEM section
+ # Extract just the GEM section by splitting appropriately
+ gem_section = lockfile.split("GEM\n").last.split(/\n(PLATFORMS|DEPENDENCIES)/)[0]
+ expect(gem_section).not_to include("actionpack (7.0.0)")
+ expect(gem_section).not_to include("activerecord (7.0.0)")
+ end
+ end
end
diff --git a/spec/bundler/install/gemfile/specific_platform_spec.rb b/spec/bundler/install/gemfile/specific_platform_spec.rb
index 1a33053dc6..448800d578 100644
--- a/spec/bundler/install/gemfile/specific_platform_spec.rb
+++ b/spec/bundler/install/gemfile/specific_platform_spec.rb
@@ -2,7 +2,7 @@
RSpec.describe "bundle install with specific platforms" do
let(:google_protobuf) { <<-G }
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "google-protobuf"
G
@@ -11,7 +11,7 @@ RSpec.describe "bundle install with specific platforms" 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 include(pl("x86_64-darwin-15"))
+ expect(the_bundle.locked_platforms).to include("universal-darwin")
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 include(
"google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin"
@@ -19,21 +19,65 @@ RSpec.describe "bundle install with specific platforms" do
end
end
+ it "still installs the platform specific variant when locked only to ruby, and the platform specific variant has different dependencies" do
+ simulate_platform "x86_64-darwin-15" do
+ build_repo4 do
+ build_gem("sass-embedded", "1.72.0") do |s|
+ s.add_dependency "rake"
+ end
+
+ build_gem("sass-embedded", "1.72.0") do |s|
+ s.platform = "x86_64-darwin-15"
+ end
+
+ build_gem "rake"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "sass-embedded"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ rake (1.0)
+ sass-embedded (1.72.0)
+ rake
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ sass-embedded
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install --verbose"
+ expect(err).to include("The following platform specific gems are getting installed, yet the lockfile includes only their generic ruby version")
+ expect(out).to include("Installing sass-embedded 1.72.0 (x86_64-darwin-15)")
+
+ expect(the_bundle).to include_gem("sass-embedded 1.72.0 x86_64-darwin-15")
+ end
+ end
+
it "understands that a non-platform specific gem in a old lockfile doesn't necessarily mean installing the non-specific variant" do
simulate_platform "x86_64-darwin-15" 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" }
+ bundle "config set --local path vendor/bundle"
- install_gemfile(google_protobuf, env: { "BUNDLER_VERSION" => "2.1.4" })
+ install_gemfile(google_protobuf)
# simulate lockfile created with old bundler, which only locks for ruby platform
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
google-protobuf (3.0.0.alpha.5.0.5.1)
@@ -44,36 +88,34 @@ RSpec.describe "bundle install with specific platforms" do
google-protobuf
BUNDLED WITH
- 2.1.4
+ #{Bundler::VERSION}
L
- # force strict usage of the lock file by setting frozen mode
- bundle "config set --local frozen true", env: { "BUNDLER_VERSION" => "2.1.4" }
+ # force strict usage of the lockfile by setting frozen mode
+ bundle "config set --local frozen true"
# 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
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
+ 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
simulate_platform "x86_64-darwin-15" 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" }
+ bundle "config set --local path vendor/bundle"
gemfile google_protobuf
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo2, "google-protobuf", "3.0.0.alpha.4.0"
end
# simulate lockfile created with old bundler, which only locks for ruby platform
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
google-protobuf (3.0.0.alpha.4.0)
@@ -84,10 +126,11 @@ RSpec.describe "bundle install with specific platforms" do
google-protobuf
#{checksums}
BUNDLED WITH
- 2.1.4
+ #{Bundler::VERSION}
L
- bundle "update", env: { "BUNDLER_VERSION" => Bundler::VERSION }
+ bundle "update"
+ expect(err).to include("The following platform specific gems are getting installed, yet the lockfile includes only their generic ruby version")
checksums.checksum gem_repo2, "google-protobuf", "3.0.0.alpha.5.0.5.1"
@@ -97,7 +140,7 @@ RSpec.describe "bundle install with specific platforms" do
# make sure we're still only locked to ruby
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
google-protobuf (3.0.0.alpha.5.0.5.1)
@@ -108,12 +151,17 @@ RSpec.describe "bundle install with specific platforms" do
google-protobuf
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
- context "when running on a legacy lockfile locked only to RUBY" do
+ context "when running on a legacy lockfile locked only to ruby" do
+ # Exercises the legacy lockfile path (use_exact_resolved_specifications? = false)
+ # because most_specific_locked_platform is ruby, matching the generic platform.
+ # Key insight: when target (arm64-darwin-22) != platform (ruby), the code tries
+ # both platforms before falling back, preserving lockfile integrity.
+
around do |example|
build_repo4 do
build_gem "nokogiri", "1.3.10"
@@ -124,14 +172,14 @@ RSpec.describe "bundle install with specific platforms" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "nokogiri"
G
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
nokogiri (1.3.10)
@@ -142,20 +190,76 @@ RSpec.describe "bundle install with specific platforms" do
nokogiri
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
simulate_platform "arm64-darwin-22", &example
end
- it "still installs the generic RUBY variant if necessary" do
- bundle "install --verbose", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
- expect(out).to include("Installing nokogiri 1.3.10")
+ it "still installs the generic ruby variant if necessary" do
+ bundle "install"
+ expect(the_bundle).to include_gem("nokogiri 1.3.10")
+ expect(the_bundle).not_to include_gem("nokogiri 1.3.10 arm64-darwin")
end
- it "still installs the generic RUBY variant if necessary, even in frozen mode" do
- bundle "install --verbose", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s, "BUNDLE_FROZEN" => "true" }
- expect(out).to include("Installing nokogiri 1.3.10")
+ it "still installs the generic ruby variant if necessary, even in frozen mode" do
+ bundle "install", env: { "BUNDLE_FROZEN" => "true" }
+ expect(the_bundle).to include_gem("nokogiri 1.3.10")
+ expect(the_bundle).not_to include_gem("nokogiri 1.3.10 arm64-darwin")
+ end
+ end
+
+ context "when platform-specific gem has incompatible required_ruby_version" do
+ # Key insight: candidate_platforms tries [target, platform, ruby] in order.
+ # Ruby platform is last since it requires compilation, but works when
+ # precompiled gems are incompatible with the current Ruby version.
+ #
+ # Note: This fix requires the lockfile to include both ruby and platform-
+ # specific variants (typical after `bundle lock --add-platform`). If the
+ # lockfile only has platform-specific gems, frozen mode cannot help because
+ # Bundler.setup would still expect the locked (incompatible) gem.
+
+ # Exercises the exact spec path (use_exact_resolved_specifications? = true)
+ # because lockfile has platform-specific entry as most_specific_locked_platform
+ it "falls back to ruby platform in frozen mode when lockfile includes both variants" do
+ build_repo4 do
+ build_gem "nokogiri", "1.18.10"
+ build_gem "nokogiri", "1.18.10" do |s|
+ s.platform = "x86_64-linux"
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ G
+
+ # Lockfile has both ruby and platform-specific gem (typical after `bundle lock --add-platform`)
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.18.10)
+ nokogiri (1.18.10-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "x86_64-linux" do
+ bundle "install", env: { "BUNDLE_FROZEN" => "true" }
+ expect(the_bundle).to include_gem("nokogiri 1.18.10")
+ expect(the_bundle).not_to include_gem("nokogiri 1.18.10 x86_64-linux")
+ end
end
end
@@ -166,24 +270,22 @@ RSpec.describe "bundle install with specific platforms" do
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"
+ s.add_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" }
+ bundle "config set --local path vendor/bundle"
gemfile <<-G
- source "https://localgemserver.test"
+ source "https://gem.repo2"
gem "libv8"
G
# simulate lockfile created with old bundler, which only locks for ruby platform
lockfile <<-L
GEM
- remote: https://localgemserver.test/
+ remote: https://gem.repo2/
specs:
libv8 (8.4.255.0)
@@ -194,13 +296,14 @@ RSpec.describe "bundle install with specific platforms" do
libv8
BUNDLED WITH
- 2.1.4
+ #{Bundler::VERSION}
L
- bundle "install --verbose", artifice: "compact_index", env: { "BUNDLER_VERSION" => "2.1.4", "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+ bundle "install --verbose"
+ expect(err).to include("The following platform specific gems are getting installed, yet the lockfile includes only their generic ruby version")
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 }
+ bundle "add mini_racer --verbose"
expect(out).to include("Using libv8 8.4.255.0 (universal-darwin)")
end
end
@@ -213,14 +316,14 @@ RSpec.describe "bundle install with specific platforms" do
end
gemfile <<-G
- source "https://localgemserver.test"
+ source "https://gem.repo4"
gem "grpc"
G
# simulate lockfile created with old bundler, which only locks for ruby platform
lockfile <<-L
GEM
- remote: https://localgemserver.test/
+ remote: https://gem.repo4/
specs:
grpc (1.50.0)
@@ -231,10 +334,11 @@ RSpec.describe "bundle install with specific platforms" do
grpc
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
- bundle "install --verbose", artifice: "compact_index_precompiled_before", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ bundle "install --verbose", artifice: "compact_index_precompiled_before"
+ expect(err).to include("The following platform specific gems are getting installed, yet the lockfile includes only their generic ruby version")
expect(out).to include("Installing grpc 1.50.0 (universal-darwin)")
end
end
@@ -268,7 +372,7 @@ RSpec.describe "bundle install with specific platforms" do
git = build_git "pg_array_parser", "1.0"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "pg_array_parser", :git => "#{lib_path("pg_array_parser-1.0")}"
G
@@ -284,17 +388,15 @@ RSpec.describe "bundle install with specific platforms" do
specs:
PLATFORMS
- java
- #{lockfile_platforms}
+ #{lockfile_platforms("java")}
DEPENDENCIES
pg_array_parser!
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
- bundle "config set --local cache_all true"
bundle "cache --all-platforms"
expect(err).to be_empty
@@ -304,12 +406,12 @@ RSpec.describe "bundle install with specific platforms" do
simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem_with_different_dependencies_per_platform
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "facter"
G
allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
- expect(the_bundle.locked_gems.platforms).to include(pl("x86_64-darwin-15"))
+ expect(the_bundle.locked_platforms).to include("universal-darwin")
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 include("CFPropertyList-1.0",
"facter-2.4.6-universal-darwin")
@@ -325,12 +427,12 @@ RSpec.describe "bundle install with specific platforms" do
simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem
install_gemfile(google_protobuf)
- bundle "lock --add-platform=#{x64_mingw32}"
+ bundle "lock --add-platform=x64-mingw-ucrt"
- expect(the_bundle.locked_gems.platforms).to include(x64_mingw32, pl("x86_64-darwin-15"))
+ expect(the_bundle.locked_platforms).to include("x64-mingw-ucrt", "universal-darwin")
expect(the_bundle.locked_gems.specs.map(&:full_name)).to include(*%w[
google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin
- google-protobuf-3.0.0.alpha.5.0.5.1-x64-mingw32
+ google-protobuf-3.0.0.alpha.5.0.5.1-x64-mingw-ucrt
])
end
end
@@ -339,9 +441,9 @@ RSpec.describe "bundle install with specific platforms" do
simulate_platform "x86_64-darwin-15" do
setup_multiplatform_gem
install_gemfile(google_protobuf)
- bundle "lock --add-platform=#{java}"
+ bundle "lock --add-platform=java"
- expect(the_bundle.locked_gems.platforms).to include(java, pl("x86_64-darwin-15"))
+ expect(the_bundle.locked_platforms).to include("java", "universal-darwin")
expect(the_bundle.locked_gems.specs.map(&:full_name)).to include(
"google-protobuf-3.0.0.alpha.5.0.5.1",
"google-protobuf-3.0.0.alpha.5.0.5.1-universal-darwin"
@@ -350,7 +452,7 @@ RSpec.describe "bundle install with specific platforms" do
end
end
- it "installs sorbet-static, which does not provide a pure ruby variant, just fine", :truffleruby do
+ it "installs sorbet-static, which does not provide a pure ruby variant, in absence of a lockfile, just fine", :truffleruby do
skip "does not apply to Windows" if Gem.win_platform?
build_repo2 do
@@ -358,14 +460,30 @@ RSpec.describe "bundle install with specific platforms" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
+
+ gem "sorbet-static", "0.5.6403"
+ G
+
+ bundle "install --verbose"
+ end
+
+ it "installs sorbet-static, which does not provide a pure ruby variant, in presence of a lockfile, just fine", :truffleruby do
+ skip "does not apply to Windows" if Gem.win_platform?
+
+ build_repo2 do
+ build_gem("sorbet-static", "0.5.6403") {|s| s.platform = Bundler.local_platform }
+ end
+
+ gemfile <<~G
+ source "https://gem.repo2"
gem "sorbet-static", "0.5.6403"
G
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
sorbet-static (0.5.6403-#{Bundler.local_platform})
@@ -376,7 +494,7 @@ RSpec.describe "bundle install with specific platforms" do
sorbet-static (= 0.5.6403)
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "install --verbose"
@@ -389,13 +507,13 @@ RSpec.describe "bundle install with specific platforms" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "sorbet-static", "0.5.6433"
G
error_message = <<~ERROR.strip
- Could not find gem 'sorbet-static (= 0.5.6433)' with platform 'arm64-darwin-21' in rubygems repository #{file_uri_for(gem_repo4)}/ or installed locally.
+ Could not find gem 'sorbet-static (= 0.5.6433)' with platform 'arm64-darwin-21' in rubygems repository https://gem.repo4/ or installed locally.
The source contains the following gems matching 'sorbet-static (= 0.5.6433)':
* sorbet-static-0.5.6433-universal-darwin-20
@@ -425,7 +543,7 @@ RSpec.describe "bundle install with specific platforms" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "sorbet", "0.5.6433"
G
@@ -434,7 +552,7 @@ RSpec.describe "bundle install with specific platforms" do
Could not find compatible versions
Because every version of sorbet depends on sorbet-static = 0.5.6433
- and sorbet-static = 0.5.6433 could not be found in rubygems repository #{file_uri_for(gem_repo4)}/ or installed locally for any resolution platforms (arm64-darwin-21),
+ and sorbet-static = 0.5.6433 could not be found in rubygems repository https://gem.repo4/ or installed locally for any resolution platforms (arm64-darwin-21),
sorbet cannot be used.
So, because Gemfile depends on sorbet = 0.5.6433,
version solving has failed.
@@ -459,13 +577,13 @@ RSpec.describe "bundle install with specific platforms" do
expect(err).to include(error_message).once
end
- it "does not generate a lockfile if RUBY platform is forced and some gem has no RUBY variant available" do
+ it "does not generate a lockfile if ruby platform is forced and some gem has no ruby variant available" do
build_repo4 do
build_gem("sorbet-static", "0.5.9889") {|s| s.platform = Gem::Platform.local }
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "sorbet-static", "0.5.9889"
G
@@ -473,22 +591,22 @@ RSpec.describe "bundle install with specific platforms" do
bundle "lock", raise_on_error: false, env: { "BUNDLE_FORCE_RUBY_PLATFORM" => "true" }
expect(err).to include <<~ERROR.rstrip
- Could not find gem 'sorbet-static (= 0.5.9889)' with platform 'ruby' in rubygems repository #{file_uri_for(gem_repo4)}/ or installed locally.
+ Could not find gem 'sorbet-static (= 0.5.9889)' with platform 'ruby' in rubygems repository https://gem.repo4/ or installed locally.
The source contains the following gems matching 'sorbet-static (= 0.5.9889)':
* sorbet-static-0.5.9889-#{Gem::Platform.local}
ERROR
end
- it "automatically fixes the lockfile if RUBY platform is locked and some gem has no RUBY variant available" do
+ it "automatically fixes the lockfile if ruby platform is locked and some gem has no ruby variant available" do
build_repo4 do
build_gem("sorbet-static-and-runtime", "0.5.10160") do |s|
- s.add_runtime_dependency "sorbet", "= 0.5.10160"
- s.add_runtime_dependency "sorbet-runtime", "= 0.5.10160"
+ s.add_dependency "sorbet", "= 0.5.10160"
+ s.add_dependency "sorbet-runtime", "= 0.5.10160"
end
build_gem("sorbet", "0.5.10160") do |s|
- s.add_runtime_dependency "sorbet-static", "= 0.5.10160"
+ s.add_dependency "sorbet-static", "= 0.5.10160"
end
build_gem("sorbet-runtime", "0.5.10160")
@@ -499,14 +617,14 @@ RSpec.describe "bundle install with specific platforms" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "sorbet-static-and-runtime"
G
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
sorbet (0.5.10160)
sorbet-static (= 0.5.10160)
@@ -523,12 +641,12 @@ RSpec.describe "bundle install with specific platforms" do
sorbet-static-and-runtime
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "update"
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo4, "sorbet", "0.5.10160"
c.checksum gem_repo4, "sorbet-runtime", "0.5.10160"
c.checksum gem_repo4, "sorbet-static", "0.5.10160", Gem::Platform.local
@@ -537,7 +655,7 @@ RSpec.describe "bundle install with specific platforms" do
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
sorbet (0.5.10160)
sorbet-static (= 0.5.10160)
@@ -554,11 +672,11 @@ RSpec.describe "bundle install with specific platforms" do
sorbet-static-and-runtime
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
- it "automatically fixes the lockfile if both RUBY platform and a more specific platform are locked, and some gem has no RUBY variant available" do
+ it "automatically fixes the lockfile if both ruby platform and a more specific platform are locked, and some gem has no ruby variant available" do
build_repo4 do
build_gem "nokogiri", "1.12.0"
build_gem "nokogiri", "1.12.0" do |s|
@@ -577,21 +695,21 @@ RSpec.describe "bundle install with specific platforms" do
simulate_platform "x86_64-darwin-22" do
install_gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "nokogiri"
gem "sorbet-static"
G
end
- checksums = checksums_section_when_existing do |c|
- c.no_checksum "nokogiri", "1.13.0", "x86_64-darwin"
- c.no_checksum "sorbet-static", "0.5.10601", "x86_64-darwin"
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "nokogiri", "1.13.0", "x86_64-darwin"
+ c.checksum gem_repo4, "sorbet-static", "0.5.10601", "x86_64-darwin"
end
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
nokogiri (1.12.0)
nokogiri (1.12.0-x86_64-darwin)
@@ -606,7 +724,7 @@ RSpec.describe "bundle install with specific platforms" do
sorbet-static
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
simulate_platform "x86_64-darwin-22" do
@@ -615,7 +733,7 @@ RSpec.describe "bundle install with specific platforms" do
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
nokogiri (1.13.0-x86_64-darwin)
sorbet-static (0.5.10601-x86_64-darwin)
@@ -628,19 +746,19 @@ RSpec.describe "bundle install with specific platforms" do
sorbet-static
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
- it "automatically fixes the lockfile if only RUBY platform is locked and some gem has no RUBY variant available" do
+ it "automatically fixes the lockfile if only ruby platform is locked and some gem has no ruby variant available" do
build_repo4 do
build_gem("sorbet-static-and-runtime", "0.5.10160") do |s|
- s.add_runtime_dependency "sorbet", "= 0.5.10160"
- s.add_runtime_dependency "sorbet-runtime", "= 0.5.10160"
+ s.add_dependency "sorbet", "= 0.5.10160"
+ s.add_dependency "sorbet-runtime", "= 0.5.10160"
end
build_gem("sorbet", "0.5.10160") do |s|
- s.add_runtime_dependency "sorbet-static", "= 0.5.10160"
+ s.add_dependency "sorbet-static", "= 0.5.10160"
end
build_gem("sorbet-runtime", "0.5.10160")
@@ -651,14 +769,14 @@ RSpec.describe "bundle install with specific platforms" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "sorbet-static-and-runtime"
G
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
sorbet (0.5.10160)
sorbet-static (= 0.5.10160)
@@ -675,12 +793,12 @@ RSpec.describe "bundle install with specific platforms" do
sorbet-static-and-runtime
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "update"
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo4, "sorbet", "0.5.10160"
c.checksum gem_repo4, "sorbet-runtime", "0.5.10160"
c.checksum gem_repo4, "sorbet-static", "0.5.10160", Gem::Platform.local
@@ -689,7 +807,7 @@ RSpec.describe "bundle install with specific platforms" do
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
sorbet (0.5.10160)
sorbet-static (= 0.5.10160)
@@ -706,10 +824,84 @@ RSpec.describe "bundle install with specific platforms" do
sorbet-static-and-runtime
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
+ it "automatically fixes the lockfile when adding a gem that introduces dependencies with no ruby platform variants transitively" do
+ simulate_platform "x86_64-linux" do
+ build_repo4 do
+ build_gem "nokogiri", "1.18.2"
+
+ build_gem "nokogiri", "1.18.2" do |s|
+ s.platform = "x86_64-linux"
+ end
+
+ build_gem("sorbet", "0.5.11835") do |s|
+ s.add_dependency "sorbet-static", "= 0.5.11835"
+ end
+
+ build_gem "sorbet-static", "0.5.11835" do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ gem "sorbet"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.18.2)
+ nokogiri (1.18.2-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "nokogiri", "1.18.2", "x86_64-linux"
+ c.checksum gem_repo4, "sorbet", "0.5.11835"
+ c.checksum gem_repo4, "sorbet-static", "0.5.11835", "x86_64-linux"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.18.2)
+ nokogiri (1.18.2-x86_64-linux)
+ sorbet (0.5.11835)
+ sorbet-static (= 0.5.11835)
+ sorbet-static (0.5.11835-x86_64-linux)
+
+ PLATFORMS
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+ sorbet
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
it "automatically fixes the lockfile if multiple platforms locked, but no valid versions of direct dependencies for all of them" do
simulate_platform "x86_64-linux" do
build_repo4 do
@@ -726,7 +918,7 @@ RSpec.describe "bundle install with specific platforms" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "nokogiri"
gem "sorbet-static"
@@ -734,7 +926,7 @@ RSpec.describe "bundle install with specific platforms" do
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
nokogiri (1.14.0-arm-linux)
nokogiri (1.14.0-x86_64-linux)
@@ -750,19 +942,19 @@ RSpec.describe "bundle install with specific platforms" do
sorbet-static
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "update"
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo4, "nokogiri", "1.14.0", "x86_64-linux"
c.checksum gem_repo4, "sorbet-static", "0.5.10696", "x86_64-linux"
end
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
nokogiri (1.14.0-x86_64-linux)
sorbet-static (0.5.10696-x86_64-linux)
@@ -775,7 +967,7 @@ RSpec.describe "bundle install with specific platforms" do
sorbet-static
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
@@ -794,12 +986,12 @@ RSpec.describe "bundle install with specific platforms" do
# Make sure sorbet-static-0.5.10549-universal-darwin-21 is installed
install_gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "sorbet-static", "= 0.5.10549"
G
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo4, "sorbet-static", "0.5.10549", "universal-darwin-20"
c.checksum gem_repo4, "sorbet-static", "0.5.10549", "universal-darwin-21"
end
@@ -807,7 +999,7 @@ RSpec.describe "bundle install with specific platforms" do
# Make sure the lockfile is missing sorbet-static-0.5.10549-universal-darwin-21
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
sorbet-static (0.5.10549-universal-darwin-20)
@@ -818,16 +1010,14 @@ RSpec.describe "bundle install with specific platforms" do
sorbet-static (= 0.5.10549)
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "install"
- checksums.no_checksum "sorbet-static", "0.5.10549", "universal-darwin-21"
-
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
sorbet-static (0.5.10549-universal-darwin-20)
sorbet-static (0.5.10549-universal-darwin-21)
@@ -839,7 +1029,64 @@ RSpec.describe "bundle install with specific platforms" do
sorbet-static (= 0.5.10549)
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ it "automatically fixes the lockfile if locked only to ruby, and some locked specs don't meet locked dependencies" do
+ simulate_platform "x86_64-linux" do
+ build_repo4 do
+ build_gem("ibandit", "0.7.0") do |s|
+ s.add_dependency "i18n", "~> 0.7.0"
+ end
+
+ build_gem("i18n", "0.7.0.beta1")
+ build_gem("i18n", "0.7.0")
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "ibandit", "~> 0.7.0"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ i18n (0.7.0.beta1)
+ ibandit (0.7.0)
+ i18n (~> 0.7.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ ibandit (~> 0.7.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock --update i18n"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ i18n (0.7.0)
+ ibandit (0.7.0)
+ i18n (~> 0.7.0)
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+ ibandit (~> 0.7.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
L
end
end
@@ -853,16 +1100,21 @@ RSpec.describe "bundle install with specific platforms" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "nokogiri"
gem "tzinfo", "~> 1.2", platform: :#{not_local_tag}
G
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "nokogiri", "1.13.8"
+ c.checksum gem_repo4, "nokogiri", "1.13.8", Gem::Platform.local
+ end
+
original_lockfile = <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
nokogiri (1.13.8)
nokogiri (1.13.8-#{Gem::Platform.local})
@@ -873,64 +1125,85 @@ RSpec.describe "bundle install with specific platforms" do
DEPENDENCIES
nokogiri
tzinfo (~> 1.2)
-
- CHECKSUMS
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
lockfile original_lockfile
bundle "lock --update"
- checksums = checksums_section_when_existing do |c|
- c.no_checksum "nokogiri", "1.13.8"
- c.no_checksum "nokogiri", "1.13.8", Gem::Platform.local
+ expect(lockfile).to eq(original_lockfile)
+ end
+
+ it "does not remove ruby if gems for other platforms, and not present in the lockfile, exist in the Gemfile, and the lockfile only has ruby" do
+ build_repo4 do
+ build_gem "nokogiri", "1.13.8"
+ build_gem "nokogiri", "1.13.8" do |s|
+ s.platform = "arm64-darwin"
+ end
end
- updated_lockfile = <<~L
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+
+ gem "tzinfo", "~> 1.2", platforms: %i[windows jruby]
+ G
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "nokogiri", "1.13.8"
+ end
+
+ original_lockfile = <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
nokogiri (1.13.8)
- nokogiri (1.13.8-#{Gem::Platform.local})
PLATFORMS
- #{lockfile_platforms("ruby")}
+ ruby
DEPENDENCIES
nokogiri
tzinfo (~> 1.2)
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
- expect(lockfile).to eq(updated_lockfile)
+ lockfile original_lockfile
+
+ simulate_platform "arm64-darwin-23" do
+ bundle "lock --update"
+ end
+
+ expect(lockfile).to eq(original_lockfile)
end
it "does not remove ruby when adding a new gem to the Gemfile" do
build_repo4 do
build_gem "concurrent-ruby", "1.2.2"
- build_gem "rack", "3.0.7"
+ build_gem "myrack", "3.0.7"
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "concurrent-ruby"
- gem "rack"
+ gem "myrack"
G
- checksums = checksums_section_when_existing do |c|
- c.no_checksum "concurrent-ruby", "1.2.2"
- c.no_checksum "rack", "3.0.7"
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "concurrent-ruby", "1.2.2"
+ c.checksum gem_repo4, "myrack", "3.0.7"
end
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
concurrent-ruby (1.2.2)
@@ -941,37 +1214,35 @@ RSpec.describe "bundle install with specific platforms" do
concurrent-ruby
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "lock"
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
concurrent-ruby (1.2.2)
- rack (3.0.7)
+ myrack (3.0.7)
PLATFORMS
- #{lockfile_platforms("ruby", generic_local_platform, defaults: [])}
+ #{lockfile_platforms(generic_default_locked_platform || local_platform, defaults: ["ruby"])}
DEPENDENCIES
concurrent-ruby
- rack
+ myrack
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
it "can fallback to a source gem when platform gems are incompatible with current ruby version" do
setup_multiplatform_gem_with_source_gem
- source = file_uri_for(gem_repo2)
-
gemfile <<~G
- source "#{source}"
+ source "https://gem.repo2"
gem "my-precompiled-gem"
G
@@ -981,7 +1252,7 @@ RSpec.describe "bundle install with specific platforms" do
# - A source gem with compatible ruby version
lockfile <<-L
GEM
- remote: #{source}/
+ remote: https://gem.repo2/
specs:
my-precompiled-gem (3.0.0)
my-precompiled-gem (3.0.0-#{Bundler.local_platform})
@@ -994,13 +1265,13 @@ RSpec.describe "bundle install with specific platforms" do
my-precompiled-gem
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle :install
end
- it "automatically fixes the lockfile if the specific platform is locked and we move to a newer ruby version for which a native package is not available" do
+ it "automatically adds the ruby variant to the lockfile if the specific platform is locked and we move to a newer ruby version for which a native package is not available" do
#
# Given an existing application using native gems (e.g., nokogiri)
# And a lockfile generated with a stable ruby version
@@ -1017,18 +1288,18 @@ RSpec.describe "bundle install with specific platforms" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "nokogiri", "1.14.0"
G
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo4, "nokogiri", "1.14.0", "x86_64-linux"
end
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
nokogiri (1.14.0-x86_64-linux)
@@ -1039,20 +1310,22 @@ RSpec.describe "bundle install with specific platforms" do
nokogiri (= 1.14.0)
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle :install
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo4, "nokogiri", "1.14.0"
+ c.checksum gem_repo4, "nokogiri", "1.14.0", "x86_64-linux"
end
expect(lockfile).to eq(<<~L)
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
nokogiri (1.14.0)
+ nokogiri (1.14.0-x86_64-linux)
PLATFORMS
x86_64-linux
@@ -1061,7 +1334,61 @@ RSpec.describe "bundle install with specific platforms" do
nokogiri (= 1.14.0)
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
+ L
+ end
+ end
+
+ it "automatically fixes the lockfile when only ruby platform locked, and adding a dependency with subdependencies not valid for ruby" do
+ simulate_platform "x86_64-linux" do
+ build_repo4 do
+ build_gem("sorbet", "0.5.10160") do |s|
+ s.add_dependency "sorbet-static", "= 0.5.10160"
+ end
+
+ build_gem("sorbet-static", "0.5.10160") do |s|
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "sorbet"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+
+ PLATFORMS
+ ruby
+
+ DEPENDENCIES
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "lock"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ sorbet (0.5.10160)
+ sorbet-static (= 0.5.10160)
+ sorbet-static (0.5.10160-x86_64-linux)
+
+ PLATFORMS
+ x86_64-linux
+
+ DEPENDENCIES
+ sorbet
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
L
end
end
@@ -1077,7 +1404,7 @@ RSpec.describe "bundle install with specific platforms" do
s.platform = "arm-linux"
end
build_gem "nokogiri", "1.14.0" do |s|
- s.platform = "x64-mingw32"
+ s.platform = "x64-mingw-ucrt"
end
build_gem "nokogiri", "1.14.0" do |s|
s.platform = "java"
@@ -1092,23 +1419,23 @@ RSpec.describe "bundle install with specific platforms" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "nokogiri"
G
bundle "lock"
- checksums = checksums_section_when_existing do |c|
- c.no_checksum "nokogiri", "1.14.0"
- c.no_checksum "nokogiri", "1.14.0", "arm-linux"
- c.no_checksum "nokogiri", "1.14.0", "x86_64-linux"
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "nokogiri", "1.14.0"
+ c.checksum gem_repo4, "nokogiri", "1.14.0", "arm-linux"
+ c.checksum gem_repo4, "nokogiri", "1.14.0", "x86_64-linux"
end
# locks all compatible platforms, excluding Java and Windows
expect(lockfile).to eq(<<~L)
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
nokogiri (1.14.0)
nokogiri (1.14.0-arm-linux)
@@ -1123,11 +1450,11 @@ RSpec.describe "bundle install with specific platforms" do
nokogiri
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "nokogiri"
gem "sorbet-static"
@@ -1138,13 +1465,13 @@ RSpec.describe "bundle install with specific platforms" do
bundle "lock"
checksums.delete "nokogiri", "arm-linux"
- checksums.no_checksum "sorbet-static", "0.5.10696", "universal-darwin-22"
- checksums.no_checksum "sorbet-static", "0.5.10696", "x86_64-linux"
+ checksums.checksum gem_repo4, "sorbet-static", "0.5.10696", "universal-darwin-22"
+ checksums.checksum gem_repo4, "sorbet-static", "0.5.10696", "x86_64-linux"
# locks only platforms compatible with all gems in the bundle
expect(lockfile).to eq(<<~L)
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
nokogiri (1.14.0)
nokogiri (1.14.0-x86_64-linux)
@@ -1160,12 +1487,12 @@ RSpec.describe "bundle install with specific platforms" do
sorbet-static
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
- it "does not fail when a platform variant is incompatible with the current ruby and another equivalent platform specific variant is part of the resolution", rubygems: ">= 3.3.21" do
+ it "does not fail when a platform variant is incompatible with the current ruby and another equivalent platform specific variant is part of the resolution" do
build_repo4 do
build_gem "nokogiri", "1.15.5"
@@ -1182,25 +1509,25 @@ RSpec.describe "bundle install with specific platforms" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "nokogiri"
gem "sass-embedded"
G
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo4, "nokogiri", "1.15.5"
- c.no_checksum "sass-embedded", "1.69.5"
+ c.checksum gem_repo4, "sass-embedded", "1.69.5"
c.checksum gem_repo4, "sass-embedded", "1.69.5", "x86_64-linux-gnu"
end
simulate_platform "x86_64-linux" do
- bundle "install --verbose", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ bundle "install --verbose"
# locks all compatible platforms, excluding Java and Windows
expect(lockfile).to eq(<<~L)
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
nokogiri (1.15.5)
sass-embedded (1.69.5)
@@ -1215,7 +1542,7 @@ RSpec.describe "bundle install with specific platforms" do
sass-embedded
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
@@ -1232,21 +1559,21 @@ RSpec.describe "bundle install with specific platforms" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "nokogiri"
G
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo4, "nokogiri", "1.15.5", "x86_64-linux"
end
simulate_platform "x86_64-linux" do
- bundle "install --verbose", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ bundle "install --verbose"
expect(lockfile).to eq(<<~L)
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
nokogiri (1.15.5-x86_64-linux)
@@ -1257,7 +1584,7 @@ RSpec.describe "bundle install with specific platforms" do
nokogiri
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
@@ -1276,17 +1603,22 @@ RSpec.describe "bundle install with specific platforms" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "rcee_precompiled", "0.5.0"
G
simulate_platform host_platform do
- bundle "lock", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ bundle "lock"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "rcee_precompiled", "0.5.0", "x86_64-linux"
+ c.checksum gem_repo4, "rcee_precompiled", "0.5.0", "x86_64-linux-musl"
+ end
expect(lockfile).to eq(<<~L)
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
rcee_precompiled (0.5.0-x86_64-linux)
rcee_precompiled (0.5.0-x86_64-linux-musl)
@@ -1297,16 +1629,16 @@ RSpec.describe "bundle install with specific platforms" do
DEPENDENCIES
rcee_precompiled (= 0.5.0)
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
end
end
- it "adds current musl platform, when there are also gnu variants", rubygems: ">= 3.3.21" do
+ it "adds current musl platform, when there are also gnu variants" do
build_repo4 do
build_gem "rcee_precompiled", "0.5.0" do |s|
s.platform = "x86_64-linux-gnu"
@@ -1318,17 +1650,22 @@ RSpec.describe "bundle install with specific platforms" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "rcee_precompiled", "0.5.0"
G
simulate_platform "x86_64-linux-musl" do
- bundle "lock", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ bundle "lock"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "rcee_precompiled", "0.5.0", "x86_64-linux-gnu"
+ c.checksum gem_repo4, "rcee_precompiled", "0.5.0", "x86_64-linux-musl"
+ end
expect(lockfile).to eq(<<~L)
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
rcee_precompiled (0.5.0-x86_64-linux-gnu)
rcee_precompiled (0.5.0-x86_64-linux-musl)
@@ -1339,9 +1676,9 @@ RSpec.describe "bundle install with specific platforms" do
DEPENDENCIES
rcee_precompiled (= 0.5.0)
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
@@ -1354,17 +1691,21 @@ RSpec.describe "bundle install with specific platforms" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "rcee_precompiled", "0.5.0"
G
simulate_platform "x86_64-darwin-15" do
- bundle "lock", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ bundle "lock"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "rcee_precompiled", "0.5.0", "universal-darwin"
+ end
expect(lockfile).to eq(<<~L)
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
rcee_precompiled (0.5.0-universal-darwin)
@@ -1373,24 +1714,196 @@ RSpec.describe "bundle install with specific platforms" do
DEPENDENCIES
rcee_precompiled (= 0.5.0)
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
+ it "does not re-resolve when a specific platform, but less specific than the current platform, is locked" do
+ build_repo4 do
+ build_gem "nokogiri"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.0)
+
+ PLATFORMS
+ arm64-darwin
+
+ DEPENDENCIES
+ nokogiri!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ simulate_platform "arm64-darwin-23" do
+ bundle "install --verbose"
+
+ expect(out).to include("Found no changes, using resolution from the lockfile")
+ end
+ end
+
+ it "does not remove generic platform gems locked for a specific platform from lockfile when unlocking an unrelated gem" do
+ build_repo4 do
+ build_gem "ffi"
+
+ build_gem "ffi" do |s|
+ s.platform = "x86_64-linux"
+ end
+
+ build_gem "nokogiri"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "ffi"
+ gem "nokogiri"
+ G
+
+ original_lockfile = <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ ffi (1.0)
+ nokogiri (1.0)
+
+ PLATFORMS
+ x86_64-linux
+
+ DEPENDENCIES
+ ffi
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ lockfile original_lockfile
+
+ simulate_platform "x86_64-linux" do
+ bundle "lock --update nokogiri"
+
+ expect(lockfile).to eq(original_lockfile)
+ end
+ end
+
+ it "does not remove generic platform gems locked for a specific platform from lockfile when unlocking an unrelated gem, and variants for other platform also locked" do
+ build_repo4 do
+ build_gem "ffi"
+
+ build_gem "ffi" do |s|
+ s.platform = "x86_64-linux"
+ end
+
+ build_gem "ffi" do |s|
+ s.platform = "java"
+ end
+
+ build_gem "nokogiri"
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "ffi"
+ gem "nokogiri"
+ G
+
+ original_lockfile = <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ ffi (1.0)
+ ffi (1.0-java)
+ nokogiri (1.0)
+
+ PLATFORMS
+ java
+ x86_64-linux
+
+ DEPENDENCIES
+ ffi
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ lockfile original_lockfile
+
+ simulate_platform "x86_64-linux" do
+ bundle "lock --update nokogiri"
+
+ expect(lockfile).to eq(original_lockfile)
+ end
+ end
+
+ it "does not remove platform specific gems from lockfile when using a ruby version that does not match their ruby requirements, since they may be useful in other rubies" do
+ build_repo4 do
+ build_gem("google-protobuf", "3.25.5")
+ build_gem("google-protobuf", "3.25.5") do |s|
+ s.required_ruby_version = "< #{current_ruby_minor}.dev"
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "google-protobuf", "~> 3.0"
+ G
+
+ original_lockfile = <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ google-protobuf (3.25.5)
+ google-protobuf (3.25.5-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ google-protobuf (~> 3.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ lockfile original_lockfile
+
+ simulate_platform "x86_64-linux" do
+ bundle "lock --update"
+ end
+
+ expect(lockfile).to eq(original_lockfile)
+ 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 = "x64-mingw-ucrt" }
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") {|s| s.platform = "x64-mingw-ucrt" }
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" }
@@ -1405,7 +1918,7 @@ RSpec.describe "bundle install with specific platforms" do
build_gem("facter", "2.4.6")
build_gem("facter", "2.4.6") do |s|
s.platform = "universal-darwin"
- s.add_runtime_dependency "CFPropertyList"
+ s.add_dependency "CFPropertyList"
end
build_gem("CFPropertyList")
end
diff --git a/spec/bundler/install/gemfile_spec.rb b/spec/bundler/install/gemfile_spec.rb
index 158645d3eb..87326f67af 100644
--- a/spec/bundler/install/gemfile_spec.rb
+++ b/spec/bundler/install/gemfile_spec.rb
@@ -4,7 +4,7 @@ RSpec.describe "bundle install" do
context "with duplicated gems" do
it "will display a warning" do
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'rails', '~> 4.0.0'
gem 'rails', '~> 4.0.0'
@@ -16,8 +16,8 @@ RSpec.describe "bundle install" do
context "with --gemfile" do
it "finds the gemfile" do
gemfile bundled_app("NotGemfile"), <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
bundle :install, gemfile: bundled_app("NotGemfile")
@@ -25,15 +25,44 @@ RSpec.describe "bundle install" do
# Specify BUNDLE_GEMFILE for `the_bundle`
# to retrieve the proper Gemfile
ENV["BUNDLE_GEMFILE"] = "NotGemfile"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ it "respects lockfile and BUNDLE_LOCKFILE" do
+ gemfile bundled_app("NotGemfile"), <<-G
+ lockfile "ReallyNotGemfile.lock"
+ source "https://gem.repo1"
+ gem 'myrack'
+ G
+
+ bundle :install, gemfile: bundled_app("NotGemfile")
+
+ ENV["BUNDLE_GEMFILE"] = "NotGemfile"
+ ENV["BUNDLE_LOCKFILE"] = "ReallyNotGemfile.lock"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ it "respects BUNDLE_LOCKFILE during bundle install" do
+ ENV["BUNDLE_LOCKFILE"] = "ReallyNotGemfile.lock"
+
+ gemfile bundled_app("NotGemfile"), <<-G
+ source "https://gem.repo1"
+ gem 'myrack'
+ G
+
+ bundle :install, gemfile: bundled_app("NotGemfile")
+ expect(bundled_app("ReallyNotGemfile.lock")).to exist
+
+ ENV["BUNDLE_GEMFILE"] = "NotGemfile"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
context "with gemfile set via config" do
before do
gemfile bundled_app("NotGemfile"), <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
bundle "config set --local gemfile #{bundled_app("NotGemfile")}"
@@ -42,34 +71,79 @@ RSpec.describe "bundle install" do
bundle "install"
bundle "list"
- expect(out).to include("rack (1.0.0)")
+ expect(out).to include("myrack (1.0.0)")
end
it "uses the gemfile while in a subdirectory" do
bundled_app("subdir").mkpath
bundle "install", dir: bundled_app("subdir")
bundle "list", dir: bundled_app("subdir")
- expect(out).to include("rack (1.0.0)")
+ expect(out).to include("myrack (1.0.0)")
end
end
- context "with deprecated features" do
- it "reports that lib is an invalid option" do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ it "reports that lib is an invalid option" do
+ gemfile <<-G
+ source "https://gem.repo1"
- gem "rack", :lib => "rack"
- G
+ gem "myrack", :lib => "myrack"
+ G
+
+ bundle :install, raise_on_error: false
+ expect(err).to match(/You passed :lib as an option for gem 'myrack', but it is invalid/)
+ end
+
+ it "reports that type is an invalid option" do
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ gem "myrack", :type => "development"
+ G
+
+ bundle :install, raise_on_error: false
+ expect(err).to match(/You passed :type as an option for gem 'myrack', but it is invalid/)
+ end
+
+ it "reports that gemfile is an invalid option" do
+ gemfile <<-G
+ source "https://gem.repo1"
+
+ gem "myrack", :gemfile => "foo"
+ G
+
+ bundle :install, raise_on_error: false
+ expect(err).to match(/You passed :gemfile as an option for gem 'myrack', but it is invalid/)
+ end
+
+ context "when an internal error happens" do
+ let(:bundler_bug) do
+ create_file("bundler_bug.rb", <<~RUBY)
+ require "bundler"
+
+ module Bundler
+ class Dsl
+ def source(source, *args, &blk)
+ nil.name
+ end
+ end
+ end
+ RUBY
+
+ bundled_app("bundler_bug.rb").to_s
+ end
+
+ it "shows culprit file and line" do
+ skip "ruby-core test setup has always \"lib\" in $LOAD_PATH so `require \"bundler\"` always activates the local version rather than using RubyGems gem activation stuff, causing conflicts" if ruby_core?
- bundle :install, raise_on_error: false
- expect(err).to match(/You passed :lib as an option for gem 'rack', but it is invalid/)
+ install_gemfile "source 'https://gem.repo1'", requires: [bundler_bug], artifice: nil, raise_on_error: false
+ expect(err).to include("bundler_bug.rb:6")
end
end
context "with engine specified in symbol", :jruby_only do
it "does not raise any error parsing Gemfile" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
ruby "#{RUBY_VERSION}", :engine => :jruby, :engine_version => "#{RUBY_ENGINE_VERSION}"
G
@@ -78,19 +152,19 @@ RSpec.describe "bundle install" do
it "installation succeeds" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
ruby "#{RUBY_VERSION}", :engine => :jruby, :engine_version => "#{RUBY_ENGINE_VERSION}"
- gem "rack"
+ gem "myrack"
G
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 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)}"
+ source "https://gem.repo1"
str = "Il était une fois ..."
puts "The source encoding is: " + str.encoding.name
@@ -105,7 +179,7 @@ RSpec.describe "bundle install" do
# NOTE: This works thanks to #eval interpreting the magic encoding comment
install_gemfile <<-G
# encoding: iso-8859-1
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
str = "Il #{"\xE9".dup.force_encoding("binary")}tait une fois ..."
puts "The source encoding is: " + str.encoding.name
diff --git a/spec/bundler/install/gems/compact_index_spec.rb b/spec/bundler/install/gems/compact_index_spec.rb
index 50add8743b..bb4d4011f5 100644
--- a/spec/bundler/install/gems/compact_index_spec.rb
+++ b/spec/bundler/install/gems/compact_index_spec.rb
@@ -7,12 +7,27 @@ RSpec.describe "compact index api" do
it "should use the API" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
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"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ it "has a debug mode" do
+ gemfile <<-G
+ source "#{source_uri}"
+ gem "myrack"
+ G
+
+ bundle :install, artifice: "compact_index", env: { "DEBUG_COMPACT_INDEX" => "true" }
+ expect(out).to include("Fetching gem metadata from #{source_uri}")
+ expect(err).to include("[Bundler::CompactIndexClient] available?")
+ expect(err).to include("[Bundler::CompactIndexClient] fetching versions")
+ expect(err).to include("[Bundler::CompactIndexClient] info(myrack)")
+ expect(err).to include("[Bundler::CompactIndexClient] fetching info/myrack")
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "should URI encode gem names" do
@@ -45,22 +60,22 @@ RSpec.describe "compact index api" do
it "should handle case sensitivity conflicts" do
build_repo4(build_compact_index: false) do
- build_gem "rack", "1.0" do |s|
- s.add_runtime_dependency("Rack", "0.1")
+ build_gem "myrack", "1.0" do |s|
+ s.add_dependency("Myrack", "0.1")
end
- build_gem "Rack", "0.1"
+ build_gem "Myrack", "0.1"
end
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"
+ gem "myrack", "1.0"
+ gem "Myrack", "0.1"
G
# 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)"
- expect(out).to eq("rack-1.0\nRack-0.1")
+ run "Bundler.require; puts Gem.loaded_specs.values_at('myrack', 'Myrack').map(&:full_name)"
+ expect(out).to eq("myrack-1.0\nMyrack-0.1")
end
it "should handle multiple gem dependencies on the same gem" do
@@ -76,15 +91,14 @@ RSpec.describe "compact index api" do
it "should use the endpoint when using deployment mode" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
bundle :install, 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"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "handles git dependencies that are in rubygems" do
@@ -95,7 +109,7 @@ RSpec.describe "compact index api" do
gemfile <<-G
source "#{source_uri}"
- git "#{file_uri_for(lib_path("foo-1.0"))}" do
+ git "#{lib_path("foo-1.0")}" do
gem 'foo'
end
G
@@ -113,7 +127,7 @@ RSpec.describe "compact index api" do
gemfile <<-G
source "#{source_uri}"
- gem 'foo', :git => "#{file_uri_for(lib_path("foo-1.0"))}"
+ gem 'foo', :git => "#{lib_path("foo-1.0")}"
G
bundle :install, artifice: "compact_index"
@@ -128,7 +142,7 @@ RSpec.describe "compact index api" do
build_git "foo"
gemfile <<-G
source "#{source_uri}"
- gem 'foo', :git => "#{file_uri_for(lib_path("foo-1.0"))}"
+ gem 'foo', :git => "#{lib_path("foo-1.0")}"
G
bundle "install", artifice: "compact_index"
@@ -141,35 +155,34 @@ RSpec.describe "compact index api" do
it "falls back when the API URL returns 403 Forbidden" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
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"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "falls back when the versions endpoint has a checksum mismatch" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
bundle :install, verbose: true, artifice: "compact_index_checksum_mismatch"
expect(out).to include("Fetching gem metadata from #{source_uri}")
expect(out).to include("The checksum of /versions does not match the checksum provided by the server!")
- expect(out).to include('Calculated checksums {"sha-256"=>"8KfZiM/fszVkqhP/m5s9lvE6M9xKu4I1bU4Izddp5Ms="} did not match expected {"sha-256"=>"ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0="}')
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(out).to include("Calculated checksums #{{ "sha-256" => "8KfZiM/fszVkqhP/m5s9lvE6M9xKu4I1bU4Izddp5Ms=" }.inspect} did not match expected #{{ "sha-256" => "ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0=" }.inspect}")
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "shows proper path when permission errors happen", :permissions do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
- versions = Pathname.new(Bundler.rubygems.user_home).join(
- ".bundle", "cache", "compact_index",
+ versions = compact_index_cache_path.join(
"localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "versions"
)
versions.dirname.mkpath
@@ -188,28 +201,28 @@ RSpec.describe "compact index api" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
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"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "handles host redirects" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
bundle :install, artifice: "compact_index_host_redirect"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "handles host redirects without Gem::Net::HTTP::Persistent" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
FileUtils.mkdir_p lib_path
@@ -227,13 +240,13 @@ RSpec.describe "compact index api" do
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"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "times out when Bundler::Fetcher redirects too much" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
bundle :install, artifice: "compact_index_redirects", raise_on_error: false
@@ -244,23 +257,23 @@ RSpec.describe "compact index api" do
it "should use the modern index for install" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
bundle "install --full-index", artifice: "compact_index"
expect(out).to include("Fetching source index from #{source_uri}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "should use the modern index for update" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
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"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
@@ -288,45 +301,27 @@ RSpec.describe "compact index api" do
end
end
- system_gems %w[rack-1.0.0 thin-1.0 net_a-1.0], gem_repo: gem_repo2
+ system_gems %w[myrack-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"] = <<~EOS.strip
#{source_uri}/versions
- #{source_uri}/info/rack
+ #{source_uri}/info/myrack
EOS
install_gemfile <<-G, artifice: "compact_index", verbose: true, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
- expect(last_command.stdboth).not_to include "Double checking"
+ expect(stdboth).not_to include "Double checking"
end
- it "fetches again when more dependencies are found in subsequent sources", bundler: "< 3" do
+ it "fetches again when more dependencies are found in subsequent sources" do
build_repo2 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
end
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
- end
-
- gemfile <<-G
- source "#{source_uri}"
- source "#{source_uri}/extra"
- gem "back_deps"
- G
-
- bundle :install, artifice: "compact_index_extra"
- expect(the_bundle).to include_gems "back_deps 1.0", "foo 1.0"
- end
-
- it "fetches again when more dependencies are found in subsequent sources with source blocks" do
- build_repo2 do
- build_gem "back_deps" do |s|
- s.add_dependency "foo"
- end
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
+ FileUtils.rm_r Dir[gem_repo2("gems/foo-*.gem")]
end
install_gemfile <<-G, artifice: "compact_index_extra", verbose: true
@@ -342,31 +337,33 @@ RSpec.describe "compact index api" do
it "fetches gem versions even when those gems are already installed" do
gemfile <<-G
source "#{source_uri}"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
G
bundle :install, artifice: "compact_index_extra_api"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
build_repo4 do
- build_gem "rack", "1.2" do |s|
- s.executables = "rackup"
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
end
end
gemfile <<-G
source "#{source_uri}" do; end
source "#{source_uri}/extra"
- gem "rack", "1.2"
+ gem "myrack", "1.2"
G
bundle :install, artifice: "compact_index_extra_api"
- expect(the_bundle).to include_gems "rack 1.2"
+ expect(the_bundle).to include_gems "myrack 1.2"
end
- it "considers all possible versions of dependencies from all api gem sources", 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.
+ it "resolves indirect dependencies to the most scoped source that includes them" 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 tries to
+ # use the version in the most scoped source, even if not compatible, and
+ # gives a resolution error
build_repo4 do
build_gem "activesupport", "1.2.0"
build_gem "somegem", "1.0.0" do |s|
@@ -376,14 +373,14 @@ RSpec.describe "compact index api" do
gemfile <<-G
source "#{source_uri}"
- source "#{source_uri}/extra"
- gem 'somegem', '1.0.0'
+ 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", raise_on_error: false
- expect(the_bundle).to include_gems "somegem 1.0.0"
- expect(the_bundle).to include_gems "activesupport 1.2.3"
+ expect(err).to include("Could not find compatible versions")
end
it "prints API output properly with back deps" do
@@ -391,7 +388,7 @@ RSpec.describe "compact index api" do
build_gem "back_deps" do |s|
s.add_dependency "foo"
end
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
+ FileUtils.rm_r Dir[gem_repo2("gems/foo-*.gem")]
end
gemfile <<-G
@@ -414,7 +411,7 @@ RSpec.describe "compact index api" do
end
build_gem "missing"
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
+ FileUtils.rm_r Dir[gem_repo2("gems/foo-*.gem")]
end
install_gemfile <<-G, artifice: "compact_index_extra_missing"
@@ -434,7 +431,7 @@ RSpec.describe "compact index api" do
end
build_gem "missing"
- FileUtils.rm_rf Dir[gem_repo4("gems/foo-*.gem")]
+ FileUtils.rm_r Dir[gem_repo4("gems/foo-*.gem")]
end
install_gemfile <<-G, artifice: "compact_index_extra_api_missing"
@@ -458,32 +455,12 @@ RSpec.describe "compact index api" do
expect(the_bundle).to include_gems "foo 1.0"
end
- 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"
- end
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
- end
-
- gemfile <<-G
- source "#{source_uri}"
- source "#{source_uri}/extra"
- gem "back_deps"
- G
-
- 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 mode with blocks" do
+ it "fetches again when more dependencies are found in subsequent sources using deployment mode" do
build_repo2 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
end
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
+ FileUtils.rm_r Dir[gem_repo2("gems/foo-*.gem")]
end
gemfile <<-G
@@ -516,59 +493,25 @@ RSpec.describe "compact index api" do
expect(out).to include("Fetching gem metadata from #{source_uri}")
end
- it "installs the binstubs", bundler: "< 3" do
- gemfile <<-G
- source "#{source_uri}"
- gem "rack"
- G
-
- bundle "install --binstubs", artifice: "compact_index"
-
- gembin "rackup"
- expect(out).to eq("1.0.0")
- end
-
- it "installs the bins when using --path and uses autoclean", bundler: "< 3" do
- gemfile <<-G
- source "#{source_uri}"
- gem "rack"
- G
-
- bundle "install --path vendor/bundle", artifice: "compact_index"
-
- expect(vendored_gems("bin/rackup")).to exist
- end
-
- it "installs the bins when using --path and uses bundle clean", bundler: "< 3" do
- gemfile <<-G
- source "#{source_uri}"
- gem "rack"
- G
-
- bundle "install --path vendor/bundle --no-clean", artifice: "compact_index"
-
- expect(vendored_gems("bin/rackup")).to exist
- end
-
it "prints post_install_messages" do
gemfile <<-G
source "#{source_uri}"
- gem 'rack-obama'
+ gem 'myrack-obama'
G
bundle :install, artifice: "compact_index"
- expect(out).to include("Post-install message from rack:")
+ expect(out).to include("Post-install message from myrack:")
end
it "should display the post install message for a dependency" do
gemfile <<-G
source "#{source_uri}"
- gem 'rack_middleware'
+ gem 'myrack_middleware'
G
bundle :install, artifice: "compact_index"
- expect(out).to include("Post-install message from rack:")
- expect(out).to include("Rack's post install message")
+ expect(out).to include("Post-install message from myrack:")
+ expect(out).to include("Myrack's post install message")
end
context "when using basic authentication" do
@@ -585,53 +528,40 @@ RSpec.describe "compact index api" do
it "passes basic authentication details and strips out creds" do
gemfile <<-G
source "#{basic_auth_source_uri}"
- gem "rack"
+ gem "myrack"
G
bundle :install, artifice: "compact_index_basic_authentication"
expect(out).not_to include("#{user}:#{password}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 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"
+ gem "myrack"
G
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 warning about ambiguous sources", bundler: "< 3" do
- gemfile <<-G
- source "#{basic_auth_source_uri}"
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- G
-
- 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"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "does not pass the user / password to different hosts on redirect" do
gemfile <<-G
source "#{basic_auth_source_uri}"
- gem "rack"
+ gem "myrack"
G
bundle :install, artifice: "compact_index_creds_diff_host"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
describe "with authentication details in bundle config" do
before do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
end
@@ -641,7 +571,7 @@ RSpec.describe "compact index api" do
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"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "reads authentication details by full url from bundle config" do
@@ -651,26 +581,26 @@ RSpec.describe "compact index api" do
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"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "should use the API" do
bundle "config set #{source_hostname} #{user}:#{password}"
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"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "prefers auth supplied in the source uri" do
gemfile <<-G
source "#{basic_auth_source_uri}"
- gem "rack"
+ gem "myrack"
G
bundle "config set #{source_hostname} otheruser:wrong"
bundle :install, artifice: "compact_index_strict_basic_authentication"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "shows instructions if auth is not provided for the source" do
@@ -701,11 +631,11 @@ RSpec.describe "compact index api" do
it "passes basic authentication details" do
gemfile <<-G
source "#{basic_auth_source_uri}"
- gem "rack"
+ gem "myrack"
G
bundle :install, artifice: "compact_index_basic_authentication"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
end
@@ -723,14 +653,14 @@ RSpec.describe "compact index api" do
end
end
- it "explains what to do to get it" do
+ it "explains what to do to get it, and includes original error" do
gemfile <<-G
source "#{source_uri.gsub(/http/, "https")}"
- gem "rack"
+ gem "myrack"
G
- bundle :install, env: { "RUBYOPT" => opt_add("-I#{bundled_app("broken_ssl")}", ENV["RUBYOPT"]) }, raise_on_error: false
- expect(err).to include("OpenSSL")
+ bundle :install, env: { "RUBYOPT" => "-I#{bundled_app("broken_ssl")}" }, raise_on_error: false, artifice: nil
+ expect(err).to include("recompile Ruby").and include("cannot load such file")
end
end
@@ -746,7 +676,7 @@ RSpec.describe "compact index api" do
end
source "#{source_uri.gsub(/http/, "https")}"
- gem "rack"
+ gem "myrack"
G
bundle :install, raise_on_error: false
@@ -763,26 +693,25 @@ RSpec.describe "compact index api" do
begin
gemfile <<-G
source "#{source_uri}"
- gem 'rack'
+ gem 'myrack'
G
bundle :install, artifice: "compact_index_forbidden"
ensure
- home(".gemrc").rmtree
+ FileUtils.rm_rf home(".gemrc")
end
end
end
it "performs update with etag not-modified" do
- versions_etag = Pathname.new(Bundler.rubygems.user_home).join(
- ".bundle", "cache", "compact_index",
+ versions_etag = compact_index_cache_path.join(
"localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "versions.etag"
)
expect(versions_etag.file?).to eq(false)
gemfile <<-G
source "#{source_uri}"
- gem 'rack', '0.9.1'
+ gem 'myrack', '0.9.1'
G
# Initial install creates the cached versions file and etag file
@@ -794,20 +723,20 @@ RSpec.describe "compact index api" do
# Update the Gemfile so we can check subsequent install was successful
gemfile <<-G
source "#{source_uri}"
- gem 'rack', '1.0.0'
+ gem 'myrack', '1.0.0'
G
# Second install should match etag
bundle :install, artifice: "compact_index_etag_match"
expect(versions_etag.binread).to eq(previous_content)
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "performs full update when range is ignored" do
gemfile <<-G
source "#{source_uri}"
- gem 'rack', '0.9.1'
+ gem 'myrack', '0.9.1'
G
# Initial install creates the cached versions file and etag file
@@ -815,11 +744,10 @@ RSpec.describe "compact index api" do
gemfile <<-G
source "#{source_uri}"
- gem 'rack', '1.0.0'
+ gem 'myrack', '1.0.0'
G
- versions = Pathname.new(Bundler.rubygems.user_home).join(
- ".bundle", "cache", "compact_index",
+ versions = compact_index_cache_path.join(
"localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "versions"
)
# Modify the cached file. The ranged request will be based on this but,
@@ -828,41 +756,40 @@ RSpec.describe "compact index api" do
bundle :install, artifice: "compact_index_range_ignored"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "performs partial update with a non-empty range" do
build_repo4 do
- build_gem "rack", "0.9.1"
+ build_gem "myrack", "0.9.1"
end
# Initial install creates the cached versions file
install_gemfile <<-G, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
source "#{source_uri}"
- gem 'rack', '0.9.1'
+ gem 'myrack', '0.9.1'
G
- update_repo4 do
- build_gem "rack", "1.0.0"
+ build_repo4 do
+ build_gem "myrack", "1.0.0"
end
install_gemfile <<-G, artifice: "compact_index_partial_update", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
source "#{source_uri}"
- gem 'rack', '1.0.0'
+ gem 'myrack', '1.0.0'
G
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "performs partial update while local cache is updated by another process" do
gemfile <<-G
source "#{source_uri}"
- gem 'rack'
+ gem 'myrack'
G
# Create a partial cache versions file
- versions = Pathname.new(Bundler.rubygems.user_home).join(
- ".bundle", "cache", "compact_index",
+ versions = compact_index_cache_path.join(
"localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "versions"
)
versions.dirname.mkpath
@@ -871,92 +798,92 @@ RSpec.describe "compact index api" do
bundle :install, artifice: "compact_index_concurrent_download"
expect(versions.read).to start_with("created_at")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "performs a partial update that fails digest check, then a full update" do
build_repo4 do
- build_gem "rack", "0.9.1"
+ build_gem "myrack", "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'
+ gem 'myrack', '0.9.1'
G
- update_repo4 do
- build_gem "rack", "1.0.0"
+ build_repo4 do
+ build_gem "myrack", "1.0.0"
end
install_gemfile <<-G, artifice: "compact_index_partial_update_bad_digest", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
source "#{source_uri}"
- gem 'rack', '1.0.0'
+ gem 'myrack', '1.0.0'
G
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "performs full update if server endpoints serve partial content responses but don't have incremental content and provide no digest" do
build_repo4 do
- build_gem "rack", "0.9.1"
+ build_gem "myrack", "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'
+ gem 'myrack', '0.9.1'
G
- update_repo4 do
- build_gem "rack", "1.0.0"
+ build_repo4 do
+ build_gem "myrack", "1.0.0"
end
install_gemfile <<-G, artifice: "compact_index_partial_update_no_digest_not_incremental", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
source "#{source_uri}"
- gem 'rack', '1.0.0'
+ gem 'myrack', '1.0.0'
G
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "performs full update of compact index info cache if range is not satisfiable" do
gemfile <<-G
source "#{source_uri}"
- gem 'rack', '0.9.1'
+ gem 'myrack', '0.9.1'
G
bundle :install, artifice: "compact_index"
+ cache_path = compact_index_cache_path.join("localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5")
+
# We must remove the etag so that we don't ignore the range and get a 304 Not Modified.
- rake_info_etag_path = File.join(Bundler.rubygems.user_home, ".bundle", "cache", "compact_index",
- "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "info-etags", "rack-11690b09f16021ff06a6857d784a1870")
- File.unlink(rake_info_etag_path) if File.exist?(rake_info_etag_path)
+ myrack_info_etag_path = File.join(cache_path, "info-etags", "myrack-92f3313ce5721296f14445c3a6b9c073")
+ File.unlink(myrack_info_etag_path) if File.exist?(myrack_info_etag_path)
- rake_info_path = File.join(Bundler.rubygems.user_home, ".bundle", "cache", "compact_index",
- "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "info", "rack")
- expected_rack_info_content = File.read(rake_info_path)
+ myrack_info_path = File.join(cache_path, "info", "myrack")
+ expected_myrack_info_content = File.read(myrack_info_path)
# Modify the cache files to make the range not satisfiable
- File.open(rake_info_path, "a") {|f| f << "0.9.2 |checksum:c55b525b421fd833a93171ad3d7f04528ca8e87d99ac273f8933038942a5888c" }
+ File.open(myrack_info_path, "a") {|f| f << "0.9.2 |checksum:c55b525b421fd833a93171ad3d7f04528ca8e87d99ac273f8933038942a5888c" }
# Update the Gemfile so the next install does its normal things
gemfile <<-G
source "#{source_uri}"
- gem 'rack', '1.0.0'
+ gem 'myrack', '1.0.0'
G
# 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"
- resulting_rack_info_content = File.read(rake_info_path)
+ resulting_myrack_info_content = File.read(myrack_info_path)
- expect(resulting_rack_info_content).to eq(expected_rack_info_content)
+ expect(resulting_myrack_info_content).to eq(expected_myrack_info_content)
end
it "fails gracefully when the source URI has an invalid scheme" do
install_gemfile <<-G, raise_on_error: false
source "htps://rubygems.org"
- gem "rack"
+ gem "myrack"
G
expect(exitstatus).to eq(15)
expect(err).to end_with(<<-E.strip)
@@ -970,7 +897,7 @@ RSpec.describe "compact index api" do
GEM
remote: #{source_uri}
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
ruby
@@ -978,40 +905,36 @@ RSpec.describe "compact index api" do
DEPENDENCIES
#{checksums_section}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
it "handles checksums from the server in base64" do
- api_checksum = checksum_digest(gem_repo1, "rack", "1.0.0")
- rack_checksum = [[api_checksum].pack("H*")].pack("m0")
- install_gemfile <<-G, artifice: "compact_index", env: { "BUNDLER_SPEC_RACK_CHECKSUM" => rack_checksum }
+ api_checksum = checksum_digest(gem_repo1, "myrack", "1.0.0")
+ myrack_checksum = [[api_checksum].pack("H*")].pack("m0")
+ install_gemfile <<-G, artifice: "compact_index", env: { "BUNDLER_SPEC_MYRACK_CHECKSUM" => myrack_checksum }
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
expect(out).to include("Fetching gem metadata from #{source_uri}")
- expect(the_bundle).to include_gems("rack 1.0.0")
+ expect(the_bundle).to include_gems("myrack 1.0.0")
end
it "raises when the checksum does not match" do
install_gemfile <<-G, artifice: "compact_index_wrong_gem_checksum", raise_on_error: false
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
- gem_path = if Bundler.feature_flag.global_gem_cache?
- default_cache_path.dirname.join("cache", "gems", "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", "rack-1.0.0.gem")
- else
- default_cache_path.dirname.join("rack-1.0.0.gem")
- end
+ gem_path = default_cache_path.dirname.join("myrack-1.0.0.gem")
expect(exitstatus).to eq(37)
expect(err).to eq <<~E.strip
Bundler found mismatched checksums. This is a potential security risk.
- rack (1.0.0) sha256=2222222222222222222222222222222222222222222222222222222222222222
+ myrack (1.0.0) sha256=2222222222222222222222222222222222222222222222222222222222222222
from the API at http://localgemserver.test/
- #{checksum_to_lock(gem_repo1, "rack", "1.0.0")}
+ #{checksum_to_lock(gem_repo1, "myrack", "1.0.0")}
from the gem at #{gem_path}
If you trust the API at http://localgemserver.test/, to resolve this issue you can:
@@ -1024,19 +947,19 @@ RSpec.describe "compact index api" do
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!", "DEBUG" => "1" }, verbose: true, raise_on_error: false
+ install_gemfile <<-G, artifice: "compact_index_wrong_gem_checksum", env: { "BUNDLER_SPEC_MYRACK_CHECKSUM" => "checksum!", "DEBUG" => "1" }, verbose: true, raise_on_error: false
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
expect(exitstatus).to eq(14)
- expect(err).to include('Invalid checksum for rack-0.9.1: "checksum!" is not a valid SHA256 hex or base64 digest')
+ expect(err).to include('Invalid checksum for myrack-0.9.1: "checksum!" is not a valid SHA256 hex or base64 digest')
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"
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
end
end
@@ -1045,7 +968,7 @@ RSpec.describe "compact index api" do
install_gemfile <<-G, artifice: "compact_index"
File.umask(0000)
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
end
@@ -1059,16 +982,16 @@ RSpec.describe "compact index api" do
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("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 corrupted API 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(", ")}).
+Bundler::APIResponseMismatchError: Downloading rails-2.3.2 revealed dependencies not in the API (#{deps.map(&:to_s).join(", ")}).
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"
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
source "#{source_uri}" do
gem "rails"
gem "activemerchant"
@@ -1079,4 +1002,11 @@ Running `bundle update rails` should fix the problem.
count = lockfile.match?("CHECKSUMS") ? 2 : 1 # Once in the specs, and once in CHECKSUMS
expect(lockfile.scan(/activemerchant \(/).size).to eq(count)
end
+
+ it "handles an API that does not provide checksums info (undocumented, support may get removed)" do
+ install_gemfile <<-G, artifice: "compact_index_no_checksums"
+ source "https://gem.repo1"
+ gem "rake"
+ G
+ end
end
diff --git a/spec/bundler/install/gems/dependency_api_fallback_spec.rb b/spec/bundler/install/gems/dependency_api_fallback_spec.rb
new file mode 100644
index 0000000000..7890cbdb99
--- /dev/null
+++ b/spec/bundler/install/gems/dependency_api_fallback_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+RSpec.describe "gemcutter's dependency API" do
+ context "when Gemcutter API takes too long to respond" do
+ before do
+ bundle "config set timeout 1"
+ end
+
+ it "times out and falls back on the modern index" do
+ install_gemfile <<-G, artifice: "endpoint_timeout"
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ expect(out).to include("Fetching source index from https://gem.repo1/")
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+ end
+end
diff --git a/spec/bundler/install/gems/dependency_api_spec.rb b/spec/bundler/install/gems/dependency_api_spec.rb
index 35468b3a1c..ac986a0c67 100644
--- a/spec/bundler/install/gems/dependency_api_spec.rb
+++ b/spec/bundler/install/gems/dependency_api_spec.rb
@@ -7,12 +7,12 @@ RSpec.describe "gemcutter's dependency API" do
it "should use the API" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
bundle :install, artifice: "endpoint"
expect(out).to include("Fetching gem metadata from #{source_uri}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "should URI encode gem names" do
@@ -56,15 +56,14 @@ RSpec.describe "gemcutter's dependency API" do
it "should use the endpoint when using deployment mode" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
bundle :install, 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"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "handles git dependencies that are in rubygems" do
@@ -75,7 +74,7 @@ RSpec.describe "gemcutter's dependency API" do
gemfile <<-G
source "#{source_uri}"
- git "#{file_uri_for(lib_path("foo-1.0"))}" do
+ git "#{lib_path("foo-1.0")}" do
gem 'foo'
end
G
@@ -93,7 +92,7 @@ RSpec.describe "gemcutter's dependency API" do
gemfile <<-G
source "#{source_uri}"
- gem 'foo', :git => "#{file_uri_for(lib_path("foo-1.0"))}"
+ gem 'foo', :git => "#{lib_path("foo-1.0")}"
G
bundle :install, artifice: "endpoint"
@@ -108,7 +107,7 @@ RSpec.describe "gemcutter's dependency API" do
build_git "foo"
gemfile <<-G
source "#{source_uri}"
- gem 'foo', :git => "#{file_uri_for(lib_path("foo-1.0"))}"
+ gem 'foo', :git => "#{lib_path("foo-1.0")}"
G
bundle "install", artifice: "endpoint"
@@ -119,24 +118,24 @@ RSpec.describe "gemcutter's dependency API" do
end
it "falls back when the API errors out" do
- simulate_platform x86_mswin32
-
- 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'"
+ simulate_platform "x86-mswin32" do
+ 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
- end
- gemfile <<-G
- source "#{source_uri}"
- gem "rcov"
- G
+ gemfile <<-G
+ source "#{source_uri}"
+ gem "rcov"
+ G
- 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"
+ 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
end
it "falls back when hitting the Gemcutter Dependency Limit" do
@@ -147,7 +146,7 @@ RSpec.describe "gemcutter's dependency API" do
gem "actionmailer"
gem "activeresource"
gem "thin"
- gem "rack"
+ gem "myrack"
gem "rails"
G
bundle :install, artifice: "endpoint_fallback"
@@ -160,7 +159,7 @@ RSpec.describe "gemcutter's dependency API" do
"activeresource 2.3.2",
"activesupport 2.3.2",
"thin 1.0.0",
- "rack 1.0.0",
+ "myrack 1.0.0",
"rails 2.3.2"
)
end
@@ -168,39 +167,39 @@ RSpec.describe "gemcutter's dependency API" do
it "falls back when Gemcutter API doesn't return proper Marshal format" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
bundle :install, verbose: true, artifice: "endpoint_marshal_fail"
expect(out).to include("could not fetch from the dependency API, trying the full index")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "falls back when the API URL returns 403 Forbidden" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
bundle :install, verbose: true, artifice: "endpoint_api_forbidden"
expect(out).to include("Fetching source index from #{source_uri}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "handles host redirects" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
bundle :install, artifice: "endpoint_host_redirect"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "handles host redirects without Gem::Net::HTTP::Persistent" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
FileUtils.mkdir_p lib_path
@@ -218,13 +217,13 @@ RSpec.describe "gemcutter's dependency API" do
bundle :install, artifice: "endpoint_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"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "timeouts when Bundler::Fetcher redirects too much" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
bundle :install, artifice: "endpoint_redirect", raise_on_error: false
@@ -235,50 +234,32 @@ RSpec.describe "gemcutter's dependency API" do
it "should use the modern index for install" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
bundle "install --full-index", artifice: "endpoint"
expect(out).to include("Fetching source index from #{source_uri}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "should use the modern index for update" do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
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"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
- it "fetches again when more dependencies are found in subsequent sources", bundler: "< 3" do
+ it "fetches again when more dependencies are found in subsequent sources" do
build_repo2 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
end
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
- end
-
- gemfile <<-G
- source "#{source_uri}"
- source "#{source_uri}/extra"
- gem "back_deps"
- G
-
- bundle :install, artifice: "endpoint_extra"
- expect(the_bundle).to include_gems "back_deps 1.0", "foo 1.0"
- end
-
- it "fetches again when more dependencies are found in subsequent sources using blocks" do
- build_repo2 do
- build_gem "back_deps" do |s|
- s.add_dependency "foo"
- end
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
+ FileUtils.rm_r Dir[gem_repo2("gems/foo-*.gem")]
end
gemfile <<-G
@@ -295,30 +276,32 @@ RSpec.describe "gemcutter's dependency API" do
it "fetches gem versions even when those gems are already installed" do
gemfile <<-G
source "#{source_uri}"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
G
bundle :install, artifice: "endpoint_extra_api"
build_repo4 do
- build_gem "rack", "1.2" do |s|
- s.executables = "rackup"
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
end
end
gemfile <<-G
source "#{source_uri}" do; end
source "#{source_uri}/extra"
- gem "rack", "1.2"
+ gem "myrack", "1.2"
G
bundle :install, artifice: "endpoint_extra_api"
- expect(the_bundle).to include_gems "rack 1.2"
+ expect(the_bundle).to include_gems "myrack 1.2"
end
- it "considers all possible versions of dependencies from all api gem sources", 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.
+ it "resolves indirect dependencies to the most scoped source that includes them" 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 tries to
+ # use the version in the most scoped source, even if not compatible, and
+ # gives a resolution error
build_repo4 do
build_gem "activesupport", "1.2.0"
build_gem "somegem", "1.0.0" do |s|
@@ -328,14 +311,14 @@ RSpec.describe "gemcutter's dependency API" do
gemfile <<-G
source "#{source_uri}"
- source "#{source_uri}/extra"
- gem 'somegem', '1.0.0'
+ source "#{source_uri}/extra" do
+ gem 'somegem', '1.0.0'
+ end
G
- bundle :install, artifice: "endpoint_extra_api"
+ bundle :install, artifice: "compact_index_extra_api", raise_on_error: false
- expect(the_bundle).to include_gems "somegem 1.0.0"
- expect(the_bundle).to include_gems "activesupport 1.2.3"
+ expect(err).to include("Could not find compatible versions")
end
it "prints API output properly with back deps" do
@@ -343,7 +326,7 @@ RSpec.describe "gemcutter's dependency API" do
build_gem "back_deps" do |s|
s.add_dependency "foo"
end
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
+ FileUtils.rm_r Dir[gem_repo2("gems/foo-*.gem")]
end
gemfile <<-G
@@ -359,33 +342,14 @@ RSpec.describe "gemcutter's dependency API" do
expect(out).to include("Fetching source index from http://localgemserver.test/extra")
end
- it "does not fetch every spec when doing back deps", bundler: "< 3" do
+ it "does not fetch every spec when doing back deps" do
build_repo2 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
end
build_gem "missing"
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
- end
-
- install_gemfile <<-G, artifice: "endpoint_extra_missing"
- source "#{source_uri}"
- source "#{source_uri}/extra"
- gem "back_deps"
- G
-
- expect(the_bundle).to include_gems "back_deps 1.0"
- end
-
- it "does not fetch every spec when doing back deps using blocks" do
- build_repo2 do
- build_gem "back_deps" do |s|
- s.add_dependency "foo"
- end
- build_gem "missing"
-
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
+ FileUtils.rm_r Dir[gem_repo2("gems/foo-*.gem")]
end
install_gemfile <<-G, artifice: "endpoint_extra_missing"
@@ -398,32 +362,12 @@ RSpec.describe "gemcutter's dependency API" do
expect(the_bundle).to include_gems "back_deps 1.0"
end
- it "fetches again when more dependencies are found in subsequent sources using deployment mode", bundler: "< 3" do
+ it "fetches again when more dependencies are found in subsequent sources using deployment mode" do
build_repo2 do
build_gem "back_deps" do |s|
s.add_dependency "foo"
end
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
- end
-
- gemfile <<-G
- source "#{source_uri}"
- source "#{source_uri}/extra"
- gem "back_deps"
- G
-
- bundle :install, 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 mode with blocks" do
- build_repo2 do
- build_gem "back_deps" do |s|
- s.add_dependency "foo"
- end
- FileUtils.rm_rf Dir[gem_repo2("gems/foo-*.gem")]
+ FileUtils.rm_r Dir[gem_repo2("gems/foo-*.gem")]
end
gemfile <<-G
@@ -472,59 +416,25 @@ RSpec.describe "gemcutter's dependency API" do
expect(out).to include("Fetching gem metadata from #{source_uri}")
end
- it "installs the binstubs", bundler: "< 3" do
- gemfile <<-G
- source "#{source_uri}"
- gem "rack"
- G
-
- bundle "install --binstubs", artifice: "endpoint"
-
- gembin "rackup"
- expect(out).to eq("1.0.0")
- end
-
- it "installs the bins when using --path and uses autoclean", bundler: "< 3" do
- gemfile <<-G
- source "#{source_uri}"
- gem "rack"
- G
-
- bundle "install --path vendor/bundle", artifice: "endpoint"
-
- expect(vendored_gems("bin/rackup")).to exist
- end
-
- it "installs the bins when using --path and uses bundle clean", bundler: "< 3" do
- gemfile <<-G
- source "#{source_uri}"
- gem "rack"
- G
-
- bundle "install --path vendor/bundle --no-clean", artifice: "endpoint"
-
- expect(vendored_gems("bin/rackup")).to exist
- end
-
it "prints post_install_messages" do
gemfile <<-G
source "#{source_uri}"
- gem 'rack-obama'
+ gem 'myrack-obama'
G
bundle :install, artifice: "endpoint"
- expect(out).to include("Post-install message from rack:")
+ expect(out).to include("Post-install message from myrack:")
end
it "should display the post install message for a dependency" do
gemfile <<-G
source "#{source_uri}"
- gem 'rack_middleware'
+ gem 'myrack_middleware'
G
bundle :install, artifice: "endpoint"
- expect(out).to include("Post-install message from rack:")
- expect(out).to include("Rack's post install message")
+ expect(out).to include("Post-install message from myrack:")
+ expect(out).to include("Myrack's post install message")
end
context "when using basic authentication" do
@@ -541,74 +451,61 @@ RSpec.describe "gemcutter's dependency API" do
it "passes basic authentication details and strips out creds" do
gemfile <<-G
source "#{basic_auth_source_uri}"
- gem "rack"
+ gem "myrack"
G
bundle :install, artifice: "endpoint_basic_authentication"
expect(out).not_to include("#{user}:#{password}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 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"
+ gem "myrack"
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"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "strips http basic authentication creds for modern index" do
gemfile <<-G
source "#{basic_auth_source_uri}"
- gem "rack"
+ gem "myrack"
G
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"
+ expect(the_bundle).to include_gems "myrack 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"
+ gem "myrack"
G
bundle :install, artifice: "endpoint_500", raise_on_error: false
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}"
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- G
-
- bundle :install, artifice: "endpoint_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"
- end
-
it "does not pass the user / password to different hosts on redirect" do
gemfile <<-G
source "#{basic_auth_source_uri}"
- gem "rack"
+ gem "myrack"
G
bundle :install, artifice: "endpoint_creds_diff_host"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
describe "with host including dashes" do
before do
gemfile <<-G
source "http://local-gemserver.test"
- gem "rack"
+ gem "myrack"
G
end
@@ -616,7 +513,7 @@ RSpec.describe "gemcutter's dependency API" 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"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
@@ -624,7 +521,7 @@ RSpec.describe "gemcutter's dependency API" do
before do
gemfile <<-G
source "#{source_uri}"
- gem "rack"
+ gem "myrack"
G
end
@@ -634,7 +531,7 @@ RSpec.describe "gemcutter's dependency API" do
bundle :install, artifice: "endpoint_strict_basic_authentication"
expect(out).to include("Fetching gem metadata from #{source_uri}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "reads authentication details by full url from bundle config" do
@@ -644,26 +541,26 @@ RSpec.describe "gemcutter's dependency API" do
bundle :install, artifice: "endpoint_strict_basic_authentication"
expect(out).to include("Fetching gem metadata from #{source_uri}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "should use the API" do
bundle "config set #{source_hostname} #{user}:#{password}"
bundle :install, artifice: "endpoint_strict_basic_authentication"
expect(out).to include("Fetching gem metadata from #{source_uri}")
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "prefers auth supplied in the source uri" do
gemfile <<-G
source "#{basic_auth_source_uri}"
- gem "rack"
+ gem "myrack"
G
bundle "config set #{source_hostname} otheruser:wrong"
bundle :install, artifice: "endpoint_strict_basic_authentication"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "shows instructions if auth is not provided for the source" do
@@ -685,11 +582,11 @@ RSpec.describe "gemcutter's dependency API" do
it "passes basic authentication details" do
gemfile <<-G
source "#{basic_auth_source_uri}"
- gem "rack"
+ gem "myrack"
G
bundle :install, artifice: "endpoint_basic_authentication"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
end
@@ -707,14 +604,14 @@ RSpec.describe "gemcutter's dependency API" do
end
end
- it "explains what to do to get it" do
+ it "explains what to do to get it, and includes original error" do
gemfile <<-G
source "#{source_uri.gsub(/http/, "https")}"
- gem "rack"
+ gem "myrack"
G
- bundle :install, env: { "RUBYOPT" => opt_add("-I#{bundled_app("broken_ssl")}", ENV["RUBYOPT"]) }, raise_on_error: false
- expect(err).to include("OpenSSL")
+ bundle :install, artifice: "fail", env: { "RUBYOPT" => "-I#{bundled_app("broken_ssl")}" }, raise_on_error: false
+ expect(err).to include("recompile Ruby").and include("cannot load such file")
end
end
@@ -730,7 +627,7 @@ RSpec.describe "gemcutter's dependency API" do
end
source "#{source_uri.gsub(/http/, "https")}"
- gem "rack"
+ gem "myrack"
G
bundle :install, raise_on_error: false
@@ -747,12 +644,12 @@ RSpec.describe "gemcutter's dependency API" do
begin
gemfile <<-G
source "#{source_uri}"
- gem 'rack'
+ gem 'myrack'
G
bundle "install", artifice: "endpoint_marshal_fail"
ensure
- home(".gemrc").rmtree
+ FileUtils.rm_rf home(".gemrc")
end
end
end
diff --git a/spec/bundler/install/gems/env_spec.rb b/spec/bundler/install/gems/env_spec.rb
index a6dfadcfc8..6d5aa456fe 100644
--- a/spec/bundler/install/gems/env_spec.rb
+++ b/spec/bundler/install/gems/env_spec.rb
@@ -4,104 +4,104 @@ RSpec.describe "bundle install with ENV conditionals" do
describe "when just setting an ENV key as a string" do
before :each do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
env "BUNDLER_TEST" do
- gem "rack"
+ gem "myrack"
end
G
end
it "excludes the gems when the ENV variable is not set" do
bundle :install
- expect(the_bundle).not_to include_gems "rack"
+ expect(the_bundle).not_to include_gems "myrack"
end
it "includes the gems when the ENV variable is set" do
ENV["BUNDLER_TEST"] = "1"
bundle :install
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
end
describe "when just setting an ENV key as a symbol" do
before :each do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
env :BUNDLER_TEST do
- gem "rack"
+ gem "myrack"
end
G
end
it "excludes the gems when the ENV variable is not set" do
bundle :install
- expect(the_bundle).not_to include_gems "rack"
+ expect(the_bundle).not_to include_gems "myrack"
end
it "includes the gems when the ENV variable is set" do
ENV["BUNDLER_TEST"] = "1"
bundle :install
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
end
describe "when setting a string to match the env" do
before :each do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
env "BUNDLER_TEST" => "foo" do
- gem "rack"
+ gem "myrack"
end
G
end
it "excludes the gems when the ENV variable is not set" do
bundle :install
- expect(the_bundle).not_to include_gems "rack"
+ expect(the_bundle).not_to include_gems "myrack"
end
it "excludes the gems when the ENV variable is set but does not match the condition" do
ENV["BUNDLER_TEST"] = "1"
bundle :install
- expect(the_bundle).not_to include_gems "rack"
+ expect(the_bundle).not_to include_gems "myrack"
end
it "includes the gems when the ENV variable is set and matches the condition" do
ENV["BUNDLER_TEST"] = "foo"
bundle :install
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
end
describe "when setting a regex to match the env" do
before :each do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
env "BUNDLER_TEST" => /foo/ do
- gem "rack"
+ gem "myrack"
end
G
end
it "excludes the gems when the ENV variable is not set" do
bundle :install
- expect(the_bundle).not_to include_gems "rack"
+ expect(the_bundle).not_to include_gems "myrack"
end
it "excludes the gems when the ENV variable is set but does not match the condition" do
ENV["BUNDLER_TEST"] = "fo"
bundle :install
- expect(the_bundle).not_to include_gems "rack"
+ expect(the_bundle).not_to include_gems "myrack"
end
it "includes the gems when the ENV variable is set and matches the condition" do
ENV["BUNDLER_TEST"] = "foobar"
bundle :install
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
end
end
diff --git a/spec/bundler/install/gems/flex_spec.rb b/spec/bundler/install/gems/flex_spec.rb
index 5e0c88fc95..b34dbbfa2a 100644
--- a/spec/bundler/install/gems/flex_spec.rb
+++ b/spec/bundler/install/gems/flex_spec.rb
@@ -3,30 +3,30 @@
RSpec.describe "bundle flex_install" do
it "installs the gems as expected" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
expect(the_bundle).to be_locked
end
it "installs even when the lockfile is invalid" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
expect(the_bundle).to be_locked
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack', '1.0'
+ source "https://gem.repo1"
+ gem 'myrack', '1.0'
G
bundle :install
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
expect(the_bundle).to be_locked
end
@@ -34,19 +34,19 @@ RSpec.describe "bundle flex_install" do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack-obama"
+ source "https://gem.repo2"
+ gem "myrack-obama"
G
- expect(the_bundle).to include_gems "rack 1.0.0", "rack-obama 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0", "myrack-obama 1.0.0"
update_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack-obama", "1.0"
+ source "https://gem.repo2"
+ gem "myrack-obama", "1.0"
G
- expect(the_bundle).to include_gems "rack 1.0.0", "rack-obama 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0", "myrack-obama 1.0.0"
end
describe "adding new gems" do
@@ -54,38 +54,38 @@ RSpec.describe "bundle flex_install" do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem 'rack'
+ source "https://gem.repo2"
+ gem 'myrack'
G
update_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem 'rack'
+ source "https://gem.repo2"
+ gem 'myrack'
gem 'activesupport', '2.3.5'
G
- expect(the_bundle).to include_gems "rack 1.0.0", "activesupport 2.3.5"
+ expect(the_bundle).to include_gems "myrack 1.0.0", "activesupport 2.3.5"
end
it "keeps child dependencies pinned" do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack-obama"
+ source "https://gem.repo2"
+ gem "myrack-obama"
G
update_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack-obama"
+ source "https://gem.repo2"
+ gem "myrack-obama"
gem "thin"
G
- expect(the_bundle).to include_gems "rack 1.0.0", "rack-obama 1.0", "thin 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0", "myrack-obama 1.0", "thin 1.0"
end
end
@@ -93,43 +93,43 @@ RSpec.describe "bundle flex_install" do
it "removes gems without changing the versions of remaining gems" do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem 'rack'
+ source "https://gem.repo2"
+ gem 'myrack'
gem 'activesupport', '2.3.5'
G
update_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem 'rack'
+ source "https://gem.repo2"
+ gem 'myrack'
G
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
expect(the_bundle).not_to include_gems "activesupport 2.3.5"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem 'rack'
+ source "https://gem.repo2"
+ gem 'myrack'
gem 'activesupport', '2.3.2'
G
- expect(the_bundle).to include_gems "rack 1.0.0", "activesupport 2.3.2"
+ expect(the_bundle).to include_gems "myrack 1.0.0", "activesupport 2.3.2"
end
it "removes top level dependencies when removed from the Gemfile while leaving other dependencies intact" do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem 'rack'
+ source "https://gem.repo2"
+ gem 'myrack'
gem 'activesupport', '2.3.5'
G
update_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem 'rack'
+ source "https://gem.repo2"
+ gem 'myrack'
G
expect(the_bundle).not_to include_gems "activesupport 2.3.5"
@@ -138,21 +138,21 @@ RSpec.describe "bundle flex_install" do
it "removes child dependencies" do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem 'rack-obama'
+ source "https://gem.repo2"
+ gem 'myrack-obama'
gem 'activesupport'
G
- expect(the_bundle).to include_gems "rack 1.0.0", "rack-obama 1.0.0", "activesupport 2.3.5"
+ expect(the_bundle).to include_gems "myrack 1.0.0", "myrack-obama 1.0.0", "activesupport 2.3.5"
update_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem 'activesupport'
G
expect(the_bundle).to include_gems "activesupport 2.3.5"
- expect(the_bundle).not_to include_gems "rack-obama", "rack"
+ expect(the_bundle).not_to include_gems "myrack-obama", "myrack"
end
end
@@ -160,25 +160,25 @@ RSpec.describe "bundle flex_install" do
before(:each) do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack_middleware"
+ source "https://gem.repo2"
+ gem "myrack_middleware"
G
- expect(the_bundle).to include_gems "rack_middleware 1.0", "rack 0.9.1"
+ expect(the_bundle).to include_gems "myrack_middleware 1.0", "myrack 0.9.1"
build_repo2 do
- build_gem "rack-obama", "2.0" do |s|
- s.add_dependency "rack", "=1.2"
+ build_gem "myrack-obama", "2.0" do |s|
+ s.add_dependency "myrack", "=1.2"
end
- build_gem "rack_middleware", "2.0" do |s|
- s.add_dependency "rack", ">=1.0"
+ build_gem "myrack_middleware", "2.0" do |s|
+ s.add_dependency "myrack", ">=1.0"
end
end
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack-obama", "2.0"
- gem "rack_middleware"
+ source "https://gem.repo2"
+ gem "myrack-obama", "2.0"
+ gem "myrack_middleware"
G
end
@@ -187,7 +187,7 @@ RSpec.describe "bundle flex_install" do
ruby <<-RUBY, raise_on_error: false
require 'bundler/setup'
RUBY
- expect(err).to match(/could not find gem 'rack-obama/i)
+ expect(err).to match(/could not find gem 'myrack-obama/i)
end
it "discards the locked gems when the Gemfile requires different versions than the lock" do
@@ -196,10 +196,10 @@ RSpec.describe "bundle flex_install" do
nice_error = <<~E.strip
Could not find compatible versions
- Because rack-obama >= 2.0 depends on rack = 1.2
- and rack = 1.2 could not be found in rubygems repository #{file_uri_for(gem_repo2)}/ or installed locally,
- rack-obama >= 2.0 cannot be used.
- So, because Gemfile depends on rack-obama = 2.0,
+ Because myrack-obama >= 2.0 depends on myrack = 1.2
+ and myrack = 1.2 could not be found in rubygems repository https://gem.repo2/ or installed locally,
+ myrack-obama >= 2.0 cannot be used.
+ So, because Gemfile depends on myrack-obama = 2.0,
version solving has failed.
E
@@ -211,12 +211,12 @@ RSpec.describe "bundle flex_install" do
bundle "config set force_ruby_platform true"
bad_error = <<~E.strip
- Bundler could not find compatible versions for gem "rack-obama":
+ Bundler could not find compatible versions for gem "myrack-obama":
In Gemfile:
- rack-obama (= 2.0)
+ myrack-obama (= 2.0)
E
- bundle "update rack_middleware", retry: 0, raise_on_error: false
+ bundle "update myrack_middleware", retry: 0, raise_on_error: false
expect(err).not_to end_with(bad_error)
end
end
@@ -233,12 +233,12 @@ RSpec.describe "bundle flex_install" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "jekyll-feed", "~> 0.12"
G
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "github-pages", "~> 226"
gem "jekyll-feed", "~> 0.12"
G
@@ -253,48 +253,72 @@ RSpec.describe "bundle flex_install" do
describe "subtler cases" do
before :each do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- gem "rack-obama"
+ source "https://gem.repo1"
+ gem "myrack"
+ gem "myrack-obama"
G
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "0.9.1"
- gem "rack-obama"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
+ gem "myrack-obama"
G
end
it "should work when you install" do
bundle "install"
- checksums = checksums_section_when_existing do |c|
- c.checksum gem_repo1, "rack", "0.9.1"
- c.checksum gem_repo1, "rack-obama", "1.0"
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo1, "myrack", "0.9.1"
+ c.checksum gem_repo1, "myrack-obama", "1.0"
end
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
- rack (0.9.1)
- rack-obama (1.0)
- rack
+ myrack (0.9.1)
+ myrack-obama (1.0)
+ myrack
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack (= 0.9.1)
- rack-obama
+ myrack (= 0.9.1)
+ myrack-obama
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
it "should work when you update" do
- bundle "update rack"
+ bundle "update myrack"
+
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo1, "myrack", "0.9.1"
+ c.checksum gem_repo1, "myrack-obama", "1.0"
+ end
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo1/
+ specs:
+ myrack (0.9.1)
+ myrack-obama (1.0)
+ myrack
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack (= 0.9.1)
+ myrack-obama
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
end
end
@@ -302,39 +326,39 @@ RSpec.describe "bundle flex_install" do
it "updates the lockfile" do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- source "#{file_uri_for(gem_repo2)}" do
+ source "https://gem.repo1"
+ source "https://gem.repo2" do
end
- gem "rack"
+ gem "myrack"
G
- checksums = checksums_section_when_existing do |c|
- c.checksum gem_repo1, "rack", "1.0.0"
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo1, "myrack", "1.0.0"
end
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
@@ -344,17 +368,17 @@ RSpec.describe "bundle flex_install" do
before(:each) do
build_repo2 do
build_gem "capybara", "0.3.9" do |s|
- s.add_dependency "rack", ">= 1.0.0"
+ s.add_dependency "myrack", ">= 1.0.0"
end
- build_gem "rack", "1.1.0"
+ build_gem "myrack", "1.1.0"
build_gem "rails", "3.0.0.rc4" do |s|
- s.add_dependency "rack", "~> 1.1.0"
+ s.add_dependency "myrack", "~> 1.1.0"
end
- build_gem "rack", "1.2.1"
+ build_gem "myrack", "1.2.1"
build_gem "rails", "3.0.0" do |s|
- s.add_dependency "rack", "~> 1.2.1"
+ s.add_dependency "myrack", "~> 1.2.1"
end
end
end
@@ -362,14 +386,14 @@ RSpec.describe "bundle flex_install" do
it "resolves them" do
# install Rails 3.0.0.rc
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "rails", "3.0.0.rc4"
gem "capybara", "0.3.9"
G
# upgrade Rails to 3.0.0 and then install again
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "rails", "3.0.0"
gem "capybara", "0.3.9"
G
diff --git a/spec/bundler/install/gems/fund_spec.rb b/spec/bundler/install/gems/fund_spec.rb
index 9aadc9ed25..0855a62b86 100644
--- a/spec/bundler/install/gems/fund_spec.rb
+++ b/spec/bundler/install/gems/fund_spec.rb
@@ -32,10 +32,10 @@ RSpec.describe "bundle install" do
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)}"
+ source "https://gem.repo2"
gem 'has_funding_and_other_metadata'
gem 'has_funding'
- gem 'rack-obama'
+ gem 'myrack-obama'
G
expect(out).to include("2 installed gems you directly depend on are looking for funding.")
@@ -43,9 +43,9 @@ RSpec.describe "bundle install" do
it "displays the singular fund message after installing" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem 'has_funding'
- gem 'rack-obama'
+ gem 'myrack-obama'
G
expect(out).to include("1 installed gem you directly depend on is looking for funding.")
@@ -59,10 +59,10 @@ RSpec.describe "bundle install" do
it "does not display the plural fund message after installing" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem 'has_funding_and_other_metadata'
gem 'has_funding'
- gem 'rack-obama'
+ gem 'myrack-obama'
G
expect(out).not_to include("2 installed gems you directly depend on are looking for funding.")
@@ -70,9 +70,9 @@ RSpec.describe "bundle install" do
it "does not display the singular fund message after installing" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem 'has_funding'
- gem 'rack-obama'
+ gem 'myrack-obama'
G
expect(out).not_to include("1 installed gem you directly depend on is looking for funding.")
@@ -82,7 +82,7 @@ RSpec.describe "bundle install" do
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)}"
+ source "https://gem.repo2"
gem "activesupport"
G
@@ -93,7 +93,7 @@ RSpec.describe "bundle install" do
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)}"
+ source "https://gem.repo2"
gem 'gem_with_dependent_funding'
G
@@ -111,7 +111,7 @@ RSpec.describe "bundle install" do
}
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'also_has_funding', :git => '#{lib_path("also_has_funding-1.0")}'
G
@@ -125,7 +125,7 @@ RSpec.describe "bundle install" do
}
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'also_has_funding', :git => '#{lib_path("also_has_funding-1.0")}'
G
@@ -135,7 +135,7 @@ RSpec.describe "bundle install" do
}
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'also_has_funding', :git => '#{lib_path("also_has_funding-1.1")}'
G
@@ -149,7 +149,7 @@ RSpec.describe "bundle install" do
}
end
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'also_has_funding', :git => '#{lib_path("also_has_funding-1.0")}'
G
diff --git a/spec/bundler/install/gems/gemfile_source_header_spec.rb b/spec/bundler/install/gems/gemfile_source_header_spec.rb
new file mode 100644
index 0000000000..9e63fa7551
--- /dev/null
+++ b/spec/bundler/install/gems/gemfile_source_header_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+RSpec.describe "fetching dependencies with a mirrored source" do
+ let(:mirror) { "https://server.example.org" }
+
+ before do
+ build_repo2
+
+ gemfile <<-G
+ source "#{mirror}"
+ gem 'weakling'
+ G
+
+ bundle "config set --local mirror.#{mirror} https://gem.repo2"
+ end
+
+ it "sets the 'X-Gemfile-Source' and 'User-Agent' headers and bundles successfully" do
+ bundle :install, artifice: "endpoint_mirror_source"
+
+ expect(out).to include("Installing weakling")
+ expect(out).to include("Bundle complete")
+ expect(the_bundle).to include_gems "weakling 0.0.3"
+ end
+end
diff --git a/spec/bundler/install/gems/mirror_probe_spec.rb b/spec/bundler/install/gems/mirror_probe_spec.rb
new file mode 100644
index 0000000000..436f116cac
--- /dev/null
+++ b/spec/bundler/install/gems/mirror_probe_spec.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+RSpec.describe "fetching dependencies with a not available mirror" do
+ before do
+ build_repo2
+
+ gemfile <<-G
+ source "https://gem.repo2"
+ gem 'weakling'
+ G
+ end
+
+ context "with a specific fallback timeout" do
+ before do
+ global_config("BUNDLE_MIRROR__HTTPS://GEM__REPO2/__FALLBACK_TIMEOUT/" => "true",
+ "BUNDLE_MIRROR__HTTPS://GEM__REPO2/" => "https://gem.mirror")
+ end
+
+ it "install a gem using the original uri when the mirror is not responding" do
+ bundle :install, env: { "BUNDLER_SPEC_FAKE_RESOLVE" => "gem.mirror" }, verbose: true
+
+ expect(out).to include("Installing weakling")
+ expect(out).to include("Bundle complete")
+ expect(the_bundle).to include_gems "weakling 0.0.3"
+ end
+ end
+
+ context "with a global fallback timeout" do
+ before do
+ global_config("BUNDLE_MIRROR__ALL__FALLBACK_TIMEOUT/" => "1",
+ "BUNDLE_MIRROR__ALL" => "https://gem.mirror")
+ end
+
+ it "install a gem using the original uri when the mirror is not responding" do
+ bundle :install, env: { "BUNDLER_SPEC_FAKE_RESOLVE" => "gem.mirror" }
+
+ expect(out).to include("Installing weakling")
+ expect(out).to include("Bundle complete")
+ expect(the_bundle).to include_gems "weakling 0.0.3"
+ end
+ end
+
+ context "with a specific mirror without a fallback timeout" do
+ before do
+ global_config("BUNDLE_MIRROR__HTTPS://GEM__REPO2/" => "https://gem.mirror")
+ end
+
+ it "fails to install the gem with a timeout error when the mirror is not responding" do
+ bundle :install, artifice: "compact_index_mirror_down", raise_on_error: false
+
+ expect(out).to be_empty
+ expect(err).to eq("Could not reach host gem.mirror. Check your network connection and try again.")
+ end
+ end
+
+ context "with a global mirror without a fallback timeout" do
+ before do
+ global_config("BUNDLE_MIRROR__ALL" => "https://gem.mirror")
+ end
+
+ it "fails to install the gem with a timeout error when the mirror is not responding" do
+ bundle :install, artifice: "compact_index_mirror_down", raise_on_error: false
+
+ expect(out).to be_empty
+ expect(err).to eq("Could not reach host gem.mirror. Check your network connection and try again.")
+ end
+ end
+end
diff --git a/spec/bundler/install/gems/mirror_spec.rb b/spec/bundler/install/gems/mirror_spec.rb
index 9611973701..70c0da50ef 100644
--- a/spec/bundler/install/gems/mirror_spec.rb
+++ b/spec/bundler/install/gems/mirror_spec.rb
@@ -4,17 +4,17 @@ RSpec.describe "bundle install with a mirror configured" do
describe "when the mirror does not match the gem source" do
before :each do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
G
bundle "config set --local mirror.http://gems.example.org http://gem-mirror.example.org"
end
it "installs from the normal location" do
bundle :install
- expect(out).to include("Fetching source index from #{file_uri_for(gem_repo1)}")
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(out).to include("Fetching gem metadata from https://gem.repo1")
+ expect(the_bundle).to include_gems "myrack 1.0"
end
end
@@ -22,18 +22,18 @@ RSpec.describe "bundle install with a mirror configured" do
before :each do
gemfile <<-G
# This source is bogus and doesn't have the gem we're looking for
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
- gem "rack"
+ gem "myrack"
G
- bundle "config set --local mirror.#{file_uri_for(gem_repo2)} #{file_uri_for(gem_repo1)}"
+ bundle "config set --local mirror.https://gem.repo2 https://gem.repo1"
end
it "installs the gem from the mirror" do
- bundle :install
- expect(out).to include("Fetching source index from #{file_uri_for(gem_repo1)}")
- expect(out).not_to include("Fetching source index from #{file_uri_for(gem_repo2)}")
- expect(the_bundle).to include_gems "rack 1.0"
+ bundle :install, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
+ expect(out).to include("Fetching gem metadata from https://gem.repo1")
+ expect(out).not_to include("Fetching gem metadata from https://gem.repo2")
+ expect(the_bundle).to include_gems "myrack 1.0"
end
end
end
diff --git a/spec/bundler/install/gems/native_extensions_spec.rb b/spec/bundler/install/gems/native_extensions_spec.rb
index 907778a384..7f230d132b 100644
--- a/spec/bundler/install/gems/native_extensions_spec.rb
+++ b/spec/bundler/install/gems/native_extensions_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe "installing a gem with native extensions" do
require "mkmf"
name = "c_extension_bundle"
dir_config(name)
- raise "OMG" unless with_config("c_extension") == "hello"
+ raise ArgumentError unless with_config("c_extension") == "hello"
create_makefile(name)
E
@@ -33,7 +33,7 @@ RSpec.describe "installing a gem with native extensions" do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "c_extension"
G
@@ -53,7 +53,7 @@ RSpec.describe "installing a gem with native extensions" do
require "mkmf"
name = "c_extension_bundle"
dir_config(name)
- raise "OMG" unless with_config("c_extension") == "hello"
+ raise ArgumentError unless with_config("c_extension") == "hello"
create_makefile(name)
E
@@ -78,7 +78,7 @@ RSpec.describe "installing a gem with native extensions" do
bundle "config set build.c_extension --with-c_extension=hello"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "c_extension", :git => #{lib_path("c_extension-1.0").to_s.dump}
G
@@ -97,7 +97,7 @@ RSpec.describe "installing a gem with native extensions" do
require "mkmf"
name = "c_extension_bundle_#{n}"
dir_config(name)
- raise "OMG" unless with_config("c_extension_#{n}") == "#{n}"
+ raise ArgumentError unless with_config("c_extension_#{n}") == "#{n}"
create_makefile(name)
E
@@ -127,13 +127,13 @@ RSpec.describe "installing a gem with native extensions" do
# 1st time, require only one gem -- only one of the extensions gets built.
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://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)}"
+ source "https://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
@@ -149,7 +149,7 @@ RSpec.describe "installing a gem with native extensions" do
require "mkmf"
name = "c_extension_bundle"
dir_config(name)
- raise "OMG" unless with_config("c_extension") == "hello" && with_config("c_extension_bundle-dir") == "hola"
+ raise ArgumentError unless with_config("c_extension") == "hello" && with_config("c_extension_bundle-dir") == "hola"
create_makefile(name)
E
@@ -174,7 +174,7 @@ RSpec.describe "installing a gem with native extensions" do
bundle "config set build.c_extension --with-c_extension=hello --with-c_extension_bundle-dir=hola"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "c_extension", :git => #{lib_path("c_extension-1.0").to_s.dump}
G
diff --git a/spec/bundler/install/gems/post_install_spec.rb b/spec/bundler/install/gems/post_install_spec.rb
index 7426f54877..af753dba3e 100644
--- a/spec/bundler/install/gems/post_install_spec.rb
+++ b/spec/bundler/install/gems/post_install_spec.rb
@@ -5,26 +5,26 @@ RSpec.describe "bundle install" do
context "when gems include post install messages" do
it "should display the post-install messages after installing" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
gem 'thin'
- gem 'rack-obama'
+ gem 'myrack-obama'
G
bundle :install
- expect(out).to include("Post-install message from rack:")
- expect(out).to include("Rack's post install message")
+ expect(out).to include("Post-install message from myrack:")
+ expect(out).to include("Myrack's post install message")
expect(out).to include("Post-install message from thin:")
expect(out).to include("Thin's post install message")
- expect(out).to include("Post-install message from rack-obama:")
- expect(out).to include("Rack-obama's post install message")
+ expect(out).to include("Post-install message from myrack-obama:")
+ expect(out).to include("Myrack-obama's post install message")
end
end
context "when gems do not include post install messages" do
it "should not display any post-install messages" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "activesupport"
G
@@ -36,13 +36,13 @@ RSpec.describe "bundle install" 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)}"
- gem 'rack_middleware'
+ source "https://gem.repo1"
+ gem 'myrack_middleware'
G
bundle :install
- expect(out).to include("Post-install message from rack:")
- expect(out).to include("Rack's post install message")
+ expect(out).to include("Post-install message from myrack:")
+ expect(out).to include("Myrack's post install message")
end
end
end
@@ -54,7 +54,7 @@ RSpec.describe "bundle install" do
s.post_install_message = "Foo's post install message"
end
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'foo', :git => '#{lib_path("foo-1.0")}'
G
@@ -68,7 +68,7 @@ RSpec.describe "bundle install" do
s.post_install_message = "Foo's post install message"
end
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'foo', :git => '#{lib_path("foo-1.0")}'
G
bundle :install
@@ -77,7 +77,7 @@ RSpec.describe "bundle install" do
s.post_install_message = "Foo's 1.1 post install message"
end
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'foo', :git => '#{lib_path("foo-1.1")}'
G
bundle :install
@@ -91,7 +91,7 @@ RSpec.describe "bundle install" do
s.post_install_message = "Foo's post install message"
end
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'foo', :git => '#{lib_path("foo-1.0")}'
G
@@ -110,7 +110,7 @@ RSpec.describe "bundle install" do
s.post_install_message = nil
end
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'foo', :git => '#{lib_path("foo-1.0")}'
G
@@ -123,11 +123,11 @@ RSpec.describe "bundle install" do
context "when ignore post-install messages for gem is set" do
it "doesn't display any post-install messages" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "config set ignore_messages.rack true"
+ bundle "config set ignore_messages.myrack true"
bundle :install
expect(out).not_to include("Post-install message")
@@ -137,8 +137,8 @@ RSpec.describe "bundle install" do
context "when ignore post-install messages for all gems" do
it "doesn't display any post-install messages" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle "config set ignore_messages true"
diff --git a/spec/bundler/install/gems/resolving_spec.rb b/spec/bundler/install/gems/resolving_spec.rb
index b54674898d..f59bb70c7b 100644
--- a/spec/bundler/install/gems/resolving_spec.rb
+++ b/spec/bundler/install/gems/resolving_spec.rb
@@ -66,7 +66,7 @@ RSpec.describe "bundle install with install-time dependencies" do
it "installs gems with implicit rake dependencies" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "with_implicit_rake_dep"
gem "another_implicit_rake_dep"
gem "rake"
@@ -84,7 +84,7 @@ RSpec.describe "bundle install with install-time dependencies" do
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)}"
+ source "https://gem.repo2"
gem "with_implicit_rake_dep"
gem "another_implicit_rake_dep"
gem "rake"
@@ -100,7 +100,7 @@ RSpec.describe "bundle install with install-time dependencies" do
expect(out).to eq("YES\nYES")
end
- it "installs gems with a dependency with no type" do
+ it "does not install gems with a dependency with no type" do
build_repo2
path = "#{gem_repo2}/#{Gem::MARSHAL_SPEC_DIR}/actionpack-2.3.2.gemspec.rz"
@@ -112,18 +112,20 @@ RSpec.describe "bundle install with install-time dependencies" do
f.write Gem.deflate(Marshal.dump(spec))
end
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo2"
gem "actionpack", "2.3.2"
G
- expect(the_bundle).to include_gems "actionpack 2.3.2", "activesupport 2.3.2"
+ expect(err).to include("Downloading actionpack-2.3.2 revealed dependencies not in the API (activesupport (= 2.3.2)).")
+
+ expect(the_bundle).not_to include_gems "actionpack 2.3.2", "activesupport 2.3.2"
end
describe "with crazy rubygem plugin stuff" do
it "installs plugins" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "net_b"
G
@@ -132,7 +134,7 @@ RSpec.describe "bundle install with install-time dependencies" do
it "installs plugins depended on by other plugins" do
install_gemfile <<-G, env: { "DEBUG" => "1" }
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "net_a"
G
@@ -141,7 +143,7 @@ RSpec.describe "bundle install with install-time dependencies" do
it "installs multiple levels of dependencies" do
install_gemfile <<-G, env: { "DEBUG" => "1" }
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "net_c"
gem "net_e"
G
@@ -152,7 +154,7 @@ RSpec.describe "bundle install with install-time dependencies" do
context "with ENV['BUNDLER_DEBUG_RESOLVER'] set" do
it "produces debug output" do
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "net_c"
gem "net_e"
G
@@ -166,7 +168,7 @@ RSpec.describe "bundle install with install-time dependencies" do
context "with ENV['DEBUG_RESOLVER'] set" do
it "produces debug output" do
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "net_c"
gem "net_e"
G
@@ -180,7 +182,7 @@ RSpec.describe "bundle install with install-time dependencies" do
context "with ENV['DEBUG_RESOLVER_TREE'] set" do
it "produces debug output" do
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "net_c"
gem "net_e"
G
@@ -199,44 +201,44 @@ RSpec.describe "bundle install with install-time dependencies" do
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"
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
end
- build_gem "rack", "9001.0.0" do |s|
+ build_gem "myrack", "9001.0.0" do |s|
s.required_ruby_version = "> 9000"
end
end
- install_gemfile <<-G, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+ install_gemfile <<-G
ruby "#{Gem.ruby_version}"
- source "http://localgemserver.test/"
- gem 'rack'
+ source "https://gem.repo2"
+ gem 'myrack'
G
- expect(err).to_not include("rack-9001.0.0 requires ruby version > 9000")
- expect(the_bundle).to include_gems("rack 1.2")
+ expect(err).to_not include("myrack-9001.0.0 requires ruby version > 9000")
+ expect(the_bundle).to include_gems("myrack 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"
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
end
- build_gem "rack", "9001.0.0" do |s|
+ build_gem "myrack", "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 }
+ install_gemfile <<-G, artifice: "endpoint"
ruby "#{Gem.ruby_version}"
- source "http://localgemserver.test/"
- gem 'rack'
+ source "https://gem.repo2"
+ gem 'myrack'
G
- expect(err).to_not include("rack-9001.0.0 requires ruby version > 9000")
- expect(the_bundle).to include_gems("rack 1.2")
+ expect(err).to_not include("myrack-9001.0.0 requires ruby version > 9000")
+ expect(the_bundle).to include_gems("myrack 1.2")
end
context "when there is a lockfile using the newer incompatible version" do
@@ -252,7 +254,7 @@ RSpec.describe "bundle install with install-time dependencies" do
end
gemfile <<-G
- source "http://localgemserver.test/"
+ source "https://gem.repo2"
gem 'parallel_tests'
G
@@ -262,7 +264,7 @@ RSpec.describe "bundle install with install-time dependencies" do
lockfile <<~L
GEM
- remote: http://localgemserver.test/
+ remote: https://gem.repo2/
specs:
parallel_tests (3.8.0)
@@ -273,20 +275,20 @@ RSpec.describe "bundle install with install-time dependencies" do
parallel_tests
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
it "automatically updates lockfile to use the older version" do
- bundle "install --verbose", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+ bundle "install --verbose"
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo2, "parallel_tests", "3.7.0"
end
expect(lockfile).to eq <<~L
GEM
- remote: http://localgemserver.test/
+ remote: https://gem.repo2/
specs:
parallel_tests (3.7.0)
@@ -297,17 +299,16 @@ RSpec.describe "bundle install with install-time dependencies" do
parallel_tests
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
it "gives a meaningful error if we're in frozen mode" do
expect do
- bundle "install --verbose", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s, "BUNDLE_FROZEN" => "true" }, raise_on_error: false
+ bundle "install", env: { "BUNDLE_FROZEN" => "true" }, raise_on_error: false
end.not_to change { lockfile }
- expect(err).to include("parallel_tests-3.8.0 requires ruby version >= #{next_ruby_minor}")
- expect(err).not_to include("That means the author of parallel_tests (3.8.0) has removed it.")
+ expect(err).to eq("parallel_tests-3.8.0 requires ruby version >= #{next_ruby_minor}, which is incompatible with the current version, #{Gem.ruby_version}")
end
end
@@ -336,7 +337,7 @@ RSpec.describe "bundle install with install-time dependencies" do
end
gemfile <<-G
- source "http://localgemserver.test/"
+ source "https://gem.repo2"
gem 'rubocop'
G
@@ -347,7 +348,7 @@ RSpec.describe "bundle install with install-time dependencies" do
lockfile <<~L
GEM
- remote: http://localgemserver.test/
+ remote: https://gem.repo2/
specs:
rubocop (1.35.0)
rubocop-ast (>= 1.20.1, < 2.0)
@@ -360,21 +361,21 @@ RSpec.describe "bundle install with install-time dependencies" do
parallel_tests
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
it "automatically updates lockfile to use the older compatible versions" do
- bundle "install --verbose", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
+ bundle "install --verbose"
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo2, "rubocop", "1.28.2"
c.checksum gem_repo2, "rubocop-ast", "1.17.0"
end
expect(lockfile).to eq <<~L
GEM
- remote: http://localgemserver.test/
+ remote: https://gem.repo2/
specs:
rubocop (1.28.2)
rubocop-ast (>= 1.17.0, < 2.0)
@@ -387,12 +388,12 @@ RSpec.describe "bundle install with install-time dependencies" do
rubocop
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
- context "with a Gemfile and lock file that don't resolve under the current platform" do
+ context "with a Gemfile and lockfile that don't resolve under the current platform" do
before do
build_repo4 do
build_gem "sorbet", "0.5.10554" do |s|
@@ -405,13 +406,13 @@ RSpec.describe "bundle install with install-time dependencies" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem 'sorbet', '= 0.5.10554'
G
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
sorbet (0.5.10554)
sorbet-static (= 0.5.10554)
@@ -424,7 +425,7 @@ RSpec.describe "bundle install with install-time dependencies" do
sorbet (= 0.5.10554)
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
@@ -434,7 +435,7 @@ RSpec.describe "bundle install with install-time dependencies" do
end
nice_error = <<~E.strip
- Could not find gems matching 'sorbet-static (= 0.5.10554)' valid for all resolution platforms (arm64-darwin-21, aarch64-linux) in rubygems repository #{file_uri_for(gem_repo4)}/ or installed locally.
+ Could not find gems matching 'sorbet-static (= 0.5.10554)' valid for all resolution platforms (arm64-darwin-21, aarch64-linux) in rubygems repository https://gem.repo4/ or installed locally.
The source contains the following gems matching 'sorbet-static (= 0.5.10554)':
* sorbet-static-0.5.10554-universal-darwin-21
@@ -461,7 +462,7 @@ RSpec.describe "bundle install with install-time dependencies" do
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
nokogiri (1.14.0-arm-linux)
nokogiri (1.14.0-x86_64-linux)
@@ -474,11 +475,11 @@ RSpec.describe "bundle install with install-time dependencies" do
nokogiri
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "nokogiri"
gem "sorbet-static"
@@ -490,7 +491,7 @@ RSpec.describe "bundle install with install-time dependencies" do
it "raises a proper error" do
nice_error = <<~E.strip
- Could not find gems matching 'sorbet-static' valid for all resolution platforms (arm-linux, x86_64-linux) in rubygems repository #{file_uri_for(gem_repo4)}/ or installed locally.
+ Could not find gems matching 'sorbet-static' valid for all resolution platforms (arm-linux, x86_64-linux) in rubygems repository https://gem.repo4/ or installed locally.
The source contains the following gems matching 'sorbet-static':
* sorbet-static-0.5.10696-x86_64-linux
@@ -499,6 +500,64 @@ RSpec.describe "bundle install with install-time dependencies" do
end
end
+ context "when locked generic variant supports current Ruby, but locked specific variant does not" do
+ let(:original_lockfile) do
+ <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ nokogiri (1.16.3)
+ nokogiri (1.16.3-x86_64-linux)
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ nokogiri
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ before do
+ build_repo4 do
+ build_gem "nokogiri", "1.16.3"
+ build_gem "nokogiri", "1.16.3" do |s|
+ s.required_ruby_version = "< #{Gem.ruby_version}"
+ s.platform = "x86_64-linux"
+ end
+ end
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "nokogiri"
+ G
+
+ lockfile original_lockfile
+ end
+
+ it "keeps both variants in the lockfile when installing, and uses the generic one since it's compatible" do
+ simulate_platform "x86_64-linux" do
+ bundle "install --verbose"
+
+ expect(lockfile).to eq(original_lockfile)
+ expect(the_bundle).to include_gems("nokogiri 1.16.3")
+ end
+ end
+
+ it "keeps both variants in the lockfile when updating, and uses the generic one since it's compatible" do
+ simulate_platform "x86_64-linux" do
+ bundle "update --verbose"
+
+ expect(lockfile).to eq(original_lockfile)
+ expect(the_bundle).to include_gems("nokogiri 1.16.3")
+ end
+ end
+ end
+
it "gives a meaningful error on ruby version mismatches between dependencies" do
build_repo4 do
build_gem "requires-old-ruby" do |s|
@@ -513,7 +572,7 @@ RSpec.describe "bundle install with install-time dependencies" do
end
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gemspec
G
@@ -531,47 +590,47 @@ RSpec.describe "bundle install with install-time dependencies" do
it "installs the older version under rate limiting conditions" do
build_repo4 do
- build_gem "rack", "9001.0.0" do |s|
+ build_gem "myrack", "9001.0.0" do |s|
s.required_ruby_version = "> 9000"
end
- build_gem "rack", "1.2"
+ build_gem "myrack", "1.2"
build_gem "foo1", "1.0"
end
- install_gemfile <<-G, artifice: "compact_index_rate_limited", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ install_gemfile <<-G, artifice: "compact_index_rate_limited"
ruby "#{Gem.ruby_version}"
- source "http://localgemserver.test/"
- gem 'rack'
+ source "https://gem.repo4"
+ gem 'myrack'
gem 'foo1'
G
- expect(err).to_not include("rack-9001.0.0 requires ruby version > 9000")
- expect(the_bundle).to include_gems("rack 1.2")
+ expect(err).to_not include("myrack-9001.0.0 requires ruby version > 9000")
+ expect(the_bundle).to include_gems("myrack 1.2")
end
it "installs the older not platform specific version" do
build_repo4 do
- build_gem "rack", "9001.0.0" do |s|
+ build_gem "myrack", "9001.0.0" do |s|
s.required_ruby_version = "> 9000"
end
- build_gem "rack", "1.2" do |s|
- s.platform = x86_mingw32
+ build_gem "myrack", "1.2" do |s|
+ s.platform = "x86-mingw32"
s.required_ruby_version = "> 9000"
end
- build_gem "rack", "1.2"
+ build_gem "myrack", "1.2"
end
- simulate_platform x86_mingw32 do
- install_gemfile <<-G, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ simulate_platform "x86-mingw32" do
+ install_gemfile <<-G, artifice: "compact_index"
ruby "#{Gem.ruby_version}"
- source "http://localgemserver.test/"
- gem 'rack'
+ source "https://gem.repo4"
+ gem 'myrack'
G
end
- expect(err).to_not include("rack-9001.0.0 requires ruby version > 9000")
- expect(err).to_not include("rack-1.2-#{Bundler.local_platform} requires ruby version > 9000")
- expect(the_bundle).to include_gems("rack 1.2")
+ expect(err).to_not include("myrack-9001.0.0 requires ruby version > 9000")
+ expect(err).to_not include("myrack-1.2-#{Bundler.local_platform} requires ruby version > 9000")
+ expect(the_bundle).to include_gems("myrack 1.2")
end
end
@@ -588,8 +647,8 @@ RSpec.describe "bundle install with install-time dependencies" do
let(:error_message_requirement) { "= #{Gem.ruby_version}" }
it "raises a proper error that mentions the current Ruby version during resolution" do
- install_gemfile <<-G, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }, raise_on_error: false
- source "http://localgemserver.test/"
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo2"
gem 'require_ruby'
G
@@ -609,8 +668,8 @@ RSpec.describe "bundle install with install-time dependencies" do
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 }, raise_on_error: false
- source "http://localgemserver.test/"
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo2"
ruby #{ruby_requirement}
gem 'require_ruby'
G
@@ -656,7 +715,7 @@ RSpec.describe "bundle install with install-time dependencies" do
end
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem 'require_rubygems'
G
@@ -671,4 +730,55 @@ RSpec.describe "bundle install with install-time dependencies" do
expect(err).to end_with(nice_error)
end
end
+
+ context "when non platform specific gems bring more dependencies", :truffleruby_only do
+ before do
+ build_repo4 do
+ build_gem "foo", "1.0" do |s|
+ s.add_dependency "bar"
+ end
+
+ build_gem "foo", "2.0" do |s|
+ s.platform = "x86_64-linux"
+ end
+
+ build_gem "bar"
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "foo"
+ G
+ end
+
+ it "locks both ruby and current platform, and resolve to ruby variants that install on truffleruby" do
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "foo", "1.0"
+ c.checksum gem_repo4, "bar", "1.0"
+ end
+
+ simulate_platform "x86_64-linux" do
+ bundle "install"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ bar (1.0)
+ foo (1.0)
+ bar
+
+ PLATFORMS
+ ruby
+ x86_64-linux
+
+ DEPENDENCIES
+ foo
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+ end
+ end
end
diff --git a/spec/bundler/install/gems/standalone_spec.rb b/spec/bundler/install/gems/standalone_spec.rb
index 46cab2dfeb..37997ffe48 100644
--- a/spec/bundler/install/gems/standalone_spec.rb
+++ b/spec/bundler/install/gems/standalone_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.shared_examples "bundle install --standalone" do
+RSpec.describe "bundle install --standalone" do
shared_examples "common functionality" do
it "still makes the gems available to normal bundler" do
args = expected_gems.map {|k, v| "#{k} #{v}" }
@@ -8,9 +8,9 @@ RSpec.shared_examples "bundle install --standalone" do
end
it "still makes system gems unavailable to normal bundler" do
- system_gems "rack-1.0.0"
+ system_gems "myrack-1.0.0"
- expect(the_bundle).to_not include_gems("rack")
+ expect(the_bundle).to_not include_gems("myrack")
end
it "generates a bundle/bundler/setup.rb" do
@@ -42,7 +42,7 @@ RSpec.shared_examples "bundle install --standalone" do
testrb << "\nrequire \"#{k}\""
testrb << "\nputs #{k.upcase}"
end
- sys_exec %(#{Gem.ruby} --disable-gems -w -e #{testrb.shellescape})
+ in_bundled_app %(#{Gem.ruby} --disable-gems -w -e #{testrb.shellescape})
expect(out).to eq(expected_gems.values.join("\n"))
end
@@ -63,14 +63,14 @@ RSpec.shared_examples "bundle install --standalone" do
end
it "makes system gems unavailable without bundler" do
- system_gems "rack-1.0.0"
+ system_gems "myrack-1.0.0"
testrb = String.new <<-RUBY
$:.unshift File.expand_path("bundle")
require "bundler/setup"
begin
- require "rack"
+ require "myrack"
rescue LoadError
puts "LoadError"
end
@@ -113,7 +113,7 @@ RSpec.shared_examples "bundle install --standalone" do
testrb << "\nrequire \"#{k}\""
testrb << "\nputs #{k.upcase}"
end
- sys_exec %(#{Gem.ruby} -w -e #{testrb.shellescape})
+ in_bundled_app %(#{Gem.ruby} -w -e #{testrb.shellescape})
expect(out).to eq(expected_gems.values.join("\n"))
end
@@ -122,7 +122,7 @@ RSpec.shared_examples "bundle install --standalone" do
describe "with simple gems" do
before do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
G
bundle "config set --local path #{bundled_app("bundle")}"
@@ -140,13 +140,8 @@ RSpec.shared_examples "bundle install --standalone" do
end
describe "with default gems and a lockfile", :ruby_repo do
- before do
- 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.1.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")))
+ it "works and points to the vendored copies, not to the default copies" do
+ base_system_gems "stringio", "psych", "etc", path: scoped_gem_path(bundled_app("bundle"))
build_gem "foo", "1.0.0", to_system: true, default: true do |s|
s.add_dependency "bar"
@@ -167,12 +162,11 @@ RSpec.shared_examples "bundle install --standalone" do
gem "foo"
G
- bundle "lock", dir: cwd, artifice: "compact_index"
- end
+ bundle "lock", dir: cwd
- it "works and points to the vendored copies, not to the default copies", :realworld 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 }
+
+ bundle :install, standalone: true, dir: cwd, env: { "BUNDLER_GEM_DEFAULT_DIR" => system_gem_path.to_s }
load_path_lines = bundled_app("bundle/bundler/setup.rb").read.split("\n").select {|line| line.start_with?("$:.unshift") }
@@ -181,6 +175,36 @@ RSpec.shared_examples "bundle install --standalone" do
'$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/foo-1.0.0/lib")',
]
end
+
+ it "works for gems with extensions and points to the vendored copies, not to the default copies" do
+ simulate_platform "arm64-darwin-23" do
+ base_system_gems "stringio", "psych", "etc", "shellwords", "open3", path: scoped_gem_path(bundled_app("bundle"))
+
+ build_gem "baz", "1.0.0", to_system: true, default: true, &:add_c_extension
+
+ build_repo4 do
+ build_gem "baz", "1.0.0", &:add_c_extension
+ end
+
+ gemfile <<-G
+ source "https://gem.repo4"
+ gem "baz"
+ G
+
+ bundle "config set --local path #{bundled_app("bundle")}"
+
+ bundle "lock", dir: cwd
+
+ bundle :install, standalone: true, dir: cwd, env: { "BUNDLER_GEM_DEFAULT_DIR" => system_gem_path.to_s }
+ end
+
+ load_path_lines = bundled_app("bundle/bundler/setup.rb").read.split("\n").select {|line| line.start_with?("$:.unshift") }
+
+ expect(load_path_lines).to eq [
+ '$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/extensions/arm64-darwin-23/#{Gem.extension_api_version}/baz-1.0.0")',
+ '$:.unshift File.expand_path("#{__dir__}/../#{RUBY_ENGINE}/#{Gem.ruby_api_version}/gems/baz-1.0.0/lib")',
+ ]
+ end
end
describe "with Gemfiles using absolute path sources and resulting bundle moved to a folder hierarchy with different nesting" do
@@ -190,7 +214,7 @@ RSpec.shared_examples "bundle install --standalone" do
Dir.mkdir bundled_app("app")
gemfile bundled_app("app/Gemfile"), <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "minitest", :path => "#{lib_path("minitest")}"
G
@@ -213,6 +237,8 @@ RSpec.shared_examples "bundle install --standalone" do
end
end
+ let(:cwd) { bundled_app }
+
describe "with Gemfiles using relative path sources and app moved to a different root" do
before do
FileUtils.mkdir_p bundled_app("app/vendor")
@@ -220,7 +246,7 @@ RSpec.shared_examples "bundle install --standalone" do
build_lib "minitest", "1.0.0", path: bundled_app("app/vendor/minitest")
gemfile bundled_app("app/Gemfile"), <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "minitest", :path => "vendor/minitest"
G
@@ -246,7 +272,7 @@ RSpec.shared_examples "bundle install --standalone" do
before do
bundle "config set --local path #{bundled_app("bundle")}"
install_gemfile <<-G, standalone: true, dir: cwd
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "very_simple_binary"
G
end
@@ -284,14 +310,14 @@ RSpec.shared_examples "bundle install --standalone" do
end
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)}"
+ source "https://gem.repo1"
gem "bar", :git => "#{lib_path("bar-1.0")}"
G
end
it "outputs a helpful error message" do
expect(err).to include("You have one or more invalid gemspecs that need to be fixed.")
- expect(err).to include("bar 1.0 has an invalid gemspec")
+ expect(err).to include("bar.gemspec is not valid")
end
end
@@ -300,7 +326,7 @@ RSpec.shared_examples "bundle install --standalone" do
build_git "devise", "1.0"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
gem "devise", :git => "#{lib_path("devise-1.0")}"
G
@@ -324,12 +350,12 @@ RSpec.shared_examples "bundle install --standalone" do
build_git "devise", "1.0"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
group :test do
gem "rspec"
- gem "rack-test"
+ gem "myrack-test"
end
G
bundle "config set --local path #{bundled_app("bundle")}"
@@ -359,7 +385,7 @@ RSpec.shared_examples "bundle install --standalone" do
RUBY
expect(out).to eq("2.3.2")
- expect(err).to eq("ZOMG LOAD ERROR")
+ expect(err_without_deprecations).to match(/cannot load such file -- spec/)
end
it "allows `without` configuration to limit the groups used in a standalone" do
@@ -377,7 +403,7 @@ RSpec.shared_examples "bundle install --standalone" do
RUBY
expect(out).to eq("2.3.2")
- expect(err).to eq("ZOMG LOAD ERROR")
+ expect(err_without_deprecations).to match(/cannot load such file -- spec/)
end
it "allows `path` configuration to change the location of the standalone bundle" do
@@ -411,7 +437,7 @@ RSpec.shared_examples "bundle install --standalone" do
RUBY
expect(out).to eq("2.3.2")
- expect(err).to eq("ZOMG LOAD ERROR")
+ expect(err_without_deprecations).to match(/cannot load such file -- spec/)
end
end
@@ -438,91 +464,61 @@ RSpec.shared_examples "bundle install --standalone" do
include_examples "common functionality"
end
end
+end
- describe "with --binstubs", bundler: "< 3" do
- before do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rails"
- G
- bundle "config set --local path #{bundled_app("bundle")}"
- bundle :install, standalone: true, binstubs: true, dir: cwd
- end
+RSpec.describe "bundle install --standalone run in a subdirectory" do
+ let(:cwd) { bundled_app("bob").tap(&:mkpath) }
- let(:expected_gems) do
- {
- "actionpack" => "2.3.2",
- "rails" => "2.3.2",
- }
- end
+ before do
+ gemfile <<-G
+ source "https://gem.repo1"
+ gem "rails"
+ G
+ end
- include_examples "common functionality"
+ it "generates the script in the proper place" do
+ bundle :install, standalone: true, dir: cwd
- it "creates stubs that use the standalone load path" do
- expect(sys_exec("bin/rails -v").chomp).to eql "2.3.2"
- end
+ expect(bundled_app("bundle/bundler/setup.rb")).to exist
+ end
- it "creates stubs that can be executed from anywhere" do
- require "tmpdir"
- sys_exec(%(#{bundled_app("bin/rails")} -v), dir: Dir.tmpdir)
- expect(out).to eq("2.3.2")
+ context "when path set to a relative path" do
+ before do
+ bundle "config set --local path bundle"
end
- it "creates stubs that can be symlinked" do
- 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")
- expect(out).to eq("2.3.2")
- end
+ it "generates the script in the proper place" do
+ bundle :install, standalone: true, dir: cwd
- it "creates stubs with the correct load path" do
- extension_line = File.read(bundled_app("bin/rails")).each_line.find {|line| line.include? "$:.unshift" }.strip
- expect(extension_line).to eq %($:.unshift File.expand_path "../bundle", __dir__)
+ expect(bundled_app("bundle/bundler/setup.rb")).to exist
end
end
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
- let(:cwd) { bundled_app("bob").tap(&:mkpath) }
-
- include_examples("bundle install --standalone")
-end
-
RSpec.describe "bundle install --standalone --local" do
before do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- system_gems "rack-1.0.0", path: default_bundle_path
+ system_gems "myrack-1.0.0", path: default_bundle_path
end
it "generates script pointing to system gems" do
bundle "install --standalone --local --verbose"
- expect(out).to include("Using rack 1.0.0")
+ expect(out).to include("Using myrack 1.0.0")
load_error_ruby <<-RUBY, "spec"
require "./bundler/setup"
- require "rack"
- puts RACK
+ require "myrack"
+ puts MYRACK
require "spec"
RUBY
expect(out).to eq("1.0.0")
- expect(err).to eq("ZOMG LOAD ERROR")
+ expect(err_without_deprecations).to match(/cannot load such file -- spec/)
end
end
diff --git a/spec/bundler/install/gems/win32_spec.rb b/spec/bundler/install/gems/win32_spec.rb
index 419b14ff0f..be37673aa1 100644
--- a/spec/bundler/install/gems/win32_spec.rb
+++ b/spec/bundler/install/gems/win32_spec.rb
@@ -4,22 +4,22 @@ RSpec.describe "bundle install with win32-generated lockfile" do
it "should read lockfile" do
File.open(bundled_app_lock, "wb") do |f|
f << "GEM\r\n"
- f << " remote: #{file_uri_for(gem_repo1)}/\r\n"
+ f << " remote: https://gem.repo1/\r\n"
f << " specs:\r\n"
f << "\r\n"
- f << " rack (1.0.0)\r\n"
+ f << " myrack (1.0.0)\r\n"
f << "\r\n"
f << "PLATFORMS\r\n"
f << " ruby\r\n"
f << "\r\n"
f << "DEPENDENCIES\r\n"
- f << " rack\r\n"
+ f << " myrack\r\n"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
- gem "rack"
+ gem "myrack"
G
end
end
diff --git a/spec/bundler/install/gemspecs_spec.rb b/spec/bundler/install/gemspecs_spec.rb
index 51aa0ed14f..dee8e547e4 100644
--- a/spec/bundler/install/gemspecs_spec.rb
+++ b/spec/bundler/install/gemspecs_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe "bundle install" do
it "still installs correctly" do
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "yaml_spec"
G
bundle :install
@@ -21,7 +21,7 @@ RSpec.describe "bundle install" do
build_lib "yaml_spec", gemspec: :yaml
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'yaml_spec', :path => "#{lib_path("yaml_spec-1.0")}"
G
expect(err).to be_empty
@@ -30,23 +30,23 @@ RSpec.describe "bundle install" do
it "should use gemspecs in the system cache when available" do
gemfile <<-G
- source "http://localtestserver.gem"
- gem 'rack'
+ source "http://localgemserver.test"
+ gem 'myrack'
G
- system_gems "rack-1.0.0", path: default_bundle_path
+ system_gems "myrack-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|
+ File.open("#{default_bundle_path}/specifications/myrack-1.0.0.gemspec", "w+") do |f|
spec = Gem::Specification.new do |s|
- s.name = "rack"
+ s.name = "myrack"
s.version = "1.0.0"
- s.add_runtime_dependency "activesupport", "2.3.2"
+ s.add_dependency "activesupport", "2.3.2"
end
f.write spec.to_ruby
end
bundle :install, artifice: "endpoint_marshal_fail" # force gemspec load
- expect(the_bundle).to include_gems "rack 1.0.0", "activesupport 2.3.2"
+ expect(the_bundle).to include_gems "myrack 1.0.0", "activesupport 2.3.2"
end
it "does not hang when gemspec has incompatible encoding" do
@@ -60,7 +60,7 @@ RSpec.describe "bundle install" do
G
install_gemfile <<-G, env: { "LANG" => "C" }
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gemspec
G
@@ -86,7 +86,7 @@ RSpec.describe "bundle install" do
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gemspec
G
@@ -102,7 +102,7 @@ RSpec.describe "bundle install" do
install_gemfile <<-G
ruby '#{RUBY_VERSION}', :engine_version => '#{RUBY_VERSION}', :engine => 'ruby'
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gemspec
G
expect(the_bundle).to include_gems "foo 1.0"
@@ -116,7 +116,7 @@ RSpec.describe "bundle install" do
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)}"
+ source "https://gem.repo1"
gemspec
G
expect(the_bundle).to include_gems "foo 1.0"
@@ -131,7 +131,7 @@ RSpec.describe "bundle install" do
install_gemfile <<-G, raise_on_error: false
ruby '#{RUBY_VERSION}', :engine_version => '#{RUBY_VERSION}', :engine => 'ruby', :patchlevel => '#{patchlevel}'
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gemspec
G
@@ -149,7 +149,7 @@ RSpec.describe "bundle install" do
install_gemfile <<-G, raise_on_error: false
ruby '#{version}', :engine_version => '#{version}', :engine => 'ruby'
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gemspec
G
@@ -157,5 +157,25 @@ RSpec.describe "bundle install" do
expect(err).to include("but your Gemfile specified")
expect(exitstatus).to eq(18)
end
+
+ it "validates gemspecs just once when everything installed and lockfile up to date" do
+ build_lib "foo"
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gemspec path: "#{lib_path("foo-1.0")}"
+
+ module Monkey
+ def validate(spec)
+ puts "Validate called on \#{spec.full_name}"
+ end
+ end
+ Bundler.rubygems.extend(Monkey)
+ G
+
+ bundle "install"
+
+ expect(out).to include("Validate called on foo-1.0").once
+ end
end
end
diff --git a/spec/bundler/install/git_spec.rb b/spec/bundler/install/git_spec.rb
index c8d574baf3..aa707a0222 100644
--- a/spec/bundler/install/git_spec.rb
+++ b/spec/bundler/install/git_spec.rb
@@ -6,23 +6,36 @@ RSpec.describe "bundle install" do
build_git "foo", "1.0", path: lib_path("foo")
install_gemfile <<-G, verbose: true
- source "#{file_uri_for(gem_repo1)}"
- gem "foo", :git => "#{file_uri_for(lib_path("foo"))}"
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo")}"
G
- 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(out).to include("Using foo 1.0 from #{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 revision hash of the gem repository when passed a relative local path" do
+ build_git "foo", "1.0", path: lib_path("foo")
+
+ relative_path = lib_path("foo").relative_path_from(bundled_app)
+ install_gemfile <<-G, verbose: true
+ source "https://gem.repo1"
+ gem "foo", :git => "#{relative_path}"
+ G
+
+ expect(out).to include("Using foo 1.0 from #{relative_path} (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 correct default branch", git: ">= 2.28.0" do
- build_git "foo", "1.0", path: lib_path("foo"), default_branch: "main"
+ build_git "foo", "1.0", path: lib_path("foo"), default_branch: "non-standard"
install_gemfile <<-G, verbose: true
- source "#{file_uri_for(gem_repo1)}"
- gem "foo", :git => "#{file_uri_for(lib_path("foo"))}"
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo")}"
G
- 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(out).to include("Using foo 1.0 from #{lib_path("foo")} (at non-standard@#{revision_for(lib_path("foo"))[0..6]})")
expect(the_bundle).to include_gems "foo 1.0", source: "git@#{lib_path("foo")}"
end
@@ -36,31 +49,31 @@ RSpec.describe "bundle install" do
update_git "foo", "3.0", path: lib_path("foo"), gemspec: true
install_gemfile <<-G, verbose: true
- source "#{file_uri_for(gem_repo1)}"
- gem "foo", :git => "#{file_uri_for(lib_path("foo"))}", :ref => "main~2"
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo")}", :ref => "main~2"
G
- expect(out).to include("Using foo 1.0 from #{file_uri_for(lib_path("foo"))} (at main~2@#{rev})")
+ expect(out).to include("Using foo 1.0 from #{lib_path("foo")} (at main~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, verbose: true
- expect(out).to include("Using foo 2.0 (was 1.0) from #{file_uri_for(lib_path("foo"))} (at main~2@#{rev2})")
+ expect(out).to include("Using foo 2.0 (was 1.0) from #{lib_path("foo")} (at main~2@#{rev2})")
expect(the_bundle).to include_gems "foo 2.0", source: "git@#{lib_path("foo")}"
end
- it "should allows git repos that are missing but not being installed" do
+ it "allows git repos that are missing but not being installed" do
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
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo-1.0")}", :group => :development
G
lockfile <<-L
GIT
- remote: #{file_uri_for(lib_path("foo-1.0"))}
+ remote: #{lib_path("foo-1.0")}
revision: #{revision}
specs:
foo (1.0)
@@ -87,9 +100,9 @@ RSpec.describe "bundle install" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "foo", :git => "#{file_uri_for(lib_path("gems"))}", :glob => "foo/*.gemspec"
- gem "zebra", :git => "#{file_uri_for(lib_path("gems"))}", :glob => "zebra/*.gemspec"
+ source "https://gem.repo2"
+ gem "foo", :git => "#{lib_path("gems")}", :glob => "foo/*.gemspec"
+ gem "zebra", :git => "#{lib_path("gems")}", :glob => "zebra/*.gemspec"
G
bundle "info foo"
@@ -112,7 +125,7 @@ RSpec.describe "bundle install" do
other_ref = other.ref_for("HEAD")
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "test", git: #{test.path.to_s.inspect}
gem "other", ref: #{other_ref.inspect}, git: #{other.path.to_s.inspect}
@@ -133,7 +146,7 @@ RSpec.describe "bundle install" do
other (1.0.0)
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
@@ -144,7 +157,7 @@ RSpec.describe "bundle install" do
test!
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
# If GH#6743 is present, the first `bundle install` will change the
@@ -178,11 +191,11 @@ RSpec.describe "bundle install" do
bundle "config set path vendor/bundle"
bundle "config set clean true"
install_gemfile <<-G, verbose: true
- source "#{file_uri_for(gem_repo1)}"
- gem "foo", :git => "#{file_uri_for(lib_path("foo"))}"
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo")}"
G
- expect(out).to include("Using foo 1.0 from #{file_uri_for(lib_path("foo"))} (at main@#{rev[0..6]})")
+ expect(out).to include("Using foo 1.0 from #{lib_path("foo")} (at main@#{rev[0..6]})")
expect(the_bundle).to include_gems "foo 1.0", source: "git@#{lib_path("foo")}"
old_lockfile = lockfile
@@ -191,15 +204,90 @@ RSpec.describe "bundle install" do
rev2 = revision_for(lib_path("foo"))
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 main@#{rev2[0..6]})")
+ expect(out).to include("Using foo 2.0 (was 1.0) from #{lib_path("foo")} (at main@#{rev2[0..6]})")
expect(out).to include("Removing foo (#{rev[0..11]})")
expect(the_bundle).to include_gems "foo 2.0", source: "git@#{lib_path("foo")}"
lockfile(old_lockfile)
bundle :install, verbose: true
- expect(out).to include("Using foo 1.0 from #{file_uri_for(lib_path("foo"))} (at main@#{rev[0..6]})")
+ expect(out).to include("Using foo 1.0 from #{lib_path("foo")} (at main@#{rev[0..6]})")
expect(the_bundle).to include_gems "foo 1.0", source: "git@#{lib_path("foo")}"
end
+
+ context "when install directory exists" do
+ let(:checkout_confirmation_log_message) { "Checking out revision" }
+ let(:using_foo_confirmation_log_message) { "Using foo 1.0 from #{lib_path("foo")} (at main@#{revision_for(lib_path("foo"))[0..6]})" }
+
+ context "and no contents besides .git directory are present" do
+ it "reinstalls gem" do
+ build_git "foo", "1.0", path: lib_path("foo")
+
+ gemfile = <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo")}"
+ G
+
+ install_gemfile gemfile, verbose: true
+
+ expect(out).to include(checkout_confirmation_log_message)
+ expect(out).to include(using_foo_confirmation_log_message)
+ expect(the_bundle).to include_gems "foo 1.0", source: "git@#{lib_path("foo")}"
+
+ # validate that the installed directory exists and has some expected contents
+ install_directory = default_bundle_path("bundler/gems/foo-#{revision_for(lib_path("foo"))[0..11]}")
+ dot_git_directory = install_directory.join(".git")
+ lib_directory = install_directory.join("lib")
+ gemspec = install_directory.join("foo.gemspec")
+ expect([install_directory, dot_git_directory, lib_directory, gemspec]).to all exist
+
+ # remove all elements in the install directory except .git directory
+ FileUtils.rm_r(lib_directory)
+ gemspec.delete
+
+ expect(dot_git_directory).to exist
+ expect(lib_directory).not_to exist
+ expect(gemspec).not_to exist
+
+ # rerun bundle install
+ install_gemfile gemfile, verbose: true
+
+ expect(out).to include(checkout_confirmation_log_message)
+ expect(out).to include(using_foo_confirmation_log_message)
+ expect(the_bundle).to include_gems "foo 1.0", source: "git@#{lib_path("foo")}"
+
+ # validate that it reinstalls all components
+ expect([install_directory, dot_git_directory, lib_directory, gemspec]).to all exist
+ end
+ end
+
+ context "and contents besides .git directory are present" do
+ # we want to confirm that the change to try to detect partial installs and reinstall does not
+ # result in repeatedly reinstalling the gem when it is fully installed
+ it "does not reinstall gem" do
+ build_git "foo", "1.0", path: lib_path("foo")
+
+ gemfile = <<-G
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo")}"
+ G
+
+ install_gemfile gemfile, verbose: true
+
+ expect(out).to include(checkout_confirmation_log_message)
+ expect(out).to include(using_foo_confirmation_log_message)
+ expect(the_bundle).to include_gems "foo 1.0", source: "git@#{lib_path("foo")}"
+
+ # rerun bundle install
+ install_gemfile gemfile, verbose: true
+
+ # it isn't altogether straight-forward to validate that bundle didn't do soething on the second run, however,
+ # the presence of the 2nd log message confirms install got past the point that it would have logged the above if
+ # it was going to
+ expect(out).not_to include(checkout_confirmation_log_message)
+ expect(out).to include(using_foo_confirmation_log_message)
+ end
+ end
+ end
end
end
diff --git a/spec/bundler/install/global_cache_spec.rb b/spec/bundler/install/global_cache_spec.rb
index 0da4de05b2..0a7daf173c 100644
--- a/spec/bundler/install/global_cache_spec.rb
+++ b/spec/bundler/install/global_cache_spec.rb
@@ -7,174 +7,217 @@ RSpec.describe "global gem caching" do
let(:source) { "http://localgemserver.test" }
let(:source2) { "http://gemserver.example.org" }
+ def cache_base
+ home(".bundle", "cache", "gems")
+ end
+
def source_global_cache(*segments)
- home(".bundle", "cache", "gems", "localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", *segments)
+ cache_base.join("localgemserver.test.80.dd34752a738ee965a2a4298dc16db6c5", *segments)
end
def source2_global_cache(*segments)
- home(".bundle", "cache", "gems", "gemserver.example.org.80.1ae1663619ffe0a3c9d97712f44c705b", *segments)
+ cache_base.join("gemserver.example.org.80.1ae1663619ffe0a3c9d97712f44c705b", *segments)
end
it "caches gems into the global cache on download" do
install_gemfile <<-G, artifice: "compact_index"
source "#{source}"
- gem "rack"
+ gem "myrack"
G
- expect(the_bundle).to include_gems "rack 1.0.0"
- expect(source_global_cache("rack-1.0.0.gem")).to exist
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ expect(source_global_cache("myrack-1.0.0.gem")).to exist
end
it "uses globally cached gems if they exist" do
source_global_cache.mkpath
- FileUtils.cp(gem_repo1("gems/rack-1.0.0.gem"), source_global_cache("rack-1.0.0.gem"))
+ FileUtils.cp(gem_repo1("gems/myrack-1.0.0.gem"), source_global_cache("myrack-1.0.0.gem"))
install_gemfile <<-G, artifice: "compact_index_no_gem"
source "#{source}"
- gem "rack"
+ gem "myrack"
G
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 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"))
+ FileUtils.touch(source_global_cache("myrack-1.0.0.gem"))
install_gemfile <<-G, artifice: "compact_index_no_gem", raise_on_error: false
source "#{source}"
- gem "rack"
+ gem "myrack"
G
- expect(err).to include("Gem::Package::FormatError: package metadata is missing in #{source_global_cache("rack-1.0.0.gem")}")
+ expect(err).to include("Gem::Package::FormatError: package metadata is missing in #{source_global_cache("myrack-1.0.0.gem")}")
+ end
+
+ it "uses a shorter path for the cache to not hit filesystem limits" do
+ install_gemfile <<-G, artifice: "compact_index", verbose: true
+ source "http://#{"a" * 255}.test"
+ gem "myrack"
+ G
+
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ source_segment = "a" * 222 + ".a3cb26de2edfce9f509a65c611d99c4b"
+ source_cache = cache_base.join(source_segment)
+ cached_gem = source_cache.join("myrack-1.0.0.gem")
+ expect(cached_gem).to exist
+ ensure
+ # We cleanup dummy files created by this spec manually because due to a
+ # Ruby on Windows bug, `FileUtils.rm_rf` (run in our global after hook)
+ # cannot traverse directories with such long names. So we delete
+ # everything explicitly to workaround the bug. An alternative workaround
+ # would be to shell out to `rm -rf`. That also works fine, but I went with
+ # the more verbose and explicit approach. This whole ensure block can be
+ # removed once/if https://bugs.ruby-lang.org/issues/21177 is fixed, and
+ # once the fix propagates to all supported rubies.
+ File.delete cached_gem
+ Dir.rmdir source_cache
+
+ File.delete compact_index_cache_path.join(source_segment, "info", "myrack")
+ Dir.rmdir compact_index_cache_path.join(source_segment, "info")
+ File.delete compact_index_cache_path.join(source_segment, "info-etags", "myrack-92f3313ce5721296f14445c3a6b9c073")
+ Dir.rmdir compact_index_cache_path.join(source_segment, "info-etags")
+ Dir.rmdir compact_index_cache_path.join(source_segment, "info-special-characters")
+ File.delete compact_index_cache_path.join(source_segment, "versions")
+ File.delete compact_index_cache_path.join(source_segment, "versions.etag")
+ Dir.rmdir compact_index_cache_path.join(source_segment)
end
describe "when the same gem from different sources is installed" do
it "should use the appropriate one from the global cache" do
+ bundle "config path.system true"
+
install_gemfile <<-G, artifice: "compact_index"
source "#{source}"
- gem "rack"
+ gem "myrack"
G
- 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
+ pristine_system_gems
+ expect(the_bundle).not_to include_gems "myrack 1.0.0"
+ expect(source_global_cache("myrack-1.0.0.gem")).to exist
+ # myrack 1.0.0 is not installed and it is in the global cache
install_gemfile <<-G, artifice: "compact_index"
source "#{source2}"
- gem "rack", "0.9.1"
+ gem "myrack", "0.9.1"
G
- 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
+ pristine_system_gems
+ expect(the_bundle).not_to include_gems "myrack 0.9.1"
+ expect(source2_global_cache("myrack-0.9.1.gem")).to exist
+ # myrack 0.9.1 is not installed and it is in the global cache
gemfile <<-G
source "#{source}"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
G
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"
- simulate_new_machine
+ # myrack 1.0.0 is installed and myrack 0.9.1 is not
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ expect(the_bundle).not_to include_gems "myrack 0.9.1"
+ pristine_system_gems
gemfile <<-G
source "#{source2}"
- gem "rack", "0.9.1"
+ gem "myrack", "0.9.1"
G
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"
+ # myrack 0.9.1 is installed and myrack 1.0.0 is not
+ expect(the_bundle).to include_gems "myrack 0.9.1"
+ expect(the_bundle).not_to include_gems "myrack 1.0.0"
end
it "should not install if the wrong source is provided" do
+ bundle "config path.system true"
+
gemfile <<-G
source "#{source}"
- gem "rack"
+ gem "myrack"
G
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
+ pristine_system_gems
+ expect(the_bundle).not_to include_gems "myrack 1.0.0"
+ expect(source_global_cache("myrack-1.0.0.gem")).to exist
+ # myrack 1.0.0 is not installed and it is in the global cache
gemfile <<-G
source "#{source2}"
- gem "rack", "0.9.1"
+ gem "myrack", "0.9.1"
G
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
+ pristine_system_gems
+ expect(the_bundle).not_to include_gems "myrack 0.9.1"
+ expect(source2_global_cache("myrack-0.9.1.gem")).to exist
+ # myrack 0.9.1 is not installed and it is in the global cache
gemfile <<-G
source "#{source2}"
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
G
- expect(source_global_cache("rack-1.0.0.gem")).to exist
- expect(source2_global_cache("rack-0.9.1.gem")).to exist
+ expect(source_global_cache("myrack-1.0.0.gem")).to exist
+ expect(source2_global_cache("myrack-0.9.1.gem")).to exist
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"
+ # myrack 1.0.0 is not installed and myrack 0.9.1 is not
+ expect(the_bundle).not_to include_gems "myrack 1.0.0"
+ expect(the_bundle).not_to include_gems "myrack 0.9.1"
gemfile <<-G
source "#{source}"
- gem "rack", "0.9.1"
+ gem "myrack", "0.9.1"
G
- expect(source_global_cache("rack-1.0.0.gem")).to exist
- expect(source2_global_cache("rack-0.9.1.gem")).to exist
+ expect(source_global_cache("myrack-1.0.0.gem")).to exist
+ expect(source2_global_cache("myrack-0.9.1.gem")).to exist
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"
+ # myrack 0.9.1 is not installed and myrack 1.0.0 is not
+ expect(the_bundle).not_to include_gems "myrack 0.9.1"
+ expect(the_bundle).not_to include_gems "myrack 1.0.0"
end
end
describe "when installing gems from a different directory" do
it "uses the global cache as a source" do
+ bundle "config path.system true"
+
install_gemfile <<-G, artifice: "compact_index"
source "#{source}"
- gem "rack"
+ gem "myrack"
gem "activesupport"
G
# Both gems are installed and in the global cache
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 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("myrack-1.0.0.gem")).to exist
expect(source_global_cache("activesupport-2.3.5.gem")).to exist
- simulate_new_machine
+ pristine_system_gems
# 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 "myrack 1.0.0"
expect(the_bundle).not_to include_gems "activesupport 2.3.5"
install_gemfile <<-G, artifice: "compact_index_no_gem"
source "#{source}"
- gem "rack"
+ gem "myrack"
G
- # rack is installed and both are in the global cache
- expect(the_bundle).to include_gems "rack 1.0.0"
+ # myrack is installed and both are in the global cache
+ expect(the_bundle).to include_gems "myrack 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("myrack-1.0.0.gem")).to exist
expect(source_global_cache("activesupport-2.3.5.gem")).to exist
create_file bundled_app2("gems.rb"), <<-G
@@ -183,9 +226,9 @@ RSpec.describe "global gem caching" do
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 "myrack 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("myrack-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
@@ -193,10 +236,10 @@ RSpec.describe "global gem caching" do
bundle :install, artifice: "compact_index_no_gem", dir: bundled_app2
# activesupport 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 "myrack 1.0.0", dir: bundled_app2
expect(the_bundle).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("myrack-1.0.0.gem")).to exist
expect(source_global_cache("activesupport-2.3.5.gem")).to exist
end
end
@@ -205,13 +248,14 @@ RSpec.describe "global gem caching" do
describe "extension caching" do
it "works" do
skip "gets incorrect ref in path" if Gem.win_platform?
+ skip "fails for unknown reason when run by ruby-core" if ruby_core?
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
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "very_simple_binary"
gem "very_simple_git_binary", :git => "#{lib_path("very_simple_git_binary-1.0")}"
@@ -219,7 +263,7 @@ RSpec.describe "global gem caching" do
G
gem_binary_cache = home(".bundle", "cache", "extensions", local_platform.to_s, Bundler.ruby_scope,
- Digest(:MD5).hexdigest("#{gem_repo1}/"), "very_simple_binary-1.0")
+ "gem.repo1.443.#{Digest(:MD5).hexdigest("gem.repo1.443./")}", "very_simple_binary-1.0")
git_binary_cache = home(".bundle", "cache", "extensions", local_platform.to_s, Bundler.ruby_scope,
"very_simple_git_binary-1.0-#{revision}", "very_simple_git_binary-1.0")
@@ -232,7 +276,7 @@ RSpec.describe "global gem caching" do
R
expect(out).to eq "VERY_SIMPLE_BINARY_IN_C\nVERY_SIMPLE_GIT_BINARY_IN_C"
- FileUtils.rm_rf Dir[home(".bundle", "cache", "extensions", "**", "*binary_c*")]
+ FileUtils.rm_r Dir[home(".bundle", "cache", "extensions", "**", "*binary_c*")]
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__)" }
diff --git a/spec/bundler/install/path_spec.rb b/spec/bundler/install/path_spec.rb
index 0a30e402b7..8c0793642b 100644
--- a/spec/bundler/install/path_spec.rb
+++ b/spec/bundler/install/path_spec.rb
@@ -3,27 +3,27 @@
RSpec.describe "bundle install" 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'"
+ build_gem "myrack", "1.0.0", to_system: true do |s|
+ s.write "lib/myrack.rb", "puts 'FAIL'"
end
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
end
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"
+ expect(the_bundle).to include_gems "myrack 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
+ run "require 'myrack'", raise_on_error: false
expect(out).to include("FAIL")
end
@@ -35,7 +35,7 @@ RSpec.describe "bundle install" do
bundle :install, dir: dir
expect(out).to include("installed into `./vendor/bundle`")
- dir.rmtree
+ FileUtils.rm_rf dir
end
it "prints a message to let the user know where gems where installed" do
@@ -44,56 +44,44 @@ RSpec.describe "bundle install" do
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", raise_on_error: false
- expect(err).to include("Please choose only one option.")
- expect(exitstatus).to eq(15)
+ it "installs the bundle relatively to repository root, when Bundler run from the same directory" do
+ bundle "config path vendor/bundle", dir: bundled_app.parent
+ bundle "install --gemfile='#{bundled_app}/Gemfile'", dir: bundled_app.parent
+ expect(out).to include("installed into `./bundled_app/vendor/bundle`")
+ expect(bundled_app("vendor/bundle")).to be_directory
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
- it "remembers to disable system gems after the first time with bundle --path vendor/bundle", bundler: "< 3" do
- bundle "install --path vendor/bundle"
- FileUtils.rm_rf bundled_app("vendor")
- bundle "install"
-
- expect(vendored_gems("gems/rack-1.0.0")).to be_directory
- expect(the_bundle).to include_gems "rack 1.0.0"
+ it "installs the bundle relatively to repository root, when Bundler run from a different directory" do
+ bundle "config path vendor/bundle", dir: bundled_app
+ bundle "install --gemfile='#{bundled_app}/Gemfile'", dir: bundled_app.parent
+ expect(out).to include("installed into `./bundled_app/vendor/bundle`")
+ expect(bundled_app("vendor/bundle")).to be_directory
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
- context "with path_relative_to_cwd set to true" do
- before { bundle "config set path_relative_to_cwd true" }
-
- it "installs the bundle relatively to current working directory", bundler: "< 3" do
- 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
- 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"
+ it "installs the standalone bundle relative to the cwd" do
+ 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 :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
+ 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
describe "when BUNDLE_PATH or the global path config is set" do
before :each do
- build_lib "rack", "1.0.0", to_system: true do |s|
- s.write "lib/rack.rb", "raise 'FAIL'"
+ build_lib "myrack", "1.0.0", to_system: true do |s|
+ s.write "lib/myrack.rb", "raise 'FAIL'"
end
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
end
@@ -112,9 +100,9 @@ RSpec.describe "bundle install" do
bundle "config set --local path vendor/bundle"
bundle :install
- expect(vendored_gems("gems/rack-1.0.0")).to be_directory
+ expect(vendored_gems("gems/myrack-1.0.0")).to be_directory
expect(bundled_app("vendor2")).not_to be_directory
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "installs gems to ." do
@@ -123,9 +111,9 @@ RSpec.describe "bundle install" do
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) }
+ paths_to_exist = %w[cache/myrack-1.0.0.gem gems/myrack-1.0.0 specifications/myrack-1.0.0.gemspec].map {|path| bundled_app(Bundler.ruby_scope, path) }
expect(paths_to_exist).to all exist
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "installs gems to the path" do
@@ -133,8 +121,8 @@ RSpec.describe "bundle install" do
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"
+ expect(bundled_app("vendor", Bundler.ruby_scope, "gems/myrack-1.0.0")).to be_directory
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "installs gems to the path relative to root when relative" do
@@ -143,8 +131,8 @@ RSpec.describe "bundle install" do
FileUtils.mkdir_p bundled_app("lol")
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"
+ expect(bundled_app("vendor", Bundler.ruby_scope, "gems/myrack-1.0.0")).to be_directory
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
end
@@ -154,26 +142,26 @@ RSpec.describe "bundle install" do
bundle :install
- expect(vendored_gems("gems/rack-1.0.0")).to be_directory
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(vendored_gems("gems/myrack-1.0.0")).to be_directory
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "sets BUNDLE_PATH as the first argument to bundle install" do
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"
+ expect(vendored_gems("gems/myrack-1.0.0")).to be_directory
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
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
+ build_gem "myrack", "1.1.0", to_system: true
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"
+ expect(vendored_gems("gems/myrack-1.0.0")).to be_directory
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "re-installs gems whose extensions have been deleted" do
@@ -182,7 +170,7 @@ RSpec.describe "bundle install" do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "very_simple_binary"
G
@@ -193,7 +181,7 @@ RSpec.describe "bundle install" do
expect(vendored_gems("extensions")).to be_directory
expect(the_bundle).to include_gems "very_simple_binary 1.0", source: "remote1"
- vendored_gems("extensions").rmtree
+ FileUtils.rm_rf vendored_gems("extensions")
run "require 'very_simple_binary_c'", raise_on_error: false
expect(err).to include("Bundler::GemNotFound")
@@ -214,8 +202,8 @@ RSpec.describe "bundle install" do
it "reports the file exists" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle "config set --local path bundle"
diff --git a/spec/bundler/install/prereleases_spec.rb b/spec/bundler/install/prereleases_spec.rb
index 629eb89dac..9f764d127c 100644
--- a/spec/bundler/install/prereleases_spec.rb
+++ b/spec/bundler/install/prereleases_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe "bundle install" do
describe "when prerelease gems are available" do
it "finds prereleases" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "not_released"
G
expect(the_bundle).to include_gems "not_released 1.0.pre"
@@ -21,7 +21,7 @@ RSpec.describe "bundle install" do
it "uses regular releases if available" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "has_prerelease"
G
expect(the_bundle).to include_gems "has_prerelease 1.0"
@@ -29,7 +29,7 @@ RSpec.describe "bundle install" do
it "uses prereleases if requested" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "has_prerelease", "1.1.pre"
G
expect(the_bundle).to include_gems "has_prerelease 1.1.pre"
@@ -38,17 +38,17 @@ RSpec.describe "bundle install" do
describe "when prerelease gems are not available" do
it "still works" do
- build_repo gem_repo3 do
- build_gem "rack"
+ build_repo3 do
+ build_gem "myrack"
end
- FileUtils.rm_rf Dir[gem_repo3("prerelease*")]
+ FileUtils.rm_r Dir[gem_repo3("prerelease*")]
install_gemfile <<-G
- source "#{file_uri_for(gem_repo3)}"
- gem "rack"
+ source "https://gem.repo3"
+ gem "myrack"
G
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
end
end
diff --git a/spec/bundler/install/process_lock_spec.rb b/spec/bundler/install/process_lock_spec.rb
index 1f8c62f26e..344caa3a93 100644
--- a/spec/bundler/install/process_lock_spec.rb
+++ b/spec/bundler/install/process_lock_spec.rb
@@ -8,23 +8,23 @@ RSpec.describe "process lock spec" do
thread = Thread.new do
Bundler::ProcessLock.lock(default_bundle_path) do
sleep 1 # ignore quality_spec
- expect(the_bundle).not_to include_gems "rack 1.0"
+ expect(the_bundle).not_to include_gems "myrack 1.0"
end
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
thread.join
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
context "when creating a lock raises Errno::ENOTSUP" do
before { allow(File).to receive(:open).and_raise(Errno::ENOTSUP) }
- it "skips creating the lock file and yields" do
+ it "skips creating the lockfile and yields" do
processed = false
Bundler::ProcessLock.lock(default_bundle_path) { processed = true }
@@ -35,7 +35,7 @@ RSpec.describe "process lock spec" do
context "when creating a lock raises Errno::EPERM" do
before { allow(File).to receive(:open).and_raise(Errno::EPERM) }
- it "skips creating the lock file and yields" do
+ it "skips creating the lockfile and yields" do
processed = false
Bundler::ProcessLock.lock(default_bundle_path) { processed = true }
@@ -46,7 +46,7 @@ RSpec.describe "process lock spec" do
context "when creating a lock raises Errno::EROFS" do
before { allow(File).to receive(:open).and_raise(Errno::EROFS) }
- it "skips creating the lock file and yields" do
+ it "skips creating the lockfile and yields" do
processed = false
Bundler::ProcessLock.lock(default_bundle_path) { processed = true }
diff --git a/spec/bundler/install/redownload_spec.rb b/spec/bundler/install/redownload_spec.rb
deleted file mode 100644
index 3a72c356d9..0000000000
--- a/spec/bundler/install/redownload_spec.rb
+++ /dev/null
@@ -1,91 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe "bundle install" do
- before :each do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- G
- end
-
- shared_examples_for "an option to force redownloading gems" do
- it "re-installs installed gems" do
- rack_lib = default_bundle_path("gems/rack-1.0.0/lib/rack.rb")
-
- bundle :install
- rack_lib.open("w") {|f| f.write("blah blah blah") }
- 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")
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
-
- it "works on first bundle install" do
- bundle :install, flag => true
-
- expect(out).to include "Installing rack 1.0.0"
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
-
- context "with a git gem" do
- let!(:ref) { build_git("foo", "1.0").ref_for("HEAD", 11) }
-
- before do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "foo", :git => "#{lib_path("foo-1.0")}"
- G
- end
-
- it "re-installs installed gems" do
- foo_lib = default_bundle_path("bundler/gems/foo-1.0-#{ref}/lib/foo.rb")
-
- bundle :install
- foo_lib.open("w") {|f| f.write("blah blah blah") }
- 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
-
- expect(the_bundle).to include_gems "foo 1.0"
- end
- end
- end
-
- describe "with --force", bundler: 2 do
- it_behaves_like "an option to force redownloading gems" do
- let(:flag) { "force" }
- end
-
- it "shows a deprecation when single flag passed" do
- 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"
- expect(err).to include "[DEPRECATED] The `--force` option has been renamed to `--redownload`"
- end
- end
-
- describe "with --redownload" do
- it_behaves_like "an option to force redownloading gems" do
- let(:flag) { "redownload" }
- end
-
- it "does not show a deprecation when single flag passed" do
- 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"
- expect(err).not_to include "[DEPRECATED] The `--force` option has been renamed to `--redownload`"
- end
- end
-end
diff --git a/spec/bundler/install/security_policy_spec.rb b/spec/bundler/install/security_policy_spec.rb
index befeb81da5..e7f64dc227 100644
--- a/spec/bundler/install/security_policy_spec.rb
+++ b/spec/bundler/install/security_policy_spec.rb
@@ -9,8 +9,8 @@ RSpec.describe "policies with unsigned gems" do
before do
build_security_repo
gemfile <<-G
- source "#{file_uri_for(security_repo)}"
- gem "rack"
+ source "https://gems.security"
+ gem "myrack"
gem "signed_gem"
G
end
@@ -18,7 +18,7 @@ RSpec.describe "policies with unsigned gems" do
it "will work after you try to deploy without a lock" do
bundle "install --deployment", raise_on_error: false
bundle :install
- expect(the_bundle).to include_gems "rack 1.0", "signed_gem 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0", "signed_gem 1.0"
end
it "will fail when given invalid security policy" do
@@ -45,7 +45,7 @@ RSpec.describe "policies with signed gems and no CA" do
before do
build_security_repo
gemfile <<-G
- source "#{file_uri_for(security_repo)}"
+ source "https://gems.security"
gem "signed_gem"
G
end
diff --git a/spec/bundler/install/yanked_spec.rb b/spec/bundler/install/yanked_spec.rb
index 5aeabd2f23..08d6bbdc2a 100644
--- a/spec/bundler/install/yanked_spec.rb
+++ b/spec/bundler/install/yanked_spec.rb
@@ -1,16 +1,14 @@
# frozen_string_literal: true
RSpec.context "when installing a bundle that includes yanked gems" do
- before(:each) do
+ it "throws an error when the original gem version is yanked" do
build_repo4 do
build_gem "foo", "9.0.0"
end
- end
- it "throws an error when the original gem version is yanked" do
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo4)}
+ remote: https://gem.repo4
specs:
foo (10.0.0)
@@ -23,19 +21,42 @@ RSpec.context "when installing a bundle that includes yanked gems" do
L
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "foo", "10.0.0"
G
expect(err).to include("Your bundle is locked to foo (10.0.0)")
end
- context "when a re-resolve is necessary, and a yanked version is considered by the resolver" do
+ context "when a platform specific yanked version is included in the lockfile, and a generic variant is available remotely" do
+ let(:original_lockfile) do
+ <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ actiontext (6.1.6)
+ nokogiri (>= 1.8)
+ foo (1.0.0)
+ nokogiri (1.13.8-#{Bundler.local_platform})
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ actiontext (= 6.1.6)
+ foo (= 1.0.0)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
before do
skip "Materialization on Windows is not yet strict, so the example does not detect the gem has been yanked" if Gem.win_platform?
build_repo4 do
- build_gem "foo", "1.0.0", "1.0.1"
+ build_gem "foo", "1.0.0"
+ build_gem "foo", "1.0.1"
build_gem "actiontext", "6.1.7" do |s|
s.add_dependency "nokogiri", ">= 1.8"
end
@@ -49,58 +70,58 @@ RSpec.context "when installing a bundle that includes yanked gems" do
end
gemfile <<~G
- source "#{source_uri}"
- gem "foo", "1.0.1"
+ source "https://gem.repo4"
+ gem "foo", "1.0.0"
gem "actiontext", "6.1.6"
G
- lockfile <<~L
- GEM
- remote: #{source_uri}/
- specs:
- actiontext (6.1.6)
- nokogiri (>= 1.8)
- foo (1.0.0)
- nokogiri (1.13.8-#{Bundler.local_platform})
+ lockfile original_lockfile
+ end
- PLATFORMS
- #{lockfile_platforms}
+ context "and a re-resolve is necessary" do
+ before do
+ gemfile gemfile.sub('"foo", "1.0.0"', '"foo", "1.0.1"')
+ end
- DEPENDENCIES
- actiontext (= 6.1.6)
- foo (= 1.0.0)
+ it "reresolves, and replaces the yanked gem with the generic version, printing a warning, when the old index is used" do
+ bundle "install", artifice: "endpoint", verbose: true
- BUNDLED WITH
- #{Bundler::VERSION}
- L
- end
-
- context "and the old index is used" do
- let(:source_uri) { file_uri_for(gem_repo4) }
+ expect(out).to include("Installing nokogiri 1.13.8").and include("Installing foo 1.0.1")
+ expect(lockfile).to eq(original_lockfile.sub("nokogiri (1.13.8-#{Bundler.local_platform})", "nokogiri (1.13.8)").gsub("1.0.0", "1.0.1"))
+ expect(err).to include("Some locked specs have possibly been yanked (nokogiri-1.13.8-#{Bundler.local_platform}). Ignoring them...")
+ end
- it "reports the yanked gem properly" do
- bundle "install", raise_on_error: false
+ it "reresolves, and replaces the yanked gem with the generic version, printing a warning, when the compact index API is used" do
+ bundle "install", artifice: "compact_index", verbose: true
- expect(err).to include("Your bundle is locked to nokogiri (1.13.8-#{Bundler.local_platform})")
+ expect(out).to include("Installing nokogiri 1.13.8").and include("Installing foo 1.0.1")
+ expect(lockfile).to eq(original_lockfile.sub("nokogiri (1.13.8-#{Bundler.local_platform})", "nokogiri (1.13.8)").gsub("1.0.0", "1.0.1"))
+ expect(err).to include("Some locked specs have possibly been yanked (nokogiri-1.13.8-#{Bundler.local_platform}). Ignoring them...")
end
end
- context "and the compact index API is used" do
- let(:source_uri) { "https://gem.repo4" }
+ it "reports the yanked gem properly when the old index is used" do
+ bundle "install", artifice: "endpoint", raise_on_error: false
- it "reports the yanked gem properly" do
- bundle "install", artifice: "compact_index", raise_on_error: false
+ expect(err).to include("Your bundle is locked to nokogiri (1.13.8-#{Bundler.local_platform})")
+ end
- expect(err).to include("Your bundle is locked to nokogiri (1.13.8-#{Bundler.local_platform})")
- end
+ it "reports the yanked gem properly when the compact index API is used" do
+ bundle "install", artifice: "compact_index", raise_on_error: false
+
+ expect(err).to include("Your bundle is locked to nokogiri (1.13.8-#{Bundler.local_platform})")
end
end
it "throws the original error when only the Gemfile specifies a gem version that doesn't exist" do
+ build_repo4 do
+ build_gem "foo", "9.0.0"
+ end
+
bundle "config set force_ruby_platform true"
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "foo", "10.0.0"
G
@@ -120,7 +141,7 @@ RSpec.context "when resolving a bundle that includes yanked gems, but unlocking
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo4)}
+ remote: https://gem.repo4
specs:
foo (9.0.0)
bar (1.0.0)
@@ -133,11 +154,11 @@ RSpec.context "when resolving a bundle that includes yanked gems, but unlocking
bar
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "foo"
gem "bar"
G
@@ -148,7 +169,7 @@ RSpec.context "when resolving a bundle that includes yanked gems, but unlocking
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
bar (2.0.0)
foo (9.0.0)
@@ -161,7 +182,7 @@ RSpec.context "when resolving a bundle that includes yanked gems, but unlocking
foo
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
@@ -169,65 +190,65 @@ end
RSpec.context "when using gem before installing" do
it "does not suggest the author has yanked the gem" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "0.9.1"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
G
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo1)}
+ remote: https://gem.repo1
specs:
- rack (0.9.1)
+ myrack (0.9.1)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack (= 0.9.1)
+ myrack (= 0.9.1)
L
bundle :list, raise_on_error: false
- expect(err).to include("Could not find rack-0.9.1 in locally installed gems")
- expect(err).to_not include("Your bundle is locked to rack (0.9.1) from")
- 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.")
+ expect(err).to include("Could not find myrack-0.9.1 in locally installed gems")
+ expect(err).to_not include("Your bundle is locked to myrack (0.9.1) from")
+ expect(err).to_not include("If you haven't changed sources, that means the author of myrack (0.9.1) has removed it.")
+ expect(err).to_not include("You'll need to update your bundle to a different version of myrack (0.9.1) that hasn't been removed in order to install.")
# Check error message is still correct when multiple platforms are locked
lockfile lockfile.gsub(/PLATFORMS\n #{lockfile_platforms}/m, "PLATFORMS\n #{lockfile_platforms("ruby")}")
bundle :list, raise_on_error: false
- expect(err).to include("Could not find rack-0.9.1 in locally installed gems")
+ expect(err).to include("Could not find myrack-0.9.1 in locally installed gems")
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"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
+ gem "myrack_middleware", "1.0"
G
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo1)}
+ remote: https://gem.repo1
specs:
- rack (0.9.1)
- rack_middleware (1.0)
+ myrack (0.9.1)
+ myrack_middleware (1.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack (= 0.9.1)
- rack_middleware (1.0)
+ myrack (= 0.9.1)
+ myrack_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 locally installed gems")
+ expect(err).to include("Could not find myrack-0.9.1, myrack_middleware-1.0 in locally installed gems")
expect(err).to include("Install missing gems with `bundle install`.")
- expect(err).to_not include("Your bundle is locked to rack (0.9.1) from")
- 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.")
+ expect(err).to_not include("Your bundle is locked to myrack (0.9.1) from")
+ expect(err).to_not include("If you haven't changed sources, that means the author of myrack (0.9.1) has removed it.")
+ expect(err).to_not include("You'll need to update your bundle to a different version of myrack (0.9.1) that hasn't been removed in order to install.")
end
end
diff --git a/spec/bundler/lock/git_spec.rb b/spec/bundler/lock/git_spec.rb
index ad13e8ffc6..c9f76115dc 100644
--- a/spec/bundler/lock/git_spec.rb
+++ b/spec/bundler/lock/git_spec.rb
@@ -1,21 +1,25 @@
# frozen_string_literal: true
RSpec.describe "bundle lock with git gems" do
- before :each do
+ let(:install_gemfile_with_foo_as_a_git_dependency) do
build_git "foo"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'foo', :git => "#{lib_path("foo-1.0")}"
G
end
it "doesn't break right after running lock" do
+ install_gemfile_with_foo_as_a_git_dependency
+
expect(the_bundle).to include_gems "foo 1.0.0"
end
it "doesn't print errors even if running lock after removing the cache" do
- FileUtils.rm_rf(Dir[default_cache_path("git/foo-1.0-*")].first)
+ install_gemfile_with_foo_as_a_git_dependency
+
+ FileUtils.rm_r(Dir[default_cache_path("git/foo-1.0-*")].first)
bundle "lock --verbose"
@@ -23,8 +27,10 @@ RSpec.describe "bundle lock with git gems" do
end
it "prints a proper error when changing a locked Gemfile to point to a bad branch" do
+ install_gemfile_with_foo_as_a_git_dependency
+
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'foo', :git => "#{lib_path("foo-1.0")}", :branch => "bad"
G
@@ -34,6 +40,8 @@ RSpec.describe "bundle lock with git gems" do
end
it "prints a proper error when installing a Gemfile with a locked ref that does not exist" do
+ install_gemfile_with_foo_as_a_git_dependency
+
lockfile <<~L
GIT
remote: #{lib_path("foo-1.0")}
@@ -42,7 +50,7 @@ RSpec.describe "bundle lock with git gems" do
foo (1.0)
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
@@ -52,7 +60,7 @@ RSpec.describe "bundle lock with git gems" do
foo!
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "install", raise_on_error: false
@@ -61,6 +69,8 @@ RSpec.describe "bundle lock with git gems" do
end
it "locks a git source to the current ref" do
+ install_gemfile_with_foo_as_a_git_dependency
+
update_git "foo"
bundle :install
@@ -73,6 +83,8 @@ RSpec.describe "bundle lock with git gems" do
end
it "properly clones a git source locked to an out of date ref" do
+ install_gemfile_with_foo_as_a_git_dependency
+
update_git "foo"
bundle :install, env: { "BUNDLE_PATH" => "foo" }
@@ -80,6 +92,8 @@ RSpec.describe "bundle lock with git gems" do
end
it "properly fetches a git source locked to an unreachable ref" do
+ install_gemfile_with_foo_as_a_git_dependency
+
# Create a commit and make it unreachable
git "checkout -b foo ", lib_path("foo-1.0")
unreachable_sha = update_git("foo").ref_for("HEAD")
@@ -87,7 +101,7 @@ RSpec.describe "bundle lock with git gems" do
git "branch -D foo ", lib_path("foo-1.0")
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'foo', :git => "#{lib_path("foo-1.0")}"
G
@@ -99,7 +113,7 @@ RSpec.describe "bundle lock with git gems" do
foo (1.0)
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
@@ -109,7 +123,7 @@ RSpec.describe "bundle lock with git gems" do
foo!
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "install"
@@ -118,12 +132,14 @@ RSpec.describe "bundle lock with git gems" do
end
it "properly fetches a git source locked to an annotated tag" do
+ install_gemfile_with_foo_as_a_git_dependency
+
# Create an annotated tag
git("tag -a v1.0 -m 'Annotated v1.0'", lib_path("foo-1.0"))
annotated_tag = git("rev-parse v1.0", lib_path("foo-1.0"))
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'foo', :git => "#{lib_path("foo-1.0")}"
G
@@ -135,7 +151,7 @@ RSpec.describe "bundle lock with git gems" do
foo (1.0)
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
@@ -145,7 +161,7 @@ RSpec.describe "bundle lock with git gems" do
foo!
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "install"
@@ -154,9 +170,89 @@ RSpec.describe "bundle lock with git gems" do
end
it "provides correct #full_gem_path" do
+ install_gemfile_with_foo_as_a_git_dependency
+
run <<-RUBY
puts Bundler.rubygems.find_name('foo').first.full_gem_path
RUBY
expect(out).to eq(bundle("info foo --path"))
end
+
+ it "does not lock versions that don't exist in the repository when changing a GEM transitive dep to a GIT direct dep" do
+ build_repo4 do
+ build_gem "activesupport", "8.0.0" do |s|
+ s.add_dependency "securerandom"
+ end
+
+ build_gem "securerandom", "0.3.1"
+ end
+
+ path = lib_path("securerandom")
+
+ build_git "securerandom", "0.3.2", path: path
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ activesupport (8.0.0)
+ securerandom
+ securerandom (0.3.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ activesupport
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ gemfile <<~G
+ source "https://gem.repo4"
+
+ gem "activesupport"
+ gem "securerandom", git: "#{path}"
+ G
+
+ bundle "lock"
+
+ expect(lockfile).to include("securerandom (0.3.2)")
+ end
+
+ it "does not lock versions that don't exist in the repository when changing a GIT direct dep to a GEM direct dep" do
+ build_repo4 do
+ build_gem "ruby-lsp", "0.16.1"
+ end
+
+ path = lib_path("ruby-lsp")
+ revision = build_git("ruby-lsp", "0.16.2", path: path).ref_for("HEAD")
+
+ lockfile <<~L
+ GIT
+ remote: #{path}
+ revision: #{revision}
+ specs:
+ ruby-lsp (0.16.2)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ ruby-lsp!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ gemfile <<~G
+ source "https://gem.repo4"
+ gem "ruby-lsp"
+ G
+
+ bundle "lock"
+
+ expect(lockfile).to include("ruby-lsp (0.16.1)")
+ end
end
diff --git a/spec/bundler/lock/lockfile_spec.rb b/spec/bundler/lock/lockfile_spec.rb
index 4fd081e7d0..dcefe9cc2a 100644
--- a/spec/bundler/lock/lockfile_spec.rb
+++ b/spec/bundler/lock/lockfile_spec.rb
@@ -6,30 +6,30 @@ RSpec.describe "the lockfile format" do
end
it "generates a simple lockfile for a single source, gem" do
- checksums = checksums_section_when_existing do |c|
- c.checksum(gem_repo2, "rack", "1.0.0")
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum(gem_repo2, "myrack", "1.0.0")
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
- gem "rack"
+ gem "myrack"
G
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
@@ -43,25 +43,25 @@ RSpec.describe "the lockfile format" do
specs:
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
omg!
- rack
+ myrack
BUNDLED WITH
1.8.2
L
install_gemfile <<-G, verbose: true, env: { "BUNDLER_VERSION" => Bundler::VERSION }
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
- gem "rack"
+ gem "myrack"
G
expect(out).not_to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with 1.8.2.")
@@ -69,44 +69,50 @@ RSpec.describe "the lockfile format" do
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
- 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
+ it "does not update the lockfile's bundler version if nothing changed during bundle install, but uses the locked version" do
version = "2.3.0"
+ build_repo4 do
+ build_gem "myrack", "1.0.0"
+
+ build_bundler version
+ end
+
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo4/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
BUNDLED WITH
#{version}
L
- install_gemfile <<-G, verbose: true, artifice: "vcr"
- source "#{file_uri_for(gem_repo2)}"
+ install_gemfile <<-G, verbose: true
+ source "https://gem.repo4"
- gem "rack"
+ gem "myrack"
G
expect(out).to include("Bundler #{Bundler::VERSION} is running, but your lockfile was generated with #{version}.")
@@ -114,277 +120,342 @@ RSpec.describe "the lockfile format" do
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo4/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
BUNDLED WITH
#{version}
G
end
- 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"
-
- checksums = checksums_section do |c|
- c.checksum(gem_repo2, "rack", "1.0.0")
- end
-
+ it "adds the BUNDLED WITH section if not present" do
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
- #{checksums}
- BUNDLED WITH
- #{version}
+ myrack
L
- install_gemfile <<-G, verbose: true
- source "#{file_uri_for(gem_repo2)}"
+ install_gemfile <<-G
+ source "https://gem.repo2"
- gem "rack"
+ gem "myrack", "> 0"
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_repo2)}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
- #{checksums}
+ myrack (> 0)
+
BUNDLED WITH
- #{version}
+ #{Bundler::VERSION}
G
end
- it "adds the BUNDLED WITH section if not present" 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_repo2)}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
+
+ BUNDLED WITH
+ #{older_major}
L
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ install_gemfile <<-G, env: { "BUNDLER_VERSION" => Bundler::VERSION }
+ source "https://gem.repo2/"
- gem "rack", "> 0"
+ gem "myrack"
G
+ expect(err).to be_empty
+
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack (> 0)
+ myrack
BUNDLED WITH
- #{Bundler::VERSION}
+ #{current_version}
G
end
- it "update the bundler major version just fine" do
- current_version = Bundler::VERSION
- older_major = previous_major(current_version)
+ it "generates a simple lockfile for a single source, gem with dependencies" do
+ install_gemfile <<-G
+ source "https://gem.repo2/"
- system_gems "bundler-#{older_major}"
+ gem "myrack-obama"
+ G
- lockfile <<-L
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo2, "myrack", "1.0.0"
+ c.checksum gem_repo2, "myrack-obama", "1.0"
+ end
+
+ expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
+ myrack-obama (1.0)
+ myrack
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
-
+ myrack-obama
+ #{checksums}
BUNDLED WITH
- #{older_major}
- L
+ #{Bundler::VERSION}
+ G
+ end
- install_gemfile <<-G, env: { "BUNDLER_VERSION" => Bundler::VERSION }
- source "#{file_uri_for(gem_repo2)}/"
+ it "generates a simple lockfile for a single source, gem with a version requirement" do
+ install_gemfile <<-G
+ source "https://gem.repo2/"
- gem "rack"
+ gem "myrack-obama", ">= 1.0"
G
- expect(err).to be_empty
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo2, "myrack", "1.0.0"
+ c.checksum gem_repo2, "myrack-obama", "1.0"
+ end
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
+ myrack-obama (1.0)
+ myrack
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
-
+ myrack-obama (>= 1.0)
+ #{checksums}
BUNDLED WITH
- #{current_version}
+ #{Bundler::VERSION}
G
end
- it "generates a simple lockfile for a single source, gem with dependencies" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}/"
+ it "generates a lockfile without credentials" do
+ bundle "config set https://localgemserver.test/ user:pass"
+
+ install_gemfile(<<-G, artifice: "endpoint_strict_basic_authentication", quiet: true)
+ source "https://gem.repo1"
+
+ source "https://localgemserver.test/" do
+
+ end
- gem "rack-obama"
+ source "https://user:pass@othergemserver.test/" do
+ gem "myrack-obama", ">= 1.0"
+ end
G
- checksums = checksums_section_when_existing do |c|
- c.checksum gem_repo2, "rack", "1.0.0"
- c.checksum gem_repo2, "rack-obama", "1.0"
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo2, "myrack", "1.0.0"
+ c.checksum gem_repo2, "myrack-obama", "1.0"
end
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo1/
+ specs:
+
+ GEM
+ remote: https://localgemserver.test/
specs:
- rack (1.0.0)
- rack-obama (1.0)
- rack
+
+ GEM
+ remote: https://othergemserver.test/
+ specs:
+ myrack (1.0.0)
+ myrack-obama (1.0)
+ myrack
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack-obama
+ myrack-obama (>= 1.0)!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
- it "generates a simple lockfile for a single source, gem with a version requirement" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}/"
+ it "does not add credentials to lockfile when it does not have them already" do
+ bundle "config set http://localgemserver.test/ user:pass"
- gem "rack-obama", ">= 1.0"
+ gemfile <<~G
+ source "https://gem.repo1"
+
+ source "http://localgemserver.test/" do
+
+ end
+
+ source "http://user:pass@othergemserver.test/" do
+ gem "myrack-obama", ">= 1.0"
+ end
G
- checksums = checksums_section_when_existing do |c|
- c.checksum gem_repo2, "rack", "1.0.0"
- c.checksum gem_repo2, "rack-obama", "1.0"
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo2, "myrack", "1.0.0"
+ c.checksum gem_repo2, "myrack-obama", "1.0"
end
- expect(lockfile).to eq <<~G
+ lockfile_without_credentials = <<~L
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: http://localgemserver.test/
+ specs:
+
+ GEM
+ remote: http://othergemserver.test/
+ specs:
+ myrack (1.0.0)
+ myrack-obama (1.0)
+ myrack
+
+ GEM
+ remote: https://gem.repo1/
specs:
- rack (1.0.0)
- rack-obama (1.0)
- rack
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack-obama (>= 1.0)
+ myrack-obama (>= 1.0)!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
- G
+ #{Bundler::VERSION}
+ L
+
+ lockfile lockfile_without_credentials
+
+ # when not re-resolving
+ bundle "install", artifice: "endpoint_strict_basic_authentication", quiet: true
+ expect(lockfile).to eq lockfile_without_credentials
+
+ # when re-resolving with full unlock
+ bundle "update", artifice: "endpoint_strict_basic_authentication"
+ expect(lockfile).to eq lockfile_without_credentials
+
+ # when re-resolving without ful unlocking
+ bundle "update myrack-obama", artifice: "endpoint_strict_basic_authentication"
+ expect(lockfile).to eq lockfile_without_credentials
end
- it "generates a lockfile without credentials" do
+ it "keeps credentials in lockfile if already there" do
bundle "config set http://localgemserver.test/ user:pass"
- install_gemfile(<<-G, artifice: "endpoint_strict_basic_authentication", quiet: true)
- source "#{file_uri_for(gem_repo1)}"
+ gemfile <<~G
+ source "https://gem.repo1"
source "http://localgemserver.test/" do
end
source "http://user:pass@othergemserver.test/" do
- gem "rack-obama", ">= 1.0"
+ gem "myrack-obama", ">= 1.0"
end
G
- checksums = checksums_section_when_existing do |c|
- c.checksum gem_repo2, "rack", "1.0.0"
- c.checksum gem_repo2, "rack-obama", "1.0"
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo2, "myrack", "1.0.0"
+ c.checksum gem_repo2, "myrack-obama", "1.0"
end
- expect(lockfile).to eq <<~G
+ lockfile_with_credentials = <<~L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: http://localgemserver.test/
specs:
GEM
- remote: http://localgemserver.test/
+ remote: http://user:pass@othergemserver.test/
specs:
+ myrack (1.0.0)
+ myrack-obama (1.0)
+ myrack
GEM
- remote: http://othergemserver.test/
+ remote: https://gem.repo1/
specs:
- rack (1.0.0)
- rack-obama (1.0)
- rack
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack-obama (>= 1.0)!
+ myrack-obama (>= 1.0)!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
- G
+ #{Bundler::VERSION}
+ L
+
+ lockfile lockfile_with_credentials
+
+ bundle "install", artifice: "endpoint_strict_basic_authentication", quiet: true
+
+ expect(lockfile).to eq lockfile_with_credentials
end
it "generates lockfiles with multiple requirements" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}/"
+ source "https://gem.repo2/"
gem "net-sftp"
G
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo2, "net-sftp", "1.1.1"
c.checksum gem_repo2, "net-ssh", "1.0"
end
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
net-sftp (1.1.1)
net-ssh (>= 1.0.0, < 1.99.0)
@@ -397,7 +468,7 @@ RSpec.describe "the lockfile format" do
net-sftp
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
expect(the_bundle).to include_gems "net-sftp 1.1.1", "net-ssh 1.0.0"
@@ -407,11 +478,11 @@ RSpec.describe "the lockfile format" do
git = build_git "foo"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "foo", "1.0"
end
@@ -423,7 +494,7 @@ RSpec.describe "the lockfile format" do
foo (1.0)
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
@@ -433,7 +504,7 @@ RSpec.describe "the lockfile format" do
foo!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
@@ -441,13 +512,13 @@ RSpec.describe "the lockfile format" do
build_lib "omg", path: lib_path("omg")
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}/"
+ source "https://gem.repo2/"
platforms :#{not_local_tag} do
gem "omg", :path => "#{lib_path("omg")}"
end
- gem "rack"
+ gem "myrack"
G
lockfile <<-L
@@ -457,34 +528,34 @@ RSpec.describe "the lockfile format" do
specs:
GEM
- remote: #{file_uri_for(gem_repo2)}//
+ remote: https://gem.repo2//
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{not_local}
DEPENDENCIES
omg!
- rack
+ myrack
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "install"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "serializes global git sources" do
git = build_git "foo"
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "foo", "1.0"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}" do
gem "foo"
end
@@ -498,7 +569,7 @@ RSpec.describe "the lockfile format" do
foo (1.0)
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
@@ -508,7 +579,7 @@ RSpec.describe "the lockfile format" do
foo!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
@@ -516,12 +587,12 @@ RSpec.describe "the lockfile format" do
git = build_git "foo"
update_git "foo", branch: "omg"
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "foo", "1.0"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}", :branch => "omg"
G
@@ -534,7 +605,7 @@ RSpec.describe "the lockfile format" do
foo (1.0)
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
@@ -544,7 +615,7 @@ RSpec.describe "the lockfile format" do
foo!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
@@ -552,12 +623,12 @@ RSpec.describe "the lockfile format" do
git = build_git "foo"
update_git "foo", tag: "omg"
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "foo", "1.0"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}", :tag => "omg"
G
@@ -570,7 +641,7 @@ RSpec.describe "the lockfile format" do
foo (1.0)
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
@@ -580,7 +651,7 @@ RSpec.describe "the lockfile format" do
foo!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
@@ -600,7 +671,7 @@ RSpec.describe "the lockfile format" do
s.add_dependency "orm_adapter"
end
- update_git "ckeditor", path: lib_path("ckeditor"), remote: file_uri_for(@remote.path)
+ update_git "ckeditor", path: lib_path("ckeditor"), remote: @remote.path
update_git "ckeditor", path: lib_path("ckeditor"), tag: "v4.0.7"
old_git = update_git "ckeditor", path: lib_path("ckeditor"), push: "v4.0.7"
@@ -614,7 +685,7 @@ RSpec.describe "the lockfile format" do
new_git = update_git "ckeditor", path: lib_path("ckeditor"), push: "v4.0.8"
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "ckeditor", :git => "#{@remote.path}", :tag => "v4.0.8"
G
@@ -628,7 +699,7 @@ RSpec.describe "the lockfile format" do
orm_adapter
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
orm_adapter (0.4.1)
@@ -639,7 +710,7 @@ RSpec.describe "the lockfile format" do
ckeditor!
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "lock"
@@ -655,7 +726,7 @@ RSpec.describe "the lockfile format" do
orm_adapter
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
orm_adapter (0.4.1)
@@ -666,19 +737,19 @@ RSpec.describe "the lockfile format" do
ckeditor!
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
it "serializes pinned path sources to the lockfile" do
build_lib "foo"
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "foo", "1.0"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :path => "#{lib_path("foo-1.0")}"
G
@@ -689,7 +760,7 @@ RSpec.describe "the lockfile format" do
foo (1.0)
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
@@ -699,23 +770,22 @@ RSpec.describe "the lockfile format" do
foo!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "serializes pinned path sources to the lockfile even when packaging" do
build_lib "foo"
- checksums = checksums_section_when_existing do |c|
- c.no_checksum "foo", "1.0"
- end
-
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :path => "#{lib_path("foo-1.0")}"
G
- bundle "config set cache_all true"
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ end
+
bundle :cache
bundle :install, local: true
@@ -726,7 +796,7 @@ RSpec.describe "the lockfile format" do
foo (1.0)
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
@@ -736,7 +806,7 @@ RSpec.describe "the lockfile format" do
foo!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
@@ -744,16 +814,16 @@ RSpec.describe "the lockfile format" do
build_lib "foo"
bar = build_git "bar"
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "foo", "1.0"
c.no_checksum "bar", "1.0"
- c.checksum gem_repo2, "rack", "1.0.0"
+ c.checksum gem_repo2, "myrack", "1.0.0"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}/"
+ source "https://gem.repo2/"
- gem "rack"
+ gem "myrack"
gem "foo", :path => "#{lib_path("foo-1.0")}"
gem "bar", :git => "#{lib_path("bar-1.0")}"
G
@@ -771,9 +841,9 @@ RSpec.describe "the lockfile format" do
foo (1.0)
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
@@ -781,92 +851,92 @@ RSpec.describe "the lockfile format" do
DEPENDENCIES
bar!
foo!
- rack
+ myrack
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "removes redundant sources" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}/"
+ source "https://gem.repo2/"
- gem "rack", :source => "#{file_uri_for(gem_repo2)}/"
+ gem "myrack", :source => "https://gem.repo2/"
G
- checksums = checksums_section_when_existing do |c|
- c.checksum gem_repo2, "rack", "1.0.0"
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo2, "myrack", "1.0.0"
end
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack!
+ myrack!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "lists gems alphabetically" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}/"
+ source "https://gem.repo2/"
gem "thin"
gem "actionpack"
- gem "rack-obama"
+ gem "myrack-obama"
G
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo2, "actionpack", "2.3.2"
c.checksum gem_repo2, "activesupport", "2.3.2"
- c.checksum gem_repo2, "rack", "1.0.0"
- c.checksum gem_repo2, "rack-obama", "1.0"
+ c.checksum gem_repo2, "myrack", "1.0.0"
+ c.checksum gem_repo2, "myrack-obama", "1.0"
c.checksum gem_repo2, "thin", "1.0"
end
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
actionpack (2.3.2)
activesupport (= 2.3.2)
activesupport (2.3.2)
- rack (1.0.0)
- rack-obama (1.0)
- rack
+ myrack (1.0.0)
+ myrack-obama (1.0)
+ myrack
thin (1.0)
- rack
+ myrack
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
actionpack
- rack-obama
+ myrack-obama
thin
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "orders dependencies' dependencies in alphabetical order" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}/"
+ source "https://gem.repo2/"
gem "rails"
G
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo2, "actionmailer", "2.3.2"
c.checksum gem_repo2, "actionpack", "2.3.2"
c.checksum gem_repo2, "activerecord", "2.3.2"
@@ -878,7 +948,7 @@ RSpec.describe "the lockfile format" do
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
actionmailer (2.3.2)
activesupport (= 2.3.2)
@@ -904,7 +974,7 @@ RSpec.describe "the lockfile format" do
rails
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
@@ -912,7 +982,7 @@ RSpec.describe "the lockfile format" 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
+ # See https://github.com/ruby/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"
@@ -920,18 +990,18 @@ RSpec.describe "the lockfile format" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}/"
+ source "https://gem.repo2"
gem 'double_deps'
G
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum gem_repo2, "double_deps", "1.0"
c.checksum gem_repo2, "net-ssh", "1.0"
end
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
double_deps (1.0)
net-ssh
@@ -945,81 +1015,81 @@ RSpec.describe "the lockfile format" do
double_deps
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "does not add the :require option to the lockfile" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}/"
+ source "https://gem.repo2/"
- gem "rack-obama", ">= 1.0", :require => "rack/obama"
+ gem "myrack-obama", ">= 1.0", :require => "myrack/obama"
G
- checksums = checksums_section_when_existing do |c|
- c.checksum gem_repo2, "rack", "1.0.0"
- c.checksum gem_repo2, "rack-obama", "1.0"
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo2, "myrack", "1.0.0"
+ c.checksum gem_repo2, "myrack-obama", "1.0"
end
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
- rack-obama (1.0)
- rack
+ myrack (1.0.0)
+ myrack-obama (1.0)
+ myrack
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack-obama (>= 1.0)
+ myrack-obama (>= 1.0)
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "does not add the :group option to the lockfile" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}/"
+ source "https://gem.repo2/"
- gem "rack-obama", ">= 1.0", :group => :test
+ gem "myrack-obama", ">= 1.0", :group => :test
G
- checksums = checksums_section_when_existing do |c|
- c.checksum gem_repo2, "rack", "1.0.0"
- c.checksum gem_repo2, "rack-obama", "1.0"
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo2, "myrack", "1.0.0"
+ c.checksum gem_repo2, "myrack-obama", "1.0"
end
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
- rack-obama (1.0)
- rack
+ myrack (1.0.0)
+ myrack-obama (1.0)
+ myrack
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack-obama (>= 1.0)
+ myrack-obama (>= 1.0)
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "stores relative paths when the path is provided in a relative fashion and in Gemfile dir" do
build_lib "foo", path: bundled_app("foo")
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "foo", "1.0"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
path "foo" do
gem "foo"
end
@@ -1032,7 +1102,7 @@ RSpec.describe "the lockfile format" do
foo (1.0)
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
@@ -1042,19 +1112,19 @@ RSpec.describe "the lockfile format" do
foo!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "stores relative paths when the path is provided in a relative fashion and is above Gemfile dir" do
build_lib "foo", path: bundled_app(File.join("..", "foo"))
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "foo", "1.0"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
path "../foo" do
gem "foo"
end
@@ -1067,7 +1137,7 @@ RSpec.describe "the lockfile format" do
foo (1.0)
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
@@ -1077,24 +1147,24 @@ RSpec.describe "the lockfile format" do
foo!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "stores relative paths when the path is provided in an absolute fashion but is relative" do
build_lib "foo", path: bundled_app("foo")
- checksums = checksums_section_when_existing do |c|
- c.no_checksum "foo", "1.0"
- end
-
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
path File.expand_path("foo", __dir__) do
gem "foo"
end
G
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "foo", "1.0"
+ end
+
expect(lockfile).to eq <<~G
PATH
remote: foo
@@ -1102,7 +1172,7 @@ RSpec.describe "the lockfile format" do
foo (1.0)
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
@@ -1112,19 +1182,19 @@ RSpec.describe "the lockfile format" do
foo!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "stores relative paths when the path is provided for gemspec" do
- build_lib("foo", path: tmp.join("foo"))
+ build_lib("foo", path: tmp("foo"))
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "foo", "1.0"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gemspec :path => "../foo"
G
@@ -1135,7 +1205,7 @@ RSpec.describe "the lockfile format" do
foo (1.0)
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
PLATFORMS
@@ -1145,57 +1215,57 @@ RSpec.describe "the lockfile format" do
foo!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "keeps existing platforms in the lockfile" do
- checksums = checksums_section_when_existing do |c|
- c.no_checksum "rack", "1.0.0"
+ checksums = checksums_section_when_enabled do |c|
+ c.no_checksum "myrack", "1.0.0"
end
lockfile <<-G
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
java
DEPENDENCIES
- rack
+ myrack
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}/"
+ source "https://gem.repo2/"
- gem "rack"
+ gem "myrack"
G
- checksums.checksum(gem_repo2, "rack", "1.0.0")
+ checksums.checksum(gem_repo2, "myrack", "1.0.0")
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms("java", local_platform, defaults: [])}
DEPENDENCIES
- rack
+ myrack
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
- it "adds compatible platform specific variants to the lockfile, even if resolution fallback to RUBY due to some other incompatible platform specific variant" do
+ it "adds compatible platform specific variants to the lockfile, even if resolution fallback to ruby due to some other incompatible platform specific variant" do
simulate_platform "arm64-darwin-23" do
build_repo4 do
build_gem "google-protobuf", "3.25.1"
@@ -1209,14 +1279,19 @@ RSpec.describe "the lockfile format" do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "google-protobuf"
G
bundle "lock --add-platform x64-mingw-ucrt"
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo4, "google-protobuf", "3.25.1"
+ c.checksum gem_repo4, "google-protobuf", "3.25.1", "arm64-darwin-23"
+ end
+
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
google-protobuf (3.25.1)
google-protobuf (3.25.1-arm64-darwin-23)
@@ -1228,9 +1303,9 @@ RSpec.describe "the lockfile format" do
DEPENDENCIES
google-protobuf
-
+ #{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
@@ -1242,255 +1317,536 @@ RSpec.describe "the lockfile format" do
end
end
- simulate_platform "universal-java-16"
-
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "platform_specific"
- G
+ simulate_platform "universal-java-16" do
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "platform_specific"
+ G
- checksums = checksums_section_when_existing do |c|
- c.checksum gem_repo2, "platform_specific", "1.0", "universal-java-16"
- end
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum gem_repo2, "platform_specific", "1.0", "universal-java-16"
+ end
- expect(lockfile).to eq <<~G
- GEM
- remote: #{file_uri_for(gem_repo2)}/
- specs:
- platform_specific (1.0-universal-java-16)
+ expect(lockfile).to eq <<~G
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ platform_specific (1.0-universal-java-16)
- PLATFORMS
- universal-java-16
+ PLATFORMS
+ universal-java-16
- DEPENDENCIES
- platform_specific
- #{checksums}
- BUNDLED WITH
- #{Bundler::VERSION}
- G
+ DEPENDENCIES
+ platform_specific
+ #{checksums}
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ G
+ end
end
it "does not add duplicate gems" do
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.checksum(gem_repo2, "activesupport", "2.3.5")
- c.checksum(gem_repo2, "rack", "1.0.0")
+ c.checksum(gem_repo2, "myrack", "1.0.0")
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}/"
- gem "rack"
+ source "https://gem.repo2/"
+ gem "myrack"
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}/"
- gem "rack"
+ source "https://gem.repo2/"
+ gem "myrack"
gem "activesupport"
G
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
activesupport (2.3.5)
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
activesupport
- rack
+ myrack
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "does not add duplicate dependencies" do
- checksums = checksums_section_when_existing do |c|
- c.checksum(gem_repo2, "rack", "1.0.0")
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum(gem_repo2, "myrack", "1.0.0")
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}/"
- gem "rack"
- gem "rack"
+ source "https://gem.repo2/"
+ gem "myrack"
+ gem "myrack"
G
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "does not add duplicate dependencies with versions" do
- checksums = checksums_section_when_existing do |c|
- c.checksum(gem_repo2, "rack", "1.0.0")
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum(gem_repo2, "myrack", "1.0.0")
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}/"
- gem "rack", "1.0"
- gem "rack", "1.0"
+ source "https://gem.repo2/"
+ gem "myrack", "1.0"
+ gem "myrack", "1.0"
G
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack (= 1.0)
+ myrack (= 1.0)
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "does not add duplicate dependencies in different groups" do
- checksums = checksums_section_when_existing do |c|
- c.checksum(gem_repo2, "rack", "1.0.0")
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum(gem_repo2, "myrack", "1.0.0")
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}/"
- gem "rack", "1.0", :group => :one
- gem "rack", "1.0", :group => :two
+ source "https://gem.repo2/"
+ gem "myrack", "1.0", :group => :one
+ gem "myrack", "1.0", :group => :two
G
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack (= 1.0)
+ myrack (= 1.0)
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "raises if two different versions are used" do
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo2)}/"
- gem "rack", "1.0"
- gem "rack", "1.1"
+ source "https://gem.repo2/"
+ gem "myrack", "1.0"
+ gem "myrack", "1.1"
G
expect(bundled_app_lock).not_to exist
- expect(err).to include "rack (= 1.0) and rack (= 1.1)"
+ expect(err).to include "myrack (= 1.0) and myrack (= 1.1)"
end
it "raises if two different sources are used" do
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo2)}/"
- gem "rack"
- gem "rack", :git => "git://hubz.com"
+ source "https://gem.repo2/"
+ gem "myrack"
+ gem "myrack", :git => "git://hubz.com"
G
expect(bundled_app_lock).not_to exist
- expect(err).to include "rack (>= 0) should come from an unspecified source and git://hubz.com"
+ expect(err).to include "myrack (>= 0) should come from an unspecified source and git://hubz.com"
end
it "works correctly with multiple version dependencies" do
- checksums = checksums_section_when_existing do |c|
- c.checksum(gem_repo2, "rack", "0.9.1")
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum(gem_repo2, "myrack", "0.9.1")
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}/"
- gem "rack", "> 0.9", "< 1.0"
+ source "https://gem.repo2/"
+ gem "myrack", "> 0.9", "< 1.0"
G
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
- rack (0.9.1)
+ myrack (0.9.1)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack (> 0.9, < 1.0)
+ myrack (> 0.9, < 1.0)
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
it "captures the Ruby version in the lockfile" do
- checksums = checksums_section_when_existing do |c|
- c.checksum(gem_repo2, "rack", "0.9.1")
+ checksums = checksums_section_when_enabled do |c|
+ c.checksum(gem_repo2, "myrack", "0.9.1")
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}/"
+ source "https://gem.repo2/"
ruby '#{Gem.ruby_version}'
- gem "rack", "> 0.9", "< 1.0"
+ gem "myrack", "> 0.9", "< 1.0"
G
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
- rack (0.9.1)
+ myrack (0.9.1)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack (> 0.9, < 1.0)
+ myrack (> 0.9, < 1.0)
#{checksums}
RUBY VERSION
- #{Bundler::RubyVersion.system}
+ #{Bundler::RubyVersion.system}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
- it "raises a helpful error message when the lockfile is missing deps" do
+ it "automatically fixes the lockfile when it's missing deps" do
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
+ specs:
+ myrack_middleware (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack_middleware
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ install_gemfile <<-G
+ source "https://gem.repo2"
+ gem "myrack_middleware"
+ G
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ myrack (0.9.1)
+ myrack_middleware (1.0)
+ myrack (= 0.9.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack_middleware
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "raises a clear error when frozen mode is set and lockfile is missing deps, and does not install any gems" do
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ myrack_middleware (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack_middleware
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ install_gemfile <<-G, env: { "BUNDLE_FROZEN" => "true" }, raise_on_error: false
+ source "https://gem.repo2"
+ gem "myrack_middleware"
+ G
+
+ expect(err).to eq("Bundler found incorrect dependencies in the lockfile for myrack_middleware-1.0")
+ expect(the_bundle).not_to include_gems "myrack_middleware 1.0"
+ end
+
+ it "raises a clear error when frozen mode is set and lockfile is missing entries in CHECKSUMS section, and does not install any gems" do
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ myrack_middleware (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack_middleware
+
+ CHECKSUMS
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ install_gemfile <<-G, env: { "BUNDLE_FROZEN" => "true" }, raise_on_error: false
+ source "https://gem.repo2"
+ gem "myrack_middleware"
+ G
+
+ expect(err).to eq <<~L.strip
+ Your lockfile is missing a CHECKSUMS entry for \"myrack_middleware\", but can't be updated because frozen mode is set
+
+ Run `bundle install` elsewhere and add the updated Gemfile.lock to version control.
+ L
+
+ expect(the_bundle).not_to include_gems "myrack_middleware 1.0"
+ end
+
+ it "raises a clear error when frozen mode is set and lockfile has empty checksums in CHECKSUMS section, and does not install any gems" do
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ myrack (0.9.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack
+
+ CHECKSUMS
+ myrack (0.9.1)
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ install_gemfile <<-G, env: { "BUNDLE_FROZEN" => "true" }, raise_on_error: false
+ source "https://gem.repo2"
+ gem "myrack"
+ G
+
+ expect(err).to eq <<~L.strip
+ Your lockfile has an empty CHECKSUMS entry for \"myrack\", but can't be updated because frozen mode is set
+
+ Run `bundle install` elsewhere and add the updated Gemfile.lock to version control.
+ L
+
+ expect(the_bundle).not_to include_gems "myrack 0.9.1"
+ end
+
+ it "automatically fixes the lockfile when it's missing deps, they conflict with other locked deps, but conflicts are fixable" do
+ build_repo4 do
+ build_gem "other_dep", "0.9"
+ build_gem "other_dep", "1.0"
+
+ build_gem "myrack", "0.9.1"
+
+ build_gem "myrack_middleware", "1.0" do |s|
+ s.add_dependency "myrack", "= 0.9.1"
+ s.add_dependency "other_dep", "= 0.9"
+ end
+ end
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ myrack_middleware (1.0)
+ other_dep (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack_middleware
+ other_dep
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem "myrack_middleware"
+ gem "other_dep"
+ G
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ myrack (0.9.1)
+ myrack_middleware (1.0)
+ myrack (= 0.9.1)
+ other_dep (= 0.9)
+ other_dep (0.9)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack_middleware
+ other_dep
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "automatically fixes the lockfile when it's missing multiple deps, they conflict with other locked deps, but conflicts are fixable" do
+ build_repo4 do
+ build_gem "other_dep", "0.9"
+ build_gem "other_dep", "1.0"
+
+ build_gem "myrack", "0.9.1"
+
+ build_gem "myrack_middleware", "1.0" do |s|
+ s.add_dependency "myrack", "= 0.9.1"
+ end
+
+ build_gem "another_dep_middleware", "1.0" do |s|
+ s.add_dependency "other_dep", "= 0.9"
+ end
+ end
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ myrack_middleware (1.0)
+ another_dep_middleware (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack_middleware
+ another_dep_middleware
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ install_gemfile <<-G
+ source "https://gem.repo4"
+ gem "myrack_middleware"
+ gem "another_dep_middleware"
+ G
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: https://gem.repo4/
+ specs:
+ another_dep_middleware (1.0)
+ other_dep (= 0.9)
+ myrack (0.9.1)
+ myrack_middleware (1.0)
+ myrack (= 0.9.1)
+ other_dep (0.9)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ another_dep_middleware
+ myrack_middleware
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "raises a resolution error when lockfile is missing deps, they conflict with other locked deps, and conflicts are not fixable" do
+ build_repo4 do
+ build_gem "other_dep", "0.9"
+ build_gem "other_dep", "1.0"
+
+ build_gem "myrack", "0.9.1"
+
+ build_gem "myrack_middleware", "1.0" do |s|
+ s.add_dependency "myrack", "= 0.9.1"
+ s.add_dependency "other_dep", "= 0.9"
+ end
+ end
+
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo4/
specs:
- rack_middleware (1.0)
+ myrack_middleware (1.0)
+ other_dep (1.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack_middleware
+ myrack_middleware
+ other_dep
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
L
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo2)}"
- gem "rack_middleware"
+ source "https://gem.repo4"
+ gem "myrack_middleware"
+ gem "other_dep", "1.0"
G
- expect(err).to include("Downloading rack_middleware-1.0 revealed dependencies not in the API or the lockfile (#{Gem::Dependency.new("rack", "= 0.9.1")}).").
- and include("Running `bundle update rack_middleware` should fix the problem.")
+ expect(err).to eq <<~ERROR.strip
+ Could not find compatible versions
+
+ Because every version of myrack_middleware depends on other_dep = 0.9
+ and Gemfile depends on myrack_middleware >= 0,
+ other_dep = 0.9 is required.
+ So, because Gemfile depends on other_dep = 1.0,
+ version solving has failed.
+ ERROR
end
it "regenerates a lockfile with no specs" do
@@ -1506,7 +1862,7 @@ RSpec.describe "the lockfile format" do
lockfile <<-G
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
PLATFORMS
@@ -1516,32 +1872,311 @@ RSpec.describe "the lockfile format" do
direct_dependency
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "direct_dependency"
G
expect(lockfile).to eq <<~G
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
direct_dependency (4.5.6)
indirect_dependency
indirect_dependency (1.2.3)
PLATFORMS
- #{lockfile_platforms("ruby", generic_local_platform, defaults: [])}
+ #{lockfile_platforms(generic_default_locked_platform || local_platform, defaults: ["ruby"])}
DEPENDENCIES
direct_dependency
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
+ G
+ end
+
+ it "automatically fixes the lockfile when it's missing deps and the full index is in use" do
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo2/
+ specs:
+ myrack_middleware (1.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack_middleware
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ install_gemfile <<-G
+ source "#{file_uri_for(gem_repo2)}"
+ gem "myrack_middleware"
+ G
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo2)}/
+ specs:
+ myrack (0.9.1)
+ myrack_middleware (1.0)
+ myrack (= 0.9.1)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ myrack_middleware
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "automatically fixes the lockfile when it includes a gem under the correct GIT section, but also under an incorrect GEM section, with a higher version, and with no explicit Gemfile requirement" do
+ git = build_git "foo"
+
+ gemfile <<~G
+ source "https://gem.repo1/"
+ gem "foo", git: "#{lib_path("foo-1.0")}"
+ G
+
+ # If the lockfile erroneously lists platform versions of the gem
+ # that don't match the locked version of the git repo we should remove them.
+
+ lockfile <<~L
+ GIT
+ remote: #{lib_path("foo-1.0")}
+ revision: #{git.ref_for("main")}
+ specs:
+ foo (1.0)
+
+ GEM
+ remote: https://gem.repo1/
+ specs:
+ foo (1.1-x86_64-linux-gnu)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install"
+
+ expect(lockfile).to eq <<~L
+ GIT
+ remote: #{lib_path("foo-1.0")}
+ revision: #{git.ref_for("main")}
+ specs:
+ foo (1.0)
+
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "automatically fixes the lockfile when it includes a gem under the correct GIT section, but also under an incorrect GEM section, with a higher version" do
+ git = build_git "foo"
+
+ gemfile <<~G
+ source "https://gem.repo1/"
+ gem "foo", "= 1.0", git: "#{lib_path("foo-1.0")}"
G
+
+ # If the lockfile erroneously lists platform versions of the gem
+ # that don't match the locked version of the git repo we should remove them.
+
+ lockfile <<~L
+ GIT
+ remote: #{lib_path("foo-1.0")}
+ revision: #{git.ref_for("main")}
+ specs:
+ foo (1.0)
+
+ GEM
+ remote: https://gem.repo1/
+ specs:
+ foo (1.1-x86_64-linux-gnu)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo (= 1.0)!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install"
+
+ expect(lockfile).to eq <<~L
+ GIT
+ remote: #{lib_path("foo-1.0")}
+ revision: #{git.ref_for("main")}
+ specs:
+ foo (1.0)
+
+ GEM
+ remote: https://gem.repo1/
+ specs:
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ foo (= 1.0)!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "automatically fixes the lockfile when it has incorrect deps, keeping the locked version" do
+ build_repo4 do
+ build_gem "net-smtp", "0.5.0" do |s|
+ s.add_dependency "net-protocol"
+ end
+
+ build_gem "net-smtp", "0.5.1" do |s|
+ s.add_dependency "net-protocol"
+ end
+
+ build_gem "net-protocol", "0.2.2"
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "net-smtp"
+ G
+
+ lockfile <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ net-protocol (0.2.2)
+ net-smtp (0.5.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ net-smtp
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install"
+
+ expect(lockfile).to eq <<~L
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ net-protocol (0.2.2)
+ net-smtp (0.5.0)
+ net-protocol
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ net-smtp
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "successfully updates the lockfile when a new gem is added in the Gemfile includes a gem that shouldn't be included" do
+ build_repo4 do
+ build_gem "logger", "1.7.0"
+ build_gem "rack", "3.2.0"
+ build_gem "net-smtp", "0.5.0"
+ end
+
+ gemfile <<~G
+ source "#{file_uri_for(gem_repo4)}"
+ gem "logger"
+ gem "net-smtp"
+
+ install_if -> { false } do
+ gem 'rack', github: 'rack/rack'
+ end
+ G
+
+ lockfile <<~L
+ GIT
+ remote: https://github.com/rack/rack.git
+ revision: 2fface9ac09fc582a81386becd939c987ad33f99
+ specs:
+ rack (3.2.0)
+
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ logger (1.7.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ logger
+ rack!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+
+ bundle "install"
+
+ expect(lockfile).to eq <<~L
+ GIT
+ remote: https://github.com/rack/rack.git
+ revision: 2fface9ac09fc582a81386becd939c987ad33f99
+ specs:
+ rack (3.2.0)
+
+ GEM
+ remote: #{file_uri_for(gem_repo4)}/
+ specs:
+ logger (1.7.0)
+ net-smtp (0.5.0)
+
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+ logger
+ net-smtp
+ rack!
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
end
shared_examples_for "a lockfile missing dependent specs" do
@@ -1555,14 +2190,14 @@ RSpec.describe "the lockfile format" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "minitest-bisect"
G
# Corrupt lockfile (completely missing path_expander)
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
minitest-bisect (1.6.0)
@@ -1573,7 +2208,7 @@ RSpec.describe "the lockfile format" do
minitest-bisect
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
cache_gems "minitest-bisect-1.6.0", "path_expander-1.1.1", gem_repo: gem_repo4
@@ -1581,7 +2216,7 @@ RSpec.describe "the lockfile format" do
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
minitest-bisect (1.6.0)
path_expander (~> 1.1)
@@ -1594,7 +2229,7 @@ RSpec.describe "the lockfile format" do
minitest-bisect
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
end
@@ -1621,13 +2256,13 @@ RSpec.describe "the lockfile format" do
end
gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "minitest-bisect"
G
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
minitest-bisect (1.6.0)
path_expander (~> 1.1)
@@ -1639,15 +2274,15 @@ RSpec.describe "the lockfile format" do
minitest-bisect
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "install --verbose"
- expect(out).to include("re-resolving dependencies because your lock file includes \"minitest-bisect\" but not some of its dependencies")
+ expect(out).to include("re-resolving dependencies because your lockfile includes \"minitest-bisect\" but not some of its dependencies")
expect(lockfile).to eq <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
minitest-bisect (1.6.0)
path_expander (~> 1.1)
@@ -1660,7 +2295,7 @@ RSpec.describe "the lockfile format" do
minitest-bisect
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
end
@@ -1673,36 +2308,36 @@ RSpec.describe "the lockfile format" do
build_repo2
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- gem "rack"
+ source "https://gem.repo2"
+ gem "myrack"
G
set_lockfile_mtime_to_known_value
end
it "generates Gemfile.lock with \\n line endings" do
expect(File.read(bundled_app_lock)).not_to match("\r\n")
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
context "during updates" do
it "preserves Gemfile.lock \\n line endings" do
update_repo2 do
- build_gem "rack", "1.2" do |s|
- s.executables = "rackup"
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
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"
+ expect(the_bundle).to include_gems "myrack 1.2"
end
it "preserves Gemfile.lock \\n\\r line endings" do
skip "needs to be adapted" if Gem.win_platform?
update_repo2 do
- build_gem "rack", "1.2" do |s|
- s.executables = "rackup"
+ build_gem "myrack", "1.2" do |s|
+ s.executables = "myrackup"
end
end
@@ -1713,7 +2348,7 @@ RSpec.describe "the lockfile format" do
expect { bundle "update", all: true }.to change { File.mtime(bundled_app_lock) }
expect(File.read(bundled_app_lock)).to match("\r\n")
- expect(the_bundle).to include_gems "rack 1.2"
+ expect(the_bundle).to include_gems "myrack 1.2"
end
end
@@ -1745,27 +2380,27 @@ RSpec.describe "the lockfile format" do
it "refuses to install if Gemfile.lock contains conflict markers" do
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo2)}//
+ remote: https://gem.repo2//
specs:
<<<<<<<
- rack (1.0.0)
+ myrack (1.0.0)
=======
- rack (1.0.1)
+ myrack (1.0.1)
>>>>>>>
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
install_gemfile <<-G, raise_on_error: false
- source "#{file_uri_for(gem_repo2)}/"
- gem "rack"
+ source "https://gem.repo2/"
+ gem "myrack"
G
expect(err).to match(/your Gemfile.lock contains merge conflicts/i)
@@ -1774,19 +2409,7 @@ RSpec.describe "the lockfile format" do
private
- def prerelease?(version)
- Gem::Version.new(version).prerelease?
- end
-
def previous_major(version)
version.split(".").map.with_index {|v, i| i == 0 ? v.to_i - 1 : v }.join(".")
end
-
- def bump_minor(version)
- bump(version, 1)
- end
-
- def bump(version, segment)
- version.split(".").map.with_index {|v, i| i == segment ? v.to_i + 1 : v }.join(".")
- end
end
diff --git a/spec/bundler/other/cli_dispatch_spec.rb b/spec/bundler/other/cli_dispatch_spec.rb
index 48b285045a..a2c745b070 100644
--- a/spec/bundler/other/cli_dispatch_spec.rb
+++ b/spec/bundler/other/cli_dispatch_spec.rb
@@ -4,17 +4,17 @@ RSpec.describe "bundle command names" do
it "work when given fully" do
bundle "install", raise_on_error: false
expect(err).to eq("Could not locate Gemfile")
- expect(last_command.stdboth).not_to include("Ambiguous command")
+ expect(stdboth).not_to include("Ambiguous command")
end
it "work when not ambiguous" do
bundle "ins", raise_on_error: false
expect(err).to eq("Could not locate Gemfile")
- expect(last_command.stdboth).not_to include("Ambiguous command")
+ expect(stdboth).not_to include("Ambiguous command")
end
it "print a friendly error when ambiguous" do
bundle "in", raise_on_error: false
- expect(err).to eq("Ambiguous command in matches [info, init, inject, install]")
+ expect(err).to eq("Ambiguous command in matches [info, init, install]")
end
end
diff --git a/spec/bundler/other/cli_man_pages_spec.rb b/spec/bundler/other/cli_man_pages_spec.rb
new file mode 100644
index 0000000000..4e8f155309
--- /dev/null
+++ b/spec/bundler/other/cli_man_pages_spec.rb
@@ -0,0 +1,100 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundle commands" do
+ it "expects all commands to have all options and subcommands documented" do
+ check_commands!(Bundler::CLI)
+
+ Bundler::CLI.subcommand_classes.each_value do |klass|
+ check_commands!(klass)
+ end
+ end
+
+ private
+
+ def check_commands!(command_class)
+ command_class.commands.each do |command_name, command|
+ if command.is_a?(Bundler::Thor::HiddenCommand)
+ man_page = man_page(command_name)
+ expect(man_page).not_to exist
+ expect(main_man_page.read).not_to include("bundle #{command_name}")
+ elsif command_class == Bundler::CLI
+ man_page = man_page(command_name)
+ expect(man_page).to exist
+
+ check_options!(command, man_page)
+ else
+ man_page = man_page(command.ancestor_name)
+ expect(man_page).to exist
+
+ check_options!(command, man_page)
+ check_subcommand!(command_name, man_page)
+ end
+ end
+ end
+
+ def check_options!(command, man_page)
+ command.options.each do |_, option|
+ check_option!(option, man_page)
+ end
+ end
+
+ def check_option!(option, man_page)
+ man_page_content = man_page.read
+
+ aliases = option.aliases
+ formatted_aliases = aliases.sort.map {|name| "`#{name}`" }.join(", ") if aliases
+
+ help = if option.type == :boolean
+ "* #{append_aliases("`#{option.switch_name}`", formatted_aliases)}:"
+ elsif option.enum
+ formatted_aliases = "`#{option.switch_name}`" if aliases.empty? && option.lazy_default
+ "* #{prepend_aliases(option.enum.sort.map {|enum| "`#{option.switch_name}=#{enum}`" }.join(", "), formatted_aliases)}:"
+ else
+ names = [option.switch_name, *aliases]
+ value =
+ case option.type
+ when :array then "<list>"
+ when :numeric then "<number>"
+ else option.name.upcase
+ end
+
+ value = option.type != :numeric && option.lazy_default ? "[=#{value}]" : "=#{value}"
+
+ "* #{names.map {|name| "`#{name}#{value}`" }.join(", ")}:"
+ end
+
+ if option.banner.include?("(removed)")
+ expect(man_page_content).not_to include(help)
+ else
+ expect(man_page_content).to include(help)
+ end
+ end
+
+ def check_subcommand!(name, man_page)
+ expect(man_page.read).to match(name)
+ end
+
+ def append_aliases(text, aliases)
+ return text if aliases.empty?
+
+ "#{text}, #{aliases}"
+ end
+
+ def prepend_aliases(text, aliases)
+ return text if aliases.empty?
+
+ "#{aliases}, #{text}"
+ end
+
+ def man_page_content(command_name)
+ man_page(command_name).read
+ end
+
+ def man_page(command_name)
+ source_root.join("lib/bundler/man/bundle-#{command_name}.1.ronn")
+ end
+
+ def main_man_page
+ source_root.join("lib/bundler/man/bundle.1.ronn")
+ end
+end
diff --git a/spec/bundler/other/ext_spec.rb b/spec/bundler/other/ext_spec.rb
index 4d954b474f..a883eefe06 100644
--- a/spec/bundler/other/ext_spec.rb
+++ b/spec/bundler/other/ext_spec.rb
@@ -1,60 +1,25 @@
# frozen_string_literal: true
-RSpec.describe "Gem::Specification#match_platform" do
+RSpec.describe "Gem::Specification#installable_on_platform?" do
it "does not match platforms other than the gem platform" do
darwin = gem "lol", "1.0", "platform_specific-1.0-x86-darwin-10"
- expect(darwin.match_platform(pl("java"))).to eq(false)
+ expect(darwin.installable_on_platform?(pl("java"))).to eq(false)
end
context "when platform is a string" do
it "matches when platform is a string" do
lazy_spec = Bundler::LazySpecification.new("lol", "1.0", "universal-mingw32")
- expect(lazy_spec.match_platform(pl("x86-mingw32"))).to eq(true)
- expect(lazy_spec.match_platform(pl("x64-mingw32"))).to eq(true)
+ expect(lazy_spec.installable_on_platform?(pl("x86-mingw32"))).to eq(true)
+ expect(lazy_spec.installable_on_platform?(pl("x64-mingw32"))).to eq(true)
end
end
end
-RSpec.describe "Bundler::GemHelpers#generic" do
- include Bundler::GemHelpers
-
- it "converts non-windows platforms into ruby" do
- expect(generic(pl("x86-darwin-10"))).to eq(pl("ruby"))
- expect(generic(pl("ruby"))).to eq(pl("ruby"))
- end
-
- it "converts java platform variants into java" do
- expect(generic(pl("universal-java-17"))).to eq(pl("java"))
- expect(generic(pl("java"))).to eq(pl("java"))
- end
-
- it "converts mswin platform variants into x86-mswin32" do
- expect(generic(pl("mswin32"))).to eq(pl("x86-mswin32"))
- expect(generic(pl("i386-mswin32"))).to eq(pl("x86-mswin32"))
- expect(generic(pl("x86-mswin32"))).to eq(pl("x86-mswin32"))
- end
-
- it "converts 32-bit mingw platform variants into x86-mingw32" do
- expect(generic(pl("mingw32"))).to eq(pl("x86-mingw32"))
- expect(generic(pl("i386-mingw32"))).to eq(pl("x86-mingw32"))
- expect(generic(pl("x86-mingw32"))).to eq(pl("x86-mingw32"))
- end
-
- it "converts 64-bit mingw platform variants into x64-mingw32" do
- expect(generic(pl("x64-mingw32"))).to eq(pl("x64-mingw32"))
- expect(generic(pl("x86_64-mingw32"))).to eq(pl("x64-mingw32"))
- end
-
- it "converts 64-bit mingw UCRT platform variants into x64-mingw-ucrt" do
- expect(generic(pl("x64-mingw-ucrt"))).to eq(pl("x64-mingw-ucrt"))
- end
-end
-
RSpec.describe "Gem::SourceIndex#refresh!" do
before do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
end
diff --git a/spec/bundler/other/major_deprecation_spec.rb b/spec/bundler/other/major_deprecation_spec.rb
index e7577d38b4..24d4153dfa 100644
--- a/spec/bundler/other/major_deprecation_spec.rb
+++ b/spec/bundler/other/major_deprecation_spec.rb
@@ -6,89 +6,75 @@ RSpec.describe "major deprecations" do
describe "Bundler" do
before do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
end
describe ".clean_env" do
before do
source = "Bundler.clean_env"
- bundle "exec ruby -e #{source.dump}"
+ bundle "exec ruby -e #{source.dump}", raise_on_error: false
end
- 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` " \
- "(called at -e:1)"
+ it "is removed in favor of .unbundled_env and shows a helpful error message about it" do
+ expect(err).to include \
+ "`Bundler.clean_env` has been removed in favor of `Bundler.unbundled_env`. " \
+ "If you instead want the environment before bundler was originally loaded, use `Bundler.original_env`" \
end
-
- pending "is removed and shows a helpful error message about it", bundler: "3"
end
describe ".with_clean_env" do
before do
source = "Bundler.with_clean_env {}"
- bundle "exec ruby -e #{source.dump}"
+ bundle "exec ruby -e #{source.dump}", raise_on_error: false
end
- 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` " \
- "(called at -e:1)"
+ it "is removed in favor of .unbundled_env and shows a helpful error message about it" do
+ expect(err).to include(
+ "`Bundler.with_clean_env` has been removed in favor of `Bundler.with_unbundled_env`. " \
+ "If you instead want the environment before bundler was originally loaded, use `Bundler.with_original_env`"
)
end
-
- pending "is removed and shows a helpful error message about it", bundler: "3"
end
describe ".clean_system" do
before do
source = "Bundler.clean_system('ls')"
- bundle "exec ruby -e #{source.dump}"
+ bundle "exec ruby -e #{source.dump}", raise_on_error: false
end
- 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` " \
- "(called at -e:1)"
+ it "is removed in favor of .unbundled_system and shows a helpful error message about it" do
+ expect(err).to include(
+ "`Bundler.clean_system` has been removed 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`" \
)
end
-
- pending "is removed and shows a helpful error message about it", bundler: "3"
end
describe ".clean_exec" do
before do
source = "Bundler.clean_exec('ls')"
- bundle "exec ruby -e #{source.dump}"
+ bundle "exec ruby -e #{source.dump}", raise_on_error: false
end
- 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` " \
- "(called at -e:1)"
+ it "is removed in favor of .unbundled_exec and shows a helpful error message about it" do
+ expect(err).to include(
+ "`Bundler.clean_exec` has been removed 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`" \
)
end
-
- pending "is removed and shows a helpful error message about it", bundler: "3"
end
describe ".environment" do
before do
source = "Bundler.environment"
- bundle "exec ruby -e #{source.dump}"
+ bundle "exec ruby -e #{source.dump}", raise_on_error: false
end
- 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)"
+ it "is removed in favor of .load and shows a helpful error message about it" do
+ expect(err).to include "Bundler.environment has been removed in favor of Bundler.load"
end
-
- pending "is removed and shows a helpful error message about it", bundler: "3"
end
end
@@ -97,11 +83,9 @@ RSpec.describe "major deprecations" 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"
+ it "is removed and shows a helpful error message about it" do
+ expect(err).to include "The `--no-keep-file-descriptors` has been removed. `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
@@ -114,89 +98,181 @@ RSpec.describe "major deprecations" do
context "bundle check --path" do
before do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
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 " \
- "path 'vendor/bundle'`, and stop using this flag"
+ it "fails with a helpful error" do
+ expect(err).to include(
+ "The `--path` flag has been removed because it relied on being " \
+ "remembered across bundler invocations, which bundler no longer " \
+ "does. Instead please use `bundle config set 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"
+ source "https://gem.repo1"
+ gem "myrack"
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 " \
- "path 'vendor/bundle'`, and stop using this flag"
+ it "fails with a helpful error" do
+ expect(err).to include(
+ "The `--path` flag has been removed because it relied on being " \
+ "remembered across bundler invocations, which bundler no longer " \
+ "does. Instead please use `bundle config set path 'vendor/bundle'`, " \
+ "and stop using this flag"
)
end
+ end
+
+ context "bundle binstubs --path=" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ bundle "binstubs myrack --path=binpath", raise_on_error: false
+ end
- pending "fails with a helpful error", bundler: "3"
+ it "fails with a helpful error" do
+ expect(err).to include(
+ "The `--path` flag has been removed because it relied on being " \
+ "remembered across bundler invocations, which bundler no longer " \
+ "does. Instead please use `bundle config set bin 'binpath'`, " \
+ "and stop using this flag"
+ )
+ end
end
context "bundle cache --all" do
before do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- bundle "cache --all", raise_on_error: false
+ bundle "cache --all --verbose", 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"
+ it "fails with a helpful error" do
+ expect(err).to include(
+ "The `--all` flag has been removed because it relied on being " \
+ "remembered across bundler invocations, which bundler no longer " \
+ "does. Instead please use `bundle config set cache_all true`, " \
+ "and stop using this flag"
)
end
+ end
- pending "fails with a helpful error", bundler: "3"
+ context "bundle cache --no-all" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ bundle "cache --no-all", raise_on_error: false
+ end
+
+ it "fails with a helpful error" do
+ expect(err).to include(
+ "The `--no-all` flag has been removed because it relied on being " \
+ "remembered across bundler invocations, which bundler no longer " \
+ "does. Instead please use `bundle config set cache_all false`, " \
+ "and stop using this flag"
+ )
+ end
end
context "bundle cache --path" do
before do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
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. " \
+ it "should print a removal error" do
+ expect(err).to include(
+ "The `--path` flag has been removed because its semantics were 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
+ end
- pending "fails with a helpful error", bundler: "3"
+ context "bundle cache --path=" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ bundle "cache --path=foo", raise_on_error: false
+ end
+
+ it "should print a deprecation warning" do
+ expect(err).to include(
+ "The `--path` flag has been removed because its semantics were 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
+ end
+
+ context "bundle cache --frozen" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ bundle "cache --frozen", raise_on_error: false
+ end
+
+ it "fails with a helpful error" do
+ expect(err).to include(
+ "The `--frozen` flag has been removed because it relied on being " \
+ "remembered across bundler invocations, which bundler no longer " \
+ "does. Instead please use `bundle config set frozen true`, " \
+ "and stop using this flag"
+ )
+ end
+ end
+
+ context "bundle cache --no-prune" do
+ before do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ bundle "cache --no-prune", raise_on_error: false
+ end
+
+ it "fails with a helpful error" do
+ expect(err).to include(
+ "The `--no-prune` flag has been removed because it relied on being " \
+ "remembered across bundler invocations, which bundler no longer " \
+ "does. Instead please use `bundle config set no_prune true`, " \
+ "and stop using this flag"
+ )
+ end
end
describe "bundle config" do
@@ -205,11 +281,11 @@ RSpec.describe "major deprecations" do
bundle "config"
end
- it "warns", bundler: "3" do
+ it "warns", bundler: "4" do
expect(deprecations).to include("Using the `config` command without a subcommand [list, get, set, unset] is deprecated and will be removed in the future. Use `bundle config list` instead.")
end
- pending "fails with a helpful error", bundler: "3"
+ pending "fails with a helpful error", bundler: "5"
end
describe "old get interface" do
@@ -217,11 +293,11 @@ RSpec.describe "major deprecations" do
bundle "config waka"
end
- it "warns", bundler: "3" do
+ it "warns", bundler: "4" do
expect(deprecations).to include("Using the `config` command without a subcommand [list, get, set, unset] is deprecated and will be removed in the future. Use `bundle config get waka` instead.")
end
- pending "fails with a helpful error", bundler: "3"
+ pending "fails with a helpful error", bundler: "5"
end
describe "old set interface" do
@@ -229,11 +305,11 @@ RSpec.describe "major deprecations" do
bundle "config waka wakapun"
end
- it "warns", bundler: "3" do
+ it "warns", bundler: "4" do
expect(deprecations).to include("Using the `config` command without a subcommand [list, get, set, unset] is deprecated and will be removed in the future. Use `bundle config set waka wakapun` instead.")
end
- pending "fails with a helpful error", bundler: "3"
+ pending "fails with a helpful error", bundler: "5"
end
describe "old set interface with --local" do
@@ -241,11 +317,11 @@ RSpec.describe "major deprecations" do
bundle "config --local waka wakapun"
end
- it "warns", bundler: "3" do
+ it "warns", bundler: "4" do
expect(deprecations).to include("Using the `config` command without a subcommand [list, get, set, unset] is deprecated and will be removed in the future. Use `bundle config set --local waka wakapun` instead.")
end
- pending "fails with a helpful error", bundler: "3"
+ pending "fails with a helpful error", bundler: "5"
end
describe "old set interface with --global" do
@@ -253,11 +329,11 @@ RSpec.describe "major deprecations" do
bundle "config --global waka wakapun"
end
- it "warns", bundler: "3" do
+ it "warns", bundler: "4" do
expect(deprecations).to include("Using the `config` command without a subcommand [list, get, set, unset] is deprecated and will be removed in the future. Use `bundle config set --global waka wakapun` instead.")
end
- pending "fails with a helpful error", bundler: "3"
+ pending "fails with a helpful error", bundler: "5"
end
describe "old unset interface" do
@@ -265,11 +341,11 @@ RSpec.describe "major deprecations" do
bundle "config --delete waka"
end
- it "warns", bundler: "3" do
+ it "warns", bundler: "4" do
expect(deprecations).to include("Using the `config` command without a subcommand [list, get, set, unset] is deprecated and will be removed in the future. Use `bundle config unset waka` instead.")
end
- pending "fails with a helpful error", bundler: "3"
+ pending "fails with a helpful error", bundler: "5"
end
describe "old unset interface with --local" do
@@ -277,11 +353,11 @@ RSpec.describe "major deprecations" do
bundle "config --delete --local waka"
end
- it "warns", bundler: "3" do
+ it "warns", bundler: "4" do
expect(deprecations).to include("Using the `config` command without a subcommand [list, get, set, unset] is deprecated and will be removed in the future. Use `bundle config unset --local waka` instead.")
end
- pending "fails with a helpful error", bundler: "3"
+ pending "fails with a helpful error", bundler: "5"
end
describe "old unset interface with --global" do
@@ -289,28 +365,28 @@ RSpec.describe "major deprecations" do
bundle "config --delete --global waka"
end
- it "warns", bundler: "3" do
+ it "warns", bundler: "4" do
expect(deprecations).to include("Using the `config` command without a subcommand [list, get, set, unset] is deprecated and will be removed in the future. Use `bundle config unset --global waka` instead.")
end
- pending "fails with a helpful error", bundler: "3"
+ pending "fails with a helpful error", bundler: "5"
end
end
describe "bundle update" do
before do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
end
- it "warns when no options are given", bundler: "3" do
+ it "warns when no options are given", bundler: "4" do
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"
+ pending "fails with a helpful error when no options are given", bundler: "5"
it "does not warn when --all is passed" do
bundle "update --all"
@@ -320,24 +396,22 @@ RSpec.describe "major deprecations" do
describe "bundle install --binstubs" do
before do
- install_gemfile <<-G, binstubs: true
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ install_gemfile <<-G, binstubs: true, raise_on_error: false
+ source "https://gem.repo1"
+ gem "myrack"
G
end
- 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`")
+ it "fails with a helpful error" do
+ expect(err).to include("The --binstubs option has been removed in favor of `bundle binstubs --all`")
end
-
- pending "fails with a helpful error", bundler: "3"
end
context "bundle install with both gems.rb and Gemfile present" do
it "should not warn about gems.rb" do
- create_file "gems.rb", <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ gemfile "gems.rb", <<-G
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle :install
@@ -345,17 +419,17 @@ RSpec.describe "major deprecations" do
end
it "should print a proper warning, and use gems.rb" do
- create_file "gems.rb", "source \"#{file_uri_for(gem_repo1)}\""
+ gemfile "gems.rb", "source 'https://gem.repo1'"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
expect(warnings).to include(
"Multiple gemfiles (gems.rb and Gemfile) detected. Make sure you remove Gemfile and Gemfile.lock since bundler is ignoring them in favor of gems.rb and gems.locked."
)
- expect(the_bundle).not_to include_gem "rack 1.0"
+ expect(the_bundle).not_to include_gem "myrack 1.0"
end
end
@@ -364,8 +438,8 @@ RSpec.describe "major deprecations" do
bundle "config set --local path vendor/bundle"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
end
@@ -383,123 +457,175 @@ RSpec.describe "major deprecations" do
}.each do |name, expectations|
option_name, value = *expectations
flag_name = "--#{name}"
+ args = %w[true false].include?(value) ? flag_name : "#{flag_name} #{value}"
context "with the #{flag_name} flag" do
before do
bundle "install" # to create a lockfile, which deployment or frozen need
- bundle "install #{flag_name} #{value}"
+
+ bundle "install #{args}", raise_on_error: false
end
- 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 #{option_name} #{value}`, and stop using this flag"
+ it "fails with a helpful error" do
+ expect(err).to include(
+ "The `#{flag_name}` flag has been removed because it relied on " \
+ "being remembered across bundler invocations, which bundler no " \
+ "longer does. Instead please use `bundle config set " \
+ "#{option_name} #{value}`, and stop using this flag"
)
end
-
- pending "fails with a helpful error", bundler: "3"
end
end
end
context "bundle install with multiple sources" do
before do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo3)}"
- source "#{file_uri_for(gem_repo1)}"
+ install_gemfile <<-G, raise_on_error: false
+ source "https://gem.repo3"
+ source "https://gem.repo1"
G
end
- it "shows a deprecation", bundler: "< 3" do
- expect(deprecations).to include(
- "Your Gemfile contains multiple global 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."
+ it "fails with a helpful error" do
+ expect(err).to include(
+ "This Gemfile contains multiple global sources. " \
+ "Each source after the first must include a block to indicate which gems " \
+ "should come from that source"
)
end
- it "doesn't show lockfile deprecations if there's a lockfile", bundler: "< 3" do
- bundle "install"
+ it "doesn't show lockfile deprecations if there's a lockfile" do
+ lockfile <<~L
+ GEM
+ remote: https://gem.repo3/
+ remote: https://gem.repo1/
+ specs:
- expect(deprecations).to include(
- "Your Gemfile contains multiple global 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."
+ PLATFORMS
+ #{lockfile_platforms}
+
+ DEPENDENCIES
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ bundle "install", raise_on_error: false
+
+ expect(err).to include(
+ "This Gemfile contains multiple global sources. " \
+ "Each source after the first must include a block to indicate which gems " \
+ "should come from that source"
)
- expect(deprecations).not_to include(
+ expect(err).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"
+ bundle "install", raise_on_error: false
- expect(deprecations).to include(
- "Your Gemfile contains multiple global 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(err).to include(
+ "This Gemfile contains multiple global sources. " \
+ "Each source after the first must include a block to indicate which gems " \
+ "should come from that source"
)
- expect(deprecations).not_to include(
+ expect(err).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 "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
+ context "bundle install 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"
+ build_repo3 do
+ build_gem "myrack", "0.9.1"
end
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- source "#{file_uri_for(gem_repo3)}" do
- gem 'rack'
+ source "https://gem.repo1"
+ source "https://gem.repo3" do
+ gem 'myrack'
end
G
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo1)}/
- remote: #{file_uri_for(gem_repo3)}/
+ remote: https://gem.repo1/
+ remote: https://gem.repo3/
specs:
- rack (0.9.1)
+ myrack (0.9.1)
PLATFORMS
ruby
DEPENDENCIES
- rack!
+ myrack!
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
+ end
- bundle "config set --local frozen true"
+ it "shows an error" do
+ bundle "install", raise_on_error: false
+
+ expect(err).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
+ end
+
+ context "bundle install with a lockfile including X64_MINGW_LEGACY platform" do
+ before do
+ gemfile <<~G
+ source "https://gem.repo1"
+ gem "rake"
+ G
- it "shows a deprecation", bundler: "< 3" do
- bundle "install"
+ lockfile <<~L
+ GEM
+ remote: https://rubygems.org/
+ specs:
+ rake (10.3.2)
- 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.")
+ PLATFORMS
+ ruby
+ x64-mingw32
+
+ DEPENDENCIES
+ rake
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
end
- pending "fails with a helpful error", bundler: "3"
+ it "warns a helpful error" do
+ bundle "install", raise_on_error: false
+
+ expect(err).to include("Found x64-mingw32 in lockfile, which is deprecated and will be removed in the future.")
+ end
+ end
+
+ context "with a global path source" do
+ before do
+ build_lib "foo"
+
+ install_gemfile <<-G, raise_on_error: false
+ path "#{lib_path("foo-1.0")}"
+ gem 'foo'
+ G
+ end
+
+ it "shows an error" do
+ expect(err).to include("You can no longer specify a path source by itself")
+ end
end
context "when Bundler.setup is run in a ruby script" do
before do
- create_file "gems.rb", "source \"#{file_uri_for(gem_repo1)}\""
+ create_file "gems.rb", "source 'https://gem.repo1'"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :group => :test
+ source "https://gem.repo1"
+ gem "myrack", :group => :test
G
ruby <<-RUBY
@@ -519,86 +645,97 @@ RSpec.describe "major deprecations" do
context "when `bundler/deployment` is required in a ruby script" do
before do
- ruby <<-RUBY
+ ruby <<-RUBY, raise_on_error: false
require 'bundler/deployment'
RUBY
end
- it "should print a capistrano deprecation warning", bundler: "< 3" do
- expect(deprecations).to include("Bundler no longer integrates " \
+ it "should print a capistrano deprecation warning" do
+ expect(err).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
+ end
- pending "fails with a helpful error", bundler: "3"
+ context "when `bundler/capistrano` is required in a ruby script" do
+ before do
+ ruby <<-RUBY, raise_on_error: false
+ require 'bundler/capistrano'
+ RUBY
+ end
+
+ it "fails with a helpful error" do
+ expect(err).to include("[REMOVED] The Bundler task for Capistrano. Please use https://github.com/capistrano/bundler")
+ end
+ end
+
+ context "when `bundler/vlad` is required in a ruby script" do
+ before do
+ ruby <<-RUBY, raise_on_error: false
+ require 'bundler/vlad'
+ RUBY
+ end
+
+ it "fails with a helpful error" do
+ expect(err).to include("[REMOVED] The Bundler task for Vlad")
+ end
end
context "bundle show" do
before do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
end
context "with --outdated flag" do
before do
- bundle "show --outdated"
+ bundle "show --outdated", raise_on_error: false
end
- 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")
+ it "fails with a helpful message" do
+ expect(err).to include("the `--outdated` flag to `bundle show` has been removed in favor of `bundle show --verbose`")
end
-
- pending "fails with a helpful message", bundler: "3"
end
end
context "bundle remove" do
before do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
end
context "with --install" do
- it "shows a deprecation warning", bundler: "< 3" do
- bundle "remove rack --install"
+ it "fails with a helpful message" do
+ bundle "remove myrack --install", raise_on_error: false
- expect(err).to include "[DEPRECATED] The `--install` flag has been deprecated. `bundle install` is triggered by default."
+ expect(err).to include "The `--install` flag has been removed. `bundle install` is triggered by default."
end
-
- pending "fails with a helpful message", bundler: "3"
end
end
- context "bundle console" do
+ context "bundle viz" do
before do
- bundle "console", raise_on_error: false
+ bundle "viz", raise_on_error: false
end
- it "prints a deprecation warning", bundler: "< 3" do
- expect(deprecations).to include \
- "bundle console will be replaced by `bin/console` generated by `bundle gem <name>`"
+ it "fails with a helpful message" do
+ expect(err).to include "The `viz` command has been renamed to `graph` and moved to a plugin. See https://github.com/rubygems/bundler-graph"
end
-
- pending "fails with a helpful message", bundler: "3"
end
- context "bundle viz", :realworld do
+ context "bundle inject" do
before do
- realworld_system_gems "ruby-graphviz --version 1.2.5"
- create_file "gems.rb", "source \"#{file_uri_for(gem_repo1)}\""
- bundle "viz"
+ bundle "inject", raise_on_error: false
end
- 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"
+ it "fails with a helpful message" do
+ expect(err).to include "The `inject` command has been replaced by the `add` command"
end
-
- pending "fails with a helpful message", bundler: "3"
end
context "bundle plugin install --local_git" do
@@ -608,17 +745,14 @@ RSpec.describe "major deprecations" do
end
end
- it "prints a deprecation warning", bundler: "< 3" do
- bundle "plugin install foo --local_git #{lib_path("foo-1.0")}"
+ it "fails with a helpful message" do
+ bundle "plugin install foo --local_git #{lib_path("foo-1.0")}", raise_on_error: false
- expect(out).to include("Installed plugin foo")
- expect(deprecations).to include "--local_git is deprecated, use --git"
+ expect(err).to include "--local_git has been removed, use --git"
end
-
- pending "fails with a helpful message", bundler: "3"
end
- describe "deprecating rubocop" do
+ describe "removing rubocop" do
before do
global_config "BUNDLE_GEM__MIT" => "false", "BUNDLE_GEM__TEST" => "false", "BUNDLE_GEM__COC" => "false",
"BUNDLE_GEM__CI" => "false", "BUNDLE_GEM__CHANGELOG" => "false"
@@ -629,9 +763,9 @@ RSpec.describe "major deprecations" do
bundle "gem my_new_gem --rubocop", raise_on_error: false
end
- it "prints a deprecation warning", bundler: "< 3" do
- expect(deprecations).to include \
- "--rubocop is deprecated, use --linter=rubocop"
+ it "prints an error" do
+ expect(err).to include \
+ "--rubocop has been removed, use --linter=rubocop"
end
end
@@ -640,32 +774,22 @@ RSpec.describe "major deprecations" do
bundle "gem my_new_gem --no-rubocop", raise_on_error: false
end
- it "prints a deprecation warning", bundler: "< 3" do
- expect(deprecations).to include \
- "--no-rubocop is deprecated, use --linter"
+ it "prints an error" do
+ expect(err).to include \
+ "--no-rubocop has been removed, use --no-linter"
end
end
+ end
- context "bundle gem with gem.rubocop set to true" do
- before do
- bundle "gem my_new_gem", env: { "BUNDLE_GEM__RUBOCOP" => "true" }, raise_on_error: false
- end
-
- 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
+ context " bundle gem --ext parameter with no value" do
+ it "prints error when used before gem name" do
+ bundle "gem --ext foo", raise_on_error: false
+ expect(err).to include "Extensions can now be generated using C or Rust, so `--ext` with no arguments has been removed. Please select a language, e.g. `--ext=rust` to generate a Rust extension."
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: "< 3" do
- expect(deprecations).to include \
- "config gem.rubocop is deprecated; we've updated your config to use gem.linter instead"
- end
+ it "prints error when used after gem name" do
+ bundle "gem foo --ext", raise_on_error: false
+ expect(err).to include "Extensions can now be generated using C or Rust, so `--ext` with no arguments has been removed. Please select a language, e.g. `--ext=rust` to generate a Rust extension."
end
end
end
diff --git a/spec/bundler/plugins/command_spec.rb b/spec/bundler/plugins/command_spec.rb
index af132d6550..f8dacb0e51 100644
--- a/spec/bundler/plugins/command_spec.rb
+++ b/spec/bundler/plugins/command_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe "command plugins" do
end
end
- bundle "plugin install command-mah --source #{file_uri_for(gem_repo2)}"
+ bundle "plugin install command-mah --source https://gem.repo2"
end
it "executes without arguments" do
@@ -29,7 +29,7 @@ RSpec.describe "command plugins" do
end
it "accepts the arguments" do
- build_repo2 do
+ update_repo2 do
build_plugin "the-echoer" do |s|
s.write "plugins.rb", <<-RUBY
module Resonance
@@ -46,7 +46,7 @@ RSpec.describe "command plugins" do
end
end
- bundle "plugin install the-echoer --source #{file_uri_for(gem_repo2)}"
+ bundle "plugin install the-echoer --source https://gem.repo2"
expect(out).to include("Installed plugin the-echoer")
bundle "echo tacos tofu lasange"
@@ -54,7 +54,7 @@ RSpec.describe "command plugins" do
end
it "raises error on redeclaration of command" do
- build_repo2 do
+ update_repo2 do
build_plugin "copycat" do |s|
s.write "plugins.rb", <<-RUBY
module CopyCat
@@ -69,7 +69,7 @@ RSpec.describe "command plugins" do
end
end
- bundle "plugin install copycat --source #{file_uri_for(gem_repo2)}", raise_on_error: false
+ bundle "plugin install copycat --source https://gem.repo2", raise_on_error: false
expect(out).not_to include("Installed plugin copycat")
diff --git a/spec/bundler/plugins/hook_spec.rb b/spec/bundler/plugins/hook_spec.rb
index f6ee0ba210..3f9053bbc8 100644
--- a/spec/bundler/plugins/hook_spec.rb
+++ b/spec/bundler/plugins/hook_spec.rb
@@ -13,17 +13,17 @@ RSpec.describe "hook plugins" do
end
end
- bundle "plugin install before-install-all-plugin --source #{file_uri_for(gem_repo2)}"
+ bundle "plugin install before-install-all-plugin --source https://gem.repo2"
end
it "runs before all rubygems are installed" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rake"
- gem "rack"
+ gem "myrack"
G
- expect(out).to include "gems to be installed rake, rack"
+ expect(out).to include "gems to be installed rake, myrack"
end
end
@@ -39,18 +39,18 @@ RSpec.describe "hook plugins" do
end
end
- bundle "plugin install before-install-plugin --source #{file_uri_for(gem_repo2)}"
+ bundle "plugin install before-install-plugin --source https://gem.repo2"
end
it "runs before each rubygem is installed" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rake"
- gem "rack"
+ gem "myrack"
G
expect(out).to include "installing gem rake"
- expect(out).to include "installing gem rack"
+ expect(out).to include "installing gem myrack"
end
end
@@ -66,17 +66,17 @@ RSpec.describe "hook plugins" do
end
end
- bundle "plugin install after-install-all-plugin --source #{file_uri_for(gem_repo2)}"
+ bundle "plugin install after-install-all-plugin --source https://gem.repo2"
end
- it "runs after each rubygem is installed" do
+ it "runs after each all rubygems are installed" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rake"
- gem "rack"
+ gem "myrack"
G
- expect(out).to include "installed gems rake, rack"
+ expect(out).to include "installed gems rake, myrack"
end
end
@@ -92,18 +92,18 @@ RSpec.describe "hook plugins" do
end
end
- bundle "plugin install after-install-plugin --source #{file_uri_for(gem_repo2)}"
+ bundle "plugin install after-install-plugin --source https://gem.repo2"
end
it "runs after each rubygem is installed" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rake"
- gem "rack"
+ gem "myrack"
G
expect(out).to include "installed gem rake : installed"
- expect(out).to include "installed gem rack : installed"
+ expect(out).to include "installed gem myrack : installed"
end
end
@@ -119,12 +119,12 @@ RSpec.describe "hook plugins" do
end
end
- bundle "plugin install before-require-all-plugin --source #{file_uri_for(gem_repo2)}"
+ bundle "plugin install before-require-all-plugin --source https://gem.repo2"
end
it "runs before all rubygems are required" do
install_gemfile_and_bundler_require
- expect(out).to include "gems to be required rake, rack"
+ expect(out).to include "gems to be required rake, myrack"
end
end
@@ -140,13 +140,13 @@ RSpec.describe "hook plugins" do
end
end
- bundle "plugin install before-require-plugin --source #{file_uri_for(gem_repo2)}"
+ bundle "plugin install before-require-plugin --source https://gem.repo2"
end
it "runs before each rubygem is required" do
install_gemfile_and_bundler_require
expect(out).to include "requiring gem rake"
- expect(out).to include "requiring gem rack"
+ expect(out).to include "requiring gem myrack"
end
end
@@ -162,12 +162,12 @@ RSpec.describe "hook plugins" do
end
end
- bundle "plugin install after-require-all-plugin --source #{file_uri_for(gem_repo2)}"
+ bundle "plugin install after-require-all-plugin --source https://gem.repo2"
end
it "runs after all rubygems are required" do
install_gemfile_and_bundler_require
- expect(out).to include "required gems rake, rack"
+ expect(out).to include "required gems rake, myrack"
end
end
@@ -183,21 +183,21 @@ RSpec.describe "hook plugins" do
end
end
- bundle "plugin install after-require-plugin --source #{file_uri_for(gem_repo2)}"
+ bundle "plugin install after-require-plugin --source https://gem.repo2"
end
it "runs after each rubygem is required" do
install_gemfile_and_bundler_require
expect(out).to include "required gem rake"
- expect(out).to include "required gem rack"
+ expect(out).to include "required gem myrack"
end
end
def install_gemfile_and_bundler_require
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rake"
- gem "rack"
+ gem "myrack"
G
ruby <<-RUBY
diff --git a/spec/bundler/plugins/install_spec.rb b/spec/bundler/plugins/install_spec.rb
index 20c2f1fd26..6cace961f5 100644
--- a/spec/bundler/plugins/install_spec.rb
+++ b/spec/bundler/plugins/install_spec.rb
@@ -9,28 +9,28 @@ RSpec.describe "bundler plugin install" do
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)}", raise_on_error: false
+ bundle "plugin install no-foo --source https://gem.repo1", raise_on_error: false
expect(err).to include("Could not find")
plugin_should_not_be_installed("no-foo")
end
it "installs from rubygems source" do
- bundle "plugin install foo --source #{file_uri_for(gem_repo2)}"
+ bundle "plugin install foo --source https://gem.repo2"
expect(out).to include("Installed plugin foo")
plugin_should_be_installed("foo")
end
it "installs from rubygems source in frozen mode" do
- bundle "plugin install foo --source #{file_uri_for(gem_repo2)}", env: { "BUNDLE_DEPLOYMENT" => "true" }
+ bundle "plugin install foo --source https://gem.repo2", env: { "BUNDLE_DEPLOYMENT" => "true" }
expect(out).to include("Installed plugin foo")
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 }
+ bundle "plugin install foo", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_SOURCES" => "https://gem.repo2" }
expect(out).to include("Installed plugin foo")
plugin_should_be_installed("foo")
@@ -45,18 +45,18 @@ RSpec.describe "bundler plugin install" do
context "plugin is already installed" do
before do
- bundle "plugin install foo --source #{file_uri_for(gem_repo2)}"
+ bundle "plugin install foo --source https://gem.repo2"
end
it "doesn't install plugin again" do
- bundle "plugin install foo --source #{file_uri_for(gem_repo2)}"
+ bundle "plugin install foo --source https://gem.repo2"
expect(out).not_to include("Installing plugin foo")
expect(out).not_to include("Installed plugin foo")
end
end
it "installs multiple plugins" do
- bundle "plugin install foo kung-foo --source #{file_uri_for(gem_repo2)}"
+ bundle "plugin install foo kung-foo --source https://gem.repo2"
expect(out).to include("Installed plugin foo")
expect(out).to include("Installed plugin kung-foo")
@@ -70,7 +70,7 @@ RSpec.describe "bundler plugin install" do
build_plugin "kung-foo", "1.1"
end
- bundle "plugin install foo kung-foo --version '1.0' --source #{file_uri_for(gem_repo2)}"
+ bundle "plugin install foo kung-foo --version '1.0' --source https://gem.repo2"
expect(out).to include("Installing foo 1.0")
expect(out).to include("Installing kung-foo 1.0")
@@ -82,18 +82,18 @@ RSpec.describe "bundler plugin install" do
build_plugin "foo", "1.1"
end
- bundle "plugin install foo --version 1.0 --source #{file_uri_for(gem_repo2)} --verbose"
+ bundle "plugin install foo --version 1.0 --source https://gem.repo2 --verbose"
expect(out).to include("Installing foo 1.0")
- bundle "plugin install foo --source #{file_uri_for(gem_repo2)} --verbose"
+ bundle "plugin install foo --source https://gem.repo2 --verbose"
expect(out).to include("Installing foo 1.1")
- bundle "plugin install foo --source #{file_uri_for(gem_repo2)} --verbose"
+ bundle "plugin install foo --source https://gem.repo2 --verbose"
expect(out).to include("Using foo 1.1")
end
it "raises an error when when --branch specified" do
- bundle "plugin install foo --branch main --source #{file_uri_for(gem_repo2)}", raise_on_error: false
+ bundle "plugin install foo --branch main --source https://gem.repo2", raise_on_error: false
expect(out).not_to include("Installed plugin foo")
@@ -101,13 +101,13 @@ RSpec.describe "bundler plugin install" do
end
it "raises an error when --ref specified" do
- bundle "plugin install foo --ref v1.2.3 --source #{file_uri_for(gem_repo2)}", raise_on_error: false
+ bundle "plugin install foo --ref v1.2.3 --source https://gem.repo2", raise_on_error: false
expect(err).to include("--ref can only be used with git sources")
end
it "raises error when both --branch and --ref options are specified" do
- bundle "plugin install foo --source #{file_uri_for(gem_repo2)} --branch main --ref v1.2.3", raise_on_error: false
+ bundle "plugin install foo --source https://gem.repo2 --branch main --ref v1.2.3", raise_on_error: false
expect(out).not_to include("Installed plugin foo")
@@ -131,7 +131,7 @@ RSpec.describe "bundler plugin install" do
s.write("src/fubar.rb")
end
end
- bundle "plugin install testing --source #{file_uri_for(gem_repo2)}"
+ bundle "plugin install testing --source https://gem.repo2"
bundle "check2", "no-color" => false
expect(out).to eq("mate")
@@ -144,17 +144,17 @@ RSpec.describe "bundler plugin install" do
build_plugin "kung-foo", "1.1"
end
- bundle "plugin install foo kung-foo --version '1.0' --source #{file_uri_for(gem_repo2)}"
+ bundle "plugin install foo kung-foo --version '1.0' --source https://gem.repo2"
expect(out).to include("Installing foo 1.0")
expect(out).to include("Installing kung-foo 1.0")
plugin_should_be_installed("foo", "kung-foo")
- build_repo2 do
+ update_repo2 do
build_gem "charlie"
end
- bundle "plugin install charlie --source #{file_uri_for(gem_repo2)}", raise_on_error: false
+ bundle "plugin install charlie --source https://gem.repo2", raise_on_error: false
expect(err).to include("Failed to install plugin `charlie`, due to Bundler::Plugin::MalformattedPlugin (plugins.rb was not found in the plugin.)")
@@ -168,12 +168,12 @@ RSpec.describe "bundler plugin install" do
build_repo2 do
build_plugin "chaplin" do |s|
s.write "plugins.rb", <<-RUBY
- raise "I got you man"
+ raise RuntimeError, "threw exception on load"
RUBY
end
end
- bundle "plugin install chaplin --source #{file_uri_for(gem_repo2)}", raise_on_error: false
+ bundle "plugin install chaplin --source https://gem.repo2", raise_on_error: false
expect(global_plugin_gem("chaplin-1.0")).not_to be_directory
@@ -187,7 +187,7 @@ RSpec.describe "bundler plugin install" do
s.write "plugins.rb"
end
- bundle "plugin install foo --git #{file_uri_for(lib_path("foo-1.0"))}"
+ bundle "plugin install foo --git #{lib_path("foo-1.0")}"
expect(out).to include("Installed plugin foo")
plugin_should_be_installed("foo")
@@ -203,13 +203,6 @@ RSpec.describe "bundler plugin install" do
expect(out).to include("Installed plugin foo")
plugin_should_be_installed("foo")
end
-
- it "raises an error when both git and local git sources are specified", bundler: "< 3" do
- bundle "plugin install foo --git /phony/path/project --local_git git@gitphony.com:/repo/project", raise_on_error: false
-
- expect(exitstatus).not_to eq(0)
- expect(err).to eq("Remote and local plugin git sources can't be both specified")
- end
end
context "path plugins" do
@@ -257,9 +250,9 @@ RSpec.describe "bundler plugin install" do
it "installs plugins listed in gemfile" do
gemfile <<-G
- source '#{file_uri_for(gem_repo2)}'
+ source 'https://gem.repo2'
plugin 'foo'
- gem 'rack', "1.0.0"
+ gem 'myrack', "1.0.0"
G
bundle "install"
@@ -268,7 +261,7 @@ RSpec.describe "bundler plugin install" do
expect(out).to include("Bundle complete!")
- expect(the_bundle).to include_gems("rack 1.0.0")
+ expect(the_bundle).to include_gems("myrack 1.0.0")
plugin_should_be_installed("foo")
end
@@ -278,7 +271,7 @@ RSpec.describe "bundler plugin install" do
end
gemfile <<-G
- source '#{file_uri_for(gem_repo2)}'
+ source 'https://gem.repo2'
plugin 'foo', "1.0"
G
@@ -297,7 +290,7 @@ RSpec.describe "bundler plugin install" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
plugin 'ga-plugin', :git => "#{lib_path("ga-plugin-1.0")}"
G
@@ -311,7 +304,7 @@ RSpec.describe "bundler plugin install" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
plugin 'ga-plugin', :path => "#{lib_path("ga-plugin-1.0")}"
G
@@ -326,7 +319,7 @@ RSpec.describe "bundler plugin install" do
path = lib_path("ga-plugin-1.0").relative_path_from(bundled_app)
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
plugin 'ga-plugin', :path => "#{path}"
G
@@ -337,22 +330,22 @@ RSpec.describe "bundler plugin install" do
context "in deployment mode" do
it "installs plugins" do
install_gemfile <<-G
- source '#{file_uri_for(gem_repo2)}'
- gem 'rack', "1.0.0"
+ source 'https://gem.repo2'
+ gem 'myrack', "1.0.0"
G
bundle "config set --local deployment true"
install_gemfile <<-G
- source '#{file_uri_for(gem_repo2)}'
+ source 'https://gem.repo2'
plugin 'foo'
- gem 'rack', "1.0.0"
+ gem 'myrack', "1.0.0"
G
expect(out).to include("Installed plugin foo")
expect(out).to include("Bundle complete!")
- expect(the_bundle).to include_gems("rack 1.0.0")
+ expect(the_bundle).to include_gems("myrack 1.0.0")
plugin_should_be_installed("foo")
end
end
@@ -364,12 +357,12 @@ RSpec.describe "bundler plugin install" do
require "bundler/inline"
gemfile do
- source '#{file_uri_for(gem_repo2)}'
+ source 'https://gem.repo2'
plugin 'foo'
end
RUBY
- ruby code, env: { "BUNDLER_VERSION" => Bundler::VERSION }
+ ruby code, artifice: "compact_index", env: { "BUNDLER_VERSION" => Bundler::VERSION }
expect(local_plugin_gem("foo-1.0", "plugins.rb")).to exist
end
end
@@ -378,7 +371,7 @@ RSpec.describe "bundler plugin install" 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)}"
+ bundle "plugin install foo --source https://gem.repo2"
plugin_should_be_installed("foo")
expect(local_plugin_gem("foo-1.0")).to be_directory
@@ -401,7 +394,7 @@ RSpec.describe "bundler plugin install" do
end
# inside the app
- gemfile "source '#{file_uri_for(gem_repo2)}'\nplugin 'fubar'"
+ gemfile "source 'https://gem.repo2'\nplugin 'fubar'"
bundle "install"
update_repo2 do
@@ -419,7 +412,7 @@ RSpec.describe "bundler plugin install" do
end
# outside the app
- bundle "plugin install fubar --source #{file_uri_for(gem_repo2)}", dir: tmp
+ bundle "plugin install fubar --source https://gem.repo2", dir: tmp
end
it "inside the app takes precedence over global plugin" do
diff --git a/spec/bundler/plugins/list_spec.rb b/spec/bundler/plugins/list_spec.rb
index 4a686415ad..30e3f82467 100644
--- a/spec/bundler/plugins/list_spec.rb
+++ b/spec/bundler/plugins/list_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe "bundler plugin list" do
context "single plugin installed" do
it "shows plugin name with commands list" do
- bundle "plugin install foo --source #{file_uri_for(gem_repo2)}"
+ bundle "plugin install foo --source https://gem.repo2"
plugin_should_be_installed("foo")
bundle "plugin list"
@@ -49,7 +49,7 @@ RSpec.describe "bundler plugin list" do
context "multiple plugins installed" do
it "shows plugin names with commands list" do
- bundle "plugin install foo bar --source #{file_uri_for(gem_repo2)}"
+ bundle "plugin install foo bar --source https://gem.repo2"
plugin_should_be_installed("foo", "bar")
bundle "plugin list"
diff --git a/spec/bundler/plugins/source/example_spec.rb b/spec/bundler/plugins/source/example_spec.rb
index e569f3e415..e64e4d6330 100644
--- a/spec/bundler/plugins/source/example_spec.rb
+++ b/spec/bundler/plugins/source/example_spec.rb
@@ -52,7 +52,7 @@ RSpec.describe "real source plugins" do
build_lib "a-path-gem"
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}" # plugin source
+ source "https://gem.repo2" # plugin source
source "#{lib_path("a-path-gem-1.0")}", :type => :mpath do
gem "a-path-gem"
end
@@ -67,10 +67,10 @@ RSpec.describe "real source plugins" do
expect(the_bundle).to include_gems("a-path-gem 1.0")
end
- it "writes to lock file" do
+ it "writes to lockfile" do
bundle "install"
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "a-path-gem", "1.0"
end
@@ -82,7 +82,7 @@ RSpec.describe "real source plugins" do
a-path-gem (1.0)
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
PLATFORMS
@@ -92,7 +92,7 @@ RSpec.describe "real source plugins" do
a-path-gem!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
@@ -110,7 +110,7 @@ RSpec.describe "real source plugins" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}" # plugin source
+ source "https://gem.repo2" # plugin source
source "#{lib_path("gem_with_bin-1.0")}", :type => :mpath do
gem "gem_with_bin"
end
@@ -124,38 +124,35 @@ RSpec.describe "real source plugins" do
let(:uri_hash) { Digest(:SHA1).hexdigest(lib_path("a-path-gem-1.0").to_s) }
it "copies repository to vendor cache and uses it" do
bundle "install"
- bundle "config set cache_all true"
bundle :cache
expect(bundled_app("vendor/cache/a-path-gem-1.0-#{uri_hash}")).to exist
expect(bundled_app("vendor/cache/a-path-gem-1.0-#{uri_hash}/.git")).not_to exist
expect(bundled_app("vendor/cache/a-path-gem-1.0-#{uri_hash}/.bundlecache")).to be_file
- FileUtils.rm_rf lib_path("a-path-gem-1.0")
+ FileUtils.rm_r lib_path("a-path-gem-1.0")
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 `path` configured" do
bundle "config set --local path vendor/bundle"
bundle :install
- bundle "config set cache_all true"
bundle :cache
expect(bundled_app("vendor/cache/a-path-gem-1.0-#{uri_hash}")).to exist
- FileUtils.rm_rf lib_path("a-path-gem-1.0")
+ FileUtils.rm_r lib_path("a-path-gem-1.0")
expect(the_bundle).to include_gems("a-path-gem 1.0")
end
it "bundler package copies repository to vendor cache" do
bundle "config set --local path vendor/bundle"
bundle :install
- bundle "config set cache_all true"
bundle :cache
expect(bundled_app("vendor/cache/a-path-gem-1.0-#{uri_hash}")).to exist
- FileUtils.rm_rf lib_path("a-path-gem-1.0")
+ FileUtils.rm_r lib_path("a-path-gem-1.0")
expect(the_bundle).to include_gems("a-path-gem 1.0")
end
end
@@ -170,7 +167,7 @@ RSpec.describe "real source plugins" do
a-path-gem (1.0)
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
PLATFORMS
@@ -180,7 +177,7 @@ RSpec.describe "real source plugins" do
a-path-gem!
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
@@ -323,8 +320,8 @@ RSpec.describe "real source plugins" do
build_git "ma-gitp-gem"
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}" # plugin source
- source "#{file_uri_for(lib_path("ma-gitp-gem-1.0"))}", :type => :gitp do
+ source "https://gem.repo2" # plugin source
+ source "#{lib_path("ma-gitp-gem-1.0")}", :type => :gitp do
gem "ma-gitp-gem"
end
G
@@ -336,24 +333,24 @@ RSpec.describe "real source plugins" do
expect(the_bundle).to include_gems("ma-gitp-gem 1.0")
end
- it "writes to lock file" do
+ it "writes to lockfile" do
revision = revision_for(lib_path("ma-gitp-gem-1.0"))
bundle "install"
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "ma-gitp-gem", "1.0"
end
expect(lockfile).to eq <<~G
PLUGIN SOURCE
- remote: #{file_uri_for(lib_path("ma-gitp-gem-1.0"))}
+ remote: #{lib_path("ma-gitp-gem-1.0")}
type: gitp
revision: #{revision}
specs:
ma-gitp-gem (1.0)
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
PLATFORMS
@@ -363,7 +360,7 @@ RSpec.describe "real source plugins" do
ma-gitp-gem!
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
@@ -372,14 +369,14 @@ RSpec.describe "real source plugins" do
revision = revision_for(lib_path("ma-gitp-gem-1.0"))
lockfile <<-G
PLUGIN SOURCE
- remote: #{file_uri_for(lib_path("ma-gitp-gem-1.0"))}
+ remote: #{lib_path("ma-gitp-gem-1.0")}
type: gitp
revision: #{revision}
specs:
ma-gitp-gem (1.0)
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
PLATFORMS
@@ -389,7 +386,7 @@ RSpec.describe "real source plugins" do
ma-gitp-gem!
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
@@ -423,8 +420,8 @@ RSpec.describe "real source plugins" do
it "updates the deps on change in gemfile" do
update_git "ma-gitp-gem", "1.1", path: lib_path("ma-gitp-gem-1.0"), gemspec: true
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}" # plugin source
- source "#{file_uri_for(lib_path("ma-gitp-gem-1.0"))}", :type => :gitp do
+ source "https://gem.repo2" # plugin source
+ source "#{lib_path("ma-gitp-gem-1.0")}", :type => :gitp do
gem "ma-gitp-gem", "1.1"
end
G
@@ -440,19 +437,18 @@ RSpec.describe "real source plugins" do
ref = git.ref_for("main", 11)
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}" # plugin source
+ source "https://gem.repo2" # plugin source
source '#{lib_path("foo-1.0")}', :type => :gitp do
gem "foo"
end
G
- bundle "config set cache_all true"
bundle :cache
expect(bundled_app("vendor/cache/foo-1.0-#{ref}")).to exist
expect(bundled_app("vendor/cache/foo-1.0-#{ref}/.git")).not_to exist
expect(bundled_app("vendor/cache/foo-1.0-#{ref}/.bundlecache")).to be_file
- FileUtils.rm_rf lib_path("foo-1.0")
+ FileUtils.rm_r lib_path("foo-1.0")
expect(the_bundle).to include_gems "foo 1.0"
end
end
diff --git a/spec/bundler/plugins/source_spec.rb b/spec/bundler/plugins/source_spec.rb
index 14643e5c81..995e50e653 100644
--- a/spec/bundler/plugins/source_spec.rb
+++ b/spec/bundler/plugins/source_spec.rb
@@ -16,8 +16,8 @@ RSpec.describe "bundler source plugin" do
it "installs bundler-source-* gem when no handler for source is present" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- source "#{file_uri_for(lib_path("gitp"))}", :type => :psource do
+ source "https://gem.repo2"
+ source "#{lib_path("gitp")}", :type => :psource do
end
G
@@ -38,8 +38,8 @@ RSpec.describe "bundler source plugin" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
- source "#{file_uri_for(lib_path("gitp"))}", :type => :psource do
+ source "https://gem.repo2"
+ source "#{lib_path("gitp")}", :type => :psource do
end
G
@@ -62,11 +62,11 @@ RSpec.describe "bundler source plugin" do
context "explicit presence in gemfile" do
before do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
plugin "another-psource"
- source "#{file_uri_for(lib_path("gitp"))}", :type => :psource do
+ source "#{lib_path("gitp")}", :type => :psource do
end
G
end
@@ -88,11 +88,11 @@ RSpec.describe "bundler source plugin" do
context "explicit default source" do
before do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
plugin "bundler-source-psource"
- source "#{file_uri_for(lib_path("gitp"))}", :type => :psource do
+ source "#{lib_path("gitp")}", :type => :psource do
end
G
end
diff --git a/spec/bundler/plugins/uninstall_spec.rb b/spec/bundler/plugins/uninstall_spec.rb
index 555c6a7002..dedcc9f37c 100644
--- a/spec/bundler/plugins/uninstall_spec.rb
+++ b/spec/bundler/plugins/uninstall_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe "bundler plugin uninstall" do
end
it "uninstalls specified plugins" do
- bundle "plugin install foo kung-foo --source #{file_uri_for(gem_repo2)}"
+ bundle "plugin install foo kung-foo --source https://gem.repo2"
plugin_should_be_installed("foo")
plugin_should_be_installed("kung-foo")
@@ -40,9 +40,9 @@ RSpec.describe "bundler plugin uninstall" do
allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
install_gemfile <<-G
- source '#{file_uri_for(gem_repo2)}'
+ source 'https://gem.repo2'
plugin 'path_plugin', :path => "#{path}"
- gem 'rack', '1.0.0'
+ gem 'myrack', '1.0.0'
G
plugin_should_be_installed("path_plugin")
@@ -57,7 +57,7 @@ RSpec.describe "bundler plugin uninstall" do
describe "with --all" do
it "uninstalls all installed plugins" do
- bundle "plugin install foo kung-foo --source #{file_uri_for(gem_repo2)}"
+ bundle "plugin install foo kung-foo --source https://gem.repo2"
plugin_should_be_installed("foo")
plugin_should_be_installed("kung-foo")
diff --git a/spec/bundler/quality_spec.rb b/spec/bundler/quality_spec.rb
index 7cdb993017..b60be9980f 100644
--- a/spec/bundler/quality_spec.rb
+++ b/spec/bundler/quality_spec.rb
@@ -20,6 +20,9 @@ RSpec.describe "The library itself" do
end
def check_for_tab_characters(filename)
+ # Because Go uses hard tabs
+ return if filename.end_with?(".go.tt")
+
failing_lines = []
each_line(filename) do |line, number|
failing_lines << number + 1 if line.include?("\t")
@@ -115,10 +118,8 @@ RSpec.describe "The library itself" do
end
it "maintains language quality of the documentation" do
- included = /ronn/
error_messages = []
man_tracked_files.each do |filename|
- next unless filename&.match?(included)
error_messages << check_for_expendable_words(filename)
error_messages << check_for_specific_pronouns(filename)
end
@@ -138,12 +139,12 @@ RSpec.describe "The library itself" do
it "documents all used settings" do
exemptions = %w[
- forget_cli_options
gem.changelog
gem.ci
gem.coc
gem.linter
gem.mit
+ gem.bundle
gem.rubocop
gem.test
git.allow_insecure
@@ -165,7 +166,8 @@ RSpec.describe "The library itself" do
line.scan(/Bundler\.settings\[:#{key_pattern}\]/).flatten.each {|s| all_settings[s] << "referenced at `#{filename}:#{number.succ}`" }
end
end
- documented_settings = File.read("lib/bundler/man/bundle-config.1.ronn")[/LIST OF AVAILABLE KEYS.*/m].scan(/^\* `#{key_pattern}`/).flatten
+ settings_section = File.read("lib/bundler/man/bundle-config.1.ronn").split(/^## /).find {|section| section.start_with?("LIST OF AVAILABLE KEYS") }
+ documented_settings = settings_section.scan(/^\* `#{key_pattern}`/).flatten
documented_settings.each do |s|
all_settings.delete(s)
@@ -185,8 +187,8 @@ RSpec.describe "The library itself" do
end
it "can still be built" do
- with_built_bundler do |_gem_path|
- expect(err).to be_empty, "bundler should build as a gem without warnings, but\n#{err}"
+ with_built_bundler do |gem_path|
+ expect(File.exist?(gem_path)).to be true
end
end
@@ -216,7 +218,7 @@ RSpec.describe "The library itself" do
end
end
- warnings = last_command.stdboth.split("\n")
+ warnings = stdboth.split("\n")
# ignore warnings around deprecated Object#=~ method in RubyGems
warnings.reject! {|w| w =~ %r{rubygems\/version.rb.*deprecated\ Object#=~} }
@@ -236,6 +238,21 @@ RSpec.describe "The library itself" do
expect(all_bad_requires).to be_empty, "#{all_bad_requires.size} internal requires that should use `require_relative`: #{all_bad_requires}"
end
+ # We don't want our artifice code to activate bundler, but it needs to use the
+ # namespaced implementation of `Net::HTTP`. So we duplicate the file in
+ # bundler that loads that.
+ it "keeps vendored_net_http spec code in sync with the lib implementation" do
+ lib_implementation_path = File.join(source_lib_dir, "bundler", "vendored_net_http.rb")
+ expect(File.exist?(lib_implementation_path)).to be_truthy
+ lib_code = File.read(lib_implementation_path)
+
+ spec_implementation_path = File.join(spec_dir, "support", "vendored_net_http.rb")
+ expect(File.exist?(spec_implementation_path)).to be_truthy
+ spec_code = File.read(spec_implementation_path)
+
+ expect(lib_code).to eq(spec_code)
+ end
+
private
def each_line(filename, &block)
diff --git a/spec/bundler/realworld/dependency_api_spec.rb b/spec/bundler/realworld/dependency_api_spec.rb
deleted file mode 100644
index ee5c0e3d0a..0000000000
--- a/spec/bundler/realworld/dependency_api_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "../support/silent_logger"
-
-RSpec.describe "gemcutter's dependency API", realworld: true do
- context "when Gemcutter API takes too long to respond" do
- before do
- require_rack
-
- port = find_unused_port
- @server_uri = "http://127.0.0.1:#{port}"
-
- require_relative "../support/artifice/endpoint_timeout"
-
- @t = Thread.new do
- server = Rack::Server.start(app: EndpointTimeout,
- Host: "0.0.0.0",
- Port: port,
- server: "webrick",
- AccessLog: [],
- Logger: Spec::SilentLogger.new)
- server.start
- end
- @t.run
-
- wait_for_server("127.0.0.1", port)
- bundle "config set timeout 1"
- end
-
- after do
- Artifice.deactivate
- @t.kill
- @t.join
- end
-
- it "times out and falls back on the modern index" do
- install_gemfile <<-G, artifice: nil
- source "#{@server_uri}"
- gem "rack"
- G
-
- expect(out).to include("Fetching source index from #{@server_uri}/")
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
- end
-end
diff --git a/spec/bundler/realworld/edgecases_spec.rb b/spec/bundler/realworld/edgecases_spec.rb
index 94ca3554b1..391aa0cef6 100644
--- a/spec/bundler/realworld/edgecases_spec.rb
+++ b/spec/bundler/realworld/edgecases_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe "real world edgecases", realworld: true do
index.search(#{name.dump}).select {|spec| requirement.satisfied_by?(spec.version) }.last
end
if rubygem.nil?
- raise "Could not find #{name} (#{requirement}) on rubygems.org!\n" \
+ raise ArgumentError, "Could not find #{name} (#{requirement}) on rubygems.org!\n" \
"Found specs:\n\#{index.send(:specs).inspect}"
end
puts "#{name} (\#{rubygem.version})"
@@ -63,153 +63,7 @@ RSpec.describe "real world edgecases", realworld: true do
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/rubygems/bundler/issues/5031
-
- pristine_system_gems "bundler-1.99.0"
-
- gemfile <<-G
- source "https://rubygems.org"
- gem 'rails', '~> 4.2.7.1'
- gem 'paperclip', '~> 5.1.0'
- G
-
- lockfile <<-L
- GEM
- remote: https://rubygems.org/
- specs:
- actionmailer (4.2.7.1)
- actionpack (= 4.2.7.1)
- actionview (= 4.2.7.1)
- activejob (= 4.2.7.1)
- mail (~> 2.5, >= 2.5.4)
- rails-dom-testing (~> 1.0, >= 1.0.5)
- actionpack (4.2.7.1)
- actionview (= 4.2.7.1)
- activesupport (= 4.2.7.1)
- rack (~> 1.6)
- rack-test (~> 0.6.2)
- rails-dom-testing (~> 1.0, >= 1.0.5)
- rails-html-sanitizer (~> 1.0, >= 1.0.2)
- actionview (4.2.7.1)
- activesupport (= 4.2.7.1)
- builder (~> 3.1)
- erubis (~> 2.7.0)
- rails-dom-testing (~> 1.0, >= 1.0.5)
- rails-html-sanitizer (~> 1.0, >= 1.0.2)
- activejob (4.2.7.1)
- activesupport (= 4.2.7.1)
- globalid (>= 0.3.0)
- activemodel (4.2.7.1)
- activesupport (= 4.2.7.1)
- builder (~> 3.1)
- activerecord (4.2.7.1)
- activemodel (= 4.2.7.1)
- activesupport (= 4.2.7.1)
- arel (~> 6.0)
- activesupport (4.2.7.1)
- i18n (~> 0.7)
- json (~> 1.7, >= 1.7.7)
- minitest (~> 5.1)
- thread_safe (~> 0.3, >= 0.3.4)
- tzinfo (~> 1.1)
- arel (6.0.3)
- builder (3.2.2)
- climate_control (0.0.3)
- activesupport (>= 3.0)
- cocaine (0.5.8)
- climate_control (>= 0.0.3, < 1.0)
- concurrent-ruby (1.0.2)
- erubis (2.7.0)
- globalid (0.3.7)
- activesupport (>= 4.1.0)
- i18n (0.7.0)
- json (1.8.3)
- loofah (2.0.3)
- nokogiri (>= 1.5.9)
- mail (2.6.4)
- mime-types (>= 1.16, < 4)
- mime-types (3.1)
- mime-types-data (~> 3.2015)
- mime-types-data (3.2016.0521)
- mimemagic (0.3.2)
- mini_portile2 (2.1.0)
- minitest (5.9.1)
- nokogiri (1.6.8)
- mini_portile2 (~> 2.1.0)
- pkg-config (~> 1.1.7)
- paperclip (5.1.0)
- activemodel (>= 4.2.0)
- activesupport (>= 4.2.0)
- cocaine (~> 0.5.5)
- mime-types
- mimemagic (~> 0.3.0)
- pkg-config (1.1.7)
- rack (1.6.4)
- rack-test (0.6.3)
- rack (>= 1.0)
- rails (4.2.7.1)
- actionmailer (= 4.2.7.1)
- actionpack (= 4.2.7.1)
- actionview (= 4.2.7.1)
- activejob (= 4.2.7.1)
- activemodel (= 4.2.7.1)
- activerecord (= 4.2.7.1)
- activesupport (= 4.2.7.1)
- bundler (>= 1.3.0, < 2.0)
- railties (= 4.2.7.1)
- sprockets-rails
- rails-deprecated_sanitizer (1.0.3)
- activesupport (>= 4.2.0.alpha)
- rails-dom-testing (1.0.7)
- activesupport (>= 4.2.0.beta, < 5.0)
- nokogiri (~> 1.6.0)
- rails-deprecated_sanitizer (>= 1.0.1)
- rails-html-sanitizer (1.0.3)
- loofah (~> 2.0)
- railties (4.2.7.1)
- actionpack (= 4.2.7.1)
- activesupport (= 4.2.7.1)
- rake (>= 0.8.7)
- thor (>= 0.18.1, < 2.0)
- rake (11.3.0)
- sprockets (3.7.0)
- concurrent-ruby (~> 1.0)
- rack (> 1, < 3)
- sprockets-rails (3.2.0)
- actionpack (>= 4.0)
- activesupport (>= 4.0)
- sprockets (>= 3.0.0)
- thor (0.19.1)
- thread_safe (0.3.5)
- tzinfo (1.2.2)
- thread_safe (~> 0.1)
-
- PLATFORMS
- ruby
-
- DEPENDENCIES
- paperclip (~> 5.1.0)
- rails (~> 4.2.7.1)
- L
-
- bundle "lock --update paperclip", env: { "BUNDLER_VERSION" => "1.99.0" }
-
- expect(lockfile).to include(rubygems_version("paperclip", "~> 5.1.0"))
- end
-
- it "outputs a helpful error message when gems have invalid gemspecs", rubygems: "< 3.3.16" 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 "outputs a helpful warning when gems have a gemspec with invalid `require_paths`", rubygems: ">= 3.3.16" do
+ it "outputs a helpful warning when gems have a gemspec with invalid `require_paths`" do
install_gemfile <<-G, standalone: true, env: { "BUNDLE_FORCE_RUBY_PLATFORM" => "1" }
source 'https://rubygems.org'
gem "resque-scheduler", "2.2.0"
@@ -218,166 +72,4 @@ RSpec.describe "real world edgecases", realworld: true do
G
expect(err).to include("resque-scheduler 2.2.0 includes a gemspec with `require_paths` set to an array of arrays. Newer versions of this gem might've already fixed this").once
end
-
- it "doesn't hang on nix gemfile" do
- skip "Only for ruby 3.0" unless RUBY_VERSION.start_with?("3.0")
-
- gemfile <<~G
- source "https://rubygems.org"
-
- 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"
- G
-
- bundle :lock, env: { "DEBUG_RESOLVER" => "1" }
-
- expect(out).to include("Solution found after 4 attempts")
- end
end
diff --git a/spec/bundler/realworld/ffi_spec.rb b/spec/bundler/realworld/ffi_spec.rb
index 5f40b43a0f..bede372b41 100644
--- a/spec/bundler/realworld/ffi_spec.rb
+++ b/spec/bundler/realworld/ffi_spec.rb
@@ -42,12 +42,12 @@ RSpec.describe "loading dynamically linked library on a bundle exec context", re
}
C
- sys_exec "gcc -g -o libfoo.so -shared -fpic libfoo.c"
+ in_bundled_app "gcc -g -o libfoo.so -shared -fpic libfoo.c"
install_gemfile <<-G
source "https://rubygems.org"
- gem 'ffi'
+ gem 'ffi', force_ruby_platform: true
G
bundle "exec ruby foo.rb"
diff --git a/spec/bundler/realworld/fixtures/tapioca/Gemfile b/spec/bundler/realworld/fixtures/tapioca/Gemfile
new file mode 100644
index 0000000000..447d715706
--- /dev/null
+++ b/spec/bundler/realworld/fixtures/tapioca/Gemfile
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+source "https://rubygems.org"
+
+gem "tapioca"
diff --git a/spec/bundler/realworld/fixtures/tapioca/Gemfile.lock b/spec/bundler/realworld/fixtures/tapioca/Gemfile.lock
new file mode 100644
index 0000000000..4ce06de722
--- /dev/null
+++ b/spec/bundler/realworld/fixtures/tapioca/Gemfile.lock
@@ -0,0 +1,49 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ erubi (1.13.1)
+ netrc (0.11.0)
+ parallel (1.26.3)
+ prism (1.3.0)
+ rbi (0.2.2)
+ prism (~> 1.0)
+ sorbet-runtime (>= 0.5.9204)
+ sorbet (0.5.11725)
+ sorbet-static (= 0.5.11725)
+ sorbet-runtime (0.5.11725)
+ sorbet-static (0.5.11725-aarch64-linux)
+ sorbet-static (0.5.11725-universal-darwin)
+ sorbet-static (0.5.11725-x86_64-linux)
+ sorbet-static-and-runtime (0.5.11725)
+ sorbet (= 0.5.11725)
+ sorbet-runtime (= 0.5.11725)
+ spoom (1.5.0)
+ erubi (>= 1.10.0)
+ prism (>= 0.28.0)
+ sorbet-static-and-runtime (>= 0.5.10187)
+ thor (>= 0.19.2)
+ tapioca (0.16.6)
+ bundler (>= 2.2.25)
+ netrc (>= 0.11.0)
+ parallel (>= 1.21.0)
+ rbi (~> 0.2)
+ sorbet-static-and-runtime (>= 0.5.11087)
+ spoom (>= 1.2.0)
+ thor (>= 1.2.0)
+ yard-sorbet
+ thor (1.4.0)
+ yard (0.9.37)
+ yard-sorbet (0.9.0)
+ sorbet-runtime
+ yard
+
+PLATFORMS
+ aarch64-linux
+ universal-darwin
+ x86_64-linux
+
+DEPENDENCIES
+ tapioca
+
+BUNDLED WITH
+ 4.1.0.dev
diff --git a/spec/bundler/realworld/fixtures/warbler/Gemfile b/spec/bundler/realworld/fixtures/warbler/Gemfile
index a8dbb4911c..07dc301d03 100644
--- a/spec/bundler/realworld/fixtures/warbler/Gemfile
+++ b/spec/bundler/realworld/fixtures/warbler/Gemfile
@@ -3,5 +3,5 @@
source "https://rubygems.org"
gem "demo", path: "./demo"
-gem "jruby-jars", "~> 9.2"
-gem "warbler", "~> 2.0"
+gem "jruby-jars", "~> 10.0"
+gem "warbler", github: "https://github.com/jruby/warbler/pull/557"
diff --git a/spec/bundler/realworld/fixtures/warbler/Gemfile.lock b/spec/bundler/realworld/fixtures/warbler/Gemfile.lock
index 5b476f8df2..2f2deea994 100644
--- a/spec/bundler/realworld/fixtures/warbler/Gemfile.lock
+++ b/spec/bundler/realworld/fixtures/warbler/Gemfile.lock
@@ -1,3 +1,15 @@
+GIT
+ remote: https://github.com/jruby/warbler.git
+ revision: 3a3a89e9a055ab1badb4e6fee860e8617b4acfe1
+ ref: refs/pull/557/head
+ specs:
+ warbler (2.0.5)
+ jruby-jars (>= 9.0.0)
+ jruby-rack (>= 1.1.1, < 1.3)
+ rake (>= 13.0.3)
+ rexml (~> 3.0)
+ rubyzip (>= 1.0.0)
+
PATH
remote: demo
specs:
@@ -6,25 +18,22 @@ PATH
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)
+ jruby-jars (10.0.0.1)
+ jruby-rack (1.2.2)
+ rake (13.3.0)
+ rexml (3.4.2)
+ rubyzip (2.4.1)
PLATFORMS
+ arm64-darwin
java
ruby
- universal-java-11
+ universal-java
DEPENDENCIES
demo!
- jruby-jars (~> 9.2)
- warbler (~> 2.0)
+ jruby-jars (~> 10.0)
+ warbler!
BUNDLED WITH
- 2.5.0.dev
+ 4.1.0.dev
diff --git a/spec/bundler/realworld/gemfile_source_header_spec.rb b/spec/bundler/realworld/gemfile_source_header_spec.rb
deleted file mode 100644
index 45f5d0fd22..0000000000
--- a/spec/bundler/realworld/gemfile_source_header_spec.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "../support/silent_logger"
-
-RSpec.describe "fetching dependencies with a mirrored source", realworld: true do
- let(:mirror) { "https://server.example.org" }
- let(:original) { "http://127.0.0.1:#{@port}" }
-
- before do
- setup_server
- bundle "config set --local mirror.#{mirror} #{original}"
- end
-
- after do
- Artifice.deactivate
- @t.kill
- @t.join
- end
-
- it "sets the 'X-Gemfile-Source' and 'User-Agent' headers and bundles successfully" do
- gemfile <<-G
- source "#{mirror}"
- gem 'weakling'
- G
-
- bundle :install, artifice: nil
-
- expect(out).to include("Installing weakling")
- expect(out).to include("Bundle complete")
- expect(the_bundle).to include_gems "weakling 0.0.3"
- end
-
- private
-
- def setup_server
- require_rack
- @port = find_unused_port
- @server_uri = "http://127.0.0.1:#{@port}"
-
- require_relative "../support/artifice/endpoint_mirror_source"
-
- @t = Thread.new do
- Rack::Server.start(app: EndpointMirrorSource,
- Host: "0.0.0.0",
- Port: @port,
- server: "webrick",
- AccessLog: [],
- Logger: Spec::SilentLogger.new)
- end.run
-
- wait_for_server("127.0.0.1", @port)
- end
-end
diff --git a/spec/bundler/realworld/mirror_probe_spec.rb b/spec/bundler/realworld/mirror_probe_spec.rb
deleted file mode 100644
index fc97f92375..0000000000
--- a/spec/bundler/realworld/mirror_probe_spec.rb
+++ /dev/null
@@ -1,131 +0,0 @@
-# frozen_string_literal: true
-
-require_relative "../support/silent_logger"
-
-RSpec.describe "fetching dependencies with a not available mirror", realworld: true do
- let(:mirror) { @mirror_uri }
- let(:original) { @server_uri }
- let(:server_port) { @server_port }
- let(:host) { "127.0.0.1" }
-
- before do
- require_rack
- setup_server
- setup_mirror
- end
-
- after do
- Artifice.deactivate
- @server_thread.kill
- @server_thread.join
- end
-
- context "with a specific fallback timeout" do
- before do
- global_config("BUNDLE_MIRROR__HTTP://127__0__0__1:#{server_port}/__FALLBACK_TIMEOUT/" => "true",
- "BUNDLE_MIRROR__HTTP://127__0__0__1:#{server_port}/" => mirror)
- end
-
- it "install a gem using the original uri when the mirror is not responding" do
- gemfile <<-G
- source "#{original}"
- gem 'weakling'
- G
-
- bundle :install, artifice: nil
-
- expect(out).to include("Installing weakling")
- expect(out).to include("Bundle complete")
- expect(the_bundle).to include_gems "weakling 0.0.3"
- end
- end
-
- context "with a global fallback timeout" do
- before do
- global_config("BUNDLE_MIRROR__ALL__FALLBACK_TIMEOUT/" => "1",
- "BUNDLE_MIRROR__ALL" => mirror)
- end
-
- it "install a gem using the original uri when the mirror is not responding" do
- gemfile <<-G
- source "#{original}"
- gem 'weakling'
- G
-
- bundle :install, artifice: nil
-
- expect(out).to include("Installing weakling")
- expect(out).to include("Bundle complete")
- expect(the_bundle).to include_gems "weakling 0.0.3"
- end
- end
-
- context "with a specific mirror without a fallback timeout" do
- before do
- global_config("BUNDLE_MIRROR__HTTP://127__0__0__1:#{server_port}/" => mirror)
- end
-
- it "fails to install the gem with a timeout error" do
- gemfile <<-G
- source "#{original}"
- gem 'weakling'
- G
-
- bundle :install, artifice: nil, raise_on_error: false
-
- expect(out).to include("Fetching source index 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
-
- context "with a global mirror without a fallback timeout" do
- before do
- global_config("BUNDLE_MIRROR__ALL" => mirror)
- end
-
- it "fails to install the gem with a timeout error" do
- gemfile <<-G
- source "#{original}"
- gem 'weakling'
- G
-
- bundle :install, artifice: nil, raise_on_error: false
-
- expect(out).to include("Fetching source index 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
-
- def setup_server
- @server_port = find_unused_port
- @server_uri = "http://#{host}:#{@server_port}"
-
- require_relative "../support/artifice/endpoint"
-
- @server_thread = Thread.new do
- Rack::Server.start(app: Endpoint,
- Host: host,
- Port: @server_port,
- server: "webrick",
- AccessLog: [],
- Logger: Spec::SilentLogger.new)
- end.run
-
- wait_for_server(host, @server_port)
- end
-
- def setup_mirror
- @mirror_port = find_unused_port
- @mirror_uri = "http://#{host}:#{@mirror_port}"
- end
-end
diff --git a/spec/bundler/realworld/slow_perf_spec.rb b/spec/bundler/realworld/slow_perf_spec.rb
index 32e266ff1b..5d36ba7455 100644
--- a/spec/bundler/realworld/slow_perf_spec.rb
+++ b/spec/bundler/realworld/slow_perf_spec.rb
@@ -30,115 +30,6 @@ RSpec.describe "bundle install with complex dependencies", realworld: true do
G
bundle "lock", env: { "DEBUG_RESOLVER" => "1" }
- expect(out).to include("Solution found after 1 attempts")
- end
-
- it "resolves big gemfile quickly" do
- gemfile <<~G
- # frozen_string_literal: true
-
- source "https://rubygems.org"
-
- 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
-
- if Bundler.feature_flag.bundler_3_mode?
- bundle "lock", env: { "DEBUG_RESOLVER" => "1" }, raise_on_error: false
-
- expect(out).to include("backtracking").exactly(26).times
- else
- bundle "lock", env: { "DEBUG_RESOLVER" => "1" }
-
- expect(out).to include("Solution found after 10 attempts")
- end
+ expect(out).to include("Solution found after 2 attempts")
end
end
diff --git a/spec/bundler/resolver/basic_spec.rb b/spec/bundler/resolver/basic_spec.rb
index 4a0dd37bf9..185df1b1c7 100644
--- a/spec/bundler/resolver/basic_spec.rb
+++ b/spec/bundler/resolver/basic_spec.rb
@@ -6,15 +6,15 @@ RSpec.describe "Resolving" do
end
it "resolves a single gem" do
- dep "rack"
+ dep "myrack"
- should_resolve_as %w[rack-1.1]
+ should_resolve_as %w[myrack-1.1]
end
it "resolves a gem with dependencies" do
dep "actionpack"
- should_resolve_as %w[actionpack-2.3.5 activesupport-2.3.5 rack-1.0]
+ should_resolve_as %w[actionpack-2.3.5 activesupport-2.3.5 myrack-1.0]
end
it "resolves a conflicting index" do
@@ -84,7 +84,7 @@ RSpec.describe "Resolving" do
dep "activesupport", "= 3.0.0.beta"
dep "actionpack"
- should_resolve_as %w[activesupport-3.0.0.beta actionpack-3.0.0.beta rack-1.1 rack-mount-0.6]
+ should_resolve_as %w[activesupport-3.0.0.beta actionpack-3.0.0.beta myrack-1.1 myrack-mount-0.6]
end
it "prefers non-pre-releases when doing conservative updates" do
@@ -211,12 +211,12 @@ RSpec.describe "Resolving" do
it "resolves all gems to latest patch" do
# strict is not set, so bar goes up a minor version due to dependency from foo 1.4.5
- should_conservative_resolve_and_include :patch, [], %w[foo-1.4.5 bar-2.1.1]
+ should_conservative_resolve_and_include :patch, true, %w[foo-1.4.5 bar-2.1.1]
end
it "resolves all gems to latest patch strict" do
# strict is set, so foo can only go up to 1.4.4 to avoid bar going up a minor version, and bar can go up to 2.0.5
- should_conservative_resolve_and_include [:patch, :strict], [], %w[foo-1.4.4 bar-2.0.5]
+ should_conservative_resolve_and_include [:patch, :strict], true, %w[foo-1.4.4 bar-2.0.5]
end
it "resolves foo only to latest patch - same dependency case" do
@@ -238,7 +238,7 @@ RSpec.describe "Resolving" do
it "resolves foo only to latest patch - changing dependency declared case" do
# bar is locked AND a declared dependency in the Gemfile, so it will not move, and therefore
# foo can only move up to 1.4.4.
- @base << build_spec("bar", "2.0.3").first
+ @base = Bundler::SpecSet.new([Bundler::LazySpecification.new("bar", Gem::Version.new("2.0.3"), nil)])
should_conservative_resolve_and_include :patch, ["foo"], %w[foo-1.4.4 bar-2.0.3]
end
@@ -256,20 +256,20 @@ RSpec.describe "Resolving" do
it "resolves all gems to latest minor" do
# strict is not set, so bar goes up a major version due to dependency from foo 1.4.5
- should_conservative_resolve_and_include :minor, [], %w[foo-1.5.1 bar-3.0.0]
+ should_conservative_resolve_and_include :minor, true, %w[foo-1.5.1 bar-3.0.0]
end
it "resolves all gems to latest minor strict" do
# strict is set, so foo can only go up to 1.5.0 to avoid bar going up a major version
- should_conservative_resolve_and_include [:minor, :strict], [], %w[foo-1.5.0 bar-2.1.1]
+ should_conservative_resolve_and_include [:minor, :strict], true, %w[foo-1.5.0 bar-2.1.1]
end
it "resolves all gems to latest major" do
- should_conservative_resolve_and_include :major, [], %w[foo-2.0.0 bar-3.0.0]
+ should_conservative_resolve_and_include :major, true, %w[foo-2.0.0 bar-3.0.0]
end
it "resolves all gems to latest major strict" do
- should_conservative_resolve_and_include [:major, :strict], [], %w[foo-2.0.0 bar-3.0.0]
+ should_conservative_resolve_and_include [:major, :strict], true, %w[foo-2.0.0 bar-3.0.0]
end
# Why would this happen in real life? If bar 2.2 has a bug that the author of foo wants to bypass
@@ -292,31 +292,31 @@ RSpec.describe "Resolving" do
end
it "could revert to a previous version level patch" do
- should_conservative_resolve_and_include :patch, [], %w[foo-1.4.4 bar-2.1.1]
+ should_conservative_resolve_and_include :patch, true, %w[foo-1.4.4 bar-2.1.1]
end
it "cannot revert to a previous version in strict mode level patch" do
# fall back to the locked resolution since strict means we can't regress either version
- should_conservative_resolve_and_include [:patch, :strict], [], %w[foo-1.4.3 bar-2.2.3]
+ should_conservative_resolve_and_include [:patch, :strict], true, %w[foo-1.4.3 bar-2.2.3]
end
it "could revert to a previous version level minor" do
- should_conservative_resolve_and_include :minor, [], %w[foo-1.5.0 bar-2.0.5]
+ should_conservative_resolve_and_include :minor, true, %w[foo-1.5.0 bar-2.0.5]
end
it "cannot revert to a previous version in strict mode level minor" do
# fall back to the locked resolution since strict means we can't regress either version
- should_conservative_resolve_and_include [:minor, :strict], [], %w[foo-1.4.3 bar-2.2.3]
+ should_conservative_resolve_and_include [:minor, :strict], true, %w[foo-1.4.3 bar-2.2.3]
end
end
end
it "handles versions that redundantly depend on themselves" do
@index = build_index do
- gem "rack", "3.0.0"
+ gem "myrack", "3.0.0"
gem "standalone_migrations", "7.1.0" do
- dep "rack", "~> 2.0"
+ dep "myrack", "~> 2.0"
end
gem "standalone_migrations", "2.0.4" do
@@ -324,22 +324,22 @@ RSpec.describe "Resolving" do
end
gem "standalone_migrations", "1.0.13" do
- dep "rack", ">= 0"
+ dep "myrack", ">= 0"
end
end
- dep "rack", "~> 3.0"
+ dep "myrack", "~> 3.0"
dep "standalone_migrations"
- should_resolve_as %w[rack-3.0.0 standalone_migrations-2.0.4]
+ should_resolve_as %w[myrack-3.0.0 standalone_migrations-2.0.4]
end
it "ignores versions that incorrectly depend on themselves" do
@index = build_index do
- gem "rack", "3.0.0"
+ gem "myrack", "3.0.0"
gem "standalone_migrations", "7.1.0" do
- dep "rack", "~> 2.0"
+ dep "myrack", "~> 2.0"
end
gem "standalone_migrations", "2.0.4" do
@@ -347,22 +347,22 @@ RSpec.describe "Resolving" do
end
gem "standalone_migrations", "1.0.13" do
- dep "rack", ">= 0"
+ dep "myrack", ">= 0"
end
end
- dep "rack", "~> 3.0"
+ dep "myrack", "~> 3.0"
dep "standalone_migrations"
- should_resolve_as %w[rack-3.0.0 standalone_migrations-1.0.13]
+ should_resolve_as %w[myrack-3.0.0 standalone_migrations-1.0.13]
end
it "does not ignore versions that incorrectly depend on themselves when dependency_api is not available" do
@index = build_index do
- gem "rack", "3.0.0"
+ gem "myrack", "3.0.0"
gem "standalone_migrations", "7.1.0" do
- dep "rack", "~> 2.0"
+ dep "myrack", "~> 2.0"
end
gem "standalone_migrations", "2.0.4" do
@@ -370,13 +370,53 @@ RSpec.describe "Resolving" do
end
gem "standalone_migrations", "1.0.13" do
- dep "rack", ">= 0"
+ dep "myrack", ">= 0"
end
end
- dep "rack", "~> 3.0"
+ dep "myrack", "~> 3.0"
dep "standalone_migrations"
- should_resolve_without_dependency_api %w[rack-3.0.0 standalone_migrations-2.0.4]
+ should_resolve_without_dependency_api %w[myrack-3.0.0 standalone_migrations-2.0.4]
+ end
+
+ it "resolves fine cases that need joining unbounded disjoint ranges" do
+ @index = build_index do
+ gem "inspec", "5.22.3" do
+ dep "ruby", ">= 3.2.2"
+ dep "train-kubernetes", ">= 0.1.7"
+ end
+
+ gem "ruby", "3.2.2"
+
+ gem "train-kubernetes", "0.1.12" do
+ dep "k8s-ruby", ">= 0.14.0"
+ end
+
+ gem "train-kubernetes", "0.1.10" do
+ dep "k8s-ruby", "= 0.10.5"
+ end
+
+ gem "train-kubernetes", "0.1.7" do
+ dep "k8s-ruby", ">= 0.10.5"
+ end
+
+ gem "k8s-ruby", "0.10.5" do
+ dep "ruby","< 3.2.2"
+ end
+
+ gem "k8s-ruby", "0.11.0" do
+ dep "ruby", ">= 3.2.2"
+ end
+
+ gem "k8s-ruby", "0.14.0" do
+ dep "ruby", "< 3.2.2"
+ end
+ end
+
+ dep "inspec", "5.22.3"
+ dep "ruby", "3.2.2"
+
+ should_resolve_as %w[inspec-5.22.3 ruby-3.2.2 train-kubernetes-0.1.7 k8s-ruby-0.11.0]
end
end
diff --git a/spec/bundler/resolver/platform_spec.rb b/spec/bundler/resolver/platform_spec.rb
index 3e959aeb89..a1d095d024 100644
--- a/spec/bundler/resolver/platform_spec.rb
+++ b/spec/bundler/resolver/platform_spec.rb
@@ -48,11 +48,11 @@ RSpec.describe "Resolving platform craziness" do
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.0.0", "x64-mingw-ucrt"
gem "foo", "1.1.0"
end
dep "foo"
- platforms "x64-mingw32"
+ platforms "x64-mingw-ucrt"
should_resolve_as %w[foo-1.1.0]
end
@@ -61,12 +61,12 @@ RSpec.describe "Resolving platform craziness" do
@index = build_index do
gem "bar", "1.0.0"
gem "foo", "1.0.0"
- gem "foo", "1.0.0", "x64-mingw32" do
+ gem "foo", "1.0.0", "x64-mingw-ucrt" do
dep "bar", "< 1"
end
end
dep "foo"
- platforms "x64-mingw32"
+ platforms "x64-mingw-ucrt"
should_resolve_as %w[foo-1.0.0]
end
@@ -74,12 +74,12 @@ RSpec.describe "Resolving platform craziness" do
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"
+ gem "foo", "1.0.0", "x64-mingw-ucrt"
end
dep "foo"
- platforms "x64-mingw32"
+ platforms "x64-mingw-ucrt"
- should_resolve_as %w[foo-1.0.0-x64-mingw32]
+ should_resolve_as %w[foo-1.0.0-x64-mingw-ucrt]
end
describe "on a linux platform" do
@@ -159,15 +159,15 @@ RSpec.describe "Resolving platform craziness" do
before do
@index = build_index do
gem "foo", "1.0.0"
- gem "foo", "1.0.0", "x64-mingw32"
+ gem "foo", "1.0.0", "x64-mingw-ucrt"
gem "foo", "1.1.0"
- gem "foo", "1.1.0", "x64-mingw32" do |s|
+ gem "foo", "1.1.0", "x64-mingw-ucrt" do |s|
s.required_ruby_version = [">= 2.0", "< 2.4"]
end
gem "Ruby\0", "2.5.1"
end
dep "Ruby\0", "2.5.1"
- platforms "x64-mingw32"
+ platforms "x64-mingw-ucrt"
end
it "takes the latest ruby gem" do
@@ -186,18 +186,18 @@ RSpec.describe "Resolving platform craziness" do
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.0.0", "x64-mingw-ucrt"
gem "foo", "1.1.0" do |s|
s.required_ruby_version = [">= 2.0"]
end
- gem "foo", "1.1.0", "x64-mingw32" do |s|
+ gem "foo", "1.1.0", "x64-mingw-ucrt" 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"
+ platforms "x64-mingw-ucrt"
should_resolve_as %w[foo-1.1.0]
end
@@ -205,18 +205,18 @@ RSpec.describe "Resolving platform craziness" do
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.0.0", "x64-mingw-ucrt"
gem "foo", "1.1.0" do |s|
s.required_ruby_version = [">= 2.0"]
end
- gem "foo", "1.1.0", "x64-mingw32" do |s|
+ gem "foo", "1.1.0", "x64-mingw-ucrt" 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"
+ platforms "x86_64-linux", "x64-mingw-ucrt"
should_resolve_as %w[foo-1.1.0]
end
@@ -342,7 +342,7 @@ RSpec.describe "Resolving platform craziness" do
describe "with mingw32" do
before :each do
@index = build_index do
- platforms "mingw32 mswin32 x64-mingw32 x64-mingw-ucrt" do |platform|
+ platforms "mingw32 mswin32 x64-mingw-ucrt" do |platform|
gem "thin", "1.2.7", platform
end
gem "win32-api", "1.5.1", "universal-mingw32"
@@ -363,10 +363,10 @@ RSpec.describe "Resolving platform craziness" do
should_resolve_as %w[thin-1.2.7-mingw32]
end
- it "finds x64-mingw32 gems" do
- platforms "x64-mingw32"
+ it "finds x64-mingw-ucrt gems" do
+ platforms "x64-mingw-ucrt"
dep "thin"
- should_resolve_as %w[thin-1.2.7-x64-mingw32]
+ should_resolve_as %w[thin-1.2.7-x64-mingw-ucrt]
end
it "finds universal-mingw gems on x86-mingw" do
@@ -376,25 +376,21 @@ RSpec.describe "Resolving platform craziness" do
end
it "finds universal-mingw gems on x64-mingw" do
- platform "x64-mingw32"
+ platform "x64-mingw-ucrt"
dep "win32-api"
should_resolve_as %w[win32-api-1.5.1-universal-mingw32]
end
- if Gem.rubygems_version >= Gem::Version.new("3.2.28")
- it "finds x64-mingw-ucrt gems" do
- platforms "x64-mingw-ucrt"
- dep "thin"
- should_resolve_as %w[thin-1.2.7-x64-mingw-ucrt]
- end
+ it "finds x64-mingw-ucrt gems" do
+ platforms "x64-mingw-ucrt"
+ dep "thin"
+ should_resolve_as %w[thin-1.2.7-x64-mingw-ucrt]
end
- if Gem.rubygems_version >= Gem::Version.new("3.3.18")
- it "finds universal-mingw gems on x64-mingw-ucrt" do
- platform "x64-mingw-ucrt"
- dep "win32-api"
- should_resolve_as %w[win32-api-1.5.1-universal-mingw32]
- end
+ it "finds universal-mingw gems on x64-mingw-ucrt" do
+ platform "x64-mingw-ucrt"
+ dep "win32-api"
+ should_resolve_as %w[win32-api-1.5.1-universal-mingw32]
end
end
diff --git a/spec/bundler/runtime/env_helpers_spec.rb b/spec/bundler/runtime/env_helpers_spec.rb
new file mode 100644
index 0000000000..c4ebdd1fd2
--- /dev/null
+++ b/spec/bundler/runtime/env_helpers_spec.rb
@@ -0,0 +1,236 @@
+# frozen_string_literal: true
+
+RSpec.describe "env helpers" do
+ def bundle_exec_ruby(args, options = {})
+ build_bundler_context options.dup
+ bundle "exec '#{Gem.ruby}' #{args}", options
+ end
+
+ def build_bundler_context(options = {})
+ bundle "config set path vendor/bundle", options.dup
+ gemfile "source 'https://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
+ 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(bundled_app("source.rb").to_s)
+ expect(stdboth).to eq(path)
+ end
+ end
+
+ it "should return the GEM_PATH present before bundle was activated" do
+ 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(bundled_app("source.rb").to_s)
+ expect(stdboth).to eq(gem_path)
+ end
+ end
+
+ 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?("#{File::PATH_SEPARATOR}/foo")}"
+ if count == 2
+ ENV["PATH"] = "#{ENV["PATH"]}#{File::PATH_SEPARATOR}/foo"
+ end
+ exec(Gem.ruby, __FILE__, (count - 1).to_s)
+ RUBY
+ path = `getconf PATH`.strip + File::PATH_SEPARATOR + File.dirname(Gem.ruby)
+ with_path_as(path) do
+ build_bundler_context
+ bundle_exec_ruby("#{bundled_app("exe.rb")} 2")
+ end
+ expect(err).to eq <<-EOS.strip
+2 false
+1 true
+0 true
+ EOS
+ end
+
+ it "removes variables that bundler added", :ruby_repo do
+ original = ruby('puts ENV.to_a.map {|e| e.join("=") }.sort.join("\n")', artifice: "fail")
+ 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"), artifice: "fail"
+ expect(out).to eq original
+ end
+ end
+
+ describe "Bundler.unbundled_env" do
+ it "should delete BUNDLE_PATH" do
+ create_file("source.rb", <<-RUBY)
+ print Bundler.unbundled_env.has_key?('BUNDLE_PATH')
+ RUBY
+ ENV["BUNDLE_PATH"] = "./foo"
+ bundle_exec_ruby bundled_app("source.rb")
+ expect(stdboth).to include "false"
+ end
+
+ 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 Bundler.unbundled_env['RUBYOPT']
+ RUBY
+ setup_require = "-r#{lib_dir}/bundler/setup"
+ ENV["BUNDLER_ORIG_RUBYOPT"] = "-W2 #{setup_require} #{ENV["RUBYOPT"]}"
+ bundle_exec_ruby bundled_app("source.rb")
+ expect(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 Bundler.unbundled_env['RUBYOPT']
+ RUBY
+ ENV["BUNDLER_ORIG_RUBYOPT"] = "-W2 -rbundler/setup #{ENV["RUBYOPT"]}"
+ bundle_exec_ruby bundled_app("source.rb")
+ expect(stdboth).not_to include("-rbundler/setup")
+ end
+
+ it "should delete BUNDLER_SETUP even if it was present in original env" do
+ create_file("source.rb", <<-RUBY)
+ print Bundler.unbundled_env.has_key?('BUNDLER_SETUP')
+ RUBY
+ ENV["BUNDLER_ORIG_BUNDLER_SETUP"] = system_gem_path("gems/bundler-#{Bundler::VERSION}/lib/bundler/setup").to_s
+ bundle_exec_ruby bundled_app("source.rb")
+ expect(stdboth).to include "false"
+ end
+
+ it "should restore RUBYLIB", :ruby_repo do
+ create_file("source.rb", <<-RUBY)
+ print Bundler.unbundled_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 bundled_app("source.rb")
+ expect(stdboth).to include("/foo-original")
+ end
+
+ it "should restore the original MANPATH" do
+ create_file("source.rb", <<-RUBY)
+ print Bundler.unbundled_env['MANPATH']
+ RUBY
+ ENV["MANPATH"] = "/foo"
+ ENV["BUNDLER_ORIG_MANPATH"] = "/foo-original"
+ bundle_exec_ruby bundled_app("source.rb")
+ expect(stdboth).to include("/foo-original")
+ end
+ end
+
+ 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 }
+ expect(actual).to eq(expected)
+ end
+
+ it "should restore the environment after execution" do
+ Bundler.with_original_env do
+ ENV["FOO"] = "hello"
+ end
+
+ expect(ENV).not_to have_key("FOO")
+ end
+ end
+
+ 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 }
+ expect(actual).to eq(expected)
+ end
+
+ it "should restore the environment after execution" do
+ Bundler.with_unbundled_env do
+ ENV["FOO"] = "hello"
+ end
+
+ expect(ENV).not_to have_key("FOO")
+ end
+ end
+
+ describe "Bundler.original_system" do
+ 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
+ run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb"))
+ expect($?.exitstatus).to eq(42)
+ end
+ end
+
+ describe "Bundler.unbundled_system" do
+ 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
+ run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb"))
+ expect($?.exitstatus).to eq(42)
+ end
+ end
+
+ describe "Bundler.original_exec" do
+ before do
+ create_file("source.rb", <<-'RUBY')
+ Process.fork do
+ exit Bundler.original_exec(%(test "\$BUNDLE_FOO" = "bar"))
+ end
+
+ _, status = Process.wait2
+
+ exit(status.exitstatus)
+ RUBY
+ end
+
+ it "runs exec inside with_original_env" do
+ skip "Fork not implemented" if Gem.win_platform?
+
+ run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb"))
+ expect($?.exitstatus).to eq(0)
+ end
+ end
+
+ describe "Bundler.unbundled_exec" do
+ before do
+ create_file("source.rb", <<-'RUBY')
+ Process.fork do
+ exit Bundler.unbundled_exec(%(test "\$BUNDLE_FOO" = "bar"))
+ end
+
+ _, status = Process.wait2
+
+ exit(status.exitstatus)
+ RUBY
+ end
+
+ it "runs exec inside with_unbundled_env" do
+ skip "Fork not implemented" if Gem.win_platform?
+
+ run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb"))
+ expect($?.exitstatus).to eq(1)
+ end
+ end
+end
diff --git a/spec/bundler/runtime/executable_spec.rb b/spec/bundler/runtime/executable_spec.rb
index 36ce6dcf67..86cd1d0039 100644
--- a/spec/bundler/runtime/executable_spec.rb
+++ b/spec/bundler/runtime/executable_spec.rb
@@ -3,140 +3,112 @@
RSpec.describe "Running bin/* commands" do
before :each do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
end
it "runs the bundled command when in the bundle" do
- bundle "binstubs rack"
+ bundle "binstubs myrack"
- build_gem "rack", "2.0", to_system: true do |s|
- s.executables = "rackup"
+ build_gem "myrack", "2.0", to_system: true do |s|
+ s.executables = "myrackup"
end
- gembin "rackup"
+ gembin "myrackup"
expect(out).to eq("1.0.0")
end
- it "allows the location of the gem stubs to be specified" do
- bundle "binstubs rack", path: "gbin"
+ it "allows the location of the gem stubs to be configured" do
+ bundle "config bin gbin"
+ bundle "binstubs myrack"
expect(bundled_app("bin")).not_to exist
- expect(bundled_app("gbin/rackup")).to exist
+ expect(bundled_app("gbin/myrackup")).to exist
- gembin bundled_app("gbin/rackup")
+ gembin bundled_app("gbin/myrackup")
expect(out).to eq("1.0.0")
end
it "allows absolute paths as a specification of where to install bin stubs" do
- bundle "binstubs rack", path: tmp("bin")
+ bundle "config bin #{tmp("bin")}"
+ bundle "binstubs myrack"
- gembin tmp("bin/rackup")
+ gembin tmp("bin/myrackup")
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.readlines(bundled_app("bin/rackup")).first).to eq("#!/usr/bin/env #{RbConfig::CONFIG["ruby_install_name"]}\n")
+ bundle "binstubs myrack"
+ expect(File.readlines(bundled_app("bin/myrackup")).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.readlines(bundled_app("bin/rackup")).first).to eq("#!/usr/bin/env ruby-foo\n")
+ bundle "binstubs myrack", shebang: "ruby-foo"
+ expect(File.readlines(bundled_app("bin/myrackup")).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 myrack"
- build_gem "rack", "2.0", to_system: true do |s|
- s.executables = "rackup"
+ build_gem "myrack", "2.0", to_system: true do |s|
+ s.executables = "myrackup"
end
- gembin "rackup", dir: tmp
+ gembin "myrackup", dir: tmp
expect(out).to eq("1.0.0")
end
it "works with gems in path" do
- build_lib "rack", path: lib_path("rack") do |s|
- s.executables = "rackup"
+ build_lib "myrack", path: lib_path("myrack") do |s|
+ s.executables = "myrackup"
end
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :path => "#{lib_path("rack")}"
+ source "https://gem.repo1"
+ gem "myrack", :path => "#{lib_path("myrack")}"
G
- bundle "binstubs rack"
+ bundle "binstubs myrack"
- build_gem "rack", "2.0", to_system: true do |s|
- s.executables = "rackup"
+ build_gem "myrack", "2.0", to_system: true do |s|
+ s.executables = "myrackup"
end
- gembin "rackup"
+ gembin "myrackup"
expect(out).to eq("1.0")
end
- it "creates a bundle binstub" do
+ it "does not create a bundle binstub" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "bundler"
G
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"
-
- expect(bundled_app("bin/rackup")).not_to exist
- end
-
- it "allows you to stop installing binstubs", bundler: "< 3" do
- skip "delete permission error" if Gem.win_platform?
-
- bundle "install --binstubs bin/"
- bundled_app("bin/rackup").rmtree
- bundle "install --binstubs \"\""
-
- expect(bundled_app("bin/rackup")).not_to exist
+ expect(bundled_app("bin/bundle")).not_to exist
- bundle "config bin"
- expect(out).to include("You have not configured a value for `bin`")
+ expect(err).to include("Bundler itself does not use binstubs because its version is selected by RubyGems")
end
- it "remembers that the option was specified", bundler: "< 3" do
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "activesupport"
- G
-
- bundle :install, binstubs: "bin"
-
- gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "activesupport"
- gem "rack"
- G
-
+ it "does not generate bin stubs if the option was not specified" do
bundle "install"
- expect(bundled_app("bin/rackup")).to exist
+ expect(bundled_app("bin/myrackup")).not_to exist
end
- it "rewrites bins on binstubs (to maintain backwards compatibility)" do
+ it "rewrites bins on binstubs with --force option" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
- create_file("bin/rackup", "OMG")
+ create_file("bin/myrackup", "OMG")
- bundle "binstubs rack"
+ bundle "binstubs myrack", { force: true }
- expect(bundled_app("bin/rackup").read).to_not eq("OMG")
+ expect(bundled_app("bin/myrackup").read.strip).to_not eq("OMG")
end
it "use BUNDLE_GEMFILE gemfile for binstub" do
@@ -148,8 +120,8 @@ RSpec.describe "Running bin/* commands" do
build_gem("bindir") {|s| s.executables = "foo" }
end
- create_file("OtherGemfile", <<-G)
- source "#{file_uri_for(gem_repo2)}"
+ gemfile("OtherGemfile", <<-G)
+ source "https://gem.repo2"
gem 'bindir'
G
diff --git a/spec/bundler/runtime/gem_tasks_spec.rb b/spec/bundler/runtime/gem_tasks_spec.rb
index f7afc0eb92..f87207f0ab 100644
--- a/spec/bundler/runtime/gem_tasks_spec.rb
+++ b/spec/bundler/runtime/gem_tasks_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
RSpec.describe "require 'bundler/gem_tasks'" do
- before :each do
+ let(:define_local_gem_using_gem_tasks) do
bundled_app("foo.gemspec").open("w") do |f|
f.write <<-GEMSPEC
Gem::Specification.new do |s|
@@ -20,17 +20,54 @@ RSpec.describe "require 'bundler/gem_tasks'" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rake"
G
end
- it "includes the relevant tasks" do
- with_gem_path_as(base_system_gem_path.to_s) do
- sys_exec "#{rake} -T", env: { "GEM_HOME" => system_gem_path.to_s }
+ let(:define_local_gem_with_extensions_using_gem_tasks_and_gemspec_dsl) do
+ bundled_app("foo.gemspec").open("w") do |f|
+ f.write <<-GEMSPEC
+ Gem::Specification.new do |s|
+ s.name = "foo"
+ s.version = "1.0"
+ s.summary = "dummy"
+ s.author = "Perry Mason"
+ s.extensions = "ext/extconf.rb"
+ end
+ GEMSPEC
+ end
+
+ bundled_app("Rakefile").open("w") do |f|
+ f.write <<-RAKEFILE
+ require "bundler/gem_tasks"
+ RAKEFILE
end
+ Dir.mkdir bundled_app("ext")
+
+ bundled_app("ext/extconf.rb").open("w") do |f|
+ f.write <<-EXTCONF
+ require "mkmf"
+ File.write("Makefile", dummy_makefile($srcdir).join)
+ EXTCONF
+ end
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+
+ gemspec
+
+ gem "rake"
+ G
+ end
+
+ it "includes the relevant tasks" do
+ define_local_gem_using_gem_tasks
+
+ in_bundled_app "rake -T"
+
expect(err).to be_empty
expected_tasks = [
"rake build",
@@ -44,9 +81,9 @@ RSpec.describe "require 'bundler/gem_tasks'" do
end
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
+ define_local_gem_using_gem_tasks
+
+ in_bundled_app "rake install"
expect(err).to be_empty
@@ -55,9 +92,19 @@ RSpec.describe "require 'bundler/gem_tasks'" do
expect(err).to be_empty
end
+ it "defines a working `rake install` task for local gems with extensions", :ruby_repo do
+ define_local_gem_with_extensions_using_gem_tasks_and_gemspec_dsl
+
+ bundle "exec rake install"
+
+ expect(err).to be_empty
+ end
+
context "rake build when path has spaces", :ruby_repo do
before do
- spaced_bundled_app = tmp.join("bundled app")
+ define_local_gem_using_gem_tasks
+
+ spaced_bundled_app = tmp("bundled app")
FileUtils.cp_r bundled_app, spaced_bundled_app
bundle "exec rake build", dir: spaced_bundled_app
end
@@ -69,7 +116,9 @@ RSpec.describe "require 'bundler/gem_tasks'" do
context "rake build when path has brackets", :ruby_repo do
before do
- bracketed_bundled_app = tmp.join("bundled[app")
+ define_local_gem_using_gem_tasks
+
+ bracketed_bundled_app = tmp("bundled[app")
FileUtils.cp_r bundled_app, bracketed_bundled_app
bundle "exec rake build", dir: bracketed_bundled_app
end
@@ -81,12 +130,14 @@ RSpec.describe "require 'bundler/gem_tasks'" do
context "bundle path configured locally" do
before do
+ define_local_gem_using_gem_tasks
+
bundle "config set path vendor/bundle"
end
it "works", :ruby_repo do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rake"
G
@@ -98,9 +149,10 @@ RSpec.describe "require 'bundler/gem_tasks'" do
end
it "adds 'pkg' to rake/clean's CLOBBER" do
- 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
+ define_local_gem_using_gem_tasks
+
+ in_bundled_app %(rake -e 'load "Rakefile"; puts CLOBBER.inspect')
+
expect(out).to eq '["pkg"]'
end
end
diff --git a/spec/bundler/runtime/inline_spec.rb b/spec/bundler/runtime/inline_spec.rb
index 50a5258dc7..e55d029a4b 100644
--- a/spec/bundler/runtime/inline_spec.rb
+++ b/spec/bundler/runtime/inline_spec.rb
@@ -2,10 +2,9 @@
RSpec.describe "bundler/inline#gemfile" do
def script(code, options = {})
- requires = ["bundler/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)
+ options[:artifice] ||= "compact_index"
+ options[:env] ||= { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
+ ruby("require 'bundler/inline'\n\n" + code, options)
end
before :each do
@@ -48,7 +47,7 @@ RSpec.describe "bundler/inline#gemfile" do
it "requires the gems" do
script <<-RUBY
gemfile do
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
path "#{lib_path}" do
gem "two"
end
@@ -59,7 +58,7 @@ RSpec.describe "bundler/inline#gemfile" do
script <<-RUBY, raise_on_error: false
gemfile do
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
path "#{lib_path}" do
gem "eleven"
end
@@ -73,16 +72,16 @@ RSpec.describe "bundler/inline#gemfile" do
script <<-RUBY
gemfile(true) do
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
end
RUBY
- expect(out).to include("Rack's post install message")
+ expect(out).to include("Myrack's post install message")
script <<-RUBY, artifice: "endpoint"
gemfile(true) do
- source "https://notaserver.com"
+ source "https://notaserver.test"
gem "activesupport", :require => true
end
RUBY
@@ -104,7 +103,7 @@ RSpec.describe "bundler/inline#gemfile" do
my_ui = MyBundlerUI.new
my_ui.level = "confirm"
gemfile(true, :ui => my_ui) do
- source "https://notaserver.com"
+ source "https://notaserver.test"
gem "activesupport", :require => true
end
RUBY
@@ -117,7 +116,7 @@ RSpec.describe "bundler/inline#gemfile" do
require 'bundler/inline'
gemfile(true, :quiet => true) do
- source "https://notaserver.com"
+ source "https://notaserver.test"
gem "activesupport", :require => true
end
RUBY
@@ -143,7 +142,7 @@ RSpec.describe "bundler/inline#gemfile" do
require 'bundler'
options = { :ui => Bundler::UI::Shell.new }
gemfile(false, options) do
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
path "#{lib_path}" do
gem "two"
end
@@ -157,11 +156,11 @@ RSpec.describe "bundler/inline#gemfile" do
it "installs quietly if necessary when the install option is not set" do
script <<-RUBY
gemfile do
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
end
- puts RACK
+ puts MYRACK
RUBY
expect(out).to eq("1.0.0")
@@ -170,21 +169,21 @@ RSpec.describe "bundler/inline#gemfile" do
it "installs subdependencies quietly if necessary when the install option is not set" do
build_repo4 do
- build_gem "rack" do |s|
- s.add_dependency "rackdep"
+ build_gem "myrack" do |s|
+ s.add_dependency "myrackdep"
end
- build_gem "rackdep", "1.0.0"
+ build_gem "myrackdep", "1.0.0"
end
- script <<-RUBY
+ script <<-RUBY, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
gemfile do
- source "#{file_uri_for(gem_repo4)}"
- gem "rack"
+ source "https://gem.repo4"
+ gem "myrack"
end
- require "rackdep"
- puts RACKDEP
+ require "myrackdep"
+ puts MYRACKDEP
RUBY
expect(out).to eq("1.0.0")
@@ -193,23 +192,23 @@ RSpec.describe "bundler/inline#gemfile" do
it "installs subdependencies quietly if necessary when the install option is not set, and multiple sources used" do
build_repo4 do
- build_gem "rack" do |s|
- s.add_dependency "rackdep"
+ build_gem "myrack" do |s|
+ s.add_dependency "myrackdep"
end
- build_gem "rackdep", "1.0.0"
+ build_gem "myrackdep", "1.0.0"
end
- script <<-RUBY
+ script <<-RUBY, artifice: "compact_index_extra_api"
gemfile do
- source "#{file_uri_for(gem_repo1)}"
- source "#{file_uri_for(gem_repo4)}" do
- gem "rack"
+ source "https://test.repo"
+ source "https://test.repo/extra" do
+ gem "myrack"
end
end
- require "rackdep"
- puts RACKDEP
+ require "myrackdep"
+ puts MYRACKDEP
RUBY
expect(out).to eq("1.0.0")
@@ -221,7 +220,7 @@ RSpec.describe "bundler/inline#gemfile" do
baz_ref = build_git("baz", "2.0.0").ref_for("HEAD")
script <<-RUBY
gemfile do
- source "#{file_uri_for(gem_repo1)}"
+ source "https://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
@@ -238,14 +237,14 @@ RSpec.describe "bundler/inline#gemfile" do
script <<-RUBY
gemfile do
path "#{lib_path}" do
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "two"
end
end
gemfile do
path "#{lib_path}" do
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "four"
end
end
@@ -256,7 +255,7 @@ RSpec.describe "bundler/inline#gemfile" do
end
it "doesn't reinstall already installed gems" do
- system_gems "rack-1.0.0"
+ system_gems "myrack-1.0.0"
script <<-RUBY
require 'bundler'
@@ -264,65 +263,65 @@ RSpec.describe "bundler/inline#gemfile" do
ui.level = "confirm"
gemfile(true, ui: ui) do
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "activesupport"
- gem "rack"
+ gem "myrack"
end
RUBY
expect(out).to include("Installing activesupport")
- expect(out).not_to include("Installing rack")
+ expect(out).not_to include("Installing myrack")
expect(err).to be_empty
end
it "installs gems in later gemfile calls" do
- system_gems "rack-1.0.0"
+ system_gems "myrack-1.0.0"
script <<-RUBY
require 'bundler'
ui = Bundler::UI::Shell.new
ui.level = "confirm"
gemfile(true, ui: ui) do
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
end
gemfile(true, ui: ui) do
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "activesupport"
end
RUBY
expect(out).to include("Installing activesupport")
- expect(out).not_to include("Installing rack")
+ expect(out).not_to include("Installing myrack")
expect(err).to be_empty
end
it "doesn't reinstall already installed gems in later gemfile calls" do
- system_gems "rack-1.0.0"
+ system_gems "myrack-1.0.0"
script <<-RUBY
require 'bundler'
ui = Bundler::UI::Shell.new
ui.level = "confirm"
gemfile(true, ui: ui) do
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "activesupport"
end
gemfile(true, ui: ui) do
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
end
RUBY
expect(out).to include("Installing activesupport")
- expect(out).not_to include("Installing rack")
+ expect(out).not_to include("Installing myrack")
expect(err).to be_empty
end
it "installs gems with native extensions in later gemfile calls" do
- system_gems "rack-1.0.0"
+ system_gems "myrack-1.0.0"
build_git "foo" do |s|
s.add_dependency "rake"
@@ -343,12 +342,12 @@ RSpec.describe "bundler/inline#gemfile" do
ui = Bundler::UI::Shell.new
ui.level = "confirm"
gemfile(true, ui: ui) do
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
end
gemfile(true, ui: ui) do
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
end
@@ -364,7 +363,7 @@ RSpec.describe "bundler/inline#gemfile" do
it "installs inline gems when a Gemfile.lock is present" do
gemfile <<-G
- source "https://notaserver.com"
+ source "https://notaserver.test"
gem "rake"
G
@@ -381,16 +380,16 @@ RSpec.describe "bundler/inline#gemfile" do
rake
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
script <<-RUBY
gemfile do
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
end
- puts RACK
+ puts MYRACK
RUBY
expect(err).to be_empty
@@ -398,7 +397,7 @@ RSpec.describe "bundler/inline#gemfile" do
it "does not leak Gemfile.lock versions to the installation output" do
gemfile <<-G
- source "https://notaserver.com"
+ source "https://notaserver.test"
gem "rake"
G
@@ -415,12 +414,12 @@ RSpec.describe "bundler/inline#gemfile" do
rake
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
script <<-RUBY
gemfile(true) do
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rake", "#{rake_version}"
end
RUBY
@@ -431,26 +430,26 @@ RSpec.describe "bundler/inline#gemfile" do
end
it "installs inline gems when frozen is set" do
- script <<-RUBY, env: { "BUNDLE_FROZEN" => "true" }
+ script <<-RUBY, env: { "BUNDLE_FROZEN" => "true", "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
gemfile do
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
end
- puts RACK
+ puts MYRACK
RUBY
expect(last_command.stderr).to be_empty
end
it "installs inline gems when deployment is set" do
- script <<-RUBY, env: { "BUNDLE_DEPLOYMENT" => "true" }
+ script <<-RUBY, env: { "BUNDLE_DEPLOYMENT" => "true", "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
gemfile do
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
end
- puts RACK
+ puts MYRACK
RUBY
expect(last_command.stderr).to be_empty
@@ -461,11 +460,11 @@ RSpec.describe "bundler/inline#gemfile" do
script <<-RUBY
gemfile do
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
end
- puts RACK
+ puts MYRACK
RUBY
expect(err).to be_empty
@@ -476,11 +475,11 @@ RSpec.describe "bundler/inline#gemfile" do
script <<-RUBY
gemfile do
- source "#{file_uri_for(gem_repo1)}"
- gem "rack" # has the rackup executable
+ source "https://gem.repo1"
+ gem "myrack" # has the myrackup executable
end
- puts RACK
+ puts MYRACK
RUBY
expect(last_command).to be_success
expect(out).to eq "1.0.0"
@@ -488,14 +487,14 @@ RSpec.describe "bundler/inline#gemfile" do
context "when BUNDLE_PATH is set" do
it "installs inline gems to the system path regardless" do
- script <<-RUBY, env: { "BUNDLE_PATH" => "./vendor/inline" }
+ script <<-RUBY, env: { "BUNDLE_PATH" => "./vendor/inline", "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
gemfile(true) do
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
end
RUBY
expect(last_command).to be_success
- expect(system_gem_path("gems/rack-1.0.0")).to exist
+ expect(system_gem_path("gems/myrack-1.0.0")).to exist
end
end
@@ -504,8 +503,8 @@ RSpec.describe "bundler/inline#gemfile" do
script <<-RUBY
gemfile(true) do
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", platform: :jruby
+ source "https://gem.repo1"
+ gem "myrack", platform: :jruby
end
RUBY
@@ -517,21 +516,21 @@ RSpec.describe "bundler/inline#gemfile" do
script <<-RUBY
gemfile do
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
end
RUBY
expect(last_command).to be_success
- expect(system_gem_path("gems/rack-1.0.0")).to exist
+ expect(system_gem_path("gems/myrack-1.0.0")).to exist
end
it "preserves previous BUNDLE_GEMFILE value" do
ENV["BUNDLE_GEMFILE"] = ""
script <<-RUBY
gemfile do
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
end
puts "BUNDLE_GEMFILE is empty" if ENV["BUNDLE_GEMFILE"].empty?
@@ -547,8 +546,8 @@ RSpec.describe "bundler/inline#gemfile" do
ENV["BUNDLE_GEMFILE"] = nil
script <<-RUBY
gemfile do
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
end
puts "BUNDLE_GEMFILE is empty" if ENV["BUNDLE_GEMFILE"].empty?
@@ -576,9 +575,9 @@ RSpec.describe "bundler/inline#gemfile" do
s.write "lib/foo.rb", foo_code
end
- script <<-RUBY, dir: tmp("path_without_gemfile")
+ script <<-RUBY, dir: tmp("path_without_gemfile"), env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo2.to_s }
gemfile do
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
path "#{lib_path}" do
gem "foo", require: false
end
@@ -591,46 +590,19 @@ RSpec.describe "bundler/inline#gemfile" do
expect(err).to be_empty
end
- it "when requiring fileutils after does not show redefinition warnings", :realworld do
- 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"
-
- 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
-
- it "does not load default timeout" do
+ it "does not load default timeout", rubygems: ">= 3.5.0" do
default_timeout_version = ruby "gem 'timeout', '< 999999'; require 'timeout'; puts Timeout::VERSION", raise_on_error: false
skip "timeout isn't a default gem" if default_timeout_version.empty?
- # This only works on RubyGems 3.5.0 or higher
- ruby "require 'rubygems/timeout'", raise_on_error: false
- skip "rubygems under test does not yet vendor timeout" unless last_command.success?
-
build_repo4 do
build_gem "timeout", "999"
end
- script <<-RUBY
+ script <<-RUBY, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
require "bundler/inline"
gemfile(true) do
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "timeout"
end
@@ -647,7 +619,7 @@ RSpec.describe "bundler/inline#gemfile" do
puts("before: \#{ENV.each_key.select { |key| key.match?(/test_variable/i) }}")
gemfile do
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
end
puts("after: \#{ENV.each_key.select { |key| key.match?(/test_variable/i) }}")
@@ -656,4 +628,78 @@ RSpec.describe "bundler/inline#gemfile" do
expect(out).to include("before: [\"Test_Variable\"]")
expect(out).to include("after: [\"Test_Variable\"]")
end
+
+ it "does not create a lockfile" do
+ script <<-RUBY
+ require 'bundler/inline'
+
+ gemfile do
+ source "https://gem.repo1"
+ end
+
+ puts Dir.glob("Gemfile.lock")
+ RUBY
+
+ expect(out).to be_empty
+ end
+
+ it "does not reset ENV" do
+ script <<-RUBY
+ require 'bundler/inline'
+
+ gemfile do
+ source "https://gem.repo1"
+
+ ENV['FOO'] = 'bar'
+ end
+
+ puts ENV['FOO']
+ RUBY
+
+ expect(out).to eq("bar")
+ end
+
+ it "does not load specified version of psych and stringio", :ruby_repo do
+ build_repo4 do
+ build_gem "psych", "999"
+ build_gem "stringio", "999"
+ end
+
+ script <<-RUBY, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ require "bundler/inline"
+
+ gemfile(true) do
+ source "https://gem.repo4"
+
+ gem "psych"
+ gem "stringio"
+ end
+ RUBY
+
+ expect(out).to include("Installing psych 999")
+ expect(out).to include("Installing stringio 999")
+ expect(out).to include("The psych gem was resolved to 999")
+ expect(out).to include("The stringio gem was resolved to 999")
+ end
+
+ it "leaves a lockfile in the same directory as the inline script alone" do
+ install_gemfile <<~G
+ source "https://gem.repo1"
+ gem "foo"
+ G
+
+ original_lockfile = lockfile
+
+ script <<-RUBY, env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo1.to_s }
+ require "bundler/inline"
+
+ gemfile(true) do
+ source "https://gem.repo1"
+
+ gem "myrack"
+ end
+ RUBY
+
+ expect(lockfile).to eq(original_lockfile)
+ end
end
diff --git a/spec/bundler/runtime/load_spec.rb b/spec/bundler/runtime/load_spec.rb
index f28ffd9460..472cde87c5 100644
--- a/spec/bundler/runtime/load_spec.rb
+++ b/spec/bundler/runtime/load_spec.rb
@@ -4,18 +4,18 @@ RSpec.describe "Bundler.load" do
describe "with a gemfile" do
before(:each) do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
allow(Bundler::SharedHelpers).to receive(:pwd).and_return(bundled_app)
end
it "provides a list of the env dependencies" do
- expect(Bundler.load.dependencies).to have_dep("rack", ">= 0")
+ expect(Bundler.load.dependencies).to have_dep("myrack", ">= 0")
end
it "provides a list of the resolved gems" do
- expect(Bundler.load.gems).to have_gem("rack-1.0.0", "bundler-#{Bundler::VERSION}")
+ expect(Bundler.load.gems).to have_gem("myrack-1.0.0", "bundler-#{Bundler::VERSION}")
end
it "ignores blank BUNDLE_GEMFILEs" do
@@ -28,20 +28,20 @@ RSpec.describe "Bundler.load" do
describe "with a gems.rb file" do
before(:each) do
- create_file "gems.rb", <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ gemfile "gems.rb", <<-G
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle :install
allow(Bundler::SharedHelpers).to receive(:pwd).and_return(bundled_app)
end
it "provides a list of the env dependencies" do
- expect(Bundler.load.dependencies).to have_dep("rack", ">= 0")
+ expect(Bundler.load.dependencies).to have_dep("myrack", ">= 0")
end
it "provides a list of the resolved gems" do
- expect(Bundler.load.gems).to have_gem("rack-1.0.0", "bundler-#{Bundler::VERSION}")
+ expect(Bundler.load.gems).to have_gem("myrack-1.0.0", "bundler-#{Bundler::VERSION}")
end
end
@@ -68,7 +68,7 @@ RSpec.describe "Bundler.load" do
begin
expect { Bundler.load }.to raise_error(Bundler::GemfileNotFound)
ensure
- bundler_gemfile.rmtree if @remove_bundler_gemfile
+ FileUtils.rm_rf bundler_gemfile if @remove_bundler_gemfile
end
end
end
@@ -76,8 +76,8 @@ RSpec.describe "Bundler.load" do
describe "when called twice" do
it "doesn't try to load the runtime twice" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
gem "activesupport", :group => :test
G
@@ -85,7 +85,7 @@ RSpec.describe "Bundler.load" do
require "bundler"
Bundler.setup :default
Bundler.require :default
- puts RACK
+ puts MYRACK
begin
require "activesupport"
rescue LoadError
@@ -100,7 +100,7 @@ RSpec.describe "Bundler.load" do
describe "not hurting brittle rubygems" do
it "does not inject #source into the generated YAML of the gem specs" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "activerecord"
G
allow(Bundler::SharedHelpers).to receive(:find_gemfile).and_return(bundled_app_gemfile)
diff --git a/spec/bundler/runtime/platform_spec.rb b/spec/bundler/runtime/platform_spec.rb
index 1925e9bf2e..68b5626ed4 100644
--- a/spec/bundler/runtime/platform_spec.rb
+++ b/spec/bundler/runtime/platform_spec.rb
@@ -3,21 +3,21 @@
RSpec.describe "Bundler.setup with multi platform stuff" do
it "raises a friendly error when gems are missing locally" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
lockfile <<-G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
- rack (1.0)
+ myrack (1.0)
PLATFORMS
#{local_tag}
DEPENDENCIES
- rack
+ myrack
G
ruby <<-R
@@ -35,7 +35,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
it "will resolve correctly on the current platform when the lockfile was targeted for a different one" do
lockfile <<-G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
nokogiri (1.4.2-java)
weakling (= 0.0.3)
@@ -48,13 +48,14 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
nokogiri
G
- simulate_platform "x86-darwin-10"
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "nokogiri"
- G
+ simulate_platform "x86-darwin-10" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "nokogiri"
+ G
- expect(the_bundle).to include_gems "nokogiri 1.4.2"
+ expect(the_bundle).to include_gems "nokogiri 1.4.2"
+ end
end
it "will keep both platforms when both ruby and a specific ruby platform are locked and the bundle is unlocked" do
@@ -82,7 +83,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
good_lockfile = <<~L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
mini_portile2 (2.5.0)
nokogiri (1.11.1)
@@ -99,11 +100,11 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
nokogiri (~> 1.11)
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "nokogiri", "~> 1.11"
G
@@ -125,13 +126,13 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
end
gemfile <<-G
- source "https://gems.repo4"
+ source "https://gem.repo4"
gem "nokogiri"
G
lockfile <<~L
GEM
- remote: https://gems.repo4/
+ remote: https://gem.repo4/
specs:
nokogiri (1.11.1)
@@ -142,10 +143,10 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
nokogiri
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
- bundle "install", artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }
+ bundle "install"
expect(out).to include("Fetching nokogiri 1.11.1")
expect(the_bundle).to include_gems "nokogiri 1.11.1"
@@ -154,13 +155,13 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
it "will use the java platform if both generic java and generic ruby platforms are locked", :jruby_only do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "nokogiri"
G
lockfile <<-G
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
nokogiri (1.4.2)
nokogiri (1.4.2-java)
@@ -181,13 +182,13 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
bundle "install"
expect(out).to include("Fetching nokogiri 1.4.2 (java)")
- expect(the_bundle).to include_gems "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
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
nokogiri (1.4.2-java)
weakling (= 0.0.3)
@@ -200,20 +201,20 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
nokogiri
G
- simulate_platform "x86-darwin-100"
-
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "nokogiri"
- gem "platform_specific"
- G
+ simulate_platform "x86-darwin-100" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "nokogiri"
+ gem "platform_specific"
+ G
- expect(the_bundle).to include_gems "nokogiri 1.4.2", "platform_specific 1.0 x86-darwin-100"
+ expect(the_bundle).to include_gems "nokogiri 1.4.2", "platform_specific 1.0 x86-darwin-100"
+ end
end
it "allows specifying only-ruby-platform on jruby", :jruby_only do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "nokogiri"
gem "platform_specific"
G
@@ -222,12 +223,12 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
bundle "install"
- expect(the_bundle).to include_gems "nokogiri 1.4.2", "platform_specific 1.0 RUBY"
+ expect(the_bundle).to include_gems "nokogiri 1.4.2", "platform_specific 1.0 ruby"
end
it "allows specifying only-ruby-platform" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "nokogiri"
gem "platform_specific"
G
@@ -236,12 +237,12 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
bundle "install"
- expect(the_bundle).to include_gems "nokogiri 1.4.2", "platform_specific 1.0 RUBY"
+ 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)}"
+ source "https://gem.repo1"
gem "nokogiri"
gem "platform_specific"
G
@@ -250,27 +251,27 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
bundle "install"
- expect(the_bundle).to include_gems "nokogiri 1.4.2", "platform_specific 1.0 RUBY"
+ 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_only do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "platform_specific"
G
- expect(the_bundle).to include_gems "platform_specific 1.0 RUBY"
+ expect(the_bundle).to include_gems "platform_specific 1.0 ruby"
end
- it "doesn't pull platform specific gems on truffleruby (except when whitelisted) even if lockfile was generated with an older version that declared RUBY as platform", :truffleruby_only do
+ it "doesn't pull platform specific gems on truffleruby (except when whitelisted) even if lockfile was generated with an older version that declared ruby as platform", :truffleruby_only do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "platform_specific"
G
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
platform_specific (1.0)
@@ -281,12 +282,12 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
platform_specific
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "install"
- expect(the_bundle).to include_gems "platform_specific 1.0 RUBY"
+ expect(the_bundle).to include_gems "platform_specific 1.0 ruby"
simulate_platform "x86_64-linux" do
build_repo4 do
@@ -298,13 +299,13 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "libv8"
G
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo4)}/
+ remote: https://gem.repo4/
specs:
libv8 (1.0)
@@ -315,7 +316,7 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
libv8
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "install"
@@ -326,13 +327,13 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
it "doesn't pull platform specific gems on truffleruby, even if lockfile only includes those", :truffleruby_only do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "platform_specific"
G
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
platform_specific (1.0-x86-darwin-100)
@@ -343,12 +344,12 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
platform_specific
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
bundle "install"
- expect(the_bundle).to include_gems "platform_specific 1.0 RUBY"
+ expect(the_bundle).to include_gems "platform_specific 1.0 ruby"
end
it "pulls platform specific gems correctly on musl" do
@@ -359,8 +360,8 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
end
simulate_platform "aarch64-linux-musl" do
- install_gemfile <<-G, artifice: "compact_index", env: { "BUNDLER_SPEC_GEM_REPO" => gem_repo4.to_s }, verbose: true
- source "https://gems.repo4"
+ install_gemfile <<-G, verbose: true
+ source "https://gem.repo4"
gem "nokogiri"
G
end
@@ -369,10 +370,10 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
end
it "allows specifying only-ruby-platform on windows with dependency platforms" do
- simulate_windows do
+ simulate_platform "x86-mswin32" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "nokogiri", :platforms => [:windows, :mswin, :mswin64, :mingw, :x64_mingw, :jruby]
+ source "https://gem.repo1"
+ gem "nokogiri", :platforms => [:windows, :jruby]
gem "platform_specific"
G
@@ -380,27 +381,27 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
bundle "install"
- expect(the_bundle).to include_gems "platform_specific 1.0 RUBY"
+ 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: bundled_app) do |s|
- s.add_dependency "rack"
+ s.add_dependency "myrack"
end
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gemspec
G
bundle :lock
- simulate_windows do
+ simulate_platform "x86-mswin32" do
bundle "config set force_ruby_platform true"
bundle "install"
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
end
@@ -410,17 +411,17 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
s.add_dependency "platform_specific"
end
end
- simulate_windows x64_mingw32 do
+ simulate_platform "x64-mingw-ucrt" do
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
platform_specific (1.0-x86-mingw32)
requires_platform_specific (1.0)
platform_specific
PLATFORMS
- x64-mingw32
+ x64-mingw-ucrt
x86-mingw32
DEPENDENCIES
@@ -428,23 +429,21 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
L
install_gemfile <<-G, verbose: true
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "requires_platform_specific"
G
expect(out).to include("lockfile does not have all gems needed for the current platform")
- expect(the_bundle).to include_gem "platform_specific 1.0 x64-mingw32"
+ expect(the_bundle).to include_gem "platform_specific 1.0 x64-mingw-ucrt"
end
end
- %w[x86-mswin32 x64-mswin64 x86-mingw32 x64-mingw32 x64-mingw-ucrt].each do |arch|
- it "allows specifying platform windows on #{arch} arch" do
- platform = send(arch.tr("-", "_"))
-
- simulate_windows platform do
+ %w[x86-mswin32 x64-mswin64 x86-mingw32 x64-mingw-ucrt aarch64-mingw-ucrt].each do |platform|
+ it "allows specifying platform windows on #{platform} platform" do
+ simulate_platform platform do
lockfile <<-L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
platform_specific (1.0-#{platform})
requires_platform_specific (1.0)
@@ -458,12 +457,10 @@ RSpec.describe "Bundler.setup with multi platform stuff" do
L
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "platform_specific", :platforms => [:windows]
G
- bundle "install"
-
expect(the_bundle).to include_gems "platform_specific 1.0 #{platform}"
end
end
diff --git a/spec/bundler/runtime/require_spec.rb b/spec/bundler/runtime/require_spec.rb
index e630e902c9..46613286d2 100644
--- a/spec/bundler/runtime/require_spec.rb
+++ b/spec/bundler/runtime/require_spec.rb
@@ -46,7 +46,7 @@ RSpec.describe "Bundler.require" do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
path "#{lib_path}" do
gem "one", :group => :bar, :require => %w[baz qux]
gem "two"
@@ -113,17 +113,15 @@ RSpec.describe "Bundler.require" do
it "raises an exception if a require is specified but the file does not exist" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
path "#{lib_path}" do
gem "two", :require => 'fail'
end
G
- load_error_run <<-R, "fail"
- Bundler.require
- R
+ run "Bundler.require", raise_on_error: false
- expect(err_without_deprecations).to eq("ZOMG LOAD ERROR")
+ expect(err_without_deprecations).to include("cannot load such file -- fail")
end
it "displays a helpful message if the required gem throws an error" do
@@ -132,7 +130,7 @@ RSpec.describe "Bundler.require" do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
path "#{lib_path}" do
gem "faulty"
end
@@ -149,22 +147,15 @@ RSpec.describe "Bundler.require" do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
path "#{lib_path}" do
gem "loadfuuu"
end
G
- cmd = <<-RUBY
- begin
- Bundler.require
- rescue LoadError => e
- warn "ZOMG LOAD ERROR: \#{e.message}"
- end
- RUBY
- run(cmd)
+ run "Bundler.require", raise_on_error: false
- expect(err_without_deprecations).to eq("ZOMG LOAD ERROR: cannot load such file -- load-bar")
+ expect(err_without_deprecations).to include("cannot load such file -- load-bar")
end
describe "with namespaced gems" do
@@ -176,7 +167,7 @@ RSpec.describe "Bundler.require" do
it "requires gem names that are namespaced" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
path '#{lib_path}' do
gem 'jquery-rails'
end
@@ -191,7 +182,7 @@ RSpec.describe "Bundler.require" do
s.write "lib/brcrypt.rb", "BCrypt = '1.0.0'"
end
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
path "#{lib_path}" do
gem "bcrypt-ruby"
@@ -209,16 +200,15 @@ RSpec.describe "Bundler.require" do
it "does not mangle explicitly given requires" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
path "#{lib_path}" do
gem 'jquery-rails', :require => 'jquery-rails'
end
G
- load_error_run <<-R, "jquery-rails"
- Bundler.require
- R
- expect(err_without_deprecations).to eq("ZOMG LOAD ERROR")
+ run "Bundler.require", raise_on_error: false
+
+ expect(err_without_deprecations).to include("cannot load such file -- jquery-rails")
end
it "handles the case where regex fails" do
@@ -227,22 +217,15 @@ RSpec.describe "Bundler.require" do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
path "#{lib_path}" do
gem "load-fuuu"
end
G
- cmd = <<-RUBY
- begin
- Bundler.require
- rescue LoadError => e
- warn "ZOMG LOAD ERROR" if e.message.include?("Could not open library 'libfuuu-1.0'")
- end
- RUBY
- run(cmd)
+ run "Bundler.require", raise_on_error: false
- expect(err_without_deprecations).to eq("ZOMG LOAD ERROR")
+ expect(err_without_deprecations).to include("libfuuu-1.0").and include("cannot open shared object file")
end
it "doesn't swallow the error when the library has an unrelated error" do
@@ -251,22 +234,15 @@ RSpec.describe "Bundler.require" do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
path "#{lib_path}" do
gem "load-fuuu"
end
G
- cmd = <<-RUBY
- begin
- Bundler.require
- rescue LoadError => e
- warn "ZOMG LOAD ERROR: \#{e.message}"
- end
- RUBY
- run(cmd)
+ run "Bundler.require", raise_on_error: false
- expect(err_without_deprecations).to eq("ZOMG LOAD ERROR: cannot load such file -- load-bar")
+ expect(err_without_deprecations).to include("cannot load such file -- load-bar")
end
end
@@ -310,7 +286,7 @@ RSpec.describe "Bundler.require" do
it "works when the gems are in the Gemfile in the correct order" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
path "#{lib_path}" do
gem "two"
gem "one"
@@ -329,7 +305,7 @@ RSpec.describe "Bundler.require" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "multi_gem", :require => "one", :group => :one
gem "multi_gem", :require => "two", :group => :two
G
@@ -353,7 +329,7 @@ RSpec.describe "Bundler.require" do
it "fails when the gems are in the Gemfile in the wrong order" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
path "#{lib_path}" do
gem "one"
gem "two"
@@ -371,26 +347,25 @@ RSpec.describe "Bundler.require" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "busted_require"
G
- load_error_run <<-R, "no_such_file_omg"
- Bundler.require
- R
- expect(err_without_deprecations).to eq("ZOMG LOAD ERROR")
+ run "Bundler.require", raise_on_error: false
+
+ expect(err_without_deprecations).to include("cannot load such file -- no_such_file_omg")
end
end
end
it "does not load rubygems gemspecs that are used" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
run <<-R
- path = File.join(Gem.dir, "specifications", "rack-1.0.0.gemspec")
+ path = File.join(Gem.dir, "specifications", "myrack-1.0.0.gemspec")
contents = File.read(path)
contents = contents.lines.to_a.insert(-2, "\n raise 'broken gemspec'\n").join
File.open(path, "w") do |f|
@@ -410,7 +385,7 @@ RSpec.describe "Bundler.require" do
build_git "foo"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "foo", :git => "#{lib_path("foo-1.0")}"
G
@@ -431,15 +406,31 @@ RSpec.describe "Bundler.require" do
expect(out).to eq("WIN")
end
+ it "does not load plugins" do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+
+ create_file "plugins/rubygems_plugin.rb", "puts 'FAIL'"
+
+ run <<~R, env: { "RUBYLIB" => rubylib.unshift(bundled_app("plugins").to_s).join(File::PATH_SEPARATOR) }
+ Bundler.require
+ puts "WIN"
+ R
+
+ expect(out).to eq("WIN")
+ end
+
it "does not extract gemspecs from application cache packages" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle :cache
- path = cached_gem("rack-1.0.0")
+ path = cached_gem("myrack-1.0.0")
run <<-R
File.open("#{path}", "w") do |f|
@@ -459,13 +450,13 @@ end
RSpec.describe "Bundler.require with platform specific dependencies" do
it "does not require the gems that are pinned to other platforms" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
platforms :#{not_local_tag} do
gem "platform_specific", :require => "omgomg"
end
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
G
run "Bundler.require"
@@ -474,14 +465,14 @@ RSpec.describe "Bundler.require with platform specific dependencies" do
it "requires gems pinned to multiple platforms, including the current one" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
platforms :#{not_local_tag}, :#{local_tag} do
- gem "rack", :require => "rack"
+ gem "myrack", :require => "myrack"
end
G
- run "Bundler.require; puts RACK"
+ run "Bundler.require; puts MYRACK"
expect(out).to eq("1.0.0")
expect(err).to be_empty
diff --git a/spec/bundler/runtime/requiring_spec.rb b/spec/bundler/runtime/requiring_spec.rb
index 1f32269622..f0e0aeacaf 100644
--- a/spec/bundler/runtime/requiring_spec.rb
+++ b/spec/bundler/runtime/requiring_spec.rb
@@ -2,14 +2,14 @@
RSpec.describe "Requiring bundler" do
it "takes care of requiring rubygems when entrypoint is bundler/setup" do
- sys_exec("#{Gem.ruby} -I#{lib_dir} -rbundler/setup -e'puts true'", env: { "RUBYOPT" => opt_add("--disable=gems", ENV["RUBYOPT"]) })
+ sys_exec("#{Gem.ruby} -I#{lib_dir} -rbundler/setup -e'puts true'", env: { "RUBYOPT" => "--disable=gems" })
- expect(last_command.stdboth).to eq("true")
+ expect(stdboth).to eq("true")
end
it "takes care of requiring rubygems when requiring just bundler" do
- sys_exec("#{Gem.ruby} -I#{lib_dir} -rbundler -e'puts true'", env: { "RUBYOPT" => opt_add("--disable=gems", ENV["RUBYOPT"]) })
+ sys_exec("#{Gem.ruby} -I#{lib_dir} -rbundler -e'puts true'", env: { "RUBYOPT" => "--disable=gems" })
- expect(last_command.stdboth).to eq("true")
+ expect(stdboth).to eq("true")
end
end
diff --git a/spec/bundler/runtime/self_management_spec.rb b/spec/bundler/runtime/self_management_spec.rb
index d15ca3189e..fbffd2dca2 100644
--- a/spec/bundler/runtime/self_management_spec.rb
+++ b/spec/bundler/runtime/self_management_spec.rb
@@ -1,52 +1,75 @@
# frozen_string_literal: true
-RSpec.describe "Self management", rubygems: ">= 3.3.0.dev", realworld: true do
+RSpec.describe "Self management" do
describe "auto switching" do
let(:previous_minor) do
- "2.3.0"
+ "9.3.0"
end
let(:current_version) do
- "2.4.0"
+ "9.4.0"
end
before do
- build_repo2
+ build_repo4 do
+ build_bundler previous_minor
+
+ build_bundler current_version
+
+ build_gem "myrack", "1.0.0"
+ end
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo4"
- gem "rack"
+ gem "myrack"
G
+
+ pristine_system_gems "bundler-#{current_version}"
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.")
+ bundle "install"
+ expect(out).to include("Bundler #{current_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", artifice: nil
- expect(out).to eq("Removing bundler (#{Bundler::VERSION})")
+ expect(out).to eq("Removing bundler (#{current_version})")
# App now uses locked version
bundle "-v", artifice: nil
- expect(out).to end_with(previous_minor[0] == "2" ? "Bundler version #{previous_minor}" : previous_minor)
+ expect(out).to eq(previous_minor)
+
+ # ruby-core test setup has always "lib" in $LOAD_PATH so `require "bundler/setup"` always activate the local version rather than using RubyGems gem activation stuff
+ unless ruby_core?
+ # App now uses locked version, even when not using the CLI directly
+ file = bundled_app("bin/bundle_version.rb")
+ create_file file, <<-RUBY
+ #!#{Gem.ruby}
+ require 'bundler/setup'
+ puts '#{previous_minor}'
+ RUBY
+ file.chmod(0o777)
+ cmd = Gem.win_platform? ? "#{Gem.ruby} bin/bundle_version.rb" : "bin/bundle_version.rb"
+ in_bundled_app cmd
+ expect(out).to eq(previous_minor)
+ end
# Subsequent installs use the locked version without reinstalling
bundle "install --verbose", artifice: nil
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.")
+ expect(out).not_to include("Bundler #{current_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.")
+ bundle "install"
+ expect(out).to include("Bundler #{current_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
@@ -55,20 +78,39 @@ RSpec.describe "Self management", rubygems: ">= 3.3.0.dev", realworld: true do
# App now uses locked version
bundle "-v"
- expect(out).to end_with(previous_minor[0] == "2" ? "Bundler version #{previous_minor}" : previous_minor)
+ expect(out).to eq(previous_minor)
+
+ # Preserves original gem home when auto-switching
+ bundle "exec ruby -e 'puts Bundler.original_env[\"GEM_HOME\"]'"
+ expect(out).to eq(ENV["GEM_HOME"])
+
+ # ruby-core test setup has always "lib" in $LOAD_PATH so `require "bundler/setup"` always activate the local version rather than using RubyGems gem activation stuff
+ unless ruby_core?
+ # App now uses locked version, even when not using the CLI directly
+ file = bundled_app("bin/bundle_version.rb")
+ create_file file, <<-RUBY
+ #!#{Gem.ruby}
+ require 'bundler/setup'
+ puts '#{previous_minor}'
+ RUBY
+ file.chmod(0o777)
+ cmd = Gem.win_platform? ? "#{Gem.ruby} bin/bundle_version.rb" : "bin/bundle_version.rb"
+ in_bundled_app cmd
+ expect(out).to eq(previous_minor)
+ end
# 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.")
+ expect(out).not_to include("Bundler #{current_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.")
+ bundle "install"
+ expect(out).to include("Bundler #{current_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
@@ -77,12 +119,12 @@ RSpec.describe "Self management", rubygems: ">= 3.3.0.dev", realworld: true do
# App now uses locked version
bundle "-v"
- expect(out).to end_with(previous_minor[0] == "2" ? "Bundler version #{previous_minor}" : previous_minor)
+ expect(out).to eq(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.")
+ expect(out).not_to include("Bundler #{current_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
@@ -92,48 +134,108 @@ RSpec.describe "Self management", rubygems: ">= 3.3.0.dev", realworld: true do
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)
+ expect(out).to eq(current_version)
+ end
+
+ it "does not try to install when --local is passed" do
+ lockfile_bundled_with(previous_minor)
+ system_gems "myrack-1.0.0", path: local_gem_path
+
+ bundle "install --local"
+ expect(out).not_to match(/Installing Bundler/)
+
+ bundle "-v"
+ expect(out).to eq(current_version)
end
it "shows a discrete message if locked bundler does not exist" do
- missing_minor = "#{Bundler::VERSION[0]}.999.999"
+ missing_minor = "#{current_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 "install"
+ 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 #{current_version}")
bundle "-v"
- expect(out).to eq(Bundler::VERSION[0] == "2" ? "Bundler version #{Bundler::VERSION}" : Bundler::VERSION)
+ expect(out).to eq(current_version)
end
it "installs BUNDLE_VERSION version when using bundle config version x.y.z" do
lockfile_bundled_with(current_version)
bundle "config set --local version #{previous_minor}"
- bundle "install", artifice: "vcr"
- expect(out).to include("Bundler #{Bundler::VERSION} is running, but your configuration was #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.")
+ bundle "install"
+ expect(out).to include("Bundler #{current_version} is running, but your configuration was #{previous_minor}. Installing Bundler #{previous_minor} and restarting using that version.")
bundle "-v"
- expect(out).to eq(previous_minor[0] == "2" ? "Bundler version #{previous_minor}" : previous_minor)
+ expect(out).to eq(previous_minor)
end
it "does not try to install when using bundle config version global" do
lockfile_bundled_with(previous_minor)
bundle "config set version system"
- bundle "install", artifice: "vcr"
+ bundle "install"
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)
+ expect(out).to eq(current_version)
+ end
+
+ it "does not try to install when using bundle config version <dev-version>" do
+ lockfile_bundled_with(previous_minor)
+
+ bundle "config set version #{previous_minor}.dev"
+ bundle "install"
+ expect(out).not_to match(/restarting using that version/)
+
+ bundle "-v"
+ expect(out).to eq(current_version)
end
it "ignores malformed lockfile version" do
lockfile_bundled_with("2.3.")
bundle "install --verbose"
- expect(out).to include("Using bundler #{Bundler::VERSION}")
+ expect(out).to include("Using bundler #{current_version}")
+ end
+
+ it "uses the right original script when re-execing, if `$0` has been changed to something that's not a script", :ruby_repo do
+ system_gems "bundler-9.9.9", path: local_gem_path
+
+ test = bundled_app("test.rb")
+
+ create_file test, <<~RUBY
+ $0 = "this is the program name"
+ require "bundler/setup"
+ RUBY
+
+ lockfile_bundled_with("9.9.9")
+
+ in_bundled_app "#{Gem.ruby} #{test}", raise_on_error: false
+ expect(err).to include("Could not find myrack-1.0.0")
+ expect(err).not_to include("this is the program name")
+ end
+
+ it "uses modified $0 when re-execing, if `$0` has been changed to a script", :ruby_repo do
+ system_gems "bundler-9.9.9", path: local_gem_path
+
+ runner = bundled_app("runner.rb")
+
+ create_file runner, <<~RUBY
+ $0 = ARGV.shift
+ load $0
+ RUBY
+
+ script = bundled_app("script.rb")
+ create_file script, <<~RUBY
+ require "bundler/setup"
+ RUBY
+
+ lockfile_bundled_with("9.9.9")
+
+ in_bundled_app "#{Gem.ruby} #{runner} #{script}", raise_on_error: false
+ expect(err).to include("Could not find myrack-1.0.0")
end
private
@@ -141,15 +243,15 @@ RSpec.describe "Self management", rubygems: ">= 3.3.0.dev", realworld: true do
def lockfile_bundled_with(version)
lockfile <<~L
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo4/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
BUNDLED WITH
#{version}
diff --git a/spec/bundler/runtime/setup_spec.rb b/spec/bundler/runtime/setup_spec.rb
index a210f99069..1ffaffef0e 100644
--- a/spec/bundler/runtime/setup_spec.rb
+++ b/spec/bundler/runtime/setup_spec.rb
@@ -6,16 +6,16 @@ RSpec.describe "Bundler.setup" do
describe "with no arguments" do
it "makes all groups available" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :group => :test
+ source "https://gem.repo1"
+ gem "myrack", :group => :test
G
ruby <<-RUBY
require 'bundler'
Bundler.setup
- require 'rack'
- puts RACK
+ require 'myrack'
+ puts MYRACK
RUBY
expect(err).to be_empty
expect(out).to eq("1.0.0")
@@ -25,9 +25,9 @@ RSpec.describe "Bundler.setup" do
describe "when called with groups" do
before(:each) do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "yard"
- gem "rack", :group => :test
+ gem "myrack", :group => :test
G
end
@@ -37,7 +37,7 @@ RSpec.describe "Bundler.setup" do
Bundler.setup(:default)
begin
- require 'rack'
+ require 'myrack'
rescue LoadError
puts "WIN"
end
@@ -51,8 +51,8 @@ RSpec.describe "Bundler.setup" do
require 'bundler'
Bundler.setup(:default, 'test')
- require 'rack'
- puts RACK
+ require 'myrack'
+ puts MYRACK
RUBY
expect(err).to be_empty
expect(out).to eq("1.0.0")
@@ -64,8 +64,8 @@ RSpec.describe "Bundler.setup" do
Bundler.setup
Bundler.setup(:default)
- require 'rack'
- puts RACK
+ require 'myrack'
+ puts MYRACK
RUBY
expect(err).to be_empty
expect(out).to eq("1.0.0")
@@ -93,12 +93,12 @@ RSpec.describe "Bundler.setup" do
require 'bundler'
Bundler.setup(:default, :test)
Bundler.setup(:default)
- require 'rack'
+ require 'myrack'
puts "FAIL"
RUBY
- expect(err).to match("rack")
+ expect(err).to match("myrack")
expect(err).to match("LoadError")
expect(out).not_to match("FAIL")
end
@@ -113,8 +113,8 @@ RSpec.describe "Bundler.setup" do
it "puts loaded gems after -I and RUBYLIB", :ruby_repo do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
ENV["RUBYOPT"] = "#{ENV["RUBYOPT"]} -Idash_i_dir"
@@ -127,18 +127,18 @@ RSpec.describe "Bundler.setup" do
RUBY
load_path = out.split("\n")
- rack_load_order = load_path.index {|path| path.include?("rack") }
+ myrack_load_order = load_path.index {|path| path.include?("myrack") }
expect(err).to be_empty
expect(load_path).to include(a_string_ending_with("dash_i_dir"), "rubylib_dir")
- expect(rack_load_order).to be > 0
+ expect(myrack_load_order).to be > 0
end
it "orders the load path correctly when there are dependencies" do
bundle "config set path.system true"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "rails"
G
@@ -166,7 +166,7 @@ RSpec.describe "Bundler.setup" do
bundle "config set path.system true"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "weakling"
gem "duradura"
gem "terranova"
@@ -189,8 +189,8 @@ RSpec.describe "Bundler.setup" do
it "raises if the Gemfile was not yet installed" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
ruby <<-R
@@ -209,8 +209,8 @@ RSpec.describe "Bundler.setup" do
it "doesn't create a Gemfile.lock if the setup fails" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
ruby <<-R, raise_on_error: false
@@ -224,15 +224,15 @@ RSpec.describe "Bundler.setup" do
it "doesn't change the Gemfile.lock if the setup fails" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
lockfile = File.read(bundled_app_lock)
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
gem "nosuchgem", "10.0"
G
@@ -247,8 +247,8 @@ RSpec.describe "Bundler.setup" do
it "makes a Gemfile.lock if setup succeeds" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
File.read(bundled_app_lock)
@@ -263,12 +263,12 @@ RSpec.describe "Bundler.setup" do
context "user provides an absolute path" do
it "uses BUNDLE_GEMFILE to locate the gemfile if present" do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
gemfile bundled_app("4realz"), <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "activesupport", "2.3.5"
G
@@ -282,7 +282,7 @@ RSpec.describe "Bundler.setup" do
context "an absolute path is not provided" 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)}"
+ source "https://gem.repo1"
G
bundle "install"
@@ -308,23 +308,23 @@ RSpec.describe "Bundler.setup" do
it "prioritizes gems in BUNDLE_PATH over gems in GEM_HOME" do
ENV["BUNDLE_PATH"] = bundled_app(".bundle").to_s
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "1.0.0"
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0"
G
- build_gem "rack", "1.0", to_system: true do |s|
- s.write "lib/rack.rb", "RACK = 'FAIL'"
+ build_gem "myrack", "1.0", to_system: true do |s|
+ s.write "lib/myrack.rb", "MYRACK = 'FAIL'"
end
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
describe "integrate with rubygems" do
describe "by replacing #gem" do
before :each do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "0.9.1"
+ source "https://gem.repo1"
+ gem "myrack", "0.9.1"
G
end
@@ -344,7 +344,7 @@ RSpec.describe "Bundler.setup" do
it "replaces #gem but raises when the version is wrong" do
run <<-R
begin
- gem "rack", "1.0.0"
+ gem "myrack", "1.0.0"
puts "FAIL"
rescue LoadError
puts "WIN"
@@ -359,14 +359,15 @@ RSpec.describe "Bundler.setup" do
before :each do
system_gems "activesupport-2.3.5"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "yard"
G
end
it "removes system gems from Gem.source_index" do
run "require 'yard'"
- expect(out).to eq("bundler-#{Bundler::VERSION}\nyard-1.0")
+ expect(out).to include("bundler-#{Bundler::VERSION}").and include("yard-1.0")
+ expect(out).not_to include("activesupport-2.3.5")
end
context "when the ruby stdlib is a substring of Gem.path" do
@@ -381,37 +382,37 @@ RSpec.describe "Bundler.setup" do
describe "with paths" do
it "activates the gems in the path source" do
- system_gems "rack-1.0.0"
+ system_gems "myrack-1.0.0"
- build_lib "rack", "1.0.0" do |s|
- s.write "lib/rack.rb", "puts 'WIN'"
+ build_lib "myrack", "1.0.0" do |s|
+ s.write "lib/myrack.rb", "puts 'WIN'"
end
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- path "#{lib_path("rack-1.0.0")}" do
- gem "rack"
+ source "https://gem.repo1"
+ path "#{lib_path("myrack-1.0.0")}" do
+ gem "myrack"
end
G
- run "require 'rack'"
+ run "require 'myrack'"
expect(out).to eq("WIN")
end
end
describe "with git" do
before do
- build_git "rack", "1.0.0"
+ build_git "myrack", "1.0.0"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-1.0.0")}"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-1.0.0")}"
G
end
it "provides a useful exception when the git repo is not checked out yet" do
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)
+ expect(err).to match(/the git source #{lib_path("myrack-1.0.0")} is not yet checked out. Please run `bundle install`/i)
end
it "does not hit the git binary if the lockfile is available and up to date" do
@@ -457,10 +458,9 @@ RSpec.describe "Bundler.setup" do
end
it "works even when the cache directory has been deleted" do
- 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"
+ FileUtils.rm_r default_cache_path
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
it "does not randomly change the path when specifying --path and the bundle directory becomes read only" do
@@ -468,7 +468,7 @@ RSpec.describe "Bundler.setup" do
bundle :install
with_read_only("#{bundled_app}/**/*") do
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
@@ -477,91 +477,91 @@ RSpec.describe "Bundler.setup" do
bundle "install"
with_read_only("#{bundled_app(".bundle")}/**/*") do
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
end
describe "when specifying local override" do
it "explodes if given path does not exist on runtime" do
- build_git "rack", "0.8"
+ build_git "myrack", "0.8"
- FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
+ FileUtils.cp_r("#{lib_path("myrack-0.8")}/.", lib_path("local-myrack"))
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
G
- bundle %(config set local.rack #{lib_path("local-rack")})
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
bundle :install
- FileUtils.rm_rf(lib_path("local-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/)
+ FileUtils.rm_r(lib_path("local-myrack"))
+ run "require 'myrack'", raise_on_error: false
+ expect(err).to match(/Cannot use local override for myrack-0.8 because #{Regexp.escape(lib_path("local-myrack").to_s)} does not exist/)
end
it "explodes if branch is not given on runtime" do
- build_git "rack", "0.8"
+ build_git "myrack", "0.8"
- FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
+ FileUtils.cp_r("#{lib_path("myrack-0.8")}/.", lib_path("local-myrack"))
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
G
- bundle %(config set local.rack #{lib_path("local-rack")})
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
bundle :install
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}"
G
- run "require 'rack'", raise_on_error: false
+ run "require 'myrack'", raise_on_error: false
expect(err).to match(/because :branch is not specified in Gemfile/)
end
it "explodes on different branches on runtime" do
- build_git "rack", "0.8"
+ build_git "myrack", "0.8"
- FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
+ FileUtils.cp_r("#{lib_path("myrack-0.8")}/.", lib_path("local-myrack"))
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "main"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
G
- bundle %(config set local.rack #{lib_path("local-rack")})
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
bundle :install
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :branch => "changed"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "changed"
G
- run "require 'rack'", raise_on_error: false
+ run "require 'myrack'", raise_on_error: false
expect(err).to match(/is using branch main but Gemfile specifies changed/)
end
it "explodes on refs with different branches on runtime" do
- build_git "rack", "0.8"
+ build_git "myrack", "0.8"
- FileUtils.cp_r("#{lib_path("rack-0.8")}/.", lib_path("local-rack"))
+ FileUtils.cp_r("#{lib_path("myrack-0.8")}/.", lib_path("local-myrack"))
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :ref => "main", :branch => "main"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :ref => "main", :branch => "main"
G
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{lib_path("rack-0.8")}", :ref => "main", :branch => "nonexistent"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :ref => "main", :branch => "nonexistent"
G
- bundle %(config set local.rack #{lib_path("local-rack")})
- run "require 'rack'", raise_on_error: false
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
+ run "require 'myrack'", raise_on_error: false
expect(err).to match(/is using branch main but Gemfile specifies nonexistent/)
end
end
@@ -570,7 +570,7 @@ RSpec.describe "Bundler.setup" do
it "doesn't change the resolve if --without is used" do
bundle "config set --local without rails"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "activesupport"
group :rails do
@@ -586,7 +586,7 @@ RSpec.describe "Bundler.setup" do
it "remembers --without and does not bail on bare Bundler.setup" do
bundle "config set --local without rails"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "activesupport"
group :rails do
@@ -606,12 +606,12 @@ RSpec.describe "Bundler.setup" do
build_lib "foo", path: path
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "activesupport", "2.3.2"
gem 'foo', :path => 'vendor/foo', :group => :development
G
- FileUtils.rm_rf(path)
+ FileUtils.rm_r(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")
@@ -629,7 +629,7 @@ RSpec.describe "Bundler.setup" do
end
install_gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "depends_on_bundler"
G
@@ -641,7 +641,7 @@ RSpec.describe "Bundler.setup" do
it "doesn't fail in frozen mode when bundler is a Gemfile dependency" do
install_gemfile <<~G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "bundler"
G
@@ -651,14 +651,14 @@ RSpec.describe "Bundler.setup" do
it "doesn't re-resolve when deleting dependencies" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
gem "actionpack"
G
install_gemfile <<-G, verbose: true
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
expect(out).to include("Some dependencies were deleted, using a subset of the resolution from the lockfile")
@@ -668,11 +668,11 @@ RSpec.describe "Bundler.setup" do
it "remembers --without and does not include groups passed to Bundler.setup" do
bundle "config set --local without rails"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "activesupport"
- group :rack do
- gem "rack"
+ group :myrack do
+ gem "myrack"
end
group :rails do
@@ -680,8 +680,8 @@ RSpec.describe "Bundler.setup" do
end
G
- expect(the_bundle).not_to include_gems "activesupport 2.3.2", groups: :rack
- expect(the_bundle).to include_gems "rack 1.0.0", groups: :rack
+ expect(the_bundle).not_to include_gems "activesupport 2.3.2", groups: :myrack
+ expect(the_bundle).to include_gems "myrack 1.0.0", groups: :myrack
end
end
@@ -691,8 +691,8 @@ RSpec.describe "Bundler.setup" do
build_git "no-gemspec", gemspec: false
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
gem "foo", :git => "#{lib_path("foo-1.0")}"
gem "no-gemspec", "1.0", :git => "#{lib_path("no-gemspec-1.0")}"
G
@@ -706,59 +706,80 @@ RSpec.describe "Bundler.setup" do
expect(out).to be_empty
end
+ it "has gem_dir pointing to local repo" do
+ build_lib "foo", "1.0", path: bundled_app
+
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gemspec
+ G
+
+ run <<-R
+ puts Gem.loaded_specs['foo'].gem_dir
+ R
+
+ expect(out).to eq(bundled_app.to_s)
+ end
+
it "does not load all gemspecs" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
run <<-R
- File.open(File.join(Gem.dir, "specifications", "broken.gemspec"), "w") do |f|
+ File.open(File.join(Gem.dir, "specifications", "invalid.gemspec"), "w") do |f|
f.write <<-RUBY
# -*- encoding: utf-8 -*-
-# stub: broken 1.0.0 ruby lib
+# stub: invalid 1.0.0 ruby lib
Gem::Specification.new do |s|
- s.name = "broken"
+ s.name = "invalid"
s.version = "1.0.0"
- raise "BROKEN GEMSPEC"
+ s.authors = ["Invalid Author"]
+ s.files = ["lib/invalid.rb"]
+ s.add_dependency "nonexistent-gem", "~> 999.999.999"
+ s.validate!
end
RUBY
end
R
run <<-R
- File.open(File.join(Gem.dir, "specifications", "broken-ext.gemspec"), "w") do |f|
+ File.open(File.join(Gem.dir, "specifications", "invalid-ext.gemspec"), "w") do |f|
f.write <<-RUBY
# -*- encoding: utf-8 -*-
-# stub: broken-ext 1.0.0 ruby lib
+# stub: invalid-ext 1.0.0 ruby lib
# stub: a.ext\\0b.ext
Gem::Specification.new do |s|
- s.name = "broken-ext"
+ s.name = "invalid-ext"
s.version = "1.0.0"
- raise "BROKEN GEMSPEC EXT"
+ s.authors = ["Invalid Author"]
+ s.files = ["lib/invalid.rb"]
+ s.required_ruby_version = "~> 0.8.0"
+ s.validate!
end
RUBY
end
# Need to write the gem.build_complete file,
# otherwise the full spec is loaded to check the installed_by_version
extensions_dir = Gem.default_ext_dir_for(Gem.dir) || File.join(Gem.dir, "extensions", Gem::Platform.local.to_s, Gem.extension_api_version)
- Bundler::FileUtils.mkdir_p(File.join(extensions_dir, "broken-ext-1.0.0"))
- File.open(File.join(extensions_dir, "broken-ext-1.0.0", "gem.build_complete"), "w") {}
+ Bundler::FileUtils.mkdir_p(File.join(extensions_dir, "invalid-ext-1.0.0"))
+ File.open(File.join(extensions_dir, "invalid-ext-1.0.0", "gem.build_complete"), "w") {}
R
run <<-R
- puts "WIN"
+ puts "Success"
R
- expect(out).to eq("WIN")
+ expect(out).to eq("Success")
end
it "ignores empty gem paths" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
ENV["GEM_HOME"] = ""
@@ -767,10 +788,10 @@ end
expect(err).to be_empty
end
- it "can require rubygems without warnings, when using a local cache" do
+ it "can require rubygems without warnings, when using a local cache", :truffleruby do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
bundle "package"
@@ -790,7 +811,7 @@ end
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "with_man"
G
@@ -814,7 +835,7 @@ end
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "with_man"
G
@@ -827,7 +848,7 @@ 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)}"
+ source "https://gem.repo4"
gem "with_man_overriding_system_man"
G
@@ -854,7 +875,7 @@ end
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem "requirepaths", :require => nil
G
@@ -865,21 +886,14 @@ end
it "should clean $LOAD_PATH properly" do
gem_name = "very_simple_binary"
full_gem_name = gem_name + "-1.0"
- ext_dir = File.join(tmp("extensions", full_gem_name))
system_gems full_gem_name
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
G
ruby <<-R
- 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 }
-
require 'bundler'
gem '#{gem_name}'
@@ -917,7 +931,7 @@ end
end
it "should not remove itself from the LOAD_PATH and require a different copy of 'bundler/setup'" do
- install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
+ install_gemfile "source 'https://gem.repo1'"
ruby <<-R, env: { "GEM_PATH" => symlinked_gem_home }
TracePoint.trace(:class) do |tp|
@@ -934,10 +948,10 @@ end
end
it "does not reveal system gems even when Gem.refresh is called" do
- system_gems "rack-1.0.0"
+ system_gems "myrack-1.0.0"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "activesupport"
G
@@ -966,7 +980,7 @@ end
FileUtils.rm(File.join(path, "foo.gemspec"))
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'foo', '1.2.3', :path => 'vendor/foo'
G
@@ -987,7 +1001,7 @@ end
FileUtils.rm(File.join(absolute_path, "foo.gemspec"))
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'foo', '1.2.3', :path => '#{relative_path}'
G
@@ -1006,7 +1020,7 @@ end
build_git "no_gemspec", gemspec: false
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "no_gemspec", "1.0", :git => "#{lib_path("no_gemspec-1.0")}"
G
end
@@ -1023,10 +1037,10 @@ end
describe "with bundled and system gems" do
before :each do
- system_gems "rack-1.0.0"
+ system_gems "myrack-1.0.0"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "activesupport", "2.3.5"
G
@@ -1035,7 +1049,7 @@ end
it "does not pull in system gems" do
run <<-R
begin;
- require 'rack'
+ require 'myrack'
rescue LoadError
puts 'WIN'
end
@@ -1057,13 +1071,13 @@ end
it "raises an exception if gem is used to invoke a system gem not in the bundle" do
run <<-R
begin
- gem 'rack'
+ gem 'myrack'
rescue LoadError => e
puts e.message
end
R
- expect(out).to eq("rack is not part of the bundle. Add it to your Gemfile.")
+ expect(out).to eq("myrack is not part of the bundle. Add it to your Gemfile.")
end
it "sets GEM_HOME appropriately" do
@@ -1075,11 +1089,11 @@ end
describe "with system gems in the bundle" do
before :each do
bundle "config set path.system true"
- system_gems "rack-1.0.0"
+ system_gems "myrack-1.0.0"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", "1.0.0"
+ source "https://gem.repo1"
+ gem "myrack", "1.0.0"
gem "activesupport", "2.3.5"
G
end
@@ -1109,7 +1123,7 @@ end
end
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "bar", :git => "#{lib_path("bar-1.0")}"
G
end
@@ -1143,7 +1157,7 @@ end
bundler_module = class << Bundler; self; end
bundler_module.send(:remove_method, :require)
def Bundler.require(path)
- raise "LOSE"
+ raise StandardError, "didn't use binding from top level"
end
Bundler.load
RUBY
@@ -1156,7 +1170,7 @@ end
describe "when Bundler is bundled" do
it "doesn't blow up" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "bundler", :path => "#{root}"
G
@@ -1169,15 +1183,15 @@ end
def lock_with(bundler_version = nil)
lock = <<~L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
L
if bundler_version
@@ -1191,8 +1205,8 @@ end
bundle "config set --local path.system true"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
end
@@ -1229,20 +1243,20 @@ end
def lock_with(ruby_version = nil)
checksums = checksums_section do |c|
- c.checksum gem_repo1, "rack", "1.0.0"
+ c.checksum gem_repo1, "myrack", "1.0.0"
end
lock = <<~L
GEM
- remote: #{file_uri_for(gem_repo1)}/
+ remote: https://gem.repo1/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
- rack
+ myrack
#{checksums}
L
@@ -1253,7 +1267,7 @@ end
lock += <<~L
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
L
lock
@@ -1262,8 +1276,8 @@ end
before do
install_gemfile <<-G
ruby ">= 0"
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
lockfile lock_with(ruby_version)
end
@@ -1305,19 +1319,19 @@ end
s.files = Dir["lib/**/*.rb"]
s.author = 'no one'
- s.add_runtime_dependency 'digest'
+ s.add_dependency 'digest'
end
G
end
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "bar", :git => "#{lib_path("bar-1.0")}"
G
bundle :install
- ruby <<-RUBY
+ ruby <<-RUBY, artifice: nil
require 'bundler/setup'
puts defined?(::Digest) ? "Digest defined" : "Digest undefined"
require 'digest'
@@ -1326,7 +1340,7 @@ end
end
it "does not load Psych" do
- gemfile "source \"#{file_uri_for(gem_repo1)}\""
+ gemfile "source 'https://gem.repo1'"
ruby <<-RUBY
require 'bundler/setup'
puts defined?(Psych::VERSION) ? Psych::VERSION : "undefined"
@@ -1339,8 +1353,8 @@ end
end
it "does not load openssl" do
- install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
- ruby <<-RUBY
+ install_gemfile "source 'https://gem.repo1'"
+ ruby <<-RUBY, artifice: nil
require "bundler/setup"
puts defined?(OpenSSL) || "undefined"
require "openssl"
@@ -1363,11 +1377,11 @@ end
G
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "test", path: "#{bundled_app("test")}"
G
- ruby <<-RUBY
+ ruby <<-RUBY, artifice: nil
require "bundler/setup"
puts defined?(URI) || "undefined"
require "uri"
@@ -1377,29 +1391,27 @@ end
end
it "activates default gems when they are part of the bundle, but not installed explicitly", :ruby_repo do
- default_json_version = ruby "gem 'json'; require 'json'; puts JSON::VERSION"
+ default_delegate_version = ruby "gem 'delegate'; require 'delegate'; puts Delegator::VERSION"
build_repo2 do
- build_gem "json", default_json_version
+ build_gem "delegate", default_delegate_version
end
- gemfile "source \"#{file_uri_for(gem_repo2)}\"; gem 'json'"
+ gemfile "source \"https://gem.repo2\"; gem 'delegate'"
ruby <<-RUBY
require "bundler/setup"
- require "json"
- puts defined?(::JSON) ? "JSON defined" : "JSON undefined"
+ require "delegate"
+ puts defined?(::Delegator) ? "Delegator defined" : "Delegator undefined"
RUBY
+ expect(out).to eq("Delegator defined")
expect(err).to be_empty
end
describe "default gem activation" do
let(:exemptions) do
exempts = %w[did_you_mean bundler uri pathname]
- exempts << "etc" if Gem.ruby_version < Gem::Version.new("3.2") && Gem.win_platform?
- 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 << "syntax_suggest" # added in Ruby 3.2 as a default gem
@@ -1440,13 +1452,13 @@ end
RUBY
it "activates no gems with -rbundler/setup" do
- install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
- ruby code, env: { "RUBYOPT" => activation_warning_hack_rubyopt + " -rbundler/setup" }
+ install_gemfile "source 'https://gem.repo1'"
+ ruby code, env: { "RUBYOPT" => activation_warning_hack_rubyopt + " -rbundler/setup" }, artifice: nil
expect(out).to eq("{}")
end
it "activates no gems with bundle exec" do
- install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
+ install_gemfile "source 'https://gem.repo1'"
create_file("script.rb", code)
bundle "exec ruby ./script.rb", env: { "RUBYOPT" => activation_warning_hack_rubyopt }
expect(out).to eq("{}")
@@ -1455,10 +1467,10 @@ end
it "activates no gems with bundle exec that is loaded" do
skip "not executable" if Gem.win_platform?
- install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
+ install_gemfile "source 'https://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", env: { "RUBYOPT" => activation_warning_hack_rubyopt }
expect(out).to eq("{}")
end
@@ -1470,7 +1482,7 @@ end
system_gems "net-http-pipeline-1.0.1", gem_repo: gem_repo4
gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "net-http-pipeline", "1.0.1"
G
@@ -1492,11 +1504,11 @@ end
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "#{g}", "999999"
G
- expect(the_bundle).to include_gem("#{g} 999999", env: { "RUBYOPT" => activation_warning_hack_rubyopt })
+ expect(the_bundle).to include_gem("#{g} 999999", env: { "RUBYOPT" => activation_warning_hack_rubyopt }, artifice: nil)
end
it "activates older versions of #{g}", :ruby_repo do
@@ -1507,69 +1519,54 @@ end
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
gem "#{g}", "0.0.0.a"
G
- expect(the_bundle).to include_gem("#{g} 0.0.0.a", env: { "RUBYOPT" => activation_warning_hack_rubyopt })
+ expect(the_bundle).to include_gem("#{g} 0.0.0.a", env: { "RUBYOPT" => activation_warning_hack_rubyopt }, artifice: nil)
end
end
end
end
describe "after setup" do
- it "allows calling #gem on random objects", bundler: "< 3" do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- G
-
- ruby <<-RUBY
- require "bundler/setup"
- Object.new.gem "rack"
- puts Gem.loaded_specs["rack"].full_name
- RUBY
-
- expect(out).to eq("rack-1.0.0")
- end
-
- it "keeps Kernel#gem private", bundler: "3" do
+ it "keeps Kernel#gem private" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
ruby <<-RUBY, raise_on_error: false
require "bundler/setup"
- Object.new.gem "rack"
+ Object.new.gem "myrack"
puts "FAIL"
RUBY
- expect(last_command.stdboth).not_to include "FAIL"
- expect(err).to include "private method `gem'"
+ expect(stdboth).not_to include "FAIL"
+ expect(err).to match(/private method [`']gem'/)
end
it "keeps Kernel#require private" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
+ source "https://gem.repo1"
+ gem "myrack"
G
ruby <<-RUBY, raise_on_error: false
require "bundler/setup"
- Object.new.require "rack"
+ Object.new.require "myrack"
puts "FAIL"
RUBY
- expect(last_command.stdboth).not_to include "FAIL"
+ expect(stdboth).not_to include "FAIL"
expect(err).to match(/private method [`']require'/)
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)}"
+ source "https://gem.repo1"
gem "yard"
- gem "rack", :group => :test
+ gem "myrack", :group => :test
G
ruby <<-RUBY, raise_on_error: false
@@ -1578,7 +1575,7 @@ end
puts Bundler.definition.specs.map(&:name).join(", ")
RUBY
- expect(out).to include("rack, yard")
+ expect(out).to include("myrack, yard")
end
it "does not cause double loads when higher versions of default gems are activated before bundler" do
@@ -1594,7 +1591,7 @@ end
system_gems "json-999.999.999", gem_repo: gem_repo2
- install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
+ install_gemfile "source 'https://gem.repo1'"
ruby <<-RUBY
require "json"
require "bundler/setup"
@@ -1606,7 +1603,7 @@ end
end
it "does not undo the Kernel.require decorations", rubygems: ">= 3.4.6" do
- install_gemfile "source \"#{file_uri_for(gem_repo1)}\""
+ install_gemfile "source 'https://gem.repo1'"
script = bundled_app("bin/script")
create_file(script, <<~RUBY)
module Kernel
@@ -1631,17 +1628,52 @@ end
end
it "performs an automatic bundle install" do
+ build_repo4 do
+ build_gem "myrack", "1.0.0"
+ end
+
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :group => :test
+ source "https://gem.repo1"
+ gem "myrack", :group => :test
G
bundle "config set auto_install 1"
- ruby <<-RUBY
+ ruby <<-RUBY, artifice: "compact_index"
require 'bundler/setup'
RUBY
expect(err).to be_empty
- expect(out).to include("Installing rack 1.0.0")
+ expect(out).to include("Installing myrack 1.0.0")
+ end
+
+ context "in a read-only filesystem" do
+ before do
+ gemfile <<-G
+ source "https://gem.repo4"
+ G
+
+ lockfile <<-L
+ GEM
+ remote: https://gem.repo4/
+
+ PLATFORMS
+ x86_64-darwin-19
+
+ DEPENDENCIES
+
+ BUNDLED WITH
+ #{Bundler::VERSION}
+ L
+ end
+
+ it "should fail loudly if the lockfile platforms don't include the current platform" do
+ simulate_platform "x86_64-linux" do
+ ruby <<-RUBY, raise_on_error: false, env: { "BUNDLER_SPEC_READ_ONLY" => "true", "BUNDLER_FORCE_TTY" => "true" }
+ require "bundler/setup"
+ RUBY
+ end
+
+ expect(err).to include("Your lockfile is missing the current platform, but can't be updated because file system is read-only")
+ end
end
end
diff --git a/spec/bundler/runtime/with_unbundled_env_spec.rb b/spec/bundler/runtime/with_unbundled_env_spec.rb
deleted file mode 100644
index 135c71b0af..0000000000
--- a/spec/bundler/runtime/with_unbundled_env_spec.rb
+++ /dev/null
@@ -1,298 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe "Bundler.with_env helpers" do
- def bundle_exec_ruby(args, options = {})
- build_bundler_context options
- bundle "exec '#{Gem.ruby}' #{args}", options
- end
-
- def build_bundler_context(options = {})
- bundle "config set path vendor/bundle"
- 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
- 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(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
- 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(bundled_app("source.rb").to_s)
- expect(last_command.stdboth).to eq(gem_path)
- end
- end
-
- 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?("#{File::PATH_SEPARATOR}/foo")}"
- if count == 2
- ENV["PATH"] = "#{ENV["PATH"]}#{File::PATH_SEPARATOR}/foo"
- end
- exec(Gem.ruby, __FILE__, (count - 1).to_s)
- RUBY
- path = `getconf PATH`.strip + File::PATH_SEPARATOR + File.dirname(Gem.ruby)
- with_path_as(path) do
- build_bundler_context
- bundle_exec_ruby("#{bundled_app("exe.rb")} 2")
- end
- expect(err).to eq <<-EOS.strip
-2 false
-1 true
-0 true
- EOS
- end
-
- it "removes variables that bundler added", :ruby_repo do
- # 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")')
- 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
- create_file("source.rb", <<-RUBY)
- print #{modified_env}.has_key?('BUNDLE_PATH')
- RUBY
- ENV["BUNDLE_PATH"] = "./foo"
- bundle_exec_ruby bundled_app("source.rb")
- expect(last_command.stdboth).to include "false"
- end
-
- 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"]}"
- bundle_exec_ruby bundled_app("source.rb")
- 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"]}"
- bundle_exec_ruby bundled_app("source.rb")
- expect(last_command.stdboth).not_to include("-rbundler/setup")
- end
-
- it "should restore RUBYLIB", :ruby_repo do
- 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 bundled_app("source.rb")
- expect(last_command.stdboth).to include("/foo-original")
- end
-
- it "should restore the original MANPATH" do
- create_file("source.rb", <<-RUBY)
- print #{modified_env}['MANPATH']
- RUBY
- ENV["MANPATH"] = "/foo"
- ENV["BUNDLER_ORIG_MANPATH"] = "/foo-original"
- bundle_exec_ruby bundled_app("source.rb")
- expect(last_command.stdboth).to include("/foo-original")
- end
- end
-
- describe "Bundler.unbundled_env" do
- let(:modified_env) { "Bundler.unbundled_env" }
-
- it_behaves_like "an unbundling helper"
- end
-
- describe "Bundler.clean_env", bundler: 2 do
- let(:modified_env) { "Bundler.clean_env" }
-
- it_behaves_like "an unbundling helper"
- end
-
- 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 }
- expect(actual).to eq(expected)
- end
-
- it "should restore the environment after execution" do
- Bundler.with_original_env do
- ENV["FOO"] = "hello"
- end
-
- expect(ENV).not_to have_key("FOO")
- end
- end
-
- describe "Bundler.with_clean_env", bundler: 2 do
- it "should set ENV to unbundled_env in the block" do
- expected = Bundler.unbundled_env
-
- actual = Bundler.ui.silence do
- Bundler.with_clean_env { ENV.to_hash }
- end
-
- expect(actual).to eq(expected)
- end
-
- it "should restore the environment after execution" do
- Bundler.ui.silence do
- Bundler.with_clean_env { ENV["FOO"] = "hello" }
- end
-
- expect(ENV).not_to have_key("FOO")
- end
- end
-
- 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 }
- expect(actual).to eq(expected)
- end
-
- it "should restore the environment after execution" do
- Bundler.with_unbundled_env do
- ENV["FOO"] = "hello"
- end
-
- expect(ENV).not_to have_key("FOO")
- end
- end
-
- describe "Bundler.original_system" do
- 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
- run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb"))
- expect($?.exitstatus).to eq(42)
- end
- end
-
- describe "Bundler.clean_system", bundler: 2 do
- 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
- run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb"))
- expect($?.exitstatus).to eq(42)
- end
- end
-
- describe "Bundler.unbundled_system" do
- 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
- run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb"))
- expect($?.exitstatus).to eq(42)
- end
- end
-
- describe "Bundler.original_exec" do
- before do
- create_file("source.rb", <<-'RUBY')
- Process.fork do
- exit Bundler.original_exec(%(test "\$BUNDLE_FOO" = "bar"))
- end
-
- _, status = Process.wait2
-
- exit(status.exitstatus)
- RUBY
- end
-
- it "runs exec inside with_original_env" do
- skip "Fork not implemented" if Gem.win_platform?
-
- run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb"))
- expect($?.exitstatus).to eq(0)
- end
- end
-
- describe "Bundler.clean_exec", bundler: 2 do
- before do
- create_file("source.rb", <<-'RUBY')
- Process.fork do
- exit Bundler.ui.silence { Bundler.clean_exec(%(test "\$BUNDLE_FOO" = "bar")) }
- end
-
- _, status = Process.wait2
-
- exit(status.exitstatus)
- RUBY
- end
-
- it "runs exec inside with_clean_env" do
- skip "Fork not implemented" if Gem.win_platform?
-
- run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb"))
- expect($?.exitstatus).to eq(1)
- end
- end
-
- describe "Bundler.unbundled_exec" do
- before do
- create_file("source.rb", <<-'RUBY')
- Process.fork do
- exit Bundler.unbundled_exec(%(test "\$BUNDLE_FOO" = "bar"))
- end
-
- _, status = Process.wait2
-
- exit(status.exitstatus)
- RUBY
- end
-
- it "runs exec inside with_clean_env" do
- skip "Fork not implemented" if Gem.win_platform?
-
- run_bundler_script({ "BUNDLE_FOO" => "bar" }, bundled_app("source.rb"))
- expect($?.exitstatus).to eq(1)
- end
- end
-end
diff --git a/spec/bundler/spec_helper.rb b/spec/bundler/spec_helper.rb
index 66bdcfa028..a79e33fbb0 100644
--- a/spec/bundler/spec_helper.rb
+++ b/spec/bundler/spec_helper.rb
@@ -9,14 +9,28 @@ if File.expand_path(__FILE__) =~ %r{([^\w/\.:\-])}
abort "The bundler specs cannot be run from a path that contains special characters (particularly #{$1.inspect})"
end
+# Bundler CLI will have different help text depending on whether any of these
+# variables is set, since the `-e` flag `bundle gem` with require an explicit
+# value if they are not set, but will use their value by default if set. So make
+# sure they are `nil` before loading bundler to get a consistent help text,
+# since some tests rely on that.
+ENV["EDITOR"] = nil
+ENV["VISUAL"] = nil
+ENV["BUNDLER_EDITOR"] = nil
require "bundler"
+
+# If we use shared GEM_HOME and install multiple versions, it may cause
+# unexpected test failures.
+gem "diff-lcs"
+
require "rspec/core"
require "rspec/expectations"
require "rspec/mocks"
require "rspec/support/differ"
+gem "rubygems-generate_index"
+require "rubygems/indexer"
require_relative "support/builders"
-require_relative "support/build_metadata"
require_relative "support/checksums"
require_relative "support/filters"
require_relative "support/helpers"
@@ -24,6 +38,7 @@ require_relative "support/indexes"
require_relative "support/matchers"
require_relative "support/permissions"
require_relative "support/platforms"
+require_relative "support/windows_tag_group"
$debug = false
@@ -42,6 +57,7 @@ RSpec.configure do |config|
config.include Spec::Path
config.include Spec::Platforms
config.include Spec::Permissions
+ config.include Spec::WindowsTagGroup
# Enable flags like --only-failures and --next-failure
config.example_status_persistence_file_path = ".rspec_status"
@@ -76,6 +92,10 @@ RSpec.configure do |config|
require_relative "support/rubygems_ext"
Spec::Rubygems.test_setup
+
+ # Simulate bundler has not yet been loaded
+ ENV.replace(ENV.to_hash.delete_if {|k, _v| k.start_with?(Bundler::EnvironmentPreserver::BUNDLER_PREFIX) })
+
ENV["BUNDLER_SPEC_RUN"] = "true"
ENV["BUNDLE_USER_CONFIG"] = ENV["BUNDLE_USER_CACHE"] = ENV["BUNDLE_USER_PLUGIN"] = nil
ENV["BUNDLE_APP_CONFIG"] = nil
@@ -87,20 +107,15 @@ RSpec.configure do |config|
# Don't wrap output in tests
ENV["THOR_COLUMNS"] = "10000"
- extend(Spec::Helpers)
- system_gems :bundler, path: pristine_system_gem_path
- end
-
- config.before :all do
- check_test_gems!
+ extend(Spec::Builders)
build_repo1
- reset_paths!
+ reset!
end
config.around :each do |example|
- FileUtils.cp_r pristine_system_gem_path, system_gem_path
+ default_system_gems
with_gem_path_as(system_gem_path) do
Bundler.ui.silence { example.run }
@@ -117,7 +132,18 @@ RSpec.configure do |config|
reset!
end
- config.after :suite do
- FileUtils.rm_rf Spec::Path.pristine_system_gem_path
+ Spec::WindowsTagGroup::EXAMPLE_MAPPINGS.each do |tag, file_paths|
+ file_pattern = Regexp.union(file_paths.map {|path| Regexp.new(Regexp.escape(path) + "$") })
+
+ config.define_derived_metadata(file_path: file_pattern) do |metadata|
+ metadata[tag] = true
+ end
end
+
+ config.before(:context) do |example|
+ metadata = example.class.metadata
+ if metadata[:type] != :aruba && metadata.keys.none? {|k| Spec::WindowsTagGroup::EXAMPLE_MAPPINGS.keys.include?(k) }
+ warn "#{metadata[:file_path]} is not assigned to any Windows runner group. see spec/support/windows_tag_group.rb for details."
+ end
+ end unless Spec::Path.ruby_core?
end
diff --git a/spec/bundler/support/artifice/compact_index_creds_diff_host.rb b/spec/bundler/support/artifice/compact_index_creds_diff_host.rb
index 401e8a98d8..282e9c8961 100644
--- a/spec/bundler/support/artifice/compact_index_creds_diff_host.rb
+++ b/spec/bundler/support/artifice/compact_index_creds_diff_host.rb
@@ -24,7 +24,7 @@ class CompactIndexCredsDiffHost < CompactIndexAPI
end
get "/gems/:id" do
- redirect "http://diffhost.com/no/creds/#{params[:id]}"
+ redirect "http://diffhost.test/no/creds/#{params[:id]}"
end
get "/no/creds/:id" do
diff --git a/spec/bundler/support/artifice/compact_index_etag_match.rb b/spec/bundler/support/artifice/compact_index_etag_match.rb
index 08d7b5ec53..6c62166051 100644
--- a/spec/bundler/support/artifice/compact_index_etag_match.rb
+++ b/spec/bundler/support/artifice/compact_index_etag_match.rb
@@ -4,7 +4,7 @@ require_relative "helpers/compact_index"
class CompactIndexEtagMatch < CompactIndexAPI
get "/versions" do
- raise "ETag header should be present" unless env["HTTP_IF_NONE_MATCH"]
+ raise ArgumentError, "ETag header should be present" unless env["HTTP_IF_NONE_MATCH"]
headers "ETag" => env["HTTP_IF_NONE_MATCH"]
status 304
body ""
diff --git a/spec/bundler/support/artifice/compact_index_mirror_down.rb b/spec/bundler/support/artifice/compact_index_mirror_down.rb
new file mode 100644
index 0000000000..88983c715d
--- /dev/null
+++ b/spec/bundler/support/artifice/compact_index_mirror_down.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require_relative "helpers/compact_index"
+require_relative "helpers/artifice"
+require_relative "helpers/rack_request"
+
+module Artifice
+ module Net
+ class HTTPMirrorDown < HTTP
+ def connect
+ raise SocketError if address == "gem.mirror"
+
+ super
+ end
+ end
+
+ HTTP.endpoint = CompactIndexAPI
+ end
+
+ replace_net_http(Net::HTTPMirrorDown)
+end
diff --git a/spec/bundler/support/artifice/compact_index_no_checksums.rb b/spec/bundler/support/artifice/compact_index_no_checksums.rb
new file mode 100644
index 0000000000..ecb7fc7d7c
--- /dev/null
+++ b/spec/bundler/support/artifice/compact_index_no_checksums.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require_relative "helpers/compact_index"
+
+class CompactIndexNoChecksums < CompactIndexAPI
+ get "/info/:name" do
+ etag_response do
+ gem = gems.find {|g| g.name == params[:name] }
+ gem.versions.map(&:number).join("\n")
+ end
+ end
+end
+
+require_relative "helpers/artifice"
+
+Artifice.activate_with(CompactIndexNoChecksums)
diff --git a/spec/bundler/support/artifice/endpoint_500.rb b/spec/bundler/support/artifice/endpoint_500.rb
index b1ed1964c8..9dd373bbf6 100644
--- a/spec/bundler/support/artifice/endpoint_500.rb
+++ b/spec/bundler/support/artifice/endpoint_500.rb
@@ -2,7 +2,7 @@
require_relative "../path"
-$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{mustermann,rack,tilt,sinatra,ruby2_keywords,base64}-*/lib")].map(&:to_s))
+$LOAD_PATH.unshift(*Spec::Path.sinatra_dependency_paths)
require "sinatra/base"
diff --git a/spec/bundler/support/artifice/endpoint_creds_diff_host.rb b/spec/bundler/support/artifice/endpoint_creds_diff_host.rb
index ce30de0a68..9cbb4de61a 100644
--- a/spec/bundler/support/artifice/endpoint_creds_diff_host.rb
+++ b/spec/bundler/support/artifice/endpoint_creds_diff_host.rb
@@ -24,7 +24,7 @@ class EndpointCredsDiffHost < Endpoint
end
get "/gems/:id" do
- redirect "http://diffhost.com/no/creds/#{params[:id]}"
+ redirect "http://diffhost.test/no/creds/#{params[:id]}"
end
get "/no/creds/:id" do
diff --git a/spec/bundler/support/artifice/fail.rb b/spec/bundler/support/artifice/fail.rb
index 8822e5b8e2..5ddbc4e590 100644
--- a/spec/bundler/support/artifice/fail.rb
+++ b/spec/bundler/support/artifice/fail.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require "bundler/vendored_net_http"
+require_relative "../vendored_net_http"
class Fail < Gem::Net::HTTP
# Gem::Net::HTTP uses a @newimpl instance variable to decide whether
diff --git a/spec/bundler/support/artifice/helpers/compact_index.rb b/spec/bundler/support/artifice/helpers/compact_index.rb
index a803a2d30a..e61fe921ec 100644
--- a/spec/bundler/support/artifice/helpers/compact_index.rb
+++ b/spec/bundler/support/artifice/helpers/compact_index.rb
@@ -2,7 +2,7 @@
require_relative "endpoint"
-$LOAD_PATH.unshift Dir[Spec::Path.base_system_gem_path.join("gems/compact_index*/lib")].first.to_s
+$LOAD_PATH.unshift Dir[Spec::Path.scoped_base_system_gem_path.join("gems/compact_index*/lib")].first.to_s
require "compact_index"
require "digest"
@@ -40,7 +40,7 @@ class CompactIndexAPI < Endpoint
end
def requested_range_for(response_body)
- ranges = Rack::Utils.byte_ranges(env, response_body.bytesize)
+ ranges = Rack::Utils.get_byte_ranges(env["HTTP_RANGE"], response_body.bytesize)
if ranges
status 206
@@ -67,11 +67,14 @@ class CompactIndexAPI < Endpoint
@gems ||= {}
@gems[gem_repo] ||= begin
specs = Bundler::Deprecate.skip_during do
- %w[specs.4.8 prerelease_specs.4.8].map do |filename|
- Marshal.load(File.open(gem_repo.join(filename)).read).map do |name, version, platform|
+ %w[specs.4.8 prerelease_specs.4.8].flat_map do |filename|
+ spec_index = gem_repo.join(filename)
+ next [] unless File.exist?(spec_index)
+
+ Marshal.load(File.binread(spec_index)).map do |name, version, platform|
load_spec(name, version, platform, gem_repo)
end
- end.flatten
+ end
end
specs.group_by(&:name).map do |name, versions|
diff --git a/spec/bundler/support/artifice/helpers/endpoint.rb b/spec/bundler/support/artifice/helpers/endpoint.rb
index 83ba1be0fc..9590611dfe 100644
--- a/spec/bundler/support/artifice/helpers/endpoint.rb
+++ b/spec/bundler/support/artifice/helpers/endpoint.rb
@@ -2,7 +2,7 @@
require_relative "../../path"
-$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{mustermann,rack,tilt,sinatra,ruby2_keywords,base64}-*/lib")].map(&:to_s))
+$LOAD_PATH.unshift(*Spec::Path.sinatra_dependency_paths)
require "sinatra/base"
@@ -27,6 +27,7 @@ class Endpoint < Sinatra::Base
set :raise_errors, true
set :show_exceptions, false
+ set :host_authorization, permitted_hosts: [".example.org", ".local", ".mirror", ".repo", ".repo1", ".repo2", ".repo3", ".repo4", ".rubygems.org", ".security", ".source", ".test", "127.0.0.1"]
def call!(*)
super.tap do
@@ -62,10 +63,10 @@ class Endpoint < Sinatra::Base
return [] if gem_names.nil? || gem_names.empty?
all_specs = %w[specs.4.8 prerelease_specs.4.8].map do |filename|
- Marshal.load(File.open(gem_repo.join(filename)).read)
+ Marshal.load(File.binread(gem_repo.join(filename)))
end.inject(:+)
- all_specs.map do |name, version, platform|
+ all_specs.filter_map do |name, version, platform|
spec = load_spec(name, version, platform, gem_repo)
next unless gem_names.include?(spec.name)
{
@@ -76,7 +77,7 @@ class Endpoint < Sinatra::Base
[dep.name, dep.requirement.requirements.map {|a| a.join(" ") }.join(", ")]
end,
}
- end.compact
+ end
end
def load_spec(name, version, platform, gem_repo)
diff --git a/spec/bundler/support/artifice/helpers/rack_request.rb b/spec/bundler/support/artifice/helpers/rack_request.rb
index f419bacb8c..05ff034463 100644
--- a/spec/bundler/support/artifice/helpers/rack_request.rb
+++ b/spec/bundler/support/artifice/helpers/rack_request.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require "rack/test"
-require "bundler/vendored_net_http"
+require_relative "../../vendored_net_http"
module Artifice
module Net
diff --git a/spec/bundler/support/artifice/vcr.rb b/spec/bundler/support/artifice/vcr.rb
index 7b9a8bdeaf..2386a4c6b7 100644
--- a/spec/bundler/support/artifice/vcr.rb
+++ b/spec/bundler/support/artifice/vcr.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require "bundler/vendored_net_http"
+require_relative "../vendored_net_http"
require_relative "../path"
CASSETTE_PATH = "#{Spec::Path.spec_dir}/support/artifice/vcr_cassettes".freeze
diff --git a/spec/bundler/support/artifice/windows.rb b/spec/bundler/support/artifice/windows.rb
index fea991c071..3056540beb 100644
--- a/spec/bundler/support/artifice/windows.rb
+++ b/spec/bundler/support/artifice/windows.rb
@@ -2,7 +2,7 @@
require_relative "../path"
-$LOAD_PATH.unshift(*Dir[Spec::Path.base_system_gem_path.join("gems/{mustermann,rack,tilt,sinatra,ruby2_keywords,base64}-*/lib")].map(&:to_s))
+$LOAD_PATH.unshift(*Spec::Path.sinatra_dependency_paths)
require "sinatra/base"
diff --git a/spec/bundler/support/build_metadata.rb b/spec/bundler/support/build_metadata.rb
index 5898e7f3bd..2eade4137b 100644
--- a/spec/bundler/support/build_metadata.rb
+++ b/spec/bundler/support/build_metadata.rb
@@ -8,11 +8,10 @@ module Spec
include Spec::Path
include Spec::Helpers
- def write_build_metadata(dir: source_root)
+ def write_build_metadata(dir: source_root, version: Bundler::VERSION)
build_metadata = {
git_commit_sha: git_commit_sha,
- built_at: loaded_gemspec.date.utc.strftime("%Y-%m-%d"),
- release: true,
+ built_at: release_date_for(version, dir: dir),
}
replace_build_metadata(build_metadata, dir: dir)
@@ -20,7 +19,7 @@ module Spec
def reset_build_metadata(dir: source_root)
build_metadata = {
- release: false,
+ built_at: nil,
}
replace_build_metadata(build_metadata, dir: dir)
@@ -41,7 +40,12 @@ module Spec
end
def git_commit_sha
- ruby_core_tarball? ? "unknown" : sys_exec("git rev-parse --short HEAD", dir: source_root).strip
+ ruby_core_tarball? ? "unknown" : git("rev-parse --short HEAD", source_root).strip
+ end
+
+ def release_date_for(version, dir:)
+ changelog = File.expand_path("CHANGELOG.md", dir)
+ File.readlines(changelog)[2].scan(/^## #{Regexp.escape(version)} \((.*)\)/).first&.first if File.exist?(changelog)
end
extend self
diff --git a/spec/bundler/support/builders.rb b/spec/bundler/support/builders.rb
index 8f646b9358..6087ea8cc8 100644
--- a/spec/bundler/support/builders.rb
+++ b/spec/bundler/support/builders.rb
@@ -2,9 +2,18 @@
require "bundler/shared_helpers"
require "shellwords"
+require "fileutils"
+require "rubygems/package"
+
+require_relative "build_metadata"
module Spec
module Builders
+ def self.extended(mod)
+ mod.extend Path
+ mod.extend Helpers
+ end
+
def self.constantize(name)
name.delete("-").upcase
end
@@ -17,13 +26,7 @@ module Spec
Gem::Platform.new(platform)
end
- def rake_version
- "13.2.1"
- 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/"
@@ -32,23 +35,23 @@ module Spec
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"
+ build_gem "myrack", %w[0.9.1 1.0.0] do |s|
+ s.executables = "myrackup"
+ s.post_install_message = "Myrack's post install message"
end
build_gem "thin" do |s|
- s.add_dependency "rack"
+ s.add_dependency "myrack"
s.post_install_message = "Thin's post install message"
end
- build_gem "rack-obama" do |s|
- s.add_dependency "rack"
- s.post_install_message = "Rack-obama's post install message"
+ build_gem "myrack-obama" do |s|
+ s.add_dependency "myrack"
+ s.post_install_message = "Myrack-obama's post install message"
end
- build_gem "rack_middleware", "1.0" do |s|
- s.add_dependency "rack", "0.9.1"
+ build_gem "myrack_middleware", "1.0" do |s|
+ s.add_dependency "myrack", "0.9.1"
end
build_gem "rails", "2.3.2" do |s|
@@ -81,80 +84,62 @@ module Spec
s.write "lib/spec.rb", "SPEC = '1.2.7'"
end
- build_gem "rack-test", no_default: true do |s|
- s.write "lib/rack/test.rb", "RACK_TEST = '1.0'"
- end
-
- build_gem "platform_specific" do |s|
- s.platform = Gem::Platform.local
- s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 #{Gem::Platform.local}'"
+ build_gem "myrack-test", no_default: true do |s|
+ s.write "lib/myrack/test.rb", "MYRACK_TEST = '1.0'"
end
build_gem "platform_specific" do |s|
s.platform = "java"
- s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 JAVA'"
end
build_gem "platform_specific" do |s|
s.platform = "ruby"
- s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 RUBY'"
end
build_gem "platform_specific" do |s|
s.platform = "x86-mswin32"
- s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0 x86-mswin32'"
end
build_gem "platform_specific" do |s|
s.platform = "x64-mswin64"
- s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0 x64-mswin64'"
end
build_gem "platform_specific" do |s|
s.platform = "x86-mingw32"
- s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0 x86-mingw32'"
end
build_gem "platform_specific" do |s|
- s.platform = "x64-mingw32"
- s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0 x64-mingw32'"
+ s.platform = "x64-mingw-ucrt"
end
build_gem "platform_specific" do |s|
- s.platform = "x64-mingw-ucrt"
- s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0 x64-mingw-ucrt'"
+ s.platform = "aarch64-mingw-ucrt"
end
build_gem "platform_specific" do |s|
s.platform = "x86-darwin-100"
- s.write "lib/platform_specific.rb", "PLATFORM_SPECIFIC = '1.0.0 x86-darwin-100'"
end
build_gem "only_java", "1.0" do |s|
s.platform = "java"
- s.write "lib/only_java.rb", "ONLY_JAVA = '1.0.0 JAVA'"
end
build_gem "only_java", "1.1" do |s|
s.platform = "java"
- s.write "lib/only_java.rb", "ONLY_JAVA = '1.1.0 JAVA'"
end
build_gem "nokogiri", "1.4.2"
build_gem "nokogiri", "1.4.2" do |s|
s.platform = "java"
- s.write "lib/nokogiri.rb", "NOKOGIRI = '1.4.2 JAVA'"
s.add_dependency "weakling", ">= 0.0.3"
end
build_gem "laduradura", "5.15.2"
build_gem "laduradura", "5.15.2" do |s|
s.platform = "java"
- s.write "lib/laduradura.rb", "LADURADURA = '5.15.2 JAVA'"
end
build_gem "laduradura", "5.15.3" do |s|
s.platform = "java"
- s.write "lib/laduradura.rb", "LADURADURA = '5.15.2 JAVA'"
end
build_gem "weakling", "0.0.3"
@@ -168,7 +153,7 @@ module Spec
build_gem "bundler", "0.9" do |s|
s.executables = "bundle"
- s.write "bin/bundle", "puts 'FAIL'"
+ s.write "bin/bundle", "#!/usr/bin/env ruby\nputs 'FAIL'"
end
# The bundler 0.8 gem has a rubygems plugin that always loads :(
@@ -196,29 +181,44 @@ module Spec
end
def build_repo2(**kwargs, &blk)
- FileUtils.rm_rf gem_repo2
- FileUtils.cp_r gem_repo1, gem_repo2
+ FileUtils.cp_r gem_repo1, gem_repo2, remove_destination: true
update_repo2(**kwargs, &blk) if block_given?
end
# A repo that has no pre-installed gems included. (The caller completely
# determines the contents with the block.)
- def build_repo4(**kwargs, &blk)
- FileUtils.rm_rf gem_repo4
- build_repo(gem_repo4, **kwargs, &blk)
+ #
+ # If the repo already exists, `#update_repo` will be called.
+ def build_repo3(**kwargs, &blk)
+ if File.exist?(gem_repo3)
+ update_repo(gem_repo3, &blk)
+ else
+ build_repo gem_repo3, **kwargs, &blk
+ end
end
- def update_repo4(&blk)
- update_repo(gem_repo4, &blk)
+ # Like build_repo3, this is a repo that has no pre-installed gems included.
+ #
+ # If the repo already exists, `#udpate_repo` will be called
+ def build_repo4(**kwargs, &blk)
+ if File.exist?(gem_repo4)
+ update_repo gem_repo4, &blk
+ else
+ build_repo gem_repo4, **kwargs, &blk
+ end
end
def update_repo2(**kwargs, &blk)
update_repo(gem_repo2, **kwargs, &blk)
end
+ def update_repo3(&blk)
+ update_repo(gem_repo3, &blk)
+ end
+
def build_security_repo
build_repo security_repo do
- build_gem "rack"
+ build_gem "myrack"
build_gem "signed_gem" do |s|
cert = "signing-cert.pem"
@@ -231,6 +231,41 @@ module Spec
end
end
+ # A minimal fake irb console
+ def build_dummy_irb(version = "9.9.9")
+ build_gem "irb", version do |s|
+ s.write "lib/irb.rb", <<-RUBY
+ class IRB
+ class << self
+ def toplevel_binding
+ unless defined?(@toplevel_binding) && @toplevel_binding
+ TOPLEVEL_BINDING.eval %{
+ def self.__irb__; binding; end
+ IRB.instance_variable_set(:@toplevel_binding, __irb__)
+ class << self; undef __irb__; end
+ }
+ end
+ @toplevel_binding.eval('private')
+ @toplevel_binding
+ end
+
+ def __irb__
+ 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 __irb__
+ end
+ end
+ RUBY
+ end
+ end
+
def build_repo(path, **kwargs, &blk)
return if File.directory?(path)
@@ -239,36 +274,17 @@ module Spec
update_repo(path,**kwargs, &blk)
end
- def check_test_gems!
- rake_path = Dir["#{Path.base_system_gems}/**/rake*.gem"].first
-
- if rake_path.nil?
- 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.nil?
- abort "Your test gems are missing! Run `rm -rf #{tmp}` and try again."
- end
- end
-
def update_repo(path, build_compact_index: true)
- if path == gem_repo1 && caller.first.split(" ").last == "`build_repo`"
+ exempted_caller = Gem.ruby_version >= Gem::Version.new("3.4.0.dev") && RUBY_ENGINE != "jruby" ? "#{Module.nesting.first}#build_repo" : "build_repo"
+ if path == gem_repo1 && caller_locations(1, 1).first.label != exempted_caller
raise "Updating gem_repo1 is unsupported -- use gem_repo2 instead"
end
return unless block_given?
@_build_path = "#{path}/gems"
@_build_repo = File.basename(path)
yield
- with_gem_path_as Path.base_system_gem_path do
- Dir[Spec::Path.base_system_gem_path.join("gems/rubygems-generate_index*/lib")].first ||
- raise("Could not find rubygems-generate_index lib directory in #{Spec::Path.base_system_gem_path}")
-
- command = "generate_index"
- command += " --no-compact" if !build_compact_index && gem_command(command + " --help").include?("--[no-]compact")
- gem_command command, dir: path
- end
+ options = { build_compact: build_compact_index }
+ Gem::Indexer.new(path, options).generate_index
ensure
@_build_path = nil
@_build_repo = nil
@@ -407,18 +423,23 @@ module Spec
end
class BundlerBuilder
- attr_writer :required_ruby_version
-
def initialize(context, name, version)
- raise "can only build bundler" unless name == "bundler"
-
@context = context
- @version = version || Bundler::VERSION
+ @spec = Spec::Path.loaded_gemspec.dup
+ @spec.version = version || Bundler::VERSION
+ end
+
+ def required_ruby_version
+ @spec.required_ruby_version
+ end
+
+ def required_ruby_version=(x)
+ @spec.required_ruby_version = x
end
def _build(options = {})
- full_name = "bundler-#{@version}"
- build_path = @context.tmp + full_name
+ full_name = "bundler-#{@spec.version}"
+ build_path = (options[:build_path] || @context.tmp) + full_name
bundler_path = build_path + "#{full_name}.gem"
FileUtils.mkdir_p build_path
@@ -429,15 +450,19 @@ module Spec
target_shipped_file = build_path + target_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
+ FileUtils.cp File.expand_path(shipped_file, @context.source_root), target_shipped_file, preserve: true
end
- @context.replace_version_file(@version, dir: build_path)
- @context.replace_required_ruby_version(@required_ruby_version, dir: build_path) if @required_ruby_version
+ @context.replace_version_file(@spec.version, dir: build_path)
+ @context.replace_changelog(@spec.version, dir: build_path) if options[:released]
- Spec::BuildMetadata.write_build_metadata(dir: build_path)
+ Spec::BuildMetadata.write_build_metadata(dir: build_path, version: @spec.version.to_s)
- @context.gem_command "build #{@context.relative_gemspec}", dir: build_path
+ Dir.chdir build_path do
+ Gem::DefaultUserInteraction.use_ui(Gem::SilentUI.new) do
+ Gem::Package.build(@spec)
+ end
+ end
if block_given?
yield(bundler_path)
@@ -445,7 +470,7 @@ module Spec
FileUtils.mv bundler_path, options[:path]
end
ensure
- build_path.rmtree
+ FileUtils.rm_rf build_path
end
end
@@ -462,6 +487,7 @@ module Spec
s.email = "foo@bar.baz"
s.homepage = "http://example.com"
s.license = "MIT"
+ s.required_ruby_version = ">= 3.0"
end
@files = {}
end
@@ -478,18 +504,13 @@ module Spec
@spec.executables = Array(val)
@spec.executables.each do |file|
executable = "#{@spec.bindir}/#{file}"
- shebang = if Bundler.current_ruby.jruby?
- "#!/usr/bin/env jruby\n"
- else
- "#!/usr/bin/env ruby\n"
- end
+ shebang = "#!/usr/bin/env ruby\n"
@spec.files << executable
write executable, "#{shebang}require_relative '../lib/#{@name}' ; puts #{Builders.constantize(@name)}"
end
end
def add_c_extension
- require_paths << "ext"
extensions << "ext/extconf.rb"
write "ext/extconf.rb", <<-RUBY
require "mkmf"
@@ -507,7 +528,7 @@ module Spec
write "ext/#{name}.c", <<-C
#include "ruby.h"
- void Init_#{name}_c() {
+ void Init_#{name}_c(void) {
rb_define_module("#{Builders.constantize(name)}_IN_C");
}
C
@@ -536,18 +557,16 @@ module Spec
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)
+ full_path = Pathname.new(path).join(file)
+ FileUtils.mkdir_p(full_path.dirname)
+ File.open(full_path, "w") {|f| f.puts source }
+ FileUtils.chmod("+x", full_path) if @spec.executables.map {|exe| "#{@spec.bindir}/#{exe}" }.include?(file)
end
path
end
@@ -640,14 +659,14 @@ module Spec
destination = opts[:path] || _default_path
FileUtils.mkdir_p(lib_path.join(destination))
- if opts[:gemspec] == :yaml || opts[:gemspec] == false
+ if [:yaml, false].include?(opts[:gemspec])
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
+ Dir.chdir(lib_path) { Gem::Package.build(@spec) }
end
gem_path = File.expand_path("#{@spec.full_name}.gem", lib_path)
diff --git a/spec/bundler/support/bundle b/spec/bundler/support/bundle
new file mode 100755
index 0000000000..8f8b535295
--- /dev/null
+++ b/spec/bundler/support/bundle
@@ -0,0 +1,6 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+require_relative "../bundler/support/activate"
+
+load File.expand_path("bundle", Spec::Path.exedir)
diff --git a/spec/bundler/support/bundle.rb b/spec/bundler/support/bundle.rb
index 5d6d658040..aa7b121706 100644
--- a/spec/bundler/support/bundle.rb
+++ b/spec/bundler/support/bundle.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
-require_relative "activate"
+require_relative "path"
-load File.expand_path("bundle", Spec::Path.bindir)
+warn "#{__FILE__} is deprecated. Please use #{Spec::Path.dev_binstub} instead"
+
+load Spec::Path.dev_binstub
diff --git a/spec/bundler/support/checksums.rb b/spec/bundler/support/checksums.rb
index f758559b3b..cf8ea417d6 100644
--- a/spec/bundler/support/checksums.rb
+++ b/spec/bundler/support/checksums.rb
@@ -54,11 +54,11 @@ module Spec
ChecksumsBuilder.new(enabled, &block)
end
- def checksums_section_when_existing(&block)
+ def checksums_section_when_enabled(target_lockfile = nil, &block)
begin
- enabled = lockfile.match?(/^CHECKSUMS$/)
+ enabled = (target_lockfile || lockfile).match?(/^CHECKSUMS$/)
rescue Errno::ENOENT
- enabled = false
+ enabled = true
end
checksums_section(enabled, &block)
end
@@ -110,5 +110,17 @@ module Spec
_checksums, tail = remaining.split("\n\n", 2)
head.concat(tail)
end
+
+ def checksum_from_package(gem_file, name, version)
+ name_tuple = Gem::NameTuple.new(name, version)
+
+ checksum = nil
+
+ File.open(gem_file, "rb") do |f|
+ checksum = Bundler::Checksum.from_gem(f, gemfile)
+ end
+
+ "#{name_tuple.lock_name} #{checksum.to_lock}"
+ end
end
end
diff --git a/spec/bundler/support/command_execution.rb b/spec/bundler/support/command_execution.rb
index 02726744d3..979a46549a 100644
--- a/spec/bundler/support/command_execution.rb
+++ b/spec/bundler/support/command_execution.rb
@@ -2,9 +2,8 @@
module Spec
class CommandExecution
- def initialize(command, working_directory:, timeout:)
+ def initialize(command, timeout:)
@command = command
- @working_directory = working_directory
@timeout = timeout
@original_stdout = String.new
@original_stderr = String.new
diff --git a/spec/bundler/support/env.rb b/spec/bundler/support/env.rb
new file mode 100644
index 0000000000..0899bd82a3
--- /dev/null
+++ b/spec/bundler/support/env.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Spec
+ module Env
+ def ruby_core?
+ File.exist?(File.expand_path("../../../lib/bundler/bundler.gemspec", __dir__))
+ end
+
+ def rubylib
+ ENV["RUBYLIB"].to_s.split(File::PATH_SEPARATOR)
+ end
+ end
+end
diff --git a/spec/bundler/support/filters.rb b/spec/bundler/support/filters.rb
index 8e164af756..6e94b10e32 100644
--- a/spec/bundler/support/filters.rb
+++ b/spec/bundler/support/filters.rb
@@ -1,11 +1,11 @@
# frozen_string_literal: true
class RequirementChecker < Proc
- def self.against(present)
- provided = Gem::Version.new(present)
-
+ def self.against(provided)
new do |required|
- !Gem::Requirement.new(required).satisfied_by?(provided)
+ requirement = Gem::Requirement.new(required)
+
+ !requirement.satisfied_by?(provided)
end.tap do |checker|
checker.provided = provided
end
@@ -14,18 +14,14 @@ class RequirementChecker < Proc
attr_accessor :provided
def inspect
- "\"!= #{provided}\""
+ "\"#{provided}\""
end
end
RSpec.configure do |config|
config.filter_run_excluding realworld: true
- git_version = Bundler::Source::Git::GitProxy.new(nil, nil).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 rubygems: RequirementChecker.against(Gem.rubygems_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?
@@ -35,4 +31,8 @@ RSpec.configure do |config|
config.filter_run_excluding man: Gem.win_platform?
config.filter_run_when_matching :focus unless ENV["CI"]
+
+ config.before(:each, :bundler) do |example|
+ bundle "config simulate_version #{example.metadata[:bundler]}"
+ end
end
diff --git a/spec/bundler/support/hax.rb b/spec/bundler/support/hax.rb
index c7fe3637cc..46718f5fa4 100644
--- a/spec/bundler/support/hax.rb
+++ b/spec/bundler/support/hax.rb
@@ -19,35 +19,56 @@ module Gem
@default_specifications_dir = nil
end
- if ENV["BUNDLER_SPEC_WINDOWS"]
- @@win_platform = true # rubocop:disable Style/ClassVars
- end
+ spec_platform = ENV["BUNDLER_SPEC_PLATFORM"]
+ if spec_platform
+ if /mingw|mswin/.match?(spec_platform)
+ @@win_platform = nil # rubocop:disable Style/ClassVars
+ RbConfig::CONFIG["host_os"] = spec_platform.gsub(/^[^-]+-/, "").tr("-", "_")
+ end
- if ENV["BUNDLER_SPEC_PLATFORM"]
- previous_platforms = @platforms
- previous_local = Platform.local
+ RbConfig::CONFIG["arch"] = spec_platform
class Platform
- @local = new(ENV["BUNDLER_SPEC_PLATFORM"])
+ @local = nil
end
- @platforms = previous_platforms.map {|platform| platform == previous_local ? Platform.local : platform }
+ @platforms = []
end
if ENV["BUNDLER_SPEC_GEM_SOURCES"]
self.sources = [ENV["BUNDLER_SPEC_GEM_SOURCES"]]
end
- if ENV["BUNDLER_IGNORE_DEFAULT_GEM"]
- module RemoveDefaultBundlerStub
- def default_stubs(pattern = "*")
- super.delete_if {|stub| stub.name == "bundler" }
+ if ENV["BUNDLER_SPEC_READ_ONLY"]
+ module ReadOnly
+ def open(file, mode)
+ if file != IO::NULL && mode == "wb"
+ raise Errno::EROFS
+ else
+ super
+ end
end
end
- class Specification
- class << self
- prepend RemoveDefaultBundlerStub
+ File.singleton_class.prepend ReadOnly
+ end
+
+ if ENV["BUNDLER_SPEC_FAKE_RESOLVE"]
+ module FakeResolv
+ def getaddrinfo(host, port)
+ if host == ENV["BUNDLER_SPEC_FAKE_RESOLVE"]
+ [["AF_INET", port, "127.0.0.1", "127.0.0.1", 2, 2, 17]]
+ else
+ super
+ end
end
end
+
+ Socket.singleton_class.prepend FakeResolv
end
end
+
+# mise installed rubygems_plugin.rb to system wide `site_ruby` directory.
+# This empty module avoid to call `mise` command.
+module ReshimInstaller
+ def self.reshim; end
+end
diff --git a/spec/bundler/support/helpers.rb b/spec/bundler/support/helpers.rb
index 049148fab0..52e6ff5d9a 100644
--- a/spec/bundler/support/helpers.rb
+++ b/spec/bundler/support/helpers.rb
@@ -1,48 +1,35 @@
# frozen_string_literal: true
-require_relative "command_execution"
require_relative "the_bundle"
require_relative "path"
+require_relative "options"
+require_relative "subprocess"
module Spec
module Helpers
include Spec::Path
+ include Spec::Options
+ include Spec::Subprocess
- class TimeoutExceeded < StandardError; end
+ def self.extended(mod)
+ mod.extend Spec::Path
+ mod.extend Spec::Options
+ mod.extend Spec::Subprocess
+ end
def reset!
Dir.glob("#{tmp}/{gems/*,*}", File::FNM_DOTMATCH).each do |dir|
next if %w[base base_system remote1 rubocop standard gems rubygems . ..].include?(File.basename(dir))
- FileUtils.rm_rf(dir)
+ FileUtils.rm_r(dir)
end
FileUtils.mkdir_p(home)
FileUtils.mkdir_p(tmpdir)
- reset_paths!
- 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")
- end
-
- def out
- last_command.stdout
- end
-
- def err
- last_command.stderr
+ def the_bundle
+ TheBundle.new
end
MAJOR_DEPRECATION = /^\[DEPRECATED\]\s*/
@@ -52,11 +39,7 @@ module Spec
end
def deprecations
- err.split("\n").select {|l| l =~ MAJOR_DEPRECATION }.join("\n").split(MAJOR_DEPRECATION)
- end
-
- def exitstatus
- last_command.exitstatus
+ err.split("\n").filter_map {|l| l.sub(MAJOR_DEPRECATION, "") if l.match?(MAJOR_DEPRECATION) }
end
def run(cmd, *args)
@@ -71,7 +54,7 @@ module Spec
begin
#{ruby}
rescue LoadError => e
- warn "ZOMG LOAD ERROR" if e.message.include?("-- #{name}")
+ warn e.message if e.message.include?("-- #{name}")
end
RUBY
opts = args.last.is_a?(Hash) ? args.pop : {}
@@ -79,6 +62,10 @@ module Spec
run(cmd, *args)
end
+ def in_bundled_app(cmd, options = {})
+ sys_exec(cmd, dir: bundled_app, raise_on_error: options[:raise_on_error])
+ end
+
def bundle(cmd, options = {}, &block)
bundle_bin = options.delete(:bundle_bin)
bundle_bin ||= installed_bindir.join("bundle")
@@ -86,29 +73,24 @@ module Spec
env = options.delete(:env) || {}
requires = options.delete(:requires) || []
- realworld = RSpec.current_example.metadata[:realworld]
- artifice = options.delete(:artifice) do
- if realworld
- "vcr"
- else
- "fail"
- end
- end
- if artifice
- requires << "#{Path.spec_dir}/support/artifice/#{artifice}.rb"
- end
+ dir = options.delete(:dir) || bundled_app
+ custom_load_path = options.delete(:load_path)
load_path = []
- load_path << spec_dir
+ load_path << custom_load_path if custom_load_path
+
+ build_env_options = { load_path: load_path, requires: requires, env: env }
+ build_env_options.merge!(artifice: options.delete(:artifice)) if options.key?(:artifice) || cmd.start_with?("exec")
+
+ match_source(cmd)
+
+ env = build_env(build_env_options)
- dir = options.delete(:dir) || bundled_app
raise_on_error = options.delete(:raise_on_error)
args = options.map do |k, v|
case v
- when nil
- next
when true
" --#{k}"
when false
@@ -118,20 +100,31 @@ module Spec
end
end.join
- ruby_cmd = build_ruby_cmd({ load_path: load_path, requires: requires, env: env })
- cmd = "#{ruby_cmd} #{bundle_bin} #{cmd}#{args}"
+ cmd = "#{Gem.ruby} #{bundle_bin} #{cmd}#{args}"
sys_exec(cmd, { env: env, dir: dir, raise_on_error: raise_on_error }, &block)
end
+ def main_source(dir)
+ gemfile = File.expand_path("Gemfile", dir)
+ return unless File.exist?(gemfile)
+
+ match = File.readlines(gemfile).first.match(/source ["'](?<source>[^"']+)["']/)
+ return unless match
+
+ match[:source]
+ end
+
def bundler(cmd, options = {})
- options[:bundle_bin] = system_gem_path.join("bin/bundler")
+ options[:bundle_bin] = system_gem_path("bin/bundler")
bundle(cmd, options)
end
def ruby(ruby, options = {})
- ruby_cmd = build_ruby_cmd
+ env = build_env({ artifice: nil }.merge(options))
escaped_ruby = ruby.shellescape
- sys_exec(%(#{ruby_cmd} -w -e #{escaped_ruby}), options)
+ options[:env] = env if env
+ options[:dir] ||= bundled_app
+ sys_exec(%(#{Gem.ruby} -w -e #{escaped_ruby}), options)
end
def load_error_ruby(ruby, name, opts = {})
@@ -139,26 +132,49 @@ module Spec
begin
#{ruby}
rescue LoadError => e
- warn "ZOMG LOAD ERROR" if e.message.include?("-- #{name}")
+ warn e.message if e.message.include?("-- #{name}")
end
R
end
- def build_ruby_cmd(options = {})
- libs = options.delete(:load_path)
- lib_option = libs ? "-I#{libs.join(File::PATH_SEPARATOR)}" : []
+ def build_env(options = {})
+ env = options.delete(:env) || {}
+ libs = options.delete(:load_path) || []
+ env["RUBYOPT"] = opt_add("-I#{libs.join(File::PATH_SEPARATOR)}", env["RUBYOPT"]) if libs.any?
+
+ current_example = RSpec.current_example
+
+ main_source = @gemfile_source if defined?(@gemfile_source)
+ compact_index_main_source = main_source&.start_with?("https://gem.repo", "https://gems.security")
requires = options.delete(:requires) || []
+ requires << hax
- hax_path = "#{Path.spec_dir}/support/hax.rb"
+ artifice = options.delete(:artifice) do
+ if current_example && current_example.metadata[:realworld]
+ "vcr"
+ elsif compact_index_main_source
+ env["BUNDLER_SPEC_GEM_REPO"] ||=
+ case main_source
+ when "https://gem.repo1" then gem_repo1.to_s
+ when "https://gem.repo2" then gem_repo2.to_s
+ when "https://gem.repo3" then gem_repo3.to_s
+ when "https://gem.repo4" then gem_repo4.to_s
+ when "https://gems.security" then security_repo.to_s
+ end
+
+ "compact_index"
+ else
+ "fail"
+ end
+ end
+ if artifice
+ requires << "#{Path.spec_dir}/support/artifice/#{artifice}.rb"
+ end
- # For specs that need to ignore the default Bundler gem, load hax before
- # anything else since other stuff may actually load bundler and not skip
- # the default version
- options[:env]&.include?("BUNDLER_IGNORE_DEFAULT_GEM") ? requires.prepend(hax_path) : requires.append(hax_path)
- require_option = requires.map {|r| "-r#{r}" }
+ requires.each {|r| env["RUBYOPT"] = opt_add("-r#{r}", env["RUBYOPT"]) }
- [Gem.ruby, *lib_option, *require_option].compact.join(" ")
+ env
end
def gembin(cmd, options = {})
@@ -168,92 +184,23 @@ module Spec
def gem_command(command, options = {})
env = options[:env] || {}
- env["RUBYOPT"] = opt_add(opt_add("-r#{spec_dir}/support/hax.rb", env["RUBYOPT"]), ENV["RUBYOPT"])
+ env["RUBYOPT"] = opt_add(opt_add("-r#{hax}", env["RUBYOPT"]), ENV["RUBYOPT"])
options[:env] = env
- sys_exec("#{Path.gem_bin} #{command}", options)
- end
- def rake
- "#{Gem.ruby} -S #{ENV["GEM_PATH"]}/bin/rake"
- end
+ # Sometimes `gem install` commands hang at dns resolution, which has a
+ # default timeout of 60 seconds. When that happens, the timeout for a
+ # command is expired too. So give `gem install` commands a bit more time.
+ options[:timeout] = 120
- def git(cmd, path, options = {})
- sys_exec("git #{cmd}", options.merge(dir: path))
+ sys_exec("#{Path.gem_bin} #{command}", options)
end
- def sys_exec(cmd, options = {})
+ def sys_exec(cmd, options = {}, &block)
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, working_directory: dir, timeout: 60)
-
- require "open3"
- 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
-
- stdout_handler = ->(data) { command_execution.original_stdout << data }
- stderr_handler = ->(data) { command_execution.original_stderr << data }
-
- stdout_thread = read_stream(stdout, stdout_handler, timeout: command_execution.timeout)
- stderr_thread = read_stream(stderr, stderr_handler, timeout: command_execution.timeout)
-
- stdout_thread.join
- stderr_thread.join
-
- status = wait_thr.value
- command_execution.exitstatus = if status.exited?
- status.exitstatus
- elsif status.signaled?
- exit_status_for_signal(status.termsig)
- end
- rescue TimeoutExceeded
- command_execution.failure_reason = :timeout
- command_execution.exitstatus = exit_status_for_signal(Signal.list["INT"])
- end
-
- unless options[:raise_on_error] == false || command_execution.success?
- command_execution.raise_error!
- end
-
- command_executions << command_execution
-
- command_execution.stdout
- end
-
- # Mostly copied from https://github.com/piotrmurach/tty-command/blob/49c37a895ccea107e8b78d20e4cb29de6a1a53c8/lib/tty/command/process_runner.rb#L165-L193
- def read_stream(stream, handler, timeout:)
- Thread.new do
- Thread.current.report_on_exception = false
- cmd_start = Time.now
- readers = [stream]
-
- while readers.any?
- ready = IO.select(readers, nil, readers, timeout)
- raise TimeoutExceeded if ready.nil?
-
- ready[0].each do |reader|
- chunk = reader.readpartial(16 * 1024)
- handler.call(chunk)
-
- # control total time spent reading
- runtime = Time.now - cmd_start
- time_left = timeout - runtime
- raise TimeoutExceeded if time_left < 0.0
- rescue Errno::EAGAIN, Errno::EINTR
- rescue EOFError, Errno::EPIPE, Errno::EIO
- readers.delete(reader)
- reader.close
- end
- end
- end
- end
-
- def all_commands_output
- return "" if command_executions.empty?
+ options[:env] = env
- "\n\nCommands:\n#{command_executions.map(&:to_s_verbose).join("\n\n")}"
+ sh(cmd, options, &block)
end
def config(config = nil, path = bundled_app(".bundle/config"))
@@ -278,10 +225,20 @@ module Spec
end
def create_file(path, contents = "")
+ contents = strip_whitespace(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(contents)
+ path.write(contents)
+
+ # if the file is a script, create respective bat file on Windows
+ if contents.start_with?("#!")
+ path.chmod(0o755)
+ if Gem.win_platform?
+ path.sub_ext(".bat").write <<~SCRIPT
+ @ECHO OFF
+ @"ruby.exe" "%~dpn0" %*
+ SCRIPT
+ end
end
end
@@ -291,6 +248,7 @@ module Spec
if contents.nil?
read_gemfile
else
+ match_source(contents)
create_file(args.pop || "Gemfile", contents)
end
end
@@ -335,38 +293,60 @@ module Spec
bundle :lock, opts
end
+ def base_system_gems(*names, **options)
+ system_gems names.map {|name| find_base_path(name) }, **options
+ end
+
def system_gems(*gems)
gems = gems.flatten
options = gems.last.is_a?(Hash) ? gems.pop : {}
install_dir = options.fetch(:path, system_gem_path)
default = options.fetch(:default, false)
- with_gem_path_as(install_dir) 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-(?<version>.*)\z/)[:version] if gem_name != "bundler"
- with_built_bundler(version) {|gem_path| install_gem(gem_path, install_dir, default) }
- elsif %r{\A(?:[a-zA-Z]:)?/.*\.gem\z}.match?(gem_name)
- install_gem(gem_name, install_dir, default)
- else
- install_gem("#{gem_repo}/gems/#{gem_name}.gem", install_dir, default)
- end
+ gems.each do |g|
+ gem_name = g.to_s
+ bundler = gem_name.match(/\Abundler-(?<version>.*)\z/)
+
+ if bundler
+ with_built_bundler(bundler[:version], released: options.fetch(:released, false)) {|gem_path| install_gem(gem_path, install_dir, default) }
+ elsif %r{\A(?:[a-zA-Z]:)?/.*\.gem\z}.match?(gem_name)
+ install_gem(gem_name, install_dir, default)
+ else
+ gem_repo = options.fetch(:gem_repo, gem_repo1)
+ install_gem("#{gem_repo}/gems/#{gem_name}.gem", install_dir, default)
end
end
end
+ def self.install_dev_bundler
+ extend self
+
+ with_built_bundler(nil, build_path: tmp_root) {|gem_path| install_gem(gem_path, pristine_system_gem_path) }
+ end
+
def install_gem(path, install_dir, default = false)
- raise "OMG `#{path}` does not exist!" unless File.exist?(path)
+ raise ArgumentError, "`#{path}` does not exist!" unless File.exist?(path)
args = "--no-document --ignore-dependencies --verbose --local --install-dir #{install_dir}"
- args += " --default" if default
gem_command "install #{args} '#{path}'"
+
+ if default
+ gem = Pathname.new(path).basename.to_s.match(/(.*)\.gem/)[1]
+
+ # Revert Gem::Installer#write_spec and apply Gem::Installer#write_default_spec
+ FileUtils.mkdir_p File.join(install_dir, "specifications", "default")
+ File.rename File.join(install_dir, "specifications", gem + ".gemspec"),
+ File.join(install_dir, "specifications", "default", gem + ".gemspec")
+
+ # Revert Gem::Installer#write_cache_file
+ File.delete File.join(install_dir, "cache", gem + ".gem")
+ end
end
- def with_built_bundler(version = nil, &block)
- Builders::BundlerBuilder.new(self, "bundler", version)._build(&block)
+ def with_built_bundler(version = nil, opts = {}, &block)
+ require_relative "builders"
+
+ Builders::BundlerBuilder.new(self, "bundler", version)._build(opts, &block)
end
def with_gem_path_as(path)
@@ -400,16 +380,6 @@ module Spec
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|
@@ -420,49 +390,43 @@ module Spec
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"
- end
+ create_file(tmp("fake_man/man"), <<~SCRIPT)
+ #!/usr/bin/env ruby
+ puts ARGV.inspect
+ SCRIPT
with_path_added(tmp("fake_man")) { yield }
end
def pristine_system_gems(*gems)
- FileUtils.rm_rf(system_gem_path)
-
- 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_r(system_gem_path)
- with_gem_path_as(path) do
- gems.each do |gem|
- gem_command "install --no-document #{gem}"
- end
+ if gems.any?
+ system_gems(*gems)
+ else
+ default_system_gems
end
end
def cache_gems(*gems, gem_repo: gem_repo1)
gems = gems.flatten
- FileUtils.rm_rf("#{bundled_app}/vendor/cache")
FileUtils.mkdir_p("#{bundled_app}/vendor/cache")
gems.each do |g|
path = "#{gem_repo}/gems/#{g}.gem"
- raise "OMG `#{path}` does not exist!" unless File.exist?(path)
+ raise ArgumentError, "`#{path}` does not exist!" unless File.exist?(path)
FileUtils.cp(path, "#{bundled_app}/vendor/cache")
end
end
def simulate_new_machine
- FileUtils.rm_rf bundled_app(".bundle")
- pristine_system_gems :bundler
+ FileUtils.rm_r bundled_app(".bundle")
+ pristine_system_gems
+ end
+
+ def default_system_gems
+ FileUtils.cp_r pristine_system_gem_path, system_gem_path
end
def simulate_ruby_platform(ruby_platform)
@@ -476,21 +440,11 @@ module Spec
def simulate_platform(platform)
old = ENV["BUNDLER_SPEC_PLATFORM"]
ENV["BUNDLER_SPEC_PLATFORM"] = platform.to_s
- yield if block_given?
+ yield
ensure
ENV["BUNDLER_SPEC_PLATFORM"] = old if block_given?
end
- def simulate_windows(platform = x86_mswin32)
- old = ENV["BUNDLER_SPEC_WINDOWS"]
- ENV["BUNDLER_SPEC_WINDOWS"] = "true"
- simulate_platform platform do
- yield
- end
- ensure
- ENV["BUNDLER_SPEC_WINDOWS"] = old
- end
-
def current_ruby_minor
Gem.ruby_version.segments.tap {|s| s.delete_at(2) }.join(".")
end
@@ -499,18 +453,12 @@ module Spec
ruby_major_minor.map.with_index {|s, i| i == 1 ? s + 1 : s }.join(".")
end
- def previous_ruby_minor
- return "2.7" if ruby_major_minor == [3, 0]
-
- ruby_major_minor.map.with_index {|s, i| i == 1 ? s - 1 : s }.join(".")
- end
-
def ruby_major_minor
Gem.ruby_version.segments[0..1]
end
def revision_for(path)
- sys_exec("git rev-parse HEAD", dir: path).strip
+ git("rev-parse HEAD", path).strip
end
def with_read_only(pattern)
@@ -562,41 +510,34 @@ module Spec
end
end
- def require_rack
- # need to hack, so we can require rack
+ def require_rack_test
+ # need to hack, so we can require rack for testing
old_gem_home = ENV["GEM_HOME"]
- ENV["GEM_HOME"] = Spec::Path.base_system_gem_path.to_s
- require "rack"
+ ENV["GEM_HOME"] = Spec::Path.scoped_base_system_gem_path.to_s
+ require "rack/test"
ENV["GEM_HOME"] = old_gem_home
end
- def wait_for_server(host, port, seconds = 15)
- tries = 0
- sleep 0.5
- TCPSocket.new(host, port)
- rescue StandardError => e
- raise(e) if tries > (seconds * 2)
- tries += 1
- retry
- end
-
- def find_unused_port
- port = 21_453
- begin
- port += 1 while TCPSocket.new("127.0.0.1", port)
- rescue StandardError
- false
- 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
+ def empty_repo4
+ FileUtils.rm_r gem_repo4
+
+ build_repo4 {}
+ end
+
private
+ def match_source(contents)
+ match = /source ["']?(?<source>http[^"']+)["']?/.match(contents)
+ return unless match
+
+ @gemfile_source = match[:source]
+ end
+
def git_root_dir?
root.to_s == `git rev-parse --show-toplevel`.chomp
end
diff --git a/spec/bundler/support/indexes.rb b/spec/bundler/support/indexes.rb
index 086a311551..1fbdd49abe 100644
--- a/spec/bundler/support/indexes.rb
+++ b/spec/bundler/support/indexes.rb
@@ -66,7 +66,6 @@ module Spec
end
def should_conservative_resolve_and_include(opts, unlock, specs)
- # empty unlock means unlock all
opts = Array(opts)
search = Bundler::GemVersionPromoter.new.tap do |s|
s.level = opts.first
@@ -77,8 +76,8 @@ module Spec
def an_awesome_index
build_index do
- gem "rack", %w[0.8 0.9 0.9.1 0.9.2 1.0 1.1]
- gem "rack-mount", %w[0.4 0.5 0.5.1 0.5.2 0.6]
+ gem "myrack", %w[0.8 0.9 0.9.1 0.9.2 1.0 1.1]
+ gem "myrack-mount", %w[0.4 0.5 0.5.1 0.5.2 0.6]
# --- Pre-release support
gem "RubyGems\0", ["1.3.2"]
@@ -89,10 +88,10 @@ module Spec
gem "actionpack", version do
dep "activesupport", version
if version >= v("3.0.0.beta")
- dep "rack", "~> 1.1"
- dep "rack-mount", ">= 0.5"
- elsif version > v("2.3") then dep "rack", "~> 1.0.0"
- elsif version > v("2.0.0") then dep "rack", "~> 0.9.0"
+ dep "myrack", "~> 1.1"
+ dep "myrack-mount", ">= 0.5"
+ elsif version > v("2.3") then dep "myrack", "~> 1.0.0"
+ elsif version > v("2.0.0") then dep "myrack", "~> 0.9.0"
end
end
gem "activerecord", version do
@@ -123,7 +122,7 @@ module Spec
end
versions "1.0 1.2 1.2.1 1.2.2 1.3 1.3.0.1 1.3.5 1.4.0 1.4.2 1.4.2.1" do |version|
- platforms "ruby java mswin32 mingw32 x64-mingw32" do |platform|
+ platforms "ruby java mswin32 mingw32 x64-mingw-ucrt" do |platform|
next if version == v("1.4.2.1") && platform != pl("x86-mswin32")
next if version == v("1.4.2") && platform == pl("x86-mswin32")
gem "nokogiri", version, platform do
@@ -367,7 +366,7 @@ module Spec
def a_circular_index
build_index do
- gem "rack", "1.0.1"
+ gem "myrack", "1.0.1"
gem("foo", "0.2.6") do
dep "bar", ">= 0"
end
diff --git a/spec/bundler/support/matchers.rb b/spec/bundler/support/matchers.rb
index 0f027dcf04..5a3c38a4db 100644
--- a/spec/bundler/support/matchers.rb
+++ b/spec/bundler/support/matchers.rb
@@ -52,7 +52,7 @@ module Spec
end
def self.define_compound_matcher(matcher, preconditions, &declarations)
- raise "Must have preconditions to define a compound matcher" if preconditions.empty?
+ raise ArgumentError, "Must have preconditions to define a compound matcher" if preconditions.empty?
define_method(matcher) do |*expected, &block_arg|
Precondition.new(
RSpec::Matchers::DSL::Matcher.new(matcher, declarations, self, *expected, &block_arg),
@@ -116,8 +116,9 @@ module Spec
source = opts.delete(:source)
groups = Array(opts.delete(:groups)).map(&:inspect).join(", ")
opts[:raise_on_error] = false
- @errors = names.map do |full_name|
+ @errors = names.filter_map do |full_name|
name, version, platform = full_name.split(/\s+/)
+ platform ||= "ruby"
require_path = name.tr("-", "/")
version_const = name == "bundler" ? "Bundler::VERSION" : Spec::Builders.constantize(name)
source_const = "#{Spec::Builders.constantize(name)}_SOURCE"
@@ -127,6 +128,7 @@ module Spec
require '#{require_path}'
actual_version, actual_platform = #{version_const}.split(/\s+/, 2)
+ actual_platform ||= "ruby"
unless Gem::Version.new(actual_version) == Gem::Version.new('#{version}')
puts actual_version
exit 64
@@ -150,14 +152,14 @@ module Spec
end
if exitstatus == 65
actual_platform = out.split("\n").last
- next "#{name} was expected to be of platform #{platform || "ruby"} but was #{actual_platform || "ruby"}"
+ next "#{name} was expected to be of platform #{platform} but was #{actual_platform}"
end
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
+ end
@errors.empty?
end
@@ -166,7 +168,7 @@ module Spec
opts = names.last.is_a?(Hash) ? names.pop : {}
groups = Array(opts.delete(:groups)).map(&:inspect).join(", ")
opts[:raise_on_error] = false
- @errors = names.map do |name|
+ @errors = names.filter_map do |name|
name, version = name.split(/\s+/, 2)
ruby <<-R, opts
begin
@@ -192,7 +194,7 @@ module Spec
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?
next "expected #{name} (#{version}) not to be installed, but it was"
- end.compact
+ end
@errors.empty?
end
diff --git a/spec/bundler/support/options.rb b/spec/bundler/support/options.rb
new file mode 100644
index 0000000000..551fa1acd8
--- /dev/null
+++ b/spec/bundler/support/options.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Spec
+ module Options
+ 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
+ end
+end
diff --git a/spec/bundler/support/path.rb b/spec/bundler/support/path.rb
index 7352d5a353..0a534dd40e 100644
--- a/spec/bundler/support/path.rb
+++ b/spec/bundler/support/path.rb
@@ -1,10 +1,14 @@
# frozen_string_literal: true
-require "pathname"
+require "pathname" unless defined?(Pathname)
require "rbconfig"
+require_relative "env"
+
module Spec
module Path
+ include Spec::Env
+
def source_root
@source_root ||= Pathname.new(ruby_core? ? "../../.." : "../..").expand_path(__dir__)
end
@@ -21,12 +25,8 @@ module Spec
@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)
+ @loaded_gemspec ||= Dir.chdir(source_root) { Gem::Specification.load(gemspec.to_s) }
end
def test_gemfile
@@ -45,8 +45,16 @@ module Spec
@dev_gemfile ||= tool_dir.join("dev_gems.rb")
end
+ def dev_binstub
+ @dev_binstub ||= bindir.join("bundle")
+ end
+
def bindir
- @bindir ||= source_root.join(ruby_core? ? "libexec" : "exe")
+ @bindir ||= source_root.join(ruby_core? ? "spec/bin" : "bin")
+ end
+
+ def exedir
+ @exedir ||= source_root.join(ruby_core? ? "libexec" : "exe")
end
def installed_bindir
@@ -58,12 +66,12 @@ module Spec
end
def gem_bin
- @gem_bin ||= ruby_core? ? ENV["GEM_COMMAND"] : "gem"
+ @gem_bin ||= 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 = env_path.split(File::PATH_SEPARATOR).reject {|path| path == exedir.to_s }.join(File::PATH_SEPARATOR) if ruby_core?
env_path
end
@@ -75,6 +83,10 @@ module Spec
@man_dir ||= lib_dir.join("bundler/man")
end
+ def hax
+ @hax ||= spec_dir.join("support/hax.rb")
+ end
+
def tracked_files
@tracked_files ||= git_ls_files(tracked_files_glob)
end
@@ -98,7 +110,18 @@ module Spec
end
def tmp(*path)
- source_root.join("tmp", scope, *path)
+ tmp_root.join("#{test_env_version}.#{scope}").join(*path)
+ end
+
+ def tmp_root
+ source_root.join("tmp")
+ end
+
+ # Bump this version whenever you make a breaking change to the spec setup
+ # that requires regenerating tmp/.
+
+ def test_env_version
+ 2
end
def scope
@@ -109,33 +132,29 @@ module Spec
end
def home(*path)
- tmp.join("home", *path)
+ tmp("home", *path)
end
def default_bundle_path(*path)
- if Bundler.feature_flag.default_install_uses_path?
- local_gem_path(*path)
- else
- system_gem_path(*path)
- end
+ system_gem_path(*path)
end
def default_cache_path(*path)
- if Bundler.feature_flag.global_gem_cache?
- home(".bundle/cache", *path)
- else
- default_bundle_path("cache/bundler", *path)
- end
+ default_bundle_path("cache/bundler", *path)
+ end
+
+ def compact_index_cache_path
+ home(".bundle/cache/compact_index")
end
def bundled_app(*path)
- root = tmp.join("bundled_app")
+ root = tmp("bundled_app")
FileUtils.mkdir_p(root)
root.join(*path)
end
def bundled_app2(*path)
- root = tmp.join("bundled_app2")
+ root = tmp("bundled_app2")
FileUtils.mkdir_p(root)
root.join(*path)
end
@@ -156,20 +175,20 @@ module Spec
bundled_app("Gemfile.lock")
end
- def base_system_gem_path
- scoped_gem_path(base_system_gems)
+ def scoped_base_system_gem_path
+ scoped_gem_path(base_system_gem_path)
end
- def base_system_gems
- tmp.join("gems/base")
+ def base_system_gem_path
+ tmp_root.join("gems/base")
end
- def rubocop_gems
- tmp.join("gems/rubocop")
+ def rubocop_gem_path
+ tmp_root.join("gems/rubocop")
end
- def standard_gems
- tmp.join("gems/standard")
+ def standard_gem_path
+ tmp_root.join("gems/standard")
end
def file_uri_for(path)
@@ -180,35 +199,35 @@ module Spec
end
def gem_repo1(*args)
- tmp("gems/remote1", *args)
+ gem_path("remote1", *args)
end
def gem_repo_missing(*args)
- tmp("gems/missing", *args)
+ gem_path("missing", *args)
end
def gem_repo2(*args)
- tmp("gems/remote2", *args)
+ gem_path("remote2", *args)
end
def gem_repo3(*args)
- tmp("gems/remote3", *args)
+ gem_path("remote3", *args)
end
def gem_repo4(*args)
- tmp("gems/remote4", *args)
+ gem_path("remote4", *args)
end
def security_repo(*args)
- tmp("gems/security_repo", *args)
+ gem_path("security_repo", *args)
end
def system_gem_path(*path)
- tmp("gems/system", *path)
+ gem_path("system", *path)
end
def pristine_system_gem_path
- tmp("gems/base_system")
+ tmp_root.join("gems/pristine_system")
end
def local_gem_path(*path, base: bundled_app)
@@ -219,6 +238,10 @@ module Spec
base.join(Gem.ruby_engine, RbConfig::CONFIG["ruby_version"])
end
+ def gem_path(*args)
+ tmp("gems", *args)
+ end
+
def lib_path(*args)
tmp("libs", *args)
end
@@ -246,7 +269,7 @@ module Spec
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}"))
+ contents.sub!(/(^\s+VERSION\s*=\s*).*$/, %(\\1"#{version}"))
File.open(version_file, "w") {|f| f << contents }
end
@@ -257,27 +280,49 @@ module Spec
File.open(gemspec_file, "w") {|f| f << contents }
end
- def ruby_core?
- # avoid to warnings
- @ruby_core ||= nil
-
- if @ruby_core.nil?
- @ruby_core = true & ENV["GEM_COMMAND"]
- else
- @ruby_core
- end
+ def replace_changelog(version, dir:)
+ changelog = File.expand_path("CHANGELOG.md", dir)
+ contents = File.readlines(changelog)
+ contents = [contents[0], contents[1], "## #{version} (2100-01-01)\n", *contents[3..-1]].join
+ File.open(changelog, "w") {|f| f << contents }
end
def git_root
ruby_core? ? source_root : source_root.parent
end
+ def rake_path
+ find_base_path("rake")
+ end
+
+ def rake_version
+ File.basename(rake_path).delete_prefix("rake-").delete_suffix(".gem")
+ end
+
+ def sinatra_dependency_paths
+ deps = %w[
+ mustermann
+ rack
+ tilt
+ sinatra
+ ruby2_keywords
+ base64
+ logger
+ cgi
+ ]
+ Dir[scoped_base_system_gem_path.join("gems/{#{deps.join(",")}}-*/lib")].map(&:to_s)
+ end
+
private
+ def find_base_path(name)
+ Dir["#{scoped_base_system_gem_path}/**/#{name}-*.gem"].first
+ end
+
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")
+ git("ls-files -z -- #{glob}", source_root).split("\x0")
end
def tracked_files_glob
@@ -289,7 +334,7 @@ module Spec
end
def man_tracked_files_glob
- ruby_core? ? "man/bundle* man/gemfile*" : "lib/bundler/man/bundle*.1 lib/bundler/man/gemfile*.5"
+ "lib/bundler/man/bundle*.1.ronn lib/bundler/man/gemfile*.5.ronn"
end
def ruby_core_tarball?
diff --git a/spec/bundler/support/platforms.rb b/spec/bundler/support/platforms.rb
index 526e1c09a9..56a0843005 100644
--- a/spec/bundler/support/platforms.rb
+++ b/spec/bundler/support/platforms.rb
@@ -2,64 +2,22 @@
module Spec
module Platforms
- include Bundler::GemHelpers
-
- def rb
- Gem::Platform::RUBY
- end
-
- def mac
- Gem::Platform.new("x86-darwin-10")
- end
-
- def x64_mac
- Gem::Platform.new("x86_64-darwin-15")
- end
-
- def java
- Gem::Platform.new([nil, "java", nil])
- end
-
- def linux
- Gem::Platform.new("x86_64-linux")
- end
-
- def x86_mswin32
- Gem::Platform.new(["x86", "mswin32", nil])
- end
-
- def x64_mswin64
- Gem::Platform.new(["x64", "mswin64", nil])
- end
-
- def x86_mingw32
- Gem::Platform.new(["x86", "mingw32", nil])
- end
-
- def x64_mingw32
- Gem::Platform.new(["x64", "mingw32", nil])
- end
-
- def x64_mingw_ucrt
- Gem::Platform.new(["x64", "mingw", "ucrt"])
- end
-
- def windows_platforms
- [x86_mswin32, x64_mswin64, x86_mingw32, x64_mingw32, x64_mingw_ucrt]
+ def not_local
+ generic_local_platform == Gem::Platform::RUBY ? "java" : Gem::Platform::RUBY
end
- def all_platforms
- [rb, java, linux, windows_platforms].flatten
+ def local_platform
+ Bundler.local_platform
end
- def not_local
- all_platforms.find {|p| p != generic_local_platform }
+ def generic_local_platform
+ Gem::Platform.generic(local_platform)
end
def local_tag
- if RUBY_PLATFORM == "java"
+ if Gem.java_platform?
:jruby
- elsif ["x64-mingw32", "x64-mingw-ucrt"].include?(RUBY_PLATFORM)
+ elsif Gem.win_platform?
:windows
else
:ruby
@@ -96,16 +54,22 @@ module Spec
end
def default_platform_list(*extra, defaults: default_locked_platforms)
- defaults.concat(extra).uniq
+ defaults.concat(extra).map(&:to_s).uniq
end
def lockfile_platforms(*extra, defaults: default_locked_platforms)
platforms = default_platform_list(*extra, defaults: defaults)
- platforms.map(&:to_s).sort.join("\n ")
+ platforms.sort.join("\n ")
end
def default_locked_platforms
- [local_platform, generic_local_platform]
+ [local_platform, generic_default_locked_platform].compact
+ end
+
+ def generic_default_locked_platform
+ return unless Bundler::MatchPlatform.generic_local_platform_is_ruby?
+
+ Gem::Platform::RUBY
end
end
end
diff --git a/spec/bundler/support/rubygems_ext.rb b/spec/bundler/support/rubygems_ext.rb
index 973044ab94..2d681529aa 100644
--- a/spec/bundler/support/rubygems_ext.rb
+++ b/spec/bundler/support/rubygems_ext.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+abort "RubyGems only supports Ruby 3.2 or higher" if RUBY_VERSION < "3.2.0"
+
require_relative "path"
$LOAD_PATH.unshift(Spec::Path.source_lib_dir.to_s)
@@ -8,10 +10,6 @@ module Spec
module Rubygems
extend self
- def dev_setup
- install_gems(dev_gemfile)
- end
-
def gem_load(gem_name, bin_container)
require_relative "switch_rubygems"
@@ -30,6 +28,9 @@ module Spec
end
def test_setup
+ # Install test dependencies unless parallel-rspec is being used, since in that case they should be setup already
+ install_test_deps unless ENV["RSPEC_FORMATTER_OUTPUT_ID"]
+
setup_test_paths
require "fileutils"
@@ -48,36 +49,19 @@ module Spec
Gem::DefaultUserInteraction.ui = Gem::SilentUI.new
end
- 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?
+ ENV["PATH"] = [Path.system_gem_path("bin"), ENV["PATH"]].join(File::PATH_SEPARATOR)
+ ENV["PATH"] = [Path.exedir, 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)
+ dev_bundle("install", gemfile: test_gemfile, path: Path.base_system_gem_path.to_s)
+ dev_bundle("install", gemfile: rubocop_gemfile, path: Path.rubocop_gem_path.to_s)
+ dev_bundle("install", gemfile: standard_gemfile, path: Path.standard_gem_path.to_s)
+
+ require_relative "helpers"
+ Helpers.install_dev_bundler
end
def check_source_control_changes(success_message:, error_message:)
@@ -100,6 +84,36 @@ module Spec
end
end
+ def dev_bundle(*args, gemfile: dev_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
+
+ require "shellwords"
+ # We don't use `Open3` here because it does not work on JRuby + Windows
+ output = `ruby #{Path.dev_binstub} #{args.shelljoin}`
+ raise output unless $?.success?
+ output
+ 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
+
private
def gem_load_and_activate(gem_name, bin_container)
@@ -117,14 +131,7 @@ module Spec
def gem_activate_and_possibly_install(gem_name)
gem_activate(gem_name)
rescue Gem::LoadError => e
- # Windows 3.0 puts a Windows stub script as `rake` while it should be
- # named `rake.bat`. RubyGems does not like that and avoids overwriting it
- # unless explicitly instructed to do so with `force`.
- if RUBY_VERSION.start_with?("3.0") && Gem.win_platform?
- Gem.install(gem_name, e.requirement, force: true)
- else
- Gem.install(gem_name, e.requirement)
- end
+ Gem.install(gem_name, e.requirement)
retry
end
@@ -135,33 +142,6 @@ module Spec
gem gem_name, gem_requirement
end
- 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
-
- puts `#{Gem.ruby} #{File.expand_path("support/bundle.rb", Path.spec_dir)} install --verbose`
- raise 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
diff --git a/spec/bundler/support/rubygems_version_manager.rb b/spec/bundler/support/rubygems_version_manager.rb
index 88da14b67e..c174c461f0 100644
--- a/spec/bundler/support/rubygems_version_manager.rb
+++ b/spec/bundler/support/rubygems_version_manager.rb
@@ -1,12 +1,13 @@
# frozen_string_literal: true
-require "pathname"
-require_relative "helpers"
-require_relative "path"
+require_relative "options"
+require_relative "env"
+require_relative "subprocess"
class RubygemsVersionManager
- include Spec::Helpers
- include Spec::Path
+ include Spec::Options
+ include Spec::Env
+ include Spec::Subprocess
def initialize(source)
@source = source
@@ -57,7 +58,7 @@ class RubygemsVersionManager
cmd = [RbConfig.ruby, $0, *ARGV].compact
- ENV["RUBYOPT"] = opt_add("-I#{local_copy_path.join("lib")}", opt_remove("--disable-gems", ENV["RUBYOPT"]))
+ ENV["RUBYOPT"] = opt_add("-I#{File.join(local_copy_path, "lib")}", opt_remove("--disable-gems", ENV["RUBYOPT"]))
exec(ENV, *cmd)
end
@@ -65,14 +66,14 @@ class RubygemsVersionManager
def switch_local_copy_if_needed
return unless local_copy_switch_needed?
- sys_exec("git checkout #{target_tag}", dir: local_copy_path)
+ git("checkout #{target_tag}", local_copy_path)
- ENV["RGV"] = local_copy_path.to_s
+ ENV["RGV"] = local_copy_path
end
def rubygems_unrequire_needed?
require "rubygems"
- !$LOADED_FEATURES.include?(local_copy_path.join("lib/rubygems.rb").to_s)
+ !$LOADED_FEATURES.include?(File.join(local_copy_path, "lib/rubygems.rb"))
end
def local_copy_switch_needed?
@@ -84,7 +85,7 @@ class RubygemsVersionManager
end
def local_copy_tag
- sys_exec("git rev-parse --abbrev-ref HEAD", dir: local_copy_path)
+ git("rev-parse --abbrev-ref HEAD", local_copy_path)
end
def local_copy_path
@@ -94,21 +95,25 @@ class RubygemsVersionManager
def resolve_local_copy_path
return expanded_source if source_is_path?
- rubygems_path = source_root.join("tmp/rubygems")
+ rubygems_path = File.join(source_root, "tmp/rubygems")
- unless rubygems_path.directory?
- sys_exec("git clone .. #{rubygems_path}", dir: source_root)
+ unless File.directory?(rubygems_path)
+ git("clone .. #{rubygems_path}", source_root)
end
rubygems_path
end
def source_is_path?
- expanded_source.directory?
+ File.directory?(expanded_source)
end
def expanded_source
- @expanded_source ||= Pathname.new(@source).expand_path(source_root)
+ @expanded_source ||= File.expand_path(@source, source_root)
+ end
+
+ def source_root
+ @source_root ||= File.expand_path(ruby_core? ? "../../.." : "../..", __dir__)
end
def resolve_target_tag
diff --git a/spec/bundler/support/setup.rb b/spec/bundler/support/setup.rb
new file mode 100644
index 0000000000..4ac2e5b472
--- /dev/null
+++ b/spec/bundler/support/setup.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require_relative "switch_rubygems"
+
+require_relative "rubygems_ext"
+Spec::Rubygems.install_test_deps
+
+require_relative "path"
+$LOAD_PATH.unshift(File.expand_path("../../lib", __dir__)) if Spec::Path.ruby_core?
diff --git a/spec/bundler/support/silent_logger.rb b/spec/bundler/support/silent_logger.rb
deleted file mode 100644
index 8665beb2c9..0000000000
--- a/spec/bundler/support/silent_logger.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-require "logger"
-module Spec
- class SilentLogger
- (::Logger.instance_methods - Object.instance_methods).each do |logger_instance_method|
- define_method(logger_instance_method) {|*args, &blk| }
- end
- end
-end
diff --git a/spec/bundler/support/subprocess.rb b/spec/bundler/support/subprocess.rb
new file mode 100644
index 0000000000..91db80da48
--- /dev/null
+++ b/spec/bundler/support/subprocess.rb
@@ -0,0 +1,115 @@
+# frozen_string_literal: true
+
+require_relative "command_execution"
+
+module Spec
+ module Subprocess
+ class TimeoutExceeded < StandardError; end
+
+ def command_executions
+ @command_executions ||= []
+ end
+
+ def last_command
+ command_executions.last || raise("There is no last command")
+ end
+
+ def out
+ last_command.stdout
+ end
+
+ def err
+ last_command.stderr
+ end
+
+ def stdboth
+ last_command.stdboth
+ end
+
+ def exitstatus
+ last_command.exitstatus
+ end
+
+ def git(cmd, path = Dir.pwd, options = {})
+ sh("git #{cmd}", options.merge(dir: path))
+ end
+
+ def sh(cmd, options = {})
+ dir = options[:dir]
+ env = options[:env] || {}
+
+ command_execution = CommandExecution.new(cmd.to_s, timeout: options[:timeout] || 60)
+
+ open3_opts = {}
+ open3_opts[:chdir] = dir if dir
+
+ require "open3"
+ require "shellwords"
+ Open3.popen3(env, *cmd.shellsplit, **open3_opts) do |stdin, stdout, stderr, wait_thr|
+ yield stdin, stdout, wait_thr if block_given?
+ stdin.close
+
+ stdout_handler = ->(data) { command_execution.original_stdout << data }
+ stderr_handler = ->(data) { command_execution.original_stderr << data }
+
+ stdout_thread = read_stream(stdout, stdout_handler, timeout: command_execution.timeout)
+ stderr_thread = read_stream(stderr, stderr_handler, timeout: command_execution.timeout)
+
+ stdout_thread.join
+ stderr_thread.join
+
+ status = wait_thr.value
+ command_execution.exitstatus = if status.exited?
+ status.exitstatus
+ elsif status.signaled?
+ exit_status_for_signal(status.termsig)
+ end
+ rescue TimeoutExceeded
+ command_execution.failure_reason = :timeout
+ command_execution.exitstatus = exit_status_for_signal(Signal.list["INT"])
+ end
+
+ unless options[:raise_on_error] == false || command_execution.success?
+ command_execution.raise_error!
+ end
+
+ command_executions << command_execution
+
+ command_execution.stdout
+ end
+
+ # Mostly copied from https://github.com/piotrmurach/tty-command/blob/49c37a895ccea107e8b78d20e4cb29de6a1a53c8/lib/tty/command/process_runner.rb#L165-L193
+ def read_stream(stream, handler, timeout:)
+ Thread.new do
+ Thread.current.report_on_exception = false
+ cmd_start = Time.now
+ readers = [stream]
+
+ while readers.any?
+ ready = IO.select(readers, nil, readers, timeout)
+ raise TimeoutExceeded if ready.nil?
+
+ ready[0].each do |reader|
+ chunk = reader.readpartial(16 * 1024)
+ handler.call(chunk)
+
+ # control total time spent reading
+ runtime = Time.now - cmd_start
+ time_left = timeout - runtime
+ raise TimeoutExceeded if time_left < 0.0
+ rescue Errno::EAGAIN, Errno::EINTR
+ rescue EOFError, Errno::EPIPE, Errno::EIO
+ readers.delete(reader)
+ reader.close
+ end
+ end
+ end
+ end
+
+ def all_commands_output
+ return "" if command_executions.empty?
+
+ "\n\nCommands:\n#{command_executions.map(&:to_s_verbose).join("\n\n")}"
+ end
+ end
+end
diff --git a/spec/bundler/support/the_bundle.rb b/spec/bundler/support/the_bundle.rb
index f252a4515b..452abd7d41 100644
--- a/spec/bundler/support/the_bundle.rb
+++ b/spec/bundler/support/the_bundle.rb
@@ -8,10 +8,8 @@ module Spec
attr_accessor :bundle_dir
- def initialize(opts = {})
- opts = opts.dup
- @bundle_dir = Pathname.new(opts.delete(:bundle_dir) { bundled_app })
- raise "Too many options! #{opts}" unless opts.empty?
+ def initialize
+ @bundle_dir = Pathname.new(bundled_app)
end
def to_s
@@ -28,8 +26,16 @@ module Spec
end
def locked_gems
- raise "Cannot read lockfile if it doesn't exist" unless locked?
+ raise ArgumentError, "Cannot read lockfile if it doesn't exist" unless locked?
Bundler::LockfileParser.new(lockfile.read)
end
+
+ def locked_specs
+ locked_gems.specs.map(&:full_name)
+ end
+
+ def locked_platforms
+ locked_gems.platforms.map(&:to_s)
+ end
end
end
diff --git a/spec/bundler/support/vendored_net_http.rb b/spec/bundler/support/vendored_net_http.rb
new file mode 100644
index 0000000000..8ff2ccd1fe
--- /dev/null
+++ b/spec/bundler/support/vendored_net_http.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+# This defined? guard can be removed once RubyGems 3.4 support is dropped.
+#
+# Bundler specs load this code from `spec/support/vendored_net_http.rb` to avoid
+# activating the Bundler gem too early. Without this guard, we get redefinition
+# warnings once Bundler is actually activated and
+# `lib/bundler/vendored_net_http.rb` is required. This is not an issue in
+# RubyGems versions including `rubygems/vendored_net_http` since `require` takes
+# care of avoiding the double load.
+#
+unless defined?(Gem::Net)
+ begin
+ require "rubygems/vendored_net_http"
+ rescue LoadError
+ begin
+ require "rubygems/net/http"
+ rescue LoadError
+ require "net/http"
+ Gem::Net = Net
+ end
+ end
+end
diff --git a/spec/bundler/support/windows_tag_group.rb b/spec/bundler/support/windows_tag_group.rb
new file mode 100644
index 0000000000..c41c446462
--- /dev/null
+++ b/spec/bundler/support/windows_tag_group.rb
@@ -0,0 +1,191 @@
+# frozen_string_literal: true
+
+# This group classifies test files into 4 groups by running `bin/rspec --profile 10000`
+# to ensure balanced execution times. When adding new test files, it is recommended to
+# re-aggregate and adjust the groups to keep them balanced.
+# For now, please add new files to group 'windows_d'.
+
+module Spec
+ module WindowsTagGroup
+ EXAMPLE_MAPPINGS = {
+ windows_a: [
+ "spec/runtime/setup_spec.rb",
+ "spec/commands/install_spec.rb",
+ "spec/commands/add_spec.rb",
+ "spec/install/gems/compact_index_spec.rb",
+ "spec/commands/config_spec.rb",
+ "spec/commands/pristine_spec.rb",
+ "spec/install/gemfile/path_spec.rb",
+ "spec/update/git_spec.rb",
+ "spec/commands/open_spec.rb",
+ "spec/commands/remove_spec.rb",
+ "spec/commands/show_spec.rb",
+ "spec/plugins/source/example_spec.rb",
+ "spec/commands/console_spec.rb",
+ "spec/runtime/require_spec.rb",
+ "spec/runtime/env_helpers_spec.rb",
+ "spec/runtime/gem_tasks_spec.rb",
+ "spec/install/gemfile_spec.rb",
+ "spec/commands/fund_spec.rb",
+ "spec/commands/init_spec.rb",
+ "spec/bundler/ruby_dsl_spec.rb",
+ "spec/bundler/mirror_spec.rb",
+ "spec/bundler/source/git/git_proxy_spec.rb",
+ "spec/bundler/source_list_spec.rb",
+ "spec/bundler/plugin/installer_spec.rb",
+ "spec/bundler/friendly_errors_spec.rb",
+ "spec/resolver/platform_spec.rb",
+ "spec/bundler/fetcher/downloader_spec.rb",
+ "spec/update/force_spec.rb",
+ "spec/bundler/env_spec.rb",
+ "spec/install/gems/mirror_spec.rb",
+ "spec/install/failure_spec.rb",
+ "spec/bundler/yaml_serializer_spec.rb",
+ "spec/bundler/environment_preserver_spec.rb",
+ "spec/install/gemfile/install_if_spec.rb",
+ "spec/install/gems/gemfile_source_header_spec.rb",
+ "spec/bundler/fetcher/base_spec.rb",
+ "spec/bundler/rubygems_integration_spec.rb",
+ "spec/bundler/worker_spec.rb",
+ "spec/bundler/dependency_spec.rb",
+ "spec/bundler/ui_spec.rb",
+ "spec/bundler/plugin/source_list_spec.rb",
+ "spec/bundler/source/path_spec.rb",
+ ],
+ windows_b: [
+ "spec/install/gemfile/git_spec.rb",
+ "spec/install/gems/standalone_spec.rb",
+ "spec/commands/lock_spec.rb",
+ "spec/cache/gems_spec.rb",
+ "spec/other/major_deprecation_spec.rb",
+ "spec/install/gems/dependency_api_spec.rb",
+ "spec/install/gemfile/gemspec_spec.rb",
+ "spec/plugins/install_spec.rb",
+ "spec/commands/binstubs_spec.rb",
+ "spec/install/gems/flex_spec.rb",
+ "spec/runtime/inline_spec.rb",
+ "spec/commands/post_bundle_message_spec.rb",
+ "spec/runtime/executable_spec.rb",
+ "spec/lock/git_spec.rb",
+ "spec/plugins/hook_spec.rb",
+ "spec/install/allow_offline_install_spec.rb",
+ "spec/install/gems/post_install_spec.rb",
+ "spec/install/gemfile/ruby_spec.rb",
+ "spec/install/security_policy_spec.rb",
+ "spec/install/yanked_spec.rb",
+ "spec/update/gemfile_spec.rb",
+ "spec/runtime/load_spec.rb",
+ "spec/plugins/command_spec.rb",
+ "spec/commands/version_spec.rb",
+ "spec/install/prereleases_spec.rb",
+ "spec/bundler/uri_credentials_filter_spec.rb",
+ "spec/bundler/plugin_spec.rb",
+ "spec/install/gems/mirror_probe_spec.rb",
+ "spec/plugins/list_spec.rb",
+ "spec/bundler/compact_index_client/parser_spec.rb",
+ "spec/bundler/gem_version_promoter_spec.rb",
+ "spec/other/cli_dispatch_spec.rb",
+ "spec/bundler/source/rubygems_spec.rb",
+ "spec/cache/platform_spec.rb",
+ "spec/update/gems/fund_spec.rb",
+ "spec/bundler/stub_specification_spec.rb",
+ "spec/bundler/retry_spec.rb",
+ "spec/bundler/installer/spec_installation_spec.rb",
+ "spec/bundler/spec_set_spec.rb",
+ "spec/quality_es_spec.rb",
+ "spec/bundler/index_spec.rb",
+ "spec/other/cli_man_pages_spec.rb",
+ ],
+ windows_c: [
+ "spec/commands/newgem_spec.rb",
+ "spec/commands/exec_spec.rb",
+ "spec/commands/clean_spec.rb",
+ "spec/commands/platform_spec.rb",
+ "spec/cache/git_spec.rb",
+ "spec/install/gemfile/groups_spec.rb",
+ "spec/commands/cache_spec.rb",
+ "spec/commands/check_spec.rb",
+ "spec/commands/list_spec.rb",
+ "spec/install/path_spec.rb",
+ "spec/bundler/cli_spec.rb",
+ "spec/install/bundler_spec.rb",
+ "spec/install/git_spec.rb",
+ "spec/commands/doctor_spec.rb",
+ "spec/bundler/dsl_spec.rb",
+ "spec/install/gems/fund_spec.rb",
+ "spec/install/gems/env_spec.rb",
+ "spec/bundler/ruby_version_spec.rb",
+ "spec/bundler/definition_spec.rb",
+ "spec/install/gemfile/eval_gemfile_spec.rb",
+ "spec/plugins/source_spec.rb",
+ "spec/install/gems/dependency_api_fallback_spec.rb",
+ "spec/plugins/uninstall_spec.rb",
+ "spec/bundler/plugin/index_spec.rb",
+ "spec/bundler/bundler_spec.rb",
+ "spec/bundler/fetcher_spec.rb",
+ "spec/bundler/source/rubygems/remote_spec.rb",
+ "spec/bundler/lockfile_parser_spec.rb",
+ "spec/cache/cache_path_spec.rb",
+ "spec/bundler/source/git_spec.rb",
+ "spec/bundler/source_spec.rb",
+ "spec/commands/ssl_spec.rb",
+ "spec/bundler/fetcher/compact_index_spec.rb",
+ "spec/bundler/plugin/api_spec.rb",
+ "spec/bundler/endpoint_specification_spec.rb",
+ "spec/bundler/fetcher/index_spec.rb",
+ "spec/bundler/settings/validator_spec.rb",
+ "spec/bundler/build_metadata_spec.rb",
+ "spec/bundler/current_ruby_spec.rb",
+ "spec/bundler/installer/gem_installer_spec.rb",
+ "spec/bundler/cli_common_spec.rb",
+ "spec/bundler/ci_detector_spec.rb",
+ ],
+ windows_d: [
+ "spec/commands/outdated_spec.rb",
+ "spec/commands/update_spec.rb",
+ "spec/lock/lockfile_spec.rb",
+ "spec/install/deploy_spec.rb",
+ "spec/install/gemfile/sources_spec.rb",
+ "spec/runtime/self_management_spec.rb",
+ "spec/install/gemfile/specific_platform_spec.rb",
+ "spec/commands/info_spec.rb",
+ "spec/install/gems/resolving_spec.rb",
+ "spec/install/gemfile/platform_spec.rb",
+ "spec/bundler/gem_helper_spec.rb",
+ "spec/install/global_cache_spec.rb",
+ "spec/runtime/platform_spec.rb",
+ "spec/update/gems/post_install_spec.rb",
+ "spec/install/gems/native_extensions_spec.rb",
+ "spec/install/force_spec.rb",
+ "spec/cache/path_spec.rb",
+ "spec/install/gemspecs_spec.rb",
+ "spec/commands/help_spec.rb",
+ "spec/bundler/shared_helpers_spec.rb",
+ "spec/bundler/settings_spec.rb",
+ "spec/resolver/basic_spec.rb",
+ "spec/install/gemfile/force_ruby_platform_spec.rb",
+ "spec/commands/licenses_spec.rb",
+ "spec/install/gemfile/lockfile_spec.rb",
+ "spec/bundler/fetcher/dependency_spec.rb",
+ "spec/quality_spec.rb",
+ "spec/bundler/remote_specification_spec.rb",
+ "spec/install/process_lock_spec.rb",
+ "spec/install/binstubs_spec.rb",
+ "spec/bundler/compact_index_client/updater_spec.rb",
+ "spec/bundler/ui/shell_spec.rb",
+ "spec/other/ext_spec.rb",
+ "spec/commands/issue_spec.rb",
+ "spec/update/path_spec.rb",
+ "spec/bundler/plugin/api/source_spec.rb",
+ "spec/install/gems/win32_spec.rb",
+ "spec/bundler/plugin/dsl_spec.rb",
+ "spec/runtime/requiring_spec.rb",
+ "spec/bundler/plugin/events_spec.rb",
+ "spec/bundler/resolver/candidate_spec.rb",
+ "spec/bundler/digest_spec.rb",
+ "spec/bundler/fetcher/gem_remote_fetcher_spec.rb",
+ "spec/bundler/uri_normalizer_spec.rb",
+ ],
+ }.freeze
+ end
+end
diff --git a/spec/bundler/update/force_spec.rb b/spec/bundler/update/force_spec.rb
new file mode 100644
index 0000000000..325f58088a
--- /dev/null
+++ b/spec/bundler/update/force_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+RSpec.describe "bundle update" do
+ before :each do
+ install_gemfile <<-G
+ source "https://gem.repo1"
+ gem "myrack"
+ G
+ end
+
+ it "re-installs installed gems with --force" do
+ myrack_lib = default_bundle_path("gems/myrack-1.0.0/lib/myrack.rb")
+ myrack_lib.open("w") {|f| f.write("blah blah blah") }
+ bundle :update, force: true
+
+ expect(out).to include "Installing myrack 1.0.0"
+ expect(myrack_lib.open(&:read)).to eq("MYRACK = '1.0.0'\n")
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+
+ it "re-installs installed gems with --redownload" do
+ myrack_lib = default_bundle_path("gems/myrack-1.0.0/lib/myrack.rb")
+ myrack_lib.open("w") {|f| f.write("blah blah blah") }
+ bundle :update, redownload: true
+
+ expect(out).to include "Installing myrack 1.0.0"
+ expect(myrack_lib.open(&:read)).to eq("MYRACK = '1.0.0'\n")
+ expect(the_bundle).to include_gems "myrack 1.0.0"
+ end
+end
diff --git a/spec/bundler/update/gemfile_spec.rb b/spec/bundler/update/gemfile_spec.rb
index d32a7945b0..cb94799061 100644
--- a/spec/bundler/update/gemfile_spec.rb
+++ b/spec/bundler/update/gemfile_spec.rb
@@ -4,8 +4,8 @@ RSpec.describe "bundle update" do
context "with --gemfile" do
it "finds the gemfile" do
gemfile bundled_app("NotGemfile"), <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
bundle :install, gemfile: bundled_app("NotGemfile")
@@ -14,15 +14,15 @@ RSpec.describe "bundle update" do
# Specify BUNDLE_GEMFILE for `the_bundle`
# to retrieve the proper Gemfile
ENV["BUNDLE_GEMFILE"] = "NotGemfile"
- expect(the_bundle).to include_gems "rack 1.0.0"
+ expect(the_bundle).to include_gems "myrack 1.0.0"
end
end
context "with gemfile set via config" do
before do
gemfile bundled_app("NotGemfile"), <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
G
bundle "config set --local gemfile #{bundled_app("NotGemfile")}"
@@ -33,7 +33,7 @@ RSpec.describe "bundle update" do
bundle "update", all: true
bundle "list"
- expect(out).to include("rack (1.0.0)")
+ expect(out).to include("myrack (1.0.0)")
end
it "uses the gemfile while in a subdirectory" do
@@ -41,7 +41,7 @@ RSpec.describe "bundle update" do
bundle "update", all: true, dir: bundled_app("subdir")
bundle "list", dir: bundled_app("subdir")
- expect(out).to include("rack (1.0.0)")
+ expect(out).to include("myrack (1.0.0)")
end
end
end
diff --git a/spec/bundler/update/gems/fund_spec.rb b/spec/bundler/update/gems/fund_spec.rb
index 4a87c16bf7..a5624d3e0a 100644
--- a/spec/bundler/update/gems/fund_spec.rb
+++ b/spec/bundler/update/gems/fund_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe "bundle update" do
end
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem 'has_funding_and_other_metadata'
gem 'has_funding', '< 2.0'
G
@@ -35,7 +35,7 @@ RSpec.describe "bundle update" do
context "when listed gems are updated" do
before do
gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
gem 'has_funding_and_other_metadata'
gem 'has_funding'
G
diff --git a/spec/bundler/update/gems/post_install_spec.rb b/spec/bundler/update/gems/post_install_spec.rb
index e3593387d4..9c71f6e0e3 100644
--- a/spec/bundler/update/gems/post_install_spec.rb
+++ b/spec/bundler/update/gems/post_install_spec.rb
@@ -5,8 +5,8 @@ RSpec.describe "bundle update" do
before do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack', "< 1.0"
+ source "https://gem.repo1"
+ gem 'myrack', "< 1.0"
gem 'thin'
G
@@ -17,10 +17,10 @@ RSpec.describe "bundle update" do
shared_examples "a config observer" do
context "when ignore post-install messages for gem is set" do
- let(:config) { "ignore_messages.rack true" }
+ let(:config) { "ignore_messages.myrack true" }
it "doesn't display gem's post-install message" do
- expect(out).not_to include("Rack's post install message")
+ expect(out).not_to include("Myrack's post install message")
end
end
@@ -35,8 +35,8 @@ RSpec.describe "bundle update" do
shared_examples "a post-install message outputter" do
it "should display post-install messages for updated gems" do
- expect(out).to include("Post-install message from rack:")
- expect(out).to include("Rack's post install message")
+ expect(out).to include("Post-install message from myrack:")
+ expect(out).to include("Myrack's post install message")
end
it "should not display the post-install message for non-updated gems" do
@@ -47,8 +47,8 @@ RSpec.describe "bundle update" do
context "when listed gem is updated" do
before do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack'
+ source "https://gem.repo1"
+ gem 'myrack'
gem 'thin'
G
@@ -62,8 +62,8 @@ RSpec.describe "bundle update" do
context "when dependency triggers update" do
before do
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem 'rack-obama'
+ source "https://gem.repo1"
+ gem 'myrack-obama'
gem 'thin'
G
diff --git a/spec/bundler/update/git_spec.rb b/spec/bundler/update/git_spec.rb
index 3b7bbfd979..526e988ab7 100644
--- a/spec/bundler/update/git_spec.rb
+++ b/spec/bundler/update/git_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe "bundle update" do
update_git "foo", branch: "omg"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{lib_path("foo-1.0")}", :branch => "omg" do
gem 'foo'
end
@@ -29,8 +29,8 @@ RSpec.describe "bundle update" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rails", :git => "#{file_uri_for(lib_path("rails"))}"
+ source "https://gem.repo1"
+ gem "rails", :git => "#{lib_path("rails")}"
G
bundle "update rails"
@@ -42,7 +42,7 @@ RSpec.describe "bundle update" do
update_git "foo", branch: "omg", path: lib_path("foo")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
git "#{lib_path("foo")}", :branch => "omg" do
gem 'foo'
end
@@ -64,8 +64,8 @@ RSpec.describe "bundle update" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "foo", :git => "#{file_uri_for(lib_path("foo"))}"
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo")}"
gem "bar"
G
@@ -83,30 +83,30 @@ RSpec.describe "bundle update" do
build_git "foo", path: lib_path("foo_two")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "foo", "1.0", :git => "#{file_uri_for(lib_path("foo_one"))}"
+ source "https://gem.repo1"
+ gem "foo", "1.0", :git => "#{lib_path("foo_one")}"
G
- FileUtils.rm_rf lib_path("foo_one")
+ FileUtils.rm_r lib_path("foo_one")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "foo", "1.0", :git => "#{file_uri_for(lib_path("foo_two"))}"
+ source "https://gem.repo1"
+ gem "foo", "1.0", :git => "#{lib_path("foo_two")}"
G
expect(err).to be_empty
- expect(out).to include("Fetching #{file_uri_for(lib_path)}/foo_two")
+ expect(out).to include("Fetching #{lib_path}/foo_two")
expect(out).to include("Bundle complete!")
end
it "fetches tags from the remote" do
build_git "foo"
@remote = build_git("bar", bare: true)
- update_git "foo", remote: file_uri_for(@remote.path)
+ update_git "foo", remote: @remote.path
update_git "foo", push: "main"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'foo', :git => "#{@remote.path}"
G
@@ -115,7 +115,7 @@ RSpec.describe "bundle update" do
update_git "foo", push: "fubar"
gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem 'foo', :git => "#{@remote.path}", :tag => "fubar"
G
@@ -142,13 +142,13 @@ RSpec.describe "bundle update" do
s.add_dependency "submodule"
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")
+ git "submodule add #{lib_path("submodule-1.0")} submodule-1.0", lib_path("has_submodule-1.0")
+ git "commit -m \"submodulator\"", lib_path("has_submodule-1.0")
end
it "it unlocks the source when submodules are added to a git source" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
git "#{lib_path("has_submodule-1.0")}" do
gem "has_submodule"
end
@@ -158,7 +158,7 @@ RSpec.describe "bundle update" do
expect(out).to eq("GEM")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
git "#{lib_path("has_submodule-1.0")}", :submodules => true do
gem "has_submodule"
end
@@ -170,7 +170,7 @@ RSpec.describe "bundle update" do
it "unlocks the source when submodules are removed from git source", git: ">= 2.9.0" do
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
git "#{lib_path("has_submodule-1.0")}", :submodules => true do
gem "has_submodule"
end
@@ -180,7 +180,7 @@ RSpec.describe "bundle update" do
expect(out).to eq("GIT")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo4)}"
+ source "https://gem.repo4"
git "#{lib_path("has_submodule-1.0")}" do
gem "has_submodule"
end
@@ -195,11 +195,11 @@ RSpec.describe "bundle update" do
build_git "foo", "1.0"
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "foo", :git => "#{file_uri_for(lib_path("foo-1.0"))}"
+ source "https://gem.repo1"
+ gem "foo", :git => "#{lib_path("foo-1.0")}"
G
- lib_path("foo-1.0").join(".git").rmtree
+ FileUtils.rm_rf lib_path("foo-1.0").join(".git")
bundle :update, all: true, raise_on_error: false
expect(err).to include(lib_path("foo-1.0").to_s).
@@ -207,19 +207,19 @@ RSpec.describe "bundle update" do
end
it "should not explode on invalid revision on update of gem by name" do
- build_git "rack", "0.8"
+ build_git "myrack", "0.8"
- build_git "rack", "0.8", path: lib_path("local-rack") do |s|
- s.write "lib/rack.rb", "puts :LOCAL"
+ build_git "myrack", "0.8", path: lib_path("local-myrack") do |s|
+ s.write "lib/myrack.rb", "puts :LOCAL"
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack", :git => "#{file_uri_for(lib_path("rack-0.8"))}", :branch => "main"
+ source "https://gem.repo1"
+ gem "myrack", :git => "#{lib_path("myrack-0.8")}", :branch => "main"
G
- bundle %(config set local.rack #{lib_path("local-rack")})
- bundle "update rack"
+ bundle %(config set local.myrack #{lib_path("local-myrack")})
+ bundle "update myrack"
expect(out).to include("Bundle updated!")
end
@@ -227,14 +227,14 @@ RSpec.describe "bundle update" do
build_git "rails", "2.3.2", path: lib_path("rails")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rails", :git => "#{file_uri_for(lib_path("rails"))}"
+ source "https://gem.repo1"
+ gem "rails", :git => "#{lib_path("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 #{file_uri_for(lib_path("rails"))} (at main@#{revision_for(lib_path("rails"))[0..6]})")
+ expect(out).to include("Using rails 3.0 (was 2.3.2) from #{lib_path("rails")} (at main@#{revision_for(lib_path("rails"))[0..6]})")
end
end
@@ -246,11 +246,11 @@ RSpec.describe "bundle update" do
end
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
git "#{lib_path("foo")}" do
gem 'foo'
end
- gem 'rack'
+ gem 'myrack'
G
end
@@ -279,7 +279,7 @@ RSpec.describe "bundle update" do
update_git "foo", path: @git.path
bundle "update --source foo"
- expect(the_bundle).to include_gems "rack 1.0"
+ expect(the_bundle).to include_gems "myrack 1.0"
end
end
@@ -289,11 +289,11 @@ RSpec.describe "bundle update" do
@git = build_git "foo", path: lib_path("bar")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo2)}"
+ source "https://gem.repo2"
git "#{lib_path("bar")}" do
gem 'foo'
end
- gem 'rack'
+ gem 'myrack'
G
end
@@ -309,9 +309,9 @@ RSpec.describe "bundle update" do
bundle "update --source bar"
- checksums = checksums_section_when_existing do |c|
+ checksums = checksums_section_when_enabled do |c|
c.no_checksum "foo", "2.0"
- c.checksum gem_repo2, "rack", "1.0.0"
+ c.checksum gem_repo2, "myrack", "1.0.0"
end
expect(lockfile).to eq <<~G
@@ -322,19 +322,19 @@ RSpec.describe "bundle update" do
foo (2.0)
GEM
- remote: #{file_uri_for(gem_repo2)}/
+ remote: https://gem.repo2/
specs:
- rack (1.0.0)
+ myrack (1.0.0)
PLATFORMS
#{lockfile_platforms}
DEPENDENCIES
foo!
- rack
+ myrack
#{checksums}
BUNDLED WITH
- #{Bundler::VERSION}
+ #{Bundler::VERSION}
G
end
end
diff --git a/spec/bundler/update/path_spec.rb b/spec/bundler/update/path_spec.rb
index 1f8992b33f..8c76c94e1a 100644
--- a/spec/bundler/update/path_spec.rb
+++ b/spec/bundler/update/path_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe "path sources" do
build_lib "activesupport", "2.3.5", path: lib_path("rails/activesupport")
install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
+ source "https://gem.repo1"
gem "activesupport", :path => "#{lib_path("rails/activesupport")}"
G
diff --git a/spec/bundler/update/redownload_spec.rb b/spec/bundler/update/redownload_spec.rb
deleted file mode 100644
index 4a8c711bfa..0000000000
--- a/spec/bundler/update/redownload_spec.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe "bundle update" do
- before :each do
- install_gemfile <<-G
- source "#{file_uri_for(gem_repo1)}"
- gem "rack"
- G
- end
-
- describe "with --force" do
- it "shows a deprecation when single flag passed", bundler: 2 do
- 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"
- 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"
- 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"
- expect(err).not_to include "[DEPRECATED] The `--force` option has been renamed to `--redownload`"
- end
-
- it "re-installs installed gems" do
- rack_lib = default_bundle_path("gems/rack-1.0.0/lib/rack.rb")
- rack_lib.open("w") {|f| f.write("blah blah blah") }
- bundle :update, redownload: true
-
- expect(out).to include "Installing rack 1.0.0"
- expect(rack_lib.open(&:read)).to eq("RACK = '1.0.0'\n")
- expect(the_bundle).to include_gems "rack 1.0.0"
- end
- end
-end
diff --git a/spec/default.mspec b/spec/default.mspec
index 57142d6dec..d756dc31ff 100644
--- a/spec/default.mspec
+++ b/spec/default.mspec
@@ -9,6 +9,7 @@ ENV["CHECK_CONSTANT_LEAKS"] ||= "true"
require "./rbconfig" unless defined?(RbConfig)
require_relative "../tool/test-coverage" if ENV.key?("COVERAGE")
+require_relative "../tool/lib/test/jobserver"
load File.dirname(__FILE__) + '/ruby/default.mspec'
OBJDIR = File.expand_path("spec/ruby/optional/capi/ext") unless defined?(OBJDIR)
class MSpecScript
@@ -34,7 +35,9 @@ class MSpecScript
# Disable to run for bundled gems in test-spec
set :bundled_gems, (File.readlines("#{srcdir}/gems/bundled_gems").map do |line|
next if /^\s*(?:#|$)/ =~ line
- "#{srcdir}/spec/ruby/library/" + line.split.first
+ gem = line.split.first
+ gem = "openstruct" if gem == "ostruct"
+ "#{srcdir}/spec/ruby/library/#{gem}"
end.compact)
set :stdlibs, Dir.glob("#{srcdir}/spec/ruby/library/*")
set :library, get(:stdlibs).to_a - get(:bundled_gems).to_a
@@ -48,34 +51,10 @@ end
module MSpecScript::JobServer
def cores(max = 1)
- if max > 1 and /(?:\A|\s)--jobserver-(?:auth|fds)=(\d+),(\d+)/ =~ ENV["MAKEFLAGS"]
- cores = 1
- begin
- r = IO.for_fd($1.to_i(10), "rb", autoclose: false)
- w = IO.for_fd($2.to_i(10), "wb", autoclose: false)
- jobtokens = r.read_nonblock(max - 1)
- cores = jobtokens.size
- if cores > 0
- cores += 1
- jobserver = w
- w = nil
- at_exit {
- jobserver.print(jobtokens)
- jobserver.close
- }
- MSpecScript::JobServer.module_eval do
- remove_method :cores
- define_method(:cores) do
- cores
- end
- end
- return cores
- end
- rescue Errno::EBADF
- ensure
- r&.close
- w&.close
- end
+ MSpecScript::JobServer.remove_method :cores
+ if cores = Test::JobServer.max_jobs(max)
+ MSpecScript::JobServer.define_method(:cores) { cores }
+ return cores
end
super
end
@@ -90,7 +69,7 @@ require 'mspec/runner/formatters/dotted'
class DottedFormatter
prepend Module.new {
BASE = __dir__ + "/ruby/" unless defined?(BASE)
- COUNT_WIDTH = 6
+ COUNT_WIDTH = 6 unless defined?(COUNT_WIDTH)
def initialize(out = nil)
super
diff --git a/spec/mmtk.mspec b/spec/mmtk.mspec
new file mode 100644
index 0000000000..ac0998708c
--- /dev/null
+++ b/spec/mmtk.mspec
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+# Testing behaviour specific to default GC
+MSpec.register(:exclude, "GC.stat increases major_gc_count after GC is run")
+MSpec.register(:exclude, "GC.stat provides some number for heap_free_slots")
+# GC::Profiler is not implemented
+MSpec.register(:exclude, "GC::Profiler.disable disables the profiler")
+MSpec.register(:exclude, "GC::Profiler.enable enables the profiler")
+MSpec.register(:exclude, "GC::Profiler.enabled? reports as disabled when disabled")
+MSpec.register(:exclude, "GC::Profiler.enabled? reports as enabled when enabled")
+MSpec.register(:exclude, "GC::Profiler.result returns a string")
+MSpec.register(:exclude, "GC::Profiler.total_time returns an float")
diff --git a/spec/mspec/lib/mspec/commands/mkspec.rb b/spec/mspec/lib/mspec/commands/mkspec.rb
index a31cb2191c..f75e683b19 100755..100644
--- a/spec/mspec/lib/mspec/commands/mkspec.rb
+++ b/spec/mspec/lib/mspec/commands/mkspec.rb
@@ -1,5 +1,3 @@
-#!/usr/bin/env ruby
-
require 'rbconfig'
require 'mspec/version'
require 'mspec/utils/options'
diff --git a/spec/mspec/lib/mspec/commands/mspec-ci.rb b/spec/mspec/lib/mspec/commands/mspec-ci.rb
index a31db1d7dc..8951572f69 100644
--- a/spec/mspec/lib/mspec/commands/mspec-ci.rb
+++ b/spec/mspec/lib/mspec/commands/mspec-ci.rb
@@ -1,7 +1,3 @@
-#!/usr/bin/env ruby
-
-$:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
-
require 'mspec/version'
require 'mspec/utils/options'
require 'mspec/utils/script'
@@ -22,6 +18,7 @@ class MSpecCI < MSpecScript
options.chdir
options.prefix
options.configure { |f| load f }
+ options.repeat
options.pretend
options.interrupt
options.timeout
diff --git a/spec/mspec/lib/mspec/commands/mspec-run.rb b/spec/mspec/lib/mspec/commands/mspec-run.rb
index 4d8f4d9984..0fb338fa23 100644
--- a/spec/mspec/lib/mspec/commands/mspec-run.rb
+++ b/spec/mspec/lib/mspec/commands/mspec-run.rb
@@ -1,7 +1,3 @@
-#!/usr/bin/env ruby
-
-$:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
-
require 'mspec/version'
require 'mspec/utils/options'
require 'mspec/utils/script'
@@ -32,6 +28,7 @@ class MSpecRun < MSpecScript
options.chdir
options.prefix
options.configure { |f| load f }
+ options.env
options.randomize
options.repeat
options.pretend
@@ -52,6 +49,9 @@ class MSpecRun < MSpecScript
options.doc "\n When to perform it"
options.action_filters
+ options.doc "\n Launchable"
+ options.launchable
+
options.doc "\n Help!"
options.debug
options.version MSpec::VERSION
diff --git a/spec/mspec/lib/mspec/commands/mspec-tag.rb b/spec/mspec/lib/mspec/commands/mspec-tag.rb
index e1d04d1446..8b1cb83809 100644
--- a/spec/mspec/lib/mspec/commands/mspec-tag.rb
+++ b/spec/mspec/lib/mspec/commands/mspec-tag.rb
@@ -1,5 +1,3 @@
-#!/usr/bin/env ruby
-
require 'mspec/version'
require 'mspec/utils/options'
require 'mspec/utils/script'
diff --git a/spec/mspec/lib/mspec/commands/mspec.rb b/spec/mspec/lib/mspec/commands/mspec.rb
index f5341c699d..a9d94ca354 100755..100644
--- a/spec/mspec/lib/mspec/commands/mspec.rb
+++ b/spec/mspec/lib/mspec/commands/mspec.rb
@@ -1,5 +1,3 @@
-#!/usr/bin/env ruby
-
require 'mspec/version'
require 'mspec/utils/options'
require 'mspec/utils/script'
diff --git a/spec/mspec/lib/mspec/guards/platform.rb b/spec/mspec/lib/mspec/guards/platform.rb
index e87b08a4c1..fadd8d75ef 100644
--- a/spec/mspec/lib/mspec/guards/platform.rb
+++ b/spec/mspec/lib/mspec/guards/platform.rb
@@ -53,16 +53,27 @@ class PlatformGuard < SpecGuard
end
end
+ # In bits
WORD_SIZE = 1.size * 8
+ deprecate_constant :WORD_SIZE
+ # In bits
POINTER_SIZE = begin
require 'rbconfig/sizeof'
RbConfig::SIZEOF["void*"] * 8
rescue LoadError
- WORD_SIZE
+ [0].pack('j').size * 8
+ end
+
+ # In bits
+ C_LONG_SIZE = if defined?(RbConfig::SIZEOF[])
+ RbConfig::SIZEOF["long"] * 8
+ else
+ [0].pack('l!').size * 8
end
def self.wordsize?(size)
+ warn "#wordsize? is deprecated, use #c_long_size?"
size == WORD_SIZE
end
@@ -70,6 +81,10 @@ class PlatformGuard < SpecGuard
size == POINTER_SIZE
end
+ def self.c_long_size?(size)
+ size == C_LONG_SIZE
+ end
+
def initialize(*args)
if args.last.is_a?(Hash)
@options, @platforms = args.last, args[0..-2]
@@ -85,10 +100,13 @@ class PlatformGuard < SpecGuard
case key
when :os
match &&= PlatformGuard.os?(*value)
- when :wordsize
- match &&= PlatformGuard.wordsize? value
when :pointer_size
match &&= PlatformGuard.pointer_size? value
+ when :wordsize
+ warn ":wordsize is deprecated, use :c_long_size"
+ match &&= PlatformGuard.wordsize? value
+ when :c_long_size
+ match &&= PlatformGuard::c_long_size? value
end
end
match
diff --git a/spec/mspec/lib/mspec/helpers/numeric.rb b/spec/mspec/lib/mspec/helpers/numeric.rb
index c1ed81a233..0b47855cd2 100644
--- a/spec/mspec/lib/mspec/helpers/numeric.rb
+++ b/spec/mspec/lib/mspec/helpers/numeric.rb
@@ -1,3 +1,4 @@
+# frozen_string_literal: true
require 'mspec/guards/platform'
def nan_value
@@ -15,11 +16,11 @@ def bignum_value(plus = 0)
end
def max_long
- 2**(0.size * 8 - 1) - 1
+ 2**(PlatformGuard::C_LONG_SIZE - 1) - 1
end
def min_long
- -(2**(0.size * 8 - 1))
+ -(2**(PlatformGuard::C_LONG_SIZE - 1))
end
# This is a bit hairy, but we need to be able to write specs that cover the
@@ -28,7 +29,24 @@ end
# specs based on the relationship between values rather than specific
# values.
if PlatformGuard.standard? or PlatformGuard.implementation? :topaz
- if PlatformGuard.wordsize? 32
+ limits_available = begin
+ require 'rbconfig/sizeof'
+ defined?(RbConfig::LIMITS.[]) && ['FIXNUM_MAX', 'FIXNUM_MIN'].all? do |key|
+ Integer === RbConfig::LIMITS[key]
+ end
+ rescue LoadError
+ false
+ end
+
+ if limits_available
+ def fixnum_max
+ RbConfig::LIMITS['FIXNUM_MAX']
+ end
+
+ def fixnum_min
+ RbConfig::LIMITS['FIXNUM_MIN']
+ end
+ elsif PlatformGuard.c_long_size? 32
def fixnum_max
(2**30) - 1
end
@@ -36,7 +54,7 @@ if PlatformGuard.standard? or PlatformGuard.implementation? :topaz
def fixnum_min
-(2**30)
end
- elsif PlatformGuard.wordsize? 64
+ elsif PlatformGuard.c_long_size? 64
def fixnum_max
(2**62) - 1
end
diff --git a/spec/mspec/lib/mspec/helpers/tmp.rb b/spec/mspec/lib/mspec/helpers/tmp.rb
index 4c0eddab75..e903dd9f50 100644
--- a/spec/mspec/lib/mspec/helpers/tmp.rb
+++ b/spec/mspec/lib/mspec/helpers/tmp.rb
@@ -36,7 +36,20 @@ all specs are cleaning up temporary files:
end
def tmp(name, uniquify = true)
- mkdir_p SPEC_TEMP_DIR unless Dir.exist? SPEC_TEMP_DIR
+ if Dir.exist? SPEC_TEMP_DIR
+ stat = File.stat(SPEC_TEMP_DIR)
+ if stat.world_writable? and !stat.sticky?
+ raise ArgumentError, "SPEC_TEMP_DIR (#{SPEC_TEMP_DIR}) is world writable but not sticky"
+ end
+ else
+ platform_is_not :windows do
+ umask = File.umask
+ if (umask & 0002) == 0 # o+w
+ raise ArgumentError, "File.umask #=> #{umask.to_s(8)} (world-writable)"
+ end
+ end
+ mkdir_p SPEC_TEMP_DIR
+ end
if uniquify and !name.empty?
slash = name.rindex "/"
diff --git a/spec/mspec/lib/mspec/runner/actions/leakchecker.rb b/spec/mspec/lib/mspec/runner/actions/leakchecker.rb
index 71797b9815..0a8c9c3252 100644
--- a/spec/mspec/lib/mspec/runner/actions/leakchecker.rb
+++ b/spec/mspec/lib/mspec/runner/actions/leakchecker.rb
@@ -132,14 +132,14 @@ class LeakChecker
attr_accessor :count
end
- def new(data)
+ def new(...)
LeakChecker::TempfileCounter.count += 1
- super(data)
+ super
end
}
LeakChecker.const_set(:TempfileCounter, m)
- class << Tempfile::Remover
+ class << Tempfile
prepend LeakChecker::TempfileCounter
end
end
diff --git a/spec/mspec/lib/mspec/runner/formatters/launchable.rb b/spec/mspec/lib/mspec/runner/formatters/launchable.rb
new file mode 100644
index 0000000000..f738781c71
--- /dev/null
+++ b/spec/mspec/lib/mspec/runner/formatters/launchable.rb
@@ -0,0 +1,88 @@
+module LaunchableFormatter
+ def self.extend_object(obj)
+ super
+ obj.init
+ end
+
+ def self.setDir(dir)
+ @@path = File.join(dir, "#{rand.to_s}.json")
+ self
+ end
+
+ def init
+ @timer = nil
+ @tests = []
+ end
+
+ def before(state = nil)
+ super
+ @timer = TimerAction.new
+ @timer.start
+ end
+
+ def after(state = nil)
+ super
+ @timer.finish
+ file = MSpec.file
+ return if file.nil? || state&.example.nil? || exception?
+
+ @tests << {:test => state, :file => file, :exception => false, duration: @timer.elapsed}
+ end
+
+ def exception(exception)
+ super
+ @timer.finish
+ file = MSpec.file
+ return if file.nil?
+
+ @tests << {:test => exception, :file => file, :exception => true, duration: @timer.elapsed}
+ end
+
+ def finish
+ super
+
+ require_relative '../../../../../../tool/lib/launchable'
+
+ @writer = writer = Launchable::JsonStreamWriter.new(@@path)
+ @writer.write_array('testCases')
+ at_exit {
+ @writer.close
+ }
+
+ repo_path = File.expand_path("#{__dir__}/../../../../../../")
+
+ @tests.each do |t|
+ testcase = t[:test].description
+ relative_path = t[:file].delete_prefix("#{repo_path}/")
+ # The test path is a URL-encoded representation.
+ # https://github.com/launchableinc/cli/blob/v1.81.0/launchable/testpath.py#L18
+ test_path = {file: relative_path, testcase: testcase}.map{|key, val|
+ "#{encode_test_path_component(key)}=#{encode_test_path_component(val)}"
+ }.join('#')
+
+ status = 'TEST_PASSED'
+ if t[:exception]
+ message = t[:test].message
+ backtrace = t[:test].backtrace
+ e = "#{message}\n#{backtrace}"
+ status = 'TEST_FAILED'
+ end
+
+ @writer.write_object(
+ {
+ testPath: test_path,
+ status: status,
+ duration: t[:duration],
+ createdAt: Time.now.to_s,
+ stderr: e,
+ stdout: nil
+ }
+ )
+ end
+ end
+
+ private
+ def encode_test_path_component component
+ component.to_s.gsub('%', '%25').gsub('=', '%3D').gsub('#', '%23').gsub('&', '%26').tr("\x00-\x08", "")
+ end
+end
diff --git a/spec/mspec/lib/mspec/runner/formatters/multi.rb b/spec/mspec/lib/mspec/runner/formatters/multi.rb
index a723ae8eb9..fa1da3766b 100644
--- a/spec/mspec/lib/mspec/runner/formatters/multi.rb
+++ b/spec/mspec/lib/mspec/runner/formatters/multi.rb
@@ -42,6 +42,6 @@ module MultiFormatter
end
def print_exception(exc, count)
- print "\n#{count})\n#{exc}\n"
+ @err.print "\n#{count})\n#{exc}\n"
end
end
diff --git a/spec/mspec/lib/mspec/utils/name_map.rb b/spec/mspec/lib/mspec/utils/name_map.rb
index bf70e651a2..9b04112e2e 100644
--- a/spec/mspec/lib/mspec/utils/name_map.rb
+++ b/spec/mspec/lib/mspec/utils/name_map.rb
@@ -66,10 +66,17 @@ class NameMap
end
def class_or_module(c)
- const = Object.const_get(c, false)
+ begin
+ const = Object.const_get(c, false)
+ rescue NameError, RuntimeError
+ # Either the constant doesn't exist or it is
+ # explicitly raising an error, like `SortedSet`.
+ return nil
+ end
+ return nil unless Module === const
+
filtered = @filter && EXCLUDED.include?(const.name)
- return const if Module === const and !filtered
- rescue NameError
+ return const unless filtered
end
def namespace(mod, const)
diff --git a/spec/mspec/lib/mspec/utils/options.rb b/spec/mspec/lib/mspec/utils/options.rb
index 3b5962dbe6..adeafa1f81 100644
--- a/spec/mspec/lib/mspec/utils/options.rb
+++ b/spec/mspec/lib/mspec/utils/options.rb
@@ -204,6 +204,13 @@ class MSpecOptions
"Load FILE containing configuration options", &block)
end
+ def env
+ on("--env", "KEY=VALUE", "Set environment variable") do |env|
+ key, value = env.split('=', 2)
+ ENV[key] = value
+ end
+ end
+
def targets
on("-t", "--target", "TARGET",
"Implementation to run the specs, where TARGET is:") do |t|
@@ -482,8 +489,17 @@ class MSpecOptions
end
end
+ def launchable
+ on("--launchable-test-reports", "DIR",
+ "DIR The directory for reporting test results in Launchable JSON format") do |o|
+ require 'mspec/runner/formatters/launchable'
+ config[:launchable] = LaunchableFormatter.setDir(o)
+ end
+ end
+
def all
configure {}
+ env
targets
formatters
filters
@@ -500,5 +516,6 @@ class MSpecOptions
action_filters
actions
debug
+ launchable
end
end
diff --git a/spec/mspec/lib/mspec/utils/script.rb b/spec/mspec/lib/mspec/utils/script.rb
index e86beaab86..15fd23fabf 100644
--- a/spec/mspec/lib/mspec/utils/script.rb
+++ b/spec/mspec/lib/mspec/utils/script.rb
@@ -159,8 +159,14 @@ class MSpecScript
end
if config[:formatter]
- config[:formatter].new(config[:output])
+ config[:formatter] = config[:formatter].new(config[:output])
end
+
+ if config[:launchable]
+ config[:formatter].extend config[:launchable]
+ end
+
+ config[:formatter]
end
# Callback for enabling custom actions, etc. This version is a
diff --git a/spec/mspec/spec/commands/mspec_ci_spec.rb b/spec/mspec/spec/commands/mspec_ci_spec.rb
index bcbc5b4224..b8dc9d062f 100644
--- a/spec/mspec/spec/commands/mspec_ci_spec.rb
+++ b/spec/mspec/spec/commands/mspec_ci_spec.rb
@@ -78,6 +78,11 @@ RSpec.describe MSpecCI, "#options" do
@script.options []
end
+ it "enables the repeat option" do
+ expect(@options).to receive(:repeat)
+ @script.options @argv
+ end
+
it "calls #custom_options" do
expect(@script).to receive(:custom_options).with(@options)
@script.options []
diff --git a/spec/mspec/spec/commands/mspec_run_spec.rb b/spec/mspec/spec/commands/mspec_run_spec.rb
index 62acd49d7f..f96be2b43e 100644
--- a/spec/mspec/spec/commands/mspec_run_spec.rb
+++ b/spec/mspec/spec/commands/mspec_run_spec.rb
@@ -105,6 +105,11 @@ RSpec.describe MSpecRun, "#options" do
@script.options @argv
end
+ it "enables the repeat option" do
+ expect(@options).to receive(:repeat)
+ @script.options @argv
+ end
+
it "exits if there are no files to process and './spec' is not a directory" do
expect(File).to receive(:directory?).with("./spec").and_return(false)
expect(@options).to receive(:parse).and_return([])
diff --git a/spec/mspec/spec/guards/platform_spec.rb b/spec/mspec/spec/guards/platform_spec.rb
index 88a7ad86f2..bd37432800 100644
--- a/spec/mspec/spec/guards/platform_spec.rb
+++ b/spec/mspec/spec/guards/platform_spec.rb
@@ -81,44 +81,44 @@ RSpec.describe Object, "#platform_is_not" do
end
end
-RSpec.describe Object, "#platform_is :wordsize => SIZE_SPEC" do
+RSpec.describe Object, "#platform_is :c_long_size => SIZE_SPEC" do
before :each do
- @guard = PlatformGuard.new :darwin, :wordsize => 32
+ @guard = PlatformGuard.new :darwin, :c_long_size => 32
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
- allow(PlatformGuard).to receive(:wordsize?).and_return(true)
- platform_is(:wordsize => 32) { ScratchPad.record :yield }
+ it "yields when #c_long_size? returns true" do
+ allow(PlatformGuard).to receive(:c_long_size?).and_return(true)
+ platform_is(:c_long_size => 32) { ScratchPad.record :yield }
expect(ScratchPad.recorded).to eq(:yield)
end
- it "doesn not yield when #wordsize? returns false" do
- allow(PlatformGuard).to receive(:wordsize?).and_return(false)
- platform_is(:wordsize => 32) { ScratchPad.record :yield }
+ it "doesn not yield when #c_long_size? returns false" do
+ allow(PlatformGuard).to receive(:c_long_size?).and_return(false)
+ platform_is(:c_long_size => 32) { ScratchPad.record :yield }
expect(ScratchPad.recorded).not_to eq(:yield)
end
end
-RSpec.describe Object, "#platform_is_not :wordsize => SIZE_SPEC" do
+RSpec.describe Object, "#platform_is_not :c_long_size => SIZE_SPEC" do
before :each do
- @guard = PlatformGuard.new :darwin, :wordsize => 32
+ @guard = PlatformGuard.new :darwin, :c_long_size => 32
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
- allow(PlatformGuard).to receive(:wordsize?).and_return(false)
- platform_is_not(:wordsize => 32) { ScratchPad.record :yield }
+ it "yields when #c_long_size? returns false" do
+ allow(PlatformGuard).to receive(:c_long_size?).and_return(false)
+ platform_is_not(:c_long_size => 32) { ScratchPad.record :yield }
expect(ScratchPad.recorded).to eq(:yield)
end
- it "doesn not yield when #wordsize? returns true" do
- allow(PlatformGuard).to receive(:wordsize?).and_return(true)
- platform_is_not(:wordsize => 32) { ScratchPad.record :yield }
+ it "doesn not yield when #c_long_size? returns true" do
+ allow(PlatformGuard).to receive(:c_long_size?).and_return(true)
+ platform_is_not(:c_long_size => 32) { ScratchPad.record :yield }
expect(ScratchPad.recorded).not_to eq(:yield)
end
end
@@ -184,13 +184,13 @@ RSpec.describe PlatformGuard, ".standard?" do
end
end
-RSpec.describe PlatformGuard, ".wordsize?" do
+RSpec.describe PlatformGuard, ".c_long_size?" do
it "returns true when arg is 32 and 1.size is 4" do
- expect(PlatformGuard.wordsize?(32)).to eq(1.size == 4)
+ expect(PlatformGuard.c_long_size?(32)).to eq(1.size == 4)
end
it "returns true when arg is 64 and 1.size is 8" do
- expect(PlatformGuard.wordsize?(64)).to eq(1.size == 8)
+ expect(PlatformGuard.c_long_size?(64)).to eq(1.size == 8)
end
end
diff --git a/spec/mspec/spec/utils/fixtures/this_file_raises.rb b/spec/mspec/spec/utils/fixtures/this_file_raises.rb
new file mode 100644
index 0000000000..8e37a587bf
--- /dev/null
+++ b/spec/mspec/spec/utils/fixtures/this_file_raises.rb
@@ -0,0 +1 @@
+raise "This is a BAD file"
diff --git a/spec/mspec/spec/utils/fixtures/this_file_raises2.rb b/spec/mspec/spec/utils/fixtures/this_file_raises2.rb
new file mode 100644
index 0000000000..8efc10199a
--- /dev/null
+++ b/spec/mspec/spec/utils/fixtures/this_file_raises2.rb
@@ -0,0 +1 @@
+raise "This is a BAD file 2"
diff --git a/spec/mspec/spec/utils/name_map_spec.rb b/spec/mspec/spec/utils/name_map_spec.rb
index a18a481500..a42dc9ffec 100644
--- a/spec/mspec/spec/utils/name_map_spec.rb
+++ b/spec/mspec/spec/utils/name_map_spec.rb
@@ -21,6 +21,9 @@ module NameMapSpecs
def f; end
end
+ autoload :BadFile, "#{__dir__}/fixtures/this_file_raises.rb"
+ autoload :BadFile2, "#{__dir__}/fixtures/this_file_raises2.rb"
+
def self.n; end
def n; end
end
@@ -84,6 +87,15 @@ RSpec.describe NameMap, "#class_or_module" do
expect(@map.class_or_module("Hell")).to eq(nil)
expect(@map.class_or_module("Bush::Brain")).to eq(nil)
end
+
+ it "returns nil if accessing the constant raises RuntimeError" do
+ expect { NameMapSpecs::BadFile }.to raise_error(RuntimeError)
+ expect(@map.class_or_module("NameMapSpecs::BadFile")).to eq(nil)
+ end
+
+ it "returns nil if accessing the constant raises RuntimeError when not triggering the autoload before" do
+ expect(@map.class_or_module("NameMapSpecs::BadFile2")).to eq(nil)
+ end
end
RSpec.describe NameMap, "#dir_name" do
diff --git a/spec/mspec/tool/remove_old_guards.rb b/spec/mspec/tool/remove_old_guards.rb
index 3fd95e6b31..75c48e0584 100644..100755
--- a/spec/mspec/tool/remove_old_guards.rb
+++ b/spec/mspec/tool/remove_old_guards.rb
@@ -1,6 +1,23 @@
+#!/usr/bin/env ruby
+
# Removes old version guards in ruby/spec.
# Run it from the ruby/spec repository root.
# The argument is the new minimum supported version.
+#
+# cd spec
+# ../mspec/tool/remove_old_guards.rb <ruby-version>
+#
+# where <ruby-version> is a version guard with which should be removed
+#
+# Example:
+# tool/remove_old_guards.rb 3.1
+#
+# As a result guards like
+# ruby_version_is "3.1" do
+# # ...
+# end
+#
+# will be removed.
def dedent(line)
if line.start_with?(" ")
@@ -105,6 +122,8 @@ def search(regexp)
end
end
+abort "usage: #{$0} <ruby-version>" if ARGV.empty?
+
version = Regexp.escape(ARGV.fetch(0))
version += "(?:\\.0)?" if version.count(".") < 2
remove_guards(/ruby_version_is (["'])#{version}\1 do/, true)
diff --git a/spec/mspec/tool/sync/sync-rubyspec.rb b/spec/mspec/tool/sync/sync-rubyspec.rb
index 13f1d8004d..617123733e 100644
--- a/spec/mspec/tool/sync/sync-rubyspec.rb
+++ b/spec/mspec/tool/sync/sync-rubyspec.rb
@@ -3,7 +3,7 @@
IMPLS = {
truffleruby: {
- git: "https://github.com/oracle/truffleruby.git",
+ git: "https://github.com/truffleruby/truffleruby.git",
from_commit: "f10ab6988d",
},
jruby: {
@@ -23,6 +23,8 @@ MSPEC = ARGV.delete('--mspec')
CHECK_LAST_MERGE = !MSPEC && ENV['CHECK_LAST_MERGE'] != 'false'
TEST_MASTER = ENV['TEST_MASTER'] != 'false'
+ONLY_FILTER = ENV['ONLY_FILTER'] == 'true'
+
MSPEC_REPO = File.expand_path("../../..", __FILE__)
raise MSPEC_REPO if !Dir.exist?(MSPEC_REPO) or !Dir.exist?("#{MSPEC_REPO}/.git")
@@ -32,6 +34,13 @@ raise RUBYSPEC_REPO unless Dir.exist?(RUBYSPEC_REPO)
SOURCE_REPO = MSPEC ? MSPEC_REPO : RUBYSPEC_REPO
+# LAST_MERGE is a commit of ruby/spec or ruby/mspec
+# which is the spec/mspec commit that was last imported in the Ruby implementation
+# (i.e. the commit in "Update to ruby/spec@commit").
+# It is normally automatically computed, but can be manually set when
+# e.g. the last update of specs wasn't merged in the Ruby implementation.
+LAST_MERGE = ENV["LAST_MERGE"]
+
NOW = Time.now
BRIGHT_RED = "\e[31;1m"
@@ -140,8 +149,8 @@ def rebase_commits(impl)
else
sh "git", "checkout", impl.name
- if ENV["LAST_MERGE"]
- last_merge = `git log -n 1 --format='%H %ct' #{ENV["LAST_MERGE"]}`
+ if LAST_MERGE
+ last_merge = `git log -n 1 --format='%H %ct' #{LAST_MERGE}`
else
last_merge = `git log --grep='^#{impl.last_merge_message}' -n 1 --format='%H %ct'`
end
@@ -230,15 +239,17 @@ def main(impls)
impl = RubyImplementation.new(impl, data)
update_repo(impl)
filter_commits(impl)
- rebase_commits(impl)
- 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)
+ unless ONLY_FILTER
+ rebase_commits(impl)
+ 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
end
diff --git a/spec/ruby/.mspec.constants b/spec/ruby/.mspec.constants
index 6e09a44362..4da3633715 100644
--- a/spec/ruby/.mspec.constants
+++ b/spec/ruby/.mspec.constants
@@ -146,6 +146,7 @@ Prime
Private
ProcFromMethod
Psych
+RactorLocalSingleton
REXML
RUBY_SIGNALS
RbReadline
diff --git a/spec/ruby/.rubocop.yml b/spec/ruby/.rubocop.yml
index be32ce8900..0b59a11512 100644
--- a/spec/ruby/.rubocop.yml
+++ b/spec/ruby/.rubocop.yml
@@ -1,13 +1,17 @@
inherit_from: .rubocop_todo.yml
AllCops:
- TargetRubyVersion: 3.0
+ TargetRubyVersion: 3.2
DisplayCopNames: true
Exclude:
- command_line/fixtures/bad_syntax.rb
+ - core/exception/fixtures/syntax_error.rb
DisabledByDefault: true
NewCops: disable
+Layout/IndentationConsistency:
+ Enabled: true
+
Layout/TrailingWhitespace:
Enabled: true
@@ -43,9 +47,23 @@ Lint/InterpolationCheck:
Lint/LiteralAsCondition:
Enabled: false
+# Required to support Ruby 3.0
+Lint/RedundantRequireStatement:
+ Exclude:
+ - core/fiber/**/*.rb
+ - library/fiber/**/*.rb
+ - optional/capi/fiber_spec.rb
+
+Lint/RedundantSafeNavigation:
+ Exclude:
+ - language/safe_navigator_spec.rb
+
Lint/RedundantSplatExpansion:
Enabled: false
+Lint/RescueException:
+ Enabled: false
+
Lint/UnifiedInteger:
Enabled: false
@@ -179,6 +197,7 @@ Style/Lambda:
- 'language/lambda_spec.rb'
- 'language/proc_spec.rb'
- 'language/numbered_parameters_spec.rb'
+ - 'language/it_parameter_spec.rb'
- 'core/kernel/lambda_spec.rb'
Style/EmptyLambdaParameter:
diff --git a/spec/ruby/.rubocop_todo.yml b/spec/ruby/.rubocop_todo.yml
index 3ebb23a8bb..bd30f3f14a 100644
--- a/spec/ruby/.rubocop_todo.yml
+++ b/spec/ruby/.rubocop_todo.yml
@@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
-# on 2019-12-12 22:16:26 +0900 using RuboCop version 0.77.0.
+# on 2024-10-12 16:01:45 UTC using RuboCop version 1.66.1.
# 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
@@ -21,6 +21,7 @@ Lint/DuplicateMethods:
- 'fixtures/class.rb'
# Offense count: 8
+# This cop supports safe autocorrection (--autocorrect).
Lint/EnsureReturn:
Exclude:
- 'language/fixtures/ensure.rb'
@@ -39,9 +40,11 @@ Lint/FloatOutOfRange:
- 'core/string/modulo_spec.rb'
# Offense count: 2
+# This cop supports safe autocorrection (--autocorrect).
Lint/ImplicitStringConcatenation:
Exclude:
- 'language/string_spec.rb'
+ - 'core/string/chilled_string_spec.rb'
# Offense count: 4
Lint/IneffectiveAccessModifier:
@@ -50,8 +53,8 @@ Lint/IneffectiveAccessModifier:
- 'core/module/fixtures/classes.rb'
- 'language/fixtures/private.rb'
-# Offense count: 72
-# Cop supports --auto-correct.
+# Offense count: 71
+# This cop supports safe autocorrection (--autocorrect).
Lint/LiteralInInterpolation:
Exclude:
- 'core/module/refine_spec.rb'
@@ -65,47 +68,28 @@ Lint/LiteralInInterpolation:
- 'language/undef_spec.rb'
# Offense count: 8
-# Cop supports --auto-correct.
+# This cop supports safe autocorrection (--autocorrect).
Lint/MultipleComparison:
Exclude:
- 'language/precedence_spec.rb'
# Offense count: 9
+# This cop supports safe autocorrection (--autocorrect).
Lint/ParenthesesAsGroupedExpression:
Exclude:
- - 'core/string/fixtures/freeze_magic_comment.rb'
- 'language/block_spec.rb'
- - 'language/fixtures/send.rb'
- 'language/method_spec.rb'
# Offense count: 2
-# Cop supports --auto-correct.
+# This cop supports safe autocorrection (--autocorrect).
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: 22
-Lint/RescueException:
+Lint/SelfAssignment:
Exclude:
- - 'command_line/fixtures/debug_info.rb'
- - 'core/dir/fileno_spec.rb'
- - 'core/exception/cause_spec.rb'
- - 'core/exception/no_method_error_spec.rb'
- - 'core/fiber/kill_spec.rb'
- - 'core/kernel/fixtures/autoload_frozen.rb'
- - 'core/kernel/raise_spec.rb'
- - 'core/module/autoload_spec.rb'
- - 'core/mutex/sleep_spec.rb'
- - 'core/thread/abort_on_exception_spec.rb'
- - 'core/thread/shared/exit.rb'
- - 'language/rescue_spec.rb'
- - 'library/erb/filename_spec.rb'
+ - 'core/gc/auto_compact_spec.rb'
# Offense count: 4
# Configuration parameters: IgnoreImplicitReferences.
@@ -113,8 +97,8 @@ Lint/ShadowedArgument:
Exclude:
- 'language/fixtures/super.rb'
-# Offense count: 39
-# Configuration parameters: AllowComments.
+# Offense count: 45
+# Configuration parameters: AllowComments, AllowNil.
Lint/SuppressedException:
Enabled: false
@@ -127,7 +111,8 @@ Lint/UnderscorePrefixedVariableName:
- 'language/block_spec.rb'
# Offense count: 7
-# Configuration parameters: ContextCreatingMethods, MethodCreatingMethods.
+# This cop supports safe autocorrection (--autocorrect).
+# Configuration parameters: AutoCorrect, ContextCreatingMethods, MethodCreatingMethods.
Lint/UselessAccessModifier:
Exclude:
- 'core/module/define_method_spec.rb'
diff --git a/spec/ruby/CONTRIBUTING.md b/spec/ruby/CONTRIBUTING.md
index c82eb5ea4f..366b484bad 100644
--- a/spec/ruby/CONTRIBUTING.md
+++ b/spec/ruby/CONTRIBUTING.md
@@ -113,9 +113,9 @@ Also `have_constant`, `have_private_instance_method`, `have_singleton_method`, e
}
```
-##### should_not raise_error
+##### `should_not raise_error`
-**To avoid!** Instead, use an expectation testing what the code in the lambda does.
+**Avoid this!** Instead, use an expectation testing what the code in the lambda does.
If an exception is raised, it will fail the example anyway.
```ruby
@@ -164,7 +164,7 @@ end
platform_is_not :linux, :darwin do # Not Linux and not Darwin
end
-platform_is wordsize: 64 do
+platform_is pointer_size: 64 do
# 64-bit platform
end
@@ -179,7 +179,9 @@ In case there is a bug in MRI and the fix will be backported to previous version
If it is not backported or not likely, use `ruby_version_is` instead.
First, file a bug at https://bugs.ruby-lang.org/.
The problem is `ruby_bug` would make non-MRI implementations fail this spec while MRI itself does not pass it, so it should only be used if the bug is/will be fixed and backported.
-Otherwise, non-MRI implementations would have to choose between being incompatible with the latest release of MRI to pass the spec or fail the spec, both which make no sense.
+Otherwise, non-MRI implementations would have to choose between being incompatible with the latest release of MRI (which has the bug) to pass the spec, or behave the same as the latest release of MRI (which has the bug) and fail the spec, both which make no sense.
+
+IOW, `ruby_bug '#NN', ''...'X.Y' do` is equivalent to `guard_not { RUBY_ENGINE == "ruby" && ruby_version_is ''...'X.Y' } do`. So it skips tests on MRI on specified versions (where a bug is present) and runs tests on alternative implementations only.
```ruby
ruby_bug '#13669', ''...'3.2' do
@@ -277,13 +279,13 @@ describe :kernel_sprintf, shared: true do
end
describe "Kernel#sprintf" do
- it_behaves_like :kernel_sprintf, -> (format, *args) {
+ it_behaves_like :kernel_sprintf, -> format, *args {
sprintf(format, *args)
}
end
describe "Kernel.sprintf" do
- it_behaves_like :kernel_sprintf, -> (format, *args) {
+ it_behaves_like :kernel_sprintf, -> format, *args {
Kernel.sprintf(format, *args)
}
end
diff --git a/spec/ruby/README.md b/spec/ruby/README.md
index 115392835f..674ada4c9e 100644
--- a/spec/ruby/README.md
+++ b/spec/ruby/README.md
@@ -26,16 +26,16 @@ ruby/spec is known to be tested in these implementations for every commit:
* [MRI](https://rubyci.org/) on 30 platforms and 4 versions
* [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)
+* [TruffleRuby](https://github.com/truffleruby/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 3.0 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 (3.0.x, 3.1.x, 3.2.x, etc), and those are tested in CI.
+ruby/spec describes the behavior of Ruby 3.2 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 (3.2.x, 3.3.x, etc), and those are tested in CI.
### 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 @andrykonchin 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.
@@ -44,7 +44,7 @@ For *testing* the development version of a Ruby implementation, one should alway
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 on a Ruby implementation can be done with:
-```
+```console
$ cd ruby_implementation/spec/ruby
# Add ../ruby_implementation/bin in PATH, or pass -t /path/to/bin/ruby
$ ../mspec/bin/mspec
@@ -62,6 +62,8 @@ For older specs try these commits:
* Ruby 2.5.9 - [Suite](https://github.com/ruby/spec/commit/c503335d3d9f6ec6ef24de60a0716c34af69b64f) using [MSpec](https://github.com/ruby/mspec/commit/0091e8a62e954717cd54641f935eaf1403692041)
* Ruby 2.6.10 - [Suite](https://github.com/ruby/spec/commit/aaf998fb8c92c4e63ad423a2e7ca6e6921818c6e) using [MSpec](https://github.com/ruby/mspec/commit/5e36c684e9e2b92b1187589bba1df22c640a8661)
* Ruby 2.7.8 - [Suite](https://github.com/ruby/spec/commit/93787e6035c925b593a9c0c6fb0e7e07a6f1df1f) using [MSpec](https://github.com/ruby/mspec/commit/1d8cf64722d8a7529f7cd205be5f16a89b7a67fd)
+* Ruby 3.0.7 - [Suite](https://github.com/ruby/spec/commit/affef93d9940f615e4836f64b011da211f570913) using [MSpec](https://github.com/ruby/mspec/commit/0aabb3e548eb5ea6cad0125f8f46cee34542b6b7)
+* Ruby 3.1.6 - [Suite](https://github.com/ruby/spec/commit/ec960f2389d1c2265d32397fa8afa6d462014efc) using [MSpec](https://github.com/ruby/mspec/commit/484310dbed35b84c74484fd674602f88c42d063a)
### Running the specs
diff --git a/spec/ruby/bin/rubocop b/spec/ruby/bin/rubocop
new file mode 100755
index 0000000000..38254f13e4
--- /dev/null
+++ b/spec/ruby/bin/rubocop
@@ -0,0 +1,12 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+require 'bundler/inline'
+
+gemfile do
+ source 'https://rubygems.org'
+
+ gem 'rubocop', '1.66.1'
+end
+
+exec(Gem.bin_path('rubocop', 'rubocop'), *ARGV)
diff --git a/spec/ruby/command_line/dash_0_spec.rb b/spec/ruby/command_line/dash_0_spec.rb
new file mode 100755
index 0000000000..2ce4f49b5e
--- /dev/null
+++ b/spec/ruby/command_line/dash_0_spec.rb
@@ -0,0 +1,13 @@
+require_relative '../spec_helper'
+
+describe "The -0 command line option" do
+ it "sets $/ and $-0" do
+ ruby_exe("puts $/, $-0", options: "-072").should == ":\n:\n"
+ end
+
+ ruby_version_is "4.0" do
+ it "sets $/ and $-0 as a frozen string" do
+ ruby_exe("puts $/.frozen?, $-0.frozen?", options: "-072").should == "true\ntrue\n"
+ end
+ end
+end
diff --git a/spec/ruby/command_line/dash_upper_u_spec.rb b/spec/ruby/command_line/dash_upper_u_spec.rb
index 15854e7b73..2c210eb603 100644
--- a/spec/ruby/command_line/dash_upper_u_spec.rb
+++ b/spec/ruby/command_line/dash_upper_u_spec.rb
@@ -2,8 +2,8 @@ require_relative '../spec_helper'
describe "ruby -U" do
it "sets Encoding.default_internal to UTF-8" do
- ruby_exe('print Encoding.default_internal.name',
- options: '-U').should == 'UTF-8'
+ ruby_exe('print Encoding.default_internal.name',
+ options: '-U').should == 'UTF-8'
end
it "sets Encoding.default_internal to UTF-8 when RUBYOPT is empty or only spaces" do
@@ -14,25 +14,25 @@ describe "ruby -U" do
end
it "does nothing different if specified multiple times" do
- ruby_exe('print Encoding.default_internal.name',
- options: '-U -U').should == 'UTF-8'
+ ruby_exe('print Encoding.default_internal.name',
+ options: '-U -U').should == 'UTF-8'
end
it "is overruled by Encoding.default_internal=" do
- ruby_exe('Encoding.default_internal="ascii"; print Encoding.default_internal.name',
- options: '-U').should == 'US-ASCII'
+ ruby_exe('Encoding.default_internal="ascii"; print Encoding.default_internal.name',
+ options: '-U').should == 'US-ASCII'
end
it "does not affect the default external encoding" do
- ruby_exe('Encoding.default_external="ascii"; print Encoding.default_external.name',
- options: '-U').should == 'US-ASCII'
+ ruby_exe('Encoding.default_external="ascii"; print Encoding.default_external.name',
+ options: '-U').should == 'US-ASCII'
end
it "does not affect the source encoding" do
- ruby_exe("print __ENCODING__.name",
- options: '-U -KE').should == 'EUC-JP'
- ruby_exe("print __ENCODING__.name",
- options: '-KE -U').should == 'EUC-JP'
+ ruby_exe("print __ENCODING__.name",
+ options: '-U -KE').should == 'EUC-JP'
+ ruby_exe("print __ENCODING__.name",
+ options: '-KE -U').should == 'EUC-JP'
end
# I assume IO redirection will break on Windows...
diff --git a/spec/ruby/command_line/dash_v_spec.rb b/spec/ruby/command_line/dash_v_spec.rb
index 747db7f755..b13350404c 100644
--- a/spec/ruby/command_line/dash_v_spec.rb
+++ b/spec/ruby/command_line/dash_v_spec.rb
@@ -6,9 +6,10 @@ describe "The -v command line option" do
describe "when used alone" do
it "prints version and ends" do
- ruby_exe(nil, args: '-v').sub("+PRISM ", "").should include(RUBY_DESCRIPTION.sub("+PRISM ", ""))
+ ruby_exe(nil, args: '-v').gsub("+PRISM ", "").should include(RUBY_DESCRIPTION.gsub("+PRISM ", ""))
end unless (defined?(RubyVM::YJIT) && RubyVM::YJIT.enabled?) ||
(defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?) ||
+ (ENV['RUBY_GC_LIBRARY'] && ENV['RUBY_GC_LIBRARY'].length > 0) ||
(ENV['RUBY_MN_THREADS'] == '1')
end
end
diff --git a/spec/ruby/command_line/feature_spec.rb b/spec/ruby/command_line/feature_spec.rb
index 4a24cc6795..838581d04a 100644
--- a/spec/ruby/command_line/feature_spec.rb
+++ b/spec/ruby/command_line/feature_spec.rb
@@ -51,7 +51,7 @@ describe "The --enable and --disable flags" do
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 unless defined?(RubyVM::YJIT) && defined?(RubyVM::ZJIT) && RubyVM::ZJIT.enabled? # You're not supposed to enable YJIT with --enable-all when ZJIT options are passed.
end
it "can be used with all for disable" do
diff --git a/spec/ruby/command_line/fixtures/debug_info.rb b/spec/ruby/command_line/fixtures/debug_info.rb
index ee607910c0..f02b041920 100644
--- a/spec/ruby/command_line/fixtures/debug_info.rb
+++ b/spec/ruby/command_line/fixtures/debug_info.rb
@@ -1,4 +1,3 @@
-# frozen_string_literal: true
a = 'string'
b = a
c = b
diff --git a/spec/ruby/command_line/frozen_strings_spec.rb b/spec/ruby/command_line/frozen_strings_spec.rb
index 06889755d2..8acab5bc1d 100644
--- a/spec/ruby/command_line/frozen_strings_spec.rb
+++ b/spec/ruby/command_line/frozen_strings_spec.rb
@@ -42,8 +42,28 @@ describe "With neither --enable-frozen-string-literal nor --disable-frozen-strin
ruby_exe(fixture(__FILE__, "freeze_flag_one_literal.rb")).chomp.should == "false"
end
- it "if file has no frozen_string_literal comment produce different mutable strings each time" do
- ruby_exe(fixture(__FILE__, "string_literal_raw.rb")).chomp.should == "frozen:false interned:false"
+ context "if file has no frozen_string_literal comment" do
+ it "produce different mutable strings each time" do
+ ruby_exe(fixture(__FILE__, "string_literal_raw.rb")).chomp.should == "frozen:false interned:false"
+ end
+
+ guard -> { ruby_version_is "3.4" and !"test".frozen? } do
+ it "complain about modification of produced mutable strings" do
+ -> { eval(<<~RUBY) }.should complain(/warning: literal string will be frozen in the future \(run with --debug-frozen-string-literal for more information\)/)
+ "test" << "!"
+ RUBY
+ end
+
+ it "does not complain about modification if Warning[:deprecated] is false" do
+ deprecated = Warning[:deprecated]
+ Warning[:deprecated] = false
+ -> { eval(<<~RUBY) }.should_not complain
+ "test" << "!"
+ RUBY
+ ensure
+ Warning[:deprecated] = deprecated
+ end
+ end
end
it "if file has frozen_string_literal:true comment produce same frozen strings each time" do
@@ -57,9 +77,18 @@ end
describe "The --debug flag produces" do
it "debugging info on attempted frozen string modification" do
- error_str = ruby_exe(fixture(__FILE__, 'debug_info.rb'), options: '--debug', args: "2>&1")
+ error_str = ruby_exe(fixture(__FILE__, 'debug_info.rb'), options: '--enable-frozen-string-literal --debug', args: "2>&1")
error_str.should include("can't modify frozen String")
error_str.should include("created at")
- error_str.should include("command_line/fixtures/debug_info.rb:2")
+ error_str.should include("command_line/fixtures/debug_info.rb:1")
+ end
+
+ guard -> { ruby_version_is "3.4" and !"test".frozen? } do
+ it "debugging info on mutating chilled string" do
+ error_str = ruby_exe(fixture(__FILE__, 'debug_info.rb'), options: '-w --debug', args: "2>&1")
+ error_str.should include("literal string will be frozen in the future")
+ error_str.should include("the string was created here")
+ error_str.should include("command_line/fixtures/debug_info.rb:1")
+ end
end
end
diff --git a/spec/ruby/command_line/rubyopt_spec.rb b/spec/ruby/command_line/rubyopt_spec.rb
index 18a5959b18..eb297cd6fe 100644
--- a/spec/ruby/command_line/rubyopt_spec.rb
+++ b/spec/ruby/command_line/rubyopt_spec.rb
@@ -22,15 +22,15 @@ describe "Processing RUBYOPT" do
result.should =~ /value of \$DEBUG is true/
end
- guard -> { not CROSS_COMPILING } do
+ guard -> { RbConfig::CONFIG["CROSS_COMPILING"] != "yes" } do
it "prints the version number for '-v'" do
ENV["RUBYOPT"] = '-v'
- ruby_exe("")[/\A.*/].should == RUBY_DESCRIPTION.sub("+PRISM ", "")
+ ruby_exe("")[/\A.*/].gsub(/\s\+(YJIT( \w+)?|ZJIT( \w+)?|PRISM|GC(\[\w+\])?)(?=\s)/, "").should == RUBY_DESCRIPTION.gsub(/\s\+(YJIT( \w+)?|ZJIT( \w+)?|PRISM|GC(\[\w+\])?)(?=\s)/, "")
end
it "ignores whitespace around the option" do
ENV["RUBYOPT"] = ' -v '
- ruby_exe("")[/\A.*/].should == RUBY_DESCRIPTION.sub("+PRISM ", "")
+ ruby_exe("")[/\A.*/].gsub(/\s\+(YJIT( \w+)?|ZJIT( \w+)?|PRISM|GC(\[\w+\])?)(?=\s)/, "").should == RUBY_DESCRIPTION.gsub(/\s\+(YJIT( \w+)?|ZJIT( \w+)?|PRISM|GC(\[\w+\])?)(?=\s)/, "")
end
end
diff --git a/spec/ruby/core/array/drop_spec.rb b/spec/ruby/core/array/drop_spec.rb
index 0ea748e47d..5926c291b8 100644
--- a/spec/ruby/core/array/drop_spec.rb
+++ b/spec/ruby/core/array/drop_spec.rb
@@ -7,7 +7,7 @@ describe "Array#drop" do
end
it "raises an ArgumentError if the number of elements specified is negative" do
- -> { [1, 2].drop(-3) }.should raise_error(ArgumentError)
+ -> { [1, 2].drop(-3) }.should raise_error(ArgumentError)
end
it "returns an empty Array if all elements are dropped" do
diff --git a/spec/ruby/core/array/each_spec.rb b/spec/ruby/core/array/each_spec.rb
index 57d6082f01..f4b5b758d0 100644
--- a/spec/ruby/core/array/each_spec.rb
+++ b/spec/ruby/core/array/each_spec.rb
@@ -7,7 +7,7 @@ require_relative '../enumerable/shared/enumeratorized'
# Mutating the array while it is being iterated is discouraged as it can result in confusing behavior.
# Yet a Ruby implementation must not crash in such a case, and following the simple CRuby behavior makes sense.
# CRuby simply reads the array storage and checks the size for every iteration;
-# like `i = 0; while i < size; yield self[i]; end`
+# like `i = 0; while i < size; yield self[i]; i += 1; end`
describe "Array#each" do
it "yields each element to the block" do
diff --git a/spec/ruby/core/array/fetch_values_spec.rb b/spec/ruby/core/array/fetch_values_spec.rb
new file mode 100644
index 0000000000..cf377b3b71
--- /dev/null
+++ b/spec/ruby/core/array/fetch_values_spec.rb
@@ -0,0 +1,55 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Array#fetch_values" do
+ before :each do
+ @array = [:a, :b, :c]
+ end
+
+ ruby_version_is "3.4" do
+ describe "with matched indexes" do
+ it "returns the values for indexes" do
+ @array.fetch_values(0).should == [:a]
+ @array.fetch_values(0, 2).should == [:a, :c]
+ @array.fetch_values(-1).should == [:c]
+ end
+
+ it "returns the values for indexes ordered in the order of the requested indexes" do
+ @array.fetch_values(2, 0).should == [:c, :a]
+ end
+ end
+
+ describe "with unmatched indexes" do
+ it "raises a index error if no block is provided" do
+ -> { @array.fetch_values(0, 1, 44) }.should raise_error(IndexError, "index 44 outside of array bounds: -3...3")
+ end
+
+ it "returns the default value from block" do
+ @array.fetch_values(44) { |index| "`#{index}' is not found" }.should == ["`44' is not found"]
+ @array.fetch_values(0, 44) { |index| "`#{index}' is not found" }.should == [:a, "`44' is not found"]
+ end
+ end
+
+ describe "without keys" do
+ it "returns an empty Array" do
+ @array.fetch_values.should == []
+ end
+ end
+
+ it "tries to convert the passed argument to an Integer using #to_int" do
+ obj = mock('to_int')
+ obj.should_receive(:to_int).and_return(2)
+ @array.fetch_values(obj).should == [:c]
+ end
+
+ it "does not support a Range object as argument" do
+ -> {
+ @array.fetch_values(1..2)
+ }.should raise_error(TypeError, "no implicit conversion of Range into Integer")
+ end
+
+ it "raises a TypeError when the passed argument can't be coerced to Integer" do
+ -> { [].fetch_values("cat") }.should raise_error(TypeError, "no implicit conversion of String into Integer")
+ end
+ end
+end
diff --git a/spec/ruby/core/array/fixtures/classes.rb b/spec/ruby/core/array/fixtures/classes.rb
index 8596245fb8..05283c0f74 100644
--- a/spec/ruby/core/array/fixtures/classes.rb
+++ b/spec/ruby/core/array/fixtures/classes.rb
@@ -56,23 +56,20 @@ module ArraySpecs
101.621, 102.816, 104.010, 105.202, 106.393, 107.583, 108.771, 109.958, 111.144, 112.329,
113.512, 114.695, 115.876, 117.057, 118.236, 119.414, 120.591, 121.767, 122.942, 124.116,
125.289, 126.462, 127.633, 128.803, 129.973, 131.141, 132.309, 133.476, 134.642, 135.807,
- ]
+ ]
def self.measure_sample_fairness(size, samples, iters)
ary = Array.new(size) { |x| x }
+ expected = iters.fdiv size
(samples).times do |i|
chi_results = []
3.times do
- counts = Array.new(size) { 0 }
- expected = iters / size
+ counts = Array.new(size, 0)
iters.times do
x = ary.sample(samples)[i]
counts[x] += 1
end
- chi_squared = 0.0
- counts.each do |count|
- chi_squared += (((count - expected) ** 2) * 1.0 / expected)
- end
+ chi_squared = counts.sum {|count| (count - expected) ** 2} / expected
chi_results << chi_squared
break if chi_squared <= CHI_SQUARED_CRITICAL_VALUES[size]
end
@@ -83,17 +80,14 @@ module ArraySpecs
def self.measure_sample_fairness_large_sample_size(size, samples, iters)
ary = Array.new(size) { |x| x }
- counts = Array.new(size) { 0 }
- expected = iters * samples / size
+ counts = Array.new(size, 0)
+ expected = (iters * samples).fdiv size
iters.times do
ary.sample(samples).each do |sample|
counts[sample] += 1
end
end
- chi_squared = 0.0
- counts.each do |count|
- chi_squared += (((count - expected) ** 2) * 1.0 / expected)
- end
+ chi_squared = counts.sum {|count| (count - expected) ** 2} / expected
# Chi squared critical values for tests with 4 degrees of freedom
# Values obtained from NIST Engineering Statistic Handbook at
@@ -223,366 +217,370 @@ module ArraySpecs
obj
end
- LargeArray = ["test_create_table_with_force_true_does_not_drop_nonexisting_table",
- "test_add_table",
- "assert_difference",
- "assert_operator",
- "instance_variables",
- "class",
- "instance_variable_get",
- "__class__",
- "expects",
- "assert_no_difference",
- "name",
- "assert_blank",
- "assert_not_same",
- "is_a?",
- "test_add_table_with_decimals",
- "test_create_table_with_timestamps_should_create_datetime_columns",
- "assert_present",
- "assert_no_match",
- "__instance_of__",
- "assert_deprecated",
- "assert",
- "assert_throws",
- "kind_of?",
- "try",
- "__instance_variable_get__",
- "object_id",
- "timeout",
- "instance_variable_set",
- "assert_nothing_thrown",
- "__instance_variable_set__",
- "copy_object",
- "test_create_table_with_timestamps_should_create_datetime_columns_with_options",
- "assert_not_deprecated",
- "assert_in_delta",
- "id",
- "copy_metaclass",
- "test_create_table_without_a_block",
- "dup",
- "assert_not_nil",
- "send",
- "__instance_variables__",
- "to_sql",
- "mock",
- "assert_send",
- "instance_variable_defined?",
- "clone",
- "require",
- "test_migrator",
- "__instance_variable_defined_eh__",
- "frozen?",
- "test_add_column_not_null_with_default",
- "freeze",
- "test_migrator_one_up",
- "test_migrator_one_down",
- "singleton_methods",
- "method_exists?",
- "create_fixtures",
- "test_migrator_one_up_one_down",
- "test_native_decimal_insert_manual_vs_automatic",
- "instance_exec",
- "__is_a__",
- "test_migrator_double_up",
- "stub",
- "private_methods",
- "stubs",
- "test_migrator_double_down",
- "fixture_path",
- "private_singleton_methods",
- "stub_everything",
- "test_migrator_one_up_with_exception_and_rollback",
- "sequence",
- "protected_methods",
- "enum_for",
- "test_finds_migrations",
- "run_before_mocha",
- "states",
- "protected_singleton_methods",
- "to_json",
- "instance_values",
- "==",
- "mocha_setup",
- "public_methods",
- "test_finds_pending_migrations",
- "mocha_verify",
- "assert_kind_of",
- "===",
- "=~",
- "test_relative_migrations",
- "mocha_teardown",
- "gem",
- "mocha",
- "test_only_loads_pending_migrations",
- "test_add_column_with_precision_and_scale",
- "require_or_load",
- "eql?",
- "require_dependency",
- "test_native_types",
- "test_target_version_zero_should_run_only_once",
- "extend",
- "to_matcher",
- "unloadable",
- "require_association",
- "hash",
- "__id__",
- "load_dependency",
- "equals",
- "test_migrator_db_has_no_schema_migrations_table",
- "test_migrator_verbosity",
- "kind_of",
- "to_yaml",
- "to_bool",
- "test_migrator_verbosity_off",
- "taint",
- "test_migrator_going_down_due_to_version_target",
- "tainted?",
- "mocha_inspect",
- "test_migrator_rollback",
- "vim",
- "untaint",
- "taguri=",
- "test_migrator_forward",
- "test_schema_migrations_table_name",
- "test_proper_table_name",
- "all_of",
- "test_add_drop_table_with_prefix_and_suffix",
- "_setup_callbacks",
- "setup",
- "Not",
- "test_create_table_with_binary_column",
- "assert_not_equal",
- "enable_warnings",
- "acts_like?",
- "Rational",
- "_removed_setup_callbacks",
- "Table",
- "bind",
- "any_of",
- "__method__",
- "test_migrator_with_duplicates",
- "_teardown_callbacks",
- "method",
- "test_migrator_with_duplicate_names",
- "_removed_teardown_callbacks",
- "any_parameters",
- "test_migrator_with_missing_version_numbers",
- "test_add_remove_single_field_using_string_arguments",
- "test_create_table_with_custom_sequence_name",
- "test_add_remove_single_field_using_symbol_arguments",
- "_one_time_conditions_valid_14?",
- "_one_time_conditions_valid_16?",
- "run_callbacks",
- "anything",
- "silence_warnings",
- "instance_variable_names",
- "_fixture_path",
- "copy_instance_variables_from",
- "fixture_path?",
- "has_entry",
- "__marshal__",
- "_fixture_table_names",
- "__kind_of__",
- "fixture_table_names?",
- "test_add_rename",
- "assert_equal",
- "_fixture_class_names",
- "fixture_class_names?",
- "has_entries",
- "_use_transactional_fixtures",
- "people",
- "test_rename_column_using_symbol_arguments",
- "use_transactional_fixtures?",
- "instance_eval",
- "blank?",
- "with_warnings",
- "__nil__",
- "load",
- "metaclass",
- "_use_instantiated_fixtures",
- "has_key",
- "class_eval",
- "present?",
- "test_rename_column",
- "teardown",
- "use_instantiated_fixtures?",
- "method_name",
- "silence_stderr",
- "presence",
- "test_rename_column_preserves_default_value_not_null",
- "silence_stream",
- "_pre_loaded_fixtures",
- "__metaclass__",
- "__fixnum__",
- "pre_loaded_fixtures?",
- "has_value",
- "suppress",
- "to_yaml_properties",
- "test_rename_nonexistent_column",
- "test_add_index",
- "includes",
- "find_correlate_in",
- "equality_predicate_sql",
- "assert_nothing_raised",
- "let",
- "not_predicate_sql",
- "test_rename_column_with_sql_reserved_word",
- "singleton_class",
- "test_rename_column_with_an_index",
- "display",
- "taguri",
- "to_yaml_style",
- "test_remove_column_with_index",
- "size",
- "current_adapter?",
- "test_remove_column_with_multi_column_index",
- "respond_to?",
- "test_change_type_of_not_null_column",
- "is_a",
- "to_a",
- "test_rename_table_for_sqlite_should_work_with_reserved_words",
- "require_library_or_gem",
- "setup_fixtures",
- "equal?",
- "teardown_fixtures",
- "nil?",
- "fixture_table_names",
- "fixture_class_names",
- "test_create_table_without_id",
- "use_transactional_fixtures",
- "test_add_column_with_primary_key_attribute",
- "repair_validations",
- "use_instantiated_fixtures",
- "instance_of?",
- "test_create_table_adds_id",
- "test_rename_table",
- "pre_loaded_fixtures",
- "to_enum",
- "test_create_table_with_not_null_column",
- "instance_of",
- "test_change_column_nullability",
- "optionally",
- "test_rename_table_with_an_index",
- "run",
- "test_change_column",
- "default_test",
- "assert_raise",
- "test_create_table_with_defaults",
- "assert_nil",
- "flunk",
- "regexp_matches",
- "duplicable?",
- "reset_mocha",
- "stubba_method",
- "filter_backtrace",
- "test_create_table_with_limits",
- "responds_with",
- "stubba_object",
- "test_change_column_with_nil_default",
- "assert_block",
- "__show__",
- "assert_date_from_db",
- "__respond_to_eh__",
- "run_in_transaction?",
- "inspect",
- "assert_sql",
- "test_change_column_with_new_default",
- "yaml_equivalent",
- "build_message",
- "to_s",
- "test_change_column_default",
- "assert_queries",
- "pending",
- "as_json",
- "assert_no_queries",
- "test_change_column_quotes_column_names",
- "assert_match",
- "test_keeping_default_and_notnull_constraint_on_change",
- "methods",
- "connection_allow_concurrency_setup",
- "connection_allow_concurrency_teardown",
- "test_create_table_with_primary_key_prefix_as_table_name_with_underscore",
- "__send__",
- "make_connection",
- "assert_raises",
- "tap",
- "with_kcode",
- "assert_instance_of",
- "test_create_table_with_primary_key_prefix_as_table_name",
- "assert_respond_to",
- "test_change_column_default_to_null",
- "assert_same",
- "__extend__"]
-
- LargeTestArraySorted = ["test_add_column_not_null_with_default",
- "test_add_column_with_precision_and_scale",
- "test_add_column_with_primary_key_attribute",
- "test_add_drop_table_with_prefix_and_suffix",
- "test_add_index",
- "test_add_remove_single_field_using_string_arguments",
- "test_add_remove_single_field_using_symbol_arguments",
- "test_add_rename",
- "test_add_table",
- "test_add_table_with_decimals",
- "test_change_column",
- "test_change_column_default",
- "test_change_column_default_to_null",
- "test_change_column_nullability",
- "test_change_column_quotes_column_names",
- "test_change_column_with_new_default",
- "test_change_column_with_nil_default",
- "test_change_type_of_not_null_column",
- "test_create_table_adds_id",
- "test_create_table_with_binary_column",
- "test_create_table_with_custom_sequence_name",
- "test_create_table_with_defaults",
- "test_create_table_with_force_true_does_not_drop_nonexisting_table",
- "test_create_table_with_limits",
- "test_create_table_with_not_null_column",
- "test_create_table_with_primary_key_prefix_as_table_name",
- "test_create_table_with_primary_key_prefix_as_table_name_with_underscore",
- "test_create_table_with_timestamps_should_create_datetime_columns",
- "test_create_table_with_timestamps_should_create_datetime_columns_with_options",
- "test_create_table_without_a_block",
- "test_create_table_without_id",
- "test_finds_migrations",
- "test_finds_pending_migrations",
- "test_keeping_default_and_notnull_constraint_on_change",
- "test_migrator",
- "test_migrator_db_has_no_schema_migrations_table",
- "test_migrator_double_down",
- "test_migrator_double_up",
- "test_migrator_forward",
- "test_migrator_going_down_due_to_version_target",
- "test_migrator_one_down",
- "test_migrator_one_up",
- "test_migrator_one_up_one_down",
- "test_migrator_one_up_with_exception_and_rollback",
- "test_migrator_rollback",
- "test_migrator_verbosity",
- "test_migrator_verbosity_off",
- "test_migrator_with_duplicate_names",
- "test_migrator_with_duplicates",
- "test_migrator_with_missing_version_numbers",
- "test_native_decimal_insert_manual_vs_automatic",
- "test_native_types",
- "test_only_loads_pending_migrations",
- "test_proper_table_name",
- "test_relative_migrations",
- "test_remove_column_with_index",
- "test_remove_column_with_multi_column_index",
- "test_rename_column",
- "test_rename_column_preserves_default_value_not_null",
- "test_rename_column_using_symbol_arguments",
- "test_rename_column_with_an_index",
- "test_rename_column_with_sql_reserved_word",
- "test_rename_nonexistent_column",
- "test_rename_table",
- "test_rename_table_for_sqlite_should_work_with_reserved_words",
- "test_rename_table_with_an_index",
- "test_schema_migrations_table_name",
- "test_target_version_zero_should_run_only_once"]
+ LargeArray = [
+ "test_create_table_with_force_true_does_not_drop_nonexisting_table",
+ "test_add_table",
+ "assert_difference",
+ "assert_operator",
+ "instance_variables",
+ "class",
+ "instance_variable_get",
+ "__class__",
+ "expects",
+ "assert_no_difference",
+ "name",
+ "assert_blank",
+ "assert_not_same",
+ "is_a?",
+ "test_add_table_with_decimals",
+ "test_create_table_with_timestamps_should_create_datetime_columns",
+ "assert_present",
+ "assert_no_match",
+ "__instance_of__",
+ "assert_deprecated",
+ "assert",
+ "assert_throws",
+ "kind_of?",
+ "try",
+ "__instance_variable_get__",
+ "object_id",
+ "timeout",
+ "instance_variable_set",
+ "assert_nothing_thrown",
+ "__instance_variable_set__",
+ "copy_object",
+ "test_create_table_with_timestamps_should_create_datetime_columns_with_options",
+ "assert_not_deprecated",
+ "assert_in_delta",
+ "id",
+ "copy_metaclass",
+ "test_create_table_without_a_block",
+ "dup",
+ "assert_not_nil",
+ "send",
+ "__instance_variables__",
+ "to_sql",
+ "mock",
+ "assert_send",
+ "instance_variable_defined?",
+ "clone",
+ "require",
+ "test_migrator",
+ "__instance_variable_defined_eh__",
+ "frozen?",
+ "test_add_column_not_null_with_default",
+ "freeze",
+ "test_migrator_one_up",
+ "test_migrator_one_down",
+ "singleton_methods",
+ "method_exists?",
+ "create_fixtures",
+ "test_migrator_one_up_one_down",
+ "test_native_decimal_insert_manual_vs_automatic",
+ "instance_exec",
+ "__is_a__",
+ "test_migrator_double_up",
+ "stub",
+ "private_methods",
+ "stubs",
+ "test_migrator_double_down",
+ "fixture_path",
+ "private_singleton_methods",
+ "stub_everything",
+ "test_migrator_one_up_with_exception_and_rollback",
+ "sequence",
+ "protected_methods",
+ "enum_for",
+ "test_finds_migrations",
+ "run_before_mocha",
+ "states",
+ "protected_singleton_methods",
+ "to_json",
+ "instance_values",
+ "==",
+ "mocha_setup",
+ "public_methods",
+ "test_finds_pending_migrations",
+ "mocha_verify",
+ "assert_kind_of",
+ "===",
+ "=~",
+ "test_relative_migrations",
+ "mocha_teardown",
+ "gem",
+ "mocha",
+ "test_only_loads_pending_migrations",
+ "test_add_column_with_precision_and_scale",
+ "require_or_load",
+ "eql?",
+ "require_dependency",
+ "test_native_types",
+ "test_target_version_zero_should_run_only_once",
+ "extend",
+ "to_matcher",
+ "unloadable",
+ "require_association",
+ "hash",
+ "__id__",
+ "load_dependency",
+ "equals",
+ "test_migrator_db_has_no_schema_migrations_table",
+ "test_migrator_verbosity",
+ "kind_of",
+ "to_yaml",
+ "to_bool",
+ "test_migrator_verbosity_off",
+ "taint",
+ "test_migrator_going_down_due_to_version_target",
+ "tainted?",
+ "mocha_inspect",
+ "test_migrator_rollback",
+ "vim",
+ "untaint",
+ "taguri=",
+ "test_migrator_forward",
+ "test_schema_migrations_table_name",
+ "test_proper_table_name",
+ "all_of",
+ "test_add_drop_table_with_prefix_and_suffix",
+ "_setup_callbacks",
+ "setup",
+ "Not",
+ "test_create_table_with_binary_column",
+ "assert_not_equal",
+ "enable_warnings",
+ "acts_like?",
+ "Rational",
+ "_removed_setup_callbacks",
+ "Table",
+ "bind",
+ "any_of",
+ "__method__",
+ "test_migrator_with_duplicates",
+ "_teardown_callbacks",
+ "method",
+ "test_migrator_with_duplicate_names",
+ "_removed_teardown_callbacks",
+ "any_parameters",
+ "test_migrator_with_missing_version_numbers",
+ "test_add_remove_single_field_using_string_arguments",
+ "test_create_table_with_custom_sequence_name",
+ "test_add_remove_single_field_using_symbol_arguments",
+ "_one_time_conditions_valid_14?",
+ "_one_time_conditions_valid_16?",
+ "run_callbacks",
+ "anything",
+ "silence_warnings",
+ "instance_variable_names",
+ "_fixture_path",
+ "copy_instance_variables_from",
+ "fixture_path?",
+ "has_entry",
+ "__marshal__",
+ "_fixture_table_names",
+ "__kind_of__",
+ "fixture_table_names?",
+ "test_add_rename",
+ "assert_equal",
+ "_fixture_class_names",
+ "fixture_class_names?",
+ "has_entries",
+ "_use_transactional_fixtures",
+ "people",
+ "test_rename_column_using_symbol_arguments",
+ "use_transactional_fixtures?",
+ "instance_eval",
+ "blank?",
+ "with_warnings",
+ "__nil__",
+ "load",
+ "metaclass",
+ "_use_instantiated_fixtures",
+ "has_key",
+ "class_eval",
+ "present?",
+ "test_rename_column",
+ "teardown",
+ "use_instantiated_fixtures?",
+ "method_name",
+ "silence_stderr",
+ "presence",
+ "test_rename_column_preserves_default_value_not_null",
+ "silence_stream",
+ "_pre_loaded_fixtures",
+ "__metaclass__",
+ "__fixnum__",
+ "pre_loaded_fixtures?",
+ "has_value",
+ "suppress",
+ "to_yaml_properties",
+ "test_rename_nonexistent_column",
+ "test_add_index",
+ "includes",
+ "find_correlate_in",
+ "equality_predicate_sql",
+ "assert_nothing_raised",
+ "let",
+ "not_predicate_sql",
+ "test_rename_column_with_sql_reserved_word",
+ "singleton_class",
+ "test_rename_column_with_an_index",
+ "display",
+ "taguri",
+ "to_yaml_style",
+ "test_remove_column_with_index",
+ "size",
+ "current_adapter?",
+ "test_remove_column_with_multi_column_index",
+ "respond_to?",
+ "test_change_type_of_not_null_column",
+ "is_a",
+ "to_a",
+ "test_rename_table_for_sqlite_should_work_with_reserved_words",
+ "require_library_or_gem",
+ "setup_fixtures",
+ "equal?",
+ "teardown_fixtures",
+ "nil?",
+ "fixture_table_names",
+ "fixture_class_names",
+ "test_create_table_without_id",
+ "use_transactional_fixtures",
+ "test_add_column_with_primary_key_attribute",
+ "repair_validations",
+ "use_instantiated_fixtures",
+ "instance_of?",
+ "test_create_table_adds_id",
+ "test_rename_table",
+ "pre_loaded_fixtures",
+ "to_enum",
+ "test_create_table_with_not_null_column",
+ "instance_of",
+ "test_change_column_nullability",
+ "optionally",
+ "test_rename_table_with_an_index",
+ "run",
+ "test_change_column",
+ "default_test",
+ "assert_raise",
+ "test_create_table_with_defaults",
+ "assert_nil",
+ "flunk",
+ "regexp_matches",
+ "duplicable?",
+ "reset_mocha",
+ "stubba_method",
+ "filter_backtrace",
+ "test_create_table_with_limits",
+ "responds_with",
+ "stubba_object",
+ "test_change_column_with_nil_default",
+ "assert_block",
+ "__show__",
+ "assert_date_from_db",
+ "__respond_to_eh__",
+ "run_in_transaction?",
+ "inspect",
+ "assert_sql",
+ "test_change_column_with_new_default",
+ "yaml_equivalent",
+ "build_message",
+ "to_s",
+ "test_change_column_default",
+ "assert_queries",
+ "pending",
+ "as_json",
+ "assert_no_queries",
+ "test_change_column_quotes_column_names",
+ "assert_match",
+ "test_keeping_default_and_notnull_constraint_on_change",
+ "methods",
+ "connection_allow_concurrency_setup",
+ "connection_allow_concurrency_teardown",
+ "test_create_table_with_primary_key_prefix_as_table_name_with_underscore",
+ "__send__",
+ "make_connection",
+ "assert_raises",
+ "tap",
+ "with_kcode",
+ "assert_instance_of",
+ "test_create_table_with_primary_key_prefix_as_table_name",
+ "assert_respond_to",
+ "test_change_column_default_to_null",
+ "assert_same",
+ "__extend__",
+ ]
+
+ LargeTestArraySorted = [
+ "test_add_column_not_null_with_default",
+ "test_add_column_with_precision_and_scale",
+ "test_add_column_with_primary_key_attribute",
+ "test_add_drop_table_with_prefix_and_suffix",
+ "test_add_index",
+ "test_add_remove_single_field_using_string_arguments",
+ "test_add_remove_single_field_using_symbol_arguments",
+ "test_add_rename",
+ "test_add_table",
+ "test_add_table_with_decimals",
+ "test_change_column",
+ "test_change_column_default",
+ "test_change_column_default_to_null",
+ "test_change_column_nullability",
+ "test_change_column_quotes_column_names",
+ "test_change_column_with_new_default",
+ "test_change_column_with_nil_default",
+ "test_change_type_of_not_null_column",
+ "test_create_table_adds_id",
+ "test_create_table_with_binary_column",
+ "test_create_table_with_custom_sequence_name",
+ "test_create_table_with_defaults",
+ "test_create_table_with_force_true_does_not_drop_nonexisting_table",
+ "test_create_table_with_limits",
+ "test_create_table_with_not_null_column",
+ "test_create_table_with_primary_key_prefix_as_table_name",
+ "test_create_table_with_primary_key_prefix_as_table_name_with_underscore",
+ "test_create_table_with_timestamps_should_create_datetime_columns",
+ "test_create_table_with_timestamps_should_create_datetime_columns_with_options",
+ "test_create_table_without_a_block",
+ "test_create_table_without_id",
+ "test_finds_migrations",
+ "test_finds_pending_migrations",
+ "test_keeping_default_and_notnull_constraint_on_change",
+ "test_migrator",
+ "test_migrator_db_has_no_schema_migrations_table",
+ "test_migrator_double_down",
+ "test_migrator_double_up",
+ "test_migrator_forward",
+ "test_migrator_going_down_due_to_version_target",
+ "test_migrator_one_down",
+ "test_migrator_one_up",
+ "test_migrator_one_up_one_down",
+ "test_migrator_one_up_with_exception_and_rollback",
+ "test_migrator_rollback",
+ "test_migrator_verbosity",
+ "test_migrator_verbosity_off",
+ "test_migrator_with_duplicate_names",
+ "test_migrator_with_duplicates",
+ "test_migrator_with_missing_version_numbers",
+ "test_native_decimal_insert_manual_vs_automatic",
+ "test_native_types",
+ "test_only_loads_pending_migrations",
+ "test_proper_table_name",
+ "test_relative_migrations",
+ "test_remove_column_with_index",
+ "test_remove_column_with_multi_column_index",
+ "test_rename_column",
+ "test_rename_column_preserves_default_value_not_null",
+ "test_rename_column_using_symbol_arguments",
+ "test_rename_column_with_an_index",
+ "test_rename_column_with_sql_reserved_word",
+ "test_rename_nonexistent_column",
+ "test_rename_table",
+ "test_rename_table_for_sqlite_should_work_with_reserved_words",
+ "test_rename_table_with_an_index",
+ "test_schema_migrations_table_name",
+ "test_target_version_zero_should_run_only_once",
+ ]
class PrivateToAry
private
diff --git a/spec/ruby/core/array/intersect_spec.rb b/spec/ruby/core/array/intersect_spec.rb
index 62ac157278..456aa26c6e 100644
--- a/spec/ruby/core/array/intersect_spec.rb
+++ b/spec/ruby/core/array/intersect_spec.rb
@@ -2,65 +2,63 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
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, 4]).should == true
- [2, 3, 4].intersect?([1, 2]).should == true
- end
+ describe 'when at least one element in two Arrays is the same' do
+ it 'returns true' do
+ [1, 2].intersect?([2, 3, 4]).should == true
+ [2, 3, 4].intersect?([1, 2]).should == true
end
+ end
- describe 'when there are no elements in common between two Arrays' do
- it 'returns false' do
- [0, 1, 2].intersect?([3, 4]).should == false
- [3, 4].intersect?([0, 1, 2]).should == false
- [3, 4].intersect?([]).should == false
- [].intersect?([0, 1, 2]).should == false
- end
+ describe 'when there are no elements in common between two Arrays' do
+ it 'returns false' do
+ [0, 1, 2].intersect?([3, 4]).should == false
+ [3, 4].intersect?([0, 1, 2]).should == false
+ [3, 4].intersect?([]).should == false
+ [].intersect?([0, 1, 2]).should == false
end
+ 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])
+ 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].intersect?(obj).should == true
- end
+ [1, 2].intersect?(obj).should == true
+ end
- it "determines equivalence between elements in the sense of eql?" do
- obj1 = mock('1')
- obj2 = mock('2')
- obj1.stub!(:hash).and_return(0)
- obj2.stub!(:hash).and_return(0)
- obj1.stub!(:eql?).and_return(true)
- obj2.stub!(:eql?).and_return(true)
+ it "determines equivalence between elements in the sense of eql?" do
+ obj1 = mock('1')
+ obj2 = mock('2')
+ obj1.stub!(:hash).and_return(0)
+ obj2.stub!(:hash).and_return(0)
+ obj1.stub!(:eql?).and_return(true)
+ obj2.stub!(:eql?).and_return(true)
- [obj1].intersect?([obj2]).should == true
+ [obj1].intersect?([obj2]).should == true
- obj1 = mock('3')
- obj2 = mock('4')
- obj1.stub!(:hash).and_return(0)
- obj2.stub!(:hash).and_return(0)
- obj1.stub!(:eql?).and_return(false)
- obj2.stub!(:eql?).and_return(false)
+ obj1 = mock('3')
+ obj2 = mock('4')
+ obj1.stub!(:hash).and_return(0)
+ obj2.stub!(:hash).and_return(0)
+ obj1.stub!(:eql?).and_return(false)
+ obj2.stub!(:eql?).and_return(false)
- [obj1].intersect?([obj2]).should == false
- end
+ [obj1].intersect?([obj2]).should == false
+ end
- it "does not call to_ary on array subclasses" do
- [5, 6].intersect?(ArraySpecs::ToAryArray[1, 2, 5, 6]).should == true
- end
+ it "does not call to_ary on array subclasses" do
+ [5, 6].intersect?(ArraySpecs::ToAryArray[1, 2, 5, 6]).should == true
+ 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.
+ 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].intersect?([x]).should == true
- end
+ [x].intersect?([x]).should == true
+ end
- it "has semantic of !(a & b).empty?" do
- [].intersect?([]).should == false
- [nil].intersect?([nil]).should == true
- end
+ it "has semantic of !(a & b).empty?" do
+ [].intersect?([]).should == false
+ [nil].intersect?([nil]).should == true
end
end
diff --git a/spec/ruby/core/array/pack/a_spec.rb b/spec/ruby/core/array/pack/a_spec.rb
index f4a40502c2..8245cd5470 100644
--- a/spec/ruby/core/array/pack/a_spec.rb
+++ b/spec/ruby/core/array/pack/a_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -27,7 +27,7 @@ describe "Array#pack with format 'A'" do
["abc"].pack("A*").should == "abc"
end
- it "padds the output with spaces when the count exceeds the size of the String" do
+ it "pads the output with spaces when the count exceeds the size of the String" do
["abc"].pack("A6").should == "abc "
end
@@ -55,7 +55,7 @@ describe "Array#pack with format 'a'" do
["abc"].pack("a*").should == "abc"
end
- it "padds the output with NULL bytes when the count exceeds the size of the String" do
+ it "pads the output with NULL bytes when the count exceeds the size of the String" do
["abc"].pack("a6").should == "abc\x00\x00\x00"
end
diff --git a/spec/ruby/core/array/pack/at_spec.rb b/spec/ruby/core/array/pack/at_spec.rb
index 3942677913..bb9801440a 100644
--- a/spec/ruby/core/array/pack/at_spec.rb
+++ b/spec/ruby/core/array/pack/at_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
diff --git a/spec/ruby/core/array/pack/b_spec.rb b/spec/ruby/core/array/pack/b_spec.rb
index ec82b7d1ab..247a9ca023 100644
--- a/spec/ruby/core/array/pack/b_spec.rb
+++ b/spec/ruby/core/array/pack/b_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
diff --git a/spec/ruby/core/array/pack/buffer_spec.rb b/spec/ruby/core/array/pack/buffer_spec.rb
index f1206efb3e..b77b2d1efa 100644
--- a/spec/ruby/core/array/pack/buffer_spec.rb
+++ b/spec/ruby/core/array/pack/buffer_spec.rb
@@ -28,6 +28,16 @@ describe "Array#pack with :buffer option" do
TypeError, "buffer must be String, not Array")
end
+ it "raise FrozenError if buffer is frozen" do
+ -> { [65].pack("c", buffer: "frozen-string".freeze) }.should raise_error(FrozenError)
+ end
+
+ it "preserves the encoding of the given buffer" do
+ buffer = ''.encode(Encoding::ISO_8859_1)
+ [65, 66, 67].pack("ccc", buffer: buffer)
+ buffer.encoding.should == Encoding::ISO_8859_1
+ end
+
context "offset (@) is specified" do
it 'keeps buffer content if it is longer than offset' do
n = [ 65, 66, 67 ]
diff --git a/spec/ruby/core/array/pack/c_spec.rb b/spec/ruby/core/array/pack/c_spec.rb
index ac133ff9b6..47b71b663d 100644
--- a/spec/ruby/core/array/pack/c_spec.rb
+++ b/spec/ruby/core/array/pack/c_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
diff --git a/spec/ruby/core/array/pack/comment_spec.rb b/spec/ruby/core/array/pack/comment_spec.rb
index 254c827ccc..daf1cff06a 100644
--- a/spec/ruby/core/array/pack/comment_spec.rb
+++ b/spec/ruby/core/array/pack/comment_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
diff --git a/spec/ruby/core/array/pack/h_spec.rb b/spec/ruby/core/array/pack/h_spec.rb
index 2c1dac8d4a..ba188874ba 100644
--- a/spec/ruby/core/array/pack/h_spec.rb
+++ b/spec/ruby/core/array/pack/h_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
diff --git a/spec/ruby/core/array/pack/l_spec.rb b/spec/ruby/core/array/pack/l_spec.rb
index b446a7a36a..f6dfb1da83 100644
--- a/spec/ruby/core/array/pack/l_spec.rb
+++ b/spec/ruby/core/array/pack/l_spec.rb
@@ -29,7 +29,7 @@ describe "Array#pack with format 'L'" do
it_behaves_like :array_pack_32bit_be, 'L>'
end
- platform_is wordsize: 32 do
+ platform_is c_long_size: 32 do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_32bit_le, 'L<_'
it_behaves_like :array_pack_32bit_le, 'L_<'
@@ -51,7 +51,7 @@ describe "Array#pack with format 'L'" do
end
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_64bit_le, 'L<_'
it_behaves_like :array_pack_64bit_le, 'L_<'
@@ -83,7 +83,7 @@ describe "Array#pack with format 'l'" do
it_behaves_like :array_pack_32bit_be, 'l>'
end
- platform_is wordsize: 32 do
+ platform_is c_long_size: 32 do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_32bit_le, 'l<_'
it_behaves_like :array_pack_32bit_le, 'l_<'
@@ -105,7 +105,7 @@ describe "Array#pack with format 'l'" do
end
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
describe "with modifier '<' and '_'" do
it_behaves_like :array_pack_64bit_le, 'l<_'
it_behaves_like :array_pack_64bit_le, 'l_<'
@@ -137,7 +137,7 @@ little_endian do
it_behaves_like :array_pack_32bit_le, 'l'
end
- platform_is wordsize: 32 do
+ platform_is c_long_size: 32 do
describe "Array#pack with format 'L' with modifier '_'" do
it_behaves_like :array_pack_32bit_le, 'L_'
end
@@ -155,7 +155,7 @@ little_endian do
end
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
describe "Array#pack with format 'L' with modifier '_'" do
it_behaves_like :array_pack_64bit_le, 'L_'
end
@@ -183,7 +183,7 @@ big_endian do
it_behaves_like :array_pack_32bit_be, 'l'
end
- platform_is wordsize: 32 do
+ platform_is c_long_size: 32 do
describe "Array#pack with format 'L' with modifier '_'" do
it_behaves_like :array_pack_32bit_be, 'L_'
end
@@ -201,7 +201,7 @@ big_endian do
end
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
describe "Array#pack with format 'L' with modifier '_'" do
it_behaves_like :array_pack_64bit_be, 'L_'
end
diff --git a/spec/ruby/core/array/pack/m_spec.rb b/spec/ruby/core/array/pack/m_spec.rb
index c6364af12d..a80f91275c 100644
--- a/spec/ruby/core/array/pack/m_spec.rb
+++ b/spec/ruby/core/array/pack/m_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
diff --git a/spec/ruby/core/array/pack/shared/basic.rb b/spec/ruby/core/array/pack/shared/basic.rb
index 5e3eea55f9..a63f64d296 100644
--- a/spec/ruby/core/array/pack/shared/basic.rb
+++ b/spec/ruby/core/array/pack/shared/basic.rb
@@ -32,34 +32,21 @@ describe :array_pack_basic_non_float, shared: true do
[@obj, @obj, @obj, @obj].pack("aa #{pack_format} # some comment \n#{pack_format}").should be_an_instance_of(String)
end
- ruby_version_is ""..."3.2" do
- it "warns in verbose mode that a directive is unknown" do
- # additional directive ('a') is required for the X directive
- -> { [@obj, @obj].pack("a R" + pack_format) }.should complain(/unknown pack directive 'R'/, verbose: true)
- -> { [@obj, @obj].pack("a 0" + pack_format) }.should complain(/unknown pack directive '0'/, verbose: true)
- -> { [@obj, @obj].pack("a :" + pack_format) }.should complain(/unknown pack directive ':'/, verbose: true)
- end
- end
-
- ruby_version_is "3.2"..."3.3" do
- # https://bugs.ruby-lang.org/issues/19150
- # NOTE: it's just a plan of the Ruby core team
+ ruby_version_is ""..."3.3" do
it "warns that a directive is unknown" do
# additional directive ('a') is required for the X directive
- -> { [@obj, @obj].pack("a R" + pack_format) }.should complain(/unknown pack directive 'R'/)
- -> { [@obj, @obj].pack("a 0" + pack_format) }.should complain(/unknown pack directive '0'/)
- -> { [@obj, @obj].pack("a :" + pack_format) }.should complain(/unknown pack directive ':'/)
+ -> { [@obj, @obj].pack("a K" + pack_format) }.should complain(/unknown pack directive 'K' in 'a K#{pack_format}'/)
+ -> { [@obj, @obj].pack("a 0" + pack_format) }.should complain(/unknown pack directive '0' in 'a 0#{pack_format}'/)
+ -> { [@obj, @obj].pack("a :" + pack_format) }.should complain(/unknown pack directive ':' in 'a :#{pack_format}'/)
end
end
ruby_version_is "3.3" do
- # https://bugs.ruby-lang.org/issues/19150
- # NOTE: Added this case just to not forget about the decision in the ticket
it "raise ArgumentError when a directive is unknown" do
# additional directive ('a') is required for the X directive
- -> { [@obj, @obj].pack("a R" + pack_format) }.should raise_error(ArgumentError)
- -> { [@obj, @obj].pack("a 0" + pack_format) }.should raise_error(ArgumentError)
- -> { [@obj, @obj].pack("a :" + pack_format) }.should raise_error(ArgumentError)
+ -> { [@obj, @obj].pack("a R" + pack_format) }.should raise_error(ArgumentError, /unknown pack directive 'R'/)
+ -> { [@obj, @obj].pack("a 0" + pack_format) }.should raise_error(ArgumentError, /unknown pack directive '0'/)
+ -> { [@obj, @obj].pack("a :" + pack_format) }.should raise_error(ArgumentError, /unknown pack directive ':'/)
end
end
diff --git a/spec/ruby/core/array/pack/shared/float.rb b/spec/ruby/core/array/pack/shared/float.rb
index 1780d7635e..76c800b74d 100644
--- a/spec/ruby/core/array/pack/shared/float.rb
+++ b/spec/ruby/core/array/pack/shared/float.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
describe :array_pack_float_le, shared: true do
it "encodes a positive Float" do
diff --git a/spec/ruby/core/array/pack/shared/integer.rb b/spec/ruby/core/array/pack/shared/integer.rb
index fd21b25b19..61f7cca184 100644
--- a/spec/ruby/core/array/pack/shared/integer.rb
+++ b/spec/ruby/core/array/pack/shared/integer.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
describe :array_pack_16bit_le, shared: true do
it "encodes the least significant 16 bits of a positive number" do
@@ -273,7 +273,7 @@ describe :array_pack_32bit_le_platform, shared: true do
str.should == "\x78\x65\x43\x12\xcd\xab\xf0\xde\x21\x43\x65\x78"
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
it "encodes the least significant 32 bits of a number that is greater than 32 bits" do
[ [[0xff_7865_4321], "\x21\x43\x65\x78"],
[[-0xff_7865_4321], "\xdf\xbc\x9a\x87"]
@@ -299,7 +299,7 @@ describe :array_pack_32bit_be_platform, shared: true do
str.should == "\x12\x43\x65\x78\xde\xf0\xab\xcd\x78\x65\x43\x21"
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
it "encodes the least significant 32 bits of a number that is greater than 32 bits" do
[ [[0xff_7865_4321], "\x78\x65\x43\x21"],
[[-0xff_7865_4321], "\x87\x9a\xbc\xdf"]
diff --git a/spec/ruby/core/array/pack/shared/string.rb b/spec/ruby/core/array/pack/shared/string.rb
index 2f70dc3951..805f78b53b 100644
--- a/spec/ruby/core/array/pack/shared/string.rb
+++ b/spec/ruby/core/array/pack/shared/string.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
describe :array_pack_string, shared: true do
it "adds count bytes of a String to the output" do
["abc"].pack(pack_format(2)).should == "ab"
diff --git a/spec/ruby/core/array/pack/u_spec.rb b/spec/ruby/core/array/pack/u_spec.rb
index b20093a647..1f84095ac4 100644
--- a/spec/ruby/core/array/pack/u_spec.rb
+++ b/spec/ruby/core/array/pack/u_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
diff --git a/spec/ruby/core/array/pack/w_spec.rb b/spec/ruby/core/array/pack/w_spec.rb
index 48ed4496a5..e770288d67 100644
--- a/spec/ruby/core/array/pack/w_spec.rb
+++ b/spec/ruby/core/array/pack/w_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
diff --git a/spec/ruby/core/array/pack/x_spec.rb b/spec/ruby/core/array/pack/x_spec.rb
index 86c3ad1aa4..012fe4567f 100644
--- a/spec/ruby/core/array/pack/x_spec.rb
+++ b/spec/ruby/core/array/pack/x_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
diff --git a/spec/ruby/core/array/pack/z_spec.rb b/spec/ruby/core/array/pack/z_spec.rb
index 5ad3afd69e..60f8f7bf10 100644
--- a/spec/ruby/core/array/pack/z_spec.rb
+++ b/spec/ruby/core/array/pack/z_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
@@ -26,7 +26,7 @@ describe "Array#pack with format 'Z'" do
["abc"].pack("Z*").should == "abc\x00"
end
- it "padds the output with NULL bytes when the count exceeds the size of the String" do
+ it "pads the output with NULL bytes when the count exceeds the size of the String" do
["abc"].pack("Z6").should == "abc\x00\x00\x00"
end
diff --git a/spec/ruby/core/array/plus_spec.rb b/spec/ruby/core/array/plus_spec.rb
index 635bd131c9..b7153fd3ef 100644
--- a/spec/ruby/core/array/plus_spec.rb
+++ b/spec/ruby/core/array/plus_spec.rb
@@ -21,7 +21,7 @@ describe "Array#+" do
([1, 2, 3] + obj).should == [1, 2, 3, "x", "y"]
end
- it "raises a Typeerror if the given argument can't be converted to an array" do
+ it "raises a TypeError if the given argument can't be converted to an array" do
-> { [1, 2, 3] + nil }.should raise_error(TypeError)
-> { [1, 2, 3] + "abc" }.should raise_error(TypeError)
end
diff --git a/spec/ruby/core/array/sample_spec.rb b/spec/ruby/core/array/sample_spec.rb
index 6ef78594f0..d4e945152d 100644
--- a/spec/ruby/core/array/sample_spec.rb
+++ b/spec/ruby/core/array/sample_spec.rb
@@ -114,6 +114,13 @@ describe "Array#sample" do
-> { [1, 2].sample(random: random) }.should raise_error(RangeError)
end
+
+ it "raises a RangeError if the value is greater than the Array size" do
+ random = mock("array_sample_random")
+ random.should_receive(:rand).and_return(3)
+
+ -> { [1, 2].sample(random: random) }.should raise_error(RangeError)
+ end
end
end
diff --git a/spec/ruby/core/array/shared/slice.rb b/spec/ruby/core/array/shared/slice.rb
index d2866970a5..b80261d32f 100644
--- a/spec/ruby/core/array/shared/slice.rb
+++ b/spec/ruby/core/array/shared/slice.rb
@@ -754,99 +754,97 @@ describe :array_slice, shared: true do
a.send(@method, (...-9)).should == []
end
- ruby_version_is "3.2" do
- describe "can be sliced with Enumerator::ArithmeticSequence" do
- it "with infinite/inverted ranges and negative steps" do
- @array = [0, 1, 2, 3, 4, 5]
- @array.send(@method, (2..).step(-1)).should == [2, 1, 0]
- @array.send(@method, (2..).step(-2)).should == [2, 0]
- @array.send(@method, (2..).step(-3)).should == [2]
- @array.send(@method, (2..).step(-4)).should == [2]
-
- @array.send(@method, (-3..).step(-1)).should == [3, 2, 1, 0]
- @array.send(@method, (-3..).step(-2)).should == [3, 1]
- @array.send(@method, (-3..).step(-3)).should == [3, 0]
- @array.send(@method, (-3..).step(-4)).should == [3]
- @array.send(@method, (-3..).step(-5)).should == [3]
-
- @array.send(@method, (..0).step(-1)).should == [5, 4, 3, 2, 1, 0]
- @array.send(@method, (..0).step(-2)).should == [5, 3, 1]
- @array.send(@method, (..0).step(-3)).should == [5, 2]
- @array.send(@method, (..0).step(-4)).should == [5, 1]
- @array.send(@method, (..0).step(-5)).should == [5, 0]
- @array.send(@method, (..0).step(-6)).should == [5]
- @array.send(@method, (..0).step(-7)).should == [5]
-
- @array.send(@method, (...0).step(-1)).should == [5, 4, 3, 2, 1]
- @array.send(@method, (...0).step(-2)).should == [5, 3, 1]
- @array.send(@method, (...0).step(-3)).should == [5, 2]
- @array.send(@method, (...0).step(-4)).should == [5, 1]
- @array.send(@method, (...0).step(-5)).should == [5]
- @array.send(@method, (...0).step(-6)).should == [5]
-
- @array.send(@method, (...1).step(-1)).should == [5, 4, 3, 2]
- @array.send(@method, (...1).step(-2)).should == [5, 3]
- @array.send(@method, (...1).step(-3)).should == [5, 2]
- @array.send(@method, (...1).step(-4)).should == [5]
- @array.send(@method, (...1).step(-5)).should == [5]
-
- @array.send(@method, (..-5).step(-1)).should == [5, 4, 3, 2, 1]
- @array.send(@method, (..-5).step(-2)).should == [5, 3, 1]
- @array.send(@method, (..-5).step(-3)).should == [5, 2]
- @array.send(@method, (..-5).step(-4)).should == [5, 1]
- @array.send(@method, (..-5).step(-5)).should == [5]
- @array.send(@method, (..-5).step(-6)).should == [5]
-
- @array.send(@method, (...-5).step(-1)).should == [5, 4, 3, 2]
- @array.send(@method, (...-5).step(-2)).should == [5, 3]
- @array.send(@method, (...-5).step(-3)).should == [5, 2]
- @array.send(@method, (...-5).step(-4)).should == [5]
- @array.send(@method, (...-5).step(-5)).should == [5]
-
- @array.send(@method, (4..1).step(-1)).should == [4, 3, 2, 1]
- @array.send(@method, (4..1).step(-2)).should == [4, 2]
- @array.send(@method, (4..1).step(-3)).should == [4, 1]
- @array.send(@method, (4..1).step(-4)).should == [4]
- @array.send(@method, (4..1).step(-5)).should == [4]
-
- @array.send(@method, (4...1).step(-1)).should == [4, 3, 2]
- @array.send(@method, (4...1).step(-2)).should == [4, 2]
- @array.send(@method, (4...1).step(-3)).should == [4]
- @array.send(@method, (4...1).step(-4)).should == [4]
-
- @array.send(@method, (-2..1).step(-1)).should == [4, 3, 2, 1]
- @array.send(@method, (-2..1).step(-2)).should == [4, 2]
- @array.send(@method, (-2..1).step(-3)).should == [4, 1]
- @array.send(@method, (-2..1).step(-4)).should == [4]
- @array.send(@method, (-2..1).step(-5)).should == [4]
-
- @array.send(@method, (-2...1).step(-1)).should == [4, 3, 2]
- @array.send(@method, (-2...1).step(-2)).should == [4, 2]
- @array.send(@method, (-2...1).step(-3)).should == [4]
- @array.send(@method, (-2...1).step(-4)).should == [4]
-
- @array.send(@method, (4..-5).step(-1)).should == [4, 3, 2, 1]
- @array.send(@method, (4..-5).step(-2)).should == [4, 2]
- @array.send(@method, (4..-5).step(-3)).should == [4, 1]
- @array.send(@method, (4..-5).step(-4)).should == [4]
- @array.send(@method, (4..-5).step(-5)).should == [4]
-
- @array.send(@method, (4...-5).step(-1)).should == [4, 3, 2]
- @array.send(@method, (4...-5).step(-2)).should == [4, 2]
- @array.send(@method, (4...-5).step(-3)).should == [4]
- @array.send(@method, (4...-5).step(-4)).should == [4]
-
- @array.send(@method, (-2..-5).step(-1)).should == [4, 3, 2, 1]
- @array.send(@method, (-2..-5).step(-2)).should == [4, 2]
- @array.send(@method, (-2..-5).step(-3)).should == [4, 1]
- @array.send(@method, (-2..-5).step(-4)).should == [4]
- @array.send(@method, (-2..-5).step(-5)).should == [4]
-
- @array.send(@method, (-2...-5).step(-1)).should == [4, 3, 2]
- @array.send(@method, (-2...-5).step(-2)).should == [4, 2]
- @array.send(@method, (-2...-5).step(-3)).should == [4]
- @array.send(@method, (-2...-5).step(-4)).should == [4]
- end
+ describe "can be sliced with Enumerator::ArithmeticSequence" do
+ it "with infinite/inverted ranges and negative steps" do
+ @array = [0, 1, 2, 3, 4, 5]
+ @array.send(@method, (2..).step(-1)).should == [2, 1, 0]
+ @array.send(@method, (2..).step(-2)).should == [2, 0]
+ @array.send(@method, (2..).step(-3)).should == [2]
+ @array.send(@method, (2..).step(-4)).should == [2]
+
+ @array.send(@method, (-3..).step(-1)).should == [3, 2, 1, 0]
+ @array.send(@method, (-3..).step(-2)).should == [3, 1]
+ @array.send(@method, (-3..).step(-3)).should == [3, 0]
+ @array.send(@method, (-3..).step(-4)).should == [3]
+ @array.send(@method, (-3..).step(-5)).should == [3]
+
+ @array.send(@method, (..0).step(-1)).should == [5, 4, 3, 2, 1, 0]
+ @array.send(@method, (..0).step(-2)).should == [5, 3, 1]
+ @array.send(@method, (..0).step(-3)).should == [5, 2]
+ @array.send(@method, (..0).step(-4)).should == [5, 1]
+ @array.send(@method, (..0).step(-5)).should == [5, 0]
+ @array.send(@method, (..0).step(-6)).should == [5]
+ @array.send(@method, (..0).step(-7)).should == [5]
+
+ @array.send(@method, (...0).step(-1)).should == [5, 4, 3, 2, 1]
+ @array.send(@method, (...0).step(-2)).should == [5, 3, 1]
+ @array.send(@method, (...0).step(-3)).should == [5, 2]
+ @array.send(@method, (...0).step(-4)).should == [5, 1]
+ @array.send(@method, (...0).step(-5)).should == [5]
+ @array.send(@method, (...0).step(-6)).should == [5]
+
+ @array.send(@method, (...1).step(-1)).should == [5, 4, 3, 2]
+ @array.send(@method, (...1).step(-2)).should == [5, 3]
+ @array.send(@method, (...1).step(-3)).should == [5, 2]
+ @array.send(@method, (...1).step(-4)).should == [5]
+ @array.send(@method, (...1).step(-5)).should == [5]
+
+ @array.send(@method, (..-5).step(-1)).should == [5, 4, 3, 2, 1]
+ @array.send(@method, (..-5).step(-2)).should == [5, 3, 1]
+ @array.send(@method, (..-5).step(-3)).should == [5, 2]
+ @array.send(@method, (..-5).step(-4)).should == [5, 1]
+ @array.send(@method, (..-5).step(-5)).should == [5]
+ @array.send(@method, (..-5).step(-6)).should == [5]
+
+ @array.send(@method, (...-5).step(-1)).should == [5, 4, 3, 2]
+ @array.send(@method, (...-5).step(-2)).should == [5, 3]
+ @array.send(@method, (...-5).step(-3)).should == [5, 2]
+ @array.send(@method, (...-5).step(-4)).should == [5]
+ @array.send(@method, (...-5).step(-5)).should == [5]
+
+ @array.send(@method, (4..1).step(-1)).should == [4, 3, 2, 1]
+ @array.send(@method, (4..1).step(-2)).should == [4, 2]
+ @array.send(@method, (4..1).step(-3)).should == [4, 1]
+ @array.send(@method, (4..1).step(-4)).should == [4]
+ @array.send(@method, (4..1).step(-5)).should == [4]
+
+ @array.send(@method, (4...1).step(-1)).should == [4, 3, 2]
+ @array.send(@method, (4...1).step(-2)).should == [4, 2]
+ @array.send(@method, (4...1).step(-3)).should == [4]
+ @array.send(@method, (4...1).step(-4)).should == [4]
+
+ @array.send(@method, (-2..1).step(-1)).should == [4, 3, 2, 1]
+ @array.send(@method, (-2..1).step(-2)).should == [4, 2]
+ @array.send(@method, (-2..1).step(-3)).should == [4, 1]
+ @array.send(@method, (-2..1).step(-4)).should == [4]
+ @array.send(@method, (-2..1).step(-5)).should == [4]
+
+ @array.send(@method, (-2...1).step(-1)).should == [4, 3, 2]
+ @array.send(@method, (-2...1).step(-2)).should == [4, 2]
+ @array.send(@method, (-2...1).step(-3)).should == [4]
+ @array.send(@method, (-2...1).step(-4)).should == [4]
+
+ @array.send(@method, (4..-5).step(-1)).should == [4, 3, 2, 1]
+ @array.send(@method, (4..-5).step(-2)).should == [4, 2]
+ @array.send(@method, (4..-5).step(-3)).should == [4, 1]
+ @array.send(@method, (4..-5).step(-4)).should == [4]
+ @array.send(@method, (4..-5).step(-5)).should == [4]
+
+ @array.send(@method, (4...-5).step(-1)).should == [4, 3, 2]
+ @array.send(@method, (4...-5).step(-2)).should == [4, 2]
+ @array.send(@method, (4...-5).step(-3)).should == [4]
+ @array.send(@method, (4...-5).step(-4)).should == [4]
+
+ @array.send(@method, (-2..-5).step(-1)).should == [4, 3, 2, 1]
+ @array.send(@method, (-2..-5).step(-2)).should == [4, 2]
+ @array.send(@method, (-2..-5).step(-3)).should == [4, 1]
+ @array.send(@method, (-2..-5).step(-4)).should == [4]
+ @array.send(@method, (-2..-5).step(-5)).should == [4]
+
+ @array.send(@method, (-2...-5).step(-1)).should == [4, 3, 2]
+ @array.send(@method, (-2...-5).step(-2)).should == [4, 2]
+ @array.send(@method, (-2...-5).step(-3)).should == [4]
+ @array.send(@method, (-2...-5).step(-4)).should == [4]
end
end
diff --git a/spec/ruby/core/array/shared/unshift.rb b/spec/ruby/core/array/shared/unshift.rb
index 4941e098f6..9e0fe7556a 100644
--- a/spec/ruby/core/array/shared/unshift.rb
+++ b/spec/ruby/core/array/shared/unshift.rb
@@ -49,7 +49,7 @@ describe :array_unshift, shared: true do
-> { ArraySpecs.frozen_array.send(@method) }.should raise_error(FrozenError)
end
- # https://github.com/oracle/truffleruby/issues/2772
+ # https://github.com/truffleruby/truffleruby/issues/2772
it "doesn't rely on Array#[]= so it can be overridden" do
subclass = Class.new(Array) do
def []=(*)
diff --git a/spec/ruby/core/array/shuffle_spec.rb b/spec/ruby/core/array/shuffle_spec.rb
index 1d528c124f..b84394bcb5 100644
--- a/spec/ruby/core/array/shuffle_spec.rb
+++ b/spec/ruby/core/array/shuffle_spec.rb
@@ -69,9 +69,18 @@ describe "Array#shuffle" do
-> { [1, 2].shuffle(random: random) }.should raise_error(RangeError)
end
- it "raises a RangeError if the value is equal to one" do
+ it "raises a RangeError if the value is equal to the Array size" do
value = mock("array_shuffle_random_value")
- value.should_receive(:to_int).at_least(1).times.and_return(1)
+ value.should_receive(:to_int).at_least(1).times.and_return(2)
+ random = mock("array_shuffle_random")
+ random.should_receive(:rand).at_least(1).times.and_return(value)
+
+ -> { [1, 2].shuffle(random: random) }.should raise_error(RangeError)
+ end
+
+ it "raises a RangeError if the value is greater than the Array size" do
+ value = mock("array_shuffle_random_value")
+ value.should_receive(:to_int).at_least(1).times.and_return(3)
random = mock("array_shuffle_random")
random.should_receive(:rand).at_least(1).times.and_return(value)
diff --git a/spec/ruby/core/array/to_h_spec.rb b/spec/ruby/core/array/to_h_spec.rb
index f4578211a1..1c814f3d01 100644
--- a/spec/ruby/core/array/to_h_spec.rb
+++ b/spec/ruby/core/array/to_h_spec.rb
@@ -45,6 +45,12 @@ describe "Array#to_h" do
[:a, :b].to_h { |k| [k, k.to_s] }.should == { a: 'a', b: 'b' }
end
+ it "passes to a block each element as a single argument" do
+ ScratchPad.record []
+ [[:a, 1], [:b, 2]].to_h { |*args| ScratchPad << args; [args[0], args[1]] }
+ ScratchPad.recorded.sort.should == [[[:a, 1]], [[:b, 2]]]
+ end
+
it "raises ArgumentError if block returns longer or shorter array" do
-> do
[:a, :b].to_h { |k| [k, k.to_s, 1] }
diff --git a/spec/ruby/core/basicobject/equal_spec.rb b/spec/ruby/core/basicobject/equal_spec.rb
index 3c1ad56d4a..ce28eaed95 100644
--- a/spec/ruby/core/basicobject/equal_spec.rb
+++ b/spec/ruby/core/basicobject/equal_spec.rb
@@ -11,8 +11,10 @@ describe "BasicObject#equal?" do
it "is unaffected by overriding __id__" do
o1 = mock("object")
o2 = mock("object")
- def o1.__id__; 10; end
- def o2.__id__; 10; end
+ suppress_warning {
+ def o1.__id__; 10; end
+ def o2.__id__; 10; end
+ }
o1.equal?(o2).should be_false
end
diff --git a/spec/ruby/core/basicobject/instance_eval_spec.rb b/spec/ruby/core/basicobject/instance_eval_spec.rb
index 1f3a43f341..633b5c2cb1 100644
--- a/spec/ruby/core/basicobject/instance_eval_spec.rb
+++ b/spec/ruby/core/basicobject/instance_eval_spec.rb
@@ -141,22 +141,11 @@ describe "BasicObject#instance_eval" do
caller.get_constant_with_string(receiver).should == :singleton_class
end
- ruby_version_is ""..."3.1" do
- it "looks in the caller scope next" do
- receiver = BasicObjectSpecs::InstEval::Constants::ConstantInReceiverClass::ReceiverScope::Receiver.new
- caller = BasicObjectSpecs::InstEval::Constants::ConstantInReceiverClass::CallerScope::Caller.new
+ it "looks in the receiver class next" do
+ receiver = BasicObjectSpecs::InstEval::Constants::ConstantInReceiverClass::ReceiverScope::Receiver.new
+ caller = BasicObjectSpecs::InstEval::Constants::ConstantInReceiverClass::CallerScope::Caller.new
- caller.get_constant_with_string(receiver).should == :Caller
- end
- end
-
- ruby_version_is "3.1" do
- it "looks in the receiver class next" do
- receiver = BasicObjectSpecs::InstEval::Constants::ConstantInReceiverClass::ReceiverScope::Receiver.new
- caller = BasicObjectSpecs::InstEval::Constants::ConstantInReceiverClass::CallerScope::Caller.new
-
- caller.get_constant_with_string(receiver).should == :Receiver
- end
+ caller.get_constant_with_string(receiver).should == :Receiver
end
it "looks in the caller class next" do
diff --git a/spec/ruby/core/basicobject/instance_exec_spec.rb b/spec/ruby/core/basicobject/instance_exec_spec.rb
index 289fdd889b..370f03d33c 100644
--- a/spec/ruby/core/basicobject/instance_exec_spec.rb
+++ b/spec/ruby/core/basicobject/instance_exec_spec.rb
@@ -84,17 +84,17 @@ describe "BasicObject#instance_exec" do
end.should raise_error(TypeError)
end
-quarantine! do # Not clean, leaves cvars lying around to break other specs
- 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
- Integer.__send__(:remove_class_variable, :@@__tmp_instance_exec_spec)
+ quarantine! do # Not clean, leaves cvars lying around to break other specs
+ 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
+ Integer.__send__(:remove_class_variable, :@@__tmp_instance_exec_spec)
+ end
end
-end
it "raises a TypeError when defining methods on numerics" do
-> do
diff --git a/spec/ruby/core/basicobject/singleton_method_added_spec.rb b/spec/ruby/core/basicobject/singleton_method_added_spec.rb
index fc65a091aa..bd21458ea7 100644
--- a/spec/ruby/core/basicobject/singleton_method_added_spec.rb
+++ b/spec/ruby/core/basicobject/singleton_method_added_spec.rb
@@ -96,6 +96,8 @@ describe "BasicObject#singleton_method_added" do
end
}.should raise_error(NoMethodError, /undefined method [`']singleton_method_added' for/)
end
+ ensure
+ BasicObjectSpecs.send(:remove_const, :NoSingletonMethodAdded)
end
it "raises NoMethodError for a singleton instance" do
diff --git a/spec/ruby/core/binding/fixtures/irb.rb b/spec/ruby/core/binding/fixtures/irb.rb
deleted file mode 100644
index 5f305f2d5d..0000000000
--- a/spec/ruby/core/binding/fixtures/irb.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-a = 10
-
-binding.irb
diff --git a/spec/ruby/core/binding/shared/clone.rb b/spec/ruby/core/binding/shared/clone.rb
index 1224b8ec7d..2d854fce96 100644
--- a/spec/ruby/core/binding/shared/clone.rb
+++ b/spec/ruby/core/binding/shared/clone.rb
@@ -40,7 +40,7 @@ describe :binding_clone, shared: true do
end
it "copies the finalizer" do
- code = <<-RUBY
+ code = <<-'RUBY'
obj = binding
ObjectSpace.define_finalizer(obj, Proc.new { STDOUT.write "finalized\n" })
diff --git a/spec/ruby/core/builtin_constants/builtin_constants_spec.rb b/spec/ruby/core/builtin_constants/builtin_constants_spec.rb
index 1960f5721f..13e066cc7f 100644
--- a/spec/ruby/core/builtin_constants/builtin_constants_spec.rb
+++ b/spec/ruby/core/builtin_constants/builtin_constants_spec.rb
@@ -4,6 +4,10 @@ describe "RUBY_VERSION" do
it "is a String" do
RUBY_VERSION.should be_kind_of(String)
end
+
+ it "is frozen" do
+ RUBY_VERSION.should.frozen?
+ end
end
describe "RUBY_PATCHLEVEL" do
@@ -16,34 +20,132 @@ describe "RUBY_COPYRIGHT" do
it "is a String" do
RUBY_COPYRIGHT.should be_kind_of(String)
end
+
+ it "is frozen" do
+ RUBY_COPYRIGHT.should.frozen?
+ end
end
describe "RUBY_DESCRIPTION" do
it "is a String" do
RUBY_DESCRIPTION.should be_kind_of(String)
end
+
+ it "is frozen" do
+ RUBY_DESCRIPTION.should.frozen?
+ end
end
describe "RUBY_ENGINE" do
it "is a String" do
RUBY_ENGINE.should be_kind_of(String)
end
+
+ it "is frozen" do
+ RUBY_ENGINE.should.frozen?
+ end
+end
+
+describe "RUBY_ENGINE_VERSION" do
+ it "is a String" do
+ RUBY_ENGINE_VERSION.should be_kind_of(String)
+ end
+
+ it "is frozen" do
+ RUBY_ENGINE_VERSION.should.frozen?
+ end
end
describe "RUBY_PLATFORM" do
it "is a String" do
RUBY_PLATFORM.should be_kind_of(String)
end
+
+ it "is frozen" do
+ RUBY_PLATFORM.should.frozen?
+ end
end
describe "RUBY_RELEASE_DATE" do
it "is a String" do
RUBY_RELEASE_DATE.should be_kind_of(String)
end
+
+ it "is frozen" do
+ RUBY_RELEASE_DATE.should.frozen?
+ end
end
describe "RUBY_REVISION" do
it "is a String" do
RUBY_REVISION.should be_kind_of(String)
end
+
+ it "is frozen" do
+ RUBY_REVISION.should.frozen?
+ end
+end
+
+ruby_version_is "4.0" do
+ context "The constant" do
+ describe "Ruby" do
+ it "is a Module" do
+ Ruby.should.instance_of?(Module)
+ end
+ end
+
+ describe "Ruby::VERSION" do
+ it "is equal to RUBY_VERSION" do
+ Ruby::VERSION.should equal(RUBY_VERSION)
+ end
+ end
+
+ describe "RUBY::PATCHLEVEL" do
+ it "is equal to RUBY_PATCHLEVEL" do
+ Ruby::PATCHLEVEL.should equal(RUBY_PATCHLEVEL)
+ end
+ end
+
+ describe "Ruby::COPYRIGHT" do
+ it "is equal to RUBY_COPYRIGHT" do
+ Ruby::COPYRIGHT.should equal(RUBY_COPYRIGHT)
+ end
+ end
+
+ describe "Ruby::DESCRIPTION" do
+ it "is equal to RUBY_DESCRIPTION" do
+ Ruby::DESCRIPTION.should equal(RUBY_DESCRIPTION)
+ end
+ end
+
+ describe "Ruby::ENGINE" do
+ it "is equal to RUBY_ENGINE" do
+ Ruby::ENGINE.should equal(RUBY_ENGINE)
+ end
+ end
+
+ describe "Ruby::ENGINE_VERSION" do
+ it "is equal to RUBY_ENGINE_VERSION" do
+ Ruby::ENGINE_VERSION.should equal(RUBY_ENGINE_VERSION)
+ end
+ end
+
+ describe "Ruby::PLATFORM" do
+ it "is equal to RUBY_PLATFORM" do
+ Ruby::PLATFORM.should equal(RUBY_PLATFORM)
+ end
+ end
+
+ describe "Ruby::RELEASE_DATE" do
+ it "is equal to RUBY_RELEASE_DATE" do
+ Ruby::RELEASE_DATE.should equal(RUBY_RELEASE_DATE)
+ end
+ end
+
+ describe "Ruby::REVISION" do
+ it "is equal to RUBY_REVISION" do
+ Ruby::REVISION.should equal(RUBY_REVISION)
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/class/attached_object_spec.rb b/spec/ruby/core/class/attached_object_spec.rb
index f1c0f63a44..8f8a0734c6 100644
--- a/spec/ruby/core/class/attached_object_spec.rb
+++ b/spec/ruby/core/class/attached_object_spec.rb
@@ -1,31 +1,29 @@
require_relative '../../spec_helper'
-ruby_version_is '3.2' do
- describe "Class#attached_object" do
- it "returns the object that is attached to a singleton class" do
- a = Class.new
+describe "Class#attached_object" do
+ it "returns the object that is attached to a singleton class" do
+ a = Class.new
- a_obj = a.new
- a_obj.singleton_class.attached_object.should == a_obj
- end
+ a_obj = a.new
+ a_obj.singleton_class.attached_object.should == a_obj
+ end
- it "returns the class object that is attached to a class's singleton class" do
- a = Class.new
- singleton_class = (class << a; self; end)
+ it "returns the class object that is attached to a class's singleton class" do
+ a = Class.new
+ singleton_class = (class << a; self; end)
- singleton_class.attached_object.should == a
- end
+ singleton_class.attached_object.should == a
+ end
- it "raises TypeError if the class is not a singleton class" do
- a = Class.new
+ it "raises TypeError if the class is not a singleton class" do
+ a = Class.new
- -> { a.attached_object }.should raise_error(TypeError, /is not a singleton class/)
- end
+ -> { a.attached_object }.should raise_error(TypeError, /is not a singleton class/)
+ end
- it "raises TypeError for special singleton classes" do
- -> { nil.singleton_class.attached_object }.should raise_error(TypeError, /[`']NilClass' is not a singleton class/)
- -> { true.singleton_class.attached_object }.should raise_error(TypeError, /[`']TrueClass' is not a singleton class/)
- -> { false.singleton_class.attached_object }.should raise_error(TypeError, /[`']FalseClass' is not a singleton class/)
- end
+ it "raises TypeError for special singleton classes" do
+ -> { nil.singleton_class.attached_object }.should raise_error(TypeError, /[`']NilClass' is not a singleton class/)
+ -> { true.singleton_class.attached_object }.should raise_error(TypeError, /[`']TrueClass' is not a singleton class/)
+ -> { false.singleton_class.attached_object }.should raise_error(TypeError, /[`']FalseClass' is not a singleton class/)
end
end
diff --git a/spec/ruby/core/class/dup_spec.rb b/spec/ruby/core/class/dup_spec.rb
index c09ed71b31..1ff9abf7b4 100644
--- a/spec/ruby/core/class/dup_spec.rb
+++ b/spec/ruby/core/class/dup_spec.rb
@@ -59,6 +59,8 @@ describe "Class#dup" do
it "stores the new name if assigned to a constant" do
CoreClassSpecs::RecordCopy = CoreClassSpecs::Record.dup
CoreClassSpecs::RecordCopy.name.should == "CoreClassSpecs::RecordCopy"
+ ensure
+ CoreClassSpecs.send(:remove_const, :RecordCopy)
end
it "raises TypeError if called on BasicObject" do
diff --git a/spec/ruby/core/class/inherited_spec.rb b/spec/ruby/core/class/inherited_spec.rb
index 8ef8bb8c35..2a8d1ff813 100644
--- a/spec/ruby/core/class/inherited_spec.rb
+++ b/spec/ruby/core/class/inherited_spec.rb
@@ -98,4 +98,21 @@ describe "Class.inherited" do
-> { Class.new(top) }.should_not raise_error
end
+ it "if the subclass is assigned to a constant, it is all set" do
+ ScratchPad.record []
+
+ parent = Class.new do
+ def self.inherited(subclass)
+ ScratchPad << defined?(self::C)
+ ScratchPad << const_defined?(:C)
+ ScratchPad << constants
+ ScratchPad << const_get(:C)
+ ScratchPad << subclass.name.match?(/\A#<Class:0x\w+>::C\z/)
+ end
+ end
+
+ class parent::C < parent; end
+
+ ScratchPad.recorded.should == ["constant", true, [:C], parent::C, true]
+ end
end
diff --git a/spec/ruby/core/class/new_spec.rb b/spec/ruby/core/class/new_spec.rb
index 93152a83ee..6fe54c3209 100644
--- a/spec/ruby/core/class/new_spec.rb
+++ b/spec/ruby/core/class/new_spec.rb
@@ -83,6 +83,8 @@ describe "Class.new" do
a = Class.new
MyClass::NestedClass = a
MyClass::NestedClass.name.should == "MyClass::NestedClass"
+ ensure
+ Object.send(:remove_const, :MyClass)
end
it "sets the new class' superclass to the given class" do
diff --git a/spec/ruby/core/class/subclasses_spec.rb b/spec/ruby/core/class/subclasses_spec.rb
index 50eb5358d9..f692152787 100644
--- a/spec/ruby/core/class/subclasses_spec.rb
+++ b/spec/ruby/core/class/subclasses_spec.rb
@@ -1,87 +1,85 @@
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
+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 from the parent" do
- parent = Class.new
- child = Class.new(parent)
- mod = Module.new
- parent.include(mod)
+ it "does not return included modules from the parent" do
+ parent = Class.new
+ child = Class.new(parent)
+ mod = Module.new
+ parent.include(mod)
- assert_subclasses(parent, [child])
- end
-
- it "does not return included modules from the child" do
- parent = Class.new
- child = Class.new(parent)
- mod = Module.new
- parent.include(mod)
+ assert_subclasses(parent, [child])
+ end
- assert_subclasses(parent, [child])
- end
+ it "does not return included modules from the child" do
+ parent = Class.new
+ child = Class.new(parent)
+ mod = Module.new
+ parent.include(mod)
- it "does not return prepended modules from the parent" do
- parent = Class.new
- child = Class.new(parent)
- mod = Module.new
- parent.prepend(mod)
+ assert_subclasses(parent, [child])
+ end
- assert_subclasses(parent, [child])
- end
+ it "does not return prepended modules from the parent" do
+ parent = Class.new
+ child = Class.new(parent)
+ mod = Module.new
+ parent.prepend(mod)
- it "does not return prepended modules from the child" do
- parent = Class.new
- child = Class.new(parent)
- mod = Module.new
- child.prepend(mod)
+ assert_subclasses(parent, [child])
+ end
- assert_subclasses(parent, [child])
- end
+ it "does not return prepended modules from the child" do
+ parent = Class.new
+ child = Class.new(parent)
+ mod = Module.new
+ child.prepend(mod)
- it "does not return singleton classes" do
- a = Class.new
+ assert_subclasses(parent, [child])
+ end
- a_obj = a.new
- def a_obj.force_singleton_class
- 42
- end
+ it "does not return singleton classes" do
+ a = Class.new
- a.subclasses.should_not include(a_obj.singleton_class)
+ a_obj = a.new
+ def a_obj.force_singleton_class
+ 42
end
- it "has 1 entry per module or class" do
- ModuleSpecs::Parent.subclasses.should == ModuleSpecs::Parent.subclasses.uniq
- 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
- it "works when creating subclasses concurrently" do
- t = 16
- n = 1000
- go = false
- superclass = Class.new
-
- threads = t.times.map do
- Thread.new do
- Thread.pass until go
- n.times.map do
- Class.new(superclass)
- end
+ it "works when creating subclasses concurrently" do
+ t = 16
+ n = 1000
+ go = false
+ superclass = Class.new
+
+ threads = t.times.map do
+ Thread.new do
+ Thread.pass until go
+ n.times.map do
+ Class.new(superclass)
end
end
+ end
- go = true
- classes = threads.map(&:value)
+ go = true
+ classes = threads.map(&:value)
- superclass.subclasses.size.should == t * n
- superclass.subclasses.each { |c| c.should be_kind_of(Class) }
- end
+ superclass.subclasses.size.should == t * n
+ superclass.subclasses.each { |c| c.should be_kind_of(Class) }
+ end
- def assert_subclasses(mod,subclasses)
- mod.subclasses.sort_by(&:inspect).should == subclasses.sort_by(&:inspect)
- end
+ def assert_subclasses(mod,subclasses)
+ mod.subclasses.sort_by(&:inspect).should == subclasses.sort_by(&:inspect)
end
end
diff --git a/spec/ruby/core/comparable/clamp_spec.rb b/spec/ruby/core/comparable/clamp_spec.rb
index 796d4a18c1..18f616a997 100644
--- a/spec/ruby/core/comparable/clamp_spec.rb
+++ b/spec/ruby/core/comparable/clamp_spec.rb
@@ -24,7 +24,7 @@ describe 'Comparable#clamp' do
c.clamp(two, three).should equal(c)
end
- it 'returns the min parameter if smaller than it' do
+ it 'returns the min parameter if less than it' do
one = ComparableSpecs::WithOnlyCompareDefined.new(1)
two = ComparableSpecs::WithOnlyCompareDefined.new(2)
c = ComparableSpecs::Weird.new(0)
@@ -40,6 +40,39 @@ describe 'Comparable#clamp' do
c.clamp(one, two).should equal(two)
end
+ context 'max is nil' do
+ it 'returns min if less than it' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ c = ComparableSpecs::Weird.new(0)
+ c.clamp(one, nil).should equal(one)
+ end
+
+ it 'always returns self if greater than min' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ c = ComparableSpecs::Weird.new(2)
+ c.clamp(one, nil).should equal(c)
+ end
+ end
+
+ context 'min is nil' do
+ it 'returns max if greater than it' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ c = ComparableSpecs::Weird.new(2)
+ c.clamp(nil, one).should equal(one)
+ end
+
+ it 'always returns self if less than max' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ c = ComparableSpecs::Weird.new(0)
+ c.clamp(nil, one).should equal(c)
+ end
+ end
+
+ it 'always returns self when min is nil and max is nil' do
+ c = ComparableSpecs::Weird.new(1)
+ c.clamp(nil, nil).should equal(c)
+ end
+
it 'returns self if within the given range parameters' do
one = ComparableSpecs::WithOnlyCompareDefined.new(1)
two = ComparableSpecs::WithOnlyCompareDefined.new(2)
@@ -52,7 +85,7 @@ describe 'Comparable#clamp' do
c.clamp(two..three).should equal(c)
end
- it 'returns the minimum value of the range parameters if smaller than it' do
+ it 'returns the minimum value of the range parameters if less than it' do
one = ComparableSpecs::WithOnlyCompareDefined.new(1)
two = ComparableSpecs::WithOnlyCompareDefined.new(2)
c = ComparableSpecs::Weird.new(0)
@@ -75,4 +108,116 @@ describe 'Comparable#clamp' do
-> { c.clamp(one...two) }.should raise_error(ArgumentError)
end
+
+ context 'with nil as the max argument' do
+ it 'returns min argument if less than it' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ zero = ComparableSpecs::WithOnlyCompareDefined.new(0)
+ c = ComparableSpecs::Weird.new(0)
+
+ c.clamp(one, nil).should equal(one)
+ c.clamp(zero, nil).should equal(c)
+ end
+
+ it 'always returns self if greater than min argument' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ two = ComparableSpecs::WithOnlyCompareDefined.new(2)
+ c = ComparableSpecs::Weird.new(2)
+
+ c.clamp(one, nil).should equal(c)
+ c.clamp(two, nil).should equal(c)
+ end
+ end
+
+ context 'with endless range' do
+ it 'returns minimum value of the range parameters if less than it' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ zero = ComparableSpecs::WithOnlyCompareDefined.new(0)
+ c = ComparableSpecs::Weird.new(0)
+
+ c.clamp(one..).should equal(one)
+ c.clamp(zero..).should equal(c)
+ end
+
+ it 'always returns self if greater than minimum value of the range parameters' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ two = ComparableSpecs::WithOnlyCompareDefined.new(2)
+ c = ComparableSpecs::Weird.new(2)
+
+ c.clamp(one..).should equal(c)
+ c.clamp(two..).should equal(c)
+ end
+
+ it 'works with exclusive range' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ c = ComparableSpecs::Weird.new(2)
+
+ c.clamp(one...).should equal(c)
+ end
+ end
+
+ context 'with nil as the min argument' do
+ it 'returns max argument if greater than it' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ c = ComparableSpecs::Weird.new(2)
+
+ c.clamp(nil, one).should equal(one)
+ end
+
+ it 'always returns self if less than max argument' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ zero = ComparableSpecs::WithOnlyCompareDefined.new(0)
+ c = ComparableSpecs::Weird.new(0)
+
+ c.clamp(nil, one).should equal(c)
+ c.clamp(nil, zero).should equal(c)
+ end
+ end
+
+ context 'with beginless range' do
+ it 'returns maximum value of the range parameters if greater than it' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ c = ComparableSpecs::Weird.new(2)
+
+ c.clamp(..one).should equal(one)
+ end
+
+ it 'always returns self if less than maximum value of the range parameters' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ zero = ComparableSpecs::WithOnlyCompareDefined.new(0)
+ c = ComparableSpecs::Weird.new(0)
+
+ c.clamp(..one).should equal(c)
+ c.clamp(..zero).should equal(c)
+ end
+
+ it 'raises an Argument error if the range parameter is exclusive' do
+ one = ComparableSpecs::WithOnlyCompareDefined.new(1)
+ c = ComparableSpecs::Weird.new(0)
+
+ -> { c.clamp(...one) }.should raise_error(ArgumentError)
+ end
+ end
+
+ context 'with nil as the min and the max argument' do
+ it 'always returns self' do
+ c = ComparableSpecs::Weird.new(1)
+
+ c.clamp(nil, nil).should equal(c)
+ end
+ end
+
+ context 'with beginless-and-endless range' do
+ it 'always returns self' do
+ c = ComparableSpecs::Weird.new(1)
+
+ c.clamp(nil..nil).should equal(c)
+ end
+
+ it 'works with exclusive range' do
+ c = ComparableSpecs::Weird.new(2)
+
+ c.clamp(nil...nil).should equal(c)
+ end
+ end
end
diff --git a/spec/ruby/core/comparable/fixtures/classes.rb b/spec/ruby/core/comparable/fixtures/classes.rb
index 4239a47d2f..2bdabbf014 100644
--- a/spec/ruby/core/comparable/fixtures/classes.rb
+++ b/spec/ruby/core/comparable/fixtures/classes.rb
@@ -7,6 +7,7 @@ module ComparableSpecs
end
def <=>(other)
+ return nil if other.nil?
self.value <=> other.value
end
end
diff --git a/spec/ruby/core/complex/equal_value_spec.rb b/spec/ruby/core/complex/equal_value_spec.rb
index ad7236b1bd..97c486d820 100644
--- a/spec/ruby/core/complex/equal_value_spec.rb
+++ b/spec/ruby/core/complex/equal_value_spec.rb
@@ -76,7 +76,7 @@ describe "Complex#==" do
(Complex(real, 0) == @other).should be_true
end
- it "returns false when when the imaginary part is not zero" do
+ it "returns false when the imaginary part is not zero" do
(Complex(3, 1) == @other).should be_false
end
end
diff --git a/spec/ruby/core/complex/polar_spec.rb b/spec/ruby/core/complex/polar_spec.rb
index 3bb3751bc6..56335584ef 100644
--- a/spec/ruby/core/complex/polar_spec.rb
+++ b/spec/ruby/core/complex/polar_spec.rb
@@ -11,20 +11,18 @@ describe "Complex.polar" do
->{ Complex.polar(nil, nil) }.should raise_error(TypeError)
end
- ruby_bug "#19004", ""..."3.2" do
- it "computes the real values of the real & imaginary parts from the polar form" do
- a = Complex.polar(1.0+0.0i, Math::PI/2+0.0i)
- a.real.should be_close(0.0, TOLERANCE)
- a.imag.should be_close(1.0, TOLERANCE)
- a.real.real?.should be_true
- a.imag.real?.should be_true
+ it "computes the real values of the real & imaginary parts from the polar form" do
+ a = Complex.polar(1.0+0.0i, Math::PI/2+0.0i)
+ a.real.should be_close(0.0, TOLERANCE)
+ a.imag.should be_close(1.0, TOLERANCE)
+ a.real.real?.should be_true
+ a.imag.real?.should be_true
- b = Complex.polar(1+0.0i)
- b.real.should be_close(1.0, TOLERANCE)
- b.imag.should be_close(0.0, TOLERANCE)
- b.real.real?.should be_true
- b.imag.real?.should be_true
- end
+ b = Complex.polar(1+0.0i)
+ b.real.should be_close(1.0, TOLERANCE)
+ b.imag.should be_close(0.0, TOLERANCE)
+ b.real.real?.should be_true
+ b.imag.real?.should be_true
end
end
diff --git a/spec/ruby/core/complex/shared/rect.rb b/spec/ruby/core/complex/shared/rect.rb
index 9f5de1ffeb..4ac294e771 100644
--- a/spec/ruby/core/complex/shared/rect.rb
+++ b/spec/ruby/core/complex/shared/rect.rb
@@ -24,15 +24,15 @@ describe :complex_rect, shared: true do
end
it "returns the real part of self as the first element" do
- @numbers.each do |number|
- number.send(@method).first.should == number.real
- end
+ @numbers.each do |number|
+ number.send(@method).first.should == number.real
+ end
end
it "returns the imaginary part of self as the last element" do
- @numbers.each do |number|
- number.send(@method).last.should == number.imaginary
- end
+ @numbers.each do |number|
+ number.send(@method).last.should == number.imaginary
+ end
end
it "raises an ArgumentError if given any arguments" do
diff --git a/spec/ruby/core/data/constants_spec.rb b/spec/ruby/core/data/constants_spec.rb
index 2eb43d501e..ad0b1ddea7 100644
--- a/spec/ruby/core/data/constants_spec.rb
+++ b/spec/ruby/core/data/constants_spec.rb
@@ -1,21 +1,11 @@
require_relative '../../spec_helper'
-ruby_version_is ''...'3.2' do
- describe "Data" do
- it "does not exist anymore" do
- Object.should_not have_constant(:Data)
- end
+describe "Data" do
+ it "is a new constant" do
+ Data.superclass.should == Object
end
-end
-
-ruby_version_is '3.2' do
- describe "Data" do
- it "is a new constant" do
- Data.superclass.should == Object
- end
- it "is not deprecated" do
- -> { Data }.should_not complain
- end
+ it "is not deprecated" do
+ -> { Data }.should_not complain
end
end
diff --git a/spec/ruby/core/data/deconstruct_keys_spec.rb b/spec/ruby/core/data/deconstruct_keys_spec.rb
new file mode 100644
index 0000000000..df378f8b98
--- /dev/null
+++ b/spec/ruby/core/data/deconstruct_keys_spec.rb
@@ -0,0 +1,130 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Data#deconstruct_keys" do
+ it "returns a hash of attributes" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys([:x, :y]).should == {x: 1, y: 2}
+ end
+
+ it "requires one argument" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ -> {
+ d.deconstruct_keys
+ }.should raise_error(ArgumentError, /wrong number of arguments \(given 0, expected 1\)/)
+ end
+
+ it "returns only specified keys" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys([:x, :y]).should == {x: 1, y: 2}
+ d.deconstruct_keys([:x] ).should == {x: 1}
+ d.deconstruct_keys([] ).should == {}
+ end
+
+ it "accepts string attribute names" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys(['x', 'y']).should == {'x' => 1, 'y' => 2}
+ end
+
+ it "accepts argument position number as well but returns them as keys" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys([0, 1]).should == {0 => 1, 1 => 2}
+ d.deconstruct_keys([0] ).should == {0 => 1}
+ d.deconstruct_keys([-1] ).should == {-1 => 2}
+ end
+
+ it "ignores incorrect position numbers" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys([0, 3]).should == {0 => 1}
+ end
+
+ it "support mixing attribute names and argument position numbers" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys([0, :x]).should == {0 => 1, :x => 1}
+ end
+
+ it "returns an empty hash when there are more keys than attributes" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys([:x, :y, :x]).should == {}
+ end
+
+ it "returns at first not existing attribute name" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys([:a, :x]).should == {}
+ d.deconstruct_keys([:x, :a]).should == {x: 1}
+ end
+
+ it "returns at first not existing argument position number" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys([3, 0]).should == {}
+ d.deconstruct_keys([0, 3]).should == {0 => 1}
+ end
+
+ it "accepts nil argument and return all the attributes" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ d.deconstruct_keys(nil).should == {x: 1, y: 2}
+ end
+
+ it "tries to convert a key with #to_int if index is not a String nor a Symbol, but responds to #to_int" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ key = mock("to_int")
+ key.should_receive(:to_int).and_return(1)
+
+ d.deconstruct_keys([key]).should == { key => 2 }
+ end
+
+ it "raises a TypeError if the conversion with #to_int does not return an Integer" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ key = mock("to_int")
+ key.should_receive(:to_int).and_return("not an Integer")
+
+ -> {
+ d.deconstruct_keys([key])
+ }.should raise_error(TypeError, /can't convert MockObject to Integer/)
+ end
+
+ it "raises TypeError if index is not a String, a Symbol and not convertible to Integer " do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ -> {
+ d.deconstruct_keys([0, []])
+ }.should raise_error(TypeError, "no implicit conversion of Array into Integer")
+ end
+
+ it "raise TypeError if passed anything except nil or array" do
+ klass = Data.define(:x, :y)
+ d = klass.new(1, 2)
+
+ -> { d.deconstruct_keys('x') }.should raise_error(TypeError, /expected Array or nil/)
+ -> { d.deconstruct_keys(1) }.should raise_error(TypeError, /expected Array or nil/)
+ -> { d.deconstruct_keys(:x) }.should raise_error(TypeError, /expected Array or nil/)
+ -> { d.deconstruct_keys({}) }.should raise_error(TypeError, /expected Array or nil/)
+ end
+end
diff --git a/spec/ruby/core/data/deconstruct_spec.rb b/spec/ruby/core/data/deconstruct_spec.rb
new file mode 100644
index 0000000000..4ca0b87039
--- /dev/null
+++ b/spec/ruby/core/data/deconstruct_spec.rb
@@ -0,0 +1,8 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Data#deconstruct" do
+ it "returns an array of attribute values" do
+ DataSpecs::Measure.new(42, "km").deconstruct.should == [42, "km"]
+ end
+end
diff --git a/spec/ruby/core/data/define_spec.rb b/spec/ruby/core/data/define_spec.rb
index 2aa2c50d4c..c0b4671e39 100644
--- a/spec/ruby/core/data/define_spec.rb
+++ b/spec/ruby/core/data/define_spec.rb
@@ -1,36 +1,34 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is "3.2" do
- describe "Data.define" do
- it "accepts no arguments" do
- empty_data = Data.define
- empty_data.members.should == []
- end
+describe "Data.define" do
+ it "accepts no arguments" do
+ empty_data = Data.define
+ empty_data.members.should == []
+ end
- it "accepts symbols" do
- movie = Data.define(:title, :year)
- movie.members.should == [:title, :year]
- end
+ it "accepts symbols" do
+ movie = Data.define(:title, :year)
+ movie.members.should == [:title, :year]
+ end
- it "accepts strings" do
- movie = Data.define("title", "year")
- movie.members.should == [:title, :year]
- end
+ it "accepts strings" do
+ movie = Data.define("title", "year")
+ movie.members.should == [:title, :year]
+ end
- it "accepts a mix of strings and symbols" do
- movie = Data.define("title", :year, "genre")
- movie.members.should == [:title, :year, :genre]
- end
+ it "accepts a mix of strings and symbols" do
+ movie = Data.define("title", :year, "genre")
+ movie.members.should == [:title, :year, :genre]
+ end
- it "accepts a block" do
- movie = Data.define(:title, :year) do
- def title_with_year
- "#{title} (#{year})"
- end
+ it "accepts a block" do
+ movie = Data.define(:title, :year) do
+ def title_with_year
+ "#{title} (#{year})"
end
- movie.members.should == [:title, :year]
- movie.new("Matrix", 1999).title_with_year.should == "Matrix (1999)"
end
+ movie.members.should == [:title, :year]
+ movie.new("Matrix", 1999).title_with_year.should == "Matrix (1999)"
end
end
diff --git a/spec/ruby/core/data/eql_spec.rb b/spec/ruby/core/data/eql_spec.rb
new file mode 100644
index 0000000000..6958d5de4a
--- /dev/null
+++ b/spec/ruby/core/data/eql_spec.rb
@@ -0,0 +1,63 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Data#eql?" do
+ it "returns true if the other is the same object" do
+ a = DataSpecs::Measure.new(42, "km")
+ a.should.eql?(a)
+ end
+
+ it "returns true if the other has all the same fields" do
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(42, "km")
+ a.should.eql?(b)
+ end
+
+ it "returns false if the other is a different object or has different fields" do
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(42, "mi")
+ a.should_not.eql?(b)
+ end
+
+ it "returns false if other is of a different class" do
+ a = DataSpecs::Measure.new(42, "km")
+ klass = Data.define(*DataSpecs::Measure.members)
+ b = klass.new(42, "km")
+ a.should_not.eql?(b)
+ end
+
+ it "returns false if any corresponding elements are not equal with #eql?" do
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(42.0, "mi")
+ a.should_not.eql?(b)
+ end
+
+ context "recursive structure" do
+ it "returns true the other is the same object" do
+ a = DataSpecs::Measure.allocate
+ a.send(:initialize, amount: 42, unit: a)
+
+ a.should.eql?(a)
+ end
+
+ it "returns true if the other has all the same fields" do
+ a = DataSpecs::Measure.allocate
+ a.send(:initialize, amount: 42, unit: a)
+
+ b = DataSpecs::Measure.allocate
+ b.send(:initialize, amount: 42, unit: b)
+
+ a.should.eql?(b)
+ end
+
+ it "returns false if any corresponding elements are not equal with #eql?" do
+ a = DataSpecs::Measure.allocate
+ a.send(:initialize, amount: a, unit: "km")
+
+ b = DataSpecs::Measure.allocate
+ b.send(:initialize, amount: b, unit: "mi")
+
+ a.should_not.eql?(b)
+ end
+ end
+end
diff --git a/spec/ruby/core/data/equal_value_spec.rb b/spec/ruby/core/data/equal_value_spec.rb
new file mode 100644
index 0000000000..d9a0dcff3e
--- /dev/null
+++ b/spec/ruby/core/data/equal_value_spec.rb
@@ -0,0 +1,63 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Data#==" do
+ it "returns true if the other is the same object" do
+ a = DataSpecs::Measure.new(42, "km")
+ a.should == a
+ end
+
+ it "returns true if the other has all the same fields" do
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(42, "km")
+ a.should == b
+ end
+
+ it "returns false if the other is a different object or has different fields" do
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(42, "mi")
+ a.should_not == b
+ end
+
+ it "returns false if other is of a different class" do
+ a = DataSpecs::Measure.new(42, "km")
+ klass = Data.define(*DataSpecs::Measure.members)
+ b = klass.new(42, "km")
+ a.should_not == b
+ end
+
+ it "returns false if any corresponding elements are not equal with #==" do
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(42.0, "mi")
+ a.should_not == b
+ end
+
+ context "recursive structure" do
+ it "returns true the other is the same object" do
+ a = DataSpecs::Measure.allocate
+ a.send(:initialize, amount: 42, unit: a)
+
+ a.should == a
+ end
+
+ it "returns true if the other has all the same fields" do
+ a = DataSpecs::Measure.allocate
+ a.send(:initialize, amount: 42, unit: a)
+
+ b = DataSpecs::Measure.allocate
+ b.send(:initialize, amount: 42, unit: b)
+
+ a.should == b
+ end
+
+ it "returns false if any corresponding elements are not equal with #==" do
+ a = DataSpecs::Measure.allocate
+ a.send(:initialize, amount: a, unit: "km")
+
+ b = DataSpecs::Measure.allocate
+ b.send(:initialize, amount: b, unit: "mi")
+
+ a.should_not == b
+ end
+ end
+end
diff --git a/spec/ruby/core/data/fixtures/classes.rb b/spec/ruby/core/data/fixtures/classes.rb
index 46a6b48bb2..650c0b2a62 100644
--- a/spec/ruby/core/data/fixtures/classes.rb
+++ b/spec/ruby/core/data/fixtures/classes.rb
@@ -1,5 +1,34 @@
module DataSpecs
- guard -> { ruby_version_is "3.2" and Data.respond_to?(:define) } do
+ if Data.respond_to?(:define)
Measure = Data.define(:amount, :unit)
+
+ class MeasureWithOverriddenName < Measure
+ def self.name
+ "A"
+ end
+ end
+
+ class DataSubclass < Data; end
+
+ MeasureSubclass = Class.new(Measure) do
+ def initialize(amount:, unit:)
+ super
+ end
+ end
+
+ Empty = Data.define()
+
+ DataWithOverriddenInitialize = Data.define(:amount, :unit) do
+ def initialize(*rest, **kw)
+ super
+ ScratchPad.record [:initialize, rest, kw]
+ end
+ end
+
+ Area = Data.define(:width, :height, :area) do
+ def initialize(width:, height:)
+ super(width: width, height: height, area: width * height)
+ end
+ end
end
end
diff --git a/spec/ruby/core/data/hash_spec.rb b/spec/ruby/core/data/hash_spec.rb
new file mode 100644
index 0000000000..c23f08a71d
--- /dev/null
+++ b/spec/ruby/core/data/hash_spec.rb
@@ -0,0 +1,25 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Data#hash" do
+ it "returns the same integer for objects with the same content" do
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(42, "km")
+ a.hash.should == b.hash
+ a.hash.should be_an_instance_of(Integer)
+ end
+
+ it "returns different hashes for objects with different values" do
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(42, "ml")
+ a.hash.should_not == b.hash
+
+ a = DataSpecs::Measure.new(42, "km")
+ b = DataSpecs::Measure.new(13, "km")
+ a.hash.should_not == b.hash
+ end
+
+ it "returns different hashes for different classes" do
+ Data.define(:x).new(1).hash.should != Data.define(:x).new(1).hash
+ end
+end
diff --git a/spec/ruby/core/data/initialize_spec.rb b/spec/ruby/core/data/initialize_spec.rb
index 2c36bd3ac4..010c73b91b 100644
--- a/spec/ruby/core/data/initialize_spec.rb
+++ b/spec/ruby/core/data/initialize_spec.rb
@@ -1,65 +1,124 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is "3.2" do
- describe "Data#initialize" do
- it "accepts positional arguments" do
- data = DataSpecs::Measure.new(42, "km")
+describe "Data#initialize" do
+ it "accepts positional arguments" do
+ data = DataSpecs::Measure.new(42, "km")
- data.amount.should == 42
- data.unit.should == "km"
- end
+ data.amount.should == 42
+ data.unit.should == "km"
+ end
- it "accepts alternative positional arguments" do
- data = DataSpecs::Measure[42, "km"]
+ it "accepts alternative positional arguments" do
+ data = DataSpecs::Measure[42, "km"]
- data.amount.should == 42
- data.unit.should == "km"
- end
+ data.amount.should == 42
+ data.unit.should == "km"
+ end
- it "accepts keyword arguments" do
- data = DataSpecs::Measure.new(amount: 42, unit: "km")
+ it "accepts keyword arguments" do
+ data = DataSpecs::Measure.new(amount: 42, unit: "km")
- data.amount.should == 42
- data.unit.should == "km"
- end
+ data.amount.should == 42
+ data.unit.should == "km"
+ end
+
+ it "accepts alternative keyword arguments" do
+ data = DataSpecs::Measure[amount: 42, unit: "km"]
- it "accepts alternative keyword arguments" do
- data = DataSpecs::Measure[amount: 42, unit: "km"]
+ data.amount.should == 42
+ data.unit.should == "km"
+ end
+
+ it "accepts String keyword arguments" do
+ data = DataSpecs::Measure.new("amount" => 42, "unit" => "km")
+
+ data.amount.should == 42
+ data.unit.should == "km"
+ end
- data.amount.should == 42
- data.unit.should == "km"
+ it "raises ArgumentError if no arguments are given" do
+ -> {
+ DataSpecs::Measure.new
+ }.should raise_error(ArgumentError) { |e|
+ e.message.should.include?("missing keywords: :amount, :unit")
+ }
+ end
+
+ it "raises ArgumentError if at least one argument is missing" do
+ -> {
+ DataSpecs::Measure.new(unit: "km")
+ }.should raise_error(ArgumentError) { |e|
+ e.message.should.include?("missing keyword: :amount")
+ }
+ end
+
+ it "raises ArgumentError if unknown keyword is given" do
+ -> {
+ DataSpecs::Measure.new(amount: 42, unit: "km", system: "metric")
+ }.should raise_error(ArgumentError) { |e|
+ e.message.should.include?("unknown keyword: :system")
+ }
+ end
+
+ it "supports super from a subclass" do
+ ms = DataSpecs::MeasureSubclass.new(amount: 1, unit: "km")
+
+ ms.amount.should == 1
+ ms.unit.should == "km"
+ end
+
+ it "supports Data with no fields" do
+ -> { DataSpecs::Empty.new }.should_not raise_error
+ end
+
+ it "can be overridden" do
+ ScratchPad.record []
+
+ measure_class = Data.define(:amount, :unit) do
+ def initialize(*, **)
+ super
+ ScratchPad << :initialize
+ end
end
- it "accepts String keyword arguments" do
- data = DataSpecs::Measure.new("amount" => 42, "unit" => "km")
+ measure_class.new(42, "m")
+ ScratchPad.recorded.should == [:initialize]
+ end
+
+ context "when it is overridden" do
+ it "is called with keyword arguments when given positional arguments" do
+ ScratchPad.clear
+ DataSpecs::DataWithOverriddenInitialize.new(42, "m")
+ ScratchPad.recorded.should == [:initialize, [], {amount: 42, unit: "m"}]
+ end
- data.amount.should == 42
- data.unit.should == "km"
+ it "is called with keyword arguments when given keyword arguments" do
+ ScratchPad.clear
+ DataSpecs::DataWithOverriddenInitialize.new(amount: 42, unit: "m")
+ ScratchPad.recorded.should == [:initialize, [], {amount: 42, unit: "m"}]
end
- it "raises ArgumentError if no arguments are given" do
- -> {
- DataSpecs::Measure.new
- }.should raise_error(ArgumentError) { |e|
- e.message.should.include?("missing keywords: :amount, :unit")
- }
+ it "is called with keyword arguments when given alternative positional arguments" do
+ ScratchPad.clear
+ DataSpecs::DataWithOverriddenInitialize[42, "m"]
+ ScratchPad.recorded.should == [:initialize, [], {amount: 42, unit: "m"}]
end
- it "raises ArgumentError if at least one argument is missing" do
- -> {
- DataSpecs::Measure.new(unit: "km")
- }.should raise_error(ArgumentError) { |e|
- e.message.should.include?("missing keyword: :amount")
- }
+ it "is called with keyword arguments when given alternative keyword arguments" do
+ ScratchPad.clear
+ DataSpecs::DataWithOverriddenInitialize[amount: 42, unit: "m"]
+ ScratchPad.recorded.should == [:initialize, [], {amount: 42, unit: "m"}]
end
- it "raises ArgumentError if unknown keyword is given" do
- -> {
- DataSpecs::Measure.new(amount: 42, unit: "km", system: "metric")
- }.should raise_error(ArgumentError) { |e|
- e.message.should.include?("unknown keyword: :system")
- }
+ # See https://github.com/ruby/psych/pull/765
+ it "can be deserialized by calling Data.instance_method(:initialize)" do
+ d1 = DataSpecs::Area.new(width: 2, height: 3)
+ d1.area.should == 6
+
+ d2 = DataSpecs::Area.allocate
+ Data.instance_method(:initialize).bind_call(d2, **d1.to_h)
+ d2.should == d1
end
end
end
diff --git a/spec/ruby/core/data/inspect_spec.rb b/spec/ruby/core/data/inspect_spec.rb
new file mode 100644
index 0000000000..38642910a0
--- /dev/null
+++ b/spec/ruby/core/data/inspect_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/inspect'
+
+describe "Data#inspect" do
+ it_behaves_like :data_inspect, :inspect
+end
diff --git a/spec/ruby/core/data/members_spec.rb b/spec/ruby/core/data/members_spec.rb
new file mode 100644
index 0000000000..457a90a0d6
--- /dev/null
+++ b/spec/ruby/core/data/members_spec.rb
@@ -0,0 +1,21 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Data#members" do
+ it "returns an array of attribute names" do
+ measure = DataSpecs::Measure.new(amount: 42, unit: 'km')
+ measure.members.should == [:amount, :unit]
+ end
+end
+
+describe "DataClass#members" do
+ it "returns an array of attribute names" do
+ DataSpecs::Measure.members.should == [:amount, :unit]
+ end
+
+ context "class inheriting Data" do
+ it "isn't available in a subclass" do
+ DataSpecs::DataSubclass.should_not.respond_to?(:members)
+ end
+ end
+end
diff --git a/spec/ruby/core/data/shared/inspect.rb b/spec/ruby/core/data/shared/inspect.rb
new file mode 100644
index 0000000000..6cd5664da7
--- /dev/null
+++ b/spec/ruby/core/data/shared/inspect.rb
@@ -0,0 +1,62 @@
+require_relative '../fixtures/classes'
+
+describe :data_inspect, shared: true do
+ it "returns a string representation showing members and values" do
+ a = DataSpecs::Measure.new(42, "km")
+ a.send(@method).should == '#<data DataSpecs::Measure amount=42, unit="km">'
+ end
+
+ it "returns a string representation without the class name for anonymous structs" do
+ Data.define(:a).new("").send(@method).should == '#<data a="">'
+ end
+
+ it "returns a string representation without the class name for structs nested in anonymous classes" do
+ c = Class.new
+ c.class_eval <<~DOC
+ Foo = Data.define(:a)
+ DOC
+
+ c::Foo.new("").send(@method).should == '#<data a="">'
+ end
+
+ it "returns a string representation without the class name for structs nested in anonymous modules" do
+ m = Module.new
+ m.class_eval <<~DOC
+ Foo = Data.define(:a)
+ DOC
+
+ m::Foo.new("").send(@method).should == '#<data a="">'
+ end
+
+ it "does not call #name method" do
+ struct = DataSpecs::MeasureWithOverriddenName.new(42, "km")
+ struct.send(@method).should == '#<data DataSpecs::MeasureWithOverriddenName amount=42, unit="km">'
+ end
+
+ it "does not call #name method when struct is anonymous" do
+ klass = Class.new(DataSpecs::Measure) do
+ def self.name
+ "A"
+ end
+ end
+ struct = klass.new(42, "km")
+ struct.send(@method).should == '#<data amount=42, unit="km">'
+ end
+
+ context "recursive structure" do
+ it "returns string representation with recursive attribute replaced with ..." do
+ a = DataSpecs::Measure.allocate
+ a.send(:initialize, amount: 42, unit: a)
+
+ a.send(@method).should == "#<data DataSpecs::Measure amount=42, unit=#<data DataSpecs::Measure:...>>"
+ end
+
+ it "returns string representation with recursive attribute replaced with ... when an anonymous class" do
+ klass = Class.new(DataSpecs::Measure)
+ a = klass.allocate
+ a.send(:initialize, amount: 42, unit: a)
+
+ a.send(@method).should =~ /#<data amount=42, unit=#<data #<Class:0x.+?>:\.\.\.>>/
+ end
+ end
+end
diff --git a/spec/ruby/core/data/to_h_spec.rb b/spec/ruby/core/data/to_h_spec.rb
new file mode 100644
index 0000000000..64816b7251
--- /dev/null
+++ b/spec/ruby/core/data/to_h_spec.rb
@@ -0,0 +1,63 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Data#to_h" do
+ it "transforms the data object into a hash" do
+ data = DataSpecs::Measure.new(amount: 42, unit: 'km')
+ data.to_h.should == { amount: 42, unit: 'km' }
+ end
+
+ context "with block" do
+ it "transforms [key, value] pairs returned by the block into a hash" do
+ data = DataSpecs::Measure.new(amount: 42, unit: 'km')
+ data.to_h { |key, value| [value, key] }.should == { 42 => :amount, 'km' => :unit }
+ end
+
+ it "passes to a block each pair's key and value as separate arguments" do
+ ScratchPad.record []
+ data = DataSpecs::Measure.new(amount: 42, unit: 'km')
+ data.to_h { |k, v| ScratchPad << [k, v]; [k, v] }
+ ScratchPad.recorded.sort.should == [[:amount, 42], [:unit, 'km']]
+
+ ScratchPad.record []
+ data.to_h { |*args| ScratchPad << args; [args[0], args[1]] }
+ ScratchPad.recorded.sort.should == [[:amount, 42], [:unit, 'km']]
+ end
+
+ it "raises ArgumentError if block returns longer or shorter array" do
+ data = DataSpecs::Measure.new(amount: 42, unit: 'km')
+ -> do
+ data.to_h { |k, v| [k.to_s, v*v, 1] }
+ end.should raise_error(ArgumentError, /element has wrong array length/)
+
+ -> do
+ data.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
+ data = DataSpecs::Measure.new(amount: 42, unit: 'km')
+ -> do
+ data.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'])
+ data = DataSpecs::Measure.new(amount: 42, unit: 'km')
+
+ data.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'])
+ data = DataSpecs::Measure.new(amount: 42, unit: 'km')
+
+ -> do
+ data.to_h { |k| x }
+ end.should raise_error(TypeError, /wrong element type MockObject/)
+ end
+ end
+end
diff --git a/spec/ruby/core/data/to_s_spec.rb b/spec/ruby/core/data/to_s_spec.rb
new file mode 100644
index 0000000000..2b4a670e8e
--- /dev/null
+++ b/spec/ruby/core/data/to_s_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/inspect'
+
+describe "Data#to_s" do
+ it_behaves_like :data_inspect, :to_s
+end
diff --git a/spec/ruby/core/data/with_spec.rb b/spec/ruby/core/data/with_spec.rb
index 97e34c951f..fd0a99d1fa 100644
--- a/spec/ruby/core/data/with_spec.rb
+++ b/spec/ruby/core/data/with_spec.rb
@@ -1,35 +1,57 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is "3.2" do
- describe "Data#with" do
- it "returns self if given no arguments" do
- data = DataSpecs::Measure.new(amount: 42, unit: "km")
- data = data.with.should.equal?(data)
- end
+describe "Data#with" do
+ it "returns self if given no arguments" do
+ data = DataSpecs::Measure.new(amount: 42, unit: "km")
+ data = data.with.should.equal?(data)
+ end
- it "accepts keyword arguments" do
- data = DataSpecs::Measure.new(amount: 42, unit: "km")
- data = data.with(amount: 4, unit: "m")
+ it "accepts keyword arguments" do
+ data = DataSpecs::Measure.new(amount: 42, unit: "km")
+ data = data.with(amount: 4, unit: "m")
- data.amount.should == 4
- data.unit.should == "m"
- end
+ data.amount.should == 4
+ data.unit.should == "m"
+ end
+
+ it "accepts String keyword arguments" do
+ data = DataSpecs::Measure.new(amount: 42, unit: "km")
+ data = data.with("amount" => 4, "unit" => "m")
+
+ data.amount.should == 4
+ data.unit.should == "m"
+ end
- it "accepts String keyword arguments" do
- data = DataSpecs::Measure.new(amount: 42, unit: "km")
- data = data.with("amount" => 4, "unit" => "m")
+ it "raises ArgumentError if no keyword arguments are given" do
+ data = DataSpecs::Measure.new(amount: 42, unit: "km")
- data.amount.should == 4
- data.unit.should == "m"
+ -> {
+ data.with(4, "m")
+ }.should raise_error(ArgumentError, "wrong number of arguments (given 2, expected 0)")
+ end
+
+ it "does not depend on the Data.new method" do
+ subclass = Class.new(DataSpecs::Measure)
+ data = subclass.new(amount: 42, unit: "km")
+
+ def subclass.new(*)
+ raise "Data.new is called"
end
- it "raises ArgumentError if no keyword arguments are given" do
- data = DataSpecs::Measure.new(amount: 42, unit: "km")
+ data_copy = data.with(unit: "m")
+ data_copy.amount.should == 42
+ data_copy.unit.should == "m"
+ end
+
+ ruby_version_is "3.3" do
+ it "calls #initialize" do
+ data = DataSpecs::DataWithOverriddenInitialize.new(42, "m")
+ ScratchPad.clear
+
+ data.with(amount: 0)
- -> {
- data.with(4, "m")
- }.should raise_error(ArgumentError, "wrong number of arguments (given 2, expected 0)")
+ ScratchPad.recorded.should == [:initialize, [], {amount: 0, unit: "m"}]
end
end
end
diff --git a/spec/ruby/core/dir/chdir_spec.rb b/spec/ruby/core/dir/chdir_spec.rb
index 729ac403e3..015386a902 100644
--- a/spec/ruby/core/dir/chdir_spec.rb
+++ b/spec/ruby/core/dir/chdir_spec.rb
@@ -19,14 +19,14 @@ describe "Dir.chdir" do
end
it "defaults to $HOME with no arguments" do
- if ENV['HOME']
- Dir.chdir
- current_dir = Dir.pwd
+ skip "$HOME not valid directory" unless ENV['HOME'] && File.directory?(ENV['HOME'])
- Dir.chdir(ENV['HOME'])
- home = Dir.pwd
- current_dir.should == home
- end
+ Dir.chdir
+ current_dir = Dir.pwd
+
+ Dir.chdir(ENV['HOME'])
+ home = Dir.pwd
+ current_dir.should == home
end
it "changes to the specified directory" do
@@ -70,6 +70,8 @@ describe "Dir.chdir" do
end
it "defaults to the home directory when given a block but no argument" do
+ skip "$HOME not valid directory" unless ENV['HOME'] && File.directory?(ENV['HOME'])
+
# Windows will return a path with forward slashes for ENV["HOME"] so we have
# to compare the route representations returned by Dir.chdir.
current_dir = ""
@@ -93,10 +95,10 @@ describe "Dir.chdir" do
end
it "raises an Errno::ENOENT if the original directory no longer exists" do
- dir1 = tmp('/testdir1')
- dir2 = tmp('/testdir2')
- File.should_not.exist?(dir1)
- File.should_not.exist?(dir2)
+ dir1 = tmp('testdir1')
+ dir2 = tmp('testdir2')
+ Dir.should_not.exist?(dir1)
+ Dir.should_not.exist?(dir2)
Dir.mkdir dir1
Dir.mkdir dir2
begin
@@ -106,8 +108,8 @@ describe "Dir.chdir" do
end
}.should raise_error(Errno::ENOENT)
ensure
- Dir.unlink dir1 if File.exist?(dir1)
- Dir.unlink dir2 if File.exist?(dir2)
+ Dir.unlink dir1 if Dir.exist?(dir1)
+ Dir.unlink dir2 if Dir.exist?(dir2)
end
end
@@ -122,3 +124,97 @@ describe "Dir.chdir" do
Dir.pwd.should == @original
end
end
+
+ruby_version_is '3.3' do
+ describe "Dir#chdir" do
+ before :all do
+ DirSpecs.create_mock_dirs
+ end
+
+ after :all do
+ DirSpecs.delete_mock_dirs
+ end
+
+ before :each do
+ @original = Dir.pwd
+ end
+
+ after :each do
+ Dir.chdir(@original)
+ end
+
+ it "changes the current working directory to self" do
+ dir = Dir.new(DirSpecs.mock_dir)
+ dir.chdir
+ Dir.pwd.should == DirSpecs.mock_dir
+ ensure
+ dir.close
+ end
+
+ it "changes the current working directory to self for duration of the block when a block is given" do
+ dir = Dir.new(DirSpecs.mock_dir)
+ pwd_in_block = nil
+
+ dir.chdir { pwd_in_block = Dir.pwd }
+
+ pwd_in_block.should == DirSpecs.mock_dir
+ Dir.pwd.should == @original
+ ensure
+ dir.close
+ end
+
+ it "returns 0 when successfully changing directory" do
+ dir = Dir.new(DirSpecs.mock_dir)
+ dir.chdir.should == 0
+ ensure
+ dir.close
+ end
+
+ it "returns the value of the block when a block is given" do
+ dir = Dir.new(DirSpecs.mock_dir)
+ dir.chdir { :block_value }.should == :block_value
+ ensure
+ dir.close
+ end
+
+ platform_is_not :windows do
+ it "does not raise an Errno::ENOENT if the original directory no longer exists" do
+ dir_name1 = tmp('testdir1')
+ dir_name2 = tmp('testdir2')
+ Dir.should_not.exist?(dir_name1)
+ Dir.should_not.exist?(dir_name2)
+ Dir.mkdir dir_name1
+ Dir.mkdir dir_name2
+
+ dir2 = Dir.new(dir_name2)
+
+ begin
+ Dir.chdir(dir_name1) do
+ dir2.chdir { Dir.unlink dir_name1 }
+ end
+ Dir.pwd.should == @original
+ ensure
+ Dir.unlink dir_name1 if Dir.exist?(dir_name1)
+ Dir.unlink dir_name2 if Dir.exist?(dir_name2)
+ end
+ ensure
+ dir2.close
+ end
+ end
+
+ it "always returns to the original directory when given a block" do
+ dir = Dir.new(DirSpecs.mock_dir)
+
+ begin
+ dir.chdir do
+ raise StandardError, "something bad happened"
+ end
+ rescue StandardError
+ end
+
+ Dir.pwd.should == @original
+ ensure
+ dir.close
+ end
+ end
+end
diff --git a/spec/ruby/core/dir/close_spec.rb b/spec/ruby/core/dir/close_spec.rb
index 5fad5eecfb..f7cce318b8 100644
--- a/spec/ruby/core/dir/close_spec.rb
+++ b/spec/ruby/core/dir/close_spec.rb
@@ -11,9 +11,43 @@ describe "Dir#close" do
it "does not raise an IOError even if the Dir instance is closed" do
dir = Dir.open DirSpecs.mock_dir
- dir.close
- -> {
- dir.close
- }.should_not raise_error(IOError)
+ dir.close.should == nil
+ dir.close.should == nil
+
+ platform_is_not :windows do
+ -> { dir.fileno }.should raise_error(IOError, /closed directory/)
+ end
+ end
+
+ it "returns nil" do
+ dir = Dir.open DirSpecs.mock_dir
+ dir.close.should == nil
+ end
+
+ ruby_version_is '3.3'...'3.4' do
+ platform_is_not :windows do
+ it "does not raise an error even if the file descriptor is closed with another Dir instance" do
+ dir = Dir.open DirSpecs.mock_dir
+ dir_new = Dir.for_fd(dir.fileno)
+
+ dir.close
+ dir_new.close
+
+ -> { dir.fileno }.should raise_error(IOError, /closed directory/)
+ -> { dir_new.fileno }.should raise_error(IOError, /closed directory/)
+ end
+ end
+ end
+
+ ruby_version_is '3.4' do
+ platform_is_not :windows do
+ it "raises an error if the file descriptor is closed with another Dir instance" do
+ dir = Dir.open DirSpecs.mock_dir
+ dir_new = Dir.for_fd(dir.fileno)
+ dir.close
+
+ -> { dir_new.close }.should raise_error(Errno::EBADF, 'Bad file descriptor - closedir')
+ end
+ end
end
end
diff --git a/spec/ruby/core/dir/exist_spec.rb b/spec/ruby/core/dir/exist_spec.rb
index 9023de533f..0b8e521894 100644
--- a/spec/ruby/core/dir/exist_spec.rb
+++ b/spec/ruby/core/dir/exist_spec.rb
@@ -14,10 +14,8 @@ describe "Dir.exist?" do
it_behaves_like :dir_exist, :exist?
end
-ruby_version_is "3.2" do
- describe "Dir.exists?" do
- it "has been removed" do
- Dir.should_not.respond_to?(:exists?)
- end
+describe "Dir.exists?" do
+ it "has been removed" do
+ Dir.should_not.respond_to?(:exists?)
end
end
diff --git a/spec/ruby/core/dir/fchdir_spec.rb b/spec/ruby/core/dir/fchdir_spec.rb
index 429e569691..52600a95f2 100644
--- a/spec/ruby/core/dir/fchdir_spec.rb
+++ b/spec/ruby/core/dir/fchdir_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
require_relative 'fixtures/common'
ruby_version_is '3.3' do
- guard -> { Dir.respond_to? :fchdir } do
+ platform_is_not :windows do
describe "Dir.fchdir" do
before :all do
DirSpecs.create_mock_dirs
@@ -13,51 +13,56 @@ ruby_version_is '3.3' do
end
before :each do
- @dirs = [Dir.new('.')]
- @original = @dirs.first.fileno
+ @original = Dir.pwd
end
after :each do
- Dir.fchdir(@original)
- @dirs.each(&:close)
+ Dir.chdir(@original)
end
- it "changes to the specified directory" do
+ it "changes the current working directory to the directory specified by the integer file descriptor" do
dir = Dir.new(DirSpecs.mock_dir)
- @dirs << dir
Dir.fchdir dir.fileno
Dir.pwd.should == DirSpecs.mock_dir
+ ensure
+ dir.close
end
it "returns 0 when successfully changing directory" do
- Dir.fchdir(@original).should == 0
+ dir = Dir.new(DirSpecs.mock_dir)
+ Dir.fchdir(dir.fileno).should == 0
+ ensure
+ dir.close
end
it "returns the value of the block when a block is given" do
- Dir.fchdir(@original) { :block_value }.should == :block_value
+ dir = Dir.new(DirSpecs.mock_dir)
+ Dir.fchdir(dir.fileno) { :block_value }.should == :block_value
+ ensure
+ dir.close
end
it "changes to the specified directory for the duration of the block" do
- pwd = Dir.pwd
dir = Dir.new(DirSpecs.mock_dir)
- @dirs << dir
Dir.fchdir(dir.fileno) { Dir.pwd }.should == DirSpecs.mock_dir
- Dir.pwd.should == pwd
+ Dir.pwd.should == @original
+ ensure
+ dir.close
end
it "raises a SystemCallError if the file descriptor given is not valid" do
- -> { Dir.fchdir(-1) }.should raise_error(SystemCallError)
- -> { Dir.fchdir(-1) { } }.should raise_error(SystemCallError)
+ -> { Dir.fchdir(-1) }.should raise_error(SystemCallError, "Bad file descriptor - fchdir")
+ -> { Dir.fchdir(-1) { } }.should raise_error(SystemCallError, "Bad file descriptor - fchdir")
end
it "raises a SystemCallError if the file descriptor given is not for a directory" do
- -> { Dir.fchdir $stdout.fileno }.should raise_error(SystemCallError)
- -> { Dir.fchdir($stdout.fileno) { } }.should raise_error(SystemCallError)
+ -> { Dir.fchdir $stdout.fileno }.should raise_error(SystemCallError, /(Not a directory|Invalid argument) - fchdir/)
+ -> { Dir.fchdir($stdout.fileno) { } }.should raise_error(SystemCallError, /(Not a directory|Invalid argument) - fchdir/)
end
end
end
- guard_not -> { Dir.respond_to? :fchdir } do
+ platform_is :windows do
describe "Dir.fchdir" do
it "raises NotImplementedError" do
-> { Dir.fchdir 1 }.should raise_error(NotImplementedError)
diff --git a/spec/ruby/core/dir/fixtures/common.rb b/spec/ruby/core/dir/fixtures/common.rb
index 087f46b331..848656c9b9 100644
--- a/spec/ruby/core/dir/fixtures/common.rb
+++ b/spec/ruby/core/dir/fixtures/common.rb
@@ -192,13 +192,7 @@ module DirSpecs
]
end
- if RUBY_VERSION > '3.1'
- def self.expected_glob_paths
- expected_paths - ['..']
- end
- else
- def self.expected_glob_paths
- expected_paths
- end
+ def self.expected_glob_paths
+ expected_paths - ['..']
end
end
diff --git a/spec/ruby/core/dir/for_fd_spec.rb b/spec/ruby/core/dir/for_fd_spec.rb
new file mode 100644
index 0000000000..ba467f2f86
--- /dev/null
+++ b/spec/ruby/core/dir/for_fd_spec.rb
@@ -0,0 +1,79 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/common'
+
+quarantine! do # leads to "Errno::EBADF: Bad file descriptor - closedir" in DirSpecs.delete_mock_dirs
+ruby_version_is '3.3' do
+ platform_is_not :windows do
+ describe "Dir.for_fd" do
+ before :all do
+ DirSpecs.create_mock_dirs
+ end
+
+ after :all do
+ DirSpecs.delete_mock_dirs
+ end
+
+ before :each do
+ @original = Dir.pwd
+ end
+
+ after :each do
+ Dir.chdir(@original)
+ end
+
+ it "returns a new Dir object representing the directory specified by the given integer directory file descriptor" do
+ dir = Dir.new(DirSpecs.mock_dir)
+ dir_new = Dir.for_fd(dir.fileno)
+
+ dir_new.should.instance_of?(Dir)
+ dir_new.children.should == dir.children
+ dir_new.fileno.should == dir.fileno
+ ensure
+ dir.close
+ end
+
+ it "returns a new Dir object without associated path" do
+ dir = Dir.new(DirSpecs.mock_dir)
+ dir_new = Dir.for_fd(dir.fileno)
+
+ dir_new.path.should == nil
+ ensure
+ dir.close
+ end
+
+ it "calls #to_int to convert a value to an Integer" do
+ dir = Dir.new(DirSpecs.mock_dir)
+ obj = mock("fd")
+ obj.should_receive(:to_int).and_return(dir.fileno)
+
+ dir_new = Dir.for_fd(obj)
+ dir_new.fileno.should == dir.fileno
+ ensure
+ dir.close
+ end
+
+ it "raises TypeError when value cannot be converted to Integer" do
+ -> {
+ Dir.for_fd(nil)
+ }.should raise_error(TypeError, "no implicit conversion from nil to integer")
+ end
+
+ it "raises a SystemCallError if the file descriptor given is not valid" do
+ -> { Dir.for_fd(-1) }.should raise_error(SystemCallError, "Bad file descriptor - fdopendir")
+ end
+
+ it "raises a SystemCallError if the file descriptor given is not for a directory" do
+ -> { Dir.for_fd $stdout.fileno }.should raise_error(SystemCallError, "Not a directory - fdopendir")
+ end
+ end
+ end
+
+ platform_is :windows do
+ describe "Dir.for_fd" do
+ it "raises NotImplementedError" do
+ -> { Dir.for_fd 1 }.should raise_error(NotImplementedError)
+ end
+ end
+ end
+end
+end
diff --git a/spec/ruby/core/dir/glob_spec.rb b/spec/ruby/core/dir/glob_spec.rb
index 32f515c81d..a60b233bc0 100644
--- a/spec/ruby/core/dir/glob_spec.rb
+++ b/spec/ruby/core/dir/glob_spec.rb
@@ -89,31 +89,15 @@ describe "Dir.glob" do
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
- ]
+ 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
+ Dir.glob('nested/**/*', File::FNM_DOTMATCH).sort.should == expected.sort
end
# This is a separate case to check **/ coming after a constant
@@ -260,34 +244,31 @@ describe "Dir.glob" do
Dir.glob('**/.*', base: "deeply/nested").sort.should == expected
end
- # < 3.1 include a "." entry for every dir: ["directory/.", "directory/structure/.", ...]
- ruby_version_is '3.1' do
- it "handles **/.* with base keyword argument and FNM_DOTMATCH" do
- expected = %w[
- .
- .dotfile.ext
- directory/structure/.ext
- ].sort
+ it "handles **/.* with base keyword argument and FNM_DOTMATCH" do
+ expected = %w[
+ .
+ .dotfile.ext
+ directory/structure/.ext
+ ].sort
- Dir.glob('**/.*', File::FNM_DOTMATCH, base: "deeply/nested").sort.should == expected
- end
+ Dir.glob('**/.*', File::FNM_DOTMATCH, base: "deeply/nested").sort.should == expected
+ end
- it "handles **/** with base keyword argument and FNM_DOTMATCH" do
- expected = %w[
- .
- .dotfile.ext
- directory
- directory/structure
- directory/structure/.ext
- directory/structure/bar
- directory/structure/baz
- directory/structure/file_one
- directory/structure/file_one.ext
- directory/structure/foo
- ].sort
-
- Dir.glob('**/**', File::FNM_DOTMATCH, base: "deeply/nested").sort.should == expected
- end
+ it "handles **/** with base keyword argument and FNM_DOTMATCH" do
+ expected = %w[
+ .
+ .dotfile.ext
+ directory
+ directory/structure
+ directory/structure/.ext
+ directory/structure/bar
+ directory/structure/baz
+ directory/structure/file_one
+ directory/structure/file_one.ext
+ directory/structure/foo
+ ].sort
+
+ Dir.glob('**/**', File::FNM_DOTMATCH, base: "deeply/nested").sort.should == expected
end
it "handles **/*pattern* with base keyword argument and FNM_DOTMATCH" do
diff --git a/spec/ruby/core/dir/home_spec.rb b/spec/ruby/core/dir/home_spec.rb
index 3cf745ab46..966ac38af3 100644
--- a/spec/ruby/core/dir/home_spec.rb
+++ b/spec/ruby/core/dir/home_spec.rb
@@ -33,40 +33,32 @@ describe "Dir.home" do
end
platform_is :windows do
- ruby_version_is "3.2" do
- it "returns the home directory with forward slashs and as UTF-8" do
- ENV['HOME'] = "C:\\rubyspäc\\home"
- home = Dir.home
- home.should == "C:/rubyspäc/home"
- home.encoding.should == Encoding::UTF_8
- end
+ it "returns the home directory with forward slashs and as UTF-8" do
+ ENV['HOME'] = "C:\\rubyspäc\\home"
+ home = Dir.home
+ home.should == "C:/rubyspäc/home"
+ home.encoding.should == Encoding::UTF_8
+ end
- it "retrieves the directory from HOME, USERPROFILE, HOMEDRIVE/HOMEPATH and the WinAPI in that order" do
- old_dirs = [ENV.delete('HOME'), ENV.delete('USERPROFILE'), ENV.delete('HOMEDRIVE'), ENV.delete('HOMEPATH')]
+ it "retrieves the directory from HOME, USERPROFILE, HOMEDRIVE/HOMEPATH and the WinAPI in that order" do
+ old_dirs = [ENV.delete('HOME'), ENV.delete('USERPROFILE'), ENV.delete('HOMEDRIVE'), ENV.delete('HOMEPATH')]
- Dir.home.should == old_dirs[1].gsub("\\", "/")
- ENV['HOMEDRIVE'] = "C:"
- ENV['HOMEPATH'] = "\\rubyspec\\home1"
- Dir.home.should == "C:/rubyspec/home1"
- ENV['USERPROFILE'] = "C:\\rubyspec\\home2"
- Dir.home.should == "C:/rubyspec/home2"
- ENV['HOME'] = "C:\\rubyspec\\home3"
- Dir.home.should == "C:/rubyspec/home3"
- ensure
- ENV['HOME'], ENV['USERPROFILE'], ENV['HOMEDRIVE'], ENV['HOMEPATH'] = *old_dirs
- end
+ Dir.home.should == old_dirs[1].gsub("\\", "/")
+ ENV['HOMEDRIVE'] = "C:"
+ ENV['HOMEPATH'] = "\\rubyspec\\home1"
+ Dir.home.should == "C:/rubyspec/home1"
+ ENV['USERPROFILE'] = "C:\\rubyspec\\home2"
+ Dir.home.should == "C:/rubyspec/home2"
+ ENV['HOME'] = "C:\\rubyspec\\home3"
+ Dir.home.should == "C:/rubyspec/home3"
+ ensure
+ ENV['HOME'], ENV['USERPROFILE'], ENV['HOMEDRIVE'], ENV['HOMEPATH'] = *old_dirs
end
end
end
describe "when called with the current user name" do
- platform_is :solaris do
- it "returns the named user's home directory from the user database" do
- Dir.home(ENV['USER']).should == `getent passwd #{ENV['USER']}|cut -d: -f6`.chomp
- end
- end
-
- platform_is_not :windows, :solaris, :android, :wasi do
+ platform_is_not :windows, :android, :wasi do
it "returns the named user's home directory, from the user database" do
Dir.home(ENV['USER']).should == `echo ~#{ENV['USER']}`.chomp
end
diff --git a/spec/ruby/core/dir/shared/delete.rb b/spec/ruby/core/dir/shared/delete.rb
index 49e88360e8..a81b059759 100644
--- a/spec/ruby/core/dir/shared/delete.rb
+++ b/spec/ruby/core/dir/shared/delete.rb
@@ -17,20 +17,10 @@ describe :dir_delete, shared: true do
Dir.send(@method, p)
end
- platform_is_not :solaris do
- it "raises an Errno::ENOTEMPTY when trying to remove a nonempty directory" do
- -> do
- Dir.send @method, DirSpecs.mock_rmdir("nonempty")
- end.should raise_error(Errno::ENOTEMPTY)
- end
- end
-
- platform_is :solaris do
- it "raises an Errno::EEXIST when trying to remove a nonempty directory" do
- -> do
- Dir.send @method, DirSpecs.mock_rmdir("nonempty")
- end.should raise_error(Errno::EEXIST)
- end
+ it "raises an Errno::ENOTEMPTY when trying to remove a nonempty directory" do
+ -> do
+ Dir.send @method, DirSpecs.mock_rmdir("nonempty")
+ end.should raise_error(Errno::ENOTEMPTY)
end
it "raises an Errno::ENOENT when trying to remove a non-existing directory" do
diff --git a/spec/ruby/core/dir/shared/exist.rb b/spec/ruby/core/dir/shared/exist.rb
index 2ea4f88a80..3097f57715 100644
--- a/spec/ruby/core/dir/shared/exist.rb
+++ b/spec/ruby/core/dir/shared/exist.rb
@@ -34,6 +34,7 @@ describe :dir_exist, shared: true do
end
it "doesn't expand paths" do
+ skip "$HOME not valid directory" unless ENV['HOME'] && File.directory?(ENV['HOME'])
Dir.send(@method, File.expand_path('~')).should be_true
Dir.send(@method, '~').should be_false
end
diff --git a/spec/ruby/core/dir/shared/glob.rb b/spec/ruby/core/dir/shared/glob.rb
index 745f02d46b..b1fc924f08 100644
--- a/spec/ruby/core/dir/shared/glob.rb
+++ b/spec/ruby/core/dir/shared/glob.rb
@@ -12,7 +12,7 @@ describe :dir_glob, shared: true do
end
it "raises an Encoding::CompatibilityError if the argument encoding is not compatible with US-ASCII" do
- pattern = "file*".dup.force_encoding Encoding::UTF_16BE
+ pattern = "files*".dup.force_encoding Encoding::UTF_16BE
-> { Dir.send(@method, pattern) }.should raise_error(Encoding::CompatibilityError)
end
@@ -42,25 +42,10 @@ describe :dir_glob, shared: true do
result.sort.should == Dir.send(@method, '*').sort
end
- ruby_version_is ""..."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
+ 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
it "matches non-dotfiles with '*'" do
@@ -151,16 +136,8 @@ describe :dir_glob, shared: true do
Dir.send(@method, 'special/test\{1\}/*').should == ['special/test{1}/file[1]']
end
- 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
+ it "matches dotfiles except .. with '.*'" do
+ Dir.send(@method, '.*').sort.should == %w|. .dotfile .dotsubdir|.sort
end
it "matches non-dotfiles with '*<non-special characters>'" do
@@ -205,16 +182,8 @@ describe :dir_glob, shared: true do
Dir.send(@method, '**').sort.should == expected
end
- 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
+ it "matches dotfiles in the current directory except .. with '.**'" do
+ Dir.send(@method, '.**').sort.should == %w|. .dotsubdir .dotfile|.sort
end
it "recursively matches any nondot subdirectories with '**/'" do
@@ -245,19 +214,9 @@ describe :dir_glob, shared: true do
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
+ it "recursively matches any subdirectories including ./ with '.**/'" do
+ Dir.chdir("#{DirSpecs.mock_dir}/subdir_one") do
+ Dir.send(@method, '.**/').should == ['./']
end
end
diff --git a/spec/ruby/core/encoding/compatible_spec.rb b/spec/ruby/core/encoding/compatible_spec.rb
index f18d8680a9..31376a3b75 100644
--- a/spec/ruby/core/encoding/compatible_spec.rb
+++ b/spec/ruby/core/encoding/compatible_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
@@ -114,11 +114,11 @@ describe "Encoding.compatible? String, String" do
end
it "returns nil when the second's Encoding is invalid and ASCII only" do
- Encoding.compatible?(@str, "\x7f".dup.force_encoding("utf-16be")).should be_nil
+ Encoding.compatible?(@str, "\x7f\x7f".dup.force_encoding("utf-16be")).should be_nil
end
it "returns nil when the second's Encoding is invalid and not ASCII only" do
- Encoding.compatible?(@str, "\xff".dup.force_encoding("utf-16be")).should be_nil
+ Encoding.compatible?(@str, "\xff\xff".dup.force_encoding("utf-16be")).should be_nil
end
it "returns the Encoding when the second's Encoding is invalid but the same as the first" do
@@ -161,6 +161,379 @@ describe "Encoding.compatible? String, String" do
Encoding.compatible?(@str, "").should == Encoding::UTF_7
end
end
+
+ # Encoding negotiation depends on whether encodings are ASCII-compatible, empty
+ # and contain only ASCII characters (that take 7 bits). Check US-ASCII, UTF-8 and
+ # BINARY encodings (as most common) as well as an ASCII-compatible, a non-ASCII-compatible and a dummy
+ # encodings in all possible combinations.
+ describe "compatibility matrix" do
+
+# Use the following script to regenerate the matrix:
+#
+# ```
+# # encoding: binary
+#
+# ENCODINGS = [
+# "US-ASCII",
+# "UTF-8",
+# "ASCII-8BIT",
+# "ISO-8859-1", # ASCII-compatible
+# "UTF-16BE", # non-ASCII-compatible
+# "ISO-2022-JP" # dummy
+# ]
+#
+# TYPES = [:empty, :"7bits", :non7bits]
+#
+# VALUES = {
+# empty: "",
+# :"7bits" => "\x01\x01",
+# non7bits: "\x01\x81"
+# }
+#
+# ENCODINGS.product(TYPES, ENCODINGS, TYPES).each do |encoding1, type1, encoding2, type2|
+# value1 = VALUES[type1].dup.force_encoding(encoding1)
+# value2 = VALUES[type2].dup.force_encoding(encoding2)
+#
+# result_encoding = Encoding.compatible?(value1, value2)
+#
+# puts "[#{encoding1.inspect}, #{value1.inspect}, #{encoding2.inspect}, #{value2.inspect}, #{result_encoding&.name.inspect}],"
+# end
+# ```
+
+ matrix = [
+ ["US-ASCII", "", "US-ASCII", "", "US-ASCII"],
+ ["US-ASCII", "", "US-ASCII", "\x01\x01", "US-ASCII"],
+ ["US-ASCII", "", "US-ASCII", "\x01\x81", "US-ASCII"],
+ ["US-ASCII", "", "UTF-8", "", "US-ASCII"],
+ ["US-ASCII", "", "UTF-8", "\u0001\u0001", "US-ASCII"],
+ ["US-ASCII", "", "UTF-8", "\u0001\x81", "UTF-8"],
+ ["US-ASCII", "", "ASCII-8BIT", "", "US-ASCII"],
+ ["US-ASCII", "", "ASCII-8BIT", "\x01\x01", "US-ASCII"],
+ ["US-ASCII", "", "ASCII-8BIT", "\x01\x81", "ASCII-8BIT"],
+ ["US-ASCII", "", "ISO-8859-1", "", "US-ASCII"],
+ ["US-ASCII", "", "ISO-8859-1", "\x01\x01", "US-ASCII"],
+ ["US-ASCII", "", "ISO-8859-1", "\x01\x81", "ISO-8859-1"],
+ ["US-ASCII", "", "UTF-16BE", "", "US-ASCII"],
+ ["US-ASCII", "", "UTF-16BE", "\u0101", "UTF-16BE"],
+ ["US-ASCII", "", "UTF-16BE", "\u0181", "UTF-16BE"],
+ ["US-ASCII", "", "ISO-2022-JP", "", "US-ASCII"],
+ ["US-ASCII", "", "ISO-2022-JP", "\x01\x01", "ISO-2022-JP"],
+ ["US-ASCII", "", "ISO-2022-JP", "\x01\x81", "ISO-2022-JP"],
+ ["US-ASCII", "\x01\x01", "US-ASCII", "", "US-ASCII"],
+ ["US-ASCII", "\x01\x01", "US-ASCII", "\x01\x01", "US-ASCII"],
+ ["US-ASCII", "\x01\x01", "US-ASCII", "\x01\x81", "US-ASCII"],
+ ["US-ASCII", "\x01\x01", "UTF-8", "", "US-ASCII"],
+ ["US-ASCII", "\x01\x01", "UTF-8", "\u0001\u0001", "US-ASCII"],
+ ["US-ASCII", "\x01\x01", "UTF-8", "\u0001\x81", "UTF-8"],
+ ["US-ASCII", "\x01\x01", "ASCII-8BIT", "", "US-ASCII"],
+ ["US-ASCII", "\x01\x01", "ASCII-8BIT", "\x01\x01", "US-ASCII"],
+ ["US-ASCII", "\x01\x01", "ASCII-8BIT", "\x01\x81", "ASCII-8BIT"],
+ ["US-ASCII", "\x01\x01", "ISO-8859-1", "", "US-ASCII"],
+ ["US-ASCII", "\x01\x01", "ISO-8859-1", "\x01\x01", "US-ASCII"],
+ ["US-ASCII", "\x01\x01", "ISO-8859-1", "\x01\x81", "ISO-8859-1"],
+ ["US-ASCII", "\x01\x01", "UTF-16BE", "", "US-ASCII"],
+ ["US-ASCII", "\x01\x01", "UTF-16BE", "\u0101", nil],
+ ["US-ASCII", "\x01\x01", "UTF-16BE", "\u0181", nil],
+ ["US-ASCII", "\x01\x01", "ISO-2022-JP", "", "US-ASCII"],
+ ["US-ASCII", "\x01\x01", "ISO-2022-JP", "\x01\x01", nil],
+ ["US-ASCII", "\x01\x01", "ISO-2022-JP", "\x01\x81", nil],
+ ["US-ASCII", "\x01\x81", "US-ASCII", "", "US-ASCII"],
+ ["US-ASCII", "\x01\x81", "US-ASCII", "\x01\x01", "US-ASCII"],
+ ["US-ASCII", "\x01\x81", "US-ASCII", "\x01\x81", "US-ASCII"],
+ ["US-ASCII", "\x01\x81", "UTF-8", "", "US-ASCII"],
+ ["US-ASCII", "\x01\x81", "UTF-8", "\u0001\u0001", "US-ASCII"],
+ ["US-ASCII", "\x01\x81", "UTF-8", "\u0001\x81", nil],
+ ["US-ASCII", "\x01\x81", "ASCII-8BIT", "", "US-ASCII"],
+ ["US-ASCII", "\x01\x81", "ASCII-8BIT", "\x01\x01", "US-ASCII"],
+ ["US-ASCII", "\x01\x81", "ASCII-8BIT", "\x01\x81", nil],
+ ["US-ASCII", "\x01\x81", "ISO-8859-1", "", "US-ASCII"],
+ ["US-ASCII", "\x01\x81", "ISO-8859-1", "\x01\x01", "US-ASCII"],
+ ["US-ASCII", "\x01\x81", "ISO-8859-1", "\x01\x81", nil],
+ ["US-ASCII", "\x01\x81", "UTF-16BE", "", "US-ASCII"],
+ ["US-ASCII", "\x01\x81", "UTF-16BE", "\u0101", nil],
+ ["US-ASCII", "\x01\x81", "UTF-16BE", "\u0181", nil],
+ ["US-ASCII", "\x01\x81", "ISO-2022-JP", "", "US-ASCII"],
+ ["US-ASCII", "\x01\x81", "ISO-2022-JP", "\x01\x01", nil],
+ ["US-ASCII", "\x01\x81", "ISO-2022-JP", "\x01\x81", nil],
+ ["UTF-8", "", "US-ASCII", "", "UTF-8"],
+ ["UTF-8", "", "US-ASCII", "\x01\x01", "UTF-8"],
+ ["UTF-8", "", "US-ASCII", "\x01\x81", "US-ASCII"],
+ ["UTF-8", "", "UTF-8", "", "UTF-8"],
+ ["UTF-8", "", "UTF-8", "\u0001\u0001", "UTF-8"],
+ ["UTF-8", "", "UTF-8", "\u0001\x81", "UTF-8"],
+ ["UTF-8", "", "ASCII-8BIT", "", "UTF-8"],
+ ["UTF-8", "", "ASCII-8BIT", "\x01\x01", "UTF-8"],
+ ["UTF-8", "", "ASCII-8BIT", "\x01\x81", "ASCII-8BIT"],
+ ["UTF-8", "", "ISO-8859-1", "", "UTF-8"],
+ ["UTF-8", "", "ISO-8859-1", "\x01\x01", "UTF-8"],
+ ["UTF-8", "", "ISO-8859-1", "\x01\x81", "ISO-8859-1"],
+ ["UTF-8", "", "UTF-16BE", "", "UTF-8"],
+ ["UTF-8", "", "UTF-16BE", "\u0101", "UTF-16BE"],
+ ["UTF-8", "", "UTF-16BE", "\u0181", "UTF-16BE"],
+ ["UTF-8", "", "ISO-2022-JP", "", "UTF-8"],
+ ["UTF-8", "", "ISO-2022-JP", "\x01\x01", "ISO-2022-JP"],
+ ["UTF-8", "", "ISO-2022-JP", "\x01\x81", "ISO-2022-JP"],
+ ["UTF-8", "\u0001\u0001", "US-ASCII", "", "UTF-8"],
+ ["UTF-8", "\u0001\u0001", "US-ASCII", "\x01\x01", "UTF-8"],
+ ["UTF-8", "\u0001\u0001", "US-ASCII", "\x01\x81", "US-ASCII"],
+ ["UTF-8", "\u0001\u0001", "UTF-8", "", "UTF-8"],
+ ["UTF-8", "\u0001\u0001", "UTF-8", "\u0001\u0001", "UTF-8"],
+ ["UTF-8", "\u0001\u0001", "UTF-8", "\u0001\x81", "UTF-8"],
+ ["UTF-8", "\u0001\u0001", "ASCII-8BIT", "", "UTF-8"],
+ ["UTF-8", "\u0001\u0001", "ASCII-8BIT", "\x01\x01", "UTF-8"],
+ ["UTF-8", "\u0001\u0001", "ASCII-8BIT", "\x01\x81", "ASCII-8BIT"],
+ ["UTF-8", "\u0001\u0001", "ISO-8859-1", "", "UTF-8"],
+ ["UTF-8", "\u0001\u0001", "ISO-8859-1", "\x01\x01", "UTF-8"],
+ ["UTF-8", "\u0001\u0001", "ISO-8859-1", "\x01\x81", "ISO-8859-1"],
+ ["UTF-8", "\u0001\u0001", "UTF-16BE", "", "UTF-8"],
+ ["UTF-8", "\u0001\u0001", "UTF-16BE", "\u0101", nil],
+ ["UTF-8", "\u0001\u0001", "UTF-16BE", "\u0181", nil],
+ ["UTF-8", "\u0001\u0001", "ISO-2022-JP", "", "UTF-8"],
+ ["UTF-8", "\u0001\u0001", "ISO-2022-JP", "\x01\x01", nil],
+ ["UTF-8", "\u0001\u0001", "ISO-2022-JP", "\x01\x81", nil],
+ ["UTF-8", "\u0001\x81", "US-ASCII", "", "UTF-8"],
+ ["UTF-8", "\u0001\x81", "US-ASCII", "\x01\x01", "UTF-8"],
+ ["UTF-8", "\u0001\x81", "US-ASCII", "\x01\x81", nil],
+ ["UTF-8", "\u0001\x81", "UTF-8", "", "UTF-8"],
+ ["UTF-8", "\u0001\x81", "UTF-8", "\u0001\u0001", "UTF-8"],
+ ["UTF-8", "\u0001\x81", "UTF-8", "\u0001\x81", "UTF-8"],
+ ["UTF-8", "\u0001\x81", "ASCII-8BIT", "", "UTF-8"],
+ ["UTF-8", "\u0001\x81", "ASCII-8BIT", "\x01\x01", "UTF-8"],
+ ["UTF-8", "\u0001\x81", "ASCII-8BIT", "\x01\x81", nil],
+ ["UTF-8", "\u0001\x81", "ISO-8859-1", "", "UTF-8"],
+ ["UTF-8", "\u0001\x81", "ISO-8859-1", "\x01\x01", "UTF-8"],
+ ["UTF-8", "\u0001\x81", "ISO-8859-1", "\x01\x81", nil],
+ ["UTF-8", "\u0001\x81", "UTF-16BE", "", "UTF-8"],
+ ["UTF-8", "\u0001\x81", "UTF-16BE", "\u0101", nil],
+ ["UTF-8", "\u0001\x81", "UTF-16BE", "\u0181", nil],
+ ["UTF-8", "\u0001\x81", "ISO-2022-JP", "", "UTF-8"],
+ ["UTF-8", "\u0001\x81", "ISO-2022-JP", "\x01\x01", nil],
+ ["UTF-8", "\u0001\x81", "ISO-2022-JP", "\x01\x81", nil],
+ ["ASCII-8BIT", "", "US-ASCII", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "", "US-ASCII", "\x01\x01", "ASCII-8BIT"],
+ ["ASCII-8BIT", "", "US-ASCII", "\x01\x81", "US-ASCII"],
+ ["ASCII-8BIT", "", "UTF-8", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "", "UTF-8", "\u0001\u0001", "ASCII-8BIT"],
+ ["ASCII-8BIT", "", "UTF-8", "\u0001\x81", "UTF-8"],
+ ["ASCII-8BIT", "", "ASCII-8BIT", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "", "ASCII-8BIT", "\x01\x01", "ASCII-8BIT"],
+ ["ASCII-8BIT", "", "ASCII-8BIT", "\x01\x81", "ASCII-8BIT"],
+ ["ASCII-8BIT", "", "ISO-8859-1", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "", "ISO-8859-1", "\x01\x01", "ASCII-8BIT"],
+ ["ASCII-8BIT", "", "ISO-8859-1", "\x01\x81", "ISO-8859-1"],
+ ["ASCII-8BIT", "", "UTF-16BE", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "", "UTF-16BE", "\u0101", "UTF-16BE"],
+ ["ASCII-8BIT", "", "UTF-16BE", "\u0181", "UTF-16BE"],
+ ["ASCII-8BIT", "", "ISO-2022-JP", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "", "ISO-2022-JP", "\x01\x01", "ISO-2022-JP"],
+ ["ASCII-8BIT", "", "ISO-2022-JP", "\x01\x81", "ISO-2022-JP"],
+ ["ASCII-8BIT", "\x01\x01", "US-ASCII", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x01", "US-ASCII", "\x01\x01", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x01", "US-ASCII", "\x01\x81", "US-ASCII"],
+ ["ASCII-8BIT", "\x01\x01", "UTF-8", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x01", "UTF-8", "\u0001\u0001", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x01", "UTF-8", "\u0001\x81", "UTF-8"],
+ ["ASCII-8BIT", "\x01\x01", "ASCII-8BIT", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x01", "ASCII-8BIT", "\x01\x01", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x01", "ASCII-8BIT", "\x01\x81", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x01", "ISO-8859-1", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x01", "ISO-8859-1", "\x01\x01", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x01", "ISO-8859-1", "\x01\x81", "ISO-8859-1"],
+ ["ASCII-8BIT", "\x01\x01", "UTF-16BE", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x01", "UTF-16BE", "\u0101", nil],
+ ["ASCII-8BIT", "\x01\x01", "UTF-16BE", "\u0181", nil],
+ ["ASCII-8BIT", "\x01\x01", "ISO-2022-JP", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x01", "ISO-2022-JP", "\x01\x01", nil],
+ ["ASCII-8BIT", "\x01\x01", "ISO-2022-JP", "\x01\x81", nil],
+ ["ASCII-8BIT", "\x01\x81", "US-ASCII", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x81", "US-ASCII", "\x01\x01", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x81", "US-ASCII", "\x01\x81", nil],
+ ["ASCII-8BIT", "\x01\x81", "UTF-8", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x81", "UTF-8", "\u0001\u0001", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x81", "UTF-8", "\u0001\x81", nil],
+ ["ASCII-8BIT", "\x01\x81", "ASCII-8BIT", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x81", "ASCII-8BIT", "\x01\x01", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x81", "ASCII-8BIT", "\x01\x81", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x81", "ISO-8859-1", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x81", "ISO-8859-1", "\x01\x01", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x81", "ISO-8859-1", "\x01\x81", nil],
+ ["ASCII-8BIT", "\x01\x81", "UTF-16BE", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x81", "UTF-16BE", "\u0101", nil],
+ ["ASCII-8BIT", "\x01\x81", "UTF-16BE", "\u0181", nil],
+ ["ASCII-8BIT", "\x01\x81", "ISO-2022-JP", "", "ASCII-8BIT"],
+ ["ASCII-8BIT", "\x01\x81", "ISO-2022-JP", "\x01\x01", nil],
+ ["ASCII-8BIT", "\x01\x81", "ISO-2022-JP", "\x01\x81", nil],
+ ["ISO-8859-1", "", "US-ASCII", "", "ISO-8859-1"],
+ ["ISO-8859-1", "", "US-ASCII", "\x01\x01", "ISO-8859-1"],
+ ["ISO-8859-1", "", "US-ASCII", "\x01\x81", "US-ASCII"],
+ ["ISO-8859-1", "", "UTF-8", "", "ISO-8859-1"],
+ ["ISO-8859-1", "", "UTF-8", "\u0001\u0001", "ISO-8859-1"],
+ ["ISO-8859-1", "", "UTF-8", "\u0001\x81", "UTF-8"],
+ ["ISO-8859-1", "", "ASCII-8BIT", "", "ISO-8859-1"],
+ ["ISO-8859-1", "", "ASCII-8BIT", "\x01\x01", "ISO-8859-1"],
+ ["ISO-8859-1", "", "ASCII-8BIT", "\x01\x81", "ASCII-8BIT"],
+ ["ISO-8859-1", "", "ISO-8859-1", "", "ISO-8859-1"],
+ ["ISO-8859-1", "", "ISO-8859-1", "\x01\x01", "ISO-8859-1"],
+ ["ISO-8859-1", "", "ISO-8859-1", "\x01\x81", "ISO-8859-1"],
+ ["ISO-8859-1", "", "UTF-16BE", "", "ISO-8859-1"],
+ ["ISO-8859-1", "", "UTF-16BE", "\u0101", "UTF-16BE"],
+ ["ISO-8859-1", "", "UTF-16BE", "\u0181", "UTF-16BE"],
+ ["ISO-8859-1", "", "ISO-2022-JP", "", "ISO-8859-1"],
+ ["ISO-8859-1", "", "ISO-2022-JP", "\x01\x01", "ISO-2022-JP"],
+ ["ISO-8859-1", "", "ISO-2022-JP", "\x01\x81", "ISO-2022-JP"],
+ ["ISO-8859-1", "\x01\x01", "US-ASCII", "", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x01", "US-ASCII", "\x01\x01", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x01", "US-ASCII", "\x01\x81", "US-ASCII"],
+ ["ISO-8859-1", "\x01\x01", "UTF-8", "", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x01", "UTF-8", "\u0001\u0001", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x01", "UTF-8", "\u0001\x81", "UTF-8"],
+ ["ISO-8859-1", "\x01\x01", "ASCII-8BIT", "", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x01", "ASCII-8BIT", "\x01\x01", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x01", "ASCII-8BIT", "\x01\x81", "ASCII-8BIT"],
+ ["ISO-8859-1", "\x01\x01", "ISO-8859-1", "", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x01", "ISO-8859-1", "\x01\x01", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x01", "ISO-8859-1", "\x01\x81", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x01", "UTF-16BE", "", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x01", "UTF-16BE", "\u0101", nil],
+ ["ISO-8859-1", "\x01\x01", "UTF-16BE", "\u0181", nil],
+ ["ISO-8859-1", "\x01\x01", "ISO-2022-JP", "", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x01", "ISO-2022-JP", "\x01\x01", nil],
+ ["ISO-8859-1", "\x01\x01", "ISO-2022-JP", "\x01\x81", nil],
+ ["ISO-8859-1", "\x01\x81", "US-ASCII", "", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x81", "US-ASCII", "\x01\x01", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x81", "US-ASCII", "\x01\x81", nil],
+ ["ISO-8859-1", "\x01\x81", "UTF-8", "", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x81", "UTF-8", "\u0001\u0001", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x81", "UTF-8", "\u0001\x81", nil],
+ ["ISO-8859-1", "\x01\x81", "ASCII-8BIT", "", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x81", "ASCII-8BIT", "\x01\x01", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x81", "ASCII-8BIT", "\x01\x81", nil],
+ ["ISO-8859-1", "\x01\x81", "ISO-8859-1", "", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x81", "ISO-8859-1", "\x01\x01", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x81", "ISO-8859-1", "\x01\x81", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x81", "UTF-16BE", "", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x81", "UTF-16BE", "\u0101", nil],
+ ["ISO-8859-1", "\x01\x81", "UTF-16BE", "\u0181", nil],
+ ["ISO-8859-1", "\x01\x81", "ISO-2022-JP", "", "ISO-8859-1"],
+ ["ISO-8859-1", "\x01\x81", "ISO-2022-JP", "\x01\x01", nil],
+ ["ISO-8859-1", "\x01\x81", "ISO-2022-JP", "\x01\x81", nil],
+ ["UTF-16BE", "", "US-ASCII", "", "UTF-16BE"],
+ ["UTF-16BE", "", "US-ASCII", "\x01\x01", "US-ASCII"],
+ ["UTF-16BE", "", "US-ASCII", "\x01\x81", "US-ASCII"],
+ ["UTF-16BE", "", "UTF-8", "", "UTF-16BE"],
+ ["UTF-16BE", "", "UTF-8", "\u0001\u0001", "UTF-8"],
+ ["UTF-16BE", "", "UTF-8", "\u0001\x81", "UTF-8"],
+ ["UTF-16BE", "", "ASCII-8BIT", "", "UTF-16BE"],
+ ["UTF-16BE", "", "ASCII-8BIT", "\x01\x01", "ASCII-8BIT"],
+ ["UTF-16BE", "", "ASCII-8BIT", "\x01\x81", "ASCII-8BIT"],
+ ["UTF-16BE", "", "ISO-8859-1", "", "UTF-16BE"],
+ ["UTF-16BE", "", "ISO-8859-1", "\x01\x01", "ISO-8859-1"],
+ ["UTF-16BE", "", "ISO-8859-1", "\x01\x81", "ISO-8859-1"],
+ ["UTF-16BE", "", "UTF-16BE", "", "UTF-16BE"],
+ ["UTF-16BE", "", "UTF-16BE", "\u0101", "UTF-16BE"],
+ ["UTF-16BE", "", "UTF-16BE", "\u0181", "UTF-16BE"],
+ ["UTF-16BE", "", "ISO-2022-JP", "", "UTF-16BE"],
+ ["UTF-16BE", "", "ISO-2022-JP", "\x01\x01", "ISO-2022-JP"],
+ ["UTF-16BE", "", "ISO-2022-JP", "\x01\x81", "ISO-2022-JP"],
+ ["UTF-16BE", "\u0101", "US-ASCII", "", "UTF-16BE"],
+ ["UTF-16BE", "\u0101", "US-ASCII", "\x01\x01", nil],
+ ["UTF-16BE", "\u0101", "US-ASCII", "\x01\x81", nil],
+ ["UTF-16BE", "\u0101", "UTF-8", "", "UTF-16BE"],
+ ["UTF-16BE", "\u0101", "UTF-8", "\u0001\u0001", nil],
+ ["UTF-16BE", "\u0101", "UTF-8", "\u0001\x81", nil],
+ ["UTF-16BE", "\u0101", "ASCII-8BIT", "", "UTF-16BE"],
+ ["UTF-16BE", "\u0101", "ASCII-8BIT", "\x01\x01", nil],
+ ["UTF-16BE", "\u0101", "ASCII-8BIT", "\x01\x81", nil],
+ ["UTF-16BE", "\u0101", "ISO-8859-1", "", "UTF-16BE"],
+ ["UTF-16BE", "\u0101", "ISO-8859-1", "\x01\x01", nil],
+ ["UTF-16BE", "\u0101", "ISO-8859-1", "\x01\x81", nil],
+ ["UTF-16BE", "\u0101", "UTF-16BE", "", "UTF-16BE"],
+ ["UTF-16BE", "\u0101", "UTF-16BE", "\u0101", "UTF-16BE"],
+ ["UTF-16BE", "\u0101", "UTF-16BE", "\u0181", "UTF-16BE"],
+ ["UTF-16BE", "\u0101", "ISO-2022-JP", "", "UTF-16BE"],
+ ["UTF-16BE", "\u0101", "ISO-2022-JP", "\x01\x01", nil],
+ ["UTF-16BE", "\u0101", "ISO-2022-JP", "\x01\x81", nil],
+ ["UTF-16BE", "\u0181", "US-ASCII", "", "UTF-16BE"],
+ ["UTF-16BE", "\u0181", "US-ASCII", "\x01\x01", nil],
+ ["UTF-16BE", "\u0181", "US-ASCII", "\x01\x81", nil],
+ ["UTF-16BE", "\u0181", "UTF-8", "", "UTF-16BE"],
+ ["UTF-16BE", "\u0181", "UTF-8", "\u0001\u0001", nil],
+ ["UTF-16BE", "\u0181", "UTF-8", "\u0001\x81", nil],
+ ["UTF-16BE", "\u0181", "ASCII-8BIT", "", "UTF-16BE"],
+ ["UTF-16BE", "\u0181", "ASCII-8BIT", "\x01\x01", nil],
+ ["UTF-16BE", "\u0181", "ASCII-8BIT", "\x01\x81", nil],
+ ["UTF-16BE", "\u0181", "ISO-8859-1", "", "UTF-16BE"],
+ ["UTF-16BE", "\u0181", "ISO-8859-1", "\x01\x01", nil],
+ ["UTF-16BE", "\u0181", "ISO-8859-1", "\x01\x81", nil],
+ ["UTF-16BE", "\u0181", "UTF-16BE", "", "UTF-16BE"],
+ ["UTF-16BE", "\u0181", "UTF-16BE", "\u0101", "UTF-16BE"],
+ ["UTF-16BE", "\u0181", "UTF-16BE", "\u0181", "UTF-16BE"],
+ ["UTF-16BE", "\u0181", "ISO-2022-JP", "", "UTF-16BE"],
+ ["UTF-16BE", "\u0181", "ISO-2022-JP", "\x01\x01", nil],
+ ["UTF-16BE", "\u0181", "ISO-2022-JP", "\x01\x81", nil],
+ ["ISO-2022-JP", "", "US-ASCII", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "", "US-ASCII", "\x01\x01", "US-ASCII"],
+ ["ISO-2022-JP", "", "US-ASCII", "\x01\x81", "US-ASCII"],
+ ["ISO-2022-JP", "", "UTF-8", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "", "UTF-8", "\u0001\u0001", "UTF-8"],
+ ["ISO-2022-JP", "", "UTF-8", "\u0001\x81", "UTF-8"],
+ ["ISO-2022-JP", "", "ASCII-8BIT", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "", "ASCII-8BIT", "\x01\x01", "ASCII-8BIT"],
+ ["ISO-2022-JP", "", "ASCII-8BIT", "\x01\x81", "ASCII-8BIT"],
+ ["ISO-2022-JP", "", "ISO-8859-1", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "", "ISO-8859-1", "\x01\x01", "ISO-8859-1"],
+ ["ISO-2022-JP", "", "ISO-8859-1", "\x01\x81", "ISO-8859-1"],
+ ["ISO-2022-JP", "", "UTF-16BE", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "", "UTF-16BE", "\u0101", "UTF-16BE"],
+ ["ISO-2022-JP", "", "UTF-16BE", "\u0181", "UTF-16BE"],
+ ["ISO-2022-JP", "", "ISO-2022-JP", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "", "ISO-2022-JP", "\x01\x01", "ISO-2022-JP"],
+ ["ISO-2022-JP", "", "ISO-2022-JP", "\x01\x81", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x01", "US-ASCII", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x01", "US-ASCII", "\x01\x01", nil],
+ ["ISO-2022-JP", "\x01\x01", "US-ASCII", "\x01\x81", nil],
+ ["ISO-2022-JP", "\x01\x01", "UTF-8", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x01", "UTF-8", "\u0001\u0001", nil],
+ ["ISO-2022-JP", "\x01\x01", "UTF-8", "\u0001\x81", nil],
+ ["ISO-2022-JP", "\x01\x01", "ASCII-8BIT", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x01", "ASCII-8BIT", "\x01\x01", nil],
+ ["ISO-2022-JP", "\x01\x01", "ASCII-8BIT", "\x01\x81", nil],
+ ["ISO-2022-JP", "\x01\x01", "ISO-8859-1", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x01", "ISO-8859-1", "\x01\x01", nil],
+ ["ISO-2022-JP", "\x01\x01", "ISO-8859-1", "\x01\x81", nil],
+ ["ISO-2022-JP", "\x01\x01", "UTF-16BE", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x01", "UTF-16BE", "\u0101", nil],
+ ["ISO-2022-JP", "\x01\x01", "UTF-16BE", "\u0181", nil],
+ ["ISO-2022-JP", "\x01\x01", "ISO-2022-JP", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x01", "ISO-2022-JP", "\x01\x01", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x01", "ISO-2022-JP", "\x01\x81", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x81", "US-ASCII", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x81", "US-ASCII", "\x01\x01", nil],
+ ["ISO-2022-JP", "\x01\x81", "US-ASCII", "\x01\x81", nil],
+ ["ISO-2022-JP", "\x01\x81", "UTF-8", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x81", "UTF-8", "\u0001\u0001", nil],
+ ["ISO-2022-JP", "\x01\x81", "UTF-8", "\u0001\x81", nil],
+ ["ISO-2022-JP", "\x01\x81", "ASCII-8BIT", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x81", "ASCII-8BIT", "\x01\x01", nil],
+ ["ISO-2022-JP", "\x01\x81", "ASCII-8BIT", "\x01\x81", nil],
+ ["ISO-2022-JP", "\x01\x81", "ISO-8859-1", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x81", "ISO-8859-1", "\x01\x01", nil],
+ ["ISO-2022-JP", "\x01\x81", "ISO-8859-1", "\x01\x81", nil],
+ ["ISO-2022-JP", "\x01\x81", "UTF-16BE", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x81", "UTF-16BE", "\u0101", nil],
+ ["ISO-2022-JP", "\x01\x81", "UTF-16BE", "\u0181", nil],
+ ["ISO-2022-JP", "\x01\x81", "ISO-2022-JP", "", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x81", "ISO-2022-JP", "\x01\x01", "ISO-2022-JP"],
+ ["ISO-2022-JP", "\x01\x81", "ISO-2022-JP", "\x01\x81", "ISO-2022-JP"],
+ ]
+
+ matrix.each do |encoding1, value1, encoding2, value2, compatible_encoding|
+ it "returns #{compatible_encoding} for #{value1.inspect} in #{encoding1} and #{value2.inspect} in #{encoding2}" do
+ actual_encoding = Encoding.compatible?(value1.dup.force_encoding(encoding1), value2.dup.force_encoding(encoding2))
+ actual_encoding&.name.should == compatible_encoding
+ end
+ end
+ end
end
describe "Encoding.compatible? String, Regexp" do
@@ -377,3 +750,9 @@ describe "Encoding.compatible? Object, Object" do
Encoding.compatible?(:sym, Object.new).should be_nil
end
end
+
+describe "Encoding.compatible? nil, nil" do
+ it "returns nil" do
+ Encoding.compatible?(nil, nil).should be_nil
+ end
+end
diff --git a/spec/ruby/core/encoding/converter/convert_spec.rb b/spec/ruby/core/encoding/converter/convert_spec.rb
index 7f249d90a3..8533af4565 100644
--- a/spec/ruby/core/encoding/converter/convert_spec.rb
+++ b/spec/ruby/core/encoding/converter/convert_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
# frozen_string_literal: true
require_relative '../../../spec_helper'
diff --git a/spec/ruby/core/encoding/converter/finish_spec.rb b/spec/ruby/core/encoding/converter/finish_spec.rb
index 239243430b..22e66df38c 100644
--- a/spec/ruby/core/encoding/converter/finish_spec.rb
+++ b/spec/ruby/core/encoding/converter/finish_spec.rb
@@ -16,8 +16,8 @@ describe "Encoding::Converter#finish" do
end
it "returns the last part of the converted String if it hasn't already" do
- @ec.convert("\u{9999}").should == "\e$B9a".dup.force_encoding('iso-2022-jp')
- @ec.finish.should == "\e(B".dup.force_encoding('iso-2022-jp')
+ @ec.convert("\u{9999}").should == "\e$B9a".dup.force_encoding('iso-2022-jp')
+ @ec.finish.should == "\e(B".dup.force_encoding('iso-2022-jp')
end
it "returns a String in the destination encoding" do
diff --git a/spec/ruby/core/encoding/converter/last_error_spec.rb b/spec/ruby/core/encoding/converter/last_error_spec.rb
index 78779be70b..ff2a2b4cbe 100644
--- a/spec/ruby/core/encoding/converter/last_error_spec.rb
+++ b/spec/ruby/core/encoding/converter/last_error_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
describe "Encoding::Converter#last_error" do
diff --git a/spec/ruby/core/encoding/converter/new_spec.rb b/spec/ruby/core/encoding/converter/new_spec.rb
index db9c3364d7..a7bef53809 100644
--- a/spec/ruby/core/encoding/converter/new_spec.rb
+++ b/spec/ruby/core/encoding/converter/new_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
describe "Encoding::Converter.new" do
diff --git a/spec/ruby/core/encoding/converter/primitive_convert_spec.rb b/spec/ruby/core/encoding/converter/primitive_convert_spec.rb
index 63f25eddef..e4aeed103e 100644
--- a/spec/ruby/core/encoding/converter/primitive_convert_spec.rb
+++ b/spec/ruby/core/encoding/converter/primitive_convert_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
# frozen_string_literal: false
require_relative '../../../spec_helper'
diff --git a/spec/ruby/core/encoding/converter/primitive_errinfo_spec.rb b/spec/ruby/core/encoding/converter/primitive_errinfo_spec.rb
index 668eb9a924..5ee8b1fecd 100644
--- a/spec/ruby/core/encoding/converter/primitive_errinfo_spec.rb
+++ b/spec/ruby/core/encoding/converter/primitive_errinfo_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
# frozen_string_literal: false
require_relative '../../../spec_helper'
diff --git a/spec/ruby/core/encoding/converter/putback_spec.rb b/spec/ruby/core/encoding/converter/putback_spec.rb
index e19fe6c314..04bb565655 100644
--- a/spec/ruby/core/encoding/converter/putback_spec.rb
+++ b/spec/ruby/core/encoding/converter/putback_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
describe "Encoding::Converter#putback" do
diff --git a/spec/ruby/core/encoding/converter/search_convpath_spec.rb b/spec/ruby/core/encoding/converter/search_convpath_spec.rb
index 0882af5539..59fe4520c0 100644
--- a/spec/ruby/core/encoding/converter/search_convpath_spec.rb
+++ b/spec/ruby/core/encoding/converter/search_convpath_spec.rb
@@ -23,8 +23,8 @@ describe "Encoding::Converter.search_convpath" do
end
it "raises an Encoding::ConverterNotFoundError if no conversion path exists" do
- -> do
- Encoding::Converter.search_convpath(Encoding::BINARY, Encoding::Emacs_Mule)
- end.should raise_error(Encoding::ConverterNotFoundError)
+ -> do
+ Encoding::Converter.search_convpath(Encoding::BINARY, Encoding::Emacs_Mule)
+ end.should raise_error(Encoding::ConverterNotFoundError)
end
end
diff --git a/spec/ruby/core/encoding/find_spec.rb b/spec/ruby/core/encoding/find_spec.rb
index 8a0873070f..9c34fe0e77 100644
--- a/spec/ruby/core/encoding/find_spec.rb
+++ b/spec/ruby/core/encoding/find_spec.rb
@@ -50,7 +50,7 @@ describe "Encoding.find" do
end
it "raises an ArgumentError if the given encoding does not exist" do
- -> { Encoding.find('dh2dh278d') }.should raise_error(ArgumentError)
+ -> { Encoding.find('dh2dh278d') }.should raise_error(ArgumentError, 'unknown encoding name - dh2dh278d')
end
# Not sure how to do a better test, since locale depends on weird platform-specific stuff
diff --git a/spec/ruby/core/encoding/fixtures/classes.rb b/spec/ruby/core/encoding/fixtures/classes.rb
index 12e9a4f348..943865e8d8 100644
--- a/spec/ruby/core/encoding/fixtures/classes.rb
+++ b/spec/ruby/core/encoding/fixtures/classes.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
module EncodingSpecs
class UndefinedConversionError
def self.exception
diff --git a/spec/ruby/core/encoding/invalid_byte_sequence_error/error_bytes_spec.rb b/spec/ruby/core/encoding/invalid_byte_sequence_error/error_bytes_spec.rb
index d2fc360dce..8b7e87960f 100644
--- a/spec/ruby/core/encoding/invalid_byte_sequence_error/error_bytes_spec.rb
+++ b/spec/ruby/core/encoding/invalid_byte_sequence_error/error_bytes_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative "../../../spec_helper"
require_relative '../fixtures/classes'
diff --git a/spec/ruby/core/encoding/invalid_byte_sequence_error/incomplete_input_spec.rb b/spec/ruby/core/encoding/invalid_byte_sequence_error/incomplete_input_spec.rb
index 8a3f3de69a..83606f77b4 100644
--- a/spec/ruby/core/encoding/invalid_byte_sequence_error/incomplete_input_spec.rb
+++ b/spec/ruby/core/encoding/invalid_byte_sequence_error/incomplete_input_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
describe "Encoding::InvalidByteSequenceError#incomplete_input?" do
diff --git a/spec/ruby/core/encoding/invalid_byte_sequence_error/readagain_bytes_spec.rb b/spec/ruby/core/encoding/invalid_byte_sequence_error/readagain_bytes_spec.rb
index a5e2824984..e5ad0a61bd 100644
--- a/spec/ruby/core/encoding/invalid_byte_sequence_error/readagain_bytes_spec.rb
+++ b/spec/ruby/core/encoding/invalid_byte_sequence_error/readagain_bytes_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative "../../../spec_helper"
require_relative '../fixtures/classes'
diff --git a/spec/ruby/core/encoding/replicate_spec.rb b/spec/ruby/core/encoding/replicate_spec.rb
index e22673db7d..2da998837f 100644
--- a/spec/ruby/core/encoding/replicate_spec.rb
+++ b/spec/ruby/core/encoding/replicate_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
describe "Encoding#replicate" do
@@ -67,7 +67,7 @@ describe "Encoding#replicate" do
end
end
- ruby_version_is "3.2"..."3.3" do
+ ruby_version_is ""..."3.3" do
it "warns about deprecation" do
-> {
Encoding::US_ASCII.replicate('MY-US-ASCII')
diff --git a/spec/ruby/core/enumerable/collect_concat_spec.rb b/spec/ruby/core/enumerable/collect_concat_spec.rb
index 6e34c9eb93..59317cfe34 100644
--- a/spec/ruby/core/enumerable/collect_concat_spec.rb
+++ b/spec/ruby/core/enumerable/collect_concat_spec.rb
@@ -3,5 +3,5 @@ require_relative 'fixtures/classes'
require_relative 'shared/collect_concat'
describe "Enumerable#collect_concat" do
- it_behaves_like :enumerable_collect_concat , :collect_concat
+ it_behaves_like :enumerable_collect_concat, :collect_concat
end
diff --git a/spec/ruby/core/enumerable/collect_spec.rb b/spec/ruby/core/enumerable/collect_spec.rb
index 1016b67798..cfa2895cce 100644
--- a/spec/ruby/core/enumerable/collect_spec.rb
+++ b/spec/ruby/core/enumerable/collect_spec.rb
@@ -3,5 +3,5 @@ require_relative 'fixtures/classes'
require_relative 'shared/collect'
describe "Enumerable#collect" do
- it_behaves_like :enumerable_collect , :collect
+ it_behaves_like :enumerable_collect, :collect
end
diff --git a/spec/ruby/core/enumerable/compact_spec.rb b/spec/ruby/core/enumerable/compact_spec.rb
index 86e95dce08..1895430c4e 100644
--- a/spec/ruby/core/enumerable/compact_spec.rb
+++ b/spec/ruby/core/enumerable/compact_spec.rb
@@ -1,11 +1,9 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is '3.1' do
- describe "Enumerable#compact" do
- it 'returns array without nil elements' do
- arr = EnumerableSpecs::Numerous.new(nil, 1, 2, nil, true)
- arr.compact.should == [1, 2, true]
- end
+describe "Enumerable#compact" do
+ it 'returns array without nil elements' do
+ arr = EnumerableSpecs::Numerous.new(nil, 1, 2, nil, true)
+ arr.compact.should == [1, 2, true]
end
end
diff --git a/spec/ruby/core/enumerable/detect_spec.rb b/spec/ruby/core/enumerable/detect_spec.rb
index e912134fed..6959aadc44 100644
--- a/spec/ruby/core/enumerable/detect_spec.rb
+++ b/spec/ruby/core/enumerable/detect_spec.rb
@@ -3,5 +3,5 @@ require_relative 'fixtures/classes'
require_relative 'shared/find'
describe "Enumerable#detect" do
- it_behaves_like :enumerable_find , :detect
+ it_behaves_like :enumerable_find, :detect
end
diff --git a/spec/ruby/core/enumerable/each_cons_spec.rb b/spec/ruby/core/enumerable/each_cons_spec.rb
index 8fb31fb925..ed77741862 100644
--- a/spec/ruby/core/enumerable/each_cons_spec.rb
+++ b/spec/ruby/core/enumerable/each_cons_spec.rb
@@ -56,10 +56,8 @@ describe "Enumerable#each_cons" do
multi.each_cons(2).to_a.should == [[[1, 2], [3, 4, 5]], [[3, 4, 5], [6, 7, 8, 9]]]
end
- ruby_version_is "3.1" do
- it "returns self when a block is given" do
- @enum.each_cons(3){}.should == @enum
- end
+ it "returns self when a block is given" do
+ @enum.each_cons(3){}.should == @enum
end
describe "when no block is given" do
diff --git a/spec/ruby/core/enumerable/each_slice_spec.rb b/spec/ruby/core/enumerable/each_slice_spec.rb
index a57a1dba81..47b8c9ba33 100644
--- a/spec/ruby/core/enumerable/each_slice_spec.rb
+++ b/spec/ruby/core/enumerable/each_slice_spec.rb
@@ -57,10 +57,8 @@ describe "Enumerable#each_slice" do
e.to_a.should == @sliced
end
- ruby_version_is "3.1" do
- it "returns self when a block is given" do
- @enum.each_slice(3){}.should == @enum
- end
+ it "returns self when a block is given" do
+ @enum.each_slice(3){}.should == @enum
end
it "gathers whole arrays as elements when each yields multiple" do
diff --git a/spec/ruby/core/enumerable/entries_spec.rb b/spec/ruby/core/enumerable/entries_spec.rb
index 83232cfa06..2de4fc756a 100644
--- a/spec/ruby/core/enumerable/entries_spec.rb
+++ b/spec/ruby/core/enumerable/entries_spec.rb
@@ -3,5 +3,5 @@ require_relative 'fixtures/classes'
require_relative 'shared/entries'
describe "Enumerable#entries" do
- it_behaves_like :enumerable_entries , :entries
+ it_behaves_like :enumerable_entries, :entries
end
diff --git a/spec/ruby/core/enumerable/filter_spec.rb b/spec/ruby/core/enumerable/filter_spec.rb
index 7e4f8c0b50..1c3a7e9ff5 100644
--- a/spec/ruby/core/enumerable/filter_spec.rb
+++ b/spec/ruby/core/enumerable/filter_spec.rb
@@ -3,5 +3,5 @@ require_relative 'fixtures/classes'
require_relative 'shared/find_all'
describe "Enumerable#filter" do
- it_behaves_like(:enumerable_find_all , :filter)
+ it_behaves_like :enumerable_find_all, :filter
end
diff --git a/spec/ruby/core/enumerable/find_all_spec.rb b/spec/ruby/core/enumerable/find_all_spec.rb
index ce9058fe77..9cd635f247 100644
--- a/spec/ruby/core/enumerable/find_all_spec.rb
+++ b/spec/ruby/core/enumerable/find_all_spec.rb
@@ -3,5 +3,5 @@ require_relative 'fixtures/classes'
require_relative 'shared/find_all'
describe "Enumerable#find_all" do
- it_behaves_like :enumerable_find_all , :find_all
+ it_behaves_like :enumerable_find_all, :find_all
end
diff --git a/spec/ruby/core/enumerable/find_spec.rb b/spec/ruby/core/enumerable/find_spec.rb
index 25aa3bf103..5ddebc05f8 100644
--- a/spec/ruby/core/enumerable/find_spec.rb
+++ b/spec/ruby/core/enumerable/find_spec.rb
@@ -3,5 +3,5 @@ require_relative 'fixtures/classes'
require_relative 'shared/find'
describe "Enumerable#find" do
- it_behaves_like :enumerable_find , :find
+ it_behaves_like :enumerable_find, :find
end
diff --git a/spec/ruby/core/enumerable/fixtures/classes.rb b/spec/ruby/core/enumerable/fixtures/classes.rb
index 2701c6999c..b5feafcfb7 100644
--- a/spec/ruby/core/enumerable/fixtures/classes.rb
+++ b/spec/ruby/core/enumerable/fixtures/classes.rb
@@ -38,12 +38,14 @@ module EnumerableSpecs
class Empty
include Enumerable
def each
+ self
end
end
class EmptyWithSize
include Enumerable
def each
+ self
end
def size
0
@@ -343,9 +345,6 @@ module EnumerableSpecs
end
end
- # Set is a core class since Ruby 3.2
- ruby_version_is '3.2' do
- class SetSubclass < Set
- end
+ class SetSubclass < Set
end
end # EnumerableSpecs utility classes
diff --git a/spec/ruby/core/enumerable/flat_map_spec.rb b/spec/ruby/core/enumerable/flat_map_spec.rb
index a294b9ddad..bd07eab6c5 100644
--- a/spec/ruby/core/enumerable/flat_map_spec.rb
+++ b/spec/ruby/core/enumerable/flat_map_spec.rb
@@ -3,5 +3,5 @@ require_relative 'fixtures/classes'
require_relative 'shared/collect_concat'
describe "Enumerable#flat_map" do
- it_behaves_like :enumerable_collect_concat , :flat_map
+ it_behaves_like :enumerable_collect_concat, :flat_map
end
diff --git a/spec/ruby/core/enumerable/map_spec.rb b/spec/ruby/core/enumerable/map_spec.rb
index d65aec238c..98a70781cf 100644
--- a/spec/ruby/core/enumerable/map_spec.rb
+++ b/spec/ruby/core/enumerable/map_spec.rb
@@ -3,5 +3,5 @@ require_relative 'fixtures/classes'
require_relative 'shared/collect'
describe "Enumerable#map" do
- it_behaves_like :enumerable_collect , :map
+ it_behaves_like :enumerable_collect, :map
end
diff --git a/spec/ruby/core/enumerable/select_spec.rb b/spec/ruby/core/enumerable/select_spec.rb
index 11168eb42e..7fc61926f9 100644
--- a/spec/ruby/core/enumerable/select_spec.rb
+++ b/spec/ruby/core/enumerable/select_spec.rb
@@ -3,5 +3,5 @@ require_relative 'fixtures/classes'
require_relative 'shared/find_all'
describe "Enumerable#select" do
- it_behaves_like :enumerable_find_all , :select
+ it_behaves_like :enumerable_find_all, :select
end
diff --git a/spec/ruby/core/enumerable/shared/inject.rb b/spec/ruby/core/enumerable/shared/inject.rb
index 693d34d675..8fb7e98c2b 100644
--- a/spec/ruby/core/enumerable/shared/inject.rb
+++ b/spec/ruby/core/enumerable/shared/inject.rb
@@ -16,6 +16,23 @@ describe :enumerable_inject, shared: true do
it "can take two argument" do
EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, :-).should == 4
+ EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, "-").should == 4
+
+ [1, 2, 3].send(@method, 10, :-).should == 4
+ [1, 2, 3].send(@method, 10, "-").should == 4
+ end
+
+ it "converts non-Symbol method name argument to String with #to_str if two arguments" do
+ name = Object.new
+ def name.to_str; "-"; end
+
+ EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, name).should == 4
+ [1, 2, 3].send(@method, 10, name).should == 4
+ end
+
+ it "raises TypeError when the second argument is not Symbol or String and it cannot be converted to String if two arguments" do
+ -> { EnumerableSpecs::Numerous.new(1, 2, 3).send(@method, 10, Object.new) }.should raise_error(TypeError, /is not a symbol nor a string/)
+ -> { [1, 2, 3].send(@method, 10, Object.new) }.should raise_error(TypeError, /is not a symbol nor a string/)
end
it "ignores the block if two arguments" do
@@ -39,6 +56,25 @@ describe :enumerable_inject, shared: true do
it "can take a symbol argument" do
EnumerableSpecs::Numerous.new(10, 1, 2, 3).send(@method, :-).should == 4
+ [10, 1, 2, 3].send(@method, :-).should == 4
+ end
+
+ it "can take a String argument" do
+ EnumerableSpecs::Numerous.new(10, 1, 2, 3).send(@method, "-").should == 4
+ [10, 1, 2, 3].send(@method, "-").should == 4
+ end
+
+ it "converts non-Symbol method name argument to String with #to_str" do
+ name = Object.new
+ def name.to_str; "-"; end
+
+ EnumerableSpecs::Numerous.new(10, 1, 2, 3).send(@method, name).should == 4
+ [10, 1, 2, 3].send(@method, name).should == 4
+ end
+
+ it "raises TypeError when passed not Symbol or String method name argument and it cannot be converted to String" do
+ -> { EnumerableSpecs::Numerous.new(10, 1, 2, 3).send(@method, Object.new) }.should raise_error(TypeError, /is not a symbol nor a string/)
+ -> { [10, 1, 2, 3].send(@method, Object.new) }.should raise_error(TypeError, /is not a symbol nor a string/)
end
it "without argument takes a block with an accumulator (with first element as initial value) and the current element. Value of block becomes new accumulator" do
@@ -67,7 +103,7 @@ describe :enumerable_inject, shared: true do
it "without inject arguments(legacy rubycon)" do
# no inject argument
- EnumerableSpecs::EachDefiner.new(2).send(@method) {|acc,x| 999 } .should == 2
+ EnumerableSpecs::EachDefiner.new(2).send(@method) {|acc,x| 999 }.should == 2
EnumerableSpecs::EachDefiner.new(2).send(@method) {|acc,x| acc }.should == 2
EnumerableSpecs::EachDefiner.new(2).send(@method) {|acc,x| x }.should == 2
@@ -77,7 +113,6 @@ describe :enumerable_inject, shared: true do
EnumerableSpecs::EachDefiner.new('a','b','c').send(@method) {|result, i| i+result}.should == "cba"
EnumerableSpecs::EachDefiner.new(3, 4, 5).send(@method) {|result, i| result*i}.should == 60
EnumerableSpecs::EachDefiner.new([1], 2, 'a','b').send(@method){|r,i| r<<i}.should == [1, 2, 'a', 'b']
-
end
it "returns nil when fails(legacy rubycon)" do
@@ -100,10 +135,8 @@ describe :enumerable_inject, shared: true do
actual.sort_by(&:to_s).should == expected.sort_by(&:to_s)
end
- ruby_bug '#18635', ''...'3.2' do
- it "raises an ArgumentError when no parameters or block is given" do
- -> { [1,2].send(@method) }.should raise_error(ArgumentError)
- -> { {one: 1, two: 2}.send(@method) }.should raise_error(ArgumentError)
- end
+ it "raises an ArgumentError when no parameters or block is given" do
+ -> { [1,2].send(@method) }.should raise_error(ArgumentError)
+ -> { {one: 1, two: 2}.send(@method) }.should raise_error(ArgumentError)
end
end
diff --git a/spec/ruby/core/enumerable/tally_spec.rb b/spec/ruby/core/enumerable/tally_spec.rb
index e0edc8dc75..95c64c1294 100644
--- a/spec/ruby/core/enumerable/tally_spec.rb
+++ b/spec/ruby/core/enumerable/tally_spec.rb
@@ -32,62 +32,60 @@ describe "Enumerable#tally" do
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 "calls #to_hash to convert argument to Hash implicitly if passed not a Hash" do
- enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz')
- object = Object.new
- def object.to_hash; { 'foo' => 1 }; end
- enum.tally(object).should == { 'foo' => 3, 'bar' => 1, 'baz' => 1}
- 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 "raises a FrozenError even if enumerable is empty" do
- enum = EnumerableSpecs::Numerous.new()
- hash = { 'foo' => 1 }.freeze
- -> { enum.tally(hash) }.should raise_error(FrozenError)
- 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
+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 "calls #to_hash to convert argument to Hash implicitly if passed not a Hash" do
+ enum = EnumerableSpecs::Numerous.new('foo', 'bar', 'foo', 'baz')
+ object = Object.new
+ def object.to_hash; { 'foo' => 1 }; end
+ enum.tally(object).should == { 'foo' => 3, 'bar' => 1, 'baz' => 1}
+ 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 "raises a FrozenError even if enumerable is empty" do
+ enum = EnumerableSpecs::Numerous.new()
+ hash = { 'foo' => 1 }.freeze
+ -> { enum.tally(hash) }.should raise_error(FrozenError)
+ 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
diff --git a/spec/ruby/core/enumerable/to_a_spec.rb b/spec/ruby/core/enumerable/to_a_spec.rb
index 0f3060dc48..723f922574 100644
--- a/spec/ruby/core/enumerable/to_a_spec.rb
+++ b/spec/ruby/core/enumerable/to_a_spec.rb
@@ -3,5 +3,5 @@ require_relative 'fixtures/classes'
require_relative 'shared/entries'
describe "Enumerable#to_a" do
- it_behaves_like :enumerable_entries , :to_a
+ it_behaves_like :enumerable_entries, :to_a
end
diff --git a/spec/ruby/core/enumerable/to_h_spec.rb b/spec/ruby/core/enumerable/to_h_spec.rb
index 0489134552..11a4933c10 100644
--- a/spec/ruby/core/enumerable/to_h_spec.rb
+++ b/spec/ruby/core/enumerable/to_h_spec.rb
@@ -53,6 +53,14 @@ describe "Enumerable#to_h" do
@enum.to_h { |k| [k, k.to_s] }.should == { a: 'a', b: 'b' }
end
+ it "passes to a block each element as a single argument" do
+ enum_of_arrays = EnumerableSpecs::EachDefiner.new([:a, 1], [:b, 2])
+
+ ScratchPad.record []
+ enum_of_arrays.to_h { |*args| ScratchPad << args; [args[0], args[1]] }
+ ScratchPad.recorded.sort.should == [[[:a, 1]], [[:b, 2]]]
+ end
+
it "raises ArgumentError if block returns longer or shorter array" do
-> do
@enum.to_h { |k| [k, k.to_s, 1] }
diff --git a/spec/ruby/core/enumerable/to_set_spec.rb b/spec/ruby/core/enumerable/to_set_spec.rb
index c21a2772c4..c02ead11fa 100644
--- a/spec/ruby/core/enumerable/to_set_spec.rb
+++ b/spec/ruby/core/enumerable/to_set_spec.rb
@@ -1,29 +1,30 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is "3.2" do
- describe "Enumerable#to_set" do
- it "returns a new Set created from self" do
- [1, 2, 3].to_set.should == Set[1, 2, 3]
- {a: 1, b: 2}.to_set.should == Set[[:b, 2], [:a, 1]]
- end
+describe "Enumerable#to_set" do
+ it "returns a new Set created from self" do
+ [1, 2, 3].to_set.should == Set[1, 2, 3]
+ {a: 1, b: 2}.to_set.should == Set[[:b, 2], [:a, 1]]
+ end
- it "passes down passed blocks" do
- [1, 2, 3].to_set { |x| x * x }.should == Set[1, 4, 9]
- end
+ it "passes down passed blocks" do
+ [1, 2, 3].to_set { |x| x * x }.should == Set[1, 4, 9]
+ end
+ ruby_version_is "4.0"..."4.1" do
it "instantiates an object of provided as the first argument set class" do
- set = [1, 2, 3].to_set(EnumerableSpecs::SetSubclass)
+ set = nil
+ proc{set = [1, 2, 3].to_set(EnumerableSpecs::SetSubclass)}.should complain(/Enumerable#to_set/)
set.should be_kind_of(EnumerableSpecs::SetSubclass)
set.to_a.sort.should == [1, 2, 3]
end
+ end
- it "does not need explicit `require 'set'`" do
- output = ruby_exe(<<~RUBY, options: '--disable-gems', args: '2>&1')
- puts [1, 2, 3].to_set
- RUBY
-
- output.chomp.should == "#<Set: {1, 2, 3}>"
+ ruby_version_is ""..."4.0" do
+ it "instantiates an object of provided as the first argument set class" do
+ set = [1, 2, 3].to_set(EnumerableSpecs::SetSubclass)
+ set.should be_kind_of(EnumerableSpecs::SetSubclass)
+ set.to_a.sort.should == [1, 2, 3]
end
end
end
diff --git a/spec/ruby/core/enumerator/each_with_index_spec.rb b/spec/ruby/core/enumerator/each_with_index_spec.rb
index 96e53a2804..4898e86fa9 100644
--- a/spec/ruby/core/enumerator/each_with_index_spec.rb
+++ b/spec/ruby/core/enumerator/each_with_index_spec.rb
@@ -1,5 +1,5 @@
require_relative '../../spec_helper'
-require_relative '../../shared/enumerator/with_index'
+require_relative 'shared/with_index'
require_relative '../enumerable/shared/enumeratorized'
describe "Enumerator#each_with_index" do
@@ -21,16 +21,16 @@ describe "Enumerator#each_with_index" do
it "passes on the given block's return value" do
arr = [1,2,3]
- arr.delete_if.with_index { |a,b| false }
+ arr.delete_if.each_with_index { |a,b| false }
arr.should == [1,2,3]
end
it "returns the iterator's return value" do
- [1,2,3].select.with_index { |a,b| false }.should == []
+ [1,2,3].select.each_with_index { |a,b| false }.should == []
+ [1,2,3].select.each_with_index { |a,b| true }.should == [1,2,3]
end
it "returns the correct value if chained with itself" do
[:a].each_with_index.each_with_index.to_a.should == [[[:a,0],0]]
- [:a].each.with_index.with_index.to_a.should == [[[:a,0],0]]
end
end
diff --git a/spec/ruby/core/enumerator/each_with_object_spec.rb b/spec/ruby/core/enumerator/each_with_object_spec.rb
index 68524dc74a..84a45ae89d 100644
--- a/spec/ruby/core/enumerator/each_with_object_spec.rb
+++ b/spec/ruby/core/enumerator/each_with_object_spec.rb
@@ -1,5 +1,5 @@
require_relative '../../spec_helper'
-require_relative '../../shared/enumerator/with_object'
+require_relative 'shared/with_object'
describe "Enumerator#each_with_object" do
it_behaves_like :enum_with_object, :each_with_object
diff --git a/spec/ruby/core/enumerator/enum_for_spec.rb b/spec/ruby/core/enumerator/enum_for_spec.rb
index fd33f463bf..fbdf98545a 100644
--- a/spec/ruby/core/enumerator/enum_for_spec.rb
+++ b/spec/ruby/core/enumerator/enum_for_spec.rb
@@ -1,5 +1,5 @@
require_relative '../../spec_helper'
-require_relative '../../shared/enumerator/enum_for'
+require_relative 'shared/enum_for'
describe "Enumerator#enum_for" do
it_behaves_like :enum_for, :enum_for
diff --git a/spec/ruby/fixtures/enumerator/classes.rb b/spec/ruby/core/enumerator/fixtures/classes.rb
index 6f285b8efa..6f285b8efa 100644
--- a/spec/ruby/fixtures/enumerator/classes.rb
+++ b/spec/ruby/core/enumerator/fixtures/classes.rb
diff --git a/spec/ruby/core/enumerator/lazy/compact_spec.rb b/spec/ruby/core/enumerator/lazy/compact_spec.rb
index e678bc71eb..65c544f062 100644
--- a/spec/ruby/core/enumerator/lazy/compact_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/compact_spec.rb
@@ -1,16 +1,14 @@
require_relative '../../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is '3.1' do
- describe "Enumerator::Lazy#compact" do
- it 'returns array without nil elements' do
- arr = [1, nil, 3, false, 5].to_enum.lazy.compact
- arr.should be_an_instance_of(Enumerator::Lazy)
- arr.force.should == [1, 3, false, 5]
- end
+describe "Enumerator::Lazy#compact" do
+ it 'returns array without nil elements' do
+ arr = [1, nil, 3, false, 5].to_enum.lazy.compact
+ arr.should be_an_instance_of(Enumerator::Lazy)
+ arr.force.should == [1, 3, false, 5]
+ end
- it "sets #size to nil" do
- Enumerator::Lazy.new(Object.new, 100) {}.compact.size.should == nil
- end
+ it "sets #size to nil" do
+ Enumerator::Lazy.new(Object.new, 100) {}.compact.size.should == nil
end
end
diff --git a/spec/ruby/core/enumerator/lazy/lazy_spec.rb b/spec/ruby/core/enumerator/lazy/lazy_spec.rb
index 0fb104e25a..b43864b673 100644
--- a/spec/ruby/core/enumerator/lazy/lazy_spec.rb
+++ b/spec/ruby/core/enumerator/lazy/lazy_spec.rb
@@ -9,16 +9,11 @@ describe "Enumerator::Lazy" do
it "defines lazy versions of a whitelist of Enumerator methods" do
lazy_methods = [
- :chunk, :collect, :collect_concat, :drop, :drop_while, :enum_for,
+ :chunk, :chunk_while, :collect, :collect_concat, :compact, :drop, :drop_while, :enum_for,
:find_all, :flat_map, :force, :grep, :grep_v, :lazy, :map, :reject,
:select, :slice_after, :slice_before, :slice_when, :take, :take_while,
- :to_enum, :zip
+ :to_enum, :uniq, :zip
]
- lazy_methods += [:chunk_while, :uniq]
-
- ruby_version_is '3.1' do
- lazy_methods += [:compact]
- end
Enumerator::Lazy.instance_methods(false).should include(*lazy_methods)
end
diff --git a/spec/ruby/core/enumerator/product/each_spec.rb b/spec/ruby/core/enumerator/product/each_spec.rb
index cabeb9d93a..88f115a712 100644
--- a/spec/ruby/core/enumerator/product/each_spec.rb
+++ b/spec/ruby/core/enumerator/product/each_spec.rb
@@ -1,73 +1,71 @@
require_relative '../../../spec_helper'
require_relative '../../enumerable/shared/enumeratorized'
-ruby_version_is "3.2" do
- describe "Enumerator::Product#each" do
- it_behaves_like :enumeratorized_with_origin_size, :each, Enumerator::Product.new([1, 2], [:a, :b])
+describe "Enumerator::Product#each" do
+ it_behaves_like :enumeratorized_with_origin_size, :each, Enumerator::Product.new([1, 2], [:a, :b])
- it "yields each element of Cartesian product of enumerators" do
- enum = Enumerator::Product.new([1, 2], [:a, :b])
- acc = []
- enum.each { |e| acc << e }
- acc.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
- end
-
- it "calls #each_entry method on enumerators" do
- object1 = Object.new
- def object1.each_entry
- yield 1
- yield 2
- end
-
- object2 = Object.new
- def object2.each_entry
- yield :a
- yield :b
- end
+ it "yields each element of Cartesian product of enumerators" do
+ enum = Enumerator::Product.new([1, 2], [:a, :b])
+ acc = []
+ enum.each { |e| acc << e }
+ acc.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
+ end
- enum = Enumerator::Product.new(object1, object2)
- acc = []
- enum.each { |e| acc << e }
- acc.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
+ it "calls #each_entry method on enumerators" do
+ object1 = Object.new
+ def object1.each_entry
+ yield 1
+ yield 2
end
- it "raises a NoMethodError if the object doesn't respond to #each_entry" do
- -> {
- Enumerator::Product.new(Object.new).each {}
- }.should raise_error(NoMethodError, /undefined method [`']each_entry' for/)
+ object2 = Object.new
+ def object2.each_entry
+ yield :a
+ yield :b
end
- it "returns enumerator if not given a block" do
- enum = Enumerator::Product.new([1, 2], [:a, :b])
- enum.each.should.kind_of?(Enumerator)
+ enum = Enumerator::Product.new(object1, object2)
+ acc = []
+ enum.each { |e| acc << e }
+ acc.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
+ end
- enum = Enumerator::Product.new([1, 2], [:a, :b])
- enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
- end
+ it "raises a NoMethodError if the object doesn't respond to #each_entry" do
+ -> {
+ Enumerator::Product.new(Object.new).each {}
+ }.should raise_error(NoMethodError, /undefined method [`']each_entry' for/)
+ end
- it "returns self if given a block" do
- enum = Enumerator::Product.new([1, 2], [:a, :b])
- enum.each {}.should.equal?(enum)
- end
+ it "returns enumerator if not given a block" do
+ enum = Enumerator::Product.new([1, 2], [:a, :b])
+ enum.each.should.kind_of?(Enumerator)
- it "doesn't accept arguments" do
- Enumerator::Product.instance_method(:each).arity.should == 0
- end
+ enum = Enumerator::Product.new([1, 2], [:a, :b])
+ enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
+ end
- it "yields each element to a block that takes multiple arguments" do
- enum = Enumerator::Product.new([1, 2], [:a, :b])
+ it "returns self if given a block" do
+ enum = Enumerator::Product.new([1, 2], [:a, :b])
+ enum.each {}.should.equal?(enum)
+ end
- acc = []
- enum.each { |x, y| acc << x }
- acc.should == [1, 1, 2, 2]
+ it "doesn't accept arguments" do
+ Enumerator::Product.instance_method(:each).arity.should == 0
+ end
- acc = []
- enum.each { |x, y| acc << y }
- acc.should == [:a, :b, :a, :b]
+ it "yields each element to a block that takes multiple arguments" do
+ enum = Enumerator::Product.new([1, 2], [:a, :b])
- acc = []
- enum.each { |x, y, z| acc << z }
- acc.should == [nil, nil, nil, nil]
- end
+ acc = []
+ enum.each { |x, y| acc << x }
+ acc.should == [1, 1, 2, 2]
+
+ acc = []
+ enum.each { |x, y| acc << y }
+ acc.should == [:a, :b, :a, :b]
+
+ acc = []
+ enum.each { |x, y, z| acc << z }
+ acc.should == [nil, nil, nil, nil]
end
end
diff --git a/spec/ruby/core/enumerator/product/initialize_copy_spec.rb b/spec/ruby/core/enumerator/product/initialize_copy_spec.rb
index 46e8421322..b1b9f3ca9b 100644
--- a/spec/ruby/core/enumerator/product/initialize_copy_spec.rb
+++ b/spec/ruby/core/enumerator/product/initialize_copy_spec.rb
@@ -1,54 +1,52 @@
require_relative '../../../spec_helper'
-ruby_version_is "3.2" do
- describe "Enumerator::Product#initialize_copy" do
- it "replaces content of the receiver with content of the other object" do
- enum = Enumerator::Product.new([true, false])
- enum2 = Enumerator::Product.new([1, 2], [:a, :b])
+describe "Enumerator::Product#initialize_copy" do
+ it "replaces content of the receiver with content of the other object" do
+ enum = Enumerator::Product.new([true, false])
+ enum2 = Enumerator::Product.new([1, 2], [:a, :b])
- enum.send(:initialize_copy, enum2)
- enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
- end
+ enum.send(:initialize_copy, enum2)
+ enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
+ end
- it "returns self" do
- enum = Enumerator::Product.new([true, false])
- enum2 = Enumerator::Product.new([1, 2], [:a, :b])
+ it "returns self" do
+ enum = Enumerator::Product.new([true, false])
+ enum2 = Enumerator::Product.new([1, 2], [:a, :b])
- enum.send(:initialize_copy, enum2).should.equal?(enum)
- end
+ enum.send(:initialize_copy, enum2).should.equal?(enum)
+ end
- it "is a private method" do
- Enumerator::Product.should have_private_instance_method(:initialize_copy, false)
- end
+ it "is a private method" do
+ Enumerator::Product.should have_private_instance_method(:initialize_copy, false)
+ end
- it "does nothing if the argument is the same as the receiver" do
- enum = Enumerator::Product.new(1..2)
- enum.send(:initialize_copy, enum).should.equal?(enum)
+ it "does nothing if the argument is the same as the receiver" do
+ enum = Enumerator::Product.new(1..2)
+ enum.send(:initialize_copy, enum).should.equal?(enum)
- enum.freeze
- enum.send(:initialize_copy, enum).should.equal?(enum)
- end
+ enum.freeze
+ enum.send(:initialize_copy, enum).should.equal?(enum)
+ end
- it "raises FrozenError if the receiver is frozen" do
- enum = Enumerator::Product.new(1..2)
- enum2 = Enumerator::Product.new(3..4)
+ it "raises FrozenError if the receiver is frozen" do
+ enum = Enumerator::Product.new(1..2)
+ enum2 = Enumerator::Product.new(3..4)
- -> { enum.freeze.send(:initialize_copy, enum2) }.should raise_error(FrozenError)
- end
+ -> { enum.freeze.send(:initialize_copy, enum2) }.should raise_error(FrozenError)
+ end
- it "raises TypeError if the objects are of different class" do
- enum = Enumerator::Product.new(1..2)
- enum2 = Class.new(Enumerator::Product).new(3..4)
+ it "raises TypeError if the objects are of different class" do
+ enum = Enumerator::Product.new(1..2)
+ enum2 = Class.new(Enumerator::Product).new(3..4)
- -> { enum.send(:initialize_copy, enum2) }.should raise_error(TypeError, 'initialize_copy should take same class object')
- -> { enum2.send(:initialize_copy, enum) }.should raise_error(TypeError, 'initialize_copy should take same class object')
- end
+ -> { enum.send(:initialize_copy, enum2) }.should raise_error(TypeError, 'initialize_copy should take same class object')
+ -> { enum2.send(:initialize_copy, enum) }.should raise_error(TypeError, 'initialize_copy should take same class object')
+ end
- it "raises ArgumentError if the argument is not initialized yet" do
- enum = Enumerator::Product.new(1..2)
- enum2 = Enumerator::Product.allocate
+ it "raises ArgumentError if the argument is not initialized yet" do
+ enum = Enumerator::Product.new(1..2)
+ enum2 = Enumerator::Product.allocate
- -> { enum.send(:initialize_copy, enum2) }.should raise_error(ArgumentError, 'uninitialized product')
- end
+ -> { enum.send(:initialize_copy, enum2) }.should raise_error(ArgumentError, 'uninitialized product')
end
end
diff --git a/spec/ruby/core/enumerator/product/initialize_spec.rb b/spec/ruby/core/enumerator/product/initialize_spec.rb
index 4b60564240..ed2a8a2a13 100644
--- a/spec/ruby/core/enumerator/product/initialize_spec.rb
+++ b/spec/ruby/core/enumerator/product/initialize_spec.rb
@@ -1,33 +1,31 @@
require_relative '../../../spec_helper'
-ruby_version_is "3.2" do
- describe "Enumerator::Product#initialize" do
- before :each do
- @uninitialized = Enumerator::Product.allocate
- end
+describe "Enumerator::Product#initialize" do
+ before :each do
+ @uninitialized = Enumerator::Product.allocate
+ end
- it "is a private method" do
- Enumerator::Product.should have_private_instance_method(:initialize, false)
- end
+ it "is a private method" do
+ Enumerator::Product.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_entry" do
- @uninitialized.send(:initialize, Object.new).should equal(@uninitialized)
- end
+ it "accepts arguments that are not Enumerable nor responding to :each_entry" do
+ @uninitialized.send(:initialize, Object.new).should equal(@uninitialized)
+ end
- describe "on frozen instance" do
- it "raises a FrozenError" do
- -> {
- @uninitialized.freeze.send(:initialize, 0..1)
- }.should raise_error(FrozenError)
- end
+ describe "on frozen instance" do
+ it "raises a FrozenError" do
+ -> {
+ @uninitialized.freeze.send(:initialize, 0..1)
+ }.should raise_error(FrozenError)
end
end
end
diff --git a/spec/ruby/core/enumerator/product/inspect_spec.rb b/spec/ruby/core/enumerator/product/inspect_spec.rb
index 1ea8e9c49b..e0d7441f26 100644
--- a/spec/ruby/core/enumerator/product/inspect_spec.rb
+++ b/spec/ruby/core/enumerator/product/inspect_spec.rb
@@ -1,22 +1,20 @@
require_relative '../../../spec_helper'
-ruby_version_is "3.2" do
- describe "Enumerator::Product#inspect" do
- it "returns a String including enumerators" do
- enum = Enumerator::Product.new([1, 2], [:a, :b])
- enum.inspect.should == "#<Enumerator::Product: [[1, 2], [:a, :b]]>"
- end
+describe "Enumerator::Product#inspect" do
+ it "returns a String including enumerators" do
+ enum = Enumerator::Product.new([1, 2], [:a, :b])
+ enum.inspect.should == "#<Enumerator::Product: [[1, 2], [:a, :b]]>"
+ end
- it "represents a recursive element with '[...]'" do
- enum = [1, 2]
- enum_recursive = Enumerator::Product.new(enum)
+ it "represents a recursive element with '[...]'" do
+ enum = [1, 2]
+ enum_recursive = Enumerator::Product.new(enum)
- enum << enum_recursive
- enum_recursive.inspect.should == "#<Enumerator::Product: [[1, 2, #<Enumerator::Product: ...>]]>"
- end
+ enum << enum_recursive
+ enum_recursive.inspect.should == "#<Enumerator::Product: [[1, 2, #<Enumerator::Product: ...>]]>"
+ end
- it "returns a not initialized representation if #initialized is not called yet" do
- Enumerator::Product.allocate.inspect.should == "#<Enumerator::Product: uninitialized>"
- end
+ it "returns a not initialized representation if #initialized is not called yet" do
+ Enumerator::Product.allocate.inspect.should == "#<Enumerator::Product: uninitialized>"
end
end
diff --git a/spec/ruby/core/enumerator/product/rewind_spec.rb b/spec/ruby/core/enumerator/product/rewind_spec.rb
index e8ee730239..2beffaf5c1 100644
--- a/spec/ruby/core/enumerator/product/rewind_spec.rb
+++ b/spec/ruby/core/enumerator/product/rewind_spec.rb
@@ -1,64 +1,62 @@
require_relative '../../../spec_helper'
-ruby_version_is "3.2" do
- describe "Enumerator::Product#rewind" do
- before :each do
- @enum = Enumerator::Product.new([1, 2].each.to_enum, [:a, :b].each.to_enum)
- end
+describe "Enumerator::Product#rewind" do
+ before :each do
+ @enum = Enumerator::Product.new([1, 2].each.to_enum, [:a, :b].each.to_enum)
+ end
- it "resets the enumerator to its initial state" do
- @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
- @enum.rewind
- @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
- end
+ it "resets the enumerator to its initial state" do
+ @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
+ @enum.rewind
+ @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
+ end
- it "returns self" do
- @enum.rewind.should.equal? @enum
- end
+ it "returns self" do
+ @enum.rewind.should.equal? @enum
+ end
- it "has no effect on a new enumerator" do
- @enum.rewind
- @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
- end
+ it "has no effect on a new enumerator" do
+ @enum.rewind
+ @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
+ end
- it "has no effect if called multiple, consecutive times" do
- @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
- @enum.rewind
- @enum.rewind
- @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
- end
+ it "has no effect if called multiple, consecutive times" do
+ @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
+ @enum.rewind
+ @enum.rewind
+ @enum.each.to_a.should == [[1, :a], [1, :b], [2, :a], [2, :b]]
+ end
- it "calls the enclosed object's rewind method if one exists" do
- obj = mock('rewinder')
- enum = Enumerator::Product.new(obj.to_enum)
+ it "calls the enclosed object's rewind method if one exists" do
+ obj = mock('rewinder')
+ enum = Enumerator::Product.new(obj.to_enum)
- obj.should_receive(:rewind)
- enum.rewind
- end
+ obj.should_receive(:rewind)
+ enum.rewind
+ end
- it "does nothing if the object doesn't have a #rewind method" do
- obj = mock('rewinder')
- enum = Enumerator::Product.new(obj.to_enum)
+ it "does nothing if the object doesn't have a #rewind method" do
+ obj = mock('rewinder')
+ enum = Enumerator::Product.new(obj.to_enum)
- enum.rewind.should == enum
- end
+ enum.rewind.should == enum
+ end
- it "calls a rewind method on each enumerable in direct order" do
- ScratchPad.record []
+ it "calls a rewind method on each enumerable in direct order" do
+ ScratchPad.record []
- object1 = Object.new
- def object1.rewind; ScratchPad << :object1; end
+ object1 = Object.new
+ def object1.rewind; ScratchPad << :object1; end
- object2 = Object.new
- def object2.rewind; ScratchPad << :object2; end
+ object2 = Object.new
+ def object2.rewind; ScratchPad << :object2; end
- object3 = Object.new
- def object3.rewind; ScratchPad << :object3; end
+ object3 = Object.new
+ def object3.rewind; ScratchPad << :object3; end
- enum = Enumerator::Product.new(object1, object2, object3)
- enum.rewind
+ enum = Enumerator::Product.new(object1, object2, object3)
+ enum.rewind
- ScratchPad.recorded.should == [:object1, :object2, :object3]
- end
+ ScratchPad.recorded.should == [:object1, :object2, :object3]
end
end
diff --git a/spec/ruby/core/enumerator/product/size_spec.rb b/spec/ruby/core/enumerator/product/size_spec.rb
index 46958b1a22..96632d6eee 100644
--- a/spec/ruby/core/enumerator/product/size_spec.rb
+++ b/spec/ruby/core/enumerator/product/size_spec.rb
@@ -1,56 +1,54 @@
require_relative '../../../spec_helper'
-ruby_version_is "3.2" do
- describe "Enumerator::Product#size" do
- it "returns the total size of the enumerator product calculated by multiplying the sizes of enumerables in the product" do
- product = Enumerator::Product.new(1..2, 1..3, 1..4)
- product.size.should == 24 # 2 * 3 * 4
- end
-
- it "returns nil if any enumerable reports its size as nil" do
- enum = Object.new
- def enum.size; nil; end
-
- product = Enumerator::Product.new(1..2, enum)
- product.size.should == nil
- end
-
- it "returns Float::INFINITY if any enumerable reports its size as Float::INFINITY" do
- enum = Object.new
- def enum.size; Float::INFINITY; end
-
- product = Enumerator::Product.new(1..2, enum)
- product.size.should == Float::INFINITY
- end
-
- it "returns nil if any enumerable reports its size as Float::NAN" do
- enum = Object.new
- def enum.size; Float::NAN; end
-
- product = Enumerator::Product.new(1..2, enum)
- product.size.should == nil
- end
-
- it "returns nil if any enumerable doesn't respond to #size" do
- enum = Object.new
- product = Enumerator::Product.new(1..2, enum)
- product.size.should == nil
- end
-
- it "returns nil if any enumerable reports a not-convertible to Integer" do
- enum = Object.new
- def enum.size; :symbol; end
-
- product = Enumerator::Product.new(1..2, enum)
- product.size.should == nil
- end
-
- it "returns nil if any enumerable reports a non-Integer but convertible to Integer size" do
- enum = Object.new
- def enum.size; 1.0; end
-
- product = Enumerator::Product.new(1..2, enum)
- product.size.should == nil
- end
+describe "Enumerator::Product#size" do
+ it "returns the total size of the enumerator product calculated by multiplying the sizes of enumerables in the product" do
+ product = Enumerator::Product.new(1..2, 1..3, 1..4)
+ product.size.should == 24 # 2 * 3 * 4
+ end
+
+ it "returns nil if any enumerable reports its size as nil" do
+ enum = Object.new
+ def enum.size; nil; end
+
+ product = Enumerator::Product.new(1..2, enum)
+ product.size.should == nil
+ end
+
+ it "returns Float::INFINITY if any enumerable reports its size as Float::INFINITY" do
+ enum = Object.new
+ def enum.size; Float::INFINITY; end
+
+ product = Enumerator::Product.new(1..2, enum)
+ product.size.should == Float::INFINITY
+ end
+
+ it "returns nil if any enumerable reports its size as Float::NAN" do
+ enum = Object.new
+ def enum.size; Float::NAN; end
+
+ product = Enumerator::Product.new(1..2, enum)
+ product.size.should == nil
+ end
+
+ it "returns nil if any enumerable doesn't respond to #size" do
+ enum = Object.new
+ product = Enumerator::Product.new(1..2, enum)
+ product.size.should == nil
+ end
+
+ it "returns nil if any enumerable reports a not-convertible to Integer" do
+ enum = Object.new
+ def enum.size; :symbol; end
+
+ product = Enumerator::Product.new(1..2, enum)
+ product.size.should == nil
+ end
+
+ it "returns nil if any enumerable reports a non-Integer but convertible to Integer size" do
+ enum = Object.new
+ def enum.size; 1.0; end
+
+ product = Enumerator::Product.new(1..2, enum)
+ product.size.should == nil
end
end
diff --git a/spec/ruby/core/enumerator/product_spec.rb b/spec/ruby/core/enumerator/product_spec.rb
index 0acca6690e..83c7cb8e0e 100644
--- a/spec/ruby/core/enumerator/product_spec.rb
+++ b/spec/ruby/core/enumerator/product_spec.rb
@@ -1,93 +1,91 @@
require_relative '../../spec_helper'
-ruby_version_is "3.2" do
- describe "Enumerator.product" do
- it "returns a Cartesian product of enumerators" do
- enum = Enumerator.product(1..2, ["A", "B"])
- enum.to_a.should == [[1, "A"], [1, "B"], [2, "A"], [2, "B"]]
- end
-
- it "accepts a list of enumerators of any length" do
- enum = Enumerator.product(1..2)
- enum.to_a.should == [[1], [2]]
+describe "Enumerator.product" do
+ it "returns a Cartesian product of enumerators" do
+ enum = Enumerator.product(1..2, ["A", "B"])
+ enum.to_a.should == [[1, "A"], [1, "B"], [2, "A"], [2, "B"]]
+ end
- enum = Enumerator.product(1..2, ["A"])
- enum.to_a.should == [[1, "A"], [2, "A"]]
+ it "accepts a list of enumerators of any length" do
+ enum = Enumerator.product(1..2)
+ enum.to_a.should == [[1], [2]]
- enum = Enumerator.product(1..2, ["A"], ["B"])
- enum.to_a.should == [[1, "A", "B"], [2, "A", "B"]]
+ enum = Enumerator.product(1..2, ["A"])
+ enum.to_a.should == [[1, "A"], [2, "A"]]
- enum = Enumerator.product(2..3, ["A"], ["B"], ["C"])
- enum.to_a.should == [[2, "A", "B", "C"], [3, "A", "B", "C"]]
- end
+ enum = Enumerator.product(1..2, ["A"], ["B"])
+ enum.to_a.should == [[1, "A", "B"], [2, "A", "B"]]
- it "returns an enumerator with an empty array when no arguments passed" do
- enum = Enumerator.product
- enum.to_a.should == [[]]
- end
+ enum = Enumerator.product(2..3, ["A"], ["B"], ["C"])
+ enum.to_a.should == [[2, "A", "B", "C"], [3, "A", "B", "C"]]
+ end
- it "returns an instance of Enumerator::Product" do
- enum = Enumerator.product
- enum.class.should == Enumerator::Product
- end
+ it "returns an enumerator with an empty array when no arguments passed" do
+ enum = Enumerator.product
+ enum.to_a.should == [[]]
+ end
- it "accepts infinite enumerators and returns infinite enumerator" do
- enum = Enumerator.product(1.., ["A", "B"])
- enum.take(5).should == [[1, "A"], [1, "B"], [2, "A"], [2, "B"], [3, "A"]]
- enum.size.should == Float::INFINITY
- end
+ it "returns an instance of Enumerator::Product" do
+ enum = Enumerator.product
+ enum.class.should == Enumerator::Product
+ end
- it "accepts a block" do
- elems = []
- enum = Enumerator.product(1..2, ["X", "Y"]) { elems << _1 }
+ it "accepts infinite enumerators and returns infinite enumerator" do
+ enum = Enumerator.product(1.., ["A", "B"])
+ enum.take(5).should == [[1, "A"], [1, "B"], [2, "A"], [2, "B"], [3, "A"]]
+ enum.size.should == Float::INFINITY
+ end
- elems.should == [[1, "X"], [1, "Y"], [2, "X"], [2, "Y"]]
- end
+ it "accepts a block" do
+ elems = []
+ enum = Enumerator.product(1..2, ["X", "Y"]) { elems << _1 }
- it "returns nil when a block passed" do
- Enumerator.product(1..2) {}.should == nil
- end
+ elems.should == [[1, "X"], [1, "Y"], [2, "X"], [2, "Y"]]
+ end
- # https://bugs.ruby-lang.org/issues/19829
- it "reject keyword arguments" do
- -> {
- Enumerator.product(1..3, foo: 1, bar: 2)
- }.should raise_error(ArgumentError, "unknown keywords: :foo, :bar")
- end
+ it "returns nil when a block passed" do
+ Enumerator.product(1..2) {}.should == nil
+ end
- it "calls only #each_entry method on arguments" do
- object = Object.new
- def object.each_entry
- yield 1
- yield 2
- end
+ # https://bugs.ruby-lang.org/issues/19829
+ it "reject keyword arguments" do
+ -> {
+ Enumerator.product(1..3, foo: 1, bar: 2)
+ }.should raise_error(ArgumentError, "unknown keywords: :foo, :bar")
+ end
- enum = Enumerator.product(object, ["A", "B"])
- enum.to_a.should == [[1, "A"], [1, "B"], [2, "A"], [2, "B"]]
+ it "calls only #each_entry method on arguments" do
+ object = Object.new
+ def object.each_entry
+ yield 1
+ yield 2
end
- it "raises NoMethodError when argument doesn't respond to #each_entry" do
- -> {
- Enumerator.product(Object.new).to_a
- }.should raise_error(NoMethodError, /undefined method [`']each_entry' for/)
- end
+ enum = Enumerator.product(object, ["A", "B"])
+ enum.to_a.should == [[1, "A"], [1, "B"], [2, "A"], [2, "B"]]
+ end
- it "calls #each_entry lazily" do
- Enumerator.product(Object.new).should be_kind_of(Enumerator)
- end
+ it "raises NoMethodError when argument doesn't respond to #each_entry" do
+ -> {
+ Enumerator.product(Object.new).to_a
+ }.should raise_error(NoMethodError, /undefined method [`']each_entry' for/)
+ end
+
+ it "calls #each_entry lazily" do
+ Enumerator.product(Object.new).should be_kind_of(Enumerator)
+ end
- it "iterates through consuming enumerator elements only once" do
- a = [1, 2, 3]
- i = 0
+ it "iterates through consuming enumerator elements only once" do
+ a = [1, 2, 3]
+ i = 0
- enum = Enumerator.new do |y|
- while i < a.size
- y << a[i]
- i += 1
- end
+ enum = Enumerator.new do |y|
+ while i < a.size
+ y << a[i]
+ i += 1
end
-
- Enumerator.product(['a', 'b'], enum).to_a.should == [["a", 1], ["a", 2], ["a", 3]]
end
+
+ Enumerator.product(['a', 'b'], enum).to_a.should == [["a", 1], ["a", 2], ["a", 3]]
end
end
diff --git a/spec/ruby/shared/enumerator/enum_for.rb b/spec/ruby/core/enumerator/shared/enum_for.rb
index a67a76c461..a67a76c461 100644
--- a/spec/ruby/shared/enumerator/enum_for.rb
+++ b/spec/ruby/core/enumerator/shared/enum_for.rb
diff --git a/spec/ruby/core/enumerator/shared/with_index.rb b/spec/ruby/core/enumerator/shared/with_index.rb
new file mode 100644
index 0000000000..78771ffe82
--- /dev/null
+++ b/spec/ruby/core/enumerator/shared/with_index.rb
@@ -0,0 +1,33 @@
+require_relative '../../../spec_helper'
+
+describe :enum_with_index, shared: true do
+
+ require_relative '../fixtures/classes'
+
+ before :each do
+ @origin = [1, 2, 3, 4]
+ @enum = @origin.to_enum
+ end
+
+ it "passes each element and its index to block" do
+ a = []
+ @enum.send(@method) { |o, i| a << [o, i] }
+ a.should == [[1, 0], [2, 1], [3, 2], [4, 3]]
+ end
+
+ it "returns the object being enumerated when given a block" do
+ @enum.send(@method) { |o, i| :glark }.should equal(@origin)
+ end
+
+ it "binds splat arguments properly" do
+ acc = []
+ @enum.send(@method) { |*b| c,d = b; acc << c; acc << d }
+ [1, 0, 2, 1, 3, 2, 4, 3].should == acc
+ end
+
+ it "returns an enumerator if no block is supplied" do
+ ewi = @enum.send(@method)
+ ewi.should be_an_instance_of(Enumerator)
+ ewi.to_a.should == [[1, 0], [2, 1], [3, 2], [4, 3]]
+ end
+end
diff --git a/spec/ruby/core/enumerator/shared/with_object.rb b/spec/ruby/core/enumerator/shared/with_object.rb
new file mode 100644
index 0000000000..d8e9d8e9f7
--- /dev/null
+++ b/spec/ruby/core/enumerator/shared/with_object.rb
@@ -0,0 +1,42 @@
+require_relative '../../../spec_helper'
+
+describe :enum_with_object, shared: true do
+ before :each do
+ @enum = [:a, :b].to_enum
+ @memo = ''
+ @block_params = @enum.send(@method, @memo).to_a
+ end
+
+ it "receives an argument" do
+ @enum.method(@method).arity.should == 1
+ end
+
+ context "with block" do
+ it "returns the given object" do
+ ret = @enum.send(@method, @memo) do |elm, memo|
+ # nothing
+ end
+ ret.should equal(@memo)
+ end
+
+ context "the block parameter" do
+ it "passes each element to first parameter" do
+ @block_params[0][0].should equal(:a)
+ @block_params[1][0].should equal(:b)
+ end
+
+ it "passes the given object to last parameter" do
+ @block_params[0][1].should equal(@memo)
+ @block_params[1][1].should equal(@memo)
+ end
+ end
+ end
+
+ context "without block" do
+ it "returns new Enumerator" do
+ ret = @enum.send(@method, @memo)
+ ret.should be_an_instance_of(Enumerator)
+ ret.should_not equal(@enum)
+ end
+ end
+end
diff --git a/spec/ruby/core/enumerator/to_enum_spec.rb b/spec/ruby/core/enumerator/to_enum_spec.rb
index cadfcf6314..7fb73d0c3c 100644
--- a/spec/ruby/core/enumerator/to_enum_spec.rb
+++ b/spec/ruby/core/enumerator/to_enum_spec.rb
@@ -1,6 +1,6 @@
require_relative '../../spec_helper'
-require_relative '../../shared/enumerator/enum_for'
+require_relative 'shared/enum_for'
describe "Enumerator#to_enum" do
- it_behaves_like :enum_for, :enum_for
+ it_behaves_like :enum_for, :to_enum
end
diff --git a/spec/ruby/core/enumerator/with_index_spec.rb b/spec/ruby/core/enumerator/with_index_spec.rb
index ac37cee508..e49aa7a939 100644
--- a/spec/ruby/core/enumerator/with_index_spec.rb
+++ b/spec/ruby/core/enumerator/with_index_spec.rb
@@ -1,5 +1,5 @@
require_relative '../../spec_helper'
-require_relative '../../shared/enumerator/with_index'
+require_relative 'shared/with_index'
require_relative '../enumerable/shared/enumeratorized'
describe "Enumerator#with_index" do
@@ -69,4 +69,21 @@ describe "Enumerator#with_index" do
@enum.with_index(-1) { |*x| res << x}
res.should == [[1,-1], [2,0], [3,1], [4,2]]
end
+
+ it "passes on the given block's return value" do
+ arr = [1,2,3]
+ arr.delete_if.with_index { |a,b| false }
+ arr.should == [1,2,3]
+
+ arr.delete_if.with_index { |a,b| true }
+ arr.should == []
+ end
+
+ it "returns the iterator's return value" do
+ @enum.select.with_index { |a,b| false }.should == []
+ end
+
+ it "returns the correct value if chained with itself" do
+ [:a].each.with_index.with_index.to_a.should == [[[:a,0],0]]
+ end
end
diff --git a/spec/ruby/core/enumerator/with_object_spec.rb b/spec/ruby/core/enumerator/with_object_spec.rb
index e7ba83fd9f..58031fd765 100644
--- a/spec/ruby/core/enumerator/with_object_spec.rb
+++ b/spec/ruby/core/enumerator/with_object_spec.rb
@@ -1,5 +1,5 @@
require_relative '../../spec_helper'
-require_relative '../../shared/enumerator/with_object'
+require_relative 'shared/with_object'
describe "Enumerator#with_object" do
it_behaves_like :enum_with_object, :with_object
diff --git a/spec/ruby/core/env/clone_spec.rb b/spec/ruby/core/env/clone_spec.rb
index 991e4e6774..01a29c6ab4 100644
--- a/spec/ruby/core/env/clone_spec.rb
+++ b/spec/ruby/core/env/clone_spec.rb
@@ -13,11 +13,9 @@ describe "ENV#clone" do
}.should raise_error(ArgumentError)
end
- ruby_version_is "3.2" do
- it "raises TypeError" do
- -> {
- ENV.clone
- }.should raise_error(TypeError, /Cannot clone ENV, use ENV.to_h to get a copy of ENV as a hash/)
- end
+ it "raises TypeError" do
+ -> {
+ ENV.clone
+ }.should raise_error(TypeError, /Cannot clone ENV, use ENV.to_h to get a copy of ENV as a hash/)
end
end
diff --git a/spec/ruby/core/env/dup_spec.rb b/spec/ruby/core/env/dup_spec.rb
index 46d125aca8..ac66b455cd 100644
--- a/spec/ruby/core/env/dup_spec.rb
+++ b/spec/ruby/core/env/dup_spec.rb
@@ -1,11 +1,9 @@
require_relative '../../spec_helper'
describe "ENV#dup" do
- ruby_version_is "3.1" do
- it "raises TypeError" do
- -> {
- ENV.dup
- }.should raise_error(TypeError, /Cannot dup ENV, use ENV.to_h to get a copy of ENV as a hash/)
- end
+ it "raises TypeError" do
+ -> {
+ ENV.dup
+ }.should raise_error(TypeError, /Cannot dup ENV, use ENV.to_h to get a copy of ENV as a hash/)
end
end
diff --git a/spec/ruby/core/env/element_reference_spec.rb b/spec/ruby/core/env/element_reference_spec.rb
index 560c127a9c..66a9bc9690 100644
--- a/spec/ruby/core/env/element_reference_spec.rb
+++ b/spec/ruby/core/env/element_reference_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
require_relative 'fixtures/common'
diff --git a/spec/ruby/core/env/fetch_spec.rb b/spec/ruby/core/env/fetch_spec.rb
index b2e7a88cab..2c5d7cc3a0 100644
--- a/spec/ruby/core/env/fetch_spec.rb
+++ b/spec/ruby/core/env/fetch_spec.rb
@@ -47,7 +47,7 @@ describe "ENV.fetch" do
it "warns on block and default parameter given" do
-> do
- ENV.fetch("foo", "default") { "bar" }.should == "bar"
+ ENV.fetch("foo", "default") { "bar" }.should == "bar"
end.should complain(/block supersedes default value argument/)
end
diff --git a/spec/ruby/core/env/inspect_spec.rb b/spec/ruby/core/env/inspect_spec.rb
index 3c611c24a1..7dd92b120f 100644
--- a/spec/ruby/core/env/inspect_spec.rb
+++ b/spec/ruby/core/env/inspect_spec.rb
@@ -4,7 +4,7 @@ describe "ENV.inspect" do
it "returns a String that looks like a Hash with real data" do
ENV["foo"] = "bar"
- ENV.inspect.should =~ /\{.*"foo"=>"bar".*\}/
+ ENV.inspect.should =~ /\{.*"foo" *=> *"bar".*\}/
ENV.delete "foo"
end
diff --git a/spec/ruby/core/env/length_spec.rb b/spec/ruby/core/env/length_spec.rb
index 536af9edf5..c6f9062892 100644
--- a/spec/ruby/core/env/length_spec.rb
+++ b/spec/ruby/core/env/length_spec.rb
@@ -2,5 +2,5 @@ require_relative '../../spec_helper'
require_relative 'shared/length'
describe "ENV.length" do
- it_behaves_like :env_length, :length
+ it_behaves_like :env_length, :length
end
diff --git a/spec/ruby/core/env/shared/update.rb b/spec/ruby/core/env/shared/update.rb
index 7d4799955b..e1b1c9c290 100644
--- a/spec/ruby/core/env/shared/update.rb
+++ b/spec/ruby/core/env/shared/update.rb
@@ -15,12 +15,10 @@ describe :env_update, shared: true do
ENV["bar"].should == "1"
end
- ruby_version_is "3.2" do
- it "adds the multiple parameter hashes to ENV, returning ENV" do
- ENV.send(@method, {"foo" => "multi1"}, {"bar" => "multi2"}).should equal(ENV)
- ENV["foo"].should == "multi1"
- ENV["bar"].should == "multi2"
- end
+ it "adds the multiple parameter hashes to ENV, returning ENV" do
+ ENV.send(@method, {"foo" => "multi1"}, {"bar" => "multi2"}).should equal(ENV)
+ ENV["foo"].should == "multi1"
+ ENV["bar"].should == "multi2"
end
it "returns ENV when no block given" do
diff --git a/spec/ruby/core/env/size_spec.rb b/spec/ruby/core/env/size_spec.rb
index f050e9e5a9..7c8072481e 100644
--- a/spec/ruby/core/env/size_spec.rb
+++ b/spec/ruby/core/env/size_spec.rb
@@ -2,5 +2,5 @@ require_relative '../../spec_helper'
require_relative 'shared/length'
describe "ENV.size" do
- it_behaves_like :env_length, :size
+ it_behaves_like :env_length, :size
end
diff --git a/spec/ruby/core/env/to_h_spec.rb b/spec/ruby/core/env/to_h_spec.rb
index 3c4a92aa57..58ea2d2030 100644
--- a/spec/ruby/core/env/to_h_spec.rb
+++ b/spec/ruby/core/env/to_h_spec.rb
@@ -18,6 +18,18 @@ describe "ENV.to_h" do
ENV.to_h { |k, v| [k, v.upcase] }.should == { 'a' => "B", 'c' => "D" }
end
+ it "passes to a block each pair's key and value as separate arguments" do
+ ENV.replace("a" => "b", "c" => "d")
+
+ ScratchPad.record []
+ ENV.to_h { |k, v| ScratchPad << [k, v]; [k, v] }
+ ScratchPad.recorded.sort.should == [["a", "b"], ["c", "d"]]
+
+ ScratchPad.record []
+ ENV.to_h { |*args| ScratchPad << args; [args[0], args[1]] }
+ ScratchPad.recorded.sort.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 }
diff --git a/spec/ruby/core/exception/detailed_message_spec.rb b/spec/ruby/core/exception/detailed_message_spec.rb
index fbe4443daa..9df164a1cf 100644
--- a/spec/ruby/core/exception/detailed_message_spec.rb
+++ b/spec/ruby/core/exception/detailed_message_spec.rb
@@ -2,42 +2,49 @@ require_relative '../../spec_helper'
require_relative 'fixtures/common'
describe "Exception#detailed_message" do
- ruby_version_is "3.2" do
- it "returns decorated message" do
- RuntimeError.new("new error").detailed_message.should == "new error (RuntimeError)"
- end
+ it "returns decorated message" do
+ RuntimeError.new("new error").detailed_message.should == "new error (RuntimeError)"
+ end
- it "is called by #full_message to allow message customization" do
- exception = Exception.new("new error")
- def exception.detailed_message(**)
- "<prefix>#{message}<suffix>"
- end
- exception.full_message(highlight: false).should.include? "<prefix>new error<suffix>"
+ it "is called by #full_message to allow message customization" do
+ exception = Exception.new("new error")
+ def exception.detailed_message(**)
+ "<prefix>#{message}<suffix>"
end
+ exception.full_message(highlight: false).should.include? "<prefix>new error<suffix>"
+ end
- it "accepts highlight keyword argument and adds escape control sequences" do
- RuntimeError.new("new error").detailed_message(highlight: true).should == "\e[1mnew error (\e[1;4mRuntimeError\e[m\e[1m)\e[m"
- end
+ it "returns just a message if exception class is anonymous" do
+ Class.new(RuntimeError).new("message").detailed_message.should == "message"
+ end
- it "allows and ignores other keyword arguments" do
- RuntimeError.new("new error").detailed_message(foo: true).should == "new error (RuntimeError)"
- end
+ it "returns 'unhandled exception' for an instance of RuntimeError with empty message" do
+ RuntimeError.new("").detailed_message.should == "unhandled exception"
+ end
- it "returns just a message if exception class is anonymous" do
- Class.new(RuntimeError).new("message").detailed_message.should == "message"
- end
+ it "returns just class name for an instance other than RuntimeError with empty message" do
+ DetailedMessageSpec::C.new("").detailed_message.should == "DetailedMessageSpec::C"
+ StandardError.new("").detailed_message.should == "StandardError"
+ end
- it "returns 'unhandled exception' for an instance of RuntimeError with empty message" do
- RuntimeError.new("").detailed_message.should == "unhandled exception"
- end
+ it "returns a generated class name for an instance of RuntimeError anonymous subclass with empty message" do
+ klass = Class.new(RuntimeError)
+ klass.new("").detailed_message.should =~ /\A#<Class:0x\h+>\z/
+ end
- it "returns just class name for an instance of RuntimeError subclass with empty message" do
- DetailedMessageSpec::C.new("").detailed_message.should == "DetailedMessageSpec::C"
- end
+ it "accepts highlight keyword argument and adds escape control sequences" do
+ RuntimeError.new("new error").detailed_message(highlight: true).should == "\e[1mnew error (\e[1;4mRuntimeError\e[m\e[1m)\e[m"
+ end
- it "returns a generated class name for an instance of RuntimeError anonymous subclass with empty message" do
- klass = Class.new(RuntimeError)
- klass.new("").detailed_message.should =~ /\A#<Class:0x\h+>\z/
- end
+ it "accepts highlight keyword argument and adds escape control sequences for an instance of RuntimeError with empty message" do
+ RuntimeError.new("").detailed_message(highlight: true).should == "\e[1;4munhandled exception\e[m"
+ end
+
+ it "accepts highlight keyword argument and adds escape control sequences for an instance other than RuntimeError with empty message" do
+ StandardError.new("").detailed_message(highlight: true).should == "\e[1;4mStandardError\e[m"
+ end
+
+ it "allows and ignores other keyword arguments" do
+ RuntimeError.new("new error").detailed_message(foo: true).should == "new error (RuntimeError)"
end
end
diff --git a/spec/ruby/core/exception/errno_spec.rb b/spec/ruby/core/exception/errno_spec.rb
index a063e522ea..1ab4277700 100644
--- a/spec/ruby/core/exception/errno_spec.rb
+++ b/spec/ruby/core/exception/errno_spec.rb
@@ -29,6 +29,8 @@ describe "Errno::EMFILE" do
ExceptionSpecs::EMFILESub = Class.new(Errno::EMFILE)
exc = ExceptionSpecs::EMFILESub.new
exc.should be_an_instance_of(ExceptionSpecs::EMFILESub)
+ ensure
+ ExceptionSpecs.send(:remove_const, :EMFILESub)
end
end
diff --git a/spec/ruby/core/exception/fixtures/common.rb b/spec/ruby/core/exception/fixtures/common.rb
index 1e243098bd..3d8a3c3430 100644
--- a/spec/ruby/core/exception/fixtures/common.rb
+++ b/spec/ruby/core/exception/fixtures/common.rb
@@ -84,6 +84,9 @@ module NoMethodErrorSpecs
class InstanceException < Exception
end
+
+ class AClass; end
+ module AModule; end
end
class NameErrorSpecs
diff --git a/spec/ruby/core/exception/frozen_error_spec.rb b/spec/ruby/core/exception/frozen_error_spec.rb
index 979ec2ff98..af2e925661 100644
--- a/spec/ruby/core/exception/frozen_error_spec.rb
+++ b/spec/ruby/core/exception/frozen_error_spec.rb
@@ -21,6 +21,22 @@ describe "FrozenError#receiver" do
end
end
+describe "FrozenError#message" do
+ it "includes a receiver" do
+ object = Object.new
+ object.freeze
+
+ msg_class = ruby_version_is("4.0") ? "Object" : "object"
+
+ -> {
+ def object.x; end
+ }.should raise_error(FrozenError, "can't modify frozen #{msg_class}: #{object}")
+
+ object = [].freeze
+ -> { object << nil }.should raise_error(FrozenError, "can't modify frozen Array: []")
+ end
+end
+
describe "Modifying a frozen object" do
context "#inspect is redefined and modifies the object" do
it "returns ... instead of String representation of object" do
diff --git a/spec/ruby/core/exception/full_message_spec.rb b/spec/ruby/core/exception/full_message_spec.rb
index 5154354555..0761d2b40c 100644
--- a/spec/ruby/core/exception/full_message_spec.rb
+++ b/spec/ruby/core/exception/full_message_spec.rb
@@ -79,6 +79,24 @@ describe "Exception#full_message" do
err.full_message(highlight: true).should !~ /unhandled exception/
err.full_message(highlight: false).should !~ /unhandled exception/
end
+
+ it "adds escape sequences to highlight some strings if the message is not specified and :highlight option is specified" do
+ e = RuntimeError.new("")
+
+ full_message = e.full_message(highlight: true, order: :top).lines
+ full_message[0].should.end_with? "\e[1;4munhandled exception\e[m\n"
+
+ full_message = e.full_message(highlight: true, order: :bottom).lines
+ full_message[0].should == "\e[1mTraceback\e[m (most recent call last):\n"
+ full_message[-1].should.end_with? "\e[1;4munhandled exception\e[m\n"
+
+ full_message = e.full_message(highlight: false, order: :top).lines
+ full_message[0].should.end_with? "unhandled exception\n"
+
+ full_message = e.full_message(highlight: false, order: :bottom).lines
+ full_message[0].should == "Traceback (most recent call last):\n"
+ full_message[-1].should.end_with? "unhandled exception\n"
+ end
end
describe "generic Error" do
@@ -147,52 +165,62 @@ describe "Exception#full_message" do
exception.full_message.should include "origin exception"
end
- ruby_version_is "3.2" do
- it "relies on #detailed_message" do
- e = RuntimeError.new("new error")
- e.define_singleton_method(:detailed_message) { |**| "DETAILED MESSAGE" }
+ it "relies on #detailed_message" do
+ e = RuntimeError.new("new error")
+ e.define_singleton_method(:detailed_message) { |**| "DETAILED MESSAGE" }
- e.full_message.lines.first.should =~ /DETAILED MESSAGE/
+ e.full_message.lines.first.should =~ /DETAILED MESSAGE/
+ end
+
+ it "passes all its own keyword arguments (with :highlight default value and without :order default value) to #detailed_message" do
+ e = RuntimeError.new("new error")
+ options_passed = nil
+ e.define_singleton_method(:detailed_message) do |**options|
+ options_passed = options
+ "DETAILED MESSAGE"
end
- it "passes all its own keyword arguments (with :highlight default value and without :order default value) to #detailed_message" do
- e = RuntimeError.new("new error")
- options_passed = nil
- e.define_singleton_method(:detailed_message) do |**options|
- options_passed = options
- "DETAILED MESSAGE"
- end
+ e.full_message(foo: "bar")
+ options_passed.should == { foo: "bar", highlight: Exception.to_tty? }
+ end
- e.full_message(foo: "bar")
- options_passed.should == { foo: "bar", highlight: Exception.to_tty? }
- end
+ it "converts #detailed_message returned value to String if it isn't a String" do
+ message = Object.new
+ def message.to_str; "DETAILED MESSAGE"; end
- it "converts #detailed_message returned value to String if it isn't a String" do
- message = Object.new
- def message.to_str; "DETAILED MESSAGE"; end
+ e = RuntimeError.new("new error")
+ e.define_singleton_method(:detailed_message) { |**| message }
- e = RuntimeError.new("new error")
- e.define_singleton_method(:detailed_message) { |**| message }
+ e.full_message.lines.first.should =~ /DETAILED MESSAGE/
+ end
- e.full_message.lines.first.should =~ /DETAILED MESSAGE/
- end
+ it "uses class name if #detailed_message returns nil" do
+ e = RuntimeError.new("new error")
+ e.define_singleton_method(:detailed_message) { |**| nil }
- it "uses class name if #detailed_message returns nil" do
- e = RuntimeError.new("new error")
- e.define_singleton_method(:detailed_message) { |**| nil }
+ e.full_message(highlight: false).lines.first.should =~ /RuntimeError/
+ e.full_message(highlight: true).lines.first.should =~ /#{Regexp.escape("\e[1;4mRuntimeError\e[m")}/
+ end
- e.full_message(highlight: false).lines.first.should =~ /RuntimeError/
- e.full_message(highlight: true).lines.first.should =~ /#{Regexp.escape("\e[1;4mRuntimeError\e[m")}/
+ it "uses class name if exception object doesn't respond to #detailed_message" do
+ e = RuntimeError.new("new error")
+ class << e
+ undef :detailed_message
end
- it "uses class name if exception object doesn't respond to #detailed_message" do
- e = RuntimeError.new("new error")
- class << e
- undef :detailed_message
- end
+ e.full_message(highlight: false).lines.first.should =~ /RuntimeError/
+ e.full_message(highlight: true).lines.first.should =~ /#{Regexp.escape("\e[1;4mRuntimeError\e[m")}/
+ end
- e.full_message(highlight: false).lines.first.should =~ /RuntimeError/
- e.full_message(highlight: true).lines.first.should =~ /#{Regexp.escape("\e[1;4mRuntimeError\e[m")}/
+ it "allows cause with empty backtrace" do
+ begin
+ raise RuntimeError.new("Some runtime error"), cause: RuntimeError.new("Some other runtime error")
+ rescue => e
end
+
+ full_message = e.full_message
+ full_message.should include "RuntimeError"
+ full_message.should include "Some runtime error"
+ full_message.should include "Some other runtime error"
end
end
diff --git a/spec/ruby/core/exception/no_method_error_spec.rb b/spec/ruby/core/exception/no_method_error_spec.rb
index 26df3338e9..772c569f67 100644
--- a/spec/ruby/core/exception/no_method_error_spec.rb
+++ b/spec/ruby/core/exception/no_method_error_spec.rb
@@ -67,7 +67,7 @@ describe "NoMethodError#message" do
end
ruby_version_is ""..."3.3" do
- it "calls receiver.inspect only when calling Exception#message" do
+ it "calls #inspect when calling Exception#message" do
ScratchPad.record []
test_class = Class.new do
def inspect
@@ -76,19 +76,163 @@ describe "NoMethodError#message" do
end
end
instance = test_class.new
+
begin
instance.bar
- rescue Exception => e
- e.name.should == :bar
- ScratchPad.recorded.should == []
- e.message.should =~ /undefined method.+\bbar\b/
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']bar' for <inspect>:#<Class:0x\h+>$/
ScratchPad.recorded.should == [:inspect_called]
end
end
+
+ it "fallbacks to a simpler representation of the receiver when receiver.inspect raises an exception" do
+ test_class = Class.new do
+ def inspect
+ raise NoMethodErrorSpecs::InstanceException
+ end
+ end
+ instance = test_class.new
+
+ begin
+ instance.bar
+ rescue NoMethodError => error
+ message = error.message
+ message.should =~ /undefined method.+\bbar\b/
+ message.should include test_class.inspect
+ end
+ end
+
+ it "uses #name to display the receiver if it is a class" do
+ klass = Class.new { def self.name; "MyClass"; end }
+
+ begin
+ klass.foo
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']foo' for MyClass:Class$/
+ end
+ end
+
+ it "uses #name to display the receiver if it is a module" do
+ mod = Module.new { def self.name; "MyModule"; end }
+
+ begin
+ mod.foo
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']foo' for MyModule:Module$/
+ end
+ end
end
ruby_version_is "3.3" do
- it "does not call receiver.inspect even when calling Exception#message" do
+ it "uses a literal name when receiver is nil" do
+ begin
+ nil.foo
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']foo' for nil\Z/
+ end
+ end
+
+ it "uses a literal name when receiver is true" do
+ begin
+ true.foo
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']foo' for true\Z/
+ end
+ end
+
+ it "uses a literal name when receiver is false" do
+ begin
+ false.foo
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']foo' for false\Z/
+ end
+ end
+
+ it "uses #name when receiver is a class" do
+ klass = Class.new { def self.name; "MyClass"; end }
+
+ begin
+ klass.foo
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']foo' for class MyClass\Z/
+ end
+ end
+
+ it "uses class' string representation when receiver is an anonymous class" do
+ klass = Class.new
+
+ begin
+ klass.foo
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']foo' for class #<Class:0x\h+>\Z/
+ end
+ end
+
+ it "uses class' string representation when receiver is a singleton class" do
+ obj = Object.new
+ singleton_class = obj.singleton_class
+
+ begin
+ singleton_class.foo
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']foo' for class #<Class:#<Object:0x\h+>>\Z/
+ end
+ end
+
+ it "uses #name when receiver is a module" do
+ mod = Module.new { def self.name; "MyModule"; end }
+
+ begin
+ mod.foo
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']foo' for module MyModule\Z/
+ end
+ end
+
+ it "uses module's string representation when receiver is an anonymous module" do
+ m = Module.new
+
+ begin
+ m.foo
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']foo' for module #<Module:0x\h+>\Z/
+ end
+ end
+
+ it "uses class #name when receiver is an ordinary object" do
+ klass = Class.new { def self.name; "MyClass"; end }
+ instance = klass.new
+
+ begin
+ instance.bar
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']bar' for an instance of MyClass\Z/
+ end
+ end
+
+ it "uses class string representation when receiver is an instance of anonymous class" do
+ klass = Class.new
+ instance = klass.new
+
+ begin
+ instance.bar
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']bar' for an instance of #<Class:0x\h+>\Z/
+ end
+ end
+
+ it "uses class name when receiver has a singleton class" do
+ instance = NoMethodErrorSpecs::NoMethodErrorA.new
+ def instance.foo; end
+
+ begin
+ instance.bar
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']bar' for #<NoMethodErrorSpecs::NoMethodErrorA:0x\h+>\Z/
+ end
+ end
+
+ it "does not call #inspect when calling Exception#message" do
ScratchPad.record []
test_class = Class.new do
def inspect
@@ -97,47 +241,29 @@ describe "NoMethodError#message" do
end
end
instance = test_class.new
+
begin
instance.bar
- rescue Exception => e
- e.name.should == :bar
- ScratchPad.recorded.should == []
- e.message.should =~ /undefined method.+\bbar\b/
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']bar' for an instance of #<Class:0x\h+>\Z/
ScratchPad.recorded.should == []
end
end
- end
- it "fallbacks to a simpler representation of the receiver when receiver.inspect raises an exception" do
- test_class = Class.new do
- def inspect
- raise NoMethodErrorSpecs::InstanceException
- end
- end
- instance = test_class.new
- begin
- instance.bar
- rescue Exception => e
- e.name.should == :bar
- message = e.message
- message.should =~ /undefined method.+\bbar\b/
- message.should include test_class.inspect
- end
- end
+ it "does not truncate long class names" do
+ class_name = 'ExceptionSpecs::A' + 'a'*100
- 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 /
- end
+ begin
+ eval <<~RUBY
+ class #{class_name}
+ 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 /
+ obj = #{class_name}.new
+ obj.foo
+ RUBY
+ rescue NoMethodError => error
+ error.message.should =~ /\Aundefined method [`']foo' for an instance of #{class_name}\Z/
+ end
end
end
end
diff --git a/spec/ruby/core/exception/set_backtrace_spec.rb b/spec/ruby/core/exception/set_backtrace_spec.rb
index 12c1da919c..2cd93326ec 100644
--- a/spec/ruby/core/exception/set_backtrace_spec.rb
+++ b/spec/ruby/core/exception/set_backtrace_spec.rb
@@ -1,13 +1,8 @@
require_relative '../../spec_helper'
require_relative 'fixtures/common'
+require_relative 'shared/set_backtrace'
describe "Exception#set_backtrace" do
- it "accepts an Array of Strings" do
- err = RuntimeError.new
- err.set_backtrace ["unhappy"]
- err.backtrace.should == ["unhappy"]
- end
-
it "allows the user to set the backtrace from a rescued exception" do
bt = ExceptionSpecs::Backtrace.backtrace
err = RuntimeError.new
@@ -20,65 +15,9 @@ describe "Exception#set_backtrace" do
err.backtrace_locations.should == nil
end
- ruby_version_is "3.4" do
- it "allows the user to set backtrace locations from a rescued exception" do
- bt_locations = ExceptionSpecs::Backtrace.backtrace_locations
- err = RuntimeError.new
- err.backtrace.should == nil
- err.backtrace_locations.should == nil
-
- err.set_backtrace bt_locations
-
- err.backtrace_locations.size.should == bt_locations.size
- err.backtrace_locations.each_with_index do |loc, index|
- other_loc = bt_locations[index]
-
- loc.path.should == other_loc.path
- loc.label.should == other_loc.label
- loc.base_label.should == other_loc.base_label
- loc.lineno.should == other_loc.lineno
- loc.absolute_path.should == other_loc.absolute_path
- loc.to_s.should == other_loc.to_s
- end
- err.backtrace.size.should == err.backtrace_locations.size
- end
- end
-
- it "accepts an empty Array" do
- err = RuntimeError.new
- err.set_backtrace []
- err.backtrace.should == []
- end
-
- it "accepts a String" do
+ it_behaves_like :exception_set_backtrace, -> backtrace {
err = RuntimeError.new
- err.set_backtrace "unhappy"
- err.backtrace.should == ["unhappy"]
- end
-
- it "accepts nil" do
- err = RuntimeError.new
- err.set_backtrace nil
- err.backtrace.should be_nil
- end
-
- it "raises a TypeError when passed a Symbol" do
- err = RuntimeError.new
- -> { err.set_backtrace :unhappy }.should raise_error(TypeError)
- end
-
- it "raises a TypeError when the Array contains a Symbol" do
- err = RuntimeError.new
- -> { err.set_backtrace ["String", :unhappy] }.should raise_error(TypeError)
- end
-
- it "raises a TypeError when the array contains nil" do
- err = Exception.new
- -> { err.set_backtrace ["String", nil] }.should raise_error(TypeError)
- end
-
- it "raises a TypeError when the argument is a nested array" do
- err = Exception.new
- -> { err.set_backtrace ["String", ["String"]] }.should raise_error(TypeError)
- end
+ err.set_backtrace(backtrace)
+ err
+ }
end
diff --git a/spec/ruby/core/exception/shared/set_backtrace.rb b/spec/ruby/core/exception/shared/set_backtrace.rb
new file mode 100644
index 0000000000..c6213b42b4
--- /dev/null
+++ b/spec/ruby/core/exception/shared/set_backtrace.rb
@@ -0,0 +1,64 @@
+require_relative '../fixtures/common'
+
+describe :exception_set_backtrace, shared: true do
+ it "accepts an Array of Strings" do
+ err = @method.call(["unhappy"])
+ err.backtrace.should == ["unhappy"]
+ end
+
+ it "allows the user to set the backtrace from a rescued exception" do
+ bt = ExceptionSpecs::Backtrace.backtrace
+ err = @method.call(bt)
+ err.backtrace.should == bt
+ end
+
+ ruby_version_is "3.4" do
+ it "allows the user to set backtrace locations from a rescued exception" do
+ bt_locations = ExceptionSpecs::Backtrace.backtrace_locations
+ err = @method.call(bt_locations)
+ err.backtrace_locations.size.should == bt_locations.size
+ err.backtrace_locations.each_with_index do |loc, index|
+ other_loc = bt_locations[index]
+
+ loc.path.should == other_loc.path
+ loc.label.should == other_loc.label
+ loc.base_label.should == other_loc.base_label
+ loc.lineno.should == other_loc.lineno
+ loc.absolute_path.should == other_loc.absolute_path
+ loc.to_s.should == other_loc.to_s
+ end
+ err.backtrace.size.should == err.backtrace_locations.size
+ end
+ end
+
+ it "accepts an empty Array" do
+ err = @method.call([])
+ err.backtrace.should == []
+ end
+
+ it "accepts a String" do
+ err = @method.call("unhappy")
+ err.backtrace.should == ["unhappy"]
+ end
+
+ it "accepts nil" do
+ err = @method.call(nil)
+ err.backtrace.should be_nil
+ end
+
+ it "raises a TypeError when passed a Symbol" do
+ -> { @method.call(:unhappy) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError when the Array contains a Symbol" do
+ -> { @method.call(["String", :unhappy]) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError when the array contains nil" do
+ -> { @method.call(["String", nil]) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError when the argument is a nested array" do
+ -> { @method.call(["String", ["String"]]) }.should raise_error(TypeError)
+ end
+end
diff --git a/spec/ruby/core/exception/syntax_error_spec.rb b/spec/ruby/core/exception/syntax_error_spec.rb
index 6cc8522de3..4c713a3507 100644
--- a/spec/ruby/core/exception/syntax_error_spec.rb
+++ b/spec/ruby/core/exception/syntax_error_spec.rb
@@ -1,27 +1,25 @@
require_relative '../../spec_helper'
-ruby_version_is "3.2" do
- describe "SyntaxError#path" do
- it "returns the file path provided to eval" do
- filename = "speccing.rb"
+describe "SyntaxError#path" do
+ it "returns the file path provided to eval" do
+ filename = "speccing.rb"
- -> {
- eval("if true", TOPLEVEL_BINDING, filename)
- }.should raise_error(SyntaxError) { |e|
- e.path.should == filename
- }
- end
+ -> {
+ eval("if true", TOPLEVEL_BINDING, filename)
+ }.should raise_error(SyntaxError) { |e|
+ e.path.should == filename
+ }
+ end
- it "returns the file path that raised an exception" do
- expected_path = fixture(__FILE__, "syntax_error.rb")
+ it "returns the file path that raised an exception" do
+ expected_path = fixture(__FILE__, "syntax_error.rb")
- -> {
- require_relative "fixtures/syntax_error"
- }.should raise_error(SyntaxError) { |e| e.path.should == expected_path }
- end
+ -> {
+ require_relative "fixtures/syntax_error"
+ }.should raise_error(SyntaxError) { |e| e.path.should == expected_path }
+ end
- it "returns nil when constructed directly" do
- SyntaxError.new.path.should == nil
- end
+ it "returns nil when constructed directly" do
+ SyntaxError.new.path.should == nil
end
end
diff --git a/spec/ruby/core/exception/system_call_error_spec.rb b/spec/ruby/core/exception/system_call_error_spec.rb
index 73167bc288..4fe51901c8 100644
--- a/spec/ruby/core/exception/system_call_error_spec.rb
+++ b/spec/ruby/core/exception/system_call_error_spec.rb
@@ -16,6 +16,8 @@ describe "SystemCallError" do
exc = ExceptionSpecs::SCESub.new
ScratchPad.recorded.should equal(:initialize)
exc.should be_an_instance_of(ExceptionSpecs::SCESub)
+ ensure
+ ExceptionSpecs.send(:remove_const, :SCESub)
end
end
@@ -25,6 +27,7 @@ describe "SystemCallError.new" do
@example_errno_class = Errno::EINVAL
@last_known_errno = Errno.constants.size - 1
@unknown_errno = Errno.constants.size
+ @some_human_readable = /[[:graph:]]+/
end
it "requires at least one argument" do
@@ -53,6 +56,11 @@ describe "SystemCallError.new" do
e.should be_an_instance_of(@example_errno_class)
end
+ it "sets an error message corresponding to an appropriate Errno class" do
+ e = SystemCallError.new(@example_errno)
+ e.message.should == 'Invalid argument'
+ end
+
it "accepts an optional custom message preceding the errno" do
exc = SystemCallError.new("custom message", @example_errno)
exc.should be_an_instance_of(@example_errno_class)
@@ -81,6 +89,23 @@ describe "SystemCallError.new" do
SystemCallError.new('foo', 2.9).should == SystemCallError.new('foo', 2)
end
+ it "treats nil errno as unknown error value" do
+ SystemCallError.new(nil).should be_an_instance_of(SystemCallError)
+ end
+
+ it "treats nil custom message as if it is not passed at all" do
+ exc = SystemCallError.new(nil, @example_errno)
+ exc.message.should == 'Invalid argument'
+ end
+
+ it "sets an 'unknown error' message when an unknown error number" do
+ SystemCallError.new(-1).message.should =~ @some_human_readable
+ end
+
+ it "adds a custom error message to an 'unknown error' message when an unknown error number and a custom message specified" do
+ SystemCallError.new("custom message", -1).message.should =~ /#{@some_human_readable}.* - custom message/
+ end
+
it "converts to Integer if errno is a Complex convertible to Integer" do
SystemCallError.new('foo', Complex(2.9, 0)).should == SystemCallError.new('foo', 2)
end
@@ -115,12 +140,7 @@ end
describe "SystemCallError#message" do
it "returns the default message when no message is given" do
- platform_is :aix do
- SystemCallError.new(2**28).message.should =~ /Error .*occurred/i
- end
- platform_is_not :aix do
- SystemCallError.new(2**28).message.should =~ /Unknown error/i
- end
+ SystemCallError.new(2**28).message.should =~ @some_human_readable
end
it "returns the message given as an argument to new" do
diff --git a/spec/ruby/core/fiber/alive_spec.rb b/spec/ruby/core/fiber/alive_spec.rb
new file mode 100644
index 0000000000..a1df582435
--- /dev/null
+++ b/spec/ruby/core/fiber/alive_spec.rb
@@ -0,0 +1,44 @@
+require_relative '../../spec_helper'
+
+describe "Fiber#alive?" do
+ it "returns true for a Fiber that hasn't had #resume called" do
+ fiber = Fiber.new { true }
+ fiber.alive?.should be_true
+ end
+
+ # FIXME: Better description?
+ it "returns true for a Fiber that's yielded to the caller" do
+ fiber = Fiber.new { Fiber.yield }
+ fiber.resume
+ fiber.alive?.should be_true
+ end
+
+ it "returns true when called from its Fiber" do
+ fiber = Fiber.new { fiber.alive?.should be_true }
+ fiber.resume
+ end
+
+ it "doesn't invoke the block associated with the Fiber" do
+ offthehook = mock('do not call')
+ offthehook.should_not_receive(:ring)
+ fiber = Fiber.new { offthehook.ring }
+ fiber.alive?
+ end
+
+ it "returns false for a Fiber that's dead" do
+ fiber = Fiber.new { true }
+ fiber.resume
+ -> { fiber.resume }.should raise_error(FiberError)
+ fiber.alive?.should be_false
+ end
+
+ it "always returns false for a dead Fiber" do
+ fiber = Fiber.new { true }
+ fiber.resume
+ -> { fiber.resume }.should raise_error(FiberError)
+ fiber.alive?.should be_false
+ -> { fiber.resume }.should raise_error(FiberError)
+ fiber.alive?.should be_false
+ fiber.alive?.should be_false
+ end
+end
diff --git a/spec/ruby/core/fiber/blocking_spec.rb b/spec/ruby/core/fiber/blocking_spec.rb
index ebefa116af..d5caf81fbe 100644
--- a/spec/ruby/core/fiber/blocking_spec.rb
+++ b/spec/ruby/core/fiber/blocking_spec.rb
@@ -1,8 +1,6 @@
require_relative '../../spec_helper'
require_relative 'shared/blocking'
-require "fiber"
-
describe "Fiber.blocking?" do
it_behaves_like :non_blocking_fiber, -> { Fiber.blocking? }
@@ -59,19 +57,17 @@ describe "Fiber#blocking?" do
end
end
-ruby_version_is "3.2" do
- describe "Fiber.blocking" do
- context "when fiber is non-blocking" do
- it "can become blocking" do
- fiber = Fiber.new(blocking: false) do
- Fiber.blocking do |f|
- f.blocking? ? :blocking : :non_blocking
- end
+describe "Fiber.blocking" do
+ context "when fiber is non-blocking" do
+ it "can become blocking" do
+ fiber = Fiber.new(blocking: false) do
+ Fiber.blocking do |f|
+ f.blocking? ? :blocking : :non_blocking
end
-
- blocking = fiber.resume
- blocking.should == :blocking
end
+
+ blocking = fiber.resume
+ blocking.should == :blocking
end
end
end
diff --git a/spec/ruby/core/fiber/current_spec.rb b/spec/ruby/core/fiber/current_spec.rb
new file mode 100644
index 0000000000..b93df77a89
--- /dev/null
+++ b/spec/ruby/core/fiber/current_spec.rb
@@ -0,0 +1,50 @@
+require_relative '../../spec_helper'
+
+describe "Fiber.current" do
+ it "returns the root Fiber when called outside of a Fiber" do
+ root = Fiber.current
+ root.should be_an_instance_of(Fiber)
+ # We can always transfer to the root Fiber; it will never die
+ 5.times do
+ root.transfer.should be_nil
+ root.alive?.should be_true
+ end
+ end
+
+ it "returns the current Fiber when called from a Fiber" do
+ fiber = Fiber.new do
+ this = Fiber.current
+ this.should be_an_instance_of(Fiber)
+ this.should == fiber
+ this.alive?.should be_true
+ end
+ fiber.resume
+ end
+
+ it "returns the current Fiber when called from a Fiber that transferred to another" do
+ states = []
+ fiber = Fiber.new do
+ states << :fiber
+ this = Fiber.current
+ this.should be_an_instance_of(Fiber)
+ this.should == fiber
+ this.alive?.should be_true
+ end
+
+ fiber2 = Fiber.new do
+ states << :fiber2
+ fiber.transfer
+ flunk
+ end
+
+ fiber3 = Fiber.new do
+ states << :fiber3
+ fiber2.transfer
+ states << :fiber3_terminated
+ end
+
+ fiber3.resume
+
+ states.should == [:fiber3, :fiber2, :fiber, :fiber3_terminated]
+ end
+end
diff --git a/spec/ruby/core/fiber/fixtures/classes.rb b/spec/ruby/core/fiber/fixtures/classes.rb
index c00facd6e1..6b0e0fbc42 100644
--- a/spec/ruby/core/fiber/fixtures/classes.rb
+++ b/spec/ruby/core/fiber/fixtures/classes.rb
@@ -1,10 +1,20 @@
module FiberSpecs
class NewFiberToRaise
- def self.raise(*args)
- fiber = Fiber.new { Fiber.yield }
+ def self.raise(*args, **kwargs, &block)
+ fiber = Fiber.new do
+ if block_given?
+ block.call do
+ Fiber.yield
+ end
+ else
+ Fiber.yield
+ end
+ end
+
fiber.resume
- fiber.raise(*args)
+
+ fiber.raise(*args, **kwargs)
end
end
diff --git a/spec/ruby/core/fiber/fixtures/scheduler.rb b/spec/ruby/core/fiber/fixtures/scheduler.rb
new file mode 100644
index 0000000000..16bd2f6b44
--- /dev/null
+++ b/spec/ruby/core/fiber/fixtures/scheduler.rb
@@ -0,0 +1,35 @@
+module FiberSpecs
+
+ class LoggingScheduler
+ attr_reader :events
+ def initialize
+ @events = []
+ end
+
+ def block(*args)
+ @events << { event: :block, fiber: Fiber.current, args: args }
+ Fiber.yield
+ end
+
+ def io_wait(*args)
+ @events << { event: :io_wait, fiber: Fiber.current, args: args }
+ Fiber.yield
+ end
+
+ def kernel_sleep(*args)
+ @events << { event: :kernel_sleep, fiber: Fiber.current, args: args }
+ Fiber.yield
+ end
+
+ def unblock(*args)
+ @events << { event: :unblock, fiber: Fiber.current, args: args }
+ Fiber.yield
+ end
+
+ def fiber_interrupt(*args)
+ @events << { event: :fiber_interrupt, fiber: Fiber.current, args: args }
+ Fiber.yield
+ end
+ end
+
+end
diff --git a/spec/ruby/core/fiber/inspect_spec.rb b/spec/ruby/core/fiber/inspect_spec.rb
index f20a153fc2..fcfef20716 100644
--- a/spec/ruby/core/fiber/inspect_spec.rb
+++ b/spec/ruby/core/fiber/inspect_spec.rb
@@ -1,5 +1,4 @@
require_relative '../../spec_helper'
-require 'fiber'
describe "Fiber#inspect" do
describe "status" do
diff --git a/spec/ruby/core/fiber/raise_spec.rb b/spec/ruby/core/fiber/raise_spec.rb
index b3e021e636..896f760290 100644
--- a/spec/ruby/core/fiber/raise_spec.rb
+++ b/spec/ruby/core/fiber/raise_spec.rb
@@ -4,6 +4,7 @@ require_relative '../../shared/kernel/raise'
describe "Fiber#raise" do
it_behaves_like :kernel_raise, :raise, FiberSpecs::NewFiberToRaise
+ it_behaves_like :kernel_raise_across_contexts, :raise, FiberSpecs::NewFiberToRaise
end
describe "Fiber#raise" do
@@ -42,7 +43,7 @@ describe "Fiber#raise" 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
+ it 'accepts error class with error message and backtrace information' do
-> {
FiberSpecs::NewFiberToRaise.raise FiberSpecs::CustomError, 'test error', ['foo', 'boo']
}.should raise_error(FiberSpecs::CustomError) { |e|
@@ -130,7 +131,6 @@ end
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
diff --git a/spec/ruby/core/fiber/resume_spec.rb b/spec/ruby/core/fiber/resume_spec.rb
index ab9a6799ab..4b20f4b4bf 100644
--- a/spec/ruby/core/fiber/resume_spec.rb
+++ b/spec/ruby/core/fiber/resume_spec.rb
@@ -1,5 +1,5 @@
require_relative '../../spec_helper'
-require_relative '../../shared/fiber/resume'
+require_relative 'shared/resume'
describe "Fiber#resume" do
it_behaves_like :fiber_resume, :resume
@@ -67,4 +67,17 @@ describe "Fiber#resume" do
ruby_exe(code).should == "ensure executed\n"
end
+
+ 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
diff --git a/spec/ruby/core/fiber/scheduler_spec.rb b/spec/ruby/core/fiber/scheduler_spec.rb
new file mode 100644
index 0000000000..15a03c1479
--- /dev/null
+++ b/spec/ruby/core/fiber/scheduler_spec.rb
@@ -0,0 +1,8 @@
+require_relative '../../spec_helper'
+require_relative 'shared/scheduler'
+
+require "fiber"
+
+describe "Fiber.scheduler" do
+ it_behaves_like :scheduler, :scheduler
+end
diff --git a/spec/ruby/core/fiber/set_scheduler_spec.rb b/spec/ruby/core/fiber/set_scheduler_spec.rb
new file mode 100644
index 0000000000..82f6acbe86
--- /dev/null
+++ b/spec/ruby/core/fiber/set_scheduler_spec.rb
@@ -0,0 +1,8 @@
+require_relative '../../spec_helper'
+require_relative 'shared/scheduler'
+
+require "fiber"
+
+describe "Fiber.scheduler" do
+ it_behaves_like :scheduler, :set_scheduler
+end
diff --git a/spec/ruby/core/fiber/shared/resume.rb b/spec/ruby/core/fiber/shared/resume.rb
new file mode 100644
index 0000000000..5ee27d1d24
--- /dev/null
+++ b/spec/ruby/core/fiber/shared/resume.rb
@@ -0,0 +1,58 @@
+describe :fiber_resume, shared: true do
+ it "can be invoked from the root Fiber" do
+ fiber = Fiber.new { :fiber }
+ fiber.send(@method).should == :fiber
+ end
+
+ it "raises a FiberError if invoked from a different Thread" do
+ fiber = Fiber.new { 42 }
+ Thread.new do
+ -> {
+ fiber.send(@method)
+ }.should raise_error(FiberError)
+ end.join
+
+ # Check the Fiber can still be used
+ fiber.send(@method).should == 42
+ end
+
+ it "passes control to the beginning of the block on first invocation" do
+ invoked = false
+ fiber = Fiber.new { invoked = true }
+ fiber.send(@method)
+ invoked.should be_true
+ end
+
+ it "returns the last value encountered on first invocation" do
+ fiber = Fiber.new { 1+1; true }
+ fiber.send(@method).should be_true
+ end
+
+ it "runs until the end of the block" do
+ obj = mock('obj')
+ obj.should_receive(:do).once
+ fiber = Fiber.new { 1 + 2; a = "glark"; obj.do }
+ fiber.send(@method)
+ 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 "raises a FiberError if the Fiber is dead" do
+ fiber = Fiber.new { true }
+ fiber.send(@method)
+ -> { fiber.send(@method) }.should raise_error(FiberError)
+ end
+
+ it "raises a LocalJumpError if the block includes a return statement" do
+ fiber = Fiber.new { return; }
+ -> { fiber.send(@method) }.should raise_error(LocalJumpError)
+ end
+
+ it "raises a LocalJumpError if the block includes a break statement" do
+ fiber = Fiber.new { break; }
+ -> { fiber.send(@method) }.should raise_error(LocalJumpError)
+ end
+end
diff --git a/spec/ruby/core/fiber/shared/scheduler.rb b/spec/ruby/core/fiber/shared/scheduler.rb
new file mode 100644
index 0000000000..19bfb75e3e
--- /dev/null
+++ b/spec/ruby/core/fiber/shared/scheduler.rb
@@ -0,0 +1,51 @@
+describe :scheduler, shared: true do
+ it "validates the scheduler for required methods" do
+ required_methods = [:block, :unblock, :kernel_sleep, :io_wait]
+ required_methods.each do |missing_method|
+ scheduler = Object.new
+ required_methods.difference([missing_method]).each do |method|
+ scheduler.define_singleton_method(method) {}
+ end
+ -> {
+ suppress_warning { Fiber.set_scheduler(scheduler) }
+ }.should raise_error(ArgumentError, /Scheduler must implement ##{missing_method}/)
+ end
+ end
+
+ it "can set and get the scheduler" do
+ required_methods = [:block, :unblock, :kernel_sleep, :io_wait]
+ scheduler = Object.new
+ required_methods.each do |method|
+ scheduler.define_singleton_method(method) {}
+ end
+ suppress_warning { Fiber.set_scheduler(scheduler) }
+ Fiber.scheduler.should == scheduler
+ end
+
+ it "returns the scheduler after setting it" do
+ required_methods = [:block, :unblock, :kernel_sleep, :io_wait]
+ scheduler = Object.new
+ required_methods.each do |method|
+ scheduler.define_singleton_method(method) {}
+ end
+ result = suppress_warning { Fiber.set_scheduler(scheduler) }
+ result.should == scheduler
+ end
+
+ it "can remove the scheduler" do
+ required_methods = [:block, :unblock, :kernel_sleep, :io_wait]
+ scheduler = Object.new
+ required_methods.each do |method|
+ scheduler.define_singleton_method(method) {}
+ end
+ suppress_warning { Fiber.set_scheduler(scheduler) }
+ Fiber.set_scheduler(nil)
+ Fiber.scheduler.should be_nil
+ end
+
+ it "can assign a nil scheduler multiple times" do
+ Fiber.set_scheduler(nil)
+ Fiber.set_scheduler(nil)
+ Fiber.scheduler.should be_nil
+ end
+end
diff --git a/spec/ruby/core/fiber/storage_spec.rb b/spec/ruby/core/fiber/storage_spec.rb
index 5c87ed5d41..015caaf3bb 100644
--- a/spec/ruby/core/fiber/storage_spec.rb
+++ b/spec/ruby/core/fiber/storage_spec.rb
@@ -1,158 +1,181 @@
require_relative '../../spec_helper'
-ruby_version_is "3.2" do
- describe "Fiber.new(storage:)" do
- it "creates a Fiber with the given storage" do
- storage = {life: 42}
- fiber = Fiber.new(storage: storage) { Fiber.current.storage }
- fiber.resume.should == storage
- end
+describe "Fiber.new(storage:)" do
+ it "creates a Fiber with the given storage" do
+ storage = {life: 42}
+ fiber = Fiber.new(storage: storage) { Fiber.current.storage }
+ fiber.resume.should == storage
+ end
- it "creates a fiber with lazily initialized storage" do
- Fiber.new(storage: nil) { Fiber[:x] = 10; Fiber.current.storage }.resume.should == {x: 10}
- end
+ it "creates a fiber with lazily initialized storage" do
+ Fiber.new(storage: nil) { Fiber[:x] = 10; Fiber.current.storage }.resume.should == {x: 10}
+ end
- it "creates a fiber by inheriting the storage of the parent fiber" do
- fiber = Fiber.new(storage: {life: 42}) do
- Fiber.new { Fiber.current.storage }.resume
- end
- fiber.resume.should == {life: 42}
+ it "creates a fiber by inheriting the storage of the parent fiber" do
+ fiber = Fiber.new(storage: {life: 42}) do
+ Fiber.new { Fiber.current.storage }.resume
end
+ fiber.resume.should == {life: 42}
+ end
- it "cannot create a fiber with non-hash storage" do
- -> { Fiber.new(storage: 42) {} }.should raise_error(TypeError)
- end
+ it "cannot create a fiber with non-hash storage" do
+ -> { Fiber.new(storage: 42) {} }.should raise_error(TypeError)
+ end
- it "cannot create a fiber with a frozen hash as storage" do
- -> { Fiber.new(storage: {life: 43}.freeze) {} }.should raise_error(FrozenError)
- end
+ it "cannot create a fiber with a frozen hash as storage" do
+ -> { Fiber.new(storage: {life: 43}.freeze) {} }.should raise_error(FrozenError)
+ end
- it "cannot create a fiber with a storage hash with non-symbol keys" do
- -> { Fiber.new(storage: {life: 43, Object.new => 44}) {} }.should raise_error(TypeError)
- end
+ it "cannot create a fiber with a storage hash with non-symbol keys" do
+ -> { Fiber.new(storage: {life: 43, Object.new => 44}) {} }.should raise_error(TypeError)
end
+end
- describe "Fiber#storage" do
- it "cannot be accessed from a different fiber" do
- f = Fiber.new(storage: {life: 42}) { nil }
- -> {
- f.storage
- }.should raise_error(ArgumentError, /Fiber storage can only be accessed from the Fiber it belongs to/)
- end
+describe "Fiber#storage" do
+ it "cannot be accessed from a different fiber" do
+ f = Fiber.new(storage: {life: 42}) { nil }
+ -> {
+ f.storage
+ }.should raise_error(ArgumentError, /Fiber storage can only be accessed from the Fiber it belongs to/)
end
+end
- describe "Fiber#storage=" do
- it "can clear the storage of the fiber" do
- fiber = Fiber.new(storage: {life: 42}) do
- Fiber.current.storage = nil
- Fiber[:x] = 10
- Fiber.current.storage
- end
- fiber.resume.should == {x: 10}
+describe "Fiber#storage=" do
+ it "can clear the storage of the fiber" do
+ fiber = Fiber.new(storage: {life: 42}) do
+ Fiber.current.storage = nil
+ Fiber[:x] = 10
+ Fiber.current.storage
end
+ fiber.resume.should == {x: 10}
+ end
- it "can set the storage of the fiber" do
- fiber = Fiber.new(storage: {life: 42}) do
- Fiber.current.storage = {life: 43}
- Fiber.current.storage
- end
- fiber.resume.should == {life: 43}
+ it "can set the storage of the fiber" do
+ fiber = Fiber.new(storage: {life: 42}) do
+ Fiber.current.storage = {life: 43}
+ Fiber.current.storage
end
+ fiber.resume.should == {life: 43}
+ end
- it "can't set the storage of the fiber to non-hash" do
- -> { Fiber.current.storage = 42 }.should raise_error(TypeError)
- end
+ it "can't set the storage of the fiber to non-hash" do
+ -> { Fiber.current.storage = 42 }.should raise_error(TypeError)
+ end
- it "can't set the storage of the fiber to a frozen hash" do
- -> { Fiber.current.storage = {life: 43}.freeze }.should raise_error(FrozenError)
- end
+ it "can't set the storage of the fiber to a frozen hash" do
+ -> { Fiber.current.storage = {life: 43}.freeze }.should raise_error(FrozenError)
+ end
- it "can't set the storage of the fiber to a hash with non-symbol keys" do
- -> { Fiber.current.storage = {life: 43, Object.new => 44} }.should raise_error(TypeError)
- end
+ it "can't set the storage of the fiber to a hash with non-symbol keys" do
+ -> { Fiber.current.storage = {life: 43, Object.new => 44} }.should raise_error(TypeError)
end
+end
- describe "Fiber.[]" do
- it "returns the value of the given key in the storage of the current fiber" do
- Fiber.new(storage: {life: 42}) { Fiber[:life] }.resume.should == 42
- end
+describe "Fiber.[]" do
+ it "returns the value of the given key in the storage of the current fiber" do
+ Fiber.new(storage: {life: 42}) { Fiber[:life] }.resume.should == 42
+ end
- it "returns nil if the key is not present in the storage of the current fiber" do
- Fiber.new(storage: {life: 42}) { Fiber[:death] }.resume.should be_nil
- end
+ it "returns nil if the key is not present in the storage of the current fiber" do
+ Fiber.new(storage: {life: 42}) { Fiber[:death] }.resume.should be_nil
+ end
+
+ it "returns nil if the current fiber has no storage" do
+ Fiber.new { Fiber[:life] }.resume.should be_nil
+ end
- it "returns nil if the current fiber has no storage" do
- Fiber.new { Fiber[:life] }.resume.should be_nil
+ ruby_version_is "3.2.3" do
+ it "can use dynamically defined keys" do
+ key = :"#{self.class.name}#.#{self.object_id}"
+ Fiber.new { Fiber[key] = 42; Fiber[key] }.resume.should == 42
end
- ruby_version_is "3.2.3" do
- it "can use dynamically defined keys" do
- key = :"#{self.class.name}#.#{self.object_id}"
- Fiber.new { Fiber[key] = 42; Fiber[key] }.resume.should == 42
+ it "can't use invalid keys" do
+ invalid_keys = [Object.new, 12]
+ invalid_keys.each do |key|
+ -> { Fiber[key] }.should raise_error(TypeError)
end
+ end
+ end
- it "can't use invalid keys" do
- invalid_keys = [Object.new, "Foo", 12]
- invalid_keys.each do |key|
- -> { Fiber[key] }.should raise_error(TypeError)
- end
- end
+ ruby_bug "#20978", ""..."3.4" do
+ it "can use keys as strings" do
+ key = Object.new
+ def key.to_str; "Foo"; end
+ Fiber.new { Fiber[key] = 42; Fiber["Foo"] }.resume.should == 42
end
- it "can access the storage of the parent fiber" do
- f = Fiber.new(storage: {life: 42}) do
- Fiber.new { Fiber[:life] }.resume
- end
- f.resume.should == 42
+ it "converts a String key into a Symbol" do
+ Fiber.new { Fiber["key"] = 42; Fiber[:key] }.resume.should == 42
+ Fiber.new { Fiber[:key] = 42; Fiber["key"] }.resume.should == 42
end
- it "can't access the storage of the fiber with non-symbol keys" do
- -> { Fiber[Object.new] }.should raise_error(TypeError)
+ it "can use any object that responds to #to_str as a key" do
+ key = mock("key")
+ key.should_receive(:to_str).twice.and_return("key")
+ Fiber.new { Fiber[key] = 42; Fiber[key] }.resume.should == 42
end
end
- describe "Fiber.[]=" do
- it "sets the value of the given key in the storage of the current fiber" do
- Fiber.new(storage: {life: 42}) { Fiber[:life] = 43; Fiber[:life] }.resume.should == 43
- end
+ it "does not call #to_sym on the key" do
+ key = mock("key")
+ key.should_not_receive(:to_sym)
+ -> { Fiber[key] }.should raise_error(TypeError)
+ end
- it "sets the value of the given key in the storage of the current fiber" do
- Fiber.new(storage: {life: 42}) { Fiber[:death] = 43; Fiber[:death] }.resume.should == 43
+ it "can access the storage of the parent fiber" do
+ f = Fiber.new(storage: {life: 42}) do
+ Fiber.new { Fiber[:life] }.resume
end
+ f.resume.should == 42
+ end
- it "sets the value of the given key in the storage of the current fiber" do
- Fiber.new { Fiber[:life] = 43; Fiber[:life] }.resume.should == 43
- end
+ it "can't access the storage of the fiber with non-symbol keys" do
+ -> { Fiber[Object.new] }.should raise_error(TypeError)
+ end
+end
- it "does not overwrite the storage of the parent fiber" do
- f = Fiber.new(storage: {life: 42}) do
- Fiber.yield Fiber.new { Fiber[:life] = 43; Fiber[:life] }.resume
- Fiber[:life]
- end
- f.resume.should == 43 # Value of the inner fiber
- f.resume.should == 42 # Value of the outer fiber
- end
+describe "Fiber.[]=" do
+ it "sets the value of the given key in the storage of the current fiber" do
+ Fiber.new(storage: {life: 42}) { Fiber[:life] = 43; Fiber[:life] }.resume.should == 43
+ end
+
+ it "sets the value of the given key in the storage of the current fiber" do
+ Fiber.new(storage: {life: 42}) { Fiber[:death] = 43; Fiber[:death] }.resume.should == 43
+ end
+
+ it "sets the value of the given key in the storage of the current fiber" do
+ Fiber.new { Fiber[:life] = 43; Fiber[:life] }.resume.should == 43
+ end
- it "can't access the storage of the fiber with non-symbol keys" do
- -> { Fiber[Object.new] = 44 }.should raise_error(TypeError)
+ it "does not overwrite the storage of the parent fiber" do
+ f = Fiber.new(storage: {life: 42}) do
+ Fiber.yield Fiber.new { Fiber[:life] = 43; Fiber[:life] }.resume
+ Fiber[:life]
end
+ f.resume.should == 43 # Value of the inner fiber
+ f.resume.should == 42 # Value of the outer fiber
+ end
- ruby_version_is "3.3" do
- it "deletes the fiber storage key when assigning nil" do
- Fiber.new(storage: {life: 42}) {
- Fiber[:life] = nil
- Fiber.current.storage
- }.resume.should == {}
- end
+ it "can't access the storage of the fiber with non-symbol keys" do
+ -> { Fiber[Object.new] = 44 }.should raise_error(TypeError)
+ end
+
+ ruby_version_is "3.3" do
+ it "deletes the fiber storage key when assigning nil" do
+ Fiber.new(storage: {life: 42}) {
+ Fiber[:life] = nil
+ Fiber.current.storage
+ }.resume.should == {}
end
end
+end
- describe "Thread.new" do
- it "creates a thread with the storage of the current fiber" do
- fiber = Fiber.new(storage: {life: 42}) do
- Thread.new { Fiber.current.storage }.value
- end
- fiber.resume.should == {life: 42}
+describe "Thread.new" do
+ it "creates a thread with the storage of the current fiber" do
+ fiber = Fiber.new(storage: {life: 42}) do
+ Thread.new { Fiber.current.storage }.value
end
+ fiber.resume.should == {life: 42}
end
end
diff --git a/spec/ruby/core/fiber/transfer_spec.rb b/spec/ruby/core/fiber/transfer_spec.rb
new file mode 100644
index 0000000000..238721475d
--- /dev/null
+++ b/spec/ruby/core/fiber/transfer_spec.rb
@@ -0,0 +1,84 @@
+require_relative '../../spec_helper'
+require_relative 'shared/resume'
+
+describe "Fiber#transfer" do
+ it_behaves_like :fiber_resume, :transfer
+end
+
+describe "Fiber#transfer" do
+ 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 == :fiber2
+ end
+
+ it "returns to the root Fiber when finished" do
+ f1 = Fiber.new { :fiber_1 }
+ f2 = Fiber.new { f1.transfer; :fiber_2 }
+
+ f2.transfer.should == :fiber_1
+ f2.transfer.should == :fiber_2
+ end
+
+ it "can be invoked from the same Fiber it transfers control to" do
+ states = []
+ fiber = Fiber.new { states << :start; fiber.transfer; states << :end }
+ fiber.transfer
+ states.should == [:start, :end]
+
+ states = []
+ fiber = Fiber.new { states << :start; fiber.transfer; states << :end }
+ fiber.resume
+ states.should == [:start, :end]
+ end
+
+ 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
+
+ it "raises a FiberError when transferring to a Fiber which resumes itself" do
+ fiber = Fiber.new { fiber.resume }
+ -> { fiber.transfer }.should raise_error(FiberError)
+ end
+
+ it "works if Fibers in different Threads each transfer to a Fiber in the same Thread" do
+ # This catches a bug where Fibers are running on a thread-pool
+ # and Fibers from a different Ruby Thread reuse the same native thread.
+ # Caching the Ruby Thread based on the native thread is not correct in that case,
+ # and the check for "fiber called across threads" in Fiber#transfer
+ # might be incorrect based on that.
+ 2.times do
+ Thread.new do
+ io_fiber = Fiber.new do |calling_fiber|
+ calling_fiber.transfer
+ end
+ io_fiber.transfer(Fiber.current)
+ value = Object.new
+ io_fiber.transfer(value).should equal value
+ end.join
+ end
+ end
+
+ it "transfers control between a non-main thread's root fiber to a child fiber and back again" do
+ states = []
+ thread = Thread.new do
+ f1 = Fiber.new do |f0|
+ states << 0
+ value2 = f0.transfer(1)
+ states << value2
+ 3
+ end
+
+ value1 = f1.transfer(Fiber.current)
+ states << value1
+ value3 = f1.transfer(2)
+ states << value3
+ end
+ thread.join
+ states.should == [0, 1, 2, 3]
+ end
+end
diff --git a/spec/ruby/core/file/birthtime_spec.rb b/spec/ruby/core/file/birthtime_spec.rb
index 755601df64..f82eaf7cca 100644
--- a/spec/ruby/core/file/birthtime_spec.rb
+++ b/spec/ruby/core/file/birthtime_spec.rb
@@ -1,60 +1,56 @@
require_relative '../../spec_helper'
-describe "File.birthtime" do
- before :each do
- @file = __FILE__
- end
+platform_is :windows, :darwin, :freebsd, :netbsd, :linux do
+ not_implemented_messages = [
+ "birthtime() function is unimplemented", # unsupported OS/version
+ "birthtime is unimplemented", # unsupported filesystem
+ ]
+
+ describe "File.birthtime" do
+ before :each do
+ @file = __FILE__
+ end
- after :each do
- @file = nil
- end
+ after :each do
+ @file = nil
+ end
- platform_is :windows, :darwin, :freebsd, :netbsd do
it "returns the birth time for the named file as a Time object" do
File.birthtime(@file)
File.birthtime(@file).should be_kind_of(Time)
+ rescue NotImplementedError => e
+ e.message.should.start_with?(*not_implemented_messages)
end
it "accepts an object that has a #to_path method" do
+ File.birthtime(@file) # Avoid to failure of mock object with old Kernel and glibc
File.birthtime(mock_to_path(@file))
+ rescue NotImplementedError => e
+ e.message.should.start_with?(*not_implemented_messages)
end
it "raises an Errno::ENOENT exception if the file is not found" do
-> { File.birthtime('bogus') }.should raise_error(Errno::ENOENT)
+ rescue NotImplementedError => e
+ e.message.should.start_with?(*not_implemented_messages)
end
end
- platform_is :openbsd do
- it "raises an NotImplementedError" do
- -> { File.birthtime(@file) }.should raise_error(NotImplementedError)
+ describe "File#birthtime" do
+ before :each do
+ @file = File.open(__FILE__)
end
- end
-
- # TODO: depends on Linux kernel version
-end
-describe "File#birthtime" do
- before :each do
- @file = File.open(__FILE__)
- end
-
- after :each do
- @file.close
- @file = nil
- end
+ after :each do
+ @file.close
+ @file = nil
+ end
- platform_is :windows, :darwin, :freebsd, :netbsd do
it "returns the birth time for self" do
@file.birthtime
@file.birthtime.should be_kind_of(Time)
+ rescue NotImplementedError => e
+ e.message.should.start_with?(*not_implemented_messages)
end
end
-
- platform_is :openbsd do
- it "raises an NotImplementedError" do
- -> { @file.birthtime }.should raise_error(NotImplementedError)
- end
- end
-
- # TODO: depends on Linux kernel version
end
diff --git a/spec/ruby/core/file/chown_spec.rb b/spec/ruby/core/file/chown_spec.rb
index 8cc8f0d04b..4db0e3712c 100644
--- a/spec/ruby/core/file/chown_spec.rb
+++ b/spec/ruby/core/file/chown_spec.rb
@@ -78,15 +78,15 @@ describe "File.chown" do
end
describe "File#chown" do
- before :each do
- @fname = tmp('file_chown_test')
- @file = File.open(@fname, 'w')
- end
+ before :each do
+ @fname = tmp('file_chown_test')
+ @file = File.open(@fname, 'w')
+ end
- after :each do
- @file.close unless @file.closed?
- rm_r @fname
- end
+ after :each do
+ @file.close unless @file.closed?
+ rm_r @fname
+ end
as_superuser do
platform_is :windows do
diff --git a/spec/ruby/core/file/constants/constants_spec.rb b/spec/ruby/core/file/constants/constants_spec.rb
index 86946822c5..bba248c21e 100644
--- a/spec/ruby/core/file/constants/constants_spec.rb
+++ b/spec/ruby/core/file/constants/constants_spec.rb
@@ -4,7 +4,7 @@ require_relative '../../../spec_helper'
"FNM_DOTMATCH", "FNM_EXTGLOB", "FNM_NOESCAPE", "FNM_PATHNAME",
"FNM_SYSCASE", "LOCK_EX", "LOCK_NB", "LOCK_SH",
"LOCK_UN", "NONBLOCK", "RDONLY",
- "RDWR", "TRUNC", "WRONLY"].each do |const|
+ "RDWR", "TRUNC", "WRONLY", "SHARE_DELETE"].each do |const|
describe "File::Constants::#{const}" do
it "is defined" do
File::Constants.const_defined?(const).should be_true
diff --git a/spec/ruby/core/file/dirname_spec.rb b/spec/ruby/core/file/dirname_spec.rb
index 8dd6c4ca88..8e6016ce6f 100644
--- a/spec/ruby/core/file/dirname_spec.rb
+++ b/spec/ruby/core/file/dirname_spec.rb
@@ -11,34 +11,32 @@ describe "File.dirname" do
File.dirname('/foo/foo').should == '/foo'
end
- ruby_version_is '3.1' do
- context "when level is passed" 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, "negative level: -1")
- end
-
- it "returns '/' when level exceeds the number of segments in the path" do
- File.dirname("/home/jason", 100).should == '/'
- end
-
- it "calls #to_int if passed not numeric value" do
- object = Object.new
- def object.to_int; 2; end
-
- File.dirname("/a/b/c/d", object).should == '/a/b'
- end
+ context "when level is passed" 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, "negative level: -1")
+ end
+
+ it "returns '/' when level exceeds the number of segments in the path" do
+ File.dirname("/home/jason", 100).should == '/'
+ end
+
+ it "calls #to_int if passed not numeric value" do
+ object = Object.new
+ def object.to_int; 2; end
+
+ File.dirname("/a/b/c/d", object).should == '/a/b'
end
end
@@ -65,19 +63,19 @@ describe "File.dirname" do
end
it "returns all the components of filename except the last one (edge cases on all platforms)" do
- File.dirname("").should == "."
- File.dirname(".").should == "."
- File.dirname("./").should == "."
- File.dirname("./b/./").should == "./b"
- File.dirname("..").should == "."
- File.dirname("../").should == "."
- File.dirname("/").should == "/"
- File.dirname("/.").should == "/"
- File.dirname("/foo/").should == "/"
- File.dirname("/foo/.").should == "/foo"
- File.dirname("/foo/./").should == "/foo"
- File.dirname("/foo/../.").should == "/foo/.."
- File.dirname("foo/../").should == "foo"
+ File.dirname("").should == "."
+ File.dirname(".").should == "."
+ File.dirname("./").should == "."
+ File.dirname("./b/./").should == "./b"
+ File.dirname("..").should == "."
+ File.dirname("../").should == "."
+ File.dirname("/").should == "/"
+ File.dirname("/.").should == "/"
+ File.dirname("/foo/").should == "/"
+ File.dirname("/foo/.").should == "/foo"
+ File.dirname("/foo/./").should == "/foo"
+ File.dirname("/foo/../.").should == "/foo/.."
+ File.dirname("foo/../").should == "foo"
end
platform_is_not :windows do
diff --git a/spec/ruby/core/file/empty_spec.rb b/spec/ruby/core/file/empty_spec.rb
index 77f132303e..e8c9941676 100644
--- a/spec/ruby/core/file/empty_spec.rb
+++ b/spec/ruby/core/file/empty_spec.rb
@@ -4,10 +4,4 @@ require_relative '../../shared/file/zero'
describe "File.empty?" do
it_behaves_like :file_zero, :empty?, File
it_behaves_like :file_zero_missing, :empty?, File
-
- platform_is :solaris do
- it "returns false for /dev/null" do
- File.empty?('/dev/null').should == true
- end
- end
end
diff --git a/spec/ruby/core/file/exist_spec.rb b/spec/ruby/core/file/exist_spec.rb
index 2633376880..b5600e5b07 100644
--- a/spec/ruby/core/file/exist_spec.rb
+++ b/spec/ruby/core/file/exist_spec.rb
@@ -5,10 +5,8 @@ describe "File.exist?" do
it_behaves_like :file_exist, :exist?, File
end
-ruby_version_is "3.2" do
- describe "File.exists?" do
- it "has been removed" do
- File.should_not.respond_to?(:exists?)
- end
+describe "File.exists?" do
+ it "has been removed" do
+ File.should_not.respond_to?(:exists?)
end
end
diff --git a/spec/ruby/core/file/flock_spec.rb b/spec/ruby/core/file/flock_spec.rb
index 070d830bc4..23ddf89ed8 100644
--- a/spec/ruby/core/file/flock_spec.rb
+++ b/spec/ruby/core/file/flock_spec.rb
@@ -72,35 +72,3 @@ describe "File#flock" do
end
end
end
-
-platform_is :solaris do
- describe "File#flock on Solaris" do
- before :each do
- @name = tmp("flock_test")
- touch(@name)
-
- @read_file = File.open @name, "r"
- @write_file = File.open @name, "w"
- end
-
- after :each do
- @read_file.flock File::LOCK_UN
- @read_file.close
- @write_file.flock File::LOCK_UN
- @write_file.close
- rm_r @name
- end
-
- it "fails with EBADF acquiring exclusive lock on read-only File" do
- -> do
- @read_file.flock File::LOCK_EX
- end.should raise_error(Errno::EBADF)
- end
-
- it "fails with EBADF acquiring shared lock on read-only File" do
- -> do
- @write_file.flock File::LOCK_SH
- end.should raise_error(Errno::EBADF)
- end
- end
-end
diff --git a/spec/ruby/core/file/lchmod_spec.rb b/spec/ruby/core/file/lchmod_spec.rb
index 7420b95e4a..3c44374983 100644
--- a/spec/ruby/core/file/lchmod_spec.rb
+++ b/spec/ruby/core/file/lchmod_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
describe "File.lchmod" do
- platform_is_not :linux, :windows, :openbsd, :solaris, :aix do
+ platform_is_not :linux, :windows, :openbsd, :aix do
before :each do
@fname = tmp('file_chmod_test')
@lname = @fname + '.lnk'
diff --git a/spec/ruby/core/file/path_spec.rb b/spec/ruby/core/file/path_spec.rb
index dfa0c4ec02..726febcc2b 100644
--- a/spec/ruby/core/file/path_spec.rb
+++ b/spec/ruby/core/file/path_spec.rb
@@ -37,4 +37,45 @@ describe "File.path" do
path.should_receive(:to_path).and_return("abc")
File.path(path).should == "abc"
end
+
+ it "raises TypeError when #to_path result is not a string" do
+ path = mock("path")
+ path.should_receive(:to_path).and_return(nil)
+ -> { File.path(path) }.should raise_error TypeError
+
+ path = mock("path")
+ path.should_receive(:to_path).and_return(42)
+ -> { File.path(path) }.should raise_error TypeError
+ end
+
+ it "raises ArgumentError for string argument contains NUL character" do
+ -> { File.path("\0") }.should raise_error ArgumentError
+ -> { File.path("a\0") }.should raise_error ArgumentError
+ -> { File.path("a\0c") }.should raise_error ArgumentError
+ end
+
+ it "raises ArgumentError when #to_path result contains NUL character" do
+ path = mock("path")
+ path.should_receive(:to_path).and_return("\0")
+ -> { File.path(path) }.should raise_error ArgumentError
+
+ path = mock("path")
+ path.should_receive(:to_path).and_return("a\0")
+ -> { File.path(path) }.should raise_error ArgumentError
+
+ path = mock("path")
+ path.should_receive(:to_path).and_return("a\0c")
+ -> { File.path(path) }.should raise_error ArgumentError
+ end
+
+ it "raises Encoding::CompatibilityError for ASCII-incompatible string argument" do
+ path = "abc".encode(Encoding::UTF_32BE)
+ -> { File.path(path) }.should raise_error Encoding::CompatibilityError
+ end
+
+ it "raises Encoding::CompatibilityError when #to_path result is ASCII-incompatible" do
+ path = mock("path")
+ path.should_receive(:to_path).and_return("abc".encode(Encoding::UTF_32BE))
+ -> { File.path(path) }.should raise_error Encoding::CompatibilityError
+ end
end
diff --git a/spec/ruby/core/file/setuid_spec.rb b/spec/ruby/core/file/setuid_spec.rb
index 281ef01ab9..9e5e86df61 100644
--- a/spec/ruby/core/file/setuid_spec.rb
+++ b/spec/ruby/core/file/setuid_spec.rb
@@ -26,10 +26,6 @@ describe "File.setuid?" do
platform_is_not :windows do
it "returns true when the gid bit is set" do
- platform_is :solaris do
- # Solaris requires execute bit before setting suid
- system "chmod u+x #{@name}"
- end
system "chmod u+s #{@name}"
File.setuid?(@name).should == true
diff --git a/spec/ruby/core/file/shared/path.rb b/spec/ruby/core/file/shared/path.rb
index aa2a64cf25..5a9fe1b0c5 100644
--- a/spec/ruby/core/file/shared/path.rb
+++ b/spec/ruby/core/file/shared/path.rb
@@ -77,18 +77,6 @@ describe :file_path, shared: true do
after :each do
rm_r @dir
end
-
- ruby_version_is ""..."3.1" do
- 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
end
end
end
diff --git a/spec/ruby/core/file/shared/update_time.rb b/spec/ruby/core/file/shared/update_time.rb
index 9c063a8e93..3fe7266a00 100644
--- a/spec/ruby/core/file/shared/update_time.rb
+++ b/spec/ruby/core/file/shared/update_time.rb
@@ -84,7 +84,7 @@ describe :update_time, shared: true do
end
platform_is :linux do
- platform_is wordsize: 64 do
+ platform_is pointer_size: 64 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 or 2486-07-02)" do
# https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#Inode_Timestamps
# "Therefore, timestamps should not overflow until May 2446."
diff --git a/spec/ruby/core/file/socket_spec.rb b/spec/ruby/core/file/socket_spec.rb
index 5d12e21f55..d3f4eb013a 100644
--- a/spec/ruby/core/file/socket_spec.rb
+++ b/spec/ruby/core/file/socket_spec.rb
@@ -1,42 +1,10 @@
require_relative '../../spec_helper'
require_relative '../../shared/file/socket'
-require 'socket'
describe "File.socket?" do
it_behaves_like :file_socket, :socket?, File
-end
-describe "File.socket?" do
it "returns false if file does not exist" do
File.socket?("I_am_a_bogus_file").should == false
end
-
- it "returns false if the file is not a socket" do
- filename = tmp("i_exist")
- touch(filename)
-
- File.socket?(filename).should == false
-
- rm_r filename
- end
-end
-
-platform_is_not :windows do
- describe "File.socket?" do
- before :each do
- # We need a really short name here.
- # On Linux the path length is limited to 107, see unix(7).
- @name = tmp("s")
- @server = UNIXServer.new @name
- end
-
- after :each do
- @server.close
- rm_r @name
- end
-
- it "returns true if the file is a socket" do
- File.socket?(@name).should == true
- end
- end
end
diff --git a/spec/ruby/core/file/stat/birthtime_spec.rb b/spec/ruby/core/file/stat/birthtime_spec.rb
index a727bbe566..9aa39297b2 100644
--- a/spec/ruby/core/file/stat/birthtime_spec.rb
+++ b/spec/ruby/core/file/stat/birthtime_spec.rb
@@ -1,27 +1,29 @@
require_relative '../../../spec_helper'
-describe "File::Stat#birthtime" do
- before :each do
- @file = tmp('i_exist')
- touch(@file) { |f| f.write "rubinius" }
- end
+platform_is(:windows, :darwin, :freebsd, :netbsd,
+ *ruby_version_is("4.0") { :linux },
+ ) do
+ not_implemented_messages = [
+ "birthtime() function is unimplemented", # unsupported OS/version
+ "birthtime is unimplemented", # unsupported filesystem
+ ]
- after :each do
- rm_r @file
- end
+ describe "File::Stat#birthtime" do
+ before :each do
+ @file = tmp('i_exist')
+ touch(@file) { |f| f.write "rubinius" }
+ end
+
+ after :each do
+ rm_r @file
+ end
- platform_is :windows, :darwin, :freebsd, :netbsd do
it "returns the birthtime of a File::Stat object" do
st = File.stat(@file)
st.birthtime.should be_kind_of(Time)
st.birthtime.should <= Time.now
- end
- end
-
- platform_is :linux, :openbsd do
- it "raises an NotImplementedError" do
- st = File.stat(@file)
- -> { st.birthtime }.should raise_error(NotImplementedError)
+ rescue NotImplementedError => e
+ e.message.should.start_with?(*not_implemented_messages)
end
end
end
diff --git a/spec/ruby/core/file/stat/rdev_major_spec.rb b/spec/ruby/core/file/stat/rdev_major_spec.rb
index f8a8d1b107..e08d19c03a 100644
--- a/spec/ruby/core/file/stat/rdev_major_spec.rb
+++ b/spec/ruby/core/file/stat/rdev_major_spec.rb
@@ -2,19 +2,12 @@ require_relative '../../../spec_helper'
describe "File::Stat#rdev_major" do
before :each do
- platform_is :solaris do
- @name = "/dev/zfs"
- end
- platform_is_not :solaris do
- @name = tmp("file.txt")
- touch(@name)
- end
+ @name = tmp("file.txt")
+ touch(@name)
end
after :each do
- platform_is_not :solaris do
- rm_r @name
- end
+ rm_r @name
end
platform_is_not :windows do
diff --git a/spec/ruby/core/file/stat/rdev_minor_spec.rb b/spec/ruby/core/file/stat/rdev_minor_spec.rb
index dc30c1f56c..ace5b8a732 100644
--- a/spec/ruby/core/file/stat/rdev_minor_spec.rb
+++ b/spec/ruby/core/file/stat/rdev_minor_spec.rb
@@ -2,19 +2,12 @@ require_relative '../../../spec_helper'
describe "File::Stat#rdev_minor" do
before :each do
- platform_is :solaris do
- @name = "/dev/zfs"
- end
- platform_is_not :solaris do
- @name = tmp("file.txt")
- touch(@name)
- end
+ @name = tmp("file.txt")
+ touch(@name)
end
after :each do
- platform_is_not :solaris do
- rm_r @name
- end
+ rm_r @name
end
platform_is_not :windows do
diff --git a/spec/ruby/core/file/zero_spec.rb b/spec/ruby/core/file/zero_spec.rb
index 63dd85ee46..01c7505ef2 100644
--- a/spec/ruby/core/file/zero_spec.rb
+++ b/spec/ruby/core/file/zero_spec.rb
@@ -4,10 +4,4 @@ require_relative '../../shared/file/zero'
describe "File.zero?" do
it_behaves_like :file_zero, :zero?, File
it_behaves_like :file_zero_missing, :zero?, File
-
- platform_is :solaris do
- it "returns false for /dev/null" do
- File.zero?('/dev/null').should == true
- end
- end
end
diff --git a/spec/ruby/core/filetest/exist_spec.rb b/spec/ruby/core/filetest/exist_spec.rb
index a95d3f91a1..612ffa9fcb 100644
--- a/spec/ruby/core/filetest/exist_spec.rb
+++ b/spec/ruby/core/filetest/exist_spec.rb
@@ -5,10 +5,8 @@ describe "FileTest.exist?" do
it_behaves_like :file_exist, :exist?, FileTest
end
-ruby_version_is "3.2" do
- describe "FileTest.exists?" do
- it "has been removed" do
- FileTest.should_not.respond_to?(:exists?)
- end
+describe "FileTest.exists?" do
+ it "has been removed" do
+ FileTest.should_not.respond_to?(:exists?)
end
end
diff --git a/spec/ruby/core/filetest/socket_spec.rb b/spec/ruby/core/filetest/socket_spec.rb
index 63a6a31ecb..f274be6318 100644
--- a/spec/ruby/core/filetest/socket_spec.rb
+++ b/spec/ruby/core/filetest/socket_spec.rb
@@ -3,4 +3,8 @@ require_relative '../../shared/file/socket'
describe "FileTest.socket?" do
it_behaves_like :file_socket, :socket?, FileTest
+
+ it "returns false if file does not exist" do
+ FileTest.socket?("I_am_a_bogus_file").should == false
+ end
end
diff --git a/spec/ruby/core/filetest/zero_spec.rb b/spec/ruby/core/filetest/zero_spec.rb
index dd6a164ec9..92cab67f1b 100644
--- a/spec/ruby/core/filetest/zero_spec.rb
+++ b/spec/ruby/core/filetest/zero_spec.rb
@@ -4,10 +4,4 @@ require_relative '../../shared/file/zero'
describe "FileTest.zero?" do
it_behaves_like :file_zero, :zero?, FileTest
it_behaves_like :file_zero_missing, :zero?, FileTest
-
- platform_is :solaris do
- it "returns false for /dev/null" do
- File.zero?('/dev/null').should == true
- end
- end
end
diff --git a/spec/ruby/core/float/ceil_spec.rb b/spec/ruby/core/float/ceil_spec.rb
index 7fc18d304c..75f5610292 100644
--- a/spec/ruby/core/float/ceil_spec.rb
+++ b/spec/ruby/core/float/ceil_spec.rb
@@ -1,6 +1,11 @@
require_relative '../../spec_helper'
+require_relative '../integer/shared/integer_ceil_precision'
describe "Float#ceil" do
+ context "with precision" do
+ it_behaves_like :integer_ceil_precision, :Float
+ end
+
it "returns the smallest Integer greater than or equal to self" do
-1.2.ceil.should eql( -1)
-1.0.ceil.should eql( -1)
diff --git a/spec/ruby/core/float/comparison_spec.rb b/spec/ruby/core/float/comparison_spec.rb
index 1373b3a1fb..0cd290f4ad 100644
--- a/spec/ruby/core/float/comparison_spec.rb
+++ b/spec/ruby/core/float/comparison_spec.rb
@@ -72,7 +72,7 @@ describe "Float#<=>" 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
+ it "returns 0 when self is Infinity and other is infinite?=1" do
obj = Object.new
def obj.infinite?
1
@@ -91,7 +91,7 @@ describe "Float#<=>" do
it "returns 1 when self is Infinity and other is infinite?=nil (which means finite)" do
obj = Object.new
def obj.infinite?
- nil
+ nil
end
(infinity_value <=> obj).should == 1
end
diff --git a/spec/ruby/core/float/floor_spec.rb b/spec/ruby/core/float/floor_spec.rb
index 046216d36d..8b492ef473 100644
--- a/spec/ruby/core/float/floor_spec.rb
+++ b/spec/ruby/core/float/floor_spec.rb
@@ -1,6 +1,11 @@
require_relative '../../spec_helper'
+require_relative '../integer/shared/integer_floor_precision'
describe "Float#floor" do
+ context "with precision" do
+ it_behaves_like :integer_floor_precision, :Float
+ end
+
it "returns the largest Integer less than or equal to self" do
-1.2.floor.should eql( -2)
-1.0.floor.should eql( -1)
diff --git a/spec/ruby/core/float/round_spec.rb b/spec/ruby/core/float/round_spec.rb
index 9b4c307f9d..7e8c792051 100644
--- a/spec/ruby/core/float/round_spec.rb
+++ b/spec/ruby/core/float/round_spec.rb
@@ -30,6 +30,11 @@ describe "Float#round" do
12.345678.round(3.999).should == 12.346
end
+ it "correctly rounds exact floats with a numerous digits in a fraction part" do
+ 0.8241000000000004.round(10).should == 0.8241
+ 0.8241000000000002.round(10).should == 0.8241
+ end
+
it "returns zero when passed a negative argument with magnitude greater than magnitude of the whole number portion of the Float" do
0.8346268.round(-1).should eql(0)
end
@@ -68,6 +73,10 @@ describe "Float#round" do
0.42.round(2.0**30).should == 0.42
end
+ it "returns rounded values for not so big argument" do
+ 0.42.round(2.0**23).should == 0.42
+ end
+
it "returns big values rounded to nearest" do
+2.5e20.round(-20).should eql( +3 * 10 ** 20 )
-2.5e20.round(-20).should eql( -3 * 10 ** 20 )
diff --git a/spec/ruby/core/gc/config_spec.rb b/spec/ruby/core/gc/config_spec.rb
new file mode 100644
index 0000000000..e20e8e4a16
--- /dev/null
+++ b/spec/ruby/core/gc/config_spec.rb
@@ -0,0 +1,83 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.4" do
+ describe "GC.config" do
+ context "without arguments" do
+ it "returns a hash of current settings" do
+ GC.config.should be_kind_of(Hash)
+ end
+
+ it "includes the name of currently loaded GC implementation as a global key" do
+ GC.config.should include(:implementation)
+ GC.config[:implementation].should be_kind_of(String)
+ end
+ end
+
+ context "with a hash of options" do
+ it "allows to set GC implementation's options, returning the new config" do
+ config = GC.config({})
+ # Try to find a boolean setting to reliably test changing it.
+ key, _value = config.find { |_k, v| v == true }
+ skip unless key
+
+ GC.config(key => false).should == config.merge(key => false)
+ GC.config[key].should == false
+ GC.config(key => true).should == config
+ GC.config[key].should == true
+ ensure
+ GC.config(config.except(:implementation))
+ end
+
+ it "does not change settings that aren't present in the hash" do
+ previous = GC.config
+ GC.config({})
+ GC.config.should == previous
+ end
+
+ it "ignores unknown keys" do
+ previous = GC.config
+ GC.config(foo: "bar")
+ GC.config.should == previous
+ end
+
+ it "raises an ArgumentError if options include global keys" do
+ -> { GC.config(implementation: "default") }.should raise_error(ArgumentError, 'Attempting to set read-only key "Implementation"')
+ end
+ end
+
+ context "with a non-hash argument" do
+ it "returns current settings if argument is nil" do
+ GC.config(nil).should == GC.config
+ end
+
+ it "raises ArgumentError for all other arguments" do
+ -> { GC.config([]) }.should raise_error(ArgumentError)
+ -> { GC.config("default") }.should raise_error(ArgumentError)
+ -> { GC.config(1) }.should raise_error(ArgumentError)
+ end
+ end
+
+ guard -> { PlatformGuard.standard? && GC.config[:implementation] == "default" } do
+ context "with default GC implementation on MRI" do
+ before do
+ @default_config = GC.config({})
+ end
+
+ after do
+ GC.config(@default_config.except(:implementation))
+ end
+
+ it "includes :rgengc_allow_full_mark option, true by default" do
+ GC.config.should include(:rgengc_allow_full_mark)
+ GC.config[:rgengc_allow_full_mark].should be_true
+ end
+
+ it "allows to set :rgengc_allow_full_mark" do
+ # This key maps truthy and falsey values to true and false.
+ GC.config(rgengc_allow_full_mark: nil).should == @default_config.merge(rgengc_allow_full_mark: false)
+ GC.config(rgengc_allow_full_mark: 1.23).should == @default_config.merge(rgengc_allow_full_mark: true)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/gc/measure_total_time_spec.rb b/spec/ruby/core/gc/measure_total_time_spec.rb
index 05d4598ebc..f5377c18fd 100644
--- a/spec/ruby/core/gc/measure_total_time_spec.rb
+++ b/spec/ruby/core/gc/measure_total_time_spec.rb
@@ -1,19 +1,17 @@
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
+describe "GC.measure_total_time" do
+ before :each do
+ @default = GC.measure_total_time
+ end
- after :each do
- GC.measure_total_time = @default
- 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
+ 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
diff --git a/spec/ruby/core/gc/total_time_spec.rb b/spec/ruby/core/gc/total_time_spec.rb
index fcc8f45a83..a8430fbe9a 100644
--- a/spec/ruby/core/gc/total_time_spec.rb
+++ b/spec/ruby/core/gc/total_time_spec.rb
@@ -1,15 +1,13 @@
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
+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
+ it "increases as collections are run" do
+ time_before = GC.total_time
+ GC.start
+ GC.total_time.should >= time_before
end
end
diff --git a/spec/ruby/core/hash/compact_spec.rb b/spec/ruby/core/hash/compact_spec.rb
index 76aa43949d..13371bce43 100644
--- a/spec/ruby/core/hash/compact_spec.rb
+++ b/spec/ruby/core/hash/compact_spec.rb
@@ -35,7 +35,7 @@ describe "Hash#compact" do
hash.compact.default_proc.should == pr
end
- it "retains compare_by_identity_flag" do
+ it "retains compare_by_identity flag" do
hash = {}.compare_by_identity
hash.compact.compare_by_identity?.should == true
hash[:a] = 1
diff --git a/spec/ruby/core/hash/constructor_spec.rb b/spec/ruby/core/hash/constructor_spec.rb
index 8d29773909..0f97f7b40e 100644
--- a/spec/ruby/core/hash/constructor_spec.rb
+++ b/spec/ruby/core/hash/constructor_spec.rb
@@ -103,14 +103,14 @@ describe "Hash.[]" do
HashSpecs::MyInitializerHash[Hash[1, 2]].should be_an_instance_of(HashSpecs::MyInitializerHash)
end
- it "removes the default value" do
+ it "does not retain the default value" do
hash = Hash.new(1)
Hash[hash].default.should be_nil
hash[:a] = 1
Hash[hash].default.should be_nil
end
- it "removes the default_proc" do
+ it "does not retain the default_proc" do
hash = Hash.new { |h, k| h[k] = [] }
Hash[hash].default_proc.should be_nil
hash[:a] = 1
@@ -118,10 +118,11 @@ describe "Hash.[]" do
end
ruby_version_is '3.3' do
- it "does not retain compare_by_identity_flag" do
- hash = {}.compare_by_identity
+ it "does not retain compare_by_identity flag" do
+ hash = { a: 1 }.compare_by_identity
Hash[hash].compare_by_identity?.should == false
- hash[:a] = 1
+
+ hash = {}.compare_by_identity
Hash[hash].compare_by_identity?.should == false
end
end
diff --git a/spec/ruby/core/hash/element_reference_spec.rb b/spec/ruby/core/hash/element_reference_spec.rb
index 94e8237839..d5859cb342 100644
--- a/spec/ruby/core/hash/element_reference_spec.rb
+++ b/spec/ruby/core/hash/element_reference_spec.rb
@@ -12,7 +12,7 @@ describe "Hash#[]" do
h[[]].should == "baz"
end
- it "returns nil as default default value" do
+ it "returns nil as default value" do
{ 0 => 0 }[5].should == nil
end
diff --git a/spec/ruby/core/hash/except_spec.rb b/spec/ruby/core/hash/except_spec.rb
index ac84f9975c..026e454b13 100644
--- a/spec/ruby/core/hash/except_spec.rb
+++ b/spec/ruby/core/hash/except_spec.rb
@@ -19,14 +19,24 @@ describe "Hash#except" 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
+ it "does not retain the default value" do
+ h = Hash.new(1)
+ h.except(:a).default.should be_nil
+ h[:a] = 1
+ h.except(:a).default.should be_nil
+ end
+
+ it "does not retain the default_proc" do
+ pr = proc { |h, k| h[k] = [] }
+ h = Hash.new(&pr)
+ h.except(:a).default_proc.should be_nil
+ h[:a] = 1
+ h.except(:a).default_proc.should be_nil
+ end
+
+ it "retains compare_by_identity flag" do
+ h = { a: 9, c: 4 }.compare_by_identity
+ h2 = h.except(:a)
+ h2.compare_by_identity?.should == true
end
end
diff --git a/spec/ruby/core/hash/hash_spec.rb b/spec/ruby/core/hash/hash_spec.rb
index 19eb806dc4..cd67f7a652 100644
--- a/spec/ruby/core/hash/hash_spec.rb
+++ b/spec/ruby/core/hash/hash_spec.rb
@@ -42,12 +42,10 @@ describe "Hash#hash" do
# Like above, because h.eql?(x: [h])
end
- ruby_version_is "3.1" do
- it "allows omitting values" do
- a = 1
- b = 2
+ it "allows omitting values" do
+ a = 1
+ b = 2
- eval('{a:, b:}.should == { a: 1, b: 2 }')
- end
+ {a:, b:}.should == { a: 1, b: 2 }
end
end
diff --git a/spec/ruby/core/hash/invert_spec.rb b/spec/ruby/core/hash/invert_spec.rb
index 73377a9e97..c06e15ff7c 100644
--- a/spec/ruby/core/hash/invert_spec.rb
+++ b/spec/ruby/core/hash/invert_spec.rb
@@ -24,4 +24,25 @@ describe "Hash#invert" do
HashSpecs::MyHash[1 => 2, 3 => 4].invert.class.should == Hash
HashSpecs::MyHash[].invert.class.should == Hash
end
+
+ it "does not retain the default value" do
+ h = Hash.new(1)
+ h.invert.default.should be_nil
+ h[:a] = 1
+ h.invert.default.should be_nil
+ end
+
+ it "does not retain the default_proc" do
+ pr = proc { |h, k| h[k] = [] }
+ h = Hash.new(&pr)
+ h.invert.default_proc.should be_nil
+ h[:a] = 1
+ h.invert.default_proc.should be_nil
+ end
+
+ it "does not retain compare_by_identity flag" do
+ h = { a: 9, c: 4 }.compare_by_identity
+ h2 = h.invert
+ h2.compare_by_identity?.should == false
+ end
end
diff --git a/spec/ruby/core/hash/merge_spec.rb b/spec/ruby/core/hash/merge_spec.rb
index 5521864297..6710d121ef 100644
--- a/spec/ruby/core/hash/merge_spec.rb
+++ b/spec/ruby/core/hash/merge_spec.rb
@@ -93,6 +93,29 @@ describe "Hash#merge" do
merged.should eql(hash)
merged.should_not equal(hash)
end
+
+ it "retains the default value" do
+ h = Hash.new(1)
+ h.merge(b: 1, d: 2).default.should == 1
+ end
+
+ it "retains the default_proc" do
+ pr = proc { |h, k| h[k] = [] }
+ h = Hash.new(&pr)
+ h.merge(b: 1, d: 2).default_proc.should == pr
+ end
+
+ it "retains compare_by_identity flag" do
+ h = { a: 9, c: 4 }.compare_by_identity
+ h2 = h.merge(b: 1, d: 2)
+ h2.compare_by_identity?.should == true
+ end
+
+ it "ignores compare_by_identity flag of an argument" do
+ h = { a: 9, c: 4 }.compare_by_identity
+ h2 = { b: 1, d: 2 }.merge(h)
+ h2.compare_by_identity?.should == false
+ end
end
describe "Hash#merge!" do
diff --git a/spec/ruby/core/hash/new_spec.rb b/spec/ruby/core/hash/new_spec.rb
index 6279815fd6..5ae3e1f98d 100644
--- a/spec/ruby/core/hash/new_spec.rb
+++ b/spec/ruby/core/hash/new_spec.rb
@@ -34,7 +34,7 @@ describe "Hash.new" do
-> { Hash.new(nil) { 0 } }.should raise_error(ArgumentError)
end
- ruby_version_is "3.3" do
+ ruby_version_is "3.3"..."3.4" do
it "emits a deprecation warning if keyword arguments are passed" do
-> { Hash.new(unknown: true) }.should complain(
Regexp.new(Regexp.escape("Calling Hash.new with keyword arguments is deprecated and will be removed in Ruby 3.4; use Hash.new({ key: value }) instead"))
@@ -46,4 +46,22 @@ describe "Hash.new" do
Hash.new({ unknown: true }).default.should == { unknown: true }
end
end
+
+ ruby_version_is "3.4" do
+ it "accepts a capacity: argument" do
+ Hash.new(5, capacity: 42).default.should == 5
+ Hash.new(capacity: 42).default.should == nil
+ (Hash.new(capacity: 42) { 1 }).default_proc.should_not == nil
+ end
+
+ it "ignores negative capacity" do
+ -> { Hash.new(capacity: -42) }.should_not raise_error
+ end
+
+ it "raises an error if unknown keyword arguments are passed" do
+ -> { Hash.new(unknown: true) }.should raise_error(ArgumentError)
+ -> { Hash.new(1, unknown: true) }.should raise_error(ArgumentError)
+ -> { Hash.new(unknown: true) { 0 } }.should raise_error(ArgumentError)
+ end
+ end
end
diff --git a/spec/ruby/core/hash/reject_spec.rb b/spec/ruby/core/hash/reject_spec.rb
index dd8e817237..8381fc7fc1 100644
--- a/spec/ruby/core/hash/reject_spec.rb
+++ b/spec/ruby/core/hash/reject_spec.rb
@@ -44,6 +44,27 @@ describe "Hash#reject" do
reject_pairs.should == reject_bang_pairs
end
+ it "does not retain the default value" do
+ h = Hash.new(1)
+ h.reject { false }.default.should be_nil
+ h[:a] = 1
+ h.reject { false }.default.should be_nil
+ end
+
+ it "does not retain the default_proc" do
+ pr = proc { |h, k| h[k] = [] }
+ h = Hash.new(&pr)
+ h.reject { false }.default_proc.should be_nil
+ h[:a] = 1
+ h.reject { false }.default_proc.should be_nil
+ end
+
+ it "retains compare_by_identity flag" do
+ h = { a: 9, c: 4 }.compare_by_identity
+ h2 = h.reject { |k, _| k == :a }
+ h2.compare_by_identity?.should == true
+ end
+
it_behaves_like :hash_iteration_no_block, :reject
it_behaves_like :enumeratorized_with_origin_size, :reject, { 1 => 2, 3 => 4, 5 => 6 }
end
diff --git a/spec/ruby/core/hash/replace_spec.rb b/spec/ruby/core/hash/replace_spec.rb
index 92b2118fd3..db30145e1a 100644
--- a/spec/ruby/core/hash/replace_spec.rb
+++ b/spec/ruby/core/hash/replace_spec.rb
@@ -1,7 +1,79 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-require_relative 'shared/replace'
describe "Hash#replace" do
- it_behaves_like :hash_replace, :replace
+ it "replaces the contents of self with other" do
+ h = { a: 1, b: 2 }
+ h.replace(c: -1, d: -2).should equal(h)
+ h.should == { c: -1, d: -2 }
+ end
+
+ it "tries to convert the passed argument to a hash using #to_hash" do
+ obj = mock('{1=>2,3=>4}')
+ obj.should_receive(:to_hash).and_return({ 1 => 2, 3 => 4 })
+
+ h = {}
+ h.replace(obj)
+ h.should == { 1 => 2, 3 => 4 }
+ end
+
+ it "calls to_hash on hash subclasses" do
+ h = {}
+ h.replace(HashSpecs::ToHashHash[1 => 2])
+ h.should == { 1 => 2 }
+ end
+
+ it "does not retain the default value" do
+ hash = Hash.new(1)
+ hash.replace(b: 2).default.should be_nil
+ end
+
+ it "transfers the default value of an argument" do
+ hash = Hash.new(1)
+ { a: 1 }.replace(hash).default.should == 1
+ end
+
+ it "does not retain the default_proc" do
+ pr = proc { |h, k| h[k] = [] }
+ hash = Hash.new(&pr)
+ hash.replace(b: 2).default_proc.should be_nil
+ end
+
+ it "transfers the default_proc of an argument" do
+ pr = proc { |h, k| h[k] = [] }
+ hash = Hash.new(&pr)
+ { a: 1 }.replace(hash).default_proc.should == pr
+ end
+
+ it "does not call the default_proc of an argument" do
+ hash_a = Hash.new { |h, k| k * 5 }
+ hash_b = Hash.new(-> { raise "Should not invoke lambda" })
+ hash_a.replace(hash_b)
+ hash_a.default.should == hash_b.default
+ end
+
+ it "transfers compare_by_identity flag of an argument" do
+ h = { a: 1, c: 3 }
+ h2 = { b: 2, d: 4 }.compare_by_identity
+ h.replace(h2)
+ h.compare_by_identity?.should == true
+ end
+
+ it "does not retain compare_by_identity flag" do
+ h = { a: 1, c: 3 }.compare_by_identity
+ h.replace(b: 2, d: 4)
+ h.compare_by_identity?.should == false
+ end
+
+ it "raises a FrozenError if called on a frozen instance that would not be modified" do
+ -> do
+ HashSpecs.frozen_hash.replace(HashSpecs.frozen_hash)
+ end.should raise_error(FrozenError)
+ end
+
+ it "raises a FrozenError if called on a frozen instance that is modified" do
+ -> do
+ HashSpecs.frozen_hash.replace(HashSpecs.empty_frozen_hash)
+ end.should raise_error(FrozenError)
+ end
end
diff --git a/spec/ruby/core/hash/shared/replace.rb b/spec/ruby/core/hash/shared/replace.rb
deleted file mode 100644
index bea64384bb..0000000000
--- a/spec/ruby/core/hash/shared/replace.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-describe :hash_replace, shared: true do
- it "replaces the contents of self with other" do
- h = { a: 1, b: 2 }
- h.send(@method, c: -1, d: -2).should equal(h)
- h.should == { c: -1, d: -2 }
- end
-
- it "tries to convert the passed argument to a hash using #to_hash" do
- obj = mock('{1=>2,3=>4}')
- obj.should_receive(:to_hash).and_return({ 1 => 2, 3 => 4 })
-
- h = {}
- h.send(@method, obj)
- h.should == { 1 => 2, 3 => 4 }
- end
-
- it "calls to_hash on hash subclasses" do
- h = {}
- h.send(@method, HashSpecs::ToHashHash[1 => 2])
- h.should == { 1 => 2 }
- end
-
- it "does not transfer default values" do
- hash_a = {}
- hash_b = Hash.new(5)
- hash_a.send(@method, hash_b)
- hash_a.default.should == 5
-
- hash_a = {}
- hash_b = Hash.new { |h, k| k * 2 }
- hash_a.send(@method, hash_b)
- hash_a.default(5).should == 10
-
- hash_a = Hash.new { |h, k| k * 5 }
- hash_b = Hash.new(-> { raise "Should not invoke lambda" })
- hash_a.send(@method, hash_b)
- hash_a.default.should == hash_b.default
- end
-
- 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(FrozenError)
- end
-
- 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(FrozenError)
- end
-end
diff --git a/spec/ruby/core/hash/shared/select.rb b/spec/ruby/core/hash/shared/select.rb
index 5170af50d6..fbeff07330 100644
--- a/spec/ruby/core/hash/shared/select.rb
+++ b/spec/ruby/core/hash/shared/select.rb
@@ -40,6 +40,27 @@ describe :hash_select, shared: true do
@empty.send(@method).should be_an_instance_of(Enumerator)
end
+ it "does not retain the default value" do
+ h = Hash.new(1)
+ h.send(@method) { true }.default.should be_nil
+ h[:a] = 1
+ h.send(@method) { true }.default.should be_nil
+ end
+
+ it "does not retain the default_proc" do
+ pr = proc { |h, k| h[k] = [] }
+ h = Hash.new(&pr)
+ h.send(@method) { true }.default_proc.should be_nil
+ h[:a] = 1
+ h.send(@method) { true }.default_proc.should be_nil
+ end
+
+ it "retains compare_by_identity flag" do
+ h = { a: 9, c: 4 }.compare_by_identity
+ h2 = h.send(@method) { |k, _| k == :a }
+ h2.compare_by_identity?.should == true
+ end
+
it_should_behave_like :hash_iteration_no_block
before :each do
diff --git a/spec/ruby/core/hash/shared/store.rb b/spec/ruby/core/hash/shared/store.rb
index dd1bb52bac..72a462a42f 100644
--- a/spec/ruby/core/hash/shared/store.rb
+++ b/spec/ruby/core/hash/shared/store.rb
@@ -91,9 +91,9 @@ describe :hash_store, shared: true do
end
it "does not raise an exception if changing the value of an existing key during iteration" do
- hash = {1 => 2, 3 => 4, 5 => 6}
- hash.each { hash.send(@method, 1, :foo) }
- hash.should == {1 => :foo, 3 => 4, 5 => 6}
+ hash = {1 => 2, 3 => 4, 5 => 6}
+ 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
diff --git a/spec/ruby/core/hash/shared/to_s.rb b/spec/ruby/core/hash/shared/to_s.rb
index 7864d7cd4c..e116b8878b 100644
--- a/spec/ruby/core/hash/shared/to_s.rb
+++ b/spec/ruby/core/hash/shared/to_s.rb
@@ -4,14 +4,8 @@ require_relative '../fixtures/classes'
describe :hash_to_s, shared: true do
it "returns a string representation with same order as each()" do
h = { a: [1, 2], b: -2, d: -6, nil => nil }
-
- pairs = []
- h.each do |key, value|
- pairs << key.inspect + '=>' + value.inspect
- end
-
- str = '{' + pairs.join(', ') + '}'
- h.send(@method).should == str
+ expected = ruby_version_is("3.4") ? "{a: [1, 2], b: -2, d: -6, nil => nil}" : "{:a=>[1, 2], :b=>-2, :d=>-6, nil=>nil}"
+ h.send(@method).should == expected
end
it "calls #inspect on keys and values" do
@@ -19,31 +13,31 @@ describe :hash_to_s, shared: true do
val = mock('val')
key.should_receive(:inspect).and_return('key')
val.should_receive(:inspect).and_return('val')
-
- { key => val }.send(@method).should == '{key=>val}'
+ expected = ruby_version_is("3.4") ? "{key => val}" : "{key=>val}"
+ { key => val }.send(@method).should == expected
end
it "does not call #to_s on a String returned from #inspect" do
str = +"abc"
str.should_not_receive(:to_s)
-
- { a: str }.send(@method).should == '{:a=>"abc"}'
+ expected = ruby_version_is("3.4") ? '{a: "abc"}' : '{:a=>"abc"}'
+ { a: str }.send(@method).should == expected
end
it "calls #to_s on the object returned from #inspect if the Object isn't a String" do
obj = mock("Hash#inspect/to_s calls #to_s")
obj.should_receive(:inspect).and_return(obj)
obj.should_receive(:to_s).and_return("abc")
-
- { a: obj }.send(@method).should == "{:a=>abc}"
+ expected = ruby_version_is("3.4") ? "{a: abc}" : "{:a=>abc}"
+ { a: obj }.send(@method).should == expected
end
it "does not call #to_str on the object returned from #inspect when it is not a String" do
obj = mock("Hash#inspect/to_s does not call #to_str")
obj.should_receive(:inspect).and_return(obj)
obj.should_not_receive(:to_str)
-
- { a: obj }.send(@method).should =~ /^\{:a=>#<MockObject:0x[0-9a-f]+>\}$/
+ expected_pattern = ruby_version_is("3.4") ? /^\{a: #<MockObject:0x[0-9a-f]+>\}$/ : /^\{:a=>#<MockObject:0x[0-9a-f]+>\}$/
+ { a: obj }.send(@method).should =~ expected_pattern
end
it "does not call #to_str on the object returned from #to_s when it is not a String" do
@@ -51,8 +45,8 @@ describe :hash_to_s, shared: true do
obj.should_receive(:inspect).and_return(obj)
obj.should_receive(:to_s).and_return(obj)
obj.should_not_receive(:to_str)
-
- { a: obj }.send(@method).should =~ /^\{:a=>#<MockObject:0x[0-9a-f]+>\}$/
+ expected_pattern = ruby_version_is("3.4") ? /^\{a: #<MockObject:0x[0-9a-f]+>\}$/ : /^\{:a=>#<MockObject:0x[0-9a-f]+>\}$/
+ { a: obj }.send(@method).should =~ expected_pattern
end
it "does not swallow exceptions raised by #to_s" do
@@ -66,24 +60,34 @@ describe :hash_to_s, shared: true do
it "handles hashes with recursive values" do
x = {}
x[0] = x
- x.send(@method).should == '{0=>{...}}'
+ expected = ruby_version_is("3.4") ? '{0 => {...}}' : '{0=>{...}}'
+ x.send(@method).should == expected
x = {}
y = {}
x[0] = y
y[1] = x
- x.send(@method).should == "{0=>{1=>{...}}}"
- y.send(@method).should == "{1=>{0=>{...}}}"
+ expected_x = ruby_version_is("3.4") ? '{0 => {1 => {...}}}' : '{0=>{1=>{...}}}'
+ expected_y = ruby_version_is("3.4") ? '{1 => {0 => {...}}}' : '{1=>{0=>{...}}}'
+ x.send(@method).should == expected_x
+ y.send(@method).should == expected_y
end
it "does not raise if inspected result is not default external encoding" do
utf_16be = mock("utf_16be")
utf_16be.should_receive(:inspect).and_return(%<"utf_16be \u3042">.encode(Encoding::UTF_16BE))
-
- {a: utf_16be}.send(@method).should == '{:a=>"utf_16be \u3042"}'
+ expected = ruby_version_is("3.4") ? '{a: "utf_16be \u3042"}' : '{:a=>"utf_16be \u3042"}'
+ {a: utf_16be}.send(@method).should == expected
end
it "works for keys and values whose #inspect return a frozen String" do
- { true => false }.to_s.should == "{true=>false}"
+ expected = ruby_version_is("3.4") ? "{true => false}" : "{true=>false}"
+ { true => false }.to_s.should == expected
+ end
+
+ ruby_version_is "3.4" do
+ it "adds quotes to symbol keys that are not valid symbol literals" do
+ { "needs-quotes": 1 }.send(@method).should == '{"needs-quotes": 1}'
+ end
end
end
diff --git a/spec/ruby/core/hash/shift_spec.rb b/spec/ruby/core/hash/shift_spec.rb
index ea36488a04..3f31b9864c 100644
--- a/spec/ruby/core/hash/shift_spec.rb
+++ b/spec/ruby/core/hash/shift_spec.rb
@@ -30,45 +30,22 @@ describe "Hash#shift" do
h.should == {}
end
- ruby_version_is '3.2' do
- it "returns nil if the Hash is empty" do
- h = {}
- def h.default(key)
- raise
- end
- h.shift.should == nil
- end
- end
-
- ruby_version_is ''...'3.2' do
- it "calls #default with nil if the Hash is empty" do
- h = {}
- def h.default(key)
- key.should == nil
- :foo
- end
- h.shift.should == :foo
+ it "returns nil if the Hash is empty" do
+ h = {}
+ def h.default(key)
+ raise
end
+ h.shift.should == nil
end
it "returns nil from an empty hash" do
{}.shift.should == nil
end
- ruby_version_is '3.2' do
- it "returns nil for empty hashes with defaults and default procs" do
- Hash.new(5).shift.should == nil
- h = Hash.new { |*args| args }
- h.shift.should == nil
- end
- end
-
- ruby_version_is ''...'3.2' do
- it "returns (computed) default for empty hashes" do
- Hash.new(5).shift.should == 5
- h = Hash.new { |*args| args }
- h.shift.should == [h, nil]
- end
+ it "returns nil for empty hashes with defaults and default procs" do
+ Hash.new(5).shift.should == nil
+ h = Hash.new { |*args| args }
+ h.shift.should == nil
end
it "preserves Hash invariants when removing the last item" do
diff --git a/spec/ruby/core/hash/slice_spec.rb b/spec/ruby/core/hash/slice_spec.rb
index e3046d83d7..4fcc01f9a6 100644
--- a/spec/ruby/core/hash/slice_spec.rb
+++ b/spec/ruby/core/hash/slice_spec.rb
@@ -50,4 +50,25 @@ describe "Hash#slice" do
ScratchPad.recorded.should == []
end
+
+ it "does not retain the default value" do
+ h = Hash.new(1)
+ h.slice(:a).default.should be_nil
+ h[:a] = 1
+ h.slice(:a).default.should be_nil
+ end
+
+ it "does not retain the default_proc" do
+ pr = proc { |h, k| h[k] = [] }
+ h = Hash.new(&pr)
+ h.slice(:a).default_proc.should be_nil
+ h[:a] = 1
+ h.slice(:a).default_proc.should be_nil
+ end
+
+ it "retains compare_by_identity flag" do
+ h = { a: 9, c: 4 }.compare_by_identity
+ h2 = h.slice(:a)
+ h2.compare_by_identity?.should == true
+ end
end
diff --git a/spec/ruby/core/hash/to_h_spec.rb b/spec/ruby/core/hash/to_h_spec.rb
index 75ebce68b1..f84fd7b503 100644
--- a/spec/ruby/core/hash/to_h_spec.rb
+++ b/spec/ruby/core/hash/to_h_spec.rb
@@ -19,17 +19,22 @@ describe "Hash#to_h" do
@h[:foo].should == :bar
end
- it "copies the default" do
+ it "retains the default" do
@h.default = 42
@h.to_h.default.should == 42
@h[:hello].should == 42
end
- it "copies the default_proc" do
+ it "retains the default_proc" do
@h.default_proc = prc = Proc.new{ |h, k| h[k] = 2 * k }
@h.to_h.default_proc.should == prc
@h[42].should == 84
end
+
+ it "retains compare_by_identity flag" do
+ @h.compare_by_identity
+ @h.to_h.compare_by_identity?.should == true
+ end
end
context "with block" do
@@ -37,6 +42,16 @@ describe "Hash#to_h" do
{ a: 1, b: 2 }.to_h { |k, v| [k.to_s, v*v]}.should == { "a" => 1, "b" => 4 }
end
+ it "passes to a block each pair's key and value as separate arguments" do
+ ScratchPad.record []
+ { a: 1, b: 2 }.to_h { |k, v| ScratchPad << [k, v]; [k, v] }
+ ScratchPad.recorded.sort.should == [[:a, 1], [:b, 2]]
+
+ ScratchPad.record []
+ { a: 1, b: 2 }.to_h { |*args| ScratchPad << args; [args[0], args[1]] }
+ ScratchPad.recorded.sort.should == [[:a, 1], [:b, 2]]
+ 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] }
@@ -68,5 +83,24 @@ describe "Hash#to_h" do
{ a: 1 }.to_h { |k| x }
end.should raise_error(TypeError, /wrong element type MockObject/)
end
+
+ it "does not retain the default value" do
+ h = Hash.new(1)
+ h2 = h.to_h { |k, v| [k.to_s, v*v]}
+ h2.default.should be_nil
+ end
+
+ it "does not retain the default_proc" do
+ pr = proc { |h, k| h[k] = [] }
+ h = Hash.new(&pr)
+ h2 = h.to_h { |k, v| [k.to_s, v*v]}
+ h2.default_proc.should be_nil
+ end
+
+ it "does not retain compare_by_identity flag" do
+ h = { a: 9, c: 4 }.compare_by_identity
+ h2 = h.to_h { |k, v| [k.to_s, v*v]}
+ h2.compare_by_identity?.should == false
+ end
end
end
diff --git a/spec/ruby/core/hash/transform_keys_spec.rb b/spec/ruby/core/hash/transform_keys_spec.rb
index 2fbb17a8e2..e2eeab1813 100644
--- a/spec/ruby/core/hash/transform_keys_spec.rb
+++ b/spec/ruby/core/hash/transform_keys_spec.rb
@@ -54,6 +54,27 @@ describe "Hash#transform_keys" do
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
+
+ it "does not retain the default value" do
+ h = Hash.new(1)
+ h.transform_keys(&:succ).default.should be_nil
+ h[:a] = 1
+ h.transform_keys(&:succ).default.should be_nil
+ end
+
+ it "does not retain the default_proc" do
+ pr = proc { |h, k| h[k] = [] }
+ h = Hash.new(&pr)
+ h.transform_values(&:succ).default_proc.should be_nil
+ h[:a] = 1
+ h.transform_values(&:succ).default_proc.should be_nil
+ end
+
+ it "does not retain compare_by_identity flag" do
+ h = { a: 9, c: 4 }.compare_by_identity
+ h2 = h.transform_keys(&:succ)
+ h2.compare_by_identity?.should == false
+ end
end
describe "Hash#transform_keys!" do
@@ -76,24 +97,12 @@ describe "Hash#transform_keys!" do
@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 break 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 "3.0.2" do
- it "returns the processed keys and non evaluated keys if we break from the block" do
- @hash.transform_keys! do |v|
- break if v == :c
- v.succ
- end
- @hash.should == { b: 1, c: 2, d: 4 }
+ it "returns the processed keys and non evaluated keys if we break 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
it "keeps later pair if new keys conflict" do
@@ -129,7 +138,7 @@ describe "Hash#transform_keys!" do
end
it "raises a FrozenError on hash argument" do
- ->{ @hash.transform_keys!({ a: :A, b: :B, c: :C }) }.should raise_error(FrozenError)
+ ->{ @hash.transform_keys!({ a: :A, b: :B, c: :C }) }.should raise_error(FrozenError)
end
context "when no block is given" do
diff --git a/spec/ruby/core/hash/transform_values_spec.rb b/spec/ruby/core/hash/transform_values_spec.rb
index acb469416a..4a0ae8a5a5 100644
--- a/spec/ruby/core/hash/transform_values_spec.rb
+++ b/spec/ruby/core/hash/transform_values_spec.rb
@@ -39,6 +39,27 @@ describe "Hash#transform_values" do
r[:foo].should == 84
r.class.should == Hash
end
+
+ it "does not retain the default value" do
+ h = Hash.new(1)
+ h.transform_values(&:succ).default.should be_nil
+ h[:a] = 1
+ h.transform_values(&:succ).default.should be_nil
+ end
+
+ it "does not retain the default_proc" do
+ pr = proc { |h, k| h[k] = [] }
+ h = Hash.new(&pr)
+ h.transform_values(&:succ).default_proc.should be_nil
+ h[:a] = 1
+ h.transform_values(&:succ).default_proc.should be_nil
+ end
+
+ it "retains compare_by_identity flag" do
+ h = { a: 9, c: 4 }.compare_by_identity
+ h2 = h.transform_values(&:succ)
+ h2.compare_by_identity?.should == true
+ end
end
describe "Hash#transform_values!" do
diff --git a/spec/ruby/core/integer/ceil_spec.rb b/spec/ruby/core/integer/ceil_spec.rb
index 13bdaf838d..eb633fba78 100644
--- a/spec/ruby/core/integer/ceil_spec.rb
+++ b/spec/ruby/core/integer/ceil_spec.rb
@@ -1,11 +1,16 @@
require_relative '../../spec_helper'
require_relative 'shared/to_i'
require_relative 'shared/integer_rounding'
+require_relative 'shared/integer_ceil_precision'
describe "Integer#ceil" do
it_behaves_like :integer_to_i, :ceil
it_behaves_like :integer_rounding_positive_precision, :ceil
+ context "with precision" do
+ it_behaves_like :integer_ceil_precision, :Integer
+ end
+
context "precision argument specified as part of the ceil method is negative" do
it "returns the smallest integer greater than self with at least precision.abs trailing zeros" do
18.ceil(-1).should eql(20)
diff --git a/spec/ruby/core/integer/ceildiv_spec.rb b/spec/ruby/core/integer/ceildiv_spec.rb
index 18d07c66d0..c6e22a457d 100644
--- a/spec/ruby/core/integer/ceildiv_spec.rb
+++ b/spec/ruby/core/integer/ceildiv_spec.rb
@@ -1,22 +1,20 @@
require_relative '../../spec_helper'
describe "Integer#ceildiv" do
- ruby_version_is '3.2' do
- it "returns a quotient of division which is rounded up to the nearest integer" do
- 0.ceildiv(3).should eql(0)
- 1.ceildiv(3).should eql(1)
- 3.ceildiv(3).should eql(1)
- 4.ceildiv(3).should eql(2)
+ it "returns a quotient of division which is rounded up to the nearest integer" do
+ 0.ceildiv(3).should eql(0)
+ 1.ceildiv(3).should eql(1)
+ 3.ceildiv(3).should eql(1)
+ 4.ceildiv(3).should eql(2)
- 4.ceildiv(-3).should eql(-1)
- -4.ceildiv(3).should eql(-1)
- -4.ceildiv(-3).should eql(2)
+ 4.ceildiv(-3).should eql(-1)
+ -4.ceildiv(3).should eql(-1)
+ -4.ceildiv(-3).should eql(2)
- 3.ceildiv(1.2).should eql(3)
- 3.ceildiv(6/5r).should eql(3)
+ 3.ceildiv(1.2).should eql(3)
+ 3.ceildiv(6/5r).should eql(3)
- (10**100-11).ceildiv(10**99-1).should eql(10)
- (10**100-9).ceildiv(10**99-1).should eql(11)
- end
+ (10**100-11).ceildiv(10**99-1).should eql(10)
+ (10**100-9).ceildiv(10**99-1).should eql(11)
end
end
diff --git a/spec/ruby/core/integer/chr_spec.rb b/spec/ruby/core/integer/chr_spec.rb
index 8fe20ff812..39cafe2874 100644
--- a/spec/ruby/core/integer/chr_spec.rb
+++ b/spec/ruby/core/integer/chr_spec.rb
@@ -10,12 +10,12 @@ describe "Integer#chr without argument" do
end
it "raises a RangeError is self is less than 0" do
- -> { -1.chr }.should raise_error(RangeError)
- -> { (-bignum_value).chr }.should raise_error(RangeError)
+ -> { -1.chr }.should raise_error(RangeError, /-1 out of char range/)
+ -> { (-bignum_value).chr }.should raise_error(RangeError, /bignum out of char range/)
end
it "raises a RangeError if self is too large" do
- -> { 2206368128.chr(Encoding::UTF_8) }.should raise_error(RangeError)
+ -> { 2206368128.chr(Encoding::UTF_8) }.should raise_error(RangeError, /2206368128 out of char range/)
end
describe "when Encoding.default_internal is nil" do
@@ -48,8 +48,8 @@ describe "Integer#chr without argument" do
end
it "raises a RangeError is self is greater than 255" do
- -> { 256.chr }.should raise_error(RangeError)
- -> { bignum_value.chr }.should raise_error(RangeError)
+ -> { 256.chr }.should raise_error(RangeError, /256 out of char range/)
+ -> { bignum_value.chr }.should raise_error(RangeError, /bignum out of char range/)
end
end
@@ -137,7 +137,7 @@ describe "Integer#chr without argument" do
[620, "TIS-620"]
].each do |integer, encoding_name|
Encoding.default_internal = Encoding.find(encoding_name)
- -> { integer.chr }.should raise_error(RangeError)
+ -> { integer.chr }.should raise_error(RangeError, /(invalid codepoint|out of char range)/)
end
end
end
@@ -165,12 +165,12 @@ describe "Integer#chr with an encoding argument" do
# http://redmine.ruby-lang.org/issues/4869
it "raises a RangeError is self is less than 0" do
- -> { -1.chr(Encoding::UTF_8) }.should raise_error(RangeError)
- -> { (-bignum_value).chr(Encoding::EUC_JP) }.should raise_error(RangeError)
+ -> { -1.chr(Encoding::UTF_8) }.should raise_error(RangeError, /-1 out of char range/)
+ -> { (-bignum_value).chr(Encoding::EUC_JP) }.should raise_error(RangeError, /bignum out of char range/)
end
it "raises a RangeError if self is too large" do
- -> { 2206368128.chr(Encoding::UTF_8) }.should raise_error(RangeError)
+ -> { 2206368128.chr(Encoding::UTF_8) }.should raise_error(RangeError, /2206368128 out of char range/)
end
it "returns a String with the specified encoding" do
diff --git a/spec/ruby/core/integer/constants_spec.rb b/spec/ruby/core/integer/constants_spec.rb
index 2077ad451e..937806c72f 100644
--- a/spec/ruby/core/integer/constants_spec.rb
+++ b/spec/ruby/core/integer/constants_spec.rb
@@ -1,41 +1,13 @@
require_relative '../../spec_helper'
describe "Fixnum" do
- ruby_version_is ""..."3.2" do
- it "is unified into Integer" do
- suppress_warning do
- Fixnum.should equal(Integer)
- end
- end
-
- it "is deprecated" do
- -> { Fixnum }.should complain(/constant ::Fixnum is deprecated/)
- end
- end
-
- ruby_version_is "3.2" do
- it "is no longer defined" do
- Object.should_not.const_defined?(:Fixnum)
- end
+ it "is no longer defined" do
+ Object.should_not.const_defined?(:Fixnum)
end
end
describe "Bignum" do
- ruby_version_is ""..."3.2" do
- it "is unified into Integer" do
- suppress_warning do
- Bignum.should equal(Integer)
- end
- end
-
- it "is deprecated" do
- -> { Bignum }.should complain(/constant ::Bignum is deprecated/)
- end
- end
-
- ruby_version_is "3.2" do
- it "is no longer defined" do
- Object.should_not.const_defined?(:Bignum)
- end
+ it "is no longer defined" do
+ Object.should_not.const_defined?(:Bignum)
end
end
diff --git a/spec/ruby/core/integer/divide_spec.rb b/spec/ruby/core/integer/divide_spec.rb
index a878c4668c..0d5e16e986 100644
--- a/spec/ruby/core/integer/divide_spec.rb
+++ b/spec/ruby/core/integer/divide_spec.rb
@@ -12,6 +12,17 @@ describe "Integer#/" do
it "supports dividing negative numbers" do
(-1 / 10).should == -1
+ (-1 / 10**10).should == -1
+ (-1 / 10**20).should == -1
+ end
+
+ it "preservers sign correctly" do
+ (4 / 3).should == 1
+ (4 / -3).should == -2
+ (-4 / 3).should == -2
+ (-4 / -3).should == 1
+ (0 / -3).should == 0
+ (0 / 3).should == 0
end
it "returns result the same class as the argument" do
@@ -58,6 +69,15 @@ describe "Integer#/" do
((10**50) / -(10**40 + 1)).should == -10000000000
end
+ it "preservers sign correctly" do
+ (4 / bignum_value).should == 0
+ (4 / -bignum_value).should == -1
+ (-4 / bignum_value).should == -1
+ (-4 / -bignum_value).should == 0
+ (0 / bignum_value).should == 0
+ (0 / -bignum_value).should == 0
+ end
+
it "returns self divided by Float" do
not_supported_on :opal do
(bignum_value(88) / 4294967295.0).should be_close(4294967297.0, TOLERANCE)
@@ -86,4 +106,21 @@ describe "Integer#/" do
-> { @bignum / :symbol }.should raise_error(TypeError)
end
end
+
+ it "coerces the RHS and calls #coerce" do
+ obj = mock("integer plus")
+ obj.should_receive(:coerce).with(6).and_return([6, 3])
+ (6 / obj).should == 2
+ end
+
+ it "coerces the RHS and calls #coerce even if it's private" do
+ obj = Object.new
+ class << obj
+ private def coerce(n)
+ [n, 3]
+ end
+ end
+
+ (6 / obj).should == 2
+ end
end
diff --git a/spec/ruby/core/integer/floor_spec.rb b/spec/ruby/core/integer/floor_spec.rb
index aaa816fdc5..8fb84d58cb 100644
--- a/spec/ruby/core/integer/floor_spec.rb
+++ b/spec/ruby/core/integer/floor_spec.rb
@@ -1,19 +1,13 @@
require_relative '../../spec_helper'
require_relative 'shared/to_i'
require_relative 'shared/integer_rounding'
+require_relative 'shared/integer_floor_precision'
describe "Integer#floor" do
it_behaves_like :integer_to_i, :floor
it_behaves_like :integer_rounding_positive_precision, :floor
- context "precision argument specified as part of the floor method is negative" do
- it "returns the largest integer less than self with at least precision.abs trailing zeros" do
- 1832.floor(-1).should eql(1830)
- 1832.floor(-2).should eql(1800)
- 1832.floor(-3).should eql(1000)
- -1832.floor(-1).should eql(-1840)
- -1832.floor(-2).should eql(-1900)
- -1832.floor(-3).should eql(-2000)
- end
+ context "with precision" do
+ it_behaves_like :integer_floor_precision, :Integer
end
end
diff --git a/spec/ruby/core/integer/left_shift_spec.rb b/spec/ruby/core/integer/left_shift_spec.rb
index 0781371d93..86c2b18ae2 100644
--- a/spec/ruby/core/integer/left_shift_spec.rb
+++ b/spec/ruby/core/integer/left_shift_spec.rb
@@ -181,10 +181,8 @@ describe "Integer#<< (with n << m)" do
(bignum_value << -(2**40)).should == 0
end
- ruby_bug "#18517", ""..."3.2" do
- it "returns 0 when m > 0 long and n == 0" do
- (0 << (2**40)).should == 0
- end
+ it "returns 0 when m > 0 long and n == 0" do
+ (0 << (2**40)).should == 0
end
it "returns 0 when m > 0 bignum and n == 0" do
diff --git a/spec/ruby/core/integer/minus_spec.rb b/spec/ruby/core/integer/minus_spec.rb
index aadf416a05..6072ba7c8b 100644
--- a/spec/ruby/core/integer/minus_spec.rb
+++ b/spec/ruby/core/integer/minus_spec.rb
@@ -40,4 +40,21 @@ describe "Integer#-" do
-> { @bignum - :symbol }.should raise_error(TypeError)
end
end
+
+ it "coerces the RHS and calls #coerce" do
+ obj = mock("integer plus")
+ obj.should_receive(:coerce).with(5).and_return([5, 10])
+ (5 - obj).should == -5
+ end
+
+ it "coerces the RHS and calls #coerce even if it's private" do
+ obj = Object.new
+ class << obj
+ private def coerce(n)
+ [n, 10]
+ end
+ end
+
+ (5 - obj).should == -5
+ end
end
diff --git a/spec/ruby/core/integer/plus_spec.rb b/spec/ruby/core/integer/plus_spec.rb
index d01a76ab58..38428e56c5 100644
--- a/spec/ruby/core/integer/plus_spec.rb
+++ b/spec/ruby/core/integer/plus_spec.rb
@@ -55,4 +55,21 @@ describe "Integer#+" do
RUBY
ruby_exe(code).should == "-1"
end
+
+ it "coerces the RHS and calls #coerce" do
+ obj = mock("integer plus")
+ obj.should_receive(:coerce).with(6).and_return([6, 3])
+ (6 + obj).should == 9
+ end
+
+ it "coerces the RHS and calls #coerce even if it's private" do
+ obj = Object.new
+ class << obj
+ private def coerce(n)
+ [n, 3]
+ end
+ end
+
+ (6 + obj).should == 9
+ end
end
diff --git a/spec/ruby/core/integer/pow_spec.rb b/spec/ruby/core/integer/pow_spec.rb
index 4712911095..ecaca01eff 100644
--- a/spec/ruby/core/integer/pow_spec.rb
+++ b/spec/ruby/core/integer/pow_spec.rb
@@ -19,13 +19,13 @@ describe "Integer#pow" 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
+ 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
+ 2.pow(5, -12).should == -4
+ -2.pow(5, 12).should == 4
-2.pow(5, -12).should == -8
end
diff --git a/spec/ruby/core/integer/remainder_spec.rb b/spec/ruby/core/integer/remainder_spec.rb
index 96268b3af5..757e42fbe8 100644
--- a/spec/ruby/core/integer/remainder_spec.rb
+++ b/spec/ruby/core/integer/remainder_spec.rb
@@ -15,8 +15,8 @@ describe "Integer#remainder" do
end
it "keeps sign of self" do
- 5.remainder( 3).should == 2
- 5.remainder(-3).should == 2
+ 5.remainder( 3).should == 2
+ 5.remainder(-3).should == 2
-5.remainder( 3).should == -2
-5.remainder(-3).should == -2
end
diff --git a/spec/ruby/core/integer/right_shift_spec.rb b/spec/ruby/core/integer/right_shift_spec.rb
index e91613d8d1..c902674e2f 100644
--- a/spec/ruby/core/integer/right_shift_spec.rb
+++ b/spec/ruby/core/integer/right_shift_spec.rb
@@ -203,10 +203,8 @@ describe "Integer#>> (with n >> m)" do
(bignum_value >> (2**40)).should == 0
end
- ruby_bug "#18517", ""..."3.2" do
- it "returns 0 when m < 0 long and n == 0" do
- (0 >> -(2**40)).should == 0
- end
+ it "returns 0 when m < 0 long and n == 0" do
+ (0 >> -(2**40)).should == 0
end
it "returns 0 when m < 0 bignum and n == 0" do
diff --git a/spec/ruby/core/integer/round_spec.rb b/spec/ruby/core/integer/round_spec.rb
index 45ac126fd3..189384f11a 100644
--- a/spec/ruby/core/integer/round_spec.rb
+++ b/spec/ruby/core/integer/round_spec.rb
@@ -21,10 +21,8 @@ describe "Integer#round" do
(-25 * 10**70).round(-71).should eql(-30 * 10**70)
end
- platform_is_not wordsize: 32 do
- it "raises a RangeError when passed a big negative value" do
- -> { 42.round(fixnum_min) }.should raise_error(RangeError)
- end
+ it "raises a RangeError when passed a big negative value" do
+ -> { 42.round(min_long - 1) }.should raise_error(RangeError)
end
it "raises a RangeError when passed Float::INFINITY" do
diff --git a/spec/ruby/core/integer/shared/exponent.rb b/spec/ruby/core/integer/shared/exponent.rb
index 15df518b7e..5ef6d686d8 100644
--- a/spec/ruby/core/integer/shared/exponent.rb
+++ b/spec/ruby/core/integer/shared/exponent.rb
@@ -48,10 +48,18 @@ describe :integer_exponent, shared: true do
(-1).send(@method, 4611686018427387905).should eql(-1)
end
- it "returns Float::INFINITY when the number is too big" do
- -> {
- 2.send(@method, 427387904).should == Float::INFINITY
- }.should complain(/warning: in a\*\*b, b may be too big/)
+ ruby_version_is ""..."3.4" do
+ it "returns Float::INFINITY when the number is too big" do
+ -> {
+ 2.send(@method, 427387904).should == Float::INFINITY
+ }.should complain(/warning: in a\*\*b, b may be too big/)
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "raises an ArgumentError when the number is too big" do
+ -> { 100000000.send(@method, 1000000000) }.should raise_error(ArgumentError)
+ end
end
it "raises a ZeroDivisionError for 0 ** -1" do
@@ -108,13 +116,23 @@ describe :integer_exponent, shared: true do
-> { @bignum.send(@method, :symbol) }.should raise_error(TypeError)
end
- it "switch to a Float when the values is too big" do
- 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
+ ruby_version_is ""..."3.4" do
+ it "switch to a Float when the values is too big" do
+ 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
+ end
+
+ ruby_version_is "3.4" do
+ it "does not switch to a Float when the values is too big" do
+ -> {
+ @bignum.send(@method, @bignum)
+ }.should raise_error(ArgumentError)
+ end
end
it "returns a complex number when negative and raised to a fractional power" do
diff --git a/spec/ruby/core/integer/shared/integer_ceil_precision.rb b/spec/ruby/core/integer/shared/integer_ceil_precision.rb
new file mode 100644
index 0000000000..9f31c2cf61
--- /dev/null
+++ b/spec/ruby/core/integer/shared/integer_ceil_precision.rb
@@ -0,0 +1,43 @@
+describe :integer_ceil_precision, shared: true do
+ context "precision is zero" do
+ it "returns integer self" do
+ send(@method, 0).ceil(0).should.eql?(0)
+ send(@method, 123).ceil(0).should.eql?(123)
+ send(@method, -123).ceil(0).should.eql?(-123)
+ end
+ end
+
+ context "precision is positive" do
+ it "returns self" do
+ send(@method, 0).ceil(1).should.eql?(send(@method, 0))
+ send(@method, 0).ceil(10).should.eql?(send(@method, 0))
+
+ send(@method, 123).ceil(10).should.eql?(send(@method, 123))
+ send(@method, -123).ceil(10).should.eql?(send(@method, -123))
+ end
+ end
+
+ context "precision is negative" do
+ it "always returns 0 when self is 0" do
+ send(@method, 0).ceil(-1).should.eql?(0)
+ send(@method, 0).ceil(-10).should.eql?(0)
+ end
+
+ it "returns largest integer less than self with at least precision.abs trailing zeros" do
+ send(@method, 123).ceil(-1).should.eql?(130)
+ send(@method, 123).ceil(-2).should.eql?(200)
+ send(@method, 123).ceil(-3).should.eql?(1000)
+
+ send(@method, -123).ceil(-1).should.eql?(-120)
+ send(@method, -123).ceil(-2).should.eql?(-100)
+ send(@method, -123).ceil(-3).should.eql?(0)
+ end
+
+ ruby_bug "#20654", ""..."3.4" do
+ it "returns 10**precision.abs when precision.abs is larger than the number digits of self" do
+ send(@method, 123).ceil(-20).should.eql?(100000000000000000000)
+ send(@method, 123).ceil(-50).should.eql?(100000000000000000000000000000000000000000000000000)
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/integer/shared/integer_floor_precision.rb b/spec/ruby/core/integer/shared/integer_floor_precision.rb
new file mode 100644
index 0000000000..4c5888c6c4
--- /dev/null
+++ b/spec/ruby/core/integer/shared/integer_floor_precision.rb
@@ -0,0 +1,43 @@
+describe :integer_floor_precision, shared: true do
+ context "precision is zero" do
+ it "returns integer self" do
+ send(@method, 0).floor(0).should.eql?(0)
+ send(@method, 123).floor(0).should.eql?(123)
+ send(@method, -123).floor(0).should.eql?(-123)
+ end
+ end
+
+ context "precision is positive" do
+ it "returns self" do
+ send(@method, 0).floor(1).should.eql?(send(@method, 0))
+ send(@method, 0).floor(10).should.eql?(send(@method, 0))
+
+ send(@method, 123).floor(10).should.eql?(send(@method, 123))
+ send(@method, -123).floor(10).should.eql?(send(@method, -123))
+ end
+ end
+
+ context "precision is negative" do
+ it "always returns 0 when self is 0" do
+ send(@method, 0).floor(-1).should.eql?(0)
+ send(@method, 0).floor(-10).should.eql?(0)
+ end
+
+ it "returns largest integer less than self with at least precision.abs trailing zeros" do
+ send(@method, 123).floor(-1).should.eql?(120)
+ send(@method, 123).floor(-2).should.eql?(100)
+ send(@method, 123).floor(-3).should.eql?(0)
+
+ send(@method, -123).floor(-1).should.eql?(-130)
+ send(@method, -123).floor(-2).should.eql?(-200)
+ send(@method, -123).floor(-3).should.eql?(-1000)
+ end
+
+ ruby_bug "#20654", ""..."3.4" do
+ it "returns -(10**precision.abs) when self is negative and precision.abs is larger than the number digits of self" do
+ send(@method, -123).floor(-20).should.eql?(-100000000000000000000)
+ send(@method, -123).floor(-50).should.eql?(-100000000000000000000000000000000000000000000000000)
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/integer/shared/modulo.rb b/spec/ruby/core/integer/shared/modulo.rb
index f678a10806..d91af1e924 100644
--- a/spec/ruby/core/integer/shared/modulo.rb
+++ b/spec/ruby/core/integer/shared/modulo.rb
@@ -1,6 +1,12 @@
describe :integer_modulo, shared: true do
context "fixnum" do
it "returns the modulus obtained from dividing self by the given argument" do
+ # test all possible combinations:
+ # - integer/double/bignum argument
+ # - positive/negative argument
+ # - positive/negative self
+ # - self greater/smaller than argument
+
13.send(@method, 4).should == 1
4.send(@method, 13).should == 4
@@ -16,8 +22,22 @@ describe :integer_modulo, shared: true do
(200).send(@method, -256).should == -56
(1000).send(@method, -512).should == -24
+ 13.send(@method, -4.0).should == -3.0
+ 4.send(@method, -13.0).should == -9.0
+
+ -13.send(@method, -4.0).should == -1.0
+ -4.send(@method, -13.0).should == -4.0
+
+ -13.send(@method, 4.0).should == 3.0
+ -4.send(@method, 13.0).should == 9.0
+
1.send(@method, 2.0).should == 1.0
200.send(@method, bignum_value).should == 200
+
+ 4.send(@method, bignum_value(10)).should == 4
+ 4.send(@method, -bignum_value(10)).should == -18446744073709551622
+ -4.send(@method, bignum_value(10)).should == 18446744073709551622
+ -4.send(@method, -bignum_value(10)).should == -4
end
it "raises a ZeroDivisionError when the given argument is 0" do
@@ -44,15 +64,35 @@ describe :integer_modulo, shared: true do
context "bignum" do
before :each do
- @bignum = bignum_value
+ @bignum = bignum_value(10)
end
it "returns the modulus obtained from dividing self by the given argument" do
+ # test all possible combinations:
+ # - integer/double/bignum argument
+ # - positive/negative argument
+ # - positive/negative self
+ # - self greater/smaller than argument
+
@bignum.send(@method, 5).should == 1
@bignum.send(@method, -5).should == -4
- @bignum.send(@method, -100).should == -84
+ (-@bignum).send(@method, 5).should == 4
+ (-@bignum).send(@method, -5).should == -1
+
@bignum.send(@method, 2.22).should be_close(1.5603603603605034, TOLERANCE)
- @bignum.send(@method, bignum_value(10)).should == 18446744073709551616
+ @bignum.send(@method, -2.22).should be_close(-0.6596396396394968, TOLERANCE)
+ (-@bignum).send(@method, 2.22).should be_close(0.6596396396394968, TOLERANCE)
+ (-@bignum).send(@method, -2.22).should be_close(-1.5603603603605034, TOLERANCE)
+
+ @bignum.send(@method, @bignum + 10).should == 18446744073709551626
+ @bignum.send(@method, -(@bignum + 10)).should == -10
+ (-@bignum).send(@method, @bignum + 10).should == 10
+ (-@bignum).send(@method, -(@bignum + 10)).should == -18446744073709551626
+
+ (@bignum + 10).send(@method, @bignum).should == 10
+ (@bignum + 10).send(@method, -@bignum).should == -18446744073709551616
+ (-(@bignum + 10)).send(@method, @bignum).should == 18446744073709551616
+ (-(@bignum + 10)).send(@method, -@bignum).should == -10
end
it "raises a ZeroDivisionError when the given argument is 0" do
diff --git a/spec/ruby/core/integer/size_spec.rb b/spec/ruby/core/integer/size_spec.rb
index a134e82384..725e9eb062 100644
--- a/spec/ruby/core/integer/size_spec.rb
+++ b/spec/ruby/core/integer/size_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
describe "Integer#size" do
- platform_is wordsize: 32 do
+ platform_is c_long_size: 32 do
it "returns the number of bytes in the machine representation of self" do
-1.size.should == 4
0.size.should == 4
@@ -9,7 +9,7 @@ describe "Integer#size" do
end
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
it "returns the number of bytes in the machine representation of self" do
-1.size.should == 8
0.size.should == 8
diff --git a/spec/ruby/core/integer/try_convert_spec.rb b/spec/ruby/core/integer/try_convert_spec.rb
index 4bc7d3851a..8a0ca671a9 100644
--- a/spec/ruby/core/integer/try_convert_spec.rb
+++ b/spec/ruby/core/integer/try_convert_spec.rb
@@ -1,50 +1,48 @@
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
+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 "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 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 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, "can't convert MockObject to Integer (MockObject#to_int gives Object)")
- 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, "can't convert MockObject to Integer (MockObject#to_int gives Object)")
+ end
- it "responds with a different error message when it raises a TypeError, depending on the type of the non-Integer object :to_int returns" do
- obj = mock("to_int")
- obj.should_receive(:to_int).and_return("A String")
- -> {
- Integer.try_convert obj
- }.should raise_error(TypeError, "can't convert MockObject to Integer (MockObject#to_int gives String)")
- end
+ it "responds with a different error message when it raises a TypeError, depending on the type of the non-Integer object :to_int returns" do
+ obj = mock("to_int")
+ obj.should_receive(:to_int).and_return("A String")
+ -> {
+ Integer.try_convert obj
+ }.should raise_error(TypeError, "can't convert MockObject to Integer (MockObject#to_int gives String)")
+ 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
+ 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
diff --git a/spec/ruby/core/io/autoclose_spec.rb b/spec/ruby/core/io/autoclose_spec.rb
new file mode 100644
index 0000000000..715ada7c93
--- /dev/null
+++ b/spec/ruby/core/io/autoclose_spec.rb
@@ -0,0 +1,77 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "IO#autoclose?" do
+ before :each do
+ @io = IOSpecs.io_fixture "lines.txt"
+ end
+
+ after :each do
+ @io.autoclose = true unless @io.closed?
+ @io.close unless @io.closed?
+ end
+
+ it "is set to true by default" do
+ @io.should.autoclose?
+ end
+
+ it "cannot be queried on a closed IO object" do
+ @io.close
+ -> { @io.autoclose? }.should raise_error(IOError, /closed stream/)
+ end
+end
+
+describe "IO#autoclose=" do
+ before :each do
+ @io = IOSpecs.io_fixture "lines.txt"
+ end
+
+ after :each do
+ @io.autoclose = true unless @io.closed?
+ @io.close unless @io.closed?
+ end
+
+ it "can be set to true" do
+ @io.autoclose = false
+ @io.autoclose = true
+ @io.should.autoclose?
+ end
+
+ it "can be set to false" do
+ @io.autoclose = true
+ @io.autoclose = false
+ @io.should_not.autoclose?
+ end
+
+ it "can be set to any truthy value" do
+ @io.autoclose = false
+ @io.autoclose = 42
+ @io.should.autoclose?
+
+ @io.autoclose = false
+ @io.autoclose = Object.new
+ @io.should.autoclose?
+ end
+
+ it "can be set to any falsy value" do
+ @io.autoclose = true
+ @io.autoclose = nil
+ @io.should_not.autoclose?
+ end
+
+ it "can be set multiple times" do
+ @io.autoclose = true
+ @io.should.autoclose?
+
+ @io.autoclose = false
+ @io.should_not.autoclose?
+
+ @io.autoclose = true
+ @io.should.autoclose?
+ end
+
+ it "cannot be set on a closed IO object" do
+ @io.close
+ -> { @io.autoclose = false }.should raise_error(IOError, /closed stream/)
+ end
+end
diff --git a/spec/ruby/core/io/binread_spec.rb b/spec/ruby/core/io/binread_spec.rb
index 418e89213b..9e36b84da9 100644
--- a/spec/ruby/core/io/binread_spec.rb
+++ b/spec/ruby/core/io/binread_spec.rb
@@ -45,7 +45,7 @@ describe "IO.binread" do
-> { IO.binread @fname, 0, -1 }.should raise_error(Errno::EINVAL)
end
- ruby_version_is "3.3" do
+ ruby_version_is "3.3"..."4.0" do
# https://bugs.ruby-lang.org/issues/19630
it "warns about deprecation given a path with a pipe" do
cmd = "|echo ok"
diff --git a/spec/ruby/core/io/buffer/empty_spec.rb b/spec/ruby/core/io/buffer/empty_spec.rb
new file mode 100644
index 0000000000..e1fd4ab6a2
--- /dev/null
+++ b/spec/ruby/core/io/buffer/empty_spec.rb
@@ -0,0 +1,29 @@
+require_relative '../../../spec_helper'
+require_relative 'shared/null_and_empty'
+
+describe "IO::Buffer#empty?" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ it_behaves_like :io_buffer_null_and_empty, :empty?
+
+ it "is true for a 0-length String-backed buffer created with .for" do
+ @buffer = IO::Buffer.for("")
+ @buffer.empty?.should be_true
+ end
+
+ ruby_version_is "3.3" do
+ it "is true for a 0-length String-backed buffer created with .string" do
+ IO::Buffer.string(0) do |buffer|
+ buffer.empty?.should be_true
+ end
+ end
+ end
+
+ it "is true for a 0-length slice of a buffer with size > 0" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.slice(3, 0).empty?.should be_true
+ end
+end
diff --git a/spec/ruby/core/io/buffer/external_spec.rb b/spec/ruby/core/io/buffer/external_spec.rb
new file mode 100644
index 0000000000..4377a38357
--- /dev/null
+++ b/spec/ruby/core/io/buffer/external_spec.rb
@@ -0,0 +1,108 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer#external?" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ context "with a buffer created with .new" do
+ it "is false for an internal buffer" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.external?.should be_false
+ end
+
+ it "is false for a mapped buffer" do
+ @buffer = IO::Buffer.new(4, IO::Buffer::MAPPED)
+ @buffer.external?.should be_false
+ end
+ end
+
+ context "with a file-backed buffer created with .map" do
+ it "is true for a regular mapping" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)
+ @buffer.external?.should be_true
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "is false for a private mapping" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY | IO::Buffer::PRIVATE)
+ @buffer.external?.should be_false
+ end
+ end
+ end
+ end
+
+ context "with a String-backed buffer created with .for" do
+ it "is true for a buffer created without a block" do
+ @buffer = IO::Buffer.for("test")
+ @buffer.external?.should be_true
+ end
+
+ it "is true for a buffer created with a block" do
+ IO::Buffer.for(+"test") do |buffer|
+ buffer.external?.should be_true
+ end
+ end
+ end
+
+ ruby_version_is "3.3" do
+ context "with a String-backed buffer created with .string" do
+ it "is true" do
+ IO::Buffer.string(4) do |buffer|
+ buffer.external?.should be_true
+ end
+ end
+ end
+ end
+
+ # Always false for slices
+ context "with a slice of a buffer" do
+ context "created with .new" do
+ it "is false when slicing an internal buffer" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.slice.external?.should be_false
+ end
+
+ it "is false when slicing a mapped buffer" do
+ @buffer = IO::Buffer.new(4, IO::Buffer::MAPPED)
+ @buffer.slice.external?.should be_false
+ end
+ end
+
+ context "created with .map" do
+ it "is false" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)
+ @buffer.slice.external?.should be_false
+ end
+ end
+ end
+
+ context "created with .for" do
+ it "is false when slicing a buffer created without a block" do
+ @buffer = IO::Buffer.for("test")
+ @buffer.slice.external?.should be_false
+ end
+
+ it "is false when slicing a buffer created with a block" do
+ IO::Buffer.for(+"test") do |buffer|
+ buffer.slice.external?.should be_false
+ end
+ end
+ end
+
+ ruby_version_is "3.3" do
+ context "created with .string" do
+ it "is false" do
+ IO::Buffer.string(4) do |buffer|
+ buffer.slice.external?.should be_false
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/io/buffer/free_spec.rb b/spec/ruby/core/io/buffer/free_spec.rb
new file mode 100644
index 0000000000..f3a4918978
--- /dev/null
+++ b/spec/ruby/core/io/buffer/free_spec.rb
@@ -0,0 +1,104 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer#free" do
+ context "with a buffer created with .new" do
+ it "frees internal memory and nullifies the buffer" do
+ buffer = IO::Buffer.new(4)
+ buffer.free
+ buffer.null?.should be_true
+ end
+
+ it "frees mapped memory and nullifies the buffer" do
+ buffer = IO::Buffer.new(4, IO::Buffer::MAPPED)
+ buffer.free
+ buffer.null?.should be_true
+ end
+ end
+
+ context "with a file-backed buffer created with .map" do
+ it "frees mapped memory and nullifies the buffer" do
+ File.open(__FILE__, "r") do |file|
+ buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)
+ buffer.free
+ buffer.null?.should be_true
+ end
+ end
+ end
+
+ context "with a String-backed buffer created with .for" do
+ context "without a block" do
+ it "disassociates the buffer from the string and nullifies the buffer" do
+ string = +"test"
+ buffer = IO::Buffer.for(string)
+ # Read-only buffer, can't modify the string.
+ buffer.free
+ buffer.null?.should be_true
+ end
+ end
+
+ context "with a block" do
+ it "disassociates the buffer from the string and nullifies the buffer" do
+ string = +"test"
+ IO::Buffer.for(string) do |buffer|
+ buffer.set_string("meat")
+ buffer.free
+ buffer.null?.should be_true
+ end
+ string.should == "meat"
+ end
+ end
+ end
+
+ ruby_version_is "3.3" do
+ context "with a String-backed buffer created with .string" do
+ it "disassociates the buffer from the string and nullifies the buffer" do
+ string =
+ IO::Buffer.string(4) do |buffer|
+ buffer.set_string("meat")
+ buffer.free
+ buffer.null?.should be_true
+ end
+ string.should == "meat"
+ end
+ end
+ end
+
+ it "can be called repeatedly without an error" do
+ buffer = IO::Buffer.new(4)
+ buffer.free
+ buffer.null?.should be_true
+ buffer.free
+ buffer.null?.should be_true
+ end
+
+ it "is disallowed while locked, raising IO::Buffer::LockedError" do
+ buffer = IO::Buffer.new(4)
+ buffer.locked do
+ -> { buffer.free }.should raise_error(IO::Buffer::LockedError, "Buffer is locked!")
+ end
+ buffer.free
+ buffer.null?.should be_true
+ end
+
+ context "with a slice of a buffer" do
+ it "nullifies the slice, not touching the buffer" do
+ buffer = IO::Buffer.new(4)
+ slice = buffer.slice(0, 2)
+
+ slice.free
+ slice.null?.should be_true
+ buffer.null?.should be_false
+
+ buffer.free
+ end
+
+ it "nullifies buffer, invalidating the slice" do
+ buffer = IO::Buffer.new(4)
+ slice = buffer.slice(0, 2)
+
+ buffer.free
+ slice.null?.should be_false
+ slice.valid?.should be_false
+ end
+ end
+end
diff --git a/spec/ruby/core/io/buffer/initialize_spec.rb b/spec/ruby/core/io/buffer/initialize_spec.rb
new file mode 100644
index 0000000000..c86d1e7f1d
--- /dev/null
+++ b/spec/ruby/core/io/buffer/initialize_spec.rb
@@ -0,0 +1,103 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer#initialize" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ it "creates a new zero-filled buffer with default size" do
+ @buffer = IO::Buffer.new
+ @buffer.size.should == IO::Buffer::DEFAULT_SIZE
+ @buffer.each(:U8).should.all? { |_offset, value| value.eql?(0) }
+ end
+
+ it "creates a buffer with default state" do
+ @buffer = IO::Buffer.new
+ @buffer.should_not.shared?
+ @buffer.should_not.readonly?
+
+ @buffer.should_not.empty?
+ @buffer.should_not.null?
+
+ # This is run-time state, set by #locked.
+ @buffer.should_not.locked?
+ end
+
+ context "with size argument" do
+ it "creates a new internal buffer if size is less than IO::Buffer::PAGE_SIZE" do
+ size = IO::Buffer::PAGE_SIZE - 1
+ @buffer = IO::Buffer.new(size)
+ @buffer.size.should == size
+ @buffer.should.internal?
+ @buffer.should_not.mapped?
+ @buffer.should_not.empty?
+ end
+
+ it "creates a new mapped buffer if size is greater than or equal to IO::Buffer::PAGE_SIZE" do
+ size = IO::Buffer::PAGE_SIZE
+ @buffer = IO::Buffer.new(size)
+ @buffer.size.should == size
+ @buffer.should_not.internal?
+ @buffer.should.mapped?
+ @buffer.should_not.empty?
+ end
+
+ it "creates a null buffer if size is 0" do
+ @buffer = IO::Buffer.new(0)
+ @buffer.size.should.zero?
+ @buffer.should_not.internal?
+ @buffer.should_not.mapped?
+ @buffer.should.null?
+ @buffer.should.empty?
+ end
+
+ it "raises TypeError if size is not an Integer" do
+ -> { IO::Buffer.new(nil) }.should raise_error(TypeError, "not an Integer")
+ -> { IO::Buffer.new(10.0) }.should raise_error(TypeError, "not an Integer")
+ end
+
+ it "raises ArgumentError if size is negative" do
+ -> { IO::Buffer.new(-1) }.should raise_error(ArgumentError, "Size can't be negative!")
+ end
+ end
+
+ context "with size and flags arguments" do
+ it "forces mapped buffer with IO::Buffer::MAPPED flag" do
+ @buffer = IO::Buffer.new(IO::Buffer::PAGE_SIZE - 1, IO::Buffer::MAPPED)
+ @buffer.should.mapped?
+ @buffer.should_not.internal?
+ @buffer.should_not.empty?
+ end
+
+ it "forces internal buffer with IO::Buffer::INTERNAL flag" do
+ @buffer = IO::Buffer.new(IO::Buffer::PAGE_SIZE, IO::Buffer::INTERNAL)
+ @buffer.should.internal?
+ @buffer.should_not.mapped?
+ @buffer.should_not.empty?
+ end
+
+ it "raises IO::Buffer::AllocationError if neither IO::Buffer::MAPPED nor IO::Buffer::INTERNAL is given" do
+ -> { IO::Buffer.new(10, IO::Buffer::READONLY) }.should raise_error(IO::Buffer::AllocationError, "Could not allocate buffer!")
+ -> { IO::Buffer.new(10, 0) }.should raise_error(IO::Buffer::AllocationError, "Could not allocate buffer!")
+ end
+
+ ruby_version_is "3.3" do
+ it "raises ArgumentError if flags is negative" do
+ -> { IO::Buffer.new(10, -1) }.should raise_error(ArgumentError, "Flags can't be negative!")
+ end
+ end
+
+ ruby_version_is ""..."3.3" do
+ it "raises IO::Buffer::AllocationError with non-Integer flags" do
+ -> { IO::Buffer.new(10, 0.0) }.should raise_error(IO::Buffer::AllocationError, "Could not allocate buffer!")
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raises TypeError with non-Integer flags" do
+ -> { IO::Buffer.new(10, 0.0) }.should raise_error(TypeError, "not an Integer")
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/io/buffer/internal_spec.rb b/spec/ruby/core/io/buffer/internal_spec.rb
new file mode 100644
index 0000000000..409699cc3c
--- /dev/null
+++ b/spec/ruby/core/io/buffer/internal_spec.rb
@@ -0,0 +1,108 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer#internal?" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ context "with a buffer created with .new" do
+ it "is true for an internal buffer" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.internal?.should be_true
+ end
+
+ it "is false for a mapped buffer" do
+ @buffer = IO::Buffer.new(4, IO::Buffer::MAPPED)
+ @buffer.internal?.should be_false
+ end
+ end
+
+ context "with a file-backed buffer created with .map" do
+ it "is false for a regular mapping" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)
+ @buffer.internal?.should be_false
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "is false for a private mapping" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY | IO::Buffer::PRIVATE)
+ @buffer.internal?.should be_false
+ end
+ end
+ end
+ end
+
+ context "with a String-backed buffer created with .for" do
+ it "is false for a buffer created without a block" do
+ @buffer = IO::Buffer.for("test")
+ @buffer.internal?.should be_false
+ end
+
+ it "is false for a buffer created with a block" do
+ IO::Buffer.for(+"test") do |buffer|
+ buffer.internal?.should be_false
+ end
+ end
+ end
+
+ ruby_version_is "3.3" do
+ context "with a String-backed buffer created with .string" do
+ it "is false" do
+ IO::Buffer.string(4) do |buffer|
+ buffer.internal?.should be_false
+ end
+ end
+ end
+ end
+
+ # Always false for slices
+ context "with a slice of a buffer" do
+ context "created with .new" do
+ it "is false when slicing an internal buffer" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.slice.internal?.should be_false
+ end
+
+ it "is false when slicing a mapped buffer" do
+ @buffer = IO::Buffer.new(4, IO::Buffer::MAPPED)
+ @buffer.slice.internal?.should be_false
+ end
+ end
+
+ context "created with .map" do
+ it "is false" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)
+ @buffer.slice.internal?.should be_false
+ end
+ end
+ end
+
+ context "created with .for" do
+ it "is false when slicing a buffer created without a block" do
+ @buffer = IO::Buffer.for("test")
+ @buffer.slice.internal?.should be_false
+ end
+
+ it "is false when slicing a buffer created with a block" do
+ IO::Buffer.for(+"test") do |buffer|
+ buffer.slice.internal?.should be_false
+ end
+ end
+ end
+
+ ruby_version_is "3.3" do
+ context "created with .string" do
+ it "is false" do
+ IO::Buffer.string(4) do |buffer|
+ buffer.slice.internal?.should be_false
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/io/buffer/locked_spec.rb b/spec/ruby/core/io/buffer/locked_spec.rb
new file mode 100644
index 0000000000..4ffa569fd2
--- /dev/null
+++ b/spec/ruby/core/io/buffer/locked_spec.rb
@@ -0,0 +1,75 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer#locked" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ context "when buffer is locked" do
+ it "allows reading and writing operations on the buffer" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.set_string("test")
+ @buffer.locked do
+ @buffer.get_string.should == "test"
+ @buffer.set_string("meat")
+ end
+ @buffer.get_string.should == "meat"
+ end
+
+ it "disallows operations changing buffer itself, raising IO::Buffer::LockedError" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.locked do
+ # Just an example, each method is responsible for checking the lock state.
+ -> { @buffer.resize(8) }.should raise_error(IO::Buffer::LockedError)
+ end
+ end
+ end
+
+ it "disallows reentrant locking, raising IO::Buffer::LockedError" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.locked do
+ -> { @buffer.locked {} }.should raise_error(IO::Buffer::LockedError, "Buffer already locked!")
+ end
+ end
+
+ it "does not propagate to buffer's slices" do
+ @buffer = IO::Buffer.new(4)
+ slice = @buffer.slice(0, 2)
+ @buffer.locked do
+ @buffer.locked?.should be_true
+ slice.locked?.should be_false
+ slice.locked { slice.locked?.should be_true }
+ end
+ end
+
+ it "does not propagate backwards from buffer's slices" do
+ @buffer = IO::Buffer.new(4)
+ slice = @buffer.slice(0, 2)
+ slice.locked do
+ slice.locked?.should be_true
+ @buffer.locked?.should be_false
+ @buffer.locked { @buffer.locked?.should be_true }
+ end
+ end
+end
+
+describe "IO::Buffer#locked?" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ it "is false by default" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.locked?.should be_false
+ end
+
+ it "is true only inside of #locked block" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.locked do
+ @buffer.locked?.should be_true
+ end
+ @buffer.locked?.should be_false
+ end
+end
diff --git a/spec/ruby/core/io/buffer/mapped_spec.rb b/spec/ruby/core/io/buffer/mapped_spec.rb
new file mode 100644
index 0000000000..b3610207ff
--- /dev/null
+++ b/spec/ruby/core/io/buffer/mapped_spec.rb
@@ -0,0 +1,108 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer#mapped?" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ context "with a buffer created with .new" do
+ it "is false for an internal buffer" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.mapped?.should be_false
+ end
+
+ it "is true for a mapped buffer" do
+ @buffer = IO::Buffer.new(4, IO::Buffer::MAPPED)
+ @buffer.mapped?.should be_true
+ end
+ end
+
+ context "with a file-backed buffer created with .map" do
+ it "is true for a regular mapping" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)
+ @buffer.mapped?.should be_true
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "is true for a private mapping" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY | IO::Buffer::PRIVATE)
+ @buffer.mapped?.should be_true
+ end
+ end
+ end
+ end
+
+ context "with a String-backed buffer created with .for" do
+ it "is false for a buffer created without a block" do
+ @buffer = IO::Buffer.for("test")
+ @buffer.mapped?.should be_false
+ end
+
+ it "is false for a buffer created with a block" do
+ IO::Buffer.for(+"test") do |buffer|
+ buffer.mapped?.should be_false
+ end
+ end
+ end
+
+ ruby_version_is "3.3" do
+ context "with a String-backed buffer created with .string" do
+ it "is false" do
+ IO::Buffer.string(4) do |buffer|
+ buffer.mapped?.should be_false
+ end
+ end
+ end
+ end
+
+ # Always false for slices
+ context "with a slice of a buffer" do
+ context "created with .new" do
+ it "is false when slicing an internal buffer" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.slice.mapped?.should be_false
+ end
+
+ it "is false when slicing a mapped buffer" do
+ @buffer = IO::Buffer.new(4, IO::Buffer::MAPPED)
+ @buffer.slice.mapped?.should be_false
+ end
+ end
+
+ context "created with .map" do
+ it "is false" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)
+ @buffer.slice.mapped?.should be_false
+ end
+ end
+ end
+
+ context "created with .for" do
+ it "is false when slicing a buffer created without a block" do
+ @buffer = IO::Buffer.for("test")
+ @buffer.slice.mapped?.should be_false
+ end
+
+ it "is false when slicing a buffer created with a block" do
+ IO::Buffer.for(+"test") do |buffer|
+ buffer.slice.mapped?.should be_false
+ end
+ end
+ end
+
+ ruby_version_is "3.3" do
+ context "created with .string" do
+ it "is false" do
+ IO::Buffer.string(4) do |buffer|
+ buffer.slice.mapped?.should be_false
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/io/buffer/null_spec.rb b/spec/ruby/core/io/buffer/null_spec.rb
new file mode 100644
index 0000000000..3fb1144d0e
--- /dev/null
+++ b/spec/ruby/core/io/buffer/null_spec.rb
@@ -0,0 +1,29 @@
+require_relative '../../../spec_helper'
+require_relative 'shared/null_and_empty'
+
+describe "IO::Buffer#null?" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ it_behaves_like :io_buffer_null_and_empty, :null?
+
+ it "is false for a 0-length String-backed buffer created with .for" do
+ @buffer = IO::Buffer.for("")
+ @buffer.null?.should be_false
+ end
+
+ ruby_version_is "3.3" do
+ it "is false for a 0-length String-backed buffer created with .string" do
+ IO::Buffer.string(0) do |buffer|
+ buffer.null?.should be_false
+ end
+ end
+ end
+
+ it "is false for a 0-length slice of a buffer with size > 0" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.slice(3, 0).null?.should be_false
+ end
+end
diff --git a/spec/ruby/core/io/buffer/private_spec.rb b/spec/ruby/core/io/buffer/private_spec.rb
new file mode 100644
index 0000000000..7aa308997b
--- /dev/null
+++ b/spec/ruby/core/io/buffer/private_spec.rb
@@ -0,0 +1,111 @@
+require_relative '../../../spec_helper'
+
+ruby_version_is "3.3" do
+ describe "IO::Buffer#private?" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ context "with a buffer created with .new" do
+ it "is false for an internal buffer" do
+ @buffer = IO::Buffer.new(4, IO::Buffer::INTERNAL)
+ @buffer.private?.should be_false
+ end
+
+ it "is false for a mapped buffer" do
+ @buffer = IO::Buffer.new(4, IO::Buffer::MAPPED)
+ @buffer.private?.should be_false
+ end
+ end
+
+ context "with a file-backed buffer created with .map" do
+ it "is false for a regular mapping" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)
+ @buffer.private?.should be_false
+ end
+ end
+
+ it "is true for a private mapping" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY | IO::Buffer::PRIVATE)
+ @buffer.private?.should be_true
+ end
+ end
+ end
+
+ context "with a String-backed buffer created with .for" do
+ it "is false for a buffer created without a block" do
+ @buffer = IO::Buffer.for("test")
+ @buffer.private?.should be_false
+ end
+
+ it "is false for a buffer created with a block" do
+ IO::Buffer.for(+"test") do |buffer|
+ buffer.private?.should be_false
+ end
+ end
+ end
+
+ context "with a String-backed buffer created with .string" do
+ it "is false" do
+ IO::Buffer.string(4) do |buffer|
+ buffer.private?.should be_false
+ end
+ end
+ end
+
+ # Always false for slices
+ context "with a slice of a buffer" do
+ context "created with .new" do
+ it "is false when slicing an internal buffer" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.slice.private?.should be_false
+ end
+
+ it "is false when slicing a mapped buffer" do
+ @buffer = IO::Buffer.new(4, IO::Buffer::MAPPED)
+ @buffer.slice.private?.should be_false
+ end
+ end
+
+ context "created with .map" do
+ it "is false when slicing a regular file-backed buffer" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)
+ @buffer.slice.private?.should be_false
+ end
+ end
+
+ it "is false when slicing a private file-backed buffer" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY | IO::Buffer::PRIVATE)
+ @buffer.slice.private?.should be_false
+ end
+ end
+ end
+
+ context "created with .for" do
+ it "is false when slicing a buffer created without a block" do
+ @buffer = IO::Buffer.for("test")
+ @buffer.slice.private?.should be_false
+ end
+
+ it "is false when slicing a buffer created with a block" do
+ IO::Buffer.for(+"test") do |buffer|
+ buffer.slice.private?.should be_false
+ end
+ end
+ end
+
+ context "created with .string" do
+ it "is false" do
+ IO::Buffer.string(4) do |buffer|
+ buffer.slice.private?.should be_false
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/io/buffer/readonly_spec.rb b/spec/ruby/core/io/buffer/readonly_spec.rb
new file mode 100644
index 0000000000..0014a876ed
--- /dev/null
+++ b/spec/ruby/core/io/buffer/readonly_spec.rb
@@ -0,0 +1,143 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer#readonly?" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ context "with a buffer created with .new" do
+ it "is false for an internal buffer" do
+ @buffer = IO::Buffer.new(4, IO::Buffer::INTERNAL)
+ @buffer.readonly?.should be_false
+ end
+
+ it "is false for a mapped buffer" do
+ @buffer = IO::Buffer.new(4, IO::Buffer::MAPPED)
+ @buffer.readonly?.should be_false
+ end
+ end
+
+ context "with a file-backed buffer created with .map" do
+ it "is false for a writable mapping" do
+ File.open(__FILE__, "r+") do |file|
+ @buffer = IO::Buffer.map(file)
+ @buffer.readonly?.should be_false
+ end
+ end
+
+ it "is true for a readonly mapping" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)
+ @buffer.readonly?.should be_true
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "is false for a private mapping" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::PRIVATE)
+ @buffer.readonly?.should be_false
+ end
+ end
+ end
+ end
+
+ context "with a String-backed buffer created with .for" do
+ it "is true for a buffer created without a block" do
+ @buffer = IO::Buffer.for(+"test")
+ @buffer.readonly?.should be_true
+ end
+
+ it "is false for a buffer created with a block" do
+ IO::Buffer.for(+"test") do |buffer|
+ buffer.readonly?.should be_false
+ end
+ end
+
+ it "is true for a buffer created with a block from a frozen string" do
+ IO::Buffer.for(-"test") do |buffer|
+ buffer.readonly?.should be_true
+ end
+ end
+ end
+
+ ruby_version_is "3.3" do
+ context "with a String-backed buffer created with .string" do
+ it "is false" do
+ IO::Buffer.string(4) do |buffer|
+ buffer.readonly?.should be_false
+ end
+ end
+ end
+ end
+
+ # This seems to be the only flag propagated from the source buffer to the slice.
+ context "with a slice of a buffer" do
+ context "created with .new" do
+ it "is false when slicing an internal buffer" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.slice.readonly?.should be_false
+ end
+
+ it "is false when slicing a mapped buffer" do
+ @buffer = IO::Buffer.new(4, IO::Buffer::MAPPED)
+ @buffer.slice.readonly?.should be_false
+ end
+ end
+
+ context "created with .map" do
+ it "is false when slicing a read-write file-backed buffer" do
+ File.open(__FILE__, "r+") do |file|
+ @buffer = IO::Buffer.map(file)
+ @buffer.slice.readonly?.should be_false
+ end
+ end
+
+ it "is true when slicing a readonly file-backed buffer" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)
+ @buffer.slice.readonly?.should be_true
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "is false when slicing a private file-backed buffer" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::PRIVATE)
+ @buffer.slice.readonly?.should be_false
+ end
+ end
+ end
+ end
+
+ context "created with .for" do
+ it "is true when slicing a buffer created without a block" do
+ @buffer = IO::Buffer.for(+"test")
+ @buffer.slice.readonly?.should be_true
+ end
+
+ it "is false when slicing a buffer created with a block" do
+ IO::Buffer.for(+"test") do |buffer|
+ buffer.slice.readonly?.should be_false
+ end
+ end
+
+ it "is true when slicing a buffer created with a block from a frozen string" do
+ IO::Buffer.for(-"test") do |buffer|
+ buffer.slice.readonly?.should be_true
+ end
+ end
+ end
+
+ ruby_version_is "3.3" do
+ context "created with .string" do
+ it "is false" do
+ IO::Buffer.string(4) do |buffer|
+ buffer.slice.readonly?.should be_false
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/io/buffer/resize_spec.rb b/spec/ruby/core/io/buffer/resize_spec.rb
new file mode 100644
index 0000000000..0da3a23356
--- /dev/null
+++ b/spec/ruby/core/io/buffer/resize_spec.rb
@@ -0,0 +1,155 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer#resize" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ context "with a buffer created with .new" do
+ it "resizes internal buffer, preserving type" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.resize(IO::Buffer::PAGE_SIZE)
+ @buffer.size.should == IO::Buffer::PAGE_SIZE
+ @buffer.internal?.should be_true
+ @buffer.mapped?.should be_false
+ end
+
+ platform_is :linux do
+ it "resizes mapped buffer, preserving type" do
+ @buffer = IO::Buffer.new(IO::Buffer::PAGE_SIZE, IO::Buffer::MAPPED)
+ @buffer.resize(4)
+ @buffer.size.should == 4
+ @buffer.internal?.should be_false
+ @buffer.mapped?.should be_true
+ end
+ end
+
+ platform_is_not :linux do
+ it "resizes mapped buffer, changing type to internal" do
+ @buffer = IO::Buffer.new(IO::Buffer::PAGE_SIZE, IO::Buffer::MAPPED)
+ @buffer.resize(4)
+ @buffer.size.should == 4
+ @buffer.internal?.should be_true
+ @buffer.mapped?.should be_false
+ end
+ end
+ end
+
+ context "with a file-backed buffer created with .map" do
+ it "disallows resizing shared buffer, raising IO::Buffer::AccessError" do
+ File.open(__FILE__, "r+") do |file|
+ @buffer = IO::Buffer.map(file)
+ -> { @buffer.resize(10) }.should raise_error(IO::Buffer::AccessError, "Cannot resize external buffer!")
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "resizes private buffer, discarding excess contents" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::PRIVATE)
+ @buffer.resize(10)
+ @buffer.size.should == 10
+ @buffer.get_string.should == "require_re"
+ @buffer.resize(12)
+ @buffer.size.should == 12
+ @buffer.get_string.should == "require_re\0\0"
+ end
+ end
+ end
+ end
+
+ context "with a String-backed buffer created with .for" do
+ context "without a block" do
+ it "disallows resizing, raising IO::Buffer::AccessError" do
+ @buffer = IO::Buffer.for(+"test")
+ -> { @buffer.resize(10) }.should raise_error(IO::Buffer::AccessError, "Cannot resize external buffer!")
+ end
+ end
+
+ context "with a block" do
+ it "disallows resizing, raising IO::Buffer::AccessError" do
+ IO::Buffer.for(+'test') do |buffer|
+ -> { buffer.resize(10) }.should raise_error(IO::Buffer::AccessError, "Cannot resize external buffer!")
+ end
+ end
+ end
+ end
+
+ ruby_version_is "3.3" do
+ context "with a String-backed buffer created with .string" do
+ it "disallows resizing, raising IO::Buffer::AccessError" do
+ IO::Buffer.string(4) do |buffer|
+ -> { buffer.resize(10) }.should raise_error(IO::Buffer::AccessError, "Cannot resize external buffer!")
+ end
+ end
+ end
+ end
+
+ context "with a null buffer" do
+ it "allows resizing a 0-sized buffer, creating a regular buffer according to new size" do
+ @buffer = IO::Buffer.new(0)
+ @buffer.resize(IO::Buffer::PAGE_SIZE)
+ @buffer.size.should == IO::Buffer::PAGE_SIZE
+ @buffer.internal?.should be_false
+ @buffer.mapped?.should be_true
+ end
+
+ it "allows resizing after a free, creating a regular buffer according to new size" do
+ @buffer = IO::Buffer.for("test")
+ @buffer.free
+ @buffer.resize(10)
+ @buffer.size.should == 10
+ @buffer.internal?.should be_true
+ @buffer.mapped?.should be_false
+ end
+ end
+
+ it "allows resizing to 0, freeing memory" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.resize(0)
+ @buffer.null?.should be_true
+ end
+
+ it "can be called repeatedly" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.resize(10)
+ @buffer.resize(27)
+ @buffer.resize(1)
+ @buffer.size.should == 1
+ end
+
+ it "always clears extra memory" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.set_string("test")
+ # This should not cause a re-allocation, just a technical resizing,
+ # even with very aggressive memory allocation.
+ @buffer.resize(2)
+ @buffer.resize(4)
+ @buffer.get_string.should == "te\0\0"
+ end
+
+ it "is disallowed while locked, raising IO::Buffer::LockedError" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.locked do
+ -> { @buffer.resize(10) }.should raise_error(IO::Buffer::LockedError, "Cannot resize locked buffer!")
+ end
+ end
+
+ it "raises ArgumentError if size is negative" do
+ @buffer = IO::Buffer.new(4)
+ -> { @buffer.resize(-1) }.should raise_error(ArgumentError, "Size can't be negative!")
+ end
+
+ it "raises TypeError if size is not an Integer" do
+ @buffer = IO::Buffer.new(4)
+ -> { @buffer.resize(nil) }.should raise_error(TypeError, "not an Integer")
+ -> { @buffer.resize(10.0) }.should raise_error(TypeError, "not an Integer")
+ end
+
+ context "with a slice of a buffer" do
+ # Current behavior of slice resizing seems unintended (it's undocumented, too).
+ # It either creates a completely new buffer, or breaks the slice on size 0.
+ it "needs to be reviewed for spec completeness"
+ end
+end
diff --git a/spec/ruby/core/io/buffer/shared/null_and_empty.rb b/spec/ruby/core/io/buffer/shared/null_and_empty.rb
new file mode 100644
index 0000000000..c8fe9e5e46
--- /dev/null
+++ b/spec/ruby/core/io/buffer/shared/null_and_empty.rb
@@ -0,0 +1,59 @@
+describe :io_buffer_null_and_empty, shared: true do
+ it "is false for a buffer with size > 0" do
+ @buffer = IO::Buffer.new(1)
+ @buffer.send(@method).should be_false
+ end
+
+ it "is false for a slice with length > 0" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.slice(1, 2).send(@method).should be_false
+ end
+
+ it "is false for a file-mapped buffer" do
+ File.open(__FILE__, "rb") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)
+ @buffer.send(@method).should be_false
+ end
+ end
+
+ it "is false for a non-empty String-backed buffer created with .for" do
+ @buffer = IO::Buffer.for("test")
+ @buffer.send(@method).should be_false
+ end
+
+ ruby_version_is "3.3" do
+ it "is false for a non-empty String-backed buffer created with .string" do
+ IO::Buffer.string(4) do |buffer|
+ buffer.send(@method).should be_false
+ end
+ end
+ end
+
+ it "is true for a 0-sized buffer" do
+ @buffer = IO::Buffer.new(0)
+ @buffer.send(@method).should be_true
+ end
+
+ it "is true for a slice of a 0-sized buffer" do
+ @buffer = IO::Buffer.new(0)
+ @buffer.slice(0, 0).send(@method).should be_true
+ end
+
+ it "is true for a freed buffer" do
+ @buffer = IO::Buffer.new(1)
+ @buffer.free
+ @buffer.send(@method).should be_true
+ end
+
+ it "is true for a buffer resized to 0" do
+ @buffer = IO::Buffer.new(1)
+ @buffer.resize(0)
+ @buffer.send(@method).should be_true
+ end
+
+ it "is true for a buffer whose memory was transferred" do
+ buffer = IO::Buffer.new(1)
+ @buffer = buffer.transfer
+ buffer.send(@method).should be_true
+ end
+end
diff --git a/spec/ruby/core/io/buffer/shared_spec.rb b/spec/ruby/core/io/buffer/shared_spec.rb
new file mode 100644
index 0000000000..f2a638cf39
--- /dev/null
+++ b/spec/ruby/core/io/buffer/shared_spec.rb
@@ -0,0 +1,117 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer#shared?" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ context "with a buffer created with .new" do
+ it "is false for an internal buffer" do
+ @buffer = IO::Buffer.new(4, IO::Buffer::INTERNAL)
+ @buffer.shared?.should be_false
+ end
+
+ it "is false for a mapped buffer" do
+ @buffer = IO::Buffer.new(4, IO::Buffer::MAPPED)
+ @buffer.shared?.should be_false
+ end
+ end
+
+ context "with a file-backed buffer created with .map" do
+ it "is true for a regular mapping" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)
+ @buffer.shared?.should be_true
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "is false for a private mapping" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY | IO::Buffer::PRIVATE)
+ @buffer.shared?.should be_false
+ end
+ end
+ end
+ end
+
+ context "with a String-backed buffer created with .for" do
+ it "is false for a buffer created without a block" do
+ @buffer = IO::Buffer.for("test")
+ @buffer.shared?.should be_false
+ end
+
+ it "is false for a buffer created with a block" do
+ IO::Buffer.for(+"test") do |buffer|
+ buffer.shared?.should be_false
+ end
+ end
+ end
+
+ ruby_version_is "3.3" do
+ context "with a String-backed buffer created with .string" do
+ it "is false" do
+ IO::Buffer.string(4) do |buffer|
+ buffer.shared?.should be_false
+ end
+ end
+ end
+ end
+
+ # Always false for slices
+ context "with a slice of a buffer" do
+ context "created with .new" do
+ it "is false when slicing an internal buffer" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.slice.shared?.should be_false
+ end
+
+ it "is false when slicing a mapped buffer" do
+ @buffer = IO::Buffer.new(4, IO::Buffer::MAPPED)
+ @buffer.slice.shared?.should be_false
+ end
+ end
+
+ context "created with .map" do
+ it "is false when slicing a regular file-backed buffer" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)
+ @buffer.slice.shared?.should be_false
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "is false when slicing a private file-backed buffer" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY | IO::Buffer::PRIVATE)
+ @buffer.slice.shared?.should be_false
+ end
+ end
+ end
+ end
+
+ context "created with .for" do
+ it "is false when slicing a buffer created without a block" do
+ @buffer = IO::Buffer.for("test")
+ @buffer.slice.shared?.should be_false
+ end
+
+ it "is false when slicing a buffer created with a block" do
+ IO::Buffer.for(+"test") do |buffer|
+ buffer.slice.shared?.should be_false
+ end
+ end
+ end
+
+ ruby_version_is "3.3" do
+ context "created with .string" do
+ it "is false" do
+ IO::Buffer.string(4) do |buffer|
+ buffer.slice.shared?.should be_false
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/io/buffer/transfer_spec.rb b/spec/ruby/core/io/buffer/transfer_spec.rb
new file mode 100644
index 0000000000..cb8c843ff2
--- /dev/null
+++ b/spec/ruby/core/io/buffer/transfer_spec.rb
@@ -0,0 +1,118 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer#transfer" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ context "with a buffer created with .new" do
+ it "transfers internal memory to a new buffer, nullifying the original" do
+ buffer = IO::Buffer.new(4)
+ info = buffer.to_s
+ @buffer = buffer.transfer
+ @buffer.to_s.should == info
+ buffer.null?.should be_true
+ end
+
+ it "transfers mapped memory to a new buffer, nullifying the original" do
+ buffer = IO::Buffer.new(4, IO::Buffer::MAPPED)
+ info = buffer.to_s
+ @buffer = buffer.transfer
+ @buffer.to_s.should == info
+ buffer.null?.should be_true
+ end
+ end
+
+ context "with a file-backed buffer created with .map" do
+ it "transfers mapped memory to a new buffer, nullifying the original" do
+ File.open(__FILE__, "r") do |file|
+ buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)
+ info = buffer.to_s
+ @buffer = buffer.transfer
+ @buffer.to_s.should == info
+ buffer.null?.should be_true
+ end
+ end
+ end
+
+ context "with a String-backed buffer created with .for" do
+ context "without a block" do
+ it "transfers memory to a new buffer, nullifying the original" do
+ buffer = IO::Buffer.for("test")
+ info = buffer.to_s
+ @buffer = buffer.transfer
+ @buffer.to_s.should == info
+ buffer.null?.should be_true
+ end
+ end
+
+ context "with a block" do
+ it "transfers memory to a new buffer, breaking the transaction by nullifying the original" do
+ IO::Buffer.for(+"test") do |buffer|
+ info = buffer.to_s
+ @buffer = buffer.transfer
+ @buffer.to_s.should == info
+ buffer.null?.should be_true
+ end
+ @buffer.null?.should be_false
+ end
+ end
+ end
+
+ ruby_version_is "3.3" do
+ context "with a String-backed buffer created with .string" do
+ it "transfers memory to a new buffer, breaking the transaction by nullifying the original" do
+ IO::Buffer.string(4) do |buffer|
+ info = buffer.to_s
+ @buffer = buffer.transfer
+ @buffer.to_s.should == info
+ buffer.null?.should be_true
+ end
+ @buffer.null?.should be_false
+ end
+ end
+ end
+
+ it "allows multiple transfers" do
+ buffer_1 = IO::Buffer.new(4)
+ buffer_2 = buffer_1.transfer
+ @buffer = buffer_2.transfer
+ buffer_1.null?.should be_true
+ buffer_2.null?.should be_true
+ @buffer.null?.should be_false
+ end
+
+ it "is disallowed while locked, raising IO::Buffer::LockedError" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.locked do
+ -> { @buffer.transfer }.should raise_error(IO::Buffer::LockedError, "Cannot transfer ownership of locked buffer!")
+ end
+ end
+
+ context "with a slice of a buffer" do
+ it "transfers source to a new slice, not touching the buffer" do
+ @buffer = IO::Buffer.new(4)
+ slice = @buffer.slice(0, 2)
+ @buffer.set_string("test")
+
+ new_slice = slice.transfer
+ slice.null?.should be_true
+ new_slice.null?.should be_false
+ @buffer.null?.should be_false
+
+ new_slice.set_string("ea")
+ @buffer.get_string.should == "east"
+ end
+
+ it "nullifies buffer, invalidating the slice" do
+ buffer = IO::Buffer.new(4)
+ slice = buffer.slice(0, 2)
+ @buffer = buffer.transfer
+
+ slice.null?.should be_false
+ slice.valid?.should be_false
+ -> { slice.get_string }.should raise_error(IO::Buffer::InvalidatedError, "Buffer has been invalidated!")
+ end
+ end
+end
diff --git a/spec/ruby/core/io/buffer/valid_spec.rb b/spec/ruby/core/io/buffer/valid_spec.rb
new file mode 100644
index 0000000000..680a35ae9a
--- /dev/null
+++ b/spec/ruby/core/io/buffer/valid_spec.rb
@@ -0,0 +1,110 @@
+require_relative '../../../spec_helper'
+
+describe "IO::Buffer#valid?" do
+ after :each do
+ @buffer&.free
+ @buffer = nil
+ end
+
+ # Non-slices are always valid
+ context "with a non-slice buffer" do
+ it "is true for a regular buffer" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.valid?.should be_true
+ end
+
+ it "is true for a 0-size buffer" do
+ @buffer = IO::Buffer.new(0)
+ @buffer.valid?.should be_true
+ end
+
+ it "is true for a freed buffer" do
+ @buffer = IO::Buffer.new(4)
+ @buffer.free
+ @buffer.valid?.should be_true
+ end
+
+ it "is true for a freed file-backed buffer" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)
+ @buffer.valid?.should be_true
+ @buffer.free
+ @buffer.valid?.should be_true
+ end
+ end
+
+ it "is true for a freed string-backed buffer" do
+ @buffer = IO::Buffer.for("hello")
+ @buffer.valid?.should be_true
+ @buffer.free
+ @buffer.valid?.should be_true
+ end
+ end
+
+ # "A buffer becomes invalid if it is a slice of another buffer (or string)
+ # which has been freed or re-allocated at a different address."
+ context "with a slice" do
+ it "is true for a slice of a live buffer" do
+ @buffer = IO::Buffer.new(4)
+ slice = @buffer.slice(0, 2)
+ slice.valid?.should be_true
+ end
+
+ context "when buffer is resized" do
+ it "is false when slice becomes outside the buffer" do
+ @buffer = IO::Buffer.new(4)
+ slice = @buffer.slice(2, 2)
+ @buffer.resize(3)
+ slice.valid?.should be_false
+ end
+
+ platform_is_not :linux do
+ # This test does not cause a copy-resize on Linux.
+ # `#resize` MAY cause the buffer to move, but there is no guarantee.
+ it "is false when buffer is copied on resize" do
+ @buffer = IO::Buffer.new(4, IO::Buffer::MAPPED)
+ slice = @buffer.slice(0, 2)
+ @buffer.resize(8)
+ slice.valid?.should be_false
+ end
+ end
+ end
+
+ it "is false for a slice of a transferred buffer" do
+ buffer = IO::Buffer.new(4)
+ slice = buffer.slice(0, 2)
+ @buffer = buffer.transfer
+ slice.valid?.should be_false
+ end
+
+ it "is false for a slice of a freed buffer" do
+ @buffer = IO::Buffer.new(4)
+ slice = @buffer.slice(0, 2)
+ @buffer.free
+ slice.valid?.should be_false
+ end
+
+ it "is false for a slice of a freed file-backed buffer" do
+ File.open(__FILE__, "r") do |file|
+ @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)
+ slice = @buffer.slice(0, 2)
+ slice.valid?.should be_true
+ @buffer.free
+ slice.valid?.should be_false
+ end
+ end
+
+ it "is true for a slice of a freed string-backed buffer while string is alive" do
+ @buffer = IO::Buffer.for("alive")
+ slice = @buffer.slice(0, 2)
+ slice.valid?.should be_true
+ @buffer.free
+ slice.valid?.should be_true
+ end
+
+ # There probably should be a test with a garbage-collected string,
+ # but it's not clear how to force that.
+
+ it "needs to be reviewed for spec completeness"
+ end
+end
diff --git a/spec/ruby/core/io/dup_spec.rb b/spec/ruby/core/io/dup_spec.rb
index 68d538377f..564e007438 100644
--- a/spec/ruby/core/io/dup_spec.rb
+++ b/spec/ruby/core/io/dup_spec.rb
@@ -25,27 +25,27 @@ describe "IO#dup" do
@i.fileno.should_not == @f.fileno
end
-quarantine! do # This does not appear to be consistent across platforms
- it "shares the original stream between the two IOs" do
- start = @f.pos
- @i.pos.should == start
+ quarantine! do # This does not appear to be consistent across platforms
+ it "shares the original stream between the two IOs" do
+ start = @f.pos
+ @i.pos.should == start
- s = "Hello, wo.. wait, where am I?\n"
- s2 = "<evil voice> Muhahahaa!"
+ s = "Hello, wo.. wait, where am I?\n"
+ s2 = "<evil voice> Muhahahaa!"
- @f.write s
- @i.pos.should == @f.pos
+ @f.write s
+ @i.pos.should == @f.pos
- @i.rewind
- @i.gets.should == s
+ @i.rewind
+ @i.gets.should == s
- @i.rewind
- @i.write s2
+ @i.rewind
+ @i.write s2
- @f.rewind
- @f.gets.should == "#{s2}\n"
+ @f.rewind
+ @f.gets.should == "#{s2}\n"
+ end
end
-end
it "allows closing the new IO without affecting the original" do
@i.close
diff --git a/spec/ruby/core/io/external_encoding_spec.rb b/spec/ruby/core/io/external_encoding_spec.rb
index 2fcf1c7218..7765c6c0f5 100644
--- a/spec/ruby/core/io/external_encoding_spec.rb
+++ b/spec/ruby/core/io/external_encoding_spec.rb
@@ -94,12 +94,10 @@ describe "IO#external_encoding" do
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
+ 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
describe "with 'r' mode" do
diff --git a/spec/ruby/core/io/foreach_spec.rb b/spec/ruby/core/io/foreach_spec.rb
index c361d27879..6abe8901ba 100644
--- a/spec/ruby/core/io/foreach_spec.rb
+++ b/spec/ruby/core/io/foreach_spec.rb
@@ -14,33 +14,35 @@ describe "IO.foreach" do
IO.foreach(@name) { $..should == @count += 1 }
end
- describe "when the filename starts with |" 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
+ ruby_version_is ""..."4.0" do
+ describe "when the filename starts with |" 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
- suppress_warning do # https://bugs.ruby-lang.org/issues/19630
- IO.foreach(cmd) { |l| ScratchPad << l }
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ IO.foreach(cmd) { |l| ScratchPad << l }
+ end
+ ScratchPad.recorded.should == ["hello\n", "line2\n"]
end
- ScratchPad.recorded.should == ["hello\n", "line2\n"]
- end
- platform_is_not :windows do
- it "gets data from a fork when passed -" do
- parent_pid = $$
+ platform_is_not :windows do
+ it "gets data from a fork when passed -" do
+ parent_pid = $$
- suppress_warning do # https://bugs.ruby-lang.org/issues/19630
- IO.foreach("|-") { |l| ScratchPad << l }
- end
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ IO.foreach("|-") { |l| ScratchPad << l }
+ end
- if $$ == parent_pid
- ScratchPad.recorded.should == ["hello\n", "from a fork\n"]
- else # child
- puts "hello"
- puts "from a fork"
- exit!
+ if $$ == parent_pid
+ ScratchPad.recorded.should == ["hello\n", "from a fork\n"]
+ else # child
+ puts "hello"
+ puts "from a fork"
+ exit!
+ end
end
end
end
diff --git a/spec/ruby/core/io/internal_encoding_spec.rb b/spec/ruby/core/io/internal_encoding_spec.rb
index 60afaf2ebd..7a583d4bcb 100644
--- a/spec/ruby/core/io/internal_encoding_spec.rb
+++ b/spec/ruby/core/io/internal_encoding_spec.rb
@@ -113,12 +113,10 @@ describe "IO#internal_encoding" do
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
+ 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
describe "with 'r' mode" do
diff --git a/spec/ruby/core/io/path_spec.rb b/spec/ruby/core/io/path_spec.rb
index 8145c32f39..798adb2163 100644
--- a/spec/ruby/core/io/path_spec.rb
+++ b/spec/ruby/core/io/path_spec.rb
@@ -1,14 +1,12 @@
require_relative '../../spec_helper'
describe "IO#path" do
- ruby_version_is "3.2" do
- it "returns the path of the file associated with the IO object" do
- path = tmp("io_path.txt")
- File.open(path, "w") do |file|
- IO.new(file.fileno, path: file.path, autoclose: false).path.should == file.path
- end
- ensure
- File.unlink(path)
+ it "returns the path of the file associated with the IO object" do
+ path = tmp("io_path.txt")
+ File.open(path, "w") do |file|
+ IO.new(file.fileno, path: file.path, autoclose: false).path.should == file.path
end
+ ensure
+ File.unlink(path)
end
end
diff --git a/spec/ruby/core/io/popen_spec.rb b/spec/ruby/core/io/popen_spec.rb
index e9d32c5c7d..6043862614 100644
--- a/spec/ruby/core/io/popen_spec.rb
+++ b/spec/ruby/core/io/popen_spec.rb
@@ -95,6 +95,22 @@ describe "IO.popen" do
@io = IO.popen(ruby_cmd('exit 0'), mode)
end
+ it "accepts a path using the chdir: keyword argument" do
+ path = File.dirname(@fname)
+
+ @io = IO.popen(ruby_cmd("puts Dir.pwd"), "r", chdir: path)
+ @io.read.chomp.should == path
+ end
+
+ it "accepts a path using the chdir: keyword argument and a coercible path" do
+ path = File.dirname(@fname)
+ object = mock("path")
+ object.should_receive(:to_path).and_return(path)
+
+ @io = IO.popen(ruby_cmd("puts Dir.pwd"), "r", chdir: object)
+ @io.read.chomp.should == path
+ end
+
describe "with a block" do
it "yields an open IO to the block" do
IO.popen(ruby_cmd('exit'), "r") do |io|
diff --git a/spec/ruby/core/io/pread_spec.rb b/spec/ruby/core/io/pread_spec.rb
index 6d93b432c2..dc7bcedf3e 100644
--- a/spec/ruby/core/io/pread_spec.rb
+++ b/spec/ruby/core/io/pread_spec.rb
@@ -59,6 +59,12 @@ guard -> { platform_is_not :windows or ruby_version_is "3.3" } do
@file.pread(0, 4).should == ""
end
+ it "returns a buffer for maxlen = 0 when buffer specified" do
+ buffer = +"foo"
+ @file.pread(0, 4, buffer).should.equal?(buffer)
+ buffer.should == "foo"
+ end
+
it "ignores the offset for maxlen = 0, even if it is out of file bounds" do
@file.pread(0, 400).should == ""
end
diff --git a/spec/ruby/core/io/puts_spec.rb b/spec/ruby/core/io/puts_spec.rb
index 9ed343c94c..a186ddaa5d 100644
--- a/spec/ruby/core/io/puts_spec.rb
+++ b/spec/ruby/core/io/puts_spec.rb
@@ -33,7 +33,7 @@ describe "IO#puts" do
ScratchPad.recorded.should == "\n"
end
- it "writes empty string with a newline when when given nil as multiple args" do
+ it "writes empty string with a newline when given nil as multiple args" do
@io.puts(nil, nil).should == nil
ScratchPad.recorded.should == "\n\n"
end
diff --git a/spec/ruby/core/io/read_spec.rb b/spec/ruby/core/io/read_spec.rb
index 8741d9f017..988ec2ce30 100644
--- a/spec/ruby/core/io/read_spec.rb
+++ b/spec/ruby/core/io/read_spec.rb
@@ -168,76 +168,78 @@ describe "IO.read" do
end
end
-describe "IO.read from a pipe" do
- it "runs the rest as a subprocess and returns the standard output" do
- cmd = "|sh -c 'echo hello'"
- platform_is :windows do
- cmd = "|cmd.exe /C echo hello"
- end
-
- suppress_warning do # https://bugs.ruby-lang.org/issues/19630
- IO.read(cmd).should == "hello\n"
- end
- end
+ruby_version_is ""..."4.0" do
+ describe "IO.read from a pipe" do
+ it "runs the rest as a subprocess and returns the standard output" do
+ cmd = "|sh -c 'echo hello'"
+ platform_is :windows do
+ cmd = "|cmd.exe /C echo hello"
+ end
- platform_is_not :windows do
- it "opens a pipe to a fork if the rest is -" do
- str = nil
suppress_warning do # https://bugs.ruby-lang.org/issues/19630
- str = IO.read("|-")
+ IO.read(cmd).should == "hello\n"
end
+ end
- if str # parent
- str.should == "hello from child\n"
- else #child
- puts "hello from child"
- exit!
+ platform_is_not :windows do
+ it "opens a pipe to a fork if the rest is -" do
+ str = nil
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ str = IO.read("|-")
+ end
+
+ if str # parent
+ str.should == "hello from child\n"
+ else #child
+ puts "hello from child"
+ exit!
+ end
end
end
- end
- it "reads only the specified number of bytes requested" do
- cmd = "|sh -c 'echo hello'"
- platform_is :windows do
- cmd = "|cmd.exe /C echo hello"
- end
+ it "reads only the specified number of bytes requested" do
+ cmd = "|sh -c 'echo hello'"
+ platform_is :windows do
+ cmd = "|cmd.exe /C echo hello"
+ end
- suppress_warning do # https://bugs.ruby-lang.org/issues/19630
- IO.read(cmd, 1).should == "h"
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ IO.read(cmd, 1).should == "h"
+ end
end
- end
- platform_is_not :windows do
- it "raises Errno::ESPIPE if passed an offset" do
- -> {
- suppress_warning do # https://bugs.ruby-lang.org/issues/19630
- IO.read("|sh -c 'echo hello'", 1, 1)
- end
- }.should raise_error(Errno::ESPIPE)
+ platform_is_not :windows do
+ it "raises Errno::ESPIPE if passed an offset" do
+ -> {
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ IO.read("|sh -c 'echo hello'", 1, 1)
+ end
+ }.should raise_error(Errno::ESPIPE)
+ end
end
- end
-quarantine! do # The process tried to write to a nonexistent pipe.
- platform_is :windows do
- # TODO: It should raise Errno::ESPIPE on Windows as well
- # once https://bugs.ruby-lang.org/issues/12230 is fixed.
- it "raises Errno::EINVAL if passed an offset" do
- -> {
- suppress_warning do # https://bugs.ruby-lang.org/issues/19630
- IO.read("|cmd.exe /C echo hello", 1, 1)
+ quarantine! do # The process tried to write to a nonexistent pipe.
+ platform_is :windows do
+ # TODO: It should raise Errno::ESPIPE on Windows as well
+ # once https://bugs.ruby-lang.org/issues/12230 is fixed.
+ it "raises Errno::EINVAL if passed an offset" do
+ -> {
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ IO.read("|cmd.exe /C echo hello", 1, 1)
+ end
+ }.should raise_error(Errno::EINVAL)
end
- }.should raise_error(Errno::EINVAL)
+ end
end
- end
-end
- ruby_version_is "3.3" do
- # https://bugs.ruby-lang.org/issues/19630
- it "warns about deprecation given a path with a pipe" do
- cmd = "|echo ok"
- -> {
- IO.read(cmd)
- }.should complain(/IO process creation with a leading '\|'/)
+ ruby_version_is "3.3" do
+ # https://bugs.ruby-lang.org/issues/19630
+ it "warns about deprecation" do
+ cmd = "|echo ok"
+ -> {
+ IO.read(cmd)
+ }.should complain(/IO process creation with a leading '\|'/)
+ end
end
end
end
diff --git a/spec/ruby/core/io/readlines_spec.rb b/spec/ruby/core/io/readlines_spec.rb
index 3a6ff3d0f3..b4770775d1 100644
--- a/spec/ruby/core/io/readlines_spec.rb
+++ b/spec/ruby/core/io/readlines_spec.rb
@@ -174,45 +174,47 @@ describe "IO.readlines" do
$_.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 = nil
- suppress_warning do # https://bugs.ruby-lang.org/issues/19630
- lines = IO.readlines(cmd)
- end
- lines.should == ["hello\n", "line2\n"]
- end
+ ruby_version_is ""..."4.0" do
+ 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
- platform_is_not :windows do
- it "gets data from a fork when passed -" do
lines = nil
suppress_warning do # https://bugs.ruby-lang.org/issues/19630
- lines = IO.readlines("|-")
+ lines = IO.readlines(cmd)
end
+ lines.should == ["hello\n", "line2\n"]
+ end
- if lines # parent
- lines.should == ["hello\n", "from a fork\n"]
- else
- puts "hello"
- puts "from a fork"
- exit!
+ platform_is_not :windows do
+ it "gets data from a fork when passed -" do
+ lines = nil
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ lines = IO.readlines("|-")
+ end
+
+ if lines # parent
+ lines.should == ["hello\n", "from a fork\n"]
+ else
+ puts "hello"
+ puts "from a fork"
+ exit!
+ end
end
end
end
- end
- ruby_version_is "3.3" do
- # https://bugs.ruby-lang.org/issues/19630
- it "warns about deprecation given a path with a pipe" do
- cmd = "|echo ok"
- -> {
- IO.readlines(cmd)
- }.should complain(/IO process creation with a leading '\|'/)
+ ruby_version_is "3.3" do
+ # https://bugs.ruby-lang.org/issues/19630
+ it "warns about deprecation given a path with a pipe" do
+ cmd = "|echo ok"
+ -> {
+ IO.readlines(cmd)
+ }.should complain(/IO process creation with a leading '\|'/)
+ end
end
end
diff --git a/spec/ruby/core/io/readpartial_spec.rb b/spec/ruby/core/io/readpartial_spec.rb
index 0852f20b2d..176c33cf9e 100644
--- a/spec/ruby/core/io/readpartial_spec.rb
+++ b/spec/ruby/core/io/readpartial_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
@@ -93,12 +93,15 @@ describe "IO#readpartial" do
@rd.readpartial(0).should == ""
end
- ruby_bug "#18421", ""..."3.0.4" do
- it "clears and returns the given buffer if the length argument is 0" do
- buffer = +"existing content"
- @rd.readpartial(0, buffer).should == buffer
- buffer.should == ""
- end
+ it "raises IOError if the stream is closed and the length argument is 0" do
+ @rd.close
+ -> { @rd.readpartial(0) }.should raise_error(IOError, "closed stream")
+ end
+
+ it "clears and returns the given buffer if the length argument is 0" do
+ buffer = +"existing content"
+ @rd.readpartial(0, buffer).should == buffer
+ buffer.should == ""
end
it "preserves the encoding of the given buffer" do
diff --git a/spec/ruby/core/io/set_encoding_by_bom_spec.rb b/spec/ruby/core/io/set_encoding_by_bom_spec.rb
index 92433d6640..30d5ce5a5a 100644
--- a/spec/ruby/core/io/set_encoding_by_bom_spec.rb
+++ b/spec/ruby/core/io/set_encoding_by_bom_spec.rb
@@ -62,11 +62,11 @@ describe "IO#set_encoding_by_bom" do
@io.rewind
@io.set_encoding(Encoding::ASCII_8BIT)
- File.binwrite(@name, "\xFE\xFFabc")
+ File.binwrite(@name, "\xFE\xFFabcd")
@io.set_encoding_by_bom.should == Encoding::UTF_16BE
@io.external_encoding.should == Encoding::UTF_16BE
- @io.read.b.should == "abc".b
+ @io.read.b.should == "abcd".b
end
it "returns the result encoding if found BOM UTF_32LE sequence" do
@@ -94,11 +94,11 @@ describe "IO#set_encoding_by_bom" do
@io.rewind
@io.set_encoding(Encoding::ASCII_8BIT)
- File.binwrite(@name, "\x00\x00\xFE\xFFabc")
+ File.binwrite(@name, "\x00\x00\xFE\xFFabcd")
@io.set_encoding_by_bom.should == Encoding::UTF_32BE
@io.external_encoding.should == Encoding::UTF_32BE
- @io.read.b.should == "abc".b
+ @io.read.b.should == "abcd".b
end
it "returns nil if io is empty" do
diff --git a/spec/ruby/core/io/shared/each.rb b/spec/ruby/core/io/shared/each.rb
index aca622834f..0747f31b8a 100644
--- a/spec/ruby/core/io/shared/each.rb
+++ b/spec/ruby/core/io/shared/each.rb
@@ -202,20 +202,10 @@ describe :io_each, shared: true do
end
describe "when passed chomp and nil as a separator" do
- ruby_version_is "3.2" do
- it "yields self's content" do
- @io.pos = 100
- @io.send(@method, nil, chomp: true) { |s| ScratchPad << s }
- ScratchPad.recorded.should == ["qui a linha cinco.\nHere is line six.\n"]
- end
- end
-
- ruby_version_is ""..."3.2" do
- it "yields self's content without trailing new line character" do
- @io.pos = 100
- @io.send(@method, nil, chomp: true) { |s| ScratchPad << s }
- ScratchPad.recorded.should == ["qui a linha cinco.\nHere is line six."]
- end
+ it "yields self's content" do
+ @io.pos = 100
+ @io.send(@method, nil, chomp: true) { |s| ScratchPad << s }
+ ScratchPad.recorded.should == ["qui a linha cinco.\nHere is line six.\n"]
end
end
diff --git a/spec/ruby/core/io/shared/gets_ascii.rb b/spec/ruby/core/io/shared/gets_ascii.rb
index 2a8fe3c9a5..2bd5470d99 100644
--- a/spec/ruby/core/io/shared/gets_ascii.rb
+++ b/spec/ruby/core/io/shared/gets_ascii.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
describe :io_gets_ascii, shared: true do
describe "with ASCII separator" do
before :each do
diff --git a/spec/ruby/core/io/shared/new.rb b/spec/ruby/core/io/shared/new.rb
index cba5f33ebf..e84133493c 100644
--- a/spec/ruby/core/io/shared/new.rb
+++ b/spec/ruby/core/io/shared/new.rb
@@ -208,6 +208,26 @@ describe :io_new, shared: true do
@io.internal_encoding.to_s.should == 'IBM866'
end
+ it "does not use binary encoding when mode encoding is specified along with binmode: true option" do
+ @io = IO.send(@method, @fd, 'w:iso-8859-1', binmode: true)
+ @io.external_encoding.to_s.should == 'ISO-8859-1'
+ end
+
+ it "does not use textmode argument when mode encoding is specified" do
+ @io = IO.send(@method, @fd, 'w:ascii-8bit', textmode: true)
+ @io.external_encoding.to_s.should == 'ASCII-8BIT'
+ end
+
+ it "does not use binmode argument when external encoding is specified via the :external_encoding option" do
+ @io = IO.send(@method, @fd, 'w', binmode: true, external_encoding: 'iso-8859-1')
+ @io.external_encoding.to_s.should == 'ISO-8859-1'
+ end
+
+ it "does not use textmode argument when external encoding is specified via the :external_encoding option" do
+ @io = IO.send(@method, @fd, 'w', textmode: true, external_encoding: 'ascii-8bit')
+ @io.external_encoding.to_s.should == 'ASCII-8BIT'
+ end
+
it "raises ArgumentError for nil options" do
-> {
IO.send(@method, @fd, 'w', nil)
@@ -325,6 +345,9 @@ describe :io_new_errors, shared: true do
@io = IO.send(@method, @fd, 'w:ISO-8859-1', external_encoding: 'ISO-8859-1')
}.should raise_error(ArgumentError)
-> {
+ @io = IO.send(@method, @fd, 'w:ISO-8859-1', internal_encoding: 'ISO-8859-1')
+ }.should raise_error(ArgumentError)
+ -> {
@io = IO.send(@method, @fd, 'w:ISO-8859-1:UTF-8', internal_encoding: 'ISO-8859-1')
}.should raise_error(ArgumentError)
end
diff --git a/spec/ruby/core/io/sysread_spec.rb b/spec/ruby/core/io/sysread_spec.rb
index 8851214283..d56a27b3af 100644
--- a/spec/ruby/core/io/sysread_spec.rb
+++ b/spec/ruby/core/io/sysread_spec.rb
@@ -131,9 +131,7 @@ describe "IO#sysread" do
@read.sysread(3).should == "ab"
end
- guard_not -> { platform_is :windows and ruby_version_is ""..."3.2" } do # https://bugs.ruby-lang.org/issues/18880
- it "raises ArgumentError when length is less than 0" do
- -> { @read.sysread(-1) }.should raise_error(ArgumentError)
- end
+ it "raises ArgumentError when length is less than 0" do
+ -> { @read.sysread(-1) }.should raise_error(ArgumentError)
end
end
diff --git a/spec/ruby/core/io/write_nonblock_spec.rb b/spec/ruby/core/io/write_nonblock_spec.rb
index c403c864fd..5bfc690f9b 100644
--- a/spec/ruby/core/io/write_nonblock_spec.rb
+++ b/spec/ruby/core/io/write_nonblock_spec.rb
@@ -43,7 +43,7 @@ platform_is_not :windows do
it "checks if the file is writable if writing zero bytes" do
-> {
- @readonly_file.write_nonblock("")
+ @readonly_file.write_nonblock("")
}.should raise_error(IOError)
end
end
diff --git a/spec/ruby/core/io/write_spec.rb b/spec/ruby/core/io/write_spec.rb
index 4a26f8dbaf..e58100f846 100644
--- a/spec/ruby/core/io/write_spec.rb
+++ b/spec/ruby/core/io/write_spec.rb
@@ -220,7 +220,7 @@ describe "IO.write" do
end
end
- ruby_version_is "3.3" do
+ ruby_version_is "3.3"..."4.0" do
# https://bugs.ruby-lang.org/issues/19630
it "warns about deprecation given a path with a pipe" do
-> {
diff --git a/spec/ruby/core/kernel/Float_spec.rb b/spec/ruby/core/kernel/Float_spec.rb
index 0f83cb5824..9c436b05f7 100644
--- a/spec/ruby/core/kernel/Float_spec.rb
+++ b/spec/ruby/core/kernel/Float_spec.rb
@@ -157,6 +157,26 @@ describe :kernel_float, shared: true do
@object.send(:Float, "1\t\n").should == 1.0
end
+ ruby_version_is ""..."3.4" do
+ it "raises ArgumentError if a fractional part is missing" do
+ -> { @object.send(:Float, "1.") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "+1.") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "-1.") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "1.e+0") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "1.e-2") }.should raise_error(ArgumentError)
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "allows String representation without a fractional part" do
+ @object.send(:Float, "1.").should == 1.0
+ @object.send(:Float, "+1.").should == 1.0
+ @object.send(:Float, "-1.").should == -1.0
+ @object.send(:Float, "1.e+0").should == 1.0
+ @object.send(:Float, "1.e-2").should be_close(0.01, TOLERANCE)
+ end
+ end
+
%w(e E).each do |e|
it "raises an ArgumentError if #{e} is the trailing character" do
-> { @object.send(:Float, "2#{e}") }.should raise_error(ArgumentError)
@@ -204,59 +224,107 @@ describe :kernel_float, shared: true do
end
end
- describe "for hexadecimal literals with binary exponent" do
- %w(p P).each do |p|
- it "interprets the fractional part (on the left side of '#{p}') in hexadecimal" do
- @object.send(:Float, "0x10#{p}0").should == 16.0
- end
-
- it "interprets the exponent (on the right of '#{p}') in decimal" do
- @object.send(:Float, "0x1#{p}10").should == 1024.0
- end
-
- it "raises an ArgumentError if #{p} is the trailing character" do
- -> { @object.send(:Float, "0x1#{p}") }.should raise_error(ArgumentError)
- end
-
- it "raises an ArgumentError if #{p} is the leading character" do
- -> { @object.send(:Float, "0x#{p}1") }.should raise_error(ArgumentError)
- end
+ context "for hexadecimal literals" do
+ it "interprets the 0x prefix as hexadecimal" do
+ @object.send(:Float, "0x10").should == 16.0
+ @object.send(:Float, "0x0F").should == 15.0
+ @object.send(:Float, "0x0f").should == 15.0
+ end
- it "returns Infinity for '0x1#{p}10000'" do
- @object.send(:Float, "0x1#{p}10000").should == Float::INFINITY
- end
+ it "interprets negative hex value" do
+ @object.send(:Float, "-0x10").should == -16.0
+ end
- it "returns 0 for '0x1#{p}-10000'" do
- @object.send(:Float, "0x1#{p}-10000").should == 0
- end
+ it "accepts embedded _ if the number does not contain a-f" do
+ @object.send(:Float, "0x1_0").should == 16.0
+ end
- it "allows embedded _ in a number on either side of the #{p}" do
- @object.send(:Float, "0x1_0#{p}10").should == 16384.0
- @object.send(:Float, "0x10#{p}1_0").should == 16384.0
- @object.send(:Float, "0x1_0#{p}1_0").should == 16384.0
+ ruby_version_is ""..."3.4.3" do
+ it "does not accept embedded _ if the number contains a-f" do
+ -> { @object.send(:Float, "0x1_0a") }.should raise_error(ArgumentError)
+ @object.send(:Float, "0x1_0a", exception: false).should be_nil
end
+ end
- it "raises an exception if a space is embedded on either side of the '#{p}'" do
- -> { @object.send(:Float, "0x1 0#{p}10") }.should raise_error(ArgumentError)
- -> { @object.send(:Float, "0x10#{p}1 0") }.should raise_error(ArgumentError)
+ ruby_version_is "3.4.3" do
+ it "accepts embedded _ if the number contains a-f" do
+ @object.send(:Float, "0x1_0a").should == 0x10a.to_f
end
+ end
- it "raises an exception if there's a leading _ on either side of the '#{p}'" do
- -> { @object.send(:Float, "0x_10#{p}10") }.should raise_error(ArgumentError)
- -> { @object.send(:Float, "0x10#{p}_10") }.should raise_error(ArgumentError)
- end
+ it "does not accept _ before, after or inside the 0x prefix" do
+ -> { @object.send(:Float, "_0x10") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "0_x10") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "0x_10") }.should raise_error(ArgumentError)
+ @object.send(:Float, "_0x10", exception: false).should be_nil
+ @object.send(:Float, "0_x10", exception: false).should be_nil
+ @object.send(:Float, "0x_10", exception: false).should be_nil
+ end
- it "raises an exception if there's a trailing _ on either side of the '#{p}'" do
- -> { @object.send(:Float, "0x10_#{p}10") }.should raise_error(ArgumentError)
- -> { @object.send(:Float, "0x10#{p}10_") }.should raise_error(ArgumentError)
- end
+ it "parses negative hexadecimal string as negative float" do
+ @object.send(:Float, "-0x7b").should == -123.0
+ end
- it "allows hexadecimal points on the left side of the '#{p}'" do
- @object.send(:Float, "0x1.8#{p}0").should == 1.5
+ ruby_version_is "3.4" do
+ it "accepts a fractional part" do
+ @object.send(:Float, "0x0.8").should == 0.5
end
+ end
- it "raises an ArgumentError if there's a decimal point on the right side of the '#{p}'" do
- -> { @object.send(:Float, "0x1#{p}1.0") }.should raise_error(ArgumentError)
+ describe "with binary exponent" do
+ %w(p P).each do |p|
+ it "interprets the fractional part (on the left side of '#{p}') in hexadecimal" do
+ @object.send(:Float, "0x10#{p}0").should == 16.0
+ end
+
+ it "interprets the exponent (on the right of '#{p}') in decimal" do
+ @object.send(:Float, "0x1#{p}10").should == 1024.0
+ end
+
+ it "raises an ArgumentError if #{p} is the trailing character" do
+ -> { @object.send(:Float, "0x1#{p}") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError if #{p} is the leading character" do
+ -> { @object.send(:Float, "0x#{p}1") }.should raise_error(ArgumentError)
+ end
+
+ it "returns Infinity for '0x1#{p}10000'" do
+ @object.send(:Float, "0x1#{p}10000").should == Float::INFINITY
+ end
+
+ it "returns 0 for '0x1#{p}-10000'" do
+ @object.send(:Float, "0x1#{p}-10000").should == 0
+ end
+
+ it "allows embedded _ in a number on either side of the #{p}" do
+ @object.send(:Float, "0x1_0#{p}10").should == 16384.0
+ @object.send(:Float, "0x10#{p}1_0").should == 16384.0
+ @object.send(:Float, "0x1_0#{p}1_0").should == 16384.0
+ end
+
+ it "raises an exception if a space is embedded on either side of the '#{p}'" do
+ -> { @object.send(:Float, "0x1 0#{p}10") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "0x10#{p}1 0") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an exception if there's a leading _ on either side of the '#{p}'" do
+ -> { @object.send(:Float, "0x_10#{p}10") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "0x10#{p}_10") }.should raise_error(ArgumentError)
+ end
+
+ it "raises an exception if there's a trailing _ on either side of the '#{p}'" do
+ -> { @object.send(:Float, "0x10_#{p}10") }.should raise_error(ArgumentError)
+ -> { @object.send(:Float, "0x10#{p}10_") }.should raise_error(ArgumentError)
+ end
+
+ it "allows hexadecimal points on the left side of the '#{p}'" do
+ @object.send(:Float, "0x1.8#{p}0").should == 1.5
+ end
+
+ it "raises an ArgumentError if there's a decimal point on the right side of the '#{p}'" do
+ -> { @object.send(:Float, "0x1#{p}1.0") }.should raise_error(ArgumentError)
+ end
end
end
end
@@ -280,7 +348,7 @@ describe :kernel_float, shared: true do
nan2.should equal(nan)
end
- it "returns the identical Infinity if to_f is called and it returns Infinity" do
+ it "returns the identical Infinity if #to_f is called and it returns Infinity" do
infinity = infinity_value
(infinity_to_f = mock('Infinity')).should_receive(:to_f).once.and_return(infinity)
infinity2 = @object.send(:Float, infinity_to_f)
diff --git a/spec/ruby/core/kernel/Rational_spec.rb b/spec/ruby/core/kernel/Rational_spec.rb
index 2d1051db7f..cc11a35451 100644
--- a/spec/ruby/core/kernel/Rational_spec.rb
+++ b/spec/ruby/core/kernel/Rational_spec.rb
@@ -1,6 +1,236 @@
require_relative '../../spec_helper'
-require_relative '../../shared/rational/Rational'
+require_relative '../rational/fixtures/rational'
describe "Kernel.Rational" do
- it_behaves_like :kernel_Rational, :Rational
+ describe "passed Integer" do
+ # Guard against the Mathn library
+ guard -> { !defined?(Math.rsqrt) } do
+ it "returns a new Rational number with 1 as the denominator" do
+ Rational(1).should eql(Rational(1, 1))
+ Rational(-3).should eql(Rational(-3, 1))
+ Rational(bignum_value).should eql(Rational(bignum_value, 1))
+ end
+ end
+ end
+
+ describe "passed two integers" do
+ it "returns a new Rational number" do
+ rat = Rational(1, 2)
+ rat.numerator.should == 1
+ rat.denominator.should == 2
+ rat.should be_an_instance_of(Rational)
+
+ rat = Rational(-3, -5)
+ rat.numerator.should == 3
+ rat.denominator.should == 5
+ rat.should be_an_instance_of(Rational)
+
+ rat = Rational(bignum_value, 3)
+ rat.numerator.should == bignum_value
+ rat.denominator.should == 3
+ rat.should be_an_instance_of(Rational)
+ end
+
+ it "reduces the Rational" do
+ rat = Rational(2, 4)
+ rat.numerator.should == 1
+ rat.denominator.should == 2
+
+ rat = Rational(3, 9)
+ rat.numerator.should == 1
+ rat.denominator.should == 3
+ end
+ end
+
+ describe "when passed a String" do
+ it "converts the String to a Rational using the same method as String#to_r" do
+ r = Rational(13, 25)
+ s_r = ".52".to_r
+ r_s = Rational(".52")
+
+ r_s.should == r
+ r_s.should == s_r
+ end
+
+ it "scales the Rational value of the first argument by the Rational value of the second" do
+ Rational(".52", ".6").should == Rational(13, 15)
+ Rational(".52", "1.6").should == Rational(13, 40)
+ end
+
+ it "does not use the same method as Float#to_r" do
+ r = Rational(3, 5)
+ f_r = 0.6.to_r
+ r_s = Rational("0.6")
+
+ r_s.should == r
+ r_s.should_not == f_r
+ end
+ end
+
+ describe "when passed a Numeric" do
+ it "calls #to_r to convert the first argument to a Rational" do
+ num = RationalSpecs::SubNumeric.new(2)
+
+ Rational(num).should == Rational(2)
+ end
+ end
+
+ describe "when passed a Complex" do
+ context "[Complex]" do
+ it "returns a Rational from the real part if the imaginary part is 0" do
+ Rational(Complex(1, 0)).should == Rational(1)
+ end
+
+ it "raises a RangeError if the imaginary part is not 0" do
+ -> { Rational(Complex(1, 2)) }.should raise_error(RangeError, "can't convert 1+2i into Rational")
+ end
+ end
+
+ context "[Numeric, Complex]" do
+ it "uses the real part if the imaginary part is 0" do
+ Rational(1, Complex(2, 0)).should == Rational(1, 2)
+ end
+
+ it "divides a numerator by the Complex denominator if the imaginary part is not 0" do
+ Rational(1, Complex(2, 1)).should == Complex(2/5r, -1/5r)
+ end
+ end
+ end
+
+ context "when passed neither a Numeric nor a String" do
+ it "converts to Rational with #to_r method" do
+ obj = Object.new
+ def obj.to_r; 1/2r; end
+
+ Rational(obj).should == 1/2r
+ end
+
+ it "tries to convert to Integer with #to_int method if it does not respond to #to_r" do
+ obj = Object.new
+ def obj.to_int; 1; end
+
+ Rational(obj).should == 1r
+ end
+
+ it "raises TypeError if it neither responds to #to_r nor #to_int method" do
+ -> { Rational([]) }.should raise_error(TypeError, "can't convert Array into Rational")
+ -> { Rational({}) }.should raise_error(TypeError, "can't convert Hash into Rational")
+ -> { Rational(nil) }.should raise_error(TypeError, "can't convert nil into Rational")
+ end
+
+ it "swallows exception raised in #to_int method" do
+ object = Object.new
+ def object.to_int() raise NoMethodError; end
+
+ -> { Rational(object) }.should raise_error(TypeError)
+ -> { Rational(object, 1) }.should raise_error(TypeError)
+ -> { Rational(1, object) }.should raise_error(TypeError)
+ end
+
+ it "raises TypeError if #to_r does not return Rational" do
+ obj = Object.new
+ def obj.to_r; []; end
+
+ -> { Rational(obj) }.should raise_error(TypeError, "can't convert Object to Rational (Object#to_r gives Array)")
+ end
+ end
+
+ it "raises a ZeroDivisionError if the second argument is 0" do
+ -> { Rational(1, 0) }.should raise_error(ZeroDivisionError, "divided by 0")
+ -> { Rational(1, 0.0) }.should raise_error(ZeroDivisionError, "divided by 0")
+ end
+
+ it "raises a TypeError if the first argument is nil" do
+ -> { Rational(nil) }.should raise_error(TypeError, "can't convert nil into Rational")
+ end
+
+ it "raises a TypeError if the second argument is nil" do
+ -> { Rational(1, nil) }.should raise_error(TypeError, "can't convert nil into Rational")
+ end
+
+ it "raises a TypeError if the first argument is a Symbol" do
+ -> { Rational(:sym) }.should raise_error(TypeError)
+ end
+
+ it "raises a TypeError if the second argument is a Symbol" do
+ -> { Rational(1, :sym) }.should raise_error(TypeError)
+ 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
+
+ it "swallows an exception raised in #to_r" do
+ obj = Object.new
+ def obj.to_r; raise; end
+ Rational(obj, exception: false).should == nil
+ end
+
+ it "swallows an exception raised in #to_int" do
+ obj = Object.new
+ def obj.to_int; raise; end
+ Rational(obj, 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
+
+ it "swallows an exception raised in #to_r" do
+ obj = Object.new
+ def obj.to_r; raise; end
+ Rational(obj, 1, exception: false).should == nil
+ end
+
+ it "swallows an exception raised in #to_int" do
+ obj = Object.new
+ def obj.to_int; raise; end
+ Rational(obj, 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
+
+ it "swallows an exception raised in #to_r" do
+ obj = Object.new
+ def obj.to_r; raise; end
+ Rational(obj, obj, exception: false).should == nil
+ end
+
+ it "swallows an exception raised in #to_int" do
+ obj = Object.new
+ def obj.to_int; raise; end
+ Rational(obj, obj, 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
+ 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
+
+ it "freezes its result" do
+ Rational(1).frozen?.should == true
+ end
end
diff --git a/spec/ruby/core/kernel/autoload_spec.rb b/spec/ruby/core/kernel/autoload_spec.rb
index 0404caec6d..5edb70541d 100644
--- a/spec/ruby/core/kernel/autoload_spec.rb
+++ b/spec/ruby/core/kernel/autoload_spec.rb
@@ -7,7 +7,9 @@ require_relative 'fixtures/classes'
autoload :KSAutoloadA, "autoload_a.rb"
autoload :KSAutoloadB, fixture(__FILE__, "autoload_b.rb")
-autoload :KSAutoloadCallsRequire, "main_autoload_not_exist.rb"
+define_autoload_KSAutoloadCallsRequire = -> {
+ autoload :KSAutoloadCallsRequire, "main_autoload_not_exist.rb"
+}
def check_autoload(const)
autoload? const
@@ -43,6 +45,7 @@ describe "Kernel#autoload" do
end
it "calls main.require(path) to load the file" do
+ define_autoload_KSAutoloadCallsRequire.call
main = TOPLEVEL_BINDING.eval("self")
main.should_receive(:require).with("main_autoload_not_exist.rb")
# The constant won't be defined since require is mocked to do nothing
diff --git a/spec/ruby/core/kernel/block_given_spec.rb b/spec/ruby/core/kernel/block_given_spec.rb
index b00bfabfc3..aece4c821d 100644
--- a/spec/ruby/core/kernel/block_given_spec.rb
+++ b/spec/ruby/core/kernel/block_given_spec.rb
@@ -5,15 +5,20 @@ describe :kernel_block_given, shared: true do
it "returns true if and only if a block is supplied" do
@object.accept_block {}.should == true
@object.accept_block_as_argument {}.should == true
+ @object.accept_block_inside_block {}.should == true
+ @object.accept_block_as_argument_inside_block {}.should == true
@object.accept_block.should == false
@object.accept_block_as_argument.should == false
+ @object.accept_block_inside_block.should == false
+ @object.accept_block_as_argument_inside_block.should == false
end
# Clarify: Based on http://www.ruby-forum.com/topic/137822 it appears
# that Matz wanted this to be true in 1.9.
it "returns false when a method defined by define_method is called with a block" do
@object.defined_block {}.should == false
+ @object.defined_block_inside_block {}.should == false
end
end
diff --git a/spec/ruby/core/kernel/caller_locations_spec.rb b/spec/ruby/core/kernel/caller_locations_spec.rb
index aaacd9a910..a917dba504 100644
--- a/spec/ruby/core/kernel/caller_locations_spec.rb
+++ b/spec/ruby/core/kernel/caller_locations_spec.rb
@@ -83,7 +83,7 @@ describe 'Kernel#caller_locations' do
end
end
- ruby_version_is "3.4" do
+ ruby_version_is "3.4"..."4.0" do
it "includes core library methods defined in Ruby" do
file, line = Kernel.instance_method(:tap).source_location
file.should.start_with?('<internal:')
@@ -94,5 +94,17 @@ describe 'Kernel#caller_locations' do
loc.path.should.start_with? "<internal:"
end
end
+
+ ruby_version_is "4.0" do
+ it "does not include core library methods defined in Ruby" do
+ file, line = Kernel.instance_method(:tap).source_location
+ file.should.start_with?('<internal:')
+
+ loc = nil
+ tap { loc = caller_locations(1, 1)[0] }
+ loc.label.should == "Kernel#tap"
+ loc.path.should == __FILE__
+ end
+ end
end
end
diff --git a/spec/ruby/core/kernel/caller_spec.rb b/spec/ruby/core/kernel/caller_spec.rb
index c3d63ccb00..7cd703de5a 100644
--- a/spec/ruby/core/kernel/caller_spec.rb
+++ b/spec/ruby/core/kernel/caller_spec.rb
@@ -43,26 +43,67 @@ describe 'Kernel#caller' do
lines[1].should =~ /\A#{path}:2:in [`']block in <main>'\n\z/
end
+ it "can be called with a range" do
+ locations1 = caller(0)
+ locations2 = caller(2..4)
+ locations1[2..4].should == locations2
+ 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)
+ locations2.should == locations1[2..-1]
end
it "works with beginless ranges" do
locations1 = KernelSpecs::CallerTest.locations(0)
locations2 = KernelSpecs::CallerTest.locations((..5))
- locations2.map(&:to_s)[eval("(2..)")].should == locations1[(..5)].map(&:to_s)[eval("(2..)")]
+ locations2[eval("(2..)")].should == locations1[(..5)][eval("(2..)")]
+ end
+
+ it "can be called with a range whose end is negative" do
+ locations1 = caller(0)
+ locations2 = caller(2..-1)
+ locations3 = caller(2..-2)
+ locations1[2..-1].should == locations2
+ locations1[2..-2].should == locations3
+ end
+
+ it "must return nil if omitting more locations than available" do
+ caller(100).should == nil
+ caller(100..-1).should == nil
+ end
+
+ it "must return [] if omitting exactly the number of locations available" do
+ omit = caller(0).length
+ caller(omit).should == []
+ end
+
+ it "must return the same locations when called with 1..-1 and when called with no arguments" do
+ caller.should == caller(1..-1)
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?('<internal:')
+ ruby_version_is ""..."4.0" do
+ it "includes core library methods defined in Ruby" do
+ file, line = Kernel.instance_method(:tap).source_location
+ file.should.start_with?('<internal:')
+
+ loc = nil
+ tap { loc = caller(1, 1)[0] }
+ loc.should =~ /\A<internal:.*in [`'](?:Kernel#)?tap'\z/
+ end
+ end
+
+ ruby_version_is "4.0" do
+ it "includes core library methods defined in Ruby" do
+ file, line = Kernel.instance_method(:tap).source_location
+ file.should.start_with?('<internal:')
- loc = nil
- tap { loc = caller(1, 1)[0] }
- loc.should =~ /\A<internal:.*in [`'](?:Kernel#)?tap'\z/
+ loc = nil
+ tap { loc = caller(1, 1)[0] }
+ loc.should =~ /\A#{ __FILE__ }:.*in [`'](?:Kernel#)?tap'\z/
+ end
end
end
end
diff --git a/spec/ruby/core/kernel/eval_spec.rb b/spec/ruby/core/kernel/eval_spec.rb
index 454bc4a58e..e027294347 100644
--- a/spec/ruby/core/kernel/eval_spec.rb
+++ b/spec/ruby/core/kernel/eval_spec.rb
@@ -175,6 +175,75 @@ describe "Kernel#eval" do
end
end
+ context "parameter forwarding" do
+ it "allows anonymous rest parameter forwarding" do
+ object = Object.new
+ def object.foo(a, b, c)
+ [a, b, c]
+ end
+ def object.bar(*)
+ eval "foo(*)"
+ end
+
+ object.bar(1, 2, 3).should == [1, 2, 3]
+ end
+
+ it "allows anonymous keyword parameters forwarding" do
+ object = Object.new
+ def object.foo(a:, b:, c:)
+ [a, b, c]
+ end
+ def object.bar(**)
+ eval "foo(**)"
+ end
+
+ object.bar(a: 1, b: 2, c: 3).should == [1, 2, 3]
+ end
+
+ it "allows anonymous block parameter forwarding" do
+ object = Object.new
+ def object.foo(&block)
+ block.call
+ end
+ def object.bar(&)
+ eval "foo(&)"
+ end
+
+ object.bar { :foobar }.should == :foobar
+ end
+
+ it "allows ... forwarding" do
+ object = Object.new
+ def object.foo(a, b:, &block)
+ [a, b, block.call]
+ end
+ def object.bar(...)
+ eval "foo(...)"
+ end
+
+ object.bar(1, b: 2) { 3 }.should == [1, 2, 3]
+ end
+
+ it "allows parameter forwarding to super" do
+ m = Module.new do
+ def foo(a, b:, &block)
+ [a, b, block.call]
+ end
+ end
+
+ c = Class.new do
+ include m
+
+ def foo(a, b:, &block)
+ eval "super"
+ end
+ end
+
+ object = c.new
+ object.foo(1, b: 2) { 3 }.should == [1, 2, 3]
+ end
+ end
+
ruby_version_is "3.3" do
it "uses (eval at __FILE__:__LINE__) if none is provided" do
eval("__FILE__").should == "(eval at #{__FILE__}:#{__LINE__})"
@@ -274,6 +343,26 @@ describe "Kernel#eval" do
eval("").should == nil
end
+ context "with shebang" do
+ it "ignores shebang with ruby interpreter" do
+ pid = eval(<<~CODE.b)
+ #!/usr/bin/env ruby
+ Process.pid
+ CODE
+
+ pid.should == Process.pid
+ end
+
+ it "ignores shebang with non-ruby interpreter" do
+ pid = eval(<<~CODE.b)
+ #!/usr/bin/env puma
+ Process.pid
+ CODE
+
+ pid.should == Process.pid
+ 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
@@ -293,6 +382,8 @@ CODE
eval(code)
EvalSpecs.constants(false).should include(:"Vπ")
EvalSpecs::Vπ.should == 3.14
+ ensure
+ EvalSpecs.send(:remove_const, :Vπ)
end
it "allows an emacs-style magic comment encoding" do
@@ -306,6 +397,8 @@ CODE
eval(code)
EvalSpecs.constants(false).should include(:"Vπemacs")
EvalSpecs::Vπemacs.should == 3.14
+ ensure
+ EvalSpecs.send(:remove_const, :Vπemacs)
end
it "allows spaces before the magic encoding comment" do
@@ -319,6 +412,8 @@ CODE
eval(code)
EvalSpecs.constants(false).should include(:"Vπspaces")
EvalSpecs::Vπspaces.should == 3.14
+ ensure
+ EvalSpecs.send(:remove_const, :Vπspaces)
end
it "allows a shebang line before the magic encoding comment" do
@@ -333,6 +428,8 @@ CODE
eval(code)
EvalSpecs.constants(false).should include(:"Vπshebang")
EvalSpecs::Vπshebang.should == 3.14
+ ensure
+ EvalSpecs.send(:remove_const, :Vπshebang)
end
it "allows a shebang line and some spaces before the magic encoding comment" do
@@ -347,6 +444,8 @@ CODE
eval(code)
EvalSpecs.constants(false).should include(:"Vπshebang_spaces")
EvalSpecs::Vπshebang_spaces.should == 3.14
+ ensure
+ EvalSpecs.send(:remove_const, :Vπshebang_spaces)
end
it "allows a magic encoding comment and a subsequent frozen_string_literal magic comment" do
@@ -365,6 +464,8 @@ CODE
EvalSpecs::Vπstring.should == "frozen"
EvalSpecs::Vπstring.encoding.should == Encoding::UTF_8
EvalSpecs::Vπstring.frozen?.should == !frozen_string_default
+ ensure
+ EvalSpecs.send(:remove_const, :Vπstring)
end
it "allows a magic encoding comment and a frozen_string_literal magic comment on the same line in emacs style" do
@@ -380,6 +481,8 @@ CODE
EvalSpecs::Vπsame_line.should == "frozen"
EvalSpecs::Vπsame_line.encoding.should == Encoding::UTF_8
EvalSpecs::Vπsame_line.frozen?.should be_true
+ ensure
+ EvalSpecs.send(:remove_const, :Vπsame_line)
end
it "ignores the magic encoding comment if it is after a frozen_string_literal magic comment" do
@@ -400,6 +503,8 @@ CODE
value.should == "frozen"
value.encoding.should == Encoding::BINARY
value.frozen?.should == !frozen_string_default
+ ensure
+ EvalSpecs.send(:remove_const, binary_constant)
end
it "ignores the frozen_string_literal magic comment if it appears after a token and warns if $VERBOSE is true" do
diff --git a/spec/ruby/core/kernel/extend_spec.rb b/spec/ruby/core/kernel/extend_spec.rb
index 47b22f3a18..6342d8cae1 100644
--- a/spec/ruby/core/kernel/extend_spec.rb
+++ b/spec/ruby/core/kernel/extend_spec.rb
@@ -76,4 +76,16 @@ describe "Kernel#extend" do
-> { @frozen.extend @module }.should raise_error(FrozenError)
end
end
+
+ it "updated class methods of a module when it extends self and includes another module" do
+ a = Module.new do
+ extend self
+ end
+ b = Module.new do
+ def foo; :foo; end
+ end
+
+ a.include b
+ a.foo.should == :foo
+ end
end
diff --git a/spec/ruby/core/kernel/fixtures/classes.rb b/spec/ruby/core/kernel/fixtures/classes.rb
index 541a4c075e..0e2b81988f 100644
--- a/spec/ruby/core/kernel/fixtures/classes.rb
+++ b/spec/ruby/core/kernel/fixtures/classes.rb
@@ -219,10 +219,28 @@ module KernelSpecs
block_given?
end
+ def self.accept_block_inside_block()
+ yield_self {
+ block_given?
+ }
+ end
+
+ def self.accept_block_as_argument_inside_block(&block)
+ yield_self {
+ block_given?
+ }
+ end
+
class << self
define_method(:defined_block) do
block_given?
end
+
+ define_method(:defined_block_inside_block) do
+ yield_self {
+ block_given?
+ }
+ end
end
end
@@ -235,10 +253,28 @@ module KernelSpecs
self.send(:block_given?)
end
+ def self.accept_block_inside_block
+ yield_self {
+ self.send(:block_given?)
+ }
+ end
+
+ def self.accept_block_as_argument_inside_block(&block)
+ yield_self {
+ self.send(:block_given?)
+ }
+ end
+
class << self
define_method(:defined_block) do
self.send(:block_given?)
end
+
+ define_method(:defined_block_inside_block) do
+ yield_self {
+ self.send(:block_given?)
+ }
+ end
end
end
@@ -251,10 +287,28 @@ module KernelSpecs
Kernel.block_given?
end
+ def self.accept_block_inside_block
+ yield_self {
+ Kernel.block_given?
+ }
+ end
+
+ def self.accept_block_as_argument_inside_block(&block)
+ yield_self {
+ Kernel.block_given?
+ }
+ end
+
class << self
define_method(:defined_block) do
Kernel.block_given?
end
+
+ define_method(:defined_block_inside_block) do
+ yield_self {
+ Kernel.block_given?
+ }
+ end
end
end
diff --git a/spec/ruby/core/kernel/format_spec.rb b/spec/ruby/core/kernel/format_spec.rb
index e8b031e480..1d0c000c15 100644
--- a/spec/ruby/core/kernel/format_spec.rb
+++ b/spec/ruby/core/kernel/format_spec.rb
@@ -12,4 +12,36 @@ describe "Kernel.format" do
it "is accessible as a module function" do
Kernel.format("%s", "hello").should == "hello"
end
+
+ describe "when $VERBOSE is true" do
+ it "warns if too many arguments are passed" do
+ code = <<~RUBY
+ $VERBOSE = true
+ format("test", 1)
+ RUBY
+
+ ruby_exe(code, args: "2>&1").should include("warning: too many arguments for format string")
+ end
+
+ it "does not warns if too many keyword arguments are passed" do
+ code = <<~RUBY
+ $VERBOSE = true
+ format("test %{test}", test: 1, unused: 2)
+ RUBY
+
+ ruby_exe(code, args: "2>&1").should_not include("warning")
+ end
+
+ ruby_bug "#20593", ""..."3.4" do
+ it "doesn't warns if keyword arguments are passed and none are used" do
+ code = <<~RUBY
+ $VERBOSE = true
+ format("test", test: 1)
+ format("test", {})
+ RUBY
+
+ ruby_exe(code, args: "2>&1").should_not include("warning")
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/kernel/inspect_spec.rb b/spec/ruby/core/kernel/inspect_spec.rb
index 1f9ce834ab..1fa66cab98 100644
--- a/spec/ruby/core/kernel/inspect_spec.rb
+++ b/spec/ruby/core/kernel/inspect_spec.rb
@@ -28,4 +28,63 @@ describe "Kernel#inspect" do
end
obj.inspect.should be_kind_of(String)
end
+
+ ruby_version_is "4.0" do
+ it "calls #instance_variables_to_inspect private method to know which variables to display" do
+ obj = Object.new
+ obj.instance_eval do
+ @host = "localhost"
+ @user = "root"
+ @password = "hunter2"
+ end
+ obj.singleton_class.class_eval do
+ private def instance_variables_to_inspect = %i[@host @user @does_not_exist]
+ end
+
+ inspected = obj.inspect.sub(/^#<Object:0x[0-9a-f]+/, '#<Object:0x00')
+ inspected.should == '#<Object:0x00 @host="localhost", @user="root">'
+
+ obj = Object.new
+ obj.instance_eval do
+ @host = "localhost"
+ @user = "root"
+ @password = "hunter2"
+ end
+ obj.singleton_class.class_eval do
+ private def instance_variables_to_inspect = []
+ end
+
+ inspected = obj.inspect.sub(/^#<Object:0x[0-9a-f]+/, '#<Object:0x00')
+ inspected.should == "#<Object:0x00>"
+ end
+
+ it "displays all instance variables if #instance_variables_to_inspect returns nil" do
+ obj = Object.new
+ obj.instance_eval do
+ @host = "localhost"
+ @user = "root"
+ @password = "hunter2"
+ end
+ obj.singleton_class.class_eval do
+ private def instance_variables_to_inspect = nil
+ end
+
+ inspected = obj.inspect.sub(/^#<Object:0x[0-9a-f]+/, '#<Object:0x00')
+ inspected.should == %{#<Object:0x00 @host="localhost", @user="root", @password="hunter2">}
+ end
+
+ it "raises an error if #instance_variables_to_inspect returns an invalid value" do
+ obj = Object.new
+ obj.instance_eval do
+ @host = "localhost"
+ @user = "root"
+ @password = "hunter2"
+ end
+ obj.singleton_class.class_eval do
+ private def instance_variables_to_inspect = {}
+ end
+
+ ->{ obj.inspect }.should raise_error(TypeError, "Expected #instance_variables_to_inspect to return an Array or nil, but it returned Hash")
+ end
+ end
end
diff --git a/spec/ruby/core/kernel/is_a_spec.rb b/spec/ruby/core/kernel/is_a_spec.rb
index dc69766f83..bd8c96529a 100644
--- a/spec/ruby/core/kernel/is_a_spec.rb
+++ b/spec/ruby/core/kernel/is_a_spec.rb
@@ -2,5 +2,5 @@ require_relative '../../spec_helper'
require_relative 'shared/kind_of'
describe "Kernel#is_a?" do
- it_behaves_like :kernel_kind_of , :is_a?
+ it_behaves_like :kernel_kind_of, :is_a?
end
diff --git a/spec/ruby/core/kernel/kind_of_spec.rb b/spec/ruby/core/kernel/kind_of_spec.rb
index 734035620c..c988edccb5 100644
--- a/spec/ruby/core/kernel/kind_of_spec.rb
+++ b/spec/ruby/core/kernel/kind_of_spec.rb
@@ -2,5 +2,5 @@ require_relative '../../spec_helper'
require_relative 'shared/kind_of'
describe "Kernel#kind_of?" do
- it_behaves_like :kernel_kind_of , :kind_of?
+ it_behaves_like :kernel_kind_of, :kind_of?
end
diff --git a/spec/ruby/core/kernel/match_spec.rb b/spec/ruby/core/kernel/match_spec.rb
index aa25006163..cd6330fe91 100644
--- a/spec/ruby/core/kernel/match_spec.rb
+++ b/spec/ruby/core/kernel/match_spec.rb
@@ -1,30 +1,7 @@
require_relative '../../spec_helper'
describe "Kernel#=~" do
- ruby_version_is ''...'3.2' 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 =~ true).should be_nil
- end
- end
-
- it "is deprecated" do
- -> do
- Object.new =~ /regexp/
- end.should complain(/deprecated Object#=~ is called on Object/, verbose: true)
- end
- end
-
- ruby_version_is '3.2' do
- it "is no longer defined" do
- Object.new.should_not.respond_to?(:=~)
- end
+ it "is no longer defined" do
+ Object.new.should_not.respond_to?(:=~)
end
end
diff --git a/spec/ruby/core/kernel/not_match_spec.rb b/spec/ruby/core/kernel/not_match_spec.rb
index f8dd82fad8..082e56fed7 100644
--- a/spec/ruby/core/kernel/not_match_spec.rb
+++ b/spec/ruby/core/kernel/not_match_spec.rb
@@ -14,18 +14,8 @@ describe "Kernel#!~" do
(obj !~ :foo).should == false
end
- ruby_version_is ""..."3.2" do
- it "returns true if self does not respond to #=~" do
- suppress_warning do
- (Object.new !~ :foo).should == true
- end
- end
- end
-
- ruby_version_is "3.2" do
- it "raises NoMethodError if self does not respond to #=~" do
- -> { Object.new !~ :foo }.should raise_error(NoMethodError)
- end
+ it "raises NoMethodError if self does not respond to #=~" do
+ -> { Object.new !~ :foo }.should raise_error(NoMethodError)
end
it 'can be overridden in subclasses' do
diff --git a/spec/ruby/core/kernel/open_spec.rb b/spec/ruby/core/kernel/open_spec.rb
index bb42c31f31..b967d5044b 100644
--- a/spec/ruby/core/kernel/open_spec.rb
+++ b/spec/ruby/core/kernel/open_spec.rb
@@ -27,64 +27,66 @@ describe "Kernel#open" do
open(@name, "r") { |f| f.gets }.should == @content
end
- platform_is_not :windows, :wasi do
- it "opens an io when path starts with a pipe" do
- suppress_warning do # https://bugs.ruby-lang.org/issues/19630
- @io = open("|date")
+ ruby_version_is ""..."4.0" do
+ platform_is_not :windows, :wasi do
+ it "opens an io when path starts with a pipe" do
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ @io = open("|date")
+ end
+ begin
+ @io.should be_kind_of(IO)
+ @io.read
+ ensure
+ @io.close
+ end
end
- begin
- @io.should be_kind_of(IO)
- @io.read
- ensure
- @io.close
- end
- end
- it "opens an io when called with a block" do
- suppress_warning do # https://bugs.ruby-lang.org/issues/19630
- @output = open("|date") { |f| f.read }
+ it "opens an io when called with a block" do
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ @output = open("|date") { |f| f.read }
+ end
+ @output.should_not == ''
end
- @output.should_not == ''
- end
- it "opens an io for writing" do
- suppress_warning do # https://bugs.ruby-lang.org/issues/19630
- -> {
- bytes = open("|cat", "w") { |io| io.write(".") }
- bytes.should == 1
- }.should output_to_fd(".")
+ it "opens an io for writing" do
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ -> {
+ bytes = open("|cat", "w") { |io| io.write(".") }
+ bytes.should == 1
+ }.should output_to_fd(".")
+ end
end
end
- end
- platform_is :windows do
- it "opens an io when path starts with a pipe" do
- suppress_warning do # https://bugs.ruby-lang.org/issues/19630
- @io = open("|date /t")
+ platform_is :windows do
+ it "opens an io when path starts with a pipe" do
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ @io = open("|date /t")
+ end
+ begin
+ @io.should be_kind_of(IO)
+ @io.read
+ ensure
+ @io.close
+ end
end
- begin
- @io.should be_kind_of(IO)
- @io.read
- ensure
- @io.close
- end
- end
- it "opens an io when called with a block" do
- suppress_warning do # https://bugs.ruby-lang.org/issues/19630
- @output = open("|date /t") { |f| f.read }
+ it "opens an io when called with a block" do
+ suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ @output = open("|date /t") { |f| f.read }
+ end
+ @output.should_not == ''
end
- @output.should_not == ''
end
- end
- ruby_version_is "3.3" do
- # https://bugs.ruby-lang.org/issues/19630
- it "warns about deprecation given a path with a pipe" do
- cmd = "|echo ok"
- -> {
- open(cmd) { |f| f.read }
- }.should complain(/Kernel#open with a leading '\|'/)
+ ruby_version_is "3.3" do
+ # https://bugs.ruby-lang.org/issues/19630
+ it "warns about deprecation given a path with a pipe" do
+ cmd = "|echo ok"
+ -> {
+ open(cmd) { |f| f.read }
+ }.should complain(/Kernel#open with a leading '\|'/)
+ end
end
end
@@ -106,7 +108,7 @@ describe "Kernel#open" do
ScratchPad.clear
end
- it "calls #to_path to covert the argument to a String before calling #to_str" do
+ it "calls #to_path to convert the argument to a String before calling #to_str" do
obj = mock("open to_path")
obj.should_receive(:to_path).at_least(1).times.and_return(@name)
obj.should_not_receive(:to_str)
diff --git a/spec/ruby/core/kernel/raise_spec.rb b/spec/ruby/core/kernel/raise_spec.rb
index 4f190c120b..fcd011d4e6 100644
--- a/spec/ruby/core/kernel/raise_spec.rb
+++ b/spec/ruby/core/kernel/raise_spec.rb
@@ -44,7 +44,242 @@ describe "Kernel#raise" do
it "raises an ArgumentError when only cause is given" do
cause = StandardError.new
- -> { raise(cause: cause) }.should raise_error(ArgumentError)
+ -> { raise(cause: cause) }.should raise_error(ArgumentError, "only cause is given with no arguments")
+ end
+
+ it "raises an ArgumentError when only cause is given even if it has nil value" do
+ -> { raise(cause: nil) }.should raise_error(ArgumentError, "only cause is given with no arguments")
+ end
+
+ it "raises a TypeError when given cause is not an instance of Exception" do
+ -> { raise "message", cause: Object.new }.should raise_error(TypeError, "exception object expected")
+ end
+
+ it "doesn't raise a TypeError when given cause is nil" do
+ -> { raise "message", cause: nil }.should raise_error(RuntimeError, "message")
+ end
+
+ it "allows cause equal an exception" do
+ e = RuntimeError.new("message")
+ -> { raise e, cause: e }.should raise_error(e)
+ end
+
+ it "doesn't set given cause when it equals an exception" do
+ e = RuntimeError.new("message")
+
+ begin
+ raise e, cause: e
+ rescue
+ end
+
+ e.cause.should == nil
+ end
+
+ it "raises ArgumentError when exception is part of the cause chain" do
+ -> {
+ begin
+ raise "Error 1"
+ rescue => e1
+ begin
+ raise "Error 2"
+ rescue => e2
+ begin
+ raise "Error 3"
+ rescue => e3
+ raise e1, cause: e3
+ end
+ end
+ end
+ }.should raise_error(ArgumentError, "circular causes")
+ end
+
+ it "re-raises a rescued exception" do
+ -> do
+ begin
+ raise StandardError, "aaa"
+ rescue Exception
+ begin
+ raise ArgumentError
+ rescue ArgumentError
+ end
+
+ # should raise StandardError "aaa"
+ raise
+ end
+ end.should raise_error(StandardError, "aaa")
+ end
+
+ it "re-raises a previously rescued exception without overwriting the cause" do
+ begin
+ begin
+ begin
+ begin
+ raise "Error 1"
+ rescue => e1
+ raise "Error 2"
+ end
+ rescue => e2
+ raise "Error 3"
+ end
+ rescue
+ e2.cause.should == e1
+ raise e2
+ end
+ rescue => e
+ e.cause.should == e1
+ end
+ end
+
+ it "re-raises a previously rescued exception with overwriting the cause when it's explicitly specified with :cause option" do
+ e4 = RuntimeError.new("Error 4")
+
+ begin
+ begin
+ begin
+ begin
+ raise "Error 1"
+ rescue => e1
+ raise "Error 2"
+ end
+ rescue => e2
+ raise "Error 3"
+ end
+ rescue
+ e2.cause.should == e1
+ raise e2, cause: e4
+ end
+ rescue => e
+ e.cause.should == e4
+ end
+ end
+
+ it "re-raises a previously rescued exception without overwriting the cause when it's explicitly specified with :cause option and has nil value" do
+ begin
+ begin
+ begin
+ begin
+ raise "Error 1"
+ rescue => e1
+ raise "Error 2"
+ end
+ rescue => e2
+ raise "Error 3"
+ end
+ rescue
+ e2.cause.should == e1
+ raise e2, cause: nil
+ end
+ rescue => e
+ e.cause.should == e1
+ end
+ end
+
+ it "re-raises a previously rescued exception without setting a cause implicitly" do
+ begin
+ begin
+ raise "Error 1"
+ rescue => e1
+ raise
+ end
+ rescue => e
+ e.should == e1
+ e.cause.should == nil
+ end
+ end
+
+ it "re-raises a previously rescued exception that has a cause without setting a cause implicitly" do
+ begin
+ begin
+ raise "Error 1"
+ rescue => e1
+ begin
+ raise "Error 2"
+ rescue => e2
+ raise
+ end
+ end
+ rescue => e
+ e.should == e2
+ e.cause.should == e1
+ end
+ end
+
+ it "re-raises a previously rescued exception that doesn't have a cause and isn't a cause of any other exception with setting a cause implicitly" do
+ begin
+ begin
+ raise "Error 1"
+ rescue => e1
+ begin
+ raise "Error 2"
+ rescue => e2
+ raise "Error 3"
+ end
+ end
+ rescue => e
+ e.message.should == "Error 3"
+ e.cause.should == e2
+ end
+ end
+
+ it "re-raises a previously rescued exception that doesn't have a cause and is a cause of other exception without setting a cause implicitly" do
+ begin
+ begin
+ raise "Error 1"
+ rescue => e1
+ begin
+ raise "Error 2"
+ rescue => e2
+ e1.cause.should == nil
+ e2.cause.should == e1
+ raise e1
+ end
+ end
+ rescue => e
+ e.should == e1
+ e.cause.should == nil
+ end
+ end
+
+ it "re-raises a previously rescued exception that doesn't have a cause and is a cause of other exception (that wasn't raised explicitly) without setting a cause implicitly" do
+ begin
+ begin
+ raise "Error 1"
+ rescue => e1
+ begin
+ foo # raises NameError
+ rescue => e2
+ e1.cause.should == nil
+ e2.cause.should == e1
+ raise e1
+ end
+ end
+ rescue => e
+ e.should == e1
+ e.cause.should == nil
+ end
+ end
+
+ it "re-raises a previously rescued exception that has a cause but isn't a cause of any other exception without setting a cause implicitly" do
+ begin
+ begin
+ raise "Error 1"
+ rescue => e1
+ begin
+ raise "Error 2"
+ rescue => e2
+ begin
+ raise "Error 3", cause: RuntimeError.new("Error 4")
+ rescue => e3
+ e2.cause.should == e1
+ e3.cause.should_not == e2
+ raise e2
+ end
+ end
+ end
+ rescue => e
+ e.should == e2
+ e.cause.should == e1
+ end
end
end
diff --git a/spec/ruby/core/kernel/require_spec.rb b/spec/ruby/core/kernel/require_spec.rb
index 4029e68725..60d17242fe 100644
--- a/spec/ruby/core/kernel/require_spec.rb
+++ b/spec/ruby/core/kernel/require_spec.rb
@@ -16,9 +16,10 @@ describe "Kernel#require" do
Kernel.should have_private_instance_method(:require)
end
- provided = %w[complex enumerator rational thread ruby2_keywords]
- ruby_version_is "3.1" do
- provided << "fiber"
+ provided = %w[complex enumerator fiber rational thread ruby2_keywords]
+ ruby_version_is "4.0" do
+ provided << "set"
+ provided << "pathname"
end
it "#{provided.join(', ')} are already required" do
@@ -31,9 +32,14 @@ describe "Kernel#require" do
features.sort.should == provided.sort
- code = provided.map { |f| "puts require #{f.inspect}\n" }.join
+ requires = provided
+ ruby_version_is "4.0" do
+ requires = requires.map { |f| f == "pathname" ? "pathname.so" : f }
+ end
+
+ code = requires.map { |f| "puts require #{f.inspect}\n" }.join
required = ruby_exe(code, options: '--disable-gems')
- required.should == "false\n" * provided.size
+ required.should == "false\n" * requires.size
end
it_behaves_like :kernel_require_basic, :require, CodeLoadingSpecs::Method.new
diff --git a/spec/ruby/core/kernel/select_spec.rb b/spec/ruby/core/kernel/select_spec.rb
index e0d82f3079..df23414b28 100644
--- a/spec/ruby/core/kernel/select_spec.rb
+++ b/spec/ruby/core/kernel/select_spec.rb
@@ -10,9 +10,9 @@ end
describe "Kernel.select" do
it 'does not block when timeout is 0' do
IO.pipe do |read, write|
- IO.select([read], [], [], 0).should == nil
+ select([read], [], [], 0).should == nil
write.write 'data'
- IO.select([read], [], [], 0).should == [[read], [], []]
+ select([read], [], [], 0).should == [[read], [], []]
end
end
end
diff --git a/spec/ruby/core/kernel/shared/load.rb b/spec/ruby/core/kernel/shared/load.rb
index 0fe2d5ce16..62c5c7be9b 100644
--- a/spec/ruby/core/kernel/shared/load.rb
+++ b/spec/ruby/core/kernel/shared/load.rb
@@ -165,37 +165,35 @@ describe :kernel_load, shared: true do
end
describe "when passed a module for 'wrap'" do
- ruby_version_is "3.1" do
- it "sets the enclosing scope to the supplied module" do
- path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
- mod = Module.new
- @object.load(path, mod)
+ it "sets the enclosing scope to the supplied module" do
+ path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
+ mod = Module.new
+ @object.load(path, mod)
- Object.const_defined?(:LoadSpecWrap).should be_false
- mod.const_defined?(:LoadSpecWrap).should be_true
+ Object.const_defined?(:LoadSpecWrap).should be_false
+ mod.const_defined?(:LoadSpecWrap).should be_true
- wrap_module = ScratchPad.recorded[1]
- wrap_module.should == mod
- end
+ wrap_module = ScratchPad.recorded[1]
+ wrap_module.should == mod
+ end
- it "makes constants and instance methods in the source file reachable with the supplied module" do
- path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
- mod = Module.new
- @object.load(path, mod)
+ it "makes constants and instance methods in the source file reachable with the supplied module" do
+ path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
+ mod = Module.new
+ @object.load(path, mod)
- mod::LOAD_WRAP_SPECS_TOP_LEVEL_CONSTANT.should == 1
- obj = Object.new
- obj.extend(mod)
- obj.send(:load_wrap_specs_top_level_method).should == :load_wrap_specs_top_level_method
- end
+ mod::LOAD_WRAP_SPECS_TOP_LEVEL_CONSTANT.should == 1
+ obj = Object.new
+ obj.extend(mod)
+ obj.send(:load_wrap_specs_top_level_method).should == :load_wrap_specs_top_level_method
+ end
- it "makes instance methods in the source file private" do
- path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
- mod = Module.new
- @object.load(path, mod)
+ it "makes instance methods in the source file private" do
+ path = File.expand_path "load_wrap_fixture.rb", CODE_LOADING_DIR
+ mod = Module.new
+ @object.load(path, mod)
- mod.private_instance_methods.include?(:load_wrap_specs_top_level_method).should == true
- end
+ mod.private_instance_methods.include?(:load_wrap_specs_top_level_method).should == true
end
end
diff --git a/spec/ruby/core/kernel/shared/require.rb b/spec/ruby/core/kernel/shared/require.rb
index 250813191b..52f86f73e5 100644
--- a/spec/ruby/core/kernel/shared/require.rb
+++ b/spec/ruby/core/kernel/shared/require.rb
@@ -223,7 +223,7 @@ describe :kernel_require, shared: true do
it "loads c-extension file when passed absolute path without extension when no .rb is present" do
# the error message is specific to what dlerror() returns
path = File.join CODE_LOADING_DIR, "a", "load_fixture"
- -> { @object.send(@method, path) }.should raise_error(Exception, /file too short|not a mach-o file/)
+ -> { @object.send(@method, path) }.should raise_error(LoadError)
end
end
@@ -231,7 +231,7 @@ describe :kernel_require, shared: true do
it "loads .bundle file when passed absolute path with .so" do
# the error message is specific to what dlerror() returns
path = File.join CODE_LOADING_DIR, "a", "load_fixture.so"
- -> { @object.send(@method, path) }.should raise_error(Exception, /load_fixture\.bundle.+(file too short|not a mach-o file)/)
+ -> { @object.send(@method, path) }.should raise_error(LoadError)
end
end
@@ -296,6 +296,16 @@ describe :kernel_require, shared: true do
$LOAD_PATH.replace [File.expand_path("b", CODE_LOADING_DIR), CODE_LOADING_DIR]
@object.require("load_fixture").should be_false
end
+
+ it "stores the missing path in a LoadError object" do
+ path = "abcd1234"
+
+ -> {
+ @object.send(@method, path)
+ }.should raise_error(LoadError) { |e|
+ e.path.should == path
+ }
+ end
end
describe "(file extensions)" do
@@ -815,4 +825,24 @@ describe :kernel_require, shared: true do
e.path.should == path
}
end
+
+ platform_is :linux, :darwin do
+ it "does not store the missing path in a LoadError object when c-extension file exists but loading fails and passed absolute path without extension" do
+ # the error message is specific to what dlerror() returns
+ path = File.join CODE_LOADING_DIR, "a", "load_fixture"
+ -> { @object.send(@method, path) }.should raise_error(LoadError) { |e|
+ e.path.should == nil
+ }
+ end
+ end
+
+ platform_is :darwin do
+ it "does not store the missing path in a LoadError object when c-extension file exists but loading fails and passed absolute path with extension" do
+ # the error message is specific to what dlerror() returns
+ path = File.join CODE_LOADING_DIR, "a", "load_fixture.bundle"
+ -> { @object.send(@method, path) }.should raise_error(LoadError) { |e|
+ e.path.should == nil
+ }
+ end
+ end
end
diff --git a/spec/ruby/core/kernel/shared/sprintf.rb b/spec/ruby/core/kernel/shared/sprintf.rb
index 13dc6e97f0..2b2c6c9b63 100644
--- a/spec/ruby/core/kernel/shared/sprintf.rb
+++ b/spec/ruby/core/kernel/shared/sprintf.rb
@@ -22,6 +22,7 @@ describe :kernel_sprintf, shared: true do
@method.call("%d", "112").should == "112"
@method.call("%d", "0127").should == "87"
@method.call("%d", "0xc4").should == "196"
+ @method.call("%d", "0").should == "0"
end
it "raises TypeError exception if cannot convert to Integer" do
@@ -57,6 +58,11 @@ describe :kernel_sprintf, shared: true do
it "works well with large numbers" do
@method.call("%#{f}", 1234567890987654321).should == "1234567890987654321"
end
+
+ it "converts to the empty string if precision is 0 and value is 0" do
+ @method.call("%.#{f}", 0).should == ""
+ @method.call("%.0#{f}", 0).should == ""
+ end
end
end
@@ -289,28 +295,12 @@ describe :kernel_sprintf, shared: true do
@method.call("%c", "a").should == "a"
end
- ruby_version_is ""..."3.2" do
- it "raises ArgumentError if argument is a string of several characters" do
- -> {
- @method.call("%c", "abc")
- }.should raise_error(ArgumentError, /%c requires a character/)
- end
-
- it "raises ArgumentError if argument is an empty string" do
- -> {
- @method.call("%c", "")
- }.should raise_error(ArgumentError, /%c requires a character/)
- end
+ it "displays only the first character if argument is a string of several characters" do
+ @method.call("%c", "abc").should == "a"
end
- ruby_version_is "3.2" do
- it "displays only the first character if argument is a string of several characters" do
- @method.call("%c", "abc").should == "a"
- end
-
- it "displays no characters if argument is an empty string" do
- @method.call("%c", "").should == ""
- end
+ it "displays no characters if argument is an empty string" do
+ @method.call("%c", "").should == ""
end
it "raises TypeError if argument is not String or Integer and cannot be converted to them" do
@@ -372,6 +362,10 @@ describe :kernel_sprintf, shared: true do
obj.should_receive(:inspect).and_return("<inspect-result>")
@method.call("%p", obj).should == "<inspect-result>"
end
+
+ it "substitutes 'nil' for nil" do
+ @method.call("%p", nil).should == "nil"
+ end
end
describe "s" do
@@ -455,7 +449,7 @@ describe :kernel_sprintf, shared: true do
it "is escaped by %" do
@method.call("%%").should == "%"
- @method.call("%%d", 10).should == "%d"
+ @method.call("%%d").should == "%d"
end
end
end
diff --git a/spec/ruby/core/kernel/singleton_method_spec.rb b/spec/ruby/core/kernel/singleton_method_spec.rb
index 0bdf125ad8..7d63fa7cc6 100644
--- a/spec/ruby/core/kernel/singleton_method_spec.rb
+++ b/spec/ruby/core/kernel/singleton_method_spec.rb
@@ -1,7 +1,7 @@
require_relative '../../spec_helper'
describe "Kernel#singleton_method" do
- it "find a method defined on the singleton class" do
+ it "finds a method defined on the singleton class" do
obj = Object.new
def obj.foo; end
obj.singleton_method(:foo).should be_an_instance_of(Method)
@@ -38,4 +38,48 @@ describe "Kernel#singleton_method" do
e.class.should == NameError
}
end
+
+ ruby_bug "#20620", ""..."3.4" do
+ it "finds a method defined in a module included in the singleton class" do
+ m = Module.new do
+ def foo
+ :foo
+ end
+ end
+
+ obj = Object.new
+ obj.singleton_class.include(m)
+
+ obj.singleton_method(:foo).should be_an_instance_of(Method)
+ obj.singleton_method(:foo).call.should == :foo
+ end
+
+ it "finds a method defined in a module prepended in the singleton class" do
+ m = Module.new do
+ def foo
+ :foo
+ end
+ end
+
+ obj = Object.new
+ obj.singleton_class.prepend(m)
+
+ obj.singleton_method(:foo).should be_an_instance_of(Method)
+ obj.singleton_method(:foo).call.should == :foo
+ end
+
+ it "finds a method defined in a module that an object is extended with" do
+ m = Module.new do
+ def foo
+ :foo
+ end
+ end
+
+ obj = Object.new
+ obj.extend(m)
+
+ obj.singleton_method(:foo).should be_an_instance_of(Method)
+ obj.singleton_method(:foo).call.should == :foo
+ end
+ end
end
diff --git a/spec/ruby/core/kernel/sleep_spec.rb b/spec/ruby/core/kernel/sleep_spec.rb
index 0570629723..e9c600aac4 100644
--- a/spec/ruby/core/kernel/sleep_spec.rb
+++ b/spec/ruby/core/kernel/sleep_spec.rb
@@ -1,4 +1,5 @@
require_relative '../../spec_helper'
+require_relative '../fiber/fixtures/scheduler'
describe "Kernel#sleep" do
it "is a private method" do
@@ -21,7 +22,7 @@ describe "Kernel#sleep" do
sleep(Rational(1, 999)).should >= 0
end
- it "accepts any Object that reponds to divmod" do
+ it "accepts any Object that responds to divmod" do
o = Object.new
def o.divmod(*); [0, 0.001]; end
sleep(o).should >= 0
@@ -51,6 +52,17 @@ describe "Kernel#sleep" do
t.value.should == 5
end
+ it "sleeps with nanosecond precision" do
+ start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ 100.times do
+ sleep(0.0001)
+ end
+ end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+
+ actual_duration = end_time - start_time
+ actual_duration.should > 0.01 # 100 * 0.0001 => 0.01
+ end
+
ruby_version_is ""..."3.3" do
it "raises a TypeError when passed nil" do
-> { sleep(nil) }.should raise_error(TypeError)
@@ -73,6 +85,40 @@ describe "Kernel#sleep" do
t.value.should == 5
end
end
+
+ context "Kernel.sleep with Fiber scheduler" do
+ before :each do
+ Fiber.set_scheduler(FiberSpecs::LoggingScheduler.new)
+ end
+
+ after :each do
+ Fiber.set_scheduler(nil)
+ end
+
+ it "calls the scheduler without arguments when no duration is given" do
+ sleeper = Fiber.new(blocking: false) do
+ sleep
+ end
+ sleeper.resume
+ Fiber.scheduler.events.should == [{ event: :kernel_sleep, fiber: sleeper, args: [] }]
+ end
+
+ it "calls the scheduler with the given duration" do
+ sleeper = Fiber.new(blocking: false) do
+ sleep(0.01)
+ end
+ sleeper.resume
+ Fiber.scheduler.events.should == [{ event: :kernel_sleep, fiber: sleeper, args: [0.01] }]
+ end
+
+ it "does not call the scheduler if the fiber is blocking" do
+ sleeper = Fiber.new(blocking: true) do
+ sleep(0.01)
+ end
+ sleeper.resume
+ Fiber.scheduler.events.should == []
+ end
+ end
end
describe "Kernel.sleep" do
diff --git a/spec/ruby/core/kernel/sprintf_spec.rb b/spec/ruby/core/kernel/sprintf_spec.rb
index 9ef7f86f16..5a4a90ff7a 100644
--- a/spec/ruby/core/kernel/sprintf_spec.rb
+++ b/spec/ruby/core/kernel/sprintf_spec.rb
@@ -13,28 +13,52 @@ end
describe "Kernel#sprintf" do
it_behaves_like :kernel_sprintf, -> format, *args {
- sprintf(format, *args)
+ r = nil
+ -> {
+ r = sprintf(format, *args)
+ }.should_not complain(verbose: true)
+ r
}
it_behaves_like :kernel_sprintf_encoding, -> format, *args {
- sprintf(format, *args)
+ r = nil
+ -> {
+ r = sprintf(format, *args)
+ }.should_not complain(verbose: true)
+ r
}
it_behaves_like :kernel_sprintf_to_str, -> format, *args {
- sprintf(format, *args)
+ r = nil
+ -> {
+ r = sprintf(format, *args)
+ }.should_not complain(verbose: true)
+ r
}
end
describe "Kernel.sprintf" do
it_behaves_like :kernel_sprintf, -> format, *args {
- Kernel.sprintf(format, *args)
+ r = nil
+ -> {
+ r = Kernel.sprintf(format, *args)
+ }.should_not complain(verbose: true)
+ r
}
it_behaves_like :kernel_sprintf_encoding, -> format, *args {
- Kernel.sprintf(format, *args)
+ r = nil
+ -> {
+ r = Kernel.sprintf(format, *args)
+ }.should_not complain(verbose: true)
+ r
}
it_behaves_like :kernel_sprintf_to_str, -> format, *args {
- Kernel.sprintf(format, *args)
+ r = nil
+ -> {
+ r = Kernel.sprintf(format, *args)
+ }.should_not complain(verbose: true)
+ r
}
end
diff --git a/spec/ruby/core/kernel/taint_spec.rb b/spec/ruby/core/kernel/taint_spec.rb
index 0c16b1dbbf..9a2efbaea0 100644
--- a/spec/ruby/core/kernel/taint_spec.rb
+++ b/spec/ruby/core/kernel/taint_spec.rb
@@ -2,26 +2,7 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Kernel#taint" do
- ruby_version_is ""..."3.2" do
- it "is a no-op" do
- suppress_warning do
- o = Object.new
- o.taint
- o.should_not.tainted?
- end
- 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
-
- ruby_version_is "3.2" do
- it "has been removed" do
- Object.new.should_not.respond_to?(:taint)
- end
+ it "has been removed" do
+ Object.new.should_not.respond_to?(:taint)
end
end
diff --git a/spec/ruby/core/kernel/tainted_spec.rb b/spec/ruby/core/kernel/tainted_spec.rb
index fcae433069..837eb1dafb 100644
--- a/spec/ruby/core/kernel/tainted_spec.rb
+++ b/spec/ruby/core/kernel/tainted_spec.rb
@@ -2,28 +2,7 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Kernel#tainted?" do
- ruby_version_is ""..."3.2" do
- it "is a no-op" do
- suppress_warning do
- o = mock('o')
- p = mock('p')
- p.taint
- o.should_not.tainted?
- p.should_not.tainted?
- end
- 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
-
- ruby_version_is "3.2" do
- it "has been removed" do
- Object.new.should_not.respond_to?(:tainted?)
- end
+ it "has been removed" do
+ Object.new.should_not.respond_to?(:tainted?)
end
end
diff --git a/spec/ruby/core/kernel/trust_spec.rb b/spec/ruby/core/kernel/trust_spec.rb
index db6f17e0fb..ef3fa9a3e1 100644
--- a/spec/ruby/core/kernel/trust_spec.rb
+++ b/spec/ruby/core/kernel/trust_spec.rb
@@ -2,27 +2,7 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Kernel#trust" do
- ruby_version_is ""..."3.2" do
- it "is a no-op" do
- suppress_warning do
- o = Object.new.untrust
- o.should_not.untrusted?
- o.trust
- o.should_not.untrusted?
- end
- 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
-
- ruby_version_is "3.2" do
- it "has been removed" do
- Object.new.should_not.respond_to?(:trust)
- end
+ it "has been removed" do
+ Object.new.should_not.respond_to?(:trust)
end
end
diff --git a/spec/ruby/core/kernel/untaint_spec.rb b/spec/ruby/core/kernel/untaint_spec.rb
index 26b2aabbe9..47e8544bd4 100644
--- a/spec/ruby/core/kernel/untaint_spec.rb
+++ b/spec/ruby/core/kernel/untaint_spec.rb
@@ -2,27 +2,7 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Kernel#untaint" do
- ruby_version_is ""..."3.2" do
- it "is a no-op" do
- suppress_warning do
- o = Object.new.taint
- o.should_not.tainted?
- o.untaint
- o.should_not.tainted?
- end
- 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
-
- ruby_version_is "3.2" do
- it "has been removed" do
- Object.new.should_not.respond_to?(:untaint)
- end
+ it "has been removed" do
+ Object.new.should_not.respond_to?(:untaint)
end
end
diff --git a/spec/ruby/core/kernel/untrust_spec.rb b/spec/ruby/core/kernel/untrust_spec.rb
index 5310cd8eb4..8787ab3fc9 100644
--- a/spec/ruby/core/kernel/untrust_spec.rb
+++ b/spec/ruby/core/kernel/untrust_spec.rb
@@ -2,26 +2,7 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Kernel#untrust" do
- ruby_version_is ""..."3.2" do
- it "is a no-op" do
- suppress_warning do
- o = Object.new
- o.untrust
- o.should_not.untrusted?
- end
- 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
-
- ruby_version_is "3.2" do
- it "has been removed" do
- Object.new.should_not.respond_to?(:untrust)
- end
+ it "has been removed" do
+ Object.new.should_not.respond_to?(:untrust)
end
end
diff --git a/spec/ruby/core/kernel/untrusted_spec.rb b/spec/ruby/core/kernel/untrusted_spec.rb
index ea36d6c98c..29261be9c4 100644
--- a/spec/ruby/core/kernel/untrusted_spec.rb
+++ b/spec/ruby/core/kernel/untrusted_spec.rb
@@ -2,27 +2,7 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Kernel#untrusted?" do
- ruby_version_is ""..."3.2" do
- it "is a no-op" do
- suppress_warning do
- o = mock('o')
- o.should_not.untrusted?
- o.untrust
- o.should_not.untrusted?
- end
- 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
-
- ruby_version_is "3.2" do
- it "has been removed" do
- Object.new.should_not.respond_to?(:untrusted?)
- end
+ it "has been removed" do
+ Object.new.should_not.respond_to?(:untrusted?)
end
end
diff --git a/spec/ruby/core/kernel/warn_spec.rb b/spec/ruby/core/kernel/warn_spec.rb
index 00164ad90b..e03498c6dc 100644
--- a/spec/ruby/core/kernel/warn_spec.rb
+++ b/spec/ruby/core/kernel/warn_spec.rb
@@ -112,6 +112,12 @@ describe "Kernel#warn" do
ruby_exe(file, options: "-rrubygems", args: "2>&1").should == "#{file}:2: warning: warn-require-warning\n"
end
+ it "doesn't show the caller when the uplevel is `nil`" do
+ w = KernelSpecs::WarnInNestedCall.new
+
+ -> { w.f4("foo", nil) }.should output(nil, "foo\n")
+ end
+
guard -> { Kernel.instance_method(:tap).source_location } do
it "skips <internal: core library methods defined in Ruby" do
file, line = Kernel.instance_method(:tap).source_location
diff --git a/spec/ruby/core/main/private_spec.rb b/spec/ruby/core/main/private_spec.rb
index e8c1f3f44c..76895fd649 100644
--- a/spec/ruby/core/main/private_spec.rb
+++ b/spec/ruby/core/main/private_spec.rb
@@ -30,16 +30,8 @@ describe "main#private" do
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
+ it "returns argument" do
+ eval("private :main_public_method", TOPLEVEL_BINDING).should equal(:main_public_method)
end
it "raises a NameError when at least one of given method names is undefined" do
diff --git a/spec/ruby/core/main/public_spec.rb b/spec/ruby/core/main/public_spec.rb
index 31baad4583..3c77798fbc 100644
--- a/spec/ruby/core/main/public_spec.rb
+++ b/spec/ruby/core/main/public_spec.rb
@@ -30,16 +30,8 @@ describe "main#public" do
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
+ it "returns argument" do
+ eval("public :main_private_method", TOPLEVEL_BINDING).should equal(:main_private_method)
end
diff --git a/spec/ruby/core/main/using_spec.rb b/spec/ruby/core/main/using_spec.rb
index 8a23970c4b..5b9a751595 100644
--- a/spec/ruby/core/main/using_spec.rb
+++ b/spec/ruby/core/main/using_spec.rb
@@ -142,11 +142,9 @@ describe "main.using" do
end.should raise_error(RuntimeError)
end
- ruby_version_is "3.2" do
- it "does not raise error when wrapped with module" do
- -> do
- load File.expand_path('../fixtures/using.rb', __FILE__), true
- end.should_not raise_error
- end
+ it "does not raise error when wrapped with module" do
+ -> do
+ load File.expand_path('../fixtures/using.rb', __FILE__), true
+ end.should_not raise_error
end
end
diff --git a/spec/ruby/core/marshal/dump_spec.rb b/spec/ruby/core/marshal/dump_spec.rb
index 0f77279a4f..ff9b9214fa 100644
--- a/spec/ruby/core/marshal/dump_spec.rb
+++ b/spec/ruby/core/marshal/dump_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'fixtures/marshal_data'
@@ -38,7 +38,7 @@ describe "Marshal.dump" do
].should be_computed_by(:dump)
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
it "dumps a positive Fixnum > 31 bits as a Bignum" do
Marshal.dump(2**31 + 1).should == "\x04\bl+\a\x01\x00\x00\x80"
end
@@ -47,6 +47,11 @@ describe "Marshal.dump" do
Marshal.dump(-2**31 - 1).should == "\x04\bl-\a\x01\x00\x00\x80"
end
end
+
+ it "does not use object links for objects repeatedly dumped" do
+ Marshal.dump([0, 0]).should == "\x04\b[\ai\x00i\x00"
+ Marshal.dump([2**16, 2**16]).should == "\x04\b[\ai\x03\x00\x00\x01i\x03\x00\x00\x01"
+ end
end
describe "with a Symbol" do
@@ -93,6 +98,11 @@ describe "Marshal.dump" do
value = [*value, value[0]]
Marshal.dump(value).should == "\x04\b[\b#{symbol1}#{symbol2};\x00"
end
+
+ it "uses symbol links for objects repeatedly dumped" do
+ symbol = :foo
+ Marshal.dump([symbol, symbol]).should == "\x04\b[\a:\bfoo;\x00" # ;\x00 is a link to the symbol object
+ end
end
describe "with an object responding to #marshal_dump" do
@@ -108,6 +118,20 @@ describe "Marshal.dump" do
it "raises TypeError if an Object is an instance of an anonymous class" do
-> { Marshal.dump(Class.new(UserMarshal).new) }.should raise_error(TypeError, /can't dump anonymous class/)
end
+
+ it "uses object links for objects repeatedly dumped" do
+ obj = UserMarshal.new
+ Marshal.dump([obj, obj]).should == "\x04\b[\aU:\x10UserMarshal:\tdata@\x06" # @\x06 is a link to the object
+ end
+
+ it "adds instance variables of a dumped object after the object itself into the objects table" do
+ value = "<foo>"
+ obj = MarshalSpec::UserMarshalDumpWithIvar.new("string", value)
+
+ # expect a link to the object (@\x06, that means Integer 1) is smaller than a link
+ # to the instance variable value (@\t, that means Integer 4)
+ Marshal.dump([obj, obj, value]).should == "\x04\b[\bU:)MarshalSpec::UserMarshalDumpWithIvarI[\x06\"\vstring\x06:\t@foo\"\n<foo>@\x06@\t"
+ end
end
describe "with an object responding to #_dump" do
@@ -166,6 +190,20 @@ describe "Marshal.dump" do
Marshal.dump([a, a]).should == "\x04\b[\aIu:\x17MarshalSpec::M1::A\v<dump>\x06:\t@foo\"\bbar#{reference}"
end
+ it "uses object links for objects repeatedly dumped" do
+ obj = UserDefined.new
+ Marshal.dump([obj, obj]).should == "\x04\b[\au:\x10UserDefined\x12\x04\b[\a:\nstuff;\x00@\x06" # @\x06 is a link to the object
+ end
+
+ it "adds instance variables of a dumped String before the object itself into the objects table" do
+ value = "<foo>"
+ obj = MarshalSpec::UserDefinedDumpWithIVars.new(+"string", value)
+
+ # expect a link to the object (@\a, that means Integer 2) is greater than a link
+ # to the instance variable value (@\x06, that means Integer 1)
+ Marshal.dump([obj, obj, value]).should == "\x04\b[\bIu:*MarshalSpec::UserDefinedDumpWithIVars\vstring\x06:\t@foo\"\n<foo>@\a@\x06"
+ end
+
describe "Core library classes with #_dump returning a String with instance variables" do
it "indexes instance variables and then a Time object itself" do
t = Time.utc(2022)
@@ -193,9 +231,16 @@ describe "Marshal.dump" do
Marshal.dump(MarshalSpec::ClassWithOverriddenName).should == "\x04\bc)MarshalSpec::ClassWithOverriddenName"
end
- it "dumps a class with multibyte characters in name" do
- source_object = eval("MarshalSpec::MultibyteぁあぃいClass".dup.force_encoding(Encoding::UTF_8))
- Marshal.dump(source_object).should == "\x04\bc,MarshalSpec::Multibyte\xE3\x81\x81\xE3\x81\x82\xE3\x81\x83\xE3\x81\x84Class"
+ ruby_version_is "4.0" do
+ it "dumps a class with multibyte characters in name" do
+ source_object = eval("MarshalSpec::MultibyteぁあぃいClass".dup.force_encoding(Encoding::UTF_8))
+ Marshal.dump(source_object).should == "\x04\bIc,MarshalSpec::Multibyte\xE3\x81\x81\xE3\x81\x82\xE3\x81\x83\xE3\x81\x84Class\x06:\x06ET"
+ Marshal.load(Marshal.dump(source_object)) == source_object
+ end
+ end
+
+ it "uses object links for objects repeatedly dumped" do
+ Marshal.dump([String, String]).should == "\x04\b[\ac\vString@\x06" # @\x06 is a link to the object
end
it "raises TypeError with an anonymous Class" do
@@ -216,9 +261,16 @@ describe "Marshal.dump" do
Marshal.dump(MarshalSpec::ModuleWithOverriddenName).should == "\x04\bc*MarshalSpec::ModuleWithOverriddenName"
end
- it "dumps a module with multibyte characters in name" do
- source_object = eval("MarshalSpec::MultibyteけげこごModule".dup.force_encoding(Encoding::UTF_8))
- Marshal.dump(source_object).should == "\x04\bm-MarshalSpec::Multibyte\xE3\x81\x91\xE3\x81\x92\xE3\x81\x93\xE3\x81\x94Module"
+ ruby_version_is "4.0" do
+ it "dumps a module with multibyte characters in name" do
+ source_object = eval("MarshalSpec::MultibyteけげこごModule".dup.force_encoding(Encoding::UTF_8))
+ Marshal.dump(source_object).should == "\x04\bIm-MarshalSpec::Multibyte\xE3\x81\x91\xE3\x81\x92\xE3\x81\x93\xE3\x81\x94Module\x06:\x06ET"
+ Marshal.load(Marshal.dump(source_object)) == source_object
+ end
+ end
+
+ it "uses object links for objects repeatedly dumped" do
+ Marshal.dump([Marshal, Marshal]).should == "\x04\b[\am\fMarshal@\x06" # @\x06 is a link to the object
end
it "raises TypeError with an anonymous Module" do
@@ -239,6 +291,23 @@ describe "Marshal.dump" do
[Marshal, nan_value, "\004\bf\bnan"],
].should be_computed_by(:dump)
end
+
+ it "may or may not use object links for objects repeatedly dumped" do
+ # it's an MRI implementation detail - on x86 architecture object links
+ # aren't used for Float values but on amd64 - object links are used
+
+ dump = Marshal.dump([0.0, 0.0])
+ ["\x04\b[\af\x060@\x06", "\x04\b[\af\x060f\x060"].should.include?(dump)
+
+ # if object links aren't used - entries in the objects table are still
+ # occupied by Float values
+ if dump == "\x04\b[\af\x060f\x060"
+ s = "string"
+ # an index of "string" ("@\b") in the object table equals 3 (`"\b".ord - 5`),
+ # so `0.0, 0,0` elements occupied indices 1 and 2
+ Marshal.dump([0.0, 0.0, s, s]).should == "\x04\b[\tf\x060f\x060\"\vstring@\b"
+ end
+ end
end
describe "with a Bignum" do
@@ -256,6 +325,11 @@ describe "Marshal.dump" do
].should be_computed_by(:dump)
end
+ it "uses object links for objects repeatedly dumped" do
+ n = 2**64
+ Marshal.dump([n, n]).should == "\x04\b[\al+\n\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00@\x06" # @\x06 is a link to the object
+ end
+
it "increases the object links counter" do
obj = Object.new
object_1_link = "\x06" # representing of (0-based) index=1 (by adding 5 for small Integers)
@@ -275,12 +349,47 @@ describe "Marshal.dump" do
it "dumps a Rational" do
Marshal.dump(Rational(2, 3)).should == "\x04\bU:\rRational[\ai\ai\b"
end
+
+ it "uses object links for objects repeatedly dumped" do
+ r = Rational(2, 3)
+ Marshal.dump([r, r]).should == "\x04\b[\aU:\rRational[\ai\ai\b@\x06" # @\x06 is a link to the object
+ end
end
describe "with a Complex" do
it "dumps a Complex" do
Marshal.dump(Complex(2, 3)).should == "\x04\bU:\fComplex[\ai\ai\b"
end
+
+ it "uses object links for objects repeatedly dumped" do
+ c = Complex(2, 3)
+ Marshal.dump([c, c]).should == "\x04\b[\aU:\fComplex[\ai\ai\b@\x06" # @\x06 is a link to the object
+ end
+ end
+
+ describe "with a Data" do
+ it "dumps a Data" do
+ Marshal.dump(MarshalSpec::DataSpec::Measure.new(100, 'km')).should == "\x04\bS:#MarshalSpec::DataSpec::Measure\a:\vamountii:\tunit\"\akm"
+ end
+
+ it "dumps an extended Data" do
+ obj = MarshalSpec::DataSpec::MeasureExtended.new(100, "km")
+ Marshal.dump(obj).should == "\x04\bS:+MarshalSpec::DataSpec::MeasureExtended\a:\vamountii:\tunit\"\akm"
+ end
+
+ it "ignores overridden name method" do
+ obj = MarshalSpec::DataSpec::MeasureWithOverriddenName.new(100, "km")
+ Marshal.dump(obj).should == "\x04\bS:5MarshalSpec::DataSpec::MeasureWithOverriddenName\a:\vamountii:\tunit\"\akm"
+ end
+
+ it "uses object links for objects repeatedly dumped" do
+ d = MarshalSpec::DataSpec::Measure.new(100, 'km')
+ Marshal.dump([d, d]).should == "\x04\b[\aS:#MarshalSpec::DataSpec::Measure\a:\vamountii:\tunit\"\akm@\x06" # @\x06 is a link to the object
+ end
+
+ it "raises TypeError with an anonymous Struct" do
+ -> { Marshal.dump(Data.define(:a).new(1)) }.should raise_error(TypeError, /can't dump anonymous class/)
+ end
end
describe "with a String" do
@@ -338,6 +447,21 @@ describe "Marshal.dump" do
it "dumps multiple strings using symlinks for the :E (encoding) symbol" do
Marshal.dump(["".encode("us-ascii"), "".encode("utf-8")]).should == "\x04\b[\aI\"\x00\x06:\x06EFI\"\x00\x06;\x00T"
end
+
+ it "uses object links for objects repeatedly dumped" do
+ s = "string"
+ Marshal.dump([s, s]).should == "\x04\b[\a\"\vstring@\x06" # @\x06 is a link to the object
+ end
+
+ it "adds instance variables after the object itself into the objects table" do
+ obj = +"string"
+ value = "<foo>"
+ obj.instance_variable_set :@foo, value
+
+ # expect a link to the object (@\x06, that means Integer 1) is smaller than a link
+ # to the instance variable value (@\a, that means Integer 2)
+ Marshal.dump([obj, obj, value]).should == "\x04\b[\bI\"\vstring\x06:\t@foo\"\n<foo>@\x06@\a"
+ end
end
describe "with a Regexp" do
@@ -405,6 +529,11 @@ describe "Marshal.dump" do
obj = MarshalSpec::RegexpWithOverriddenName.new("")
Marshal.dump(obj).should == "\x04\bIC:*MarshalSpec::RegexpWithOverriddenName/\x00\x00\x06:\x06EF"
end
+
+ it "uses object links for objects repeatedly dumped" do
+ r = /\A.\Z/
+ Marshal.dump([r, r]).should == "\x04\b[\aI/\n\\A.\\Z\x00\x06:\x06EF@\x06" # @\x06 is a link to the object
+ end
end
describe "with an Array" do
@@ -440,6 +569,21 @@ describe "Marshal.dump" do
obj = MarshalSpec::ArrayWithOverriddenName.new
Marshal.dump(obj).should == "\x04\bC:)MarshalSpec::ArrayWithOverriddenName[\x00"
end
+
+ it "uses object links for objects repeatedly dumped" do
+ a = [1]
+ Marshal.dump([a, a]).should == "\x04\b[\a[\x06i\x06@\x06" # @\x06 is a link to the object
+ end
+
+ it "adds instance variables after the object itself into the objects table" do
+ obj = []
+ value = "<foo>"
+ obj.instance_variable_set :@foo, value
+
+ # expect a link to the object (@\x06, that means Integer 1) is smaller than a link
+ # to the instance variable value (@\a, that means Integer 2)
+ Marshal.dump([obj, obj, value]).should == "\x04\b[\bI[\x00\x06:\t@foo\"\n<foo>@\x06@\a"
+ end
end
describe "with a Hash" do
@@ -459,20 +603,18 @@ describe "Marshal.dump" do
Marshal.dump(Hash.new(1)).should == "\004\b}\000i\006"
end
- ruby_version_is "3.1" do
- it "dumps a Hash with compare_by_identity" do
- h = {}
- h.compare_by_identity
+ it "dumps a Hash with compare_by_identity" do
+ h = {}
+ h.compare_by_identity
- Marshal.dump(h).should == "\004\bC:\tHash{\x00"
- end
+ Marshal.dump(h).should == "\004\bC:\tHash{\x00"
+ end
- it "dumps a Hash subclass with compare_by_identity" do
- h = UserHash.new
- h.compare_by_identity
+ it "dumps a Hash subclass with compare_by_identity" do
+ h = UserHash.new
+ h.compare_by_identity
- Marshal.dump(h).should == "\x04\bC:\rUserHashC:\tHash{\x00"
- end
+ Marshal.dump(h).should == "\x04\bC:\rUserHashC:\tHash{\x00"
end
it "raises a TypeError with hash having default proc" do
@@ -497,6 +639,21 @@ describe "Marshal.dump" do
obj = MarshalSpec::HashWithOverriddenName.new
Marshal.dump(obj).should == "\x04\bC:(MarshalSpec::HashWithOverriddenName{\x00"
end
+
+ it "uses object links for objects repeatedly dumped" do
+ h = {a: 1}
+ Marshal.dump([h, h]).should == "\x04\b[\a{\x06:\x06ai\x06@\x06" # @\x06 is a link to the object
+ end
+
+ it "adds instance variables after the object itself into the objects table" do
+ obj = {}
+ value = "<foo>"
+ obj.instance_variable_set :@foo, value
+
+ # expect a link to the object (@\x06, that means Integer 1) is smaller than a link
+ # to the instance variable value (@\a, that means Integer 2)
+ Marshal.dump([obj, obj, value]).should == "\x04\b[\bI{\x00\x06:\t@foo\"\n<foo>@\x06@\a"
+ end
end
describe "with a Struct" do
@@ -531,9 +688,24 @@ describe "Marshal.dump" do
Marshal.dump(obj).should == "\x04\bS:*MarshalSpec::StructWithOverriddenName\x06:\x06a\"\vmember"
end
+ it "uses object links for objects repeatedly dumped" do
+ s = Struct::Pyramid.new
+ Marshal.dump([s, s]).should == "\x04\b[\aS:\x14Struct::Pyramid\x00@\x06" # @\x06 is a link to the object
+ end
+
it "raises TypeError with an anonymous Struct" do
-> { Marshal.dump(Struct.new(:a).new(1)) }.should raise_error(TypeError, /can't dump anonymous class/)
end
+
+ it "adds instance variables after the object itself into the objects table" do
+ obj = Struct::Pyramid.new
+ value = "<foo>"
+ obj.instance_variable_set :@foo, value
+
+ # expect a link to the object (@\x06, that means Integer 1) is smaller than a link
+ # to the instance variable value (@\a, that means Integer 2)
+ Marshal.dump([obj, obj, value]).should == "\x04\b[\bIS:\x14Struct::Pyramid\x00\x06:\t@foo\"\n<foo>@\x06@\a"
+ end
end
describe "with an Object" do
@@ -623,21 +795,45 @@ describe "Marshal.dump" do
ObjectSpace.define_finalizer(obj, finalizer.method(:noop))
Marshal.load(Marshal.dump(obj)).class.should == Object
end
+
+ it "uses object links for objects repeatedly dumped" do
+ obj = Object.new
+ Marshal.dump([obj, obj]).should == "\x04\b[\ao:\vObject\x00@\x06" # @\x06 is a link to the object
+ end
+
+ it "adds instance variables after the object itself into the objects table" do
+ obj = Object.new
+ value = "<foo>"
+ obj.instance_variable_set :@foo, value
+
+ # expect a link to the object (@\x06, that means Integer 1) is smaller than a link
+ # to the instance variable value (@\a, that means Integer 2)
+ Marshal.dump([obj, obj, value]).should == "\x04\b[\bo:\vObject\x06:\t@foo\"\n<foo>@\x06@\a"
+ end
end
describe "with a Range" do
- it "dumps a Range inclusive of end (with indeterminant order)" do
+ it "dumps a Range inclusive of end" do
dump = Marshal.dump(1..2)
+ dump.should == "\x04\bo:\nRange\b:\texclF:\nbegini\x06:\bendi\a"
+
load = Marshal.load(dump)
load.should == (1..2)
end
- it "dumps a Range exclusive of end (with indeterminant order)" do
+ it "dumps a Range exclusive of end" do
dump = Marshal.dump(1...2)
+ dump.should == "\x04\bo:\nRange\b:\texclT:\nbegini\x06:\bendi\a"
+
load = Marshal.load(dump)
load.should == (1...2)
end
+ it "uses object links for objects repeatedly dumped" do
+ r = 1..2
+ Marshal.dump([r, r]).should == "\x04\b[\ao:\nRange\b:\texclF:\nbegini\x06:\bendi\a@\x06" # @\x06 is a link to the object
+ end
+
it "raises TypeError with an anonymous Range subclass" do
-> { Marshal.dump(Class.new(Range).new(1, 2)) }.should raise_error(TypeError, /can't dump anonymous class/)
end
@@ -684,9 +880,32 @@ describe "Marshal.dump" do
Marshal.dump(obj).should include("MarshalSpec::TimeWithOverriddenName")
end
- it "dumps a Time subclass with multibyte characters in name" do
- source_object = eval("MarshalSpec::MultibyteぁあぃいTime".dup.force_encoding(Encoding::UTF_8))
- Marshal.dump(source_object).should == "\x04\bc+MarshalSpec::Multibyte\xE3\x81\x81\xE3\x81\x82\xE3\x81\x83\xE3\x81\x84Time"
+ ruby_version_is "4.0" do
+ it "dumps a Time subclass with multibyte characters in name" do
+ source_object = eval("MarshalSpec::MultibyteぁあぃいTime".dup.force_encoding(Encoding::UTF_8))
+ Marshal.dump(source_object).should == "\x04\bIc+MarshalSpec::Multibyte\xE3\x81\x81\xE3\x81\x82\xE3\x81\x83\xE3\x81\x84Time\x06:\x06ET"
+ Marshal.load(Marshal.dump(source_object)) == source_object
+ end
+ end
+
+ it "uses object links for objects repeatedly dumped" do
+ # order of the offset and zone instance variables is a subject to change
+ # and may be different on different CRuby versions
+ base = Regexp.quote("\x04\b[\aIu:\tTime\r\xF5\xEF\e\x80\x00\x00\x00\x00\a")
+ offset = Regexp.quote(":\voffseti\x020*:\tzoneI\"\bAST\x06:\x06EF")
+ zone = Regexp.quote(":\tzoneI\"\bAST\x06:\x06EF:\voffseti\x020*")
+ instance_variables = /#{offset}|#{zone}/
+ Marshal.dump([@t, @t]).should =~ /\A#{base}#{instance_variables}@\a\Z/ # @\a is a link to the object
+ end
+
+ it "adds instance variables before the object itself into the objects table" do
+ obj = @utc
+ value = "<foo>"
+ obj.instance_variable_set :@foo, value
+
+ # expect a link to the object (@\b, that means Integer 3) is greater than a link
+ # to the instance variable value (@\x06, that means Integer 1)
+ Marshal.dump([obj, obj, value]).should == "\x04\b[\bIu:\tTime\r \x00\x1C\xC0\x00\x00\x00\x00\a:\t@foo\"\n<foo>:\tzoneI\"\bUTC\x06:\x06EF@\b@\x06"
end
it "raises TypeError with an anonymous Time subclass" do
@@ -743,6 +962,21 @@ describe "Marshal.dump" do
Marshal.dump(e).should =~ /undefined method [`']foo' for ("":String|an instance of String)/
end
+ it "uses object links for objects repeatedly dumped" do
+ e = Exception.new
+ Marshal.dump([e, e]).should == "\x04\b[\ao:\x0EException\a:\tmesg0:\abt0@\x06" # @\x\a is a link to the object
+ end
+
+ it "adds instance variables after the object itself into the objects table" do
+ obj = Exception.new
+ value = "<foo>"
+ obj.instance_variable_set :@foo, value
+
+ # expect a link to the object (@\x06, that means Integer 1) is smaller than a link
+ # to the instance variable value (@\a, that means Integer 2)
+ Marshal.dump([obj, obj, value]).should == "\x04\b[\bo:\x0EException\b:\tmesg0:\abt0:\t@foo\"\n<foo>@\x06@\a"
+ end
+
it "raises TypeError if an Object is an instance of an anonymous class" do
anonymous_class = Class.new(Exception)
obj = anonymous_class.new
diff --git a/spec/ruby/core/marshal/fixtures/marshal_data.rb b/spec/ruby/core/marshal/fixtures/marshal_data.rb
index a508b6bea1..c16d9e4bb6 100644
--- a/spec/ruby/core/marshal/fixtures/marshal_data.rb
+++ b/spec/ruby/core/marshal/fixtures/marshal_data.rb
@@ -1,4 +1,7 @@
-# -*- encoding: binary -*-
+# encoding: binary
+
+require_relative 'marshal_multibyte_data'
+
class UserDefined
class Nested
def ==(other)
@@ -94,6 +97,25 @@ class UserDefinedString
end
end
+module MarshalSpec
+ class UserDefinedDumpWithIVars
+ attr_reader :string
+
+ def initialize(string, ivar_value)
+ @string = string
+ @string.instance_variable_set(:@foo, ivar_value)
+ end
+
+ def _dump(depth)
+ @string
+ end
+
+ def self._load(data)
+ new(data)
+ end
+ end
+end
+
class UserPreviouslyDefinedWithInitializedIvar
attr_accessor :field1, :field2
end
@@ -136,6 +158,32 @@ class UserMarshalWithIvar
end
end
+module MarshalSpec
+ class UserMarshalDumpWithIvar
+ attr_reader :data
+
+ def initialize(data, ivar_value)
+ @data = data
+ @ivar_value = ivar_value
+ end
+
+ def marshal_dump
+ obj = [data]
+ obj.instance_variable_set(:@foo, @ivar_value)
+ obj
+ end
+
+ def marshal_load(o)
+ @data = o[0]
+ end
+
+ def ==(other)
+ self.class === other and
+ @data = other.data
+ end
+ end
+end
+
class UserArray < Array
end
@@ -267,17 +315,6 @@ module MarshalSpec
end
end
- module_eval(<<~ruby.dup.force_encoding(Encoding::UTF_8))
- class MultibyteぁあぃいClass
- end
-
- module MultibyteけげこごModule
- end
-
- class MultibyteぁあぃいTime < Time
- end
- ruby
-
class ObjectWithFreezeRaisingException < Object
def freeze
raise
@@ -494,6 +531,20 @@ module MarshalSpec
"\004\bS:\024Struct::Pyramid\000"],
"Random" => random_data,
}
+
+ module DataSpec
+ Measure = Data.define(:amount, :unit)
+ Empty = Data.define
+
+ MeasureExtended = Class.new(Measure)
+ MeasureExtended.extend(Enumerable)
+
+ class MeasureWithOverriddenName < Measure
+ def self.name
+ "Foo"
+ end
+ end
+ end
end
class ArraySub < Array
diff --git a/spec/ruby/core/marshal/fixtures/marshal_multibyte_data.rb b/spec/ruby/core/marshal/fixtures/marshal_multibyte_data.rb
new file mode 100644
index 0000000000..98a0d43392
--- /dev/null
+++ b/spec/ruby/core/marshal/fixtures/marshal_multibyte_data.rb
@@ -0,0 +1,12 @@
+# -*- encoding: utf-8 -*-
+
+module MarshalSpec
+ class MultibyteぁあぃいClass
+ end
+
+ module MultibyteけげこごModule
+ end
+
+ class MultibyteぁあぃいTime < Time
+ end
+end
diff --git a/spec/ruby/core/marshal/shared/load.rb b/spec/ruby/core/marshal/shared/load.rb
index f599042529..204a4d34e3 100644
--- a/spec/ruby/core/marshal/shared/load.rb
+++ b/spec/ruby/core/marshal/shared/load.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../fixtures/marshal_data'
describe :marshal_load, shared: true do
@@ -23,250 +23,164 @@ describe :marshal_load, shared: true do
-> { Marshal.send(@method, kaboom) }.should raise_error(ArgumentError)
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 "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
+ 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?
- it "returns frozen structs" do
- struct = Marshal.send(@method, Marshal.dump(MarshalSpec::StructToDump.new(1, 2)), freeze: true)
- struct.should == MarshalSpec::StructToDump.new(1, 2)
- struct.should.frozen?
- end
+ 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 "returns frozen objects" do
- source_object = Object.new
+ 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
- object = Marshal.send(@method, Marshal.dump(source_object), freeze: true)
- object.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
- describe "deep freezing" do
- it "returns hashes with frozen keys and values" do
- key = Object.new
- value = Object.new
- source_object = {key => value}
+ it "returns frozen regexps" do
+ regexp = Marshal.send(@method, Marshal.dump(/foo/), freeze: true)
+ regexp.should == /foo/
+ regexp.should.frozen?
+ end
- hash = Marshal.send(@method, Marshal.dump(source_object), freeze: true)
- hash.size.should == 1
- hash.keys[0].should.frozen?
- hash.values[0].should.frozen?
- end
+ it "returns frozen structs" do
+ struct = Marshal.send(@method, Marshal.dump(MarshalSpec::StructToDump.new(1, 2)), freeze: true)
+ struct.should == MarshalSpec::StructToDump.new(1, 2)
+ struct.should.frozen?
+ end
- it "returns arrays with frozen elements" do
- object = Object.new
- source_object = [object]
+ it "returns frozen objects" do
+ source_object = Object.new
- array = Marshal.send(@method, Marshal.dump(source_object), freeze: true)
- array.size.should == 1
- array[0].should.frozen?
- end
+ object = Marshal.send(@method, Marshal.dump(source_object), freeze: true)
+ object.should.frozen?
+ end
- it "returns structs with frozen members" do
- object1 = Object.new
- object2 = Object.new
- source_object = MarshalSpec::StructToDump.new(object1, object2)
+ describe "deep freezing" do
+ it "returns hashes with frozen keys and values" do
+ key = Object.new
+ value = Object.new
+ source_object = {key => value}
- struct = Marshal.send(@method, Marshal.dump(source_object), freeze: true)
- struct.a.should.frozen?
- struct.b.should.frozen?
- end
+ hash = Marshal.send(@method, Marshal.dump(source_object), freeze: true)
+ hash.size.should == 1
+ hash.keys[0].should.frozen?
+ hash.values[0].should.frozen?
+ end
- it "returns objects with frozen instance variables" do
- source_object = Object.new
- instance_variable = Object.new
- source_object.instance_variable_set(:@a, instance_variable)
+ it "returns arrays with frozen elements" do
+ object = Object.new
+ source_object = [object]
- object = Marshal.send(@method, Marshal.dump(source_object), freeze: true)
- object.instance_variable_get(:@a).should != nil
- object.instance_variable_get(:@a).should.frozen?
- end
+ array = Marshal.send(@method, Marshal.dump(source_object), freeze: true)
+ array.size.should == 1
+ array[0].should.frozen?
+ end
- it "deduplicates frozen strings" do
- source_object = ["foo" + "bar", "foobar"]
- object = Marshal.send(@method, Marshal.dump(source_object), freeze: true)
+ it "returns structs with frozen members" do
+ object1 = Object.new
+ object2 = Object.new
+ source_object = MarshalSpec::StructToDump.new(object1, object2)
- object[0].should equal(object[1])
- end
+ struct = Marshal.send(@method, Marshal.dump(source_object), freeze: true)
+ struct.a.should.frozen?
+ struct.b.should.frozen?
end
- it "does not freeze modules" do
- object = Marshal.send(@method, Marshal.dump(Kernel), freeze: true)
- object.should_not.frozen?
- Kernel.should_not.frozen?
- end
+ it "returns objects with frozen instance variables" do
+ source_object = Object.new
+ instance_variable = Object.new
+ source_object.instance_variable_set(:@a, instance_variable)
- it "does not freeze classes" do
- object = Marshal.send(@method, Marshal.dump(Object), freeze: true)
- object.should_not.frozen?
- Object.should_not.frozen?
+ object = Marshal.send(@method, Marshal.dump(source_object), freeze: true)
+ object.instance_variable_get(:@a).should != nil
+ object.instance_variable_get(:@a).should.frozen?
end
- ruby_bug "#19427", ""..."3.3" do
- it "does freeze extended objects" do
- object = Marshal.load("\x04\be:\x0FEnumerableo:\vObject\x00", freeze: true)
- object.should.frozen?
- end
+ it "deduplicates frozen strings" do
+ source_object = ["foo" + "bar", "foobar"]
+ object = Marshal.send(@method, Marshal.dump(source_object), freeze: true)
- it "does freeze extended objects with instance variables" do
- object = Marshal.load("\x04\be:\x0FEnumerableo:\vObject\x06:\n@ivarT", freeze: true)
- object.should.frozen?
- end
+ object[0].should equal(object[1])
end
+ end
- ruby_bug "#19427", "3.1"..."3.3" do
- it "returns frozen object having #_dump method" do
- object = Marshal.send(@method, Marshal.dump(UserDefined.new), freeze: true)
- object.should.frozen?
- end
-
- it "returns frozen object responding to #marshal_dump and #marshal_load" do
- object = Marshal.send(@method, Marshal.dump(UserMarshal.new), freeze: true)
- object.should.frozen?
- end
+ it "does not freeze modules" do
+ object = Marshal.send(@method, Marshal.dump(Kernel), freeze: true)
+ object.should_not.frozen?
+ Kernel.should_not.frozen?
+ end
- it "returns frozen object extended by a module" do
- object = Object.new
- object.extend(MarshalSpec::ModuleToExtendBy)
+ it "does not freeze classes" do
+ object = Marshal.send(@method, Marshal.dump(Object), freeze: true)
+ object.should_not.frozen?
+ Object.should_not.frozen?
+ end
- object = Marshal.send(@method, Marshal.dump(object), freeze: true)
- object.should.frozen?
- end
+ ruby_bug "#19427", ""..."3.3" do
+ it "does freeze extended objects" do
+ object = Marshal.load("\x04\be:\x0FEnumerableo:\vObject\x00", freeze: true)
+ object.should.frozen?
end
- it "does not call freeze method" do
- object = MarshalSpec::ObjectWithFreezeRaisingException.new
- object = Marshal.send(@method, Marshal.dump(object), freeze: true)
+ it "does freeze extended objects with instance variables" do
+ object = Marshal.load("\x04\be:\x0FEnumerableo:\vObject\x06:\n@ivarT", freeze: true)
object.should.frozen?
end
+ end
- it "returns frozen object even if object does not respond to freeze method" do
- object = MarshalSpec::ObjectWithoutFreeze.new
- object = Marshal.send(@method, Marshal.dump(object), freeze: true)
+ ruby_bug "#19427", ""..."3.3" do
+ it "returns frozen object having #_dump method" do
+ object = Marshal.send(@method, Marshal.dump(UserDefined.new), freeze: true)
object.should.frozen?
end
- it "returns a frozen object when is an instance of String/Array/Regexp/Hash subclass and has instance variables" do
- source_object = UserString.new
- source_object.instance_variable_set(:@foo, "bar")
-
- object = Marshal.send(@method, Marshal.dump(source_object), freeze: true)
+ it "returns frozen object responding to #marshal_dump and #marshal_load" do
+ object = Marshal.send(@method, Marshal.dump(UserMarshal.new), freeze: true)
object.should.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 "returns frozen object extended by a module" do
+ object = Object.new
+ object.extend(MarshalSpec::ModuleToExtendBy)
- 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
+ object = Marshal.send(@method, Marshal.dump(object), freeze: true)
+ object.should.frozen?
end
end
- end
- 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
-
- 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
+ it "does not call freeze method" do
+ object = MarshalSpec::ObjectWithFreezeRaisingException.new
+ object = Marshal.send(@method, Marshal.dump(object), freeze: true)
+ object.should.frozen?
end
- ruby_bug "#19427", ""..."3.3" do
- it "call the proc with extended objects" do
- objs = []
- obj = Marshal.load("\x04\be:\x0FEnumerableo:\vObject\x00", Proc.new { |o| objs << o; o })
- objs.should == [obj]
- end
+ it "returns frozen object even if object does not respond to freeze method" do
+ object = MarshalSpec::ObjectWithoutFreeze.new
+ object = Marshal.send(@method, Marshal.dump(object), freeze: true)
+ object.should.frozen?
end
- it "returns the value of the proc" do
- Marshal.send(@method, Marshal.dump([1,2]), proc { [3,4] }).should == [3,4]
- end
+ it "returns a frozen object when is an instance of String/Array/Regexp/Hash subclass and has instance variables" do
+ source_object = UserString.new
+ source_object.instance_variable_set(:@foo, "bar")
- 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
+ object = Marshal.send(@method, Marshal.dump(source_object), freeze: true)
+ object.should.frozen?
+ end
- it "loads an Array with proc" do
+ describe "when called with a proc" do
+ it "call the proc with frozen objects" do
arr = []
s = +'hi'
s.instance_variable_set(:@foo, 5)
@@ -279,16 +193,96 @@ describe :marshal_load, shared: true do
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}
+ 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)
+ 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
+
+ describe "when called with a proc" 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
+
+ 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
+
+ ruby_bug "#19427", ""..."3.3" do
+ it "call the proc with extended objects" do
+ objs = []
+ obj = Marshal.load("\x04\be:\x0FEnumerableo:\vObject\x00", Proc.new { |o| objs << o; o })
+ objs.should == [obj]
+ end
+ end
+
+ it "returns the value of the proc" do
+ Marshal.send(@method, Marshal.dump([1,2]), proc { [3,4] }).should == [3,4]
+ 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.inspect; arg })
+ ret[0].should == 1.inspect
+ ret[1].should == a.inspect
+ ret.size.should == 2
+ 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.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
@@ -364,39 +358,37 @@ describe :marshal_load, shared: true do
end
end
- 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]
+ 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[0].should == o1
- arr[1].should == o2
- arr[2].should == obj
- arr.size.should == 3
- 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.dup; o }
+ o1 = UserMarshal.new
+ o2 = UserMarshalWithIvar.new
- 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[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.size.should == 6
- end
+ arr.size.should == 6
end
it "assigns classes to nested subclasses of Array correctly" do
@@ -526,28 +518,26 @@ describe :marshal_load, shared: true do
unmarshalled[:key].instance_variable_get(:@string_ivar).should == 'string ivar'
end
- ruby_version_is "3.1" do
- it "preserves compare_by_identity behaviour" do
- h = { a: 1 }
- h.compare_by_identity
- unmarshalled = Marshal.send(@method, Marshal.dump(h))
- unmarshalled.should.compare_by_identity?
+ it "preserves compare_by_identity behaviour" do
+ h = { a: 1 }
+ h.compare_by_identity
+ unmarshalled = Marshal.send(@method, Marshal.dump(h))
+ unmarshalled.should.compare_by_identity?
- h = { a: 1 }
- unmarshalled = Marshal.send(@method, Marshal.dump(h))
- unmarshalled.should_not.compare_by_identity?
- end
+ h = { a: 1 }
+ unmarshalled = Marshal.send(@method, Marshal.dump(h))
+ unmarshalled.should_not.compare_by_identity?
+ end
- it "preserves compare_by_identity behaviour for a Hash subclass" do
- h = UserHash.new({ a: 1 })
- h.compare_by_identity
- unmarshalled = Marshal.send(@method, Marshal.dump(h))
- unmarshalled.should.compare_by_identity?
+ it "preserves compare_by_identity behaviour for a Hash subclass" do
+ h = UserHash.new({ a: 1 })
+ h.compare_by_identity
+ unmarshalled = Marshal.send(@method, Marshal.dump(h))
+ unmarshalled.should.compare_by_identity?
- h = UserHash.new({ a: 1 })
- unmarshalled = Marshal.send(@method, Marshal.dump(h))
- unmarshalled.should_not.compare_by_identity?
- end
+ h = UserHash.new({ a: 1 })
+ unmarshalled = Marshal.send(@method, Marshal.dump(h))
+ unmarshalled.should_not.compare_by_identity?
end
it "allocates an instance of the proper class when Hash subclass with compare_by_identity behaviour" do
@@ -749,6 +739,32 @@ describe :marshal_load, shared: true do
end
end
+ describe "for a Data" do
+ it "loads a Data" do
+ obj = MarshalSpec::DataSpec::Measure.new(100, 'km')
+ dumped = "\x04\bS:#MarshalSpec::DataSpec::Measure\a:\vamountii:\tunit\"\akm"
+ Marshal.dump(obj).should == dumped
+
+ Marshal.send(@method, dumped).should == obj
+ end
+
+ it "loads an extended Data" do
+ obj = MarshalSpec::DataSpec::MeasureExtended.new(100, "km")
+ dumped = "\x04\bS:+MarshalSpec::DataSpec::MeasureExtended\a:\vamountii:\tunit\"\akm"
+ Marshal.dump(obj).should == dumped
+
+ Marshal.send(@method, dumped).should == obj
+ end
+
+ it "returns a frozen object" do
+ obj = MarshalSpec::DataSpec::Measure.new(100, 'km')
+ dumped = "\x04\bS:#MarshalSpec::DataSpec::Measure\a:\vamountii:\tunit\"\akm"
+ Marshal.dump(obj).should == dumped
+
+ Marshal.send(@method, dumped).should.frozen?
+ end
+ end
+
describe "for an Exception" do
it "loads a marshalled exception with no message" do
obj = Exception.new
@@ -1049,7 +1065,7 @@ describe :marshal_load, shared: true do
end
describe "for a Bignum" do
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
context "that is Bignum on 32-bit platforms but Fixnum on 64-bit" do
it "dumps a Fixnum" do
val = Marshal.send(@method, "\004\bl+\ab:wU")
diff --git a/spec/ruby/core/matchdata/bytebegin_spec.rb b/spec/ruby/core/matchdata/bytebegin_spec.rb
new file mode 100644
index 0000000000..08c1fd6d1e
--- /dev/null
+++ b/spec/ruby/core/matchdata/bytebegin_spec.rb
@@ -0,0 +1,132 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.4" do
+ describe "MatchData#bytebegin" do
+ context "when passed an integer argument" do
+ it "returns the byte-based offset of the start of the nth element" do
+ match_data = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ match_data.bytebegin(0).should == 1
+ match_data.bytebegin(2).should == 2
+ end
+
+ it "returns nil when the nth match isn't found" do
+ match_data = /something is( not)? (right)/.match("something is right")
+ match_data.bytebegin(1).should be_nil
+ end
+
+ it "returns the byte-based offset for multi-byte strings" do
+ match_data = /(.)(.)(\d+)(\d)/.match("TñX1138.")
+ match_data.bytebegin(0).should == 1
+ match_data.bytebegin(2).should == 3
+ end
+
+ not_supported_on :opal do
+ it "returns the byte-based offset for multi-byte strings with unicode regexp" do
+ match_data = /(.)(.)(\d+)(\d)/u.match("TñX1138.")
+ match_data.bytebegin(0).should == 1
+ match_data.bytebegin(2).should == 3
+ end
+ end
+
+ it "tries to convert the passed argument to an Integer using #to_int" do
+ obj = mock('to_int')
+ obj.should_receive(:to_int).and_return(2)
+
+ match_data = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ match_data.bytebegin(obj).should == 2
+ end
+
+ it "raises IndexError if index is out of bounds" do
+ match_data = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ -> {
+ match_data.bytebegin(-1)
+ }.should raise_error(IndexError, "index -1 out of matches")
+
+ -> {
+ match_data.bytebegin(3)
+ }.should raise_error(IndexError, "index 3 out of matches")
+ end
+ end
+
+ context "when passed a String argument" do
+ it "return the byte-based offset of the start of the named capture" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
+ match_data.bytebegin("a").should == 1
+ match_data.bytebegin("b").should == 3
+ end
+
+ it "returns the byte-based offset for multi byte strings" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/.match("TñX1138.")
+ match_data.bytebegin("a").should == 1
+ match_data.bytebegin("b").should == 4
+ end
+
+ not_supported_on :opal do
+ it "returns the byte-based offset for multi byte strings with unicode regexp" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/u.match("TñX1138.")
+ match_data.bytebegin("a").should == 1
+ match_data.bytebegin("b").should == 4
+ end
+ end
+
+ it "returns the byte-based offset for the farthest match when multiple named captures use the same name" do
+ match_data = /(?<a>.)(.)(?<a>\d+)(\d)/.match("THX1138.")
+ match_data.bytebegin("a").should == 3
+ end
+
+ it "returns the byte-based offset for multi-byte names" do
+ match_data = /(?<æ>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
+ match_data.bytebegin("æ").should == 1
+ end
+
+ it "raises IndexError if there is no group with the provided name" do
+ match_data = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ -> {
+ match_data.bytebegin("y")
+ }.should raise_error(IndexError, "undefined group name reference: y")
+ end
+ end
+
+ context "when passed a Symbol argument" do
+ it "return the byte-based offset of the start of the named capture" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
+ match_data.bytebegin(:a).should == 1
+ match_data.bytebegin(:b).should == 3
+ end
+
+ it "returns the byte-based offset for multi byte strings" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/.match("TñX1138.")
+ match_data.bytebegin(:a).should == 1
+ match_data.bytebegin(:b).should == 4
+ end
+
+ not_supported_on :opal do
+ it "returns the byte-based offset for multi byte strings with unicode regexp" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/u.match("TñX1138.")
+ match_data.bytebegin(:a).should == 1
+ match_data.bytebegin(:b).should == 4
+ end
+ end
+
+ it "returns the byte-based offset for the farthest match when multiple named captures use the same name" do
+ match_data = /(?<a>.)(.)(?<a>\d+)(\d)/.match("THX1138.")
+ match_data.bytebegin(:a).should == 3
+ end
+
+ it "returns the byte-based offset for multi-byte names" do
+ match_data = /(?<æ>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
+ match_data.bytebegin(:æ).should == 1
+ end
+
+ it "raises IndexError if there is no group with the provided name" do
+ match_data = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ -> {
+ match_data.bytebegin(:y)
+ }.should raise_error(IndexError, "undefined group name reference: y")
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/matchdata/byteend_spec.rb b/spec/ruby/core/matchdata/byteend_spec.rb
new file mode 100644
index 0000000000..98015e287d
--- /dev/null
+++ b/spec/ruby/core/matchdata/byteend_spec.rb
@@ -0,0 +1,104 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.4" do
+ describe "MatchData#byteend" do
+ context "when passed an integer argument" do
+ it "returns the byte-based offset of the end of the nth element" do
+ match_data = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ match_data.byteend(0).should == 7
+ match_data.byteend(2).should == 3
+ end
+
+ it "returns nil when the nth match isn't found" do
+ match_data = /something is( not)? (right)/.match("something is right")
+ match_data.byteend(1).should be_nil
+ end
+
+ it "returns the byte-based offset for multi-byte strings" do
+ match_data = /(.)(.)(\d+)(\d)/.match("TñX1138.")
+ match_data.byteend(0).should == 8
+ match_data.byteend(2).should == 4
+ end
+
+ not_supported_on :opal do
+ it "returns the byte-based offset for multi-byte strings with unicode regexp" do
+ match_data = /(.)(.)(\d+)(\d)/u.match("TñX1138.")
+ match_data.byteend(0).should == 8
+ match_data.byteend(2).should == 4
+ end
+ end
+
+ it "tries to convert the passed argument to an Integer using #to_int" do
+ obj = mock('to_int')
+ obj.should_receive(:to_int).and_return(2)
+
+ match_data = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ match_data.byteend(obj).should == 3
+ end
+ end
+
+ context "when passed a String argument" do
+ it "return the byte-based offset of the start of the named capture" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
+ match_data.byteend("a").should == 2
+ match_data.byteend("b").should == 6
+ end
+
+ it "returns the byte-based offset for multi byte strings" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/.match("TñX1138.")
+ match_data.byteend("a").should == 3
+ match_data.byteend("b").should == 7
+ end
+
+ not_supported_on :opal do
+ it "returns the byte-based offset for multi byte strings with unicode regexp" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/u.match("TñX1138.")
+ match_data.byteend("a").should == 3
+ match_data.byteend("b").should == 7
+ end
+ end
+
+ it "returns the byte-based offset for the farthest match when multiple named captures use the same name" do
+ match_data = /(?<a>.)(.)(?<a>\d+)(\d)/.match("THX1138.")
+ match_data.byteend("a").should == 6
+ end
+
+ it "returns the byte-based offset for multi-byte names" do
+ match_data = /(?<æ>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
+ match_data.byteend("æ").should == 2
+ end
+ end
+
+ context "when passed a Symbol argument" do
+ it "return the byte-based offset of the start of the named capture" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
+ match_data.byteend(:a).should == 2
+ match_data.byteend(:b).should == 6
+ end
+
+ it "returns the byte-based offset for multi byte strings" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/.match("TñX1138.")
+ match_data.byteend(:a).should == 3
+ match_data.byteend(:b).should == 7
+ end
+
+ not_supported_on :opal do
+ it "returns the byte-based offset for multi byte strings with unicode regexp" do
+ match_data = /(?<a>.)(.)(?<b>\d+)(\d)/u.match("TñX1138.")
+ match_data.byteend(:a).should == 3
+ match_data.byteend(:b).should == 7
+ end
+ end
+
+ it "returns the byte-based offset for the farthest match when multiple named captures use the same name" do
+ match_data = /(?<a>.)(.)(?<a>\d+)(\d)/.match("THX1138.")
+ match_data.byteend(:a).should == 6
+ end
+
+ it "returns the byte-based offset for multi-byte names" do
+ match_data = /(?<æ>.)(.)(?<b>\d+)(\d)/.match("THX1138.")
+ match_data.byteend(:æ).should == 2
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/matchdata/byteoffset_spec.rb b/spec/ruby/core/matchdata/byteoffset_spec.rb
index b27267fd0e..fb8f5fb67d 100644
--- a/spec/ruby/core/matchdata/byteoffset_spec.rb
+++ b/spec/ruby/core/matchdata/byteoffset_spec.rb
@@ -1,95 +1,93 @@
require_relative '../../spec_helper'
describe "MatchData#byteoffset" do
- ruby_version_is "3.2" do
- it "returns beginning and ending byte-based offset of whole matched substring for 0 element" do
- m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- m.byteoffset(0).should == [1, 7]
- end
+ it "returns beginning and ending byte-based offset of whole matched substring for 0 element" do
+ m = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ m.byteoffset(0).should == [1, 7]
+ end
- it "returns beginning and ending byte-based offset of n-th match, all the subsequent elements are capturing groups" do
- m = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ it "returns beginning and ending byte-based offset of n-th match, all the subsequent elements are capturing groups" do
+ m = /(.)(.)(\d+)(\d)/.match("THX1138.")
- m.byteoffset(2).should == [2, 3]
- m.byteoffset(3).should == [3, 6]
- m.byteoffset(4).should == [6, 7]
- end
+ m.byteoffset(2).should == [2, 3]
+ m.byteoffset(3).should == [3, 6]
+ m.byteoffset(4).should == [6, 7]
+ end
- it "accepts String as a reference to a named capture" do
- m = /(?<f>foo)(?<b>bar)/.match("foobar")
+ it "accepts String as a reference to a named capture" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
- m.byteoffset("f").should == [0, 3]
- m.byteoffset("b").should == [3, 6]
- end
+ m.byteoffset("f").should == [0, 3]
+ m.byteoffset("b").should == [3, 6]
+ end
- it "accepts Symbol as a reference to a named capture" do
- m = /(?<f>foo)(?<b>bar)/.match("foobar")
+ it "accepts Symbol as a reference to a named capture" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
- m.byteoffset(:f).should == [0, 3]
- m.byteoffset(:b).should == [3, 6]
- end
+ m.byteoffset(:f).should == [0, 3]
+ m.byteoffset(:b).should == [3, 6]
+ end
- it "returns [nil, nil] if a capturing group is optional and doesn't match" do
- m = /(?<x>q..)?/.match("foobarbaz")
+ it "returns [nil, nil] if a capturing group is optional and doesn't match" do
+ m = /(?<x>q..)?/.match("foobarbaz")
- m.byteoffset("x").should == [nil, nil]
- m.byteoffset(1).should == [nil, nil]
- end
+ m.byteoffset("x").should == [nil, nil]
+ m.byteoffset(1).should == [nil, nil]
+ end
- it "returns correct beginning and ending byte-based offset for multi-byte strings" do
- m = /\A\u3042(.)(.)?(.)\z/.match("\u3042\u3043\u3044")
+ it "returns correct beginning and ending byte-based offset for multi-byte strings" do
+ m = /\A\u3042(.)(.)?(.)\z/.match("\u3042\u3043\u3044")
- m.byteoffset(1).should == [3, 6]
- m.byteoffset(3).should == [6, 9]
- end
+ m.byteoffset(1).should == [3, 6]
+ m.byteoffset(3).should == [6, 9]
+ end
- it "returns [nil, nil] if a capturing group is optional and doesn't match for multi-byte string" do
- m = /\A\u3042(.)(.)?(.)\z/.match("\u3042\u3043\u3044")
+ it "returns [nil, nil] if a capturing group is optional and doesn't match for multi-byte string" do
+ m = /\A\u3042(.)(.)?(.)\z/.match("\u3042\u3043\u3044")
- m.byteoffset(2).should == [nil, nil]
- end
+ m.byteoffset(2).should == [nil, nil]
+ end
- it "converts argument into integer if is not String nor Symbol" do
- m = /(?<f>foo)(?<b>bar)/.match("foobar")
+ it "converts argument into integer if is not String nor Symbol" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
- obj = Object.new
- def obj.to_int; 2; end
+ obj = Object.new
+ def obj.to_int; 2; end
- m.byteoffset(1r).should == [0, 3]
- m.byteoffset(1.1).should == [0, 3]
- m.byteoffset(obj).should == [3, 6]
- end
+ m.byteoffset(1r).should == [0, 3]
+ m.byteoffset(1.1).should == [0, 3]
+ m.byteoffset(obj).should == [3, 6]
+ end
- it "raises IndexError if there is no group with the provided name" do
- m = /(?<f>foo)(?<b>bar)/.match("foobar")
+ it "raises IndexError if there is no group with the provided name" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
- -> {
- m.byteoffset("y")
- }.should raise_error(IndexError, "undefined group name reference: y")
+ -> {
+ m.byteoffset("y")
+ }.should raise_error(IndexError, "undefined group name reference: y")
- -> {
- m.byteoffset(:y)
- }.should raise_error(IndexError, "undefined group name reference: y")
- end
+ -> {
+ m.byteoffset(:y)
+ }.should raise_error(IndexError, "undefined group name reference: y")
+ end
- it "raises IndexError if index is out of bounds" do
- m = /(?<f>foo)(?<b>bar)/.match("foobar")
+ it "raises IndexError if index is out of bounds" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
- -> {
- m.byteoffset(-1)
- }.should raise_error(IndexError, "index -1 out of matches")
+ -> {
+ m.byteoffset(-1)
+ }.should raise_error(IndexError, "index -1 out of matches")
- -> {
- m.byteoffset(3)
- }.should raise_error(IndexError, "index 3 out of matches")
- end
+ -> {
+ m.byteoffset(3)
+ }.should raise_error(IndexError, "index 3 out of matches")
+ end
- it "raises TypeError if can't convert argument into Integer" do
- m = /(?<f>foo)(?<b>bar)/.match("foobar")
+ it "raises TypeError if can't convert argument into Integer" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
- -> {
- m.byteoffset([])
- }.should raise_error(TypeError, "no implicit conversion of Array into Integer")
- end
+ -> {
+ m.byteoffset([])
+ }.should raise_error(TypeError, "no implicit conversion of Array into Integer")
end
end
diff --git a/spec/ruby/core/matchdata/deconstruct_keys_spec.rb b/spec/ruby/core/matchdata/deconstruct_keys_spec.rb
index 5b68f886c7..bf22bc33ff 100644
--- a/spec/ruby/core/matchdata/deconstruct_keys_spec.rb
+++ b/spec/ruby/core/matchdata/deconstruct_keys_spec.rb
@@ -1,65 +1,63 @@
require_relative '../../spec_helper'
describe "MatchData#deconstruct_keys" do
- ruby_version_is "3.2" do
- it "returns whole hash for nil as an argument" do
- m = /(?<f>foo)(?<b>bar)/.match("foobar")
+ it "returns whole hash for nil as an argument" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
- m.deconstruct_keys(nil).should == { f: "foo", b: "bar" }
- end
+ m.deconstruct_keys(nil).should == { f: "foo", b: "bar" }
+ end
- it "returns only specified keys" do
- m = /(?<f>foo)(?<b>bar)/.match("foobar")
+ it "returns only specified keys" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
- m.deconstruct_keys([:f]).should == { f: "foo" }
- end
+ m.deconstruct_keys([:f]).should == { f: "foo" }
+ end
- it "requires one argument" do
- m = /l/.match("l")
+ it "requires one argument" do
+ m = /l/.match("l")
- -> {
- m.deconstruct_keys
- }.should raise_error(ArgumentError, "wrong number of arguments (given 0, expected 1)")
- end
+ -> {
+ m.deconstruct_keys
+ }.should raise_error(ArgumentError, "wrong number of arguments (given 0, expected 1)")
+ end
- it "it raises error when argument is neither nil nor array" do
- m = /(?<f>foo)(?<b>bar)/.match("foobar")
+ it "it raises error when argument is neither nil nor array" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
- -> { m.deconstruct_keys(1) }.should raise_error(TypeError, "wrong argument type Integer (expected Array)")
- -> { m.deconstruct_keys("asd") }.should raise_error(TypeError, "wrong argument type String (expected Array)")
- -> { m.deconstruct_keys(:x) }.should raise_error(TypeError, "wrong argument type Symbol (expected Array)")
- -> { m.deconstruct_keys({}) }.should raise_error(TypeError, "wrong argument type Hash (expected Array)")
- end
+ -> { m.deconstruct_keys(1) }.should raise_error(TypeError, "wrong argument type Integer (expected Array)")
+ -> { m.deconstruct_keys("asd") }.should raise_error(TypeError, "wrong argument type String (expected Array)")
+ -> { m.deconstruct_keys(:x) }.should raise_error(TypeError, "wrong argument type Symbol (expected Array)")
+ -> { m.deconstruct_keys({}) }.should raise_error(TypeError, "wrong argument type Hash (expected Array)")
+ end
- it "returns {} when passed []" do
- m = /(?<f>foo)(?<b>bar)/.match("foobar")
+ it "returns {} when passed []" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
- m.deconstruct_keys([]).should == {}
- end
+ m.deconstruct_keys([]).should == {}
+ end
- it "does not accept non-Symbol keys" do
- m = /(?<f>foo)(?<b>bar)/.match("foobar")
+ it "does not accept non-Symbol keys" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
- -> {
- m.deconstruct_keys(['year', :foo])
- }.should raise_error(TypeError, "wrong argument type String (expected Symbol)")
- end
+ -> {
+ m.deconstruct_keys(['year', :foo])
+ }.should raise_error(TypeError, "wrong argument type String (expected Symbol)")
+ end
- it "process keys till the first non-existing one" do
- m = /(?<f>foo)(?<b>bar)(?<c>baz)/.match("foobarbaz")
+ it "process keys till the first non-existing one" do
+ m = /(?<f>foo)(?<b>bar)(?<c>baz)/.match("foobarbaz")
- m.deconstruct_keys([:f, :a, :b]).should == { f: "foo" }
- end
+ m.deconstruct_keys([:f, :a, :b]).should == { f: "foo" }
+ end
- it "returns {} when there are no named captured groups at all" do
- m = /foo.+/.match("foobar")
+ it "returns {} when there are no named captured groups at all" do
+ m = /foo.+/.match("foobar")
- m.deconstruct_keys(nil).should == {}
- end
+ m.deconstruct_keys(nil).should == {}
+ end
- it "returns {} when passed more keys than named captured groups" do
- m = /(?<f>foo)(?<b>bar)/.match("foobar")
- m.deconstruct_keys([:f, :b, :c]).should == {}
- end
+ it "returns {} when passed more keys than named captured groups" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
+ m.deconstruct_keys([:f, :b, :c]).should == {}
end
end
diff --git a/spec/ruby/core/matchdata/deconstruct_spec.rb b/spec/ruby/core/matchdata/deconstruct_spec.rb
index 6af55113b6..c55095665d 100644
--- a/spec/ruby/core/matchdata/deconstruct_spec.rb
+++ b/spec/ruby/core/matchdata/deconstruct_spec.rb
@@ -2,7 +2,5 @@ require_relative '../../spec_helper'
require_relative 'shared/captures'
describe "MatchData#deconstruct" do
- ruby_version_is "3.2" do
- it_behaves_like :matchdata_captures, :deconstruct
- end
+ it_behaves_like :matchdata_captures, :deconstruct
end
diff --git a/spec/ruby/core/matchdata/element_reference_spec.rb b/spec/ruby/core/matchdata/element_reference_spec.rb
index 806db2d7b5..0924be0aae 100644
--- a/spec/ruby/core/matchdata/element_reference_spec.rb
+++ b/spec/ruby/core/matchdata/element_reference_spec.rb
@@ -20,6 +20,11 @@ describe "MatchData#[]" do
# negative index is larger than the number of match values
/(.)(.)(\d+)(\d)/.match("THX1138.")[-30, 2].should == nil
+ # positive index larger than number of match values
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[5, 2].should == []
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[6, 2].should == nil
+ /(.)(.)(\d+)(\d)/.match("THX1138.")[30, 2].should == nil
+
# length argument larger than number of match values is capped to match value length
/(.)(.)(\d+)(\d)/.match("THX1138.")[3, 10].should == %w|113 8|
diff --git a/spec/ruby/core/matchdata/match_length_spec.rb b/spec/ruby/core/matchdata/match_length_spec.rb
index f7785ab1a0..824f94a397 100644
--- a/spec/ruby/core/matchdata/match_length_spec.rb
+++ b/spec/ruby/core/matchdata/match_length_spec.rb
@@ -2,33 +2,31 @@
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.")
+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
+ 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 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>t(?<a>ack))/)
- md.match_length(:a).should == 3
- md.match_length(:t).should == 4
- end
+ it "returns the length of the corresponding named match when given a Symbol" do
+ md = 'haystack'.match(/(?<t>t(?<a>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>t)(?<a>all)?/)
- md.match_length(:t).should == 1
- md.match_length(:a).should == nil
- end
+ it "returns nil on non-matching index matches" do
+ md = 'haystack'.match(/(?<t>t)(?<a>all)?/)
+ md.match_length(:t).should == 1
+ md.match_length(:a).should == nil
end
end
diff --git a/spec/ruby/core/matchdata/match_spec.rb b/spec/ruby/core/matchdata/match_spec.rb
index 545de6f93f..a16914ea15 100644
--- a/spec/ruby/core/matchdata/match_spec.rb
+++ b/spec/ruby/core/matchdata/match_spec.rb
@@ -2,33 +2,31 @@
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.")
+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
+ 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 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>t(?<a>ack))/)
- md.match(:a).should == 'ack'
- md.match(:t).should == 'tack'
- end
+ it "returns the corresponding named match when given a Symbol" do
+ md = 'haystack'.match(/(?<t>t(?<a>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>t)(?<a>all)?/)
- md.match(:t).should == 't'
- md.match(:a).should == nil
- end
+ it "returns nil on non-matching index matches" do
+ md = 'haystack'.match(/(?<t>t)(?<a>all)?/)
+ md.match(:t).should == 't'
+ md.match(:a).should == nil
end
end
diff --git a/spec/ruby/core/matchdata/offset_spec.rb b/spec/ruby/core/matchdata/offset_spec.rb
index 1ccb54b7a7..a03d58aad1 100644
--- a/spec/ruby/core/matchdata/offset_spec.rb
+++ b/spec/ruby/core/matchdata/offset_spec.rb
@@ -1,30 +1,102 @@
-# -*- encoding: utf-8 -*-
-
require_relative '../../spec_helper'
describe "MatchData#offset" do
- it "returns a two element array with the begin and end of the nth match" do
- match_data = /(.)(.)(\d+)(\d)/.match("THX1138.")
- match_data.offset(0).should == [1, 7]
- match_data.offset(4).should == [6, 7]
+ it "returns beginning and ending character offset of whole matched substring for 0 element" do
+ m = /(.)(.)(\d+)(\d)/.match("THX1138.")
+ m.offset(0).should == [1, 7]
+ end
+
+ it "returns beginning and ending character offset of n-th match, all the subsequent elements are capturing groups" do
+ m = /(.)(.)(\d+)(\d)/.match("THX1138.")
+
+ m.offset(2).should == [2, 3]
+ m.offset(3).should == [3, 6]
+ m.offset(4).should == [6, 7]
+ end
+
+ it "accepts String as a reference to a named capture" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ m.offset("f").should == [0, 3]
+ m.offset("b").should == [3, 6]
+ end
+
+ it "accepts Symbol as a reference to a named capture" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ m.offset(:f).should == [0, 3]
+ m.offset(:b).should == [3, 6]
end
- it "returns [nil, nil] when the nth match isn't found" do
- match_data = /something is( not)? (right)/.match("something is right")
- match_data.offset(1).should == [nil, nil]
+ it "returns [nil, nil] if a capturing group is optional and doesn't match" do
+ m = /(?<x>q..)?/.match("foobarbaz")
+
+ m.offset("x").should == [nil, nil]
+ m.offset(1).should == [nil, nil]
end
- it "returns the offset for multi byte strings" do
- match_data = /(.)(.)(\d+)(\d)/.match("TñX1138.")
- match_data.offset(0).should == [1, 7]
- match_data.offset(4).should == [6, 7]
+ it "returns correct beginning and ending character offset for multi-byte strings" do
+ m = /\A\u3042(.)(.)?(.)\z/.match("\u3042\u3043\u3044")
+
+ m.offset(1).should == [1, 2]
+ m.offset(3).should == [2, 3]
end
not_supported_on :opal do
- it "returns the offset for multi byte strings with unicode regexp" do
- match_data = /(.)(.)(\d+)(\d)/u.match("TñX1138.")
- match_data.offset(0).should == [1, 7]
- match_data.offset(4).should == [6, 7]
+ it "returns correct character offset for multi-byte strings with unicode regexp" do
+ m = /\A\u3042(.)(.)?(.)\z/u.match("\u3042\u3043\u3044")
+
+ m.offset(1).should == [1, 2]
+ m.offset(3).should == [2, 3]
end
end
+
+ it "returns [nil, nil] if a capturing group is optional and doesn't match for multi-byte string" do
+ m = /\A\u3042(.)(.)?(.)\z/.match("\u3042\u3043\u3044")
+
+ m.offset(2).should == [nil, nil]
+ end
+
+ it "converts argument into integer if is not String nor Symbol" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ obj = Object.new
+ def obj.to_int; 2; end
+
+ m.offset(1r).should == [0, 3]
+ m.offset(1.1).should == [0, 3]
+ m.offset(obj).should == [3, 6]
+ end
+
+ it "raises IndexError if there is no group with the provided name" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ -> {
+ m.offset("y")
+ }.should raise_error(IndexError, "undefined group name reference: y")
+
+ -> {
+ m.offset(:y)
+ }.should raise_error(IndexError, "undefined group name reference: y")
+ end
+
+ it "raises IndexError if index is out of bounds" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ -> {
+ m.offset(-1)
+ }.should raise_error(IndexError, "index -1 out of matches")
+
+ -> {
+ m.offset(3)
+ }.should raise_error(IndexError, "index 3 out of matches")
+ end
+
+ it "raises TypeError if can't convert argument into Integer" do
+ m = /(?<f>foo)(?<b>bar)/.match("foobar")
+
+ -> {
+ m.offset([])
+ }.should raise_error(TypeError, "no implicit conversion of Array into Integer")
+ end
end
diff --git a/spec/ruby/core/math/atanh_spec.rb b/spec/ruby/core/math/atanh_spec.rb
index 21fb209941..edcb8f2e52 100644
--- a/spec/ruby/core/math/atanh_spec.rb
+++ b/spec/ruby/core/math/atanh_spec.rb
@@ -1,6 +1,6 @@
require_relative '../../spec_helper'
-require_relative '../../fixtures/math/common'
-require_relative '../../shared/math/atanh'
+require_relative 'fixtures/common'
+require_relative 'shared/atanh'
describe "Math.atanh" do
it_behaves_like :math_atanh_base, :atanh, Math
diff --git a/spec/ruby/core/math/expm1_spec.rb b/spec/ruby/core/math/expm1_spec.rb
new file mode 100644
index 0000000000..5725319abb
--- /dev/null
+++ b/spec/ruby/core/math/expm1_spec.rb
@@ -0,0 +1,37 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+ruby_version_is "4.0" do
+ describe "Math.expm1" do
+ it "calculates Math.exp(arg) - 1" do
+ Math.expm1(3).should == Math.exp(3) - 1
+ end
+
+ it "preserves precision that can be lost otherwise" do
+ Math.expm1(1.0e-16).should be_close(1.0e-16, TOLERANCE)
+ Math.expm1(1.0e-16).should != 0.0
+ end
+
+ it "raises a TypeError if the argument cannot be coerced with Float()" do
+ -> { Math.expm1("test") }.should raise_error(TypeError, "can't convert String into Float")
+ end
+
+ it "returns NaN given NaN" do
+ Math.expm1(nan_value).nan?.should be_true
+ end
+
+ it "raises a TypeError if the argument is nil" do
+ -> { Math.expm1(nil) }.should raise_error(TypeError, "can't convert nil into Float")
+ end
+
+ it "accepts any argument that can be coerced with Float()" do
+ Math.expm1(MathSpecs::Float.new).should be_close(Math::E - 1, TOLERANCE)
+ end
+ end
+
+ describe "Math#expm1" do
+ it "is accessible as a private instance method" do
+ IncludesMath.new.send(:expm1, 23.1415).should be_close(11226018483.0012, TOLERANCE)
+ end
+ end
+end
diff --git a/spec/ruby/fixtures/math/common.rb b/spec/ruby/core/math/fixtures/common.rb
index 024732fa7a..024732fa7a 100644
--- a/spec/ruby/fixtures/math/common.rb
+++ b/spec/ruby/core/math/fixtures/common.rb
diff --git a/spec/ruby/core/math/lgamma_spec.rb b/spec/ruby/core/math/lgamma_spec.rb
index 33e7836448..2bf350993e 100644
--- a/spec/ruby/core/math/lgamma_spec.rb
+++ b/spec/ruby/core/math/lgamma_spec.rb
@@ -5,10 +5,8 @@ describe "Math.lgamma" do
Math.lgamma(0).should == [infinity_value, 1]
end
- platform_is_not :windows do
- it "returns [Infinity, 1] when passed -1" do
- Math.lgamma(-1).should == [infinity_value, 1]
- end
+ it "returns [Infinity, ...] when passed -1" do
+ Math.lgamma(-1)[0].should == infinity_value
end
it "returns [Infinity, -1] when passed -0.0" do
@@ -47,8 +45,7 @@ describe "Math.lgamma" do
Math.lgamma(infinity_value).should == [infinity_value, 1]
end
- it "returns [NaN, 1] when passed NaN" do
- Math.lgamma(nan_value)[0].nan?.should be_true
- Math.lgamma(nan_value)[1].should == 1
+ it "returns [NaN, ...] when passed NaN" do
+ Math.lgamma(nan_value)[0].should.nan?
end
end
diff --git a/spec/ruby/core/math/log1p_spec.rb b/spec/ruby/core/math/log1p_spec.rb
new file mode 100644
index 0000000000..216358a3c4
--- /dev/null
+++ b/spec/ruby/core/math/log1p_spec.rb
@@ -0,0 +1,49 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+ruby_version_is "4.0" do
+ describe "Math.log1p" do
+ it "calculates Math.log(1 + arg)" do
+ Math.log1p(3).should == Math.log(1 + 3)
+ end
+
+ it "preserves precision that can be lost otherwise" do
+ Math.log1p(1e-16).should be_close(1.0e-16, TOLERANCE)
+ Math.log1p(1e-16).should != 0.0
+ end
+
+ it "raises an Math::DomainError if the argument is less than 1" do
+ -> { Math.log1p(-1-1e-15) }.should raise_error(Math::DomainError, "Numerical argument is out of domain - log1p")
+ end
+
+ it "raises a TypeError if the argument cannot be coerced with Float()" do
+ -> { Math.log1p("test") }.should raise_error(TypeError, "can't convert String into Float")
+ end
+
+ it "raises a TypeError for numerical values passed as string" do
+ -> { Math.log1p("10") }.should raise_error(TypeError, "can't convert String into Float")
+ end
+
+ it "does not accept a second argument for the base" do
+ -> { Math.log1p(9, 3) }.should raise_error(ArgumentError, "wrong number of arguments (given 2, expected 1)")
+ end
+
+ it "returns NaN given NaN" do
+ Math.log1p(nan_value).nan?.should be_true
+ end
+
+ it "raises a TypeError if the argument is nil" do
+ -> { Math.log1p(nil) }.should raise_error(TypeError, "can't convert nil into Float")
+ end
+
+ it "accepts any argument that can be coerced with Float()" do
+ Math.log1p(MathSpecs::Float.new).should be_close(0.6931471805599453, TOLERANCE)
+ end
+ end
+
+ describe "Math#log1p" do
+ it "is accessible as a private instance method" do
+ IncludesMath.new.send(:log1p, 4.21).should be_close(1.65057985576528, TOLERANCE)
+ end
+ end
+end
diff --git a/spec/ruby/shared/math/atanh.rb b/spec/ruby/core/math/shared/atanh.rb
index 3fb64153a0..3fb64153a0 100644
--- a/spec/ruby/shared/math/atanh.rb
+++ b/spec/ruby/core/math/shared/atanh.rb
diff --git a/spec/ruby/core/method/owner_spec.rb b/spec/ruby/core/method/owner_spec.rb
index 05422f1697..1cdc4edfa7 100644
--- a/spec/ruby/core/method/owner_spec.rb
+++ b/spec/ruby/core/method/owner_spec.rb
@@ -24,9 +24,7 @@ describe "Method#owner" do
end
end
- ruby_version_is "3.2" do
- it "returns the class on which public was called for a private method in ancestor" do
- MethodSpecs::InheritedMethods::C.new.method(:derp).owner.should == MethodSpecs::InheritedMethods::C
- end
+ it "returns the class on which public was called for a private method in ancestor" do
+ MethodSpecs::InheritedMethods::C.new.method(:derp).owner.should == MethodSpecs::InheritedMethods::C
end
end
diff --git a/spec/ruby/core/method/parameters_spec.rb b/spec/ruby/core/method/parameters_spec.rb
index 8495aef4d2..f1c2523cf0 100644
--- a/spec/ruby/core/method/parameters_spec.rb
+++ b/spec/ruby/core/method/parameters_spec.rb
@@ -233,54 +233,27 @@ describe "Method#parameters" do
m.method(:handled_via_method_missing).parameters.should == [[:rest]]
end
- ruby_version_is '3.2' do
- it "adds rest arg with name * for \"star\" argument" do
- m = MethodSpecs::Methods.new
- m.method(:one_unnamed_splat).parameters.should == [[:rest, :*]]
- end
-
- it "adds keyrest arg with ** as a name for \"double star\" argument" do
- m = MethodSpecs::Methods.new
- m.method(:one_unnamed_keyrest).parameters.should == [[:keyrest, :**]]
- end
+ it "adds rest arg with name * for \"star\" argument" do
+ m = MethodSpecs::Methods.new
+ m.method(:one_unnamed_splat).parameters.should == [[:rest, :*]]
end
- ruby_version_is ''...'3.2' do
- it "adds nameless rest arg for \"star\" argument" do
- m = MethodSpecs::Methods.new
- m.method(:one_unnamed_splat).parameters.should == [[:rest]]
- end
-
- it "adds nameless keyrest arg for \"double star\" argument" do
- m = MethodSpecs::Methods.new
- m.method(:one_unnamed_keyrest).parameters.should == [[:keyrest]]
- end
+ it "adds keyrest arg with ** as a name for \"double star\" argument" do
+ m = MethodSpecs::Methods.new
+ m.method(:one_unnamed_keyrest).parameters.should == [[:keyrest, :**]]
end
- ruby_version_is '3.1' do
- it "adds block arg with name & for anonymous block argument" do
- object = Object.new
-
- eval(<<~RUBY).should == [[:block, :&]]
- def object.foo(&)
- end
- object.method(:foo).parameters
- RUBY
+ it "adds block arg with name & for anonymous block argument" do
+ object = Object.new
+ def object.foo(&)
end
- end
- ruby_version_is ""..."3.1" do
- it "returns [:rest, :*], [:block, :&] for forward parameters operator" do
- m = MethodSpecs::Methods.new
- m.method(:forward_parameters).parameters.should == [[:rest, :*], [:block, :&]]
- end
+ object.method(:foo).parameters.should == [[:block, :&]]
end
- ruby_version_is "3.1" do
- it "returns [:rest, :*], [:keyrest, :**], [:block, :&] for forward parameters operator" do
- m = MethodSpecs::Methods.new
- m.method(:forward_parameters).parameters.should == [[:rest, :*], [:keyrest, :**], [:block, :&]]
- end
+ it "returns [:rest, :*], [:keyrest, :**], [:block, :&] for forward parameters operator" do
+ m = MethodSpecs::Methods.new
+ m.method(:forward_parameters).parameters.should == [[:rest, :*], [:keyrest, :**], [:block, :&]]
end
it "returns the args and block for a splat and block argument" do
diff --git a/spec/ruby/core/method/private_spec.rb b/spec/ruby/core/method/private_spec.rb
index fd550036a3..e708542b2e 100644
--- a/spec/ruby/core/method/private_spec.rb
+++ b/spec/ruby/core/method/private_spec.rb
@@ -2,27 +2,8 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Method#private?" do
- ruby_version_is "3.1"..."3.2" do
- it "returns false when the method is public" do
- obj = MethodSpecs::Methods.new
- obj.method(:my_public_method).private?.should == false
- end
-
- it "returns false when the method is protected" do
- obj = MethodSpecs::Methods.new
- obj.method(:my_protected_method).private?.should == false
- end
-
- it "returns true when the method is private" do
- obj = MethodSpecs::Methods.new
- obj.method(:my_private_method).private?.should == true
- end
- end
-
- ruby_version_is "3.2" do
- it "has been removed" do
- obj = MethodSpecs::Methods.new
- obj.method(:my_private_method).should_not.respond_to?(:private?)
- end
+ it "has been removed" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:my_private_method).should_not.respond_to?(:private?)
end
end
diff --git a/spec/ruby/core/method/protected_spec.rb b/spec/ruby/core/method/protected_spec.rb
index 8423e8c64c..f9e422ae3d 100644
--- a/spec/ruby/core/method/protected_spec.rb
+++ b/spec/ruby/core/method/protected_spec.rb
@@ -2,27 +2,8 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Method#protected?" do
- ruby_version_is "3.1"..."3.2" do
- it "returns false when the method is public" do
- obj = MethodSpecs::Methods.new
- obj.method(:my_public_method).protected?.should == false
- end
-
- it "returns true when the method is protected" do
- obj = MethodSpecs::Methods.new
- obj.method(:my_protected_method).protected?.should == true
- end
-
- it "returns false when the method is private" do
- obj = MethodSpecs::Methods.new
- obj.method(:my_private_method).protected?.should == false
- end
- end
-
- ruby_version_is "3.2" do
- it "has been removed" do
- obj = MethodSpecs::Methods.new
- obj.method(:my_protected_method).should_not.respond_to?(:protected?)
- end
+ it "has been removed" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:my_protected_method).should_not.respond_to?(:protected?)
end
end
diff --git a/spec/ruby/core/method/public_spec.rb b/spec/ruby/core/method/public_spec.rb
index 20d0081a27..4cb23f4cf1 100644
--- a/spec/ruby/core/method/public_spec.rb
+++ b/spec/ruby/core/method/public_spec.rb
@@ -2,27 +2,8 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Method#public?" do
- ruby_version_is "3.1"..."3.2" do
- it "returns true when the method is public" do
- obj = MethodSpecs::Methods.new
- obj.method(:my_public_method).public?.should == true
- end
-
- it "returns false when the method is protected" do
- obj = MethodSpecs::Methods.new
- obj.method(:my_protected_method).public?.should == false
- end
-
- it "returns false when the method is private" do
- obj = MethodSpecs::Methods.new
- obj.method(:my_private_method).public?.should == false
- end
- end
-
- ruby_version_is "3.2" do
- it "has been removed" do
- obj = MethodSpecs::Methods.new
- obj.method(:my_public_method).should_not.respond_to?(:public?)
- end
+ it "has been removed" do
+ obj = MethodSpecs::Methods.new
+ obj.method(:my_public_method).should_not.respond_to?(:public?)
end
end
diff --git a/spec/ruby/core/method/shared/dup.rb b/spec/ruby/core/method/shared/dup.rb
index 1a10b90689..c74847083f 100644
--- a/spec/ruby/core/method/shared/dup.rb
+++ b/spec/ruby/core/method/shared/dup.rb
@@ -16,7 +16,7 @@ describe :method_dup, shared: true do
end
it "copies the finalizer" do
- code = <<-RUBY
+ code = <<-'RUBY'
obj = Object.new.method(:method)
ObjectSpace.define_finalizer(obj, Proc.new { STDOUT.write "finalized\n" })
diff --git a/spec/ruby/core/method/source_location_spec.rb b/spec/ruby/core/method/source_location_spec.rb
index c5b296f6e2..87413a2ab6 100644
--- a/spec/ruby/core/method/source_location_spec.rb
+++ b/spec/ruby/core/method/source_location_spec.rb
@@ -11,23 +11,23 @@ describe "Method#source_location" do
end
it "sets the first value to the path of the file in which the method was defined" do
- file = @method.source_location.first
+ file = @method.source_location[0]
file.should be_an_instance_of(String)
file.should == File.realpath('fixtures/classes.rb', __dir__)
end
it "sets the last value to an Integer representing the line on which the method was defined" do
- line = @method.source_location.last
+ line = @method.source_location[1]
line.should be_an_instance_of(Integer)
line.should == 5
end
it "returns the last place the method was defined" do
- MethodSpecs::SourceLocation.method(:redefined).source_location.last.should == 13
+ MethodSpecs::SourceLocation.method(:redefined).source_location[1].should == 13
end
it "returns the location of the original method even if it was aliased" do
- MethodSpecs::SourceLocation.new.method(:aka).source_location.last.should == 17
+ MethodSpecs::SourceLocation.new.method(:aka).source_location[1].should == 17
end
it "works for methods defined with a block" do
@@ -108,7 +108,13 @@ describe "Method#source_location" do
c = Class.new do
eval('def self.m; end', nil, "foo", 100)
end
- c.method(:m).source_location.should == ["foo", 100]
+ location = c.method(:m).source_location
+ ruby_version_is(""..."4.1") do
+ location.should == ["foo", 100]
+ end
+ ruby_version_is("4.1") do
+ location.should == ["foo", 100, 0, 100, 15]
+ end
end
describe "for a Method generated by respond_to_missing?" do
diff --git a/spec/ruby/core/method/unbind_spec.rb b/spec/ruby/core/method/unbind_spec.rb
index bdedd513ce..0b630e4d88 100644
--- a/spec/ruby/core/method/unbind_spec.rb
+++ b/spec/ruby/core/method/unbind_spec.rb
@@ -27,16 +27,8 @@ describe "Method#unbind" do
@string.should =~ /MethodSpecs::MyMod/
end
- ruby_version_is ""..."3.2" do
- it "returns a String containing the Module the method is referenced from" do
- @string.should =~ /MethodSpecs::MySub/
- end
- end
-
- ruby_version_is "3.2" do
- it "returns a String containing the Module the method is referenced from" do
- @string.should =~ /MethodSpecs::MyMod/
- end
+ it "returns a String containing the Module the method is referenced from" do
+ @string.should =~ /MethodSpecs::MyMod/
end
end
diff --git a/spec/ruby/core/module/ancestors_spec.rb b/spec/ruby/core/module/ancestors_spec.rb
index 5e4c196206..90c26941d1 100644
--- a/spec/ruby/core/module/ancestors_spec.rb
+++ b/spec/ruby/core/module/ancestors_spec.rb
@@ -7,10 +7,17 @@ describe "Module#ancestors" do
ModuleSpecs.ancestors.should == [ModuleSpecs]
ModuleSpecs::Basic.ancestors.should == [ModuleSpecs::Basic]
ModuleSpecs::Super.ancestors.should == [ModuleSpecs::Super, ModuleSpecs::Basic]
- ModuleSpecs.without_test_modules(ModuleSpecs::Parent.ancestors).should ==
- [ModuleSpecs::Parent, Object, Kernel, BasicObject]
- ModuleSpecs.without_test_modules(ModuleSpecs::Child.ancestors).should ==
- [ModuleSpecs::Child, ModuleSpecs::Super, ModuleSpecs::Basic, ModuleSpecs::Parent, Object, Kernel, BasicObject]
+ if defined?(Ruby::Box) && Ruby::Box.enabled?
+ ModuleSpecs.without_test_modules(ModuleSpecs::Parent.ancestors).should ==
+ [ModuleSpecs::Parent, Object, Ruby::Box::Loader, Kernel, BasicObject]
+ ModuleSpecs.without_test_modules(ModuleSpecs::Child.ancestors).should ==
+ [ModuleSpecs::Child, ModuleSpecs::Super, ModuleSpecs::Basic, ModuleSpecs::Parent, Object, Ruby::Box::Loader, Kernel, BasicObject]
+ else
+ ModuleSpecs.without_test_modules(ModuleSpecs::Parent.ancestors).should ==
+ [ModuleSpecs::Parent, Object, Kernel, BasicObject]
+ ModuleSpecs.without_test_modules(ModuleSpecs::Child.ancestors).should ==
+ [ModuleSpecs::Child, ModuleSpecs::Super, ModuleSpecs::Basic, ModuleSpecs::Parent, Object, Kernel, BasicObject]
+ end
end
it "returns only modules and classes" do
@@ -21,6 +28,17 @@ describe "Module#ancestors" do
ModuleSpecs::Parent.ancestors.should == ModuleSpecs::Parent.ancestors.uniq
end
+ it "returns a module that is included later into a nested module as well" do
+ m1 = Module.new
+ m2 = Module.new
+ m3 = Module.new do
+ include m2
+ end
+ m2.include m1 # should be after m3 includes m2
+
+ m3.ancestors.should == [m3, m2, m1]
+ end
+
describe "when called on a singleton class" do
it "includes the singleton classes of ancestors" do
parent = Class.new
diff --git a/spec/ruby/core/module/autoload_spec.rb b/spec/ruby/core/module/autoload_spec.rb
index 45d18b8608..625d945686 100644
--- a/spec/ruby/core/module/autoload_spec.rb
+++ b/spec/ruby/core/module/autoload_spec.rb
@@ -486,42 +486,21 @@ describe "Module#autoload" do
ScratchPad.recorded.should == [:raise, :raise]
end
- 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
-
- 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
+ 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.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.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
+ 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
it "does not try to load the file again if the loaded file did not define the constant" do
@@ -624,78 +603,51 @@ describe "Module#autoload" do
end
end
- ruby_version_is "3.2" do
- it "warns once in verbose mode if the constant was defined in a parent scope" do
- ScratchPad.record -> {
- ModuleSpecs::DeclaredInCurrentDefinedInParent = :declared_in_current_defined_in_parent
- }
+ it "warns once in verbose mode if the constant was defined in a parent scope" do
+ ScratchPad.record -> {
+ ModuleSpecs::DeclaredInCurrentDefinedInParent = :declared_in_current_defined_in_parent
+ }
- module ModuleSpecs
- module Autoload
- autoload :DeclaredInCurrentDefinedInParent, fixture(__FILE__, "autoload_callback.rb")
- self.autoload?(:DeclaredInCurrentDefinedInParent).should == fixture(__FILE__, "autoload_callback.rb")
- const_defined?(:DeclaredInCurrentDefinedInParent).should == true
-
- -> {
- DeclaredInCurrentDefinedInParent
- }.should complain(
- /Expected .*autoload_callback.rb to define ModuleSpecs::Autoload::DeclaredInCurrentDefinedInParent but it didn't/,
- verbose: true,
- )
-
- -> {
- DeclaredInCurrentDefinedInParent
- }.should_not complain(/.*/, verbose: true)
- self.autoload?(:DeclaredInCurrentDefinedInParent).should == nil
- const_defined?(:DeclaredInCurrentDefinedInParent).should == false
- ModuleSpecs.const_defined?(:DeclaredInCurrentDefinedInParent).should == true
- end
+ module ModuleSpecs
+ module Autoload
+ autoload :DeclaredInCurrentDefinedInParent, fixture(__FILE__, "autoload_callback.rb")
+ self.autoload?(:DeclaredInCurrentDefinedInParent).should == fixture(__FILE__, "autoload_callback.rb")
+ const_defined?(:DeclaredInCurrentDefinedInParent).should == true
+
+ -> {
+ DeclaredInCurrentDefinedInParent
+ }.should complain(
+ /Expected .*autoload_callback.rb to define ModuleSpecs::Autoload::DeclaredInCurrentDefinedInParent but it didn't/,
+ verbose: true,
+ )
+
+ -> {
+ DeclaredInCurrentDefinedInParent
+ }.should_not complain(/.*/, verbose: true)
+ self.autoload?(:DeclaredInCurrentDefinedInParent).should == nil
+ const_defined?(:DeclaredInCurrentDefinedInParent).should == false
+ ModuleSpecs.const_defined?(:DeclaredInCurrentDefinedInParent).should == true
end
end
end
- 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_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
+ it "looks up in parent scope after failed autoload" do
+ @remove << :DeclaredInCurrentDefinedInParent
+ module ModuleSpecs::Autoload
+ ScratchPad.record -> {
+ DeclaredInCurrentDefinedInParent = :declared_in_current_defined_in_parent
+ }
- DeclaredInCurrentDefinedInParent.should == :declared_in_current_defined_in_parent
+ 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
- end
- end
-
- 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
+ DeclaredInCurrentDefinedInParent.should == :declared_in_current_defined_in_parent
end
end
@@ -766,6 +718,21 @@ describe "Module#autoload" do
end
end
+ it "should trigger the autoload when using `private_constant`" do
+ @remove << :DynClass
+ module ModuleSpecs::Autoload
+ autoload :DynClass, fixture(__FILE__, "autoload_c.rb")
+ private_constant :DynClass
+
+ ScratchPad.recorded.should be_nil
+
+ DynClass::C.new.loaded.should == :dynclass_c
+ ScratchPad.recorded.should == :loaded
+ end
+
+ -> { ModuleSpecs::Autoload::DynClass }.should raise_error(NameError, /private constant/)
+ end
+
# [ruby-core:19127] [ruby-core:29941]
it "does NOT raise a NameError when the autoload file did not define the constant and a module is opened with the same name" do
module ModuleSpecs::Autoload
diff --git a/spec/ruby/core/module/const_added_spec.rb b/spec/ruby/core/module/const_added_spec.rb
index f9edda3a07..90cd36551a 100644
--- a/spec/ruby/core/module/const_added_spec.rb
+++ b/spec/ruby/core/module/const_added_spec.rb
@@ -1,160 +1,238 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
+require_relative 'fixtures/const_added'
describe "Module#const_added" do
- ruby_version_is "3.2" do
- it "is a private instance method" do
- Module.should have_private_instance_method(:const_added)
+ it "is a private instance method" do
+ Module.should have_private_instance_method(:const_added)
+ end
+
+ it "returns nil in the default implementation" do
+ Module.new do
+ const_added(:TEST).should == nil
end
+ end
- it "returns nil in the default implementation" do
- Module.new do
- const_added(:TEST).should == nil
+ it "for a class defined with the `class` keyword, const_added runs before inherited" do
+ ScratchPad.record []
+
+ mod = Module.new do
+ def self.const_added(_)
+ ScratchPad << :const_added
end
end
- it "is called when a new constant is assigned on self" do
- ScratchPad.record []
-
- mod = Module.new do
- def self.const_added(name)
- ScratchPad << name
- end
+ parent = Class.new do
+ def self.inherited(_)
+ ScratchPad << :inherited
end
+ end
- mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
- TEST = 1
- RUBY
+ class mod::C < parent; end
- ScratchPad.recorded.should == [:TEST]
- end
+ ScratchPad.recorded.should == [:const_added, :inherited]
+ end
- it "is called when a new constant is assigned on self through const_set" do
- ScratchPad.record []
+ it "the superclass of a class assigned to a constant is set before const_added is called" do
+ ScratchPad.record []
- mod = Module.new do
- def self.const_added(name)
- ScratchPad << name
- end
+ parent = Class.new do
+ def self.const_added(name)
+ ScratchPad << name
+ ScratchPad << const_get(name).superclass
end
+ end
+
+ class parent::C < parent; end
- mod.const_set(:TEST, 1)
+ ScratchPad.recorded.should == [:C, parent]
+ end
+
+ it "is called when a new constant is assigned on self" do
+ ScratchPad.record []
- ScratchPad.recorded.should == [:TEST]
+ mod = Module.new do
+ def self.const_added(name)
+ ScratchPad << name
+ end
end
- it "is called when a new module is defined under self" do
- ScratchPad.record []
+ mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
+ TEST = 1
+ RUBY
- mod = Module.new do
- def self.const_added(name)
- ScratchPad << name
- end
+ ScratchPad.recorded.should == [:TEST]
+ end
+
+ it "is called when a new constant is assigned on self through const_set" do
+ ScratchPad.record []
+
+ mod = Module.new do
+ def self.const_added(name)
+ ScratchPad << name
end
+ end
- mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
- module SubModule
- end
+ mod.const_set(:TEST, 1)
- module SubModule
- end
- RUBY
+ ScratchPad.recorded.should == [:TEST]
+ end
- ScratchPad.recorded.should == [:SubModule]
+ it "is called when a new module is defined under self" do
+ ScratchPad.record []
+
+ mod = Module.new do
+ def self.const_added(name)
+ ScratchPad << name
+ end
end
- it "is called when a new class is defined under self" do
- ScratchPad.record []
+ mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
+ module SubModule
+ end
+
+ module SubModule
+ end
+ RUBY
+
+ ScratchPad.recorded.should == [:SubModule]
+ end
+
+ it "is called when a new module is defined under a named module (assigned to a constant)" do
+ ScratchPad.record []
+
+ ModuleSpecs::ConstAddedSpecs::NamedModule = Module.new do
+ def self.const_added(name)
+ ScratchPad << name
+ end
- mod = Module.new do
+ module self::A
def self.const_added(name)
ScratchPad << name
end
- end
- mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
- class SubClass
+ module self::B
end
+ end
+ end
- class SubClass
- end
- RUBY
+ ScratchPad.recorded.should == [:A, :B]
+ ModuleSpecs::ConstAddedSpecs.send :remove_const, :NamedModule
+ end
+
+ it "is called when a new class is defined under self" do
+ ScratchPad.record []
- ScratchPad.recorded.should == [:SubClass]
+ mod = Module.new do
+ def self.const_added(name)
+ ScratchPad << name
+ end
end
- it "is called when an autoload is defined" do
- ScratchPad.record []
+ mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
+ class SubClass
+ end
- mod = Module.new do
- def self.const_added(name)
- ScratchPad << name
- end
+ class SubClass
end
+ RUBY
- mod.autoload :Autoload, "foo"
- ScratchPad.recorded.should == [:Autoload]
- end
+ ScratchPad.recorded.should == [:SubClass]
+ end
+
+ it "is called when a new class is defined under a named module (assigned to a constant)" do
+ ScratchPad.record []
- it "is called with a precise caller location with the line of definition" do
- ScratchPad.record []
+ ModuleSpecs::ConstAddedSpecs::NamedModuleB = Module.new do
+ def self.const_added(name)
+ ScratchPad << name
+ end
- mod = Module.new do
+ class self::A
def self.const_added(name)
- location = caller_locations(1, 1)[0]
- ScratchPad << location.lineno
+ ScratchPad << name
+ end
+
+ class self::B
end
end
+ end
- line = __LINE__
- mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
- TEST = 1
+ ScratchPad.recorded.should == [:A, :B]
+ ModuleSpecs::ConstAddedSpecs.send :remove_const, :NamedModuleB
+ end
- module SubModule
- end
+ it "is called when an autoload is defined" do
+ ScratchPad.record []
- class SubClass
- end
- RUBY
+ mod = Module.new do
+ def self.const_added(name)
+ ScratchPad << name
+ end
+ end
- mod.const_set(:CONST_SET, 1)
+ mod.autoload :Autoload, "foo"
+ ScratchPad.recorded.should == [:Autoload]
+ end
- ScratchPad.recorded.should == [line + 2, line + 4, line + 7, line + 11]
+ it "is called with a precise caller location with the line of definition" do
+ ScratchPad.record []
+
+ mod = Module.new do
+ def self.const_added(name)
+ location = caller_locations(1, 1)[0]
+ ScratchPad << location.lineno
+ end
end
- it "is called when the constant is already assigned a value" do
- ScratchPad.record []
+ line = __LINE__
+ mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
+ TEST = 1
- mod = Module.new do
- def self.const_added(name)
- ScratchPad.record const_get(name)
- end
+ module SubModule
end
- mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
- TEST = 123
- RUBY
+ class SubClass
+ end
+ RUBY
- ScratchPad.recorded.should == 123
- end
+ mod.const_set(:CONST_SET, 1)
- it "records re-definition of existing constants" do
- ScratchPad.record []
+ ScratchPad.recorded.should == [line + 2, line + 4, line + 7, line + 11]
+ end
- mod = Module.new do
- def self.const_added(name)
- ScratchPad << const_get(name)
- end
+ it "is called when the constant is already assigned a value" do
+ ScratchPad.record []
+
+ mod = Module.new do
+ def self.const_added(name)
+ ScratchPad.record const_get(name)
end
+ end
+
+ mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
+ TEST = 123
+ RUBY
- -> {
- mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
- TEST = 123
- TEST = 456
- RUBY
- }.should complain(/warning: already initialized constant .+::TEST/)
+ ScratchPad.recorded.should == 123
+ end
+
+ it "records re-definition of existing constants" do
+ ScratchPad.record []
- ScratchPad.recorded.should == [123, 456]
+ mod = Module.new do
+ def self.const_added(name)
+ ScratchPad << const_get(name)
+ end
end
+
+ -> {
+ mod.module_eval(<<-RUBY, __FILE__, __LINE__ + 1)
+ TEST = 123
+ TEST = 456
+ RUBY
+ }.should complain(/warning: already initialized constant .+::TEST/)
+
+ ScratchPad.recorded.should == [123, 456]
end
end
diff --git a/spec/ruby/core/module/const_defined_spec.rb b/spec/ruby/core/module/const_defined_spec.rb
index 027cf5a245..8b137cd134 100644
--- a/spec/ruby/core/module/const_defined_spec.rb
+++ b/spec/ruby/core/module/const_defined_spec.rb
@@ -65,6 +65,8 @@ describe "Module#const_defined?" do
str = "CS_CONSTλ".encode("euc-jp")
ConstantSpecs.const_set str, 1
ConstantSpecs.const_defined?(str).should be_true
+ ensure
+ ConstantSpecs.send(:remove_const, str)
end
it "returns false if the constant is not defined in the receiver, its superclass, or any included modules" do
diff --git a/spec/ruby/core/module/const_get_spec.rb b/spec/ruby/core/module/const_get_spec.rb
index 0233118f4b..4b53cbe7b3 100644
--- a/spec/ruby/core/module/const_get_spec.rb
+++ b/spec/ruby/core/module/const_get_spec.rb
@@ -131,7 +131,7 @@ describe "Module#const_get" do
end
it "does read private constants" do
- ConstantSpecs.const_get(:CS_PRIVATE).should == :cs_private
+ ConstantSpecs.const_get(:CS_PRIVATE).should == :cs_private
end
it 'does autoload a constant' do
@@ -202,40 +202,60 @@ describe "Module#const_get" do
ConstantSpecs::ContainerA::ChildA::CS_CONST301 = :const301_5
ConstantSpecs::ContainerA::ChildA.const_get(:CS_CONST301).should == :const301_5
+ ensure
+ ConstantSpecs::ClassA.send(:remove_const, :CS_CONST301)
+ ConstantSpecs::ModuleA.send(:remove_const, :CS_CONST301)
+ ConstantSpecs::ParentA.send(:remove_const, :CS_CONST301)
+ ConstantSpecs::ContainerA::ChildA.send(:remove_const, :CS_CONST301)
end
it "searches a module included in the immediate class before the superclass" do
ConstantSpecs::ParentB::CS_CONST302 = :const302_1
ConstantSpecs::ModuleF::CS_CONST302 = :const302_2
ConstantSpecs::ContainerB::ChildB.const_get(:CS_CONST302).should == :const302_2
+ ensure
+ ConstantSpecs::ParentB.send(:remove_const, :CS_CONST302)
+ ConstantSpecs::ModuleF.send(:remove_const, :CS_CONST302)
end
it "searches the superclass before a module included in the superclass" do
ConstantSpecs::ModuleE::CS_CONST303 = :const303_1
ConstantSpecs::ParentB::CS_CONST303 = :const303_2
ConstantSpecs::ContainerB::ChildB.const_get(:CS_CONST303).should == :const303_2
+ ensure
+ ConstantSpecs::ModuleE.send(:remove_const, :CS_CONST303)
+ ConstantSpecs::ParentB.send(:remove_const, :CS_CONST303)
end
it "searches a module included in the superclass" do
ConstantSpecs::ModuleA::CS_CONST304 = :const304_1
ConstantSpecs::ModuleE::CS_CONST304 = :const304_2
ConstantSpecs::ContainerB::ChildB.const_get(:CS_CONST304).should == :const304_2
+ ensure
+ ConstantSpecs::ModuleA.send(:remove_const, :CS_CONST304)
+ ConstantSpecs::ModuleE.send(:remove_const, :CS_CONST304)
end
it "searches the superclass chain" do
ConstantSpecs::ModuleA::CS_CONST305 = :const305
ConstantSpecs::ContainerB::ChildB.const_get(:CS_CONST305).should == :const305
+ ensure
+ ConstantSpecs::ModuleA.send(:remove_const, :CS_CONST305)
end
it "returns a toplevel constant when the receiver is a Class" do
Object::CS_CONST306 = :const306
ConstantSpecs::ContainerB::ChildB.const_get(:CS_CONST306).should == :const306
+ ensure
+ Object.send(:remove_const, :CS_CONST306)
end
it "returns a toplevel constant when the receiver is a Module" do
Object::CS_CONST308 = :const308
ConstantSpecs.const_get(:CS_CONST308).should == :const308
ConstantSpecs::ModuleA.const_get(:CS_CONST308).should == :const308
+ ensure
+ Object.send(:remove_const, :CS_CONST308)
end
it "returns the updated value of a constant" do
@@ -246,6 +266,8 @@ describe "Module#const_get" do
ConstantSpecs::ClassB::CS_CONST309 = :const309_2
}.should complain(/already initialized constant/)
ConstantSpecs::ClassB.const_get(:CS_CONST309).should == :const309_2
+ ensure
+ ConstantSpecs::ClassB.send(:remove_const, :CS_CONST309)
end
end
end
diff --git a/spec/ruby/core/module/const_set_spec.rb b/spec/ruby/core/module/const_set_spec.rb
index 5bdfd7b68f..823768b882 100644
--- a/spec/ruby/core/module/const_set_spec.rb
+++ b/spec/ruby/core/module/const_set_spec.rb
@@ -8,16 +8,23 @@ describe "Module#const_set" do
ConstantSpecs.const_set "CS_CONST402", :const402
ConstantSpecs.const_get(:CS_CONST402).should == :const402
+ ensure
+ ConstantSpecs.send(:remove_const, :CS_CONST401)
+ ConstantSpecs.send(:remove_const, :CS_CONST402)
end
it "returns the value set" do
ConstantSpecs.const_set(:CS_CONST403, :const403).should == :const403
+ ensure
+ ConstantSpecs.send(:remove_const, :CS_CONST403)
end
it "sets the name of an anonymous module" do
m = Module.new
ConstantSpecs.const_set(:CS_CONST1000, m)
m.name.should == "ConstantSpecs::CS_CONST1000"
+ ensure
+ ConstantSpecs.send(:remove_const, :CS_CONST1000)
end
it "sets the name of a module scoped by an anonymous module" do
@@ -38,6 +45,8 @@ describe "Module#const_set" do
b.name.should == "ModuleSpecs_CS3::B"
c.name.should == "ModuleSpecs_CS3::B::C"
d.name.should == "ModuleSpecs_CS3::D"
+ ensure
+ Object.send(:remove_const, :ModuleSpecs_CS3)
end
it "raises a NameError if the name does not start with a capital letter" do
@@ -55,6 +64,8 @@ describe "Module#const_set" do
ConstantSpecs.const_set("CS_CONST404", :const404).should == :const404
-> { ConstantSpecs.const_set "Name=", 1 }.should raise_error(NameError)
-> { ConstantSpecs.const_set "Name?", 1 }.should raise_error(NameError)
+ ensure
+ ConstantSpecs.send(:remove_const, :CS_CONST404)
end
it "calls #to_str to convert the given name to a String" do
@@ -62,6 +73,8 @@ describe "Module#const_set" do
name.should_receive(:to_str).and_return("CS_CONST405")
ConstantSpecs.const_set(name, :const405).should == :const405
ConstantSpecs::CS_CONST405.should == :const405
+ ensure
+ ConstantSpecs.send(:remove_const, :CS_CONST405)
end
it "raises a TypeError if conversion to a String by calling #to_str fails" do
diff --git a/spec/ruby/core/module/const_source_location_spec.rb b/spec/ruby/core/module/const_source_location_spec.rb
index c194c9113f..96649ea10b 100644
--- a/spec/ruby/core/module/const_source_location_spec.rb
+++ b/spec/ruby/core/module/const_source_location_spec.rb
@@ -19,40 +19,60 @@ describe "Module#const_source_location" do
ConstantSpecs::ContainerA::ChildA::CSL_CONST301 = :const301_5
ConstantSpecs::ContainerA::ChildA.const_source_location(:CSL_CONST301).should == [__FILE__, __LINE__ - 1]
+ ensure
+ ConstantSpecs::ClassA.send(:remove_const, :CSL_CONST301)
+ ConstantSpecs::ModuleA.send(:remove_const, :CSL_CONST301)
+ ConstantSpecs::ParentA.send(:remove_const, :CSL_CONST301)
+ ConstantSpecs::ContainerA::ChildA.send(:remove_const, :CSL_CONST301)
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]
+ ensure
+ ConstantSpecs::ParentB.send(:remove_const, :CSL_CONST302)
+ ConstantSpecs::ModuleF.send(:remove_const, :CSL_CONST302)
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]
+ ensure
+ ConstantSpecs::ModuleE.send(:remove_const, :CSL_CONST303)
+ ConstantSpecs::ParentB.send(:remove_const, :CSL_CONST303)
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]
+ ensure
+ ConstantSpecs::ModuleA.send(:remove_const, :CSL_CONST304)
+ ConstantSpecs::ModuleE.send(:remove_const, :CSL_CONST304)
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]
+ ensure
+ ConstantSpecs::ModuleA.send(:remove_const, :CSL_CONST305)
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]
+ ensure
+ Object.send(:remove_const, :CSL_CONST306)
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]
+ ensure
+ Object.send(:remove_const, :CSL_CONST308)
end
it "returns path to the updated value of a constant" do
@@ -63,6 +83,8 @@ describe "Module#const_source_location" do
ConstantSpecs::ClassB::CSL_CONST309 = :const309_2
}.should complain(/already initialized constant/)
ConstantSpecs::ClassB.const_source_location(:CSL_CONST309).should == [__FILE__, __LINE__ - 2]
+ ensure
+ ConstantSpecs::ClassB.send(:remove_const, :CSL_CONST309)
end
end
@@ -207,7 +229,7 @@ describe "Module#const_source_location" do
end
it "does search private constants path" do
- ConstantSpecs.const_source_location(:CS_PRIVATE).should == [@constants_fixture_path, ConstantSpecs::CS_PRIVATE_LINE]
+ ConstantSpecs.const_source_location(:CS_PRIVATE).should == [@constants_fixture_path, ConstantSpecs::CS_PRIVATE_LINE]
end
it "works for eval with a given line" do
@@ -223,6 +245,14 @@ describe "Module#const_source_location" do
@line = __LINE__ - 1
end
+ before :each do
+ @loaded_features = $".dup
+ end
+
+ after :each do
+ $".replace @loaded_features
+ end
+
it 'returns the autoload location while not resolved' do
ConstantSpecs.const_source_location('CSL_CONST1').should == [__FILE__, @line]
end
@@ -243,6 +273,8 @@ describe "Module#const_source_location" do
ConstantSpecs.const_source_location(:ConstSource).should == autoload_location
ConstantSpecs::ConstSource::LOCATION.should == ConstantSpecs.const_source_location(:ConstSource)
ConstantSpecs::BEFORE_DEFINE_LOCATION.should == autoload_location
+ ConstantSpecs.send :remove_const, :ConstSource
+ ConstantSpecs.send :remove_const, :BEFORE_DEFINE_LOCATION
end
end
end
diff --git a/spec/ruby/core/module/define_method_spec.rb b/spec/ruby/core/module/define_method_spec.rb
index e04bb87ceb..c5dfc53764 100644
--- a/spec/ruby/core/module/define_method_spec.rb
+++ b/spec/ruby/core/module/define_method_spec.rb
@@ -476,6 +476,9 @@ describe "Module#define_method" do
ChildClass = Class.new(ParentClass) { define_method(:foo) { :baz } }
ParentClass.send :define_method, :foo, ChildClass.instance_method(:foo)
}.should raise_error(TypeError, /bind argument must be a subclass of ChildClass/)
+ ensure
+ Object.send(:remove_const, :ParentClass)
+ Object.send(:remove_const, :ChildClass)
end
it "raises a TypeError when an UnboundMethod from one class is defined on an unrelated class" do
diff --git a/spec/ruby/core/module/deprecate_constant_spec.rb b/spec/ruby/core/module/deprecate_constant_spec.rb
index aabef934c4..ec0de6782f 100644
--- a/spec/ruby/core/module/deprecate_constant_spec.rb
+++ b/spec/ruby/core/module/deprecate_constant_spec.rb
@@ -44,6 +44,15 @@ describe "Module#deprecate_constant" do
end
end
+ ruby_bug '#20900', ''...'3.4' do
+ describe "when removing the deprecated module" do
+ it "warns with a message" do
+ @module.deprecate_constant :PUBLIC1
+ -> { @module.module_eval {remove_const :PUBLIC1} }.should complain(/warning: constant .+::PUBLIC1 is deprecated/)
+ end
+ end
+ end
+
it "accepts multiple symbols and strings as constant names" do
@module.deprecate_constant "PUBLIC1", :PUBLIC2
diff --git a/spec/ruby/core/module/fixtures/classes.rb b/spec/ruby/core/module/fixtures/classes.rb
index a434e7b0b8..964f64c593 100644
--- a/spec/ruby/core/module/fixtures/classes.rb
+++ b/spec/ruby/core/module/fixtures/classes.rb
@@ -1,6 +1,6 @@
module ModuleSpecs
def self.without_test_modules(modules)
- ignore = %w[MSpecRSpecAdapter PP::ObjectMixin ModuleSpecs::IncludedInObject MainSpecs::Module ConstantSpecs::ModuleA]
+ ignore = %w[MSpecRSpecAdapter PP::ObjectMixin MainSpecs::Module ConstantSpecs::ModuleA]
modules.reject { |k| ignore.include?(k.name) }
end
diff --git a/spec/ruby/core/module/fixtures/const_added.rb b/spec/ruby/core/module/fixtures/const_added.rb
new file mode 100644
index 0000000000..0f5baad65d
--- /dev/null
+++ b/spec/ruby/core/module/fixtures/const_added.rb
@@ -0,0 +1,4 @@
+module ModuleSpecs
+ module ConstAddedSpecs
+ end
+end
diff --git a/spec/ruby/core/module/fixtures/name.rb b/spec/ruby/core/module/fixtures/name.rb
index fb9e66c309..25c74d3944 100644
--- a/spec/ruby/core/module/fixtures/name.rb
+++ b/spec/ruby/core/module/fixtures/name.rb
@@ -7,4 +7,7 @@ module ModuleSpecs
Cß.name
end
end
+
+ module NameSpecs
+ end
end
diff --git a/spec/ruby/core/module/fixtures/set_temporary_name.rb b/spec/ruby/core/module/fixtures/set_temporary_name.rb
new file mode 100644
index 0000000000..901b3b94d1
--- /dev/null
+++ b/spec/ruby/core/module/fixtures/set_temporary_name.rb
@@ -0,0 +1,4 @@
+module ModuleSpecs
+ module SetTemporaryNameSpec
+ end
+end
diff --git a/spec/ruby/core/module/include_spec.rb b/spec/ruby/core/module/include_spec.rb
index 78f6b41031..210918b2e7 100644
--- a/spec/ruby/core/module/include_spec.rb
+++ b/spec/ruby/core/module/include_spec.rb
@@ -44,35 +44,23 @@ describe "Module#include" do
end
it "does not raise a TypeError when the argument is an instance of a subclass of Module" do
- -> { ModuleSpecs::SubclassSpec.include(ModuleSpecs::Subclass.new) }.should_not raise_error(TypeError)
- end
-
- ruby_version_is ""..."3.2" do
- it "raises ArgumentError when the argument is a refinement" do
- refinement = nil
-
- Module.new do
- refine String do
- refinement = self
- end
- end
-
- -> { ModuleSpecs::Basic.include(refinement) }.should raise_error(ArgumentError, "refinement module is not allowed")
+ class ModuleSpecs::SubclassSpec::AClass
end
+ -> { ModuleSpecs::SubclassSpec::AClass.include(ModuleSpecs::Subclass.new) }.should_not raise_error(TypeError)
+ ensure
+ ModuleSpecs::SubclassSpec.send(:remove_const, :AClass)
end
- ruby_version_is "3.2" do
- it "raises a TypeError when the argument is a refinement" do
- refinement = nil
+ it "raises a TypeError when the argument is a refinement" do
+ refinement = nil
- Module.new do
- refine String do
- refinement = self
- end
+ Module.new do
+ refine String do
+ refinement = self
end
-
- -> { ModuleSpecs::Basic.include(refinement) }.should raise_error(TypeError, "Cannot include refinement")
end
+
+ -> { ModuleSpecs::Basic.include(refinement) }.should raise_error(TypeError, "Cannot include refinement")
end
it "imports constants to modules and classes" do
@@ -427,6 +415,8 @@ describe "Module#include" do
M.const_set(:FOO, 'm')
B.foo.should == 'm'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstUpdated)
end
it "updates the constant when a module included after a call is later updated" do
@@ -453,6 +443,8 @@ describe "Module#include" do
M.const_set(:FOO, 'm')
B.foo.should == 'm'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstLaterUpdated)
end
it "updates the constant when a module included in another module after a call is later updated" do
@@ -479,6 +471,8 @@ describe "Module#include" do
M.const_set(:FOO, 'm')
B.foo.should == 'm'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstModuleLaterUpdated)
end
it "updates the constant when a nested included module is updated" do
@@ -507,6 +501,8 @@ describe "Module#include" do
N.const_set(:FOO, 'n')
B.foo.should == 'n'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstUpdatedNestedIncludeUpdated)
end
it "updates the constant when a new module is included" do
@@ -531,6 +527,8 @@ describe "Module#include" do
B.include(M)
B.foo.should == 'm'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstUpdatedNewInclude)
end
it "updates the constant when a new module with nested module is included" do
@@ -559,6 +557,8 @@ describe "Module#include" do
B.include M
B.foo.should == 'n'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstUpdatedNestedIncluded)
end
it "overrides a previous super method call" do
@@ -581,6 +581,29 @@ describe "Module#include" do
c2.include(m)
c2.new.foo.should == [:c2, :m1]
end
+
+ it "update a module when a nested module is updated and includes a module on its own" do
+ m1 = Module.new
+ m2 = Module.new do
+ def m2; [:m2]; end
+ end
+ m3 = Module.new do
+ def m3; [:m3]; end
+ end
+ m4 = Module.new do
+ def m4; [:m4]; end
+ end
+ c = Class.new
+
+ c.include(m1)
+ m1.include(m2)
+ m2.include(m3)
+ m3.include(m4)
+
+ c.new.m2.should == [:m2]
+ c.new.m3.should == [:m3]
+ c.new.m4.should == [:m4]
+ end
end
describe "Module#include?" do
diff --git a/spec/ruby/core/module/instance_method_spec.rb b/spec/ruby/core/module/instance_method_spec.rb
index 8d006e647e..182cdf5c54 100644
--- a/spec/ruby/core/module/instance_method_spec.rb
+++ b/spec/ruby/core/module/instance_method_spec.rb
@@ -48,11 +48,6 @@ describe "Module#instance_method" do
@mod_um.inspect.should =~ /\bbar\b/
@mod_um.inspect.should =~ /\bModuleSpecs::InstanceMethMod\b/
-
- ruby_version_is ""..."3.2" do
- @child_um.inspect.should =~ /\bModuleSpecs::InstanceMethChild\b/
- @mod_um.inspect.should =~ /\bModuleSpecs::InstanceMethChild\b/
- end
end
it "raises a TypeError if the given name is not a String/Symbol" do
diff --git a/spec/ruby/core/module/module_function_spec.rb b/spec/ruby/core/module/module_function_spec.rb
index 1c3ec5471b..51f647142e 100644
--- a/spec/ruby/core/module/module_function_spec.rb
+++ b/spec/ruby/core/module/module_function_spec.rb
@@ -38,22 +38,11 @@ describe "Module#module_function with specific method names" do
m.respond_to?(:test3).should == false
end
- 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
-
- 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
+ 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
@@ -216,19 +205,9 @@ describe "Module#module_function as a toggle (no arguments) in a Module body" do
m.respond_to?(:test2).should == true
end
- ruby_version_is ""..."3.1" do
- it "returns self" do
- Module.new do
- module_function.should equal(self)
- end
- end
- end
-
- ruby_version_is "3.1" do
- it "returns nil" do
- Module.new do
- module_function.should equal(nil)
- end
+ it "returns nil" do
+ Module.new do
+ module_function.should equal(nil)
end
end
diff --git a/spec/ruby/core/module/name_spec.rb b/spec/ruby/core/module/name_spec.rb
index 0d1f4e24d5..d3318e1645 100644
--- a/spec/ruby/core/module/name_spec.rb
+++ b/spec/ruby/core/module/name_spec.rb
@@ -30,6 +30,8 @@ describe "Module#name" do
m::N.name.should =~ /\A#<Module:0x\h+>::N\z/
ModuleSpecs::Anonymous::WasAnnon = m::N
m::N.name.should == "ModuleSpecs::Anonymous::WasAnnon"
+ ensure
+ ModuleSpecs::Anonymous.send(:remove_const, :WasAnnon)
end
it "may be the repeated in different module objects" do
@@ -76,12 +78,16 @@ describe "Module#name" do
m = Module.new
ModuleSpecs::Anonymous::A = m
m.name.should == "ModuleSpecs::Anonymous::A"
+ ensure
+ ModuleSpecs::Anonymous.send(:remove_const, :A)
end
it "is set when assigning to a constant (constant path does not match outer module name)" do
m = Module.new
ModuleSpecs::Anonymous::SameChild::A = m
m.name.should == "ModuleSpecs::Anonymous::Child::A"
+ ensure
+ ModuleSpecs::Anonymous::SameChild.send(:remove_const, :A)
end
it "is not modified when assigning to a new constant after it has been accessed" do
@@ -90,6 +96,9 @@ describe "Module#name" do
m.name.should == "ModuleSpecs::Anonymous::B"
ModuleSpecs::Anonymous::C = m
m.name.should == "ModuleSpecs::Anonymous::B"
+ ensure
+ ModuleSpecs::Anonymous.send(:remove_const, :B)
+ ModuleSpecs::Anonymous.send(:remove_const, :C)
end
it "is not modified when assigned to a different anonymous module" do
@@ -125,6 +134,8 @@ describe "Module#name" do
m::N = Module.new
ModuleSpecs::Anonymous::E = m
m::N.name.should == "ModuleSpecs::Anonymous::E::N"
+ ensure
+ ModuleSpecs::Anonymous.send(:remove_const, :E)
end
# https://bugs.ruby-lang.org/issues/19681
@@ -138,6 +149,48 @@ describe "Module#name" do
"ModuleSpecs::Anonymous::StoredInMultiplePlaces::O"
]
valid_names.should include(m::N.name) # You get one of the two, but you don't know which one.
+ ensure
+ ModuleSpecs::Anonymous.send(:remove_const, :StoredInMultiplePlaces)
+ end
+
+ it "is set in #const_added callback when a module defined in the top-level scope" do
+ ruby_exe(<<~RUBY, args: "2>&1").chomp.should == "TEST1\nTEST2"
+ class Module
+ def const_added(name)
+ puts const_get(name).name
+ end
+ end
+
+ # module with name
+ module TEST1
+ end
+
+ # anonymous module
+ TEST2 = Module.new
+ RUBY
+ end
+
+ it "is set in #const_added callback for a nested module when an outer module defined in the top-level scope" do
+ ScratchPad.record []
+
+ ModuleSpecs::NameSpecs::NamedModule = Module.new do
+ def self.const_added(name)
+ ScratchPad << const_get(name).name
+ end
+
+ module self::A
+ def self.const_added(name)
+ ScratchPad << const_get(name).name
+ end
+
+ module self::B
+ end
+ end
+ end
+
+ ScratchPad.recorded.should.one?(/#<Module.+>::A$/)
+ ScratchPad.recorded.should.one?(/#<Module.+>::A::B$/)
+ ModuleSpecs::NameSpecs.send :remove_const, :NamedModule
end
it "returns a frozen String" do
diff --git a/spec/ruby/core/module/new_spec.rb b/spec/ruby/core/module/new_spec.rb
index da7f3b8720..ec521360bd 100644
--- a/spec/ruby/core/module/new_spec.rb
+++ b/spec/ruby/core/module/new_spec.rb
@@ -6,6 +6,10 @@ describe "Module.new" do
Module.new.is_a?(Module).should == true
end
+ it "creates a module without a name" do
+ Module.new.name.should be_nil
+ end
+
it "creates a new Module and passes it to the provided block" do
test_mod = nil
m = Module.new do |mod|
diff --git a/spec/ruby/core/module/prepend_spec.rb b/spec/ruby/core/module/prepend_spec.rb
index b40d12f0de..71e82c513e 100644
--- a/spec/ruby/core/module/prepend_spec.rb
+++ b/spec/ruby/core/module/prepend_spec.rb
@@ -261,6 +261,8 @@ describe "Module#prepend" do
B.prepend M
B.foo.should == 'm'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstUpdatePrepended)
end
it "updates the constant when a prepended module is updated" do
@@ -281,6 +283,8 @@ describe "Module#prepend" do
M.const_set(:FOO, 'm')
B.foo.should == 'm'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstPrependedUpdated)
end
it "updates the constant when there is a base included constant and the prepended module overrides it" do
@@ -302,6 +306,8 @@ describe "Module#prepend" do
A.prepend M
A.foo.should == 'm'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstIncludedPrependedOverride)
end
it "updates the constant when there is a base included constant and the prepended module is later updated" do
@@ -325,6 +331,8 @@ describe "Module#prepend" do
M.const_set(:FOO, 'm')
A.foo.should == 'm'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstIncludedPrependedLaterUpdated)
end
it "updates the constant when a module prepended after a constant is later updated" do
@@ -348,6 +356,8 @@ describe "Module#prepend" do
M.const_set(:FOO, 'm')
B.foo.should == 'm'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstUpdatedPrependedAfterLaterUpdated)
end
it "updates the constant when a module is prepended after another and the constant is defined later on that module" do
@@ -372,6 +382,8 @@ describe "Module#prepend" do
N.const_set(:FOO, 'n')
A.foo.should == 'n'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstUpdatedPrependedAfterConstDefined)
end
it "updates the constant when a module is included in a prepended module and the constant is defined later" do
@@ -399,6 +411,8 @@ describe "Module#prepend" do
N.const_set(:FOO, 'n')
A.foo.should == 'n'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstUpdatedIncludedInPrependedConstDefinedLater)
end
it "updates the constant when a new module with an included module is prepended" do
@@ -425,6 +439,8 @@ describe "Module#prepend" do
B.prepend M
B.foo.should == 'n'
end
+ ensure
+ ModuleSpecs.send(:remove_const, :ConstUpdatedNewModuleIncludedPrepended)
end
it "raises a TypeError when the argument is not a Module" do
@@ -432,35 +448,23 @@ describe "Module#prepend" do
end
it "does not raise a TypeError when the argument is an instance of a subclass of Module" do
- -> { ModuleSpecs::SubclassSpec.prepend(ModuleSpecs::Subclass.new) }.should_not raise_error(TypeError)
- end
-
- ruby_version_is ""..."3.2" do
- it "raises ArgumentError when the argument is a refinement" do
- refinement = nil
-
- Module.new do
- refine String do
- refinement = self
- end
- end
-
- -> { ModuleSpecs::Basic.prepend(refinement) }.should raise_error(ArgumentError, "refinement module is not allowed")
+ class ModuleSpecs::SubclassSpec::AClass
end
+ -> { ModuleSpecs::SubclassSpec::AClass.prepend(ModuleSpecs::Subclass.new) }.should_not raise_error(TypeError)
+ ensure
+ ModuleSpecs::SubclassSpec.send(:remove_const, :AClass)
end
- ruby_version_is "3.2" do
- it "raises a TypeError when the argument is a refinement" do
- refinement = nil
+ it "raises a TypeError when the argument is a refinement" do
+ refinement = nil
- Module.new do
- refine String do
- refinement = self
- end
+ Module.new do
+ refine String do
+ refinement = self
end
-
- -> { ModuleSpecs::Basic.prepend(refinement) }.should raise_error(TypeError, "Cannot prepend refinement")
end
+
+ -> { ModuleSpecs::Basic.prepend(refinement) }.should raise_error(TypeError, "Cannot prepend refinement")
end
it "imports constants" do
@@ -787,34 +791,17 @@ describe "Module#prepend" do
# https://bugs.ruby-lang.org/issues/17423
describe "when module already exists in ancestor chain" do
- ruby_version_is ""..."3.1" do
- it "does not modify the ancestor chain" do
- m = Module.new do; end
- a = Module.new do; end
- b = Class.new do; end
-
- b.include(a)
- a.prepend(m)
- b.ancestors.take(4).should == [b, m, a, Object]
-
- b.prepend(m)
- b.ancestors.take(4).should == [b, m, a, Object]
- end
- end
+ it "modifies the ancestor chain" do
+ m = Module.new do; end
+ a = Module.new do; end
+ b = Class.new do; end
- ruby_version_is "3.1" do
- it "modifies the ancestor chain" do
- m = Module.new do; end
- a = Module.new do; end
- b = Class.new do; end
+ b.include(a)
+ a.prepend(m)
+ b.ancestors.take(4).should == [b, m, a, Object]
- b.include(a)
- a.prepend(m)
- b.ancestors.take(4).should == [b, m, a, Object]
-
- b.prepend(m)
- b.ancestors.take(5).should == [m, b, m, a, Object]
- end
+ b.prepend(m)
+ b.ancestors.take(5).should == [m, b, m, a, Object]
end
end
diff --git a/spec/ruby/core/module/private_spec.rb b/spec/ruby/core/module/private_spec.rb
index ead806637c..9e1a297eea 100644
--- a/spec/ruby/core/module/private_spec.rb
+++ b/spec/ruby/core/module/private_spec.rb
@@ -38,25 +38,13 @@ describe "Module#private" do
:module_specs_public_method_on_object_for_kernel_private)
end
- 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
+ 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
diff --git a/spec/ruby/core/module/protected_spec.rb b/spec/ruby/core/module/protected_spec.rb
index 058d49d751..9e37223e18 100644
--- a/spec/ruby/core/module/protected_spec.rb
+++ b/spec/ruby/core/module/protected_spec.rb
@@ -39,25 +39,13 @@ describe "Module#protected" do
:module_specs_public_method_on_object_for_kernel_protected)
end
- 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
+ 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
diff --git a/spec/ruby/core/module/public_spec.rb b/spec/ruby/core/module/public_spec.rb
index e3b183f228..ce31eb5d0e 100644
--- a/spec/ruby/core/module/public_spec.rb
+++ b/spec/ruby/core/module/public_spec.rb
@@ -27,25 +27,13 @@ describe "Module#public" do
:module_specs_private_method_on_object_for_kernel_public)
end
- 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
+ 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
diff --git a/spec/ruby/core/module/refine_spec.rb b/spec/ruby/core/module/refine_spec.rb
index 11085c325b..d219b98825 100644
--- a/spec/ruby/core/module/refine_spec.rb
+++ b/spec/ruby/core/module/refine_spec.rb
@@ -243,36 +243,10 @@ describe "Module#refine" do
result.should == "foo from singleton class"
end
- ruby_version_is ""..."3.2" do
- it "looks in the included modules for builtin methods" do
- result = ruby_exe(<<-RUBY)
- a = Module.new do
- def /(other) quo(other) end
- end
-
- refinement = Module.new do
- refine Integer do
- include a
- end
- end
-
- result = nil
- Module.new do
- using refinement
- result = 1 / 2
- end
-
- print result.class
- RUBY
-
- result.should == 'Rational'
- end
- end
-
it "looks in later included modules of the refined module first" do
a = Module.new do
def foo
- "foo from A"
+ "foo from A"
end
end
@@ -300,67 +274,6 @@ describe "Module#refine" do
result.should == "foo from IncludeMeLater"
end
- 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
-
- 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
-
- 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
@@ -606,30 +519,6 @@ describe "Module#refine" do
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
-
- refinement = Module.new do
- refine refined_class do
- include ModuleSpecs::IncludedModule
-
- def foo
- super
- end
- 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 refined class" do
refined_class = ModuleSpecs.build_refined_class
@@ -650,59 +539,6 @@ describe "Module#refine" do
result.should == "foo"
end
- 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
- [: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, :C]
- end
-
- 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.
@@ -763,179 +599,6 @@ describe "Module#refine" do
}.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
it 'and alias aliases a method within a refinement module, but not outside it' do
diff --git a/spec/ruby/core/module/refinements_spec.rb b/spec/ruby/core/module/refinements_spec.rb
index 5648fcbd6f..05658a8b0e 100644
--- a/spec/ruby/core/module/refinements_spec.rb
+++ b/spec/ruby/core/module/refinements_spec.rb
@@ -1,45 +1,43 @@
require_relative '../../spec_helper'
describe "Module#refinements" do
- ruby_version_is "3.2" do
- it "returns refinements defined in a module" do
- ScratchPad.record []
-
- m = Module.new do
- refine String do
- ScratchPad << self
- end
-
- refine Array do
- ScratchPad << self
- end
+ it "returns refinements defined in a module" do
+ ScratchPad.record []
+
+ m = Module.new do
+ refine String do
+ ScratchPad << self
end
- m.refinements.sort_by(&:object_id).should == ScratchPad.recorded.sort_by(&:object_id)
+ refine Array do
+ ScratchPad << self
+ end
end
- it "does not return refinements defined in the included module" do
- ScratchPad.record []
+ m.refinements.sort_by(&:object_id).should == ScratchPad.recorded.sort_by(&:object_id)
+ end
- m1 = Module.new do
- refine Integer do
- nil
- end
+ it "does not return refinements defined in the included module" do
+ ScratchPad.record []
+
+ m1 = Module.new do
+ refine Integer do
+ nil
end
+ end
- m2 = Module.new do
- include m1
+ m2 = Module.new do
+ include m1
- refine String do
- ScratchPad << self
- end
+ refine String do
+ ScratchPad << self
end
-
- m2.refinements.should == ScratchPad.recorded
end
- it "returns an empty array if no refinements defined in a module" do
- Module.new.refinements.should == []
- end
+ m2.refinements.should == ScratchPad.recorded
+ end
+
+ it "returns an empty array if no refinements defined in a module" do
+ Module.new.refinements.should == []
end
end
diff --git a/spec/ruby/core/module/remove_const_spec.rb b/spec/ruby/core/module/remove_const_spec.rb
index 0ac23f05a5..35a9d65105 100644
--- a/spec/ruby/core/module/remove_const_spec.rb
+++ b/spec/ruby/core/module/remove_const_spec.rb
@@ -101,5 +101,7 @@ describe "Module#remove_const" do
A.send(:remove_const,:FOO)
A.foo.should == 'm'
end
+ ensure
+ ConstantSpecs.send(:remove_const, :RemovedConstantUpdate)
end
end
diff --git a/spec/ruby/core/module/ruby2_keywords_spec.rb b/spec/ruby/core/module/ruby2_keywords_spec.rb
index aca419f522..652f9f7083 100644
--- a/spec/ruby/core/module/ruby2_keywords_spec.rb
+++ b/spec/ruby/core/module/ruby2_keywords_spec.rb
@@ -76,122 +76,60 @@ describe "Module#ruby2_keywords" do
Hash.ruby2_keywords_hash?(marked).should == true
end
- ruby_version_is "3.2" do
- it "makes a copy and unmark the Hash when calling a method taking (*args)" do
- obj = Object.new
- obj.singleton_class.class_exec do
- def splat(*args)
- args.last
- end
-
- def splat1(arg, *args)
- args.last
- end
+ it "makes a copy and unmark the Hash when calling a method taking (*args)" do
+ obj = Object.new
+ obj.singleton_class.class_exec do
+ def splat(*args)
+ args.last
+ end
- def proc_call(*args)
- -> *a { a.last }.call(*args)
- end
+ def splat1(arg, *args)
+ args.last
end
- h = { a: 1 }
- args = mark(**h)
- marked = args.last
- Hash.ruby2_keywords_hash?(marked).should == true
-
- after_usage = obj.splat(*args)
- after_usage.should == h
- after_usage.should_not.equal?(h)
- after_usage.should_not.equal?(marked)
- Hash.ruby2_keywords_hash?(after_usage).should == false
- Hash.ruby2_keywords_hash?(marked).should == true
-
- args = mark(1, **h)
- marked = args.last
- after_usage = obj.splat1(*args)
- after_usage.should == h
- after_usage.should_not.equal?(h)
- after_usage.should_not.equal?(marked)
- Hash.ruby2_keywords_hash?(after_usage).should == false
- Hash.ruby2_keywords_hash?(marked).should == true
-
- args = mark(**h)
- marked = args.last
- after_usage = obj.proc_call(*args)
- after_usage.should == h
- after_usage.should_not.equal?(h)
- after_usage.should_not.equal?(marked)
- Hash.ruby2_keywords_hash?(after_usage).should == false
- Hash.ruby2_keywords_hash?(marked).should == true
-
- args = mark(**h)
- marked = args.last
- after_usage = obj.send(:splat, *args)
- after_usage.should == h
- after_usage.should_not.equal?(h)
- after_usage.should_not.equal?(marked)
- Hash.ruby2_keywords_hash?(after_usage).should == false
- Hash.ruby2_keywords_hash?(marked).should == true
+ def proc_call(*args)
+ -> *a { a.last }.call(*args)
+ end
end
- end
- ruby_version_is ""..."3.2" do
- # https://bugs.ruby-lang.org/issues/18625
- it "does NOT copy the Hash when calling a method taking (*args)" do
- obj = Object.new
- obj.singleton_class.class_exec do
- def splat(*args)
- args.last
- end
+ h = { a: 1 }
+ args = mark(**h)
+ marked = args.last
+ Hash.ruby2_keywords_hash?(marked).should == true
- def splat1(arg, *args)
- args.last
- end
+ after_usage = obj.splat(*args)
+ after_usage.should == h
+ after_usage.should_not.equal?(h)
+ after_usage.should_not.equal?(marked)
+ Hash.ruby2_keywords_hash?(after_usage).should == false
+ Hash.ruby2_keywords_hash?(marked).should == true
- def proc_call(*args)
- -> *a { a.last }.call(*args)
- end
- end
+ args = mark(1, **h)
+ marked = args.last
+ after_usage = obj.splat1(*args)
+ after_usage.should == h
+ after_usage.should_not.equal?(h)
+ after_usage.should_not.equal?(marked)
+ Hash.ruby2_keywords_hash?(after_usage).should == false
+ Hash.ruby2_keywords_hash?(marked).should == true
- h = { a: 1 }
- args = mark(**h)
- marked = args.last
- Hash.ruby2_keywords_hash?(marked).should == true
-
- after_usage = obj.splat(*args)
- after_usage.should == h
- after_usage.should_not.equal?(h)
- after_usage.should.equal?(marked) # https://bugs.ruby-lang.org/issues/18625
- Hash.ruby2_keywords_hash?(after_usage).should == true # https://bugs.ruby-lang.org/issues/18625
- Hash.ruby2_keywords_hash?(marked).should == true
-
- args = mark(1, **h)
- marked = args.last
- after_usage = obj.splat1(*args)
- after_usage.should == h
- after_usage.should_not.equal?(h)
- after_usage.should.equal?(marked) # https://bugs.ruby-lang.org/issues/18625
- Hash.ruby2_keywords_hash?(after_usage).should == true # https://bugs.ruby-lang.org/issues/18625
- Hash.ruby2_keywords_hash?(marked).should == true
-
- args = mark(**h)
- marked = args.last
- after_usage = obj.proc_call(*args)
- after_usage.should == h
- after_usage.should_not.equal?(h)
- after_usage.should.equal?(marked) # https://bugs.ruby-lang.org/issues/18625
- Hash.ruby2_keywords_hash?(after_usage).should == true # https://bugs.ruby-lang.org/issues/18625
- Hash.ruby2_keywords_hash?(marked).should == true
-
- args = mark(**h)
- marked = args.last
- after_usage = obj.send(:splat, *args)
- after_usage.should == h
- after_usage.should_not.equal?(h)
- send_copies = RUBY_ENGINE == "ruby" # inconsistent with Proc#call above for CRuby
- after_usage.equal?(marked).should == !send_copies
- Hash.ruby2_keywords_hash?(after_usage).should == !send_copies
- Hash.ruby2_keywords_hash?(marked).should == true
- end
+ args = mark(**h)
+ marked = args.last
+ after_usage = obj.proc_call(*args)
+ after_usage.should == h
+ after_usage.should_not.equal?(h)
+ after_usage.should_not.equal?(marked)
+ Hash.ruby2_keywords_hash?(after_usage).should == false
+ Hash.ruby2_keywords_hash?(marked).should == true
+
+ args = mark(**h)
+ marked = args.last
+ after_usage = obj.send(:splat, *args)
+ after_usage.should == h
+ after_usage.should_not.equal?(h)
+ after_usage.should_not.equal?(marked)
+ Hash.ruby2_keywords_hash?(after_usage).should == false
+ Hash.ruby2_keywords_hash?(marked).should == true
end
it "applies to the underlying method and applies across aliasing" do
@@ -275,7 +213,7 @@ describe "Module#ruby2_keywords" do
it "prints warning when a method accepts keywords" do
obj = Object.new
- def obj.foo(a:, b:) end
+ def obj.foo(*a, b:) end
-> {
obj.singleton_class.class_exec do
@@ -286,7 +224,7 @@ describe "Module#ruby2_keywords" do
it "prints warning when a method accepts keyword splat" do
obj = Object.new
- def obj.foo(**a) end
+ def obj.foo(*a, **b) end
-> {
obj.singleton_class.class_exec do
@@ -294,4 +232,17 @@ describe "Module#ruby2_keywords" do
end
}.should complain(/Skipping set of ruby2_keywords flag for/)
end
+
+ ruby_version_is "4.0" do
+ it "prints warning when a method accepts post arguments" 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
+ end
end
diff --git a/spec/ruby/core/module/set_temporary_name_spec.rb b/spec/ruby/core/module/set_temporary_name_spec.rb
index f5886a3398..46605ed675 100644
--- a/spec/ruby/core/module/set_temporary_name_spec.rb
+++ b/spec/ruby/core/module/set_temporary_name_spec.rb
@@ -1,4 +1,5 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/set_temporary_name'
ruby_version_is "3.3" do
describe "Module#set_temporary_name" do
@@ -13,13 +14,34 @@ ruby_version_is "3.3" do
m.name.should be_nil
end
+ it "returns self" do
+ m = Module.new
+ m.set_temporary_name("fake_name").should.equal? m
+ end
+
it "can assign a temporary name which is not a valid constant path" do
m = Module.new
- m.set_temporary_name("a::B")
- m.name.should == "a::B"
+
+ m.set_temporary_name("name")
+ m.name.should == "name"
m.set_temporary_name("Template['foo.rb']")
m.name.should == "Template['foo.rb']"
+
+ m.set_temporary_name("a::B")
+ m.name.should == "a::B"
+
+ m.set_temporary_name("A::b")
+ m.name.should == "A::b"
+
+ m.set_temporary_name("A::B::")
+ m.name.should == "A::B::"
+
+ m.set_temporary_name("A::::B")
+ m.name.should == "A::::B"
+
+ m.set_temporary_name("A=")
+ m.name.should == "A="
end
it "can't assign empty string as name" do
@@ -43,7 +65,7 @@ ruby_version_is "3.3" do
-> { Object.set_temporary_name("fake_name") }.should raise_error(RuntimeError, "can't change permanent name")
end
- it "can assign a temporary name to a nested module" do
+ it "can assign a temporary name to a module nested into an anonymous module" do
m = Module.new
module m::N; end
m::N.name.should =~ /\A#<Module:0x\h+>::N\z/
@@ -55,6 +77,18 @@ ruby_version_is "3.3" do
m::N.name.should be_nil
end
+ it "discards a temporary name when an outer anonymous module gets a permanent name" do
+ m = Module.new
+ module m::N; end
+
+ m::N.set_temporary_name("fake_name")
+ m::N.name.should == "fake_name"
+
+ ModuleSpecs::SetTemporaryNameSpec::M = m
+ m::N.name.should == "ModuleSpecs::SetTemporaryNameSpec::M::N"
+ ModuleSpecs::SetTemporaryNameSpec.send :remove_const, :M
+ end
+
it "can update the name when assigned to a constant" do
m = Module.new
m::N = Module.new
@@ -64,5 +98,50 @@ ruby_version_is "3.3" do
m::M = m::N
m::M.name.should =~ /\A#<Module:0x\h+>::M\z/m
end
+
+ it "can reassign a temporary name repeatedly" do
+ m = Module.new
+
+ m.set_temporary_name("fake_name")
+ m.name.should == "fake_name"
+
+ m.set_temporary_name("fake_name_2")
+ m.name.should == "fake_name_2"
+ end
+
+ ruby_bug "#21094", ""..."4.0" do
+ it "also updates a name of a nested module" do
+ m = Module.new
+ m::N = Module.new
+ m::N.name.should =~ /\A#<Module:0x\h+>::N\z/
+
+ m.set_temporary_name "m"
+ m::N.name.should == "m::N"
+
+ m.set_temporary_name nil
+ m::N.name.should == nil
+ end
+ end
+
+ it "keeps temporary name when assigned in an anonymous module" do
+ outer = Module.new
+ m = Module.new
+ m.set_temporary_name "m"
+ m.name.should == "m"
+ outer::M = m
+ m.name.should == "m"
+ m.inspect.should == "m"
+ end
+
+ it "keeps temporary name when assigned in an anonymous module and nested before" do
+ outer = Module.new
+ m = Module.new
+ outer::A = m
+ m.set_temporary_name "m"
+ m.name.should == "m"
+ outer::M = m
+ m.name.should == "m"
+ m.inspect.should == "m"
+ end
end
end
diff --git a/spec/ruby/core/module/to_s_spec.rb b/spec/ruby/core/module/to_s_spec.rb
index 6b1a615ef9..83c0ae0825 100644
--- a/spec/ruby/core/module/to_s_spec.rb
+++ b/spec/ruby/core/module/to_s_spec.rb
@@ -51,6 +51,8 @@ describe "Module#to_s" do
ModuleSpecs::RefinementInspect::R.name.should == 'ModuleSpecs::RefinementInspect::R'
ModuleSpecs::RefinementInspect::R.to_s.should == '#<refinement:String@ModuleSpecs::RefinementInspect>'
+ ensure
+ ModuleSpecs.send(:remove_const, :RefinementInspect)
end
it 'does not call #inspect or #to_s for singleton classes' do
diff --git a/spec/ruby/core/module/undefined_instance_methods_spec.rb b/spec/ruby/core/module/undefined_instance_methods_spec.rb
index 3be860d053..d33ee93fc1 100644
--- a/spec/ruby/core/module/undefined_instance_methods_spec.rb
+++ b/spec/ruby/core/module/undefined_instance_methods_spec.rb
@@ -2,25 +2,23 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Module#undefined_instance_methods" do
- ruby_version_is "3.2" do
- it "returns methods undefined in the class" do
- methods = ModuleSpecs::UndefinedInstanceMethods::Parent.undefined_instance_methods
- methods.should == [:undefed_method]
- end
+ it "returns methods undefined in the class" do
+ methods = ModuleSpecs::UndefinedInstanceMethods::Parent.undefined_instance_methods
+ methods.should == [:undefed_method]
+ end
- it "returns inherited methods undefined in the class" do
- methods = ModuleSpecs::UndefinedInstanceMethods::Child.undefined_instance_methods
- methods.should include(:parent_method, :another_parent_method)
- end
+ it "returns inherited methods undefined in the class" do
+ methods = ModuleSpecs::UndefinedInstanceMethods::Child.undefined_instance_methods
+ methods.should include(:parent_method, :another_parent_method)
+ end
- it "returns methods from an included module that are undefined in the class" do
- methods = ModuleSpecs::UndefinedInstanceMethods::Grandchild.undefined_instance_methods
- methods.should include(:super_included_method)
- end
+ it "returns methods from an included module that are undefined in the class" do
+ methods = ModuleSpecs::UndefinedInstanceMethods::Grandchild.undefined_instance_methods
+ methods.should include(:super_included_method)
+ end
- it "does not returns ancestors undefined methods" do
- methods = ModuleSpecs::UndefinedInstanceMethods::Grandchild.undefined_instance_methods
- methods.should_not include(:parent_method, :another_parent_method)
- end
+ it "does not returns ancestors undefined methods" do
+ methods = ModuleSpecs::UndefinedInstanceMethods::Grandchild.undefined_instance_methods
+ methods.should_not include(:parent_method, :another_parent_method)
end
end
diff --git a/spec/ruby/core/module/used_refinements_spec.rb b/spec/ruby/core/module/used_refinements_spec.rb
index c16cab0e3c..40dd4a444e 100644
--- a/spec/ruby/core/module/used_refinements_spec.rb
+++ b/spec/ruby/core/module/used_refinements_spec.rb
@@ -1,87 +1,85 @@
require_relative '../../spec_helper'
describe "Module.used_refinements" do
- ruby_version_is "3.2" do
- it "returns list of all refinements imported in the current scope" do
- refinement_int = nil
- refinement_str = nil
- ScratchPad.record []
-
- m1 = Module.new do
- refine Integer do
- refinement_int = self
- end
+ it "returns list of all refinements imported in the current scope" do
+ refinement_int = nil
+ refinement_str = nil
+ ScratchPad.record []
+
+ m1 = Module.new do
+ refine Integer do
+ refinement_int = self
end
+ end
- m2 = Module.new do
- refine String do
- refinement_str = self
- end
+ m2 = Module.new do
+ refine String do
+ refinement_str = self
end
+ end
- Module.new do
- using m1
- using m2
+ Module.new do
+ using m1
+ using m2
- Module.used_refinements.each { |r| ScratchPad << r }
- end
-
- ScratchPad.recorded.sort_by(&:object_id).should == [refinement_int, refinement_str].sort_by(&:object_id)
+ Module.used_refinements.each { |r| ScratchPad << r }
end
- it "returns empty array if does not have any refinements imported" do
- used_refinements = nil
+ ScratchPad.recorded.sort_by(&:object_id).should == [refinement_int, refinement_str].sort_by(&:object_id)
+ end
- Module.new do
- used_refinements = Module.used_refinements
- end
+ it "returns empty array if does not have any refinements imported" do
+ used_refinements = nil
- used_refinements.should == []
+ Module.new do
+ used_refinements = Module.used_refinements
end
- it "ignores refinements imported in a module that is included into the current one" do
- used_refinements = nil
+ used_refinements.should == []
+ end
- m1 = Module.new do
- refine Integer do
- nil
- end
- end
+ it "ignores refinements imported in a module that is included into the current one" do
+ used_refinements = nil
- m2 = Module.new do
- using m1
+ m1 = Module.new do
+ refine Integer do
+ nil
end
+ end
- Module.new do
- include m2
+ m2 = Module.new do
+ using m1
+ end
- used_refinements = Module.used_refinements
- end
+ Module.new do
+ include m2
- used_refinements.should == []
+ used_refinements = Module.used_refinements
end
- it "returns refinements even not defined directly in a module refinements are imported from" do
- used_refinements = nil
- ScratchPad.record []
+ used_refinements.should == []
+ end
- m1 = Module.new do
- refine Integer do
- ScratchPad << self
- end
- end
+ it "returns refinements even not defined directly in a module refinements are imported from" do
+ used_refinements = nil
+ ScratchPad.record []
- m2 = Module.new do
- include m1
+ m1 = Module.new do
+ refine Integer do
+ ScratchPad << self
end
+ end
- Module.new do
- using m2
+ m2 = Module.new do
+ include m1
+ end
- used_refinements = Module.used_refinements
- end
+ Module.new do
+ using m2
- used_refinements.should == ScratchPad.recorded
+ used_refinements = Module.used_refinements
end
+
+ used_refinements.should == ScratchPad.recorded
end
end
diff --git a/spec/ruby/core/numeric/shared/imag.rb b/spec/ruby/core/numeric/shared/imag.rb
index ac2da40a3b..4f117e243a 100644
--- a/spec/ruby/core/numeric/shared/imag.rb
+++ b/spec/ruby/core/numeric/shared/imag.rb
@@ -19,8 +19,8 @@ describe :numeric_imag, shared: true do
end
it "raises an ArgumentError if given any arguments" do
- @numbers.each do |number|
- -> { number.send(@method, number) }.should raise_error(ArgumentError)
- end
+ @numbers.each do |number|
+ -> { number.send(@method, number) }.should raise_error(ArgumentError)
+ end
end
end
diff --git a/spec/ruby/core/numeric/shared/rect.rb b/spec/ruby/core/numeric/shared/rect.rb
index 9cde19a398..120a69b1c4 100644
--- a/spec/ruby/core/numeric/shared/rect.rb
+++ b/spec/ruby/core/numeric/shared/rect.rb
@@ -25,24 +25,24 @@ describe :numeric_rect, shared: true do
end
it "returns self as the first element" do
- @numbers.each do |number|
- if Float === number and number.nan?
- number.send(@method).first.nan?.should be_true
- else
- number.send(@method).first.should == number
- end
- end
+ @numbers.each do |number|
+ if Float === number and number.nan?
+ number.send(@method).first.nan?.should be_true
+ else
+ number.send(@method).first.should == number
+ end
+ end
end
it "returns 0 as the last element" do
- @numbers.each do |number|
- number.send(@method).last.should == 0
- end
+ @numbers.each do |number|
+ number.send(@method).last.should == 0
+ end
end
it "raises an ArgumentError if given any arguments" do
- @numbers.each do |number|
- -> { number.send(@method, number) }.should raise_error(ArgumentError)
- end
+ @numbers.each do |number|
+ -> { number.send(@method, number) }.should raise_error(ArgumentError)
+ end
end
end
diff --git a/spec/ruby/core/objectspace/_id2ref_spec.rb b/spec/ruby/core/objectspace/_id2ref_spec.rb
index c088ae2743..1ae3230bdf 100644
--- a/spec/ruby/core/objectspace/_id2ref_spec.rb
+++ b/spec/ruby/core/objectspace/_id2ref_spec.rb
@@ -1,52 +1,65 @@
require_relative '../../spec_helper'
-describe "ObjectSpace._id2ref" do
- it "converts an object id to a reference to the object" do
- s = "I am a string"
- r = ObjectSpace._id2ref(s.object_id)
- r.should == s
+ruby_version_is "4.0" do
+ describe "ObjectSpace._id2ref" do
+ it "is deprecated" do
+ id = nil.object_id
+ -> {
+ ObjectSpace._id2ref(id)
+ }.should complain(/warning: ObjectSpace\._id2ref is deprecated/)
+ end
end
+end
- it "retrieves true by object_id" do
- ObjectSpace._id2ref(true.object_id).should == true
- end
+ruby_version_is ""..."4.0" do
+ describe "ObjectSpace._id2ref" do
+ it "converts an object id to a reference to the object" do
+ s = "I am a string"
+ r = ObjectSpace._id2ref(s.object_id)
+ r.should == s
+ end
- it "retrieves false by object_id" do
- ObjectSpace._id2ref(false.object_id).should == false
- end
+ it "retrieves true by object_id" do
+ ObjectSpace._id2ref(true.object_id).should == true
+ end
- it "retrieves nil by object_id" do
- ObjectSpace._id2ref(nil.object_id).should == nil
- end
+ it "retrieves false by object_id" do
+ ObjectSpace._id2ref(false.object_id).should == false
+ 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 nil by object_id" do
+ ObjectSpace._id2ref(nil.object_id).should == nil
+ 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 small Integer by object_id" do
+ ObjectSpace._id2ref(1.object_id).should == 1
+ ObjectSpace._id2ref((-42).object_id).should == -42
+ end
- it "retrieves a Symbol by object_id" do
- ObjectSpace._id2ref(:sym.object_id).should.equal?(:sym)
- 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 String by object_id" do
- obj = "str"
- ObjectSpace._id2ref(obj.object_id).should.equal?(obj)
- end
+ it "retrieves a Symbol by object_id" do
+ ObjectSpace._id2ref(:sym.object_id).should.equal?(:sym)
+ 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 a String by object_id" do
+ obj = "str"
+ ObjectSpace._id2ref(obj.object_id).should.equal?(obj)
+ end
- it "retrieves an Encoding by object_id" do
- ObjectSpace._id2ref(Encoding::UTF_8.object_id).should.equal?(Encoding::UTF_8)
- 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
- proc { ObjectSpace._id2ref(1 << 60) }.should raise_error(RangeError)
+ it 'raises RangeError when an object could not be found' do
+ proc { ObjectSpace._id2ref(1 << 60) }.should raise_error(RangeError)
+ end
end
end
diff --git a/spec/ruby/core/objectspace/add_finalizer_spec.rb b/spec/ruby/core/objectspace/add_finalizer_spec.rb
deleted file mode 100644
index 3540ac0413..0000000000
--- a/spec/ruby/core/objectspace/add_finalizer_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "ObjectSpace.add_finalizer" do
- it "needs to be reviewed for spec completeness"
-end
diff --git a/spec/ruby/core/objectspace/call_finalizer_spec.rb b/spec/ruby/core/objectspace/call_finalizer_spec.rb
deleted file mode 100644
index 6dce92ddd6..0000000000
--- a/spec/ruby/core/objectspace/call_finalizer_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "ObjectSpace.call_finalizer" do
- it "needs to be reviewed for spec completeness"
-end
diff --git a/spec/ruby/core/objectspace/define_finalizer_spec.rb b/spec/ruby/core/objectspace/define_finalizer_spec.rb
index effecc41d0..0f4b54c345 100644
--- a/spec/ruby/core/objectspace/define_finalizer_spec.rb
+++ b/spec/ruby/core/objectspace/define_finalizer_spec.rb
@@ -156,7 +156,7 @@ describe "ObjectSpace.define_finalizer" do
end
it "allows multiple finalizers with different 'callables' to be defined" do
- code = <<-RUBY
+ code = <<-'RUBY'
obj = Object.new
ObjectSpace.define_finalizer(obj, Proc.new { STDOUT.write "finalized1\n" })
@@ -168,25 +168,48 @@ describe "ObjectSpace.define_finalizer" do
ruby_exe(code).lines.sort.should == ["finalized1\n", "finalized2\n"]
end
- ruby_version_is "3.1" do
- describe "when $VERBOSE is not nil" do
- it "warns if an exception is raised in finalizer" do
- code = <<-RUBY
- ObjectSpace.define_finalizer(Object.new) { raise "finalizing" }
- RUBY
+ it "defines same finalizer only once" do
+ code = <<~RUBY
+ obj = Object.new
+ p = proc { |id| print "ok" }
+ ObjectSpace.define_finalizer(obj, p.dup)
+ ObjectSpace.define_finalizer(obj, p.dup)
+ RUBY
- ruby_exe(code, args: "2>&1").should include("warning: Exception in finalizer", "finalizing")
- end
+ ruby_exe(code).should == "ok"
+ end
+
+ it "returns the defined finalizer" do
+ obj = Object.new
+ p = proc { |id| }
+ p2 = p.dup
+
+ ret = ObjectSpace.define_finalizer(obj, p)
+ ret.should == [0, p]
+ ret[1].should.equal?(p)
+
+ ret = ObjectSpace.define_finalizer(obj, p2)
+ ret.should == [0, p]
+ ret[1].should.equal?(p)
+ end
+
+ describe "when $VERBOSE is not nil" do
+ it "warns if an exception is raised in finalizer" do
+ code = <<-RUBY
+ ObjectSpace.define_finalizer(Object.new) { raise "finalizing" }
+ RUBY
+
+ ruby_exe(code, args: "2>&1").should include("warning: Exception in finalizer", "finalizing")
end
+ end
- describe "when $VERBOSE is nil" do
- it "does not warn even if an exception is raised in finalizer" do
- code = <<-RUBY
- ObjectSpace.define_finalizer(Object.new) { raise "finalizing" }
- RUBY
+ describe "when $VERBOSE is nil" do
+ it "does not warn even if an exception is raised in finalizer" do
+ code = <<-RUBY
+ ObjectSpace.define_finalizer(Object.new) { raise "finalizing" }
+ RUBY
- ruby_exe(code, args: "2>&1", options: "-W0").should == ""
- end
+ ruby_exe(code, args: "2>&1", options: "-W0").should == ""
end
end
end
diff --git a/spec/ruby/core/objectspace/finalizers_spec.rb b/spec/ruby/core/objectspace/finalizers_spec.rb
deleted file mode 100644
index e7f20fc8a0..0000000000
--- a/spec/ruby/core/objectspace/finalizers_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "ObjectSpace.finalizers" do
- it "needs to be reviewed for spec completeness"
-end
diff --git a/spec/ruby/core/objectspace/remove_finalizer_spec.rb b/spec/ruby/core/objectspace/remove_finalizer_spec.rb
deleted file mode 100644
index 0b2b8cf16b..0000000000
--- a/spec/ruby/core/objectspace/remove_finalizer_spec.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require_relative '../../spec_helper'
-
-describe "ObjectSpace.remove_finalizer" do
- it "needs to be reviewed for spec completeness"
-end
diff --git a/spec/ruby/core/objectspace/undefine_finalizer_spec.rb b/spec/ruby/core/objectspace/undefine_finalizer_spec.rb
index 11d43121f8..f57d5a7845 100644
--- a/spec/ruby/core/objectspace/undefine_finalizer_spec.rb
+++ b/spec/ruby/core/objectspace/undefine_finalizer_spec.rb
@@ -1,5 +1,33 @@
require_relative '../../spec_helper'
describe "ObjectSpace.undefine_finalizer" do
- it "needs to be reviewed for spec completeness"
+ it "removes finalizers for an object" do
+ code = <<~RUBY
+ obj = Object.new
+ ObjectSpace.define_finalizer(obj, proc { |id| puts "hello" })
+ ObjectSpace.undefine_finalizer(obj)
+ RUBY
+
+ ruby_exe(code).should.empty?
+ end
+
+ it "should not remove finalizers for a frozen object" do
+ code = <<~RUBY
+ obj = Object.new
+ ObjectSpace.define_finalizer(obj, proc { |id| print "ok" })
+ obj.freeze
+ begin
+ ObjectSpace.undefine_finalizer(obj)
+ rescue
+ end
+ RUBY
+
+ ruby_exe(code).should == "ok"
+ end
+
+ it "should raise when removing finalizers for a frozen object" do
+ obj = Object.new
+ obj.freeze
+ -> { ObjectSpace.undefine_finalizer(obj) }.should raise_error(FrozenError)
+ end
end
diff --git a/spec/ruby/core/objectspace/weakkeymap/clear_spec.rb b/spec/ruby/core/objectspace/weakkeymap/clear_spec.rb
new file mode 100644
index 0000000000..8050e2c307
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakkeymap/clear_spec.rb
@@ -0,0 +1,27 @@
+require_relative '../../../spec_helper'
+
+ruby_version_is '3.3' do
+ describe "ObjectSpace::WeakKeyMap#clear" do
+ it "removes all the entries" do
+ m = ObjectSpace::WeakKeyMap.new
+
+ key = Object.new
+ value = Object.new
+ m[key] = value
+
+ key2 = Object.new
+ value2 = Object.new
+ m[key2] = value2
+
+ m.clear
+
+ m.key?(key).should == false
+ m.key?(key2).should == false
+ end
+
+ it "returns self" do
+ m = ObjectSpace::WeakKeyMap.new
+ m.clear.should.equal?(m)
+ end
+ end
+end
diff --git a/spec/ruby/core/objectspace/weakkeymap/delete_spec.rb b/spec/ruby/core/objectspace/weakkeymap/delete_spec.rb
index 6e534b8ea8..3cd61355d6 100644
--- a/spec/ruby/core/objectspace/weakkeymap/delete_spec.rb
+++ b/spec/ruby/core/objectspace/weakkeymap/delete_spec.rb
@@ -33,8 +33,19 @@ ruby_version_is '3.3' do
end
it "returns nil if the key is not found when no block is given" do
- m = ObjectSpace::WeakMap.new
+ m = ObjectSpace::WeakKeyMap.new
m.delete(Object.new).should == nil
end
+
+ it "returns nil when a key cannot be garbage collected" do
+ map = ObjectSpace::WeakKeyMap.new
+
+ map.delete(1).should == nil
+ map.delete(1.0).should == nil
+ map.delete(:a).should == nil
+ map.delete(true).should == nil
+ map.delete(false).should == nil
+ map.delete(nil).should == nil
+ end
end
end
diff --git a/spec/ruby/core/objectspace/weakkeymap/element_reference_spec.rb b/spec/ruby/core/objectspace/weakkeymap/element_reference_spec.rb
index 862480cd02..51368e8d3b 100644
--- a/spec/ruby/core/objectspace/weakkeymap/element_reference_spec.rb
+++ b/spec/ruby/core/objectspace/weakkeymap/element_reference_spec.rb
@@ -1,4 +1,5 @@
require_relative '../../../spec_helper'
+require_relative 'fixtures/classes'
ruby_version_is "3.3" do
describe "ObjectSpace::WeakKeyMap#[]" do
@@ -15,12 +16,92 @@ ruby_version_is "3.3" do
map[key2].should == ref2
end
- it "matches using equality semantics" do
+ it "compares keys with #eql? semantics" do
+ map = ObjectSpace::WeakKeyMap.new
+ key = [1.0]
+ map[key] = "x"
+ map[[1]].should == nil
+ map[[1.0]].should == "x"
+ key.should == [1.0] # keep the key alive until here to keep the map entry
+
+ map = ObjectSpace::WeakKeyMap.new
+ key = [1]
+ map[key] = "x"
+ map[[1.0]].should == nil
+ map[[1]].should == "x"
+ key.should == [1] # keep the key alive until here to keep the map entry
+
map = ObjectSpace::WeakKeyMap.new
key1, key2 = %w[a a].map(&:upcase)
ref = "x"
map[key1] = ref
map[key2].should == ref
end
+
+ it "compares key via #hash first" do
+ x = mock('0')
+ x.should_receive(:hash).and_return(0)
+
+ map = ObjectSpace::WeakKeyMap.new
+ key = 'foo'
+ map[key] = :bar
+ map[x].should == nil
+ end
+
+ it "does not compare keys with different #hash values via #eql?" do
+ x = mock('x')
+ x.should_not_receive(:eql?)
+ x.stub!(:hash).and_return(0)
+
+ y = mock('y')
+ y.should_not_receive(:eql?)
+ y.stub!(:hash).and_return(1)
+
+ map = ObjectSpace::WeakKeyMap.new
+ map[y] = 1
+ map[x].should == nil
+ end
+
+ it "compares keys with the same #hash value via #eql?" do
+ x = mock('x')
+ x.should_receive(:eql?).and_return(true)
+ x.stub!(:hash).and_return(42)
+
+ y = mock('y')
+ y.should_not_receive(:eql?)
+ y.stub!(:hash).and_return(42)
+
+ map = ObjectSpace::WeakKeyMap.new
+ map[y] = 1
+ map[x].should == 1
+ end
+
+ it "finds a value via an identical key even when its #eql? isn't reflexive" do
+ x = mock('x')
+ x.should_receive(:hash).at_least(1).and_return(42)
+ x.stub!(:eql?).and_return(false) # Stubbed for clarity and latitude in implementation; not actually sent by MRI.
+
+ map = ObjectSpace::WeakKeyMap.new
+ map[x] = :x
+ map[x].should == :x
+ end
+
+ it "supports keys with private #hash method" do
+ key = WeakKeyMapSpecs::KeyWithPrivateHash.new
+ map = ObjectSpace::WeakKeyMap.new
+ map[key] = 42
+ map[key].should == 42
+ end
+
+ it "returns nil and does not raise error when a key cannot be garbage collected" do
+ map = ObjectSpace::WeakKeyMap.new
+
+ map[1].should == nil
+ map[1.0].should == nil
+ map[:a].should == nil
+ map[true].should == nil
+ map[false].should == nil
+ map[nil].should == nil
+ end
end
end
diff --git a/spec/ruby/core/objectspace/weakkeymap/element_set_spec.rb b/spec/ruby/core/objectspace/weakkeymap/element_set_spec.rb
index c427e01ca5..8db8d780c7 100644
--- a/spec/ruby/core/objectspace/weakkeymap/element_set_spec.rb
+++ b/spec/ruby/core/objectspace/weakkeymap/element_set_spec.rb
@@ -8,10 +8,6 @@ ruby_version_is "3.3" do
map[key].should == value
end
- def should_not_accept(map, key, value)
- -> { map[key] = value }.should raise_error(ArgumentError)
- end
-
it "is correct" do
map = ObjectSpace::WeakKeyMap.new
key1, key2 = %w[a b].map(&:upcase)
@@ -40,32 +36,47 @@ ruby_version_is "3.3" do
should_accept(map, y, x)
end
- it "rejects symbols as keys" do
+ it "does not duplicate and freeze String keys (like Hash#[]= does)" do
map = ObjectSpace::WeakKeyMap.new
- should_not_accept(map, :foo, true)
- should_not_accept(map, rand.to_s.to_sym, true)
- end
+ key = +"a"
+ map[key] = 1
- it "rejects integers as keys" do
- map = ObjectSpace::WeakKeyMap.new
- should_not_accept(map, 42, true)
- should_not_accept(map, 2 ** 68, true)
- end
+ map.getkey("a").should.equal? key
+ map.getkey("a").should_not.frozen?
- it "rejects floats as keys" do
- map = ObjectSpace::WeakKeyMap.new
- should_not_accept(map, 4.2, true)
+ key.should == "a" # keep the key alive until here to keep the map entry
end
- it "rejects booleans as keys" do
- map = ObjectSpace::WeakKeyMap.new
- should_not_accept(map, true, true)
- should_not_accept(map, false, true)
- end
+ context "a key cannot be garbage collected" do
+ it "raises ArgumentError when Integer is used as a key" do
+ map = ObjectSpace::WeakKeyMap.new
+ -> { map[1] = "x" }.should raise_error(ArgumentError, /WeakKeyMap (keys )?must be garbage collectable/)
+ end
- it "rejects nil as keys" do
- map = ObjectSpace::WeakKeyMap.new
- should_not_accept(map, nil, true)
+ it "raises ArgumentError when Float is used as a key" do
+ map = ObjectSpace::WeakKeyMap.new
+ -> { map[1.0] = "x" }.should raise_error(ArgumentError, /WeakKeyMap (keys )?must be garbage collectable/)
+ end
+
+ it "raises ArgumentError when Symbol is used as a key" do
+ map = ObjectSpace::WeakKeyMap.new
+ -> { map[:a] = "x" }.should raise_error(ArgumentError, /WeakKeyMap (keys )?must be garbage collectable/)
+ end
+
+ it "raises ArgumentError when true is used as a key" do
+ map = ObjectSpace::WeakKeyMap.new
+ -> { map[true] = "x" }.should raise_error(ArgumentError, /WeakKeyMap (keys )?must be garbage collectable/)
+ end
+
+ it "raises ArgumentError when false is used as a key" do
+ map = ObjectSpace::WeakKeyMap.new
+ -> { map[false] = "x" }.should raise_error(ArgumentError, /WeakKeyMap (keys )?must be garbage collectable/)
+ end
+
+ it "raises ArgumentError when nil is used as a key" do
+ map = ObjectSpace::WeakKeyMap.new
+ -> { map[nil] = "x" }.should raise_error(ArgumentError, /WeakKeyMap (keys )?must be garbage collectable/)
+ end
end
end
end
diff --git a/spec/ruby/core/objectspace/weakkeymap/fixtures/classes.rb b/spec/ruby/core/objectspace/weakkeymap/fixtures/classes.rb
new file mode 100644
index 0000000000..0fd04551b5
--- /dev/null
+++ b/spec/ruby/core/objectspace/weakkeymap/fixtures/classes.rb
@@ -0,0 +1,5 @@
+module WeakKeyMapSpecs
+ class KeyWithPrivateHash
+ private :hash
+ end
+end
diff --git a/spec/ruby/core/objectspace/weakkeymap/getkey_spec.rb b/spec/ruby/core/objectspace/weakkeymap/getkey_spec.rb
index 3af0186f27..8a2dbf809d 100644
--- a/spec/ruby/core/objectspace/weakkeymap/getkey_spec.rb
+++ b/spec/ruby/core/objectspace/weakkeymap/getkey_spec.rb
@@ -9,6 +9,20 @@ ruby_version_is "3.3" do
map[key1] = true
map.getkey(key2).should equal(key1)
map.getkey("X").should == nil
+
+ key1.should == "A" # keep the key alive until here to keep the map entry
+ key2.should == "A" # keep the key alive until here to keep the map entry
+ end
+
+ it "returns nil when a key cannot be garbage collected" do
+ map = ObjectSpace::WeakKeyMap.new
+
+ map.getkey(1).should == nil
+ map.getkey(1.0).should == nil
+ map.getkey(:a).should == nil
+ map.getkey(true).should == nil
+ map.getkey(false).should == nil
+ map.getkey(nil).should == nil
end
end
end
diff --git a/spec/ruby/core/objectspace/weakkeymap/inspect_spec.rb b/spec/ruby/core/objectspace/weakkeymap/inspect_spec.rb
index 557fbc8733..319f050970 100644
--- a/spec/ruby/core/objectspace/weakkeymap/inspect_spec.rb
+++ b/spec/ruby/core/objectspace/weakkeymap/inspect_spec.rb
@@ -12,6 +12,10 @@ ruby_version_is "3.3" do
map.inspect.should =~ /\A\#<ObjectSpace::WeakKeyMap:0x\h+ size=2>\z/
map[key3] = 3
map.inspect.should =~ /\A\#<ObjectSpace::WeakKeyMap:0x\h+ size=2>\z/
+
+ key1.should == "foo" # keep the key alive until here to keep the map entry
+ key2.should == "bar" # keep the key alive until here to keep the map entry
+ key3.should == "bar" # keep the key alive until here to keep the map entry
end
end
end
diff --git a/spec/ruby/core/objectspace/weakkeymap/key_spec.rb b/spec/ruby/core/objectspace/weakkeymap/key_spec.rb
index 2af9c2b8e7..a9a2e12432 100644
--- a/spec/ruby/core/objectspace/weakkeymap/key_spec.rb
+++ b/spec/ruby/core/objectspace/weakkeymap/key_spec.rb
@@ -29,5 +29,16 @@ ruby_version_is "3.3" do
map[key] = nil
map.key?(key).should == true
end
+
+ it "returns false when a key cannot be garbage collected" do
+ map = ObjectSpace::WeakKeyMap.new
+
+ map.key?(1).should == false
+ map.key?(1.0).should == false
+ map.key?(:a).should == false
+ map.key?(true).should == false
+ map.key?(false).should == false
+ map.key?(nil).should == false
+ end
end
end
diff --git a/spec/ruby/core/proc/clone_spec.rb b/spec/ruby/core/proc/clone_spec.rb
index 7eca9c561e..730dc421a8 100644
--- a/spec/ruby/core/proc/clone_spec.rb
+++ b/spec/ruby/core/proc/clone_spec.rb
@@ -1,4 +1,5 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/common'
require_relative 'shared/dup'
describe "Proc#clone" do
@@ -12,4 +13,18 @@ describe "Proc#clone" do
proc.clone.frozen?.should == true
end
end
+
+ ruby_version_is "3.3" do
+ it "calls #initialize_clone on subclass" do
+ obj = ProcSpecs::MyProc2.new(:a, 2) { }
+ dup = obj.clone
+
+ dup.should_not equal(obj)
+ dup.class.should == ProcSpecs::MyProc2
+
+ dup.first.should == :a
+ dup.second.should == 2
+ dup.initializer.should == :clone
+ end
+ end
end
diff --git a/spec/ruby/core/proc/curry_spec.rb b/spec/ruby/core/proc/curry_spec.rb
index 24df2a8a72..6daabe0ee1 100644
--- a/spec/ruby/core/proc/curry_spec.rb
+++ b/spec/ruby/core/proc/curry_spec.rb
@@ -159,15 +159,14 @@ describe "Proc#curry with arity argument" do
end
it "can be passed more than _arity_ arguments if created from a proc" do
- -> { @proc_add.curry(3)[1,2,3,4].should == 6 }.should_not
- raise_error(ArgumentError)
- -> { @proc_add.curry(1)[1,2].curry(3)[3,4,5,6].should == 6 }.should_not
- raise_error(ArgumentError)
+ @proc_add.curry(3)[1,2,3,4].should == 6
+
+ @proc_add.curry(3)[1,2].curry(3)[3,4,5,6].should == 6
end
it "raises an ArgumentError if passed more than _arity_ arguments when created from a lambda" do
-> { @lambda_add.curry(3)[1,2,3,4] }.should raise_error(ArgumentError)
- -> { @lambda_add.curry(1)[1,2].curry(3)[3,4,5,6] }.should raise_error(ArgumentError)
+ -> { @lambda_add.curry(3)[1,2].curry(3)[3,4,5,6] }.should raise_error(ArgumentError)
end
it "returns Procs with arities of -1 regardless of the value of _arity_" do
diff --git a/spec/ruby/core/proc/dup_spec.rb b/spec/ruby/core/proc/dup_spec.rb
index dd19b3c1e9..716357d1f0 100644
--- a/spec/ruby/core/proc/dup_spec.rb
+++ b/spec/ruby/core/proc/dup_spec.rb
@@ -1,4 +1,5 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/common'
require_relative 'shared/dup'
describe "Proc#dup" do
@@ -10,4 +11,18 @@ describe "Proc#dup" do
proc.frozen?.should == true
proc.dup.frozen?.should == false
end
+
+ ruby_version_is "3.3" do
+ it "calls #initialize_dup on subclass" do
+ obj = ProcSpecs::MyProc2.new(:a, 2) { }
+ dup = obj.dup
+
+ dup.should_not equal(obj)
+ dup.class.should == ProcSpecs::MyProc2
+
+ dup.first.should == :a
+ dup.second.should == 2
+ dup.initializer.should == :dup
+ end
+ end
end
diff --git a/spec/ruby/core/proc/element_reference_spec.rb b/spec/ruby/core/proc/element_reference_spec.rb
index 9077e44c34..81ceb91af5 100644
--- a/spec/ruby/core/proc/element_reference_spec.rb
+++ b/spec/ruby/core/proc/element_reference_spec.rb
@@ -17,7 +17,7 @@ describe "Proc#call on a Proc created with Kernel#lambda or Kernel#proc" do
it_behaves_like :proc_call_on_proc_or_lambda, :call
end
-describe "Proc#[] with frozen_string_literals" do
+describe "Proc#[] with frozen_string_literal: true/false" do
it "doesn't duplicate frozen strings" do
ProcArefSpecs.aref.frozen?.should be_false
ProcArefSpecs.aref_freeze.frozen?.should be_true
diff --git a/spec/ruby/core/proc/fixtures/common.rb b/spec/ruby/core/proc/fixtures/common.rb
index 6e27a2dee7..dfe67d7ba8 100644
--- a/spec/ruby/core/proc/fixtures/common.rb
+++ b/spec/ruby/core/proc/fixtures/common.rb
@@ -32,7 +32,28 @@ module ProcSpecs
@second = b
end
- attr_reader :first, :second
+ attr_reader :first, :second, :initializer
+
+ def initialize_copy(other)
+ super
+ @initializer = :copy
+ @first = other.first
+ @second = other.second
+ end
+
+ def initialize_dup(other)
+ super
+ @initializer = :dup
+ @first = other.first
+ @second = other.second
+ end
+
+ def initialize_clone(other, **options)
+ super
+ @initializer = :clone
+ @first = other.first
+ @second = other.second
+ end
end
class Arity
diff --git a/spec/ruby/core/proc/parameters_spec.rb b/spec/ruby/core/proc/parameters_spec.rb
index 972596d2ea..cf8a8f5b12 100644
--- a/spec/ruby/core/proc/parameters_spec.rb
+++ b/spec/ruby/core/proc/parameters_spec.rb
@@ -20,29 +20,27 @@ describe "Proc#parameters" do
proc {|x| }.parameters.first.first.should == :opt
end
- ruby_version_is "3.2" do
- it "sets the first element of each sub-Array to :req for required argument if lambda keyword used" do
- proc {|x| }.parameters(lambda: true).first.first.should == :req
- proc {|y,*x| }.parameters(lambda: true).first.first.should == :req
- end
+ it "sets the first element of each sub-Array to :req for required argument if lambda keyword used" do
+ proc {|x| }.parameters(lambda: true).first.first.should == :req
+ proc {|y,*x| }.parameters(lambda: true).first.first.should == :req
+ end
- it "regards named parameters in procs as required if lambda keyword used" do
- proc {|x| }.parameters(lambda: true).first.first.should == :req
- end
+ it "regards named parameters in procs as required if lambda keyword used" do
+ proc {|x| }.parameters(lambda: true).first.first.should == :req
+ end
- it "regards named parameters in lambda as optional if lambda: false keyword used" do
- -> x { }.parameters(lambda: false).first.first.should == :opt
- end
+ it "regards named parameters in lambda as optional if lambda: false keyword used" do
+ -> x { }.parameters(lambda: false).first.first.should == :opt
+ end
- it "regards named parameters in procs and lambdas as required if lambda keyword is truthy" do
- proc {|x| }.parameters(lambda: 123).first.first.should == :req
- -> x { }.parameters(lambda: 123).first.first.should == :req
- end
+ it "regards named parameters in procs and lambdas as required if lambda keyword is truthy" do
+ proc {|x| }.parameters(lambda: 123).first.first.should == :req
+ -> x { }.parameters(lambda: 123).first.first.should == :req
+ end
- it "ignores the lambda keyword if it is nil" do
- proc {|x|}.parameters(lambda: nil).first.first.should == :opt
- -> x { }.parameters(lambda: nil).first.first.should == :req
- end
+ it "ignores the lambda keyword if it is nil" do
+ proc {|x|}.parameters(lambda: nil).first.first.should == :opt
+ -> x { }.parameters(lambda: nil).first.first.should == :req
end
it "regards optional keyword parameters in procs as optional" do
@@ -64,7 +62,7 @@ describe "Proc#parameters" do
end
it "regards keyword parameters in lambdas as required" do
- eval("lambda {|x:| }").parameters.first.first.should == :keyreq
+ -> x: { }.parameters.first.first.should == :keyreq
end
it "sets the first element of each sub-Array to :rest for parameters prefixed with asterisks" do
@@ -110,30 +108,16 @@ describe "Proc#parameters" do
-> x { }.parameters.should == [[:req, :x]]
end
- ruby_version_is '3.2' do
- it "adds rest arg with name * for \"star\" argument" do
- -> * {}.parameters.should == [[:rest, :*]]
- end
-
- it "adds keyrest arg with ** as a name for \"double star\" argument" do
- -> ** {}.parameters.should == [[:keyrest, :**]]
- end
+ it "adds rest arg with name * for \"star\" argument" do
+ -> * {}.parameters.should == [[:rest, :*]]
end
- ruby_version_is ''...'3.2' do
- it "adds nameless rest arg for \"star\" argument" do
- -> * {}.parameters.should == [[:rest]]
- end
-
- it "adds nameless keyrest arg for \"double star\" argument" do
- -> ** {}.parameters.should == [[:keyrest]]
- end
+ it "adds keyrest arg with ** as a name for \"double star\" argument" do
+ -> ** {}.parameters.should == [[:keyrest, :**]]
end
- ruby_version_is '3.1' do
- it "adds block arg with name & for anonymous block argument" do
- eval('-> & {}.parameters').should == [[:block, :&]]
- end
+ it "adds block arg with name & for anonymous block argument" do
+ -> & {}.parameters.should == [[:block, :&]]
end
it "does not add locals as block options with a block and splat" do
@@ -174,4 +158,18 @@ describe "Proc#parameters" do
it "returns :nokey for **nil parameter" do
proc { |**nil| }.parameters.should == [[:nokey]]
end
+
+ ruby_version_is "3.4"..."4.0" do
+ it "handles the usage of `it` as a parameter" do
+ eval("proc { it }").parameters.should == [[:opt, nil]]
+ eval("lambda { it }").parameters.should == [[:req]]
+ end
+ end
+
+ ruby_version_is "4.0" do
+ it "handles the usage of `it` as a parameter" do
+ eval("proc { it }").parameters.should == [[:opt]]
+ eval("lambda { it }").parameters.should == [[:req]]
+ end
+ end
end
diff --git a/spec/ruby/core/proc/ruby2_keywords_spec.rb b/spec/ruby/core/proc/ruby2_keywords_spec.rb
index ab67302231..d7f8f592e1 100644
--- a/spec/ruby/core/proc/ruby2_keywords_spec.rb
+++ b/spec/ruby/core/proc/ruby2_keywords_spec.rb
@@ -39,7 +39,7 @@ describe "Proc#ruby2_keywords" do
end
it "prints warning when a proc accepts keywords" do
- f = -> a:, b: { }
+ f = -> *a, b: { }
-> {
f.ruby2_keywords
@@ -47,10 +47,20 @@ describe "Proc#ruby2_keywords" do
end
it "prints warning when a proc accepts keyword splat" do
- f = -> **a { }
+ f = -> *a, **b { }
-> {
f.ruby2_keywords
}.should complain(/Skipping set of ruby2_keywords flag for/)
end
+
+ ruby_version_is "4.0" do
+ it "prints warning when a proc accepts post arguments" do
+ f = -> *a, b { }
+
+ -> {
+ f.ruby2_keywords
+ }.should complain(/Skipping set of ruby2_keywords flag for/)
+ end
+ end
end
diff --git a/spec/ruby/core/proc/shared/dup.rb b/spec/ruby/core/proc/shared/dup.rb
index c419a4078a..1266337f94 100644
--- a/spec/ruby/core/proc/shared/dup.rb
+++ b/spec/ruby/core/proc/shared/dup.rb
@@ -8,12 +8,10 @@ describe :proc_dup, shared: true do
a.call.should == b.call
end
- ruby_version_is "3.2" do
- it "returns an instance of subclass" do
- cl = Class.new(Proc)
+ it "returns an instance of subclass" do
+ cl = Class.new(Proc)
- cl.new{}.send(@method).class.should == cl
- end
+ cl.new{}.send(@method).class.should == cl
end
ruby_version_is "3.4" do
@@ -25,7 +23,7 @@ describe :proc_dup, shared: true do
end
it "copies the finalizer" do
- code = <<-RUBY
+ code = <<-'RUBY'
obj = Proc.new { }
ObjectSpace.define_finalizer(obj, Proc.new { STDOUT.write "finalized\n" })
diff --git a/spec/ruby/core/proc/source_location_spec.rb b/spec/ruby/core/proc/source_location_spec.rb
index a8b99287d5..fd33f21a26 100644
--- a/spec/ruby/core/proc/source_location_spec.rb
+++ b/spec/ruby/core/proc/source_location_spec.rb
@@ -17,57 +17,64 @@ describe "Proc#source_location" do
end
it "sets the first value to the path of the file in which the proc was defined" do
- file = @proc.source_location.first
+ file = @proc.source_location[0]
file.should be_an_instance_of(String)
file.should == File.realpath('fixtures/source_location.rb', __dir__)
- file = @proc_new.source_location.first
+ file = @proc_new.source_location[0]
file.should be_an_instance_of(String)
file.should == File.realpath('fixtures/source_location.rb', __dir__)
- file = @lambda.source_location.first
+ file = @lambda.source_location[0]
file.should be_an_instance_of(String)
file.should == File.realpath('fixtures/source_location.rb', __dir__)
- file = @method.source_location.first
+ file = @method.source_location[0]
file.should be_an_instance_of(String)
file.should == File.realpath('fixtures/source_location.rb', __dir__)
end
- it "sets the last value to an Integer representing the line on which the proc was defined" do
- line = @proc.source_location.last
+ it "sets the second value to an Integer representing the line on which the proc was defined" do
+ line = @proc.source_location[1]
line.should be_an_instance_of(Integer)
line.should == 4
- line = @proc_new.source_location.last
+ line = @proc_new.source_location[1]
line.should be_an_instance_of(Integer)
line.should == 12
- line = @lambda.source_location.last
+ line = @lambda.source_location[1]
line.should be_an_instance_of(Integer)
line.should == 8
- line = @method.source_location.last
+ line = @method.source_location[1]
line.should be_an_instance_of(Integer)
line.should == 15
end
it "works even if the proc was created on the same line" do
- proc { true }.source_location.should == [__FILE__, __LINE__]
- Proc.new { true }.source_location.should == [__FILE__, __LINE__]
- -> { true }.source_location.should == [__FILE__, __LINE__]
+ ruby_version_is(""..."4.1") do
+ proc { true }.source_location.should == [__FILE__, __LINE__]
+ Proc.new { true }.source_location.should == [__FILE__, __LINE__]
+ -> { true }.source_location.should == [__FILE__, __LINE__]
+ end
+ ruby_version_is("4.1") do
+ proc { true }.source_location.should == [__FILE__, __LINE__, 11, __LINE__, 19]
+ Proc.new { true }.source_location.should == [__FILE__, __LINE__, 15, __LINE__, 23]
+ -> { true }.source_location.should == [__FILE__, __LINE__, 6, __LINE__, 17]
+ end
end
it "returns the first line of a multi-line proc (i.e. the line containing 'proc do')" do
- ProcSpecs::SourceLocation.my_multiline_proc.source_location.last.should == 20
- ProcSpecs::SourceLocation.my_multiline_proc_new.source_location.last.should == 34
- ProcSpecs::SourceLocation.my_multiline_lambda.source_location.last.should == 27
+ ProcSpecs::SourceLocation.my_multiline_proc.source_location[1].should == 20
+ ProcSpecs::SourceLocation.my_multiline_proc_new.source_location[1].should == 34
+ ProcSpecs::SourceLocation.my_multiline_lambda.source_location[1].should == 27
end
it "returns the location of the proc's body; not necessarily the proc itself" do
- ProcSpecs::SourceLocation.my_detached_proc.source_location.last.should == 41
- ProcSpecs::SourceLocation.my_detached_proc_new.source_location.last.should == 51
- ProcSpecs::SourceLocation.my_detached_lambda.source_location.last.should == 46
+ ProcSpecs::SourceLocation.my_detached_proc.source_location[1].should == 41
+ ProcSpecs::SourceLocation.my_detached_proc_new.source_location[1].should == 51
+ ProcSpecs::SourceLocation.my_detached_lambda.source_location[1].should == 46
end
it "returns the same value for a proc-ified method as the method reports" do
@@ -86,6 +93,12 @@ describe "Proc#source_location" do
it "works for eval with a given line" do
proc = eval('-> {}', nil, "foo", 100)
- proc.source_location.should == ["foo", 100]
+ location = proc.source_location
+ ruby_version_is(""..."4.1") do
+ location.should == ["foo", 100]
+ end
+ ruby_version_is("4.1") do
+ location.should == ["foo", 100, 0, 100, 5]
+ end
end
end
diff --git a/spec/ruby/core/process/_fork_spec.rb b/spec/ruby/core/process/_fork_spec.rb
index 6f711ad2dd..e1f45e2656 100644
--- a/spec/ruby/core/process/_fork_spec.rb
+++ b/spec/ruby/core/process/_fork_spec.rb
@@ -1,24 +1,24 @@
require_relative '../../spec_helper'
-ruby_version_is "3.1" do
- describe "Process._fork" do
- it "for #respond_to? returns the same as Process.respond_to?(:fork)" do
- Process.respond_to?(:_fork).should == Process.respond_to?(:fork)
- end
+describe "Process._fork" do
+ it "for #respond_to? returns the same as Process.respond_to?(:fork)" do
+ Process.respond_to?(:_fork).should == Process.respond_to?(:fork)
+ end
- guard_not -> { Process.respond_to?(:fork) } do
- it "raises a NotImplementedError when called" do
- -> { Process._fork }.should raise_error(NotImplementedError)
- end
+ # Using respond_to? in a guard here is OK because the correct semantics
+ # are that _fork is implemented if and only if fork is (see above).
+ guard_not -> { Process.respond_to?(:fork) } do
+ it "raises a NotImplementedError when called" do
+ -> { Process._fork }.should raise_error(NotImplementedError)
end
+ end
- guard -> { Process.respond_to?(:fork) } do
- it "is called by Process#fork" do
- Process.should_receive(:_fork).once.and_return(42)
+ guard -> { Process.respond_to?(:fork) } do
+ it "is called by Process#fork" do
+ Process.should_receive(:_fork).once.and_return(42)
- pid = Process.fork {}
- pid.should equal(42)
- end
+ pid = Process.fork {}
+ pid.should equal(42)
end
end
end
diff --git a/spec/ruby/core/process/constants_spec.rb b/spec/ruby/core/process/constants_spec.rb
index 616c54b8e1..57cacadef2 100644
--- a/spec/ruby/core/process/constants_spec.rb
+++ b/spec/ruby/core/process/constants_spec.rb
@@ -2,69 +2,91 @@ require_relative '../../spec_helper'
describe "Process::Constants" do
platform_is :darwin, :netbsd, :freebsd do
- it "has the correct constant values on BSD-like systems" do
- Process::WNOHANG.should == 1
- Process::WUNTRACED.should == 2
- Process::PRIO_PROCESS.should == 0
- Process::PRIO_PGRP.should == 1
- Process::PRIO_USER.should == 2
- Process::RLIM_INFINITY.should == 9223372036854775807
- Process::RLIMIT_CPU.should == 0
- Process::RLIMIT_FSIZE.should == 1
- Process::RLIMIT_DATA.should == 2
- Process::RLIMIT_STACK.should == 3
- Process::RLIMIT_CORE.should == 4
- Process::RLIMIT_RSS.should == 5
- Process::RLIMIT_MEMLOCK.should == 6
- Process::RLIMIT_NPROC.should == 7
- Process::RLIMIT_NOFILE.should == 8
+ it "are all present on BSD-like systems" do
+ %i[
+ WNOHANG
+ WUNTRACED
+ PRIO_PROCESS
+ PRIO_PGRP
+ PRIO_USER
+ RLIM_INFINITY
+ RLIMIT_CPU
+ RLIMIT_FSIZE
+ RLIMIT_DATA
+ RLIMIT_STACK
+ RLIMIT_CORE
+ RLIMIT_RSS
+ RLIMIT_MEMLOCK
+ RLIMIT_NPROC
+ RLIMIT_NOFILE
+ ].each do |const|
+ Process.const_defined?(const).should be_true
+ Process.const_get(const).should be_an_instance_of(Integer)
+ end
end
end
platform_is :darwin do
- it "has the correct constant values on Darwin" do
- Process::RLIM_SAVED_MAX.should == 9223372036854775807
- Process::RLIM_SAVED_CUR.should == 9223372036854775807
- Process::RLIMIT_AS.should == 5
+ it "are all present on Darwin" do
+ %i[
+ RLIM_SAVED_MAX
+ RLIM_SAVED_CUR
+ RLIMIT_AS
+ ].each do |const|
+ Process.const_defined?(const).should be_true
+ Process.const_get(const).should be_an_instance_of(Integer)
+ end
end
end
platform_is :linux do
- it "has the correct constant values on Linux" do
- Process::WNOHANG.should == 1
- Process::WUNTRACED.should == 2
- Process::PRIO_PROCESS.should == 0
- Process::PRIO_PGRP.should == 1
- Process::PRIO_USER.should == 2
- Process::RLIMIT_CPU.should == 0
- Process::RLIMIT_FSIZE.should == 1
- Process::RLIMIT_DATA.should == 2
- Process::RLIMIT_STACK.should == 3
- Process::RLIMIT_CORE.should == 4
- Process::RLIMIT_RSS.should == 5
- Process::RLIMIT_NPROC.should == 6
- Process::RLIMIT_NOFILE.should == 7
- Process::RLIMIT_MEMLOCK.should == 8
- Process::RLIMIT_AS.should == 9
-
- # These values appear to change according to the platform.
- values = [4294967295, 9223372036854775807, 18446744073709551615]
- values.include?(Process::RLIM_INFINITY).should be_true
- values.include?(Process::RLIM_SAVED_MAX).should be_true
- values.include?(Process::RLIM_SAVED_CUR).should be_true
+ it "are all present on Linux" do
+ %i[
+ WNOHANG
+ WUNTRACED
+ PRIO_PROCESS
+ PRIO_PGRP
+ PRIO_USER
+ 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_true
+ Process.const_get(const).should be_an_instance_of(Integer)
+ end
end
end
platform_is :netbsd, :freebsd do
- it "has the correct constant values on NetBSD and FreeBSD" do
- Process::RLIMIT_SBSIZE.should == 9 # FIXME: what's it equal?
- Process::RLIMIT_AS.should == 10
+ it "are all present on NetBSD and FreeBSD" do
+ %i[
+ RLIMIT_SBSIZE
+ RLIMIT_AS
+ ].each do |const|
+ Process.const_defined?(const).should be_true
+ Process.const_get(const).should be_an_instance_of(Integer)
+ end
end
end
platform_is :freebsd do
- it "has the correct constant values on FreeBSD" do
- Process::RLIMIT_NPTS.should == 11
+ it "are all present on FreeBSD" do
+ %i[
+ RLIMIT_NPTS
+ ].each do |const|
+ Process.const_defined?(const).should be_true
+ Process.const_get(const).should be_an_instance_of(Integer)
+ end
end
end
diff --git a/spec/ruby/core/process/daemon_spec.rb b/spec/ruby/core/process/daemon_spec.rb
index 70ffd1b320..20b0d743b9 100644
--- a/spec/ruby/core/process/daemon_spec.rb
+++ b/spec/ruby/core/process/daemon_spec.rb
@@ -2,6 +2,9 @@ require_relative '../../spec_helper'
require_relative 'fixtures/common'
platform_is_not :windows do
+ # macOS 15 is not working this examples
+ return if /darwin/ =~ RUBY_PLATFORM && /15/ =~ `sw_vers -productVersion`
+
describe :process_daemon_keep_stdio_open_false, shared: true do
it "redirects stdout to /dev/null" do
@daemon.invoke("keep_stdio_open_false_stdout", @object).should == ""
diff --git a/spec/ruby/core/process/fixtures/clocks.rb b/spec/ruby/core/process/fixtures/clocks.rb
index f043f6ac1f..5757e280be 100644
--- a/spec/ruby/core/process/fixtures/clocks.rb
+++ b/spec/ruby/core/process/fixtures/clocks.rb
@@ -2,7 +2,7 @@ module ProcessSpecs
def self.clock_constants
clocks = []
- platform_is_not :windows, :solaris do
+ platform_is_not :windows do
clocks += Process.constants.select { |c| c.to_s.start_with?('CLOCK_') }
# These require CAP_WAKE_ALARM and are not documented in
diff --git a/spec/ruby/core/process/gid_spec.rb b/spec/ruby/core/process/gid_spec.rb
index 07221da420..ca935ed520 100644
--- a/spec/ruby/core/process/gid_spec.rb
+++ b/spec/ruby/core/process/gid_spec.rb
@@ -3,8 +3,8 @@ require_relative '../../spec_helper'
describe "Process.gid" do
platform_is_not :windows do
it "returns the correct gid for the user executing this process" do
- current_gid_according_to_unix = `id -gr`.to_i
- Process.gid.should == current_gid_according_to_unix
+ current_gid_according_to_unix = `id -gr`.to_i
+ Process.gid.should == current_gid_according_to_unix
end
end
diff --git a/spec/ruby/core/process/setrlimit_spec.rb b/spec/ruby/core/process/setrlimit_spec.rb
index b92f98fd40..ba8d1e04ca 100644
--- a/spec/ruby/core/process/setrlimit_spec.rb
+++ b/spec/ruby/core/process/setrlimit_spec.rb
@@ -73,20 +73,18 @@ describe "Process.setrlimit" do
Process.setrlimit(:STACK, *Process.getrlimit(Process::RLIMIT_STACK)).should be_nil
end
- platform_is_not :solaris, :aix do
+ platform_is_not :aix do
it "coerces :MEMLOCK into RLIMIT_MEMLOCK" do
Process.setrlimit(:MEMLOCK, *Process.getrlimit(Process::RLIMIT_MEMLOCK)).should be_nil
end
end
- platform_is_not :solaris do
- it "coerces :NPROC into RLIMIT_NPROC" do
- Process.setrlimit(:NPROC, *Process.getrlimit(Process::RLIMIT_NPROC)).should be_nil
- end
+ it "coerces :NPROC into RLIMIT_NPROC" do
+ Process.setrlimit(:NPROC, *Process.getrlimit(Process::RLIMIT_NPROC)).should be_nil
+ end
- it "coerces :RSS into RLIMIT_RSS" do
- Process.setrlimit(:RSS, *Process.getrlimit(Process::RLIMIT_RSS)).should be_nil
- end
+ it "coerces :RSS into RLIMIT_RSS" do
+ Process.setrlimit(:RSS, *Process.getrlimit(Process::RLIMIT_RSS)).should be_nil
end
platform_is :netbsd, :freebsd do
@@ -155,20 +153,18 @@ describe "Process.setrlimit" do
Process.setrlimit("STACK", *Process.getrlimit(Process::RLIMIT_STACK)).should be_nil
end
- platform_is_not :solaris, :aix do
+ platform_is_not :aix do
it "coerces 'MEMLOCK' into RLIMIT_MEMLOCK" do
Process.setrlimit("MEMLOCK", *Process.getrlimit(Process::RLIMIT_MEMLOCK)).should be_nil
end
end
- platform_is_not :solaris do
- it "coerces 'NPROC' into RLIMIT_NPROC" do
- Process.setrlimit("NPROC", *Process.getrlimit(Process::RLIMIT_NPROC)).should be_nil
- end
+ it "coerces 'NPROC' into RLIMIT_NPROC" do
+ Process.setrlimit("NPROC", *Process.getrlimit(Process::RLIMIT_NPROC)).should be_nil
+ end
- it "coerces 'RSS' into RLIMIT_RSS" do
- Process.setrlimit("RSS", *Process.getrlimit(Process::RLIMIT_RSS)).should be_nil
- end
+ it "coerces 'RSS' into RLIMIT_RSS" do
+ Process.setrlimit("RSS", *Process.getrlimit(Process::RLIMIT_RSS)).should be_nil
end
platform_is :netbsd, :freebsd do
diff --git a/spec/ruby/core/process/status/bit_and_spec.rb b/spec/ruby/core/process/status/bit_and_spec.rb
index 97f768fdc1..a805364629 100644
--- a/spec/ruby/core/process/status/bit_and_spec.rb
+++ b/spec/ruby/core/process/status/bit_and_spec.rb
@@ -1,5 +1,38 @@
require_relative '../../../spec_helper'
-describe "Process::Status#&" do
- it "needs to be reviewed for spec completeness"
+ruby_version_is ""..."4.0" do
+
+ describe "Process::Status#&" do
+ it "returns a bitwise and of the integer status of an exited child" do
+ suppress_warning do
+ ruby_exe("exit(29)", exit_status: 29)
+ ($? & 0).should == 0
+ ($? & $?.to_i).should == $?.to_i
+
+ # Actual value is implementation specific
+ platform_is :linux do
+ # 29 == 0b11101
+ ($? & 0b1011100000000).should == 0b1010100000000
+ end
+ end
+ end
+
+ ruby_version_is "3.3"..."4.0" do
+ it "raises an ArgumentError if mask is negative" do
+ suppress_warning do
+ ruby_exe("exit(0)")
+ -> {
+ $? & -1
+ }.should raise_error(ArgumentError, 'negative mask value: -1')
+ end
+ end
+
+ it "shows a deprecation warning" do
+ ruby_exe("exit(0)")
+ -> {
+ $? & 0
+ }.should complain(/warning: Process::Status#& is deprecated and will be removed .*use other Process::Status predicates instead/)
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/process/status/right_shift_spec.rb b/spec/ruby/core/process/status/right_shift_spec.rb
index e9dda437e8..355aaf4c95 100644
--- a/spec/ruby/core/process/status/right_shift_spec.rb
+++ b/spec/ruby/core/process/status/right_shift_spec.rb
@@ -1,5 +1,37 @@
require_relative '../../../spec_helper'
-describe "Process::Status#>>" do
- it "needs to be reviewed for spec completeness"
+ruby_version_is ""..."4.0" do
+
+ describe "Process::Status#>>" do
+ it "returns a right shift of the integer status of an exited child" do
+ suppress_warning do
+ ruby_exe("exit(29)", exit_status: 29)
+ ($? >> 0).should == $?.to_i
+ ($? >> 1).should == $?.to_i >> 1
+
+ # Actual value is implementation specific
+ platform_is :linux do
+ ($? >> 8).should == 29
+ end
+ end
+ end
+
+ ruby_version_is "3.3"..."4.0" do
+ it "raises an ArgumentError if shift value is negative" do
+ suppress_warning do
+ ruby_exe("exit(0)")
+ -> {
+ $? >> -1
+ }.should raise_error(ArgumentError, 'negative shift value: -1')
+ end
+ end
+
+ it "shows a deprecation warning" do
+ ruby_exe("exit(0)")
+ -> {
+ $? >> 0
+ }.should complain(/warning: Process::Status#>> is deprecated and will be removed .*use other Process::Status attributes instead/)
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/process/tms/cstime_spec.rb b/spec/ruby/core/process/tms/cstime_spec.rb
new file mode 100644
index 0000000000..9c2d9e8632
--- /dev/null
+++ b/spec/ruby/core/process/tms/cstime_spec.rb
@@ -0,0 +1,17 @@
+require_relative '../../../spec_helper'
+
+describe "Process::Tms#cstime" do
+ it "returns cstime attribute" do
+ cstime = Object.new
+ Process::Tms.new(nil, nil, nil, cstime).cstime.should == cstime
+ end
+end
+
+describe "Process::Tms#cstime=" do
+ it "assigns a value to the cstime attribute" do
+ cstime = Object.new
+ tms = Process::Tms.new
+ tms.cstime = cstime
+ tms.cstime.should == cstime
+ end
+end
diff --git a/spec/ruby/core/process/tms/cutime_spec.rb b/spec/ruby/core/process/tms/cutime_spec.rb
new file mode 100644
index 0000000000..0ac3ff1964
--- /dev/null
+++ b/spec/ruby/core/process/tms/cutime_spec.rb
@@ -0,0 +1,17 @@
+require_relative '../../../spec_helper'
+
+describe "Process::Tms#cutime" do
+ it "returns cutime attribute" do
+ cutime = Object.new
+ Process::Tms.new(nil, nil, cutime, nil).cutime.should == cutime
+ end
+end
+
+describe "Process::Tms#cutime=" do
+ it "assigns a value to the cutime attribute" do
+ cutime = Object.new
+ tms = Process::Tms.new
+ tms.cutime = cutime
+ tms.cutime.should == cutime
+ end
+end
diff --git a/spec/ruby/core/process/tms/stime_spec.rb b/spec/ruby/core/process/tms/stime_spec.rb
new file mode 100644
index 0000000000..1e8371475f
--- /dev/null
+++ b/spec/ruby/core/process/tms/stime_spec.rb
@@ -0,0 +1,17 @@
+require_relative '../../../spec_helper'
+
+describe "Process::Tms#stime" do
+ it "returns stime attribute" do
+ stime = Object.new
+ Process::Tms.new(nil, stime, nil, nil).stime.should == stime
+ end
+end
+
+describe "Process::Tms#stime=" do
+ it "assigns a value to the stime attribute" do
+ stime = Object.new
+ tms = Process::Tms.new
+ tms.stime = stime
+ tms.stime.should == stime
+ end
+end
diff --git a/spec/ruby/core/process/tms/utime_spec.rb b/spec/ruby/core/process/tms/utime_spec.rb
new file mode 100644
index 0000000000..403a31e2e6
--- /dev/null
+++ b/spec/ruby/core/process/tms/utime_spec.rb
@@ -0,0 +1,17 @@
+require_relative '../../../spec_helper'
+
+describe "Process::Tms#utime" do
+ it "returns utime attribute" do
+ utime = Object.new
+ Process::Tms.new(utime, nil, nil, nil).utime.should == utime
+ end
+end
+
+describe "Process::Tms#utime=" do
+ it "assigns a value to the ctime attribute" do
+ utime = Object.new
+ tms = Process::Tms.new
+ tms.utime = utime
+ tms.utime.should == utime
+ end
+end
diff --git a/spec/ruby/core/queue/deq_spec.rb b/spec/ruby/core/queue/deq_spec.rb
index f84d4220ea..a2784e6a63 100644
--- a/spec/ruby/core/queue/deq_spec.rb
+++ b/spec/ruby/core/queue/deq_spec.rb
@@ -7,7 +7,5 @@ describe "Queue#deq" do
end
describe "Queue operations with timeout" do
- ruby_version_is "3.2" do
- it_behaves_like :rb_num2dbl_fails, nil, -> v { q = Queue.new; q.push(1); q.deq(timeout: v) }
- end
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = Queue.new; q.push(1); q.deq(timeout: v) }
end
diff --git a/spec/ruby/core/queue/freeze_spec.rb b/spec/ruby/core/queue/freeze_spec.rb
new file mode 100644
index 0000000000..ced2cc52dd
--- /dev/null
+++ b/spec/ruby/core/queue/freeze_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative '../../shared/queue/freeze'
+
+describe "Queue#freeze" do
+ it_behaves_like :queue_freeze, :freeze, -> { Queue.new }
+end
diff --git a/spec/ruby/core/queue/initialize_spec.rb b/spec/ruby/core/queue/initialize_spec.rb
index c6c1ae63c5..592fbe2487 100644
--- a/spec/ruby/core/queue/initialize_spec.rb
+++ b/spec/ruby/core/queue/initialize_spec.rb
@@ -11,9 +11,21 @@ describe "Queue#initialize" do
Queue.private_instance_methods.include?(:initialize).should == true
end
- ruby_version_is '3.1' do
- it "adds all elements of the passed Enumerable to self" do
- q = Queue.new([1, 2, 3])
+ 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
+
+ describe "converts the given argument to an Array using #to_a" do
+ 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
@@ -22,41 +34,27 @@ describe "Queue#initialize" do
q.should.empty?
end
- describe "converts the given argument to an Array using #to_a" do
- 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 a TypeError if the given argument can't be converted to an Array" do
- -> { Queue.new(42) }.should raise_error(TypeError)
- -> { Queue.new(:abc) }.should raise_error(TypeError)
- end
-
- it "raises a NoMethodError if the given argument raises a NoMethodError during type coercion to an Array" do
- enumerable = MockObject.new('mock-enumerable')
- enumerable.should_receive(:to_a).and_raise(NoMethodError)
- -> { Queue.new(enumerable) }.should raise_error(NoMethodError)
- end
+ it "raises a TypeError if the given argument can't be converted to an Array" do
+ -> { Queue.new(42) }.should raise_error(TypeError)
+ -> { Queue.new(:abc) }.should raise_error(TypeError)
end
- it "raises TypeError if the provided Enumerable does not respond to #to_a" do
+ it "raises a NoMethodError if the given argument raises a NoMethodError during type coercion to an Array" do
enumerable = MockObject.new('mock-enumerable')
- -> { Queue.new(enumerable) }.should raise_error(TypeError, "can't convert MockObject into Array")
+ enumerable.should_receive(:to_a).and_raise(NoMethodError)
+ -> { Queue.new(enumerable) }.should raise_error(NoMethodError)
end
+ end
- it "raises TypeError if #to_a does not return Array" do
- enumerable = MockObject.new('mock-enumerable')
- enumerable.should_receive(:to_a).and_return("string")
+ it "raises TypeError 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
- -> { Queue.new(enumerable) }.should raise_error(TypeError, "can't convert MockObject to Array (MockObject#to_a gives String)")
- end
+ it "raises TypeError if #to_a does not return Array" do
+ enumerable = MockObject.new('mock-enumerable')
+ enumerable.should_receive(:to_a).and_return("string")
+
+ -> { Queue.new(enumerable) }.should raise_error(TypeError, "can't convert MockObject to Array (MockObject#to_a gives String)")
end
end
diff --git a/spec/ruby/core/queue/pop_spec.rb b/spec/ruby/core/queue/pop_spec.rb
index d344740834..3dff7db242 100644
--- a/spec/ruby/core/queue/pop_spec.rb
+++ b/spec/ruby/core/queue/pop_spec.rb
@@ -7,7 +7,5 @@ describe "Queue#pop" do
end
describe "Queue operations with timeout" do
- ruby_version_is "3.2" do
- it_behaves_like :rb_num2dbl_fails, nil, -> v { q = Queue.new; q.push(1); q.pop(timeout: v) }
- end
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = Queue.new; q.push(1); q.pop(timeout: v) }
end
diff --git a/spec/ruby/core/queue/shift_spec.rb b/spec/ruby/core/queue/shift_spec.rb
index 64165e0b61..c105da74b2 100644
--- a/spec/ruby/core/queue/shift_spec.rb
+++ b/spec/ruby/core/queue/shift_spec.rb
@@ -7,7 +7,5 @@ describe "Queue#shift" do
end
describe "Queue operations with timeout" do
- ruby_version_is "3.2" do
- it_behaves_like :rb_num2dbl_fails, nil, -> v { q = Queue.new; q.push(1); q.shift(timeout: v) }
- end
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = Queue.new; q.push(1); q.shift(timeout: v) }
end
diff --git a/spec/ruby/core/random/bytes_spec.rb b/spec/ruby/core/random/bytes_spec.rb
index b42dc61234..c9be07cd3f 100644
--- a/spec/ruby/core/random/bytes_spec.rb
+++ b/spec/ruby/core/random/bytes_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
require_relative 'shared/bytes'
diff --git a/spec/ruby/core/random/default_spec.rb b/spec/ruby/core/random/default_spec.rb
index 01d7430df8..9e4845986d 100644
--- a/spec/ruby/core/random/default_spec.rb
+++ b/spec/ruby/core/random/default_spec.rb
@@ -1,35 +1,7 @@
require_relative '../../spec_helper'
describe "Random::DEFAULT" do
- ruby_version_is ''...'3.2' do
- it "returns a random number generator" do
- suppress_warning do
- Random::DEFAULT.should respond_to(:rand)
- 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
-
- 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
-
- ruby_version_is '3.2' do
- it "is no longer defined" do
- Random.should_not.const_defined?(:DEFAULT)
- end
+ it "is no longer defined" do
+ Random.should_not.const_defined?(:DEFAULT)
end
end
diff --git a/spec/ruby/core/random/new_spec.rb b/spec/ruby/core/random/new_spec.rb
index 90e2a9d6f2..69210cef03 100644
--- a/spec/ruby/core/random/new_spec.rb
+++ b/spec/ruby/core/random/new_spec.rb
@@ -11,7 +11,7 @@ describe "Random.new" do
it "returns Random instances initialized with different seeds" do
first = Random.new
second = Random.new
- (0..20).map { first.rand } .should_not == (0..20).map { second.rand }
+ (0..20).map { first.rand }.should_not == (0..20).map { second.rand }
end
it "accepts an Integer seed value as an argument" do
diff --git a/spec/ruby/core/range/case_compare_spec.rb b/spec/ruby/core/range/case_compare_spec.rb
index 65878aaabe..c9b253f0a5 100644
--- a/spec/ruby/core/range/case_compare_spec.rb
+++ b/spec/ruby/core/range/case_compare_spec.rb
@@ -11,7 +11,7 @@ describe "Range#===" do
it_behaves_like :range_cover_and_include, :===
it_behaves_like :range_cover, :===
- ruby_bug "#19533", "3.2"..."3.3" do
+ ruby_bug "#19533", ""..."3.3" do
it "returns true on any value if begin and end are both nil" do
(nil..nil).should === 1
end
diff --git a/spec/ruby/core/range/cover_spec.rb b/spec/ruby/core/range/cover_spec.rb
index eb7cddc967..c05bb50614 100644
--- a/spec/ruby/core/range/cover_spec.rb
+++ b/spec/ruby/core/range/cover_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
require_relative 'shared/cover_and_include'
require_relative 'shared/cover'
diff --git a/spec/ruby/core/range/each_spec.rb b/spec/ruby/core/range/each_spec.rb
index ecae17c881..f10330d61d 100644
--- a/spec/ruby/core/range/each_spec.rb
+++ b/spec/ruby/core/range/each_spec.rb
@@ -40,21 +40,21 @@ describe "Range#each" do
it "works with endless ranges" do
a = []
- eval("(-2..)").each { |x| break if x > 2; a << x }
+ (-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 }
+ (-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'..).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'...).each { |x| break if x > "D"; a << x }
a.should == ["A", "B", "C", "D"]
end
@@ -82,27 +82,14 @@ describe "Range#each" do
enum.to_a.should == [1, 2, 3]
end
- 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
+ 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
+ (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
it "passes each Symbol element by using #succ" do
diff --git a/spec/ruby/core/range/include_spec.rb b/spec/ruby/core/range/include_spec.rb
index 277de205d1..449e18985b 100644
--- a/spec/ruby/core/range/include_spec.rb
+++ b/spec/ruby/core/range/include_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
require_relative 'shared/cover_and_include'
require_relative 'shared/include'
diff --git a/spec/ruby/core/range/last_spec.rb b/spec/ruby/core/range/last_spec.rb
index 6698686dd5..82b3e2ff53 100644
--- a/spec/ruby/core/range/last_spec.rb
+++ b/spec/ruby/core/range/last_spec.rb
@@ -8,10 +8,8 @@ describe "Range#last" do
(1..5).last(3).should == [3, 4, 5]
end
- ruby_bug '#18994', '2.7'...'3.2' do
- it "returns the specified number if elements for single element inclusive range" do
- (1..1).last(1).should == [1]
- end
+ it "returns the specified number if elements for single element inclusive range" do
+ (1..1).last(1).should == [1]
end
it "returns an empty array for an empty Range" do
diff --git a/spec/ruby/core/range/max_spec.rb b/spec/ruby/core/range/max_spec.rb
index a3bbc31e7d..09371f5298 100644
--- a/spec/ruby/core/range/max_spec.rb
+++ b/spec/ruby/core/range/max_spec.rb
@@ -55,10 +55,24 @@ describe "Range#max" do
(..1.0).max.should == 1.0
end
- it "raises for an exclusive beginless range" do
+ ruby_version_is ""..."4.0" do
+ it "raises for an exclusive beginless Integer range" do
+ -> {
+ (...1).max
+ }.should raise_error(TypeError, 'cannot exclude end value with non Integer begin value')
+ end
+ end
+
+ ruby_version_is "4.0" do
+ it "returns the end point for exclusive beginless Integer ranges" do
+ (...1).max.should == 0
+ end
+ end
+
+ it "raises for an exclusive beginless non Integer range" do
-> {
- (...1).max
- }.should raise_error(TypeError, 'cannot exclude end value with non Integer begin value')
+ (...1.0).max
+ }.should raise_error(TypeError, 'cannot exclude non Integer end value')
end
end
diff --git a/spec/ruby/core/range/member_spec.rb b/spec/ruby/core/range/member_spec.rb
index ab61f92951..78299ae9e5 100644
--- a/spec/ruby/core/range/member_spec.rb
+++ b/spec/ruby/core/range/member_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
require_relative 'shared/cover_and_include'
require_relative 'shared/include'
diff --git a/spec/ruby/core/range/overlap_spec.rb b/spec/ruby/core/range/overlap_spec.rb
new file mode 100644
index 0000000000..9b6fc13493
--- /dev/null
+++ b/spec/ruby/core/range/overlap_spec.rb
@@ -0,0 +1,89 @@
+require_relative '../../spec_helper'
+
+ruby_version_is '3.3' do
+ describe "Range#overlap?" do
+ it "returns true if other Range overlaps self" do
+ (0..2).overlap?(1..3).should == true
+ (1..3).overlap?(0..2).should == true
+ (0..2).overlap?(0..2).should == true
+ (0..3).overlap?(1..2).should == true
+ (1..2).overlap?(0..3).should == true
+
+ ('a'..'c').overlap?('b'..'d').should == true
+ end
+
+ it "returns false if other Range does not overlap self" do
+ (0..2).overlap?(3..4).should == false
+ (0..2).overlap?(-4..-1).should == false
+
+ ('a'..'c').overlap?('d'..'f').should == false
+ end
+
+ it "raises TypeError when called with non-Range argument" do
+ -> {
+ (0..2).overlap?(1)
+ }.should raise_error(TypeError, "wrong argument type Integer (expected Range)")
+ end
+
+ it "returns true when beginningless and endless Ranges overlap" do
+ (0..2).overlap?(..3).should == true
+ (0..2).overlap?(..1).should == true
+ (0..2).overlap?(..0).should == true
+
+ (..3).overlap?(0..2).should == true
+ (..1).overlap?(0..2).should == true
+ (..0).overlap?(0..2).should == true
+
+ (0..2).overlap?(-1..).should == true
+ (0..2).overlap?(1..).should == true
+ (0..2).overlap?(2..).should == true
+
+ (-1..).overlap?(0..2).should == true
+ (1..).overlap?(0..2).should == true
+ (2..).overlap?(0..2).should == true
+
+ (0..).overlap?(2..).should == true
+ (..0).overlap?(..2).should == true
+ end
+
+ it "returns false when beginningless and endless Ranges do not overlap" do
+ (0..2).overlap?(..-1).should == false
+ (0..2).overlap?(3..).should == false
+
+ (..-1).overlap?(0..2).should == false
+ (3..).overlap?(0..2).should == false
+ end
+
+ it "returns false when Ranges are not compatible" do
+ (0..2).overlap?('a'..'d').should == false
+ end
+
+ it "return false when self is empty" do
+ (2..0).overlap?(1..3).should == false
+ (2...2).overlap?(1..3).should == false
+ (1...1).overlap?(1...1).should == false
+ (2..0).overlap?(2..0).should == false
+
+ ('c'..'a').overlap?('b'..'d').should == false
+ ('a'...'a').overlap?('b'..'d').should == false
+ ('b'...'b').overlap?('b'...'b').should == false
+ ('c'...'a').overlap?('c'...'a').should == false
+ end
+
+ it "return false when other Range is empty" do
+ (1..3).overlap?(2..0).should == false
+ (1..3).overlap?(2...2).should == false
+
+ ('b'..'d').overlap?('c'..'a').should == false
+ ('b'..'d').overlap?('c'...'c').should == false
+ end
+
+ it "takes into account exclusive end" do
+ (0...2).overlap?(2..4).should == false
+ (2..4).overlap?(0...2).should == false
+
+ ('a'...'c').overlap?('c'..'e').should == false
+ ('c'..'e').overlap?('a'...'c').should == false
+ end
+ end
+end
diff --git a/spec/ruby/core/range/reverse_each_spec.rb b/spec/ruby/core/range/reverse_each_spec.rb
new file mode 100644
index 0000000000..56390cc0da
--- /dev/null
+++ b/spec/ruby/core/range/reverse_each_spec.rb
@@ -0,0 +1,103 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.3" do
+ describe "Range#reverse_each" do
+ it "traverses the Range in reverse order and passes each element to block" do
+ a = []
+ (1..3).reverse_each { |i| a << i }
+ a.should == [3, 2, 1]
+
+ a = []
+ (1...3).reverse_each { |i| a << i }
+ a.should == [2, 1]
+ end
+
+ it "returns self" do
+ r = (1..3)
+ r.reverse_each { |x| }.should equal(r)
+ end
+
+ it "returns an Enumerator if no block given" do
+ enum = (1..3).reverse_each
+ enum.should be_an_instance_of(Enumerator)
+ enum.to_a.should == [3, 2, 1]
+ end
+
+ it "raises a TypeError for endless Ranges of Integers" do
+ -> {
+ (1..).reverse_each.take(3)
+ }.should raise_error(TypeError, "can't iterate from NilClass")
+ end
+
+ it "raises a TypeError for endless Ranges of non-Integers" do
+ -> {
+ ("a"..).reverse_each.take(3)
+ }.should raise_error(TypeError, "can't iterate from NilClass")
+ end
+
+ context "Integer boundaries" do
+ it "supports beginningless Ranges" do
+ (..5).reverse_each.take(3).should == [5, 4, 3]
+ end
+ end
+
+ context "non-Integer boundaries" do
+ it "uses #succ to iterate a Range of non-Integer elements" do
+ y = mock('y')
+ x = mock('x')
+
+ x.should_receive(:succ).any_number_of_times.and_return(y)
+ x.should_receive(:<=>).with(y).any_number_of_times.and_return(-1)
+ x.should_receive(:<=>).with(x).any_number_of_times.and_return(0)
+ y.should_receive(:<=>).with(x).any_number_of_times.and_return(1)
+ y.should_receive(:<=>).with(y).any_number_of_times.and_return(0)
+
+ a = []
+ (x..y).each { |i| a << i }
+ a.should == [x, y]
+ end
+
+ it "uses #succ to iterate a Range of Strings" do
+ a = []
+ ('A'..'D').reverse_each { |i| a << i }
+ a.should == ['D','C','B','A']
+ end
+
+ it "uses #succ to iterate a Range of Symbols" do
+ a = []
+ (:A..:D).reverse_each { |i| a << i }
+ a.should == [:D, :C, :B, :A]
+ end
+
+ it "raises a TypeError when `begin` value does not respond to #succ" do
+ -> { (Time.now..Time.now).reverse_each { |x| x } }.should raise_error(TypeError, /can't iterate from Time/)
+ -> { (//..//).reverse_each { |x| x } }.should raise_error(TypeError, /can't iterate from Regexp/)
+ -> { ([]..[]).reverse_each { |x| x } }.should raise_error(TypeError, /can't iterate from Array/)
+ end
+
+ it "does not support beginningless Ranges" do
+ -> {
+ (..'a').reverse_each { |x| x }
+ }.should raise_error(TypeError, /can't iterate from NilClass/)
+ end
+ end
+
+ context "when no block is given" do
+ describe "returned Enumerator size" do
+ it "returns the Range size when Range size is finite" do
+ (1..3).reverse_each.size.should == 3
+ end
+
+ ruby_bug "#20936", "3.4"..."4.0" do
+ it "returns Infinity when Range size is infinite" do
+ (..3).reverse_each.size.should == Float::INFINITY
+ end
+ end
+
+ it "returns nil when Range size is unknown" do
+ ('a'..'z').reverse_each.size.should == nil
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/range/shared/cover.rb b/spec/ruby/core/range/shared/cover.rb
index 0b41a26455..eaefb45942 100644
--- a/spec/ruby/core/range/shared/cover.rb
+++ b/spec/ruby/core/range/shared/cover.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
diff --git a/spec/ruby/core/range/shared/cover_and_include.rb b/spec/ruby/core/range/shared/cover_and_include.rb
index f36a2cef8b..13fc5e1790 100644
--- a/spec/ruby/core/range/shared/cover_and_include.rb
+++ b/spec/ruby/core/range/shared/cover_and_include.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
describe :range_cover_and_include, shared: true do
@@ -20,8 +20,8 @@ describe :range_cover_and_include, shared: true do
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
+ (1..).send(@method, 2.4).should == true
+ (0.5...).send(@method, 2.4).should == true
end
it "returns true if other is an element of self for beginless ranges" do
@@ -29,6 +29,17 @@ describe :range_cover_and_include, shared: true do
(...10.5).send(@method, 2.4).should == true
end
+ it "returns false if values are not comparable" do
+ (1..10).send(@method, nil).should == false
+ (1...10).send(@method, nil).should == false
+
+ (..10).send(@method, nil).should == false
+ (...10).send(@method, nil).should == false
+
+ (1..).send(@method, nil).should == false
+ (1...).send(@method, nil).should == false
+ end
+
it "compares values using <=>" do
rng = (1..5)
m = mock("int")
diff --git a/spec/ruby/core/range/shared/include.rb b/spec/ruby/core/range/shared/include.rb
index c6c5c2becf..15a0e5fb9f 100644
--- a/spec/ruby/core/range/shared/include.rb
+++ b/spec/ruby/core/range/shared/include.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
diff --git a/spec/ruby/core/range/size_spec.rb b/spec/ruby/core/range/size_spec.rb
index a1fe3ce17d..1a3ddd197e 100644
--- a/spec/ruby/core/range/size_spec.rb
+++ b/spec/ruby/core/range/size_spec.rb
@@ -22,16 +22,7 @@ describe "Range#size" do
eval("('z'..)").size.should == nil
end
- ruby_version_is ""..."3.2" do
- it 'returns Float::INFINITY for all beginless ranges' do
- (..1).size.should == Float::INFINITY
- (...0.5).size.should == Float::INFINITY
- (..nil).size.should == Float::INFINITY
- (...'o').size.should == Float::INFINITY
- end
- end
-
- ruby_version_is "3.2"..."3.4" do
+ ruby_version_is ""..."3.4" do
it 'returns Float::INFINITY for all beginless ranges if the end is numeric' do
(..1).size.should == Float::INFINITY
(...0.5).size.should == Float::INFINITY
diff --git a/spec/ruby/core/range/step_spec.rb b/spec/ruby/core/range/step_spec.rb
index 64ea3de4ed..0d0caf746d 100644
--- a/spec/ruby/core/range/step_spec.rb
+++ b/spec/ruby/core/range/step_spec.rb
@@ -10,44 +10,50 @@ describe "Range#step" do
r.step { }.should equal(r)
end
- it "raises TypeError if step" do
- obj = mock("mock")
- -> { (1..10).step(obj) { } }.should raise_error(TypeError)
- end
+ ruby_version_is ""..."3.4" do
+ it "calls #to_int to coerce step to an Integer" do
+ obj = mock("Range#step")
+ obj.should_receive(:to_int).and_return(1)
- it "calls #to_int to coerce step to an Integer" do
- obj = mock("Range#step")
- obj.should_receive(:to_int).and_return(1)
+ (1..2).step(obj) { |x| ScratchPad << x }
+ ScratchPad.recorded.should eql([1, 2])
+ end
- (1..2).step(obj) { |x| ScratchPad << x }
- ScratchPad.recorded.should eql([1, 2])
- end
+ it "raises a TypeError if step does not respond to #to_int" do
+ obj = mock("Range#step non-integer")
- 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
- -> { (1..2).step(obj) { } }.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")
- 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
- -> { (1..2).step(obj) { } }.should raise_error(TypeError)
- end
+ it "raises a TypeError if the first element does not respond to #succ" do
+ obj = mock("Range#step non-comparable")
+ obj.should_receive(:<=>).with(obj).and_return(1)
- it "coerces the argument to integer by invoking to_int" do
- (obj = mock("2")).should_receive(:to_int).and_return(2)
- res = []
- (1..10).step(obj) {|x| res << x}
- res.should == [1, 3, 5, 7, 9]
+ -> { (obj..obj).step { |x| x } }.should raise_error(TypeError)
+ end
end
- it "raises a TypeError if the first element does not respond to #succ" do
- obj = mock("Range#step non-comparable")
- obj.should_receive(:<=>).with(obj).and_return(1)
+ ruby_version_is "3.4" do
+ it "calls #coerce to coerce step to an Integer" do
+ obj = mock("Range#step")
+ obj.should_receive(:coerce).at_least(:once).and_return([1, 2])
+
+ (1..3).step(obj) { |x| ScratchPad << x }
+ ScratchPad.recorded.should eql([1, 3])
+ end
- -> { (obj..obj).step { |x| x } }.should raise_error(TypeError)
+ it "raises a TypeError if step does not respond to #coerce" do
+ obj = mock("Range#step non-coercible")
+
+ -> { (1..2).step(obj) { } }.should raise_error(TypeError)
+ end
end
it "raises an ArgumentError if step is 0" do
@@ -58,8 +64,17 @@ describe "Range#step" do
-> { (-1..1).step(0.0) { |x| x } }.should raise_error(ArgumentError)
end
- it "raises an ArgumentError if step is negative" do
- -> { (-1..1).step(-2) { |x| x } }.should raise_error(ArgumentError)
+ ruby_version_is "3.4" do
+ it "does not raise an ArgumentError if step is 0 for non-numeric ranges" do
+ t = Time.utc(2023, 2, 24)
+ -> { (t..t+1).step(0) { break } }.should_not raise_error(ArgumentError)
+ end
+ end
+
+ ruby_version_is ""..."3.4" do
+ it "raises an ArgumentError if step is negative" do
+ -> { (-1..1).step(-2) { |x| x } }.should raise_error(ArgumentError)
+ end
end
describe "with inclusive end" do
@@ -78,6 +93,18 @@ describe "Range#step" do
(-2..2).step(1.5) { |x| ScratchPad << x }
ScratchPad.recorded.should eql([-2.0, -0.5, 1.0])
end
+
+ ruby_version_is "3.4" do
+ it "does not iterate if step is negative for forward range" do
+ (-1..1).step(-1) { |x| ScratchPad << x }
+ ScratchPad.recorded.should eql([])
+ end
+
+ it "iterates backward if step is negative for backward range" do
+ (1..-1).step(-1) { |x| ScratchPad << x }
+ ScratchPad.recorded.should eql([1, 0, -1])
+ end
+ end
end
describe "and Float values" do
@@ -162,13 +189,96 @@ describe "Range#step" do
-> { ("A".."G").step(2.0) { } }.should raise_error(TypeError)
end
- it "calls #succ on begin and each element returned by #succ" do
- obj = mock("Range#step String start")
- obj.should_receive(:<=>).exactly(3).times.and_return(-1, -1, -1, 0)
- obj.should_receive(:succ).exactly(2).times.and_return(obj)
+ ruby_version_is ""..."3.4" do
+ it "calls #succ on begin and each element returned by #succ" do
+ obj = mock("Range#step String start")
+ obj.should_receive(:<=>).exactly(3).times.and_return(-1, -1, -1, 0)
+ obj.should_receive(:succ).exactly(2).times.and_return(obj)
+
+ (obj..obj).step { |x| ScratchPad << x }
+ ScratchPad.recorded.should == [obj, obj, obj]
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "yields String values adjusted by step and less than or equal to end" do
+ ("A".."AAA").step("A") { |x| ScratchPad << x }
+ ScratchPad.recorded.should == ["A", "AA", "AAA"]
+ end
+
+ it "raises a TypeError when passed an incompatible type step" do
+ -> { ("A".."G").step([]) { } }.should raise_error(TypeError)
+ end
+
+ it "calls #+ on begin and each element returned by #+" do
+ start = mock("Range#step String start")
+ stop = mock("Range#step String stop")
+
+ mid1 = mock("Range#step String mid1")
+ mid2 = mock("Range#step String mid2")
+
+ step = mock("Range#step String step")
+
+ # Deciding on the direction of iteration
+ start.should_receive(:<=>).with(stop).at_least(:twice).and_return(-1)
+ # Deciding whether the step moves iteration in the right direction
+ start.should_receive(:<=>).with(mid1).and_return(-1)
+ # Iteration 1
+ start.should_receive(:+).at_least(:once).with(step).and_return(mid1)
+ # Iteration 2
+ mid1.should_receive(:<=>).with(stop).and_return(-1)
+ mid1.should_receive(:+).with(step).and_return(mid2)
+ # Iteration 3
+ mid2.should_receive(:<=>).with(stop).and_return(0)
+
+ (start..stop).step(step) { |x| ScratchPad << x }
+ ScratchPad.recorded.should == [start, mid1, mid2]
+ end
+
+ it "iterates backward if the step is decreasing values, and the range is backward" do
+ start = mock("Range#step String start")
+ stop = mock("Range#step String stop")
+
+ mid1 = mock("Range#step String mid1")
+ mid2 = mock("Range#step String mid2")
+
+ step = mock("Range#step String step")
+
+ # Deciding on the direction of iteration
+ start.should_receive(:<=>).with(stop).at_least(:twice).and_return(1)
+ # Deciding whether the step moves iteration in the right direction
+ start.should_receive(:<=>).with(mid1).and_return(1)
+ # Iteration 1
+ start.should_receive(:+).at_least(:once).with(step).and_return(mid1)
+ # Iteration 2
+ mid1.should_receive(:<=>).with(stop).and_return(1)
+ mid1.should_receive(:+).with(step).and_return(mid2)
+ # Iteration 3
+ mid2.should_receive(:<=>).with(stop).and_return(0)
+
+ (start..stop).step(step) { |x| ScratchPad << x }
+ ScratchPad.recorded.should == [start, mid1, mid2]
+ end
+
+ it "does no iteration of the direction of the range and of the step don't match" do
+ start = mock("Range#step String start")
+ stop = mock("Range#step String stop")
- (obj..obj).step { |x| ScratchPad << x }
- ScratchPad.recorded.should == [obj, obj, obj]
+ mid1 = mock("Range#step String mid1")
+ mid2 = mock("Range#step String mid2")
+
+ step = mock("Range#step String step")
+
+ # Deciding on the direction of iteration: stop > start
+ start.should_receive(:<=>).with(stop).at_least(:twice).and_return(1)
+ # Deciding whether the step moves iteration in the right direction
+ # start + step < start, the direction is opposite to the range's
+ start.should_receive(:+).with(step).and_return(mid1)
+ start.should_receive(:<=>).with(mid1).and_return(-1)
+
+ (start..stop).step(step) { |x| ScratchPad << x }
+ ScratchPad.recorded.should == []
+ end
end
end
end
@@ -212,13 +322,11 @@ describe "Range#step" do
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])
+ 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
+ (1.0...55.6).step(18.2).size.should == 4
end
it "handles infinite values at either end" do
@@ -266,18 +374,31 @@ describe "Range#step" do
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
- ("A"..."E").step { |x| ScratchPad << x }
- ScratchPad.recorded.should == ["A", "B", "C", "D"]
- end
+ ruby_version_is ""..."3.4" do
+ it "yields String values incremented by #succ and less than or equal to end when not passed a step" do
+ ("A"..."E").step { |x| ScratchPad << x }
+ ScratchPad.recorded.should == ["A", "B", "C", "D"]
+ end
- it "yields String values incremented by #succ called Integer step times" do
- ("A"..."G").step(2) { |x| ScratchPad << x }
- ScratchPad.recorded.should == ["A", "C", "E"]
+ it "yields String values incremented by #succ called Integer step times" do
+ ("A"..."G").step(2) { |x| ScratchPad << x }
+ ScratchPad.recorded.should == ["A", "C", "E"]
+ end
+
+ it "raises a TypeError when passed a Float step" do
+ -> { ("A"..."G").step(2.0) { } }.should raise_error(TypeError)
+ end
end
- it "raises a TypeError when passed a Float step" do
- -> { ("A"..."G").step(2.0) { } }.should raise_error(TypeError)
+ ruby_version_is "3.4" do
+ it "yields String values adjusted by step and less than or equal to end" do
+ ("A"..."AAA").step("A") { |x| ScratchPad << x }
+ ScratchPad.recorded.should == ["A", "AA"]
+ end
+
+ it "raises a TypeError when passed an incompatible type step" do
+ -> { ("A".."G").step([]) { } }.should raise_error(TypeError)
+ end
end
end
end
@@ -285,93 +406,109 @@ describe "Range#step" do
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 }
+ (-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 }
+ (-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 }
+ (-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 }
+ (-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 }
+ (-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 }
+ (-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 }
+ (-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 }
+ (-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 }
+ (-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 }
+ (-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 }
+ (-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 }
+ (-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 }
+ (-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 }
+ (-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 }
+ ('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 }
+ ('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 }
+ ('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 }
+ ('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)
+ -> { ('A'..).step(2.0) { } }.should raise_error(TypeError)
+ -> { ('A'...).step(2.0) { } }.should raise_error(TypeError)
+ end
+
+ ruby_version_is "3.4" do
+ it "yields String values adjusted by step" do
+ ('A'..).step("A") { |x| break if x > "AAA"; ScratchPad << x }
+ ScratchPad.recorded.should == ["A", "AA", "AAA"]
+
+ ScratchPad.record []
+ ('A'...).step("A") { |x| break if x > "AAA"; ScratchPad << x }
+ ScratchPad.recorded.should == ["A", "AA", "AAA"]
+ end
+
+ it "raises a TypeError when passed an incompatible type step" do
+ -> { ('A'..).step([]) { } }.should raise_error(TypeError)
+ -> { ('A'...).step([]) { } }.should raise_error(TypeError)
+ end
end
end
end
@@ -383,15 +520,24 @@ describe "Range#step" do
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")
- -> { (1..2).step(obj) }.should raise_error(TypeError)
+ ruby_version_is ""..."3.4" 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 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
- 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)
+ ruby_version_is "3.4" do
+ it "does not raise if step is incompatible" do
+ obj = mock("Range#step non-integer")
+ -> { (1..2).step(obj) }.should_not raise_error
+ end
end
it "returns the ceil of range size divided by the number of steps" do
@@ -431,19 +577,36 @@ describe "Range#step" do
(1.0...6.4).step(1.8).size.should == 3
end
- it "returns nil with begin and end are String" do
- ("A".."E").step(2).size.should == nil
- ("A"..."E").step(2).size.should == nil
- ("A".."E").step.size.should == nil
- ("A"..."E").step.size.should == nil
+ ruby_version_is ""..."3.4" do
+ it "returns nil with begin and end are String" do
+ ("A".."E").step(2).size.should == nil
+ ("A"..."E").step(2).size.should == nil
+ ("A".."E").step.size.should == nil
+ ("A"..."E").step.size.should == nil
+ end
+
+ it "return nil and not raises a TypeError if the first element does not respond to #succ" do
+ obj = mock("Range#step non-comparable")
+ obj.should_receive(:<=>).with(obj).and_return(1)
+ enum = (obj..obj).step
+ -> { enum.size }.should_not raise_error
+ enum.size.should == nil
+ end
end
- it "return nil and not raises a TypeError if the first element does not respond to #succ" do
- obj = mock("Range#step non-comparable")
- obj.should_receive(:<=>).with(obj).and_return(1)
- enum = (obj..obj).step
- -> { enum.size }.should_not raise_error
- enum.size.should == nil
+ ruby_version_is "3.4" do
+ it "returns nil with begin and end are String" do
+ ("A".."E").step("A").size.should == nil
+ ("A"..."E").step("A").size.should == nil
+ end
+
+ it "return nil and not raises a TypeError if the first element is not of compatible type" do
+ obj = mock("Range#step non-comparable")
+ obj.should_receive(:<=>).with(obj).and_return(1)
+ enum = (obj..obj).step(obj)
+ -> { enum.size }.should_not raise_error
+ enum.size.should == nil
+ end
end
end
@@ -470,22 +633,48 @@ describe "Range#step" do
(1..).step(2).take(3).should == [1, 3, 5]
end
- it "returns an instance of Enumerator when begin is not numeric" do
- ("a"..).step.class.should == Enumerator
- ("a"..).step(2).take(3).should == %w[a c e]
+ ruby_version_is ""..."3.4" do
+ it "returns an instance of Enumerator when begin is not numeric" do
+ ("a"..).step.class.should == Enumerator
+ ("a"..).step(2).take(3).should == %w[a c e]
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "returns an instance of Enumerator when begin is not numeric" do
+ ("a"..).step("a").class.should == Enumerator
+ ("a"..).step("a").take(3).should == %w[a aa aaa]
+ end
end
end
context "when range is beginless and endless" do
- it "returns an instance of Enumerator" do
- Range.new(nil, nil).step.class.should == Enumerator
+ ruby_version_is ""..."3.4" do
+ it "returns an instance of Enumerator" do
+ Range.new(nil, nil).step.class.should == Enumerator
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "raises an ArgumentError" do
+ -> { Range.new(nil, nil).step(1) }.should raise_error(ArgumentError)
+ 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
- ("a".."z").step(3).take(4).should == %w[a d g j]
+ ruby_version_is ""..."3.4" do
+ it "returns an instance of Enumerator" do
+ ("a".."z").step.class.should == Enumerator
+ ("a".."z").step(3).take(4).should == %w[a d g j]
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "returns an instance of Enumerator" do
+ ("a".."z").step("a").class.should == Enumerator
+ ("a".."z").step("a").take(4).should == %w[a aa aaa aaaa]
+ end
end
end
end
diff --git a/spec/ruby/core/range/to_set_spec.rb b/spec/ruby/core/range/to_set_spec.rb
new file mode 100644
index 0000000000..589c0e9aed
--- /dev/null
+++ b/spec/ruby/core/range/to_set_spec.rb
@@ -0,0 +1,55 @@
+require_relative '../../spec_helper'
+require_relative '../enumerable/fixtures/classes'
+
+describe "Enumerable#to_set" do
+ it "returns a new Set created from self" do
+ (1..4).to_set.should == Set[1, 2, 3, 4]
+ (1...4).to_set.should == Set[1, 2, 3]
+ end
+
+ it "passes down passed blocks" do
+ (1..3).to_set { |x| x * x }.should == Set[1, 4, 9]
+ end
+
+ ruby_version_is "4.0" do
+ it "raises a RangeError if the range is infinite" do
+ -> { (1..).to_set }.should raise_error(RangeError, "cannot convert endless range to a set")
+ -> { (1...).to_set }.should raise_error(RangeError, "cannot convert endless range to a set")
+ end
+ end
+
+ ruby_version_is ""..."4.0" do
+ it "instantiates an object of provided as the first argument set class" do
+ set = (1..3).to_set(EnumerableSpecs::SetSubclass)
+ set.should be_kind_of(EnumerableSpecs::SetSubclass)
+ set.to_a.sort.should == [1, 2, 3]
+ end
+ end
+
+ ruby_version_is "4.0"..."4.1" do
+ it "instantiates an object of provided as the first argument set class and warns" do
+ set = nil
+ proc {
+ set = (1..3).to_set(EnumerableSpecs::SetSubclass)
+ }.should complain(/Enumerable#to_set/)
+ set.should be_kind_of(EnumerableSpecs::SetSubclass)
+ set.to_a.sort.should == [1, 2, 3]
+ end
+ end
+
+ ruby_version_is "4.1" do
+ it "does not accept any positional argument" do
+ -> {
+ (1..3).to_set(EnumerableSpecs::SetSubclass)
+ }.should raise_error(ArgumentError, 'wrong number of arguments (given 1, expected 0)')
+ end
+ end
+
+ it "does not need explicit `require 'set'`" do
+ output = ruby_exe(<<~RUBY, options: '--disable-gems', args: '2>&1')
+ puts (1..3).to_set.to_a.inspect
+ RUBY
+
+ output.chomp.should == "[1, 2, 3]"
+ end
+end
diff --git a/spec/ruby/core/rational/abs_spec.rb b/spec/ruby/core/rational/abs_spec.rb
index 7272ad2422..54099aa14d 100644
--- a/spec/ruby/core/rational/abs_spec.rb
+++ b/spec/ruby/core/rational/abs_spec.rb
@@ -1,5 +1,5 @@
require_relative "../../spec_helper"
-require_relative '../../shared/rational/abs'
+require_relative 'shared/abs'
describe "Rational#abs" do
it_behaves_like :rational_abs, :abs
diff --git a/spec/ruby/core/rational/ceil_spec.rb b/spec/ruby/core/rational/ceil_spec.rb
index e736351604..d5bdadf3b6 100644
--- a/spec/ruby/core/rational/ceil_spec.rb
+++ b/spec/ruby/core/rational/ceil_spec.rb
@@ -1,6 +1,45 @@
require_relative "../../spec_helper"
-require_relative '../../shared/rational/ceil'
describe "Rational#ceil" do
- it_behaves_like :rational_ceil, :ceil
+ before do
+ @rational = Rational(2200, 7)
+ end
+
+ describe "with no arguments (precision = 0)" do
+ it "returns an Integer" do
+ @rational.ceil.should be_kind_of(Integer)
+ end
+
+ it "returns the truncated value toward positive infinity" do
+ @rational.ceil.should == 315
+ Rational(1, 2).ceil.should == 1
+ Rational(-1, 2).ceil.should == 0
+ end
+ end
+
+ describe "with a precision < 0" do
+ it "returns an Integer" do
+ @rational.ceil(-2).should be_kind_of(Integer)
+ @rational.ceil(-1).should be_kind_of(Integer)
+ end
+
+ it "moves the truncation point n decimal places left" do
+ @rational.ceil(-3).should == 1000
+ @rational.ceil(-2).should == 400
+ @rational.ceil(-1).should == 320
+ end
+ end
+
+ describe "with precision > 0" do
+ it "returns a Rational" do
+ @rational.ceil(1).should be_kind_of(Rational)
+ @rational.ceil(2).should be_kind_of(Rational)
+ end
+
+ it "moves the truncation point n decimal places right" do
+ @rational.ceil(1).should == Rational(3143, 10)
+ @rational.ceil(2).should == Rational(31429, 100)
+ @rational.ceil(3).should == Rational(157143, 500)
+ end
+ end
end
diff --git a/spec/ruby/core/rational/comparison_spec.rb b/spec/ruby/core/rational/comparison_spec.rb
index 877069fb8f..c9db60d5c7 100644
--- a/spec/ruby/core/rational/comparison_spec.rb
+++ b/spec/ruby/core/rational/comparison_spec.rb
@@ -1,23 +1,93 @@
require_relative "../../spec_helper"
-require_relative '../../shared/rational/comparison'
+require_relative 'fixtures/rational'
describe "Rational#<=> when passed a Rational object" do
- it_behaves_like :rational_cmp_rat, :<=>
+ it "returns 1 when self is greater than the passed argument" do
+ (Rational(4, 4) <=> Rational(3, 4)).should equal(1)
+ (Rational(-3, 4) <=> Rational(-4, 4)).should equal(1)
+ end
+
+ it "returns 0 when self is equal to the passed argument" do
+ (Rational(4, 4) <=> Rational(4, 4)).should equal(0)
+ (Rational(-3, 4) <=> Rational(-3, 4)).should equal(0)
+ end
+
+ it "returns -1 when self is less than the passed argument" do
+ (Rational(3, 4) <=> Rational(4, 4)).should equal(-1)
+ (Rational(-4, 4) <=> Rational(-3, 4)).should equal(-1)
+ end
end
describe "Rational#<=> when passed an Integer object" do
- it_behaves_like :rational_cmp_int, :<=>
+ it "returns 1 when self is greater than the passed argument" do
+ (Rational(4, 4) <=> 0).should equal(1)
+ (Rational(4, 4) <=> -10).should equal(1)
+ (Rational(-3, 4) <=> -1).should equal(1)
+ end
+
+ it "returns 0 when self is equal to the passed argument" do
+ (Rational(4, 4) <=> 1).should equal(0)
+ (Rational(-8, 4) <=> -2).should equal(0)
+ end
+
+ it "returns -1 when self is less than the passed argument" do
+ (Rational(3, 4) <=> 1).should equal(-1)
+ (Rational(-4, 4) <=> 0).should equal(-1)
+ end
end
describe "Rational#<=> when passed a Float object" do
- it_behaves_like :rational_cmp_float, :<=>
+ it "returns 1 when self is greater than the passed argument" do
+ (Rational(4, 4) <=> 0.5).should equal(1)
+ (Rational(4, 4) <=> -1.5).should equal(1)
+ (Rational(-3, 4) <=> -0.8).should equal(1)
+ end
+
+ it "returns 0 when self is equal to the passed argument" do
+ (Rational(4, 4) <=> 1.0).should equal(0)
+ (Rational(-6, 4) <=> -1.5).should equal(0)
+ end
+
+ it "returns -1 when self is less than the passed argument" do
+ (Rational(3, 4) <=> 1.2).should equal(-1)
+ (Rational(-4, 4) <=> 0.5).should equal(-1)
+ end
end
describe "Rational#<=> when passed an Object that responds to #coerce" do
- it_behaves_like :rational_cmp_coerce, :<=>
- it_behaves_like :rational_cmp_coerce_exception, :<=>
+ it "calls #coerce on the passed argument with self" do
+ rational = Rational(3, 4)
+
+ obj = mock("Object")
+ obj.should_receive(:coerce).with(rational).and_return([1, 2])
+
+ rational <=> obj
+ end
+
+ it "calls #<=> on the coerced Rational with the coerced Object" do
+ rational = Rational(3, 4)
+
+ coerced_rational = mock("Coerced Rational")
+ coerced_rational.should_receive(:<=>).and_return(:result)
+
+ coerced_obj = mock("Coerced Object")
+
+ obj = mock("Object")
+ obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj])
+
+ (rational <=> obj).should == :result
+ end
+
+ 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
end
describe "Rational#<=> when passed a non-Numeric Object that doesn't respond to #coerce" do
- it_behaves_like :rational_cmp_other, :<=>
+ it "returns nil" do
+ (Rational <=> mock("Object")).should be_nil
+ end
end
diff --git a/spec/ruby/core/rational/denominator_spec.rb b/spec/ruby/core/rational/denominator_spec.rb
index c2f49b4190..4687244893 100644
--- a/spec/ruby/core/rational/denominator_spec.rb
+++ b/spec/ruby/core/rational/denominator_spec.rb
@@ -1,6 +1,14 @@
require_relative "../../spec_helper"
-require_relative '../../shared/rational/denominator'
describe "Rational#denominator" do
- it_behaves_like :rational_denominator, :denominator
+ it "returns the denominator" do
+ Rational(3, 4).denominator.should equal(4)
+ Rational(3, -4).denominator.should equal(4)
+
+ Rational(1, bignum_value).denominator.should == bignum_value
+ end
+
+ it "returns 1 if no denominator was given" do
+ Rational(80).denominator.should == 1
+ end
end
diff --git a/spec/ruby/core/rational/div_spec.rb b/spec/ruby/core/rational/div_spec.rb
index bee7d01a67..d3adb9b536 100644
--- a/spec/ruby/core/rational/div_spec.rb
+++ b/spec/ruby/core/rational/div_spec.rb
@@ -1,18 +1,54 @@
require_relative "../../spec_helper"
-require_relative '../../shared/rational/div'
describe "Rational#div" do
- it_behaves_like :rational_div, :div
+ it "returns an Integer" do
+ Rational(229, 21).div(82).should be_kind_of(Integer)
+ end
+
+ it "raises an ArgumentError if passed more than one argument" do
+ -> { Rational(3, 4).div(2,3) }.should raise_error(ArgumentError)
+ end
+
+ # See http://redmine.ruby-lang.org/issues/show/1648
+ it "raises a TypeError if passed a non-numeric argument" do
+ -> { Rational(3, 4).div([]) }.should raise_error(TypeError)
+ end
end
describe "Rational#div passed a Rational" do
- it_behaves_like :rational_div_rat, :div
+ it "performs integer division and returns the result" do
+ Rational(2, 3).div(Rational(2, 3)).should == 1
+ Rational(-2, 9).div(Rational(-9, 2)).should == 0
+ end
+
+ it "raises a ZeroDivisionError when the argument has a numerator of 0" do
+ -> { Rational(3, 4).div(Rational(0, 3)) }.should raise_error(ZeroDivisionError)
+ end
+
+ it "raises a ZeroDivisionError when the argument has a numerator of 0.0" do
+ -> { Rational(3, 4).div(Rational(0.0, 3)) }.should raise_error(ZeroDivisionError)
+ end
end
describe "Rational#div passed an Integer" do
- it_behaves_like :rational_div_int, :div
+ it "performs integer division and returns the result" do
+ Rational(2, 1).div(1).should == 2
+ Rational(25, 5).div(-50).should == -1
+ end
+
+ it "raises a ZeroDivisionError when the argument is 0" do
+ -> { Rational(3, 4).div(0) }.should raise_error(ZeroDivisionError)
+ end
end
describe "Rational#div passed a Float" do
- it_behaves_like :rational_div_float, :div
+ it "performs integer division and returns the result" do
+ Rational(2, 3).div(30.333).should == 0
+ Rational(2, 9).div(Rational(-8.6)).should == -1
+ Rational(3.12).div(0.5).should == 6
+ end
+
+ it "raises a ZeroDivisionError when the argument is 0.0" do
+ -> { Rational(3, 4).div(0.0) }.should raise_error(ZeroDivisionError)
+ end
end
diff --git a/spec/ruby/core/rational/divide_spec.rb b/spec/ruby/core/rational/divide_spec.rb
index 14e8c4c195..8f5ca1fdec 100644
--- a/spec/ruby/core/rational/divide_spec.rb
+++ b/spec/ruby/core/rational/divide_spec.rb
@@ -1,20 +1,74 @@
require_relative "../../spec_helper"
-require_relative '../../shared/rational/divide'
-require_relative '../../shared/rational/arithmetic_exception_in_coerce'
+require_relative 'shared/arithmetic_exception_in_coerce'
describe "Rational#/" do
- it_behaves_like :rational_divide, :/
+ it "calls #coerce on the passed argument with self" do
+ rational = Rational(3, 4)
+ obj = mock("Object")
+ obj.should_receive(:coerce).with(rational).and_return([1, 2])
+
+ rational / obj
+ end
+
+ it "calls #/ on the coerced Rational with the coerced Object" do
+ rational = Rational(3, 4)
+
+ coerced_rational = mock("Coerced Rational")
+ coerced_rational.should_receive(:/).and_return(:result)
+
+ coerced_obj = mock("Coerced Object")
+
+ obj = mock("Object")
+ obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj])
+
+ (rational / obj).should == :result
+ end
+
it_behaves_like :rational_arithmetic_exception_in_coerce, :/
end
describe "Rational#/ when passed an Integer" do
- it_behaves_like :rational_divide_int, :/
+ it "returns self divided by other as a Rational" do
+ (Rational(3, 4) / 2).should eql(Rational(3, 8))
+ (Rational(2, 4) / 2).should eql(Rational(1, 4))
+ (Rational(6, 7) / -2).should eql(Rational(-3, 7))
+ end
+
+ it "raises a ZeroDivisionError when passed 0" do
+ -> { Rational(3, 4) / 0 }.should raise_error(ZeroDivisionError)
+ end
end
describe "Rational#/ when passed a Rational" do
- it_behaves_like :rational_divide_rat, :/
+ it "returns self divided by other as a Rational" do
+ (Rational(3, 4) / Rational(3, 4)).should eql(Rational(1, 1))
+ (Rational(2, 4) / Rational(1, 4)).should eql(Rational(2, 1))
+
+ (Rational(2, 4) / 2).should == Rational(1, 4)
+ (Rational(6, 7) / -2).should == Rational(-3, 7)
+ end
+
+ it "raises a ZeroDivisionError when passed a Rational with a numerator of 0" do
+ -> { Rational(3, 4) / Rational(0, 1) }.should raise_error(ZeroDivisionError)
+ end
end
describe "Rational#/ when passed a Float" do
- it_behaves_like :rational_divide_float, :/
+ it "returns self divided by other as a Float" do
+ (Rational(3, 4) / 0.75).should eql(1.0)
+ (Rational(3, 4) / 0.25).should eql(3.0)
+ (Rational(3, 4) / 0.3).should eql(2.5)
+
+ (Rational(-3, 4) / 0.3).should eql(-2.5)
+ (Rational(3, -4) / 0.3).should eql(-2.5)
+ (Rational(3, 4) / -0.3).should eql(-2.5)
+ end
+
+ it "returns infinity when passed 0" do
+ (Rational(3, 4) / 0.0).infinite?.should eql(1)
+ (Rational(-3, -4) / 0.0).infinite?.should eql(1)
+
+ (Rational(-3, 4) / 0.0).infinite?.should eql(-1)
+ (Rational(3, -4) / 0.0).infinite?.should eql(-1)
+ end
end
diff --git a/spec/ruby/core/rational/divmod_spec.rb b/spec/ruby/core/rational/divmod_spec.rb
index 7ffdde74f4..f0555294a3 100644
--- a/spec/ruby/core/rational/divmod_spec.rb
+++ b/spec/ruby/core/rational/divmod_spec.rb
@@ -1,14 +1,42 @@
require_relative "../../spec_helper"
-require_relative '../../shared/rational/divmod'
describe "Rational#divmod when passed a Rational" do
- it_behaves_like :rational_divmod_rat, :divmod
+ it "returns the quotient as Integer and the remainder as Rational" do
+ Rational(7, 4).divmod(Rational(1, 2)).should eql([3, Rational(1, 4)])
+ Rational(7, 4).divmod(Rational(-1, 2)).should eql([-4, Rational(-1, 4)])
+ Rational(0, 4).divmod(Rational(4, 3)).should eql([0, Rational(0, 1)])
+
+ Rational(bignum_value, 4).divmod(Rational(4, 3)).should eql([3458764513820540928, Rational(0, 1)])
+ end
+
+ 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
describe "Rational#divmod when passed an Integer" do
- it_behaves_like :rational_divmod_int, :divmod
+ it "returns the quotient as Integer and the remainder as Rational" do
+ Rational(7, 4).divmod(2).should eql([0, Rational(7, 4)])
+ Rational(7, 4).divmod(-2).should eql([-1, Rational(-1, 4)])
+
+ Rational(bignum_value, 4).divmod(3).should eql([1537228672809129301, Rational(1, 1)])
+ end
+
+ it "raises a ZeroDivisionError when passed 0" do
+ -> { Rational(7, 4).divmod(0) }.should raise_error(ZeroDivisionError)
+ end
end
describe "Rational#divmod when passed a Float" do
- it_behaves_like :rational_divmod_float, :divmod
+ it "returns the quotient as Integer and the remainder as Float" do
+ Rational(7, 4).divmod(0.5).should eql([3, 0.25])
+ end
+
+ it "returns the quotient as Integer and the remainder as Float" do
+ Rational(7, 4).divmod(-0.5).should eql([-4, -0.25])
+ end
+
+ it "raises a ZeroDivisionError when passed 0" do
+ -> { Rational(7, 4).divmod(0.0) }.should raise_error(ZeroDivisionError)
+ end
end
diff --git a/spec/ruby/core/rational/equal_value_spec.rb b/spec/ruby/core/rational/equal_value_spec.rb
index c6f7f4c6a2..ba40d29c3b 100644
--- a/spec/ruby/core/rational/equal_value_spec.rb
+++ b/spec/ruby/core/rational/equal_value_spec.rb
@@ -1,18 +1,39 @@
require_relative "../../spec_helper"
-require_relative '../../shared/rational/equal_value'
describe "Rational#==" do
- it_behaves_like :rational_equal_value, :==
+ it "returns the result of calling #== with self on the passed argument" do
+ obj = mock("Object")
+ obj.should_receive(:==).and_return(:result)
+
+ (Rational(3, 4) == obj).should_not be_false
+ end
end
describe "Rational#== when passed a Rational" do
- it_behaves_like :rational_equal_value_rat, :==
+ it "returns true if self has the same numerator and denominator as the passed argument" do
+ (Rational(3, 4) == Rational(3, 4)).should be_true
+ (Rational(-3, -4) == Rational(3, 4)).should be_true
+ (Rational(-4, 5) == Rational(4, -5)).should be_true
+
+ (Rational(bignum_value, 3) == Rational(bignum_value, 3)).should be_true
+ (Rational(-bignum_value, 3) == Rational(bignum_value, -3)).should be_true
+ end
end
describe "Rational#== when passed a Float" do
- it_behaves_like :rational_equal_value_float, :==
+ it "converts self to a Float and compares it with the passed argument" do
+ (Rational(3, 4) == 0.75).should be_true
+ (Rational(4, 2) == 2.0).should be_true
+ (Rational(-4, 2) == -2.0).should be_true
+ (Rational(4, -2) == -2.0).should be_true
+ end
end
describe "Rational#== when passed an Integer" do
- it_behaves_like :rational_equal_value_int, :==
+ it "returns true if self has the passed argument as numerator and a denominator of 1" do
+ # Rational(x, y) reduces x and y automatically
+ (Rational(4, 2) == 2).should be_true
+ (Rational(-4, 2) == -2).should be_true
+ (Rational(4, -2) == -2).should be_true
+ end
end
diff --git a/spec/ruby/core/rational/exponent_spec.rb b/spec/ruby/core/rational/exponent_spec.rb
index 7e35b4ebc1..65fbf2ed1c 100644
--- a/spec/ruby/core/rational/exponent_spec.rb
+++ b/spec/ruby/core/rational/exponent_spec.rb
@@ -1,6 +1,236 @@
require_relative "../../spec_helper"
-require_relative '../../shared/rational/exponent'
describe "Rational#**" do
- it_behaves_like :rational_exponent, :**
+ describe "when passed Rational" do
+ # Guard against the Mathn library
+ guard -> { !defined?(Math.rsqrt) } do
+ it "returns Rational(1) if the exponent is Rational(0)" do
+ (Rational(0) ** Rational(0)).should eql(Rational(1))
+ (Rational(1) ** Rational(0)).should eql(Rational(1))
+ (Rational(3, 4) ** Rational(0)).should eql(Rational(1))
+ (Rational(-1) ** Rational(0)).should eql(Rational(1))
+ (Rational(-3, 4) ** Rational(0)).should eql(Rational(1))
+ (Rational(bignum_value) ** Rational(0)).should eql(Rational(1))
+ (Rational(-bignum_value) ** Rational(0)).should eql(Rational(1))
+ end
+
+ it "returns self raised to the argument as a Rational if the exponent's denominator is 1" do
+ (Rational(3, 4) ** Rational(1, 1)).should eql(Rational(3, 4))
+ (Rational(3, 4) ** Rational(2, 1)).should eql(Rational(9, 16))
+ (Rational(3, 4) ** Rational(-1, 1)).should eql(Rational(4, 3))
+ (Rational(3, 4) ** Rational(-2, 1)).should eql(Rational(16, 9))
+ end
+
+ it "returns self raised to the argument as a Float if the exponent's denominator is not 1" do
+ (Rational(3, 4) ** Rational(4, 3)).should be_close(0.681420222312052, TOLERANCE)
+ (Rational(3, 4) ** Rational(-4, 3)).should be_close(1.46752322173095, TOLERANCE)
+ (Rational(3, 4) ** Rational(4, -3)).should be_close(1.46752322173095, TOLERANCE)
+ end
+
+ it "returns a complex number when self is negative and the passed argument is not 0" do
+ (Rational(-3, 4) ** Rational(-4, 3)).should be_close(Complex(-0.7337616108654732, 1.2709123906625817), TOLERANCE)
+ end
+ end
+ end
+
+ describe "when passed Integer" do
+ it "returns the Rational value of self raised to the passed argument" do
+ (Rational(3, 4) ** 4).should == Rational(81, 256)
+ (Rational(3, 4) ** -4).should == Rational(256, 81)
+ (Rational(-3, 4) ** -4).should == Rational(256, 81)
+ (Rational(3, -4) ** -4).should == Rational(256, 81)
+
+ (Rational(bignum_value, 4) ** 4).should == Rational(452312848583266388373324160190187140051835877600158453279131187530910662656, 1)
+ (Rational(3, bignum_value) ** -4).should == Rational(115792089237316195423570985008687907853269984665640564039457584007913129639936, 81)
+ (Rational(-bignum_value, 4) ** -4).should == Rational(1, 452312848583266388373324160190187140051835877600158453279131187530910662656)
+ (Rational(3, -bignum_value) ** -4).should == Rational(115792089237316195423570985008687907853269984665640564039457584007913129639936, 81)
+ end
+
+ # Guard against the Mathn library
+ guard -> { !defined?(Math.rsqrt) } do
+ it "returns Rational(1, 1) when the passed argument is 0" do
+ (Rational(3, 4) ** 0).should eql(Rational(1, 1))
+ (Rational(-3, 4) ** 0).should eql(Rational(1, 1))
+ (Rational(3, -4) ** 0).should eql(Rational(1, 1))
+
+ (Rational(bignum_value, 4) ** 0).should eql(Rational(1, 1))
+ (Rational(3, -bignum_value) ** 0).should eql(Rational(1, 1))
+ end
+ end
+ end
+
+ describe "when passed Bignum" do
+ # #5713
+ it "returns Rational(0) when self is Rational(0) and the exponent is positive" do
+ (Rational(0) ** bignum_value).should eql(Rational(0))
+ end
+
+ it "raises ZeroDivisionError when self is Rational(0) and the exponent is negative" do
+ -> { Rational(0) ** -bignum_value }.should raise_error(ZeroDivisionError)
+ end
+
+ it "returns Rational(1) when self is Rational(1)" do
+ (Rational(1) ** bignum_value).should eql(Rational(1))
+ (Rational(1) ** -bignum_value).should eql(Rational(1))
+ end
+
+ it "returns Rational(1) when self is Rational(-1) and the exponent is positive and even" do
+ (Rational(-1) ** bignum_value(0)).should eql(Rational(1))
+ (Rational(-1) ** bignum_value(2)).should eql(Rational(1))
+ end
+
+ it "returns Rational(-1) when self is Rational(-1) and the exponent is positive and odd" do
+ (Rational(-1) ** bignum_value(1)).should eql(Rational(-1))
+ (Rational(-1) ** bignum_value(3)).should eql(Rational(-1))
+ end
+
+ ruby_version_is ""..."3.4" do
+ it "returns positive Infinity when self is > 1" do
+ -> {
+ (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)
+ }.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
+ end
+
+ ruby_version_is "3.4" do
+ it "raises an ArgumentError when self is > 1" do
+ -> {
+ (Rational(2) ** bignum_value)
+ }.should raise_error(ArgumentError)
+ -> {
+ (Rational(fixnum_max) ** bignum_value)
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when self is > 1 and the exponent is negative" do
+ -> {
+ (Rational(2) ** -bignum_value)
+ }.should raise_error(ArgumentError)
+ -> {
+ (Rational(fixnum_max) ** -bignum_value)
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when self is < -1" do
+ -> {
+ (Rational(-2) ** bignum_value)
+ }.should raise_error(ArgumentError)
+ -> {
+ (Rational(fixnum_min) ** bignum_value)
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises an ArgumentError when self is < -1 and the exponent is negative" do
+ -> {
+ (Rational(-2) ** -bignum_value)
+ }.should raise_error(ArgumentError)
+ -> {
+ (Rational(fixnum_min) ** -bignum_value)
+ }.should raise_error(ArgumentError)
+ end
+ 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
+ ruby_version_is ""..."3.4" do
+ it "returns positive Infinity when self < -1" do
+ -> {
+ (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)
+ }.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
+ end
+
+ describe "when passed Float" do
+ it "returns self converted to Float and raised to the passed argument" do
+ (Rational(3, 1) ** 3.0).should eql(27.0)
+ (Rational(3, 1) ** 1.5).should be_close(5.19615242270663, TOLERANCE)
+ (Rational(3, 1) ** -1.5).should be_close(0.192450089729875, TOLERANCE)
+ end
+
+ it "returns a complex number if self is negative and the passed argument is not 0" do
+ (Rational(-3, 2) ** 1.5).should be_close(Complex(0.0, -1.8371173070873836), TOLERANCE)
+ (Rational(3, -2) ** 1.5).should be_close(Complex(0.0, -1.8371173070873836), TOLERANCE)
+ (Rational(3, -2) ** -1.5).should be_close(Complex(0.0, 0.5443310539518174), TOLERANCE)
+ end
+
+ it "returns Complex(1.0) when the passed argument is 0.0" do
+ (Rational(3, 4) ** 0.0).should == Complex(1.0)
+ (Rational(-3, 4) ** 0.0).should == Complex(1.0)
+ (Rational(-3, 4) ** 0.0).should == Complex(1.0)
+ end
+ end
+
+ it "calls #coerce on the passed argument with self" do
+ rational = Rational(3, 4)
+ obj = mock("Object")
+ obj.should_receive(:coerce).with(rational).and_return([1, 2])
+
+ rational ** obj
+ end
+
+ it "calls #** on the coerced Rational with the coerced Object" do
+ rational = Rational(3, 4)
+
+ coerced_rational = mock("Coerced Rational")
+ coerced_rational.should_receive(:**).and_return(:result)
+
+ coerced_obj = mock("Coerced Object")
+
+ obj = mock("Object")
+ obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj])
+
+ (rational ** obj).should == :result
+ end
+
+ it "raises ZeroDivisionError for Rational(0, 1) passed a negative Integer" do
+ [-1, -4, -9999].each do |exponent|
+ -> { Rational(0, 1) ** exponent }.should raise_error(ZeroDivisionError, "divided by 0")
+ end
+ end
+
+ it "raises ZeroDivisionError for Rational(0, 1) passed a negative Rational with denominator 1" do
+ [Rational(-1, 1), Rational(-3, 1)].each do |exponent|
+ -> { Rational(0, 1) ** exponent }.should raise_error(ZeroDivisionError, "divided by 0")
+ end
+ end
+
+ # #7513
+ it "raises ZeroDivisionError for Rational(0, 1) passed a negative Rational" do
+ -> { Rational(0, 1) ** Rational(-3, 2) }.should raise_error(ZeroDivisionError, "divided by 0")
+ end
+
+ it "returns Infinity for Rational(0, 1) passed a negative Float" do
+ [-1.0, -3.0, -3.14].each do |exponent|
+ (Rational(0, 1) ** exponent).infinite?.should == 1
+ end
+ end
end
diff --git a/spec/ruby/core/rational/fdiv_spec.rb b/spec/ruby/core/rational/fdiv_spec.rb
index b75f39abd5..118d93dbe7 100644
--- a/spec/ruby/core/rational/fdiv_spec.rb
+++ b/spec/ruby/core/rational/fdiv_spec.rb
@@ -1,6 +1,5 @@
require_relative "../../spec_helper"
-require_relative '../../shared/rational/fdiv'
describe "Rational#fdiv" do
- it_behaves_like :rational_fdiv, :fdiv
+ it "needs to be reviewed for spec completeness"
end
diff --git a/spec/ruby/fixtures/rational.rb b/spec/ruby/core/rational/fixtures/rational.rb
index 844d7f9820..844d7f9820 100644
--- a/spec/ruby/fixtures/rational.rb
+++ b/spec/ruby/core/rational/fixtures/rational.rb
diff --git a/spec/ruby/core/rational/floor_spec.rb b/spec/ruby/core/rational/floor_spec.rb
index 70db0499d0..8068aaf119 100644
--- a/spec/ruby/core/rational/floor_spec.rb
+++ b/spec/ruby/core/rational/floor_spec.rb
@@ -1,6 +1,45 @@
require_relative "../../spec_helper"
-require_relative '../../shared/rational/floor'
describe "Rational#floor" do
- it_behaves_like :rational_floor, :floor
+ before do
+ @rational = Rational(2200, 7)
+ end
+
+ describe "with no arguments (precision = 0)" do
+ it "returns an integer" do
+ @rational.floor.should be_kind_of(Integer)
+ end
+
+ it "returns the truncated value toward negative infinity" do
+ @rational.floor.should == 314
+ Rational(1, 2).floor.should == 0
+ Rational(-1, 2).floor.should == -1
+ end
+ end
+
+ describe "with a precision < 0" do
+ it "returns an integer" do
+ @rational.floor(-2).should be_kind_of(Integer)
+ @rational.floor(-1).should be_kind_of(Integer)
+ end
+
+ it "moves the truncation point n decimal places left" do
+ @rational.floor(-3).should == 0
+ @rational.floor(-2).should == 300
+ @rational.floor(-1).should == 310
+ end
+ end
+
+ describe "with a precision > 0" do
+ it "returns a Rational" do
+ @rational.floor(1).should be_kind_of(Rational)
+ @rational.floor(2).should be_kind_of(Rational)
+ end
+
+ it "moves the truncation point n decimal places right" do
+ @rational.floor(1).should == Rational(1571, 5)
+ @rational.floor(2).should == Rational(7857, 25)
+ @rational.floor(3).should == Rational(62857, 200)
+ end
+ end
end
diff --git a/spec/ruby/core/rational/hash_spec.rb b/spec/ruby/core/rational/hash_spec.rb
index 7e8d30049b..528638056a 100644
--- a/spec/ruby/core/rational/hash_spec.rb
+++ b/spec/ruby/core/rational/hash_spec.rb
@@ -1,6 +1,9 @@
require_relative "../../spec_helper"
-require_relative '../../shared/rational/hash'
describe "Rational#hash" do
- it_behaves_like :rational_hash, :hash
+ # BUG: Rational(2, 3).hash == Rational(3, 2).hash
+ it "is static" do
+ Rational(2, 3).hash.should == Rational(2, 3).hash
+ Rational(2, 4).hash.should_not == Rational(2, 3).hash
+ end
end
diff --git a/spec/ruby/core/rational/inspect_spec.rb b/spec/ruby/core/rational/inspect_spec.rb
index 2cbf6cadc1..edc5cffee9 100644
--- a/spec/ruby/core/rational/inspect_spec.rb
+++ b/spec/ruby/core/rational/inspect_spec.rb
@@ -1,6 +1,14 @@
require_relative "../../spec_helper"
-require_relative '../../shared/rational/inspect'
describe "Rational#inspect" do
- it_behaves_like :rational_inspect, :inspect
+ 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)"
+
+ # Guard against the Mathn library
+ guard -> { !defined?(Math.rsqrt) } do
+ Rational(bignum_value, 1).inspect.should == "(#{bignum_value}/1)"
+ end
+ end
end
diff --git a/spec/ruby/core/rational/magnitude_spec.rb b/spec/ruby/core/rational/magnitude_spec.rb
index 27d9af6a81..f5f667edb1 100644
--- a/spec/ruby/core/rational/magnitude_spec.rb
+++ b/spec/ruby/core/rational/magnitude_spec.rb
@@ -1,5 +1,5 @@
require_relative "../../spec_helper"
-require_relative '../../shared/rational/abs'
+require_relative 'shared/abs'
describe "Rational#abs" do
it_behaves_like :rational_abs, :magnitude
diff --git a/spec/ruby/core/rational/minus_spec.rb b/spec/ruby/core/rational/minus_spec.rb
index a61b62ebe6..8aee85f9dd 100644
--- a/spec/ruby/core/rational/minus_spec.rb
+++ b/spec/ruby/core/rational/minus_spec.rb
@@ -1,5 +1,5 @@
require_relative '../../spec_helper'
-require_relative '../../shared/rational/arithmetic_exception_in_coerce'
+require_relative 'shared/arithmetic_exception_in_coerce'
describe "Rational#-" do
it_behaves_like :rational_arithmetic_exception_in_coerce, :-
diff --git a/spec/ruby/core/rational/modulo_spec.rb b/spec/ruby/core/rational/modulo_spec.rb
index 7a60c176ac..23ed93e118 100644
--- a/spec/ruby/core/rational/modulo_spec.rb
+++ b/spec/ruby/core/rational/modulo_spec.rb
@@ -1,6 +1,43 @@
require_relative "../../spec_helper"
-require_relative '../../shared/rational/modulo'
describe "Rational#%" do
- it_behaves_like :rational_modulo, :%
+ it "returns the remainder when this value is divided by other" do
+ (Rational(2, 3) % Rational(2, 3)).should == Rational(0, 1)
+ (Rational(4, 3) % Rational(2, 3)).should == Rational(0, 1)
+ (Rational(2, -3) % Rational(-2, 3)).should == Rational(0, 1)
+ (Rational(0, -1) % -1).should == Rational(0, 1)
+
+ (Rational(7, 4) % Rational(1, 2)).should == Rational(1, 4)
+ (Rational(7, 4) % 1).should == Rational(3, 4)
+ (Rational(7, 4) % Rational(1, 7)).should == Rational(1, 28)
+
+ (Rational(3, 4) % -1).should == Rational(-1, 4)
+ (Rational(1, -5) % -1).should == Rational(-1, 5)
+ end
+
+ it "returns a Float value when the argument is Float" do
+ (Rational(7, 4) % 1.0).should be_kind_of(Float)
+ (Rational(7, 4) % 1.0).should == 0.75
+ (Rational(7, 4) % 0.26).should be_close(0.19, 0.0001)
+ end
+
+ it "raises ZeroDivisionError on zero denominator" do
+ -> {
+ Rational(3, 5) % Rational(0, 1)
+ }.should raise_error(ZeroDivisionError)
+
+ -> {
+ Rational(0, 1) % Rational(0, 1)
+ }.should raise_error(ZeroDivisionError)
+
+ -> {
+ Rational(3, 5) % 0
+ }.should raise_error(ZeroDivisionError)
+ end
+
+ it "raises a ZeroDivisionError when the argument is 0.0" do
+ -> {
+ Rational(3, 5) % 0.0
+ }.should raise_error(ZeroDivisionError)
+ end
end
diff --git a/spec/ruby/core/rational/multiply_spec.rb b/spec/ruby/core/rational/multiply_spec.rb
index 7413376bb1..87fb4de2b4 100644
--- a/spec/ruby/core/rational/multiply_spec.rb
+++ b/spec/ruby/core/rational/multiply_spec.rb
@@ -1,20 +1,65 @@
require_relative "../../spec_helper"
-require_relative '../../shared/rational/multiply'
-require_relative '../../shared/rational/arithmetic_exception_in_coerce'
+require_relative 'shared/arithmetic_exception_in_coerce'
describe "Rational#*" do
- it_behaves_like :rational_multiply, :*
+ it "calls #coerce on the passed argument with self" do
+ rational = Rational(3, 4)
+ obj = mock("Object")
+ obj.should_receive(:coerce).with(rational).and_return([1, 2])
+
+ rational * obj
+ end
+
+ it "calls #* on the coerced Rational with the coerced Object" do
+ rational = Rational(3, 4)
+
+ coerced_rational = mock("Coerced Rational")
+ coerced_rational.should_receive(:*).and_return(:result)
+
+ coerced_obj = mock("Coerced Object")
+
+ obj = mock("Object")
+ obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj])
+
+ (rational * obj).should == :result
+ end
+
it_behaves_like :rational_arithmetic_exception_in_coerce, :*
end
describe "Rational#* passed a Rational" do
- it_behaves_like :rational_multiply_rat, :*
+ it "returns self divided by other as a Rational" do
+ (Rational(3, 4) * Rational(3, 4)).should eql(Rational(9, 16))
+ (Rational(2, 4) * Rational(1, 4)).should eql(Rational(1, 8))
+
+ (Rational(3, 4) * Rational(0, 1)).should eql(Rational(0, 4))
+ end
end
describe "Rational#* passed a Float" do
- it_behaves_like :rational_multiply_float, :*
+ it "returns self divided by other as a Float" do
+ (Rational(3, 4) * 0.75).should eql(0.5625)
+ (Rational(3, 4) * 0.25).should eql(0.1875)
+ (Rational(3, 4) * 0.3).should be_close(0.225, TOLERANCE)
+
+ (Rational(-3, 4) * 0.3).should be_close(-0.225, TOLERANCE)
+ (Rational(3, -4) * 0.3).should be_close(-0.225, TOLERANCE)
+ (Rational(3, 4) * -0.3).should be_close(-0.225, TOLERANCE)
+
+ (Rational(3, 4) * 0.0).should eql(0.0)
+ (Rational(-3, -4) * 0.0).should eql(0.0)
+
+ (Rational(-3, 4) * 0.0).should eql(0.0)
+ (Rational(3, -4) * 0.0).should eql(0.0)
+ end
end
describe "Rational#* passed an Integer" do
- it_behaves_like :rational_multiply_int, :*
+ it "returns self divided by other as a Rational" do
+ (Rational(3, 4) * 2).should eql(Rational(3, 2))
+ (Rational(2, 4) * 2).should eql(Rational(1, 1))
+ (Rational(6, 7) * -2).should eql(Rational(-12, 7))
+
+ (Rational(3, 4) * 0).should eql(Rational(0, 4))
+ end
end
diff --git a/spec/ruby/core/rational/numerator_spec.rb b/spec/ruby/core/rational/numerator_spec.rb
index 6f9a9c0e3b..2b9fe2ff5c 100644
--- a/spec/ruby/core/rational/numerator_spec.rb
+++ b/spec/ruby/core/rational/numerator_spec.rb
@@ -1,6 +1,10 @@
require_relative "../../spec_helper"
-require_relative '../../shared/rational/numerator'
describe "Rational#numerator" do
- it_behaves_like :rational_numerator, :numerator
+ it "returns the numerator" do
+ Rational(3, 4).numerator.should equal(3)
+ Rational(3, -4).numerator.should equal(-3)
+
+ Rational(bignum_value, 1).numerator.should == bignum_value
+ end
end
diff --git a/spec/ruby/core/rational/plus_spec.rb b/spec/ruby/core/rational/plus_spec.rb
index 67c0ff63d2..01df5f6719 100644
--- a/spec/ruby/core/rational/plus_spec.rb
+++ b/spec/ruby/core/rational/plus_spec.rb
@@ -1,19 +1,50 @@
require_relative "../../spec_helper"
-require_relative '../../shared/rational/plus'
-require_relative '../../shared/rational/arithmetic_exception_in_coerce'
+require_relative 'shared/arithmetic_exception_in_coerce'
describe "Rational#+" do
- it_behaves_like :rational_plus, :+
+ it "calls #coerce on the passed argument with self" do
+ rational = Rational(3, 4)
+ obj = mock("Object")
+ obj.should_receive(:coerce).with(rational).and_return([1, 2])
+
+ rational + obj
+ end
+
+ it "calls #+ on the coerced Rational with the coerced Object" do
+ rational = Rational(3, 4)
+
+ coerced_rational = mock("Coerced Rational")
+ coerced_rational.should_receive(:+).and_return(:result)
+
+ coerced_obj = mock("Coerced Object")
+
+ obj = mock("Object")
+ obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj])
+
+ (rational + obj).should == :result
+ end
+
it_behaves_like :rational_arithmetic_exception_in_coerce, :+
end
describe "Rational#+ with a Rational" do
- it_behaves_like :rational_plus_rat, :+
+ it "returns the result of subtracting other from self as a Rational" do
+ (Rational(3, 4) + Rational(0, 1)).should eql(Rational(3, 4))
+ (Rational(3, 4) + Rational(1, 4)).should eql(Rational(1, 1))
+
+ (Rational(3, 4) + Rational(2, 1)).should eql(Rational(11, 4))
+ end
end
describe "Rational#+ with a Float" do
- it_behaves_like :rational_plus_float, :+
+ it "returns the result of subtracting other from self as a Float" do
+ (Rational(3, 4) + 0.2).should eql(0.95)
+ (Rational(3, 4) + 2.5).should eql(3.25)
+ end
end
describe "Rational#+ with an Integer" do
- it_behaves_like :rational_plus_int, :+
+ it "returns the result of subtracting other from self as a Rational" do
+ (Rational(3, 4) + 1).should eql(Rational(7, 4))
+ (Rational(3, 4) + 2).should eql(Rational(11, 4))
+ end
end
diff --git a/spec/ruby/core/rational/quo_spec.rb b/spec/ruby/core/rational/quo_spec.rb
index 181f091f7c..907898ad34 100644
--- a/spec/ruby/core/rational/quo_spec.rb
+++ b/spec/ruby/core/rational/quo_spec.rb
@@ -1,6 +1,25 @@
require_relative "../../spec_helper"
-require_relative '../../shared/rational/divide'
describe "Rational#quo" do
- it_behaves_like :rational_divide, :quo
+ it "calls #coerce on the passed argument with self" do
+ rational = Rational(3, 4)
+ obj = mock("Object")
+ obj.should_receive(:coerce).with(rational).and_return([1, 2])
+
+ rational.quo(obj)
+ end
+
+ it "calls #/ on the coerced Rational with the coerced Object" do
+ rational = Rational(3, 4)
+
+ coerced_rational = mock("Coerced Rational")
+ coerced_rational.should_receive(:/).and_return(:result)
+
+ coerced_obj = mock("Coerced Object")
+
+ obj = mock("Object")
+ obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj])
+
+ rational.quo(obj).should == :result
+ end
end
diff --git a/spec/ruby/core/rational/remainder_spec.rb b/spec/ruby/core/rational/remainder_spec.rb
index 1c0035e5f4..86ba4674e6 100644
--- a/spec/ruby/core/rational/remainder_spec.rb
+++ b/spec/ruby/core/rational/remainder_spec.rb
@@ -1,6 +1,5 @@
require_relative "../../spec_helper"
-require_relative '../../shared/rational/remainder'
describe "Rational#remainder" do
- it_behaves_like :rational_remainder, :remainder
+ it "needs to be reviewed for spec completeness"
end
diff --git a/spec/ruby/core/rational/round_spec.rb b/spec/ruby/core/rational/round_spec.rb
index 36614a552d..ac3dcafe7b 100644
--- a/spec/ruby/core/rational/round_spec.rb
+++ b/spec/ruby/core/rational/round_spec.rb
@@ -1,6 +1,106 @@
require_relative '../../spec_helper'
-require_relative '../../shared/rational/round'
describe "Rational#round" do
- it_behaves_like :rational_round, :round
+ before do
+ @rational = Rational(2200, 7)
+ end
+
+ describe "with no arguments (precision = 0)" do
+ it "returns an integer" do
+ @rational.round.should be_kind_of(Integer)
+ Rational(0, 1).round(0).should be_kind_of(Integer)
+ Rational(124, 1).round(0).should be_kind_of(Integer)
+ end
+
+ it "returns the truncated value toward the nearest integer" do
+ @rational.round.should == 314
+ Rational(0, 1).round(0).should == 0
+ Rational(2, 1).round(0).should == 2
+ end
+
+ it "returns the rounded value toward the nearest integer" do
+ Rational(1, 2).round.should == 1
+ Rational(-1, 2).round.should == -1
+ Rational(3, 2).round.should == 2
+ Rational(-3, 2).round.should == -2
+ Rational(5, 2).round.should == 3
+ Rational(-5, 2).round.should == -3
+ end
+ end
+
+ describe "with a precision < 0" do
+ it "returns an integer" do
+ @rational.round(-2).should be_kind_of(Integer)
+ @rational.round(-1).should be_kind_of(Integer)
+ Rational(0, 1).round(-1).should be_kind_of(Integer)
+ Rational(2, 1).round(-1).should be_kind_of(Integer)
+ end
+
+ it "moves the truncation point n decimal places left" do
+ @rational.round(-3).should == 0
+ @rational.round(-2).should == 300
+ @rational.round(-1).should == 310
+ end
+ end
+
+ describe "with a precision > 0" do
+ it "returns a Rational" do
+ @rational.round(1).should be_kind_of(Rational)
+ @rational.round(2).should be_kind_of(Rational)
+ # Guard against the Mathn library
+ guard -> { !defined?(Math.rsqrt) } do
+ Rational(0, 1).round(1).should be_kind_of(Rational)
+ Rational(2, 1).round(1).should be_kind_of(Rational)
+ end
+ end
+
+ it "moves the truncation point n decimal places right" do
+ @rational.round(1).should == Rational(3143, 10)
+ @rational.round(2).should == Rational(31429, 100)
+ @rational.round(3).should == Rational(157143, 500)
+ Rational(0, 1).round(1).should == Rational(0, 1)
+ Rational(2, 1).round(1).should == Rational(2, 1)
+ end
+
+ it "doesn't alter the value if the precision is too great" do
+ Rational(3, 2).round(10).should == Rational(3, 2).round(20)
+ end
+
+ # #6605
+ it "doesn't fail when rounding to an absurdly large positive precision" do
+ Rational(3, 2).round(2_097_171).should == Rational(3, 2)
+ end
+ end
+
+ describe "with half option" do
+ it "returns an Integer when precision is not passed" do
+ Rational(10, 4).round(half: nil).should == 3
+ Rational(10, 4).round(half: :up).should == 3
+ Rational(10, 4).round(half: :down).should == 2
+ Rational(10, 4).round(half: :even).should == 2
+ Rational(-10, 4).round(half: nil).should == -3
+ Rational(-10, 4).round(half: :up).should == -3
+ Rational(-10, 4).round(half: :down).should == -2
+ Rational(-10, 4).round(half: :even).should == -2
+ end
+
+ it "returns a Rational when the precision is greater than 0" do
+ Rational(25, 100).round(1, half: nil).should == Rational(3, 10)
+ Rational(25, 100).round(1, half: :up).should == Rational(3, 10)
+ Rational(25, 100).round(1, half: :down).should == Rational(1, 5)
+ Rational(25, 100).round(1, half: :even).should == Rational(1, 5)
+ Rational(35, 100).round(1, half: nil).should == Rational(2, 5)
+ Rational(35, 100).round(1, half: :up).should == Rational(2, 5)
+ Rational(35, 100).round(1, half: :down).should == Rational(3, 10)
+ Rational(35, 100).round(1, half: :even).should == Rational(2, 5)
+ Rational(-25, 100).round(1, half: nil).should == Rational(-3, 10)
+ Rational(-25, 100).round(1, half: :up).should == Rational(-3, 10)
+ Rational(-25, 100).round(1, half: :down).should == Rational(-1, 5)
+ Rational(-25, 100).round(1, half: :even).should == Rational(-1, 5)
+ end
+
+ it "raise for a non-existent round mode" do
+ -> { Rational(10, 4).round(half: :nonsense) }.should raise_error(ArgumentError, "invalid rounding mode: nonsense")
+ end
+ end
end
diff --git a/spec/ruby/core/rational/shared/abs.rb b/spec/ruby/core/rational/shared/abs.rb
new file mode 100644
index 0000000000..3d64bcc1a0
--- /dev/null
+++ b/spec/ruby/core/rational/shared/abs.rb
@@ -0,0 +1,11 @@
+require_relative '../../../spec_helper'
+
+describe :rational_abs, shared: true do
+ it "returns self's absolute value" do
+ Rational(3, 4).send(@method).should == Rational(3, 4)
+ Rational(-3, 4).send(@method).should == Rational(3, 4)
+ Rational(3, -4).send(@method).should == Rational(3, 4)
+
+ Rational(bignum_value, -bignum_value).send(@method).should == Rational(bignum_value, bignum_value)
+ end
+end
diff --git a/spec/ruby/core/rational/shared/arithmetic_exception_in_coerce.rb b/spec/ruby/core/rational/shared/arithmetic_exception_in_coerce.rb
new file mode 100644
index 0000000000..f4cf70d147
--- /dev/null
+++ b/spec/ruby/core/rational/shared/arithmetic_exception_in_coerce.rb
@@ -0,0 +1,11 @@
+require_relative '../fixtures/rational'
+
+describe :rational_arithmetic_exception_in_coerce, shared: true 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
+end
diff --git a/spec/ruby/core/rational/to_f_spec.rb b/spec/ruby/core/rational/to_f_spec.rb
index a9cd1be3b5..d0da49d377 100644
--- a/spec/ruby/core/rational/to_f_spec.rb
+++ b/spec/ruby/core/rational/to_f_spec.rb
@@ -1,6 +1,16 @@
require_relative "../../spec_helper"
-require_relative '../../shared/rational/to_f'
describe "Rational#to_f" do
- it_behaves_like :rational_to_f, :to_f
+ it "returns self converted to a Float" do
+ Rational(3, 4).to_f.should eql(0.75)
+ Rational(3, -4).to_f.should eql(-0.75)
+ Rational(-1, 4).to_f.should eql(-0.25)
+ Rational(-1, -4).to_f.should eql(0.25)
+ end
+
+ it "converts to a Float for large numerator and denominator" do
+ num = 1000000000000000000000000000000000048148248609680896326399448564623182963452541226153892315137780403285956264146010000000000000000000000000000000000048148248609680896326399448564623182963452541226153892315137780403285956264146010000000000000000000000000000000000048148248609680896326399448564623182963452541226153892315137780403285956264146009
+ den = 2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+ Rational(num, den).to_f.should == 500.0
+ end
end
diff --git a/spec/ruby/core/rational/to_i_spec.rb b/spec/ruby/core/rational/to_i_spec.rb
index 22cf02b4da..520a380b2a 100644
--- a/spec/ruby/core/rational/to_i_spec.rb
+++ b/spec/ruby/core/rational/to_i_spec.rb
@@ -1,6 +1,12 @@
require_relative "../../spec_helper"
-require_relative '../../shared/rational/to_i'
describe "Rational#to_i" do
- it_behaves_like :rational_to_i, :to_i
+ it "converts self to an Integer by truncation" do
+ Rational(7, 4).to_i.should eql(1)
+ Rational(11, 4).to_i.should eql(2)
+ end
+
+ it "converts self to an Integer by truncation" do
+ Rational(-7, 4).to_i.should eql(-1)
+ end
end
diff --git a/spec/ruby/core/rational/to_r_spec.rb b/spec/ruby/core/rational/to_r_spec.rb
index 03f204daf1..34f16d7890 100644
--- a/spec/ruby/core/rational/to_r_spec.rb
+++ b/spec/ruby/core/rational/to_r_spec.rb
@@ -1,8 +1,13 @@
require_relative "../../spec_helper"
-require_relative '../../shared/rational/to_r'
describe "Rational#to_r" do
- it_behaves_like :rational_to_r, :to_r
+ it "returns self" do
+ a = Rational(3, 4)
+ a.to_r.should equal(a)
+
+ a = Rational(bignum_value, 4)
+ a.to_r.should equal(a)
+ end
it "raises TypeError trying to convert BasicObject" do
obj = BasicObject.new
diff --git a/spec/ruby/core/rational/to_s_spec.rb b/spec/ruby/core/rational/to_s_spec.rb
index 5d90c7d80b..24e30778e5 100644
--- a/spec/ruby/core/rational/to_s_spec.rb
+++ b/spec/ruby/core/rational/to_s_spec.rb
@@ -1,6 +1,14 @@
require_relative "../../spec_helper"
-require_relative '../../shared/rational/to_s'
describe "Rational#to_s" do
- it_behaves_like :rational_to_s, :to_s
+ it "returns a string representation of self" do
+ # Guard against the Mathn library
+ guard -> { !defined?(Math.rsqrt) } do
+ Rational(1, 1).to_s.should == "1/1"
+ Rational(2, 1).to_s.should == "2/1"
+ end
+ Rational(1, 2).to_s.should == "1/2"
+ Rational(-1, 3).to_s.should == "-1/3"
+ Rational(1, -3).to_s.should == "-1/3"
+ end
end
diff --git a/spec/ruby/core/rational/truncate_spec.rb b/spec/ruby/core/rational/truncate_spec.rb
index 47a7cdf17c..728fca34ea 100644
--- a/spec/ruby/core/rational/truncate_spec.rb
+++ b/spec/ruby/core/rational/truncate_spec.rb
@@ -1,6 +1,71 @@
require_relative "../../spec_helper"
-require_relative '../../shared/rational/truncate'
describe "Rational#truncate" do
- it_behaves_like :rational_truncate, :truncate
+ before do
+ @rational = Rational(2200, 7)
+ end
+
+ describe "with no arguments (precision = 0)" do
+ it "returns an integer" do
+ @rational.truncate.should be_kind_of(Integer)
+ end
+
+ it "returns the truncated value toward 0" do
+ @rational.truncate.should == 314
+ Rational(1, 2).truncate.should == 0
+ Rational(-1, 2).truncate.should == 0
+ end
+ end
+
+ describe "with an explicit precision = 0" do
+ it "returns an integer" do
+ @rational.truncate(0).should be_kind_of(Integer)
+ end
+
+ it "returns the truncated value toward 0" do
+ @rational.truncate(0).should == 314
+ Rational(1, 2).truncate(0).should == 0
+ Rational(-1, 2).truncate(0).should == 0
+ end
+ end
+
+ describe "with a precision < 0" do
+ it "returns an integer" do
+ @rational.truncate(-2).should be_kind_of(Integer)
+ @rational.truncate(-1).should be_kind_of(Integer)
+ end
+
+ it "moves the truncation point n decimal places left" do
+ @rational.truncate(-3).should == 0
+ @rational.truncate(-2).should == 300
+ @rational.truncate(-1).should == 310
+ end
+ end
+
+ describe "with a precision > 0" do
+ it "returns a Rational" do
+ @rational.truncate(1).should be_kind_of(Rational)
+ @rational.truncate(2).should be_kind_of(Rational)
+ end
+
+ it "moves the truncation point n decimal places right" do
+ @rational.truncate(1).should == Rational(1571, 5)
+ @rational.truncate(2).should == Rational(7857, 25)
+ @rational.truncate(3).should == Rational(62857, 200)
+ end
+ end
+
+ describe "with an invalid value for precision" do
+ it "raises a TypeError" do
+ -> { @rational.truncate(nil) }.should raise_error(TypeError, "not an integer")
+ -> { @rational.truncate(1.0) }.should raise_error(TypeError, "not an integer")
+ -> { @rational.truncate('') }.should raise_error(TypeError, "not an integer")
+ end
+
+ it "does not call to_int on the argument" do
+ object = Object.new
+ object.should_not_receive(:to_int)
+ -> { @rational.truncate(object) }.should raise_error(TypeError, "not an integer")
+ end
+ end
end
diff --git a/spec/ruby/core/refinement/append_features_spec.rb b/spec/ruby/core/refinement/append_features_spec.rb
index fb84f245bd..f7e5f32bc1 100644
--- a/spec/ruby/core/refinement/append_features_spec.rb
+++ b/spec/ruby/core/refinement/append_features_spec.rb
@@ -1,20 +1,18 @@
require_relative '../../spec_helper'
describe "Refinement#append_features" do
- ruby_version_is "3.2" do
- it "is not defined" do
- Refinement.should_not have_private_instance_method(:append_features)
- end
+ it "is not defined" do
+ Refinement.should_not have_private_instance_method(:append_features)
+ end
- it "is not called by Module#include" do
- c = Class.new
- Module.new do
- refine c do
- called = false
- define_method(:append_features){called = true}
- proc{c.include(self)}.should raise_error(TypeError)
- called.should == false
- end
+ it "is not called by Module#include" do
+ c = Class.new
+ Module.new do
+ refine c do
+ called = false
+ define_method(:append_features){called = true}
+ proc{c.include(self)}.should raise_error(TypeError)
+ called.should == false
end
end
end
diff --git a/spec/ruby/core/refinement/extend_object_spec.rb b/spec/ruby/core/refinement/extend_object_spec.rb
index 6c2a0af4f3..4da8b359cc 100644
--- a/spec/ruby/core/refinement/extend_object_spec.rb
+++ b/spec/ruby/core/refinement/extend_object_spec.rb
@@ -1,22 +1,20 @@
require_relative '../../spec_helper'
describe "Refinement#extend_object" do
- ruby_version_is "3.2" do
- it "is not defined" do
- Refinement.should_not have_private_instance_method(:extend_object)
- end
+ it "is not defined" do
+ Refinement.should_not have_private_instance_method(:extend_object)
+ end
- it "is not called by Object#extend" do
- c = Class.new
- Module.new do
- refine c do
- called = false
- define_method(:extend_object) { called = true }
- -> {
- c.extend(self)
- }.should raise_error(TypeError)
- called.should == false
- end
+ it "is not called by Object#extend" do
+ c = Class.new
+ Module.new do
+ refine c do
+ called = false
+ define_method(:extend_object) { called = true }
+ -> {
+ c.extend(self)
+ }.should raise_error(TypeError)
+ called.should == false
end
end
end
diff --git a/spec/ruby/core/refinement/import_methods_spec.rb b/spec/ruby/core/refinement/import_methods_spec.rb
index 614c54dff8..13c0b1004c 100644
--- a/spec/ruby/core/refinement/import_methods_spec.rb
+++ b/spec/ruby/core/refinement/import_methods_spec.rb
@@ -2,137 +2,76 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Refinement#import_methods" do
- ruby_version_is "3.1" do
- context "when methods are defined in Ruby code" do
- it "imports methods" do
- str_utils = Module.new do
- def indent(level)
- " " * level + self
- end
- end
-
- Module.new do
- refine String do
- import_methods str_utils
- "foo".indent(3).should == " foo"
- end
+ context "when methods are defined in Ruby code" do
+ it "imports methods" do
+ str_utils = Module.new do
+ def indent(level)
+ " " * level + self
end
end
- it "throws an exception when argument is not a module" do
- Module.new do
- refine String do
- -> {
- import_methods Integer
- }.should raise_error(TypeError, "wrong argument type Class (expected Module)")
- end
+ Module.new do
+ refine String do
+ import_methods str_utils
+ "foo".indent(3).should == " foo"
end
end
+ end
- it "imports methods from multiple modules" do
- str_utils = Module.new do
- def indent(level)
- " " * level + self
- end
- end
-
- str_utils_fancy = Module.new do
- def indent_star(level)
- "*" * level + self
- end
- end
-
- Module.new do
- refine String do
- import_methods str_utils, str_utils_fancy
- "foo".indent(3).should == " foo"
- "foo".indent_star(3).should == "***foo"
- end
+ it "throws an exception when argument is not a module" do
+ Module.new do
+ refine String do
+ -> {
+ import_methods Integer
+ }.should raise_error(TypeError, "wrong argument type Class (expected Module)")
end
end
+ end
- it "imports a method defined in the last module if method with same name is defined in multiple modules" do
- str_utils = Module.new do
- def indent(level)
- " " * level + self
- end
- end
-
- str_utils_fancy = Module.new do
- def indent(level)
- "*" * level + self
- end
- end
-
- Module.new do
- refine String do
- import_methods str_utils, str_utils_fancy
- "foo".indent(3).should == "***foo"
- end
+ it "imports methods from multiple modules" do
+ str_utils = Module.new do
+ def indent(level)
+ " " * level + self
end
end
- it "still imports methods of modules listed before a module that contains method not defined in Ruby" do
- str_utils = Module.new do
- def indent(level)
- " " * level + self
- end
- end
-
- string_refined = Module.new do
- refine String do
- -> {
- import_methods str_utils, Kernel
- }.should raise_error(ArgumentError)
- end
+ str_utils_fancy = Module.new do
+ def indent_star(level)
+ "*" * level + self
end
+ end
- Module.new do
- using string_refined
+ Module.new do
+ refine String do
+ import_methods str_utils, str_utils_fancy
"foo".indent(3).should == " foo"
+ "foo".indent_star(3).should == "***foo"
end
end
end
- it "warns if a module includes/prepends some other module" do
- module1 = Module.new do
- end
-
- module2 = Module.new do
- include module1
- end
-
- Module.new do
- refine String do
- -> {
- import_methods module2
- }.should complain(/warning: #<Module:\w*> has ancestors, but Refinement#import_methods doesn't import their methods/)
+ it "imports a method defined in the last module if method with same name is defined in multiple modules" do
+ str_utils = Module.new do
+ def indent(level)
+ " " * level + self
end
end
- Module.new do
- refine String do
- -> {
- import_methods RefinementSpec::ModuleWithAncestors
- }.should complain(/warning: RefinementSpec::ModuleWithAncestors has ancestors, but Refinement#import_methods doesn't import their methods/)
+ str_utils_fancy = Module.new do
+ def indent(level)
+ "*" * level + self
end
end
- end
- it "doesn't import methods from included/prepended modules" do
Module.new do
refine String do
- suppress_warning { import_methods RefinementSpec::ModuleWithAncestors }
+ import_methods str_utils, str_utils_fancy
+ "foo".indent(3).should == "***foo"
end
-
- using self
- -> {
- "foo".indent(3)
- }.should raise_error(NoMethodError, /undefined method [`']indent' for ("foo":String|an instance of String)/)
end
end
- it "doesn't import any methods if one of the arguments is not a module" do
+ it "still imports methods of modules listed before a module that contains method not defined in Ruby" do
str_utils = Module.new do
def indent(level)
" " * level + self
@@ -142,126 +81,185 @@ describe "Refinement#import_methods" do
string_refined = Module.new do
refine String do
-> {
- import_methods str_utils, Integer
- }.should raise_error(TypeError)
+ import_methods str_utils, Kernel
+ }.should raise_error(ArgumentError)
end
end
Module.new do
using string_refined
+ "foo".indent(3).should == " foo"
+ end
+ end
+ end
+
+ it "warns if a module includes/prepends some other module" do
+ module1 = Module.new do
+ end
+
+ module2 = Module.new do
+ include module1
+ end
+
+ Module.new do
+ refine String do
-> {
- "foo".indent(3)
- }.should raise_error(NoMethodError)
+ import_methods module2
+ }.should complain(/warning: #<Module:\w*> has ancestors, but Refinement#import_methods doesn't import their methods/)
end
end
- it "imports methods from multiple modules so that methods see other's module's methods" do
- str_utils = Module.new do
- def indent(level)
- " " * level + self
- end
+ Module.new do
+ refine String do
+ -> {
+ import_methods RefinementSpec::ModuleWithAncestors
+ }.should complain(/warning: RefinementSpec::ModuleWithAncestors has ancestors, but Refinement#import_methods doesn't import their methods/)
+ end
+ end
+ end
+
+ it "doesn't import methods from included/prepended modules" do
+ Module.new do
+ refine String do
+ suppress_warning { import_methods RefinementSpec::ModuleWithAncestors }
end
- str_utils_normal = Module.new do
- def indent_normal(level)
- self.indent(level)
- end
+ using self
+ -> {
+ "foo".indent(3)
+ }.should raise_error(NoMethodError, /undefined method [`']indent' for ("foo":String|an instance of String)/)
+ end
+ end
+
+ it "doesn't import any methods if one of the arguments is not a module" do
+ str_utils = Module.new do
+ def indent(level)
+ " " * level + self
end
+ end
- Module.new do
- refine String do
- import_methods str_utils, str_utils_normal
- end
+ string_refined = Module.new do
+ refine String do
+ -> {
+ import_methods str_utils, Integer
+ }.should raise_error(TypeError)
+ end
+ end
- using self
- "foo".indent_normal(3).should == " foo"
+ Module.new do
+ using string_refined
+ -> {
+ "foo".indent(3)
+ }.should raise_error(NoMethodError)
+ end
+ end
+
+ it "imports methods from multiple modules so that methods see other's module's methods" do
+ str_utils = Module.new do
+ def indent(level)
+ " " * level + self
end
end
- it "imports methods from module so that methods can see each other" do
- str_utils = Module.new do
- def indent(level)
- " " * level + self
- end
+ str_utils_normal = Module.new do
+ def indent_normal(level)
+ self.indent(level)
+ end
+ end
- def indent_with_dot(level)
- self.indent(level) + "."
- end
+ Module.new do
+ refine String do
+ import_methods str_utils, str_utils_normal
end
- Module.new do
- refine String do
- import_methods str_utils
- end
+ using self
+ "foo".indent_normal(3).should == " foo"
+ end
+ end
- using self
- "foo".indent_with_dot(3).should == " foo."
+ it "imports methods from module so that methods can see each other" do
+ str_utils = Module.new do
+ def indent(level)
+ " " * level + self
+ end
+
+ def indent_with_dot(level)
+ self.indent(level) + "."
end
end
- it "doesn't import module's class methods" do
- str_utils = Module.new do
- def self.indent(level)
- " " * level + self
- end
+ Module.new do
+ refine String do
+ import_methods str_utils
end
- Module.new do
- refine String do
- import_methods str_utils
- end
+ using self
+ "foo".indent_with_dot(3).should == " foo."
+ end
+ end
- using self
- -> {
- String.indent(3)
- }.should raise_error(NoMethodError, /undefined method [`']indent' for (String:Class|class String)/)
+ it "doesn't import module's class methods" do
+ str_utils = Module.new do
+ def self.indent(level)
+ " " * level + self
end
end
- it "imports module methods with super" do
- class_to_refine = Class.new do
- def foo(number)
- 2 * number
- end
+ Module.new do
+ refine String do
+ import_methods str_utils
end
- extension = Module.new do
- def foo(number)
- super * 2
- end
+ using self
+ -> {
+ String.indent(3)
+ }.should raise_error(NoMethodError, /undefined method [`']indent' for (String:Class|class String)/)
+ end
+ end
+
+ it "imports module methods with super" do
+ class_to_refine = Class.new do
+ def foo(number)
+ 2 * number
end
+ end
- refinement = Module.new do
- refine class_to_refine do
- import_methods extension
- end
+ extension = Module.new do
+ def foo(number)
+ super * 2
end
+ end
- Module.new do
- using refinement
- class_to_refine.new.foo(2).should == 8
+ refinement = Module.new do
+ refine class_to_refine do
+ import_methods extension
end
end
- context "when methods are not defined in Ruby code" do
- it "raises ArgumentError" do
- Module.new do
- refine String do
- -> {
- import_methods Kernel
- }.should raise_error(ArgumentError)
- end
+ Module.new do
+ using refinement
+ class_to_refine.new.foo(2).should == 8
+ end
+ end
+
+ context "when methods are not defined in Ruby code" do
+ it "raises ArgumentError" do
+ Module.new do
+ refine String do
+ -> {
+ import_methods Kernel
+ }.should raise_error(ArgumentError)
end
end
+ end
- it "raises ArgumentError when importing methods from C extension" do
- require 'zlib'
- Module.new do
- refine String do
- -> {
- import_methods Zlib
- }.should raise_error(ArgumentError, /Can't import method which is not defined with Ruby code: Zlib#*/)
- end
+ it "raises ArgumentError when importing methods from C extension" do
+ require 'zlib'
+ Module.new do
+ refine String do
+ -> {
+ import_methods Zlib
+ }.should raise_error(ArgumentError, /Can't import method which is not defined with Ruby code: Zlib#*/)
end
end
end
diff --git a/spec/ruby/core/refinement/include_spec.rb b/spec/ruby/core/refinement/include_spec.rb
index 25a53f0ec7..57451bd9bc 100644
--- a/spec/ruby/core/refinement/include_spec.rb
+++ b/spec/ruby/core/refinement/include_spec.rb
@@ -1,26 +1,12 @@
require_relative '../../spec_helper'
describe "Refinement#include" do
- ruby_version_is "3.1"..."3.2" do
- it "warns about deprecation" do
- Module.new do
- refine String do
- -> {
- include Module.new
- }.should complain(/warning: Refinement#include is deprecated and will be removed in Ruby 3.2/)
- end
- end
- end
- end
-
- ruby_version_is "3.2" do
- it "raises a TypeError" do
- Module.new do
- refine String do
- -> {
- include Module.new
- }.should raise_error(TypeError, "Refinement#include has been removed")
- end
+ it "raises a TypeError" do
+ Module.new do
+ refine String do
+ -> {
+ include Module.new
+ }.should raise_error(TypeError, "Refinement#include has been removed")
end
end
end
diff --git a/spec/ruby/core/refinement/prepend_features_spec.rb b/spec/ruby/core/refinement/prepend_features_spec.rb
index 9fdea199a2..fbc431bbd2 100644
--- a/spec/ruby/core/refinement/prepend_features_spec.rb
+++ b/spec/ruby/core/refinement/prepend_features_spec.rb
@@ -1,20 +1,18 @@
require_relative '../../spec_helper'
describe "Refinement#prepend_features" do
- ruby_version_is "3.2" do
- it "is not defined" do
- Refinement.should_not have_private_instance_method(:prepend_features)
- end
+ it "is not defined" do
+ Refinement.should_not have_private_instance_method(:prepend_features)
+ end
- it "is not called by Module#prepend" do
- c = Class.new
- Module.new do
- refine c do
- called = false
- define_method(:prepend_features){called = true}
- proc{c.prepend(self)}.should raise_error(TypeError)
- called.should == false
- end
+ it "is not called by Module#prepend" do
+ c = Class.new
+ Module.new do
+ refine c do
+ called = false
+ define_method(:prepend_features){called = true}
+ proc{c.prepend(self)}.should raise_error(TypeError)
+ called.should == false
end
end
end
diff --git a/spec/ruby/core/refinement/prepend_spec.rb b/spec/ruby/core/refinement/prepend_spec.rb
index 27b70d392a..64cf7cd17f 100644
--- a/spec/ruby/core/refinement/prepend_spec.rb
+++ b/spec/ruby/core/refinement/prepend_spec.rb
@@ -1,26 +1,12 @@
require_relative '../../spec_helper'
describe "Refinement#prepend" do
- ruby_version_is "3.1"..."3.2" do
- it "warns about deprecation" do
- Module.new do
- refine String do
- -> {
- prepend Module.new
- }.should complain(/warning: Refinement#prepend is deprecated and will be removed in Ruby 3.2/)
- end
- end
- end
- end
-
- ruby_version_is "3.2" do
- it "raises a TypeError" do
- Module.new do
- refine String do
- -> {
- prepend Module.new
- }.should raise_error(TypeError, "Refinement#prepend has been removed")
- end
+ it "raises a TypeError" do
+ Module.new do
+ refine String do
+ -> {
+ prepend Module.new
+ }.should raise_error(TypeError, "Refinement#prepend has been removed")
end
end
end
diff --git a/spec/ruby/core/refinement/refined_class_spec.rb b/spec/ruby/core/refinement/refined_class_spec.rb
index 00b65d0895..60a58380cc 100644
--- a/spec/ruby/core/refinement/refined_class_spec.rb
+++ b/spec/ruby/core/refinement/refined_class_spec.rb
@@ -1,8 +1,29 @@
-require_relative '../../spec_helper'
+require_relative "../../spec_helper"
+require_relative 'shared/target'
describe "Refinement#refined_class" do
- ruby_version_is "3.2"..."3.3" do
- it "returns the class refined by the receiver" do
+ ruby_version_is ""..."3.3" do
+ it_behaves_like :refinement_target, :refined_class
+ end
+
+ ruby_version_is "3.3"..."3.4" do
+ it "has been deprecated in favour of Refinement#target" do
+ refinement_int = nil
+
+ Module.new do
+ refine Integer do
+ refinement_int = self
+ end
+ end
+
+ -> {
+ refinement_int.refined_class
+ }.should complain(/warning: Refinement#refined_class is deprecated and will be removed in Ruby 3.4; use Refinement#target instead/)
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "has been removed" do
refinement_int = nil
Module.new do
@@ -11,7 +32,7 @@ describe "Refinement#refined_class" do
end
end
- refinement_int.refined_class.should == Integer
+ refinement_int.should_not.respond_to?(:refined_class)
end
end
end
diff --git a/spec/ruby/core/refinement/shared/target.rb b/spec/ruby/core/refinement/shared/target.rb
new file mode 100644
index 0000000000..79557bea0b
--- /dev/null
+++ b/spec/ruby/core/refinement/shared/target.rb
@@ -0,0 +1,13 @@
+describe :refinement_target, shared: true do
+ it "returns the class refined by the receiver" do
+ refinement_int = nil
+
+ Module.new do
+ refine Integer do
+ refinement_int = self
+ end
+ end
+
+ refinement_int.send(@method).should == Integer
+ end
+end
diff --git a/spec/ruby/core/refinement/target_spec.rb b/spec/ruby/core/refinement/target_spec.rb
new file mode 100644
index 0000000000..fee9588a96
--- /dev/null
+++ b/spec/ruby/core/refinement/target_spec.rb
@@ -0,0 +1,8 @@
+require_relative "../../spec_helper"
+require_relative 'shared/target'
+
+describe "Refinement#target" do
+ ruby_version_is "3.3" do
+ it_behaves_like :refinement_target, :target
+ end
+end
diff --git a/spec/ruby/core/regexp/compile_spec.rb b/spec/ruby/core/regexp/compile_spec.rb
index c41399cfbb..887c8d77dc 100644
--- a/spec/ruby/core/regexp/compile_spec.rb
+++ b/spec/ruby/core/regexp/compile_spec.rb
@@ -14,6 +14,6 @@ describe "Regexp.compile given a Regexp" do
it_behaves_like :regexp_new_regexp, :compile
end
-describe "Regexp.new given a non-String/Regexp" do
+describe "Regexp.compile given a non-String/Regexp" do
it_behaves_like :regexp_new_non_string_or_regexp, :compile
end
diff --git a/spec/ruby/core/regexp/linear_time_spec.rb b/spec/ruby/core/regexp/linear_time_spec.rb
index 4dc436264f..cf9e73c37c 100644
--- a/spec/ruby/core/regexp/linear_time_spec.rb
+++ b/spec/ruby/core/regexp/linear_time_spec.rb
@@ -1,25 +1,33 @@
require_relative '../../spec_helper'
-ruby_version_is "3.2" do
- describe "Regexp.linear_time?" do
- it "returns true if matching can be done in linear time" do
- Regexp.linear_time?(/a/).should == true
- Regexp.linear_time?('a').should == true
- end
+describe "Regexp.linear_time?" do
+ it "returns true if matching can be done in linear time" do
+ Regexp.linear_time?(/a/).should == true
+ Regexp.linear_time?('a').should == true
+ end
- it "return false if matching can't be done in linear time" do
- Regexp.linear_time?(/(a)\1/).should == false
- Regexp.linear_time?("(a)\\1").should == false
- end
+ it "returns true if matching can be done in linear time for a binary Regexp" do
+ Regexp.linear_time?(/[\x80-\xff]/n).should == true
+ end
- it "accepts flags for string argument" do
- Regexp.linear_time?('a', Regexp::IGNORECASE).should == true
- end
+ it "return false if matching can't be done in linear time" do
+ Regexp.linear_time?(/(a)\1/).should == false
+ Regexp.linear_time?("(a)\\1").should == false
+ end
+
+ it "accepts flags for string argument" do
+ Regexp.linear_time?('a', Regexp::IGNORECASE).should == true
+ end
+
+ it "warns about flags being ignored for regexp arguments" do
+ -> {
+ Regexp.linear_time?(/a/, Regexp::IGNORECASE)
+ }.should complain(/warning: flags ignored/)
+ end
- it "warns about flags being ignored for regexp arguments" do
- -> {
- Regexp.linear_time?(/a/, Regexp::IGNORECASE)
- }.should complain(/warning: flags ignored/)
+ ruby_version_is "3.3" do
+ it "returns true for positive lookarounds" do
+ Regexp.linear_time?(/(?:(?=a*)a)*/).should == true
end
end
end
diff --git a/spec/ruby/core/regexp/new_spec.rb b/spec/ruby/core/regexp/new_spec.rb
index 65f612df55..79210e9a23 100644
--- a/spec/ruby/core/regexp/new_spec.rb
+++ b/spec/ruby/core/regexp/new_spec.rb
@@ -7,11 +7,11 @@ end
describe "Regexp.new given a String" do
it_behaves_like :regexp_new_string, :new
+ it_behaves_like :regexp_new_string_binary, :new
end
describe "Regexp.new given a Regexp" do
it_behaves_like :regexp_new_regexp, :new
- it_behaves_like :regexp_new_string_binary, :new
end
describe "Regexp.new given a non-String/Regexp" do
diff --git a/spec/ruby/core/regexp/shared/new.rb b/spec/ruby/core/regexp/shared/new.rb
index 7c3fabf612..12c3d7c9c2 100644
--- a/spec/ruby/core/regexp/shared/new.rb
+++ b/spec/ruby/core/regexp/shared/new.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
describe :regexp_new, shared: true do
it "requires one argument and creates a new regular expression object" do
@@ -56,7 +56,7 @@ describe :regexp_new_string, shared: true do
end
it "raises a RegexpError when passed an incorrect regexp" do
- -> { Regexp.send(@method, "^[$", 0) }.should raise_error(RegexpError)
+ -> { Regexp.send(@method, "^[$", 0) }.should raise_error(RegexpError, Regexp.new(Regexp.escape("premature end of char-class: /^[$/")))
end
it "does not set Regexp options if only given one argument" do
@@ -123,345 +123,100 @@ describe :regexp_new_string, shared: true do
(r.options & Regexp::EXTENDED).should_not == 0
end
- ruby_version_is ""..."3.2" do
- it "does not try to convert the second argument to Integer with #to_int method call" do
- ScratchPad.clear
- obj = Object.new
- def obj.to_int() ScratchPad.record(:called) end
+ it "does not try to convert the second argument to Integer with #to_int method call" do
+ ScratchPad.clear
+ obj = Object.new
+ def obj.to_int() ScratchPad.record(:called) end
+ -> {
Regexp.send(@method, "Hi", obj)
+ }.should complain(/expected true or false as ignorecase/, {verbose: true})
- ScratchPad.recorded.should == nil
- end
- end
-
- ruby_version_is "3.2" do
- it "does not try to convert the second argument to Integer with #to_int method call" do
- ScratchPad.clear
- obj = Object.new
- def obj.to_int() ScratchPad.record(:called) end
-
- -> {
- Regexp.send(@method, "Hi", obj)
- }.should complain(/expected true or false as ignorecase/, {verbose: true})
-
- ScratchPad.recorded.should == nil
- end
+ ScratchPad.recorded.should == nil
end
- ruby_version_is ""..."3.2" do
- it "treats any non-Integer, non-nil, non-false second argument as IGNORECASE" do
+ it "warns any non-Integer, non-nil, non-false second argument" do
+ r = nil
+ -> {
r = Regexp.send(@method, 'Hi', Object.new)
- (r.options & Regexp::IGNORECASE).should_not == 0
- (r.options & Regexp::MULTILINE).should == 0
- not_supported_on :opal do
- (r.options & Regexp::EXTENDED).should == 0
- end
- end
- end
-
- ruby_version_is "3.2" do
- it "warns any non-Integer, non-nil, non-false second argument" do
- r = nil
- -> {
- r = Regexp.send(@method, 'Hi', Object.new)
- }.should complain(/expected true or false as ignorecase/, {verbose: true})
- (r.options & Regexp::IGNORECASE).should_not == 0
- (r.options & Regexp::MULTILINE).should == 0
- not_supported_on :opal do
- (r.options & Regexp::EXTENDED).should == 0
- end
- end
-
- it "accepts a String of supported flags as the second argument" do
- r = Regexp.send(@method, 'Hi', 'i')
- (r.options & Regexp::IGNORECASE).should_not == 0
- (r.options & Regexp::MULTILINE).should == 0
- not_supported_on :opal do
- (r.options & Regexp::EXTENDED).should == 0
- end
-
- r = Regexp.send(@method, 'Hi', 'imx')
- (r.options & Regexp::IGNORECASE).should_not == 0
- (r.options & Regexp::MULTILINE).should_not == 0
- not_supported_on :opal do
- (r.options & Regexp::EXTENDED).should_not == 0
- end
-
- r = Regexp.send(@method, 'Hi', 'mimi')
- (r.options & Regexp::IGNORECASE).should_not == 0
- (r.options & Regexp::MULTILINE).should_not == 0
- not_supported_on :opal do
- (r.options & Regexp::EXTENDED).should == 0
- end
-
- r = Regexp.send(@method, 'Hi', '')
- (r.options & Regexp::IGNORECASE).should == 0
- (r.options & Regexp::MULTILINE).should == 0
- not_supported_on :opal do
- (r.options & Regexp::EXTENDED).should == 0
- end
- end
-
- it "raises an Argument error if the second argument contains unsupported chars" do
- -> { Regexp.send(@method, 'Hi', 'e') }.should raise_error(ArgumentError, "unknown regexp option: e")
- -> { Regexp.send(@method, 'Hi', 'n') }.should raise_error(ArgumentError, "unknown regexp option: n")
- -> { Regexp.send(@method, 'Hi', 's') }.should raise_error(ArgumentError, "unknown regexp option: s")
- -> { Regexp.send(@method, 'Hi', 'u') }.should raise_error(ArgumentError, "unknown regexp option: u")
- -> { Regexp.send(@method, 'Hi', 'j') }.should raise_error(ArgumentError, "unknown regexp option: j")
- -> { Regexp.send(@method, 'Hi', 'mjx') }.should raise_error(ArgumentError, /unknown regexp option: mjx\b/)
+ }.should complain(/expected true or false as ignorecase/, {verbose: true})
+ (r.options & Regexp::IGNORECASE).should_not == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
end
end
- ruby_version_is ""..."3.2" do
- it "ignores the third argument if it is 'e' or 'euc' (case-insensitive)" do
- -> {
- Regexp.send(@method, 'Hi', nil, 'e').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'euc').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'E').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'EUC').encoding.should == Encoding::US_ASCII
- }.should complain(/encoding option is ignored/)
+ it "accepts a String of supported flags as the second argument" do
+ r = Regexp.send(@method, 'Hi', 'i')
+ (r.options & Regexp::IGNORECASE).should_not == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
end
- it "ignores the third argument if it is 's' or 'sjis' (case-insensitive)" do
- -> {
- Regexp.send(@method, 'Hi', nil, 's').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'sjis').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'S').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'SJIS').encoding.should == Encoding::US_ASCII
- }.should complain(/encoding option is ignored/)
+ r = Regexp.send(@method, 'Hi', 'imx')
+ (r.options & Regexp::IGNORECASE).should_not == 0
+ (r.options & Regexp::MULTILINE).should_not == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should_not == 0
end
- it "ignores the third argument if it is 'u' or 'utf8' (case-insensitive)" do
- -> {
- Regexp.send(@method, 'Hi', nil, 'u').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'utf8').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'U').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'UTF8').encoding.should == Encoding::US_ASCII
- }.should complain(/encoding option is ignored/)
+ r = Regexp.send(@method, 'Hi', 'mimi')
+ (r.options & Regexp::IGNORECASE).should_not == 0
+ (r.options & Regexp::MULTILINE).should_not == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
end
- it "uses US_ASCII encoding if third argument is 'n' or 'none' (case insensitive) and only ascii characters" do
- Regexp.send(@method, 'Hi', nil, 'n').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'none').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'N').encoding.should == Encoding::US_ASCII
- Regexp.send(@method, 'Hi', nil, 'NONE').encoding.should == Encoding::US_ASCII
+ r = Regexp.send(@method, 'Hi', '')
+ (r.options & Regexp::IGNORECASE).should == 0
+ (r.options & Regexp::MULTILINE).should == 0
+ not_supported_on :opal do
+ (r.options & Regexp::EXTENDED).should == 0
end
+ end
- it "uses ASCII_8BIT encoding if third argument is 'n' or 'none' (case insensitive) and non-ascii characters" do
- a = "(?:[\x8E\xA1-\xFE])"
- str = "\A(?:#{a}|x*)\z"
-
- Regexp.send(@method, str, nil, 'N').encoding.should == Encoding::BINARY
- Regexp.send(@method, str, nil, 'n').encoding.should == Encoding::BINARY
- Regexp.send(@method, str, nil, 'none').encoding.should == Encoding::BINARY
- Regexp.send(@method, str, nil, 'NONE').encoding.should == Encoding::BINARY
- end
+ it "raises an Argument error if the second argument contains unsupported chars" do
+ -> { Regexp.send(@method, 'Hi', 'e') }.should raise_error(ArgumentError, "unknown regexp option: e")
+ -> { Regexp.send(@method, 'Hi', 'n') }.should raise_error(ArgumentError, "unknown regexp option: n")
+ -> { Regexp.send(@method, 'Hi', 's') }.should raise_error(ArgumentError, "unknown regexp option: s")
+ -> { Regexp.send(@method, 'Hi', 'u') }.should raise_error(ArgumentError, "unknown regexp option: u")
+ -> { Regexp.send(@method, 'Hi', 'j') }.should raise_error(ArgumentError, "unknown regexp option: j")
+ -> { Regexp.send(@method, 'Hi', 'mjx') }.should raise_error(ArgumentError, /unknown regexp option: mjx\b/)
end
describe "with escaped characters" do
it "raises a Regexp error if there is a trailing backslash" do
- -> { Regexp.send(@method, "\\") }.should raise_error(RegexpError)
+ -> { Regexp.send(@method, "\\") }.should raise_error(RegexpError, Regexp.new(Regexp.escape("too short escape sequence: /\\/")))
end
it "does not raise a Regexp error if there is an escaped trailing backslash" do
-> { Regexp.send(@method, "\\\\") }.should_not raise_error(RegexpError)
end
- it "accepts a backspace followed by a character" do
+ it "accepts a backspace followed by a non-special character" do
Regexp.send(@method, "\\N").should == /#{"\x5c"+"N"}/
end
- it "accepts a one-digit octal value" do
- Regexp.send(@method, "\0").should == /#{"\x00"}/
- end
-
- it "accepts a two-digit octal value" do
- Regexp.send(@method, "\11").should == /#{"\x09"}/
- end
-
- it "accepts a one-digit hexadecimal value" do
- Regexp.send(@method, "\x9n").should == /#{"\x09n"}/
- end
-
- it "accepts a two-digit hexadecimal value" do
- Regexp.send(@method, "\x23").should == /#{"\x23"}/
- end
-
- it "interprets a digit following a two-digit hexadecimal value as a character" do
- Regexp.send(@method, "\x420").should == /#{"\x420"}/
- end
-
it "raises a RegexpError if \\x is not followed by any hexadecimal digits" do
- -> { Regexp.send(@method, "\\" + "xn") }.should raise_error(RegexpError)
- end
-
- it "accepts an escaped string interpolation" do
- Regexp.send(@method, "\#{abc}").should == /#{"\#{abc}"}/
- end
-
- it "accepts '\\n'" do
- Regexp.send(@method, "\n").should == /#{"\x0a"}/
- end
-
- it "accepts '\\t'" do
- Regexp.send(@method, "\t").should == /#{"\x09"}/
- end
-
- it "accepts '\\r'" do
- Regexp.send(@method, "\r").should == /#{"\x0d"}/
- end
-
- it "accepts '\\f'" do
- Regexp.send(@method, "\f").should == /#{"\x0c"}/
- end
-
- it "accepts '\\v'" do
- Regexp.send(@method, "\v").should == /#{"\x0b"}/
- end
-
- it "accepts '\\a'" do
- Regexp.send(@method, "\a").should == /#{"\x07"}/
- end
-
- it "accepts '\\e'" do
- Regexp.send(@method, "\e").should == /#{"\x1b"}/
- end
-
- it "accepts '\\C-\\n'" do
- Regexp.send(@method, "\C-\n").should == /#{"\x0a"}/
- end
-
- it "accepts '\\C-\\t'" do
- Regexp.send(@method, "\C-\t").should == /#{"\x09"}/
- end
-
- it "accepts '\\C-\\r'" do
- Regexp.send(@method, "\C-\r").should == /#{"\x0d"}/
- end
-
- it "accepts '\\C-\\f'" do
- Regexp.send(@method, "\C-\f").should == /#{"\x0c"}/
- end
-
- it "accepts '\\C-\\v'" do
- Regexp.send(@method, "\C-\v").should == /#{"\x0b"}/
- end
-
- it "accepts '\\C-\\a'" do
- Regexp.send(@method, "\C-\a").should == /#{"\x07"}/
- end
-
- it "accepts '\\C-\\e'" do
- Regexp.send(@method, "\C-\e").should == /#{"\x1b"}/
- end
-
- it "accepts multiple consecutive '\\' characters" do
- Regexp.send(@method, "\\\\\\N").should == /#{"\\\\\\"+"N"}/
- end
-
- it "accepts characters and escaped octal digits" do
- Regexp.send(@method, "abc\076").should == /#{"abc\x3e"}/
- end
-
- it "accepts escaped octal digits and characters" do
- Regexp.send(@method, "\076abc").should == /#{"\x3eabc"}/
- end
-
- it "accepts characters and escaped hexadecimal digits" do
- Regexp.send(@method, "abc\x42").should == /#{"abc\x42"}/
- end
-
- it "accepts escaped hexadecimal digits and characters" do
- Regexp.send(@method, "\x3eabc").should == /#{"\x3eabc"}/
- end
-
- it "accepts escaped hexadecimal and octal digits" do
- Regexp.send(@method, "\061\x42").should == /#{"\x31\x42"}/
- end
-
- it "accepts \\u{H} for a single Unicode codepoint" do
- Regexp.send(@method, "\u{f}").should == /#{"\x0f"}/
- end
-
- it "accepts \\u{HH} for a single Unicode codepoint" do
- Regexp.send(@method, "\u{7f}").should == /#{"\x7f"}/
- end
-
- it "accepts \\u{HHH} for a single Unicode codepoint" do
- Regexp.send(@method, "\u{07f}").should == /#{"\x7f"}/
- end
-
- it "accepts \\u{HHHH} for a single Unicode codepoint" do
- Regexp.send(@method, "\u{0000}").should == /#{"\x00"}/
- end
-
- it "accepts \\u{HHHHH} for a single Unicode codepoint" do
- Regexp.send(@method, "\u{00001}").should == /#{"\x01"}/
- end
-
- it "accepts \\u{HHHHHH} for a single Unicode codepoint" do
- Regexp.send(@method, "\u{000000}").should == /#{"\x00"}/
- end
-
- it "accepts characters followed by \\u{HHHH}" do
- Regexp.send(@method, "abc\u{3042}").should == /#{"abc\u3042"}/
- end
-
- it "accepts \\u{HHHH} followed by characters" do
- Regexp.send(@method, "\u{3042}abc").should == /#{"\u3042abc"}/
- end
-
- it "accepts escaped hexadecimal digits followed by \\u{HHHH}" do
- Regexp.send(@method, "\x42\u{3042}").should == /#{"\x42\u3042"}/
- end
-
- it "accepts escaped octal digits followed by \\u{HHHH}" do
- Regexp.send(@method, "\056\u{3042}").should == /#{"\x2e\u3042"}/
- end
-
- it "accepts a combination of escaped octal and hexadecimal digits and \\u{HHHH}" do
- Regexp.send(@method, "\056\x42\u{3042}\x52\076").should == /#{"\x2e\x42\u3042\x52\x3e"}/
- end
-
- it "accepts \\uHHHH for a single Unicode codepoint" do
- Regexp.send(@method, "\u3042").should == /#{"\u3042"}/
- end
-
- it "accepts characters followed by \\uHHHH" do
- Regexp.send(@method, "abc\u3042").should == /#{"abc\u3042"}/
- end
-
- it "accepts \\uHHHH followed by characters" do
- Regexp.send(@method, "\u3042abc").should == /#{"\u3042abc"}/
- end
-
- it "accepts escaped hexadecimal digits followed by \\uHHHH" do
- Regexp.send(@method, "\x42\u3042").should == /#{"\x42\u3042"}/
- end
-
- it "accepts escaped octal digits followed by \\uHHHH" do
- Regexp.send(@method, "\056\u3042").should == /#{"\x2e\u3042"}/
- end
-
- it "accepts a combination of escaped octal and hexadecimal digits and \\uHHHH" do
- Regexp.send(@method, "\056\x42\u3042\x52\076").should == /#{"\x2e\x42\u3042\x52\x3e"}/
- end
-
- it "accepts a multiple byte character which need not be escaped" do
- Regexp.send(@method, "\").should == /#{""}/
+ -> { Regexp.send(@method, "\\" + "xn") }.should raise_error(RegexpError, Regexp.new(Regexp.escape("invalid hex escape: /\\xn/")))
end
it "raises a RegexpError if less than four digits are given for \\uHHHH" do
- -> { Regexp.send(@method, "\\" + "u304") }.should raise_error(RegexpError)
+ -> { Regexp.send(@method, "\\" + "u304") }.should raise_error(RegexpError, Regexp.new(Regexp.escape("invalid Unicode escape: /\\u304/")))
end
it "raises a RegexpError if the \\u{} escape is empty" do
- -> { Regexp.send(@method, "\\" + "u{}") }.should raise_error(RegexpError)
+ -> { Regexp.send(@method, "\\" + "u{}") }.should raise_error(RegexpError, Regexp.new(Regexp.escape("invalid Unicode list: /\\u{}/")))
+ end
+
+ it "raises a RegexpError if the \\u{} escape contains non hexadecimal digits" do
+ -> { Regexp.send(@method, "\\" + "u{abcX}") }.should raise_error(RegexpError, Regexp.new(Regexp.escape("invalid Unicode list: /\\u{abcX}/")))
end
it "raises a RegexpError if more than six hexadecimal digits are given" do
- -> { Regexp.send(@method, "\\" + "u{0ffffff}") }.should raise_error(RegexpError)
+ -> { Regexp.send(@method, "\\" + "u{0ffffff}") }.should raise_error(RegexpError, Regexp.new(Regexp.escape("invalid Unicode range: /\\u{0ffffff}/")))
end
it "returns a Regexp with US-ASCII encoding if only 7-bit ASCII characters are present regardless of the input String's encoding" do
@@ -502,69 +257,6 @@ end
describe :regexp_new_string_binary, shared: true do
describe "with escaped characters" do
- it "accepts a three-digit octal value" do
- Regexp.send(@method, "\315").should == /#{"\xcd"}/
- end
-
- it "interprets a digit following a three-digit octal value as a character" do
- Regexp.send(@method, "\3762").should == /#{"\xfe2"}/
- end
-
- it "accepts '\\M-\\n'" do
- Regexp.send(@method, "\M-\n").should == /#{"\x8a"}/
- end
-
- it "accepts '\\M-\\t'" do
- Regexp.send(@method, "\M-\t").should == /#{"\x89"}/
- end
-
- it "accepts '\\M-\\r'" do
- Regexp.send(@method, "\M-\r").should == /#{"\x8d"}/
- end
-
- it "accepts '\\M-\\f'" do
- Regexp.send(@method, "\M-\f").should == /#{"\x8c"}/
- end
-
- it "accepts '\\M-\\v'" do
- Regexp.send(@method, "\M-\v").should == /#{"\x8b"}/
- end
-
- it "accepts '\\M-\\a'" do
- Regexp.send(@method, "\M-\a").should == /#{"\x87"}/
- end
-
- it "accepts '\\M-\\e'" do
- Regexp.send(@method, "\M-\e").should == /#{"\x9b"}/
- end
-
- it "accepts '\\M-\\C-\\n'" do
- Regexp.send(@method, "\M-\C-\n").should == /#{"\x8a"}/
- end
-
- it "accepts '\\M-\\C-\\t'" do
- Regexp.send(@method, "\M-\C-\t").should == /#{"\x89"}/
- end
-
- it "accepts '\\M-\\C-\\r'" do
- Regexp.send(@method, "\M-\C-\r").should == /#{"\x8d"}/
- end
-
- it "accepts '\\M-\\C-\\f'" do
- Regexp.send(@method, "\M-\C-\f").should == /#{"\x8c"}/
- end
-
- it "accepts '\\M-\\C-\\v'" do
- Regexp.send(@method, "\M-\C-\v").should == /#{"\x8b"}/
- end
-
- it "accepts '\\M-\\C-\\a'" do
- Regexp.send(@method, "\M-\C-\a").should == /#{"\x87"}/
- end
-
- it "accepts '\\M-\\C-\\e'" do
- Regexp.send(@method, "\M-\C-\e").should == /#{"\x9b"}/
- end
end
end
@@ -619,11 +311,5 @@ describe :regexp_new_regexp, shared: true do
it "sets the encoding to US-ASCII if the Regexp literal has the 'n' option and the source String is ASCII only" do
Regexp.send(@method, /Hi/n).encoding.should == Encoding::US_ASCII
end
-
- ruby_version_is ''...'3.2' do
- it "sets the encoding to source String's encoding if the Regexp literal has the 'n' option and the source String is not ASCII only" do
- Regexp.send(@method, Regexp.new("\\xff", nil, 'n')).encoding.should == Encoding::BINARY
- end
- end
end
end
diff --git a/spec/ruby/core/regexp/shared/quote.rb b/spec/ruby/core/regexp/shared/quote.rb
index b5ecc35f04..3f46a18b5b 100644
--- a/spec/ruby/core/regexp/shared/quote.rb
+++ b/spec/ruby/core/regexp/shared/quote.rb
@@ -1,9 +1,9 @@
-# -*- encoding: binary -*-
+# encoding: binary
describe :regexp_quote, shared: true do
it "escapes any characters with special meaning in a regular expression" do
- Regexp.send(@method, '\*?{}.+^[]()- ').should == '\\\\\*\?\{\}\.\+\^\[\]\(\)\-\\ '
- Regexp.send(@method, "\*?{}.+^[]()- ").should == '\\*\\?\\{\\}\\.\\+\\^\\[\\]\\(\\)\\-\\ '
+ Regexp.send(@method, '\*?{}.+^$[]()- ').should == '\\\\\*\?\{\}\.\+\^\$\[\]\(\)\-\\ '
+ Regexp.send(@method, "\*?{}.+^$[]()- ").should == '\\*\\?\\{\\}\\.\\+\\^\\$\\[\\]\\(\\)\\-\\ '
Regexp.send(@method, '\n\r\f\t').should == '\\\\n\\\\r\\\\f\\\\t'
Regexp.send(@method, "\n\r\f\t").should == '\\n\\r\\f\\t'
end
diff --git a/spec/ruby/core/regexp/timeout_spec.rb b/spec/ruby/core/regexp/timeout_spec.rb
index 6fce261814..c64103c82c 100644
--- a/spec/ruby/core/regexp/timeout_spec.rb
+++ b/spec/ruby/core/regexp/timeout_spec.rb
@@ -1,35 +1,33 @@
require_relative '../../spec_helper'
-ruby_version_is "3.2" do
- describe "Regexp.timeout" do
- after :each do
- Regexp.timeout = nil
- end
+describe "Regexp.timeout" do
+ after :each do
+ Regexp.timeout = nil
+ end
- it "returns global timeout" do
- Regexp.timeout = 3
- Regexp.timeout.should == 3
- end
+ it "returns global timeout" do
+ Regexp.timeout = 3
+ Regexp.timeout.should == 3
+ end
- it "raises Regexp::TimeoutError after global timeout elapsed" do
- Regexp.timeout = 0.001
- Regexp.timeout.should == 0.001
+ it "raises Regexp::TimeoutError after global timeout elapsed" do
+ Regexp.timeout = 0.001
+ Regexp.timeout.should == 0.001
- -> {
- # A typical ReDoS case
- /^(a*)*$/ =~ "a" * 1000000 + "x"
- }.should raise_error(Regexp::TimeoutError, "regexp match timeout")
- end
+ -> {
+ # A typical ReDoS case
+ /^(a*)*$/ =~ "a" * 1000000 + "x"
+ }.should raise_error(Regexp::TimeoutError, "regexp match timeout")
+ end
- it "raises Regexp::TimeoutError after timeout keyword value elapsed" do
- Regexp.timeout = 3 # This should be ignored
- Regexp.timeout.should == 3
+ it "raises Regexp::TimeoutError after timeout keyword value elapsed" do
+ Regexp.timeout = 3 # This should be ignored
+ Regexp.timeout.should == 3
- re = Regexp.new("^a*b?a*$", timeout: 0.001)
+ re = Regexp.new("^a*b?a*$", timeout: 0.001)
- -> {
- re =~ "a" * 1000000 + "x"
- }.should raise_error(Regexp::TimeoutError, "regexp match timeout")
- end
+ -> {
+ re =~ "a" * 1000000 + "x"
+ }.should raise_error(Regexp::TimeoutError, "regexp match timeout")
end
end
diff --git a/spec/ruby/core/set/add_spec.rb b/spec/ruby/core/set/add_spec.rb
new file mode 100644
index 0000000000..0fe1a0926c
--- /dev/null
+++ b/spec/ruby/core/set/add_spec.rb
@@ -0,0 +1,34 @@
+require_relative '../../spec_helper'
+require_relative 'shared/add'
+
+describe "Set#add" do
+ it_behaves_like :set_add, :add
+end
+
+describe "Set#add?" do
+ before :each do
+ @set = Set.new
+ 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
+ end
+
+ it "raises RuntimeError when called during iteration" do
+ set = Set[:a, :b, :c, :d, :e, :f]
+ set.each do |_m|
+ -> { set << 1 }.should raise_error(RuntimeError, /iteration/)
+ end
+ set.should == Set[:a, :b, :c, :d, :e, :f]
+ end
+end
diff --git a/spec/ruby/core/set/append_spec.rb b/spec/ruby/core/set/append_spec.rb
new file mode 100644
index 0000000000..82d34d9130
--- /dev/null
+++ b/spec/ruby/core/set/append_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/add'
+
+describe "Set#<<" do
+ it_behaves_like :set_add, :<<
+end
diff --git a/spec/ruby/core/set/case_compare_spec.rb b/spec/ruby/core/set/case_compare_spec.rb
new file mode 100644
index 0000000000..3781b1b963
--- /dev/null
+++ b/spec/ruby/core/set/case_compare_spec.rb
@@ -0,0 +1,11 @@
+require_relative '../../spec_helper'
+require_relative 'shared/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
+end
diff --git a/spec/ruby/core/set/case_equality_spec.rb b/spec/ruby/core/set/case_equality_spec.rb
new file mode 100644
index 0000000000..19c1fb6b9c
--- /dev/null
+++ b/spec/ruby/core/set/case_equality_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/include'
+
+describe "Set#===" do
+ it_behaves_like :set_include, :===
+end
diff --git a/spec/ruby/core/set/classify_spec.rb b/spec/ruby/core/set/classify_spec.rb
new file mode 100644
index 0000000000..d86ea2722d
--- /dev/null
+++ b/spec/ruby/core/set/classify_spec.rb
@@ -0,0 +1,26 @@
+require_relative '../../spec_helper'
+
+describe "Set#classify" do
+ before :each do
+ @set = Set["one", "two", "three", "four"]
+ end
+
+ it "yields each Object in self" do
+ res = []
+ @set.classify { |x| res << x }
+ res.sort.should == ["one", "two", "three", "four"].sort
+ 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 => Set["one", "two"], 4 => Set["four"], 5 => Set["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 => Set["one", "two"], 4 => Set["four"], 5 => Set["three"] }
+ end
+end
diff --git a/spec/ruby/core/set/clear_spec.rb b/spec/ruby/core/set/clear_spec.rb
new file mode 100644
index 0000000000..ebeac211d3
--- /dev/null
+++ b/spec/ruby/core/set/clear_spec.rb
@@ -0,0 +1,16 @@
+require_relative '../../spec_helper'
+
+describe "Set#clear" do
+ before :each do
+ @set = Set["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)
+ end
+end
diff --git a/spec/ruby/core/set/collect_spec.rb b/spec/ruby/core/set/collect_spec.rb
new file mode 100644
index 0000000000..d186f1a0d9
--- /dev/null
+++ b/spec/ruby/core/set/collect_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/collect'
+
+describe "Set#collect!" do
+ it_behaves_like :set_collect_bang, :collect!
+end
diff --git a/spec/ruby/core/set/compare_by_identity_spec.rb b/spec/ruby/core/set/compare_by_identity_spec.rb
new file mode 100644
index 0000000000..238dc117a6
--- /dev/null
+++ b/spec/ruby/core/set/compare_by_identity_spec.rb
@@ -0,0 +1,153 @@
+require_relative '../../spec_helper'
+
+describe "Set#compare_by_identity" do
+ it "compares its members by identity" do
+ a = "a"
+ b1 = "b"
+ b2 = b1.dup
+
+ set = Set.new
+ set.compare_by_identity
+ set.merge([a, a, b1, b2])
+ set.to_a.sort.should == [a, b1, b2].sort
+ end
+
+ it "causes future comparisons on the receiver to be made by identity" do
+ elt = [1]
+ set = Set.new
+ set << elt
+ set.member?(elt.dup).should be_true
+ set.compare_by_identity
+ set.member?(elt.dup).should be_false
+ end
+
+ it "rehashes internally so that old members can be looked up" do
+ set = Set.new
+ (1..10).each { |k| set << k }
+ o = Object.new
+ def o.hash; 123; end
+ set << o
+ set.compare_by_identity
+ set.member?(o).should be_true
+ end
+
+ it "returns self" do
+ set = Set.new
+ result = set.compare_by_identity
+ result.should equal(set)
+ end
+
+ it "is idempotent and has no effect on an already compare_by_identity set" do
+ set = Set.new.compare_by_identity
+ set << :foo
+ set.compare_by_identity.should equal(set)
+ set.should.compare_by_identity?
+ set.to_a.should == [:foo]
+ end
+
+ it "uses the semantics of BasicObject#equal? to determine members identity" do
+ :a.equal?(:a).should == true
+ Set.new.compare_by_identity.merge([:a, :a]).to_a.should == [:a]
+
+ ary1 = [1]
+ ary2 = [1]
+ ary1.equal?(ary2).should == false
+ Set.new.compare_by_identity.merge([ary1, ary2]).to_a.sort.should == [ary1, ary2].sort
+ end
+
+ it "uses #equal? semantics, but doesn't actually call #equal? to determine identity" do
+ set = Set.new.compare_by_identity
+ obj = mock("equal")
+ obj.should_not_receive(:equal?)
+ set << :foo
+ set << obj
+ set.to_a.should == [:foo, obj]
+ end
+
+ it "does not call #hash on members" do
+ elt = mock("element")
+ elt.should_not_receive(:hash)
+ set = Set.new.compare_by_identity
+ set << elt
+ set.member?(elt).should be_true
+ end
+
+ it "regards #dup'd objects as having different identities" do
+ a1 = "a"
+ a2 = a1.dup
+
+ set = Set.new.compare_by_identity
+ set.merge([a1, a2])
+ set.to_a.sort.should == [a1, a2].sort
+ end
+
+ it "regards #clone'd objects as having different identities" do
+ a1 = "a"
+ a2 = a1.clone
+
+ set = Set.new.compare_by_identity
+ set.merge([a1, a2])
+ set.to_a.sort.should == [a1, a2].sort
+ end
+
+ ruby_version_is "4.0" do
+ it "raises a FrozenError on frozen sets" do
+ set = Set.new.freeze
+ -> {
+ set.compare_by_identity
+ }.should raise_error(FrozenError, /can't modify frozen Set: (#<)?Set(\[|: {)[\]}]>?/)
+ end
+ end
+
+ ruby_version_is ""..."4.0" do
+ it "raises a FrozenError on frozen sets" do
+ set = Set.new.freeze
+ -> {
+ set.compare_by_identity
+ }.should raise_error(FrozenError, /frozen Hash/)
+ end
+ end
+
+ it "persists over #dups" do
+ set = Set.new.compare_by_identity
+ set << :a
+ set_dup = set.dup
+ set_dup.should == set
+ set_dup << :a
+ set_dup.to_a.should == [:a]
+ end
+
+ it "persists over #clones" do
+ set = Set.new.compare_by_identity
+ set << :a
+ set_clone = set.clone
+ set_clone.should == set
+ set_clone << :a
+ set_clone.to_a.should == [:a]
+ end
+
+ it "is not equal to set what does not compare by identity" do
+ Set.new([1, 2]).should == Set.new([1, 2])
+ Set.new([1, 2]).should_not == Set.new([1, 2]).compare_by_identity
+ end
+end
+
+describe "Set#compare_by_identity?" do
+ it "returns false by default" do
+ 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.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.should.compare_by_identity?
+ set.should.compare_by_identity?
+ set.should.compare_by_identity?
+ end
+end
diff --git a/spec/ruby/core/set/comparison_spec.rb b/spec/ruby/core/set/comparison_spec.rb
new file mode 100644
index 0000000000..62059b70b3
--- /dev/null
+++ b/spec/ruby/core/set/comparison_spec.rb
@@ -0,0 +1,26 @@
+require_relative '../../spec_helper'
+
+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
diff --git a/spec/ruby/core/set/constructor_spec.rb b/spec/ruby/core/set/constructor_spec.rb
new file mode 100644
index 0000000000..365081ad39
--- /dev/null
+++ b/spec/ruby/core/set/constructor_spec.rb
@@ -0,0 +1,14 @@
+require_relative '../../spec_helper'
+
+describe "Set[]" do
+ it "returns a new Set populated with the passed Objects" do
+ set = Set[1, 2, 3]
+
+ set.instance_of?(Set).should be_true
+ set.size.should eql(3)
+
+ set.should include(1)
+ set.should include(2)
+ set.should include(3)
+ end
+end
diff --git a/spec/ruby/core/set/delete_if_spec.rb b/spec/ruby/core/set/delete_if_spec.rb
new file mode 100644
index 0000000000..beda73a5e5
--- /dev/null
+++ b/spec/ruby/core/set/delete_if_spec.rb
@@ -0,0 +1,37 @@
+require_relative '../../spec_helper'
+
+describe "Set#delete_if" do
+ before :each do
+ @set = Set["one", "two", "three"]
+ end
+
+ it "yields every element of self" do
+ ret = []
+ @set.delete_if { |x| ret << x }
+ ret.sort.should == ["one", "two", "three"].sort
+ 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)
+
+ @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)
+
+ enum.each { |x| x.size == 3 }
+
+ @set.should_not include("one")
+ @set.should_not include("two")
+ @set.should include("three")
+ end
+end
diff --git a/spec/ruby/core/set/delete_spec.rb b/spec/ruby/core/set/delete_spec.rb
new file mode 100644
index 0000000000..a2543ecbee
--- /dev/null
+++ b/spec/ruby/core/set/delete_spec.rb
@@ -0,0 +1,36 @@
+require_relative '../../spec_helper'
+
+describe "Set#delete" do
+ before :each do
+ @set = Set["a", "b", "c"]
+ end
+
+ it "deletes the passed Object from self" do
+ @set.delete("a")
+ @set.should_not include("a")
+ end
+
+ it "returns self" do
+ @set.delete("a").should equal(@set)
+ @set.delete("x").should equal(@set)
+ end
+end
+
+describe "Set#delete?" do
+ before :each do
+ @set = Set["a", "b", "c"]
+ 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
+ end
+end
diff --git a/spec/ruby/core/set/difference_spec.rb b/spec/ruby/core/set/difference_spec.rb
new file mode 100644
index 0000000000..149f946592
--- /dev/null
+++ b/spec/ruby/core/set/difference_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/difference'
+
+describe "Set#difference" do
+ it_behaves_like :set_difference, :difference
+end
diff --git a/spec/ruby/core/set/disjoint_spec.rb b/spec/ruby/core/set/disjoint_spec.rb
new file mode 100644
index 0000000000..89a3c4b157
--- /dev/null
+++ b/spec/ruby/core/set/disjoint_spec.rb
@@ -0,0 +1,22 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/set_like'
+
+describe "Set#disjoint?" do
+ it "returns false when two Sets have at least one element in common" do
+ Set[1, 2].disjoint?(Set[2, 3]).should == false
+ end
+
+ it "returns true when two Sets have no element in common" do
+ Set[1, 2].disjoint?(Set[3, 4]).should == true
+ end
+
+ context "when comparing to a Set-like object" do
+ it "returns false when a Set has at least one element in common with a Set-like object" do
+ Set[1, 2].disjoint?(SetSpecs::SetLike.new([2, 3])).should be_false
+ end
+
+ it "returns true when a Set has no element in common with a Set-like object" do
+ Set[1, 2].disjoint?(SetSpecs::SetLike.new([3, 4])).should be_true
+ end
+ end
+end
diff --git a/spec/ruby/core/set/divide_spec.rb b/spec/ruby/core/set/divide_spec.rb
new file mode 100644
index 0000000000..c6c6003e99
--- /dev/null
+++ b/spec/ruby/core/set/divide_spec.rb
@@ -0,0 +1,68 @@
+require_relative '../../spec_helper'
+
+describe "Set#divide" do
+ it "divides self into a set of subsets based on the blocks return values" do
+ set = Set["one", "two", "three", "four", "five"].divide { |x| x.length }
+ set.map { |x| x.to_a.sort }.sort.should == [["five", "four"], ["one", "two"], ["three"]]
+ end
+
+ it "yields each Object to the block" do
+ ret = []
+ Set["one", "two", "three", "four", "five"].divide { |x| ret << x }
+ ret.sort.should == ["five", "four", "one", "three", "two"]
+ end
+
+ it "returns an enumerator when not passed a block" do
+ ret = Set[1, 2, 3, 4].divide
+ ret.should be_kind_of(Enumerator)
+ ret.each(&:even?).should == Set[Set[1, 3], Set[2, 4]]
+ end
+end
+
+describe "Set#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 = Set[1, 3, 4, 6, 9, 10, 11].divide { |x, y| (x - y).abs == 1 }
+ set.map{ |x| x.to_a.sort }.sort.should == [[1], [3, 4], [6], [9, 10, 11]]
+ end
+
+ ruby_version_is "4.0" do
+ it "yields each two Object to the block" do
+ ret = []
+ Set[1, 2].divide { |x, y| ret << [x, y] }
+ ret.sort.should == [[1, 2], [2, 1]]
+ end
+ end
+
+ ruby_version_is ""..."4.0" do
+ it "yields each two Object to the block" do
+ ret = []
+ Set[1, 2].divide { |x, y| ret << [x, y] }
+ ret.sort.should == [[1, 1], [1, 2], [2, 1], [2, 2]]
+ end
+ end
+
+ it "returns an enumerator when not passed a block" do
+ ret = Set[1, 2, 3, 4].divide
+ ret.should be_kind_of(Enumerator)
+ ret.each { |a, b| (a + b).even? }.should == Set[Set[1, 3], Set[2, 4]]
+ end
+end
+
+describe "Set#divide when passed a block with an arity of > 2" do
+ it "only uses the first element if the arity > 2" do
+ set = Set["one", "two", "three", "four", "five"].divide do |x, y, z|
+ y.should be_nil
+ z.should be_nil
+ x.length
+ end
+ set.map { |x| x.to_a.sort }.sort.should == [["five", "four"], ["one", "two"], ["three"]]
+ end
+
+ it "only uses the first element if the arity = -1" do
+ set = Set["one", "two", "three", "four", "five"].divide do |*xs|
+ xs.size.should == 1
+ xs.first.length
+ end
+ set.map { |x| x.to_a.sort }.sort.should == [["five", "four"], ["one", "two"], ["three"]]
+ end
+end
diff --git a/spec/ruby/core/set/each_spec.rb b/spec/ruby/core/set/each_spec.rb
new file mode 100644
index 0000000000..3d9cdc2d46
--- /dev/null
+++ b/spec/ruby/core/set/each_spec.rb
@@ -0,0 +1,26 @@
+require_relative '../../spec_helper'
+
+describe "Set#each" do
+ before :each do
+ @set = Set[1, 2, 3]
+ end
+
+ it "yields each Object in self" do
+ ret = []
+ @set.each { |x| ret << x }
+ ret.sort.should == [1, 2, 3]
+ 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
+ enum.should be_an_instance_of(Enumerator)
+
+ ret = []
+ enum.each { |x| ret << x }
+ ret.sort.should == [1, 2, 3]
+ end
+end
diff --git a/spec/ruby/core/set/empty_spec.rb b/spec/ruby/core/set/empty_spec.rb
new file mode 100644
index 0000000000..4b55658e20
--- /dev/null
+++ b/spec/ruby/core/set/empty_spec.rb
@@ -0,0 +1,9 @@
+require_relative '../../spec_helper'
+
+describe "Set#empty?" do
+ it "returns true if self is empty" do
+ Set[].empty?.should be_true
+ Set[1].empty?.should be_false
+ Set[1,2,3].empty?.should be_false
+ end
+end
diff --git a/spec/ruby/core/set/enumerable/to_set_spec.rb b/spec/ruby/core/set/enumerable/to_set_spec.rb
new file mode 100644
index 0000000000..f139e1c025
--- /dev/null
+++ b/spec/ruby/core/set/enumerable/to_set_spec.rb
@@ -0,0 +1,12 @@
+require_relative '../../../spec_helper'
+
+describe "Enumerable#to_set" do
+ it "returns a new Set created from self" do
+ [1, 2, 3].to_set.should == Set[1, 2, 3]
+ {a: 1, b: 2}.to_set.should == Set[[:b, 2], [:a, 1]]
+ end
+
+ it "passes down passed blocks" do
+ [1, 2, 3].to_set { |x| x * x }.should == Set[1, 4, 9]
+ end
+end
diff --git a/spec/ruby/core/set/eql_spec.rb b/spec/ruby/core/set/eql_spec.rb
new file mode 100644
index 0000000000..4ad5c3aa5a
--- /dev/null
+++ b/spec/ruby/core/set/eql_spec.rb
@@ -0,0 +1,14 @@
+require_relative '../../spec_helper'
+
+describe "Set#eql?" do
+ it "returns true when the passed argument is a Set and contains the same elements" do
+ Set[].should eql(Set[])
+ Set[1, 2, 3].should eql(Set[1, 2, 3])
+ Set[1, 2, 3].should eql(Set[3, 2, 1])
+ Set["a", :b, ?c].should eql(Set[?c, :b, "a"])
+
+ Set[1, 2, 3].should_not eql(Set[1.0, 2, 3])
+ Set[1, 2, 3].should_not eql(Set[2, 3])
+ Set[1, 2, 3].should_not eql(Set[])
+ end
+end
diff --git a/spec/ruby/core/set/equal_value_spec.rb b/spec/ruby/core/set/equal_value_spec.rb
new file mode 100644
index 0000000000..721a79a3f1
--- /dev/null
+++ b/spec/ruby/core/set/equal_value_spec.rb
@@ -0,0 +1,34 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/set_like'
+
+describe "Set#==" do
+ it "returns true when the passed Object is a Set and self and the Object contain the same elements" do
+ Set[].should == Set[]
+ Set[1, 2, 3].should == Set[1, 2, 3]
+ Set["1", "2", "3"].should == Set["1", "2", "3"]
+
+ Set[1, 2, 3].should_not == Set[1.0, 2, 3]
+ Set[1, 2, 3].should_not == [1, 2, 3]
+ end
+
+ it "does not depend on the order of the elements" do
+ Set[1, 2, 3].should == Set[3, 2, 1]
+ Set[:a, "b", ?c].should == Set[?c, "b", :a]
+ end
+
+ it "does not depend on the order of nested Sets" do
+ Set[Set[1], Set[2], Set[3]].should == Set[Set[3], Set[2], Set[1]]
+
+ set1 = Set[Set["a", "b"], Set["c", "d"], Set["e", "f"]]
+ set2 = Set[Set["c", "d"], Set["a", "b"], Set["e", "f"]]
+ set1.should == set2
+ end
+
+ ruby_version_is ""..."4.0" do
+ context "when comparing to a Set-like object" do
+ it "returns true when a Set and a Set-like object contain the same elements" do
+ Set[1, 2, 3].should == SetSpecs::SetLike.new([1, 2, 3])
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/set/exclusion_spec.rb b/spec/ruby/core/set/exclusion_spec.rb
new file mode 100644
index 0000000000..bbc29afa95
--- /dev/null
+++ b/spec/ruby/core/set/exclusion_spec.rb
@@ -0,0 +1,17 @@
+require_relative '../../spec_helper'
+
+describe "Set#^" do
+ before :each do
+ @set = Set[1, 2, 3, 4]
+ end
+
+ it "returns a new Set containing elements that are not in both self and the passed Enumerable" do
+ (@set ^ Set[3, 4, 5]).should == Set[1, 2, 5]
+ (@set ^ [3, 4, 5]).should == Set[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)
+ end
+end
diff --git a/spec/ruby/library/set/filter_spec.rb b/spec/ruby/core/set/filter_spec.rb
index 779254ad68..779254ad68 100644
--- a/spec/ruby/library/set/filter_spec.rb
+++ b/spec/ruby/core/set/filter_spec.rb
diff --git a/spec/ruby/core/set/fixtures/set_like.rb b/spec/ruby/core/set/fixtures/set_like.rb
new file mode 100644
index 0000000000..86dec2ed52
--- /dev/null
+++ b/spec/ruby/core/set/fixtures/set_like.rb
@@ -0,0 +1,30 @@
+
+module SetSpecs
+ # This class is used to test the interaction of "Set-like" objects with real Sets
+ #
+ # These "Set-like" objects reply to is_a?(Set) with true and thus real Set objects are able to transparently
+ # interoperate with them in a duck-typing manner.
+ class SetLike
+ include Enumerable
+
+ def is_a?(klass)
+ super || klass == ::Set
+ end
+
+ def initialize(entries)
+ @entries = entries
+ end
+
+ def each(&block)
+ @entries.each(&block)
+ end
+
+ def inspect
+ "#<#{self.class}: {#{map(&:inspect).join(", ")}}>"
+ end
+
+ def size
+ @entries.size
+ end
+ end
+end
diff --git a/spec/ruby/core/set/flatten_merge_spec.rb b/spec/ruby/core/set/flatten_merge_spec.rb
new file mode 100644
index 0000000000..13cedeead9
--- /dev/null
+++ b/spec/ruby/core/set/flatten_merge_spec.rb
@@ -0,0 +1,24 @@
+require_relative '../../spec_helper'
+
+describe "Set#flatten_merge" do
+ ruby_version_is ""..."4.0" do
+ it "is protected" do
+ Set.should have_protected_instance_method("flatten_merge")
+ end
+
+ it "flattens the passed Set and merges it into self" do
+ set1 = Set[1, 2]
+ set2 = Set[3, 4, Set[5, 6]]
+
+ set1.send(:flatten_merge, set2).should == Set[1, 2, 3, 4, 5, 6]
+ end
+
+ it "raises an ArgumentError when trying to flatten a recursive Set" do
+ set1 = Set[1, 2, 3]
+ set2 = Set[5, 6, 7]
+ set2 << set2
+
+ -> { set1.send(:flatten_merge, set2) }.should raise_error(ArgumentError)
+ end
+ end
+end
diff --git a/spec/ruby/core/set/flatten_spec.rb b/spec/ruby/core/set/flatten_spec.rb
new file mode 100644
index 0000000000..f2cb3dfa52
--- /dev/null
+++ b/spec/ruby/core/set/flatten_spec.rb
@@ -0,0 +1,59 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/set_like'
+set_version = defined?(Set::VERSION) ? Set::VERSION : '1.0.0'
+
+describe "Set#flatten" do
+ it "returns a copy of self with each included Set flattened" do
+ set = Set[1, 2, Set[3, 4, Set[5, 6, Set[7, 8]]], 9, 10]
+ flattened_set = set.flatten
+
+ flattened_set.should_not equal(set)
+ flattened_set.should == Set[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ end
+
+ it "raises an ArgumentError when self is recursive" do
+ (set = Set[]) << set
+ -> { set.flatten }.should raise_error(ArgumentError)
+ end
+
+ ruby_version_is ""..."4.0" do
+ context "when Set contains a Set-like object" do
+ it "returns a copy of self with each included Set-like object flattened" do
+ Set[SetSpecs::SetLike.new([1])].flatten.should == Set[1]
+ end
+ end
+ end
+end
+
+describe "Set#flatten!" do
+ it "flattens self" do
+ set = Set[1, 2, Set[3, 4, Set[5, 6, Set[7, 8]]], 9, 10]
+ set.flatten!
+ set.should == Set[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
+ end
+
+ it "returns self when self was modified" do
+ set = Set[1, 2, Set[3, 4]]
+ set.flatten!.should equal(set)
+ end
+
+ it "returns nil when self was not modified" do
+ set = Set[1, 2, 3, 4]
+ set.flatten!.should be_nil
+ end
+
+ it "raises an ArgumentError when self is recursive" do
+ (set = Set[]) << set
+ -> { set.flatten! }.should raise_error(ArgumentError)
+ end
+
+ version_is(set_version, ""..."1.1.0") do #ruby_version_is ""..."3.3" do
+ ruby_version_is ""..."4.0" do
+ context "when Set contains a Set-like object" do
+ it "flattens self, including Set-like objects" do
+ Set[SetSpecs::SetLike.new([1])].flatten!.should == Set[1]
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/set/hash_spec.rb b/spec/ruby/core/set/hash_spec.rb
new file mode 100644
index 0000000000..63a0aa66a5
--- /dev/null
+++ b/spec/ruby/core/set/hash_spec.rb
@@ -0,0 +1,19 @@
+require_relative '../../spec_helper'
+
+describe "Set#hash" do
+ it "is static" do
+ Set[].hash.should == Set[].hash
+ Set[1, 2, 3].hash.should == Set[1, 2, 3].hash
+ Set[:a, "b", ?c].hash.should == Set[?c, "b", :a].hash
+
+ Set[].hash.should_not == Set[1, 2, 3].hash
+ Set[1, 2, 3].hash.should_not == Set[:a, "b", ?c].hash
+ end
+
+ ruby_version_is ""..."4.0" do
+ # see https://github.com/jruby/jruby/issues/8393
+ it "is equal to nil.hash for an uninitialized Set" do
+ Set.allocate.hash.should == nil.hash
+ end
+ end
+end
diff --git a/spec/ruby/core/set/include_spec.rb b/spec/ruby/core/set/include_spec.rb
new file mode 100644
index 0000000000..dd33bbc3bd
--- /dev/null
+++ b/spec/ruby/core/set/include_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/include'
+
+describe "Set#include?" do
+ it_behaves_like :set_include, :include?
+end
diff --git a/spec/ruby/core/set/initialize_clone_spec.rb b/spec/ruby/core/set/initialize_clone_spec.rb
new file mode 100644
index 0000000000..13abb7ee4e
--- /dev/null
+++ b/spec/ruby/core/set/initialize_clone_spec.rb
@@ -0,0 +1,15 @@
+require_relative '../../spec_helper'
+
+describe "Set#initialize_clone" 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
diff --git a/spec/ruby/core/set/initialize_spec.rb b/spec/ruby/core/set/initialize_spec.rb
new file mode 100644
index 0000000000..ad9e1bd8c9
--- /dev/null
+++ b/spec/ruby/core/set/initialize_spec.rb
@@ -0,0 +1,72 @@
+require_relative '../../spec_helper'
+
+describe "Set#initialize" do
+ it "is private" do
+ Set.should have_private_instance_method(:initialize)
+ end
+
+ it "adds all elements of the passed Enumerable to self" do
+ s = Set.new([1, 2, 3])
+ s.size.should eql(3)
+ s.should include(1)
+ s.should include(2)
+ 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)
+
+ s = Set.new({})
+ s.size.should eql(0)
+ end
+
+ it "preprocesses all elements by a passed block before adding to self" do
+ s = Set.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 "should initialize with empty array and block" do
+ s = Set.new([]) { |x| x * x }
+ s.size.should eql(0)
+ end
+
+ it "should initialize with empty set and block" do
+ s = Set.new(Set.new) { |x| x * x }
+ s.size.should eql(0)
+ end
+
+ it "should initialize with just block" do
+ s = Set.new { |x| x * x }
+ s.size.should eql(0)
+ s.should eql(Set.new)
+ end
+end
diff --git a/spec/ruby/core/set/inspect_spec.rb b/spec/ruby/core/set/inspect_spec.rb
new file mode 100644
index 0000000000..0dcce83eb6
--- /dev/null
+++ b/spec/ruby/core/set/inspect_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/inspect'
+
+describe "Set#inspect" do
+ it_behaves_like :set_inspect, :inspect
+end
diff --git a/spec/ruby/core/set/intersect_spec.rb b/spec/ruby/core/set/intersect_spec.rb
new file mode 100644
index 0000000000..0736dea5fd
--- /dev/null
+++ b/spec/ruby/core/set/intersect_spec.rb
@@ -0,0 +1,22 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/set_like'
+
+describe "Set#intersect?" do
+ it "returns true when two Sets have at least one element in common" do
+ Set[1, 2].intersect?(Set[2, 3]).should == true
+ end
+
+ it "returns false when two Sets have no element in common" do
+ Set[1, 2].intersect?(Set[3, 4]).should == false
+ end
+
+ context "when comparing to a Set-like object" do
+ it "returns true when a Set has at least one element in common with a Set-like object" do
+ Set[1, 2].intersect?(SetSpecs::SetLike.new([2, 3])).should be_true
+ end
+
+ it "returns false when a Set has no element in common with a Set-like object" do
+ Set[1, 2].intersect?(SetSpecs::SetLike.new([3, 4])).should be_false
+ end
+ end
+end
diff --git a/spec/ruby/core/set/intersection_spec.rb b/spec/ruby/core/set/intersection_spec.rb
new file mode 100644
index 0000000000..136b886775
--- /dev/null
+++ b/spec/ruby/core/set/intersection_spec.rb
@@ -0,0 +1,10 @@
+require_relative '../../spec_helper'
+require_relative 'shared/intersection'
+
+describe "Set#intersection" do
+ it_behaves_like :set_intersection, :intersection
+end
+
+describe "Set#&" do
+ it_behaves_like :set_intersection, :&
+end
diff --git a/spec/ruby/core/set/join_spec.rb b/spec/ruby/core/set/join_spec.rb
new file mode 100644
index 0000000000..1c1e8a8af8
--- /dev/null
+++ b/spec/ruby/core/set/join_spec.rb
@@ -0,0 +1,30 @@
+require_relative '../../spec_helper'
+
+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
+
+ ruby_version_is ""..."4.0" do
+ 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/spec/ruby/core/set/keep_if_spec.rb b/spec/ruby/core/set/keep_if_spec.rb
new file mode 100644
index 0000000000..d6abdd6adc
--- /dev/null
+++ b/spec/ruby/core/set/keep_if_spec.rb
@@ -0,0 +1,37 @@
+require_relative '../../spec_helper'
+
+describe "Set#keep_if" do
+ before :each do
+ @set = Set["one", "two", "three"]
+ end
+
+ it "yields every element of self" do
+ ret = []
+ @set.keep_if { |x| ret << x }
+ ret.sort.should == ["one", "two", "three"].sort
+ end
+
+ it "keeps every element from self for which the passed block returns true" do
+ @set.keep_if { |x| x.size != 3 }
+ @set.size.should eql(1)
+
+ @set.should_not include("one")
+ @set.should_not include("two")
+ @set.should include("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)
+
+ enum.each { |x| x.size != 3 }
+
+ @set.should_not include("one")
+ @set.should_not include("two")
+ @set.should include("three")
+ end
+end
diff --git a/spec/ruby/core/set/length_spec.rb b/spec/ruby/core/set/length_spec.rb
new file mode 100644
index 0000000000..6bb697b4ca
--- /dev/null
+++ b/spec/ruby/core/set/length_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/length'
+
+describe "Set#length" do
+ it_behaves_like :set_length, :length
+end
diff --git a/spec/ruby/core/set/map_spec.rb b/spec/ruby/core/set/map_spec.rb
new file mode 100644
index 0000000000..996191b0a8
--- /dev/null
+++ b/spec/ruby/core/set/map_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/collect'
+
+describe "Set#map!" do
+ it_behaves_like :set_collect_bang, :map!
+end
diff --git a/spec/ruby/core/set/member_spec.rb b/spec/ruby/core/set/member_spec.rb
new file mode 100644
index 0000000000..5c82e8f826
--- /dev/null
+++ b/spec/ruby/core/set/member_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/include'
+
+describe "Set#member?" do
+ it_behaves_like :set_include, :member?
+end
diff --git a/spec/ruby/core/set/merge_spec.rb b/spec/ruby/core/set/merge_spec.rb
new file mode 100644
index 0000000000..0c6ed27670
--- /dev/null
+++ b/spec/ruby/core/set/merge_spec.rb
@@ -0,0 +1,37 @@
+require_relative '../../spec_helper'
+
+describe "Set#merge" do
+ it "adds the elements of the passed Enumerable to self" do
+ Set[:a, :b].merge(Set[:b, :c, :d]).should == Set[:a, :b, :c, :d]
+ Set[1, 2].merge([3, 4]).should == Set[1, 2, 3, 4]
+ end
+
+ it "returns self" do
+ set = Set[1, 2]
+ set.merge([3, 4]).should equal(set)
+ end
+
+ it "raises an ArgumentError when passed a non-Enumerable" do
+ -> { Set[1, 2].merge(1) }.should raise_error(ArgumentError)
+ -> { Set[1, 2].merge(Object.new) }.should raise_error(ArgumentError)
+ end
+
+ it "raises RuntimeError when called during iteration" do
+ set = Set[:a, :b]
+ set.each do |_m|
+ -> { set.merge([1, 2]) }.should raise_error(RuntimeError, /iteration/)
+ end
+ end
+
+ ruby_version_is ""..."3.3" do
+ it "accepts only a single argument" do
+ -> { Set[].merge([], []) }.should raise_error(ArgumentError, "wrong number of arguments (given 2, expected 1)")
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "accepts multiple arguments" do
+ Set[:a, :b].merge(Set[:b, :c], [:d]).should == Set[:a, :b, :c, :d]
+ end
+ end
+end
diff --git a/spec/ruby/core/set/minus_spec.rb b/spec/ruby/core/set/minus_spec.rb
new file mode 100644
index 0000000000..72f98f985e
--- /dev/null
+++ b/spec/ruby/core/set/minus_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/difference'
+
+describe "Set#-" do
+ it_behaves_like :set_difference, :-
+end
diff --git a/spec/ruby/core/set/plus_spec.rb b/spec/ruby/core/set/plus_spec.rb
new file mode 100644
index 0000000000..7e44ff0b7e
--- /dev/null
+++ b/spec/ruby/core/set/plus_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/union'
+
+describe "Set#+" do
+ it_behaves_like :set_union, :+
+end
diff --git a/spec/ruby/core/set/pretty_print_cycle_spec.rb b/spec/ruby/core/set/pretty_print_cycle_spec.rb
new file mode 100644
index 0000000000..7e6017c112
--- /dev/null
+++ b/spec/ruby/core/set/pretty_print_cycle_spec.rb
@@ -0,0 +1,14 @@
+require_relative '../../spec_helper'
+
+describe "Set#pretty_print_cycle" do
+ it "passes the 'pretty print' representation of a self-referencing Set to the pretty print writer" do
+ pp = mock("PrettyPrint")
+ ruby_version_is(""..."4.0") do
+ pp.should_receive(:text).with("#<Set: {...}>")
+ end
+ ruby_version_is("4.0") do
+ pp.should_receive(:text).with("Set[...]")
+ end
+ Set[1, 2, 3].pretty_print_cycle(pp)
+ end
+end
diff --git a/spec/ruby/core/set/proper_subset_spec.rb b/spec/ruby/core/set/proper_subset_spec.rb
new file mode 100644
index 0000000000..fb7848c001
--- /dev/null
+++ b/spec/ruby/core/set/proper_subset_spec.rb
@@ -0,0 +1,45 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/set_like'
+set_version = defined?(Set::VERSION) ? Set::VERSION : '1.0.0'
+
+describe "Set#proper_subset?" do
+ before :each do
+ @set = Set[1, 2, 3, 4]
+ end
+
+ it "returns true if passed a Set that self is a proper subset of" do
+ Set[].proper_subset?(@set).should be_true
+ Set[].proper_subset?(Set[1, 2, 3]).should be_true
+ Set[].proper_subset?(Set["a", :b, ?c]).should be_true
+
+ Set[1, 2, 3].proper_subset?(@set).should be_true
+ Set[1, 3].proper_subset?(@set).should be_true
+ Set[1, 2].proper_subset?(@set).should be_true
+ Set[1].proper_subset?(@set).should be_true
+
+ Set[5].proper_subset?(@set).should be_false
+ Set[1, 5].proper_subset?(@set).should be_false
+ Set[nil].proper_subset?(@set).should be_false
+ Set["test"].proper_subset?(@set).should be_false
+
+ @set.proper_subset?(@set).should be_false
+ Set[].proper_subset?(Set[]).should be_false
+ end
+
+ it "raises an ArgumentError when passed a non-Set" do
+ -> { Set[].proper_subset?([]) }.should raise_error(ArgumentError)
+ -> { Set[].proper_subset?(1) }.should raise_error(ArgumentError)
+ -> { Set[].proper_subset?("test") }.should raise_error(ArgumentError)
+ -> { Set[].proper_subset?(Object.new) }.should raise_error(ArgumentError)
+ end
+
+ version_is(set_version, ""..."1.1.0") do #ruby_version_is ""..."3.3" do
+ ruby_version_is ""..."4.0" do
+ context "when comparing to a Set-like object" do
+ it "returns true if passed a Set-like object that self is a proper subset of" do
+ Set[1, 2, 3].proper_subset?(SetSpecs::SetLike.new([1, 2, 3, 4])).should be_true
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/set/proper_superset_spec.rb b/spec/ruby/core/set/proper_superset_spec.rb
new file mode 100644
index 0000000000..dc1e87e230
--- /dev/null
+++ b/spec/ruby/core/set/proper_superset_spec.rb
@@ -0,0 +1,42 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/set_like'
+
+describe "Set#proper_superset?" do
+ before :each do
+ @set = Set[1, 2, 3, 4]
+ end
+
+ it "returns true if passed a Set that self is a proper superset of" do
+ @set.proper_superset?(Set[]).should be_true
+ Set[1, 2, 3].proper_superset?(Set[]).should be_true
+ Set["a", :b, ?c].proper_superset?(Set[]).should be_true
+
+ @set.proper_superset?(Set[1, 2, 3]).should be_true
+ @set.proper_superset?(Set[1, 3]).should be_true
+ @set.proper_superset?(Set[1, 2]).should be_true
+ @set.proper_superset?(Set[1]).should be_true
+
+ @set.proper_superset?(Set[5]).should be_false
+ @set.proper_superset?(Set[1, 5]).should be_false
+ @set.proper_superset?(Set[nil]).should be_false
+ @set.proper_superset?(Set["test"]).should be_false
+
+ @set.proper_superset?(@set).should be_false
+ Set[].proper_superset?(Set[]).should be_false
+ end
+
+ it "raises an ArgumentError when passed a non-Set" do
+ -> { Set[].proper_superset?([]) }.should raise_error(ArgumentError)
+ -> { Set[].proper_superset?(1) }.should raise_error(ArgumentError)
+ -> { Set[].proper_superset?("test") }.should raise_error(ArgumentError)
+ -> { Set[].proper_superset?(Object.new) }.should raise_error(ArgumentError)
+ end
+
+ ruby_version_is ""..."4.0" do
+ context "when comparing to a Set-like object" do
+ it "returns true if passed a Set-like object that self is a proper superset of" do
+ Set[1, 2, 3, 4].proper_superset?(SetSpecs::SetLike.new([1, 2, 3])).should be_true
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/set/reject_spec.rb b/spec/ruby/core/set/reject_spec.rb
new file mode 100644
index 0000000000..91d0293415
--- /dev/null
+++ b/spec/ruby/core/set/reject_spec.rb
@@ -0,0 +1,41 @@
+require_relative '../../spec_helper'
+
+describe "Set#reject!" do
+ before :each do
+ @set = Set["one", "two", "three"]
+ end
+
+ it "yields every element of self" do
+ ret = []
+ @set.reject! { |x| ret << x }
+ ret.sort.should == ["one", "two", "three"].sort
+ 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)
+
+ @set.should_not include("one")
+ @set.should_not include("two")
+ @set.should include("three")
+ 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)
+
+ enum.each { |x| x.size == 3 }
+
+ @set.should_not include("one")
+ @set.should_not include("two")
+ @set.should include("three")
+ end
+end
diff --git a/spec/ruby/core/set/replace_spec.rb b/spec/ruby/core/set/replace_spec.rb
new file mode 100644
index 0000000000..c66a2d0ec3
--- /dev/null
+++ b/spec/ruby/core/set/replace_spec.rb
@@ -0,0 +1,24 @@
+require_relative '../../spec_helper'
+
+describe "Set#replace" do
+ before :each do
+ @set = Set[:a, :b, :c]
+ end
+
+ it "replaces the contents with other and returns self" do
+ @set.replace(Set[1, 2, 3]).should == @set
+ @set.should == Set[1, 2, 3]
+ end
+
+ it "raises RuntimeError when called during iteration" do
+ set = Set[:a, :b, :c, :d, :e, :f]
+ set.each do |_m|
+ -> { set.replace(Set[1, 2, 3]) }.should raise_error(RuntimeError, /iteration/)
+ end
+ set.should == Set[:a, :b, :c, :d, :e, :f]
+ end
+
+ it "accepts any enumerable as other" do
+ @set.replace([1, 2, 3]).should == Set[1, 2, 3]
+ end
+end
diff --git a/spec/ruby/library/set/select_spec.rb b/spec/ruby/core/set/select_spec.rb
index b458ffacaa..b458ffacaa 100644
--- a/spec/ruby/library/set/select_spec.rb
+++ b/spec/ruby/core/set/select_spec.rb
diff --git a/spec/ruby/core/set/set_spec.rb b/spec/ruby/core/set/set_spec.rb
new file mode 100644
index 0000000000..fd1d2072e3
--- /dev/null
+++ b/spec/ruby/core/set/set_spec.rb
@@ -0,0 +1,10 @@
+require_relative '../../spec_helper'
+
+describe 'Set' do
+ it 'is available without explicit requiring' do
+ output = ruby_exe(<<~RUBY, options: '--disable-gems', args: '2>&1')
+ puts Set.new([1, 2, 3]).to_a.inspect
+ RUBY
+ output.chomp.should == "[1, 2, 3]"
+ end
+end
diff --git a/spec/ruby/library/set/shared/add.rb b/spec/ruby/core/set/shared/add.rb
index 9e797f5df9..9e797f5df9 100644
--- a/spec/ruby/library/set/shared/add.rb
+++ b/spec/ruby/core/set/shared/add.rb
diff --git a/spec/ruby/library/set/shared/collect.rb b/spec/ruby/core/set/shared/collect.rb
index bc58c231be..bc58c231be 100644
--- a/spec/ruby/library/set/shared/collect.rb
+++ b/spec/ruby/core/set/shared/collect.rb
diff --git a/spec/ruby/library/set/shared/difference.rb b/spec/ruby/core/set/shared/difference.rb
index f88987ed2a..f88987ed2a 100644
--- a/spec/ruby/library/set/shared/difference.rb
+++ b/spec/ruby/core/set/shared/difference.rb
diff --git a/spec/ruby/library/set/shared/include.rb b/spec/ruby/core/set/shared/include.rb
index b4d95cde24..b4d95cde24 100644
--- a/spec/ruby/library/set/shared/include.rb
+++ b/spec/ruby/core/set/shared/include.rb
diff --git a/spec/ruby/core/set/shared/inspect.rb b/spec/ruby/core/set/shared/inspect.rb
new file mode 100644
index 0000000000..a90af66c98
--- /dev/null
+++ b/spec/ruby/core/set/shared/inspect.rb
@@ -0,0 +1,45 @@
+describe :set_inspect, shared: true do
+ it "returns a String representation of self" do
+ Set[].send(@method).should be_kind_of(String)
+ Set[nil, false, true].send(@method).should be_kind_of(String)
+ Set[1, 2, 3].send(@method).should be_kind_of(String)
+ Set["1", "2", "3"].send(@method).should be_kind_of(String)
+ Set[:a, "b", Set[?c]].send(@method).should be_kind_of(String)
+ end
+
+ ruby_version_is "4.0" do
+ it "does include the elements of the set" do
+ Set["1"].send(@method).should == 'Set["1"]'
+ end
+ end
+
+ ruby_version_is ""..."4.0" do
+ it "does include the elements of the set" do
+ Set["1"].send(@method).should == '#<Set: {"1"}>'
+ end
+ end
+
+ it "puts spaces between the elements" do
+ Set["1", "2"].send(@method).should include('", "')
+ end
+
+ ruby_version_is "4.0" do
+ it "correctly handles cyclic-references" do
+ set1 = Set[]
+ set2 = Set[set1]
+ set1 << set2
+ set1.send(@method).should be_kind_of(String)
+ set1.send(@method).should include("Set[...]")
+ end
+ end
+
+ ruby_version_is ""..."4.0" do
+ it "correctly handles cyclic-references" do
+ set1 = Set[]
+ set2 = Set[set1]
+ set1 << set2
+ set1.send(@method).should be_kind_of(String)
+ set1.send(@method).should include("#<Set: {...}>")
+ end
+ end
+end
diff --git a/spec/ruby/library/set/shared/intersection.rb b/spec/ruby/core/set/shared/intersection.rb
index 5ae4199c94..5ae4199c94 100644
--- a/spec/ruby/library/set/shared/intersection.rb
+++ b/spec/ruby/core/set/shared/intersection.rb
diff --git a/spec/ruby/library/set/shared/length.rb b/spec/ruby/core/set/shared/length.rb
index a8fcee9f39..a8fcee9f39 100644
--- a/spec/ruby/library/set/shared/length.rb
+++ b/spec/ruby/core/set/shared/length.rb
diff --git a/spec/ruby/core/set/shared/select.rb b/spec/ruby/core/set/shared/select.rb
new file mode 100644
index 0000000000..467b236ed3
--- /dev/null
+++ b/spec/ruby/core/set/shared/select.rb
@@ -0,0 +1,41 @@
+require_relative '../../../spec_helper'
+
+describe :set_select_bang, shared: true do
+ before :each do
+ @set = Set["one", "two", "three"]
+ end
+
+ it "yields every element of self" do
+ ret = []
+ @set.send(@method) { |x| ret << x }
+ ret.sort.should == ["one", "two", "three"].sort
+ end
+
+ it "keeps every element from self for which the passed block returns true" do
+ @set.send(@method) { |x| x.size != 3 }
+ @set.size.should eql(1)
+
+ @set.should_not include("one")
+ @set.should_not include("two")
+ @set.should include("three")
+ end
+
+ it "returns self when self was modified" do
+ @set.send(@method) { false }.should equal(@set)
+ end
+
+ it "returns nil when self was not modified" do
+ @set.send(@method) { true }.should be_nil
+ end
+
+ it "returns an Enumerator when passed no block" do
+ enum = @set.send(@method)
+ enum.should be_an_instance_of(Enumerator)
+
+ enum.each { |x| x.size != 3 }
+
+ @set.should_not include("one")
+ @set.should_not include("two")
+ @set.should include("three")
+ end
+end
diff --git a/spec/ruby/library/set/shared/union.rb b/spec/ruby/core/set/shared/union.rb
index 314f0e852d..314f0e852d 100644
--- a/spec/ruby/library/set/shared/union.rb
+++ b/spec/ruby/core/set/shared/union.rb
diff --git a/spec/ruby/core/set/size_spec.rb b/spec/ruby/core/set/size_spec.rb
new file mode 100644
index 0000000000..4ae22c5f0a
--- /dev/null
+++ b/spec/ruby/core/set/size_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/length'
+
+describe "Set#size" do
+ it_behaves_like :set_length, :size
+end
diff --git a/spec/ruby/core/set/sortedset/sortedset_spec.rb b/spec/ruby/core/set/sortedset/sortedset_spec.rb
new file mode 100644
index 0000000000..f3c1ec058d
--- /dev/null
+++ b/spec/ruby/core/set/sortedset/sortedset_spec.rb
@@ -0,0 +1,13 @@
+require_relative '../../../spec_helper'
+
+describe "SortedSet" do
+ ruby_version_is ""..."4.0" 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
diff --git a/spec/ruby/core/set/subset_spec.rb b/spec/ruby/core/set/subset_spec.rb
new file mode 100644
index 0000000000..112bd9b38a
--- /dev/null
+++ b/spec/ruby/core/set/subset_spec.rb
@@ -0,0 +1,45 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/set_like'
+set_version = defined?(Set::VERSION) ? Set::VERSION : '1.0.0'
+
+describe "Set#subset?" do
+ before :each do
+ @set = Set[1, 2, 3, 4]
+ end
+
+ it "returns true if passed a Set that is equal to self or self is a subset of" do
+ @set.subset?(@set).should be_true
+ Set[].subset?(Set[]).should be_true
+
+ Set[].subset?(@set).should be_true
+ Set[].subset?(Set[1, 2, 3]).should be_true
+ Set[].subset?(Set["a", :b, ?c]).should be_true
+
+ Set[1, 2, 3].subset?(@set).should be_true
+ Set[1, 3].subset?(@set).should be_true
+ Set[1, 2].subset?(@set).should be_true
+ Set[1].subset?(@set).should be_true
+
+ Set[5].subset?(@set).should be_false
+ Set[1, 5].subset?(@set).should be_false
+ Set[nil].subset?(@set).should be_false
+ Set["test"].subset?(@set).should be_false
+ end
+
+ it "raises an ArgumentError when passed a non-Set" do
+ -> { Set[].subset?([]) }.should raise_error(ArgumentError)
+ -> { Set[].subset?(1) }.should raise_error(ArgumentError)
+ -> { Set[].subset?("test") }.should raise_error(ArgumentError)
+ -> { Set[].subset?(Object.new) }.should raise_error(ArgumentError)
+ end
+
+ version_is(set_version, ""..."1.1.0") do #ruby_version_is ""..."3.3" do
+ ruby_version_is ""..."4.0" do
+ context "when comparing to a Set-like object" do
+ it "returns true if passed a Set-like object that self is a subset of" do
+ Set[1, 2, 3].subset?(SetSpecs::SetLike.new([1, 2, 3, 4])).should be_true
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/set/subtract_spec.rb b/spec/ruby/core/set/subtract_spec.rb
new file mode 100644
index 0000000000..ae4bc73d41
--- /dev/null
+++ b/spec/ruby/core/set/subtract_spec.rb
@@ -0,0 +1,16 @@
+require_relative '../../spec_helper'
+
+describe "Set#subtract" do
+ before :each do
+ @set = Set[:a, :b, :c]
+ end
+
+ it "deletes any elements contained in other and returns self" do
+ @set.subtract(Set[:b, :c]).should == @set
+ @set.should == Set[:a]
+ end
+
+ it "accepts any enumerable as other" do
+ @set.subtract([:c]).should == Set[:a, :b]
+ end
+end
diff --git a/spec/ruby/core/set/superset_spec.rb b/spec/ruby/core/set/superset_spec.rb
new file mode 100644
index 0000000000..9b3df2d047
--- /dev/null
+++ b/spec/ruby/core/set/superset_spec.rb
@@ -0,0 +1,42 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/set_like'
+
+describe "Set#superset?" do
+ before :each do
+ @set = Set[1, 2, 3, 4]
+ end
+
+ it "returns true if passed a Set that equals self or self is a proper superset of" do
+ @set.superset?(@set).should be_true
+ Set[].superset?(Set[]).should be_true
+
+ @set.superset?(Set[]).should be_true
+ Set[1, 2, 3].superset?(Set[]).should be_true
+ Set["a", :b, ?c].superset?(Set[]).should be_true
+
+ @set.superset?(Set[1, 2, 3]).should be_true
+ @set.superset?(Set[1, 3]).should be_true
+ @set.superset?(Set[1, 2]).should be_true
+ @set.superset?(Set[1]).should be_true
+
+ @set.superset?(Set[5]).should be_false
+ @set.superset?(Set[1, 5]).should be_false
+ @set.superset?(Set[nil]).should be_false
+ @set.superset?(Set["test"]).should be_false
+ end
+
+ it "raises an ArgumentError when passed a non-Set" do
+ -> { Set[].superset?([]) }.should raise_error(ArgumentError)
+ -> { Set[].superset?(1) }.should raise_error(ArgumentError)
+ -> { Set[].superset?("test") }.should raise_error(ArgumentError)
+ -> { Set[].superset?(Object.new) }.should raise_error(ArgumentError)
+ end
+
+ ruby_version_is ""..."4.0" do
+ context "when comparing to a Set-like object" do
+ it "returns true if passed a Set-like object that self is a superset of" do
+ Set[1, 2, 3, 4].superset?(SetSpecs::SetLike.new([1, 2, 3])).should be_true
+ end
+ end
+ end
+end
diff --git a/spec/ruby/core/set/to_a_spec.rb b/spec/ruby/core/set/to_a_spec.rb
new file mode 100644
index 0000000000..1e9800167a
--- /dev/null
+++ b/spec/ruby/core/set/to_a_spec.rb
@@ -0,0 +1,7 @@
+require_relative '../../spec_helper'
+
+describe "Set#to_a" do
+ it "returns an array containing elements of self" do
+ Set[1, 2, 3].to_a.sort.should == [1, 2, 3]
+ end
+end
diff --git a/spec/ruby/core/set/to_s_spec.rb b/spec/ruby/core/set/to_s_spec.rb
new file mode 100644
index 0000000000..55b8bfd9b2
--- /dev/null
+++ b/spec/ruby/core/set/to_s_spec.rb
@@ -0,0 +1,11 @@
+require_relative "../../spec_helper"
+require_relative 'shared/inspect'
+
+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
+end
diff --git a/spec/ruby/core/set/union_spec.rb b/spec/ruby/core/set/union_spec.rb
new file mode 100644
index 0000000000..3e77022d4b
--- /dev/null
+++ b/spec/ruby/core/set/union_spec.rb
@@ -0,0 +1,10 @@
+require_relative '../../spec_helper'
+require_relative 'shared/union'
+
+describe "Set#union" do
+ it_behaves_like :set_union, :union
+end
+
+describe "Set#|" do
+ it_behaves_like :set_union, :|
+end
diff --git a/spec/ruby/core/sizedqueue/append_spec.rb b/spec/ruby/core/sizedqueue/append_spec.rb
index 6fffe2f272..c52baa3802 100644
--- a/spec/ruby/core/sizedqueue/append_spec.rb
+++ b/spec/ruby/core/sizedqueue/append_spec.rb
@@ -12,7 +12,5 @@ describe "SizedQueue#<<" do
end
describe "SizedQueue operations with timeout" do
- ruby_version_is "3.2" do
- it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(1); q.send(:<<, 1, timeout: v) }
- end
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(1); q.send(:<<, 1, timeout: v) }
end
diff --git a/spec/ruby/core/sizedqueue/deq_spec.rb b/spec/ruby/core/sizedqueue/deq_spec.rb
index 985d654bb3..2aeb52f8a6 100644
--- a/spec/ruby/core/sizedqueue/deq_spec.rb
+++ b/spec/ruby/core/sizedqueue/deq_spec.rb
@@ -7,7 +7,5 @@ describe "SizedQueue#deq" do
end
describe "SizedQueue operations with timeout" do
- ruby_version_is "3.2" do
- it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(10); q.push(1); q.deq(timeout: v) }
- end
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(10); q.push(1); q.deq(timeout: v) }
end
diff --git a/spec/ruby/core/sizedqueue/enq_spec.rb b/spec/ruby/core/sizedqueue/enq_spec.rb
index 619373e46b..b955909475 100644
--- a/spec/ruby/core/sizedqueue/enq_spec.rb
+++ b/spec/ruby/core/sizedqueue/enq_spec.rb
@@ -12,7 +12,5 @@ describe "SizedQueue#enq" do
end
describe "SizedQueue operations with timeout" do
- ruby_version_is "3.2" do
- it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(1); q.enq(1, timeout: v) }
- end
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(1); q.enq(1, timeout: v) }
end
diff --git a/spec/ruby/core/sizedqueue/freeze_spec.rb b/spec/ruby/core/sizedqueue/freeze_spec.rb
new file mode 100644
index 0000000000..98f01cae2f
--- /dev/null
+++ b/spec/ruby/core/sizedqueue/freeze_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative '../../shared/queue/freeze'
+
+describe "SizedQueue#freeze" do
+ it_behaves_like :queue_freeze, :freeze, -> { SizedQueue.new(1) }
+end
diff --git a/spec/ruby/core/sizedqueue/pop_spec.rb b/spec/ruby/core/sizedqueue/pop_spec.rb
index 5e7cfea8fb..6338ddbaa0 100644
--- a/spec/ruby/core/sizedqueue/pop_spec.rb
+++ b/spec/ruby/core/sizedqueue/pop_spec.rb
@@ -7,7 +7,5 @@ describe "SizedQueue#pop" do
end
describe "SizedQueue operations with timeout" do
- ruby_version_is "3.2" do
- it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(10); q.push(1); q.pop(timeout: v) }
- end
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(10); q.push(1); q.pop(timeout: v) }
end
diff --git a/spec/ruby/core/sizedqueue/push_spec.rb b/spec/ruby/core/sizedqueue/push_spec.rb
index ce61e89b53..9eaa6beca0 100644
--- a/spec/ruby/core/sizedqueue/push_spec.rb
+++ b/spec/ruby/core/sizedqueue/push_spec.rb
@@ -12,7 +12,5 @@ describe "SizedQueue#push" do
end
describe "SizedQueue operations with timeout" do
- ruby_version_is "3.2" do
- it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(1); q.push(1, timeout: v) }
- end
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(1); q.push(1, timeout: v) }
end
diff --git a/spec/ruby/core/sizedqueue/shift_spec.rb b/spec/ruby/core/sizedqueue/shift_spec.rb
index 3220801f3a..52974c1d99 100644
--- a/spec/ruby/core/sizedqueue/shift_spec.rb
+++ b/spec/ruby/core/sizedqueue/shift_spec.rb
@@ -7,7 +7,5 @@ describe "SizedQueue#shift" do
end
describe "SizedQueue operations with timeout" do
- ruby_version_is "3.2" do
- it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(10); q.push(1); q.shift(timeout: v) }
- end
+ it_behaves_like :rb_num2dbl_fails, nil, -> v { q = SizedQueue.new(10); q.push(1); q.shift(timeout: v) }
end
diff --git a/spec/ruby/core/string/append_as_bytes_spec.rb b/spec/ruby/core/string/append_as_bytes_spec.rb
new file mode 100644
index 0000000000..b1703e5f89
--- /dev/null
+++ b/spec/ruby/core/string/append_as_bytes_spec.rb
@@ -0,0 +1,58 @@
+require_relative '../../spec_helper'
+
+describe "String#append_bytes" do
+ ruby_version_is "3.4" do
+ it "doesn't allow to mutate frozen strings" do
+ str = "hello".freeze
+ -> { str.append_as_bytes("\xE2\x82") }.should raise_error(FrozenError)
+ end
+
+ it "allows creating broken strings" do
+ str = +"hello"
+ str.append_as_bytes("\xE2\x82")
+ str.valid_encoding?.should == false
+
+ str.append_as_bytes("\xAC")
+ str.valid_encoding?.should == true
+
+ str = "abc".encode(Encoding::UTF_32LE)
+ str.append_as_bytes("def")
+ str.encoding.should == Encoding::UTF_32LE
+ str.valid_encoding?.should == false
+ end
+
+ it "never changes the receiver encoding" do
+ str = "".b
+ str.append_as_bytes("€")
+ str.encoding.should == Encoding::BINARY
+ end
+
+ it "accepts variadic String or Integer arguments" do
+ str = "hello".b
+ str.append_as_bytes("\xE2\x82", 12, 43, "\xAC")
+ str.encoding.should == Encoding::BINARY
+ str.should == "hello\xE2\x82\f+\xAC".b
+ end
+
+ it "truncates integers to the least significant byte" do
+ str = +""
+ str.append_as_bytes(0x131, 0x232, 0x333, bignum_value, bignum_value(1))
+ str.bytes.should == [0x31, 0x32, 0x33, 0, 1]
+ end
+
+ it "wraps negative integers" do
+ str = "".b
+ str.append_as_bytes(-1, -bignum_value, -bignum_value(1))
+ str.bytes.should == [0xFF, 0, 0xFF]
+ end
+
+ it "only accepts strings or integers, and doesn't attempt to cast with #to_str or #to_int" do
+ to_str = mock("to_str")
+ to_str.should_not_receive(:to_str)
+ to_str.should_not_receive(:to_int)
+
+ str = +"hello"
+ -> { str.append_as_bytes(to_str) }.should raise_error(TypeError, "wrong argument type MockObject (expected String or Integer)")
+ end
+ end
+end
diff --git a/spec/ruby/core/string/byteindex_spec.rb b/spec/ruby/core/string/byteindex_spec.rb
index 47c7be1029..d420f3f683 100644
--- a/spec/ruby/core/string/byteindex_spec.rb
+++ b/spec/ruby/core/string/byteindex_spec.rb
@@ -4,301 +4,295 @@ require_relative 'fixtures/classes'
require_relative 'shared/byte_index_common.rb'
describe "String#byteindex" do
- ruby_version_is "3.2" do
- it "calls #to_str to convert the first argument" do
- char = mock("string index char")
- char.should_receive(:to_str).and_return("b")
- "abc".byteindex(char).should == 1
- end
-
- it "calls #to_int to convert the second argument" do
- offset = mock("string index offset")
- offset.should_receive(:to_int).and_return(1)
- "abc".byteindex("c", offset).should == 2
- end
+ it "calls #to_str to convert the first argument" do
+ char = mock("string index char")
+ char.should_receive(:to_str).and_return("b")
+ "abc".byteindex(char).should == 1
+ end
- it "does not raise IndexError when byte offset is correct or on string boundary" do
- "わ".byteindex("").should == 0
- "わ".byteindex("", 0).should == 0
- "わ".byteindex("", 3).should == 3
- end
+ it "calls #to_int to convert the second argument" do
+ offset = mock("string index offset")
+ offset.should_receive(:to_int).and_return(1)
+ "abc".byteindex("c", offset).should == 2
+ end
- it_behaves_like :byte_index_common, :byteindex
+ it "does not raise IndexError when byte offset is correct or on string boundary" do
+ "わ".byteindex("").should == 0
+ "わ".byteindex("", 0).should == 0
+ "わ".byteindex("", 3).should == 3
end
+
+ it_behaves_like :byte_index_common, :byteindex
end
describe "String#byteindex with String" do
- ruby_version_is "3.2" do
- it "behaves the same as String#byteindex(char) for one-character strings" do
- "blablabla hello cruel world...!".split("").uniq.each do |str|
- chr = str[0]
- str.byteindex(str).should == str.byteindex(chr)
+ it "behaves the same as String#byteindex(char) for one-character strings" do
+ "blablabla hello cruel world...!".split("").uniq.each do |str|
+ chr = str[0]
+ str.byteindex(str).should == str.byteindex(chr)
- 0.upto(str.size + 1) do |start|
- str.byteindex(str, start).should == str.byteindex(chr, start)
- end
+ 0.upto(str.size + 1) do |start|
+ str.byteindex(str, start).should == str.byteindex(chr, start)
+ end
- (-str.size - 1).upto(-1) do |start|
- str.byteindex(str, start).should == str.byteindex(chr, start)
- end
+ (-str.size - 1).upto(-1) do |start|
+ str.byteindex(str, start).should == str.byteindex(chr, start)
end
end
+ end
- it "returns the byteindex of the first occurrence of the given substring" do
- "blablabla".byteindex("").should == 0
- "blablabla".byteindex("b").should == 0
- "blablabla".byteindex("bla").should == 0
- "blablabla".byteindex("blabla").should == 0
- "blablabla".byteindex("blablabla").should == 0
-
- "blablabla".byteindex("l").should == 1
- "blablabla".byteindex("la").should == 1
- "blablabla".byteindex("labla").should == 1
- "blablabla".byteindex("lablabla").should == 1
-
- "blablabla".byteindex("a").should == 2
- "blablabla".byteindex("abla").should == 2
- "blablabla".byteindex("ablabla").should == 2
- end
+ it "returns the byteindex of the first occurrence of the given substring" do
+ "blablabla".byteindex("").should == 0
+ "blablabla".byteindex("b").should == 0
+ "blablabla".byteindex("bla").should == 0
+ "blablabla".byteindex("blabla").should == 0
+ "blablabla".byteindex("blablabla").should == 0
+
+ "blablabla".byteindex("l").should == 1
+ "blablabla".byteindex("la").should == 1
+ "blablabla".byteindex("labla").should == 1
+ "blablabla".byteindex("lablabla").should == 1
+
+ "blablabla".byteindex("a").should == 2
+ "blablabla".byteindex("abla").should == 2
+ "blablabla".byteindex("ablabla").should == 2
+ end
- it "treats the offset as a byteindex" do
- "aaaaa".byteindex("a", 0).should == 0
- "aaaaa".byteindex("a", 2).should == 2
- "aaaaa".byteindex("a", 4).should == 4
- end
+ it "treats the offset as a byteindex" do
+ "aaaaa".byteindex("a", 0).should == 0
+ "aaaaa".byteindex("a", 2).should == 2
+ "aaaaa".byteindex("a", 4).should == 4
+ end
- it "ignores string subclasses" do
- "blablabla".byteindex(StringSpecs::MyString.new("bla")).should == 0
- StringSpecs::MyString.new("blablabla").byteindex("bla").should == 0
- StringSpecs::MyString.new("blablabla").byteindex(StringSpecs::MyString.new("bla")).should == 0
- end
+ it "ignores string subclasses" do
+ "blablabla".byteindex(StringSpecs::MyString.new("bla")).should == 0
+ StringSpecs::MyString.new("blablabla").byteindex("bla").should == 0
+ StringSpecs::MyString.new("blablabla").byteindex(StringSpecs::MyString.new("bla")).should == 0
+ end
- it "starts the search at the given offset" do
- "blablabla".byteindex("bl", 0).should == 0
- "blablabla".byteindex("bl", 1).should == 3
- "blablabla".byteindex("bl", 2).should == 3
- "blablabla".byteindex("bl", 3).should == 3
-
- "blablabla".byteindex("bla", 0).should == 0
- "blablabla".byteindex("bla", 1).should == 3
- "blablabla".byteindex("bla", 2).should == 3
- "blablabla".byteindex("bla", 3).should == 3
-
- "blablabla".byteindex("blab", 0).should == 0
- "blablabla".byteindex("blab", 1).should == 3
- "blablabla".byteindex("blab", 2).should == 3
- "blablabla".byteindex("blab", 3).should == 3
-
- "blablabla".byteindex("la", 1).should == 1
- "blablabla".byteindex("la", 2).should == 4
- "blablabla".byteindex("la", 3).should == 4
- "blablabla".byteindex("la", 4).should == 4
-
- "blablabla".byteindex("lab", 1).should == 1
- "blablabla".byteindex("lab", 2).should == 4
- "blablabla".byteindex("lab", 3).should == 4
- "blablabla".byteindex("lab", 4).should == 4
-
- "blablabla".byteindex("ab", 2).should == 2
- "blablabla".byteindex("ab", 3).should == 5
- "blablabla".byteindex("ab", 4).should == 5
- "blablabla".byteindex("ab", 5).should == 5
-
- "blablabla".byteindex("", 0).should == 0
- "blablabla".byteindex("", 1).should == 1
- "blablabla".byteindex("", 2).should == 2
- "blablabla".byteindex("", 7).should == 7
- "blablabla".byteindex("", 8).should == 8
- "blablabla".byteindex("", 9).should == 9
- end
+ it "starts the search at the given offset" do
+ "blablabla".byteindex("bl", 0).should == 0
+ "blablabla".byteindex("bl", 1).should == 3
+ "blablabla".byteindex("bl", 2).should == 3
+ "blablabla".byteindex("bl", 3).should == 3
+
+ "blablabla".byteindex("bla", 0).should == 0
+ "blablabla".byteindex("bla", 1).should == 3
+ "blablabla".byteindex("bla", 2).should == 3
+ "blablabla".byteindex("bla", 3).should == 3
+
+ "blablabla".byteindex("blab", 0).should == 0
+ "blablabla".byteindex("blab", 1).should == 3
+ "blablabla".byteindex("blab", 2).should == 3
+ "blablabla".byteindex("blab", 3).should == 3
+
+ "blablabla".byteindex("la", 1).should == 1
+ "blablabla".byteindex("la", 2).should == 4
+ "blablabla".byteindex("la", 3).should == 4
+ "blablabla".byteindex("la", 4).should == 4
+
+ "blablabla".byteindex("lab", 1).should == 1
+ "blablabla".byteindex("lab", 2).should == 4
+ "blablabla".byteindex("lab", 3).should == 4
+ "blablabla".byteindex("lab", 4).should == 4
+
+ "blablabla".byteindex("ab", 2).should == 2
+ "blablabla".byteindex("ab", 3).should == 5
+ "blablabla".byteindex("ab", 4).should == 5
+ "blablabla".byteindex("ab", 5).should == 5
+
+ "blablabla".byteindex("", 0).should == 0
+ "blablabla".byteindex("", 1).should == 1
+ "blablabla".byteindex("", 2).should == 2
+ "blablabla".byteindex("", 7).should == 7
+ "blablabla".byteindex("", 8).should == 8
+ "blablabla".byteindex("", 9).should == 9
+ end
- it "starts the search at offset + self.length if offset is negative" do
- str = "blablabla"
+ it "starts the search at offset + self.length if offset is negative" do
+ str = "blablabla"
- ["bl", "bla", "blab", "la", "lab", "ab", ""].each do |needle|
- (-str.length .. -1).each do |offset|
- str.byteindex(needle, offset).should ==
- str.byteindex(needle, offset + str.length)
- end
+ ["bl", "bla", "blab", "la", "lab", "ab", ""].each do |needle|
+ (-str.length .. -1).each do |offset|
+ str.byteindex(needle, offset).should ==
+ str.byteindex(needle, offset + str.length)
end
end
+ end
- it "returns nil if the substring isn't found" do
- "blablabla".byteindex("B").should == nil
- "blablabla".byteindex("z").should == nil
- "blablabla".byteindex("BLA").should == nil
- "blablabla".byteindex("blablablabla").should == nil
- "blablabla".byteindex("", 10).should == nil
+ it "returns nil if the substring isn't found" do
+ "blablabla".byteindex("B").should == nil
+ "blablabla".byteindex("z").should == nil
+ "blablabla".byteindex("BLA").should == nil
+ "blablabla".byteindex("blablablabla").should == nil
+ "blablabla".byteindex("", 10).should == nil
- "hello".byteindex("he", 1).should == nil
- "hello".byteindex("he", 2).should == nil
- "I’ve got a multibyte character.\n".byteindex("\n\n").should == nil
- end
+ "hello".byteindex("he", 1).should == nil
+ "hello".byteindex("he", 2).should == nil
+ "I’ve got a multibyte character.\n".byteindex("\n\n").should == nil
+ end
- it "returns the character byteindex of a multibyte character" do
- "ありがとう".byteindex("が").should == 6
- end
+ it "returns the character byteindex of a multibyte character" do
+ "ありがとう".byteindex("が").should == 6
+ end
- it "returns the character byteindex after offset" do
- "われわれ".byteindex("わ", 3).should == 6
- "ありがとうありがとう".byteindex("が", 9).should == 21
- end
+ it "returns the character byteindex after offset" do
+ "われわれ".byteindex("わ", 3).should == 6
+ "ありがとうありがとう".byteindex("が", 9).should == 21
+ end
- it "returns the character byteindex after a partial first match" do
- "</</h".byteindex("</h").should == 2
- end
+ it "returns the character byteindex after a partial first match" do
+ "</</h".byteindex("</h").should == 2
+ end
- it "raises an Encoding::CompatibilityError if the encodings are incompatible" do
- char = "れ".encode Encoding::EUC_JP
- -> do
- "あれ".byteindex(char)
- end.should raise_error(Encoding::CompatibilityError)
- end
+ it "raises an Encoding::CompatibilityError if the encodings are incompatible" do
+ char = "れ".encode Encoding::EUC_JP
+ -> do
+ "あれ".byteindex(char)
+ end.should raise_error(Encoding::CompatibilityError)
+ end
- it "handles a substring in a superset encoding" do
- 'abc'.dup.force_encoding(Encoding::US_ASCII).byteindex('é').should == nil
- end
+ it "handles a substring in a superset encoding" do
+ 'abc'.dup.force_encoding(Encoding::US_ASCII).byteindex('é').should == nil
+ end
- it "handles a substring in a subset encoding" do
- 'été'.byteindex('t'.dup.force_encoding(Encoding::US_ASCII)).should == 2
- end
+ it "handles a substring in a subset encoding" do
+ 'été'.byteindex('t'.dup.force_encoding(Encoding::US_ASCII)).should == 2
end
end
describe "String#byteindex with Regexp" do
- ruby_version_is "3.2" do
- it "behaves the same as String#byteindex(string) for escaped string regexps" do
- ["blablabla", "hello cruel world...!"].each do |str|
- ["", "b", "bla", "lab", "o c", "d."].each do |needle|
- regexp = Regexp.new(Regexp.escape(needle))
- str.byteindex(regexp).should == str.byteindex(needle)
-
- 0.upto(str.size + 1) do |start|
- str.byteindex(regexp, start).should == str.byteindex(needle, start)
- end
-
- (-str.size - 1).upto(-1) do |start|
- str.byteindex(regexp, start).should == str.byteindex(needle, start)
- end
+ it "behaves the same as String#byteindex(string) for escaped string regexps" do
+ ["blablabla", "hello cruel world...!"].each do |str|
+ ["", "b", "bla", "lab", "o c", "d."].each do |needle|
+ regexp = Regexp.new(Regexp.escape(needle))
+ str.byteindex(regexp).should == str.byteindex(needle)
+
+ 0.upto(str.size + 1) do |start|
+ str.byteindex(regexp, start).should == str.byteindex(needle, start)
+ end
+
+ (-str.size - 1).upto(-1) do |start|
+ str.byteindex(regexp, start).should == str.byteindex(needle, start)
end
end
end
+ end
- it "returns the byteindex of the first match of regexp" do
- "blablabla".byteindex(/bla/).should == 0
- "blablabla".byteindex(/BLA/i).should == 0
+ it "returns the byteindex of the first match of regexp" do
+ "blablabla".byteindex(/bla/).should == 0
+ "blablabla".byteindex(/BLA/i).should == 0
- "blablabla".byteindex(/.{0}/).should == 0
- "blablabla".byteindex(/.{6}/).should == 0
- "blablabla".byteindex(/.{9}/).should == 0
+ "blablabla".byteindex(/.{0}/).should == 0
+ "blablabla".byteindex(/.{6}/).should == 0
+ "blablabla".byteindex(/.{9}/).should == 0
- "blablabla".byteindex(/.*/).should == 0
- "blablabla".byteindex(/.+/).should == 0
+ "blablabla".byteindex(/.*/).should == 0
+ "blablabla".byteindex(/.+/).should == 0
- "blablabla".byteindex(/lab|b/).should == 0
+ "blablabla".byteindex(/lab|b/).should == 0
- not_supported_on :opal do
- "blablabla".byteindex(/\A/).should == 0
- "blablabla".byteindex(/\Z/).should == 9
- "blablabla".byteindex(/\z/).should == 9
- "blablabla\n".byteindex(/\Z/).should == 9
- "blablabla\n".byteindex(/\z/).should == 10
- end
+ not_supported_on :opal do
+ "blablabla".byteindex(/\A/).should == 0
+ "blablabla".byteindex(/\Z/).should == 9
+ "blablabla".byteindex(/\z/).should == 9
+ "blablabla\n".byteindex(/\Z/).should == 9
+ "blablabla\n".byteindex(/\z/).should == 10
+ end
- "blablabla".byteindex(/^/).should == 0
- "\nblablabla".byteindex(/^/).should == 0
- "b\nablabla".byteindex(/$/).should == 1
- "bl\nablabla".byteindex(/$/).should == 2
+ "blablabla".byteindex(/^/).should == 0
+ "\nblablabla".byteindex(/^/).should == 0
+ "b\nablabla".byteindex(/$/).should == 1
+ "bl\nablabla".byteindex(/$/).should == 2
- "blablabla".byteindex(/.l./).should == 0
- end
+ "blablabla".byteindex(/.l./).should == 0
+ end
- it "starts the search at the given offset" do
- "blablabla".byteindex(/.{0}/, 5).should == 5
- "blablabla".byteindex(/.{1}/, 5).should == 5
- "blablabla".byteindex(/.{2}/, 5).should == 5
- "blablabla".byteindex(/.{3}/, 5).should == 5
- "blablabla".byteindex(/.{4}/, 5).should == 5
-
- "blablabla".byteindex(/.{0}/, 3).should == 3
- "blablabla".byteindex(/.{1}/, 3).should == 3
- "blablabla".byteindex(/.{2}/, 3).should == 3
- "blablabla".byteindex(/.{5}/, 3).should == 3
- "blablabla".byteindex(/.{6}/, 3).should == 3
-
- "blablabla".byteindex(/.l./, 0).should == 0
- "blablabla".byteindex(/.l./, 1).should == 3
- "blablabla".byteindex(/.l./, 2).should == 3
- "blablabla".byteindex(/.l./, 3).should == 3
-
- "xblaxbla".byteindex(/x./, 0).should == 0
- "xblaxbla".byteindex(/x./, 1).should == 4
- "xblaxbla".byteindex(/x./, 2).should == 4
-
- not_supported_on :opal do
- "blablabla\n".byteindex(/\Z/, 9).should == 9
- end
+ it "starts the search at the given offset" do
+ "blablabla".byteindex(/.{0}/, 5).should == 5
+ "blablabla".byteindex(/.{1}/, 5).should == 5
+ "blablabla".byteindex(/.{2}/, 5).should == 5
+ "blablabla".byteindex(/.{3}/, 5).should == 5
+ "blablabla".byteindex(/.{4}/, 5).should == 5
+
+ "blablabla".byteindex(/.{0}/, 3).should == 3
+ "blablabla".byteindex(/.{1}/, 3).should == 3
+ "blablabla".byteindex(/.{2}/, 3).should == 3
+ "blablabla".byteindex(/.{5}/, 3).should == 3
+ "blablabla".byteindex(/.{6}/, 3).should == 3
+
+ "blablabla".byteindex(/.l./, 0).should == 0
+ "blablabla".byteindex(/.l./, 1).should == 3
+ "blablabla".byteindex(/.l./, 2).should == 3
+ "blablabla".byteindex(/.l./, 3).should == 3
+
+ "xblaxbla".byteindex(/x./, 0).should == 0
+ "xblaxbla".byteindex(/x./, 1).should == 4
+ "xblaxbla".byteindex(/x./, 2).should == 4
+
+ not_supported_on :opal do
+ "blablabla\n".byteindex(/\Z/, 9).should == 9
end
+ end
- it "starts the search at offset + self.length if offset is negative" do
- str = "blablabla"
+ it "starts the search at offset + self.length if offset is negative" do
+ str = "blablabla"
- ["bl", "bla", "blab", "la", "lab", "ab", ""].each do |needle|
- (-str.length .. -1).each do |offset|
- str.byteindex(needle, offset).should ==
- str.byteindex(needle, offset + str.length)
- end
+ ["bl", "bla", "blab", "la", "lab", "ab", ""].each do |needle|
+ (-str.length .. -1).each do |offset|
+ str.byteindex(needle, offset).should ==
+ str.byteindex(needle, offset + str.length)
end
end
+ end
- it "returns nil if the substring isn't found" do
- "blablabla".byteindex(/BLA/).should == nil
+ it "returns nil if the substring isn't found" do
+ "blablabla".byteindex(/BLA/).should == nil
- "blablabla".byteindex(/.{10}/).should == nil
- "blaxbla".byteindex(/.x/, 3).should == nil
- "blaxbla".byteindex(/..x/, 2).should == nil
- end
+ "blablabla".byteindex(/.{10}/).should == nil
+ "blaxbla".byteindex(/.x/, 3).should == nil
+ "blaxbla".byteindex(/..x/, 2).should == nil
+ end
- it "returns nil if the Regexp matches the empty string and the offset is out of range" do
- "ruby".byteindex(//, 12).should be_nil
- end
+ it "returns nil if the Regexp matches the empty string and the offset is out of range" do
+ "ruby".byteindex(//, 12).should be_nil
+ end
- it "supports \\G which matches at the given start offset" do
- "helloYOU.".byteindex(/\GYOU/, 5).should == 5
- "helloYOU.".byteindex(/\GYOU/).should == nil
+ it "supports \\G which matches at the given start offset" do
+ "helloYOU.".byteindex(/\GYOU/, 5).should == 5
+ "helloYOU.".byteindex(/\GYOU/).should == nil
- re = /\G.+YOU/
- # The # marks where \G will match.
- [
- ["#hi!YOUall.", 0],
- ["h#i!YOUall.", 1],
- ["hi#!YOUall.", 2],
- ["hi!#YOUall.", nil]
- ].each do |spec|
+ re = /\G.+YOU/
+ # The # marks where \G will match.
+ [
+ ["#hi!YOUall.", 0],
+ ["h#i!YOUall.", 1],
+ ["hi#!YOUall.", 2],
+ ["hi!#YOUall.", nil]
+ ].each do |spec|
- start = spec[0].byteindex("#")
- str = spec[0].delete("#")
+ start = spec[0].byteindex("#")
+ str = spec[0].delete("#")
- str.byteindex(re, start).should == spec[1]
- end
+ str.byteindex(re, start).should == spec[1]
end
+ end
- it "converts start_offset to an integer via to_int" do
- obj = mock('1')
- obj.should_receive(:to_int).and_return(1)
- "RWOARW".byteindex(/R./, obj).should == 4
- end
+ it "converts start_offset to an integer via to_int" do
+ obj = mock('1')
+ obj.should_receive(:to_int).and_return(1)
+ "RWOARW".byteindex(/R./, obj).should == 4
+ end
- it "returns the character byteindex of a multibyte character" do
- "ありがとう".byteindex(/が/).should == 6
- end
+ it "returns the character byteindex of a multibyte character" do
+ "ありがとう".byteindex(/が/).should == 6
+ end
- it "returns the character byteindex after offset" do
- "われわれ".byteindex(/わ/, 3).should == 6
- end
+ it "returns the character byteindex after offset" do
+ "われわれ".byteindex(/わ/, 3).should == 6
+ end
- it "treats the offset as a byteindex" do
- "われわわれ".byteindex(/わ/, 6).should == 6
- end
+ it "treats the offset as a byteindex" do
+ "われわわれ".byteindex(/わ/, 6).should == 6
end
end
diff --git a/spec/ruby/core/string/byterindex_spec.rb b/spec/ruby/core/string/byterindex_spec.rb
index 150f709b90..983222e35d 100644
--- a/spec/ruby/core/string/byterindex_spec.rb
+++ b/spec/ruby/core/string/byterindex_spec.rb
@@ -4,356 +4,350 @@ require_relative 'fixtures/classes'
require_relative 'shared/byte_index_common.rb'
describe "String#byterindex with object" do
- ruby_version_is "3.2" do
- it "tries to convert obj to a string via to_str" do
- obj = mock('lo')
- def obj.to_str() "lo" end
- "hello".byterindex(obj).should == "hello".byterindex("lo")
-
- obj = mock('o')
- def obj.respond_to?(arg, *) true end
- def obj.method_missing(*args) "o" end
- "hello".byterindex(obj).should == "hello".byterindex("o")
- end
-
- it "calls #to_int to convert the second argument" do
- offset = mock("string index offset")
- offset.should_receive(:to_int).and_return(3)
- "abc".byterindex("c", offset).should == 2
- end
+ it "tries to convert obj to a string via to_str" do
+ obj = mock('lo')
+ def obj.to_str() "lo" end
+ "hello".byterindex(obj).should == "hello".byterindex("lo")
+
+ obj = mock('o')
+ def obj.respond_to?(arg, *) true end
+ def obj.method_missing(*args) "o" end
+ "hello".byterindex(obj).should == "hello".byterindex("o")
+ end
- it "does not raise IndexError when byte offset is correct or on string boundary" do
- "わ".byterindex("", 0).should == 0
- "わ".byterindex("", 3).should == 3
- "わ".byterindex("").should == 3
- end
+ it "calls #to_int to convert the second argument" do
+ offset = mock("string index offset")
+ offset.should_receive(:to_int).and_return(3)
+ "abc".byterindex("c", offset).should == 2
+ end
- it_behaves_like :byte_index_common, :byterindex
+ it "does not raise IndexError when byte offset is correct or on string boundary" do
+ "わ".byterindex("", 0).should == 0
+ "わ".byterindex("", 3).should == 3
+ "わ".byterindex("").should == 3
end
+
+ it_behaves_like :byte_index_common, :byterindex
end
describe "String#byterindex with String" do
- ruby_version_is "3.2" do
- it "behaves the same as String#byterindex(char) for one-character strings" do
- "blablabla hello cruel world...!".split("").uniq.each do |str|
- chr = str[0]
- str.byterindex(str).should == str.byterindex(chr)
+ it "behaves the same as String#byterindex(char) for one-character strings" do
+ "blablabla hello cruel world...!".split("").uniq.each do |str|
+ chr = str[0]
+ str.byterindex(str).should == str.byterindex(chr)
- 0.upto(str.size + 1) do |start|
- str.byterindex(str, start).should == str.byterindex(chr, start)
- end
+ 0.upto(str.size + 1) do |start|
+ str.byterindex(str, start).should == str.byterindex(chr, start)
+ end
- (-str.size - 1).upto(-1) do |start|
- str.byterindex(str, start).should == str.byterindex(chr, start)
- end
+ (-str.size - 1).upto(-1) do |start|
+ str.byterindex(str, start).should == str.byterindex(chr, start)
end
end
+ end
- it "behaves the same as String#byterindex(?char) for one-character strings" do
- "blablabla hello cruel world...!".split("").uniq.each do |str|
- chr = str[0] =~ / / ? str[0] : eval("?#{str[0]}")
- str.byterindex(str).should == str.byterindex(chr)
+ it "behaves the same as String#byterindex(?char) for one-character strings" do
+ "blablabla hello cruel world...!".split("").uniq.each do |str|
+ chr = str[0] =~ / / ? str[0] : eval("?#{str[0]}")
+ str.byterindex(str).should == str.byterindex(chr)
- 0.upto(str.size + 1) do |start|
- str.byterindex(str, start).should == str.byterindex(chr, start)
- end
+ 0.upto(str.size + 1) do |start|
+ str.byterindex(str, start).should == str.byterindex(chr, start)
+ end
- (-str.size - 1).upto(-1) do |start|
- str.byterindex(str, start).should == str.byterindex(chr, start)
- end
+ (-str.size - 1).upto(-1) do |start|
+ str.byterindex(str, start).should == str.byterindex(chr, start)
end
end
+ end
- it "returns the index of the last occurrence of the given substring" do
- "blablabla".byterindex("").should == 9
- "blablabla".byterindex("a").should == 8
- "blablabla".byterindex("la").should == 7
- "blablabla".byterindex("bla").should == 6
- "blablabla".byterindex("abla").should == 5
- "blablabla".byterindex("labla").should == 4
- "blablabla".byterindex("blabla").should == 3
- "blablabla".byterindex("ablabla").should == 2
- "blablabla".byterindex("lablabla").should == 1
- "blablabla".byterindex("blablabla").should == 0
-
- "blablabla".byterindex("l").should == 7
- "blablabla".byterindex("bl").should == 6
- "blablabla".byterindex("abl").should == 5
- "blablabla".byterindex("labl").should == 4
- "blablabla".byterindex("blabl").should == 3
- "blablabla".byterindex("ablabl").should == 2
- "blablabla".byterindex("lablabl").should == 1
- "blablabla".byterindex("blablabl").should == 0
-
- "blablabla".byterindex("b").should == 6
- "blablabla".byterindex("ab").should == 5
- "blablabla".byterindex("lab").should == 4
- "blablabla".byterindex("blab").should == 3
- "blablabla".byterindex("ablab").should == 2
- "blablabla".byterindex("lablab").should == 1
- "blablabla".byterindex("blablab").should == 0
- end
+ it "returns the index of the last occurrence of the given substring" do
+ "blablabla".byterindex("").should == 9
+ "blablabla".byterindex("a").should == 8
+ "blablabla".byterindex("la").should == 7
+ "blablabla".byterindex("bla").should == 6
+ "blablabla".byterindex("abla").should == 5
+ "blablabla".byterindex("labla").should == 4
+ "blablabla".byterindex("blabla").should == 3
+ "blablabla".byterindex("ablabla").should == 2
+ "blablabla".byterindex("lablabla").should == 1
+ "blablabla".byterindex("blablabla").should == 0
+
+ "blablabla".byterindex("l").should == 7
+ "blablabla".byterindex("bl").should == 6
+ "blablabla".byterindex("abl").should == 5
+ "blablabla".byterindex("labl").should == 4
+ "blablabla".byterindex("blabl").should == 3
+ "blablabla".byterindex("ablabl").should == 2
+ "blablabla".byterindex("lablabl").should == 1
+ "blablabla".byterindex("blablabl").should == 0
+
+ "blablabla".byterindex("b").should == 6
+ "blablabla".byterindex("ab").should == 5
+ "blablabla".byterindex("lab").should == 4
+ "blablabla".byterindex("blab").should == 3
+ "blablabla".byterindex("ablab").should == 2
+ "blablabla".byterindex("lablab").should == 1
+ "blablabla".byterindex("blablab").should == 0
+ end
- it "ignores string subclasses" do
- "blablabla".byterindex(StringSpecs::MyString.new("bla")).should == 6
- StringSpecs::MyString.new("blablabla").byterindex("bla").should == 6
- StringSpecs::MyString.new("blablabla").byterindex(StringSpecs::MyString.new("bla")).should == 6
- end
+ it "ignores string subclasses" do
+ "blablabla".byterindex(StringSpecs::MyString.new("bla")).should == 6
+ StringSpecs::MyString.new("blablabla").byterindex("bla").should == 6
+ StringSpecs::MyString.new("blablabla").byterindex(StringSpecs::MyString.new("bla")).should == 6
+ end
- it "starts the search at the given offset" do
- "blablabla".byterindex("bl", 0).should == 0
- "blablabla".byterindex("bl", 1).should == 0
- "blablabla".byterindex("bl", 2).should == 0
- "blablabla".byterindex("bl", 3).should == 3
-
- "blablabla".byterindex("bla", 0).should == 0
- "blablabla".byterindex("bla", 1).should == 0
- "blablabla".byterindex("bla", 2).should == 0
- "blablabla".byterindex("bla", 3).should == 3
-
- "blablabla".byterindex("blab", 0).should == 0
- "blablabla".byterindex("blab", 1).should == 0
- "blablabla".byterindex("blab", 2).should == 0
- "blablabla".byterindex("blab", 3).should == 3
- "blablabla".byterindex("blab", 6).should == 3
- "blablablax".byterindex("blab", 6).should == 3
-
- "blablabla".byterindex("la", 1).should == 1
- "blablabla".byterindex("la", 2).should == 1
- "blablabla".byterindex("la", 3).should == 1
- "blablabla".byterindex("la", 4).should == 4
-
- "blablabla".byterindex("lab", 1).should == 1
- "blablabla".byterindex("lab", 2).should == 1
- "blablabla".byterindex("lab", 3).should == 1
- "blablabla".byterindex("lab", 4).should == 4
-
- "blablabla".byterindex("ab", 2).should == 2
- "blablabla".byterindex("ab", 3).should == 2
- "blablabla".byterindex("ab", 4).should == 2
- "blablabla".byterindex("ab", 5).should == 5
-
- "blablabla".byterindex("", 0).should == 0
- "blablabla".byterindex("", 1).should == 1
- "blablabla".byterindex("", 2).should == 2
- "blablabla".byterindex("", 7).should == 7
- "blablabla".byterindex("", 8).should == 8
- "blablabla".byterindex("", 9).should == 9
- "blablabla".byterindex("", 10).should == 9
- end
+ it "starts the search at the given offset" do
+ "blablabla".byterindex("bl", 0).should == 0
+ "blablabla".byterindex("bl", 1).should == 0
+ "blablabla".byterindex("bl", 2).should == 0
+ "blablabla".byterindex("bl", 3).should == 3
+
+ "blablabla".byterindex("bla", 0).should == 0
+ "blablabla".byterindex("bla", 1).should == 0
+ "blablabla".byterindex("bla", 2).should == 0
+ "blablabla".byterindex("bla", 3).should == 3
+
+ "blablabla".byterindex("blab", 0).should == 0
+ "blablabla".byterindex("blab", 1).should == 0
+ "blablabla".byterindex("blab", 2).should == 0
+ "blablabla".byterindex("blab", 3).should == 3
+ "blablabla".byterindex("blab", 6).should == 3
+ "blablablax".byterindex("blab", 6).should == 3
+
+ "blablabla".byterindex("la", 1).should == 1
+ "blablabla".byterindex("la", 2).should == 1
+ "blablabla".byterindex("la", 3).should == 1
+ "blablabla".byterindex("la", 4).should == 4
+
+ "blablabla".byterindex("lab", 1).should == 1
+ "blablabla".byterindex("lab", 2).should == 1
+ "blablabla".byterindex("lab", 3).should == 1
+ "blablabla".byterindex("lab", 4).should == 4
+
+ "blablabla".byterindex("ab", 2).should == 2
+ "blablabla".byterindex("ab", 3).should == 2
+ "blablabla".byterindex("ab", 4).should == 2
+ "blablabla".byterindex("ab", 5).should == 5
+
+ "blablabla".byterindex("", 0).should == 0
+ "blablabla".byterindex("", 1).should == 1
+ "blablabla".byterindex("", 2).should == 2
+ "blablabla".byterindex("", 7).should == 7
+ "blablabla".byterindex("", 8).should == 8
+ "blablabla".byterindex("", 9).should == 9
+ "blablabla".byterindex("", 10).should == 9
+ end
- it "starts the search at offset + self.length if offset is negative" do
- str = "blablabla"
+ it "starts the search at offset + self.length if offset is negative" do
+ str = "blablabla"
- ["bl", "bla", "blab", "la", "lab", "ab", ""].each do |needle|
- (-str.length .. -1).each do |offset|
- str.byterindex(needle, offset).should ==
- str.byterindex(needle, offset + str.length)
- end
+ ["bl", "bla", "blab", "la", "lab", "ab", ""].each do |needle|
+ (-str.length .. -1).each do |offset|
+ str.byterindex(needle, offset).should ==
+ str.byterindex(needle, offset + str.length)
end
end
+ end
- it "returns nil if the substring isn't found" do
- "blablabla".byterindex("B").should == nil
- "blablabla".byterindex("z").should == nil
- "blablabla".byterindex("BLA").should == nil
- "blablabla".byterindex("blablablabla").should == nil
+ it "returns nil if the substring isn't found" do
+ "blablabla".byterindex("B").should == nil
+ "blablabla".byterindex("z").should == nil
+ "blablabla".byterindex("BLA").should == nil
+ "blablabla".byterindex("blablablabla").should == nil
- "hello".byterindex("lo", 0).should == nil
- "hello".byterindex("lo", 1).should == nil
- "hello".byterindex("lo", 2).should == nil
+ "hello".byterindex("lo", 0).should == nil
+ "hello".byterindex("lo", 1).should == nil
+ "hello".byterindex("lo", 2).should == nil
- "hello".byterindex("llo", 0).should == nil
- "hello".byterindex("llo", 1).should == nil
+ "hello".byterindex("llo", 0).should == nil
+ "hello".byterindex("llo", 1).should == nil
- "hello".byterindex("el", 0).should == nil
- "hello".byterindex("ello", 0).should == nil
+ "hello".byterindex("el", 0).should == nil
+ "hello".byterindex("ello", 0).should == nil
- "hello".byterindex("", -6).should == nil
- "hello".byterindex("", -7).should == nil
+ "hello".byterindex("", -6).should == nil
+ "hello".byterindex("", -7).should == nil
- "hello".byterindex("h", -6).should == nil
- end
+ "hello".byterindex("h", -6).should == nil
+ end
- it "tries to convert start_offset to an integer via to_int" do
- obj = mock('5')
- def obj.to_int() 5 end
- "str".byterindex("st", obj).should == 0
+ it "tries to convert start_offset to an integer via to_int" do
+ obj = mock('5')
+ def obj.to_int() 5 end
+ "str".byterindex("st", obj).should == 0
- obj = mock('5')
- def obj.respond_to?(arg, *) true end
- def obj.method_missing(*args) 5 end
- "str".byterindex("st", obj).should == 0
- end
+ obj = mock('5')
+ def obj.respond_to?(arg, *) true end
+ def obj.method_missing(*args) 5 end
+ "str".byterindex("st", obj).should == 0
+ end
- it "raises a TypeError when given offset is nil" do
- -> { "str".byterindex("st", nil) }.should raise_error(TypeError)
- end
+ it "raises a TypeError when given offset is nil" do
+ -> { "str".byterindex("st", nil) }.should raise_error(TypeError)
+ end
- it "handles a substring in a superset encoding" do
- 'abc'.dup.force_encoding(Encoding::US_ASCII).byterindex('é').should == nil
- end
+ it "handles a substring in a superset encoding" do
+ 'abc'.dup.force_encoding(Encoding::US_ASCII).byterindex('é').should == nil
+ end
- it "handles a substring in a subset encoding" do
- 'été'.byterindex('t'.dup.force_encoding(Encoding::US_ASCII)).should == 2
- end
+ it "handles a substring in a subset encoding" do
+ 'été'.byterindex('t'.dup.force_encoding(Encoding::US_ASCII)).should == 2
end
end
describe "String#byterindex with Regexp" do
- ruby_version_is "3.2" do
- it "behaves the same as String#byterindex(string) for escaped string regexps" do
- ["blablabla", "hello cruel world...!"].each do |str|
- ["", "b", "bla", "lab", "o c", "d."].each do |needle|
- regexp = Regexp.new(Regexp.escape(needle))
- str.byterindex(regexp).should == str.byterindex(needle)
-
- 0.upto(str.size + 1) do |start|
- str.byterindex(regexp, start).should == str.byterindex(needle, start)
- end
-
- (-str.size - 1).upto(-1) do |start|
- str.byterindex(regexp, start).should == str.byterindex(needle, start)
- end
+ it "behaves the same as String#byterindex(string) for escaped string regexps" do
+ ["blablabla", "hello cruel world...!"].each do |str|
+ ["", "b", "bla", "lab", "o c", "d."].each do |needle|
+ regexp = Regexp.new(Regexp.escape(needle))
+ str.byterindex(regexp).should == str.byterindex(needle)
+
+ 0.upto(str.size + 1) do |start|
+ str.byterindex(regexp, start).should == str.byterindex(needle, start)
+ end
+
+ (-str.size - 1).upto(-1) do |start|
+ str.byterindex(regexp, start).should == str.byterindex(needle, start)
end
end
end
+ end
- it "returns the index of the first match from the end of string of regexp" do
- "blablabla".byterindex(/bla/).should == 6
- "blablabla".byterindex(/BLA/i).should == 6
-
- "blablabla".byterindex(/.{0}/).should == 9
- "blablabla".byterindex(/.{1}/).should == 8
- "blablabla".byterindex(/.{2}/).should == 7
- "blablabla".byterindex(/.{6}/).should == 3
- "blablabla".byterindex(/.{9}/).should == 0
+ it "returns the index of the first match from the end of string of regexp" do
+ "blablabla".byterindex(/bla/).should == 6
+ "blablabla".byterindex(/BLA/i).should == 6
- "blablabla".byterindex(/.*/).should == 9
- "blablabla".byterindex(/.+/).should == 8
+ "blablabla".byterindex(/.{0}/).should == 9
+ "blablabla".byterindex(/.{1}/).should == 8
+ "blablabla".byterindex(/.{2}/).should == 7
+ "blablabla".byterindex(/.{6}/).should == 3
+ "blablabla".byterindex(/.{9}/).should == 0
- "blablabla".byterindex(/bla|a/).should == 8
+ "blablabla".byterindex(/.*/).should == 9
+ "blablabla".byterindex(/.+/).should == 8
- not_supported_on :opal do
- "blablabla".byterindex(/\A/).should == 0
- "blablabla".byterindex(/\Z/).should == 9
- "blablabla".byterindex(/\z/).should == 9
- "blablabla\n".byterindex(/\Z/).should == 10
- "blablabla\n".byterindex(/\z/).should == 10
- end
+ "blablabla".byterindex(/bla|a/).should == 8
- "blablabla".byterindex(/^/).should == 0
- not_supported_on :opal do
- "\nblablabla".byterindex(/^/).should == 1
- "b\nlablabla".byterindex(/^/).should == 2
- end
- "blablabla".byterindex(/$/).should == 9
-
- "blablabla".byterindex(/.l./).should == 6
+ not_supported_on :opal do
+ "blablabla".byterindex(/\A/).should == 0
+ "blablabla".byterindex(/\Z/).should == 9
+ "blablabla".byterindex(/\z/).should == 9
+ "blablabla\n".byterindex(/\Z/).should == 10
+ "blablabla\n".byterindex(/\z/).should == 10
end
- it "starts the search at the given offset" do
- "blablabla".byterindex(/.{0}/, 5).should == 5
- "blablabla".byterindex(/.{1}/, 5).should == 5
- "blablabla".byterindex(/.{2}/, 5).should == 5
- "blablabla".byterindex(/.{3}/, 5).should == 5
- "blablabla".byterindex(/.{4}/, 5).should == 5
-
- "blablabla".byterindex(/.{0}/, 3).should == 3
- "blablabla".byterindex(/.{1}/, 3).should == 3
- "blablabla".byterindex(/.{2}/, 3).should == 3
- "blablabla".byterindex(/.{5}/, 3).should == 3
- "blablabla".byterindex(/.{6}/, 3).should == 3
-
- "blablabla".byterindex(/.l./, 0).should == 0
- "blablabla".byterindex(/.l./, 1).should == 0
- "blablabla".byterindex(/.l./, 2).should == 0
- "blablabla".byterindex(/.l./, 3).should == 3
-
- "blablablax".byterindex(/.x/, 10).should == 8
- "blablablax".byterindex(/.x/, 9).should == 8
- "blablablax".byterindex(/.x/, 8).should == 8
-
- "blablablax".byterindex(/..x/, 10).should == 7
- "blablablax".byterindex(/..x/, 9).should == 7
- "blablablax".byterindex(/..x/, 8).should == 7
- "blablablax".byterindex(/..x/, 7).should == 7
-
- not_supported_on :opal do
- "blablabla\n".byterindex(/\Z/, 9).should == 9
- end
+ "blablabla".byterindex(/^/).should == 0
+ not_supported_on :opal do
+ "\nblablabla".byterindex(/^/).should == 1
+ "b\nlablabla".byterindex(/^/).should == 2
end
+ "blablabla".byterindex(/$/).should == 9
- it "starts the search at offset + self.length if offset is negative" do
- str = "blablabla"
+ "blablabla".byterindex(/.l./).should == 6
+ end
- ["bl", "bla", "blab", "la", "lab", "ab", ""].each do |needle|
- (-str.length .. -1).each do |offset|
- str.byterindex(needle, offset).should ==
- str.byterindex(needle, offset + str.length)
- end
- end
+ it "starts the search at the given offset" do
+ "blablabla".byterindex(/.{0}/, 5).should == 5
+ "blablabla".byterindex(/.{1}/, 5).should == 5
+ "blablabla".byterindex(/.{2}/, 5).should == 5
+ "blablabla".byterindex(/.{3}/, 5).should == 5
+ "blablabla".byterindex(/.{4}/, 5).should == 5
+
+ "blablabla".byterindex(/.{0}/, 3).should == 3
+ "blablabla".byterindex(/.{1}/, 3).should == 3
+ "blablabla".byterindex(/.{2}/, 3).should == 3
+ "blablabla".byterindex(/.{5}/, 3).should == 3
+ "blablabla".byterindex(/.{6}/, 3).should == 3
+
+ "blablabla".byterindex(/.l./, 0).should == 0
+ "blablabla".byterindex(/.l./, 1).should == 0
+ "blablabla".byterindex(/.l./, 2).should == 0
+ "blablabla".byterindex(/.l./, 3).should == 3
+
+ "blablablax".byterindex(/.x/, 10).should == 8
+ "blablablax".byterindex(/.x/, 9).should == 8
+ "blablablax".byterindex(/.x/, 8).should == 8
+
+ "blablablax".byterindex(/..x/, 10).should == 7
+ "blablablax".byterindex(/..x/, 9).should == 7
+ "blablablax".byterindex(/..x/, 8).should == 7
+ "blablablax".byterindex(/..x/, 7).should == 7
+
+ not_supported_on :opal do
+ "blablabla\n".byterindex(/\Z/, 9).should == 9
end
+ end
- it "returns nil if the substring isn't found" do
- "blablabla".byterindex(/BLA/).should == nil
- "blablabla".byterindex(/.{10}/).should == nil
- "blablablax".byterindex(/.x/, 7).should == nil
- "blablablax".byterindex(/..x/, 6).should == nil
+ it "starts the search at offset + self.length if offset is negative" do
+ str = "blablabla"
- not_supported_on :opal do
- "blablabla".byterindex(/\Z/, 5).should == nil
- "blablabla".byterindex(/\z/, 5).should == nil
- "blablabla\n".byterindex(/\z/, 9).should == nil
+ ["bl", "bla", "blab", "la", "lab", "ab", ""].each do |needle|
+ (-str.length .. -1).each do |offset|
+ str.byterindex(needle, offset).should ==
+ str.byterindex(needle, offset + str.length)
end
end
+ end
+
+ it "returns nil if the substring isn't found" do
+ "blablabla".byterindex(/BLA/).should == nil
+ "blablabla".byterindex(/.{10}/).should == nil
+ "blablablax".byterindex(/.x/, 7).should == nil
+ "blablablax".byterindex(/..x/, 6).should == nil
not_supported_on :opal do
- it "supports \\G which matches at the given start offset" do
- "helloYOU.".byterindex(/YOU\G/, 8).should == 5
- "helloYOU.".byterindex(/YOU\G/).should == nil
-
- idx = "helloYOUall!".index("YOU")
- re = /YOU.+\G.+/
- # The # marks where \G will match.
- [
- ["helloYOU#all.", nil],
- ["helloYOUa#ll.", idx],
- ["helloYOUal#l.", idx],
- ["helloYOUall#.", idx],
- ["helloYOUall.#", nil]
- ].each do |i|
- start = i[0].index("#")
- str = i[0].delete("#")
-
- str.byterindex(re, start).should == i[1]
- end
+ "blablabla".byterindex(/\Z/, 5).should == nil
+ "blablabla".byterindex(/\z/, 5).should == nil
+ "blablabla\n".byterindex(/\z/, 9).should == nil
+ end
+ end
+
+ not_supported_on :opal do
+ it "supports \\G which matches at the given start offset" do
+ "helloYOU.".byterindex(/YOU\G/, 8).should == 5
+ "helloYOU.".byterindex(/YOU\G/).should == nil
+
+ idx = "helloYOUall!".index("YOU")
+ re = /YOU.+\G.+/
+ # The # marks where \G will match.
+ [
+ ["helloYOU#all.", nil],
+ ["helloYOUa#ll.", idx],
+ ["helloYOUal#l.", idx],
+ ["helloYOUall#.", idx],
+ ["helloYOUall.#", nil]
+ ].each do |i|
+ start = i[0].index("#")
+ str = i[0].delete("#")
+
+ str.byterindex(re, start).should == i[1]
end
end
+ end
- it "tries to convert start_offset to an integer" do
- obj = mock('5')
- def obj.to_int() 5 end
- "str".byterindex(/../, obj).should == 1
+ it "tries to convert start_offset to an integer" do
+ obj = mock('5')
+ def obj.to_int() 5 end
+ "str".byterindex(/../, obj).should == 1
- obj = mock('5')
- def obj.respond_to?(arg, *) true end
- def obj.method_missing(*args); 5; end
- "str".byterindex(/../, obj).should == 1
- end
+ obj = mock('5')
+ def obj.respond_to?(arg, *) true end
+ def obj.method_missing(*args); 5; end
+ "str".byterindex(/../, obj).should == 1
+ end
- it "raises a TypeError when given offset is nil" do
- -> { "str".byterindex(/../, nil) }.should raise_error(TypeError)
- end
+ it "raises a TypeError when given offset is nil" do
+ -> { "str".byterindex(/../, nil) }.should raise_error(TypeError)
+ end
- it "returns the reverse byte index of a multibyte character" do
- "ありがりがとう".byterindex("が").should == 12
- "ありがりがとう".byterindex(/が/).should == 12
- end
+ it "returns the reverse byte index of a multibyte character" do
+ "ありがりがとう".byterindex("が").should == 12
+ "ありがりがとう".byterindex(/が/).should == 12
+ end
- it "returns the character index before the finish" do
- "ありがりがとう".byterindex("が", 9).should == 6
- "ありがりがとう".byterindex(/が/, 9).should == 6
- end
+ it "returns the character index before the finish" do
+ "ありがりがとう".byterindex("が", 9).should == 6
+ "ありがりがとう".byterindex(/が/, 9).should == 6
end
end
diff --git a/spec/ruby/core/string/byteslice_spec.rb b/spec/ruby/core/string/byteslice_spec.rb
index 5b1027f4a5..4ad9e8d8f1 100644
--- a/spec/ruby/core/string/byteslice_spec.rb
+++ b/spec/ruby/core/string/byteslice_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
require_relative 'shared/slice'
@@ -17,7 +17,7 @@ describe "String#byteslice with Range" do
it_behaves_like :string_slice_range, :byteslice
end
-describe "String#byteslice on on non ASCII strings" do
+describe "String#byteslice on non ASCII strings" do
it "returns byteslice of unicode strings" do
"\u3042".byteslice(1).should == "\x81".dup.force_encoding("UTF-8")
"\u3042".byteslice(1, 2).should == "\x81\x82".dup.force_encoding("UTF-8")
diff --git a/spec/ruby/core/string/bytesplice_spec.rb b/spec/ruby/core/string/bytesplice_spec.rb
index 967edcba29..2c770e340a 100644
--- a/spec/ruby/core/string/bytesplice_spec.rb
+++ b/spec/ruby/core/string/bytesplice_spec.rb
@@ -3,131 +3,291 @@
require_relative '../../spec_helper'
describe "String#bytesplice" do
- ruby_version_is "3.2" do
- it "raises IndexError when index is less than -bytesize" do
- -> { "hello".bytesplice(-6, 0, "xxx") }.should raise_error(IndexError, "index -6 out of string")
+ it "raises IndexError when index is less than -bytesize" do
+ -> { "hello".bytesplice(-6, 0, "xxx") }.should raise_error(IndexError, "index -6 out of string")
+ end
+
+ it "raises IndexError when index is greater than bytesize" do
+ -> { "hello".bytesplice(6, 0, "xxx") }.should raise_error(IndexError, "index 6 out of string")
+ end
+
+ it "raises IndexError for negative length" do
+ -> { "abc".bytesplice(0, -2, "") }.should raise_error(IndexError, "negative length -2")
+ end
+
+ it "replaces with integer indices" do
+ "hello".bytesplice(-5, 0, "xxx").should == "xxxhello"
+ "hello".bytesplice(0, 0, "xxx").should == "xxxhello"
+ "hello".bytesplice(0, 1, "xxx").should == "xxxello"
+ "hello".bytesplice(0, 5, "xxx").should == "xxx"
+ "hello".bytesplice(0, 6, "xxx").should == "xxx"
+ end
+
+ it "raises RangeError when range left boundary is less than -bytesize" do
+ -> { "hello".bytesplice(-6...-6, "xxx") }.should raise_error(RangeError, "-6...-6 out of range")
+ end
+
+ it "replaces with ranges" do
+ "hello".bytesplice(-5...-5, "xxx").should == "xxxhello"
+ "hello".bytesplice(0...0, "xxx").should == "xxxhello"
+ "hello".bytesplice(0..0, "xxx").should == "xxxello"
+ "hello".bytesplice(0...1, "xxx").should == "xxxello"
+ "hello".bytesplice(0..1, "xxx").should == "xxxllo"
+ "hello".bytesplice(0..-1, "xxx").should == "xxx"
+ "hello".bytesplice(0...5, "xxx").should == "xxx"
+ "hello".bytesplice(0...6, "xxx").should == "xxx"
+ end
+
+ it "raises TypeError when integer index is provided without length argument" do
+ -> { "hello".bytesplice(0, "xxx") }.should raise_error(TypeError, "wrong argument type Integer (expected Range)")
+ end
+
+ it "replaces on an empty string" do
+ "".bytesplice(0, 0, "").should == ""
+ "".bytesplice(0, 0, "xxx").should == "xxx"
+ end
+
+ it "mutates self" do
+ s = "hello"
+ s.bytesplice(2, 1, "xxx").should.equal?(s)
+ end
+
+ it "raises when string is frozen" do
+ s = "hello".freeze
+ -> { s.bytesplice(2, 1, "xxx") }.should raise_error(FrozenError, "can't modify frozen String: \"hello\"")
+ end
+
+ ruby_version_is "3.3" do
+ it "raises IndexError when str_index is less than -bytesize" do
+ -> { "hello".bytesplice(2, 1, "HELLO", -6, 0) }.should raise_error(IndexError, "index -6 out of string")
end
- it "raises IndexError when index is greater than bytesize" do
- -> { "hello".bytesplice(6, 0, "xxx") }.should raise_error(IndexError, "index 6 out of string")
+ it "raises IndexError when str_index is greater than bytesize" do
+ -> { "hello".bytesplice(2, 1, "HELLO", 6, 0) }.should raise_error(IndexError, "index 6 out of string")
end
- it "raises IndexError for negative length" do
- -> { "abc".bytesplice(0, -2, "") }.should raise_error(IndexError, "negative length -2")
+ it "raises IndexError for negative str length" do
+ -> { "abc".bytesplice(0, 1, "", 0, -2) }.should raise_error(IndexError, "negative length -2")
end
- it "replaces with integer indices" do
- "hello".bytesplice(-5, 0, "xxx").should == "xxxhello"
- "hello".bytesplice(0, 0, "xxx").should == "xxxhello"
- "hello".bytesplice(0, 1, "xxx").should == "xxxello"
- "hello".bytesplice(0, 5, "xxx").should == "xxx"
- "hello".bytesplice(0, 6, "xxx").should == "xxx"
+ it "replaces with integer str indices" do
+ "hello".bytesplice(1, 2, "HELLO", -5, 0).should == "hlo"
+ "hello".bytesplice(1, 2, "HELLO", 0, 0).should == "hlo"
+ "hello".bytesplice(1, 2, "HELLO", 0, 1).should == "hHlo"
+ "hello".bytesplice(1, 2, "HELLO", 0, 5).should == "hHELLOlo"
+ "hello".bytesplice(1, 2, "HELLO", 0, 6).should == "hHELLOlo"
end
- it "raises RangeError when range left boundary is less than -bytesize" do
- -> { "hello".bytesplice(-6...-6, "xxx") }.should raise_error(RangeError, "-6...-6 out of range")
+ it "raises RangeError when str range left boundary is less than -bytesize" do
+ -> { "hello".bytesplice(0..1, "HELLO", -6...-6) }.should raise_error(RangeError, "-6...-6 out of range")
end
- it "replaces with ranges" do
- "hello".bytesplice(-5...-5, "xxx").should == "xxxhello"
- "hello".bytesplice(0...0, "xxx").should == "xxxhello"
- "hello".bytesplice(0..0, "xxx").should == "xxxello"
- "hello".bytesplice(0...1, "xxx").should == "xxxello"
- "hello".bytesplice(0..1, "xxx").should == "xxxllo"
- "hello".bytesplice(0..-1, "xxx").should == "xxx"
- "hello".bytesplice(0...5, "xxx").should == "xxx"
- "hello".bytesplice(0...6, "xxx").should == "xxx"
+ it "replaces with str ranges" do
+ "hello".bytesplice(1..2, "HELLO", -5...-5).should == "hlo"
+ "hello".bytesplice(1..2, "HELLO", 0...0).should == "hlo"
+ "hello".bytesplice(1..2, "HELLO", 0..0).should == "hHlo"
+ "hello".bytesplice(1..2, "HELLO", 0...1).should == "hHlo"
+ "hello".bytesplice(1..2, "HELLO", 0..1).should == "hHElo"
+ "hello".bytesplice(1..2, "HELLO", 0..-1).should == "hHELLOlo"
+ "hello".bytesplice(1..2, "HELLO", 0...5).should == "hHELLOlo"
+ "hello".bytesplice(1..2, "HELLO", 0...6).should == "hHELLOlo"
end
- it "raises TypeError when integer index is provided without length argument" do
- -> { "hello".bytesplice(0, "xxx") }.should raise_error(TypeError, "wrong argument type Integer (expected Range)")
+ it "raises ArgumentError when integer str index is provided without str length argument" do
+ -> { "hello".bytesplice(0, 1, "xxx", 0) }.should raise_error(ArgumentError, "wrong number of arguments (given 4, expected 2, 3, or 5)")
end
- it "replaces on an empty string" do
- "".bytesplice(0, 0, "").should == ""
- "".bytesplice(0, 0, "xxx").should == "xxx"
+ it "replaces on an empty string with str index/length" do
+ "".bytesplice(0, 0, "", 0, 0).should == ""
+ "".bytesplice(0, 0, "xxx", 0, 1).should == "x"
end
- it "mutates self" do
+ it "mutates self with substring and str index/length" do
s = "hello"
- s.bytesplice(2, 1, "xxx").should.equal?(s)
+ s.bytesplice(2, 1, "xxx", 1, 2).should.equal?(s)
+ s.should.eql?("hexxlo")
end
- it "raises when string is frozen" do
+ it "raises when string is frozen and str index/length" do
s = "hello".freeze
- -> { s.bytesplice(2, 1, "xxx") }.should raise_error(FrozenError, "can't modify frozen String: \"hello\"")
+ -> { s.bytesplice(2, 1, "xxx", 0, 1) }.should raise_error(FrozenError, "can't modify frozen String: \"hello\"")
+ end
+
+ it "replaces on an empty string with str range" do
+ "".bytesplice(0..0, "", 0..0).should == ""
+ "".bytesplice(0..0, "xyz", 0..1).should == "xy"
+ end
+
+ it "mutates self with substring and str range" do
+ s = "hello"
+ s.bytesplice(2..2, "xyz", 1..2).should.equal?(s)
+ s.should.eql?("heyzlo")
+ end
+
+ it "raises when string is frozen and str range" do
+ s = "hello".freeze
+ -> { s.bytesplice(2..2, "yzx", 0..1) }.should raise_error(FrozenError, "can't modify frozen String: \"hello\"")
end
end
end
describe "String#bytesplice with multibyte characters" do
- ruby_version_is "3.2" do
- it "raises IndexError when index is out of byte size boundary" do
- -> { "こんにちは".bytesplice(-16, 0, "xxx") }.should raise_error(IndexError, "index -16 out of string")
+ it "raises IndexError when index is out of byte size boundary" do
+ -> { "こんにちは".bytesplice(-16, 0, "xxx") }.should raise_error(IndexError, "index -16 out of string")
+ end
+
+ it "raises IndexError when index is not on a codepoint boundary" do
+ -> { "こんにちは".bytesplice(1, 0, "xxx") }.should raise_error(IndexError, "offset 1 does not land on character boundary")
+ end
+
+ it "raises IndexError when length is not matching the codepoint boundary" do
+ -> { "こんにちは".bytesplice(0, 1, "xxx") }.should raise_error(IndexError, "offset 1 does not land on character boundary")
+ -> { "こんにちは".bytesplice(0, 2, "xxx") }.should raise_error(IndexError, "offset 2 does not land on character boundary")
+ end
+
+ it "replaces with integer indices" do
+ "こんにちは".bytesplice(-15, 0, "xxx").should == "xxxこんにちは"
+ "こんにちは".bytesplice(0, 0, "xxx").should == "xxxこんにちは"
+ "こんにちは".bytesplice(0, 3, "xxx").should == "xxxんにちは"
+ "こんにちは".bytesplice(3, 3, "はは").should == "こははにちは"
+ "こんにちは".bytesplice(15, 0, "xxx").should == "こんにちはxxx"
+ end
+
+ it "replaces with range" do
+ "こんにちは".bytesplice(-15...-16, "xxx").should == "xxxこんにちは"
+ "こんにちは".bytesplice(0...0, "xxx").should == "xxxこんにちは"
+ "こんにちは".bytesplice(0..2, "xxx").should == "xxxんにちは"
+ "こんにちは".bytesplice(0...3, "xxx").should == "xxxんにちは"
+ "こんにちは".bytesplice(0..5, "xxx").should == "xxxにちは"
+ "こんにちは".bytesplice(0..-1, "xxx").should == "xxx"
+ "こんにちは".bytesplice(0...15, "xxx").should == "xxx"
+ "こんにちは".bytesplice(0...18, "xxx").should == "xxx"
+ end
+
+ it "treats negative length for range as 0" do
+ "こんにちは".bytesplice(0...-100, "xxx").should == "xxxこんにちは"
+ "こんにちは".bytesplice(3...-100, "xxx").should == "こxxxんにちは"
+ "こんにちは".bytesplice(-15...-100, "xxx").should == "xxxこんにちは"
+ end
+
+ it "raises when ranges not match codepoint boundaries" do
+ -> { "こんにちは".bytesplice(0..0, "x") }.should raise_error(IndexError, "offset 1 does not land on character boundary")
+ -> { "こんにちは".bytesplice(0..1, "x") }.should raise_error(IndexError, "offset 2 does not land on character boundary")
+ # Begin is incorrect
+ -> { "こんにちは".bytesplice(-4..-1, "x") }.should raise_error(IndexError, "offset 11 does not land on character boundary")
+ -> { "こんにちは".bytesplice(-5..-1, "x") }.should raise_error(IndexError, "offset 10 does not land on character boundary")
+ # End is incorrect
+ -> { "こんにちは".bytesplice(-3..-2, "x") }.should raise_error(IndexError, "offset 14 does not land on character boundary")
+ -> { "こんにちは".bytesplice(-3..-3, "x") }.should raise_error(IndexError, "offset 13 does not land on character boundary")
+ end
+
+ it "deals with a different encoded argument" do
+ s = "こんにちは"
+ s.encoding.should == Encoding::UTF_8
+ sub = "xxxxxx"
+ sub.force_encoding(Encoding::US_ASCII)
+
+ result = s.bytesplice(0, 3, sub)
+ result.should == "xxxxxxんにちは"
+ result.encoding.should == Encoding::UTF_8
+
+ s = "xxxxxx"
+ s.force_encoding(Encoding::US_ASCII)
+ sub = "こんにちは"
+ sub.encoding.should == Encoding::UTF_8
+
+ result = s.bytesplice(0, 3, sub)
+ result.should == "こんにちはxxx"
+ result.encoding.should == Encoding::UTF_8
+ end
+
+ ruby_version_is "3.3" do
+ it "raises IndexError when str_index is out of byte size boundary" do
+ -> { "こんにちは".bytesplice(3, 3, "こんにちは", -16, 0) }.should raise_error(IndexError, "index -16 out of string")
end
- it "raises IndexError when index is not on a codepoint boundary" do
- -> { "こんにちは".bytesplice(1, 0, "xxx") }.should raise_error(IndexError, "offset 1 does not land on character boundary")
+ it "raises IndexError when str_index is not on a codepoint boundary" do
+ -> { "こんにちは".bytesplice(3, 3, "こんにちは", 1, 0) }.should raise_error(IndexError, "offset 1 does not land on character boundary")
end
- it "raises IndexError when length is not matching the codepoint boundary" do
- -> { "こんにちは".bytesplice(0, 1, "xxx") }.should raise_error(IndexError, "offset 1 does not land on character boundary")
- -> { "こんにちは".bytesplice(0, 2, "xxx") }.should raise_error(IndexError, "offset 2 does not land on character boundary")
+ it "raises IndexError when str_length is not matching the codepoint boundary" do
+ -> { "こんにちは".bytesplice(3, 3, "こんにちは", 0, 1) }.should raise_error(IndexError, "offset 1 does not land on character boundary")
+ -> { "こんにちは".bytesplice(3, 3, "こんにちは", 0, 2) }.should raise_error(IndexError, "offset 2 does not land on character boundary")
end
- it "replaces with integer indices" do
- "こんにちは".bytesplice(-15, 0, "xxx").should == "xxxこんにちは"
- "こんにちは".bytesplice(0, 0, "xxx").should == "xxxこんにちは"
- "こんにちは".bytesplice(0, 3, "xxx").should == "xxxんにちは"
- "こんにちは".bytesplice(3, 3, "はは").should == "こははにちは"
- "こんにちは".bytesplice(15, 0, "xxx").should == "こんにちはxxx"
+ it "replaces with integer str indices" do
+ "こんにちは".bytesplice(3, 3, "こんにちは", -15, 0).should == "こにちは"
+ "こんにちは".bytesplice(3, 3, "こんにちは", 0, 0).should == "こにちは"
+ "こんにちは".bytesplice(3, 3, "こんにちは", 0, 3).should == "ここにちは"
+ "こんにちは".bytesplice(3, 3, "はは", 3, 3).should == "こはにちは"
+ "こんにちは".bytesplice(3, 3, "こんにちは", 15, 0).should == "こにちは"
end
- it "replaces with range" do
- "こんにちは".bytesplice(-15...-16, "xxx").should == "xxxこんにちは"
- "こんにちは".bytesplice(0...0, "xxx").should == "xxxこんにちは"
- "こんにちは".bytesplice(0..2, "xxx").should == "xxxんにちは"
- "こんにちは".bytesplice(0...3, "xxx").should == "xxxんにちは"
- "こんにちは".bytesplice(0..5, "xxx").should == "xxxにちは"
- "こんにちは".bytesplice(0..-1, "xxx").should == "xxx"
- "こんにちは".bytesplice(0...15, "xxx").should == "xxx"
- "こんにちは".bytesplice(0...18, "xxx").should == "xxx"
+ it "replaces with str range" do
+ "こんにちは".bytesplice(0..2, "こんにちは", -15...-16).should == "んにちは"
+ "こんにちは".bytesplice(0..2, "こんにちは", 0...0).should == "んにちは"
+ "こんにちは".bytesplice(0..2, "こんにちは", 3..5).should == "んんにちは"
+ "こんにちは".bytesplice(0..2, "こんにちは", 3...6).should == "んんにちは"
+ "こんにちは".bytesplice(0..2, "こんにちは", 3..8).should == "んにんにちは"
+ "こんにちは".bytesplice(0..2, "こんにちは", 0..-1).should == "こんにちはんにちは"
+ "こんにちは".bytesplice(0..2, "こんにちは", 0...15).should == "こんにちはんにちは"
+ "こんにちは".bytesplice(0..2, "こんにちは", 0...18).should == "こんにちはんにちは"
end
- it "treats negative length for range as 0" do
- "こんにちは".bytesplice(0...-100, "xxx").should == "xxxこんにちは"
- "こんにちは".bytesplice(3...-100, "xxx").should == "こxxxんにちは"
- "こんにちは".bytesplice(-15...-100, "xxx").should == "xxxこんにちは"
+ it "treats negative length for str range as 0" do
+ "こんにちは".bytesplice(0..2, "こんにちは", 0...-100).should == "んにちは"
+ "こんにちは".bytesplice(0..2, "こんにちは", 3...-100).should == "んにちは"
+ "こんにちは".bytesplice(0..2, "こんにちは", -15...-100).should == "んにちは"
end
- it "raises when ranges not match codepoint boundaries" do
- -> { "こんにちは".bytesplice(0..0, "x") }.should raise_error(IndexError, "offset 1 does not land on character boundary")
- -> { "こんにちは".bytesplice(0..1, "x") }.should raise_error(IndexError, "offset 2 does not land on character boundary")
+ it "raises when ranges not match codepoint boundaries in str" do
+ -> { "こんにちは".bytesplice(3...3, "こ", 0..0) }.should raise_error(IndexError, "offset 1 does not land on character boundary")
+ -> { "こんにちは".bytesplice(3...3, "こ", 0..1) }.should raise_error(IndexError, "offset 2 does not land on character boundary")
# Begin is incorrect
- -> { "こんにちは".bytesplice(-4..-1, "x") }.should raise_error(IndexError, "offset 11 does not land on character boundary")
- -> { "こんにちは".bytesplice(-5..-1, "x") }.should raise_error(IndexError, "offset 10 does not land on character boundary")
+ -> { "こんにちは".bytesplice(3...3, "こんにちは", -4..-1) }.should raise_error(IndexError, "offset 11 does not land on character boundary")
+ -> { "こんにちは".bytesplice(3...3, "こんにちは", -5..-1) }.should raise_error(IndexError, "offset 10 does not land on character boundary")
# End is incorrect
- -> { "こんにちは".bytesplice(-3..-2, "x") }.should raise_error(IndexError, "offset 14 does not land on character boundary")
- -> { "こんにちは".bytesplice(-3..-3, "x") }.should raise_error(IndexError, "offset 13 does not land on character boundary")
+ -> { "こんにちは".bytesplice(3...3, "こんにちは", -3..-2) }.should raise_error(IndexError, "offset 14 does not land on character boundary")
+ -> { "こんにちは".bytesplice(3...3, "こんにちは", -3..-3) }.should raise_error(IndexError, "offset 13 does not land on character boundary")
end
- it "deals with a different encoded argument" do
+ it "deals with a different encoded argument with str index/length" do
s = "こんにちは"
s.encoding.should == Encoding::UTF_8
- sub = "xxxxxx"
+ sub = "goodbye"
sub.force_encoding(Encoding::US_ASCII)
- result = s.bytesplice(0, 3, sub)
- result.should == "xxxxxxんにちは"
+ result = s.bytesplice(3, 3, sub, 0, 3)
+ result.should == "こgooにちは"
result.encoding.should == Encoding::UTF_8
- s = "xxxxxx"
+ s = "hello"
+ s.force_encoding(Encoding::US_ASCII)
+ sub = "こんにちは"
+ sub.encoding.should == Encoding::UTF_8
+
+ result = s.bytesplice(1, 2, sub, 3, 3)
+ result.should == "hんlo"
+ result.encoding.should == Encoding::UTF_8
+ end
+
+ it "deals with a different encoded argument with str range" do
+ s = "こんにちは"
+ s.encoding.should == Encoding::UTF_8
+ sub = "goodbye"
+ sub.force_encoding(Encoding::US_ASCII)
+
+ result = s.bytesplice(3..5, sub, 0..2)
+ result.should == "こgooにちは"
+ result.encoding.should == Encoding::UTF_8
+
+ s = "hello"
s.force_encoding(Encoding::US_ASCII)
sub = "こんにちは"
sub.encoding.should == Encoding::UTF_8
- result = s.bytesplice(0, 3, sub)
- result.should == "こんにちはxxx"
+ result = s.bytesplice(1..2, sub, 3..5)
+ result.should == "hんlo"
result.encoding.should == Encoding::UTF_8
end
end
diff --git a/spec/ruby/core/string/chilled_string_spec.rb b/spec/ruby/core/string/chilled_string_spec.rb
index 9f81b1af6d..73d055cbdf 100644
--- a/spec/ruby/core/string/chilled_string_spec.rb
+++ b/spec/ruby/core/string/chilled_string_spec.rb
@@ -2,69 +2,149 @@ require_relative '../../spec_helper'
describe "chilled String" do
guard -> { ruby_version_is "3.4" and !"test".equal?("test") } do
- describe "#frozen?" do
- it "returns false" do
- "chilled".frozen?.should == false
+ describe "chilled string literals" do
+
+ describe "#frozen?" do
+ it "returns false" do
+ "chilled".frozen?.should == false
+ end
end
- end
- describe "#-@" do
- it "returns a different instance" do
- input = "chilled"
- interned = (-input)
- interned.frozen?.should == true
- interned.object_id.should_not == input.object_id
+ describe "#-@" do
+ it "returns a different instance" do
+ input = "chilled"
+ interned = (-input)
+ interned.frozen?.should == true
+ interned.object_id.should_not == input.object_id
+ end
end
- end
- describe "#+@" do
- it "returns a different instance" do
- input = "chilled"
- duped = (+input)
- duped.frozen?.should == false
- duped.object_id.should_not == input.object_id
+ describe "#+@" do
+ it "returns a different instance" do
+ input = "chilled"
+ duped = (+input)
+ duped.frozen?.should == false
+ duped.object_id.should_not == input.object_id
+ end
end
- end
- describe "#clone" do
- it "preserves chilled status" do
- input = "chilled".clone
- -> {
- input << "-mutated"
- }.should complain(/literal string will be frozen in the future/)
- input.should == "chilled-mutated"
+ describe "#clone" do
+ it "preserves chilled status" do
+ input = "chilled".clone
+ -> {
+ input << "-mutated"
+ }.should complain(/literal string will be frozen in the future/)
+ input.should == "chilled-mutated"
+ end
+ end
+
+ describe "mutation" do
+ it "emits a warning" do
+ input = "chilled"
+ -> {
+ input << "-mutated"
+ }.should complain(/literal string will be frozen in the future/)
+ input.should == "chilled-mutated"
+ end
+
+ it "emits a warning for concatenated strings" do
+ input = "still" "+chilled"
+ -> {
+ input << "-mutated"
+ }.should complain(/literal string will be frozen in the future/)
+ input.should == "still+chilled-mutated"
+ end
+
+ it "emits a warning on singleton_class creation" do
+ -> {
+ "chilled".singleton_class
+ }.should complain(/literal string will be frozen in the future/)
+ end
+
+ it "emits a warning on instance variable assignment" do
+ -> {
+ "chilled".instance_variable_set(:@ivar, 42)
+ }.should complain(/literal string will be frozen in the future/)
+ end
+
+ it "raises FrozenError after the string was explicitly frozen" do
+ input = "chilled"
+ input.freeze
+ -> {
+ -> {
+ input << "mutated"
+ }.should raise_error(FrozenError)
+ }.should_not complain(/literal string will be frozen in the future/)
+ end
end
end
- describe "mutation" do
- it "emits a warning" do
- input = "chilled"
- -> {
- input << "-mutated"
- }.should complain(/literal string will be frozen in the future/)
- input.should == "chilled-mutated"
+ describe "chilled strings returned by Symbol#to_s" do
+
+ describe "#frozen?" do
+ it "returns false" do
+ :chilled.to_s.frozen?.should == false
+ end
end
- it "emits a warning on singleton_class creation" do
- -> {
- "chilled".singleton_class
- }.should complain(/literal string will be frozen in the future/)
+ describe "#-@" do
+ it "returns a different instance" do
+ input = :chilled.to_s
+ interned = (-input)
+ interned.frozen?.should == true
+ interned.object_id.should_not == input.object_id
+ end
end
- it "emits a warning on instance variable assignment" do
- -> {
- "chilled".instance_variable_set(:@ivar, 42)
- }.should complain(/literal string will be frozen in the future/)
+ describe "#+@" do
+ it "returns a different instance" do
+ input = :chilled.to_s
+ duped = (+input)
+ duped.frozen?.should == false
+ duped.object_id.should_not == input.object_id
+ end
+ end
+
+ describe "#clone" do
+ it "preserves chilled status" do
+ input = :chilled.to_s.clone
+ -> {
+ input << "-mutated"
+ }.should complain(/string returned by :chilled\.to_s will be frozen in the future/)
+ input.should == "chilled-mutated"
+ end
end
- it "raises FrozenError after the string was explicitly frozen" do
- input = "chilled"
- input.freeze
- -> {
+ describe "mutation" do
+ it "emits a warning" do
+ input = :chilled.to_s
+ -> {
+ input << "-mutated"
+ }.should complain(/string returned by :chilled\.to_s will be frozen in the future/)
+ input.should == "chilled-mutated"
+ end
+
+ it "emits a warning on singleton_class creation" do
+ -> {
+ :chilled.to_s.singleton_class
+ }.should complain(/string returned by :chilled\.to_s will be frozen in the future/)
+ end
+
+ it "emits a warning on instance variable assignment" do
+ -> {
+ :chilled.to_s.instance_variable_set(:@ivar, 42)
+ }.should complain(/string returned by :chilled\.to_s will be frozen in the future/)
+ end
+
+ it "raises FrozenError after the string was explicitly frozen" do
+ input = :chilled.to_s
+ input.freeze
-> {
- input << "mutated"
- }.should raise_error(FrozenError)
- }.should_not complain(/literal string will be frozen in the future/)
+ -> {
+ input << "mutated"
+ }.should raise_error(FrozenError)
+ }.should_not complain(/string returned by :chilled\.to_s will be frozen in the future/)
+ end
end
end
end
diff --git a/spec/ruby/core/string/codepoints_spec.rb b/spec/ruby/core/string/codepoints_spec.rb
index b276d0baa8..12a5bf5892 100644
--- a/spec/ruby/core/string/codepoints_spec.rb
+++ b/spec/ruby/core/string/codepoints_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
require_relative 'shared/codepoints'
require_relative 'shared/each_codepoint_without_block'
diff --git a/spec/ruby/core/string/count_spec.rb b/spec/ruby/core/string/count_spec.rb
index 06ba5a4f0e..e614e901dd 100644
--- a/spec/ruby/core/string/count_spec.rb
+++ b/spec/ruby/core/string/count_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
diff --git a/spec/ruby/core/string/dedup_spec.rb b/spec/ruby/core/string/dedup_spec.rb
index 57d2be2cfd..2b31d80708 100644
--- a/spec/ruby/core/string/dedup_spec.rb
+++ b/spec/ruby/core/string/dedup_spec.rb
@@ -2,7 +2,5 @@ require_relative '../../spec_helper'
require_relative 'shared/dedup'
describe 'String#dedup' do
- ruby_version_is '3.2' do
- it_behaves_like :string_dedup, :dedup
- end
+ it_behaves_like :string_dedup, :dedup
end
diff --git a/spec/ruby/core/string/encode_spec.rb b/spec/ruby/core/string/encode_spec.rb
index 97dd753b62..cd449498a3 100644
--- a/spec/ruby/core/string/encode_spec.rb
+++ b/spec/ruby/core/string/encode_spec.rb
@@ -61,10 +61,22 @@ describe "String#encode" do
str.encode(invalid: :replace).should_not equal(str)
end
- it "normalizes newlines" do
- "\r\nfoo".encode(universal_newline: true).should == "\nfoo"
+ it "normalizes newlines with cr_newline option" do
+ "\r\nfoo".encode(cr_newline: true).should == "\r\rfoo"
+ "\rfoo".encode(cr_newline: true).should == "\rfoo"
+ "\nfoo".encode(cr_newline: true).should == "\rfoo"
+ end
+ it "normalizes newlines with crlf_newline option" do
+ "\r\nfoo".encode(crlf_newline: true).should == "\r\r\nfoo"
+ "\rfoo".encode(crlf_newline: true).should == "\rfoo"
+ "\nfoo".encode(crlf_newline: true).should == "\r\nfoo"
+ end
+
+ it "normalizes newlines with universal_newline option" do
+ "\r\nfoo".encode(universal_newline: true).should == "\nfoo"
"\rfoo".encode(universal_newline: true).should == "\nfoo"
+ "\nfoo".encode(universal_newline: true).should == "\nfoo"
end
it "replaces invalid encoding in source with default replacement" do
diff --git a/spec/ruby/core/string/lstrip_spec.rb b/spec/ruby/core/string/lstrip_spec.rb
index 99bab6f349..c83650207e 100644
--- a/spec/ruby/core/string/lstrip_spec.rb
+++ b/spec/ruby/core/string/lstrip_spec.rb
@@ -7,11 +7,11 @@ 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"
- " こにちわ".lstrip.should == "こにちわ"
+ " 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"
+ " こにちわ".lstrip.should == "こにちわ"
end
it "works with lazy substrings" do
@@ -22,8 +22,8 @@ describe "String#lstrip" do
end
it "strips leading \\0" do
- "\x00hello".lstrip.should == "hello"
- "\000 \000hello\000 \000".lstrip.should == "hello\000 \000"
+ "\x00hello".lstrip.should == "hello"
+ "\000 \000hello\000 \000".lstrip.should == "hello\000 \000"
end
end
diff --git a/spec/ruby/core/string/modulo_spec.rb b/spec/ruby/core/string/modulo_spec.rb
index 9045afa263..46e0aa0f36 100644
--- a/spec/ruby/core/string/modulo_spec.rb
+++ b/spec/ruby/core/string/modulo_spec.rb
@@ -391,16 +391,8 @@ describe "String#%" do
("%c" % 'A').should == "A"
end
- ruby_version_is ""..."3.2" do
- it "raises an exception for multiple character strings as argument for %c" do
- -> { "%c" % 'AA' }.should raise_error(ArgumentError)
- end
- end
-
- ruby_version_is "3.2" do
- it "supports only the first character as argument for %c" do
- ("%c" % 'AA').should == "A"
- end
+ it "supports only the first character as argument for %c" do
+ ("%c" % 'AA').should == "A"
end
it "calls to_str on argument for %c formats" do
@@ -570,7 +562,7 @@ describe "String#%" do
("%1$p" % [10, 5]).should == "10"
("%-22p" % 10).should == "10 "
("%*p" % [10, 10]).should == " 10"
- ("%p" % {capture: 1}).should == "{:capture=>1}"
+ ("%p" % {capture: 1}).should == {capture: 1}.inspect
("%p" % "str").should == "\"str\""
end
@@ -749,6 +741,11 @@ describe "String#%" do
(format % "-10.4e-20").should == (format % -10.4e-20)
(format % ".5").should == (format % 0.5)
(format % "-.5").should == (format % -0.5)
+
+ ruby_version_is "3.4" do
+ (format % "10.").should == (format % 10)
+ end
+
# Something's strange with this spec:
# it works just fine in individual mode, but not when run as part of a group
(format % "10_1_0.5_5_5").should == (format % 1010.555)
@@ -758,7 +755,6 @@ describe "String#%" do
-> { format % "" }.should raise_error(ArgumentError)
-> { format % "x" }.should raise_error(ArgumentError)
-> { format % "." }.should raise_error(ArgumentError)
- -> { format % "10." }.should raise_error(ArgumentError)
-> { format % "5x" }.should raise_error(ArgumentError)
-> { format % "0b1" }.should raise_error(ArgumentError)
-> { format % "10e10.5" }.should raise_error(ArgumentError)
diff --git a/spec/ruby/core/string/rindex_spec.rb b/spec/ruby/core/string/rindex_spec.rb
index 88ce733583..0863a9c3be 100644
--- a/spec/ruby/core/string/rindex_spec.rb
+++ b/spec/ruby/core/string/rindex_spec.rb
@@ -371,8 +371,8 @@ describe "String#rindex with Regexp" do
end
it "returns the character index before the finish" do
- "ありがりがとう".rindex("が", 3).should == 2
- "ありがりがとう".rindex(/が/, 3).should == 2
+ "ありがりがとう".rindex("が", 3).should == 2
+ "ありがりがとう".rindex(/が/, 3).should == 2
end
it "raises an Encoding::CompatibilityError if the encodings are incompatible" do
diff --git a/spec/ruby/core/string/rstrip_spec.rb b/spec/ruby/core/string/rstrip_spec.rb
index 6d46eb590e..55773f5238 100644
--- a/spec/ruby/core/string/rstrip_spec.rb
+++ b/spec/ruby/core/string/rstrip_spec.rb
@@ -68,27 +68,13 @@ describe "String#rstrip!" do
-> { "".freeze.rstrip! }.should raise_error(FrozenError)
end
- ruby_version_is "3.2" do
- it "raises an Encoding::CompatibilityError if the last non-space codepoint is invalid" do
- s = "abc\xDF".force_encoding(Encoding::UTF_8)
- s.valid_encoding?.should be_false
- -> { s.rstrip! }.should raise_error(Encoding::CompatibilityError)
+ it "raises an Encoding::CompatibilityError if the last non-space codepoint is invalid" do
+ s = "abc\xDF".force_encoding(Encoding::UTF_8)
+ s.valid_encoding?.should be_false
+ -> { s.rstrip! }.should raise_error(Encoding::CompatibilityError)
- s = "abc\xDF ".force_encoding(Encoding::UTF_8)
- s.valid_encoding?.should be_false
- -> { s.rstrip! }.should raise_error(Encoding::CompatibilityError)
- end
- end
-
- ruby_version_is ""..."3.2" do
- it "raises an ArgumentError if the last non-space codepoint is invalid" do
- s = "abc\xDF".force_encoding(Encoding::UTF_8)
- s.valid_encoding?.should be_false
- -> { s.rstrip! }.should raise_error(ArgumentError)
-
- s = "abc\xDF ".force_encoding(Encoding::UTF_8)
- s.valid_encoding?.should be_false
- -> { s.rstrip! }.should raise_error(ArgumentError)
- end
+ s = "abc\xDF ".force_encoding(Encoding::UTF_8)
+ s.valid_encoding?.should be_false
+ -> { s.rstrip! }.should raise_error(Encoding::CompatibilityError)
end
end
diff --git a/spec/ruby/core/string/scan_spec.rb b/spec/ruby/core/string/scan_spec.rb
index 70c3b7fb7b..bbe843b591 100644
--- a/spec/ruby/core/string/scan_spec.rb
+++ b/spec/ruby/core/string/scan_spec.rb
@@ -103,11 +103,11 @@ describe "String#scan with pattern and block" do
offsets = []
str.scan(/([aeiou])/) do
- md = $~
- md.string.should == str
- matches << md.to_a
- offsets << md.offset(0)
- str
+ md = $~
+ md.string.should == str
+ matches << md.to_a
+ offsets << md.offset(0)
+ str
end
matches.should == [["e", "e"], ["o", "o"]]
@@ -117,11 +117,11 @@ describe "String#scan with pattern and block" do
offsets = []
str.scan("l") do
- md = $~
- md.string.should == str
- matches << md.to_a
- offsets << md.offset(0)
- str
+ md = $~
+ md.string.should == str
+ matches << md.to_a
+ offsets << md.offset(0)
+ str
end
matches.should == [["l"], ["l"]]
diff --git a/spec/ruby/core/string/shared/codepoints.rb b/spec/ruby/core/string/shared/codepoints.rb
index f71263054a..1c28ba3d5e 100644
--- a/spec/ruby/core/string/shared/codepoints.rb
+++ b/spec/ruby/core/string/shared/codepoints.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
describe :string_codepoints, shared: true do
it "returns self" do
s = "foo"
diff --git a/spec/ruby/core/string/shared/dedup.rb b/spec/ruby/core/string/shared/dedup.rb
index 97b5df6ed1..1ffd6aa0fd 100644
--- a/spec/ruby/core/string/shared/dedup.rb
+++ b/spec/ruby/core/string/shared/dedup.rb
@@ -48,9 +48,4 @@ describe :string_dedup, shared: true do
dynamic.send(@method).should_not equal("this string is frozen".send(@method).freeze)
dynamic.send(@method).should equal(dynamic)
end
-
- it "interns the provided string if it is frozen" do
- dynamic = "this string is unique and frozen #{rand}".freeze
- dynamic.send(@method).should equal(dynamic)
- end
end
diff --git a/spec/ruby/core/string/shared/each_codepoint_without_block.rb b/spec/ruby/core/string/shared/each_codepoint_without_block.rb
index 31b4c02c9c..c88e5c54c7 100644
--- a/spec/ruby/core/string/shared/each_codepoint_without_block.rb
+++ b/spec/ruby/core/string/shared/each_codepoint_without_block.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
describe :string_each_codepoint_without_block, shared: true do
describe "when no block is given" do
it "returns an Enumerator" do
diff --git a/spec/ruby/core/string/shared/encode.rb b/spec/ruby/core/string/shared/encode.rb
index 3776e0d709..9466308886 100644
--- a/spec/ruby/core/string/shared/encode.rb
+++ b/spec/ruby/core/string/shared/encode.rb
@@ -194,6 +194,190 @@ describe :string_encode, shared: true do
end
end
+ describe "given the fallback option" do
+ context "given a hash" do
+ it "looks up the replacement value from the hash" do
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: { "\ufffd" => "bar" })
+ encoded.should == "Bbar"
+ end
+
+ it "calls to_str on the returned value" do
+ obj = Object.new
+ obj.should_receive(:to_str).and_return("bar")
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: { "\ufffd" => obj })
+ encoded.should == "Bbar"
+ end
+
+ it "does not call to_s on the returned value" do
+ obj = Object.new
+ obj.should_not_receive(:to_s)
+ -> {
+ "B\ufffd".encode(Encoding::US_ASCII, fallback: { "\ufffd" => obj })
+ }.should raise_error(TypeError, "no implicit conversion of Object into String")
+ end
+
+ it "raises an error if the key is not present in the hash" do
+ -> {
+ "B\ufffd".encode(Encoding::US_ASCII, fallback: { "foo" => "bar" })
+ }.should raise_error(Encoding::UndefinedConversionError, "U+FFFD from UTF-8 to US-ASCII")
+ end
+
+ it "raises an error if the value is itself invalid" do
+ -> {
+ "B\ufffd".encode(Encoding::US_ASCII, fallback: { "\ufffd" => "\uffee" })
+ }.should raise_error(ArgumentError, "too big fallback string")
+ end
+
+ it "uses the hash's default value if set" do
+ hash = {}
+ hash.default = "bar"
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: hash)
+ encoded.should == "Bbar"
+ end
+
+ it "uses the result of calling default_proc if set" do
+ hash = {}
+ hash.default_proc = -> _, _ { "bar" }
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: hash)
+ encoded.should == "Bbar"
+ end
+ end
+
+ context "given an object inheriting from Hash" do
+ before do
+ klass = Class.new(Hash)
+ @hash_like = klass.new
+ @hash_like["\ufffd"] = "bar"
+ end
+
+ it "looks up the replacement value from the object" do
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: @hash_like)
+ encoded.should == "Bbar"
+ end
+ end
+
+ context "given an object responding to []" do
+ before do
+ klass = Class.new do
+ def [](c) = c.bytes.inspect
+ end
+ @hash_like = klass.new
+ end
+
+ it "calls [] on the object, passing the invalid character" do
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: @hash_like)
+ encoded.should == "B[239, 191, 189]"
+ end
+ end
+
+ context "given an object not responding to []" do
+ before do
+ @non_hash_like = Object.new
+ end
+
+ it "raises an error" do
+ -> {
+ "B\ufffd".encode(Encoding::US_ASCII, fallback: @non_hash_like)
+ }.should raise_error(Encoding::UndefinedConversionError, "U+FFFD from UTF-8 to US-ASCII")
+ end
+ end
+
+ context "given a proc" do
+ it "calls the proc to get the replacement value, passing in the invalid character" do
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: proc { |c| c.bytes.inspect })
+ encoded.should == "B[239, 191, 189]"
+ end
+
+ it "calls to_str on the returned value" do
+ obj = Object.new
+ obj.should_receive(:to_str).and_return("bar")
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: proc { |c| obj })
+ encoded.should == "Bbar"
+ end
+
+ it "does not call to_s on the returned value" do
+ obj = Object.new
+ obj.should_not_receive(:to_s)
+ -> {
+ "B\ufffd".encode(Encoding::US_ASCII, fallback: proc { |c| obj })
+ }.should raise_error(TypeError, "no implicit conversion of Object into String")
+ end
+
+ it "raises an error if the returned value is itself invalid" do
+ -> {
+ "B\ufffd".encode(Encoding::US_ASCII, fallback: -> c { "\uffee" })
+ }.should raise_error(ArgumentError, "too big fallback string")
+ end
+ end
+
+ context "given a lambda" do
+ it "calls the lambda to get the replacement value, passing in the invalid character" do
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: -> c { c.bytes.inspect })
+ encoded.should == "B[239, 191, 189]"
+ end
+
+ it "calls to_str on the returned value" do
+ obj = Object.new
+ obj.should_receive(:to_str).and_return("bar")
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: -> c { obj })
+ encoded.should == "Bbar"
+ end
+
+ it "does not call to_s on the returned value" do
+ obj = Object.new
+ obj.should_not_receive(:to_s)
+ -> {
+ "B\ufffd".encode(Encoding::US_ASCII, fallback: -> c { obj })
+ }.should raise_error(TypeError, "no implicit conversion of Object into String")
+ end
+
+ it "raises an error if the returned value is itself invalid" do
+ -> {
+ "B\ufffd".encode(Encoding::US_ASCII, fallback: -> c { "\uffee" })
+ }.should raise_error(ArgumentError, "too big fallback string")
+ end
+ end
+
+ context "given a method" do
+ def replace(c) = c.bytes.inspect
+ def replace_bad(c) = "\uffee"
+
+ def replace_to_str(c)
+ obj = Object.new
+ obj.should_receive(:to_str).and_return("bar")
+ obj
+ end
+
+ def replace_to_s(c)
+ obj = Object.new
+ obj.should_not_receive(:to_s)
+ obj
+ end
+
+ it "calls the method to get the replacement value, passing in the invalid character" do
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: method(:replace))
+ encoded.should == "B[239, 191, 189]"
+ end
+
+ it "calls to_str on the returned value" do
+ encoded = "B\ufffd".encode(Encoding::US_ASCII, fallback: method(:replace_to_str))
+ encoded.should == "Bbar"
+ end
+
+ it "does not call to_s on the returned value" do
+ -> {
+ "B\ufffd".encode(Encoding::US_ASCII, fallback: method(:replace_to_s))
+ }.should raise_error(TypeError, "no implicit conversion of Object into String")
+ end
+
+ it "raises an error if the returned value is itself invalid" do
+ -> {
+ "B\ufffd".encode(Encoding::US_ASCII, fallback: method(:replace_bad))
+ }.should raise_error(ArgumentError, "too big fallback string")
+ end
+ end
+ end
+
describe "given the xml: :text option" do
it "replaces all instances of '&' with '&amp;'" do
'& and &'.send(@method, "UTF-8", xml: :text).should == '&amp; and &amp;'
diff --git a/spec/ruby/core/string/shared/eql.rb b/spec/ruby/core/string/shared/eql.rb
index 845b0a3e15..d5af337d53 100644
--- a/spec/ruby/core/string/shared/eql.rb
+++ b/spec/ruby/core/string/shared/eql.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
diff --git a/spec/ruby/core/string/shared/slice.rb b/spec/ruby/core/string/shared/slice.rb
index 2f69b9ddce..7b9b9f6a14 100644
--- a/spec/ruby/core/string/shared/slice.rb
+++ b/spec/ruby/core/string/shared/slice.rb
@@ -119,6 +119,18 @@ describe :string_slice_index_length, shared: true do
"hello there".send(@method, -4,-3).should == nil
end
+ platform_is pointer_size: 64 do
+ it "returns nil if the length is negative big value" do
+ "hello there".send(@method, 4, -(1 << 31)).should == nil
+
+ # by some reason length < -(1 << 31) on CI on Windows leads to
+ # 'RangeError: bignum too big to convert into `long'' error
+ platform_is_not :windows do
+ "hello there".send(@method, 4, -(1 << 63)).should == nil
+ end
+ end
+ end
+
it "calls to_int on the given index and the given length" do
"hello".send(@method, 0.5, 1).should == "h"
"hello".send(@method, 0.5, 2.5).should == "he"
@@ -152,6 +164,11 @@ describe :string_slice_index_length, shared: true do
-> { "hello".send(@method, 0, bignum_value) }.should raise_error(RangeError)
end
+ it "raises a RangeError if the index or length is too small" do
+ -> { "hello".send(@method, -bignum_value, 1) }.should raise_error(RangeError)
+ -> { "hello".send(@method, 0, -bignum_value) }.should raise_error(RangeError)
+ end
+
it "returns String instances" do
s = StringSpecs::MyString.new("hello")
s.send(@method, 0,0).should be_an_instance_of(String)
diff --git a/spec/ruby/core/string/shared/succ.rb b/spec/ruby/core/string/shared/succ.rb
index b69a394875..7c68345f10 100644
--- a/spec/ruby/core/string/shared/succ.rb
+++ b/spec/ruby/core/string/shared/succ.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
describe :string_succ, shared: true do
it "returns an empty string for empty strings" do
"".send(@method).should == ""
diff --git a/spec/ruby/core/string/squeeze_spec.rb b/spec/ruby/core/string/squeeze_spec.rb
index 4ea238e6b5..981d480684 100644
--- a/spec/ruby/core/string/squeeze_spec.rb
+++ b/spec/ruby/core/string/squeeze_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
# frozen_string_literal: false
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
diff --git a/spec/ruby/core/string/sub_spec.rb b/spec/ruby/core/string/sub_spec.rb
index 4f9f87a433..6ff28ec851 100644
--- a/spec/ruby/core/string/sub_spec.rb
+++ b/spec/ruby/core/string/sub_spec.rb
@@ -232,10 +232,10 @@ describe "String#sub with pattern and block" do
offsets = []
str.sub(/([aeiou])/) do
- md = $~
- md.string.should == str
- offsets << md.offset(0)
- str
+ md = $~
+ md.string.should == str
+ offsets << md.offset(0)
+ str
end.should == "hhellollo"
offsets.should == [[1, 2]]
@@ -339,10 +339,10 @@ describe "String#sub! with pattern and block" do
offsets = []
str.dup.sub!(/([aeiou])/) do
- md = $~
- md.string.should == str
- offsets << md.offset(0)
- str
+ md = $~
+ md.string.should == str
+ offsets << md.offset(0)
+ str
end.should == "hhellollo"
offsets.should == [[1, 2]]
diff --git a/spec/ruby/core/string/swapcase_spec.rb b/spec/ruby/core/string/swapcase_spec.rb
index 7f4c68366d..011a213501 100644
--- a/spec/ruby/core/string/swapcase_spec.rb
+++ b/spec/ruby/core/string/swapcase_spec.rb
@@ -5,9 +5,9 @@ require_relative 'fixtures/classes'
describe "String#swapcase" do
it "returns a new string with all uppercase chars from self converted to lowercase and vice versa" do
- "Hello".swapcase.should == "hELLO"
- "cYbEr_PuNk11".swapcase.should == "CyBeR_pUnK11"
- "+++---111222???".swapcase.should == "+++---111222???"
+ "Hello".swapcase.should == "hELLO"
+ "cYbEr_PuNk11".swapcase.should == "CyBeR_pUnK11"
+ "+++---111222???".swapcase.should == "+++---111222???"
end
it "returns a String in the same encoding as self" do
diff --git a/spec/ruby/core/string/to_c_spec.rb b/spec/ruby/core/string/to_c_spec.rb
index 9d24f1f56c..1813890e72 100644
--- a/spec/ruby/core/string/to_c_spec.rb
+++ b/spec/ruby/core/string/to_c_spec.rb
@@ -13,18 +13,20 @@ describe "String#to_c" do
it "ignores trailing garbage" do
'79+4iruby'.to_c.should == Complex(79, 4)
- ruby_bug "[Bug #19087]", ""..."3.2" do
- '7__9+4__0i'.to_c.should == Complex(7, 0)
- end
+ '7__9+4__0i'.to_c.should == Complex(7, 0)
end
- it "understands Float::INFINITY" do
- 'Infinity'.to_c.should == Complex(0, 1)
- '-Infinity'.to_c.should == Complex(0, -1)
- end
+ context "it treats special float value strings as characters" do
+ it "parses any string that starts with 'I' as 1i" do
+ 'Infinity'.to_c.should == Complex(0, 1)
+ '-Infinity'.to_c.should == Complex(0, -1)
+ 'Insecure'.to_c.should == Complex(0, 1)
+ '-Insecure'.to_c.should == Complex(0, -1)
+ end
- it "understands Float::NAN" do
- 'NaN'.to_c.should == Complex(0, 0)
+ it "does not parse any numeric information in 'NaN'" do
+ 'NaN'.to_c.should == Complex(0, 0)
+ end
end
it "allows null-byte" do
@@ -39,15 +41,13 @@ describe "String#to_c" do
}.should raise_error(Encoding::CompatibilityError, "ASCII incompatible encoding: UTF-16")
end
- ruby_version_is "3.2" do
- it "treats a sequence of underscores as an end of Complex string" do
- "5+3_1i".to_c.should == Complex(5, 31)
- "5+3__1i".to_c.should == Complex(5)
- "5+3___1i".to_c.should == Complex(5)
+ it "treats a sequence of underscores as an end of Complex string" do
+ "5+3_1i".to_c.should == Complex(5, 31)
+ "5+3__1i".to_c.should == Complex(5)
+ "5+3___1i".to_c.should == Complex(5)
- "12_3".to_c.should == Complex(123)
- "12__3".to_c.should == Complex(12)
- "12___3".to_c.should == Complex(12)
- end
+ "12_3".to_c.should == Complex(123)
+ "12__3".to_c.should == Complex(12)
+ "12___3".to_c.should == Complex(12)
end
end
diff --git a/spec/ruby/core/string/to_f_spec.rb b/spec/ruby/core/string/to_f_spec.rb
index cf64ecfc5d..abfd2517b6 100644
--- a/spec/ruby/core/string/to_f_spec.rb
+++ b/spec/ruby/core/string/to_f_spec.rb
@@ -5,16 +5,15 @@ require_relative 'fixtures/classes'
describe "String#to_f" do
it "treats leading characters of self as a floating point number" do
- "123.45e1".to_f.should == 1234.5
- "45.67 degrees".to_f.should == 45.67
- "0".to_f.should == 0.0
- "123.45e1".to_f.should == 1234.5
+ "123.45e1".to_f.should == 1234.5
+ "45.67 degrees".to_f.should == 45.67
+ "0".to_f.should == 0.0
- ".5".to_f.should == 0.5
- ".5e1".to_f.should == 5.0
- "5.".to_f.should == 5.0
- "5e".to_f.should == 5.0
- "5E".to_f.should == 5.0
+ ".5".to_f.should == 0.5
+ ".5e1".to_f.should == 5.0
+ "5.".to_f.should == 5.0
+ "5e".to_f.should == 5.0
+ "5E".to_f.should == 5.0
end
it "treats special float value strings as characters" do
@@ -43,18 +42,39 @@ describe "String#to_f" do
"1_234_567.890_1".to_f.should == 1_234_567.890_1
end
- it "returns 0 for strings with any non-digit in them" do
- "blah".to_f.should == 0
- "0b5".to_f.should == 0
- "0d5".to_f.should == 0
- "0o5".to_f.should == 0
- "0xx5".to_f.should == 0
- end
-
it "returns 0 for strings with leading underscores" do
"_9".to_f.should == 0
end
+ it "stops if the underscore is not followed or preceded by a number" do
+ "1__2".to_f.should == 1.0
+ "1_.2".to_f.should == 1.0
+ "1._2".to_f.should == 1.0
+ "1.2_e2".to_f.should == 1.2
+ "1.2e_2".to_f.should == 1.2
+ "1_x2".to_f.should == 1.0
+ "1x_2".to_f.should == 1.0
+ "+_1".to_f.should == 0.0
+ "-_1".to_f.should == 0.0
+ end
+
+ it "does not allow prefixes to autodetect the base" do
+ "0b10".to_f.should == 0
+ "010".to_f.should == 10
+ "0o10".to_f.should == 0
+ "0d10".to_f.should == 0
+ "0x10".to_f.should == 0
+ end
+
+ it "treats any non-numeric character other than '.', 'e' and '_' as terminals" do
+ "blah".to_f.should == 0
+ "1b5".to_f.should == 1
+ "1d5".to_f.should == 1
+ "1o5".to_f.should == 1
+ "1xx5".to_f.should == 1
+ "x5".to_f.should == 0
+ end
+
it "takes an optional sign" do
"-45.67 degrees".to_f.should == -45.67
"+45.67 degrees".to_f.should == 45.67
@@ -63,8 +83,60 @@ describe "String#to_f" do
(1.0 / "-0".to_f).to_s.should == "-Infinity"
end
+ it "treats a second 'e' as terminal" do
+ "1.234e1e2".to_f.should == 1.234e1
+ end
+
+ it "treats a second '.' as terminal" do
+ "1.2.3".to_f.should == 1.2
+ end
+
+ it "treats a '.' after an 'e' as terminal" do
+ "1.234e1.9".to_f.should == 1.234e1
+ end
+
it "returns 0.0 if the conversion fails" do
"bad".to_f.should == 0.0
"thx1138".to_f.should == 0.0
end
+
+ it "ignores leading and trailing whitespace" do
+ " 1.2".to_f.should == 1.2
+ "1.2 ".to_f.should == 1.2
+ " 1.2 ".to_f.should == 1.2
+ "\t1.2".to_f.should == 1.2
+ "\n1.2".to_f.should == 1.2
+ "\v1.2".to_f.should == 1.2
+ "\f1.2".to_f.should == 1.2
+ "\r1.2".to_f.should == 1.2
+ end
+
+ it "treats non-printable ASCII characters as terminals" do
+ "\0001.2".to_f.should == 0
+ "\0011.2".to_f.should == 0
+ "\0371.2".to_f.should == 0
+ "\1771.2".to_f.should == 0
+ "\2001.2".b.to_f.should == 0
+ "\3771.2".b.to_f.should == 0
+ end
+
+ ruby_version_is "3.2.3" do
+ it "raises Encoding::CompatibilityError if String is in not ASCII-compatible encoding" do
+ -> {
+ '1.2'.encode("UTF-16").to_f
+ }.should raise_error(Encoding::CompatibilityError, "ASCII incompatible encoding: UTF-16")
+ end
+ end
+
+ it "allows String representation without a fractional part" do
+ "1.".to_f.should == 1.0
+ "+1.".to_f.should == 1.0
+ "-1.".to_f.should == -1.0
+ "1.e+0".to_f.should == 1.0
+ "1.e+0".to_f.should == 1.0
+
+ ruby_bug "#20705", ""..."3.4" do
+ "1.e-2".to_f.should be_close(0.01, TOLERANCE)
+ end
+ end
end
diff --git a/spec/ruby/core/string/to_i_spec.rb b/spec/ruby/core/string/to_i_spec.rb
index 9931502baa..39f69acda3 100644
--- a/spec/ruby/core/string/to_i_spec.rb
+++ b/spec/ruby/core/string/to_i_spec.rb
@@ -10,7 +10,7 @@ describe "String#to_i" do
"1_2_3asdf".to_i.should == 123
end
- it "ignores multiple non-consecutive underscoes when the first digit is 0" do
+ it "ignores multiple non-consecutive underscores when the first digit is 0" do
(2..16).each do |base|
"0_0_010".to_i(base).should == base;
end
diff --git a/spec/ruby/core/string/to_r_spec.rb b/spec/ruby/core/string/to_r_spec.rb
index 7e1d635d3b..4ffbb10d98 100644
--- a/spec/ruby/core/string/to_r_spec.rb
+++ b/spec/ruby/core/string/to_r_spec.rb
@@ -33,6 +33,10 @@ describe "String#to_r" do
"-20".to_r.should == Rational(-20, 1)
end
+ it "accepts leading plus signs" do
+ "+20".to_r.should == Rational(20, 1)
+ end
+
it "does not treat a leading period without a numeric prefix as a decimal point" do
".9".to_r.should_not == Rational(8106479329266893, 9007199254740992)
end
diff --git a/spec/ruby/core/string/unpack/a_spec.rb b/spec/ruby/core/string/unpack/a_spec.rb
index 4002ece697..a68e842e15 100644
--- a/spec/ruby/core/string/unpack/a_spec.rb
+++ b/spec/ruby/core/string/unpack/a_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
diff --git a/spec/ruby/core/string/unpack/at_spec.rb b/spec/ruby/core/string/unpack/at_spec.rb
index 70b2389d69..d4133c23ee 100644
--- a/spec/ruby/core/string/unpack/at_spec.rb
+++ b/spec/ruby/core/string/unpack/at_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
diff --git a/spec/ruby/core/string/unpack/b_spec.rb b/spec/ruby/core/string/unpack/b_spec.rb
index 23d93a8aea..b088f901fc 100644
--- a/spec/ruby/core/string/unpack/b_spec.rb
+++ b/spec/ruby/core/string/unpack/b_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
diff --git a/spec/ruby/core/string/unpack/c_spec.rb b/spec/ruby/core/string/unpack/c_spec.rb
index c2bf813954..1e9548fb82 100644
--- a/spec/ruby/core/string/unpack/c_spec.rb
+++ b/spec/ruby/core/string/unpack/c_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
diff --git a/spec/ruby/core/string/unpack/comment_spec.rb b/spec/ruby/core/string/unpack/comment_spec.rb
index e18a53df3c..050d2b7fc0 100644
--- a/spec/ruby/core/string/unpack/comment_spec.rb
+++ b/spec/ruby/core/string/unpack/comment_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
diff --git a/spec/ruby/core/string/unpack/h_spec.rb b/spec/ruby/core/string/unpack/h_spec.rb
index 19c4d63664..535836087d 100644
--- a/spec/ruby/core/string/unpack/h_spec.rb
+++ b/spec/ruby/core/string/unpack/h_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
diff --git a/spec/ruby/core/string/unpack/l_spec.rb b/spec/ruby/core/string/unpack/l_spec.rb
index 18bb68b8d0..0adb567eca 100644
--- a/spec/ruby/core/string/unpack/l_spec.rb
+++ b/spec/ruby/core/string/unpack/l_spec.rb
@@ -14,7 +14,7 @@ describe "String#unpack with format 'L'" do
it_behaves_like :string_unpack_32bit_be_unsigned, 'L>'
end
- platform_is wordsize: 32 do
+ platform_is c_long_size: 32 do
describe "with modifier '<' and '_'" do
it_behaves_like :string_unpack_32bit_le, 'L<_'
it_behaves_like :string_unpack_32bit_le, 'L_<'
@@ -44,7 +44,7 @@ describe "String#unpack with format 'L'" do
end
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
describe "with modifier '<' and '_'" do
it_behaves_like :string_unpack_64bit_le, 'L<_'
it_behaves_like :string_unpack_64bit_le, 'L_<'
@@ -86,7 +86,7 @@ describe "String#unpack with format 'l'" do
it_behaves_like :string_unpack_32bit_be_signed, 'l>'
end
- platform_is wordsize: 32 do
+ platform_is c_long_size: 32 do
describe "with modifier '<' and '_'" do
it_behaves_like :string_unpack_32bit_le, 'l<_'
it_behaves_like :string_unpack_32bit_le, 'l_<'
@@ -116,7 +116,7 @@ describe "String#unpack with format 'l'" do
end
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
describe "with modifier '<' and '_'" do
it_behaves_like :string_unpack_64bit_le, 'l<_'
it_behaves_like :string_unpack_64bit_le, 'l_<'
@@ -160,7 +160,7 @@ little_endian do
it_behaves_like :string_unpack_32bit_le_signed, 'l'
end
- platform_is wordsize: 32 do
+ platform_is c_long_size: 32 do
describe "String#unpack with format 'L' with modifier '_'" do
it_behaves_like :string_unpack_32bit_le, 'L_'
it_behaves_like :string_unpack_32bit_le_unsigned, 'L_'
@@ -182,7 +182,7 @@ little_endian do
end
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
describe "String#unpack with format 'L' with modifier '_'" do
it_behaves_like :string_unpack_64bit_le, 'L_'
it_behaves_like :string_unpack_64bit_le_unsigned, 'L_'
@@ -218,7 +218,7 @@ big_endian do
it_behaves_like :string_unpack_32bit_be_signed, 'l'
end
- platform_is wordsize: 32 do
+ platform_is c_long_size: 32 do
describe "String#unpack with format 'L' with modifier '_'" do
it_behaves_like :string_unpack_32bit_be, 'L_'
it_behaves_like :string_unpack_32bit_be_unsigned, 'L_'
@@ -240,7 +240,7 @@ big_endian do
end
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
describe "String#unpack with format 'L' with modifier '_'" do
it_behaves_like :string_unpack_64bit_be, 'L_'
it_behaves_like :string_unpack_64bit_be_unsigned, 'L_'
diff --git a/spec/ruby/core/string/unpack/m_spec.rb b/spec/ruby/core/string/unpack/m_spec.rb
index c551c755d1..357987a053 100644
--- a/spec/ruby/core/string/unpack/m_spec.rb
+++ b/spec/ruby/core/string/unpack/m_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
diff --git a/spec/ruby/core/string/unpack/shared/basic.rb b/spec/ruby/core/string/unpack/shared/basic.rb
index bb5302edc5..734630bda0 100644
--- a/spec/ruby/core/string/unpack/shared/basic.rb
+++ b/spec/ruby/core/string/unpack/shared/basic.rb
@@ -8,6 +8,22 @@ describe :string_unpack_basic, shared: true do
d.should_receive(:to_str).and_return("a"+unpack_format)
"abc".unpack(d).should be_an_instance_of(Array)
end
+
+ ruby_version_is ""..."3.3" do
+ it "warns about using an unknown directive" do
+ -> { "abcdefgh".unpack("a R" + unpack_format) }.should complain(/unknown unpack directive 'R' in 'a R#{unpack_format}'/)
+ -> { "abcdefgh".unpack("a 0" + unpack_format) }.should complain(/unknown unpack directive '0' in 'a 0#{unpack_format}'/)
+ -> { "abcdefgh".unpack("a :" + unpack_format) }.should complain(/unknown unpack directive ':' in 'a :#{unpack_format}'/)
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raises ArgumentError when a directive is unknown" do
+ -> { "abcdefgh".unpack("a K" + unpack_format) }.should raise_error(ArgumentError, "unknown unpack directive 'K' in 'a K#{unpack_format}'")
+ -> { "abcdefgh".unpack("a 0" + unpack_format) }.should raise_error(ArgumentError, "unknown unpack directive '0' in 'a 0#{unpack_format}'")
+ -> { "abcdefgh".unpack("a :" + unpack_format) }.should raise_error(ArgumentError, "unknown unpack directive ':' in 'a :#{unpack_format}'")
+ end
+ end
end
describe :string_unpack_no_platform, shared: true do
diff --git a/spec/ruby/core/string/unpack/shared/float.rb b/spec/ruby/core/string/unpack/shared/float.rb
index 93282bf4c9..b31c2c8bdc 100644
--- a/spec/ruby/core/string/unpack/shared/float.rb
+++ b/spec/ruby/core/string/unpack/shared/float.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
describe :string_unpack_float_le, shared: true do
it "decodes one float for a single format character" do
diff --git a/spec/ruby/core/string/unpack/shared/integer.rb b/spec/ruby/core/string/unpack/shared/integer.rb
index d71a2cf00d..d3934753ba 100644
--- a/spec/ruby/core/string/unpack/shared/integer.rb
+++ b/spec/ruby/core/string/unpack/shared/integer.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
describe :string_unpack_16bit_le, shared: true do
it "decodes one short for a single format character" do
diff --git a/spec/ruby/core/string/unpack/u_spec.rb b/spec/ruby/core/string/unpack/u_spec.rb
index 456abee784..68c8f6f11c 100644
--- a/spec/ruby/core/string/unpack/u_spec.rb
+++ b/spec/ruby/core/string/unpack/u_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
diff --git a/spec/ruby/core/string/unpack/w_spec.rb b/spec/ruby/core/string/unpack/w_spec.rb
index 6a1cff1965..7d3533ccae 100644
--- a/spec/ruby/core/string/unpack/w_spec.rb
+++ b/spec/ruby/core/string/unpack/w_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
diff --git a/spec/ruby/core/string/unpack/x_spec.rb b/spec/ruby/core/string/unpack/x_spec.rb
index 5e248de77e..2926ebbe0f 100644
--- a/spec/ruby/core/string/unpack/x_spec.rb
+++ b/spec/ruby/core/string/unpack/x_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
diff --git a/spec/ruby/core/string/unpack/z_spec.rb b/spec/ruby/core/string/unpack/z_spec.rb
index ce8da4b29e..1030390550 100644
--- a/spec/ruby/core/string/unpack/z_spec.rb
+++ b/spec/ruby/core/string/unpack/z_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/basic'
diff --git a/spec/ruby/core/string/unpack1_spec.rb b/spec/ruby/core/string/unpack1_spec.rb
index df830916a3..cfb47fe695 100644
--- a/spec/ruby/core/string/unpack1_spec.rb
+++ b/spec/ruby/core/string/unpack1_spec.rb
@@ -8,29 +8,40 @@ describe "String#unpack1" do
"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 "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 "traits offset as a bytes offset" do
- "؈".unpack("CC").should == [216, 136]
- "؈".unpack1("C").should == 216
- "؈".unpack1("C", offset: 1).should == 136
- end
+ it "traits offset as a bytes offset" do
+ "؈".unpack("CC").should == [216, 136]
+ "؈".unpack1("C").should == 216
+ "؈".unpack1("C", offset: 1).should == 136
+ end
- it "raises an ArgumentError when the offset is negative" do
- -> { "a".unpack1("C", offset: -1) }.should raise_error(ArgumentError, "offset can't be negative")
- end
+ it "raises an ArgumentError when the offset is negative" do
+ -> { "a".unpack1("C", offset: -1) }.should raise_error(ArgumentError, "offset can't be negative")
+ 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 larger than the string bytesize" do
+ -> { "a".unpack1("C", offset: 2) }.should raise_error(ArgumentError, "offset outside of string")
+ end
+
+ context "with format 'm0'" do
+ # unpack1("m0") takes a special code path that calls Pack.unpackBase46Strict instead of Pack.unpack_m,
+ # which is why we repeat the tests for unpack("m0") here.
- it "returns nil if the offset is at the end of the string" do
- "a".unpack1("C", offset: 1).should == nil
+ it "decodes base64" do
+ "dGVzdA==".unpack1("m0").should == "test"
end
- it "raises an ArgumentError when the offset is larger than the string bytesize" do
- -> { "a".unpack1("C", offset: 2) }.should raise_error(ArgumentError, "offset outside of string")
+ it "raises an ArgumentError for an invalid base64 character" do
+ -> { "dGV%zdA==".unpack1("m0") }.should raise_error(ArgumentError)
end
end
end
diff --git a/spec/ruby/core/string/unpack_spec.rb b/spec/ruby/core/string/unpack_spec.rb
index 52b4af3a95..a0abf8fa99 100644
--- a/spec/ruby/core/string/unpack_spec.rb
+++ b/spec/ruby/core/string/unpack_spec.rb
@@ -9,26 +9,24 @@ describe "String#unpack" 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
+ it "starts unpacking from the given offset" do
+ "abc".unpack("CC", offset: 1).should == [98, 99]
+ end
- it "traits offset as a bytes offset" do
- "؈".unpack("CC").should == [216, 136]
- "؈".unpack("CC", offset: 1).should == [136, nil]
- end
+ it "traits offset as a bytes offset" do
+ "؈".unpack("CC").should == [216, 136]
+ "؈".unpack("CC", offset: 1).should == [136, nil]
+ end
- it "raises an ArgumentError when the offset is negative" do
- -> { "a".unpack("C", offset: -1) }.should raise_error(ArgumentError, "offset can't be negative")
- end
+ it "raises an ArgumentError when the offset is negative" do
+ -> { "a".unpack("C", offset: -1) }.should raise_error(ArgumentError, "offset can't be negative")
+ end
- it "returns nil if the offset is at the end of the string" do
- "a".unpack("C", offset: 1).should == [nil]
- 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, "offset outside of string")
- end
+ it "raises an ArgumentError when the offset is larger than the string" do
+ -> { "a".unpack("C", offset: 2) }.should raise_error(ArgumentError, "offset outside of string")
end
end
diff --git a/spec/ruby/core/string/uplus_spec.rb b/spec/ruby/core/string/uplus_spec.rb
index c0b0c49ede..20767bcc01 100644
--- a/spec/ruby/core/string/uplus_spec.rb
+++ b/spec/ruby/core/string/uplus_spec.rb
@@ -13,14 +13,48 @@ describe 'String#+@' do
output.should == 'foobar'
end
- it 'returns self if the String is not frozen' do
- input = 'foo'
+ it 'returns a mutable String itself' do
+ input = String.new("foo")
output = +input
- output.equal?(input).should == true
+ output.should.equal?(input)
+
+ input << "bar"
+ output.should == "foobar"
+ end
+
+ context 'if file has "frozen_string_literal: true" magic comment' do
+ it 'returns mutable copy of a literal' do
+ ruby_exe(fixture(__FILE__, "freeze_magic_comment.rb")).should == 'mutable'
+ end
end
- it 'returns mutable copy despite freeze-magic-comment in file' do
- ruby_exe(fixture(__FILE__, "freeze_magic_comment.rb")).should == 'mutable'
+ context 'if file has "frozen_string_literal: false" magic comment' do
+ it 'returns literal string itself' do
+ input = 'foo'
+ output = +input
+
+ output.equal?(input).should == true
+ end
+ end
+
+ context 'if file has no frozen_string_literal magic comment' do
+ ruby_version_is ''...'3.4' do
+ it 'returns literal string itself' do
+ eval(<<~RUBY).should == true
+ s = "foo"
+ s.equal?(+s)
+ RUBY
+ end
+ end
+
+ ruby_version_is '3.4' do
+ it 'returns mutable copy of a literal' do
+ eval(<<~RUBY).should == false
+ s = "foo"
+ s.equal?(+s)
+ RUBY
+ end
+ end
end
end
diff --git a/spec/ruby/core/struct/constants_spec.rb b/spec/ruby/core/struct/constants_spec.rb
index fa61a4b912..7e8af1a211 100644
--- a/spec/ruby/core/struct/constants_spec.rb
+++ b/spec/ruby/core/struct/constants_spec.rb
@@ -1,15 +1,13 @@
require_relative '../../spec_helper'
-ruby_version_is "3.2" do
- describe "Struct::Group" do
- it "is no longer defined" do
- Struct.should_not.const_defined?(:Group)
- end
+describe "Struct::Group" do
+ it "is no longer defined" do
+ Struct.should_not.const_defined?(:Group)
end
+end
- describe "Struct::Passwd" do
- it "is no longer defined" do
- Struct.should_not.const_defined?(:Passwd)
- end
+describe "Struct::Passwd" do
+ it "is no longer defined" do
+ Struct.should_not.const_defined?(:Passwd)
end
end
diff --git a/spec/ruby/core/struct/deconstruct_keys_spec.rb b/spec/ruby/core/struct/deconstruct_keys_spec.rb
index b4c84c49df..e16b50f930 100644
--- a/spec/ruby/core/struct/deconstruct_keys_spec.rb
+++ b/spec/ruby/core/struct/deconstruct_keys_spec.rb
@@ -40,6 +40,21 @@ describe "Struct#deconstruct_keys" do
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}
+ s.deconstruct_keys([-1] ).should == {-1 => 30}
+ end
+
+ it "ignores incorrect position numbers" do
+ struct = Struct.new(:x, :y, :z)
+ s = struct.new(10, 20, 30)
+
+ s.deconstruct_keys([0, 3]).should == {0 => 10}
+ end
+
+ it "support mixing attribute names and argument position numbers" do
+ struct = Struct.new(:x, :y)
+ s = struct.new(1, 2)
+
+ s.deconstruct_keys([0, :x]).should == {0 => 1, :x => 1}
end
it "returns an empty hash when there are more keys than attributes" do
@@ -57,6 +72,14 @@ describe "Struct#deconstruct_keys" do
s.deconstruct_keys([:x, :a]).should == {x: 1}
end
+ it "returns at first not existing argument position number" do
+ struct = Struct.new(:x, :y)
+ s = struct.new(1, 2)
+
+ s.deconstruct_keys([3, 0]).should == {}
+ s.deconstruct_keys([0, 3]).should == {0 => 1}
+ end
+
it "accepts nil argument and return all the attributes" do
struct = Struct.new(:x, :y)
obj = struct.new(1, 2)
@@ -64,6 +87,37 @@ describe "Struct#deconstruct_keys" do
obj.deconstruct_keys(nil).should == {x: 1, y: 2}
end
+ it "tries to convert a key with #to_int if index is not a String nor a Symbol, but responds to #to_int" do
+ struct = Struct.new(:x, :y)
+ s = struct.new(1, 2)
+
+ key = mock("to_int")
+ key.should_receive(:to_int).and_return(1)
+
+ s.deconstruct_keys([key]).should == { key => 2 }
+ end
+
+ it "raises a TypeError if the conversion with #to_int does not return an Integer" do
+ struct = Struct.new(:x, :y)
+ s = struct.new(1, 2)
+
+ key = mock("to_int")
+ key.should_receive(:to_int).and_return("not an Integer")
+
+ -> {
+ s.deconstruct_keys([key])
+ }.should raise_error(TypeError, /can't convert MockObject to Integer/)
+ end
+
+ it "raises TypeError if index is not a String, a Symbol and not convertible to Integer" do
+ struct = Struct.new(:x, :y)
+ s = struct.new(1, 2)
+
+ -> {
+ s.deconstruct_keys([0, []])
+ }.should raise_error(TypeError, "no implicit conversion of Array into Integer")
+ end
+
it "raise TypeError if passed anything except nil or array" do
struct = Struct.new(:x, :y)
s = struct.new(1, 2)
diff --git a/spec/ruby/core/struct/element_set_spec.rb b/spec/ruby/core/struct/element_set_spec.rb
index 6ba7b081a9..0a0e34a5ee 100644
--- a/spec/ruby/core/struct/element_set_spec.rb
+++ b/spec/ruby/core/struct/element_set_spec.rb
@@ -26,4 +26,11 @@ describe "Struct#[]=" do
-> { car[-4] = true }.should raise_error(IndexError)
-> { car[Object.new] = true }.should raise_error(TypeError)
end
+
+ it "raises a FrozenError on a frozen struct" do
+ car = StructClasses::Car.new('Ford', 'Ranger')
+ car.freeze
+
+ -> { car[:model] = 'Escape' }.should raise_error(FrozenError)
+ end
end
diff --git a/spec/ruby/core/struct/fixtures/classes.rb b/spec/ruby/core/struct/fixtures/classes.rb
index bf838d05df..7b80b814ef 100644
--- a/spec/ruby/core/struct/fixtures/classes.rb
+++ b/spec/ruby/core/struct/fixtures/classes.rb
@@ -29,4 +29,6 @@ module StructClasses
super
end
end
+
+ class StructSubclass < Struct; end
end
diff --git a/spec/ruby/core/struct/initialize_spec.rb b/spec/ruby/core/struct/initialize_spec.rb
index a5ebe9551c..06055594d5 100644
--- a/spec/ruby/core/struct/initialize_spec.rb
+++ b/spec/ruby/core/struct/initialize_spec.rb
@@ -41,21 +41,11 @@ describe "Struct#initialize" do
StructClasses::SubclassX.new(:y).new.key.should == :value
end
- ruby_version_is "3.1"..."3.2" do
- it "warns about passing only keyword arguments" do
- -> {
- StructClasses::Ruby.new(version: "3.1", platform: "OS")
- }.should complain(/warning: Passing only keyword arguments/)
- end
- end
+ it "can be initialized with keyword arguments" do
+ positional_args = StructClasses::Ruby.new("3.2", "OS")
+ keyword_args = StructClasses::Ruby.new(version: "3.2", platform: "OS")
- ruby_version_is "3.2" do
- it "can be initialized with keyword arguments" do
- positional_args = StructClasses::Ruby.new("3.2", "OS")
- keyword_args = StructClasses::Ruby.new(version: "3.2", platform: "OS")
-
- positional_args.version.should == keyword_args.version
- positional_args.platform.should == keyword_args.platform
- end
+ positional_args.version.should == keyword_args.version
+ positional_args.platform.should == keyword_args.platform
end
end
diff --git a/spec/ruby/core/struct/keyword_init_spec.rb b/spec/ruby/core/struct/keyword_init_spec.rb
index 8de4c14351..536b82041a 100644
--- a/spec/ruby/core/struct/keyword_init_spec.rb
+++ b/spec/ruby/core/struct/keyword_init_spec.rb
@@ -1,40 +1,45 @@
require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
-ruby_version_is "3.1" do
- # See https://bugs.ruby-lang.org/issues/18008
- describe "StructClass#keyword_init?" do
- it "returns true for a struct that accepts keyword arguments to initialize" do
- struct = Struct.new(:arg, keyword_init: true)
- struct.keyword_init?.should be_true
- end
+# See https://bugs.ruby-lang.org/issues/18008
+describe "StructClass#keyword_init?" do
+ it "returns true for a struct that accepts keyword arguments to initialize" do
+ struct = Struct.new(:arg, keyword_init: true)
+ struct.keyword_init?.should be_true
+ end
- it "returns false for a struct that does not accept keyword arguments to initialize" do
- struct = Struct.new(:arg, keyword_init: false)
- struct.keyword_init?.should be_false
- end
+ it "returns false for a struct that does not accept keyword arguments to initialize" do
+ struct = Struct.new(:arg, keyword_init: false)
+ struct.keyword_init?.should be_false
+ end
- it "returns nil for a struct that did not explicitly specify keyword_init" do
- struct = Struct.new(:arg)
- struct.keyword_init?.should be_nil
- end
+ it "returns nil for a struct that did not explicitly specify keyword_init" do
+ struct = Struct.new(:arg)
+ struct.keyword_init?.should be_nil
+ end
- it "returns nil for a struct that does specify keyword_init to be nil" do
- struct = Struct.new(:arg, keyword_init: nil)
- struct.keyword_init?.should be_nil
- end
+ it "returns nil for a struct that does specify keyword_init to be nil" do
+ struct = Struct.new(:arg, keyword_init: nil)
+ struct.keyword_init?.should be_nil
+ end
- it "returns true for any truthy value, not just for true" do
- struct = Struct.new(:arg, keyword_init: 1)
- struct.keyword_init?.should be_true
+ it "returns true for any truthy value, not just for true" do
+ struct = Struct.new(:arg, keyword_init: 1)
+ struct.keyword_init?.should be_true
- struct = Struct.new(:arg, keyword_init: "")
- struct.keyword_init?.should be_true
+ struct = Struct.new(:arg, keyword_init: "")
+ struct.keyword_init?.should be_true
- struct = Struct.new(:arg, keyword_init: [])
- struct.keyword_init?.should be_true
+ struct = Struct.new(:arg, keyword_init: [])
+ struct.keyword_init?.should be_true
+
+ struct = Struct.new(:arg, keyword_init: {})
+ struct.keyword_init?.should be_true
+ end
- struct = Struct.new(:arg, keyword_init: {})
- struct.keyword_init?.should be_true
+ context "class inheriting Struct" do
+ it "isn't available in a subclass" do
+ StructClasses::StructSubclass.should_not.respond_to?(:keyword_init?)
end
end
end
diff --git a/spec/ruby/core/struct/members_spec.rb b/spec/ruby/core/struct/members_spec.rb
index 1f2ff950d9..1ff7b9387a 100644
--- a/spec/ruby/core/struct/members_spec.rb
+++ b/spec/ruby/core/struct/members_spec.rb
@@ -11,3 +11,15 @@ describe "Struct#members" do
it_behaves_like :struct_accessor, :members
end
+
+describe "StructClass#members" do
+ it "returns an array of attribute names" do
+ StructClasses::Car.members.should == [:make, :model, :year]
+ end
+
+ context "class inheriting Struct" do
+ it "isn't available in a subclass" do
+ StructClasses::StructSubclass.should_not.respond_to?(:members)
+ end
+ end
+end
diff --git a/spec/ruby/core/struct/new_spec.rb b/spec/ruby/core/struct/new_spec.rb
index a94eb852e1..1d35de7b87 100644
--- a/spec/ruby/core/struct/new_spec.rb
+++ b/spec/ruby/core/struct/new_spec.rb
@@ -6,6 +6,8 @@ describe "Struct.new" do
struct = Struct.new('Animal', :name, :legs, :eyeballs)
struct.should == Struct::Animal
struct.name.should == "Struct::Animal"
+ ensure
+ Struct.send(:remove_const, :Animal)
end
it "overwrites previously defined constants with string as first argument" do
@@ -19,6 +21,8 @@ describe "Struct.new" do
second.should == Struct::Person
first.members.should_not == second.members
+ ensure
+ Struct.send(:remove_const, :Person)
end
it "calls to_str on its first argument (constant name)" do
@@ -27,6 +31,8 @@ describe "Struct.new" do
struct = Struct.new(obj)
struct.should == Struct::Foo
struct.name.should == "Struct::Foo"
+ ensure
+ Struct.send(:remove_const, :Foo)
end
it "creates a new anonymous class with nil first argument" do
@@ -67,20 +73,8 @@ describe "Struct.new" do
-> { Struct.new(:animal, ['chris', 'evan']) }.should raise_error(TypeError)
end
- ruby_version_is ""..."3.2" do
- it "raises a TypeError or ArgumentError if passed a Hash with an unknown key" do
- # CRuby < 3.2 raises ArgumentError: unknown keyword: :name, but that seems a bug:
- # https://bugs.ruby-lang.org/issues/18632
- -> { Struct.new(:animal, { name: 'chris' }) }.should raise_error(StandardError) { |e|
- [ArgumentError, TypeError].should.include?(e.class)
- }
- end
- end
-
- ruby_version_is "3.2" do
- it "raises a TypeError if passed a Hash with an unknown key" do
- -> { Struct.new(:animal, { name: 'chris' }) }.should raise_error(TypeError)
- end
+ it "raises a TypeError if passed a Hash with an unknown key" do
+ -> { Struct.new(:animal, { name: 'chris' }) }.should raise_error(TypeError)
end
ruby_version_is ""..."3.3" do
@@ -138,6 +132,8 @@ describe "Struct.new" do
it "creates a constant in subclass' namespace" do
struct = StructClasses::Apple.new('Computer', :size)
struct.should == StructClasses::Apple::Computer
+ ensure
+ StructClasses::Apple.send(:remove_const, :Computer)
end
it "creates an instance" do
@@ -158,29 +154,43 @@ describe "Struct.new" do
-> { StructClasses::Ruby.new('2.0', 'i686', true) }.should raise_error(ArgumentError)
end
- ruby_version_is ''...'3.1' do
- it "passes a hash as a normal argument" do
- type = Struct.new(:args)
+ it "accepts keyword arguments to initialize" do
+ type = Struct.new(:args)
- obj = suppress_warning {type.new(keyword: :arg)}
- obj2 = type.new(*[{keyword: :arg}])
+ obj = type.new(args: 42)
+ obj2 = type.new(42)
- obj.should == obj2
- obj.args.should == {keyword: :arg}
- obj2.args.should == {keyword: :arg}
- end
+ obj.should == obj2
+ obj.args.should == 42
+ obj2.args.should == 42
end
- ruby_version_is '3.2' do
- it "accepts keyword arguments to initialize" do
- type = Struct.new(:args)
+ context "given positional and keyword arguments" do
+ it "treats keyword arguments as a positional parameter" do
+ type = Struct.new(:a, :b)
+ s = type.new("a", b: "b")
+ s.a.should == "a"
+ s.b.should == {b: "b"}
+
+ type = Struct.new(:a, :b, :c)
+ s = type.new("a", b: "b", c: "c")
+ s.a.should == "a"
+ s.b.should == {b: "b", c: "c"}
+ s.c.should == nil
+ end
+
+ it "ignores empty keyword arguments" do
+ type = Struct.new(:a, :b)
+ h = {}
+ s = type.new("a", **h)
- obj = type.new(args: 42)
- obj2 = type.new(42)
+ s.a.should == "a"
+ s.b.should == nil
+ end
- obj.should == obj2
- obj.args.should == 42
- obj2.args.should == 42
+ it "raises ArgumentError when all struct attribute values are specified" do
+ type = Struct.new(:a, :b)
+ -> { type.new("a", "b", c: "c") }.should raise_error(ArgumentError, "struct size differs")
end
end
end
diff --git a/spec/ruby/core/struct/struct_spec.rb b/spec/ruby/core/struct/struct_spec.rb
index 8817dc1a58..1b6a4488ce 100644
--- a/spec/ruby/core/struct/struct_spec.rb
+++ b/spec/ruby/core/struct/struct_spec.rb
@@ -33,6 +33,13 @@ describe "Struct anonymous class instance methods" do
car['model'].should == 'F150'
car[1].should == 'F150'
end
+
+ it "writer methods raise a FrozenError on a frozen struct" do
+ car = StructClasses::Car.new('Ford', 'Ranger')
+ car.freeze
+
+ -> { car.model = 'Escape' }.should raise_error(FrozenError)
+ end
end
describe "Struct subclasses" do
diff --git a/spec/ruby/core/struct/to_h_spec.rb b/spec/ruby/core/struct/to_h_spec.rb
index bfb0af07ba..861ce3f49d 100644
--- a/spec/ruby/core/struct/to_h_spec.rb
+++ b/spec/ruby/core/struct/to_h_spec.rb
@@ -21,6 +21,18 @@ describe "Struct#to_h" do
h.should == { "make" => "ford", "model" => "ranger", "year" => "" }
end
+ it "passes to a block each pair's key and value as separate arguments" do
+ s = StructClasses::Ruby.new('3.2.4', 'macos')
+
+ ScratchPad.record []
+ s.to_h { |k, v| ScratchPad << [k, v]; [k, v] }
+ ScratchPad.recorded.sort.should == [[:platform, 'macos'], [:version, '3.2.4']]
+
+ ScratchPad.record []
+ s.to_h { |*args| ScratchPad << args; [args[0], args[1]] }
+ ScratchPad.recorded.sort.should == [[:platform, 'macos'], [:version, '3.2.4']]
+ 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] }
diff --git a/spec/ruby/core/symbol/inspect_spec.rb b/spec/ruby/core/symbol/inspect_spec.rb
index 6dbb36c2ad..df4566c48e 100644
--- a/spec/ruby/core/symbol/inspect_spec.rb
+++ b/spec/ruby/core/symbol/inspect_spec.rb
@@ -6,7 +6,7 @@ describe "Symbol#inspect" do
:fred? => ":fred?",
:fred! => ":fred!",
:BAD! => ":BAD!",
- :_BAD! => ":_BAD!",
+ :_BAD! => ":_BAD!",
:$ruby => ":$ruby",
:@ruby => ":@ruby",
:@@ruby => ":@@ruby",
@@ -66,9 +66,9 @@ describe "Symbol#inspect" do
:~ => ":~",
:| => ":|",
- :"!" => [":\"!\"", ":!" ],
- :"!=" => [":\"!=\"", ":!="],
- :"!~" => [":\"!~\"", ":!~"],
+ :"!" => ":!",
+ :"!=" => ":!=",
+ :"!~" => ":!~",
:"\$" => ":\"$\"", # for justice!
:"&&" => ":\"&&\"",
:"'" => ":\"\'\"",
@@ -96,10 +96,15 @@ describe "Symbol#inspect" do
:"foo " => ":\"foo \"",
:" foo" => ":\" foo\"",
:" " => ":\" \"",
+
+ :"ê" => [":ê", ":\"\\u00EA\""],
+ :"测" => [":测", ":\"\\u6D4B\""],
+ :"🦊" => [":🦊", ":\"\\u{1F98A}\""],
}
+ expected_by_encoding = Encoding::default_external == Encoding::UTF_8 ? 0 : 1
symbols.each do |input, expected|
- expected = expected[1] if expected.is_a?(Array)
+ expected = expected[expected_by_encoding] if expected.is_a?(Array)
it "returns self as a symbol literal for #{expected}" do
input.inspect.should == expected
end
diff --git a/spec/ruby/core/symbol/shared/id2name.rb b/spec/ruby/core/symbol/shared/id2name.rb
index d012b7634e..00a9c7d7dc 100644
--- a/spec/ruby/core/symbol/shared/id2name.rb
+++ b/spec/ruby/core/symbol/shared/id2name.rb
@@ -13,4 +13,18 @@ describe :symbol_id2name, shared: true do
symbol.send(@method).encoding.should == Encoding::US_ASCII
end
+
+ ruby_version_is "3.4" do
+ it "warns about mutating returned string" do
+ -> { :bad!.send(@method).upcase! }.should complain(/warning: string returned by :bad!.to_s will be frozen in the future/)
+ end
+
+ it "does not warn about mutation when Warning[:deprecated] is false" do
+ deprecated = Warning[:deprecated]
+ Warning[:deprecated] = false
+ -> { :bad!.send(@method).upcase! }.should_not complain
+ ensure
+ Warning[:deprecated] = deprecated
+ end
+ end
end
diff --git a/spec/ruby/core/symbol/shared/slice.rb b/spec/ruby/core/symbol/shared/slice.rb
index 0df87e183d..d3d4aad617 100644
--- a/spec/ruby/core/symbol/shared/slice.rb
+++ b/spec/ruby/core/symbol/shared/slice.rb
@@ -7,7 +7,7 @@ describe :symbol_slice, shared: true do
end
it "returns nil if the index starts from the end and is greater than the length" do
- :symbol.send(@method, -10).should be_nil
+ :symbol.send(@method, -10).should be_nil
end
it "returns nil if the index is greater than the length" do
diff --git a/spec/ruby/core/symbol/to_proc_spec.rb b/spec/ruby/core/symbol/to_proc_spec.rb
index 54eccdba11..def5d6d344 100644
--- a/spec/ruby/core/symbol/to_proc_spec.rb
+++ b/spec/ruby/core/symbol/to_proc_spec.rb
@@ -27,31 +27,29 @@ describe "Symbol#to_proc" do
pr.parameters.should == [[:req], [:rest]]
end
- ruby_version_is "3.2" do
- it "only calls public methods" do
- body = proc do
- public def pub; @a << :pub end
- protected def pro; @a << :pro end
- private def pri; @a << :pri end
- attr_reader :a
- end
+ it "only calls public methods" do
+ body = proc do
+ public def pub; @a << :pub end
+ protected def pro; @a << :pro end
+ private def pri; @a << :pri end
+ attr_reader :a
+ end
- @a = []
- singleton_class.class_eval(&body)
- tap(&:pub)
- proc{tap(&:pro)}.should raise_error(NoMethodError, /protected method [`']pro' called/)
- proc{tap(&:pri)}.should raise_error(NoMethodError, /private method [`']pri' called/)
- @a.should == [:pub]
+ @a = []
+ singleton_class.class_eval(&body)
+ tap(&:pub)
+ proc{tap(&:pro)}.should raise_error(NoMethodError, /protected method [`']pro' called/)
+ proc{tap(&:pri)}.should raise_error(NoMethodError, /private method [`']pri' called/)
+ @a.should == [:pub]
- @a = []
- c = Class.new(&body)
- o = c.new
- o.instance_variable_set(:@a, [])
- o.tap(&:pub)
- proc{tap(&:pro)}.should raise_error(NoMethodError, /protected method [`']pro' called/)
- proc{o.tap(&:pri)}.should raise_error(NoMethodError, /private method [`']pri' called/)
- o.a.should == [:pub]
- end
+ @a = []
+ c = Class.new(&body)
+ o = c.new
+ o.instance_variable_set(:@a, [])
+ o.tap(&:pub)
+ proc{tap(&:pro)}.should raise_error(NoMethodError, /protected method [`']pro' called/)
+ proc{o.tap(&:pri)}.should raise_error(NoMethodError, /private method [`']pri' called/)
+ o.a.should == [:pub]
end
it "raises an ArgumentError when calling #call on the Proc without receiver" do
diff --git a/spec/ruby/core/thread/abort_on_exception_spec.rb b/spec/ruby/core/thread/abort_on_exception_spec.rb
index 34b648ca0f..49be84ea9f 100644
--- a/spec/ruby/core/thread/abort_on_exception_spec.rb
+++ b/spec/ruby/core/thread/abort_on_exception_spec.rb
@@ -72,7 +72,7 @@ describe "Thread.abort_on_exception" do
end
after do
- Thread.abort_on_exception = @abort_on_exception
+ Thread.abort_on_exception = @abort_on_exception
end
it "is false by default" do
diff --git a/spec/ruby/core/thread/backtrace/limit_spec.rb b/spec/ruby/core/thread/backtrace/limit_spec.rb
index 26a87a806c..b55ca67ea0 100644
--- a/spec/ruby/core/thread/backtrace/limit_spec.rb
+++ b/spec/ruby/core/thread/backtrace/limit_spec.rb
@@ -1,15 +1,13 @@
require_relative '../../../spec_helper'
-ruby_version_is "3.1" do
- describe "Thread::Backtrace.limit" do
- it "returns maximum backtrace length set by --backtrace-limit command-line option" do
- out = ruby_exe("print Thread::Backtrace.limit", options: "--backtrace-limit=2")
- out.should == "2"
- end
+describe "Thread::Backtrace.limit" do
+ it "returns maximum backtrace length set by --backtrace-limit command-line option" do
+ out = ruby_exe("print Thread::Backtrace.limit", options: "--backtrace-limit=2")
+ out.should == "2"
+ end
- it "returns -1 when --backtrace-limit command-line option is not set" do
- out = ruby_exe("print Thread::Backtrace.limit")
- out.should == "-1"
- end
+ it "returns -1 when --backtrace-limit command-line option is not set" do
+ out = ruby_exe("print Thread::Backtrace.limit")
+ out.should == "-1"
end
end
diff --git a/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb b/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb
index 6e381e4868..68a69049d9 100644
--- a/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb
+++ b/spec/ruby/core/thread/backtrace/location/absolute_path_spec.rb
@@ -27,20 +27,11 @@ describe 'Thread::Backtrace::Location#absolute_path' do
end
context "when used in eval with a given filename" do
- code = "caller_locations(0)[0].absolute_path"
+ it "returns nil with absolute_path" do
+ 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
+ eval(code, nil, "foo.rb").should == nil
+ eval(code, nil, "foo/bar.rb").should == nil
end
end
diff --git a/spec/ruby/core/thread/each_caller_location_spec.rb b/spec/ruby/core/thread/each_caller_location_spec.rb
index 29c271789b..aa7423675b 100644
--- a/spec/ruby/core/thread/each_caller_location_spec.rb
+++ b/spec/ruby/core/thread/each_caller_location_spec.rb
@@ -1,49 +1,47 @@
require_relative '../../spec_helper'
describe "Thread.each_caller_location" do
- ruby_version_is "3.2" do
- it "iterates through the current execution stack and matches caller_locations content and type" do
- ScratchPad.record []
- Thread.each_caller_location { |l| ScratchPad << l; }
+ it "iterates through the current execution stack and matches caller_locations content and type" do
+ ScratchPad.record []
+ Thread.each_caller_location { |l| ScratchPad << l; }
- ScratchPad.recorded.map(&:to_s).should == caller_locations.map(&:to_s)
- ScratchPad.recorded[0].should be_kind_of(Thread::Backtrace::Location)
- end
+ ScratchPad.recorded.map(&:to_s).should == caller_locations.map(&:to_s)
+ ScratchPad.recorded[0].should be_kind_of(Thread::Backtrace::Location)
+ end
- it "returns subset of 'Thread.to_enum(:each_caller_location)' locations" do
- ar = []
- ecl = Thread.each_caller_location { |x| ar << x }
+ it "returns subset of 'Thread.to_enum(:each_caller_location)' locations" do
+ ar = []
+ ecl = Thread.each_caller_location { |x| ar << x }
- (ar.map(&:to_s) - Thread.to_enum(:each_caller_location).to_a.map(&:to_s)).should.empty?
- end
+ (ar.map(&:to_s) - Thread.to_enum(:each_caller_location).to_a.map(&:to_s)).should.empty?
+ end
- it "stops the backtrace iteration if 'break' occurs" do
- i = 0
- ar = []
- ecl = Thread.each_caller_location do |x|
- ar << x
- i += 1
- break x if i == 2
- end
-
- ar.map(&:to_s).should == caller_locations(1, 2).map(&:to_s)
- ecl.should be_kind_of(Thread::Backtrace::Location)
+ it "stops the backtrace iteration if 'break' occurs" do
+ i = 0
+ ar = []
+ ecl = Thread.each_caller_location do |x|
+ ar << x
+ i += 1
+ break x if i == 2
end
- it "returns nil" do
- Thread.each_caller_location {}.should == nil
- end
+ ar.map(&:to_s).should == caller_locations(1, 2).map(&:to_s)
+ ecl.should be_kind_of(Thread::Backtrace::Location)
+ end
- it "raises LocalJumpError when called without a block" do
- -> {
- Thread.each_caller_location
- }.should raise_error(LocalJumpError, "no block given")
- end
+ it "returns nil" do
+ Thread.each_caller_location {}.should == nil
+ end
- it "doesn't accept keyword arguments" do
- -> {
- Thread.each_caller_location(12, foo: 10) {}
- }.should raise_error(ArgumentError);
- end
+ it "raises LocalJumpError when called without a block" do
+ -> {
+ Thread.each_caller_location
+ }.should raise_error(LocalJumpError, "no block given")
+ end
+
+ it "doesn't accept keyword arguments" do
+ -> {
+ Thread.each_caller_location(12, foo: 10) {}
+ }.should raise_error(ArgumentError);
end
end
diff --git a/spec/ruby/core/thread/element_reference_spec.rb b/spec/ruby/core/thread/element_reference_spec.rb
index 85280cb287..fde9d1f440 100644
--- a/spec/ruby/core/thread/element_reference_spec.rb
+++ b/spec/ruby/core/thread/element_reference_spec.rb
@@ -37,6 +37,17 @@ describe "Thread#[]" do
t2["value"].should == 2
end
+ it "converts a key that is neither String nor Symbol with #to_str" do
+ key = mock('value')
+ key.should_receive(:to_str).and_return('value')
+
+ th = Thread.new do
+ Thread.current[:value] = 1
+ end.join
+
+ th[key].should == 1
+ end
+
it "raises exceptions on the wrong type of keys" do
-> { Thread.current[nil] }.should raise_error(TypeError)
-> { Thread.current[5] }.should raise_error(TypeError)
diff --git a/spec/ruby/core/thread/element_set_spec.rb b/spec/ruby/core/thread/element_set_spec.rb
index c7498f7ac9..f205177304 100644
--- a/spec/ruby/core/thread/element_set_spec.rb
+++ b/spec/ruby/core/thread/element_set_spec.rb
@@ -12,10 +12,33 @@ describe "Thread#[]=" do
th.freeze
-> {
th[:foo] = "bar"
- }.should raise_error(FrozenError, /frozen/)
+ }.should raise_error(FrozenError, "can't modify frozen thread locals")
end.join
end
+ it "accepts Strings and Symbols" do
+ t1 = Thread.new do
+ Thread.current[:value] = 1
+ end.join
+ t2 = Thread.new do
+ Thread.current["value"] = 2
+ end.join
+
+ t1[:value].should == 1
+ t2[:value].should == 2
+ end
+
+ it "converts a key that is neither String nor Symbol with #to_str" do
+ key = mock('value')
+ key.should_receive(:to_str).and_return('value')
+
+ th = Thread.new do
+ Thread.current[key] = 1
+ end.join
+
+ th[:value].should == 1
+ end
+
it "raises exceptions on the wrong type of keys" do
-> { Thread.current[nil] = true }.should raise_error(TypeError)
-> { Thread.current[5] = true }.should raise_error(TypeError)
diff --git a/spec/ruby/core/thread/fixtures/classes.rb b/spec/ruby/core/thread/fixtures/classes.rb
index 23a090feb0..7c485660a8 100644
--- a/spec/ruby/core/thread/fixtures/classes.rb
+++ b/spec/ruby/core/thread/fixtures/classes.rb
@@ -6,6 +6,31 @@ module ThreadSpecs
end
end
+ class NewThreadToRaise
+ def self.raise(*args, **kwargs, &block)
+ thread = Thread.new do
+ Thread.current.report_on_exception = false
+
+ if block_given?
+ block.call do
+ sleep
+ end
+ else
+ sleep
+ end
+ end
+
+ Thread.pass until thread.stop?
+
+ thread.raise(*args, **kwargs)
+
+ thread.join
+ ensure
+ thread.kill if thread.alive?
+ Thread.pass while thread.alive? # Thread#kill may not terminate a thread immediately so it may be detected as a leaked one
+ end
+ end
+
class Status
attr_reader :thread, :inspect, :status, :to_s
def initialize(thread)
diff --git a/spec/ruby/core/thread/group_spec.rb b/spec/ruby/core/thread/group_spec.rb
index 59f5ac37c8..d0d4704b66 100644
--- a/spec/ruby/core/thread/group_spec.rb
+++ b/spec/ruby/core/thread/group_spec.rb
@@ -1,5 +1,16 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
+
describe "Thread#group" do
- it "needs to be reviewed for spec completeness"
+ it "returns the default thread group for the main thread" do
+ Thread.main.group.should == ThreadGroup::Default
+ end
+
+ it "returns the thread group explicitly set for this thread" do
+ thread = Thread.new { nil }
+ thread_group = ThreadGroup.new
+ thread_group.add(thread)
+ thread.group.should == thread_group
+ ensure
+ thread.join if thread
+ end
end
diff --git a/spec/ruby/core/thread/key_spec.rb b/spec/ruby/core/thread/key_spec.rb
index 6940cf5f28..339fa98f53 100644
--- a/spec/ruby/core/thread/key_spec.rb
+++ b/spec/ruby/core/thread/key_spec.rb
@@ -16,6 +16,13 @@ describe "Thread#key?" do
@th.key?(:stanley.to_s).should == false
end
+ it "converts a key that is neither String nor Symbol with #to_str" do
+ key = mock('key')
+ key.should_receive(:to_str).and_return('oliver')
+
+ @th.key?(key).should == true
+ end
+
it "raises exceptions on the wrong type of keys" do
-> { Thread.current.key? nil }.should raise_error(TypeError)
-> { Thread.current.key? 5 }.should raise_error(TypeError)
diff --git a/spec/ruby/core/thread/native_thread_id_spec.rb b/spec/ruby/core/thread/native_thread_id_spec.rb
index 17a08c8a15..374cc59279 100644
--- a/spec/ruby/core/thread/native_thread_id_spec.rb
+++ b/spec/ruby/core/thread/native_thread_id_spec.rb
@@ -1,37 +1,35 @@
require_relative '../../spec_helper'
-ruby_version_is "3.1" do
- platform_is :linux, :darwin, :windows, :freebsd do
- describe "Thread#native_thread_id" do
- it "returns an integer when the thread is alive" do
- Thread.current.native_thread_id.should be_kind_of(Integer)
- end
+platform_is :linux, :darwin, :windows, :freebsd do
+ describe "Thread#native_thread_id" do
+ it "returns an integer when the thread is alive" do
+ Thread.current.native_thread_id.should be_kind_of(Integer)
+ end
- it "returns nil when the thread is not running" do
- t = Thread.new {}
- t.join
- t.native_thread_id.should == nil
- end
+ it "returns nil when the thread is not running" do
+ t = Thread.new {}
+ t.join
+ t.native_thread_id.should == nil
+ end
- it "each thread has different native thread id" do
- t = Thread.new { sleep }
- Thread.pass until t.stop?
- main_thread_id = Thread.current.native_thread_id
- t_thread_id = t.native_thread_id
+ it "each thread has different native thread id" do
+ t = Thread.new { sleep }
+ Thread.pass until t.stop?
+ main_thread_id = Thread.current.native_thread_id
+ t_thread_id = t.native_thread_id
- if ruby_version_is "3.3"
- # native_thread_id can be nil on a M:N scheduler
- t_thread_id.should be_kind_of(Integer) if t_thread_id != nil
- else
- t_thread_id.should be_kind_of(Integer)
- end
+ if ruby_version_is "3.3"
+ # native_thread_id can be nil on a M:N scheduler
+ t_thread_id.should be_kind_of(Integer) if t_thread_id != nil
+ else
+ t_thread_id.should be_kind_of(Integer)
+ end
- main_thread_id.should_not == t_thread_id
+ main_thread_id.should_not == t_thread_id
- t.run
- t.join
- t.native_thread_id.should == nil
- end
+ t.run
+ t.join
+ t.native_thread_id.should == nil
end
end
end
diff --git a/spec/ruby/core/thread/raise_spec.rb b/spec/ruby/core/thread/raise_spec.rb
index 49323cf270..b473eabd42 100644
--- a/spec/ruby/core/thread/raise_spec.rb
+++ b/spec/ruby/core/thread/raise_spec.rb
@@ -3,6 +3,9 @@ require_relative 'fixtures/classes'
require_relative '../../shared/kernel/raise'
describe "Thread#raise" do
+ it_behaves_like :kernel_raise, :raise, ThreadSpecs::NewThreadToRaise
+ it_behaves_like :kernel_raise_across_contexts, :raise, ThreadSpecs::NewThreadToRaise
+
it "ignores dead threads and returns nil" do
t = Thread.new { :dead }
Thread.pass while t.alive?
diff --git a/spec/ruby/core/thread/thread_variable_get_spec.rb b/spec/ruby/core/thread/thread_variable_get_spec.rb
index 0ad19bfd88..1ea34cf2b3 100644
--- a/spec/ruby/core/thread/thread_variable_get_spec.rb
+++ b/spec/ruby/core/thread/thread_variable_get_spec.rb
@@ -14,12 +14,47 @@ describe "Thread#thread_variable_get" do
end
it "returns the value previously set by #thread_variable_set" do
- @t.thread_variable_set :a, 49
+ @t.thread_variable_set(:a, 49)
@t.thread_variable_get(:a).should == 49
end
it "returns a value private to self" do
- @t.thread_variable_set :thread_variable_get_spec, 82
+ @t.thread_variable_set(:thread_variable_get_spec, 82)
Thread.current.thread_variable_get(:thread_variable_get_spec).should be_nil
end
+
+ it "accepts String and Symbol keys interchangeably" do
+ @t.thread_variable_set("a", 49)
+ @t.thread_variable_get("a").should == 49
+ @t.thread_variable_get(:a).should == 49
+ end
+
+ it "converts a key that is neither String nor Symbol with #to_str" do
+ key = mock('key')
+ key.should_receive(:to_str).and_return('a')
+ @t.thread_variable_set(:a, 49)
+ @t.thread_variable_get(key).should == 49
+ end
+
+ it "does not raise FrozenError if the thread is frozen" do
+ @t.freeze
+ @t.thread_variable_get(:a).should be_nil
+ end
+
+ it "raises a TypeError if the key is neither Symbol nor String when thread variables are already set" do
+ @t.thread_variable_set(:a, 49)
+ -> { @t.thread_variable_get(123) }.should raise_error(TypeError, /123 is not a symbol/)
+ end
+
+ ruby_version_is '3.4' do
+ it "raises a TypeError if the key is neither Symbol nor String when no thread variables are set" do
+ -> { @t.thread_variable_get(123) }.should raise_error(TypeError, /123 is not a symbol/)
+ end
+
+ it "raises a TypeError if the key is neither Symbol nor String without calling #to_sym" do
+ key = mock('key')
+ key.should_not_receive(:to_sym)
+ -> { @t.thread_variable_get(key) }.should raise_error(TypeError, /#{Regexp.escape(key.inspect)} is not a symbol/)
+ end
+ end
end
diff --git a/spec/ruby/core/thread/thread_variable_set_spec.rb b/spec/ruby/core/thread/thread_variable_set_spec.rb
index 1338c306c7..eadee76afb 100644
--- a/spec/ruby/core/thread/thread_variable_set_spec.rb
+++ b/spec/ruby/core/thread/thread_variable_set_spec.rb
@@ -10,17 +10,53 @@ describe "Thread#thread_variable_set" do
end
it "returns the value set" do
- (@t.thread_variable_set :a, 2).should == 2
+ @t.thread_variable_set(:a, 2).should == 2
end
it "sets a value that will be returned by #thread_variable_get" do
- @t.thread_variable_set :a, 49
+ @t.thread_variable_set(:a, 49)
@t.thread_variable_get(:a).should == 49
end
it "sets a value private to self" do
- @t.thread_variable_set :thread_variable_get_spec, 82
+ @t.thread_variable_set(:thread_variable_get_spec, 82)
@t.thread_variable_get(:thread_variable_get_spec).should == 82
Thread.current.thread_variable_get(:thread_variable_get_spec).should be_nil
end
+
+ it "accepts String and Symbol keys interchangeably" do
+ @t.thread_variable_set('a', 49)
+ @t.thread_variable_get('a').should == 49
+
+ @t.thread_variable_set(:a, 50)
+ @t.thread_variable_get('a').should == 50
+ end
+
+ it "converts a key that is neither String nor Symbol with #to_str" do
+ key = mock('key')
+ key.should_receive(:to_str).and_return('a')
+ @t.thread_variable_set(key, 49)
+ @t.thread_variable_get(:a).should == 49
+ end
+
+ it "removes a key if the value is nil" do
+ @t.thread_variable_set(:a, 52)
+ @t.thread_variable_set(:a, nil)
+ @t.thread_variable?(:a).should be_false
+ end
+
+ it "raises a FrozenError if the thread is frozen" do
+ @t.freeze
+ -> { @t.thread_variable_set(:a, 1) }.should raise_error(FrozenError, "can't modify frozen thread locals")
+ end
+
+ it "raises a TypeError if the key is neither Symbol nor String, nor responds to #to_str" do
+ -> { @t.thread_variable_set(123, 1) }.should raise_error(TypeError, /123 is not a symbol/)
+ end
+
+ it "does not try to convert the key with #to_sym" do
+ key = mock('key')
+ key.should_not_receive(:to_sym)
+ -> { @t.thread_variable_set(key, 42) }.should raise_error(TypeError, /#{Regexp.quote(key.inspect)} is not a symbol/)
+ end
end
diff --git a/spec/ruby/core/thread/thread_variable_spec.rb b/spec/ruby/core/thread/thread_variable_spec.rb
index 6bd1950c04..1b021e9404 100644
--- a/spec/ruby/core/thread/thread_variable_spec.rb
+++ b/spec/ruby/core/thread/thread_variable_spec.rb
@@ -10,12 +10,51 @@ describe "Thread#thread_variable?" do
end
it "returns false if the thread variables do not contain 'key'" do
- @t.thread_variable_set :a, 2
+ @t.thread_variable_set(:a, 2)
@t.thread_variable?(:b).should be_false
end
it "returns true if the thread variables contain 'key'" do
- @t.thread_variable_set :a, 2
+ @t.thread_variable_set(:a, 2)
@t.thread_variable?(:a).should be_true
end
+
+ it "accepts String and Symbol keys interchangeably" do
+ @t.thread_variable?('a').should be_false
+ @t.thread_variable?(:a).should be_false
+
+ @t.thread_variable_set(:a, 49)
+
+ @t.thread_variable?('a').should be_true
+ @t.thread_variable?(:a).should be_true
+ end
+
+ it "converts a key that is neither String nor Symbol with #to_str" do
+ key = mock('key')
+ key.should_receive(:to_str).and_return('a')
+ @t.thread_variable_set(:a, 49)
+ @t.thread_variable?(key).should be_true
+ end
+
+ it "does not raise FrozenError if the thread is frozen" do
+ @t.freeze
+ @t.thread_variable?(:a).should be_false
+ end
+
+ it "raises a TypeError if the key is neither Symbol nor String when thread variables are already set" do
+ @t.thread_variable_set(:a, 49)
+ -> { @t.thread_variable?(123) }.should raise_error(TypeError, /123 is not a symbol/)
+ end
+
+ ruby_version_is '3.4' do
+ it "raises a TypeError if the key is neither Symbol nor String when no thread variables are set" do
+ -> { @t.thread_variable?(123) }.should raise_error(TypeError, /123 is not a symbol/)
+ end
+
+ it "raises a TypeError if the key is neither Symbol nor String without calling #to_sym" do
+ key = mock('key')
+ key.should_not_receive(:to_sym)
+ -> { @t.thread_variable?(key) }.should raise_error(TypeError, /#{Regexp.escape(key.inspect)} is not a symbol/)
+ end
+ end
end
diff --git a/spec/ruby/core/thread/thread_variables_spec.rb b/spec/ruby/core/thread/thread_variables_spec.rb
index 1bd68b17f1..51ceef3376 100644
--- a/spec/ruby/core/thread/thread_variables_spec.rb
+++ b/spec/ruby/core/thread/thread_variables_spec.rb
@@ -10,15 +10,15 @@ describe "Thread#thread_variables" do
end
it "returns the keys of all the values set" do
- @t.thread_variable_set :a, 2
- @t.thread_variable_set :b, 4
- @t.thread_variable_set :c, 6
+ @t.thread_variable_set(:a, 2)
+ @t.thread_variable_set(:b, 4)
+ @t.thread_variable_set(:c, 6)
@t.thread_variables.sort.should == [:a, :b, :c]
end
- it "sets a value private to self" do
- @t.thread_variable_set :a, 82
- @t.thread_variable_set :b, 82
+ it "returns the keys private to self" do
+ @t.thread_variable_set(:a, 82)
+ @t.thread_variable_set(:b, 82)
Thread.current.thread_variables.should_not include(:a, :b)
end
@@ -26,4 +26,14 @@ describe "Thread#thread_variables" do
Thread.current.thread_variables.should == []
@t.thread_variables.should == []
end
+
+ it "returns keys as Symbols" do
+ key = mock('key')
+ key.should_receive(:to_str).and_return('a')
+
+ @t.thread_variable_set(key, 49)
+ @t.thread_variable_set('b', 50)
+ @t.thread_variable_set(:c, 51)
+ @t.thread_variables.sort.should == [:a, :b, :c]
+ end
end
diff --git a/spec/ruby/core/time/_dump_spec.rb b/spec/ruby/core/time/_dump_spec.rb
index 4dc1c43cd2..852f9a07ab 100644
--- a/spec/ruby/core/time/_dump_spec.rb
+++ b/spec/ruby/core/time/_dump_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
describe "Time#_dump" do
diff --git a/spec/ruby/core/time/_load_spec.rb b/spec/ruby/core/time/_load_spec.rb
index bb0d705bbc..30899de262 100644
--- a/spec/ruby/core/time/_load_spec.rb
+++ b/spec/ruby/core/time/_load_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
describe "Time._load" do
diff --git a/spec/ruby/core/time/at_spec.rb b/spec/ruby/core/time/at_spec.rb
index 48fb3c6f52..97906b8c8c 100644
--- a/spec/ruby/core/time/at_spec.rb
+++ b/spec/ruby/core/time/at_spec.rb
@@ -102,8 +102,8 @@ describe "Time.at" do
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)
+ def o.to_r; Rational(5, 2) end
+ -> { Time.at(o) }.should raise_error(TypeError, "can't convert MockObject into an exact number")
end
end
end
@@ -228,6 +228,12 @@ describe "Time.at" do
time.utc_offset.should == -9*60*60
time.zone.should == nil
time.to_i.should == @epoch_time
+
+ time = Time.at(@epoch_time, in: "-09:00:01")
+
+ time.utc_offset.should == -(9*60*60 + 1)
+ time.zone.should == nil
+ time.to_i.should == @epoch_time
end
it "could be UTC offset as a number of seconds" do
@@ -280,5 +286,31 @@ describe "Time.at" do
-> { Time.at(@epoch_time, in: "+09:99") }.should raise_error(ArgumentError)
-> { Time.at(@epoch_time, in: "ABC") }.should raise_error(ArgumentError)
end
+
+ it "raises ArgumentError if hours greater than 23" do # TODO
+ -> { Time.at(@epoch_time, in: "+24:00") }.should raise_error(ArgumentError, "utc_offset out of range")
+ -> { Time.at(@epoch_time, in: "+2400") }.should raise_error(ArgumentError, "utc_offset out of range")
+
+ -> { Time.at(@epoch_time, in: "+99:00") }.should raise_error(ArgumentError, "utc_offset out of range")
+ -> { Time.at(@epoch_time, in: "+9900") }.should raise_error(ArgumentError, "utc_offset out of range")
+ end
+
+ it "raises ArgumentError if minutes greater than 59" do # TODO
+ -> { Time.at(@epoch_time, in: "+00:60") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:60')
+ -> { Time.at(@epoch_time, in: "+0060") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +0060')
+
+ -> { Time.at(@epoch_time, in: "+00:99") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:99')
+ -> { Time.at(@epoch_time, in: "+0099") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +0099')
+ end
+
+ ruby_bug '#20797', ''...'3.4' do
+ it "raises ArgumentError if seconds greater than 59" do
+ -> { Time.at(@epoch_time, in: "+00:00:60") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:00:60')
+ -> { Time.at(@epoch_time, in: "+000060") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +000060')
+
+ -> { Time.at(@epoch_time, in: "+00:00:99") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:00:99')
+ -> { Time.at(@epoch_time, in: "+000099") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +000099')
+ end
+ end
end
end
diff --git a/spec/ruby/core/time/comparison_spec.rb b/spec/ruby/core/time/comparison_spec.rb
index 5b53c9fb50..866fbea72e 100644
--- a/spec/ruby/core/time/comparison_spec.rb
+++ b/spec/ruby/core/time/comparison_spec.rb
@@ -55,6 +55,32 @@ describe "Time#<=>" do
}.should_not complain
end
+ context "given different timezones" do
+ it "returns 0 if time is the same as other" do
+ # three timezones, all at the same timestamp
+ time_utc = Time.new(2000, 1, 1, 0, 0, 0, 0)
+ time_cet = Time.new(2000, 1, 1, 1, 0, 0, '+01:00')
+ time_brt = Time.new(1999, 12, 31, 21, 0, 0, '-03:00')
+ (time_utc <=> time_cet).should == 0
+ (time_utc <=> time_brt).should == 0
+ (time_cet <=> time_brt).should == 0
+ end
+
+ it "returns -1 if the first argument is before the second argument" do
+ # time_brt is later, even though the date is earlier
+ time_utc = Time.new(2000, 1, 1, 0, 0, 0, 0)
+ time_brt = Time.new(1999, 12, 31, 23, 0, 0, '-03:00')
+ (time_utc <=> time_brt).should == -1
+ end
+
+ it "returns 1 if the first argument is before the second argument" do
+ # time_brt is later, even though the date is earlier
+ time_utc = Time.new(2000, 1, 1, 0, 0, 0, 0)
+ time_brt = Time.new(1999, 12, 31, 23, 0, 0, '-03:00')
+ (time_brt <=> time_utc).should == 1
+ end
+ end
+
describe "given a non-Time argument" do
it "returns nil if argument <=> self returns nil" do
t = Time.now
diff --git a/spec/ruby/core/time/deconstruct_keys_spec.rb b/spec/ruby/core/time/deconstruct_keys_spec.rb
index ee17e7dbd4..b5cfdaa93f 100644
--- a/spec/ruby/core/time/deconstruct_keys_spec.rb
+++ b/spec/ruby/core/time/deconstruct_keys_spec.rb
@@ -1,45 +1,43 @@
require_relative '../../spec_helper'
-ruby_version_is "3.2" do
- describe "Time#deconstruct_keys" do
- it "returns whole hash for nil as an argument" do
- d = Time.utc(2022, 10, 5, 13, 30)
- res = { year: 2022, month: 10, day: 5, yday: 278, wday: 3, hour: 13,
- min: 30, sec: 0, subsec: 0, dst: false, zone: "UTC" }
- d.deconstruct_keys(nil).should == res
- end
-
- it "returns only specified keys" do
- d = Time.utc(2022, 10, 5, 13, 39)
- d.deconstruct_keys([:zone, :subsec]).should == { zone: "UTC", subsec: 0 }
- end
-
- it "requires one argument" do
- -> {
- Time.new(2022, 10, 5, 13, 30).deconstruct_keys
- }.should raise_error(ArgumentError)
- end
-
- it "it raises error when argument is neither nil nor array" do
- d = Time.new(2022, 10, 5, 13, 30)
-
- -> { d.deconstruct_keys(1) }.should raise_error(TypeError, "wrong argument type Integer (expected Array or nil)")
- -> { d.deconstruct_keys("asd") }.should raise_error(TypeError, "wrong argument type String (expected Array or nil)")
- -> { d.deconstruct_keys(:x) }.should raise_error(TypeError, "wrong argument type Symbol (expected Array or nil)")
- -> { d.deconstruct_keys({}) }.should raise_error(TypeError, "wrong argument type Hash (expected Array or nil)")
- end
-
- it "returns {} when passed []" do
- Time.new(2022, 10, 5, 13, 30).deconstruct_keys([]).should == {}
- end
-
- it "ignores non-Symbol keys" do
- Time.new(2022, 10, 5, 13, 30).deconstruct_keys(['year', []]).should == {}
- end
-
- it "ignores not existing Symbol keys and processes keys after the first non-existing one" do
- d = Time.utc(2022, 10, 5, 13, 30)
- d.deconstruct_keys([:year, :a, :month, :b, :day]).should == { year: 2022, month: 10, day: 5 }
- end
+describe "Time#deconstruct_keys" do
+ it "returns whole hash for nil as an argument" do
+ d = Time.utc(2022, 10, 5, 13, 30)
+ res = { year: 2022, month: 10, day: 5, yday: 278, wday: 3, hour: 13,
+ min: 30, sec: 0, subsec: 0, dst: false, zone: "UTC" }
+ d.deconstruct_keys(nil).should == res
+ end
+
+ it "returns only specified keys" do
+ d = Time.utc(2022, 10, 5, 13, 39)
+ d.deconstruct_keys([:zone, :subsec]).should == { zone: "UTC", subsec: 0 }
+ end
+
+ it "requires one argument" do
+ -> {
+ Time.new(2022, 10, 5, 13, 30).deconstruct_keys
+ }.should raise_error(ArgumentError)
+ end
+
+ it "it raises error when argument is neither nil nor array" do
+ d = Time.new(2022, 10, 5, 13, 30)
+
+ -> { d.deconstruct_keys(1) }.should raise_error(TypeError, "wrong argument type Integer (expected Array or nil)")
+ -> { d.deconstruct_keys("asd") }.should raise_error(TypeError, "wrong argument type String (expected Array or nil)")
+ -> { d.deconstruct_keys(:x) }.should raise_error(TypeError, "wrong argument type Symbol (expected Array or nil)")
+ -> { d.deconstruct_keys({}) }.should raise_error(TypeError, "wrong argument type Hash (expected Array or nil)")
+ end
+
+ it "returns {} when passed []" do
+ Time.new(2022, 10, 5, 13, 30).deconstruct_keys([]).should == {}
+ end
+
+ it "ignores non-Symbol keys" do
+ Time.new(2022, 10, 5, 13, 30).deconstruct_keys(['year', []]).should == {}
+ end
+
+ it "ignores not existing Symbol keys and processes keys after the first non-existing one" do
+ d = Time.utc(2022, 10, 5, 13, 30)
+ d.deconstruct_keys([:year, :a, :month, :b, :day]).should == { year: 2022, month: 10, day: 5 }
end
end
diff --git a/spec/ruby/core/time/getlocal_spec.rb b/spec/ruby/core/time/getlocal_spec.rb
index 926a6dbf45..398596f400 100644
--- a/spec/ruby/core/time/getlocal_spec.rb
+++ b/spec/ruby/core/time/getlocal_spec.rb
@@ -14,6 +14,7 @@ describe "Time#getlocal" do
t = Time.gm(2007, 1, 9, 12, 0, 0).getlocal(3630)
t.should == Time.new(2007, 1, 9, 13, 0, 30, 3630)
t.utc_offset.should == 3630
+ t.zone.should be_nil
end
platform_is_not :windows do
@@ -59,12 +60,24 @@ describe "Time#getlocal" do
t.utc_offset.should == 3600
end
+ it "returns a Time with a UTC offset specified as +HH:MM:SS" do
+ t = Time.gm(2007, 1, 9, 12, 0, 0).getlocal("+01:00:01")
+ t.should == Time.new(2007, 1, 9, 13, 0, 1, 3601)
+ t.utc_offset.should == 3601
+ end
+
it "returns a Time with a UTC offset specified as -HH:MM" do
t = Time.gm(2007, 1, 9, 12, 0, 0).getlocal("-01:00")
t.should == Time.new(2007, 1, 9, 11, 0, 0, -3600)
t.utc_offset.should == -3600
end
+ it "returns a Time with a UTC offset specified as -HH:MM:SS" do
+ t = Time.gm(2007, 1, 9, 12, 0, 0).getlocal("-01:00:01")
+ t.should == Time.new(2007, 1, 9, 10, 59, 59, -3601)
+ t.utc_offset.should == -3601
+ end
+
describe "with an argument that responds to #to_str" do
it "coerces using #to_str" do
o = mock('string')
@@ -97,6 +110,32 @@ describe "Time#getlocal" do
-> { t.getlocal(86400) }.should raise_error(ArgumentError)
end
+ it "raises ArgumentError if String argument and hours greater than 23" do
+ -> { Time.now.getlocal("+24:00") }.should raise_error(ArgumentError, "utc_offset out of range")
+ -> { Time.now.getlocal("+2400") }.should raise_error(ArgumentError, "utc_offset out of range")
+
+ -> { Time.now.getlocal("+99:00") }.should raise_error(ArgumentError, "utc_offset out of range")
+ -> { Time.now.getlocal("+9900") }.should raise_error(ArgumentError, "utc_offset out of range")
+ end
+
+ it "raises ArgumentError if String argument and minutes greater than 59" do
+ -> { Time.now.getlocal("+00:60") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:60')
+ -> { Time.now.getlocal("+0060") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +0060')
+
+ -> { Time.now.getlocal("+00:99") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:99')
+ -> { Time.now.getlocal("+0099") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +0099')
+ end
+
+ ruby_bug '#20797', ''...'3.4' do
+ it "raises ArgumentError if String argument and seconds greater than 59" do
+ -> { Time.now.getlocal("+00:00:60") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:00:60')
+ -> { Time.now.getlocal("+000060") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +000060')
+
+ -> { Time.now.getlocal("+00:00:99") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:00:99')
+ -> { Time.now.getlocal("+000099") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +000099')
+ end
+ end
+
describe "with a timezone argument" do
it "returns a Time in the timezone" do
zone = TimeSpecs::Timezone.new(offset: (5*3600+30*60))
diff --git a/spec/ruby/core/time/iso8601_spec.rb b/spec/ruby/core/time/iso8601_spec.rb
new file mode 100644
index 0000000000..ad60c3bb32
--- /dev/null
+++ b/spec/ruby/core/time/iso8601_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/xmlschema'
+
+describe "Time#iso8601" do
+ it_behaves_like :time_xmlschema, :iso8601
+end
diff --git a/spec/ruby/core/time/localtime_spec.rb b/spec/ruby/core/time/localtime_spec.rb
index 609b6532a1..71c0dfebde 100644
--- a/spec/ruby/core/time/localtime_spec.rb
+++ b/spec/ruby/core/time/localtime_spec.rb
@@ -72,6 +72,13 @@ describe "Time#localtime" do
t.utc_offset.should == 3600
end
+ it "returns a Time with a UTC offset specified as +HH:MM:SS" do
+ t = Time.gm(2007, 1, 9, 12, 0, 0)
+ t.localtime("+01:00:01")
+ t.should == Time.new(2007, 1, 9, 13, 0, 1, 3601)
+ t.utc_offset.should == 3601
+ end
+
it "returns a Time with a UTC offset specified as -HH:MM" do
t = Time.gm(2007, 1, 9, 12, 0, 0)
t.localtime("-01:00")
@@ -79,6 +86,13 @@ describe "Time#localtime" do
t.utc_offset.should == -3600
end
+ it "returns a Time with a UTC offset specified as -HH:MM:SS" do
+ t = Time.gm(2007, 1, 9, 12, 0, 0)
+ t.localtime("-01:00:01")
+ t.should == Time.new(2007, 1, 9, 10, 59, 59, -3601)
+ t.utc_offset.should == -3601
+ end
+
it "returns a Time with a UTC offset specified as UTC" do
t = Time.new(2007, 1, 9, 12, 0, 0, 3600)
t.localtime("UTC")
@@ -91,6 +105,32 @@ describe "Time#localtime" do
t.utc_offset.should == 3600 * 2
end
+ it "raises ArgumentError if String argument and hours greater than 23" do
+ -> { Time.now.localtime("+24:00") }.should raise_error(ArgumentError, "utc_offset out of range")
+ -> { Time.now.localtime("+2400") }.should raise_error(ArgumentError, "utc_offset out of range")
+
+ -> { Time.now.localtime("+99:00") }.should raise_error(ArgumentError, "utc_offset out of range")
+ -> { Time.now.localtime("+9900") }.should raise_error(ArgumentError, "utc_offset out of range")
+ end
+
+ it "raises ArgumentError if String argument and minutes greater than 59" do
+ -> { Time.now.localtime("+00:60") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:60')
+ -> { Time.now.localtime("+0060") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +0060')
+
+ -> { Time.now.localtime("+00:99") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:99')
+ -> { Time.now.localtime("+0099") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +0099')
+ end
+
+ ruby_bug '#20797', ''...'3.4' do
+ it "raises ArgumentError if String argument and seconds greater than 59" do
+ -> { Time.now.localtime("+00:00:60") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:00:60')
+ -> { Time.now.localtime("+000060") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +000060')
+
+ -> { Time.now.localtime("+00:00:99") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:00:99')
+ -> { Time.now.localtime("+000099") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +000099')
+ end
+ end
+
platform_is_not :windows do
it "changes the timezone according to the set one" do
t = Time.new(2005, 2, 27, 22, 50, 0, -3600)
@@ -128,6 +168,17 @@ describe "Time#localtime" do
end
end
+ describe "with an argument that responds to #utc_to_local" do
+ it "coerces using #utc_to_local" do
+ o = mock('string')
+ o.should_receive(:utc_to_local).and_return(Time.new(2007, 1, 9, 13, 0, 0, 3600))
+ t = Time.gm(2007, 1, 9, 12, 0, 0)
+ t.localtime(o)
+ t.should == Time.new(2007, 1, 9, 13, 0, 0, 3600)
+ t.utc_offset.should == 3600
+ end
+ end
+
it "raises ArgumentError if the String argument is not of the form (+|-)HH:MM" do
t = Time.now
-> { t.localtime("3600") }.should raise_error(ArgumentError)
diff --git a/spec/ruby/core/time/minus_spec.rb b/spec/ruby/core/time/minus_spec.rb
index 8449778465..9182d99652 100644
--- a/spec/ruby/core/time/minus_spec.rb
+++ b/spec/ruby/core/time/minus_spec.rb
@@ -109,7 +109,7 @@ describe "Time#-" do
it "does not return a subclass instance" do
c = Class.new(Time)
- x = c.now + 1
+ x = c.now - 1
x.should be_an_instance_of(Time)
end
diff --git a/spec/ruby/core/time/new_spec.rb b/spec/ruby/core/time/new_spec.rb
index d686355270..dc3ccbdc00 100644
--- a/spec/ruby/core/time/new_spec.rb
+++ b/spec/ruby/core/time/new_spec.rb
@@ -58,30 +58,28 @@ describe "Time.new with a utc_offset argument" do
Time.new(2000, 1, 1, 0, 0, 0, "-04:10:43").utc_offset.should == -15043
end
- ruby_bug '#13669', ''...'3.1' do
- it "returns a Time with a UTC offset specified as +HH" do
- Time.new(2000, 1, 1, 0, 0, 0, "+05").utc_offset.should == 3600 * 5
- end
+ it "returns a Time with a UTC offset specified as +HH" do
+ Time.new(2000, 1, 1, 0, 0, 0, "+05").utc_offset.should == 3600 * 5
+ end
- it "returns a Time with a UTC offset specified as -HH" do
- Time.new(2000, 1, 1, 0, 0, 0, "-05").utc_offset.should == -3600 * 5
- end
+ it "returns a Time with a UTC offset specified as -HH" do
+ Time.new(2000, 1, 1, 0, 0, 0, "-05").utc_offset.should == -3600 * 5
+ end
- it "returns a Time with a UTC offset specified as +HHMM" do
- Time.new(2000, 1, 1, 0, 0, 0, "+0530").utc_offset.should == 19800
- end
+ it "returns a Time with a UTC offset specified as +HHMM" do
+ Time.new(2000, 1, 1, 0, 0, 0, "+0530").utc_offset.should == 19800
+ end
- it "returns a Time with a UTC offset specified as -HHMM" do
- Time.new(2000, 1, 1, 0, 0, 0, "-0530").utc_offset.should == -19800
- end
+ it "returns a Time with a UTC offset specified as -HHMM" do
+ Time.new(2000, 1, 1, 0, 0, 0, "-0530").utc_offset.should == -19800
+ end
- it "returns a Time with a UTC offset specified as +HHMMSS" do
- Time.new(2000, 1, 1, 0, 0, 0, "+053037").utc_offset.should == 19837
- end
+ it "returns a Time with a UTC offset specified as +HHMMSS" do
+ Time.new(2000, 1, 1, 0, 0, 0, "+053037").utc_offset.should == 19837
+ end
- it "returns a Time with a UTC offset specified as -HHMMSS" do
- Time.new(2000, 1, 1, 0, 0, 0, "-053037").utc_offset.should == -19837
- end
+ it "returns a Time with a UTC offset specified as -HHMMSS" do
+ Time.new(2000, 1, 1, 0, 0, 0, "-053037").utc_offset.should == -19837
end
describe "with an argument that responds to #to_str" do
@@ -129,18 +127,9 @@ describe "Time.new with a utc_offset argument" do
end
end
- ruby_version_is ""..."3.1" do
- it "raises ArgumentError if the string argument is J" do
- message = '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset'
- -> { Time.new(2000, 1, 1, 0, 0, 0, "J") }.should raise_error(ArgumentError, message)
- end
- end
-
- ruby_version_is "3.1" do
- it "raises ArgumentError if the string argument is J" do
- message = '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: J'
- -> { Time.new(2000, 1, 1, 0, 0, 0, "J") }.should raise_error(ArgumentError, message)
- end
+ it "raises ArgumentError if the string argument is J" do
+ message = '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: J'
+ -> { Time.new(2000, 1, 1, 0, 0, 0, "J") }.should raise_error(ArgumentError, message)
end
it "returns a local Time if the argument is nil" do
@@ -193,6 +182,7 @@ describe "Time.new with a utc_offset argument" do
end
end
+# The method #local_to_utc is tested only here because Time.new is the only method that calls #local_to_utc.
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))
@@ -213,9 +203,7 @@ describe "Time.new with a timezone argument" do
time
end
- -> {
- Time.new(2000, 1, 1, 12, 0, 0, zone).should be_kind_of(Time)
- }.should_not raise_error
+ Time.new(2000, 1, 1, 12, 0, 0, zone).should be_kind_of(Time)
end
it "raises TypeError if timezone does not implement #local_to_utc method" do
@@ -226,7 +214,7 @@ describe "Time.new with a timezone argument" do
-> {
Time.new(2000, 1, 1, 12, 0, 0, zone)
- }.should raise_error(TypeError, /can't convert \w+ into an exact number/)
+ }.should raise_error(TypeError, /can't convert Object into an exact number/)
end
it "does not raise exception if timezone does not implement #utc_to_local method" do
@@ -235,51 +223,48 @@ describe "Time.new with a timezone argument" do
time
end
- -> {
- Time.new(2000, 1, 1, 12, 0, 0, zone).should be_kind_of(Time)
- }.should_not raise_error
+ Time.new(2000, 1, 1, 12, 0, 0, zone).should be_kind_of(Time)
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
+ # or respond to #to_int method. 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)
+ time = Time.utc(t.year, t.mon, t.day, t.hour, t.min, t.sec)
+ time - 60 * 60 # - 1 hour
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
+ 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
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)
+ time = Time.utc(t.year, t.mon, t.day, t.hour, t.min, t.sec)
+ time -= 60 * 60 # - 1 hour
+ Class.new(Time).utc(time.year, time.mon, time.day, time.hour, 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
+ 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
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)
+ obj = Object.new
+ obj.singleton_class.define_method(:to_i) { time.to_i - 60*60 }
+ obj
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
+ 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
end
- it "could have any #zone and #utc_offset because they are ignored" do
+ it "could have any #zone and #utc_offset because they are ignored if it isn't an instance of Time" 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)
@@ -293,7 +278,15 @@ describe "Time.new with a timezone argument" do
Time.new(2000, 1, 1, 12, 0, 0, zone).utc_offset.should == 0
end
- it "leads to raising Argument error if difference between argument and result is too large" do
+ it "cannot have arbitrary #utc_offset if it is an instance of Time" do
+ zone = Object.new
+ def zone.local_to_utc(t)
+ Time.new(t.year, t.mon, t.mday, t.hour, t.min, t.sec, 9*60*60)
+ end
+ Time.new(2000, 1, 1, 12, 0, 0, zone).utc_offset.should == 9*60*60
+ end
+
+ it "raises ArgumentError 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)
@@ -318,12 +311,9 @@ describe "Time.new with a timezone argument" do
end
it "implements subset of Time methods" do
+ # List only methods that are explicitly documented.
[
- :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,
+ :year, :mon, :mday, :hour, :min, :sec, :to_i, :isdst
].each do |name|
@obj.respond_to?(name).should == true
end
@@ -403,243 +393,360 @@ describe "Time.new with a timezone argument" do
end
end
- ruby_version_is '3.1' do # https://bugs.ruby-lang.org/issues/17485
- describe ":in keyword argument" do
- it "could be UTC offset as a String in '+HH:MM or '-HH:MM' format" do
- time = Time.new(2000, 1, 1, 12, 0, 0, in: "+05:00")
+ describe ":in keyword argument" do
+ it "could be UTC offset as a String in '+HH:MM or '-HH:MM' format" do
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: "+05:00")
- time.utc_offset.should == 5*60*60
- time.zone.should == nil
+ time.utc_offset.should == 5*60*60
+ time.zone.should == nil
- time = Time.new(2000, 1, 1, 12, 0, 0, in: "-09:00")
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: "-09:00")
- time.utc_offset.should == -9*60*60
- time.zone.should == nil
- end
+ time.utc_offset.should == -9*60*60
+ time.zone.should == nil
- it "could be UTC offset as a number of seconds" do
- time = Time.new(2000, 1, 1, 12, 0, 0, in: 5*60*60)
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: "-09:00:01")
- time.utc_offset.should == 5*60*60
- time.zone.should == nil
+ time.utc_offset.should == -(9*60*60 + 1)
+ time.zone.should == nil
+ end
- time = Time.new(2000, 1, 1, 12, 0, 0, in: -9*60*60)
+ it "could be UTC offset as a number of seconds" do
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: 5*60*60)
- time.utc_offset.should == -9*60*60
- time.zone.should == nil
- end
+ time.utc_offset.should == 5*60*60
+ time.zone.should == nil
- it "returns a Time with UTC offset specified as a single letter military timezone" do
- Time.new(2000, 1, 1, 0, 0, 0, in: "W").utc_offset.should == 3600 * -10
- end
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: -9*60*60)
- it "could be a timezone object" do
- zone = TimeSpecs::TimezoneWithName.new(name: "Asia/Colombo")
- time = Time.new(2000, 1, 1, 12, 0, 0, in: zone)
+ time.utc_offset.should == -9*60*60
+ time.zone.should == nil
+ end
- time.utc_offset.should == 5*3600+30*60
- time.zone.should == zone
+ it "returns a Time with UTC offset specified as a single letter military timezone" do
+ Time.new(2000, 1, 1, 0, 0, 0, in: "W").utc_offset.should == 3600 * -10
+ end
- zone = TimeSpecs::TimezoneWithName.new(name: "PST")
- time = Time.new(2000, 1, 1, 12, 0, 0, in: zone)
+ it "could be a timezone object" do
+ zone = TimeSpecs::TimezoneWithName.new(name: "Asia/Colombo")
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: zone)
- time.utc_offset.should == -9*60*60
- time.zone.should == zone
- end
+ time.utc_offset.should == 5*3600+30*60
+ time.zone.should == zone
- it "allows omitting minor arguments" do
- Time.new(2000, 1, 1, 12, 1, 1, in: "+05:00").should == Time.new(2000, 1, 1, 12, 1, 1, "+05:00")
- Time.new(2000, 1, 1, 12, 1, in: "+05:00").should == Time.new(2000, 1, 1, 12, 1, 0, "+05:00")
- Time.new(2000, 1, 1, 12, in: "+05:00").should == Time.new(2000, 1, 1, 12, 0, 0, "+05:00")
- Time.new(2000, 1, 1, in: "+05:00").should == Time.new(2000, 1, 1, 0, 0, 0, "+05:00")
- Time.new(2000, 1, in: "+05:00").should == Time.new(2000, 1, 1, 0, 0, 0, "+05:00")
- Time.new(2000, in: "+05:00").should == Time.new(2000, 1, 1, 0, 0, 0, "+05:00")
- Time.new(in: "+05:00").should be_close(Time.now.getlocal("+05:00"), TIME_TOLERANCE)
- end
+ zone = TimeSpecs::TimezoneWithName.new(name: "PST")
+ time = Time.new(2000, 1, 1, 12, 0, 0, in: zone)
- it "converts to a provided timezone if all the positional arguments are omitted" do
- Time.new(in: "+05:00").utc_offset.should == 5*3600
- end
+ time.utc_offset.should == -9*60*60
+ time.zone.should == zone
+ end
- it "raises ArgumentError if format is invalid" do
- -> { Time.new(2000, 1, 1, 12, 0, 0, in: "+09:99") }.should raise_error(ArgumentError)
- -> { Time.new(2000, 1, 1, 12, 0, 0, in: "ABC") }.should raise_error(ArgumentError)
- end
+ it "allows omitting minor arguments" do
+ Time.new(2000, 1, 1, 12, 1, 1, in: "+05:00").should == Time.new(2000, 1, 1, 12, 1, 1, "+05:00")
+ Time.new(2000, 1, 1, 12, 1, in: "+05:00").should == Time.new(2000, 1, 1, 12, 1, 0, "+05:00")
+ Time.new(2000, 1, 1, 12, in: "+05:00").should == Time.new(2000, 1, 1, 12, 0, 0, "+05:00")
+ Time.new(2000, 1, 1, in: "+05:00").should == Time.new(2000, 1, 1, 0, 0, 0, "+05:00")
+ Time.new(2000, 1, in: "+05:00").should == Time.new(2000, 1, 1, 0, 0, 0, "+05:00")
+ Time.new(2000, in: "+05:00").should == Time.new(2000, 1, 1, 0, 0, 0, "+05:00")
+ Time.new(in: "+05:00").should be_close(Time.now.getlocal("+05:00"), TIME_TOLERANCE)
+ end
- it "raises ArgumentError if two offset arguments are given" do
- -> {
- Time.new(2000, 1, 1, 12, 0, 0, "+05:00", in: "+05:00")
- }.should raise_error(ArgumentError, "timezone argument given as positional and keyword arguments")
- end
+ it "converts to a provided timezone if all the positional arguments are omitted" do
+ Time.new(in: "+05:00").utc_offset.should == 5*3600
+ end
+
+ it "raises ArgumentError if format is invalid" do
+ -> { Time.new(2000, 1, 1, 12, 0, 0, in: "+09:99") }.should raise_error(ArgumentError)
+ -> { Time.new(2000, 1, 1, 12, 0, 0, in: "ABC") }.should raise_error(ArgumentError)
+ end
+
+ it "raises ArgumentError if two offset arguments are given" do
+ -> {
+ Time.new(2000, 1, 1, 12, 0, 0, "+05:00", in: "+05:00")
+ }.should raise_error(ArgumentError, "timezone argument given as positional and keyword arguments")
end
end
- ruby_version_is "3.2" do
- describe "Time.new with a String argument" do
- it "parses an ISO-8601 like format" do
- t = Time.utc(2020, 12, 24, 15, 56, 17)
+ describe "Time.new with a String argument" do
+ it "parses an ISO-8601 like format" do
+ t = Time.utc(2020, 12, 24, 15, 56, 17)
- Time.new("2020-12-24T15:56:17Z").should == t
- Time.new("2020-12-25 00:56:17 +09:00").should == t
- Time.new("2020-12-25 00:57:47 +09:01:30").should == t
- Time.new("2020-12-25 00:56:17 +0900").should == t
- Time.new("2020-12-25 00:57:47 +090130").should == t
- Time.new("2020-12-25T00:56:17+09:00").should == t
- end
+ Time.new("2020-12-24T15:56:17Z").should == t
+ Time.new("2020-12-25 00:56:17 +09:00").should == t
+ Time.new("2020-12-25 00:57:47 +09:01:30").should == t
+ Time.new("2020-12-25 00:56:17 +0900").should == t
+ Time.new("2020-12-25 00:57:47 +090130").should == t
+ Time.new("2020-12-25T00:56:17+09:00").should == t
- it "accepts precision keyword argument and truncates specified digits of sub-second part" do
- Time.new("2021-12-25 00:00:00.123456789876 +09:00").subsec.should == 0.123456789r
- Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: nil).subsec.should == 0.123456789876r
- Time.new("2021-12-25 00:00:00 +09:00", precision: 0).subsec.should == 0
- Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: -1).subsec.should == 0.123456789876r
- end
+ Time.new("2020-12-25T00:56:17.123456+09:00").should == Time.utc(2020, 12, 24, 15, 56, 17, 123456)
+ end
- it "returns Time in local timezone if not provided in the String argument" do
- Time.new("2021-12-25 00:00:00").zone.should == Time.new(2021, 12, 25).zone
- Time.new("2021-12-25 00:00:00").utc_offset.should == Time.new(2021, 12, 25).utc_offset
- end
+ it "accepts precision keyword argument and truncates specified digits of sub-second part" do
+ Time.new("2021-12-25 00:00:00.123456789876 +09:00").subsec.should == 0.123456789r
+ Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: nil).subsec.should == 0.123456789876r
+ Time.new("2021-12-25 00:00:00 +09:00", precision: 0).subsec.should == 0
+ Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: -1).subsec.should == 0.123456789876r
+ end
- it "returns Time in timezone specified in the String argument" do
- Time.new("2021-12-25 00:00:00 +05:00").to_s.should == "2021-12-25 00:00:00 +0500"
- end
+ it "returns Time in local timezone if not provided in the String argument" do
+ Time.new("2021-12-25 00:00:00").zone.should == Time.new(2021, 12, 25).zone
+ Time.new("2021-12-25 00:00:00").utc_offset.should == Time.new(2021, 12, 25).utc_offset
+ end
- it "returns Time in timezone specified in the String argument even if the in keyword argument provided" do
- Time.new("2021-12-25 00:00:00 +09:00", in: "-01:00").to_s.should == "2021-12-25 00:00:00 +0900"
- end
+ it "returns Time in timezone specified in the String argument" do
+ Time.new("2021-12-25 00:00:00 +05:00").to_s.should == "2021-12-25 00:00:00 +0500"
+ end
- it "returns Time in timezone specified with in keyword argument if timezone isn't provided in the String argument" do
- Time.new("2021-12-25 00:00:00", in: "-01:00").to_s.should == "2021-12-25 00:00:00 -0100"
- end
+ it "returns Time in timezone specified in the String argument even if the in keyword argument provided" do
+ Time.new("2021-12-25 00:00:00 +09:00", in: "-01:00").to_s.should == "2021-12-25 00:00:00 +0900"
+ end
- it "converts precision keyword argument into Integer if is not nil" do
- obj = Object.new
- def obj.to_int; 3; end
+ it "returns Time in timezone specified with in keyword argument if timezone isn't provided in the String argument" do
+ Time.new("2021-12-25 00:00:00", in: "-01:00").to_s.should == "2021-12-25 00:00:00 -0100"
+ end
- Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: 1.2).subsec.should == 0.1r
- Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: obj).subsec.should == 0.123r
- Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: 3r).subsec.should == 0.123r
- end
+ it "returns Time of Jan 1 for string with just year" do
+ Time.new("2021").should == Time.new(2021, 1, 1)
+ Time.new("2021").zone.should == Time.new(2021, 1, 1).zone
+ Time.new("2021").utc_offset.should == Time.new(2021, 1, 1).utc_offset
+ end
- ruby_version_is ""..."3.3" do
- it "raise TypeError is can't convert precision keyword argument into Integer" do
- -> {
- Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: "")
- }.should raise_error(TypeError, "no implicit conversion from string")
- end
- end
+ it "returns Time of Jan 1 for string with just year in timezone specified with in keyword argument" do
+ Time.new("2021", in: "+17:00").to_s.should == "2021-01-01 00:00:00 +1700"
+ end
- ruby_version_is "3.3" do
- it "raise TypeError is can't convert precision keyword argument into Integer" do
- -> {
- Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: "")
- }.should raise_error(TypeError, "no implicit conversion of String into Integer")
- end
- end
+ it "converts precision keyword argument into Integer if is not nil" do
+ obj = Object.new
+ def obj.to_int; 3; end
- it "raises ArgumentError if part of time string is missing" do
- -> {
- Time.new("2020-12-25 00:56 +09:00")
- }.should raise_error(ArgumentError, "missing sec part: 00:56 ")
+ Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: 1.2).subsec.should == 0.1r
+ Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: obj).subsec.should == 0.123r
+ Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: 3r).subsec.should == 0.123r
+ end
+
+ it "returns Time with correct subseconds when given seconds fraction is shorted than 6 digits" do
+ Time.new("2020-12-25T00:56:17.123 +09:00").nsec.should == 123000000
+ Time.new("2020-12-25T00:56:17.123 +09:00").usec.should == 123000
+ Time.new("2020-12-25T00:56:17.123 +09:00").subsec.should == 0.123
+ end
+
+ it "returns Time with correct subseconds when given seconds fraction is milliseconds" do
+ Time.new("2020-12-25T00:56:17.123456 +09:00").nsec.should == 123456000
+ Time.new("2020-12-25T00:56:17.123456 +09:00").usec.should == 123456
+ Time.new("2020-12-25T00:56:17.123456 +09:00").subsec.should == 0.123456
+ end
+
+ it "returns Time with correct subseconds when given seconds fraction is longer that 6 digits but shorted than 9 digits" do
+ Time.new("2020-12-25T00:56:17.12345678 +09:00").nsec.should == 123456780
+ Time.new("2020-12-25T00:56:17.12345678 +09:00").usec.should == 123456
+ Time.new("2020-12-25T00:56:17.12345678 +09:00").subsec.should == 0.12345678
+ end
+ it "returns Time with correct subseconds when given seconds fraction is nanoseconds" do
+ Time.new("2020-12-25T00:56:17.123456789 +09:00").nsec.should == 123456789
+ Time.new("2020-12-25T00:56:17.123456789 +09:00").usec.should == 123456
+ Time.new("2020-12-25T00:56:17.123456789 +09:00").subsec.should == 0.123456789
+ end
+
+ it "returns Time with correct subseconds when given seconds fraction is longer than 9 digits" do
+ Time.new("2020-12-25T00:56:17.123456789876 +09:00").nsec.should == 123456789
+ Time.new("2020-12-25T00:56:17.123456789876 +09:00").usec.should == 123456
+ Time.new("2020-12-25T00:56:17.123456789876 +09:00").subsec.should == 0.123456789
+ end
+
+ ruby_version_is ""..."3.3" do
+ it "raise TypeError is can't convert precision keyword argument into Integer" do
-> {
- Time.new("2020-12-25 00 +09:00")
- }.should raise_error(ArgumentError, "missing min part: 00 ")
+ Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: "")
+ }.should raise_error(TypeError, "no implicit conversion from string")
end
+ end
- it "raises ArgumentError if subsecond is missing after dot" do
+ ruby_version_is "3.3" do
+ it "raise TypeError is can't convert precision keyword argument into Integer" do
-> {
- Time.new("2020-12-25 00:56:17. +0900")
- }.should raise_error(ArgumentError, "subsecond expected after dot: 00:56:17. ")
+ Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: "")
+ }.should raise_error(TypeError, "no implicit conversion of String into Integer")
end
+ end
- it "raises ArgumentError if String argument is not in the supported format" do
- -> {
- Time.new("021-12-25 00:00:00.123456 +09:00")
- }.should raise_error(ArgumentError, "year must be 4 or more digits: 021")
+ it "raises ArgumentError if part of time string is missing" do
+ -> {
+ Time.new("2020-12-25 00:56 +09:00")
+ }.should raise_error(ArgumentError, /missing sec part: 00:56 |can't parse:/)
- -> {
- Time.new("2020-012-25 00:56:17 +0900")
- }.should raise_error(ArgumentError, /\Atwo digits mon is expected after [`']-': -012-25 00:\z/)
+ -> {
+ Time.new("2020-12-25 00 +09:00")
+ }.should raise_error(ArgumentError, /missing min part: 00 |can't parse:/)
+ end
+ ruby_version_is "3.2.3" do
+ it "raises ArgumentError if the time part is missing" do
-> {
- Time.new("2020-2-25 00:56:17 +0900")
- }.should raise_error(ArgumentError, /\Atwo digits mon is expected after [`']-': -2-25 00:56\z/)
+ Time.new("2020-12-25")
+ }.should raise_error(ArgumentError, /no time information|can't parse:/)
+ end
+ it "raises ArgumentError if day is missing" do
-> {
- Time.new("2020-12-215 00:56:17 +0900")
- }.should raise_error(ArgumentError, /\Atwo digits mday is expected after [`']-': -215 00:56:\z/)
+ Time.new("2020-12")
+ }.should raise_error(ArgumentError, /no time information|can't parse:/)
+ end
+ end
- -> {
- Time.new("2020-12-25 000:56:17 +0900")
- }.should raise_error(ArgumentError, "two digits hour is expected: 000:56:17 ")
+ it "raises ArgumentError if subsecond is missing after dot" do
+ -> {
+ Time.new("2020-12-25 00:56:17. +0900")
+ }.should raise_error(ArgumentError, /subsecond expected after dot: 00:56:17. |can't parse:/)
+ end
- -> {
- Time.new("2020-12-25 0:56:17 +0900")
- }.should raise_error(ArgumentError, "two digits hour is expected: 0:56:17 +0")
+ it "raises ArgumentError if String argument is not in the supported format" do
+ -> {
+ Time.new("021-12-25 00:00:00.123456 +09:00")
+ }.should raise_error(ArgumentError, /year must be 4 or more digits: 021|can't parse:/)
- -> {
- Time.new("2020-12-25 00:516:17 +0900")
- }.should raise_error(ArgumentError, /\Atwo digits min is expected after [`']:': :516:17 \+09\z/)
+ -> {
+ Time.new("2020-012-25 00:56:17 +0900")
+ }.should raise_error(ArgumentError, /\Atwo digits mon is expected after [`']-': -012-25 00:\z|can't parse:/)
- -> {
- Time.new("2020-12-25 00:6:17 +0900")
- }.should raise_error(ArgumentError, /\Atwo digits min is expected after [`']:': :6:17 \+0900\z/)
+ -> {
+ Time.new("2020-2-25 00:56:17 +0900")
+ }.should raise_error(ArgumentError, /\Atwo digits mon is expected after [`']-': -2-25 00:56\z|can't parse:/)
- -> {
- Time.new("2020-12-25 00:56:137 +0900")
- }.should raise_error(ArgumentError, /\Atwo digits sec is expected after [`']:': :137 \+0900\z/)
+ -> {
+ Time.new("2020-12-215 00:56:17 +0900")
+ }.should raise_error(ArgumentError, /\Atwo digits mday is expected after [`']-': -215 00:56:\z|can't parse:/)
- -> {
- Time.new("2020-12-25 00:56:7 +0900")
- }.should raise_error(ArgumentError, /\Atwo digits sec is expected after [`']:': :7 \+0900\z/)
+ -> {
+ Time.new("2020-12-25 000:56:17 +0900")
+ }.should raise_error(ArgumentError, /two digits hour is expected: 000:56:17 |can't parse:/)
- -> {
- Time.new("2020-12-25 00:56. +0900")
- }.should raise_error(ArgumentError, "fraction min is not supported: 00:56.")
+ -> {
+ Time.new("2020-12-25 0:56:17 +0900")
+ }.should raise_error(ArgumentError, /two digits hour is expected: 0:56:17 \+0|can't parse:/)
+
+ -> {
+ Time.new("2020-12-25 00:516:17 +0900")
+ }.should raise_error(ArgumentError, /\Atwo digits min is expected after [`']:': :516:17 \+09\z|can't parse:/)
+
+ -> {
+ Time.new("2020-12-25 00:6:17 +0900")
+ }.should raise_error(ArgumentError, /\Atwo digits min is expected after [`']:': :6:17 \+0900\z|can't parse:/)
+
+ -> {
+ Time.new("2020-12-25 00:56:137 +0900")
+ }.should raise_error(ArgumentError, /\Atwo digits sec is expected after [`']:': :137 \+0900\z|can't parse:/)
+
+ -> {
+ Time.new("2020-12-25 00:56:7 +0900")
+ }.should raise_error(ArgumentError, /\Atwo digits sec is expected after [`']:': :7 \+0900\z|can't parse:/)
+
+ -> {
+ Time.new("2020-12-25 00:56. +0900")
+ }.should raise_error(ArgumentError, /fraction min is not supported: 00:56\.|can't parse:/)
+
+ -> {
+ Time.new("2020-12-25 00. +0900")
+ }.should raise_error(ArgumentError, /fraction hour is not supported: 00\.|can't parse:/)
+ end
+
+ it "raises ArgumentError if date/time parts values are not valid" do
+ -> {
+ Time.new("2020-13-25 00:56:17 +09:00")
+ }.should raise_error(ArgumentError, /(mon|argument) out of range/)
+
+ -> {
+ Time.new("2020-12-32 00:56:17 +09:00")
+ }.should raise_error(ArgumentError, /(mday|argument) out of range/)
+
+ -> {
+ Time.new("2020-12-25 25:56:17 +09:00")
+ }.should raise_error(ArgumentError, /(hour|argument) out of range/)
+
+ -> {
+ Time.new("2020-12-25 00:61:17 +09:00")
+ }.should raise_error(ArgumentError, /(min|argument) out of range/)
+
+ -> {
+ Time.new("2020-12-25 00:56:61 +09:00")
+ }.should raise_error(ArgumentError, /(sec|argument) out of range/)
+
+ -> {
+ Time.new("2020-12-25 00:56:17 +23:59:60")
+ }.should raise_error(ArgumentError, /utc_offset|argument out of range/)
+
+ -> {
+ Time.new("2020-12-25 00:56:17 +24:00")
+ }.should raise_error(ArgumentError, /(utc_offset|argument) out of range/)
+
+ -> {
+ Time.new("2020-12-25 00:56:17 +23:61")
+ }.should raise_error(ArgumentError, /utc_offset/)
+ ruby_bug '#20797', ''...'3.4' do
-> {
- Time.new("2020-12-25 00. +0900")
- }.should raise_error(ArgumentError, "fraction hour is not supported: 00.")
+ Time.new("2020-12-25 00:56:17 +00:23:61")
+ }.should raise_error(ArgumentError, /utc_offset/)
end
+ end
- it "raises ArgumentError if date/time parts values are not valid" do
- -> {
- Time.new("2020-13-25 00:56:17 +09:00")
- }.should raise_error(ArgumentError, "mon out of range")
+ it "raises ArgumentError if utc offset parts are not valid" do
+ -> { Time.new("2020-12-25 00:56:17 +24:00") }.should raise_error(ArgumentError, "utc_offset out of range")
+ -> { Time.new("2020-12-25 00:56:17 +2400") }.should raise_error(ArgumentError, "utc_offset out of range")
- -> {
- Time.new("2020-12-32 00:56:17 +09:00")
- }.should raise_error(ArgumentError, "mday out of range")
+ -> { Time.new("2020-12-25 00:56:17 +99:00") }.should raise_error(ArgumentError, "utc_offset out of range")
+ -> { Time.new("2020-12-25 00:56:17 +9900") }.should raise_error(ArgumentError, "utc_offset out of range")
- -> {
- Time.new("2020-12-25 25:56:17 +09:00")
- }.should raise_error(ArgumentError, "hour out of range")
+ -> { Time.new("2020-12-25 00:56:17 +00:60") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:60')
+ -> { Time.new("2020-12-25 00:56:17 +0060") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +0060')
- -> {
- Time.new("2020-12-25 00:61:17 +09:00")
- }.should raise_error(ArgumentError, "min out of range")
+ -> { Time.new("2020-12-25 00:56:17 +00:99") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:99')
+ -> { Time.new("2020-12-25 00:56:17 +0099") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +0099')
- -> {
- Time.new("2020-12-25 00:56:61 +09:00")
- }.should raise_error(ArgumentError, "sec out of range")
+ ruby_bug '#20797', ''...'3.4' do
+ -> { Time.new("2020-12-25 00:56:17 +00:00:60") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:00:60')
+ -> { Time.new("2020-12-25 00:56:17 +000060") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +000060')
- -> {
- Time.new("2020-12-25 00:56:17 +23:59:60")
- }.should raise_error(ArgumentError, "utc_offset out of range")
+ -> { Time.new("2020-12-25 00:56:17 +00:00:99") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:00:99')
+ -> { Time.new("2020-12-25 00:56:17 +000099") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +000099')
+ end
+ end
- -> {
- Time.new("2020-12-25 00:56:17 +24:00")
- }.should raise_error(ArgumentError, "utc_offset out of range")
+ it "raises ArgumentError if string has not ascii-compatible encoding" do
+ -> {
+ Time.new("2021-11-31 00:00:60 +09:00".encode("utf-32le"))
+ }.should raise_error(ArgumentError, "time string should have ASCII compatible encoding")
+ end
- -> {
- Time.new("2020-12-25 00:56:17 +23:61")
- }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +23:61')
+ it "raises ArgumentError if string doesn't start with year" do
+ -> {
+ Time.new("a\nb")
+ }.should raise_error(ArgumentError, "can't parse: \"a\\nb\"")
+ end
+
+ it "raises ArgumentError if string has extra characters after offset" do
+ -> {
+ Time.new("2021-11-31 00:00:59 +09:00 abc")
+ }.should raise_error(ArgumentError, /can't parse.+ abc/)
+ end
+
+ ruby_version_is "3.2.3" do
+ it "raises ArgumentError when there are leading space characters" do
+ -> { Time.new(" 2020-12-02 00:00:00") }.should raise_error(ArgumentError, /can't parse/)
+ -> { Time.new("\t2020-12-02 00:00:00") }.should raise_error(ArgumentError, /can't parse/)
+ -> { Time.new("\n2020-12-02 00:00:00") }.should raise_error(ArgumentError, /can't parse/)
+ -> { Time.new("\v2020-12-02 00:00:00") }.should raise_error(ArgumentError, /can't parse/)
+ -> { Time.new("\f2020-12-02 00:00:00") }.should raise_error(ArgumentError, /can't parse/)
+ -> { Time.new("\r2020-12-02 00:00:00") }.should raise_error(ArgumentError, /can't parse/)
end
- it "raises ArgumentError if string has not ascii-compatible encoding" do
- -> {
- Time.new("2021-11-31 00:00:60 +09:00".encode("utf-32le"))
- }.should raise_error(ArgumentError, "time string should have ASCII compatible encoding")
+ it "raises ArgumentError when there are trailing whitespaces" do
+ -> { Time.new("2020-12-02 00:00:00 ") }.should raise_error(ArgumentError, /can't parse/)
+ -> { Time.new("2020-12-02 00:00:00\t") }.should raise_error(ArgumentError, /can't parse/)
+ -> { Time.new("2020-12-02 00:00:00\n") }.should raise_error(ArgumentError, /can't parse/)
+ -> { Time.new("2020-12-02 00:00:00\v") }.should raise_error(ArgumentError, /can't parse/)
+ -> { Time.new("2020-12-02 00:00:00\f") }.should raise_error(ArgumentError, /can't parse/)
+ -> { Time.new("2020-12-02 00:00:00\r") }.should raise_error(ArgumentError, /can't parse/)
end
end
end
diff --git a/spec/ruby/core/time/now_spec.rb b/spec/ruby/core/time/now_spec.rb
index d47f00723e..e3fe6edad6 100644
--- a/spec/ruby/core/time/now_spec.rb
+++ b/spec/ruby/core/time/now_spec.rb
@@ -4,53 +4,177 @@ require_relative 'shared/now'
describe "Time.now" do
it_behaves_like :time_now, :now
- ruby_version_is '3.1' do # https://bugs.ruby-lang.org/issues/17485
- describe ":in keyword argument" do
- it "could be UTC offset as a String in '+HH:MM or '-HH:MM' format" do
- time = Time.now(in: "+05:00")
+ describe ":in keyword argument" do
+ it "could be UTC offset as a String in '+HH:MM or '-HH:MM' format" do
+ time = Time.now(in: "+05:00")
- time.utc_offset.should == 5*60*60
- time.zone.should == nil
+ time.utc_offset.should == 5*60*60
+ time.zone.should == nil
- time = Time.now(in: "-09:00")
+ time = Time.now(in: "-09:00")
- time.utc_offset.should == -9*60*60
- time.zone.should == nil
+ time.utc_offset.should == -9*60*60
+ time.zone.should == nil
+
+ time = Time.now(in: "-09:00:01")
+
+ time.utc_offset.should == -(9*60*60 + 1)
+ time.zone.should == nil
+ end
+
+ it "could be UTC offset as a number of seconds" do
+ time = Time.now(in: 5*60*60)
+
+ time.utc_offset.should == 5*60*60
+ time.zone.should == nil
+
+ time = Time.now(in: -9*60*60)
+
+ time.utc_offset.should == -9*60*60
+ time.zone.should == nil
+ end
+
+ it "returns a Time with UTC offset specified as a single letter military timezone" do
+ Time.now(in: "W").utc_offset.should == 3600 * -10
+ end
+
+ it "could be a timezone object" do
+ zone = TimeSpecs::TimezoneWithName.new(name: "Asia/Colombo")
+ time = Time.now(in: zone)
+
+ time.utc_offset.should == 5*3600+30*60
+ time.zone.should == zone
+
+ zone = TimeSpecs::TimezoneWithName.new(name: "PST")
+ time = Time.now(in: zone)
+
+ time.utc_offset.should == -9*60*60
+ time.zone.should == zone
+ end
+
+ it "raises ArgumentError if format is invalid" do
+ -> { Time.now(in: "+09:99") }.should raise_error(ArgumentError)
+ -> { Time.now(in: "ABC") }.should raise_error(ArgumentError)
+ end
+
+ it "raises ArgumentError if String argument and hours greater than 23" do
+ -> { Time.now(in: "+24:00") }.should raise_error(ArgumentError, "utc_offset out of range")
+ -> { Time.now(in: "+2400") }.should raise_error(ArgumentError, "utc_offset out of range")
+
+ -> { Time.now(in: "+99:00") }.should raise_error(ArgumentError, "utc_offset out of range")
+ -> { Time.now(in: "+9900") }.should raise_error(ArgumentError, "utc_offset out of range")
+ end
+
+ it "raises ArgumentError if String argument and minutes greater than 59" do
+ -> { Time.now(in: "+00:60") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:60')
+ -> { Time.now(in: "+0060") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +0060')
+
+ -> { Time.now(in: "+00:99") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:99')
+ -> { Time.now(in: "+0099") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +0099')
+ end
+
+ ruby_bug '#20797', ''...'3.4' do
+ it "raises ArgumentError if String argument and seconds greater than 59" do
+ -> { Time.now(in: "+00:00:60") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:00:60')
+ -> { Time.now(in: "+000060") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +000060')
+
+ -> { Time.now(in: "+00:00:99") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +00:00:99')
+ -> { Time.now(in: "+000099") }.should raise_error(ArgumentError, '"+HH:MM", "-HH:MM", "UTC" or "A".."I","K".."Z" expected for utc_offset: +000099')
end
+ end
+ end
- it "could be UTC offset as a number of seconds" do
- time = Time.now(in: 5*60*60)
+ describe "Timezone object" do # https://bugs.ruby-lang.org/issues/17485
+ 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_offset.should == 5*60*60
- time.zone.should == nil
+ -> {
+ Time.now(in: zone)
+ }.should raise_error(TypeError, /can't convert Object into an exact number/)
+ end
- time = Time.now(in: -9*60*60)
+ 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.now(in: zone).should be_kind_of(Time)
+ end
- time.utc_offset.should == -9*60*60
- time.zone.should == nil
+ # The result also should be a Time or Time-like object (not necessary to be the same class)
+ # or Integer. 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(t)
+ time = Time.new(t.year, t.mon, t.day, t.hour, t.min, t.sec, t.utc_offset)
+ time + 60 * 60 # + 1 hour
+ end
+
+ Time.now(in: zone).should be_kind_of(Time)
+ Time.now(in: zone).utc_offset.should == 3600
end
- it "returns a Time with UTC offset specified as a single letter military timezone" do
- Time.now(in: "W").utc_offset.should == 3600 * -10
+ it "could be Time subclass instance" do
+ zone = Object.new
+ def zone.utc_to_local(t)
+ time = Time.new(t.year, t.mon, t.day, t.hour, t.min, t.sec, t.utc_offset)
+ time += 60 * 60 # + 1 hour
+
+ Class.new(Time).new(time.year, time.mon, time.day, time.hour, time.min, time.sec, time.utc_offset)
+ end
+
+ Time.now(in: zone).should be_kind_of(Time)
+ Time.now(in: zone).utc_offset.should == 3600
end
- it "could be a timezone object" do
- zone = TimeSpecs::TimezoneWithName.new(name: "Asia/Colombo")
- time = Time.now(in: zone)
+ it "could be Integer" do
+ zone = Object.new
+ def zone.utc_to_local(time)
+ time.to_i + 60*60
+ end
+
+ Time.now(in: zone).should be_kind_of(Time)
+ Time.now(in: zone).utc_offset.should == 60*60
+ end
- time.utc_offset.should == 5*3600+30*60
- time.zone.should == zone
+ it "could have any #zone and #utc_offset because they are ignored" do
+ zone = Object.new
+ def zone.utc_to_local(t)
+ Struct.new(:year, :mon, :mday, :hour, :min, :sec, :isdst, :to_i, :zone, :utc_offset) # rubocop:disable Lint/StructNewOverride
+ .new(t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.isdst, t.to_i, 'America/New_York', -5*60*60)
+ end
+ Time.now(in: zone).utc_offset.should == 0
- zone = TimeSpecs::TimezoneWithName.new(name: "PST")
- time = Time.now(in: zone)
+ zone = Object.new
+ def zone.utc_to_local(t)
+ Struct.new(:year, :mon, :mday, :hour, :min, :sec, :isdst, :to_i, :zone, :utc_offset) # rubocop:disable Lint/StructNewOverride
+ .new(t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.isdst, t.to_i, 'Asia/Tokyo', 9*60*60)
+ end
+ Time.now(in: zone).utc_offset.should == 0
- time.utc_offset.should == -9*60*60
- time.zone.should == zone
+ zone = Object.new
+ def zone.utc_to_local(t)
+ Time.new(t.year, t.mon, t.mday, t.hour, t.min, t.sec, 9*60*60)
+ end
+ Time.now(in: zone).utc_offset.should == 0
end
- it "raises ArgumentError if format is invalid" do
- -> { Time.now(in: "+09:99") }.should raise_error(ArgumentError)
- -> { Time.now(in: "ABC") }.should raise_error(ArgumentError)
+ it "raises ArgumentError if difference between argument and result is too large" do
+ zone = Object.new
+ def zone.utc_to_local(t)
+ time = Time.utc(t.year, t.mon, t.day, t.hour, t.min, t.sec, t.utc_offset)
+ time -= 24 * 60 * 60 # - 1 day
+ Time.utc(time.year, time.mon, time.day, time.hour, time.min, time.sec, time.utc_offset)
+ end
+
+ -> {
+ Time.now(in: zone)
+ }.should raise_error(ArgumentError, "utc_offset out of range")
end
end
end
diff --git a/spec/ruby/core/time/shared/gmtime.rb b/spec/ruby/core/time/shared/gmtime.rb
index bae19da462..7b4f65f0b7 100644
--- a/spec/ruby/core/time/shared/gmtime.rb
+++ b/spec/ruby/core/time/shared/gmtime.rb
@@ -4,7 +4,14 @@ describe :time_gmtime, shared: true do
with_timezone("CST", -6) do
t = Time.local(2007, 1, 9, 6, 0, 0)
t.send(@method)
- t.should == Time.gm(2007, 1, 9, 12, 0, 0)
+ # Time#== compensates for time zones, so check all parts separately
+ t.year.should == 2007
+ t.month.should == 1
+ t.mday.should == 9
+ t.hour.should == 12
+ t.min.should == 0
+ t.sec.should == 0
+ t.zone.should == "UTC"
end
end
diff --git a/spec/ruby/core/time/shared/time_params.rb b/spec/ruby/core/time/shared/time_params.rb
index b6a6c88c8e..9832fd17fe 100644
--- a/spec/ruby/core/time/shared/time_params.rb
+++ b/spec/ruby/core/time/shared/time_params.rb
@@ -179,6 +179,10 @@ describe :time_params, shared: true do
}.should raise_error(ArgumentError, "argument out of range")
end
+ it "raises ArgumentError when given 8 arguments" do
+ -> { Time.send(@method, *[0]*8) }.should raise_error(ArgumentError)
+ end
+
it "raises ArgumentError when given 9 arguments" do
-> { Time.send(@method, *[0]*9) }.should raise_error(ArgumentError)
end
diff --git a/spec/ruby/core/time/shared/xmlschema.rb b/spec/ruby/core/time/shared/xmlschema.rb
new file mode 100644
index 0000000000..d68c18df36
--- /dev/null
+++ b/spec/ruby/core/time/shared/xmlschema.rb
@@ -0,0 +1,31 @@
+describe :time_xmlschema, shared: true do
+ ruby_version_is "3.4" do
+ it "generates ISO-8601 strings in Z for UTC times" do
+ t = Time.utc(1985, 4, 12, 23, 20, 50, 521245)
+ t.send(@method).should == "1985-04-12T23:20:50Z"
+ t.send(@method, 2).should == "1985-04-12T23:20:50.52Z"
+ t.send(@method, 9).should == "1985-04-12T23:20:50.521245000Z"
+ end
+
+ it "generates ISO-8601 string with timeone offset for non-UTC times" do
+ t = Time.new(1985, 4, 12, 23, 20, 50, "+02:00")
+ t.send(@method).should == "1985-04-12T23:20:50+02:00"
+ t.send(@method, 2).should == "1985-04-12T23:20:50.00+02:00"
+ end
+
+ it "year is always at least 4 digits" do
+ t = Time.utc(12, 4, 12)
+ t.send(@method).should == "0012-04-12T00:00:00Z"
+ end
+
+ it "year can be more than 4 digits" do
+ t = Time.utc(40_000, 4, 12)
+ t.send(@method).should == "40000-04-12T00:00:00Z"
+ end
+
+ it "year can be negative" do
+ t = Time.utc(-2000, 4, 12)
+ t.send(@method).should == "-2000-04-12T00:00:00Z"
+ end
+ end
+end
diff --git a/spec/ruby/core/time/strftime_spec.rb b/spec/ruby/core/time/strftime_spec.rb
index 4cb300c916..fd233f3577 100644
--- a/spec/ruby/core/time/strftime_spec.rb
+++ b/spec/ruby/core/time/strftime_spec.rb
@@ -50,44 +50,42 @@ describe "Time#strftime" do
time.strftime("%::z").should == "+01:01:05"
end
- ruby_version_is "3.1" do
- it "supports RFC 3339 UTC for unknown offset local time, -0000, as %-z" do
- time = Time.gm(2022)
-
- time.strftime("%z").should == "+0000"
- time.strftime("%-z").should == "-0000"
- time.strftime("%-:z").should == "-00:00"
- time.strftime("%-::z").should == "-00:00:00"
- end
+ it "supports RFC 3339 UTC for unknown offset local time, -0000, as %-z" do
+ time = Time.gm(2022)
- it "applies '-' flag to UTC time" do
- time = Time.utc(2022)
- time.strftime("%-z").should == "-0000"
+ time.strftime("%z").should == "+0000"
+ time.strftime("%-z").should == "-0000"
+ time.strftime("%-:z").should == "-00:00"
+ time.strftime("%-::z").should == "-00:00:00"
+ end
- time = Time.gm(2022)
- time.strftime("%-z").should == "-0000"
+ it "applies '-' flag to UTC time" do
+ time = Time.utc(2022)
+ time.strftime("%-z").should == "-0000"
- time = Time.new(2022, 1, 1, 0, 0, 0, "Z")
- time.strftime("%-z").should == "-0000"
+ time = Time.gm(2022)
+ time.strftime("%-z").should == "-0000"
- time = Time.new(2022, 1, 1, 0, 0, 0, "-00:00")
- time.strftime("%-z").should == "-0000"
+ time = Time.new(2022, 1, 1, 0, 0, 0, "Z")
+ time.strftime("%-z").should == "-0000"
- time = Time.new(2022, 1, 1, 0, 0, 0, "+03:00").utc
- time.strftime("%-z").should == "-0000"
- end
+ time = Time.new(2022, 1, 1, 0, 0, 0, "-00:00")
+ time.strftime("%-z").should == "-0000"
- it "ignores '-' flag for non-UTC time" do
- time = Time.new(2022, 1, 1, 0, 0, 0, "+03:00")
- time.strftime("%-z").should == "+0300"
- end
+ time = Time.new(2022, 1, 1, 0, 0, 0, "+03:00").utc
+ time.strftime("%-z").should == "-0000"
+ end
- it "works correctly with width, _ and 0 flags, and :" do
- Time.now.utc.strftime("%-_10z").should == " -000"
- Time.now.utc.strftime("%-10z").should == "-000000000"
- Time.now.utc.strftime("%-010:z").should == "-000000:00"
- Time.now.utc.strftime("%-_10:z").should == " -0:00"
- Time.now.utc.strftime("%-_10::z").should == " -0:00:00"
- end
+ it "ignores '-' flag for non-UTC time" do
+ time = Time.new(2022, 1, 1, 0, 0, 0, "+03:00")
+ time.strftime("%-z").should == "+0300"
+ end
+
+ it "works correctly with width, _ and 0 flags, and :" do
+ Time.now.utc.strftime("%-_10z").should == " -000"
+ Time.now.utc.strftime("%-10z").should == "-000000000"
+ Time.now.utc.strftime("%-010:z").should == "-000000:00"
+ Time.now.utc.strftime("%-_10:z").should == " -0:00"
+ Time.now.utc.strftime("%-_10::z").should == " -0:00:00"
end
end
diff --git a/spec/ruby/core/time/utc_spec.rb b/spec/ruby/core/time/utc_spec.rb
index 566509fd33..ab3c0df657 100644
--- a/spec/ruby/core/time/utc_spec.rb
+++ b/spec/ruby/core/time/utc_spec.rb
@@ -22,10 +22,8 @@ describe "Time#utc?" do
Time.now.localtime("UTC").utc?.should == true
Time.at(Time.now, in: 'UTC').utc?.should == true
- ruby_version_is "3.1" do
- Time.new(2022, 1, 1, 0, 0, 0, in: "UTC").utc?.should == true
- Time.now(in: "UTC").utc?.should == true
- end
+ Time.new(2022, 1, 1, 0, 0, 0, in: "UTC").utc?.should == true
+ Time.now(in: "UTC").utc?.should == true
end
it "does treat time with Z offset as UTC" do
@@ -33,26 +31,26 @@ describe "Time#utc?" do
Time.now.localtime("Z").utc?.should == true
Time.at(Time.now, in: 'Z').utc?.should == true
- ruby_version_is "3.1" do
- Time.new(2022, 1, 1, 0, 0, 0, in: "Z").utc?.should == true
- Time.now(in: "Z").utc?.should == true
- end
+ Time.new(2022, 1, 1, 0, 0, 0, in: "Z").utc?.should == true
+ Time.now(in: "Z").utc?.should == true
end
- ruby_version_is "3.1" do
- it "does treat time with -00:00 offset as UTC" do
- Time.new(2022, 1, 1, 0, 0, 0, "-00:00").utc?.should == true
- Time.now.localtime("-00:00").utc?.should == true
- Time.at(Time.now, in: '-00:00').utc?.should == true
- end
+ it "does treat time with -00:00 offset as UTC" do
+ Time.new(2022, 1, 1, 0, 0, 0, "-00:00").utc?.should == true
+ Time.now.localtime("-00:00").utc?.should == true
+ Time.at(Time.now, in: '-00:00').utc?.should == true
end
it "does not treat time with +00:00 offset as UTC" do
Time.new(2022, 1, 1, 0, 0, 0, "+00:00").utc?.should == false
+ Time.now.localtime("+00:00").utc?.should == false
+ Time.at(Time.now, in: "+00:00").utc?.should == false
end
it "does not treat time with 0 offset as UTC" do
Time.new(2022, 1, 1, 0, 0, 0, 0).utc?.should == false
+ Time.now.localtime(0).utc?.should == false
+ Time.at(Time.now, in: 0).utc?.should == false
end
end
diff --git a/spec/ruby/core/time/xmlschema_spec.rb b/spec/ruby/core/time/xmlschema_spec.rb
new file mode 100644
index 0000000000..bdf1dc7923
--- /dev/null
+++ b/spec/ruby/core/time/xmlschema_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../spec_helper'
+require_relative 'shared/xmlschema'
+
+describe "Time#xmlschema" do
+ it_behaves_like :time_xmlschema, :xmlschema
+end
diff --git a/spec/ruby/core/time/yday_spec.rb b/spec/ruby/core/time/yday_spec.rb
index 6ea5ff8f1b..e920c2e28d 100644
--- a/spec/ruby/core/time/yday_spec.rb
+++ b/spec/ruby/core/time/yday_spec.rb
@@ -1,4 +1,5 @@
require_relative '../../spec_helper'
+require_relative '../../shared/time/yday'
describe "Time#yday" do
it "returns an integer representing the day of the year, 1..366" do
@@ -7,15 +8,5 @@ describe "Time#yday" do
end
end
- it 'returns the correct value for each day of each month' do
- mdays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
-
- yday = 1
- mdays.each_with_index do |days, month|
- days.times do |day|
- Time.new(2014, month+1, day+1).yday.should == yday
- yday += 1
- end
- end
- end
+ it_behaves_like :time_yday, -> year, month, day { Time.new(year, month, day).yday }
end
diff --git a/spec/ruby/core/time/zone_spec.rb b/spec/ruby/core/time/zone_spec.rb
index 63c92602d1..9a15bd569b 100644
--- a/spec/ruby/core/time/zone_spec.rb
+++ b/spec/ruby/core/time/zone_spec.rb
@@ -69,22 +69,18 @@ describe "Time#zone" do
Time.at(Time.now, in: 'UTC').zone.should == "UTC"
Time.at(Time.now, in: 'Z').zone.should == "UTC"
- ruby_version_is "3.1" do
- Time.new(2022, 1, 1, 0, 0, 0, "-00:00").zone.should == "UTC"
- Time.now.localtime("-00:00").zone.should == "UTC"
- Time.at(Time.now, in: '-00:00').zone.should == "UTC"
- end
+ Time.new(2022, 1, 1, 0, 0, 0, "-00:00").zone.should == "UTC"
+ Time.now.localtime("-00:00").zone.should == "UTC"
+ Time.at(Time.now, in: '-00:00').zone.should == "UTC"
- ruby_version_is "3.1" do
- Time.new(2022, 1, 1, 0, 0, 0, in: "UTC").zone.should == "UTC"
- Time.new(2022, 1, 1, 0, 0, 0, in: "Z").zone.should == "UTC"
+ Time.new(2022, 1, 1, 0, 0, 0, in: "UTC").zone.should == "UTC"
+ Time.new(2022, 1, 1, 0, 0, 0, in: "Z").zone.should == "UTC"
- Time.now(in: 'UTC').zone.should == "UTC"
- Time.now(in: 'Z').zone.should == "UTC"
+ Time.now(in: 'UTC').zone.should == "UTC"
+ Time.now(in: 'Z').zone.should == "UTC"
- Time.at(Time.now, in: 'UTC').zone.should == "UTC"
- Time.at(Time.now, in: 'Z').zone.should == "UTC"
- end
+ Time.at(Time.now, in: 'UTC').zone.should == "UTC"
+ Time.at(Time.now, in: 'Z').zone.should == "UTC"
end
platform_is_not :aix, :windows do
diff --git a/spec/ruby/core/tracepoint/allow_reentry_spec.rb b/spec/ruby/core/tracepoint/allow_reentry_spec.rb
index 6bff1bed76..75e9e859a9 100644
--- a/spec/ruby/core/tracepoint/allow_reentry_spec.rb
+++ b/spec/ruby/core/tracepoint/allow_reentry_spec.rb
@@ -1,32 +1,30 @@
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
-ruby_version_is "3.1" do
- describe 'TracePoint.allow_reentry' do
- it 'allows the reentrance in a given block' do
- event_lines = []
- l1 = l2 = l3 = l4 = nil
- TracePoint.new(:line) do |tp|
- next unless TracePointSpec.target_thread?
+describe 'TracePoint.allow_reentry' do
+ it 'allows the reentrance in a given block' do
+ event_lines = []
+ l1 = l2 = l3 = l4 = nil
+ TracePoint.new(:line) do |tp|
+ next unless TracePointSpec.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__
+ 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
-
- event_lines.should == [l1, l3, l4, l2, l3, l4]
+ end.enable do
+ c = 3; l1 = __LINE__
+ d = 4; l2 = __LINE__
end
- it 'raises RuntimeError when not called inside a TracePoint' do
- -> {
- TracePoint.allow_reentry{}
- }.should raise_error(RuntimeError)
- end
+ event_lines.should == [l1, l3, l4, l2, l3, l4]
+ end
+
+ it 'raises RuntimeError when not called inside a TracePoint' do
+ -> {
+ TracePoint.allow_reentry{}
+ }.should raise_error(RuntimeError)
end
end
diff --git a/spec/ruby/core/tracepoint/enable_spec.rb b/spec/ruby/core/tracepoint/enable_spec.rb
index 6cc8bb3897..93a6b281e3 100644
--- a/spec/ruby/core/tracepoint/enable_spec.rb
+++ b/spec/ruby/core/tracepoint/enable_spec.rb
@@ -57,50 +57,25 @@ describe 'TracePoint#enable' do
end.enable { event_name.should equal(:line) }
end
- ruby_version_is '3.2' do
- it 'enables the trace object only for the current 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_not.include?(thread)
+ it 'enables the trace object only for the current thread' do
+ threads = []
+ trace = TracePoint.new(:line) do |tp|
+ # Runs on purpose on any Thread
+ threads << Thread.current
end
- end
- ruby_version_is ''...'3.2' do
- 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
+ thread = nil
+ trace.enable do
+ line_event = true
+ thread = Thread.new do
+ event_in_other_thread = true
end
-
- threads = threads.uniq
- threads.should.include?(Thread.current)
- threads.should.include?(thread)
+ thread.join
end
+
+ threads = threads.uniq
+ threads.should.include?(Thread.current)
+ threads.should_not.include?(thread)
end
it 'can accept arguments within a block but it should not yield arguments' do
diff --git a/spec/ruby/core/tracepoint/inspect_spec.rb b/spec/ruby/core/tracepoint/inspect_spec.rb
index cc6bf0f842..6cc2ebe243 100644
--- a/spec/ruby/core/tracepoint/inspect_spec.rb
+++ b/spec/ruby/core/tracepoint/inspect_spec.rb
@@ -24,6 +24,8 @@ describe 'TracePoint#inspect' do
line = nil
TracePoint.new(:line) { |tp|
next unless TracePointSpec.target_thread?
+ next unless tp.path == __FILE__
+
inspect ||= tp.inspect
}.enable do
line = __LINE__
@@ -37,6 +39,8 @@ describe 'TracePoint#inspect' do
line = nil
TracePoint.new(:call) { |tp|
next unless TracePointSpec.target_thread?
+ next unless tp.path == __FILE__
+
inspect ||= tp.inspect
}.enable do
line = __LINE__ + 1
@@ -52,6 +56,8 @@ describe 'TracePoint#inspect' do
line = nil
TracePoint.new(:return) { |tp|
next unless TracePointSpec.target_thread?
+ next unless tp.path == __FILE__
+
inspect ||= tp.inspect
}.enable do
line = __LINE__ + 4
@@ -61,6 +67,7 @@ describe 'TracePoint#inspect' do
end
trace_point_spec_test_return
end
+ ruby_version_is("3.4") { line -= 1 }
inspect.should =~ /\A#<TracePoint:return [`']trace_point_spec_test_return'#{@path_prefix}#{__FILE__}:#{line}>\z/
end
@@ -69,6 +76,8 @@ describe 'TracePoint#inspect' do
inspect = nil
tracepoint = TracePoint.new(:c_call) { |tp|
next unless TracePointSpec.target_thread?
+ next unless tp.path == __FILE__
+
inspect ||= tp.inspect
}
line = __LINE__ + 2
@@ -84,6 +93,8 @@ describe 'TracePoint#inspect' do
line = nil
TracePoint.new(:class) { |tp|
next unless TracePointSpec.target_thread?
+ next unless tp.path == __FILE__
+
inspect ||= tp.inspect
}.enable do
line = __LINE__ + 1
@@ -100,6 +111,7 @@ describe 'TracePoint#inspect' do
thread_inspection = nil
TracePoint.new(:thread_begin) { |tp|
next unless Thread.current == thread
+
inspect ||= tp.inspect
}.enable(target_thread: nil) do
thread = Thread.new {}
@@ -116,6 +128,7 @@ describe 'TracePoint#inspect' do
thread_inspection = nil
TracePoint.new(:thread_end) { |tp|
next unless Thread.current == thread
+
inspect ||= tp.inspect
}.enable(target_thread: nil) do
thread = Thread.new {}
diff --git a/spec/ruby/core/tracepoint/raised_exception_spec.rb b/spec/ruby/core/tracepoint/raised_exception_spec.rb
index ca2f50abb3..5ac8531840 100644
--- a/spec/ruby/core/tracepoint/raised_exception_spec.rb
+++ b/spec/ruby/core/tracepoint/raised_exception_spec.rb
@@ -17,4 +17,22 @@ describe 'TracePoint#raised_exception' do
raised_exception.should equal(error_result)
end
end
+
+ ruby_version_is "3.3" do
+ it 'returns value from exception rescued on the :rescue event' do
+ raised_exception, error_result = nil
+ trace = TracePoint.new(:rescue) { |tp|
+ next unless TracePointSpec.target_thread?
+ raised_exception = tp.raised_exception
+ }
+ trace.enable do
+ begin
+ raise StandardError
+ rescue => e
+ error_result = e
+ end
+ raised_exception.should equal(error_result)
+ end
+ end
+ end
end
diff --git a/spec/ruby/core/unboundmethod/equal_value_spec.rb b/spec/ruby/core/unboundmethod/equal_value_spec.rb
index 036c6b7f8c..b2d78c50af 100644
--- a/spec/ruby/core/unboundmethod/equal_value_spec.rb
+++ b/spec/ruby/core/unboundmethod/equal_value_spec.rb
@@ -76,38 +76,19 @@ describe "UnboundMethod#==" do
(@identical_body == @original_body).should == false
end
- ruby_version_is ""..."3.2" do
- it "returns false if same method but one extracted from a subclass" do
- (@parent == @child1).should == false
- (@child1 == @parent).should == false
- end
-
- it "returns false if same method but extracted from two different subclasses" do
- (@child2 == @child1).should == false
- (@child1 == @child2).should == false
- end
-
- it "returns false if methods are the same but added from an included Module" do
- (@includee == @includer).should == false
- (@includer == @includee).should == false
- end
+ it "returns true if same method but one extracted from a subclass" do
+ (@parent == @child1).should == true
+ (@child1 == @parent).should == true
end
- ruby_version_is "3.2" do
- it "returns true if same method but one extracted from a subclass" do
- (@parent == @child1).should == true
- (@child1 == @parent).should == true
- end
-
- it "returns false if same method but extracted from two different subclasses" do
- (@child2 == @child1).should == true
- (@child1 == @child2).should == true
- end
+ it "returns true if same method but extracted from two different subclasses" do
+ (@child2 == @child1).should == true
+ (@child1 == @child2).should == true
+ end
- it "returns true if methods are the same but added from an included Module" do
- (@includee == @includer).should == true
- (@includer == @includee).should == true
- end
+ it "returns true if methods are the same but added from an included Module" do
+ (@includee == @includer).should == true
+ (@includer == @includee).should == true
end
it "returns false if both have same Module, same name, identical body but not the same" do
diff --git a/spec/ruby/core/unboundmethod/owner_spec.rb b/spec/ruby/core/unboundmethod/owner_spec.rb
index e8a734dac4..b099c56de1 100644
--- a/spec/ruby/core/unboundmethod/owner_spec.rb
+++ b/spec/ruby/core/unboundmethod/owner_spec.rb
@@ -25,9 +25,7 @@ describe "UnboundMethod#owner" do
child_singleton_class.instance_method(:another_class_method).owner.should == child_singleton_class
end
- ruby_version_is "3.2" do
- it "returns the class on which public was called for a private method in ancestor" do
- MethodSpecs::InheritedMethods::C.instance_method(:derp).owner.should == MethodSpecs::InheritedMethods::C
- end
+ it "returns the class on which public was called for a private method in ancestor" do
+ MethodSpecs::InheritedMethods::C.instance_method(:derp).owner.should == MethodSpecs::InheritedMethods::C
end
end
diff --git a/spec/ruby/core/unboundmethod/private_spec.rb b/spec/ruby/core/unboundmethod/private_spec.rb
index 8ea50bb5d4..5a563939d1 100644
--- a/spec/ruby/core/unboundmethod/private_spec.rb
+++ b/spec/ruby/core/unboundmethod/private_spec.rb
@@ -2,27 +2,8 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "UnboundMethod#private?" do
- ruby_version_is "3.1"..."3.2" do
- it "returns false when the method is public" do
- obj = UnboundMethodSpecs::Methods.new
- obj.method(:my_public_method).unbind.private?.should == false
- end
-
- it "returns false when the method is protected" do
- obj = UnboundMethodSpecs::Methods.new
- obj.method(:my_protected_method).unbind.private?.should == false
- end
-
- it "returns true when the method is private" do
- obj = UnboundMethodSpecs::Methods.new
- obj.method(:my_private_method).unbind.private?.should == true
- end
- end
-
- ruby_version_is "3.2" do
- it "has been removed" do
- obj = UnboundMethodSpecs::Methods.new
- obj.method(:my_private_method).unbind.should_not.respond_to?(:private?)
- end
+ it "has been removed" do
+ obj = UnboundMethodSpecs::Methods.new
+ obj.method(:my_private_method).unbind.should_not.respond_to?(:private?)
end
end
diff --git a/spec/ruby/core/unboundmethod/protected_spec.rb b/spec/ruby/core/unboundmethod/protected_spec.rb
index 0c215d8638..70622d658d 100644
--- a/spec/ruby/core/unboundmethod/protected_spec.rb
+++ b/spec/ruby/core/unboundmethod/protected_spec.rb
@@ -2,27 +2,8 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "UnboundMethod#protected?" do
- ruby_version_is "3.1"..."3.2" do
- it "returns false when the method is public" do
- obj = UnboundMethodSpecs::Methods.new
- obj.method(:my_public_method).unbind.protected?.should == false
- end
-
- it "returns true when the method is protected" do
- obj = UnboundMethodSpecs::Methods.new
- obj.method(:my_protected_method).unbind.protected?.should == true
- end
-
- it "returns false when the method is private" do
- obj = UnboundMethodSpecs::Methods.new
- obj.method(:my_private_method).unbind.protected?.should == false
- end
- end
-
- ruby_version_is "3.2" do
- it "has been removed" do
- obj = UnboundMethodSpecs::Methods.new
- obj.method(:my_protected_method).unbind.should_not.respond_to?(:protected?)
- end
+ it "has been removed" do
+ obj = UnboundMethodSpecs::Methods.new
+ obj.method(:my_protected_method).unbind.should_not.respond_to?(:protected?)
end
end
diff --git a/spec/ruby/core/unboundmethod/public_spec.rb b/spec/ruby/core/unboundmethod/public_spec.rb
index 552bbf6eab..ae75e2601c 100644
--- a/spec/ruby/core/unboundmethod/public_spec.rb
+++ b/spec/ruby/core/unboundmethod/public_spec.rb
@@ -2,27 +2,8 @@ require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "UnboundMethod#public?" do
- ruby_version_is "3.1"..."3.2" do
- it "returns true when the method is public" do
- obj = UnboundMethodSpecs::Methods.new
- obj.method(:my_public_method).unbind.public?.should == true
- end
-
- it "returns false when the method is protected" do
- obj = UnboundMethodSpecs::Methods.new
- obj.method(:my_protected_method).unbind.public?.should == false
- end
-
- it "returns false when the method is private" do
- obj = UnboundMethodSpecs::Methods.new
- obj.method(:my_private_method).unbind.public?.should == false
- end
- end
-
- ruby_version_is "3.2" do
- it "has been removed" do
- obj = UnboundMethodSpecs::Methods.new
- obj.method(:my_public_method).unbind.should_not.respond_to?(:public?)
- end
+ it "has been removed" do
+ obj = UnboundMethodSpecs::Methods.new
+ obj.method(:my_public_method).unbind.should_not.respond_to?(:public?)
end
end
diff --git a/spec/ruby/core/unboundmethod/shared/dup.rb b/spec/ruby/core/unboundmethod/shared/dup.rb
index 943a7faaa3..194e2cc1a1 100644
--- a/spec/ruby/core/unboundmethod/shared/dup.rb
+++ b/spec/ruby/core/unboundmethod/shared/dup.rb
@@ -16,7 +16,7 @@ describe :unboundmethod_dup, shared: true do
end
it "copies the finalizer" do
- code = <<-RUBY
+ code = <<-'RUBY'
obj = Class.instance_method(:instance_method)
ObjectSpace.define_finalizer(obj, Proc.new { STDOUT.write "finalized\n" })
diff --git a/spec/ruby/core/unboundmethod/shared/to_s.rb b/spec/ruby/core/unboundmethod/shared/to_s.rb
index b92bb0b207..6b2c9c3e79 100644
--- a/spec/ruby/core/unboundmethod/shared/to_s.rb
+++ b/spec/ruby/core/unboundmethod/shared/to_s.rb
@@ -20,22 +20,11 @@ describe :unboundmethod_to_s, shared: true do
it "the String shows the method name, Module defined in and Module extracted from" do
@from_module.send(@method).should =~ /\bfrom_mod\b/
@from_module.send(@method).should =~ /\bUnboundMethodSpecs::Mod\b/
-
- ruby_version_is ""..."3.2" do
- @from_method.send(@method).should =~ /\bUnboundMethodSpecs::Methods\b/
- end
end
it "returns a String including all details" do
- ruby_version_is ""..."3.2" do
- @from_module.send(@method).should.start_with? "#<UnboundMethod: UnboundMethodSpecs::Methods(UnboundMethodSpecs::Mod)#from_mod"
- @from_method.send(@method).should.start_with? "#<UnboundMethod: UnboundMethodSpecs::Methods(UnboundMethodSpecs::Mod)#from_mod"
- end
-
- ruby_version_is "3.2" do
- @from_module.send(@method).should.start_with? "#<UnboundMethod: UnboundMethodSpecs::Mod#from_mod"
- @from_method.send(@method).should.start_with? "#<UnboundMethod: UnboundMethodSpecs::Mod#from_mod"
- end
+ @from_module.send(@method).should.start_with? "#<UnboundMethod: UnboundMethodSpecs::Mod#from_mod"
+ @from_method.send(@method).should.start_with? "#<UnboundMethod: UnboundMethodSpecs::Mod#from_mod"
end
it "does not show the defining module if it is the same as the origin" do
diff --git a/spec/ruby/core/unboundmethod/source_location_spec.rb b/spec/ruby/core/unboundmethod/source_location_spec.rb
index 5c2f14362c..9cc2198017 100644
--- a/spec/ruby/core/unboundmethod/source_location_spec.rb
+++ b/spec/ruby/core/unboundmethod/source_location_spec.rb
@@ -7,23 +7,23 @@ describe "UnboundMethod#source_location" do
end
it "sets the first value to the path of the file in which the method was defined" do
- file = @method.source_location.first
+ file = @method.source_location[0]
file.should be_an_instance_of(String)
file.should == File.realpath('fixtures/classes.rb', __dir__)
end
- it "sets the last value to an Integer representing the line on which the method was defined" do
- line = @method.source_location.last
+ it "sets the second value to an Integer representing the line on which the method was defined" do
+ line = @method.source_location[1]
line.should be_an_instance_of(Integer)
line.should == 5
end
it "returns the last place the method was defined" do
- UnboundMethodSpecs::SourceLocation.method(:redefined).unbind.source_location.last.should == 13
+ UnboundMethodSpecs::SourceLocation.method(:redefined).unbind.source_location[1].should == 13
end
it "returns the location of the original method even if it was aliased" do
- UnboundMethodSpecs::SourceLocation.instance_method(:aka).source_location.last.should == 17
+ UnboundMethodSpecs::SourceLocation.instance_method(:aka).source_location[1].should == 17
end
it "works for define_method methods" do
@@ -54,6 +54,12 @@ describe "UnboundMethod#source_location" do
c = Class.new do
eval('def m; end', nil, "foo", 100)
end
- c.instance_method(:m).source_location.should == ["foo", 100]
+ location = c.instance_method(:m).source_location
+ ruby_version_is(""..."4.1") do
+ location.should == ["foo", 100]
+ end
+ ruby_version_is("4.1") do
+ location.should == ["foo", 100, 0, 100, 10]
+ end
end
end
diff --git a/spec/ruby/core/warning/categories_spec.rb b/spec/ruby/core/warning/categories_spec.rb
new file mode 100644
index 0000000000..1e310ef38b
--- /dev/null
+++ b/spec/ruby/core/warning/categories_spec.rb
@@ -0,0 +1,12 @@
+require_relative '../../spec_helper'
+
+ruby_version_is "3.4" do
+ describe "Warning.categories" do
+ # There might be more, but these are standard across Ruby implementations
+ it "returns the list of possible warning categories" do
+ Warning.categories.should.include? :deprecated
+ Warning.categories.should.include? :experimental
+ Warning.categories.should.include? :performance
+ end
+ end
+end
diff --git a/spec/ruby/core/warning/warn_spec.rb b/spec/ruby/core/warning/warn_spec.rb
index 8f96fe9287..2e4a822e02 100644
--- a/spec/ruby/core/warning/warn_spec.rb
+++ b/spec/ruby/core/warning/warn_spec.rb
@@ -97,6 +97,20 @@ describe "Warning.warn" do
end
end
+ ruby_version_is "3.4" do
+ it "warns when category is :strict_unused_block but Warning[:strict_unused_block] is false" do
+ warn_strict_unused_block = Warning[:strict_unused_block]
+ Warning[:strict_unused_block] = true
+ begin
+ -> {
+ Warning.warn("foo", category: :strict_unused_block)
+ }.should complain("foo")
+ ensure
+ Warning[:strict_unused_block] = warn_strict_unused_block
+ end
+ end
+ end
+
it "doesn't print message when category is :deprecated but Warning[:deprecated] is false" do
warn_deprecated = Warning[:deprecated]
Warning[:deprecated] = false
@@ -121,6 +135,44 @@ describe "Warning.warn" do
end
end
+ ruby_version_is "3.4" do
+ it "doesn't print message when category is :strict_unused_block but Warning[:strict_unused_block] is false" do
+ warn_strict_unused_block = Warning[:strict_unused_block]
+ Warning[:strict_unused_block] = false
+ begin
+ -> {
+ Warning.warn("foo", category: :strict_unused_block)
+ }.should_not complain
+ ensure
+ Warning[:strict_unused_block] = warn_strict_unused_block
+ end
+ end
+ end
+
+ ruby_bug '#20573', ''...'3.4' do
+ it "isn't called by Kernel.warn when category is :deprecated but Warning[:deprecated] is false" do
+ warn_deprecated = Warning[:deprecated]
+ begin
+ Warning[:deprecated] = false
+ Warning.should_not_receive(:warn)
+ Kernel.warn("foo", category: :deprecated)
+ ensure
+ Warning[:deprecated] = warn_deprecated
+ end
+ end
+
+ it "isn't called by Kernel.warn when category is :experimental but Warning[:experimental] is false" do
+ warn_experimental = Warning[:experimental]
+ begin
+ Warning[:experimental] = false
+ Warning.should_not_receive(:warn)
+ Kernel.warn("foo", category: :experimental)
+ ensure
+ Warning[:experimental] = warn_experimental
+ end
+ end
+ end
+
it "prints the message when VERBOSE is false" do
-> { Warning.warn("foo") }.should complain("foo")
end
diff --git a/spec/ruby/default.mspec b/spec/ruby/default.mspec
index 1e8f8893aa..c8b1215f56 100644
--- a/spec/ruby/default.mspec
+++ b/spec/ruby/default.mspec
@@ -20,8 +20,11 @@ class MSpecScript
# C extension API specs
set :capi, [ 'optional/capi' ]
+ # Thread safety specs
+ set :thread_safety, [ 'optional/thread_safety' ]
+
# A list of _all_ optional specs
- set :optional, get(:capi)
+ set :optional, get(:capi) + get(:thread_safety)
# An ordered list of the directories containing specs to run
set :files, get(:command_line) + get(:language) + get(:core) + get(:library) + get(:security) + get(:optional)
diff --git a/spec/ruby/fixtures/constants.rb b/spec/ruby/fixtures/constants.rb
index ffe45fb1f6..7f0b88daab 100644
--- a/spec/ruby/fixtures/constants.rb
+++ b/spec/ruby/fixtures/constants.rb
@@ -10,7 +10,7 @@
# variety in class and module configurations, including hierarchy,
# containment, inclusion, singletons and toplevel.
#
-# Constants are numbered for for uniqueness. The CS_ prefix is uniformly used
+# Constants are numbered for uniqueness. The CS_ prefix is uniformly used
# and is to minimize clashes with other toplevel constants (see e.g. ModuleA
# which is included in Object). Constant values are symbols. A numbered suffix
# is used to distinguish constants with the same name defined in different
diff --git a/spec/ruby/fixtures/io.rb b/spec/ruby/fixtures/io.rb
new file mode 100644
index 0000000000..87ebbbb2bd
--- /dev/null
+++ b/spec/ruby/fixtures/io.rb
@@ -0,0 +1,12 @@
+module IOSpec
+ def self.exhaust_write_buffer(io)
+ written = 0
+ buf = " " * 4096
+
+ while true
+ written += io.write_nonblock(buf)
+ end
+ rescue Errno::EAGAIN, Errno::EWOULDBLOCK
+ written
+ end
+end
diff --git a/spec/ruby/language/assignments_spec.rb b/spec/ruby/language/assignments_spec.rb
index 2773508d8d..c4adf73c1c 100644
--- a/spec/ruby/language/assignments_spec.rb
+++ b/spec/ruby/language/assignments_spec.rb
@@ -23,25 +23,12 @@ describe 'Assignments' do
ScratchPad.recorded.should == [:receiver, :argument, :rhs]
end
- # similar tests for evaluation order are located in language/constants_spec.rb
- ruby_version_is ''...'3.2' do
- it 'evaluates expressions right to left when assignment with compounded constant' do
- m = Module.new
- ScratchPad.record []
-
- (ScratchPad << :module; m)::A = (ScratchPad << :rhs; :value)
- ScratchPad.recorded.should == [:rhs, :module]
- end
- end
-
- ruby_version_is '3.2' do
- it 'evaluates expressions left to right when assignment with compounded constant' do
- m = Module.new
- ScratchPad.record []
+ it 'evaluates expressions left to right when assignment with compounded constant' do
+ m = Module.new
+ ScratchPad.record []
- (ScratchPad << :module; m)::A = (ScratchPad << :rhs; :value)
- ScratchPad.recorded.should == [:module, :rhs]
- end
+ (ScratchPad << :module; m)::A = (ScratchPad << :rhs; :value)
+ ScratchPad.recorded.should == [:module, :rhs]
end
it 'raises TypeError after evaluation of right-hand-side when compounded constant module is not a module' do
@@ -54,6 +41,65 @@ describe 'Assignments' do
ScratchPad.recorded.should == [:rhs]
end
end
+
+ context "given block argument" do
+ before do
+ @klass = Class.new do
+ def initialize(h) @h = h end
+ def [](k, &block) @h[k]; end
+ def []=(k, v, &block) @h[k] = v; end
+ end
+ end
+
+ ruby_version_is ""..."3.4" do
+ it "accepts block argument" do
+ obj = @klass.new(a: 1)
+ block = proc {}
+
+ eval "obj[:a, &block] = 2"
+ eval("obj[:a, &block]").should == 2
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "raises SyntaxError" do
+ obj = @klass.new(a: 1)
+ block = proc {}
+
+ -> {
+ eval "obj[:a, &block] = 2"
+ }.should raise_error(SyntaxError, /unexpected block arg given in index assignment|block arg given in index assignment/)
+ end
+ end
+ end
+
+ context "given keyword arguments" do
+ before do
+ @klass = Class.new do
+ attr_reader :x
+
+ def []=(*args, **kw)
+ @x = [args, kw]
+ end
+ end
+ end
+
+ ruby_version_is ""..."3.4" do
+ it "supports keyword arguments in index assignments" do
+ a = @klass.new
+ eval "a[1, 2, 3, b: 4] = 5"
+ a.x.should == [[1, 2, 3, {b: 4}, 5], {}]
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "raises SyntaxError when given keyword arguments in index assignments" do
+ a = @klass.new
+ -> { eval "a[1, 2, 3, b: 4] = 5" }.should raise_error(SyntaxError,
+ /keywords are not allowed in index assignment expressions|keyword arg given in index assignment/) # prism|parse.y
+ end
+ end
+ end
end
describe 'using +=' do
@@ -127,6 +173,77 @@ describe 'Assignments' do
a.public_method(:k, 2).should == 2
end
+ context "given block argument" do
+ before do
+ @klass = Class.new do
+ def initialize(h) @h = h end
+ def [](k, &block) @h[k]; end
+ def []=(k, v, &block) @h[k] = v; end
+ end
+ end
+
+ ruby_version_is ""..."3.4" do
+ it "accepts block argument" do
+ obj = @klass.new(a: 1)
+ block = proc {}
+
+ eval "obj[:a, &block] += 2"
+ eval("obj[:a, &block]").should == 3
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "raises SyntaxError" do
+ obj = @klass.new(a: 1)
+ block = proc {}
+
+ -> {
+ eval "obj[:a, &block] += 2"
+ }.should raise_error(SyntaxError, /unexpected block arg given in index assignment|block arg given in index assignment/)
+ end
+ end
+ end
+
+ context "given keyword arguments" do
+ before do
+ @klass = Class.new do
+ attr_reader :x
+
+ def [](*args)
+ 100
+ end
+
+ def []=(*args, **kw)
+ @x = [args, kw]
+ end
+ end
+ end
+
+ ruby_version_is ""..."3.3" do
+ it "supports keyword arguments in index assignments" do
+ a = @klass.new
+ eval "a[1, 2, 3, b: 4] += 5"
+ a.x.should == [[1, 2, 3, {b: 4}, 105], {}]
+ end
+ end
+
+ ruby_version_is "3.3"..."3.4" do
+ it "supports keyword arguments in index assignments" do
+ a = @klass.new
+ eval "a[1, 2, 3, b: 4] += 5"
+ a.x.should == [[1, 2, 3, 105], {b: 4}]
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "raises SyntaxError when given keyword arguments in index assignments" do
+ a = @klass.new
+ -> { eval "a[1, 2, 3, b: 4] += 5" }.should raise_error(SyntaxError,
+ /keywords are not allowed in index assignment expressions|keyword arg given in index assignment/) # prism|parse.y
+ end
+ end
+ end
+
context 'splatted argument' do
it 'correctly handles it' do
@b[:m] = 10
@@ -276,158 +393,102 @@ end
describe 'Multiple assignments' do
describe 'evaluation order' do
- ruby_version_is ''...'3.1' do
- it 'evaluates expressions right to left when assignment with an accessor' do
- object = Object.new
- def object.a=(value) end
- ScratchPad.record []
-
- (ScratchPad << :a; object).a, (ScratchPad << :b; object).a = (ScratchPad << :c; :c), (ScratchPad << :d; :d)
- ScratchPad.recorded.should == [:c, :d, :a, :b]
- end
-
- it 'evaluates expressions right to left when assignment with a nested accessor' do
- object = Object.new
- def object.a=(value) end
- ScratchPad.record []
+ it 'evaluates expressions left to right when assignment with an accessor' do
+ object = Object.new
+ def object.a=(value) end
+ ScratchPad.record []
- ((ScratchPad << :a; object).a, foo), bar = [(ScratchPad << :b; :b)]
- ScratchPad.recorded.should == [:b, :a]
- end
+ (ScratchPad << :a; object).a, (ScratchPad << :b; object).a = (ScratchPad << :c; :c), (ScratchPad << :d; :d)
+ ScratchPad.recorded.should == [:a, :b, :c, :d]
end
- ruby_version_is '3.1' do
- it 'evaluates expressions left to right when assignment with an accessor' do
- object = Object.new
- def object.a=(value) end
- ScratchPad.record []
-
- (ScratchPad << :a; object).a, (ScratchPad << :b; object).a = (ScratchPad << :c; :c), (ScratchPad << :d; :d)
- ScratchPad.recorded.should == [:a, :b, :c, :d]
- end
-
- it 'evaluates expressions left to right when assignment with a nested accessor' do
- object = Object.new
- def object.a=(value) end
- ScratchPad.record []
-
- ((ScratchPad << :a; object).a, foo), bar = [(ScratchPad << :b; :b)]
- ScratchPad.recorded.should == [:a, :b]
- end
-
- it 'evaluates expressions left to right when assignment with a deeply nested accessor' do
- o = Object.new
- def o.a=(value) end
- def o.b=(value) end
- def o.c=(value) end
- def o.d=(value) end
- def o.e=(value) end
- def o.f=(value) end
- ScratchPad.record []
-
- (ScratchPad << :a; o).a,
- ((ScratchPad << :b; o).b,
- ((ScratchPad << :c; o).c, (ScratchPad << :d; o).d),
- (ScratchPad << :e; o).e),
- (ScratchPad << :f; o).f = (ScratchPad << :value; :value)
+ it 'evaluates expressions left to right when assignment with a nested accessor' do
+ object = Object.new
+ def object.a=(value) end
+ ScratchPad.record []
- ScratchPad.recorded.should == [:a, :b, :c, :d, :e, :f, :value]
- end
+ ((ScratchPad << :a; object).a, foo), bar = [(ScratchPad << :b; :b)]
+ ScratchPad.recorded.should == [:a, :b]
end
- ruby_version_is ''...'3.1' do
- it 'evaluates expressions right to left when assignment with a #[]=' do
- object = Object.new
- def object.[]=(_, _) end
- ScratchPad.record []
-
- (ScratchPad << :a; object)[(ScratchPad << :b; :b)], (ScratchPad << :c; object)[(ScratchPad << :d; :d)] = (ScratchPad << :e; :e), (ScratchPad << :f; :f)
- ScratchPad.recorded.should == [:e, :f, :a, :b, :c, :d]
- end
-
- it 'evaluates expressions right to left when assignment with a nested #[]=' do
- object = Object.new
- def object.[]=(_, _) end
- ScratchPad.record []
-
- ((ScratchPad << :a; object)[(ScratchPad << :b; :b)], foo), bar = [(ScratchPad << :c; :c)]
- ScratchPad.recorded.should == [:c, :a, :b]
- end
+ it 'evaluates expressions left to right when assignment with a deeply nested accessor' do
+ o = Object.new
+ def o.a=(value) end
+ def o.b=(value) end
+ def o.c=(value) end
+ def o.d=(value) end
+ def o.e=(value) end
+ def o.f=(value) end
+ ScratchPad.record []
+
+ (ScratchPad << :a; o).a,
+ ((ScratchPad << :b; o).b,
+ ((ScratchPad << :c; o).c, (ScratchPad << :d; o).d),
+ (ScratchPad << :e; o).e),
+ (ScratchPad << :f; o).f = (ScratchPad << :value; :value)
+
+ ScratchPad.recorded.should == [:a, :b, :c, :d, :e, :f, :value]
end
- ruby_version_is '3.1' do
- it 'evaluates expressions left to right when assignment with a #[]=' do
- object = Object.new
- def object.[]=(_, _) end
- ScratchPad.record []
+ it 'evaluates expressions left to right when assignment with a #[]=' do
+ object = Object.new
+ def object.[]=(_, _) end
+ ScratchPad.record []
- (ScratchPad << :a; object)[(ScratchPad << :b; :b)], (ScratchPad << :c; object)[(ScratchPad << :d; :d)] = (ScratchPad << :e; :e), (ScratchPad << :f; :f)
- ScratchPad.recorded.should == [:a, :b, :c, :d, :e, :f]
- end
+ (ScratchPad << :a; object)[(ScratchPad << :b; :b)], (ScratchPad << :c; object)[(ScratchPad << :d; :d)] = (ScratchPad << :e; :e), (ScratchPad << :f; :f)
+ ScratchPad.recorded.should == [:a, :b, :c, :d, :e, :f]
+ end
- it 'evaluates expressions left to right when assignment with a nested #[]=' do
- object = Object.new
- def object.[]=(_, _) end
- ScratchPad.record []
+ it 'evaluates expressions left to right when assignment with a nested #[]=' do
+ object = Object.new
+ def object.[]=(_, _) end
+ ScratchPad.record []
- ((ScratchPad << :a; object)[(ScratchPad << :b; :b)], foo), bar = [(ScratchPad << :c; :c)]
- ScratchPad.recorded.should == [:a, :b, :c]
- end
+ ((ScratchPad << :a; object)[(ScratchPad << :b; :b)], foo), bar = [(ScratchPad << :c; :c)]
+ ScratchPad.recorded.should == [:a, :b, :c]
+ end
- it 'evaluates expressions left to right when assignment with a deeply nested #[]=' do
- o = Object.new
- def o.[]=(_, _) end
- ScratchPad.record []
+ it 'evaluates expressions left to right when assignment with a deeply nested #[]=' do
+ o = Object.new
+ def o.[]=(_, _) end
+ ScratchPad.record []
- (ScratchPad << :ra; o)[(ScratchPad << :aa; :aa)],
- ((ScratchPad << :rb; o)[(ScratchPad << :ab; :ab)],
- ((ScratchPad << :rc; o)[(ScratchPad << :ac; :ac)], (ScratchPad << :rd; o)[(ScratchPad << :ad; :ad)]),
- (ScratchPad << :re; o)[(ScratchPad << :ae; :ae)]),
- (ScratchPad << :rf; o)[(ScratchPad << :af; :af)] = (ScratchPad << :value; :value)
+ (ScratchPad << :ra; o)[(ScratchPad << :aa; :aa)],
+ ((ScratchPad << :rb; o)[(ScratchPad << :ab; :ab)],
+ ((ScratchPad << :rc; o)[(ScratchPad << :ac; :ac)], (ScratchPad << :rd; o)[(ScratchPad << :ad; :ad)]),
+ (ScratchPad << :re; o)[(ScratchPad << :ae; :ae)]),
+ (ScratchPad << :rf; o)[(ScratchPad << :af; :af)] = (ScratchPad << :value; :value)
- ScratchPad.recorded.should == [:ra, :aa, :rb, :ab, :rc, :ac, :rd, :ad, :re, :ae, :rf, :af, :value]
- end
+ ScratchPad.recorded.should == [:ra, :aa, :rb, :ab, :rc, :ac, :rd, :ad, :re, :ae, :rf, :af, :value]
end
- ruby_version_is ''...'3.2' do
- it 'evaluates expressions right to left when assignment with compounded constant' do
- m = Module.new
- ScratchPad.record []
+ it 'evaluates expressions left to right when assignment with compounded constant' do
+ m = Module.new
+ ScratchPad.record []
- (ScratchPad << :a; m)::A, (ScratchPad << :b; m)::B = (ScratchPad << :c; :c), (ScratchPad << :d; :d)
- ScratchPad.recorded.should == [:c, :d, :a, :b]
- end
+ (ScratchPad << :a; m)::A, (ScratchPad << :b; m)::B = (ScratchPad << :c; :c), (ScratchPad << :d; :d)
+ ScratchPad.recorded.should == [:a, :b, :c, :d]
end
- ruby_version_is '3.2' do
- it 'evaluates expressions left to right when assignment with compounded constant' do
- m = Module.new
- ScratchPad.record []
-
- (ScratchPad << :a; m)::A, (ScratchPad << :b; m)::B = (ScratchPad << :c; :c), (ScratchPad << :d; :d)
- ScratchPad.recorded.should == [:a, :b, :c, :d]
- end
-
- it 'evaluates expressions left to right when assignment with a nested compounded constant' do
- m = Module.new
- ScratchPad.record []
+ it 'evaluates expressions left to right when assignment with a nested compounded constant' do
+ m = Module.new
+ ScratchPad.record []
- ((ScratchPad << :a; m)::A, foo), bar = [(ScratchPad << :b; :b)]
- ScratchPad.recorded.should == [:a, :b]
- end
+ ((ScratchPad << :a; m)::A, foo), bar = [(ScratchPad << :b; :b)]
+ ScratchPad.recorded.should == [:a, :b]
+ end
- it 'evaluates expressions left to right when assignment with deeply nested compounded constants' do
- m = Module.new
- ScratchPad.record []
+ it 'evaluates expressions left to right when assignment with deeply nested compounded constants' do
+ m = Module.new
+ ScratchPad.record []
- (ScratchPad << :a; m)::A,
- ((ScratchPad << :b; m)::B,
- ((ScratchPad << :c; m)::C, (ScratchPad << :d; m)::D),
- (ScratchPad << :e; m)::E),
- (ScratchPad << :f; m)::F = (ScratchPad << :value; :value)
+ (ScratchPad << :a; m)::A,
+ ((ScratchPad << :b; m)::B,
+ ((ScratchPad << :c; m)::C, (ScratchPad << :d; m)::D),
+ (ScratchPad << :e; m)::E),
+ (ScratchPad << :f; m)::F = (ScratchPad << :value; :value)
- ScratchPad.recorded.should == [:a, :b, :c, :d, :e, :f, :value]
- end
+ ScratchPad.recorded.should == [:a, :b, :c, :d, :e, :f, :value]
end
end
diff --git a/spec/ruby/language/block_spec.rb b/spec/ruby/language/block_spec.rb
index 578d9cb3b0..cc003b8946 100644
--- a/spec/ruby/language/block_spec.rb
+++ b/spec/ruby/language/block_spec.rb
@@ -62,37 +62,18 @@ describe "A block yielded a single" do
m([1, 2, 3, 4, 5, 6]) { |a, b=5, c=6, *d, e, f| [a, b, c, d, e, f] }.should == [1, 2, 3, [4], 5, 6]
end
- ruby_version_is "3.2" do
- it "does not autosplat single argument to required arguments when a keyword rest argument is present" do
- m([1, 2]) { |a, **k| [a, k] }.should == [[1, 2], {}]
- end
-
- it "does not autosplat single argument to required arguments when keyword arguments are present" do
- m([1, 2]) { |a, b: :b, c: :c| [a, b, c] }.should == [[1, 2], :b, :c]
- end
-
- it "raises error when required keyword arguments are present" do
- -> {
- m([1, 2]) { |a, b:, c:| [a, b, c] }
- }.should raise_error(ArgumentError, "missing keywords: :b, :c")
- end
+ it "does not autosplat single argument to required arguments when a keyword rest argument is present" do
+ m([1, 2]) { |a, **k| [a, k] }.should == [[1, 2], {}]
end
- ruby_version_is ''..."3.2" do
- # https://bugs.ruby-lang.org/issues/18633
- it "autosplats single argument to required arguments when a keyword rest argument is present" do
- m([1, 2]) { |a, **k| [a, k] }.should == [1, {}]
- end
-
- it "autosplats single argument to required arguments when optional keyword arguments are present" do
- m([1, 2]) { |a, b: :b, c: :c| [a, b, c] }.should == [1, :b, :c]
- end
+ it "does not autosplat single argument to required arguments when keyword arguments are present" do
+ m([1, 2]) { |a, b: :b, c: :c| [a, b, c] }.should == [[1, 2], :b, :c]
+ end
- it "raises error when required keyword arguments are present" do
- -> {
- m([1, 2]) { |a, b:, c:| [a, b, c] }
- }.should raise_error(ArgumentError, "missing keywords: :b, :c")
- end
+ it "raises error when required keyword arguments are present" do
+ -> {
+ m([1, 2]) { |a, b:, c:| [a, b, c] }
+ }.should raise_error(ArgumentError, "missing keywords: :b, :c")
end
it "assigns elements to mixed argument types" do
@@ -294,7 +275,7 @@ describe "A block" do
end
it "may include a rescue clause" do
- eval("@y.z do raise ArgumentError; rescue ArgumentError; 7; end").should == 7
+ @y.z do raise ArgumentError; rescue ArgumentError; 7; end.should == 7
end
end
@@ -308,7 +289,7 @@ describe "A block" do
end
it "may include a rescue clause" do
- eval('@y.z do || raise ArgumentError; rescue ArgumentError; 7; end').should == 7
+ @y.z do || raise ArgumentError; rescue ArgumentError; 7; end.should == 7
end
end
@@ -337,7 +318,7 @@ describe "A block" do
end
it "may include a rescue clause" do
- eval('@y.s(1) do |x| raise ArgumentError; rescue ArgumentError; 7; end').should == 7
+ @y.s(1) do |x| raise ArgumentError; rescue ArgumentError; 7; end.should == 7
end
end
@@ -737,9 +718,9 @@ describe "A block" do
end
it "accepts unnamed arguments" do
- eval("lambda { |_,_| }").should be_an_instance_of(Proc)
- eval("->(_,_) {}").should be_an_instance_of(Proc)
- eval("Proc.new { |_,_| }").should be_an_instance_of(Proc)
+ lambda { |_,_| }.should be_an_instance_of(Proc) # rubocop:disable Style/Lambda
+ -> _,_ {}.should be_an_instance_of(Proc)
+ Proc.new { |_,_| }.should be_an_instance_of(Proc)
end
end
@@ -960,24 +941,27 @@ describe "Post-args" do
end
describe "with a circular argument reference" do
- it "raises a SyntaxError if using an existing local with the same name as the argument" do
- a = 1
- -> {
- @proc = eval "proc { |a=a| a }"
- }.should raise_error(SyntaxError)
+ ruby_version_is ""..."3.4" do
+ it "raises a SyntaxError if using the argument in its default value" do
+ a = 1
+ -> {
+ eval "proc { |a=a| a }"
+ }.should raise_error(SyntaxError)
+ end
end
- it "raises a SyntaxError if there is an existing method with the same name as the argument" do
- def a; 1; end
- -> {
- @proc = eval "proc { |a=a| a }"
- }.should raise_error(SyntaxError)
+ ruby_version_is "3.4" do
+ it "is nil if using the argument in its default value" do
+ -> {
+ eval "proc { |a=a| a }.call"
+ }.call.should == nil
+ end
end
+ end
- it "calls an existing method with the same name as the argument if explicitly using ()" do
- def a; 1; end
- proc { |a=a()| a }.call.should == 1
- end
+ it "calls an existing method with the same name as the argument if explicitly using ()" do
+ def a; 1; end
+ proc { |a=a()| a }.call.should == 1
end
end
@@ -996,76 +980,159 @@ describe "Post-args" do
end
end
+# tested more thoroughly in language/delegation_spec.rb
describe "Anonymous block forwarding" do
- ruby_version_is "3.1" do
- it "forwards blocks to other method that formally declares anonymous block" do
- eval <<-EOF
- def b(&); c(&) end
- def c(&); yield :non_null end
- EOF
+ it "forwards blocks to other method that formally declares anonymous block" do
+ def b(&); c(&) end
+ def c(&); yield :non_null end
+
+ b { |c| c }.should == :non_null
+ end
- b { |c| c }.should == :non_null
+ it "requires the anonymous block parameter to be declared if directly passing a block" do
+ -> { eval "def a; b(&); end; def b; end" }.should raise_error(SyntaxError)
+ end
+
+ it "works when it's the only declared parameter" do
+ def inner; yield end
+ def block_only(&); inner(&) end
+
+ block_only { 1 }.should == 1
+ end
+
+ it "works alongside positional parameters" do
+ def inner; yield end
+ def pos(arg1, &); inner(&) end
+
+ pos(:a) { 1 }.should == 1
+ end
+
+ it "works alongside positional arguments and splatted keyword arguments" do
+ def inner; yield end
+ def pos_kwrest(arg1, **kw, &); inner(&) end
+
+ pos_kwrest(:a, arg: 3) { 1 }.should == 1
+ end
+
+ it "works alongside positional arguments and disallowed keyword arguments" do
+ def inner; yield end
+ def no_kw(arg1, **nil, &); inner(&) end
+
+ no_kw(:a) { 1 }.should == 1
+ end
+
+ it "works alongside explicit keyword arguments" do
+ eval <<-EOF
+ def inner; yield end
+ def rest_kw(*a, kwarg: 1, &); inner(&) end
+ def kw(kwarg: 1, &); inner(&) end
+ def pos_kw_kwrest(arg1, kwarg: 1, **kw, &); inner(&) end
+ def pos_rkw(arg1, kwarg1:, &); inner(&) end
+ def all(arg1, arg2, *rest, post1, post2, kw1: 1, kw2: 2, okw1:, okw2:, &); inner(&) end
+ def all_kwrest(arg1, arg2, *rest, post1, post2, kw1: 1, kw2: 2, okw1:, okw2:, **kw, &); inner(&) end
+ EOF
+
+ rest_kw { 1 }.should == 1
+ kw { 1 }.should == 1
+ pos_kw_kwrest(:a) { 1 }.should == 1
+ pos_rkw(:a, kwarg1: 3) { 1 }.should == 1
+ all(:a, :b, :c, :d, :e, okw1: 'x', okw2: 'y') { 1 }.should == 1
+ all_kwrest(:a, :b, :c, :d, :e, okw1: 'x', okw2: 'y') { 1 }.should == 1
+ end
+end
+
+describe "`it` calls without arguments in a block with no ordinary parameters" do
+ ruby_version_is "3.3"..."3.4" do
+ it "emits a deprecation warning" do
+ -> {
+ eval "proc { it }"
+ }.should complain(/warning: `it` calls without arguments will refer to the first block param in Ruby 3.4; use it\(\) or self.it/)
end
- it "requires the anonymous block parameter to be declared if directly passing a block" do
- -> { eval "def a; b(&); end; def b; end" }.should raise_error(SyntaxError)
+ it "emits a deprecation warning if numbered parameters are used" do
+ -> {
+ eval "proc { it; _1 }"
+ }.should complain(/warning: `it` calls without arguments will refer to the first block param in Ruby 3.4; use it\(\) or self.it/)
end
- it "works when it's the only declared parameter" do
- eval <<-EOF
- def inner; yield end
- def block_only(&); inner(&) end
- EOF
+ it "does not emit a deprecation warning when a block has parameters" do
+ -> { eval "proc { |a, b| it }" }.should_not complain
+ -> { eval "proc { |*rest| it }" }.should_not complain
+ -> { eval "proc { |*| it }" }.should_not complain
+ -> { eval "proc { |a:, b:| it }" }.should_not complain
+ -> { eval "proc { |**kw| it }" }.should_not complain
+ -> { eval "proc { |**| it }" }.should_not complain
+ -> { eval "proc { |&block| it }" }.should_not complain
+ -> { eval "proc { |&| it }" }.should_not complain
+ -> { eval "proc { || it }" }.should_not complain
+ end
- block_only { 1 }.should == 1
+ it "does not emit a deprecation warning when `it` calls with arguments" do
+ -> { eval "proc { it(42) }" }.should_not complain
+ -> { eval "proc { it 42 }" }.should_not complain
end
- it "works alongside positional parameters" do
- eval <<-EOF
- def inner; yield end
- def pos(arg1, &); inner(&) end
- EOF
+ it "does not emit a deprecation warning when `it` calls with a block" do
+ -> { eval "proc { it {} }" }.should_not complain
+ end
- pos(:a) { 1 }.should == 1
+ it "does not emit a deprecation warning when a local variable inside the block named `it` exists" do
+ -> { eval "proc { it = 42; it }" }.should_not complain
end
- it "works alongside positional arguments and splatted keyword arguments" do
- eval <<-EOF
- def inner; yield end
- def pos_kwrest(arg1, **kw, &); inner(&) end
- EOF
+ it "does not emit a deprecation warning when `it` calls with explicit empty arguments list" do
+ -> { eval "proc { it() }" }.should_not complain
+ end
- pos_kwrest(:a, arg: 3) { 1 }.should == 1
+ it "calls the method `it` if defined" do
+ o = Object.new
+ def o.it
+ 21
+ end
+ suppress_warning do
+ o.instance_eval("proc { it * 2 }").call(1).should == 42
+ end
end
+ end
- it "works alongside positional arguments and disallowed keyword arguments" do
- eval <<-EOF
- def inner; yield end
- def no_kw(arg1, **nil, &); inner(&) end
- EOF
+ ruby_version_is "3.4" do
+ it "does not emit a deprecation warning" do
+ -> {
+ eval "proc { it }"
+ }.should_not complain
+ end
- no_kw(:a) { 1 }.should == 1
+ it "acts as the first argument if no local variables exist" do
+ eval("proc { it * 2 }").call(5).should == 10
+ end
+
+ it "can be reassigned to act as a local variable" do
+ eval("proc { tmp = it; it = tmp * 2; it }").call(21).should == 42
+ end
+
+ it "can be used in nested calls" do
+ eval("proc { it.map { it * 2 } }").call([1, 2, 3]).should == [2, 4, 6]
end
- end
- ruby_version_is "3.2" do
- it "works alongside explicit keyword arguments" do
- eval <<-EOF
- def inner; yield end
- def rest_kw(*a, kwarg: 1, &); inner(&) end
- def kw(kwarg: 1, &); inner(&) end
- def pos_kw_kwrest(arg1, kwarg: 1, **kw, &); inner(&) end
- def pos_rkw(arg1, kwarg1:, &); inner(&) end
- def all(arg1, arg2, *rest, post1, post2, kw1: 1, kw2: 2, okw1:, okw2:, &); inner(&) end
- def all_kwrest(arg1, arg2, *rest, post1, post2, kw1: 1, kw2: 2, okw1:, okw2:, **kw, &); inner(&) end
- EOF
-
- rest_kw { 1 }.should == 1
- kw { 1 }.should == 1
- pos_kw_kwrest(:a) { 1 }.should == 1
- pos_rkw(:a, kwarg1: 3) { 1 }.should == 1
- all(:a, :b, :c, :d, :e, okw1: 'x', okw2: 'y') { 1 }.should == 1
- all_kwrest(:a, :b, :c, :d, :e, okw1: 'x', okw2: 'y') { 1 }.should == 1
+ it "cannot be mixed with numbered parameters" do
+ -> {
+ eval "proc { it + _1 }"
+ }.should raise_error(SyntaxError, /numbered parameters are not allowed when 'it' is already used|'it' is already used in/)
+
+ -> {
+ eval "proc { _1 + it }"
+ }.should raise_error(SyntaxError, /numbered parameter is already used in|'it' is not allowed when a numbered parameter is already used/)
end
end
end
+
+describe "if `it` is defined as a variable" do
+ it "treats `it` as a captured variable if defined outside of a block" do
+ it = 5
+ proc { it }.call(0).should == 5
+ end
+
+ it "treats `it` as a local variable if defined inside of a block" do
+ proc { it = 5; it }.call(0).should == 5
+ end
+end
diff --git a/spec/ruby/language/case_spec.rb b/spec/ruby/language/case_spec.rb
index d289eca037..464d06e46a 100644
--- a/spec/ruby/language/case_spec.rb
+++ b/spec/ruby/language/case_spec.rb
@@ -427,7 +427,7 @@ describe "The 'case'-construct" do
:bar
end
RUBY
- }.should complain(/warning: duplicated .when' clause with line \d+ is ignored/, verbose: true)
+ }.should complain(/warning: (duplicated .when' clause with line \d+ is ignored|'when' clause on line \d+ duplicates 'when' clause on line \d+ and is ignored)/, verbose: true)
end
end
diff --git a/spec/ruby/language/class_spec.rb b/spec/ruby/language/class_spec.rb
index eab3cd0651..6fb785fd56 100644
--- a/spec/ruby/language/class_spec.rb
+++ b/spec/ruby/language/class_spec.rb
@@ -46,7 +46,14 @@ describe "A class definition" do
-> {
class ClassSpecsNumber
end
- }.should raise_error(TypeError)
+ }.should raise_error(TypeError, /\AClassSpecsNumber is not a class/)
+ end
+
+ it "raises TypeError if constant given as class name exists and is a Module but not a Class" do
+ -> {
+ class ClassSpecs
+ end
+ }.should raise_error(TypeError, /\AClassSpecs is not a class/)
end
# test case known to be detecting bugs (JRuby, MRI)
@@ -271,6 +278,8 @@ describe "A class definition" do
AnonWithConstant.name.should == 'AnonWithConstant'
klass.get_class_name.should == 'AnonWithConstant'
+ ensure
+ Object.send(:remove_const, :AnonWithConstant)
end
end
end
@@ -344,6 +353,39 @@ describe "Reopening a class" do
ClassSpecs::M.m.should == 1
ClassSpecs::L.singleton_class.send(:remove_method, :m)
end
+
+ it "does not reopen a class included in Object" do
+ ruby_exe(<<~RUBY).should == "false"
+ module IncludedInObject
+ class IncludedClass
+ end
+ end
+ class Object
+ include IncludedInObject
+ end
+ class IncludedClass
+ end
+ print IncludedInObject::IncludedClass == Object::IncludedClass
+ RUBY
+ end
+
+ it "does not reopen a class included in non-Object modules" do
+ ruby_exe(<<~RUBY).should == "false/false"
+ module Included
+ module IncludedClass; end
+ end
+ module M
+ include Included
+ module IncludedClass; end
+ end
+ class C
+ include Included
+ module IncludedClass; end
+ end
+ print Included::IncludedClass == M::IncludedClass, "/",
+ Included::IncludedClass == C::IncludedClass
+ RUBY
+ end
end
describe "class provides hooks" do
diff --git a/spec/ruby/language/constants_spec.rb b/spec/ruby/language/constants_spec.rb
index 08c534487e..063c52c422 100644
--- a/spec/ruby/language/constants_spec.rb
+++ b/spec/ruby/language/constants_spec.rb
@@ -72,39 +72,60 @@ describe "Literal (A::X) constant resolution" do
ConstantSpecs::ModuleA::CS_CONST101 = :const101_5
ConstantSpecs::ModuleA::CS_CONST101.should == :const101_5
+ ensure
+ ConstantSpecs::ClassB.send(:remove_const, :CS_CONST101)
+ ConstantSpecs::ParentB.send(:remove_const, :CS_CONST101)
+ ConstantSpecs::ContainerB.send(:remove_const, :CS_CONST101)
+ ConstantSpecs::ContainerB::ChildB.send(:remove_const, :CS_CONST101)
+ ConstantSpecs::ModuleA.send(:remove_const, :CS_CONST101)
end
it "searches a module included in the immediate class before the superclass" do
ConstantSpecs::ParentB::CS_CONST102 = :const102_1
ConstantSpecs::ModuleF::CS_CONST102 = :const102_2
ConstantSpecs::ContainerB::ChildB::CS_CONST102.should == :const102_2
+ ensure
+ ConstantSpecs::ParentB.send(:remove_const, :CS_CONST102)
+ ConstantSpecs::ModuleF.send(:remove_const, :CS_CONST102)
end
it "searches the superclass before a module included in the superclass" do
ConstantSpecs::ModuleE::CS_CONST103 = :const103_1
ConstantSpecs::ParentB::CS_CONST103 = :const103_2
ConstantSpecs::ContainerB::ChildB::CS_CONST103.should == :const103_2
+ ensure
+ ConstantSpecs::ModuleE.send(:remove_const, :CS_CONST103)
+ ConstantSpecs::ParentB.send(:remove_const, :CS_CONST103)
end
it "searches a module included in the superclass" do
ConstantSpecs::ModuleA::CS_CONST104 = :const104_1
ConstantSpecs::ModuleE::CS_CONST104 = :const104_2
ConstantSpecs::ContainerB::ChildB::CS_CONST104.should == :const104_2
+ ensure
+ ConstantSpecs::ModuleA.send(:remove_const, :CS_CONST104)
+ ConstantSpecs::ModuleE.send(:remove_const, :CS_CONST104)
end
it "searches the superclass chain" do
ConstantSpecs::ModuleA::CS_CONST105 = :const105
ConstantSpecs::ContainerB::ChildB::CS_CONST105.should == :const105
+ ensure
+ ConstantSpecs::ModuleA.send(:remove_const, :CS_CONST105)
end
it "searches Object if no class or module qualifier is given" do
CS_CONST106 = :const106
CS_CONST106.should == :const106
+ ensure
+ Object.send(:remove_const, :CS_CONST106)
end
it "searches Object if a toplevel qualifier (::X) is given" do
::CS_CONST107 = :const107
::CS_CONST107.should == :const107
+ ensure
+ Object.send(:remove_const, :CS_CONST107)
end
it "does not search the singleton class of the class or module" do
@@ -123,6 +144,9 @@ describe "Literal (A::X) constant resolution" do
end
-> { ConstantSpecs::CS_CONST108 }.should raise_error(NameError)
+ ensure
+ ConstantSpecs::ContainerB::ChildB.singleton_class.send(:remove_const, :CS_CONST108)
+ ConstantSpecs.singleton_class.send(:remove_const, :CS_CONST108)
end
it "returns the updated value when a constant is reassigned" do
@@ -133,36 +157,20 @@ describe "Literal (A::X) constant resolution" do
ConstantSpecs::ClassB::CS_CONST109 = :const109_2
}.should complain(/already initialized constant/)
ConstantSpecs::ClassB::CS_CONST109.should == :const109_2
+ ensure
+ ConstantSpecs::ClassB.send(:remove_const, :CS_CONST109)
end
- ruby_version_is "3.2" do
- it "evaluates left-to-right" do
- mod = Module.new
+ it "evaluates left-to-right" do
+ mod = Module.new
- mod.module_eval <<-EOC
- order = []
- ConstantSpecsRHS = Module.new
- (order << :lhs; ConstantSpecsRHS)::B = (order << :rhs)
- EOC
+ mod.module_eval <<-EOC
+ order = []
+ ConstantSpecsRHS = Module.new
+ (order << :lhs; ConstantSpecsRHS)::B = (order << :rhs)
+ EOC
- mod::ConstantSpecsRHS::B.should == [:lhs, :rhs]
- end
- end
-
- ruby_version_is ""..."3.2" do
- it "evaluates the right hand side before evaluating a constant path" do
- mod = Module.new
-
- mod.module_eval <<-EOC
- ConstantSpecsRHS::B = begin
- module ConstantSpecsRHS; end
-
- "hello"
- end
- EOC
-
- mod::ConstantSpecsRHS::B.should == 'hello'
- end
+ mod::ConstantSpecsRHS::B.should == [:lhs, :rhs]
end
end
@@ -292,6 +300,12 @@ describe "Constant resolution within methods" do
ConstantSpecs::ClassB.new.const201.should == :const201_2
ConstantSpecs::ParentB.new.const201.should == :const201_3
ConstantSpecs::ContainerB::ChildB.new.const201.should == :const201_5
+ ensure
+ ConstantSpecs::ModuleA.send(:remove_const, :CS_CONST201)
+ ConstantSpecs::ClassB.send(:remove_const, :CS_CONST201)
+ ConstantSpecs::ParentB.send(:remove_const, :CS_CONST201)
+ ConstantSpecs::ContainerB.send(:remove_const, :CS_CONST201)
+ ConstantSpecs::ContainerB::ChildB.send(:remove_const, :CS_CONST201)
end
it "searches a module included in the immediate class before the superclass" do
@@ -300,6 +314,9 @@ describe "Constant resolution within methods" do
ConstantSpecs::ContainerB::ChildB.const202.should == :const202_1
ConstantSpecs::ContainerB::ChildB.new.const202.should == :const202_1
+ ensure
+ ConstantSpecs::ParentB.send(:remove_const, :CS_CONST202)
+ ConstantSpecs::ContainerB::ChildB.send(:remove_const, :CS_CONST202)
end
it "searches the superclass before a module included in the superclass" do
@@ -308,6 +325,9 @@ describe "Constant resolution within methods" do
ConstantSpecs::ContainerB::ChildB.const203.should == :const203_1
ConstantSpecs::ContainerB::ChildB.new.const203.should == :const203_1
+ ensure
+ ConstantSpecs::ParentB.send(:remove_const, :CS_CONST203)
+ ConstantSpecs::ModuleE.send(:remove_const, :CS_CONST203)
end
it "searches a module included in the superclass" do
@@ -316,6 +336,9 @@ describe "Constant resolution within methods" do
ConstantSpecs::ContainerB::ChildB.const204.should == :const204_1
ConstantSpecs::ContainerB::ChildB.new.const204.should == :const204_1
+ ensure
+ ConstantSpecs::ModuleA.send(:remove_const, :CS_CONST204)
+ ConstantSpecs::ModuleE.send(:remove_const, :CS_CONST204)
end
it "searches the superclass chain" do
@@ -323,6 +346,8 @@ describe "Constant resolution within methods" do
ConstantSpecs::ContainerB::ChildB.const205.should == :const205
ConstantSpecs::ContainerB::ChildB.new.const205.should == :const205
+ ensure
+ ConstantSpecs::ModuleA.send(:remove_const, :CS_CONST205)
end
it "searches the lexical scope of the method not the receiver's immediate class" do
@@ -334,6 +359,9 @@ describe "Constant resolution within methods" do
end
ConstantSpecs::ContainerB::ChildB.const206.should == :const206_1
+ ensure
+ ConstantSpecs::ContainerB::ChildB.send(:remove_const, :CS_CONST206)
+ ConstantSpecs::ContainerB::ChildB.singleton_class.send(:remove_const, :CS_CONST206)
end
it "searches the lexical scope of a singleton method" do
@@ -341,12 +369,17 @@ describe "Constant resolution within methods" do
ConstantSpecs::ClassB::CS_CONST207 = :const207_2
ConstantSpecs::CS_CONST208.const207.should == :const207_1
+ ensure
+ ConstantSpecs.send(:remove_const, :CS_CONST207)
+ ConstantSpecs::ClassB.send(:remove_const, :CS_CONST207)
end
it "does not search the lexical scope of the caller" do
ConstantSpecs::ClassB::CS_CONST209 = :const209
-> { ConstantSpecs::ClassB.const209 }.should raise_error(NameError)
+ ensure
+ ConstantSpecs::ClassB.send(:remove_const, :CS_CONST209)
end
it "searches the lexical scope of a block" do
@@ -354,6 +387,9 @@ describe "Constant resolution within methods" do
ConstantSpecs::ParentB::CS_CONST210 = :const210_2
ConstantSpecs::ClassB.const210.should == :const210_1
+ ensure
+ ConstantSpecs::ClassB.send(:remove_const, :CS_CONST210)
+ ConstantSpecs::ParentB.send(:remove_const, :CS_CONST210)
end
it "searches Object as a lexical scope only if Object is explicitly opened" do
@@ -364,6 +400,11 @@ describe "Constant resolution within methods" do
Object::CS_CONST212 = :const212_2
ConstantSpecs::ParentB::CS_CONST212 = :const212_1
ConstantSpecs::ContainerB::ChildB.const212.should == :const212_1
+ ensure
+ Object.send(:remove_const, :CS_CONST211)
+ ConstantSpecs::ParentB.send(:remove_const, :CS_CONST211)
+ Object.send(:remove_const, :CS_CONST212)
+ ConstantSpecs::ParentB.send(:remove_const, :CS_CONST212)
end
it "returns the updated value when a constant is reassigned" do
@@ -376,6 +417,8 @@ describe "Constant resolution within methods" do
}.should complain(/already initialized constant/)
ConstantSpecs::ContainerB::ChildB.const213.should == :const213_2
ConstantSpecs::ContainerB::ChildB.new.const213.should == :const213_2
+ ensure
+ ConstantSpecs::ParentB.send(:remove_const, :CS_CONST213)
end
it "does not search the lexical scope of qualifying modules" do
@@ -384,6 +427,8 @@ describe "Constant resolution within methods" do
-> do
ConstantSpecs::ContainerB::ChildB.const214
end.should raise_error(NameError)
+ ensure
+ ConstantSpecs::ContainerB.send(:remove_const, :CS_CONST214)
end
end
@@ -484,6 +529,10 @@ describe "Module#private_constant marked constants" do
PrivateModule::X.should == 1
end
+ ensure
+ module ::ConstantVisibility::ModuleContainer
+ PrivateModule.send(:remove_const, :X)
+ end
end
it "can be reopened as a class where constant is not private" do
@@ -494,6 +543,10 @@ describe "Module#private_constant marked constants" do
PrivateClass::X.should == 1
end
+ ensure
+ module ::ConstantVisibility::ModuleContainer
+ PrivateClass.send(:remove_const, :X)
+ end
end
it "is not defined? with A::B form" do
@@ -565,6 +618,10 @@ describe "Module#private_constant marked constants" do
PrivateModule::X.should == 1
end
+ ensure
+ class ::ConstantVisibility::ClassContainer
+ PrivateModule.send(:remove_const, :X)
+ end
end
it "can be reopened as a class where constant is not private" do
@@ -575,6 +632,10 @@ describe "Module#private_constant marked constants" do
PrivateClass::X.should == 1
end
+ ensure
+ class ::ConstantVisibility::ClassContainer
+ PrivateClass.send(:remove_const, :X)
+ end
end
it "is not defined? with A::B form" do
diff --git a/spec/ruby/language/def_spec.rb b/spec/ruby/language/def_spec.rb
index 42e721c68c..0cf1790791 100644
--- a/spec/ruby/language/def_spec.rb
+++ b/spec/ruby/language/def_spec.rb
@@ -97,7 +97,8 @@ describe "An instance method" do
def foo; end
end
}.should raise_error(FrozenError) { |e|
- e.message.should.start_with? "can't modify frozen module"
+ msg_class = ruby_version_is("4.0") ? "Module" : "module"
+ e.message.should == "can't modify frozen #{msg_class}: #{e.receiver}"
}
-> {
@@ -106,7 +107,8 @@ describe "An instance method" do
def foo; end
end
}.should raise_error(FrozenError){ |e|
- e.message.should.start_with? "can't modify frozen class"
+ msg_class = ruby_version_is("4.0") ? "Class" : "class"
+ e.message.should == "can't modify frozen #{msg_class}: #{e.receiver}"
}
end
end
@@ -197,15 +199,25 @@ describe "An instance method with a default argument" do
foo(2,3,3).should == [2,3,[3]]
end
- it "raises a SyntaxError when there is an existing method with the same name as the local variable" do
- def bar
- 1
+ ruby_version_is ""..."3.4" do
+ it "raises a SyntaxError if using the argument in its default value" do
+ -> {
+ eval "def foo(bar = bar)
+ bar
+ end"
+ }.should raise_error(SyntaxError)
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "is nil if using the argument in its default value" do
+ -> {
+ eval "def foo(bar = bar)
+ bar
+ end
+ foo"
+ }.call.should == nil
end
- -> {
- eval "def foo(bar = bar)
- bar
- end"
- }.should raise_error(SyntaxError)
end
it "calls a method with the same name as the local when explicitly using ()" do
@@ -273,20 +285,21 @@ describe "A singleton method definition" do
it "raises FrozenError with the correct class name" do
obj = Object.new
obj.freeze
- -> { def obj.foo; end }.should raise_error(FrozenError){ |e|
- e.message.should.start_with? "can't modify frozen object"
- }
+ msg_class = ruby_version_is("4.0") ? "Object" : "object"
+ -> { def obj.foo; end }.should raise_error(FrozenError, "can't modify frozen #{msg_class}: #{obj}")
+ obj = Object.new
c = obj.singleton_class
- -> { def c.foo; end }.should raise_error(FrozenError){ |e|
- e.message.should.start_with? "can't modify frozen Class"
- }
+ c.singleton_class.freeze
+ -> { def c.foo; end }.should raise_error(FrozenError, "can't modify frozen Class: #{c}")
+
+ c = Class.new
+ c.freeze
+ -> { def c.foo; end }.should raise_error(FrozenError, "can't modify frozen Class: #{c}")
m = Module.new
m.freeze
- -> { def m.foo; end }.should raise_error(FrozenError){ |e|
- e.message.should.start_with? "can't modify frozen Module"
- }
+ -> { def m.foo; end }.should raise_error(FrozenError, "can't modify frozen Module: #{m}")
end
end
@@ -514,6 +527,8 @@ describe "A nested method definition" do
obj = DefSpecNested.new
obj.inherited_method.should == obj
+ ensure
+ DefSpecNested.send(:remove_const, :TARGET)
end
# See http://yugui.jp/articles/846#label-3
@@ -535,6 +550,8 @@ describe "A nested method definition" do
DefSpecNested.should_not have_instance_method :arg_method
DefSpecNested.should_not have_instance_method :body_method
+ ensure
+ DefSpecNested.send(:remove_const, :OBJ)
end
it "creates an instance method inside Class.new" do
diff --git a/spec/ruby/language/defined_spec.rb b/spec/ruby/language/defined_spec.rb
index 34408c0190..80ad1818b1 100644
--- a/spec/ruby/language/defined_spec.rb
+++ b/spec/ruby/language/defined_spec.rb
@@ -900,6 +900,10 @@ describe "The defined? keyword for a scoped constant" do
defined?(DefinedSpecs::Undefined).should be_nil
end
+ it "returns nil when the constant is not defined and the outer module implements .const_missing" do
+ defined?(DefinedSpecs::ModuleWithConstMissing::Undefined).should be_nil
+ end
+
it "does not call .const_missing if the constant is not defined" do
DefinedSpecs.should_not_receive(:const_missing)
defined?(DefinedSpecs::UnknownChild).should be_nil
diff --git a/spec/ruby/language/delegation_spec.rb b/spec/ruby/language/delegation_spec.rb
index d780506421..c711a536c2 100644
--- a/spec/ruby/language/delegation_spec.rb
+++ b/spec/ruby/language/delegation_spec.rb
@@ -1,6 +1,7 @@
require_relative '../spec_helper'
require_relative 'fixtures/delegation'
+# Forwarding anonymous parameters
describe "delegation with def(...)" do
it "delegates rest and kwargs" do
a = Class.new(DelegationSpecs::Target)
@@ -10,10 +11,10 @@ describe "delegation with def(...)" do
end
RUBY
- a.new.delegate(1, b: 2).should == [[1], {b: 2}]
+ a.new.delegate(1, b: 2).should == [[1], {b: 2}, nil]
end
- it "delegates block" do
+ it "delegates a block literal" do
a = Class.new(DelegationSpecs::Target)
a.class_eval(<<-RUBY)
def delegate_block(...)
@@ -24,6 +25,18 @@ describe "delegation with def(...)" do
a.new.delegate_block(1, b: 2) { |x| x }.should == [{b: 2}, [1]]
end
+ it "delegates a block argument" do
+ a = Class.new(DelegationSpecs::Target)
+ a.class_eval(<<-RUBY)
+ def delegate(...)
+ target(...)
+ end
+ RUBY
+
+ block = proc {}
+ a.new.delegate(1, b: 2, &block).should == [[1], {b: 2}, block]
+ end
+
it "parses as open endless Range when brackets are omitted" do
a = Class.new(DelegationSpecs::Target)
suppress_warning do
@@ -34,7 +47,7 @@ describe "delegation with def(...)" do
RUBY
end
- a.new.delegate(1, b: 2).should == Range.new([[], {}], nil, true)
+ a.new.delegate(1, b: 2).should == Range.new([[], {}, nil], nil, true)
end
end
@@ -47,10 +60,10 @@ describe "delegation with def(x, ...)" do
end
RUBY
- a.new.delegate(0, 1, b: 2).should == [[1], {b: 2}]
+ a.new.delegate(0, 1, b: 2).should == [[1], {b: 2}, nil]
end
- it "delegates block" do
+ it "delegates a block literal" do
a = Class.new(DelegationSpecs::Target)
a.class_eval(<<-RUBY)
def delegate_block(x, ...)
@@ -60,34 +73,86 @@ describe "delegation with def(x, ...)" do
a.new.delegate_block(0, 1, b: 2) { |x| x }.should == [{b: 2}, [1]]
end
-end
-ruby_version_is "3.2" do
- describe "delegation with def(*)" do
- it "delegates rest" do
- a = Class.new(DelegationSpecs::Target)
- a.class_eval(<<-RUBY)
- def delegate(*)
- target(*)
+ it "delegates a block argument" do
+ a = Class.new(DelegationSpecs::Target)
+ a.class_eval(<<-RUBY)
+ def delegate(...)
+ target(...)
end
RUBY
- a.new.delegate(0, 1).should == [[0, 1], {}]
+ block = proc {}
+ a.new.delegate(1, b: 2, &block).should == [[1], {b: 2}, block]
+ end
+end
+
+describe "delegation with def(*)" do
+ it "delegates rest" do
+ a = Class.new(DelegationSpecs::Target)
+ a.class_eval(<<-RUBY)
+ def delegate(*)
+ target(*)
+ end
+ RUBY
+
+ a.new.delegate(0, 1).should == [[0, 1], {}, nil]
+ end
+
+ ruby_version_is "3.3" do
+ context "within a block that accepts anonymous rest within a method that accepts anonymous rest" do
+ it "does not allow delegating rest" do
+ -> {
+ eval "def m(*); proc { |*| n(*) } end"
+ }.should raise_error(SyntaxError, /anonymous rest parameter is also used within block/)
+ end
end
end
end
-ruby_version_is "3.2" do
- describe "delegation with def(**)" do
- it "delegates kwargs" do
- a = Class.new(DelegationSpecs::Target)
- a.class_eval(<<-RUBY)
- def delegate(**)
- target(**)
+describe "delegation with def(**)" do
+ it "delegates kwargs" do
+ a = Class.new(DelegationSpecs::Target)
+ a.class_eval(<<-RUBY)
+ def delegate(**)
+ target(**)
+ end
+ RUBY
+
+ a.new.delegate(a: 1) { |x| x }.should == [[], {a: 1}, nil]
+ end
+
+ ruby_version_is "3.3" do
+ context "within a block that accepts anonymous kwargs within a method that accepts anonymous kwargs" do
+ it "does not allow delegating kwargs" do
+ -> {
+ eval "def m(**); proc { |**| n(**) } end"
+ }.should raise_error(SyntaxError, /anonymous keyword rest parameter is also used within block/)
end
+ end
+ end
+end
+
+describe "delegation with def(&)" do
+ it "delegates an anonymous block parameter" do
+ a = Class.new(DelegationSpecs::Target)
+ a.class_eval(<<-RUBY)
+ def delegate(&)
+ target(&)
+ end
RUBY
- a.new.delegate(a: 1) { |x| x }.should == [[], {a: 1}]
+ block = proc {}
+ a.new.delegate(&block).should == [[], {}, block]
+ end
+
+ ruby_version_is "3.3" do
+ context "within a block that accepts anonymous block within a method that accepts anonymous block" do
+ it "does not allow delegating a block" do
+ -> {
+ eval "def m(&); proc { |&| n(&) } end"
+ }.should raise_error(SyntaxError, /anonymous block parameter is also used within block/)
+ end
end
end
end
diff --git a/spec/ruby/language/ensure_spec.rb b/spec/ruby/language/ensure_spec.rb
index 16e626b4d0..b76292c007 100644
--- a/spec/ruby/language/ensure_spec.rb
+++ b/spec/ruby/language/ensure_spec.rb
@@ -339,10 +339,8 @@ describe "An ensure block inside 'do end' block" do
end
end
line = __LINE__
- foo.should == [
- "#{__FILE__}:#{line-3}:in 'foo'",
- "#{__FILE__}:#{line+1}:in 'block (3 levels) in <top (required)>'"
- ]
+ foo[0].should =~ /#{__FILE__}:#{line-3}:in 'foo'/
+ foo[1].should =~ /#{__FILE__}:#{line+2}:in 'block/
end
end
end
diff --git a/spec/ruby/language/fixtures/class_with_class_variable.rb b/spec/ruby/language/fixtures/class_with_class_variable.rb
new file mode 100644
index 0000000000..0b07f16d30
--- /dev/null
+++ b/spec/ruby/language/fixtures/class_with_class_variable.rb
@@ -0,0 +1,9 @@
+module StringSpecs
+ class ClassWithClassVariable
+ @@a = "xxx"
+
+ def foo
+ "#@@a"
+ end
+ end
+end
diff --git a/spec/ruby/language/fixtures/defined.rb b/spec/ruby/language/fixtures/defined.rb
index a9552619bf..3761cfa5bd 100644
--- a/spec/ruby/language/fixtures/defined.rb
+++ b/spec/ruby/language/fixtures/defined.rb
@@ -285,6 +285,12 @@ module DefinedSpecs
end
end
+ module ModuleWithConstMissing
+ def self.const_missing(const)
+ const
+ end
+ end
+
class SuperWithIntermediateModules
include IntermediateModule1
include IntermediateModule2
diff --git a/spec/ruby/language/fixtures/delegation.rb b/spec/ruby/language/fixtures/delegation.rb
index 527d928390..da2b024791 100644
--- a/spec/ruby/language/fixtures/delegation.rb
+++ b/spec/ruby/language/fixtures/delegation.rb
@@ -1,7 +1,7 @@
module DelegationSpecs
class Target
- def target(*args, **kwargs)
- [args, kwargs]
+ def target(*args, **kwargs, &block)
+ [args, kwargs, block]
end
def target_block(*args, **kwargs)
diff --git a/spec/ruby/language/fixtures/module.rb b/spec/ruby/language/fixtures/module.rb
index 33d323846e..75eee77791 100644
--- a/spec/ruby/language/fixtures/module.rb
+++ b/spec/ruby/language/fixtures/module.rb
@@ -12,13 +12,4 @@ module ModuleSpecs
module Anonymous
end
-
- module IncludedInObject
- module IncludedModuleSpecs
- end
- end
-end
-
-class Object
- include ModuleSpecs::IncludedInObject
end
diff --git a/spec/ruby/language/fixtures/private.rb b/spec/ruby/language/fixtures/private.rb
index 96f73cea3f..da3e0a97f9 100644
--- a/spec/ruby/language/fixtures/private.rb
+++ b/spec/ruby/language/fixtures/private.rb
@@ -43,17 +43,17 @@ module Private
end
end
- class E
- include D
- end
-
- class G
- def foo
- "foo"
- end
- end
-
- class H < A
- private :foo
- end
+ class E
+ include D
+ end
+
+ class G
+ def foo
+ "foo"
+ end
+ end
+
+ class H < A
+ private :foo
+ end
end
diff --git a/spec/ruby/language/fixtures/send.rb b/spec/ruby/language/fixtures/send.rb
index 918241e171..4787abee5c 100644
--- a/spec/ruby/language/fixtures/send.rb
+++ b/spec/ruby/language/fixtures/send.rb
@@ -43,9 +43,9 @@ module LangSendSpecs
attr_writer :foo
private :foo=
- def call_self_foo_equals(value)
- self.foo = value
- end
+ def call_self_foo_equals(value)
+ self.foo = value
+ end
def call_self_foo_equals_masgn(value)
a, self.foo = 1, value
@@ -81,6 +81,16 @@ module LangSendSpecs
end
end
+ class RawToProc
+ def initialize(to_proc)
+ @to_proc = to_proc
+ end
+
+ def to_proc
+ @to_proc
+ end
+ end
+
class ToAry
def initialize(obj)
@obj = obj
diff --git a/spec/ruby/language/for_spec.rb b/spec/ruby/language/for_spec.rb
index 0ad5ea88af..b8ddfe5f0d 100644
--- a/spec/ruby/language/for_spec.rb
+++ b/spec/ruby/language/for_spec.rb
@@ -19,6 +19,27 @@ describe "The for expression" do
end
end
+ it "iterates over a list of arrays and destructures with an empty splat" do
+ for i, * in [[1,2]]
+ i.should == 1
+ end
+ end
+
+ it "iterates over a list of arrays and destructures with a splat" do
+ for i, *j in [[1,2]]
+ i.should == 1
+ j.should == [2]
+ end
+ end
+
+ it "iterates over a list of arrays and destructures with a splat and additional targets" do
+ for i, *j, k in [[1,2,3,4]]
+ i.should == 1
+ j.should == [2,3]
+ k.should == 4
+ end
+ end
+
it "iterates over an Hash passing each key-value pair to the block" do
k = 0
l = 0
@@ -81,6 +102,88 @@ describe "The for expression" do
end
end
+ it "allows a global variable as an iterator name" do
+ old_global_var = $var
+ m = [1,2,3]
+ n = 0
+ for $var in m
+ n += 1
+ end
+ $var.should == 3
+ n.should == 3
+ $var = old_global_var
+ end
+
+ it "allows an attribute as an iterator name" do
+ class OFor
+ attr_accessor :target
+ end
+
+ ofor = OFor.new
+ m = [1,2,3]
+ n = 0
+ for ofor.target in m
+ n += 1
+ end
+ ofor.target.should == 3
+ n.should == 3
+ end
+
+ # Segfault in MRI 3.3 and lower: https://bugs.ruby-lang.org/issues/20468
+ ruby_bug "#20468", ""..."3.4" do
+ it "allows an attribute with safe navigation as an iterator name" do
+ class OFor
+ attr_accessor :target
+ end
+
+ ofor = OFor.new
+ m = [1,2,3]
+ n = 0
+ eval <<~RUBY
+ for ofor&.target in m
+ n += 1
+ end
+ RUBY
+ ofor.target.should == 3
+ n.should == 3
+ end
+
+ it "allows an attribute with safe navigation on a nil base as an iterator name" do
+ ofor = nil
+ m = [1,2,3]
+ n = 0
+ eval <<~RUBY
+ for ofor&.target in m
+ n += 1
+ end
+ RUBY
+ ofor.should be_nil
+ n.should == 3
+ end
+ end
+
+ it "allows an array index writer as an iterator name" do
+ arr = [:a, :b, :c]
+ m = [1,2,3]
+ n = 0
+ for arr[1] in m
+ n += 1
+ end
+ arr.should == [:a, 3, :c]
+ n.should == 3
+ end
+
+ it "allows a hash index writer as an iterator name" do
+ hash = { a: 10, b: 20, c: 30 }
+ m = [1,2,3]
+ n = 0
+ for hash[:b] in m
+ n += 1
+ end
+ hash.should == { a: 10, b: 3, c: 30 }
+ n.should == 3
+ end
+
# 1.9 behaviour verified by nobu in
# http://redmine.ruby-lang.org/issues/show/2053
it "yields only as many values as there are arguments" do
diff --git a/spec/ruby/language/hash_spec.rb b/spec/ruby/language/hash_spec.rb
index 068ac0f39c..668716e2e3 100644
--- a/spec/ruby/language/hash_spec.rb
+++ b/spec/ruby/language/hash_spec.rb
@@ -60,14 +60,12 @@ describe "Hash literal" do
@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
+ 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
it "accepts a hanging comma" do
@@ -77,9 +75,9 @@ describe "Hash literal" do
end
it "recognizes '=' at the end of the key" do
- eval("{:a==>1}").should == {:"a=" => 1}
- eval("{:a= =>1}").should == {:"a=" => 1}
- eval("{:a= => 1}").should == {:"a=" => 1}
+ {:a==>1}.should == {:"a=" => 1}
+ {:a= =>1}.should == {:"a=" => 1}
+ {:a= => 1}.should == {:"a=" => 1}
end
it "with '==>' in the middle raises SyntaxError" do
@@ -87,11 +85,11 @@ describe "Hash literal" do
end
it "recognizes '!' at the end of the key" do
- eval("{:a! =>1}").should == {:"a!" => 1}
- eval("{:a! => 1}").should == {:"a!" => 1}
+ {:a! =>1}.should == {:"a!" => 1}
+ {:a! => 1}.should == {:"a!" => 1}
- eval("{a!:1}").should == {:"a!" => 1}
- eval("{a!: 1}").should == {:"a!" => 1}
+ {a!:1}.should == {:"a!" => 1}
+ {a!: 1}.should == {:"a!" => 1}
end
it "raises a SyntaxError if there is no space between `!` and `=>`" do
@@ -99,11 +97,11 @@ describe "Hash literal" do
end
it "recognizes '?' at the end of the key" do
- eval("{:a? =>1}").should == {:"a?" => 1}
- eval("{:a? => 1}").should == {:"a?" => 1}
+ {:a? =>1}.should == {:"a?" => 1}
+ {:a? => 1}.should == {:"a?" => 1}
- eval("{a?:1}").should == {:"a?" => 1}
- eval("{a?: 1}").should == {:"a?" => 1}
+ {a?:1}.should == {:"a?" => 1}
+ {a?: 1}.should == {:"a?" => 1}
end
it "raises a SyntaxError if there is no space between `?` and `=>`" do
@@ -129,7 +127,7 @@ describe "Hash literal" do
it "accepts mixed 'key: value', 'key => value' and '\"key\"': value' syntax" do
h = {:a => 1, :b => 2, "c" => 3, :d => 4}
- eval('{a: 1, :b => 2, "c" => 3, "d": 4}').should == h
+ {a: 1, :b => 2, "c" => 3, "d": 4}.should == h
end
it "expands an '**{}' element into the containing Hash literal initialization" do
@@ -151,6 +149,26 @@ describe "Hash literal" do
{a: 1, **h, c: 4}.should == {a: 1, b: 2, c: 4}
end
+ ruby_version_is ""..."3.4" do
+ it "does not expand nil using ** into {} and raises TypeError" do
+ h = nil
+ -> { {a: 1, **h} }.should raise_error(TypeError, "no implicit conversion of nil into Hash")
+
+ -> { {a: 1, **nil} }.should raise_error(TypeError, "no implicit conversion of nil into Hash")
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "expands nil using ** into {}" do
+ h = nil
+ {**h}.should == {}
+ {a: 1, **h}.should == {a: 1}
+
+ {**nil}.should == {}
+ {a: 1, **nil}.should == {a: 1}
+ end
+ end
+
it "expands an '**{}' or '**obj' element with the last key/value pair taking precedence" do
-> {
@h = eval "{a: 1, **{a: 2, b: 3, c: 1}, c: 3}"
@@ -259,50 +277,48 @@ describe "The ** operator" do
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
+ describe "hash with omitted value" do
+ it "accepts short notation 'key' for 'key: value' syntax" do
+ a, b, c = 1, 2, 3
+ h = {a:}
+ {a: 1}.should == h
+ h = {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 "ignores hanging comma on short notation" do
+ a, b, c = 1, 2, 3
+ h = {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 "accepts mixed syntax" do
+ a, e = 1, 5
+ h = {a:, b: 2, "c" => 3, :d => 4, e:}
+ {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
+ 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
+ def foo(val)
+ {bar:, val:}
+ end
+ RUBY
- a.new.foo(1).should == {bar: "baz", val: 1}
- end
+ a.new.foo(1).should == {bar: "baz", val: 1}
+ end
- it "raises a SyntaxError when the hash key ends with `!`" do
- -> { eval("{a!:}") }.should raise_error(SyntaxError, /identifier a! is not valid to get/)
- end
+ it "raises a SyntaxError when the hash key ends with `!`" do
+ -> { eval("{a!:}") }.should raise_error(SyntaxError, /identifier a! is not valid to get/)
+ end
- it "raises a SyntaxError when the hash key ends with `?`" do
- -> { eval("{a?:}") }.should raise_error(SyntaxError, /identifier a\? is not valid to get/)
- end
+ it "raises a SyntaxError when the hash key ends with `?`" do
+ -> { eval("{a?:}") }.should raise_error(SyntaxError, /identifier a\? is not valid to get/)
end
end
end
diff --git a/spec/ruby/language/heredoc_spec.rb b/spec/ruby/language/heredoc_spec.rb
index b3b160fd11..47ee9c2c51 100644
--- a/spec/ruby/language/heredoc_spec.rb
+++ b/spec/ruby/language/heredoc_spec.rb
@@ -106,4 +106,14 @@ HERE
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
+
+ it "reports line numbers inside HEREDOC with method call" do
+ -> {
+ <<-HERE.chomp
+ a
+ b
+ #{c}
+ HERE
+ }.should raise_error(NameError) { |e| e.backtrace[0].should.start_with?("#{__FILE__}:#{__LINE__ - 2}") }
+ end
end
diff --git a/spec/ruby/language/it_parameter_spec.rb b/spec/ruby/language/it_parameter_spec.rb
new file mode 100644
index 0000000000..72023180d9
--- /dev/null
+++ b/spec/ruby/language/it_parameter_spec.rb
@@ -0,0 +1,66 @@
+require_relative '../spec_helper'
+
+ruby_version_is "3.4" do
+ describe "The `it` parameter" do
+ it "provides it in a block" do
+ -> { it }.call("a").should == "a"
+ proc { it }.call("a").should == "a"
+ lambda { it }.call("a").should == "a"
+ ["a"].map { it }.should == ["a"]
+ end
+
+ it "assigns nil to not passed parameters" do
+ proc { it }.call().should == nil
+ end
+
+ it "can be used in both outer and nested blocks at the same time" do
+ -> { it + -> { it * it }.call(2) }.call(3).should == 7
+ end
+
+ it "is a regular local variable if there is already a 'it' local variable" do
+ it = 0
+ proc { it }.call("a").should == 0
+ end
+
+ it "raises SyntaxError when block parameters are specified explicitly" do
+ -> { eval("-> () { it }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
+ -> { eval("-> (x) { it }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
+
+ -> { eval("proc { || it }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
+ -> { eval("proc { |x| it }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
+
+ -> { eval("lambda { || it }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
+ -> { eval("lambda { |x| it }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
+
+ -> { eval("['a'].map { || it }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
+ -> { eval("['a'].map { |x| it }") }.should raise_error(SyntaxError, /ordinary parameter is defined/)
+ end
+
+ it "affects block arity" do
+ -> {}.arity.should == 0
+ -> { it }.arity.should == 1
+ end
+
+ it "affects block parameters" do
+ -> { it }.parameters.should == [[:req]]
+
+ ruby_version_is ""..."4.0" do
+ proc { it }.parameters.should == [[:opt, nil]]
+ end
+ ruby_version_is "4.0" do
+ proc { it }.parameters.should == [[:opt]]
+ end
+ end
+
+ it "does not affect binding local variables" do
+ -> { it; binding.local_variables }.call("a").should == []
+ end
+
+ it "does not work in methods" do
+ obj = Object.new
+ def obj.foo; it; end
+
+ -> { obj.foo("a") }.should raise_error(ArgumentError, /wrong number of arguments/)
+ end
+ end
+end
diff --git a/spec/ruby/language/keyword_arguments_spec.rb b/spec/ruby/language/keyword_arguments_spec.rb
index 8668799d26..4f6370d419 100644
--- a/spec/ruby/language/keyword_arguments_spec.rb
+++ b/spec/ruby/language/keyword_arguments_spec.rb
@@ -323,76 +323,36 @@ describe "Keyword arguments" do
m({a: 1}).should == [[{a: 1}], {}]
end
- ruby_version_is "3.1" do
- describe "omitted values" do
- it "accepts short notation 'key' for 'key: value' syntax" do
- def m(a:, b:)
- [a, b]
- end
-
- a = 1
- b = 2
-
- eval('m(a:, b:).should == [1, 2]')
- end
- end
- end
-
- ruby_version_is "3.2" do
- it "does not work with call(*ruby2_keyword_args) with missing ruby2_keywords in between" do
- class << self
- def n(*args) # Note the missing ruby2_keywords here
- target(*args)
- end
-
- ruby2_keywords def m(*args)
- n(*args)
- end
+ describe "omitted values" do
+ it "accepts short notation 'key' for 'key: value' syntax" do
+ def m(a:, b:)
+ [a, b]
end
- empty = {}
- m(**empty).should == [[], {}]
- m(empty).should == [[{}], {}]
+ a = 1
+ b = 2
- m(a: 1).should == [[{a: 1}], {}]
- m({a: 1}).should == [[{a: 1}], {}]
+ m(a:, b:).should == [1, 2]
end
end
- ruby_version_is ""..."3.2" do
- # https://bugs.ruby-lang.org/issues/18625
- it "works with call(*ruby2_keyword_args) with missing ruby2_keywords in between due to CRuby bug #18625" do
- class << self
- def n(*args) # Note the missing ruby2_keywords here
- target(*args)
- end
-
- ruby2_keywords def m(*args)
- n(*args)
- end
+ it "does not work with call(*ruby2_keyword_args) with missing ruby2_keywords in between" do
+ class << self
+ def n(*args) # Note the missing ruby2_keywords here
+ target(*args)
end
- empty = {}
- m(**empty).should == [[], {}]
- Hash.ruby2_keywords_hash?(empty).should == false
- m(empty).should == [[{}], {}]
- Hash.ruby2_keywords_hash?(empty).should == false
-
- m(a: 1).should == [[], {a: 1}]
- m({a: 1}).should == [[{a: 1}], {}]
-
- kw = {a: 1}
+ ruby2_keywords def m(*args)
+ n(*args)
+ end
+ end
- m(**kw).should == [[], {a: 1}]
- m(**kw)[1].should == kw
- m(**kw)[1].should_not.equal?(kw)
- Hash.ruby2_keywords_hash?(kw).should == false
- Hash.ruby2_keywords_hash?(m(**kw)[1]).should == false
+ empty = {}
+ m(**empty).should == [[], {}]
+ m(empty).should == [[{}], {}]
- m(kw).should == [[{a: 1}], {}]
- m(kw)[0][0].should.equal?(kw)
- Hash.ruby2_keywords_hash?(kw).should == false
- end
+ m(a: 1).should == [[{a: 1}], {}]
+ m({a: 1}).should == [[{a: 1}], {}]
end
end
diff --git a/spec/ruby/language/lambda_spec.rb b/spec/ruby/language/lambda_spec.rb
index 3ab3569ebe..ed5a1c69e8 100644
--- a/spec/ruby/language/lambda_spec.rb
+++ b/spec/ruby/language/lambda_spec.rb
@@ -263,18 +263,21 @@ describe "A lambda literal -> () { }" do
end
describe "with circular optional argument reference" do
- it "raises a SyntaxError if using an existing local with the same name as the argument" do
- a = 1
- -> {
- @proc = eval "-> (a=a) { a }"
- }.should raise_error(SyntaxError)
+ ruby_version_is ""..."3.4" do
+ it "raises a SyntaxError if using the argument in its default value" do
+ a = 1
+ -> {
+ eval "-> (a=a) { a }"
+ }.should raise_error(SyntaxError)
+ end
end
- it "raises a SyntaxError if there is an existing method with the same name as the argument" do
- def a; 1; end
- -> {
- @proc = eval "-> (a=a) { a }"
- }.should raise_error(SyntaxError)
+ ruby_version_is "3.4" do
+ it "is nil if using the argument in its default value" do
+ -> {
+ eval "-> (a=a) { a }.call"
+ }.call.should == nil
+ end
end
it "calls an existing method with the same name as the argument if explicitly using ()" do
diff --git a/spec/ruby/language/magic_comment_spec.rb b/spec/ruby/language/magic_comment_spec.rb
index f2bf3a08e5..af9c9dbfd0 100644
--- a/spec/ruby/language/magic_comment_spec.rb
+++ b/spec/ruby/language/magic_comment_spec.rb
@@ -45,7 +45,8 @@ end
describe "Magic comments" do
describe "in stdin" do
- it_behaves_like :magic_comments, :locale, -> file {
+ default = (platform_is :windows and ruby_version_is "4.0") ? :UTF8 : :locale
+ it_behaves_like :magic_comments, default, -> file {
print_at_exit = fixture(__FILE__, "print_magic_comment_result_at_exit.rb")
ruby_exe(nil, args: "< #{fixture(__FILE__, file)}", options: "-r#{print_at_exit}")
}
diff --git a/spec/ruby/language/method_spec.rb b/spec/ruby/language/method_spec.rb
index 9abe4cde20..8f72bd45ed 100644
--- a/spec/ruby/language/method_spec.rb
+++ b/spec/ruby/language/method_spec.rb
@@ -1175,6 +1175,31 @@ describe "A method" do
end
end
+context "when passing **nil into a method that accepts keyword arguments" do
+ ruby_version_is ""..."3.4" do
+ it "raises TypeError" do
+ def m(**kw) kw; end
+
+ h = nil
+ -> { m(a: 1, **h) }.should raise_error(TypeError, "no implicit conversion of nil into Hash")
+ -> { m(a: 1, **nil) }.should raise_error(TypeError, "no implicit conversion of nil into Hash")
+ end
+ end
+
+ ruby_version_is "3.4" do
+ it "expands nil using ** into {}" do
+ def m(**kw) kw; end
+
+ h = nil
+ m(**h).should == {}
+ m(a: 1, **h).should == {a: 1}
+
+ m(**nil).should == {}
+ m(a: 1, **nil).should == {a: 1}
+ end
+ end
+end
+
describe "A method call with a space between method name and parentheses" do
before(:each) do
def m(*args)
@@ -1416,53 +1441,209 @@ describe "Keyword arguments are now separated from positional arguments" do
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
+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 = call(a:)
+ h.should == {a: 1}
+ arr.should == []
+
+ arr, h = call(a:, b:, c:)
+ h.should == {a: 1, b: 2, c: 3}
+ arr.should == []
+
+ arr, h = 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
- a, b, c = 1, 2, 3
- arr, h = eval('call a:')
- h.should == {a: 1}
- arr.should == []
+ foo(1).should == [[], {bar: "baz", val: 1}]
+ end
+ end
+end
- arr, h = eval('call(a:, b:, c:)')
- h.should == {a: 1, b: 2, c: 3}
- arr.should == []
+describe "Inside 'endless' method definitions" do
+ it "allows method calls without parenthesis" do
+ def greet(person) = "Hi, ".dup.concat person
- arr, h = eval('call(a:, b: 10, c:)')
- h.should == {a: 1, b: 10, c: 3}
- arr.should == []
+ greet("Homer").should == "Hi, Homer"
+ end
+end
+
+describe "warning about not used block argument" do
+ ruby_version_is "3.4" do
+ it "warns when passing a block argument to a method that never uses it" do
+ def m_that_does_not_use_block
+ 42
end
+
+ -> {
+ m_that_does_not_use_block { }
+ }.should complain(
+ /#{__FILE__}:#{__LINE__ - 2}: warning: the block passed to 'm_that_does_not_use_block' defined at #{__FILE__}:#{__LINE__ - 7} may be ignored/,
+ verbose: true)
end
- context "with methods and local variables" do
- evaluate <<-ruby do
- def call(*args, **kwargs) = [args, kwargs]
+ it "does not warn when passing a block argument to a method that declares a block parameter" do
+ def m_with_block_parameter(&block)
+ 42
+ end
- def bar
- "baz"
- end
+ -> { m_with_block_parameter { } }.should_not complain(verbose: true)
+ end
- def foo(val)
- call bar:, val:
- end
- ruby
+ it "does not warn when passing a block argument to a method that declares an anonymous block parameter" do
+ def m_with_anonymous_block_parameter(&)
+ 42
+ end
+
+ -> { m_with_anonymous_block_parameter { } }.should_not complain(verbose: true)
+ end
- foo(1).should == [[], {bar: "baz", val: 1}]
+ it "does not warn when passing a block argument to a method that yields an implicit block parameter" do
+ def m_with_yield
+ yield 42
end
+
+ -> { m_with_yield { } }.should_not complain(verbose: true)
end
- end
- describe "Inside 'endless' method definitions" do
- it "allows method calls without parenthesis" do
- eval <<-ruby
- def greet(person) = "Hi, ".dup.concat person
- ruby
+ it "warns when passing a block argument to a method that calls #block_given?" do
+ def m_with_block_given
+ block_given?
+ end
+
+ -> {
+ m_with_block_given { }
+ }.should complain(
+ /#{__FILE__}:#{__LINE__ - 2}: warning: the block passed to 'm_with_block_given' defined at #{__FILE__}:#{__LINE__ - 7} may be ignored/,
+ verbose: true)
+ end
+
+ it "does not warn when passing a block argument to a method that calls super" do
+ parent = Class.new do
+ def m
+ end
+ end
+
+ child = Class.new(parent) do
+ def m
+ super
+ end
+ end
+
+ obj = child.new
+ -> { obj.m { } }.should_not complain(verbose: true)
+ end
+
+ it "does not warn when passing a block argument to a method that calls super(...)" do
+ parent = Class.new do
+ def m(a)
+ end
+ end
+
+ child = Class.new(parent) do
+ def m(...)
+ super(...)
+ end
+ end
+
+ obj = child.new
+ -> { obj.m(42) { } }.should_not complain(verbose: true)
+ end
+
+ it "does not warn when called #initialize()" do
+ klass = Class.new do
+ def initialize
+ end
+ end
+
+ -> { klass.new {} }.should_not complain(verbose: true)
+ end
+
+ it "does not warn when passing a block argument to a method that calls super()" do
+ parent = Class.new do
+ def m
+ end
+ end
- greet("Homer").should == "Hi, Homer"
+ child = Class.new(parent) do
+ def m
+ super()
+ end
+ end
+
+ obj = child.new
+ -> { obj.m { } }.should_not complain(verbose: true)
+ end
+
+ it "warns only once per call site" do
+ def m_that_does_not_use_block
+ 42
+ end
+
+ def call_m_that_does_not_use_block
+ m_that_does_not_use_block {}
+ end
+
+ -> {
+ m_that_does_not_use_block { }
+ }.should complain(/the block passed to 'm_that_does_not_use_block' defined at .+ may be ignored/, verbose: true)
+
+ -> {
+ m_that_does_not_use_block { }
+ }.should_not complain(verbose: true)
+ end
+
+ it "can be disabled with :strict_unused_block warning category" do
+ def m_that_does_not_use_block
+ 42
+ end
+
+ # ensure that warning is emitted
+ -> { m_that_does_not_use_block { } }.should complain(verbose: true)
+
+ warn_strict_unused_block = Warning[:strict_unused_block]
+ Warning[:strict_unused_block] = false
+ begin
+ -> { m_that_does_not_use_block { } }.should_not complain(verbose: true)
+ ensure
+ Warning[:strict_unused_block] = warn_strict_unused_block
+ end
+ end
+
+ it "can be enabled with :strict_unused_block = true warning category in not verbose mode" do
+ def m_that_does_not_use_block
+ 42
+ end
+
+ warn_strict_unused_block = Warning[:strict_unused_block]
+ Warning[:strict_unused_block] = true
+ begin
+ -> {
+ m_that_does_not_use_block { }
+ }.should complain(/the block passed to 'm_that_does_not_use_block' defined at .+ may be ignored/)
+ ensure
+ Warning[:strict_unused_block] = warn_strict_unused_block
+ end
end
end
end
diff --git a/spec/ruby/language/module_spec.rb b/spec/ruby/language/module_spec.rb
index fffcf9c90d..fba4aa8c6e 100644
--- a/spec/ruby/language/module_spec.rb
+++ b/spec/ruby/language/module_spec.rb
@@ -26,20 +26,39 @@ describe "The module keyword" do
it "reopens an existing module" do
module ModuleSpecs; Reopened = true; end
ModuleSpecs::Reopened.should be_true
- end
-
- ruby_version_is '3.2' do
- it "does not reopen a module included in Object" do
- module IncludedModuleSpecs; Reopened = true; end
- ModuleSpecs::IncludedInObject::IncludedModuleSpecs.should_not == Object::IncludedModuleSpecs
- end
- end
-
- ruby_version_is ''...'3.2' do
- it "reopens a module included in Object" do
- module IncludedModuleSpecs; Reopened = true; end
- ModuleSpecs::IncludedInObject::IncludedModuleSpecs::Reopened.should be_true
- end
+ ensure
+ ModuleSpecs.send(:remove_const, :Reopened)
+ end
+
+ it "does not reopen a module included in Object" do
+ ruby_exe(<<~RUBY).should == "false"
+ module IncludedInObject
+ module IncludedModule; end
+ end
+ class Object
+ include IncludedInObject
+ end
+ module IncludedModule; end
+ print IncludedInObject::IncludedModule == Object::IncludedModule
+ RUBY
+ end
+
+ it "does not reopen a module included in non-Object modules" do
+ ruby_exe(<<~RUBY).should == "false/false"
+ module Included
+ module IncludedModule; end
+ end
+ module M
+ include Included
+ module IncludedModule; end
+ end
+ class C
+ include Included
+ module IncludedModule; end
+ end
+ print Included::IncludedModule == M::IncludedModule, "/",
+ Included::IncludedModule == C::IncludedModule
+ RUBY
end
it "raises a TypeError if the constant is a Class" do
@@ -76,6 +95,8 @@ describe "Assigning an anonymous module to a constant" do
::ModuleSpecs_CS1 = mod
mod.name.should == "ModuleSpecs_CS1"
+ ensure
+ Object.send(:remove_const, :ModuleSpecs_CS1)
end
it "sets the name of a module scoped by an anonymous module" do
@@ -96,5 +117,7 @@ describe "Assigning an anonymous module to a constant" do
b.name.should == "ModuleSpecs_CS2::B"
c.name.should == "ModuleSpecs_CS2::B::C"
d.name.should == "ModuleSpecs_CS2::D"
+ ensure
+ Object.send(:remove_const, :ModuleSpecs_CS2)
end
end
diff --git a/spec/ruby/language/numbered_parameters_spec.rb b/spec/ruby/language/numbered_parameters_spec.rb
index 06f9948c58..de532c326d 100644
--- a/spec/ruby/language/numbered_parameters_spec.rb
+++ b/spec/ruby/language/numbered_parameters_spec.rb
@@ -90,9 +90,18 @@ describe "Numbered parameters" do
proc { _2 }.parameters.should == [[:opt, :_1], [:opt, :_2]]
end
- it "affects binding local variables" do
- -> { _1; binding.local_variables }.call("a").should == [:_1]
- -> { _2; binding.local_variables }.call("a", "b").should == [:_1, :_2]
+ ruby_version_is ""..."4.0" do
+ it "affects binding local variables" do
+ -> { _1; binding.local_variables }.call("a").should == [:_1]
+ -> { _2; binding.local_variables }.call("a", "b").should == [:_1, :_2]
+ end
+ end
+
+ ruby_version_is "4.0" do
+ it "does not affect binding local variables" do
+ -> { _1; binding.local_variables }.call("a").should == []
+ -> { _2; binding.local_variables }.call("a", "b").should == []
+ end
end
it "does not work in methods" do
diff --git a/spec/ruby/language/optional_assignments_spec.rb b/spec/ruby/language/optional_assignments_spec.rb
index 2443cc6b79..5fe3e3671b 100644
--- a/spec/ruby/language/optional_assignments_spec.rb
+++ b/spec/ruby/language/optional_assignments_spec.rb
@@ -698,6 +698,8 @@ describe 'Optional constant assignment' do
x.should == 1
y.should == 0
ConstantSpecs::ClassA::NIL_OR_ASSIGNED_CONSTANT3.should == nil
+ ensure
+ ConstantSpecs::ClassA.send(:remove_const, :NIL_OR_ASSIGNED_CONSTANT3)
end
end
diff --git a/spec/ruby/language/pattern_matching_spec.rb b/spec/ruby/language/pattern_matching_spec.rb
index a8ec078cd0..c1a6f0e4d6 100644
--- a/spec/ruby/language/pattern_matching_spec.rb
+++ b/spec/ruby/language/pattern_matching_spec.rb
@@ -1,155 +1,143 @@
require_relative '../spec_helper'
describe "Pattern matching" do
- # TODO: Remove excessive eval calls when Ruby 3 is the minimum version.
- # It is best to keep the eval's longer if other Ruby impls cannot parse pattern matching yet.
-
before :each do
ScratchPad.record []
end
- describe "can be standalone assoc operator that" do
+ describe "Rightward assignment (`=>`) that can be standalone assoc operator that" do
it "deconstructs value" do
suppress_warning do
- eval(<<-RUBY).should == [0, 1]
- [0, 1] => [a, b]
- [a, b]
- RUBY
+ [0, 1] => [a, b]
+ [a, b].should == [0, 1]
end
end
it "deconstructs value and properly scopes variables" do
suppress_warning do
- eval(<<-RUBY).should == [0, nil]
- a = nil
- eval(<<-PATTERN)
- [0, 1] => [a, b]
- PATTERN
- [a, defined?(b)]
- RUBY
+ a = nil
+ 1.times {
+ [0, 1] => [a, b]
+ }
+ [a, defined?(b)].should == [0, nil]
end
end
+
+ it "can work with keywords" do
+ { a: 0, b: 1 } => { a:, b: }
+ [a, b].should == [0, 1]
+ end
+ end
+
+ describe "One-line pattern matching" do
+ it "can be used to check if a pattern matches for Array-like entities" do
+ ([0, 1] in [a, b]).should == true
+ ([0, 1] in [a, b, c]).should == false
+ end
+
+ it "can be used to check if a pattern matches for Hash-like entities" do
+ ({ a: 0, b: 1 } in { a:, b: }).should == true
+ ({ a: 0, b: 1 } in { a:, b:, c: }).should == false
+ 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
+ case [0, 1, 2, 3]
+ in [*pre, 2, 3]
+ pre
+ else
+ false
+ end.should == [0, 1]
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
+ case [0, 1, 2, 3]
+ in [0, 1, *post]
+ post
+ else
+ false
+ end.should == [2, 3]
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
+ case [0, 1, 2, 3, 4]
+ in [*pre, 2, *post]
+ [pre, post]
+ else
+ false
+ end.should == [[0, 1], [3, 4]]
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
+ case [0, 1, 2, 3, 4]
+ in [*everything]
+ everything
+ else
+ false
+ end.should == [0, 1, 2, 3, 4]
end
it "will match an empty Array-like structure" do
- eval(<<~RUBY).should == []
- case []
- in [*everything]
- everything
- else
- false
- end
- RUBY
+ case []
+ in [*everything]
+ everything
+ else
+ false
+ end.should == []
end
it "can be nested" do
- eval(<<~RUBY).should == [[0, [2, 4, 6]], [[4, 16, 64]], 27]
- case [0, [2, 4, 6], [3, 9, 27], [4, 16, 64]]
- in [*pre, [*, 9, a], *post]
- [pre, post, a]
- else
- false
- end
- RUBY
+ case [0, [2, 4, 6], [3, 9, 27], [4, 16, 64]]
+ in [*pre, [*, 9, a], *post]
+ [pre, post, a]
+ else
+ false
+ end.should == [[0, [2, 4, 6]], [[4, 16, 64]], 27]
end
it "can be nested with an array pattern" do
- eval(<<~RUBY).should == [[4, 16, 64]]
- case [0, [2, 4, 6], [3, 9, 27], [4, 16, 64]]
- in [_, _, [*, 9, *], *post]
- post
- else
- false
- end
- RUBY
+ case [0, [2, 4, 6], [3, 9, 27], [4, 16, 64]]
+ in [_, _, [*, 9, *], *post]
+ post
+ else
+ false
+ end.should == [[4, 16, 64]]
end
it "can be nested within a hash pattern" do
- eval(<<~RUBY).should == [27]
- case {a: [3, 9, 27]}
- in {a: [*, 9, *post]}
- post
- else
- false
- end
- RUBY
+ case {a: [3, 9, 27]}
+ in {a: [*, 9, *post]}
+ post
+ else
+ false
+ end.should == [27]
end
it "can nest hash and array patterns" do
- eval(<<~RUBY).should == [42, 2]
- case [0, {a: 42, b: [0, 1]}, {a: 42, b: [1, 2]}]
- in [*, {a:, b: [1, c]}, *]
- [a, c]
- else
- false
- end
- RUBY
+ case [0, {a: 42, b: [0, 1]}, {a: 42, b: [1, 2]}]
+ in [*, {a:, b: [1, c]}, *]
+ [a, c]
+ else
+ false
+ end.should == [42, 2]
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
+ case [0, 1]
+ in [0]
+ :foo
+ in [0, 1]
+ :bar
+ end.should == :bar
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
+ case [0, 1]
+ in [0] then :foo
+ in [0, 1] then :bar
+ end.should == :bar
end
describe "warning" do
@@ -176,27 +164,17 @@ describe "Pattern matching" 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
+ it "does not warn about pattern matching is experimental feature" do
+ -> { eval @src }.should_not complain
end
end
end
it "binds variables" do
- eval(<<~RUBY).should == 1
- case [0, 1]
- in [0, a]
- a
- end
- RUBY
+ case [0, 1]
+ in [0, a]
+ a
+ end.should == 1
end
it "cannot mix in and when operators" do
@@ -220,47 +198,46 @@ describe "Pattern matching" do
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
+ case [0, 1]
+ in [0]
+ :foo
+ in [0, 1]
+ :bar
+ in [0, 1]
+ :baz
+ end.should == :bar
end
it "executes else clause if no pattern matches" do
- eval(<<~RUBY).should == false
- case [0, 1]
- in [0]
- true
- else
- false
- end
- RUBY
+ case [0, 1]
+ in [0]
+ true
+ else
+ false
+ end.should == false
end
it "raises NoMatchingPatternError if no pattern matches and no else clause" do
-> {
- eval <<~RUBY
- case [0, 1]
- in [0]
- end
- RUBY
+ case [0, 1]
+ in [0]
+ end
}.should raise_error(NoMatchingPatternError, /\[0, 1\]/)
+
+ error_pattern = ruby_version_is("3.4") ? /\{a: 0, b: 1\}/ : /\{:a=>0, :b=>1\}/
+ -> {
+ case {a: 0, b: 1}
+ in a: 1, b: 1
+ end
+ }.should raise_error(NoMatchingPatternError, error_pattern)
end
it "raises NoMatchingPatternError if no pattern matches and evaluates the expression only once" do
evals = 0
-> {
- eval <<~RUBY
- case (evals += 1; [0, 1])
- in [0]
- end
- RUBY
+ case (evals += 1; [0, 1])
+ in [0]
+ end
}.should raise_error(NoMatchingPatternError, /\[0, 1\]/)
evals.should == 1
end
@@ -273,230 +250,185 @@ describe "Pattern matching" do
true
end
RUBY
- }.should raise_error(SyntaxError, /unexpected|expected a delimiter after the predicates of a `when` clause/)
+ }.should raise_error(SyntaxError, /unexpected|expected a delimiter after the patterns of an `in` clause/)
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
+ case (ScratchPad << :foo; 1)
+ in 0
+ false
+ in 1
+ true
+ end.should == true
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
+ case 0
+ in 0 if false
+ true
+ else
+ false
+ end.should == false
- eval(<<~RUBY).should == true
- case 0
- in 0 if true
- true
- else
- false
- end
- RUBY
+ case 0
+ in 0 if true
+ true
+ else
+ false
+ end.should == true
end
it "supports unless guard" do
- eval(<<~RUBY).should == false
- case 0
- in 0 unless true
- true
- else
- false
- end
- RUBY
+ case 0
+ in 0 unless true
+ true
+ else
+ false
+ end.should == false
- eval(<<~RUBY).should == true
- case 0
- in 0 unless false
- true
- else
- false
- end
- RUBY
+ case 0
+ in 0 unless false
+ true
+ else
+ false
+ end.should == true
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
+ case [0, 1]
+ in [a, 1] if a >= 0
+ true
+ end.should == true
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
+ case 0
+ in 1 if (ScratchPad << :foo) || true
+ else
+ end
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
+ case 0
+ in 0 if false
+ :foo
+ in 0 if true
+ :bar
+ end.should == :bar
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
+ case 0
+ in 0 if false
+ true
+ else
+ false
+ end.should == false
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
+ case [0, 1]
+ in [0, 1] if false
+ end
}.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
+ case 0
+ in 0
+ true
+ end.should == true
- eval(<<~RUBY).should == true
- case 0
- in (-1..1)
- true
- end
- RUBY
+ case 0
+ in (
+ -1..1)
+ true
+ end.should == true
- eval(<<~RUBY).should == true
- case 0
- in Integer
- true
- end
- RUBY
+ case 0
+ in Integer
+ true
+ end.should == true
- eval(<<~RUBY).should == true
- case "0"
- in /0/
- true
- end
- RUBY
+ case "0"
+ in /0/
+ true
+ end.should == true
- eval(<<~RUBY).should == true
- case "0"
- in ->(s) { s == "0" }
- true
- end
- RUBY
+ case "0"
+ in -> s { s == "0" }
+ true
+ end.should == true
end
it "allows string literal with interpolation" do
x = "x"
- eval(<<~RUBY).should == true
- case "x"
- in "#{x + ""}"
- true
- end
- RUBY
+ case "x"
+ in "#{x + ""}"
+ true
+ end.should == true
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
+ case 0
+ in a
+ a
+ end.should == 0
end
it "makes bounded variable visible outside a case statement scope" do
- eval(<<~RUBY).should == 0
- case 0
- in a
- end
+ case 0
+ in a
+ end
- a
- RUBY
+ a.should == 0
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
+ case 0
+ in a
+ in b
+ in c
+ end
- [a, b, c]
- RUBY
+ [a, b, c].should == [0, nil, nil]
end
it "allow using _ name to drop values" do
- eval(<<~RUBY).should == 0
- case [0, 1]
- in [a, _]
- a
- end
- RUBY
+ case [0, 1]
+ in [a, _]
+ a
+ end.should == 0
end
it "supports using _ in a pattern several times" do
- eval(<<~RUBY).should == true
- case [0, 1, 2]
- in [0, _, _]
- true
- end
- RUBY
+ case [0, 1, 2]
+ in [0, _, _]
+ true
+ end.should == true
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
+ case [0, 1, 2]
+ in [0, _x, _x]
+ true
+ end.should == true
- eval(<<~RUBY).should == true
- case {a: 0, b: 1, c: 2}
- in {a: 0, b: _x, c: _x}
- true
- end
- RUBY
+ case {a: 0, b: 1, c: 2}
+ in {a: 0, b: _x, c: _x}
+ true
+ end.should == true
end
it "does not support using variable name (except _) several times" do
@@ -512,30 +444,24 @@ describe "Pattern matching" do
it "supports existing variables in a pattern specified with ^ operator" do
a = 0
- eval(<<~RUBY).should == true
- case 0
- in ^a
- true
- end
- RUBY
+ case 0
+ in ^a
+ true
+ end.should == true
end
it "allows applying ^ operator to bound variables" do
- eval(<<~RUBY).should == 1
- case [1, 1]
- in [n, ^n]
- n
- end
- RUBY
+ case [1, 1]
+ in [n, ^n]
+ n
+ end.should == 1
- eval(<<~RUBY).should == false
- case [1, 2]
- in [n, ^n]
- true
- else
- false
- end
- RUBY
+ case [1, 2]
+ in [n, ^n]
+ true
+ else
+ false
+ end.should == false
end
it "requires bound variable to be specified in a pattern before ^ operator when it relies on a bound variable" do
@@ -554,12 +480,10 @@ describe "Pattern matching" do
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
+ case 0
+ in 0 | 1 | 2
+ true
+ end.should == true
end
it "does not support variable binding" do
@@ -569,124 +493,103 @@ describe "Pattern matching" do
in [0, 0] | [0, a]
end
RUBY
- }.should raise_error(SyntaxError, /illegal variable in alternative pattern/)
+ }.should raise_error(SyntaxError)
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
+ case [0, 1]
+ in [1, _]
+ false
+ in [0, 0] | [0, _a]
+ true
+ end.should == true
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
+ case [[1], ["2"]]
+ in [[0] | nil, _]
+ false
+ in [[1], [1]]
+ false
+ in [[1], [2 | "2"]]
+ true
+ end.should == true
- eval(<<~RUBY).should == true
- case [1, 2]
- in [0, _] | {a: 0}
- false
- in {a: 1, b: 2} | [1, 2]
- true
- end
- RUBY
+ case [1, 2]
+ in [0, _] | {a: 0}
+ false
+ in {a: 1, b: 2} | [1, 2]
+ true
+ end.should == true
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
+ case 0
+ in Integer => n
+ n
+ end.should == 0
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
+ case [1, [2, 3]]
+ in [1, Array => ary]
+ ary
+ end.should == [2, 3]
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
+ case [0, 1, 2]
+ in Array(0, 1, 2)
+ true
+ end.should == true
end
it "supports form Constant[pat, pat, ...]" do
- eval(<<~RUBY).should == true
- case [0, 1, 2]
- in Array[0, 1, 2]
- true
- end
- RUBY
+ case [0, 1, 2]
+ in Array[0, 1, 2]
+ true
+ end.should == true
end
it "supports form [pat, pat, ...]" do
- eval(<<~RUBY).should == true
- case [0, 1, 2]
- in [0, 1, 2]
- true
- end
- RUBY
+ case [0, 1, 2]
+ in [0, 1, 2]
+ true
+ end.should == true
end
it "supports form pat, pat, ..." do
- eval(<<~RUBY).should == true
- case [0, 1, 2]
- in 0, 1, 2
- true
- end
- RUBY
+ case [0, 1, 2]
+ in 0, 1, 2
+ true
+ end.should == true
- eval(<<~RUBY).should == 1
- case [0, 1, 2]
- in 0, a, 2
- a
- end
- RUBY
+ case [0, 1, 2]
+ in 0, a, 2
+ a
+ end.should == 1
- eval(<<~RUBY).should == [1, 2]
- case [0, 1, 2]
- in 0, *rest
- rest
- end
- RUBY
+ case [0, 1, 2]
+ in 0, *rest
+ rest
+ end.should == [1, 2]
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
+ def obj.deconstruct
+ [0, 1]
+ end
+
+ case obj
+ in [Integer, Integer]
+ true
+ end.should == true
end
it "calls #deconstruct once for multiple patterns, caching the result" do
@@ -697,314 +600,267 @@ describe "Pattern matching" do
[0, 1]
end
- eval(<<~RUBY).should == true
- case obj
- in [1, 2]
- false
- in [0, 1]
- true
- end
- RUBY
+ case obj
+ in [1, 2]
+ false
+ in [0, 1]
+ true
+ end.should == true
ScratchPad.recorded.should == [:deconstruct]
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
+ case obj
+ in [3, 4]
+ true
+ else
+ false
+ end.should == true
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
+ case [0, 1, 2]
+ in String[0, 1, 2]
+ true
+ else
+ false
+ end.should == false
end
it "checks Constant === object before calling #deconstruct" do
c1 = Class.new
obj = c1.new
obj.should_not_receive(:deconstruct)
- eval(<<~RUBY).should == false
- case obj
- in String[1]
- true
- else
- false
- end
- RUBY
+
+ case obj
+ in String[1]
+ true
+ else
+ false
+ end.should == false
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
+ case obj
+ in Object[]
+ true
+ else
+ false
+ end.should == false
end
it "raises TypeError if #deconstruct method does not return array" do
obj = Object.new
- def obj.deconstruct; "" end
+
+ def obj.deconstruct
+ ""
+ end
-> {
- eval <<~RUBY
- case obj
- in Object[]
- else
- end
- RUBY
+ case obj
+ in Object[]
+ else
+ end
}.should raise_error(TypeError, /deconstruct must return Array/)
end
it "accepts a subclass of Array from #deconstruct" do
obj = Object.new
+
def obj.deconstruct
Class.new(Array).new([0, 1])
end
- eval(<<~RUBY).should == true
- case obj
- in [1, 2]
- false
- in [0, 1]
- true
- end
- RUBY
+ case obj
+ in [1, 2]
+ false
+ in [0, 1]
+ true
+ end.should == true
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
+ def obj.deconstruct
+ [1]
+ end
+
+ case obj
+ in Object[0]
+ true
+ else
+ false
+ end.should == false
end
it "binds variables" do
- eval(<<~RUBY).should == [0, 1, 2]
- case [0, 1, 2]
- in [a, b, c]
- [a, b, c]
- end
- RUBY
+ case [0, 1, 2]
+ in [a, b, c]
+ [a, b, c]
+ end.should == [0, 1, 2]
end
it "supports splat operator *rest" do
- eval(<<~RUBY).should == [1, 2]
- case [0, 1, 2]
- in [0, *rest]
- rest
- end
- RUBY
+ case [0, 1, 2]
+ in [0, *rest]
+ rest
+ end.should == [1, 2]
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
+ case [0, 1, 2, 3]
+ in [1, 2]
+ true
+ else
+ false
+ end.should == false
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
+ case [0, 1, 2, 3]
+ in [0, 1, ]
+ true
+ end.should == true
- eval(<<~RUBY).should == true
- case [0, 1, 2, 3]
- in 0, 1,;
- true
- end
- RUBY
+ case [0, 1, 2, 3]
+ in 0, 1,;
+ true
+ end.should == true
end
it "matches [] with []" do
- eval(<<~RUBY).should == true
- case []
- in []
- true
- end
- RUBY
+ case []
+ in []
+ true
+ end.should == true
end
it "matches anything with *" do
- eval(<<~RUBY).should == true
- case [0, 1]
- in *;
- true
- end
- RUBY
+ case [0, 1]
+ in *;
+ true
+ end.should == true
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
+ case [[1], ["2"]]
+ in [[0] | nil, _]
+ false
+ in [[1], [1]]
+ false
+ in [[1], [2 | "2"]]
+ true
+ end.should == true
- eval(<<~RUBY).should == true
- case [1, 2]
- in [0, _] | {a: 0}
- false
- in {a: 1, b: 2} | [1, 2]
- true
- end
- RUBY
+ case [1, 2]
+ in [0, _] | {a: 0}
+ false
+ in {a: 1, b: 2} | [1, 2]
+ true
+ end.should == true
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
+ case {a: 0, b: 1}
+ in Hash(a: 0, b: 1)
+ true
+ end.should == true
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
+ case {a: 0, b: 1}
+ in Hash[a: 0, b: 1]
+ true
+ end.should == true
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
+ case {a: 0, b: 1}
+ in {a: 0, b: 1}
+ true
+ end.should == true
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
+ case {a: 0, b: 1}
+ in a: 0, b: 1
+ true
+ end.should == true
- eval(<<~RUBY).should == [0, 1]
- case {a: 0, b: 1}
- in a: a, b: b
- [a, b]
- end
- RUBY
+ case {a: 0, b: 1}
+ in a: a, b: b
+ [a, b]
+ end.should == [0, 1]
- eval(<<~RUBY).should == { b: 1, c: 2 }
- case {a: 0, b: 1, c: 2}
- in a: 0, **rest
- rest
- end
- RUBY
+ case {a: 0, b: 1, c: 2}
+ in a: 0, **rest
+ rest
+ end.should == {b: 1, c: 2}
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
+ case {a: 0, b: 1}
+ in Hash(a:, b:)
+ [a, b]
+ end.should == [0, 1]
a = b = nil
- eval(<<~RUBY).should == [0, 1]
- case {a: 0, b: 1}
- in Hash[a:, b:]
- [a, b]
- end
- RUBY
+
+ case {a: 0, b: 1}
+ in Hash[a:, b:]
+ [a, b]
+ end.should == [0, 1]
a = b = nil
- eval(<<~RUBY).should == [0, 1]
- case {a: 0, b: 1}
- in {a:, b:}
- [a, b]
- end
- RUBY
+
+ case {a: 0, b: 1}
+ in {a:, b:}
+ [a, b]
+ end.should == [0, 1]
a = nil
- eval(<<~RUBY).should == [0, {b: 1, c: 2}]
- case {a: 0, b: 1, c: 2}
- in {a:, **rest}
- [a, rest]
- end
- RUBY
+
+ case {a: 0, b: 1, c: 2}
+ in {a:, **rest}
+ [a, rest]
+ end.should == [0, {b: 1, c: 2}]
a = b = nil
- eval(<<~RUBY).should == [0, 1]
- case {a: 0, b: 1}
- in a:, b:
- [a, b]
- end
- RUBY
+
+ case {a: 0, b: 1}
+ in a:, b:
+ [a, b]
+ end.should == [0, 1]
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
+ case {a: 0, b: 1}
+ in Hash(a:, b: x)
+ [a, x]
+ end.should == [0, 1]
end
it "supports 'string': key literal" do
- eval(<<~RUBY).should == true
- case {a: 0}
- in {"a": 0}
- true
- end
- RUBY
+ case {a: 0}
+ in {"a": 0}
+ true
+ end.should == true
end
it "does not support non-symbol keys" do
@@ -1018,8 +874,6 @@ describe "Pattern matching" do
end
it "does not support string interpolation in keys" do
- x = "a"
-
-> {
eval <<~'RUBY'
case {a: 1}
@@ -1041,14 +895,15 @@ describe "Pattern matching" do
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
+ def obj.deconstruct_keys(*)
+ {a: 1}
+ end
+
+ case obj
+ in {a: 1}
+ true
+ end.should == true
end
it "calls #deconstruct_keys per pattern" do
@@ -1059,96 +914,92 @@ describe "Pattern matching" do
{a: 1}
end
- eval(<<~RUBY).should == true
- case obj
- in {b: 1}
- false
- in {a: 1}
- true
- end
- RUBY
+ case obj
+ in {b: 1}
+ false
+ in {a: 1}
+ true
+ end.should == true
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
+ case {a: 1}
+ in String[a: 1]
+ true
+ else
+ false
+ end.should == false
end
it "checks Constant === object before calling #deconstruct_keys" do
c1 = Class.new
obj = c1.new
obj.should_not_receive(:deconstruct_keys)
- eval(<<~RUBY).should == false
- case obj
- in String(a: 1)
- true
- else
- false
- end
- RUBY
+
+ case obj
+ in String(a: 1)
+ true
+ else
+ false
+ end.should == false
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
+ case obj
+ in Object[a: 1]
+ true
+ else
+ false
+ end.should == false
end
it "does not match object if #deconstruct_keys method does not return Hash" do
obj = Object.new
- def obj.deconstruct_keys(*); "" end
+
+ def obj.deconstruct_keys(*)
+ ""
+ end
-> {
- eval <<~RUBY
- case obj
- in Object[a: 1]
- end
- RUBY
+ case obj
+ in Object[a: 1]
+ end
}.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
+ def obj.deconstruct_keys(*)
+ {"a" => 1}
+ end
+
+ case obj
+ in Object[a: 1]
+ true
+ else
+ false
+ end.should == false
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
+ def obj.deconstruct_keys(*)
+ {a: 1}
+ end
+
+ case obj
+ in Object[a: 2]
+ true
+ else
+ false
+ end.should == false
end
it "passes keys specified in pattern as arguments to #deconstruct_keys method" do
@@ -1159,11 +1010,9 @@ describe "Pattern matching" do
{a: 1, b: 2, c: 3}
end
- eval <<~RUBY
- case obj
- in Object[a: 1, b: 2, c: 3]
- end
- RUBY
+ case obj
+ in Object[a: 1, b: 2, c: 3]
+ end
ScratchPad.recorded.sort.should == [[[:a, :b, :c]]]
end
@@ -1176,11 +1025,9 @@ describe "Pattern matching" do
{a: 1, b: 2, c: 3}
end
- eval <<~RUBY
- case obj
- in Object[a: 1, b: 2, **]
- end
- RUBY
+ case obj
+ in Object[a: 1, b: 2, **]
+ end
ScratchPad.recorded.sort.should == [[[:a, :b]]]
end
@@ -1193,131 +1040,105 @@ describe "Pattern matching" do
{a: 1, b: 2}
end
- eval <<~RUBY
- case obj
- in Object[a: 1, **rest]
- end
- RUBY
+ case obj
+ in Object[a: 1, **rest]
+ end
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
+ case {a: 0, b: 1, c: 2}
+ in {a: x, b: y, c: z}
+ [x, y, z]
+ end.should == [0, 1, 2]
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
+ case {a: 0, b: 1, c: 2}
+ in {a: 0, **rest}
+ rest
+ end.should == {b: 1, c: 2}
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
+ case {a: 1, b: 2}
+ in {a: 1, b: 2, **nil}
+ true
+ end.should == true
- eval(<<~RUBY).should == false
- case {a: 1, b: 2}
- in {a: 1, **nil}
- true
- else
- false
- end
- RUBY
+ case {a: 1, b: 2}
+ in {a: 1, **nil}
+ true
+ else
+ false
+ end.should == false
end
it "can match partially" do
- eval(<<~RUBY).should == true
- case {a: 1, b: 2}
- in {a: 1}
- true
- end
- RUBY
+ case {a: 1, b: 2}
+ in {a: 1}
+ true
+ end.should == true
end
it "matches {} with {}" do
- eval(<<~RUBY).should == true
- case {}
- in {}
- true
- end
- RUBY
+ case {}
+ in {}
+ true
+ end.should == true
end
it "in {} only matches empty hashes" do
- eval(<<~RUBY).should == false
- case {a: 1}
- in {}
- true
- else
- false
- end
- RUBY
+ case {a: 1}
+ in {}
+ true
+ else
+ false
+ end.should == false
end
it "in {**nil} only matches empty hashes" do
- eval(<<~RUBY).should == true
- case {}
- in {**nil}
- true
- else
- false
- end
- RUBY
+ case {}
+ in {**nil}
+ true
+ else
+ false
+ end.should == true
- eval(<<~RUBY).should == false
- case {a: 1}
- in {**nil}
- true
- else
- false
- end
- RUBY
+ case {a: 1}
+ in {**nil}
+ true
+ else
+ false
+ end.should == false
end
it "matches anything with **" do
- eval(<<~RUBY).should == true
- case {a: 1}
- in **;
- true
- end
- RUBY
+ case {a: 1}
+ in **;
+ true
+ end.should == true
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
+ 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.should == true
- 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
+ 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.should == true
end
end
@@ -1335,12 +1156,11 @@ describe "Pattern matching" do
Module.new do
using refinery
- result = eval(<<~RUBY)
+ result =
case []
in [0]
true
end
- RUBY
end
result.should == true
@@ -1359,12 +1179,11 @@ describe "Pattern matching" do
Module.new do
using refinery
- result = eval(<<~RUBY)
+ result =
case {}
in a: 0
true
end
- RUBY
end
result.should == true
@@ -1383,12 +1202,11 @@ describe "Pattern matching" do
Module.new do
using refinery
- result = eval(<<~RUBY)
+ result =
case {}
in Array
true
end
- RUBY
end
result.should == true
@@ -1396,114 +1214,97 @@ describe "Pattern matching" do
end
describe "Ruby 3.1 improvements" do
- 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
+ it "can omit parentheses in one line pattern matching" do
+ [1, 2] => a, b
+ [a, b].should == [1, 2]
- eval(<<~RUBY).should == 1
- {a: 1} => a:
- a
- RUBY
- end
-
- it "supports pinning instance variables" do
- eval(<<~RUBY).should == true
- @a = /a/
- case 'abc'
- in ^@a
- true
- end
- RUBY
- end
+ {a: 1} => a:
+ a.should == 1
+ end
- it "supports pinning class variables" do
- result = nil
- Module.new do
- result = module_eval(<<~RUBY)
- @@a = 0..10
-
- case 2
- in ^@@a
- true
- end
- RUBY
- end
+ it "supports pinning instance variables" do
+ @a = /a/
+ case 'abc'
+ in ^@a
+ true
+ end.should == true
+ end
- result.should == true
- end
+ it "supports pinning class variables" do
+ result = nil
+ Module.new do
+ # avoid "class variable access from toplevel" runtime error with #module_eval
+ result = module_eval(<<~RUBY)
+ @@a = 0..10
- it "supports pinning global variables" do
- eval(<<~RUBY).should == true
- $a = /a/
- case 'abc'
- in ^$a
+ case 2
+ in ^@@a
true
end
RUBY
end
- it "supports pinning expressions" do
- eval(<<~RUBY).should == true
- case 'abc'
- in ^(/a/)
- true
- end
- RUBY
+ result.should == true
+ end
- eval(<<~RUBY).should == true
- case 0
- in ^(0+0)
- true
- end
- RUBY
- end
+ it "supports pinning global variables" do
+ $a = /a/
+ case 'abc'
+ in ^$a
+ true
+ end.should == true
+ end
- it "supports pinning expressions in array pattern" do
- eval(<<~RUBY).should == true
- case [3]
- in [^(1+2)]
- true
- end
- RUBY
- end
+ it "supports pinning expressions" do
+ case 'abc'
+ in ^(/a/)
+ true
+ end.should == true
- it "supports pinning expressions in hash pattern" do
- eval(<<~RUBY).should == true
- case {name: '2.6', released_at: Time.new(2018, 12, 25)}
- in {released_at: ^(Time.new(2010)..Time.new(2020))}
- true
- end
- RUBY
- end
+ case 0
+ in ^(0 + 0)
+ true
+ end.should == true
+ end
+
+ it "supports pinning expressions in array pattern" do
+ case [3]
+ in [^(1 + 2)]
+ true
+ end.should == true
+ end
+
+ it "supports pinning expressions in hash pattern" do
+ case {name: '2.6', released_at: Time.new(2018, 12, 25)}
+ in {released_at: ^(Time.new(2010)..Time.new(2020))}
+ true
+ end.should == true
end
end
describe "value in pattern" do
it "returns true if the pattern matches" do
- eval("1 in 1").should == true
+ (1 in 1).should == true
- eval("1 in Integer").should == true
+ (1 in Integer).should == true
e = nil
- eval("[1, 2] in [1, e]").should == true
+ ([1, 2] in [1, e]).should == true
e.should == 2
k = nil
- eval("{k: 1} in {k:}").should == true
+ ({k: 1} in {k:}).should == true
k.should == 1
end
it "returns false if the pattern does not match" do
- eval("1 in 2").should == false
+ (1 in 2).should == false
- eval("1 in Float").should == false
+ (1 in Float).should == false
- eval("[1, 2] in [2, e]").should == false
+ ([1, 2] in [2, e]).should == false
- eval("{k: 1} in {k: 2}").should == false
+ ({k: 1} in {k: 2}).should == false
end
end
end
diff --git a/spec/ruby/language/precedence_spec.rb b/spec/ruby/language/precedence_spec.rb
index c5adcca2c0..5e606c16d8 100644
--- a/spec/ruby/language/precedence_spec.rb
+++ b/spec/ruby/language/precedence_spec.rb
@@ -294,14 +294,14 @@ describe "Operators" do
-> { eval("1...2...3") }.should raise_error(SyntaxError)
end
- it ".. ... have higher precedence than ? :" do
- # Use variables to avoid warnings
- from = 1
- to = 2
- # These are flip-flop, not Range instances
- (from..to ? 3 : 4).should == 3
- (from...to ? 3 : 4).should == 3
- end
+ it ".. ... have higher precedence than ? :" do
+ # Use variables to avoid warnings
+ from = 1
+ to = 2
+ # These are flip-flop, not Range instances
+ (from..to ? 3 : 4).should == 3
+ (from...to ? 3 : 4).should == 3
+ end
it "? : is right-associative" do
(true ? 2 : 3 ? 4 : 5).should == 2
diff --git a/spec/ruby/language/predefined_spec.rb b/spec/ruby/language/predefined_spec.rb
index ac28f1e8a0..fc1667a38f 100644
--- a/spec/ruby/language/predefined_spec.rb
+++ b/spec/ruby/language/predefined_spec.rb
@@ -1,4 +1,5 @@
require_relative '../spec_helper'
+require_relative '../core/exception/shared/set_backtrace'
require 'stringio'
# The following tables are excerpted from Programming Ruby: The Pragmatic Programmer's Guide'
@@ -71,7 +72,7 @@ describe "Predefined global $~" do
match2.should_not == nil
$~.should == match2
- eval 'match3 = /baz/.match("baz")'
+ match3 = /baz/.match("baz")
match3.should_not == nil
$~.should == match3
@@ -88,8 +89,8 @@ describe "Predefined global $~" do
$~ = /foo/.match("foo")
$~.should be_an_instance_of(MatchData)
- -> { $~ = Object.new }.should raise_error(TypeError)
- -> { $~ = 1 }.should raise_error(TypeError)
+ -> { $~ = Object.new }.should raise_error(TypeError, 'wrong argument type Object (expected MatchData)')
+ -> { $~ = 1 }.should raise_error(TypeError, 'wrong argument type Integer (expected MatchData)')
end
it "changes the value of derived capture globals when assigned" do
@@ -136,6 +137,19 @@ describe "Predefined global $&" do
"abc".dup.force_encoding(Encoding::EUC_JP) =~ /b/
$&.encoding.should equal(Encoding::EUC_JP)
end
+
+ it "is read-only" do
+ -> {
+ eval %q{$& = ""}
+ }.should raise_error(SyntaxError, /Can't set variable \$&/)
+ end
+
+ it "is read-only when aliased" do
+ alias $predefined_spec_ampersand $&
+ -> {
+ $predefined_spec_ampersand = ""
+ }.should raise_error(NameError, '$predefined_spec_ampersand is a read-only variable')
+ end
end
describe "Predefined global $`" do
@@ -154,6 +168,19 @@ describe "Predefined global $`" do
"abc".dup.force_encoding(Encoding::ISO_8859_1) =~ /a/
$`.encoding.should equal(Encoding::ISO_8859_1)
end
+
+ it "is read-only" do
+ -> {
+ eval %q{$` = ""}
+ }.should raise_error(SyntaxError, /Can't set variable \$`/)
+ end
+
+ it "is read-only when aliased" do
+ alias $predefined_spec_backquote $`
+ -> {
+ $predefined_spec_backquote = ""
+ }.should raise_error(NameError, '$predefined_spec_backquote is a read-only variable')
+ end
end
describe "Predefined global $'" do
@@ -172,6 +199,19 @@ describe "Predefined global $'" do
"abc".dup.force_encoding(Encoding::ISO_8859_1) =~ /c/
$'.encoding.should equal(Encoding::ISO_8859_1)
end
+
+ it "is read-only" do
+ -> {
+ eval %q{$' = ""}
+ }.should raise_error(SyntaxError, /Can't set variable \$'/)
+ end
+
+ it "is read-only when aliased" do
+ alias $predefined_spec_single_quote $'
+ -> {
+ $predefined_spec_single_quote = ""
+ }.should raise_error(NameError, '$predefined_spec_single_quote is a read-only variable')
+ end
end
describe "Predefined global $+" do
@@ -190,6 +230,19 @@ describe "Predefined global $+" do
"abc".dup.force_encoding(Encoding::EUC_JP) =~ /(b)/
$+.encoding.should equal(Encoding::EUC_JP)
end
+
+ it "is read-only" do
+ -> {
+ eval %q{$+ = ""}
+ }.should raise_error(SyntaxError, /Can't set variable \$\+/)
+ end
+
+ it "is read-only when aliased" do
+ alias $predefined_spec_plus $+
+ -> {
+ $predefined_spec_plus = ""
+ }.should raise_error(NameError, '$predefined_spec_plus is a read-only variable')
+ end
end
describe "Predefined globals $1..N" do
@@ -229,7 +282,7 @@ describe "Predefined global $stdout" do
end
it "raises TypeError error if assigned to nil" do
- -> { $stdout = nil }.should raise_error(TypeError)
+ -> { $stdout = nil }.should raise_error(TypeError, '$stdout must have write method, NilClass given')
end
it "raises TypeError error if assigned to object that doesn't respond to #write" do
@@ -243,6 +296,22 @@ describe "Predefined global $stdout" do
end
describe "Predefined global $!" do
+ it "is Fiber-local" do
+ Fiber.new do
+ raise "hi"
+ rescue
+ Fiber.yield
+ end.resume
+
+ $!.should == nil
+ end
+
+ it "is read-only" do
+ -> {
+ $! = []
+ }.should raise_error(NameError, '$! is a read-only variable')
+ end
+
# See http://jira.codehaus.org/browse/JRUBY-5550
it "remains nil after a failed core class \"checked\" coercion against a class that defines method_missing" do
$!.should == nil
@@ -502,6 +571,75 @@ describe "Predefined global $!" do
end
end
+describe "Predefined global $@" do
+ it "is Fiber-local" do
+ Fiber.new do
+ raise "hi"
+ rescue
+ Fiber.yield
+ end.resume
+
+ $@.should == nil
+ end
+
+ it "is set to a backtrace of a rescued exception" do
+ begin
+ raise
+ rescue
+ $@.should be_an_instance_of(Array)
+ $@.should == $!.backtrace
+ end
+ end
+
+ it "is cleared when an exception is rescued" do
+ begin
+ raise
+ rescue
+ end
+
+ $@.should == nil
+ end
+
+ it "is not set when there is no current exception" do
+ $@.should == nil
+ end
+
+ it "is set to a backtrace of a rescued exception" do
+ begin
+ raise
+ rescue
+ $@.should be_an_instance_of(Array)
+ $@.should == $!.backtrace
+ end
+ end
+
+ it "is not read-only" do
+ begin
+ raise
+ rescue
+ $@ = []
+ $@.should == []
+ end
+ end
+
+ it_behaves_like :exception_set_backtrace, -> backtrace {
+ exception = nil
+ begin
+ raise
+ rescue
+ $@ = backtrace
+ exception = $!
+ end
+ exception
+ }
+
+ it "cannot be assigned when there is no a rescued exception" do
+ -> {
+ $@ = []
+ }.should raise_error(ArgumentError, '$! not set')
+ end
+end
+
# Input/Output Variables
# ---------------------------------------------------------------------------------------------------
#
@@ -549,12 +687,39 @@ describe "Predefined global $/" do
$VERBOSE = @verbose
end
- it "can be assigned a String" do
- str = "abc"
- $/ = str
- $/.should equal(str)
+ ruby_version_is ""..."4.0" do
+ it "can be assigned a String" do
+ str = +"abc"
+ $/ = str
+ $/.should equal(str)
+ end
end
+ ruby_version_is "4.0" do
+ it "makes a new frozen String from the assigned String" do
+ string_subclass = Class.new(String)
+ str = string_subclass.new("abc")
+ str.instance_variable_set(:@ivar, 1)
+ $/ = str
+ $/.should.frozen?
+ $/.should be_an_instance_of(String)
+ $/.should_not.instance_variable_defined?(:@ivar)
+ $/.should == str
+ end
+
+ it "makes a new frozen String if it's not frozen" do
+ str = +"abc"
+ $/ = str
+ $/.should.frozen?
+ $/.should == str
+ end
+
+ it "assigns the given String if it's frozen and has no instance variables" do
+ str = "abc".freeze
+ $/ = str
+ $/.should equal(str)
+ end
+ end
it "can be assigned nil" do
$/ = nil
$/.should be_nil
@@ -573,15 +738,19 @@ describe "Predefined global $/" do
obj = mock("$/ value")
obj.should_not_receive(:to_str)
- -> { $/ = obj }.should raise_error(TypeError)
+ -> { $/ = obj }.should raise_error(TypeError, 'value of $/ must be String')
end
it "raises a TypeError if assigned an Integer" do
- -> { $/ = 1 }.should raise_error(TypeError)
+ -> { $/ = 1 }.should raise_error(TypeError, 'value of $/ must be String')
end
it "raises a TypeError if assigned a boolean" do
- -> { $/ = true }.should raise_error(TypeError)
+ -> { $/ = true }.should raise_error(TypeError, 'value of $/ must be String')
+ end
+
+ it "warns if assigned non-nil" do
+ -> { $/ = "_" }.should complain(/warning: (?:non-nil )?[`']\$\/' is deprecated/)
end
end
@@ -598,10 +767,38 @@ describe "Predefined global $-0" do
$VERBOSE = @verbose
end
- it "can be assigned a String" do
- str = "abc"
- $-0 = str
- $-0.should equal(str)
+ ruby_version_is ""..."4.0" do
+ it "can be assigned a String" do
+ str = +"abc"
+ $-0 = str
+ $-0.should equal(str)
+ end
+ end
+
+ ruby_version_is "4.0" do
+ it "makes a new frozen String from the assigned String" do
+ string_subclass = Class.new(String)
+ str = string_subclass.new("abc")
+ str.instance_variable_set(:@ivar, 1)
+ $-0 = str
+ $-0.should.frozen?
+ $-0.should be_an_instance_of(String)
+ $-0.should_not.instance_variable_defined?(:@ivar)
+ $-0.should == str
+ end
+
+ it "makes a new frozen String if it's not frozen" do
+ str = +"abc"
+ $-0 = str
+ $-0.should.frozen?
+ $-0.should == str
+ end
+
+ it "assigns the given String if it's frozen and has no instance variables" do
+ str = "abc".freeze
+ $-0 = str
+ $-0.should equal(str)
+ end
end
it "can be assigned nil" do
@@ -622,15 +819,19 @@ describe "Predefined global $-0" do
obj = mock("$-0 value")
obj.should_not_receive(:to_str)
- -> { $-0 = obj }.should raise_error(TypeError)
+ -> { $-0 = obj }.should raise_error(TypeError, 'value of $-0 must be String')
end
it "raises a TypeError if assigned an Integer" do
- -> { $-0 = 1 }.should raise_error(TypeError)
+ -> { $-0 = 1 }.should raise_error(TypeError, 'value of $-0 must be String')
end
it "raises a TypeError if assigned a boolean" do
- -> { $-0 = true }.should raise_error(TypeError)
+ -> { $-0 = true }.should raise_error(TypeError, 'value of $-0 must be String')
+ end
+
+ it "warns if assigned non-nil" do
+ -> { $-0 = "_" }.should complain(/warning: (?:non-nil )?[`']\$-0' is deprecated/)
end
end
@@ -664,12 +865,16 @@ describe "Predefined global $\\" do
obj = mock("$\\ value")
obj.should_not_receive(:to_str)
- -> { $\ = obj }.should raise_error(TypeError)
+ -> { $\ = obj }.should raise_error(TypeError, 'value of $\ must be String')
end
it "raises a TypeError if assigned not String" do
- -> { $\ = 1 }.should raise_error(TypeError)
- -> { $\ = true }.should raise_error(TypeError)
+ -> { $\ = 1 }.should raise_error(TypeError, 'value of $\ must be String')
+ -> { $\ = true }.should raise_error(TypeError, 'value of $\ must be String')
+ end
+
+ it "warns if assigned non-nil" do
+ -> { $\ = "_" }.should complain(/warning: (?:non-nil )?[`']\$\\' is deprecated/)
end
end
@@ -683,11 +888,11 @@ describe "Predefined global $," do
end
it "raises TypeError if assigned a non-String" do
- -> { $, = Object.new }.should raise_error(TypeError)
+ -> { $, = Object.new }.should raise_error(TypeError, 'value of $, must be String')
end
it "warns if assigned non-nil" do
- -> { $, = "_" }.should complain(/warning: [`']\$,' is deprecated/)
+ -> { $, = "_" }.should complain(/warning: (?:non-nil )?[`']\$,' is deprecated/)
end
end
@@ -724,7 +929,7 @@ describe "Predefined global $;" do
end
it "warns if assigned non-nil" do
- -> { $; = "_" }.should complain(/warning: [`']\$;' is deprecated/)
+ -> { $; = "_" }.should complain(/warning: (?:non-nil )?[`']\$;' is deprecated/)
end
end
@@ -758,7 +963,7 @@ describe "Predefined global $_" do
match.should == "bar\n"
$_.should == match
- eval 'match = stdin.gets'
+ match = stdin.gets
match.should == "baz\n"
$_.should == match
@@ -868,22 +1073,28 @@ describe "Execution variable $:" do
it "is read-only" do
-> {
$: = []
- }.should raise_error(NameError)
+ }.should raise_error(NameError, '$: is a read-only variable')
-> {
$LOAD_PATH = []
- }.should raise_error(NameError)
+ }.should raise_error(NameError, '$LOAD_PATH is a read-only variable')
-> {
$-I = []
- }.should raise_error(NameError)
+ }.should raise_error(NameError, '$-I is a read-only variable')
end
it "default $LOAD_PATH entries until sitelibdir included have @gem_prelude_index set" do
skip "no sense in ruby itself" if MSpecScript.instance_variable_defined?(:@testing_ruby)
- $:.should.include?(RbConfig::CONFIG['sitelibdir'])
- idx = $:.index(RbConfig::CONFIG['sitelibdir'])
+ if platform_is :windows
+ # See https://github.com/ruby/setup-ruby/pull/762#issuecomment-2917460440
+ $:.should.find { |e| File.realdirpath(e) == RbConfig::CONFIG['sitelibdir'] }
+ idx = $:.index { |e| File.realdirpath(e) == RbConfig::CONFIG['sitelibdir'] }
+ else
+ $:.should.include?(RbConfig::CONFIG['sitelibdir'])
+ idx = $:.index(RbConfig::CONFIG['sitelibdir'])
+ end
$:[idx..-1].all? { |p| p.instance_variable_defined?(:@gem_prelude_index) }.should be_true
$:[0...idx].all? { |p| !p.instance_variable_defined?(:@gem_prelude_index) }.should be_true
@@ -898,11 +1109,11 @@ describe "Global variable $\"" do
it "is read-only" do
-> {
$" = []
- }.should raise_error(NameError)
+ }.should raise_error(NameError, '$" is a read-only variable')
-> {
$LOADED_FEATURES = []
- }.should raise_error(NameError)
+ }.should raise_error(NameError, '$LOADED_FEATURES is a read-only variable')
end
end
@@ -910,7 +1121,7 @@ describe "Global variable $<" do
it "is read-only" do
-> {
$< = nil
- }.should raise_error(NameError)
+ }.should raise_error(NameError, '$< is a read-only variable')
end
end
@@ -918,7 +1129,7 @@ describe "Global variable $FILENAME" do
it "is read-only" do
-> {
$FILENAME = "-"
- }.should raise_error(NameError)
+ }.should raise_error(NameError, '$FILENAME is a read-only variable')
end
end
@@ -926,7 +1137,7 @@ describe "Global variable $?" do
it "is read-only" do
-> {
$? = nil
- }.should raise_error(NameError)
+ }.should raise_error(NameError, '$? is a read-only variable')
end
it "is thread-local" do
@@ -937,19 +1148,19 @@ end
describe "Global variable $-a" do
it "is read-only" do
- -> { $-a = true }.should raise_error(NameError)
+ -> { $-a = true }.should raise_error(NameError, '$-a is a read-only variable')
end
end
describe "Global variable $-l" do
it "is read-only" do
- -> { $-l = true }.should raise_error(NameError)
+ -> { $-l = true }.should raise_error(NameError, '$-l is a read-only variable')
end
end
describe "Global variable $-p" do
it "is read-only" do
- -> { $-p = true }.should raise_error(NameError)
+ -> { $-p = true }.should raise_error(NameError, '$-p is a read-only variable')
end
end
@@ -1100,7 +1311,7 @@ describe "The predefined standard object nil" do
end
it "raises a SyntaxError if assigned to" do
- -> { eval("nil = true") }.should raise_error(SyntaxError)
+ -> { eval("nil = true") }.should raise_error(SyntaxError, /Can't assign to nil/)
end
end
@@ -1110,7 +1321,7 @@ describe "The predefined standard object true" do
end
it "raises a SyntaxError if assigned to" do
- -> { eval("true = false") }.should raise_error(SyntaxError)
+ -> { eval("true = false") }.should raise_error(SyntaxError, /Can't assign to true/)
end
end
@@ -1120,13 +1331,13 @@ describe "The predefined standard object false" do
end
it "raises a SyntaxError if assigned to" do
- -> { eval("false = nil") }.should raise_error(SyntaxError)
+ -> { eval("false = nil") }.should raise_error(SyntaxError, /Can't assign to false/)
end
end
describe "The self pseudo-variable" do
it "raises a SyntaxError if assigned to" do
- -> { eval("self = 1") }.should raise_error(SyntaxError)
+ -> { eval("self = 1") }.should raise_error(SyntaxError, /Can't change the value of self/)
end
end
@@ -1317,9 +1528,9 @@ end
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, path = $LOAD_PATH.resolve_feature_path('pp')
extension.should == :rb
- path.should.end_with?('/set.rb')
+ path.should.end_with?('/pp.rb')
end
it "returns what will be loaded without actual loading, .so file" do
@@ -1331,16 +1542,8 @@ describe "$LOAD_PATH.resolve_feature_path" do
path.should.end_with?("/etc.#{RbConfig::CONFIG['DLEXT']}")
end
- ruby_version_is ""..."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
+ it "return nil if feature cannot be found" do
+ $LOAD_PATH.resolve_feature_path('noop').should be_nil
end
end
diff --git a/spec/ruby/language/private_spec.rb b/spec/ruby/language/private_spec.rb
index ddf185e6d2..b04aa25c9e 100644
--- a/spec/ruby/language/private_spec.rb
+++ b/spec/ruby/language/private_spec.rb
@@ -34,7 +34,7 @@ describe "The private keyword" do
it "changes visibility of previously called method" do
klass = Class.new do
def foo
- "foo"
+ "foo"
end
end
f = klass.new
diff --git a/spec/ruby/language/proc_spec.rb b/spec/ruby/language/proc_spec.rb
index cc69b7799c..ca9a13aa61 100644
--- a/spec/ruby/language/proc_spec.rb
+++ b/spec/ruby/language/proc_spec.rb
@@ -104,7 +104,7 @@ describe "A Proc" do
end
it "assigns all passed values after the first to the rest argument" do
- @l.call(1, 2, 3).should == [1, [2, 3]]
+ @l.call(1, 2, 3).should == [1, [2, 3]]
end
it "does not call #to_ary to convert a single passed object to an Array" do
diff --git a/spec/ruby/language/regexp/anchors_spec.rb b/spec/ruby/language/regexp/anchors_spec.rb
index 0129e255da..cdc06c0b4d 100644
--- a/spec/ruby/language/regexp/anchors_spec.rb
+++ b/spec/ruby/language/regexp/anchors_spec.rb
@@ -124,10 +124,10 @@ describe "Regexps with anchors" do
/foo\b/.match("foo").to_a.should == ["foo"]
/foo\b/.match("foo\n").to_a.should == ["foo"]
LanguageSpecs.white_spaces.scan(/./).each do |c|
- /foo\b/.match("foo" + c).to_a.should == ["foo"]
+ /foo\b/.match("foo" + c).to_a.should == ["foo"]
end
LanguageSpecs.non_alphanum_non_space.scan(/./).each do |c|
- /foo\b/.match("foo" + c).to_a.should == ["foo"]
+ /foo\b/.match("foo" + c).to_a.should == ["foo"]
end
/foo\b/.match("foo\0").to_a.should == ["foo"]
# Basic non-matching
@@ -145,10 +145,10 @@ describe "Regexps with anchors" do
/foo\B/.match("foo").should be_nil
/foo\B/.match("foo\n").should be_nil
LanguageSpecs.white_spaces.scan(/./).each do |c|
- /foo\B/.match("foo" + c).should be_nil
+ /foo\B/.match("foo" + c).should be_nil
end
LanguageSpecs.non_alphanum_non_space.scan(/./).each do |c|
- /foo\B/.match("foo" + c).should be_nil
+ /foo\B/.match("foo" + c).should be_nil
end
/foo\B/.match("foo\0").should be_nil
end
diff --git a/spec/ruby/language/regexp/character_classes_spec.rb b/spec/ruby/language/regexp/character_classes_spec.rb
index 98d431a817..018757db41 100644
--- a/spec/ruby/language/regexp/character_classes_spec.rb
+++ b/spec/ruby/language/regexp/character_classes_spec.rb
@@ -113,7 +113,7 @@ describe "Regexp with character classes" do
end
it "doesn't matches Unicode marks with [[:alnum:]]" do
- "\u{36F}".match(/[[:alnum:]]/).should be_nil
+ "\u{3099}".match(/[[:alnum:]]/).should be_nil
end
it "doesn't match Unicode control characters with [[:alnum:]]" do
@@ -133,7 +133,7 @@ describe "Regexp with character classes" do
end
it "doesn't matches Unicode marks with [[:alpha:]]" do
- "\u{36F}".match(/[[:alpha:]]/).should be_nil
+ "\u{3099}".match(/[[:alpha:]]/).should be_nil
end
it "doesn't match Unicode control characters with [[:alpha:]]" do
@@ -226,7 +226,7 @@ describe "Regexp with character classes" do
end
it "matches Unicode letter characters with [[:graph:]]" do
- "à".match(/[[:graph:]]/).to_a.should == ["à"]
+ "à".match(/[[:graph:]]/).to_a.should == ["à"]
end
it "matches Unicode digits with [[:graph:]]" do
@@ -562,6 +562,13 @@ describe "Regexp with character classes" do
"\u{16EE}".match(/[[:word:]]/).to_a.should == ["\u{16EE}"]
end
+ ruby_bug "#19417", ""..."3.4.6" do
+ it "matches Unicode join control characters with [[:word:]]" do
+ "\u{200C}".match(/[[:word:]]/).to_a.should == ["\u{200C}"]
+ "\u{200D}".match(/[[:word:]]/).to_a.should == ["\u{200D}"]
+ end
+ end
+
it "doesn't match Unicode No characters with [[:word:]]" do
"\u{17F0}".match(/[[:word:]]/).should be_nil
end
diff --git a/spec/ruby/language/regexp/encoding_spec.rb b/spec/ruby/language/regexp/encoding_spec.rb
index 0571b2d3cf..ceb9cf823a 100644
--- a/spec/ruby/language/regexp/encoding_spec.rb
+++ b/spec/ruby/language/regexp/encoding_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
require_relative '../fixtures/classes'
@@ -39,7 +39,11 @@ describe "Regexps with encoding modifiers" do
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".dup.force_encoding('utf-8')) }.should complain(%r{historical binary regexp match /.../n against UTF-8 string})
+ -> {
+ eval <<~RUBY
+ /./n.match("\303\251".dup.force_encoding('utf-8'))
+ RUBY
+ }.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
diff --git a/spec/ruby/language/regexp/escapes_spec.rb b/spec/ruby/language/regexp/escapes_spec.rb
index 16a4d8c23b..541998b937 100644
--- a/spec/ruby/language/regexp/escapes_spec.rb
+++ b/spec/ruby/language/regexp/escapes_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
require_relative '../fixtures/classes'
diff --git a/spec/ruby/language/regexp/grouping_spec.rb b/spec/ruby/language/regexp/grouping_spec.rb
index 2f04a04018..313858f714 100644
--- a/spec/ruby/language/regexp/grouping_spec.rb
+++ b/spec/ruby/language/regexp/grouping_spec.rb
@@ -12,7 +12,7 @@ describe "Regexps with grouping" do
end
it "raises a SyntaxError when parentheses aren't balanced" do
- -> { eval "/(hay(st)ack/" }.should raise_error(SyntaxError)
+ -> { eval "/(hay(st)ack/" }.should raise_error(SyntaxError)
end
it "supports (?: ) (non-capturing group)" do
diff --git a/spec/ruby/language/regexp_spec.rb b/spec/ruby/language/regexp_spec.rb
index 89d0914807..ce344b5b05 100644
--- a/spec/ruby/language/regexp_spec.rb
+++ b/spec/ruby/language/regexp_spec.rb
@@ -62,7 +62,7 @@ describe "Literal Regexps" do
end
end
- it "supports non-paired delimiters delimiters with %r" do
+ it "supports non-paired delimiters with %r" do
LanguageSpecs.non_paired_delimiters.each do |c|
eval("%r#{c} foo #{c}").should == / foo /
end
@@ -112,7 +112,7 @@ describe "Literal Regexps" do
/foo.(?<=\d)/.match("fooA foo1").to_a.should == ["foo1"]
end
- ruby_bug "#13671", ""..."3.5" do # https://bugs.ruby-lang.org/issues/13671
+ ruby_bug "#13671", ""..."4.0" do # https://bugs.ruby-lang.org/issues/13671
it "handles a lookbehind with ss characters" do
r = Regexp.new("(?<!dss)", Regexp::IGNORECASE)
r.should =~ "✨"
diff --git a/spec/ruby/language/rescue_spec.rb b/spec/ruby/language/rescue_spec.rb
index a3ee4807ac..6be3bfd023 100644
--- a/spec/ruby/language/rescue_spec.rb
+++ b/spec/ruby/language/rescue_spec.rb
@@ -52,6 +52,16 @@ describe "The rescue keyword" do
RescueSpecs::SafeNavigationSetterCaptor.should_capture_exception
end
+ it 'using a safely navigated setter method on a nil target' do
+ target = nil
+ begin
+ raise SpecificExampleException, "Raising this to be handled below"
+ rescue SpecificExampleException => target&.captured_error
+ :caught
+ end.should == :caught
+ target.should be_nil
+ end
+
it 'using a setter method' do
RescueSpecs::SetterCaptor.should_capture_exception
end
@@ -126,10 +136,14 @@ describe "The rescue keyword" do
it 'captures successfully at the top-level' do
ScratchPad.record []
+ loaded_features = $".dup
+ begin
+ require_relative 'fixtures/rescue/top_level'
- require_relative 'fixtures/rescue/top_level'
-
- ScratchPad.recorded.should == ["message"]
+ ScratchPad.recorded.should == ["message"]
+ ensure
+ $".replace loaded_features
+ end
end
end
@@ -563,10 +577,8 @@ describe "The rescue keyword" do
end
end
line = __LINE__
- foo.should == [
- "#{__FILE__}:#{line-3}:in 'foo'",
- "#{__FILE__}:#{line+1}:in 'block (3 levels) in <top (required)>'"
- ]
+ foo[0].should =~ /#{__FILE__}:#{line-3}:in 'foo'/
+ foo[1].should =~ /#{__FILE__}:#{line+2}:in 'block/
end
end
diff --git a/spec/ruby/language/reserved_keywords.rb b/spec/ruby/language/reserved_keywords.rb
new file mode 100644
index 0000000000..6c40e34ccc
--- /dev/null
+++ b/spec/ruby/language/reserved_keywords.rb
@@ -0,0 +1,149 @@
+require_relative '../spec_helper'
+
+describe "Ruby's reserved keywords" do
+ # Copied from https://github.com/ruby/ruby/blob/master/defs/keywords
+ keywords = %w[
+ alias
+ and
+ begin
+ BEGIN
+ break
+ case
+ class
+ def
+ defined?
+ do
+ else
+ elsif
+ end
+ END
+ ensure
+ false
+ for
+ if
+ in
+ module
+ next
+ nil
+ not
+ or
+ redo
+ rescue
+ retry
+ return
+ self
+ super
+ then
+ true
+ undef
+ unless
+ until
+ when
+ while
+ yield
+ __ENCODING__
+ __FILE__
+ __LINE__
+ ]
+
+ keywords.each do |name|
+ describe "keyword '#{name}'" do
+ it "can't be used as local variable name" do
+ -> { eval(<<~RUBY) }.should raise_error(SyntaxError)
+ #{name} = :local_variable
+ RUBY
+ end
+
+ if name == "defined?"
+ it "can't be used as an instance variable name" do
+ -> { eval(<<~RUBY) }.should raise_error(SyntaxError)
+ @#{name} = :instance_variable
+ RUBY
+ end
+
+ it "can't be used as a class variable name" do
+ -> { eval(<<~RUBY) }.should raise_error(SyntaxError)
+ class C
+ @@#{name} = :class_variable
+ end
+ RUBY
+ end
+
+ it "can't be used as a global variable name" do
+ -> { eval(<<~RUBY) }.should raise_error(SyntaxError)
+ $#{name} = :global_variable
+ RUBY
+ end
+ else
+ it "can be used as an instance variable name" do
+ result = eval <<~RUBY
+ @#{name} = :instance_variable
+ @#{name}
+ RUBY
+
+ result.should == :instance_variable
+ end
+
+ it "can be used as a class variable name" do
+ result = eval <<~RUBY
+ class C
+ @@#{name} = :class_variable
+ @@#{name}
+ end
+ RUBY
+
+ result.should == :class_variable
+ end
+
+ it "can be used as a global variable name" do
+ result = eval <<~RUBY
+ $#{name} = :global_variable
+ $#{name}
+ RUBY
+
+ result.should == :global_variable
+ end
+ end
+
+ it "can't be used as a positional parameter name" do
+ -> { eval(<<~RUBY) }.should raise_error(SyntaxError)
+ def x(#{name}); end
+ RUBY
+ end
+
+ invalid_kw_param_names = ["BEGIN","END","defined?"]
+
+ if invalid_kw_param_names.include?(name)
+ it "can't be used a keyword parameter name" do
+ -> { eval(<<~RUBY) }.should raise_error(SyntaxError)
+ def m(#{name}:); end
+ RUBY
+ end
+ else
+ it "can be used a keyword parameter name" do
+ result = instance_eval <<~RUBY
+ def m(#{name}:)
+ binding.local_variable_get(:#{name})
+ end
+
+ m(#{name}: :argument)
+ RUBY
+
+ result.should == :argument
+ end
+ end
+
+ it "can be used as a method name" do
+ result = instance_eval <<~RUBY
+ def #{name}
+ :method_return_value
+ end
+
+ send(:#{name})
+ RUBY
+
+ result.should == :method_return_value
+ end
+ end
+ end
+end
diff --git a/spec/ruby/language/send_spec.rb b/spec/ruby/language/send_spec.rb
index aaccdf0998..5d6340ffc5 100644
--- a/spec/ruby/language/send_spec.rb
+++ b/spec/ruby/language/send_spec.rb
@@ -106,6 +106,24 @@ describe "Invoking a method" do
specs.yield_now(&o).should == :from_to_proc
end
+ ruby_version_is "4.0" do
+ it "raises TypeError if 'to_proc' doesn't return a Proc" do
+ o = LangSendSpecs::RawToProc.new(42)
+
+ -> {
+ specs.makeproc(&o)
+ }.should raise_error(TypeError, "can't convert LangSendSpecs::RawToProc to Proc (LangSendSpecs::RawToProc#to_proc gives Integer)")
+ end
+
+ it "raises TypeError if block object isn't a Proc and doesn't respond to `to_proc`" do
+ o = Object.new
+
+ -> {
+ specs.makeproc(&o)
+ }.should raise_error(TypeError, "no implicit conversion of Object into Proc")
+ end
+ end
+
it "raises a SyntaxError with both a literal block and an object as block" do
-> {
eval "specs.oneb(10, &l){ 42 }"
diff --git a/spec/ruby/language/string_spec.rb b/spec/ruby/language/string_spec.rb
index 083a7f5db5..f287731bed 100644
--- a/spec/ruby/language/string_spec.rb
+++ b/spec/ruby/language/string_spec.rb
@@ -1,6 +1,7 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../spec_helper'
+require_relative 'fixtures/class_with_class_variable'
# TODO: rewrite these horrid specs. it "are..." seriously?!
@@ -27,6 +28,11 @@ describe "Ruby character strings" do
"#$ip".should == 'xxx'
end
+ it "interpolate class variables just with the # character" do
+ object = StringSpecs::ClassWithClassVariable.new
+ object.foo.should == 'xxx'
+ end
+
it "allows underscore as part of a variable name in a simple interpolation" do
@my_ip = 'xxx'
"#@my_ip".should == 'xxx'
@@ -280,15 +286,15 @@ describe "Ruby String interpolation" do
it "creates a non-frozen String" do
code = <<~'RUBY'
- "a#{6*7}c"
+ "a#{6*7}c"
RUBY
eval(code).should_not.frozen?
end
it "creates a non-frozen String when # frozen-string-literal: true is used" do
code = <<~'RUBY'
- # frozen-string-literal: true
- "a#{6*7}c"
+ # frozen-string-literal: true
+ "a#{6*7}c"
RUBY
eval(code).should_not.frozen?
end
diff --git a/spec/ruby/language/super_spec.rb b/spec/ruby/language/super_spec.rb
index a98b3b3091..7d9e896d8b 100644
--- a/spec/ruby/language/super_spec.rb
+++ b/spec/ruby/language/super_spec.rb
@@ -70,7 +70,7 @@ describe "The super keyword" do
SuperSpecs::S4::B.new.foo([],"test").should == ["B#foo(a,test)", "A#foo"]
end
- it "raises an error error when super method does not exist" do
+ it "raises an error when super method does not exist" do
sup = Class.new
sub_normal = Class.new(sup) do
def foo
diff --git a/spec/ruby/language/undef_spec.rb b/spec/ruby/language/undef_spec.rb
index 29dba4afb4..268c0b84c3 100644
--- a/spec/ruby/language/undef_spec.rb
+++ b/spec/ruby/language/undef_spec.rb
@@ -69,7 +69,7 @@ describe "The undef keyword" do
it "raises a NameError when passed a missing name" do
Class.new do
-> {
- undef not_exist
+ undef not_exist
}.should raise_error(NameError) { |e|
# a NameError and not a NoMethodError
e.class.should == NameError
diff --git a/spec/ruby/language/variables_spec.rb b/spec/ruby/language/variables_spec.rb
index 01be61a9dc..e134271939 100644
--- a/spec/ruby/language/variables_spec.rb
+++ b/spec/ruby/language/variables_spec.rb
@@ -14,69 +14,34 @@ describe "Evaluation order during assignment" do
end
context "with multiple assignment" do
- ruby_version_is ""..."3.1" do
- it "does not evaluate from left to right" do
- obj = VariablesSpecs::EvalOrder.new
-
- obj.instance_eval do
- foo[0], bar.baz = a, b
- end
-
- obj.order.should == ["a", "b", "foo", "foo[]=", "bar", "bar.baz="]
+ it "evaluates from left to right, receivers first then methods" do
+ obj = VariablesSpecs::EvalOrder.new
+ obj.instance_eval do
+ foo[0], bar.baz = a, b
end
- it "cannot be used to swap variables with nested method calls" do
- node = VariablesSpecs::EvalOrder.new.node
-
- original_node = node
- original_node_left = node.left
- original_node_left_right = node.left.right
-
- node.left, node.left.right, node = node.left.right, node, node.left
- # Should evaluate in the order of:
- # RHS: node.left.right, node, node.left
- # LHS:
- # * node(original_node), original_node.left = original_node_left_right
- # * node(original_node), node.left(changed in the previous assignment to original_node_left_right),
- # original_node_left_right.right = original_node
- # * node = original_node_left
-
- node.should == original_node_left
- node.right.should_not == original_node
- node.right.left.should_not == original_node_left_right
- end
+ obj.order.should == ["foo", "bar", "a", "b", "foo[]=", "bar.baz="]
end
- ruby_version_is "3.1" do
- it "evaluates from left to right, receivers first then methods" do
- obj = VariablesSpecs::EvalOrder.new
- obj.instance_eval do
- foo[0], bar.baz = a, b
- end
+ it "can be used to swap variables with nested method calls" do
+ node = VariablesSpecs::EvalOrder.new.node
- obj.order.should == ["foo", "bar", "a", "b", "foo[]=", "bar.baz="]
- end
+ original_node = node
+ original_node_left = node.left
+ original_node_left_right = node.left.right
- it "can be used to swap variables with nested method calls" do
- node = VariablesSpecs::EvalOrder.new.node
-
- original_node = node
- original_node_left = node.left
- original_node_left_right = node.left.right
-
- node.left, node.left.right, node = node.left.right, node, node.left
- # Should evaluate in the order of:
- # LHS: node, node.left(original_node_left)
- # RHS: original_node_left_right, original_node, original_node_left
- # Ops:
- # * node(original_node), original_node.left = original_node_left_right
- # * original_node_left.right = original_node
- # * node = original_node_left
-
- node.should == original_node_left
- node.right.should == original_node
- node.right.left.should == original_node_left_right
- end
+ node.left, node.left.right, node = node.left.right, node, node.left
+ # Should evaluate in the order of:
+ # LHS: node, node.left(original_node_left)
+ # RHS: original_node_left_right, original_node, original_node_left
+ # Ops:
+ # * node(original_node), original_node.left = original_node_left_right
+ # * original_node_left.right = original_node
+ # * node = original_node_left
+
+ node.should == original_node_left
+ node.right.should == original_node
+ node.right.left.should == original_node_left_right
end
end
end
@@ -381,6 +346,9 @@ describe "Multiple assignment" do
SINGLE_RHS_1, SINGLE_RHS_2 = 1
[SINGLE_RHS_1, SINGLE_RHS_2].should == [1, nil]
end
+ ensure
+ VariableSpecs.send(:remove_const, :SINGLE_RHS_1)
+ VariableSpecs.send(:remove_const, :SINGLE_RHS_2)
end
end
@@ -395,11 +363,22 @@ describe "Multiple assignment" do
a.should == []
end
- it "calls #to_a to convert nil to an empty Array" do
- nil.should_receive(:to_a).and_return([])
+ ruby_version_is "4.0" do
+ it "converts nil to empty array without calling a method" do
+ nil.should_not_receive(:to_a)
- (*a = *nil).should == []
- a.should == []
+ (*a = *nil).should == []
+ a.should == []
+ end
+ end
+
+ ruby_version_is ""..."4.0" do
+ it "calls #to_a to convert nil to an empty Array" do
+ nil.should_receive(:to_a).and_return([])
+
+ (*a = *nil).should == []
+ a.should == []
+ end
end
it "does not call #to_a on an Array" do
@@ -619,6 +598,8 @@ describe "Multiple assignment" do
(*SINGLE_SPLATTED_RHS) = *1
SINGLE_SPLATTED_RHS.should == [1]
end
+ ensure
+ VariableSpecs.send(:remove_const, :SINGLE_SPLATTED_RHS)
end
end
@@ -818,6 +799,9 @@ describe "Multiple assignment" do
MRHS_VALUES_1.should == 1
MRHS_VALUES_2.should == 2
end
+ ensure
+ VariableSpecs.send(:remove_const, :MRHS_VALUES_1)
+ VariableSpecs.send(:remove_const, :MRHS_VALUES_2)
end
it "assigns all RHS values as an array to a single LHS constant" do
@@ -825,6 +809,8 @@ describe "Multiple assignment" do
MRHS_VALUES = 1, 2, 3
MRHS_VALUES.should == [1, 2, 3]
end
+ ensure
+ VariableSpecs.send(:remove_const, :MRHS_VALUES)
end
end
diff --git a/spec/ruby/library/bigdecimal/BigDecimal_spec.rb b/spec/ruby/library/bigdecimal/BigDecimal_spec.rb
index 43a779b420..8596356abd 100644
--- a/spec/ruby/library/bigdecimal/BigDecimal_spec.rb
+++ b/spec/ruby/library/bigdecimal/BigDecimal_spec.rb
@@ -31,16 +31,12 @@ describe "Kernel#BigDecimal" do
end
it "accepts significant digits >= given precision" do
- suppress_warning do
- BigDecimal("3.1415923", 10).precs[1].should >= 10
- end
+ BigDecimal("3.1415923", 10).should == BigDecimal("3.1415923")
end
it "determines precision from initial value" do
pi_string = "3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593014782083152134043"
- suppress_warning {
- BigDecimal(pi_string).precs[1]
- }.should >= pi_string.size-1
+ BigDecimal(pi_string).precision.should == pi_string.size-1
end
it "ignores leading and trailing whitespace" do
@@ -98,7 +94,11 @@ describe "Kernel#BigDecimal" 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
+ if BigDecimal::VERSION >= "3.1.9"
+ BigDecimal("0.", exception: false).to_i.should == 0
+ else
+ BigDecimal("0.", exception: false).should be_nil
+ end
end
end
@@ -152,8 +152,10 @@ describe "Kernel#BigDecimal" do
BigDecimal("-12345.6E-1").should == -reference
end
- it "raises ArgumentError when Float is used without precision" do
- -> { BigDecimal(1.0) }.should raise_error(ArgumentError)
+ version_is BigDecimal::VERSION, "3.3.0" do
+ it "allows Float without precision" do
+ BigDecimal(1.2).should == BigDecimal("1.2")
+ end
end
it "returns appropriate BigDecimal zero for signed zero" do
@@ -202,14 +204,6 @@ describe "Kernel#BigDecimal" do
Float(@b).to_s.should == "166.66666666666666"
end
- it "has the expected precision on the LHS" do
- suppress_warning { @a.precs[0] }.should == 18
- end
-
- it "has the expected maximum precision on the LHS" do
- suppress_warning { @a.precs[1] }.should == 27
- end
-
it "produces the expected result when done via Float" do
(Float(@a) - Float(@b)).to_s.should == "-6.666596163995564e-10"
end
@@ -220,34 +214,10 @@ describe "Kernel#BigDecimal" do
# Check underlying methods work as we understand
- 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, _ = suppress_warning { b.precs }
- (precs >= 9).should be_true
- (precs >= n).should be_true
- (precs % 9).should == 0
- end
- 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 = suppress_warning { b.precs }
- max.should == precs + 9
- end
- suppress_warning { BigDecimal('NaN').precs[1] }.should == 9
- end
-
it "BigDecimal(Rational, 18) produces the result we expect" do
BigDecimal(@b, 18).to_s.should == "0.166666666666666667e3"
end
- it "BigDecimal(Rational, BigDecimal.precs[0]) produces the result we expect" do
- BigDecimal(@b, suppress_warning { @a.precs[0] }).to_s.should == "0.166666666666666667e3"
- end
-
# Check the top-level expression works as we expect
it "produces a BigDecimal" do
@@ -255,8 +225,8 @@ describe "Kernel#BigDecimal" do
end
it "produces the expected result" do
- @c.should == BigDecimal("-0.666667e-9")
- @c.to_s.should == "-0.666667e-9"
+ @c.round(15).should == BigDecimal("-0.666667e-9")
+ @c.round(15).to_s.should == "-0.666667e-9"
end
it "produces the correct class for other arithmetic operators" do
diff --git a/spec/ruby/library/bigdecimal/add_spec.rb b/spec/ruby/library/bigdecimal/add_spec.rb
index 542713011d..9cdab7d910 100644
--- a/spec/ruby/library/bigdecimal/add_spec.rb
+++ b/spec/ruby/library/bigdecimal/add_spec.rb
@@ -73,14 +73,6 @@ describe "BigDecimal#add" do
# BigDecimal("0.88").add(0.0, 1).should == BigDecimal("0.9")
# end
- describe "with Object" do
- it "tries to coerce the other operand to self" do
- object = mock("Object")
- object.should_receive(:coerce).with(@frac_3).and_return([@frac_3, @frac_4])
- @frac_3.add(object, 1).should == BigDecimal("0.1E16")
- end
- end
-
describe "with Rational" do
it "produces a BigDecimal" do
(@three + Rational(500, 2)).should == BigDecimal("0.253e3")
diff --git a/spec/ruby/library/bigdecimal/core_spec.rb b/spec/ruby/library/bigdecimal/core_spec.rb
index acee4dcf56..5097d70865 100644
--- a/spec/ruby/library/bigdecimal/core_spec.rb
+++ b/spec/ruby/library/bigdecimal/core_spec.rb
@@ -20,9 +20,12 @@ describe "Core extension by bigdecimal" do
describe "BigDecimal#log" do
it "handles high-precision Rational arguments" do
- result = BigDecimal('0.22314354220170971436137296411949880462556361100856391620766259404746040597133837784E0')
+ # log(BigDecimal(r, 50), 50)
+ result1 = BigDecimal('0.22314354220170971436137296411949880462556361100856e0')
+ # log(BigDecimal(r, 1000), 50)
+ result2 = BigDecimal('0.22314354220170971436137296411949880462556361100853e0')
r = Rational(1_234_567_890, 987_654_321)
- BigMath.log(r, 50).should == result
+ [result1, result2].should include(BigMath.log(r, 50).mult(1, 50))
end
end
diff --git a/spec/ruby/library/bigdecimal/divmod_spec.rb b/spec/ruby/library/bigdecimal/divmod_spec.rb
index 294f01cba0..85c014bb8c 100644
--- a/spec/ruby/library/bigdecimal/divmod_spec.rb
+++ b/spec/ruby/library/bigdecimal/divmod_spec.rb
@@ -33,14 +33,16 @@ describe "BigDecimal#mod_part_of_divmod" do
end
end
- it_behaves_like :bigdecimal_modulo, :mod_part_of_divmod
+ version_is BigDecimal::VERSION, ""..."4.0.0" do
+ it_behaves_like :bigdecimal_modulo, :mod_part_of_divmod
+ end
it "raises ZeroDivisionError if other is zero" do
bd5667 = BigDecimal("5667.19")
-
+ zero = BigDecimal("0")
-> { bd5667.mod_part_of_divmod(0) }.should raise_error(ZeroDivisionError)
-> { bd5667.mod_part_of_divmod(BigDecimal("0")) }.should raise_error(ZeroDivisionError)
- -> { @zero.mod_part_of_divmod(@zero) }.should raise_error(ZeroDivisionError)
+ -> { zero.mod_part_of_divmod(zero) }.should raise_error(ZeroDivisionError)
end
end
@@ -73,14 +75,25 @@ describe "BigDecimal#divmod" do
@zeroes = [@zero, @zero_pos, @zero_neg]
end
- it "divides value, returns an array" do
- res = @a.divmod(5)
- res.kind_of?(Array).should == true
+ version_is BigDecimal::VERSION, ""..."4.0.0" do
+ it "divides value, returns [BigDecimal, BigDecimal]" do
+ res = @a.divmod(5)
+ res.kind_of?(Array).should == true
+ DivmodSpecs.check_both_bigdecimal(res)
+ end
+ end
+
+ version_is BigDecimal::VERSION, "4.0.0" do
+ it "divides value, returns [Integer, BigDecimal]" do
+ res = @a.divmod(5)
+ res.kind_of?(Array).should == true
+ res[0].kind_of?(Integer).should == true
+ res[1].kind_of?(BigDecimal).should == true
+ end
end
it "array contains quotient and modulus as BigDecimal" do
res = @a.divmod(5)
- DivmodSpecs.check_both_bigdecimal(res)
res[0].should == BigDecimal('0.8E1')
res[1].should == BigDecimal('2.00000000000000000001')
@@ -123,17 +136,27 @@ describe "BigDecimal#divmod" do
values_and_zeroes.each do |val1|
values.each do |val2|
res = val1.divmod(val2)
- DivmodSpecs.check_both_bigdecimal(res)
res[0].should == ((val1/val2).floor)
res[1].should == (val1 - res[0] * val2)
end
end
end
- it "returns an array of two NaNs if NaN is involved" do
- (@special_vals + @regular_vals + @zeroes).each do |val|
- DivmodSpecs.check_both_nan(val.divmod(@nan))
- DivmodSpecs.check_both_nan(@nan.divmod(val))
+ version_is BigDecimal::VERSION, "4.0.0" do
+ it "raise FloatDomainError error if NaN is involved" do
+ (@special_vals + @regular_vals + @zeroes).each do |val|
+ -> { val.divmod(@nan) }.should raise_error(FloatDomainError)
+ -> { @nan.divmod(val) }.should raise_error(FloatDomainError)
+ end
+ end
+ end
+
+ version_is BigDecimal::VERSION, ""..."4.0.0" do
+ it "returns an array of two NaNs if NaN is involved" do
+ (@special_vals + @regular_vals + @zeroes).each do |val|
+ DivmodSpecs.check_both_nan(val.divmod(@nan))
+ DivmodSpecs.check_both_nan(@nan.divmod(val))
+ end
end
end
@@ -145,21 +168,30 @@ describe "BigDecimal#divmod" do
end
end
- it "returns an array of Infinity and NaN if the dividend is Infinity" do
- @regular_vals.each do |val|
- array = @infinity.divmod(val)
- array.length.should == 2
- array[0].infinite?.should == (val > 0 ? 1 : -1)
- array[1].should.nan?
+ version_is BigDecimal::VERSION, ""..."4.0.0" do
+ it "returns an array of Infinity and NaN if the dividend is Infinity" do
+ @regular_vals.each do |val|
+ array = @infinity.divmod(val)
+ array.length.should == 2
+ array[0].infinite?.should == (val > 0 ? 1 : -1)
+ array[1].should.nan?
+ end
end
end
- it "returns an array of zero and the dividend if the divisor is Infinity" do
- @regular_vals.each do |val|
- array = val.divmod(@infinity)
- array.length.should == 2
- array[0].should == @zero
- array[1].should == val
+ version_is BigDecimal::VERSION, "3.3.0" do
+ it "returns an array of zero and the dividend or minus one and Infinity if the divisor is Infinity" do
+ @regular_vals.each do |val|
+ array = val.divmod(@infinity)
+ array.length.should == 2
+ if val >= 0
+ array[0].should == @zero
+ array[1].should == val
+ else
+ array[0].should == @one_minus
+ array[1].should == @infinity
+ end
+ end
end
end
diff --git a/spec/ruby/library/bigdecimal/fix_spec.rb b/spec/ruby/library/bigdecimal/fix_spec.rb
index 231c9a587e..2c6276899e 100644
--- a/spec/ruby/library/bigdecimal/fix_spec.rb
+++ b/spec/ruby/library/bigdecimal/fix_spec.rb
@@ -2,20 +2,20 @@ require_relative '../../spec_helper'
require 'bigdecimal'
describe "BigDecimal#fix" do
- before :each do
- @zero = BigDecimal("0")
- @mixed = BigDecimal("1.23456789")
- @pos_int = BigDecimal("2E5555")
- @neg_int = BigDecimal("-2E5555")
- @pos_frac = BigDecimal("2E-9999")
- @neg_frac = BigDecimal("-2E-9999")
-
- @infinity = BigDecimal("Infinity")
- @infinity_neg = BigDecimal("-Infinity")
- @nan = BigDecimal("NaN")
- @zero_pos = BigDecimal("+0")
- @zero_neg = BigDecimal("-0")
- end
+ before :each do
+ @zero = BigDecimal("0")
+ @mixed = BigDecimal("1.23456789")
+ @pos_int = BigDecimal("2E5555")
+ @neg_int = BigDecimal("-2E5555")
+ @pos_frac = BigDecimal("2E-9999")
+ @neg_frac = BigDecimal("-2E-9999")
+
+ @infinity = BigDecimal("Infinity")
+ @infinity_neg = BigDecimal("-Infinity")
+ @nan = BigDecimal("NaN")
+ @zero_pos = BigDecimal("+0")
+ @zero_neg = BigDecimal("-0")
+ end
it "returns a BigDecimal" do
BigDecimal("2E100000000").fix.kind_of?(BigDecimal).should == true
diff --git a/spec/ruby/library/bigdecimal/mult_spec.rb b/spec/ruby/library/bigdecimal/mult_spec.rb
index b7f8044b0b..2353df9cb8 100644
--- a/spec/ruby/library/bigdecimal/mult_spec.rb
+++ b/spec/ruby/library/bigdecimal/mult_spec.rb
@@ -21,12 +21,4 @@ describe "BigDecimal#mult" do
@e.mult(@one, 1).should be_close(@one, @tolerance)
@e3_minus.mult(@one, 1).should be_close(0, @tolerance2)
end
-
- describe "with Object" do
- it "tries to coerce the other operand to self" do
- object = mock("Object")
- object.should_receive(:coerce).with(@e3_minus).and_return([@e3_minus, @e3_plus])
- @e3_minus.mult(object, 1).should == BigDecimal("9")
- end
- end
end
diff --git a/spec/ruby/library/bigdecimal/precs_spec.rb b/spec/ruby/library/bigdecimal/precs_spec.rb
deleted file mode 100644
index 5fda8d3087..0000000000
--- a/spec/ruby/library/bigdecimal/precs_spec.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-require_relative '../../spec_helper'
-require 'bigdecimal'
-
-describe "BigDecimal#precs" do
- before :each do
- @infinity = BigDecimal("Infinity")
- @infinity_neg = BigDecimal("-Infinity")
- @nan = BigDecimal("NaN")
- @zero = BigDecimal("0")
- @zero_neg = BigDecimal("-0")
-
- @arr = [BigDecimal("2E40001"), BigDecimal("3E-20001"),\
- @infinity, @infinity_neg, @nan, @zero, @zero_neg]
- @precision = BigDecimal::BASE.to_s.length - 1
- end
-
- it "returns array of two values" do
- 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
- 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
- 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
- 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/spec/ruby/library/bigdecimal/remainder_spec.rb b/spec/ruby/library/bigdecimal/remainder_spec.rb
index bac5f37ba9..0eb06f7ef1 100644
--- a/spec/ruby/library/bigdecimal/remainder_spec.rb
+++ b/spec/ruby/library/bigdecimal/remainder_spec.rb
@@ -37,9 +37,11 @@ describe "BigDecimal#remainder" do
@neg_int.remainder(@pos_frac).should == @neg_int - @pos_frac * (@neg_int / @pos_frac).truncate
end
- it "returns NaN used with zero" do
- @mixed.remainder(@zero).should.nan?
- @zero.remainder(@zero).should.nan?
+ version_is BigDecimal::VERSION, "3.3.0" do
+ it "raises ZeroDivisionError used with zero" do
+ -> { @mixed.remainder(@zero) }.should raise_error(ZeroDivisionError)
+ -> { @zero.remainder(@zero) }.should raise_error(ZeroDivisionError)
+ end
end
it "returns zero if used on zero" do
diff --git a/spec/ruby/library/bigdecimal/round_spec.rb b/spec/ruby/library/bigdecimal/round_spec.rb
index fba52df65d..6a4d220417 100644
--- a/spec/ruby/library/bigdecimal/round_spec.rb
+++ b/spec/ruby/library/bigdecimal/round_spec.rb
@@ -228,15 +228,7 @@ describe "BigDecimal#round" do
-> { BigDecimal('-Infinity').round(2) }.should_not raise_error(FloatDomainError)
end
- version_is BigDecimal::VERSION, ''...'3.1.3' do #ruby_version_is ''...'3.2' do
- it 'raise for a non-existent round mode' do
- -> { @p1_50.round(0, :nonsense) }.should raise_error(ArgumentError, "invalid rounding mode")
- end
- end
-
- version_is BigDecimal::VERSION, '3.1.3' do #ruby_version_is '3.2' do
- it 'raise for a non-existent round mode' do
- -> { @p1_50.round(0, :nonsense) }.should raise_error(ArgumentError, "invalid rounding mode (nonsense)")
- end
+ it 'raise for a non-existent round mode' do
+ -> { @p1_50.round(0, :nonsense) }.should raise_error(ArgumentError, "invalid rounding mode (nonsense)")
end
end
diff --git a/spec/ruby/library/bigdecimal/shared/modulo.rb b/spec/ruby/library/bigdecimal/shared/modulo.rb
index aa5c5a640b..eeb030fd23 100644
--- a/spec/ruby/library/bigdecimal/shared/modulo.rb
+++ b/spec/ruby/library/bigdecimal/shared/modulo.rb
@@ -101,10 +101,16 @@ describe :bigdecimal_modulo, shared: true do
@infinity_minus.send(@method, @infinity).should.nan?
end
- it "returns the dividend if the divisor is Infinity" do
- @one.send(@method, @infinity).should == @one
- @one.send(@method, @infinity_minus).should == @one
- @frac_2.send(@method, @infinity_minus).should == @frac_2
+ version_is BigDecimal::VERSION, "3.3.0" do
+ it "returns the dividend if the divisor is Infinity and signs are same" do
+ @one.send(@method, @infinity).should == @one
+ (-@frac_2).send(@method, @infinity_minus).should == -@frac_2
+ end
+
+ it "returns the divisor if the divisor is Infinity and signs are different" do
+ (-@one).send(@method, @infinity).should == @infinity
+ @frac_2.send(@method, @infinity_minus).should == @infinity_minus
+ end
end
it "raises TypeError if the argument cannot be coerced to BigDecimal" do
diff --git a/spec/ruby/library/bigdecimal/shared/power.rb b/spec/ruby/library/bigdecimal/shared/power.rb
index 568a08589b..6dafb638e2 100644
--- a/spec/ruby/library/bigdecimal/shared/power.rb
+++ b/spec/ruby/library/bigdecimal/shared/power.rb
@@ -10,8 +10,8 @@ describe :bigdecimal_power, shared: true do
e = BigDecimal("1.00000000000000000000123456789")
one = BigDecimal("1")
ten = BigDecimal("10")
- # The tolerance is dependent upon the size of BASE_FIG
- tolerance = BigDecimal("1E-70")
+ # Accuracy is at least ndigits(== 30) + DOUBLE_FIG(== 16)
+ tolerance = BigDecimal("1E-46")
ten_powers = BigDecimal("1E10000")
pi = BigDecimal("3.14159265358979")
e3_minus.send(@method, 2).should == e3_minus_power_2
diff --git a/spec/ruby/library/bigdecimal/shared/quo.rb b/spec/ruby/library/bigdecimal/shared/quo.rb
index 46e6d62bf4..18ff2fe9a5 100644
--- a/spec/ruby/library/bigdecimal/shared/quo.rb
+++ b/spec/ruby/library/bigdecimal/shared/quo.rb
@@ -31,6 +31,7 @@ describe :bigdecimal_quo, shared: true do
describe "with Object" do
it "tries to coerce the other operand to self" do
+ skip if @method == :div
object = mock("Object")
object.should_receive(:coerce).with(@one).and_return([@one, @two])
@one.send(@method, object, *@object).should == BigDecimal("0.5")
diff --git a/spec/ruby/library/bigdecimal/split_spec.rb b/spec/ruby/library/bigdecimal/split_spec.rb
index f9b4bab5f7..53b1f649d9 100644
--- a/spec/ruby/library/bigdecimal/split_spec.rb
+++ b/spec/ruby/library/bigdecimal/split_spec.rb
@@ -58,16 +58,16 @@ describe "BigDecimal#split" do
end
it "third value: the base (currently always ten)" do
- @arr[2].should == 10
- @arr_neg[2].should == 10
- @arr_big[2].should == 10
- @arr_big_neg[2].should == 10
- @huge[2].should == 10
- @infinity.split[2].should == 10
- @nan.split[2].should == 10
- @infinity_neg.split[2].should == 10
- @zero.split[2].should == 10
- @zero_neg.split[2].should == 10
+ @arr[2].should == 10
+ @arr_neg[2].should == 10
+ @arr_big[2].should == 10
+ @arr_big_neg[2].should == 10
+ @huge[2].should == 10
+ @infinity.split[2].should == 10
+ @nan.split[2].should == 10
+ @infinity_neg.split[2].should == 10
+ @zero.split[2].should == 10
+ @zero_neg.split[2].should == 10
end
it "fourth value: the exponent" do
diff --git a/spec/ruby/library/bigdecimal/sqrt_spec.rb b/spec/ruby/library/bigdecimal/sqrt_spec.rb
index 8fd1ec0f39..42cf4545cb 100644
--- a/spec/ruby/library/bigdecimal/sqrt_spec.rb
+++ b/spec/ruby/library/bigdecimal/sqrt_spec.rb
@@ -36,7 +36,7 @@ describe "BigDecimal#sqrt" do
BigDecimal('121').sqrt(5).should be_close(11, 0.00001)
end
- platform_is_not wordsize: 32 do # fails on i686
+ platform_is_not c_long_size: 32 do # fails on i686
it "returns square root of 0.9E-99999 with desired precision" do
@frac_2.sqrt(1).to_s.should =~ /\A0\.3E-49999\z/i
end
diff --git a/spec/ruby/library/bigdecimal/sub_spec.rb b/spec/ruby/library/bigdecimal/sub_spec.rb
index bddfec2186..3b62a0c794 100644
--- a/spec/ruby/library/bigdecimal/sub_spec.rb
+++ b/spec/ruby/library/bigdecimal/sub_spec.rb
@@ -35,14 +35,6 @@ describe "BigDecimal#sub" do
@frac_1.sub(@frac_1, 1000000).should == @zero
end
- describe "with Object" do
- it "tries to coerce the other operand to self" do
- object = mock("Object")
- object.should_receive(:coerce).with(@frac_3).and_return([@frac_3, @frac_4])
- @frac_3.sub(object, 1).should == BigDecimal("-0.9E15")
- end
- end
-
describe "with Rational" do
it "produces a BigDecimal" do
(@three - Rational(500, 2)).should == BigDecimal('-0.247e3')
diff --git a/spec/ruby/library/bigdecimal/to_i_spec.rb b/spec/ruby/library/bigdecimal/to_i_spec.rb
index 09481fce15..e5e65c562e 100644
--- a/spec/ruby/library/bigdecimal/to_i_spec.rb
+++ b/spec/ruby/library/bigdecimal/to_i_spec.rb
@@ -3,5 +3,5 @@ require_relative 'shared/to_int'
require 'bigdecimal'
describe "BigDecimal#to_i" do
- it_behaves_like :bigdecimal_to_int, :to_i
+ it_behaves_like :bigdecimal_to_int, :to_i
end
diff --git a/spec/ruby/library/bigdecimal/truncate_spec.rb b/spec/ruby/library/bigdecimal/truncate_spec.rb
index 4ad9eb92d1..0ae0421b30 100644
--- a/spec/ruby/library/bigdecimal/truncate_spec.rb
+++ b/spec/ruby/library/bigdecimal/truncate_spec.rb
@@ -4,11 +4,11 @@ require 'bigdecimal'
describe "BigDecimal#truncate" do
before :each do
- @arr = ['3.14159', '8.7', "0.314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593014782083152134043E1"]
- @big = BigDecimal("123456.789")
- @nan = BigDecimal('NaN')
- @infinity = BigDecimal('Infinity')
- @infinity_negative = BigDecimal('-Infinity')
+ @arr = ['3.14159', '8.7', "0.314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593014782083152134043E1"]
+ @big = BigDecimal("123456.789")
+ @nan = BigDecimal('NaN')
+ @infinity = BigDecimal('Infinity')
+ @infinity_negative = BigDecimal('-Infinity')
end
it "returns value of type Integer." do
diff --git a/spec/ruby/library/cgi/cookie/domain_spec.rb b/spec/ruby/library/cgi/cookie/domain_spec.rb
index 962609ebaf..0ed56d6d61 100644
--- a/spec/ruby/library/cgi/cookie/domain_spec.rb
+++ b/spec/ruby/library/cgi/cookie/domain_spec.rb
@@ -1,23 +1,26 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::Cookie#domain" do
- it "returns self's domain" do
- cookie = CGI::Cookie.new("test-cookie")
- cookie.domain.should be_nil
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- cookie = CGI::Cookie.new("name" => "test-cookie", "domain" => "example.com")
- cookie.domain.should == "example.com"
+ describe "CGI::Cookie#domain" do
+ it "returns self's domain" do
+ cookie = CGI::Cookie.new("test-cookie")
+ cookie.domain.should be_nil
+
+ cookie = CGI::Cookie.new("name" => "test-cookie", "domain" => "example.com")
+ cookie.domain.should == "example.com"
+ end
end
-end
-describe "CGI::Cookie#domain=" do
- it "sets self's domain" do
- cookie = CGI::Cookie.new("test-cookie")
- cookie.domain = "test.com"
- cookie.domain.should == "test.com"
+ describe "CGI::Cookie#domain=" do
+ it "sets self's domain" do
+ cookie = CGI::Cookie.new("test-cookie")
+ cookie.domain = "test.com"
+ cookie.domain.should == "test.com"
- cookie.domain = "example.com"
- cookie.domain.should == "example.com"
+ cookie.domain = "example.com"
+ cookie.domain.should == "example.com"
+ end
end
end
diff --git a/spec/ruby/library/cgi/cookie/expires_spec.rb b/spec/ruby/library/cgi/cookie/expires_spec.rb
index c8f26d01cd..c5b2c4faf9 100644
--- a/spec/ruby/library/cgi/cookie/expires_spec.rb
+++ b/spec/ruby/library/cgi/cookie/expires_spec.rb
@@ -1,23 +1,26 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::Cookie#expires" do
- it "returns self's expiration date" do
- cookie = CGI::Cookie.new("test-cookie")
- cookie.expires.should be_nil
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- cookie = CGI::Cookie.new("name" => "test-cookie", "expires" => Time.at(1196524602))
- cookie.expires.should == Time.at(1196524602)
+ describe "CGI::Cookie#expires" do
+ it "returns self's expiration date" do
+ cookie = CGI::Cookie.new("test-cookie")
+ cookie.expires.should be_nil
+
+ cookie = CGI::Cookie.new("name" => "test-cookie", "expires" => Time.at(1196524602))
+ cookie.expires.should == Time.at(1196524602)
+ end
end
-end
-describe "CGI::Cookie#expires=" do
- it "sets self's expiration date" do
- cookie = CGI::Cookie.new("test-cookie")
- cookie.expires = Time.at(1196524602)
- cookie.expires.should == Time.at(1196524602)
+ describe "CGI::Cookie#expires=" do
+ it "sets self's expiration date" do
+ cookie = CGI::Cookie.new("test-cookie")
+ cookie.expires = Time.at(1196524602)
+ cookie.expires.should == Time.at(1196524602)
- cookie.expires = Time.at(1196525000)
- cookie.expires.should == Time.at(1196525000)
+ cookie.expires = Time.at(1196525000)
+ cookie.expires.should == Time.at(1196525000)
+ end
end
end
diff --git a/spec/ruby/library/cgi/cookie/initialize_spec.rb b/spec/ruby/library/cgi/cookie/initialize_spec.rb
index 4b6e104b10..248f35e78b 100644
--- a/spec/ruby/library/cgi/cookie/initialize_spec.rb
+++ b/spec/ruby/library/cgi/cookie/initialize_spec.rb
@@ -1,147 +1,150 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::Cookie#initialize when passed String" do
- before :each do
- @cookie = CGI::Cookie.allocate
- end
-
- it "sets the self's name to the passed String" do
- @cookie.send(:initialize, "test-cookie")
- @cookie.name.should == "test-cookie"
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- it "sets the self's value to an empty Array" do
- @cookie.send(:initialize, "test-cookie")
- @cookie.value.should == []
- end
-
- it "sets self to a non-secure cookie" do
- @cookie.send(:initialize, "test")
- @cookie.secure.should be_false
- end
-
- it "does set self's path to an empty String when ENV[\"SCRIPT_NAME\"] is not set" do
- @cookie.send(:initialize, "test-cookie")
- @cookie.path.should == ""
- end
-
- it "does set self's path based on ENV[\"SCRIPT_NAME\"] when ENV[\"SCRIPT_NAME\"] is set" do
- old_script_name = ENV["SCRIPT_NAME"]
+ describe "CGI::Cookie#initialize when passed String" do
+ before :each do
+ @cookie = CGI::Cookie.allocate
+ end
- begin
- ENV["SCRIPT_NAME"] = "some/path/script.rb"
+ it "sets the self's name to the passed String" do
@cookie.send(:initialize, "test-cookie")
- @cookie.path.should == "some/path/"
+ @cookie.name.should == "test-cookie"
+ end
- ENV["SCRIPT_NAME"] = "script.rb"
+ it "sets the self's value to an empty Array" do
@cookie.send(:initialize, "test-cookie")
- @cookie.path.should == ""
+ @cookie.value.should == []
+ end
- ENV["SCRIPT_NAME"] = nil
+ it "sets self to a non-secure cookie" do
+ @cookie.send(:initialize, "test")
+ @cookie.secure.should be_false
+ end
+
+ it "does set self's path to an empty String when ENV[\"SCRIPT_NAME\"] is not set" do
@cookie.send(:initialize, "test-cookie")
@cookie.path.should == ""
- ensure
- ENV["SCRIPT_NAME"] = old_script_name
end
- end
- it "does not set self's expiration date" do
- @cookie.expires.should be_nil
- end
+ it "does set self's path based on ENV[\"SCRIPT_NAME\"] when ENV[\"SCRIPT_NAME\"] is set" do
+ old_script_name = ENV["SCRIPT_NAME"]
- it "does not set self's domain" do
- @cookie.domain.should be_nil
- end
-end
+ begin
+ ENV["SCRIPT_NAME"] = "some/path/script.rb"
+ @cookie.send(:initialize, "test-cookie")
+ @cookie.path.should == "some/path/"
-describe "CGI::Cookie#initialize when passed Hash" do
- before :each do
- @cookie = CGI::Cookie.allocate
- end
+ ENV["SCRIPT_NAME"] = "script.rb"
+ @cookie.send(:initialize, "test-cookie")
+ @cookie.path.should == ""
+
+ ENV["SCRIPT_NAME"] = nil
+ @cookie.send(:initialize, "test-cookie")
+ @cookie.path.should == ""
+ ensure
+ ENV["SCRIPT_NAME"] = old_script_name
+ end
+ end
+
+ it "does not set self's expiration date" do
+ @cookie.expires.should be_nil
+ end
- it "sets self's contents based on the passed Hash" do
- @cookie.send(:initialize,
- 'name' => 'test-cookie',
- 'value' => ["one", "two", "three"],
- 'path' => 'some/path/',
- 'domain' => 'example.com',
- 'expires' => Time.at(1196524602),
- 'secure' => true)
-
- @cookie.name.should == "test-cookie"
- @cookie.value.should == ["one", "two", "three"]
- @cookie.path.should == "some/path/"
- @cookie.domain.should == "example.com"
- @cookie.expires.should == Time.at(1196524602)
- @cookie.secure.should be_true
+ it "does not set self's domain" do
+ @cookie.domain.should be_nil
+ end
end
- it "does set self's path based on ENV[\"SCRIPT_NAME\"] when the Hash has no 'path' entry" do
- old_script_name = ENV["SCRIPT_NAME"]
+ describe "CGI::Cookie#initialize when passed Hash" do
+ before :each do
+ @cookie = CGI::Cookie.allocate
+ end
- begin
- ENV["SCRIPT_NAME"] = "some/path/script.rb"
- @cookie.send(:initialize, 'name' => 'test-cookie')
+ it "sets self's contents based on the passed Hash" do
+ @cookie.send(:initialize,
+ 'name' => 'test-cookie',
+ 'value' => ["one", "two", "three"],
+ 'path' => 'some/path/',
+ 'domain' => 'example.com',
+ 'expires' => Time.at(1196524602),
+ 'secure' => true)
+
+ @cookie.name.should == "test-cookie"
+ @cookie.value.should == ["one", "two", "three"]
@cookie.path.should == "some/path/"
+ @cookie.domain.should == "example.com"
+ @cookie.expires.should == Time.at(1196524602)
+ @cookie.secure.should be_true
+ end
- ENV["SCRIPT_NAME"] = "script.rb"
- @cookie.send(:initialize, 'name' => 'test-cookie')
- @cookie.path.should == ""
+ it "does set self's path based on ENV[\"SCRIPT_NAME\"] when the Hash has no 'path' entry" do
+ old_script_name = ENV["SCRIPT_NAME"]
- ENV["SCRIPT_NAME"] = nil
- @cookie.send(:initialize, 'name' => 'test-cookie')
- @cookie.path.should == ""
- ensure
- ENV["SCRIPT_NAME"] = old_script_name
+ begin
+ ENV["SCRIPT_NAME"] = "some/path/script.rb"
+ @cookie.send(:initialize, 'name' => 'test-cookie')
+ @cookie.path.should == "some/path/"
+
+ ENV["SCRIPT_NAME"] = "script.rb"
+ @cookie.send(:initialize, 'name' => 'test-cookie')
+ @cookie.path.should == ""
+
+ ENV["SCRIPT_NAME"] = nil
+ @cookie.send(:initialize, 'name' => 'test-cookie')
+ @cookie.path.should == ""
+ ensure
+ ENV["SCRIPT_NAME"] = old_script_name
+ end
end
- end
- it "tries to convert the Hash's 'value' to an Array using #Array" do
- obj = mock("Converted To Array")
- obj.should_receive(:to_ary).and_return(["1", "2", "3"])
- @cookie.send(:initialize,
- 'name' => 'test-cookie',
- 'value' => obj)
- @cookie.value.should == [ "1", "2", "3" ]
-
- obj = mock("Converted To Array")
- obj.should_receive(:to_a).and_return(["one", "two", "three"])
- @cookie.send(:initialize,
- 'name' => 'test-cookie',
- 'value' => obj)
- @cookie.value.should == [ "one", "two", "three" ]
-
- obj = mock("Put into an Array")
- @cookie.send(:initialize,
- 'name' => 'test-cookie',
- 'value' => obj)
- @cookie.value.should == [ obj ]
- end
+ it "tries to convert the Hash's 'value' to an Array using #Array" do
+ obj = mock("Converted To Array")
+ obj.should_receive(:to_ary).and_return(["1", "2", "3"])
+ @cookie.send(:initialize,
+ 'name' => 'test-cookie',
+ 'value' => obj)
+ @cookie.value.should == [ "1", "2", "3" ]
+
+ obj = mock("Converted To Array")
+ obj.should_receive(:to_a).and_return(["one", "two", "three"])
+ @cookie.send(:initialize,
+ 'name' => 'test-cookie',
+ 'value' => obj)
+ @cookie.value.should == [ "one", "two", "three" ]
+
+ obj = mock("Put into an Array")
+ @cookie.send(:initialize,
+ 'name' => 'test-cookie',
+ 'value' => obj)
+ @cookie.value.should == [ obj ]
+ end
- it "raises a ArgumentError when the passed Hash has no 'name' entry" do
- -> { @cookie.send(:initialize, {}) }.should raise_error(ArgumentError)
- -> { @cookie.send(:initialize, "value" => "test") }.should raise_error(ArgumentError)
+ it "raises a ArgumentError when the passed Hash has no 'name' entry" do
+ -> { @cookie.send(:initialize, {}) }.should raise_error(ArgumentError)
+ -> { @cookie.send(:initialize, "value" => "test") }.should raise_error(ArgumentError)
+ end
end
-end
-describe "CGI::Cookie#initialize when passed String, values ..." do
- before :each do
- @cookie = CGI::Cookie.allocate
- end
+ describe "CGI::Cookie#initialize when passed String, values ..." do
+ before :each do
+ @cookie = CGI::Cookie.allocate
+ end
- it "sets the self's name to the passed String" do
- @cookie.send(:initialize, "test-cookie", "one", "two", "three")
- @cookie.name.should == "test-cookie"
- end
+ it "sets the self's name to the passed String" do
+ @cookie.send(:initialize, "test-cookie", "one", "two", "three")
+ @cookie.name.should == "test-cookie"
+ end
- it "sets the self's value to an Array containing all passed values" do
- @cookie.send(:initialize, "test-cookie", "one", "two", "three")
- @cookie.value.should == ["one", "two", "three"]
- end
+ it "sets the self's value to an Array containing all passed values" do
+ @cookie.send(:initialize, "test-cookie", "one", "two", "three")
+ @cookie.value.should == ["one", "two", "three"]
+ end
- it "sets self to a non-secure cookie" do
- @cookie.send(:initialize, "test", "one", "two", "three")
- @cookie.secure.should be_false
+ it "sets self to a non-secure cookie" do
+ @cookie.send(:initialize, "test", "one", "two", "three")
+ @cookie.secure.should be_false
+ end
end
end
diff --git a/spec/ruby/library/cgi/cookie/name_spec.rb b/spec/ruby/library/cgi/cookie/name_spec.rb
index 326a43ade3..4908204e8a 100644
--- a/spec/ruby/library/cgi/cookie/name_spec.rb
+++ b/spec/ruby/library/cgi/cookie/name_spec.rb
@@ -1,23 +1,26 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::Cookie#name" do
- it "returns self's name" do
- cookie = CGI::Cookie.new("test-cookie")
- cookie.name.should == "test-cookie"
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- cookie = CGI::Cookie.new("name" => "another-cookie")
- cookie.name.should == "another-cookie"
+ describe "CGI::Cookie#name" do
+ it "returns self's name" do
+ cookie = CGI::Cookie.new("test-cookie")
+ cookie.name.should == "test-cookie"
+
+ cookie = CGI::Cookie.new("name" => "another-cookie")
+ cookie.name.should == "another-cookie"
+ end
end
-end
-describe "CGI::Cookie#name=" do
- it "sets self's expiration date" do
- cookie = CGI::Cookie.new("test-cookie")
- cookie.name = "another-name"
- cookie.name.should == "another-name"
+ describe "CGI::Cookie#name=" do
+ it "sets self's expiration date" do
+ cookie = CGI::Cookie.new("test-cookie")
+ cookie.name = "another-name"
+ cookie.name.should == "another-name"
- cookie.name = "and-one-more"
- cookie.name.should == "and-one-more"
+ cookie.name = "and-one-more"
+ cookie.name.should == "and-one-more"
+ end
end
end
diff --git a/spec/ruby/library/cgi/cookie/parse_spec.rb b/spec/ruby/library/cgi/cookie/parse_spec.rb
index d484c7bad9..bc505c37ba 100644
--- a/spec/ruby/library/cgi/cookie/parse_spec.rb
+++ b/spec/ruby/library/cgi/cookie/parse_spec.rb
@@ -1,26 +1,29 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::Cookie.parse" do
- it "parses a raw cookie string into a hash of Cookies" do
- expected = { "test-cookie" => ["one", "two", "three"] }
- CGI::Cookie.parse("test-cookie=one&two&three").should == expected
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- expected = { "second-cookie" => ["three", "four"], "first-cookie" => ["one", "two"] }
- CGI::Cookie.parse("first-cookie=one&two;second-cookie=three&four").should == expected
- end
+ describe "CGI::Cookie.parse" do
+ it "parses a raw cookie string into a hash of Cookies" do
+ expected = { "test-cookie" => ["one", "two", "three"] }
+ CGI::Cookie.parse("test-cookie=one&two&three").should == expected
- it "does not use , for cookie separators" do
- expected = {
- "first-cookie" => ["one", "two"],
- "second-cookie" => ["three", "four,third_cookie=five", "six"]
- }
- CGI::Cookie.parse("first-cookie=one&two;second-cookie=three&four,third_cookie=five&six").should == expected
- end
+ expected = { "second-cookie" => ["three", "four"], "first-cookie" => ["one", "two"] }
+ CGI::Cookie.parse("first-cookie=one&two;second-cookie=three&four").should == expected
+ end
+
+ it "does not use , for cookie separators" do
+ expected = {
+ "first-cookie" => ["one", "two"],
+ "second-cookie" => ["three", "four,third_cookie=five", "six"]
+ }
+ CGI::Cookie.parse("first-cookie=one&two;second-cookie=three&four,third_cookie=five&six").should == expected
+ end
- it "unescapes the Cookie values" do
- cookie = "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%7E"
- expected = { "test-cookie" => [ " !\"\#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" ] }
- CGI::Cookie.parse(cookie).should == expected
+ it "unescapes the Cookie values" do
+ cookie = "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%7E"
+ expected = { "test-cookie" => [ " !\"\#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" ] }
+ CGI::Cookie.parse(cookie).should == expected
+ end
end
end
diff --git a/spec/ruby/library/cgi/cookie/path_spec.rb b/spec/ruby/library/cgi/cookie/path_spec.rb
index 8a2f05aa50..13ee5d726b 100644
--- a/spec/ruby/library/cgi/cookie/path_spec.rb
+++ b/spec/ruby/library/cgi/cookie/path_spec.rb
@@ -1,23 +1,26 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::Cookie#path" do
- it "returns self's path" do
- cookie = CGI::Cookie.new("test-cookie")
- cookie.path.should == ""
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- cookie = CGI::Cookie.new("name" => "test-cookie", "path" => "/some/path/")
- cookie.path.should == "/some/path/"
+ describe "CGI::Cookie#path" do
+ it "returns self's path" do
+ cookie = CGI::Cookie.new("test-cookie")
+ cookie.path.should == ""
+
+ cookie = CGI::Cookie.new("name" => "test-cookie", "path" => "/some/path/")
+ cookie.path.should == "/some/path/"
+ end
end
-end
-describe "CGI::Cookie#path=" do
- it "sets self's path" do
- cookie = CGI::Cookie.new("test-cookie")
- cookie.path = "/some/path/"
- cookie.path.should == "/some/path/"
+ describe "CGI::Cookie#path=" do
+ it "sets self's path" do
+ cookie = CGI::Cookie.new("test-cookie")
+ cookie.path = "/some/path/"
+ cookie.path.should == "/some/path/"
- cookie.path = "/another/path/"
- cookie.path.should == "/another/path/"
+ cookie.path = "/another/path/"
+ cookie.path.should == "/another/path/"
+ end
end
end
diff --git a/spec/ruby/library/cgi/cookie/secure_spec.rb b/spec/ruby/library/cgi/cookie/secure_spec.rb
index 694bc2eeed..cb38c8c2e0 100644
--- a/spec/ruby/library/cgi/cookie/secure_spec.rb
+++ b/spec/ruby/library/cgi/cookie/secure_spec.rb
@@ -1,70 +1,73 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::Cookie#secure" do
- before :each do
- @cookie = CGI::Cookie.new("test-cookie")
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- it "returns whether self is a secure cookie or not" do
- @cookie.secure = true
- @cookie.secure.should be_true
+ describe "CGI::Cookie#secure" do
+ before :each do
+ @cookie = CGI::Cookie.new("test-cookie")
+ end
- @cookie.secure = false
- @cookie.secure.should be_false
- end
-end
+ it "returns whether self is a secure cookie or not" do
+ @cookie.secure = true
+ @cookie.secure.should be_true
-describe "CGI::Cookie#secure= when passed true" do
- before :each do
- @cookie = CGI::Cookie.new("test-cookie")
+ @cookie.secure = false
+ @cookie.secure.should be_false
+ end
end
- it "returns true" do
- (@cookie.secure = true).should be_true
- end
+ describe "CGI::Cookie#secure= when passed true" do
+ before :each do
+ @cookie = CGI::Cookie.new("test-cookie")
+ end
- it "sets self to a secure cookie" do
- @cookie.secure = true
- @cookie.secure.should be_true
- end
-end
+ it "returns true" do
+ (@cookie.secure = true).should be_true
+ end
-describe "CGI::Cookie#secure= when passed false" do
- before :each do
- @cookie = CGI::Cookie.new("test-cookie")
+ it "sets self to a secure cookie" do
+ @cookie.secure = true
+ @cookie.secure.should be_true
+ end
end
- it "returns false" do
- (@cookie.secure = false).should be_false
- end
+ describe "CGI::Cookie#secure= when passed false" do
+ before :each do
+ @cookie = CGI::Cookie.new("test-cookie")
+ end
- it "sets self to a non-secure cookie" do
- @cookie.secure = false
- @cookie.secure.should be_false
- end
-end
+ it "returns false" do
+ (@cookie.secure = false).should be_false
+ end
-describe "CGI::Cookie#secure= when passed Object" do
- before :each do
- @cookie = CGI::Cookie.new("test-cookie")
+ it "sets self to a non-secure cookie" do
+ @cookie.secure = false
+ @cookie.secure.should be_false
+ end
end
- it "does not change self's secure value" do
- @cookie.secure = false
+ describe "CGI::Cookie#secure= when passed Object" do
+ before :each do
+ @cookie = CGI::Cookie.new("test-cookie")
+ end
+
+ it "does not change self's secure value" do
+ @cookie.secure = false
- @cookie.secure = Object.new
- @cookie.secure.should be_false
+ @cookie.secure = Object.new
+ @cookie.secure.should be_false
- @cookie.secure = "Test"
- @cookie.secure.should be_false
+ @cookie.secure = "Test"
+ @cookie.secure.should be_false
- @cookie.secure = true
+ @cookie.secure = true
- @cookie.secure = Object.new
- @cookie.secure.should be_true
+ @cookie.secure = Object.new
+ @cookie.secure.should be_true
- @cookie.secure = "Test"
- @cookie.secure.should be_true
+ @cookie.secure = "Test"
+ @cookie.secure.should be_true
+ end
end
end
diff --git a/spec/ruby/library/cgi/cookie/to_s_spec.rb b/spec/ruby/library/cgi/cookie/to_s_spec.rb
index da15e6ed2a..20d2579f8d 100644
--- a/spec/ruby/library/cgi/cookie/to_s_spec.rb
+++ b/spec/ruby/library/cgi/cookie/to_s_spec.rb
@@ -1,33 +1,36 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::Cookie#to_s" do
- it "returns a String representation of self" do
- cookie = CGI::Cookie.new("test-cookie")
- cookie.to_s.should == "test-cookie=; path="
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- cookie = CGI::Cookie.new("test-cookie", "value")
- cookie.to_s.should == "test-cookie=value; path="
+ describe "CGI::Cookie#to_s" do
+ it "returns a String representation of self" do
+ cookie = CGI::Cookie.new("test-cookie")
+ cookie.to_s.should == "test-cookie=; path="
- cookie = CGI::Cookie.new("test-cookie", "one", "two", "three")
- cookie.to_s.should == "test-cookie=one&two&three; path="
+ cookie = CGI::Cookie.new("test-cookie", "value")
+ cookie.to_s.should == "test-cookie=value; path="
- cookie = CGI::Cookie.new(
- 'name' => 'test-cookie',
- 'value' => ["one", "two", "three"],
- 'path' => 'some/path/',
- 'domain' => 'example.com',
- 'expires' => Time.at(1196524602),
- 'secure' => true)
- cookie.to_s.should == "test-cookie=one&two&three; domain=example.com; path=some/path/; expires=Sat, 01 Dec 2007 15:56:42 GMT; secure"
- end
+ cookie = CGI::Cookie.new("test-cookie", "one", "two", "three")
+ cookie.to_s.should == "test-cookie=one&two&three; path="
- it "escapes the self's values" do
- cookie = CGI::Cookie.new("test-cookie", " !\"\#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}")
- 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
+ cookie = CGI::Cookie.new(
+ 'name' => 'test-cookie',
+ 'value' => ["one", "two", "three"],
+ 'path' => 'some/path/',
+ 'domain' => 'example.com',
+ 'expires' => Time.at(1196524602),
+ 'secure' => true)
+ cookie.to_s.should == "test-cookie=one&two&three; domain=example.com; path=some/path/; expires=Sat, 01 Dec 2007 15:56:42 GMT; secure"
+ end
+
+ it "escapes the self's values" do
+ cookie = CGI::Cookie.new("test-cookie", " !\"\#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}")
+ 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
- it "does not escape tilde" do
- cookie = CGI::Cookie.new("test-cookie", "~").to_s.should == "test-cookie=~; path="
+ it "does not escape tilde" do
+ cookie = CGI::Cookie.new("test-cookie", "~").to_s.should == "test-cookie=~; path="
+ end
end
end
diff --git a/spec/ruby/library/cgi/cookie/value_spec.rb b/spec/ruby/library/cgi/cookie/value_spec.rb
index 1d5da3a3ac..672653d7f4 100644
--- a/spec/ruby/library/cgi/cookie/value_spec.rb
+++ b/spec/ruby/library/cgi/cookie/value_spec.rb
@@ -1,76 +1,79 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::Cookie#value" do
- it "returns self's value" do
- cookie = CGI::Cookie.new("test-cookie")
- cookie.value.should == []
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- cookie = CGI::Cookie.new("test-cookie", "one")
- cookie.value.should == ["one"]
+ describe "CGI::Cookie#value" do
+ it "returns self's value" do
+ cookie = CGI::Cookie.new("test-cookie")
+ cookie.value.should == []
- cookie = CGI::Cookie.new("test-cookie", "one", "two", "three")
- cookie.value.should == ["one", "two", "three"]
+ cookie = CGI::Cookie.new("test-cookie", "one")
+ cookie.value.should == ["one"]
- cookie = CGI::Cookie.new("name" => "test-cookie", "value" => ["one", "two", "three"])
- cookie.value.should == ["one", "two", "three"]
- end
+ cookie = CGI::Cookie.new("test-cookie", "one", "two", "three")
+ cookie.value.should == ["one", "two", "three"]
- it "is in synch with self" do
- fail = []
- [
- :pop,
- :shift,
- [:<<, "Hello"],
- [:push, "Hello"],
- [:unshift, "World"],
- [:replace, ["A", "B"]],
- [:[]=, 1, "Set"],
- [:delete, "first"],
- [:delete_at, 0],
- ].each do |method, *args|
- cookie1 = CGI::Cookie.new("test-cookie", "first", "second")
- cookie2 = CGI::Cookie.new("test-cookie", "first", "second")
- cookie1.send(method, *args)
- cookie2.value.send(method, *args)
- fail << method unless cookie1.value == cookie2.value
+ cookie = CGI::Cookie.new("name" => "test-cookie", "value" => ["one", "two", "three"])
+ cookie.value.should == ["one", "two", "three"]
end
- fail.should be_empty
- end
-end
-describe "CGI::Cookie#value=" do
- before :each do
- @cookie = CGI::Cookie.new("test-cookie")
+ it "is in synch with self" do
+ fail = []
+ [
+ :pop,
+ :shift,
+ [:<<, "Hello"],
+ [:push, "Hello"],
+ [:unshift, "World"],
+ [:replace, ["A", "B"]],
+ [:[]=, 1, "Set"],
+ [:delete, "first"],
+ [:delete_at, 0],
+ ].each do |method, *args|
+ cookie1 = CGI::Cookie.new("test-cookie", "first", "second")
+ cookie2 = CGI::Cookie.new("test-cookie", "first", "second")
+ cookie1.send(method, *args)
+ cookie2.value.send(method, *args)
+ fail << method unless cookie1.value == cookie2.value
+ end
+ fail.should be_empty
+ end
end
- it "sets self's value" do
- @cookie.value = ["one"]
- @cookie.value.should == ["one"]
+ describe "CGI::Cookie#value=" do
+ before :each do
+ @cookie = CGI::Cookie.new("test-cookie")
+ end
- @cookie.value = ["one", "two", "three"]
- @cookie.value.should == ["one", "two", "three"]
- end
+ it "sets self's value" do
+ @cookie.value = ["one"]
+ @cookie.value.should == ["one"]
- it "automatically converts the passed Object to an Array using #Array" do
- @cookie.value = "test"
- @cookie.value.should == ["test"]
+ @cookie.value = ["one", "two", "three"]
+ @cookie.value.should == ["one", "two", "three"]
+ end
- obj = mock("to_a")
- obj.should_receive(:to_a).and_return(["1", "2"])
- @cookie.value = obj
- @cookie.value.should == ["1", "2"]
+ it "automatically converts the passed Object to an Array using #Array" do
+ @cookie.value = "test"
+ @cookie.value.should == ["test"]
- obj = mock("to_ary")
- obj.should_receive(:to_ary).and_return(["1", "2"])
- @cookie.value = obj
- @cookie.value.should == ["1", "2"]
- end
+ obj = mock("to_a")
+ obj.should_receive(:to_a).and_return(["1", "2"])
+ @cookie.value = obj
+ @cookie.value.should == ["1", "2"]
- it "does keep self and the values in sync" do
- @cookie.value = ["one", "two", "three"]
- @cookie[0].should == "one"
- @cookie[1].should == "two"
- @cookie[2].should == "three"
+ obj = mock("to_ary")
+ obj.should_receive(:to_ary).and_return(["1", "2"])
+ @cookie.value = obj
+ @cookie.value.should == ["1", "2"]
+ end
+
+ it "does keep self and the values in sync" do
+ @cookie.value = ["one", "two", "three"]
+ @cookie[0].should == "one"
+ @cookie[1].should == "two"
+ @cookie[2].should == "three"
+ end
end
end
diff --git a/spec/ruby/library/cgi/escapeElement_spec.rb b/spec/ruby/library/cgi/escapeElement_spec.rb
index 148926c453..72c38d6028 100644
--- a/spec/ruby/library/cgi/escapeElement_spec.rb
+++ b/spec/ruby/library/cgi/escapeElement_spec.rb
@@ -1,5 +1,11 @@
require_relative '../../spec_helper'
-require 'cgi'
+
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+end
+ruby_version_is "4.0" do
+ require 'cgi/escape'
+end
describe "CGI.escapeElement when passed String, elements, ..." do
it "escapes only the tags of the passed elements in the passed String" do
diff --git a/spec/ruby/library/cgi/escapeHTML_spec.rb b/spec/ruby/library/cgi/escapeHTML_spec.rb
index 421aac5d4a..6e70e87ed7 100644
--- a/spec/ruby/library/cgi/escapeHTML_spec.rb
+++ b/spec/ruby/library/cgi/escapeHTML_spec.rb
@@ -1,5 +1,9 @@
require_relative '../../spec_helper'
-require 'cgi'
+begin
+ require 'cgi/escape'
+rescue LoadError
+ require 'cgi'
+end
describe "CGI.escapeHTML" do
it "escapes special HTML characters (&\"<>') in the passed argument" do
diff --git a/spec/ruby/library/cgi/escapeURIComponent_spec.rb b/spec/ruby/library/cgi/escapeURIComponent_spec.rb
index f05795a2f5..1cea2b786a 100644
--- a/spec/ruby/library/cgi/escapeURIComponent_spec.rb
+++ b/spec/ruby/library/cgi/escapeURIComponent_spec.rb
@@ -1,57 +1,78 @@
require_relative '../../spec_helper'
-require 'cgi'
+begin
+ require 'cgi/escape'
+rescue LoadError
+ require 'cgi'
+end
-ruby_version_is "3.2" do
- describe "CGI.escapeURIComponent" do
- it "escapes whitespace" do
- string = "&<>\" \xE3\x82\x86\xE3\x82\x93\xE3\x82\x86\xE3\x82\x93"
- CGI.escapeURIComponent(string).should == '%26%3C%3E%22%20%E3%82%86%E3%82%93%E3%82%86%E3%82%93'
- end
+describe "CGI.escapeURIComponent" do
+ it "percent-encodes characters reserved according to RFC 3986" do
+ # https://www.rfc-editor.org/rfc/rfc3986#section-2.2
+ string = ":/?#[]@!$&'()*+,;="
+ CGI.escapeURIComponent(string).should == "%3A%2F%3F%23%5B%5D%40%21%24%26%27%28%29%2A%2B%2C%3B%3D"
+ end
- it "does not escape with unreserved characters" do
- string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"
- CGI.escapeURIComponent(string).should == "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"
- end
+ it "does not percent-encode unreserved characters according to RFC 3986" do
+ string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"
+ CGI.escapeURIComponent(string).should == "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"
+ end
- it "supports String with invalid encoding" do
- string = "\xC0\<\<".dup.force_encoding("UTF-8")
- CGI.escapeURIComponent(string).should == "%C0%3C%3C"
- end
+ it "encodes % character as %25" do
+ CGI.escapeURIComponent("%").should == "%25"
+ end
- it "processes String bytes one by one, not characters" do
- CGI.escapeURIComponent("β").should == "%CE%B2" # "β" bytes representation is CE B2
- end
+ # Compare to .escape which uses "+".
+ it "percent-encodes single whitespace" do
+ CGI.escapeURIComponent(" ").should == "%20"
+ end
- it "raises a TypeError with nil" do
- -> {
- CGI.escapeURIComponent(nil)
- }.should raise_error(TypeError, 'no implicit conversion of nil into String')
- end
+ it "percent-encodes all non-reserved and non-unreserved ASCII characters" do
+ special_set = ":/?#[]@!$&'()*+,;=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"
+ all_other = (0x00..0x7F).filter_map { |i| i.chr unless special_set.include?(i.chr) }.join
+ encoded = CGI.escapeURIComponent(all_other)
+ encoded.should.match?(/\A(?:%[0-9A-F]{2}){#{all_other.length}}\z/)
+ end
- it "encodes empty string" do
- CGI.escapeURIComponent("").should == ""
- end
+ it "percent-encodes non-ASCII bytes" do
+ bytes = (0x80..0xFF).map(&:chr).join
+ encoded = CGI.escapeURIComponent(bytes)
+ encoded.should.match?(/\A(?:%[0-9A-F]{2}){#{bytes.length}}\z/)
+ end
- it "encodes single whitespace" do
- CGI.escapeURIComponent(" ").should == "%20"
- end
+ it "processes multi-byte characters as separate bytes, percent-encoding each one" do
+ CGI.escapeURIComponent("β").should == "%CE%B2" # "β" bytes representation is CE B2
+ end
- it "encodes double whitespace" do
- CGI.escapeURIComponent(" ").should == "%20%20"
- end
+ it "produces a copy of an empty string" do
+ string = "".encode(Encoding::BINARY)
+ encoded = CGI.escapeURIComponent(string)
+ encoded.should == ""
+ encoded.encoding.should == Encoding::BINARY
+ string.should_not.equal?(encoded)
+ end
- it "preserves encoding" do
- string = "whatever".encode("ASCII-8BIT")
- CGI.escapeURIComponent(string).encoding.should == Encoding::ASCII_8BIT
- end
+ it "preserves string's encoding" do
+ string = "whatever".encode("ASCII-8BIT")
+ CGI.escapeURIComponent(string).encoding.should == Encoding::ASCII_8BIT
+ end
- it "uses implicit type conversion to String" do
- object = Object.new
- def object.to_str
- "a b"
- end
+ it "processes even strings with invalid encoding, percent-encoding octets as-is" do
+ string = "\xC0<<".dup.force_encoding("UTF-8")
+ CGI.escapeURIComponent(string).should == "%C0%3C%3C"
+ end
- CGI.escapeURIComponent(object).should == "a%20b"
+ it "raises a TypeError with nil" do
+ -> {
+ CGI.escapeURIComponent(nil)
+ }.should raise_error(TypeError, "no implicit conversion of nil into String")
+ end
+
+ it "uses implicit type conversion to String" do
+ object = Object.new
+ def object.to_str
+ "a b"
end
+
+ CGI.escapeURIComponent(object).should == "a%20b"
end
end
diff --git a/spec/ruby/library/cgi/escape_spec.rb b/spec/ruby/library/cgi/escape_spec.rb
index c599a73cf0..55eb0b66c2 100644
--- a/spec/ruby/library/cgi/escape_spec.rb
+++ b/spec/ruby/library/cgi/escape_spec.rb
@@ -1,5 +1,9 @@
require_relative '../../spec_helper'
-require 'cgi'
+begin
+ require 'cgi/escape'
+rescue LoadError
+ require 'cgi'
+end
describe "CGI.escape" do
it "url-encodes the passed argument" do
diff --git a/spec/ruby/library/cgi/htmlextension/a_spec.rb b/spec/ruby/library/cgi/htmlextension/a_spec.rb
index 05b4c2d14c..78d3dec8fa 100644
--- a/spec/ruby/library/cgi/htmlextension/a_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/a_spec.rb
@@ -1,49 +1,52 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'fixtures/common'
-describe "CGI::HtmlExtension#a" do
- before :each do
- @html = CGISpecs.cgi_new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'fixtures/common'
- describe "when passed a String" do
- it "returns an 'a'-element, using the passed String as the 'href'-attribute" do
- output = @html.a("http://www.example.com")
- output.should equal_element("A", "HREF" => "http://www.example.com")
+ describe "CGI::HtmlExtension#a" do
+ before :each do
+ @html = CGISpecs.cgi_new
end
- it "includes the passed block's return value when passed a block" do
- output = @html.a("http://www.example.com") { "Example" }
- output.should equal_element("A", { "HREF" => "http://www.example.com" }, "Example")
- end
- end
+ describe "when passed a String" do
+ it "returns an 'a'-element, using the passed String as the 'href'-attribute" do
+ output = @html.a("http://www.example.com")
+ output.should equal_element("A", "HREF" => "http://www.example.com")
+ end
- describe "when passed a Hash" do
- it "returns an 'a'-element, using the passed Hash for attributes" do
- attributes = {"HREF" => "http://www.example.com", "TARGET" => "_top"}
- @html.a(attributes).should equal_element("A", attributes)
+ it "includes the passed block's return value when passed a block" do
+ output = @html.a("http://www.example.com") { "Example" }
+ output.should equal_element("A", { "HREF" => "http://www.example.com" }, "Example")
+ end
end
- it "includes the passed block's return value when passed a block" do
- attributes = {"HREF" => "http://www.example.com", "TARGET" => "_top"}
- @html.a(attributes) { "Example" }.should equal_element("A", attributes, "Example")
- end
- end
+ describe "when passed a Hash" do
+ it "returns an 'a'-element, using the passed Hash for attributes" do
+ attributes = {"HREF" => "http://www.example.com", "TARGET" => "_top"}
+ @html.a(attributes).should equal_element("A", attributes)
+ end
- describe "when each HTML generation" do
- it "returns the doctype declaration for HTML3" do
- CGISpecs.cgi_new("html3").a.should == %(<A HREF=""></A>)
- CGISpecs.cgi_new("html3").a { "link text" }.should == %(<A HREF="">link text</A>)
+ it "includes the passed block's return value when passed a block" do
+ attributes = {"HREF" => "http://www.example.com", "TARGET" => "_top"}
+ @html.a(attributes) { "Example" }.should equal_element("A", attributes, "Example")
+ end
end
- it "returns the doctype declaration for HTML4" do
- CGISpecs.cgi_new("html4").a.should == %(<A HREF=""></A>)
- CGISpecs.cgi_new("html4").a { "link text" }.should == %(<A HREF="">link text</A>)
- end
- it "returns the doctype declaration for the Transitional version of HTML4" do
- CGISpecs.cgi_new("html4Tr").a.should == %(<A HREF=""></A>)
- CGISpecs.cgi_new("html4Tr").a { "link text" }.should == %(<A HREF="">link text</A>)
+ describe "when each HTML generation" do
+ it "returns the doctype declaration for HTML3" do
+ CGISpecs.cgi_new("html3").a.should == %(<A HREF=""></A>)
+ CGISpecs.cgi_new("html3").a { "link text" }.should == %(<A HREF="">link text</A>)
+ end
+
+ it "returns the doctype declaration for HTML4" do
+ CGISpecs.cgi_new("html4").a.should == %(<A HREF=""></A>)
+ CGISpecs.cgi_new("html4").a { "link text" }.should == %(<A HREF="">link text</A>)
+ end
+ it "returns the doctype declaration for the Transitional version of HTML4" do
+ CGISpecs.cgi_new("html4Tr").a.should == %(<A HREF=""></A>)
+ CGISpecs.cgi_new("html4Tr").a { "link text" }.should == %(<A HREF="">link text</A>)
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/htmlextension/base_spec.rb b/spec/ruby/library/cgi/htmlextension/base_spec.rb
index 877ac321cd..1eedfdea54 100644
--- a/spec/ruby/library/cgi/htmlextension/base_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/base_spec.rb
@@ -1,33 +1,36 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'fixtures/common'
-describe "CGI::HtmlExtension#base" do
- before :each do
- @html = CGISpecs.cgi_new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'fixtures/common'
- describe "when bassed a String" do
- it "returns a 'base'-element, using the passed String as the 'href'-attribute" do
- output = @html.base("http://www.example.com")
- output.should equal_element("BASE", {"HREF" => "http://www.example.com"}, nil, not_closed: true)
+ describe "CGI::HtmlExtension#base" do
+ before :each do
+ @html = CGISpecs.cgi_new
end
- it "ignores a passed block" do
- output = @html.base("http://www.example.com") { "Example" }
- output.should equal_element("BASE", {"HREF" => "http://www.example.com"}, nil, not_closed: true)
- end
- end
+ describe "when bassed a String" do
+ it "returns a 'base'-element, using the passed String as the 'href'-attribute" do
+ output = @html.base("http://www.example.com")
+ output.should equal_element("BASE", {"HREF" => "http://www.example.com"}, nil, not_closed: true)
+ end
- describe "when passed a Hash" do
- it "returns a 'base'-element, using the passed Hash for attributes" do
- output = @html.base("HREF" => "http://www.example.com", "ID" => "test")
- output.should equal_element("BASE", {"HREF" => "http://www.example.com", "ID" => "test"}, nil, not_closed: true)
+ it "ignores a passed block" do
+ output = @html.base("http://www.example.com") { "Example" }
+ output.should equal_element("BASE", {"HREF" => "http://www.example.com"}, nil, not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.base("HREF" => "http://www.example.com", "ID" => "test") { "Example" }
- output.should equal_element("BASE", {"HREF" => "http://www.example.com", "ID" => "test"}, nil, not_closed: true)
+ describe "when passed a Hash" do
+ it "returns a 'base'-element, using the passed Hash for attributes" do
+ output = @html.base("HREF" => "http://www.example.com", "ID" => "test")
+ output.should equal_element("BASE", {"HREF" => "http://www.example.com", "ID" => "test"}, nil, not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.base("HREF" => "http://www.example.com", "ID" => "test") { "Example" }
+ output.should equal_element("BASE", {"HREF" => "http://www.example.com", "ID" => "test"}, nil, not_closed: true)
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/htmlextension/blockquote_spec.rb b/spec/ruby/library/cgi/htmlextension/blockquote_spec.rb
index a7b833b1c5..883e36f78b 100644
--- a/spec/ruby/library/cgi/htmlextension/blockquote_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/blockquote_spec.rb
@@ -1,33 +1,36 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'fixtures/common'
-describe "CGI::HtmlExtension#blockquote" do
- before :each do
- @html = CGISpecs.cgi_new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'fixtures/common'
- describe "when passed a String" do
- it "returns a 'blockquote'-element, using the passed String for the 'cite'-attribute" do
- output = @html.blockquote("http://www.example.com/quotes/foo.html")
- output.should equal_element("BLOCKQUOTE", "CITE" => "http://www.example.com/quotes/foo.html")
+ describe "CGI::HtmlExtension#blockquote" do
+ before :each do
+ @html = CGISpecs.cgi_new
end
- it "includes the passed block's return value when passed a block" do
- output = @html.blockquote("http://www.example.com/quotes/foo.html") { "Foo!" }
- output.should equal_element("BLOCKQUOTE", { "CITE" => "http://www.example.com/quotes/foo.html" }, "Foo!")
- end
- end
+ describe "when passed a String" do
+ it "returns a 'blockquote'-element, using the passed String for the 'cite'-attribute" do
+ output = @html.blockquote("http://www.example.com/quotes/foo.html")
+ output.should equal_element("BLOCKQUOTE", "CITE" => "http://www.example.com/quotes/foo.html")
+ end
- describe "when passed a Hash" do
- it "returns a 'blockquote'-element, using the passed Hash for attributes" do
- output = @html.blockquote("CITE" => "http://www.example.com/quotes/foo.html", "ID" => "test")
- output.should equal_element("BLOCKQUOTE", "CITE" => "http://www.example.com/quotes/foo.html", "ID" => "test")
+ it "includes the passed block's return value when passed a block" do
+ output = @html.blockquote("http://www.example.com/quotes/foo.html") { "Foo!" }
+ output.should equal_element("BLOCKQUOTE", { "CITE" => "http://www.example.com/quotes/foo.html" }, "Foo!")
+ end
end
- it "includes the passed block's return value when passed a block" do
- output = @html.blockquote("CITE" => "http://www.example.com/quotes/foo.html", "ID" => "test") { "Foo!" }
- output.should equal_element("BLOCKQUOTE", {"CITE" => "http://www.example.com/quotes/foo.html", "ID" => "test"}, "Foo!")
+ describe "when passed a Hash" do
+ it "returns a 'blockquote'-element, using the passed Hash for attributes" do
+ output = @html.blockquote("CITE" => "http://www.example.com/quotes/foo.html", "ID" => "test")
+ output.should equal_element("BLOCKQUOTE", "CITE" => "http://www.example.com/quotes/foo.html", "ID" => "test")
+ end
+
+ it "includes the passed block's return value when passed a block" do
+ output = @html.blockquote("CITE" => "http://www.example.com/quotes/foo.html", "ID" => "test") { "Foo!" }
+ output.should equal_element("BLOCKQUOTE", {"CITE" => "http://www.example.com/quotes/foo.html", "ID" => "test"}, "Foo!")
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/htmlextension/br_spec.rb b/spec/ruby/library/cgi/htmlextension/br_spec.rb
index dfca121884..23c2cb4a48 100644
--- a/spec/ruby/library/cgi/htmlextension/br_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/br_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'fixtures/common'
-describe "CGI::HtmlExtension#br" do
- before :each do
- @html = CGISpecs.cgi_new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'fixtures/common'
- describe "when each HTML generation" do
- it "returns the doctype declaration for HTML3" do
- CGISpecs.cgi_new("html3").br.should == "<BR>"
+ describe "CGI::HtmlExtension#br" do
+ before :each do
+ @html = CGISpecs.cgi_new
end
- it "returns the doctype declaration for HTML4" do
- CGISpecs.cgi_new("html4").br.should == "<BR>"
- end
- it "returns the doctype declaration for the Transitional version of HTML4" do
- CGISpecs.cgi_new("html4Tr").br.should == "<BR>"
+ describe "when each HTML generation" do
+ it "returns the doctype declaration for HTML3" do
+ CGISpecs.cgi_new("html3").br.should == "<BR>"
+ end
+
+ it "returns the doctype declaration for HTML4" do
+ CGISpecs.cgi_new("html4").br.should == "<BR>"
+ end
+ it "returns the doctype declaration for the Transitional version of HTML4" do
+ CGISpecs.cgi_new("html4Tr").br.should == "<BR>"
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/htmlextension/caption_spec.rb b/spec/ruby/library/cgi/htmlextension/caption_spec.rb
index 16615028b8..3d3e21ecaa 100644
--- a/spec/ruby/library/cgi/htmlextension/caption_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/caption_spec.rb
@@ -1,33 +1,36 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'fixtures/common'
-describe "CGI::HtmlExtension#caption" do
- before :each do
- @html = CGISpecs.cgi_new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'fixtures/common'
- describe "when passed a String" do
- it "returns a 'caption'-element, using the passed String for the 'align'-attribute" do
- output = @html.caption("left")
- output.should equal_element("CAPTION", "ALIGN" => "left")
+ describe "CGI::HtmlExtension#caption" do
+ before :each do
+ @html = CGISpecs.cgi_new
end
- it "includes the passed block's return value when passed a block" do
- output = @html.caption("left") { "Capital Cities" }
- output.should equal_element("CAPTION", {"ALIGN" => "left"}, "Capital Cities")
- end
- end
+ describe "when passed a String" do
+ it "returns a 'caption'-element, using the passed String for the 'align'-attribute" do
+ output = @html.caption("left")
+ output.should equal_element("CAPTION", "ALIGN" => "left")
+ end
- describe "when passed a Hash" do
- it "returns a 'caption'-element, using the passed Hash for attributes" do
- output = @html.caption("ALIGN" => "left", "ID" => "test")
- output.should equal_element("CAPTION", "ALIGN" => "left", "ID" => "test")
+ it "includes the passed block's return value when passed a block" do
+ output = @html.caption("left") { "Capital Cities" }
+ output.should equal_element("CAPTION", {"ALIGN" => "left"}, "Capital Cities")
+ end
end
- it "includes the passed block's return value when passed a block" do
- output = @html.caption("ALIGN" => "left", "ID" => "test") { "Capital Cities" }
- output.should equal_element("CAPTION", {"ALIGN" => "left", "ID" => "test"}, "Capital Cities")
+ describe "when passed a Hash" do
+ it "returns a 'caption'-element, using the passed Hash for attributes" do
+ output = @html.caption("ALIGN" => "left", "ID" => "test")
+ output.should equal_element("CAPTION", "ALIGN" => "left", "ID" => "test")
+ end
+
+ it "includes the passed block's return value when passed a block" do
+ output = @html.caption("ALIGN" => "left", "ID" => "test") { "Capital Cities" }
+ output.should equal_element("CAPTION", {"ALIGN" => "left", "ID" => "test"}, "Capital Cities")
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/htmlextension/checkbox_group_spec.rb b/spec/ruby/library/cgi/htmlextension/checkbox_group_spec.rb
index 64f852cc52..07163c010e 100644
--- a/spec/ruby/library/cgi/htmlextension/checkbox_group_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/checkbox_group_spec.rb
@@ -1,76 +1,79 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'fixtures/common'
-describe "CGI::HtmlExtension#checkbox_group" do
- before :each do
- @html = CGISpecs.cgi_new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'fixtures/common'
- describe "when passed name, values ..." do
- it "returns a sequence of 'checkbox'-elements with the passed name and the passed values" do
- output = CGISpecs.split(@html.checkbox_group("test", "foo", "bar", "baz"))
- output[0].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "foo"}, "foo", not_closed: true)
- output[1].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "bar"}, "bar", not_closed: true)
- output[2].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "baz"}, "baz", not_closed: true)
+ describe "CGI::HtmlExtension#checkbox_group" do
+ before :each do
+ @html = CGISpecs.cgi_new
end
- it "allows passing a value inside an Array" do
- output = CGISpecs.split(@html.checkbox_group("test", ["foo"], "bar", ["baz"]))
- output[0].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "foo"}, "foo", not_closed: true)
- output[1].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "bar"}, "bar", not_closed: true)
- output[2].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "baz"}, "baz", not_closed: true)
- end
+ describe "when passed name, values ..." do
+ it "returns a sequence of 'checkbox'-elements with the passed name and the passed values" do
+ output = CGISpecs.split(@html.checkbox_group("test", "foo", "bar", "baz"))
+ output[0].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "baz"}, "baz", not_closed: true)
+ end
- it "allows passing a value as an Array containing the value and the checked state or a label" do
- output = CGISpecs.split(@html.checkbox_group("test", ["foo"], ["bar", true], ["baz", "label for baz"]))
- output[0].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "foo"}, "foo", not_closed: true)
- output[1].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "test", "TYPE" => "checkbox", "VALUE" => "bar"}, "bar", not_closed: true)
- output[2].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "baz"}, "label for baz", not_closed: true)
- end
+ it "allows passing a value inside an Array" do
+ output = CGISpecs.split(@html.checkbox_group("test", ["foo"], "bar", ["baz"]))
+ output[0].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "baz"}, "baz", not_closed: true)
+ end
- it "allows passing a value as an Array containing the value, a label and the checked state" do
- output = CGISpecs.split(@html.checkbox_group("test", ["foo", "label for foo", true], ["bar", "label for bar", false], ["baz", "label for baz", true]))
- output[0].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "test", "TYPE" => "checkbox", "VALUE" => "foo"}, "label for foo", not_closed: true)
- output[1].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "bar"}, "label for bar", not_closed: true)
- output[2].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "test", "TYPE" => "checkbox", "VALUE" => "baz"}, "label for baz", not_closed: true)
- end
+ it "allows passing a value as an Array containing the value and the checked state or a label" do
+ output = CGISpecs.split(@html.checkbox_group("test", ["foo"], ["bar", true], ["baz", "label for baz"]))
+ output[0].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "test", "TYPE" => "checkbox", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "baz"}, "label for baz", not_closed: true)
+ end
- it "returns an empty String when passed no values" do
- @html.checkbox_group("test").should == ""
- end
+ it "allows passing a value as an Array containing the value, a label and the checked state" do
+ output = CGISpecs.split(@html.checkbox_group("test", ["foo", "label for foo", true], ["bar", "label for bar", false], ["baz", "label for baz", true]))
+ output[0].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "test", "TYPE" => "checkbox", "VALUE" => "foo"}, "label for foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "bar"}, "label for bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "test", "TYPE" => "checkbox", "VALUE" => "baz"}, "label for baz", not_closed: true)
+ end
+
+ it "returns an empty String when passed no values" do
+ @html.checkbox_group("test").should == ""
+ end
- it "ignores a passed block" do
- output = CGISpecs.split(@html.checkbox_group("test", "foo", "bar", "baz") { "test" })
- output[0].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "foo"}, "foo", not_closed: true)
- output[1].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "bar"}, "bar", not_closed: true)
- output[2].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "baz"}, "baz", not_closed: true)
+ it "ignores a passed block" do
+ output = CGISpecs.split(@html.checkbox_group("test", "foo", "bar", "baz") { "test" })
+ output[0].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "baz"}, "baz", not_closed: true)
+ end
end
- end
- describe "when passed Hash" do
- it "uses the passed Hash to generate the checkbox sequence" do
- output = CGISpecs.split(@html.checkbox_group("NAME" => "name", "VALUES" => ["foo", "bar", "baz"]))
- output[0].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "foo"}, "foo", not_closed: true)
- output[1].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "bar"}, "bar", not_closed: true)
- output[2].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "baz"}, "baz", not_closed: true)
+ describe "when passed Hash" do
+ it "uses the passed Hash to generate the checkbox sequence" do
+ output = CGISpecs.split(@html.checkbox_group("NAME" => "name", "VALUES" => ["foo", "bar", "baz"]))
+ output[0].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "baz"}, "baz", not_closed: true)
- output = CGISpecs.split(@html.checkbox_group("NAME" => "name", "VALUES" => [["foo"], ["bar", true], "baz"]))
- output[0].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "foo"}, "foo", not_closed: true)
- output[1].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "name", "TYPE" => "checkbox", "VALUE" => "bar"}, "bar", not_closed: true)
- output[2].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "baz"}, "baz", not_closed: true)
+ output = CGISpecs.split(@html.checkbox_group("NAME" => "name", "VALUES" => [["foo"], ["bar", true], "baz"]))
+ output[0].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "name", "TYPE" => "checkbox", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "baz"}, "baz", not_closed: true)
- output = CGISpecs.split(@html.checkbox_group("NAME" => "name", "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"]))
- output[0].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "1"}, "Foo", not_closed: true)
- output[1].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "name", "TYPE" => "checkbox", "VALUE" => "2"}, "Bar", not_closed: true)
- output[2].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "Baz"}, "Baz", not_closed: true)
- end
+ output = CGISpecs.split(@html.checkbox_group("NAME" => "name", "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"]))
+ output[0].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "1"}, "Foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "name", "TYPE" => "checkbox", "VALUE" => "2"}, "Bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "Baz"}, "Baz", not_closed: true)
+ end
- it "ignores a passed block" do
- output = CGISpecs.split(@html.checkbox_group("NAME" => "name", "VALUES" => ["foo", "bar", "baz"]) { "test" })
- output[0].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "foo"}, "foo", not_closed: true)
- output[1].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "bar"}, "bar", not_closed: true)
- output[2].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "baz"}, "baz", not_closed: true)
+ it "ignores a passed block" do
+ output = CGISpecs.split(@html.checkbox_group("NAME" => "name", "VALUES" => ["foo", "bar", "baz"]) { "test" })
+ output[0].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "checkbox", "VALUE" => "baz"}, "baz", not_closed: true)
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/htmlextension/checkbox_spec.rb b/spec/ruby/library/cgi/htmlextension/checkbox_spec.rb
index af76fa1da9..ad87b78061 100644
--- a/spec/ruby/library/cgi/htmlextension/checkbox_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/checkbox_spec.rb
@@ -1,77 +1,80 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'fixtures/common'
-describe "CGI::HtmlExtension#checkbox" do
- before :each do
- @html = CGISpecs.cgi_new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'fixtures/common'
- describe "when passed no arguments" do
- it "returns a checkbox-'input'-element without a name" do
- output = @html.checkbox
- output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "checkbox"}, "", not_closed: true)
+ describe "CGI::HtmlExtension#checkbox" do
+ before :each do
+ @html = CGISpecs.cgi_new
end
- it "ignores a passed block" do
- output = @html.checkbox { "test" }
- output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "checkbox"}, "", not_closed: true)
- end
- end
+ describe "when passed no arguments" do
+ it "returns a checkbox-'input'-element without a name" do
+ output = @html.checkbox
+ output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "checkbox"}, "", not_closed: true)
+ end
- describe "when passed name" do
- it "returns a checkbox-'input'-element with the passed name" do
- output = @html.checkbox("test")
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.checkbox { "test" }
+ output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "checkbox"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.checkbox("test") { "test" }
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox"}, "", not_closed: true)
- end
- end
+ describe "when passed name" do
+ it "returns a checkbox-'input'-element with the passed name" do
+ output = @html.checkbox("test")
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox"}, "", not_closed: true)
+ end
- describe "CGI::HtmlExtension#checkbox when passed name, value" do
- it "returns a checkbox-'input'-element with the passed name and value" do
- output = @html.checkbox("test", "test-value")
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "test-value"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.checkbox("test") { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.checkbox("test", "test-value") { "test" }
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "test-value"}, "", not_closed: true)
+ describe "CGI::HtmlExtension#checkbox when passed name, value" do
+ it "returns a checkbox-'input'-element with the passed name and value" do
+ output = @html.checkbox("test", "test-value")
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "test-value"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.checkbox("test", "test-value") { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "test-value"}, "", not_closed: true)
+ end
end
- end
- describe "when passed name, value, checked" do
- it "returns a checked checkbox-'input'-element with the passed name and value when checked is true" do
- output = @html.checkbox("test", "test-value", true)
- output.should equal_element("INPUT", {"CHECKED" => true, "NAME" => "test", "TYPE" => "checkbox", "VALUE" => "test-value"}, "", not_closed: true)
+ describe "when passed name, value, checked" do
+ it "returns a checked checkbox-'input'-element with the passed name and value when checked is true" do
+ output = @html.checkbox("test", "test-value", true)
+ output.should equal_element("INPUT", {"CHECKED" => true, "NAME" => "test", "TYPE" => "checkbox", "VALUE" => "test-value"}, "", not_closed: true)
- output = @html.checkbox("test", "test-value", false)
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "test-value"}, "", not_closed: true)
+ output = @html.checkbox("test", "test-value", false)
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "test-value"}, "", not_closed: true)
- output = @html.checkbox("test", "test-value", nil)
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "test-value"}, "", not_closed: true)
- end
+ output = @html.checkbox("test", "test-value", nil)
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "test-value"}, "", not_closed: true)
+ end
- it "ignores a passed block" do
- output = @html.checkbox("test", "test-value", nil) { "test" }
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "test-value"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.checkbox("test", "test-value", nil) { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "checkbox", "VALUE" => "test-value"}, "", not_closed: true)
+ end
end
- end
- describe "when passed Hash" do
- it "returns a checkbox-'input'-element using the passed Hash for attributes" do
- attributes = {"NAME" => "test", "VALUE" => "test-value", "CHECKED" => true}
- output = @html.checkbox(attributes)
- output.should equal_element("INPUT", attributes, "", not_closed: true)
- end
+ describe "when passed Hash" do
+ it "returns a checkbox-'input'-element using the passed Hash for attributes" do
+ attributes = {"NAME" => "test", "VALUE" => "test-value", "CHECKED" => true}
+ output = @html.checkbox(attributes)
+ output.should equal_element("INPUT", attributes, "", not_closed: true)
+ end
- it "ignores a passed block" do
- attributes = {"NAME" => "test", "VALUE" => "test-value", "CHECKED" => true}
- output = @html.checkbox(attributes) { "test" }
- output.should equal_element("INPUT", attributes, "", not_closed: true)
+ it "ignores a passed block" do
+ attributes = {"NAME" => "test", "VALUE" => "test-value", "CHECKED" => true}
+ output = @html.checkbox(attributes) { "test" }
+ output.should equal_element("INPUT", attributes, "", not_closed: true)
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/htmlextension/doctype_spec.rb b/spec/ruby/library/cgi/htmlextension/doctype_spec.rb
index 9a28a8883b..02af831855 100644
--- a/spec/ruby/library/cgi/htmlextension/doctype_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/doctype_spec.rb
@@ -1,27 +1,30 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'fixtures/common'
-describe "CGI::HtmlExtension#doctype" do
- describe "when each HTML generation" do
- it "returns the doctype declaration for HTML3" do
- expect = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">'
- CGISpecs.cgi_new("html3").doctype.should == expect
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'fixtures/common'
- it "returns the doctype declaration for HTML4" do
- expect = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">'
- CGISpecs.cgi_new("html4").doctype.should == expect
- end
+ describe "CGI::HtmlExtension#doctype" do
+ describe "when each HTML generation" do
+ it "returns the doctype declaration for HTML3" do
+ expect = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">'
+ CGISpecs.cgi_new("html3").doctype.should == expect
+ end
- it "returns the doctype declaration for the Frameset version of HTML4" do
- expect = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">'
- CGISpecs.cgi_new("html4Fr").doctype.should == expect
- end
+ it "returns the doctype declaration for HTML4" do
+ expect = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">'
+ CGISpecs.cgi_new("html4").doctype.should == expect
+ end
+
+ it "returns the doctype declaration for the Frameset version of HTML4" do
+ expect = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">'
+ CGISpecs.cgi_new("html4Fr").doctype.should == expect
+ end
- it "returns the doctype declaration for the Transitional version of HTML4" do
- expect = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">'
- CGISpecs.cgi_new("html4Tr").doctype.should == expect
+ it "returns the doctype declaration for the Transitional version of HTML4" do
+ expect = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">'
+ CGISpecs.cgi_new("html4Tr").doctype.should == expect
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/htmlextension/file_field_spec.rb b/spec/ruby/library/cgi/htmlextension/file_field_spec.rb
index 2a0632fd58..eff077b9a2 100644
--- a/spec/ruby/library/cgi/htmlextension/file_field_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/file_field_spec.rb
@@ -1,72 +1,75 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'fixtures/common'
-describe "CGI::HtmlExtension#file_field" do
- before :each do
- @html = CGISpecs.cgi_new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'fixtures/common'
- describe "when passed no arguments" do
- it "returns a file-'input'-element without a name and a size of 20" do
- output = @html.file_field
- output.should equal_element("INPUT", {"SIZE" => 20, "NAME" => "", "TYPE" => "file"}, "", not_closed: true)
+ describe "CGI::HtmlExtension#file_field" do
+ before :each do
+ @html = CGISpecs.cgi_new
end
- it "ignores a passed block" do
- output = @html.file_field { "test" }
- output.should equal_element("INPUT", {"SIZE" => 20, "NAME" => "", "TYPE" => "file"}, "", not_closed: true)
- end
- end
+ describe "when passed no arguments" do
+ it "returns a file-'input'-element without a name and a size of 20" do
+ output = @html.file_field
+ output.should equal_element("INPUT", {"SIZE" => 20, "NAME" => "", "TYPE" => "file"}, "", not_closed: true)
+ end
- describe "when passed name" do
- it "returns a checkbox-'input'-element with the passed name" do
- output = @html.file_field("Example")
- output.should equal_element("INPUT", {"SIZE" => 20, "NAME" => "Example", "TYPE" => "file"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.file_field { "test" }
+ output.should equal_element("INPUT", {"SIZE" => 20, "NAME" => "", "TYPE" => "file"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.file_field("Example") { "test" }
- output.should equal_element("INPUT", {"SIZE" => 20, "NAME" => "Example", "TYPE" => "file"}, "", not_closed: true)
- end
- end
+ describe "when passed name" do
+ it "returns a checkbox-'input'-element with the passed name" do
+ output = @html.file_field("Example")
+ output.should equal_element("INPUT", {"SIZE" => 20, "NAME" => "Example", "TYPE" => "file"}, "", not_closed: true)
+ end
- describe "when passed name, size" do
- it "returns a checkbox-'input'-element with the passed name and size" do
- output = @html.file_field("Example", 40)
- output.should equal_element("INPUT", {"SIZE" => 40, "NAME" => "Example", "TYPE" => "file"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.file_field("Example") { "test" }
+ output.should equal_element("INPUT", {"SIZE" => 20, "NAME" => "Example", "TYPE" => "file"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.file_field("Example", 40) { "test" }
- output.should equal_element("INPUT", {"SIZE" => 40, "NAME" => "Example", "TYPE" => "file"}, "", not_closed: true)
- end
- end
+ describe "when passed name, size" do
+ it "returns a checkbox-'input'-element with the passed name and size" do
+ output = @html.file_field("Example", 40)
+ output.should equal_element("INPUT", {"SIZE" => 40, "NAME" => "Example", "TYPE" => "file"}, "", not_closed: true)
+ end
- describe "when passed name, size, maxlength" do
- it "returns a checkbox-'input'-element with the passed name, size and maxlength" do
- output = @html.file_field("Example", 40, 100)
- output.should equal_element("INPUT", {"SIZE" => 40, "NAME" => "Example", "TYPE" => "file", "MAXLENGTH" => 100}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.file_field("Example", 40) { "test" }
+ output.should equal_element("INPUT", {"SIZE" => 40, "NAME" => "Example", "TYPE" => "file"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.file_field("Example", 40, 100) { "test" }
- output.should equal_element("INPUT", {"SIZE" => 40, "NAME" => "Example", "TYPE" => "file", "MAXLENGTH" => 100}, "", not_closed: true)
+ describe "when passed name, size, maxlength" do
+ it "returns a checkbox-'input'-element with the passed name, size and maxlength" do
+ output = @html.file_field("Example", 40, 100)
+ output.should equal_element("INPUT", {"SIZE" => 40, "NAME" => "Example", "TYPE" => "file", "MAXLENGTH" => 100}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.file_field("Example", 40, 100) { "test" }
+ output.should equal_element("INPUT", {"SIZE" => 40, "NAME" => "Example", "TYPE" => "file", "MAXLENGTH" => 100}, "", not_closed: true)
+ end
end
- end
- describe "when passed a Hash" do
- it "returns a file-'input'-element using the passed Hash for attributes" do
- output = @html.file_field("NAME" => "test", "SIZE" => 40)
- output.should equal_element("INPUT", {"NAME" => "test", "SIZE" => 40}, "", not_closed: true)
+ describe "when passed a Hash" do
+ it "returns a file-'input'-element using the passed Hash for attributes" do
+ output = @html.file_field("NAME" => "test", "SIZE" => 40)
+ output.should equal_element("INPUT", {"NAME" => "test", "SIZE" => 40}, "", not_closed: true)
- output = @html.file_field("NAME" => "test", "MAXLENGTH" => 100)
- output.should equal_element("INPUT", {"NAME" => "test", "MAXLENGTH" => 100}, "", not_closed: true)
- end
+ output = @html.file_field("NAME" => "test", "MAXLENGTH" => 100)
+ output.should equal_element("INPUT", {"NAME" => "test", "MAXLENGTH" => 100}, "", not_closed: true)
+ end
- it "ignores a passed block" do
- output = @html.file_field("NAME" => "test", "SIZE" => 40) { "test" }
- output.should equal_element("INPUT", {"NAME" => "test", "SIZE" => 40}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.file_field("NAME" => "test", "SIZE" => 40) { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "SIZE" => 40}, "", not_closed: true)
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/htmlextension/form_spec.rb b/spec/ruby/library/cgi/htmlextension/form_spec.rb
index 8c0ac97735..55ac63152b 100644
--- a/spec/ruby/library/cgi/htmlextension/form_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/form_spec.rb
@@ -1,58 +1,61 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'fixtures/common'
-describe "CGI::HtmlExtension#form" do
- before :each do
- @html = CGISpecs.cgi_new
- @html.stub!(:script_name).and_return("/path/to/some/script")
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'fixtures/common'
- describe "when passed no arguments" do
- it "returns a 'form'-element" do
- output = @html.form
- output.should equal_element("FORM", {"ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "post", "ACTION" => "/path/to/some/script"}, "")
+ describe "CGI::HtmlExtension#form" do
+ before :each do
+ @html = CGISpecs.cgi_new
+ @html.stub!(:script_name).and_return("/path/to/some/script")
end
- it "includes the return value of the passed block when passed a block" do
- output = @html.form { "test" }
- output.should equal_element("FORM", {"ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "post", "ACTION" => "/path/to/some/script"}, "test")
- end
- end
+ describe "when passed no arguments" do
+ it "returns a 'form'-element" do
+ output = @html.form
+ output.should equal_element("FORM", {"ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "post", "ACTION" => "/path/to/some/script"}, "")
+ end
- describe "when passed method" do
- it "returns a 'form'-element with the passed method" do
- output = @html.form("get")
- output.should equal_element("FORM", {"ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "get", "ACTION" => "/path/to/some/script"}, "")
+ it "includes the return value of the passed block when passed a block" do
+ output = @html.form { "test" }
+ output.should equal_element("FORM", {"ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "post", "ACTION" => "/path/to/some/script"}, "test")
+ end
end
- it "includes the return value of the passed block when passed a block" do
- output = @html.form("get") { "test" }
- output.should equal_element("FORM", {"ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "get", "ACTION" => "/path/to/some/script"}, "test")
- end
- end
+ describe "when passed method" do
+ it "returns a 'form'-element with the passed method" do
+ output = @html.form("get")
+ output.should equal_element("FORM", {"ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "get", "ACTION" => "/path/to/some/script"}, "")
+ end
- describe "when passed method, action" do
- it "returns a 'form'-element with the passed method and the passed action" do
- output = @html.form("get", "/some/other/script")
- output.should equal_element("FORM", {"ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "get", "ACTION" => "/some/other/script"}, "")
+ it "includes the return value of the passed block when passed a block" do
+ output = @html.form("get") { "test" }
+ output.should equal_element("FORM", {"ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "get", "ACTION" => "/path/to/some/script"}, "test")
+ end
end
- it "includes the return value of the passed block when passed a block" do
- output = @html.form("get", "/some/other/script") { "test" }
- output.should equal_element("FORM", {"ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "get", "ACTION" => "/some/other/script"}, "test")
- end
- end
+ describe "when passed method, action" do
+ it "returns a 'form'-element with the passed method and the passed action" do
+ output = @html.form("get", "/some/other/script")
+ output.should equal_element("FORM", {"ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "get", "ACTION" => "/some/other/script"}, "")
+ end
- describe "when passed method, action, enctype" do
- it "returns a 'form'-element with the passed method, action and enctype" do
- output = @html.form("get", "/some/other/script", "multipart/form-data")
- output.should equal_element("FORM", {"ENCTYPE" => "multipart/form-data", "METHOD" => "get", "ACTION" => "/some/other/script"}, "")
+ it "includes the return value of the passed block when passed a block" do
+ output = @html.form("get", "/some/other/script") { "test" }
+ output.should equal_element("FORM", {"ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "get", "ACTION" => "/some/other/script"}, "test")
+ end
end
- it "includes the return value of the passed block when passed a block" do
- output = @html.form("get", "/some/other/script", "multipart/form-data") { "test" }
- output.should equal_element("FORM", {"ENCTYPE" => "multipart/form-data", "METHOD" => "get", "ACTION" => "/some/other/script"}, "test")
+ describe "when passed method, action, enctype" do
+ it "returns a 'form'-element with the passed method, action and enctype" do
+ output = @html.form("get", "/some/other/script", "multipart/form-data")
+ output.should equal_element("FORM", {"ENCTYPE" => "multipart/form-data", "METHOD" => "get", "ACTION" => "/some/other/script"}, "")
+ end
+
+ it "includes the return value of the passed block when passed a block" do
+ output = @html.form("get", "/some/other/script", "multipart/form-data") { "test" }
+ output.should equal_element("FORM", {"ENCTYPE" => "multipart/form-data", "METHOD" => "get", "ACTION" => "/some/other/script"}, "test")
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/htmlextension/frame_spec.rb b/spec/ruby/library/cgi/htmlextension/frame_spec.rb
index 2ddd4e1ef0..fef40849eb 100644
--- a/spec/ruby/library/cgi/htmlextension/frame_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/frame_spec.rb
@@ -1,14 +1,17 @@
require_relative '../../../spec_helper'
-require_relative 'fixtures/common'
-require 'cgi'
-describe "CGI::HtmlExtension#frame" do
- before :each do
- @html = CGISpecs.cgi_new("html4Fr")
- end
+ruby_version_is ""..."4.0" do
+ require_relative 'fixtures/common'
+ require 'cgi'
+
+ describe "CGI::HtmlExtension#frame" do
+ before :each do
+ @html = CGISpecs.cgi_new("html4Fr")
+ end
- it "initializes the HTML Generation methods for the Frameset version of HTML4" do
- @html.frameset.should == "<FRAMESET></FRAMESET>"
- @html.frameset { "link text" }.should == "<FRAMESET>link text</FRAMESET>"
+ it "initializes the HTML Generation methods for the Frameset version of HTML4" do
+ @html.frameset.should == "<FRAMESET></FRAMESET>"
+ @html.frameset { "link text" }.should == "<FRAMESET>link text</FRAMESET>"
+ end
end
end
diff --git a/spec/ruby/library/cgi/htmlextension/frameset_spec.rb b/spec/ruby/library/cgi/htmlextension/frameset_spec.rb
index baeb446593..3ad0a9c4d2 100644
--- a/spec/ruby/library/cgi/htmlextension/frameset_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/frameset_spec.rb
@@ -1,14 +1,17 @@
require_relative '../../../spec_helper'
-require_relative 'fixtures/common'
-require 'cgi'
-describe "CGI::HtmlExtension#frameset" do
- before :each do
- @html = CGISpecs.cgi_new("html4Fr")
- end
+ruby_version_is ""..."4.0" do
+ require_relative 'fixtures/common'
+ require 'cgi'
+
+ describe "CGI::HtmlExtension#frameset" do
+ before :each do
+ @html = CGISpecs.cgi_new("html4Fr")
+ end
- it "initializes the HTML Generation methods for the Frameset version of HTML4" do
- @html.frameset.should == "<FRAMESET></FRAMESET>"
- @html.frameset { "link text" }.should == "<FRAMESET>link text</FRAMESET>"
+ it "initializes the HTML Generation methods for the Frameset version of HTML4" do
+ @html.frameset.should == "<FRAMESET></FRAMESET>"
+ @html.frameset { "link text" }.should == "<FRAMESET>link text</FRAMESET>"
+ end
end
end
diff --git a/spec/ruby/library/cgi/htmlextension/hidden_spec.rb b/spec/ruby/library/cgi/htmlextension/hidden_spec.rb
index 52ebd8c261..b2323775f6 100644
--- a/spec/ruby/library/cgi/htmlextension/hidden_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/hidden_spec.rb
@@ -1,59 +1,62 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'fixtures/common'
-describe "CGI::HtmlExtension#hidden" do
- before :each do
- @html = CGISpecs.cgi_new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'fixtures/common'
- describe "when passed no arguments" do
- it "returns an hidden-'input'-element without a name" do
- output = @html.hidden
- output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "hidden"}, "", not_closed: true)
+ describe "CGI::HtmlExtension#hidden" do
+ before :each do
+ @html = CGISpecs.cgi_new
end
- it "ignores a passed block" do
- output = @html.hidden { "test" }
- output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "hidden"}, "", not_closed: true)
- end
- end
+ describe "when passed no arguments" do
+ it "returns an hidden-'input'-element without a name" do
+ output = @html.hidden
+ output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "hidden"}, "", not_closed: true)
+ end
- describe "when passed name" do
- it "returns an hidden-'input'-element with the passed name" do
- output = @html.hidden("test")
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "hidden"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.hidden { "test" }
+ output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "hidden"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.hidden("test") { "test" }
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "hidden"}, "", not_closed: true)
- end
- end
+ describe "when passed name" do
+ it "returns an hidden-'input'-element with the passed name" do
+ output = @html.hidden("test")
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "hidden"}, "", not_closed: true)
+ end
- describe "when passed name, value" do
- it "returns an hidden-'input'-element with the passed name and value" do
- output = @html.hidden("test", "some value")
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "hidden", "VALUE" => "some value"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.hidden("test") { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "hidden"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.hidden("test", "some value") { "test" }
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "hidden", "VALUE" => "some value"}, "", not_closed: true)
- end
- end
+ describe "when passed name, value" do
+ it "returns an hidden-'input'-element with the passed name and value" do
+ output = @html.hidden("test", "some value")
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "hidden", "VALUE" => "some value"}, "", not_closed: true)
+ end
- describe "when passed Hash" do
- it "returns a checkbox-'input'-element using the passed Hash for attributes" do
- attributes = { "NAME" => "test", "VALUE" => "some value" }
- output = @html.hidden("test", "some value")
- output.should equal_element("INPUT", attributes, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.hidden("test", "some value") { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "hidden", "VALUE" => "some value"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- attributes = { "NAME" => "test", "VALUE" => "some value" }
- output = @html.hidden("test", "some value") { "test" }
- output.should equal_element("INPUT", attributes, "", not_closed: true)
+ describe "when passed Hash" do
+ it "returns a checkbox-'input'-element using the passed Hash for attributes" do
+ attributes = { "NAME" => "test", "VALUE" => "some value" }
+ output = @html.hidden("test", "some value")
+ output.should equal_element("INPUT", attributes, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ attributes = { "NAME" => "test", "VALUE" => "some value" }
+ output = @html.hidden("test", "some value") { "test" }
+ output.should equal_element("INPUT", attributes, "", not_closed: true)
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/htmlextension/html_spec.rb b/spec/ruby/library/cgi/htmlextension/html_spec.rb
index 5d89c82086..60a10fb6b4 100644
--- a/spec/ruby/library/cgi/htmlextension/html_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/html_spec.rb
@@ -1,66 +1,69 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'fixtures/common'
-describe "CGI::HtmlExtension#html" do
- before :each do
- @html = CGISpecs.cgi_new
- @html.stub!(:doctype).and_return("<!DOCTYPE SUPA-FUNKAY-RUBYSPEC-DOCTYPE>")
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'fixtures/common'
- describe "when passed no arguments" do
- it "returns a self's doctype and an 'html'-element" do
- expected = '<!DOCTYPE SUPA-FUNKAY-RUBYSPEC-DOCTYPE><HTML>'
- @html.html.should == expected
+ describe "CGI::HtmlExtension#html" do
+ before :each do
+ @html = CGISpecs.cgi_new
+ @html.stub!(:doctype).and_return("<!DOCTYPE SUPA-FUNKAY-RUBYSPEC-DOCTYPE>")
end
- it "includes the passed block when passed a block" do
- expected = '<!DOCTYPE SUPA-FUNKAY-RUBYSPEC-DOCTYPE><HTML>test</HTML>'
- @html.html { "test" }.should == expected
- end
- end
+ describe "when passed no arguments" do
+ it "returns a self's doctype and an 'html'-element" do
+ expected = '<!DOCTYPE SUPA-FUNKAY-RUBYSPEC-DOCTYPE><HTML>'
+ @html.html.should == expected
+ end
- describe "when passed 'PRETTY'" do
- it "returns pretty output when the passed String is 'PRETTY" do
- expected = "<!DOCTYPE SUPA-FUNKAY-RUBYSPEC-DOCTYPE>\n<HTML>\n"
- @html.html("PRETTY").should == expected
+ it "includes the passed block when passed a block" do
+ expected = '<!DOCTYPE SUPA-FUNKAY-RUBYSPEC-DOCTYPE><HTML>test</HTML>'
+ @html.html { "test" }.should == expected
+ end
end
- it "includes the passed block when passed a block" do
- expected = "<!DOCTYPE SUPA-FUNKAY-RUBYSPEC-DOCTYPE>\n<HTML>\n test\n</HTML>\n"
- @html.html("PRETTY") { "test" }.should == expected
- end
- end
+ describe "when passed 'PRETTY'" do
+ it "returns pretty output when the passed String is 'PRETTY" do
+ expected = "<!DOCTYPE SUPA-FUNKAY-RUBYSPEC-DOCTYPE>\n<HTML>\n"
+ @html.html("PRETTY").should == expected
+ end
- describe "when passed a Hash" do
- it "returns an 'html'-element using the passed Hash for attributes" do
- expected = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"><HTML BLA="TEST">'
- @html.html("DOCTYPE" => '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">', "BLA" => "TEST").should == expected
+ it "includes the passed block when passed a block" do
+ expected = "<!DOCTYPE SUPA-FUNKAY-RUBYSPEC-DOCTYPE>\n<HTML>\n test\n</HTML>\n"
+ @html.html("PRETTY") { "test" }.should == expected
+ end
end
- it "omits the doctype when the Hash contains a 'DOCTYPE' entry that's false or nil" do
- @html.html("DOCTYPE" => false).should == "<HTML>"
- @html.html("DOCTYPE" => nil).should == "<HTML>"
- end
- end
+ describe "when passed a Hash" do
+ it "returns an 'html'-element using the passed Hash for attributes" do
+ expected = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"><HTML BLA="TEST">'
+ @html.html("DOCTYPE" => '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">', "BLA" => "TEST").should == expected
+ end
- describe "when each HTML generation" do
- it "returns the doctype declaration for HTML3" do
- expect = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">'
- CGISpecs.cgi_new("html3").html.should == expect + "<HTML>"
- CGISpecs.cgi_new("html3").html { "html body" }.should == expect + "<HTML>html body</HTML>"
+ it "omits the doctype when the Hash contains a 'DOCTYPE' entry that's false or nil" do
+ @html.html("DOCTYPE" => false).should == "<HTML>"
+ @html.html("DOCTYPE" => nil).should == "<HTML>"
+ end
end
- it "returns the doctype declaration for HTML4" do
- expect = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">'
- CGISpecs.cgi_new("html4").html.should == expect + "<HTML>"
- CGISpecs.cgi_new("html4").html { "html body" }.should == expect + "<HTML>html body</HTML>"
- end
+ describe "when each HTML generation" do
+ it "returns the doctype declaration for HTML3" do
+ expect = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">'
+ CGISpecs.cgi_new("html3").html.should == expect + "<HTML>"
+ CGISpecs.cgi_new("html3").html { "html body" }.should == expect + "<HTML>html body</HTML>"
+ end
+
+ it "returns the doctype declaration for HTML4" do
+ expect = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">'
+ CGISpecs.cgi_new("html4").html.should == expect + "<HTML>"
+ CGISpecs.cgi_new("html4").html { "html body" }.should == expect + "<HTML>html body</HTML>"
+ end
- it "returns the doctype declaration for the Transitional version of HTML4" do
- expect = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">'
- CGISpecs.cgi_new("html4Tr").html.should == expect + "<HTML>"
- CGISpecs.cgi_new("html4Tr").html { "html body" }.should == expect + "<HTML>html body</HTML>"
+ it "returns the doctype declaration for the Transitional version of HTML4" do
+ expect = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">'
+ CGISpecs.cgi_new("html4Tr").html.should == expect + "<HTML>"
+ CGISpecs.cgi_new("html4Tr").html { "html body" }.should == expect + "<HTML>html body</HTML>"
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/htmlextension/image_button_spec.rb b/spec/ruby/library/cgi/htmlextension/image_button_spec.rb
index d14bec9ca3..f8770119d4 100644
--- a/spec/ruby/library/cgi/htmlextension/image_button_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/image_button_spec.rb
@@ -1,69 +1,72 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'fixtures/common'
-describe "CGI::HtmlExtension#image_button" do
- before :each do
- @html = CGISpecs.cgi_new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'fixtures/common'
- describe "when passed no arguments" do
- it "returns an image-'input'-element without a source image" do
- output = @html.image_button
- output.should equal_element("INPUT", {"SRC" => "", "TYPE" => "image"}, "", not_closed: true)
+ describe "CGI::HtmlExtension#image_button" do
+ before :each do
+ @html = CGISpecs.cgi_new
end
- it "ignores a passed block" do
- output = @html.image_button { "test" }
- output.should equal_element("INPUT", {"SRC" => "", "TYPE" => "image"}, "", not_closed: true)
- end
- end
+ describe "when passed no arguments" do
+ it "returns an image-'input'-element without a source image" do
+ output = @html.image_button
+ output.should equal_element("INPUT", {"SRC" => "", "TYPE" => "image"}, "", not_closed: true)
+ end
- describe "when passed src" do
- it "returns an image-'input'-element with the passed src" do
- output = @html.image_button("/path/to/image.png")
- output.should equal_element("INPUT", {"SRC" => "/path/to/image.png", "TYPE" => "image"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.image_button { "test" }
+ output.should equal_element("INPUT", {"SRC" => "", "TYPE" => "image"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.image_button("/path/to/image.png") { "test" }
- output.should equal_element("INPUT", {"SRC" => "/path/to/image.png", "TYPE" => "image"}, "", not_closed: true)
- end
- end
+ describe "when passed src" do
+ it "returns an image-'input'-element with the passed src" do
+ output = @html.image_button("/path/to/image.png")
+ output.should equal_element("INPUT", {"SRC" => "/path/to/image.png", "TYPE" => "image"}, "", not_closed: true)
+ end
- describe "when passed src, name" do
- it "returns an image-'input'-element with the passed src and name" do
- output = @html.image_button("/path/to/image.png", "test")
- output.should equal_element("INPUT", {"SRC" => "/path/to/image.png", "TYPE" => "image", "NAME" => "test"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.image_button("/path/to/image.png") { "test" }
+ output.should equal_element("INPUT", {"SRC" => "/path/to/image.png", "TYPE" => "image"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.image_button("/path/to/image.png", "test") { "test" }
- output.should equal_element("INPUT", {"SRC" => "/path/to/image.png", "TYPE" => "image", "NAME" => "test"}, "", not_closed: true)
- end
- end
+ describe "when passed src, name" do
+ it "returns an image-'input'-element with the passed src and name" do
+ output = @html.image_button("/path/to/image.png", "test")
+ output.should equal_element("INPUT", {"SRC" => "/path/to/image.png", "TYPE" => "image", "NAME" => "test"}, "", not_closed: true)
+ end
- describe "when passed src, name, alt" do
- it "returns an image-'input'-element with the passed src, name and alt" do
- output = @html.image_button("/path/to/image.png", "test", "alternative")
- output.should equal_element("INPUT", {"SRC" => "/path/to/image.png", "TYPE" => "image", "NAME" => "test", "ALT" => "alternative"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.image_button("/path/to/image.png", "test") { "test" }
+ output.should equal_element("INPUT", {"SRC" => "/path/to/image.png", "TYPE" => "image", "NAME" => "test"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.image_button("/path/to/image.png", "test", "alternative") { "test" }
- output.should equal_element("INPUT", {"SRC" => "/path/to/image.png", "TYPE" => "image", "NAME" => "test", "ALT" => "alternative"}, "", not_closed: true)
- end
- end
+ describe "when passed src, name, alt" do
+ it "returns an image-'input'-element with the passed src, name and alt" do
+ output = @html.image_button("/path/to/image.png", "test", "alternative")
+ output.should equal_element("INPUT", {"SRC" => "/path/to/image.png", "TYPE" => "image", "NAME" => "test", "ALT" => "alternative"}, "", not_closed: true)
+ end
- describe "when passed Hash" do
- it "returns a image-'input'-element using the passed Hash for attributes" do
- output = @html.image_button("NAME" => "test", "VALUE" => "test-value")
- output.should equal_element("INPUT", {"SRC" => "", "TYPE" => "image", "NAME" => "test", "VALUE" => "test-value"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.image_button("/path/to/image.png", "test", "alternative") { "test" }
+ output.should equal_element("INPUT", {"SRC" => "/path/to/image.png", "TYPE" => "image", "NAME" => "test", "ALT" => "alternative"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.image_button("NAME" => "test", "VALUE" => "test-value") { "test" }
- output.should equal_element("INPUT", {"SRC" => "", "TYPE" => "image", "NAME" => "test", "VALUE" => "test-value"}, "", not_closed: true)
+ describe "when passed Hash" do
+ it "returns a image-'input'-element using the passed Hash for attributes" do
+ output = @html.image_button("NAME" => "test", "VALUE" => "test-value")
+ output.should equal_element("INPUT", {"SRC" => "", "TYPE" => "image", "NAME" => "test", "VALUE" => "test-value"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.image_button("NAME" => "test", "VALUE" => "test-value") { "test" }
+ output.should equal_element("INPUT", {"SRC" => "", "TYPE" => "image", "NAME" => "test", "VALUE" => "test-value"}, "", not_closed: true)
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/htmlextension/img_spec.rb b/spec/ruby/library/cgi/htmlextension/img_spec.rb
index 994ae7fedf..a05cfdea48 100644
--- a/spec/ruby/library/cgi/htmlextension/img_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/img_spec.rb
@@ -1,83 +1,86 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'fixtures/common'
-describe "CGI::HtmlExtension#img" do
- before :each do
- @html = CGISpecs.cgi_new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'fixtures/common'
- describe "when passed no arguments" do
- it "returns an 'img'-element without an src-url or alt-text" do
- output = @html.img
- output.should equal_element("IMG", { "SRC" => "", "ALT" => "" }, "", not_closed: true)
+ describe "CGI::HtmlExtension#img" do
+ before :each do
+ @html = CGISpecs.cgi_new
end
- it "ignores a passed block" do
- output = @html.img { "test" }
- output.should equal_element("IMG", { "SRC" => "", "ALT" => "" }, "", not_closed: true)
- end
- end
+ describe "when passed no arguments" do
+ it "returns an 'img'-element without an src-url or alt-text" do
+ output = @html.img
+ output.should equal_element("IMG", { "SRC" => "", "ALT" => "" }, "", not_closed: true)
+ end
- describe "when passed src" do
- it "returns an 'img'-element with the passed src-url" do
- output = @html.img("/path/to/some/image.png")
- output.should equal_element("IMG", { "SRC" => "/path/to/some/image.png", "ALT" => "" }, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.img { "test" }
+ output.should equal_element("IMG", { "SRC" => "", "ALT" => "" }, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.img("/path/to/some/image.png")
- output.should equal_element("IMG", { "SRC" => "/path/to/some/image.png", "ALT" => "" }, "", not_closed: true)
- end
- end
+ describe "when passed src" do
+ it "returns an 'img'-element with the passed src-url" do
+ output = @html.img("/path/to/some/image.png")
+ output.should equal_element("IMG", { "SRC" => "/path/to/some/image.png", "ALT" => "" }, "", not_closed: true)
+ end
- describe "when passed src, alt" do
- it "returns an 'img'-element with the passed src-url and the passed alt-text" do
- output = @html.img("/path/to/some/image.png", "Alternative")
- output.should equal_element("IMG", { "SRC" => "/path/to/some/image.png", "ALT" => "Alternative" }, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.img("/path/to/some/image.png")
+ output.should equal_element("IMG", { "SRC" => "/path/to/some/image.png", "ALT" => "" }, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.img("/path/to/some/image.png", "Alternative") { "test" }
- output.should equal_element("IMG", { "SRC" => "/path/to/some/image.png", "ALT" => "Alternative" }, "", not_closed: true)
- end
- end
+ describe "when passed src, alt" do
+ it "returns an 'img'-element with the passed src-url and the passed alt-text" do
+ output = @html.img("/path/to/some/image.png", "Alternative")
+ output.should equal_element("IMG", { "SRC" => "/path/to/some/image.png", "ALT" => "Alternative" }, "", not_closed: true)
+ end
- describe "when passed src, alt, width" do
- it "returns an 'img'-element with the passed src-url, the passed alt-text and the passed width" do
- output = @html.img("/path/to/some/image.png", "Alternative", 40)
- output.should equal_element("IMG", { "SRC" => "/path/to/some/image.png", "ALT" => "Alternative", "WIDTH" => "40" }, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.img("/path/to/some/image.png", "Alternative") { "test" }
+ output.should equal_element("IMG", { "SRC" => "/path/to/some/image.png", "ALT" => "Alternative" }, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.img("/path/to/some/image.png", "Alternative", 40) { "test" }
- output.should equal_element("IMG", { "SRC" => "/path/to/some/image.png", "ALT" => "Alternative", "WIDTH" => "40" }, "", not_closed: true)
- end
- end
+ describe "when passed src, alt, width" do
+ it "returns an 'img'-element with the passed src-url, the passed alt-text and the passed width" do
+ output = @html.img("/path/to/some/image.png", "Alternative", 40)
+ output.should equal_element("IMG", { "SRC" => "/path/to/some/image.png", "ALT" => "Alternative", "WIDTH" => "40" }, "", not_closed: true)
+ end
- describe "when passed src, alt, width, height" do
- it "returns an 'img'-element with the passed src-url, the passed alt-text, the passed width and the passed height" do
- output = @html.img("/path/to/some/image.png", "Alternative", 40, 60)
- output.should equal_element("IMG", { "SRC" => "/path/to/some/image.png", "ALT" => "Alternative", "WIDTH" => "40", "HEIGHT" => "60" }, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.img("/path/to/some/image.png", "Alternative", 40) { "test" }
+ output.should equal_element("IMG", { "SRC" => "/path/to/some/image.png", "ALT" => "Alternative", "WIDTH" => "40" }, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.img { "test" }
- output.should equal_element("IMG", { "SRC" => "", "ALT" => "" }, "", not_closed: true)
- end
- end
+ describe "when passed src, alt, width, height" do
+ it "returns an 'img'-element with the passed src-url, the passed alt-text, the passed width and the passed height" do
+ output = @html.img("/path/to/some/image.png", "Alternative", 40, 60)
+ output.should equal_element("IMG", { "SRC" => "/path/to/some/image.png", "ALT" => "Alternative", "WIDTH" => "40", "HEIGHT" => "60" }, "", not_closed: true)
+ end
- describe "when passed Hash" do
- it "returns an 'img'-element with the passed Hash as attributes" do
- attributes = { "SRC" => "src", "ALT" => "alt", "WIDTH" => 100, "HEIGHT" => 50 }
- output = @html.img(attributes)
- output.should equal_element("IMG", attributes, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.img { "test" }
+ output.should equal_element("IMG", { "SRC" => "", "ALT" => "" }, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- attributes = { "SRC" => "src", "ALT" => "alt", "WIDTH" => 100, "HEIGHT" => 50 }
- output = @html.img(attributes) { "test" }
- output.should equal_element("IMG", attributes, "", not_closed: true)
+ describe "when passed Hash" do
+ it "returns an 'img'-element with the passed Hash as attributes" do
+ attributes = { "SRC" => "src", "ALT" => "alt", "WIDTH" => 100, "HEIGHT" => 50 }
+ output = @html.img(attributes)
+ output.should equal_element("IMG", attributes, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ attributes = { "SRC" => "src", "ALT" => "alt", "WIDTH" => 100, "HEIGHT" => 50 }
+ output = @html.img(attributes) { "test" }
+ output.should equal_element("IMG", attributes, "", not_closed: true)
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/htmlextension/multipart_form_spec.rb b/spec/ruby/library/cgi/htmlextension/multipart_form_spec.rb
index 0bf2042a33..ee1c45b84e 100644
--- a/spec/ruby/library/cgi/htmlextension/multipart_form_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/multipart_form_spec.rb
@@ -1,64 +1,67 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'fixtures/common'
-describe "CGI::HtmlExtension#multipart_form" do
- before :each do
- @html = CGISpecs.cgi_new
- @html.stub!(:script_name).and_return("/path/to/some/script.rb")
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'fixtures/common'
- describe "when passed no arguments" do
- it "returns a 'form'-element with it's enctype set to multipart" do
- output = @html.multipart_form
- output.should equal_element("FORM", { "ENCTYPE" => "multipart/form-data", "METHOD" => "post" }, "")
+ describe "CGI::HtmlExtension#multipart_form" do
+ before :each do
+ @html = CGISpecs.cgi_new
+ @html.stub!(:script_name).and_return("/path/to/some/script.rb")
end
- it "includes the return value of the passed block when passed a block" do
- output = @html.multipart_form { "test" }
- output.should equal_element("FORM", { "ENCTYPE" => "multipart/form-data", "METHOD" => "post" }, "test")
- end
- end
+ describe "when passed no arguments" do
+ it "returns a 'form'-element with it's enctype set to multipart" do
+ output = @html.multipart_form
+ output.should equal_element("FORM", { "ENCTYPE" => "multipart/form-data", "METHOD" => "post" }, "")
+ end
- describe "when passed action" do
- it "returns a 'form'-element with the passed action" do
- output = @html.multipart_form("/some/other/script.rb")
- output.should equal_element("FORM", { "ENCTYPE" => "multipart/form-data", "METHOD" => "post", "ACTION" => "/some/other/script.rb" }, "")
+ it "includes the return value of the passed block when passed a block" do
+ output = @html.multipart_form { "test" }
+ output.should equal_element("FORM", { "ENCTYPE" => "multipart/form-data", "METHOD" => "post" }, "test")
+ end
end
- it "includes the return value of the passed block when passed a block" do
- output = @html.multipart_form("/some/other/script.rb") { "test" }
- output.should equal_element("FORM", { "ENCTYPE" => "multipart/form-data", "METHOD" => "post", "ACTION" => "/some/other/script.rb" }, "test")
- end
- end
+ describe "when passed action" do
+ it "returns a 'form'-element with the passed action" do
+ output = @html.multipart_form("/some/other/script.rb")
+ output.should equal_element("FORM", { "ENCTYPE" => "multipart/form-data", "METHOD" => "post", "ACTION" => "/some/other/script.rb" }, "")
+ end
- describe "when passed action, enctype" do
- it "returns a 'form'-element with the passed action and enctype" do
- output = @html.multipart_form("/some/other/script.rb", "application/x-www-form-urlencoded")
- output.should equal_element("FORM", { "ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "post", "ACTION" => "/some/other/script.rb" }, "")
+ it "includes the return value of the passed block when passed a block" do
+ output = @html.multipart_form("/some/other/script.rb") { "test" }
+ output.should equal_element("FORM", { "ENCTYPE" => "multipart/form-data", "METHOD" => "post", "ACTION" => "/some/other/script.rb" }, "test")
+ end
end
- it "includes the return value of the passed block when passed a block" do
- output = @html.multipart_form("/some/other/script.rb", "application/x-www-form-urlencoded") { "test" }
- output.should equal_element("FORM", { "ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "post", "ACTION" => "/some/other/script.rb" }, "test")
+ describe "when passed action, enctype" do
+ it "returns a 'form'-element with the passed action and enctype" do
+ output = @html.multipart_form("/some/other/script.rb", "application/x-www-form-urlencoded")
+ output.should equal_element("FORM", { "ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "post", "ACTION" => "/some/other/script.rb" }, "")
+ end
+
+ it "includes the return value of the passed block when passed a block" do
+ output = @html.multipart_form("/some/other/script.rb", "application/x-www-form-urlencoded") { "test" }
+ output.should equal_element("FORM", { "ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "post", "ACTION" => "/some/other/script.rb" }, "test")
+ end
end
- end
- describe "when passed Hash" do
- it "returns a 'form'-element with the passed Hash as attributes" do
- output = @html.multipart_form("ID" => "test")
- output.should equal_element("FORM", { "ENCTYPE" => "multipart/form-data", "METHOD" => "post", "ID" => "test" }, "")
+ describe "when passed Hash" do
+ it "returns a 'form'-element with the passed Hash as attributes" do
+ output = @html.multipart_form("ID" => "test")
+ output.should equal_element("FORM", { "ENCTYPE" => "multipart/form-data", "METHOD" => "post", "ID" => "test" }, "")
- output = @html.multipart_form("ID" => "test", "ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "get")
- output.should equal_element("FORM", { "ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "get", "ID" => "test" }, "")
- end
+ output = @html.multipart_form("ID" => "test", "ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "get")
+ output.should equal_element("FORM", { "ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "get", "ID" => "test" }, "")
+ end
- it "includes the return value of the passed block when passed a block" do
- output = @html.multipart_form("ID" => "test") { "test" }
- output.should equal_element("FORM", { "ENCTYPE" => "multipart/form-data", "METHOD" => "post", "ID" => "test" }, "test")
+ it "includes the return value of the passed block when passed a block" do
+ output = @html.multipart_form("ID" => "test") { "test" }
+ output.should equal_element("FORM", { "ENCTYPE" => "multipart/form-data", "METHOD" => "post", "ID" => "test" }, "test")
- output = @html.multipart_form("ID" => "test", "ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "get") { "test" }
- output.should equal_element("FORM", { "ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "get", "ID" => "test" }, "test")
+ output = @html.multipart_form("ID" => "test", "ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "get") { "test" }
+ output.should equal_element("FORM", { "ENCTYPE" => "application/x-www-form-urlencoded", "METHOD" => "get", "ID" => "test" }, "test")
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/htmlextension/password_field_spec.rb b/spec/ruby/library/cgi/htmlextension/password_field_spec.rb
index 683bc428ba..0fefdd5c45 100644
--- a/spec/ruby/library/cgi/htmlextension/password_field_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/password_field_spec.rb
@@ -1,84 +1,87 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'fixtures/common'
-describe "CGI::HtmlExtension#password_field" do
- before :each do
- @html = CGISpecs.cgi_new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'fixtures/common'
- describe "when passed no arguments" do
- it "returns an password-'input'-element without a name" do
- output = @html.password_field
- output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "password", "SIZE" => "40"}, "", not_closed: true)
+ describe "CGI::HtmlExtension#password_field" do
+ before :each do
+ @html = CGISpecs.cgi_new
end
- it "ignores a passed block" do
- output = @html.password_field { "test" }
- output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "password", "SIZE" => "40"}, "", not_closed: true)
- end
- end
+ describe "when passed no arguments" do
+ it "returns an password-'input'-element without a name" do
+ output = @html.password_field
+ output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "password", "SIZE" => "40"}, "", not_closed: true)
+ end
- describe "when passed name" do
- it "returns an password-'input'-element with the passed name" do
- output = @html.password_field("test")
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "password", "SIZE" => "40"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.password_field { "test" }
+ output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "password", "SIZE" => "40"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.password_field("test") { "test" }
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "password", "SIZE" => "40"}, "", not_closed: true)
- end
- end
+ describe "when passed name" do
+ it "returns an password-'input'-element with the passed name" do
+ output = @html.password_field("test")
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "password", "SIZE" => "40"}, "", not_closed: true)
+ end
- describe "when passed name, value" do
- it "returns an password-'input'-element with the passed name and value" do
- output = @html.password_field("test", "some value")
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "password", "VALUE" => "some value", "SIZE" => "40"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.password_field("test") { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "password", "SIZE" => "40"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.password_field("test", "some value") { "test" }
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "password", "VALUE" => "some value", "SIZE" => "40"}, "", not_closed: true)
- end
- end
+ describe "when passed name, value" do
+ it "returns an password-'input'-element with the passed name and value" do
+ output = @html.password_field("test", "some value")
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "password", "VALUE" => "some value", "SIZE" => "40"}, "", not_closed: true)
+ end
- describe "when passed name, value, size" do
- it "returns an password-'input'-element with the passed name, value and size" do
- output = @html.password_field("test", "some value", 60)
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "password", "VALUE" => "some value", "SIZE" => "60"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.password_field("test", "some value") { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "password", "VALUE" => "some value", "SIZE" => "40"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.password_field("test", "some value", 60) { "test" }
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "password", "VALUE" => "some value", "SIZE" => "60"}, "", not_closed: true)
- end
- end
+ describe "when passed name, value, size" do
+ it "returns an password-'input'-element with the passed name, value and size" do
+ output = @html.password_field("test", "some value", 60)
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "password", "VALUE" => "some value", "SIZE" => "60"}, "", not_closed: true)
+ end
- describe "when passed name, value, size, maxlength" do
- it "returns an password-'input'-element with the passed name, value, size and maxlength" do
- output = @html.password_field("test", "some value", 60, 12)
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "password", "VALUE" => "some value", "SIZE" => "60", "MAXLENGTH" => 12}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.password_field("test", "some value", 60) { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "password", "VALUE" => "some value", "SIZE" => "60"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.password_field("test", "some value", 60, 12) { "test" }
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "password", "VALUE" => "some value", "SIZE" => "60", "MAXLENGTH" => 12}, "", not_closed: true)
+ describe "when passed name, value, size, maxlength" do
+ it "returns an password-'input'-element with the passed name, value, size and maxlength" do
+ output = @html.password_field("test", "some value", 60, 12)
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "password", "VALUE" => "some value", "SIZE" => "60", "MAXLENGTH" => 12}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.password_field("test", "some value", 60, 12) { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "password", "VALUE" => "some value", "SIZE" => "60", "MAXLENGTH" => 12}, "", not_closed: true)
+ end
end
- end
- describe "when passed Hash" do
- it "returns a checkbox-'input'-element using the passed Hash for attributes" do
- output = @html.password_field("NAME" => "test", "VALUE" => "some value")
- output.should equal_element("INPUT", { "NAME" => "test", "VALUE" => "some value", "TYPE" => "password" }, "", not_closed: true)
+ describe "when passed Hash" do
+ it "returns a checkbox-'input'-element using the passed Hash for attributes" do
+ output = @html.password_field("NAME" => "test", "VALUE" => "some value")
+ output.should equal_element("INPUT", { "NAME" => "test", "VALUE" => "some value", "TYPE" => "password" }, "", not_closed: true)
- output = @html.password_field("TYPE" => "hidden")
- output.should equal_element("INPUT", {"TYPE" => "password"}, "", not_closed: true)
- end
+ output = @html.password_field("TYPE" => "hidden")
+ output.should equal_element("INPUT", {"TYPE" => "password"}, "", not_closed: true)
+ end
- it "ignores a passed block" do
- output = @html.password_field("NAME" => "test", "VALUE" => "some value") { "test" }
- output.should equal_element("INPUT", { "NAME" => "test", "VALUE" => "some value", "TYPE" => "password" }, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.password_field("NAME" => "test", "VALUE" => "some value") { "test" }
+ output.should equal_element("INPUT", { "NAME" => "test", "VALUE" => "some value", "TYPE" => "password" }, "", not_closed: true)
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/htmlextension/popup_menu_spec.rb b/spec/ruby/library/cgi/htmlextension/popup_menu_spec.rb
index 3462be09b0..7452d15317 100644
--- a/spec/ruby/library/cgi/htmlextension/popup_menu_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/popup_menu_spec.rb
@@ -1,8 +1,11 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'fixtures/common'
-require_relative 'shared/popup_menu'
-describe "CGI::HtmlExtension#popup_menu" do
- it_behaves_like :cgi_htmlextension_popup_menu, :popup_menu
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'fixtures/common'
+ require_relative 'shared/popup_menu'
+
+ describe "CGI::HtmlExtension#popup_menu" do
+ it_behaves_like :cgi_htmlextension_popup_menu, :popup_menu
+ end
end
diff --git a/spec/ruby/library/cgi/htmlextension/radio_button_spec.rb b/spec/ruby/library/cgi/htmlextension/radio_button_spec.rb
index 3dc3c879b5..8458685cdc 100644
--- a/spec/ruby/library/cgi/htmlextension/radio_button_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/radio_button_spec.rb
@@ -1,77 +1,80 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'fixtures/common'
-describe "CGI::HtmlExtension#radio_button" do
- before :each do
- @html = CGISpecs.cgi_new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'fixtures/common'
- describe "when passed no arguments" do
- it "returns a radio-'input'-element without a name" do
- output = @html.radio_button
- output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "radio"}, "", not_closed: true)
+ describe "CGI::HtmlExtension#radio_button" do
+ before :each do
+ @html = CGISpecs.cgi_new
end
- it "ignores a passed block" do
- output = @html.radio_button { "test" }
- output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "radio"}, "", not_closed: true)
- end
- end
+ describe "when passed no arguments" do
+ it "returns a radio-'input'-element without a name" do
+ output = @html.radio_button
+ output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "radio"}, "", not_closed: true)
+ end
- describe "when passed name" do
- it "returns a radio-'input'-element with the passed name" do
- output = @html.radio_button("test")
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.radio_button { "test" }
+ output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "radio"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.radio_button("test") { "test" }
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio"}, "", not_closed: true)
- end
- end
+ describe "when passed name" do
+ it "returns a radio-'input'-element with the passed name" do
+ output = @html.radio_button("test")
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio"}, "", not_closed: true)
+ end
- describe "CGI::HtmlExtension#checkbox when passed name, value" do
- it "returns a radio-'input'-element with the passed name and value" do
- output = @html.radio_button("test", "test-value")
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "test-value"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.radio_button("test") { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.radio_button("test", "test-value") { "test" }
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "test-value"}, "", not_closed: true)
+ describe "CGI::HtmlExtension#checkbox when passed name, value" do
+ it "returns a radio-'input'-element with the passed name and value" do
+ output = @html.radio_button("test", "test-value")
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "test-value"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.radio_button("test", "test-value") { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "test-value"}, "", not_closed: true)
+ end
end
- end
- describe "when passed name, value, checked" do
- it "returns a checked radio-'input'-element with the passed name and value when checked is true" do
- output = @html.radio_button("test", "test-value", true)
- output.should equal_element("INPUT", {"CHECKED" => true, "NAME" => "test", "TYPE" => "radio", "VALUE" => "test-value"}, "", not_closed: true)
+ describe "when passed name, value, checked" do
+ it "returns a checked radio-'input'-element with the passed name and value when checked is true" do
+ output = @html.radio_button("test", "test-value", true)
+ output.should equal_element("INPUT", {"CHECKED" => true, "NAME" => "test", "TYPE" => "radio", "VALUE" => "test-value"}, "", not_closed: true)
- output = @html.radio_button("test", "test-value", false)
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "test-value"}, "", not_closed: true)
+ output = @html.radio_button("test", "test-value", false)
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "test-value"}, "", not_closed: true)
- output = @html.radio_button("test", "test-value", nil)
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "test-value"}, "", not_closed: true)
- end
+ output = @html.radio_button("test", "test-value", nil)
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "test-value"}, "", not_closed: true)
+ end
- it "ignores a passed block" do
- output = @html.radio_button("test", "test-value", nil) { "test" }
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "test-value"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.radio_button("test", "test-value", nil) { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "test-value"}, "", not_closed: true)
+ end
end
- end
- describe "when passed Hash" do
- it "returns a radio-'input'-element using the passed Hash for attributes" do
- attributes = {"NAME" => "test", "VALUE" => "test-value", "CHECKED" => true}
- output = @html.radio_button(attributes)
- output.should equal_element("INPUT", attributes, "", not_closed: true)
- end
+ describe "when passed Hash" do
+ it "returns a radio-'input'-element using the passed Hash for attributes" do
+ attributes = {"NAME" => "test", "VALUE" => "test-value", "CHECKED" => true}
+ output = @html.radio_button(attributes)
+ output.should equal_element("INPUT", attributes, "", not_closed: true)
+ end
- it "ignores a passed block" do
- attributes = {"NAME" => "test", "VALUE" => "test-value", "CHECKED" => true}
- output = @html.radio_button(attributes) { "test" }
- output.should equal_element("INPUT", attributes, "", not_closed: true)
+ it "ignores a passed block" do
+ attributes = {"NAME" => "test", "VALUE" => "test-value", "CHECKED" => true}
+ output = @html.radio_button(attributes) { "test" }
+ output.should equal_element("INPUT", attributes, "", not_closed: true)
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/htmlextension/radio_group_spec.rb b/spec/ruby/library/cgi/htmlextension/radio_group_spec.rb
index 1bfd43449d..fd925a5165 100644
--- a/spec/ruby/library/cgi/htmlextension/radio_group_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/radio_group_spec.rb
@@ -1,77 +1,80 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'fixtures/common'
-describe "CGI::HtmlExtension#radio_group" do
- before :each do
- @html = CGISpecs.cgi_new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'fixtures/common'
- describe "when passed name, values ..." do
- it "returns a sequence of 'radio'-elements with the passed name and the passed values" do
- output = CGISpecs.split(@html.radio_group("test", "foo", "bar", "baz"))
- output[0].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "foo"}, "foo", not_closed: true)
- output[1].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "bar"}, "bar", not_closed: true)
- output[2].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "baz"}, "baz", not_closed: true)
+ describe "CGI::HtmlExtension#radio_group" do
+ before :each do
+ @html = CGISpecs.cgi_new
end
- it "allows passing a value inside an Array" do
- output = CGISpecs.split(@html.radio_group("test", ["foo"], "bar", ["baz"]))
- output[0].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "foo"}, "foo", not_closed: true)
- output[1].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "bar"}, "bar", not_closed: true)
- output[2].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "baz"}, "baz", not_closed: true)
- end
+ describe "when passed name, values ..." do
+ it "returns a sequence of 'radio'-elements with the passed name and the passed values" do
+ output = CGISpecs.split(@html.radio_group("test", "foo", "bar", "baz"))
+ output[0].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "baz"}, "baz", not_closed: true)
+ end
- it "allows passing a value as an Array containing the value and the checked state or a label" do
- output = CGISpecs.split(@html.radio_group("test", ["foo"], ["bar", true], ["baz", "label for baz"]))
- output[0].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "foo"}, "foo", not_closed: true)
- output[1].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "test", "TYPE" => "radio", "VALUE" => "bar"}, "bar", not_closed: true)
- output[2].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "baz"}, "label for baz", not_closed: true)
- end
+ it "allows passing a value inside an Array" do
+ output = CGISpecs.split(@html.radio_group("test", ["foo"], "bar", ["baz"]))
+ output[0].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "baz"}, "baz", not_closed: true)
+ end
- # TODO: CGI does not like passing false instead of true.
- it "allows passing a value as an Array containing the value, a label and the checked state" do
- output = CGISpecs.split(@html.radio_group("test", ["foo", "label for foo", true], ["bar", "label for bar", false], ["baz", "label for baz", true]))
- output[0].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "test", "TYPE" => "radio", "VALUE" => "foo"}, "label for foo", not_closed: true)
- output[1].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "bar"}, "label for bar", not_closed: true)
- output[2].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "test", "TYPE" => "radio", "VALUE" => "baz"}, "label for baz", not_closed: true)
- end
+ it "allows passing a value as an Array containing the value and the checked state or a label" do
+ output = CGISpecs.split(@html.radio_group("test", ["foo"], ["bar", true], ["baz", "label for baz"]))
+ output[0].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "test", "TYPE" => "radio", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "baz"}, "label for baz", not_closed: true)
+ end
- it "returns an empty String when passed no values" do
- @html.radio_group("test").should == ""
- end
+ # TODO: CGI does not like passing false instead of true.
+ it "allows passing a value as an Array containing the value, a label and the checked state" do
+ output = CGISpecs.split(@html.radio_group("test", ["foo", "label for foo", true], ["bar", "label for bar", false], ["baz", "label for baz", true]))
+ output[0].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "test", "TYPE" => "radio", "VALUE" => "foo"}, "label for foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "bar"}, "label for bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "test", "TYPE" => "radio", "VALUE" => "baz"}, "label for baz", not_closed: true)
+ end
+
+ it "returns an empty String when passed no values" do
+ @html.radio_group("test").should == ""
+ end
- it "ignores a passed block" do
- output = CGISpecs.split(@html.radio_group("test", "foo", "bar", "baz") { "test" })
- output[0].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "foo"}, "foo", not_closed: true)
- output[1].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "bar"}, "bar", not_closed: true)
- output[2].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "baz"}, "baz", not_closed: true)
+ it "ignores a passed block" do
+ output = CGISpecs.split(@html.radio_group("test", "foo", "bar", "baz") { "test" })
+ output[0].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "test", "TYPE" => "radio", "VALUE" => "baz"}, "baz", not_closed: true)
+ end
end
- end
- describe "when passed Hash" do
- it "uses the passed Hash to generate the radio sequence" do
- output = CGISpecs.split(@html.radio_group("NAME" => "name", "VALUES" => ["foo", "bar", "baz"]))
- output[0].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "foo"}, "foo", not_closed: true)
- output[1].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "bar"}, "bar", not_closed: true)
- output[2].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "baz"}, "baz", not_closed: true)
+ describe "when passed Hash" do
+ it "uses the passed Hash to generate the radio sequence" do
+ output = CGISpecs.split(@html.radio_group("NAME" => "name", "VALUES" => ["foo", "bar", "baz"]))
+ output[0].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "baz"}, "baz", not_closed: true)
- output = CGISpecs.split(@html.radio_group("NAME" => "name", "VALUES" => [["foo"], ["bar", true], "baz"]))
- output[0].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "foo"}, "foo", not_closed: true)
- output[1].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "name", "TYPE" => "radio", "VALUE" => "bar"}, "bar", not_closed: true)
- output[2].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "baz"}, "baz", not_closed: true)
+ output = CGISpecs.split(@html.radio_group("NAME" => "name", "VALUES" => [["foo"], ["bar", true], "baz"]))
+ output[0].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "name", "TYPE" => "radio", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "baz"}, "baz", not_closed: true)
- output = CGISpecs.split(@html.radio_group("NAME" => "name", "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"]))
- output[0].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "1"}, "Foo", not_closed: true)
- output[1].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "name", "TYPE" => "radio", "VALUE" => "2"}, "Bar", not_closed: true)
- output[2].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "Baz"}, "Baz", not_closed: true)
- end
+ output = CGISpecs.split(@html.radio_group("NAME" => "name", "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"]))
+ output[0].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "1"}, "Foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"CHECKED" => true, "NAME" => "name", "TYPE" => "radio", "VALUE" => "2"}, "Bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "Baz"}, "Baz", not_closed: true)
+ end
- it "ignores a passed block" do
- output = CGISpecs.split(@html.radio_group("NAME" => "name", "VALUES" => ["foo", "bar", "baz"]) { "test" })
- output[0].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "foo"}, "foo", not_closed: true)
- output[1].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "bar"}, "bar", not_closed: true)
- output[2].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "baz"}, "baz", not_closed: true)
+ it "ignores a passed block" do
+ output = CGISpecs.split(@html.radio_group("NAME" => "name", "VALUES" => ["foo", "bar", "baz"]) { "test" })
+ output[0].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "foo"}, "foo", not_closed: true)
+ output[1].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "bar"}, "bar", not_closed: true)
+ output[2].should equal_element("INPUT", {"NAME" => "name", "TYPE" => "radio", "VALUE" => "baz"}, "baz", not_closed: true)
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/htmlextension/reset_spec.rb b/spec/ruby/library/cgi/htmlextension/reset_spec.rb
index 86fa25fc8a..80e4441b16 100644
--- a/spec/ruby/library/cgi/htmlextension/reset_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/reset_spec.rb
@@ -1,57 +1,60 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'fixtures/common'
-describe "CGI::HtmlExtension#reset" do
- before :each do
- @html = CGISpecs.cgi_new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'fixtures/common'
- describe "when passed no arguments" do
- it "returns a reset-'input'-element" do
- output = @html.reset
- output.should equal_element("INPUT", {"TYPE" => "reset"}, "", not_closed: true)
+ describe "CGI::HtmlExtension#reset" do
+ before :each do
+ @html = CGISpecs.cgi_new
end
- it "ignores a passed block" do
- output = @html.reset { "test" }
- output.should equal_element("INPUT", {"TYPE" => "reset"}, "", not_closed: true)
- end
- end
+ describe "when passed no arguments" do
+ it "returns a reset-'input'-element" do
+ output = @html.reset
+ output.should equal_element("INPUT", {"TYPE" => "reset"}, "", not_closed: true)
+ end
- describe "when passed value" do
- it "returns a reset-'input'-element with the passed value" do
- output = @html.reset("Example")
- output.should equal_element("INPUT", {"TYPE" => "reset", "VALUE" => "Example"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.reset { "test" }
+ output.should equal_element("INPUT", {"TYPE" => "reset"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.reset("Example") { "test" }
- output.should equal_element("INPUT", {"TYPE" => "reset", "VALUE" => "Example"}, "", not_closed: true)
- end
- end
+ describe "when passed value" do
+ it "returns a reset-'input'-element with the passed value" do
+ output = @html.reset("Example")
+ output.should equal_element("INPUT", {"TYPE" => "reset", "VALUE" => "Example"}, "", not_closed: true)
+ end
- describe "when passed value, name" do
- it "returns a reset-'input'-element with the passed value and the passed name" do
- output = @html.reset("Example", "test-name")
- output.should equal_element("INPUT", {"TYPE" => "reset", "VALUE" => "Example", "NAME" => "test-name"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.reset("Example") { "test" }
+ output.should equal_element("INPUT", {"TYPE" => "reset", "VALUE" => "Example"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.reset("Example", "test-name") { "test" }
- output.should equal_element("INPUT", {"TYPE" => "reset", "VALUE" => "Example", "NAME" => "test-name"}, "", not_closed: true)
- end
- end
+ describe "when passed value, name" do
+ it "returns a reset-'input'-element with the passed value and the passed name" do
+ output = @html.reset("Example", "test-name")
+ output.should equal_element("INPUT", {"TYPE" => "reset", "VALUE" => "Example", "NAME" => "test-name"}, "", not_closed: true)
+ end
- describe "when passed Hash" do
- it "returns a reset-'input'-element with the passed value" do
- output = @html.reset("Example")
- output.should equal_element("INPUT", {"TYPE" => "reset", "VALUE" => "Example"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.reset("Example", "test-name") { "test" }
+ output.should equal_element("INPUT", {"TYPE" => "reset", "VALUE" => "Example", "NAME" => "test-name"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.reset("Example") { "test" }
- output.should equal_element("INPUT", {"TYPE" => "reset", "VALUE" => "Example"}, "", not_closed: true)
+ describe "when passed Hash" do
+ it "returns a reset-'input'-element with the passed value" do
+ output = @html.reset("Example")
+ output.should equal_element("INPUT", {"TYPE" => "reset", "VALUE" => "Example"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.reset("Example") { "test" }
+ output.should equal_element("INPUT", {"TYPE" => "reset", "VALUE" => "Example"}, "", not_closed: true)
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/htmlextension/scrolling_list_spec.rb b/spec/ruby/library/cgi/htmlextension/scrolling_list_spec.rb
index 4eb0c86c1a..b565444679 100644
--- a/spec/ruby/library/cgi/htmlextension/scrolling_list_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/scrolling_list_spec.rb
@@ -1,8 +1,11 @@
require_relative '../../../spec_helper'
-require_relative 'fixtures/common'
-require 'cgi'
-require_relative 'shared/popup_menu'
-describe "CGI::HtmlExtension#scrolling_list" do
- it_behaves_like :cgi_htmlextension_popup_menu, :scrolling_list
+ruby_version_is ""..."4.0" do
+ require_relative 'fixtures/common'
+ require 'cgi'
+ require_relative 'shared/popup_menu'
+
+ describe "CGI::HtmlExtension#scrolling_list" do
+ it_behaves_like :cgi_htmlextension_popup_menu, :scrolling_list
+ end
end
diff --git a/spec/ruby/library/cgi/htmlextension/submit_spec.rb b/spec/ruby/library/cgi/htmlextension/submit_spec.rb
index 063891b959..bb6e079c4e 100644
--- a/spec/ruby/library/cgi/htmlextension/submit_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/submit_spec.rb
@@ -1,57 +1,60 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'fixtures/common'
-describe "CGI::HtmlExtension#submit" do
- before :each do
- @html = CGISpecs.cgi_new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'fixtures/common'
- describe "when passed no arguments" do
- it "returns a submit-'input'-element" do
- output = @html.submit
- output.should equal_element("INPUT", {"TYPE" => "submit"}, "", not_closed: true)
+ describe "CGI::HtmlExtension#submit" do
+ before :each do
+ @html = CGISpecs.cgi_new
end
- it "ignores a passed block" do
- output = @html.submit { "test" }
- output.should equal_element("INPUT", {"TYPE" => "submit"}, "", not_closed: true)
- end
- end
+ describe "when passed no arguments" do
+ it "returns a submit-'input'-element" do
+ output = @html.submit
+ output.should equal_element("INPUT", {"TYPE" => "submit"}, "", not_closed: true)
+ end
- describe "when passed value" do
- it "returns a submit-'input'-element with the passed value" do
- output = @html.submit("Example")
- output.should equal_element("INPUT", {"TYPE" => "submit", "VALUE" => "Example"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.submit { "test" }
+ output.should equal_element("INPUT", {"TYPE" => "submit"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.submit("Example") { "test" }
- output.should equal_element("INPUT", {"TYPE" => "submit", "VALUE" => "Example"}, "", not_closed: true)
- end
- end
+ describe "when passed value" do
+ it "returns a submit-'input'-element with the passed value" do
+ output = @html.submit("Example")
+ output.should equal_element("INPUT", {"TYPE" => "submit", "VALUE" => "Example"}, "", not_closed: true)
+ end
- describe "when passed value, name" do
- it "returns a submit-'input'-element with the passed value and the passed name" do
- output = @html.submit("Example", "test-name")
- output.should equal_element("INPUT", {"TYPE" => "submit", "VALUE" => "Example", "NAME" => "test-name"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.submit("Example") { "test" }
+ output.should equal_element("INPUT", {"TYPE" => "submit", "VALUE" => "Example"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.submit("Example", "test-name") { "test" }
- output.should equal_element("INPUT", {"TYPE" => "submit", "VALUE" => "Example", "NAME" => "test-name"}, "", not_closed: true)
- end
- end
+ describe "when passed value, name" do
+ it "returns a submit-'input'-element with the passed value and the passed name" do
+ output = @html.submit("Example", "test-name")
+ output.should equal_element("INPUT", {"TYPE" => "submit", "VALUE" => "Example", "NAME" => "test-name"}, "", not_closed: true)
+ end
- describe "when passed Hash" do
- it "returns a submit-'input'-element with the passed value" do
- output = @html.submit("Example")
- output.should equal_element("INPUT", {"TYPE" => "submit", "VALUE" => "Example"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.submit("Example", "test-name") { "test" }
+ output.should equal_element("INPUT", {"TYPE" => "submit", "VALUE" => "Example", "NAME" => "test-name"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.submit("Example") { "test" }
- output.should equal_element("INPUT", {"TYPE" => "submit", "VALUE" => "Example"}, "", not_closed: true)
+ describe "when passed Hash" do
+ it "returns a submit-'input'-element with the passed value" do
+ output = @html.submit("Example")
+ output.should equal_element("INPUT", {"TYPE" => "submit", "VALUE" => "Example"}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.submit("Example") { "test" }
+ output.should equal_element("INPUT", {"TYPE" => "submit", "VALUE" => "Example"}, "", not_closed: true)
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/htmlextension/text_field_spec.rb b/spec/ruby/library/cgi/htmlextension/text_field_spec.rb
index 44b5a5e69f..37e13e3746 100644
--- a/spec/ruby/library/cgi/htmlextension/text_field_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/text_field_spec.rb
@@ -1,84 +1,87 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'fixtures/common'
-describe "CGI::HtmlExtension#text_field" do
- before :each do
- @html = CGISpecs.cgi_new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'fixtures/common'
- describe "when passed no arguments" do
- it "returns an text-'input'-element without a name" do
- output = @html.text_field
- output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "text", "SIZE" => "40"}, "", not_closed: true)
+ describe "CGI::HtmlExtension#text_field" do
+ before :each do
+ @html = CGISpecs.cgi_new
end
- it "ignores a passed block" do
- output = @html.text_field { "test" }
- output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "text", "SIZE" => "40"}, "", not_closed: true)
- end
- end
+ describe "when passed no arguments" do
+ it "returns an text-'input'-element without a name" do
+ output = @html.text_field
+ output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "text", "SIZE" => "40"}, "", not_closed: true)
+ end
- describe "when passed name" do
- it "returns an text-'input'-element with the passed name" do
- output = @html.text_field("test")
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "text", "SIZE" => "40"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.text_field { "test" }
+ output.should equal_element("INPUT", {"NAME" => "", "TYPE" => "text", "SIZE" => "40"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.text_field("test") { "test" }
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "text", "SIZE" => "40"}, "", not_closed: true)
- end
- end
+ describe "when passed name" do
+ it "returns an text-'input'-element with the passed name" do
+ output = @html.text_field("test")
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "text", "SIZE" => "40"}, "", not_closed: true)
+ end
- describe "when passed name, value" do
- it "returns an text-'input'-element with the passed name and value" do
- output = @html.text_field("test", "some value")
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "text", "VALUE" => "some value", "SIZE" => "40"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.text_field("test") { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "text", "SIZE" => "40"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.text_field("test", "some value") { "test" }
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "text", "VALUE" => "some value", "SIZE" => "40"}, "", not_closed: true)
- end
- end
+ describe "when passed name, value" do
+ it "returns an text-'input'-element with the passed name and value" do
+ output = @html.text_field("test", "some value")
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "text", "VALUE" => "some value", "SIZE" => "40"}, "", not_closed: true)
+ end
- describe "when passed name, value, size" do
- it "returns an text-'input'-element with the passed name, value and size" do
- output = @html.text_field("test", "some value", 60)
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "text", "VALUE" => "some value", "SIZE" => "60"}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.text_field("test", "some value") { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "text", "VALUE" => "some value", "SIZE" => "40"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.text_field("test", "some value", 60) { "test" }
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "text", "VALUE" => "some value", "SIZE" => "60"}, "", not_closed: true)
- end
- end
+ describe "when passed name, value, size" do
+ it "returns an text-'input'-element with the passed name, value and size" do
+ output = @html.text_field("test", "some value", 60)
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "text", "VALUE" => "some value", "SIZE" => "60"}, "", not_closed: true)
+ end
- describe "when passed name, value, size, maxlength" do
- it "returns an text-'input'-element with the passed name, value, size and maxlength" do
- output = @html.text_field("test", "some value", 60, 12)
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "text", "VALUE" => "some value", "SIZE" => "60", "MAXLENGTH" => 12}, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.text_field("test", "some value", 60) { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "text", "VALUE" => "some value", "SIZE" => "60"}, "", not_closed: true)
+ end
end
- it "ignores a passed block" do
- output = @html.text_field("test", "some value", 60, 12) { "test" }
- output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "text", "VALUE" => "some value", "SIZE" => "60", "MAXLENGTH" => 12}, "", not_closed: true)
+ describe "when passed name, value, size, maxlength" do
+ it "returns an text-'input'-element with the passed name, value, size and maxlength" do
+ output = @html.text_field("test", "some value", 60, 12)
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "text", "VALUE" => "some value", "SIZE" => "60", "MAXLENGTH" => 12}, "", not_closed: true)
+ end
+
+ it "ignores a passed block" do
+ output = @html.text_field("test", "some value", 60, 12) { "test" }
+ output.should equal_element("INPUT", {"NAME" => "test", "TYPE" => "text", "VALUE" => "some value", "SIZE" => "60", "MAXLENGTH" => 12}, "", not_closed: true)
+ end
end
- end
- describe "when passed Hash" do
- it "returns a checkbox-'input'-element using the passed Hash for attributes" do
- output = @html.text_field("NAME" => "test", "VALUE" => "some value")
- output.should equal_element("INPUT", { "NAME" => "test", "VALUE" => "some value", "TYPE" => "text" }, "", not_closed: true)
+ describe "when passed Hash" do
+ it "returns a checkbox-'input'-element using the passed Hash for attributes" do
+ output = @html.text_field("NAME" => "test", "VALUE" => "some value")
+ output.should equal_element("INPUT", { "NAME" => "test", "VALUE" => "some value", "TYPE" => "text" }, "", not_closed: true)
- output = @html.text_field("TYPE" => "hidden")
- output.should equal_element("INPUT", {"TYPE" => "text"}, "", not_closed: true)
- end
+ output = @html.text_field("TYPE" => "hidden")
+ output.should equal_element("INPUT", {"TYPE" => "text"}, "", not_closed: true)
+ end
- it "ignores a passed block" do
- output = @html.text_field("NAME" => "test", "VALUE" => "some value") { "test" }
- output.should equal_element("INPUT", { "NAME" => "test", "VALUE" => "some value", "TYPE" => "text" }, "", not_closed: true)
+ it "ignores a passed block" do
+ output = @html.text_field("NAME" => "test", "VALUE" => "some value") { "test" }
+ output.should equal_element("INPUT", { "NAME" => "test", "VALUE" => "some value", "TYPE" => "text" }, "", not_closed: true)
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/htmlextension/textarea_spec.rb b/spec/ruby/library/cgi/htmlextension/textarea_spec.rb
index db84a973d2..99c6d3dd2d 100644
--- a/spec/ruby/library/cgi/htmlextension/textarea_spec.rb
+++ b/spec/ruby/library/cgi/htmlextension/textarea_spec.rb
@@ -1,73 +1,76 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'fixtures/common'
-describe "CGI::HtmlExtension#textarea" do
- before :each do
- @html = CGISpecs.cgi_new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'fixtures/common'
- describe "when passed no arguments" do
- it "returns an 'textarea'-element without a name" do
- output = @html.textarea
- output.should equal_element("TEXTAREA", {"NAME" => "", "COLS" => "70", "ROWS" => "10"}, "")
+ describe "CGI::HtmlExtension#textarea" do
+ before :each do
+ @html = CGISpecs.cgi_new
end
- it "includes the return value of the passed block when passed a block" do
- output = @html.textarea { "Example" }
- output.should equal_element("TEXTAREA", {"NAME" => "", "COLS" => "70", "ROWS" => "10"}, "Example")
- end
- end
+ describe "when passed no arguments" do
+ it "returns an 'textarea'-element without a name" do
+ output = @html.textarea
+ output.should equal_element("TEXTAREA", {"NAME" => "", "COLS" => "70", "ROWS" => "10"}, "")
+ end
- describe "when passed name" do
- it "returns an 'textarea'-element with the passed name" do
- output = @html.textarea("test")
- output.should equal_element("TEXTAREA", {"NAME" => "test", "COLS" => "70", "ROWS" => "10"}, "")
+ it "includes the return value of the passed block when passed a block" do
+ output = @html.textarea { "Example" }
+ output.should equal_element("TEXTAREA", {"NAME" => "", "COLS" => "70", "ROWS" => "10"}, "Example")
+ end
end
- it "includes the return value of the passed block when passed a block" do
- output = @html.textarea("test") { "Example" }
- output.should equal_element("TEXTAREA", {"NAME" => "test", "COLS" => "70", "ROWS" => "10"}, "Example")
- end
- end
+ describe "when passed name" do
+ it "returns an 'textarea'-element with the passed name" do
+ output = @html.textarea("test")
+ output.should equal_element("TEXTAREA", {"NAME" => "test", "COLS" => "70", "ROWS" => "10"}, "")
+ end
- describe "when passed name, cols" do
- it "returns an 'textarea'-element with the passed name and the passed amount of columns" do
- output = @html.textarea("test", 40)
- output.should equal_element("TEXTAREA", {"NAME" => "test", "COLS" => "40", "ROWS" => "10"}, "")
+ it "includes the return value of the passed block when passed a block" do
+ output = @html.textarea("test") { "Example" }
+ output.should equal_element("TEXTAREA", {"NAME" => "test", "COLS" => "70", "ROWS" => "10"}, "Example")
+ end
end
- it "includes the return value of the passed block when passed a block" do
- output = @html.textarea("test", 40) { "Example" }
- output.should equal_element("TEXTAREA", {"NAME" => "test", "COLS" => "40", "ROWS" => "10"}, "Example")
- end
- end
+ describe "when passed name, cols" do
+ it "returns an 'textarea'-element with the passed name and the passed amount of columns" do
+ output = @html.textarea("test", 40)
+ output.should equal_element("TEXTAREA", {"NAME" => "test", "COLS" => "40", "ROWS" => "10"}, "")
+ end
- describe "when passed name, cols, rows" do
- it "returns an 'textarea'-element with the passed name, the passed amount of columns and the passed number of rows" do
- output = @html.textarea("test", 40, 5)
- output.should equal_element("TEXTAREA", {"NAME" => "test", "COLS" => "40", "ROWS" => "5"}, "")
+ it "includes the return value of the passed block when passed a block" do
+ output = @html.textarea("test", 40) { "Example" }
+ output.should equal_element("TEXTAREA", {"NAME" => "test", "COLS" => "40", "ROWS" => "10"}, "Example")
+ end
end
- it "includes the return value of the passed block when passed a block" do
- output = @html.textarea("test", 40, 5) { "Example" }
- output.should equal_element("TEXTAREA", {"NAME" => "test", "COLS" => "40", "ROWS" => "5"}, "Example")
+ describe "when passed name, cols, rows" do
+ it "returns an 'textarea'-element with the passed name, the passed amount of columns and the passed number of rows" do
+ output = @html.textarea("test", 40, 5)
+ output.should equal_element("TEXTAREA", {"NAME" => "test", "COLS" => "40", "ROWS" => "5"}, "")
+ end
+
+ it "includes the return value of the passed block when passed a block" do
+ output = @html.textarea("test", 40, 5) { "Example" }
+ output.should equal_element("TEXTAREA", {"NAME" => "test", "COLS" => "40", "ROWS" => "5"}, "Example")
+ end
end
- end
- describe "when passed Hash" do
- it "uses the passed Hash as attributes" do
- @html.textarea("ID" => "test").should == '<TEXTAREA ID="test"></TEXTAREA>'
+ describe "when passed Hash" do
+ it "uses the passed Hash as attributes" do
+ @html.textarea("ID" => "test").should == '<TEXTAREA ID="test"></TEXTAREA>'
- attributes = {"ID" => "test-id", "NAME" => "test-name"}
- output = @html.textarea(attributes)
- output.should equal_element("TEXTAREA", attributes, "")
- end
+ attributes = {"ID" => "test-id", "NAME" => "test-name"}
+ output = @html.textarea(attributes)
+ output.should equal_element("TEXTAREA", attributes, "")
+ end
- it "includes the return value of the passed block when passed a block" do
- attributes = {"ID" => "test-id", "NAME" => "test-name"}
- output = @html.textarea(attributes) { "test" }
- output.should equal_element("TEXTAREA", attributes, "test")
+ it "includes the return value of the passed block when passed a block" do
+ attributes = {"ID" => "test-id", "NAME" => "test-name"}
+ output = @html.textarea(attributes) { "test" }
+ output.should equal_element("TEXTAREA", attributes, "test")
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/http_header_spec.rb b/spec/ruby/library/cgi/http_header_spec.rb
index 4094bebed3..8d9f3fe9b8 100644
--- a/spec/ruby/library/cgi/http_header_spec.rb
+++ b/spec/ruby/library/cgi/http_header_spec.rb
@@ -1,8 +1,11 @@
require_relative '../../spec_helper'
-require 'cgi'
-require_relative 'shared/http_header'
+ruby_version_is ""..."4.0" do
+ require 'cgi'
-describe "CGI#http_header" do
- it_behaves_like :cgi_http_header, :http_header
+ require_relative 'shared/http_header'
+
+ describe "CGI#http_header" do
+ it_behaves_like :cgi_http_header, :http_header
+ end
end
diff --git a/spec/ruby/library/cgi/initialize_spec.rb b/spec/ruby/library/cgi/initialize_spec.rb
index 61bc971d49..b8ecf5cac2 100644
--- a/spec/ruby/library/cgi/initialize_spec.rb
+++ b/spec/ruby/library/cgi/initialize_spec.rb
@@ -1,133 +1,136 @@
require_relative '../../spec_helper'
-require 'cgi'
-describe "CGI#initialize" do
- it "is private" do
- CGI.should have_private_instance_method(:initialize)
- end
-end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
-describe "CGI#initialize when passed no arguments" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.allocate
- end
-
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
-
- it "extends self with CGI::QueryExtension" do
- @cgi.send(:initialize)
- @cgi.should be_kind_of(CGI::QueryExtension)
+ describe "CGI#initialize" do
+ it "is private" do
+ CGI.should have_private_instance_method(:initialize)
+ end
end
- it "does not extend self with CGI::HtmlExtension" do
- @cgi.send(:initialize)
- @cgi.should_not be_kind_of(CGI::HtmlExtension)
- end
+ describe "CGI#initialize when passed no arguments" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.allocate
+ end
- it "does not extend self with any of the other HTML modules" do
- @cgi.send(:initialize)
- @cgi.should_not be_kind_of(CGI::HtmlExtension)
- @cgi.should_not be_kind_of(CGI::Html3)
- @cgi.should_not be_kind_of(CGI::Html4)
- @cgi.should_not be_kind_of(CGI::Html4Tr)
- @cgi.should_not be_kind_of(CGI::Html4Fr)
- end
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "sets #cookies based on ENV['HTTP_COOKIE']" do
- begin
- old_env, ENV["HTTP_COOKIE"] = ENV["HTTP_COOKIE"], "test=test yay"
+ it "extends self with CGI::QueryExtension" do
@cgi.send(:initialize)
- @cgi.cookies.should == { "test"=>[ "test yay" ] }
- ensure
- ENV["HTTP_COOKIE"] = old_env
+ @cgi.should be_kind_of(CGI::QueryExtension)
end
- end
- it "sets #params based on ENV['QUERY_STRING'] when ENV['REQUEST_METHOD'] is GET" do
- begin
- old_env_query, ENV["QUERY_STRING"] = ENV["QUERY_STRING"], "?test=a&test2=b"
- old_env_method, ENV["REQUEST_METHOD"] = ENV["REQUEST_METHOD"], "GET"
+ it "does not extend self with CGI::HtmlExtension" do
@cgi.send(:initialize)
- @cgi.params.should == { "test2" => ["b"], "?test" => ["a"] }
- ensure
- ENV["QUERY_STRING"] = old_env_query
- ENV["REQUEST_METHOD"] = old_env_method
+ @cgi.should_not be_kind_of(CGI::HtmlExtension)
end
- end
- it "sets #params based on ENV['QUERY_STRING'] when ENV['REQUEST_METHOD'] is HEAD" do
- begin
- old_env_query, ENV["QUERY_STRING"] = ENV["QUERY_STRING"], "?test=a&test2=b"
- old_env_method, ENV["REQUEST_METHOD"] = ENV["REQUEST_METHOD"], "HEAD"
+ it "does not extend self with any of the other HTML modules" do
@cgi.send(:initialize)
- @cgi.params.should == { "test2" => ["b"], "?test" => ["a"] }
- ensure
- ENV["QUERY_STRING"] = old_env_query
- ENV["REQUEST_METHOD"] = old_env_method
+ @cgi.should_not be_kind_of(CGI::HtmlExtension)
+ @cgi.should_not be_kind_of(CGI::Html3)
+ @cgi.should_not be_kind_of(CGI::Html4)
+ @cgi.should_not be_kind_of(CGI::Html4Tr)
+ @cgi.should_not be_kind_of(CGI::Html4Fr)
end
- end
-end
-describe "CGI#initialize when passed type" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.allocate
- end
+ it "sets #cookies based on ENV['HTTP_COOKIE']" do
+ begin
+ old_env, ENV["HTTP_COOKIE"] = ENV["HTTP_COOKIE"], "test=test yay"
+ @cgi.send(:initialize)
+ @cgi.cookies.should == { "test"=>[ "test yay" ] }
+ ensure
+ ENV["HTTP_COOKIE"] = old_env
+ end
+ end
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
+ it "sets #params based on ENV['QUERY_STRING'] when ENV['REQUEST_METHOD'] is GET" do
+ begin
+ old_env_query, ENV["QUERY_STRING"] = ENV["QUERY_STRING"], "?test=a&test2=b"
+ old_env_method, ENV["REQUEST_METHOD"] = ENV["REQUEST_METHOD"], "GET"
+ @cgi.send(:initialize)
+ @cgi.params.should == { "test2" => ["b"], "?test" => ["a"] }
+ ensure
+ ENV["QUERY_STRING"] = old_env_query
+ ENV["REQUEST_METHOD"] = old_env_method
+ end
+ end
+
+ it "sets #params based on ENV['QUERY_STRING'] when ENV['REQUEST_METHOD'] is HEAD" do
+ begin
+ old_env_query, ENV["QUERY_STRING"] = ENV["QUERY_STRING"], "?test=a&test2=b"
+ old_env_method, ENV["REQUEST_METHOD"] = ENV["REQUEST_METHOD"], "HEAD"
+ @cgi.send(:initialize)
+ @cgi.params.should == { "test2" => ["b"], "?test" => ["a"] }
+ ensure
+ ENV["QUERY_STRING"] = old_env_query
+ ENV["REQUEST_METHOD"] = old_env_method
+ end
+ end
end
+ describe "CGI#initialize when passed type" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.allocate
+ end
- it "extends self with CGI::QueryExtension" do
- @cgi.send(:initialize, "test")
- @cgi.should be_kind_of(CGI::QueryExtension)
- end
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "extends self with CGI::QueryExtension, CGI::Html3 and CGI::HtmlExtension when the passed type is 'html3'" do
- @cgi.send(:initialize, "html3")
- @cgi.should be_kind_of(CGI::Html3)
- @cgi.should be_kind_of(CGI::HtmlExtension)
- @cgi.should be_kind_of(CGI::QueryExtension)
- @cgi.should_not be_kind_of(CGI::Html4)
- @cgi.should_not be_kind_of(CGI::Html4Tr)
- @cgi.should_not be_kind_of(CGI::Html4Fr)
- end
+ it "extends self with CGI::QueryExtension" do
+ @cgi.send(:initialize, "test")
+ @cgi.should be_kind_of(CGI::QueryExtension)
+ end
- it "extends self with CGI::QueryExtension, CGI::Html4 and CGI::HtmlExtension when the passed type is 'html4'" do
- @cgi.send(:initialize, "html4")
- @cgi.should be_kind_of(CGI::Html4)
- @cgi.should be_kind_of(CGI::HtmlExtension)
- @cgi.should be_kind_of(CGI::QueryExtension)
+ it "extends self with CGI::QueryExtension, CGI::Html3 and CGI::HtmlExtension when the passed type is 'html3'" do
+ @cgi.send(:initialize, "html3")
+ @cgi.should be_kind_of(CGI::Html3)
+ @cgi.should be_kind_of(CGI::HtmlExtension)
+ @cgi.should be_kind_of(CGI::QueryExtension)
- @cgi.should_not be_kind_of(CGI::Html3)
- @cgi.should_not be_kind_of(CGI::Html4Tr)
- @cgi.should_not be_kind_of(CGI::Html4Fr)
- end
+ @cgi.should_not be_kind_of(CGI::Html4)
+ @cgi.should_not be_kind_of(CGI::Html4Tr)
+ @cgi.should_not be_kind_of(CGI::Html4Fr)
+ end
- it "extends self with CGI::QueryExtension, CGI::Html4Tr and CGI::HtmlExtension when the passed type is 'html4Tr'" do
- @cgi.send(:initialize, "html4Tr")
- @cgi.should be_kind_of(CGI::Html4Tr)
- @cgi.should be_kind_of(CGI::HtmlExtension)
- @cgi.should be_kind_of(CGI::QueryExtension)
+ it "extends self with CGI::QueryExtension, CGI::Html4 and CGI::HtmlExtension when the passed type is 'html4'" do
+ @cgi.send(:initialize, "html4")
+ @cgi.should be_kind_of(CGI::Html4)
+ @cgi.should be_kind_of(CGI::HtmlExtension)
+ @cgi.should be_kind_of(CGI::QueryExtension)
- @cgi.should_not be_kind_of(CGI::Html3)
- @cgi.should_not be_kind_of(CGI::Html4)
- @cgi.should_not be_kind_of(CGI::Html4Fr)
- end
+ @cgi.should_not be_kind_of(CGI::Html3)
+ @cgi.should_not be_kind_of(CGI::Html4Tr)
+ @cgi.should_not be_kind_of(CGI::Html4Fr)
+ end
- it "extends self with CGI::QueryExtension, CGI::Html4Tr, CGI::Html4Fr and CGI::HtmlExtension when the passed type is 'html4Fr'" do
- @cgi.send(:initialize, "html4Fr")
- @cgi.should be_kind_of(CGI::Html4Tr)
- @cgi.should be_kind_of(CGI::Html4Fr)
- @cgi.should be_kind_of(CGI::HtmlExtension)
- @cgi.should be_kind_of(CGI::QueryExtension)
+ it "extends self with CGI::QueryExtension, CGI::Html4Tr and CGI::HtmlExtension when the passed type is 'html4Tr'" do
+ @cgi.send(:initialize, "html4Tr")
+ @cgi.should be_kind_of(CGI::Html4Tr)
+ @cgi.should be_kind_of(CGI::HtmlExtension)
+ @cgi.should be_kind_of(CGI::QueryExtension)
- @cgi.should_not be_kind_of(CGI::Html3)
- @cgi.should_not be_kind_of(CGI::Html4)
+ @cgi.should_not be_kind_of(CGI::Html3)
+ @cgi.should_not be_kind_of(CGI::Html4)
+ @cgi.should_not be_kind_of(CGI::Html4Fr)
+ end
+
+ it "extends self with CGI::QueryExtension, CGI::Html4Tr, CGI::Html4Fr and CGI::HtmlExtension when the passed type is 'html4Fr'" do
+ @cgi.send(:initialize, "html4Fr")
+ @cgi.should be_kind_of(CGI::Html4Tr)
+ @cgi.should be_kind_of(CGI::Html4Fr)
+ @cgi.should be_kind_of(CGI::HtmlExtension)
+ @cgi.should be_kind_of(CGI::QueryExtension)
+
+ @cgi.should_not be_kind_of(CGI::Html3)
+ @cgi.should_not be_kind_of(CGI::Html4)
+ end
end
end
diff --git a/spec/ruby/library/cgi/out_spec.rb b/spec/ruby/library/cgi/out_spec.rb
index bc09f5bcbb..733e656ea1 100644
--- a/spec/ruby/library/cgi/out_spec.rb
+++ b/spec/ruby/library/cgi/out_spec.rb
@@ -1,51 +1,54 @@
require_relative '../../spec_helper'
-require 'cgi'
-describe "CGI#out" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- $stdout, @old_stdout = IOStub.new, $stdout
- end
-
- after :each do
- $stdout = @old_stdout
- ENV['REQUEST_METHOD'] = @old_request_method
- end
-
- it "it writes a HTMl header based on the passed argument to $stdout" do
- @cgi.out { "" }
- $stdout.should == "Content-Type: text/html\r\nContent-Length: 0\r\n\r\n"
- end
-
- it "appends the block's return value to the HTML header" do
- @cgi.out { "test!" }
- $stdout.should == "Content-Type: text/html\r\nContent-Length: 5\r\n\r\ntest!"
- end
-
- it "automatically sets the Content-Length Header based on the block's return value" do
- @cgi.out { "0123456789" }
- $stdout.should == "Content-Type: text/html\r\nContent-Length: 10\r\n\r\n0123456789"
- end
-
- it "includes Cookies in the @output_cookies field" do
- @cgi.instance_variable_set(:@output_cookies, ["multiple", "cookies"])
- @cgi.out { "" }
- $stdout.should == "Content-Type: text/html\r\nContent-Length: 0\r\nSet-Cookie: multiple\r\nSet-Cookie: cookies\r\n\r\n"
- end
-end
-
-describe "CGI#out when passed no block" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
-
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
-
- it "raises a LocalJumpError" do
- -> { @cgi.out }.should raise_error(LocalJumpError)
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+
+ describe "CGI#out" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ $stdout, @old_stdout = IOStub.new, $stdout
+ end
+
+ after :each do
+ $stdout = @old_stdout
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "it writes a HTMl header based on the passed argument to $stdout" do
+ @cgi.out { "" }
+ $stdout.should == "Content-Type: text/html\r\nContent-Length: 0\r\n\r\n"
+ end
+
+ it "appends the block's return value to the HTML header" do
+ @cgi.out { "test!" }
+ $stdout.should == "Content-Type: text/html\r\nContent-Length: 5\r\n\r\ntest!"
+ end
+
+ it "automatically sets the Content-Length Header based on the block's return value" do
+ @cgi.out { "0123456789" }
+ $stdout.should == "Content-Type: text/html\r\nContent-Length: 10\r\n\r\n0123456789"
+ end
+
+ it "includes Cookies in the @output_cookies field" do
+ @cgi.instance_variable_set(:@output_cookies, ["multiple", "cookies"])
+ @cgi.out { "" }
+ $stdout.should == "Content-Type: text/html\r\nContent-Length: 0\r\nSet-Cookie: multiple\r\nSet-Cookie: cookies\r\n\r\n"
+ end
+ end
+
+ describe "CGI#out when passed no block" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
+
+ it "raises a LocalJumpError" do
+ -> { @cgi.out }.should raise_error(LocalJumpError)
+ end
end
end
diff --git a/spec/ruby/library/cgi/parse_spec.rb b/spec/ruby/library/cgi/parse_spec.rb
index 04539b1226..f09270c195 100644
--- a/spec/ruby/library/cgi/parse_spec.rb
+++ b/spec/ruby/library/cgi/parse_spec.rb
@@ -1,24 +1,27 @@
require_relative '../../spec_helper'
-require 'cgi'
-describe "CGI.parse when passed String" do
- it "parses a HTTP Query String into a Hash" do
- CGI.parse("test=test&a=b").should == { "a" => ["b"], "test" => ["test"] }
- CGI.parse("test=1,2,3").should == { "test" => ["1,2,3"] }
- CGI.parse("test=a&a=&b=").should == { "test" => ["a"], "a" => [""], "b" => [""] }
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- it "parses query strings with semicolons in place of ampersands" do
- CGI.parse("test=test;a=b").should == { "a" => ["b"], "test" => ["test"] }
- CGI.parse("test=a;a=;b=").should == { "test" => ["a"], "a" => [""], "b" => [""] }
- end
+ describe "CGI.parse when passed String" do
+ it "parses a HTTP Query String into a Hash" do
+ CGI.parse("test=test&a=b").should == { "a" => ["b"], "test" => ["test"] }
+ CGI.parse("test=1,2,3").should == { "test" => ["1,2,3"] }
+ CGI.parse("test=a&a=&b=").should == { "test" => ["a"], "a" => [""], "b" => [""] }
+ end
- it "allows passing multiple values for one key" do
- CGI.parse("test=1&test=2&test=3").should == { "test" => ["1", "2", "3"] }
- CGI.parse("test[]=1&test[]=2&test[]=3").should == { "test[]" => [ "1", "2", "3" ] }
- end
+ it "parses query strings with semicolons in place of ampersands" do
+ CGI.parse("test=test;a=b").should == { "a" => ["b"], "test" => ["test"] }
+ CGI.parse("test=a;a=;b=").should == { "test" => ["a"], "a" => [""], "b" => [""] }
+ end
+
+ it "allows passing multiple values for one key" do
+ CGI.parse("test=1&test=2&test=3").should == { "test" => ["1", "2", "3"] }
+ CGI.parse("test[]=1&test[]=2&test[]=3").should == { "test[]" => [ "1", "2", "3" ] }
+ end
- it "unescapes keys and values" do
- CGI.parse("hello%3F=hello%21").should == { "hello?" => ["hello!"] }
+ it "unescapes keys and values" do
+ CGI.parse("hello%3F=hello%21").should == { "hello?" => ["hello!"] }
+ end
end
end
diff --git a/spec/ruby/library/cgi/pretty_spec.rb b/spec/ruby/library/cgi/pretty_spec.rb
index a7b7505c15..9df1611037 100644
--- a/spec/ruby/library/cgi/pretty_spec.rb
+++ b/spec/ruby/library/cgi/pretty_spec.rb
@@ -1,24 +1,27 @@
require_relative '../../spec_helper'
-require 'cgi'
-describe "CGI.pretty when passed html" do
- it "indents the passed html String with two spaces" do
- CGI.pretty("<HTML><BODY></BODY></HTML>").should == <<-EOS
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+
+ describe "CGI.pretty when passed html" do
+ it "indents the passed html String with two spaces" do
+ CGI.pretty("<HTML><BODY></BODY></HTML>").should == <<-EOS
<HTML>
<BODY>
</BODY>
</HTML>
EOS
+ end
end
-end
-describe "CGI.pretty when passed html, indentation_unit" do
- it "indents the passed html String with the passed indentation_unit" do
- CGI.pretty("<HTML><BODY></BODY></HTML>", "\t").should == <<-EOS
+ describe "CGI.pretty when passed html, indentation_unit" do
+ it "indents the passed html String with the passed indentation_unit" do
+ CGI.pretty("<HTML><BODY></BODY></HTML>", "\t").should == <<-EOS
<HTML>
\t<BODY>
\t</BODY>
</HTML>
EOS
+ end
end
end
diff --git a/spec/ruby/library/cgi/print_spec.rb b/spec/ruby/library/cgi/print_spec.rb
index 18ab8d673b..f4f461c5c0 100644
--- a/spec/ruby/library/cgi/print_spec.rb
+++ b/spec/ruby/library/cgi/print_spec.rb
@@ -1,26 +1,29 @@
require_relative '../../spec_helper'
-require 'cgi'
-describe "CGI#print" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI#print" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
- it "passes all arguments to $stdout.print" do
- $stdout.should_receive(:print).with("test")
- @cgi.print("test")
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- $stdout.should_receive(:print).with("one", "two", "three", ["four", "five"])
- @cgi.print("one", "two", "three", ["four", "five"])
- end
+ it "passes all arguments to $stdout.print" do
+ $stdout.should_receive(:print).with("test")
+ @cgi.print("test")
+
+ $stdout.should_receive(:print).with("one", "two", "three", ["four", "five"])
+ @cgi.print("one", "two", "three", ["four", "five"])
+ end
- it "returns the result of calling $stdout.print" do
- $stdout.should_receive(:print).with("test").and_return(:expected)
- @cgi.print("test").should == :expected
+ it "returns the result of calling $stdout.print" do
+ $stdout.should_receive(:print).with("test").and_return(:expected)
+ @cgi.print("test").should == :expected
+ end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/accept_charset_spec.rb b/spec/ruby/library/cgi/queryextension/accept_charset_spec.rb
index 0487569b9c..be05f0c175 100644
--- a/spec/ruby/library/cgi/queryextension/accept_charset_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/accept_charset_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#accept_charset" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#accept_charset" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['HTTP_ACCEPT_CHARSET']" do
- old_value, ENV['HTTP_ACCEPT_CHARSET'] = ENV['HTTP_ACCEPT_CHARSET'], "ISO-8859-1,utf-8;q=0.7,*;q=0.7"
- begin
- @cgi.accept_charset.should == "ISO-8859-1,utf-8;q=0.7,*;q=0.7"
- ensure
- ENV['HTTP_ACCEPT_CHARSET'] = old_value
+ it "returns ENV['HTTP_ACCEPT_CHARSET']" do
+ old_value, ENV['HTTP_ACCEPT_CHARSET'] = ENV['HTTP_ACCEPT_CHARSET'], "ISO-8859-1,utf-8;q=0.7,*;q=0.7"
+ begin
+ @cgi.accept_charset.should == "ISO-8859-1,utf-8;q=0.7,*;q=0.7"
+ ensure
+ ENV['HTTP_ACCEPT_CHARSET'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/accept_encoding_spec.rb b/spec/ruby/library/cgi/queryextension/accept_encoding_spec.rb
index 35ff3c2b30..42eb4a49b5 100644
--- a/spec/ruby/library/cgi/queryextension/accept_encoding_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/accept_encoding_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#accept_encoding" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#accept_encoding" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['HTTP_ACCEPT_ENCODING']" do
- old_value, ENV['HTTP_ACCEPT_ENCODING'] = ENV['HTTP_ACCEPT_ENCODING'], "gzip,deflate"
- begin
- @cgi.accept_encoding.should == "gzip,deflate"
- ensure
- ENV['HTTP_ACCEPT_ENCODING'] = old_value
+ it "returns ENV['HTTP_ACCEPT_ENCODING']" do
+ old_value, ENV['HTTP_ACCEPT_ENCODING'] = ENV['HTTP_ACCEPT_ENCODING'], "gzip,deflate"
+ begin
+ @cgi.accept_encoding.should == "gzip,deflate"
+ ensure
+ ENV['HTTP_ACCEPT_ENCODING'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/accept_language_spec.rb b/spec/ruby/library/cgi/queryextension/accept_language_spec.rb
index 4a15d58914..19f29c6345 100644
--- a/spec/ruby/library/cgi/queryextension/accept_language_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/accept_language_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#accept_language" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#accept_language" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['HTTP_ACCEPT_LANGUAGE']" do
- old_value, ENV['HTTP_ACCEPT_LANGUAGE'] = ENV['HTTP_ACCEPT_LANGUAGE'], "en-us,en;q=0.5"
- begin
- @cgi.accept_language.should == "en-us,en;q=0.5"
- ensure
- ENV['HTTP_ACCEPT_LANGUAGE'] = old_value
+ it "returns ENV['HTTP_ACCEPT_LANGUAGE']" do
+ old_value, ENV['HTTP_ACCEPT_LANGUAGE'] = ENV['HTTP_ACCEPT_LANGUAGE'], "en-us,en;q=0.5"
+ begin
+ @cgi.accept_language.should == "en-us,en;q=0.5"
+ ensure
+ ENV['HTTP_ACCEPT_LANGUAGE'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/accept_spec.rb b/spec/ruby/library/cgi/queryextension/accept_spec.rb
index af5209ffbe..dcae39a736 100644
--- a/spec/ruby/library/cgi/queryextension/accept_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/accept_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#accept" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#accept" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['HTTP_ACCEPT']" do
- old_value, ENV['HTTP_ACCEPT'] = ENV['HTTP_ACCEPT'], "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"
- begin
- @cgi.accept.should == "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"
- ensure
- ENV['HTTP_ACCEPT'] = old_value
+ it "returns ENV['HTTP_ACCEPT']" do
+ old_value, ENV['HTTP_ACCEPT'] = ENV['HTTP_ACCEPT'], "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"
+ begin
+ @cgi.accept.should == "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"
+ ensure
+ ENV['HTTP_ACCEPT'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/auth_type_spec.rb b/spec/ruby/library/cgi/queryextension/auth_type_spec.rb
index 25318269b1..75e9cdb27a 100644
--- a/spec/ruby/library/cgi/queryextension/auth_type_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/auth_type_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#auth_type" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#auth_type" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['AUTH_TYPE']" do
- old_value, ENV['AUTH_TYPE'] = ENV['AUTH_TYPE'], "Basic"
- begin
- @cgi.auth_type.should == "Basic"
- ensure
- ENV['AUTH_TYPE'] = old_value
+ it "returns ENV['AUTH_TYPE']" do
+ old_value, ENV['AUTH_TYPE'] = ENV['AUTH_TYPE'], "Basic"
+ begin
+ @cgi.auth_type.should == "Basic"
+ ensure
+ ENV['AUTH_TYPE'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/cache_control_spec.rb b/spec/ruby/library/cgi/queryextension/cache_control_spec.rb
index 0471307c22..c4b727e671 100644
--- a/spec/ruby/library/cgi/queryextension/cache_control_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/cache_control_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#cache_control" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#cache_control" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['HTTP_CACHE_CONTROL']" do
- old_value, ENV['HTTP_CACHE_CONTROL'] = ENV['HTTP_CACHE_CONTROL'], "no-cache"
- begin
- @cgi.cache_control.should == "no-cache"
- ensure
- ENV['HTTP_CACHE_CONTROL'] = old_value
+ it "returns ENV['HTTP_CACHE_CONTROL']" do
+ old_value, ENV['HTTP_CACHE_CONTROL'] = ENV['HTTP_CACHE_CONTROL'], "no-cache"
+ begin
+ @cgi.cache_control.should == "no-cache"
+ ensure
+ ENV['HTTP_CACHE_CONTROL'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/content_length_spec.rb b/spec/ruby/library/cgi/queryextension/content_length_spec.rb
index de823f7119..a8b87e148c 100644
--- a/spec/ruby/library/cgi/queryextension/content_length_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/content_length_spec.rb
@@ -1,26 +1,29 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#content_length" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#content_length" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['CONTENT_LENGTH'] as Integer" do
- old_value = ENV['CONTENT_LENGTH']
- begin
- ENV['CONTENT_LENGTH'] = nil
- @cgi.content_length.should be_nil
+ it "returns ENV['CONTENT_LENGTH'] as Integer" do
+ old_value = ENV['CONTENT_LENGTH']
+ begin
+ ENV['CONTENT_LENGTH'] = nil
+ @cgi.content_length.should be_nil
- ENV['CONTENT_LENGTH'] = "100"
- @cgi.content_length.should eql(100)
- ensure
- ENV['CONTENT_LENGTH'] = old_value
+ ENV['CONTENT_LENGTH'] = "100"
+ @cgi.content_length.should eql(100)
+ ensure
+ ENV['CONTENT_LENGTH'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/content_type_spec.rb b/spec/ruby/library/cgi/queryextension/content_type_spec.rb
index 49b8389c87..d3cbdf0b14 100644
--- a/spec/ruby/library/cgi/queryextension/content_type_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/content_type_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#content_type" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#content_type" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['CONTENT_TYPE']" do
- old_value, ENV['CONTENT_TYPE'] = ENV['CONTENT_TYPE'], "text/html"
- begin
- @cgi.content_type.should == "text/html"
- ensure
- ENV['CONTENT_TYPE'] = old_value
+ it "returns ENV['CONTENT_TYPE']" do
+ old_value, ENV['CONTENT_TYPE'] = ENV['CONTENT_TYPE'], "text/html"
+ begin
+ @cgi.content_type.should == "text/html"
+ ensure
+ ENV['CONTENT_TYPE'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/cookies_spec.rb b/spec/ruby/library/cgi/queryextension/cookies_spec.rb
index 4befd61ab7..266fe0c721 100644
--- a/spec/ruby/library/cgi/queryextension/cookies_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/cookies_spec.rb
@@ -1,10 +1,13 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#cookies" do
- it "needs to be reviewed for spec completeness"
-end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+
+ describe "CGI::QueryExtension#cookies" do
+ it "needs to be reviewed for spec completeness"
+ end
-describe "CGI::QueryExtension#cookies=" do
- it "needs to be reviewed for spec completeness"
+ describe "CGI::QueryExtension#cookies=" do
+ it "needs to be reviewed for spec completeness"
+ end
end
diff --git a/spec/ruby/library/cgi/queryextension/element_reference_spec.rb b/spec/ruby/library/cgi/queryextension/element_reference_spec.rb
index 6ac5b46407..0b57387efc 100644
--- a/spec/ruby/library/cgi/queryextension/element_reference_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/element_reference_spec.rb
@@ -1,27 +1,30 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#[]" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- ENV['QUERY_STRING'], @old_query_string = "one=a&two=b&two=c", ENV['QUERY_STRING']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- ENV['QUERY_STRING'] = @old_query_string
- end
+ describe "CGI::QueryExtension#[]" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ ENV['QUERY_STRING'], @old_query_string = "one=a&two=b&two=c", ENV['QUERY_STRING']
+ @cgi = CGI.new
+ end
- it "it returns the value for the parameter with the given key" do
- @cgi["one"].should == "a"
- end
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ ENV['QUERY_STRING'] = @old_query_string
+ end
- it "only returns the first value for parameters with multiple values" do
- @cgi["two"].should == "b"
- end
+ it "it returns the value for the parameter with the given key" do
+ @cgi["one"].should == "a"
+ end
+
+ it "only returns the first value for parameters with multiple values" do
+ @cgi["two"].should == "b"
+ end
- it "returns a String" do
- @cgi["one"].should be_kind_of(String)
+ it "returns a String" do
+ @cgi["one"].should be_kind_of(String)
+ end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/from_spec.rb b/spec/ruby/library/cgi/queryextension/from_spec.rb
index 04a992cfc7..b341e0be10 100644
--- a/spec/ruby/library/cgi/queryextension/from_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/from_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#from" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#from" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['HTTP_FROM']" do
- old_value, ENV['HTTP_FROM'] = ENV['HTTP_FROM'], "googlebot(at)googlebot.com"
- begin
- @cgi.from.should == "googlebot(at)googlebot.com"
- ensure
- ENV['HTTP_FROM'] = old_value
+ it "returns ENV['HTTP_FROM']" do
+ old_value, ENV['HTTP_FROM'] = ENV['HTTP_FROM'], "googlebot(at)googlebot.com"
+ begin
+ @cgi.from.should == "googlebot(at)googlebot.com"
+ ensure
+ ENV['HTTP_FROM'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/gateway_interface_spec.rb b/spec/ruby/library/cgi/queryextension/gateway_interface_spec.rb
index 3ead5bd8bf..c82522326b 100644
--- a/spec/ruby/library/cgi/queryextension/gateway_interface_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/gateway_interface_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#gateway_interface" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#gateway_interface" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['GATEWAY_INTERFACE']" do
- old_value, ENV['GATEWAY_INTERFACE'] = ENV['GATEWAY_INTERFACE'], "CGI/1.1"
- begin
- @cgi.gateway_interface.should == "CGI/1.1"
- ensure
- ENV['GATEWAY_INTERFACE'] = old_value
+ it "returns ENV['GATEWAY_INTERFACE']" do
+ old_value, ENV['GATEWAY_INTERFACE'] = ENV['GATEWAY_INTERFACE'], "CGI/1.1"
+ begin
+ @cgi.gateway_interface.should == "CGI/1.1"
+ ensure
+ ENV['GATEWAY_INTERFACE'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/has_key_spec.rb b/spec/ruby/library/cgi/queryextension/has_key_spec.rb
index 525b45b507..43f7aae1b2 100644
--- a/spec/ruby/library/cgi/queryextension/has_key_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/has_key_spec.rb
@@ -1,7 +1,10 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'shared/has_key'
-describe "CGI::QueryExtension#has_key?" do
- it_behaves_like :cgi_query_extension_has_key_p, :has_key?
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'shared/has_key'
+
+ describe "CGI::QueryExtension#has_key?" do
+ it_behaves_like :cgi_query_extension_has_key_p, :has_key?
+ end
end
diff --git a/spec/ruby/library/cgi/queryextension/host_spec.rb b/spec/ruby/library/cgi/queryextension/host_spec.rb
index e820e0afc3..e1047c942b 100644
--- a/spec/ruby/library/cgi/queryextension/host_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/host_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#host" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#host" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['HTTP_HOST']" do
- old_value, ENV['HTTP_HOST'] = ENV['HTTP_HOST'], "localhost"
- begin
- @cgi.host.should == "localhost"
- ensure
- ENV['HTTP_HOST'] = old_value
+ it "returns ENV['HTTP_HOST']" do
+ old_value, ENV['HTTP_HOST'] = ENV['HTTP_HOST'], "localhost"
+ begin
+ @cgi.host.should == "localhost"
+ ensure
+ ENV['HTTP_HOST'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/include_spec.rb b/spec/ruby/library/cgi/queryextension/include_spec.rb
index 12365ea284..7275c309f9 100644
--- a/spec/ruby/library/cgi/queryextension/include_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/include_spec.rb
@@ -1,7 +1,10 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'shared/has_key'
-describe "CGI::QueryExtension#include?" do
- it_behaves_like :cgi_query_extension_has_key_p, :include?
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'shared/has_key'
+
+ describe "CGI::QueryExtension#include?" do
+ it_behaves_like :cgi_query_extension_has_key_p, :include?
+ end
end
diff --git a/spec/ruby/library/cgi/queryextension/key_spec.rb b/spec/ruby/library/cgi/queryextension/key_spec.rb
index d0f1e4cee2..dc2f52fbe0 100644
--- a/spec/ruby/library/cgi/queryextension/key_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/key_spec.rb
@@ -1,7 +1,10 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require_relative 'shared/has_key'
-describe "CGI::QueryExtension#key?" do
- it_behaves_like :cgi_query_extension_has_key_p, :key?
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require_relative 'shared/has_key'
+
+ describe "CGI::QueryExtension#key?" do
+ it_behaves_like :cgi_query_extension_has_key_p, :key?
+ end
end
diff --git a/spec/ruby/library/cgi/queryextension/keys_spec.rb b/spec/ruby/library/cgi/queryextension/keys_spec.rb
index 14d77180fa..bb16914065 100644
--- a/spec/ruby/library/cgi/queryextension/keys_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/keys_spec.rb
@@ -1,20 +1,23 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#keys" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- ENV['QUERY_STRING'], @old_query_string = "one=a&two=b", ENV['QUERY_STRING']
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- @cgi = CGI.new
- end
+ describe "CGI::QueryExtension#keys" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ ENV['QUERY_STRING'], @old_query_string = "one=a&two=b", ENV['QUERY_STRING']
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- ENV['QUERY_STRING'] = @old_query_string
- end
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ ENV['QUERY_STRING'] = @old_query_string
+ end
- it "returns all parameter keys as an Array" do
- @cgi.keys.sort.should == ["one", "two"]
+ it "returns all parameter keys as an Array" do
+ @cgi.keys.sort.should == ["one", "two"]
+ end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/multipart_spec.rb b/spec/ruby/library/cgi/queryextension/multipart_spec.rb
index ced4cb05a1..281791892c 100644
--- a/spec/ruby/library/cgi/queryextension/multipart_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/multipart_spec.rb
@@ -1,20 +1,22 @@
require_relative '../../../spec_helper'
-require 'cgi'
-require "stringio"
-describe "CGI::QueryExtension#multipart?" do
- before :each do
- @old_stdin = $stdin
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+ require "stringio"
- @old_request_method = ENV['REQUEST_METHOD']
- @old_content_type = ENV['CONTENT_TYPE']
- @old_content_length = ENV['CONTENT_LENGTH']
+ describe "CGI::QueryExtension#multipart?" do
+ before :each do
+ @old_stdin = $stdin
- ENV['REQUEST_METHOD'] = "POST"
- ENV["CONTENT_TYPE"] = "multipart/form-data; boundary=---------------------------1137522503144128232716531729"
- ENV["CONTENT_LENGTH"] = "222"
+ @old_request_method = ENV['REQUEST_METHOD']
+ @old_content_type = ENV['CONTENT_TYPE']
+ @old_content_length = ENV['CONTENT_LENGTH']
- $stdin = StringIO.new <<-EOS
+ ENV['REQUEST_METHOD'] = "POST"
+ ENV["CONTENT_TYPE"] = "multipart/form-data; boundary=---------------------------1137522503144128232716531729"
+ ENV["CONTENT_LENGTH"] = "222"
+
+ $stdin = StringIO.new <<-EOS
-----------------------------1137522503144128232716531729\r
Content-Disposition: form-data; name="file"; filename=""\r
Content-Type: application/octet-stream\r
@@ -23,18 +25,19 @@ Content-Type: application/octet-stream\r
-----------------------------1137522503144128232716531729--\r
EOS
- @cgi = CGI.new
- end
+ @cgi = CGI.new
+ end
- after :each do
- $stdin = @old_stdin
+ after :each do
+ $stdin = @old_stdin
- ENV['REQUEST_METHOD'] = @old_request_method
- ENV['CONTENT_TYPE'] = @old_content_type
- ENV['CONTENT_LENGTH'] = @old_content_length
- end
+ ENV['REQUEST_METHOD'] = @old_request_method
+ ENV['CONTENT_TYPE'] = @old_content_type
+ ENV['CONTENT_LENGTH'] = @old_content_length
+ end
- it "returns true if the current Request is a multipart request" do
- @cgi.multipart?.should be_true
+ it "returns true if the current Request is a multipart request" do
+ @cgi.multipart?.should be_true
+ end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/negotiate_spec.rb b/spec/ruby/library/cgi/queryextension/negotiate_spec.rb
index b6fe036042..4083e6a8cd 100644
--- a/spec/ruby/library/cgi/queryextension/negotiate_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/negotiate_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#negotiate" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#negotiate" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['HTTP_NEGOTIATE']" do
- old_value, ENV['HTTP_NEGOTIATE'] = ENV['HTTP_NEGOTIATE'], "trans"
- begin
- @cgi.negotiate.should == "trans"
- ensure
- ENV['HTTP_NEGOTIATE'] = old_value
+ it "returns ENV['HTTP_NEGOTIATE']" do
+ old_value, ENV['HTTP_NEGOTIATE'] = ENV['HTTP_NEGOTIATE'], "trans"
+ begin
+ @cgi.negotiate.should == "trans"
+ ensure
+ ENV['HTTP_NEGOTIATE'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/params_spec.rb b/spec/ruby/library/cgi/queryextension/params_spec.rb
index f4449e3c8a..938028ea14 100644
--- a/spec/ruby/library/cgi/queryextension/params_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/params_spec.rb
@@ -1,37 +1,40 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#params" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- ENV['QUERY_STRING'], @old_query_string = "one=a&two=b&two=c&three", ENV['QUERY_STRING']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['QUERY_STRING'] = @old_query_string
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#params" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ ENV['QUERY_STRING'], @old_query_string = "one=a&two=b&two=c&three", ENV['QUERY_STRING']
+ @cgi = CGI.new
+ end
- it "returns the parsed HTTP Query Params" do
- @cgi.params.should == {"three"=>[], "two"=>["b", "c"], "one"=>["a"]}
- end
-end
+ after :each do
+ ENV['QUERY_STRING'] = @old_query_string
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
-describe "CGI::QueryExtension#params=" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
+ it "returns the parsed HTTP Query Params" do
+ @cgi.params.should == {"three"=>[], "two"=>["b", "c"], "one"=>["a"]}
+ end
end
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#params=" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "sets the HTTP Query Params to the passed argument" do
- @cgi.params.should == {}
+ it "sets the HTTP Query Params to the passed argument" do
+ @cgi.params.should == {}
- @cgi.params = {"one"=>["a"], "two"=>["b", "c"]}
- @cgi.params.should == {"one"=>["a"], "two"=>["b", "c"]}
+ @cgi.params = {"one"=>["a"], "two"=>["b", "c"]}
+ @cgi.params.should == {"one"=>["a"], "two"=>["b", "c"]}
+ end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/path_info_spec.rb b/spec/ruby/library/cgi/queryextension/path_info_spec.rb
index 9785df85f1..9b7834c514 100644
--- a/spec/ruby/library/cgi/queryextension/path_info_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/path_info_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#path_info" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#path_info" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['PATH_INFO']" do
- old_value, ENV['PATH_INFO'] = ENV['PATH_INFO'], "/test/path"
- begin
- @cgi.path_info.should == "/test/path"
- ensure
- ENV['PATH_INFO'] = old_value
+ it "returns ENV['PATH_INFO']" do
+ old_value, ENV['PATH_INFO'] = ENV['PATH_INFO'], "/test/path"
+ begin
+ @cgi.path_info.should == "/test/path"
+ ensure
+ ENV['PATH_INFO'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/path_translated_spec.rb b/spec/ruby/library/cgi/queryextension/path_translated_spec.rb
index 417a749341..a773aaafdb 100644
--- a/spec/ruby/library/cgi/queryextension/path_translated_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/path_translated_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#path_translated" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#path_translated" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['PATH_TRANSLATED']" do
- old_value, ENV['PATH_TRANSLATED'] = ENV['PATH_TRANSLATED'], "/full/path/to/dir"
- begin
- @cgi.path_translated.should == "/full/path/to/dir"
- ensure
- ENV['PATH_TRANSLATED'] = old_value
+ it "returns ENV['PATH_TRANSLATED']" do
+ old_value, ENV['PATH_TRANSLATED'] = ENV['PATH_TRANSLATED'], "/full/path/to/dir"
+ begin
+ @cgi.path_translated.should == "/full/path/to/dir"
+ ensure
+ ENV['PATH_TRANSLATED'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/pragma_spec.rb b/spec/ruby/library/cgi/queryextension/pragma_spec.rb
index 02d5c91221..be384182a5 100644
--- a/spec/ruby/library/cgi/queryextension/pragma_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/pragma_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#pragma" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#pragma" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['HTTP_PRAGMA']" do
- old_value, ENV['HTTP_PRAGMA'] = ENV['HTTP_PRAGMA'], "no-cache"
- begin
- @cgi.pragma.should == "no-cache"
- ensure
- ENV['HTTP_PRAGMA'] = old_value
+ it "returns ENV['HTTP_PRAGMA']" do
+ old_value, ENV['HTTP_PRAGMA'] = ENV['HTTP_PRAGMA'], "no-cache"
+ begin
+ @cgi.pragma.should == "no-cache"
+ ensure
+ ENV['HTTP_PRAGMA'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/query_string_spec.rb b/spec/ruby/library/cgi/queryextension/query_string_spec.rb
index a6b454a7eb..64fbeaea10 100644
--- a/spec/ruby/library/cgi/queryextension/query_string_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/query_string_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#query_string" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#query_string" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['QUERY_STRING']" do
- old_value, ENV['QUERY_STRING'] = ENV['QUERY_STRING'], "one=a&two=b"
- begin
- @cgi.query_string.should == "one=a&two=b"
- ensure
- ENV['QUERY_STRING'] = old_value
+ it "returns ENV['QUERY_STRING']" do
+ old_value, ENV['QUERY_STRING'] = ENV['QUERY_STRING'], "one=a&two=b"
+ begin
+ @cgi.query_string.should == "one=a&two=b"
+ ensure
+ ENV['QUERY_STRING'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/raw_cookie2_spec.rb b/spec/ruby/library/cgi/queryextension/raw_cookie2_spec.rb
index 3d7072e346..30d314aca1 100644
--- a/spec/ruby/library/cgi/queryextension/raw_cookie2_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/raw_cookie2_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#raw_cookie2" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#raw_cookie2" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['HTTP_COOKIE2']" do
- old_value, ENV['HTTP_COOKIE2'] = ENV['HTTP_COOKIE2'], "some_cookie=data"
- begin
- @cgi.raw_cookie2.should == "some_cookie=data"
- ensure
- ENV['HTTP_COOKIE2'] = old_value
+ it "returns ENV['HTTP_COOKIE2']" do
+ old_value, ENV['HTTP_COOKIE2'] = ENV['HTTP_COOKIE2'], "some_cookie=data"
+ begin
+ @cgi.raw_cookie2.should == "some_cookie=data"
+ ensure
+ ENV['HTTP_COOKIE2'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/raw_cookie_spec.rb b/spec/ruby/library/cgi/queryextension/raw_cookie_spec.rb
index ede7b9ff87..affa504b39 100644
--- a/spec/ruby/library/cgi/queryextension/raw_cookie_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/raw_cookie_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#raw_cookie" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#raw_cookie" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['HTTP_COOKIE']" do
- old_value, ENV['HTTP_COOKIE'] = ENV['HTTP_COOKIE'], "some_cookie=data"
- begin
- @cgi.raw_cookie.should == "some_cookie=data"
- ensure
- ENV['HTTP_COOKIE'] = old_value
+ it "returns ENV['HTTP_COOKIE']" do
+ old_value, ENV['HTTP_COOKIE'] = ENV['HTTP_COOKIE'], "some_cookie=data"
+ begin
+ @cgi.raw_cookie.should == "some_cookie=data"
+ ensure
+ ENV['HTTP_COOKIE'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/referer_spec.rb b/spec/ruby/library/cgi/queryextension/referer_spec.rb
index 6cd5dc96f8..53fc19ddd0 100644
--- a/spec/ruby/library/cgi/queryextension/referer_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/referer_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#referer" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#referer" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['HTTP_REFERER']" do
- old_value, ENV['HTTP_REFERER'] = ENV['HTTP_REFERER'], "example.com"
- begin
- @cgi.referer.should == "example.com"
- ensure
- ENV['HTTP_REFERER'] = old_value
+ it "returns ENV['HTTP_REFERER']" do
+ old_value, ENV['HTTP_REFERER'] = ENV['HTTP_REFERER'], "example.com"
+ begin
+ @cgi.referer.should == "example.com"
+ ensure
+ ENV['HTTP_REFERER'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/remote_addr_spec.rb b/spec/ruby/library/cgi/queryextension/remote_addr_spec.rb
index 0259402b23..7b5addc2d5 100644
--- a/spec/ruby/library/cgi/queryextension/remote_addr_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/remote_addr_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#remote_addr" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#remote_addr" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['REMOTE_ADDR']" do
- old_value, ENV['REMOTE_ADDR'] = ENV['REMOTE_ADDR'], "127.0.0.1"
- begin
- @cgi.remote_addr.should == "127.0.0.1"
- ensure
- ENV['REMOTE_ADDR'] = old_value
+ it "returns ENV['REMOTE_ADDR']" do
+ old_value, ENV['REMOTE_ADDR'] = ENV['REMOTE_ADDR'], "127.0.0.1"
+ begin
+ @cgi.remote_addr.should == "127.0.0.1"
+ ensure
+ ENV['REMOTE_ADDR'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/remote_host_spec.rb b/spec/ruby/library/cgi/queryextension/remote_host_spec.rb
index cf77e0031b..2dfe59ca38 100644
--- a/spec/ruby/library/cgi/queryextension/remote_host_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/remote_host_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#remote_host" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#remote_host" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['REMOTE_HOST']" do
- old_value, ENV['REMOTE_HOST'] = ENV['REMOTE_HOST'], "test.host"
- begin
- @cgi.remote_host.should == "test.host"
- ensure
- ENV['REMOTE_HOST'] = old_value
+ it "returns ENV['REMOTE_HOST']" do
+ old_value, ENV['REMOTE_HOST'] = ENV['REMOTE_HOST'], "test.host"
+ begin
+ @cgi.remote_host.should == "test.host"
+ ensure
+ ENV['REMOTE_HOST'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/remote_ident_spec.rb b/spec/ruby/library/cgi/queryextension/remote_ident_spec.rb
index 5b51d6b8ee..bb05fc7942 100644
--- a/spec/ruby/library/cgi/queryextension/remote_ident_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/remote_ident_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#remote_ident" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#remote_ident" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['REMOTE_IDENT']" do
- old_value, ENV['REMOTE_IDENT'] = ENV['REMOTE_IDENT'], "no-idea-what-this-is-for"
- begin
- @cgi.remote_ident.should == "no-idea-what-this-is-for"
- ensure
- ENV['REMOTE_IDENT'] = old_value
+ it "returns ENV['REMOTE_IDENT']" do
+ old_value, ENV['REMOTE_IDENT'] = ENV['REMOTE_IDENT'], "no-idea-what-this-is-for"
+ begin
+ @cgi.remote_ident.should == "no-idea-what-this-is-for"
+ ensure
+ ENV['REMOTE_IDENT'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/remote_user_spec.rb b/spec/ruby/library/cgi/queryextension/remote_user_spec.rb
index 1a93bb6561..29856302ab 100644
--- a/spec/ruby/library/cgi/queryextension/remote_user_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/remote_user_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#remote_user" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#remote_user" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['REMOTE_USER']" do
- old_value, ENV['REMOTE_USER'] = ENV['REMOTE_USER'], "username"
- begin
- @cgi.remote_user.should == "username"
- ensure
- ENV['REMOTE_USER'] = old_value
+ it "returns ENV['REMOTE_USER']" do
+ old_value, ENV['REMOTE_USER'] = ENV['REMOTE_USER'], "username"
+ begin
+ @cgi.remote_user.should == "username"
+ ensure
+ ENV['REMOTE_USER'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/request_method_spec.rb b/spec/ruby/library/cgi/queryextension/request_method_spec.rb
index eabdd6998b..7331b134d2 100644
--- a/spec/ruby/library/cgi/queryextension/request_method_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/request_method_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#request_method" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#request_method" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['REQUEST_METHOD']" do
- old_value, ENV['REQUEST_METHOD'] = ENV['REQUEST_METHOD'], "GET"
- begin
- @cgi.request_method.should == "GET"
- ensure
- ENV['REQUEST_METHOD'] = old_value
+ it "returns ENV['REQUEST_METHOD']" do
+ old_value, ENV['REQUEST_METHOD'] = ENV['REQUEST_METHOD'], "GET"
+ begin
+ @cgi.request_method.should == "GET"
+ ensure
+ ENV['REQUEST_METHOD'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/script_name_spec.rb b/spec/ruby/library/cgi/queryextension/script_name_spec.rb
index 341b7b6fea..4b359a545f 100644
--- a/spec/ruby/library/cgi/queryextension/script_name_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/script_name_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#script_name" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#script_name" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['SCRIPT_NAME']" do
- old_value, ENV['SCRIPT_NAME'] = ENV['SCRIPT_NAME'], "/path/to/script.rb"
- begin
- @cgi.script_name.should == "/path/to/script.rb"
- ensure
- ENV['SCRIPT_NAME'] = old_value
+ it "returns ENV['SCRIPT_NAME']" do
+ old_value, ENV['SCRIPT_NAME'] = ENV['SCRIPT_NAME'], "/path/to/script.rb"
+ begin
+ @cgi.script_name.should == "/path/to/script.rb"
+ ensure
+ ENV['SCRIPT_NAME'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/server_name_spec.rb b/spec/ruby/library/cgi/queryextension/server_name_spec.rb
index b12aaf8c5c..c1f7fb4c54 100644
--- a/spec/ruby/library/cgi/queryextension/server_name_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/server_name_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#server_name" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#server_name" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['SERVER_NAME']" do
- old_value, ENV['SERVER_NAME'] = ENV['SERVER_NAME'], "localhost"
- begin
- @cgi.server_name.should == "localhost"
- ensure
- ENV['SERVER_NAME'] = old_value
+ it "returns ENV['SERVER_NAME']" do
+ old_value, ENV['SERVER_NAME'] = ENV['SERVER_NAME'], "localhost"
+ begin
+ @cgi.server_name.should == "localhost"
+ ensure
+ ENV['SERVER_NAME'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/server_port_spec.rb b/spec/ruby/library/cgi/queryextension/server_port_spec.rb
index 0e688a99bf..60c03ea639 100644
--- a/spec/ruby/library/cgi/queryextension/server_port_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/server_port_spec.rb
@@ -1,26 +1,29 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#server_port" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#server_port" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['SERVER_PORT'] as Integer" do
- old_value = ENV['SERVER_PORT']
- begin
- ENV['SERVER_PORT'] = nil
- @cgi.server_port.should be_nil
+ it "returns ENV['SERVER_PORT'] as Integer" do
+ old_value = ENV['SERVER_PORT']
+ begin
+ ENV['SERVER_PORT'] = nil
+ @cgi.server_port.should be_nil
- ENV['SERVER_PORT'] = "3000"
- @cgi.server_port.should eql(3000)
- ensure
- ENV['SERVER_PORT'] = old_value
+ ENV['SERVER_PORT'] = "3000"
+ @cgi.server_port.should eql(3000)
+ ensure
+ ENV['SERVER_PORT'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/server_protocol_spec.rb b/spec/ruby/library/cgi/queryextension/server_protocol_spec.rb
index f9dcf3c5b8..fdbcc2108f 100644
--- a/spec/ruby/library/cgi/queryextension/server_protocol_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/server_protocol_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#server_protocol" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#server_protocol" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['SERVER_PROTOCOL']" do
- old_value, ENV['SERVER_PROTOCOL'] = ENV['SERVER_PROTOCOL'], "HTTP/1.1"
- begin
- @cgi.server_protocol.should == "HTTP/1.1"
- ensure
- ENV['SERVER_PROTOCOL'] = old_value
+ it "returns ENV['SERVER_PROTOCOL']" do
+ old_value, ENV['SERVER_PROTOCOL'] = ENV['SERVER_PROTOCOL'], "HTTP/1.1"
+ begin
+ @cgi.server_protocol.should == "HTTP/1.1"
+ ensure
+ ENV['SERVER_PROTOCOL'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/server_software_spec.rb b/spec/ruby/library/cgi/queryextension/server_software_spec.rb
index df349cdf2e..c5811a2268 100644
--- a/spec/ruby/library/cgi/queryextension/server_software_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/server_software_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#server_software" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#server_software" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['SERVER_SOFTWARE']" do
- old_value, ENV['SERVER_SOFTWARE'] = ENV['SERVER_SOFTWARE'], "Server/1.0.0"
- begin
- @cgi.server_software.should == "Server/1.0.0"
- ensure
- ENV['SERVER_SOFTWARE'] = old_value
+ it "returns ENV['SERVER_SOFTWARE']" do
+ old_value, ENV['SERVER_SOFTWARE'] = ENV['SERVER_SOFTWARE'], "Server/1.0.0"
+ begin
+ @cgi.server_software.should == "Server/1.0.0"
+ ensure
+ ENV['SERVER_SOFTWARE'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/queryextension/user_agent_spec.rb b/spec/ruby/library/cgi/queryextension/user_agent_spec.rb
index ec5ef187dd..3240352ef6 100644
--- a/spec/ruby/library/cgi/queryextension/user_agent_spec.rb
+++ b/spec/ruby/library/cgi/queryextension/user_agent_spec.rb
@@ -1,22 +1,25 @@
require_relative '../../../spec_helper'
-require 'cgi'
-describe "CGI::QueryExtension#user_agent" do
- before :each do
- ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
- @cgi = CGI.new
- end
+ruby_version_is ""..."4.0" do
+ require 'cgi'
- after :each do
- ENV['REQUEST_METHOD'] = @old_request_method
- end
+ describe "CGI::QueryExtension#user_agent" do
+ before :each do
+ ENV['REQUEST_METHOD'], @old_request_method = "GET", ENV['REQUEST_METHOD']
+ @cgi = CGI.new
+ end
+
+ after :each do
+ ENV['REQUEST_METHOD'] = @old_request_method
+ end
- it "returns ENV['HTTP_USER_AGENT']" do
- old_value, ENV['HTTP_USER_AGENT'] = ENV['HTTP_USER_AGENT'], "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_2; de-de) AppleWebKit/527+ (KHTML, like Gecko) Version/3.1 Safari/525.13"
- begin
- @cgi.user_agent.should == "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_2; de-de) AppleWebKit/527+ (KHTML, like Gecko) Version/3.1 Safari/525.13"
- ensure
- ENV['HTTP_USER_AGENT'] = old_value
+ it "returns ENV['HTTP_USER_AGENT']" do
+ old_value, ENV['HTTP_USER_AGENT'] = ENV['HTTP_USER_AGENT'], "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_2; de-de) AppleWebKit/527+ (KHTML, like Gecko) Version/3.1 Safari/525.13"
+ begin
+ @cgi.user_agent.should == "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_2; de-de) AppleWebKit/527+ (KHTML, like Gecko) Version/3.1 Safari/525.13"
+ ensure
+ ENV['HTTP_USER_AGENT'] = old_value
+ end
end
end
end
diff --git a/spec/ruby/library/cgi/rfc1123_date_spec.rb b/spec/ruby/library/cgi/rfc1123_date_spec.rb
index 6904eeabaa..636185f22c 100644
--- a/spec/ruby/library/cgi/rfc1123_date_spec.rb
+++ b/spec/ruby/library/cgi/rfc1123_date_spec.rb
@@ -1,10 +1,13 @@
require_relative '../../spec_helper'
-require 'cgi'
-describe "CGI.rfc1123_date when passed Time" do
- it "returns the passed Time formatted in RFC1123 ('Sat, 01 Dec 2007 15:56:42 GMT')" do
- input = Time.at(1196524602)
- expected = 'Sat, 01 Dec 2007 15:56:42 GMT'
- CGI.rfc1123_date(input).should == expected
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+
+ describe "CGI.rfc1123_date when passed Time" do
+ it "returns the passed Time formatted in RFC1123 ('Sat, 01 Dec 2007 15:56:42 GMT')" do
+ input = Time.at(1196524602)
+ expected = 'Sat, 01 Dec 2007 15:56:42 GMT'
+ CGI.rfc1123_date(input).should == expected
+ end
end
end
diff --git a/spec/ruby/library/cgi/unescapeElement_spec.rb b/spec/ruby/library/cgi/unescapeElement_spec.rb
index ae4d50b076..db83f0d2fb 100644
--- a/spec/ruby/library/cgi/unescapeElement_spec.rb
+++ b/spec/ruby/library/cgi/unescapeElement_spec.rb
@@ -1,5 +1,11 @@
require_relative '../../spec_helper'
-require 'cgi'
+
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+end
+ruby_version_is "4.0" do
+ require 'cgi/escape'
+end
describe "CGI.unescapeElement when passed String, elements, ..." do
it "unescapes only the tags of the passed elements in the passed String" do
diff --git a/spec/ruby/library/cgi/unescapeHTML_spec.rb b/spec/ruby/library/cgi/unescapeHTML_spec.rb
index 84b30c6aa6..e43dcc83e5 100644
--- a/spec/ruby/library/cgi/unescapeHTML_spec.rb
+++ b/spec/ruby/library/cgi/unescapeHTML_spec.rb
@@ -1,5 +1,9 @@
require_relative '../../spec_helper'
-require 'cgi'
+begin
+ require 'cgi/escape'
+rescue LoadError
+ require 'cgi'
+end
describe "CGI.unescapeHTML" do
it "unescapes '&amp; &lt; &gt; &quot;' to '& < > \"'" do
diff --git a/spec/ruby/library/cgi/unescapeURIComponent_spec.rb b/spec/ruby/library/cgi/unescapeURIComponent_spec.rb
new file mode 100644
index 0000000000..f80eb1626b
--- /dev/null
+++ b/spec/ruby/library/cgi/unescapeURIComponent_spec.rb
@@ -0,0 +1,128 @@
+require_relative '../../spec_helper'
+
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+end
+ruby_version_is "4.0" do
+ require 'cgi/escape'
+end
+
+describe "CGI.unescapeURIComponent" do
+ it "decodes any percent-encoded octets to their corresponding bytes according to RFC 3986" do
+ string = (0x00..0xff).map { |i| "%%%02x" % i }.join
+ expected = (0x00..0xff).map { |i| i.chr }.join.force_encoding(Encoding::UTF_8)
+ CGI.unescapeURIComponent(string).should == expected
+ end
+
+ it "disregards case of characters in a percent-encoding triplet" do
+ CGI.unescapeURIComponent("%CE%B2abc").should == "βabc"
+ CGI.unescapeURIComponent("%ce%b2ABC").should == "βABC"
+ end
+
+ it "leaves any non-percent-encoded characters as-is" do
+ string = "ABCDEFGHIJKLMNOPQRSTUVWXYZ:/?#[]@!$&'()*+,;=\t\x0D\xFFβᛉ▒90%"
+ decoded = CGI.unescapeURIComponent(string)
+ decoded.should == string
+ string.should_not.equal?(decoded)
+ end
+
+ it "leaves sequences which can't be a percent-encoded octet as-is" do
+ string = "%AZ%B"
+ decoded = CGI.unescapeURIComponent(string)
+ decoded.should == string
+ string.should_not.equal?(decoded)
+ end
+
+ it "creates a String with the specified target Encoding" do
+ string = CGI.unescapeURIComponent("%D2%3C%3CABC", Encoding::ISO_8859_1)
+ string.encoding.should == Encoding::ISO_8859_1
+ string.should == "Ò<<ABC".encode("ISO-8859-1")
+ end
+
+ it "accepts a string name of an Encoding" do
+ CGI.unescapeURIComponent("%D2%3C%3CABC", "ISO-8859-1").should == "Ò<<ABC".encode("ISO-8859-1")
+ end
+
+ it "raises ArgumentError if specified encoding is unknown" do
+ -> { CGI.unescapeURIComponent("ABC", "ISO-JOKE-1") }.should raise_error(ArgumentError, "unknown encoding name - ISO-JOKE-1")
+ end
+
+ ruby_version_is ""..."4.0" do
+ it "uses CGI.accept_charset as the default target encoding" do
+ original_charset = CGI.accept_charset
+ CGI.accept_charset = "ISO-8859-1"
+ decoded = CGI.unescapeURIComponent("%D2%3C%3CABC")
+ decoded.should == "Ò<<ABC".encode("ISO-8859-1")
+ decoded.encoding.should == Encoding::ISO_8859_1
+ ensure
+ CGI.accept_charset = original_charset
+ end
+
+ it "has CGI.accept_charset as UTF-8 by default" do
+ decoded = CGI.unescapeURIComponent("%CE%B2ABC")
+ decoded.should == "βABC"
+ decoded.encoding.should == Encoding::UTF_8
+ end
+ end
+
+ ruby_version_is "4.0" do
+ # "cgi/escape" does not have methods to access @@accept_charset.
+ # Full "cgi" gem provides them, allowing to possibly change it.
+ it "uses CGI's @@accept_charset as the default target encoding" do
+ original_charset = CGI.class_variable_get(:@@accept_charset)
+ CGI.class_variable_set(:@@accept_charset, "ISO-8859-1")
+ decoded = CGI.unescapeURIComponent("%D2%3C%3CABC")
+ decoded.should == "Ò<<ABC".encode("ISO-8859-1")
+ decoded.encoding.should == Encoding::ISO_8859_1
+ ensure
+ CGI.class_variable_set(:@@accept_charset, original_charset)
+ end
+
+ it "has CGI's @@accept_charset as UTF-8 by default" do
+ decoded = CGI.unescapeURIComponent("%CE%B2ABC")
+ decoded.should == "βABC"
+ decoded.encoding.should == Encoding::UTF_8
+ end
+ end
+
+ context "when source string specifies octets invalid in target encoding" do
+ it "uses source string's encoding" do
+ string = "%A2%A6%A3".encode(Encoding::SHIFT_JIS)
+ decoded = CGI.unescapeURIComponent(string, Encoding::US_ASCII)
+ decoded.encoding.should == Encoding::SHIFT_JIS
+ decoded.should == "「ヲ」".encode(Encoding::SHIFT_JIS)
+ decoded.valid_encoding?.should be_true
+ end
+
+ it "uses source string's encoding even if it's also invalid" do
+ string = "%FF".encode(Encoding::US_ASCII)
+ decoded = CGI.unescapeURIComponent(string, Encoding::SHIFT_JIS)
+ decoded.encoding.should == Encoding::US_ASCII
+ decoded.should == "\xFF".dup.force_encoding(Encoding::US_ASCII)
+ decoded.valid_encoding?.should be_false
+ end
+ end
+
+ it "decodes an empty string as an empty string with target encoding" do
+ string = "".encode(Encoding::BINARY)
+ decoded = CGI.unescapeURIComponent(string, "UTF-8")
+ decoded.should == ""
+ decoded.encoding.should == Encoding::UTF_8
+ string.should_not.equal?(decoded)
+ end
+
+ it "raises a TypeError with nil" do
+ -> {
+ CGI.unescapeURIComponent(nil)
+ }.should raise_error(TypeError, "no implicit conversion of nil into String")
+ end
+
+ it "uses implicit type conversion to String" do
+ object = Object.new
+ def object.to_str
+ "a%20b"
+ end
+
+ CGI.unescapeURIComponent(object).should == "a b"
+ end
+end
diff --git a/spec/ruby/library/cgi/unescape_spec.rb b/spec/ruby/library/cgi/unescape_spec.rb
index c593e24b4a..aa731b9367 100644
--- a/spec/ruby/library/cgi/unescape_spec.rb
+++ b/spec/ruby/library/cgi/unescape_spec.rb
@@ -1,6 +1,12 @@
# -*- encoding: utf-8 -*-
require_relative '../../spec_helper'
-require 'cgi'
+
+ruby_version_is ""..."4.0" do
+ require 'cgi'
+end
+ruby_version_is "4.0" do
+ require 'cgi/escape'
+end
describe "CGI.unescape" do
it "url-decodes the passed argument" do
diff --git a/spec/ruby/library/coverage/fixtures/code_with_begin.rb b/spec/ruby/library/coverage/fixtures/code_with_begin.rb
new file mode 100644
index 0000000000..9a6384e337
--- /dev/null
+++ b/spec/ruby/library/coverage/fixtures/code_with_begin.rb
@@ -0,0 +1,3 @@
+begin
+ 'coverage with begin'
+end
diff --git a/spec/ruby/library/coverage/result_spec.rb b/spec/ruby/library/coverage/result_spec.rb
index 33276778e8..0101eb6a64 100644
--- a/spec/ruby/library/coverage/result_spec.rb
+++ b/spec/ruby/library/coverage/result_spec.rb
@@ -6,6 +6,7 @@ describe 'Coverage.result' do
@class_file = fixture __FILE__, 'some_class.rb'
@config_file = fixture __FILE__, 'start_coverage.rb'
@eval_code_file = fixture __FILE__, 'eval_code.rb'
+ @with_begin_file = fixture __FILE__, 'code_with_begin.rb'
end
before :each do
@@ -16,6 +17,7 @@ describe 'Coverage.result' do
$LOADED_FEATURES.delete(@class_file)
$LOADED_FEATURES.delete(@config_file)
$LOADED_FEATURES.delete(@eval_code_file)
+ $LOADED_FEATURES.delete(@with_begin_file)
Coverage.result if Coverage.running?
end
@@ -32,39 +34,37 @@ describe 'Coverage.result' do
}
end
- ruby_version_is "3.2" do
- it 'returns results for each mode separately when enabled :all modes' do
- Coverage.start(:all)
- require @class_file.chomp('.rb')
- result = Coverage.result
+ it 'returns results for each mode separately when enabled :all modes' do
+ Coverage.start(:all)
+ require @class_file.chomp('.rb')
+ result = Coverage.result
+
+ result.should == {
+ @class_file => {
+ lines: [
+ nil, nil, 1, nil, nil, 1, nil, nil, 0, nil, nil, nil, nil, nil, nil, nil
+ ],
+ branches: {},
+ methods: {
+ [SomeClass, :some_method, 6, 2, 11, 5] => 0
+ }
+ }
+ }
+ end
+
+ it 'returns results for each mode separately when enabled any mode explicitly' do
+ Coverage.start(lines: true)
+ require @class_file.chomp('.rb')
+ result = Coverage.result
- result.should == {
- @class_file => {
+ result.should == {
+ @class_file =>
+ {
lines: [
nil, nil, 1, nil, nil, 1, nil, nil, 0, nil, nil, nil, nil, nil, nil, nil
- ],
- branches: {},
- methods: {
- [SomeClass, :some_method, 6, 2, 11, 5] => 0
- }
+ ]
}
- }
- end
-
- it 'returns results for each mode separately when enabled any mode explicitly' do
- Coverage.start(lines: true)
- require @class_file.chomp('.rb')
- result = Coverage.result
-
- result.should == {
- @class_file =>
- {
- lines: [
- nil, nil, 1, nil, nil, 1, nil, nil, 0, nil, nil, nil, nil, nil, nil, nil
- ]
- }
- }
- end
+ }
end
it 'no requires/loads should give empty hash' do
@@ -106,63 +106,37 @@ describe 'Coverage.result' do
result.should == {}
end
- 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] }
- 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
- ruby_version_is '3.1'...'3.2' do
- it 'returns the correct results when eval is used' do
- Coverage.start
- require @eval_code_file.chomp('.rb')
- result = Coverage.result
+ it 'returns the correct results when eval coverage is enabled' do
+ Coverage.supported?(:eval).should == true
- result.should == {
- @eval_code_file => [
- 1, nil, 1, nil, 1, nil, nil, nil, nil, nil, 1
- ]
- }
- end
- end
-
- ruby_version_is '3.2' do
- it 'returns the correct results when eval coverage is enabled' do
- Coverage.supported?(:eval).should == true
-
- Coverage.start(lines: true, eval: true)
- require @eval_code_file.chomp('.rb')
- result = Coverage.result
+ Coverage.start(lines: true, eval: true)
+ require @eval_code_file.chomp('.rb')
+ result = Coverage.result
- result.should == {
- @eval_code_file => {
- lines: [1, nil, 1, nil, 1, 1, nil, nil, nil, nil, 1]
- }
+ result.should == {
+ @eval_code_file => {
+ lines: [1, nil, 1, nil, 1, 1, nil, nil, nil, nil, 1]
}
- end
+ }
+ end
- it 'returns the correct results when eval coverage is disabled' do
- Coverage.supported?(:eval).should == true
+ it 'returns the correct results when eval coverage is disabled' do
+ Coverage.supported?(:eval).should == true
- Coverage.start(lines: true, eval: false)
- require @eval_code_file.chomp('.rb')
- result = Coverage.result
+ Coverage.start(lines: true, eval: false)
+ require @eval_code_file.chomp('.rb')
+ result = Coverage.result
- result.should == {
- @eval_code_file => {
- lines: [1, nil, 1, nil, 1, nil, nil, nil, nil, nil, 1]
- }
+ result.should == {
+ @eval_code_file => {
+ lines: [1, nil, 1, nil, 1, nil, nil, nil, nil, nil, 1]
}
- end
+ }
end
it "disables coverage measurement when stop option is not specified" do
@@ -354,4 +328,16 @@ describe 'Coverage.result' do
Coverage.peek_result.should == result
end
+
+ it 'covers 100% lines with begin' do
+ Coverage.start
+ require @with_begin_file.chomp('.rb')
+ result = Coverage.result
+
+ result.should == {
+ @with_begin_file => [
+ nil, 1, nil
+ ]
+ }
+ end
end
diff --git a/spec/ruby/library/coverage/start_spec.rb b/spec/ruby/library/coverage/start_spec.rb
index 7fccf2d5cf..c921b85401 100644
--- a/spec/ruby/library/coverage/start_spec.rb
+++ b/spec/ruby/library/coverage/start_spec.rb
@@ -19,73 +19,69 @@ describe 'Coverage.start' do
Coverage.start.should == nil
end
- ruby_version_is '3.1' do
- it 'raises error when repeated Coverage.start call happens' do
+ it 'raises error when repeated Coverage.start call happens' do
+ Coverage.start
+
+ -> {
Coverage.start
+ }.should raise_error(RuntimeError, 'coverage measurement is already setup')
+ end
+
+ it "accepts :all optional argument" do
+ Coverage.start(:all)
+ Coverage.should.running?
+ end
+
+ it "accepts lines: optional keyword argument" do
+ Coverage.start(lines: true)
+ Coverage.should.running?
+ end
+
+ it "accepts branches: optional keyword argument" do
+ Coverage.start(branches: true)
+ Coverage.should.running?
+ end
+
+ it "accepts methods: optional keyword argument" do
+ Coverage.start(methods: true)
+ Coverage.should.running?
+ end
+
+ it "accepts eval: optional keyword argument" do
+ Coverage.start(eval: true)
+ Coverage.should.running?
+ end
+
+ it "accepts oneshot_lines: optional keyword argument" do
+ Coverage.start(oneshot_lines: true)
+ Coverage.should.running?
+ end
+
+ it "ignores unknown keyword arguments" do
+ Coverage.start(foo: true)
+ Coverage.should.running?
+ end
+
+ it "expects a Hash if not passed :all" do
+ -> {
+ Coverage.start(42)
+ }.should raise_error(TypeError, "no implicit conversion of Integer into Hash")
+ end
+
+ it "does not accept both lines: and oneshot_lines: keyword arguments" do
+ -> {
+ Coverage.start(lines: true, oneshot_lines: true)
+ }.should raise_error(RuntimeError, "cannot enable lines and oneshot_lines simultaneously")
+ end
+
+ it "enables the coverage measurement if passed options with `false` value" do
+ Coverage.start(lines: false, branches: false, methods: false, eval: false, oneshot_lines: false)
+ Coverage.should.running?
+ end
- -> {
- Coverage.start
- }.should raise_error(RuntimeError, 'coverage measurement is already setup')
- end
- end
-
- ruby_version_is '3.2' do
- it "accepts :all optional argument" do
- Coverage.start(:all)
- Coverage.should.running?
- end
-
- it "accepts lines: optional keyword argument" do
- Coverage.start(lines: true)
- Coverage.should.running?
- end
-
- it "accepts branches: optional keyword argument" do
- Coverage.start(branches: true)
- Coverage.should.running?
- end
-
- it "accepts methods: optional keyword argument" do
- Coverage.start(methods: true)
- Coverage.should.running?
- end
-
- it "accepts eval: optional keyword argument" do
- Coverage.start(eval: true)
- Coverage.should.running?
- end
-
- it "accepts oneshot_lines: optional keyword argument" do
- Coverage.start(oneshot_lines: true)
- Coverage.should.running?
- end
-
- it "ignores unknown keyword arguments" do
- Coverage.start(foo: true)
- Coverage.should.running?
- end
-
- it "expects a Hash if not passed :all" do
- -> {
- Coverage.start(42)
- }.should raise_error(TypeError, "no implicit conversion of Integer into Hash")
- end
-
- it "does not accept both lines: and oneshot_lines: keyword arguments" do
- -> {
- Coverage.start(lines: true, oneshot_lines: true)
- }.should raise_error(RuntimeError, "cannot enable lines and oneshot_lines simultaneously")
- end
-
- it "enables the coverage measurement if passed options with `false` value" do
- Coverage.start(lines: false, branches: false, methods: false, eval: false, oneshot_lines: false)
- Coverage.should.running?
- end
-
- it "measures coverage within eval" do
- Coverage.start(lines: true, eval: true)
- eval("Object.new\n"*3, binding, "test.rb", 1)
- Coverage.result["test.rb"].should == {lines: [1, 1, 1]}
- end
+ it "measures coverage within eval" do
+ Coverage.start(lines: true, eval: true)
+ eval("Object.new\n"*3, binding, "test.rb", 1)
+ Coverage.result["test.rb"].should == {lines: [1, 1, 1]}
end
end
diff --git a/spec/ruby/library/coverage/supported_spec.rb b/spec/ruby/library/coverage/supported_spec.rb
index 78b3784ee0..9226548c1f 100644
--- a/spec/ruby/library/coverage/supported_spec.rb
+++ b/spec/ruby/library/coverage/supported_spec.rb
@@ -2,31 +2,29 @@ require_relative '../../spec_helper'
require 'coverage'
describe "Coverage.supported?" do
- ruby_version_is "3.2" do
- it "returns true or false if coverage measurement is supported for the given mode" do
- [true, false].should.include?(Coverage.supported?(:lines))
- [true, false].should.include?(Coverage.supported?(:branches))
- [true, false].should.include?(Coverage.supported?(:methods))
- [true, false].should.include?(Coverage.supported?(:eval))
- end
+ it "returns true or false if coverage measurement is supported for the given mode" do
+ [true, false].should.include?(Coverage.supported?(:lines))
+ [true, false].should.include?(Coverage.supported?(:branches))
+ [true, false].should.include?(Coverage.supported?(:methods))
+ [true, false].should.include?(Coverage.supported?(:eval))
+ end
- it "returns false for not existing modes" do
- Coverage.supported?(:foo).should == false
- Coverage.supported?(:bar).should == false
- end
+ it "returns false for not existing modes" do
+ Coverage.supported?(:foo).should == false
+ Coverage.supported?(:bar).should == false
+ end
- it "raise TypeError if argument is not Symbol" do
- -> {
- Coverage.supported?("lines")
- }.should raise_error(TypeError, "wrong argument type String (expected Symbol)")
+ it "raise TypeError if argument is not Symbol" do
+ -> {
+ Coverage.supported?("lines")
+ }.should raise_error(TypeError, "wrong argument type String (expected Symbol)")
- -> {
- Coverage.supported?([])
- }.should raise_error(TypeError, "wrong argument type Array (expected Symbol)")
+ -> {
+ Coverage.supported?([])
+ }.should raise_error(TypeError, "wrong argument type Array (expected Symbol)")
- -> {
- Coverage.supported?(1)
- }.should raise_error(TypeError, "wrong argument type Integer (expected Symbol)")
- end
+ -> {
+ Coverage.supported?(1)
+ }.should raise_error(TypeError, "wrong argument type Integer (expected Symbol)")
end
end
diff --git a/spec/ruby/library/date/accessor_spec.rb b/spec/ruby/library/date/accessor_spec.rb
index 68a2d9f3de..74ed0e9c21 100644
--- a/spec/ruby/library/date/accessor_spec.rb
+++ b/spec/ruby/library/date/accessor_spec.rb
@@ -38,7 +38,7 @@ describe "Date#year" do
end
describe "Date#yday" do
- it "determines the year" do
+ it "determines the day of the year" do
Date.civil(2007, 1, 17).yday.should == 17
Date.civil(2008, 10, 28).yday.should == 302
end
diff --git a/spec/ruby/library/date/deconstruct_keys_spec.rb b/spec/ruby/library/date/deconstruct_keys_spec.rb
index 92579e35c7..b9dd6b8816 100644
--- a/spec/ruby/library/date/deconstruct_keys_spec.rb
+++ b/spec/ruby/library/date/deconstruct_keys_spec.rb
@@ -2,43 +2,41 @@ require_relative '../../spec_helper'
require 'date'
date_version = defined?(Date::VERSION) ? Date::VERSION : '3.1.0'
-version_is date_version, "3.3" do #ruby_version_is "3.2" do
- describe "Date#deconstruct_keys" do
- it "returns whole hash for nil as an argument" do
- d = Date.new(2022, 10, 5)
- d.deconstruct_keys(nil).should == { year: 2022, month: 10, day: 5, yday: 278, wday: 3 }
- end
-
- it "returns only specified keys" do
- d = Date.new(2022, 10, 5)
- d.deconstruct_keys([:year, :month]).should == { year: 2022, month: 10 }
- end
-
- it "requires one argument" do
- -> {
- Date.new(2022, 10, 5).deconstruct_keys
- }.should raise_error(ArgumentError)
- end
-
- it "it raises error when argument is neither nil nor array" do
- d = Date.new(2022, 10, 5)
-
- -> { d.deconstruct_keys(1) }.should raise_error(TypeError, "wrong argument type Integer (expected Array or nil)")
- -> { d.deconstruct_keys("asd") }.should raise_error(TypeError, "wrong argument type String (expected Array or nil)")
- -> { d.deconstruct_keys(:x) }.should raise_error(TypeError, "wrong argument type Symbol (expected Array or nil)")
- -> { d.deconstruct_keys({}) }.should raise_error(TypeError, "wrong argument type Hash (expected Array or nil)")
- end
-
- it "returns {} when passed []" do
- Date.new(2022, 10, 5).deconstruct_keys([]).should == {}
- end
-
- it "ignores non-Symbol keys" do
- Date.new(2022, 10, 5).deconstruct_keys(['year', []]).should == {}
- end
-
- it "ignores not existing Symbol keys" do
- Date.new(2022, 10, 5).deconstruct_keys([:year, :a]).should == { year: 2022 }
- end
+describe "Date#deconstruct_keys" do
+ it "returns whole hash for nil as an argument" do
+ d = Date.new(2022, 10, 5)
+ d.deconstruct_keys(nil).should == { year: 2022, month: 10, day: 5, yday: 278, wday: 3 }
+ end
+
+ it "returns only specified keys" do
+ d = Date.new(2022, 10, 5)
+ d.deconstruct_keys([:year, :month]).should == { year: 2022, month: 10 }
+ end
+
+ it "requires one argument" do
+ -> {
+ Date.new(2022, 10, 5).deconstruct_keys
+ }.should raise_error(ArgumentError)
+ end
+
+ it "it raises error when argument is neither nil nor array" do
+ d = Date.new(2022, 10, 5)
+
+ -> { d.deconstruct_keys(1) }.should raise_error(TypeError, "wrong argument type Integer (expected Array or nil)")
+ -> { d.deconstruct_keys("asd") }.should raise_error(TypeError, "wrong argument type String (expected Array or nil)")
+ -> { d.deconstruct_keys(:x) }.should raise_error(TypeError, "wrong argument type Symbol (expected Array or nil)")
+ -> { d.deconstruct_keys({}) }.should raise_error(TypeError, "wrong argument type Hash (expected Array or nil)")
+ end
+
+ it "returns {} when passed []" do
+ Date.new(2022, 10, 5).deconstruct_keys([]).should == {}
+ end
+
+ it "ignores non-Symbol keys" do
+ Date.new(2022, 10, 5).deconstruct_keys(['year', []]).should == {}
+ end
+
+ it "ignores not existing Symbol keys" do
+ Date.new(2022, 10, 5).deconstruct_keys([:year, :a]).should == { year: 2022 }
end
end
diff --git a/spec/ruby/library/date/mon_spec.rb b/spec/ruby/library/date/mon_spec.rb
index 724e7d6564..616d72cf88 100644
--- a/spec/ruby/library/date/mon_spec.rb
+++ b/spec/ruby/library/date/mon_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
+require_relative 'shared/month'
require 'date'
describe "Date#mon" do
- it "needs to be reviewed for spec completeness"
+ it_behaves_like :date_month, :mon
end
diff --git a/spec/ruby/library/date/month_spec.rb b/spec/ruby/library/date/month_spec.rb
index e040f9a94c..f493ec8119 100644
--- a/spec/ruby/library/date/month_spec.rb
+++ b/spec/ruby/library/date/month_spec.rb
@@ -1,9 +1,7 @@
require_relative '../../spec_helper'
+require_relative 'shared/month'
require 'date'
describe "Date#month" do
- it "returns the month" do
- m = Date.new(2000, 7, 1).month
- m.should == 7
- end
+ it_behaves_like :date_month, :month
end
diff --git a/spec/ruby/library/date/shared/month.rb b/spec/ruby/library/date/shared/month.rb
new file mode 100644
index 0000000000..5fcb2cbeb0
--- /dev/null
+++ b/spec/ruby/library/date/shared/month.rb
@@ -0,0 +1,6 @@
+describe :date_month, shared: true do
+ it "returns the month" do
+ m = Date.new(2000, 7, 1).send(@method)
+ m.should == 7
+ end
+end
diff --git a/spec/ruby/library/date/strftime_spec.rb b/spec/ruby/library/date/strftime_spec.rb
index b5232a2073..1b93a8d1b2 100644
--- a/spec/ruby/library/date/strftime_spec.rb
+++ b/spec/ruby/library/date/strftime_spec.rb
@@ -23,19 +23,9 @@ describe "Date#strftime" do
@date.strftime("%Z").should == "+00:00"
end
- # %v is %e-%b-%Y for Date/DateTime
- version_is date_version, ""..."3.2" do #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
-
- version_is date_version, "3.2" do #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
+ 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
# additional conversion specifiers only in Date/DateTime
diff --git a/spec/ruby/library/date/yday_spec.rb b/spec/ruby/library/date/yday_spec.rb
index cfb174a4c2..7dd42e52a5 100644
--- a/spec/ruby/library/date/yday_spec.rb
+++ b/spec/ruby/library/date/yday_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
+require_relative '../../shared/time/yday'
require 'date'
describe "Date#yday" do
- it "needs to be reviewed for spec completeness"
+ it_behaves_like :time_yday, -> year, month, day { Date.new(year, month, day).yday }
end
diff --git a/spec/ruby/library/datetime/deconstruct_keys_spec.rb b/spec/ruby/library/datetime/deconstruct_keys_spec.rb
index 77ceaa51c4..154c024a23 100644
--- a/spec/ruby/library/datetime/deconstruct_keys_spec.rb
+++ b/spec/ruby/library/datetime/deconstruct_keys_spec.rb
@@ -2,45 +2,43 @@ require_relative '../../spec_helper'
require 'date'
date_version = defined?(Date::VERSION) ? Date::VERSION : '3.1.0'
-version_is date_version, "3.3" do #ruby_version_is "3.2" do
- describe "DateTime#deconstruct_keys" do
- it "returns whole hash for nil as an argument" do
- d = DateTime.new(2022, 10, 5, 13, 30)
- res = { year: 2022, month: 10, day: 5, yday: 278, wday: 3, hour: 13,
- min: 30, sec: 0, sec_fraction: (0/1), zone: "+00:00" }
- d.deconstruct_keys(nil).should == res
- end
-
- it "returns only specified keys" do
- d = DateTime.new(2022, 10, 5, 13, 39)
- d.deconstruct_keys([:zone, :hour]).should == { zone: "+00:00", hour: 13 }
- end
-
- it "requires one argument" do
- -> {
- DateTime.new(2022, 10, 5, 13, 30).deconstruct_keys
- }.should raise_error(ArgumentError)
- end
-
- it "it raises error when argument is neither nil nor array" do
- d = DateTime.new(2022, 10, 5, 13, 30)
-
- -> { d.deconstruct_keys(1) }.should raise_error(TypeError, "wrong argument type Integer (expected Array or nil)")
- -> { d.deconstruct_keys("asd") }.should raise_error(TypeError, "wrong argument type String (expected Array or nil)")
- -> { d.deconstruct_keys(:x) }.should raise_error(TypeError, "wrong argument type Symbol (expected Array or nil)")
- -> { d.deconstruct_keys({}) }.should raise_error(TypeError, "wrong argument type Hash (expected Array or nil)")
- end
-
- it "returns {} when passed []" do
- DateTime.new(2022, 10, 5, 13, 30).deconstruct_keys([]).should == {}
- end
-
- it "ignores non-Symbol keys" do
- DateTime.new(2022, 10, 5, 13, 30).deconstruct_keys(['year', []]).should == {}
- end
-
- it "ignores not existing Symbol keys" do
- DateTime.new(2022, 10, 5, 13, 30).deconstruct_keys([:year, :a]).should == { year: 2022 }
- end
+describe "DateTime#deconstruct_keys" do
+ it "returns whole hash for nil as an argument" do
+ d = DateTime.new(2022, 10, 5, 13, 30)
+ res = { year: 2022, month: 10, day: 5, yday: 278, wday: 3, hour: 13,
+ min: 30, sec: 0, sec_fraction: (0/1), zone: "+00:00" }
+ d.deconstruct_keys(nil).should == res
+ end
+
+ it "returns only specified keys" do
+ d = DateTime.new(2022, 10, 5, 13, 39)
+ d.deconstruct_keys([:zone, :hour]).should == { zone: "+00:00", hour: 13 }
+ end
+
+ it "requires one argument" do
+ -> {
+ DateTime.new(2022, 10, 5, 13, 30).deconstruct_keys
+ }.should raise_error(ArgumentError)
+ end
+
+ it "it raises error when argument is neither nil nor array" do
+ d = DateTime.new(2022, 10, 5, 13, 30)
+
+ -> { d.deconstruct_keys(1) }.should raise_error(TypeError, "wrong argument type Integer (expected Array or nil)")
+ -> { d.deconstruct_keys("asd") }.should raise_error(TypeError, "wrong argument type String (expected Array or nil)")
+ -> { d.deconstruct_keys(:x) }.should raise_error(TypeError, "wrong argument type Symbol (expected Array or nil)")
+ -> { d.deconstruct_keys({}) }.should raise_error(TypeError, "wrong argument type Hash (expected Array or nil)")
+ end
+
+ it "returns {} when passed []" do
+ DateTime.new(2022, 10, 5, 13, 30).deconstruct_keys([]).should == {}
+ end
+
+ it "ignores non-Symbol keys" do
+ DateTime.new(2022, 10, 5, 13, 30).deconstruct_keys(['year', []]).should == {}
+ end
+
+ it "ignores not existing Symbol keys" do
+ DateTime.new(2022, 10, 5, 13, 30).deconstruct_keys([:year, :a]).should == { year: 2022 }
end
end
diff --git a/spec/ruby/library/datetime/strftime_spec.rb b/spec/ruby/library/datetime/strftime_spec.rb
index abb0838e8e..a07cc9c1aa 100644
--- a/spec/ruby/library/datetime/strftime_spec.rb
+++ b/spec/ruby/library/datetime/strftime_spec.rb
@@ -33,19 +33,9 @@ describe "DateTime#strftime" do
@time.strftime("%Z").should == "+00:00"
end
- # %v is %e-%b-%Y for Date/DateTime
- version_is date_version, ""..."3.2" do #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
-
- version_is date_version, "3.2" do #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
+ 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
# additional conversion specifiers only in Date/DateTime
diff --git a/spec/ruby/library/datetime/time/to_datetime_spec.rb b/spec/ruby/library/datetime/time/to_datetime_spec.rb
index 1125dbe851..5589725238 100644
--- a/spec/ruby/library/datetime/time/to_datetime_spec.rb
+++ b/spec/ruby/library/datetime/time/to_datetime_spec.rb
@@ -15,17 +15,15 @@ describe "Time#to_datetime" do
datetime.sec.should == 59
end
- version_is date_version, '3.2.3' do #ruby_version_is '3.2' do
- it "returns a DateTime representing the same instant before Gregorian" do
- time = Time.utc(1582, 10, 14, 23, 58, 59)
- datetime = time.to_datetime
- datetime.year.should == 1582
- datetime.month.should == 10
- datetime.day.should == 4
- datetime.hour.should == 23
- datetime.min.should == 58
- datetime.sec.should == 59
- end
+ it "returns a DateTime representing the same instant before Gregorian" do
+ time = Time.utc(1582, 10, 14, 23, 58, 59)
+ datetime = time.to_datetime
+ datetime.year.should == 1582
+ datetime.month.should == 10
+ datetime.day.should == 4
+ datetime.hour.should == 23
+ datetime.min.should == 58
+ datetime.sec.should == 59
end
it "roundtrips" do
diff --git a/spec/ruby/library/datetime/to_time_spec.rb b/spec/ruby/library/datetime/to_time_spec.rb
index 09e6192e7f..58bb363653 100644
--- a/spec/ruby/library/datetime/to_time_spec.rb
+++ b/spec/ruby/library/datetime/to_time_spec.rb
@@ -19,17 +19,15 @@ describe "DateTime#to_time" do
time.sec.should == 59
end
- version_is date_version, '3.2.3' do #ruby_version_is "3.2" do
- it "returns a Time representing the same instant before Gregorian" do
- datetime = DateTime.civil(1582, 10, 4, 23, 58, 59)
- time = datetime.to_time.utc
- time.year.should == 1582
- time.month.should == 10
- time.day.should == 14
- time.hour.should == 23
- time.min.should == 58
- time.sec.should == 59
- end
+ it "returns a Time representing the same instant before Gregorian" do
+ datetime = DateTime.civil(1582, 10, 4, 23, 58, 59)
+ time = datetime.to_time.utc
+ time.year.should == 1582
+ time.month.should == 10
+ time.day.should == 14
+ time.hour.should == 23
+ time.min.should == 58
+ time.sec.should == 59
end
it "preserves the same time regardless of local time or zone" do
diff --git a/spec/ruby/library/datetime/yday_spec.rb b/spec/ruby/library/datetime/yday_spec.rb
new file mode 100644
index 0000000000..08a72c6480
--- /dev/null
+++ b/spec/ruby/library/datetime/yday_spec.rb
@@ -0,0 +1,7 @@
+require_relative '../../spec_helper'
+require_relative '../../shared/time/yday'
+require 'date'
+
+describe "DateTime#yday" do
+ it_behaves_like :time_yday, -> year, month, day { DateTime.new(year, month, day).yday }
+end
diff --git a/spec/ruby/library/digest/md5/append_spec.rb b/spec/ruby/library/digest/md5/append_spec.rb
index a7f841c883..0abdc074a1 100644
--- a/spec/ruby/library/digest/md5/append_spec.rb
+++ b/spec/ruby/library/digest/md5/append_spec.rb
@@ -3,5 +3,5 @@ require_relative 'shared/constants'
require_relative 'shared/update'
describe "Digest::MD5#<<" do
- it_behaves_like :md5_update, :<<
+ it_behaves_like :md5_update, :<<
end
diff --git a/spec/ruby/library/digest/md5/shared/constants.rb b/spec/ruby/library/digest/md5/shared/constants.rb
index e807b96f9f..664dd18e9c 100644
--- a/spec/ruby/library/digest/md5/shared/constants.rb
+++ b/spec/ruby/library/digest/md5/shared/constants.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require 'digest/md5'
module MD5Constants
diff --git a/spec/ruby/library/digest/sha1/shared/constants.rb b/spec/ruby/library/digest/sha1/shared/constants.rb
index 169438747f..d77c05a968 100644
--- a/spec/ruby/library/digest/sha1/shared/constants.rb
+++ b/spec/ruby/library/digest/sha1/shared/constants.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require 'digest/sha1'
diff --git a/spec/ruby/library/digest/sha256/append_spec.rb b/spec/ruby/library/digest/sha256/append_spec.rb
index 9ca3496afc..ab594c105f 100644
--- a/spec/ruby/library/digest/sha256/append_spec.rb
+++ b/spec/ruby/library/digest/sha256/append_spec.rb
@@ -3,5 +3,5 @@ require_relative 'shared/constants'
require_relative 'shared/update'
describe "Digest::SHA256#<<" do
- it_behaves_like :sha256_update, :<<
+ it_behaves_like :sha256_update, :<<
end
diff --git a/spec/ruby/library/digest/sha256/shared/constants.rb b/spec/ruby/library/digest/sha256/shared/constants.rb
index 351679f344..afe8f11426 100644
--- a/spec/ruby/library/digest/sha256/shared/constants.rb
+++ b/spec/ruby/library/digest/sha256/shared/constants.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require 'digest/sha2'
diff --git a/spec/ruby/library/digest/sha384/append_spec.rb b/spec/ruby/library/digest/sha384/append_spec.rb
index 2bc0c5b90b..94c036cc3f 100644
--- a/spec/ruby/library/digest/sha384/append_spec.rb
+++ b/spec/ruby/library/digest/sha384/append_spec.rb
@@ -3,5 +3,5 @@ require_relative 'shared/constants'
require_relative 'shared/update'
describe "Digest::SHA384#<<" do
- it_behaves_like :sha384_update, :<<
+ it_behaves_like :sha384_update, :<<
end
diff --git a/spec/ruby/library/digest/sha384/shared/constants.rb b/spec/ruby/library/digest/sha384/shared/constants.rb
index 2050f03f2b..a78d571d26 100644
--- a/spec/ruby/library/digest/sha384/shared/constants.rb
+++ b/spec/ruby/library/digest/sha384/shared/constants.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require 'digest/sha2'
diff --git a/spec/ruby/library/digest/sha512/append_spec.rb b/spec/ruby/library/digest/sha512/append_spec.rb
index e5f84b56f4..9106e9685d 100644
--- a/spec/ruby/library/digest/sha512/append_spec.rb
+++ b/spec/ruby/library/digest/sha512/append_spec.rb
@@ -3,5 +3,5 @@ require_relative 'shared/constants'
require_relative 'shared/update'
describe "Digest::SHA512#<<" do
- it_behaves_like :sha512_update, :<<
+ it_behaves_like :sha512_update, :<<
end
diff --git a/spec/ruby/library/digest/sha512/shared/constants.rb b/spec/ruby/library/digest/sha512/shared/constants.rb
index 2765a1ec16..91787381ee 100644
--- a/spec/ruby/library/digest/sha512/shared/constants.rb
+++ b/spec/ruby/library/digest/sha512/shared/constants.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require 'digest/sha2'
diff --git a/spec/ruby/library/erb/def_class_spec.rb b/spec/ruby/library/erb/def_class_spec.rb
index 88bd385f4c..fb687531e0 100644
--- a/spec/ruby/library/erb/def_class_spec.rb
+++ b/spec/ruby/library/erb/def_class_spec.rb
@@ -24,6 +24,8 @@ END
MyClass1ForErb = erb.def_class(MyClass1ForErb_, 'render()')
MyClass1ForErb.method_defined?(:render).should == true
MyClass1ForErb.new('foo', 123).render().should == expected
+ ensure
+ Object.send(:remove_const, :MyClass1ForErb)
end
end
diff --git a/spec/ruby/library/erb/def_module_spec.rb b/spec/ruby/library/erb/def_module_spec.rb
index 806e564ef0..5f67aeb2b9 100644
--- a/spec/ruby/library/erb/def_module_spec.rb
+++ b/spec/ruby/library/erb/def_module_spec.rb
@@ -22,6 +22,9 @@ END
include MyModule2ForErb
end
MyClass2ForErb.new.render('foo', 123).should == expected
+ ensure
+ Object.send(:remove_const, :MyClass2ForErb)
+ Object.send(:remove_const, :MyModule2ForErb)
end
end
diff --git a/spec/ruby/library/erb/defmethod/def_erb_method_spec.rb b/spec/ruby/library/erb/defmethod/def_erb_method_spec.rb
index dc1e044d9c..1cd7582936 100644
--- a/spec/ruby/library/erb/defmethod/def_erb_method_spec.rb
+++ b/spec/ruby/library/erb/defmethod/def_erb_method_spec.rb
@@ -58,6 +58,8 @@ END
end
end
MyClass4ForErb.new([10,20,30]).render().should == expected
+ ensure
+ Object.send(:remove_const, :MY_INPUT4_FOR_ERB)
end
diff --git a/spec/ruby/library/erb/new_spec.rb b/spec/ruby/library/erb/new_spec.rb
index a5aeeaeed1..f8192bff99 100644
--- a/spec/ruby/library/erb/new_spec.rb
+++ b/spec/ruby/library/erb/new_spec.rb
@@ -130,7 +130,7 @@ END
<b><%#= item %></b>
<%# end %>
END
- ERBSpecs.new_erb(input).result.should == "\n<b></b>\n\n"
+ ERBSpecs.new_erb(input).result.should == "\n<b></b>\n\n"
ERBSpecs.new_erb(input, trim_mode: '<>').result.should == "<b></b>\n"
end
@@ -139,8 +139,8 @@ END
->{ ERB.new("<%= list %>").result }.should raise_error(NameError)
end
- describe "warning about arguments" do
- version_is ERB.version, "2.2.1" do #ruby_version_is "3.1" do
+ version_is ERB.const_get(:VERSION, false), ""..."6.0.0" do
+ describe "warning about arguments" do
it "warns when passed safe_level and later arguments" do
-> {
ERB.new(@eruby_str, nil, '%')
diff --git a/spec/ruby/library/fiber/alive_spec.rb b/spec/ruby/library/fiber/alive_spec.rb
deleted file mode 100644
index 47149d5279..0000000000
--- a/spec/ruby/library/fiber/alive_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-require_relative '../../spec_helper'
-
-require 'fiber'
-
-describe "Fiber#alive?" do
- it "returns true for a Fiber that hasn't had #resume called" do
- fiber = Fiber.new { true }
- fiber.alive?.should be_true
- end
-
- # FIXME: Better description?
- it "returns true for a Fiber that's yielded to the caller" do
- fiber = Fiber.new { Fiber.yield }
- fiber.resume
- fiber.alive?.should be_true
- end
-
- it "returns true when called from its Fiber" do
- fiber = Fiber.new { fiber.alive?.should be_true }
- fiber.resume
- end
-
- it "doesn't invoke the block associated with the Fiber" do
- offthehook = mock('do not call')
- offthehook.should_not_receive(:ring)
- fiber = Fiber.new { offthehook.ring }
- fiber.alive?
- end
-
- it "returns false for a Fiber that's dead" do
- fiber = Fiber.new { true }
- fiber.resume
- -> { fiber.resume }.should raise_error(FiberError)
- fiber.alive?.should be_false
- end
-
- it "always returns false for a dead Fiber" do
- fiber = Fiber.new { true }
- fiber.resume
- -> { fiber.resume }.should raise_error(FiberError)
- fiber.alive?.should be_false
- -> { fiber.resume }.should raise_error(FiberError)
- fiber.alive?.should be_false
- fiber.alive?.should be_false
- end
-end
diff --git a/spec/ruby/library/fiber/current_spec.rb b/spec/ruby/library/fiber/current_spec.rb
deleted file mode 100644
index 1467a88d0d..0000000000
--- a/spec/ruby/library/fiber/current_spec.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-require_relative '../../spec_helper'
-
-require 'fiber'
-
-describe "Fiber.current" do
- ruby_version_is "3.1" do
- it "is available without an extra require" do
- ruby_exe("print Fiber.current.class", options: '--disable-gems --disable-did-you-mean').should == "Fiber"
- end
- end
-
- it "returns the root Fiber when called outside of a Fiber" do
- root = Fiber.current
- root.should be_an_instance_of(Fiber)
- # We can always transfer to the root Fiber; it will never die
- 5.times do
- root.transfer.should be_nil
- root.alive?.should be_true
- end
- end
-
- it "returns the current Fiber when called from a Fiber" do
- fiber = Fiber.new do
- this = Fiber.current
- this.should be_an_instance_of(Fiber)
- this.should == fiber
- this.alive?.should be_true
- end
- fiber.resume
- end
-
- it "returns the current Fiber when called from a Fiber that transferred to another" do
- states = []
- fiber = Fiber.new do
- states << :fiber
- this = Fiber.current
- this.should be_an_instance_of(Fiber)
- this.should == fiber
- this.alive?.should be_true
- end
-
- fiber2 = Fiber.new do
- states << :fiber2
- fiber.transfer
- flunk
- end
-
- fiber3 = Fiber.new do
- states << :fiber3
- fiber2.transfer
- states << :fiber3_terminated
- end
-
- fiber3.resume
-
- states.should == [:fiber3, :fiber2, :fiber, :fiber3_terminated]
- end
-end
diff --git a/spec/ruby/library/fiber/resume_spec.rb b/spec/ruby/library/fiber/resume_spec.rb
deleted file mode 100644
index fd69d3ba99..0000000000
--- a/spec/ruby/library/fiber/resume_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require_relative '../../spec_helper'
-
-require 'fiber'
-
-describe "Fiber#resume" 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
diff --git a/spec/ruby/library/fiber/transfer_spec.rb b/spec/ruby/library/fiber/transfer_spec.rb
deleted file mode 100644
index e20d51352e..0000000000
--- a/spec/ruby/library/fiber/transfer_spec.rb
+++ /dev/null
@@ -1,86 +0,0 @@
-require_relative '../../spec_helper'
-require_relative '../../shared/fiber/resume'
-
-require 'fiber'
-
-describe "Fiber#transfer" do
- it_behaves_like :fiber_resume, :transfer
-end
-
-describe "Fiber#transfer" do
- 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 == :fiber2
- end
-
- it "returns to the root Fiber when finished" do
- f1 = Fiber.new { :fiber_1 }
- f2 = Fiber.new { f1.transfer; :fiber_2 }
-
- f2.transfer.should == :fiber_1
- f2.transfer.should == :fiber_2
- end
-
- it "can be invoked from the same Fiber it transfers control to" do
- states = []
- fiber = Fiber.new { states << :start; fiber.transfer; states << :end }
- fiber.transfer
- states.should == [:start, :end]
-
- states = []
- fiber = Fiber.new { states << :start; fiber.transfer; states << :end }
- fiber.resume
- states.should == [:start, :end]
- end
-
- 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
-
- it "raises a FiberError when transferring to a Fiber which resumes itself" do
- fiber = Fiber.new { fiber.resume }
- -> { fiber.transfer }.should raise_error(FiberError)
- end
-
- it "works if Fibers in different Threads each transfer to a Fiber in the same Thread" do
- # This catches a bug where Fibers are running on a thread-pool
- # and Fibers from a different Ruby Thread reuse the same native thread.
- # Caching the Ruby Thread based on the native thread is not correct in that case,
- # and the check for "fiber called across threads" in Fiber#transfer
- # might be incorrect based on that.
- 2.times do
- Thread.new do
- io_fiber = Fiber.new do |calling_fiber|
- calling_fiber.transfer
- end
- io_fiber.transfer(Fiber.current)
- value = Object.new
- io_fiber.transfer(value).should equal value
- end.join
- end
- end
-
- it "transfers control between a non-main thread's root fiber to a child fiber and back again" do
- states = []
- thread = Thread.new do
- f1 = Fiber.new do |f0|
- states << 0
- value2 = f0.transfer(1)
- states << value2
- 3
- end
-
- value1 = f1.transfer(Fiber.current)
- states << value1
- value3 = f1.transfer(2)
- states << value3
- end
- thread.join
- states.should == [0, 1, 2, 3]
- end
-end
diff --git a/spec/ruby/library/find/fixtures/common.rb b/spec/ruby/library/find/fixtures/common.rb
index 14a7edb09a..99f3bbb45a 100644
--- a/spec/ruby/library/find/fixtures/common.rb
+++ b/spec/ruby/library/find/fixtures/common.rb
@@ -71,13 +71,17 @@ module FindDirSpecs
end
def self.create_mock_dirs
+ tmp('') # make sure there is an tmpdir
umask = File.umask 0
- mock_dir_files.each do |name|
- file = File.join mock_dir, name
- mkdir_p File.dirname(file)
- touch file
+ begin
+ mock_dir_files.each do |name|
+ file = File.join mock_dir, name
+ mkdir_p File.dirname(file)
+ touch file
+ end
+ ensure
+ File.umask umask
end
- File.umask umask
end
def self.delete_mock_dirs
diff --git a/spec/ruby/library/io-wait/fixtures/classes.rb b/spec/ruby/library/io-wait/fixtures/classes.rb
deleted file mode 100644
index 837c7edd06..0000000000
--- a/spec/ruby/library/io-wait/fixtures/classes.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-module IOWaitSpec
- def self.exhaust_write_buffer(io)
- written = 0
- buf = " " * 4096
-
- begin
- written += io.write_nonblock(buf)
- rescue Errno::EAGAIN, Errno::EWOULDBLOCK
- return written
- end while true
- end
-end
diff --git a/spec/ruby/library/io-wait/wait_readable_spec.rb b/spec/ruby/library/io-wait/wait_readable_spec.rb
index 06ffbda5c8..d7473f029f 100644
--- a/spec/ruby/library/io-wait/wait_readable_spec.rb
+++ b/spec/ruby/library/io-wait/wait_readable_spec.rb
@@ -1,9 +1,5 @@
require_relative '../../spec_helper'
-ruby_version_is ''...'3.2' do
- require 'io/wait'
-end
-
describe "IO#wait_readable" do
before :each do
@io = File.new(__FILE__ )
@@ -24,4 +20,23 @@ describe "IO#wait_readable" do
it "waits for the IO to become readable with the given large timeout" do
@io.wait_readable(365 * 24 * 60 * 60).should == @io
end
+
+ it "can be interrupted" do
+ rd, wr = IO.pipe
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+
+ t = Thread.new do
+ rd.wait_readable(10)
+ end
+
+ Thread.pass until t.stop?
+ t.kill
+ t.join
+
+ finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ (finish - start).should < 9
+ ensure
+ rd.close
+ wr.close
+ end
end
diff --git a/spec/ruby/library/io-wait/wait_spec.rb b/spec/ruby/library/io-wait/wait_spec.rb
index fc07c6a8d9..6a3890a401 100644
--- a/spec/ruby/library/io-wait/wait_spec.rb
+++ b/spec/ruby/library/io-wait/wait_spec.rb
@@ -1,9 +1,5 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-
-ruby_version_is ''...'3.2' do
- require 'io/wait'
-end
+require_relative '../../fixtures/io'
describe "IO#wait" do
before :each do
@@ -25,26 +21,13 @@ describe "IO#wait" do
end
context "[events, timeout] passed" do
- ruby_version_is ""..."3.2" do
- it "returns self when the READABLE event is ready during the timeout" do
- @w.write('data to read')
- @r.wait(IO::READABLE, 2).should.equal?(@r)
- end
-
- it "returns self when the WRITABLE event is ready during the timeout" do
- @w.wait(IO::WRITABLE, 0).should.equal?(@w)
- end
+ it "returns events mask when the READABLE event is ready during the timeout" do
+ @w.write('data to read')
+ @r.wait(IO::READABLE, 2).should == IO::READABLE
end
- ruby_version_is "3.2" do
- it "returns events mask when the READABLE event is ready during the timeout" do
- @w.write('data to read')
- @r.wait(IO::READABLE, 2).should == IO::READABLE
- end
-
- it "returns events mask when the WRITABLE event is ready during the timeout" do
- @w.wait(IO::WRITABLE, 0).should == IO::WRITABLE
- end
+ it "returns events mask when the WRITABLE event is ready during the timeout" do
+ @w.wait(IO::WRITABLE, 0).should == IO::WRITABLE
end
it "waits for the READABLE event to be ready" do
@@ -55,7 +38,7 @@ describe "IO#wait" do
end
it "waits for the WRITABLE event to be ready" do
- written_bytes = IOWaitSpec.exhaust_write_buffer(@w)
+ written_bytes = IOSpec.exhaust_write_buffer(@w)
@w.wait(IO::WRITABLE, 0).should == nil
@r.read(written_bytes)
@@ -67,7 +50,7 @@ describe "IO#wait" do
end
it "returns nil when the WRITABLE event is not ready during the timeout" do
- IOWaitSpec.exhaust_write_buffer(@w)
+ IOSpec.exhaust_write_buffer(@w)
@w.wait(IO::WRITABLE, 0).should == nil
end
@@ -76,11 +59,9 @@ describe "IO#wait" do
-> { @io.wait(IO::READABLE, 0) }.should raise_error(IOError, "closed stream")
end
- ruby_version_is "3.2" do
- it "raises ArgumentError when events is not positive" do
- -> { @w.wait(0, 0) }.should raise_error(ArgumentError, "Events must be positive integer!")
- -> { @w.wait(-1, 0) }.should raise_error(ArgumentError, "Events must be positive integer!")
- end
+ it "raises ArgumentError when events is not positive" do
+ -> { @w.wait(0, 0) }.should raise_error(ArgumentError, "Events must be positive integer!")
+ -> { @w.wait(-1, 0) }.should raise_error(ArgumentError, "Events must be positive integer!")
end
it "changes thread status to 'sleep' when waits for READABLE event" do
@@ -91,14 +72,48 @@ describe "IO#wait" do
t.join # Thread#kill doesn't wait for the thread to end
end
- it "changes thread status to 'sleep' when waits for WRITABLE event" do
- written_bytes = IOWaitSpec.exhaust_write_buffer(@w)
+ # https://github.com/ruby/ruby/actions/runs/11948300522/job/33305664284?pr=12139
+ platform_is_not :windows do
+ it "changes thread status to 'sleep' when waits for WRITABLE event" do
+ IOSpec.exhaust_write_buffer(@w)
- t = Thread.new { @w.wait(IO::WRITABLE, 10) }
- sleep 1
- t.status.should == 'sleep'
+ t = Thread.new { @w.wait(IO::WRITABLE, 10) }
+ sleep 1
+ t.status.should == 'sleep'
+ t.kill
+ t.join # Thread#kill doesn't wait for the thread to end
+ end
+ end
+
+ it "can be interrupted when waiting for READABLE event" do
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+
+ t = Thread.new do
+ @r.wait(IO::READABLE, 10)
+ end
+
+ Thread.pass until t.stop?
+ t.kill
+ t.join # Thread#kill doesn't wait for the thread to end
+
+ finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ (finish - start).should < 9
+ end
+
+ it "can be interrupted when waiting for WRITABLE event" do
+ IOSpec.exhaust_write_buffer(@w)
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+
+ t = Thread.new do
+ @w.wait(IO::WRITABLE, 10)
+ end
+
+ Thread.pass until t.stop?
t.kill
t.join # Thread#kill doesn't wait for the thread to end
+
+ finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ (finish - start).should < 9
end
end
@@ -122,34 +137,26 @@ describe "IO#wait" do
end
it "accepts a list of modes" do
- @io.wait(0, :r, :w, :rw).should == @io
+ @io.wait(0, :r, :w, :rw).should == @io
end
- # It works at least since 2.7 but by some reason may fail on 3.1
- ruby_version_is "3.2" do
- it "accepts timeout and mode in any order" do
- @io.wait(0, :r).should == @io
- @io.wait(:r, 0).should == @io
- @io.wait(:r, 0, :w).should == @io
- end
+ it "accepts timeout and mode in any order" do
+ @io.wait(0, :r).should == @io
+ @io.wait(:r, 0).should == @io
+ @io.wait(:r, 0, :w).should == @io
end
it "raises ArgumentError when passed wrong Symbol value as mode argument" do
-> { @io.wait(0, :wrong) }.should raise_error(ArgumentError, "unsupported mode: wrong")
end
- # It works since 3.0 but by some reason may fail on 3.1
- ruby_version_is "3.2" do
- it "raises ArgumentError when several Integer arguments passed" do
- -> { @w.wait(0, 10, :r) }.should raise_error(ArgumentError, "timeout given more than once")
- end
+ it "raises ArgumentError when several Integer arguments passed" do
+ -> { @w.wait(0, 10, :r) }.should raise_error(ArgumentError, "timeout given more than once")
end
- ruby_version_is "3.2" do
- it "raises IOError when io is closed (closed stream (IOError))" do
- @io.close
- -> { @io.wait(0, :r) }.should raise_error(IOError, "closed stream")
- end
+ it "raises IOError when io is closed (closed stream (IOError))" do
+ @io.close
+ -> { @io.wait(0, :r) }.should raise_error(IOError, "closed stream")
end
end
end
diff --git a/spec/ruby/library/io-wait/wait_writable_spec.rb b/spec/ruby/library/io-wait/wait_writable_spec.rb
index 8c44780d39..2017817caa 100644
--- a/spec/ruby/library/io-wait/wait_writable_spec.rb
+++ b/spec/ruby/library/io-wait/wait_writable_spec.rb
@@ -1,8 +1,5 @@
require_relative '../../spec_helper'
-
-ruby_version_is ''...'3.2' do
- require 'io/wait'
-end
+require_relative '../../fixtures/io'
describe "IO#wait_writable" do
it "waits for the IO to become writable with no timeout" do
@@ -17,4 +14,24 @@ describe "IO#wait_writable" do
# Represents one year and is larger than a 32-bit int
STDOUT.wait_writable(365 * 24 * 60 * 60).should == STDOUT
end
+
+ it "can be interrupted" do
+ rd, wr = IO.pipe
+ IOSpec.exhaust_write_buffer(wr)
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+
+ t = Thread.new do
+ wr.wait_writable(10)
+ end
+
+ Thread.pass until t.stop?
+ t.kill
+ t.join
+
+ finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ (finish - start).should < 9
+ ensure
+ rd.close unless rd.closed?
+ wr.close unless wr.closed?
+ end
end
diff --git a/spec/ruby/library/ipaddr/new_spec.rb b/spec/ruby/library/ipaddr/new_spec.rb
index 714c1e2f1a..2c0f44acf2 100644
--- a/spec/ruby/library/ipaddr/new_spec.rb
+++ b/spec/ruby/library/ipaddr/new_spec.rb
@@ -77,40 +77,16 @@ describe "IPAddr#new" do
a.family.should == Socket::AF_INET6
end
- ipaddr_version = if defined?(IPAddr::VERSION) #ruby_version_is ""..."3.1" do
- IPAddr::VERSION
- else
- "1.2.2"
- end
-
- version_is ipaddr_version, ""..."1.2.3" do #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
-
- version_is ipaddr_version, "1.2.3" do #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
+ 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
diff --git a/spec/ruby/library/irb/fixtures/irb.rb b/spec/ruby/library/irb/fixtures/irb.rb
new file mode 100644
index 0000000000..8d386dfda1
--- /dev/null
+++ b/spec/ruby/library/irb/fixtures/irb.rb
@@ -0,0 +1,3 @@
+a = 10
+
+binding.irb # rubocop:disable Lint/Debugger
diff --git a/spec/ruby/core/binding/irb_spec.rb b/spec/ruby/library/irb/irb_spec.rb
index 2607c7ef33..2607c7ef33 100644
--- a/spec/ruby/core/binding/irb_spec.rb
+++ b/spec/ruby/library/irb/irb_spec.rb
diff --git a/spec/ruby/library/logger/logger/new_spec.rb b/spec/ruby/library/logger/logger/new_spec.rb
index d3100ee2d1..3db20e7432 100644
--- a/spec/ruby/library/logger/logger/new_spec.rb
+++ b/spec/ruby/library/logger/logger/new_spec.rb
@@ -13,24 +13,24 @@ describe "Logger#new" do
rm_r @file_path
end
- it "creates a new logger object" do
- l = Logger.new(STDERR)
- -> { l.add(Logger::WARN, "Foo") }.should output_to_fd(/Foo/, STDERR)
- end
+ it "creates a new logger object" do
+ l = Logger.new(STDERR)
+ -> { l.add(Logger::WARN, "Foo") }.should output_to_fd(/Foo/, STDERR)
+ end
- it "receives a logging device as first argument" do
- l = Logger.new(@log_file)
- l.add(Logger::WARN, "Test message")
+ it "receives a logging device as first argument" do
+ l = Logger.new(@log_file)
+ l.add(Logger::WARN, "Test message")
- @log_file.rewind
- LoggerSpecs.strip_date(@log_file.readline).should == "WARN -- : Test message\n"
- l.close
- end
+ @log_file.rewind
+ LoggerSpecs.strip_date(@log_file.readline).should == "WARN -- : Test message\n"
+ l.close
+ end
it "receives a frequency rotation as second argument" do
- -> { Logger.new(@log_file, "daily") }.should_not raise_error
- -> { Logger.new(@log_file, "weekly") }.should_not raise_error
- -> { Logger.new(@log_file, "monthly") }.should_not raise_error
+ -> { Logger.new(@log_file, "daily") }.should_not raise_error
+ -> { Logger.new(@log_file, "weekly") }.should_not raise_error
+ -> { Logger.new(@log_file, "monthly") }.should_not raise_error
end
it "also receives a number of log files to keep as second argument" do
diff --git a/spec/ruby/library/matrix/exponent_spec.rb b/spec/ruby/library/matrix/exponent_spec.rb
index b76e18b4cd..38cdfa9276 100644
--- a/spec/ruby/library/matrix/exponent_spec.rb
+++ b/spec/ruby/library/matrix/exponent_spec.rb
@@ -34,17 +34,15 @@ describe "Matrix#**" do
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
+ 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
+ it "raises an ErrDimensionMismatch for non-square matrices" do
+ m = Matrix[ [1, 1] ]
+ -> { m ** 0 }.should raise_error(Matrix::ErrDimensionMismatch)
end
end
end
diff --git a/spec/ruby/library/net-ftp/connect_spec.rb b/spec/ruby/library/net-ftp/connect_spec.rb
index 4330d430b4..e606b11e2a 100644
--- a/spec/ruby/library/net-ftp/connect_spec.rb
+++ b/spec/ruby/library/net-ftp/connect_spec.rb
@@ -26,14 +26,6 @@ describe "Net::FTP#connect" do
@ftp.connect(@server.hostname, @server.server_port).should be_nil
end
- ruby_version_is ""..."3.1" do
- 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
- 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
diff --git a/spec/ruby/library/net-ftp/fixtures/server.rb b/spec/ruby/library/net-ftp/fixtures/server.rb
index ecbed591d5..8b34d3f8bd 100644
--- a/spec/ruby/library/net-ftp/fixtures/server.rb
+++ b/spec/ruby/library/net-ftp/fixtures/server.rb
@@ -9,7 +9,7 @@ module NetFTPSpecs
attr_reader :server_port
def initialize
- @hostname = "localhost"
+ @hostname = "127.0.0.1"
@server = TCPServer.new(@hostname, 0)
@server_port = @server.addr[1]
diff --git a/spec/ruby/library/net-ftp/shared/puttextfile.rb b/spec/ruby/library/net-ftp/shared/puttextfile.rb
index 4722439674..e2c0453352 100644
--- a/spec/ruby/library/net-ftp/shared/puttextfile.rb
+++ b/spec/ruby/library/net-ftp/shared/puttextfile.rb
@@ -34,8 +34,16 @@ describe :net_ftp_puttextfile, shared: true do
remote_lines.should == local_lines.gsub("\n", "\r\n")
end
- it "returns nil" do
- @ftp.send(@method, @local_fixture_file, "text").should be_nil
+ guard -> { Net::FTP::VERSION < '0.3.6' } do
+ it "returns nil" do
+ @ftp.send(@method, @local_fixture_file, "text").should be_nil
+ end
+ end
+
+ guard -> { Net::FTP::VERSION >= '0.3.6' } do
+ it "returns the response" do
+ @ftp.send(@method, @local_fixture_file, "text").should == @ftp.last_response
+ end
end
describe "when passed a block" do
diff --git a/spec/ruby/library/net-http/HTTPServerException_spec.rb b/spec/ruby/library/net-http/HTTPServerException_spec.rb
index 5e0a833fee..020d3cce85 100644
--- a/spec/ruby/library/net-http/HTTPServerException_spec.rb
+++ b/spec/ruby/library/net-http/HTTPServerException_spec.rb
@@ -3,10 +3,10 @@ require 'net/http'
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/)
+ -> { eval("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/)
+ -> { eval("Net::HTTPServerException").should < Net::HTTPExceptions }.should complain(/warning: constant Net::HTTPServerException is deprecated/)
end
end
diff --git a/spec/ruby/library/net-http/http/post_spec.rb b/spec/ruby/library/net-http/http/post_spec.rb
index d7d94fec4a..b8b8d16ad1 100644
--- a/spec/ruby/library/net-http/http/post_spec.rb
+++ b/spec/ruby/library/net-http/http/post_spec.rb
@@ -25,9 +25,11 @@ describe "Net::HTTP.post" do
response.should be_kind_of(Net::HTTPResponse)
end
- 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"')
+ ruby_version_is ""..."4.0" do
+ 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" }.inspect.delete("{}"))
+ end
end
it "does not support HTTP Basic Auth" do
diff --git a/spec/ruby/library/net-http/http/send_request_spec.rb b/spec/ruby/library/net-http/http/send_request_spec.rb
index e82b2a96a1..af35c068ce 100644
--- a/spec/ruby/library/net-http/http/send_request_spec.rb
+++ b/spec/ruby/library/net-http/http/send_request_spec.rb
@@ -54,7 +54,7 @@ describe "Net::HTTP#send_request" do
@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 }.inspect.delete("{}"))
end
end
end
diff --git a/spec/ruby/library/net-http/httpgenericrequest/exec_spec.rb b/spec/ruby/library/net-http/httpgenericrequest/exec_spec.rb
index 7de03d7da0..a09f9d5bec 100644
--- a/spec/ruby/library/net-http/httpgenericrequest/exec_spec.rb
+++ b/spec/ruby/library/net-http/httpgenericrequest/exec_spec.rb
@@ -31,18 +31,20 @@ describe "Net::HTTPGenericRequest#exec when passed socket, version, path" do
end
describe "when a request body is set" do
- it "sets the 'Content-Type' header to 'application/x-www-form-urlencoded' unless the 'Content-Type' header is supplied" do
- request = Net::HTTPGenericRequest.new("POST", true, true, "/some/path")
- request.body = "Some Content"
-
- request.exec(@buffered_socket, "1.1", "/some/other/path")
- str = @socket.string
-
- str.should =~ %r[POST /some/other/path HTTP/1.1\r\n]
- str.should =~ %r[Accept: \*/\*\r\n]
- str.should =~ %r[Content-Type: application/x-www-form-urlencoded\r\n]
- str.should =~ %r[Content-Length: 12\r\n]
- str[-16..-1].should == "\r\n\r\nSome Content"
+ ruby_version_is ""..."4.0" do
+ it "sets the 'Content-Type' header to 'application/x-www-form-urlencoded' unless the 'Content-Type' header is supplied" do
+ request = Net::HTTPGenericRequest.new("POST", true, true, "/some/path")
+ request.body = "Some Content"
+
+ request.exec(@buffered_socket, "1.1", "/some/other/path")
+ str = @socket.string
+
+ str.should =~ %r[POST /some/other/path HTTP/1.1\r\n]
+ str.should =~ %r[Accept: \*/\*\r\n]
+ str.should =~ %r[Content-Type: application/x-www-form-urlencoded\r\n]
+ str.should =~ %r[Content-Length: 12\r\n]
+ str[-16..-1].should == "\r\n\r\nSome Content"
+ end
end
it "correctly sets the 'Content-Length' header and includes the body" do
@@ -62,19 +64,21 @@ describe "Net::HTTPGenericRequest#exec when passed socket, version, path" do
end
describe "when a body stream is set" do
- it "sets the 'Content-Type' header to 'application/x-www-form-urlencoded' unless the 'Content-Type' header is supplied" do
- request = Net::HTTPGenericRequest.new("POST", true, true, "/some/path",
- "Content-Length" => "10")
- request.body_stream = StringIO.new("a" * 20)
-
- request.exec(@buffered_socket, "1.1", "/some/other/path")
- str = @socket.string
-
- str.should =~ %r[POST /some/other/path HTTP/1.1\r\n]
- str.should =~ %r[Accept: \*/\*\r\n]
- str.should =~ %r[Content-Type: application/x-www-form-urlencoded\r\n]
- str.should =~ %r[Content-Length: 10\r\n]
- str[-24..-1].should == "\r\n\r\naaaaaaaaaaaaaaaaaaaa"
+ ruby_version_is ""..."4.0" do
+ it "sets the 'Content-Type' header to 'application/x-www-form-urlencoded' unless the 'Content-Type' header is supplied" do
+ request = Net::HTTPGenericRequest.new("POST", true, true, "/some/path",
+ "Content-Length" => "10")
+ request.body_stream = StringIO.new("a" * 20)
+
+ request.exec(@buffered_socket, "1.1", "/some/other/path")
+ str = @socket.string
+
+ str.should =~ %r[POST /some/other/path HTTP/1.1\r\n]
+ str.should =~ %r[Accept: \*/\*\r\n]
+ str.should =~ %r[Content-Type: application/x-www-form-urlencoded\r\n]
+ str.should =~ %r[Content-Length: 10\r\n]
+ str[-24..-1].should == "\r\n\r\naaaaaaaaaaaaaaaaaaaa"
+ end
end
it "sends the whole stream, regardless of the 'Content-Length' header" do
diff --git a/spec/ruby/library/objectspace/memsize_of_spec.rb b/spec/ruby/library/objectspace/memsize_of_spec.rb
index eefafbb334..cbb5a07d54 100644
--- a/spec/ruby/library/objectspace/memsize_of_spec.rb
+++ b/spec/ruby/library/objectspace/memsize_of_spec.rb
@@ -13,7 +13,7 @@ describe "ObjectSpace.memsize_of" do
end
it "returns 0 for literal Symbols" do
- ObjectSpace.memsize_of(:abc).should == 0
+ ObjectSpace.memsize_of(:object_space_memsize_spec_static_sym).should == 0
end
it "returns a positive Integer for an Object" do
diff --git a/spec/ruby/library/objectspace/trace_object_allocations_spec.rb b/spec/ruby/library/objectspace/trace_object_allocations_spec.rb
index 612430e067..0f1e2aa8b9 100644
--- a/spec/ruby/library/objectspace/trace_object_allocations_spec.rb
+++ b/spec/ruby/library/objectspace/trace_object_allocations_spec.rb
@@ -2,6 +2,20 @@ require_relative '../../spec_helper'
require 'objspace'
describe "ObjectSpace.trace_object_allocations" do
+ def has_class_frame?
+ Class.new {
+ attr_reader :c
+
+ def initialize
+ @c = caller_locations.first.label =~ /new/
+ end
+ }.new.c
+ end
+
+ def obj_class_path
+ has_class_frame? ? "Class" : nil
+ end
+
it "runs a block" do
ScratchPad.clear
ObjectSpace.trace_object_allocations do
@@ -13,7 +27,7 @@ describe "ObjectSpace.trace_object_allocations" do
it "records info for allocation_class_path" do
ObjectSpace.trace_object_allocations do
o = Object.new
- ObjectSpace.allocation_class_path(o).should == "Class"
+ ObjectSpace.allocation_class_path(o).should == obj_class_path
a = [1, 2, 3]
ObjectSpace.allocation_class_path(a).should == nil
end
@@ -31,7 +45,7 @@ describe "ObjectSpace.trace_object_allocations" do
it "records info for allocation_method_id" do
ObjectSpace.trace_object_allocations do
o = Object.new
- ObjectSpace.allocation_method_id(o).should == :new
+ ObjectSpace.allocation_method_id(o).should == (has_class_frame? ? :new : nil)
a = [1, 2, 3]
ObjectSpace.allocation_method_id(a).should == nil
end
@@ -58,7 +72,7 @@ describe "ObjectSpace.trace_object_allocations" do
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.allocation_class_path(o).should == obj_class_path
ObjectSpace.trace_object_allocations_clear
ObjectSpace.allocation_class_path(o).should be_nil
end
@@ -69,14 +83,14 @@ describe "ObjectSpace.trace_object_allocations" do
ObjectSpace.trace_object_allocations do
o = Object.new
end
- ObjectSpace.allocation_class_path(o).should == "Class"
+ ObjectSpace.allocation_class_path(o).should == obj_class_path
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"
+ ObjectSpace.allocation_class_path(o).should == obj_class_path
a = [1, 2, 3]
ObjectSpace.allocation_class_path(a).should == nil
ensure
@@ -91,14 +105,14 @@ describe "ObjectSpace.trace_object_allocations" do
ensure
ObjectSpace.trace_object_allocations_stop
end
- ObjectSpace.allocation_class_path(o).should == "Class"
+ ObjectSpace.allocation_class_path(o).should == obj_class_path
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"
+ ObjectSpace.allocation_class_path(o).should == obj_class_path
end
end
end
@@ -109,7 +123,7 @@ describe "ObjectSpace.trace_object_allocations" do
ObjectSpace.trace_object_allocations_start
begin
o = Object.new
- ObjectSpace.allocation_class_path(o).should == "Class"
+ ObjectSpace.allocation_class_path(o).should == obj_class_path
ensure
ObjectSpace.trace_object_allocations_stop
end
@@ -122,7 +136,7 @@ describe "ObjectSpace.trace_object_allocations" do
ObjectSpace.trace_object_allocations_start
begin
o = Object.new
- ObjectSpace.allocation_class_path(o).should == "Class"
+ ObjectSpace.allocation_class_path(o).should == obj_class_path
ObjectSpace.trace_object_allocations_stop
ensure
ObjectSpace.trace_object_allocations_stop
diff --git a/spec/ruby/library/objectspace/trace_spec.rb b/spec/ruby/library/objectspace/trace_spec.rb
index 532c282ce4..3957dc930d 100644
--- a/spec/ruby/library/objectspace/trace_spec.rb
+++ b/spec/ruby/library/objectspace/trace_spec.rb
@@ -1,15 +1,13 @@
require_relative '../../spec_helper'
-ruby_version_is "3.1" do
- describe 'require "objspace/trace"' do
- it "shows object allocation sites" do
- file = fixture(__FILE__ , "trace.rb")
- ruby_exe(file, args: "2>&1").lines(chomp: true).should == [
- "objspace/trace is enabled",
- "\"foo\" @ #{file}:3",
- "\"bar\" @ #{file}:4",
- "42"
- ]
- end
+describe 'require "objspace/trace"' do
+ it "shows object allocation sites" do
+ file = fixture(__FILE__ , "trace.rb")
+ ruby_exe(file, args: "2>&1").lines(chomp: true).should == [
+ "objspace/trace is enabled",
+ "\"foo\" @ #{file}:3",
+ "\"bar\" @ #{file}:4",
+ "42"
+ ]
end
end
diff --git a/spec/ruby/library/openssl/digest/initialize_spec.rb b/spec/ruby/library/openssl/digest/initialize_spec.rb
index 1cd0409c4d..b5911716ca 100644
--- a/spec/ruby/library/openssl/digest/initialize_spec.rb
+++ b/spec/ruby/library/openssl/digest/initialize_spec.rb
@@ -23,18 +23,14 @@ describe "OpenSSL::Digest#initialize" do
OpenSSL::Digest.new("sha512").name.should == "SHA512"
end
- it "throws an error when called with an unknown digest" do
- -> { OpenSSL::Digest.new("wd40") }.should raise_error(RuntimeError, /Unsupported digest algorithm \(wd40\)/)
+ version_is OpenSSL::VERSION, "4.0.0" do
+ it "throws an error when called with an unknown digest" do
+ -> { OpenSSL::Digest.new("wd40") }.should raise_error(OpenSSL::Digest::DigestError, /wd40/)
+ end
end
it "cannot be called with a symbol" do
- -> { OpenSSL::Digest.new(:SHA1) }.should raise_error(TypeError, /wrong argument type Symbol/)
- end
-
- it "does not call #to_str on the argument" do
- name = mock("digest name")
- name.should_not_receive(:to_str)
- -> { OpenSSL::Digest.new(name) }.should raise_error(TypeError, /wrong argument type/)
+ -> { OpenSSL::Digest.new(:SHA1) }.should raise_error(TypeError)
end
end
@@ -62,7 +58,7 @@ describe "OpenSSL::Digest#initialize" do
end
it "cannot be called with a digest class" do
- -> { OpenSSL::Digest.new(OpenSSL::Digest::SHA1) }.should raise_error(TypeError, /wrong argument type Class/)
+ -> { OpenSSL::Digest.new(OpenSSL::Digest::SHA1) }.should raise_error(TypeError)
end
context "when called without an initial String argument" do
diff --git a/spec/ruby/library/openssl/kdf/pbkdf2_hmac_spec.rb b/spec/ruby/library/openssl/kdf/pbkdf2_hmac_spec.rb
index 40f8597275..1112972060 100644
--- a/spec/ruby/library/openssl/kdf/pbkdf2_hmac_spec.rb
+++ b/spec/ruby/library/openssl/kdf/pbkdf2_hmac_spec.rb
@@ -107,21 +107,15 @@ describe "OpenSSL::KDF.pbkdf2_hmac" do
it "raises a TypeError when hash is neither a String nor an OpenSSL::Digest" do
-> {
OpenSSL::KDF.pbkdf2_hmac("secret", **@defaults, hash: Object.new)
- }.should raise_error(TypeError, "wrong argument type Object (expected OpenSSL/Digest)")
+ }.should raise_error(TypeError)
end
- it "raises a TypeError when hash is neither a String nor an OpenSSL::Digest, it does not try to call #to_str" do
- hash = mock("hash")
- hash.should_not_receive(:to_str)
- -> {
- OpenSSL::KDF.pbkdf2_hmac("secret", **@defaults, hash: hash)
- }.should raise_error(TypeError, "wrong argument type MockObject (expected OpenSSL/Digest)")
- end
-
- it "raises a RuntimeError for unknown digest algorithms" do
- -> {
- OpenSSL::KDF.pbkdf2_hmac("secret", **@defaults, hash: "wd40")
- }.should raise_error(RuntimeError, /Unsupported digest algorithm \(wd40\)/)
+ version_is OpenSSL::VERSION, "4.0.0" do
+ it "raises a OpenSSL::Digest::DigestError for unknown digest algorithms" do
+ -> {
+ OpenSSL::KDF.pbkdf2_hmac("secret", **@defaults, hash: "wd40")
+ }.should raise_error(OpenSSL::Digest::DigestError, /wd40/)
+ end
end
it "treats salt as a required keyword" do
diff --git a/spec/ruby/library/openssl/kdf/scrypt_spec.rb b/spec/ruby/library/openssl/kdf/scrypt_spec.rb
index 5dc9f2f281..e01b8bca8a 100644
--- a/spec/ruby/library/openssl/kdf/scrypt_spec.rb
+++ b/spec/ruby/library/openssl/kdf/scrypt_spec.rb
@@ -1,7 +1,8 @@
require_relative '../../../spec_helper'
require 'openssl'
-guard -> { OpenSSL::KDF.respond_to?(:scrypt) } do
+# LibreSSL seems not to support scrypt
+guard -> { OpenSSL::OPENSSL_VERSION.start_with?('OpenSSL') and OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10100000 } do
describe "OpenSSL::KDF.scrypt" do
before :each do
@defaults = {
diff --git a/spec/ruby/library/openssl/shared/constants.rb b/spec/ruby/library/openssl/shared/constants.rb
index 0bed4156a1..836f75011b 100644
--- a/spec/ruby/library/openssl/shared/constants.rb
+++ b/spec/ruby/library/openssl/shared/constants.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
module HMACConstants
Contents = "Ipsum is simply dummy text of the printing and typesetting industry. \nLorem Ipsum has been the industrys standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. \nIt has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. \nIt was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."
diff --git a/spec/ruby/library/pathname/glob_spec.rb b/spec/ruby/library/pathname/glob_spec.rb
index ced810fa90..de322bab47 100644
--- a/spec/ruby/library/pathname/glob_spec.rb
+++ b/spec/ruby/library/pathname/glob_spec.rb
@@ -21,6 +21,10 @@ describe 'Pathname.glob' do
Pathname.glob(@dir + 'lib/*.js').should == []
end
+ it 'returns [] when the pathname does not exist' do
+ Pathname.glob('i_dont_exist/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
@@ -67,6 +71,10 @@ describe 'Pathname#glob' do
Pathname.new(@dir).glob('lib/*.js').should == []
end
+ it 'returns [] when the pathname does not exist' do
+ Pathname.new('./i_dont_exist').glob('lib/*.js').should == []
+ end
+
it 'returns matching file paths' do
Pathname.new(@dir).glob('lib/*i*.rb').sort.should == [Pathname.new(@file_1), Pathname.new(@file_2)].sort
end
diff --git a/spec/ruby/library/pp/pp_spec.rb b/spec/ruby/library/pp/pp_spec.rb
index 243478efd9..e45a6bb94f 100644
--- a/spec/ruby/library/pp/pp_spec.rb
+++ b/spec/ruby/library/pp/pp_spec.rb
@@ -25,6 +25,6 @@ describe "PP.pp" do
hash = { 'key' => 42 }
-> {
PP.pp hash
- }.should output('{"key"=>42}' + "\n")
+ }.should output("#{hash.inspect}\n")
end
end
diff --git a/spec/ruby/library/random/formatter/alphanumeric_spec.rb b/spec/ruby/library/random/formatter/alphanumeric_spec.rb
new file mode 100644
index 0000000000..9bd325e1d0
--- /dev/null
+++ b/spec/ruby/library/random/formatter/alphanumeric_spec.rb
@@ -0,0 +1,56 @@
+require_relative '../../../spec_helper'
+
+require 'random/formatter'
+
+describe "Random::Formatter#alphanumeric" do
+ before :each do
+ @object = Object.new
+ @object.extend(Random::Formatter)
+ @object.define_singleton_method(:bytes) do |n|
+ "\x00".b * n
+ end
+ end
+
+ it "generates a random alphanumeric string" do
+ @object.alphanumeric.should =~ /\A[A-Za-z0-9]+\z/
+ end
+
+ it "has a default size of 16 characters" do
+ @object.alphanumeric.size.should == 16
+ end
+
+ it "accepts a 'size' argument" do
+ @object.alphanumeric(10).size.should == 10
+ end
+
+ it "uses the default size if 'nil' is given as size argument" do
+ @object.alphanumeric(nil).size.should == 16
+ end
+
+ it "raises an ArgumentError if the size is not numeric" do
+ -> {
+ @object.alphanumeric("10")
+ }.should raise_error(ArgumentError)
+ end
+
+ it "does not coerce the size argument with #to_int" do
+ size = mock("size")
+ size.should_not_receive(:to_int)
+ -> {
+ @object.alphanumeric(size)
+ }.should raise_error(ArgumentError)
+ end
+
+ ruby_version_is "3.3" do
+ it "accepts a 'chars' argument with the output alphabet" do
+ @object.alphanumeric(chars: ['a', 'b']).should =~ /\A[ab]+\z/
+ end
+
+ it "converts the elements of chars using #to_s" do
+ to_s = mock("to_s")
+ to_s.should_receive(:to_s).and_return("[mock to_s]")
+ # Using 1 value in chars results in an infinite loop
+ @object.alphanumeric(1, chars: [to_s, to_s]).should == "[mock to_s]"
+ end
+ end
+end
diff --git a/spec/ruby/library/rbconfig/rbconfig_spec.rb b/spec/ruby/library/rbconfig/rbconfig_spec.rb
index b90cc90970..b9a4588bf0 100644
--- a/spec/ruby/library/rbconfig/rbconfig_spec.rb
+++ b/spec/ruby/library/rbconfig/rbconfig_spec.rb
@@ -9,6 +9,13 @@ describe 'RbConfig::CONFIG' do
end
end
+ it 'has MAJOR, MINOR, TEENY, and PATCHLEVEL matching RUBY_VERSION and RUBY_PATCHLEVEL' do
+ major, minor, teeny = RUBY_VERSION.split('.')
+ RbConfig::CONFIG.values_at("MAJOR", "MINOR", "TEENY", "PATCHLEVEL").should == [
+ major, minor, teeny, RUBY_PATCHLEVEL.to_s
+ ]
+ end
+
# These directories have no meanings before the installation.
guard -> { RbConfig::TOPDIR } do
it "['rubylibdir'] returns the directory containing Ruby standard libraries" do
@@ -88,6 +95,30 @@ describe 'RbConfig::CONFIG' do
end
end
end
+
+ guard -> { %w[aarch64 arm64].include? RbConfig::CONFIG['host_cpu'] } do
+ it "['host_cpu'] returns CPU architecture properly for AArch64" do
+ platform_is :darwin do
+ RbConfig::CONFIG['host_cpu'].should == 'arm64'
+ end
+
+ platform_is_not :darwin do
+ RbConfig::CONFIG['host_cpu'].should == 'aarch64'
+ end
+ end
+ end
+
+ guard -> { platform_is(:linux) || platform_is(:darwin) } do
+ it "['host_os'] returns a proper OS name or platform" do
+ platform_is :darwin do
+ RbConfig::CONFIG['host_os'].should.match?(/darwin/)
+ end
+
+ platform_is :linux do
+ RbConfig::CONFIG['host_os'].should.match?(/linux/)
+ end
+ end
+ end
end
describe "RbConfig::TOPDIR" do
@@ -99,3 +130,34 @@ describe "RbConfig::TOPDIR" do
end
end
end
+
+describe "RUBY_PLATFORM" do
+ it "RUBY_PLATFORM contains a proper CPU architecture" do
+ RUBY_PLATFORM.should.include? RbConfig::CONFIG['host_cpu']
+ end
+
+ guard -> { platform_is(:linux) || platform_is(:darwin) } do
+ it "RUBY_PLATFORM contains OS name" do
+ # don't use RbConfig::CONFIG['host_os'] as far as it could be slightly different, e.g. linux-gnu
+ platform_is(:linux) do
+ RUBY_PLATFORM.should.include? 'linux'
+ end
+
+ platform_is(:darwin) do
+ RUBY_PLATFORM.should.include? 'darwin'
+ end
+ end
+ end
+end
+
+describe "RUBY_DESCRIPTION" do
+ guard_not -> { RUBY_ENGINE == "ruby" && !RbConfig::TOPDIR } do
+ it "contains version" do
+ RUBY_DESCRIPTION.should.include? RUBY_VERSION
+ end
+
+ it "contains RUBY_PLATFORM" do
+ RUBY_DESCRIPTION.should.include? RUBY_PLATFORM
+ end
+ end
+end
diff --git a/spec/ruby/library/rbconfig/unicode_emoji_version_spec.rb b/spec/ruby/library/rbconfig/unicode_emoji_version_spec.rb
index 3dc9900127..521a750bf7 100644
--- a/spec/ruby/library/rbconfig/unicode_emoji_version_spec.rb
+++ b/spec/ruby/library/rbconfig/unicode_emoji_version_spec.rb
@@ -2,22 +2,16 @@ require_relative '../../spec_helper'
require 'rbconfig'
describe "RbConfig::CONFIG['UNICODE_EMOJI_VERSION']" do
- ruby_version_is ""..."3.1" do
- it "is 12.1" do
- RbConfig::CONFIG['UNICODE_EMOJI_VERSION'].should == "12.1"
- end
- end
-
- ruby_version_is "3.1"..."3.2" do
- it "is 13.1" do
- RbConfig::CONFIG['UNICODE_EMOJI_VERSION'].should == "13.1"
+ ruby_version_is ""..."3.4" do
+ it "is 15.0" do
+ RbConfig::CONFIG['UNICODE_EMOJI_VERSION'].should == "15.0"
end
end
# Caution: ruby_version_is means is_or_later
- ruby_version_is "3.2" do
- it "is 15.0" do
- RbConfig::CONFIG['UNICODE_EMOJI_VERSION'].should == "15.0"
+ ruby_version_is "4.0" do
+ it "is 17.0" do
+ RbConfig::CONFIG['UNICODE_EMOJI_VERSION'].should == "17.0"
end
end
end
diff --git a/spec/ruby/library/rbconfig/unicode_version_spec.rb b/spec/ruby/library/rbconfig/unicode_version_spec.rb
index 458f13bf03..5cdde74f79 100644
--- a/spec/ruby/library/rbconfig/unicode_version_spec.rb
+++ b/spec/ruby/library/rbconfig/unicode_version_spec.rb
@@ -2,22 +2,16 @@ require_relative '../../spec_helper'
require 'rbconfig'
describe "RbConfig::CONFIG['UNICODE_VERSION']" do
- ruby_version_is ""..."3.1" do
- it "is 12.1.0" do
- RbConfig::CONFIG['UNICODE_VERSION'].should == "12.1.0"
- end
- end
-
- ruby_version_is "3.1"..."3.2" do
- it "is 13.0.0" do
- RbConfig::CONFIG['UNICODE_VERSION'].should == "13.0.0"
+ ruby_version_is ""..."3.4" do
+ it "is 15.0.0" do
+ RbConfig::CONFIG['UNICODE_VERSION'].should == "15.0.0"
end
end
# Caution: ruby_version_is means is_or_later
- ruby_version_is "3.2" do
- it "is 15.0.0" do
- RbConfig::CONFIG['UNICODE_VERSION'].should == "15.0.0"
+ ruby_version_is "4.0" do
+ it "is 17.0.0" do
+ RbConfig::CONFIG['UNICODE_VERSION'].should == "17.0.0"
end
end
end
diff --git a/spec/ruby/library/rubygems/gem/bin_path_spec.rb b/spec/ruby/library/rubygems/gem/bin_path_spec.rb
index 67b3e042c2..0b8c4db08b 100644
--- a/spec/ruby/library/rubygems/gem/bin_path_spec.rb
+++ b/spec/ruby/library/rubygems/gem/bin_path_spec.rb
@@ -22,6 +22,7 @@ describe "Gem.bin_path" do
end
skip "Could not find the default gemspecs" unless Dir.exist?(default_specifications_dir)
+ skip "default_specifications_dir mismatch with GEM_HOME" if ENV["GEM_HOME"] && !default_specifications_dir.start_with?(ENV['GEM_HOME'])
Gem::Specification.each_spec([default_specifications_dir]) do |spec|
spec.executables.each do |exe|
diff --git a/spec/ruby/library/securerandom/random_number_spec.rb b/spec/ruby/library/securerandom/random_number_spec.rb
index 03781f4901..bb25bc496e 100644
--- a/spec/ruby/library/securerandom/random_number_spec.rb
+++ b/spec/ruby/library/securerandom/random_number_spec.rb
@@ -11,8 +11,8 @@ describe "SecureRandom.random_number" do
(1..64).each do |idx|
num = SecureRandom.random_number(idx)
num.should be_kind_of(Integer)
- (0 <= num).should == true
- (num < idx).should == true
+ 0.should <= num
+ num.should < idx
end
end
@@ -21,8 +21,8 @@ describe "SecureRandom.random_number" do
11.times do
num = SecureRandom.random_number max
num.should be_kind_of(Integer)
- (0 <= num).should == true
- (num < max).should == true
+ 0.should <= num
+ num.should < max
end
end
@@ -30,8 +30,8 @@ describe "SecureRandom.random_number" do
64.times do
num = SecureRandom.random_number
num.should be_kind_of(Float)
- (0.0 <= num).should == true
- (num < 1.0).should == true
+ 0.0.should <= num
+ num.should < 1.0
end
end
@@ -39,8 +39,8 @@ describe "SecureRandom.random_number" do
64.times do
num = SecureRandom.random_number 11...13
num.should be_kind_of(Integer)
- (11 <= num).should == true
- (num < 13).should == true
+ 11.should <= num
+ num.should < 13
end
end
@@ -50,8 +50,8 @@ describe "SecureRandom.random_number" do
32.times do
num = SecureRandom.random_number lower..upper
num.should be_kind_of(Integer)
- (lower <= num).should == true
- (num <= upper).should == true
+ lower.should <= num
+ num.should <= upper
end
end
@@ -59,23 +59,23 @@ describe "SecureRandom.random_number" do
64.times do
num = SecureRandom.random_number 0.6..0.9
num.should be_kind_of(Float)
- (0.6 <= num).should == true
- (num <= 0.9).should == true
+ 0.6.should <= num
+ num.should <= 0.9
end
end
it "generates a random float number between 0.0 and 1.0 if argument is negative" do
num = SecureRandom.random_number(-10)
num.should be_kind_of(Float)
- (0.0 <= num).should == true
- (num < 1.0).should == true
+ 0.0.should <= num
+ num.should < 1.0
end
it "generates a random float number between 0.0 and 1.0 if argument is negative float" do
num = SecureRandom.random_number(-11.1)
num.should be_kind_of(Float)
- (0.0 <= num).should == true
- (num < 1.0).should == true
+ 0.0.should <= num
+ num.should < 1.0
end
it "generates different float numbers with subsequent invocations" do
@@ -84,7 +84,7 @@ describe "SecureRandom.random_number" do
256.times do
val = SecureRandom.random_number
# make sure the random values are not repeating
- values.include?(val).should == false
+ values.should_not include(val)
values << val
end
end
diff --git a/spec/ruby/library/set/add_spec.rb b/spec/ruby/library/set/add_spec.rb
deleted file mode 100644
index 68356cc111..0000000000
--- a/spec/ruby/library/set/add_spec.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-require_relative 'shared/add'
-
-describe "Set#add" do
- it_behaves_like :set_add, :add
-end
-
-describe "Set#add?" do
- before :each do
- @set = Set.new
- 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
- end
-end
diff --git a/spec/ruby/library/set/append_spec.rb b/spec/ruby/library/set/append_spec.rb
deleted file mode 100644
index 8b3498b779..0000000000
--- a/spec/ruby/library/set/append_spec.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-require_relative 'shared/add'
-
-describe "Set#<<" do
- it_behaves_like :set_add, :<<
-end
diff --git a/spec/ruby/library/set/case_compare_spec.rb b/spec/ruby/library/set/case_compare_spec.rb
deleted file mode 100644
index 70d392a27d..0000000000
--- a/spec/ruby/library/set/case_compare_spec.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'shared/include'
-require 'set'
-
-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
-end
diff --git a/spec/ruby/library/set/case_equality_spec.rb b/spec/ruby/library/set/case_equality_spec.rb
deleted file mode 100644
index 10cbfd380a..0000000000
--- a/spec/ruby/library/set/case_equality_spec.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'shared/include'
-require 'set'
-
-describe "Set#===" do
- it_behaves_like :set_include, :===
-end
diff --git a/spec/ruby/library/set/classify_spec.rb b/spec/ruby/library/set/classify_spec.rb
deleted file mode 100644
index ec600c91d6..0000000000
--- a/spec/ruby/library/set/classify_spec.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-
-describe "Set#classify" do
- before :each do
- @set = Set["one", "two", "three", "four"]
- end
-
- it "yields each Object in self" do
- res = []
- @set.classify { |x| res << x }
- res.sort.should == ["one", "two", "three", "four"].sort
- 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 => Set["one", "two"], 4 => Set["four"], 5 => Set["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 => Set["one", "two"], 4 => Set["four"], 5 => Set["three"] }
- end
-end
diff --git a/spec/ruby/library/set/clear_spec.rb b/spec/ruby/library/set/clear_spec.rb
deleted file mode 100644
index 2b1c9c5b5a..0000000000
--- a/spec/ruby/library/set/clear_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-
-describe "Set#clear" do
- before :each do
- @set = Set["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)
- end
-end
diff --git a/spec/ruby/library/set/collect_spec.rb b/spec/ruby/library/set/collect_spec.rb
deleted file mode 100644
index f8813a9331..0000000000
--- a/spec/ruby/library/set/collect_spec.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-require_relative 'shared/collect'
-
-describe "Set#collect!" do
- it_behaves_like :set_collect_bang, :collect!
-end
diff --git a/spec/ruby/library/set/compare_by_identity_spec.rb b/spec/ruby/library/set/compare_by_identity_spec.rb
deleted file mode 100644
index 602d1e758e..0000000000
--- a/spec/ruby/library/set/compare_by_identity_spec.rb
+++ /dev/null
@@ -1,143 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-
-describe "Set#compare_by_identity" do
- it "compares its members by identity" do
- a = "a"
- b1 = "b"
- b2 = b1.dup
-
- set = Set.new
- set.compare_by_identity
- set.merge([a, a, b1, b2])
- set.to_a.sort.should == [a, b1, b2].sort
- end
-
- it "causes future comparisons on the receiver to be made by identity" do
- elt = [1]
- set = Set.new
- set << elt
- set.member?(elt.dup).should be_true
- set.compare_by_identity
- set.member?(elt.dup).should be_false
- end
-
- it "rehashes internally so that old members can be looked up" do
- set = Set.new
- (1..10).each { |k| set << k }
- o = Object.new
- def o.hash; 123; end
- set << o
- set.compare_by_identity
- set.member?(o).should be_true
- end
-
- it "returns self" do
- set = Set.new
- result = set.compare_by_identity
- result.should equal(set)
- end
-
- it "is idempotent and has no effect on an already compare_by_identity set" do
- set = Set.new.compare_by_identity
- set << :foo
- set.compare_by_identity.should equal(set)
- set.should.compare_by_identity?
- set.to_a.should == [:foo]
- end
-
- it "uses the semantics of BasicObject#equal? to determine members identity" do
- :a.equal?(:a).should == true
- Set.new.compare_by_identity.merge([:a, :a]).to_a.should == [:a]
-
- ary1 = [1]
- ary2 = [1]
- ary1.equal?(ary2).should == false
- Set.new.compare_by_identity.merge([ary1, ary2]).to_a.sort.should == [ary1, ary2].sort
- end
-
- it "uses #equal? semantics, but doesn't actually call #equal? to determine identity" do
- set = Set.new.compare_by_identity
- obj = mock("equal")
- obj.should_not_receive(:equal?)
- set << :foo
- set << obj
- set.to_a.should == [:foo, obj]
- end
-
- it "does not call #hash on members" do
- elt = mock("element")
- elt.should_not_receive(:hash)
- set = Set.new.compare_by_identity
- set << elt
- set.member?(elt).should be_true
- end
-
- it "regards #dup'd objects as having different identities" do
- a1 = "a"
- a2 = a1.dup
-
- set = Set.new.compare_by_identity
- set.merge([a1, a2])
- set.to_a.sort.should == [a1, a2].sort
- end
-
- it "regards #clone'd objects as having different identities" do
- a1 = "a"
- a2 = a1.clone
-
- set = Set.new.compare_by_identity
- set.merge([a1, a2])
- set.to_a.sort.should == [a1, a2].sort
- end
-
- it "raises a FrozenError on frozen sets" do
- set = Set.new.freeze
- -> {
- set.compare_by_identity
- }.should raise_error(FrozenError, /frozen Hash/)
- end
-
- it "persists over #dups" do
- set = Set.new.compare_by_identity
- set << :a
- set_dup = set.dup
- set_dup.should == set
- set_dup << :a
- set_dup.to_a.should == [:a]
- end
-
- it "persists over #clones" do
- set = Set.new.compare_by_identity
- set << :a
- set_clone = set.clone
- set_clone.should == set
- set_clone << :a
- set_clone.to_a.should == [:a]
- end
-
- it "is not equal to set what does not compare by identity" do
- Set.new([1, 2]).should == Set.new([1, 2])
- Set.new([1, 2]).should_not == Set.new([1, 2]).compare_by_identity
- end
-end
-
-describe "Set#compare_by_identity?" do
- it "returns false by default" do
- 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.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.should.compare_by_identity?
- set.should.compare_by_identity?
- set.should.compare_by_identity?
- end
-end
diff --git a/spec/ruby/library/set/comparison_spec.rb b/spec/ruby/library/set/comparison_spec.rb
deleted file mode 100644
index ddcfbae0af..0000000000
--- a/spec/ruby/library/set/comparison_spec.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-
-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
diff --git a/spec/ruby/library/set/constructor_spec.rb b/spec/ruby/library/set/constructor_spec.rb
deleted file mode 100644
index bb84861514..0000000000
--- a/spec/ruby/library/set/constructor_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-
-describe "Set[]" do
- it "returns a new Set populated with the passed Objects" do
- set = Set[1, 2, 3]
-
- set.instance_of?(Set).should be_true
- set.size.should eql(3)
-
- set.should include(1)
- set.should include(2)
- set.should include(3)
- end
-end
diff --git a/spec/ruby/library/set/delete_if_spec.rb b/spec/ruby/library/set/delete_if_spec.rb
deleted file mode 100644
index 33caeeaab7..0000000000
--- a/spec/ruby/library/set/delete_if_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-
-describe "Set#delete_if" do
- before :each do
- @set = Set["one", "two", "three"]
- end
-
- it "yields every element of self" do
- ret = []
- @set.delete_if { |x| ret << x }
- ret.sort.should == ["one", "two", "three"].sort
- 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)
-
- @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)
-
- enum.each { |x| x.size == 3 }
-
- @set.should_not include("one")
- @set.should_not include("two")
- @set.should include("three")
- end
-end
diff --git a/spec/ruby/library/set/delete_spec.rb b/spec/ruby/library/set/delete_spec.rb
deleted file mode 100644
index b12524384a..0000000000
--- a/spec/ruby/library/set/delete_spec.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-
-describe "Set#delete" do
- before :each do
- @set = Set["a", "b", "c"]
- end
-
- it "deletes the passed Object from self" do
- @set.delete("a")
- @set.should_not include("a")
- end
-
- it "returns self" do
- @set.delete("a").should equal(@set)
- @set.delete("x").should equal(@set)
- end
-end
-
-describe "Set#delete?" do
- before :each do
- @set = Set["a", "b", "c"]
- 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
- end
-end
diff --git a/spec/ruby/library/set/difference_spec.rb b/spec/ruby/library/set/difference_spec.rb
deleted file mode 100644
index 422f2ed3c7..0000000000
--- a/spec/ruby/library/set/difference_spec.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-require_relative 'shared/difference'
-
-describe "Set#difference" do
- it_behaves_like :set_difference, :difference
-end
diff --git a/spec/ruby/library/set/disjoint_spec.rb b/spec/ruby/library/set/disjoint_spec.rb
deleted file mode 100644
index ea3b141455..0000000000
--- a/spec/ruby/library/set/disjoint_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/set_like'
-require 'set'
-
-describe "Set#disjoint?" do
- it "returns false when two Sets have at least one element in common" do
- Set[1, 2].disjoint?(Set[2, 3]).should == false
- end
-
- it "returns true when two Sets have no element in common" do
- Set[1, 2].disjoint?(Set[3, 4]).should == true
- end
-
- context "when comparing to a Set-like object" do
- it "returns false when a Set has at least one element in common with a Set-like object" do
- Set[1, 2].disjoint?(SetSpecs::SetLike.new([2, 3])).should be_false
- end
-
- it "returns true when a Set has no element in common with a Set-like object" do
- Set[1, 2].disjoint?(SetSpecs::SetLike.new([3, 4])).should be_true
- end
- end
-end
diff --git a/spec/ruby/library/set/divide_spec.rb b/spec/ruby/library/set/divide_spec.rb
deleted file mode 100644
index 998a1b292c..0000000000
--- a/spec/ruby/library/set/divide_spec.rb
+++ /dev/null
@@ -1,59 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-
-describe "Set#divide" do
- it "divides self into a set of subsets based on the blocks return values" do
- set = Set["one", "two", "three", "four", "five"].divide { |x| x.length }
- set.map { |x| x.to_a.sort }.sort.should == [["five", "four"], ["one", "two"], ["three"]]
- end
-
- it "yields each Object to the block" do
- ret = []
- Set["one", "two", "three", "four", "five"].divide { |x| ret << x }
- ret.sort.should == ["five", "four", "one", "three", "two"]
- end
-
- it "returns an enumerator when not passed a block" do
- ret = Set[1, 2, 3, 4].divide
- ret.should be_kind_of(Enumerator)
- ret.each(&:even?).should == Set[Set[1, 3], Set[2, 4]]
- end
-end
-
-describe "Set#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 = Set[1, 3, 4, 6, 9, 10, 11].divide { |x, y| (x - y).abs == 1 }
- set.map{ |x| x.to_a.sort }.sort.should == [[1], [3, 4], [6], [9, 10, 11]]
- end
-
- it "yields each two Object to the block" do
- ret = []
- Set[1, 2].divide { |x, y| ret << [x, y] }
- ret.sort.should == [[1, 1], [1, 2], [2, 1], [2, 2]]
- end
-
- it "returns an enumerator when not passed a block" do
- ret = Set[1, 2, 3, 4].divide
- ret.should be_kind_of(Enumerator)
- ret.each { |a, b| (a + b).even? }.should == Set[Set[1, 3], Set[2, 4]]
- end
-end
-
-describe "Set#divide when passed a block with an arity of > 2" do
- it "only uses the first element if the arity > 2" do
- set = Set["one", "two", "three", "four", "five"].divide do |x, y, z|
- y.should be_nil
- z.should be_nil
- x.length
- end
- set.map { |x| x.to_a.sort }.sort.should == [["five", "four"], ["one", "two"], ["three"]]
- end
-
- it "only uses the first element if the arity = -1" do
- set = Set["one", "two", "three", "four", "five"].divide do |*xs|
- xs.size.should == 1
- xs.first.length
- end
- set.map { |x| x.to_a.sort }.sort.should == [["five", "four"], ["one", "two"], ["three"]]
- end
-end
diff --git a/spec/ruby/library/set/each_spec.rb b/spec/ruby/library/set/each_spec.rb
deleted file mode 100644
index 44e185a4da..0000000000
--- a/spec/ruby/library/set/each_spec.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-
-describe "Set#each" do
- before :each do
- @set = Set[1, 2, 3]
- end
-
- it "yields each Object in self" do
- ret = []
- @set.each { |x| ret << x }
- ret.sort.should == [1, 2, 3]
- 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
- enum.should be_an_instance_of(Enumerator)
-
- ret = []
- enum.each { |x| ret << x }
- ret.sort.should == [1, 2, 3]
- end
-end
diff --git a/spec/ruby/library/set/empty_spec.rb b/spec/ruby/library/set/empty_spec.rb
deleted file mode 100644
index 1789a664c7..0000000000
--- a/spec/ruby/library/set/empty_spec.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-
-describe "Set#empty?" do
- it "returns true if self is empty" do
- Set[].empty?.should be_true
- Set[1].empty?.should be_false
- Set[1,2,3].empty?.should be_false
- end
-end
diff --git a/spec/ruby/library/set/enumerable/to_set_spec.rb b/spec/ruby/library/set/enumerable/to_set_spec.rb
deleted file mode 100644
index b2d850515b..0000000000
--- a/spec/ruby/library/set/enumerable/to_set_spec.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-require_relative '../../../spec_helper'
-require 'set'
-
-describe "Enumerable#to_set" do
- it "returns a new Set created from self" do
- [1, 2, 3].to_set.should == Set[1, 2, 3]
- {a: 1, b: 2}.to_set.should == Set[[:b, 2], [:a, 1]]
- end
-
- it "passes down passed blocks" do
- [1, 2, 3].to_set { |x| x * x }.should == Set[1, 4, 9]
- end
-end
diff --git a/spec/ruby/library/set/eql_spec.rb b/spec/ruby/library/set/eql_spec.rb
deleted file mode 100644
index dd8e633775..0000000000
--- a/spec/ruby/library/set/eql_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-
-describe "Set#eql?" do
- it "returns true when the passed argument is a Set and contains the same elements" do
- Set[].should eql(Set[])
- Set[1, 2, 3].should eql(Set[1, 2, 3])
- Set[1, 2, 3].should eql(Set[3, 2, 1])
- Set["a", :b, ?c].should eql(Set[?c, :b, "a"])
-
- Set[1, 2, 3].should_not eql(Set[1.0, 2, 3])
- Set[1, 2, 3].should_not eql(Set[2, 3])
- Set[1, 2, 3].should_not eql(Set[])
- end
-end
diff --git a/spec/ruby/library/set/equal_value_spec.rb b/spec/ruby/library/set/equal_value_spec.rb
deleted file mode 100644
index f5b5f790c0..0000000000
--- a/spec/ruby/library/set/equal_value_spec.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/set_like'
-require 'set'
-
-describe "Set#==" do
- it "returns true when the passed Object is a Set and self and the Object contain the same elements" do
- Set[].should == Set[]
- Set[1, 2, 3].should == Set[1, 2, 3]
- Set["1", "2", "3"].should == Set["1", "2", "3"]
-
- Set[1, 2, 3].should_not == Set[1.0, 2, 3]
- Set[1, 2, 3].should_not == [1, 2, 3]
- end
-
- it "does not depend on the order of the elements" do
- Set[1, 2, 3].should == Set[3, 2, 1]
- Set[:a, "b", ?c].should == Set[?c, "b", :a]
- end
-
- it "does not depend on the order of nested Sets" do
- Set[Set[1], Set[2], Set[3]].should == Set[Set[3], Set[2], Set[1]]
-
- set1 = Set[Set["a", "b"], Set["c", "d"], Set["e", "f"]]
- set2 = Set[Set["c", "d"], Set["a", "b"], Set["e", "f"]]
- set1.should == set2
- end
-
- context "when comparing to a Set-like object" do
- it "returns true when a Set and a Set-like object contain the same elements" do
- Set[1, 2, 3].should == SetSpecs::SetLike.new([1, 2, 3])
- end
- end
-end
diff --git a/spec/ruby/library/set/exclusion_spec.rb b/spec/ruby/library/set/exclusion_spec.rb
deleted file mode 100644
index 5bc4b5a2bf..0000000000
--- a/spec/ruby/library/set/exclusion_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-
-describe "Set#^" do
- before :each do
- @set = Set[1, 2, 3, 4]
- end
-
- it "returns a new Set containing elements that are not in both self and the passed Enumerable" do
- (@set ^ Set[3, 4, 5]).should == Set[1, 2, 5]
- (@set ^ [3, 4, 5]).should == Set[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)
- end
-end
diff --git a/spec/ruby/library/set/fixtures/set_like.rb b/spec/ruby/library/set/fixtures/set_like.rb
deleted file mode 100644
index 46f61a451e..0000000000
--- a/spec/ruby/library/set/fixtures/set_like.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-require 'set'
-
-module SetSpecs
- # This class is used to test the interaction of "Set-like" objects with real Sets
- #
- # These "Set-like" objects reply to is_a?(Set) with true and thus real Set objects are able to transparently
- # interoperate with them in a duck-typing manner.
- class SetLike
- include Enumerable
-
- def is_a?(klass)
- super || klass == ::Set
- end
-
- def initialize(entries)
- @entries = entries
- end
-
- def each(&block)
- @entries.each(&block)
- end
-
- def inspect
- "#<#{self.class}: {#{map(&:inspect).join(", ")}}>"
- end
-
- def size
- @entries.size
- end
- end
-end
diff --git a/spec/ruby/library/set/flatten_merge_spec.rb b/spec/ruby/library/set/flatten_merge_spec.rb
deleted file mode 100644
index f2c99a9481..0000000000
--- a/spec/ruby/library/set/flatten_merge_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-
-describe "Set#flatten_merge" do
- it "is protected" do
- Set.should have_protected_instance_method("flatten_merge")
- end
-
- it "flattens the passed Set and merges it into self" do
- set1 = Set[1, 2]
- set2 = Set[3, 4, Set[5, 6]]
-
- set1.send(:flatten_merge, set2).should == Set[1, 2, 3, 4, 5, 6]
- end
-
- it "raises an ArgumentError when trying to flatten a recursive Set" do
- set1 = Set[1, 2, 3]
- set2 = Set[5, 6, 7]
- set2 << set2
-
- -> { set1.send(:flatten_merge, set2) }.should raise_error(ArgumentError)
- end
-end
diff --git a/spec/ruby/library/set/flatten_spec.rb b/spec/ruby/library/set/flatten_spec.rb
deleted file mode 100644
index 51b58d6439..0000000000
--- a/spec/ruby/library/set/flatten_spec.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/set_like'
-require 'set'
-set_version = defined?(Set::VERSION) ? Set::VERSION : '1.0.0'
-
-describe "Set#flatten" do
- it "returns a copy of self with each included Set flattened" do
- set = Set[1, 2, Set[3, 4, Set[5, 6, Set[7, 8]]], 9, 10]
- flattened_set = set.flatten
-
- flattened_set.should_not equal(set)
- flattened_set.should == Set[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
- end
-
- it "raises an ArgumentError when self is recursive" do
- (set = Set[]) << set
- -> { set.flatten }.should raise_error(ArgumentError)
- end
-
- context "when Set contains a Set-like object" do
- it "returns a copy of self with each included Set-like object flattened" do
- Set[SetSpecs::SetLike.new([1])].flatten.should == Set[1]
- end
- end
-end
-
-describe "Set#flatten!" do
- it "flattens self" do
- set = Set[1, 2, Set[3, 4, Set[5, 6, Set[7, 8]]], 9, 10]
- set.flatten!
- set.should == Set[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
- end
-
- it "returns self when self was modified" do
- set = Set[1, 2, Set[3, 4]]
- set.flatten!.should equal(set)
- end
-
- it "returns nil when self was not modified" do
- set = Set[1, 2, 3, 4]
- set.flatten!.should be_nil
- end
-
- it "raises an ArgumentError when self is recursive" do
- (set = Set[]) << set
- -> { set.flatten! }.should raise_error(ArgumentError)
- end
-
- version_is(set_version, ""..."1.1.0") do #ruby_version_is ""..."3.3" do
- context "when Set contains a Set-like object" do
- it "flattens self, including Set-like objects" do
- Set[SetSpecs::SetLike.new([1])].flatten!.should == Set[1]
- end
- end
- end
-end
diff --git a/spec/ruby/library/set/hash_spec.rb b/spec/ruby/library/set/hash_spec.rb
deleted file mode 100644
index 47c43c05f1..0000000000
--- a/spec/ruby/library/set/hash_spec.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-
-describe "Set#hash" do
- it "is static" do
- Set[].hash.should == Set[].hash
- Set[1, 2, 3].hash.should == Set[1, 2, 3].hash
- Set[:a, "b", ?c].hash.should == Set[?c, "b", :a].hash
-
- Set[].hash.should_not == Set[1, 2, 3].hash
- Set[1, 2, 3].hash.should_not == Set[:a, "b", ?c].hash
- end
-end
diff --git a/spec/ruby/library/set/include_spec.rb b/spec/ruby/library/set/include_spec.rb
deleted file mode 100644
index 68532d9a04..0000000000
--- a/spec/ruby/library/set/include_spec.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'shared/include'
-require 'set'
-
-describe "Set#include?" do
- it_behaves_like :set_include, :include?
-end
diff --git a/spec/ruby/library/set/initialize_clone_spec.rb b/spec/ruby/library/set/initialize_clone_spec.rb
deleted file mode 100644
index bda42cd6e8..0000000000
--- a/spec/ruby/library/set/initialize_clone_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-
-describe "Set#initialize_clone" 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
diff --git a/spec/ruby/library/set/initialize_spec.rb b/spec/ruby/library/set/initialize_spec.rb
deleted file mode 100644
index 76ebc0a20a..0000000000
--- a/spec/ruby/library/set/initialize_spec.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-
-describe "Set#initialize" do
- it "is private" do
- Set.should have_private_instance_method(:initialize)
- end
-
- it "adds all elements of the passed Enumerable to self" do
- s = Set.new([1, 2, 3])
- s.size.should eql(3)
- s.should include(1)
- s.should include(2)
- 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)
-
- s = Set.new({})
- s.size.should eql(0)
- end
-
- it "preprocesses all elements by a passed block before adding to self" do
- s = Set.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 "should initialize with empty array and block" do
- s = Set.new([]) { |x| x * x }
- s.size.should eql(0)
- end
-
- it "should initialize with empty set and block" do
- s = Set.new(Set.new) { |x| x * x }
- s.size.should eql(0)
- end
-
- it "should initialize with just block" do
- s = Set.new { |x| x * x }
- s.size.should eql(0)
- s.should eql(Set.new)
- end
-end
diff --git a/spec/ruby/library/set/inspect_spec.rb b/spec/ruby/library/set/inspect_spec.rb
deleted file mode 100644
index 4060c63b95..0000000000
--- a/spec/ruby/library/set/inspect_spec.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'shared/inspect'
-require 'set'
-
-describe "Set#inspect" do
- it_behaves_like :set_inspect, :inspect
-end
diff --git a/spec/ruby/library/set/intersect_spec.rb b/spec/ruby/library/set/intersect_spec.rb
deleted file mode 100644
index e60f06db94..0000000000
--- a/spec/ruby/library/set/intersect_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/set_like'
-require 'set'
-
-describe "Set#intersect?" do
- it "returns true when two Sets have at least one element in common" do
- Set[1, 2].intersect?(Set[2, 3]).should == true
- end
-
- it "returns false when two Sets have no element in common" do
- Set[1, 2].intersect?(Set[3, 4]).should == false
- end
-
- context "when comparing to a Set-like object" do
- it "returns true when a Set has at least one element in common with a Set-like object" do
- Set[1, 2].intersect?(SetSpecs::SetLike.new([2, 3])).should be_true
- end
-
- it "returns false when a Set has no element in common with a Set-like object" do
- Set[1, 2].intersect?(SetSpecs::SetLike.new([3, 4])).should be_false
- end
- end
-end
diff --git a/spec/ruby/library/set/intersection_spec.rb b/spec/ruby/library/set/intersection_spec.rb
deleted file mode 100644
index 792c2d8f07..0000000000
--- a/spec/ruby/library/set/intersection_spec.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'shared/intersection'
-require 'set'
-
-describe "Set#intersection" do
- it_behaves_like :set_intersection, :intersection
-end
-
-describe "Set#&" do
- it_behaves_like :set_intersection, :&
-end
diff --git a/spec/ruby/library/set/join_spec.rb b/spec/ruby/library/set/join_spec.rb
deleted file mode 100644
index 3f511a84e4..0000000000
--- a/spec/ruby/library/set/join_spec.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-
-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
diff --git a/spec/ruby/library/set/keep_if_spec.rb b/spec/ruby/library/set/keep_if_spec.rb
deleted file mode 100644
index 7edc80769f..0000000000
--- a/spec/ruby/library/set/keep_if_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-
-describe "Set#keep_if" do
- before :each do
- @set = Set["one", "two", "three"]
- end
-
- it "yields every element of self" do
- ret = []
- @set.keep_if { |x| ret << x }
- ret.sort.should == ["one", "two", "three"].sort
- end
-
- it "keeps every element from self for which the passed block returns true" do
- @set.keep_if { |x| x.size != 3 }
- @set.size.should eql(1)
-
- @set.should_not include("one")
- @set.should_not include("two")
- @set.should include("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)
-
- enum.each { |x| x.size != 3 }
-
- @set.should_not include("one")
- @set.should_not include("two")
- @set.should include("three")
- end
-end
diff --git a/spec/ruby/library/set/length_spec.rb b/spec/ruby/library/set/length_spec.rb
deleted file mode 100644
index fef63d25a7..0000000000
--- a/spec/ruby/library/set/length_spec.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'shared/length'
-require 'set'
-
-describe "Set#length" do
- it_behaves_like :set_length, :length
-end
diff --git a/spec/ruby/library/set/map_spec.rb b/spec/ruby/library/set/map_spec.rb
deleted file mode 100644
index e60e98b179..0000000000
--- a/spec/ruby/library/set/map_spec.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-require_relative 'shared/collect'
-
-describe "Set#map!" do
- it_behaves_like :set_collect_bang, :map!
-end
diff --git a/spec/ruby/library/set/member_spec.rb b/spec/ruby/library/set/member_spec.rb
deleted file mode 100644
index 5b56a38ab9..0000000000
--- a/spec/ruby/library/set/member_spec.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'shared/include'
-require 'set'
-
-describe "Set#member?" do
- it_behaves_like :set_include, :member?
-end
diff --git a/spec/ruby/library/set/merge_spec.rb b/spec/ruby/library/set/merge_spec.rb
deleted file mode 100644
index a8e3ffc870..0000000000
--- a/spec/ruby/library/set/merge_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-
-describe "Set#merge" do
- it "adds the elements of the passed Enumerable to self" do
- Set[:a, :b].merge(Set[:b, :c, :d]).should == Set[:a, :b, :c, :d]
- Set[1, 2].merge([3, 4]).should == Set[1, 2, 3, 4]
- end
-
- it "returns self" do
- set = Set[1, 2]
- set.merge([3, 4]).should equal(set)
- end
-
- it "raises an ArgumentError when passed a non-Enumerable" do
- -> { Set[1, 2].merge(1) }.should raise_error(ArgumentError)
- -> { Set[1, 2].merge(Object.new) }.should raise_error(ArgumentError)
- end
-end
diff --git a/spec/ruby/library/set/minus_spec.rb b/spec/ruby/library/set/minus_spec.rb
deleted file mode 100644
index 3fe0b6a2cc..0000000000
--- a/spec/ruby/library/set/minus_spec.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-require_relative 'shared/difference'
-
-describe "Set#-" do
- it_behaves_like :set_difference, :-
-end
diff --git a/spec/ruby/library/set/plus_spec.rb b/spec/ruby/library/set/plus_spec.rb
deleted file mode 100644
index 3e70d3269d..0000000000
--- a/spec/ruby/library/set/plus_spec.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'shared/union'
-require 'set'
-
-describe "Set#+" do
- it_behaves_like :set_union, :+
-end
diff --git a/spec/ruby/library/set/pretty_print_cycle_spec.rb b/spec/ruby/library/set/pretty_print_cycle_spec.rb
deleted file mode 100644
index 4f440353e5..0000000000
--- a/spec/ruby/library/set/pretty_print_cycle_spec.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-
-describe "Set#pretty_print_cycle" do
- it "passes the 'pretty print' representation of a self-referencing Set to the pretty print writer" do
- pp = mock("PrettyPrint")
- pp.should_receive(:text).with("#<Set: {...}>")
- Set[1, 2, 3].pretty_print_cycle(pp)
- end
-end
diff --git a/spec/ruby/library/set/pretty_print_spec.rb b/spec/ruby/library/set/pretty_print_spec.rb
deleted file mode 100644
index ea9ead0df8..0000000000
--- a/spec/ruby/library/set/pretty_print_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-
-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("#<Set: {")
- pp.should_receive(:text).with("}>")
-
- pp.should_receive(:nest).with(1).and_yield
- pp.should_receive(:seplist).with(set)
-
- set.pretty_print(pp)
- end
- end
-end
diff --git a/spec/ruby/library/set/proper_subset_spec.rb b/spec/ruby/library/set/proper_subset_spec.rb
deleted file mode 100644
index 6b51dedc9f..0000000000
--- a/spec/ruby/library/set/proper_subset_spec.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/set_like'
-require 'set'
-set_version = defined?(Set::VERSION) ? Set::VERSION : '1.0.0'
-
-describe "Set#proper_subset?" do
- before :each do
- @set = Set[1, 2, 3, 4]
- end
-
- it "returns true if passed a Set that self is a proper subset of" do
- Set[].proper_subset?(@set).should be_true
- Set[].proper_subset?(Set[1, 2, 3]).should be_true
- Set[].proper_subset?(Set["a", :b, ?c]).should be_true
-
- Set[1, 2, 3].proper_subset?(@set).should be_true
- Set[1, 3].proper_subset?(@set).should be_true
- Set[1, 2].proper_subset?(@set).should be_true
- Set[1].proper_subset?(@set).should be_true
-
- Set[5].proper_subset?(@set).should be_false
- Set[1, 5].proper_subset?(@set).should be_false
- Set[nil].proper_subset?(@set).should be_false
- Set["test"].proper_subset?(@set).should be_false
-
- @set.proper_subset?(@set).should be_false
- Set[].proper_subset?(Set[]).should be_false
- end
-
- it "raises an ArgumentError when passed a non-Set" do
- -> { Set[].proper_subset?([]) }.should raise_error(ArgumentError)
- -> { Set[].proper_subset?(1) }.should raise_error(ArgumentError)
- -> { Set[].proper_subset?("test") }.should raise_error(ArgumentError)
- -> { Set[].proper_subset?(Object.new) }.should raise_error(ArgumentError)
- end
-
- version_is(set_version, ""..."1.1.0") do #ruby_version_is ""..."3.3" do
- context "when comparing to a Set-like object" do
- it "returns true if passed a Set-like object that self is a proper subset of" do
- Set[1, 2, 3].proper_subset?(SetSpecs::SetLike.new([1, 2, 3, 4])).should be_true
- end
- end
- end
-end
diff --git a/spec/ruby/library/set/proper_superset_spec.rb b/spec/ruby/library/set/proper_superset_spec.rb
deleted file mode 100644
index a386c8c097..0000000000
--- a/spec/ruby/library/set/proper_superset_spec.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/set_like'
-require 'set'
-
-describe "Set#proper_superset?" do
- before :each do
- @set = Set[1, 2, 3, 4]
- end
-
- it "returns true if passed a Set that self is a proper superset of" do
- @set.proper_superset?(Set[]).should be_true
- Set[1, 2, 3].proper_superset?(Set[]).should be_true
- Set["a", :b, ?c].proper_superset?(Set[]).should be_true
-
- @set.proper_superset?(Set[1, 2, 3]).should be_true
- @set.proper_superset?(Set[1, 3]).should be_true
- @set.proper_superset?(Set[1, 2]).should be_true
- @set.proper_superset?(Set[1]).should be_true
-
- @set.proper_superset?(Set[5]).should be_false
- @set.proper_superset?(Set[1, 5]).should be_false
- @set.proper_superset?(Set[nil]).should be_false
- @set.proper_superset?(Set["test"]).should be_false
-
- @set.proper_superset?(@set).should be_false
- Set[].proper_superset?(Set[]).should be_false
- end
-
- it "raises an ArgumentError when passed a non-Set" do
- -> { Set[].proper_superset?([]) }.should raise_error(ArgumentError)
- -> { Set[].proper_superset?(1) }.should raise_error(ArgumentError)
- -> { Set[].proper_superset?("test") }.should raise_error(ArgumentError)
- -> { Set[].proper_superset?(Object.new) }.should raise_error(ArgumentError)
- end
-
- context "when comparing to a Set-like object" do
- it "returns true if passed a Set-like object that self is a proper superset of" do
- Set[1, 2, 3, 4].proper_superset?(SetSpecs::SetLike.new([1, 2, 3])).should be_true
- end
- end
-end
diff --git a/spec/ruby/library/set/reject_spec.rb b/spec/ruby/library/set/reject_spec.rb
deleted file mode 100644
index 9131f960ad..0000000000
--- a/spec/ruby/library/set/reject_spec.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-
-describe "Set#reject!" do
- before :each do
- @set = Set["one", "two", "three"]
- end
-
- it "yields every element of self" do
- ret = []
- @set.reject! { |x| ret << x }
- ret.sort.should == ["one", "two", "three"].sort
- 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)
-
- @set.should_not include("one")
- @set.should_not include("two")
- @set.should include("three")
- 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)
-
- enum.each { |x| x.size == 3 }
-
- @set.should_not include("one")
- @set.should_not include("two")
- @set.should include("three")
- end
-end
diff --git a/spec/ruby/library/set/replace_spec.rb b/spec/ruby/library/set/replace_spec.rb
deleted file mode 100644
index 7511066c9c..0000000000
--- a/spec/ruby/library/set/replace_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-
-describe "Set#replace" do
- before :each do
- @set = Set[:a, :b, :c]
- end
-
- it "replaces the contents with other and returns self" do
- @set.replace(Set[1, 2, 3]).should == @set
- @set.should == Set[1, 2, 3]
- end
-
- it "accepts any enumerable as other" do
- @set.replace([1, 2, 3]).should == Set[1, 2, 3]
- end
-end
diff --git a/spec/ruby/library/set/set_spec.rb b/spec/ruby/library/set/set_spec.rb
deleted file mode 100644
index 2a4edc6dfc..0000000000
--- a/spec/ruby/library/set/set_spec.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-require_relative '../../spec_helper'
-
-describe 'Set' do
- ruby_version_is '3.2' do
- it 'is available without explicit requiring' do
- output = ruby_exe(<<~RUBY, options: '--disable-gems', args: '2>&1')
- puts Set.new([1, 2, 3])
- RUBY
- output.chomp.should == "#<Set: {1, 2, 3}>"
- end
- end
-end
diff --git a/spec/ruby/library/set/shared/inspect.rb b/spec/ruby/library/set/shared/inspect.rb
deleted file mode 100644
index adb6ddb4c9..0000000000
--- a/spec/ruby/library/set/shared/inspect.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-describe :set_inspect, shared: true do
- it "returns a String representation of self" do
- Set[].send(@method).should be_kind_of(String)
- Set[nil, false, true].send(@method).should be_kind_of(String)
- Set[1, 2, 3].send(@method).should be_kind_of(String)
- Set["1", "2", "3"].send(@method).should be_kind_of(String)
- Set[:a, "b", Set[?c]].send(@method).should be_kind_of(String)
- end
-
- it "does include the elements of the set" do
- Set["1"].send(@method).should == '#<Set: {"1"}>'
- end
-
- it "puts spaces between the elements" do
- Set["1", "2"].send(@method).should include('", "')
- end
-
- it "correctly handles cyclic-references" do
- set1 = Set[]
- set2 = Set[set1]
- set1 << set2
- set1.send(@method).should be_kind_of(String)
- set1.send(@method).should include("#<Set: {...}>")
- end
-end
diff --git a/spec/ruby/library/set/shared/select.rb b/spec/ruby/library/set/shared/select.rb
deleted file mode 100644
index 2108d398b4..0000000000
--- a/spec/ruby/library/set/shared/select.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-require_relative '../../../spec_helper'
-require 'set'
-
-describe :set_select_bang, shared: true do
- before :each do
- @set = Set["one", "two", "three"]
- end
-
- it "yields every element of self" do
- ret = []
- @set.send(@method) { |x| ret << x }
- ret.sort.should == ["one", "two", "three"].sort
- end
-
- it "keeps every element from self for which the passed block returns true" do
- @set.send(@method) { |x| x.size != 3 }
- @set.size.should eql(1)
-
- @set.should_not include("one")
- @set.should_not include("two")
- @set.should include("three")
- end
-
- it "returns self when self was modified" do
- @set.send(@method) { false }.should equal(@set)
- end
-
- it "returns nil when self was not modified" do
- @set.send(@method) { true }.should be_nil
- end
-
- it "returns an Enumerator when passed no block" do
- enum = @set.send(@method)
- enum.should be_an_instance_of(Enumerator)
-
- enum.each { |x| x.size != 3 }
-
- @set.should_not include("one")
- @set.should_not include("two")
- @set.should include("three")
- end
-end
diff --git a/spec/ruby/library/set/size_spec.rb b/spec/ruby/library/set/size_spec.rb
deleted file mode 100644
index 3c8cb38517..0000000000
--- a/spec/ruby/library/set/size_spec.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'shared/length'
-require 'set'
-
-describe "Set#size" do
- it_behaves_like :set_length, :size
-end
diff --git a/spec/ruby/library/set/sortedset/sortedset_spec.rb b/spec/ruby/library/set/sortedset/sortedset_spec.rb
deleted file mode 100644
index 67993dee29..0000000000
--- a/spec/ruby/library/set/sortedset/sortedset_spec.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-require_relative '../../../spec_helper'
-require 'set'
-
-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
diff --git a/spec/ruby/library/set/subset_spec.rb b/spec/ruby/library/set/subset_spec.rb
deleted file mode 100644
index 85666d633f..0000000000
--- a/spec/ruby/library/set/subset_spec.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/set_like'
-require 'set'
-set_version = defined?(Set::VERSION) ? Set::VERSION : '1.0.0'
-
-describe "Set#subset?" do
- before :each do
- @set = Set[1, 2, 3, 4]
- end
-
- it "returns true if passed a Set that is equal to self or self is a subset of" do
- @set.subset?(@set).should be_true
- Set[].subset?(Set[]).should be_true
-
- Set[].subset?(@set).should be_true
- Set[].subset?(Set[1, 2, 3]).should be_true
- Set[].subset?(Set["a", :b, ?c]).should be_true
-
- Set[1, 2, 3].subset?(@set).should be_true
- Set[1, 3].subset?(@set).should be_true
- Set[1, 2].subset?(@set).should be_true
- Set[1].subset?(@set).should be_true
-
- Set[5].subset?(@set).should be_false
- Set[1, 5].subset?(@set).should be_false
- Set[nil].subset?(@set).should be_false
- Set["test"].subset?(@set).should be_false
- end
-
- it "raises an ArgumentError when passed a non-Set" do
- -> { Set[].subset?([]) }.should raise_error(ArgumentError)
- -> { Set[].subset?(1) }.should raise_error(ArgumentError)
- -> { Set[].subset?("test") }.should raise_error(ArgumentError)
- -> { Set[].subset?(Object.new) }.should raise_error(ArgumentError)
- end
-
- version_is(set_version, ""..."1.1.0") do #ruby_version_is ""..."3.3" do
- context "when comparing to a Set-like object" do
- it "returns true if passed a Set-like object that self is a subset of" do
- Set[1, 2, 3].subset?(SetSpecs::SetLike.new([1, 2, 3, 4])).should be_true
- end
- end
- end
-end
diff --git a/spec/ruby/library/set/subtract_spec.rb b/spec/ruby/library/set/subtract_spec.rb
deleted file mode 100644
index 56713de8b3..0000000000
--- a/spec/ruby/library/set/subtract_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-
-describe "Set#subtract" do
- before :each do
- @set = Set[:a, :b, :c]
- end
-
- it "deletes any elements contained in other and returns self" do
- @set.subtract(Set[:b, :c]).should == @set
- @set.should == Set[:a]
- end
-
- it "accepts any enumerable as other" do
- @set.subtract([:c]).should == Set[:a, :b]
- end
-end
diff --git a/spec/ruby/library/set/superset_spec.rb b/spec/ruby/library/set/superset_spec.rb
deleted file mode 100644
index bd9d2f3eee..0000000000
--- a/spec/ruby/library/set/superset_spec.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'fixtures/set_like'
-require 'set'
-
-describe "Set#superset?" do
- before :each do
- @set = Set[1, 2, 3, 4]
- end
-
- it "returns true if passed a Set that equals self or self is a proper superset of" do
- @set.superset?(@set).should be_true
- Set[].superset?(Set[]).should be_true
-
- @set.superset?(Set[]).should be_true
- Set[1, 2, 3].superset?(Set[]).should be_true
- Set["a", :b, ?c].superset?(Set[]).should be_true
-
- @set.superset?(Set[1, 2, 3]).should be_true
- @set.superset?(Set[1, 3]).should be_true
- @set.superset?(Set[1, 2]).should be_true
- @set.superset?(Set[1]).should be_true
-
- @set.superset?(Set[5]).should be_false
- @set.superset?(Set[1, 5]).should be_false
- @set.superset?(Set[nil]).should be_false
- @set.superset?(Set["test"]).should be_false
- end
-
- it "raises an ArgumentError when passed a non-Set" do
- -> { Set[].superset?([]) }.should raise_error(ArgumentError)
- -> { Set[].superset?(1) }.should raise_error(ArgumentError)
- -> { Set[].superset?("test") }.should raise_error(ArgumentError)
- -> { Set[].superset?(Object.new) }.should raise_error(ArgumentError)
- end
-
- context "when comparing to a Set-like object" do
- it "returns true if passed a Set-like object that self is a superset of" do
- Set[1, 2, 3, 4].superset?(SetSpecs::SetLike.new([1, 2, 3])).should be_true
- end
- end
-end
diff --git a/spec/ruby/library/set/to_a_spec.rb b/spec/ruby/library/set/to_a_spec.rb
deleted file mode 100644
index 689e44f38a..0000000000
--- a/spec/ruby/library/set/to_a_spec.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-require_relative '../../spec_helper'
-require 'set'
-
-describe "Set#to_a" do
- it "returns an array containing elements of self" do
- Set[1, 2, 3].to_a.sort.should == [1, 2, 3]
- end
-end
diff --git a/spec/ruby/library/set/to_s_spec.rb b/spec/ruby/library/set/to_s_spec.rb
deleted file mode 100644
index 3c26ae9346..0000000000
--- a/spec/ruby/library/set/to_s_spec.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-require_relative "../../spec_helper"
-require_relative 'shared/inspect'
-require 'set'
-
-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
-end
diff --git a/spec/ruby/library/set/union_spec.rb b/spec/ruby/library/set/union_spec.rb
deleted file mode 100644
index 20fe0ddca3..0000000000
--- a/spec/ruby/library/set/union_spec.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'shared/union'
-require 'set'
-
-describe "Set#union" do
- it_behaves_like :set_union, :union
-end
-
-describe "Set#|" do
- it_behaves_like :set_union, :|
-end
diff --git a/spec/ruby/library/socket/addrinfo/afamily_spec.rb b/spec/ruby/library/socket/addrinfo/afamily_spec.rb
index 7229dab9de..5d075be057 100644
--- a/spec/ruby/library/socket/addrinfo/afamily_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/afamily_spec.rb
@@ -23,15 +23,13 @@ describe "Addrinfo#afamily" do
end
end
- with_feature :unix_socket do
- describe "for a unix socket" do
- before :each do
- @addrinfo = Addrinfo.unix("/tmp/sock")
- end
-
- it "returns Socket::AF_UNIX" do
- @addrinfo.afamily.should == Socket::AF_UNIX
- end
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns Socket::AF_UNIX" do
+ @addrinfo.afamily.should == Socket::AF_UNIX
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/family_addrinfo_spec.rb b/spec/ruby/library/socket/addrinfo/family_addrinfo_spec.rb
index 2bc3b6a2e3..3c2f9f73d8 100644
--- a/spec/ruby/library/socket/addrinfo/family_addrinfo_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/family_addrinfo_spec.rb
@@ -50,38 +50,36 @@ describe 'Addrinfo#family_addrinfo' do
end
end
- with_feature :unix_socket do
- describe 'with a UNIX Addrinfo' do
- before do
- @source = Addrinfo.unix('cats')
- end
+ describe 'with a UNIX Addrinfo' do
+ before do
+ @source = Addrinfo.unix('cats')
+ end
- it 'raises ArgumentError if more than 1 argument is given' do
- -> { @source.family_addrinfo('foo', 'bar') }.should raise_error(ArgumentError)
- end
+ it 'raises ArgumentError if more than 1 argument is given' do
+ -> { @source.family_addrinfo('foo', 'bar') }.should raise_error(ArgumentError)
+ end
- it 'returns an Addrinfo when a UNIX socket path is given' do
- addr = @source.family_addrinfo('dogs')
+ it 'returns an Addrinfo when a UNIX socket path is given' do
+ addr = @source.family_addrinfo('dogs')
- addr.should be_an_instance_of(Addrinfo)
- end
+ addr.should be_an_instance_of(Addrinfo)
+ end
- describe 'the returned Addrinfo' do
- before do
- @addr = @source.family_addrinfo('dogs')
- end
+ describe 'the returned Addrinfo' do
+ before do
+ @addr = @source.family_addrinfo('dogs')
+ end
- it 'uses AF_UNIX as the address family' do
- @addr.afamily.should == Socket::AF_UNIX
- 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 PF_UNIX as the protocol family' do
+ @addr.pfamily.should == Socket::PF_UNIX
+ end
- it 'uses the given socket path' do
- @addr.unix_path.should == 'dogs'
- end
+ it 'uses the given socket path' do
+ @addr.unix_path.should == 'dogs'
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/getaddrinfo_spec.rb b/spec/ruby/library/socket/addrinfo/getaddrinfo_spec.rb
index 67fad73815..e05fe9967a 100644
--- a/spec/ruby/library/socket/addrinfo/getaddrinfo_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/getaddrinfo_spec.rb
@@ -73,19 +73,15 @@ describe 'Addrinfo.getaddrinfo' do
end
end
- platform_is_not :'solaris2.10' do # i386-solaris
- it 'sets a custom socket protocol of the Addrinfo instances' do
- array = Addrinfo.getaddrinfo('127.0.0.1', 80, nil, nil, Socket::IPPROTO_UDP)
+ it 'sets a custom socket protocol of the Addrinfo instances' do
+ array = Addrinfo.getaddrinfo('127.0.0.1', 80, nil, nil, Socket::IPPROTO_UDP)
- array[0].protocol.should == Socket::IPPROTO_UDP
- end
+ array[0].protocol.should == Socket::IPPROTO_UDP
end
- platform_is_not :solaris do
- it 'sets the canonical name when AI_CANONNAME is given as a flag' do
- array = Addrinfo.getaddrinfo('localhost', 80, nil, nil, nil, Socket::AI_CANONNAME)
+ it 'sets the canonical name when AI_CANONNAME is given as a flag' do
+ array = Addrinfo.getaddrinfo('localhost', 80, nil, nil, nil, Socket::AI_CANONNAME)
- array[0].canonname.should be_an_instance_of(String)
- end
+ array[0].canonname.should be_an_instance_of(String)
end
end
diff --git a/spec/ruby/library/socket/addrinfo/getnameinfo_spec.rb b/spec/ruby/library/socket/addrinfo/getnameinfo_spec.rb
index 76579de74c..43b5a2000a 100644
--- a/spec/ruby/library/socket/addrinfo/getnameinfo_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/getnameinfo_spec.rb
@@ -22,19 +22,17 @@ describe 'Addrinfo#getnameinfo' do
platform_is :linux do
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
+ 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'
- end
+ host.should == @host
+ path.should == 'cats'
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/initialize_spec.rb b/spec/ruby/library/socket/addrinfo/initialize_spec.rb
index 83b204b575..1f16531aaa 100644
--- a/spec/ruby/library/socket/addrinfo/initialize_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/initialize_spec.rb
@@ -17,7 +17,7 @@ describe "Addrinfo#initialize" do
@addrinfo.ip_port.should == 25
end
- it "returns the Socket::UNSPEC pfamily" do
+ it "returns the UNSPEC pfamily" do
@addrinfo.pfamily.should == Socket::PF_UNSPEC
end
@@ -53,7 +53,7 @@ describe "Addrinfo#initialize" do
@addrinfo.ip_port.should == 25
end
- it "returns the Socket::UNSPEC pfamily" do
+ it "returns the INET6 pfamily" do
@addrinfo.pfamily.should == Socket::PF_INET6
end
@@ -83,7 +83,7 @@ describe "Addrinfo#initialize" do
@addrinfo.ip_port.should == 25
end
- it "returns the Socket::UNSPEC pfamily" do
+ it "returns the INET6 pfamily" do
@addrinfo.pfamily.should == Socket::PF_INET6
end
@@ -113,7 +113,7 @@ describe "Addrinfo#initialize" do
@addrinfo.ip_port.should == 25
end
- it "returns the Socket::UNSPEC pfamily" do
+ it "returns the INET6 pfamily" do
@addrinfo.pfamily.should == Socket::PF_INET6
end
@@ -147,11 +147,11 @@ describe "Addrinfo#initialize" do
@addrinfo.ip_port.should == 46102
end
- it "returns the Socket::PF_INET pfamily" do
+ it "returns the INET pfamily" do
@addrinfo.pfamily.should == Socket::PF_INET
end
- it "returns the INET6 afamily" do
+ it "returns the INET afamily" do
@addrinfo.afamily.should == Socket::AF_INET
end
@@ -217,11 +217,11 @@ describe "Addrinfo#initialize" do
@addrinfo.ip_port.should == 46102
end
- it "returns the Socket::UNSPEC pfamily" do
+ it "returns the INET pfamily" do
@addrinfo.pfamily.should == Socket::PF_INET
end
- it "returns the INET6 afamily" do
+ it "returns the INET afamily" do
@addrinfo.afamily.should == Socket::AF_INET
end
@@ -247,11 +247,11 @@ describe "Addrinfo#initialize" do
@addrinfo.ip_port.should == 46102
end
- it "returns the Socket::UNSPEC pfamily" do
+ it "returns the INET pfamily" do
@addrinfo.pfamily.should == Socket::PF_INET
end
- it "returns the INET6 afamily" do
+ it "returns the INET afamily" do
@addrinfo.afamily.should == Socket::AF_INET
end
@@ -311,11 +311,11 @@ describe "Addrinfo#initialize" do
@addrinfo.ip_port.should == 46102
end
- it "returns the Socket::UNSPEC pfamily" do
+ it "returns the INET pfamily" do
@addrinfo.pfamily.should == Socket::PF_INET
end
- it "returns the INET6 afamily" do
+ it "returns the INET afamily" do
@addrinfo.afamily.should == Socket::AF_INET
end
@@ -335,7 +335,7 @@ describe "Addrinfo#initialize" do
@sockaddr = ['AF_INET6', 80, 'hostname', '127.0.0.1']
end
- it "raises SocketError when using any Socket constant except except AF_INET(6)/PF_INET(6)" do
+ it "raises SocketError when using any Socket constant except AF_INET(6)/PF_INET(6)" do
Socket.constants.grep(/(^AF_|^PF_)(?!INET)/).each do |constant|
value = Socket.const_get(constant)
-> {
@@ -362,7 +362,7 @@ describe "Addrinfo#initialize" do
end
end
- platform_is_not :windows, :aix, :solaris do
+ platform_is_not :windows, :aix do
(Socket.constants.grep(/^IPPROTO/) - valid).each do |type|
it "raises SocketError when using #{type}" do
value = Socket.const_get(type)
@@ -390,7 +390,7 @@ describe "Addrinfo#initialize" do
end
end
- platform_is_not :windows, :aix, :solaris do
+ platform_is_not :windows, :aix do
(Socket.constants.grep(/^IPPROTO/) - valid).each do |type|
it "raises SocketError when using #{type}" do
value = Socket.const_get(type)
@@ -495,7 +495,7 @@ describe "Addrinfo#initialize" do
end
end
- platform_is_not :windows, :aix, :solaris do
+ platform_is_not :windows, :aix do
(Socket.constants.grep(/^IPPROTO/) - valid).each do |type|
it "raises SocketError when using #{type}" do
value = Socket.const_get(type)
@@ -514,13 +514,13 @@ describe "Addrinfo#initialize" do
@sockaddr = Socket.sockaddr_in(80, '127.0.0.1')
end
- it 'returns an Addrinfo with :PF_INET family' do
+ it 'returns an Addrinfo with :PF_INET family' do
addr = Addrinfo.new(@sockaddr, :PF_INET)
addr.pfamily.should == Socket::PF_INET
end
- it 'returns an Addrinfo with :INET family' do
+ it 'returns an Addrinfo with :INET family' do
addr = Addrinfo.new(@sockaddr, :INET)
addr.pfamily.should == Socket::PF_INET
@@ -544,13 +544,13 @@ describe "Addrinfo#initialize" do
@sockaddr = Socket.sockaddr_in(80, '127.0.0.1')
end
- it 'returns an Addrinfo with "PF_INET" family' do
+ it 'returns an Addrinfo with "PF_INET" family' do
addr = Addrinfo.new(@sockaddr, 'PF_INET')
addr.pfamily.should == Socket::PF_INET
end
- it 'returns an Addrinfo with "INET" family' do
+ it 'returns an Addrinfo with "INET" family' do
addr = Addrinfo.new(@sockaddr, 'INET')
addr.pfamily.should == Socket::PF_INET
@@ -569,23 +569,21 @@ describe "Addrinfo#initialize" do
end
end
- with_feature :unix_socket do
- describe 'using separate arguments for a Unix socket' do
- before do
- @sockaddr = Socket.pack_sockaddr_un('socket')
- end
+ describe 'using separate arguments for a Unix socket' do
+ before do
+ @sockaddr = Socket.pack_sockaddr_un('socket')
+ end
- it 'returns an Addrinfo with the correct unix path' do
- Addrinfo.new(@sockaddr).unix_path.should == 'socket'
- end
+ it 'returns an Addrinfo with the correct unix path' do
+ Addrinfo.new(@sockaddr).unix_path.should == 'socket'
+ end
- it 'returns an Addrinfo with the correct protocol family' do
- Addrinfo.new(@sockaddr).pfamily.should == Socket::PF_UNSPEC
- end
+ it 'returns an Addrinfo with the correct protocol family' do
+ Addrinfo.new(@sockaddr).pfamily.should == Socket::PF_UNSPEC
+ end
- it 'returns an Addrinfo with the correct address family' do
- Addrinfo.new(@sockaddr).afamily.should == Socket::AF_UNIX
- end
+ it 'returns an Addrinfo with the correct address family' do
+ Addrinfo.new(@sockaddr).afamily.should == Socket::AF_UNIX
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/inspect_sockaddr_spec.rb b/spec/ruby/library/socket/addrinfo/inspect_sockaddr_spec.rb
index 70ca4dd4d7..6b18c79469 100644
--- a/spec/ruby/library/socket/addrinfo/inspect_sockaddr_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/inspect_sockaddr_spec.rb
@@ -32,19 +32,17 @@ describe 'Addrinfo#inspect_sockaddr' do
end
end
- with_feature :unix_socket do
- describe 'using a UNIX path' do
- it 'returns a String containing the UNIX path' do
- addr = Addrinfo.unix('/foo/bar')
+ describe 'using a UNIX path' do
+ it 'returns a String containing the UNIX path' do
+ addr = Addrinfo.unix('/foo/bar')
- addr.inspect_sockaddr.should == '/foo/bar'
- end
+ addr.inspect_sockaddr.should == '/foo/bar'
+ end
- it 'returns a String containing the UNIX path when using a relative path' do
- addr = Addrinfo.unix('foo')
+ it 'returns a String containing the UNIX path when using a relative path' do
+ addr = Addrinfo.unix('foo')
- addr.inspect_sockaddr.should == 'UNIX foo'
- end
+ addr.inspect_sockaddr.should == 'UNIX foo'
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/inspect_spec.rb b/spec/ruby/library/socket/addrinfo/inspect_spec.rb
index 98e1e83ffa..1442af6162 100644
--- a/spec/ruby/library/socket/addrinfo/inspect_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/inspect_spec.rb
@@ -41,25 +41,23 @@ describe 'Addrinfo#inspect' do
end
end
- with_feature :unix_socket do
- describe 'using a UNIX Addrinfo' do
- it 'returns a String' do
- addr = Addrinfo.unix('/foo')
+ describe 'using a UNIX Addrinfo' do
+ it 'returns a String' do
+ addr = Addrinfo.unix('/foo')
- addr.inspect.should == '#<Addrinfo: /foo SOCK_STREAM>'
- end
+ addr.inspect.should == '#<Addrinfo: /foo SOCK_STREAM>'
+ end
- it 'returns a String when using a relative UNIX path' do
- addr = Addrinfo.unix('foo')
+ it 'returns a String when using a relative UNIX path' do
+ addr = Addrinfo.unix('foo')
- addr.inspect.should == '#<Addrinfo: UNIX foo SOCK_STREAM>'
- end
+ addr.inspect.should == '#<Addrinfo: UNIX foo SOCK_STREAM>'
+ end
- it 'returns a String when using a DGRAM socket' do
- addr = Addrinfo.unix('/foo', Socket::SOCK_DGRAM)
+ it 'returns a String when using a DGRAM socket' do
+ addr = Addrinfo.unix('/foo', Socket::SOCK_DGRAM)
- addr.inspect.should == '#<Addrinfo: /foo SOCK_DGRAM>'
- end
+ addr.inspect.should == '#<Addrinfo: /foo SOCK_DGRAM>'
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/ip_address_spec.rb b/spec/ruby/library/socket/addrinfo/ip_address_spec.rb
index 4522cf5cfd..193432e861 100644
--- a/spec/ruby/library/socket/addrinfo/ip_address_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ip_address_spec.rb
@@ -21,15 +21,13 @@ describe "Addrinfo#ip_address" do
end
end
- with_feature :unix_socket do
- describe "for a unix socket" do
- before :each do
- @addrinfo = Addrinfo.unix("/tmp/sock")
- end
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
- it "raises an exception" do
- -> { @addrinfo.ip_address }.should raise_error(SocketError)
- end
+ it "raises an exception" do
+ -> { @addrinfo.ip_address }.should raise_error(SocketError)
end
end
diff --git a/spec/ruby/library/socket/addrinfo/ip_port_spec.rb b/spec/ruby/library/socket/addrinfo/ip_port_spec.rb
index 4118607db0..f10ce35143 100644
--- a/spec/ruby/library/socket/addrinfo/ip_port_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ip_port_spec.rb
@@ -21,15 +21,13 @@ describe "Addrinfo#ip_port" do
end
end
- with_feature :unix_socket do
- describe "for a unix socket" do
- before :each do
- @addrinfo = Addrinfo.unix("/tmp/sock")
- end
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
- it "raises an exception" do
- -> { @addrinfo.ip_port }.should raise_error(SocketError)
- end
+ it "raises an exception" do
+ -> { @addrinfo.ip_port }.should raise_error(SocketError)
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/ip_spec.rb b/spec/ruby/library/socket/addrinfo/ip_spec.rb
index 80e7a62df7..09b9341605 100644
--- a/spec/ruby/library/socket/addrinfo/ip_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ip_spec.rb
@@ -22,15 +22,13 @@ describe "Addrinfo#ip?" do
end
end
- with_feature :unix_socket do
- describe "for a unix socket" do
- before :each do
- @addrinfo = Addrinfo.unix("/tmp/sock")
- end
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
- it "returns false" do
- @addrinfo.ip?.should be_false
- end
+ it "returns false" do
+ @addrinfo.ip?.should be_false
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/ip_unpack_spec.rb b/spec/ruby/library/socket/addrinfo/ip_unpack_spec.rb
index 6c81c48d1c..58260c4557 100644
--- a/spec/ruby/library/socket/addrinfo/ip_unpack_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ip_unpack_spec.rb
@@ -21,15 +21,13 @@ describe "Addrinfo#ip_unpack" do
end
end
- with_feature :unix_socket do
- describe "for a unix socket" do
- before :each do
- @addrinfo = Addrinfo.unix("/tmp/sock")
- end
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
- it "raises an exception" do
- -> { @addrinfo.ip_unpack }.should raise_error(SocketError)
- end
+ it "raises an exception" do
+ -> { @addrinfo.ip_unpack }.should raise_error(SocketError)
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/ipv4_loopback_spec.rb b/spec/ruby/library/socket/addrinfo/ipv4_loopback_spec.rb
index 10ad084fc9..3a584d4f52 100644
--- a/spec/ruby/library/socket/addrinfo/ipv4_loopback_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ipv4_loopback_spec.rb
@@ -29,15 +29,13 @@ describe "Addrinfo#ipv4_loopback?" do
end
end
- with_feature :unix_socket do
- describe "for a unix socket" do
- before :each do
- @addrinfo = Addrinfo.unix("/tmp/sock")
- end
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
- it "returns false" do
- @addrinfo.ipv4_loopback?.should be_false
- end
+ it "returns false" do
+ @addrinfo.ipv4_loopback?.should be_false
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/ipv4_multicast_spec.rb b/spec/ruby/library/socket/addrinfo/ipv4_multicast_spec.rb
index f7fead8640..e4b4cfcc84 100644
--- a/spec/ruby/library/socket/addrinfo/ipv4_multicast_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ipv4_multicast_spec.rb
@@ -15,15 +15,13 @@ describe "Addrinfo#ipv4_multicast?" do
Addrinfo.ip('::1').should_not.ipv4_multicast?
end
- with_feature :unix_socket do
- describe "for a unix socket" do
- before :each do
- @addrinfo = Addrinfo.unix("/tmp/sock")
- end
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
- it "returns false" do
- @addrinfo.ipv4_multicast?.should be_false
- end
+ it "returns false" do
+ @addrinfo.ipv4_multicast?.should be_false
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/ipv4_private_spec.rb b/spec/ruby/library/socket/addrinfo/ipv4_private_spec.rb
index e5a33b4953..97218b5ba3 100644
--- a/spec/ruby/library/socket/addrinfo/ipv4_private_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ipv4_private_spec.rb
@@ -33,15 +33,13 @@ describe "Addrinfo#ipv4_private?" do
end
end
- with_feature :unix_socket do
- describe "for a unix socket" do
- before :each do
- @addrinfo = Addrinfo.unix("/tmp/sock")
- end
-
- it "returns false" do
- @addrinfo.ipv4_private?.should be_false
- end
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns false" do
+ @addrinfo.ipv4_private?.should be_false
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/ipv4_spec.rb b/spec/ruby/library/socket/addrinfo/ipv4_spec.rb
index 7cba8209b6..61f7759b10 100644
--- a/spec/ruby/library/socket/addrinfo/ipv4_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ipv4_spec.rb
@@ -21,15 +21,13 @@ describe "Addrinfo#ipv4?" do
end
end
- with_feature :unix_socket do
- describe "for a unix socket" do
- before :each do
- @addrinfo = Addrinfo.unix("/tmp/sock")
- end
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
- it "returns false" do
- @addrinfo.ipv4?.should be_false
- end
+ it "returns false" do
+ @addrinfo.ipv4?.should be_false
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/ipv6_loopback_spec.rb b/spec/ruby/library/socket/addrinfo/ipv6_loopback_spec.rb
index 9ff8f107bf..ffc75185ea 100644
--- a/spec/ruby/library/socket/addrinfo/ipv6_loopback_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ipv6_loopback_spec.rb
@@ -31,15 +31,13 @@ describe "Addrinfo#ipv6_loopback?" do
end
end
- with_feature :unix_socket do
- describe "for a unix socket" do
- before :each do
- @addrinfo = Addrinfo.unix("/tmp/sock")
- end
-
- it "returns false" do
- @addrinfo.ipv6_loopback?.should be_false
- end
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns false" do
+ @addrinfo.ipv6_loopback?.should be_false
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/ipv6_multicast_spec.rb b/spec/ruby/library/socket/addrinfo/ipv6_multicast_spec.rb
index 2c987b5921..99d4e8cf4d 100644
--- a/spec/ruby/library/socket/addrinfo/ipv6_multicast_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ipv6_multicast_spec.rb
@@ -34,15 +34,13 @@ describe "Addrinfo#ipv6_multicast?" do
end
end
- with_feature :unix_socket do
- describe "for a unix socket" do
- before :each do
- @addrinfo = Addrinfo.unix("/tmp/sock")
- end
-
- it "returns false" do
- @addrinfo.ipv6_multicast?.should be_false
- end
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns false" do
+ @addrinfo.ipv6_multicast?.should be_false
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/ipv6_spec.rb b/spec/ruby/library/socket/addrinfo/ipv6_spec.rb
index 131e38849c..436d5e930b 100644
--- a/spec/ruby/library/socket/addrinfo/ipv6_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ipv6_spec.rb
@@ -21,15 +21,13 @@ describe "Addrinfo#ipv6?" do
end
end
- with_feature :unix_socket do
- describe "for a unix socket" do
- before :each do
- @addrinfo = Addrinfo.unix("/tmp/sock")
- end
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
- it "returns false" do
- @addrinfo.ipv6?.should be_false
- end
+ it "returns false" do
+ @addrinfo.ipv6?.should be_false
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/ipv6_to_ipv4_spec.rb b/spec/ruby/library/socket/addrinfo/ipv6_to_ipv4_spec.rb
index 6dfaf531ae..29050bec20 100644
--- a/spec/ruby/library/socket/addrinfo/ipv6_to_ipv4_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/ipv6_to_ipv4_spec.rb
@@ -62,7 +62,7 @@ guard -> { SocketSpecs.ipv6_available? } do
Addrinfo.ip('192.168.1.1').ipv6_to_ipv4.should be_nil
end
- with_feature :unix_socket do
+ describe 'for a unix socket' do
it 'returns nil for a UNIX Addrinfo' do
Addrinfo.unix('foo').ipv6_to_ipv4.should be_nil
end
diff --git a/spec/ruby/library/socket/addrinfo/marshal_dump_spec.rb b/spec/ruby/library/socket/addrinfo/marshal_dump_spec.rb
index c4220a6f3e..e2c3497f7f 100644
--- a/spec/ruby/library/socket/addrinfo/marshal_dump_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/marshal_dump_spec.rb
@@ -32,10 +32,8 @@ describe 'Addrinfo#marshal_dump' do
@array[3].should == 'SOCK_STREAM'
end
- platform_is_not :'solaris2.10' do # i386-solaris
- it 'includes the protocol as the 5th value' do
- @array[4].should == 'IPPROTO_TCP'
- end
+ it 'includes the protocol as the 5th value' do
+ @array[4].should == 'IPPROTO_TCP'
end
it 'includes the canonical name as the 6th value' do
@@ -44,40 +42,38 @@ describe 'Addrinfo#marshal_dump' do
end
end
- with_feature :unix_socket do
- describe 'using a UNIX Addrinfo' do
+ describe 'using a UNIX Addrinfo' do
+ before do
+ @addr = Addrinfo.unix('foo')
+ end
+
+ it 'returns an Array' do
+ @addr.marshal_dump.should be_an_instance_of(Array)
+ end
+
+ describe 'the returned Array' do
before do
- @addr = Addrinfo.unix('foo')
+ @array = @addr.marshal_dump
end
- it 'returns an Array' do
- @addr.marshal_dump.should be_an_instance_of(Array)
+ it 'includes the address family as the 1st value' do
+ @array[0].should == 'AF_UNIX'
end
- describe 'the returned Array' do
- before do
- @array = @addr.marshal_dump
- end
-
- it 'includes the address family as the 1st value' do
- @array[0].should == 'AF_UNIX'
- end
-
- it 'includes the UNIX path as the 2nd value' do
- @array[1].should == @addr.unix_path
- end
+ it 'includes the UNIX path as the 2nd value' do
+ @array[1].should == @addr.unix_path
+ end
- it 'includes the protocol family as the 3rd value' do
- @array[2].should == 'PF_UNIX'
- end
+ it 'includes the protocol family as the 3rd value' do
+ @array[2].should == 'PF_UNIX'
+ end
- it 'includes the socket type as the 4th value' do
- @array[3].should == 'SOCK_STREAM'
- end
+ it 'includes the socket type as the 4th value' do
+ @array[3].should == 'SOCK_STREAM'
+ end
- it 'includes the protocol as the 5th value' do
- @array[4].should == 0
- end
+ it 'includes the protocol as the 5th value' do
+ @array[4].should == 0
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/marshal_load_spec.rb b/spec/ruby/library/socket/addrinfo/marshal_load_spec.rb
index aa20865224..02cef90115 100644
--- a/spec/ruby/library/socket/addrinfo/marshal_load_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/marshal_load_spec.rb
@@ -18,18 +18,16 @@ describe 'Addrinfo#marshal_load' do
end
end
- with_feature :unix_socket do
- describe 'using a UNIX socket' do
- it 'returns a new Addrinfo' do
- source = Addrinfo.unix('foo')
- addr = Marshal.load(Marshal.dump(source))
+ describe 'using a UNIX socket' do
+ it 'returns a new Addrinfo' do
+ source = Addrinfo.unix('foo')
+ addr = Marshal.load(Marshal.dump(source))
- addr.afamily.should == source.afamily
- addr.pfamily.should == source.pfamily
- addr.socktype.should == source.socktype
- addr.protocol.should == source.protocol
- addr.unix_path.should == source.unix_path
- end
+ addr.afamily.should == source.afamily
+ addr.pfamily.should == source.pfamily
+ addr.socktype.should == source.socktype
+ addr.protocol.should == source.protocol
+ addr.unix_path.should == source.unix_path
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/pfamily_spec.rb b/spec/ruby/library/socket/addrinfo/pfamily_spec.rb
index 984744a964..da530b7fdc 100644
--- a/spec/ruby/library/socket/addrinfo/pfamily_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/pfamily_spec.rb
@@ -29,15 +29,13 @@ describe "Addrinfo#pfamily" do
end
end
- with_feature :unix_socket do
- describe "for a unix socket" do
- before :each do
- @addrinfo = Addrinfo.unix("/tmp/sock")
- end
-
- it "returns Socket::PF_UNIX" do
- @addrinfo.pfamily.should == Socket::PF_UNIX
- end
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns Socket::PF_UNIX" do
+ @addrinfo.pfamily.should == Socket::PF_UNIX
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/protocol_spec.rb b/spec/ruby/library/socket/addrinfo/protocol_spec.rb
index ea143fc4a8..f6ffc9acf9 100644
--- a/spec/ruby/library/socket/addrinfo/protocol_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/protocol_spec.rb
@@ -10,15 +10,13 @@ describe "Addrinfo#protocol" do
Addrinfo.tcp('::1', 80).protocol.should == Socket::IPPROTO_TCP
end
- with_feature :unix_socket do
- describe "for a unix socket" do
- before :each do
- @addrinfo = Addrinfo.unix("/tmp/sock")
- end
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
- it "returns 0" do
- @addrinfo.protocol.should == 0
- end
+ it "returns 0" do
+ @addrinfo.protocol.should == 0
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/shared/to_sockaddr.rb b/spec/ruby/library/socket/addrinfo/shared/to_sockaddr.rb
index 4f7cf439a0..70d6bfbbfe 100644
--- a/spec/ruby/library/socket/addrinfo/shared/to_sockaddr.rb
+++ b/spec/ruby/library/socket/addrinfo/shared/to_sockaddr.rb
@@ -19,15 +19,13 @@ describe :socket_addrinfo_to_sockaddr, shared: true do
end
end
- with_feature :unix_socket do
- describe "for a unix socket" do
- before :each do
- @addrinfo = Addrinfo.unix("/tmp/sock")
- end
-
- it "returns a sockaddr packed structure" do
- @addrinfo.send(@method).should == Socket.sockaddr_un('/tmp/sock')
- end
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
+
+ it "returns a sockaddr packed structure" do
+ @addrinfo.send(@method).should == Socket.sockaddr_un('/tmp/sock')
end
end
diff --git a/spec/ruby/library/socket/addrinfo/socktype_spec.rb b/spec/ruby/library/socket/addrinfo/socktype_spec.rb
index b994bea140..e5f02cd759 100644
--- a/spec/ruby/library/socket/addrinfo/socktype_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/socktype_spec.rb
@@ -9,15 +9,13 @@ describe "Addrinfo#socktype" do
Addrinfo.tcp('127.0.0.1', 80).socktype.should == Socket::SOCK_STREAM
end
- with_feature :unix_socket do
- describe "for a unix socket" do
- before :each do
- @addrinfo = Addrinfo.unix("/tmp/sock")
- end
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
- it "returns Socket::SOCK_STREAM" do
- @addrinfo.socktype.should == Socket::SOCK_STREAM
- end
+ it "returns Socket::SOCK_STREAM" do
+ @addrinfo.socktype.should == Socket::SOCK_STREAM
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/udp_spec.rb b/spec/ruby/library/socket/addrinfo/udp_spec.rb
index b05cbf9b0b..ac02e76ef5 100644
--- a/spec/ruby/library/socket/addrinfo/udp_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/udp_spec.rb
@@ -27,10 +27,8 @@ describe 'Addrinfo.udp' do
Addrinfo.udp(ip_address, 80).socktype.should == Socket::SOCK_DGRAM
end
- platform_is_not :solaris do
- it 'sets the socket protocol' do
- Addrinfo.udp(ip_address, 80).protocol.should == Socket::IPPROTO_UDP
- end
+ it 'sets the socket protocol' do
+ Addrinfo.udp(ip_address, 80).protocol.should == Socket::IPPROTO_UDP
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/unix_path_spec.rb b/spec/ruby/library/socket/addrinfo/unix_path_spec.rb
index 6bfb56a4ac..2a9076a354 100644
--- a/spec/ruby/library/socket/addrinfo/unix_path_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/unix_path_spec.rb
@@ -1,37 +1,35 @@
require_relative '../spec_helper'
-with_feature :unix_socket do
- describe "Addrinfo#unix_path" do
- describe "for an ipv4 socket" do
+describe "Addrinfo#unix_path" do
+ describe "for an ipv4 socket" do
- before :each do
- @addrinfo = Addrinfo.tcp("127.0.0.1", 80)
- end
-
- it "raises an exception" do
- -> { @addrinfo.unix_path }.should raise_error(SocketError)
- end
+ before :each do
+ @addrinfo = Addrinfo.tcp("127.0.0.1", 80)
+ end
+ it "raises an exception" do
+ -> { @addrinfo.unix_path }.should raise_error(SocketError)
end
- describe "for an ipv6 socket" do
- before :each do
- @addrinfo = Addrinfo.tcp("::1", 80)
- end
+ end
- it "raises an exception" do
- -> { @addrinfo.unix_path }.should raise_error(SocketError)
- end
+ describe "for an ipv6 socket" do
+ before :each do
+ @addrinfo = Addrinfo.tcp("::1", 80)
end
- describe "for a unix socket" do
- before :each do
- @addrinfo = Addrinfo.unix("/tmp/sock")
- end
+ it "raises an exception" do
+ -> { @addrinfo.unix_path }.should raise_error(SocketError)
+ end
+ end
+
+ describe "for a unix socket" do
+ before :each do
+ @addrinfo = Addrinfo.unix("/tmp/sock")
+ end
- it "returns the socket path" do
- @addrinfo.unix_path.should == "/tmp/sock"
- end
+ it "returns the socket path" do
+ @addrinfo.unix_path.should == "/tmp/sock"
end
end
end
diff --git a/spec/ruby/library/socket/addrinfo/unix_spec.rb b/spec/ruby/library/socket/addrinfo/unix_spec.rb
index 4596ece17e..7597533a76 100644
--- a/spec/ruby/library/socket/addrinfo/unix_spec.rb
+++ b/spec/ruby/library/socket/addrinfo/unix_spec.rb
@@ -1,36 +1,34 @@
require_relative '../spec_helper'
-with_feature :unix_socket do
- describe 'Addrinfo.unix' do
- it 'returns an Addrinfo instance' do
- Addrinfo.unix('socket').should be_an_instance_of(Addrinfo)
- end
+describe 'Addrinfo.unix' do
+ it 'returns an Addrinfo instance' do
+ Addrinfo.unix('socket').should be_an_instance_of(Addrinfo)
+ end
- it 'sets the IP address' do
- Addrinfo.unix('socket').unix_path.should == 'socket'
- end
+ it 'sets the IP address' do
+ Addrinfo.unix('socket').unix_path.should == 'socket'
+ end
- it 'sets the address family' do
- Addrinfo.unix('socket').afamily.should == Socket::AF_UNIX
- end
+ it 'sets the address family' do
+ Addrinfo.unix('socket').afamily.should == Socket::AF_UNIX
+ end
- it 'sets the protocol family' do
- Addrinfo.unix('socket').pfamily.should == Socket::PF_UNIX
- end
+ it 'sets the protocol family' do
+ Addrinfo.unix('socket').pfamily.should == Socket::PF_UNIX
+ end
- it 'sets the socket type' do
- Addrinfo.unix('socket').socktype.should == Socket::SOCK_STREAM
- end
+ it 'sets the socket type' do
+ Addrinfo.unix('socket').socktype.should == Socket::SOCK_STREAM
+ end
- it 'sets a custom socket type' do
- addr = Addrinfo.unix('socket', Socket::SOCK_DGRAM)
+ it 'sets a custom socket type' do
+ addr = Addrinfo.unix('socket', Socket::SOCK_DGRAM)
- addr.socktype.should == Socket::SOCK_DGRAM
- end
+ addr.socktype.should == Socket::SOCK_DGRAM
+ end
- it 'sets the socket protocol to 0' do
- Addrinfo.unix('socket').protocol.should == 0
- end
+ it 'sets the socket protocol to 0' do
+ Addrinfo.unix('socket').protocol.should == 0
end
end
diff --git a/spec/ruby/library/socket/ancillarydata/initialize_spec.rb b/spec/ruby/library/socket/ancillarydata/initialize_spec.rb
index 344d1485c5..eca45599d7 100644
--- a/spec/ruby/library/socket/ancillarydata/initialize_spec.rb
+++ b/spec/ruby/library/socket/ancillarydata/initialize_spec.rb
@@ -106,7 +106,7 @@ with_feature :ancillary_data do
Socket::AncillaryData.new(:INET, :SOCKET, :RIGHTS, '').type.should == Socket::SCM_RIGHTS
end
- platform_is_not :"solaris2.10", :aix do
+ platform_is_not :aix do
it 'sets the type to SCM_TIMESTAMP when using :TIMESTAMP as the type argument' do
Socket::AncillaryData.new(:INET, :SOCKET, :TIMESTAMP, '').type.should == Socket::SCM_TIMESTAMP
end
diff --git a/spec/ruby/library/socket/ancillarydata/unix_rights_spec.rb b/spec/ruby/library/socket/ancillarydata/unix_rights_spec.rb
index 65ffcb01af..95052fd91c 100644
--- a/spec/ruby/library/socket/ancillarydata/unix_rights_spec.rb
+++ b/spec/ruby/library/socket/ancillarydata/unix_rights_spec.rb
@@ -50,7 +50,7 @@ with_feature :ancillary_data do
-> { data.unix_rights }.should raise_error(TypeError)
end
- platform_is_not :"solaris2.10", :aix do
+ platform_is_not :aix do
it 'raises TypeError when the type is not SCM_RIGHTS' do
data = Socket::AncillaryData.new(:INET, :SOCKET, :TIMESTAMP, '')
diff --git a/spec/ruby/library/socket/basicsocket/connect_address_spec.rb b/spec/ruby/library/socket/basicsocket/connect_address_spec.rb
index 1a1c9982d9..2e318fcb85 100644
--- a/spec/ruby/library/socket/basicsocket/connect_address_spec.rb
+++ b/spec/ruby/library/socket/basicsocket/connect_address_spec.rb
@@ -94,61 +94,59 @@ describe 'Socket#connect_address' do
end
end
- with_feature :unix_socket do
- platform_is_not :aix do
- describe 'using an unbound UNIX socket' do
- before do
- @path = SocketSpecs.socket_path
- @server = UNIXServer.new(@path)
- @client = UNIXSocket.new(@path)
- end
-
- after do
- @client.close
- @server.close
- rm_r(@path)
- end
-
- it 'raises SocketError' do
- -> { @client.connect_address }.should raise_error(SocketError)
- end
- end
- end
-
- describe 'using a bound UNIX socket' do
+ platform_is_not :aix do
+ describe 'using an unbound UNIX socket' do
before do
@path = SocketSpecs.socket_path
- @sock = UNIXServer.new(@path)
+ @server = UNIXServer.new(@path)
+ @client = UNIXSocket.new(@path)
end
after do
- @sock.close
+ @client.close
+ @server.close
rm_r(@path)
end
- it 'returns an Addrinfo' do
- @sock.connect_address.should be_an_instance_of(Addrinfo)
+ it 'raises SocketError' do
+ -> { @client.connect_address }.should raise_error(SocketError)
end
+ end
+ end
- it 'uses the correct socket path' do
- @sock.connect_address.unix_path.should == @path
- end
+ describe 'using a bound UNIX socket' do
+ before do
+ @path = SocketSpecs.socket_path
+ @sock = UNIXServer.new(@path)
+ end
- it 'uses AF_UNIX as the address family' do
- @sock.connect_address.afamily.should == Socket::AF_UNIX
- end
+ after do
+ @sock.close
+ rm_r(@path)
+ end
- it 'uses PF_UNIX as the protocol family' do
- @sock.connect_address.pfamily.should == Socket::PF_UNIX
- end
+ it 'returns an Addrinfo' do
+ @sock.connect_address.should be_an_instance_of(Addrinfo)
+ end
- it 'uses SOCK_STREAM as the socket type' do
- @sock.connect_address.socktype.should == Socket::SOCK_STREAM
- end
+ it 'uses the correct socket path' do
+ @sock.connect_address.unix_path.should == @path
+ end
- it 'uses 0 as the protocol' do
- @sock.connect_address.protocol.should == 0
- end
+ it 'uses AF_UNIX as the address family' do
+ @sock.connect_address.afamily.should == Socket::AF_UNIX
+ end
+
+ it 'uses PF_UNIX as the protocol family' do
+ @sock.connect_address.pfamily.should == Socket::PF_UNIX
+ end
+
+ it 'uses SOCK_STREAM as the socket type' do
+ @sock.connect_address.socktype.should == Socket::SOCK_STREAM
+ end
+
+ it 'uses 0 as the protocol' do
+ @sock.connect_address.protocol.should == 0
end
end
end
diff --git a/spec/ruby/library/socket/basicsocket/getpeereid_spec.rb b/spec/ruby/library/socket/basicsocket/getpeereid_spec.rb
index 6179211d96..2e03cd3684 100644
--- a/spec/ruby/library/socket/basicsocket/getpeereid_spec.rb
+++ b/spec/ruby/library/socket/basicsocket/getpeereid_spec.rb
@@ -2,7 +2,7 @@ require_relative '../spec_helper'
require_relative '../fixtures/classes'
describe 'BasicSocket#getpeereid' do
- with_feature :unix_socket do
+ platform_is_not :windows do
describe 'using a UNIXSocket' do
before do
@path = SocketSpecs.socket_path
diff --git a/spec/ruby/library/socket/basicsocket/recv_nonblock_spec.rb b/spec/ruby/library/socket/basicsocket/recv_nonblock_spec.rb
index df42c116fb..f2a6682f12 100644
--- a/spec/ruby/library/socket/basicsocket/recv_nonblock_spec.rb
+++ b/spec/ruby/library/socket/basicsocket/recv_nonblock_spec.rb
@@ -99,3 +99,74 @@ describe "Socket::BasicSocket#recv_nonblock" do
end
end
end
+
+describe "Socket::BasicSocket#recv_nonblock" do
+ context "when recvfrom(2) returns 0 (if no messages are available to be received and the peer has performed an orderly shutdown)" do
+ describe "stream socket" do
+ before :each do
+ @server = TCPServer.new('127.0.0.1', 0)
+ @port = @server.addr[1]
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ end
+
+ ruby_version_is ""..."3.3" do
+ it "returns an empty String on a closed stream socket" do
+ ready = false
+
+ t = Thread.new do
+ client = @server.accept
+
+ Thread.pass while !ready
+ begin
+ client.recv_nonblock(10)
+ rescue IO::EAGAINWaitReadable
+ retry
+ end
+ ensure
+ client.close if client
+ end
+
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ socket = TCPSocket.new('127.0.0.1', @port)
+ socket.close
+ ready = true
+
+ t.value.should == ""
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "returns nil on a closed stream socket" do
+ ready = false
+
+ t = Thread.new do
+ client = @server.accept
+
+ Thread.pass while !ready
+ begin
+ client.recv_nonblock(10)
+ rescue IO::EAGAINWaitReadable
+ retry
+ end
+ ensure
+ client.close if client
+ end
+
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ socket = TCPSocket.new('127.0.0.1', @port)
+ socket.close
+ ready = true
+
+ t.value.should be_nil
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/basicsocket/recv_spec.rb b/spec/ruby/library/socket/basicsocket/recv_spec.rb
index e82a357d3d..a51920f52a 100644
--- a/spec/ruby/library/socket/basicsocket/recv_spec.rb
+++ b/spec/ruby/library/socket/basicsocket/recv_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../spec_helper'
require_relative '../fixtures/classes'
@@ -32,47 +32,26 @@ describe "BasicSocket#recv" do
ScratchPad.recorded.should == 'hello'
end
- ruby_version_is "3.3" do
- it "returns nil on a closed stream socket" do
- t = Thread.new do
- client = @server.accept
- packet = client.recv(10)
- client.close
- packet
- end
-
- Thread.pass while t.status and t.status != "sleep"
- t.status.should_not be_nil
+ it "accepts flags to specify unusual receiving behaviour" do
+ t = Thread.new do
+ client = @server.accept
- socket = TCPSocket.new('127.0.0.1', @port)
- socket.close
+ # in-band data (TCP), doesn't receive the flag.
+ ScratchPad.record client.recv(10)
- t.value.should be_nil
+ # this recv is important (TODO: explain)
+ client.recv(10)
+ client.close
end
- end
-
- platform_is_not :solaris do
- it "accepts flags to specify unusual receiving behaviour" do
- t = Thread.new do
- client = @server.accept
-
- # in-band data (TCP), doesn't receive the flag.
- ScratchPad.record client.recv(10)
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
- # this recv is important (TODO: explain)
- client.recv(10)
- client.close
- end
- Thread.pass while t.status and t.status != "sleep"
- t.status.should_not be_nil
-
- socket = TCPSocket.new('127.0.0.1', @port)
- socket.send('helloU', Socket::MSG_OOB)
- socket.shutdown(1)
- t.join
- socket.close
- ScratchPad.recorded.should == 'hello'
- end
+ socket = TCPSocket.new('127.0.0.1', @port)
+ socket.send('helloU', Socket::MSG_OOB)
+ socket.shutdown(1)
+ t.join
+ socket.close
+ ScratchPad.recorded.should == 'hello'
end
it "gets lines delimited with a custom separator" do
@@ -192,3 +171,80 @@ describe 'BasicSocket#recv' do
end
end
end
+
+describe "BasicSocket#recv" do
+ context "when recvfrom(2) returns 0 (if no messages are available to be received and the peer has performed an orderly shutdown)" do
+ describe "stream socket" do
+ before :each do
+ @server = TCPServer.new('127.0.0.1', 0)
+ @port = @server.addr[1]
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ end
+
+ ruby_version_is ""..."3.3" do
+ it "returns an empty String on a closed stream socket" do
+ t = Thread.new do
+ client = @server.accept
+ client.recv(10)
+ ensure
+ client.close if client
+ end
+
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ socket = TCPSocket.new('127.0.0.1', @port)
+ socket.close
+
+ t.value.should == ""
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "returns nil on a closed stream socket" do
+ t = Thread.new do
+ client = @server.accept
+ client.recv(10)
+ ensure
+ client.close if client
+ end
+
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ socket = TCPSocket.new('127.0.0.1', @port)
+ socket.close
+
+ t.value.should be_nil
+ end
+ end
+ end
+
+ describe "datagram socket" do
+ SocketSpecs.each_ip_protocol do |family, ip_address|
+ before :each do
+ @server = UDPSocket.new(family)
+ @client = UDPSocket.new(family)
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ @client.close unless @client.closed?
+ end
+
+ it "returns empty String" do
+ @server.bind(ip_address, 0)
+ addr = @server.connect_address
+ @client.connect(addr.ip_address, addr.ip_port)
+
+ @client.send('', 0)
+
+ @server.recv(1).should == ""
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/basicsocket/recvmsg_nonblock_spec.rb b/spec/ruby/library/socket/basicsocket/recvmsg_nonblock_spec.rb
index cc4275c417..b5fdd7c93b 100644
--- a/spec/ruby/library/socket/basicsocket/recvmsg_nonblock_spec.rb
+++ b/spec/ruby/library/socket/basicsocket/recvmsg_nonblock_spec.rb
@@ -222,3 +222,79 @@ describe 'BasicSocket#recvmsg_nonblock' do
end
end
end
+
+describe 'BasicSocket#recvmsg_nonblock' do
+ context "when recvfrom(2) returns 0 (if no messages are available to be received and the peer has performed an orderly shutdown)" do
+ describe "stream socket" do
+ before :each do
+ @server = TCPServer.new('127.0.0.1', 0)
+ @port = @server.addr[1]
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ end
+
+ ruby_version_is ""..."3.3" do
+ platform_is_not :windows do # #recvmsg_nonblock() raises 'Errno::EINVAL: Invalid argument - recvmsg(2)'
+ it "returns an empty String as received data on a closed stream socket" do
+ ready = false
+
+ t = Thread.new do
+ client = @server.accept
+
+ Thread.pass while !ready
+ begin
+ client.recvmsg_nonblock(10)
+ rescue IO::EAGAINWaitReadable
+ retry
+ end
+ ensure
+ client.close if client
+ end
+
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ socket = TCPSocket.new('127.0.0.1', @port)
+ socket.close
+ ready = true
+
+ t.value.should.is_a? Array
+ t.value[0].should == ""
+ end
+ end
+ end
+
+ ruby_version_is "3.3" do
+ platform_is_not :windows do
+ it "returns nil on a closed stream socket" do
+ ready = false
+
+ t = Thread.new do
+ client = @server.accept
+
+ Thread.pass while !ready
+ begin
+ client.recvmsg_nonblock(10)
+ rescue IO::EAGAINWaitReadable
+ retry
+ end
+ ensure
+ client.close if client
+ end
+
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ socket = TCPSocket.new('127.0.0.1', @port)
+ socket.close
+ ready = true
+
+ t.value.should be_nil
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/basicsocket/recvmsg_spec.rb b/spec/ruby/library/socket/basicsocket/recvmsg_spec.rb
index 8063723701..04ba1d74c7 100644
--- a/spec/ruby/library/socket/basicsocket/recvmsg_spec.rb
+++ b/spec/ruby/library/socket/basicsocket/recvmsg_spec.rb
@@ -195,3 +195,87 @@ describe 'BasicSocket#recvmsg' do
end
end
end
+
+describe 'BasicSocket#recvmsg' do
+ context "when recvfrom(2) returns 0 (if no messages are available to be received and the peer has performed an orderly shutdown)" do
+ describe "stream socket" do
+ before :each do
+ @server = TCPServer.new('127.0.0.1', 0)
+ @port = @server.addr[1]
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ end
+
+ ruby_version_is ""..."3.3" do
+ platform_is_not :windows do
+ it "returns an empty String as received data on a closed stream socket" do
+ t = Thread.new do
+ client = @server.accept
+ client.recvmsg(10)
+ ensure
+ client.close if client
+ end
+
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ socket = TCPSocket.new('127.0.0.1', @port)
+ socket.close
+
+ t.value.should.is_a? Array
+ t.value[0].should == ""
+ end
+ end
+ end
+
+ ruby_version_is "3.3" do
+ platform_is_not :windows do
+ it "returns nil on a closed stream socket" do
+ t = Thread.new do
+ client = @server.accept
+ client.recvmsg(10)
+ ensure
+ client.close if client
+ end
+
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ socket = TCPSocket.new('127.0.0.1', @port)
+ socket.close
+
+ t.value.should be_nil
+ end
+ end
+ end
+ end
+
+ describe "datagram socket" do
+ SocketSpecs.each_ip_protocol do |family, ip_address|
+ before :each do
+ @server = UDPSocket.new(family)
+ @client = UDPSocket.new(family)
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ @client.close unless @client.closed?
+ end
+
+ it "returns an empty String as received data" do
+ @server.bind(ip_address, 0)
+ addr = @server.connect_address
+ @client.connect(addr.ip_address, addr.ip_port)
+
+ @client.send('', 0)
+ message = @server.recvmsg(1)
+
+ message.should.is_a? Array
+ message[0].should == ""
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/basicsocket/send_spec.rb b/spec/ruby/library/socket/basicsocket/send_spec.rb
index 86b5567026..25ba3f5655 100644
--- a/spec/ruby/library/socket/basicsocket/send_spec.rb
+++ b/spec/ruby/library/socket/basicsocket/send_spec.rb
@@ -16,29 +16,29 @@ describe "BasicSocket#send" do
@socket.close
end
- it "sends a message to another socket and returns the number of bytes sent" do
- data = +""
- t = Thread.new do
- client = @server.accept
- loop do
- got = client.recv(5)
- break if got.nil? || got.empty?
- data << got
- end
- client.close
- end
- Thread.pass while t.status and t.status != "sleep"
- t.status.should_not be_nil
-
- @socket.send('hello', 0).should == 5
- @socket.shutdown(1) # indicate, that we are done sending
- @socket.recv(10)
-
- t.join
- data.should == 'hello'
- end
-
- platform_is_not :solaris, :windows do
+ it "sends a message to another socket and returns the number of bytes sent" do
+ data = +""
+ t = Thread.new do
+ client = @server.accept
+ loop do
+ got = client.recv(5)
+ break if got.nil? || got.empty?
+ data << got
+ end
+ client.close
+ end
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ @socket.send('hello', 0).should == 5
+ @socket.shutdown(1) # indicate, that we are done sending
+ @socket.recv(10)
+
+ t.join
+ data.should == 'hello'
+ end
+
+ platform_is_not :windows do
it "accepts flags to specify unusual sending behaviour" do
data = nil
peek_data = nil
@@ -62,25 +62,25 @@ describe "BasicSocket#send" do
end
it "accepts a sockaddr as recipient address" do
- data = +""
- t = Thread.new do
- client = @server.accept
- loop do
- got = client.recv(5)
- break if got.nil? || got.empty?
- data << got
- end
- client.close
- end
- Thread.pass while t.status and t.status != "sleep"
- t.status.should_not be_nil
-
- sockaddr = Socket.pack_sockaddr_in(@port, "127.0.0.1")
- @socket.send('hello', 0, sockaddr).should == 5
- @socket.shutdown # indicate, that we are done sending
-
- t.join
- data.should == 'hello'
+ data = +""
+ t = Thread.new do
+ client = @server.accept
+ loop do
+ got = client.recv(5)
+ break if got.nil? || got.empty?
+ data << got
+ end
+ client.close
+ end
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ sockaddr = Socket.pack_sockaddr_in(@port, "127.0.0.1")
+ @socket.send('hello', 0, sockaddr).should == 5
+ @socket.shutdown # indicate, that we are done sending
+
+ t.join
+ data.should == 'hello'
end
end
diff --git a/spec/ruby/library/socket/basicsocket/setsockopt_spec.rb b/spec/ruby/library/socket/basicsocket/setsockopt_spec.rb
index 1e8d84e1c9..f686e67326 100644
--- a/spec/ruby/library/socket/basicsocket/setsockopt_spec.rb
+++ b/spec/ruby/library/socket/basicsocket/setsockopt_spec.rb
@@ -315,22 +315,20 @@ describe 'BasicSocket#setsockopt' do
end
end
- with_feature :unix_socket do
- describe 'using a UNIX socket' do
- before do
- @path = SocketSpecs.socket_path
- @server = UNIXServer.new(@path)
- end
+ describe 'using a UNIX socket' do
+ before do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.new(@path)
+ end
- after do
- @server.close
- rm_r @path
- end
+ after do
+ @server.close
+ rm_r @path
+ end
- it 'sets a boolean option' do
- @server.setsockopt(:SOCKET, :REUSEADDR, true)
- @server.getsockopt(:SOCKET, :REUSEADDR).bool.should == true
- end
+ it 'sets a boolean option' do
+ @server.setsockopt(:SOCKET, :REUSEADDR, true)
+ @server.getsockopt(:SOCKET, :REUSEADDR).bool.should == true
end
end
end
diff --git a/spec/ruby/library/socket/constants/constants_spec.rb b/spec/ruby/library/socket/constants/constants_spec.rb
index 637bc6740a..b9a9d42725 100644
--- a/spec/ruby/library/socket/constants/constants_spec.rb
+++ b/spec/ruby/library/socket/constants/constants_spec.rb
@@ -68,7 +68,7 @@ describe "Socket::Constants" do
end
end
- platform_is_not :solaris, :windows, :aix, :android do
+ platform_is_not :windows, :aix, :android do
it "defines multicast options" do
consts = ["IP_MAX_MEMBERSHIPS"]
consts.each do |c|
diff --git a/spec/ruby/library/socket/ipsocket/getaddress_spec.rb b/spec/ruby/library/socket/ipsocket/getaddress_spec.rb
index 96324982e5..329f8267d3 100644
--- a/spec/ruby/library/socket/ipsocket/getaddress_spec.rb
+++ b/spec/ruby/library/socket/ipsocket/getaddress_spec.rb
@@ -2,7 +2,6 @@ require_relative '../spec_helper'
require_relative '../fixtures/classes'
describe "Socket::IPSocket#getaddress" do
-
it "returns the IP address of hostname" do
addr_local = IPSocket.getaddress(SocketSpecs.hostname)
["127.0.0.1", "::1"].include?(addr_local).should == true
@@ -14,6 +13,10 @@ describe "Socket::IPSocket#getaddress" do
IPSocket.getaddress('::1').should == '::1'
end
+ it 'returns IPv4 compatible IPv6 addresses' do
+ IPSocket.getaddress('::ffff:192.168.1.1').should == '::ffff:192.168.1.1'
+ end
+
# There is no way to make this fail-proof on all machines, because
# DNS servers like opendns return A records for ANY host, including
# traditionally invalidly named ones.
diff --git a/spec/ruby/library/socket/ipsocket/recvfrom_spec.rb b/spec/ruby/library/socket/ipsocket/recvfrom_spec.rb
index 2af86ea70d..b58903df23 100644
--- a/spec/ruby/library/socket/ipsocket/recvfrom_spec.rb
+++ b/spec/ruby/library/socket/ipsocket/recvfrom_spec.rb
@@ -69,6 +69,88 @@ describe "Socket::IPSocket#recvfrom" do
end
end
+describe "Socket::IPSocket#recvfrom" do
+ context "when recvfrom(2) returns 0 (if no messages are available to be received and the peer has performed an orderly shutdown)" do
+ describe "stream socket" do
+ before :each do
+ @server = TCPServer.new("127.0.0.1", 0)
+ port = @server.addr[1]
+ @client = TCPSocket.new("127.0.0.1", port)
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ @client.close unless @client.closed?
+ end
+
+ ruby_version_is ""..."3.3" do
+ it "returns an empty String as received data on a closed stream socket" do
+ t = Thread.new do
+ client = @server.accept
+ message = client.recvfrom(10)
+ message
+ ensure
+ client.close if client
+ end
+
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ @client.close
+
+ t.value.should.is_a? Array
+ t.value[0].should == ""
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "returns nil on a closed stream socket" do
+ t = Thread.new do
+ client = @server.accept
+ message = client.recvfrom(10)
+ message
+ ensure
+ client.close if client
+ end
+
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ @client.close
+
+ t.value.should be_nil
+ end
+ end
+ end
+
+ describe "datagram socket" do
+ SocketSpecs.each_ip_protocol do |family, ip_address|
+ before :each do
+ @server = UDPSocket.new(family)
+ @client = UDPSocket.new(family)
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ @client.close unless @client.closed?
+ end
+
+ it "returns an empty String as received data" do
+ @server.bind(ip_address, 0)
+ addr = @server.connect_address
+ @client.connect(addr.ip_address, addr.ip_port)
+
+ @client.send('', 0)
+ message = @server.recvfrom(1)
+
+ message.should.is_a? Array
+ message[0].should == ""
+ end
+ end
+ end
+ end
+end
+
describe 'Socket::IPSocket#recvfrom' do
SocketSpecs.each_ip_protocol do |family, ip_address, family_name|
before do
diff --git a/spec/ruby/library/socket/shared/address.rb b/spec/ruby/library/socket/shared/address.rb
index f3be9cfb99..49ba17c400 100644
--- a/spec/ruby/library/socket/shared/address.rb
+++ b/spec/ruby/library/socket/shared/address.rb
@@ -129,41 +129,51 @@ describe :socket_local_remote_address, shared: true do
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
+ 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
+ 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 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 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
+ 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 'uses the correct socket path' do
+ platform_is_not :windows do
+ it 'equals address of peer socket' do
if @method == :local_address
- @addr.unix_path.should == ""
+ @addr.to_s.should == @b.remote_address.to_s
else
- @addr.unix_path.should == @path
+ @addr.to_s.should == @b.local_address.to_s
end
end
+ end
+ guard -> { platform_is :windows and ruby_bug "#21702", ""..."4.2" } do
it 'equals address of peer socket' do
if @method == :local_address
@addr.to_s.should == @b.remote_address.to_s
@@ -171,23 +181,23 @@ describe :socket_local_remote_address, shared: true do
@addr.to_s.should == @b.local_address.to_s
end
end
+ end
- it 'returns an Addrinfo' do
- @addr.should be_an_instance_of(Addrinfo)
- 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 '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
+ 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
diff --git a/spec/ruby/library/socket/shared/pack_sockaddr.rb b/spec/ruby/library/socket/shared/pack_sockaddr.rb
index 26fdf682b1..4bfcf4edb9 100644
--- a/spec/ruby/library/socket/shared/pack_sockaddr.rb
+++ b/spec/ruby/library/socket/shared/pack_sockaddr.rb
@@ -22,11 +22,9 @@ describe :socket_pack_sockaddr_in, shared: true do
Socket.unpack_sockaddr_in(sockaddr_in).should == [80, '0.0.0.0']
end
- platform_is_not :solaris do
- it 'resolves the service name to a port' do
- sockaddr_in = Socket.public_send(@method, 'http', '127.0.0.1')
- Socket.unpack_sockaddr_in(sockaddr_in).should == [80, '127.0.0.1']
- end
+ it 'resolves the service name to a port' do
+ sockaddr_in = Socket.public_send(@method, 'http', '127.0.0.1')
+ Socket.unpack_sockaddr_in(sockaddr_in).should == [80, '127.0.0.1']
end
describe 'using an IPv4 address' do
@@ -38,47 +36,32 @@ describe :socket_pack_sockaddr_in, shared: true do
end
end
- platform_is_not :solaris do
- describe 'using an IPv6 address' do
- it 'returns a String of 28 bytes' do
- str = Socket.public_send(@method, 80, '::1')
+ describe 'using an IPv6 address' do
+ it 'returns a String of 28 bytes' do
+ str = Socket.public_send(@method, 80, '::1')
- str.should be_an_instance_of(String)
- str.bytesize.should == 28
- end
- end
- end
-
- platform_is :solaris do
- describe 'using an IPv6 address' do
- it 'returns a String of 32 bytes' do
- str = Socket.public_send(@method, 80, '::1')
-
- str.should be_an_instance_of(String)
- str.bytesize.should == 32
- end
+ str.should be_an_instance_of(String)
+ str.bytesize.should == 28
end
end
end
describe :socket_pack_sockaddr_un, shared: true do
- with_feature :unix_socket do
- it 'should be idempotent' do
- bytes = Socket.public_send(@method, '/tmp/foo').bytes
- bytes[2..9].should == [47, 116, 109, 112, 47, 102, 111, 111]
- bytes[10..-1].all?(&:zero?).should == true
- end
+ it 'should be idempotent' do
+ bytes = Socket.public_send(@method, '/tmp/foo').bytes
+ bytes[2..9].should == [47, 116, 109, 112, 47, 102, 111, 111]
+ bytes[10..-1].all?(&:zero?).should == true
+ end
- it "packs and unpacks" do
- sockaddr_un = Socket.public_send(@method, '/tmp/s')
- Socket.unpack_sockaddr_un(sockaddr_un).should == '/tmp/s'
- end
+ it "packs and unpacks" do
+ sockaddr_un = Socket.public_send(@method, '/tmp/s')
+ Socket.unpack_sockaddr_un(sockaddr_un).should == '/tmp/s'
+ end
- it "handles correctly paths with multibyte chars" do
- sockaddr_un = Socket.public_send(@method, '/home/вася/sock')
- path = Socket.unpack_sockaddr_un(sockaddr_un).encode('UTF-8', 'UTF-8')
- path.should == '/home/вася/sock'
- end
+ it "handles correctly paths with multibyte chars" do
+ sockaddr_un = Socket.public_send(@method, '/home/вася/sock')
+ path = Socket.unpack_sockaddr_un(sockaddr_un).encode('UTF-8', 'UTF-8')
+ path.should == '/home/вася/sock'
end
platform_is :linux do
@@ -99,7 +82,7 @@ describe :socket_pack_sockaddr_un, shared: true do
end
end
- platform_is_not :windows, :aix do
+ platform_is_not :aix do
it "raises ArgumentError for paths that are too long" do
# AIX doesn't raise error
long_path = 'a' * 110
diff --git a/spec/ruby/library/socket/socket/bind_spec.rb b/spec/ruby/library/socket/socket/bind_spec.rb
index 4465a3dafa..e76336eafa 100644
--- a/spec/ruby/library/socket/socket/bind_spec.rb
+++ b/spec/ruby/library/socket/socket/bind_spec.rb
@@ -122,7 +122,7 @@ describe 'Socket#bind' do
-> { @socket.bind(sockaddr1) }.should raise_error(Errno::EACCES)
end
- end
+ end
end
end
diff --git a/spec/ruby/library/socket/socket/connect_nonblock_spec.rb b/spec/ruby/library/socket/socket/connect_nonblock_spec.rb
index 3cf667fc4a..359b8719fb 100644
--- a/spec/ruby/library/socket/socket/connect_nonblock_spec.rb
+++ b/spec/ruby/library/socket/socket/connect_nonblock_spec.rb
@@ -16,42 +16,40 @@ describe "Socket#connect_nonblock" do
@thread.join if @thread
end
- platform_is_not :solaris do
- it "connects the socket to the remote side" do
- port = nil
- accept = false
- @thread = Thread.new do
- server = TCPServer.new(@hostname, 0)
- port = server.addr[1]
- Thread.pass until accept
- conn = server.accept
- conn << "hello!"
- conn.close
- server.close
- end
-
- Thread.pass until port
+ it "connects the socket to the remote side" do
+ port = nil
+ accept = false
+ @thread = Thread.new do
+ server = TCPServer.new(@hostname, 0)
+ port = server.addr[1]
+ Thread.pass until accept
+ conn = server.accept
+ conn << "hello!"
+ conn.close
+ server.close
+ end
- addr = Socket.sockaddr_in(port, @hostname)
- begin
- @socket.connect_nonblock(addr)
- rescue Errno::EINPROGRESS
- end
+ Thread.pass until port
- accept = true
- IO.select nil, [@socket]
+ addr = Socket.sockaddr_in(port, @hostname)
+ begin
+ @socket.connect_nonblock(addr)
+ rescue Errno::EINPROGRESS
+ end
- begin
- @socket.connect_nonblock(addr)
- rescue Errno::EISCONN
- # Not all OS's use this errno, so we trap and ignore it
- end
+ accept = true
+ IO.select nil, [@socket]
- @socket.read(6).should == "hello!"
+ begin
+ @socket.connect_nonblock(addr)
+ rescue Errno::EISCONN
+ # Not all OS's use this errno, so we trap and ignore it
end
+
+ @socket.read(6).should == "hello!"
end
- platform_is_not :freebsd, :solaris, :aix do
+ platform_is_not :freebsd, :aix do
it "raises Errno::EINPROGRESS when the connect would block" do
-> do
@socket.connect_nonblock(@addr)
@@ -135,7 +133,7 @@ describe 'Socket#connect_nonblock' do
end
end
- platform_is_not :freebsd, :solaris do
+ platform_is_not :freebsd do
it 'raises IO:EINPROGRESSWaitWritable when the connection would block' do
@server.bind(@sockaddr)
diff --git a/spec/ruby/library/socket/socket/connect_spec.rb b/spec/ruby/library/socket/socket/connect_spec.rb
index 8653fba552..130379ce2b 100644
--- a/spec/ruby/library/socket/socket/connect_spec.rb
+++ b/spec/ruby/library/socket/socket/connect_spec.rb
@@ -53,4 +53,26 @@ describe 'Socket#connect' do
end
end
end
+
+ ruby_version_is "3.4" do
+ it "fails with timeout" do
+ # TEST-NET-1 IP address are reserved for documentation and example purposes.
+ address = Socket.pack_sockaddr_in(1, "192.0.2.1")
+
+ client = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM)
+ client.timeout = 0
+
+ -> {
+ begin
+ client.connect(address)
+ rescue Errno::ECONNREFUSED
+ skip "Outgoing packets may be filtered"
+ rescue Errno::ENETUNREACH
+ skip "Off line"
+ end
+ }.should raise_error(IO::TimeoutError)
+ ensure
+ client.close
+ end
+ end
end
diff --git a/spec/ruby/library/socket/socket/getaddrinfo_spec.rb b/spec/ruby/library/socket/socket/getaddrinfo_spec.rb
index e0eff3cef4..6576af52ee 100644
--- a/spec/ruby/library/socket/socket/getaddrinfo_spec.rb
+++ b/spec/ruby/library/socket/socket/getaddrinfo_spec.rb
@@ -11,7 +11,7 @@ describe "Socket.getaddrinfo" do
BasicSocket.do_not_reverse_lookup = @do_not_reverse_lookup
end
- platform_is_not :solaris, :windows do
+ platform_is_not :windows do
it "gets the address information" do
expected = []
# The check for AP_INET6's class is needed because ipaddr.rb adds
@@ -106,6 +106,24 @@ describe "Socket.getaddrinfo" do
]
res.each { |a| expected.should include(a) }
end
+
+ ruby_version_is ""..."3.3" do
+ it "raises SocketError when fails to resolve address" do
+ -> {
+ Socket.getaddrinfo("www.kame.net", 80, "AF_UNIX")
+ }.should raise_error(SocketError)
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raises ResolutionError when fails to resolve address" do
+ -> {
+ Socket.getaddrinfo("www.kame.net", 80, "AF_UNIX")
+ }.should raise_error(Socket::ResolutionError) { |e|
+ [Socket::EAI_FAMILY, Socket::EAI_FAIL].should.include?(e.error_code)
+ }
+ end
+ end
end
end
diff --git a/spec/ruby/library/socket/socket/gethostbyaddr_spec.rb b/spec/ruby/library/socket/socket/gethostbyaddr_spec.rb
index a4c8355520..5d936046f5 100644
--- a/spec/ruby/library/socket/socket/gethostbyaddr_spec.rb
+++ b/spec/ruby/library/socket/socket/gethostbyaddr_spec.rb
@@ -18,11 +18,8 @@ describe 'Socket.gethostbyaddr' do
@array = suppress_warning { Socket.gethostbyaddr(@addr) }
end
- # RubyCI Solaris 11x defines 127.0.0.1 as unstable11x
- platform_is_not :"solaris2.11" do
- it 'includes the hostname as the first value' do
- @array[0].should == SocketSpecs.hostname_reverse_lookup
- end
+ it 'includes the hostname as the first value' do
+ @array[0].should == SocketSpecs.hostname_reverse_lookup
end
it 'includes the aliases as the 2nd value' do
diff --git a/spec/ruby/library/socket/socket/gethostbyname_spec.rb b/spec/ruby/library/socket/socket/gethostbyname_spec.rb
index 0858e255e4..618ef85387 100644
--- a/spec/ruby/library/socket/socket/gethostbyname_spec.rb
+++ b/spec/ruby/library/socket/socket/gethostbyname_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../spec_helper'
require_relative '../fixtures/classes'
diff --git a/spec/ruby/library/socket/socket/gethostname_spec.rb b/spec/ruby/library/socket/socket/gethostname_spec.rb
index 4b79747b27..dfca7cf5cd 100644
--- a/spec/ruby/library/socket/socket/gethostname_spec.rb
+++ b/spec/ruby/library/socket/socket/gethostname_spec.rb
@@ -2,7 +2,17 @@ require_relative '../spec_helper'
require_relative '../fixtures/classes'
describe "Socket.gethostname" do
+ def system_hostname
+ if platform_is_not :windows
+ # `uname -n` is the most portable way to get the hostname, as it is a POSIX standard:
+ `uname -n`.strip
+ else
+ # Windows does not have uname, so we use hostname instead:
+ `hostname`.strip
+ end
+ end
+
it "returns the host name" do
- Socket.gethostname.should == `hostname`.strip
+ Socket.gethostname.should == system_hostname
end
end
diff --git a/spec/ruby/library/socket/socket/getifaddrs_spec.rb b/spec/ruby/library/socket/socket/getifaddrs_spec.rb
index 7df542abe6..839854ea27 100644
--- a/spec/ruby/library/socket/socket/getifaddrs_spec.rb
+++ b/spec/ruby/library/socket/socket/getifaddrs_spec.rb
@@ -1,6 +1,6 @@
require_relative '../spec_helper'
-platform_is_not :aix, :"solaris2.10" do
+platform_is_not :aix do
describe 'Socket.getifaddrs' do
before do
@ifaddrs = Socket.getifaddrs
diff --git a/spec/ruby/library/socket/socket/getnameinfo_spec.rb b/spec/ruby/library/socket/socket/getnameinfo_spec.rb
index 4f13bf484d..af4a10c9c2 100644
--- a/spec/ruby/library/socket/socket/getnameinfo_spec.rb
+++ b/spec/ruby/library/socket/socket/getnameinfo_spec.rb
@@ -60,6 +60,24 @@ describe "Socket.getnameinfo" do
name_info = Socket.getnameinfo ["AF_INET", 9, 'foo', '127.0.0.1']
name_info[1].should == 'discard'
end
+
+ ruby_version_is ""..."3.3" do
+ it "raises SocketError when fails to resolve address" do
+ -> {
+ Socket.getnameinfo(["AF_UNIX", 80, "0.0.0.0"])
+ }.should raise_error(SocketError)
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raises ResolutionError when fails to resolve address" do
+ -> {
+ Socket.getnameinfo(["AF_UNIX", 80, "0.0.0.0"])
+ }.should raise_error(Socket::ResolutionError) { |e|
+ [Socket::EAI_FAMILY, Socket::EAI_FAIL].should.include?(e.error_code)
+ }
+ end
+ end
end
describe 'Socket.getnameinfo' do
diff --git a/spec/ruby/library/socket/socket/recvfrom_nonblock_spec.rb b/spec/ruby/library/socket/socket/recvfrom_nonblock_spec.rb
index 5596f91bb8..01b42bcc52 100644
--- a/spec/ruby/library/socket/socket/recvfrom_nonblock_spec.rb
+++ b/spec/ruby/library/socket/socket/recvfrom_nonblock_spec.rb
@@ -137,3 +137,83 @@ describe 'Socket#recvfrom_nonblock' do
end
end
end
+
+describe 'Socket#recvfrom_nonblock' do
+ context "when recvfrom(2) returns 0 (if no messages are available to be received and the peer has performed an orderly shutdown)" do
+ describe "stream socket" do
+ before :each do
+ @server = Socket.new Socket::AF_INET, :STREAM, 0
+ @sockaddr = Socket.sockaddr_in(0, "127.0.0.1")
+ @server.bind(@sockaddr)
+ @server.listen(1)
+
+ server_ip = @server.local_address.ip_port
+ @server_addr = Socket.sockaddr_in(server_ip, "127.0.0.1")
+
+ @client = Socket.new(Socket::AF_INET, :STREAM, 0)
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ @client.close unless @client.closed?
+ end
+
+ ruby_version_is ""..."3.3" do
+ it "returns an empty String as received data on a closed stream socket" do
+ ready = false
+
+ t = Thread.new do
+ client, _ = @server.accept
+
+ Thread.pass while !ready
+ begin
+ client.recvfrom_nonblock(10)
+ rescue IO::EAGAINWaitReadable
+ retry
+ end
+ ensure
+ client.close if client
+ end
+
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ @client.connect(@server_addr)
+ @client.close
+ ready = true
+
+ t.value.should.is_a? Array
+ t.value[0].should == ""
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "returns nil on a closed stream socket" do
+ ready = false
+
+ t = Thread.new do
+ client, _ = @server.accept
+
+ Thread.pass while !ready
+ begin
+ client.recvfrom_nonblock(10)
+ rescue IO::EAGAINWaitReadable
+ retry
+ end
+ ensure
+ client.close if client
+ end
+
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ @client.connect(@server_addr)
+ @client.close
+ ready = true
+
+ t.value.should be_nil
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/socket/recvfrom_spec.rb b/spec/ruby/library/socket/socket/recvfrom_spec.rb
index faf161e4a5..6ba39ffcaf 100644
--- a/spec/ruby/library/socket/socket/recvfrom_spec.rb
+++ b/spec/ruby/library/socket/socket/recvfrom_spec.rb
@@ -90,3 +90,90 @@ describe 'Socket#recvfrom' do
end
end
end
+
+describe 'Socket#recvfrom' do
+ context "when recvfrom(2) returns 0 (if no messages are available to be received and the peer has performed an orderly shutdown)" do
+ describe "stream socket" do
+ before :each do
+ @server = Socket.new Socket::AF_INET, :STREAM, 0
+ sockaddr = Socket.sockaddr_in(0, "127.0.0.1")
+ @server.bind(sockaddr)
+ @server.listen(1)
+
+ server_ip = @server.local_address.ip_port
+ @server_addr = Socket.sockaddr_in(server_ip, "127.0.0.1")
+
+ @client = Socket.new(Socket::AF_INET, :STREAM, 0)
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ @client.close unless @client.closed?
+ end
+
+ ruby_version_is ""..."3.3" do
+ it "returns an empty String as received data on a closed stream socket" do
+ t = Thread.new do
+ client, _ = @server.accept
+ client.recvfrom(10)
+ ensure
+ client.close if client
+ end
+
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ @client.connect(@server_addr)
+ @client.close
+
+ t.value.should.is_a? Array
+ t.value[0].should == ""
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "returns nil on a closed stream socket" do
+ t = Thread.new do
+ client, _ = @server.accept
+ client.recvfrom(10)
+ ensure
+ client.close if client
+ end
+
+ Thread.pass while t.status and t.status != "sleep"
+ t.status.should_not be_nil
+
+ @client.connect(@server_addr)
+ @client.close
+
+ t.value.should be_nil
+ end
+ end
+ end
+
+ describe "datagram socket" do
+ SocketSpecs.each_ip_protocol do |family, ip_address|
+ before :each do
+ @server = Socket.new(family, :DGRAM)
+ @client = Socket.new(family, :DGRAM)
+ end
+
+ after :each do
+ @server.close unless @server.closed?
+ @client.close unless @client.closed?
+ end
+
+ it "returns an empty String as received data" do
+ @server.bind(Socket.sockaddr_in(0, ip_address))
+ @client.connect(@server.getsockname)
+
+ @client.send('', 0)
+ message = @server.recvfrom(1)
+
+ message.should.is_a? Array
+ message[0].should == ""
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/socket/udp_server_loop_spec.rb b/spec/ruby/library/socket/socket/udp_server_loop_spec.rb
index fc030e75b9..cd22ea56cf 100644
--- a/spec/ruby/library/socket/socket/udp_server_loop_spec.rb
+++ b/spec/ruby/library/socket/socket/udp_server_loop_spec.rb
@@ -50,10 +50,10 @@ describe 'Socket.udp_server_loop' do
end
end
+ thread.join
+
msg.should == 'hello'
src.should be_an_instance_of(Socket::UDPSource)
-
- thread.join
end
end
end
diff --git a/spec/ruby/library/socket/socket/unix_server_loop_spec.rb b/spec/ruby/library/socket/socket/unix_server_loop_spec.rb
index 0f34d4a50b..6192bc8bf6 100644
--- a/spec/ruby/library/socket/socket/unix_server_loop_spec.rb
+++ b/spec/ruby/library/socket/socket/unix_server_loop_spec.rb
@@ -1,58 +1,56 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
-with_feature :unix_socket do
- describe 'Socket.unix_server_loop' do
- before do
- @path = SocketSpecs.socket_path
- end
+describe 'Socket.unix_server_loop' do
+ before do
+ @path = SocketSpecs.socket_path
+ end
- after do
- rm_r(@path) if File.file?(@path)
- end
+ after do
+ rm_r(@path) if File.file?(@path)
+ end
- describe 'when no connections are available' do
- it 'blocks the caller' do
- -> { Socket.unix_server_loop(@path) }.should block_caller
- end
+ describe 'when no connections are available' do
+ it 'blocks the caller' do
+ -> { Socket.unix_server_loop(@path) }.should block_caller
end
+ end
- describe 'when a connection is available' do
- before do
- @client = nil
- end
+ describe 'when a connection is available' do
+ before do
+ @client = nil
+ end
- after do
- @sock.close if @sock
- @client.close if @client
- end
+ after do
+ @sock.close if @sock
+ @client.close if @client
+ end
- it 'yields a Socket and an Addrinfo' do
- @sock, addr = nil
+ it 'yields a Socket and an Addrinfo' do
+ @sock, addr = nil
- thread = Thread.new do
- Socket.unix_server_loop(@path) do |socket, addrinfo|
- @sock = socket
- addr = addrinfo
+ thread = Thread.new do
+ Socket.unix_server_loop(@path) do |socket, addrinfo|
+ @sock = socket
+ addr = addrinfo
- break
- end
+ break
end
+ end
- SocketSpecs.loop_with_timeout do
- begin
- @client = Socket.unix(@path)
- rescue SystemCallError
- sleep 0.01
- :retry
- end
+ SocketSpecs.loop_with_timeout do
+ begin
+ @client = Socket.unix(@path)
+ rescue SystemCallError
+ sleep 0.01
+ :retry
end
+ end
- thread.join
+ thread.join
- @sock.should be_an_instance_of(Socket)
- addr.should be_an_instance_of(Addrinfo)
- end
+ @sock.should be_an_instance_of(Socket)
+ addr.should be_an_instance_of(Addrinfo)
end
end
end
diff --git a/spec/ruby/library/socket/socket/unix_server_socket_spec.rb b/spec/ruby/library/socket/socket/unix_server_socket_spec.rb
index fc357740fa..34c3b96d07 100644
--- a/spec/ruby/library/socket/socket/unix_server_socket_spec.rb
+++ b/spec/ruby/library/socket/socket/unix_server_socket_spec.rb
@@ -1,48 +1,46 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
-with_feature :unix_socket do
- describe 'Socket.unix_server_socket' do
+describe 'Socket.unix_server_socket' do
+ before do
+ @path = SocketSpecs.socket_path
+ end
+
+ after do
+ rm_r(@path)
+ end
+
+ describe 'when no block is given' do
before do
- @path = SocketSpecs.socket_path
+ @socket = nil
end
after do
- rm_r(@path)
+ @socket.close
end
- describe 'when no block is given' do
- before do
- @socket = nil
- end
-
- after do
- @socket.close
- end
+ it 'returns a Socket' do
+ @socket = Socket.unix_server_socket(@path)
- it 'returns a Socket' do
- @socket = Socket.unix_server_socket(@path)
-
- @socket.should be_an_instance_of(Socket)
- end
+ @socket.should be_an_instance_of(Socket)
end
+ end
- describe 'when a block is given' do
- it 'yields a Socket' do
- Socket.unix_server_socket(@path) do |sock|
- sock.should be_an_instance_of(Socket)
- end
+ describe 'when a block is given' do
+ it 'yields a Socket' do
+ Socket.unix_server_socket(@path) do |sock|
+ sock.should be_an_instance_of(Socket)
end
+ end
- it 'closes the Socket when the block returns' do
- socket = nil
-
- Socket.unix_server_socket(@path) do |sock|
- socket = sock
- end
+ it 'closes the Socket when the block returns' do
+ socket = nil
- socket.should be_an_instance_of(Socket)
+ Socket.unix_server_socket(@path) do |sock|
+ socket = sock
end
+
+ socket.should be_an_instance_of(Socket)
end
end
end
diff --git a/spec/ruby/library/socket/socket/unix_spec.rb b/spec/ruby/library/socket/socket/unix_spec.rb
index 4bff59bd4b..2a5d77f96f 100644
--- a/spec/ruby/library/socket/socket/unix_spec.rb
+++ b/spec/ruby/library/socket/socket/unix_spec.rb
@@ -1,45 +1,43 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
-with_feature :unix_socket do
- describe 'Socket.unix' do
- before do
- @path = SocketSpecs.socket_path
- @server = UNIXServer.new(@path)
- @socket = nil
- end
+describe 'Socket.unix' do
+ before do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.new(@path)
+ @socket = nil
+ end
- after do
- @server.close
- @socket.close if @socket
+ after do
+ @server.close
+ @socket.close if @socket
- rm_r(@path)
- end
+ rm_r(@path)
+ end
- describe 'when no block is given' do
- it 'returns a Socket' do
- @socket = Socket.unix(@path)
+ describe 'when no block is given' do
+ it 'returns a Socket' do
+ @socket = Socket.unix(@path)
- @socket.should be_an_instance_of(Socket)
- end
+ @socket.should be_an_instance_of(Socket)
end
+ end
- describe 'when a block is given' do
- it 'yields a Socket' do
- Socket.unix(@path) do |sock|
- sock.should be_an_instance_of(Socket)
- end
+ describe 'when a block is given' do
+ it 'yields a Socket' do
+ Socket.unix(@path) do |sock|
+ sock.should be_an_instance_of(Socket)
end
+ end
- it 'closes the Socket when the block returns' do
- socket = nil
-
- Socket.unix(@path) do |sock|
- socket = sock
- end
+ it 'closes the Socket when the block returns' do
+ socket = nil
- socket.should.closed?
+ Socket.unix(@path) do |sock|
+ socket = sock
end
+
+ socket.should.closed?
end
end
end
diff --git a/spec/ruby/library/socket/socket/unpack_sockaddr_in_spec.rb b/spec/ruby/library/socket/socket/unpack_sockaddr_in_spec.rb
index 79ec68cd18..935b5cb543 100644
--- a/spec/ruby/library/socket/socket/unpack_sockaddr_in_spec.rb
+++ b/spec/ruby/library/socket/socket/unpack_sockaddr_in_spec.rb
@@ -32,15 +32,13 @@ describe "Socket.unpack_sockaddr_in" do
end
end
- with_feature :unix_socket do
- it "raises an ArgumentError when the sin_family is not AF_INET" do
- sockaddr = Socket.sockaddr_un '/tmp/x'
- -> { Socket.unpack_sockaddr_in sockaddr }.should raise_error(ArgumentError)
- end
+ it "raises an ArgumentError when the sin_family is not AF_INET" do
+ sockaddr = Socket.sockaddr_un '/tmp/x'
+ -> { Socket.unpack_sockaddr_in sockaddr }.should raise_error(ArgumentError)
+ end
- it "raises an ArgumentError when passed addrinfo is not AF_INET/AF_INET6" do
- addrinfo = Addrinfo.unix('/tmp/sock')
- -> { Socket.unpack_sockaddr_in(addrinfo) }.should raise_error(ArgumentError)
- end
+ it "raises an ArgumentError when passed addrinfo is not AF_INET/AF_INET6" do
+ addrinfo = Addrinfo.unix('/tmp/sock')
+ -> { Socket.unpack_sockaddr_in(addrinfo) }.should raise_error(ArgumentError)
end
end
diff --git a/spec/ruby/library/socket/socket/unpack_sockaddr_un_spec.rb b/spec/ruby/library/socket/socket/unpack_sockaddr_un_spec.rb
index 12f970f89b..6e0f11de3d 100644
--- a/spec/ruby/library/socket/socket/unpack_sockaddr_un_spec.rb
+++ b/spec/ruby/library/socket/socket/unpack_sockaddr_un_spec.rb
@@ -1,26 +1,24 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
-with_feature :unix_socket do
- describe 'Socket.unpack_sockaddr_un' do
- it 'decodes sockaddr to unix path' do
- sockaddr = Socket.sockaddr_un('/tmp/sock')
- Socket.unpack_sockaddr_un(sockaddr).should == '/tmp/sock'
- end
+describe 'Socket.unpack_sockaddr_un' do
+ it 'decodes sockaddr to unix path' do
+ sockaddr = Socket.sockaddr_un('/tmp/sock')
+ Socket.unpack_sockaddr_un(sockaddr).should == '/tmp/sock'
+ end
- it 'returns unix path from a passed Addrinfo' do
- addrinfo = Addrinfo.unix('/tmp/sock')
- Socket.unpack_sockaddr_un(addrinfo).should == '/tmp/sock'
- end
+ it 'returns unix path from a passed Addrinfo' do
+ addrinfo = Addrinfo.unix('/tmp/sock')
+ Socket.unpack_sockaddr_un(addrinfo).should == '/tmp/sock'
+ end
- 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
+ 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
- it 'raises an ArgumentError when passed addrinfo is not AF_UNIX' do
- addrinfo = Addrinfo.tcp('127.0.0.1', 0)
- -> { Socket.unpack_sockaddr_un(addrinfo) }.should raise_error(ArgumentError)
- end
+ it 'raises an ArgumentError when passed addrinfo is not AF_UNIX' do
+ addrinfo = Addrinfo.tcp('127.0.0.1', 0)
+ -> { Socket.unpack_sockaddr_un(addrinfo) }.should raise_error(ArgumentError)
end
end
diff --git a/spec/ruby/library/socket/spec_helper.rb b/spec/ruby/library/socket/spec_helper.rb
index 1121542dd5..b33663e02d 100644
--- a/spec/ruby/library/socket/spec_helper.rb
+++ b/spec/ruby/library/socket/spec_helper.rb
@@ -2,7 +2,6 @@ require_relative '../../spec_helper'
require 'socket'
MSpec.enable_feature :sock_packet if Socket.const_defined?(:SOCK_PACKET)
-MSpec.enable_feature :unix_socket unless PlatformGuard.windows?
MSpec.enable_feature :udp_cork if Socket.const_defined?(:UDP_CORK)
MSpec.enable_feature :tcp_cork if Socket.const_defined?(:TCP_CORK)
MSpec.enable_feature :pktinfo if Socket.const_defined?(:IP_PKTINFO)
diff --git a/spec/ruby/library/socket/tcpsocket/gethostbyname_spec.rb b/spec/ruby/library/socket/tcpsocket/gethostbyname_spec.rb
index f0e98778f5..5a2c704f35 100644
--- a/spec/ruby/library/socket/tcpsocket/gethostbyname_spec.rb
+++ b/spec/ruby/library/socket/tcpsocket/gethostbyname_spec.rb
@@ -2,7 +2,7 @@ require_relative '../spec_helper'
require_relative '../fixtures/classes'
# TODO: verify these for windows
-describe "TCPSocket#gethostbyname" do
+describe "TCPSocket.gethostbyname" do
before :each do
suppress_warning do
@host_info = TCPSocket.gethostbyname(SocketSpecs.hostname)
@@ -52,7 +52,7 @@ describe "TCPSocket#gethostbyname" do
end
end
-describe 'TCPSocket#gethostbyname' do
+describe 'TCPSocket.gethostbyname' do
it 'returns an Array' do
suppress_warning do
TCPSocket.gethostbyname('127.0.0.1').should be_an_instance_of(Array)
diff --git a/spec/ruby/library/socket/tcpsocket/shared/new.rb b/spec/ruby/library/socket/tcpsocket/shared/new.rb
index 90f8d7e6a2..0e405253c8 100644
--- a/spec/ruby/library/socket/tcpsocket/shared/new.rb
+++ b/spec/ruby/library/socket/tcpsocket/shared/new.rb
@@ -14,26 +14,13 @@ describe :tcpsocket_new, shared: true do
}
end
- ruby_version_is ""..."3.2" 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)
- rescue Errno::ENETUNREACH
- # In the case all network interfaces down.
- # raise_error cannot deal with multiple expected exceptions
- end
- end
-
- ruby_version_is "3.2" do
- it 'raises IO::TimeoutError 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(IO::TimeoutError)
- rescue Errno::ENETUNREACH
- # In the case all network interfaces down.
- # raise_error cannot deal with multiple expected exceptions
- end
+ it 'raises IO::TimeoutError 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(IO::TimeoutError)
+ rescue Errno::ENETUNREACH
+ # In the case all network interfaces down.
+ # raise_error cannot deal with multiple expected exceptions
end
describe "with a running server" do
@@ -66,14 +53,23 @@ describe :tcpsocket_new, shared: true do
end
it "connects to a server when passed local_host and local_port arguments" do
- server = TCPServer.new(SocketSpecs.hostname, 0)
+ retries = 0
+ max_retries = 3
+
begin
- available_port = server.addr[1]
- ensure
- server.close
+ retries += 1
+ server = TCPServer.new(SocketSpecs.hostname, 0)
+ begin
+ available_port = server.addr[1]
+ ensure
+ server.close
+ end
+ @socket = TCPSocket.send(@method, @hostname, @server.port,
+ @hostname, available_port)
+ rescue Errno::EADDRINUSE
+ raise if retries >= max_retries
+ retry
end
- @socket = TCPSocket.send(@method, @hostname, @server.port,
- @hostname, available_port)
@socket.should be_an_instance_of(TCPSocket)
end
diff --git a/spec/ruby/library/socket/unixserver/accept_nonblock_spec.rb b/spec/ruby/library/socket/unixserver/accept_nonblock_spec.rb
index dba3de7359..f67941b296 100644
--- a/spec/ruby/library/socket/unixserver/accept_nonblock_spec.rb
+++ b/spec/ruby/library/socket/unixserver/accept_nonblock_spec.rb
@@ -1,87 +1,85 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
-with_feature :unix_socket do
- describe "UNIXServer#accept_nonblock" do
- before :each do
- @path = SocketSpecs.socket_path
- @server = UNIXServer.open(@path)
- @client = UNIXSocket.open(@path)
+describe "UNIXServer#accept_nonblock" do
+ before :each do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.open(@path)
+ @client = UNIXSocket.open(@path)
- @socket = @server.accept_nonblock
- @client.send("foobar", 0)
- end
+ @socket = @server.accept_nonblock
+ @client.send("foobar", 0)
+ end
- after :each do
- @socket.close
- @client.close
- @server.close
- SocketSpecs.rm_socket @path
- end
+ after :each do
+ @socket.close
+ @client.close
+ @server.close
+ SocketSpecs.rm_socket @path
+ end
- it "accepts a connection in a non-blocking way" do
- data = @socket.recvfrom(6).first
- data.should == "foobar"
- end
+ it "accepts a connection in a non-blocking way" do
+ data = @socket.recvfrom(6).first
+ data.should == "foobar"
+ end
- it "returns a UNIXSocket" do
- @socket.should be_kind_of(UNIXSocket)
- end
+ it "returns a UNIXSocket" do
+ @socket.should be_kind_of(UNIXSocket)
+ end
+
+ it 'returns :wait_readable in exceptionless mode' do
+ @server.accept_nonblock(exception: false).should == :wait_readable
+ end
+end
- it 'returns :wait_readable in exceptionless mode' do
- @server.accept_nonblock(exception: false).should == :wait_readable
+describe 'UNIXServer#accept_nonblock' do
+ before do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.new(@path)
+ end
+
+ after do
+ @server.close
+ rm_r(@path)
+ end
+
+ describe 'without a client' do
+ it 'raises IO::WaitReadable' do
+ -> { @server.accept_nonblock }.should raise_error(IO::WaitReadable)
end
end
- describe 'UNIXServer#accept_nonblock' do
+ describe 'with a client' do
before do
- @path = SocketSpecs.socket_path
- @server = UNIXServer.new(@path)
+ @client = UNIXSocket.new(@path)
end
after do
- @server.close
- rm_r(@path)
+ @client.close
+ @socket.close if @socket
end
- describe 'without a client' do
- it 'raises IO::WaitReadable' do
- -> { @server.accept_nonblock }.should raise_error(IO::WaitReadable)
+ describe 'without any data' do
+ it 'returns a UNIXSocket' do
+ @socket = @server.accept_nonblock
+ @socket.should be_an_instance_of(UNIXSocket)
end
end
- describe 'with a client' do
+ describe 'with data available' do
before do
- @client = UNIXSocket.new(@path)
- end
-
- after do
- @client.close
- @socket.close if @socket
+ @client.write('hello')
end
- describe 'without any data' do
- it 'returns a UNIXSocket' do
- @socket = @server.accept_nonblock
- @socket.should be_an_instance_of(UNIXSocket)
- end
+ it 'returns a UNIXSocket' do
+ @socket = @server.accept_nonblock
+ @socket.should be_an_instance_of(UNIXSocket)
end
- describe 'with data available' do
- before do
- @client.write('hello')
- end
-
- it 'returns a UNIXSocket' do
+ describe 'the returned UNIXSocket' do
+ it 'can read the data written' do
@socket = @server.accept_nonblock
- @socket.should be_an_instance_of(UNIXSocket)
- end
-
- describe 'the returned UNIXSocket' do
- it 'can read the data written' do
- @socket = @server.accept_nonblock
- @socket.recv(5).should == 'hello'
- end
+ @socket.recv(5).should == 'hello'
end
end
end
diff --git a/spec/ruby/library/socket/unixserver/accept_spec.rb b/spec/ruby/library/socket/unixserver/accept_spec.rb
index 1305bc6220..cc2c922b6f 100644
--- a/spec/ruby/library/socket/unixserver/accept_spec.rb
+++ b/spec/ruby/library/socket/unixserver/accept_spec.rb
@@ -1,126 +1,124 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
-with_feature :unix_socket do
- describe "UNIXServer#accept" do
- before :each do
- @path = SocketSpecs.socket_path
- @server = UNIXServer.open(@path)
- end
+describe "UNIXServer#accept" do
+ before :each do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.open(@path)
+ end
- after :each do
- @server.close if @server
- SocketSpecs.rm_socket @path
- end
+ after :each do
+ @server.close if @server
+ SocketSpecs.rm_socket @path
+ end
- it "accepts what is written by the client" do
- client = UNIXSocket.open(@path)
+ it "accepts what is written by the client" do
+ client = UNIXSocket.open(@path)
- client.send('hello', 0)
+ client.send('hello', 0)
- sock = @server.accept
- begin
- data, info = sock.recvfrom(5)
+ sock = @server.accept
+ begin
+ data, info = sock.recvfrom(5)
- data.should == 'hello'
- info.should_not be_empty
- ensure
- sock.close
- client.close
- end
+ data.should == 'hello'
+ info.should_not be_empty
+ ensure
+ sock.close
+ client.close
end
+ end
- it "can be interrupted by Thread#kill" do
- t = Thread.new {
- @server.accept
- }
- Thread.pass while t.status and t.status != "sleep"
-
- # kill thread, ensure it dies in a reasonable amount of time
- t.kill
- a = 0
- while t.alive? and a < 5000
- sleep 0.001
- a += 1
- end
- a.should < 5000
+ it "can be interrupted by Thread#kill" do
+ t = Thread.new {
+ @server.accept
+ }
+ Thread.pass while t.status and t.status != "sleep"
+
+ # kill thread, ensure it dies in a reasonable amount of time
+ t.kill
+ a = 0
+ while t.alive? and a < 5000
+ sleep 0.001
+ a += 1
end
+ a.should < 5000
+ end
- it "can be interrupted by Thread#raise" do
- t = Thread.new {
- -> {
- @server.accept
- }.should raise_error(Exception, "interrupted")
- }
+ it "can be interrupted by Thread#raise" do
+ t = Thread.new {
+ -> {
+ @server.accept
+ }.should raise_error(Exception, "interrupted")
+ }
- Thread.pass while t.status and t.status != "sleep"
- t.raise Exception, "interrupted"
- t.join
- end
+ Thread.pass while t.status and t.status != "sleep"
+ t.raise Exception, "interrupted"
+ t.join
end
end
-with_feature :unix_socket do
- describe 'UNIXServer#accept' do
+describe 'UNIXServer#accept' do
+ before do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.new(@path)
+ end
+
+ after do
+ @server.close
+ rm_r(@path)
+ end
+
+ describe 'without a client' do
+ it 'blocks the calling thread' do
+ -> { @server.accept }.should block_caller
+ end
+ end
+
+ describe 'with a client' do
before do
- @path = SocketSpecs.socket_path
- @server = UNIXServer.new(@path)
+ @client = UNIXSocket.new(@path)
end
after do
- @server.close
- rm_r(@path)
+ @client.close
+ @socket.close if @socket
end
- describe 'without a client' do
- it 'blocks the calling thread' do
- -> { @server.accept }.should block_caller
+ describe 'without any data' do
+ it 'returns a UNIXSocket' do
+ @socket = @server.accept
+ @socket.should be_an_instance_of(UNIXSocket)
end
end
- describe 'with a client' do
+ describe 'with data available' do
before do
- @client = UNIXSocket.new(@path)
- end
-
- after do
- @client.close
- @socket.close if @socket
+ @client.write('hello')
end
- describe 'without any data' do
- it 'returns a UNIXSocket' do
- @socket = @server.accept
- @socket.should be_an_instance_of(UNIXSocket)
- end
+ it 'returns a UNIXSocket' do
+ @socket = @server.accept
+ @socket.should be_an_instance_of(UNIXSocket)
end
- describe 'with data available' do
- before do
- @client.write('hello')
- end
-
- it 'returns a UNIXSocket' do
+ describe 'the returned UNIXSocket' do
+ it 'can read the data written' do
@socket = @server.accept
- @socket.should be_an_instance_of(UNIXSocket)
+ @socket.recv(5).should == 'hello'
end
- describe 'the returned UNIXSocket' do
- it 'can read the data written' do
- @socket = @server.accept
- @socket.recv(5).should == 'hello'
- end
-
+ platform_is_not :windows do
it "is set to nonblocking" do
require 'io/nonblock'
@socket = @server.accept
@socket.should.nonblock?
end
+ end
- it "is set to close on exec" do
- @socket = @server.accept
- @socket.should.close_on_exec?
- end
+ it "is set to close on exec" do
+ @socket = @server.accept
+ @socket.should.close_on_exec?
end
end
end
diff --git a/spec/ruby/library/socket/unixserver/for_fd_spec.rb b/spec/ruby/library/socket/unixserver/for_fd_spec.rb
index 8cc55ef391..be1c2df4d7 100644
--- a/spec/ruby/library/socket/unixserver/for_fd_spec.rb
+++ b/spec/ruby/library/socket/unixserver/for_fd_spec.rb
@@ -1,23 +1,21 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
-with_feature :unix_socket do
- describe "UNIXServer.for_fd" do
- before :each do
- @unix_path = SocketSpecs.socket_path
- @unix = UNIXServer.new(@unix_path)
- end
+describe "UNIXServer.for_fd" do
+ before :each do
+ @unix_path = SocketSpecs.socket_path
+ @unix = UNIXServer.new(@unix_path)
+ end
- after :each do
- @unix.close if @unix
- SocketSpecs.rm_socket @unix_path
- end
+ after :each do
+ @unix.close if @unix
+ SocketSpecs.rm_socket @unix_path
+ end
- it "can calculate the path" do
- b = UNIXServer.for_fd(@unix.fileno)
- b.autoclose = false
+ it "can calculate the path" do
+ b = UNIXServer.for_fd(@unix.fileno)
+ b.autoclose = false
- b.path.should == @unix_path
- end
+ b.path.should == @unix_path
end
end
diff --git a/spec/ruby/library/socket/unixserver/initialize_spec.rb b/spec/ruby/library/socket/unixserver/initialize_spec.rb
index 0cc49ef1eb..3728a307b0 100644
--- a/spec/ruby/library/socket/unixserver/initialize_spec.rb
+++ b/spec/ruby/library/socket/unixserver/initialize_spec.rb
@@ -1,28 +1,26 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
-with_feature :unix_socket do
- describe 'UNIXServer#initialize' do
- before do
- @path = SocketSpecs.socket_path
- @server = UNIXServer.new(@path)
- end
+describe 'UNIXServer#initialize' do
+ before do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.new(@path)
+ end
- after do
- @server.close if @server
- rm_r @path
- end
+ after do
+ @server.close if @server
+ rm_r @path
+ end
- it 'returns a new UNIXServer' do
- @server.should be_an_instance_of(UNIXServer)
- end
+ it 'returns a new UNIXServer' do
+ @server.should be_an_instance_of(UNIXServer)
+ end
- it 'sets the socket to binmode' do
- @server.binmode?.should be_true
- end
+ it 'sets the socket to binmode' do
+ @server.binmode?.should be_true
+ end
- it 'raises Errno::EADDRINUSE when the socket is already in use' do
- -> { UNIXServer.new(@path) }.should raise_error(Errno::EADDRINUSE)
- end
+ it 'raises Errno::EADDRINUSE when the socket is already in use' do
+ -> { UNIXServer.new(@path) }.should raise_error(Errno::EADDRINUSE)
end
end
diff --git a/spec/ruby/library/socket/unixserver/listen_spec.rb b/spec/ruby/library/socket/unixserver/listen_spec.rb
index b90b3bbb09..7938d648c4 100644
--- a/spec/ruby/library/socket/unixserver/listen_spec.rb
+++ b/spec/ruby/library/socket/unixserver/listen_spec.rb
@@ -1,21 +1,19 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
-with_feature :unix_socket do
- describe 'UNIXServer#listen' do
- before do
- @path = SocketSpecs.socket_path
- @server = UNIXServer.new(@path)
- end
+describe 'UNIXServer#listen' do
+ before do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.new(@path)
+ end
- after do
- @server.close
+ after do
+ @server.close
- rm_r(@path)
- end
+ rm_r(@path)
+ end
- it 'returns 0' do
- @server.listen(1).should == 0
- end
+ it 'returns 0' do
+ @server.listen(1).should == 0
end
end
diff --git a/spec/ruby/library/socket/unixserver/new_spec.rb b/spec/ruby/library/socket/unixserver/new_spec.rb
index a160e3ce5c..7d0c7bf76e 100644
--- a/spec/ruby/library/socket/unixserver/new_spec.rb
+++ b/spec/ruby/library/socket/unixserver/new_spec.rb
@@ -1,14 +1,12 @@
require_relative '../spec_helper'
require_relative 'shared/new'
-with_feature :unix_socket do
- describe "UNIXServer.new" do
- it_behaves_like :unixserver_new, :new
+describe "UNIXServer.new" do
+ it_behaves_like :unixserver_new, :new
- it "does not use the given block and warns to use UNIXServer::open" do
- -> {
- @server = UNIXServer.new(@path) { raise }
- }.should complain(/warning: UNIXServer::new\(\) does not take block; use UNIXServer::open\(\) instead/)
- end
+ it "does not use the given block and warns to use UNIXServer::open" do
+ -> {
+ @server = UNIXServer.new(@path) { raise }
+ }.should complain(/warning: UNIXServer::new\(\) does not take block; use UNIXServer::open\(\) instead/)
end
end
diff --git a/spec/ruby/library/socket/unixserver/open_spec.rb b/spec/ruby/library/socket/unixserver/open_spec.rb
index 16453dd3bd..c49df802d0 100644
--- a/spec/ruby/library/socket/unixserver/open_spec.rb
+++ b/spec/ruby/library/socket/unixserver/open_spec.rb
@@ -2,25 +2,23 @@ require_relative '../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/new'
-with_feature :unix_socket do
- describe "UNIXServer.open" do
- it_behaves_like :unixserver_new, :open
+describe "UNIXServer.open" do
+ it_behaves_like :unixserver_new, :open
- before :each do
- @path = SocketSpecs.socket_path
- end
+ before :each do
+ @path = SocketSpecs.socket_path
+ end
- after :each do
- @server.close if @server
- @server = nil
- SocketSpecs.rm_socket @path
- end
+ after :each do
+ @server.close if @server
+ @server = nil
+ SocketSpecs.rm_socket @path
+ end
- it "yields the new UNIXServer object to the block, if given" do
- UNIXServer.open(@path) do |unix|
- unix.path.should == @path
- unix.addr.should == ["AF_UNIX", @path]
- end
+ it "yields the new UNIXServer object to the block, if given" do
+ UNIXServer.open(@path) do |unix|
+ unix.path.should == @path
+ unix.addr.should == ["AF_UNIX", @path]
end
end
end
diff --git a/spec/ruby/library/socket/unixserver/sysaccept_spec.rb b/spec/ruby/library/socket/unixserver/sysaccept_spec.rb
index e59731878a..c4a4ecc824 100644
--- a/spec/ruby/library/socket/unixserver/sysaccept_spec.rb
+++ b/spec/ruby/library/socket/unixserver/sysaccept_spec.rb
@@ -1,51 +1,49 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
-with_feature :unix_socket do
- describe 'UNIXServer#sysaccept' do
+describe 'UNIXServer#sysaccept' do
+ before do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.new(@path)
+ end
+
+ after do
+ @server.close
+
+ rm_r(@path)
+ end
+
+ describe 'without a client' do
+ it 'blocks the calling thread' do
+ -> { @server.sysaccept }.should block_caller
+ end
+ end
+
+ describe 'with a client' do
before do
- @path = SocketSpecs.socket_path
- @server = UNIXServer.new(@path)
+ @client = UNIXSocket.new(@path)
end
after do
- @server.close
-
- rm_r(@path)
+ Socket.for_fd(@fd).close if @fd
+ @client.close
end
- describe 'without a client' do
- it 'blocks the calling thread' do
- -> { @server.sysaccept }.should block_caller
+ describe 'without any data' do
+ it 'returns an Integer' do
+ @fd = @server.sysaccept
+ @fd.should be_kind_of(Integer)
end
end
- describe 'with a client' do
+ describe 'with data available' do
before do
- @client = UNIXSocket.new(@path)
- end
-
- after do
- Socket.for_fd(@fd).close if @fd
- @client.close
+ @client.write('hello')
end
- describe 'without any data' do
- it 'returns an Integer' do
- @fd = @server.sysaccept
- @fd.should be_kind_of(Integer)
- end
- end
-
- describe 'with data available' do
- before do
- @client.write('hello')
- end
-
- it 'returns an Integer' do
- @fd = @server.sysaccept
- @fd.should be_kind_of(Integer)
- end
+ it 'returns an Integer' do
+ @fd = @server.sysaccept
+ @fd.should be_kind_of(Integer)
end
end
end
diff --git a/spec/ruby/library/socket/unixsocket/addr_spec.rb b/spec/ruby/library/socket/unixsocket/addr_spec.rb
index d93e061312..1afe9b12dc 100644
--- a/spec/ruby/library/socket/unixsocket/addr_spec.rb
+++ b/spec/ruby/library/socket/unixsocket/addr_spec.rb
@@ -1,35 +1,33 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
-with_feature :unix_socket do
- describe "UNIXSocket#addr" do
- before :each do
- @path = SocketSpecs.socket_path
- @server = UNIXServer.open(@path)
- @client = UNIXSocket.open(@path)
- end
+describe "UNIXSocket#addr" do
+ before :each do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.open(@path)
+ @client = UNIXSocket.open(@path)
+ end
- after :each do
- @client.close
- @server.close
- SocketSpecs.rm_socket @path
- end
+ after :each do
+ @client.close
+ @server.close
+ SocketSpecs.rm_socket @path
+ end
- it "returns an array" do
- @client.addr.should be_kind_of(Array)
- end
+ it "returns an array" do
+ @client.addr.should be_kind_of(Array)
+ end
- it "returns the address family of this socket in an array" do
- @client.addr[0].should == "AF_UNIX"
- @server.addr[0].should == "AF_UNIX"
- end
+ it "returns the address family of this socket in an array" do
+ @client.addr[0].should == "AF_UNIX"
+ @server.addr[0].should == "AF_UNIX"
+ end
- it "returns the path of the socket in an array if it's a server" do
- @server.addr[1].should == @path
- end
+ it "returns the path of the socket in an array if it's a server" do
+ @server.addr[1].should == @path
+ end
- it "returns an empty string for path if it's a client" do
- @client.addr[1].should == ""
- end
+ it "returns an empty string for path if it's a client" do
+ @client.addr[1].should == ""
end
end
diff --git a/spec/ruby/library/socket/unixsocket/initialize_spec.rb b/spec/ruby/library/socket/unixsocket/initialize_spec.rb
index bf7896ab0e..5dccfcc745 100644
--- a/spec/ruby/library/socket/unixsocket/initialize_spec.rb
+++ b/spec/ruby/library/socket/unixsocket/initialize_spec.rb
@@ -1,48 +1,56 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
-with_feature :unix_socket do
- describe 'UNIXSocket#initialize' do
- describe 'using a non existing path' do
+describe 'UNIXSocket#initialize' do
+ describe 'using a non existing path' do
+ platform_is_not :windows do
it 'raises Errno::ENOENT' do
-> { UNIXSocket.new(SocketSpecs.socket_path) }.should raise_error(Errno::ENOENT)
end
end
- describe 'using an existing socket path' do
- before do
- @path = SocketSpecs.socket_path
- @server = UNIXServer.new(@path)
- @socket = UNIXSocket.new(@path)
+ platform_is :windows do
+ # Why, Windows, why?
+ it 'raises Errno::ECONNREFUSED' do
+ -> { UNIXSocket.new(SocketSpecs.socket_path) }.should raise_error(Errno::ECONNREFUSED)
end
+ end
+ end
- after do
- @socket.close
- @server.close
- rm_r(@path)
- end
+ describe 'using an existing socket path' do
+ before do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.new(@path)
+ @socket = UNIXSocket.new(@path)
+ end
- it 'returns a new UNIXSocket' do
- @socket.should be_an_instance_of(UNIXSocket)
- end
+ after do
+ @socket.close
+ @server.close
+ rm_r(@path)
+ end
- it 'sets the socket path to an empty String' do
- @socket.path.should == ''
- end
+ it 'returns a new UNIXSocket' do
+ @socket.should be_an_instance_of(UNIXSocket)
+ end
- it 'sets the socket to binmode' do
- @socket.binmode?.should be_true
- end
+ it 'sets the socket path to an empty String' do
+ @socket.path.should == ''
+ end
+
+ it 'sets the socket to binmode' do
+ @socket.binmode?.should be_true
+ end
+ platform_is_not :windows do
it 'sets the socket to nonblock' do
require 'io/nonblock'
@socket.should.nonblock?
end
+ end
- it 'sets the socket to close on exec' do
- @socket.should.close_on_exec?
- end
-
+ it 'sets the socket to close on exec' do
+ @socket.should.close_on_exec?
end
end
end
diff --git a/spec/ruby/library/socket/unixsocket/inspect_spec.rb b/spec/ruby/library/socket/unixsocket/inspect_spec.rb
index a542ba6db5..77bb521069 100644
--- a/spec/ruby/library/socket/unixsocket/inspect_spec.rb
+++ b/spec/ruby/library/socket/unixsocket/inspect_spec.rb
@@ -1,17 +1,15 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
-with_feature :unix_socket do
- describe "UNIXSocket#inspect" do
- it "returns sockets fd for unnamed sockets" do
- begin
- s1, s2 = UNIXSocket.socketpair
- s1.inspect.should == "#<UNIXSocket:fd #{s1.fileno}>"
- s2.inspect.should == "#<UNIXSocket:fd #{s2.fileno}>"
- ensure
- s1.close
- s2.close
- end
+describe "UNIXSocket#inspect" do
+ it "returns sockets fd for unnamed sockets" do
+ begin
+ s1, s2 = UNIXSocket.socketpair
+ s1.inspect.should == "#<UNIXSocket:fd #{s1.fileno}>"
+ s2.inspect.should == "#<UNIXSocket:fd #{s2.fileno}>"
+ ensure
+ s1.close
+ s2.close
end
end
end
diff --git a/spec/ruby/library/socket/unixsocket/local_address_spec.rb b/spec/ruby/library/socket/unixsocket/local_address_spec.rb
index 734253e7f5..0fdec38293 100644
--- a/spec/ruby/library/socket/unixsocket/local_address_spec.rb
+++ b/spec/ruby/library/socket/unixsocket/local_address_spec.rb
@@ -1,94 +1,92 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
-with_feature :unix_socket do
- describe 'UNIXSocket#local_address' do
- before do
- @path = SocketSpecs.socket_path
- @server = UNIXServer.new(@path)
- @client = UNIXSocket.new(@path)
- end
+describe 'UNIXSocket#local_address' do
+ before do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.new(@path)
+ @client = UNIXSocket.new(@path)
+ end
- after do
- @client.close
- @server.close
+ after do
+ @client.close
+ @server.close
- rm_r(@path)
- end
-
- it 'returns an Addrinfo' do
- @client.local_address.should be_an_instance_of(Addrinfo)
- end
+ rm_r(@path)
+ end
- describe 'the returned Addrinfo' do
- platform_is_not :aix do
- it 'uses AF_UNIX as the address family' do
- @client.local_address.afamily.should == Socket::AF_UNIX
- end
+ it 'returns an Addrinfo' do
+ @client.local_address.should be_an_instance_of(Addrinfo)
+ end
- it 'uses PF_UNIX as the protocol family' do
- @client.local_address.pfamily.should == Socket::PF_UNIX
- end
+ describe 'the returned Addrinfo' do
+ platform_is_not :aix do
+ it 'uses AF_UNIX as the address family' do
+ @client.local_address.afamily.should == Socket::AF_UNIX
end
- it 'uses SOCK_STREAM as the socket type' do
- @client.local_address.socktype.should == Socket::SOCK_STREAM
+ it 'uses PF_UNIX as the protocol family' do
+ @client.local_address.pfamily.should == Socket::PF_UNIX
end
+ end
- platform_is_not :aix do
- it 'uses an empty socket path' do
- @client.local_address.unix_path.should == ''
- end
- end
+ it 'uses SOCK_STREAM as the socket type' do
+ @client.local_address.socktype.should == Socket::SOCK_STREAM
+ end
- it 'uses 0 as the protocol' do
- @client.local_address.protocol.should == 0
+ platform_is_not :aix do
+ it 'uses an empty socket path' do
+ @client.local_address.unix_path.should == ''
end
end
- end
- describe 'UNIXSocket#local_address with a UNIX socket pair' do
- before :each do
- @sock, @sock2 = Socket.pair(Socket::AF_UNIX, Socket::SOCK_STREAM)
+ it 'uses 0 as the protocol' do
+ @client.local_address.protocol.should == 0
end
+ end
+end
- after :each do
- @sock.close
- @sock2.close
- end
+describe 'UNIXSocket#local_address with a UNIX socket pair' do
+ before :each do
+ @sock, @sock2 = Socket.pair(Socket::AF_UNIX, Socket::SOCK_STREAM)
+ end
- it 'returns an Addrinfo' do
- @sock.local_address.should be_an_instance_of(Addrinfo)
- end
+ after :each do
+ @sock.close
+ @sock2.close
+ end
- describe 'the returned Addrinfo' do
- it 'uses AF_UNIX as the address family' do
- @sock.local_address.afamily.should == Socket::AF_UNIX
- end
+ it 'returns an Addrinfo' do
+ @sock.local_address.should be_an_instance_of(Addrinfo)
+ end
- it 'uses PF_UNIX as the protocol family' do
- @sock.local_address.pfamily.should == Socket::PF_UNIX
- end
+ describe 'the returned Addrinfo' do
+ it 'uses AF_UNIX as the address family' do
+ @sock.local_address.afamily.should == Socket::AF_UNIX
+ end
- it 'uses SOCK_STREAM as the socket type' do
- @sock.local_address.socktype.should == Socket::SOCK_STREAM
- end
+ it 'uses PF_UNIX as the protocol family' do
+ @sock.local_address.pfamily.should == Socket::PF_UNIX
+ end
- it 'raises SocketError for #ip_address' do
- -> {
- @sock.local_address.ip_address
- }.should raise_error(SocketError, "need IPv4 or IPv6 address")
- end
+ it 'uses SOCK_STREAM as the socket type' do
+ @sock.local_address.socktype.should == Socket::SOCK_STREAM
+ end
- it 'raises SocketError for #ip_port' do
- -> {
- @sock.local_address.ip_port
- }.should raise_error(SocketError, "need IPv4 or IPv6 address")
- end
+ it 'raises SocketError for #ip_address' do
+ -> {
+ @sock.local_address.ip_address
+ }.should raise_error(SocketError, "need IPv4 or IPv6 address")
+ end
- it 'uses 0 as the protocol' do
- @sock.local_address.protocol.should == 0
- end
+ it 'raises SocketError for #ip_port' do
+ -> {
+ @sock.local_address.ip_port
+ }.should raise_error(SocketError, "need IPv4 or IPv6 address")
+ end
+
+ it 'uses 0 as the protocol' do
+ @sock.local_address.protocol.should == 0
end
end
end
diff --git a/spec/ruby/library/socket/unixsocket/new_spec.rb b/spec/ruby/library/socket/unixsocket/new_spec.rb
index 6d8ea6dcfe..fea2c1e2b7 100644
--- a/spec/ruby/library/socket/unixsocket/new_spec.rb
+++ b/spec/ruby/library/socket/unixsocket/new_spec.rb
@@ -1,14 +1,12 @@
require_relative '../spec_helper'
require_relative 'shared/new'
-with_feature :unix_socket do
- describe "UNIXSocket.new" do
- it_behaves_like :unixsocket_new, :new
+describe "UNIXSocket.new" do
+ it_behaves_like :unixsocket_new, :new
- it "does not use the given block and warns to use UNIXSocket::open" do
- -> {
- @client = UNIXSocket.new(@path) { raise }
- }.should complain(/warning: UNIXSocket::new\(\) does not take block; use UNIXSocket::open\(\) instead/)
- end
+ it "does not use the given block and warns to use UNIXSocket::open" do
+ -> {
+ @client = UNIXSocket.new(@path) { raise }
+ }.should complain(/warning: UNIXSocket::new\(\) does not take block; use UNIXSocket::open\(\) instead/)
end
end
diff --git a/spec/ruby/library/socket/unixsocket/open_spec.rb b/spec/ruby/library/socket/unixsocket/open_spec.rb
index 61def30abb..b5e8c6c23a 100644
--- a/spec/ruby/library/socket/unixsocket/open_spec.rb
+++ b/spec/ruby/library/socket/unixsocket/open_spec.rb
@@ -2,27 +2,25 @@ require_relative '../spec_helper'
require_relative '../fixtures/classes'
require_relative 'shared/new'
-with_feature :unix_socket do
- describe "UNIXSocket.open" do
- it_behaves_like :unixsocket_new, :open
- end
+describe "UNIXSocket.open" do
+ it_behaves_like :unixsocket_new, :open
+end
- describe "UNIXSocket.open" do
- before :each do
- @path = SocketSpecs.socket_path
- @server = UNIXServer.open(@path)
- end
+describe "UNIXSocket.open" do
+ before :each do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.open(@path)
+ end
- after :each do
- @server.close
- SocketSpecs.rm_socket @path
- end
+ after :each do
+ @server.close
+ SocketSpecs.rm_socket @path
+ end
- 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.should_not.closed?
- end
+ 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.should_not.closed?
end
end
end
diff --git a/spec/ruby/library/socket/unixsocket/pair_spec.rb b/spec/ruby/library/socket/unixsocket/pair_spec.rb
index d80b60894d..9690142668 100644
--- a/spec/ruby/library/socket/unixsocket/pair_spec.rb
+++ b/spec/ruby/library/socket/unixsocket/pair_spec.rb
@@ -1,38 +1,18 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
require_relative '../shared/partially_closable_sockets'
+require_relative 'shared/pair'
-with_feature :unix_socket do
- describe "UNIXSocket.pair" do
- it_should_behave_like :partially_closable_sockets
+describe "UNIXSocket.pair" do
+ it_should_behave_like :unixsocket_pair
+ it_should_behave_like :partially_closable_sockets
- before :each do
- @s1, @s2 = UNIXSocket.pair
- end
-
- after :each do
- @s1.close
- @s2.close
- end
-
- it "returns a pair of connected sockets" do
- @s1.puts "foo"
- @s2.gets.should == "foo\n"
- end
-
- it "returns sockets with no name" do
- @s1.path.should == @s2.path
- @s1.path.should == ""
- end
-
- it "returns sockets with no address" do
- @s1.addr.should == ["AF_UNIX", ""]
- @s2.addr.should == ["AF_UNIX", ""]
- end
+ before :each do
+ @s1, @s2 = UNIXSocket.pair
+ end
- it "returns sockets with no peeraddr" do
- @s1.peeraddr.should == ["AF_UNIX", ""]
- @s2.peeraddr.should == ["AF_UNIX", ""]
- end
+ after :each do
+ @s1.close
+ @s2.close
end
end
diff --git a/spec/ruby/library/socket/unixsocket/partially_closable_spec.rb b/spec/ruby/library/socket/unixsocket/partially_closable_spec.rb
index ef7d0f0b2a..108a6c3063 100644
--- a/spec/ruby/library/socket/unixsocket/partially_closable_spec.rb
+++ b/spec/ruby/library/socket/unixsocket/partially_closable_spec.rb
@@ -2,22 +2,20 @@ require_relative '../spec_helper'
require_relative '../fixtures/classes'
require_relative '../shared/partially_closable_sockets'
-with_feature :unix_socket do
- describe "UNIXSocket partial closability" do
- before :each do
- @path = SocketSpecs.socket_path
- @server = UNIXServer.open(@path)
- @s1 = UNIXSocket.new(@path)
- @s2 = @server.accept
- end
-
- after :each do
- @server.close
- @s1.close
- @s2.close
- SocketSpecs.rm_socket @path
- end
+describe "UNIXSocket partial closability" do
+ before :each do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.open(@path)
+ @s1 = UNIXSocket.new(@path)
+ @s2 = @server.accept
+ end
- it_should_behave_like :partially_closable_sockets
+ after :each do
+ @server.close
+ @s1.close
+ @s2.close
+ SocketSpecs.rm_socket @path
end
+
+ it_should_behave_like :partially_closable_sockets
end
diff --git a/spec/ruby/library/socket/unixsocket/path_spec.rb b/spec/ruby/library/socket/unixsocket/path_spec.rb
index a608378e4f..ffe7e4bea2 100644
--- a/spec/ruby/library/socket/unixsocket/path_spec.rb
+++ b/spec/ruby/library/socket/unixsocket/path_spec.rb
@@ -1,26 +1,24 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
-with_feature :unix_socket do
- describe "UNIXSocket#path" do
- before :each do
- @path = SocketSpecs.socket_path
- @server = UNIXServer.open(@path)
- @client = UNIXSocket.open(@path)
- end
+describe "UNIXSocket#path" do
+ before :each do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.open(@path)
+ @client = UNIXSocket.open(@path)
+ end
- after :each do
- @client.close
- @server.close
- SocketSpecs.rm_socket @path
- end
+ after :each do
+ @client.close
+ @server.close
+ SocketSpecs.rm_socket @path
+ end
- it "returns the path of the socket if it's a server" do
- @server.path.should == @path
- end
+ it "returns the path of the socket if it's a server" do
+ @server.path.should == @path
+ end
- it "returns an empty string for path if it's a client" do
- @client.path.should == ""
- end
+ it "returns an empty string for path if it's a client" do
+ @client.path.should == ""
end
end
diff --git a/spec/ruby/library/socket/unixsocket/peeraddr_spec.rb b/spec/ruby/library/socket/unixsocket/peeraddr_spec.rb
index 72bc96b1fe..10cab13b42 100644
--- a/spec/ruby/library/socket/unixsocket/peeraddr_spec.rb
+++ b/spec/ruby/library/socket/unixsocket/peeraddr_spec.rb
@@ -1,28 +1,26 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
-with_feature :unix_socket do
- describe "UNIXSocket#peeraddr" do
- before :each do
- @path = SocketSpecs.socket_path
- @server = UNIXServer.open(@path)
- @client = UNIXSocket.open(@path)
- end
+describe "UNIXSocket#peeraddr" do
+ before :each do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.open(@path)
+ @client = UNIXSocket.open(@path)
+ end
- after :each do
- @client.close
- @server.close
- SocketSpecs.rm_socket @path
- end
+ after :each do
+ @client.close
+ @server.close
+ SocketSpecs.rm_socket @path
+ end
- it "returns the address family and path of the server end of the connection" do
- @client.peeraddr.should == ["AF_UNIX", @path]
- end
+ it "returns the address family and path of the server end of the connection" do
+ @client.peeraddr.should == ["AF_UNIX", @path]
+ end
- it "raises an error in server sockets" do
- -> {
- @server.peeraddr
- }.should raise_error(Errno::ENOTCONN)
- end
+ it "raises an error in server sockets" do
+ -> {
+ @server.peeraddr
+ }.should raise_error(Errno::ENOTCONN)
end
end
diff --git a/spec/ruby/library/socket/unixsocket/recv_io_spec.rb b/spec/ruby/library/socket/unixsocket/recv_io_spec.rb
index 1dbc4538e3..f0b408f309 100644
--- a/spec/ruby/library/socket/unixsocket/recv_io_spec.rb
+++ b/spec/ruby/library/socket/unixsocket/recv_io_spec.rb
@@ -1,7 +1,7 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
-with_feature :unix_socket do
+platform_is_not :windows do
describe "UNIXSocket#recv_io" do
before :each do
@path = SocketSpecs.socket_path
diff --git a/spec/ruby/library/socket/unixsocket/recvfrom_spec.rb b/spec/ruby/library/socket/unixsocket/recvfrom_spec.rb
index d849fdc302..9ae3777961 100644
--- a/spec/ruby/library/socket/unixsocket/recvfrom_spec.rb
+++ b/spec/ruby/library/socket/unixsocket/recvfrom_spec.rb
@@ -1,59 +1,105 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
-with_feature :unix_socket do
- describe "UNIXSocket#recvfrom" do
- before :each do
- @path = SocketSpecs.socket_path
- @server = UNIXServer.open(@path)
- @client = UNIXSocket.open(@path)
+describe "UNIXSocket#recvfrom" do
+ before :each do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.open(@path)
+ @client = UNIXSocket.open(@path)
+ end
+
+ after :each do
+ @client.close
+ @server.close
+ SocketSpecs.rm_socket @path
+ end
+
+ it "receives len bytes from sock, returning an array containing sent data as first element" do
+ @client.send("foobar", 0)
+ sock = @server.accept
+ sock.recvfrom(6).first.should == "foobar"
+ sock.close
+ end
+
+ context "when called on a server's socket" do
+ platform_is_not :windows do
+ it "returns an array containing basic information on the client as second element" do
+ @client.send("foobar", 0)
+ sock = @server.accept
+ data = sock.recvfrom(6)
+ data.last.should == ["AF_UNIX", ""]
+ sock.close
+ end
end
- after :each do
- @client.close
- @server.close
- SocketSpecs.rm_socket @path
+ guard -> { platform_is :windows and ruby_bug "#21702", ""..."4.2" } do
+ it "returns an array containing basic information on the client as second element" do
+ @client.send("foobar", 0)
+ sock = @server.accept
+ data = sock.recvfrom(6)
+ data.last.should == ["AF_UNIX", ""]
+ sock.close
+ end
end
+ end
- it "receives len bytes from sock" do
- @client.send("foobar", 0)
- sock = @server.accept
- sock.recvfrom(6).first.should == "foobar"
- sock.close
+ context "when called on a client's socket" do
+ platform_is :linux do
+ it "returns an array containing server's address as second element" do
+ @client.send("", 0)
+ sock = @server.accept
+ sock.send("barfoo", 0)
+ @client.recvfrom(6).last.should == ["AF_UNIX", @server.local_address.unix_path]
+ sock.close
+ end
end
- it "returns an array with data and information on the sender" do
- @client.send("foobar", 0)
- sock = @server.accept
- data = sock.recvfrom(6)
- data.first.should == "foobar"
- data.last.should == ["AF_UNIX", ""]
- sock.close
+ guard -> { platform_is :windows and ruby_bug "#21702", ""..."4.2" } do
+ it "returns an array containing server's address as second element" do
+ @client.send("", 0)
+ sock = @server.accept
+ sock.send("barfoo", 0)
+ # This may not be correct, depends on what underlying recvfrom actually returns.
+ @client.recvfrom(6).last.should == ["AF_UNIX", @server.local_address.unix_path]
+ sock.close
+ end
end
- it "allows an output buffer as third argument" do
- buffer = +''
+ platform_is :darwin do
+ it "returns an array containing basic information on the server as second element" do
+ @client.send("", 0)
+ sock = @server.accept
+ sock.send("barfoo", 0)
+ @client.recvfrom(6).last.should == ["AF_UNIX", ""]
+ sock.close
+ end
+ end
+ end
- @client.send("foobar", 0)
- sock = @server.accept
- message, = sock.recvfrom(6, 0, buffer)
- sock.close
+ it "allows an output buffer as third argument" do
+ buffer = +''
- message.should.equal?(buffer)
- buffer.should == "foobar"
- end
+ @client.send("foobar", 0)
+ sock = @server.accept
+ message, = sock.recvfrom(6, 0, buffer)
+ sock.close
- it "preserves the encoding of the given buffer" do
- buffer = ''.encode(Encoding::ISO_8859_1)
+ message.should.equal?(buffer)
+ buffer.should == "foobar"
+ end
- @client.send("foobar", 0)
- sock = @server.accept
- sock.recvfrom(6, 0, buffer)
- sock.close
+ it "preserves the encoding of the given buffer" do
+ buffer = ''.encode(Encoding::ISO_8859_1)
- buffer.encoding.should == Encoding::ISO_8859_1
- end
+ @client.send("foobar", 0)
+ sock = @server.accept
+ sock.recvfrom(6, 0, buffer)
+ sock.close
+ buffer.encoding.should == Encoding::ISO_8859_1
+ end
+
+ platform_is_not :windows do
it "uses different message options" do
@client.send("foobar", Socket::MSG_PEEK)
sock = @server.accept
@@ -65,24 +111,34 @@ with_feature :unix_socket do
sock.close
end
end
+end
- describe 'UNIXSocket#recvfrom' do
- describe 'using a socket pair' do
- before do
- @client, @server = UNIXSocket.socketpair
- @client.write('hello')
- end
+describe 'UNIXSocket#recvfrom' do
+ describe 'using a socket pair' do
+ before do
+ @client, @server = UNIXSocket.socketpair
+ @client.write('hello')
+ end
- after do
- @client.close
- @server.close
+ after do
+ @client.close
+ @server.close
+ end
+
+ platform_is_not :windows do
+ it 'returns an Array containing the data and address information' do
+ @server.recvfrom(5).should == ['hello', ['AF_UNIX', '']]
end
+ end
+ guard -> { platform_is :windows and ruby_bug "#21702", ""..."4.2" } do
it 'returns an Array containing the data and address information' do
@server.recvfrom(5).should == ['hello', ['AF_UNIX', '']]
end
end
+ end
+ platform_is_not :windows do
# These specs are taken from the rdoc examples on UNIXSocket#recvfrom.
describe 'using a UNIX socket constructed using UNIXSocket.for_fd' do
before do
diff --git a/spec/ruby/library/socket/unixsocket/remote_address_spec.rb b/spec/ruby/library/socket/unixsocket/remote_address_spec.rb
index 0b416254d0..84bdff0a6a 100644
--- a/spec/ruby/library/socket/unixsocket/remote_address_spec.rb
+++ b/spec/ruby/library/socket/unixsocket/remote_address_spec.rb
@@ -1,45 +1,43 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
-with_feature :unix_socket do
- describe 'UNIXSocket#remote_address' do
- before do
- @path = SocketSpecs.socket_path
- @server = UNIXServer.new(@path)
- @client = UNIXSocket.new(@path)
- end
+describe 'UNIXSocket#remote_address' do
+ before do
+ @path = SocketSpecs.socket_path
+ @server = UNIXServer.new(@path)
+ @client = UNIXSocket.new(@path)
+ end
- after do
- @client.close
- @server.close
+ after do
+ @client.close
+ @server.close
- rm_r(@path)
- end
+ rm_r(@path)
+ end
- it 'returns an Addrinfo' do
- @client.remote_address.should be_an_instance_of(Addrinfo)
- end
+ it 'returns an Addrinfo' do
+ @client.remote_address.should be_an_instance_of(Addrinfo)
+ end
- describe 'the returned Addrinfo' do
- it 'uses AF_UNIX as the address family' do
- @client.remote_address.afamily.should == Socket::AF_UNIX
- end
+ describe 'the returned Addrinfo' do
+ it 'uses AF_UNIX as the address family' do
+ @client.remote_address.afamily.should == Socket::AF_UNIX
+ end
- it 'uses PF_UNIX as the protocol family' do
- @client.remote_address.pfamily.should == Socket::PF_UNIX
- end
+ it 'uses PF_UNIX as the protocol family' do
+ @client.remote_address.pfamily.should == Socket::PF_UNIX
+ end
- it 'uses SOCK_STREAM as the socket type' do
- @client.remote_address.socktype.should == Socket::SOCK_STREAM
- end
+ it 'uses SOCK_STREAM as the socket type' do
+ @client.remote_address.socktype.should == Socket::SOCK_STREAM
+ end
- it 'uses the correct socket path' do
- @client.remote_address.unix_path.should == @path
- end
+ it 'uses the correct socket path' do
+ @client.remote_address.unix_path.should == @path
+ end
- it 'uses 0 as the protocol' do
- @client.remote_address.protocol.should == 0
- end
+ it 'uses 0 as the protocol' do
+ @client.remote_address.protocol.should == 0
end
end
end
diff --git a/spec/ruby/library/socket/unixsocket/send_io_spec.rb b/spec/ruby/library/socket/unixsocket/send_io_spec.rb
index 80f3550c6d..52186ec3cf 100644
--- a/spec/ruby/library/socket/unixsocket/send_io_spec.rb
+++ b/spec/ruby/library/socket/unixsocket/send_io_spec.rb
@@ -1,7 +1,7 @@
require_relative '../spec_helper'
require_relative '../fixtures/classes'
-with_feature :unix_socket do
+platform_is_not :windows do
describe "UNIXSocket#send_io" do
before :each do
@path = SocketSpecs.socket_path
diff --git a/spec/ruby/library/socket/unixsocket/shared/pair.rb b/spec/ruby/library/socket/unixsocket/shared/pair.rb
new file mode 100644
index 0000000000..d68ee466bf
--- /dev/null
+++ b/spec/ruby/library/socket/unixsocket/shared/pair.rb
@@ -0,0 +1,47 @@
+require_relative '../../spec_helper'
+require_relative '../../fixtures/classes'
+
+describe :unixsocket_pair, shared: true do
+ it "returns two UNIXSockets" do
+ @s1.should be_an_instance_of(UNIXSocket)
+ @s2.should be_an_instance_of(UNIXSocket)
+ end
+
+ it "returns a pair of connected sockets" do
+ @s1.puts "foo"
+ @s2.gets.should == "foo\n"
+ end
+
+ platform_is_not :windows do
+ it "sets the socket paths to empty Strings" do
+ @s1.path.should == ""
+ @s2.path.should == ""
+ end
+
+ it "sets the socket addresses to empty Strings" do
+ @s1.addr.should == ["AF_UNIX", ""]
+ @s2.addr.should == ["AF_UNIX", ""]
+ end
+
+ it "sets the socket peer addresses to empty Strings" do
+ @s1.peeraddr.should == ["AF_UNIX", ""]
+ @s2.peeraddr.should == ["AF_UNIX", ""]
+ end
+ end
+
+ platform_is :windows do
+ it "emulates unnamed sockets with a temporary file with a path" do
+ @s1.addr.should == ["AF_UNIX", @s1.path]
+ @s2.peeraddr.should == ["AF_UNIX", @s1.path]
+ end
+
+ it "sets the peer address of first socket to an empty string" do
+ @s1.peeraddr.should == ["AF_UNIX", ""]
+ end
+
+ it "sets the address and path of second socket to an empty string" do
+ @s2.addr.should == ["AF_UNIX", ""]
+ @s2.path.should == ""
+ end
+ end
+end
diff --git a/spec/ruby/library/socket/unixsocket/socketpair_spec.rb b/spec/ruby/library/socket/unixsocket/socketpair_spec.rb
index 3e9646f76b..c61fc00be4 100644
--- a/spec/ruby/library/socket/unixsocket/socketpair_spec.rb
+++ b/spec/ruby/library/socket/unixsocket/socketpair_spec.rb
@@ -1,40 +1,18 @@
require_relative '../spec_helper'
+require_relative '../fixtures/classes'
+require_relative '../shared/partially_closable_sockets'
+require_relative 'shared/pair'
-with_feature :unix_socket do
- describe 'UNIXSocket.socketpair' do
- before do
- @s1, @s2 = UNIXSocket.socketpair
- end
+describe "UNIXSocket.socketpair" do
+ it_should_behave_like :unixsocket_pair
+ it_should_behave_like :partially_closable_sockets
- after do
- @s1.close
- @s2.close
- end
-
- it 'returns two UNIXSockets' do
- @s1.should be_an_instance_of(UNIXSocket)
- @s2.should be_an_instance_of(UNIXSocket)
- end
-
- it 'connects the sockets to each other' do
- @s1.write('hello')
-
- @s2.recv(5).should == 'hello'
- end
-
- it 'sets the socket paths to empty Strings' do
- @s1.path.should == ''
- @s2.path.should == ''
- end
-
- it 'sets the socket addresses to empty Strings' do
- @s1.addr.should == ['AF_UNIX', '']
- @s2.addr.should == ['AF_UNIX', '']
- end
+ before :each do
+ @s1, @s2 = UNIXSocket.socketpair
+ end
- it 'sets the socket peer addresses to empty Strings' do
- @s1.peeraddr.should == ['AF_UNIX', '']
- @s2.peeraddr.should == ['AF_UNIX', '']
- end
+ after :each do
+ @s1.close
+ @s2.close
end
end
diff --git a/spec/ruby/library/stringio/each_line_spec.rb b/spec/ruby/library/stringio/each_line_spec.rb
index c68f7dae82..4ac0db7c45 100644
--- a/spec/ruby/library/stringio/each_line_spec.rb
+++ b/spec/ruby/library/stringio/each_line_spec.rb
@@ -21,3 +21,7 @@ end
describe "StringIO#each_line when passed limit" do
it_behaves_like :stringio_each_limit, :each_line
end
+
+describe "StringIO#each when passed separator and limit" do
+ it_behaves_like :stringio_each_separator_and_limit, :each_line
+end
diff --git a/spec/ruby/library/stringio/each_spec.rb b/spec/ruby/library/stringio/each_spec.rb
index 2c30ed5cda..7eb322f3ff 100644
--- a/spec/ruby/library/stringio/each_spec.rb
+++ b/spec/ruby/library/stringio/each_spec.rb
@@ -25,3 +25,7 @@ end
describe "StringIO#each when passed limit" do
it_behaves_like :stringio_each_limit, :each
end
+
+describe "StringIO#each when passed separator and limit" do
+ it_behaves_like :stringio_each_separator_and_limit, :each
+end
diff --git a/spec/ruby/library/stringio/fileno_spec.rb b/spec/ruby/library/stringio/fileno_spec.rb
index eea03a5af3..5a9f440a0f 100644
--- a/spec/ruby/library/stringio/fileno_spec.rb
+++ b/spec/ruby/library/stringio/fileno_spec.rb
@@ -1,6 +1,5 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/each'
+require 'stringio'
describe "StringIO#fileno" do
it "returns nil" do
diff --git a/spec/ruby/library/stringio/fixtures/classes.rb b/spec/ruby/library/stringio/fixtures/classes.rb
index bb8dc354cc..832c5457d7 100644
--- a/spec/ruby/library/stringio/fixtures/classes.rb
+++ b/spec/ruby/library/stringio/fixtures/classes.rb
@@ -4,12 +4,12 @@ class StringSubclass < String; end
module StringIOSpecs
def self.build
- str = <<-EOS
+ str = <<-EOS
each
peach
pear
plum
- EOS
+ EOS
StringIO.new(str)
end
end
diff --git a/spec/ruby/library/stringio/gets_spec.rb b/spec/ruby/library/stringio/gets_spec.rb
index 4af7704a41..ac876f0b4f 100644
--- a/spec/ruby/library/stringio/gets_spec.rb
+++ b/spec/ruby/library/stringio/gets_spec.rb
@@ -1,250 +1,61 @@
require_relative '../../spec_helper'
require "stringio"
+require_relative "shared/gets"
-describe "StringIO#gets when passed [separator]" do
- before :each do
- @io = StringIO.new("this>is>an>example")
- end
-
- it "returns the data read till the next occurrence of the passed separator" do
- @io.gets(">").should == "this>"
- @io.gets(">").should == "is>"
- @io.gets(">").should == "an>"
- @io.gets(">").should == "example"
- end
-
- it "sets $_ to the read content" do
- @io.gets(">")
- $_.should == "this>"
- @io.gets(">")
- $_.should == "is>"
- @io.gets(">")
- $_.should == "an>"
- @io.gets(">")
- $_.should == "example"
- @io.gets(">")
- $_.should be_nil
- end
-
- it "accepts string as separator" do
- @io.gets("is>")
- $_.should == "this>"
- @io.gets("an>")
- $_.should == "is>an>"
- @io.gets("example")
- $_.should == "example"
- @io.gets("ple")
- $_.should be_nil
- end
-
- it "updates self's lineno by one" do
- @io.gets(">")
- @io.lineno.should eql(1)
-
- @io.gets(">")
- @io.lineno.should eql(2)
-
- @io.gets(">")
- @io.lineno.should eql(3)
- end
-
- it "returns the next paragraph when the passed separator is an empty String" do
- io = StringIO.new("this is\n\nan example")
- io.gets("").should == "this is\n\n"
- io.gets("").should == "an example"
- end
-
- it "returns the remaining content starting at the current position when passed nil" do
- io = StringIO.new("this is\n\nan example")
- io.pos = 5
- io.gets(nil).should == "is\n\nan example"
- end
+describe "StringIO#gets" do
+ describe "when passed [separator]" do
+ it_behaves_like :stringio_gets_separator, :gets
- it "tries to convert the passed separator to a String using #to_str" do
- obj = mock('to_str')
- obj.should_receive(:to_str).and_return(">")
- @io.gets(obj).should == "this>"
- end
-end
-
-describe "StringIO#gets when passed no argument" do
- before :each do
- @io = StringIO.new("this is\nan example\nfor StringIO#gets")
- end
+ it "returns nil if self is at the end" do
+ @io = StringIO.new("this>is>an>example")
- it "returns the data read till the next occurrence of $/ or till eof" do
- @io.gets.should == "this is\n"
-
- begin
- old_sep = $/
- suppress_warning {$/ = " "}
- @io.gets.should == "an "
- @io.gets.should == "example\nfor "
- @io.gets.should == "StringIO#gets"
- ensure
- suppress_warning {$/ = old_sep}
+ @io.pos = 36
+ @io.gets(">").should be_nil
+ @io.gets(">").should be_nil
end
end
- it "sets $_ to the read content" do
- @io.gets
- $_.should == "this is\n"
- @io.gets
- $_.should == "an example\n"
- @io.gets
- $_.should == "for StringIO#gets"
- @io.gets
- $_.should be_nil
- end
-
- it "updates self's position" do
- @io.gets
- @io.pos.should eql(8)
-
- @io.gets
- @io.pos.should eql(19)
-
- @io.gets
- @io.pos.should eql(36)
- end
-
- it "updates self's lineno" do
- @io.gets
- @io.lineno.should eql(1)
-
- @io.gets
- @io.lineno.should eql(2)
-
- @io.gets
- @io.lineno.should eql(3)
- end
-
- it "returns nil if self is at the end" do
- @io.pos = 36
- @io.gets.should be_nil
- @io.gets.should be_nil
- end
-end
-
-describe "StringIO#gets when passed [limit]" do
- before :each do
- @io = StringIO.new("this>is>an>example")
- end
-
- it "returns the data read until the limit is met" do
- @io.gets(4).should == "this"
- @io.gets(3).should == ">is"
- @io.gets(5).should == ">an>e"
- @io.gets(6).should == "xample"
- end
-
- it "sets $_ to the read content" do
- @io.gets(4)
- $_.should == "this"
- @io.gets(3)
- $_.should == ">is"
- @io.gets(5)
- $_.should == ">an>e"
- @io.gets(6)
- $_.should == "xample"
- @io.gets(3)
- $_.should be_nil
- end
-
- it "updates self's lineno by one" do
- @io.gets(3)
- @io.lineno.should eql(1)
-
- @io.gets(3)
- @io.lineno.should eql(2)
-
- @io.gets(3)
- @io.lineno.should eql(3)
- end
-
- it "tries to convert the passed limit to an Integer using #to_int" do
- obj = mock('to_int')
- obj.should_receive(:to_int).and_return(4)
- @io.gets(obj).should == "this"
- end
-
- it "returns a blank string when passed a limit of 0" do
- @io.gets(0).should == ""
- end
-
- it "ignores it when passed a negative limit" do
- @io.gets(-4).should == "this>is>an>example"
- end
-end
+ describe "when passed [limit]" do
+ it_behaves_like :stringio_gets_limit, :gets
-describe "StringIO#gets when passed [separator] and [limit]" do
- before :each do
- @io = StringIO.new("this>is>an>example")
- end
-
- it "returns the data read until the limit is consumed or the separator is met" do
- @io.gets('>', 8).should == "this>"
- @io.gets('>', 2).should == "is"
- @io.gets('>', 10).should == ">"
- @io.gets('>', 6).should == "an>"
- @io.gets('>', 5).should == "examp"
- end
+ it "returns nil if self is at the end" do
+ @io = StringIO.new("this>is>an>example")
- it "sets $_ to the read content" do
- @io.gets('>', 8)
- $_.should == "this>"
- @io.gets('>', 2)
- $_.should == "is"
- @io.gets('>', 10)
- $_.should == ">"
- @io.gets('>', 6)
- $_.should == "an>"
- @io.gets('>', 5)
- $_.should == "examp"
+ @io.pos = 36
+ @io.gets(3).should be_nil
+ @io.gets(3).should be_nil
+ end
end
- it "updates self's lineno by one" do
- @io.gets('>', 3)
- @io.lineno.should eql(1)
+ describe "when passed [separator] and [limit]" do
+ it_behaves_like :stringio_gets_separator_and_limit, :gets
- @io.gets('>', 3)
- @io.lineno.should eql(2)
+ it "returns nil if self is at the end" do
+ @io = StringIO.new("this>is>an>example")
- @io.gets('>', 3)
- @io.lineno.should eql(3)
+ @io.pos = 36
+ @io.gets(">", 3).should be_nil
+ @io.gets(">", 3).should be_nil
+ end
end
- it "tries to convert the passed separator to a String using #to_str" do
- obj = mock('to_str')
- obj.should_receive(:to_str).and_return('>')
- @io.gets(obj, 5).should == "this>"
- end
+ describe "when passed no argument" do
+ it_behaves_like :stringio_gets_no_argument, :gets
- it "does not raise TypeError if passed separator is nil" do
- @io.gets(nil, 5).should == "this>"
- end
+ it "returns nil if self is at the end" do
+ @io = StringIO.new("this>is>an>example")
- it "tries to convert the passed limit to an Integer using #to_int" do
- obj = mock('to_int')
- obj.should_receive(:to_int).and_return(5)
- @io.gets('>', obj).should == "this>"
+ @io.pos = 36
+ @io.gets.should be_nil
+ @io.gets.should be_nil
+ end
end
-end
-
-describe "StringIO#gets when in write-only mode" do
- it "raises an IOError" do
- io = StringIO.new(+"xyz", "w")
- -> { io.gets }.should raise_error(IOError)
- io = StringIO.new("xyz")
- io.close_read
- -> { io.gets }.should raise_error(IOError)
+ describe "when passed [chomp]" do
+ it_behaves_like :stringio_gets_chomp, :gets
end
-end
-describe "StringIO#gets when passed [chomp]" do
- it "returns the data read without a trailing newline character" do
- io = StringIO.new("this>is>an>example\n")
- io.gets(chomp: true).should == "this>is>an>example"
+ describe "when in write-only mode" do
+ it_behaves_like :stringio_gets_write_only, :gets
end
end
diff --git a/spec/ruby/library/stringio/initialize_spec.rb b/spec/ruby/library/stringio/initialize_spec.rb
index ad067a0be1..6f4d2e456c 100644
--- a/spec/ruby/library/stringio/initialize_spec.rb
+++ b/spec/ruby/library/stringio/initialize_spec.rb
@@ -130,6 +130,26 @@ describe "StringIO#initialize when passed [Object, mode]" do
-> { @io.send(:initialize, str, "w") }.should raise_error(Errno::EACCES)
-> { @io.send(:initialize, str, "a") }.should raise_error(Errno::EACCES)
end
+
+ it "truncates all the content if passed w mode" do
+ io = StringIO.allocate
+ source = +"example".encode(Encoding::ISO_8859_1);
+
+ io.send(:initialize, source, "w")
+
+ io.string.should.empty?
+ io.string.encoding.should == Encoding::ISO_8859_1
+ end
+
+ it "truncates all the content if passed IO::TRUNC mode" do
+ io = StringIO.allocate
+ source = +"example".encode(Encoding::ISO_8859_1);
+
+ io.send(:initialize, source, IO::TRUNC)
+
+ io.string.should.empty?
+ io.string.encoding.should == Encoding::ISO_8859_1
+ end
end
describe "StringIO#initialize when passed [Object]" do
@@ -172,7 +192,7 @@ end
# NOTE: Synchronise with core/io/new_spec.rb (core/io/shared/new.rb)
describe "StringIO#initialize when passed keyword arguments" do
it "sets the mode based on the passed :mode option" do
- io = StringIO.new("example", "r")
+ io = StringIO.new("example", mode: "r")
io.closed_read?.should be_false
io.closed_write?.should be_true
end
diff --git a/spec/ruby/library/stringio/readline_spec.rb b/spec/ruby/library/stringio/readline_spec.rb
index b16a16e23f..085360707f 100644
--- a/spec/ruby/library/stringio/readline_spec.rb
+++ b/spec/ruby/library/stringio/readline_spec.rb
@@ -1,150 +1,58 @@
require_relative '../../spec_helper'
+require "stringio"
require_relative 'fixtures/classes'
+require_relative "shared/gets"
+describe "StringIO#readline" do
+ describe "when passed [separator]" do
+ it_behaves_like :stringio_gets_separator, :readline
-describe "StringIO#readline when passed [separator]" do
- before :each do
- @io = StringIO.new("this>is>an>example")
- end
-
- it "returns the data read till the next occurrence of the passed separator" do
- @io.readline(">").should == "this>"
- @io.readline(">").should == "is>"
- @io.readline(">").should == "an>"
- @io.readline(">").should == "example"
- end
-
- it "sets $_ to the read content" do
- @io.readline(">")
- $_.should == "this>"
- @io.readline(">")
- $_.should == "is>"
- @io.readline(">")
- $_.should == "an>"
- @io.readline(">")
- $_.should == "example"
- end
-
- it "updates self's lineno by one" do
- @io.readline(">")
- @io.lineno.should eql(1)
-
- @io.readline(">")
- @io.lineno.should eql(2)
-
- @io.readline(">")
- @io.lineno.should eql(3)
- end
-
- it "returns the next paragraph when the passed separator is an empty String" do
- io = StringIO.new("this is\n\nan example")
- io.readline("").should == "this is\n\n"
- io.readline("").should == "an example"
- end
-
- it "returns the remaining content starting at the current position when passed nil" do
- io = StringIO.new("this is\n\nan example")
- io.pos = 5
- io.readline(nil).should == "is\n\nan example"
- end
-
- it "tries to convert the passed separator to a String using #to_str" do
- obj = mock('to_str')
- obj.should_receive(:to_str).and_return(">")
- @io.readline(obj).should == "this>"
- end
-end
-
-describe "StringIO#readline when passed no argument" do
- before :each do
- @io = StringIO.new("this is\nan example\nfor StringIO#readline")
- end
-
- it "returns the data read till the next occurrence of $/ or till eof" do
- @io.readline.should == "this is\n"
+ it "raises an IOError if self is at the end" do
+ @io = StringIO.new("this>is>an>example")
- begin
- old_sep = $/
- suppress_warning {$/ = " "}
- @io.readline.should == "an "
- @io.readline.should == "example\nfor "
- @io.readline.should == "StringIO#readline"
- ensure
- suppress_warning {$/ = old_sep}
+ @io.pos = 36
+ -> { @io.readline(">") }.should raise_error(IOError)
end
end
- it "sets $_ to the read content" do
- @io.readline
- $_.should == "this is\n"
- @io.readline
- $_.should == "an example\n"
- @io.readline
- $_.should == "for StringIO#readline"
- end
+ describe "when passed [limit]" do
+ it_behaves_like :stringio_gets_limit, :readline
- it "updates self's position" do
- @io.readline
- @io.pos.should eql(8)
+ it "raises an IOError if self is at the end" do
+ @io = StringIO.new("this>is>an>example")
- @io.readline
- @io.pos.should eql(19)
-
- @io.readline
- @io.pos.should eql(40)
+ @io.pos = 36
+ -> { @io.readline(3) }.should raise_error(IOError)
+ end
end
- it "updates self's lineno" do
- @io.readline
- @io.lineno.should eql(1)
+ describe "when passed [separator] and [limit]" do
+ it_behaves_like :stringio_gets_separator_and_limit, :readline
- @io.readline
- @io.lineno.should eql(2)
+ it "raises an IOError if self is at the end" do
+ @io = StringIO.new("this>is>an>example")
- @io.readline
- @io.lineno.should eql(3)
- end
-
- it "raises an IOError if self is at the end" do
- @io.pos = 40
- -> { @io.readline }.should raise_error(IOError)
- end
-end
-
-describe "StringIO#readline when in write-only mode" do
- it "raises an IOError" do
- io = StringIO.new(+"xyz", "w")
- -> { io.readline }.should raise_error(IOError)
-
- io = StringIO.new("xyz")
- io.close_read
- -> { io.readline }.should raise_error(IOError)
+ @io.pos = 36
+ -> { @io.readline(">", 3) }.should raise_error(IOError)
+ end
end
-end
-describe "StringIO#readline when passed [chomp]" do
- it "returns the data read without a trailing newline character" do
- io = StringIO.new("this>is>an>example\n")
- io.readline(chomp: true).should == "this>is>an>example"
- end
-end
+ describe "when passed no argument" do
+ it_behaves_like :stringio_gets_no_argument, :readline
-describe "StringIO#readline when passed [limit]" do
- before :each do
- @io = StringIO.new("this>is>an>example")
- end
+ it "raises an IOError if self is at the end" do
+ @io = StringIO.new("this>is>an>example")
- it "returns the data read until the limit is met" do
- io = StringIO.new("this>is>an>example\n")
- io.readline(3).should == "thi"
+ @io.pos = 36
+ -> { @io.readline }.should raise_error(IOError)
+ end
end
- it "returns a blank string when passed a limit of 0" do
- @io.readline(0).should == ""
+ describe "when passed [chomp]" do
+ it_behaves_like :stringio_gets_chomp, :readline
end
- it "ignores it when the limit is negative" do
- seen = []
- @io.readline(-4).should == "this>is>an>example"
+ describe "when in write-only mode" do
+ it_behaves_like :stringio_gets_write_only, :readline
end
end
diff --git a/spec/ruby/library/stringio/readpartial_spec.rb b/spec/ruby/library/stringio/readpartial_spec.rb
index f25cef4014..dadefb7837 100644
--- a/spec/ruby/library/stringio/readpartial_spec.rb
+++ b/spec/ruby/library/stringio/readpartial_spec.rb
@@ -10,13 +10,7 @@ describe "StringIO#readpartial" do
@string.close unless @string.closed?
end
- it "raises IOError on closed stream" do
- @string.close
- -> { @string.readpartial(10) }.should raise_error(IOError)
- end
-
it "reads at most the specified number of bytes" do
-
# buffered read
@string.read(1).should == 'S'
# return only specified number, not the whole buffer
@@ -30,6 +24,14 @@ describe "StringIO#readpartial" do
@string.readpartial(3).should == ", l"
end
+ it "reads after ungetc with multibyte characters in the buffer" do
+ @string = StringIO.new(+"∂φ/∂x = gaîté")
+ c = @string.getc
+ @string.ungetc(c)
+ @string.readpartial(3).should == "\xE2\x88\x82".b
+ @string.readpartial(3).should == "\xCF\x86/".b
+ end
+
it "reads after ungetc without data in the buffer" do
@string = StringIO.new
@string.write("f").should == 1
@@ -67,14 +69,34 @@ describe "StringIO#readpartial" do
it "raises IOError if the stream is closed" do
@string.close
- -> { @string.readpartial(1) }.should raise_error(IOError)
+ -> { @string.readpartial(1) }.should raise_error(IOError, "not opened for reading")
end
it "raises ArgumentError if the negative argument is provided" do
- -> { @string.readpartial(-1) }.should raise_error(ArgumentError)
+ -> { @string.readpartial(-1) }.should raise_error(ArgumentError, "negative length -1 given")
end
it "immediately returns an empty string if the length argument is 0" do
@string.readpartial(0).should == ""
end
+
+ it "raises IOError if the stream is closed and the length argument is 0" do
+ @string.close
+ -> { @string.readpartial(0) }.should raise_error(IOError, "not opened for reading")
+ end
+
+ it "clears and returns the given buffer if the length argument is 0" do
+ buffer = +"existing content"
+ @string.readpartial(0, buffer).should == buffer
+ buffer.should == ""
+ end
+
+ version_is StringIO::VERSION, "3.1.2" do # ruby_version_is "3.4"
+ it "preserves the encoding of the given buffer" do
+ buffer = ''.encode(Encoding::ISO_8859_1)
+ @string.readpartial(10, buffer)
+
+ buffer.encoding.should == Encoding::ISO_8859_1
+ end
+ end
end
diff --git a/spec/ruby/library/stringio/set_encoding_by_bom_spec.rb b/spec/ruby/library/stringio/set_encoding_by_bom_spec.rb
new file mode 100644
index 0000000000..1030aad042
--- /dev/null
+++ b/spec/ruby/library/stringio/set_encoding_by_bom_spec.rb
@@ -0,0 +1,237 @@
+require 'stringio'
+require_relative '../../spec_helper'
+
+# Should be synced with specs for IO#set_encoding_by_bom
+describe "StringIO#set_encoding_by_bom" do
+ it "returns nil if not readable" do
+ io = StringIO.new("".b, "wb")
+
+ io.set_encoding_by_bom.should be_nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ end
+
+ it "returns the result encoding if found BOM UTF-8 sequence" do
+ io = StringIO.new("\u{FEFF}".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_8
+ io.external_encoding.should == Encoding::UTF_8
+ io.read.b.should == "".b
+
+ io = StringIO.new("\u{FEFF}abc".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_8
+ io.external_encoding.should == Encoding::UTF_8
+ io.read.b.should == "abc".b
+ end
+
+ it "returns the result encoding if found BOM UTF_16LE sequence" do
+ io = StringIO.new("\xFF\xFE".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_16LE
+ io.external_encoding.should == Encoding::UTF_16LE
+ io.read.b.should == "".b
+
+ io = StringIO.new("\xFF\xFEabc".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_16LE
+ io.external_encoding.should == Encoding::UTF_16LE
+ io.read.b.should == "abc".b
+ end
+
+ it "returns the result encoding if found BOM UTF_16BE sequence" do
+ io = StringIO.new("\xFE\xFF".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_16BE
+ io.external_encoding.should == Encoding::UTF_16BE
+ io.read.b.should == "".b
+
+ io = StringIO.new("\xFE\xFFabc".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_16BE
+ io.external_encoding.should == Encoding::UTF_16BE
+ io.read.b.should == "abc".b
+ end
+
+ it "returns the result encoding if found BOM UTF_32LE sequence" do
+ io = StringIO.new("\xFF\xFE\x00\x00".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_32LE
+ io.external_encoding.should == Encoding::UTF_32LE
+ io.read.b.should == "".b
+
+ io = StringIO.new("\xFF\xFE\x00\x00abc".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_32LE
+ io.external_encoding.should == Encoding::UTF_32LE
+ io.read.b.should == "abc".b
+ end
+
+ it "returns the result encoding if found BOM UTF_32BE sequence" do
+ io = StringIO.new("\x00\x00\xFE\xFF".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_32BE
+ io.external_encoding.should == Encoding::UTF_32BE
+ io.read.b.should == "".b
+
+ io = StringIO.new("\x00\x00\xFE\xFFabc".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_32BE
+ io.external_encoding.should == Encoding::UTF_32BE
+ io.read.b.should == "abc".b
+ end
+
+ it "returns nil if io is empty" do
+ io = StringIO.new("".b, "rb")
+ io.set_encoding_by_bom.should be_nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ end
+
+ it "returns nil if UTF-8 BOM sequence is incomplete" do
+ io = StringIO.new("\xEF".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\xEF".b
+
+ io = StringIO.new("\xEFa".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\xEFa".b
+
+ io = StringIO.new("\xEF\xBB".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\xEF\xBB".b
+
+ io = StringIO.new("\xEF\xBBa".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\xEF\xBBa".b
+ end
+
+ it "returns nil if UTF-16BE BOM sequence is incomplete" do
+ io = StringIO.new("\xFE".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\xFE".b
+
+ io = StringIO.new("\xFEa".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\xFEa".b
+ end
+
+ it "returns nil if UTF-16LE/UTF-32LE BOM sequence is incomplete" do
+ io = StringIO.new("\xFF".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\xFF".b
+
+ io = StringIO.new("\xFFa".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\xFFa".b
+ end
+
+ it "returns UTF-16LE if UTF-32LE BOM sequence is incomplete" do
+ io = StringIO.new("\xFF\xFE".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_16LE
+ io.external_encoding.should == Encoding::UTF_16LE
+ io.read.b.should == "".b
+
+ io = StringIO.new("\xFF\xFE\x00".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_16LE
+ io.external_encoding.should == Encoding::UTF_16LE
+ io.read.b.should == "\x00".b
+
+ io = StringIO.new("\xFF\xFE\x00a".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_16LE
+ io.external_encoding.should == Encoding::UTF_16LE
+ io.read.b.should == "\x00a".b
+ end
+
+ it "returns nil if UTF-32BE BOM sequence is incomplete" do
+ io = StringIO.new("\x00".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\x00".b
+
+ io = StringIO.new("\x00a".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\x00a".b
+
+ io = StringIO.new("\x00\x00".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\x00\x00".b
+
+ io = StringIO.new("\x00\x00a".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\x00\x00a".b
+
+ io = StringIO.new("\x00\x00\xFE".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\x00\x00\xFE".b
+
+ io = StringIO.new("\x00\x00\xFEa".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\x00\x00\xFEa".b
+ end
+
+ it "returns nil if found BOM sequence not provided" do
+ io = StringIO.new("abc".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read(3).should == "abc".b
+ end
+
+ it "does not raise exception if io not in binary mode" do
+ io = StringIO.new("", 'r')
+ io.set_encoding_by_bom.should == nil
+ end
+
+ it "does not raise exception if encoding already set" do
+ io = StringIO.new("".b, "rb")
+ io.set_encoding("utf-8")
+ io.set_encoding_by_bom.should == nil
+ end
+
+ it "does not raise exception if encoding conversion is already set" do
+ io = StringIO.new("".b, "rb")
+ io.set_encoding(Encoding::UTF_8, Encoding::UTF_16BE)
+
+ io.set_encoding_by_bom.should == nil
+ end
+
+ it "raises FrozenError when io is frozen" do
+ io = StringIO.new()
+ io.freeze
+ -> { io.set_encoding_by_bom }.should raise_error(FrozenError)
+ end
+
+ it "does not raise FrozenError when initial string is frozen" do
+ io = StringIO.new("".freeze)
+ io.set_encoding_by_bom.should == nil
+ end
+end
diff --git a/spec/ruby/library/stringio/shared/each.rb b/spec/ruby/library/stringio/shared/each.rb
index e0dd3f9b8f..626b41a4d3 100644
--- a/spec/ruby/library/stringio/shared/each.rb
+++ b/spec/ruby/library/stringio/shared/each.rb
@@ -36,22 +36,11 @@ describe :stringio_each_separator, shared: true do
seen.should == ["2 1 2 1 2"]
end
- version_is StringIO::VERSION, ""..."3.0.4" do #ruby_version_is ""..."3.2" do
- it "yields each paragraph with two separation characters when passed an empty String as separator" do
- seen = []
- io = StringIO.new("para1\n\npara2\n\n\npara3")
- io.send(@method, "") {|s| seen << s}
- seen.should == ["para1\n\n", "para2\n\n", "para3"]
- end
- end
-
- version_is StringIO::VERSION, "3.0.4" do #ruby_version_is "3.2" do
- it "yields each paragraph with all separation characters when passed an empty String as separator" do
- seen = []
- io = StringIO.new("para1\n\npara2\n\n\npara3")
- io.send(@method, "") {|s| seen << s}
- seen.should == ["para1\n\n", "para2\n\n\n", "para3"]
- end
+ it "yields each paragraph with all separation characters when passed an empty String as separator" do
+ seen = []
+ io = StringIO.new("para1\n\npara2\n\n\npara3")
+ io.send(@method, "") {|s| seen << s}
+ seen.should == ["para1\n\n", "para2\n\n\n", "para3"]
end
end
@@ -161,3 +150,60 @@ describe :stringio_each_limit, shared: true do
seen.should == ["a b ", "c d ", "e\n", "1 2 ", "3 4 ", "5"]
end
end
+
+describe :stringio_each_separator_and_limit, shared: true do
+ before :each do
+ @io = StringIO.new("this>is>an>example")
+ end
+
+ it "returns the data read until the limit is consumed or the separator is met" do
+ @io.send(@method, '>', 8) { |s| break s }.should == "this>"
+ @io.send(@method, '>', 2) { |s| break s }.should == "is"
+ @io.send(@method, '>', 10) { |s| break s }.should == ">"
+ @io.send(@method, '>', 6) { |s| break s }.should == "an>"
+ @io.send(@method, '>', 5) { |s| break s }.should == "examp"
+ end
+
+ it "truncates the multi-character separator at the end to meet the limit" do
+ @io.send(@method, "is>an", 7) { |s| break s }.should == "this>is"
+ end
+
+ it "does not change $_" do
+ $_ = "test"
+ @io.send(@method, '>', 8) { |s| s }
+ $_.should == "test"
+ end
+
+ it "updates self's lineno by one" do
+ @io.send(@method, '>', 3) { |s| break s }
+ @io.lineno.should eql(1)
+
+ @io.send(@method, '>', 3) { |s| break s }
+ @io.lineno.should eql(2)
+
+ @io.send(@method, '>', 3) { |s| break s }
+ @io.lineno.should eql(3)
+ end
+
+ it "tries to convert the passed separator to a String using #to_str" do # TODO
+ obj = mock('to_str')
+ obj.should_receive(:to_str).and_return('>')
+
+ seen = []
+ @io.send(@method, obj, 5) { |s| seen << s }
+ seen.should == ["this>", "is>", "an>", "examp", "le"]
+ end
+
+ it "does not raise TypeError if passed separator is nil" do
+ @io.send(@method, nil, 5) { |s| break s }.should == "this>"
+ end
+
+ it "tries to convert the passed limit to an Integer using #to_int" do # TODO
+ obj = mock('to_int')
+ obj.should_receive(:to_int).and_return(5)
+
+ seen = []
+ @io.send(@method, '>', obj) { |s| seen << s }
+ seen.should == ["this>", "is>", "an>", "examp", "le"]
+ end
+end
diff --git a/spec/ruby/library/stringio/shared/gets.rb b/spec/ruby/library/stringio/shared/gets.rb
new file mode 100644
index 0000000000..8396b161f1
--- /dev/null
+++ b/spec/ruby/library/stringio/shared/gets.rb
@@ -0,0 +1,249 @@
+describe :stringio_gets_separator, shared: true do
+ describe "when passed [separator]" do
+ before :each do
+ @io = StringIO.new("this>is>an>example")
+ end
+
+ it "returns the data read till the next occurrence of the passed separator" do
+ @io.send(@method, ">").should == "this>"
+ @io.send(@method, ">").should == "is>"
+ @io.send(@method, ">").should == "an>"
+ @io.send(@method, ">").should == "example"
+ end
+
+ it "sets $_ to the read content" do
+ @io.send(@method, ">")
+ $_.should == "this>"
+ @io.send(@method, ">")
+ $_.should == "is>"
+ @io.send(@method, ">")
+ $_.should == "an>"
+ @io.send(@method, ">")
+ $_.should == "example"
+ end
+
+ it "accepts string as separator" do
+ @io.send(@method, "is>")
+ $_.should == "this>"
+ @io.send(@method, "an>")
+ $_.should == "is>an>"
+ @io.send(@method, "example")
+ $_.should == "example"
+ end
+
+ it "updates self's lineno by one" do
+ @io.send(@method, ">")
+ @io.lineno.should eql(1)
+
+ @io.send(@method, ">")
+ @io.lineno.should eql(2)
+
+ @io.send(@method, ">")
+ @io.lineno.should eql(3)
+ end
+
+ it "returns the next paragraph when the passed separator is an empty String" do
+ io = StringIO.new("this is\n\nan example")
+ io.send(@method, "").should == "this is\n\n"
+ io.send(@method, "").should == "an example"
+ end
+
+ it "returns the remaining content starting at the current position when passed nil" do
+ io = StringIO.new("this is\n\nan example")
+ io.pos = 5
+ io.send(@method, nil).should == "is\n\nan example"
+ end
+
+ it "tries to convert the passed separator to a String using #to_str" do
+ obj = mock('to_str')
+ obj.should_receive(:to_str).and_return(">")
+ @io.send(@method, obj).should == "this>"
+ end
+ end
+end
+
+describe :stringio_gets_limit, shared: true do
+ describe "when passed [limit]" do
+ before :each do
+ @io = StringIO.new("this>is>an>example")
+ end
+
+ it "returns the data read until the limit is met" do
+ @io.send(@method, 4).should == "this"
+ @io.send(@method, 3).should == ">is"
+ @io.send(@method, 5).should == ">an>e"
+ @io.send(@method, 6).should == "xample"
+ end
+
+ it "sets $_ to the read content" do
+ @io.send(@method, 4)
+ $_.should == "this"
+ @io.send(@method, 3)
+ $_.should == ">is"
+ @io.send(@method, 5)
+ $_.should == ">an>e"
+ @io.send(@method, 6)
+ $_.should == "xample"
+ end
+
+ it "updates self's lineno by one" do
+ @io.send(@method, 3)
+ @io.lineno.should eql(1)
+
+ @io.send(@method, 3)
+ @io.lineno.should eql(2)
+
+ @io.send(@method, 3)
+ @io.lineno.should eql(3)
+ end
+
+ it "tries to convert the passed limit to an Integer using #to_int" do
+ obj = mock('to_int')
+ obj.should_receive(:to_int).and_return(4)
+ @io.send(@method, obj).should == "this"
+ end
+
+ it "returns a blank string when passed a limit of 0" do
+ @io.send(@method, 0).should == ""
+ end
+
+ it "ignores it when passed a negative limit" do
+ @io.send(@method, -4).should == "this>is>an>example"
+ end
+ end
+end
+
+describe :stringio_gets_separator_and_limit, shared: true do
+ describe "when passed [separator] and [limit]" do
+ before :each do
+ @io = StringIO.new("this>is>an>example")
+ end
+
+ it "returns the data read until the limit is consumed or the separator is met" do
+ @io.send(@method, '>', 8).should == "this>"
+ @io.send(@method, '>', 2).should == "is"
+ @io.send(@method, '>', 10).should == ">"
+ @io.send(@method, '>', 6).should == "an>"
+ @io.send(@method, '>', 5).should == "examp"
+ end
+
+ it "truncates the multi-character separator at the end to meet the limit" do
+ @io.send(@method, "is>an", 7).should == "this>is"
+ end
+
+ it "sets $_ to the read content" do
+ @io.send(@method, '>', 8)
+ $_.should == "this>"
+ @io.send(@method, '>', 2)
+ $_.should == "is"
+ @io.send(@method, '>', 10)
+ $_.should == ">"
+ @io.send(@method, '>', 6)
+ $_.should == "an>"
+ @io.send(@method, '>', 5)
+ $_.should == "examp"
+ end
+
+ it "updates self's lineno by one" do
+ @io.send(@method, '>', 3)
+ @io.lineno.should eql(1)
+
+ @io.send(@method, '>', 3)
+ @io.lineno.should eql(2)
+
+ @io.send(@method, '>', 3)
+ @io.lineno.should eql(3)
+ end
+
+ it "tries to convert the passed separator to a String using #to_str" do
+ obj = mock('to_str')
+ obj.should_receive(:to_str).and_return('>')
+ @io.send(@method, obj, 5).should == "this>"
+ end
+
+ it "does not raise TypeError if passed separator is nil" do
+ @io.send(@method, nil, 5).should == "this>"
+ end
+
+ it "tries to convert the passed limit to an Integer using #to_int" do
+ obj = mock('to_int')
+ obj.should_receive(:to_int).and_return(5)
+ @io.send(@method, '>', obj).should == "this>"
+ end
+ end
+end
+
+describe :stringio_gets_no_argument, shared: true do
+ describe "when passed no argument" do
+ before :each do
+ @io = StringIO.new("this is\nan example\nfor StringIO#gets")
+ end
+
+ it "returns the data read till the next occurrence of $/ or till eof" do
+ @io.send(@method).should == "this is\n"
+
+ begin
+ old_sep = $/
+ suppress_warning {$/ = " "}
+ @io.send(@method).should == "an "
+ @io.send(@method).should == "example\nfor "
+ @io.send(@method).should == "StringIO#gets"
+ ensure
+ suppress_warning {$/ = old_sep}
+ end
+ end
+
+ it "sets $_ to the read content" do
+ @io.send(@method)
+ $_.should == "this is\n"
+ @io.send(@method)
+ $_.should == "an example\n"
+ @io.send(@method)
+ $_.should == "for StringIO#gets"
+ end
+
+ it "updates self's position" do
+ @io.send(@method)
+ @io.pos.should eql(8)
+
+ @io.send(@method)
+ @io.pos.should eql(19)
+
+ @io.send(@method)
+ @io.pos.should eql(36)
+ end
+
+ it "updates self's lineno" do
+ @io.send(@method)
+ @io.lineno.should eql(1)
+
+ @io.send(@method)
+ @io.lineno.should eql(2)
+
+ @io.send(@method)
+ @io.lineno.should eql(3)
+ end
+ end
+end
+
+describe :stringio_gets_chomp, shared: true do
+ describe "when passed [chomp]" do
+ it "returns the data read without a trailing newline character" do
+ io = StringIO.new("this>is>an>example\n")
+ io.send(@method, chomp: true).should == "this>is>an>example"
+ end
+ end
+end
+
+describe :stringio_gets_write_only, shared: true do
+ describe "when in write-only mode" do
+ it "raises an IOError" do
+ io = StringIO.new(+"xyz", "w")
+ -> { io.send(@method) }.should raise_error(IOError)
+
+ io = StringIO.new("xyz")
+ io.close_read
+ -> { io.send(@method) }.should raise_error(IOError)
+ end
+ end
+end
diff --git a/spec/ruby/library/stringio/shared/read.rb b/spec/ruby/library/stringio/shared/read.rb
index 8ef6ec2734..22f76b0fb0 100644
--- a/spec/ruby/library/stringio/shared/read.rb
+++ b/spec/ruby/library/stringio/shared/read.rb
@@ -15,7 +15,7 @@ describe :stringio_read, shared: true do
buffer.should == "example"
end
- ruby_version_is ""..."3.4" do
+ guard -> { StringIO::VERSION < "3.1.2" } do
it "does not preserve the encoding of the given buffer" do
buffer = ''.encode(Encoding::ISO_8859_1)
@io.send(@method, 7, buffer)
@@ -24,7 +24,7 @@ describe :stringio_read, shared: true do
end
end
- ruby_version_is "3.4" do
+ guard -> { StringIO::VERSION >= "3.1.2" } do
it "preserves the encoding of the given buffer" do
buffer = ''.encode(Encoding::ISO_8859_1)
@io.send(@method, 7, buffer)
diff --git a/spec/ruby/library/stringio/shared/sysread.rb b/spec/ruby/library/stringio/shared/sysread.rb
index 937bac705c..3e23fbc233 100644
--- a/spec/ruby/library/stringio/shared/sysread.rb
+++ b/spec/ruby/library/stringio/shared/sysread.rb
@@ -10,6 +10,6 @@ describe :stringio_sysread_length, shared: true do
it "raises an EOFError when passed length > 0 and no data remains" do
@io.read.should == "example"
- -> { @io.sysread(1) }.should raise_error(EOFError)
+ -> { @io.send(@method, 1) }.should raise_error(EOFError)
end
end
diff --git a/spec/ruby/library/stringio/shared/write.rb b/spec/ruby/library/stringio/shared/write.rb
index 404e08b93d..4661658baf 100644
--- a/spec/ruby/library/stringio/shared/write.rb
+++ b/spec/ruby/library/stringio/shared/write.rb
@@ -94,7 +94,7 @@ describe :stringio_write_string, shared: true do
end
it "does not transcode the given string when the external encoding is set and the string encoding is BINARY" do
- str = "été".b
+ str = "été_".b
io = StringIO.new.set_encoding(Encoding::UTF_16BE)
io.external_encoding.should == Encoding::UTF_16BE
diff --git a/spec/ruby/library/stringio/sysread_spec.rb b/spec/ruby/library/stringio/sysread_spec.rb
index 8f78073f42..fabb06dd9a 100644
--- a/spec/ruby/library/stringio/sysread_spec.rb
+++ b/spec/ruby/library/stringio/sysread_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
require "stringio"
require_relative 'shared/read'
+require_relative 'shared/sysread'
describe "StringIO#sysread when passed length, buffer" do
it_behaves_like :stringio_read, :sysread
@@ -32,6 +33,10 @@ describe "StringIO#sysread when passed nil" do
end
end
+describe "StringIO#sysread when passed length" do
+ it_behaves_like :stringio_sysread_length, :sysread
+end
+
describe "StringIO#sysread when passed [length]" do
before :each do
@io = StringIO.new("example")
diff --git a/spec/ruby/library/stringscanner/captures_spec.rb b/spec/ruby/library/stringscanner/captures_spec.rb
new file mode 100644
index 0000000000..bdfb0e0cc5
--- /dev/null
+++ b/spec/ruby/library/stringscanner/captures_spec.rb
@@ -0,0 +1,36 @@
+require_relative '../../spec_helper'
+require 'strscan'
+
+describe "StringScanner#captures" do
+ before do
+ @s = StringScanner.new('Fri Dec 12 1975 14:39')
+ end
+
+ it "returns the array of captured values of the most recent matching" do
+ @s.exist?(/(?<wday>\w+) (?<month>\w+) (?<day>\d+)/)
+ @s.captures.should == ["Fri", "Dec", "12"]
+ end
+
+ it "returns nil if the last match fails" do
+ @s.scan(/nope/)
+ @s.captures.should == nil
+ end
+
+ it "returns nil if there is no any match done" do
+ @s.captures.should == nil
+ end
+
+ version_is StringScanner::Version, ""..."3.0.8" do # ruby_version_is ""..."3.3.3"
+ it "returns '' for an optional capturing group if it doesn't match" do
+ @s.exist?(/(?<wday>\w+) (?<month>\w+) (?<day>\s+)?/)
+ @s.captures.should == ["Fri", "Dec", ""]
+ end
+ end
+
+ version_is StringScanner::Version, "3.0.8" do # ruby_version_is "3.3.3"
+ it "returns nil for an optional capturing group if it doesn't match" do
+ @s.exist?(/(?<wday>\w+) (?<month>\w+) (?<day>\s+)?/)
+ @s.captures.should == ["Fri", "Dec", nil]
+ end
+ end
+end
diff --git a/spec/ruby/library/stringscanner/charpos_spec.rb b/spec/ruby/library/stringscanner/charpos_spec.rb
new file mode 100644
index 0000000000..9aa5b00dd9
--- /dev/null
+++ b/spec/ruby/library/stringscanner/charpos_spec.rb
@@ -0,0 +1,18 @@
+require_relative '../../spec_helper'
+require 'strscan'
+
+describe "StringScanner#charpos" do
+ it "returns character index corresponding to the current position" do
+ s = StringScanner.new("abc")
+
+ s.scan_until(/b/)
+ s.charpos.should == 2
+ end
+
+ it "is multi-byte character sensitive" do
+ s = StringScanner.new("abcädeföghi")
+
+ s.scan_until(/ö/)
+ s.charpos.should == 8
+ end
+end
diff --git a/spec/ruby/library/stringscanner/check_spec.rb b/spec/ruby/library/stringscanner/check_spec.rb
index a97c26af83..5e855e154a 100644
--- a/spec/ruby/library/stringscanner/check_spec.rb
+++ b/spec/ruby/library/stringscanner/check_spec.rb
@@ -22,4 +22,72 @@ describe "StringScanner#check" do
@s.matched.should == nil
end
+ describe "#[] successive call with a capture group name" do
+ context "when #check was called with a Regexp pattern" do
+ it "returns matched substring when matching succeeded" do
+ @s.check(/(?<a>This)/)
+ @s.should.matched?
+ @s[:a].should == "This"
+ end
+
+ it "returns nil when matching failed" do
+ @s.check(/(?<a>2008)/)
+ @s.should_not.matched?
+ @s[:a].should be_nil
+ end
+ end
+
+ context "when #check was called with a String pattern" do
+ # https://github.com/ruby/strscan/issues/139
+ version_is StringScanner::Version, "3.1.1"..."3.1.3" do # ruby_version_is "3.4.0"..."3.4.3"
+ it "returns nil when matching succeeded" do
+ @s.check("This")
+ @s.should.matched?
+ @s[:a].should be_nil
+ end
+ end
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4"
+ it "raises IndexError when matching succeeded" do
+ @s.check("This")
+ @s.should.matched?
+ -> { @s[:a] }.should raise_error(IndexError)
+ end
+ end
+
+ it "returns nil when matching failed" do
+ @s.check("2008")
+ @s.should_not.matched?
+ @s[:a].should be_nil
+ end
+
+ it "returns a matching substring when given Integer index" do
+ @s.check("This")
+ @s[0].should == "This"
+ end
+
+ # https://github.com/ruby/strscan/issues/135
+ version_is StringScanner::Version, "3.1.1"..."3.1.3" do # ruby_version_is "3.4.0"..."3.4.3"
+ it "ignores the previous matching with Regexp" do
+ @s.exist?(/(?<a>This)/)
+ @s.should.matched?
+ @s[:a].should == "This"
+
+ @s.check("This")
+ @s.should.matched?
+ @s[:a].should be_nil
+ end
+ end
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4.0"..."3.4.3"
+ it "ignores the previous matching with Regexp" do
+ @s.exist?(/(?<a>This)/)
+ @s.should.matched?
+ @s[:a].should == "This"
+
+ @s.check("This")
+ @s.should.matched?
+ -> { @s[:a] }.should raise_error(IndexError)
+ end
+ end
+ end
+ end
end
diff --git a/spec/ruby/library/stringscanner/check_until_spec.rb b/spec/ruby/library/stringscanner/check_until_spec.rb
index ad222fd76b..582da66b37 100644
--- a/spec/ruby/library/stringscanner/check_until_spec.rb
+++ b/spec/ruby/library/stringscanner/check_until_spec.rb
@@ -2,20 +2,128 @@ require_relative '../../spec_helper'
require 'strscan'
describe "StringScanner#check_until" do
- before :each do
+ before do
@s = StringScanner.new("This is a test")
end
- it "returns the same value of scan_until, but don't advances the scan pointer" do
+ it "returns the same value of #scan_until, but don't advances the scan pointer" do
@s.check_until(/a/).should == "This is a"
@s.pos.should == 0
- @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)')
+ it "sets the last match result" do
+ @s.check_until(/a/)
+
+ @s.pre_match.should == "This is "
+ @s.matched.should == "a"
+ @s.post_match.should == " test"
+ end
+
+ version_is StringScanner::Version, ""..."3.1.1" do # ruby_version_is ""..."3.4"
+ it "raises TypeError if given a String" do
+ -> {
+ @s.check_until('T')
+ }.should raise_error(TypeError, 'wrong argument type String (expected Regexp)')
+ end
+ end
+
+ version_is StringScanner::Version, "3.1.1" do # ruby_version_is "3.4"
+ it "searches a substring in the rest part of a string if given a String" do
+ @s.check_until("a").should == "This is a"
+ @s.pos.should == 0
+ end
+
+ # https://github.com/ruby/strscan/issues/131
+ version_is StringScanner::Version, "3.1.1"..."3.1.3" do # ruby_version_is "3.4.1"
+ it "sets the last match result if given a String" do
+ @s.check_until("a")
+
+ @s.pre_match.should == ""
+ @s.matched.should == "This is a"
+ @s.post_match.should == " test"
+ end
+ end
+
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4"
+ it "sets the last match result if given a String" do
+ @s.check_until("a")
+
+ @s.pre_match.should == "This is "
+ @s.matched.should == "a"
+ @s.post_match.should == " test"
+ end
+ end
+ end
+
+ describe "#[] successive call with a capture group name" do
+ context "when #check_until was called with a Regexp pattern" do
+ it "returns matched substring when matching succeeded" do
+ @s.check_until(/(?<a>This)/)
+ @s.should.matched?
+ @s[:a].should == "This"
+ end
+
+ it "returns nil when matching failed" do
+ @s.check_until(/(?<a>2008)/)
+ @s.should_not.matched?
+ @s[:a].should be_nil
+ end
+ end
+
+ version_is StringScanner::Version, "3.1.1" do # ruby_version_is "3.4"
+ context "when #check_until was called with a String pattern" do
+ # https://github.com/ruby/strscan/issues/139
+ version_is StringScanner::Version, "3.1.1"..."3.1.3" do # ruby_version_is "3.4.0"..."3.4.3"
+ it "returns nil when matching succeeded" do
+ @s.check_until("This")
+ @s.should.matched?
+ @s[:a].should be_nil
+ end
+ end
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4.3"
+ it "raises IndexError when matching succeeded" do
+ @s.check_until("This")
+ @s.should.matched?
+ -> { @s[:a] }.should raise_error(IndexError)
+ end
+ end
+
+ it "returns nil when matching failed" do
+ @s.check_until("2008")
+ @s.should_not.matched?
+ @s[:a].should be_nil
+ end
+
+ it "returns a matching substring when given Integer index" do
+ @s.check_until("This")
+ @s[0].should == "This"
+ end
+
+ # https://github.com/ruby/strscan/issues/135
+ version_is StringScanner::Version, "3.1.1"..."3.1.3" do # ruby_version_is "3.4.0"..."3.4.3"
+ it "ignores the previous matching with Regexp" do
+ @s.exist?(/(?<a>This)/)
+ @s.should.matched?
+ @s[:a].should == "This"
+
+ @s.check_until("This")
+ @s.should.matched?
+ @s[:a].should be_nil
+ end
+ end
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4.0"..."3.4.3"
+ it "ignores the previous matching with Regexp" do
+ @s.exist?(/(?<a>This)/)
+ @s.should.matched?
+ @s[:a].should == "This"
+
+ @s.check_until("This")
+ @s.should.matched?
+ -> { @s[:a] }.should raise_error(IndexError)
+ end
+ end
+ end
+ end
end
end
diff --git a/spec/ruby/library/stringscanner/clear_spec.rb b/spec/ruby/library/stringscanner/clear_spec.rb
deleted file mode 100644
index 7ae089704a..0000000000
--- a/spec/ruby/library/stringscanner/clear_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'shared/terminate'
-require 'strscan'
-
-describe "StringScanner#clear" do
- it_behaves_like :strscan_terminate, :clear
-
- it "warns in verbose mode that the method is obsolete" do
- s = StringScanner.new("abc")
- -> {
- s.clear
- }.should complain(/clear.*obsolete.*terminate/, verbose: true)
-
- -> {
- s.clear
- }.should_not complain(verbose: false)
- end
-end
diff --git a/spec/ruby/library/stringscanner/element_reference_spec.rb b/spec/ruby/library/stringscanner/element_reference_spec.rb
index 60fe15d807..91b6d86dc7 100644
--- a/spec/ruby/library/stringscanner/element_reference_spec.rb
+++ b/spec/ruby/library/stringscanner/element_reference_spec.rb
@@ -8,6 +8,7 @@ describe "StringScanner#[]" do
it "returns nil if there is no current match" do
@s[0].should be_nil
+ @s[:wday].should be_nil
end
it "returns the n-th subgroup in the most recent match" do
@@ -42,12 +43,18 @@ describe "StringScanner#[]" do
-> { @s[0..2]}.should raise_error(TypeError)
end
- it "raises a IndexError when there's no named capture" do
+ it "raises a IndexError when there's no any named capture group in the regexp" do
@s.scan(/(\w+) (\w+) (\d+) /)
-> { @s["wday"]}.should raise_error(IndexError)
-> { @s[:wday]}.should raise_error(IndexError)
end
+ it "raises a IndexError when given a not existing capture group name" do
+ @s.scan(/(?<a>\w+) (?<b>\w+) (?<c>\d+) /)
+ -> { @s["wday"]}.should raise_error(IndexError)
+ -> { @s[:wday]}.should raise_error(IndexError)
+ end
+
it "returns named capture" do
@s.scan(/(?<wday>\w+) (?<month>\w+) (?<day>\d+) /)
@s["wday"].should == "Fri"
diff --git a/spec/ruby/library/stringscanner/empty_spec.rb b/spec/ruby/library/stringscanner/empty_spec.rb
deleted file mode 100644
index d9449bea6e..0000000000
--- a/spec/ruby/library/stringscanner/empty_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'shared/eos'
-require 'strscan'
-
-describe "StringScanner#empty?" do
- it_behaves_like :strscan_eos, :empty?
-
- it "warns in verbose mode that the method is obsolete" do
- s = StringScanner.new("abc")
- -> {
- s.empty?
- }.should complain(/empty?.*obsolete.*eos?/, verbose: true)
-
- -> {
- s.empty?
- }.should_not complain(verbose: false)
- end
-end
diff --git a/spec/ruby/library/stringscanner/eos_spec.rb b/spec/ruby/library/stringscanner/eos_spec.rb
index b58ee1e473..03c2804e5b 100644
--- a/spec/ruby/library/stringscanner/eos_spec.rb
+++ b/spec/ruby/library/stringscanner/eos_spec.rb
@@ -1,7 +1,20 @@
require_relative '../../spec_helper'
-require_relative 'shared/eos'
require 'strscan'
describe "StringScanner#eos?" do
- it_behaves_like :strscan_eos, :eos?
+ before :each do
+ @s = StringScanner.new("This is a test")
+ end
+
+ it "returns true if the scan pointer is at the end of the string" do
+ @s.terminate
+ @s.should.eos?
+
+ s = StringScanner.new('')
+ s.should.eos?
+ end
+
+ it "returns false if the scan pointer is not at the end of the string" do
+ @s.should_not.eos?
+ end
end
diff --git a/spec/ruby/library/stringscanner/exist_spec.rb b/spec/ruby/library/stringscanner/exist_spec.rb
index ff860a0d3e..a408fd0b8d 100644
--- a/spec/ruby/library/stringscanner/exist_spec.rb
+++ b/spec/ruby/library/stringscanner/exist_spec.rb
@@ -2,11 +2,11 @@ require_relative '../../spec_helper'
require 'strscan'
describe "StringScanner#exist?" do
- before :each do
+ before do
@s = StringScanner.new("This is a test")
end
- it "returns the index of the first occurrence of the given pattern" do
+ it "returns distance in bytes between the current position and the end of the matched substring" do
@s.exist?(/s/).should == 4
@s.scan(/This is/)
@s.exist?(/s/).should == 6
@@ -22,9 +22,98 @@ describe "StringScanner#exist?" do
@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)')
+ it "does not modify the current position" do
+ @s.pos.should == 0
+ @s.exist?(/s/).should == 4
+ @s.pos.should == 0
+ end
+
+ version_is StringScanner::Version, ""..."3.1.1" do # ruby_version_is ""..."3.4"
+ it "raises TypeError if given a String" do
+ -> {
+ @s.exist?('T')
+ }.should raise_error(TypeError, 'wrong argument type String (expected Regexp)')
+ end
+ end
+
+ version_is StringScanner::Version, "3.1.1" do # ruby_version_is "3.4"
+ it "searches a substring in the rest part of a string if given a String" do
+ @s.exist?('a').should == 9
+ end
+
+ it "returns nil if the pattern isn't found in the string" do
+ @s.exist?("S").should == nil
+ end
+ end
+
+ describe "#[] successive call with a capture group name" do
+ context "when #exist? was called with a Regexp pattern" do
+ it "returns matched substring when matching succeeded" do
+ @s.exist?(/(?<a>This)/)
+ @s.should.matched?
+ @s[:a].should == "This"
+ end
+
+ it "returns nil when matching failed" do
+ @s.exist?(/(?<a>2008)/)
+ @s.should_not.matched?
+ @s[:a].should be_nil
+ end
+ end
+
+ version_is StringScanner::Version, "3.1.1" do # ruby_version_is "3.4"
+ context "when #exist? was called with a String pattern" do
+ # https://github.com/ruby/strscan/issues/139
+ version_is StringScanner::Version, "3.1.1"..."3.1.3" do # ruby_version_is "3.4.0"..."3.4.3"
+ it "returns nil when matching succeeded" do
+ @s.exist?("This")
+ @s.should.matched?
+ @s[:a].should be_nil
+ end
+ end
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4.3"
+ it "raises IndexError when matching succeeded" do
+ @s.exist?("This")
+ @s.should.matched?
+ -> { @s[:a] }.should raise_error(IndexError)
+ end
+ end
+
+ it "returns nil when matching failed" do
+ @s.exist?("2008")
+ @s.should_not.matched?
+ @s[:a].should be_nil
+ end
+
+ it "returns a matching substring when given Integer index" do
+ @s.exist?("This")
+ @s[0].should == "This"
+ end
+
+ # https://github.com/ruby/strscan/issues/135
+ version_is StringScanner::Version, "3.1.1"..."3.1.3" do # ruby_version_is "3.4.0"..."3.4.3"
+ it "ignores the previous matching with Regexp" do
+ @s.exist?(/(?<a>This)/)
+ @s.should.matched?
+ @s[:a].should == "This"
+
+ @s.exist?("This")
+ @s.should.matched?
+ @s[:a].should be_nil
+ end
+ end
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4.0"..."3.4.3"
+ it "ignores the previous matching with Regexp" do
+ @s.exist?(/(?<a>This)/)
+ @s.should.matched?
+ @s[:a].should == "This"
+
+ @s.exist?("This")
+ @s.should.matched?
+ -> { @s[:a] }.should raise_error(IndexError)
+ end
+ end
+ end
+ end
end
end
diff --git a/spec/ruby/library/stringscanner/fixed_anchor_spec.rb b/spec/ruby/library/stringscanner/fixed_anchor_spec.rb
new file mode 100644
index 0000000000..ce0b714fa8
--- /dev/null
+++ b/spec/ruby/library/stringscanner/fixed_anchor_spec.rb
@@ -0,0 +1,17 @@
+require_relative '../../spec_helper'
+require 'strscan'
+
+describe "StringScanner#fixed_anchor?" do
+ it "returns whether the fixed-anchor property is set" do
+ s = StringScanner.new("foo", fixed_anchor: true)
+ s.should.fixed_anchor?
+
+ s = StringScanner.new("foo", fixed_anchor: false)
+ s.should_not.fixed_anchor?
+ end
+
+ it "is set to false by default" do
+ s = StringScanner.new("foo")
+ s.should_not.fixed_anchor?
+ end
+end
diff --git a/spec/ruby/library/stringscanner/get_byte_spec.rb b/spec/ruby/library/stringscanner/get_byte_spec.rb
index 29e2f557de..144859abc9 100644
--- a/spec/ruby/library/stringscanner/get_byte_spec.rb
+++ b/spec/ruby/library/stringscanner/get_byte_spec.rb
@@ -1,7 +1,84 @@
+# encoding: binary
require_relative '../../spec_helper'
-require_relative 'shared/get_byte'
require 'strscan'
describe "StringScanner#get_byte" do
- it_behaves_like :strscan_get_byte, :get_byte
+ it "scans one byte and returns it" do
+ s = StringScanner.new('abc5.')
+ s.get_byte.should == 'a'
+ s.get_byte.should == 'b'
+ s.get_byte.should == 'c'
+ s.get_byte.should == '5'
+ s.get_byte.should == '.'
+ end
+
+ it "is not multi-byte character sensitive" do
+ s = StringScanner.new("\244\242")
+ s.get_byte.should == "\244"
+ s.get_byte.should == "\242"
+ end
+
+ it "returns nil at the end of the string" do
+ # empty string case
+ s = StringScanner.new('')
+ s.get_byte.should == nil
+ s.get_byte.should == nil
+
+ # non-empty string case
+ s = StringScanner.new('a')
+ s.get_byte # skip one
+ s.get_byte.should == nil
+ end
+
+ describe "#[] successive call with a capture group name" do
+ # https://github.com/ruby/strscan/issues/139
+ version_is StringScanner::Version, "3.1.1"..."3.1.3" do # ruby_version_is "3.4.0"..."3.4.3"
+ it "returns nil" do
+ s = StringScanner.new("This is a test")
+ s.get_byte
+ s.should.matched?
+ s[:a].should be_nil
+ end
+ end
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4.3"
+ it "raises IndexError" do
+ s = StringScanner.new("This is a test")
+ s.get_byte
+ s.should.matched?
+ -> { s[:a] }.should raise_error(IndexError)
+ end
+ end
+
+ it "returns a matching character when given Integer index" do
+ s = StringScanner.new("This is a test")
+ s.get_byte
+ s[0].should == "T"
+ end
+
+ # https://github.com/ruby/strscan/issues/135
+ version_is StringScanner::Version, "3.1.1"..."3.1.3" do # ruby_version_is "3.4.0"..."3.4.3"
+ it "ignores the previous matching with Regexp" do
+ s = StringScanner.new("This is a test")
+ s.exist?(/(?<a>This)/)
+ s.should.matched?
+ s[:a].should == "This"
+
+ s.get_byte
+ s.should.matched?
+ s[:a].should be_nil
+ end
+ end
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4.3"
+ it "ignores the previous matching with Regexp" do
+ s = StringScanner.new("This is a test")
+ s.exist?(/(?<a>This)/)
+ s.should.matched?
+ s[:a].should == "This"
+
+ s.get_byte
+ s.should.matched?
+ -> { s[:a] }.should raise_error(IndexError)
+ end
+ end
+ end
end
diff --git a/spec/ruby/library/stringscanner/getbyte_spec.rb b/spec/ruby/library/stringscanner/getbyte_spec.rb
deleted file mode 100644
index e0659a5829..0000000000
--- a/spec/ruby/library/stringscanner/getbyte_spec.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'shared/get_byte'
-require_relative 'shared/extract_range'
-require 'strscan'
-
-describe "StringScanner#getbyte" do
- it_behaves_like :strscan_get_byte, :getbyte
-
- it "warns in verbose mode that the method is obsolete" do
- s = StringScanner.new("abc")
- -> {
- s.getbyte
- }.should complain(/getbyte.*obsolete.*get_byte/, verbose: true)
-
- -> {
- s.getbyte
- }.should_not complain(verbose: false)
- end
-
- it_behaves_like :extract_range, :getbyte
-end
diff --git a/spec/ruby/library/stringscanner/getch_spec.rb b/spec/ruby/library/stringscanner/getch_spec.rb
index 449c20ad3b..d369391b14 100644
--- a/spec/ruby/library/stringscanner/getch_spec.rb
+++ b/spec/ruby/library/stringscanner/getch_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../spec_helper'
require_relative 'shared/extract_range'
require 'strscan'
@@ -31,5 +31,59 @@ describe "StringScanner#getch" do
s.getch.should == nil
end
+ describe "#[] successive call with a capture group name" do
+ # https://github.com/ruby/strscan/issues/139
+ version_is StringScanner::Version, "3.1.1"..."3.1.3" do # ruby_version_is "3.4.0"..."3.4.3"
+ it "returns nil" do
+ s = StringScanner.new("This is a test")
+ s.getch
+ s.should.matched?
+ s[:a].should be_nil
+ end
+ end
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4.3"
+ it "raises IndexError" do
+ s = StringScanner.new("This is a test")
+ s.getch
+ s.should.matched?
+ -> { s[:a] }.should raise_error(IndexError)
+ end
+ end
+
+ it "returns a matching character when given Integer index" do
+ s = StringScanner.new("This is a test")
+ s.getch
+ s[0].should == "T"
+ end
+
+ # https://github.com/ruby/strscan/issues/135
+ version_is StringScanner::Version, "3.1.1"..."3.1.3" do # ruby_version_is "3.4.0"..."3.4.3"
+ it "ignores the previous matching with Regexp" do
+ s = StringScanner.new("This is a test")
+
+ s.exist?(/(?<a>This)/)
+ s.should.matched?
+ s[:a].should == "This"
+
+ s.getch
+ s.should.matched?
+ s[:a].should be_nil
+ end
+ end
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4.0"..."3.4.3"
+ it "ignores the previous matching with Regexp" do
+ s = StringScanner.new("This is a test")
+
+ s.exist?(/(?<a>This)/)
+ s.should.matched?
+ s[:a].should == "This"
+
+ s.getch
+ s.should.matched?
+ -> { s[:a] }.should raise_error(IndexError)
+ end
+ end
+ end
+
it_behaves_like :extract_range, :getch
end
diff --git a/spec/ruby/library/stringscanner/initialize_spec.rb b/spec/ruby/library/stringscanner/initialize_spec.rb
index 047d9d058b..77f6084c1b 100644
--- a/spec/ruby/library/stringscanner/initialize_spec.rb
+++ b/spec/ruby/library/stringscanner/initialize_spec.rb
@@ -24,4 +24,9 @@ describe "StringScanner#initialize" do
scan = StringScanner.new(m)
scan.string.should == s
end
+
+ it "accepts a fixed_anchor keyword argument" do
+ s = StringScanner.new("foo", fixed_anchor: true)
+ s.should.fixed_anchor?
+ end
end
diff --git a/spec/ruby/library/stringscanner/match_spec.rb b/spec/ruby/library/stringscanner/match_spec.rb
index ec59680914..a27bb51d72 100644
--- a/spec/ruby/library/stringscanner/match_spec.rb
+++ b/spec/ruby/library/stringscanner/match_spec.rb
@@ -17,6 +17,15 @@ describe "StringScanner#match?" do
@s.match?(/\s+/).should == nil
end
+ it "sets the last match result" do
+ @s.pos = 8
+ @s.match?(/a/)
+
+ @s.pre_match.should == "This is "
+ @s.matched.should == "a"
+ @s.post_match.should == " test"
+ end
+
it "effects pre_match" do
@s.scan(/\w+/)
@s.scan(/\s/)
@@ -25,4 +34,18 @@ describe "StringScanner#match?" do
@s.match?(/\w+/)
@s.pre_match.should == "This "
end
+
+ describe "#[] successive call with a capture group name" do
+ it "returns matched substring when matching succeeded" do
+ @s.match?(/(?<a>This)/)
+ @s.should.matched?
+ @s[:a].should == "This"
+ end
+
+ it "returns nil when matching failed" do
+ @s.match?(/(?<a>2008)/)
+ @s.should_not.matched?
+ @s[:a].should be_nil
+ end
+ end
end
diff --git a/spec/ruby/library/stringscanner/must_C_version_spec.rb b/spec/ruby/library/stringscanner/must_C_version_spec.rb
index fcc5b596f6..9d6edfe7b6 100644
--- a/spec/ruby/library/stringscanner/must_C_version_spec.rb
+++ b/spec/ruby/library/stringscanner/must_C_version_spec.rb
@@ -3,6 +3,6 @@ require 'strscan'
describe "StringScanner.must_C_version" do
it "returns self" do
- StringScanner.must_C_version.should == StringScanner
+ StringScanner.must_C_version.should == StringScanner
end
end
diff --git a/spec/ruby/library/stringscanner/named_captures_spec.rb b/spec/ruby/library/stringscanner/named_captures_spec.rb
new file mode 100644
index 0000000000..a68d66c216
--- /dev/null
+++ b/spec/ruby/library/stringscanner/named_captures_spec.rb
@@ -0,0 +1,30 @@
+require_relative '../../spec_helper'
+require 'strscan'
+
+describe "StringScanner#named_captures" do
+ before do
+ @s = StringScanner.new('Fri Dec 12 1975 14:39')
+ end
+
+ it "returns a hash of names and matched substrings for named capturing groups in a regular expression of the most recent matching" do
+ @s.exist?(/(?<wday>\w+) (?<month>\w+) (?<day>\d+)/)
+ @s.named_captures.should == {"wday" => "Fri", "month" => "Dec", "day" => "12"}
+ end
+
+ it "returns {} if there are no named capturing groups" do
+ @s.exist?(/(\w+) (\w+) (\d+)/)
+ @s.named_captures.should == {}
+ end
+
+ # https://github.com/ruby/strscan/issues/132
+ ruby_bug "", ""..."3.3" do # fixed in strscan v3.0.7
+ it "returns {} if there is no any matching done" do
+ @s.named_captures.should == {}
+ end
+ end
+
+ it "returns nil for an optional named capturing group if it doesn't match" do
+ @s.exist?(/(?<wday>\w+) (?<month>\w+) (?<day>\s+)?/)
+ @s.named_captures.should == {"wday" => "Fri", "month" => "Dec", "day" => nil}
+ end
+end
diff --git a/spec/ruby/library/stringscanner/peek_byte_spec.rb b/spec/ruby/library/stringscanner/peek_byte_spec.rb
new file mode 100644
index 0000000000..88ef4a2b7c
--- /dev/null
+++ b/spec/ruby/library/stringscanner/peek_byte_spec.rb
@@ -0,0 +1,35 @@
+require_relative '../../spec_helper'
+require 'strscan'
+
+version_is StringScanner::Version, "3.1.1" do # ruby_version_is "3.4"
+ describe "StringScanner#peek_byte" do
+ it "returns a byte at the current position as an Integer" do
+ s = StringScanner.new('This is a test')
+ s.peek_byte.should == 84
+ end
+
+ it "returns nil at the end of the string" do
+ s = StringScanner.new('a')
+ s.getch # skip one
+ s.pos.should == 1
+ s.peek_byte.should == nil
+ end
+
+ it "is not multi-byte character sensitive" do
+ s = StringScanner.new("∂") # "∂".bytes => [226, 136, 130]
+ s.peek_byte.should == 226
+ s.pos = 1
+ s.peek_byte.should == 136
+ s.pos = 2
+ s.peek_byte.should == 130
+ end
+
+ it "doesn't change current position" do
+ s = StringScanner.new('This is a test')
+
+ s.pos.should == 0
+ s.peek_byte.should == 84
+ s.pos.should == 0
+ end
+ end
+end
diff --git a/spec/ruby/library/stringscanner/peek_spec.rb b/spec/ruby/library/stringscanner/peek_spec.rb
index cbb5630ff9..d490abecf9 100644
--- a/spec/ruby/library/stringscanner/peek_spec.rb
+++ b/spec/ruby/library/stringscanner/peek_spec.rb
@@ -1,7 +1,42 @@
require_relative '../../spec_helper'
-require_relative 'shared/peek'
require 'strscan'
describe "StringScanner#peek" do
- it_behaves_like :strscan_peek, :peek
+ before :each do
+ @s = StringScanner.new('This is a test')
+ end
+
+ it "returns at most the specified number of bytes from the current position" do
+ @s.peek(4).should == "This"
+ @s.pos.should == 0
+ @s.pos = 5
+ @s.peek(2).should == "is"
+ @s.peek(1000).should == "is a test"
+
+ s = StringScanner.new("été")
+ s.peek(2).should == "é"
+ end
+
+ it "returns an empty string when the passed argument is zero" do
+ @s.peek(0).should == ""
+ end
+
+ it "raises a ArgumentError when the passed argument is negative" do
+ -> { @s.peek(-2) }.should raise_error(ArgumentError)
+ end
+
+ it "raises a RangeError when the passed argument is a Bignum" do
+ -> { @s.peek(bignum_value) }.should raise_error(RangeError)
+ end
+
+ it "returns an instance of String when passed a String subclass" do
+ cls = Class.new(String)
+ sub = cls.new("abc")
+
+ s = StringScanner.new(sub)
+
+ ch = s.peek(1)
+ ch.should_not be_kind_of(cls)
+ ch.should be_an_instance_of(String)
+ end
end
diff --git a/spec/ruby/library/stringscanner/peep_spec.rb b/spec/ruby/library/stringscanner/peep_spec.rb
deleted file mode 100644
index bf6d579325..0000000000
--- a/spec/ruby/library/stringscanner/peep_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'shared/peek'
-require 'strscan'
-
-describe "StringScanner#peep" do
- it_behaves_like :strscan_peek, :peep
-
- it "warns in verbose mode that the method is obsolete" do
- s = StringScanner.new("abc")
- -> {
- s.peep(1)
- }.should complain(/peep.*obsolete.*peek/, verbose: true)
-
- -> {
- s.peep(1)
- }.should_not complain(verbose: false)
- end
-end
diff --git a/spec/ruby/library/stringscanner/rest_size_spec.rb b/spec/ruby/library/stringscanner/rest_size_spec.rb
index e62e3a8f8c..a5e971631a 100644
--- a/spec/ruby/library/stringscanner/rest_size_spec.rb
+++ b/spec/ruby/library/stringscanner/rest_size_spec.rb
@@ -1,7 +1,21 @@
require_relative '../../spec_helper'
-require_relative 'shared/rest_size'
require 'strscan'
describe "StringScanner#rest_size" do
- it_behaves_like :strscan_rest_size, :rest_size
+ before :each do
+ @s = StringScanner.new('This is a test')
+ end
+
+ it "returns the length of the rest of the string" do
+ @s.rest_size.should == 14
+ @s.scan(/This/)
+ @s.rest_size.should == 10
+ @s.terminate
+ @s.rest_size.should == 0
+ end
+
+ it "is equivalent to rest.size" do
+ @s.scan(/This/)
+ @s.rest_size.should == @s.rest.size
+ end
end
diff --git a/spec/ruby/library/stringscanner/restsize_spec.rb b/spec/ruby/library/stringscanner/restsize_spec.rb
deleted file mode 100644
index 710520afae..0000000000
--- a/spec/ruby/library/stringscanner/restsize_spec.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-require_relative '../../spec_helper'
-require_relative 'shared/rest_size'
-require 'strscan'
-
-describe "StringScanner#restsize" do
- it_behaves_like :strscan_rest_size, :restsize
-
- it "warns in verbose mode that the method is obsolete" do
- s = StringScanner.new("abc")
- -> {
- s.restsize
- }.should complain(/restsize.*obsolete.*rest_size/, verbose: true)
-
- -> {
- s.restsize
- }.should_not complain(verbose: false)
- end
-end
diff --git a/spec/ruby/library/stringscanner/scan_byte_spec.rb b/spec/ruby/library/stringscanner/scan_byte_spec.rb
new file mode 100644
index 0000000000..aa2decc8f7
--- /dev/null
+++ b/spec/ruby/library/stringscanner/scan_byte_spec.rb
@@ -0,0 +1,98 @@
+require_relative '../../spec_helper'
+require 'strscan'
+
+version_is StringScanner::Version, "3.1.1" do # ruby_version_is "3.4"
+ describe "StringScanner#scan_byte" do
+ it "scans one byte and returns it as on Integer" do
+ s = StringScanner.new('abc') # "abc".bytes => [97, 98, 99]
+ s.scan_byte.should == 97
+ s.scan_byte.should == 98
+ s.scan_byte.should == 99
+ end
+
+ it "is not multi-byte character sensitive" do
+ s = StringScanner.new("あ") # "あ".bytes => [227, 129, 130]
+ s.scan_byte.should == 227
+ s.scan_byte.should == 129
+ s.scan_byte.should == 130
+ end
+
+ it "returns nil at the end of the string" do
+ s = StringScanner.new('a')
+ s.scan_byte # skip one
+ s.scan_byte.should == nil
+ s.pos.should == 1
+ end
+
+ it "changes current position" do
+ s = StringScanner.new('abc')
+ s.pos.should == 0
+ s.scan_byte
+ s.pos.should == 1
+ end
+
+ it "sets the last match result" do
+ s = StringScanner.new('abc')
+ s.pos = 1
+ s.scan_byte
+
+ s.pre_match.should == "a"
+ s.matched.should == "b"
+ s.post_match.should == "c"
+ end
+
+ describe "#[] successive call with a capture group name" do
+ # https://github.com/ruby/strscan/issues/139
+ version_is StringScanner::Version, "3.1.1"..."3.1.3" do # ruby_version_is "3.4.0"..."3.4.3"
+ it "returns nil" do
+ s = StringScanner.new("abc")
+ s.scan_byte
+ s.should.matched?
+ s[:a].should be_nil
+ end
+ end
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4.3"
+ it "raises IndexError" do
+ s = StringScanner.new("abc")
+ s.scan_byte
+ s.should.matched?
+ -> { s[:a] }.should raise_error(IndexError)
+ end
+ end
+
+ it "returns a matching character when given Integer index" do
+ s = StringScanner.new("This is a test")
+ s.scan_byte
+ s[0].should == "T"
+ end
+
+ # https://github.com/ruby/strscan/issues/135
+ version_is StringScanner::Version, "3.1.1"..."3.1.3" do # ruby_version_is "3.4.0"..."3.4.3"
+ it "ignores the previous matching with Regexp" do
+ s = StringScanner.new("abc")
+
+ s.exist?(/(?<a>a)/)
+ s.should.matched?
+ s[:a].should == "a"
+
+ s.scan_byte
+ s.should.matched?
+ s[:a].should == nil
+ end
+ end
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4.0"..."3.4.3"
+ it "ignores the previous matching with Regexp" do
+ s = StringScanner.new("abc")
+
+ s.exist?(/(?<a>a)/)
+ s.should.matched?
+ s[:a].should == "a"
+
+ s.scan_byte
+ s.should.matched?
+ -> { s[:a] }.should raise_error(IndexError)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/stringscanner/scan_full_spec.rb b/spec/ruby/library/stringscanner/scan_full_spec.rb
index ed34d7d3f6..967313f5ca 100644
--- a/spec/ruby/library/stringscanner/scan_full_spec.rb
+++ b/spec/ruby/library/stringscanner/scan_full_spec.rb
@@ -27,4 +27,18 @@ describe "StringScanner#scan_full" do
@s.scan_full(/This/, true, true).should == "This"
@s.pos.should == 4
end
+
+ describe "#[] successive call with a capture group name" do
+ it "returns matched substring when matching succeeded" do
+ @s.scan_full(/(?<a>This)/, false, false)
+ @s.should.matched?
+ @s[:a].should == "This"
+ end
+
+ it "returns nil when matching failed" do
+ @s.scan_full(/(?<a>2008)/, false, false)
+ @s.should_not.matched?
+ @s[:a].should be_nil
+ end
+ end
end
diff --git a/spec/ruby/library/stringscanner/scan_integer_spec.rb b/spec/ruby/library/stringscanner/scan_integer_spec.rb
new file mode 100644
index 0000000000..fe0d26f404
--- /dev/null
+++ b/spec/ruby/library/stringscanner/scan_integer_spec.rb
@@ -0,0 +1,157 @@
+require_relative '../../spec_helper'
+require 'strscan'
+
+version_is StringScanner::Version, "3.1.1" do # ruby_version_is "3.4"
+ describe "StringScanner#scan_integer" do
+ it "returns the matched Integer literal starting from the current position" do
+ s = StringScanner.new("42")
+ s.scan_integer.should == 42
+ end
+
+ it "returns nil when no Integer literal matched starting from the current position" do
+ s = StringScanner.new("a42")
+ s.scan_integer.should == nil
+ end
+
+ it "supports a sign +/-" do
+ StringScanner.new("+42").scan_integer.should == 42
+ StringScanner.new("-42").scan_integer.should == -42
+ end
+
+ it "changes the current position" do
+ s = StringScanner.new("42abc")
+ s.scan_integer
+ s.pos.should == 2
+ end
+
+ # https://github.com/ruby/strscan/issues/130
+ ruby_bug "", "3.4"..."4.0" do # introduced in strscan v3.1.1
+ it "sets the last match result" do
+ s = StringScanner.new("42abc")
+ s.scan_integer
+
+ s.should.matched?
+ s.matched.should == "42"
+ s.pre_match.should == ""
+ s.post_match.should == "abc"
+ s.matched_size.should == 2
+ end
+ end
+
+ it "raises Encoding::CompatibilityError when a scanned string not is ASCII-compatible encoding" do
+ string = "42".encode(Encoding::UTF_16BE)
+ s = StringScanner.new(string)
+
+ -> {
+ s.scan_integer
+ }.should raise_error(Encoding::CompatibilityError, 'ASCII incompatible encoding: UTF-16BE')
+ end
+
+ context "given base" do
+ it "supports base: 10" do
+ s = StringScanner.new("42")
+ s.scan_integer(base: 10).should == 42
+ end
+
+ it "supports base: 16" do
+ StringScanner.new("0xff").scan_integer(base: 16).should == 0xff
+ StringScanner.new("-0xff").scan_integer(base: 16).should == -0xff
+ StringScanner.new("0xFF").scan_integer(base: 16).should == 0xff
+ StringScanner.new("-0xFF").scan_integer(base: 16).should == -0xff
+ StringScanner.new("ff").scan_integer(base: 16).should == 0xff
+ StringScanner.new("-ff").scan_integer(base: 16).should == -0xff
+ end
+
+ it "raises ArgumentError when passed not supported base" do
+ -> {
+ StringScanner.new("42").scan_integer(base: 5)
+ }.should raise_error(ArgumentError, "Unsupported integer base: 5, expected 10 or 16")
+ end
+
+ version_is StringScanner::Version, "3.1.1"..."3.1.3" do # ruby_version_is "3.4.0"..."3.4.3"
+ it "does not match '0x' prefix on its own" do
+ StringScanner.new("0x").scan_integer(base: 16).should == nil
+ StringScanner.new("-0x").scan_integer(base: 16).should == nil
+ StringScanner.new("+0x").scan_integer(base: 16).should == nil
+ end
+ end
+
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4.3"
+ it "matches '0' in a '0x' that is followed by non-hex characters" do
+ StringScanner.new("0x!@#").scan_integer(base: 16).should == 0
+ StringScanner.new("-0x!@#").scan_integer(base: 16).should == 0
+ StringScanner.new("+0x!@#").scan_integer(base: 16).should == 0
+ end
+
+ it "matches '0' in a '0x' located in the end of a string" do
+ StringScanner.new("0x").scan_integer(base: 16).should == 0
+ StringScanner.new("-0x").scan_integer(base: 16).should == 0
+ StringScanner.new("+0x").scan_integer(base: 16).should == 0
+ end
+ end
+ end
+ end
+
+ describe "#[] successive call with a capture group name" do
+ # https://github.com/ruby/strscan/issues/139
+ version_is StringScanner::Version, "3.1.1"..."3.1.3" do # ruby_version_is "3.4.0"..."3.4.3"
+ it "returns nil substring when matching succeeded" do
+ s = StringScanner.new("42")
+ s.scan_integer
+ s.should.matched?
+ s[:a].should == nil
+ end
+ end
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4.3"
+ it "raises IndexError when matching succeeded" do
+ s = StringScanner.new("42")
+ s.scan_integer
+ s.should.matched?
+ -> { s[:a] }.should raise_error(IndexError)
+ end
+ end
+
+ it "returns nil when matching failed" do
+ s = StringScanner.new("a42")
+ s.scan_integer
+ s.should_not.matched?
+ s[:a].should be_nil
+ end
+
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4"
+ it "returns a matching substring when given Integer index" do
+ s = StringScanner.new("42")
+ s.scan_integer
+ s[0].should == "42"
+ end
+ end
+
+ # https://github.com/ruby/strscan/issues/135
+ version_is StringScanner::Version, "3.1.1"..."3.1.3" do # ruby_version_is "3.4.0"..."3.4.3"
+ it "does not ignore the previous matching with Regexp" do
+ s = StringScanner.new("42")
+
+ s.exist?(/(?<a>42)/)
+ s.should.matched?
+ s[:a].should == "42"
+
+ s.scan_integer
+ s.should.matched?
+ s[:a].should == "42"
+ end
+ end
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4"
+ it "ignores the previous matching with Regexp" do
+ s = StringScanner.new("42")
+
+ s.exist?(/(?<a>42)/)
+ s.should.matched?
+ s[:a].should == "42"
+
+ s.scan_integer
+ s.should.matched?
+ -> { s[:a] }.should raise_error(IndexError)
+ end
+ end
+ end
+end
diff --git a/spec/ruby/library/stringscanner/scan_spec.rb b/spec/ruby/library/stringscanner/scan_spec.rb
index ea711767b9..088c3419fb 100644
--- a/spec/ruby/library/stringscanner/scan_spec.rb
+++ b/spec/ruby/library/stringscanner/scan_spec.rb
@@ -60,6 +60,20 @@ describe "StringScanner#scan" do
-> { @s.scan(:test) }.should raise_error(TypeError)
-> { @s.scan(mock('x')) }.should raise_error(TypeError)
end
+
+ describe "#[] successive call with a capture group name" do
+ it "returns matched substring when matching succeeded" do
+ @s.scan(/(?<a>This)/)
+ @s.should.matched?
+ @s[:a].should == "This"
+ end
+
+ it "returns nil when matching failed" do
+ @s.scan(/(?<a>2008)/)
+ @s.should_not.matched?
+ @s[:a].should be_nil
+ end
+ end
end
describe "StringScanner#scan with fixed_anchor: true" do
diff --git a/spec/ruby/library/stringscanner/scan_until_spec.rb b/spec/ruby/library/stringscanner/scan_until_spec.rb
index 6b7782572d..610060d6f1 100644
--- a/spec/ruby/library/stringscanner/scan_until_spec.rb
+++ b/spec/ruby/library/stringscanner/scan_until_spec.rb
@@ -2,14 +2,20 @@ require_relative '../../spec_helper'
require 'strscan'
describe "StringScanner#scan_until" do
- before :each do
+ before do
@s = StringScanner.new("This is a test")
end
it "returns the substring up to and including the end of the match" do
- @s.scan_until(/a/).should == "This is a"
- @s.pre_match.should == "This is "
- @s.post_match.should == " test"
+ @s.scan_until(/a/).should == "This is a"
+ end
+
+ it "sets the last match result" do
+ @s.scan_until(/a/)
+
+ @s.pre_match.should == "This is "
+ @s.matched.should == "a"
+ @s.post_match.should == " test"
end
it "returns nil if there's no match" do
@@ -21,9 +27,109 @@ describe "StringScanner#scan_until" do
@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)')
+ version_is StringScanner::Version, ""..."3.1.1" do # ruby_version_is ""..."3.4"
+ it "raises TypeError if given a String" do
+ -> {
+ @s.scan_until('T')
+ }.should raise_error(TypeError, 'wrong argument type String (expected Regexp)')
+ end
+ end
+
+ version_is StringScanner::Version, "3.1.1" do # ruby_version_is "3.4"
+ it "searches a substring in the rest part of a string if given a String" do
+ @s.scan_until("a").should == "This is a"
+ end
+
+ # https://github.com/ruby/strscan/issues/131
+ version_is StringScanner::Version, "3.1.1"..."3.1.3" do # ruby_version_is "3.4.1"
+ it "sets the last match result if given a String" do
+ @s.scan_until("a")
+
+ @s.pre_match.should == ""
+ @s.matched.should == "This is a"
+ @s.post_match.should == " test"
+ end
+ end
+
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4"
+ it "sets the last match result if given a String" do
+ @s.scan_until("a")
+
+ @s.pre_match.should == "This is "
+ @s.matched.should == "a"
+ @s.post_match.should == " test"
+ end
+ end
+ end
+
+ describe "#[] successive call with a capture group name" do
+ context "when #scan_until was called with a Regexp pattern" do
+ it "returns matched substring when matching succeeded" do
+ @s.scan_until(/(?<a>This)/)
+ @s.should.matched?
+ @s[:a].should == "This"
+ end
+
+ it "returns nil when matching failed" do
+ @s.scan_until(/(?<a>2008)/)
+ @s.should_not.matched?
+ @s[:a].should be_nil
+ end
+ end
+
+ version_is StringScanner::Version, "3.1.1" do # ruby_version_is "3.4"
+ context "when #scan_until was called with a String pattern" do
+ # https://github.com/ruby/strscan/issues/139
+ version_is StringScanner::Version, "3.1.1"..."3.1.3" do # ruby_version_is "3.4.0"..."3.4.3"
+ it "returns nil when matching succeeded" do
+ @s.scan_until("This")
+ @s.should.matched?
+ @s[:a].should be_nil
+ end
+ end
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4.3"
+ it "raises IndexError when matching succeeded" do
+ @s.scan_until("This")
+ @s.should.matched?
+ -> { @s[:a] }.should raise_error(IndexError)
+ end
+ end
+
+ it "returns nil when matching failed" do
+ @s.scan_until("2008")
+ @s.should_not.matched?
+ @s[:a].should be_nil
+ end
+
+ it "returns a matching substring when given Integer index" do
+ @s.scan_until("This")
+ @s[0].should == "This"
+ end
+
+ # https://github.com/ruby/strscan/issues/135
+ version_is StringScanner::Version, "3.1.1"..."3.1.3" do # ruby_version_is "3.4.0"..."3.4.3"
+ it "ignores the previous matching with Regexp" do
+ @s.exist?(/(?<a>This)/)
+ @s.should.matched?
+ @s[:a].should == "This"
+
+ @s.scan_until("This")
+ @s.should.matched?
+ @s[:a].should be_nil
+ end
+ end
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4"
+ it "ignores the previous matching with Regexp" do
+ @s.exist?(/(?<a>This)/)
+ @s.should.matched?
+ @s[:a].should == "This"
+
+ @s.scan_until("This")
+ @s.should.matched?
+ -> { @s[:a] }.should raise_error(IndexError)
+ end
+ end
+ end
+ end
end
end
diff --git a/spec/ruby/library/stringscanner/search_full_spec.rb b/spec/ruby/library/stringscanner/search_full_spec.rb
index 7d2a714fa5..197adfda4d 100644
--- a/spec/ruby/library/stringscanner/search_full_spec.rb
+++ b/spec/ruby/library/stringscanner/search_full_spec.rb
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
require 'strscan'
describe "StringScanner#search_full" do
- before :each do
+ before do
@s = StringScanner.new("This is a test")
end
@@ -28,9 +28,106 @@ describe "StringScanner#search_full" do
@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)')
+ it "sets the last match result" do
+ @s.search_full(/is a/, false, false)
+
+ @s.pre_match.should == "This "
+ @s.matched.should == "is a"
+ @s.post_match.should == " test"
+ end
+
+ version_is StringScanner::Version, ""..."3.1.1" do # ruby_version_is ""..."3.4"
+ 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
+
+ version_is StringScanner::Version, "3.1.1" do # ruby_version_is "3.4"
+ it "searches a substring in the rest part of a string if given a String" do
+ @s.search_full("is a", false, false).should == 9
+ end
+
+ # https://github.com/ruby/strscan/issues/131
+ version_is StringScanner::Version, "3.1.1"..."3.1.3" do # ruby_version_is "3.4.1"
+ it "sets the last match result if given a String" do
+ @s.search_full("is a", false, false)
+
+ @s.pre_match.should == ""
+ @s.matched.should == "This is a"
+ @s.post_match.should == " test"
+ end
+ end
+
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4"
+ it "sets the last match result if given a String" do
+ @s.search_full("is a", false, false)
+
+ @s.pre_match.should == "This "
+ @s.matched.should == "is a"
+ @s.post_match.should == " test"
+ end
+ end
+ end
+
+ describe "#[] successive call with a capture group name" do
+ context "when #search_full was called with a Regexp pattern" do
+ it "returns matched substring when matching succeeded" do
+ @s.search_full(/(?<a>This)/, false, false)
+ @s.should.matched?
+ @s[:a].should == "This"
+ end
+
+ it "returns nil when matching failed" do
+ @s.search_full(/(?<a>2008)/, false, false)
+ @s.should_not.matched?
+ @s[:a].should be_nil
+ end
+ end
+
+ version_is StringScanner::Version, "3.1.1" do # ruby_version_is "3.4"
+ context "when #search_full was called with a String pattern" do
+ # https://github.com/ruby/strscan/issues/139
+ version_is StringScanner::Version, "3.1.1"..."3.1.3" do # ruby_version_is "3.4.0"..."3.4.3"
+ it "returns nil when matching succeeded" do
+ @s.search_full("This", false, false)
+ @s.should.matched?
+ @s[:a].should be_nil
+ end
+ end
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4.3"
+ it "raises IndexError when matching succeeded" do
+ @s.search_full("This", false, false)
+ @s.should.matched?
+ -> { @s[:a] }.should raise_error(IndexError)
+ end
+ end
+
+ it "returns nil when matching failed" do
+ @s.search_full("2008", false, false)
+ @s.should_not.matched?
+ @s[:a].should be_nil
+ end
+
+ it "returns a matching substring when given Integer index" do
+ @s.search_full("This", false, false)
+ @s[0].should == "This"
+ end
+
+ # https://github.com/ruby/strscan/issues/135
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4"
+ it "ignores the previous matching with Regexp" do
+ @s.exist?(/(?<a>This)/)
+ @s.should.matched?
+ @s[:a].should == "This"
+
+ @s.search_full("This", false, false)
+ @s.should.matched?
+ -> { @s[:a] }.should raise_error(IndexError)
+ end
+ end
+ end
+ end
end
end
diff --git a/spec/ruby/library/stringscanner/shared/eos.rb b/spec/ruby/library/stringscanner/shared/eos.rb
deleted file mode 100644
index ea04c764a2..0000000000
--- a/spec/ruby/library/stringscanner/shared/eos.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-describe :strscan_eos, shared: true do
- before :each do
- @s = StringScanner.new("This is a test")
- end
-
- it "returns true if the scan pointer is at the end of the string" do
- @s.terminate
- @s.send(@method).should be_true
-
- s = StringScanner.new('')
- s.send(@method).should be_true
- end
-
- it "returns false if the scan pointer is not at the end of the string" do
- @s.send(@method).should be_false
- end
-end
diff --git a/spec/ruby/library/stringscanner/shared/get_byte.rb b/spec/ruby/library/stringscanner/shared/get_byte.rb
deleted file mode 100644
index 763ab6f4a4..0000000000
--- a/spec/ruby/library/stringscanner/shared/get_byte.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# -*- encoding: binary -*-
-describe :strscan_get_byte, shared: true do
- it "scans one byte and returns it" do
- s = StringScanner.new('abc5.')
- s.send(@method).should == 'a'
- s.send(@method).should == 'b'
- s.send(@method).should == 'c'
- s.send(@method).should == '5'
- s.send(@method).should == '.'
- end
-
- it "is not multi-byte character sensitive" do
- s = StringScanner.new("\244\242")
- s.send(@method).should == "\244"
- s.send(@method).should == "\242"
- end
-
- it "returns nil at the end of the string" do
- # empty string case
- s = StringScanner.new('')
- s.send(@method).should == nil
- s.send(@method).should == nil
-
- # non-empty string case
- s = StringScanner.new('a')
- s.send(@method) # skip one
- s.send(@method).should == nil
- end
-end
diff --git a/spec/ruby/library/stringscanner/shared/peek.rb b/spec/ruby/library/stringscanner/shared/peek.rb
deleted file mode 100644
index 4c757866c1..0000000000
--- a/spec/ruby/library/stringscanner/shared/peek.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-describe :strscan_peek, shared: true do
- before :each do
- @s = StringScanner.new('This is a test')
- end
-
- it "returns at most the specified number of bytes from the current position" do
- @s.send(@method, 4).should == "This"
- @s.pos.should == 0
- @s.pos = 5
- @s.send(@method, 2).should == "is"
- @s.send(@method, 1000).should == "is a test"
-
- s = StringScanner.new("été")
- s.send(@method, 2).should == "é"
- end
-
- it "returns an empty string when the passed argument is zero" do
- @s.send(@method, 0).should == ""
- end
-
- it "raises a ArgumentError when the passed argument is negative" do
- -> { @s.send(@method, -2) }.should raise_error(ArgumentError)
- end
-
- it "raises a RangeError when the passed argument is a Bignum" do
- -> { @s.send(@method, bignum_value) }.should raise_error(RangeError)
- end
-
- it "returns an instance of String when passed a String subclass" do
- cls = Class.new(String)
- sub = cls.new("abc")
-
- s = StringScanner.new(sub)
-
- ch = s.send(@method, 1)
- ch.should_not be_kind_of(cls)
- ch.should be_an_instance_of(String)
- end
-end
diff --git a/spec/ruby/library/stringscanner/shared/pos.rb b/spec/ruby/library/stringscanner/shared/pos.rb
index 6d540881f2..eea7ead6b5 100644
--- a/spec/ruby/library/stringscanner/shared/pos.rb
+++ b/spec/ruby/library/stringscanner/shared/pos.rb
@@ -22,6 +22,13 @@ describe :strscan_pos, shared: true do
@s.terminate
@s.send(@method).should == @s.string.length
end
+
+ it "is not multi-byte character sensitive" do
+ s = StringScanner.new("abcädeföghi")
+
+ s.scan_until(/ö/)
+ s.pos.should == 10
+ end
end
describe :strscan_pos_set, shared: true do
diff --git a/spec/ruby/library/stringscanner/shared/rest_size.rb b/spec/ruby/library/stringscanner/shared/rest_size.rb
deleted file mode 100644
index 4c4f49e45c..0000000000
--- a/spec/ruby/library/stringscanner/shared/rest_size.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-describe :strscan_rest_size, shared: true do
- before :each do
- @s = StringScanner.new('This is a test')
- end
-
- it "returns the length of the rest of the string" do
- @s.send(@method).should == 14
- @s.scan(/This/)
- @s.send(@method).should == 10
- @s.terminate
- @s.send(@method).should == 0
- end
-
- it "is equivalent to rest.size" do
- @s.scan(/This/)
- @s.send(@method).should == @s.rest.size
- end
-end
diff --git a/spec/ruby/library/stringscanner/shared/terminate.rb b/spec/ruby/library/stringscanner/shared/terminate.rb
deleted file mode 100644
index bf41d097e2..0000000000
--- a/spec/ruby/library/stringscanner/shared/terminate.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-describe :strscan_terminate, shared: true do
- it "set the scan pointer to the end of the string and clear matching data." do
- s = StringScanner.new('This is a test')
- s.send(@method)
- s.bol?.should be_false
- s.eos?.should be_true
- end
-end
diff --git a/spec/ruby/library/stringscanner/skip_spec.rb b/spec/ruby/library/stringscanner/skip_spec.rb
index 473361782c..12f5b7781c 100644
--- a/spec/ruby/library/stringscanner/skip_spec.rb
+++ b/spec/ruby/library/stringscanner/skip_spec.rb
@@ -15,4 +15,18 @@ describe "StringScanner#skip" do
@s.skip(/\s+/).should == nil
@s.skip(/\d+/).should == nil
end
+
+ describe "#[] successive call with a capture group name" do
+ it "returns matched substring when matching succeeded" do
+ @s.skip(/(?<a>This)/)
+ @s.should.matched?
+ @s[:a].should == "This"
+ end
+
+ it "returns nil when matching failed" do
+ @s.skip(/(?<a>2008)/)
+ @s.should_not.matched?
+ @s[:a].should be_nil
+ end
+ end
end
diff --git a/spec/ruby/library/stringscanner/skip_until_spec.rb b/spec/ruby/library/stringscanner/skip_until_spec.rb
index 7b56f13e4f..5d73d8f0b9 100644
--- a/spec/ruby/library/stringscanner/skip_until_spec.rb
+++ b/spec/ruby/library/stringscanner/skip_until_spec.rb
@@ -2,23 +2,131 @@ require_relative '../../spec_helper'
require 'strscan'
describe "StringScanner#skip_until" do
- before :each do
+ before do
@s = StringScanner.new("This is a test")
end
it "returns the number of bytes advanced and advances the scan pointer until pattern is matched and consumed" do
@s.skip_until(/a/).should == 9
@s.pos.should == 9
+ end
+
+ it "sets the last match result" do
+ @s.skip_until(/a/)
+
+ @s.pre_match.should == "This is "
@s.matched.should == "a"
+ @s.post_match.should == " test"
end
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)')
+ version_is StringScanner::Version, ""..."3.1.1" do # ruby_version_is ""..."3.4"
+ it "raises TypeError if given a String" do
+ -> {
+ @s.skip_until('T')
+ }.should raise_error(TypeError, 'wrong argument type String (expected Regexp)')
+ end
+ end
+
+ version_is StringScanner::Version, "3.1.1" do # ruby_version_is "3.4"
+ it "searches a substring in the rest part of a string if given a String" do
+ @s.skip_until("a").should == 9
+ @s.pos.should == 9
+ end
+
+ # https://github.com/ruby/strscan/issues/131
+ version_is StringScanner::Version, "3.1.1"..."3.1.3" do # ruby_version_is "3.4.1"
+ it "sets the last match result if given a String" do
+ @s.skip_until("a")
+
+ @s.pre_match.should == ""
+ @s.matched.should == "This is a"
+ @s.post_match.should == " test"
+ end
+ end
+
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4"
+ it "sets the last match result if given a String" do
+ @s.skip_until("a")
+
+ @s.pre_match.should == "This is "
+ @s.matched.should == "a"
+ @s.post_match.should == " test"
+ end
+ end
+ end
+
+ describe "#[] successive call with a capture group name" do
+ context "when #scan_until was called with a Regexp pattern" do
+ it "returns matched substring when matching succeeded" do
+ @s.skip_until(/(?<a>This)/)
+ @s.should.matched?
+ @s[:a].should == "This"
+ end
+
+ it "returns nil when matching failed" do
+ @s.skip_until(/(?<a>2008)/)
+ @s.should_not.matched?
+ @s[:a].should be_nil
+ end
+ end
+
+ version_is StringScanner::Version, "3.1.1" do # ruby_version_is "3.4"
+ context "when #skip_until was called with a String pattern" do
+ # https://github.com/ruby/strscan/issues/139
+ version_is StringScanner::Version, "3.1.1"..."3.1.3" do # ruby_version_is "3.4.0"..."3.4.3"
+ it "returns nil when matching succeeded" do
+ @s.skip_until("This")
+ @s.should.matched?
+ @s[:a].should be_nil
+ end
+ end
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4.3"
+ it "raises IndexError when matching succeeded" do
+ @s.skip_until("This")
+ @s.should.matched?
+ -> { @s[:a] }.should raise_error(IndexError)
+ end
+ end
+
+ it "returns nil when matching failed" do
+ @s.skip_until("2008")
+ @s.should_not.matched?
+ @s[:a].should be_nil
+ end
+
+ it "returns a matching substring when given Integer index" do
+ @s.skip_until("This")
+ @s[0].should == "This"
+ end
+
+ # https://github.com/ruby/strscan/issues/135
+ version_is StringScanner::Version, "3.1.1"..."3.1.3" do # ruby_version_is "3.4.0"..."3.4.3"
+ it "ignores the previous matching with Regexp" do
+ @s.exist?(/(?<a>This)/)
+ @s.should.matched?
+ @s[:a].should == "This"
+
+ @s.skip_until("This")
+ @s.should.matched?
+ @s[:a].should be_nil
+ end
+ end
+ version_is StringScanner::Version, "3.1.3" do # ruby_version_is "3.4"
+ it "ignores the previous matching with Regexp" do
+ @s.exist?(/(?<a>This)/)
+ @s.should.matched?
+ @s[:a].should == "This"
+
+ @s.skip_until("This")
+ @s.should.matched?
+ -> { @s[:a] }.should raise_error(IndexError)
+ end
+ end
+ end
+ end
end
end
diff --git a/spec/ruby/library/stringscanner/terminate_spec.rb b/spec/ruby/library/stringscanner/terminate_spec.rb
index 249023f1ab..3cff5c010c 100644
--- a/spec/ruby/library/stringscanner/terminate_spec.rb
+++ b/spec/ruby/library/stringscanner/terminate_spec.rb
@@ -1,7 +1,11 @@
require_relative '../../spec_helper'
-require_relative 'shared/terminate'
require 'strscan'
describe "StringScanner#terminate" do
- it_behaves_like :strscan_terminate, :terminate
+ it "set the scan pointer to the end of the string and clear matching data." do
+ s = StringScanner.new('This is a test')
+ s.terminate
+ s.should_not.bol?
+ s.should.eos?
+ end
end
diff --git a/spec/ruby/library/stringscanner/unscan_spec.rb b/spec/ruby/library/stringscanner/unscan_spec.rb
index df0ea43367..b7b4876b8a 100644
--- a/spec/ruby/library/stringscanner/unscan_spec.rb
+++ b/spec/ruby/library/stringscanner/unscan_spec.rb
@@ -21,8 +21,8 @@ describe "StringScanner#unscan" do
@s.pos.should == pos
end
- it "raises a ScanError when the previous match had failed" do
- -> { @s.unscan }.should raise_error(ScanError)
- -> { @s.scan(/\d/); @s.unscan }.should raise_error(ScanError)
+ it "raises a StringScanner::Error when the previous match had failed" do
+ -> { @s.unscan }.should raise_error(StringScanner::Error)
+ -> { @s.scan(/\d/); @s.unscan }.should raise_error(StringScanner::Error)
end
end
diff --git a/spec/ruby/library/stringscanner/values_at_spec.rb b/spec/ruby/library/stringscanner/values_at_spec.rb
new file mode 100644
index 0000000000..14d4a5f6a7
--- /dev/null
+++ b/spec/ruby/library/stringscanner/values_at_spec.rb
@@ -0,0 +1,68 @@
+require_relative '../../spec_helper'
+require 'strscan'
+
+describe "StringScanner#captures" do
+ before do
+ @s = StringScanner.new('Fri Dec 12 1975 14:39')
+ end
+
+ context "when passed a list of Integers" do
+ it "returns an array containing each value given by one of integers" do
+ @s.exist?(/(?<wday>\w+) (?<month>\w+) (?<day>\d+)/)
+ @s.values_at(0, 1, 2, 3).should == ["Fri Dec 12", "Fri", "Dec", "12"]
+ end
+
+ it "returns nil value for any integer that is out of range" do
+ @s.exist?(/(?<wday>\w+) (?<month>\w+) (?<day>\d+)/)
+ @s.values_at(4).should == [nil]
+ @s.values_at(-5).should == [nil]
+ end
+ end
+
+ context "when passed names" do
+ it 'slices captures with the given names' do
+ @s.exist?(/(?<wday>\w+) (?<month>\w+) (?<day>\d+)/)
+ @s.values_at(:wday, :month, :day).should == ["Fri", "Dec", "12"]
+ end
+
+ it 'slices captures with the given String names' do
+ @s.exist?(/(?<wday>\w+) (?<month>\w+) (?<day>\d+)/)
+ @s.values_at("wday", "month", "day").should == ["Fri", "Dec", "12"]
+ end
+
+ it "raises IndexError when given unknown name" do
+ @s.exist?(/(?<wday>\w+) (?<month>\w+) (?<day>\d+)/)
+
+ -> {
+ @s.values_at("foo")
+ }.should raise_error(IndexError, "undefined group name reference: foo")
+ end
+ end
+
+ it 'supports mixing of names and indices' do
+ @s.exist?(/(?<wday>\w+) (?<month>\w+) (?<day>\d+)/)
+ @s.values_at(1, "wday", 2, "month", 3, "day").should == ["Fri", "Fri", "Dec", "Dec", "12", "12"]
+ end
+
+ it "returns a new empty Array if no arguments given" do
+ @s.exist?(/(?<wday>\w+) (?<month>\w+) (?<day>\d+)/)
+ @s.values_at().should == []
+ end
+
+ it "fails when passed arguments of unsupported types" do
+ @s.exist?(/(?<wday>\w+) (?<month>\w+) (?<day>\d+)/)
+
+ -> {
+ @s.values_at([])
+ }.should raise_error(TypeError, "no implicit conversion of Array into Integer")
+ end
+
+ it "returns nil if the most recent matching fails" do
+ @s.exist?(/(?<wday>\w+) (?<month>\w+) (?<day>\s+)/)
+ @s.values_at(1, 2, 3).should == nil
+ end
+
+ it "returns nil if there is no any matching done" do
+ @s.values_at(1, 2, 3).should == nil
+ end
+end
diff --git a/spec/ruby/library/syslog/constants_spec.rb b/spec/ruby/library/syslog/constants_spec.rb
index 2b9524c53d..fc9db47dd8 100644
--- a/spec/ruby/library/syslog/constants_spec.rb
+++ b/spec/ruby/library/syslog/constants_spec.rb
@@ -4,7 +4,7 @@ platform_is_not :windows do
require 'syslog'
describe "Syslog::Constants" do
- platform_is_not :windows, :solaris, :aix do
+ platform_is_not :windows, :aix do
before :all do
@constants = %w(LOG_AUTHPRIV LOG_USER LOG_LOCAL2 LOG_NOTICE LOG_NDELAY
LOG_SYSLOG LOG_ALERT LOG_FTP LOG_LOCAL5 LOG_ERR LOG_AUTH
diff --git a/spec/ruby/library/syslog/log_spec.rb b/spec/ruby/library/syslog/log_spec.rb
index 8589fb1f73..0c855b8257 100644
--- a/spec/ruby/library/syslog/log_spec.rb
+++ b/spec/ruby/library/syslog/log_spec.rb
@@ -4,7 +4,7 @@ platform_is_not :windows do
require 'syslog'
describe "Syslog.log" do
- platform_is_not :windows, :darwin, :solaris, :aix, :android do
+ platform_is_not :windows, :darwin, :aix, :android do
before :each do
Syslog.opened?.should be_false
diff --git a/spec/ruby/library/syslog/shared/log.rb b/spec/ruby/library/syslog/shared/log.rb
index 12e4ea8366..9f9302b214 100644
--- a/spec/ruby/library/syslog/shared/log.rb
+++ b/spec/ruby/library/syslog/shared/log.rb
@@ -1,5 +1,5 @@
describe :syslog_log, shared: true do
- platform_is_not :windows, :darwin, :solaris, :aix, :android do
+ platform_is_not :windows, :darwin, :aix, :android do
before :each do
Syslog.opened?.should be_false
end
diff --git a/spec/ruby/library/tempfile/callback_spec.rb b/spec/ruby/library/tempfile/callback_spec.rb
deleted file mode 100644
index c0b1518326..0000000000
--- a/spec/ruby/library/tempfile/callback_spec.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-require_relative '../../spec_helper'
-require 'tempfile'
-
-describe "Tempfile.callback" do
- it "needs to be reviewed for spec completeness"
-end
diff --git a/spec/ruby/library/tempfile/create_spec.rb b/spec/ruby/library/tempfile/create_spec.rb
new file mode 100644
index 0000000000..74c48bf32a
--- /dev/null
+++ b/spec/ruby/library/tempfile/create_spec.rb
@@ -0,0 +1,176 @@
+require_relative '../../spec_helper'
+require 'tempfile'
+
+describe "Tempfile.create" do
+ after :each do
+ if @tempfile
+ @tempfile.close
+ File.unlink(@tempfile.path) if File.file?(@tempfile.path)
+ end
+ end
+
+ it "returns a new, open regular File instance placed in tmpdir" do
+ @tempfile = Tempfile.create
+ # Unlike Tempfile.open this returns a true File,
+ # but `.should be_an_instance_of(File)` would be true either way.
+ @tempfile.instance_of?(File).should be_true
+
+ @tempfile.should_not.closed?
+ File.file?(@tempfile.path).should be_true
+
+ @tempfile.path.should.start_with?(Dir.tmpdir)
+ @tempfile.path.should_not == "#{Dir.tmpdir}/"
+ end
+
+ it "returns file in w+ mode" do
+ @tempfile = Tempfile.create
+ @tempfile << "Test!\nMore test!"
+ @tempfile.rewind
+ @tempfile.read.should == "Test!\nMore test!"
+
+ # Not "a+" mode, which would write at the end of the file.
+ @tempfile.rewind
+ @tempfile.print "Trust"
+ @tempfile.rewind
+ @tempfile.read.should == "Trust\nMore test!"
+ end
+
+ platform_is_not :windows do
+ it "returns a private, readable and writable file" do
+ @tempfile = Tempfile.create
+ stat = @tempfile.stat
+ stat.should.readable?
+ stat.should.writable?
+ stat.should_not.executable?
+ stat.should_not.world_readable?
+ stat.should_not.world_writable?
+ end
+ end
+
+ platform_is :windows do
+ it "returns a public, readable and writable file" do
+ @tempfile = Tempfile.create
+ stat = @tempfile.stat
+ stat.should.readable?
+ stat.should.writable?
+ stat.should_not.executable?
+ stat.should.world_readable?
+ stat.should.world_writable?
+ end
+ end
+
+ context "when called with a block" do
+ it "returns the value of the block" do
+ value = Tempfile.create do |tempfile|
+ tempfile << "Test!"
+ "return"
+ end
+ value.should == "return"
+ end
+
+ it "closes and unlinks file after block execution" do
+ Tempfile.create do |tempfile|
+ @tempfile = tempfile
+ @tempfile.should_not.closed?
+ File.exist?(@tempfile.path).should be_true
+ end
+
+ @tempfile.should.closed?
+ File.exist?(@tempfile.path).should be_false
+ end
+ end
+
+ context "when called with a single positional argument" do
+ it "uses a String as a prefix for the filename" do
+ @tempfile = Tempfile.create("create_spec")
+ @tempfile.path.should.start_with?("#{Dir.tmpdir}/create_spec")
+ @tempfile.path.should_not == "#{Dir.tmpdir}/create_spec"
+ end
+
+ it "uses an array of one String as a prefix for the filename" do
+ @tempfile = Tempfile.create(["create_spec"])
+ @tempfile.path.should.start_with?("#{Dir.tmpdir}/create_spec")
+ @tempfile.path.should_not == "#{Dir.tmpdir}/create_spec"
+ end
+
+ it "uses an array of two Strings as a prefix and suffix for the filename" do
+ @tempfile = Tempfile.create(["create_spec", ".temp"])
+ @tempfile.path.should.start_with?("#{Dir.tmpdir}/create_spec")
+ @tempfile.path.should.end_with?(".temp")
+ end
+
+ it "ignores excessive array elements after the first two" do
+ @tempfile = Tempfile.create(["create_spec", ".temp", :".txt"])
+ @tempfile.path.should.start_with?("#{Dir.tmpdir}/create_spec")
+ @tempfile.path.should.end_with?(".temp")
+ end
+
+ it "raises ArgumentError if passed something else than a String or an array of Strings" do
+ -> { Tempfile.create(:create_spec) }.should raise_error(ArgumentError, "unexpected prefix: :create_spec")
+ -> { Tempfile.create([:create_spec]) }.should raise_error(ArgumentError, "unexpected prefix: :create_spec")
+ -> { Tempfile.create(["create_spec", :temp]) }.should raise_error(ArgumentError, "unexpected suffix: :temp")
+ end
+ end
+
+ context "when called with a second positional argument" do
+ it "uses it as a directory for the tempfile" do
+ @tempfile = Tempfile.create("create_spec", "./")
+ @tempfile.path.should.start_with?("./create_spec")
+ end
+
+ it "raises TypeError if argument can not be converted to a String" do
+ -> { Tempfile.create("create_spec", :temp) }.should raise_error(TypeError, "no implicit conversion of Symbol into String")
+ end
+ end
+
+ context "when called with a mode option" do
+ it "ORs it with the default mode, forcing it to be readable and writable" do
+ @tempfile = Tempfile.create(mode: File::RDONLY)
+ @tempfile.puts "test"
+ @tempfile.rewind
+ @tempfile.read.should == "test\n"
+ end
+
+ it "raises NoMethodError if passed a String mode" do
+ -> { Tempfile.create(mode: "wb") }.should raise_error(NoMethodError, /undefined method ['`]|' for .+String/)
+ end
+ end
+
+ ruby_version_is "3.4" do
+ context "when called with anonymous: true" do
+ it "returns an already unlinked File without a proper path" do
+ @tempfile = Tempfile.create(anonymous: true)
+ @tempfile.should_not.closed?
+ @tempfile.path.should == "#{Dir.tmpdir}/"
+ File.file?(@tempfile.path).should be_false
+ end
+
+ it "unlinks file before calling the block" do
+ Tempfile.create(anonymous: true) do |tempfile|
+ @tempfile = tempfile
+ @tempfile.should_not.closed?
+ @tempfile.path.should == "#{Dir.tmpdir}/"
+ File.file?(@tempfile.path).should be_false
+ end
+ @tempfile.should.closed?
+ end
+ end
+
+ context "when called with anonymous: false" do
+ it "returns a usual File with a path" do
+ @tempfile = Tempfile.create(anonymous: false)
+ @tempfile.should_not.closed?
+ @tempfile.path.should.start_with?(Dir.tmpdir)
+ File.file?(@tempfile.path).should be_true
+ end
+ end
+ end
+
+ context "when called with other options" do
+ it "passes them along to File.open" do
+ @tempfile = Tempfile.create(encoding: "IBM037:IBM037", binmode: true)
+ @tempfile.external_encoding.should == Encoding.find("IBM037")
+ @tempfile.binmode?.should be_true
+ end
+ end
+end
diff --git a/spec/ruby/library/time/iso8601_spec.rb b/spec/ruby/library/time/iso8601_spec.rb
index 4a9eb45613..ab35ab25d6 100644
--- a/spec/ruby/library/time/iso8601_spec.rb
+++ b/spec/ruby/library/time/iso8601_spec.rb
@@ -2,6 +2,6 @@ require_relative '../../spec_helper'
require_relative 'shared/xmlschema'
require 'time'
-describe "Time.xmlschema" do
- it_behaves_like :time_xmlschema, :iso8601
+describe "Time.iso8601" do
+ it_behaves_like :time_library_xmlschema, :iso8601
end
diff --git a/spec/ruby/library/time/shared/rfc2822.rb b/spec/ruby/library/time/shared/rfc2822.rb
index d99f1f76de..e460d655a6 100644
--- a/spec/ruby/library/time/shared/rfc2822.rb
+++ b/spec/ruby/library/time/shared/rfc2822.rb
@@ -1,33 +1,33 @@
describe :time_rfc2822, shared: true do
it "parses RFC-822 strings" do
t1 = (Time.utc(1976, 8, 26, 14, 30) + 4 * 3600)
- t2 = Time.rfc2822("26 Aug 76 14:30 EDT")
+ t2 = Time.send(@method, "26 Aug 76 14:30 EDT")
t1.should == t2
t3 = Time.utc(1976, 8, 27, 9, 32) + 7 * 3600
- t4 = Time.rfc2822("27 Aug 76 09:32 PDT")
+ t4 = Time.send(@method, "27 Aug 76 09:32 PDT")
t3.should == t4
end
it "parses RFC-2822 strings" do
t1 = Time.utc(1997, 11, 21, 9, 55, 6) + 6 * 3600
- t2 = Time.rfc2822("Fri, 21 Nov 1997 09:55:06 -0600")
+ t2 = Time.send(@method, "Fri, 21 Nov 1997 09:55:06 -0600")
t1.should == t2
t3 = Time.utc(2003, 7, 1, 10, 52, 37) - 2 * 3600
- t4 = Time.rfc2822("Tue, 1 Jul 2003 10:52:37 +0200")
+ t4 = Time.send(@method, "Tue, 1 Jul 2003 10:52:37 +0200")
t3.should == t4
t5 = Time.utc(1997, 11, 21, 10, 1, 10) + 6 * 3600
- t6 = Time.rfc2822("Fri, 21 Nov 1997 10:01:10 -0600")
+ t6 = Time.send(@method, "Fri, 21 Nov 1997 10:01:10 -0600")
t5.should == t6
t7 = Time.utc(1997, 11, 21, 11, 0, 0) + 6 * 3600
- t8 = Time.rfc2822("Fri, 21 Nov 1997 11:00:00 -0600")
+ t8 = Time.send(@method, "Fri, 21 Nov 1997 11:00:00 -0600")
t7.should == t8
t9 = Time.utc(1997, 11, 24, 14, 22, 1) + 8 * 3600
- t10 = Time.rfc2822("Mon, 24 Nov 1997 14:22:01 -0800")
+ t10 = Time.send(@method, "Mon, 24 Nov 1997 14:22:01 -0800")
t9.should == t10
begin
@@ -36,11 +36,11 @@ describe :time_rfc2822, shared: true do
# ignore
else
t11 = Time.utc(1969, 2, 13, 23, 32, 54) + 3 * 3600 + 30 * 60
- t12 = Time.rfc2822("Thu, 13 Feb 1969 23:32:54 -0330")
+ t12 = Time.send(@method, "Thu, 13 Feb 1969 23:32:54 -0330")
t11.should == t12
t13 = Time.utc(1969, 2, 13, 23, 32, 0) + 3 * 3600 + 30 * 60
- t14 = Time.rfc2822(" Thu,
+ t14 = Time.send(@method, " Thu,
13
Feb
1969
@@ -50,16 +50,16 @@ describe :time_rfc2822, shared: true do
end
t15 = Time.utc(1997, 11, 21, 9, 55, 6)
- t16 = Time.rfc2822("21 Nov 97 09:55:06 GMT")
+ t16 = Time.send(@method, "21 Nov 97 09:55:06 GMT")
t15.should == t16
t17 = Time.utc(1997, 11, 21, 9, 55, 6) + 6 * 3600
- t18 = Time.rfc2822("Fri, 21 Nov 1997 09 : 55 : 06 -0600")
+ t18 = Time.send(@method, "Fri, 21 Nov 1997 09 : 55 : 06 -0600")
t17.should == t18
-> {
# inner comment is not supported.
- Time.rfc2822("Fri, 21 Nov 1997 09(comment): 55 : 06 -0600")
+ Time.send(@method, "Fri, 21 Nov 1997 09(comment): 55 : 06 -0600")
}.should raise_error(ArgumentError)
end
end
diff --git a/spec/ruby/library/time/shared/xmlschema.rb b/spec/ruby/library/time/shared/xmlschema.rb
index 44d33cda7e..0002886ca5 100644
--- a/spec/ruby/library/time/shared/xmlschema.rb
+++ b/spec/ruby/library/time/shared/xmlschema.rb
@@ -1,24 +1,24 @@
-describe :time_xmlschema, shared: true do
+describe :time_library_xmlschema, shared: true do
it "parses ISO-8601 strings" do
t = Time.utc(1985, 4, 12, 23, 20, 50, 520000)
s = "1985-04-12T23:20:50.52Z"
- t.should == Time.xmlschema(s)
- #s.should == t.xmlschema(2)
+ t.should == Time.send(@method, s)
+ #s.should == t.send(@method, 2)
t = Time.utc(1996, 12, 20, 0, 39, 57)
s = "1996-12-19T16:39:57-08:00"
- t.should == Time.xmlschema(s)
+ t.should == Time.send(@method, s)
# There is no way to generate time string with arbitrary timezone.
s = "1996-12-20T00:39:57Z"
- t.should == Time.xmlschema(s)
- #assert_equal(s, t.xmlschema)
+ t.should == Time.send(@method, s)
+ #assert_equal(s, t.send(@method))
t = Time.utc(1990, 12, 31, 23, 59, 60)
s = "1990-12-31T23:59:60Z"
- t.should == Time.xmlschema(s)
+ t.should == Time.send(@method, s)
# leap second is representable only if timezone file has it.
s = "1990-12-31T15:59:60-08:00"
- t.should == Time.xmlschema(s)
+ t.should == Time.send(@method, s)
begin
Time.at(-1)
@@ -27,27 +27,27 @@ describe :time_xmlschema, shared: true do
else
t = Time.utc(1937, 1, 1, 11, 40, 27, 870000)
s = "1937-01-01T12:00:27.87+00:20"
- t.should == Time.xmlschema(s)
+ t.should == Time.send(@method, s)
end
# more
- # (Time.utc(1999, 5, 31, 13, 20, 0) + 5 * 3600).should == Time.xmlschema("1999-05-31T13:20:00-05:00")
- # (Time.local(2000, 1, 20, 12, 0, 0)).should == Time.xmlschema("2000-01-20T12:00:00")
- # (Time.utc(2000, 1, 20, 12, 0, 0)).should == Time.xmlschema("2000-01-20T12:00:00Z")
- # (Time.utc(2000, 1, 20, 12, 0, 0) - 12 * 3600).should == Time.xmlschema("2000-01-20T12:00:00+12:00")
- # (Time.utc(2000, 1, 20, 12, 0, 0) + 13 * 3600).should == Time.xmlschema("2000-01-20T12:00:00-13:00")
- # (Time.utc(2000, 3, 4, 23, 0, 0) - 3 * 3600).should == Time.xmlschema("2000-03-04T23:00:00+03:00")
- # (Time.utc(2000, 3, 4, 20, 0, 0)).should == Time.xmlschema("2000-03-04T20:00:00Z")
- # (Time.local(2000, 1, 15, 0, 0, 0)).should == Time.xmlschema("2000-01-15T00:00:00")
- # (Time.local(2000, 2, 15, 0, 0, 0)).should == Time.xmlschema("2000-02-15T00:00:00")
- # (Time.local(2000, 1, 15, 12, 0, 0)).should == Time.xmlschema("2000-01-15T12:00:00")
- # (Time.utc(2000, 1, 16, 12, 0, 0)).should == Time.xmlschema("2000-01-16T12:00:00Z")
- # (Time.local(2000, 1, 1, 12, 0, 0)).should == Time.xmlschema("2000-01-01T12:00:00")
- # (Time.utc(1999, 12, 31, 23, 0, 0)).should == Time.xmlschema("1999-12-31T23:00:00Z")
- # (Time.local(2000, 1, 16, 12, 0, 0)).should == Time.xmlschema("2000-01-16T12:00:00")
- # (Time.local(2000, 1, 16, 0, 0, 0)).should == Time.xmlschema("2000-01-16T00:00:00")
- # (Time.utc(2000, 1, 12, 12, 13, 14)).should == Time.xmlschema("2000-01-12T12:13:14Z")
- # (Time.utc(2001, 4, 17, 19, 23, 17, 300000)).should == Time.xmlschema("2001-04-17T19:23:17.3Z")
+ # (Time.utc(1999, 5, 31, 13, 20, 0) + 5 * 3600).should == Time.send(@method, "1999-05-31T13:20:00-05:00")
+ # (Time.local(2000, 1, 20, 12, 0, 0)).should == Time.send(@method, "2000-01-20T12:00:00")
+ # (Time.utc(2000, 1, 20, 12, 0, 0)).should == Time.send(@method, "2000-01-20T12:00:00Z")
+ # (Time.utc(2000, 1, 20, 12, 0, 0) - 12 * 3600).should == Time.send(@method, "2000-01-20T12:00:00+12:00")
+ # (Time.utc(2000, 1, 20, 12, 0, 0) + 13 * 3600).should == Time.send(@method, "2000-01-20T12:00:00-13:00")
+ # (Time.utc(2000, 3, 4, 23, 0, 0) - 3 * 3600).should == Time.send(@method, "2000-03-04T23:00:00+03:00")
+ # (Time.utc(2000, 3, 4, 20, 0, 0)).should == Time.send(@method, "2000-03-04T20:00:00Z")
+ # (Time.local(2000, 1, 15, 0, 0, 0)).should == Time.send(@method, "2000-01-15T00:00:00")
+ # (Time.local(2000, 2, 15, 0, 0, 0)).should == Time.send(@method, "2000-02-15T00:00:00")
+ # (Time.local(2000, 1, 15, 12, 0, 0)).should == Time.send(@method, "2000-01-15T12:00:00")
+ # (Time.utc(2000, 1, 16, 12, 0, 0)).should == Time.send(@method, "2000-01-16T12:00:00Z")
+ # (Time.local(2000, 1, 1, 12, 0, 0)).should == Time.send(@method, "2000-01-01T12:00:00")
+ # (Time.utc(1999, 12, 31, 23, 0, 0)).should == Time.send(@method, "1999-12-31T23:00:00Z")
+ # (Time.local(2000, 1, 16, 12, 0, 0)).should == Time.send(@method, "2000-01-16T12:00:00")
+ # (Time.local(2000, 1, 16, 0, 0, 0)).should == Time.send(@method, "2000-01-16T00:00:00")
+ # (Time.utc(2000, 1, 12, 12, 13, 14)).should == Time.send(@method, "2000-01-12T12:13:14Z")
+ # (Time.utc(2001, 4, 17, 19, 23, 17, 300000)).should == Time.send(@method, "2001-04-17T19:23:17.3Z")
end
end
diff --git a/spec/ruby/library/time/xmlschema_spec.rb b/spec/ruby/library/time/xmlschema_spec.rb
index 4279311199..ff3c864a02 100644
--- a/spec/ruby/library/time/xmlschema_spec.rb
+++ b/spec/ruby/library/time/xmlschema_spec.rb
@@ -3,5 +3,5 @@ require_relative 'shared/xmlschema'
require 'time'
describe "Time.xmlschema" do
- it_behaves_like :time_xmlschema, :xmlschema
+ it_behaves_like :time_library_xmlschema, :xmlschema
end
diff --git a/spec/ruby/library/timeout/timeout_spec.rb b/spec/ruby/library/timeout/timeout_spec.rb
index 584b38d8ec..e16bcaea6a 100644
--- a/spec/ruby/library/timeout/timeout_spec.rb
+++ b/spec/ruby/library/timeout/timeout_spec.rb
@@ -39,4 +39,12 @@ describe "Timeout.timeout" do
42
end.should == 42
end
+
+ ruby_version_is "3.4" do
+ it "raises an ArgumentError when provided with a negative duration" do
+ -> {
+ Timeout.timeout(-1)
+ }.should raise_error(ArgumentError, "Timeout sec must be a non-negative number")
+ end
+ end
end
diff --git a/spec/ruby/library/uri/generic/host_spec.rb b/spec/ruby/library/uri/generic/host_spec.rb
index 210124ef66..4a5a162512 100644
--- a/spec/ruby/library/uri/generic/host_spec.rb
+++ b/spec/ruby/library/uri/generic/host_spec.rb
@@ -2,11 +2,9 @@ require_relative '../../../spec_helper'
require 'uri'
describe "URI::Generic#host" do
- version_is URI::VERSION, "0.12" do #ruby_version_is "3.2" do
- # https://hackerone.com/reports/156615
- it "returns empty string when host is empty" do
- URI.parse('http:////foo.com').host.should == ''
- end
+ # https://hackerone.com/reports/156615
+ it "returns empty string when host is empty" do
+ URI.parse('http:////foo.com').host.should == ''
end
end
diff --git a/spec/ruby/library/uri/generic/to_s_spec.rb b/spec/ruby/library/uri/generic/to_s_spec.rb
index 8cebd374a1..c436ee3c03 100644
--- a/spec/ruby/library/uri/generic/to_s_spec.rb
+++ b/spec/ruby/library/uri/generic/to_s_spec.rb
@@ -2,10 +2,8 @@ require_relative '../../../spec_helper'
require 'uri'
describe "URI::Generic#to_s" do
- version_is URI::VERSION, "0.12" do #ruby_version_is "3.2" do
- # https://hackerone.com/reports/156615
- it "preserves / characters when host is empty" do
- URI('http:///foo.com').to_s.should == 'http:///foo.com'
- end
+ # https://hackerone.com/reports/156615
+ it "preserves / characters when host is empty" do
+ URI('http:///foo.com').to_s.should == 'http:///foo.com'
end
end
diff --git a/spec/ruby/library/uri/set_component_spec.rb b/spec/ruby/library/uri/set_component_spec.rb
index 642a5d6fcf..1d4165c535 100644
--- a/spec/ruby/library/uri/set_component_spec.rb
+++ b/spec/ruby/library/uri/set_component_spec.rb
@@ -6,25 +6,27 @@ describe "URI#select" do
it "conforms to the MatzRuby tests" do
uri = URI.parse('http://foo:bar@baz')
(uri.user = 'oof').should == 'oof'
- uri.to_s.should == 'http://oof:bar@baz'
- (uri.password = 'rab').should == 'rab'
- uri.to_s.should == 'http://oof:rab@baz'
- (uri.userinfo = 'foo').should == 'foo'
- uri.to_s.should == 'http://foo:rab@baz'
- (uri.userinfo = ['foo', 'bar']).should == ['foo', 'bar']
- uri.to_s.should == 'http://foo:bar@baz'
- (uri.userinfo = ['foo']).should == ['foo']
- uri.to_s.should == 'http://foo:bar@baz'
- (uri.host = 'zab').should == 'zab'
- uri.to_s.should == 'http://foo:bar@zab'
- (uri.port = 8080).should == 8080
- uri.to_s.should == 'http://foo:bar@zab:8080'
- (uri.path = '/').should == '/'
- uri.to_s.should == 'http://foo:bar@zab:8080/'
- (uri.query = 'a=1').should == 'a=1'
- uri.to_s.should == 'http://foo:bar@zab:8080/?a=1'
- (uri.fragment = 'b123').should == 'b123'
- uri.to_s.should == 'http://foo:bar@zab:8080/?a=1#b123'
+ version_is(URI::VERSION, "1.0.4") do
+ uri.to_s.should == 'http://oof@baz'
+ (uri.password = 'rab').should == 'rab'
+ uri.to_s.should == 'http://oof:rab@baz'
+ (uri.userinfo = 'foo').should == 'foo'
+ uri.to_s.should == 'http://foo@baz'
+ (uri.userinfo = ['foo', 'bar']).should == ['foo', 'bar']
+ uri.to_s.should == 'http://foo:bar@baz'
+ (uri.userinfo = ['foo']).should == ['foo']
+ uri.to_s.should == 'http://foo@baz'
+ (uri.host = 'zab').should == 'zab'
+ uri.to_s.should == 'http://zab'
+ (uri.port = 8080).should == 8080
+ uri.to_s.should == 'http://zab:8080'
+ (uri.path = '/').should == '/'
+ uri.to_s.should == 'http://zab:8080/'
+ (uri.query = 'a=1').should == 'a=1'
+ uri.to_s.should == 'http://zab:8080/?a=1'
+ (uri.fragment = 'b123').should == 'b123'
+ uri.to_s.should == 'http://zab:8080/?a=1#b123'
+ end
uri = URI.parse('http://example.com')
-> { uri.password = 'bar' }.should raise_error(URI::InvalidURIError)
diff --git a/spec/ruby/library/uri/shared/parse.rb b/spec/ruby/library/uri/shared/parse.rb
index 87e1ee933e..c5057b6c4b 100644
--- a/spec/ruby/library/uri/shared/parse.rb
+++ b/spec/ruby/library/uri/shared/parse.rb
@@ -192,8 +192,15 @@ describe :uri_parse, shared: true do
file.should be_kind_of(URI::Generic)
end
- it "raises errors on malformed URIs" do
- -> { @object.parse('http://a_b:80/') }.should raise_error(URI::InvalidURIError)
- -> { @object.parse('http://a_b/') }.should raise_error(URI::InvalidURIError)
+ if URI::DEFAULT_PARSER == URI::RFC2396_Parser
+ it "raises errors on malformed URIs" do
+ -> { @object.parse('http://a_b:80/') }.should raise_error(URI::InvalidURIError)
+ -> { @object.parse('http://a_b/') }.should raise_error(URI::InvalidURIError)
+ end
+ elsif URI::DEFAULT_PARSER == URI::RFC3986_Parser
+ it "does not raise errors on URIs contained underscore" do
+ -> { @object.parse('http://a_b:80/') }.should_not raise_error(URI::InvalidURIError)
+ -> { @object.parse('http://a_b/') }.should_not raise_error(URI::InvalidURIError)
+ end
end
end
diff --git a/spec/ruby/library/win32ole/fixtures/classes.rb b/spec/ruby/library/win32ole/fixtures/classes.rb
index f61cf6ba69..5a16fcca45 100644
--- a/spec/ruby/library/win32ole/fixtures/classes.rb
+++ b/spec/ruby/library/win32ole/fixtures/classes.rb
@@ -1,14 +1,25 @@
require 'win32ole'
+# win32ole deprecated constants like WIN32OLE_TYPELIB in Ruby 3.4
+# but only added the replacements like WIN32OLE::TypeLib in Ruby 3.4.
+# So we use the new-style constants in specs to avoid deprecation warnings
+# and we define the new-style constants as the old ones if they don't exist yet.
+WIN32OLE::TypeLib ||= WIN32OLE_TYPELIB
+WIN32OLE::RuntimeError ||= WIN32OLERuntimeError
+WIN32OLE::Method ||= WIN32OLE_METHOD
+WIN32OLE::Type ||= WIN32OLE_TYPE
+WIN32OLE::Event ||= WIN32OLE_EVENT
+WIN32OLE::Param ||= WIN32OLE_PARAM
+
module WIN32OLESpecs
- MSXML_AVAILABLE = WIN32OLE_TYPELIB.typelibs.any? { |t| t.name.start_with?('Microsoft XML') }
- SYSTEM_MONITOR_CONTROL_AVAILABLE = WIN32OLE_TYPELIB.typelibs.any? { |t| t.name.start_with?('System Monitor Control') }
+ MSXML_AVAILABLE = WIN32OLE::TypeLib.typelibs.any? { |t| t.name.start_with?('Microsoft XML') }
+ SYSTEM_MONITOR_CONTROL_AVAILABLE = WIN32OLE::TypeLib.typelibs.any? { |t| t.name.start_with?('System Monitor Control') }
def self.new_ole(name)
tries = 0
begin
WIN32OLE.new(name)
- rescue WIN32OLERuntimeError => e
+ rescue WIN32OLE::RuntimeError => e
if tries < 3
tries += 1
$stderr.puts "WIN32OLESpecs#new_ole retry (#{tries}): #{e.class}: #{e.message}"
diff --git a/spec/ruby/library/win32ole/win32ole/locale_spec.rb b/spec/ruby/library/win32ole/win32ole/locale_spec.rb
index 78ede4375a..89e84d8038 100644
--- a/spec/ruby/library/win32ole/win32ole/locale_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole/locale_spec.rb
@@ -13,14 +13,14 @@ platform_is :windows do
begin
begin
WIN32OLE.locale = 1041
- rescue WIN32OLERuntimeError
+ rescue WIN32OLE::RuntimeError
STDERR.puts("\n#{__FILE__}:#{__LINE__}:#{self.class.name}.test_s_locale_set is skipped(Japanese locale is not installed)")
return
end
WIN32OLE.locale.should == 1041
WIN32OLE.locale = WIN32OLE::LOCALE_SYSTEM_DEFAULT
- -> { WIN32OLE.locale = 111 }.should raise_error WIN32OLERuntimeError
+ -> { WIN32OLE.locale = 111 }.should raise_error WIN32OLE::RuntimeError
WIN32OLE.locale.should == WIN32OLE::LOCALE_SYSTEM_DEFAULT
ensure
WIN32OLE.locale.should == WIN32OLE::LOCALE_SYSTEM_DEFAULT
diff --git a/spec/ruby/library/win32ole/win32ole/new_spec.rb b/spec/ruby/library/win32ole/win32ole/new_spec.rb
index 7e91c2d3ea..b2a0a5da18 100644
--- a/spec/ruby/library/win32ole/win32ole/new_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole/new_spec.rb
@@ -17,8 +17,8 @@ platform_is :windows do
-> { WIN32OLESpecs.new_ole(42) }.should raise_error( TypeError )
end
- it "raises WIN32OLERuntimeError if invalid string is given" do
- -> { WIN32OLE.new('foo') }.should raise_error( WIN32OLERuntimeError )
+ it "raises WIN32OLE::RuntimeError if invalid string is given" do
+ -> { WIN32OLE.new('foo') }.should raise_error( WIN32OLE::RuntimeError )
end
end
diff --git a/spec/ruby/library/win32ole/win32ole/ole_func_methods_spec.rb b/spec/ruby/library/win32ole/win32ole/ole_func_methods_spec.rb
index 2bbe8c27d4..b846685518 100644
--- a/spec/ruby/library/win32ole/win32ole/ole_func_methods_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole/ole_func_methods_spec.rb
@@ -11,8 +11,8 @@ platform_is :windows do
-> { @dict.ole_func_methods(1) }.should raise_error ArgumentError
end
- it "returns an array of WIN32OLE_METHODs" do
- @dict.ole_func_methods.all? { |m| m.kind_of? WIN32OLE_METHOD }.should be_true
+ it "returns an array of WIN32OLE::Methods" do
+ @dict.ole_func_methods.all? { |m| m.kind_of? WIN32OLE::Method }.should be_true
end
it "contains a 'AddRef' method for Scripting Dictionary" do
diff --git a/spec/ruby/library/win32ole/win32ole/ole_get_methods_spec.rb b/spec/ruby/library/win32ole/win32ole/ole_get_methods_spec.rb
index c1d1970214..b6e7f960bb 100644
--- a/spec/ruby/library/win32ole/win32ole/ole_get_methods_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole/ole_get_methods_spec.rb
@@ -8,8 +8,8 @@ platform_is :windows do
@win32ole = WIN32OLESpecs.new_ole('Shell.Application')
end
- it "returns an array of WIN32OLE_METHOD objects" do
- @win32ole.ole_get_methods.all? {|m| m.kind_of? WIN32OLE_METHOD}.should be_true
+ it "returns an array of WIN32OLE::Method objects" do
+ @win32ole.ole_get_methods.all? {|m| m.kind_of? WIN32OLE::Method}.should be_true
end
end
diff --git a/spec/ruby/library/win32ole/win32ole/ole_methods_spec.rb b/spec/ruby/library/win32ole/win32ole/ole_methods_spec.rb
index fe161ce9f0..92c4363f78 100644
--- a/spec/ruby/library/win32ole/win32ole/ole_methods_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole/ole_methods_spec.rb
@@ -11,8 +11,8 @@ platform_is :windows do
-> { @dict.ole_methods(1) }.should raise_error ArgumentError
end
- it "returns an array of WIN32OLE_METHODs" do
- @dict.ole_methods.all? { |m| m.kind_of? WIN32OLE_METHOD }.should be_true
+ it "returns an array of WIN32OLE::Methods" do
+ @dict.ole_methods.all? { |m| m.kind_of? WIN32OLE::Method }.should be_true
end
it "contains a 'AddRef' method for Scripting Dictionary" do
diff --git a/spec/ruby/library/win32ole/win32ole/ole_obj_help_spec.rb b/spec/ruby/library/win32ole/win32ole/ole_obj_help_spec.rb
index afcf16a051..f298f19dba 100644
--- a/spec/ruby/library/win32ole/win32ole/ole_obj_help_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole/ole_obj_help_spec.rb
@@ -12,8 +12,8 @@ platform_is :windows do
-> { @dict.ole_obj_help(1) }.should raise_error ArgumentError
end
- it "returns an instance of WIN32OLE_TYPE" do
- @dict.ole_obj_help.kind_of?(WIN32OLE_TYPE).should be_true
+ it "returns an instance of WIN32OLE::Type" do
+ @dict.ole_obj_help.kind_of?(WIN32OLE::Type).should be_true
end
end
end
diff --git a/spec/ruby/library/win32ole/win32ole/ole_put_methods_spec.rb b/spec/ruby/library/win32ole/win32ole/ole_put_methods_spec.rb
index c091c83c95..2b46ae47de 100644
--- a/spec/ruby/library/win32ole/win32ole/ole_put_methods_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole/ole_put_methods_spec.rb
@@ -11,8 +11,8 @@ platform_is :windows do
-> { @dict.ole_put_methods(1) }.should raise_error ArgumentError
end
- it "returns an array of WIN32OLE_METHODs" do
- @dict.ole_put_methods.all? { |m| m.kind_of? WIN32OLE_METHOD }.should be_true
+ it "returns an array of WIN32OLE::Methods" do
+ @dict.ole_put_methods.all? { |m| m.kind_of? WIN32OLE::Method }.should be_true
end
it "contains a 'Key' method for Scripting Dictionary" do
diff --git a/spec/ruby/library/win32ole/win32ole/shared/ole_method.rb b/spec/ruby/library/win32ole/win32ole/shared/ole_method.rb
index f1fd8713a4..bae424a604 100644
--- a/spec/ruby/library/win32ole/win32ole/shared/ole_method.rb
+++ b/spec/ruby/library/win32ole/win32ole/shared/ole_method.rb
@@ -10,9 +10,9 @@ platform_is :windows do
-> { @dict.send(@method) }.should raise_error ArgumentError
end
- it "returns the WIN32OLE_METHOD 'Add' if given 'Add'" do
+ it "returns the WIN32OLE::Method 'Add' if given 'Add'" do
result = @dict.send(@method, "Add")
- result.kind_of?(WIN32OLE_METHOD).should be_true
+ result.kind_of?(WIN32OLE::Method).should be_true
result.name.should == 'Add'
end
end
diff --git a/spec/ruby/library/win32ole/win32ole_event/new_spec.rb b/spec/ruby/library/win32ole/win32ole_event/new_spec.rb
index 94fabb1e3b..4efd4c3e0f 100644
--- a/spec/ruby/library/win32ole/win32ole_event/new_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_event/new_spec.rb
@@ -3,7 +3,7 @@ platform_is :windows do
require_relative '../fixtures/classes'
guard -> { WIN32OLESpecs::MSXML_AVAILABLE } do
- describe "WIN32OLE_EVENT.new" do
+ describe "WIN32OLE::Event.new" do
before :all do
@xml_dom = WIN32OLESpecs.new_ole('MSXML.DOMDocument')
end
@@ -13,21 +13,21 @@ platform_is :windows do
end
it "raises TypeError given invalid argument" do
- -> { WIN32OLE_EVENT.new "A" }.should raise_error TypeError
+ -> { WIN32OLE::Event.new "A" }.should raise_error TypeError
end
it "raises RuntimeError if event does not exist" do
- -> { WIN32OLE_EVENT.new(@xml_dom, 'A') }.should raise_error RuntimeError
+ -> { WIN32OLE::Event.new(@xml_dom, 'A') }.should raise_error RuntimeError
end
it "raises RuntimeError if OLE object has no events" do
dict = WIN32OLESpecs.new_ole('Scripting.Dictionary')
- -> { WIN32OLE_EVENT.new(dict) }.should raise_error RuntimeError
+ -> { WIN32OLE::Event.new(dict) }.should raise_error RuntimeError
end
- it "creates WIN32OLE_EVENT object" do
- ev = WIN32OLE_EVENT.new(@xml_dom)
- ev.should be_kind_of WIN32OLE_EVENT
+ it "creates WIN32OLE::Event object" do
+ ev = WIN32OLE::Event.new(@xml_dom)
+ ev.should be_kind_of WIN32OLE::Event
end
end
end
diff --git a/spec/ruby/library/win32ole/win32ole_event/on_event_spec.rb b/spec/ruby/library/win32ole/win32ole_event/on_event_spec.rb
index 0957bdd2d4..acc7d2d6b6 100644
--- a/spec/ruby/library/win32ole/win32ole_event/on_event_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_event/on_event_spec.rb
@@ -15,7 +15,7 @@ platform_is :windows do
@event_spec_alt = "spec_alt"
end
- describe "WIN32OLE_EVENT#on_event" do
+ describe "WIN32OLE::Event#on_event" do
before :all do
@fn_xml = File.absolute_path "../fixtures/event.xml", __dir__
end
@@ -23,7 +23,7 @@ platform_is :windows do
before :each do
@xml_dom = WIN32OLESpecs.new_ole 'MSXML.DOMDocument'
@xml_dom.async = true
- @ev = WIN32OLE_EVENT.new @xml_dom
+ @ev = WIN32OLE::Event.new @xml_dom
@event_global = ''
@event_specific = ''
@event_spec_alt = ''
@@ -37,21 +37,21 @@ platform_is :windows do
it "sets global event handler properly, and the handler is invoked by event loop" do
@ev.on_event { |*args| handler_global(*args) }
@xml_dom.loadXML "<program><name>Ruby</name><version>trunk</version></program>"
- WIN32OLE_EVENT.message_loop
+ WIN32OLE::Event.message_loop
@event_global.should =~ /onreadystatechange/
end
it "accepts a String argument and the handler is invoked by event loop" do
@ev.on_event("onreadystatechange") { |*args| @event = 'foo' }
@xml_dom.loadXML "<program><name>Ruby</name><version>trunk</version></program>"
- WIN32OLE_EVENT.message_loop
+ WIN32OLE::Event.message_loop
@event.should =~ /foo/
end
it "accepts a Symbol argument and the handler is invoked by event loop" do
@ev.on_event(:onreadystatechange) { |*args| @event = 'bar' }
@xml_dom.loadXML "<program><name>Ruby</name><version>trunk</version></program>"
- WIN32OLE_EVENT.message_loop
+ WIN32OLE::Event.message_loop
@event.should =~ /bar/
end
@@ -60,7 +60,7 @@ platform_is :windows do
@ev.on_event("onreadystatechange") { |*args| handler_specific(*args) }
@ev.on_event("onreadystatechange") { |*args| handler_spec_alt(*args) }
@xml_dom.load @fn_xml
- WIN32OLE_EVENT.message_loop
+ WIN32OLE::Event.message_loop
@event_global.should == 'ondataavailable'
@event_global.should_not =~ /onreadystatechange/
@event_specific.should == ''
diff --git a/spec/ruby/library/win32ole/win32ole_method/dispid_spec.rb b/spec/ruby/library/win32ole/win32ole_method/dispid_spec.rb
index ece71df0d4..e5f55f2d38 100644
--- a/spec/ruby/library/win32ole/win32ole_method/dispid_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_method/dispid_spec.rb
@@ -2,10 +2,10 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_METHOD#dispid" do
+ describe "WIN32OLE::Method#dispid" do
before :each do
- ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
- @m = WIN32OLE_METHOD.new(ole_type, "namespace")
+ ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
+ @m = WIN32OLE::Method.new(ole_type, "namespace")
end
it "raises ArgumentError if argument is given" do
diff --git a/spec/ruby/library/win32ole/win32ole_method/event_interface_spec.rb b/spec/ruby/library/win32ole/win32ole_method/event_interface_spec.rb
index 78634d2fde..bea47348ee 100644
--- a/spec/ruby/library/win32ole/win32ole_method/event_interface_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_method/event_interface_spec.rb
@@ -3,12 +3,12 @@ platform_is :windows do
require_relative '../fixtures/classes'
guard -> { WIN32OLESpecs::SYSTEM_MONITOR_CONTROL_AVAILABLE } do
- describe "WIN32OLE_METHOD#event_interface" do
+ describe "WIN32OLE::Method#event_interface" do
before :each do
- ole_type = WIN32OLE_TYPE.new("System Monitor Control", "SystemMonitor")
- @on_dbl_click_method = WIN32OLE_METHOD.new(ole_type, "OnDblClick")
- ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
- @namespace_method = WIN32OLE_METHOD.new(ole_type, "namespace")
+ ole_type = WIN32OLE::Type.new("System Monitor Control", "SystemMonitor")
+ @on_dbl_click_method = WIN32OLE::Method.new(ole_type, "OnDblClick")
+ ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
+ @namespace_method = WIN32OLE::Method.new(ole_type, "namespace")
end
it "raises ArgumentError if argument is given" do
diff --git a/spec/ruby/library/win32ole/win32ole_method/event_spec.rb b/spec/ruby/library/win32ole/win32ole_method/event_spec.rb
index 9b642a010c..5a94cf5ce6 100644
--- a/spec/ruby/library/win32ole/win32ole_method/event_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_method/event_spec.rb
@@ -3,10 +3,10 @@ platform_is :windows do
require_relative '../fixtures/classes'
guard -> { WIN32OLESpecs::SYSTEM_MONITOR_CONTROL_AVAILABLE } do
- describe "WIN32OLE_METHOD#event?" do
+ describe "WIN32OLE::Method#event?" do
before :each do
- ole_type = WIN32OLE_TYPE.new("System Monitor Control", "SystemMonitor")
- @on_dbl_click_method = WIN32OLE_METHOD.new(ole_type, "OnDblClick")
+ ole_type = WIN32OLE::Type.new("System Monitor Control", "SystemMonitor")
+ @on_dbl_click_method = WIN32OLE::Method.new(ole_type, "OnDblClick")
end
it "raises ArgumentError if argument is given" do
diff --git a/spec/ruby/library/win32ole/win32ole_method/helpcontext_spec.rb b/spec/ruby/library/win32ole/win32ole_method/helpcontext_spec.rb
index d1c5ee3be2..83f34b9c10 100644
--- a/spec/ruby/library/win32ole/win32ole_method/helpcontext_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_method/helpcontext_spec.rb
@@ -2,12 +2,12 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_METHOD#helpcontext" do
+ describe "WIN32OLE::Method#helpcontext" do
before :each do
- ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "FileSystemObject")
- @get_file_version = WIN32OLE_METHOD.new(ole_type, "GetFileVersion")
- ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "File")
- @m_file_name = WIN32OLE_METHOD.new(ole_type, "name")
+ ole_type = WIN32OLE::Type.new("Microsoft Scripting Runtime", "FileSystemObject")
+ @get_file_version = WIN32OLE::Method.new(ole_type, "GetFileVersion")
+ ole_type = WIN32OLE::Type.new("Microsoft Scripting Runtime", "File")
+ @m_file_name = WIN32OLE::Method.new(ole_type, "name")
end
it "raises ArgumentError if argument is given" do
diff --git a/spec/ruby/library/win32ole/win32ole_method/helpfile_spec.rb b/spec/ruby/library/win32ole/win32ole_method/helpfile_spec.rb
index 59dad9244c..9cf9d63d3b 100644
--- a/spec/ruby/library/win32ole/win32ole_method/helpfile_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_method/helpfile_spec.rb
@@ -2,10 +2,10 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_METHOD#helpfile" do
+ describe "WIN32OLE::Method#helpfile" do
before :each do
- ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "File")
- @m_file_name = WIN32OLE_METHOD.new(ole_type, "name")
+ ole_type = WIN32OLE::Type.new("Microsoft Scripting Runtime", "File")
+ @m_file_name = WIN32OLE::Method.new(ole_type, "name")
end
it "raises ArgumentError if argument is given" do
diff --git a/spec/ruby/library/win32ole/win32ole_method/helpstring_spec.rb b/spec/ruby/library/win32ole/win32ole_method/helpstring_spec.rb
index b2f24ba151..5ae4a5e090 100644
--- a/spec/ruby/library/win32ole/win32ole_method/helpstring_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_method/helpstring_spec.rb
@@ -2,10 +2,10 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_METHOD#helpstring" do
+ describe "WIN32OLE::Method#helpstring" do
before :each do
- ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "File")
- @m_file_name = WIN32OLE_METHOD.new(ole_type, "name")
+ ole_type = WIN32OLE::Type.new("Microsoft Scripting Runtime", "File")
+ @m_file_name = WIN32OLE::Method.new(ole_type, "name")
end
it "raises ArgumentError if argument is given" do
diff --git a/spec/ruby/library/win32ole/win32ole_method/invkind_spec.rb b/spec/ruby/library/win32ole/win32ole_method/invkind_spec.rb
index d7fedf0d36..06acbb58a5 100644
--- a/spec/ruby/library/win32ole/win32ole_method/invkind_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_method/invkind_spec.rb
@@ -2,10 +2,10 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_METHOD#invkind" do
+ describe "WIN32OLE::Method#invkind" do
before :each do
- ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "File")
- @m_file_name = WIN32OLE_METHOD.new(ole_type, "name")
+ ole_type = WIN32OLE::Type.new("Microsoft Scripting Runtime", "File")
+ @m_file_name = WIN32OLE::Method.new(ole_type, "name")
end
it "raises ArgumentError if argument is given" do
diff --git a/spec/ruby/library/win32ole/win32ole_method/invoke_kind_spec.rb b/spec/ruby/library/win32ole/win32ole_method/invoke_kind_spec.rb
index d5536fd17b..0e97ec3305 100644
--- a/spec/ruby/library/win32ole/win32ole_method/invoke_kind_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_method/invoke_kind_spec.rb
@@ -2,10 +2,10 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_METHOD#invoke_kind" do
+ describe "WIN32OLE::Method#invoke_kind" do
before :each do
- ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "File")
- @m_file_name = WIN32OLE_METHOD.new(ole_type, "name")
+ ole_type = WIN32OLE::Type.new("Microsoft Scripting Runtime", "File")
+ @m_file_name = WIN32OLE::Method.new(ole_type, "name")
end
it "raises ArgumentError if argument is given" do
diff --git a/spec/ruby/library/win32ole/win32ole_method/name_spec.rb b/spec/ruby/library/win32ole/win32ole_method/name_spec.rb
index 477b820f4d..6e2e233a62 100644
--- a/spec/ruby/library/win32ole/win32ole_method/name_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_method/name_spec.rb
@@ -4,7 +4,7 @@ require_relative 'shared/name'
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_METHOD#name" do
+ describe "WIN32OLE::Method#name" do
it_behaves_like :win32ole_method_name, :name
end
diff --git a/spec/ruby/library/win32ole/win32ole_method/new_spec.rb b/spec/ruby/library/win32ole/win32ole_method/new_spec.rb
index 4e427421b9..46186ae566 100644
--- a/spec/ruby/library/win32ole/win32ole_method/new_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_method/new_spec.rb
@@ -2,31 +2,31 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_METHOD.new" do
+ describe "WIN32OLE::Method.new" do
before :each do
- @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
end
it "raises TypeError when given non-strings" do
- -> { WIN32OLE_METHOD.new(1, 2) }.should raise_error TypeError
+ -> { WIN32OLE::Method.new(1, 2) }.should raise_error TypeError
end
it "raises ArgumentError if only 1 argument is given" do
- -> { WIN32OLE_METHOD.new("hello") }.should raise_error ArgumentError
- -> { WIN32OLE_METHOD.new(@ole_type) }.should raise_error ArgumentError
+ -> { WIN32OLE::Method.new("hello") }.should raise_error ArgumentError
+ -> { WIN32OLE::Method.new(@ole_type) }.should raise_error ArgumentError
end
- it "returns a valid WIN32OLE_METHOD object" do
- WIN32OLE_METHOD.new(@ole_type, "Open").should be_kind_of WIN32OLE_METHOD
- WIN32OLE_METHOD.new(@ole_type, "open").should be_kind_of WIN32OLE_METHOD
+ it "returns a valid WIN32OLE::Method object" do
+ WIN32OLE::Method.new(@ole_type, "Open").should be_kind_of WIN32OLE::Method
+ WIN32OLE::Method.new(@ole_type, "open").should be_kind_of WIN32OLE::Method
end
- it "raises WIN32OLERuntimeError if the method does not exist" do
- -> { WIN32OLE_METHOD.new(@ole_type, "NonexistentMethod") }.should raise_error WIN32OLERuntimeError
+ it "raises WIN32OLE::RuntimeError if the method does not exist" do
+ -> { WIN32OLE::Method.new(@ole_type, "NonexistentMethod") }.should raise_error WIN32OLE::RuntimeError
end
it "raises TypeError if second argument is not a String" do
- -> { WIN32OLE_METHOD.new(@ole_type, 5) }.should raise_error TypeError
+ -> { WIN32OLE::Method.new(@ole_type, 5) }.should raise_error TypeError
end
end
diff --git a/spec/ruby/library/win32ole/win32ole_method/offset_vtbl_spec.rb b/spec/ruby/library/win32ole/win32ole_method/offset_vtbl_spec.rb
index b3da9a8303..3c80cb3c2a 100644
--- a/spec/ruby/library/win32ole/win32ole_method/offset_vtbl_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_method/offset_vtbl_spec.rb
@@ -2,10 +2,10 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_METHOD#offset_vtbl" do
+ describe "WIN32OLE::Method#offset_vtbl" do
before :each do
- ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "File")
- @m_file_name = WIN32OLE_METHOD.new(ole_type, "name")
+ ole_type = WIN32OLE::Type.new("Microsoft Scripting Runtime", "File")
+ @m_file_name = WIN32OLE::Method.new(ole_type, "name")
end
it "raises ArgumentError if argument is given" do
diff --git a/spec/ruby/library/win32ole/win32ole_method/params_spec.rb b/spec/ruby/library/win32ole/win32ole_method/params_spec.rb
index 09fb0eb5ac..0b1b4595a3 100644
--- a/spec/ruby/library/win32ole/win32ole_method/params_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_method/params_spec.rb
@@ -2,12 +2,12 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_METHOD#params" do
+ describe "WIN32OLE::Method#params" do
before :each do
- ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "File")
- @m_file_name = WIN32OLE_METHOD.new(ole_type, "name")
- ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
- @m_browse_for_folder = WIN32OLE_METHOD.new(ole_type, "BrowseForFolder")
+ ole_type = WIN32OLE::Type.new("Microsoft Scripting Runtime", "File")
+ @m_file_name = WIN32OLE::Method.new(ole_type, "name")
+ ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
+ @m_browse_for_folder = WIN32OLE::Method.new(ole_type, "BrowseForFolder")
end
it "raises ArgumentError if argument is given" do
@@ -19,8 +19,8 @@ platform_is :windows do
@m_file_name.params.should be_empty
end
- it "returns 4-element array of WIN32OLE_PARAM for Shell's 'BrowseForFolder' method" do
- @m_browse_for_folder.params.all? { |p| p.kind_of? WIN32OLE_PARAM }.should be_true
+ it "returns 4-element array of WIN32OLE::Param for Shell's 'BrowseForFolder' method" do
+ @m_browse_for_folder.params.all? { |p| p.kind_of? WIN32OLE::Param }.should be_true
@m_browse_for_folder.params.size == 4
end
diff --git a/spec/ruby/library/win32ole/win32ole_method/return_type_detail_spec.rb b/spec/ruby/library/win32ole/win32ole_method/return_type_detail_spec.rb
index 582a5951d5..c3725bfef2 100644
--- a/spec/ruby/library/win32ole/win32ole_method/return_type_detail_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_method/return_type_detail_spec.rb
@@ -2,10 +2,10 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_METHOD#return_type_detail" do
+ describe "WIN32OLE::Method#return_type_detail" do
before :each do
- ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
- @m_browse_for_folder = WIN32OLE_METHOD.new(ole_type, "BrowseForFolder")
+ ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
+ @m_browse_for_folder = WIN32OLE::Method.new(ole_type, "BrowseForFolder")
end
it "raises ArgumentError if argument is given" do
diff --git a/spec/ruby/library/win32ole/win32ole_method/return_type_spec.rb b/spec/ruby/library/win32ole/win32ole_method/return_type_spec.rb
index dd8add402d..9e5a1eb1df 100644
--- a/spec/ruby/library/win32ole/win32ole_method/return_type_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_method/return_type_spec.rb
@@ -2,10 +2,10 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_METHOD#return_type" do
+ describe "WIN32OLE::Method#return_type" do
before :each do
- ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "File")
- @m_file_name = WIN32OLE_METHOD.new(ole_type, "name")
+ ole_type = WIN32OLE::Type.new("Microsoft Scripting Runtime", "File")
+ @m_file_name = WIN32OLE::Method.new(ole_type, "name")
end
it "raises ArgumentError if argument is given" do
diff --git a/spec/ruby/library/win32ole/win32ole_method/return_vtype_spec.rb b/spec/ruby/library/win32ole/win32ole_method/return_vtype_spec.rb
index 3fca3d54ed..34fd135b8c 100644
--- a/spec/ruby/library/win32ole/win32ole_method/return_vtype_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_method/return_vtype_spec.rb
@@ -2,10 +2,10 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_METHOD#return_vtype" do
+ describe "WIN32OLE::Method#return_vtype" do
before :each do
- ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
- @m_browse_for_folder = WIN32OLE_METHOD.new(ole_type, "BrowseForFolder")
+ ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
+ @m_browse_for_folder = WIN32OLE::Method.new(ole_type, "BrowseForFolder")
end
it "raises ArgumentError if argument is given" do
diff --git a/spec/ruby/library/win32ole/win32ole_method/shared/name.rb b/spec/ruby/library/win32ole/win32ole_method/shared/name.rb
index ddaff4011b..7e2197ca5a 100644
--- a/spec/ruby/library/win32ole/win32ole_method/shared/name.rb
+++ b/spec/ruby/library/win32ole/win32ole_method/shared/name.rb
@@ -3,8 +3,8 @@ platform_is :windows do
describe :win32ole_method_name, shared: true do
before :each do
- ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "File")
- @m_file_name = WIN32OLE_METHOD.new(ole_type, "name")
+ ole_type = WIN32OLE::Type.new("Microsoft Scripting Runtime", "File")
+ @m_file_name = WIN32OLE::Method.new(ole_type, "name")
end
it "raises ArgumentError if argument is given" do
diff --git a/spec/ruby/library/win32ole/win32ole_method/size_opt_params_spec.rb b/spec/ruby/library/win32ole/win32ole_method/size_opt_params_spec.rb
index fe9facb53a..38cb21ccef 100644
--- a/spec/ruby/library/win32ole/win32ole_method/size_opt_params_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_method/size_opt_params_spec.rb
@@ -2,10 +2,10 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_METHOD#size_opt_params" do
+ describe "WIN32OLE::Method#size_opt_params" do
before :each do
- ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
- @m_browse_for_folder = WIN32OLE_METHOD.new(ole_type, "BrowseForFolder")
+ ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
+ @m_browse_for_folder = WIN32OLE::Method.new(ole_type, "BrowseForFolder")
end
it "raises ArgumentError if argument is given" do
diff --git a/spec/ruby/library/win32ole/win32ole_method/size_params_spec.rb b/spec/ruby/library/win32ole/win32ole_method/size_params_spec.rb
index 8ea6e61e7d..5d0a35a0ef 100644
--- a/spec/ruby/library/win32ole/win32ole_method/size_params_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_method/size_params_spec.rb
@@ -2,10 +2,10 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_METHOD#size_params" do
+ describe "WIN32OLE::Method#size_params" do
before :each do
- ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
- @m_browse_for_folder = WIN32OLE_METHOD.new(ole_type, "BrowseForFolder")
+ ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
+ @m_browse_for_folder = WIN32OLE::Method.new(ole_type, "BrowseForFolder")
end
it "raises ArgumentError if argument is given" do
diff --git a/spec/ruby/library/win32ole/win32ole_method/to_s_spec.rb b/spec/ruby/library/win32ole/win32ole_method/to_s_spec.rb
index 11107a77fc..cdcc4525b1 100644
--- a/spec/ruby/library/win32ole/win32ole_method/to_s_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_method/to_s_spec.rb
@@ -4,7 +4,7 @@ require_relative 'shared/name'
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_METHOD#name" do
+ describe "WIN32OLE::Method#name" do
it_behaves_like :win32ole_method_name, :to_s
end
diff --git a/spec/ruby/library/win32ole/win32ole_method/visible_spec.rb b/spec/ruby/library/win32ole/win32ole_method/visible_spec.rb
index d1a50523fc..2f02c15c8b 100644
--- a/spec/ruby/library/win32ole/win32ole_method/visible_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_method/visible_spec.rb
@@ -2,10 +2,10 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_METHOD#visible?" do
+ describe "WIN32OLE::Method#visible?" do
before :each do
- ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
- @m_browse_for_folder = WIN32OLE_METHOD.new(ole_type, "BrowseForFolder")
+ ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
+ @m_browse_for_folder = WIN32OLE::Method.new(ole_type, "BrowseForFolder")
end
it "raises ArgumentError if argument is given" do
diff --git a/spec/ruby/library/win32ole/win32ole_param/default_spec.rb b/spec/ruby/library/win32ole/win32ole_param/default_spec.rb
index 44bd3d7fd3..a37b03866d 100644
--- a/spec/ruby/library/win32ole/win32ole_param/default_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_param/default_spec.rb
@@ -2,14 +2,14 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_PARAM#default" do
+ describe "WIN32OLE::Param#default" do
before :each do
- ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
- m_browse_for_folder = WIN32OLE_METHOD.new(ole_type, "BrowseForFolder")
+ ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
+ m_browse_for_folder = WIN32OLE::Method.new(ole_type, "BrowseForFolder")
@params = m_browse_for_folder.params
- ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "FileSystemObject")
- m_copyfile = WIN32OLE_METHOD.new(ole_type, "CopyFile")
+ ole_type = WIN32OLE::Type.new("Microsoft Scripting Runtime", "FileSystemObject")
+ m_copyfile = WIN32OLE::Method.new(ole_type, "CopyFile")
@param_overwritefiles = m_copyfile.params[2]
end
@@ -17,7 +17,7 @@ platform_is :windows do
-> { @params[0].default(1) }.should raise_error ArgumentError
end
- it "returns nil for each of WIN32OLE_PARAM for Shell's 'BrowseForFolder' method" do
+ it "returns nil for each of WIN32OLE::Param for Shell's 'BrowseForFolder' method" do
@params.each do |p|
p.default.should be_nil
end
diff --git a/spec/ruby/library/win32ole/win32ole_param/input_spec.rb b/spec/ruby/library/win32ole/win32ole_param/input_spec.rb
index e9134b1df8..d7e27d7739 100644
--- a/spec/ruby/library/win32ole/win32ole_param/input_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_param/input_spec.rb
@@ -2,10 +2,10 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_PARAM#input?" do
+ describe "WIN32OLE::Param#input?" do
before :each do
- ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "FileSystemObject")
- m_copyfile = WIN32OLE_METHOD.new(ole_type, "CopyFile")
+ ole_type = WIN32OLE::Type.new("Microsoft Scripting Runtime", "FileSystemObject")
+ m_copyfile = WIN32OLE::Method.new(ole_type, "CopyFile")
@param_overwritefiles = m_copyfile.params[2]
end
diff --git a/spec/ruby/library/win32ole/win32ole_param/name_spec.rb b/spec/ruby/library/win32ole/win32ole_param/name_spec.rb
index 67a8955ba4..2c3474ffb3 100644
--- a/spec/ruby/library/win32ole/win32ole_param/name_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_param/name_spec.rb
@@ -4,7 +4,7 @@ require_relative 'shared/name'
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_PARAM#name" do
+ describe "WIN32OLE::Param#name" do
it_behaves_like :win32ole_param_name, :name
end
diff --git a/spec/ruby/library/win32ole/win32ole_param/ole_type_detail_spec.rb b/spec/ruby/library/win32ole/win32ole_param/ole_type_detail_spec.rb
index f05455e3f1..e3379dbf3e 100644
--- a/spec/ruby/library/win32ole/win32ole_param/ole_type_detail_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_param/ole_type_detail_spec.rb
@@ -2,10 +2,10 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_PARAM#ole_type_detail" do
+ describe "WIN32OLE::Param#ole_type_detail" do
before :each do
- ole_type_detail = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "FileSystemObject")
- m_copyfile = WIN32OLE_METHOD.new(ole_type_detail, "CopyFile")
+ ole_type_detail = WIN32OLE::Type.new("Microsoft Scripting Runtime", "FileSystemObject")
+ m_copyfile = WIN32OLE::Method.new(ole_type_detail, "CopyFile")
@param_overwritefiles = m_copyfile.params[2]
end
diff --git a/spec/ruby/library/win32ole/win32ole_param/ole_type_spec.rb b/spec/ruby/library/win32ole/win32ole_param/ole_type_spec.rb
index 1467130e03..a7b6666807 100644
--- a/spec/ruby/library/win32ole/win32ole_param/ole_type_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_param/ole_type_spec.rb
@@ -2,10 +2,10 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_PARAM#ole_type" do
+ describe "WIN32OLE::Param#ole_type" do
before :each do
- ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "FileSystemObject")
- m_copyfile = WIN32OLE_METHOD.new(ole_type, "CopyFile")
+ ole_type = WIN32OLE::Type.new("Microsoft Scripting Runtime", "FileSystemObject")
+ m_copyfile = WIN32OLE::Method.new(ole_type, "CopyFile")
@param_overwritefiles = m_copyfile.params[2]
end
diff --git a/spec/ruby/library/win32ole/win32ole_param/optional_spec.rb b/spec/ruby/library/win32ole/win32ole_param/optional_spec.rb
index b39ee41179..50e95fc77f 100644
--- a/spec/ruby/library/win32ole/win32ole_param/optional_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_param/optional_spec.rb
@@ -2,10 +2,10 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_PARAM#optional?" do
+ describe "WIN32OLE::Param#optional?" do
before :each do
- ole_type_detail = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "FileSystemObject")
- m_copyfile = WIN32OLE_METHOD.new(ole_type_detail, "CopyFile")
+ ole_type_detail = WIN32OLE::Type.new("Microsoft Scripting Runtime", "FileSystemObject")
+ m_copyfile = WIN32OLE::Method.new(ole_type_detail, "CopyFile")
@param_overwritefiles = m_copyfile.params[2]
end
diff --git a/spec/ruby/library/win32ole/win32ole_param/retval_spec.rb b/spec/ruby/library/win32ole/win32ole_param/retval_spec.rb
index dd613dd29a..fa4a09ea0c 100644
--- a/spec/ruby/library/win32ole/win32ole_param/retval_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_param/retval_spec.rb
@@ -2,10 +2,10 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_PARAM#retval?" do
+ describe "WIN32OLE::Param#retval?" do
before :each do
- ole_type_detail = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "FileSystemObject")
- m_copyfile = WIN32OLE_METHOD.new(ole_type_detail, "CopyFile")
+ ole_type_detail = WIN32OLE::Type.new("Microsoft Scripting Runtime", "FileSystemObject")
+ m_copyfile = WIN32OLE::Method.new(ole_type_detail, "CopyFile")
@param_overwritefiles = m_copyfile.params[2]
end
diff --git a/spec/ruby/library/win32ole/win32ole_param/shared/name.rb b/spec/ruby/library/win32ole/win32ole_param/shared/name.rb
index 043bc32856..56ff24ddc8 100644
--- a/spec/ruby/library/win32ole/win32ole_param/shared/name.rb
+++ b/spec/ruby/library/win32ole/win32ole_param/shared/name.rb
@@ -3,8 +3,8 @@ platform_is :windows do
describe :win32ole_param_name, shared: true do
before :each do
- ole_type_detail = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "FileSystemObject")
- m_copyfile = WIN32OLE_METHOD.new(ole_type_detail, "CopyFile")
+ ole_type_detail = WIN32OLE::Type.new("Microsoft Scripting Runtime", "FileSystemObject")
+ m_copyfile = WIN32OLE::Method.new(ole_type_detail, "CopyFile")
@param_overwritefiles = m_copyfile.params[2]
end
diff --git a/spec/ruby/library/win32ole/win32ole_param/to_s_spec.rb b/spec/ruby/library/win32ole/win32ole_param/to_s_spec.rb
index e9153a2eb2..c59f426692 100644
--- a/spec/ruby/library/win32ole/win32ole_param/to_s_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_param/to_s_spec.rb
@@ -4,7 +4,7 @@ require_relative 'shared/name'
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_PARAM#to_s" do
+ describe "WIN32OLE::Param#to_s" do
it_behaves_like :win32ole_param_name, :to_s
end
diff --git a/spec/ruby/library/win32ole/win32ole_type/guid_spec.rb b/spec/ruby/library/win32ole/win32ole_type/guid_spec.rb
index abdf8d34b9..e574a945ad 100644
--- a/spec/ruby/library/win32ole/win32ole_type/guid_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_type/guid_spec.rb
@@ -2,9 +2,9 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_TYPE#guid for Shell Controls" do
+ describe "WIN32OLE::Type#guid for Shell Controls" do
before :each do
- @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
end
after :each do
diff --git a/spec/ruby/library/win32ole/win32ole_type/helpcontext_spec.rb b/spec/ruby/library/win32ole/win32ole_type/helpcontext_spec.rb
index eee23abc56..35911fec52 100644
--- a/spec/ruby/library/win32ole/win32ole_type/helpcontext_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_type/helpcontext_spec.rb
@@ -2,9 +2,9 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_TYPE#helpcontext for Shell Controls" do
+ describe "WIN32OLE::Type#helpcontext for Shell Controls" do
before :each do
- @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
end
after :each do
diff --git a/spec/ruby/library/win32ole/win32ole_type/helpfile_spec.rb b/spec/ruby/library/win32ole/win32ole_type/helpfile_spec.rb
index 3a0a9ead94..7bd61a1c40 100644
--- a/spec/ruby/library/win32ole/win32ole_type/helpfile_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_type/helpfile_spec.rb
@@ -2,9 +2,9 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_TYPE#helpfile for Shell Controls" do
+ describe "WIN32OLE::Type#helpfile for Shell Controls" do
before :each do
- @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
end
after :each do
diff --git a/spec/ruby/library/win32ole/win32ole_type/helpstring_spec.rb b/spec/ruby/library/win32ole/win32ole_type/helpstring_spec.rb
index 9ab0004668..940475b25e 100644
--- a/spec/ruby/library/win32ole/win32ole_type/helpstring_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_type/helpstring_spec.rb
@@ -2,9 +2,9 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_TYPE#helpstring for Shell Controls" do
+ describe "WIN32OLE::Type#helpstring for Shell Controls" do
before :each do
- @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
end
after :each do
diff --git a/spec/ruby/library/win32ole/win32ole_type/major_version_spec.rb b/spec/ruby/library/win32ole/win32ole_type/major_version_spec.rb
index 7d2731f778..598e5bcef8 100644
--- a/spec/ruby/library/win32ole/win32ole_type/major_version_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_type/major_version_spec.rb
@@ -2,9 +2,9 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_TYPE#major_version for Shell Controls" do
+ describe "WIN32OLE::Type#major_version for Shell Controls" do
before :each do
- @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
end
after :each do
diff --git a/spec/ruby/library/win32ole/win32ole_type/minor_version_spec.rb b/spec/ruby/library/win32ole/win32ole_type/minor_version_spec.rb
index 3904e78d42..59cfb94012 100644
--- a/spec/ruby/library/win32ole/win32ole_type/minor_version_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_type/minor_version_spec.rb
@@ -2,9 +2,9 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_TYPE#minor_version for Shell Controls" do
+ describe "WIN32OLE::Type#minor_version for Shell Controls" do
before :each do
- @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
end
after :each do
diff --git a/spec/ruby/library/win32ole/win32ole_type/name_spec.rb b/spec/ruby/library/win32ole/win32ole_type/name_spec.rb
index d76998d7dc..4cc3426872 100644
--- a/spec/ruby/library/win32ole/win32ole_type/name_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_type/name_spec.rb
@@ -4,7 +4,7 @@ require_relative 'shared/name'
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_TYPE#name" do
+ describe "WIN32OLE::Type#name" do
it_behaves_like :win32ole_type_name, :name
end
diff --git a/spec/ruby/library/win32ole/win32ole_type/new_spec.rb b/spec/ruby/library/win32ole/win32ole_type/new_spec.rb
index cc691ffa67..185a235940 100644
--- a/spec/ruby/library/win32ole/win32ole_type/new_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_type/new_spec.rb
@@ -2,39 +2,39 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_TYPE.new" do
+ describe "WIN32OLE::Type.new" do
it "raises ArgumentError with no argument" do
- -> { WIN32OLE_TYPE.new }.should raise_error ArgumentError
+ -> { WIN32OLE::Type.new }.should raise_error ArgumentError
end
it "raises ArgumentError with invalid string" do
- -> { WIN32OLE_TYPE.new("foo") }.should raise_error ArgumentError
+ -> { WIN32OLE::Type.new("foo") }.should raise_error ArgumentError
end
it "raises TypeError if second argument is not a String" do
- -> { WIN32OLE_TYPE.new(1,2) }.should raise_error TypeError
+ -> { WIN32OLE::Type.new(1,2) }.should raise_error TypeError
-> {
- WIN32OLE_TYPE.new('Microsoft Shell Controls And Automation',2)
+ WIN32OLE::Type.new('Microsoft Shell Controls And Automation',2)
}.should raise_error TypeError
end
- it "raise WIN32OLERuntimeError if OLE object specified is not found" do
+ it "raise WIN32OLE::RuntimeError if OLE object specified is not found" do
-> {
- WIN32OLE_TYPE.new('Microsoft Shell Controls And Automation','foo')
- }.should raise_error WIN32OLERuntimeError
+ WIN32OLE::Type.new('Microsoft Shell Controls And Automation','foo')
+ }.should raise_error WIN32OLE::RuntimeError
-> {
- WIN32OLE_TYPE.new('Microsoft Shell Controls And Automation','Application')
- }.should raise_error WIN32OLERuntimeError
+ WIN32OLE::Type.new('Microsoft Shell Controls And Automation','Application')
+ }.should raise_error WIN32OLE::RuntimeError
end
- it "creates WIN32OLE_TYPE object from name and valid type" do
- ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
- ole_type.should be_kind_of WIN32OLE_TYPE
+ it "creates WIN32OLE::Type object from name and valid type" do
+ ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
+ ole_type.should be_kind_of WIN32OLE::Type
end
- it "creates WIN32OLE_TYPE object from CLSID and valid type" do
- ole_type2 = WIN32OLE_TYPE.new("{13709620-C279-11CE-A49E-444553540000}", "Shell")
- ole_type2.should be_kind_of WIN32OLE_TYPE
+ it "creates WIN32OLE::Type object from CLSID and valid type" do
+ ole_type2 = WIN32OLE::Type.new("{13709620-C279-11CE-A49E-444553540000}", "Shell")
+ ole_type2.should be_kind_of WIN32OLE::Type
end
end
diff --git a/spec/ruby/library/win32ole/win32ole_type/ole_classes_spec.rb b/spec/ruby/library/win32ole/win32ole_type/ole_classes_spec.rb
index a3a1d4ac58..ed14e37a95 100644
--- a/spec/ruby/library/win32ole/win32ole_type/ole_classes_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_type/ole_classes_spec.rb
@@ -2,9 +2,9 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_TYPE.ole_classes for Shell Controls" do
+ describe "WIN32OLE::Type.ole_classes for Shell Controls" do
before :each do
- @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
end
after :each do
@@ -12,7 +12,7 @@ platform_is :windows do
end
it "returns array of WIN32OLE_TYPEs" do
- WIN32OLE_TYPE.ole_classes("Microsoft Shell Controls And Automation").all? {|e| e.kind_of? WIN32OLE_TYPE }.should be_true
+ WIN32OLE::Type.ole_classes("Microsoft Shell Controls And Automation").all? {|e| e.kind_of? WIN32OLE::Type }.should be_true
end
end
diff --git a/spec/ruby/library/win32ole/win32ole_type/ole_methods_spec.rb b/spec/ruby/library/win32ole/win32ole_type/ole_methods_spec.rb
index 3b99b97a61..0c031abaa6 100644
--- a/spec/ruby/library/win32ole/win32ole_type/ole_methods_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_type/ole_methods_spec.rb
@@ -2,9 +2,9 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_TYPE#ole_methods for Shell Controls" do
+ describe "WIN32OLE::Type#ole_methods for Shell Controls" do
before :each do
- @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
end
after :each do
@@ -12,7 +12,7 @@ platform_is :windows do
end
it "returns an Integer" do
- @ole_type.ole_methods.all? { |m| m.kind_of? WIN32OLE_METHOD }.should be_true
+ @ole_type.ole_methods.all? { |m| m.kind_of? WIN32OLE::Method }.should be_true
end
end
diff --git a/spec/ruby/library/win32ole/win32ole_type/ole_type_spec.rb b/spec/ruby/library/win32ole/win32ole_type/ole_type_spec.rb
index 24292b1c4f..49c1902f8c 100644
--- a/spec/ruby/library/win32ole/win32ole_type/ole_type_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_type/ole_type_spec.rb
@@ -2,9 +2,9 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_TYPE#ole_type for Shell Controls" do
+ describe "WIN32OLE::Type#ole_type for Shell Controls" do
before :each do
- @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
end
after :each do
diff --git a/spec/ruby/library/win32ole/win32ole_type/progid_spec.rb b/spec/ruby/library/win32ole/win32ole_type/progid_spec.rb
index 340fdb34e8..9a700426d9 100644
--- a/spec/ruby/library/win32ole/win32ole_type/progid_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_type/progid_spec.rb
@@ -2,9 +2,9 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_TYPE#progid for Shell Controls" do
+ describe "WIN32OLE::Type#progid for Shell Controls" do
before :each do
- @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
end
after :each do
diff --git a/spec/ruby/library/win32ole/win32ole_type/progids_spec.rb b/spec/ruby/library/win32ole/win32ole_type/progids_spec.rb
index 793535b48d..b1b57960cd 100644
--- a/spec/ruby/library/win32ole/win32ole_type/progids_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_type/progids_spec.rb
@@ -2,13 +2,13 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_TYPE.progids" do
+ describe "WIN32OLE::Type.progids" do
it "raises ArgumentError if an argument is given" do
- -> { WIN32OLE_TYPE.progids(1) }.should raise_error ArgumentError
+ -> { WIN32OLE::Type.progids(1) }.should raise_error ArgumentError
end
it "returns an array containing 'Shell.Explorer'" do
- WIN32OLE_TYPE.progids().include?('Shell.Explorer').should be_true
+ WIN32OLE::Type.progids().include?('Shell.Explorer').should be_true
end
end
diff --git a/spec/ruby/library/win32ole/win32ole_type/shared/name.rb b/spec/ruby/library/win32ole/win32ole_type/shared/name.rb
index 6f37446b23..efae7aeec1 100644
--- a/spec/ruby/library/win32ole/win32ole_type/shared/name.rb
+++ b/spec/ruby/library/win32ole/win32ole_type/shared/name.rb
@@ -3,7 +3,7 @@ platform_is :windows do
describe :win32ole_type_name, shared: true do
before :each do
- @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
+ @ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
end
it "raises ArgumentError if argument is given" do
diff --git a/spec/ruby/library/win32ole/win32ole_type/src_type_spec.rb b/spec/ruby/library/win32ole/win32ole_type/src_type_spec.rb
index 3f89fe702a..3c7651cc1f 100644
--- a/spec/ruby/library/win32ole/win32ole_type/src_type_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_type/src_type_spec.rb
@@ -2,9 +2,9 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_TYPE#src_type for Shell Controls" do
+ describe "WIN32OLE::Type#src_type for Shell Controls" do
before :each do
- @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
end
after :each do
diff --git a/spec/ruby/library/win32ole/win32ole_type/to_s_spec.rb b/spec/ruby/library/win32ole/win32ole_type/to_s_spec.rb
index 9f086a5a35..03a0344fdb 100644
--- a/spec/ruby/library/win32ole/win32ole_type/to_s_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_type/to_s_spec.rb
@@ -4,7 +4,7 @@ require_relative 'shared/name'
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_TYPE#to_s" do
+ describe "WIN32OLE::Type#to_s" do
it_behaves_like :win32ole_type_name, :to_s
end
diff --git a/spec/ruby/library/win32ole/win32ole_type/typekind_spec.rb b/spec/ruby/library/win32ole/win32ole_type/typekind_spec.rb
index 391d505e01..8b62f3e2eb 100644
--- a/spec/ruby/library/win32ole/win32ole_type/typekind_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_type/typekind_spec.rb
@@ -2,9 +2,9 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_TYPE#typekind for Shell Controls" do
+ describe "WIN32OLE::Type#typekind for Shell Controls" do
before :each do
- @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
end
after :each do
diff --git a/spec/ruby/library/win32ole/win32ole_type/typelibs_spec.rb b/spec/ruby/library/win32ole/win32ole_type/typelibs_spec.rb
index a487208caa..71d7cf00f7 100644
--- a/spec/ruby/library/win32ole/win32ole_type/typelibs_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_type/typelibs_spec.rb
@@ -2,9 +2,9 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_TYPE.typelibs for Shell Controls" do
+ describe "WIN32OLE::Type.typelibs for Shell Controls" do
before :each do
- @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
end
after :each do
@@ -12,11 +12,11 @@ platform_is :windows do
end
it "raises ArgumentError if any argument is give" do
- -> { WIN32OLE_TYPE.typelibs(1) }.should raise_error ArgumentError
+ -> { WIN32OLE::Type.typelibs(1) }.should raise_error ArgumentError
end
it "returns array of type libraries" do
- WIN32OLE_TYPE.typelibs().include?("Microsoft Shell Controls And Automation").should be_true
+ WIN32OLE::Type.typelibs().include?("Microsoft Shell Controls And Automation").should be_true
end
end
diff --git a/spec/ruby/library/win32ole/win32ole_type/variables_spec.rb b/spec/ruby/library/win32ole/win32ole_type/variables_spec.rb
index 7f61b8af95..b1a407523c 100644
--- a/spec/ruby/library/win32ole/win32ole_type/variables_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_type/variables_spec.rb
@@ -2,9 +2,9 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_TYPE#variables for Shell Controls" do
+ describe "WIN32OLE::Type#variables for Shell Controls" do
before :each do
- @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
end
after :each do
diff --git a/spec/ruby/library/win32ole/win32ole_type/visible_spec.rb b/spec/ruby/library/win32ole/win32ole_type/visible_spec.rb
index 99e34edcdd..05c54c8838 100644
--- a/spec/ruby/library/win32ole/win32ole_type/visible_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_type/visible_spec.rb
@@ -2,9 +2,9 @@ require_relative "../../../spec_helper"
platform_is :windows do
require 'win32ole'
- describe "WIN32OLE_TYPE#visible? for Shell Controls" do
+ describe "WIN32OLE::Type#visible? for Shell Controls" do
before :each do
- @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
end
after :each do
diff --git a/spec/ruby/library/win32ole/win32ole_variable/ole_type_detail_spec.rb b/spec/ruby/library/win32ole/win32ole_variable/ole_type_detail_spec.rb
index 7a9c791494..89576ceedc 100644
--- a/spec/ruby/library/win32ole/win32ole_variable/ole_type_detail_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_variable/ole_type_detail_spec.rb
@@ -6,7 +6,7 @@ platform_is :windows do
# not sure how WIN32OLE_VARIABLE objects are supposed to be generated
# WIN32OLE_VARIABLE.new even seg faults in some cases
before :each do
- ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
+ ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
@var = ole_type.variables[0]
end
diff --git a/spec/ruby/library/win32ole/win32ole_variable/ole_type_spec.rb b/spec/ruby/library/win32ole/win32ole_variable/ole_type_spec.rb
index 03a9aa4c74..441011f1e7 100644
--- a/spec/ruby/library/win32ole/win32ole_variable/ole_type_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_variable/ole_type_spec.rb
@@ -6,7 +6,7 @@ platform_is :windows do
# not sure how WIN32OLE_VARIABLE objects are supposed to be generated
# WIN32OLE_VARIABLE.new even seg faults in some cases
before :each do
- ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
+ ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
@var = ole_type.variables[0]
end
diff --git a/spec/ruby/library/win32ole/win32ole_variable/shared/name.rb b/spec/ruby/library/win32ole/win32ole_variable/shared/name.rb
index 033e830fac..d02942ce0a 100644
--- a/spec/ruby/library/win32ole/win32ole_variable/shared/name.rb
+++ b/spec/ruby/library/win32ole/win32ole_variable/shared/name.rb
@@ -5,7 +5,7 @@ platform_is :windows do
# not sure how WIN32OLE_VARIABLE objects are supposed to be generated
# WIN32OLE_VARIABLE.new even seg faults in some cases
before :each do
- ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
+ ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
@var = ole_type.variables[0]
end
diff --git a/spec/ruby/library/win32ole/win32ole_variable/value_spec.rb b/spec/ruby/library/win32ole/win32ole_variable/value_spec.rb
index b7849793c5..d26273ebed 100644
--- a/spec/ruby/library/win32ole/win32ole_variable/value_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_variable/value_spec.rb
@@ -6,7 +6,7 @@ platform_is :windows do
# not sure how WIN32OLE_VARIABLE objects are supposed to be generated
# WIN32OLE_VARIABLE.new even seg faults in some cases
before :each do
- ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
+ ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
@var = ole_type.variables[0]
end
diff --git a/spec/ruby/library/win32ole/win32ole_variable/variable_kind_spec.rb b/spec/ruby/library/win32ole/win32ole_variable/variable_kind_spec.rb
index 7a79d32ddc..17bc47160a 100644
--- a/spec/ruby/library/win32ole/win32ole_variable/variable_kind_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_variable/variable_kind_spec.rb
@@ -6,7 +6,7 @@ platform_is :windows do
# not sure how WIN32OLE_VARIABLE objects are supposed to be generated
# WIN32OLE_VARIABLE.new even seg faults in some cases
before :each do
- ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
+ ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
@var = ole_type.variables[0]
end
diff --git a/spec/ruby/library/win32ole/win32ole_variable/varkind_spec.rb b/spec/ruby/library/win32ole/win32ole_variable/varkind_spec.rb
index 9d7b8238c8..c5f8164509 100644
--- a/spec/ruby/library/win32ole/win32ole_variable/varkind_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_variable/varkind_spec.rb
@@ -7,7 +7,7 @@ platform_is :windows do
# not sure how WIN32OLE_VARIABLE objects are supposed to be generated
# WIN32OLE_VARIABLE.new even seg faults in some cases
before :each do
- ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
+ ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
@var = ole_type.variables[0]
end
diff --git a/spec/ruby/library/win32ole/win32ole_variable/visible_spec.rb b/spec/ruby/library/win32ole/win32ole_variable/visible_spec.rb
index 60252e8139..ba53a81de0 100644
--- a/spec/ruby/library/win32ole/win32ole_variable/visible_spec.rb
+++ b/spec/ruby/library/win32ole/win32ole_variable/visible_spec.rb
@@ -6,7 +6,7 @@ platform_is :windows do
# not sure how WIN32OLE_VARIABLE objects are supposed to be generated
# WIN32OLE_VARIABLE.new even seg faults in some cases
before :each do
- ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
+ ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
@var = ole_type.variables[0]
end
diff --git a/spec/ruby/library/yaml/dump_spec.rb b/spec/ruby/library/yaml/dump_spec.rb
index ea94b2f856..97b665d6a5 100644
--- a/spec/ruby/library/yaml/dump_spec.rb
+++ b/spec/ruby/library/yaml/dump_spec.rb
@@ -39,7 +39,11 @@ describe "YAML.dump" do
end
it "dumps an OpenStruct" do
- require "ostruct"
+ begin
+ require "ostruct"
+ rescue LoadError
+ skip "OpenStruct is not available"
+ end
os = OpenStruct.new("age" => 20, "name" => "John")
yaml_dump = YAML.dump(os)
diff --git a/spec/ruby/library/yaml/shared/load.rb b/spec/ruby/library/yaml/shared/load.rb
index bd55332fe5..b8bb605b0a 100644
--- a/spec/ruby/library/yaml/shared/load.rb
+++ b/spec/ruby/library/yaml/shared/load.rb
@@ -123,7 +123,11 @@ describe :yaml_load_unsafe, shared: true do
end
it "loads an OpenStruct" do
- require "ostruct"
+ begin
+ require "ostruct"
+ rescue LoadError
+ skip "OpenStruct is not available"
+ end
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
diff --git a/spec/ruby/library/yaml/to_yaml_spec.rb b/spec/ruby/library/yaml/to_yaml_spec.rb
index 547009c942..08c5451416 100644
--- a/spec/ruby/library/yaml/to_yaml_spec.rb
+++ b/spec/ruby/library/yaml/to_yaml_spec.rb
@@ -65,6 +65,8 @@ describe "Object#to_yaml" do
it "returns the YAML representation of a Struct object" do
Person = Struct.new(:name, :gender)
Person.new("Jane", "female").to_yaml.should match_yaml("--- !ruby/struct:Person\nname: Jane\ngender: female\n")
+ ensure
+ Object.send(:remove_const, :Person)
end
it "returns the YAML representation of an unnamed Struct object" do
diff --git a/spec/ruby/library/zlib/gzipreader/each_char_spec.rb b/spec/ruby/library/zlib/gzipreader/each_char_spec.rb
new file mode 100644
index 0000000000..de6396da7e
--- /dev/null
+++ b/spec/ruby/library/zlib/gzipreader/each_char_spec.rb
@@ -0,0 +1,51 @@
+require_relative '../../../spec_helper'
+require 'stringio'
+require 'zlib'
+
+describe "Zlib::GzipReader#each_char" do
+
+ before :each do
+ @data = '12345abcde'
+ @zip = [31, 139, 8, 0, 44, 220, 209, 71, 0, 3, 51, 52, 50, 54, 49, 77,
+ 76, 74, 78, 73, 5, 0, 157, 5, 0, 36, 10, 0, 0, 0].pack('C*')
+
+ @io = StringIO.new @zip
+ ScratchPad.clear
+ end
+
+ it "calls the given block for each char in the stream, passing the char as an argument" do
+ gz = Zlib::GzipReader.new @io
+
+ ScratchPad.record []
+ gz.each_char { |b| ScratchPad << b }
+
+ ScratchPad.recorded.should == ["1", "2", "3", "4", "5", "a", "b", "c", "d", "e"]
+ end
+
+ it "returns an enumerator, which yields each char in the stream, when no block is passed" do
+ gz = Zlib::GzipReader.new @io
+ enum = gz.each_char
+
+ ScratchPad.record []
+ while true
+ begin
+ ScratchPad << enum.next
+ rescue StopIteration
+ break
+ end
+ end
+
+ ScratchPad.recorded.should == ["1", "2", "3", "4", "5", "a", "b", "c", "d", "e"]
+ end
+
+ it "increments position before calling the block" do
+ gz = Zlib::GzipReader.new @io
+
+ i = 1
+ gz.each_char do |ignore|
+ gz.pos.should == i
+ i += 1
+ end
+ end
+
+end
diff --git a/spec/ruby/library/zlib/inflate/set_dictionary_spec.rb b/spec/ruby/library/zlib/inflate/set_dictionary_spec.rb
index 251cec44bb..375ee3c765 100644
--- a/spec/ruby/library/zlib/inflate/set_dictionary_spec.rb
+++ b/spec/ruby/library/zlib/inflate/set_dictionary_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative '../../../spec_helper'
require 'zlib'
diff --git a/spec/ruby/optional/capi/array_spec.rb b/spec/ruby/optional/capi/array_spec.rb
index 9c35017e21..7e87859856 100644
--- a/spec/ruby/optional/capi/array_spec.rb
+++ b/spec/ruby/optional/capi/array_spec.rb
@@ -343,37 +343,39 @@ describe "C-API Array function" do
end
end
- describe "rb_iterate" do
- it "calls an callback function as a block passed to an method" do
- s = [1,2,3,4]
- s2 = @s.rb_iterate(s)
+ ruby_version_is ""..."4.0" do
+ describe "rb_iterate" 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.should == s
+ s2.should == s
- # Make sure they're different objects
- s2.equal?(s).should be_false
- end
+ # Make sure they're different objects
+ s2.equal?(s).should be_false
+ end
- it "calls a function with the other function available as a block" do
- h = {a: 1, b: 2}
+ 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]
- end
+ @s.rb_iterate_each_pair(h).sort.should == [1,2]
+ end
- it "calls a function which can yield into the original block" do
- s2 = []
+ it "calls a function which can yield into the original block" do
+ s2 = []
- o = Object.new
- def o.each
- yield 1
- yield 2
- yield 3
- yield 4
- end
+ o = Object.new
+ def o.each
+ yield 1
+ yield 2
+ yield 3
+ yield 4
+ end
- @s.rb_iterate_then_yield(o) { |x| s2 << x }
+ @s.rb_iterate_then_yield(o) { |x| s2 << x }
- s2.should == [1,2,3,4]
+ s2.should == [1,2,3,4]
+ end
end
end
diff --git a/spec/ruby/optional/capi/bignum_spec.rb b/spec/ruby/optional/capi/bignum_spec.rb
index cde929af28..179f053eec 100644
--- a/spec/ruby/optional/capi/bignum_spec.rb
+++ b/spec/ruby/optional/capi/bignum_spec.rb
@@ -7,21 +7,23 @@ def ensure_bignum(n)
n
end
-full_range_longs = (fixnum_max == 2**(0.size * 8 - 1) - 1)
+full_range_longs = (fixnum_max == max_long)
+max_ulong = begin
+ require 'rbconfig/sizeof'
+ RbConfig::LIMITS['ULONG_MAX']
+rescue LoadError
+ nil
+end
+# If the system doesn't offer ULONG_MAX, assume 2's complement and derive it
+# from LONG_MAX.
+max_ulong ||= 2 * (max_long + 1) - 1
describe "CApiBignumSpecs" do
before :each do
@s = CApiBignumSpecs.new
-
- if full_range_longs
- @max_long = 2**(0.size * 8 - 1) - 1
- @min_long = -@max_long - 1
- @max_ulong = ensure_bignum(2**(0.size * 8) - 1)
- else
- @max_long = ensure_bignum(2**(0.size * 8 - 1) - 1)
- @min_long = ensure_bignum(-@max_long - 1)
- @max_ulong = ensure_bignum(2**(0.size * 8) - 1)
- end
+ @max_long = max_long
+ @min_long = min_long
+ @max_ulong = ensure_bignum(max_ulong)
end
describe "rb_big2long" do
@@ -123,7 +125,7 @@ describe "CApiBignumSpecs" do
val.should == @max_ulong
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
it "packs max_ulong into 2 ulongs to allow sign bit" do
val = @s.rb_big_pack_length(@max_ulong)
val.should == 2
diff --git a/spec/ruby/optional/capi/binding_spec.rb b/spec/ruby/optional/capi/binding_spec.rb
index 2165705457..5d0ef2efb8 100644
--- a/spec/ruby/optional/capi/binding_spec.rb
+++ b/spec/ruby/optional/capi/binding_spec.rb
@@ -8,21 +8,9 @@ describe "CApiBindingSpecs" do
end
describe "Kernel#binding" do
- ruby_version_is '3.2' do
- it "raises when called from C" do
- foo = 14
- -> { @b.get_binding }.should raise_error(RuntimeError)
- end
- end
-
- ruby_version_is ''...'3.2' 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
+ it "raises when called from C" do
+ foo = 14
+ -> { @b.get_binding }.should raise_error(RuntimeError)
end
end
end
diff --git a/spec/ruby/optional/capi/class_spec.rb b/spec/ruby/optional/capi/class_spec.rb
index a231245ebe..7abb5d4ed9 100644
--- a/spec/ruby/optional/capi/class_spec.rb
+++ b/spec/ruby/optional/capi/class_spec.rb
@@ -365,6 +365,8 @@ describe "C-API Class function" do
"ClassUnder6",
Class.new)
}.should raise_error(TypeError)
+ ensure
+ CApiClassSpecs.send(:remove_const, :ClassUnder6)
end
it "defines a class for an existing Autoload" do
diff --git a/spec/ruby/optional/capi/data_spec.rb b/spec/ruby/optional/capi/data_spec.rb
index 18c769332e..d000eba6e3 100644
--- a/spec/ruby/optional/capi/data_spec.rb
+++ b/spec/ruby/optional/capi/data_spec.rb
@@ -1,52 +1,53 @@
require_relative 'spec_helper'
+ruby_version_is ""..."3.4" do
+ load_extension("data")
-load_extension("data")
-
-describe "CApiAllocSpecs (a class with an alloc func defined)" do
- it "calls the alloc func" do
- @s = CApiAllocSpecs.new
- @s.wrapped_data.should == 42 # not defined in initialize
- end
-end
-
-describe "CApiWrappedStruct" do
- before :each do
- @s = CApiWrappedStructSpecs.new
- end
-
- it "wraps with Data_Wrap_Struct and Data_Get_Struct returns data" do
- a = @s.wrap_struct(1024)
- @s.get_struct(a).should == 1024
+ describe "CApiAllocSpecs (a class with an alloc func defined)" do
+ it "calls the alloc func" do
+ @s = CApiAllocSpecs.new
+ @s.wrapped_data.should == 42 # not defined in initialize
+ end
end
- describe "RDATA()" do
- it "returns the struct data" do
- a = @s.wrap_struct(1024)
- @s.get_struct_rdata(a).should == 1024
+ describe "CApiWrappedStruct" do
+ before :each do
+ @s = CApiWrappedStructSpecs.new
end
- it "allows changing the wrapped struct" do
+ it "wraps with Data_Wrap_Struct and Data_Get_Struct returns data" do
a = @s.wrap_struct(1024)
- @s.change_struct(a, 100)
- @s.get_struct(a).should == 100
+ @s.get_struct(a).should == 1024
end
- it "raises a TypeError if the object does not wrap a struct" do
- -> { @s.get_struct(Object.new) }.should raise_error(TypeError)
+ describe "RDATA()" do
+ it "returns the struct data" do
+ a = @s.wrap_struct(1024)
+ @s.get_struct_rdata(a).should == 1024
+ end
+
+ it "allows changing the wrapped struct" do
+ a = @s.wrap_struct(1024)
+ @s.change_struct(a, 100)
+ @s.get_struct(a).should == 100
+ end
+
+ it "raises a TypeError if the object does not wrap a struct" do
+ -> { @s.get_struct(Object.new) }.should raise_error(TypeError)
+ end
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
+ 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
- end
- describe "DATA_PTR" do
- it "returns the struct data" do
- a = @s.wrap_struct(1024)
- @s.get_struct_data_ptr(a).should == 1024
+ describe "DATA_PTR" do
+ it "returns the struct data" do
+ a = @s.wrap_struct(1024)
+ @s.get_struct_data_ptr(a).should == 1024
+ end
end
end
end
diff --git a/spec/ruby/optional/capi/debug_spec.rb b/spec/ruby/optional/capi/debug_spec.rb
index 148b8c38fb..14ba25609c 100644
--- a/spec/ruby/optional/capi/debug_spec.rb
+++ b/spec/ruby/optional/capi/debug_spec.rb
@@ -37,9 +37,12 @@ describe "C-API Debug function" do
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|
+ frames.each do |_s, klass, binding, iseq, backtrace_location|
if binding
- binding.source_location.should == [backtrace_location.path, backtrace_location.lineno]
+ # YJIT modifies Array#each backtraces but leaves its source_location as is
+ unless defined?(RubyVM::YJIT) && klass == Array && iseq.label == "each"
+ binding.source_location.should == [backtrace_location.path, backtrace_location.lineno]
+ end
method_name = binding.eval('__method__')
if method_name
method_name.should == backtrace_location.base_label.to_sym
diff --git a/spec/ruby/optional/capi/digest_spec.rb b/spec/ruby/optional/capi/digest_spec.rb
new file mode 100644
index 0000000000..65c5ecebb1
--- /dev/null
+++ b/spec/ruby/optional/capi/digest_spec.rb
@@ -0,0 +1,103 @@
+require_relative 'spec_helper'
+
+begin
+ require 'fiddle'
+rescue LoadError
+ return
+end
+
+load_extension('digest')
+
+describe "C-API Digest functions" do
+ before :each do
+ @s = CApiDigestSpecs.new
+ end
+
+ describe "rb_digest_make_metadata" do
+ before :each do
+ @metadata = @s.rb_digest_make_metadata
+ end
+
+ it "should store the block length" do
+ @s.block_length(@metadata).should == 40
+ end
+
+ it "should store the digest length" do
+ @s.digest_length(@metadata).should == 20
+ end
+
+ it "should store the context size" do
+ @s.context_size(@metadata).should == 129
+ end
+ end
+
+ describe "digest plugin" do
+ before :each do
+ @s = CApiDigestSpecs.new
+ @digest = Digest::TestDigest.new
+
+ # A pointer to the CTX type defined in the extension for this spec. Digest does not make the context directly
+ # accessible as part of its API. However, to ensure we are properly loading the plugin, it's useful to have
+ # direct access to the context pointer to verify its contents.
+ @context = Fiddle::Pointer.new(@s.context(@digest))
+ end
+
+ it "should report the block length" do
+ @digest.block_length.should == 40
+ end
+
+ it "should report the digest length" do
+ @digest.digest_length.should == 20
+ end
+
+ it "should initialize the context" do
+ # Our test plugin always writes the string "Initialized\n" when its init function is called.
+ verify_context("Initialized\n")
+ end
+
+ it "should update the digest" do
+ @digest.update("hello world")
+
+ # Our test plugin always writes the string "Updated: <data>\n" when its update function is called.
+ current = "Initialized\nUpdated: hello world"
+ verify_context(current)
+
+ @digest << "blah"
+
+ current = "Initialized\nUpdated: hello worldUpdated: blah"
+ verify_context(current)
+ end
+
+ it "should finalize the digest" do
+ @digest.update("")
+
+ finish_string = @digest.instance_eval { finish }
+
+ # We expect the plugin to write out the last `@digest.digest_length` bytes, followed by the string "Finished\n".
+ #
+ finish_string.should == "d\nUpdated: Finished\n"
+ finish_string.encoding.should == Encoding::ASCII_8BIT
+ end
+
+ it "should reset the context" do
+ @digest.update("foo")
+ verify_context("Initialized\nUpdated: foo")
+
+ @digest.reset
+
+ # The context will be recreated as a result of the `reset` so we must fetch the latest context pointer.
+ @context = Fiddle::Pointer.new(@s.context(@digest))
+
+ verify_context("Initialized\n")
+ end
+
+ def verify_context(current_body)
+ # In the CTX type, the length of the current context contents is stored in the first byte.
+ byte_count = @context[0]
+ byte_count.should == current_body.bytesize
+
+ # After the size byte follows a string.
+ @context[1, byte_count].should == current_body
+ end
+ end
+end
diff --git a/spec/ruby/optional/capi/encoding_spec.rb b/spec/ruby/optional/capi/encoding_spec.rb
index 1529e012b0..c14983c7ea 100644
--- a/spec/ruby/optional/capi/encoding_spec.rb
+++ b/spec/ruby/optional/capi/encoding_spec.rb
@@ -171,7 +171,7 @@ describe "C-API Encoding function" do
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("é").should == 0xE9
+ @s.rb_enc_mbc_to_codepoint("é").should == 0xE9
end
it "returns 0 if p == e" do
@@ -724,25 +724,25 @@ describe "C-API Encoding function" do
end
describe "rb_define_dummy_encoding" do
+ run = 0
+
it "defines the dummy encoding" do
- @s.rb_define_dummy_encoding("FOO")
- enc = Encoding.find("FOO")
+ @s.rb_define_dummy_encoding("FOO#{run += 1}")
+ enc = Encoding.find("FOO#{run}")
enc.should.dummy?
end
it "returns the index of the dummy encoding" do
- index = @s.rb_define_dummy_encoding("BAR")
+ index = @s.rb_define_dummy_encoding("BAR#{run += 1}")
index.should == Encoding.list.size - 1
end
- ruby_version_is "3.2" do
- it "raises EncodingError if too many encodings" do
- code = <<-RUBY
- require #{extension_path.dump}
- 1_000.times {|i| CApiEncodingSpecs.new.rb_define_dummy_encoding("R_\#{i}") }
- RUBY
- ruby_exe(code, args: "2>&1", exit_status: 1).should.include?('too many encoding (> 256) (EncodingError)')
- end
+ it "raises EncodingError if too many encodings" do
+ code = <<-RUBY
+ require #{extension_path.dump}
+ 1_000.times {|i| CApiEncodingSpecs.new.rb_define_dummy_encoding("R_\#{i}") }
+ RUBY
+ ruby_exe(code, args: "2>&1", exit_status: 1).should.include?('too many encoding (> 256) (EncodingError)')
end
end
end
diff --git a/spec/ruby/optional/capi/exception_spec.rb b/spec/ruby/optional/capi/exception_spec.rb
index 5bb60608b2..5bc8e26c62 100644
--- a/spec/ruby/optional/capi/exception_spec.rb
+++ b/spec/ruby/optional/capi/exception_spec.rb
@@ -100,6 +100,26 @@ describe "C-API Exception function" do
end
end
+ describe "rb_error_frozen_object" do
+ it "raises a FrozenError regardless of the object's frozen state" do
+ # The type of the argument we supply doesn't matter. The choice here is arbitrary and we only change the type
+ # of the argument to ensure the exception messages are set correctly.
+ -> { @s.rb_error_frozen_object(Array.new) }.should raise_error(FrozenError, "can't modify frozen Array: []")
+ -> { @s.rb_error_frozen_object(Array.new.freeze) }.should raise_error(FrozenError, "can't modify frozen Array: []")
+ end
+
+ it "properly handles recursive rb_error_frozen_object calls" do
+ klass = Class.new(Object)
+ object = klass.new
+ s = @s
+ klass.define_method :inspect do
+ s.rb_error_frozen_object(object)
+ end
+
+ -> { @s.rb_error_frozen_object(object) }.should raise_error(FrozenError, "can't modify frozen #{klass}: ...")
+ end
+ end
+
describe "rb_syserr_new" do
it "returns system error with default message when passed message is NULL" do
exception = @s.rb_syserr_new(Errno::ENOENT::Errno, nil)
diff --git a/spec/ruby/optional/capi/ext/array_spec.c b/spec/ruby/optional/capi/ext/array_spec.c
index 2347798bb4..628c4df9d7 100644
--- a/spec/ruby/optional/capi/ext/array_spec.c
+++ b/spec/ruby/optional/capi/ext/array_spec.c
@@ -196,6 +196,7 @@ static VALUE copy_ary(RB_BLOCK_CALL_FUNC_ARGLIST(el, new_ary)) {
return rb_ary_push(new_ary, el);
}
+#ifndef RUBY_VERSION_IS_4_0
static VALUE array_spec_rb_iterate(VALUE self, VALUE ary) {
VALUE new_ary = rb_ary_new();
@@ -203,6 +204,7 @@ static VALUE array_spec_rb_iterate(VALUE self, VALUE ary) {
return new_ary;
}
+#endif
static VALUE array_spec_rb_block_call(VALUE self, VALUE ary) {
VALUE new_ary = rb_ary_new();
@@ -216,6 +218,7 @@ static VALUE sub_pair(RB_BLOCK_CALL_FUNC_ARGLIST(el, holder)) {
return rb_ary_push(holder, rb_ary_entry(el, 1));
}
+#ifndef RUBY_VERSION_IS_4_0
static VALUE each_pair(VALUE obj) {
return rb_funcall(obj, rb_intern("each_pair"), 0);
}
@@ -227,6 +230,7 @@ static VALUE array_spec_rb_iterate_each_pair(VALUE self, VALUE obj) {
return new_ary;
}
+#endif
static VALUE array_spec_rb_block_call_each_pair(VALUE self, VALUE obj) {
VALUE new_ary = rb_ary_new();
@@ -241,10 +245,12 @@ static VALUE iter_yield(RB_BLOCK_CALL_FUNC_ARGLIST(el, ary)) {
return Qnil;
}
+#ifndef RUBY_VERSION_IS_4_0
static VALUE array_spec_rb_iterate_then_yield(VALUE self, VALUE obj) {
rb_iterate(rb_each, obj, iter_yield, obj);
return Qnil;
}
+#endif
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);
@@ -308,9 +314,11 @@ void Init_array_spec(void) {
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);
+#ifndef RUBY_VERSION_IS_4_0
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);
+#endif
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);
diff --git a/spec/ruby/optional/capi/ext/class_spec.c b/spec/ruby/optional/capi/ext/class_spec.c
index c13f02ecf2..8ac0e7a93f 100644
--- a/spec/ruby/optional/capi/ext/class_spec.c
+++ b/spec/ruby/optional/capi/ext/class_spec.c
@@ -65,11 +65,9 @@ static VALUE class_spec_rb_class_new_instance(VALUE self, VALUE args, VALUE klas
return rb_class_new_instance(RARRAY_LENINT(args), RARRAY_PTR(args), klass);
}
-#ifdef RUBY_VERSION_IS_3_0
static VALUE class_spec_rb_class_new_instance_kw(VALUE self, VALUE args, VALUE klass) {
return rb_class_new_instance_kw(RARRAY_LENINT(args), RARRAY_PTR(args), klass, RB_PASS_KEYWORDS);
}
-#endif
static VALUE class_spec_rb_class_real(VALUE self, VALUE object) {
if (rb_type_p(object, T_FIXNUM)) {
@@ -160,9 +158,7 @@ void Init_class_spec(void) {
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, 2);
-#ifdef RUBY_VERSION_IS_3_0
rb_define_method(cls, "rb_class_new_instance_kw", class_spec_rb_class_new_instance_kw, 2);
-#endif
rb_define_method(cls, "rb_class_real", class_spec_rb_class_real, 1);
rb_define_method(cls, "rb_class_get_superclass", class_spec_rb_class_get_superclass, 1);
rb_define_method(cls, "rb_class_superclass", class_spec_rb_class_superclass, 1);
diff --git a/spec/ruby/optional/capi/ext/constants_spec.c b/spec/ruby/optional/capi/ext/constants_spec.c
index 9aee8db37f..05819ea476 100644
--- a/spec/ruby/optional/capi/ext/constants_spec.c
+++ b/spec/ruby/optional/capi/ext/constants_spec.c
@@ -14,9 +14,6 @@ defconstfunc(rb_cBinding)
defconstfunc(rb_cClass)
defconstfunc(rb_cComplex)
defconstfunc(rb_mComparable)
-#ifndef RUBY_VERSION_IS_3_0
-defconstfunc(rb_cData)
-#endif
defconstfunc(rb_cDir)
defconstfunc(rb_cEncoding)
defconstfunc(rb_mEnumerable)
@@ -97,9 +94,6 @@ void Init_constants_spec(void) {
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);
diff --git a/spec/ruby/optional/capi/ext/data_spec.c b/spec/ruby/optional/capi/ext/data_spec.c
index ef069ef0ba..efefe37c3a 100644
--- a/spec/ruby/optional/capi/ext/data_spec.c
+++ b/spec/ruby/optional/capi/ext/data_spec.c
@@ -3,6 +3,7 @@
#include <string.h>
+#ifndef RUBY_VERSION_IS_3_4
#ifdef __cplusplus
extern "C" {
#endif
@@ -70,8 +71,10 @@ VALUE sws_rb_check_type(VALUE self, VALUE obj, VALUE other) {
rb_check_type(obj, TYPE(other));
return Qtrue;
}
+#endif
void Init_data_spec(void) {
+#ifndef RUBY_VERSION_IS_3_4
VALUE cls = rb_define_class("CApiAllocSpecs", rb_cObject);
rb_define_alloc_func(cls, sdaf_alloc_func);
rb_define_method(cls, "wrapped_data", sdaf_get_struct, 0);
@@ -82,6 +85,7 @@ void Init_data_spec(void) {
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);
+#endif
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/ext/digest_spec.c b/spec/ruby/optional/capi/ext/digest_spec.c
new file mode 100644
index 0000000000..65c8defa20
--- /dev/null
+++ b/spec/ruby/optional/capi/ext/digest_spec.c
@@ -0,0 +1,168 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#include "ruby/digest.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DIGEST_LENGTH 20
+#define BLOCK_LENGTH 40
+
+const char *init_string = "Initialized\n";
+const char *update_string = "Updated: ";
+const char *finish_string = "Finished\n";
+
+#define PAYLOAD_SIZE 128
+
+typedef struct CTX {
+ uint8_t pos;
+ char payload[PAYLOAD_SIZE];
+} CTX;
+
+void* context = NULL;
+
+int digest_spec_plugin_init(void *raw_ctx) {
+ // Make the context accessible to tests. This isn't safe, but there's no way to access the context otherwise.
+ context = raw_ctx;
+
+ struct CTX *ctx = (struct CTX *)raw_ctx;
+ size_t len = strlen(init_string);
+
+ // Clear the payload since this init function will be invoked as part of the `reset` operation.
+ memset(ctx->payload, 0, PAYLOAD_SIZE);
+
+ // Write a simple value we can verify in tests.
+ // This is not what a real digest would do, but we're using a dummy digest plugin to test interactions.
+ memcpy(ctx->payload, init_string, len);
+ ctx->pos = (uint8_t) len;
+
+ return 1;
+}
+
+void digest_spec_plugin_update(void *raw_ctx, unsigned char *ptr, size_t size) {
+ struct CTX *ctx = (struct CTX *)raw_ctx;
+ size_t update_str_len = strlen(update_string);
+
+ if (ctx->pos + update_str_len + size >= PAYLOAD_SIZE) {
+ rb_raise(rb_eRuntimeError, "update size too large; reset the digest and write fewer updates");
+ }
+
+ // Write the supplied value to the payload so it can be easily verified in test.
+ // This is not what a real digest would do, but we're using a dummy digest plugin to test interactions.
+ memcpy(ctx->payload + ctx->pos, update_string, update_str_len);
+ ctx->pos += update_str_len;
+
+ memcpy(ctx->payload + ctx->pos, ptr, size);
+ ctx->pos += size;
+
+ return;
+}
+
+int digest_spec_plugin_finish(void *raw_ctx, unsigned char *ptr) {
+ struct CTX *ctx = (struct CTX *)raw_ctx;
+ size_t finish_string_len = strlen(finish_string);
+
+ // We're always going to write DIGEST_LENGTH bytes. In a real plugin, this would be the digest value. Here we
+ // write out a text string in order to make validation in tests easier.
+ //
+ // In order to delineate the output more clearly from an `Digest#update` call, we always write out the
+ // `finish_string` message. That leaves `DIGEST_LENGTH - finish_string_len` bytes to read out of the context.
+ size_t context_bytes = DIGEST_LENGTH - finish_string_len;
+
+ memcpy(ptr, ctx->payload + (ctx->pos - context_bytes), context_bytes);
+ memcpy(ptr + context_bytes, finish_string, finish_string_len);
+
+ return 1;
+}
+
+static const rb_digest_metadata_t metadata = {
+ // The RUBY_DIGEST_API_VERSION value comes from ruby/digest.h and may vary based on the Ruby being tested. Since
+ // it isn't publicly exposed in the digest gem, we ignore for these tests. Either the test hard-codes an expected
+ // value and is subject to breaking depending on the Ruby being run or we publicly expose `RUBY_DIGEST_API_VERSION`,
+ // in which case the test would pass trivially.
+ RUBY_DIGEST_API_VERSION,
+ DIGEST_LENGTH,
+ BLOCK_LENGTH,
+ sizeof(CTX),
+ (rb_digest_hash_init_func_t) digest_spec_plugin_init,
+ (rb_digest_hash_update_func_t) digest_spec_plugin_update,
+ (rb_digest_hash_finish_func_t) digest_spec_plugin_finish,
+};
+
+// The `get_metadata_ptr` function is not publicly available in the digest gem. However, we need to use
+// to extract the `rb_digest_metadata_t*` value set up by the plugin so we reproduce and adjust the
+// definition here.
+//
+// Taken and adapted from https://github.com/ruby/digest/blob/v3.2.0/ext/digest/digest.c#L558-L568
+static rb_digest_metadata_t * get_metadata_ptr(VALUE obj) {
+ rb_digest_metadata_t *algo;
+
+#ifdef DIGEST_USE_RB_EXT_RESOLVE_SYMBOL
+ // In the digest gem there is an additional data type check performed before reading the value out.
+ // Since the type definition isn't public, we can't use it as part of a type check here so we omit it.
+ // This is safe to do because this code is intended to only load digest plugins written as part of this test suite.
+ algo = (rb_digest_metadata_t *) RTYPEDDATA_DATA(obj);
+#else
+# undef RUBY_UNTYPED_DATA_WARNING
+# define RUBY_UNTYPED_DATA_WARNING 0
+ Data_Get_Struct(obj, rb_digest_metadata_t, algo);
+#endif
+
+ return algo;
+}
+
+VALUE digest_spec_rb_digest_make_metadata(VALUE self) {
+ return rb_digest_make_metadata(&metadata);
+}
+
+VALUE digest_spec_block_length(VALUE self, VALUE meta) {
+ rb_digest_metadata_t* algo = get_metadata_ptr(meta);
+
+ return SIZET2NUM(algo->block_len);
+}
+
+VALUE digest_spec_digest_length(VALUE self, VALUE meta) {
+ rb_digest_metadata_t* algo = get_metadata_ptr(meta);
+
+ return SIZET2NUM(algo->digest_len);
+}
+
+VALUE digest_spec_context_size(VALUE self, VALUE meta) {
+ rb_digest_metadata_t* algo = get_metadata_ptr(meta);
+
+ return SIZET2NUM(algo->ctx_size);
+}
+
+#ifndef PTR2NUM
+#define PTR2NUM(x) (rb_int2inum((intptr_t)(void *)(x)))
+#endif
+
+VALUE digest_spec_context(VALUE self, VALUE digest) {
+ return PTR2NUM(context);
+}
+
+void Init_digest_spec(void) {
+ VALUE cls;
+
+ cls = rb_define_class("CApiDigestSpecs", rb_cObject);
+ rb_define_method(cls, "rb_digest_make_metadata", digest_spec_rb_digest_make_metadata, 0);
+ rb_define_method(cls, "block_length", digest_spec_block_length, 1);
+ rb_define_method(cls, "digest_length", digest_spec_digest_length, 1);
+ rb_define_method(cls, "context_size", digest_spec_context_size, 1);
+ rb_define_method(cls, "context", digest_spec_context, 1);
+
+ VALUE mDigest, cDigest_Base, cDigest;
+
+ mDigest = rb_define_module("Digest");
+ mDigest = rb_digest_namespace();
+ cDigest_Base = rb_const_get(mDigest, rb_intern_const("Base"));
+
+ cDigest = rb_define_class_under(mDigest, "TestDigest", cDigest_Base);
+ rb_iv_set(cDigest, "metadata", rb_digest_make_metadata(&metadata));
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/ruby/optional/capi/ext/exception_spec.c b/spec/ruby/optional/capi/ext/exception_spec.c
index 0e8347ab0d..c3b94d7bcd 100644
--- a/spec/ruby/optional/capi/ext/exception_spec.c
+++ b/spec/ruby/optional/capi/ext/exception_spec.c
@@ -36,6 +36,13 @@ VALUE exception_spec_rb_set_errinfo(VALUE self, VALUE exc) {
return Qnil;
}
+NORETURN(VALUE exception_spec_rb_error_frozen_object(VALUE self, VALUE object));
+
+VALUE exception_spec_rb_error_frozen_object(VALUE self, VALUE object) {
+ rb_error_frozen_object(object);
+ UNREACHABLE_RETURN(Qnil);
+}
+
VALUE exception_spec_rb_syserr_new(VALUE self, VALUE num, VALUE msg) {
int n = NUM2INT(num);
char *cstr = NULL;
@@ -66,6 +73,7 @@ void Init_exception_spec(void) {
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_error_frozen_object", exception_spec_rb_error_frozen_object, 1);
rb_define_method(cls, "rb_syserr_new", exception_spec_rb_syserr_new, 2);
rb_define_method(cls, "rb_syserr_new_str", exception_spec_rb_syserr_new_str, 2);
rb_define_method(cls, "rb_make_exception", exception_spec_rb_make_exception, 1);
diff --git a/spec/ruby/optional/capi/ext/fiber_spec.c b/spec/ruby/optional/capi/ext/fiber_spec.c
index f06a54494e..db54f7ad8c 100644
--- a/spec/ruby/optional/capi/ext/fiber_spec.c
+++ b/spec/ruby/optional/capi/ext/fiber_spec.c
@@ -44,12 +44,10 @@ 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);
@@ -58,10 +56,7 @@ void Init_fiber_spec(void) {
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
diff --git a/spec/ruby/optional/capi/ext/finalizer_spec.c b/spec/ruby/optional/capi/ext/finalizer_spec.c
new file mode 100644
index 0000000000..83347da912
--- /dev/null
+++ b/spec/ruby/optional/capi/ext/finalizer_spec.c
@@ -0,0 +1,25 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static VALUE define_finalizer(VALUE self, VALUE obj, VALUE finalizer) {
+ return rb_define_finalizer(obj, finalizer);
+}
+
+static VALUE undefine_finalizer(VALUE self, VALUE obj) {
+ return rb_undefine_finalizer(obj);
+}
+
+void Init_finalizer_spec(void) {
+ VALUE cls = rb_define_class("CApiFinalizerSpecs", rb_cObject);
+
+ rb_define_method(cls, "rb_define_finalizer", define_finalizer, 2);
+ rb_define_method(cls, "rb_undefine_finalizer", undefine_finalizer, 1);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/spec/ruby/optional/capi/ext/hash_spec.c b/spec/ruby/optional/capi/ext/hash_spec.c
index 69ef02d5da..653917f2c4 100644
--- a/spec/ruby/optional/capi/ext/hash_spec.c
+++ b/spec/ruby/optional/capi/ext/hash_spec.c
@@ -105,11 +105,9 @@ VALUE hash_spec_rb_hash_new(VALUE self) {
return rb_hash_new();
}
-#ifdef RUBY_VERSION_IS_3_2
VALUE hash_spec_rb_hash_new_capa(VALUE self, VALUE capacity) {
return rb_hash_new_capa(NUM2LONG(capacity));
}
-#endif
VALUE rb_ident_hash_new(void); /* internal.h, used in ripper */
@@ -134,6 +132,20 @@ VALUE hash_spec_compute_a_hash_code(VALUE self, VALUE seed) {
return ULONG2NUM(h);
}
+VALUE hash_spec_rb_hash_bulk_insert(VALUE self, VALUE array_len, VALUE array, VALUE hash) {
+ VALUE* ptr;
+
+ if (array == Qnil) {
+ ptr = NULL;
+ } else {
+ ptr = RARRAY_PTR(array);
+ }
+
+ long len = FIX2LONG(array_len);
+ rb_hash_bulk_insert(len, ptr, hash);
+ return Qnil;
+}
+
void Init_hash_spec(void) {
VALUE cls = rb_define_class("CApiHashSpecs", rb_cObject);
rb_define_method(cls, "rb_hash", hash_spec_rb_hash, 1);
@@ -155,13 +167,12 @@ 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);
-#ifdef RUBY_VERSION_IS_3_2
rb_define_method(cls, "rb_hash_new_capa", hash_spec_rb_hash_new_capa, 1);
-#endif
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);
+ rb_define_method(cls, "rb_hash_bulk_insert", hash_spec_rb_hash_bulk_insert, 3);
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/ext/io_spec.c b/spec/ruby/optional/capi/ext/io_spec.c
index 1a73331386..f3ede15729 100644
--- a/spec/ruby/optional/capi/ext/io_spec.c
+++ b/spec/ruby/optional/capi/ext/io_spec.c
@@ -28,13 +28,7 @@ static int set_non_blocking(int fd) {
}
static int io_spec_get_fd(VALUE io) {
-#ifdef RUBY_VERSION_IS_3_1
return rb_io_descriptor(io);
-#else
- rb_io_t* fp;
- GetOpenFile(io, fp);
- return fp->fd;
-#endif
}
VALUE io_spec_GetOpenFile_fd(VALUE self, VALUE io) {
@@ -143,7 +137,7 @@ VALUE io_spec_rb_io_wait_readable(VALUE self, VALUE io, VALUE read_p) {
errno = saved_errno;
}
- ret = rb_io_wait_readable(fd);
+ ret = rb_io_maybe_wait_readable(errno, io, Qnil);
if (RTEST(read_p)) {
ssize_t r = read(fd, buf, RB_IO_WAIT_READABLE_BUF);
@@ -162,18 +156,15 @@ VALUE io_spec_rb_io_wait_readable(VALUE self, VALUE io, VALUE read_p) {
}
VALUE io_spec_rb_io_wait_writable(VALUE self, VALUE io) {
- int ret = rb_io_wait_writable(io_spec_get_fd(io));
+ int ret = rb_io_maybe_wait_writable(errno, io, Qnil);
return ret ? Qtrue : Qfalse;
}
-#ifdef RUBY_VERSION_IS_3_1
VALUE io_spec_rb_io_maybe_wait_writable(VALUE self, VALUE error, VALUE io, VALUE timeout) {
int ret = rb_io_maybe_wait_writable(NUM2INT(error), io, timeout);
return INT2NUM(ret);
}
-#endif
-#ifdef RUBY_VERSION_IS_3_1
#ifdef SET_NON_BLOCKING_FAILS_ALWAYS
NORETURN(VALUE io_spec_rb_io_maybe_wait_readable(VALUE self, VALUE error, VALUE io, VALUE timeout, VALUE read_p));
#endif
@@ -216,13 +207,10 @@ VALUE io_spec_rb_io_maybe_wait_readable(VALUE self, VALUE error, VALUE io, VALUE
UNREACHABLE_RETURN(Qnil);
#endif
}
-#endif
-#ifdef RUBY_VERSION_IS_3_1
VALUE io_spec_rb_io_maybe_wait(VALUE self, VALUE error, VALUE io, VALUE events, VALUE timeout) {
return rb_io_maybe_wait(NUM2INT(error), io, events, timeout);
}
-#endif
VALUE io_spec_rb_thread_wait_fd(VALUE self, VALUE io) {
rb_thread_wait_fd(io_spec_get_fd(io));
@@ -230,13 +218,13 @@ VALUE io_spec_rb_thread_wait_fd(VALUE self, VALUE io) {
}
VALUE io_spec_rb_wait_for_single_fd(VALUE self, VALUE io, VALUE events, VALUE secs, VALUE usecs) {
- int fd = io_spec_get_fd(io);
- struct timeval tv;
+ VALUE timeout = Qnil;
if (!NIL_P(secs)) {
- tv.tv_sec = FIX2INT(secs);
- tv.tv_usec = FIX2INT(usecs);
+ timeout = rb_float_new((double)FIX2INT(secs) + (0.000001 * FIX2INT(usecs)));
}
- return INT2FIX(rb_wait_for_single_fd(fd, FIX2INT(events), NIL_P(secs) ? NULL : &tv));
+ VALUE result = rb_io_wait(io, events, timeout);
+ if (result == Qfalse) return INT2FIX(0);
+ else return result;
}
VALUE io_spec_rb_thread_fd_writable(VALUE self, VALUE io) {
@@ -330,13 +318,15 @@ static VALUE io_spec_errno_set(VALUE self, VALUE val) {
}
VALUE io_spec_mode_sync_flag(VALUE self, VALUE io) {
+ int mode;
#ifdef RUBY_VERSION_IS_3_3
- if (rb_io_mode(io) & FMODE_SYNC) {
+ mode = rb_io_mode(io);
#else
rb_io_t *fp;
GetOpenFile(io, fp);
- if (fp->mode & FMODE_SYNC) {
+ mode = fp->mode;
#endif
+ if (mode & FMODE_SYNC) {
return Qtrue;
} else {
return Qfalse;
@@ -351,6 +341,25 @@ static VALUE io_spec_rb_io_mode(VALUE self, VALUE io) {
static VALUE io_spec_rb_io_path(VALUE self, VALUE io) {
return rb_io_path(io);
}
+
+static VALUE io_spec_rb_io_closed_p(VALUE self, VALUE io) {
+ return rb_io_closed_p(io);
+}
+
+static VALUE io_spec_rb_io_open_descriptor(VALUE self, VALUE klass, VALUE descriptor, VALUE mode, VALUE path, VALUE timeout, VALUE internal_encoding, VALUE external_encoding, VALUE ecflags, VALUE ecopts) {
+ struct rb_io_encoding io_encoding;
+
+ io_encoding.enc = rb_to_encoding(internal_encoding);
+ io_encoding.enc2 = rb_to_encoding(external_encoding);
+ io_encoding.ecflags = FIX2INT(ecflags);
+ io_encoding.ecopts = ecopts;
+
+ return rb_io_open_descriptor(klass, FIX2INT(descriptor), FIX2INT(mode), path, timeout, &io_encoding);
+}
+
+static VALUE io_spec_rb_io_open_descriptor_without_encoding(VALUE self, VALUE klass, VALUE descriptor, VALUE mode, VALUE path, VALUE timeout) {
+ return rb_io_open_descriptor(klass, FIX2INT(descriptor), FIX2INT(mode), path, timeout, NULL);
+}
#endif
void Init_io_spec(void) {
@@ -370,11 +379,9 @@ void Init_io_spec(void) {
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);
-#ifdef RUBY_VERSION_IS_3_1
rb_define_method(cls, "rb_io_maybe_wait_writable", io_spec_rb_io_maybe_wait_writable, 3);
rb_define_method(cls, "rb_io_maybe_wait_readable", io_spec_rb_io_maybe_wait_readable, 4);
rb_define_method(cls, "rb_io_maybe_wait", io_spec_rb_io_maybe_wait, 4);
-#endif
rb_define_method(cls, "rb_thread_wait_fd", io_spec_rb_thread_wait_fd, 1);
rb_define_method(cls, "rb_thread_fd_writable", io_spec_rb_thread_fd_writable, 1);
rb_define_method(cls, "rb_thread_fd_select_read", io_spec_rb_thread_fd_select_read, 1);
@@ -389,6 +396,14 @@ void Init_io_spec(void) {
#if defined(RUBY_VERSION_IS_3_3) || defined(TRUFFLERUBY)
rb_define_method(cls, "rb_io_mode", io_spec_rb_io_mode, 1);
rb_define_method(cls, "rb_io_path", io_spec_rb_io_path, 1);
+ rb_define_method(cls, "rb_io_closed_p", io_spec_rb_io_closed_p, 1);
+ rb_define_method(cls, "rb_io_open_descriptor", io_spec_rb_io_open_descriptor, 9);
+ rb_define_method(cls, "rb_io_open_descriptor_without_encoding", io_spec_rb_io_open_descriptor_without_encoding, 5);
+ rb_define_const(cls, "FMODE_READABLE", INT2FIX(FMODE_READABLE));
+ rb_define_const(cls, "FMODE_WRITABLE", INT2FIX(FMODE_WRITABLE));
+ rb_define_const(cls, "FMODE_BINMODE", INT2FIX(FMODE_BINMODE));
+ rb_define_const(cls, "FMODE_TEXTMODE", INT2FIX(FMODE_TEXTMODE));
+ rb_define_const(cls, "ECONV_UNIVERSAL_NEWLINE_DECORATOR", INT2FIX(ECONV_UNIVERSAL_NEWLINE_DECORATOR));
#endif
}
diff --git a/spec/ruby/optional/capi/ext/kernel_spec.c b/spec/ruby/optional/capi/ext/kernel_spec.c
index 1761599081..a8fed21b59 100644
--- a/spec/ruby/optional/capi/ext/kernel_spec.c
+++ b/spec/ruby/optional/capi/ext/kernel_spec.c
@@ -7,16 +7,12 @@
extern "C" {
#endif
-VALUE kernel_spec_call_proc(VALUE arg_array) {
+static VALUE kernel_spec_call_proc(VALUE arg_array) {
VALUE arg = rb_ary_pop(arg_array);
VALUE proc = rb_ary_pop(arg_array);
return rb_funcall(proc, rb_intern("call"), 1, arg);
}
-VALUE kernel_spec_call_proc_raise(VALUE arg_array, VALUE raised_exc) {
- return kernel_spec_call_proc(arg_array);
-}
-
static VALUE kernel_spec_rb_block_given_p(VALUE self) {
return rb_block_given_p() ? Qtrue : Qfalse;
}
@@ -71,11 +67,20 @@ VALUE kernel_spec_rb_block_call_no_func(VALUE self, VALUE ary) {
return rb_block_call(ary, rb_intern("map"), 0, NULL, (rb_block_call_func_t)NULL, Qnil);
}
-
VALUE kernel_spec_rb_frame_this_func(VALUE self) {
return ID2SYM(rb_frame_this_func());
}
+VALUE kernel_spec_rb_category_warn_deprecated(VALUE self) {
+ rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "foo");
+ return Qnil;
+}
+
+VALUE kernel_spec_rb_category_warn_deprecated_with_integer_extra_value(VALUE self, VALUE value) {
+ rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "foo %d", FIX2INT(value));
+ return Qnil;
+}
+
VALUE kernel_spec_rb_ensure(VALUE self, VALUE main_proc, VALUE arg,
VALUE ensure_proc, VALUE arg2) {
VALUE main_array, ensure_array;
@@ -112,9 +117,11 @@ VALUE kernel_spec_rb_eval_string(VALUE self, VALUE str) {
return rb_eval_string(RSTRING_PTR(str));
}
+#ifndef RUBY_VERSION_IS_4_0
VALUE kernel_spec_rb_eval_cmd_kw(VALUE self, VALUE cmd, VALUE args, VALUE kw_splat) {
return rb_eval_cmd_kw(cmd, args, NUM2INT(kw_splat));
}
+#endif
VALUE kernel_spec_rb_raise(VALUE self, VALUE hash) {
rb_hash_aset(hash, ID2SYM(rb_intern("stage")), ID2SYM(rb_intern("before")));
@@ -134,7 +141,16 @@ VALUE kernel_spec_rb_throw_obj(VALUE self, VALUE obj, VALUE result) {
return ID2SYM(rb_intern("rb_throw_failed"));
}
-VALUE kernel_spec_call_proc_with_raised_exc(VALUE arg_array, VALUE raised_exc) {
+VALUE kernel_spec_rb_errinfo(VALUE self) {
+ return rb_errinfo();
+}
+
+VALUE kernel_spec_rb_set_errinfo(VALUE self, VALUE exc) {
+ rb_set_errinfo(exc);
+ return Qnil;
+}
+
+static VALUE kernel_spec_call_proc_with_raised_exc(VALUE arg_array, VALUE raised_exc) {
VALUE argv[2];
int argc;
@@ -181,7 +197,7 @@ VALUE kernel_spec_rb_rescue2(int argc, VALUE *args, VALUE self) {
rb_ary_push(raise_array, args[3]);
return rb_rescue2(kernel_spec_call_proc, main_array,
- kernel_spec_call_proc_raise, raise_array, args[4], args[5], (VALUE)0);
+ kernel_spec_call_proc_with_raised_exc, raise_array, args[4], args[5], (VALUE)0);
}
static VALUE kernel_spec_rb_protect_yield(VALUE self, VALUE obj, VALUE ary) {
@@ -195,7 +211,7 @@ 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) {
+static VALUE kernel_spec_rb_protect_ignore_status(VALUE self, VALUE obj, VALUE ary) {
int status = 0;
VALUE res = rb_protect(rb_yield, obj, &status);
rb_ary_store(ary, 0, INT2NUM(23));
@@ -221,7 +237,7 @@ static VALUE kernel_spec_rb_eval_string_protect(VALUE self, VALUE str, VALUE ary
VALUE kernel_spec_rb_sys_fail(VALUE self, VALUE msg) {
errno = 1;
if (msg == Qnil) {
- rb_sys_fail(0);
+ rb_sys_fail(NULL);
} else if (self != Qundef) {
rb_sys_fail(StringValuePtr(msg));
}
@@ -237,6 +253,13 @@ VALUE kernel_spec_rb_syserr_fail(VALUE self, VALUE err, VALUE msg) {
return Qnil;
}
+VALUE kernel_spec_rb_syserr_fail_str(VALUE self, VALUE err, VALUE msg) {
+ if (self != Qundef) {
+ rb_syserr_fail_str(NUM2INT(err), msg);
+ }
+ return Qnil;
+}
+
VALUE kernel_spec_rb_warn(VALUE self, VALUE msg) {
rb_warn("%s", StringValuePtr(msg));
return Qnil;
@@ -318,6 +341,10 @@ static VALUE kernel_spec_rb_f_sprintf(VALUE self, VALUE ary) {
return rb_f_sprintf((int)RARRAY_LEN(ary), RARRAY_PTR(ary));
}
+static VALUE kernel_spec_rb_str_format(VALUE self, VALUE count, VALUE ary, VALUE format) {
+ return rb_str_format(FIX2INT(count), RARRAY_PTR(ary), format);
+}
+
static VALUE kernel_spec_rb_make_backtrace(VALUE self) {
return rb_make_backtrace();
}
@@ -326,7 +353,6 @@ static VALUE kernel_spec_rb_funcallv(VALUE self, VALUE obj, VALUE method, VALUE
return rb_funcallv(obj, SYM2ID(method), RARRAY_LENINT(args), RARRAY_PTR(args));
}
-#ifdef RUBY_VERSION_IS_3_0
static VALUE kernel_spec_rb_funcallv_kw(VALUE self, VALUE obj, VALUE method, VALUE args) {
return rb_funcallv_kw(obj, SYM2ID(method), RARRAY_LENINT(args), RARRAY_PTR(args), RB_PASS_KEYWORDS);
}
@@ -334,7 +360,6 @@ static VALUE kernel_spec_rb_funcallv_kw(VALUE self, VALUE obj, VALUE method, VAL
static VALUE kernel_spec_rb_keyword_given_p(int argc, VALUE *args, VALUE self) {
return rb_keyword_given_p() ? Qtrue : Qfalse;
}
-#endif
static VALUE kernel_spec_rb_funcallv_public(VALUE self, VALUE obj, VALUE method) {
return rb_funcallv_public(obj, SYM2ID(method), 0, NULL);
@@ -376,22 +401,30 @@ void Init_kernel_spec(void) {
rb_define_method(cls, "rb_block_lambda", kernel_spec_rb_block_lambda, 0);
rb_define_method(cls, "rb_frame_this_func_test", kernel_spec_rb_frame_this_func, 0);
rb_define_method(cls, "rb_frame_this_func_test_again", kernel_spec_rb_frame_this_func, 0);
+ rb_define_method(cls, "rb_category_warn_deprecated", kernel_spec_rb_category_warn_deprecated, 0);
+ rb_define_method(cls, "rb_category_warn_deprecated_with_integer_extra_value", kernel_spec_rb_category_warn_deprecated_with_integer_extra_value, 1);
rb_define_method(cls, "rb_ensure", kernel_spec_rb_ensure, 4);
rb_define_method(cls, "rb_eval_string", kernel_spec_rb_eval_string, 1);
+#ifndef RUBY_VERSION_IS_4_0
rb_define_method(cls, "rb_eval_cmd_kw", kernel_spec_rb_eval_cmd_kw, 3);
+#endif
rb_define_method(cls, "rb_raise", kernel_spec_rb_raise, 1);
rb_define_method(cls, "rb_throw", kernel_spec_rb_throw, 1);
rb_define_method(cls, "rb_throw_obj", kernel_spec_rb_throw_obj, 2);
+ rb_define_method(cls, "rb_errinfo", kernel_spec_rb_errinfo, 0);
+ rb_define_method(cls, "rb_set_errinfo", kernel_spec_rb_set_errinfo, 1);
+ rb_define_method(cls, "rb_rescue", kernel_spec_rb_rescue, 4);
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_ignore_status", kernel_spec_rb_protect_ignore_status, 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);
rb_define_method(cls, "rb_sys_fail", kernel_spec_rb_sys_fail, 1);
rb_define_method(cls, "rb_syserr_fail", kernel_spec_rb_syserr_fail, 2);
+ rb_define_method(cls, "rb_syserr_fail_str", kernel_spec_rb_syserr_fail_str, 2);
rb_define_method(cls, "rb_warn", kernel_spec_rb_warn, 1);
rb_define_method(cls, "rb_yield", kernel_spec_rb_yield, 1);
rb_define_method(cls, "rb_yield_indirected", kernel_spec_rb_yield_indirected, 1);
@@ -402,12 +435,11 @@ void Init_kernel_spec(void) {
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_str_format", kernel_spec_rb_str_format, 3);
rb_define_method(cls, "rb_make_backtrace", kernel_spec_rb_make_backtrace, 0);
rb_define_method(cls, "rb_funcallv", kernel_spec_rb_funcallv, 3);
-#ifdef RUBY_VERSION_IS_3_0
rb_define_method(cls, "rb_funcallv_kw", kernel_spec_rb_funcallv_kw, 3);
rb_define_method(cls, "rb_keyword_given_p", kernel_spec_rb_keyword_given_p, -1);
-#endif
rb_define_method(cls, "rb_funcallv_public", kernel_spec_rb_funcallv_public, 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, 4);
diff --git a/spec/ruby/optional/capi/ext/mutex_spec.c b/spec/ruby/optional/capi/ext/mutex_spec.c
index c2fdf917ac..d2c8f98e89 100644
--- a/spec/ruby/optional/capi/ext/mutex_spec.c
+++ b/spec/ruby/optional/capi/ext/mutex_spec.c
@@ -29,15 +29,34 @@ VALUE mutex_spec_rb_mutex_sleep(VALUE self, VALUE mutex, VALUE timeout) {
return rb_mutex_sleep(mutex, timeout);
}
-
VALUE mutex_spec_rb_mutex_callback(VALUE arg) {
return rb_funcall(arg, rb_intern("call"), 0);
}
+VALUE mutex_spec_rb_mutex_naughty_callback(VALUE arg) {
+ int *result = (int *) arg;
+ return (VALUE) result;
+}
+
+VALUE mutex_spec_rb_mutex_callback_basic(VALUE arg) {
+ return arg;
+}
+
VALUE mutex_spec_rb_mutex_synchronize(VALUE self, VALUE mutex, VALUE value) {
return rb_mutex_synchronize(mutex, mutex_spec_rb_mutex_callback, value);
}
+VALUE mutex_spec_rb_mutex_synchronize_with_naughty_callback(VALUE self, VALUE mutex) {
+ // a naughty callback accepts or returns not a Ruby object but arbitrary value
+ int arg = 42;
+ VALUE result = rb_mutex_synchronize(mutex, mutex_spec_rb_mutex_naughty_callback, (VALUE) &arg);
+ return INT2NUM(*((int *) result));
+}
+
+VALUE mutex_spec_rb_mutex_synchronize_with_native_callback(VALUE self, VALUE mutex, VALUE value) {
+ return rb_mutex_synchronize(mutex, mutex_spec_rb_mutex_callback_basic, value);
+}
+
void Init_mutex_spec(void) {
VALUE cls = rb_define_class("CApiMutexSpecs", rb_cObject);
rb_define_method(cls, "rb_mutex_new", mutex_spec_rb_mutex_new, 0);
@@ -47,6 +66,8 @@ void Init_mutex_spec(void) {
rb_define_method(cls, "rb_mutex_unlock", mutex_spec_rb_mutex_unlock, 1);
rb_define_method(cls, "rb_mutex_sleep", mutex_spec_rb_mutex_sleep, 2);
rb_define_method(cls, "rb_mutex_synchronize", mutex_spec_rb_mutex_synchronize, 2);
+ rb_define_method(cls, "rb_mutex_synchronize_with_naughty_callback", mutex_spec_rb_mutex_synchronize_with_naughty_callback, 1);
+ rb_define_method(cls, "rb_mutex_synchronize_with_native_callback", mutex_spec_rb_mutex_synchronize_with_native_callback, 2);
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/ext/object_spec.c b/spec/ruby/optional/capi/ext/object_spec.c
index aa60662e1e..995bc38fcf 100644
--- a/spec/ruby/optional/capi/ext/object_spec.c
+++ b/spec/ruby/optional/capi/ext/object_spec.c
@@ -15,11 +15,6 @@ 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;
- }
-#endif
if (strcmp(flag_cstr, "FL_FREEZE") == 0) {
return FL_FREEZE;
}
@@ -30,22 +25,6 @@ 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;
-}
-
-static VALUE object_spec_OBJ_TAINTED(VALUE self, VALUE obj) {
- return OBJ_TAINTED(obj) ? Qtrue : Qfalse;
-}
-
-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);
}
@@ -154,12 +133,6 @@ static VALUE object_specs_rb_obj_method(VALUE self, VALUE obj, VALUE method) {
return rb_obj_method(obj, method);
}
-#ifndef RUBY_VERSION_IS_3_2
-static VALUE object_spec_rb_obj_taint(VALUE self, VALUE obj) {
- return rb_obj_taint(obj);
-}
-#endif
-
static VALUE so_require(VALUE self) {
rb_require("fixtures/foo");
return Qnil;
@@ -410,15 +383,20 @@ static VALUE object_spec_custom_alloc_func_p(VALUE self, VALUE klass) {
return allocator ? Qtrue : Qfalse;
}
+static VALUE object_spec_redefine_frozen(VALUE self) {
+ // The purpose of this spec is to verify that `frozen?`
+ // and `RB_OBJ_FROZEN` do not mutually recurse infinitely.
+ if (RB_OBJ_FROZEN(self)) {
+ return Qtrue;
+ }
+
+ return 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);
@@ -443,15 +421,11 @@ void Init_object_spec(void) {
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);
-#ifndef RUBY_VERSION_IS_3_2
- rb_define_method(cls, "rb_obj_taint", object_spec_rb_obj_taint, 1);
-#endif
rb_define_method(cls, "rb_require", so_require, 0);
rb_define_method(cls, "rb_respond_to", so_respond_to, 2);
rb_define_method(cls, "rb_method_boundp", object_spec_rb_method_boundp, 3);
rb_define_method(cls, "rb_obj_respond_to", so_obj_respond_to, 3);
rb_define_method(cls, "rb_special_const_p", object_spec_rb_special_const_p, 1);
-
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);
@@ -491,6 +465,9 @@ void Init_object_spec(void) {
rb_define_method(cls, "custom_alloc_func?", object_spec_custom_alloc_func_p, 1);
rb_define_method(cls, "not_implemented_method", rb_f_notimplement, -1);
rb_define_method(cls, "rb_ivar_foreach", object_spec_rb_ivar_foreach, 1);
+
+ cls = rb_define_class("CApiObjectRedefinitionSpecs", rb_cObject);
+ rb_define_method(cls, "frozen?", object_spec_redefine_frozen, 0);
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/ext/range_spec.c b/spec/ruby/optional/capi/ext/range_spec.c
index b0cf1a8662..9faed3e5ee 100644
--- a/spec/ruby/optional/capi/ext/range_spec.c
+++ b/spec/ruby/optional/capi/ext/range_spec.c
@@ -25,9 +25,9 @@ VALUE range_spec_rb_range_values(VALUE self, VALUE range) {
return ary;
}
-VALUE range_spec_rb_range_beg_len(VALUE self, VALUE range, VALUE begpv, VALUE lenpv, VALUE lenv, VALUE errv) {
- long begp = FIX2LONG(begpv);
- long lenp = FIX2LONG(lenpv);
+VALUE range_spec_rb_range_beg_len(VALUE self, VALUE range, VALUE lenv, VALUE errv) {
+ long begp = 0;
+ long lenp = 0;
long len = FIX2LONG(lenv);
int err = FIX2INT(errv);
VALUE ary = rb_ary_new();
@@ -38,11 +38,51 @@ VALUE range_spec_rb_range_beg_len(VALUE self, VALUE range, VALUE begpv, VALUE le
return ary;
}
+VALUE range_spec_rb_arithmetic_sequence_extract(VALUE self, VALUE object) {
+ VALUE ary = rb_ary_new();
+ rb_arithmetic_sequence_components_t components;
+
+ int status = rb_arithmetic_sequence_extract(object, &components);
+
+ if (!status) {
+ rb_ary_store(ary, 0, LONG2FIX(status));
+ return ary;
+ }
+
+ rb_ary_store(ary, 0, LONG2FIX(status));
+ rb_ary_store(ary, 1, components.begin);
+ rb_ary_store(ary, 2, components.end);
+ rb_ary_store(ary, 3, components.step);
+ rb_ary_store(ary, 4, components.exclude_end ? Qtrue : Qfalse);
+ return ary;
+}
+
+VALUE range_spec_rb_arithmetic_sequence_beg_len_step(VALUE self, VALUE aseq, VALUE lenv, VALUE errv) {
+ long begp = 0;
+ long lenp = 0;
+ long stepp = 0;
+
+ long len = FIX2LONG(lenv);
+ int err = FIX2INT(errv);
+
+ VALUE success = rb_arithmetic_sequence_beg_len_step(aseq, &begp, &lenp, &stepp, len, err);
+
+ VALUE ary = rb_ary_new();
+ rb_ary_store(ary, 0, success);
+ rb_ary_store(ary, 1, LONG2FIX(begp));
+ rb_ary_store(ary, 2, LONG2FIX(lenp));
+ rb_ary_store(ary, 3, LONG2FIX(stepp));
+
+ return ary;
+}
+
void Init_range_spec(void) {
VALUE cls = rb_define_class("CApiRangeSpecs", rb_cObject);
rb_define_method(cls, "rb_range_new", range_spec_rb_range_new, -1);
rb_define_method(cls, "rb_range_values", range_spec_rb_range_values, 1);
- rb_define_method(cls, "rb_range_beg_len", range_spec_rb_range_beg_len, 5);
+ rb_define_method(cls, "rb_range_beg_len", range_spec_rb_range_beg_len, 3);
+ rb_define_method(cls, "rb_arithmetic_sequence_extract", range_spec_rb_arithmetic_sequence_extract, 1);
+ rb_define_method(cls, "rb_arithmetic_sequence_beg_len_step", range_spec_rb_arithmetic_sequence_beg_len_step, 3);
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/ext/rbasic_spec.c b/spec/ruby/optional/capi/ext/rbasic_spec.c
index 26be2fed6d..5a95b92804 100644
--- a/spec/ruby/optional/capi/ext/rbasic_spec.c
+++ b/spec/ruby/optional/capi/ext/rbasic_spec.c
@@ -31,13 +31,6 @@ static const VALUE DATA_VISIBLE_BITS = FL_FREEZE | ~(FL_USER0 - 1);
#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);
}
@@ -93,9 +86,6 @@ static VALUE rbasic_rdata_spec_get_klass(VALUE self, VALUE structure) {
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);
diff --git a/spec/ruby/optional/capi/ext/rubyspec.h b/spec/ruby/optional/capi/ext/rubyspec.h
index 09135774af..6c4bea5da0 100644
--- a/spec/ruby/optional/capi/ext/rubyspec.h
+++ b/spec/ruby/optional/capi/ext/rubyspec.h
@@ -5,11 +5,7 @@
* guards to assist with version incompatibilities. */
#include <ruby.h>
-#ifdef HAVE_RUBY_VERSION_H
-# include <ruby/version.h>
-#else
-# include <version.h>
-#endif
+#include <ruby/version.h>
/* copied from ext/-test-/cxxanyargs/cxxanyargs.cpp */
#if 0 /* Ignore deprecation warnings */
@@ -34,32 +30,21 @@
#endif
-#ifndef RUBY_VERSION_MAJOR
-#define RUBY_VERSION_MAJOR RUBY_API_VERSION_MAJOR
-#define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
-#define RUBY_VERSION_TEENY RUBY_API_VERSION_TEENY
-#endif
-
-#define RUBY_VERSION_BEFORE(major,minor,teeny) \
- ((RUBY_VERSION_MAJOR < (major)) || \
- (RUBY_VERSION_MAJOR == (major) && RUBY_VERSION_MINOR < (minor)) || \
- (RUBY_VERSION_MAJOR == (major) && RUBY_VERSION_MINOR == (minor) && RUBY_VERSION_TEENY < (teeny)))
-#define RUBY_VERSION_SINCE(major,minor,teeny) (!RUBY_VERSION_BEFORE(major, minor, teeny))
+#define RUBY_VERSION_BEFORE(major,minor) \
+ ((RUBY_API_VERSION_MAJOR < (major)) || \
+ (RUBY_API_VERSION_MAJOR == (major) && RUBY_API_VERSION_MINOR < (minor)))
+#define RUBY_VERSION_SINCE(major,minor) (!RUBY_VERSION_BEFORE(major, minor))
-#if RUBY_VERSION_SINCE(3, 3, 0)
-#define RUBY_VERSION_IS_3_3
-#endif
-
-#if RUBY_VERSION_SINCE(3, 2, 0)
-#define RUBY_VERSION_IS_3_2
+#if RUBY_VERSION_SINCE(4, 0)
+#define RUBY_VERSION_IS_4_0
#endif
-#if RUBY_VERSION_SINCE(3, 1, 0)
-#define RUBY_VERSION_IS_3_1
+#if RUBY_VERSION_SINCE(3, 4)
+#define RUBY_VERSION_IS_3_4
#endif
-#if RUBY_VERSION_SINCE(3, 0, 0)
-#define RUBY_VERSION_IS_3_0
+#if RUBY_VERSION_SINCE(3, 3)
+#define RUBY_VERSION_IS_3_3
#endif
#endif
diff --git a/spec/ruby/optional/capi/ext/set_spec.c b/spec/ruby/optional/capi/ext/set_spec.c
new file mode 100644
index 0000000000..11a271b361
--- /dev/null
+++ b/spec/ruby/optional/capi/ext/set_spec.c
@@ -0,0 +1,65 @@
+#include "ruby.h"
+#include "rubyspec.h"
+
+#ifdef RUBY_VERSION_IS_4_0
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RBOOL(x) ((x) ? Qtrue : Qfalse)
+
+int yield_element_and_arg(VALUE element, VALUE arg) {
+ return RTEST(rb_yield_values(2, element, arg)) ? ST_CONTINUE : ST_STOP;
+}
+
+VALUE set_spec_rb_set_foreach(VALUE self, VALUE set, VALUE arg) {
+ rb_set_foreach(set, yield_element_and_arg, arg);
+ return Qnil;
+}
+
+VALUE set_spec_rb_set_new(VALUE self) {
+ return rb_set_new();
+}
+
+VALUE set_spec_rb_set_new_capa(VALUE self, VALUE capa) {
+ return rb_set_new_capa(NUM2INT(capa));
+}
+
+VALUE set_spec_rb_set_lookup(VALUE self, VALUE set, VALUE element) {
+ return RBOOL(rb_set_lookup(set, element));
+}
+
+VALUE set_spec_rb_set_add(VALUE self, VALUE set, VALUE element) {
+ return RBOOL(rb_set_add(set, element));
+}
+
+VALUE set_spec_rb_set_clear(VALUE self, VALUE set) {
+ return rb_set_clear(set);
+}
+
+VALUE set_spec_rb_set_delete(VALUE self, VALUE set, VALUE element) {
+ return RBOOL(rb_set_delete(set, element));
+}
+
+VALUE set_spec_rb_set_size(VALUE self, VALUE set) {
+ return SIZET2NUM(rb_set_size(set));
+}
+
+void Init_set_spec(void) {
+ VALUE cls = rb_define_class("CApiSetSpecs", rb_cObject);
+
+ rb_define_method(cls, "rb_set_foreach", set_spec_rb_set_foreach, 2);
+ rb_define_method(cls, "rb_set_new", set_spec_rb_set_new, 0);
+ rb_define_method(cls, "rb_set_new_capa", set_spec_rb_set_new_capa, 1);
+ rb_define_method(cls, "rb_set_lookup", set_spec_rb_set_lookup, 2);
+ rb_define_method(cls, "rb_set_add", set_spec_rb_set_add, 2);
+ rb_define_method(cls, "rb_set_clear", set_spec_rb_set_clear, 1);
+ rb_define_method(cls, "rb_set_delete", set_spec_rb_set_delete, 2);
+ rb_define_method(cls, "rb_set_size", set_spec_rb_set_size, 1);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/spec/ruby/optional/capi/ext/string_spec.c b/spec/ruby/optional/capi/ext/string_spec.c
index cec3f65f45..094013e049 100644
--- a/spec/ruby/optional/capi/ext/string_spec.c
+++ b/spec/ruby/optional/capi/ext/string_spec.c
@@ -117,6 +117,10 @@ VALUE string_spec_rb_str_cmp(VALUE self, VALUE str1, VALUE str2) {
return INT2NUM(rb_str_cmp(str1, str2));
}
+VALUE string_spec_rb_str_strlen(VALUE self, VALUE str) {
+ return LONG2NUM(rb_str_strlen(str));
+}
+
VALUE string_spec_rb_str_conv_enc(VALUE self, VALUE str, VALUE from, VALUE to) {
rb_encoding* from_enc;
rb_encoding* to_enc;
@@ -248,16 +252,6 @@ VALUE string_spec_rb_str_new5(VALUE self, VALUE str, VALUE ptr, VALUE len) {
return rb_str_new5(str, RSTRING_PTR(ptr), FIX2INT(len));
}
-#ifndef RUBY_VERSION_IS_3_2
-VALUE string_spec_rb_tainted_str_new(VALUE self, VALUE str, VALUE len) {
- return rb_tainted_str_new(RSTRING_PTR(str), FIX2INT(len));
-}
-
-VALUE string_spec_rb_tainted_str_new2(VALUE self, VALUE str) {
- return rb_tainted_str_new2(RSTRING_PTR(str));
-}
-#endif
-
VALUE string_spec_rb_str_plus(VALUE self, VALUE str1, VALUE str2) {
return rb_str_plus(str1, str2);
}
@@ -446,6 +440,7 @@ static VALUE string_spec_rb_str_free(VALUE self, VALUE str) {
static VALUE string_spec_rb_sprintf1(VALUE self, VALUE str, VALUE repl) {
return rb_sprintf(RSTRING_PTR(str), RSTRING_PTR(repl));
}
+
static VALUE string_spec_rb_sprintf2(VALUE self, VALUE str, VALUE repl1, VALUE repl2) {
return rb_sprintf(RSTRING_PTR(str), RSTRING_PTR(repl1), RSTRING_PTR(repl2));
}
@@ -577,6 +572,11 @@ static VALUE string_spec_rb_enc_interned_str_cstr(VALUE self, VALUE str, VALUE e
return rb_enc_interned_str_cstr(RSTRING_PTR(str), e);
}
+static VALUE string_spec_rb_enc_interned_str(VALUE self, VALUE str, VALUE len, VALUE enc) {
+ rb_encoding *e = NIL_P(enc) ? 0 : rb_to_encoding(enc);
+ return rb_enc_interned_str(RSTRING_PTR(str), FIX2LONG(len), e);
+}
+
static VALUE string_spec_rb_str_to_interned_str(VALUE self, VALUE str) {
return rb_str_to_interned_str(str);
}
@@ -600,6 +600,7 @@ void Init_string_spec(void) {
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_strlen", string_spec_rb_str_strlen, 1);
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);
rb_define_method(cls, "rb_str_drop_bytes", string_spec_rb_str_drop_bytes, 2);
@@ -625,10 +626,6 @@ void Init_string_spec(void) {
rb_define_method(cls, "rb_str_new3", string_spec_rb_str_new3, 1);
rb_define_method(cls, "rb_str_new4", string_spec_rb_str_new4, 1);
rb_define_method(cls, "rb_str_new5", string_spec_rb_str_new5, 3);
-#ifndef RUBY_VERSION_IS_3_2
- rb_define_method(cls, "rb_tainted_str_new", string_spec_rb_tainted_str_new, 2);
- rb_define_method(cls, "rb_tainted_str_new2", string_spec_rb_tainted_str_new2, 1);
-#endif
rb_define_method(cls, "rb_str_plus", string_spec_rb_str_plus, 2);
rb_define_method(cls, "rb_str_times", string_spec_rb_str_times, 2);
rb_define_method(cls, "rb_str_modify_expand", string_spec_rb_str_modify_expand, 2);
@@ -682,6 +679,7 @@ void Init_string_spec(void) {
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);
rb_define_method(cls, "rb_enc_interned_str_cstr", string_spec_rb_enc_interned_str_cstr, 2);
+ rb_define_method(cls, "rb_enc_interned_str", string_spec_rb_enc_interned_str, 3);
rb_define_method(cls, "rb_str_to_interned_str", string_spec_rb_str_to_interned_str, 1);
}
diff --git a/spec/ruby/optional/capi/ext/struct_spec.c b/spec/ruby/optional/capi/ext/struct_spec.c
index 9c45bd5672..756cfca8dd 100644
--- a/spec/ruby/optional/capi/ext/struct_spec.c
+++ b/spec/ruby/optional/capi/ext/struct_spec.c
@@ -28,7 +28,7 @@ static VALUE struct_spec_rb_struct_aset(VALUE self, VALUE st, VALUE key, VALUE v
}
/* Only allow setting three attributes, should be sufficient for testing. */
-static VALUE struct_spec_struct_define(VALUE self, VALUE name,
+static VALUE struct_spec_rb_struct_define(VALUE self, VALUE name,
VALUE attr1, VALUE attr2, VALUE attr3) {
const char *a1 = StringValuePtr(attr1);
@@ -42,7 +42,7 @@ static VALUE struct_spec_struct_define(VALUE self, VALUE name,
}
/* Only allow setting three attributes, should be sufficient for testing. */
-static VALUE struct_spec_struct_define_under(VALUE self, VALUE outer,
+static VALUE struct_spec_rb_struct_define_under(VALUE self, VALUE outer,
VALUE name, VALUE attr1, VALUE attr2, VALUE attr3) {
const char *nm = StringValuePtr(name);
@@ -62,6 +62,27 @@ static VALUE struct_spec_rb_struct_size(VALUE self, VALUE st) {
return rb_struct_size(st);
}
+static VALUE struct_spec_rb_struct_initialize(VALUE self, VALUE st, VALUE values) {
+ return rb_struct_initialize(st, values);
+}
+
+#if defined(RUBY_VERSION_IS_3_3)
+/* Only allow setting three attributes, should be sufficient for testing. */
+static VALUE struct_spec_rb_data_define(VALUE self, VALUE superclass,
+ VALUE attr1, VALUE attr2, VALUE attr3) {
+
+ const char *a1 = StringValuePtr(attr1);
+ const char *a2 = StringValuePtr(attr2);
+ const char *a3 = StringValuePtr(attr3);
+
+ if (superclass == Qnil) {
+ superclass = 0;
+ }
+
+ return rb_data_define(superclass, a1, a2, a3, NULL);
+}
+#endif
+
void Init_struct_spec(void) {
VALUE cls = rb_define_class("CApiStructSpecs", rb_cObject);
rb_define_method(cls, "rb_struct_aref", struct_spec_rb_struct_aref, 2);
@@ -69,10 +90,14 @@ void Init_struct_spec(void) {
rb_define_method(cls, "rb_struct_s_members", struct_spec_rb_struct_s_members, 1);
rb_define_method(cls, "rb_struct_members", struct_spec_rb_struct_members, 1);
rb_define_method(cls, "rb_struct_aset", struct_spec_rb_struct_aset, 3);
- 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_define", struct_spec_rb_struct_define, 4);
+ rb_define_method(cls, "rb_struct_define_under", struct_spec_rb_struct_define_under, 5);
rb_define_method(cls, "rb_struct_new", struct_spec_rb_struct_new, 4);
rb_define_method(cls, "rb_struct_size", struct_spec_rb_struct_size, 1);
+ rb_define_method(cls, "rb_struct_initialize", struct_spec_rb_struct_initialize, 2);
+#if defined(RUBY_VERSION_IS_3_3)
+ rb_define_method(cls, "rb_data_define", struct_spec_rb_data_define, 4);
+#endif
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/ext/thread_spec.c b/spec/ruby/optional/capi/ext/thread_spec.c
index 3511c2fbcf..ac77e4e813 100644
--- a/spec/ruby/optional/capi/ext/thread_spec.c
+++ b/spec/ruby/optional/capi/ext/thread_spec.c
@@ -118,7 +118,6 @@ static VALUE thread_spec_rb_thread_wait_for(VALUE self, VALUE s, VALUE ms) {
return Qnil;
}
-
VALUE thread_spec_call_proc(void *arg_ptr) {
VALUE arg_array = (VALUE)arg_ptr;
VALUE arg = rb_ary_pop(arg_array);
@@ -167,6 +166,12 @@ static VALUE thread_spec_ruby_native_thread_p_new_thread(VALUE self) {
#endif
}
+#ifdef RUBY_VERSION_IS_4_0
+static VALUE thread_spec_ruby_thread_has_gvl_p(VALUE self) {
+ return ruby_thread_has_gvl_p() ? Qtrue : Qfalse;
+}
+#endif
+
void Init_thread_spec(void) {
VALUE cls = rb_define_class("CApiThreadSpecs", rb_cObject);
rb_define_method(cls, "rb_thread_alone", thread_spec_rb_thread_alone, 0);
@@ -180,6 +185,9 @@ void Init_thread_spec(void) {
rb_define_method(cls, "rb_thread_create", thread_spec_rb_thread_create, 2);
rb_define_method(cls, "ruby_native_thread_p", thread_spec_ruby_native_thread_p, 0);
rb_define_method(cls, "ruby_native_thread_p_new_thread", thread_spec_ruby_native_thread_p_new_thread, 0);
+#ifdef RUBY_VERSION_IS_4_0
+ rb_define_method(cls, "ruby_thread_has_gvl_p", thread_spec_ruby_thread_has_gvl_p, 0);
+#endif
}
#ifdef __cplusplus
diff --git a/spec/ruby/optional/capi/ext/typed_data_spec.c b/spec/ruby/optional/capi/ext/typed_data_spec.c
index 38889ecf5c..221f1c8ac4 100644
--- a/spec/ruby/optional/capi/ext/typed_data_spec.c
+++ b/spec/ruby/optional/capi/ext/typed_data_spec.c
@@ -106,6 +106,8 @@ VALUE sws_typed_wrap_struct(VALUE self, VALUE val) {
return TypedData_Wrap_Struct(rb_cObject, &sample_typed_wrapped_struct_data_type, bar);
}
+#undef RUBY_UNTYPED_DATA_WARNING
+#define RUBY_UNTYPED_DATA_WARNING 0
VALUE sws_untyped_wrap_struct(VALUE self, VALUE val) {
int* data = (int*) malloc(sizeof(int));
*data = FIX2INT(val);
diff --git a/spec/ruby/optional/capi/fiber_spec.rb b/spec/ruby/optional/capi/fiber_spec.rb
index 357033f860..05d867498c 100644
--- a/spec/ruby/optional/capi/fiber_spec.rb
+++ b/spec/ruby/optional/capi/fiber_spec.rb
@@ -1,5 +1,4 @@
require_relative 'spec_helper'
-require 'fiber'
load_extension('fiber')
@@ -49,41 +48,39 @@ describe "C-API Fiber function" do
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
+ 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
+ fiber.resume
- result = @s.rb_fiber_raise(fiber, "Boom!")
- result.should be_an_instance_of(RuntimeError)
- result.message.should == "Boom!"
- end
+ 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
+ it "raises an exception on the transferred fiber" do
+ main = Fiber.current
- fiber = Fiber.new do
- begin
- main.transfer
- rescue => error
- error
- end
+ fiber = Fiber.new do
+ begin
+ main.transfer
+ rescue => error
+ error
end
+ end
- fiber.transfer
+ fiber.transfer
- result = @s.rb_fiber_raise(fiber, "Boom!")
- result.should be_an_instance_of(RuntimeError)
- result.message.should == "Boom!"
- end
+ result = @s.rb_fiber_raise(fiber, "Boom!")
+ result.should be_an_instance_of(RuntimeError)
+ result.message.should == "Boom!"
end
end
end
diff --git a/spec/ruby/optional/capi/finalizer_spec.rb b/spec/ruby/optional/capi/finalizer_spec.rb
new file mode 100644
index 0000000000..162e8ea693
--- /dev/null
+++ b/spec/ruby/optional/capi/finalizer_spec.rb
@@ -0,0 +1,40 @@
+require_relative "spec_helper"
+
+extension_path = load_extension("finalizer")
+
+describe "CApiFinalizerSpecs" do
+ before :each do
+ @s = CApiFinalizerSpecs.new
+ end
+
+ describe "rb_define_finalizer" do
+ it "defines a finalizer on the object" do
+ code = <<~RUBY
+ require #{extension_path.dump}
+
+ obj = Object.new
+ finalizer = Proc.new { puts "finalizer run" }
+ CApiFinalizerSpecs.new.rb_define_finalizer(obj, finalizer)
+ RUBY
+
+ ruby_exe(code).should == "finalizer run\n"
+ end
+ end
+
+ describe "rb_undefine_finalizer" do
+ ruby_bug "#20981", "3.4.0"..."3.4.2" do
+ it "removes finalizers from the object" do
+ code = <<~RUBY
+ require #{extension_path.dump}
+
+ obj = Object.new
+ finalizer = Proc.new { puts "finalizer run" }
+ ObjectSpace.define_finalizer(obj, finalizer)
+ CApiFinalizerSpecs.new.rb_undefine_finalizer(obj)
+ RUBY
+
+ ruby_exe(code).should.empty?
+ end
+ end
+ end
+end
diff --git a/spec/ruby/optional/capi/fixnum_spec.rb b/spec/ruby/optional/capi/fixnum_spec.rb
index aa02a0543b..e691aa3893 100644
--- a/spec/ruby/optional/capi/fixnum_spec.rb
+++ b/spec/ruby/optional/capi/fixnum_spec.rb
@@ -25,7 +25,7 @@ describe "CApiFixnumSpecs" do
end
end
- platform_is wordsize: 64 do # sizeof(long) > sizeof(int)
+ platform_is c_long_size: 64 do # sizeof(long) > sizeof(int)
it "raises a TypeError if passed nil" do
-> { @s.FIX2INT(nil) }.should raise_error(TypeError)
end
@@ -74,7 +74,7 @@ describe "CApiFixnumSpecs" do
end
end
- platform_is wordsize: 64 do # sizeof(long) > sizeof(int)
+ platform_is c_long_size: 64 do # sizeof(long) > sizeof(int)
it "raises a TypeError if passed nil" do
-> { @s.FIX2UINT(nil) }.should raise_error(TypeError)
end
diff --git a/spec/ruby/optional/capi/globals_spec.rb b/spec/ruby/optional/capi/globals_spec.rb
index 48677620bc..4657293e15 100644
--- a/spec/ruby/optional/capi/globals_spec.rb
+++ b/spec/ruby/optional/capi/globals_spec.rb
@@ -41,14 +41,19 @@ describe "CApiGlobalSpecs" do
@f.sb_get_global_value.should == "XYZ"
end
+ run = 0
+
it "rb_define_readonly_variable should define a new readonly global variable" do
+ name = "ro_gvar#{run += 1}"
+ eval <<~RUBY
# Check the gvar doesn't exist and ensure rb_gv_get doesn't implicitly declare the gvar,
# otherwise the rb_define_readonly_variable call will conflict.
- suppress_warning { @f.sb_gv_get("ro_gvar") } .should == nil
+ suppress_warning { @f.sb_gv_get("#{name}") }.should == nil
- @f.rb_define_readonly_variable("ro_gvar", 15)
- $ro_gvar.should == 15
- -> { $ro_gvar = 10 }.should raise_error(NameError)
+ @f.rb_define_readonly_variable("#{name}", 15)
+ $#{name}.should == 15
+ -> { $#{name} = 10 }.should raise_error(NameError)
+ RUBY
end
it "rb_define_hooked_variable should define a C hooked global variable" do
diff --git a/spec/ruby/optional/capi/hash_spec.rb b/spec/ruby/optional/capi/hash_spec.rb
index a0e49ffc4c..3a27de3bfa 100644
--- a/spec/ruby/optional/capi/hash_spec.rb
+++ b/spec/ruby/optional/capi/hash_spec.rb
@@ -50,19 +50,17 @@ describe "C-API Hash function" do
end
end
- ruby_version_is '3.2' do
- describe "rb_hash_new_capa" do
- it "returns a new hash" do
- @s.rb_hash_new_capa(3).should == {}
- end
+ describe "rb_hash_new_capa" do
+ it "returns a new hash" do
+ @s.rb_hash_new_capa(3).should == {}
+ end
- it "creates a hash with no default proc" do
- @s.rb_hash_new_capa(3) {}.default_proc.should be_nil
- end
+ it "creates a hash with no default proc" do
+ @s.rb_hash_new_capa(3) {}.default_proc.should be_nil
+ end
- it "raises RuntimeError when negative index is provided" do
- -> { @s.rb_hash_new_capa(-1) }.should raise_error(RuntimeError, "st_table too big")
- end
+ it "raises RuntimeError when negative index is provided" do
+ -> { @s.rb_hash_new_capa(-1) }.should raise_error(RuntimeError, "st_table too big")
end
end
@@ -194,6 +192,61 @@ describe "C-API Hash function" do
end
end
+ describe "rb_hash_bulk_insert" do
+ it 'inserts key-value pairs into the hash' do
+ arr = [:a, 1, :b, 2, :c, 3]
+ hash = {}
+
+ @s.rb_hash_bulk_insert(arr.length, arr, hash)
+
+ hash.should == {a: 1, b: 2, c: 3}
+ end
+
+ it 'overwrites existing keys' do
+ arr = [:a, 4, :b, 5, :c, 6]
+ hash = {a: 1, b: 2}
+
+ @s.rb_hash_bulk_insert(arr.length, arr, hash)
+
+ hash.should == {a: 4, b: 5, c: 6}
+ end
+
+ it 'uses the last key in the array if it appears multiple times' do
+ arr = [:a, 1, :b, 2, :a, 3]
+ hash = {}
+
+ @s.rb_hash_bulk_insert(arr.length, arr, hash)
+
+ hash.should == {a: 3, b: 2}
+ end
+
+ it 'allows the array to be NULL if the length is zero' do
+ hash = {}
+
+ @s.rb_hash_bulk_insert(0, nil, hash)
+
+ hash.should == {}
+ end
+
+ it 'does not include any keys after the given length' do
+ arr = [:a, 1, :b, 2, :c, 3, :d, 4]
+ hash = {}
+
+ @s.rb_hash_bulk_insert(arr.length - 2, arr, hash)
+
+ hash.should == {a: 1, b: 2, c: 3}
+ end
+
+ it 'does not modify the hash if the length is zero' do
+ arr = []
+ hash = {a: 1, b: 2}
+
+ @s.rb_hash_bulk_insert(arr.length, arr, hash)
+
+ hash.should == {a: 1, b: 2}
+ end
+ end
+
describe "rb_hash_size" do
it "returns the size of the hash" do
hsh = {fast: 'car', good: 'music'}
diff --git a/spec/ruby/optional/capi/integer_spec.rb b/spec/ruby/optional/capi/integer_spec.rb
index 089872381c..f177374569 100644
--- a/spec/ruby/optional/capi/integer_spec.rb
+++ b/spec/ruby/optional/capi/integer_spec.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
require_relative 'spec_helper'
load_extension("integer")
diff --git a/spec/ruby/optional/capi/io_spec.rb b/spec/ruby/optional/capi/io_spec.rb
index 870abef3ea..ab7a7fc8f6 100644
--- a/spec/ruby/optional/capi/io_spec.rb
+++ b/spec/ruby/optional/capi/io_spec.rb
@@ -1,4 +1,5 @@
require_relative 'spec_helper'
+require_relative '../../fixtures/io'
load_extension('io')
@@ -261,24 +262,38 @@ describe "C-API IO function" do
end
end
- ruby_version_is "3.1" do
- describe "rb_io_maybe_wait_writable" do
- it "returns mask for events if operation was interrupted" do
- @o.rb_io_maybe_wait_writable(Errno::EINTR::Errno, @w_io, nil).should == IO::WRITABLE
- end
+ describe "rb_io_maybe_wait_writable" do
+ it "returns mask for events if operation was interrupted" do
+ @o.rb_io_maybe_wait_writable(Errno::EINTR::Errno, @w_io, nil).should == IO::WRITABLE
+ end
- it "returns 0 if there is no error condition" do
- @o.rb_io_maybe_wait_writable(0, @w_io, nil).should == 0
- end
+ it "returns 0 if there is no error condition" do
+ @o.rb_io_maybe_wait_writable(0, @w_io, nil).should == 0
+ end
- it "raises an IOError if the IO is closed" do
- @w_io.close
- -> { @o.rb_io_maybe_wait_writable(0, @w_io, nil) }.should raise_error(IOError, "closed stream")
- end
+ it "raises an IOError if the IO is closed" do
+ @w_io.close
+ -> { @o.rb_io_maybe_wait_writable(0, @w_io, nil) }.should raise_error(IOError, "closed stream")
+ end
- it "raises an IOError if the IO is not initialized" do
- -> { @o.rb_io_maybe_wait_writable(0, IO.allocate, nil) }.should raise_error(IOError, "uninitialized stream")
+ it "raises an IOError if the IO is not initialized" do
+ -> { @o.rb_io_maybe_wait_writable(0, IO.allocate, nil) }.should raise_error(IOError, "uninitialized stream")
+ end
+
+ it "can be interrupted" do
+ IOSpec.exhaust_write_buffer(@w_io)
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+
+ t = Thread.new do
+ @o.rb_io_maybe_wait_writable(0, @w_io, 10)
end
+
+ Thread.pass until t.stop?
+ t.kill
+ t.join
+
+ finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ (finish - start).should < 9
end
end
@@ -332,37 +347,50 @@ describe "C-API IO function" do
end
end
- ruby_version_is "3.1" do
- describe "rb_io_maybe_wait_readable" do
- it "returns mask for events if operation was interrupted" do
- @o.rb_io_maybe_wait_readable(Errno::EINTR::Errno, @r_io, nil, false).should == IO::READABLE
- end
+ describe "rb_io_maybe_wait_readable" do
+ it "returns mask for events if operation was interrupted" do
+ @o.rb_io_maybe_wait_readable(Errno::EINTR::Errno, @r_io, nil, false).should == IO::READABLE
+ end
- it "returns 0 if there is no error condition" do
- @o.rb_io_maybe_wait_readable(0, @r_io, nil, false).should == 0
+ it "returns 0 if there is no error condition" do
+ @o.rb_io_maybe_wait_readable(0, @r_io, nil, false).should == 0
+ end
+
+ it "blocks until the io is readable and returns events that actually occurred" do
+ @o.instance_variable_set :@write_data, false
+ thr = Thread.new do
+ Thread.pass until @o.instance_variable_get(:@write_data)
+ @w_io.write "rb_io_wait_readable"
end
- it "blocks until the io is readable and returns events that actually occurred" do
- @o.instance_variable_set :@write_data, false
- thr = Thread.new do
- Thread.pass until @o.instance_variable_get(:@write_data)
- @w_io.write "rb_io_wait_readable"
- end
+ @o.rb_io_maybe_wait_readable(Errno::EAGAIN::Errno, @r_io, IO::READABLE, true).should == IO::READABLE
+ @o.instance_variable_get(:@read_data).should == "rb_io_wait_re"
+
+ thr.join
+ end
- @o.rb_io_maybe_wait_readable(Errno::EAGAIN::Errno, @r_io, IO::READABLE, true).should == IO::READABLE
- @o.instance_variable_get(:@read_data).should == "rb_io_wait_re"
+ it "can be interrupted" do
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
- thr.join
+ t = Thread.new do
+ @o.rb_io_maybe_wait_readable(0, @r_io, 10, false)
end
- it "raises an IOError if the IO is closed" do
- @r_io.close
- -> { @o.rb_io_maybe_wait_readable(0, @r_io, nil, false) }.should raise_error(IOError, "closed stream")
- end
+ Thread.pass until t.stop?
+ t.kill
+ t.join
- it "raises an IOError if the IO is not initialized" do
- -> { @o.rb_io_maybe_wait_readable(0, IO.allocate, nil, false) }.should raise_error(IOError, "uninitialized stream")
- end
+ finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ (finish - start).should < 9
+ end
+
+ it "raises an IOError if the IO is closed" do
+ @r_io.close
+ -> { @o.rb_io_maybe_wait_readable(0, @r_io, nil, false) }.should raise_error(IOError, "closed stream")
+ end
+
+ it "raises an IOError if the IO is not initialized" do
+ -> { @o.rb_io_maybe_wait_readable(0, IO.allocate, nil, false) }.should raise_error(IOError, "uninitialized stream")
end
end
end
@@ -405,39 +433,64 @@ describe "C-API IO function" do
end
end
- ruby_version_is "3.1" do
- describe "rb_io_maybe_wait" do
- it "waits til an fd is ready for reading" do
- start = false
- thr = Thread.new do
- start = true
- sleep 0.05
- @w_io.write "rb_io_maybe_wait"
- end
+ describe "rb_io_maybe_wait" do
+ it "waits til an fd is ready for reading" do
+ start = false
+ thr = Thread.new do
+ start = true
+ sleep 0.05
+ @w_io.write "rb_io_maybe_wait"
+ end
+
+ Thread.pass until start
- Thread.pass until start
+ @o.rb_io_maybe_wait(Errno::EAGAIN::Errno, @r_io, IO::READABLE, nil).should == IO::READABLE
- @o.rb_io_maybe_wait(Errno::EAGAIN::Errno, @r_io, IO::READABLE, nil).should == IO::READABLE
+ thr.join
+ end
- thr.join
- end
+ it "returns mask for events if operation was interrupted" do
+ @o.rb_io_maybe_wait(Errno::EINTR::Errno, @w_io, IO::WRITABLE, nil).should == IO::WRITABLE
+ end
- it "returns mask for events if operation was interrupted" do
- @o.rb_io_maybe_wait(Errno::EINTR::Errno, @w_io, IO::WRITABLE, nil).should == IO::WRITABLE
- end
+ it "raises an IOError if the IO is closed" do
+ @w_io.close
+ -> { @o.rb_io_maybe_wait(0, @w_io, IO::WRITABLE, nil) }.should raise_error(IOError, "closed stream")
+ end
- it "returns false if there is no error condition" do
- @o.rb_io_maybe_wait(0, @w_io, IO::WRITABLE, nil).should == false
- end
+ it "raises an IOError if the IO is not initialized" do
+ -> { @o.rb_io_maybe_wait(0, IO.allocate, IO::WRITABLE, nil) }.should raise_error(IOError, "uninitialized stream")
+ end
- it "raises an IOError if the IO is closed" do
- @w_io.close
- -> { @o.rb_io_maybe_wait(0, @w_io, IO::WRITABLE, nil) }.should raise_error(IOError, "closed stream")
+ it "can be interrupted when waiting for READABLE event" do
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+
+ t = Thread.new do
+ @o.rb_io_maybe_wait(0, @r_io, IO::READABLE, 10)
end
- it "raises an IOError if the IO is not initialized" do
- -> { @o.rb_io_maybe_wait(0, IO.allocate, IO::WRITABLE, nil) }.should raise_error(IOError, "uninitialized stream")
+ Thread.pass until t.stop?
+ t.kill
+ t.join
+
+ finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ (finish - start).should < 9
+ end
+
+ it "can be interrupted when waiting for WRITABLE event" do
+ IOSpec.exhaust_write_buffer(@w_io)
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+
+ t = Thread.new do
+ @o.rb_io_maybe_wait(0, @w_io, IO::WRITABLE, 10)
end
+
+ Thread.pass until t.stop?
+ t.kill
+ t.join
+
+ finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ (finish - start).should < 9
end
end
@@ -457,6 +510,160 @@ describe "C-API IO function" do
@o.rb_io_path(@rw_io).should == @name
end
end
+
+ describe "rb_io_closed_p" do
+ it "returns false when io is not closed" do
+ @o.rb_io_closed_p(@r_io).should == false
+ @r_io.closed?.should == false
+ end
+
+ it "returns true when io is closed" do
+ @r_io.close
+
+ @o.rb_io_closed_p(@r_io).should == true
+ @r_io.closed?.should == true
+ end
+ end
+
+ quarantine! do # "Errno::EBADF: Bad file descriptor" at closing @r_io, @rw_io etc in the after :each hook
+ describe "rb_io_open_descriptor" do
+ it "creates a new IO instance" do
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
+ io.should.is_a?(IO)
+ end
+
+ it "return an instance of the specified class" do
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
+ io.class.should == File
+
+ io = @o.rb_io_open_descriptor(IO, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
+ io.class.should == IO
+ end
+
+ it "sets the specified file descriptor" do
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
+ io.fileno.should == @r_io.fileno
+ end
+
+ it "sets the specified path" do
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
+ io.path.should == "a.txt"
+ end
+
+ it "sets the specified mode" do
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, CApiIOSpecs::FMODE_BINMODE, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
+ io.should.binmode?
+
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, CApiIOSpecs::FMODE_TEXTMODE, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
+ io.should_not.binmode?
+ end
+
+ it "sets the specified timeout" do
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
+ io.timeout.should == 60
+ end
+
+ it "sets the specified internal encoding" do
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
+ io.internal_encoding.should == Encoding::US_ASCII
+ end
+
+ it "sets the specified external encoding" do
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
+ io.external_encoding.should == Encoding::UTF_8
+ end
+
+ it "does not apply the specified encoding flags" do
+ name = tmp("rb_io_open_descriptor_specs")
+ File.write(name, "123\r\n456\n89")
+ file = File.open(name, "r")
+
+ io = @o.rb_io_open_descriptor(File, file.fileno, CApiIOSpecs::FMODE_READABLE, "a.txt", 60, "US-ASCII", "UTF-8", CApiIOSpecs::ECONV_UNIVERSAL_NEWLINE_DECORATOR, {})
+ io.read_nonblock(20).should == "123\r\n456\n89"
+ ensure
+ file.close
+ rm_r name
+ end
+
+ it "ignores the IO open options" do
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {external_encoding: "windows-1251"})
+ io.external_encoding.should == Encoding::UTF_8
+
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {internal_encoding: "windows-1251"})
+ io.internal_encoding.should == Encoding::US_ASCII
+
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {encoding: "windows-1251:binary"})
+ io.external_encoding.should == Encoding::UTF_8
+ io.internal_encoding.should == Encoding::US_ASCII
+
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {textmode: false})
+ io.should_not.binmode?
+
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {binmode: true})
+ io.should_not.binmode?
+
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {autoclose: false})
+ io.should.autoclose?
+
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, "a.txt", 60, "US-ASCII", "UTF-8", 0, {path: "a.txt"})
+ io.path.should == "a.txt"
+ end
+
+ it "ignores the IO encoding options" do
+ io = @o.rb_io_open_descriptor(File, @w_io.fileno, CApiIOSpecs::FMODE_WRITABLE, "a.txt", 60, "US-ASCII", "UTF-8", 0, {crlf_newline: true})
+
+ io.write("123\r\n456\n89")
+ io.flush
+
+ @r_io.read_nonblock(20).should == "123\r\n456\n89"
+ end
+
+ it "allows wrong mode" do
+ io = @o.rb_io_open_descriptor(File, @w_io.fileno, CApiIOSpecs::FMODE_READABLE, "a.txt", 60, "US-ASCII", "UTF-8", 0, {})
+ io.should.is_a?(File)
+
+ platform_is_not :windows do
+ -> { io.read_nonblock(1) }.should raise_error(Errno::EBADF)
+ end
+
+ platform_is :windows do
+ -> { io.read_nonblock(1) }.should raise_error(IO::EWOULDBLOCKWaitReadable)
+ end
+ end
+
+ it "tolerates NULL as rb_io_encoding *encoding parameter" do
+ io = @o.rb_io_open_descriptor_without_encoding(File, @r_io.fileno, 0, "a.txt", 60)
+ io.should.is_a?(File)
+ end
+
+ it "deduplicates path String" do
+ path = "a.txt".dup
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, path, 60, "US-ASCII", "UTF-8", 0, {})
+ io.path.should_not equal(path)
+
+ path = "a.txt".freeze
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, path, 60, "US-ASCII", "UTF-8", 0, {})
+ io.path.should_not equal(path)
+ end
+
+ it "calls #to_str to convert a path to a String" do
+ path = Object.new
+ def path.to_str; "a.txt"; end
+
+ io = @o.rb_io_open_descriptor(File, @r_io.fileno, 0, path, 60, "US-ASCII", "UTF-8", 0, {})
+
+ io.path.should == "a.txt"
+ end
+ end
+ end
+ end
+
+ ruby_version_is "3.4" do
+ describe "rb_io_maybe_wait" do
+ it "returns nil if there is no error condition" do
+ @o.rb_io_maybe_wait(0, @w_io, IO::WRITABLE, nil).should == nil
+ end
+ end
end
end
diff --git a/spec/ruby/optional/capi/kernel_spec.rb b/spec/ruby/optional/capi/kernel_spec.rb
index 3b61d4f0f1..6633ee50c1 100644
--- a/spec/ruby/optional/capi/kernel_spec.rb
+++ b/spec/ruby/optional/capi/kernel_spec.rb
@@ -3,11 +3,19 @@ require_relative 'fixtures/kernel'
kernel_path = load_extension("kernel")
+class CApiKernelSpecs::Exc < StandardError
+end
+exception_class = CApiKernelSpecs::Exc
+
describe "C-API Kernel function" do
before :each do
@s = CApiKernelSpecs.new
end
+ after :each do
+ @s.rb_errinfo.should == nil
+ end
+
describe "rb_block_given_p" do
it "returns false if no block is passed" do
@s.should_not.rb_block_given_p
@@ -78,6 +86,22 @@ describe "C-API Kernel function" do
-> { @s.rb_raise(h) }.should raise_error(TypeError)
h[:stage].should == :before
end
+
+ it "re-raises a rescued exception" do
+ -> do
+ begin
+ raise StandardError, "aaa"
+ rescue Exception
+ begin
+ @s.rb_raise({})
+ rescue TypeError
+ end
+
+ # should raise StandardError "aaa"
+ raise
+ end
+ end.should raise_error(StandardError, "aaa")
+ end
end
describe "rb_throw" do
@@ -132,26 +156,16 @@ describe "C-API Kernel function" do
end
describe "rb_warn" do
- before :each do
- @stderr, $stderr = $stderr, IOStub.new
- @verbose = $VERBOSE
- end
-
- after :each do
- $stderr = @stderr
- $VERBOSE = @verbose
- end
-
it "prints a message to $stderr if $VERBOSE evaluates to true" do
- $VERBOSE = true
- @s.rb_warn("This is a warning")
- $stderr.should =~ /This is a warning/
+ -> {
+ @s.rb_warn("This is a warning")
+ }.should complain(/warning: This is a warning/, verbose: true)
end
it "prints a message to $stderr if $VERBOSE evaluates to false" do
- $VERBOSE = false
- @s.rb_warn("This is a warning")
- $stderr.should =~ /This is a warning/
+ -> {
+ @s.rb_warn("This is a warning")
+ }.should complain(/warning: This is a warning/, verbose: false)
end
end
@@ -173,13 +187,35 @@ describe "C-API Kernel function" do
it "raises an exception from the given error" do
-> do
@s.rb_syserr_fail(Errno::EINVAL::Errno, "additional info")
- end.should raise_error(Errno::EINVAL, /additional info/)
+ end.should raise_error(Errno::EINVAL, "Invalid argument - additional info")
end
it "can take a NULL message" do
-> do
@s.rb_syserr_fail(Errno::EINVAL::Errno, nil)
- end.should raise_error(Errno::EINVAL)
+ end.should raise_error(Errno::EINVAL, "Invalid argument")
+ end
+
+ it "uses some kind of string as message when errno is unknown" do
+ -> { @s.rb_syserr_fail(-10, nil) }.should raise_error(SystemCallError, /[[:graph:]]+/)
+ end
+ end
+
+ describe "rb_syserr_fail_str" do
+ it "raises an exception from the given error" do
+ -> do
+ @s.rb_syserr_fail_str(Errno::EINVAL::Errno, "additional info")
+ end.should raise_error(Errno::EINVAL, "Invalid argument - additional info")
+ end
+
+ it "can take nil as a message" do
+ -> do
+ @s.rb_syserr_fail_str(Errno::EINVAL::Errno, nil)
+ end.should raise_error(Errno::EINVAL, "Invalid argument")
+ end
+
+ it "uses some kind of string as message when errno is unknown" do
+ -> { @s.rb_syserr_fail_str(-10, nil) }.should raise_error(SystemCallError, /[[:graph:]]+/)
end
end
@@ -206,10 +242,8 @@ describe "C-API Kernel function" do
@s.rb_yield(1) { break 73 }.should == 73
end
- platform_is_not :"solaris2.10" do # NOTE: i386-pc-solaris2.10
- it "rb_yield through a callback to a block that breaks with a value returns the value" do
- @s.rb_yield_indirected(1) { break 73 }.should == 73
- end
+ it "rb_yield through a callback to a block that breaks with a value returns the value" do
+ @s.rb_yield_indirected(1) { break 73 }.should == 73
end
it "rb_yield to block passed to enumerator" do
@@ -295,7 +329,7 @@ describe "C-API Kernel function" do
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(77, proof) { |x| raise NameError}
+ @s.rb_protect_yield(77, proof) { |x| raise NameError }
end.should raise_error(NameError)
proof[0].should == 23
end
@@ -303,7 +337,7 @@ describe "C-API Kernel function" do
it "will return nil if an error was raised" do
proof = [] # Hold proof of work performed after the yield.
-> do
- @s.rb_protect_yield(77, 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
@@ -311,14 +345,21 @@ describe "C-API Kernel function" do
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
+ @s.rb_protect_null_status(42) { |x| raise NameError }.should == nil
+ @s.rb_errinfo().should.is_a? NameError
+ ensure
+ @s.rb_set_errinfo(nil)
end
- it "populates errinfo with the captured exception" do
+ it "populates rb_errinfo() with the captured exception" do
proof = []
- @s.rb_protect_errinfo(77, proof) { |x| raise NameError }.class.should == NameError
+ @s.rb_protect_ignore_status(77, proof) { |x| raise NameError }
+ @s.rb_errinfo().should.is_a? NameError
+ # Note: on CRuby $! is the NameError here, but not clear if that is desirable or bug
proof[0].should == 23
proof[1].should == nil
+ ensure
+ @s.rb_set_errinfo(nil)
end
end
@@ -382,9 +423,21 @@ describe "C-API Kernel function" do
-> { @s.rb_rescue(@std_error_proc, nil, @std_error_proc, nil) }.should raise_error(StandardError)
end
- it "makes $! available only during the 'rescue function' execution" do
- @s.rb_rescue(@std_error_proc, nil, -> *_ { $! }, nil).class.should == StandardError
+ it "sets $! and rb_errinfo() during the 'rescue function' execution" do
+ @s.rb_rescue(-> *_ { raise exception_class, '' }, nil, -> _, exc {
+ exc.should.is_a?(exception_class)
+ $!.should.equal?(exc)
+ @s.rb_errinfo.should.equal?(exc)
+ }, nil)
+
+ @s.rb_rescue(-> _ { @s.rb_raise({}) }, nil, -> _, exc {
+ exc.should.is_a?(TypeError)
+ $!.should.equal?(exc)
+ @s.rb_errinfo.should.equal?(exc)
+ }, nil)
+
$!.should == nil
+ @s.rb_errinfo.should == nil
end
it "returns the break value if the passed function yields to a block with a break" do
@@ -402,7 +455,7 @@ describe "C-API Kernel function" do
describe "rb_rescue2" do
it "only rescues if one of the passed exceptions is raised" do
- proc = -> x { x }
+ proc = -> x, _exc { x }
arg_error_proc = -> *_ { raise ArgumentError, '' }
run_error_proc = -> *_ { raise RuntimeError, '' }
type_error_proc = -> *_ { raise Exception, 'custom error' }
@@ -418,6 +471,23 @@ describe "C-API Kernel function" do
@s.rb_rescue2(-> *_ { raise RuntimeError, "foo" }, :no_exc, -> x { x }, :exc, Object.new, 42)
}.should raise_error(TypeError, /class or module required/)
end
+
+ it "sets $! and rb_errinfo() during the 'rescue function' execution" do
+ @s.rb_rescue2(-> *_ { raise exception_class, '' }, :no_exc, -> _, exc {
+ exc.should.is_a?(exception_class)
+ $!.should.equal?(exc)
+ @s.rb_errinfo.should.equal?(exc)
+ }, :exc, exception_class, ScriptError)
+
+ @s.rb_rescue2(-> *_ { @s.rb_raise({}) }, :no_exc, -> _, exc {
+ exc.should.is_a?(TypeError)
+ $!.should.equal?(exc)
+ @s.rb_errinfo.should.equal?(exc)
+ }, :exc, TypeError, ArgumentError)
+
+ $!.should == nil
+ @s.rb_errinfo.should == nil
+ end
end
describe "rb_catch" do
@@ -470,6 +540,40 @@ describe "C-API Kernel function" do
end
end
+ describe "rb_category_warn" do
+ it "emits a warning into stderr" do
+ Warning[:deprecated] = true
+
+ -> {
+ @s.rb_category_warn_deprecated
+ }.should complain(/warning: foo/, verbose: true)
+ end
+
+ it "supports printf format modifiers" do
+ Warning[:deprecated] = true
+
+ -> {
+ @s.rb_category_warn_deprecated_with_integer_extra_value(42)
+ }.should complain(/warning: foo 42/, verbose: true)
+ end
+
+ it "does not emits a warning when a category is disabled" do
+ Warning[:deprecated] = false
+
+ -> {
+ @s.rb_category_warn_deprecated
+ }.should_not complain(verbose: true)
+ end
+
+ it "does not emits a warning when $VERBOSE is nil" do
+ Warning[:deprecated] = true
+
+ -> {
+ @s.rb_category_warn_deprecated
+ }.should_not complain(verbose: nil)
+ end
+ end
+
describe "rb_ensure" do
it "executes passed function and returns its value" do
proc = -> x { x }
@@ -486,12 +590,33 @@ describe "C-API Kernel function" do
it "executes passed 'ensure function' when an exception is raised" do
foo = nil
- raise_proc = -> { raise '' }
+ raise_proc = -> _ { raise exception_class }
ensure_proc = -> x { foo = x }
- @s.rb_ensure(raise_proc, nil, ensure_proc, :foo) rescue nil
+ -> {
+ @s.rb_ensure(raise_proc, nil, ensure_proc, :foo)
+ }.should raise_error(exception_class)
foo.should == :foo
end
+ it "sets $! and rb_errinfo() during the 'ensure function' execution" do
+ -> {
+ @s.rb_ensure(-> _ { raise exception_class }, nil, -> _ {
+ $!.should.is_a?(exception_class)
+ @s.rb_errinfo.should.is_a?(exception_class)
+ }, nil)
+ }.should raise_error(exception_class)
+
+ -> {
+ @s.rb_ensure(-> _ { @s.rb_raise({}) }, nil, -> _ {
+ $!.should.is_a?(TypeError)
+ @s.rb_errinfo.should.is_a?(TypeError)
+ }, nil)
+ }.should raise_error(TypeError)
+
+ $!.should == nil
+ @s.rb_errinfo.should == nil
+ end
+
it "raises the same exception raised inside passed function" do
raise_proc = -> *_ { raise RuntimeError, 'foo' }
proc = -> *_ { }
@@ -510,22 +635,24 @@ describe "C-API Kernel function" do
end
end
- describe "rb_eval_cmd_kw" do
- it "evaluates a string of ruby code" do
- @s.rb_eval_cmd_kw("1+1", [], 0).should == 2
- end
+ ruby_version_is ""..."4.0" do
+ describe "rb_eval_cmd_kw" do
+ it "evaluates a string of ruby code" do
+ @s.rb_eval_cmd_kw("1+1", [], 0).should == 2
+ end
- it "calls a proc with the supplied arguments" do
- @s.rb_eval_cmd_kw(-> *x { x.map { |i| i + 1 } }, [1, 3, 7], 0).should == [2, 4, 8]
- end
+ it "calls a proc with the supplied arguments" do
+ @s.rb_eval_cmd_kw(-> *x { x.map { |i| i + 1 } }, [1, 3, 7], 0).should == [2, 4, 8]
+ end
- it "calls a proc with keyword arguments if kw_splat is non zero" do
- a_proc = -> *x, **y {
- res = x.map { |i| i + 1 }
- y.each { |k, v| res << k; res << v }
- res
- }
- @s.rb_eval_cmd_kw(a_proc, [1, 3, 7, {a: 1, b: 2, c: 3}], 1).should == [2, 4, 8, :a, 1, :b, 2, :c, 3]
+ it "calls a proc with keyword arguments if kw_splat is non zero" do
+ a_proc = -> *x, **y {
+ res = x.map { |i| i + 1 }
+ y.each { |k, v| res << k; res << v }
+ res
+ }
+ @s.rb_eval_cmd_kw(a_proc, [1, 3, 7, {a: 1, b: 2, c: 3}], 1).should == [2, 4, 8, :a, 1, :b, 2, :c, 3]
+ end
end
end
@@ -787,4 +914,10 @@ describe "C-API Kernel function" do
@s.rb_check_funcall(object, :protected_method, []).should == :protected
end
end
+
+ describe "rb_str_format" do
+ it "returns a string according to format and arguments" do
+ @s.rb_str_format(3, [10, 2.5, "test"], "%d %f %s").should == "10 2.500000 test"
+ end
+ end
end
diff --git a/spec/ruby/optional/capi/module_spec.rb b/spec/ruby/optional/capi/module_spec.rb
index d7c0ab9c52..af39ec0192 100644
--- a/spec/ruby/optional/capi/module_spec.rb
+++ b/spec/ruby/optional/capi/module_spec.rb
@@ -22,6 +22,8 @@ describe "CApiModule" do
it "sets a new constant on a module" do
@m.rb_const_set(CApiModuleSpecs::C, :W, 7)
CApiModuleSpecs::C::W.should == 7
+ ensure
+ CApiModuleSpecs::C.send(:remove_const, :W)
end
it "sets an existing constant's value" do
@@ -36,7 +38,7 @@ describe "CApiModule" do
CApiModuleSpecs::C.const_set(:_INVALID, 1)
}.should raise_error(NameError, /wrong constant name/)
- @m.rb_const_set(CApiModuleSpecs::C, :_INVALID, 2)
+ suppress_warning { @m.rb_const_set(CApiModuleSpecs::C, :_INVALID, 2) }
@m.rb_const_get(CApiModuleSpecs::C, :_INVALID).should == 2
# Ruby-level should still not allow access
@@ -93,6 +95,8 @@ describe "CApiModule" do
it "defines a new constant on a module" do
@m.rb_define_const(CApiModuleSpecs::C, "V", 7)
CApiModuleSpecs::C::V.should == 7
+ ensure
+ CApiModuleSpecs::C.send(:remove_const, :V)
end
it "sets an existing constant's value" do
diff --git a/spec/ruby/optional/capi/mutex_spec.rb b/spec/ruby/optional/capi/mutex_spec.rb
index 34659974f5..71a2212e36 100644
--- a/spec/ruby/optional/capi/mutex_spec.rb
+++ b/spec/ruby/optional/capi/mutex_spec.rb
@@ -85,5 +85,18 @@ describe "C-API Mutex functions" do
callback = -> { @m.locked?.should be_true }
@s.rb_mutex_synchronize(@m, callback)
end
+
+ it "returns a value returned from a callback" do
+ callback = -> { :foo }
+ @s.rb_mutex_synchronize(@m, callback).should == :foo
+ end
+
+ it "calls a C-function that accepts and returns non-VALUE values" do
+ @s.rb_mutex_synchronize_with_naughty_callback(@m).should == 42
+ end
+
+ it "calls a native function" do
+ @s.rb_mutex_synchronize_with_native_callback(@m, 42).should == 42
+ end
end
end
diff --git a/spec/ruby/optional/capi/numeric_spec.rb b/spec/ruby/optional/capi/numeric_spec.rb
index 95213d3f2b..e9667da5ba 100644
--- a/spec/ruby/optional/capi/numeric_spec.rb
+++ b/spec/ruby/optional/capi/numeric_spec.rb
@@ -106,7 +106,7 @@ describe "CApiNumericSpecs" do
@s.NUM2LONG(5).should == 5
end
- platform_is wordsize: 32 do
+ platform_is c_long_size: 32 do
it "converts -1 to an signed number" do
@s.NUM2LONG(-1).should == -1
end
@@ -120,7 +120,7 @@ describe "CApiNumericSpecs" do
end
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
it "converts -1 to an signed number" do
@s.NUM2LONG(-1).should == -1
end
@@ -210,7 +210,7 @@ describe "CApiNumericSpecs" do
@s.NUM2ULONG(5).should == 5
end
- platform_is wordsize: 32 do
+ platform_is c_long_size: 32 do
it "converts -1 to an unsigned number" do
@s.NUM2ULONG(-1).should == 4294967295
end
@@ -231,7 +231,7 @@ describe "CApiNumericSpecs" do
end
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
it "converts -1 to an unsigned number" do
@s.NUM2ULONG(-1).should == 18446744073709551615
end
diff --git a/spec/ruby/optional/capi/object_spec.rb b/spec/ruby/optional/capi/object_spec.rb
index 7bc7bd992a..8b4d8a9bba 100644
--- a/spec/ruby/optional/capi/object_spec.rb
+++ b/spec/ruby/optional/capi/object_spec.rb
@@ -691,6 +691,16 @@ describe "CApiObject" do
end
end
+ describe "redefining frozen? works" do
+ it "allows an object to override frozen?" do
+ obj = CApiObjectRedefinitionSpecs.new
+
+ obj.frozen?.should == false
+ obj.freeze
+ obj.frozen?.should == true
+ end
+ end
+
describe "rb_obj_taint" do
end
@@ -888,7 +898,7 @@ describe "CApiObject" do
end
end
- # The `generic_iv_tbl` table and `*_generic_ivar` functions are for mutable
+ # The `generic_fields_tbl` table and `*_generic_ivar` functions are for mutable
# objects which do not store ivars directly in MRI such as RString, because
# there is no member iv_index_tbl (ivar table) such as in RObject and RClass.
diff --git a/spec/ruby/optional/capi/range_spec.rb b/spec/ruby/optional/capi/range_spec.rb
index 7a52dc7ff8..80c052e79a 100644
--- a/spec/ruby/optional/capi/range_spec.rb
+++ b/spec/ruby/optional/capi/range_spec.rb
@@ -69,7 +69,7 @@ describe "C-API Range function" do
describe "rb_range_beg_len" do
it "returns correct begin, length and result" do
r = 2..5
- begp, lenp, result = @s.rb_range_beg_len(r, 0, 0, 10, 0)
+ begp, lenp, result = @s.rb_range_beg_len(r, 10, 0)
result.should be_true
begp.should == 2
lenp.should == 4
@@ -77,19 +77,155 @@ describe "C-API Range function" do
it "returns nil when not in range" do
r = 2..5
- begp, lenp, result = @s.rb_range_beg_len(r, 0, 0, 1, 0)
+ begp, lenp, result = @s.rb_range_beg_len(r, 1, 0)
result.should be_nil
end
it "raises a RangeError when not in range and err is 1" do
r = -5..-1
- -> { @s.rb_range_beg_len(r, 0, 0, 1, 1) }.should raise_error(RangeError)
+ -> { @s.rb_range_beg_len(r, 1, 1) }.should raise_error(RangeError)
end
it "returns nil when not in range and err is 0" do
r = -5..-1
- begp, lenp, result = @s.rb_range_beg_len(r, 0, 0, 1, 0)
+ begp, lenp, result = @s.rb_range_beg_len(r, 1, 0)
result.should be_nil
end
end
+
+ describe "rb_arithmetic_sequence_extract" do
+ it "returns begin, end, step, exclude end of an instance of an Enumerator::ArithmeticSequence" do
+ enum = (10..20).step(5)
+ enum.should.kind_of?(Enumerator::ArithmeticSequence)
+
+ @s.rb_arithmetic_sequence_extract(enum).should == [1, 10, 20, 5, false]
+ end
+
+ it "returns begin, end, step, exclude end of an instance of a Range" do
+ range = (10..20)
+ @s.rb_arithmetic_sequence_extract(range).should == [1, 10, 20, 1, false]
+ end
+
+ it "returns begin, end, step, exclude end of a non-Range object with Range properties" do
+ object = Object.new
+ def object.begin
+ 10
+ end
+ def object.end
+ 20
+ end
+ def object.exclude_end?
+ false
+ end
+
+ @s.rb_arithmetic_sequence_extract(object).should == [1, 10, 20, 1, false]
+ end
+
+ it "returns failed status if given object is not Enumerator::ArithmeticSequence or Range or Range-like object" do
+ object = Object.new
+ @s.rb_arithmetic_sequence_extract(object).should == [0]
+ end
+ end
+
+ describe "rb_arithmetic_sequence_beg_len_step" do
+ it "returns correct begin, length, step and result" do
+ as = (2..5).step(5)
+ error_code = 0
+
+ success, beg, len, step = @s.rb_arithmetic_sequence_beg_len_step(as, 6, error_code)
+ success.should be_true
+
+ beg.should == 2
+ len.should == 4
+ step.should == 5
+ end
+
+ it "takes into account excluded end boundary" do
+ as = (2...5).step(1)
+ error_code = 0
+
+ success, _, len, _ = @s.rb_arithmetic_sequence_beg_len_step(as, 6, error_code)
+ success.should be_true
+ len.should == 3
+ end
+
+ it "adds length to negative begin boundary" do
+ as = (-2..5).step(1)
+ error_code = 0
+
+ success, beg, len, _ = @s.rb_arithmetic_sequence_beg_len_step(as, 6, error_code)
+ success.should be_true
+
+ beg.should == 4
+ len.should == 2
+ end
+
+ it "adds length to negative end boundary" do
+ as = (2..-1).step(1)
+ error_code = 0
+
+ success, beg, len, _ = @s.rb_arithmetic_sequence_beg_len_step(as, 6, error_code)
+ success.should be_true
+
+ beg.should == 2
+ len.should == 4
+ end
+
+ it "truncates arithmetic sequence length if end boundary greater than specified length value" do
+ as = (2..10).step(1)
+ error_code = 0
+
+ success, _, len, _ = @s.rb_arithmetic_sequence_beg_len_step(as, 6, error_code)
+ success.should be_true
+ len.should == 4
+ end
+
+ it "returns inverted begin and end boundaries when step is negative" do
+ as = (2..5).step(-2)
+ error_code = 0
+
+ success, beg, len, step = @s.rb_arithmetic_sequence_beg_len_step(as, 6, error_code)
+ success.should be_true
+
+ beg.should == 5
+ len.should == 0
+ step.should == -2
+ end
+
+ it "returns nil when not in range and error code = 0" do
+ as = (2..5).step(1)
+ error_code = 0
+
+ success, = @s.rb_arithmetic_sequence_beg_len_step(as, 1, error_code)
+ success.should be_nil
+ end
+
+ it "returns nil when not in range, negative boundaries and error code = 0" do
+ as = (-5..-1).step(1)
+ error_code = 0
+
+ success, = @s.rb_arithmetic_sequence_beg_len_step(as, 1, 0)
+ success.should be_nil
+ end
+
+ it "returns begin, length and step and doesn't raise a RangeError when not in range and error code = 1" do
+ as = (2..5).step(1)
+ error_code = 1
+
+ success, beg, len, step = @s.rb_arithmetic_sequence_beg_len_step(as, 1, error_code)
+ success.should be_true
+
+ beg.should == 2
+ len.should == 4
+ step.should == 1
+ end
+
+ it "returns nil and doesn't raise a RangeError when not in range, negative boundaries and error code = 1" do
+ as = (-5..-1).step(1)
+ error_code = 1
+
+ success, = @s.rb_arithmetic_sequence_beg_len_step(as, 1, error_code)
+ success.should be_nil
+ end
+ end
end
diff --git a/spec/ruby/optional/capi/rbasic_spec.rb b/spec/ruby/optional/capi/rbasic_spec.rb
index f3367e05ff..7b5b5b2fed 100644
--- a/spec/ruby/optional/capi/rbasic_spec.rb
+++ b/spec/ruby/optional/capi/rbasic_spec.rb
@@ -1,7 +1,9 @@
require_relative 'spec_helper'
require_relative 'shared/rbasic'
load_extension("rbasic")
-load_extension("data")
+ruby_version_is ""..."3.4" do
+ load_extension("data")
+end
load_extension("array")
describe "RBasic support for regular objects" do
@@ -12,33 +14,35 @@ describe "RBasic support for regular objects" do
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
+ruby_version_is ""..."3.4" do
+ 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 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.get_flags(obj1).should == 1 << 14 | 1 << 16 | initial
+ 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.get_flags(obj1).should == 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
+ @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
end
diff --git a/spec/ruby/optional/capi/regexp_spec.rb b/spec/ruby/optional/capi/regexp_spec.rb
index af366e17a2..49ac79f5c4 100644
--- a/spec/ruby/optional/capi/regexp_spec.rb
+++ b/spec/ruby/optional/capi/regexp_spec.rb
@@ -77,7 +77,7 @@ describe "C-API Regexp function" do
end
it "returns MatchData when used with rb_reg_match" do
- @p.rb_reg_match_backref_get(/a/, 'ab')[0].should == 'a'
+ @p.rb_reg_match_backref_get(/a/, 'ab')[0].should == 'a'
end
end
@@ -110,7 +110,7 @@ describe "C-API Regexp function" do
end
end
- describe "rb_memicmp" do
+ describe "rb_memcicmp" do
it "returns 0 for identical strings" do
@p.rb_memcicmp('Hello', 'Hello').should == 0
end
diff --git a/spec/ruby/optional/capi/set_spec.rb b/spec/ruby/optional/capi/set_spec.rb
new file mode 100644
index 0000000000..3e35be0505
--- /dev/null
+++ b/spec/ruby/optional/capi/set_spec.rb
@@ -0,0 +1,96 @@
+require_relative 'spec_helper'
+
+ruby_version_is "4.0" do
+ load_extension("set")
+
+ describe "C-API Set function" do
+ before :each do
+ @s = CApiSetSpecs.new
+ end
+
+ describe "rb_set_foreach" do
+ it "calls function with each element and arg" do
+ a = []
+ @s.rb_set_foreach(Set[1, 2], 3) {|*args| a.concat(args) }
+ a.should == [1, 3, 2, 3]
+ end
+
+ it "respects function return value" do
+ a = []
+ @s.rb_set_foreach(Set[1, 2], 3) do |*args|
+ a.concat(args)
+ false
+ end
+ a.should == [1, 3]
+ end
+ end
+
+ describe "rb_set_new" do
+ it "returns a new set" do
+ @s.rb_set_new.should == Set[]
+ end
+ end
+
+ describe "rb_set_new_capa" do
+ it "returns a new set" do
+ @s.rb_set_new_capa(3).should == Set[]
+ end
+ end
+
+ describe "rb_set_lookup" do
+ it "returns whether the element is in the set" do
+ set = Set[1]
+ @s.rb_set_lookup(set, 1).should == true
+ @s.rb_set_lookup(set, 2).should == false
+ end
+ end
+
+ describe "rb_set_add" do
+ it "adds element to set" do
+ set = Set[]
+ @s.rb_set_add(set, 1).should == true
+ set.should == Set[1]
+ @s.rb_set_add(set, 2).should == true
+ set.should == Set[1, 2]
+ end
+
+ it "returns false if element is already in set" do
+ set = Set[1]
+ @s.rb_set_add(set, 1).should == false
+ set.should == Set[1]
+ end
+ end
+
+ describe "rb_set_clear" do
+ it "empties and returns self" do
+ set = Set[1]
+ @s.rb_set_clear(set).should equal(set)
+ set.should == Set[]
+ end
+ end
+
+ describe "rb_set_delete" do
+ it "removes element from set" do
+ set = Set[1, 2]
+ @s.rb_set_delete(set, 1).should == true
+ set.should == Set[2]
+ @s.rb_set_delete(set, 2).should == true
+ set.should == Set[]
+ end
+
+ it "returns false if element is not already in set" do
+ set = Set[2]
+ @s.rb_set_delete(set, 1).should == false
+ set.should == Set[2]
+ end
+ end
+
+ describe "rb_set_size" do
+ it "returns number of elements in set" do
+ @s.rb_set_size(Set[]).should == 0
+ @s.rb_set_size(Set[1]).should == 1
+ @s.rb_set_size(Set[1,2]).should == 2
+ end
+ end
+ end
+end
diff --git a/spec/ruby/optional/capi/shared/rbasic.rb b/spec/ruby/optional/capi/shared/rbasic.rb
index 9d80a93e1d..e3485d4b7b 100644
--- a/spec/ruby/optional/capi/shared/rbasic.rb
+++ b/spec/ruby/optional/capi/shared/rbasic.rb
@@ -1,7 +1,6 @@
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
diff --git a/spec/ruby/optional/capi/spec_helper.rb b/spec/ruby/optional/capi/spec_helper.rb
index 2691aa1332..e7abf46e6c 100644
--- a/spec/ruby/optional/capi/spec_helper.rb
+++ b/spec/ruby/optional/capi/spec_helper.rb
@@ -74,12 +74,19 @@ def compile_extension(name)
init_mkmf unless required
create_makefile(ext, tmpdir)
else
+ # Workaround for digest C-API specs to find the ruby/digest.h header
+ # when run in the CRuby repository via make test-spec
+ if MSpecScript.instance_variable_defined?(:@testing_ruby)
+ ruby_repository_extra_include_dir = "-I#{RbConfig::CONFIG.fetch("prefix")}/#{RbConfig::CONFIG.fetch("EXTOUT")}/include"
+ end
+
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
append_cflags '-Wno-declaration-after-statement'
+ #{"append_cflags #{ruby_repository_extra_include_dir.inspect}" if ruby_repository_extra_include_dir}
create_makefile(#{ext.inspect})
RUBY
output = ruby_exe("extconf.rb")
@@ -115,13 +122,9 @@ def setup_make
opts = {}
if /(?:\A|\s)--jobserver-(?:auth|fds)=(\d+),(\d+)/ =~ make_flags
- begin
- r = IO.for_fd($1.to_i(10), "rb", autoclose: false)
- w = IO.for_fd($2.to_i(10), "wb", autoclose: false)
- rescue Errno::EBADF
- else
- opts[r] = r
- opts[w] = w
+ [$1, $2].each do |fd|
+ fd = fd.to_i(10)
+ opts[fd] = fd
end
end
diff --git a/spec/ruby/optional/capi/string_spec.rb b/spec/ruby/optional/capi/string_spec.rb
index a8edf998b5..72f20ee6a5 100644
--- a/spec/ruby/optional/capi/string_spec.rb
+++ b/spec/ruby/optional/capi/string_spec.rb
@@ -191,11 +191,19 @@ describe "C-API String function" do
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"
+ lens = [4]
+
+ ruby_version_is "4.0" do
+ lens << 100
+ end
+
+ lens.each do |len|
+ s = @s.rb_str_tmp_new(len)
+ s.encoding.should == Encoding::BINARY
+ s.bytesize.should == len
+ s.size.should == len
+ s.should == "\x00" * len
+ end
end
end
@@ -449,6 +457,20 @@ describe "C-API String function" do
end
end
+ describe "rb_str_strlen" do
+ it 'returns 0 as the length of an empty string' do
+ @s.rb_str_strlen('').should == 0
+ end
+
+ it 'returns the number of characters in a string' do
+ @s.rb_str_strlen('hello').should == 5
+ end
+
+ it 'returns the number of characters in a string with multi-byte characters' do
+ @s.rb_str_strlen('こんにちは').should == 5
+ end
+ end
+
describe "rb_str_split" do
it "splits strings over a splitter" do
@s.rb_str_split("Hello,Goodbye").should == ["Hello", "Goodbye"]
@@ -888,16 +910,20 @@ describe "C-API String function" do
end
it "returns the original String if a transcoding error occurs" do
- a = [0xEE].pack('C').force_encoding("utf-8")
- @s.rb_str_conv_enc(a, Encoding::UTF_8, Encoding::EUC_JP).should equal(a)
+ a = [0xEE].pack('C').force_encoding(Encoding::UTF_8)
+ @s.rb_str_conv_enc(a, Encoding::UTF_8, Encoding::EUC_JP).should.equal?(a)
+ a.encoding.should == Encoding::UTF_8
+
+ a = "\x80".b
+ @s.rb_str_conv_enc(a, Encoding::BINARY, Encoding::UTF_8).should.equal?(a)
+ a.encoding.should == Encoding::BINARY
end
it "returns a transcoded String" do
- a = "\xE3\x81\x82\xE3\x82\x8C".dup.force_encoding("utf-8")
+ a = "\xE3\x81\x82\xE3\x82\x8C".dup.force_encoding(Encoding::UTF_8)
result = @s.rb_str_conv_enc(a, Encoding::UTF_8, Encoding::EUC_JP)
- x = [0xA4, 0xA2, 0xA4, 0xEC].pack('C4').force_encoding('utf-8')
- result.should == x.force_encoding("euc-jp")
- result.encoding.should equal(Encoding::EUC_JP)
+ result.should == [0xA4, 0xA2, 0xA4, 0xEC].pack('C4').force_encoding(Encoding::EUC_JP)
+ result.encoding.should == Encoding::EUC_JP
end
describe "when the String encoding is equal to the destination encoding" do
@@ -994,7 +1020,7 @@ describe "C-API String function" do
result = @s.rb_str_export_to_enc(source, Encoding::UTF_8)
source.bytes.should == [0, 255]
end
-end
+ end
describe "rb_sprintf" do
it "replaces the parts like sprintf" do
@@ -1022,11 +1048,19 @@ end
@s.rb_sprintf3(true.class).should == s
end
- ruby_bug "#19167", ""..."3.2" do
- it "formats a TrueClass VALUE as 'true' if sign specified in format" do
- s = 'Result: TrueClass.'
- @s.rb_sprintf4(true.class).should == s
- end
+ it "formats a TrueClass VALUE as 'true' if sign specified in format" do
+ s = 'Result: TrueClass.'
+ @s.rb_sprintf4(true.class).should == s
+ end
+
+ it "formats nil using to_s if sign not specified in format" do
+ s = 'Result: .'
+ @s.rb_sprintf3(nil).should == s
+ end
+
+ it "formats nil using inspect if sign specified in format" do
+ s = 'Result: nil.'
+ @s.rb_sprintf4(nil).should == s
end
it "truncates a string to a supplied precision if that is shorter than the string" do
@@ -1096,7 +1130,7 @@ end
end
it "tries to convert the passed argument to a string by calling #to_s" do
- @s.rb_String({"bar" => "foo"}).should == '{"bar"=>"foo"}'
+ @s.rb_String({"bar" => "foo"}).should == {"bar" => "foo"}.to_s
end
end
@@ -1185,28 +1219,50 @@ end
describe "rb_str_locktmp" do
it "raises an error when trying to lock an already locked string" do
- str = "test"
+ 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"
+ str = +"test"
@s.rb_str_locktmp(str).should == str
-> { str.upcase! }.should raise_error(RuntimeError, 'can\'t modify string; temporarily locked')
end
+
+ ruby_version_is "4.0" do
+ it "raises FrozenError if string is frozen" do
+ str = -"rb_str_locktmp"
+ -> { @s.rb_str_locktmp(str) }.should raise_error(FrozenError)
+
+ str = +"rb_str_locktmp"
+ str.freeze
+ -> { @s.rb_str_locktmp(str) }.should raise_error(FrozenError)
+ end
+ end
end
describe "rb_str_unlocktmp" do
it "unlocks a locked string" do
- str = "test"
+ 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')
+ -> { @s.rb_str_unlocktmp(+"test") }.should raise_error(RuntimeError, 'temporal unlocking already unlocked string')
+ end
+
+ ruby_version_is "4.0" do
+ it "raises FrozenError if string is frozen" do
+ str = -"rb_str_locktmp"
+ -> { @s.rb_str_unlocktmp(str) }.should raise_error(FrozenError)
+
+ str = +"rb_str_locktmp"
+ str.freeze
+ -> { @s.rb_str_unlocktmp(str) }.should raise_error(FrozenError)
+ end
end
end
@@ -1247,6 +1303,51 @@ end
end
end
+ describe "rb_enc_interned_str" do
+ it "returns a frozen string" do
+ str = "hello"
+ val = @s.rb_enc_interned_str(str, str.bytesize, Encoding::US_ASCII)
+
+ val.should.is_a?(String)
+ val.encoding.should == Encoding::US_ASCII
+ val.should.frozen?
+ end
+
+ it "returns the same frozen string" do
+ str = "hello"
+ result1 = @s.rb_enc_interned_str(str, str.bytesize, Encoding::US_ASCII)
+ result2 = @s.rb_enc_interned_str(str, str.bytesize, Encoding::US_ASCII)
+ result1.should.equal?(result2)
+ end
+
+ it "returns different frozen strings for different encodings" do
+ str = "hello"
+ result1 = @s.rb_enc_interned_str(str, str.bytesize, Encoding::US_ASCII)
+ result2 = @s.rb_enc_interned_str(str, str.bytesize, Encoding::UTF_8)
+ result1.should_not.equal?(result2)
+ end
+
+ it 'returns the same string when using non-ascii characters' do
+ str = 'こんにちは'
+ result1 = @s.rb_enc_interned_str(str, str.bytesize, Encoding::UTF_8)
+ result2 = @s.rb_enc_interned_str(str, str.bytesize, Encoding::UTF_8)
+ result1.should.equal?(result2)
+ end
+
+ it "returns the same string as String#-@" do
+ str = "hello"
+ @s.rb_enc_interned_str(str, str.bytesize, Encoding::UTF_8).should.equal?(-str)
+ end
+
+ ruby_bug "#20322", ""..."3.4" do
+ it "uses the default encoding if encoding is null" do
+ str = "hello"
+ val = @s.rb_enc_interned_str(str, str.bytesize, nil)
+ val.encoding.should == Encoding::ASCII_8BIT
+ end
+ end
+ end
+
describe "rb_str_to_interned_str" do
it "returns a frozen string" do
str = "hello"
diff --git a/spec/ruby/optional/capi/struct_spec.rb b/spec/ruby/optional/capi/struct_spec.rb
index 0e9e366908..cc8d7f932e 100644
--- a/spec/ruby/optional/capi/struct_spec.rb
+++ b/spec/ruby/optional/capi/struct_spec.rb
@@ -208,4 +208,109 @@ describe "C-API Struct function" do
@s.rb_struct_size(@struct).should == 3
end
end
+
+ describe "rb_struct_initialize" do
+ it "sets all members" do
+ @s.rb_struct_initialize(@struct, [1, 2, 3]).should == nil
+ @struct.a.should == 1
+ @struct.b.should == 2
+ @struct.c.should == 3
+ end
+
+ it "does not freeze the Struct instance" do
+ @s.rb_struct_initialize(@struct, [1, 2, 3]).should == nil
+ @struct.should_not.frozen?
+ @s.rb_struct_initialize(@struct, [4, 5, 6]).should == nil
+ @struct.a.should == 4
+ @struct.b.should == 5
+ @struct.c.should == 6
+ end
+
+ it "raises ArgumentError if too many values" do
+ -> { @s.rb_struct_initialize(@struct, [1, 2, 3, 4]) }.should raise_error(ArgumentError, "struct size differs")
+ end
+
+ it "treats missing values as nil" do
+ @s.rb_struct_initialize(@struct, [1, 2]).should == nil
+ @struct.a.should == 1
+ @struct.b.should == 2
+ @struct.c.should == nil
+ end
+ end
+end
+
+ruby_version_is "3.3" do
+ describe "C-API Data function" do
+ before :all do
+ @s = CApiStructSpecs.new
+ @klass = @s.rb_data_define(nil, "a", "b", "c")
+ end
+
+ describe "rb_data_define" do
+ it "returns a subclass of Data class when passed nil as the first argument" do
+ @klass.should.is_a? Class
+ @klass.superclass.should == Data
+ end
+
+ it "returns a subclass of a class when passed as the first argument" do
+ superclass = Class.new(Data)
+ klass = @s.rb_data_define(superclass, "a", "b", "c")
+
+ klass.should.is_a? Class
+ klass.superclass.should == superclass
+ end
+
+ it "creates readers for the members" do
+ obj = @klass.new(1, 2, 3)
+
+ obj.a.should == 1
+ obj.b.should == 2
+ obj.c.should == 3
+ end
+
+ it "returns the member names as Symbols" do
+ obj = @klass.new(0, 0, 0)
+
+ obj.members.should == [:a, :b, :c]
+ end
+
+ it "raises an ArgumentError if arguments contain duplicate member name" do
+ -> { @s.rb_data_define(nil, "a", "b", "a") }.should raise_error(ArgumentError)
+ end
+
+ it "raises when first argument is not a class" do
+ -> { @s.rb_data_define([], "a", "b", "c") }.should raise_error(TypeError, "wrong argument type Array (expected Class)")
+ end
+ end
+
+ describe "rb_struct_initialize" do
+ it "sets all members for a Data instance" do
+ data = @klass.allocate
+ @s.rb_struct_initialize(data, [1, 2, 3]).should == nil
+ data.a.should == 1
+ data.b.should == 2
+ data.c.should == 3
+ end
+
+ it "freezes the Data instance" do
+ data = @klass.allocate
+ @s.rb_struct_initialize(data, [1, 2, 3]).should == nil
+ data.should.frozen?
+ -> { @s.rb_struct_initialize(data, [1, 2, 3]) }.should raise_error(FrozenError)
+ end
+
+ it "raises ArgumentError if too many values" do
+ data = @klass.allocate
+ -> { @s.rb_struct_initialize(data, [1, 2, 3, 4]) }.should raise_error(ArgumentError, "struct size differs")
+ end
+
+ it "treats missing values as nil" do
+ data = @klass.allocate
+ @s.rb_struct_initialize(data, [1, 2]).should == nil
+ data.a.should == 1
+ data.b.should == 2
+ data.c.should == nil
+ end
+ end
+ end
end
diff --git a/spec/ruby/optional/capi/thread_spec.rb b/spec/ruby/optional/capi/thread_spec.rb
index af641f0564..117726f0e2 100644
--- a/spec/ruby/optional/capi/thread_spec.rb
+++ b/spec/ruby/optional/capi/thread_spec.rb
@@ -184,4 +184,12 @@ describe "C-API Thread function" do
thr.value.should be_true
end
end
+
+ ruby_version_is "4.0" do
+ describe "ruby_thread_has_gvl_p" do
+ it "returns true if the current thread has the GVL" do
+ @t.ruby_thread_has_gvl_p.should be_true
+ end
+ end
+ end
end
diff --git a/spec/ruby/optional/capi/util_spec.rb b/spec/ruby/optional/capi/util_spec.rb
index 9ff8b4760a..6cf064bf97 100644
--- a/spec/ruby/optional/capi/util_spec.rb
+++ b/spec/ruby/optional/capi/util_spec.rb
@@ -209,7 +209,7 @@ describe "C-API Util function" do
end
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
describe "rb_long2int" do
it "raises a RangeError if the value is outside the range of a C int" do
-> { @o.rb_long2int(0xffff_ffff_ffff) }.should raise_error(RangeError)
diff --git a/spec/ruby/optional/thread_safety/fixtures/classes.rb b/spec/ruby/optional/thread_safety/fixtures/classes.rb
new file mode 100644
index 0000000000..4f0ad030e5
--- /dev/null
+++ b/spec/ruby/optional/thread_safety/fixtures/classes.rb
@@ -0,0 +1,39 @@
+module ThreadSafetySpecs
+ # Returns the number of processors, rounded up so it's always a multiple of 2
+ def self.processors
+ require 'etc'
+ n = Etc.nprocessors
+ raise "expected at least 1 processor" if n < 1
+ n += 1 if n.odd? # ensure it's a multiple of 2
+ n
+ end
+
+ class Counter
+ def initialize
+ @value = 0
+ @mutex = Mutex.new
+ end
+
+ def get
+ @mutex.synchronize { @value }
+ end
+
+ def increment
+ @mutex.synchronize do
+ @value += 1
+ end
+ end
+ end
+
+ class Barrier
+ def initialize(parties)
+ @parties = parties
+ @counter = Counter.new
+ end
+
+ def wait
+ @counter.increment
+ Thread.pass until @counter.get == @parties
+ end
+ end
+end
diff --git a/spec/ruby/optional/thread_safety/hash_spec.rb b/spec/ruby/optional/thread_safety/hash_spec.rb
new file mode 100644
index 0000000000..53127fc973
--- /dev/null
+++ b/spec/ruby/optional/thread_safety/hash_spec.rb
@@ -0,0 +1,210 @@
+require_relative '../../spec_helper'
+require_relative 'fixtures/classes'
+
+describe "Hash thread safety" do
+ it "supports concurrent #[]=" do
+ n_threads = ThreadSafetySpecs.processors
+
+ n = 1_000
+ operations = n * n_threads
+
+ h = {}
+ barrier = ThreadSafetySpecs::Barrier.new(n_threads + 1)
+
+ threads = n_threads.times.map { |t|
+ Thread.new {
+ barrier.wait
+ base = t * n
+ n.times do |j|
+ h[base+j] = t
+ end
+ }
+ }
+
+ barrier.wait
+ threads.each(&:join)
+
+ h.size.should == operations
+ h.each_pair { |key, value|
+ (key / n).should == value
+ }
+ end
+
+ # can't add a new key into hash during iteration (RuntimeError) on CRuby.
+ # Yet it's good to test this for implementations that support it.
+ guard_not -> { PlatformGuard.standard? } do
+ it "supports concurrent #[]= and #delete and iteration" do
+ n_threads = ThreadSafetySpecs.processors
+
+ n = 1_000
+ operations = n * n_threads / 2
+
+ h = {}
+ barrier1 = ThreadSafetySpecs::Barrier.new(n_threads + 2)
+ barrier2 = ThreadSafetySpecs::Barrier.new(n_threads + 1)
+
+ threads = n_threads.times.map { |t|
+ Thread.new {
+ barrier1.wait
+ base = t * n
+ n.times do |j|
+ h[base+j] = t
+ end
+
+ barrier2.wait
+ n.times do |j|
+ # delete only even keys
+ h.delete(base+j).should == t if (base+j).even?
+ end
+ }
+ }
+
+ read = true
+ reader = Thread.new {
+ barrier1.wait
+ while read
+ h.each_pair { |k,v|
+ k.should.is_a?(Integer)
+ v.should.is_a?(Integer)
+ (k / n).should == v
+ }
+ end
+ }
+
+ barrier1.wait
+ barrier2.wait
+ threads.each(&:join)
+ read = false
+ reader.join
+
+ # odd keys are left
+ h.size.should == operations
+ h.each_pair { |key, value|
+ key.should.odd?
+ (key / n).should == value
+ }
+ end
+ end
+
+ it "supports concurrent #[]= and #[]" do
+ n_threads = ThreadSafetySpecs.processors
+
+ n = 1_000
+ operations = n * n_threads / 2
+
+ h = {}
+ barrier = ThreadSafetySpecs::Barrier.new(n_threads + 1)
+
+ threads = n_threads.times.map { |t|
+ Thread.new {
+ barrier.wait
+ base = (t / 2) * n
+
+ if t.even?
+ n.times do |j|
+ k = base + j
+ h[k] = k
+ end
+ else
+ n.times do |j|
+ k = base + j
+ Thread.pass until v = h[k]
+ v.should == k
+ end
+ end
+ }
+ }
+
+ barrier.wait
+ threads.each(&:join)
+
+ h.size.should == operations
+ h.each_pair { |key, value|
+ key.should == value
+ }
+ end
+
+ it "supports concurrent #[]= and #[] with change to #compare_by_identity in the middle" do
+ n_threads = ThreadSafetySpecs.processors
+
+ n = 1_000
+ operations = n * n_threads / 2
+
+ h = {}
+ barrier = ThreadSafetySpecs::Barrier.new(n_threads + 1)
+
+ threads = n_threads.times.map { |t|
+ Thread.new {
+ barrier.wait
+ base = (t / 2) * n
+
+ if t.even?
+ n.times do |j|
+ k = base + j
+ h[k] = k
+ end
+ else
+ n.times do |j|
+ k = base + j
+ Thread.pass until v = h[k]
+ v.should == k
+ end
+ end
+ }
+ }
+
+ changer = Thread.new {
+ Thread.pass until h.size >= operations / 2
+ h.should_not.compare_by_identity?
+ h.compare_by_identity
+ h.should.compare_by_identity?
+ }
+
+ barrier.wait
+ threads.each(&:join)
+ changer.join
+
+ h.size.should == operations
+ h.each_pair { |key, value|
+ key.should == value
+ }
+ end
+
+ it "supports repeated concurrent #[]= and #delete and always returns a #size >= 0" do
+ n_threads = ThreadSafetySpecs.processors
+
+ n = 1_000
+ operations = n * n_threads / 2
+
+ h = {}
+ barrier = ThreadSafetySpecs::Barrier.new(n_threads + 1)
+ deleted = ThreadSafetySpecs::Counter.new
+
+ threads = n_threads.times.map { |t|
+ Thread.new {
+ barrier.wait
+ key = t / 2
+
+ if t.even?
+ n.times {
+ Thread.pass until h.delete(key)
+ h.size.should >= 0
+ deleted.increment
+ }
+ else
+ n.times {
+ h[key] = key
+ Thread.pass while h.key?(key)
+ }
+ end
+ }
+ }
+
+ barrier.wait
+ threads.each(&:join)
+
+ deleted.get.should == operations
+ h.size.should == 0
+ h.should.empty?
+ end
+end
diff --git a/spec/ruby/security/cve_2020_10663_spec.rb b/spec/ruby/security/cve_2020_10663_spec.rb
index cce1beb012..c44a13a0dd 100644
--- a/spec/ruby/security/cve_2020_10663_spec.rb
+++ b/spec/ruby/security/cve_2020_10663_spec.rb
@@ -1,39 +1,49 @@
require_relative '../spec_helper'
-require 'json'
-module JSONSpecs
- class MyClass
- def initialize(foo)
- @foo = foo
- end
+ruby_version_is ""..."4.0" do
+ require 'json'
- def self.json_create(hash)
- new(*hash['args'])
- end
+ module JSONSpecs
+ class MyClass
+ def initialize(foo)
+ @foo = foo
+ end
- def to_json(*args)
- { 'json_class' => self.class.name, 'args' => [ @foo ] }.to_json(*args)
+ 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
-end
-guard -> {
- JSON.const_defined?(:Pure) or
- version_is(JSON::VERSION, '2.3.0')
-} do
- 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)
+ guard -> {
+ JSON.const_defined?(:Pure) or
+ version_is(JSON::VERSION, '2.3.0')
+ } do
+ 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, create_additions: true).class.should == JSONSpecs::MyClass
+ JSON(json, create_additions: true).class.should == JSONSpecs::MyClass
+ if version_is(JSON::VERSION, '2.8.0')
+ warning = /\Wcreate_additions:\s*true\W\s+is\s+deprecated/
+ else
+ warning = ''
+ end
+ -> {
+ JSON.load(json).class.should == JSONSpecs::MyClass
+ }.should output_to_fd(warning, STDERR)
- JSON.parse(json).class.should == Hash
- JSON.parse(json, nil).class.should == Hash
- JSON(json).class.should == Hash
+ 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/spec/ruby/security/cve_2024_49761_spec.rb b/spec/ruby/security/cve_2024_49761_spec.rb
new file mode 100644
index 0000000000..c66b438eef
--- /dev/null
+++ b/spec/ruby/security/cve_2024_49761_spec.rb
@@ -0,0 +1,7 @@
+require_relative '../spec_helper'
+
+describe "CVE-2024-49761 is resisted by" do
+ it "the Regexp implementation handling that regular expression in linear time" do
+ Regexp.linear_time?(/&#0*((?:\d+)|(?:x[a-fA-F0-9]+));/).should == true
+ end
+end
diff --git a/spec/ruby/shared/enumerator/with_index.rb b/spec/ruby/shared/enumerator/with_index.rb
deleted file mode 100644
index 89f40070e0..0000000000
--- a/spec/ruby/shared/enumerator/with_index.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :enum_with_index, shared: true do
-
- require_relative '../../fixtures/enumerator/classes'
-
- before :each do
- @origin = [1, 2, 3, 4]
- @enum = @origin.to_enum
- end
-
- it "passes each element and its index to block" do
- a = []
- @enum.send(@method) { |o, i| a << [o, i] }
- a.should == [[1, 0], [2, 1], [3, 2], [4, 3]]
- end
-
- it "returns the object being enumerated when given a block" do
- @enum.send(@method) { |o, i| :glark }.should equal(@origin)
- end
-
- it "binds splat arguments properly" do
- acc = []
- @enum.send(@method) { |*b| c,d = b; acc << c; acc << d }
- [1, 0, 2, 1, 3, 2, 4, 3].should == acc
- end
-
- it "returns an enumerator if no block is supplied" do
- ewi = @enum.send(@method)
- ewi.should be_an_instance_of(Enumerator)
- ewi.to_a.should == [[1, 0], [2, 1], [3, 2], [4, 3]]
- end
-end
diff --git a/spec/ruby/shared/enumerator/with_object.rb b/spec/ruby/shared/enumerator/with_object.rb
deleted file mode 100644
index c2e3a79366..0000000000
--- a/spec/ruby/shared/enumerator/with_object.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :enum_with_object, shared: true do
- before :each do
- @enum = [:a, :b].to_enum
- @memo = ''
- @block_params = @enum.send(@method, @memo).to_a
- end
-
- it "receives an argument" do
- @enum.method(@method).arity.should == 1
- end
-
- context "with block" do
- it "returns the given object" do
- ret = @enum.send(@method, @memo) do |elm, memo|
- # nothing
- end
- ret.should equal(@memo)
- end
-
- context "the block parameter" do
- it "passes each element to first parameter" do
- @block_params[0][0].should equal(:a)
- @block_params[1][0].should equal(:b)
- end
-
- it "passes the given object to last parameter" do
- @block_params[0][1].should equal(@memo)
- @block_params[1][1].should equal(@memo)
- end
- end
- end
-
- context "without block" do
- it "returns new Enumerator" do
- ret = @enum.send(@method, @memo)
- ret.should be_an_instance_of(Enumerator)
- ret.should_not equal(@enum)
- end
- end
-end
diff --git a/spec/ruby/shared/fiber/resume.rb b/spec/ruby/shared/fiber/resume.rb
deleted file mode 100644
index f3477804ad..0000000000
--- a/spec/ruby/shared/fiber/resume.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-describe :fiber_resume, shared: true do
- it "can be invoked from the root Fiber" do
- fiber = Fiber.new { :fiber }
- fiber.send(@method).should == :fiber
- end
-
- it "raises a FiberError if invoked from a different Thread" do
- fiber = Fiber.new { 42 }
- Thread.new do
- -> {
- fiber.send(@method)
- }.should raise_error(FiberError)
- end.join
-
- # Check the Fiber can still be used
- fiber.send(@method).should == 42
- end
-
- it "passes control to the beginning of the block on first invocation" do
- invoked = false
- fiber = Fiber.new { invoked = true }
- fiber.send(@method)
- invoked.should be_true
- end
-
- it "returns the last value encountered on first invocation" do
- fiber = Fiber.new { 1+1; true }
- fiber.send(@method).should be_true
- end
-
- it "runs until the end of the block" do
- obj = mock('obj')
- obj.should_receive(:do).once
- fiber = Fiber.new { 1 + 2; a = "glark"; obj.do }
- fiber.send(@method)
- 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 "raises a FiberError if the Fiber is dead" do
- fiber = Fiber.new { true }
- fiber.send(@method)
- -> { fiber.send(@method) }.should raise_error(FiberError)
- end
-
- it "raises a LocalJumpError if the block includes a return statement" do
- fiber = Fiber.new { return; }
- -> { fiber.send(@method) }.should raise_error(LocalJumpError)
- end
-
- it "raises a LocalJumpError if the block includes a break statement" do
- fiber = Fiber.new { break; }
- -> { fiber.send(@method) }.should raise_error(LocalJumpError)
- end
-end
diff --git a/spec/ruby/shared/file/size.rb b/spec/ruby/shared/file/size.rb
index 880dfbb612..cba99fe6a5 100644
--- a/spec/ruby/shared/file/size.rb
+++ b/spec/ruby/shared/file/size.rb
@@ -72,7 +72,7 @@ describe :file_size_nil_when_missing, shared: true do
end
it "returns nil if file_name doesn't exist or has 0 size" do
- @object.send(@method, @missing).should == nil
+ @object.send(@method, @missing).should == nil
end
end
diff --git a/spec/ruby/shared/file/socket.rb b/spec/ruby/shared/file/socket.rb
index 55a1cfd284..ef6c482d1c 100644
--- a/spec/ruby/shared/file/socket.rb
+++ b/spec/ruby/shared/file/socket.rb
@@ -1,3 +1,33 @@
describe :file_socket, shared: true do
- it "accepts an object that has a #to_path method"
+ it "returns false if the file is not a socket" do
+ filename = tmp("i_exist")
+ touch(filename)
+
+ @object.send(@method, filename).should == false
+
+ rm_r filename
+ end
+
+ it "returns true if the file is a socket" do
+ require 'socket'
+
+ # We need a really short name here.
+ # On Linux the path length is limited to 107, see unix(7).
+ name = tmp("s")
+ server = UNIXServer.new(name)
+
+ @object.send(@method, name).should == true
+
+ server.close
+ rm_r name
+ end
+
+ it "accepts an object that has a #to_path method" do
+ obj = Object.new
+ def obj.to_path
+ __FILE__
+ end
+
+ @object.send(@method, obj).should == false
+ end
end
diff --git a/spec/ruby/shared/file/sticky.rb b/spec/ruby/shared/file/sticky.rb
index 38bb6ed26b..e07fa22fd7 100644
--- a/spec/ruby/shared/file/sticky.rb
+++ b/spec/ruby/shared/file/sticky.rb
@@ -8,7 +8,7 @@ describe :file_sticky, shared: true do
Dir.rmdir(@dir) if File.exist?(@dir)
end
- platform_is_not :windows, :darwin, :freebsd, :netbsd, :openbsd, :solaris, :aix do
+ platform_is_not :windows, :darwin, :freebsd, :netbsd, :openbsd, :aix do
it "returns true if the named file has the sticky bit, otherwise false" do
Dir.mkdir @dir, 01755
diff --git a/spec/ruby/shared/io/putc.rb b/spec/ruby/shared/io/putc.rb
index e6012c0098..cdf18ac9fd 100644
--- a/spec/ruby/shared/io/putc.rb
+++ b/spec/ruby/shared/io/putc.rb
@@ -1,4 +1,4 @@
-# -*- encoding: binary -*-
+# encoding: binary
describe :io_putc, shared: true do
after :each do
@io.close if @io && !@io.closed?
diff --git a/spec/ruby/shared/kernel/raise.rb b/spec/ruby/shared/kernel/raise.rb
index 1917a4c923..2be06ea797 100644
--- a/spec/ruby/shared/kernel/raise.rb
+++ b/spec/ruby/shared/kernel/raise.rb
@@ -49,21 +49,6 @@ describe :kernel_raise, shared: true do
end
end
- it "does not allow message and extra keyword arguments" do
- data_error = Class.new(StandardError) do
- attr_reader :data
- def initialize(data)
- @data = data
- end
- end
-
- -> { @object.raise(data_error, {a: 1}, b: 2) }.should raise_error(StandardError) do |e|
- [TypeError, ArgumentError].should.include?(e.class)
- end
-
- -> { @object.raise(data_error, {a: 1}, [], b: 2) }.should raise_error(ArgumentError)
- end
-
it "raises RuntimeError if no exception class is given" do
-> { @object.raise }.should raise_error(RuntimeError, "")
end
@@ -74,7 +59,7 @@ describe :kernel_raise, shared: true do
end
it "raises a RuntimeError if string given" do
- -> { @object.raise("a bad thing") }.should raise_error(RuntimeError)
+ -> { @object.raise("a bad thing") }.should raise_error(RuntimeError, "a bad thing")
end
it "passes no arguments to the constructor when given only an exception class" do
@@ -86,59 +71,57 @@ describe :kernel_raise, shared: true do
end
it "raises a TypeError when passed a non-Exception object" do
- -> { @object.raise(Object.new) }.should raise_error(TypeError)
+ -> { @object.raise(Object.new) }.should raise_error(TypeError, "exception class/object expected")
+ -> { @object.raise(Object.new, "message") }.should raise_error(TypeError, "exception class/object expected")
+ -> { @object.raise(Object.new, "message", []) }.should raise_error(TypeError, "exception class/object expected")
end
it "raises a TypeError when passed true" do
- -> { @object.raise(true) }.should raise_error(TypeError)
+ -> { @object.raise(true) }.should raise_error(TypeError, "exception class/object expected")
end
it "raises a TypeError when passed false" do
- -> { @object.raise(false) }.should raise_error(TypeError)
+ -> { @object.raise(false) }.should raise_error(TypeError, "exception class/object expected")
end
it "raises a TypeError when passed nil" do
- -> { @object.raise(nil) }.should raise_error(TypeError)
+ -> { @object.raise(nil) }.should raise_error(TypeError, "exception class/object expected")
+ end
+
+ it "raises a TypeError when passed a message and an extra argument" do
+ -> { @object.raise("message", {cause: RuntimeError.new()}) }.should raise_error(TypeError, "exception class/object expected")
+ end
+
+ it "raises TypeError when passed a non-Exception object but it responds to #exception method that doesn't return an instance of Exception class" do
+ e = Object.new
+ def e.exception
+ Array
+ end
+
+ -> {
+ @object.raise e
+ }.should raise_error(TypeError, "exception object expected")
end
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
- initial_raise_line = __LINE__; Fiber.yield
- rescue => raised
- begin
- raise_again_line = __LINE__; Fiber.yield raised
- rescue => raised_again
- raised_again
- end
- end
- end
- fiber.resume
- raised = fiber.raise 'raised'
- raised_again = fiber.raise raised
- else
- begin
- initial_raise_line = __LINE__; @object.raise 'raised'
- rescue => raised
- begin
- raise_again_line = __LINE__; @object.raise raised
- rescue => raised_again
- raised_again
- end
- end
+ exception = nil
+
+ begin
+ raise "raised"
+ rescue => exception
+ # Ignore.
end
- raised_again.backtrace.first.should include("#{__FILE__}:#{initial_raise_line}:")
- raised_again.backtrace.first.should_not include("#{__FILE__}:#{raise_again_line}:")
+ backtrace = exception.backtrace
+
+ begin
+ raised_exception = @object.raise(exception)
+ rescue => raised_exception
+ # Ignore.
+ end
+
+ raised_exception.backtrace.should == backtrace
+ raised_exception.should == exception
end
it "allows Exception, message, and backtrace parameters" do
@@ -157,4 +140,259 @@ describe :kernel_raise, shared: true do
}
end
end
+
+ ruby_version_is "4.0" do
+ it "allows cause keyword argument" do
+ cause = StandardError.new("original error")
+ result = nil
+
+ -> do
+ @object.raise("new error", cause: cause)
+ end.should raise_error(RuntimeError, "new error") do |error|
+ error.cause.should == cause
+ end
+ end
+
+ it "raises an ArgumentError when only cause is given" do
+ cause = StandardError.new("cause")
+ -> do
+ @object.raise(cause: cause)
+ end.should raise_error(ArgumentError, "only cause is given with no arguments")
+ end
+
+ it "raises an ArgumentError when only cause is given and is nil" do
+ -> do
+ @object.raise(cause: nil)
+ end.should raise_error(ArgumentError, "only cause is given with no arguments")
+ end
+
+ it "raises a TypeError when given cause is not an instance of Exception" do
+ cause = Object.new
+ -> do
+ @object.raise("message", cause: cause)
+ end.should raise_error(TypeError, "exception object expected")
+ end
+
+ it "doesn't set given cause when it equals the raised exception" do
+ cause = StandardError.new("cause")
+ result = nil
+
+ -> do
+ @object.raise(cause, cause: cause)
+ end.should raise_error(StandardError, "cause") do |error|
+ error.should == cause
+ error.cause.should == nil
+ end
+ end
+
+ it "accepts cause equal an exception" do
+ error = RuntimeError.new("message")
+ result = nil
+
+ -> do
+ @object.raise(error, cause: error)
+ end.should raise_error(RuntimeError, "message") do |e|
+ e.cause.should == nil
+ end
+ end
+
+ it "rejects circular causes" do
+ -> {
+ begin
+ raise "Error 1"
+ rescue => error1
+ begin
+ raise "Error 2"
+ rescue => error2
+ begin
+ raise "Error 3"
+ rescue => error3
+ @object.raise(error1, cause: error3)
+ end
+ end
+ end
+ }.should raise_error(ArgumentError, "circular causes")
+ end
+
+ it "supports exception class with message and cause" do
+ cause = StandardError.new("cause message")
+ result = nil
+
+ -> do
+ @object.raise(ArgumentError, "argument error message", cause: cause)
+ end.should raise_error(ArgumentError, "argument error message") do |error|
+ error.should be_kind_of(ArgumentError)
+ error.message.should == "argument error message"
+ error.cause.should == cause
+ end
+ end
+
+ it "supports exception class with message, backtrace and cause" do
+ cause = StandardError.new("cause message")
+ backtrace = ["line1", "line2"]
+ result = nil
+
+ -> do
+ @object.raise(ArgumentError, "argument error message", backtrace, cause: cause)
+ end.should raise_error(ArgumentError, "argument error message") do |error|
+ error.should be_kind_of(ArgumentError)
+ error.message.should == "argument error message"
+ error.cause.should == cause
+ error.backtrace.should == backtrace
+ end
+ end
+
+ it "supports automatic cause chaining" do
+ -> do
+ begin
+ raise "first error"
+ rescue
+ # No explicit cause - should chain automatically:
+ @object.raise("second error")
+ end
+ end.should raise_error(RuntimeError, "second error") do |error|
+ error.cause.should be_kind_of(RuntimeError)
+ error.cause.message.should == "first error"
+ end
+ end
+
+ it "supports cause: nil to prevent automatic cause chaining" do
+ -> do
+ begin
+ raise "first error"
+ rescue
+ # Explicit nil prevents chaining:
+ @object.raise("second error", cause: nil)
+ end
+ end.should raise_error(RuntimeError, "second error") do |error|
+ error.cause.should == nil
+ end
+ end
+ end
+end
+
+describe :kernel_raise_across_contexts, shared: true do
+ ruby_version_is "4.0" do
+ describe "with cause keyword argument" do
+ it "uses the cause from the calling context" do
+ original_cause = nil
+ result = nil
+
+ # We have no cause ($!) and we don't specify one explicitly either:
+ @object.raise("second error") do |&block|
+ begin
+ begin
+ raise "first error"
+ rescue => original_cause
+ # We have a cause here ($!) but we should ignore it:
+ block.call
+ end
+ rescue => result
+ # Ignore.
+ end
+ end
+
+ result.should be_kind_of(RuntimeError)
+ result.message.should == "second error"
+ result.cause.should == nil
+ end
+
+ it "accepts a cause keyword argument that overrides the last exception" do
+ original_cause = nil
+ override_cause = StandardError.new("override cause")
+ result = nil
+
+ begin
+ raise "outer error"
+ rescue
+ # We have an existing cause, but we want to override it:
+ @object.raise("second error", cause: override_cause) do |&block|
+ begin
+ begin
+ raise "first error"
+ rescue => original_cause
+ # We also have an existing cause here:
+ block.call
+ end
+ rescue => result
+ # Ignore.
+ end
+ end
+ end
+
+ result.should be_kind_of(RuntimeError)
+ result.message.should == "second error"
+ result.cause.should == override_cause
+ end
+
+ it "supports automatic cause chaining from calling context" do
+ result = nil
+
+ @object.raise("new error") do |&block|
+ begin
+ begin
+ raise "original error"
+ rescue
+ block.call # Let the context yield/sleep
+ end
+ rescue => result
+ # Ignore.
+ end
+ end
+
+ result.should be_kind_of(RuntimeError)
+ result.message.should == "new error"
+ # Calling context has no current exception:
+ result.cause.should == nil
+ end
+
+ it "supports explicit cause: nil to prevent cause chaining" do
+ result = nil
+
+ begin
+ raise "calling context error"
+ rescue
+ @object.raise("new error", cause: nil) do |&block|
+ begin
+ begin
+ raise "target context error"
+ rescue
+ block.call # Let the context yield/sleep
+ end
+ rescue => result
+ # Ignore.
+ end
+ end
+
+ result.should be_kind_of(RuntimeError)
+ result.message.should == "new error"
+ result.cause.should == nil
+ end
+ end
+
+ it "raises TypeError when cause is not an Exception" do
+ -> {
+ @object.raise("error", cause: "not an exception") do |&block|
+ begin
+ block.call # Let the context yield/sleep
+ rescue
+ # Ignore - we expect the TypeError to be raised in the calling context
+ end
+ end
+ }.should raise_error(TypeError, "exception object expected")
+ end
+
+ it "raises ArgumentError when only cause is given with no arguments" do
+ -> {
+ @object.raise(cause: StandardError.new("cause")) do |&block|
+ begin
+ block.call # Let the context yield/sleep
+ rescue
+ # Ignore - we expect the ArgumentError to be raised in the calling context
+ end
+ end
+ }.should raise_error(ArgumentError, "only cause is given with no arguments")
+ end
+ end
+ end
end
diff --git a/spec/ruby/shared/process/fork.rb b/spec/ruby/shared/process/fork.rb
index 11e18d7b1c..8dbb3d0da4 100644
--- a/spec/ruby/shared/process/fork.rb
+++ b/spec/ruby/shared/process/fork.rb
@@ -23,31 +23,31 @@ describe :process_fork, shared: true do
end
it "returns status zero" do
- pid = Process.fork { exit! 0 }
+ pid = @object.fork { exit! 0 }
_, result = Process.wait2(pid)
result.exitstatus.should == 0
end
it "returns status zero" do
- pid = Process.fork { exit 0 }
+ pid = @object.fork { exit 0 }
_, result = Process.wait2(pid)
result.exitstatus.should == 0
end
it "returns status zero" do
- pid = Process.fork {}
+ pid = @object.fork {}
_, result = Process.wait2(pid)
result.exitstatus.should == 0
end
it "returns status non-zero" do
- pid = Process.fork { exit! 42 }
+ pid = @object.fork { exit! 42 }
_, result = Process.wait2(pid)
result.exitstatus.should == 42
end
it "returns status non-zero" do
- pid = Process.fork { exit 42 }
+ pid = @object.fork { exit 42 }
_, result = Process.wait2(pid)
result.exitstatus.should == 42
end
diff --git a/spec/ruby/shared/queue/deque.rb b/spec/ruby/shared/queue/deque.rb
index 0abba5301e..a154da6274 100644
--- a/spec/ruby/shared/queue/deque.rb
+++ b/spec/ruby/shared/queue/deque.rb
@@ -65,66 +65,64 @@ describe :queue_deq, shared: true do
end
describe "with a timeout" do
- ruby_version_is "3.2" do
- it "returns an item if one is available in time" do
- q = @object.call
-
- t = Thread.new {
- q.send(@method, timeout: TIME_TOLERANCE).should == 1
- }
- Thread.pass until t.status == "sleep" && q.num_waiting == 1
- q << 1
- t.join
- end
-
- it "returns nil if no item is available in time" do
- q = @object.call
-
- Thread.new {
- q.send(@method, timeout: 0.001).should == nil
- }.join
- end
-
- it "does nothing if the timeout is nil" do
- q = @object.call
- t = Thread.new {
- q.send(@method, timeout: nil).should == 1
- }
- Thread.pass until t.status == "sleep" && q.num_waiting == 1
- q << 1
- t.join
- end
-
- it "immediately returns nil if no item is available and the timeout is 0" do
- q = @object.call
- q << 1
- q.send(@method, timeout: 0).should == 1
- q.send(@method, timeout: 0).should == nil
- end
-
- it "raise TypeError if timeout is not a valid numeric" do
- q = @object.call
- -> {
- q.send(@method, timeout: "1")
- }.should raise_error(TypeError, "no implicit conversion to float from string")
-
- -> {
- q.send(@method, timeout: false)
- }.should raise_error(TypeError, "no implicit conversion to float from false")
- end
-
- it "raise ArgumentError if non_block = true is passed too" do
- q = @object.call
- -> {
- q.send(@method, true, timeout: 1)
- }.should raise_error(ArgumentError, "can't set a timeout if non_block is enabled")
- end
-
- it "returns nil for a closed empty queue" do
- q = @object.call
- q.close
- q.send(@method, timeout: 0).should == nil
- end
+ it "returns an item if one is available in time" do
+ q = @object.call
+
+ t = Thread.new {
+ q.send(@method, timeout: TIME_TOLERANCE).should == 1
+ }
+ Thread.pass until t.status == "sleep" && q.num_waiting == 1
+ q << 1
+ t.join
+ end
+
+ it "returns nil if no item is available in time" do
+ q = @object.call
+
+ Thread.new {
+ q.send(@method, timeout: 0.001).should == nil
+ }.join
+ end
+
+ it "does nothing if the timeout is nil" do
+ q = @object.call
+ t = Thread.new {
+ q.send(@method, timeout: nil).should == 1
+ }
+ Thread.pass until t.status == "sleep" && q.num_waiting == 1
+ q << 1
+ t.join
+ end
+
+ it "immediately returns nil if no item is available and the timeout is 0" do
+ q = @object.call
+ q << 1
+ q.send(@method, timeout: 0).should == 1
+ q.send(@method, timeout: 0).should == nil
+ end
+
+ it "raise TypeError if timeout is not a valid numeric" do
+ q = @object.call
+ -> {
+ q.send(@method, timeout: "1")
+ }.should raise_error(TypeError, "no implicit conversion to float from string")
+
+ -> {
+ q.send(@method, timeout: false)
+ }.should raise_error(TypeError, "no implicit conversion to float from false")
+ end
+
+ it "raise ArgumentError if non_block = true is passed too" do
+ q = @object.call
+ -> {
+ q.send(@method, true, timeout: 1)
+ }.should raise_error(ArgumentError, "can't set a timeout if non_block is enabled")
+ end
+
+ it "returns nil for a closed empty queue" do
+ q = @object.call
+ q.close
+ q.send(@method, timeout: 0).should == nil
end
end
diff --git a/spec/ruby/shared/queue/freeze.rb b/spec/ruby/shared/queue/freeze.rb
new file mode 100644
index 0000000000..4c506a4235
--- /dev/null
+++ b/spec/ruby/shared/queue/freeze.rb
@@ -0,0 +1,18 @@
+describe :queue_freeze, shared: true do
+ ruby_version_is ""..."3.3" do
+ it "can be frozen" do
+ queue = @object.call
+ queue.freeze
+ queue.should.frozen?
+ end
+ end
+
+ ruby_version_is "3.3" do
+ it "raises an exception when freezing" do
+ queue = @object.call
+ -> {
+ queue.freeze
+ }.should raise_error(TypeError, "cannot freeze #{queue}")
+ end
+ end
+end
diff --git a/spec/ruby/shared/rational/Rational.rb b/spec/ruby/shared/rational/Rational.rb
deleted file mode 100644
index 500f7ed271..0000000000
--- a/spec/ruby/shared/rational/Rational.rb
+++ /dev/null
@@ -1,150 +0,0 @@
-require_relative '../../spec_helper'
-require_relative '../../fixtures/rational'
-
-describe :kernel_Rational, shared: true do
- describe "passed Integer" do
- # Guard against the Mathn library
- guard -> { !defined?(Math.rsqrt) } do
- it "returns a new Rational number with 1 as the denominator" do
- Rational(1).should eql(Rational(1, 1))
- Rational(-3).should eql(Rational(-3, 1))
- Rational(bignum_value).should eql(Rational(bignum_value, 1))
- end
- end
- end
-
- describe "passed two integers" do
- it "returns a new Rational number" do
- rat = Rational(1, 2)
- rat.numerator.should == 1
- rat.denominator.should == 2
- rat.should be_an_instance_of(Rational)
-
- rat = Rational(-3, -5)
- rat.numerator.should == 3
- rat.denominator.should == 5
- rat.should be_an_instance_of(Rational)
-
- rat = Rational(bignum_value, 3)
- rat.numerator.should == bignum_value
- rat.denominator.should == 3
- rat.should be_an_instance_of(Rational)
- end
-
- it "reduces the Rational" do
- rat = Rational(2, 4)
- rat.numerator.should == 1
- rat.denominator.should == 2
-
- rat = Rational(3, 9)
- rat.numerator.should == 1
- rat.denominator.should == 3
- end
- end
-
- describe "when passed a String" do
- it "converts the String to a Rational using the same method as String#to_r" do
- r = Rational(13, 25)
- s_r = ".52".to_r
- r_s = Rational(".52")
-
- r_s.should == r
- r_s.should == s_r
- end
-
- it "scales the Rational value of the first argument by the Rational value of the second" do
- Rational(".52", ".6").should == Rational(13, 15)
- Rational(".52", "1.6").should == Rational(13, 40)
- end
-
- it "does not use the same method as Float#to_r" do
- r = Rational(3, 5)
- f_r = 0.6.to_r
- r_s = Rational("0.6")
-
- r_s.should == r
- r_s.should_not == f_r
- end
- end
-
- describe "when passed a Numeric" do
- it "calls #to_r to convert the first argument to a Rational" do
- num = RationalSpecs::SubNumeric.new(2)
-
- Rational(num).should == Rational(2)
- end
- end
-
- describe "when passed a Complex" do
- it "returns a Rational from the real part if the imaginary part is 0" do
- Rational(Complex(1, 0)).should == Rational(1)
- end
-
- it "raises a RangeError if the imaginary part is not 0" do
- -> { Rational(Complex(1, 2)) }.should raise_error(RangeError)
- end
- end
-
- it "raises a ZeroDivisionError if the second argument is 0" do
- -> { Rational(1, 0) }.should raise_error(ZeroDivisionError, "divided by 0")
- -> { Rational(1, 0.0) }.should raise_error(ZeroDivisionError, "divided by 0")
- end
-
- it "raises a TypeError if the first argument is nil" do
- -> { Rational(nil) }.should raise_error(TypeError)
- end
-
- it "raises a TypeError if the second argument is nil" do
- -> { Rational(1, nil) }.should raise_error(TypeError)
- end
-
- it "raises a TypeError if the first argument is a Symbol" do
- -> { Rational(:sym) }.should raise_error(TypeError)
- end
-
- it "raises a TypeError if the second argument is a Symbol" do
- -> { Rational(1, :sym) }.should raise_error(TypeError)
- 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
- 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
- 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
-
- it "freezes its result" do
- Rational(1).frozen?.should == true
- end
-end
diff --git a/spec/ruby/shared/rational/abs.rb b/spec/ruby/shared/rational/abs.rb
deleted file mode 100644
index 8beb20da7e..0000000000
--- a/spec/ruby/shared/rational/abs.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :rational_abs, shared: true do
- it "returns self's absolute value" do
- Rational(3, 4).send(@method).should == Rational(3, 4)
- Rational(-3, 4).send(@method).should == Rational(3, 4)
- Rational(3, -4).send(@method).should == Rational(3, 4)
-
- Rational(bignum_value, -bignum_value).send(@method).should == Rational(bignum_value, bignum_value)
- end
-end
diff --git a/spec/ruby/shared/rational/arithmetic_exception_in_coerce.rb b/spec/ruby/shared/rational/arithmetic_exception_in_coerce.rb
deleted file mode 100644
index 0dff91d522..0000000000
--- a/spec/ruby/shared/rational/arithmetic_exception_in_coerce.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-require_relative '../../fixtures/rational'
-
-describe :rational_arithmetic_exception_in_coerce, shared: true 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
-end
diff --git a/spec/ruby/shared/rational/ceil.rb b/spec/ruby/shared/rational/ceil.rb
deleted file mode 100644
index f1cf60d2be..0000000000
--- a/spec/ruby/shared/rational/ceil.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :rational_ceil, shared: true do
- before do
- @rational = Rational(2200, 7)
- end
-
- describe "with no arguments (precision = 0)" do
- it "returns an Integer" do
- @rational.ceil.should be_kind_of(Integer)
- end
-
- it "returns the truncated value toward positive infinity" do
- @rational.ceil.should == 315
- Rational(1, 2).ceil.should == 1
- Rational(-1, 2).ceil.should == 0
- end
- end
-
- describe "with a precision < 0" do
- it "returns an Integer" do
- @rational.ceil(-2).should be_kind_of(Integer)
- @rational.ceil(-1).should be_kind_of(Integer)
- end
-
- it "moves the truncation point n decimal places left" do
- @rational.ceil(-3).should == 1000
- @rational.ceil(-2).should == 400
- @rational.ceil(-1).should == 320
- end
- end
-
- describe "with precision > 0" do
- it "returns a Rational" do
- @rational.ceil(1).should be_kind_of(Rational)
- @rational.ceil(2).should be_kind_of(Rational)
- end
-
- it "moves the truncation point n decimal places right" do
- @rational.ceil(1).should == Rational(3143, 10)
- @rational.ceil(2).should == Rational(31429, 100)
- @rational.ceil(3).should == Rational(157143, 500)
- end
- end
-end
diff --git a/spec/ruby/shared/rational/comparison.rb b/spec/ruby/shared/rational/comparison.rb
deleted file mode 100644
index 860462f579..0000000000
--- a/spec/ruby/shared/rational/comparison.rb
+++ /dev/null
@@ -1,95 +0,0 @@
-require_relative '../../spec_helper'
-require_relative '../../fixtures/rational'
-
-describe :rational_cmp_rat, shared: true do
- it "returns 1 when self is greater than the passed argument" do
- (Rational(4, 4) <=> Rational(3, 4)).should equal(1)
- (Rational(-3, 4) <=> Rational(-4, 4)).should equal(1)
- end
-
- it "returns 0 when self is equal to the passed argument" do
- (Rational(4, 4) <=> Rational(4, 4)).should equal(0)
- (Rational(-3, 4) <=> Rational(-3, 4)).should equal(0)
- end
-
- it "returns -1 when self is less than the passed argument" do
- (Rational(3, 4) <=> Rational(4, 4)).should equal(-1)
- (Rational(-4, 4) <=> Rational(-3, 4)).should equal(-1)
- end
-end
-
-describe :rational_cmp_int, shared: true do
- it "returns 1 when self is greater than the passed argument" do
- (Rational(4, 4) <=> 0).should equal(1)
- (Rational(4, 4) <=> -10).should equal(1)
- (Rational(-3, 4) <=> -1).should equal(1)
- end
-
- it "returns 0 when self is equal to the passed argument" do
- (Rational(4, 4) <=> 1).should equal(0)
- (Rational(-8, 4) <=> -2).should equal(0)
- end
-
- it "returns -1 when self is less than the passed argument" do
- (Rational(3, 4) <=> 1).should equal(-1)
- (Rational(-4, 4) <=> 0).should equal(-1)
- end
-end
-
-describe :rational_cmp_float, shared: true do
- it "returns 1 when self is greater than the passed argument" do
- (Rational(4, 4) <=> 0.5).should equal(1)
- (Rational(4, 4) <=> -1.5).should equal(1)
- (Rational(-3, 4) <=> -0.8).should equal(1)
- end
-
- it "returns 0 when self is equal to the passed argument" do
- (Rational(4, 4) <=> 1.0).should equal(0)
- (Rational(-6, 4) <=> -1.5).should equal(0)
- end
-
- it "returns -1 when self is less than the passed argument" do
- (Rational(3, 4) <=> 1.2).should equal(-1)
- (Rational(-4, 4) <=> 0.5).should equal(-1)
- end
-end
-
-describe :rational_cmp_coerce, shared: true do
- it "calls #coerce on the passed argument with self" do
- rational = Rational(3, 4)
-
- obj = mock("Object")
- obj.should_receive(:coerce).with(rational).and_return([1, 2])
-
- rational <=> obj
- end
-
- it "calls #<=> on the coerced Rational with the coerced Object" do
- rational = Rational(3, 4)
-
- coerced_rational = mock("Coerced Rational")
- coerced_rational.should_receive(:<=>).and_return(:result)
-
- coerced_obj = mock("Coerced Object")
-
- obj = mock("Object")
- obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj])
-
- (rational <=> obj).should == :result
- end
-end
-
-describe :rational_cmp_coerce_exception, shared: true 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)
-
- -> { Rational(3, 4) <=> b }.should raise_error(RationalSpecs::CoerceError)
- end
-end
-
-describe :rational_cmp_other, shared: true do
- it "returns nil" do
- (Rational <=> mock("Object")).should be_nil
- end
-end
diff --git a/spec/ruby/shared/rational/denominator.rb b/spec/ruby/shared/rational/denominator.rb
deleted file mode 100644
index 10d46aacb3..0000000000
--- a/spec/ruby/shared/rational/denominator.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :rational_denominator, shared: true do
- it "returns the denominator" do
- Rational(3, 4).denominator.should equal(4)
- Rational(3, -4).denominator.should equal(4)
-
- Rational(1, bignum_value).denominator.should == bignum_value
- end
-
- it "returns 1 if no denominator was given" do
- Rational(80).denominator.should == 1
- end
-end
diff --git a/spec/ruby/shared/rational/div.rb b/spec/ruby/shared/rational/div.rb
deleted file mode 100644
index d5bd9e6644..0000000000
--- a/spec/ruby/shared/rational/div.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :rational_div_rat, shared: true do
- it "performs integer division and returns the result" do
- Rational(2, 3).div(Rational(2, 3)).should == 1
- Rational(-2, 9).div(Rational(-9, 2)).should == 0
- end
-
- it "raises a ZeroDivisionError when the argument has a numerator of 0" do
- -> { Rational(3, 4).div(Rational(0, 3)) }.should raise_error(ZeroDivisionError)
- end
-
- it "raises a ZeroDivisionError when the argument has a numerator of 0.0" do
- -> { Rational(3, 4).div(Rational(0.0, 3)) }.should raise_error(ZeroDivisionError)
- end
-end
-
-describe :rational_div_float, shared: true do
- it "performs integer division and returns the result" do
- Rational(2, 3).div(30.333).should == 0
- Rational(2, 9).div(Rational(-8.6)).should == -1
- Rational(3.12).div(0.5).should == 6
- end
-
- it "raises a ZeroDivisionError when the argument is 0.0" do
- -> { Rational(3, 4).div(0.0) }.should raise_error(ZeroDivisionError)
- end
-end
-
-describe :rational_div_int, shared: true do
- it "performs integer division and returns the result" do
- Rational(2, 1).div(1).should == 2
- Rational(25, 5).div(-50).should == -1
- end
-
- it "raises a ZeroDivisionError when the argument is 0" do
- -> { Rational(3, 4).div(0) }.should raise_error(ZeroDivisionError)
- end
-end
-
-describe :rational_div, shared: true do
- it "returns an Integer" do
- Rational(229, 21).div(82).should be_kind_of(Integer)
- end
-
- it "raises an ArgumentError if passed more than one argument" do
- -> { Rational(3, 4).div(2,3) }.should raise_error(ArgumentError)
- end
-
- # See http://redmine.ruby-lang.org/issues/show/1648
- it "raises a TypeError if passed a non-numeric argument" do
- -> { Rational(3, 4).div([]) }.should raise_error(TypeError)
- end
-end
diff --git a/spec/ruby/shared/rational/divide.rb b/spec/ruby/shared/rational/divide.rb
deleted file mode 100644
index 7d6d66390f..0000000000
--- a/spec/ruby/shared/rational/divide.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :rational_divide_rat, shared: true do
- it "returns self divided by other as a Rational" do
- Rational(3, 4).send(@method, Rational(3, 4)).should eql(Rational(1, 1))
- Rational(2, 4).send(@method, Rational(1, 4)).should eql(Rational(2, 1))
-
- Rational(2, 4).send(@method, 2).should == Rational(1, 4)
- Rational(6, 7).send(@method, -2).should == Rational(-3, 7)
- end
-
- it "raises a ZeroDivisionError when passed a Rational with a numerator of 0" do
- -> { Rational(3, 4).send(@method, Rational(0, 1)) }.should raise_error(ZeroDivisionError)
- end
-end
-
-describe :rational_divide_int, shared: true do
- it "returns self divided by other as a Rational" do
- Rational(3, 4).send(@method, 2).should eql(Rational(3, 8))
- Rational(2, 4).send(@method, 2).should eql(Rational(1, 4))
- Rational(6, 7).send(@method, -2).should eql(Rational(-3, 7))
- end
-
- it "raises a ZeroDivisionError when passed 0" do
- -> { Rational(3, 4).send(@method, 0) }.should raise_error(ZeroDivisionError)
- end
-end
-
-describe :rational_divide_float, shared: true do
- it "returns self divided by other as a Float" do
- Rational(3, 4).send(@method, 0.75).should eql(1.0)
- Rational(3, 4).send(@method, 0.25).should eql(3.0)
- Rational(3, 4).send(@method, 0.3).should eql(2.5)
-
- Rational(-3, 4).send(@method, 0.3).should eql(-2.5)
- Rational(3, -4).send(@method, 0.3).should eql(-2.5)
- Rational(3, 4).send(@method, -0.3).should eql(-2.5)
- end
-
- it "returns infinity when passed 0" do
- Rational(3, 4).send(@method, 0.0).infinite?.should eql(1)
- Rational(-3, -4).send(@method, 0.0).infinite?.should eql(1)
-
- Rational(-3, 4).send(@method, 0.0).infinite?.should eql(-1)
- Rational(3, -4).send(@method, 0.0).infinite?.should eql(-1)
- end
-end
-
-describe :rational_divide, shared: true do
- it "calls #coerce on the passed argument with self" do
- rational = Rational(3, 4)
- obj = mock("Object")
- obj.should_receive(:coerce).with(rational).and_return([1, 2])
-
- rational.send(@method, obj)
- end
-
- it "calls #/ on the coerced Rational with the coerced Object" do
- rational = Rational(3, 4)
-
- coerced_rational = mock("Coerced Rational")
- coerced_rational.should_receive(:/).and_return(:result)
-
- coerced_obj = mock("Coerced Object")
-
- obj = mock("Object")
- obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj])
-
- rational.send(@method, obj).should == :result
- end
-end
diff --git a/spec/ruby/shared/rational/divmod.rb b/spec/ruby/shared/rational/divmod.rb
deleted file mode 100644
index 9e23a18186..0000000000
--- a/spec/ruby/shared/rational/divmod.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :rational_divmod_rat, shared: true do
- it "returns the quotient as Integer and the remainder as Rational" do
- Rational(7, 4).divmod(Rational(1, 2)).should eql([3, Rational(1, 4)])
- Rational(7, 4).divmod(Rational(-1, 2)).should eql([-4, Rational(-1, 4)])
- Rational(0, 4).divmod(Rational(4, 3)).should eql([0, Rational(0, 1)])
-
- Rational(bignum_value, 4).divmod(Rational(4, 3)).should eql([3458764513820540928, Rational(0, 1)])
- end
-
- 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
-
-describe :rational_divmod_int, shared: true do
- it "returns the quotient as Integer and the remainder as Rational" do
- Rational(7, 4).divmod(2).should eql([0, Rational(7, 4)])
- Rational(7, 4).divmod(-2).should eql([-1, Rational(-1, 4)])
-
- Rational(bignum_value, 4).divmod(3).should eql([1537228672809129301, Rational(1, 1)])
- end
-
- it "raises a ZeroDivisionError when passed 0" do
- -> { Rational(7, 4).divmod(0) }.should raise_error(ZeroDivisionError)
- end
-end
-
-describe :rational_divmod_float, shared: true do
- it "returns the quotient as Integer and the remainder as Float" do
- Rational(7, 4).divmod(0.5).should eql([3, 0.25])
- end
-
- it "returns the quotient as Integer and the remainder as Float" do
- Rational(7, 4).divmod(-0.5).should eql([-4, -0.25])
- end
-
- it "raises a ZeroDivisionError when passed 0" do
- -> { Rational(7, 4).divmod(0.0) }.should raise_error(ZeroDivisionError)
- end
-end
diff --git a/spec/ruby/shared/rational/equal_value.rb b/spec/ruby/shared/rational/equal_value.rb
deleted file mode 100644
index b2e7e09415..0000000000
--- a/spec/ruby/shared/rational/equal_value.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :rational_equal_value_rat, shared: true do
- it "returns true if self has the same numerator and denominator as the passed argument" do
- (Rational(3, 4) == Rational(3, 4)).should be_true
- (Rational(-3, -4) == Rational(3, 4)).should be_true
- (Rational(-4, 5) == Rational(4, -5)).should be_true
-
- (Rational(bignum_value, 3) == Rational(bignum_value, 3)).should be_true
- (Rational(-bignum_value, 3) == Rational(bignum_value, -3)).should be_true
- end
-end
-
-describe :rational_equal_value_int, shared: true do
- it "returns true if self has the passed argument as numerator and a denominator of 1" do
- # Rational(x, y) reduces x and y automatically
- (Rational(4, 2) == 2).should be_true
- (Rational(-4, 2) == -2).should be_true
- (Rational(4, -2) == -2).should be_true
- end
-end
-
-describe :rational_equal_value_float, shared: true do
- it "converts self to a Float and compares it with the passed argument" do
- (Rational(3, 4) == 0.75).should be_true
- (Rational(4, 2) == 2.0).should be_true
- (Rational(-4, 2) == -2.0).should be_true
- (Rational(4, -2) == -2.0).should be_true
- end
-end
-
-describe :rational_equal_value, shared: true do
- it "returns the result of calling #== with self on the passed argument" do
- obj = mock("Object")
- obj.should_receive(:==).and_return(:result)
-
- (Rational(3, 4) == obj).should_not be_false
- end
-end
diff --git a/spec/ruby/shared/rational/exponent.rb b/spec/ruby/shared/rational/exponent.rb
deleted file mode 100644
index b0e9b23574..0000000000
--- a/spec/ruby/shared/rational/exponent.rb
+++ /dev/null
@@ -1,196 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :rational_exponent, shared: true do
- describe "when passed Rational" do
- # Guard against the Mathn library
- guard -> { !defined?(Math.rsqrt) } do
- it "returns Rational(1) if the exponent is Rational(0)" do
- (Rational(0) ** Rational(0)).should eql(Rational(1))
- (Rational(1) ** Rational(0)).should eql(Rational(1))
- (Rational(3, 4) ** Rational(0)).should eql(Rational(1))
- (Rational(-1) ** Rational(0)).should eql(Rational(1))
- (Rational(-3, 4) ** Rational(0)).should eql(Rational(1))
- (Rational(bignum_value) ** Rational(0)).should eql(Rational(1))
- (Rational(-bignum_value) ** Rational(0)).should eql(Rational(1))
- end
-
- it "returns self raised to the argument as a Rational if the exponent's denominator is 1" do
- (Rational(3, 4) ** Rational(1, 1)).should eql(Rational(3, 4))
- (Rational(3, 4) ** Rational(2, 1)).should eql(Rational(9, 16))
- (Rational(3, 4) ** Rational(-1, 1)).should eql(Rational(4, 3))
- (Rational(3, 4) ** Rational(-2, 1)).should eql(Rational(16, 9))
- end
-
- it "returns self raised to the argument as a Float if the exponent's denominator is not 1" do
- (Rational(3, 4) ** Rational(4, 3)).should be_close(0.681420222312052, TOLERANCE)
- (Rational(3, 4) ** Rational(-4, 3)).should be_close(1.46752322173095, TOLERANCE)
- (Rational(3, 4) ** Rational(4, -3)).should be_close(1.46752322173095, TOLERANCE)
- end
-
- it "returns a complex number when self is negative and the passed argument is not 0" do
- (Rational(-3, 4) ** Rational(-4, 3)).should be_close(Complex(-0.7337616108654732, 1.2709123906625817), TOLERANCE)
- end
- end
- end
-
- describe "when passed Integer" do
- it "returns the Rational value of self raised to the passed argument" do
- (Rational(3, 4) ** 4).should == Rational(81, 256)
- (Rational(3, 4) ** -4).should == Rational(256, 81)
- (Rational(-3, 4) ** -4).should == Rational(256, 81)
- (Rational(3, -4) ** -4).should == Rational(256, 81)
-
- (Rational(bignum_value, 4) ** 4).should == Rational(452312848583266388373324160190187140051835877600158453279131187530910662656, 1)
- (Rational(3, bignum_value) ** -4).should == Rational(115792089237316195423570985008687907853269984665640564039457584007913129639936, 81)
- (Rational(-bignum_value, 4) ** -4).should == Rational(1, 452312848583266388373324160190187140051835877600158453279131187530910662656)
- (Rational(3, -bignum_value) ** -4).should == Rational(115792089237316195423570985008687907853269984665640564039457584007913129639936, 81)
- end
-
- # Guard against the Mathn library
- guard -> { !defined?(Math.rsqrt) } do
- it "returns Rational(1, 1) when the passed argument is 0" do
- (Rational(3, 4) ** 0).should eql(Rational(1, 1))
- (Rational(-3, 4) ** 0).should eql(Rational(1, 1))
- (Rational(3, -4) ** 0).should eql(Rational(1, 1))
-
- (Rational(bignum_value, 4) ** 0).should eql(Rational(1, 1))
- (Rational(3, -bignum_value) ** 0).should eql(Rational(1, 1))
- end
- end
- end
-
- describe "when passed Bignum" do
- # #5713
- it "returns Rational(0) when self is Rational(0) and the exponent is positive" do
- (Rational(0) ** bignum_value).should eql(Rational(0))
- end
-
- it "raises ZeroDivisionError when self is Rational(0) and the exponent is negative" do
- -> { Rational(0) ** -bignum_value }.should raise_error(ZeroDivisionError)
- end
-
- it "returns Rational(1) when self is Rational(1)" do
- (Rational(1) ** bignum_value).should eql(Rational(1))
- (Rational(1) ** -bignum_value).should eql(Rational(1))
- end
-
- it "returns Rational(1) when self is Rational(-1) and the exponent is positive and even" do
- (Rational(-1) ** bignum_value(0)).should eql(Rational(1))
- (Rational(-1) ** bignum_value(2)).should eql(Rational(1))
- end
-
- it "returns Rational(-1) when self is Rational(-1) and the exponent is positive and odd" do
- (Rational(-1) ** bignum_value(1)).should eql(Rational(-1))
- (Rational(-1) ** bignum_value(3)).should eql(Rational(-1))
- end
-
- it "returns positive Infinity when self is > 1" do
- -> {
- (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)
- }.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
- }.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)
- }.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
-
- describe "when passed Float" do
- it "returns self converted to Float and raised to the passed argument" do
- (Rational(3, 1) ** 3.0).should eql(27.0)
- (Rational(3, 1) ** 1.5).should be_close(5.19615242270663, TOLERANCE)
- (Rational(3, 1) ** -1.5).should be_close(0.192450089729875, TOLERANCE)
- end
-
- it "returns a complex number if self is negative and the passed argument is not 0" do
- (Rational(-3, 2) ** 1.5).should be_close(Complex(0.0, -1.8371173070873836), TOLERANCE)
- (Rational(3, -2) ** 1.5).should be_close(Complex(0.0, -1.8371173070873836), TOLERANCE)
- (Rational(3, -2) ** -1.5).should be_close(Complex(0.0, 0.5443310539518174), TOLERANCE)
- end
-
- it "returns Complex(1.0) when the passed argument is 0.0" do
- (Rational(3, 4) ** 0.0).should == Complex(1.0)
- (Rational(-3, 4) ** 0.0).should == Complex(1.0)
- (Rational(-3, 4) ** 0.0).should == Complex(1.0)
- end
- end
-
- it "calls #coerce on the passed argument with self" do
- rational = Rational(3, 4)
- obj = mock("Object")
- obj.should_receive(:coerce).with(rational).and_return([1, 2])
-
- rational ** obj
- end
-
- it "calls #** on the coerced Rational with the coerced Object" do
- rational = Rational(3, 4)
-
- coerced_rational = mock("Coerced Rational")
- coerced_rational.should_receive(:**).and_return(:result)
-
- coerced_obj = mock("Coerced Object")
-
- obj = mock("Object")
- obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj])
-
- (rational ** obj).should == :result
- end
-
- it "raises ZeroDivisionError for Rational(0, 1) passed a negative Integer" do
- [-1, -4, -9999].each do |exponent|
- -> { Rational(0, 1) ** exponent }.should raise_error(ZeroDivisionError, "divided by 0")
- end
- end
-
- it "raises ZeroDivisionError for Rational(0, 1) passed a negative Rational with denominator 1" do
- [Rational(-1, 1), Rational(-3, 1)].each do |exponent|
- -> { Rational(0, 1) ** exponent }.should raise_error(ZeroDivisionError, "divided by 0")
- end
- end
-
- # #7513
- it "raises ZeroDivisionError for Rational(0, 1) passed a negative Rational" do
- -> { Rational(0, 1) ** Rational(-3, 2) }.should raise_error(ZeroDivisionError, "divided by 0")
- end
-
- platform_is_not :solaris do # See https://github.com/ruby/spec/issues/134
- it "returns Infinity for Rational(0, 1) passed a negative Float" do
- [-1.0, -3.0, -3.14].each do |exponent|
- (Rational(0, 1) ** exponent).infinite?.should == 1
- end
- end
- end
-end
diff --git a/spec/ruby/shared/rational/fdiv.rb b/spec/ruby/shared/rational/fdiv.rb
deleted file mode 100644
index 6911ade8ac..0000000000
--- a/spec/ruby/shared/rational/fdiv.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :rational_fdiv, shared: true do
- it "needs to be reviewed for spec completeness"
-end
diff --git a/spec/ruby/shared/rational/floor.rb b/spec/ruby/shared/rational/floor.rb
deleted file mode 100644
index ddf7fdbd17..0000000000
--- a/spec/ruby/shared/rational/floor.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :rational_floor, shared: true do
- before do
- @rational = Rational(2200, 7)
- end
-
- describe "with no arguments (precision = 0)" do
- it "returns an integer" do
- @rational.floor.should be_kind_of(Integer)
- end
-
- it "returns the truncated value toward negative infinity" do
- @rational.floor.should == 314
- Rational(1, 2).floor.should == 0
- Rational(-1, 2).floor.should == -1
- end
- end
-
- describe "with a precision < 0" do
- it "returns an integer" do
- @rational.floor(-2).should be_kind_of(Integer)
- @rational.floor(-1).should be_kind_of(Integer)
- end
-
- it "moves the truncation point n decimal places left" do
- @rational.floor(-3).should == 0
- @rational.floor(-2).should == 300
- @rational.floor(-1).should == 310
- end
- end
-
- describe "with a precision > 0" do
- it "returns a Rational" do
- @rational.floor(1).should be_kind_of(Rational)
- @rational.floor(2).should be_kind_of(Rational)
- end
-
- it "moves the truncation point n decimal places right" do
- @rational.floor(1).should == Rational(1571, 5)
- @rational.floor(2).should == Rational(7857, 25)
- @rational.floor(3).should == Rational(62857, 200)
- end
- end
-end
diff --git a/spec/ruby/shared/rational/hash.rb b/spec/ruby/shared/rational/hash.rb
deleted file mode 100644
index 50f21cec20..0000000000
--- a/spec/ruby/shared/rational/hash.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :rational_hash, shared: true do
- # BUG: Rational(2, 3).hash == Rational(3, 2).hash
- it "is static" do
- Rational(2, 3).hash.should == Rational(2, 3).hash
- Rational(2, 4).hash.should_not == Rational(2, 3).hash
- end
-end
diff --git a/spec/ruby/shared/rational/inspect.rb b/spec/ruby/shared/rational/inspect.rb
deleted file mode 100644
index 19691a2f25..0000000000
--- a/spec/ruby/shared/rational/inspect.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :rational_inspect, shared: true 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)"
-
- # Guard against the Mathn library
- guard -> { !defined?(Math.rsqrt) } do
- Rational(bignum_value, 1).inspect.should == "(#{bignum_value}/1)"
- end
- end
-end
diff --git a/spec/ruby/shared/rational/modulo.rb b/spec/ruby/shared/rational/modulo.rb
deleted file mode 100644
index 9e4b0c49e6..0000000000
--- a/spec/ruby/shared/rational/modulo.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :rational_modulo, shared: true do
- it "returns the remainder when this value is divided by other" do
- Rational(2, 3).send(@method, Rational(2, 3)).should == Rational(0, 1)
- Rational(4, 3).send(@method, Rational(2, 3)).should == Rational(0, 1)
- Rational(2, -3).send(@method, Rational(-2, 3)).should == Rational(0, 1)
- Rational(0, -1).send(@method, -1).should == Rational(0, 1)
-
- Rational(7, 4).send(@method, Rational(1, 2)).should == Rational(1, 4)
- Rational(7, 4).send(@method, 1).should == Rational(3, 4)
- Rational(7, 4).send(@method, Rational(1, 7)).should == Rational(1, 28)
-
- Rational(3, 4).send(@method, -1).should == Rational(-1, 4)
- Rational(1, -5).send(@method, -1).should == Rational(-1, 5)
- end
-
- it "returns a Float value when the argument is Float" do
- Rational(7, 4).send(@method, 1.0).should be_kind_of(Float)
- Rational(7, 4).send(@method, 1.0).should == 0.75
- Rational(7, 4).send(@method, 0.26).should be_close(0.19, 0.0001)
- end
-
- it "raises ZeroDivisionError on zero denominator" do
- -> {
- Rational(3, 5).send(@method, Rational(0, 1))
- }.should raise_error(ZeroDivisionError)
-
- -> {
- Rational(0, 1).send(@method, Rational(0, 1))
- }.should raise_error(ZeroDivisionError)
-
- -> {
- Rational(3, 5).send(@method, 0)
- }.should raise_error(ZeroDivisionError)
- end
-
- it "raises a ZeroDivisionError when the argument is 0.0" do
- -> {
- Rational(3, 5).send(@method, 0.0)
- }.should raise_error(ZeroDivisionError)
- end
-end
diff --git a/spec/ruby/shared/rational/multiply.rb b/spec/ruby/shared/rational/multiply.rb
deleted file mode 100644
index 9c861cf79d..0000000000
--- a/spec/ruby/shared/rational/multiply.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :rational_multiply_rat, shared: true do
- it "returns self divided by other as a Rational" do
- (Rational(3, 4) * Rational(3, 4)).should eql(Rational(9, 16))
- (Rational(2, 4) * Rational(1, 4)).should eql(Rational(1, 8))
-
- (Rational(3, 4) * Rational(0, 1)).should eql(Rational(0, 4))
- end
-end
-
-describe :rational_multiply_int, shared: true do
- it "returns self divided by other as a Rational" do
- (Rational(3, 4) * 2).should eql(Rational(3, 2))
- (Rational(2, 4) * 2).should eql(Rational(1, 1))
- (Rational(6, 7) * -2).should eql(Rational(-12, 7))
-
- (Rational(3, 4) * 0).should eql(Rational(0, 4))
- end
-end
-
-describe :rational_multiply_float, shared: true do
- it "returns self divided by other as a Float" do
- (Rational(3, 4) * 0.75).should eql(0.5625)
- (Rational(3, 4) * 0.25).should eql(0.1875)
- (Rational(3, 4) * 0.3).should be_close(0.225, TOLERANCE)
-
- (Rational(-3, 4) * 0.3).should be_close(-0.225, TOLERANCE)
- (Rational(3, -4) * 0.3).should be_close(-0.225, TOLERANCE)
- (Rational(3, 4) * -0.3).should be_close(-0.225, TOLERANCE)
-
- (Rational(3, 4) * 0.0).should eql(0.0)
- (Rational(-3, -4) * 0.0).should eql(0.0)
-
- (Rational(-3, 4) * 0.0).should eql(0.0)
- (Rational(3, -4) * 0.0).should eql(0.0)
- end
-end
-
-describe :rational_multiply, shared: true do
- it "calls #coerce on the passed argument with self" do
- rational = Rational(3, 4)
- obj = mock("Object")
- obj.should_receive(:coerce).with(rational).and_return([1, 2])
-
- rational * obj
- end
-
- it "calls #* on the coerced Rational with the coerced Object" do
- rational = Rational(3, 4)
-
- coerced_rational = mock("Coerced Rational")
- coerced_rational.should_receive(:*).and_return(:result)
-
- coerced_obj = mock("Coerced Object")
-
- obj = mock("Object")
- obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj])
-
- (rational * obj).should == :result
- end
-end
diff --git a/spec/ruby/shared/rational/numerator.rb b/spec/ruby/shared/rational/numerator.rb
deleted file mode 100644
index 50d768168c..0000000000
--- a/spec/ruby/shared/rational/numerator.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :rational_numerator, shared: true do
- it "returns the numerator" do
- Rational(3, 4).numerator.should equal(3)
- Rational(3, -4).numerator.should equal(-3)
-
- Rational(bignum_value, 1).numerator.should == bignum_value
- end
-end
diff --git a/spec/ruby/shared/rational/plus.rb b/spec/ruby/shared/rational/plus.rb
deleted file mode 100644
index b126360ee4..0000000000
--- a/spec/ruby/shared/rational/plus.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :rational_plus_rat, shared: true do
- it "returns the result of subtracting other from self as a Rational" do
- (Rational(3, 4) + Rational(0, 1)).should eql(Rational(3, 4))
- (Rational(3, 4) + Rational(1, 4)).should eql(Rational(1, 1))
-
- (Rational(3, 4) + Rational(2, 1)).should eql(Rational(11, 4))
- end
-end
-
-describe :rational_plus_int, shared: true do
- it "returns the result of subtracting other from self as a Rational" do
- (Rational(3, 4) + 1).should eql(Rational(7, 4))
- (Rational(3, 4) + 2).should eql(Rational(11, 4))
- end
-end
-
-describe :rational_plus_float, shared: true do
- it "returns the result of subtracting other from self as a Float" do
- (Rational(3, 4) + 0.2).should eql(0.95)
- (Rational(3, 4) + 2.5).should eql(3.25)
- end
-end
-
-describe :rational_plus, shared: true do
- it "calls #coerce on the passed argument with self" do
- rational = Rational(3, 4)
- obj = mock("Object")
- obj.should_receive(:coerce).with(rational).and_return([1, 2])
-
- rational + obj
- end
-
- it "calls #+ on the coerced Rational with the coerced Object" do
- rational = Rational(3, 4)
-
- coerced_rational = mock("Coerced Rational")
- coerced_rational.should_receive(:+).and_return(:result)
-
- coerced_obj = mock("Coerced Object")
-
- obj = mock("Object")
- obj.should_receive(:coerce).and_return([coerced_rational, coerced_obj])
-
- (rational + obj).should == :result
- end
-end
diff --git a/spec/ruby/shared/rational/remainder.rb b/spec/ruby/shared/rational/remainder.rb
deleted file mode 100644
index dd907608db..0000000000
--- a/spec/ruby/shared/rational/remainder.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :rational_remainder, shared: true do
- it "needs to be reviewed for spec completeness"
-end
diff --git a/spec/ruby/shared/rational/round.rb b/spec/ruby/shared/rational/round.rb
deleted file mode 100644
index 5b159ee3e6..0000000000
--- a/spec/ruby/shared/rational/round.rb
+++ /dev/null
@@ -1,106 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :rational_round, shared: true do
- before do
- @rational = Rational(2200, 7)
- end
-
- describe "with no arguments (precision = 0)" do
- it "returns an integer" do
- @rational.round.should be_kind_of(Integer)
- Rational(0, 1).round(0).should be_kind_of(Integer)
- Rational(124, 1).round(0).should be_kind_of(Integer)
- end
-
- it "returns the truncated value toward the nearest integer" do
- @rational.round.should == 314
- Rational(0, 1).round(0).should == 0
- Rational(2, 1).round(0).should == 2
- end
-
- it "returns the rounded value toward the nearest integer" do
- Rational(1, 2).round.should == 1
- Rational(-1, 2).round.should == -1
- Rational(3, 2).round.should == 2
- Rational(-3, 2).round.should == -2
- Rational(5, 2).round.should == 3
- Rational(-5, 2).round.should == -3
- end
- end
-
- describe "with a precision < 0" do
- it "returns an integer" do
- @rational.round(-2).should be_kind_of(Integer)
- @rational.round(-1).should be_kind_of(Integer)
- Rational(0, 1).round(-1).should be_kind_of(Integer)
- Rational(2, 1).round(-1).should be_kind_of(Integer)
- end
-
- it "moves the truncation point n decimal places left" do
- @rational.round(-3).should == 0
- @rational.round(-2).should == 300
- @rational.round(-1).should == 310
- end
- end
-
- describe "with a precision > 0" do
- it "returns a Rational" do
- @rational.round(1).should be_kind_of(Rational)
- @rational.round(2).should be_kind_of(Rational)
- # Guard against the Mathn library
- guard -> { !defined?(Math.rsqrt) } do
- Rational(0, 1).round(1).should be_kind_of(Rational)
- Rational(2, 1).round(1).should be_kind_of(Rational)
- end
- end
-
- it "moves the truncation point n decimal places right" do
- @rational.round(1).should == Rational(3143, 10)
- @rational.round(2).should == Rational(31429, 100)
- @rational.round(3).should == Rational(157143, 500)
- Rational(0, 1).round(1).should == Rational(0, 1)
- Rational(2, 1).round(1).should == Rational(2, 1)
- end
-
- it "doesn't alter the value if the precision is too great" do
- Rational(3, 2).round(10).should == Rational(3, 2).round(20)
- end
-
- # #6605
- it "doesn't fail when rounding to an absurdly large positive precision" do
- Rational(3, 2).round(2_097_171).should == Rational(3, 2)
- end
- end
-
- describe "with half option" do
- it "returns an Integer when precision is not passed" do
- Rational(10, 4).round(half: nil).should == 3
- Rational(10, 4).round(half: :up).should == 3
- Rational(10, 4).round(half: :down).should == 2
- Rational(10, 4).round(half: :even).should == 2
- Rational(-10, 4).round(half: nil).should == -3
- Rational(-10, 4).round(half: :up).should == -3
- Rational(-10, 4).round(half: :down).should == -2
- Rational(-10, 4).round(half: :even).should == -2
- end
-
- it "returns a Rational when the precision is greater than 0" do
- Rational(25, 100).round(1, half: nil).should == Rational(3, 10)
- Rational(25, 100).round(1, half: :up).should == Rational(3, 10)
- Rational(25, 100).round(1, half: :down).should == Rational(1, 5)
- Rational(25, 100).round(1, half: :even).should == Rational(1, 5)
- Rational(35, 100).round(1, half: nil).should == Rational(2, 5)
- Rational(35, 100).round(1, half: :up).should == Rational(2, 5)
- Rational(35, 100).round(1, half: :down).should == Rational(3, 10)
- Rational(35, 100).round(1, half: :even).should == Rational(2, 5)
- Rational(-25, 100).round(1, half: nil).should == Rational(-3, 10)
- Rational(-25, 100).round(1, half: :up).should == Rational(-3, 10)
- Rational(-25, 100).round(1, half: :down).should == Rational(-1, 5)
- Rational(-25, 100).round(1, half: :even).should == Rational(-1, 5)
- end
-
- it "raise for a non-existent round mode" do
- -> { Rational(10, 4).round(half: :nonsense) }.should raise_error(ArgumentError, "invalid rounding mode: nonsense")
- end
- end
-end
diff --git a/spec/ruby/shared/rational/to_f.rb b/spec/ruby/shared/rational/to_f.rb
deleted file mode 100644
index 472a585daa..0000000000
--- a/spec/ruby/shared/rational/to_f.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :rational_to_f, shared: true do
- it "returns self converted to a Float" do
- Rational(3, 4).to_f.should eql(0.75)
- Rational(3, -4).to_f.should eql(-0.75)
- Rational(-1, 4).to_f.should eql(-0.25)
- Rational(-1, -4).to_f.should eql(0.25)
- end
-
- it "converts to a Float for large numerator and denominator" do
- num = 1000000000000000000000000000000000048148248609680896326399448564623182963452541226153892315137780403285956264146010000000000000000000000000000000000048148248609680896326399448564623182963452541226153892315137780403285956264146010000000000000000000000000000000000048148248609680896326399448564623182963452541226153892315137780403285956264146009
- den = 2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
- Rational(num, den).to_f.should == 500.0
- end
-end
diff --git a/spec/ruby/shared/rational/to_i.rb b/spec/ruby/shared/rational/to_i.rb
deleted file mode 100644
index 9be1183aa4..0000000000
--- a/spec/ruby/shared/rational/to_i.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :rational_to_i, shared: true do
- it "converts self to an Integer by truncation" do
- Rational(7, 4).to_i.should eql(1)
- Rational(11, 4).to_i.should eql(2)
- end
-
- it "converts self to an Integer by truncation" do
- Rational(-7, 4).to_i.should eql(-1)
- end
-end
diff --git a/spec/ruby/shared/rational/to_r.rb b/spec/ruby/shared/rational/to_r.rb
deleted file mode 100644
index 372c086850..0000000000
--- a/spec/ruby/shared/rational/to_r.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :rational_to_r, shared: true do
- it "returns self" do
- a = Rational(3, 4)
- a.to_r.should equal(a)
-
- a = Rational(bignum_value, 4)
- a.to_r.should equal(a)
- end
-end
diff --git a/spec/ruby/shared/rational/to_s.rb b/spec/ruby/shared/rational/to_s.rb
deleted file mode 100644
index e90c6e5e39..0000000000
--- a/spec/ruby/shared/rational/to_s.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :rational_to_s, shared: true do
- it "returns a string representation of self" do
- # Guard against the Mathn library
- guard -> { !defined?(Math.rsqrt) } do
- Rational(1, 1).to_s.should == "1/1"
- Rational(2, 1).to_s.should == "2/1"
- end
- Rational(1, 2).to_s.should == "1/2"
- Rational(-1, 3).to_s.should == "-1/3"
- Rational(1, -3).to_s.should == "-1/3"
- end
-end
diff --git a/spec/ruby/shared/rational/truncate.rb b/spec/ruby/shared/rational/truncate.rb
deleted file mode 100644
index df5198ca02..0000000000
--- a/spec/ruby/shared/rational/truncate.rb
+++ /dev/null
@@ -1,71 +0,0 @@
-require_relative '../../spec_helper'
-
-describe :rational_truncate, shared: true do
- before do
- @rational = Rational(2200, 7)
- end
-
- describe "with no arguments (precision = 0)" do
- it "returns an integer" do
- @rational.truncate.should be_kind_of(Integer)
- end
-
- it "returns the truncated value toward 0" do
- @rational.truncate.should == 314
- Rational(1, 2).truncate.should == 0
- Rational(-1, 2).truncate.should == 0
- end
- end
-
- describe "with an explicit precision = 0" do
- it "returns an integer" do
- @rational.truncate(0).should be_kind_of(Integer)
- end
-
- it "returns the truncated value toward 0" do
- @rational.truncate(0).should == 314
- Rational(1, 2).truncate(0).should == 0
- Rational(-1, 2).truncate(0).should == 0
- end
- end
-
- describe "with a precision < 0" do
- it "returns an integer" do
- @rational.truncate(-2).should be_kind_of(Integer)
- @rational.truncate(-1).should be_kind_of(Integer)
- end
-
- it "moves the truncation point n decimal places left" do
- @rational.truncate(-3).should == 0
- @rational.truncate(-2).should == 300
- @rational.truncate(-1).should == 310
- end
- end
-
- describe "with a precision > 0" do
- it "returns a Rational" do
- @rational.truncate(1).should be_kind_of(Rational)
- @rational.truncate(2).should be_kind_of(Rational)
- end
-
- it "moves the truncation point n decimal places right" do
- @rational.truncate(1).should == Rational(1571, 5)
- @rational.truncate(2).should == Rational(7857, 25)
- @rational.truncate(3).should == Rational(62857, 200)
- end
- end
-
- describe "with an invalid value for precision" do
- it "raises a TypeError" do
- -> { @rational.truncate(nil) }.should raise_error(TypeError, "not an integer")
- -> { @rational.truncate(1.0) }.should raise_error(TypeError, "not an integer")
- -> { @rational.truncate('') }.should raise_error(TypeError, "not an integer")
- end
-
- it "does not call to_int on the argument" do
- object = Object.new
- object.should_not_receive(:to_int)
- -> { @rational.truncate(object) }.should raise_error(TypeError, "not an integer")
- end
- end
-end
diff --git a/spec/ruby/shared/sizedqueue/enque.rb b/spec/ruby/shared/sizedqueue/enque.rb
index 2f25517675..6804af3fb3 100644
--- a/spec/ruby/shared/sizedqueue/enque.rb
+++ b/spec/ruby/shared/sizedqueue/enque.rb
@@ -49,83 +49,81 @@ describe :sizedqueue_enq, shared: true do
end
describe "with a timeout" do
- ruby_version_is "3.2" do
- it "returns self if the item was pushed in time" do
- q = @object.call(1)
- q << 1
-
- t = Thread.new {
- q.send(@method, 2, timeout: TIME_TOLERANCE).should == q
- }
- Thread.pass until t.status == "sleep" && q.num_waiting == 1
- q.pop
- t.join
- end
-
- it "does nothing if the timeout is nil" do
- q = @object.call(1)
- q << 1
- t = Thread.new {
- q.send(@method, 2, timeout: nil).should == q
- }
- t.join(0.2).should == nil
- q.pop
- t.join
- end
-
- it "returns nil if no space is available and timeout is 0" do
- q = @object.call(1)
- q.send(@method, 1, timeout: 0).should == q
- q.send(@method, 2, timeout: 0).should == nil
- end
-
- it "returns nil if no space is available in time" do
- q = @object.call(1)
- q << 1
- Thread.new {
- q.send(@method, 2, timeout: 0.001).should == nil
- }.join
- end
-
- it "raise TypeError if timeout is not a valid numeric" do
- q = @object.call(1)
- -> {
- q.send(@method, 2, timeout: "1")
- }.should raise_error(TypeError, "no implicit conversion to float from string")
-
- -> {
- q.send(@method, 2, timeout: false)
- }.should raise_error(TypeError, "no implicit conversion to float from false")
- end
-
- it "raise ArgumentError if non_block = true is passed too" do
- q = @object.call(1)
- -> {
- q.send(@method, 2, true, timeout: 1)
- }.should raise_error(ArgumentError, "can't set a timeout if non_block is enabled")
- end
-
- it "raise ClosedQueueError when closed before enqueued" do
- q = @object.call(1)
- q.close
- -> { q.send(@method, 2, timeout: 1) }.should raise_error(ClosedQueueError, "queue closed")
- end
-
- it "interrupts enqueuing threads with ClosedQueueError when the queue is closed" do
- q = @object.call(1)
- q << 1
-
- t = Thread.new {
- -> { q.send(@method, 1, timeout: TIME_TOLERANCE) }.should raise_error(ClosedQueueError, "queue closed")
- }
-
- Thread.pass until q.num_waiting == 1
-
- q.close
-
- t.join
- q.pop.should == 1
- end
+ it "returns self if the item was pushed in time" do
+ q = @object.call(1)
+ q << 1
+
+ t = Thread.new {
+ q.send(@method, 2, timeout: TIME_TOLERANCE).should == q
+ }
+ Thread.pass until t.status == "sleep" && q.num_waiting == 1
+ q.pop
+ t.join
+ end
+
+ it "does nothing if the timeout is nil" do
+ q = @object.call(1)
+ q << 1
+ t = Thread.new {
+ q.send(@method, 2, timeout: nil).should == q
+ }
+ t.join(0.2).should == nil
+ q.pop
+ t.join
+ end
+
+ it "returns nil if no space is available and timeout is 0" do
+ q = @object.call(1)
+ q.send(@method, 1, timeout: 0).should == q
+ q.send(@method, 2, timeout: 0).should == nil
+ end
+
+ it "returns nil if no space is available in time" do
+ q = @object.call(1)
+ q << 1
+ Thread.new {
+ q.send(@method, 2, timeout: 0.001).should == nil
+ }.join
+ end
+
+ it "raise TypeError if timeout is not a valid numeric" do
+ q = @object.call(1)
+ -> {
+ q.send(@method, 2, timeout: "1")
+ }.should raise_error(TypeError, "no implicit conversion to float from string")
+
+ -> {
+ q.send(@method, 2, timeout: false)
+ }.should raise_error(TypeError, "no implicit conversion to float from false")
+ end
+
+ it "raise ArgumentError if non_block = true is passed too" do
+ q = @object.call(1)
+ -> {
+ q.send(@method, 2, true, timeout: 1)
+ }.should raise_error(ArgumentError, "can't set a timeout if non_block is enabled")
+ end
+
+ it "raise ClosedQueueError when closed before enqueued" do
+ q = @object.call(1)
+ q.close
+ -> { q.send(@method, 2, timeout: 1) }.should raise_error(ClosedQueueError, "queue closed")
+ end
+
+ it "interrupts enqueuing threads with ClosedQueueError when the queue is closed" do
+ q = @object.call(1)
+ q << 1
+
+ t = Thread.new {
+ -> { q.send(@method, 1, timeout: TIME_TOLERANCE) }.should raise_error(ClosedQueueError, "queue closed")
+ }
+
+ Thread.pass until q.num_waiting == 1
+
+ q.close
+
+ t.join
+ q.pop.should == 1
end
end
end
diff --git a/spec/ruby/shared/string/end_with.rb b/spec/ruby/shared/string/end_with.rb
index 94a7f97513..08f43c1bce 100644
--- a/spec/ruby/shared/string/end_with.rb
+++ b/spec/ruby/shared/string/end_with.rb
@@ -55,7 +55,7 @@ describe :end_with, shared: true do
it "checks that we are starting to match at the head of a character" do
"\xC3\xA9".send(@method).should_not.end_with?("\xA9")
"\xe3\x81\x82".send(@method).should_not.end_with?("\x82")
- "ab".dup.force_encoding("UTF-16BE").send(@method).should_not.end_with?(
- "b".dup.force_encoding("UTF-16BE"))
+ "\xd8\x00\xdc\x00".dup.force_encoding("UTF-16BE").send(@method).should_not.end_with?(
+ "\xdc\x00".dup.force_encoding("UTF-16BE"))
end
end
diff --git a/spec/ruby/shared/string/times.rb b/spec/ruby/shared/string/times.rb
index aaf748bad9..4814f894cf 100644
--- a/spec/ruby/shared/string/times.rb
+++ b/spec/ruby/shared/string/times.rb
@@ -44,13 +44,13 @@ describe :string_times, shared: true do
result.encoding.should equal(Encoding::UTF_8)
end
- platform_is wordsize: 32 do
+ platform_is c_long_size: 32 do
it "raises an ArgumentError if the length of the resulting string doesn't fit into a long" do
-> { @object.call("abc", (2 ** 31) - 1) }.should raise_error(ArgumentError)
end
end
- platform_is wordsize: 64 do
+ platform_is c_long_size: 64 do
it "raises an ArgumentError if the length of the resulting string doesn't fit into a long" do
-> { @object.call("abc", (2 ** 63) - 1) }.should raise_error(ArgumentError)
end
diff --git a/spec/ruby/shared/time/yday.rb b/spec/ruby/shared/time/yday.rb
new file mode 100644
index 0000000000..f81c45261c
--- /dev/null
+++ b/spec/ruby/shared/time/yday.rb
@@ -0,0 +1,18 @@
+describe :time_yday, shared: true do
+ it 'returns the correct value for each day of each month' do
+ mdays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
+
+ yday = 1
+ mdays.each_with_index do |days, month|
+ days.times do |day|
+ @method.call(2014, month+1, day+1).should == yday
+ yday += 1
+ end
+ end
+ end
+
+ it 'supports leap years' do
+ @method.call(2016, 2, 29).should == 31 + 29
+ @method.call(2016, 3, 1).should == 31 + 29 + 1
+ end
+end
diff --git a/spec/syntax_suggest/integration/syntax_suggest_spec.rb b/spec/syntax_suggest/integration/syntax_suggest_spec.rb
index 9071d37c1b..015d088c92 100644
--- a/spec/syntax_suggest/integration/syntax_suggest_spec.rb
+++ b/spec/syntax_suggest/integration/syntax_suggest_spec.rb
@@ -4,6 +4,10 @@ require_relative "../spec_helper"
module SyntaxSuggest
RSpec.describe "Integration tests that don't spawn a process (like using the cli)" do
+ before(:each) do
+ skip "Benchmark is not available" unless defined?(::Benchmark)
+ end
+
it "does not timeout on massive files" do
next unless ENV["SYNTAX_SUGGEST_TIMEOUT"]
diff --git a/spec/syntax_suggest/spec_helper.rb b/spec/syntax_suggest/spec_helper.rb
index 89bc9f4ab1..b5d2924e69 100644
--- a/spec/syntax_suggest/spec_helper.rb
+++ b/spec/syntax_suggest/spec_helper.rb
@@ -3,7 +3,10 @@
require "bundler/setup"
require "syntax_suggest/api"
-require "benchmark"
+begin
+ require "benchmark"
+rescue LoadError
+end
require "tempfile"
RSpec.configure do |config|
diff --git a/spec/syntax_suggest/unit/mini_stringio_spec.rb b/spec/syntax_suggest/unit/mini_stringio_spec.rb
new file mode 100644
index 0000000000..75d94deae1
--- /dev/null
+++ b/spec/syntax_suggest/unit/mini_stringio_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require_relative "../spec_helper"
+
+module SyntaxSuggest
+ RSpec.describe "MiniStringIO" do
+ it "#puts with no inputs" do
+ io = MiniStringIO.new
+ io.puts
+ expect(io.string).to eq($/)
+ end
+
+ it "#puts with an input" do
+ io = MiniStringIO.new
+ io.puts "Hello"
+ expect(io.string).to eq(["Hello", $/].join)
+ end
+
+ it "#puts with an input with a newline" do
+ io = MiniStringIO.new
+ io.puts "Hello\n"
+ expect(io.string).to eq(["Hello\n", $/].join)
+ end
+ end
+end
diff --git a/sprintf.c b/sprintf.c
index 98877d25d2..de88a9f4b3 100644
--- a/sprintf.c
+++ b/sprintf.c
@@ -67,7 +67,8 @@ sign_bits(int base, const char *p)
#define CHECK(l) do {\
int cr = ENC_CODERANGE(result);\
- while ((l) >= bsiz - blen) {\
+ RUBY_ASSERT(bsiz >= blen); \
+ while ((l) > bsiz - blen) {\
bsiz*=2;\
if (bsiz<0) rb_raise(rb_eArgError, "too big specifier");\
}\
@@ -247,8 +248,7 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
}
#define update_coderange(partial) do { \
- if (coderange != ENC_CODERANGE_BROKEN && scanned < blen \
- && rb_enc_to_index(enc) /* != ENCINDEX_ASCII_8BIT */) { \
+ if (coderange != ENC_CODERANGE_BROKEN && scanned < blen) { \
int cr = coderange; \
scanned += rb_str_coderange_scan_restartable(buf+scanned, buf+blen, enc, &cr); \
ENC_CODERANGE_SET(result, \
@@ -441,7 +441,7 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
VALUE val = GETARG();
VALUE tmp;
unsigned int c;
- int n;
+ int n, encidx;
tmp = rb_check_string_type(val);
if (!NIL_P(tmp)) {
@@ -451,11 +451,13 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
goto format_s1;
}
n = NUM2INT(val);
- if (n >= 0) n = rb_enc_codelen((c = n), enc);
+ if (n >= 0) {
+ n = rb_enc_codelen((c = n), enc);
+ encidx = rb_ascii8bit_appendable_encoding_index(enc, c);
+ }
if (n <= 0) {
rb_raise(rb_eArgError, "invalid character");
}
- int encidx = rb_ascii8bit_appendable_encoding_index(enc, c);
if (encidx >= 0 && encidx != rb_enc_to_index(enc)) {
/* special case */
rb_enc_associate_index(result, encidx);
@@ -808,7 +810,7 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
if (FIXNUM_P(num)) {
if ((SIGNED_VALUE)num < 0) {
long n = -FIX2LONG(num);
- num = LONG2FIX(n);
+ num = LONG2NUM(n);
sign = -1;
}
}
@@ -937,7 +939,7 @@ rb_str_format(int argc, const VALUE *argv, VALUE fmt)
rb_str_tmp_frozen_release(orig, fmt);
/* XXX - We cannot validate the number of arguments if (digit)$ style used.
*/
- if (posarg >= 0 && nextarg < argc) {
+ if (posarg >= 0 && nextarg < argc && !(argc == 2 && RB_TYPE_P(argv[1], T_HASH))) {
const char *mesg = "too many arguments for format string";
if (RTEST(ruby_debug)) rb_raise(rb_eArgError, "%s", mesg);
if (RTEST(ruby_verbose)) rb_warn("%s", mesg);
@@ -1165,7 +1167,9 @@ ruby_vsprintf0(VALUE result, char *p, const char *fmt, va_list ap)
RBASIC_SET_CLASS_RAW(result, klass);
p = RSTRING_PTR(result);
long blen = (char *)f._p - p;
- if (scanned < blen) {
+
+ coderange = ENC_CODERANGE(result);
+ if (coderange != ENC_CODERANGE_UNKNOWN && scanned < blen) {
rb_str_coderange_scan_restartable(p + scanned, p + blen, rb_enc_get(result), &coderange);
ENC_CODERANGE_SET(result, coderange);
}
diff --git a/st.c b/st.c
index 4f0259a237..8937f7935f 100644
--- a/st.c
+++ b/st.c
@@ -103,12 +103,15 @@
#ifdef NOT_RUBY
#include "regint.h"
#include "st.h"
+#include <assert.h>
#elif defined RUBY_EXPORT
#include "internal.h"
#include "internal/bits.h"
#include "internal/hash.h"
#include "internal/sanitizers.h"
+#include "internal/set_table.h"
#include "internal/st.h"
+#include "ruby_assert.h"
#endif
#include <stdio.h>
@@ -116,7 +119,6 @@
#include <stdlib.h>
#endif
#include <string.h>
-#include <assert.h>
#ifdef __GNUC__
#define PREFETCH(addr, write_p) __builtin_prefetch(addr, write_p)
@@ -314,17 +316,22 @@ static const struct st_features features[] = {
#define RESERVED_HASH_VAL (~(st_hash_t) 0)
#define RESERVED_HASH_SUBSTITUTION_VAL ((st_hash_t) 0)
-/* Return hash value of KEY for table TAB. */
static inline st_hash_t
-do_hash(st_data_t key, st_table *tab)
+normalize_hash_value(st_hash_t hash)
{
- st_hash_t hash = (st_hash_t)(tab->type->hash)(key);
-
/* RESERVED_HASH_VAL is used for a deleted entry. Map it into
another value. Such mapping should be extremely rare. */
return hash == RESERVED_HASH_VAL ? RESERVED_HASH_SUBSTITUTION_VAL : hash;
}
+/* Return hash value of KEY for table TAB. */
+static inline st_hash_t
+do_hash(st_data_t key, st_table *tab)
+{
+ st_hash_t hash = (st_hash_t)(tab->type->hash)(key);
+ return normalize_hash_value(hash);
+}
+
/* Power of 2 defining the minimal number of allocated entries. */
#define MINIMAL_POWER2 2
@@ -667,6 +674,7 @@ st_free_table(st_table *tab)
size_t
st_memsize(const st_table *tab)
{
+ RUBY_ASSERT(tab != NULL);
return(sizeof(st_table)
+ (tab->bins == NULL ? 0 : bins_size(tab))
+ get_allocated_entries(tab) * sizeof(st_table_entry));
@@ -741,7 +749,7 @@ rebuild_table(st_table *tab)
else {
st_table *new_tab;
/* This allocation could trigger GC and compaction. If tab is the
- * gen_iv_tbl, then tab could have changed in size due to objects being
+ * gen_fields_tbl, then tab could have changed in size due to objects being
* freed and/or moved. Do not store attributes of tab before this line. */
new_tab = st_init_table_with_size(tab->type,
2 * tab->num_entries - 1);
@@ -784,6 +792,8 @@ rebuild_table_with(st_table *const new_tab, st_table *const tab)
new_tab->num_entries++;
ni++;
}
+
+ assert(new_tab->num_entries == tab->num_entries);
}
static void
@@ -1173,6 +1183,8 @@ st_add_direct_with_hash(st_table *tab,
st_index_t ind;
st_index_t bin_ind;
+ assert(hash != RESERVED_HASH_VAL);
+
rebuild_table_if_necessary(tab);
ind = tab->entries_bound++;
entry = &tab->entries[ind];
@@ -1190,7 +1202,7 @@ void
rb_st_add_direct_with_hash(st_table *tab,
st_data_t key, st_data_t value, st_hash_t hash)
{
- st_add_direct_with_hash(tab, key, value, hash);
+ st_add_direct_with_hash(tab, key, value, normalize_hash_value(hash));
}
/* Insert (KEY, VALUE) into table TAB. The table should not have
@@ -1484,7 +1496,16 @@ st_update(st_table *tab, st_data_t key,
value = entry->record;
}
old_key = key;
+
+ unsigned int rebuilds_num = tab->rebuilds_num;
+
retval = (*func)(&key, &value, arg, existing);
+
+ // We need to make sure that the callback didn't cause a table rebuild
+ // Ideally we would make sure no operations happened
+ assert(rebuilds_num == tab->rebuilds_num);
+ (void)rebuilds_num;
+
switch (retval) {
case ST_CONTINUE:
if (! existing) {
@@ -2309,20 +2330,6 @@ rb_hash_bulk_insert_into_st_table(long argc, const VALUE *argv, VALUE hash)
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");
- }
-}
-
void
rb_st_compact_table(st_table *tab)
{
@@ -2336,4 +2343,882 @@ rb_st_compact_table(st_table *tab)
}
}
+/*
+ * set_table related code
+ */
+
+struct set_table_entry {
+ st_hash_t hash;
+ st_data_t key;
+};
+
+/* Return hash value of KEY for table TAB. */
+static inline st_hash_t
+set_do_hash(st_data_t key, set_table *tab)
+{
+ st_hash_t hash = (st_hash_t)(tab->type->hash)(key);
+ return normalize_hash_value(hash);
+}
+
+/* Return bin size index of table TAB. */
+static inline unsigned int
+set_get_size_ind(const set_table *tab)
+{
+ return tab->size_ind;
+}
+
+/* Return the number of allocated bins of table TAB. */
+static inline st_index_t
+set_get_bins_num(const set_table *tab)
+{
+ return ((st_index_t) 1)<<tab->bin_power;
+}
+
+/* Return mask for a bin index in table TAB. */
+static inline st_index_t
+set_bins_mask(const set_table *tab)
+{
+ return set_get_bins_num(tab) - 1;
+}
+
+/* Return the index of table TAB bin corresponding to
+ HASH_VALUE. */
+static inline st_index_t
+set_hash_bin(st_hash_t hash_value, set_table *tab)
+{
+ return hash_value & set_bins_mask(tab);
+}
+
+/* Return the number of allocated entries of table TAB. */
+static inline st_index_t
+set_get_allocated_entries(const set_table *tab)
+{
+ return ((st_index_t) 1)<<tab->entry_power;
+}
+
+static inline size_t
+set_allocated_entries_size(const set_table *tab)
+{
+ return set_get_allocated_entries(tab) * sizeof(set_table_entry);
+}
+
+static inline bool
+set_has_bins(const set_table *tab)
+{
+ return tab->entry_power > MAX_POWER2_FOR_TABLES_WITHOUT_BINS;
+}
+
+/* Return size of the allocated bins of table TAB. */
+static inline st_index_t
+set_bins_size(const set_table *tab)
+{
+ if (set_has_bins(tab)) {
+ return features[tab->entry_power].bins_words * sizeof (st_index_t);
+ }
+
+ return 0;
+}
+
+static inline st_index_t *
+set_bins_ptr(const set_table *tab)
+{
+ if (set_has_bins(tab)) {
+ return (st_index_t *)(((char *)tab->entries) + set_allocated_entries_size(tab));
+ }
+
+ return NULL;
+}
+
+/* Mark all bins of table TAB as empty. */
+static void
+set_initialize_bins(set_table *tab)
+{
+ memset(set_bins_ptr(tab), 0, set_bins_size(tab));
+}
+
+/* Make table TAB empty. */
+static void
+set_make_tab_empty(set_table *tab)
+{
+ tab->num_entries = 0;
+ tab->entries_start = tab->entries_bound = 0;
+ if (set_bins_ptr(tab) != NULL)
+ set_initialize_bins(tab);
+}
+
+static set_table *
+set_init_existing_table_with_size(set_table *tab, const struct st_hash_type *type, st_index_t size)
+{
+ int n;
+
+#ifdef HASH_LOG
+#if HASH_LOG+0 < 0
+ {
+ const char *e = getenv("ST_HASH_LOG");
+ if (!e || !*e) init_st = 1;
+ }
+#endif
+ if (init_st == 0) {
+ init_st = 1;
+ atexit(stat_col);
+ }
+#endif
+
+ n = get_power2(size);
+
+ tab->type = type;
+ tab->entry_power = n;
+ tab->bin_power = features[n].bin_power;
+ tab->size_ind = features[n].size_ind;
+
+ size_t memsize = 0;
+ if (set_has_bins(tab)) {
+ memsize += set_bins_size(tab);
+ }
+ memsize += set_get_allocated_entries(tab) * sizeof(set_table_entry);
+ tab->entries = (set_table_entry *)malloc(memsize);
+ set_make_tab_empty(tab);
+ tab->rebuilds_num = 0;
+ return tab;
+}
+
+/* Create and return table with TYPE which can hold at least SIZE
+ entries. The real number of entries which the table can hold is
+ the nearest power of two for SIZE. */
+set_table *
+set_init_table_with_size(set_table *tab, const struct st_hash_type *type, st_index_t size)
+{
+ if (tab == NULL) tab = malloc(sizeof(set_table));
+
+ set_init_existing_table_with_size(tab, type, size);
+
+ return tab;
+}
+
+set_table *
+set_init_numtable(void)
+{
+ return set_init_table_with_size(NULL, &type_numhash, 0);
+}
+
+set_table *
+set_init_numtable_with_size(st_index_t size)
+{
+ return set_init_table_with_size(NULL, &type_numhash, size);
+}
+
+size_t
+set_table_size(const struct set_table *tbl)
+{
+ return tbl->num_entries;
+}
+
+/* Make table TAB empty. */
+void
+set_table_clear(set_table *tab)
+{
+ set_make_tab_empty(tab);
+ tab->rebuilds_num++;
+}
+
+/* Free table TAB space. This should only be used if you passed NULL to
+ set_init_table_with_size/set_copy when creating the table. */
+void
+set_free_table(set_table *tab)
+{
+ free(tab->entries);
+ free(tab);
+}
+
+/* Return byte size of memory allocated for table TAB. */
+size_t
+set_memsize(const set_table *tab)
+{
+ return(sizeof(set_table)
+ + (tab->entry_power <= MAX_POWER2_FOR_TABLES_WITHOUT_BINS ? 0 : set_bins_size(tab))
+ + set_get_allocated_entries(tab) * sizeof(set_table_entry));
+}
+
+static st_index_t
+set_find_table_entry_ind(set_table *tab, st_hash_t hash_value, st_data_t key);
+
+static st_index_t
+set_find_table_bin_ind(set_table *tab, st_hash_t hash_value, st_data_t key);
+
+static st_index_t
+set_find_table_bin_ind_direct(set_table *table, st_hash_t hash_value, st_data_t key);
+
+static st_index_t
+set_find_table_bin_ptr_and_reserve(set_table *tab, st_hash_t *hash_value,
+ st_data_t key, st_index_t *bin_ind);
+
+static void set_rebuild_table_with(set_table *const new_tab, set_table *const tab);
+static void set_rebuild_move_table(set_table *const new_tab, set_table *const tab);
+static void set_rebuild_cleanup(set_table *const tab);
+
+/* Rebuild table TAB. Rebuilding removes all deleted bins and entries
+ and can change size of the table entries and bins arrays.
+ Rebuilding is implemented by creation of a new table or by
+ compaction of the existing one. */
+static void
+set_rebuild_table(set_table *tab)
+{
+ if ((2 * tab->num_entries <= set_get_allocated_entries(tab)
+ && REBUILD_THRESHOLD * tab->num_entries > set_get_allocated_entries(tab))
+ || tab->num_entries < (1 << MINIMAL_POWER2)) {
+ /* Compaction: */
+ tab->num_entries = 0;
+ if (set_has_bins(tab))
+ set_initialize_bins(tab);
+ set_rebuild_table_with(tab, tab);
+ }
+ else {
+ set_table *new_tab;
+ /* This allocation could trigger GC and compaction. If tab is the
+ * gen_fields_tbl, then tab could have changed in size due to objects being
+ * freed and/or moved. Do not store attributes of tab before this line. */
+ new_tab = set_init_table_with_size(NULL, tab->type,
+ 2 * tab->num_entries - 1);
+ set_rebuild_table_with(new_tab, tab);
+ set_rebuild_move_table(new_tab, tab);
+ }
+ set_rebuild_cleanup(tab);
+}
+
+static void
+set_rebuild_table_with(set_table *const new_tab, set_table *const tab)
+{
+ st_index_t i, ni;
+ unsigned int size_ind;
+ set_table_entry *new_entries;
+ set_table_entry *curr_entry_ptr;
+ st_index_t *bins;
+ st_index_t bin_ind;
+
+ new_entries = new_tab->entries;
+
+ ni = 0;
+ bins = set_bins_ptr(new_tab);
+ size_ind = set_get_size_ind(new_tab);
+ st_index_t bound = tab->entries_bound;
+ set_table_entry *entries = tab->entries;
+
+ for (i = tab->entries_start; i < bound; i++) {
+ curr_entry_ptr = &entries[i];
+ PREFETCH(entries + i + 1, 0);
+ if (EXPECT(DELETED_ENTRY_P(curr_entry_ptr), 0))
+ continue;
+ if (&new_entries[ni] != curr_entry_ptr)
+ new_entries[ni] = *curr_entry_ptr;
+ if (EXPECT(bins != NULL, 1)) {
+ bin_ind = set_find_table_bin_ind_direct(new_tab, curr_entry_ptr->hash,
+ curr_entry_ptr->key);
+ set_bin(bins, size_ind, bin_ind, ni + ENTRY_BASE);
+ }
+ new_tab->num_entries++;
+ ni++;
+ }
+
+ assert(new_tab->num_entries == tab->num_entries);
+}
+
+static void
+set_rebuild_move_table(set_table *const new_tab, set_table *const tab)
+{
+ tab->entry_power = new_tab->entry_power;
+ tab->bin_power = new_tab->bin_power;
+ tab->size_ind = new_tab->size_ind;
+ free(tab->entries);
+ tab->entries = new_tab->entries;
+ free(new_tab);
+}
+
+static void
+set_rebuild_cleanup(set_table *const tab)
+{
+ tab->entries_start = 0;
+ tab->entries_bound = tab->num_entries;
+ tab->rebuilds_num++;
+}
+
+/* Return the next secondary hash index for table TAB using previous
+ index IND and PERTURB. Finally modulo of the function becomes a
+ full *cycle linear congruential generator*, in other words it
+ 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 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.
+
+ For our case a is 5, c is 1, and m is a power of two. */
+static inline st_index_t
+set_secondary_hash(st_index_t ind, set_table *tab, st_index_t *perturb)
+{
+ *perturb >>= 11;
+ ind = (ind << 2) + ind + *perturb + 1;
+ return set_hash_bin(ind, tab);
+}
+
+/* Find an entry with HASH_VALUE and KEY in TABLE using a linear
+ search. Return the index of the found entry in array `entries`.
+ If it is not found, return UNDEFINED_ENTRY_IND. If the table was
+ rebuilt during the search, return REBUILT_TABLE_ENTRY_IND. */
+static inline st_index_t
+set_find_entry(set_table *tab, st_hash_t hash_value, st_data_t key)
+{
+ int eq_p, rebuilt_p;
+ st_index_t i, bound;
+ set_table_entry *entries;
+
+ bound = tab->entries_bound;
+ entries = tab->entries;
+ for (i = tab->entries_start; i < bound; i++) {
+ DO_PTR_EQUAL_CHECK(tab, &entries[i], hash_value, key, eq_p, rebuilt_p);
+ if (EXPECT(rebuilt_p, 0))
+ return REBUILT_TABLE_ENTRY_IND;
+ if (eq_p)
+ return i;
+ }
+ return UNDEFINED_ENTRY_IND;
+}
+
+/* Use the quadratic probing. The method has a better data locality
+ but more collisions than the current approach. In average it
+ results in a bit slower search. */
+/*#define QUADRATIC_PROBE*/
+
+/* Return index of entry with HASH_VALUE and KEY in table TAB. If
+ there is no such entry, return UNDEFINED_ENTRY_IND. If the table
+ was rebuilt during the search, return REBUILT_TABLE_ENTRY_IND. */
+static st_index_t
+set_find_table_entry_ind(set_table *tab, st_hash_t hash_value, st_data_t key)
+{
+ int eq_p, rebuilt_p;
+ st_index_t ind;
+#ifdef QUADRATIC_PROBE
+ st_index_t d;
+#else
+ st_index_t perturb;
+#endif
+ st_index_t bin;
+ set_table_entry *entries = tab->entries;
+
+ ind = set_hash_bin(hash_value, tab);
+#ifdef QUADRATIC_PROBE
+ d = 1;
+#else
+ perturb = hash_value;
+#endif
+ for (;;) {
+ bin = get_bin(set_bins_ptr(tab), set_get_size_ind(tab), ind);
+ if (! EMPTY_OR_DELETED_BIN_P(bin)) {
+ DO_PTR_EQUAL_CHECK(tab, &entries[bin - ENTRY_BASE], hash_value, key, eq_p, rebuilt_p);
+ if (EXPECT(rebuilt_p, 0))
+ return REBUILT_TABLE_ENTRY_IND;
+ if (eq_p)
+ break;
+ }
+ else if (EMPTY_BIN_P(bin))
+ return UNDEFINED_ENTRY_IND;
+#ifdef QUADRATIC_PROBE
+ ind = set_hash_bin(ind + d, tab);
+ d++;
+#else
+ ind = set_secondary_hash(ind, tab, &perturb);
+#endif
+ }
+ return bin;
+}
+
+/* Find and return index of table TAB bin corresponding to an entry
+ with HASH_VALUE and KEY. If there is no such bin, return
+ UNDEFINED_BIN_IND. If the table was rebuilt during the search,
+ return REBUILT_TABLE_BIN_IND. */
+static st_index_t
+set_find_table_bin_ind(set_table *tab, st_hash_t hash_value, st_data_t key)
+{
+ int eq_p, rebuilt_p;
+ st_index_t ind;
+#ifdef QUADRATIC_PROBE
+ st_index_t d;
+#else
+ st_index_t perturb;
+#endif
+ st_index_t bin;
+ set_table_entry *entries = tab->entries;
+
+ ind = set_hash_bin(hash_value, tab);
+#ifdef QUADRATIC_PROBE
+ d = 1;
+#else
+ perturb = hash_value;
+#endif
+ for (;;) {
+ bin = get_bin(set_bins_ptr(tab), set_get_size_ind(tab), ind);
+ if (! EMPTY_OR_DELETED_BIN_P(bin)) {
+ DO_PTR_EQUAL_CHECK(tab, &entries[bin - ENTRY_BASE], hash_value, key, eq_p, rebuilt_p);
+ if (EXPECT(rebuilt_p, 0))
+ return REBUILT_TABLE_BIN_IND;
+ if (eq_p)
+ break;
+ }
+ else if (EMPTY_BIN_P(bin))
+ return UNDEFINED_BIN_IND;
+#ifdef QUADRATIC_PROBE
+ ind = set_hash_bin(ind + d, tab);
+ d++;
+#else
+ ind = set_secondary_hash(ind, tab, &perturb);
+#endif
+ }
+ return ind;
+}
+
+/* Find and return index of table TAB bin corresponding to an entry
+ with HASH_VALUE and KEY. The entry should be in the table
+ already. */
+static st_index_t
+set_find_table_bin_ind_direct(set_table *tab, st_hash_t hash_value, st_data_t key)
+{
+ st_index_t ind;
+#ifdef QUADRATIC_PROBE
+ st_index_t d;
+#else
+ st_index_t perturb;
+#endif
+ st_index_t bin;
+
+ ind = set_hash_bin(hash_value, tab);
+#ifdef QUADRATIC_PROBE
+ d = 1;
+#else
+ perturb = hash_value;
+#endif
+ for (;;) {
+ bin = get_bin(set_bins_ptr(tab), set_get_size_ind(tab), ind);
+ if (EMPTY_OR_DELETED_BIN_P(bin))
+ return ind;
+#ifdef QUADRATIC_PROBE
+ ind = set_hash_bin(ind + d, tab);
+ d++;
+#else
+ ind = set_secondary_hash(ind, tab, &perturb);
+#endif
+ }
+}
+
+/* Mark I-th bin of table TAB as empty, in other words not
+ corresponding to any entry. */
+#define MARK_SET_BIN_EMPTY(tab, i) (set_bin(set_bins_ptr(tab), set_get_size_ind(tab), i, EMPTY_BIN))
+
+/* Return index of table TAB bin for HASH_VALUE and KEY through
+ BIN_IND and the pointed value as the function result. Reserve the
+ bin for inclusion of the corresponding entry into the table if it
+ is not there yet. We always find such bin as bins array length is
+ bigger entries array. Although we can reuse a deleted bin, the
+ result bin value is always empty if the table has no entry with
+ KEY. Return the entries array index of the found entry or
+ UNDEFINED_ENTRY_IND if it is not found. If the table was rebuilt
+ during the search, return REBUILT_TABLE_ENTRY_IND. */
+static st_index_t
+set_find_table_bin_ptr_and_reserve(set_table *tab, st_hash_t *hash_value,
+ st_data_t key, st_index_t *bin_ind)
+{
+ int eq_p, rebuilt_p;
+ st_index_t ind;
+ st_hash_t curr_hash_value = *hash_value;
+#ifdef QUADRATIC_PROBE
+ st_index_t d;
+#else
+ st_index_t perturb;
+#endif
+ st_index_t entry_index;
+ st_index_t firset_deleted_bin_ind;
+ set_table_entry *entries;
+
+ ind = set_hash_bin(curr_hash_value, tab);
+#ifdef QUADRATIC_PROBE
+ d = 1;
+#else
+ perturb = curr_hash_value;
+#endif
+ firset_deleted_bin_ind = UNDEFINED_BIN_IND;
+ entries = tab->entries;
+ for (;;) {
+ entry_index = get_bin(set_bins_ptr(tab), set_get_size_ind(tab), ind);
+ if (EMPTY_BIN_P(entry_index)) {
+ tab->num_entries++;
+ entry_index = UNDEFINED_ENTRY_IND;
+ if (firset_deleted_bin_ind != UNDEFINED_BIN_IND) {
+ /* We can reuse bin of a deleted entry. */
+ ind = firset_deleted_bin_ind;
+ MARK_SET_BIN_EMPTY(tab, ind);
+ }
+ break;
+ }
+ else if (! DELETED_BIN_P(entry_index)) {
+ DO_PTR_EQUAL_CHECK(tab, &entries[entry_index - ENTRY_BASE], curr_hash_value, key, eq_p, rebuilt_p);
+ if (EXPECT(rebuilt_p, 0))
+ return REBUILT_TABLE_ENTRY_IND;
+ if (eq_p)
+ break;
+ }
+ else if (firset_deleted_bin_ind == UNDEFINED_BIN_IND)
+ firset_deleted_bin_ind = ind;
+#ifdef QUADRATIC_PROBE
+ ind = set_hash_bin(ind + d, tab);
+ d++;
+#else
+ ind = set_secondary_hash(ind, tab, &perturb);
+#endif
+ }
+ *bin_ind = ind;
+ return entry_index;
+}
+
+/* Find an entry with KEY in table TAB. Return non-zero if we found
+ it. */
+int
+set_table_lookup(set_table *tab, st_data_t key)
+{
+ st_index_t bin;
+ st_hash_t hash = set_do_hash(key, tab);
+
+ retry:
+ if (!set_has_bins(tab)) {
+ bin = set_find_entry(tab, hash, key);
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ if (bin == UNDEFINED_ENTRY_IND)
+ return 0;
+ }
+ else {
+ bin = set_find_table_entry_ind(tab, hash, key);
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ if (bin == UNDEFINED_ENTRY_IND)
+ return 0;
+ bin -= ENTRY_BASE;
+ }
+ return 1;
+}
+
+/* Check the table and rebuild it if it is necessary. */
+static inline void
+set_rebuild_table_if_necessary (set_table *tab)
+{
+ st_index_t bound = tab->entries_bound;
+
+ if (bound == set_get_allocated_entries(tab))
+ set_rebuild_table(tab);
+}
+
+/* Insert KEY into table TAB and return zero. If there is
+ already entry with KEY in the table, return nonzero and update
+ the value of the found entry. */
+int
+set_insert(set_table *tab, st_data_t key)
+{
+ set_table_entry *entry;
+ st_index_t bin;
+ st_index_t ind;
+ st_hash_t hash_value;
+ st_index_t bin_ind;
+ int new_p;
+
+ hash_value = set_do_hash(key, tab);
+ retry:
+ set_rebuild_table_if_necessary(tab);
+ if (!set_has_bins(tab)) {
+ bin = set_find_entry(tab, hash_value, key);
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ new_p = bin == UNDEFINED_ENTRY_IND;
+ if (new_p)
+ tab->num_entries++;
+ bin_ind = UNDEFINED_BIN_IND;
+ }
+ else {
+ bin = set_find_table_bin_ptr_and_reserve(tab, &hash_value,
+ key, &bin_ind);
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ new_p = bin == UNDEFINED_ENTRY_IND;
+ bin -= ENTRY_BASE;
+ }
+ if (new_p) {
+ ind = tab->entries_bound++;
+ entry = &tab->entries[ind];
+ entry->hash = hash_value;
+ entry->key = key;
+ if (bin_ind != UNDEFINED_BIN_IND)
+ set_bin(set_bins_ptr(tab), set_get_size_ind(tab), bin_ind, ind + ENTRY_BASE);
+ return 0;
+ }
+ return 1;
+}
+
+/* Create a copy of old_tab into new_tab. */
+static set_table *
+set_replace(set_table *new_tab, set_table *old_tab)
+{
+ *new_tab = *old_tab;
+ size_t memsize = set_allocated_entries_size(old_tab) + set_bins_size(old_tab);
+ new_tab->entries = (set_table_entry *)malloc(memsize);
+ MEMCPY(new_tab->entries, old_tab->entries, char, memsize);
+ return new_tab;
+}
+
+/* Create and return a copy of table OLD_TAB. */
+set_table *
+set_copy(set_table *new_tab, set_table *old_tab)
+{
+ if (new_tab == NULL) new_tab = (set_table *) malloc(sizeof(set_table));
+
+ if (set_replace(new_tab, old_tab) == NULL) {
+ set_free_table(new_tab);
+ return NULL;
+ }
+
+ return new_tab;
+}
+
+/* Update the entries start of table TAB after removing an entry
+ with index N in the array entries. */
+static inline void
+set_update_range_for_deleted(set_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) {
+ st_index_t start = n + 1;
+ st_index_t bound = tab->entries_bound;
+ set_table_entry *entries = tab->entries;
+ while (start < bound && DELETED_ENTRY_P(&entries[start])) start++;
+ tab->entries_start = start;
+ }
+}
+
+/* Mark I-th bin of table TAB as corresponding to a deleted table
+ entry. Update number of entries in the table and number of bins
+ corresponding to deleted entries. */
+#define MARK_SET_BIN_DELETED(tab, i) \
+ do { \
+ set_bin(set_bins_ptr(tab), set_get_size_ind(tab), i, DELETED_BIN); \
+ } while (0)
+
+/* Delete entry with KEY from table TAB, and return non-zero. If
+ there is no entry with KEY in the table, return zero. */
+int
+set_table_delete(set_table *tab, st_data_t *key)
+{
+ set_table_entry *entry;
+ st_index_t bin;
+ st_index_t bin_ind;
+ st_hash_t hash;
+
+ hash = set_do_hash(*key, tab);
+ retry:
+ if (!set_has_bins(tab)) {
+ bin = set_find_entry(tab, hash, *key);
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ if (bin == UNDEFINED_ENTRY_IND) {
+ return 0;
+ }
+ }
+ else {
+ bin_ind = set_find_table_bin_ind(tab, hash, *key);
+ if (EXPECT(bin_ind == REBUILT_TABLE_BIN_IND, 0))
+ goto retry;
+ if (bin_ind == UNDEFINED_BIN_IND) {
+ return 0;
+ }
+ bin = get_bin(set_bins_ptr(tab), set_get_size_ind(tab), bin_ind) - ENTRY_BASE;
+ MARK_SET_BIN_DELETED(tab, bin_ind);
+ }
+ entry = &tab->entries[bin];
+ *key = entry->key;
+ MARK_ENTRY_DELETED(entry);
+ tab->num_entries--;
+ set_update_range_for_deleted(tab, bin);
+ return 1;
+}
+
+/* Traverse all entries in table TAB calling FUNC with current entry
+ key and zero. If the call returns ST_STOP, stop
+ traversing. If the call returns ST_DELETE, delete the current
+ entry from the table. In case of ST_CHECK or ST_CONTINUE, continue
+ traversing. The function returns zero unless an error is found.
+ CHECK_P is flag of set_foreach_check call. The behavior is a bit
+ different for ST_CHECK and when the current element is removed
+ during traversing. */
+static inline int
+set_general_foreach(set_table *tab, set_foreach_check_callback_func *func,
+ set_update_callback_func *replace, st_data_t arg,
+ int check_p)
+{
+ st_index_t bin;
+ st_index_t bin_ind;
+ set_table_entry *entries, *curr_entry_ptr;
+ enum st_retval retval;
+ st_index_t i, rebuilds_num;
+ st_hash_t hash;
+ st_data_t key;
+ int error_p, packed_p = !set_has_bins(tab);
+
+ entries = tab->entries;
+ /* The bound can change inside the loop even without rebuilding
+ 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))
+ continue;
+ key = curr_entry_ptr->key;
+ rebuilds_num = tab->rebuilds_num;
+ hash = curr_entry_ptr->hash;
+ retval = (*func)(key, arg, 0);
+
+ if (retval == ST_REPLACE && replace) {
+ retval = (*replace)(&key, arg, TRUE);
+ curr_entry_ptr->key = key;
+ }
+
+ if (rebuilds_num != tab->rebuilds_num) {
+ retry:
+ entries = tab->entries;
+ packed_p = !set_has_bins(tab);
+ if (packed_p) {
+ i = set_find_entry(tab, hash, key);
+ if (EXPECT(i == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ error_p = i == UNDEFINED_ENTRY_IND;
+ }
+ else {
+ i = set_find_table_entry_ind(tab, hash, key);
+ if (EXPECT(i == REBUILT_TABLE_ENTRY_IND, 0))
+ goto retry;
+ error_p = i == UNDEFINED_ENTRY_IND;
+ i -= ENTRY_BASE;
+ }
+ if (error_p && check_p) {
+ /* call func with error notice */
+ retval = (*func)(0, arg, 1);
+ return 1;
+ }
+ curr_entry_ptr = &entries[i];
+ }
+ switch (retval) {
+ case ST_REPLACE:
+ break;
+ case ST_CONTINUE:
+ break;
+ case ST_CHECK:
+ if (check_p)
+ break;
+ case ST_STOP:
+ return 0;
+ case ST_DELETE: {
+ st_data_t key = curr_entry_ptr->key;
+
+ again:
+ if (packed_p) {
+ bin = set_find_entry(tab, hash, key);
+ if (EXPECT(bin == REBUILT_TABLE_ENTRY_IND, 0))
+ goto again;
+ if (bin == UNDEFINED_ENTRY_IND)
+ break;
+ }
+ else {
+ bin_ind = set_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(set_bins_ptr(tab), set_get_size_ind(tab), bin_ind) - ENTRY_BASE;
+ MARK_SET_BIN_DELETED(tab, bin_ind);
+ }
+ curr_entry_ptr = &entries[bin];
+ MARK_ENTRY_DELETED(curr_entry_ptr);
+ tab->num_entries--;
+ set_update_range_for_deleted(tab, bin);
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+int
+set_foreach_with_replace(set_table *tab, set_foreach_check_callback_func *func, set_update_callback_func *replace, st_data_t arg)
+{
+ return set_general_foreach(tab, func, replace, arg, TRUE);
+}
+
+struct set_functor {
+ set_foreach_callback_func *func;
+ st_data_t arg;
+};
+
+static int
+set_apply_functor(st_data_t k, st_data_t d, int _)
+{
+ const struct set_functor *f = (void *)d;
+ return f->func(k, f->arg);
+}
+
+int
+set_table_foreach(set_table *tab, set_foreach_callback_func *func, st_data_t arg)
+{
+ const struct set_functor f = { func, arg };
+ return set_general_foreach(tab, set_apply_functor, NULL, (st_data_t)&f, FALSE);
+}
+
+/* See comments for function set_delete_safe. */
+int
+set_foreach_check(set_table *tab, set_foreach_check_callback_func *func, st_data_t arg,
+ st_data_t never ATTRIBUTE_UNUSED)
+{
+ return set_general_foreach(tab, func, NULL, arg, TRUE);
+}
+
+/* Set up array KEYS by at most SIZE keys of head table TAB entries.
+ Return the number of keys set up in array KEYS. */
+inline st_index_t
+set_keys(set_table *tab, st_data_t *keys, st_index_t size)
+{
+ st_index_t i, bound;
+ st_data_t key, *keys_start, *keys_end;
+ set_table_entry *curr_entry_ptr, *entries = tab->entries;
+
+ bound = tab->entries_bound;
+ keys_start = keys;
+ keys_end = keys + size;
+ for (i = tab->entries_start; i < bound; i++) {
+ if (keys == keys_end)
+ break;
+ curr_entry_ptr = &entries[i];
+ key = curr_entry_ptr->key;
+ if (! DELETED_ENTRY_P(curr_entry_ptr))
+ *keys++ = key;
+ }
+
+ return keys - keys_start;
+}
+
+void
+set_compact_table(set_table *tab)
+{
+ st_index_t num = tab->num_entries;
+ if (REBUILD_THRESHOLD * num <= set_get_allocated_entries(tab)) {
+ /* Compaction: */
+ set_table *new_tab = set_init_table_with_size(NULL, tab->type, 2 * num);
+ set_rebuild_table_with(new_tab, tab);
+ set_rebuild_move_table(new_tab, tab);
+ set_rebuild_cleanup(tab);
+ }
+}
+
#endif
diff --git a/strftime.c b/strftime.c
index 33e7d3fdb8..9be4bb9d07 100644
--- a/strftime.c
+++ b/strftime.c
@@ -171,7 +171,9 @@ resize_buffer(VALUE ftime, char *s, const char **start, const char **endp,
ptrdiff_t n, size_t maxsize)
{
size_t len = s - *start;
- size_t nlen = len + n * 2;
+ size_t need = len + n * 2;
+ size_t nlen = rb_str_capacity(ftime);
+ while (nlen < need) nlen <<= 1;
if (nlen < len || nlen > maxsize) {
return 0;
@@ -930,6 +932,7 @@ rb_strftime(const char *format, size_t format_len, rb_encoding *enc,
VALUE time, const struct vtm *vtm, VALUE timev, int gmt)
{
VALUE result = rb_enc_str_new(0, 0, enc);
+ ENC_CODERANGE_CLEAR(result);
return rb_strftime_with_timespec(result, format, format_len, enc,
time, vtm, timev, NULL, gmt,
strftime_size_limit(format_len));
@@ -940,6 +943,7 @@ rb_strftime_timespec(const char *format, size_t format_len, rb_encoding *enc,
VALUE time, const struct vtm *vtm, struct timespec *ts, int gmt)
{
VALUE result = rb_enc_str_new(0, 0, enc);
+ ENC_CODERANGE_CLEAR(result);
return rb_strftime_with_timespec(result, format, format_len, enc,
time, vtm, Qnil, ts, gmt,
strftime_size_limit(format_len));
@@ -983,10 +987,10 @@ vtm2tm_noyear(const struct vtm *vtm, struct tm *result)
tm.tm_yday = vtm->yday-1;
tm.tm_isdst = vtm->isdst;
#if defined(HAVE_STRUCT_TM_TM_GMTOFF)
- tm.tm_gmtoff = NUM2LONG(vtm->utc_offset);
+ tm.tm_gmtoff = 0;
#endif
#if defined(HAVE_TM_ZONE)
- tm.tm_zone = (char *)vtm->zone;
+ tm.tm_zone = NULL;
#endif
*result = tm;
}
diff --git a/string.c b/string.c
index acad662e4d..1e0b9929ef 100644
--- a/string.c
+++ b/string.c
@@ -28,9 +28,11 @@
#include "internal/array.h"
#include "internal/compar.h"
#include "internal/compilers.h"
+#include "internal/concurrent_set.h"
#include "internal/encoding.h"
#include "internal/error.h"
#include "internal/gc.h"
+#include "internal/hash.h"
#include "internal/numeric.h"
#include "internal/object.h"
#include "internal/proc.h"
@@ -41,9 +43,13 @@
#include "probes.h"
#include "ruby/encoding.h"
#include "ruby/re.h"
+#include "ruby/thread.h"
#include "ruby/util.h"
+#include "ruby/ractor.h"
#include "ruby_assert.h"
+#include "shape.h"
#include "vm_sync.h"
+#include "ruby/internal/attr/nonstring.h"
#if defined HAVE_CRYPT_R
# if defined HAVE_CRYPT_H
@@ -80,17 +86,21 @@ VALUE rb_cSymbol;
/* Flags of RString
*
+ * 0: STR_SHARED (equal to ELTS_SHARED)
+ * The string is shared. The buffer this string points to is owned by
+ * another string (the shared root).
* 1: RSTRING_NOEMBED
* The string is not embedded. When a string is embedded, the contents
* follow the header. When a string is not embedded, the contents is
* on a separately allocated buffer.
- * 2: STR_SHARED (equal to ELTS_SHARED)
- * The string is shared. The buffer this string points to is owned by
- * another string (the shared root).
- * 3: STR_CHILLED (will be frozen in a future version)
- * The string appears frozen but can be mutated with a warning.
+ * 2: STR_CHILLED_LITERAL (will be frozen in a future version)
+ * The string was allocated as a literal in a file without an explicit `frozen_string_literal` comment.
+ * It emits a deprecation warning when mutated for the first time.
+ * 3: STR_CHILLED_SYMBOL_TO_S (will be frozen in a future version)
+ * The string was allocated by the `Symbol#to_s` method.
+ * It emits a deprecation warning when mutated for the first time.
* 4: STR_PRECOMPUTED_HASH
- * The string is embedded and has its precomputed hascode stored
+ * The string is embedded and has its precomputed hashcode stored
* after the terminator.
* 5: STR_SHARED_ROOT
* Other strings may point to the contents of this string. When this
@@ -136,21 +146,7 @@ VALUE rb_cSymbol;
RSTRING(str)->len = (n); \
} while (0)
-static inline bool
-str_enc_fastpath(VALUE str)
-{
- // The overwhelming majority of strings are in one of these 3 encodings.
- switch (ENCODING_GET_INLINED(str)) {
- case ENCINDEX_ASCII_8BIT:
- case ENCINDEX_UTF_8:
- case ENCINDEX_US_ASCII:
- return true;
- default:
- return false;
- }
-}
-
-#define TERM_LEN(str) (str_enc_fastpath(str) ? 1 : rb_enc_mbminlen(rb_enc_from_index(ENCODING_GET(str))))
+#define TERM_LEN(str) (rb_str_enc_fastpath(str) ? 1 : rb_enc_mbminlen(rb_enc_from_index(ENCODING_GET(str))))
#define TERM_FILL(ptr, termlen) do {\
char *const term_fill_ptr = (ptr);\
const int term_fill_len = (termlen);\
@@ -189,6 +185,7 @@ str_enc_fastpath(VALUE str)
RUBY_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); \
+ rb_gc_register_pinning_obj(str); \
FL_SET((shared_str), STR_SHARED_ROOT); \
if (RBASIC_CLASS((shared_str)) == 0) /* for CoW-friendliness */ \
FL_SET_RAW((shared_str), STR_BORROWED); \
@@ -224,9 +221,11 @@ rb_str_reembeddable_p(VALUE str)
}
static inline size_t
-rb_str_embed_size(long capa)
+rb_str_embed_size(long capa, long termlen)
{
- return offsetof(struct RString, as.embed.ary) + capa;
+ size_t size = offsetof(struct RString, as.embed.ary) + capa + termlen;
+ if (size < sizeof(struct RString)) size = sizeof(struct RString);
+ return size;
}
size_t
@@ -234,28 +233,30 @@ rb_str_size_as_embedded(VALUE str)
{
size_t real_size;
if (STR_EMBED_P(str)) {
- real_size = rb_str_embed_size(RSTRING(str)->len) + TERM_LEN(str);
+ size_t capa = RSTRING(str)->len;
+ if (FL_TEST_RAW(str, STR_PRECOMPUTED_HASH)) capa += sizeof(st_index_t);
+
+ real_size = rb_str_embed_size(capa, TERM_LEN(str));
}
/* if the string is not currently embedded, but it can be embedded, how
* much space would it require */
else if (rb_str_reembeddable_p(str)) {
- real_size = rb_str_embed_size(RSTRING(str)->as.heap.aux.capa) + TERM_LEN(str);
+ size_t capa = RSTRING(str)->as.heap.aux.capa;
+ if (FL_TEST_RAW(str, STR_PRECOMPUTED_HASH)) capa += sizeof(st_index_t);
+
+ real_size = rb_str_embed_size(capa, TERM_LEN(str));
}
else {
real_size = sizeof(struct RString);
}
- if (FL_TEST_RAW(str, STR_PRECOMPUTED_HASH)) {
- real_size += sizeof(st_index_t);
- }
-
return real_size;
}
static inline bool
STR_EMBEDDABLE_P(long len, long termlen)
{
- return rb_gc_size_allocatable_p(rb_str_embed_size(len + termlen));
+ return rb_gc_size_allocatable_p(rb_str_embed_size(len, termlen));
}
static VALUE str_replace_shared_without_enc(VALUE str2, VALUE str);
@@ -342,16 +343,18 @@ mustnot_wchar(VALUE str)
}
}
-static int fstring_cmp(VALUE a, VALUE b);
-
-static VALUE register_fstring(VALUE str, bool copy, bool precompute_hash);
+static VALUE register_fstring(VALUE str, bool copy, bool force_precompute_hash);
-const struct st_hash_type rb_fstring_hash_type = {
- fstring_cmp,
- rb_str_hash,
-};
+#if SIZEOF_LONG == SIZEOF_VOIDP
+#define PRECOMPUTED_FAKESTR_HASH 1
+#else
+#endif
-#define BARE_STRING_P(str) (!FL_ANY_RAW(str, FL_EXIVAR) && RBASIC_CLASS(str) == rb_cString)
+static inline bool
+BARE_STRING_P(VALUE str)
+{
+ return RBASIC_CLASS(str) == rb_cString && !rb_shape_obj_has_ivars(str);
+}
static inline st_index_t
str_do_hash(VALUE str)
@@ -365,7 +368,7 @@ str_do_hash(VALUE str)
}
static VALUE
-str_precompute_hash(VALUE str)
+str_store_precomputed_hash(VALUE str, st_index_t hash)
{
RUBY_ASSERT(!FL_TEST_RAW(str, STR_PRECOMPUTED_HASH));
RUBY_ASSERT(STR_EMBED_P(str));
@@ -376,89 +379,13 @@ str_precompute_hash(VALUE str)
RUBY_ASSERT(free_bytes >= sizeof(st_index_t));
#endif
- typedef struct {char bytes[sizeof(st_index_t)];} unaligned_index;
- union {st_index_t i; unaligned_index b;} u = {.i = str_do_hash(str)};
- *(unaligned_index *)(RSTRING_END(str) + TERM_LEN(str)) = u.b;
+ memcpy(RSTRING_END(str) + TERM_LEN(str), &hash, sizeof(hash));
FL_SET(str, STR_PRECOMPUTED_HASH);
return str;
}
-struct fstr_update_arg {
- VALUE fstr;
- bool copy;
- bool precompute_hash;
-};
-
-static int
-fstr_update_callback(st_data_t *key, st_data_t *value, st_data_t data, int existing)
-{
-
- struct fstr_update_arg *arg = (struct fstr_update_arg *)data;
- VALUE str = (VALUE)*key;
-
- if (existing) {
- /* because of lazy sweep, str may be unmarked already and swept
- * at next time */
-
- if (rb_objspace_garbage_object_p(str)) {
- arg->fstr = Qundef;
- return ST_DELETE;
- }
-
- arg->fstr = str;
- return ST_STOP;
- }
- else {
- if (FL_TEST_RAW(str, STR_FAKESTR)) {
- if (arg->copy) {
- VALUE new_str;
- long len = RSTRING_LEN(str);
- long capa = len + sizeof(st_index_t);
- int term_len = TERM_LEN(str);
-
- if (arg->precompute_hash && STR_EMBEDDABLE_P(capa, term_len)) {
- new_str = str_alloc_embed(rb_cString, capa + term_len);
- memcpy(RSTRING_PTR(new_str), RSTRING_PTR(str), len);
- STR_SET_LEN(new_str, RSTRING_LEN(str));
- TERM_FILL(RSTRING_END(new_str), TERM_LEN(str));
- rb_enc_copy(new_str, str);
- str_precompute_hash(new_str);
- }
- else {
- new_str = str_new(rb_cString, RSTRING(str)->as.heap.ptr, RSTRING(str)->len);
- rb_enc_copy(new_str, str);
- }
- str = new_str;
- }
- else {
- str = str_new_static(rb_cString, RSTRING(str)->as.heap.ptr,
- RSTRING(str)->len,
- ENCODING_GET(str));
- }
- OBJ_FREEZE(str);
- }
- else {
- if (!OBJ_FROZEN(str) || CHILLED_STRING_P(str)) {
- str = str_new_frozen(rb_cString, str);
- }
- if (STR_SHARED_P(str)) { /* str should not be shared */
- /* shared substring */
- str_make_independent(str);
- RUBY_ASSERT(OBJ_FROZEN(str));
- }
- if (!BARE_STRING_P(str)) {
- str = str_new_frozen(rb_cString, str);
- }
- }
- RBASIC(str)->flags |= RSTRING_FSTR;
-
- *key = *value = arg->fstr = str;
- return ST_CONTINUE;
- }
-}
-
VALUE
rb_fstring(VALUE str)
{
@@ -496,37 +423,200 @@ rb_fstring(VALUE str)
return fstr;
}
+static VALUE fstring_table_obj;
+
static VALUE
-register_fstring(VALUE str, bool copy, bool precompute_hash)
+fstring_concurrent_set_hash(VALUE str)
+{
+#ifdef PRECOMPUTED_FAKESTR_HASH
+ st_index_t h;
+ if (FL_TEST_RAW(str, STR_FAKESTR)) {
+ // register_fstring precomputes the hash and stores it in capa for fake strings
+ h = (st_index_t)RSTRING(str)->as.heap.aux.capa;
+ }
+ else {
+ h = rb_str_hash(str);
+ }
+ // rb_str_hash doesn't include the encoding for ascii only strings, so
+ // we add it to avoid common collisions between `:sym.name` (ASCII) and `"sym"` (UTF-8)
+ return (VALUE)rb_hash_end(rb_hash_uint32(h, (uint32_t)ENCODING_GET_INLINED(str)));
+#else
+ return (VALUE)rb_str_hash(str);
+#endif
+}
+
+static bool
+fstring_concurrent_set_cmp(VALUE a, VALUE b)
+{
+ long alen, blen;
+ const char *aptr, *bptr;
+
+ RUBY_ASSERT(RB_TYPE_P(a, T_STRING));
+ RUBY_ASSERT(RB_TYPE_P(b, T_STRING));
+
+ RSTRING_GETMEM(a, aptr, alen);
+ RSTRING_GETMEM(b, bptr, blen);
+ return (alen == blen &&
+ ENCODING_GET(a) == ENCODING_GET(b) &&
+ memcmp(aptr, bptr, alen) == 0);
+}
+
+struct fstr_create_arg {
+ bool copy;
+ bool force_precompute_hash;
+};
+
+static VALUE
+fstring_concurrent_set_create(VALUE str, void *data)
+{
+ struct fstr_create_arg *arg = data;
+
+ // Unless the string is empty or binary, its coderange has been precomputed.
+ int coderange = ENC_CODERANGE(str);
+
+ if (FL_TEST_RAW(str, STR_FAKESTR)) {
+ if (arg->copy) {
+ VALUE new_str;
+ long len = RSTRING_LEN(str);
+ long capa = len + sizeof(st_index_t);
+ int term_len = TERM_LEN(str);
+
+ if (arg->force_precompute_hash && STR_EMBEDDABLE_P(capa, term_len)) {
+ new_str = str_alloc_embed(rb_cString, capa + term_len);
+ memcpy(RSTRING_PTR(new_str), RSTRING_PTR(str), len);
+ STR_SET_LEN(new_str, RSTRING_LEN(str));
+ TERM_FILL(RSTRING_END(new_str), TERM_LEN(str));
+ rb_enc_copy(new_str, str);
+ str_store_precomputed_hash(new_str, str_do_hash(str));
+ }
+ else {
+ new_str = str_new(rb_cString, RSTRING(str)->as.heap.ptr, RSTRING(str)->len);
+ rb_enc_copy(new_str, str);
+#ifdef PRECOMPUTED_FAKESTR_HASH
+ if (rb_str_capacity(new_str) >= RSTRING_LEN(str) + term_len + sizeof(st_index_t)) {
+ str_store_precomputed_hash(new_str, (st_index_t)RSTRING(str)->as.heap.aux.capa);
+ }
+#endif
+ }
+ str = new_str;
+ }
+ else {
+ str = str_new_static(rb_cString, RSTRING(str)->as.heap.ptr,
+ RSTRING(str)->len,
+ ENCODING_GET(str));
+ }
+ OBJ_FREEZE(str);
+ }
+ else {
+ if (!OBJ_FROZEN(str) || CHILLED_STRING_P(str)) {
+ str = str_new_frozen(rb_cString, str);
+ }
+ if (STR_SHARED_P(str)) { /* str should not be shared */
+ /* shared substring */
+ str_make_independent(str);
+ RUBY_ASSERT(OBJ_FROZEN(str));
+ }
+ if (!BARE_STRING_P(str)) {
+ str = str_new_frozen(rb_cString, str);
+ }
+ }
+
+ ENC_CODERANGE_SET(str, coderange);
+ RBASIC(str)->flags |= RSTRING_FSTR;
+ if (!RB_OBJ_SHAREABLE_P(str)) {
+ RB_OBJ_SET_SHAREABLE(str);
+ }
+ RUBY_ASSERT((rb_gc_verify_shareable(str), 1));
+ RUBY_ASSERT(RB_TYPE_P(str, T_STRING));
+ RUBY_ASSERT(OBJ_FROZEN(str));
+ RUBY_ASSERT(!FL_TEST_RAW(str, STR_FAKESTR));
+ RUBY_ASSERT(!rb_shape_obj_has_ivars(str));
+ RUBY_ASSERT(RBASIC_CLASS(str) == rb_cString);
+ RUBY_ASSERT(!rb_objspace_garbage_object_p(str));
+
+ return str;
+}
+
+static const struct rb_concurrent_set_funcs fstring_concurrent_set_funcs = {
+ .hash = fstring_concurrent_set_hash,
+ .cmp = fstring_concurrent_set_cmp,
+ .create = fstring_concurrent_set_create,
+ .free = NULL,
+};
+
+void
+Init_fstring_table(void)
{
- struct fstr_update_arg args = {
+ fstring_table_obj = rb_concurrent_set_new(&fstring_concurrent_set_funcs, 8192);
+ rb_gc_register_address(&fstring_table_obj);
+}
+
+static VALUE
+register_fstring(VALUE str, bool copy, bool force_precompute_hash)
+{
+ struct fstr_create_arg args = {
.copy = copy,
- .precompute_hash = precompute_hash
+ .force_precompute_hash = force_precompute_hash
};
- 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 (UNDEF_P(args.fstr));
+#if SIZEOF_VOIDP == SIZEOF_LONG
+ if (FL_TEST_RAW(str, STR_FAKESTR)) {
+ // if the string hasn't been interned, we'll need the hash twice, so we
+ // compute it once and store it in capa
+ RSTRING(str)->as.heap.aux.capa = (long)str_do_hash(str);
}
- RB_VM_LOCK_LEAVE();
+#endif
- RUBY_ASSERT(OBJ_FROZEN(args.fstr));
- RUBY_ASSERT(!FL_TEST_RAW(args.fstr, STR_FAKESTR));
- RUBY_ASSERT(!FL_TEST_RAW(args.fstr, FL_EXIVAR));
- RUBY_ASSERT(RBASIC_CLASS(args.fstr) == rb_cString);
+ VALUE result = rb_concurrent_set_find_or_insert(&fstring_table_obj, str, &args);
+
+ RUBY_ASSERT(!rb_objspace_garbage_object_p(result));
+ RUBY_ASSERT(RB_TYPE_P(result, T_STRING));
+ RUBY_ASSERT(OBJ_FROZEN(result));
+ RUBY_ASSERT(RB_OBJ_SHAREABLE_P(result));
+ RUBY_ASSERT((rb_gc_verify_shareable(result), 1));
+ RUBY_ASSERT(!FL_TEST_RAW(result, STR_FAKESTR));
+ RUBY_ASSERT(RBASIC_CLASS(result) == rb_cString);
+
+ return result;
+}
+
+bool
+rb_obj_is_fstring_table(VALUE obj)
+{
+ ASSERT_vm_locking();
- return args.fstr;
+ return obj == fstring_table_obj;
+}
+
+void
+rb_gc_free_fstring(VALUE obj)
+{
+ ASSERT_vm_locking_with_barrier();
+
+ RUBY_ASSERT(FL_TEST(obj, RSTRING_FSTR));
+ RUBY_ASSERT(OBJ_FROZEN(obj));
+ RUBY_ASSERT(!FL_TEST(obj, STR_SHARED));
+
+ rb_concurrent_set_delete_by_identity(fstring_table_obj, obj);
+
+ RB_DEBUG_COUNTER_INC(obj_str_fstr);
+
+ FL_UNSET(obj, RSTRING_FSTR);
+}
+
+void
+rb_fstring_foreach_with_replace(int (*callback)(VALUE *str, void *data), void *data)
+{
+ if (fstring_table_obj) {
+ rb_concurrent_set_foreach_with_replace(fstring_table_obj, callback, data);
+ }
}
static VALUE
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 */
+ RBASIC_SET_SHAPE_ID((VALUE)fake_str, ROOT_SHAPE_ID);
if (!name) {
RUBY_ASSERT_ALWAYS(len == 0);
@@ -559,14 +649,14 @@ rb_setup_fake_str(struct RString *fake_str, const char *name, long len, rb_encod
VALUE
rb_fstring_new(const char *ptr, long len)
{
- struct RString fake_str;
+ struct RString fake_str = {RBASIC_INIT};
return register_fstring(setup_fake_str(&fake_str, ptr, len, ENCINDEX_US_ASCII), false, false);
}
VALUE
rb_fstring_enc_new(const char *ptr, long len, rb_encoding *enc)
{
- struct RString fake_str;
+ struct RString fake_str = {RBASIC_INIT};
return register_fstring(rb_setup_fake_str(&fake_str, ptr, len, enc), false, false);
}
@@ -576,41 +666,30 @@ rb_fstring_cstr(const char *ptr)
return rb_fstring_new(ptr, strlen(ptr));
}
-static int
-fstring_set_class_i(st_data_t key, st_data_t val, st_data_t arg)
-{
- RBASIC_SET_CLASS((VALUE)key, (VALUE)arg);
- return ST_CONTINUE;
-}
-
-static int
-fstring_cmp(VALUE a, VALUE b)
-{
- long alen, blen;
- const char *aptr, *bptr;
- RSTRING_GETMEM(a, aptr, alen);
- RSTRING_GETMEM(b, bptr, blen);
- return (alen != blen ||
- ENCODING_GET(a) != ENCODING_GET(b) ||
- memcmp(aptr, bptr, alen) != 0);
-}
-
-static inline int
+static inline bool
single_byte_optimizable(VALUE str)
{
- rb_encoding *enc;
-
+ int encindex = ENCODING_GET(str);
+ switch (encindex) {
+ case ENCINDEX_ASCII_8BIT:
+ case ENCINDEX_US_ASCII:
+ return true;
+ case ENCINDEX_UTF_8:
+ // For UTF-8 it's worth scanning the string coderange when unknown.
+ return rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT;
+ }
/* Conservative. It may be ENC_CODERANGE_UNKNOWN. */
- if (ENC_CODERANGE(str) == ENC_CODERANGE_7BIT)
- return 1;
+ if (ENC_CODERANGE(str) == ENC_CODERANGE_7BIT) {
+ return true;
+ }
- enc = STR_ENC_GET(str);
- if (rb_enc_mbmaxlen(enc) == 1)
- return 1;
+ if (rb_enc_mbmaxlen(rb_enc_from_index(encindex)) == 1) {
+ return true;
+ }
/* Conservative. Possibly single byte.
* "\xa1" in Shift_JIS for example. */
- return 0;
+ return false;
}
VALUE rb_fs;
@@ -618,7 +697,7 @@ VALUE rb_fs;
static inline const char *
search_nonascii(const char *p, const char *e)
{
- const uintptr_t *s, *t;
+ const char *s, *t;
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
# if SIZEOF_UINTPTR_T == 8
@@ -662,17 +741,19 @@ search_nonascii(const char *p, const char *e)
#define aligned_ptr(value) \
__builtin_assume_aligned((value), sizeof(uintptr_t))
#else
-#define aligned_ptr(value) (uintptr_t *)(value)
+#define aligned_ptr(value) (value)
#endif
s = aligned_ptr(p);
- t = (uintptr_t *)(e - (SIZEOF_VOIDP-1));
+ t = (e - (SIZEOF_VOIDP-1));
#undef aligned_ptr
- for (;s < t; s++) {
- if (*s & NONASCII_MASK) {
+ for (;s < t; s += sizeof(uintptr_t)) {
+ uintptr_t word;
+ memcpy(&word, s, sizeof(word));
+ if (word & NONASCII_MASK) {
#ifdef WORDS_BIGENDIAN
- return (const char *)s + (nlz_intptr(*s&NONASCII_MASK)>>3);
+ return (const char *)s + (nlz_intptr(word&NONASCII_MASK)>>3);
#else
- return (const char *)s + (ntz_intptr(*s&NONASCII_MASK)>>3);
+ return (const char *)s + (ntz_intptr(word&NONASCII_MASK)>>3);
#endif
}
}
@@ -855,16 +936,24 @@ rb_enc_str_coderange(VALUE str)
return cr;
}
+static inline bool
+rb_enc_str_asciicompat(VALUE str)
+{
+ int encindex = ENCODING_GET_INLINED(str);
+ return rb_str_encindex_fastpath(encindex) || rb_enc_asciicompat(rb_enc_get_from_index(encindex));
+}
+
int
rb_enc_str_asciionly_p(VALUE str)
{
- rb_encoding *enc = STR_ENC_GET(str);
-
- if (!rb_enc_asciicompat(enc))
- return FALSE;
- else if (is_ascii_string(str))
- return TRUE;
- return FALSE;
+ switch(ENC_CODERANGE(str)) {
+ case ENC_CODERANGE_UNKNOWN:
+ return rb_enc_str_asciicompat(str) && is_ascii_string(str);
+ case ENC_CODERANGE_7BIT:
+ return true;
+ default:
+ return false;
+ }
}
static inline void
@@ -881,7 +970,7 @@ str_capacity(VALUE str, const int termlen)
if (STR_EMBED_P(str)) {
return str_embed_capa(str) - termlen;
}
- else if (FL_TEST(str, STR_SHARED|STR_NOFREE)) {
+ else if (FL_ANY_RAW(str, STR_SHARED|STR_NOFREE)) {
return RSTRING(str)->len;
}
else {
@@ -906,13 +995,16 @@ must_not_null(const char *ptr)
static inline VALUE
str_alloc_embed(VALUE klass, size_t capa)
{
- size_t size = rb_str_embed_size(capa);
+ size_t size = rb_str_embed_size(capa, 0);
RUBY_ASSERT(size > 0);
RUBY_ASSERT(rb_gc_size_allocatable_p(size));
NEWOBJ_OF(str, struct RString, klass,
T_STRING | (RGENGC_WB_PROTECTED_STRING ? FL_WB_PROTECTED : 0), size, 0);
+ str->len = 0;
+ str->as.embed.ary[0] = 0;
+
return (VALUE)str;
}
@@ -922,6 +1014,10 @@ str_alloc_heap(VALUE klass)
NEWOBJ_OF(str, struct RString, klass,
T_STRING | STR_NOEMBED | (RGENGC_WB_PROTECTED_STRING ? FL_WB_PROTECTED : 0), sizeof(struct RString), 0);
+ str->len = 0;
+ str->as.heap.aux.capa = 0;
+ str->as.heap.ptr = NULL;
+
return (VALUE)str;
}
@@ -936,7 +1032,7 @@ empty_str_alloc(VALUE klass)
}
static VALUE
-str_new0(VALUE klass, const char *ptr, long len, int termlen)
+str_enc_new(VALUE klass, const char *ptr, long len, rb_encoding *enc)
{
VALUE str;
@@ -944,12 +1040,18 @@ str_new0(VALUE klass, const char *ptr, long len, int termlen)
rb_raise(rb_eArgError, "negative string size (or size too big)");
}
+ if (enc == NULL) {
+ enc = rb_ascii8bit_encoding();
+ }
+
RUBY_DTRACE_CREATE_HOOK(STRING, len);
+ int termlen = rb_enc_mbminlen(enc);
+
if (STR_EMBEDDABLE_P(len, termlen)) {
str = str_alloc_embed(klass, len + termlen);
if (len == 0) {
- ENC_CODERANGE_SET(str, ENC_CODERANGE_7BIT);
+ ENC_CODERANGE_SET(str, rb_enc_asciicompat(enc) ? ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID);
}
}
else {
@@ -961,9 +1063,16 @@ str_new0(VALUE klass, const char *ptr, long len, int termlen)
RSTRING(str)->as.heap.ptr =
rb_xmalloc_mul_add_mul(sizeof(char), len, sizeof(char), termlen);
}
+
+ rb_enc_raw_set(str, enc);
+
if (ptr) {
memcpy(RSTRING_PTR(str), ptr, len);
}
+ else {
+ memset(RSTRING_PTR(str), 0, len);
+ }
+
STR_SET_LEN(str, len);
TERM_FILL(RSTRING_PTR(str) + len, termlen);
return str;
@@ -972,7 +1081,7 @@ str_new0(VALUE klass, const char *ptr, long len, int termlen)
static VALUE
str_new(VALUE klass, const char *ptr, long len)
{
- return str_new0(klass, ptr, len, 1);
+ return str_enc_new(klass, ptr, len, rb_ascii8bit_encoding());
}
VALUE
@@ -984,29 +1093,19 @@ rb_str_new(const char *ptr, long len)
VALUE
rb_usascii_str_new(const char *ptr, long len)
{
- VALUE str = rb_str_new(ptr, len);
- ENCODING_CODERANGE_SET(str, rb_usascii_encindex(), ENC_CODERANGE_7BIT);
- return str;
+ return str_enc_new(rb_cString, ptr, len, rb_usascii_encoding());
}
VALUE
rb_utf8_str_new(const char *ptr, long len)
{
- VALUE str = str_new(rb_cString, ptr, len);
- rb_enc_associate_index(str, rb_utf8_encindex());
- return str;
+ return str_enc_new(rb_cString, ptr, len, rb_utf8_encoding());
}
VALUE
rb_enc_str_new(const char *ptr, long len, rb_encoding *enc)
{
- VALUE str;
-
- if (!enc) return rb_str_new(ptr, len);
-
- str = str_new0(rb_cString, ptr, len, rb_enc_mbminlen(enc));
- rb_enc_associate(str, enc);
- return str;
+ return str_enc_new(rb_cString, ptr, len, enc);
}
VALUE
@@ -1024,17 +1123,13 @@ rb_str_new_cstr(const char *ptr)
VALUE
rb_usascii_str_new_cstr(const char *ptr)
{
- VALUE str = rb_str_new_cstr(ptr);
- ENCODING_CODERANGE_SET(str, rb_usascii_encindex(), ENC_CODERANGE_7BIT);
- return str;
+ return rb_enc_str_new_cstr(ptr, rb_usascii_encoding());
}
VALUE
rb_utf8_str_new_cstr(const char *ptr)
{
- VALUE str = rb_str_new_cstr(ptr);
- rb_enc_associate_index(str, rb_utf8_encindex());
- return str;
+ return rb_enc_str_new_cstr(ptr, rb_utf8_encoding());
}
VALUE
@@ -1057,8 +1152,7 @@ str_new_static(VALUE klass, const char *ptr, long len, int encindex)
}
if (!ptr) {
- rb_encoding *enc = rb_enc_get_from_index(encindex);
- str = str_new0(klass, ptr, len, rb_enc_mbminlen(enc));
+ str = str_enc_new(klass, ptr, len, rb_enc_from_index(encindex));
}
else {
RUBY_DTRACE_CREATE_HOOK(STRING, len);
@@ -1067,8 +1161,8 @@ str_new_static(VALUE klass, const char *ptr, long len, int encindex)
RSTRING(str)->as.heap.ptr = (char *)ptr;
RSTRING(str)->as.heap.aux.capa = len;
RBASIC(str)->flags |= STR_NOFREE;
+ rb_enc_associate_index(str, encindex);
}
- rb_enc_associate_index(str, encindex);
return str;
}
@@ -1415,6 +1509,14 @@ rb_str_new_frozen_String(VALUE orig)
return str_new_frozen(rb_cString, orig);
}
+
+VALUE
+rb_str_frozen_bare_string(VALUE orig)
+{
+ if (RB_LIKELY(BARE_STRING_P(orig) && OBJ_FROZEN_RAW(orig))) return orig;
+ return str_new_frozen(rb_cString, orig);
+}
+
VALUE
rb_str_tmp_frozen_acquire(VALUE orig)
{
@@ -1439,7 +1541,7 @@ rb_str_tmp_frozen_no_embed_acquire(VALUE orig)
* allocated. If the string is shared then the shared root must be
* embedded, so we want to create a copy. If the string is a shared root
* then it must be embedded, so we want to create a copy. */
- if (STR_EMBED_P(orig) || FL_TEST_RAW(orig, STR_SHARED | STR_SHARED_ROOT)) {
+ if (STR_EMBED_P(orig) || FL_TEST_RAW(orig, STR_SHARED | STR_SHARED_ROOT | RSTRING_FSTR)) {
RSTRING(str)->as.heap.ptr = rb_xmalloc_mul_add_mul(sizeof(char), capa, sizeof(char), TERM_LEN(orig));
memcpy(RSTRING(str)->as.heap.ptr, RSTRING_PTR(orig), capa);
}
@@ -1450,6 +1552,10 @@ rb_str_tmp_frozen_no_embed_acquire(VALUE orig)
RBASIC(str)->flags |= RBASIC(orig)->flags & STR_NOFREE;
RBASIC(orig)->flags &= ~STR_NOFREE;
STR_SET_SHARED(orig, str);
+ if (RB_OBJ_SHAREABLE_P(orig)) {
+ RB_OBJ_SET_SHAREABLE(str);
+ RUBY_ASSERT((rb_gc_verify_shareable(str), 1));
+ }
}
RSTRING(str)->len = RSTRING(orig)->len;
@@ -1467,8 +1573,8 @@ rb_str_tmp_frozen_release(VALUE orig, VALUE tmp)
if (STR_EMBED_P(tmp)) {
RUBY_ASSERT(OBJ_FROZEN_RAW(tmp));
}
- else if (FL_TEST_RAW(orig, STR_SHARED) &&
- !FL_TEST_RAW(orig, STR_TMPLOCK|RUBY_FL_FREEZE)) {
+ else if (FL_TEST_RAW(orig, STR_SHARED | STR_TMPLOCK) == STR_TMPLOCK &&
+ !OBJ_FROZEN_RAW(orig)) {
VALUE shared = RSTRING(orig)->as.heap.aux.shared;
if (shared == tmp && !FL_TEST_RAW(tmp, STR_BORROWED)) {
@@ -1499,6 +1605,7 @@ heap_str_make_shared(VALUE klass, VALUE orig)
{
RUBY_ASSERT(!STR_EMBED_P(orig));
RUBY_ASSERT(!STR_SHARED_P(orig));
+ RUBY_ASSERT(!RB_OBJ_SHAREABLE_P(orig));
VALUE str = str_alloc_heap(klass);
STR_SET_LEN(str, RSTRING_LEN(orig));
@@ -1508,7 +1615,7 @@ heap_str_make_shared(VALUE klass, VALUE orig)
RBASIC(orig)->flags &= ~STR_NOFREE;
STR_SET_SHARED(orig, str);
if (klass == 0)
- FL_UNSET_RAW(str, STR_BORROWED);
+ FL_UNSET_RAW(str, STR_BORROWED);
return str;
}
@@ -1518,10 +1625,11 @@ str_new_frozen_buffer(VALUE klass, VALUE orig, int copy_encoding)
VALUE str;
long len = RSTRING_LEN(orig);
+ rb_encoding *enc = copy_encoding ? STR_ENC_GET(orig) : rb_ascii8bit_encoding();
int termlen = copy_encoding ? TERM_LEN(orig) : 1;
if (STR_EMBED_P(orig) || STR_EMBEDDABLE_P(len, termlen)) {
- str = str_new0(klass, RSTRING_PTR(orig), len, termlen);
+ str = str_enc_new(klass, RSTRING_PTR(orig), len, enc);
RUBY_ASSERT(STR_EMBED_P(str));
}
else {
@@ -1557,7 +1665,12 @@ str_new_frozen_buffer(VALUE klass, VALUE orig, int copy_encoding)
TERM_FILL(RSTRING_END(str), TERM_LEN(orig));
}
else {
- str = heap_str_make_shared(klass, orig);
+ if (RB_OBJ_SHAREABLE_P(orig)) {
+ str = str_new(klass, RSTRING_PTR(orig), RSTRING_LEN(orig));
+ }
+ else {
+ str = heap_str_make_shared(klass, orig);
+ }
}
}
@@ -1569,7 +1682,7 @@ str_new_frozen_buffer(VALUE klass, VALUE orig, int copy_encoding)
VALUE
rb_str_new_with_class(VALUE obj, const char *ptr, long len)
{
- return str_new0(rb_obj_class(obj), ptr, len, TERM_LEN(obj));
+ return str_enc_new(rb_obj_class(obj), ptr, len, STR_ENC_GET(obj));
}
static VALUE
@@ -1619,17 +1732,6 @@ rb_str_tmp_new(long len)
void
rb_str_free(VALUE str)
{
- if (FL_TEST(str, RSTRING_FSTR)) {
- st_data_t fstr = (st_data_t)str;
-
- 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)) {
RB_DEBUG_COUNTER_INC(obj_str_embed);
}
@@ -1770,13 +1872,15 @@ str_replace(VALUE str, VALUE str2)
static inline VALUE
ec_str_alloc_embed(struct rb_execution_context_struct *ec, VALUE klass, size_t capa)
{
- size_t size = rb_str_embed_size(capa);
+ size_t size = rb_str_embed_size(capa, 0);
RUBY_ASSERT(size > 0);
RUBY_ASSERT(rb_gc_size_allocatable_p(size));
NEWOBJ_OF(str, struct RString, klass,
T_STRING | (RGENGC_WB_PROTECTED_STRING ? FL_WB_PROTECTED : 0), size, ec);
+ str->len = 0;
+
return (VALUE)str;
}
@@ -1786,45 +1890,16 @@ ec_str_alloc_heap(struct rb_execution_context_struct *ec, VALUE klass)
NEWOBJ_OF(str, struct RString, klass,
T_STRING | STR_NOEMBED | (RGENGC_WB_PROTECTED_STRING ? FL_WB_PROTECTED : 0), sizeof(struct RString), ec);
+ str->as.heap.aux.capa = 0;
+ str->as.heap.ptr = NULL;
+
return (VALUE)str;
}
static inline VALUE
-str_duplicate_setup(VALUE klass, VALUE str, VALUE dup)
+str_duplicate_setup_encoding(VALUE str, VALUE dup, VALUE flags)
{
- const VALUE flag_mask =
- ENC_CODERANGE_MASK | ENCODING_MASK |
- FL_FREEZE
- ;
- VALUE flags = FL_TEST_RAW(str, flag_mask);
int encidx = 0;
- if (STR_EMBED_P(str)) {
- long len = RSTRING_LEN(str);
-
- RUBY_ASSERT(STR_EMBED_P(dup));
- RUBY_ASSERT(str_embed_capa(dup) >= len + 1);
- 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)) {
- root = RSTRING(str)->as.heap.aux.shared;
- }
- else if (UNLIKELY(!(flags & FL_FREEZE))) {
- root = str = str_new_frozen(klass, str);
- flags = FL_TEST_RAW(str, flag_mask);
- }
- RUBY_ASSERT(!STR_SHARED_P(root));
- RUBY_ASSERT(RB_OBJ_FROZEN_RAW(root));
-
- RSTRING(dup)->as.heap.ptr = RSTRING_PTR(str);
- FL_SET(root, STR_SHARED_ROOT);
- RB_OBJ_WRITE(dup, &RSTRING(dup)->as.heap.aux.shared, root);
- flags |= RSTRING_NOEMBED | STR_SHARED;
- }
-
- STR_SET_LEN(dup, RSTRING_LEN(str));
-
if ((flags & ENCODING_MASK) == (ENCODING_INLINE_MAX<<ENCODING_SHIFT)) {
encidx = rb_enc_get_index(str);
flags &= ~ENCODING_MASK;
@@ -1834,18 +1909,54 @@ str_duplicate_setup(VALUE klass, VALUE str, VALUE dup)
return dup;
}
+static const VALUE flag_mask = ENC_CODERANGE_MASK | ENCODING_MASK | FL_FREEZE;
+
static inline VALUE
-ec_str_duplicate(struct rb_execution_context_struct *ec, VALUE klass, VALUE str)
+str_duplicate_setup_embed(VALUE klass, VALUE str, VALUE dup)
+{
+ VALUE flags = FL_TEST_RAW(str, flag_mask);
+ long len = RSTRING_LEN(str);
+
+ RUBY_ASSERT(STR_EMBED_P(dup));
+ RUBY_ASSERT(str_embed_capa(dup) >= len + TERM_LEN(str));
+ MEMCPY(RSTRING(dup)->as.embed.ary, RSTRING(str)->as.embed.ary, char, len + TERM_LEN(str));
+ STR_SET_LEN(dup, RSTRING_LEN(str));
+ return str_duplicate_setup_encoding(str, dup, flags);
+}
+
+static inline VALUE
+str_duplicate_setup_heap(VALUE klass, VALUE str, VALUE dup)
+{
+ VALUE flags = FL_TEST_RAW(str, flag_mask);
+ VALUE root = str;
+ if (FL_TEST_RAW(str, STR_SHARED)) {
+ root = RSTRING(str)->as.heap.aux.shared;
+ }
+ else if (UNLIKELY(!OBJ_FROZEN_RAW(str))) {
+ root = str = str_new_frozen(klass, str);
+ flags = FL_TEST_RAW(str, flag_mask);
+ }
+ RUBY_ASSERT(!STR_SHARED_P(root));
+ RUBY_ASSERT(RB_OBJ_FROZEN_RAW(root));
+
+ RSTRING(dup)->as.heap.ptr = RSTRING_PTR(str);
+ FL_SET_RAW(dup, RSTRING_NOEMBED);
+ STR_SET_SHARED(dup, root);
+ flags |= RSTRING_NOEMBED | STR_SHARED;
+
+ STR_SET_LEN(dup, RSTRING_LEN(str));
+ return str_duplicate_setup_encoding(str, dup, flags);
+}
+
+static inline VALUE
+str_duplicate_setup(VALUE klass, VALUE str, VALUE dup)
{
- VALUE dup;
if (STR_EMBED_P(str)) {
- dup = ec_str_alloc_embed(ec, klass, RSTRING_LEN(str) + TERM_LEN(str));
+ return str_duplicate_setup_embed(klass, str, dup);
}
else {
- dup = ec_str_alloc_heap(ec, klass);
+ return str_duplicate_setup_heap(klass, str, dup);
}
-
- return str_duplicate_setup(klass, str, dup);
}
static inline VALUE
@@ -1873,7 +1984,7 @@ VALUE
rb_str_dup_m(VALUE str)
{
if (LIKELY(BARE_STRING_P(str))) {
- return str_duplicate(rb_obj_class(str), str);
+ return str_duplicate(rb_cString, str);
}
else {
return rb_obj_dup(str);
@@ -1891,17 +2002,41 @@ VALUE
rb_ec_str_resurrect(struct rb_execution_context_struct *ec, VALUE str, bool chilled)
{
RUBY_DTRACE_CREATE_HOOK(STRING, RSTRING_LEN(str));
- VALUE new_str = ec_str_duplicate(ec, rb_cString, str);
+ VALUE new_str, klass = rb_cString;
+
+ if (!(chilled && RTEST(rb_ivar_defined(str, id_debug_created_info))) && STR_EMBED_P(str)) {
+ new_str = ec_str_alloc_embed(ec, klass, RSTRING_LEN(str) + TERM_LEN(str));
+ str_duplicate_setup_embed(klass, str, new_str);
+ }
+ else {
+ new_str = ec_str_alloc_heap(ec, klass);
+ str_duplicate_setup_heap(klass, str, new_str);
+ }
if (chilled) {
- STR_CHILL_RAW(new_str);
+ FL_SET_RAW(new_str, STR_CHILLED_LITERAL);
}
return new_str;
}
+VALUE
+rb_str_with_debug_created_info(VALUE str, VALUE path, int line)
+{
+ VALUE debug_info = rb_ary_new_from_args(2, path, INT2FIX(line));
+ if (OBJ_FROZEN_RAW(str)) str = rb_str_dup(str);
+ rb_ivar_set(str, id_debug_created_info, rb_ary_freeze(debug_info));
+ FL_SET_RAW(str, STR_CHILLED_LITERAL);
+ return rb_str_freeze(str);
+}
+
+/*
+ * The documentation block below uses an include (instead of inline text)
+ * because the included text has non-ASCII characters (which are not allowed in a C file).
+ */
+
/*
*
* call-seq:
- * String.new(string = '', **opts) -> new_string
+ * String.new(string = ''.encode(Encoding::ASCII_8BIT) , **options) -> new_string
*
* :include: doc/string/new.rdoc
*
@@ -2008,8 +2143,6 @@ rb_str_s_new(int argc, VALUE *argv, VALUE klass)
encoding = kwargs[0];
capacity = kwargs[1];
- int termlen = 1;
-
if (n == 1) {
orig = StringValue(orig);
}
@@ -2025,7 +2158,6 @@ rb_str_s_new(int argc, VALUE *argv, VALUE klass)
if (!UNDEF_P(encoding)) {
enc = rb_to_encoding(encoding);
- termlen = rb_enc_mbminlen(enc);
}
// If capacity is nil, we're basically just duping `orig`.
@@ -2056,18 +2188,9 @@ rb_str_s_new(int argc, VALUE *argv, VALUE klass)
}
}
- long fake_len = capa - termlen;
- if (fake_len < 0) {
- fake_len = 0;
- }
-
- VALUE str = str_new0(klass, NULL, fake_len, termlen);
+ VALUE str = str_enc_new(klass, NULL, capa, enc);
STR_SET_LEN(str, 0);
- TERM_FILL(RSTRING_PTR(str), termlen);
-
- if (enc) {
- rb_enc_associate(str, enc);
- }
+ TERM_FILL(RSTRING_PTR(str), enc ? rb_enc_mbmaxlen(enc) : 1);
if (!NIL_P(orig)) {
rb_str_buf_append(str, orig);
@@ -2315,12 +2438,13 @@ rb_str_bytesize(VALUE str)
* call-seq:
* empty? -> true or false
*
- * Returns +true+ if the length of +self+ is zero, +false+ otherwise:
+ * Returns whether the length of +self+ is zero:
*
- * "hello".empty? # => false
- * " ".empty? # => false
- * "".empty? # => true
+ * 'hello'.empty? # => false
+ * ' '.empty? # => false
+ * ''.empty? # => true
*
+ * Related: see {Querying}[rdoc-ref:String@Querying].
*/
static VALUE
@@ -2331,12 +2455,13 @@ rb_str_empty(VALUE str)
/*
* call-seq:
- * string + other_string -> new_string
+ * self + other_string -> new_string
*
- * Returns a new +String+ containing +other_string+ concatenated to +self+:
+ * 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"
*
+ * Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
*/
VALUE
@@ -2356,7 +2481,7 @@ rb_str_plus(VALUE str1, VALUE str2)
if (len1 > LONG_MAX - len2) {
rb_raise(rb_eArgError, "string size too big");
}
- str3 = str_new0(rb_cString, 0, len1+len2, termlen);
+ str3 = str_enc_new(rb_cString, 0, len1+len2, enc);
ptr3 = RSTRING_PTR(str3);
memcpy(ptr3, ptr1, len1);
memcpy(ptr3+len1, ptr2, len2);
@@ -2402,13 +2527,14 @@ rb_str_opt_plus(VALUE str1, VALUE str2)
/*
* call-seq:
- * string * integer -> new_string
+ * self * n -> new_string
*
- * Returns a new +String+ containing +integer+ copies of +self+:
+ * Returns a new string containing +n+ copies of +self+:
*
- * "Ho! " * 3 # => "Ho! Ho! Ho! "
- * "Ho! " * 0 # => ""
+ * 'Ho!' * 3 # => "Ho!Ho!Ho!"
+ * 'No!' * 0 # => ""
*
+ * Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
*/
VALUE
@@ -2451,7 +2577,7 @@ rb_str_times(VALUE str, VALUE times)
len *= RSTRING_LEN(str);
termlen = TERM_LEN(str);
- str2 = str_new0(rb_cString, 0, len, termlen);
+ str2 = str_enc_new(rb_cString, 0, len, STR_ENC_GET(str));
ptr2 = RSTRING_PTR(str2);
if (len) {
n = RSTRING_LEN(str);
@@ -2471,20 +2597,22 @@ rb_str_times(VALUE str, VALUE times)
/*
* call-seq:
- * string % object -> new_string
+ * self % object -> new_string
*
- * Returns the result of formatting +object+ into the format specification +self+
- * (see Kernel#sprintf for formatting details):
+ * Returns the result of formatting +object+ into the format specifications
+ * contained in +self+
+ * (see {Format Specifications}[rdoc-ref:language/format_specifications.rdoc]):
*
- * "%05d" % 123 # => "00123"
+ * '%05d' % 123 # => "00123"
*
- * If +self+ contains multiple substitutions, +object+ must be
- * an Array or Hash containing the values to be substituted:
+ * If +self+ contains multiple format specifications,
+ * +object+ must be an array or hash containing the objects to be formatted:
*
- * "%-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"
+ * '%-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"
*
+ * Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
*/
static VALUE
@@ -2506,37 +2634,54 @@ rb_check_lockedtmp(VALUE str)
}
}
+// If none of these flags are set, we know we have an modifiable string.
+// If any is set, we need to do more detailed checks.
+#define STR_UNMODIFIABLE_MASK (FL_FREEZE | STR_TMPLOCK | STR_CHILLED)
static inline void
str_modifiable(VALUE str)
{
- if (CHILLED_STRING_P(str)) {
- CHILLED_STRING_MUTATED(str);
+ RUBY_ASSERT(ruby_thread_has_gvl_p());
+
+ if (RB_UNLIKELY(FL_ANY_RAW(str, STR_UNMODIFIABLE_MASK))) {
+ if (CHILLED_STRING_P(str)) {
+ CHILLED_STRING_MUTATED(str);
+ }
+ rb_check_lockedtmp(str);
+ rb_check_frozen(str);
}
- rb_check_lockedtmp(str);
- rb_check_frozen(str);
}
static inline int
str_dependent_p(VALUE str)
{
if (STR_EMBED_P(str) || !FL_TEST(str, STR_SHARED|STR_NOFREE)) {
- return 0;
+ return FALSE;
}
else {
- return 1;
+ return TRUE;
}
}
+// If none of these flags are set, we know we have an independent string.
+// If any is set, we need to do more detailed checks.
+#define STR_DEPENDANT_MASK (STR_UNMODIFIABLE_MASK | STR_SHARED | STR_NOFREE)
static inline int
str_independent(VALUE str)
{
- str_modifiable(str);
- return !str_dependent_p(str);
+ RUBY_ASSERT(ruby_thread_has_gvl_p());
+
+ if (RB_UNLIKELY(FL_ANY_RAW(str, STR_DEPENDANT_MASK))) {
+ str_modifiable(str);
+ return !str_dependent_p(str);
+ }
+ return TRUE;
}
static void
str_make_independent_expand(VALUE str, long len, long expand, const int termlen)
{
+ RUBY_ASSERT(ruby_thread_has_gvl_p());
+
char *ptr;
char *oldptr;
long capa = len + expand;
@@ -2579,6 +2724,8 @@ rb_str_modify(VALUE str)
void
rb_str_modify_expand(VALUE str, long expand)
{
+ RUBY_ASSERT(ruby_thread_has_gvl_p());
+
int termlen = TERM_LEN(str);
long len = RSTRING_LEN(str);
@@ -2623,10 +2770,17 @@ str_discard(VALUE str)
void
rb_must_asciicompat(VALUE str)
{
- rb_encoding *enc = rb_enc_get(str);
- if (!enc) {
+ int encindex = rb_enc_get_index(str);
+
+ if (RB_UNLIKELY(encindex == -1)) {
rb_raise(rb_eTypeError, "not encoding capable object");
}
+
+ if (RB_LIKELY(rb_str_encindex_fastpath(encindex))) {
+ return;
+ }
+
+ rb_encoding *enc = rb_enc_from_index(encindex);
if (!rb_enc_asciicompat(enc)) {
rb_raise(rb_eEncCompatError, "ASCII incompatible encoding: %s", rb_enc_name(enc));
}
@@ -2635,6 +2789,8 @@ rb_must_asciicompat(VALUE str)
VALUE
rb_string_value(volatile VALUE *ptr)
{
+ RUBY_ASSERT(ruby_thread_has_gvl_p());
+
VALUE s = *ptr;
if (!RB_TYPE_P(s, T_STRING)) {
s = rb_str_to_str(s);
@@ -2721,16 +2877,21 @@ str_null_check(VALUE str, int *w)
{
char *s = RSTRING_PTR(str);
long len = RSTRING_LEN(str);
- rb_encoding *enc = rb_enc_get(str);
- const int minlen = rb_enc_mbminlen(enc);
+ int minlen = 1;
+
+ if (RB_UNLIKELY(!rb_str_enc_fastpath(str))) {
+ rb_encoding *enc = rb_enc_get(str);
+ minlen = rb_enc_mbminlen(enc);
- if (minlen > 1) {
- *w = 1;
- if (str_null_char(s, len, minlen, enc)) {
- return NULL;
+ if (minlen > 1) {
+ *w = 1;
+ if (str_null_char(s, len, minlen, enc)) {
+ return NULL;
+ }
+ return str_fill_term(str, s, len, minlen);
}
- return str_fill_term(str, s, len, minlen);
}
+
*w = 0;
if (!s || memchr(s, 0, len)) {
return NULL;
@@ -2741,6 +2902,34 @@ str_null_check(VALUE str, int *w)
return s;
}
+const char *
+rb_str_null_check(VALUE str)
+{
+ RUBY_ASSERT(RB_TYPE_P(str, T_STRING));
+
+ char *s;
+ long len;
+ RSTRING_GETMEM(str, s, len);
+
+ if (RB_LIKELY(rb_str_enc_fastpath(str))) {
+ if (!s || memchr(s, 0, len)) {
+ rb_raise(rb_eArgError, "string contains null byte");
+ }
+ }
+ else {
+ int w;
+ const char *s = str_null_check(str, &w);
+ if (!s) {
+ if (w) {
+ rb_raise(rb_eArgError, "string contains null char");
+ }
+ rb_raise(rb_eArgError, "string contains null byte");
+ }
+ }
+
+ return s;
+}
+
char *
rb_str_to_cstr(VALUE str)
{
@@ -2782,14 +2971,16 @@ rb_check_string_type(VALUE str)
* call-seq:
* String.try_convert(object) -> object, new_string, or nil
*
- * If +object+ is a +String+ object, returns +object+.
+ * Attempts to convert the given +object+ to a string.
+ *
+ * If +object+ is already a string, returns +object+, unmodified.
*
* Otherwise if +object+ responds to <tt>:to_str</tt>,
* calls <tt>object.to_str</tt> and returns the result.
*
* Returns +nil+ if +object+ does not respond to <tt>:to_str</tt>.
*
- * Raises an exception unless <tt>object.to_str</tt> returns a +String+ object.
+ * Raises an exception unless <tt>object.to_str</tt> returns a string.
*/
static VALUE
rb_str_s_try_convert(VALUE dummy, VALUE str)
@@ -2985,11 +3176,12 @@ rb_str_subpos(VALUE str, long beg, long *lenp)
{
long len = *lenp;
long slen = -1L;
- long blen = RSTRING_LEN(str);
+ const long blen = RSTRING_LEN(str);
rb_encoding *enc = STR_ENC_GET(str);
char *p, *s = RSTRING_PTR(str), *e = s + blen;
if (len < 0) return 0;
+ if (beg < 0 && -beg < 0) return 0;
if (!blen) {
len = 0;
}
@@ -3007,7 +3199,8 @@ rb_str_subpos(VALUE str, long beg, long *lenp)
}
if (beg < 0) {
if (len > -beg) len = -beg;
- if (-beg * rb_enc_mbmaxlen(enc) < RSTRING_LEN(str) / 8) {
+ if ((ENC_CODERANGE(str) == ENC_CODERANGE_VALID) &&
+ (-beg * rb_enc_mbmaxlen(enc) < blen / 8)) {
beg = -beg;
while (beg-- > len && (e = rb_enc_prev_char(s, e, e, enc)) != 0);
p = e;
@@ -3025,7 +3218,7 @@ rb_str_subpos(VALUE str, long beg, long *lenp)
if (len == 0) goto end;
}
}
- else if (beg > 0 && beg > RSTRING_LEN(str)) {
+ else if (beg > 0 && beg > blen) {
return 0;
}
if (len == 0) {
@@ -3073,6 +3266,12 @@ rb_str_substr(VALUE str, long beg, long len)
return str_substr(str, beg, len, TRUE);
}
+VALUE
+rb_str_substr_two_fixnums(VALUE str, VALUE beg, VALUE len, int empty)
+{
+ return str_substr(str, NUM2LONG(beg), NUM2LONG(len), empty);
+}
+
static VALUE
str_substr(VALUE str, long beg, long len, int empty)
{
@@ -3105,9 +3304,12 @@ rb_str_freeze(VALUE str)
* call-seq:
* +string -> new_string or self
*
- * Returns +self+ if +self+ is not frozen.
+ * Returns +self+ if +self+ is not frozen and can be mutated
+ * without warning issuance.
*
* Otherwise returns <tt>self.dup</tt>, which is not frozen.
+ *
+ * Related: see {Freezing/Unfreezing}[rdoc-ref:String@Freezing-2FUnfreezing].
*/
static VALUE
str_uplus(VALUE str)
@@ -3122,24 +3324,37 @@ str_uplus(VALUE str)
/*
* call-seq:
- * -string -> frozen_string
- * dedup -> frozen_string
+ * -self -> frozen_string
+ *
+ * Returns a frozen string equal to +self+.
*
- * Returns a frozen, possibly pre-existing copy of the string.
+ * The returned string is +self+ if and only if all of the following are true:
*
- * The returned +String+ will be deduplicated as long as it does not have
- * any instance variables set on it and is not a String subclass.
+ * - +self+ is already frozen.
+ * - +self+ is an instance of \String (rather than of a subclass of \String)
+ * - +self+ has no instance variables set on it.
*
- * Note that <tt>-string</tt> variant is more convenient for defining
- * constants:
+ * Otherwise, the returned string is a frozen copy of +self+.
*
- * FILENAME = -'config/database.yml'
+ * Returning +self+, when possible, saves duplicating +self+;
+ * see {Data deduplication}[https://en.wikipedia.org/wiki/Data_deduplication].
*
- * while +dedup+ is better suitable for using the method in chains
- * of calculations:
+ * It may also save duplicating other, already-existing, strings:
*
- * @url_list.concat(urls.map(&:dedup))
+ * s0 = 'foo'
+ * s1 = 'foo'
+ * s0.object_id == s1.object_id # => false
+ * (-s0).object_id == (-s1).object_id # => true
*
+ * Note that method #-@ is convenient for defining a constant:
+ *
+ * FileName = -'config/database.yml'
+ *
+ * While its alias #dedup is better suited for chaining:
+ *
+ * 'foo'.dedup.gsub!('o')
+ *
+ * Related: see {Freezing/Unfreezing}[rdoc-ref:String@Freezing-2FUnfreezing].
*/
static VALUE
str_uminus(VALUE str)
@@ -3156,6 +3371,7 @@ RUBY_ALIAS_FUNCTION(rb_str_dup_frozen(VALUE str), rb_str_new_frozen, (str))
VALUE
rb_str_locktmp(VALUE str)
{
+ rb_check_frozen(str);
if (FL_TEST(str, STR_TMPLOCK)) {
rb_raise(rb_eRuntimeError, "temporal locking already locked string");
}
@@ -3166,6 +3382,7 @@ rb_str_locktmp(VALUE str)
VALUE
rb_str_unlocktmp(VALUE str)
{
+ rb_check_frozen(str);
if (!FL_TEST(str, STR_TMPLOCK)) {
rb_raise(rb_eRuntimeError, "temporal unlocking already unlocked string");
}
@@ -3183,6 +3400,8 @@ rb_str_locktmp_ensure(VALUE str, VALUE (*func)(VALUE), VALUE arg)
void
rb_str_set_len(VALUE str, long len)
{
+ RUBY_ASSERT(ruby_thread_has_gvl_p());
+
long capa;
const int termlen = TERM_LEN(str);
@@ -3237,14 +3456,14 @@ rb_str_resize(VALUE str, long len)
int independent = str_independent(str);
long slen = RSTRING_LEN(str);
+ const int termlen = TERM_LEN(str);
- if (slen > len && ENC_CODERANGE(str) != ENC_CODERANGE_7BIT) {
+ if (slen > len || (termlen != 1 && slen < len)) {
ENC_CODERANGE_CLEAR(str);
}
{
long capa;
- const int termlen = TERM_LEN(str);
if (STR_EMBED_P(str)) {
if (len == slen) return str;
if (str_embed_capa(str) >= len + termlen) {
@@ -3281,6 +3500,32 @@ rb_str_resize(VALUE str, long len)
return str;
}
+static void
+str_ensure_available_capa(VALUE str, long len)
+{
+ str_modify_keep_cr(str);
+
+ const int termlen = TERM_LEN(str);
+ long olen = RSTRING_LEN(str);
+
+ if (RB_UNLIKELY(olen > LONG_MAX - len)) {
+ rb_raise(rb_eArgError, "string sizes too big");
+ }
+
+ long total = olen + len;
+ long capa = str_capacity(str, termlen);
+
+ if (capa < total) {
+ if (total >= LONG_MAX / 2) {
+ capa = total;
+ }
+ while (total > capa) {
+ capa = 2 * capa + termlen; /* == 2*(capa+termlen)-termlen */
+ }
+ RESIZE_CAPA_TERM(str, capa, termlen);
+ }
+}
+
static VALUE
str_buf_cat4(VALUE str, const char *ptr, long len, bool keep_cr)
{
@@ -3347,6 +3592,62 @@ rb_str_cat_cstr(VALUE str, const char *ptr)
return rb_str_buf_cat(str, ptr, strlen(ptr));
}
+static void
+rb_str_buf_cat_byte(VALUE str, unsigned char byte)
+{
+ RUBY_ASSERT(RB_ENCODING_GET_INLINED(str) == ENCINDEX_ASCII_8BIT || RB_ENCODING_GET_INLINED(str) == ENCINDEX_US_ASCII);
+
+ // We can't write directly to shared strings without impacting others, so we must make the string independent.
+ if (UNLIKELY(!str_independent(str))) {
+ str_make_independent(str);
+ }
+
+ long string_length = -1;
+ const int null_terminator_length = 1;
+ char *sptr;
+ RSTRING_GETMEM(str, sptr, string_length);
+
+ // Ensure the resulting string wouldn't be too long.
+ if (UNLIKELY(string_length > LONG_MAX - 1)) {
+ rb_raise(rb_eArgError, "string sizes too big");
+ }
+
+ long string_capacity = str_capacity(str, null_terminator_length);
+
+ // Get the code range before any modifications since those might clear the code range.
+ int cr = ENC_CODERANGE(str);
+
+ // Check if the string has spare string_capacity to write the new byte.
+ if (LIKELY(string_capacity >= string_length + 1)) {
+ // In fast path we can write the new byte and note the string's new length.
+ sptr[string_length] = byte;
+ STR_SET_LEN(str, string_length + 1);
+ TERM_FILL(sptr + string_length + 1, null_terminator_length);
+ }
+ else {
+ // If there's not enough string_capacity, make a call into the general string concatenation function.
+ str_buf_cat(str, (char *)&byte, 1);
+ }
+
+ // If the code range is already known, we can derive the resulting code range cheaply by looking at the byte we
+ // just appended. If the code range is unknown, but the string was empty, then we can also derive the code range
+ // by looking at the byte we just appended. Otherwise, we'd have to scan the bytes to determine the code range so
+ // we leave it as unknown. It cannot be broken for binary strings so we don't need to handle that option.
+ if (cr == ENC_CODERANGE_7BIT || string_length == 0) {
+ if (ISASCII(byte)) {
+ ENC_CODERANGE_SET(str, ENC_CODERANGE_7BIT);
+ }
+ else {
+ ENC_CODERANGE_SET(str, ENC_CODERANGE_VALID);
+
+ // Promote a US-ASCII string to ASCII-8BIT when a non-ASCII byte is appended.
+ if (UNLIKELY(RB_ENCODING_GET_INLINED(str) == ENCINDEX_US_ASCII)) {
+ rb_enc_associate_index(str, ENCINDEX_ASCII_8BIT);
+ }
+ }
+ }
+}
+
RUBY_ALIAS_FUNCTION(rb_str_buf_cat(VALUE str, const char *ptr, long len), rb_str_cat, (str, ptr, len))
RUBY_ALIAS_FUNCTION(rb_str_buf_cat2(VALUE str, const char *ptr), rb_str_cat_cstr, (str, ptr))
RUBY_ALIAS_FUNCTION(rb_str_cat2(VALUE str, const char *ptr), rb_str_cat_cstr, (str, ptr))
@@ -3477,7 +3778,7 @@ rb_str_buf_append(VALUE str, VALUE str2)
{
int str2_cr = rb_enc_str_coderange(str2);
- if (str_enc_fastpath(str)) {
+ if (rb_str_enc_fastpath(str)) {
switch (str2_cr) {
case ENC_CODERANGE_7BIT:
// If RHS is 7bit we can do simple concatenation
@@ -3544,19 +3845,7 @@ rb_str_concat_literals(size_t num, const VALUE *strary)
* call-seq:
* concat(*objects) -> string
*
- * Concatenates each object in +objects+ to +self+ and returns +self+:
- *
- * s = 'foo'
- * s.concat('bar', 'baz') # => "foobarbaz"
- * s # => "foobarbaz"
- *
- * For each given object +object+ that is an Integer,
- * the value is considered a codepoint and converted to a character before concatenation:
- *
- * s = 'foo'
- * s.concat(32, 'bar', 32, 'baz') # => "foo bar baz"
- *
- * Related: String#<<, which takes a single argument.
+ * :include: doc/string/concat.rdoc
*/
static VALUE
rb_str_concat_multi(int argc, VALUE *argv, VALUE str)
@@ -3581,21 +3870,179 @@ rb_str_concat_multi(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * string << object -> string
+ * append_as_bytes(*objects) -> self
+ *
+ * Concatenates each object in +objects+ into +self+; returns +self+;
+ * performs no encoding validation or conversion:
+ *
+ * s = 'foo'
+ * s.append_as_bytes(" \xE2\x82") # => "foo \xE2\x82"
+ * s.valid_encoding? # => false
+ * s.append_as_bytes("\xAC 12")
+ * s.valid_encoding? # => true
+ *
+ * When a given object is an integer,
+ * the value is considered an 8-bit byte;
+ * if the integer occupies more than one byte (i.e,. is greater than 255),
+ * appends only the low-order byte (similar to String#setbyte):
+ *
+ * s = ""
+ * s.append_as_bytes(0, 257) # => "\u0000\u0001"
+ * s.bytesize # => 2
+ *
+ * Related: see {Modifying}[rdoc-ref:String@Modifying].
+ */
+
+VALUE
+rb_str_append_as_bytes(int argc, VALUE *argv, VALUE str)
+{
+ long needed_capacity = 0;
+ volatile VALUE t0;
+ enum ruby_value_type *types = ALLOCV_N(enum ruby_value_type, t0, argc);
+
+ for (int index = 0; index < argc; index++) {
+ VALUE obj = argv[index];
+ enum ruby_value_type type = types[index] = rb_type(obj);
+ switch (type) {
+ case T_FIXNUM:
+ case T_BIGNUM:
+ needed_capacity++;
+ break;
+ case T_STRING:
+ needed_capacity += RSTRING_LEN(obj);
+ break;
+ default:
+ rb_raise(
+ rb_eTypeError,
+ "wrong argument type %"PRIsVALUE" (expected String or Integer)",
+ rb_obj_class(obj)
+ );
+ break;
+ }
+ }
+
+ str_ensure_available_capa(str, needed_capacity);
+ char *sptr = RSTRING_END(str);
+
+ for (int index = 0; index < argc; index++) {
+ VALUE obj = argv[index];
+ enum ruby_value_type type = types[index];
+ switch (type) {
+ case T_FIXNUM:
+ case T_BIGNUM: {
+ argv[index] = obj = rb_int_and(obj, INT2FIX(0xff));
+ char byte = (char)(NUM2INT(obj) & 0xFF);
+ *sptr = byte;
+ sptr++;
+ break;
+ }
+ case T_STRING: {
+ const char *ptr;
+ long len;
+ RSTRING_GETMEM(obj, ptr, len);
+ memcpy(sptr, ptr, len);
+ sptr += len;
+ break;
+ }
+ default:
+ rb_bug("append_as_bytes arguments should have been validated");
+ }
+ }
+
+ STR_SET_LEN(str, RSTRING_LEN(str) + needed_capacity);
+ TERM_FILL(sptr, TERM_LEN(str)); /* sentinel */
+
+ int cr = ENC_CODERANGE(str);
+ switch (cr) {
+ case ENC_CODERANGE_7BIT: {
+ for (int index = 0; index < argc; index++) {
+ VALUE obj = argv[index];
+ enum ruby_value_type type = types[index];
+ switch (type) {
+ case T_FIXNUM:
+ case T_BIGNUM: {
+ if (!ISASCII(NUM2INT(obj))) {
+ goto clear_cr;
+ }
+ break;
+ }
+ case T_STRING: {
+ if (ENC_CODERANGE(obj) != ENC_CODERANGE_7BIT) {
+ goto clear_cr;
+ }
+ break;
+ }
+ default:
+ rb_bug("append_as_bytes arguments should have been validated");
+ }
+ }
+ break;
+ }
+ case ENC_CODERANGE_VALID:
+ if (ENCODING_GET_INLINED(str) == ENCINDEX_ASCII_8BIT) {
+ goto keep_cr;
+ }
+ else {
+ goto clear_cr;
+ }
+ break;
+ default:
+ goto clear_cr;
+ break;
+ }
+
+ RB_GC_GUARD(t0);
+
+ clear_cr:
+ // If no fast path was hit, we clear the coderange.
+ // append_as_bytes is predominantly meant to be used in
+ // buffering situation, hence it's likely the coderange
+ // will never be scanned, so it's not worth spending time
+ // precomputing the coderange except for simple and common
+ // situations.
+ ENC_CODERANGE_CLEAR(str);
+ keep_cr:
+ return str;
+}
+
+/*
+ * call-seq:
+ * self << object -> self
+ *
+ * Appends a string representation of +object+ to +self+;
+ * returns +self+.
*
- * Concatenates +object+ to +self+ and returns +self+:
+ * If +object+ is a string, appends it to +self+:
*
* s = 'foo'
* s << 'bar' # => "foobar"
* s # => "foobar"
*
- * If +object+ is an Integer,
- * the value is considered a codepoint and converted to a character before concatenation:
+ * If +object+ is an integer,
+ * its value is considered a codepoint;
+ * converts the value to a character before concatenating:
*
* s = 'foo'
* s << 33 # => "foo!"
*
- * Related: String#concat, which takes multiple arguments.
+ * Additionally, if the codepoint is in range <tt>0..0xff</tt>
+ * and the encoding of +self+ is Encoding::US_ASCII,
+ * changes the encoding to Encoding::ASCII_8BIT:
+ *
+ * s = 'foo'.encode(Encoding::US_ASCII)
+ * s.encoding # => #<Encoding:US-ASCII>
+ * s << 0xff # => "foo\xFF"
+ * s.encoding # => #<Encoding:BINARY (ASCII-8BIT)>
+ *
+ * Raises RangeError if that codepoint is not representable in the encoding of +self+:
+ *
+ * s = 'foo'
+ * s.encoding # => <Encoding:UTF-8>
+ * s << 0x00110000 # 1114112 out of char range (RangeError)
+ * s = 'foo'.encode(Encoding::EUC_JP)
+ * s << 0x00800080 # invalid codepoint 0x800080 in EUC-JP (RangeError)
+ *
+ * Related: see {Modifying}[rdoc-ref:String@Modifying].
*/
VALUE
rb_str_concat(VALUE str1, VALUE str2)
@@ -3619,14 +4066,9 @@ rb_str_concat(VALUE str1, VALUE str2)
}
encidx = rb_ascii8bit_appendable_encoding_index(enc, code);
+
if (encidx >= 0) {
- char buf[1];
- buf[0] = (char)code;
- rb_str_cat(str1, buf, 1);
- if (encidx != rb_enc_to_index(enc)) {
- rb_enc_associate_index(str1, encidx);
- ENC_CODERANGE_SET(str1, ENC_CODERANGE_VALID);
- }
+ rb_str_buf_cat_byte(str1, (unsigned char)code);
}
else {
long pos = RSTRING_LEN(str1);
@@ -3683,15 +4125,14 @@ rb_ascii8bit_appendable_encoding_index(rb_encoding *enc, unsigned int code)
/*
* call-seq:
- * prepend(*other_strings) -> string
+ * prepend(*other_strings) -> new_string
*
- * Prepends each string in +other_strings+ to +self+ and returns +self+:
+ * Prefixes to +self+ the concatenation of the given +other_strings+; returns +self+:
*
- * s = 'foo'
- * s.prepend('bar', 'baz') # => "barbazfoo"
- * s # => "barbazfoo"
+ * 'baz'.prepend('foo', 'bar') # => "foobarbaz"
+ *
+ * Related: see {Modifying}[rdoc-ref:String@Modifying].
*
- * Related: String#concat.
*/
static VALUE
@@ -3719,8 +4160,8 @@ st_index_t
rb_str_hash(VALUE str)
{
if (FL_TEST_RAW(str, STR_PRECOMPUTED_HASH)) {
- typedef struct {char bytes[sizeof(st_index_t)];} unaligned_index;
- st_index_t precomputed_hash = ((union {st_index_t i; unaligned_index b;} *)(RSTRING_END(str) + TERM_LEN(str)))->i;
+ st_index_t precomputed_hash;
+ memcpy(&precomputed_hash, RSTRING_END(str) + TERM_LEN(str), sizeof(precomputed_hash));
RUBY_ASSERT(precomputed_hash == str_do_hash(str));
return precomputed_hash;
@@ -3745,10 +4186,8 @@ rb_str_hash_cmp(VALUE str1, VALUE str2)
* call-seq:
* hash -> integer
*
- * Returns the integer hash value for +self+.
- * The value is based on the length, content and encoding of +self+.
+ * :include: doc/string/hash.rdoc
*
- * Related: Object#hash.
*/
static VALUE
@@ -3813,22 +4252,29 @@ rb_str_cmp(VALUE str1, VALUE str2)
/*
* call-seq:
- * string == object -> true or false
- * string === object -> true or false
+ * self == other -> true or false
*
- * Returns +true+ if +object+ has the same length and content;
- * as +self+; +false+ otherwise:
+ * Returns whether +other+ is equal to +self+.
+ *
+ * When +other+ is a string, returns whether +other+ has the same length and content as +self+:
*
* s = 'foo'
- * s == 'foo' # => true
+ * s == 'foo' # => true
* s == 'food' # => false
- * s == 'FOO' # => false
+ * s == 'FOO' # => false
*
* 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 <code>object.==</code>.
+ * "\u{e4 f6 fc}".encode(Encoding::ISO_8859_1) == ("\u{c4 d6 dc}") # => false
+ *
+ * When +other+ is not a string:
+ *
+ * - If +other+ responds to method <tt>to_str</tt>,
+ * <tt>other == self</tt> is called and its return value is returned.
+ * - If +other+ does not respond to <tt>to_str</tt>,
+ * +false+ is returned.
+ *
+ * Related: {Comparing}[rdoc-ref:String@Comparing].
*/
VALUE
@@ -3848,17 +4294,7 @@ rb_str_equal(VALUE str1, VALUE str2)
* call-seq:
* 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
+ * :include: doc/string/eql_p.rdoc
*
*/
@@ -3872,24 +4308,31 @@ rb_str_eql(VALUE str1, VALUE str2)
/*
* call-seq:
- * string <=> other_string -> -1, 0, 1, or nil
+ * self <=> other -> -1, 0, 1, or nil
*
- * Compares +self+ and +other_string+, returning:
+ * Compares +self+ and +other+,
+ * evaluating their _contents_, not their _lengths_.
*
- * - -1 if +other_string+ is larger.
- * - 0 if the two are equal.
- * - 1 if +other_string+ is smaller.
- * - +nil+ if the two are incomparable.
+ * Returns:
+ *
+ * - +-1+, if +self+ is smaller.
+ * - +0+, if the two are equal.
+ * - +1+, if +self+ is larger.
+ * - +nil+, if the two are incomparable.
*
* Examples:
*
- * 'foo' <=> 'foo' # => 0
- * 'foo' <=> 'food' # => -1
- * 'food' <=> 'foo' # => 1
- * 'FOO' <=> 'foo' # => -1
- * 'foo' <=> 'FOO' # => 1
- * 'foo' <=> 1 # => nil
+ * 'a' <=> 'b' # => -1
+ * 'a' <=> 'ab' # => -1
+ * 'a' <=> 'a' # => 0
+ * 'b' <=> 'a' # => 1
+ * 'ab' <=> 'a' # => 1
+ * 'a' <=> :a # => nil
*
+ * \Class \String includes module Comparable,
+ * each of whose methods uses String#<=> for comparison.
+ *
+ * Related: see {Comparing}[rdoc-ref:String@Comparing].
*/
static VALUE
@@ -3911,26 +4354,26 @@ static VALUE str_casecmp_p(VALUE str1, VALUE str2);
* call-seq:
* casecmp(other_string) -> -1, 0, 1, or nil
*
- * Compares <tt>self.downcase</tt> and <tt>other_string.downcase</tt>; returns:
+ * Ignoring case, compares +self+ and +other_string+; returns:
*
- * - -1 if <tt>other_string.downcase</tt> is larger.
+ * - -1 if <tt>self.downcase</tt> is smaller than <tt>other_string.downcase</tt>.
* - 0 if the two are equal.
- * - 1 if <tt>other_string.downcase</tt> is smaller.
+ * - 1 if <tt>self.downcase</tt> is larger than <tt>other_string.downcase</tt>.
* - +nil+ if the two are incomparable.
*
+ * See {Case Mapping}[rdoc-ref:case_mapping.rdoc].
+ *
* Examples:
*
- * 'foo'.casecmp('foo') # => 0
+ * 'foo'.casecmp('goo') # => -1
+ * 'goo'.casecmp('foo') # => 1
* 'foo'.casecmp('food') # => -1
* 'food'.casecmp('foo') # => 1
- * 'FOO'.casecmp('foo') # => 0
- * 'foo'.casecmp('FOO') # => 0
- * 'foo'.casecmp(1) # => nil
- *
- * See {Case Mapping}[rdoc-ref:case_mapping.rdoc].
- *
- * Related: String#casecmp?.
+ * 'FOO'.casecmp('foo') # => 0
+ * 'foo'.casecmp('FOO') # => 0
+ * 'foo'.casecmp(1) # => nil
*
+ * Related: see {Comparing}[rdoc-ref:String@Comparing].
*/
static VALUE
@@ -3995,9 +4438,9 @@ str_casecmp(VALUE str1, VALUE str2)
p2 += l2;
}
}
- if (RSTRING_LEN(str1) == RSTRING_LEN(str2)) return INT2FIX(0);
- if (RSTRING_LEN(str1) > RSTRING_LEN(str2)) return INT2FIX(1);
- return INT2FIX(-1);
+ if (p1 == p1end && p2 == p2end) return INT2FIX(0);
+ if (p1 == p1end) return INT2FIX(-1);
+ return INT2FIX(1);
}
/*
@@ -4005,22 +4448,21 @@ str_casecmp(VALUE str1, VALUE str2)
* 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:
- *
- * 'foo'.casecmp?(1) # => nil
+ * Unicode case folding, +false+ if unequal, +nil+ if incomparable.
*
* See {Case Mapping}[rdoc-ref:case_mapping.rdoc].
*
- * Related: String#casecmp.
+ * Examples:
*
+ * 'foo'.casecmp?('goo') # => false
+ * 'goo'.casecmp?('foo') # => false
+ * 'foo'.casecmp?('food') # => false
+ * 'food'.casecmp?('foo') # => false
+ * 'FOO'.casecmp?('foo') # => true
+ * 'foo'.casecmp?('FOO') # => true
+ * 'foo'.casecmp?(1) # => nil
+ *
+ * Related: see {Comparing}[rdoc-ref:String@Comparing].
*/
static VALUE
@@ -4116,8 +4558,7 @@ rb_strseq_index(VALUE str, VALUE sub, long offset, int in_byte)
/*
* call-seq:
- * index(substring, offset = 0) -> integer or nil
- * index(regexp, offset = 0) -> integer or nil
+ * index(pattern, offset = 0) -> integer or nil
*
* :include: doc/string/index.rdoc
*
@@ -4174,54 +4615,82 @@ rb_str_index_m(int argc, VALUE *argv, VALUE str)
static void
str_ensure_byte_pos(VALUE str, long pos)
{
- const char *s = RSTRING_PTR(str);
- const char *e = RSTRING_END(str);
- const char *p = s + pos;
- if (!at_char_boundary(s, p, e, rb_enc_get(str))) {
- rb_raise(rb_eIndexError,
- "offset %ld does not land on character boundary", pos);
+ if (!single_byte_optimizable(str)) {
+ const char *s = RSTRING_PTR(str);
+ const char *e = RSTRING_END(str);
+ const char *p = s + pos;
+ if (!at_char_boundary(s, p, e, rb_enc_get(str))) {
+ rb_raise(rb_eIndexError,
+ "offset %ld does not land on character boundary", pos);
+ }
}
}
/*
* call-seq:
- * byteindex(substring, offset = 0) -> integer or nil
- * byteindex(regexp, offset = 0) -> integer or nil
+ * byteindex(object, offset = 0) -> integer or nil
*
- * Returns the Integer byte-based index of the first occurrence of the given +substring+,
- * or +nil+ if none found:
+ * Returns the 0-based integer index of a substring of +self+
+ * specified by +object+ (a string or Regexp) and +offset+,
+ * or +nil+ if there is no such substring;
+ * the returned index is the count of _bytes_ (not characters).
*
- * 'foo'.byteindex('f') # => 0
- * 'foo'.byteindex('o') # => 1
- * 'foo'.byteindex('oo') # => 1
- * 'foo'.byteindex('ooo') # => nil
+ * When +object+ is a string,
+ * returns the index of the first found substring equal to +object+:
*
- * Returns the Integer byte-based index of the first match for the given Regexp +regexp+,
- * or +nil+ if none found:
+ * s = 'foo' # => "foo"
+ * s.size # => 3 # Three 1-byte characters.
+ * s.bytesize # => 3 # Three bytes.
+ * s.byteindex('f') # => 0
+ * s.byteindex('o') # => 1
+ * s.byteindex('oo') # => 1
+ * s.byteindex('ooo') # => nil
*
- * 'foo'.byteindex(/f/) # => 0
- * 'foo'.byteindex(/o/) # => 1
- * 'foo'.byteindex(/oo/) # => 1
- * 'foo'.byteindex(/ooo/) # => nil
+ * When +object+ is a Regexp,
+ * returns the index of the first found substring matching +object+;
+ * updates {Regexp-related global variables}[rdoc-ref:Regexp@Global+Variables]:
*
- * Integer argument +offset+, if given, specifies the byte-based position in the
- * string to begin the search:
+ * s = 'foo'
+ * s.byteindex(/f/) # => 0
+ * $~ # => #<MatchData "f">
+ * s.byteindex(/o/) # => 1
+ * s.byteindex(/oo/) # => 1
+ * s.byteindex(/ooo/) # => nil
+ * $~ # => nil
*
- * 'foo'.byteindex('o', 1) # => 1
- * 'foo'.byteindex('o', 2) # => 2
- * 'foo'.byteindex('o', 3) # => nil
+ * \Integer argument +offset+, if given, specifies the 0-based index
+ * of the byte where searching is to begin.
*
- * If +offset+ is negative, counts backward from the end of +self+:
+ * When +offset+ is non-negative,
+ * searching begins at byte position +offset+:
*
- * 'foo'.byteindex('o', -1) # => 2
- * 'foo'.byteindex('o', -2) # => 1
- * 'foo'.byteindex('o', -3) # => 1
- * 'foo'.byteindex('o', -4) # => nil
+ * s = 'foo'
+ * s.byteindex('o', 1) # => 1
+ * s.byteindex('o', 2) # => 2
+ * s.byteindex('o', 3) # => nil
+ *
+ * When +offset+ is negative, counts backward from the end of +self+:
*
- * If +offset+ does not land on character (codepoint) boundary, +IndexError+ is
- * raised.
+ * s = 'foo'
+ * s.byteindex('o', -1) # => 2
+ * s.byteindex('o', -2) # => 1
+ * s.byteindex('o', -3) # => 1
+ * s.byteindex('o', -4) # => nil
*
- * Related: String#index, String#byterindex.
+ * Raises IndexError if the byte at +offset+ is not the first byte of a character:
+ *
+ * s = "\uFFFF\uFFFF" # => "\uFFFF\uFFFF"
+ * s.size # => 2 # Two 3-byte characters.
+ * s.bytesize # => 6 # Six bytes.
+ * s.byteindex("\uFFFF") # => 0
+ * s.byteindex("\uFFFF", 1) # Raises IndexError
+ * s.byteindex("\uFFFF", 2) # Raises IndexError
+ * s.byteindex("\uFFFF", 3) # => 3
+ * s.byteindex("\uFFFF", 4) # Raises IndexError
+ * s.byteindex("\uFFFF", 5) # Raises IndexError
+ * s.byteindex("\uFFFF", 6) # => nil
+ *
+ * Related: see {Querying}[rdoc-ref:String@Querying].
*/
static VALUE
@@ -4263,7 +4732,19 @@ rb_str_byteindex_m(int argc, VALUE *argv, VALUE str)
return Qnil;
}
-#ifdef HAVE_MEMRCHR
+#ifndef HAVE_MEMRCHR
+static void*
+memrchr(const char *search_str, int chr, long search_len)
+{
+ const char *ptr = search_str + search_len;
+ while (ptr > search_str) {
+ if ((unsigned char)*(--ptr) == chr) return (void *)ptr;
+ }
+
+ return ((void *)0);
+}
+#endif
+
static long
str_rindex(VALUE str, VALUE sub, const char *s, rb_encoding *enc)
{
@@ -4280,6 +4761,10 @@ str_rindex(VALUE str, VALUE sub, const char *s, rb_encoding *enc)
c = *t & 0xff;
searchlen = s - sbeg + 1;
+ if (memcmp(s, t, slen) == 0) {
+ return s - sbeg;
+ }
+
do {
hit = memrchr(sbeg, c, searchlen);
if (!hit) break;
@@ -4295,29 +4780,6 @@ str_rindex(VALUE str, VALUE sub, const char *s, rb_encoding *enc)
return -1;
}
-#else
-static long
-str_rindex(VALUE str, VALUE sub, const char *s, rb_encoding *enc)
-{
- long slen;
- char *sbeg, *e, *t;
-
- sbeg = RSTRING_PTR(str);
- e = RSTRING_END(str);
- t = RSTRING_PTR(sub);
- slen = RSTRING_LEN(sub);
-
- while (s) {
- if (memcmp(s, t, slen) == 0) {
- return s - sbeg;
- }
- if (s <= sbeg) break;
- s = rb_enc_prev_char(sbeg, s, e, enc);
- }
-
- return -1;
-}
-#endif
/* found index in byte */
static long
@@ -4354,59 +4816,10 @@ rb_str_rindex(VALUE str, VALUE sub, long pos)
/*
* call-seq:
- * 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.
+ * rindex(pattern, offset = self.length) -> integer or nil
*
- * 'foo'.rindex(/o+/) # => 2
- * $~ #=> #<MatchData "o">
+ * :include:doc/string/rindex.rdoc
*
- * To get the last longest match, needs to combine with negative
- * lookbehind.
- *
- * 'foo'.rindex(/(?<!o)o+/) # => 1
- * $~ #=> #<MatchData "oo">
- *
- * Or String#index with negative lookforward.
- *
- * 'foo'.index(/o+(?!.*o)/) # => 1
- * $~ #=> #<MatchData "oo">
- *
- * 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
@@ -4484,65 +4897,90 @@ rb_str_byterindex(VALUE str, VALUE sub, long pos)
return str_rindex(str, sub, s, enc);
}
-
/*
* call-seq:
- * byterindex(substring, offset = self.bytesize) -> integer or nil
- * byterindex(regexp, offset = self.bytesize) -> integer or nil
+ * byterindex(object, offset = self.bytesize) -> integer or nil
*
- * Returns the Integer byte-based index of the _last_ occurrence of the given +substring+,
- * or +nil+ if none found:
+ * Returns the 0-based integer index of a substring of +self+
+ * that is the _last_ match for the given +object+ (a string or Regexp) and +offset+,
+ * or +nil+ if there is no such substring;
+ * the returned index is the count of _bytes_ (not characters).
*
- * 'foo'.byterindex('f') # => 0
- * 'foo'.byterindex('o') # => 2
- * 'foo'.byterindex('oo') # => 1
- * 'foo'.byterindex('ooo') # => nil
+ * When +object+ is a string,
+ * returns the index of the _last_ found substring equal to +object+:
*
- * Returns the Integer byte-based index of the _last_ match for the given Regexp +regexp+,
- * or +nil+ if none found:
+ * s = 'foo' # => "foo"
+ * s.size # => 3 # Three 1-byte characters.
+ * s.bytesize # => 3 # Three bytes.
+ * s.byterindex('f') # => 0
+ s.byterindex('o') # => 2
+ s.byterindex('oo') # => 1
+ s.byterindex('ooo') # => nil
*
- * 'foo'.byterindex(/f/) # => 0
- * 'foo'.byterindex(/o/) # => 2
- * 'foo'.byterindex(/oo/) # => 1
- * 'foo'.byterindex(/ooo/) # => nil
+ * When +object+ is a Regexp,
+ * returns the index of the last found substring matching +object+;
+ * updates {Regexp-related global variables}[rdoc-ref:Regexp@Global+Variables]:
*
- * The _last_ match means starting at the possible last position, not
- * the last of longest matches.
+ * s = 'foo'
+ * s.byterindex(/f/) # => 0
+ * $~ # => #<MatchData "f">
+ * s.byterindex(/o/) # => 2
+ * s.byterindex(/oo/) # => 1
+ * s.byterindex(/ooo/) # => nil
+ * $~ # => nil
*
- * 'foo'.byterindex(/o+/) # => 2
- * $~ #=> #<MatchData "o">
+ * The last match means starting at the possible last position,
+ * not the last of the longest matches:
*
- * To get the last longest match, needs to combine with negative
- * lookbehind.
+ * s = 'foo'
+ * s.byterindex(/o+/) # => 2
+ * $~ #=> #<MatchData "o">
*
- * 'foo'.byterindex(/(?<!o)o+/) # => 1
- * $~ #=> #<MatchData "oo">
+ * To get the last longest match, use a negative lookbehind:
*
- * Or String#byteindex with negative lookforward.
+ * s = 'foo'
+ * s.byterindex(/(?<!o)o+/) # => 1
+ * $~ # => #<MatchData "oo">
*
- * 'foo'.byteindex(/o+(?!.*o)/) # => 1
- * $~ #=> #<MatchData "oo">
+ * Or use method #byteindex with negative lookahead:
*
- * Integer argument +offset+, if given and non-negative, specifies the maximum starting byte-based position in the
- * string to _end_ the search:
+ * s = 'foo'
+ * s.byteindex(/o+(?!.*o)/) # => 1
+ * $~ #=> #<MatchData "oo">
*
- * 'foo'.byterindex('o', 0) # => nil
- * 'foo'.byterindex('o', 1) # => 1
- * 'foo'.byterindex('o', 2) # => 2
- * 'foo'.byterindex('o', 3) # => 2
+ * \Integer argument +offset+, if given, specifies the 0-based index
+ * of the byte where searching is to end.
*
- * 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+:
+ * When +offset+ is non-negative,
+ * searching ends at byte position +offset+:
*
- * 'foo'.byterindex('o', -1) # => 2
- * 'foo'.byterindex('o', -2) # => 1
- * 'foo'.byterindex('o', -3) # => nil
- * 'foo'.byterindex('o', -4) # => nil
+ * s = 'foo'
+ * s.byterindex('o', 0) # => nil
+ * s.byterindex('o', 1) # => 1
+ * s.byterindex('o', 2) # => 2
+ * s.byterindex('o', 3) # => 2
*
- * If +offset+ does not land on character (codepoint) boundary, +IndexError+ is
- * raised.
+ * When +offset+ is negative, counts backward from the end of +self+:
*
- * Related: String#byteindex.
+ * s = 'foo'
+ * s.byterindex('o', -1) # => 2
+ * s.byterindex('o', -2) # => 1
+ * s.byterindex('o', -3) # => nil
+ *
+ * Raises IndexError if the byte at +offset+ is not the first byte of a character:
+ *
+ * s = "\uFFFF\uFFFF" # => "\uFFFF\uFFFF"
+ * s.size # => 2 # Two 3-byte characters.
+ * s.bytesize # => 6 # Six bytes.
+ * s.byterindex("\uFFFF") # => 3
+ * s.byterindex("\uFFFF", 1) # Raises IndexError
+ * s.byterindex("\uFFFF", 2) # Raises IndexError
+ * s.byterindex("\uFFFF", 3) # => 3
+ * s.byterindex("\uFFFF", 4) # Raises IndexError
+ * s.byterindex("\uFFFF", 5) # Raises IndexError
+ * s.byterindex("\uFFFF", 6) # => nil
+ *
+ * Related: see {Querying}[rdoc-ref:String@Querying].
*/
static VALUE
@@ -4586,30 +5024,36 @@ rb_str_byterindex_m(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * string =~ regexp -> integer or nil
- * string =~ object -> integer or nil
+ * self =~ other -> integer or nil
*
- * Returns the Integer index of the first substring that matches
- * the given +regexp+, or +nil+ if no match found:
+ * When +other+ is a Regexp:
+ *
+ * - Returns the integer index (in characters) of the first match
+ * for +self+ and +other+, or +nil+ if none;
+ * - Updates {Regexp-related global variables}[rdoc-ref:Regexp@Global+Variables].
+ *
+ * Examples:
*
* 'foo' =~ /f/ # => 0
+ * $~ # => #<MatchData "f">
* 'foo' =~ /o/ # => 1
+ * $~ # => #<MatchData "o">
* 'foo' =~ /x/ # => nil
- *
- * Note: also updates Regexp@Global+Variables.
- *
- * If the given +object+ is not a Regexp, returns the value
- * returned by <tt>object =~ self</tt>.
+ * $~ # => nil
*
* Note that <tt>string =~ regexp</tt> is different from <tt>regexp =~ string</tt>
* (see Regexp#=~):
*
- * number= nil
- * "no. 9" =~ /(?<number>\d+)/
- * number # => nil (not assigned)
- * /(?<number>\d+)/ =~ "no. 9"
- * number #=> "9"
+ * number = nil
+ * 'no. 9' =~ /(?<number>\d+)/ # => 4
+ * number # => nil # Not assigned.
+ * /(?<number>\d+)/ =~ 'no. 9' # => 4
+ * number # => "9" # Assigned.
+ *
+ * When +other+ is not a Regexp, returns the value
+ * returned by <tt>other =~ self</tt>.
*
+ * Related: see {Querying}[rdoc-ref:String@Querying].
*/
static VALUE
@@ -4636,34 +5080,36 @@ static VALUE get_pat(VALUE);
* match(pattern, offset = 0) -> matchdata or nil
* match(pattern, offset = 0) {|matchdata| ... } -> object
*
- * Returns a MatchData object (or +nil+) based on +self+ and the given +pattern+.
- *
- * Note: also updates Regexp@Global+Variables.
+ * Creates a MatchData object based on +self+ and the given arguments;
+ * updates {Regexp Global Variables}[rdoc-ref:Regexp@Global+Variables].
*
* - 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 = <tt>regexp.match(self)
*
- * With no block given, returns the computed +matchdata+:
+ * matchdata = regexp.match(self[offset..])
*
- * 'foo'.match('f') # => #<MatchData "f">
- * 'foo'.match('o') # => #<MatchData "o">
- * 'foo'.match('x') # => nil
- *
- * If Integer argument +offset+ is given, the search begins at index +offset+:
+ * With no block given, returns the computed +matchdata+ or +nil+:
*
+ * 'foo'.match('f') # => #<MatchData "f">
+ * 'foo'.match('o') # => #<MatchData "o">
+ * 'foo'.match('x') # => nil
* 'foo'.match('f', 1) # => nil
* 'foo'.match('o', 1) # => #<MatchData "o">
*
- * With a block given, calls the block with the computed +matchdata+
- * and returns the block's return value:
+ * With a block given and computed +matchdata+ non-nil, calls the block with +matchdata+;
+ * returns the block's return value:
*
* 'foo'.match(/o/) {|matchdata| matchdata } # => #<MatchData "o">
- * 'foo'.match(/x/) {|matchdata| matchdata } # => nil
- * 'foo'.match(/f/, 1) {|matchdata| matchdata } # => nil
*
+ * With a block given and +nil+ +matchdata+, does not call the block:
+ *
+ * 'foo'.match(/x/) {|matchdata| fail 'Cannot happen' } # => nil
+ *
+ * Related: see {Querying}[rdoc-ref:String@Querying].
*/
static VALUE
@@ -4685,24 +5131,23 @@ rb_str_match_m(int argc, VALUE *argv, VALUE str)
* call-seq:
* match?(pattern, offset = 0) -> true or false
*
- * Returns +true+ or +false+ based on whether a match is found for +self+ and +pattern+.
+ * Returns whether a match is found for +self+ and the given arguments;
+ * does not update {Regexp Global Variables}[rdoc-ref:Regexp@Global+Variables].
*
- * Note: does not update Regexp@Global+Variables.
+ * Computes +regexp+ by converting +pattern+ (if not already a Regexp):
*
- * Computes +regexp+ by converting +pattern+ (if not already a Regexp).
* regexp = Regexp.new(pattern)
*
- * Returns +true+ if <tt>self+.match(regexp)</tt> returns a MatchData object,
+ * Returns +true+ if <tt>self[offset..].match(regexp)</tt> 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
*
+ * Related: see {Querying}[rdoc-ref:String@Querying].
*/
static VALUE
@@ -4903,57 +5348,7 @@ static VALUE str_succ(VALUE str);
* call-seq:
* 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"
- * '<<koala>>'.succ # => "<<koalb>>"
- * '***'.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"
- *
- * 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:
- *
- * '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:
- *
- * 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 # => ""
+ * :include: doc/string/succ.rdoc
*
*/
@@ -5058,7 +5453,9 @@ str_succ(VALUE str)
* call-seq:
* succ! -> self
*
- * Equivalent to String#succ, but modifies +self+ in place; returns +self+.
+ * Like String#succ, but modifies +self+ in place; returns +self+.
+ *
+ * Related: see {Modifying}[rdoc-ref:String@Modifying].
*/
static VALUE
@@ -5091,33 +5488,7 @@ str_upto_i(VALUE str, VALUE arg)
* upto(other_string, exclusive = false) {|string| ... } -> self
* upto(other_string, exclusive = false) -> new_enumerator
*
- * 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 <tt>self.succ</tt>, and so on;
- * the sequence terminates when value +other_string+ is reached;
- * returns +self+:
- *
- * 'a8'.upto('b6') {|s| print s, ' ' } # => "a8"
- * Output:
- *
- * a8 a9 b0 b1 b2 b3 b4 b5 b6
- *
- * 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 }
- *
- * With no block given, returns a new Enumerator:
- *
- * 'a8'.upto('b6') # => #<Enumerator: "a8":upto("b6")>
+ * :include: doc/string/upto.rdoc
*
*/
@@ -5358,15 +5729,13 @@ rb_str_aref(VALUE str, VALUE indx)
/*
* call-seq:
- * 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.
- * See examples at {String Slices}[rdoc-ref:String@String+Slices].
+ * self[offset] -> new_string or nil
+ * self[offset, size] -> new_string or nil
+ * self[range] -> new_string or nil
+ * self[regexp, capture = 0] -> new_string or nil
+ * self[substring] -> new_string or nil
*
+ * :include: doc/string/aref.rdoc
*
*/
@@ -5378,9 +5747,7 @@ rb_str_aref_m(int argc, VALUE *argv, VALUE str)
return rb_str_subpat(str, argv[0], argv[1]);
}
else {
- long beg = NUM2LONG(argv[0]);
- long len = NUM2LONG(argv[1]);
- return rb_str_substr(str, beg, len);
+ return rb_str_substr_two_fixnums(str, argv[0], argv[1], TRUE);
}
}
rb_check_arity(argc, 1, 2);
@@ -5583,28 +5950,13 @@ rb_str_aset(VALUE str, VALUE indx, VALUE val)
/*
* call-seq:
- * string[index] = new_string
- * string[start, length] = new_string
- * string[range] = new_string
- * string[regexp, capture = 0] = new_string
- * string[substring] = new_string
- *
- * Replaces all, some, or none of the contents of +self+; returns +new_string+.
- * See {String Slices}[rdoc-ref:String@String+Slices].
+ * self[index] = other_string -> new_string
+ * self[start, length] = other_string -> new_string
+ * self[range] = other_string -> new_string
+ * self[regexp, capture = 0] = other_string -> new_string
+ * self[substring] = other_string -> new_string
*
- * A few examples:
- *
- * s = 'foo'
- * s[2] = 'rtune' # => "rtune"
- * s # => "fortune"
- * s[1, 5] = 'init' # => "init"
- * s # => "finite"
- * s[3..4] = 'al' # => "al"
- * s # => "finale"
- * s[/e$/] = 'ly' # => "ly"
- * s # => "finally"
- * s['lly'] = 'ncial' # => "ncial"
- * s # => "financial"
+ * :include: doc/string/aset.rdoc
*
*/
@@ -5626,19 +5978,9 @@ rb_str_aset_m(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * insert(index, other_string) -> self
+ * insert(offset, other_string) -> self
*
- * 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 <tt>index+1</tt>
- * (that is, _after_ <tt>self[index]</tt>):
- *
- * 'foo'.insert(-2, 'bar') # => "fobaro"
+ * :include: doc/string/insert.rdoc
*
*/
@@ -5666,18 +6008,20 @@ rb_str_insert(VALUE str, VALUE idx, VALUE str2)
* slice!(regexp, capture = 0) -> new_string or nil
* slice!(substring) -> new_string or nil
*
- * Removes and returns the substring of +self+ specified by the arguments.
- * See {String Slices}[rdoc-ref:String@String+Slices].
+ * Like String#[] (and its alias String#slice), except that:
+ *
+ * - Performs substitutions in +self+ (not in a copy of +self+).
+ * - Returns the removed substring if any modifications were made, +nil+ otherwise.
*
* 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"
+ * s = 'hello'
+ * s.slice!('e') # => "e"
+ * s # => "hllo"
+ * s.slice!('e') # => nil
+ * s # => "hllo"
*
+ * Related: see {Modifying}[rdoc-ref:String@Modifying].
*/
static VALUE
@@ -5816,14 +6160,17 @@ get_pat_quoted(VALUE pat, int check)
}
static long
-rb_pat_search(VALUE pat, VALUE str, long pos, int set_backref_str)
+rb_pat_search0(VALUE pat, VALUE str, long pos, int set_backref_str, VALUE *match)
{
if (BUILTIN_TYPE(pat) == T_STRING) {
pos = rb_str_byteindex(str, pat, pos);
if (set_backref_str) {
if (pos >= 0) {
str = rb_str_new_frozen_String(str);
- rb_backref_set_string(str, pos, RSTRING_LEN(pat));
+ VALUE match_data = rb_backref_set_string(str, pos, RSTRING_LEN(pat));
+ if (match) {
+ *match = match_data;
+ }
}
else {
rb_backref_set(Qnil);
@@ -5832,23 +6179,28 @@ rb_pat_search(VALUE pat, VALUE str, long pos, int set_backref_str)
return pos;
}
else {
- return rb_reg_search0(pat, str, pos, 0, set_backref_str);
+ return rb_reg_search0(pat, str, pos, 0, set_backref_str, match);
}
}
+static long
+rb_pat_search(VALUE pat, VALUE str, long pos, int set_backref_str)
+{
+ return rb_pat_search0(pat, str, pos, set_backref_str, NULL);
+}
+
/*
* call-seq:
* 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}[rdoc-ref:String@Substitution+Methods].
+ * Like String#sub, except that:
*
- * Related: String#sub, String#gsub, String#gsub!.
+ * - Changes are made to +self+, not to copy of +self+.
+ * - Returns +self+ if any changes are made, +nil+ otherwise.
*
+ * Related: see {Modifying}[rdoc-ref:String@Modifying].
*/
static VALUE
@@ -5967,13 +6319,7 @@ rb_str_sub_bang(int argc, VALUE *argv, VALUE str)
* 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}[rdoc-ref:String@Substitution+Methods].
- *
- * Related: String#sub!, String#gsub, String#gsub!.
- *
+ * :include: doc/string/sub.rdoc
*/
static VALUE
@@ -5987,12 +6333,12 @@ rb_str_sub(int argc, VALUE *argv, VALUE str)
static VALUE
str_gsub(int argc, VALUE *argv, VALUE str, int bang)
{
- VALUE pat, val = Qnil, repl, match0 = Qnil, dest, hash = Qnil;
+ VALUE pat, val = Qnil, repl, match0 = Qnil, dest, hash = Qnil, match = Qnil;
long beg, beg0, end0;
long offset, blen, slen, len, last;
- enum {STR, ITER, MAP} mode = STR;
+ enum {STR, ITER, FAST_MAP, MAP} mode = STR;
char *sp, *cp;
- int need_backref = -1;
+ int need_backref_str = -1;
rb_encoding *str_enc;
switch (argc) {
@@ -6006,6 +6352,9 @@ str_gsub(int argc, VALUE *argv, VALUE str, int bang)
if (NIL_P(hash)) {
StringValue(repl);
}
+ else if (rb_hash_default_unredefined(hash) && !FL_TEST_RAW(hash, RHASH_PROC_DEFAULT)) {
+ mode = FAST_MAP;
+ }
else {
mode = MAP;
}
@@ -6015,7 +6364,8 @@ str_gsub(int argc, VALUE *argv, VALUE str, int bang)
}
pat = get_pat_quoted(argv[0], 1);
- beg = rb_pat_search(pat, str, 0, need_backref);
+ beg = rb_pat_search0(pat, str, 0, need_backref_str, &match);
+
if (beg < 0) {
if (bang) return Qnil; /* no match, no substitution */
return str_duplicate(rb_cString, str);
@@ -6032,7 +6382,6 @@ str_gsub(int argc, VALUE *argv, VALUE str, int bang)
ENC_CODERANGE_SET(dest, rb_enc_asciicompat(str_enc) ? ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID);
do {
- VALUE match = rb_backref_get();
struct re_registers *regs = RMATCH_REGS(match);
if (RB_TYPE_P(pat, T_STRING)) {
beg0 = beg;
@@ -6045,12 +6394,23 @@ str_gsub(int argc, VALUE *argv, VALUE str, int bang)
if (mode == ITER) match0 = rb_reg_nth_match(0, match);
}
- if (mode) {
+ if (mode != STR) {
if (mode == ITER) {
val = rb_obj_as_string(rb_yield(match0));
}
else {
- val = rb_hash_aref(hash, rb_str_subseq(str, beg0, end0 - beg0));
+ struct RString fake_str = {RBASIC_INIT};
+ VALUE key;
+ if (mode == FAST_MAP) {
+ // It is safe to use a fake_str here because we established that it won't escape,
+ // as it's only used for `rb_hash_aref` and we checked the hash doesn't have a
+ // default proc.
+ key = setup_fake_str(&fake_str, sp + beg0, end0 - beg0, ENCODING_GET_INLINED(str));
+ }
+ else {
+ key = rb_str_subseq(str, beg0, end0 - beg0);
+ }
+ val = rb_hash_aref(hash, key);
val = rb_obj_as_string(val);
}
str_mod_check(str, sp, slen);
@@ -6058,10 +6418,10 @@ str_gsub(int argc, VALUE *argv, VALUE str, int bang)
rb_raise(rb_eRuntimeError, "block should not cheat");
}
}
- else if (need_backref) {
+ else if (need_backref_str) {
val = rb_reg_regsub(repl, str, regs, RB_TYPE_P(pat, T_STRING) ? Qnil : pat);
- if (need_backref < 0) {
- need_backref = val != repl;
+ if (need_backref_str < 0) {
+ need_backref_str = val != repl;
}
}
else {
@@ -6089,14 +6449,20 @@ str_gsub(int argc, VALUE *argv, VALUE str, int bang)
}
cp = RSTRING_PTR(str) + offset;
if (offset > RSTRING_LEN(str)) break;
- beg = rb_pat_search(pat, str, offset, need_backref);
+
+ // In FAST_MAP and STR mode the backref can't escape so we can re-use the MatchData safely.
+ if (mode != FAST_MAP && mode != STR) {
+ match = Qnil;
+ }
+ beg = rb_pat_search0(pat, str, offset, need_backref_str, &match);
RB_GC_GUARD(match);
} while (beg >= 0);
+
if (RSTRING_LEN(str) > offset) {
rb_enc_str_buf_cat(dest, cp, RSTRING_LEN(str) - offset, str_enc);
}
- rb_pat_search(pat, str, last, 1);
+ rb_pat_search0(pat, str, last, 1, &match);
if (bang) {
str_shared_replace(str, dest);
}
@@ -6114,15 +6480,12 @@ str_gsub(int argc, VALUE *argv, VALUE str, int bang)
* 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}[rdoc-ref:String@Substitution+Methods].
- *
- * Returns an Enumerator if no +replacement+ and no block given.
+ * Like String#gsub, except that:
*
- * Related: String#sub, String#gsub, String#sub!.
+ * - Performs substitutions in +self+ (not in a copy of +self+).
+ * - Returns +self+ if any characters are removed, +nil+ otherwise.
*
+ * Related: see {Modifying}[rdoc-ref:String@Modifying].
*/
static VALUE
@@ -6139,14 +6502,41 @@ rb_str_gsub_bang(int argc, VALUE *argv, VALUE str)
* gsub(pattern) {|match| ... } -> new_string
* gsub(pattern) -> enumerator
*
- * Returns a copy of +self+ with all occurrences of the given +pattern+ replaced.
+ * Returns a copy of +self+ with zero or more substrings replaced.
*
- * See {Substitution Methods}[rdoc-ref:String@Substitution+Methods].
+ * Argument +pattern+ may be a string or a Regexp;
+ * argument +replacement+ may be a string or a Hash.
+ * Varying types for the argument values makes this method very versatile.
*
- * Returns an Enumerator if no +replacement+ and no block given.
+ * Below are some simple examples;
+ * for many more examples, see {Substitution Methods}[rdoc-ref:String@Substitution+Methods].
*
- * Related: String#sub, String#sub!, String#gsub!.
+ * With arguments +pattern+ and string +replacement+ given,
+ * replaces each matching substring with the given +replacement+ string:
*
+ * s = 'abracadabra'
+ * s.gsub('ab', 'AB') # => "ABracadABra"
+ * s.gsub(/[a-c]/, 'X') # => "XXrXXXdXXrX"
+ *
+ * With arguments +pattern+ and hash +replacement+ given,
+ * replaces each matching substring with a value from the given +replacement+ hash,
+ * or removes it:
+ *
+ * h = {'a' => 'A', 'b' => 'B', 'c' => 'C'}
+ * s.gsub(/[a-c]/, h) # => "ABrACAdABrA" # 'a', 'b', 'c' replaced.
+ * s.gsub(/[a-d]/, h) # => "ABrACAABrA" # 'd' removed.
+ *
+ * With argument +pattern+ and a block given,
+ * calls the block with each matching substring;
+ * replaces that substring with the block's return value:
+ *
+ * s.gsub(/[a-d]/) {|substring| substring.upcase }
+ * # => "ABrACADABrA"
+ *
+ * With argument +pattern+ and no block given,
+ * returns a new Enumerator.
+ *
+ * Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
*/
static VALUE
@@ -6160,11 +6550,13 @@ rb_str_gsub(int argc, VALUE *argv, VALUE str)
* call-seq:
* replace(other_string) -> self
*
- * Replaces the contents of +self+ with the contents of +other_string+:
+ * Replaces the contents of +self+ with the contents of +other_string+;
+ * returns +self+:
*
* s = 'foo' # => "foo"
* s.replace('bar') # => "bar"
*
+ * Related: see {Modifying}[rdoc-ref:String@Modifying].
*/
VALUE
@@ -6184,9 +6576,11 @@ rb_str_replace(VALUE str, VALUE str2)
*
* Removes the contents of +self+:
*
- * s = 'foo' # => "foo"
- * s.clear # => ""
+ * s = 'foo'
+ * s.clear # => ""
+ * s # => ""
*
+ * Related: see {Modifying}[rdoc-ref:String@Modifying].
*/
static VALUE
@@ -6207,10 +6601,7 @@ rb_str_clear(VALUE str)
* call-seq:
* chr -> string
*
- * Returns a string containing the first character of +self+:
- *
- * s = 'foo' # => "foo"
- * s.chr # => "f"
+ * :include: doc/string/chr.rdoc
*
*/
@@ -6224,14 +6615,8 @@ rb_str_chr(VALUE str)
* call-seq:
* getbyte(index) -> integer or nil
*
- * Returns the byte at zero-based +index+ as an integer, or +nil+ if +index+ is out of range:
+ * :include: doc/string/getbyte.rdoc
*
- * s = 'abcde' # => "abcde"
- * s.getbyte(0) # => 97
- * s.getbyte(-1) # => 101
- * s.getbyte(5) # => nil
- *
- * Related: String#setbyte.
*/
VALUE
rb_str_getbyte(VALUE str, VALUE index)
@@ -6250,13 +6635,14 @@ rb_str_getbyte(VALUE str, VALUE index)
* call-seq:
* setbyte(index, integer) -> integer
*
- * Sets the byte at zero-based +index+ to +integer+; returns +integer+:
+ * Sets the byte at zero-based offset +index+ to the value of the given +integer+;
+ * returns +integer+:
*
- * s = 'abcde' # => "abcde"
- * s.setbyte(0, 98) # => 98
- * s # => "bbcde"
+ * s = 'xyzzy'
+ * s.setbyte(2, 129) # => 129
+ * s # => "xy\x81zy"
*
- * Related: String#getbyte.
+ * Related: see {Modifying}[rdoc-ref:String@Modifying].
*/
VALUE
rb_str_setbyte(VALUE str, VALUE index, VALUE value)
@@ -6387,45 +6773,10 @@ str_byte_aref(VALUE str, VALUE indx)
/*
* call-seq:
- * 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.
- *
- * 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
- * <tt>byteslice(range.begin, range.size)</tt>:
- *
- * 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 # => #<Encoding:UTF-8>
- * s.byteslice(4).encoding # => #<Encoding:UTF-8>
+ * byteslice(offset, length = 1) -> string or nil
+ * byteslice(range) -> string or nil
*
+ * :include: doc/string/byteslice.rdoc
*/
static VALUE
@@ -6465,23 +6816,12 @@ str_check_beg_len(VALUE str, long *beg, long *len)
/*
* call-seq:
- * bytesplice(index, length, str) -> string
- * bytesplice(index, length, str, str_index, str_length) -> string
- * bytesplice(range, str) -> string
- * bytesplice(range, str, str_range) -> string
- *
- * Replaces some or all of the content of +self+ with +str+, and returns +self+.
- * The portion of the string affected is determined using
- * the same criteria as String#byteslice, except that +length+ cannot be omitted.
- * If the replacement string is not the same length as the text it is replacing,
- * the string will be adjusted accordingly.
+ * bytesplice(offset, length, str) -> self
+ * bytesplice(offset, length, str, str_offset, str_length) -> self
+ * bytesplice(range, str) -> self
+ * bytesplice(range, str, str_range) -> self
*
- * If +str_index+ and +str_length+, or +str_range+ are given, the content of +self+ is replaced by str.byteslice(str_index, str_length) or str.byteslice(str_range); however the substring of +str+ is not allocated as a new string.
- *
- * The form that take an Integer will raise an IndexError if the value is out
- * of range; the Range form will raise a RangeError.
- * If the beginning or ending offset does not land on character (codepoint)
- * boundary, an IndexError will be raised.
+ * :include: doc/string/bytesplice.rdoc
*/
static VALUE
@@ -6489,7 +6829,6 @@ rb_str_bytesplice(int argc, VALUE *argv, VALUE str)
{
long beg, len, vbeg, vlen;
VALUE val;
- rb_encoding *enc;
int cr;
rb_check_arity(argc, 2, 5);
@@ -6534,10 +6873,13 @@ rb_str_bytesplice(int argc, VALUE *argv, VALUE str)
}
str_check_beg_len(str, &beg, &len);
str_check_beg_len(val, &vbeg, &vlen);
- enc = rb_enc_check(str, val);
str_modify_keep_cr(str);
+
+ if (RB_UNLIKELY(ENCODING_GET_INLINED(str) != ENCODING_GET_INLINED(val))) {
+ rb_enc_associate(str, rb_enc_check(str, val));
+ }
+
rb_str_update_1(str, beg, len, val, vbeg, vlen);
- rb_enc_associate(str, enc);
cr = ENC_CODERANGE_AND(ENC_CODERANGE(str), ENC_CODERANGE(val));
if (cr != ENC_CODERANGE_BROKEN)
ENC_CODERANGE_SET(str, cr);
@@ -6546,12 +6888,16 @@ rb_str_bytesplice(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * reverse -> string
+ * reverse -> new_string
*
* Returns a new string with the characters from +self+ in reverse order.
*
- * 'stressed'.reverse # => "desserts"
+ * 'drawer'.reverse # => "reward"
+ * 'reviled'.reverse # => "deliver"
+ * 'stressed'.reverse # => "desserts"
+ * 'semordnilaps'.reverse # => "spalindromes"
*
+ * Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
*/
static VALUE
@@ -6611,10 +6957,12 @@ rb_str_reverse(VALUE str)
*
* Returns +self+ with its characters reversed:
*
- * s = 'stressed'
- * s.reverse! # => "desserts"
- * s # => "desserts"
+ * 'drawer'.reverse! # => "reward"
+ * 'reviled'.reverse! # => "deliver"
+ * 'stressed'.reverse! # => "desserts"
+ * 'semordnilaps'.reverse! # => "spalindromes"
*
+ * Related: see {Modifying}[rdoc-ref:String@Modifying].
*/
static VALUE
@@ -6648,13 +6996,17 @@ rb_str_reverse_bang(VALUE str)
* call-seq:
* include?(other_string) -> true or false
*
- * Returns +true+ if +self+ contains +other_string+, +false+ otherwise:
+ * Returns whether +self+ contains +other_string+:
*
- * s = 'foo'
- * s.include?('f') # => true
- * s.include?('fo') # => true
- * s.include?('food') # => false
+ * s = 'bar'
+ * s.include?('ba') # => true
+ * s.include?('ar') # => true
+ * s.include?('bar') # => true
+ * s.include?('a') # => true
+ * s.include?('') # => true
+ * s.include?('foo') # => false
*
+ * Related: see {Querying}[rdoc-ref:String@Querying].
*/
VALUE
@@ -6674,12 +7026,13 @@ rb_str_include(VALUE str, VALUE arg)
* 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 (0, 2..36)):
+ * as an integer in the given +base+;
+ * +base+ must be either +0+ or in range <tt>(2..36)</tt>:
*
* '123456'.to_i # => 123456
* '123def'.to_i(16) # => 1195503
*
- * With +base+ zero, string +object+ may contain leading characters
+ * With +base+ zero given, string +object+ may contain leading characters
* to specify the actual base:
*
* '123def'.to_i(0) # => 123
@@ -6699,6 +7052,7 @@ rb_str_include(VALUE str, VALUE arg)
* 'abcdef'.to_i # => 0
* '2'.to_i(2) # => 0
*
+ * Related: see {Converting to Non-String}[rdoc-ref:String@Converting+to+Non--5CString].
*/
static VALUE
@@ -6722,7 +7076,7 @@ rb_str_to_i(int argc, VALUE *argv, VALUE str)
* '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:
+ * Characters past a leading valid number are ignored:
*
* '3.14 (pi to two places)'.to_f # => 3.14
*
@@ -6730,6 +7084,7 @@ rb_str_to_i(int argc, VALUE *argv, VALUE str)
*
* 'abcdef'.to_f # => 0.0
*
+ * See {Converting to Non-String}[rdoc-ref:String@Converting+to+Non--5CString].
*/
static VALUE
@@ -6741,10 +7096,12 @@ rb_str_to_f(VALUE str)
/*
* call-seq:
- * to_s -> self or string
+ * to_s -> self or new_string
*
* Returns +self+ if +self+ is a +String+,
* or +self+ converted to a +String+ if +self+ is a subclass of +String+.
+ *
+ * Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
*/
static VALUE
@@ -6877,12 +7234,7 @@ rb_str_escape(VALUE str)
* call-seq:
* inspect -> string
*
- * Returns a printable version of +self+, enclosed in double-quotes,
- * and with special characters escaped:
- *
- * s = "foo\tbar\tbaz\n"
- * s.inspect
- * # => "\"foo\\tbar\\tbaz\\n\""
+ * :include: doc/string/inspect.rdoc
*
*/
@@ -6987,16 +7339,9 @@ rb_str_inspect(VALUE str)
/*
* call-seq:
- * dump -> string
+ * dump -> new_string
*
- * Returns a printable version of +self+, enclosed in double-quotes,
- * with special characters escaped, and with non-printing characters
- * replaced by hexadecimal notation:
- *
- * "hello \n ''".dump # => "\"hello \\n ''\""
- * "\f\x00\xff\\\"".dump # => "\"\\f\\x00\\xFF\\\\\\\"\""
- *
- * Related: String#undump (inverse of String#dump).
+ * :include: doc/string/dump.rdoc
*
*/
@@ -7256,10 +7601,6 @@ undump_after_backslash(VALUE undumped, const char **ss, const char *s_end, rb_en
}
break;
case 'x':
- if (*utf8) {
- rb_raise(rb_eRuntimeError, "hex escape and Unicode escape are mixed");
- }
- *binary = true;
if (++s >= s_end) {
rb_raise(rb_eRuntimeError, "invalid hex escape");
}
@@ -7267,6 +7608,12 @@ undump_after_backslash(VALUE undumped, const char **ss, const char *s_end, rb_en
if (hexlen != 2) {
rb_raise(rb_eRuntimeError, "invalid hex escape");
}
+ if (!ISASCII(*buf)) {
+ if (*utf8) {
+ rb_raise(rb_eRuntimeError, "hex escape and Unicode escape are mixed");
+ }
+ *binary = true;
+ }
rb_str_cat(undumped, (char *)buf, 1);
s += hexlen;
break;
@@ -7282,17 +7629,11 @@ static VALUE rb_str_is_ascii_only_p(VALUE str);
/*
* call-seq:
- * undump -> string
- *
- * Returns an unescaped version of +self+:
+ * undump -> new_string
*
- * 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).
+ * Inverse of String#dump; returns a copy of +self+ with changes of the kinds made by String#dump "undone."
*
+ * Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
*/
static VALUE
@@ -7617,21 +7958,14 @@ upcase_single(VALUE str)
/*
* call-seq:
- * upcase!(*options) -> self or nil
- *
- * 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
+ * upcase!(mapping) -> self or nil
*
- * The casing may be affected by the given +options+;
- * see {Case Mapping}[rdoc-ref:case_mapping.rdoc].
+ * Like String#upcase, except that:
*
- * Related: String#upcase, String#downcase, String#downcase!.
+ * - Changes character casings in +self+ (not in a copy of +self+).
+ * - Returns +self+ if any changes are made, +nil+ otherwise.
*
+ * Related: See {Modifying}[rdoc-ref:String@Modifying].
*/
static VALUE
@@ -7659,18 +7993,9 @@ rb_str_upcase_bang(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * upcase(*options) -> string
- *
- * Returns a string containing the upcased characters in +self+:
- *
- * s = 'Hello World!' # => "Hello World!"
- * s.upcase # => "HELLO WORLD!"
- *
- * The casing may be affected by the given +options+;
- * see {Case Mapping}[rdoc-ref:case_mapping.rdoc].
- *
- * Related: String#upcase!, String#downcase, String#downcase!.
+ * upcase(mapping = :ascii) -> new_string
*
+ * :include: doc/string/upcase.rdoc
*/
static VALUE
@@ -7719,21 +8044,14 @@ downcase_single(VALUE str)
/*
* call-seq:
- * downcase!(*options) -> self or nil
- *
- * 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
+ * downcase!(mapping) -> self or nil
*
- * The casing may be affected by the given +options+;
- * see {Case Mapping}[rdoc-ref:case_mapping.rdoc].
+ * Like String#downcase, except that:
*
- * Related: String#downcase, String#upcase, String#upcase!.
+ * - Changes character casings in +self+ (not in a copy of +self+).
+ * - Returns +self+ if any changes are made, +nil+ otherwise.
*
+ * Related: See {Modifying}[rdoc-ref:String@Modifying].
*/
static VALUE
@@ -7761,17 +8079,9 @@ rb_str_downcase_bang(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * downcase(*options) -> string
+ * downcase(mapping = :ascii) -> new_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}[rdoc-ref:case_mapping.rdoc].
- *
- * Related: String#downcase!, String#upcase, String#upcase!.
+ * :include: doc/string/downcase.rdoc
*
*/
@@ -7803,22 +8113,14 @@ rb_str_downcase(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * capitalize!(*options) -> self or nil
- *
- * Upcases the first character in +self+;
- * downcases the remaining characters;
- * returns +self+ if any changes were made, +nil+ otherwise:
+ * capitalize!(mapping = :ascii) -> self or nil
*
- * s = 'hello World!' # => "hello World!"
- * s.capitalize! # => "Hello world!"
- * s # => "Hello world!"
- * s.capitalize! # => nil
+ * Like String#capitalize, except that:
*
- * The casing may be affected by the given +options+;
- * see {Case Mapping}[rdoc-ref:case_mapping.rdoc].
- *
- * Related: String#capitalize.
+ * - Changes character casings in +self+ (not in a copy of +self+).
+ * - Returns +self+ if any changes are made, +nil+ otherwise.
*
+ * Related: See {Modifying}[rdoc-ref:String@Modifying].
*/
static VALUE
@@ -7843,19 +8145,9 @@ rb_str_capitalize_bang(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * capitalize(*options) -> string
- *
- * Returns a string containing the characters in +self+;
- * the first character is upcased;
- * the remaining characters are downcased:
- *
- * s = 'hello World!' # => "hello World!"
- * s.capitalize # => "Hello world!"
+ * capitalize(mapping = :ascii) -> new_string
*
- * The casing may be affected by the given +options+;
- * see {Case Mapping}[rdoc-ref:case_mapping.rdoc].
- *
- * Related: String#capitalize!.
+ * :include: doc/string/capitalize.rdoc
*
*/
@@ -7882,22 +8174,14 @@ rb_str_capitalize(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * swapcase!(*options) -> self or nil
- *
- * Upcases each lowercase character in +self+;
- * downcases uppercase character;
- * returns +self+ if any changes were made, +nil+ otherwise:
+ * swapcase!(mapping) -> self or nil
*
- * s = 'Hello World!' # => "Hello World!"
- * s.swapcase! # => "hELLO wORLD!"
- * s # => "hELLO wORLD!"
- * ''.swapcase! # => nil
+ * Like String#swapcase, except that:
*
- * The casing may be affected by the given +options+;
- * see {Case Mapping}[rdoc-ref:case_mapping.rdoc].
- *
- * Related: String#swapcase.
+ * - Changes are made to +self+, not to copy of +self+.
+ * - Returns +self+ if any changes are made, +nil+ otherwise.
*
+ * Related: see {Modifying}[rdoc-ref:String@Modifying].
*/
static VALUE
@@ -7921,19 +8205,9 @@ rb_str_swapcase_bang(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * swapcase(*options) -> string
- *
- * Returns a string containing the characters in +self+, with cases reversed;
- * each uppercase character is downcased;
- * each lowercase character is upcased:
+ * swapcase(mapping = :ascii) -> new_string
*
- * s = 'Hello World!' # => "Hello World!"
- * s.swapcase # => "hELLO wORLD!"
- *
- * The casing may be affected by the given +options+;
- * see {Case Mapping}[rdoc-ref:case_mapping.rdoc].
- *
- * Related: String#swapcase!.
+ * :include: doc/string/swapcase.rdoc
*
*/
@@ -8289,9 +8563,12 @@ tr_trans(VALUE str, VALUE src, VALUE repl, int sflag)
* call-seq:
* tr!(selector, replacements) -> self or nil
*
- * Like String#tr, but modifies +self+ in place.
- * Returns +self+ if any changes were made, +nil+ otherwise.
+ * Like String#tr, except:
+ *
+ * - Performs substitutions in +self+ (not in a copy of +self+).
+ * - Returns +self+ if any modifications were made, +nil+ otherwise.
*
+ * Related: {Modifying}[rdoc-ref:String@Modifying].
*/
static VALUE
@@ -8327,17 +8604,15 @@ rb_str_tr_bang(VALUE str, VALUE src, VALUE repl)
*
* Arguments +selector+ and +replacements+ must be valid character selectors
* (see {Character Selectors}[rdoc-ref:character_selectors.rdoc]),
- * and may use any of its valid forms, including negation, ranges, and escaping:
+ * and may use any of its valid forms, including negation, ranges, and escapes:
*
- * # Negation.
- * 'hello'.tr('^aeiou', '-') # => "-e--o"
- * # Ranges.
- * 'ibm'.tr('b-z', 'a-z') # => "hal"
- * # Escapes.
+ * 'hello'.tr('^aeiou', '-') # => "-e--o" # Negation.
+ * 'ibm'.tr('b-z', 'a-z') # => "hal" # Range.
* 'hel^lo'.tr('\^aeiou', '-') # => "h-l-l-" # Escaped leading caret.
* 'i-b-m'.tr('b\-z', 'a-z') # => "ibabm" # Escaped embedded hyphen.
* 'foo\\bar'.tr('ab\\', 'XYZ') # => "fooZYXr" # Escaped backslash.
*
+ * Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
*/
static VALUE
@@ -8440,9 +8715,10 @@ tr_find(unsigned int c, const char table[TR_TABLE_SIZE], VALUE del, VALUE nodel)
* call-seq:
* delete!(*selectors) -> self or nil
*
- * Like String#delete, but modifies +self+ in place.
- * Returns +self+ if any changes were made, +nil+ otherwise.
+ * Like String#delete, but modifies +self+ in place;
+ * returns +self+ if any characters were deleted, +nil+ otherwise.
*
+ * Related: see {Modifying}[rdoc-ref:String@Modifying].
*/
static VALUE
@@ -8511,13 +8787,7 @@ rb_str_delete_bang(int argc, VALUE *argv, VALUE str)
* call-seq:
* delete(*selectors) -> new_string
*
- * Returns a copy of +self+ with characters specified by +selectors+ removed
- * (see {Multiple Character Selectors}[rdoc-ref:character_selectors.rdoc@Multiple+Character+Selectors]):
- *
- * "hello".delete "l","lo" #=> "heo"
- * "hello".delete "lo" #=> "he"
- * "hello".delete "aeiou", "^e" #=> "hell"
- * "hello".delete "ej-m" #=> "ho"
+ * :include: doc/string/delete.rdoc
*
*/
@@ -8534,8 +8804,12 @@ rb_str_delete(int argc, VALUE *argv, VALUE str)
* call-seq:
* squeeze!(*selectors) -> self or nil
*
- * Like String#squeeze, but modifies +self+ in place.
- * Returns +self+ if any changes were made, +nil+ otherwise.
+ * Like String#squeeze, except that:
+ *
+ * - Characters are squeezed in +self+ (not in a copy of +self+).
+ * - Returns +self+ if any changes are made, +nil+ otherwise.
+ *
+ * Related: See {Modifying}[rdoc-ref:String@Modifying].
*/
static VALUE
@@ -8618,16 +8892,7 @@ rb_str_squeeze_bang(int argc, VALUE *argv, VALUE str)
* call-seq:
* squeeze(*selectors) -> new_string
*
- * Returns a copy of +self+ with characters specified by +selectors+ "squeezed"
- * (see {Multiple Character Selectors}[rdoc-ref:character_selectors.rdoc@Multiple+Character+Selectors]):
- *
- * "Squeezed" means that each multiple-character run of a selected character
- * is squeezed down to a single character;
- * with no arguments given, squeezes all characters:
- *
- * "yellow moon".squeeze #=> "yelow mon"
- * " now is the".squeeze(" ") #=> " now is the"
- * "putters shoot balls".squeeze("m-z") #=> "puters shot balls"
+ * :include: doc/string/squeeze.rdoc
*
*/
@@ -8644,10 +8909,12 @@ rb_str_squeeze(int argc, VALUE *argv, VALUE str)
* call-seq:
* tr_s!(selector, replacements) -> self or nil
*
- * Like String#tr_s, but modifies +self+ in place.
- * Returns +self+ if any changes were made, +nil+ otherwise.
+ * Like String#tr_s, except:
+ *
+ * - Modifies +self+ in place (not a copy of +self+).
+ * - Returns +self+ if any changes were made, +nil+ otherwise.
*
- * Related: String#squeeze!.
+ * Related: {Modifying}[rdoc-ref:String@Modifying].
*/
static VALUE
@@ -8659,16 +8926,21 @@ rb_str_tr_s_bang(VALUE str, VALUE src, VALUE repl)
/*
* call-seq:
- * tr_s(selector, replacements) -> string
+ * tr_s(selector, replacements) -> new_string
+ *
+ * Like String#tr, except:
*
- * Like String#tr, but also squeezes the modified portions of the translated string;
- * returns a new string (translated and squeezed).
+ * - Also squeezes the modified portions of the translated string;
+ * see String#squeeze.
+ * - Returns the translated and squeezed string.
+ *
+ * Examples:
*
* 'hello'.tr_s('l', 'r') #=> "hero"
* 'hello'.tr_s('el', '-') #=> "h-o"
* 'hello'.tr_s('el', 'hx') #=> "hhxo"
*
- * Related: String#squeeze.
+ * Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
*
*/
@@ -8685,23 +8957,7 @@ rb_str_tr_s(VALUE str, VALUE src, VALUE repl)
* call-seq:
* count(*selectors) -> integer
*
- * Returns the total number of characters in +self+
- * that are specified by the given +selectors+
- * (see {Multiple Character Selectors}[rdoc-ref:character_selectors.rdoc@Multiple+Character+Selectors]):
- *
- * a = "hello world"
- * a.count "lo" #=> 5
- * a.count "lo", "o" #=> 2
- * a.count "hello", "^l" #=> 4
- * a.count "ej-m" #=> 4
- *
- * "hello^world".count "\\^aeiou" #=> 4
- * "hello-world".count "a\\-eo" #=> 4
- *
- * c = "hello world\\r\\n"
- * c.count "\\" #=> 2
- * c.count "\\A" #=> 0
- * c.count "X-\\w" #=> 3
+ * :include: doc/string/count.rdoc
*/
static VALUE
@@ -8864,8 +9120,8 @@ literal_split_pattern(VALUE spat, split_type_t default_type)
/*
* call-seq:
- * split(field_sep = $;, limit = nil) -> array
- * split(field_sep = $;, limit = nil) {|substring| ... } -> self
+ * split(field_sep = $;, limit = 0) -> array_of_substrings
+ * split(field_sep = $;, limit = 0) {|substring| ... } -> self
*
* :include: doc/string/split.rdoc
*
@@ -8936,11 +9192,15 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
}
}
-#define SPLIT_STR(beg, len) (empty_count = split_string(result, str, beg, len, empty_count))
+#define SPLIT_STR(beg, len) ( \
+ empty_count = split_string(result, str, beg, len, empty_count), \
+ str_mod_check(str, str_start, str_len))
beg = 0;
char *ptr = RSTRING_PTR(str);
- char *eptr = RSTRING_END(str);
+ char *const str_start = ptr;
+ const long str_len = RSTRING_LEN(str);
+ char *const eptr = str_start + str_len;
if (split_type == SPLIT_TYPE_AWK) {
char *bptr = ptr;
int skip = 1;
@@ -9001,7 +9261,6 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
}
}
else if (split_type == SPLIT_TYPE_STRING) {
- char *str_start = ptr;
char *substr_start = ptr;
char *sptr = RSTRING_PTR(spat);
long slen = RSTRING_LEN(spat);
@@ -9018,6 +9277,7 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
continue;
}
SPLIT_STR(substr_start - str_start, (ptr+end) - substr_start);
+ str_mod_check(spat, sptr, slen);
ptr += end + slen;
substr_start = ptr;
if (!NIL_P(limit) && lim <= ++i) break;
@@ -9025,7 +9285,6 @@ rb_str_split_m(int argc, VALUE *argv, VALUE str)
beg = ptr - str_start;
}
else if (split_type == SPLIT_TYPE_CHARS) {
- char *str_start = ptr;
int n;
if (result) result = rb_ary_new_capa(RSTRING_LEN(str));
@@ -9290,8 +9549,8 @@ rb_str_enumerate_lines(int argc, VALUE *argv, VALUE str, VALUE ary)
/*
* call-seq:
- * each_line(line_sep = $/, chomp: false) {|substring| ... } -> self
- * each_line(line_sep = $/, chomp: false) -> enumerator
+ * each_line(record_separator = $/, chomp: false) {|substring| ... } -> self
+ * each_line(record_separator = $/, chomp: false) -> enumerator
*
* :include: doc/string/each_line.rdoc
*
@@ -9306,11 +9565,53 @@ rb_str_each_line(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * lines(Line_sep = $/, chomp: false) -> array_of_strings
+ * lines(record_separator = $/, chomp: false) -> array_of_strings
+ *
+ * Returns substrings ("lines") of +self+
+ * according to the given arguments:
+ *
+ * s = <<~EOT
+ * This is the first line.
+ * This is line two.
*
- * Forms substrings ("lines") of +self+ according to the given arguments
- * (see String#each_line for details); returns the lines in an array.
+ * This is line four.
+ * This is line five.
+ * EOT
*
+ * With the default argument values:
+ *
+ * $/ # => "\n"
+ * s.lines
+ * # =>
+ * ["This is the first line.\n",
+ * "This is line two.\n",
+ * "\n",
+ * "This is line four.\n",
+ * "This is line five.\n"]
+ *
+ * With a different +record_separator+:
+ *
+ * record_separator = ' is '
+ * s.lines(record_separator)
+ * # =>
+ * ["This is ",
+ * "the first line.\nThis is ",
+ * "line two.\n\nThis is ",
+ * "line four.\nThis is ",
+ * "line five.\n"]
+ *
+ * With keyword argument +chomp+ as +true+,
+ * removes the trailing newline from each line:
+ *
+ * s.lines(chomp: true)
+ * # =>
+ * ["This is the first line.",
+ * "This is line two.",
+ * "",
+ * "This is line four.",
+ * "This is line five."]
+ *
+ * Related: see {Converting to Non-String}[rdoc-ref:String@Converting+to+Non--5CString].
*/
static VALUE
@@ -9411,7 +9712,7 @@ rb_str_enumerate_chars(VALUE str, VALUE ary)
/*
* call-seq:
- * each_char {|c| ... } -> self
+ * each_char {|char| ... } -> self
* each_char -> enumerator
*
* :include: doc/string/each_char.rdoc
@@ -9471,7 +9772,7 @@ rb_str_enumerate_codepoints(VALUE str, VALUE ary)
/*
* call-seq:
- * each_codepoint {|integer| ... } -> self
+ * each_codepoint {|codepoint| ... } -> self
* each_codepoint -> enumerator
*
* :include: doc/string/each_codepoint.rdoc
@@ -9641,7 +9942,7 @@ rb_str_enumerate_grapheme_clusters(VALUE str, VALUE ary)
/*
* call-seq:
- * each_grapheme_cluster {|gc| ... } -> self
+ * each_grapheme_cluster {|grapheme_cluster| ... } -> self
* each_grapheme_cluster -> enumerator
*
* :include: doc/string/each_grapheme_cluster.rdoc
@@ -9692,10 +9993,12 @@ chopped_length(VALUE str)
* call-seq:
* chop! -> self or nil
*
- * Like String#chop, but modifies +self+ in place;
- * returns +nil+ if +self+ is empty, +self+ otherwise.
+ * Like String#chop, except that:
+ *
+ * - Removes trailing characters from +self+ (not from a copy of +self+).
+ * - Returns +self+ if any characters are removed, +nil+ otherwise.
*
- * Related: String#chomp!.
+ * Related: see {Modifying}[rdoc-ref:String@Modifying].
*/
static VALUE
@@ -9872,9 +10175,12 @@ rb_str_chomp_string(VALUE str, VALUE rs)
* call-seq:
* chomp!(line_sep = $/) -> self or nil
*
- * Like String#chomp, but modifies +self+ in place;
- * returns +nil+ if no modification made, +self+ otherwise.
+ * Like String#chomp, except that:
*
+ * - Removes trailing characters from +self+ (not from a copy of +self+).
+ * - Returns +self+ if any characters are removed, +nil+ otherwise.
+ *
+ * Related: see {Modifying}[rdoc-ref:String@Modifying].
*/
static VALUE
@@ -9905,6 +10211,22 @@ rb_str_chomp(int argc, VALUE *argv, VALUE str)
return rb_str_subseq(str, 0, chompped_length(str, rs));
}
+static void
+tr_setup_table_multi(char table[TR_TABLE_SIZE], VALUE *tablep, VALUE *ctablep,
+ VALUE str, int num_selectors, VALUE *selectors)
+{
+ int i;
+
+ for (i=0; i<num_selectors; i++) {
+ VALUE selector = selectors[i];
+ rb_encoding *enc;
+
+ StringValue(selector);
+ enc = rb_enc_check(str, selector);
+ tr_setup_table(selector, table, i==0, tablep, ctablep, enc);
+ }
+}
+
static long
lstrip_offset(VALUE str, const char *s, const char *e, rb_encoding *enc)
{
@@ -9928,18 +10250,39 @@ lstrip_offset(VALUE str, const char *s, const char *e, rb_encoding *enc)
return s - start;
}
+static long
+lstrip_offset_table(VALUE str, const char *s, const char *e, rb_encoding *enc,
+ char table[TR_TABLE_SIZE], VALUE del, VALUE nodel)
+{
+ const char *const start = s;
+
+ if (!s || s >= e) return 0;
+
+ /* remove leading characters in the table */
+ while (s < e) {
+ int n;
+ unsigned int cc = rb_enc_codepoint_len(s, e, &n, enc);
+
+ if (!tr_find(cc, table, del, nodel)) break;
+ s += n;
+ }
+ return s - start;
+}
+
/*
* call-seq:
- * lstrip! -> self or nil
+ * lstrip!(*selectors) -> self or nil
+ *
+ * Like String#lstrip, except that:
*
- * Like String#lstrip, except that any modifications are made in +self+;
- * returns +self+ if any modification are made, +nil+ otherwise.
+ * - Performs stripping in +self+ (not in a copy of +self+).
+ * - Returns +self+ if any characters are stripped, +nil+ otherwise.
*
- * Related: String#rstrip!, String#strip!.
+ * Related: see {Modifying}[rdoc-ref:String@Modifying].
*/
static VALUE
-rb_str_lstrip_bang(VALUE str)
+rb_str_lstrip_bang(int argc, VALUE *argv, VALUE str)
{
rb_encoding *enc;
char *start, *s;
@@ -9948,7 +10291,17 @@ rb_str_lstrip_bang(VALUE str)
str_modify_keep_cr(str);
enc = STR_ENC_GET(str);
RSTRING_GETMEM(str, start, olen);
- loffset = lstrip_offset(str, start, start+olen, enc);
+ if (argc > 0) {
+ char table[TR_TABLE_SIZE];
+ VALUE del = 0, nodel = 0;
+
+ tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
+ loffset = lstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
+ }
+ else {
+ loffset = lstrip_offset(str, start, start+olen, enc);
+ }
+
if (loffset > 0) {
long len = olen-loffset;
s = start + loffset;
@@ -9963,26 +10316,48 @@ rb_str_lstrip_bang(VALUE str)
/*
* call-seq:
- * lstrip -> new_string
+ * lstrip(*selectors) -> new_string
*
* Returns a copy of +self+ with leading whitespace removed;
* see {Whitespace in Strings}[rdoc-ref:String@Whitespace+in+Strings]:
*
* whitespace = "\x00\t\n\v\f\r "
* s = whitespace + 'abc' + whitespace
- * s # => "\u0000\t\n\v\f\r abc\u0000\t\n\v\f\r "
- * s.lstrip # => "abc\u0000\t\n\v\f\r "
+ * # => "\u0000\t\n\v\f\r abc\u0000\t\n\v\f\r "
+ * s.lstrip
+ * # => "abc\u0000\t\n\v\f\r "
+ *
+ * If +selectors+ are given, removes characters of +selectors+ from the beginning of +self+:
+ *
+ * s = "---abc+++"
+ * s.lstrip("-") # => "abc+++"
+ *
+ * +selectors+ must be valid character selectors (see {Character Selectors}[rdoc-ref:character_selectors.rdoc]),
+ * and may use any of its valid forms, including negation, ranges, and escapes:
*
- * Related: String#rstrip, String#strip.
+ * "01234abc56789".lstrip("0-9") # "abc56789"
+ * "01234abc56789".lstrip("0-9", "^4-6") # "4abc56789"
+ *
+ * Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
*/
static VALUE
-rb_str_lstrip(VALUE str)
+rb_str_lstrip(int argc, VALUE *argv, VALUE str)
{
char *start;
long len, loffset;
+
RSTRING_GETMEM(str, start, len);
- loffset = lstrip_offset(str, start, start+len, STR_ENC_GET(str));
+ if (argc > 0) {
+ char table[TR_TABLE_SIZE];
+ VALUE del = 0, nodel = 0;
+
+ tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
+ loffset = lstrip_offset_table(str, start, start+len, STR_ENC_GET(str), table, del, nodel);
+ }
+ else {
+ loffset = lstrip_offset(str, start, start+len, STR_ENC_GET(str));
+ }
if (loffset <= 0) return str_duplicate(rb_cString, str);
return rb_str_subseq(str, loffset, len - loffset);
}
@@ -10016,18 +10391,44 @@ rstrip_offset(VALUE str, const char *s, const char *e, rb_encoding *enc)
return e - t;
}
+static long
+rstrip_offset_table(VALUE str, const char *s, const char *e, rb_encoding *enc,
+ char table[TR_TABLE_SIZE], VALUE del, VALUE nodel)
+{
+ const char *t;
+ char *tp;
+
+ rb_str_check_dummy_enc(enc);
+ if (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN) {
+ rb_raise(rb_eEncCompatError, "invalid byte sequence in %s", rb_enc_name(enc));
+ }
+ if (!s || s >= e) return 0;
+ t = e;
+
+ /* remove trailing characters in the table */
+ while ((tp = rb_enc_prev_char(s, t, e, enc)) != NULL) {
+ unsigned int c = rb_enc_codepoint(tp, e, enc);
+ if (!tr_find(c, table, del, nodel)) break;
+ t = tp;
+ }
+
+ return e - t;
+}
+
/*
* call-seq:
- * rstrip! -> self or nil
+ * rstrip!(*selectors) -> self or nil
+ *
+ * Like String#rstrip, except that:
*
- * Like String#rstrip, except that any modifications are made in +self+;
- * returns +self+ if any modification are made, +nil+ otherwise.
+ * - Performs stripping in +self+ (not in a copy of +self+).
+ * - Returns +self+ if any characters are stripped, +nil+ otherwise.
*
- * Related: String#lstrip!, String#strip!.
+ * Related: see {Modifying}[rdoc-ref:String@Modifying].
*/
static VALUE
-rb_str_rstrip_bang(VALUE str)
+rb_str_rstrip_bang(int argc, VALUE *argv, VALUE str)
{
rb_encoding *enc;
char *start;
@@ -10036,7 +10437,16 @@ rb_str_rstrip_bang(VALUE str)
str_modify_keep_cr(str);
enc = STR_ENC_GET(str);
RSTRING_GETMEM(str, start, olen);
- roffset = rstrip_offset(str, start, start+olen, enc);
+ if (argc > 0) {
+ char table[TR_TABLE_SIZE];
+ VALUE del = 0, nodel = 0;
+
+ tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
+ roffset = rstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
+ }
+ else {
+ roffset = rstrip_offset(str, start, start+olen, enc);
+ }
if (roffset > 0) {
long len = olen - roffset;
@@ -10050,9 +10460,9 @@ rb_str_rstrip_bang(VALUE str)
/*
* call-seq:
- * rstrip -> new_string
+ * rstrip(*selectors) -> new_string
*
- * Returns a copy of the receiver with trailing whitespace removed;
+ * Returns a copy of +self+ with trailing whitespace removed;
* see {Whitespace in Strings}[rdoc-ref:String@Whitespace+in+Strings]:
*
* whitespace = "\x00\t\n\v\f\r "
@@ -10060,11 +10470,22 @@ rb_str_rstrip_bang(VALUE str)
* s # => "\u0000\t\n\v\f\r abc\u0000\t\n\v\f\r "
* s.rstrip # => "\u0000\t\n\v\f\r abc"
*
- * Related: String#lstrip, String#strip.
+ * If +selectors+ are given, removes characters of +selectors+ from the end of +self+:
+ *
+ * s = "---abc+++"
+ * s.rstrip("+") # => "---abc"
+ *
+ * +selectors+ must be valid character selectors (see {Character Selectors}[rdoc-ref:character_selectors.rdoc]),
+ * and may use any of its valid forms, including negation, ranges, and escapes:
+ *
+ * "01234abc56789".rstrip("0-9") # "01234abc"
+ * "01234abc56789".rstrip("0-9", "^4-6") # "01234abc56"
+ *
+ * Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
*/
static VALUE
-rb_str_rstrip(VALUE str)
+rb_str_rstrip(int argc, VALUE *argv, VALUE str)
{
rb_encoding *enc;
char *start;
@@ -10072,8 +10493,16 @@ rb_str_rstrip(VALUE str)
enc = STR_ENC_GET(str);
RSTRING_GETMEM(str, start, olen);
- roffset = rstrip_offset(str, start, start+olen, enc);
+ if (argc > 0) {
+ char table[TR_TABLE_SIZE];
+ VALUE del = 0, nodel = 0;
+ tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
+ roffset = rstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
+ }
+ else {
+ roffset = rstrip_offset(str, start, start+olen, enc);
+ }
if (roffset <= 0) return str_duplicate(rb_cString, str);
return rb_str_subseq(str, 0, olen-roffset);
}
@@ -10081,16 +10510,18 @@ rb_str_rstrip(VALUE str)
/*
* call-seq:
- * strip! -> self or nil
+ * strip!(*selectors) -> self or nil
*
- * Like String#strip, except that any modifications are made in +self+;
- * returns +self+ if any modification are made, +nil+ otherwise.
+ * Like String#strip, except that:
*
- * Related: String#lstrip!, String#strip!.
+ * - Any modifications are made to +self+.
+ * - Returns +self+ if any modification are made, +nil+ otherwise.
+ *
+ * Related: see {Modifying}[rdoc-ref:String@Modifying].
*/
static VALUE
-rb_str_strip_bang(VALUE str)
+rb_str_strip_bang(int argc, VALUE *argv, VALUE str)
{
char *start;
long olen, loffset, roffset;
@@ -10099,8 +10530,19 @@ rb_str_strip_bang(VALUE str)
str_modify_keep_cr(str);
enc = STR_ENC_GET(str);
RSTRING_GETMEM(str, start, olen);
- loffset = lstrip_offset(str, start, start+olen, enc);
- roffset = rstrip_offset(str, start+loffset, start+olen, enc);
+
+ if (argc > 0) {
+ char table[TR_TABLE_SIZE];
+ VALUE del = 0, nodel = 0;
+
+ tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
+ loffset = lstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
+ roffset = rstrip_offset_table(str, start+loffset, start+olen, enc, table, del, nodel);
+ }
+ else {
+ loffset = lstrip_offset(str, start, start+olen, enc);
+ roffset = rstrip_offset(str, start+loffset, start+olen, enc);
+ }
if (loffset > 0 || roffset > 0) {
long len = olen-roffset;
@@ -10118,29 +10560,52 @@ rb_str_strip_bang(VALUE str)
/*
* call-seq:
- * strip -> new_string
+ * strip(*selectors) -> new_string
*
- * Returns a copy of the receiver with leading and trailing whitespace removed;
+ * Returns a copy of +self+ with leading and trailing whitespace removed;
* see {Whitespace in Strings}[rdoc-ref:String@Whitespace+in+Strings]:
*
* whitespace = "\x00\t\n\v\f\r "
* s = whitespace + 'abc' + whitespace
- * s # => "\u0000\t\n\v\f\r abc\u0000\t\n\v\f\r "
+ * # => "\u0000\t\n\v\f\r abc\u0000\t\n\v\f\r "
* s.strip # => "abc"
*
- * Related: String#lstrip, String#rstrip.
+ * If +selectors+ are given, removes characters of +selectors+ from both ends of +self+:
+ *
+ * s = "---abc+++"
+ * s.strip("-+") # => "abc"
+ * s.strip("+-") # => "abc"
+ *
+ * +selectors+ must be valid character selectors (see {Character Selectors}[rdoc-ref:character_selectors.rdoc]),
+ * and may use any of its valid forms, including negation, ranges, and escapes:
+ *
+ * "01234abc56789".strip("0-9") # "abc"
+ * "01234abc56789".strip("0-9", "^4-6") # "4abc56"
+ *
+ * Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String].
*/
static VALUE
-rb_str_strip(VALUE str)
+rb_str_strip(int argc, VALUE *argv, VALUE str)
{
char *start;
long olen, loffset, roffset;
rb_encoding *enc = STR_ENC_GET(str);
RSTRING_GETMEM(str, start, olen);
- loffset = lstrip_offset(str, start, start+olen, enc);
- roffset = rstrip_offset(str, start+loffset, start+olen, enc);
+
+ if (argc > 0) {
+ char table[TR_TABLE_SIZE];
+ VALUE del = 0, nodel = 0;
+
+ tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
+ loffset = lstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
+ roffset = rstrip_offset_table(str, start+loffset, start+olen, enc, table, del, nodel);
+ }
+ else {
+ loffset = lstrip_offset(str, start, start+olen, enc);
+ roffset = rstrip_offset(str, start+loffset, start+olen, enc);
+ }
if (loffset <= 0 && roffset <= 0) return str_duplicate(rb_cString, str);
return rb_str_subseq(str, loffset, olen-loffset-roffset);
@@ -10205,40 +10670,10 @@ scan_once(VALUE str, VALUE pat, long *start, int set_backref_str)
/*
* call-seq:
- * scan(string_or_regexp) -> array
- * scan(string_or_regexp) {|matches| ... } -> self
+ * scan(pattern) -> array_of_results
+ * scan(pattern) {|result| ... } -> self
*
- * Matches a pattern against +self+; the pattern is:
- *
- * - +string_or_regexp+ itself, if it is a Regexp.
- * - <tt>Regexp.quote(string_or_regexp)</tt>, if +string_or_regexp+ is a string.
- *
- * Iterates through +self+, generating a collection of matching results:
- *
- * - If the pattern contains no groups, each result is the
- * matched string, <code>$&</code>.
- * - If the pattern contains groups, each result is an array
- * containing one entry per group.
- *
- * With no block given, returns an array of the results:
- *
- * s = 'cruel world'
- * s.scan(/\w+/) # => ["cruel", "world"]
- * s.scan(/.../) # => ["cru", "el ", "wor"]
- * s.scan(/(...)/) # => [["cru"], ["el "], ["wor"]]
- * s.scan(/(..)(..)/) # => [["cr", "ue"], ["l ", "wo"]]
- *
- * With a block given, calls the block with each result; returns +self+:
- *
- * s.scan(/\w+/) {|w| print "<<#{w}>> " }
- * print "\n"
- * s.scan(/(.)(.)/) {|x,y| print y, x }
- * print "\n"
- *
- * Output:
- *
- * <<cruel>> <<world>>
- * rceu lowlr
+ * :include: doc/string/scan.rdoc
*
*/
@@ -10280,18 +10715,46 @@ rb_str_scan(VALUE str, VALUE pat)
* call-seq:
* hex -> integer
*
- * Interprets the leading substring of +self+ as a string of hexadecimal digits
- * (with an optional sign and an optional <code>0x</code>) and returns the
- * corresponding number;
- * returns zero if there is no such leading substring:
+ * Interprets the leading substring of +self+ as hexadecimal, possibly signed;
+ * returns its value as an integer.
+ *
+ * The leading substring is interpreted as hexadecimal when it begins with:
+ *
+ * - One or more character representing hexadecimal digits
+ * (each in one of the ranges <tt>'0'..'9'</tt>, <tt>'a'..'f'</tt>, or <tt>'A'..'F'</tt>);
+ * the string to be interpreted ends at the first character that does not represent a hexadecimal digit:
+ *
+ * 'f'.hex # => 15
+ * '11'.hex # => 17
+ * 'FFF'.hex # => 4095
+ * 'fffg'.hex # => 4095
+ * 'foo'.hex # => 15 # 'f' hexadecimal, 'oo' not.
+ * 'bar'.hex # => 186 # 'ba' hexadecimal, 'r' not.
+ * 'deadbeef'.hex # => 3735928559
+ *
+ * - <tt>'0x'</tt> or <tt>'0X'</tt>, followed by one or more hexadecimal digits:
*
- * '0x0a'.hex # => 10
- * '-1234'.hex # => -4660
- * '0'.hex # => 0
- * 'non-numeric'.hex # => 0
+ * '0xfff'.hex # => 4095
+ * '0xfffg'.hex # => 4095
*
- * Related: String#oct.
+ * Any of the above may prefixed with <tt>'-'</tt>, which negates the interpreted value:
*
+ * '-fff'.hex # => -4095
+ * '-0xFFF'.hex # => -4095
+ *
+ * For any substring not described above, returns zero:
+ *
+ * 'xxx'.hex # => 0
+ * ''.hex # => 0
+ *
+ * Note that, unlike #oct, this method interprets only hexadecimal,
+ * and not binary, octal, or decimal notations:
+ *
+ * '0b111'.hex # => 45329
+ * '0o777'.hex # => 0
+ * '0d999'.hex # => 55705
+ *
+ * Related: See {Converting to Non-String}[rdoc-ref:String@Converting+to+Non--5CString].
*/
static VALUE
@@ -10305,20 +10768,79 @@ rb_str_hex(VALUE str)
* call-seq:
* oct -> integer
*
- * Interprets the leading substring of +self+ as a string of octal digits
- * (with an optional sign) and returns the corresponding number;
- * returns zero if there is no such leading substring:
+ * Interprets the leading substring of +self+ as octal, binary, decimal, or hexadecimal, possibly signed;
+ * returns their value as an integer.
+ *
+ * In brief:
+ *
+ * # Interpreted as octal.
+ * '777'.oct # => 511
+ * '777x'.oct # => 511
+ * '0777'.oct # => 511
+ * '0o777'.oct # => 511
+ * '-777'.oct # => -511
+ * # Not interpreted as octal.
+ * '0b111'.oct # => 7 # Interpreted as binary.
+ * '0d999'.oct # => 999 # Interpreted as decimal.
+ * '0xfff'.oct # => 4095 # Interpreted as hexadecimal.
+ *
+ * The leading substring is interpreted as octal when it begins with:
+ *
+ * - One or more character representing octal digits
+ * (each in the range <tt>'0'..'7'</tt>);
+ * the string to be interpreted ends at the first character that does not represent an octal digit:
+ *
+ * '7'.oct @ => 7
+ * '11'.oct # => 9
+ * '777'.oct # => 511
+ * '0777'.oct # => 511
+ * '7778'.oct # => 511
+ * '777x'.oct # => 511
+ *
+ * - <tt>'0o'</tt>, followed by one or more octal digits:
+ *
+ * '0o777'.oct # => 511
+ * '0o7778'.oct # => 511
+ *
+ * The leading substring is _not_ interpreted as octal when it begins with:
+ *
+ * - <tt>'0b'</tt>, followed by one or more characters representing binary digits
+ * (each in the range <tt>'0'..'1'</tt>);
+ * the string to be interpreted ends at the first character that does not represent a binary digit.
+ * the string is interpreted as binary digits (base 2):
*
- * '123'.oct # => 83
- * '-377'.oct # => -255
- * '0377non-numeric'.oct # => 255
- * 'non-numeric'.oct # => 0
+ * '0b111'.oct # => 7
+ * '0b1112'.oct # => 7
*
- * If +self+ starts with <tt>0</tt>, radix indicators are honored;
- * see Kernel#Integer.
+ * - <tt>'0d'</tt>, followed by one or more characters representing decimal digits
+ * (each in the range <tt>'0'..'9'</tt>);
+ * the string to be interpreted ends at the first character that does not represent a decimal digit.
+ * the string is interpreted as decimal digits (base 10):
*
- * Related: String#hex.
+ * '0d999'.oct # => 999
+ * '0d999x'.oct # => 999
*
+ * - <tt>'0x'</tt>, followed by one or more characters representing hexadecimal digits
+ * (each in one of the ranges <tt>'0'..'9'</tt>, <tt>'a'..'f'</tt>, or <tt>'A'..'F'</tt>);
+ * the string to be interpreted ends at the first character that does not represent a hexadecimal digit.
+ * the string is interpreted as hexadecimal digits (base 16):
+ *
+ * '0xfff'.oct # => 4095
+ * '0xfffg'.oct # => 4095
+ *
+ * Any of the above may prefixed with <tt>'-'</tt>, which negates the interpreted value:
+ *
+ * '-777'.oct # => -511
+ * '-0777'.oct # => -511
+ * '-0b111'.oct # => -7
+ * '-0xfff'.oct # => -4095
+ *
+ * For any substring not described above, returns zero:
+ *
+ * 'foo'.oct # => 0
+ * ''.oct # => 0
+ *
+ * Related: see {Converting to Non-String}[rdoc-ref:String@Converting+to+Non--5CString].
*/
static VALUE
@@ -10334,11 +10856,6 @@ rb_str_oct(VALUE str)
static struct {
rb_nativethread_lock_t lock;
} crypt_mutex = {PTHREAD_MUTEX_INITIALIZER};
-
-static void
-crypt_mutex_initialize(void)
-{
-}
#endif
/*
@@ -10409,6 +10926,7 @@ rb_str_crypt(VALUE str, VALUE salt)
struct crypt_data *data;
# define CRYPT_END() ALLOCV_END(databuf)
#else
+ char *tmp_buf;
extern char *crypt(const char *, const char *);
# define CRYPT_END() rb_nativethread_lock_unlock(&crypt_mutex.lock)
#endif
@@ -10443,7 +10961,6 @@ 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
@@ -10452,8 +10969,21 @@ rb_str_crypt(VALUE str, VALUE salt)
CRYPT_END();
rb_syserr_fail(err, "crypt");
}
+#ifdef HAVE_CRYPT_R
result = rb_str_new_cstr(res);
CRYPT_END();
+#else
+ // We need to copy this buffer because it's static and we need to unlock the mutex
+ // before allocating a new object (the string to be returned). If we allocate while
+ // holding the lock, we could run GC which fires the VM barrier and causes a deadlock
+ // if other ractors are waiting on this lock.
+ size_t res_size = strlen(res)+1;
+ tmp_buf = ALLOCA_N(char, res_size); // should be small enough to alloca
+ memcpy(tmp_buf, res, res_size);
+ res = tmp_buf;
+ CRYPT_END();
+ result = rb_str_new_cstr(res);
+#endif
return result;
}
@@ -10581,7 +11111,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_cString, 0, len, termlen);
+ res = str_enc_new(rb_cString, 0, len, enc);
p = RSTRING_PTR(res);
if (flen <= 1) {
memset(p, *f, llen);
@@ -10617,7 +11147,7 @@ rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag)
}
TERM_FILL(p, termlen);
STR_SET_LEN(res, p-RSTRING_PTR(res));
- rb_enc_associate(res, enc);
+
if (argc == 2)
cr = ENC_CODERANGE_AND(cr, ENC_CODERANGE(pad));
if (cr != ENC_CODERANGE_BROKEN)
@@ -10630,12 +11160,10 @@ rb_str_justify(int argc, VALUE *argv, VALUE str, char jflag)
/*
* call-seq:
- * ljust(size, pad_string = ' ') -> new_string
+ * ljust(width, pad_string = ' ') -> new_string
*
* :include: doc/string/ljust.rdoc
*
- * Related: String#rjust, String#center.
- *
*/
static VALUE
@@ -10646,12 +11174,10 @@ rb_str_ljust(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * rjust(size, pad_string = ' ') -> new_string
+ * rjust(width, pad_string = ' ') -> new_string
*
* :include: doc/string/rjust.rdoc
*
- * Related: String#ljust, String#center.
- *
*/
static VALUE
@@ -10667,8 +11193,6 @@ rb_str_rjust(int argc, VALUE *argv, VALUE str)
*
* :include: doc/string/center.rdoc
*
- * Related: String#ljust, String#rjust.
- *
*/
static VALUE
@@ -10679,7 +11203,7 @@ rb_str_center(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * partition(string_or_regexp) -> [head, match, tail]
+ * partition(pattern) -> [pre_match, first_match, post_match]
*
* :include: doc/string/partition.rdoc
*
@@ -10716,7 +11240,7 @@ rb_str_partition(VALUE str, VALUE sep)
/*
* call-seq:
- * rpartition(sep) -> [head, match, tail]
+ * rpartition(pattern) -> [pre_match, last_match, post_match]
*
* :include: doc/string/rpartition.rdoc
*
@@ -10756,7 +11280,7 @@ rb_str_rpartition(VALUE str, VALUE sep)
/*
* call-seq:
- * start_with?(*string_or_regexp) -> true or false
+ * start_with?(*patterns) -> true or false
*
* :include: doc/string/start_with_p.rdoc
*
@@ -10881,9 +11405,10 @@ deleted_prefix_length(VALUE str, VALUE prefix)
* call-seq:
* delete_prefix!(prefix) -> self or nil
*
- * Like String#delete_prefix, except that +self+ is modified in place.
- * Returns +self+ if the prefix is removed, +nil+ otherwise.
+ * Like String#delete_prefix, except that +self+ is modified in place;
+ * returns +self+ if the prefix is removed, +nil+ otherwise.
*
+ * Related: see {Modifying}[rdoc-ref:String@Modifying].
*/
static VALUE
@@ -10956,9 +11481,10 @@ deleted_suffix_length(VALUE str, VALUE suffix)
* call-seq:
* delete_suffix!(suffix) -> self or nil
*
- * Like String#delete_suffix, except that +self+ is modified in place.
- * Returns +self+ if the suffix is removed, +nil+ otherwise.
+ * Like String#delete_suffix, except that +self+ is modified in place;
+ * returns +self+ if the suffix is removed, +nil+ otherwise.
*
+ * Related: see {Modifying}[rdoc-ref:String@Modifying].
*/
static VALUE
@@ -11010,6 +11536,21 @@ rb_str_setter(VALUE val, ID id, VALUE *var)
}
static void
+nil_setter_warning(ID id)
+{
+ rb_warn_deprecated("non-nil '%"PRIsVALUE"'", NULL, rb_id2str(id));
+}
+
+void
+rb_deprecated_str_setter(VALUE val, ID id, VALUE *var)
+{
+ rb_str_setter(val, id, var);
+ if (!NIL_P(*var)) {
+ nil_setter_warning(id);
+ }
+}
+
+static void
rb_fs_setter(VALUE val, ID id, VALUE *var)
{
val = rb_fs_check(val);
@@ -11019,7 +11560,7 @@ rb_fs_setter(VALUE val, ID id, VALUE *var)
rb_id2str(id));
}
if (!NIL_P(val)) {
- rb_warn_deprecated("'$;'", NULL);
+ nil_setter_warning(id);
}
*var = val;
}
@@ -11060,7 +11601,7 @@ rb_str_force_encoding(VALUE str, VALUE enc)
/*
* call-seq:
- * b -> string
+ * b -> new_string
*
* :include: doc/string/b.rdoc
*
@@ -11103,11 +11644,8 @@ rb_str_b(VALUE str)
* call-seq:
* valid_encoding? -> true or false
*
- * Returns +true+ if +self+ is encoded correctly, +false+ otherwise:
+ * :include: doc/string/valid_encoding_p.rdoc
*
- * "\xc2\xa1".force_encoding("UTF-8").valid_encoding? # => true
- * "\xc2".force_encoding("UTF-8").valid_encoding? # => false
- * "\x80".force_encoding("UTF-8").valid_encoding? # => false
*/
static VALUE
@@ -11122,12 +11660,12 @@ rb_str_valid_encoding_p(VALUE str)
* call-seq:
* ascii_only? -> true or false
*
- * Returns +true+ if +self+ contains only ASCII characters,
- * +false+ otherwise:
+ * Returns whether +self+ contains only ASCII characters:
*
* 'abc'.ascii_only? # => true
* "abc\u{6666}".ascii_only? # => false
*
+ * Related: see {Querying}[rdoc-ref:String@Querying].
*/
static VALUE
@@ -11243,7 +11781,7 @@ enc_str_scrub(rb_encoding *enc, VALUE str, VALUE repl, int cr)
encidx = rb_enc_to_index(enc);
#define DEFAULT_REPLACE_CHAR(str) do { \
- static const char replace[sizeof(str)-1] = str; \
+ RBIMPL_ATTR_NONSTRING() static const char replace[sizeof(str)-1] = str; \
rep = replace; replen = (int)sizeof(replace); \
} while (0)
@@ -11459,8 +11997,8 @@ enc_str_scrub(rb_encoding *enc, VALUE str, VALUE repl, int cr)
/*
* call-seq:
- * scrub(replacement_string = default_replacement) -> new_string
- * scrub{|bytes| ... } -> new_string
+ * scrub(replacement_string = default_replacement_string) -> new_string
+ * scrub{|sequence| ... } -> new_string
*
* :include: doc/string/scrub.rdoc
*
@@ -11475,11 +12013,15 @@ str_scrub(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * scrub! -> self
- * scrub!(replacement_string = default_replacement) -> self
- * scrub!{|bytes| ... } -> self
+ * scrub!(replacement_string = default_replacement_string) -> self
+ * scrub!{|sequence| ... } -> self
+ *
+ * Like String#scrub, except that:
*
- * Like String#scrub, except that any replacements are made in +self+.
+ * - Any replacements are made in +self+.
+ * - Returns +self+.
+ *
+ * Related: see {Modifying}[rdoc-ref:String@Modifying].
*
*/
static VALUE
@@ -11514,34 +12056,8 @@ unicode_normalize_common(int argc, VALUE *argv, VALUE str, ID id)
* call-seq:
* unicode_normalize(form = :nfc) -> string
*
- * Returns a copy of +self+ with
- * {Unicode normalization}[https://unicode.org/reports/tr15] applied.
- *
- * Argument +form+ must be one of the following symbols
- * (see {Unicode normalization forms}[https://unicode.org/reports/tr15/#Norm_Forms]):
- *
- * - +:nfc+: Canonical decomposition, followed by canonical composition.
- * - +:nfd+: Canonical decomposition.
- * - +:nfkc+: Compatibility decomposition, followed by canonical composition.
- * - +:nfkd+: Compatibility decomposition.
+ * :include: doc/string/unicode_normalize.rdoc
*
- * The encoding of +self+ must be one of:
- *
- * - Encoding::UTF_8
- * - Encoding::UTF_16BE
- * - Encoding::UTF_16LE
- * - Encoding::UTF_32BE
- * - Encoding::UTF_32LE
- * - Encoding::GB18030
- * - Encoding::UCS_2BE
- * - Encoding::UCS_4BE
- *
- * Examples:
- *
- * "a\u0300".unicode_normalize # => "a"
- * "\u00E0".unicode_normalize(:nfd) # => "a "
- *
- * Related: String#unicode_normalize!, String#unicode_normalized?.
*/
static VALUE
rb_str_unicode_normalize(int argc, VALUE *argv, VALUE str)
@@ -11554,9 +12070,9 @@ rb_str_unicode_normalize(int argc, VALUE *argv, VALUE str)
* unicode_normalize!(form = :nfc) -> self
*
* Like String#unicode_normalize, except that the normalization
- * is performed on +self+.
+ * is performed on +self+ (not on a copy of +self+).
*
- * Related String#unicode_normalized?.
+ * Related: see {Modifying}[rdoc-ref:String@Modifying].
*
*/
static VALUE
@@ -11568,8 +12084,9 @@ rb_str_unicode_normalize_bang(int argc, VALUE *argv, VALUE str)
/* call-seq:
* unicode_normalized?(form = :nfc) -> true or false
*
- * Returns +true+ if +self+ is in the given +form+ of Unicode normalization,
- * +false+ otherwise.
+ * Returns whether +self+ is in the given +form+ of Unicode normalization;
+ * see String#unicode_normalize.
+ *
* The +form+ must be one of +:nfc+, +:nfd+, +:nfkc+, or +:nfkd+.
*
* Examples:
@@ -11582,11 +12099,10 @@ rb_str_unicode_normalize_bang(int argc, VALUE *argv, VALUE str)
*
* Raises an exception if +self+ is not in a Unicode encoding:
*
- * s = "\xE0".force_encoding('ISO-8859-1')
- * s.unicode_normalized? # Raises Encoding::CompatibilityError.
- *
- * Related: String#unicode_normalize, String#unicode_normalize!.
+ * s = "\xE0".force_encoding(Encoding::ISO_8859_1)
+ * s.unicode_normalized? # Raises Encoding::CompatibilityError
*
+ * Related: see {Querying}[rdoc-ref:String@Querying].
*/
static VALUE
rb_str_unicode_normalized_p(int argc, VALUE *argv, VALUE str)
@@ -11656,7 +12172,7 @@ rb_str_unicode_normalized_p(int argc, VALUE *argv, VALUE str)
*
* == What's Here
*
- * First, what's elsewhere. \Class +Symbol+:
+ * First, what's elsewhere. Class +Symbol+:
*
* - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
* - Includes {module Comparable}[rdoc-ref:Comparable@What-27s+Here].
@@ -11718,9 +12234,9 @@ rb_str_unicode_normalized_p(int argc, VALUE *argv, VALUE str)
/*
* call-seq:
- * symbol == object -> true or false
+ * self == other -> true or false
*
- * Returns +true+ if +object+ is the same object as +self+, +false+ otherwise.
+ * Returns whether +other+ is the same object as +self+.
*/
#define sym_equal rb_obj_equal
@@ -11842,7 +12358,9 @@ sym_inspect(VALUE sym)
VALUE
rb_sym_to_s(VALUE sym)
{
- return str_new_shared(rb_cString, rb_sym2str(sym));
+ VALUE str = str_new_shared(rb_cString, rb_sym2str(sym));
+ FL_SET_RAW(str, STR_CHILLED_SYMBOL_TO_S);
+ return str;
}
VALUE
@@ -11876,18 +12394,24 @@ sym_succ(VALUE sym)
/*
* call-seq:
- * symbol <=> object -> -1, 0, +1, or nil
+ * self <=> other -> -1, 0, 1, or nil
*
- * If +object+ is a symbol,
- * returns the equivalent of <tt>symbol.to_s <=> object.to_s</tt>:
+ * Compares +self+ and +other+, using String#<=>.
*
- * :bar <=> :foo # => -1
- * :foo <=> :foo # => 0
- * :foo <=> :bar # => 1
+ * Returns:
*
- * Otherwise, returns +nil+:
+ * - <tt>self.to_s <=> other.to_s</tt>, if +other+ is a symbol.
+ * - +nil+, otherwise.
+ *
+ * Examples:
*
- * :foo <=> 'bar' # => nil
+ * :bar <=> :foo # => -1
+ * :foo <=> :foo # => 0
+ * :foo <=> :bar # => 1
+ * :foo <=> 'bar' # => nil
+ *
+ * \Class \Symbol includes module Comparable,
+ * each of whose methods uses Symbol#<=> for comparison.
*
* Related: String#<=>.
*/
@@ -11937,9 +12461,9 @@ sym_casecmp_p(VALUE sym, VALUE other)
/*
* call-seq:
- * symbol =~ object -> integer or nil
+ * self =~ other -> integer or nil
*
- * Equivalent to <tt>symbol.to_s =~ object</tt>,
+ * Equivalent to <tt>self.to_s =~ other</tt>,
* including possible updates to global variables;
* see String#=~.
*
@@ -11985,11 +12509,11 @@ sym_match_m_p(int argc, VALUE *argv, VALUE sym)
/*
* call-seq:
- * symbol[index] -> string or nil
- * symbol[start, length] -> string or nil
- * symbol[range] -> string or nil
- * symbol[regexp, capture = 0] -> string or nil
- * symbol[substring] -> string or nil
+ * self[offset] -> string or nil
+ * self[offset, size] -> string or nil
+ * self[range] -> string or nil
+ * self[regexp, capture = 0] -> string or nil
+ * self[substring] -> string or nil
*
* Equivalent to <tt>symbol.to_s[]</tt>; see String#[].
*
@@ -12030,7 +12554,7 @@ sym_empty(VALUE sym)
/*
* call-seq:
- * upcase(*options) -> symbol
+ * upcase(mapping) -> symbol
*
* Equivalent to <tt>sym.to_s.upcase.to_sym</tt>.
*
@@ -12046,7 +12570,7 @@ sym_upcase(int argc, VALUE *argv, VALUE sym)
/*
* call-seq:
- * downcase(*options) -> symbol
+ * downcase(mapping) -> symbol
*
* Equivalent to <tt>sym.to_s.downcase.to_sym</tt>.
*
@@ -12064,7 +12588,7 @@ sym_downcase(int argc, VALUE *argv, VALUE sym)
/*
* call-seq:
- * capitalize(*options) -> symbol
+ * capitalize(mapping) -> symbol
*
* Equivalent to <tt>sym.to_s.capitalize.to_sym</tt>.
*
@@ -12080,7 +12604,7 @@ sym_capitalize(int argc, VALUE *argv, VALUE sym)
/*
* call-seq:
- * swapcase(*options) -> symbol
+ * swapcase(mapping) -> symbol
*
* Equivalent to <tt>sym.to_s.swapcase.to_sym</tt>.
*
@@ -12143,7 +12667,7 @@ string_for_symbol(VALUE name)
if (!RB_TYPE_P(name, T_STRING)) {
VALUE tmp = rb_check_string_type(name);
if (NIL_P(tmp)) {
- rb_raise(rb_eTypeError, "%+"PRIsVALUE" is not a symbol",
+ rb_raise(rb_eTypeError, "%+"PRIsVALUE" is not a symbol nor a string",
name);
}
name = tmp;
@@ -12197,8 +12721,16 @@ rb_str_to_interned_str(VALUE 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, false);
+ struct RString fake_str = {RBASIC_INIT};
+ int encidx = ENCINDEX_US_ASCII;
+ int coderange = ENC_CODERANGE_7BIT;
+ if (len > 0 && search_nonascii(ptr, ptr + len)) {
+ encidx = ENCINDEX_ASCII_8BIT;
+ coderange = ENC_CODERANGE_VALID;
+ }
+ VALUE str = setup_fake_str(&fake_str, ptr, len, encidx);
+ ENC_CODERANGE_SET(str, coderange);
+ return register_fstring(str, true, false);
}
VALUE
@@ -12214,7 +12746,7 @@ rb_enc_interned_str(const char *ptr, long len, rb_encoding *enc)
rb_enc_autoload(enc);
}
- struct RString fake_str;
+ struct RString fake_str = {RBASIC_INIT};
return register_fstring(rb_setup_fake_str(&fake_str, ptr, len, enc), true, false);
}
@@ -12225,8 +12757,10 @@ rb_enc_literal_str(const char *ptr, long len, rb_encoding *enc)
rb_enc_autoload(enc);
}
- struct RString fake_str;
- return register_fstring(rb_setup_fake_str(&fake_str, ptr, len, enc), true, true);
+ struct RString fake_str = {RBASIC_INIT};
+ VALUE str = register_fstring(rb_setup_fake_str(&fake_str, ptr, len, enc), true, true);
+ RUBY_ASSERT(RB_OBJ_SHAREABLE_P(str) && (rb_gc_verify_shareable(str), 1));
+ return str;
}
VALUE
@@ -12235,17 +12769,44 @@ rb_enc_interned_str_cstr(const char *ptr, rb_encoding *enc)
return rb_enc_interned_str(ptr, strlen(ptr), enc);
}
+#if USE_YJIT || USE_ZJIT
+void
+rb_jit_str_concat_codepoint(VALUE str, VALUE codepoint)
+{
+ if (RB_LIKELY(ENCODING_GET_INLINED(str) == rb_ascii8bit_encindex())) {
+ ssize_t code = RB_NUM2SSIZE(codepoint);
+
+ if (RB_LIKELY(code >= 0 && code < 0xff)) {
+ rb_str_buf_cat_byte(str, (char) code);
+ return;
+ }
+ }
+
+ rb_str_concat(str, codepoint);
+}
+#endif
+
+static int
+fstring_set_class_i(VALUE *str, void *data)
+{
+ RBASIC_SET_CLASS(*str, rb_cString);
+
+ return ST_CONTINUE;
+}
+
void
Init_String(void)
{
rb_cString = rb_define_class("String", rb_cObject);
- RUBY_ASSERT(rb_vm_fstring_table());
- st_foreach(rb_vm_fstring_table(), fstring_set_class_i, rb_cString);
+
+ rb_concurrent_set_foreach_with_replace(fstring_table_obj, fstring_set_class_i, NULL);
+
rb_include_module(rb_cString, rb_mComparable);
rb_define_alloc_func(rb_cString, empty_str_alloc);
rb_define_singleton_method(rb_cString, "new", rb_str_s_new, -1);
rb_define_singleton_method(rb_cString, "try_convert", rb_str_s_try_convert, 1);
rb_define_method(rb_cString, "initialize", rb_str_init, -1);
+ rb_define_method(rb_cString, "replace", rb_str_replace, 1);
rb_define_method(rb_cString, "initialize_copy", rb_str_replace, 1);
rb_define_method(rb_cString, "<=>", rb_str_cmp_m, 1);
rb_define_method(rb_cString, "==", rb_str_equal, 1);
@@ -12276,7 +12837,6 @@ Init_String(void)
rb_define_method(rb_cString, "byteindex", rb_str_byteindex_m, -1);
rb_define_method(rb_cString, "rindex", rb_str_rindex_m, -1);
rb_define_method(rb_cString, "byterindex", rb_str_byterindex_m, -1);
- rb_define_method(rb_cString, "replace", rb_str_replace, 1);
rb_define_method(rb_cString, "clear", rb_str_clear, 0);
rb_define_method(rb_cString, "chr", rb_str_chr, 0);
rb_define_method(rb_cString, "getbyte", rb_str_getbyte, 1);
@@ -12325,6 +12885,7 @@ Init_String(void)
rb_define_method(rb_cString, "reverse", rb_str_reverse, 0);
rb_define_method(rb_cString, "reverse!", rb_str_reverse_bang, 0);
rb_define_method(rb_cString, "concat", rb_str_concat_multi, -1);
+ rb_define_method(rb_cString, "append_as_bytes", rb_str_append_as_bytes, -1);
rb_define_method(rb_cString, "<<", rb_str_concat, 1);
rb_define_method(rb_cString, "prepend", rb_str_prepend_multi, -1);
rb_define_method(rb_cString, "crypt", rb_str_crypt, 1);
@@ -12346,9 +12907,9 @@ Init_String(void)
rb_define_method(rb_cString, "gsub", rb_str_gsub, -1);
rb_define_method(rb_cString, "chop", rb_str_chop, 0);
rb_define_method(rb_cString, "chomp", rb_str_chomp, -1);
- rb_define_method(rb_cString, "strip", rb_str_strip, 0);
- rb_define_method(rb_cString, "lstrip", rb_str_lstrip, 0);
- rb_define_method(rb_cString, "rstrip", rb_str_rstrip, 0);
+ rb_define_method(rb_cString, "strip", rb_str_strip, -1);
+ rb_define_method(rb_cString, "lstrip", rb_str_lstrip, -1);
+ rb_define_method(rb_cString, "rstrip", rb_str_rstrip, -1);
rb_define_method(rb_cString, "delete_prefix", rb_str_delete_prefix, 1);
rb_define_method(rb_cString, "delete_suffix", rb_str_delete_suffix, 1);
@@ -12356,9 +12917,9 @@ Init_String(void)
rb_define_method(rb_cString, "gsub!", rb_str_gsub_bang, -1);
rb_define_method(rb_cString, "chop!", rb_str_chop_bang, 0);
rb_define_method(rb_cString, "chomp!", rb_str_chomp_bang, -1);
- rb_define_method(rb_cString, "strip!", rb_str_strip_bang, 0);
- rb_define_method(rb_cString, "lstrip!", rb_str_lstrip_bang, 0);
- rb_define_method(rb_cString, "rstrip!", rb_str_rstrip_bang, 0);
+ rb_define_method(rb_cString, "strip!", rb_str_strip_bang, -1);
+ rb_define_method(rb_cString, "lstrip!", rb_str_lstrip_bang, -1);
+ rb_define_method(rb_cString, "rstrip!", rb_str_rstrip_bang, -1);
rb_define_method(rb_cString, "delete_prefix!", rb_str_delete_prefix_bang, 1);
rb_define_method(rb_cString, "delete_suffix!", rb_str_delete_suffix_bang, 1);
@@ -12416,7 +12977,6 @@ Init_String(void)
rb_define_method(rb_cSymbol, "==", sym_equal, 1);
rb_define_method(rb_cSymbol, "===", sym_equal, 1);
rb_define_method(rb_cSymbol, "inspect", sym_inspect, 0);
- rb_define_method(rb_cSymbol, "name", rb_sym2str, 0); /* in symbol.c */
rb_define_method(rb_cSymbol, "to_proc", rb_sym_to_proc, 0); /* in proc.c */
rb_define_method(rb_cSymbol, "succ", sym_succ, 0);
rb_define_method(rb_cSymbol, "next", sym_succ, 0);
@@ -12444,3 +13004,4 @@ Init_String(void)
rb_define_method(rb_cSymbol, "encoding", sym_encoding, 0);
}
+
diff --git a/string.rb b/string.rb
deleted file mode 100644
index bec4e8cecf..0000000000
--- a/string.rb
+++ /dev/null
@@ -1,552 +0,0 @@
-# A +String+ object has an arbitrary sequence of bytes,
-# typically representing text or binary data.
-# A +String+ object may be created using String::new or as literals.
-#
-# String objects differ from Symbol objects in that Symbol objects are
-# designed to be used as identifiers, instead of text or data.
-#
-# You can create a +String+ object explicitly with:
-#
-# - A {string literal}[rdoc-ref:syntax/literals.rdoc@String+Literals].
-# - A {heredoc literal}[rdoc-ref:syntax/literals.rdoc@Here+Document+Literals].
-#
-# You can convert certain objects to Strings with:
-#
-# - \Method #String.
-#
-# Some +String+ methods modify +self+.
-# Typically, a method whose name ends with <tt>!</tt> modifies +self+
-# and returns +self+;
-# often a similarly named method (without the <tt>!</tt>)
-# 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.
-#
-# - 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.
-#
-# <b>Argument +pattern+</b>
-#
-# 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"
-#
-# <b>+String+ +replacement+</b>
-#
-# 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:
-#
-# - <tt>\n</tt> (_n_ a non-negative integer) refers to <tt>$n</tt>.
-# - <tt>\k<name></tt> refers to the named capture +name+.
-#
-# See Regexp for details.
-#
-# Note that within the string +replacement+, a character combination
-# such as <tt>$&</tt> is treated as ordinary text, and not as
-# a special match variable.
-# However, you may refer to some special match variables using these
-# combinations:
-#
-# - <tt>\&</tt> and <tt>\0</tt> correspond to <tt>$&</tt>,
-# which contains the complete matched text.
-# - <tt>\'</tt> corresponds to <tt>$'</tt>,
-# which contains string after match.
-# - <tt>\`</tt> corresponds to <tt>$`</tt>,
-# which contains string before match.
-# - <tt>\\+</tt> corresponds to <tt>$+</tt>,
-# which contains last capture group.
-#
-# See Regexp for details.
-#
-# Note that <tt>\\\\</tt> is interpreted as an escape, i.e., a single backslash.
-#
-# Note also that a string literal consumes backslashes.
-# See {String Literals}[rdoc-ref:syntax/literals.rdoc@String+Literals] for details about string literals.
-#
-# A back-reference is typically preceded by an additional backslash.
-# For example, if you want to write a back-reference <tt>\&</tt> in
-# +replacement+ with a double-quoted string literal, you need to write
-# <tt>"..\\\\&.."</tt>.
-#
-# If you want to write a non-back-reference string <tt>\&</tt> 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: <tt>"..\\\\\\\\&.."</tt>.
-#
-# You may want to use the block form to avoid a lot of backslashes.
-#
-# <b>\Hash +replacement+</b>
-#
-# 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"
-#
-# <b>Block</b>
-#
-# 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 <tt>$1</tt>, <tt>$2</tt>, <tt>$`</tt>,
-# <tt>$&</tt>, and <tt>$'</tt> are set appropriately.
-#
-# == Whitespace in Strings
-#
-# In class +String+, _whitespace_ is defined as a contiguous sequence of characters
-# consisting of any mixture of the following:
-#
-# - NL (null): <tt>"\x00"</tt>, <tt>"\u0000"</tt>.
-# - HT (horizontal tab): <tt>"\x09"</tt>, <tt>"\t"</tt>.
-# - LF (line feed): <tt>"\x0a"</tt>, <tt>"\n"</tt>.
-# - VT (vertical tab): <tt>"\x0b"</tt>, <tt>"\v"</tt>.
-# - FF (form feed): <tt>"\x0c"</tt>, <tt>"\f"</tt>.
-# - CR (carriage return): <tt>"\x0d"</tt>, <tt>"\r"</tt>.
-# - SP (space): <tt>"\x20"</tt>, <tt>" "</tt>.
-#
-#
-# Whitespace is relevant for these methods:
-#
-# - #lstrip, #lstrip!: strip leading whitespace.
-# - #rstrip, #rstrip!: strip trailing whitespace.
-# - #strip, #strip!: strip leading and trailing whitespace.
-#
-# == +String+ Slices
-#
-# A _slice_ of a string is a substring that is selected by certain criteria.
-#
-# These instance methods make use of slicing:
-#
-# - String#[] (also aliased as String#slice) returns a slice copied from +self+.
-# - String#[]= returns a copy of +self+ with a slice replaced.
-# - String#slice! returns +self+ with a slice removed.
-#
-# Each of the above methods takes arguments that determine the slice
-# to be copied or replaced.
-#
-# The arguments have several forms.
-# For string +string+, the forms are:
-#
-# - <tt>string[index]</tt>.
-# - <tt>string[start, length]</tt>.
-# - <tt>string[range]</tt>.
-# - <tt>string[regexp, capture = 0]</tt>.
-# - <tt>string[substring]</tt>.
-#
-# <b><tt>string[index]</tt></b>
-#
-# When non-negative integer argument +index+ is given,
-# the slice is the 1-character substring found in +self+ at character offset +index+:
-#
-# 'bar'[0] # => "b"
-# 'bar'[2] # => "r"
-# 'bar'[20] # => nil
-# 'тест'[2] # => "с"
-# 'こんにちは'[4] # => "は"
-#
-# When negative integer +index+ is given,
-# the slice begins at the offset given by counting backward from the end of +self+:
-#
-# 'bar'[-3] # => "b"
-# 'bar'[-1] # => "r"
-# 'bar'[-20] # => nil
-#
-# <b><tt>string[start, length]</tt></b>
-#
-# When non-negative integer arguments +start+ and +length+ are given,
-# the slice begins at character offset +start+, if it exists,
-# and continues for +length+ characters, if available:
-#
-# 'foo'[0, 2] # => "fo"
-# 'тест'[1, 2] # => "ес"
-# 'こんにちは'[2, 2] # => "にち"
-# # Zero length.
-# 'foo'[2, 0] # => ""
-# # Length not entirely available.
-# 'foo'[1, 200] # => "oo"
-# # Start out of range.
-# 'foo'[4, 2] # => nil
-#
-# Special case: if +start+ is equal to the length of +self+,
-# the slice is a new empty string:
-#
-# 'foo'[3, 2] # => ""
-# 'foo'[3, 200] # => ""
-#
-# When negative +start+ and non-negative +length+ are given,
-# the slice beginning is determined by counting backward from the end of +self+,
-# and the slice continues for +length+ characters, if available:
-#
-# 'foo'[-2, 2] # => "oo"
-# 'foo'[-2, 200] # => "oo"
-# # Start out of range.
-# 'foo'[-4, 2] # => nil
-#
-# When negative +length+ is given, there is no slice:
-#
-# 'foo'[1, -1] # => nil
-# 'foo'[-2, -1] # => nil
-#
-# <b><tt>string[range]</tt></b>
-#
-# When Range argument +range+ is given,
-# creates a substring of +string+ using the indices in +range+.
-# The slice is then determined as above:
-#
-# 'foo'[0..1] # => "fo"
-# 'foo'[0, 2] # => "fo"
-#
-# 'foo'[2...2] # => ""
-# 'foo'[2, 0] # => ""
-#
-# 'foo'[1..200] # => "oo"
-# 'foo'[1, 200] # => "oo"
-#
-# 'foo'[4..5] # => nil
-# 'foo'[4, 2] # => nil
-#
-# 'foo'[-4..-3] # => nil
-# 'foo'[-4, 2] # => nil
-#
-# 'foo'[3..4] # => ""
-# 'foo'[3, 2] # => ""
-#
-# 'foo'[-2..-1] # => "oo"
-# 'foo'[-2, 2] # => "oo"
-#
-# 'foo'[-2..197] # => "oo"
-# 'foo'[-2, 200] # => "oo"
-#
-# <b><tt>string[regexp, capture = 0]</tt></b>
-#
-# When the Regexp argument +regexp+ is given,
-# and the +capture+ argument is <tt>0</tt>,
-# the slice is the first matching substring found in +self+:
-#
-# 'foo'[/o/] # => "o"
-# 'foo'[/x/] # => nil
-# s = 'hello there'
-# s[/[aeiou](.)\1/] # => "ell"
-# s[/[aeiou](.)\1/, 0] # => "ell"
-#
-# If argument +capture+ is given and not <tt>0</tt>,
-# it should be either an capture group index (integer)
-# or a capture group name (string or symbol);
-# the slice is the specified capture (see Regexp@Groups+and+Captures):
-#
-# s = 'hello there'
-# s[/[aeiou](.)\1/, 1] # => "l"
-# s[/(?<vowel>[aeiou])(?<non_vowel>[^aeiou])/, "non_vowel"] # => "l"
-# s[/(?<vowel>[aeiou])(?<non_vowel>[^aeiou])/, :vowel] # => "e"
-#
-# If an invalid capture group index is given, there is no slice.
-# If an invalid capture group name is given, +IndexError+ is raised.
-#
-# <b><tt>string[substring]</tt></b>
-#
-# When the single +String+ argument +substring+ is given,
-# returns the substring from +self+ if found, otherwise +nil+:
-#
-# 'foo'['oo'] # => "oo"
-# 'foo'['xx'] # => nil
-#
-# == What's Here
-#
-# First, what's elsewhere. \Class +String+:
-#
-# - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here].
-# - Includes {module Comparable}[rdoc-ref:Comparable@What-27s+Here].
-#
-# Here, class +String+ provides methods that are useful for:
-#
-# - {Creating a String}[rdoc-ref:String@Methods+for+Creating+a+String]
-# - {Frozen/Unfrozen Strings}[rdoc-ref:String@Methods+for+a+Frozen-2FUnfrozen+String]
-# - {Querying}[rdoc-ref:String@Methods+for+Querying]
-# - {Comparing}[rdoc-ref:String@Methods+for+Comparing]
-# - {Modifying a String}[rdoc-ref:String@Methods+for+Modifying+a+String]
-# - {Converting to New String}[rdoc-ref:String@Methods+for+Converting+to+New+String]
-# - {Converting to Non-String}[rdoc-ref:String@Methods+for+Converting+to+Non-String]
-# - {Iterating}[rdoc-ref:String@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
-#
-# - #+@: Returns a string that is not frozen: +self+, if not frozen;
-# +self.dup+ otherwise.
-# - #-@: 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_
-#
-# - #=~: 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
-#
-# - #==, #===: Returns +true+ if a given other string has the same content as +self+.
-# - #eql?: Returns +true+ if the content is the same as the given other string.
-# - #<=>: Returns -1, 0, or 1 as a given other string is smaller than,
-# equal to, or larger than +self+.
-# - #casecmp: Ignoring case, returns -1, 0, or 1 as 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 newline characters 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 <tt>\xNN</tt> notation replace by <tt>\uNNNN</tt> 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 newline characters 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+.
-#
-# <em>Characters, Bytes, and Clusters</em>
-#
-# - #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.
-#
-# <em>Strings and Symbols</em>
-#
-# - #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.
-
-class String; end
diff --git a/struct.c b/struct.c